pax_global_header00006660000000000000000000000064142215750460014520gustar00rootroot0000000000000052 comment=14c86f66b20901b60ee276da355c1b62642c18d2 blis-0.9.0/000077500000000000000000000000001422157504600124575ustar00rootroot00000000000000blis-0.9.0/.appveyor.yml000066400000000000000000000040141422157504600151240ustar00rootroot00000000000000skip_branch_with_pr: true environment: matrix: - LIB_TYPE: shared CONFIG: auto CC: gcc THREADING: pthreads CBLAS: no - LIB_TYPE: static CONFIG: auto CC: clang THREADING: no - LIB_TYPE: shared CONFIG: x86_64 CC: clang THREADING: pthreads - LIB_TYPE: static CONFIG: auto CC: clang THREADING: openmp install: - set "PATH=C:\msys64\mingw64\bin;C:\msys64\bin;%PATH%" - if [%CC%]==[clang] set "PATH=C:\Program Files\LLVM\bin;%PATH%" - if [%CC%]==[clang] set "AR=llvm-ar" - if [%CC%]==[clang] set "AS=llvm-as" - if [%CC%]==[clang] call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" amd64 build_script: - if [%LIB_TYPE%]==[shared] set "CONFIGURE_OPTS=%CONFIGURE_OPTS% --enable-shared --disable-static" - if [%LIB_TYPE%]==[static] set "CONFIGURE_OPTS=%CONFIGURE_OPTS% --disable-shared --enable-static" - if not [%CBLAS%]==[no] set "CONFIGURE_OPTS=%CONFIGURE_OPTS% --enable-cblas" - set RANLIB=echo - set LIBPTHREAD= - set "PATH=%PATH%;C:\blis\lib" - set "CFLAGS=-Wno-macro-redefined" - bash -lc "cd /c/projects/blis && ./configure %CONFIGURE_OPTS% --enable-threading=%THREADING% --enable-arg-max-hack --prefix=/c/blis %CONFIG%" - bash -lc "cd /c/projects/blis && mingw32-make -j4 V=1" - bash -lc "cd /c/projects/blis && mingw32-make install" - 7z a C:\blis.zip C:\blis - ps: Push-AppveyorArtifact C:\blis.zip test_script: # "make checkblas" does not work with shared linking Windows due to inability to override xerbla_ - if [%LIB_TYPE%]==[shared] set "TEST_TARGET=checkblis-fast" - if [%LIB_TYPE%]==[static] set "TEST_TARGET=check" - bash -lc "cd /c/projects/blis && mingw32-make %TEST_TARGET% -j4 V=1" # Enable this to be able to login to the build worker. You can use the # `remmina` program in Ubuntu, use the login information that the line below # prints into the log. #on_finish: #- ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1')) blis-0.9.0/.dir-locals.el000066400000000000000000000005271422157504600151140ustar00rootroot00000000000000;; First (minimal) attempt at configuring Emacs CC mode for the BLIS ;; layout requirements. ((c-mode . ((c-file-style . "stroustrup") (c-basic-offset . 4) (comment-start . "// ") (comment-end . "") (indent-tabs-mode . t) (tab-width . 4) (parens-require-spaces . nil)))) blis-0.9.0/.gitignore000066400000000000000000000013721422157504600144520ustar00rootroot00000000000000# -- generic files to ignore -- # emacs backup files *~ # vim backup files *.swp # NFS file .nfs* # -- compiler-related -- # object files # NOTE: This will result in git also exluding the top-level obj directory # since its only contents are .o files. *.o # static library archives # NOTE: This will result in git also exluding the top-level lib directory # since its only contents are .a files. *.a *.so *.so.* # test executables *.x *.pexe *.nexe *.js # link map files *.map # -- build system files -- config.mk bli_config.h bli_addon.h # -- monolithic headers -- include/*/*.h # -- makefile fragments -- .fragment.mk # -- misc. -- # BLIS testsuite output file output.testsuite.* # BLAS test output files out.* # GTAGS database GPATH GRTAGS GTAGS blis-0.9.0/.travis.yml000066400000000000000000000067041422157504600145770ustar00rootroot00000000000000language: c sudo: required dist: focal branches: only: - master - dev - amd matrix: include: # full testsuite (all tests + mixed datatype (gemm_nn only) + salt + SDE + OOT) - os: linux compiler: gcc env: OOT=1 TEST=ALL SDE=1 THR="none" CONF="x86_64" \ PACKAGES="gcc-9 binutils" # openmp build - os: linux compiler: gcc env: OOT=0 TEST=FAST SDE=0 THR="openmp" CONF="auto" \ PACKAGES="gcc-9 binutils" # pthreads build - os: linux compiler: gcc env: OOT=0 TEST=FAST SDE=0 THR="pthreads" CONF="auto" \ PACKAGES="gcc-9 binutils" # clang build - os: linux compiler: clang env: OOT=0 TEST=FAST SDE=0 THR="none" CONF="auto" # There seems to be some difficulty installing 2 Clang toolchains of different versions. # Use the TravisCI default. # PACKAGES="clang-8 binutils" # macOS with system compiler (clang) - os: osx compiler: clang env: OOT=0 TEST=FAST SDE=0 THR="none" CONF="auto" # cortexa15 build and fast testsuite (qemu) - os: linux compiler: arm-linux-gnueabihf-gcc env: OOT=0 TEST=FAST SDE=0 THR="none" CONF="cortexa15" \ CC=arm-linux-gnueabihf-gcc CXX=arm-linux-gnueabihf-g++ \ PACKAGES="gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf libc6-dev-armhf-cross qemu-system-arm qemu-user" \ TESTSUITE_WRAPPER="qemu-arm -cpu cortex-a15 -L /usr/arm-linux-gnueabihf/" # cortexa57 build and fast testsuite (qemu) - os: linux compiler: aarch64-linux-gnu-gcc env: OOT=0 TEST=FAST SDE=0 THR="none" CONF="cortexa57" \ CC=aarch64-linux-gnu-gcc CXX=aarch64-linux-gnu-g++ \ PACKAGES="gcc-aarch64-linux-gnu g++-aarch64-linux-gnu libc6-dev-arm64-cross qemu-system-arm qemu-user" \ TESTSUITE_WRAPPER="qemu-aarch64 -L /usr/aarch64-linux-gnu/" # Apple M1 (firestorm) build and fast testsuite (qemu) - os: linux compiler: aarch64-linux-gnu-gcc env: OOT=0 TEST=FAST SDE=0 THR="none" CONF="firestorm" \ CC=aarch64-linux-gnu-gcc CXX=aarch64-linux-gnu-g++ \ PACKAGES="gcc-aarch64-linux-gnu g++-aarch64-linux-gnu libc6-dev-arm64-cross qemu-system-arm qemu-user" \ TESTSUITE_WRAPPER="qemu-aarch64 -L /usr/aarch64-linux-gnu/" # armsve build and fast testsuite (qemu) - os: linux compiler: aarch64-linux-gnu-gcc-10 env: OOT=0 TEST=FAST SDE=0 THR="none" CONF="armsve" \ CC=aarch64-linux-gnu-gcc-10 CXX=aarch64-linux-gnu-g++-10 \ PACKAGES="gcc-10-aarch64-linux-gnu g++-10-aarch64-linux-gnu libc6-dev-arm64-cross qemu-system-arm qemu-user" \ TESTSUITE_WRAPPER="qemu-aarch64 -cpu max,sve=true,sve512=true -L /usr/aarch64-linux-gnu/" install: - if [ "$CC" = "gcc" ] && [ "$TRAVIS_OS_NAME" = "linux" ]; then export CC="gcc-9"; fi - if [ -n "$PACKAGES" ] && [ "$TRAVIS_OS_NAME" = "linux" ]; then sudo apt-get install -y $PACKAGES; fi script: - export DIST_PATH=. - pwd - if [ $OOT -eq 1 ]; then export DIST_PATH=`pwd`; mkdir ../oot; cd ../oot; chmod -R a-w $DIST_PATH; fi - pwd - $DIST_PATH/configure -p `pwd`/../install -t $THR CC=$CC $CONF - pwd - ls -l - $CC --version - make -j 2 - make install - $DIST_PATH/travis/cxx/cxx-test.sh $DIST_PATH $(ls -1 include) # Qemu SVE is failing sgemmt in some cases. Skip as this issue is not observed on real chip (A64fx). - if [ "$CONF" = "armsve" ]; then sed -i 's/.*\.*/0/' $DIST_PATH/testsuite/input.operations.fast; fi - if [ "$TEST" != "0" ]; then travis_wait 30 $DIST_PATH/travis/do_testsuite.sh; fi - if [ "$SDE" = "1" ]; then travis_wait 30 $DIST_PATH/travis/do_sde.sh; fi blis-0.9.0/CHANGELOG000066400000000000000000037021221422157504600137000ustar00rootroot00000000000000commit 8535b3e11d2297854991c4272932ce4974dda629 (HEAD -> master, tag: 0.8.1) Author: Field G. Van Zee Date: Mon Mar 22 17:42:33 2021 -0500 Version file update (0.8.1) commit e56d9f2d94ed247696dda2cbf94d2ca05c7fc089 (origin/master, origin/HEAD) Author: Field G. Van Zee Date: Mon Mar 22 17:40:50 2021 -0500 ReleaseNotes.md update in advance of next version. commit ca83f955d45814b7d84f53933cdb73323c0dea2c Author: Field G. Van Zee Date: Mon Mar 22 17:21:21 2021 -0500 CREDITS file update. commit 57ef61f6cdb86957f67212aa59407f2f8e7f3d1a Merge: bf1b578e e7a4a8ed Author: Field G. Van Zee Date: Fri Mar 19 13:05:43 2021 -0500 Merge branch 'master' of github.com:flame/blis commit bf1b578ea32ea1c9dbf7cb3586969e8ae89aa5ef Author: Field G. Van Zee Date: Fri Mar 19 13:03:17 2021 -0500 Reduced KC on skx from 384 to 256. Details: - Reduced the KC cache blocksize for double real on the skx subconfig from 384 to 256. The maximum (extended) KC was also reduced accordingly from 480 to 320. Thanks to Tze Meng Low for suggesting this change. commit e7a4a8edc940942357e8e4c4594383a29a962f93 Author: Nicholai Tukanov Date: Wed Mar 17 19:43:31 2021 -0500 Fix calculation of new pb size (#487) Details: - Added missing parentheses to the i8 and i4 instantiations of the GENERIC_GEMM macro in sandbox/power10/generic_gemm.c. commit 4493cf516e01aba82642a43abe350943ba458fe2 Author: Field G. Van Zee Date: Mon Mar 15 13:12:49 2021 -0500 Redefined BLIS_NUM_ARCHS to update automatically. Details: - Changed BLIS_NUM_ARCHS from a cpp macro definition to the last enum value in the arch_t enum. This means that it no longer needs to get updated manually whenever new subconfigurations are added to BLIS. Also removed the explicit initial index assigment of 0 from the first enum value, which was unnecessary due to how the C language standard mandates indexing of enum values. Thanks to Devin Matthews for originally submitting this as a PR in #446. - Updated docs/ConfigurationHowTo.md to reflect the aforementioned change. commit a4b73de84cdffcbe5cf71969a0f7f0f8202b3510 Author: Field G. Van Zee Date: Fri Mar 12 17:12:27 2021 -0600 Disabled _self() and _equal() in bli_pthread API. Details: - Disabled the _self() and _equal() extensions to the bli_pthread API introduced in d479654. These functions were disabled after I realized that they aren't actually needed yet. Thanks to Devin Matthews for helping me reason through the appropriate consumer code that will appear in BLIS (eventually) in a future commit. (Also, I could never get the Windows branch to link properly in clang builds in AppVeyor. See the comment I left in the code, and #485, for more info.) commit f9d604679d8715bc3e79a8630268446889b51388 Author: Field G. Van Zee Date: Thu Mar 11 16:57:55 2021 -0600 Added _self() and _equal() to bli_pthread API. Details: - Expanded the bli_pthread API to include equivalents to pthread_self() and pthread_equal(). Implemented these two functions for all three cpp branches present within bli_pthread.c: systemless, Windows, and Linux/BSD. commit fa9b3c8f6b3d5717f19832362104413e1a86dfb0 Author: Field G. Van Zee Date: Thu Mar 11 15:13:51 2021 -0600 Shuffled code in Windows branch of bli_pthreads.c. Details: - Reordered the definitions in the cpp branch in bli_pthreads.c that defines the bli_pthreads API in terms of Windows API calls. Also added missing comments that mark sections of the API, which brings the code into harmony with other cpp branches (as well as bli_pthread.h). commit 95d4f3934d806b3563f6648d57a4e381d747caf5 Author: Field G. Van Zee Date: Thu Mar 11 13:50:40 2021 -0600 Moved cpp macro redef of strerror_r to bli_env.c. Details: - Relocated the _MSC_VER-guarded cpp macro re-definition of strerror_r (in terms of strerror_s) from bli_thread.h to bli_env.c. It was likely left behind in bli_thread.h in a previous commit, when code that now resides in bli_env.c was moved from bli_thread.c. (I couldn't find any other instance of strerror_r being used in BLIS, so I moved the #define directly to bli_env.c rather than place it in bli_env.h.) The code that uses strerror_r is currently disabled, though, so this commit should have no affect on BLIS. commit 8a3066c315358d45d4f5b710c54594455f9e8fc6 Author: Field G. Van Zee Date: Tue Mar 9 17:52:59 2021 -0600 Relocated gemmsup_ref general stride handling. Details: - Moved the logic that checks for general stridedness in any of the matrix operands in a gemmsup problem. The logic previously resided near the top of bli_gemmsup_int(), which is the thread entry point for the parallel region of the current gemmsup implementation. The problem with this setup was that the code would attempt to reject problems with any general-strided operands by returning BLIS_FAILURE, and that return value was then being ignored by the l3_sup thread decorator, which unconditionally returns BLIS_SUCCESS. To solve this issue, rather than try to manage n return values, one from each of n threads, I simply moved the logic into bli_gemmsup_ref(). I didn't move it any higher (e.g. bli_gemmsup()) because I still want the logic to be part of the current gemmsup handler implementation. That is, perhaps someone else will create a different handler, and that author wants to handle general stride differently. (We don't want to force them into a particular way of handling general stride.) - Removed the general stride handling from bli_gemmtsup_int(), even though this function is inoperative for now. - This commit addresses issue #484. Thanks to RuQing Xu for reporting this issue. commit 670bc7b60f6065893e8ec1bebd2fc9e5ba710dff Author: Nicholai Tukanov Date: Fri Mar 5 13:53:43 2021 -0600 Add low-precision POWER10 gemm kernels (#467) Details: - This commit adds a new BLIS sandbox that (1) provides implementations based on low-precision gemm kernels, and (2) extends the BLIS typed API for those new implementations. Currently, these new kernels can only be used for the POWER10 microarchitecture; however, they may provide a template for developing similar kernels for other microarchitectures (even those beyond POWER), as changes would likely be limited to select places in the microkernel and possibly the packing routines. The new low-precision operations that are now supported include: shgemm, sbgemm, i16gemm, i8gemm, i4gemm. For more information, refer to the POWER10.md document that is included in 'sandbox/power10'. commit b8dcc5bc75a746807d6f8fa22dc2123c98396bf5 (origin/dev, origin/amd, dev, amd) Author: RuQing Xu Date: Tue Mar 2 06:58:24 2021 +0800 Fixed typed API definition for gemmt (#476) Details: - Fixed incorrect definition and prototype of bli_?gemmt() in frame/3/bli_l3_tapi.c and .h, respectively. gemmt was previously defined identically to gemm, which was wrong because it did not take into account the uplo property of C. - Fixed incorrect API documentation for her2k/syr2k in BLISTypedAPI.md. Specifically, the document erroneously listed only a single transab parameter instead of transa and transb. commit a0e4fe2340a93521e1b1a835a96d0f26dec8406a Author: Ilknur Date: Tue Mar 2 02:06:56 2021 +0400 Fixed double free() in level1v example (#482) Details: - In exampls/tapi/00level1v.c, pointer 'z' was being freed twice and pointer 'a' was not being freed at all. This commit correctly frees each pointer exactly once. commit f5871c7e06a75799251d6b55a8a5fbfa1a92cf95 Author: Field G. Van Zee Date: Sun Feb 28 17:03:57 2021 -0600 Added complex asm packm kernels for 'haswell' set. Details: - Implemented assembly-based packm kernels for single- and double- precision complex domain (c and z) and housed them in the 'haswell' kernel set. This means c3xk, c8xk, z3xk, and z4xk are now all optimized. - Registered the aforementioned packm kernels in the haswell, zen, and zen2 subconfigs. - Minor modifications to the corresponding s and d packm kernels that were introduced in 426ad67. - Thanks to AMD, who originally contributed the double-precision real packm kernels (d6xk and d8xk), upon which these complex kernels are partially based. commit 426ad679f55264e381eb57a372632b774320fb85 Author: Field G. Van Zee Date: Sat Feb 27 18:39:56 2021 -0600 Added assembly packm kernels for 'haswell' set. Details: - Implemented assembly-based packm kernels for single- and double- precision real domain (s and d) and housed them in the 'haswell' kernel set. This means s6xk, s16xk, d6xk, and d8xk are now all optimized. - Registered the aforementioned packm kernels in the haswell, zen, and zen2 subconfigs. - Thanks to AMD, who originally contributed the double-precision real packm kernels (d6xk and d8xk), which I have now tweaked and used to create comparable single-precision real kernels (s6xk and s16xk). commit f50c1b7e5886d29efe134e1994d05af9949cd4b6 Merge: 8f39aea1 b3953b93 Author: Devin Matthews Date: Mon Feb 1 11:55:51 2021 -0600 Merge pull request #473 from ajaypanyala/pkgconfig build: generate pkgconfig file commit 8f39aea11f80a805b66cff4b4dc5e72727ea461d Merge: f8db9fb3 2a815d5b Author: Field G. Van Zee Date: Sat Jan 30 17:59:56 2021 -0600 Merge branch 'dev' commit f8db9fb33b48844d6b47fdef699625bd9197745a Author: Field G. Van Zee Date: Thu Jan 28 08:04:52 2021 -0600 Fixed missing parentheses in README.md Citations. commit b3953b938eee59f79b4a4162ba583a5cb59fa34e Author: Ajay Panyala Date: Tue Jan 12 17:07:04 2021 -0800 drop CFLAGS in the generated pkgconfig file commit b02d9376bac31c1a1c7916f44c4946277a1425e2 Author: Ajay Panyala Date: Mon Jan 11 20:50:01 2021 -0800 add datadir commit d8d8deeb6d8b84adb7ae5fdb88c6dd4f06624a76 Author: Ajay Panyala Date: Mon Jan 11 17:47:50 2021 -0800 generate pkgconfig file commit 8c65411c7c8737248a6f054ffa0ce008c95cb515 Merge: 328b4f88 874c3f04 Author: Devin Matthews Date: Mon Jan 11 16:01:45 2021 -0600 Merge pull request #471 from flame/fix-470 Fix kernel-to-config mapping for intel64 commit 874c3f04ece9af4d8fdf0e2713e21a259c117656 Author: Devin Matthews Date: Fri Jan 8 13:56:30 2021 -0600 Update configure Choose last sub-config in the kernel-to-config map if the config list doesn't contain the name of the kernel set. E.g. for "zen: skx knl haswell" pick "haswell" instead of "skx" which was chosen previously. Fixes #470. commit 2a815d5b365d934cb351b2f2a8cd1366e997b2e1 Author: Field G. Van Zee Date: Mon Jan 4 18:03:39 2021 -0600 Support trsm pre-inversion in 1m, bb, ref kernels. Details: - Expanded support for disabling trsm diagonal pre-inversion to other microkernel types, including the reference microkernel as well as the kernel implementations for 1m and the pre-broadcast B (bb) format used by the power9 subconfig. This builds on the 'haswell' and 'penryn' kernel support added in 7038bba. Thanks to Bhaskar Nallani for reminding me, in #461 (post-closure), that 1m support was missing from that commit. - Removed cpp branch of ref_kernels/3/bli_trsm_ref.c that contained the omp simd implementation after making a stripped-down copy in 'old'. This code has been disabled for some time and it seemed better suited to rot away out of sight rather than clutter up a file that is already cluttered by the presence of lower and upper versions. - Minor comment update to bli_ind_init(). commit c3ed2cbb9f60100fc9beb2a9d75476de9f711dc5 Author: Field G. Van Zee Date: Mon Jan 4 16:16:32 2021 -0600 Enable 1m only if real domain ukr is not reference. Details: - Previously, BLIS would automatically enable use of the 1m method for a given precision if the complex domain microkernel was a reference kernel. This commit adds an additional constraint so that 1m is only enabled if the corresponding real domain microkernel is NOT reference. That is, BLIS now forgos use of 1m if both the real and complex domain kernels are reference implementations. Note that this does not prevent 1m from being enabled manually under those conditions; it only means that 1m will not be enabled automatically at initialization-time. commit ed50c947385ba3b0b5d550015f38f7f0a31755c0 Merge: 0cef09aa 328b4f88 Author: Field G. Van Zee Date: Mon Jan 4 14:31:44 2021 -0600 Merge branch 'master' into dev commit 328b4f8872b4bca9a53d2de8c6e285f3eb13d196 Author: Devin Matthews Date: Wed Dec 30 17:54:18 2020 -0600 Shared object (dylib) was not built correctly for partial build. The SO build rule used $? instead of $^. Observed on macOS, not sure if it affected Linux or not. commit ae6ef66ef824da9bc6348bf9d1b588cd4f2ded9b Author: Devin Matthews Date: Wed Dec 30 17:34:55 2020 -0600 bli_diag_offset_with_trans had wrong return type. Fixes #468. commit ebcf197fb86fdd0a864ea928140752bc2462e8c6 Merge: 472f138c 21aa67e1 Author: Devin Matthews Date: Sat Dec 5 22:26:27 2020 -0600 Merge pull request #466 from isuruf/patch-3 fix cc_vendor for crosstool-ng toolchains commit 21aa67e11cebbc5a6dd7c6353154256294df3c33 Author: Isuru Fernando Date: Sat Dec 5 21:59:13 2020 -0600 fix cc_vendor for crosstool-ng toolchains commit 472f138cb927b7259126ebb9c68919cfcc7a4ea3 Author: Field G. Van Zee Date: Sat Dec 5 14:13:52 2020 -0600 Fixed typo in README.md to CodingConventions.md. commit 0cef09aa92208441a656bf097f197ea8e22b533b Author: Field G. Van Zee Date: Fri Dec 4 16:40:59 2020 -0600 Consolidated code in level-3 _front() functions. Details: - Reduced a code segment that appears in all of the bli_*_front() functions except for bli_gemm_front(). Previously, the code looked like this (taken from bli_herk_front()): if ( bli_cntx_method( cntx ) == BLIS_NAT ) { bli_obj_set_pack_schema( BLIS_PACKED_ROW_PANELS, &a_local ); bli_obj_set_pack_schema( BLIS_PACKED_COL_PANELS, &ah_local ); } else // if ( bli_cntx_method( cntx ) != BLIS_NAT ) { pack_t schema_a = bli_cntx_schema_a_block( cntx ); pack_t schema_b = bli_cntx_schema_b_panel( cntx ); bli_obj_set_pack_schema( schema_a, &a_local ); bli_obj_set_pack_schema( schema_b, &ah_local ); } This code segment is part of a sort-of-hack that allows us to communicate the pack schemas into the level-3 thread decorator, which needs them so that they can be passed into bli_l3_cntl_create_if(), where the control tree is created. However, the first conditional case above is unnecessary because the second case is fully generalized. That is, even in the native case, the context contains correct, queryable schemas. Thus, these code segments were reduced to something like: pack_t schema_a = bli_cntx_schema_a_block( cntx ); pack_t schema_b = bli_cntx_schema_b_panel( cntx ); bli_obj_set_pack_schema( schema_a, &a_local ); bli_obj_set_pack_schema( schema_b, &ah_local ); There's always a small chance that the seemingly unnecessary code in the first branch case has some special use that is not apparent to me, but the testsuite's default input parameters seem to think this commit will be fine. commit 7038bbaa05484141195822291cf3ba88cbce4980 Author: Field G. Van Zee Date: Fri Dec 4 16:08:15 2020 -0600 Optionally disable trsm diagonal pre-inversion. Details: - Implemented a configure-time option, --disable-trsm-preinversion, that optionally disables the pre-inversion of diagonal elements of the triangular matrix in the trsm operation and instead uses division instructions within the gemmtrsm microkernels. Pre-inversion is enabled by default. When it is disabled, performance may suffer slightly, but numerical robustness should improve for certain pathological cases involving denormal (subnormal) numbers that would otherwise result in overflow in the pre-inverted value. Thanks to Bhaskar Nallani for reporting this issue via #461. - Added preprocessor macro guards to bli_trsm_cntl.c as well as the gemmtrsm microkernels for 'haswell' and 'penryn' kernel sets pursuant to the aforementioned feature. - Added macros to frame/include/bli_x86_asm_macros.h related to division instructions. commit 78aee79452cce2691c40f05b3632bdfc122300af Author: Field G. Van Zee Date: Wed Dec 2 13:02:36 2020 -0600 Allow amaxv testsuite module to run with dim = 0. Details: - Exit early from libblis_test_amaxv_check() when the vector dimension (length) of x is 0. This allows the module to run when the testsuite driver passes in a problem size of 0. Thanks to Meghana Vankadari for alerting us to this issue via #459. - Note: All other testsuite modules appear to work with problem sizes of 0, except for the microkernel modules. I chose not to "fix" those modules because a failure (or segmentation fault, as happens in this case) is actually meaningful in that it alerts the developer that some microkernels cannot be used with k = 0. Specifically, the 'haswell' kernel set contains microkernels that preload elements of B. Those microkernels would need to be restructured to avoid preloading in order to support usage when k = 0. commit 92d2b12a44ee0990c22735472aeaf1c17deb2d9b Author: Field G. Van Zee Date: Wed Dec 2 13:02:00 2020 -0600 Fixed obscure testsuite gemmt dependency bug. Details: - Fixed a bug in the gemmt testsuite module that only manifested when testing of gemmt is enabled but testing of gemv is disabled. The bug was due to a copy-paste error dating back to the introduction of gemmt in 88ad841. commit b43dae9a5d2f078c9bbe07079031d6c00a68b7de Author: Field G. Van Zee Date: Tue Dec 1 16:44:38 2020 -0600 Fixed copy-paste bugs in edge-case sup kernels. Details: - Fixed bugs in two sup kernels, bli_dgemmsup_rv_haswell_asm_1x6() and bli_dgemmsup_rd_haswell_asm_1x4(), which involved extraneous assembly instructions that were left over from when the kernels were first written. These instructions would cause segmentation faults in some situations where extra memory was not allocated beyond the end of the matrix buffers. Thanks to Kiran Varaganti for reporting these bugs and to Bhaskar Nallani for identifying the cause and solution. commit 11dfc176a3c422729f453f6c23204cf023e9954d Author: Field G. Van Zee Date: Tue Dec 1 19:51:27 2020 +0000 Reorganized thread auto-factorization logic. Details: - Reorganized logic of bli_thread_partition_2x2() so that the primary guts were factored out into "fast" and "slow" variants. Then added logic to the "fast" variant that allows for more optimal thread factorizations in some situations where there is at least one factor of 2. - Changed BLIS_THREAD_RATIO_M from 2 to 1 in bli_kernel_macro_defs.h and added comments to that file describing BLIS_THREAD_RATIO_? and BLIS_THREAD_MAX_?R. - In bli_family_zen.h and bli_family_zen2.h, preprocessed out several macros not used in vanilla BLIS and removed the unused macro BLIS_ENABLE_ZEN_BLOCK_SIZES from the former file. - Disabled AMD's small matrix handling entry points in bli_syrk_front.c and bli_trsm_front.c. (These branches of small matrix handling have not been reviewed by vanilla BLIS developers.) - Added commented-out calls printf() to bli_rntm.c. - Whitespace changes to bli_thread.c. commit 6d3bafacd7aa7ad198762b39490876c172bfbbcb Author: Devin Matthews Date: Sat Nov 28 17:17:56 2020 -0600 Update BuildSystem.md Add git version >= 1.8.5 requirement (see #462). commit 64856ea5a61b01d585750815788b6a775f729647 Author: Field G. Van Zee Date: Mon Nov 23 16:54:51 2020 -0600 Auto-reduce (by default) prime numbers of threads. Details: - When requesting multithreaded parallelism by specifying the total number of threads (whether it be via environment variable, globally at runtime, or locally at runtime), reduce the number of threads actually used by one if the original value (a) is prime and (b) exceeds a minimum threshold defined by the macro BLIS_NT_MAX_PRIME, which is set to 11 by default. If, when specifying the total number of threads (and not the individual ways of parallelism for each loop), prime numbers of threads are desired, this feature may be overridden by defining the BLIS_ENABLE_AUTO_PRIME_NUM_THREADS macro in the bli_family_*.h that corresponds to the configuration family targeted at configure-time. (For now, there is no configure option(s) to control this feature.) Thanks to Jeff Diamond for suggesting this change. - Defined a new function in bli_thread.c, bli_is_prime(), that returns a bool that determines whether an integer is prime. This function is implemented in terms of existing functions in bli_thread.c. - Updated docs/Multithreading.md to document the above feature, along with unrelated minor edits. commit 55933b6ff6b9b8a12041715f42bba06273d84b74 Author: Field G. Van Zee Date: Fri Nov 20 10:39:32 2020 -0600 Added missing attribution to docs/ReleaseNotes.md. commit e310f57b4b29fbfee479e0f9fe2040851efdec4f Author: Field G. Van Zee Date: Thu Nov 19 13:33:37 2020 -0600 CHANGELOG update (0.8.0) commit 9b387f6d5a010969727ec583c0cdd067a5274ed8 (tag: 0.8.0) Author: Field G. Van Zee Date: Thu Nov 19 13:33:37 2020 -0600 Version file update (0.8.0) commit 2928ec750d3a3e1e5d55de5b57ddc04e9d0bd796 Author: Field G. Van Zee Date: Wed Nov 18 18:31:35 2020 -0600 ReleaseNotes.md update in advance of next version. Details: - Updated docs/ReleaseNotes.md in preparation for next version. commit b9899bedff6854639468daa7a973bb14ca131a74 Author: Field G. Van Zee Date: Wed Nov 18 16:52:41 2020 -0600 CREDITS file update. commit 9bb23e6c2a44b77292a72093938ab1ee6e6cc26a Author: Field G. Van Zee Date: Mon Nov 16 15:55:45 2020 -0600 Added support for systemless build (no pthreads). Details: - Added a configure option, --[enable|disable]-system, which determines whether the modest operating system dependencies in BLIS are included. The most notable example of this on Linux and BSD/OSX is the use of POSIX threads to ensure thread safety for when application-level threads call BLIS. When --disable-system is given, the bli_pthreads implementation is dummied out entirely, allowing the calling code within BLIS to remain unchanged. Why would anyone want to build BLIS like this? The motivating example was submitted via #454 in which a user wanted to build BLIS for a simulator such as gem5 where thread safety may not be a concern (and where the operating system is largely absent anyway). Thanks to Stepan Nassyr for suggesting this feature. - Another, more minor side effect of the --disable-system option is that the implementation of bli_clock() unconditionally returns 0.0 instead of the time elapsed since some fixed point in the past. The reasoning for this is that if the operating system is truly minimal, the system function call upon which bli_clock() would normally be implemented (e.g. clock_gettime()) may not be available. - Refactored preprocess-guarded code in bli_pthread.c and bli_pthread.h to remove redundancies. - Removed old comments and commented #include of "bli_pthread_wrap.h" from bli_system.h. - Documented bli_clock() and bli_clock_min_diff() in BLISObjectAPI.md and BLISTypedAPI.md, with a note that both are non-functional when BLIS is configured with --disable-system. commit 88ad84143414644df4c56733b1cf91a36bfacaf8 Author: Field G. Van Zee Date: Sat Nov 14 09:39:48 2020 -0600 Squash-merge 'pr' into 'squash'. (#457) Merged contributions from AMD's AOCL BLIS (#448). Details: - Added support for level-3 operation gemmt, which performs a gemm on only the lower or upper triangle of a square matrix C. For now, only the conventional/large code path will be supported (in vanilla BLIS). This was accomplished by leveraging the existing variant logic for herk. However, some of the infrastructure to support a gemmtsup is included in this commit, including - A bli_gemmtsup() front-end, similar to bli_gemmsup(). - A bli_gemmtsup_ref() reference handler function. - A bli_gemmtsup_int() variant chooser function (with variant calls commented out). - Added support for inducing complex domain gemmt via the 1m method. - Added gemmt APIs to the BLAS and CBLAS compatiblity layers. - Added gemmt test module to testsuite. - Added standalone gemmt test driver to 'test' directory. - Documented gemmt APIs in BLISObjectAPI.md and BLISTypedAPI.md. - Added a C++ template header (blis.hh) containing a BLAS-inspired wrapper to a set of polymorphic CBLAS-like function wrappers defined in another header (cblas.hh). These two headers are installed if running the 'install' target with INSTALL_HH is set to 'yes'. (Also added a set of unit tests that exercise blis.hh, although they are disabled for now because they aren't compatible with out-of-tree builds.) These files now live in the 'vendor' top-level directory. - Various updates to 'zen' and 'zen2' subconfigurations, particularly within the context initialization functions. - Added s and d copyv, setv, and swapv kernels to kernels/zen/1, and various minor updates to dotv and scalv kernels. Also added various sup kernels contributed by AMD to kernels/zen/3. However, these kernels are (for now) not yet used, in part because they caused AppVeyor clang failures, and also because I have not found time to review and vet them. - Output the python found during configure into the definition of PYTHON in build/config.mk (via build/config.mk.in). - Added early-return checks (A, B, or C with zero dimension; alpha = 0) to bli_gemm_front.c. - Implemented explicit beta = 0 handling in for the sgemm ukernel in bli_gemm_armv7a_int_d4x4.c, which was previously missing. This latent bug surfaced because the gemmt module verifies its computation using gemm with its beta parameter set to zero, which, on a cortexa15 system caused the gemm kernel code to unconditionally multiply the uninitialized C data by beta. The C matrix likely contained non-numeric values such as NaN, which then would have resulted in a false failure. - Fixed a bug whereby the implementation for bli_herk_determine_kc(), in bli_l3_blocksize.c, was inadvertantly being defined in terms of helper functions meant for trmm. This bug was probably harmless since the trmm code should have also done the right thing for herk. - Used cpp macros to neutralize the various AOCL_DTL_TRACE_ macros in kernels/zen/3/bli_gemm_small.c since those macros are not used in vanilla BLIS. - Added cpp guard to definition of bli_mem_clear() in bli_mem.h to accommodate C++'s stricter type checking. - Added cpp guard to test/*.c drivers that facilitate compilation on Windows systems. - Various whitespace changes. commit 234b8b0cf48f1ee965bd7999b291fc7add3b9a54 Author: Field G. Van Zee Date: Thu Nov 12 19:11:16 2020 -0600 Increased dotxaxpyf testsuite thresholds. Details: - Increased the test thresholds used by the dotxaxpyf testsuite module by a factor of five in order to avoid residuals that unnecessarily fall in the MARGINAL range. This commit should fix #455. Thanks to @nagsingh for reporting this issue. commit ed612dd82c50063cfd23576a6b2465213d31b14b Author: Field G. Van Zee Date: Sat Nov 7 13:09:42 2020 -0600 Updated README.md with sgemmsup blurb. Details: - Added an entry to the "What's New" section of the README.md to announce the availability of sgemmsup. commit e14424f55b15d67e8d18384aea45a11b9b772e02 Merge: 0cfe1aac eccdd75a Author: Field G. Van Zee Date: Sat Nov 7 13:02:50 2020 -0600 Merge branch 'dev' commit 0cfe1aac222008a78dff3ee03ef5183413936706 Author: Field G. Van Zee Date: Fri Oct 30 17:10:36 2020 -0500 Relocated operation index to ToC in API docs. Details: - Moved the "Operation index" section of both the BLISObjectAPI.md and BLISTypedAPI.md docs to appear immediately after the table of contents of each document. This allows the reader to quickly jump to the documentation for any operation without having to scroll through much of the document (when rendered via a web browser). - Fixed a mistake in the BLISObjectAPI.md for the setd operation, which does *not* observe the diag property of its matrix argument. Thanks to Jeff Diamond for reporting this. commit 2a0682f8e5998be536da313525292f0da6193147 Author: Field G. Van Zee Date: Sun Oct 18 18:04:03 2020 -0500 Implemented runtime subconfig selection (#451). Details: - Implemented support for the user manually overriding the automatic subconfiguration selection that happens at runtime. This override can be requested by setting the BLIS_ARCH_TYPE environment variable. The variable must be set to the arch_t id (as enumerated in bli_type_defs.h) corresponding to the desired subconfiguration. If a value outside this enumerated range is given, BLIS will abort with an error message. If the value is in the valid range but corresponds to a subconfiguration that was not activated at configure-time/compile-time, BLIS will abort with a (different) error message. Thanks to decandia50 for suggesting this feature via issue #451. - Defined a new function bli_gks_lookup_id to return the address of an internal data structure within the gks. If this address is NULL, then it indicates that the subconfig corresponding to the arch_t id passed into the function was not compiled into BLIS. This function is used in the second of the two abort scenarios described above. - Defined the enumerated error code BLIS_UNINITIALIZED_GKS_CNTX, which is returned for the latter of the two abort scenarios mentioned above, along with a corresponding error message and a function to perform the error check. - Added cpp macro branching to bli_env.c to support compilation of the auto-detect.x executable during configure-time. This cpp branch is similar to the cpp code already found in bli_arch.c and bli_cpuid.c. - Cleaned up the auto_detect() function to facilitate easier maintenance going forward. Also added a convenient debug switch that outputs the compilation command for the auto-detect.x executable and exits. commit eccdd75a2d8a0c46e91e94036179c49aa5fa601c Author: Field G. Van Zee Date: Fri Oct 9 15:44:16 2020 -0500 Whitespace tweak in docs/PerformanceSmall.md. commit 7677e9ba60ac27496e3421c2acc7c239e3f860e9 Merge: addcd46b a0849d39 Author: Field G. Van Zee Date: Fri Oct 9 15:41:25 2020 -0500 Merge branch 'dev' of github.com:flame/blis into dev commit addcd46b0559d401aa7d33d4c7e6f63f5313a8e0 Author: Field G. Van Zee Date: Fri Oct 9 15:41:09 2020 -0500 Added Epyc 7742 Zen2 ("Rome") sup perf results. Details: - Added single-threaded and multithreaded sup performance results to docs/PerformanceSmall.md for both sgemm and dgemm. These results were gathered on an Epyc 7742 "Rome" server featuring AMD's Zen2 microarchitecture. Special thanks to Jeff Diamond for facilitating access to the system via the Oracle Cloud. - Updates to octave scripts in test/sup/octave for use with Octave 5.2 and for use with subplot_tight(). - Minor updates to octave scripts in test/3/octave. - Renamed files containing the previous Zen performance results for consistency with the new results. - Decreased line thickness slightly in large/conventional Zen2 graphs. I'm done tweaking those this time. Really. - Added missing line regarding eigen header installation for each microarchitecture section. commit a0849d390d04067b82af937cda8191b049b98915 Author: Field G. Van Zee Date: Fri Oct 9 20:22:17 2020 +0000 Register l3 sup kernels in zen2 subconfig. Details: - Registered full suite of sgemm and dgemm sup millikernels, blocksizes, and crossover thresholds in bli_cntx_init_zen2.c. - Minor updates to test/sup/runme.sh for running on Zen2 Epyc 7742 system. commit d98368c32d5fbfaab8966ee331d9bcb5c4fe7a59 Author: Field G. Van Zee Date: Thu Oct 8 19:05:51 2020 -0500 Another tweak to line thickness of Zen2 graphs. commit 1855dfbdaafa37892b36c97fd317fd5d8da76676 Author: Field G. Van Zee Date: Thu Oct 8 19:01:00 2020 -0500 Tweaked line thickness in Zen2 graphs once more. Details: - Decreased (relative to previous commit) line thickness in recent Zen2 graphs. commit 0991611e7ed82889c53a5c3f1ef1d49552c50d61 Author: Field G. Van Zee Date: Thu Oct 8 18:54:49 2020 -0500 Increased line thickness in recent Zen2 graphs. Details: - Increased the width of the lines in the graphs introduced in 74ec6b8. commit 8273cbacd7799e9af59e5320d66055f2f5d9cb31 Author: Field G. Van Zee Date: Wed Oct 7 14:51:33 2020 -0500 README.md, docs/FAQ.md updates. Details: - Added a frequently asked question to docs/FAQ.md regarding the difference between upstream (vanilla) BLIS and AMD BLIS. - Updated the name of ICES in the README.md to reflect the Oden rebranding. commit a178a822ad3d5021489a0e61f909d8550ae12a8f Author: Field G. Van Zee Date: Wed Sep 30 16:00:52 2020 -0500 Added Zen2 links to docs/Performance.md Contents. commit 74ec6b8f457cabe37d2382aaab35ba04fc737948 Author: Field G. Van Zee Date: Wed Sep 30 15:54:18 2020 -0500 Added Epyc 7742 Zen2 ("Rome") performance results. Details: - Added single-threaded and multithreaded performance results to docs/Performance.md. These results were gathered on an Epyc 7742 "Rome" server with AMD's Zen2 microarchitecture. Special thanks to Jeff Diamond for facilitating access to the system via the Oracle Cloud. - Renamed files containing the previous Zen performance results for consistency with the new results. commit bc4a213a2c3dcf8bbfcbb3a1ef3e9fc9e3226c34 Author: Field G. Van Zee Date: Wed Sep 30 15:28:20 2020 -0500 Updated matlab (now octave) plot code in test/3. Details: - Renamed test/3/matlab to test/3/octave. - Within test/3, updated and tuned plot_l3_perf.m and plot_panel_4x5.m files for use with octave (which is free and doesn't crash on me mid-way through my use of subplot). - Updated runthese.m scratchpad for zen2 invocations. - Added Nikolay S.'s subplot_tight() function, along with its license. commit c77ddc418187e1884fa6bcfe570eee295b9cb8bc Author: Field G. Van Zee Date: Wed Sep 30 20:15:43 2020 +0000 Added optional numactl usage to test/3/runme.sh. commit 2d8ec164e7ae4f0c461c27309dc1f5d1966eb003 Author: Nicholai Tukanov Date: Tue Sep 29 16:52:18 2020 -0500 Add POWER10 support to BLIS (#450) commit 4fd8d9fec2052257bf2a5c6e0d48ae619ff6c3e4 Author: Field G. Van Zee Date: Mon Sep 28 23:39:05 2020 +0000 Tweaked zen2 subconfig's MC cache blocksizes. Details: - Updated the MC cache blocksizes registered by the 'zen2' subconfig. - Minor updates to test/3/Makefile and test/3/runme.sh. commit 5efcdeffd58af621476d179afc0c19c0f912baa8 Author: Field G. Van Zee Date: Fri Sep 25 14:25:24 2020 -0500 More minor README.md updates. commit 9e940f8aad6f065ea1689e791b9a4e1fb7900c40 Author: Field G. Van Zee Date: Fri Sep 25 13:53:35 2020 -0500 Added 1m SISC bibtex to README.md. Details: - Added final citation info to 1m bibtex in README.md file. - Updated draft 1m paper link. - Changed some http to https. commit e293cae2d1b9067261f613f25eaa0e871356b317 Author: Field G. Van Zee Date: Tue Sep 15 16:09:11 2020 -0500 Implemented sgemmsup assembly kernels. Details: - Created a set of single-precision real millikernels and microkernels comparable to the dgemmsup kernels that already exist within BLIS. - Added prototypes for all kernels within bli_kernels_haswell.h. - Registered entry-point millikernels in bli_cntx_init_haswell.c and bli_cntx_init_zen.c. - Added sgemmsup support to the Makefile, runme.sh script, and source file in test/sup. This included edits that allow for separate "small" dimensions for single- and double-precision as well as for single- vs. multithreaded execution. commit 2765c6f37c11cb7f71cd4b81c64cea6130636c68 Author: Field G. Van Zee Date: Sat Sep 12 17:48:15 2020 -0500 Type saga continues; fixed sgemm ukernel signature. Details: - Changed double* pointers in sgemm function signature to float*. At this point I've lost track of whether this was my fault or another dormant bug like the one described in ece9f6a, but at this point I no longer care. It's one of those days (aka I didn't ask for this). commit 0779559509e0a1af077530d09ed151dac54f32ee Author: Field G. Van Zee Date: Sat Sep 12 17:37:21 2020 -0500 Fixed missing restrict in knl sgemm prototype. Details: - Added a missing 'restrict' qualifier in the sgemm ukernel prototype for knl. (Not sure how that code was ever compiling before now.) commit ece9f6a3ef1b26b53ecf968cd069df7a85b139fb Author: Field G. Van Zee Date: Sat Sep 12 17:22:42 2020 -0500 Fixed dormant type bugs in bli_kernels_knl.h. Details: - Fixed dormant type mismatches in the use of the prototype-generating macros in bli_kernels_knl.h. Specifically, some float prototypes were incorrectly using double as their ctype. This didn't actually matter until the type changes in 645d771, as previously those types were not used since packm was prototyped with void* pointers. commit 8ebb3b60e1c4c045ddb48e02de6e246cecde24a4 Author: Field G. Van Zee Date: Sat Sep 12 17:00:47 2020 -0500 Fixed accidental breakage in 645d771. Details: - In trying to clean up kappa_cast variables in the reference packm kernels, which I initally believed to be redundant given the other void* -> ctype* changes in 645d771, I accidentally ended up violating restrict semantics for 1e/1r packing and possibly other packm kernels. (Normally, my pre-commit testsuite run would have caught this, but I was unknowingly using an edited input.operations file in which I'd disabled most tests as part of unrelated work.) This commit reverts the kappa_cast changes in 645d771. commit 645d771a14ae89aa7131d6f8f4f4a8090329d05e Author: Field G. Van Zee Date: Sat Sep 12 15:31:56 2020 -0500 Minor packm kernel type cleanup (void* -> ctype*). Details: - Changed all void* function arguments in reference packm kernels to those of the native type (ctype*). These pointers no longer need to be void* and are better represented by their native types anyway. (See below for details.) Updated knl packm kernels accordingly. - In the definition of the PACKM_KER_PROT prototype macro template in frame/1m/bli_l1m_ker_prot.h, changed the pointer types for kappa, a, and p from void* to ctype*. They were originally void* because these function signatures had to share the same type so they could all be stored in a single array of that shared type, from which they were queried and called by packm_cxk(). This is no longer how the function pointers are stored, and so it no longer makes sense to force the caller of packm kernels to use void*, only so that the implementor of the packm kernels can typecast back to the native datatype within the kernel definition. This change has no effect internally within BLIS because currently all packm kernels are called after querying the function addresses from the context and then typecasting to the appropriate function pointer type, which is based upon type-specific function pointers like float* and double*. - Removed a comment in frame/1m/bli_l1m_ft_ker.h that was outdated and misleading due to changes to the handling of packm kernels since moving them into the context. commit 54bf6c35542a297e25bc8efec6067a6df80536f4 Author: Field G. Van Zee Date: Thu Sep 10 15:42:01 2020 -0500 Minor README.md update. Details: - Added a new entry to the "What people are saying about BLIS" section. commit e50b4d40462714ae33df284655a2faf7fa35f37c Author: Field G. Van Zee Date: Wed Sep 9 14:12:53 2020 -0500 Minor update to README.md (SIAM Best Paper Prize). commit a8efb72074691e2610372108becd88b4b392299e Merge: b0c4da17 97e87f2c Author: Devin Matthews Date: Mon Sep 7 16:18:19 2020 -0500 Merge pull request #434 from flame/intel-zdot Add an option to change the complex return type. commit 97e87f2c9f3878a05e1b7c6ec237ee88d9a72a42 Author: Field G. Van Zee Date: Mon Sep 7 15:56:42 2020 -0500 Whitespace/comment updates to #434 PR. commit b0c4da1732b6c6a9ff66f70c36e4722e0f9645ae Merge: 810e90ee b1b5870d Author: Devin Matthews Date: Mon Sep 7 15:47:54 2020 -0500 Merge pull request #436 from flame/s390x Add checks so that s390x is detected as 64-bit. commit 810e90ee806510c57504f0cf8eeaf608d38bd9dd Author: Field G. Van Zee Date: Tue Sep 1 16:11:40 2020 -0500 Minor README.md update. Details: - Added HPE to list of funders. - Changed http to https in funders' website links. commit 7d411282196e036991c26e52cb5e5f85769c8059 Author: Devin Matthews Date: Thu Aug 13 17:50:58 2020 -0500 Use -O2 for all framework code. (#435) It seems that -O3 might be causing intermittent problems with the f2c'ed packed and banded code. -O3 is retained for kernel code. Fixes #341 and fixes #342. commit 9c5b485d356367b0a1288761cd623f52036e7344 Author: Dave Love Date: Fri Aug 7 20:11:18 2020 +0000 Don't override -mcpu with -march on ARM (#353) * Use -mcpu for ARM See the GCC doc about -march, -mtune, and -mpu and maybe https://community.arm.com/developer/tools-software/tools/b/tools-software-ides-blog/posts/compiler-flags-across-architectures-march-mtune-and-mcpu * Fix typo in flags * Fix typo in cortexa9 flags * Modify cortexa53 compilation flags to fix failing BLAS check (#341) commit c253d14a72a746b670b3ffbb6e81bcafc73d1133 Author: Devin Matthews Date: Fri Aug 7 09:39:04 2020 -0500 Also handle Intel-style complex return in CBLAS interface. commit 5d653a11a0cc71305d0995507b1733995856f475 Author: Devin Matthews Date: Thu Aug 6 17:58:26 2020 -0500 Update Multithreading.md Addresses the issue raised in #426. commit b1b5870dd3f9b1c78cf5f58a53514d73f001fc4c Author: Devin Matthews Date: Thu Aug 6 17:34:20 2020 -0500 Add checks so that s390x is detected as 64-bit. commit 882dcb11bfc9ea50aa2f9044621833efd90d42be Author: Field G. Van Zee Date: Thu Aug 6 17:28:14 2020 -0500 Mention example code at top of documentation docs. Details: - Steer the reader towards the example code section of each documentation doc (object and typed). - Trivial update to examples/oapi/README, examples/tapi/README. commit f4894512e5bf56ff83701c07dd02972e300741a5 Author: Field G. Van Zee Date: Thu Aug 6 17:20:00 2020 -0500 Very minor updates to previous commit. commit adedb893ae8dfacd1dc54035979e15c44d589dbb Author: Field G. Van Zee Date: Thu Aug 6 17:14:01 2020 -0500 Documented mutator functions in BLISObjectAPI.md. Details: - Added documentation for commonly-used object mutator functions in BLISObjectAPI.md. Previously, only accessor functions were documented. Thanks to Jeff Diamond for pointing out this omission. - Explicitly set the 'diag' property of objects in oapi example modules (08level2.c and 09level3.c). commit 5b5278ff494888509543a79c09ea82089f6c95d9 Author: Devin Matthews Date: Thu Aug 6 14:19:37 2020 -0500 Use #ifdef instead of #if as macro may be undefined. commit 7fdc0fc893d0c6727b725ea842053b65be2c20ba Author: Devin Matthews Date: Thu Aug 6 14:03:55 2020 -0500 Add an option to change the complex return type. ifort apparently does not return complex numbers in registers as in C/C++ (or gfortran), but instead creates a "hidden" first parameter for the return value. The option --complex-return=gnu|intel has been added, as well as a guess based on a provided FC if not specified (otherwise default to gnu). This option affects the signatures of cdotc, cdotu, zdotc, and zdotu, and a single library cannot be used with both GNU and Intel Fortran compilers. Fixes #433. commit 6e522e5823b762d4be09b6acdca30faafba56758 Author: Field G. Van Zee Date: Thu Jul 30 19:31:37 2020 -0500 Mention disabling of sup in docs/Sandboxes.md. Details: - Added language to remind the reader to disable sup if the intended behavior is for the sandbox implementation to handle all problem sizes, even the smaller ones that would normally be handled by the sup code path. commit 00e14cb6d849e963a2e1ac35e7dbbe186af00a58 Author: Field G. Van Zee Date: Wed Jul 29 14:24:34 2020 -0500 Replaced use of bool_t type with C99 bool. Details: - Textually replaced nearly all non-comment instances of bool_t with the C99 bool type. A few remaining instances, such as those in the files bli_herk_x_ker_var2.c, bli_trmm_xx_ker_var2.c, and bli_trsm_xx_ker_var2.c, were promoted to dim_t since they were being used not for boolean purposes but to index into an array. - This commit constitutes the third phase of a transition toward using C99's bool instead of bool_t, which was raised in issue #420. The first phase, which cleaned up various typecasts in preparation for using bool as the basis for bool_t (instead of gint_t), was implemented by commit a69a4d7. The second phase, which redefined the bool_t typedef in terms of bool (from gint_t), was implemented by commit 2c554c2. commit 2c554c2fce885f965a425e727a0314d3ba66c06d Author: Field G. Van Zee Date: Fri Jul 24 15:57:19 2020 -0500 Redefined bool_t typedef in terms of C99 bool. Details: - Changed the typedef that defines bool_t from: typedef gint_t bool_t; where gint_t is a signed integer that forms the basis of most other integers in BLIS, to: typedef bool bool_t; - Changed BLIS's TRUE and FALSE macro definitions from being in terms of integer literals: #define TRUE 1 #define FALSE 0 to being in terms of C99 boolean constants: #define TRUE true #define FALSE false which are provided by stdbool.h. - This commit constitutes the second phase of a transition toward using C99's bool instead of bool_t, which will address issue #420. The first phase, which cleaned up various typecasts in preparation for using bool as the basis for bool_t (instead of gint_t), was implemented by commit a69a4d7. commit e01dd125581cec87f61e15590922de0dc938ec42 Author: Field G. Van Zee Date: Fri Jul 24 15:41:46 2020 -0500 Fail-safe updates to Makefiles in 'test' dir. Details: - Updated Makefiles in test, test/3, and test/sup so that running any of the usual targets without having first built BLIS results in a helpful error message. For example, if BLIS is not yet configured, make will output: Makefile:327: *** Cannot proceed: config.mk not detected! Run configure first. Stop. Similarly, if BLIS is configured but not yet built, make will output: Makefile:340: *** Cannot proceed: BLIS library not yet built! Run make first. Stop. In previous commits, these actions would result in a rather cryptic make error such as: make: *** No rule to make target 'test_sgemm_2400_asm_blis_st.x', needed by 'blis-nat-st'. Stop. commit b4f47f7540062da3463e2cb91083c12fdda0d30a Author: Devin Matthews Date: Fri Jul 24 13:56:13 2020 -0500 Add BLIS_EXPORT_BLIS to bli_abort. (#429) Fixes #428. commit a69a4d7e2f4607c919db30b14535234ce169c789 Author: Field G. Van Zee Date: Wed Jul 22 16:13:09 2020 -0500 Cleaned up bool_t usage and various typecasts. Details: - Fixed various typecasts in frame/base/bli_cntx.h frame/base/bli_mbool.h frame/base/bli_rntm.h frame/include/bli_misc_macro_defs.h frame/include/bli_obj_macro_defs.h frame/include/bli_param_macro_defs.h that were missing or being done improperly/incompletely. For example, many return values were being typecast as (bool_t)x && y rather than (bool_t)(x && y) Thankfully, none of these deficiencies had manifested as actual bugs at the time of this commit. - Changed the return type of bli_env_get_var() from dim_t to gint_t. This reflects the fact that bli_env_get_var() needs to be able to return a signed integer, and even though dim_t is currently defined as a signed integer, it does not intuitively appear to necessarily be signed by inspection (i.e., an integer named "dim_t" for matrix "dimension"). Also, updated use of bli_env_get_var() within bli_pack.c to reflect the changed return type. - Redefined type of thrcomm_t.barrier_sense field from bool_t to gint_t and added comments to the bli_thrcomm_*.h files that will explain a planned replacement of bool_t with C99's bool type. - Note: These changes are being made to facilitate the substitution of 'bool' for 'bool_t', which will eliminate the namespace conflict with arm_sve.h as reported in issue #420. This commit implements the first phase of that transition. Thanks to RuQing Xu for reporting this issue. - CREDITS file update. commit a6437a5c11d364c6c88af527294d29734d7cc7d6 Author: Field G. Van Zee Date: Mon Jul 20 19:21:07 2020 -0500 Replaced broken ref99 sandbox w/ simpler version. Details: - The 'ref99' sandbox was broken by multiple refactorings and internal API changes over the last two years. Rather than try to fix it, I've replaced it with a much simpler version based on var2 of gemmsup. Why not fix the previous implementation? It occurred to me that the old implementation was trying to be a lightly simplified duplication of what exists in the framework. Duplication aside, this sandbox would have worked fine if it had been completely independent of the framework code. The problem was that it was only partially independent, with many function calls calling a function in BLIS rather than a duplicated/simplified version within the sandbox. (And the reason I didn't make it fully independent to begin with was that it seemed unnecessarily duplicative at the time.) Maintaining two versions of the same implementation is problematic for obvious reasons, especially when it wasn't even done properly to begin with. This explains the reimplementation in this commit. The only catch is that the newer implementation is single-threaded only and does not perform any packing on either input matrix (A or B). Basically, it's only meant to be a simple placeholder that shows how you could plug in your own implementation. Thanks to Francisco Igual for reporting this brokenness. - Updated the three reference gemmsup kernels (defined in ref_kernels/3/bli_gemmsup_ref.c) so that they properly handle conjugation of conja and/or conjb. The general storage kernel, which is currently identical to the column-storage kernel, is used in the new ref99 sandbox to provide basic support for all datatypes (including scomplex and dcomplex). - Minor updates to docs/Sandboxes.md, including adding the threading and packing limitations to the Caveats section. - Fixed a comment typo in bli_l3_sup_var1n2m.c (upon which the new sandbox implementation is based). commit bca040be9da542dd9c75d91890fa7731841d733d Merge: 2605eb4d 171ecc1d Author: Devin Matthews Date: Mon Jul 20 09:27:30 2020 -0500 Merge pull request #425 from gmargari/patch-1 Update Multithreading.md commit 171ecc1dc6f055ea39da30e508f711b49a734359 Author: Giorgos Margaritis Date: Mon Jul 20 12:24:06 2020 +0300 Update Multithreading.md commit 2605eb4d99d3813c37a624c011aa2459324a6d89 Author: Field G. Van Zee Date: Wed Jul 15 15:25:19 2020 -0500 Added missing rv_d?x6 edge cases to sup kernel. Details: - Added support to bli_gemmsup_rv_haswell_asm_d6x8n.c for handling various n = 6 edge cases with a single sup kernel call. Previously, only n = {4,2,1} were handled explicitly as single kernel calls; that is, cases where n = 6 were previously being executed via two kernel calls (n = 4 and n = 2). - Added commented debug line to testsuite's test_libblis.c. commit 72f6ed0637dfcb021de04ac7d214d5c87e55d799 Author: Field G. Van Zee Date: Fri Jul 3 17:55:54 2020 -0500 Declare/define static functions via BLIS_INLINE. Details: - Updated all static function definitions to use the cpp macro BLIS_INLINE instead of the static keyword. This allows blis.h to use a different keyword (inline) to define these functions when compiling with C++, which might otherwise trigger "defined but not used" warning messages. Thanks to Giorgos Margaritis for reporting this issue and Devin Matthews for suggesting the fix. - Updated the following files, which are used by configure's hardware auto-detection facility, to unconditionally #define BLIS_INLINE to the static keyword (since we know BLIS will be compiled with C, not C++): build/detect/config/config_detect.c frame/base/bli_arch.c frame/base/bli_cpuid.c - CREDITS file update. commit 5fc701ac5f94c6300febbb2f24e731aa34f0f34a Author: Field G. Van Zee Date: Wed Jul 1 15:48:58 2020 -0500 Added -fomit-frame-pointer option to CKOPTFLAGS. Details: - Added the -fomit-frame-pointer compiler option to the CKOPTFLAGS variable in the following make_defs.mk files: config/haswell/make_defs.mk config/skx/make_defs.mk as well as comments that mention why the compiler option is needed. This option is needed to prevent the compiler from using the rbp frame register (in the very early portion of kernel code, typically where k_iter and k_left are defined and computed), which, as of 1c719c9, is used explicitly by the gemmsup millikernels. Thanks to Devin Matthews for identifying this missing option and to Jeff Diamond for reporting the original bug in #417. - The file config/zen/amd_config.mk which feeds into the make_defs.mk for both zen and zen2 subconfigs, was also touched, but only to add a commented-out compiler option (and the aforementioned explanatory comment) since that file already uses -fomit-frame-pointer in COPTFLAGS, which forms the basis of CKOPTFLAGS. commit 6af59b705782dada47e45df6634b479fe781d4fe Author: Field G. Van Zee Date: Wed Jul 1 14:54:23 2020 -0500 Fixed disabled edge case optimization in gemmsup. Details: - Fixed an inadvertently disabled edge case optimization in the two gemmsup variants in bli_l3_sup_var1n2m.c. Background: These edge case optimizations allow the last millikernel operation in the jr loop to be executed with inflated an register blocksize if it is the last (or only) iteration. For example, if mr=6 and nr=8 and the gemmsup problem is m=8, n=100, k=100. (In this case, the panel-block variant (var1n) is executed, which places the jr loop in the m dimension.) In principle, this problem could be executed as two millikernels: one with dimensions 6x100x100, and one as 2x100x100. However, with the support for inflated blocksizes in the kernel, the entire 8x100x100 problem can be passed to the millikernel function, which will then execute it more favorably as two 4x100x100 millikernel sub-calls. Now, this optimization is disabled under certain circumstances, such as when multithreading. Previously, the is_mt predicate was being set incorrectly such that it was non-zero even when running single-threaded. - Upon fixing the is_mt issue above, another bit of code needed to be moved so that the result of the optimization could have an impact on the assignment of loop bounds ranges to threads. commit b37634540fab0f9b8d4751b8356ee2e17c9e3b00 Author: Field G. Van Zee Date: Thu Jun 25 16:05:12 2020 -0500 Support ldims, packing in sup/test drivers. Details: - Updated the test/sup source file (test_gemm.c) and Makefile to support building matrices with small or large leading dimensions, and updated runme.sh to support executing both kinds of test drivers. - Updated runme.sh to allow for executing sup drivers with unpacked (the default) or packed matrices (via setting BLIS_PACK_A, BLIS_PACK_B environment variables), and for capturing output to files that encode both the leading dimension (small or large) and packing status into the filenames. - Consolidated octave scripts in test/sup/octave_st, test/sup/octave_mt into test/sup/octave and updated the octave code in that consolidated directory to read the new output filename format (encoding ldim and packing). Also added comments and streamlined code, particularly in plot_panel_trxsh.m. Tested the octave scripts with octave 5.2.0. - Moved old octave_st, octave_mt directories to test/sup/old. commit ceb9b95a96cc3844ecb43d9af48ab289584e76b6 Author: Field G. Van Zee Date: Thu Jun 18 17:15:25 2020 -0500 Fixed incorrect link to shiftd in BLISTypedAPI.md. Details: - Previously, the entry for shiftd in the Operation index section of BLISTypedAPI.md was incorrectly linking to the shiftd operation entry in BLISObjectAPI.md. This has been fixed. Thanks to Jeff Diamond for helping find this incorrect link. commit b3c42016818797f79e55b32c8b7d090f9d0aa0ea Author: Field G. Van Zee Date: Thu Jun 18 14:00:56 2020 -0500 CREDITS file update. commit 31af73c11abae03248d959da0f81eacea015b57a Author: Isuru Fernando Date: Thu Jun 18 13:35:54 2020 -0500 Expand windows instructions (#414) * Expand windows instructions * Windows: both static and shared don't work at the same time commit b5b604e106076028279e6d94dc0e51b8ad48e802 Author: Field G. Van Zee Date: Wed Jun 17 16:42:24 2020 -0500 Ensure random objects' 1-norms are non-zero. Details: - Fixed an innocuous bug that manifested when running the testsuite on extremely small matrices with randomization via the "powers of 2 in narrow precision range" option enabled. When the randomization function emits a perfect 0.0 to fill a 1x1 matrix, the testsuite will then compute 0.0/0.0 during the normalization process, which leads to NaN residuals. The solution entails smarter implementaions of randv, randnv, randm, and randnm, each of which will compute the 1-norm of the vector or matrix in question. If the object has a 1-norm of 0.0, the object is re-randomized until the 1-norm is not 0.0. Thanks to Kiran Varaganti for reporting this issue (#413). - Updated the implementation of randm_unb_var1() so that it loops over a call to the randv_unb_var1() implementation directly rather than calling it indirectly via randv(). This was done to avoid the overhead of multiple calls to norm1v() when randomizing the rows/columns of a matrix. - Updated comments. commit 35e38fb693e7cbf2f3d7e0505a63b2c05d3f158d Author: Isuru Fernando Date: Tue Jun 16 10:59:41 2020 -0500 FIx typo in FAQ commit 1c719c91a3ef0be29a918097652beef35647d4b2 Author: Field G. Van Zee Date: Thu Jun 4 17:21:08 2020 -0500 Bugfixes, cleanup of sup dgemm ukernels. Details: - Fixed a few not-really-bugs: - Previously, the d6x8m kernels were still prefetching the next upanel of A using MR*rs_a instead of ps_a (same for prefetching of next upanel of B in d6x8n kernels using NR*cs_b instead of ps_b). Given that the upanels might be packed, using ps_a or ps_b is the correct way to compute the prefetch address. - Fixed an obscure bug in the rd_d6x8m kernel that, by dumb luck, executed as intended even though it was based on a faulty pointer management. Basically, in the rd_d6x8m kernel, the pointer for B (stored in rdx) was loaded only once, outside of the jj loop, and in the second iteration its new position was calculated by incrementing rdx by the *absolute* offset (four columns), which happened to be the same as the relative offset (also four columns) that was needed. It worked only because that loop only executed twice. A similar issue was fixed in the rd_d6x8n kernels. - Various cleanups and additions, including: - Factored out the loading of rs_c into rdi in rd_d6x8[mn] kernels so that it is loaded only once outside of the loops rather than multiple times inside the loops. - Changed outer loop in rd kernels so that the jump/comparison and loop bounds more closely mimic what you'd see in higher-level source code. That is, something like: for( i = 0; i < 6; i+=3 ) rather than something like: for( i = 0; i <= 3; i+=3 ) - Switched row-based IO to use byte offsets instead of byte column strides (e.g. via rsi register), which were known to be 8 anyway since otherwise that conditional branch wouldn't have executed. - Cleaned up and homogenized prefetching a bit. - Updated the comments that show the before and after of the in-register transpositions. - Added comments to column-based IO cases to indicate which columns are being accessed/updated. - Added rbp register to clobber lists. - Removed some dead (commented out) code. - Fixed some copy-paste typos in comments in the rv_6x8n kernels. - Cleaned up whitespace (including leading ws -> tabs). - Moved edge case (non-milli) kernels to their own directory, d6x8, and split them into separate files based on the "NR" value of the kernels (Mx8, Mx4, Mx2, etc.). - Moved config-specific reference Mx1 kernels into their own file (e.g. bli_gemmsup_r_haswell_ref_dMx1.c) inside the d6x8 directory. - Added rd_dMx1 assembly kernels, which seems marginally faster than the corresponding reference kernels. - Updated comments in ref_kernels/bli_cntx_ref.c and changed to using the row-oriented reference kernels for all storage combos. commit 943a21def0bedc1732c0a2453afe7c90d7f62e95 Author: Isuru Fernando Date: Thu May 21 14:09:21 2020 -0500 Add build instructions for Windows (#404) commit fbef422f0d968df10e598668b427af230cfe07e8 Author: Field G. Van Zee Date: Thu May 21 10:30:41 2020 -0500 Separate OS X and Windows into separate FAQs. Details: - Separated the unified Mac OS X / Windows frequently asked question into two separate questions, one for each OS. commit 28be1a4265ea67e3f177c391aba3dbbcf840bd52 Author: Guodong Xu Date: Thu May 21 02:22:22 2020 +0800 avoid loading twice in armv8a gemm kernel (#403) This bug happens at a corner case, when k_iter == 0 and we jump to CONSIDERKLEFT. In current design, first row/col. of a and b are loaded twice. The fix is to rearrange a and b (first row/col.) loading instructions. Signed-off-by: Guodong Xu commit d51245e58b0beff2717156b980007c90337150d8 Author: Field G. Van Zee Date: Fri May 8 18:00:54 2020 -0500 Add support for Intel oneAPI in configure. Details: - Properly select cc_vendor based on the output of invoking CC with the --version option, including cases where CC is the variant of clang that is included with Intel oneAPI. (However, we continue to treat the compiler as clang for other purposes, not icc.) Thanks to Ajay Panyala and Devin Matthews for reporting on this issue via #402. commit 787adad73bd5eb65c12c39d732723a1ac0448748 Author: Field G. Van Zee Date: Fri May 8 16:18:20 2020 -0500 Defined netlib equivalent of xerbla_array(). Details: - Added a function definition for xerbla_array_(), which largely mirrors its netlib implementation. Thanks to Isuru Fernando for suggesting the addition of this function. commit c53b5153bee585685bf95ce22e058a7af72ecef0 Author: Field G. Van Zee Date: Tue May 5 12:39:12 2020 -0500 Documented Perl prerequisite for build system. Details: - Added Perl to list of prerequisites for building BLIS. This is in part (and perhaps completely?) due to some substitution commands used at the end of configure that include '\n' characters that are not properly interpreted by the version of sed included on some versions of OS X. This new documentation addresses issue #398. commit f032d5d4a6ed34c8c3e5ba1ed0b14d1956d0097c Author: Guodong Xu Date: Thu Apr 30 01:08:46 2020 +0800 New kernel set for Arm SVE using assembly (#396) Here adds two kernels for Arm SVE vector extensions. 1. a gemm kernel for double at sizes 8x8. 2. a packm kernel for double at dimension 8xk. To achive best performance, variable length agonostic programming is not used. Vector length (VL) of 256 bits is mandated in both kernels. Kernels to support other VLs can be added later. "SVE is a vector extension for AArch64 execution mode for the A64 instruction set of the Armv8 architecture. Unlike other SIMD architectures, SVE does not define the size of the vector registers, but constrains into a range of possible values, from a minimum of 128 bits up to a maximum of 2048 in 128-bit wide units. Therefore, any CPU vendor can implement the extension by choosing the vector register size that better suits the workloads the CPU is targeting. Instructions are provided specifically to query an implementation for its register size, to guarantee that the applications can run on different implementations of the ISA without the need to recompile the code." [1] [1] https://developer.arm.com/solutions/hpc/resources/hpc-white-papers/arm-scalable-vector-extensions-and-application-to-machine-learning Signed-off-by: Guodong Xu commit 4d87eb24e8e1f5a21e04586f6df4f427bae0091b Author: Yingbo Ma Date: Mon Apr 27 17:02:47 2020 -0400 Update KernelsHowTo.md (#395) commit 477ce91c5281df2bbfaddc4d86312fb8c8f879e2 Author: Field G. Van Zee Date: Wed Apr 22 14:26:49 2020 -0500 Moved #include "cpuid.h" to bli_cpuid.c. Details: - Relocated the #include "cpuid.h" directive from bli_cpuid.h to bli_cpuid.c. This was done because cpuid.h (which is pulled into the post-build blis.h developer header) doesn't protect its definitions with a preprocessor guard of the form: #ifndef FOOBAR_H #define FOOBAR_H // header contents. #endif and as a result, applications (previously) could not #include both blis.h and cpuid.h (since the former was already including the latter). Thanks to Bhaskar Nallani for raising this issue via #393 and to Devin Matthews for suggesting this fix. - CREDITS file update. commit 8bde63ffd7474a97c3a3b0b0dc1eae45be0ab889 Author: Field G. Van Zee Date: Sat Apr 18 12:50:12 2020 -0500 Adding missing conjy to her2/syr2 in typed API doc. Details: - Fixed a missing argument (conjy) in the function signatures of bli_?her2() and bli_?syr2() in docs/BLISTypedAPI.md. Thanks to Robert van de Geijn for reporting this omission. commit 976902406b610afdbacb2d80a7a2b4b43ff30321 Author: Field G. Van Zee Date: Fri Apr 17 15:11:10 2020 -0500 Disable packing by default in expert rntm_t init. Details: - Changed the behavior of bli_rntm_init() as well as the static initializer, BLIS_RNTM_INITIALIZER, so that user-initialized rntm_t objects by default specify the disabling of packing for A and B. Packing of A/B was already disabled by default when calling non-expert APIs (and enabled only when the user set environment variables BLIS_PACK_A or BLIS_PACK_B). With this commit, the default behavior of using user-initialized rntm_t objects with expert APIs comes into line with the default behavior of non-expert APIs--that is, they now both lead to the avoidance of packing in the sup code path. (Note: The conventional code path is unaffected by the environment variables BLIS_PACK_A/BLIS_PACK_B and/or the disabling of packing in a rntm_t object when calling an expert API.) This addresses issue #392. Thanks to Kiran Varaganti for bringing this inconsistency to our attention. - The above change was accomplished by changing the the definitions of static functions bli_rntm_clear_pack_a() and bli_rntm_clear_pack_b() in bli_rntm.h, which are both for internal use only. commit 5f2aee7c5fa5d562acaf8fbde3df0e2a04e1dd1b Author: Field G. Van Zee Date: Tue Apr 7 14:55:15 2020 -0500 README.md update to promote supmt dgemm. Details: - Updated the sup entry in the "What's New" section of the README.md file to promote the multithreaded dgemm sup feature introduced in c0558fd. commit f5923cd9ff5fbd91190277dea8e52027174a1d57 Author: Field G. Van Zee Date: Tue Apr 7 14:41:45 2020 -0500 CHANGELOG update (0.7.0) commit 68b88aca6692c75a9f686187e6c4a4e196ae60a9 (tag: 0.7.0) Author: Field G. Van Zee Date: Tue Apr 7 14:41:44 2020 -0500 Version file update (0.7.0) commit b04de636c1702e4cb8e7ad82bab3cf43d2dbdfc6 Author: Field G. Van Zee Date: Tue Apr 7 14:37:43 2020 -0500 ReleaseNotes.md update in advance of next version. Details: - Updated docs/ReleaseNotes.md in preparation for next version. commit 2cb604ba472049ad498df72d4a2dc47a161d4c3c Author: Field G. Van Zee Date: Mon Apr 6 16:42:14 2020 -0500 Rename more bli_thread_obarrier(), _obroadcast(). Details: - Renamed instances of bli_thread_obarrier() and bli_thread_obroadcast() that were made in the supmt-specific code commited to the 'amd' branch, which has now been merged with 'master'. Prior to the merge, 'master' received commit c01d249, which applied these renamings to the existing, non-sup codebase. commit efb12bc895de451067649d5dceb059b7827a025f Author: Field G. Van Zee Date: Mon Apr 6 15:01:53 2020 -0500 Minor updates/elaborations to RELEASING file. commit 2e3b3782cfb7a2fd0d1a325844983639756def7d Merge: 9f3a8d4d da0c086f Author: Field G. Van Zee Date: Mon Apr 6 14:55:35 2020 -0500 Merge branch 'master' into amd commit da0c086f4643772e111318f95a712831b0f981a8 Author: Satish Balay Date: Tue Mar 31 17:09:41 2020 -0500 OSX: specify the full path to the location of libblis.dylib (#390) * OSX: specify the full path to the location of libblis.dylib so that it can be found at runtime Before this change: Appication gives runtime error [when linked with blis] dyld: Library not loaded: libblis.3.dylib balay@kpro lib % otool -L libblis.dylib libblis.dylib: libblis.3.dylib (compatibility version 0.0.0, current version 0.0.0) /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1281.0.0) After this change: balay@kpro lib % otool -L libblis.dylib libblis.dylib: /Users/balay/petsc/arch-darwin-c-debug/lib/libblis.3.dylib (compatibility version 0.0.0, current version 0.0.0) /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1281.0.0) * INSTALL_LIBDIR -> libdir as INSTALL_LIBDIR has DESTDIR Co-Authored-By: Jed Brown * CREDITS file update. Co-authored-by: Jed Brown Co-authored-by: Field G. Van Zee commit 2bca03ea9d87c0da829031a5332545d05e352211 Author: Field G. Van Zee Date: Sat Mar 28 22:10:00 2020 +0000 Updates, tweaks to runme.sh in test/1m4m. Details: - Made several updates to test/1m4m/runme.sh, including: - Added missing handling for 1m and 4m1a implementations when setting the BLIS_??_NT environment variables. - Added support for using numactl to run the test executables. - Several other cleanups. commit c40a33190b94af5d5c201be63366594859b1233f Author: Field G. Van Zee Date: Thu Mar 26 16:55:00 2020 -0500 Warn user when auto-detection returns 'generic'. Details: - Added logic to configure that causes the script to output a warning to the user if/when "./configure auto" is run and the underlying hardware feature detection code is unable to identify the hardware. In these cases, the auto-detect code will return 'generic', which is likely not what the user expected, and a flag will be set so that a message is printed at the end of the configure output. (Thankfully, we don't expect this scenario to play out very often.) Thanks to Devin Matthews for suggesting this fix #384. commit 492a736fab5b9c882996ca024b64646877f22a89 Author: Devin Matthews Date: Tue Mar 24 17:28:47 2020 -0500 Fix vectorized version of bli_amaxv (#382) * Fix vectorized version of bli_amaxv To match Netlib, i?amax should return: - the lowest index among equal values - the first NaN if one is encountered * Fix typos. * And another one... * Update ref. amaxv kernel too. * Re-enabled optimized amaxv kernels. Details: - Re-enabled the optimized, intrinsics-based amaxv kernels in the 'zen' kernel set for use in haswell, zen, zen2, knl, and skx subconfigs. These two kernels (for s and d datatypes) were temporarily disabled in e186d71 as part of issue #380. However, the key missing semantic properties that prompted the disabling of these kernels--returning the index of the *first* rather than of the last element with largest absolute value, and returning the index of the first NaN if one is encountered--were added as part of #382 thanks to Devin Matthews. Thus, now that the kernels are working as expected once more, this commit causes these kernels to once again be registered for the affected subconfigs, which effectively reverts all code changes included in e186d71. - Whitespace/formatting updates to new macros in bli_amaxv_zen_int.c. Co-authored-by: Field G. Van Zee commit e186d7141a51f2d7196c580e24e7b7db8f209db9 Author: Field G. Van Zee Date: Sat Mar 21 18:40:36 2020 -0500 Disabled optimized amaxv kernels. Details: - Disabled use of optimized amaxv kernels, which use vector intrinsics for both 's' and 'd' datatypes. We disable these kernels because the current implementations fail to observe a semantic property of the BLAS i?amax_() subroutine, which is to return the index of the *first* element containing the maximum absolute value (that is, the first element if there exist two or more elements that contain the same value). With the optimized kernels disabled, the affected subconfigurations (haswell, zen, zen2, knl, and skx) will use the default reference implementations. Thanks to Mat Cross for reporting this issue via #380. - CREDITS file update. commit 9f3a8d4d851725436b617297231a417aa9ce8c6a Author: Field G. Van Zee Date: Sat Mar 14 17:48:43 2020 -0500 Added missing return to bli_thread_partition_2x2(). Details: - Added a missing return statement to the body of an early case handling branch in bli_thread_partition_2x2(). This bug only affected cases where n_threads < 4, and even then, the code meant to handle cases where n_threads >= 4 executes and does the right thing, albeit using more CPU cycles than needed. Nonetheless, thanks to Kiran Varaganti for reporting this bug via issue #377. - Whitespace changes to bli_thread.c (spaces -> tabs). commit 8c3d9b9eeb6f816ec8c32a944f632a5ad3637593 Merge: 71249fe8 0f9e0399 Author: Field G. Van Zee Date: Tue Mar 10 14:03:33 2020 -0500 Merge branch 'amd' of github.com:flame/blis into amd commit 71249fe8ddaa772616698f1e3814d40e012909ea Author: Field G. Van Zee Date: Tue Mar 10 13:55:29 2020 -0500 Merged test/sup, test/supmt into test/sup. Details: - Updated the Makefile, test_gemm.c, and runme.sh in test/sup to be able to compile and run both single-threaded and multithreaded experiments. This should help with maintenance going forward. - Created a test/sup/octave_st directory of scripts (based on the previous test/sup/octave scripts) as well as a test/sup/octave_mt directory (based on the previous test/supmt/octave scripts). The octave scripts are slightly different and not easily mergeable, and thus for now I'll maintain them separately. - Preserved the previous test/sup directory as test/sup/old/supst and the previous test/supmt directory as test/sup/old/supmt. commit 0f9e0399e16e96da2620faf2c0c3c21274bb2ebd Author: Field G. Van Zee Date: Thu Mar 5 17:03:21 2020 -0600 Updated sup performance graphs; added mt results. Details: - Reran all existing single-threaded performance experiments comparing BLIS sup to other implementations (including the conventional code path within BLIS), using the latest versions (where appropriate). - Added multithreaded results for the three existing hardware types showcased in docs/PerformanceSmall.md: Kaby Lake, Haswell, and Epyc (Zen1). - Various minor updates to the text in docs/PerformanceSmall.md. - Updates to the octave scripts in test/sup/octave, test/supmt/octave. commit 90db88e5729732628c1f3acc96eeefab49f2da41 Author: Field G. Van Zee Date: Mon Mar 2 15:06:48 2020 -0600 Updated sup[mt] Makefiles for variable dim ranges. Details: - Updated test/sup/Makefile and test/supmt/Makefile to allow specifying different problem size ranges for the drivers where one, two, or three matrix dimensions is large. This will facilitate the generation of more meaningful graphs, particularly when two dimensions are tiny. commit 31f11a06ea9501724feec0d2fc5e4644d7dd34fc Author: Field G. Van Zee Date: Thu Feb 27 14:33:20 2020 -0600 Updates to octave scripts in test/sup[mt]/octave. Details: - Optimized scripts in test/sup/octave and test/supmt/octave for use with octave 5.2.0 on Ubuntu 18.04. - Fixed stray 'end' keywords in gen_opsupnames.m and plot_l3sup_perf.m, which were not only unnecessary but also causing issues with versions 5.x. commit c01d249d7c546fe2e3cee3fe071cd4c4c88b9115 Author: Field G. Van Zee Date: Tue Feb 25 14:50:53 2020 -0600 Renamed bli_thread_obarrier(), _obroadcast(). Details: - Renamed two bli_thread_*() APIs: bli_thread_obarrier() -> bli_thread_barrier() bli_thread_obroadcast() -> bli_thread_broadcast() The 'o' was a leftover from when thrcomm_t objects tracked both "inner" and "outer" communicators. They have long since been simplified to only support the latter, and thus the 'o' is superfluous. commit f6e6bf73e695226c8b23fe7900da0e0ef37030c1 Author: Field G. Van Zee Date: Mon Feb 24 17:52:23 2020 -0600 List Gentoo under supported external packages. Details: - Add mention of Gentoo Linux under the list of external packages in the README.md file. Thanks to M. Zhou for maintaining this package. commit 9e5f7296ccf9b3f7b7041fe1df20b927cd0e914b Author: Field G. Van Zee Date: Tue Feb 18 15:16:03 2020 -0600 Skip building thrinfo_t tree when mt is disabled. Details: - Return early from bli_thrinfo_sup_grow() if the thrinfo_t object address is equal to either &BLIS_GEMM_SINGLE_THREADED or &BLIS_PACKM_SINGLE_THREADED. - Added preprocessor logic to bli_l3_sup_thread_decorator() in bli_l3_sup_decor_single.c that (by default) disables code that creates and frees the thrinfo_t tree and instead passes &BLIS_GEMM_SINGLE_THREADED as the thrinfo_t pointer into the sup implementation. - The net effect of the above changes is that a small amount of thrinfo_t overhead is avoided when running small/skinny dgemm problems when BLIS is compiled with multithreading disabled. commit 90081e6a64b5ccea9211bdef193c2d332c68492f Author: Field G. Van Zee Date: Mon Feb 17 14:57:25 2020 -0600 Fixed bug(s) in mt sup when single-threaded. Details: - Fixed a syntax bug in bli_l3_sup_decor_single.c as a result of changing function interface for the thread entry point function (of type l3supint_t). - Unfortunately, fixing the interface was not enough, as it caused a memory leak in the sba at bli_finalize() time. It turns out that, due to the new multithreading-capable variant code useing thrinfo_t objects--specifically, their calling of bli_thrinfo_grow()--we have to pass in a real thrinfo_t object rather than the global objects &BLIS_PACKM_SINGLE_THREADED or &BLIS_GEMM_SINGLE_THREADED. Thus, I inserted the appropriate logic from the OpenMP and pthreads versions so that single-threaded execution would work as intended with the newly upgraded variants. commit c0558fde4511557c8f08867b035ee57dd2669dc6 Author: Field G. Van Zee Date: Mon Feb 17 14:08:08 2020 -0600 Support multithreading within the sup framework. Details: - Added multithreading support to the sup framework (via either OpenMP or pthreads). Both variants 1n and 2m now have the appropriate threading infrastructure, including data partitioning logic, to parallelize computation. This support handles all four combinations of packing on matrices A and B (neither, A only, B only, or both). This implementation tries to be a little smarter when automatic threading is requested (e.g. via BLIS_NUM_THREADS) in that it will recalculate the factorization in units of micropanels (rather than using the raw dimensions) in bli_l3_sup_int.c, when the final problem shape is known and after threads have already been spawned. - Implemented bli_?packm_sup_var2(), which packs to conventional row- or column-stored matrices. (This is used for the rrc and crc storage cases.) Previously, copym was used, but that would no longer suffice because it could not be parallelized. - Minor reorganization of packing-related sup functions. Specifically, bli_packm_sup_init_mem_[ab]() are called from within packm_sup_[ab]() instead of from the variant functions. This has the effect of making the variant functions more readable. - Added additional bli_thrinfo_set_*() static functions to bli_thrinfo.h and inserted usage of these functions within bli_thrinfo_init(), which previously was accessing thrinfo_t fields via the -> operator. - Renamed bli_partition_2x2() to bli_thread_partition_2x2(). - Added an auto_factor field to the rntm_t struct in order to track whether automatic thread factorization was originally requested. - Added new test drivers in test/supmt that perform multithreaded sup tests, as well as appropriate octave/matlab scripts to plot the resulting output files. - Added additional language to docs/Multithreading.md to make it clear that specifying any BLIS_*_NT variable, even if it is set to 1, will be considered manual specification for the purposes of determining whether to auto-factorize via BLIS_NUM_THREADS. - Minor comment updates. commit d7a7679182d72a7eaecef4cd9b9a103ee0a7b42b Author: Field G. Van Zee Date: Fri Feb 7 17:37:03 2020 -0600 Fixed int-to-packbuf_t conversion error (C++ only). Details: - Fixed an error that manifests only when using C++ (specifically, modern versions of g++) to compile drivers in 'test' (and likely most other application code that #includes blis.h. Thanks to Ajay Panyala for reporting this issue (#374). commit d626112b8d5302f9585fb37a8e37849747a2a317 Author: Field G. Van Zee Date: Wed Jan 15 13:27:02 2020 -0600 Removed sorting on LDFLAGS in common.mk (#373). Details: - Removed a line of code in common.mk that passed LDFLAGS through the sort function. The purpose was not to sort the contents, but rather to remove duplicates. However, there is valid syntax in a string of linker flags that, when sorted, yields different/broken behavior. So I've removed the line in common.mk that sorts LDFLAGS. Also, for future use, I've added a new function, rm-dupls, that removes duplicates without sorting. (This function was based on code from a stackoverflow thread that is linked to in the comments for that code.) Thanks to Isuru Fernando for reporting this issue (#373). commit e67deb22aaeab5ed6794364520190936748ef272 Author: Field G. Van Zee Date: Tue Jan 14 16:01:34 2020 -0600 CHANGELOG update (0.6.1) commit 10949f528c5ffc5c3a2cad47fe16a802afb021be (tag: 0.6.1) Author: Field G. Van Zee Date: Tue Jan 14 16:01:33 2020 -0600 Version file update (0.6.1) commit 5db8e710a2baff121cba9c63b61ca254a2ec097a Author: Field G. Van Zee Date: Tue Jan 14 15:59:59 2020 -0600 ReleaseNotes.md update in advance of next version. Details: - Updated ReleaseNotes.md in preparation for next version. commit cde4d9d7a26eb51dcc5a59943361dfb8fda45dea Author: Field G. Van Zee Date: Tue Jan 14 15:19:25 2020 -0600 Removed 'attic/windows' (to prevent confusion). Details: - Finally removed 'attic/windows' and its contents. This directory once contained "proto" Windows support for BLIS, but we've since moved on to (thanks to Isuru Fernando) providing Windows DLL support via AppVeyor's build artifacts. Furthermore, since 'windows' was the only subdirectory within 'attic', the directory path would show up in GitHub's listing at https://github.com/flame/blis, which probably led to someone being confused about how BLIS provides Windows support. I assume (but don't know for sure) that nobody is using these files, so this is admittedly a case of shoot first and ask questions later. commit 7d3407d4681c6449f4bbb8ec681983700ab968f3 Author: Field G. Van Zee Date: Tue Jan 14 15:17:53 2020 -0600 CREDITS file update. commit f391b3e2e7d11a37300d4c8d3f6a584022a599f5 Author: Dave Love Date: Mon Jan 6 20:15:48 2020 +0000 Fix parsing in vpu_count on workstation SKX (#351) * Fix parsing in vpu_count on workstation SKX * Document Skylake-X as Haswell for single FMA * Update vpu_count for Skylake and Cascade Lake models * Support printing the configuration selected, controlled by the environment Intended particularly for diagnosing mis-selection of SKX through unknown, or incorrect, number of VPUs. * Move bli_log outside the cpp condition, and use it where intended * Add Fixme comment (Skylake D) * Mostly superficial edits to commits towards #351. Details: - Moved architecture/sub-config logging-related code from bli_cpuid.c to bli_arch.c, tweaked names, and added more set/get layering. - Tweaked log messages output from bli_cpuid_is_skx() in bli_cpuid.c. - Content, whitespace changes to new bullet in HardwareSupport.md that relates to single-VPU Skylake-Xs. * Fix comment typos Co-authored-by: Field G. Van Zee commit 5ca1a3cfc1c1cc4dd9da6a67aa072ed90f07e867 Author: Field G. Van Zee Date: Mon Jan 6 12:29:12 2020 -0600 Fixed 'configure' breakage introduced in 6433831. Details: - Added a missing 'fi' (endif) keyword to a conditional block added in the configure script in commit 6433831. commit e7431b4a834ef4f165c143f288585ce8e2272a23 Author: Field G. Van Zee Date: Mon Jan 6 12:01:41 2020 -0600 Updated 1m draft article link in README.md. commit 6433831cc3988ad205637ebdebcd6d8f7cfcf148 Author: Jeff Hammond Date: Fri Jan 3 17:52:49 2020 -0800 blacklist ICC 18 for knl/skx due to test failures Signed-off-by: Jeff Hammond commit af3589f1f98781e3a94a8f9cea8d5ea6f155f7d2 Author: Jeff Hammond Date: Fri Jan 3 13:23:24 2020 -0800 blacklist Intel 19+ Signed-off-by: Jeff Hammond commit 60de939debafb233e57fd4e804ef21b6de198caf Author: Jeff Hammond Date: Wed Jan 1 21:30:38 2020 -0800 fix link to docs the comment contains an incorrect link, which is trivially fixed here. @fgvanzee I hope you don't mind that I committed directly to master but this cannot break anything. commit 52711073789b6b84eb99bb0d6883f457ed3fcf80 Author: Field G. Van Zee Date: Mon Dec 16 16:30:26 2019 -0600 Fixed bugs in cblas_sdsdot(), sdsdot_(). Details: - Fixed a bug in sdsdot_sub() that redundantly added the "alpha" scalar, named 'sb'. This value was already being added by the underlying sdsdot_() function. Thus, we no longer add 'sb' within sdsdot_sub(). Thanks to Simon Lukas Märtens for reporting this bug via #367. - Fixed a second bug in order of typecasting intermediate products in sdsdot_(). Previously, the "alpha" scalar was being added after the "outer" typecast to float. However, the operation is supposed to first add the dot product to the (promoted) scalar and THEN downcast the sum to float. Thanks to Devin Matthews for catching this bug. commit fe2560a4b1d8ef8d0a446df6002b1e7decc826e9 Author: Field G. Van Zee Date: Fri Dec 6 17:12:44 2019 -0600 Annoted missing thread-related symbols for export. Details: - Added BLIS_EXPORT_BLIS annotation to function prototypes for bli_thrcomm_bcast() bli_thrcomm_barrier() bli_thread_range_sub() so that these functions are exported to shared libraries by default. This (hopefully) fixes issue #366. Thanks to Kyungmin Lee for reporting this bug. - CREDITS file update. commit 2853825234001af8f175ad47cef5d6ff9b7a5982 Merge: efa61a6c 61b1f0b0 Author: Field G. Van Zee Date: Fri Dec 6 16:06:46 2019 -0600 Merge branch 'master' into amd commit 61b1f0b0602faa978d9912fe58c6c952a33af0ac Author: Nicholai Tukanov Date: Wed Dec 4 14:18:47 2019 -0600 Add prototypes for POWER9 reference kernels (#365) Updates and fixes to power9 subconfig. Details: - Register s,c,z reference gemm and trsm ukernels that assume elements of B have been broadcast. - Added prototypes for level-3 ukernels that assume elements of B have been broadcast. Also added prototype for an spackm function that employs a duplication/broadcast factor of 4. - Register virtual gemmtrsm ukernels that work with broadcasting of B. - Disable right-side hemm, symm, trmm, and trmm3 in bli_family_power9.h. - Thanks to Nicholai Tukanov for providing these updates. commit efa61a6c8b1cfa48781fc2e4799ff32e1b7f8f77 Author: Field G. Van Zee Date: Fri Nov 29 16:17:04 2019 -0600 Added missing bli_l3_sup_thread_decorator() symbol. Details: - Defined dummy versions of bli_l3_sup_thread_decorator() for Openmp and pthreads so that those builds don't fail when performing shared library linking (especially for Windows DLLs via AppVeyor). For now, these dummy implementations of bli_l3_sup_thread_decorator() are merely carbon-copies of the implementation provided for single- threaded execution (ie: the one found in bli_l3_sup_decor_single.c). Thus, an OpenMP or pthreads build will be able to use the gemmsup code (including the new selective packing functionality), as it did before 39fa7136, even though it will not actually employ any multithreaded parallelism. commit 39fa7136f4a4e55ccd9796fb79ad5f121b872ad9 Author: Field G. Van Zee Date: Fri Nov 29 15:27:07 2019 -0600 Added support for selective packing to gemmsup. Details: - Implemented optional packing for A or B (or both) within the sup framework (which currently only supports gemm). The request for packing either matrix A or matrix B can be made via setting environment variables BLIS_PACK_A or BLIS_PACK_B (to any non-zero value; if set, zero means "disable packing"). It can also be made globally at runtime via bli_pack_set_pack_a() and bli_pack_set_pack_b() or with individual rntm_t objects via bli_rntm_set_pack_a() and bli_rntm_set_pack_b() if using the expert interface of either the BLIS typed or object APIs. (If using the BLAS API, environment variables are the only way to communicate the packing request.) - One caveat (for now) with the current implementation of selective packing is that any blocksize extension registered in the _cntx_init function (such as is currently used by haswell and zen subconfigs) will be ignored if the affected matrix is packed. The reason is simply that I didn't get around to implementing the necessary logic to pack a larger edge-case micropanel, though this is entirely possible and should be done in the future. - Spun off the variant-choosing portion of bli_gemmsup_ref() into bli_gemmsup_int(), in bli_l3_sup_int.c. - Added new files, bli_l3_sup_packm_a.c, bli_l3_sup_packm_b.c, along with corresponding headers, in which higher-level packm-related functions are defined for use within the sup framework. The actual packm variant code resides in bli_l3_sup_packm_var.c. - Pass the following new parameters into var1n and var2m: packa, packb bool_t's, pointer to a rntm_t, pointer to a cntl_t (which is for now always NULL), and pointer to a thrinfo_t* (which for nowis the address of the global single-threaded packm thread control node). - Added panel strides ps_a and ps_b to the auxinfo_t structure so that the millikernel can query the panel stride of the packed matrix and step through it accordingly. If the matrix isn't packed, the panel stride of interest for the given millikernel will be set to the appropriate value so that the mkernel may step through the unpacked matrix as it normally would. - Modified the rv_6x8m and rv_6x8n millikernels to read the appropriate panel strides (ps_a and ps_b, respectively) instead of computing them on the fly. - Spun off the environment variable getting and setting functions into a new file, bli_env.c (with a corresponding prototype header). These functions are now used by the threading infrastructure (e.g. BLIS_NUM_THREADS, BLIS_JC_NT, etc.) as well as the selective packing infrastructure (e.g. BLIS_PACK_A, BLIS_PACK_B). - Added a static initializer for mem_t objects, BLIS_MEM_INITIALIZER. - Added a static initializer for pblk_t objects, BLIS_PBLK_INITIALIZER, for use within the definition of BLIS_MEM_INITIALIZER. - Moved the global_rntm object to bli_rntm.c and extern it where needed. This means that the function bli_thread_init_rntm() was renamed to bli_rntm_init_from_global() and relocated accordingly. - Added a new bli_pack.c function, which serves as the home for functions that manage the pack_a and pack_b fields of the global rntm_t, including from environment variables, just as we have functions to manage the threading fields of the global rntm_t in bli_thread.c. - Reorganized naming for files in frame/thread, which mostly involved spinning off the bli_l3_thread_decorator() functions into their own files. This change makes more sense when considering the further addition of bli_l3_sup_thread_decorator() functions (for now limited only to the single-threaded form found in the _single.c file). - Explicitly initialize the reference sup handlers in both bli_cntx_init_haswell.c and bli_cntx_init_zen.c so that it's more obvious how to customize to a different handler, if desired. - Removed various snippets of disabled code. - Various comment updates. commit bbb21fd0a9be8c5644bec37c75f9396eeeb69e48 Author: Field G. Van Zee Date: Thu Nov 21 18:15:16 2019 -0600 Tweaked SIAM/SC Best Prize language in README.md. commit 043366f92d5f5f651d5e3371ac3adb36baf4adce Author: Field G. Van Zee Date: Thu Nov 21 18:13:51 2019 -0600 Fixed typo in previous commit (SIAM/SC prize). commit 05a4d583e65a46ff2a1100ab4433975d905d91f9 Author: Field G. Van Zee Date: Thu Nov 21 18:12:24 2019 -0600 Added SIAM/SC prize to "What's New" in README.md. commit 881b05ecd40c7bc0422d3479a02a28b1cb48383f Author: Field G. Van Zee Date: Thu Nov 21 16:34:27 2019 -0600 Fixed blastest failure for 'generic' subconfig. Details: - Fixed a subtle and complicated bug that only manifested via the BLAS test drivers in the generic subconfiguration, and possibly any other subconfiguration that did not register complex-domain gemm ukernels, or registered ONLY real-domain ukernels as row-preferential. This is a long story, but it boils down to an exception to the "transpose the operation to bring storage of C into agreement with ukernel pref" optimization in bli_hemm_front.c and bli_symm_front.c sabotaging the proper functioning of the 1m method, but only when the imaginary component of beta is zero. See the comments in issue #342 for more details. Thanks to Dave Love for identifying the commit in which this bug was introduced, and other feedback related to this bug. commit 0c7165fb01cdebbc31ec00124d446161b289942f Author: Field G. Van Zee Date: Thu Nov 14 16:48:14 2019 -0600 Fixed obscure bug in bli_acquire_mpart_[mn]dim(). Details: - Fixed a bug in bli_acquire_mpart_mdim(), bli_acquire_mpart_ndim(), and bli_acquire_mpart_mndim() that allowed the use of a blocksize b that is too large given the current row/column index (i.e., the i/j argument) and the size of the dimension being partitioned (i.e., the m/n argument). This bug only affected backwards partitioning/motion through the dimension and was the result of a misplaced conditional check-and-redirect to the backwards code path. It should be noted that this bug was discovered not because it manifested the way it could (thanks to the callers in BLIS making sure to always pass in the "correct" blocksize b), but could have manifested if the functions were used by 3rd party callers. Thanks to Minh Quan Ho for reporting the bug via issue #363. commit fb8bef9982171ee0f60bc39e41a33c4d31fd59a9 Author: Field G. Van Zee Date: Thu Nov 14 13:05:28 2019 -0600 Fixed copy-paste bug in bli_spackm_6xk_bb4_ref(). Details: - Fixed a copy-paste bug in the new bli_spackm_6xk_bb4_ref() that manifested as failures in single-precision real level-3 operations. Also replaced the duplication factor constants with a const-qualifed varialbe, dfac, so that this won't happen again. - Changed NC for single-precision real from 4080 to 8160 so that the packed matrix B will have the same byte footprint in both single and double real. commit 8f399c89403d5824ba767df1426706cf2d19d0a7 Author: Field G. Van Zee Date: Tue Nov 12 15:32:57 2019 -0600 Tweaked/added notes to docs/Multithreading.md. Details: - Added language to docs/Multithreading.md cautioning the reader about the nuances of setting multithreading parameters via the manual and automatic ways simultaneously, and also about how these parameters behave when multithreading is disabled at configure-time. These changes are an attempt to address the issues that arose in issue #362. Thanks to Jérémie du Boisberranger for his feedback on this topic. - CREDITS file update. commit bdc7ee3394500d8e5b626af6ff37c048398bb27e Author: Field G. Van Zee Date: Mon Nov 11 15:47:17 2019 -0600 Various fixes to support packing duplication in B. Details: - Added cpp macros to trmm and trmm3 front-ends to optionally force those operations to be cast so the structured matrix is on the left. symm and hemm already had such macros, but these too were renamed so that the macros were individual to the operation. We now have four such macros: #define BLIS_DISABLE_HEMM_RIGHT #define BLIS_DISABLE_SYMM_RIGHT #define BLIS_DISABLE_TRMM_RIGHT #define BLIS_DISABLE_TRMM3_RIGHT Also, updated the comments in the symm and hemm front-ends related to the first two macro guards, and added corresponding comments to the trmm and trmm3 front-ends for the latter two guards. (They all functionally do the same thing, just for their specific operations.) Thanks to Jeff Hammond for reporting the bugs that led me to this change (via #359). - Updated config/old/haswellbb subconfiguration (used to debug issues related to duplicating B during packing) to register: a packing kernel for single-precision real; gemmbb ukernels for s, c, and z; trsmbb ukernels for s, c, and z; gemmtrsmbb virtual ukrnels for s, c and z; and to use non-default cache and register blocksizes for s, c, and z datatypes. Also declared prototypes for all of the gemmbb, trsmbb, and gemmtrsmbb ukernel functions within the bli_cntx_init_haswellbb() function. This should, once applied to the power9 configuration, fix the remaining issues in #359. - Defined bli_spackm_6xk_bb4_ref(), which packs single reals with a duplication factor of 4. This function is defined in the same file as bli_dpackm_6xk_bb2_ref() (bli_packm_cxk_bb_ref.c). commit 0eb79ca8503bd7b237994335b9687457227d3290 Author: Field G. Van Zee Date: Fri Nov 8 14:48:48 2019 -0600 Avoid unused variable warning in lread.c (#356). Details: - Replaced the line f = f; with ( void )f; for the unused variable 'f' in blastest/f2c/lread.c. (Hopefully) addresses issue #356, but since we don't use xlc who knows. Thanks to Jeff Hammond for reporting this. commit f377bb448512f0b578263387eed7eaf8f2b72bb7 Author: Jérôme Duval Date: Thu Nov 7 23:39:29 2019 +0100 Add Haiku to the known OS list (#361) commit e29b1f9706b6d9ed798b7f6325f275df4e6be973 Author: Field G. Van Zee Date: Tue Nov 5 17:15:19 2019 -0600 Fixed failing testsuite gemmtrsm_ukr for power9. Details: - Added code that fixes false failures in the gemmtrsm_ukr module of the testsuite. The tests were failing because the computation (bli_gemv()) that performs the numerical check was not able to properly travserse the matrix operands bx1 and b11 that are views into the micropanel of B, which has duplicated/broadcast elements under the power9 subconfig. (For example, a micropanel of B with duplication factor of 2 needs to use a column stride of 2; previously, the column stride was being interpreted as 1.) - Defined separate bli_obj_set_row_stride() and bli_obj_set_col_stride() static functions in bli_obj_macro_defs.h. (Previously, only the function bli_obj_set_strides() was defined. Amazing to think that we got this far without these former functions.) - Updated/expounded upon comments. commit 49177a6b9afcccca5b39a21c6fd8e243525e1505 Author: Field G. Van Zee Date: Mon Nov 4 18:09:37 2019 -0600 Fixed latent testsuite ukr module bugs for power9. Details: - Fixed a latent bug in the testsuite ukernel modules (gemm, trsm, and gemmtrsm) that only manifested once we began running with parameters that mimic those of power9. The problem was rooted in the way those modules were creating objects (and thus allocating memory) for the micropanel operands to the microkernel being tested. Since power9 duplicates/broadcasts elements of B in memory, we needed an easy way of asking for more than one storage element per logical element in the matrix. I incorrectly expressed this as: bli_obj_create( datatype, k, n, ldbp, 1, &bp ); The problem here is that bli_obj_create() is exceedingly efficient at calculating the size it passes to malloc() and doesn't allocate a full leading dimension's worth of elements for the last column (or row, in this example). This would normally not bother anyone since you're not supposed to access that memory anyway. But here, my attempted "hack" for getting extra elements was insufficient, and needed to be changed to: bli_obj_create( datatype, k, ldbp, ldbp, 1, &bp ); That is, the extra elements needed to be baked into the dimensions of the matrix object in order to have the intended effect on the number of elements actually allocated. Thanks to Jeff Hammond for reporting this bug. - Fixed a typically harmless memory leak in the aforementioned test modules (the objects for the packed micropanels were not being freed). - Updated/expanded a common comment across all three ukr test modules. commit c84391314d4f1b3f73d868f72105324e649f2a72 Author: Field G. Van Zee Date: Mon Nov 4 13:57:12 2019 -0600 Reverted minor temp/wspace changes from b426f9e. Details: - Added missing license header to bli_pwr9_asm_macros_12x6.h. - Reverted temporary changes to various files in 'test' and 'testsuite' directories. - Moved testsuite/jobscripts into testsuite/old. - Minor whitespace/comment changes across various files. commit 4870260f6b8c06d2cc01b7147d7433ddee213f7f Author: Jeff Hammond Date: Mon Nov 4 11:55:47 2019 -0800 blacklist GCC 5 and older for POWER9 (#360) commit b426f9e04e5499c6f9c752e49c33800bfaadda4c Author: Nicholai Tukanov Date: Fri Nov 1 17:57:03 2019 -0500 POWER9 DGEMM (#355) Implemented and registered power9 dgemm ukernel. Details: - Implemented 12x6 dgemm microkernel for power9. This microkernel assumes that elements of B have been duplicated/broadcast during the packing step. The microkernel uses a column orientation for its microtile vector registers and thus implements column storage and general stride IO cases. (A row storage IO case via in-register transposition may be added at a future date.) It should be noted that we recommend using this microkernel with gcc and *not* xlc, as issues with the latter cropped up during development, including but not limited to slightly incompatible vector register mnemonics in the GNU extended inline assembly clobber list. commit 58102aeaa282dc79554ed045e1b17a6eda292e15 Merge: 52059506 b9bc222b Author: Field G. Van Zee Date: Mon Oct 28 17:58:31 2019 -0500 Merge branch 'amd' commit 52059506b2d5fd4c3738165195abeb356a134bd4 Author: Field G. Van Zee Date: Wed Oct 23 15:26:42 2019 -0500 Added "How to Download BLIS" section to README.md. Details: - Added a new section to the README.md, just prior to the "Getting Started" section, titled "How to Download BLIS". This section details the user's options for obtaining BLIS and lays out four common ways of downloading the library. Thanks to Jeff Diamond for his feedback on this topic. commit e6f0a96cc59aef728470f6850947ba856148c38a Author: Field G. Van Zee Date: Mon Oct 14 17:05:39 2019 -0500 Updated README.md to ack Facebook as funder. commit b9bc222bfc3db4f9ae5d7b3321346eed70c2c3fb Author: Field G. Van Zee Date: Mon Oct 14 16:38:15 2019 -0500 Call bli_syrk_small() before error checking. Details: - In bli_syrk_front(), moved the conditional call to bli_syrk_check() (if error checking is enabled) and the conditional scaling of C by beta (if alpha is zero) so that they occur after, instead of before, the call to bli_syrk_small(). This sequencing now matches that of bli_gemm_small() in bli_gemm_front() and bli_trsm_small() in bli_trsm_front(). commit f0959a81dbcf30d8a1076d0a6348a9835079d31a Author: Field G. Van Zee Date: Mon Oct 14 15:46:28 2019 -0500 When manual config is blacklisted, output error. Details: - Fixed and adjusted the logic in configure so that a more informative error message is output when a user runs './configure ... ' and is present in the configuration blacklist. Previously, this particular set of conditions would result in the message: 'user-specified configuration '' is NOT registered! That is, the error message mis-identified the targeted configuration as the empty string, and (more importantly) mis-identifies the problem. Thanks to Tze Meng Low for reporting this issue. - Fixed a nearby error messages somewhat unrelated to the issue above. Specifically, the wrong string was being printed when the error message was identifying an auto-detected configuration that did not appear to be registered. commit 6218ac95a525eefa8921baf8d0d7057dfacebe9c Merge: 0016d541 a617301f Author: Field G. Van Zee Date: Fri Oct 11 11:53:51 2019 -0500 Merge branch 'master' into amd commit 0016d541e6b0da617b1fae6612d2b314901b7a75 Author: Field G. Van Zee Date: Fri Oct 11 11:09:44 2019 -0500 Changed -march=znver2 to =znver1 for clang on zen2. Details: - In config/zen2/make_defs.mk, changed the -march= flag so that -march=znver1 is used instead of -march=znver2 when CC_VENDOR is clang. (The gcc branch attempts to differentiate between various versions, but the equivalent version cutoffs for clang are not yet known by us, so we have to use a single flag for all versions of clang. Hopefully -march=znver1 is new enough. If not, we'll fall back to -march=bdver4 -mno-fma4 -mno-tbm -mno-xop -mno-lwp.) This issue was discovered thanks to AppVeyor. commit e94a0530e5ac4c78a18f09105f40003be2b517f7 Author: Field G. Van Zee Date: Fri Oct 11 10:48:27 2019 -0500 Corrected zen NC that was non-multiple of NR. Details: - Updated an incorrectly set cache blocksize NC for single real within config/zen/bli_cntx_init_zen.c that was non a multiple of the corresponding value of NR. This issue, which was caught by Travis CI, was introduced in 29b0e1e. commit a2ffac752076bf55eb8c1fe2c5da8d9104f1f85b Merge: 1cfe8e25 29b0e1ef Author: Field G. Van Zee Date: Fri Oct 11 10:31:18 2019 -0500 Merge branch 'amd-master' into amd commit 29b0e1ef4e8b84ce76888d73c090009b361f1306 Merge: 1cfe8e25 fdce1a56 Author: Field G. Van Zee Date: Fri Oct 11 10:24:24 2019 -0500 Code review + tweaks to AMD's AOCL 2.0 PR (#349). Details: - NOTE: This is a merge commit of 'master' of git://github.com/amd/blis into 'amd-master' of flame/blis. - Fixed a bug in the downstream value of BLIS_NUM_ARCHS, which was inadvertantly not incremented when the Zen2 subconfiguration was added. - In bli_gemm_front(), added a missing conditional constraint around the call to bli_gemm_small() that ensures that the computation precision of C matches the storage precision of C. - In bli_syrk_front(), reorganized and relocated the notrans/trans logic that existed around the call to bli_syrk_small() into bli_syrk_small() to minimize the calling code footprint and also to bring that code into stylistic harmony with similar code in bli_gemm_front() and bli_trsm_front(). Also, replaced direct accessing of obj_t fields with proper accessor static functions (e.g. 'a->dim[0]' becomes 'bli_obj_length( a )'). - Added #ifdef BLIS_ENABLE_SMALL_MATRIX guard around prototypes for bli_gemm_small(), bli_syrk_small(), and bli_trsm_small(). This is strictly speaking unnecessary, but it serves as a useful visual cue to those who may be reading the files. - Removed cpp macro-protected small matrix debugging code from bli_trsm_front.c. - Added a GCC_OT_9_1_0 variable to build/config.mk.in to facilitate gcc version check for availability of -march=znver2, and added appropriate support to configure script. - Cleanups to compiler flags common to recent AMD microarchitectures in config/zen/amd_config.mk, including: removal of -march=znver1 et al. from CKVECFLAGS (since the -march flag is added within make_defs.mk); setting CRVECFLAGS similarly to CKVECFLAGS. - Cleanups to config/zen/bli_cntx_init_zen.c. - Cleanups, added comments to config/zen/make_defs.mk. - Cleanups to config/zen2/make_defs.mk, including making use of newly- added GCC_OT_9_1_0 and existing GCC_OT_6_1_0 to choose the correct set of compiler flags based on the version of gcc being used. - Reverted downstream changes to test/test_gemm.c. - Various whitespace/comment changes. commit a617301f9365ac720ff286514105d1b78951368b Author: Field G. Van Zee Date: Tue Oct 8 17:14:05 2019 -0500 Updates to docs/CodingConventions.md. commit 171f10069199f0cd280f18aac184546bd877c4fe Merge: 702486b1 05d58edf Author: Field G. Van Zee Date: Fri Oct 4 11:18:23 2019 -0500 Merge remote-tracking branch 'loveshack/emacs' commit 702486b12560b5c696ba06de9a73fc0d5107ca44 Author: Field G. Van Zee Date: Wed Oct 2 16:35:41 2019 -0500 Removed stray FAQ section introduced in 1907000. commit 1907000ad6ea396970c010f07ae42980b7b14fa0 Author: Field G. Van Zee Date: Wed Oct 2 16:31:54 2019 -0500 Updated to FAQ (AMD-related questions). Details: - Added a couple potential frequently-asked questions/answers releated to AMD's fork of BLIS. - Updated existing answers to other questions. commit 834f30a0dad808931c9d80bd5831b636ed0e1098 Author: Field G. Van Zee Date: Wed Oct 2 12:45:56 2019 -0500 Mention mixeddt paper in docs/MixedDatatypes.md. commit 05d58edfe0ea9279971d74f17a5f7a69c4672ed5 Author: Dave Love Date: Wed Oct 2 10:33:44 2019 +0100 Note .dir-locals.el in docs commit 531110c339f199a4d165d707c988d89ab4f5bfe8 Author: Dave Love Date: Wed Oct 2 10:16:22 2019 +0100 Modify Emacs config Confine it to cc-mode and add comment-start/end. commit 4bab365cab98202259c70feba6ec87408cba28d8 Author: Dave Love Date: Tue Oct 1 19:22:47 2019 +0000 Add .dir-locals.el for Emacs (#348) A minimal version that could probably do with extending, but at least gets the indentation roughly right. commit 4ec8dad66b3d37b0a2b47d19b7144bb62d332622 Author: Dave Love Date: Thu Sep 26 16:27:53 2019 +0100 Add .dir-locals.el for Emacs A minimal version that could probably do with extending, but at least gets the indentation roughly right. commit bc16ec7d1e2a30ce4a751255b70c9cbe87409e4f Author: Field G. Van Zee Date: Mon Sep 23 15:37:33 2019 -0500 Set execute bits of shared library at install-time. Details: - Modified the 0644 octal code used during installation of shared libraries to 0755 (for Linux/OSX only). Thanks to Adam J. Stewart for reporting this issue via #343. - CREDITS file update. commit c60db26aee9e7b4e5d0b031b0881e58d23666b53 Author: Field G. Van Zee Date: Tue Sep 17 18:04:17 2019 -0500 Fixed bad loop counter in bli_[cz]scal2bbs_mxn(). Details: - Fixed a typo in the loop counter for the 'd' (duplication) dimension in the complex macros of frame/include/level0/bb/bli_scal2bbs_mxn.h. They shouldn't be used by anyone yet, but thankfully clang via AppVeyor spit out warnings that alerted me to the issue. commit c766c81d628f0451d8255bf5e4b8be0a4ef91978 Author: Field G. Van Zee Date: Tue Sep 17 18:00:29 2019 -0500 Added missing schema arg to knl packm kernels. Details: - Added the pack_t schema argument to the knl packm kernel functions. This change was intended for inclusion in 31c8657. (Thank you SDE + Travis CI.) commit 31c8657f1d6d8f6efd8a73fd1995e995fc56748b Author: Field G. Van Zee Date: Tue Sep 17 17:42:10 2019 -0500 Added support for pre-broadcast when packing B. Details: - Added support for being able to duplicate (broadcast) elements in memory when packing matrix B (ie: the left-hand operand) in level-3 operations. This turns out advantageous for some architectures that can afford the cost of the extra bandwidth and somehow benefit from the pre-broadcast elements (and thus being able to avoid using broadcast-style load instructions on micro-rows of B in the gemm microkernel). - Support optionally disabling right-side hemm and symm. If this occurs, hemm_r is implemented in terms of hemm_l (and symm_r in terms of symm_l). This is needed when broadcasting during packing because the alternative--supporting the broadcast of B while also allowing matrix B to be Hermitian/symmetric--would be an absolute mess. - Support alignment factors for packed blocks of A, B, and C separately (as well as for general-purpose buffers). In addition, we support byte offsets from those alignment values (which is different from aligning by align+offset bytes to begin with). The default alignment values are BLIS_PAGE_SIZE in all four cases, with the offset values defaulting to zero. - Pass pack_t schema into bli_?packm_cxk() so that it can be then passed into the packm kernel, where it will be needed by packm kernels that perform broadcasts of B, since the idea is that we *only* want to broadcast when packing micropanels of B and not A. - Added definition for variadic bli_cntx_set_l3_vir_ukrs(), which can be used to set custom virtual level-3 microkernels in the cntx_t, which would typically be done in the bli_cntx_init_*() function defined in the subconfiguration of interest. - Added a "broadcast B" kernel function for use with NP/NR = 12/6, defined in in ref_kernels/1m/bli_packm_cxk_bb_ref.c. - Added a gemm, gemmtrsm, and trsm "broadcast B" reference kernels defined in ref_kernels/3/bb. (These kernels have been tested with double real with NP/NR = 12/6.) - Added #ifndef ... #endif guards around several macro constants defined in frame/include/bli_kernel_macro_defs.h. - Defined a few "broadcast B" static functions in frame/include/level0/bb for use by "broadcast B"-style packm reference kernels. For now, only the real domain kernels are tested and fully defined. - Output the alignment and offset values for packed blocks of A and B in the testsuite's "BLIS configuration info" section. - Comment updates to various files. - Bumped so_version to 3.0.0. commit fd9bf497cd4ff73ccdfc030ba037b3cb2f1c2fad Author: Field G. Van Zee Date: Tue Sep 17 15:45:24 2019 -0500 CREDITS file update. commit 6c8f2d1486ce31ad3c2083e5c2035acfd4409a43 Author: ShmuelLevine Date: Tue Sep 17 16:43:46 2019 -0400 Fix description for function bli_*pxby2v (#340) Fix typo in BLISTypedAPI.md for bli_?axpy2v() description. commit b5679c1520f8ae7637b3cc2313133461f62398dc Author: Field G. Van Zee Date: Tue Sep 17 14:00:37 2019 -0500 Inserted Multithreading links into BuildSystem.md. Details: - Inserted brief disclaimers about default disabled multithreading and default single-threadedness to BuildSystem.md along with links to the Multithreading.md document. Thanks to Jeff Diamond for suggesting these additions. - Trivial reword of sentence regarding automatically-detected architectures. commit f4f5170f8482c94132832eb3033bc8796da5420b Author: Isuru Fernando Date: Wed Sep 11 07:34:48 2019 -0500 Update README.md (#338) commit 1cfe8e2562e5e50769468382626ce36b734741c1 Author: Field G. Van Zee Date: Thu Sep 5 16:08:30 2019 -0500 Reimplemented bli_cpuid_query() for ARM. Details: - Rewrote bli_cpuid_query() for ARM architectures to use stdio-based functions such as fopen() and fgets() instead of popen(). The new code does more or less the same thing as before--searches /proc/cpuinfo for various strings, which are then parsed in order to determine the model, part number, and features. Thanks to Dave Love for suggesting this change in issue #335. commit 7c7819145740e96929466a248d6375d40e397e19 Author: Devin Matthews Date: Fri Aug 30 16:52:09 2019 -0500 Always use sqsumv to compute normfv. (#334) * Always use sqsumv to compute normfv on MacOS. * Unconditionally disable the "dot trick" in normfv. * Added explanatory comment to normfv definition. Details: - Added a comment above the unconditional disabling of the dotv-based implementation to normfv. Thanks to Roman Yurchak, Devin Matthews, and Isuru Fernando in helping with this improvement. - CREDITS file update. commit 80e6c10b72d50863b4b64d79f784df7befedfcd1 Author: Field G. Van Zee Date: Thu Aug 29 12:12:08 2019 -0500 Added reproduction section to Performance docs. Details: - Added section titled "Reproduction" to both Performance.md and PerformanceSmall.md that briefly nudges the motivated reader in the right direction if he/she wishes to run the same performance benchmarks used to produce the graphs shown in those documents. Thanks to Dave Love for making this suggestion. commit 14cb426414856024b9ae0f84ac21efcc1d329467 Author: Field G. Van Zee Date: Wed Aug 28 17:04:33 2019 -0500 Updated OpenBLAS, Eigen sup results. Details: - Updated the results shown in docs/PerformanceSmall.md for OpenBLAS and Eigen. commit b02e0aae8ce2705e91023b98ed416cd05430a78e Author: Field G. Van Zee Date: Tue Aug 27 14:37:46 2019 -0500 Updated test drivers to iterate backwards. Details: - Updated test driver source in test, test/3, test/1m4m, and test/mixeddt to iterate through the problem space backwards. This can help avoid certain situations where the CPU frequency does not immediately throttle up to its maximum. Thanks to Robert van de Geijn for recommending this fix (originally made to test/sup drivers in 57e422a). - Applied off-by-one matlab output bugfix from b6017e5 to test drivers in test, test/3, test/1m4m, and test/mixeddt directories. commit b6017e53f4b26c99b14cdaa408351f11322b1e80 Author: Field G. Van Zee Date: Tue Aug 27 14:18:14 2019 -0500 Bugfix of output text + tweaks to test/sup driver. Details: - Fixed an off-by-one bug in the output of matlab row indices in test/sup/test_gemm.c that only manifested when the problem size increment was equal to 1. - Disabled the building of rrc, rcr, rcc, crr, crc, and ccr storage combinations for blissup drivers in test/sup. This helps make the building of drivers complete sooner. - Trivial changes to test/sup/runme.sh. commit 138d403b6bb15e687a3fe26d3d967b8ccd1ed97b Author: Devin Matthews Date: Mon Aug 26 18:11:27 2019 -0500 Use -funsafe-math-optimizations and -ffp-contract=fast for all reference kernels when using gcc or clang. (#331) commit d5a05a15a7fcc38fb2519031dcc62de8ea4a530c Author: Field G. Van Zee Date: Mon Aug 26 16:54:31 2019 -0500 Cropped whitespace from new sup graphs. Details: - Previously forgot crop whitespace from the new .png graphs added/updated in docs/graphs/sup. commit a6c80171a353db709e43f9e6e7a3da87ce4d17ed Author: Field G. Van Zee Date: Mon Aug 26 16:51:31 2019 -0500 Fixed contents links in docs/PerformanceSmall.md. Details: - Corrected links in contents section of docs/PerformanceSmall.md, which were erroneously directing readers to the corresponding sections of docs/Performance.md. commit 40781774df56a912144ef19cc191ed626a89f0de Author: Field G. Van Zee Date: Mon Aug 26 16:47:37 2019 -0500 Updated sup performance graphs with libxsmm. Details: - Added libxsmm to column-stored sup graphs presented in docs/PerformanceSmall.md. - Updated sup results for BLASFEO. - Added sup results for Lonestar5 (Haswell). - Addresses issue #326. commit bfddf671328e7e372ac7228f72ff2d9d8e03ae18 Author: figual Date: Mon Aug 26 12:01:33 2019 +0200 Fixed context registration for Cortex A53 (#329). commit 4a0a6e89c568246d14de4cc30e3ff35aac23d774 Author: Field G. Van Zee Date: Sat Aug 24 15:25:16 2019 -0500 Changed test/sup alpha to 1; test libxsmm+netlib. Details: - Changed the value of alpha to 1.0 in test/sup/test_gemm.c. This is needed because libxsmm currently only optimizes gemm operations where alpha is unit (and beta is unit or zero). - Adjusted the test/sup/Makefile to test libxsmm with netlib BLAS as its fallback library. This is the library that will be called the problem dimensions are deemed too large, or any other criteria for optimization are not met. (This was done not because it is realistic, but rather so that it would be very clear when libxsmm ceased handling gemm calls internally when the data are graphed.) commit 7aa52b57832176c5c13a48e30a282e09ecdabf73 Author: Field G. Van Zee Date: Fri Aug 23 16:12:50 2019 -0500 Use libxsmm API in test/sup; add missing -ldl. Details: - Switch the driver source in test/sup so that libxsmm_?gemm() is called instead of ?gemm_() when compiling for / linking against libxsmm. libxsmm's documentation isn't clear on whether it is even *trying* to provide BLAS API compatibility, and I got tired of trying to figure it out. - Added missing -ldl in LDFLAGS when linking against libxsmm. commit 57e422aa168bee7416965265c93fcd4934cd7041 Author: Field G. Van Zee Date: Fri Aug 23 14:17:52 2019 -0500 Added libxsmm support to test/sup drivers. Details: - Modified test/sup/Makefile to build drivers that test the performance of skinny/small problems via libxsmm. - Modified test/sup/runme.sh to run aforementioned drivers. - Modified test/sup/test_gemm.c so that problem sizes are tested in reverse order (from largest to smallest). This can help avoid certain situations where the CPU frequency does not immediately throttle up to its maximum. Thanks to Robert van de Geijn for recommending this fix. commit 661681fe33978acce370255815c76348f83632bc Merge: 2f387e32 ef0a1a0f Author: Field G. Van Zee Date: Thu Aug 22 14:29:50 2019 -0500 Merge branch 'master' of github.com:flame/blis commit 2f387e32ef5f9a17bafb5076dc9f66c38b52b32d Author: Field G. Van Zee Date: Thu Aug 22 14:27:30 2019 -0500 Added Eigen -march=native hack to perf docs. Details: - Spell out the hack given to me by Sameer Agarwal in order to get Eigen to build with -march=native (which is critically important for Eigen) in docs/Performance.md and docs/PerformanceSmall.md. commit ef0a1a0faf683fe205f85308a54a77ffd68a9a6c Author: Devin Matthews Date: Wed Aug 21 17:40:24 2019 -0500 Update do_sde.sh (#330) * Update do_sde.sh Automatically accept SDE license and download directly from Intel * Update .travis.yml [ci skip] * Update .travis.yml Enable SDE testing for PRs. commit 0cd383d53a8c4a6871892a0395591ef5630d4ac0 Author: Field G. Van Zee Date: Wed Aug 21 13:39:05 2019 -0500 Corrected variable type and comment update. Details: - Forgot to save all changes from bli_gemmtrsm4m1_ref.c before commit in 8122f59. Fixed type mismatch and referenced github issue in comment. commit 8122f59745db780987da6aa1e851e9e76aa985e0 Author: Field G. Van Zee Date: Wed Aug 21 13:22:12 2019 -0500 Pacify 'restrict' warning in gemmtrsm4m1 ref ukr. Details: - Previously, some versions of gcc would complain that the same pointer, one_r, is being passed in for both alpha and beta in the fourth call to the real gemm ukernel in bli_gemmtrsm4m1_ref.c. This is understandable since the compiler knows that the real gemm ukernel qualifies all of its floating-point arguments (including alpha and beta) with restrict. A small hack has been inserted into the file that defines a new variable to store the value 1.0, which is now used in lieu of one_r for beta in the fourth call to the real gemm ukernel, which should pacify the compiler now. Thanks to Dave Love for reporting this issue (#328) and for Devin Matthews for offering his 'restrict' expertise. commit e8c6281f139bdfc9bd68c3b36e5e89059b0ead2e Author: Field G. Van Zee Date: Wed Aug 21 12:38:53 2019 -0500 Add -march support for specific gcc version ranges. Details: - Added logic to configure that checks the version of the compiler against known version ranges that could cause problems later in the build process. For example, versions of gcc older than 4.9.0 use different -march labels than version 4.9.0 or later ('-march=corei7-avx' vs '-march=sandybridge', respectively). Similarly, before 6.1, compilation on Zen was possible, but you need to start with -march=bdver4 and then disable instruction sets that were discarded during the transition from Excavator to Zen. So now, configure substitutes 'yes'/'no' values into anchors in config.mk.in, which sets various make variables (e.g. GCC_OT_4_9_0), which can be accessed and branched upon by the various configurations' make_defs.mk files when setting their compiler flags. - Updated config/haswell/make_defs.mk to branch on GCC_OT_4_9_0. - Updated config/sandybridge/make_defs.mk to branch on GCC_OT_4_9_0. - Updated config/zen/make_defs.mk to branch on GCC_OT_6_1_0. commit e6ac4ebcb6e6a372820e7f509c0af3342966b84a Author: Field G. Van Zee Date: Tue Aug 20 13:49:47 2019 -0500 Added page size, source location to perf docs. Details: - Added the page size, as returned via 'getconf -a | grep PAGE_SIZE', and the location of the performance drivers to docs/Performance.md (test/3) and docs/PerformanceSmall.md (test/sup). Thanks to Dave Love for suggesting these additions in #325. commit fdce1a5648d69034fab39943100289323011c36f Author: Meghana Date: Wed Jul 24 15:04:41 2019 +0530 changed gcc version check condition from 'ifeq' to 'if greater or equal' Change-Id: Ie4c461867829bcc113210791bbefb9517e52c226 commit c9486e0c4f82cd9f58f5ceb71c0df039e9970a20 Author: Meghana Date: Wed Jul 24 09:45:17 2019 +0530 code to detect version of gcc and set flags accordingly for zen2 Change-Id: I29b0311d0000dee1a2533ee29941acf53f9e9f34 commit 54afe3dfe6828a1aff65baabbf14c98d92e50692 Author: Field G. Van Zee Date: Tue Jul 23 16:54:28 2019 -0500 Added "Education and Learning" ToC entry to README. commit 9f53b1ce7ac702e84e71801fe96986f6aa16040e Author: Field G. Van Zee Date: Tue Jul 23 16:50:35 2019 -0500 Added "Education and Learning" section to README. Details: - Added a short section after the Intro of the README.md file titled "Education and Learning" that directs interested readers to the "LAFF-On Programming for High-Performance" massive open online course (MOOC) hosted via edX. commit deda4ca8a094ee18d7c7c45e040e8ef180f33a48 Author: Field G. Van Zee Date: Mon Jul 22 13:59:05 2019 -0500 Added test/1m4m driver directory. Details: - Added a new standalone test driver directory named '1m4m' that can build and run performance experiments for BLIS 1m, 4m1a, assembly, OpenBLAS, and the vendor library (MKL). This new driver directory was used to regenerate performance results for the 1m paper. - Added alternate (commented-out) cache blocksizes to config/haswell/bli_cntx_init_haswell.c. These blocksizes tend to work well on an a 12-core Intel Xeon E5-2650 v3. commit dcc0ce12fde4c6dca2b4764a1922a2ab19725867 Author: Meghana Date: Mon Jul 22 17:12:01 2019 +0530 Added a global Makefile for AMD architectures in config/zen folder This Makefile(amd_config.mk) has all the flags that are common to EPYC series Change-Id: Ic02c60a8293ccdd37f0f292e631acd198e6895de commit af17bca26a8bd3dcbee8ca81c18d7b25de09c483 Author: Field G. Van Zee Date: Fri Jul 19 14:46:23 2019 -0500 Updated haswell MC cache blocksizes. Details: - Updated the default MC cache blocksizes used by the haswell subconfig for both row-preferential (the default) and column-preferential microkernels. commit b5e9bce4dde5bf014dd9771ae741048e1f6c7748 Author: Field G. Van Zee Date: Fri Jul 19 14:42:37 2019 -0500 Updated -march flags for sandybridge, haswell. Details: - Updated the '-march=corei7-avx' flag in the sandybridge subconfig to '-march=sandybridge' and the '-march=core-avx2' flag in the haswell subconfig to '-march=haswell'. The older flags were used by older versions of gcc and should have been updated to the newer forms a long time ago. (The older flags were clearly working, even though they are no longer documented in the gcc man page.) commit c22b9dba5859a9fc94c8431eccc9e4eb9be02be1 Author: Field G. Van Zee Date: Tue Jul 16 13:14:47 2019 -0500 More updates to comments in testsuite modules. Details: - Updated most comments in testsuite modules that describe how the correctness test is performed so that it is clear whether the vector (normfv) or matrix (normfm) form of Frobenius norm is used. commit c4cc6fa702f444a05963db01db51bc7d6669e979 Author: Field G. Van Zee Date: Tue Jul 16 13:00:35 2019 -0500 New cntx_t blksz "set" functions + misc tweaks. Details: - Defined two new static functions in bli_cntx.h: bli_cntx_set_blksz_def_dt() bli_cntx_set_blksz_max_dt() which developers may find convenient when experimenting with different values of cache blocksizes. - Updated one- and two-socket multithreaded problem size range and increment values in test/3/Makefile. - Changed default to column storage in test/3/test_gemm.c. - Fixed typo in comment in testsuite/src/test_subm.c. commit b84cee29f42855dc1f263e42b83b1a46ac8def87 Merge: 1f80858a c7dd6e6c Author: Meghana Vankadari Date: Mon Jul 8 02:03:07 2019 -0400 Merge "Added compiler flags for vanilla clang" into amd-staging-rome2.0 commit 1f80858abf5ca220b2998fbe6f9b06c32d3864c3 Author: kdevraje Date: Fri Jul 5 16:05:11 2019 +0530 This checkin solves the dgemm performance issue jira ticket CPUPL 458, as #else was missed during integration, it was always following else path to get the block sizes Change-Id: I0084b5856c2513ab1066c08c15b5086db6532717 commit c7dd6e6cd2f910cbefcdc1e04a5adeb919a23de0 Author: Meghana Date: Thu Jul 4 09:32:51 2019 +0530 Added compiler flags for vanilla clang Change-Id: I13c00b4c0d65bbda4c929848fd48b0ab611952ab commit 2acd49b76457635625a01e31c2abc8902b23cf51 Author: Meghana Date: Mon Jul 1 15:42:38 2019 +0530 fix for test failures using AOCC 2.0 Change-Id: If44eaccc64bbe96bbbe1d32279b1b5773aba08d1 commit ceee2f973ebe115beca55ca77f9e3ce36b14c28a Author: Field G. Van Zee Date: Mon Jun 24 17:47:40 2019 -0500 Fixed thrinfo_t printing bug for small problems. Details: - Fixed a bug in bli_l3_thrinfo_print_gemm_paths() and bli_l3_thrinfo_print_trsm_paths(), defined in bli_l3_thrinfo.c, whereby subnodes of the thrinfo_t tree are "dereferenced" near the beginning of the functions, which may lead to segfaults in certain situations where the thread tree was not fully formed because the matrix problem was too small for the level of parallelism specified. (That is, too small because some problems were assigned no work due to the smallest units in the m and n dimensions being defined by the register blocksizes mr and nr.) The fix requires several nested levels of if statements, and this is one of those few instances where use of goto statements results in (mostly) prettier code, especially in the case of _gemm_paths(). And while it wasn't necessary, I ported this goto usage to the loop body that prints the thrinfo_t work_id and comm_id values for each thread. Thanks to Nicholai Tukanov for helping to find this bug. commit cac127182dd88ed0394ad81e6b91b897198e168a Merge: 565fa385 3a45ecb1 Author: kdevraje Date: Mon Jun 24 13:01:27 2019 +0530 Merge branch 'amd-staging-rome2.0' of ssh://git.amd.com:29418/cpulibraries/er/blis with public repo commit id 565fa3853b381051ac92cff764625909d105644d. Change-Id: I68b9824b110cf14df248217a24a6191b3df79d42 commit c152109e9a3b1cd74760e8a3215a676d25c18d2e Author: Field G. Van Zee Date: Wed Jun 19 13:23:24 2019 -0500 Updated BLASFEO results in PerformanceSmall.md. Details: - Updated the BLASFEO performance graphs shown in PerformanceSmall.md using a new commit of BLASFEO (2c9f312); updated PerformanceSmall.md accordingly. - Updated test/sup/octave/plot_l3sup_perf.m so that the .m files containing the mpnpkp results do not need to be preprocessed in order to plot half the problem size range (ie: up to 400 instead of the 800 range of the other shape cases). - Trivial updates to runme.m. commit 4d19c98110691d33ecef09d7e1b97bd1ccf4c420 Author: Field G. Van Zee Date: Sat Jun 8 11:02:03 2019 -0500 Trivial change to MixedDatatypes.md link text. commit 24965beabe83e19acf62008366097a7f198d4841 Author: Field G. Van Zee Date: Sat Jun 8 11:00:22 2019 -0500 Fixed typo in README.md's MixedDatatypes.md link. commit 50dc5d95760f41c5117c46f754245edc642b2179 Author: Field G. Van Zee Date: Fri Jun 7 13:10:16 2019 -0500 Adjust -fopenmp-simd for icc's preferred syntax. Details: - Use -qopenmp-simd instead of -fopenmp-simd when compiling with Intel icc. Recall that this option is used for SIMD auto-vectorization in reference kernels only. Support for the -f option has been completely deprecated and removed in newer versions of icc in favor of -q. Thanks to Victor Eijkhout for reporting this issue and suggesting the fix. commit ad937db9507786874c801b41a4992aef42d924a1 Author: Field G. Van Zee Date: Fri Jun 7 11:34:08 2019 -0500 Added missing #include "bli_family_thunderx2.h". Details: - Added a cpp-conditional directive block to bli_arch_config.h that #includes "bli_family_thunderx2.h". The code has been missing since adf5c17f. However, this never manifested as an error because the file is virtually empty and not needed for thunderx2 (or most subconfigs). Thanks to Jeff Diamond for helping to spot this. commit ce671917b2bc24895289247feef46f6fdd5020e7 Author: Field G. Van Zee Date: Thu Jun 6 14:17:21 2019 -0500 Fixed formatting/typo in docs/PerformanceSmall.md. commit 86c33a4eb284e2cf3282a1809be377785cdb3703 Author: Field G. Van Zee Date: Wed Jun 5 11:43:55 2019 -0500 Tweaked language in README.md related to sup/AMD. commit cbaa22e1ca368d36a8510f2b4ecd6f1523d1e1f3 Author: Field G. Van Zee Date: Tue Jun 4 16:06:58 2019 -0500 Added BLASFEO results to docs/PerformanceSmall.md. Details: - Updated the graphs linked in PerformanceSmall.md with BLASFEO results, and added documenting language accordingly. - Updated scripts in test/sup/octave to plot BLASFEO data. - Minor tweak to language re: how OpenBLAS was configured for docs/Performance.md. commit 763fa39c3088c0e2c0155675a3ca868a58bffb30 Author: Field G. Van Zee Date: Tue Jun 4 14:46:45 2019 -0500 Minor tweaks to test/sup. Details: - Changed starting problem and increment from 16 to 4. - Added 'lll' (square problems) to list of problem size shapes to compile and run with. - Define BLASFEO location and added BLASFEO-related definitions. commit 5e1e696003c9151b1879b910a1957b7bdd7b0deb Author: Field G. Van Zee Date: Mon Jun 3 18:37:20 2019 -0500 CHANGELOG update (0.6.0) commit 18c876b989fd0dcaa27becd14e4f16bdac7e89b3 (tag: 0.6.0) Author: Field G. Van Zee Date: Mon Jun 3 18:37:19 2019 -0500 Version file update (0.6.0) commit 0f1b3bf49eb593ca7bb08b68a7209f7cd550f912 Author: Field G. Van Zee Date: Mon Jun 3 18:35:19 2019 -0500 ReleaseNotes.md update in advance of next version. Details: - Updated ReleaseNotes.md in preparation for next version. - CREDITS file update. commit 27da2e8400d900855da0d834b5417d7e83f21de1 Author: Field G. Van Zee Date: Mon Jun 3 17:14:56 2019 -0500 Minor edits to docs/PerformanceSmall.md. Details: - Added performance analysis to "Comments" section of both Kaby Lake and Epyc sections. - Added emphasis to certain passages. commit 09ba05c6f87efbaadf085497dc137845f16ee9c5 Author: Field G. Van Zee Date: Mon Jun 3 16:53:19 2019 -0500 Added sup performance graphs/document to 'docs'. Details: - Added a new markdown document, docs/PerformanceSmall.md, which publishes new performance graphs for Kaby Lake and Epyc showcasing the new BLIS sup (small/skinny/unpacked) framework logic and kernels. For now, only single-threaded dgemm performance is shown. - Reorganized graphs in docs/graphs into docs/graphs/large, with new graphs being placed in docs/graphs/sup. - Updates to scripts in test/sup/octave, mostly to allow decent output in both GNU octave and Matlab. - Updated README.md to mention and refer to the new PerformanceSmall.md document. commit 6bf449cc6941734748034de0e9af22b75f1d6ba1 Merge: abd8a9fa a4e8801d Author: Field G. Van Zee Date: Fri May 31 17:42:40 2019 -0500 Merge branch 'amd' commit a4e8801d08d81fa42ebea6a05a990de8dcedc803 Author: Field G. Van Zee Date: Fri May 31 17:30:51 2019 -0500 Increased MT sup threshold for double to 201. Details: - Fine-tuned the double-precision real MT threshold (which controls whether the sup implementation kicks for smaller m dimension values) from 180 to 201 for haswell and 180 to 256 for zen. - Updated octave scripts in test/sup/octave to include a seventh column to display performance for m = n = k. commit 3a45ecb15456249c30ccccd60e42152f355615c1 Merge: 3f867c96 b69fb0b7 Author: Kiran Devrajegowda Date: Fri May 31 06:47:02 2019 -0400 Merge "Added back BLIS_ENABLE_ZEN_BLOCK_SIZES macro to zen configuration, this is same as release 1.3. This was added before to improve DGEMM Multithreaded scalability on Naples for when number of threads is greater than 16. By mistake this got deleted in many changes done for 2.0 release, now we are adding this change back., in bli_gemm_front.c - code cleanup" into amd-staging-rome2.0 commit b69fb0b74a4756168de270fc9b18f7cf7aa57f17 Author: Kiran Varaganti Date: Fri May 31 15:14:22 2019 +0530 Added back BLIS_ENABLE_ZEN_BLOCK_SIZES macro to zen configuration, this is same as release 1.3. This was added before to improve DGEMM Multithreaded scalability on Naples for when number of threads is greater than 16. By mistake this got deleted in many changes done for 2.0 release, now we are adding this change back., in bli_gemm_front.c - code cleanup Change-Id: I9f5d8225254676a99c6f2b09a0825e545206d0fc commit 3f867c96caea3bbbbeeff1995d90f6cf8c9895fb Author: kdevraje Date: Fri May 31 12:22:44 2019 +0530 When running HPL with pure MPI without DGEMM Threading (Single Threaded BLIS ), making this macro 1 gives best performance.wq Change-Id: I24fd0bf99216f315e49f1c74c44c3feaffd7078d commit abd8a9fa7df4569aa2711964c19888b8e248901f (origin/pfhp) Author: Field G. Van Zee Date: Tue May 28 12:49:44 2019 -0500 Inadvertantly hidden xerbla_() in blastest (#313). Details: - Attempted a fix to issue #313, which reports that when building only a shared library (ie: static library build is disabled), running the BLAS test drivers can fail because those drivers provide their own local version of xerbla_() as a clever (albeit still rather hackish) way of checking the error codes that result from the individual tests. This local xerbla_() function is never found at link-time because the BLAS test drivers' Makefile imports BLIS compilation flags via the get-user-cflags-for() function, which currently conveys the -fvisibility=hidden flag, which hides symbols unless they are explicitly annotated for export. The -fvisibility=hidden flag was only ever intended for use when building BLIS (not for applications), and so the attempted solution here is to omit the symbol export flag(s) from get-user-cflags-for() by storing the symbol export flag(s) to a new BULID_SYMFLAGS variable instead of appending it to the subconfigurations' CMISCFLAGS variable (which is returned by every get-*-cflags-for() function). Thanks to M. Zhou for reporting this issue and also to Isuru Fernando for suggesting the fix. - Renamed BUILD_FLAGS to BUILD_CPPFLAGS to harmonize with the newly created BUILD_SYMFLAGS. - Fixed typo in entry for --export-shared flag in 'configure --help' text. commit 13806ba3b01ca0dd341f4720fb930f97e46710b0 Author: kdevraje Date: Mon May 27 16:24:43 2019 +0530 This check in has changes w.r.t Copyright information, which is changed to (start year) - 2019 Change-Id: Ide3c8f7172210b8d3538d3c36e88634ab1ba9041 commit ee123f535872510f77100d3d55a43d4ca56047d5 Author: Meghana Date: Mon May 27 15:36:44 2019 +0530 Defined small matrix thresholds for TRSM for various cases for NAPLES and ROME Updated copyright information for kernels/zen/bli_trsm_small.c file Removed separate kernels for zen2 architecture Instead added threshold conditions in zen kernels both for ROME and NAPLES Change-Id: Ifd715731741d649b6ad16b123a86dbd6665d97e5 commit 9d93a4caa21402d3a90aac45d7a1603736c9fd63 Author: prangana Date: Fri May 24 17:59:13 2019 +0530 update version 2.0 commit 755730608d923538273a90c48bfdf77571f86519 Author: Field G. Van Zee Date: Thu May 23 17:34:36 2019 -0500 Minor rewording of language around mt env. vars. commit ba31abe73c97c16c78fffc59a215761b8d9fd1f6 Author: Field G. Van Zee Date: Thu May 23 14:59:53 2019 -0500 Added BLIS theading info to Performance.md. Details: - Documented the BLIS environment variables that were set (e.g. BLIS_JC_NT, BLIS_IC_NT, BLIS_JR_NT) for each machine and threading configuration in order to achieve the parallelism reported on in docs/Performance.md. commit cb788ffc89cac03b44803620412a5e83450ca949 Author: Field G. Van Zee Date: Thu May 23 13:00:53 2019 -0500 Increased MT sup threshold for double to 180. Details: - Increased the double-precision real MT threshold (which controls whether the sup implementation kicks for smaller m dimension values) from 80 to 180, and this change was made for both haswell and zen subconfigurations. This is less about the m dimension in particular and more about facilitating a smoother performance transition when m = n = k. commit 057f5f3d211e7513f457ee6ca6c9555d00ad1e57 Author: Field G. Van Zee Date: Thu May 23 12:51:17 2019 -0500 Minor build system housekeeping. Details: - Commented out redundant setting of LIBBLIS_LINK within all driver- level Makefiles. This variable is already set within common.mk, and so the only time it should be overridden is if the user wants to link to a different copy of libblis. - Very minor changes to build/gen-make-frags/gen-make-frag.sh. - Whitespace and inconsequential quoting change to configure. - Moved top-level 'windows' directory into a new 'attic' directory. commit e05171118c377f356f89c4daf8a0d5ddc5a4e4f7 Author: Meghana Date: Thu May 23 16:15:27 2019 +0530 Implemented TRSM for small matrices for cases where A is on the right Added separate kernels for zen and zen2 Change-Id: I6318ddc250cf82516c1aa4732718a35eae0c9134 commit 02920f5c480c42706b487e37b5ecc96c3555b851 Author: kdevraje Date: Thu May 23 15:29:59 2019 +0530 make checkblis fails for matrix dimension check at the begining hence reverting it Change-Id: Ibd2ee8c2d4914598b72003fbfc5845be9c9c1e87 commit 84215022f29fb3bfedd254d041635308d177e6c0 Author: kdevraje Date: Thu May 23 11:08:41 2019 +0530 Adding threshold condition to dgemm small matrix kernels, defining the constants in zen2 configuration Change-Id: I53a58b5d734925a6fcb8d8bea5a02ddb8971fcd5 commit a3554eb1dcc1b5b94d81c60761b2f01c3d827ffa Merge: ea082f83 17b878b6 Author: kdevraje Date: Thu May 23 11:51:07 2019 +0530 Merge branch 'amd-staging-rome2.0' of ssh://git.amd.com:29418/cpulibraries/er/blis to configure zen2 Change-Id: I97e17bca9716b80b862925f97bb513c07b4b0cae commit ea082f839071dd9ec555062dc3851c31d12f00e4 Author: kdevraje Date: Thu May 23 10:38:29 2019 +0530 adding empty zen2 directory with .gitignore file Change-Id: Ifa37cf54b2578aa19ad335372b44bca17043fe4b commit b80bd5bcb2be8551a9a21fafc8e6c8b6336c99b5 Author: Kiran Varaganti Date: Tue May 21 15:11:47 2019 +0530 config/zen/bli_cntx_init_zen.c: removed BLIS_ENBLE_ZEN_BLOCK_SIZES macro. We have different configurations for both zen and zen2 config/zen/bli_family_zen.h: deleted macro BLIS_ENBLE_ZEN_BLOCK_SIZES config/zen/make_defs.mk: removed compiler flag -mno-avx256-split-unaligned-store frame/base/bli_cpuid.c: ROME family is 17H but model # is from 0x30H. test/test_gemm.c - commented out #define FILE_IN_OUT (some compilation error when BLIS is configured as amd64) Now we can use single configuration has ./configure amd64 - this will work both for ROME & Naples Change-Id: I91b4fc35380f8a35b4f4c345da040c6b5910b4a2 commit a042db011df9a1c3e7c7ac546541f4746b176ea5 Author: Kiran Varaganti Date: Mon May 20 14:17:32 2019 +0530 Modified make_defs.mk for zen2 to get compiled by gcc version less than gcc9.0 Change-Id: I8fcac30538ee39534c296932639053b47b9a2d43 commit a23f92594cf3d530e5794307fe97afc877d853b7 Author: Kiran Varaganti Date: Mon May 20 10:48:06 2019 +0530 config_registry: New AMD zen2 architecture configuration added. frame/base/bli_arch.c: #ifdef BLIS_FAMILY_ZEN2 id = BLIS_ARCH_ZEN2; #endif added. zen2 is added in config_name[BLIS_NUM_ARCHS] frame/base/bli_cpuid.c : #ifdef BLIS_CONFIG_ZEN2 if ( bli_cpuid_is_zen2( family, model, features ) ) return BLIS_ARCH_ZEN2; #endif, defined new function bool bli_cpuid_is_zen2(...). frame/base/bli_cpuid.h : declared bli_cpuid_is_zen2(..). frame/base/bli_gks.c : #ifdef BLIS_CONFIG_ZEN2 bli_gks_register_cntx(BLIS_ARCH_ZEN2, bli_cntx_init_zen2, bli_cntx_init_zen2_ref, bli_cntx_init_zen2_ind); #endif frame/include/bli_arch_config.h : #ifdef BLIS_CONFIG_ZEN2 CNTX_INIT_PROTS(zen2) #endif #ifdef BLIS_FAMILY_ZEN2 #include "bli_family_zen2.h" #endif frame/include/bli_type_defs.h : added BLIS_ARCH_ZEN2 in arch_t enum. BLIS_NUM_ARCHS 20 Change-Id: I2a2d9b7266673e78a4f8543b1bfb5425b0aa7866 commit 17b878b66d917d50b6fe23721d8579e826cb3e8c Author: kdevraje Date: Wed May 22 14:02:53 2019 +0530 adding license same as in ut-austin-amd-branch Change-Id: I6790768d2bf5d42369d304ef93e34701f95fbaff commit df755848b8a271323e007c7a628c64af63deab00 Merge: ca4b33c0 c72ae27a Author: kdevraje Date: Wed May 22 13:30:07 2019 +0530 Merge branch 'amd-staging-rome2.0' of ssh://git.amd.com:29418/cpulibraries/er/blis into rome2.0 Change-Id: Ie8aad1ab810f0f3c0b90ec67f9dd3dfb8dcc74cc commit c72ae27adee4726679ee004d02c972582b5285b4 Author: Nisanth M P Date: Mon Mar 19 12:49:26 2018 +0530 Re-enabling the small matrix gemm optimization for target zen Change-Id: I13872784586984634d728cd99a00f71c3f904395 commit ab0818af80f7f683080873f3fa24734b65267df2 Author: sraut Date: Wed Oct 3 15:30:33 2018 +0530 Review comments incorporated for small TRSM. Change-Id: Ia64b7b2c0375cc501c2cb0be8a1af93111808cd9 commit 32392cfc72af7f42da817a129748349fb1951346 Author: Jeff Hammond Date: Tue May 14 15:52:30 2019 -0400 add info about CXX in configure (#311) commit fa7e6b182b8365465ade178b0e4cd344ff6f6460 Author: Field G. Van Zee Date: Wed May 1 19:13:00 2019 -0500 Define _POSIX_C_SOURCE in bli_system.h. Details: - Added #ifndef _POSIX_C_SOURCE #define _POSIX_C_SOURCE 200809L #endif to bli_system.h so that an application that uses BLIS (specifically, an application that #includes blis.h) does not need to remember to #define the macro itself (either on the command line or in the code that includes blis.h) in order to activate things like the pthreads. Thanks to Christos Psarras for reporting this issue and suggesting this fix. - Commented out #include in bli_system.h, since I don't think this header is used/needed anymore. - Comment update to function macro for bli_?normiv_unb_var1() in frame/util/bli_util_unb_var1.c. commit 3df84f1b5d5e1146bb01bfc466ac20c60a9cc859 Author: Field G. Van Zee Date: Sat Apr 27 21:27:32 2019 -0500 Minor bugfixes in sup dgemm implementation. Details: - Fixed an obscure but in the bli_dgemmsup_rv_haswell_asm_5x8n() kernel that only affected the beta == 0, column-storage output case. Thanks to the BLAS test drivers for catching this bug. - Previously, bli_gemmsup_ref_var1n() and _var2m() were returning if k = 0, when the correct action would be to scale by beta (and then return). Thanks to the BLAS test drivers to catching this bug. - Changed the sup threshold behavior such that the sup implementation only kicks in if a matrix dimension is strictly less than (rather than less than or equal to) the threshold in question. - Initialize all thresholds to zero (instead of 10) by default in ref_kernels/bli_cntx_ref.c. This, combined with the above change to threshold testing means that calls to BLIS or BLAS with one or more matrix dimensions of zero will no longer trigger the sup implementation. - Added disabled debugging output to frame/3/bli_l3_sup.c (for future use, perhaps). commit ecbdd1c42dcebfecd729fe351e6bb0076aba7d81 Author: Field G. Van Zee Date: Sat Apr 27 19:38:11 2019 -0500 Ceased use of BLIS_ENABLE_SUP_MR/NR_EXT macros. Details: - Removed already limited use of the BLIS_ENABLE_SUP_MR_EXT and BLIS_ENABLE_SUP_NR_EXT macros in bli_gemmsup_ref_var1n() and bli_gemmsup_ref_var2m(). Their purpose was merely to avoid a long conditional that would determine whether to allow the last iteration to be merged with the second-to-last iteration. Functionally, the macros were not needed, and they ended up causing problems when building configuration families such as intel64 and x86_64. commit aa8a6bec3036a41e1bff2034f8ef6766a704ec49 Author: Field G. Van Zee Date: Sat Apr 27 18:53:33 2019 -0500 Fixed typo in --disable-sup-handling macro guard. Details: - Fixed an incorrectly-named macro guard that is intended to allow disabling of the sup framework via the configure option --disable-sup-handling. In this case, the preprocessor macro, BLIS_DISABLE_SUP_HANDLING, was still named by its name from an older uncommitted version of the code (BLIS_DISABLE_SM_HANDLING). commit b9c9f03502c78a63cfcc21654b06e9089e2a3822 Author: Field G. Van Zee Date: Sat Apr 27 18:44:50 2019 -0500 Implemented gemm on skinny/unpacked matrices. Details: - Implemented a new sub-framework within BLIS to support the management of code and kernels that specifically target matrix problems for which at least one dimension is deemed to be small, which can result in long and skinny matrix operands that are ill-suited for the conventional level-3 implementations in BLIS. The new framework tackles the problem in two ways. First the stripped-down algorithmic loops forgo the packing that is famously performed in the classic code path. That is, the computation is performed by a new family of kernels tailored specifically for operating on the source matrices as-is (unpacked). Second, these new kernels will typically (and in the case of haswell and zen, do in fact) include separate assembly sub-kernels for handling of edge cases, which helps smooth performance when performing problems whose m and n dimension are not naturally multiples of the register blocksizes. In a reference to the sub-framework's purpose of supporting skinny/unpacked level-3 operations, the "sup" operation suffix (e.g. gemmsup) is typically used to denote a separate namespace for related code and kernels. NOTE: Since the sup framework does not perform any packing, it targets row- and column-stored matrices A, B, and C. For now, if any matrix has non-unit strides in both dimensions, the problem is computed by the conventional implementation. - Implemented the default sup handler as a front-end to two variants. bli_gemmsup_ref_var2() provides a block-panel variant (in which the 2nd loop around the microkernel iterates over n and the 1st loop iterates over m), while bli_gemmsup_ref_var1() provides a panel-block variant (2nd loop over m and 1st loop over n). However, these variants are not used by default and provided for reference only. Instead, the default sup handler calls _var2m() and _var1n(), which are similar to _var2() and _var1(), respectively, except that they defer to the sup kernel itself to iterate over the m and n dimension, respectively. In other words, these variants rely not on microkernels, but on so-called "millikernels" that iterate along m and k, or n and k. The benefit of using millikernels is a reduction of function call and related (local integer typecast) overhead as well as the ability for the kernel to know which micropanel (A or B) will change during the next iteration of the 1st loop, which allows it to focus its prefetching on that micropanel. (In _var2m()'s millikernel, the upanel of A changes while the same upanel of B is reused. In _var1n()'s, the upanel of B changes while the upanel of A is reused.) - Added a new configure option, --[en|dis]able-sup-handling, which is enabled by default. However, the default thresholds at which the default sup handler is activated are set to zero for each of the m, n, and k dimensions, which effectively disables the implementation. (The default sup handler only accepts the problem if at least one dimension is smaller than or equal to its corresponding threshold. If all dimensions are larger than their thresholds, the problem is rejected by the sup front-end and control is passed back to the conventional implementation, which proceeds normally.) - Added support to the cntx_t structure to track new fields related to the sup framework, most notably: - sup thresholds: the thresholds at which the sup handler is called. - sup handlers: the address of the function to call to implement the level-3 skinny/unpacked matrix implementation. - sup blocksizes: the register and cache blocksizes used by the sup implementation (which may be the same or different from those used by the conventional packm-based approach). - sup kernels: the kernels that the handler will use in implementing the sup functionality. - sup kernel prefs: the IO preference of the sup kernels, which may differ from the preferences of the conventional gemm microkernels' IO preferences. - Added a bool_t to the rntm_t structure that indicates whether sup handling should be enabled/disabled. This allows per-call control of whether the sup implementation is used, which is useful for test drivers that wish to switch between the conventional and sup codes without having to link to different copies of BLIS. The corresponding accessor functions for this new bool_t are defined in bli_rntm.h. - Implemented several row-preferential gemmsup kernels in a new directory, kernels/haswell/3/sup. These kernels include two general implementation types--'rd' and 'rv'--for the 6x8 base shape, with two specialized millikernels that embed the 1st loop within the kernel itself. - Added ref_kernels/3/bli_gemmsup_ref.c, which provides reference gemmsup microkernels. NOTE: These microkernels, unlike the current crop of conventional (pack-based) microkernels, do not use constant loop bounds. Additionally, their inner loop iterates over the k dimension. - Defined new typedef enums: - stor3_t: captures the effective storage combination of the level-3 problem. Valid values are BLIS_RRR, BLIS_RRC, BLIS_RCR, etc. A special value of BLIS_XXX is used to denote an arbitrary combination which, in practice, means that at least one of the operands is stored according to general stride. - threshid_t: captures each of the three dimension thresholds. - Changed bli_adjust_strides() in bli_obj.c so that bli_obj_create() can be passed "-1, -1" as a lazy request for row storage. (Note that "0, 0" is still accepted as a lazy request for column storage.) - Added support for various instructions to bli_x86_asm_macros.h, including imul, vhaddps/pd, and other instructions related to integer vectors. - Disabled the older small matrix handling code inserted by AMD in bli_gemm_front.c, since the sup framework introduced in this commit is intended to provide a more generalized solution. - Added test/sup directory, which contains standalone performance test drivers, a Makefile, a runme.sh script, and an 'octave' directory containing scripts compatible with GNU Octave. (They also may work with matlab, but if not, they are probably close to working.) - Reinterpret the storage combination string (sc_str) in the various level-3 testsuite modules (e.g. src/test_gemm.c) so that the order of each matrix storage char is "cab" rather than "abc". - Comment updates in level-3 BLAS API wrappers in frame/compat. commit 0d549ceda822833bec192bbf80633599620c15d9 Author: Isuru Fernando Date: Sat Apr 27 22:56:02 2019 +0000 make unix friendly archives on appveyor (#310) commit ca4b33c001f9e959c43b95a9a23f9df5adec7adf Author: Kiran Varaganti Date: Wed Apr 24 15:02:39 2019 +0530 Added compiler option (-mno-avx256-split-unaligned-store) in the file config/zen/make_defs.mk to improve performance of intrinsic codes, this flag ensures compiler generates 256-bit stores for the equivalent intrinsics code. Change-Id: I8f8cd81a3604869df18d38bc42097a04f178d324 commit 945928c650051c04d6900c7f4e9e29cd0e5b299f Merge: 663f6629 74e513eb Author: Field G. Van Zee Date: Wed Apr 17 15:58:56 2019 -0500 Merge branch 'amd' of github.com:flame/blis into amd commit 74e513eb6a6787a925d43cd1500277d54d86ab8f Author: Field G. Van Zee Date: Wed Apr 17 13:34:44 2019 -0500 Support row storage in Eigen gemm test/3 driver. Details: - Added preprocessor branches to test/3/test_gemm.c to explicitly support row-stored matrices. Column-stored matrices are also still supported (and is the default for now). (This is mainly residual work leftover from initial integration of Eigen into the test drivers, so if we ever want to test Eigen with row-stored matrices, the code will be ready to use, even if it is not yet integrated into the Makefile in test/3.) commit b5d457fae9bd75c4ca67f7bc7214e527aa248127 Author: Field G. Van Zee Date: Tue Apr 16 12:50:01 2019 -0500 Applied forgotten variable rename from 89a70cc. Details: - Somehow the variable name change (root_file_name -> root_inputname) in flatten-headers.py mentioned in the commit log entry for 89a70cc didn't make it into the actual commit. This commit applies that change. commit 89a70cccf869333147eb2559cdfa5a23dc915824 Author: Field G. Van Zee Date: Thu Apr 11 18:33:08 2019 -0500 GNU-like handling of installation prefix et al. Details: - Changed the default installation prefix from $HOME/lib to /usr/local. - Modified the way configure internally handles the prefix, libdir, includedir, and sharedir (and also added an --exec-prefix option). The defaults to these variables are set as follows: prefix: /usr/local exec_prefix: ${prefix} libdir: ${exec_prefix}/lib includedir: ${prefix}/include sharedir: ${prefix}/share The key change, aside from the addition of exec_prefix and its use to define the default to libdir, is that the variables are substituted into config.mk with quoting that delays evaluation, meaning the substituted values may contain unevaluated references to other variables (namely, ${prefix} and ${exec_prefix}). This more closely follows GNU conventions, including those used by GNU autoconf, and also allows make to override any one of the variables *after* configure has already been run (e.g. during 'make install'). - Updates to build/config.mk.in pursuant to above changes. - Updates to output of 'configure --help' pursuant to above changes. - Updated docs/BuildSystem.md to reflect the new default installation prefix, as well as mention EXECPREFIX and SHAREDIR. - Changed the definitions of the UNINSTALL_OLD_* variables in the top-level Makefile to use $(wildcard ...) instead of 'find'. This was motivated by the new way of handling prefix and friends, which leads to the 'find' command being run on /usr/local (by default), which can take a while almost never yielding any benefit (since the user will very rarely use the uninstall-old targets). - Removed periods from the end of descriptive output statements (i.e., non-verbose output) since those statements often end with file or directory paths, which get confusing to read when puctuated by a period. - Trival change to 'make showconfig' output. - Removed my name from 'configure --help'. (Many have contributed to it over the years.) - In configure script, changed the default state of threading_model variable from 'no' to 'off' to match that of debug_type, where there are similarly more than two valid states. ('no' is still accepted if given via the --enable-debug= option, though it will be standardized to 'off' prior to config.mk being written out.) - Minor variable name change in flatten-headers.py that was intended for 32812ff. - CREDITS file update. commit 9d76688ad90014a11ddc0c2f27253d62806216b1 Author: kdevraje Date: Thu Apr 11 10:22:48 2019 +0530 Fix for single rank crash with HPL application. When computing offset of C buffer, as integer variables are used for a row and column index, the intermediate result value overflows and a negative value gets added to the buffer, when the negative value is too large it would index the buffer out of the range resulting in segmentation fault. Although the crash is a result of dgemm kernel, added similar code in sgemm kernel also. Change-Id: I171119b0ec0dfbd8e63f1fcd6609a94384aabd27 commit 32812ff5aba05d34c421fe1024a61f3e2d5e7052 Author: Field G. Van Zee Date: Tue Apr 9 12:20:19 2019 -0500 Minor bugfix to flatten-headers.py. Details: - Fixed a minor bug in flatten-headers.py whereby the script, upon encountering a #include directive for the root header file, would erroneously recurse and inline the conents of that root header. The script has been modified to avoid recursion into any headers that share the same name as the root-level header that was passed into the script. (Note: this bug didn't actually manifest in BLIS, so it's merely a precaution for usage of flatten-headers.py in other contexts.) commit bec90e0b6aeb3c9b19589c2b700fda2d66f6ccdf Author: Field G. Van Zee Date: Tue Apr 2 17:45:13 2019 -0500 Minor update to docs/HardwareSupport.md document. Details: - Added more details and clarifying language to implications of 1m and the recycling of microkernels between microarchitectures. commit 89cd650e7be01b59aefaa85885a3ea78970351e4 Author: Field G. Van Zee Date: Tue Apr 2 17:23:55 2019 -0500 Use void_fp for function pointers instead of void*. Change void*-typed function pointers to void_fp. - Updated all instances of void* variables that store function pointers to variables of a new type, void_fp. Originally, I wanted to define the type of void_fp as "void (*void_fp)( void )"--that is, a pointer to a function with no return value and no arguments. However, once I did this, I realized that gcc complains with incompatible pointer type (-Wincompatible-pointer-types) warnings every time any such a pointer is being assigned to its final, type-accurate function pointer type. That is, gcc will silently typecast a void* to another defined function pointer type (e.g. dscalv_ker_ft) during an assignment from the former to the latter, but the same statement will trigger a warning when typecasting from a void_fp type. I suspect an explicit typecast is needed in order to avoid the warning, which I'm not willing to insert at this time. - Added a typedef to bli_type_defs.h defining void_fp as void*, along with a commented-out version of the aborted definition described above. (Note that POSIX requires that void* and function pointers be interchangeable; it is the C standard that does not provide this guarantee.) - Comment updates to various _oapi.c files. commit ffce3d632b284eb52474036096815ec38ca8dd5f Author: Field G. Van Zee Date: Tue Apr 2 14:40:50 2019 -0500 Renamed armv8a gemm kernel filename. Details: - Renamed kernels/armv8a/3/bli_gemm_armv8a_opt_4x4.c to kernels/armv8a/3/bli_gemm_armv8a_asm_d6x8.c. This follows the naming convention used by other kernel sets, most notably haswell. commit 77867478af02144544b4e7b6df5d54d874f3f93b Author: Isuru Fernando Date: Tue Apr 2 13:33:11 2019 -0500 Use pthreads on MinGW and Cygwin (#307) commit 7bc75882f02ce3470a357950878492e87e688cec Author: Field G. Van Zee Date: Thu Mar 28 17:40:50 2019 -0500 Updated Eigen results in docs/graphs with 3.3.90. Details: - Updated the level-3 performance graphs in docs/graphs with new Eigen results, this time using a development version cloned from their git mirror on March 27, 2019 (version 3.3.90). Performance is improved over 3.3.7, though still noticeably short of BLIS/MKL in most cases. - Very minor updates to docs/Performance.md and matlab scripts in test/3/matlab. commit 20ea7a1217d3833db89a96158c42da2d6e968ed8 Author: Field G. Van Zee Date: Wed Mar 27 18:09:17 2019 -0500 Minor text updates (Eigen) to docs/Performance.md. Details: - Added/updated a few more details, mostly regarding Eigen. commit bfb7e1bc6af468e4ff22f7e27151ea400dcd318a Merge: 044df950 2c85e1dd Author: Field G. Van Zee Date: Wed Mar 27 17:58:19 2019 -0500 Merge branch 'dev' commit 2c85e1dd9d5d84da7228ea4ae6deec56a89b3a8f Author: Field G. Van Zee Date: Wed Mar 27 16:29:51 2019 -0500 Added Eigen results to performance graphs. Details: - Updated the Haswell, SkylakeX, and Epyc performance graphs in docs/graphs to report on Eigen implementations, where applicable. Specifically, Eigen implements all level-3 operations sequentially, however, of those operations it only provides multithreaded gemm. Thus, mt results for symm/hemm, syrk/herk, trmm, and trsm are omitted. Thanks to Sameer Agarwal for his help configuring and using Eigen. - Updated docs/Performance.md to note the new implementation tested. - CREDITS file update. commit bfac7e385f8061f2e6591de208b0acf852f04580 Author: Field G. Van Zee Date: Wed Mar 27 16:04:48 2019 -0500 Added ability to plot with Eigen in test/3/matlab. Details: - Updated matlab scripts in test/3/matlab to optionally plot/display Eigen performance curves. Whether Eigen is plotted is determined by a new boolean function parameter, with_eigen. - Updated runme.m scratchpad to reflect the latest invocations of the plot_panel_4x5() function (with Eigen plotting enabled). commit 67535317b9411c90de7fa4cb5b0fdb8f61fdcd79 Author: Field G. Van Zee Date: Wed Mar 27 13:32:18 2019 -0500 Fixed mislabeled eigen output from test/3 drivers. Details: - Fixed the Makefile in test/3 so that it no longer incorrectly labels the matlab output variables from Eigen-linked hemm, herk, trmm, and trsm driver output as "vendor". (The gemm drivers were already correctly outputing matlab variables containing the "eigen" label.) commit 044df9506f823643c0cdd53e81ad3c27a9f9d4ff Author: Isuru Fernando Date: Wed Mar 27 12:39:31 2019 -0500 Test with shared on windows (#306) Export macros can't support both shared and static at the same time. When blis is built with both shared and static, headers assume that shared is used at link time and dllimports the symbols with __imp_ prefix. To use the headers with static libraries a user can give -DBLIS_EXPORT= to import the symbol without the __imp_ prefix commit 5e6b160c8a85e5e23bab0f64958a8acf4918a4ed Author: Field G. Van Zee Date: Tue Mar 26 19:10:59 2019 -0500 Link to Eigen BLAS for non-gemm drivers in test/3. Details: - Adjusted test/3/Makefile so that the test drivers are linked against Eigen's BLAS library for hemm, herk, trmm, and trsm. We have to do this since Eigen's headers don't define implementations to the standard BLAS APIs. - Simplified #included headers in hemm, herk, trmm, and trsm source driver files, since nothing specific to Eigen is needed at compile-time for those operations. commit e593221383aae19dfdc3f30539de80ed05cfec7f Merge: 92fb9c87 c208b9dc Author: Field G. Van Zee Date: Tue Mar 26 15:51:45 2019 -0500 Merge branch 'master' into dev commit 92fb9c87bf88b9f9c401eeecd9aa9c3521bc2adb Author: Field G. Van Zee Date: Tue Mar 26 15:43:23 2019 -0500 Add more support for Eigen to drivers in test/3. Details: - Use compile-time implementations of Eigen in test_gemm.c via new EIGEN cpp macro, defined on command line. (Linking to Eigen's BLAS library is not necessary.) However, as of Eigen 3.3.7, Eigen only parallelizes the gemm operation and not hemm, herk, trmm, trsm, or any other level-3 operation. - Fixed a bug in trmm and trsm drivers whereby the wrong function (bli_does_trans()) was being called to determine whether the object for matrix A should be created for a left- or right-side case. This was corrected by changing the function to bli_is_left(), as is done in the hemm driver. - Added support for running Eigen test drivers from runme.sh. commit c208b9dc46852c877197d53b6dd913a046b6ebb6 Author: Isuru Fernando Date: Mon Mar 25 13:03:44 2019 -0500 Fix clang version detection (#305) clang -dumpversion gives 4.2.1 for all clang versions as clang was originally compatible with gcc 4.2.1 Apple clang version and clang version are two different things and the real clang version cannot be deduced from apple clang version programatically. Rely on wikipedia to map apple clang to clang version Also fixes assembly detection with clang clang 3.8 can't build knl as it doesn't recognize zmm0 commit 53842c7e7d530cb2d5609d6d124ae350fc345c32 Author: Kiran Varaganti Date: Fri Mar 22 13:57:14 2019 +0530 Removed printing alpha and beta values Change-Id: I49102db510311a30f6a936f9d843f35838f50d23 commit 6805db45e343d83d1adaf9157cf0b841653e9ede Author: Kiran Varaganti Date: Fri Mar 22 12:55:35 2019 +0530 Corrected setting alpha & beta values- alpha = -1 and beta = 1 - bli_setc(-1.0, 0, &alpha) should be used rather than bli_setc(0.0, -1.0, &alpha). This corrected now Change-Id: Ic1102dfd6b50ccf212386a1211c6f31e8d987ef9 commit feefcab4427a75b0b55af215486b85abcda314f7 Author: Field G. Van Zee Date: Thu Mar 21 18:11:20 2019 -0500 Allow disabling of BLAS prototypes at compile-time. Details: - Modified bli_blas.h so that: - By default, if the BLAS layer is enabled at configure-time, BLAS prototypes are also enabled within blis.h; - But if the user #defines BLIS_DISABLE_BLAS_DEFS prior to including blis.h, BLAS prototypes are skipped over entirely so that, for example, the application or some other header pulled in by the application may prototype the BLAS functions without causing any duplication. - Updated docs/BuildSystem.md to document the feature above, and related text. commit 20153cd4b594bc34f860c381ec18de3a6cc743c7 Author: Kiran Varaganti Date: Thu Mar 21 16:23:53 2019 +0530 Modified test_gemm.c file in test folder A Macro 'FILE_IN_OUT" is defined to read input parameters from a csv file. Format for input file: Each line defines a gemm problem with following parameters: m k n cs_a cs_b cs_c The operation always implemented is C = C - A*B and column-major format. When macro is disabled - it reverts back to original implementation. Usage: ./test_gemm_.x input.csv output.csv GEMM is called through BLAS interface For BLIS - the test application also prints either 'S' indicating small gemm routine or 'N' - conventional BLIS gemm for MKL/OpenBLAS - ignore this character Change-Id: I0924ef2c1f7bdea48d4cdb230b888e2af2c86a36 commit 288843b06d91e1b4fade337959aef773090bd1c9 Author: Field G. Van Zee Date: Wed Mar 20 17:52:23 2019 -0500 Added Eigen support to test/3 Makefile, runme.sh. Details: - Added targets to test/3/Makefile that link against a BLAS library build by Eigen. It appears, however, that Eigen's BLAS library does not support multithreading. (It may be that multithreading is only available when using the native C++ APIs.) - Updated runme.sh with a few Eigen-related tweaks. - Minor tweaks to docs/Performance.md. commit 153e0be21d9ff413e370511b68d553dd02abada9 Author: Field G. Van Zee Date: Tue Mar 19 17:53:18 2019 -0500 More minor tweaks to docs/Performance.md. Details: - Defined GFLOPS as billions of floating-point operations per second, and reworded the sentence after about normalization. commit 05c4e42642cc0c8dbfa94a6c21e975ac30c0517a Author: Field G. Van Zee Date: Tue Mar 19 17:07:20 2019 -0500 CHANGELOG update (0.5.2) commit 9204cd0cb0cc27790b8b5a2deb0233acd9edeb9b (tag: 0.5.2) Author: Field G. Van Zee Date: Tue Mar 19 17:07:18 2019 -0500 Version file update (0.5.2) commit 64560cd9248ebf4c02c4a1eeef958e1ca434e510 Author: Field G. Van Zee Date: Tue Mar 19 17:04:20 2019 -0500 ReleaseNotes.md update in advance of next version. Details: - Updated ReleaseNotes.md in preparation for next version. commit ab5ad557ea69479d487c9a3cb516f43fa1089863 Author: Field G. Van Zee Date: Tue Mar 19 16:50:41 2019 -0500 Very minor tweaks to Performance.md. commit 03c4a25e1aa8a6c21abbb789baa599ac419c3641 Author: Field G. Van Zee Date: Tue Mar 19 16:47:15 2019 -0500 Minor fixes to docs/Performance.md. Details: - Fixed some incorrect labels associated with the pdf/png graphs, apparently the result of copy-pasting. commit fe6dd8b132f39ecb8893d54cd8e75d4bbf6dab83 Author: Field G. Van Zee Date: Tue Mar 19 16:30:23 2019 -0500 Fixed broken section links in docs/Performance.md. Details: - Fixed a few broken section links in the Contents section. commit 913cf97653f5f9a40aa89a5b79e2b0a8882dd509 Author: Field G. Van Zee Date: Tue Mar 19 16:15:24 2019 -0500 Added docs/Performance.md and docs/graphs subdir. Details: - Added a new markdown document, docs/Performance.md, which reports performance of a representative set of level-3 operations across a variety of hardware architectures, comparing BLIS to OpenBLAS and a vendor library (MKL on Intel/AMD, ARMPL on ARM). Performance graphs, in pdf and png formats, reside in docs/graphs. - Updated README.md to link to new Performance.md document. - Minor updates to CREDITS, docs/Multithreading.md. - Minor updates to matlab scripts in test/3/matlab. commit 9945ef24fd758396b698b19bb4e23e53b9d95725 Author: Field G. Van Zee Date: Tue Mar 19 15:28:44 2019 -0500 Adjusted cache blocksizes for zen subconfig. Details: - Adjusted the zen sub-configuration's cache blocksizes for float, scomplex, and dcomplex based on the existing values for double. (The previous values were taken directly from the haswell subconfig, which targets Intel Haswell/Broadwell/Skylake systems.) commit d202d008d51251609d08d3c278bb6f4ca9caf8e4 Author: Field G. Van Zee Date: Mon Mar 18 18:18:25 2019 -0500 Renamed --enable-export-all to --export-shared=[]. Details: - Replaced the existing --enable-export-all / --disable-export-all configure option with --export-shared=[public|all], with the 'public' instance of the latter corresponding to --disable-export-all and the 'all' instance corresponding to --enable-export-all. Nothing else semantically about the option, or its default, has changed. commit ff78089870f714663026a7136e696603b5259560 Author: Field G. Van Zee Date: Mon Mar 18 13:22:55 2019 -0500 Updates to docs/Multithreading.md. Details: - Made extra explicit the fact that: (a) multithreading in BLIS is disabled by default; and (b) even with multithreading enabled, the user must specify multithreading at runtime in order to observe parallelism. Thanks to M. Zhou for suggesting these clarifications in #292. - Also made explicit that only the environment variable and global runtime API methods are available when using the BLAS API. If the user wishes to use the local runtime API (specify multithreading on a per-call basis), one of the native BLIS APIs must be used. commit 3a929a3d0ba0353159a6d4cd188f01b7a390ccfc Author: Kiran Varaganti Date: Mon Mar 18 10:51:41 2019 +0530 Fixed code merging: bli_gemm_small.c - missed conditional checks for L!=0 && K!=0. Now they are added. This fix is done to pass blastest Change-Id: Idc9c9a04d2015a68a19553c437ecaf8f1584026c commit 663f662932c3f182fefc3c77daa1bf8c3394bb8b Merge: 938c05ef 6bfe3812 Author: Field G. Van Zee Date: Sat Mar 16 16:17:12 2019 -0500 Merge branch 'amd' of github.com:flame/blis into amd commit 938c05ef8654e2fc013d39a57f51d91d40cc40fb Merge: 4ed39c09 5a5f494e Author: Field G. Van Zee Date: Sat Mar 16 16:01:43 2019 -0500 Merge branch 'amd' of github.com:flame/blis into amd commit 6bfe3812e29b86c95b828822e4e5473b48891167 Author: Field G. Van Zee Date: Fri Mar 15 13:57:49 2019 -0500 Use -fvisibility=[...] with clang on Linux/BSD/OSX. Details: - Modified common.mk to use the -fvisibility=[hidden|default] option when compiling with clang on non-Windows platforms (Linux, BSD, OS X, etc.). Thanks to Isuru Fernando for pointing out this option works with clang on these OSes. commit 809395649c5bbf48778ede4c03c1df705dd49566 Author: Field G. Van Zee Date: Wed Mar 13 18:21:35 2019 -0500 Annotated additional symbols for export. Details: - Added export annotations to additional function prototypes in order to accommodate the testsuite. - Disabled calling bli_amaxv_check() from within the testsuite's test_amaxv.c. commit e095926c643fd9c9c2220ebecd749caae0f71d42 Author: Field G. Van Zee Date: Wed Mar 13 17:35:18 2019 -0500 Support shared lib export of only public symbols. Details: - Introduced a new configure option, --enable-export-all, which will cause all shared library symbols to be exported by default, or, alternatively, --disable-export-all, which will cause all symbols to be hidden by default, with only those symbols that are annotated for visibility, via BLIS_EXPORT_BLIS (and BLIS_EXPORT_BLAS for BLAS symbols), to be exported. The default for this configure option is --disable-export-all. Thanks to Isuru Fernando for consulting on this commit. - Removed BLIS_EXPORT_BLIS annotations from frame/1m/bli_l1m_unb_var1.h, which was intended for 5a5f494. - Relocated BLIS_EXPORT-related cpp logic from bli_config.h.in to frame/include/bli_config_macro_defs.h. - Provided appropriate logic within common.mk to implement variable symbol visibility for gcc, clang, and icc (to the extend that each of these compilers allow). - Relocated --help text associated with debug option (-d) to configure slightly further down in the list. commit 5a5f494e428372c7c27ed1f14802e15a83221e87 Author: Field G. Van Zee Date: Tue Mar 12 18:45:09 2019 -0500 Removed export macros from all internal prototypes. Details: - After merging PR #303, at Isuru's request, I removed the use of BLIS_EXPORT_BLIS from all function prototypes *except* those that we potentially wish to be exported in shared/dynamic libraries. In other words, I removed the use of BLIS_EXPORT_BLIS from all prototypes of functions that can be considered private or for internal use only. This is likely the last big modification along the path towards implementing the functionality spelled out in issue #248. Thanks again to Isuru Fernando for his initial efforts of sprinkling the export macros throughout BLIS, which made removing them where necessary relatively painless. Also, I'd like to thank Tony Kelman, Nathaniel Smith, Ian Henriksen, Marat Dukhan, and Matthew Brett for participating in the initial discussion in issue #37 that was later summarized and restated in issue #248. - CREDITS file update. commit 3dc18920b6226026406f1d2a8b2c2b405a2649d5 Merge: b938c16b 766769ee Author: Field G. Van Zee Date: Tue Mar 12 11:20:25 2019 -0500 Merge branch 'master' into dev commit 766769eeb944bd28641a6f72c49a734da20da755 Author: Isuru Fernando Date: Mon Mar 11 19:05:32 2019 -0500 Export functions without def file (#303) * Revert "restore bli_extern_defs exporting for now" This reverts commit 09fb07c350b2acee17645e8e9e1b8d829c73dca8. * Remove symbols not intended to be public * No need of def file anymore * Fix whitespace * No need of configure option * Remove export macro from definitions * Remove blas export macro from definitions commit 4ed39c0971c7917e2675cf5449f563b1f4751ccc Merge: 540ec1b4 b938c16b Author: Field G. Van Zee Date: Fri Mar 8 11:56:58 2019 -0600 Merge branch 'amd' of github.com:flame/blis into amd commit b938c16b0c9e839335ac2c14944b82890143d02f Author: Field G. Van Zee Date: Thu Mar 7 16:40:39 2019 -0600 Renamed test/3m4m to test/3. Details: - Renamed '3m4m' directory to '3', which captures the directory nicely since it builds test drivers to test level-3 operations. - These test drivers ceased to be used to test the 3m and 4m (or even 1m) induced methods long ago, hence the name change. commit ab89a40582ec7acf802e59b0763bed099a02edd8 Author: Field G. Van Zee Date: Thu Mar 7 16:26:12 2019 -0600 More minor updates and edits to test/3m4m. Details: - Further updates to matlab scripts, mostly for compatibility with GNU Octave. - More tweaks to runme.sh. - Updates to runme.m that allow copy-paste into matlab interactive session to generate graphs. commit f0e70dfbf3fee4c4e382c2c4e87c25454cbc79a1 Author: Field G. Van Zee Date: Thu Mar 7 01:04:05 2019 +0000 Very minor updates to test/3m4m for ul252. Details: - Very minor updates to the newly revamped test/3m4m drivers when used on a Xeon Platinum (SkylakeX). commit 7fe44748383071f1cbbc77d904f4ae5538e13065 Author: Kiran Varaganti Date: Wed Mar 6 16:23:31 2019 +0530 Disabled BLIS_ENABLE_ZEN_BLOCK_SIZES in bli_family_zen.h for ROME tuning Change-Id: Iec47fcf51f4d4396afef1ce3958e58cf02c59a57 commit 9f1dbe572b1fd5e7dd30d5649bdf59259ad770d5 Author: Field G. Van Zee Date: Tue Mar 5 17:47:55 2019 -0600 Overhauled test/3m4m Makefile and scripts. Details: - Rewrote much of Makefile to generate executables for single- and dual- socket multithreading as well as single-threaded. Each of the three can also use a different problem size range/increment, as is often appropriate when doubling/halving the number of threads. - Rewrote runme.sh script to flexibly execute as many threading parameter scenarios as is given in the input parameter string (currently set within the script itself). The string also encodes the maximum problem size for each threading scenario, which is used to identify the executable to run. Also improved the "progress" output of the script to reduce redundant info and improve readability in terminals that are not especially wide. - Minor updates to test_*.c source files. - Updated matlab scripts according to changes made to the Makefile, test drivers, and runme.sh script, and renamed 'plot_all.m' to 'runme.m'. commit f5ed95ecd7d5eb4a63e1333ad5cc6765fc8df9fe Author: Kiran Varaganti Date: Tue Mar 5 15:01:57 2019 +0530 Merged BLIS Release 1.3 Modified config/zen/make_defs.mk, now CKVECFLAGS := -mavx2 -mfpmath=sse -mfma -march=znver1 Change-Id: Ia0942d285a21447cd0c470de1bc021fe63e80d81 commit 3bdab823fa93342895bf45d812439324a37db77c Merge: 70f12f20 e2a02ebd Author: Field G. Van Zee Date: Thu Feb 28 14:07:24 2019 -0600 Merge branch 'master' into dev commit e2a02ebd005503c63138d48a2b7d18978ee29205 Author: Field G. Van Zee Date: Thu Feb 28 13:58:59 2019 -0600 Updates (from ls5) to test/3m4m/runme.sh. Details: - Lonestar5-specific updates to runme.sh. commit f0dcc8944fa379d53770f5cae5d670140918f00c Author: Isuru Fernando Date: Wed Feb 27 17:27:23 2019 -0600 Add symbol export macro for all functions (#302) * initial export of blis functions * Regenerate def file for master * restore bli_extern_defs exporting for now commit 540ec1b479712d5e1da637a718927249c15d867f Author: Field G. Van Zee Date: Sun Feb 24 19:09:10 2019 -0600 Updated level-3 BLAS to call object API directly. Details: - Updated the BLAS compatibility layer for level-3 operations so that the corresponding BLIS object API is called directly rather than first calling the typed BLIS API. The previous code based on the typed BLIS API calls is still available in a deactivated cpp macro branch, which may be re-activated by #defining BLIS_BLAS3_CALLS_TAPI. (This does not yet correspond to a configure option. If it seems like people might want to toggle this behavior more regularly, a configure option can be added in the future.) - Updated the BLIS typed API to statically "pre-initialize" objects via new initializor macros. Initialization is then finished via calls to static functions bli_obj_init_finish_1x1() and bli_obj_init_finish(), which are similar to the previously-called functions, bli_obj_create_1x1_with_attached_buffer() and bli_obj_create_with_attached_buffer(), respectively. (The BLAS compatibility layer updates mentioned above employ this new technique as well.) - Transformed certain routines in bli_param_map.c--specifically, the ones that convert netlib-style parameters to BLIS equivalents--into static functions, now in bli_param_map.h. (The remaining three classes of conversation routines were left unchanged.) - Added the aforementioned pre-initializor macros to bli_type_defs.h. - Relocated bli_obj_init_const() and bli_obj_init_constdata() from bli_obj_macro_defs.h to bli_type_defs.h. - Added a few macros to bli_param_macro_defs.h for testing domains for real/complexness and precisions for single/double-ness. commit 8e023bc914e9b4ac1f13614feb360b105fbe44d2 Author: Field G. Van Zee Date: Fri Feb 22 16:55:30 2019 -0600 Updates to 3m4m/matlab scripts. Details: - Minor updates to matlab graph-generating scripts. - Added a plot_all.m script that is more of a scratchpad for copying and pasting function invocations into matlab to generate plots that are presently of interest to us. commit b06244d98cc468346eb1a8eb931bc05f35ff280c Merge: e938ff08 4c7e6680 Author: praveeng Date: Thu Feb 21 12:56:15 2019 +0530 Merge branch 'ut-austin-amd' of ssh://git.amd.com:29418/cpulibraries/er/blis into ut-austin-amd commit e938ff08cea3d108c84524eb129d9e89d701ea90 Author: praveeng Date: Thu Feb 21 12:44:38 2019 +0530 deleted test.txt Change-Id: I3871f5fe76e548bc29ec2733745b29964e829dd3 commit ed13ad465dcba350ad3d5e16c9cc7542e33f3760 Author: mkv Date: Thu Feb 21 01:04:16 2019 -0500 added test file for initial commit commit 4c7e6680832b497468cf50c2399e3ac4de0e3450 Author: praveeng Date: Thu Feb 21 12:44:38 2019 +0530 deleted test.txt Change-Id: I3871f5fe76e548bc29ec2733745b29964e829dd3 commit 95e070581c54ed2edc211874faec56055ea298c8 Author: mkv Date: Thu Feb 21 01:04:16 2019 -0500 added test file for initial commit commit 70f12f209bc1901b5205902503707134cf2991a0 Author: Field G. Van Zee Date: Wed Feb 20 16:10:10 2019 -0600 Changed unsafe-loop to unsafe-math optimizations. Details: - Changed -funsafe-loop-optimizations (re-)introduced in 7690855 for make_defs.mk files' CRVECFLAGS to -funsafe-math-optimizations (to account for a miscommunication in issue #300). Thanks to Dave Love for this suggestion and Jeff Hammond for his feedback on the topic. commit 7690855c5106a56e5b341a350f8db1c78caacd89 Author: Field G. Van Zee Date: Mon Feb 18 19:16:01 2019 -0600 Restored -funsafe-loop-optimizations to subconfigs. Details: - Restored use of -funsafe-loop-optimizations in the definitions of CRVECFLAGS (when using gcc), but only for sub-configurations (and not configuration families such as amd64, intel64, and x86_64). This more or less reverts 5190d05 and 6cf1550. commit 44994d1490897b08cde52a615a2e37ddae8b2061 Author: Field G. Van Zee Date: Mon Feb 18 18:35:30 2019 -0600 Disable TBM, XOP, LWP instructions in AMD configs. Details: - Added -mno-tbm -mno-xop -mno-lwp to CKVECFLAGS in bulldozer, piledriver, steamroller, and excavator configurations to explicitly disable AMD's bulldozer-era TBM, XOP, and LWP instruction sets in an attempt to fix the invalid instruction error that has plagued Travis CI builds since 6a014a3. Thanks to Devin Matthews for pointing out that the offending instruction was part of TBM (issue #300). - Restored -O3 to piledriver configuration's COPTFLAGS. commit 1e5b530744c1906140d47f43c5cad235eaa619cf Author: Field G. Van Zee Date: Mon Feb 18 18:04:38 2019 -0600 Reverted piledriver COPTFLAGS from -O3 to -O2. Details: - Debugging continues; changing COPTFLAGS for piledriver subconfig from -O3 to -O2, its original value prior to 6a014a3. commit 6cf155049168652c512aefdd16d74e7ff39b98df Author: Field G. Van Zee Date: Mon Feb 18 17:29:51 2019 -0600 Removed -funsafe-loop-optimizations from all configs. Details: - Error persists. Removed -funsafe-loop-optimizations from all remaining sub-configurations. commit 5190d05a27c5fa4c7942e20094f76eb9a9785c3e Author: Field G. Van Zee Date: Mon Feb 18 17:07:35 2019 -0600 Removed -funsafe-loop-optimizations from piledriver. Details: - Error persists; continuing debugging from bf0fb78c by removing -funsafe-loop-optimizations from piledriver configuration. commit bf0fb78c5e575372060d22f5ceeb5b332e8978ec Author: Field G. Van Zee Date: Mon Feb 18 16:51:38 2019 -0600 Removed -funsafe-loop-optimizations from families. Details: - Removed -funsafe-loop-optimizations from the configuration families affected by 6a014a3, specifically: intel64, amd64, and x86_64. This is part of an attempt to debug why the sde, as executed by Travis CI, is crashing via the following error: TID 0 SDE-ERROR: Executed instruction not valid for specified chip (ICELAKE): 0x9172a5: bextr_xop rax, rcx, 0x103 commit 6a014a3377a2e829dbc294b814ca257a2bfcb763 Author: Field G. Van Zee Date: Mon Feb 18 14:52:29 2019 -0600 Standardized optimization flags in make_defs.mk. Details: - Per Dave Love's recommendation in issue #300, this commit defines COPTFLAGS := -03 and CRVECFLAGS := $(CKVECFLAGS) -funsafe-loop-optimizations in the make_defs.mk for all Intel- and AMD-based configurations. commit 565fa3853b381051ac92cff764625909d105644d Author: Field G. Van Zee Date: Mon Feb 18 11:43:58 2019 -0600 Redirect trsm pc, ir parallelism to ic, jr loops. Details: - trsm parallelization was temporarily simplifed in 075143d to entirely ignore any parallelism specified via the pc or ir loops. Now, any parallelism specified to the pc loop will be redirected to the ic loop, and any parallelism specified to the ir loop will be redirected to the jr loop. (Note that because of inter-iteration dependencies, trsm cannot parallelize the ir loop. Parallelism via the pc loop is at least somewhat feasible in theory, but it would require tracking dependencies between blocks--something for which BLIS currently lacks the necessary supporting infrastructure.) commit a023c643f25222593f4c98c2166212561d030621 Author: Field G. Van Zee Date: Thu Feb 14 20:18:55 2019 -0600 Regenerated symbols in build/libblis-symbols.def. Details: - Reran ./build/regen-symbols.sh after running 'configure --enable-cblas auto' commit 075143dfd92194647da9022c1a58511b20fc11f3 Author: Field G. Van Zee Date: Thu Feb 14 18:52:45 2019 -0600 Added support for IC loop parallelism to trsm. Details: - Parallelism within the IC loop (3rd loop around the microkernel) is now supported within the trsm operation. This is done via a new branch on each of the control and thread trees, which guide execution of a new trsm-only subproblem from within bli_trsm_blk_var1(). This trsm subproblem corresponds to the macrokernel computation on only the block of A that contains the diagonal (labeled as A11 in algorithms with FLAME-like partitioning), and the corresponding row panel of C. During the trsm subproblem, all threads within the JC communicator participate and parallelize along the JR loop, including any parallelism that was specified for the IC loop. (IR loop parallelism is not supported for trsm due to inter-iteration dependencies.) After this trsm subproblem is complete, a barrier synchronizes all participating threads and then they proceed to apply the prescribed BLIS_IC_NT (or equivalent) ways of parallelism (and any BLIS_JR_NT parallelism specified within) to the remaining gemm subproblem (the rank-k update that is performed using the newly updated row-panel of B). Thus, trsm now supports JC, IC, and JR loop parallelism. - Modified bli_trsm_l_cntl_create() to create the new "prenode" branch of the trsm_l cntl_t tree. The trsm_r tree was left unchanged, for now, since it is not currently used. (All trsm problems are cast in terms of left-side trsm.) - Updated bli_cntl_free_w_thrinfo() to be able to free the newly shaped trsm cntl_t trees. Fixed a potentially latent bug whereby a cntl_t subnode is only recursed upon if there existed a corresponding thrinfo_t node, which may not always exist (for problems too small to employ full parallelization due to the minimum granularity imposed by micropanels). - Updated other functions in frame/base/bli_cntl.c, such as bli_cntl_copy() and bli_cntl_mark_family(), to recurse on sub-prenodes if they exist. - Updated bli_thrinfo_free() to recurse into sub-nodes and prenodes when they exist, and added support for growing a prenode branch to bli_thrinfo_grow() via a corresponding set of help functions named with the _prenode() suffix. - Added a bszid_t field thrinfo_t nodes. This field comes in handy when debugging the allocation/release of thrinfo_t nodes, as it helps trace the "identity" of each nodes as it is created/destroyed. - Renamed bli_l3_thrinfo_print_paths() -> bli_l3_thrinfo_print_gemm_paths() and created a separate bli_l3_thrinfo_print_trsm_paths() function to print out the newly reconfigured thrinfo_t trees for the trsm operation. - Trival changes to bli_gemm_blk_var?.c and bli_trsm_blk_var?.c regarding variable declarations. - Removed subpart_t enum values BLIS_SUBPART1T, BLIS_SUBPART1B, BLIS_SUBPART1L, BLIS_SUBPART1R. Then added support for two new labels (semantically speaking): BLIS_SUBPART1A and BLIS_SUBPART1B, which represent the subpartition ahead of and behind, respectively, BLIS_SUBPART1. Updated check functions in bli_check.c accordingly. - Shuffled layering/APIs for bli_acquire_mpart_[mn]dim() and bli_acquire_mpart_t2b/b2t(), _l2r/r2l(). - Deprecated old functions in frame/3/bli_l3_thrinfo.c. commit 78bc0bc8b6b528c79b11f81ea19250a1db7450ed Author: Nicholai Tukanov Date: Thu Feb 14 13:29:02 2019 -0600 Power9 sub-configuration (#298) Formally registered power9 sub-configuration. Details: - Added and registered power9 sub-configuration into the build system. Thanks to Nicholai Tukanov and Devangi Parikh for these contributions. - Note: The sub-configuration does not yet have a corresponding architecture-specific kernel set registered, and so for now the sub-config is using the generic kernel set. commit 6b832731261f9e7ad003a9ea4682e9ca973ef844 Author: Field G. Van Zee Date: Tue Feb 12 16:01:28 2019 -0600 Generalized ref kernels' pragma omp simd usage. Details: - Replaced direct usage of _Pragma( "omp simd" ) in reference kernels with PRAGMA_SIMD, which is defined as a function of the compiler being used in a new bli_pragma_macro_defs.h file. That definition is cleared when BLIS detects that the -fopenmp-simd command line option is unsupported. Thanks to Devin Matthews and Jeff Hammond for suggestions that guided this commit. - Updated configure and bli_config.h.in so that the appropriate anchor is substituted in (when the corresponding pragma omp simd support is present). commit b1f5ce8622b682b79f956fed83f04a60daa8e0fc Author: Field G. Van Zee Date: Tue Feb 5 17:38:50 2019 -0600 Minor updates to scripts in test/mixeddt/matlab. commit 38203ecd15b1fa50897d733daeac6850d254e581 Author: Devangi N. Parikh Date: Mon Feb 4 15:28:28 2019 -0500 Added thunderx2 system in the mixeddt test scripts Details: - Added thunderx2 (tx2) as a system in the runme.sh in test/mixeddt commit dfc91843ea52297bf636147793029a0c1345be04 Author: Devangi N. Parikh Date: Mon Feb 4 15:23:40 2019 -0500 Fixed gcc flags for thunderx2 subconfiguration Details: - Fixed -march flag. Thunderx2 is an armv8.1a architecture not armv8a. commit c665eb9b888ec7e41bd0a28c4c8ac4094d0a01b5 Author: Field G. Van Zee Date: Mon Jan 28 16:22:23 2019 -0600 Minor updates to docs, Makefiles. Details: - Changed all occurrances of micro-kernel -> microkernel macro-kernel -> macrokernel micro-panel -> micropanel in all markdown documents in 'docs' directory. This change is being made since we've reached the point in adoption and acceptance of BLIS's insights where words such as "microkernel" are no longer new, and therefore now merit being unhyphenated. - Updated "Implementation Notes" sections of KernelsHowTo.md, which still contained references to nonexistent cpp macros such as BLIS_DEFAULT_MR_? and BLIS_PACKDIM_MR_?. - Added 'run-fast' and 'check-fast' targets to testsuite/Makefile. - Minor updates to Testsuite.md, including suggesting use of 'make check' and 'make check-fast' when running from the local testsuite directory. - Added a comment to top-level Makefile explaining the purpose behind the TESTSUITE_WRAPPER variable, which at first glance appears to serve no purpose. commit 1aa280d0520ed5eaea3b119b4e92b789ecad78a4 Author: M. Zhou <5723047+cdluminate@users.noreply.github.com> Date: Sun Jan 27 21:40:48 2019 +0000 Amend OS detection for kFreeBSD. (#295) commit fffc23bb35d117a433886eb52ee684ff5cf6997f Author: Field G. Van Zee Date: Fri Jan 25 13:35:31 2019 -0600 CREDITS file update. commit 26c5cf495ce22521af5a36a1012491213d5a4551 Author: Field G. Van Zee Date: Thu Jan 24 18:49:31 2019 -0600 Fixed bug in skx subconfig related to bdd46f9. Details: - Fixed code in the skx subconfiguration that became a bug after committing bdd46f9. Specifically, the bli_cntx_init_skx() function was overwriting default blocksizes for the scomplex and dcomplex microkernels despite the fact that only single and double real microkernels were being registered. This was not a problem prior to bdd46f9 since all microkernels used dynamically-queried (at runtime) register blocksizes for loop bounds. However, post-bdd46f9, this became a bug because the reference ukernels for scomplex and dcomplex were written with their register blocksizes hard-coded as constant loop bounds, which conflicted the the erroneous scomplex and dcomplex values that bli_cntx_init_skx() was setting in the context. The lesson here is that going forward, all subconfigurations must not set any blocksizes for datatypes corresponding to default/reference microkernels. (Note that a blocksize is left unchanged by the bli_cntx_set_blkszs() function if it was set to -1.) commit 180f8e42e167b83a757340ad4bd4a5c7a1d6437b Author: Field G. Van Zee Date: Thu Jan 24 18:01:15 2019 -0600 Fixed undefined behavior trsm ukr bug in bdd46f9. Details: - Fixed a bug that mainfested anytime a configuration was used in which optimized microkernels were registered and the trsm operation (or kernel) was invoked. The bug resulted from the optimized microkernels' register blocksizes conflicting with the hard-coded values--expressed in the form of constant loop bounds--used in the new reference trsm ukernels that were introduced in bdd46f9. The fix was easy: reverting back to the implementation that uses variable-bound loops, which amounted to changing an #if 0 to #if 1 (since I preserved the older implementation in the file alongside the new code based on constant- bound loops). It should be noted that this fix must be permanent, since the trsm kernel code with constant-bound loops can never work with gemm ukernels that use different register blocksizes. commit bdd46f9ee88057d52610161966a11c224e5a026c Author: Field G. Van Zee Date: Thu Jan 24 17:23:18 2019 -0600 Rewrote reference kernels to use #pragma omp simd. Details: - Rewrote level-1v, -1f, and -3 reference kernels in terms of simplified indexing annotated by the #pragma omp simd directive, which a compiler can use to vectorize certain constant-bounded loops. (The new kernels actually use _Pragma("omp simd") since the kernels are defined via templatizing macros.) Modest speedup was observed in most cases using gcc 5.4.0, which may improve with newer versions. Thanks to Devin Matthews for suggesting this via issue #286 and #259. - Updated default blocksizes defined in ref_kernels/bli_cntx_ref.c to be 4x16, 4x8, 4x8, and 4x4 for single, double, scomplex and dcomplex, respectively, with a default row preference for the gemm ukernel. Also updated axpyf, dotxf, and dotxaxpyf fusing factors to 8, 6, and 4, respectively, for all datatypes. - Modified configure to verify that -fopenmp-simd is a valid compiler option (via a new detect/omp_simd/omp_simd_detect.c file). - Added a new header in which prefetch macros are defined according to which compiler is detected (via macros such as __GNUC__). These prefetch macros are not yet employed anywhere, though. - Updated the year in copyrights of template license headers in build/templates and removed AMD as a default copyright holder. commit 63de2b0090829677755eb5cdb27e73bc738da32d Author: Field G. Van Zee Date: Wed Jan 23 12:16:27 2019 -0600 Prevent redef of ftnlen in blastest f2c_types.h. Details: - Guard typedef of ftnlen in f2c_types.h with a #ifndef HAVE_BLIS_H directive to prevent the redefinition of that type. Thanks to Jeff Diamond for reporting this compiler warning (and apologies for the delay in committing a fix). commit eec2e183a7b7d67702dbd1f39c153f38148b2446 Author: Field G. Van Zee Date: Mon Jan 21 12:12:18 2019 -0600 Added escaping to '/' in os_name in configure. Details: - Add os_name to the list of variables into which the '/' character is escaped. This is meant to address (or at least make progress toward addressing) #293. Thanks to Isuru Fernando for spotting this as the potential fix, and also thanks to M. Zhou for the original report. commit adf5c17f0839fdbc1f4a1780f637928b1e78e389 Author: Field G. Van Zee Date: Fri Jan 18 15:14:45 2019 -0600 Formally registered thunderx2 subconfiguration. Details: - Added a separate subconfiguration for thunderx2, which now uses different optimization flags than cortexa57/cortexa53. commit 094cfdf7df6c2764c25fcbfce686ba29b933942c Author: M. Zhou <5723047+cdluminate@users.noreply.github.com> Date: Fri Jan 18 18:46:13 2019 +0000 Port BLIS to GNU Hurd OS. (#294) Prevent blis.h from misidentifying Hurd as OSX. commit 5d7d616e8e591c2f3c7c2d73220eb27ea484f9c9 Author: Field G. Van Zee Date: Tue Jan 15 20:52:51 2019 -0600 README.md update re: mixeddt TOMS paper. commit 58c7fb4788177487f73a3964b7a910fe4dc75941 Author: Field G. Van Zee Date: Tue Jan 8 17:00:27 2019 -0600 Added more matlab scripts for mixeddt paper. Details: - Added a variant set of matlab scripts geared to producing plots that reflect performance data gathered with and without extra memory optimizations enabled. These scripts reside (for now) in test/mixeddt/matlab/wawoxmem. commit 34286eb914b48b56cdda4dfce192608b9f86d053 Author: Field G. Van Zee Date: Tue Jan 8 11:41:20 2019 -0600 Minor update to docs/HardwareSupport.md. commit 108b04dc5b1b1288db95f24088d1e40407d7bc88 Author: Field G. Van Zee Date: Mon Jan 7 20:16:31 2019 -0600 Regenerated symbols in build/libblis-symbols.def. Details: - Reran ./build/regen-symbols.sh after running 'configure --enable-cblas auto' to reflect removal of bli_malloc_pool() and bli_free_pool(). commit 706cbd9d5622f4690e6332a89cf41ab5c8771899 Author: Field G. Van Zee Date: Mon Jan 7 18:28:19 2019 -0600 Minor tweaks/cleanups to bli_malloc.c, _apool.c. Details: - Removed malloc_ft and free_ft function pointer arguments from the interface to bli_apool_init() after deciding that there is no need to specify the malloc()/free() for blocks within the apool. (The apool blocks are actually just array_t structs.) Instead, we simply call bli_malloc_intl()/_free_intl() directly. This has the added benefit of allowing additional output when memory tracing is enabled via --enable-mem-tracing. Also made corresponding changes elsewhere in the apool API. - Changed the inner pools (elements of the array_t within the apool_t) to use BLIS_MALLOC_POOL and BLIS_FREE_POOL instead of BLIS_MALLOC_INTL and BLIS_FREE_INTL. - Disabled definitions of bli_malloc_pool() and bli_free_pool() since there are no longer any consumers of these functions. - Very minor comment / printf() updates. commit 579145039d945adbcad1177b1d53fb2d3f2e6573 Author: Minh Quan Ho <1337056+hominhquan@users.noreply.github.com> Date: Mon Jan 7 23:00:15 2019 +0100 Initialize error messages at compile time (#289) * Initialize error messages at compile time - Assigning strings directly to the bli_error_string array, instead of snprintf() at execution-time. * Retired bli_error_init(), _finalize(). Details: - Removed functions obviated by changes in 80e8dc6: bli_error_init(), bli_error_finalize(), and bli_error_init_msgs(), as well as calls to the former two in bli_init.c. * Regenerated symbols in build/libblis-symbols.def. Details: - Reran ./build/regen-symbols.sh after running 'configure --enable-cblas auto'. commit aafbca086e36b6727d7be67e21fef5bd9ff7bfd9 Author: Field G. Van Zee Date: Mon Jan 7 12:38:21 2019 -0600 Updated external package language in README.md. Details: - Updated/added comments about Fedora, OpenSUSE, and GNU Guix under the newly-renamed "External GNU/Linux packages" section. Thanks to Dave Love for providing these revisions. commit daacfe68404c9cc8078e5e7ba49a8c7d93e8cda3 Author: Field G. Van Zee Date: Mon Jan 7 12:12:47 2019 -0600 Allow running configure with python 3.4. Details: - Relax version blacklisting of python3 to allow 3.4 or later instead of 3.5 or later. Thanks to Dave Love for pointing out that 3.4 was sufficient for the purpose of BLIS's build system. (It should be noted that we're not sure which, if any, python3 versions prior to 3.4 are insufficient, and that the only thing stopping us from determining this is the fact that these earlier versions of python3 are not readily available for us to test with.) - Updated docs/BuildSystem.md to be explicit about current python2 vs python3 version requirements. commit cdbf16aa93234e0d6a80f0d0e385ec81e7b75465 Author: prangana Date: Fri Jan 4 15:59:21 2019 +0530 Update version 1.3 Change-Id: I32a7d24af860e87a60396614075236afb65a28a9 commit cf9c1150515b8e9cc4f12e0d4787b3471b12ba4a Author: kdevraje Date: Thu Jan 3 09:51:46 2019 +0530 This commit adds a macro, which is to be enabled when BLIS is working on single instance mode Change-Id: I7f3fd654b78e64c4e6e24e9f0e245b1a30c492b0 commit ad8d9adb09a7dd267bbdeb2bd1fbbf9daf64ee76 Author: Field G. Van Zee Date: Thu Jan 3 16:08:24 2019 -0600 README.md, CREDITS update. Details: - Added "What's New" and "What People Are Saying About BLIS" sections to README.md. - Added missing github handles to various individuals' entries in the CREDITS file. commit 7052fca5aef430241278b67d24cef6fe33106904 Author: Field G. Van Zee Date: Wed Jan 2 13:48:40 2019 -0600 Apply f272c289 to bli_fmalloc_noalign(). Details: - Perform the same check for NULL return values and error message output in bli_fmalloc_noalign() as is performed by bli_fmalloc_align(). (This change was intended for f272c289.) commit 528e3ad16a42311a852a8376101959b4ccd801a5 Merge: 3126c52e f272c289 Author: Field G. Van Zee Date: Wed Jan 2 13:39:19 2019 -0600 Merge branch 'amd' commit 3126c52ea795ffb7d30b16b7f7ccc2a288a6158d Merge: 61441b24 8091998b Author: Field G. Van Zee Date: Wed Jan 2 13:37:37 2019 -0600 Merge branch 'amd' commit f272c2899a6764eedbe05cea874ee3bd258dbff3 Author: Field G. Van Zee Date: Wed Jan 2 12:34:15 2019 -0600 Add error message to malloc() check for NULL. Details: - Output an error message if and when the malloc()-equivalent called by bli_fmalloc_align() ever returns NULL. Everything was already in place for this to happen, including the error return code, the error string sprintf(), the error checking function bli_check_valid_malloc_buf() definition, and its prototype. Thanks to Minh Quan Ho for pointing out the missing error message. - Increased the default block_ptrs_len for each inner pool stored in the small block allocator from 10 to 25. Under normal execution, each thread uses only 21 blocks, so this change will prevent the sba from needing to resize the block_ptrs array of any given inner pool as threads initially populate the pool with small blocks upon first execution of a level-3 operation. - Nix stray newline echo in configure. commit eb97f778a1e13ee8d3b3aade05e479c4dfcfa7c0 Author: Field G. Van Zee Date: Tue Dec 25 20:17:09 2018 -0600 Added missing AMD copyrights to previous commit. Details: - Forgot to add AMD copyrights to several touched files that did not already have them in 2f31743. commit 2f3174330fb29164097d664b7c84e05c7ced7d95 Author: Field G. Van Zee Date: Tue Dec 25 19:35:01 2018 -0600 Implemented a pool-based small block allocator. Details: - Implemented a sophisticated data structure and set of APIs that track the small blocks of memory (around 80-100 bytes each) used when creating nodes for control and thread trees (cntl_t and thrinfo_t) as well as thread communicators (thrcomm_t). The purpose of the small block allocator, or sba, is to allow the library to transition into a runtime state in which it does not perform any calls to malloc() or free() during normal execution of level-3 operations, regardless of the threading environment (potentially multiple application threads as well as multiple BLIS threads). The functionality relies on a new data structure, apool_t, which is (roughly speaking) a pool of arrays, where each array element is a pool of small blocks. The outer pool, which is protected by a mutex, provides separate arrays for each application thread while the arrays each handle multiple BLIS threads for any given application thread. The design minimizes the potential for lock contention, as only concurrent application threads would need to fight for the apool_t lock, and only if they happen to begin their level-3 operations at precisely the same time. Thanks to Kiran Varaganti and AMD for requesting this feature. - Added a configure option to disable the sba pools, which are enabled by default; renamed the --[dis|en]able-packbuf-pools option to --[dis|en]able-pba-pools; and rewrote the --help text associated with this new option and consolidated it with the --help text for the option associated with the sba (--[dis|en]able-sba-pools). - Moved the membrk field from the cntx_t to the rntm_t. We now pass in a rntm_t* to the bli_membrk_acquire() and _release() APIs, just as we do for bli_sba_acquire() and _release(). - Replaced all calls to bli_malloc_intl() and bli_free_intl() that are used for small blocks with calls to bli_sba_acquire(), which takes a rntm (in addition to the bytes requested), and bli_sba_release(). These latter two functions reduce to the former two when the sba pools are disabled at configure-time. - Added rntm_t* arguments to various cntl_t and thrinfo_t functions, as required by the new usage of bli_sba_acquire() and _release(). - Moved the freeing of "old" blocks (those allocated prior to a change in the block_size) from bli_membrk_acquire_m() to the implementation of the pool_t checkout function. - Miscellaneous improvements to the pool_t API. - Added a block_size field to the pblk_t. - Harmonized the way that the trsm_ukr testsuite module performs packing relative to that of gemmtrsm_ukr, in part to avoid the need to create a packm control tree node, which now requires a rntm_t that has been initialized with an sba and membrk. - Re-enable explicit call bli_finalize() in testsuite so that users who run the testsuite with memory tracing enabled can check for memory leaks. - Manually imported the compact/minor changes from 61441b24 that cause the rntm to be copied locally when it is passed in via one of the expert APIs. - Reordered parameters to various bli_thrcomm_*() functions so that the thrcomm_t* to the comm being modified is last, not first. - Added more descriptive tracing for allocating/freeing small blocks and formalized via a new configure option: --[dis|en]able-mem-tracing. - Moved some unused scalm code and headers into frame/1m/other. - Whitespace changes to bli_pthread.c. - Regenerated build/libblis-symbols.def. commit 61441b24f3244a4b202c29611a4899dd5c51d3a1 Author: Field G. Van Zee Date: Thu Dec 20 19:38:11 2018 -0600 Make local copy of user's rntm_t in level-3 ops. Details: - In the case that the caller passes in a non-NULL rntm_t pointer into one of the expert APIs for a level-3 operation (e.g. bli_gemm_ex()), make a local copy of the rntm_t and use the address of that local copy in all subsequent execution (which may change the contents of the rntm_t). This prevents a potentially confusing situation whereby a user-initialized rntm_t is used once (in, say, gemm), and then found by the user to be in a different state before it is used a second time. commit e809b5d2f1023b4249969e2f516291c9a3a00b80 Merge: 76016691 0476f706 Author: Field G. Van Zee Date: Thu Dec 20 16:27:26 2018 -0600 Merge branch 'master' into amd commit 1f4eeee5175a8fc9ac312847c796ce6db5fe75b9 Author: sraut Date: Wed Dec 19 21:21:10 2018 +0530 Fixed BLAS test failures of small matrix SYRK for single and double precision. Details: - SYRK for small matrix was implemented by reusing small GEMM routine. This was resulting in output written to the full C matrix, and C being symmetric the lower and upper triangles of C matrix contained same results. BLAS SYRK API spec demands either lower or upper triangle of C matrix to be written with results. So, this was resulting in BLAS test failures, even though testsuite of BLIS was passing small SYRK operation. - To fix BLAS test failures of small matrix SYRK, separate kernel routines are implemented for small SYRK for both single and double precision. The newly added small SYRK routines are in file kernels/zen/3/bli_syrk_small.c. Now the intermediate results of matrix C are written to a scratch buffer. Final results are written from scratch buffer to matrix C using SIMD copy to either lower or upper traingle part of matrix C. - Source and header files frame/3/syrk/bli_syrk_front.c and frame/3/syrk/bli_syrk_front.h are changed to invoke new small SYRK routines. Change-Id: I9cfb1116c93d150aefac673fca033952ecac97cb commit 6d267375c3a0543f20604d74cc678ad91db3b6f1 Author: sraut Date: Wed Dec 19 14:22:21 2018 +0530 This commit improves the performance of multi-instance DGEMM when these multiple threads are binded to a CCX. Multi-Instance: Each thread runs a sequential DGEMM. Change-Id: I306920c8061b6dad61efac1dae68727f4ac27df6 commit 0476f706b93e83f6b74a3d7b7e6e9cc9a1a52c3b Author: Field G. Van Zee Date: Tue Dec 18 14:56:20 2018 -0600 CHANGELOG update (0.5.1) commit e0408c3ca3d53bc8e6fedac46ea42c86e06c922d (tag: 0.5.1) Author: Field G. Van Zee Date: Tue Dec 18 14:56:16 2018 -0600 Version file update (0.5.1) commit 3ab231afc9f69d14493908c53c85a84c5fba58aa Author: Field G. Van Zee Date: Tue Dec 18 14:53:37 2018 -0600 ReleaseNotes.md update in advance of next version. Details: - Updated ReleaseNotes.md in preparation for next version. commit d1aa87164e1e82347d62aa98793963c5265ef7e7 Author: Field G. Van Zee Date: Tue Dec 18 14:52:40 2018 -0600 README.md update (External packages section). Details: - Updated External packages section in anticipation of introducing BLIS into Debian package universe. Thanks to M. Zhou for sponsoring BLIS in Debian. commit 7bf901e9265a1acd78e44c06f7178c8152c7e267 Author: sraut Date: Tue Dec 18 14:39:16 2018 +0530 Fix on EPYC machine for multi instance performance issue, Issue: For the default values of mc, kc and nc with multi instance mode the performance across the cores dip drastically. Fix: After experimentation found different set of values (mc, kc and nc) which fits in the cache size, and performance across the remains same across all the cores. Change-Id: I98265e3b7e61cd7602a0cc5596240e86c08c03fe commit d2b2a0819a2fccad9165bc48c0e172d79a87542c Author: Field G. Van Zee Date: Mon Dec 17 19:26:35 2018 -0600 Removed stray sections from Multithreading.md. Details: - Removed unintended section headers from before table of contents. commit 93d56319f2953cf0e9df1ff2cda90b8e41351b2c Author: Field G. Van Zee Date: Mon Dec 17 19:17:30 2018 -0600 Added missing bli_init_once() in bli_thread API. Details: - Fixed an issue with specifying threading globally at runtime via bli_thread_set_num_threads() (the automatic way) or via bli_thread_set_ways() (the manual way), with bli_thread_init_rntm() also affected. These functions were not calling bli_init_once() prior to acting, and therefore their effects on the global rntm_t structure were being wiped out by the eventual call to bli_init_once(), by some other BLIS function. Thanks to Ali Emre Gülcü for reporting the behavior associated with this bug. - Added additional content to docs/Multithreading.md covering topics of choosing between OpenMP and pthreads, and specifying affinity via OpenMP. - CREDITS file update. commit 76016691e2c514fcb59f940c092475eda968daa2 Author: Field G. Van Zee Date: Thu Dec 13 17:23:09 2018 -0600 Improvements to bli_pool; malloc()/free() tracing. Details: - Added malloc_ft and free_ft fields to pool_t, which are provided when the pool is initialized, to allow bli_pool_alloc_block() and bli_pool_free_block() to call bli_fmalloc_align()/bli_ffree_align() with arbitrary align_size values (according to how the pool_t was initialized). - Added a block_ptrs_len argument to bli_pool_init(), which allows the caller to specify an initial length for the block_ptrs array, which previously suffered the cost of being reallocated, copied, and freed each time a new block was added to the pool. - Consolidated the "buf_sys" and "buf_align" pointer fields in pblk_t into a single "buf" field. Consolidated the bli_pblk API accordingly and also updated the bli_mem API implementation. This was done because I'd previously already implemented opaque alignment via bli_malloc_align(), which allocates extra space and stores the original pointer returned by malloc() one element before the element whose address is aligned. - Tweaked bli_membrk_acquire_m() and bli_membrk_release() to call bli_fmalloc_align() and bli_ffree_align(), which required adding an align_size field to the membrk_t struct. - Pass the pack schemas directly into bli_l3_cntl_create_if() rather than transmit them via objects for A and B. - Simplified bli_l3_cntl_free_if() and renamed to bli_l3_cntl_free(). The function had not been conditionally freeing control trees for quite some time. Also, removed obj_t* parameters since they aren't needed anymore (or never were). - Spun-off OpenMP nesting code in bli_l3_thread_decorator() to a separate function, bli_l3_thread_decorator_thread_check(). - Renamed: bli_malloc_align() -> bli_fmalloc_align() bli_free_align() -> bli_ffree_align() bli_malloc_noalign() -> bli_fmalloc_noalign() bli_free_noalign() -> bli_ffree_noalign() The 'f' is for "function" since they each take a malloc_ft or free_ft function pointer argument. - Inserted various printf() calls for the purposes of tracing memory allocation and freeing, guarded by cpp macro ENABLE_MEM_DEBUG, which, for now, is intended to be a "hidden" feature rather than one hooked up to a configure-time option. - Defined bli_rntm_equals(), which compares two rntm_t for equality. (There are no use cases for this function yet, but there may be soon.) - Whitespace changes to function parameter lists in bli_pool.c, .h. commit f808d829c58dc4194cc3ebc3825fbdde12cd3f93 Author: Field G. Van Zee Date: Wed Dec 12 15:22:59 2018 -0600 Handle edge cases, zero-filling in packm kernels. Details: - Updated the API and semantics of packm kernels such that they must now handle edge cases, meaning that a c-by-k packm kernel must be able to pack edge cases that are fewer than c rows/columns and be able to zero-fill the remaining elements. They must also be able to zero-fill the equivalent region when copying fewer than k columns/rows (which is needed by trsm). The new packm kernel API is generally: void packm_kernel ( conj_t conja, dim_t cdim, dim_t n, dim_t n_max, ctype* restrict kappa, ctype* restrict a, inc_t inca, inc_t lda, ctype* restrict p, inc_t ldp, cntx_t* restrict cntx ); where cdim and n are the dimensions (short and long, respectively) of the submatrix being copied from the source matrix A, and n_max is the "full" long dimension (corresponding to the k dimension in gemm) of the micropanel. The "full" short dimension (corresponding to the register blocksize MR or NR) is not part of the API because it is known intrinsically by the packm kernel implementation. Thanks to Devin Matthews for prompting us to make this change (#282). - Updated all reference packm kernels in ref_kernels/1m according to above changes, as well as all optimized packm kernels (which only consisted of those for knl). - Bumped the major soname version number in 'so_version' to 2. At first I was considering leaving it unchanged, but I couldn't escape the reality that the packm kernel API is much closer to an expert API than it is some obscure helper function interface within the framework that nobody would ever notice. - Removed reference packm kernels for mr/nr = 30. The only sub-config that would have been using those kernels is knc, which is likely no longer being used by very many people (if any). (This also mostly offset the larger object code footprint incurred by moving the edge- case handling into the individual packm kernels.) - Fixed an obscure race condition for 3mh and 4mh induced methods in which those implementations were modifying the contexts stored in the gks rather than a local copy. - Fixed a minor bug in the testsuite that prevented non-1m-based induced method implementations of trsm from executing. commit 02ec0be3ba0b0d6b4186386ae140906a96de919b Merge: e275def3 c534da62 Author: Field G. Van Zee Date: Wed Dec 5 19:33:53 2018 -0600 Merge branch 'master' into amd commit c534da62c0015f91391983da5376c9e091378010 Author: Field G. Van Zee Date: Wed Dec 5 15:51:05 2018 -0600 Disabled ARM configuration families in registry. Details: - Disabled (commented out) the arm32 and arm64 configuration families in the config_registry file. Having a configuration family registered only makes sense if BLIS is currently outfitted with runtime hardware detection logic to choose the appropriate sub-configuration. That logic is currently missing for ARM architectures, and thus having the ARM configuration families in the configuration registry only serves to confuse people. Thanks to Devangi Parikh for suggesting this change. commit 6885051a164628904fad0d8a3b39c82f9a7b193c Author: Field G. Van Zee Date: Wed Dec 5 14:45:39 2018 -0600 Generalizations/cleanup to mixeddt matlab scripts. Details: - Parameterized, reorganized, and added comments to matlab scripts in test/mixeddt/matlab. - Reordered some lines of code and added comments to plot_l3_perf.m in test/3m4m/matlab. commit cbdb0566bf3201a495bbdcb8cb50342fa0098649 Author: Field G. Van Zee Date: Wed Dec 5 20:06:32 2018 +0000 Updates to 3m4m, mixeddt test driver files. Details: - Updated 3m4m and mixeddt Makefiles and runme.sh scripts, mostly to port recent changes to the former to the latter. - Disabled (for now) code in 3m4m/test_*.c files that disables all induced methods except for the one that is requested from the Makefile via the IND macro. This is done because usually, we want to test whatever method is enabled automatically for complex datatypes. (That is, when native complex microkernels are missing, we usually want to test performance of 1m.) commit 0645f239fbdf37ee9d2096ee3bb0e76b3302cfff Author: Field G. Van Zee Date: Tue Dec 4 14:31:06 2018 -0600 Remove UT-Austin from copyright headers' clause 3. Details: - Removed explicit reference to The University of Texas at Austin in the third clause of the license comment blocks of all relevant files and replaced it with a more all-encompassing "copyright holder(s)". - Removed duplicate words ("derived") from a few kernels' license comment blocks. - Homogenized license comment block in kernels/zen/3/bli_gemm_small.c with format of all other comment blocks. commit 9b688a2d69dd420f4d2582827c5ac87e422cd3bc Author: Field G. Van Zee Date: Tue Dec 4 13:30:25 2018 -0600 Refer to color mm algorithm in Multithreading.md. commit 22384fd2b749aa8cfdfad1084ce5e7dbd4ad2d64 Author: Field G. Van Zee Date: Tue Dec 4 13:09:04 2018 -0600 Minor updates to test_gemm.c in test/mixeddt. commit 2ba3b1780cbca58e43a3948d67bd07e637036125 Author: Field G. Van Zee Date: Mon Dec 3 19:40:39 2018 -0600 Removed symbols from libblis-symbols.def. Details: - Removed bli_gemm_md_front() and bli_gemm_md_zgemm() symbols from build/libblis-symbols.def, which will hopefully appease AppVeyor. commit dcb38c4e59c3395c258799e69bfe2104c578c528 Merge: dc184095 375eb30b Author: Field G. Van Zee Date: Mon Dec 3 18:06:19 2018 -0600 Merge branch 'dev' commit 375eb30b0a63ac06a363a5f75f283584258db48b Author: Field G. Van Zee Date: Mon Dec 3 17:49:52 2018 -0600 Added mixed-precision support to 1m method. Details: - Lifted the constraint that 1m only be used when all operands' storage datatypes (along with the computation datatype) are equal. Now, 1m may be used as long as all operands are stored in the complex domain. This change largely consisted of adding the ability to pack to 1e and 1r formats from one precision to another. It also required adding logic for handling complex values of alpha to bli_packm_blk_var1_md() (similar to the logic in bli_packm_blk_var1()). - Fixed a bug in several virtual microkernels (bli_gemm_md_c2r_ref.c, bli_gemm1m_ref.c, and bli_gemmtrsm1m_ref.c) that resulted in the wrong ukernel output preference field being read. Previously, the preference for the native complex ukernel was being read instead of the pref for the native real domain ukernel. This bug would not manifest if the preference for the native complex ukernel happened to be equal to that of the native real ukernel. - Added support for testing mixed-precision 1m execution via the gemm module of the testsuite. - Tweaked/simplified bli_gemm_front() and bli_gemm_md.c so that pack schemas are always read from the context, rather than trying to sometimes embed them directly to the A and B objects. (They are still embedded, but now uniformly only after reading the schemas from the context.) - Redefined cpp macro bli_l3_ind_recast_1m_params() as a static function and renamed to bli_gemm_ind_recast_1m_params() (since gemm is the only consumer). - Added 1m optimization logic (via bli_gemm_ind_recast_1m_params()) to bli_gemm_ker_var2_md(). - Added explicit handling for beta == 1 and beta == 0 in the reference gemm1m virtual microkernel in ref_kernels/ind/bli_gemm1m_ref.c. - Rewrote various level-0 macro defs, including axpyris, axpbyris, scal2ris, and xpbyris (and their conjugating counterparts) to explicitly support three operand types and updated invocations to xpbyris in bli_gemmtrsm1m_ref.c. - Query and use the storage datatype of the packed object instead of the storage datatype of the source object in bli_packm_blk_var1(). - Relocated and renamed frame/ind/misc/bli_l3_ind_opt.h to frame/3/gemm/ind/bli_gemm_ind_opt.h. - Various whitespace/comment updates. commit e275def30ac41cadce296560fa67282704f20a02 Merge: 8091998b dc184095 Author: Field G. Van Zee Date: Fri Nov 30 15:39:50 2018 -0600 Merge branch 'master' into amd commit dc18409551f341125169fe8d4d43ac45e81bdf28 Author: Field G. Van Zee Date: Wed Nov 28 11:58:40 2018 -0600 CREDITS file update. commit ee4d2712963816f84d7e3fdd39d93424e1aaf63d Merge: e81c4b56 3d7e8bc3 Author: Field G. Van Zee Date: Wed Nov 28 11:52:57 2018 -0600 Merge pull request #287 from SuperFluffy/fix_configuration_links Fix configuration links commit 3d7e8bc3b8e77693152138e75676f71573e5e6cd Author: Richard Janis Goldschmidt Date: Wed Nov 28 15:56:37 2018 +0100 Fix configuration links commit 6a4885f8be9ecd81423ebf2eb6da75d7981c979b Merge: 1d8aae22 e81c4b56 Author: Field G. Van Zee Date: Tue Nov 27 13:22:59 2018 -0600 Merge branch 'master' into dev commit e81c4b56660b25a39f8fdc09fbe07459c5bd8e8e Merge: 757043ea cfbdb58d Author: Field G. Van Zee Date: Wed Nov 21 17:00:49 2018 -0600 Merge pull request #285 from isuruf/pthread Move LDFLAGS to the end commit cfbdb58de2e44f2e3a3d8b14fceece7aef4b3006 Author: Isuru Fernando Date: Wed Nov 21 14:23:39 2018 -0600 Move LDFLAGS to the end Otherwise the linker will drop flags like -lpthread commit 757043eae8630c0a76e9bb04f2cb0bd72439a86a Merge: e769bf46 7af8fa01 Author: Field G. Van Zee Date: Wed Nov 21 13:07:26 2018 -0600 Merge pull request #283 from isuruf/patch-3 Fix MinGW and Cygwin build failures commit 7af8fa01373b7bb30fa3b1fd110fd201c87ea225 Author: Isuru Fernando Date: Wed Nov 21 02:10:05 2018 -0600 Fix blis dll path commit 2acd8dcd23805203a6821358c5e3e09d521fecdf Author: Isuru Fernando Date: Wed Nov 21 02:02:18 2018 -0600 Fix install path of dll.a commit b7b0ad22b151e89e2a6c7782cf4d8d47b4e60734 Author: Isuru Fernando Date: Wed Nov 21 01:54:44 2018 -0600 Test mingw commit bafe521ed0012b7b8814404b78a6c576d8386370 Author: Isuru Fernando Date: Wed Nov 21 01:54:36 2018 -0600 Fixes for mingw commit be831879bd03edcddff8a345161f749ad92215af Author: Isuru Fernando Date: Wed Nov 21 01:39:32 2018 -0600 test gcc shared commit f6b924648c79c4b1c3d3c7fbf85372680aff8362 Author: Isuru Fernando Date: Wed Nov 21 01:39:19 2018 -0600 Don't use .def for gcc commit ce6e4eae6d5e977e6f699acc9cf239be8ac53771 Author: Isuru Fernando Date: Wed Nov 21 01:34:56 2018 -0600 test no threading commit c9169b4685bfe81bc562cf9128b35a6a9884799b Author: Isuru Fernando Date: Wed Nov 21 01:17:36 2018 -0600 Add mingw64 path commit 0f753090eaf4264b743a49ce15de97514bcbe112 Author: Isuru Fernando Date: Wed Nov 21 01:14:52 2018 -0600 Fix PATH commit d424470b1f2fa8717fa54c0245b21341504665f6 Author: Isuru Fernando Date: Wed Nov 21 01:04:26 2018 -0600 Check openmp and pthreads threading commit c73e7601e58239e2dedec6c9f1b752e949254a42 Author: Isuru Fernando Date: Wed Nov 21 00:50:33 2018 -0600 Revert "enable rdp" This reverts commit 368274bcbd0c9232521d14fa28304f35ced0e6d7. commit 6209b2e6060b89e65f3405c31333af8952dd63c0 Author: Isuru Fernando Date: Wed Nov 21 00:50:22 2018 -0600 Remove conda commit 0b1b344447b8a2fcd635a48f0ce7ce89b2107dc4 Author: Isuru Fernando Date: Wed Nov 21 00:42:39 2018 -0600 Fix make name commit 7a9838983ba8dd32ac9f87712255721542ff561f Author: Isuru Fernando Date: Wed Nov 21 00:35:27 2018 -0600 Use m2w64-make commit 4c1dedd6a90087807f16353a5d0bcaaade35a7a5 Author: Isuru Fernando Date: Wed Nov 21 00:28:20 2018 -0600 No activate on gcc commit 368274bcbd0c9232521d14fa28304f35ced0e6d7 Author: Isuru Fernando Date: Tue Nov 20 23:40:26 2018 -0600 enable rdp commit 707a5e7f9b07f554e1e9289dd0ce3b7dc4fded6e Author: Isuru Fernando Date: Tue Nov 20 23:39:31 2018 -0600 No conda for mingw build commit 65b0565c0ad9162d4474bd84eabde491fa971538 Author: Isuru Fernando Date: Tue Nov 20 23:19:38 2018 -0600 Check MinGW-w64 commit 9ddffba5847080e0d77d9e6059d05dc4b1d89ba5 Author: Isuru Fernando Date: Wed Nov 21 00:23:34 2018 -0600 Fix MinGW build failure Fixes https://github.com/flame/blis/issues/278 commit 1d8aae220bc52ce8e3a8afaa64b57e5d83480bdc Author: Field G. Van Zee Date: Tue Nov 20 18:42:07 2018 -0600 Track internal scalar datatypes. Details: - Added a num_t datatype bitfield to the obj_t in the form of a new info2 field in the obj_t. This change was made primarily so that in the case of mixed-datatype gemm, the alpha scalar would not need to be cast to the storage datatype of B (or A) before then being cast to the computation datatype just before the macrokernel is called. This double-casting regime could result in loss of precision if the storage datatype of B (or A) is less than the computation precision. In practice, it was likely not going to be a big deal since most usage of alpha is for -1.0, 0.0, and 1.0 (or integer multiples thereof), which can all be represented exactly in single or double precision. - The type of objbits_t was changed to uint32_t, so the new format potentially takes up the same space as the previous obj_t definition, assuming no padding inserted by the compiler. Shrinking info to 32 bits and spilling over into a second field was chosen over using the high 32 bits of a single 64-bit objbits_t info field because many of the bitwise operations are performed with enums such as num_t, dom_t, and prec_t, which may take on the type of 32-bit ints. It's easier to just keep all of those bitwise operations in 32 bits than perform a million typecasts throughout bli_type_defs.h and bli_obj_macro_defs.h to ensure that the integers are treated as 64-bit for the purposes of the ANDs, ORs, and bitshifts. - Many comment updates. - Thanks to Devin Matthews and Devangi Parikh for their feedback and involvement during this commit cycle. commit e769bf46b0931d68031af212110484ec98e16908 Author: Field G. Van Zee Date: Tue Nov 20 16:16:53 2018 -0600 Tweak testsuite to issue FAIL for Nan, Inf (#279). Details: - Adjusted the definition for libblis_test_get_string_for_result() in testsuite/src/test_libblis.c so that the "FAIL" string is returned if the computed residual contains either NaN or Inf. Previously, a residual containing NaN would result in the selection of the "PASS" string. Thanks to Devin Matthews for reporting this issue (#279). - Expounded on comment for the macro definitions of bli_isnan() and bli_isinf() in bli_misc_macro_defs.h to make it more obvious why they must remain macros. commit 279deae18fb8b8106161863b46fcb38232314de4 Author: Field G. Van Zee Date: Fri Nov 16 11:34:19 2018 -0600 Added 4x5 matlab plotting scripts to test/3m4m. Details: - Added a new directory, test/3m4m/matlab, containing matlab scripts for plotting 4x5 panels of performance graphs (using the subplot() function) for gemm, hemm, herk, trmm, and trsm across all four floating-point datatypes. I expect to further refine these scripts as time goes on, but their current state constitutes a good start. commit 7b02c726650336c12286c8ba166d1d0fdf7601a8 Author: Field G. Van Zee Date: Wed Nov 14 13:49:55 2018 -0600 CREDITS file update. commit 84dd298a27033945fa2d3b6e5dce1fe625cd2a0a Author: Field G. Van Zee Date: Wed Nov 14 13:47:45 2018 -0600 Patch to fix msys2/Windows build failure (#277). Details: - Expanded cpp guard in frame/include/bli_x86_asm_macros.h to also check __MINGW32__ in addition to _WIN32, __clang__, and __MIC__. Thanks to Isuru Fernando for suggesting this fix, and also to Costas Yamin for originally reporting the issue (#277). commit 8091998b6500e343c2024561c2b1aa73c3bafb0b Merge: 333d8562 7b5ba731 Author: Field G. Van Zee Date: Wed Nov 14 12:36:35 2018 -0600 Merge branch 'master' into amd commit 7b5ba7319b3901ad0e6c6b4fa3c1d96b579efbe9 Merge: ce719f81 52392932 Author: Field G. Van Zee Date: Wed Nov 14 12:32:01 2018 -0600 Merge branch 'dev' of github.com:flame/blis into dev commit 52392932dc1ea3c16220cc4e6978efcb2f5f0616 Author: Field G. Van Zee Date: Tue Nov 13 22:23:38 2018 +0000 Minor fixes to test/3m4m drivers. Details: - Cleanups to Makefile to allow all test drivers to be built for OpenBLAS and MKL in addition to BLIS. - Fixed copy-paste typos in test_hemm in calls to ssymm_() and dsymm_(). - Fixed incorrect types for betap in BLAS cpp macro branch of test_herk.c. commit 4f12e36a0d0e6df146314b4e50e36c5e7a1af3d3 Author: Field G. Van Zee Date: Tue Nov 13 14:23:12 2018 -0600 Fixed number of columns in first output line. Details: - In previous commit, forgot to remove output column corresponding to the k dimension. commit a2e0cdd7debf8109198536d55af05d5631072fb2 Author: Field G. Van Zee Date: Tue Nov 13 14:15:11 2018 -0600 Added hemm test driver to test/3m4m. Details: - Added a new test_hemm.c test driver to test/3m4m, which was modeled after the driver by the similar name in test. Also updated Makefile so that blis-nat-[sm]t would trigger builds for the new driver. commit 0f9b53e84b48d8d73a56cc9889eae3595ca58a78 Author: Field G. Van Zee Date: Tue Nov 13 13:03:15 2018 -0600 Fixed a bug in high-level mixeddt conditional. Details: - Fixed a bug in frame/3/bli_l3_oapi.c in the conditional that divides use of induced method (1m) execution from native execution. The former was intended to only be used in cases where all storage datatypes are complex and the datatype of C is equal to the computation datatype. (If mixed datatypes are detected, native execution would be used.) However, the code in bli_gemm() was erroneously checking the execution datatype instead of the computation datatype, which at that point is guaranteed to be equal to the storage datatype even if the computation datatype contains a different value. Thanks to Devangi Parikh for helping in isolating this bug. commit 333d8562f04eea0676139a10cb80a97f107b45b0 Author: Field G. Van Zee Date: Sun Nov 11 14:28:53 2018 -0600 Added debug output to bli_malloc.c. Details: - Added debug output to bli_malloc.c in order to debug certain kinds of memory behavior in BLIS. The printf() statements are disabled and must be enabled manually. - Whitespace/comment updates in bli_membrk.c. commit ce719f816d1237f5277527d7f61123e77180be54 Author: Field G. Van Zee Date: Sat Nov 10 14:48:43 2018 -0600 More edits to mixeddt matlab scripts. Details: - Renamed scripts in test/mixeddt/matlab: plot_case_all.m -> plot_dom_all.m plot_case_md.m -> plot_dom_case.m plot_all_md.m -> plot_dt_all.m - Added plot_dt_select.m in order to plot select graphs for the main body of the mixeddt paper, and added additional related legend handling in plot_gemm_perf.m. - Added test/mixeddt/matlab/output and a .gitkeep file within in order to force git to recognize the directory. commit bf99e7c14baf45725b698d06ad043b531e3a2763 Author: Field G. Van Zee Date: Thu Nov 8 18:47:17 2018 -0600 Minor updates to test/mixeddt driver. Details: - Cleaned up test/mixeddt Makefile in preparation for gathering new data for mixeddt paper, including renaming implementations to "internal" and "ad-hoc" to match the terminology to be used in the paper. - Added new matlab scripts for generating 8 figures, each covering all mixed-precision cases for each mixed-domain case. - Updated the runme.sh script according to changes to Makefile. - Fixed a minor bug in test_gemm.c that may have given incorrect performance in complex, homogeneous storage datatype cases where the computation precision was equal to the storage precisions. (Examples: zzzd, cccs.) commit 4bbb454bf3c361af9e97bfa394a73d610cd9002a Author: Field G. Van Zee Date: Sat Nov 3 19:11:01 2018 -0500 Testsuite docs update for mixed-datatype gemm. Details: - Updated docs/Testsuite.md to include mention of the new mixed-domain and mixed-precision settings, including descriptions. - Updated docs/MixedDatatypes.md to include a brief section on running the testsuite to exercise mixed-datatype functionality, which mostly amounts to a link to the Testsuite.md document. - Minor verbiage change to testsuite output to correct a misleading label associated with the value returned by the query function bli_info_get_simd_num_registers(). (The function does not return the number of SIMD registers present in the hardware, but rather a maximum assumed value for the purposes of allocating temporary microtile workspace on the function stack.) commit 16401ae922b1285437cf5f6867b2764650a95fb0 Merge: f19c33af 2d403a15 Author: Field G. Van Zee Date: Sat Nov 3 19:09:43 2018 -0500 Merge branch 'dev' commit 2d403a1535380a2ebe2ae2c0f5ac54ba7564fbeb Merge: e90e7f30 4a12979f Author: Field G. Van Zee Date: Thu Nov 1 20:18:53 2018 -0500 Merge pull request #275 from RhysU/patch-1 Spelling in FAQ commit 4a12979f65697ed79ba290efd59f4b994ac9429b Author: Rhys Ulerich Date: Thu Nov 1 20:20:59 2018 -0400 Spelling in FAQ commit f19c33af4cbe6f5705b96fbf2b8799c3c2bd75c3 Author: Field G. Van Zee Date: Fri Oct 26 17:07:15 2018 -0500 Disallow 64b BLAS integers + 32b BLIS integers. Details: - Print an error message from configure if the user attempts to explicitly configure BLIS for simultaneous use of 64-bit integers in the BLAS API with 32-bit integers in the BLIS API. - Added cpp macro conditional to bli_type_defs.h to mandate that BLIS integers be 64 bits if the BLAS integers are 64 bits. This and the above item take care of issue #274. Thanks to Devin Matthews and Jeff Hammond for suggesting these safeguards. - Slight reorganization and relabeling (for clarity) of BLAS/CBLAS sections and BLIS integer size line of the testsuite configuration output. - Very minor edits to docs/MixedDatatypes.md. commit e90e7f309b3f2760a01e8e09a29bf702754fa2b5 (origin/win-pthreads) Author: Field G. Van Zee Date: Thu Oct 25 14:09:43 2018 -0500 CHANGELOG update (0.5.0) commit be7c57819cfd48adb175d9a480cc9f37928645c1 (tag: 0.5.0) Author: Field G. Van Zee Date: Thu Oct 25 14:09:40 2018 -0500 Version file update (0.5.0) commit 75da7f2a208ad7d26ed9c6d3e10d08b2a1caf9d6 Author: Field G. Van Zee Date: Thu Oct 25 14:02:41 2018 -0500 ReleaseNotes.md update in advance of next version. Details: - Updated ReleaseNotes.md in preparation for next version. - Updated docs/FAQ.md to reflect recent developments, and other edits. - Minor updates to RELEASING. commit 6fbc456fb3f4401ec951a618990f15a84fdfa236 Author: Field G. Van Zee Date: Thu Oct 25 13:20:25 2018 -0500 Added SALT testing to Travis CI. Details: - Modified .travis.yml to automatically employ the simulation of application-level threading within the testsuite, with supporting changes to common.mk, the top-level Makefile, and travis/do_testsuite.sh. - Added a new pair of input files to testsuite directory with the '.salt' suffix (similar to those with the '.fast' suffix) for testing application-level threading. - Updated docs/BuildSystem.md to document the new make targets 'testblis-salt' and 'checkblis-salt'. commit 0e27963a6770e6b64f3299ad0613d5df45d8b6ae Author: Field G. Van Zee Date: Wed Oct 24 12:16:19 2018 -0500 Add bli_pthread_mutex_trylock(). Details: - Added the missing bli_pthread_mutex_trylock() function and prototype to the non-Windows sections of bli_pthread.c and .h. This function isn't needed by BLIS, but I figured why not make the Windows and non-Windows sections consistent with one another. commit 4b683740c12f83804a51ec610b16ce28607d5c85 Author: Field G. Van Zee Date: Wed Oct 24 11:56:16 2018 -0500 Defined bli_pthread_cond_*() and related defs. Details: - Added function definitions for bli_pthread_cond_*() as well as related types and constants to bli_pthread.c, and corresponding prototypes to bli_pthread.h. commit 4b4f8072b9bb495b3e01d45698b0bad3dac31ba8 Author: Field G. Van Zee Date: Wed Oct 24 11:31:46 2018 -0500 Define bli_pthreads barrier types on OS X. Details: - Fully define bli_pthreads barrier-related types on OS X. Only typedef those types in terms of pthreads types on non-Windows, non-Apple OSes (i.e. Linux). commit ad98790dcef6bd9aab7f13d615b987b5daa58757 Author: Field G. Van Zee Date: Tue Oct 23 20:35:05 2018 -0500 Fix names of Windows pthread initializer macros. Details: - Renamed the PTHREAD_ initializer macros in the Windows cpp case to use BLIS_ prefixes to match their non-Windows counterparts. commit 06c23954e6b17219a50c3d37821544a46defaf89 Author: Field G. Van Zee Date: Tue Oct 23 19:16:54 2018 -0500 Defined unified bli_pthreads_*() API for all OSes. Details: - Expanded the bli_pthread_*() -> pthread_*() wrappers in frame/thread/bli_pthread.c to include cases for Windows taken from frame/base/bli_pthread_wrap.c. Now, bli_thread_*() is always defined and always used by BLIS and the BLIS testsuite (in lieu of calling pthreads directly, as before). The implementation used in this new API depends on whether we are building for Windows, and to a lesser extent, whether we are building on OS X. For the core API, Windows uses Windows threads, non-Windows (Linux, OS X) uses pthreads. OS X and Windows get barriers implemented in terms of other bli_pthread_*() functions, and Linux gets barriers implemented in terms of pthread_barrier*(). This commit addresses issue #273. - Fixed a bug in the Linux definition of bli_pthread_mutex_unlock(), which was erroneously calling pthread_mutex_lock(). - Minor changes to configure so that the auto-detection executable can be built given the above changes (most notably, turning on POSIX extensions via -D_GNU_SOURCE). - Removed temporary play-test code for shiftd that accidentally got committed into test/3m4m/test_gemm.c. commit 0ae9585da1e3db1cf8034d4b16305a5883beb0d3 Author: pradeeptrgit Date: Tue Oct 23 09:36:23 2018 +0530 Update version number to 1.2 Change-Id: Ibb31f6683cdecca6b218bc2f0c14701d7e92ebf3 commit eac7d267a017d646a2c5b4fa565f4637ebfd9da7 Author: Field G. Van Zee Date: Mon Oct 22 18:10:59 2018 -0500 Unconditionally define bli_l3_thread_entry(). Details: - Define a dummy bli_l3_thread_entry() function when multithreading is disabled altogether, or enabled via OpenMP. This function was originally necessary when multithreading is enabled via pthreads. By defining the function no matter the threading options given, it is less likely that an AppVeyor Windows build will complain due to a missing symbol in the DLL. (To be clear: AppVeyor was working fine before, but a problem may have arisen if it were switched to an OpenMP build.) - Removed the prototype for bli_l3_thread_entry() from bli_thrcomm_pthreads.c and placed it in bli_thrcomm.h. - Regenerated the symbols list file build/libblis-symbols.def. commit 4ee986f0a74207f4ca29df077929134725d62b80 Author: Field G. Van Zee Date: Mon Oct 22 14:09:44 2018 -0500 Added mixed-datatype testing to Travis CI (#271). Details: - Modified .travis.yml to automatically test the mixed-datatype support of the gemm operation, with supporting changes to common.mk, the top-level Makefile, and travis/do_testsuite.sh. - Added a new pair of input files to testsuite directory with the '.mixed' suffix (similar to those with the '.fast' suffix) for testing mixed-datatype gemm. - Updated docs/BuildSystem.md to document the new make targets 'testblis-md' and 'checkblis-md'. commit c3c6ebc9c6244053d654a9b0c955acb2fef42ee8 Author: Field G. Van Zee Date: Sun Oct 21 18:48:54 2018 -0500 Fixed thrinfo_t printing for small problems. Details: - Fixed a bug in the code that prints out the communicator and work ids from the various threads' thrinfo_t nodes. This bug manifested when the dimension being parallelized was not large enough such that every thread was assigned actual work (since the minimum amount of work is determined by the register blocksize in the dimension being parallelized). In those cases, the threads that receive no work in that dimension do not finish building their thrinfo_t tree, leaving lower-level nodes non-existent. (The bug itself was usally observed as a segfault when the printing code attempted to dereference all the way down the thrinfo_t tree.) The solution involves explicitly checking each node as it is dereferenced, and if at any time NULL is found, all subsequent communicator and work ids are set to -1. commit 73a222c0d99dcc221be7dea10eaebf844f31f72e Author: Field G. Van Zee Date: Sat Oct 20 14:13:04 2018 -0500 Minor edits to 'configure --help' text. commit 14f3d5e6df183819a0c393b2661ad15df0786544 Author: Field G. Van Zee Date: Fri Oct 19 20:39:35 2018 -0500 Refresh libblis-symbols.def post-merge 090e4f0. commit 090e4f08fc2f429a1b2db77b0a6f8276f892a7ac Merge: c9be5889 0854e880 Author: Field G. Van Zee Date: Fri Oct 19 18:41:10 2018 -0500 Merge branch 'master' into dev commit 0854e880b0848e0c2e3d0644c93c80b0fd13c0dc Merge: 4e38a8d4 343a2715 Author: Field G. Van Zee Date: Fri Oct 19 18:05:00 2018 -0500 Merge pull request #261 from flame/win-pthreads Implement missing pthreads function on Windows commit c9be5889fbe947c64ef75740662e4d63032f4c35 Author: Field G. Van Zee Date: Fri Oct 19 17:42:40 2018 -0500 Added "Known issues" section to Multithreading.md. Details: - Added known issues section to Multithreading.md. - Trivial changes to MixedDatatypes.md, Sandboxes.md. commit 343a2715ebee28d250ee41b914abdcd1dc77c344 Author: Field G. Van Zee Date: Fri Oct 19 16:59:19 2018 -0500 Whitespace changes to configure, bli_pthread_wrap. Details: - Mostly whitespace changes (spaces to tabs) to configure and bli_pthread_wrap.c and .h. commit 3678a1cd518df9447b4b1ea86885eb2ba8abcf6e Merge: 85397cd4 4e38a8d4 Author: Field G. Van Zee Date: Fri Oct 19 16:11:31 2018 -0500 Merge branch 'master' into win-pthreads commit 4e38a8d4eebb18ead74e644fac76a4fde8e7f6c6 Author: Field G. Van Zee Date: Fri Oct 19 15:54:15 2018 -0500 Implemented python version checking in configure. Details: - Added python version checking to configure script. (Recall that python is needed to execute the flatten-headers.py script.) Minimum versions of python needed are currently as follows: python2: 2.7 or later python3: 3.5 or later The standard search order for python interpeters is: python python3 python2 The PYTHON environment variable is also supported and will be checked before the standard search order list. - Updated BuildSystem.md to include: a minimum make version; mention that the C compiler must actually be a C99 compiler; and the caveat that Windows builds do not require pthreads since BLIS can provide an implementation of pthreads internally. commit 85397cd4fa52f6c4c33f4fb715478c55533c680e Author: Field G. Van Zee Date: Fri Oct 19 13:12:43 2018 -0500 Added explanatory comment to bli_pthread.c. Details: - Added a verbose comment to bli_pthread.c that explains why a bli_ wrapper to pthreads APIs is useful. commit 53c07035ef61cc9b8469636d4d8fa5085f37652d Author: Field G. Van Zee Date: Fri Oct 19 12:53:03 2018 -0500 Refresh libblis-symbols.def from bb6df28. Details: - Forgot to regenerate the symbols file after the previous commit (bb6df281) in which shiftd operation was introduced. commit 473ce54f5fbea4860ac0514e7e8b022c1ea03e63 Author: Field G. Van Zee Date: Thu Oct 18 19:03:56 2018 -0500 Added bli_pthread_*() API. Details: - Defined a bli_pthread_*() API so that the testsuite, when being linked against a Windows DLL, will be able to access pthreads functionality without those pthreads functions being explicitly exported by the DLL. Instead, we export the bli_pthread_*() layer, which uses types and functions that are identical to pthreads, but adds a 'bli_' prefix. Only a few basic functions are present in the bli_pthreads_*() API for now. Thanks to Devin Matthews and Isuru Fernando for their help on a related PR (#261) that this commit will hopefully facilitate. - Updated testsuite so that it calls bli_pthread_*() layer instead of pthread_*() functions directly. - Regenerated build/libblis-symbols.def. - Comment updated to build/regen-symbols.sh. commit bb6df2814fcaa2fa62a549379f61be2f8667a598 Author: Field G. Van Zee Date: Thu Oct 18 17:11:39 2018 -0500 Defined a new level-1d operation: shiftd. Details: - Defined a new level-1d operation called 'shiftd', including object and typed APIs. This operation adds a scalar value to every element along an arbitrary diagonal of a matrix. Currently, shiftd is implemented in terms of the addv kernel. (The scalar is passed in as the x vector with an increment of zero.) - Replaced ad-hoc usage of setd and addd (after creating a temporary matrix object) with use of shiftd, which is much more concise, in various test driver files in the testsuite. Similar changes were made to the standalone test drivers and the example code. - Added documentation entries in BLISObjectAPI.md and BLISTypedAPI.md for bli_shiftd() and bli_?shiftd(), respectively. - Added observed object properties to level-1d documentation in BLISObjectAPI.md. commit 53e0a0c9b38e8525c7224e280342ef56328af567 Merge: 1c7247b6 ec676799 Author: Field G. Van Zee Date: Thu Oct 18 14:54:59 2018 -0500 Merge branch 'master' into win-pthreads commit ec67679990660a60362a49406595383672812287 Author: Field G. Van Zee Date: Thu Oct 18 14:27:02 2018 -0500 Refreshed Windows symbol list; added regen script. Details: - Moved windows/build/libblis-symbols.def to build/libblis-symbols.def. Updated link commands in common.mk accordingly. - Added a new script build/regen-symbols.sh that will regenerate the libblis-symbols.def file in its new location after building a haswell-targeted shared library. Thanks to Isuru Fernando for providing the symbol generation command. - Ran the new script to refresh the symbols file. commit fdad54ab8eee4a7efd04ec4afb3e6902eb22e60a Author: Field G. Van Zee Date: Thu Oct 18 12:43:22 2018 -0500 Removed old symbol from libblis-symbols.def. Details: - Removed bli_gemm_ker_var1() from windows/build/libblis-symbols.def since this function is no longer compiled. commit 49d3f9fcbb4a75553439f97c099ea48d85763eea Merge: 779d64dc 3c527256 Author: Field G. Van Zee Date: Wed Oct 17 18:00:40 2018 -0500 Merge branch 'master' into dev commit 3c52725693d0d7726e1c8fb224f9b1ef786db8b9 Author: Field G. Van Zee Date: Wed Oct 17 14:56:22 2018 -0500 Renamed/moved l3 zen ukernels to haswell kernel set. Details: - Renamed the microkernels in kernels/zen/3 to kernels/haswell/3 and then updated the file contents to use the 'haswell' infix. - Updated bli_cntx_init_zen.c and bli_cntx_init_haswell.c according to above function renames. - Moved/updated the corresponding prototypes in bli_kernels_zen.h to bli_kernels_haswell.h. - Updated config_registry according to above changes. - NOTE: This rename reflects the fact that haswell microkernels are specifically written to overcome the floating-point latency for FMA instructions on Intel Haswell-like architectures, which can issue two FMA instructions per cycle. These ukernels happen to work fine on AMD Zen-based architectures. However, Zen only issues one FMA per cycle, which, while halving its floating-point throughput, gives it extra flexibility in the design of its microkernels--namely, mr and nr can be smaller and still overcome the floating-point latency for those single-issue cores. A smaller value of mr and nr allows for a larger value of kc, which may be useful in some situations. In the future, we may write such Zen-specific microkernels to take advantage of this additional flexibility. commit 71c5832d5f5596f25204980803423d08143a4010 Author: Field G. Van Zee Date: Wed Oct 17 14:11:01 2018 -0500 Consolidated slab/rr-explicit level-3 macrokernels. Details: - Consolidated the *sl.c and *rr.c level-3 macrokernels into a single file per sl/rr pair, with those files named as they were before c92762e. The consolidation does not take away the *option* of using slab or round-robin assignment of micropanels to threads; it merely *hides* the choice within the definitions of functions such as bli_thread_range_jrir(), bli_packm_my_iter(), and bli_is_last_iter() rather than expose that choice explicitly in the code. The choice of slab or rr is not always hidden, however; there are some cases involving herk and trmm, for example, that require some part of the computation to use rr unconditionally. (The --thread-part-jrir option controls the partitioning in all other cases.) - Note: Originally, the sl and rr macrokernels were separated out for clarity. However, aside from the additional binary code bloat, I later deemed that clarity not worth the price of maintaining the additional (mostly similar) codes. commit 57eab3a4f0e43099fc2ff189df9fcc0d7801c2cd Author: Field G. Van Zee Date: Wed Oct 17 11:29:20 2018 -0500 CREDITS file update. commit 6722ec21817cbab9d86ee63f00984eb407b5e627 Author: Ye Luo Date: Wed Oct 17 11:26:00 2018 -0500 Fix bgclang compilation on BGQ (#270) * Fix bgq kernels * Support bgq with bgclang commit 1c7247b6d146fc728d7c4240e4e069e33f8f8868 Merge: c1bc5530 6c5a1aaf Author: Devin Matthews Date: Tue Oct 16 14:44:32 2018 -0500 Merge branch 'win-pthreads' of github.com:flame/blis into win-pthreads commit c1bc5530d51bf55b4aa3c35165f6d4452a0fd779 Author: Devin Matthews Date: Tue Oct 16 14:44:10 2018 -0500 Don't call pthread_once in auto-detect. commit b9c61d03f542a2e92551ff0595415bec3076ab25 Merge: 5a1e461f 3612ecac Author: Field G. Van Zee Date: Tue Oct 16 14:39:57 2018 -0500 Merge branch 'nested-omp-patch' commit 5a1e461ffe09ed200ee2fc7aafccf6dd7e8c0080 Author: Field G. Van Zee Date: Tue Oct 16 14:21:45 2018 -0500 Execute flatten-headers.py via $(PYTHON). Details: - Execute build/flatten-headers.py python script via $(PYTHON) in common.mk. This allows distributions that define the current/preferred python interpreter in the PYTHON environment variable to use that interpreter when executing flatten-headers.py. Thanks to Isuru Fernando for this suggestion, and for Dave Love for submitting the initial issue/request. commit 6c5a1aaff540b19672e91501e894ed695aee322b Author: Devin Matthews Date: Tue Oct 16 10:15:59 2018 -0500 Fix type in bli_pthread_wrap.c commit 29e6245816760b1bd4ac738d7d3e11a9d9d13473 Merge: 0b73209f ed657714 Author: Devin Matthews Date: Tue Oct 16 10:12:25 2018 -0500 Merge branch 'master' into win-pthreads commit 0b73209f6b22cc024169146d343627f6999b63d8 Author: Devin Matthews Date: Tue Oct 16 10:02:06 2018 -0500 Add missing argument to WaitForSingleObject and use $is_win in configure to turn off pthreads. commit ed65771482a705f7ed028d822489766327b44e76 Author: Field G. Van Zee Date: Mon Oct 15 17:54:45 2018 -0500 Fixed merge fail on testsuite threading macros. Details: - Applied the following C preprocessor macro renames BLIS_DEFAULT_MR_THREAD_MAX -> BLIS_THREAD_MAX_IR BLIS_DEFAULT_NR_THREAD_MAX -> BLIS_THREAD_MAX_JR BLIS_DEFAULT_M_THREAD_RATIO -> BLIS_THREAD_RATIO_M BLIS_DEFAULT_N_THREAD_RATIO -> BLIS_THREAD_RATIO_N in src/test_libblis.c. This is apparently the result of a failure by git to properly merge the 'master' and 'amd' branches in the previous commit. (The 'master' branch contained a commit, 53a9ab1, in which these same cpp macros were renamed throughout the source distribution. commit dc5fd898af8c74c2e2a75fc647157da0d04dd922 Merge: 667d3929 637c2ce7 Author: Field G. Van Zee Date: Mon Oct 15 17:41:35 2018 -0500 Merge branch 'amd' commit 779d64dc3091dea6b7530283304e52878151d218 Author: Field G. Van Zee Date: Mon Oct 15 17:13:18 2018 -0500 Added entry for xpbym to input.operations.fast. Details: - Forgot to add an entry for the new xpbym operation to input.operations.fast in previous commit. commit 5fec95b99f61761963834f62a9867f797687813c Author: Field G. Van Zee Date: Mon Oct 15 16:37:39 2018 -0500 Implemented mixed-datatype support for gemm. Details: - Implemented support for gemm where A, B, and C may have different storage datatypes, as well as a computational precision (and implied computation domain) that may be different from the storage precision of either A or B. This results in 128 different combinations, all which are implemented within this commit. (For now, the mixed-datatype functionality is only supported via the object API.) If desired, the mixed-datatype support may be disabled at configure-time. - Added a memory-intensive optimization to certain mixed-datatype cases that requires a single m-by-n matrix be allocated (temporarily) per call to gemm. This optimization aims to avoid the overhead involved in repeatedly updating C with general stride, or updating C after a typecast from the computation precision. This memory optimization may be disabled at configure-time (provided that the mixed-datatype support is enabled in the first place). - Added support for testing mixed-datatype combinations to testsuite. The user may test gemm with mixed domains, precisions, both, or neither. - Added a standalone test driver directory for building and running mixed-datatype performance experiments. - Defined a new variation of castm, castnzm, which operates like castm except that imaginary values are not touched when casting a real operand to a complex operand. (By contrast, in these situations castm sets the imaginary components of the destination matrix to zero.) - Defined bli_obj_imag_is_zero() and substituted calls in lieu of all usages of bli_obj_imag_equals() that tested against BLIS_ZERO, and also simplified the implementation of bli_obj_imag_equals(). - Fixed bad behavior from bli_obj_is_real() and bli_obj_is_complex() when given BLIS_CONSTANT objects. - Disabled dt_on_output field in auxinfo_t structure as well as all accessor functions. Also commented out all usage of accessor functions within macrokernels. (Typecasting in the microkernel is still feasible, though probably unrealistic for now given the additional complexity required.) - Use void function pointer type (instead of void*) for storing function pointers in bli_l0_fpa.c. - Added documentation for using gemm with mixed datatypes in docs/MixedDatatypes.md and example code in examples/oapi/11gemm_md.c. - Defined level-1d operation xpbyd and level-1m operation xpbym. - Added xpbym test module to testsuite. - Updated frame/include/bli_x86_asm_macros.h with additional macros (courtsey of Devin Matthews). commit 3612ecac98a9d36c3fcd64154121d420bb69febd (origin/nested-omp-patch) Author: Field G. Van Zee Date: Thu Oct 11 15:16:41 2018 -0500 Added comments to nested OpenMP handling code. Details: - Added comments to bli_thrcomm_openmp.c relating to changes made in 6ac0c80 and 1064d79. commit 667d3929ee20e94849b4e25b693b4037b7e3f350 Author: Field G. Van Zee Date: Thu Oct 11 11:47:57 2018 -0500 Added Fortran APIs for some thread functions. Details: - Defined Fortran-77 compatible APIs for bli_thread_set_num_threads() and bli_thread_set_ways(). These wrappers are defined in frame/compat/blis/thread/b77_thread.c. Thanks to Kay Dewhurst for suggesting these new interfaces. - Added missing prototype for bli_thread_set_ways() in bli_thread.h and removed prototypes for non-existent functions bli_thread_set_*_nt(). - CREDITS file update. commit 1064d79711f03a0541b92d8b8b9b7e25e04097a5 Author: Devin Matthews Date: Thu Oct 11 11:14:25 2018 -0500 Adjust rntm_t struct as well. commit 6ac0c805609b85616ddb32e50101c4f9feb25a35 Author: Devin Matthews Date: Thu Oct 11 10:45:07 2018 -0500 Fix OMP nesting problem. Detect when OpenMP uses fewer threads than requested and correct accordingly, so that we don't wait forever for nonexistent threads. Fixes #267. commit 78a6935483409ae277c766406e175772e820b1de Author: sraut Date: Thu Oct 11 10:49:40 2018 +0530 Added comments for the change in syrk small matrix change. Change-Id: I958939e9953323730da49ef07d1b10e578837d82 commit 53a9ab1c85be14dcfd2560f5b16e898e3e258797 Author: Field G. Van Zee Date: Wed Oct 10 15:11:09 2018 -0500 Renamed thread auto-factorization macro constants. Details: - Renamed the following C preprocessor macros whose fallback/default values are specified within frame/include/bli_kernel_macro_defs.h: BLIS_DEFAULT_MR_THREAD_MAX -> BLIS_THREAD_MAX_IR BLIS_DEFAULT_NR_THREAD_MAX -> BLIS_THREAD_MAX_JR BLIS_DEFAULT_M_THREAD_RATIO -> BLIS_THREAD_RATIO_M BLIS_DEFAULT_N_THREAD_RATIO -> BLIS_THREAD_RATIO_N - Renamed the above cpp macro overrides within the knl, skx, and zen sub-configurations, as well as invocations of those macros in bli_rntm.c. - Moved config/zen/bli_kernel.h to an 'old' directory as it is no longer used by any code within BLIS. commit 637c2ce794b0414ba8b25e9a452f7d64f825d63a Author: Field G. Van Zee Date: Tue Oct 9 17:18:04 2018 -0500 Updated column index range for irun.py -q. Details: - Forgot to apply the column index range fix in 10f179f to situations when "quiet" mode (-q) is requested. This commit applies the new column index range modifications to the quiet case. commit e2a59400bdda7ed7ee0ff00edea70c00ed593b6c Author: Field G. Van Zee Date: Tue Oct 9 15:29:48 2018 -0500 Allow trsm_l parallelism in the jc loop. Details: - Previously, trsm was consolidating all ways of parallelism into the jr loop. This was unnecessary and to some degree detrimental on some types of hardware. Now, any parallelism bound for the jc loop will be applied to the jc loop, while all other loops' parallelism is funneled to the jr loop. Thanks to Devangi Parikh for helping investigate this issue and suggesting the fix. - NOTE: This change affects only left-side trsm. However, currently right-side trsm is currently implemented in terms of the left-side case, and thus the change effectively applies to both left and right cases. commit f1dba506c970f14e612580d3c171e7c5ffd0a5fb Author: Field G. Van Zee Date: Mon Oct 8 17:59:41 2018 -0500 Output threading status/params from testsuite. Details: - Updated testsuite to output various parameters related to parallelism in BLIS. These parameters include: - threading status: disabled, openmp, or pthreads; - thread partitioning for jr/ir loops: slab or rr (round-robin); - ways of parallelism from environment variables, and also actual values used by gemm, herk, trmm_l, trmm_r, trsm_l, and trsm_r for square problems (assuming all dimensions are set to 1000); - automatic thread factorization parameters. - Also output the status of two relatively new configure-time options: libmemkind and the sandbox. commit 10f179fb13fc1179921a4ef8efdd2174f01e07da Author: Field G. Van Zee Date: Mon Oct 8 14:36:38 2018 -0500 Updated irun.py to use updated column index range. Details: - Updated the irun.py script so that it updates the matlab column index range (if found) to reflect the additional columns of data that are substituted in. Thanks to Devangi Parikh for recognizing and reporting this issue. commit c244a716c97849dee41f52b5f424116aae1b710b Author: Field G. Van Zee Date: Sun Oct 7 20:59:40 2018 -0500 Added missing -r option to configure --help output. Details: - Added inadvertantly-omitted mention of -r option-equivalent to --thread-part-jrir to the output for 'configure --help'. Also made minor edits to the same text. commit c92762ecdca1eb0b08c8acd583b4739a1e3fbd39 Author: Field G. Van Zee Date: Sun Oct 7 20:30:32 2018 -0500 Added option of slab or rr partitioning in jr/ir. Details: - Updated existing macrokernel function names and definitions to explicitly use slab assignment of micropanels to threads, then created duplicate versions of macrokernels that explicitly use round-robin assignment instead of slab. NOTE: As in ac18949, trsm_r macrokernels were not substantially updated in this commit because they are currently disabled in bli_trsm_front.c. - Updated existing packing function (in blk_packm_blk_var1.c) to explicitly use slab partitioning, and then duplicated for round-robin. - Updated control tree initialization to use the appropriate macrokernel and packm function pointers depending on which method (slab or rr) was enabled at configure-time. - Updated configure script to accept new --thread-part-jrir=[slab|rr] option (-m [slab|rr] for short), which allows the user to explicitly request either slab or round-robin assignment (partitioning) of micropanels to threads. - Updated sandbox/ref99 according to above changes. - Minor updates to build/add-copyright.py. commit 98e01ea04bfe1032e5bd4781043afd84f864a19e Merge: ac18949a 541b8a3b Author: Field G. Van Zee Date: Thu Oct 4 20:44:12 2018 -0500 Merge branch 'master' into amd commit 541b8a3b3e9af4078f5e6fb2f9608d681839952a Author: Field G. Van Zee Date: Thu Oct 4 20:39:06 2018 -0500 Removed 1h short-circuit from bli_clock_min_diff(). Details: - Removed a guard from bli_clock_min_diff() that would return 0 if the time delta was greater than 60 minutes. This was originally intended to disregard extremely large values under the assumption that the user probably didn't intend to run a test that long. However, since it is in bli_clock_min_diff(), it doesn't actually help short-circuit an implementation that is hanging or looping infinitely, since such an implementation would first have to finish before the bli_clock_min_diff() is called. Thanks to Kiran Varaganti for reporting this issue. commit f0c3ef359f7c6c1687fb2671cb35deb346e00597 Author: Kiran V Date: Thu Oct 4 16:32:21 2018 +0530 This is a fix to floating-point exception error for BLIS SGEMM with larger matrix sizes. BUG No: CPUPL-197 fixed by Thangaraj Santanu The bli_clock_min_diff() function in BLIS assumed that if the time taken is greater than 1 hour then the reading must be wrong. However this is not the case in general, while the other checks such as time taken closer to zero or nsec is ofcourse valid. gerrit review: http://git.amd.com:8080/#/c/118694/1/frame/base/bli_clock.c Change-Id: I9dc313d7c5fdc20684f67a516bf3237de3e0694a commit 8bf30eb4735872388b5317883d99b775a344ce25 Author: Devangi N. Parikh Date: Wed Oct 3 22:22:29 2018 -0400 Fixed runme.sh in test/studies/thunderx2 Details: - Fixed the setting of threads for a single core run. commit f6f2456ba2afa8f85f43c7c2c90acc439d61d94f Author: Devangi N. Parikh Date: Wed Oct 3 21:43:46 2018 -0400 Fixed the Makefile in test/studies/thunderx2 Details: - Fixed target for make-all-st and make-all-mt so that the armpl targets are built commit 743a1a6dec1bd3908f0f15513b501c9bd59715b3 Author: Field G. Van Zee Date: Wed Oct 3 14:40:10 2018 -0500 Fixed misleading version query from gcc 7+. Details: - gcc 7 introduced new behavior to the -dumpversion option whereby only the major version component is output. However, as part of this change, gcc 7 also introduced a new option, -dumpfullversion, which is guaranteed to always output the major, minor, and revision numbers. If we are using gcc 7 or later, we re-query the version string with this new option and then re-parse the result so as to avoid misleading output from configure (e.g. using gcc 7.3.0 is reported as 7.7.7). commit de07840ba5672b9d7b2ed2b918974e98c3f249fb Author: Field G. Van Zee Date: Wed Oct 3 13:57:25 2018 -0500 Whitespace, https updates to README.md. Details: - Reformatted to fit all lines within 80 columns, unless a link is too long to fit on a single line. - Changed some links from http to https. commit 80a8b3dd8034ec8bc03d31be3f9c837c3f6fc94b Author: sraut Date: Wed Oct 3 15:30:33 2018 +0530 Review comments incorporated for small TRSM. Change-Id: Ia64b7b2c0375cc501c2cb0be8a1af93111808cd9 commit b8dfd82e0d1afda4ee5436662d63515a59b2dee3 Author: Devin Matthews Date: Tue Oct 2 15:37:12 2018 -0500 Get pthreads via blis.h in the test driver. commit d0c0c20b7bd3ecf914b5910a50f618fb7d7aa355 Author: Devin Matthews Date: Tue Oct 2 15:16:00 2018 -0500 There seems to be a problem with _POSIX_BARRIERS on Travis. commit 0904d9e4df0c8a256ac35c491f14a587ebe9fca2 Author: Devin Matthews Date: Tue Oct 2 15:04:36 2018 -0500 *Always* use Windows primitives instead of pthreads. commit 998317d309934cd7129f8c818ea6e5f07534ebc8 Author: Devin Matthews Date: Tue Oct 2 14:43:24 2018 -0500 Remove pthreads from appveyor build. commit 627d0c5bfd4b7b149803587391c93b164c11ced5 Author: Devin Matthews Date: Tue Oct 2 14:40:55 2018 -0500 Combine the alternative barrier implementation for macOS with the pthread wrapper for Windows. Also implement pthread_{create,join} for Windows. commit 81d2c064a209df7eca7d6103696ca3a137a7f82e Author: Devin Matthews Date: Tue Oct 2 11:46:36 2018 -0500 Add wrapper for basic pthreads functionality (mutex, once) with MSVC. commit d33f130ea621fca1dccb30631f454d237918eb04 Author: Devin Matthews Date: Tue Oct 2 11:45:43 2018 -0500 Some configure changes: 1) Allow environment variables to be set anywhere in the argument list. 2) Allow any environment variable to be set. 3) Allow LIBPHTREAD to be set to null without getting defaulted to -lpthread. commit 9d5f1c4f3bf70c2c0ea84bfa326a0113ae2d176c Author: Field G. Van Zee Date: Mon Oct 1 17:39:26 2018 -0500 Patch to avoid gcc warning in blastest/f2c/open.c. Details: - Use the modulo operator to limit the size of an integer that is given to sprintf(). This avoids a warning in some versions of gcc about the integer potentially overflowing the available space in the string into which the integer is being printed. commit 0c3cd00ba76de607e807f8deb04b1a2ce18ea7a8 Author: Field G. Van Zee Date: Mon Oct 1 16:18:25 2018 -0500 More README.md updates. Details: - Replaced much of "Getting Started" section with a shortened version of the bullet list of documentation currently shown in the github wiki page. Thanks to Devangi Parikh for her feedback in this change. commit 8eaf34bd23b30a1857a50d7142ee9811895f24bf Author: Field G. Van Zee Date: Mon Oct 1 14:29:07 2018 -0500 Very minor README.md update. commit 599090e0eb41b2706fa1231fa7b90096f3281678 Author: Field G. Van Zee Date: Mon Oct 1 14:04:30 2018 -0500 README.md update. Details: - Added language mentioning SHPC group to Introduction. commit ee46fa3efb6e920fa6c3d0b0601007f5de31deb5 Author: sraut Date: Mon Oct 1 16:30:30 2018 +0530 Small TRSM optimization changes :- 1) single precision small trsm kernels for XAt=B case are further optimized for performance. 2) double precision small trsm kernels for AX=B and XAtB cases are implemented. 3) single precision small trsm kernels for AutX=B are implemented in intrinsics to improve the current performance. Change-Id: Ic9d67ae6d8522615257dde018903f049dcffa2cf commit 08045a6c52b6e025652c5b18eb120c0f4e61cf6f Author: sraut Date: Mon Oct 1 15:38:23 2018 +0530 Corrected the fix made for blastest level-3 failure to check m,n,k non-zero condition in bli_gemm_small.c Change-Id: Idaf9f2327c3127b04a2738ae8a058b83d6c57934 commit ac18949a4b9613741b9ea8e5026d8083acef6fe4 Author: Field G. Van Zee Date: Sun Sep 30 18:54:56 2018 -0500 Multithreading optimizations for l3 macrokernels. Details: - Adjusted the method by which micropanels are assigned to threads in the 2nd (jr) and 1st (ir) loops around the microkernel to (mostly) employ contiguous "slab" partitioning rather than interleaved (round robin) partitioning. The new partitioning schemes and related details for specific families of operations are listed below: - gemm: slab partitioning. - herk: slab partitioning for region corresponding to non-triangular region of C; round robin partitioning for triangular region. - trmm: slab partitioning for region corresponding to non-triangular region of B; round robin partitioning for triangular region. (NOTE: This affects both left- and right-side macrokernels: trmm_ll, trmm_lu, trmm_rl, trmm_ru.) - trsm: slab partitioning. (NOTE: This only affects only left-side macrokernels trsm_ll, trsm_lu; right-side macrokernels were not touched.) Also note that the previous macrokernels were preserved inside of the 'other' directory of each operation family directory (e.g. frame/3/gemm/other, frame/3/herk/other, etc). - Updated gemm macrokernel in sandbox/ref99 in light of above changes and fixed a stale function pointer type in blx_gemm_int.c (gemm_voft -> gemm_var_oft). - Added standalone test drivers in test/3m4m for herk, trmm, and trsm and minor changes to test/3m4m/Makefile. - Updated the arguments and definitions of bli_*_get_next_[ab]_upanel() and bli_trmm_?_?r_my_iter() macros defined in bli_l3_thrinfo.h. - Renamed bli_thread_get_range*() APIs to bli_thread_range*(). commit b952ca8feb6f17f71a4512649c2aa72bdee9c8f4 Author: Field G. Van Zee Date: Fri Sep 28 16:12:32 2018 -0500 CREDITS file update. commit 7d96fc437ebaa9dd2d7071865b5df16402fadd64 Author: Field G. Van Zee Date: Fri Sep 28 15:40:45 2018 -0500 Allow slashes ('/') in version tags. Details: - Updated the configure script to allow slashes in version string. This is needed so that downstream maintainers (such as those for Debian) can create local tags such as "upstream/0.4.1". Thanks to M. Zhou for reporting this issue via PR #256 and providing me the information needed to debug the problem. commit 5fdddf6f37c64da093c7f59e3a85214e819ae652 Author: Field G. Van Zee Date: Fri Sep 28 11:25:54 2018 -0500 Removed 'debian' directory. Details: - Removed the top-level 'debian' directory. This directory is apparently no longer needed (issue #257). Thanks to M. Zhou and Nico Schlömer for their contributions. commit 9814cfdf3157ef4726ee604fc895d56e8063d765 Author: Meghana Date: Fri Sep 28 11:02:39 2018 +0530 fixed blastest level-3 failure by adding ((M&N&K) != 0) to check condition in bli_gemm_small.c Change-Id: I85e4a32996ebb880f3c00bd293edc38f74700fe6 commit 86330953b14c180862deef3ccdcc6431259be27b Merge: 7af5283d 807a6548 Author: praveeng Date: Fri Sep 28 10:08:06 2018 +0530 Resolved conflicts and modified bli_trsm_small.c Change-Id: I578d419cff658003e0fdd4c4cdc93145d951ce31 commit 60b2650d7406d266feffe232c2d5692a9e3886d0 Author: Field G. Van Zee Date: Mon Sep 24 15:04:45 2018 -0500 Added statistics-collecting irun.py script. Details: - Added irun.py script to 'build' directory. This irun.py script is a python script for repeatedly invoking a test driver executable, such as those found in test/3m4m, and replace the performance output column with four columns that aggregate statistics. Specifically, the script reports the minimum, average, maximum, and standard deviation for each problem size. This script is useful especially (though not exclusively) when trying to determine the impact of relatively minor changes to the code, or other small optimizations that may be difficult to distinguish from "noise." One way this "noise" manifests is that a test executable may run slightly slower or faster for all problem sizes (and all implementations) tested by the executable over the life of a single execution. The cause of these minor across-the-board pertubations in the overall performance signatures is unknown, though we hypothesize that it may relate to any number of issues such as operating system scheduling, where in memory the program is loaded, or how the CPU clock frequency is throttled at the time of execution. Regardless of the source of these subtle performance anomalies, the statistical properties reported by the irun.py script help the user to more precisely characterize the underlying performance exhibited by any given test driver, which allows him or her to make better judgments about the true difference in performance between two implementations, or minor changes within a single implementation. commit 807a654888117fb3a27ea36384f1c1c11b882cd5 Author: Field G. Van Zee Date: Thu Sep 20 15:41:05 2018 -0500 Fixed confusing configure message for libmemkind. Details: - Corrected feedback echoed to user by configure when libmemkind is found but not explicitly requested. In these cases, configure would echo a message that it had received an explicit request to enable libmemkind, which was not accurate, even if the end result was the same--that libmemkind is enabled by default when it is found. Thanks To Devangi Parikh for reporting this issue. commit 02adab427c779b0aaf38a5877a5f0246b1909e8f Author: Devangi N. Parikh Date: Thu Sep 20 14:38:50 2018 -0400 Created a 'thunderx2' subdirectory within test/studies Details: - Created a 'thunderx2' subdirectory within test/studies to house various level-3 test driver used to measure performance on ThunderX2. commit d7537fb51dac0636591fc7c68261a2322642ab3c Merge: dad07245 c03728f1 Author: Field G. Van Zee Date: Wed Sep 12 15:24:20 2018 -0500 Merge branch 'dev' commit dad07245dbcfaf35232ec379ba756eb133c361c1 Author: Devangi N. Parikh Date: Wed Sep 12 04:16:58 2018 -0500 Fixed yet another bug in runme script in test/studies Details: - Fixed another copy-paste bug commit e669057fe35f2037d8111af687d84a0ecf6d7a2a Author: Devangi N. Parikh Date: Tue Sep 11 22:29:42 2018 -0500 Fixed bug in runme script in test/studies Details: - Fixed bug in runme script for skx studies that set the number of threads incorrectly commit 232fdc3df3e01ae3f86d53767bd14eb93b511e6e Author: Devangi N. Parikh Date: Mon Sep 10 18:45:50 2018 -0500 Updated runme script in test/studies. Details: - Updated runme script for skx studies to run multithreading tests on 1 and 2 sockets. commit c03728f1f45edb5e434db90ab8a77ba0184a682b Author: Field G. Van Zee Date: Mon Sep 10 17:54:27 2018 -0500 Various minor cleanups. Details: - Rewrote bli_winsys.c to define bli_setenv() and bli_sleep() unconditionally, but differently for Windows and non-Windows, but then disabled the definition of bli_setenv() entirely since BLIS no longer needs to set environment variables. Updated bli_winsys.h accordingly, and call bli_sleep() from within testsuite instead of sleep() directly. - Use #if !defined(_POSIX_BARRIERS) || (_POSIX_BARRIERS != 200809L) instead of #if !defined(_POSIX_BARRIERS) || (_POSIX_BARRIERS < 0) when guarding against local definition of pthread barrier in testsuite. (The description for unistd.h implies that _POSIX_BARRIERS should always be set to 200809L when barriers are supported, though I won't be surprised if we encounter a case in the future where it is set to something else such as 1 while still supported.) - Removed old _VERS_CONF_INST definitions and installation rules in top-level Makefile. These are no longer needed because we no longer output libraries with the version and configuration name as substrings. - Comment/whitespace updates in Makefile, config.mk.in, common.mk, configure, bli_extern_defs.h, and test_libblis.h. - Added mention of 1m to README.md and other trivial tweaks. commit e249a00a82908054ecd307cf602c8801275903e8 Author: Field G. Van Zee Date: Mon Sep 10 16:48:35 2018 -0500 Imported skx dgemm ukernel from skx-redux branch. Details: - Added the new bli_dgemm_skx_asm_16x14.c microkernel from the skx-redux branch, along with appropriate blocksizes in bli_cntx_init_skx.c and a prototype in bli_kernels_skx.h. (Devin has not yet written the sgemm analague, so for now we will continue using the older sgemm ukernel.) - Updated frame/include/bli_x86_asm_macros.h with a minor change that was present within the skx-redux branch. commit e93b01ff60bf9742baa5eefd93e208d1219e7a43 Author: Isuru Fernando Date: Sun Sep 9 15:57:43 2018 -0500 Windows DLL support (#246) * Enable shared * Enable rdp * Add support for dll * Use libblis-symbols.def * Fix building dlls * Fix libblis-symbols.def * Fix soname * Fix Makefile error * Fix install target * Fix missing symbols * Add BLIS_MINUS_TWO * Add path to dll * Fix OSX soname * Add declspec for dll * Add -DBLIS_BUILD_DLL * Replace @enable_shared@ in config * switch to auto for now * blis_ -> bli_ * Remove BLIS_BUILD_DLL in make check * change auto->haswell * enable_shared_01 * Add wno-macro-redefined * print out.cblat3 * BLIS_BUILD_DLL -> BLIS_IS_BUILDING_LIBRARY * Use V=1 * Remove fpic for windows * Remember LIBPTHREAD * Remove libm for windows * Remember AR * Fix remembering libpthread * Add Wno-maybe-uninitialized in only gcc * Don't do blastest for shared for now * Fix install target And remove unnecessary change * test auto and x86_64 * Fix install target again * Use IS_WIN variable * Remove leading dot from LIBBLIS_SO_MAJ_EXT * Make is_win yes/no * Add comments for windows builds * Change if else blocks location commit 1330d5c4bc3b644ec0af54c3939a5b9f00eacd9c Author: Field G. Van Zee Date: Fri Sep 7 19:37:59 2018 -0500 Employ "user" cflags for tl Makefile test targets. Details: - Use get-user-cflags-for() to generate cflags when compiling BLAS test drivers and BLIS testsuite from top-level Makefile. Meant to include these changes in previous commit (4b5437e). Thanks to Isuru Fernando for pointing out this oversight. commit 4b5437ec7afb2befffffbb83f7872bcb4fc61e51 Author: Field G. Van Zee Date: Fri Sep 7 17:24:32 2018 -0500 Define a cpp macro specific to BLIS compilation. Details: - Tweaked the cflags functions in common.mk so that a new preprocessor macro, BLIS_IS_BUILDING_LIBRARY, is defined, but only when BLIS itself is being built. This macro will not be defined when, for example, the testsuite or example code compiles code local to those applications. This was done in part by defining a new cflags function get-user-cflags-for(), which is now the designated function for application Makefiles if they wish to inherit a basic set of CFLAGS from BLIS. (The compiler flags returned are identical to that of get-frame-cflags-for() except that -DBLIS_IS_BUILDING_LIBRARY is omitted.) - Updated all test driver-like makefiles to call get-user-cflags-for() instead of get-frame-cflags-for(). commit cc2cca4f56eb30212a0dce3e5c121e64d9e59560 Merge: e19e7212 fb81c7fc Author: Field G. Van Zee Date: Thu Sep 6 17:12:13 2018 -0500 Merge branch 'dev' commit e19e7212872da3d464734199193436faa51f0da0 Merge: 97965b09 b3d0702c Author: Jeff Hammond Date: Thu Sep 6 14:58:49 2018 -0700 Merge pull request #244 from kali/pthread-barrier-osx add an adhoc impl for pthread_barrier commit b3d0702cf2ef6dda19a23dd8a677be1b6f73c322 Merge: 4e7d0670 97965b09 Author: Jeff Hammond Date: Thu Sep 6 14:58:23 2018 -0700 Merge branch 'master' into pthread-barrier-osx commit 4e7d06700f176a62952d7d51e41fdcbc6b7a9d5f Author: Mathieu Poumeyrol Date: Thu Sep 6 23:48:31 2018 +0200 second __APPLE__ commit fb81c7fc665d68e6a2add163feb29acc0bce8936 Author: Field G. Van Zee Date: Thu Sep 6 16:29:39 2018 -0500 Defined cortexa53 sub-configuration. Details: - Added a new sub-configuration 'cortexa53', which is a mirror image of cortexa57 except that it will use slightly different compiler flags. Thanks to Mathieu Poumeyrol for making this suggestion after discovering that the compiler flags being used by cortexa57 were not working properly in certain OS X environments (the fix to which is currently pending in pull request #245). commit 24ecc0d94aaa9ab4df1ae6d199c4ec6d7783169f Author: Mathieu Poumeyrol Date: Thu Sep 6 22:10:16 2018 +0200 use _POSIX_BARRIERS instead of __APPLE__ commit 97965b09059a610db06fb7a22bdfa79c0d37d673 Author: Mathieu Poumeyrol Date: Thu Sep 6 21:10:29 2018 +0200 cortexa9 and cortexa53 travis build + qemu test (#245) commit a6802eab7d94b5a9de633c53beca8245b74f5dc6 Author: Mathieu Poumeyrol Date: Thu Sep 6 17:16:35 2018 +0200 reinstantiate test on macos commit d688a2b7e5a19cba44ea398a99e325e19b8fce50 Author: Mathieu Poumeyrol Date: Thu Sep 6 15:25:16 2018 +0200 add an adhoc impl for pthread_barrier commit ab9f9e684dc3ffbb70cc45b21c67af5d916919e5 Author: Field G. Van Zee Date: Thu Aug 30 15:14:02 2018 -0500 CHANGELOG update (0.4.1) commit 10fd614031307c46db3d893528d4e5fc31f490b3 (tag: 0.4.1) Author: Field G. Van Zee Date: Thu Aug 30 15:13:59 2018 -0500 Version file update (0.4.1) commit 08dd67c4b21244851f8416bd59159bea7a9c5b3d Author: Field G. Van Zee Date: Thu Aug 30 15:12:13 2018 -0500 ReleaseNotes.md update in advance of next version. commit 4fa4cb0734e7de6505b5d6f1aeef3a5d5c89dcbb Author: Field G. Van Zee Date: Wed Aug 29 18:06:41 2018 -0500 Trivial comment header updates. Details: - Removed four trailing spaces after "BLIS" that occurs in most files' commented-out license headers. - Added UT copyright lines to some files. (These files previously had only AMD copyright lines but were contributed to by both UT and AMD.) - In some files' copyright lines, expanded 'The University of Texas' to 'The University of Texas at Austin'. - Fixed various typos/misspellings in some license headers. commit b051ffb815baf6c3ece2b5118b679fd9219d5780 Merge: 6f33d9de aaa549f4 Author: Field G. Van Zee Date: Wed Aug 29 17:06:48 2018 -0500 Merge branch 'dev' commit 6f33d9de21fbc2f579846b9104fb9d513753f79c Author: Mathieu Poumeyrol Date: Wed Aug 29 23:48:22 2018 +0200 fix compilation of armv7a kernels (#242) commit 8199e339aefdd27019c7f3d8c99818d375d5400b Author: Field G. Van Zee Date: Mon Aug 27 07:00:12 2018 -0500 Added testsuite threading to input.general.fast. Details: - Added lines associated with the testsuite's new threading option to input.general.fast. This change was intended for the previous commit (10d0735). commit 10d07357afbb2d468837aa97369ef9a6d0610817 Author: Field G. Van Zee Date: Sun Aug 26 20:34:30 2018 -0500 Better thread safety; added threading to testsuite. Details: - Replaced critical sections that were conditional upon multithreading being enabled (via pthreads or OpenMP) with unconditional use of pthreads mutexes. (Why pthreads? Because BLIS already requires it for its initialization mechanism: pthread_once().) This was done in bli_error.c, bli_gks.c, bli_l3_ind.c. Also, replaced usage of BLIS's mtx_t object and bli_mutex_*() API with pthread mutexes in bli_thread.c. The previous status quo could result in a race condition if the application called BLIS from more than one thread. The new pthread-based code should be completely agnostic to the application's threading configuration. Thanks to AMD for bringing to our attention the need for a thread-safety review. - Added an option to the testsuite to simulate application-level multithreading. Specifically, each thread maintains a counter that is incremented after each experiment. The thread only executes the experiment if: counter % n_threads == thread_id. In other words, the threads simply take turns executing each problem experiment. Also, POSIX guarantees that fprintf() will not intermingle output, so output was switched to fprintf() instead of libblis_test_fprintf(). - Changed membrk_t objects to use pthread_mutex_t intead of mtx_t and replaced use of bli_mutex_init()/_finalize() in bli_membrk.c with wrappers to pthread_mutex_init()/_destroy(). - Changed the implementation of bli_l3_ind_oper_enable_only() to fix a race condition; specifically, two threads calling the function with the same parameters could lead to a non-deterministic outcome. - Added #include to bli_cpuid.c and moved the same in bli_arch.c. - Added 'const' to declaration of OPT_MARKER in bli_getopt.c. - Added #include to bli_system.h. - Added add-copyright.py script to automate adding new copyright lines to (and updating existing lines of) source files. commit aaa549f4d1e63929fe2bea023ce849253cfbbb42 Author: Field G. Van Zee Date: Sun Aug 26 20:13:51 2018 -0500 Minor update to configure --help (--sharedir option). Details: - Fixed/tweaked description for --sharedir=SHAREDIR option. commit 573b8ac373f821a65cc8afd51cdbe03b8ec01081 Author: Field G. Van Zee Date: Sun Aug 26 13:51:32 2018 -0500 Fixed copy-paste typo in previous commit. Details: - Fixed a typo in travis/do_testsuite.sh introduced in 62ea1d3. commit 62ea1d33d3bc1e890420a1e828b9d0e87e87533b Author: Field G. Van Zee Date: Sun Aug 26 13:35:53 2018 -0500 Fixed broken out-of-tree builds. Details: - Fixed stale filepaths to check-blastest.sh and check-blistest.sh in travis/do_testsuite.sh and travis/do_sde.sh. - Create a symbolic link to the 'config' directory so that the top-level Makefile can find the configs' make_defs.mk files during out-of-tree builds. - Added additional case handling to out-of-tree scenario to handle situations where files 'Makefile', 'common.mk', or 'config' exist but are not symbolic links. In such cases, configure warns the user and exits. - Homogenized various error messages throughout configure. - Belated thanks to Victor Eijkhout for requesting the feature added in 0f491e9 whereby lesser Makefiles can compile and link against an existing installation of BLIS. commit 0f491e994a7e14d4dfce26e6a51dba2bccad29a3 Author: Field G. Van Zee Date: Sat Aug 25 20:12:36 2018 -0500 Allow lesser Makefiles to reference installed BLIS. Details: - Updated the build system so that "lesser" Makefiles, such as those in belonging to example code or the testsuite, may be run even if the directory is orphaned from the original build tree. This allows a user to configure, compile, and install BLIS, delete the build tree (that is, the source distribution, or the build directory for out- of-tree builds) and then compile example or testsuite code and link against the installed copy of BLIS (provided the example or testsuite directory was preserved or obtained from another source). The only requirement is that make be invoked while setting the BLIS_INSTALL_PATH variable to the same installation prefix used when BLIS was configured. The easiest syntax is: make BLIS_INSTALL_PATH=/install/prefix though it's also permissible to set BLIS_INSTALL_PATH as an environment variable prior to running 'make'. - Updated all lesser Makefiles to implement the new aforementioned build behavior. - Relocated check-blastest.sh and check-blistest.sh from build to blastest and testsuite, respectively, so that if those directories are copied elsewhere the user can still run 'make check' locally. - Updated docs/Testsuite.md with language that mentions this new option of building/linking against an installed copy of BLIS. commit 36ff92ce0d3b428b15b6cddc6f5944afe22e43ec Author: Field G. Van Zee Date: Fri Aug 24 18:26:09 2018 -0500 Missing C++ compiler no longer fatal to configure. Details: - Changed configure so that the absence of any C++ compiler from the pre-defined search list does not result in an exit. Instead, in this situation, the found_cxx variable is assigned 'c++notfound' and the error message is changed to remind the user that C++ will not be available in the sandbox. Thanks to Devangi Parikh for reporting this issue. - Also tweaked the message when a C++ compiler *is* found to remind any would-be confused user that BLIS will only use C++ if it is needed by code in the sandbox. commit 658f0a129bdc565b072696b6ebddce501132091c Author: Field G. Van Zee Date: Fri Aug 24 17:49:37 2018 -0500 Fixed obscure integer size bug in va_arg() usage. Details: - Fixed a bug in the way that the variadic bli_cntx_set_l3_nat_ukrs() function was defined. This function is meant to take a microkernel id, microkernel datatype, microkernel address, and microkernel preference as arguments, and is typically called within the bli_cntx_init_*() function defined within a sub-configuration for initializing an appropriate context. The problem is with the final argument: the microkernel preference. These preferences are actually boolean values, 0 or 1 (encoded as FALSE or TRUE). Since the variadic function does not give the compiler any type information for any variadic arguments, they are "promoted" in the course of internal (macroized) processing according to default argument promotion rules. Thus, integer literals such as 0 and 1 become int and floating-point literals (such as 0.0 or 1.0) become double. Previous to this commit, we indicated to va_arg() that the ukernel preference was a 'bool_t', which is a typedef of int64_t on 64-bit systems. On systems where int is defined as 64 bits, no problems manifest since int is the same size as the type we passed in to va_arg(), but on systems where int is 32 bits, the ukernel preference could be misinterpreted as a garbage value. (This was observed on a modern armv8 system.) The fix was to interpret the bool_t value as int and then immediately typecast it to and store it as a bool_t. Special thanks to Devangi Parikh for helping track down this issue, including deciphering the use of va_arg() and its byzantine treatment of types. - Added explicit typecasts for all invocations of va_arg() in bli_cntx.c. commit e71dc389120b032e42091e4d1a928515ed6f7275 Author: Field G. Van Zee Date: Fri Aug 24 15:56:04 2018 -0500 Fixed a very minor memory leak in gks. Details: - Fixed a memory leak in the global kernel structure that resulted in 56 bytes per configured architecture (of which only 18 are presently supported by BLIS). The leak would only manifest if BLIS was initialized and then finalized before the application terminated. Thanks to Devangi Parikh for helping track down this leak. commit a7e3a5f9753468c8e665e6c5c3b38d22b7c92500 Author: Field G. Van Zee Date: Fri Aug 24 14:51:11 2018 -0500 Fixed uncallable bli_finalize(). Details: - Previously, bli_finalize_once()--which, like bli_init_once(), was implemented in terms of pthread_once()--was using the same pthread_once_t control object being used by bli_init(), thus guaranteeing that it would never be called as long as BLIS had already been initialized. This could manifest as a rather large memory leak to any application that attempted to finalize BLIS midway through its execution (since BLIS reserves several megabytes of storage for packing buffers per thread used). The fix entailed giving each function its own pthread_once_t object. Thanks to Devangi Parikh for helping track down this very quiet bug. commit a79c21c7c17fb4854fd24c73b81ec5543f74082d Author: Field G. Van Zee Date: Thu Aug 23 14:40:46 2018 -0500 Fixed cleanmk target post-1b0f8d6. Details: - Changed the cleanmk target to delete makefile fragments from their new home in obj/$(CONFIG_NAME). The old definition worked only because of a typo (REFERKN_PATH instead of REFKERN_PATH), and only in the non-verbose (V != 1) case. commit ffb57242f3eb1175c991fe1b492595fdaa175c27 Author: Field G. Van Zee Date: Wed Aug 22 18:22:41 2018 -0500 Cosmetic output changes to configure. Details: - Disable sandbox-related obj directory creation, directory mirroring, and makefile fragment generation when a sandbox is not enabled. - Prevent various duplicate actions by configure (such as those mentioned above for sandboxes above). commit ac17454aae9ad430f05aa7c156919c6c695c300c Merge: a77bec76 7afd095a Author: Field G. Van Zee Date: Wed Aug 22 15:34:53 2018 -0500 Merge branch 'master' into dev commit a77bec766a01e42f13f8cacbec8c4cbde8ecefef Author: Field G. Van Zee Date: Wed Aug 22 15:31:29 2018 -0500 Whitespace changes, minor renames in build system. Details: - Minor whitespace cleanup, mostly in the form of spaces -> tabs. - Shortened certain variables' _FRAGMENT_ infixes to _FRAG_ in common.mk. commit 1b0f8d60d1132b56485cc202ebf1246898d3a2a4 Author: Devin Matthews Date: Wed Aug 22 13:19:29 2018 -0700 Generate makefile fragments in build tree (#240) * Make src dir read-only in out-of-tree build test. * Generate makefile fragments in the build tree. commit 7afd095af33690e0175903852b354c9fe46993f6 Author: Field G. Van Zee Date: Wed Aug 22 14:58:24 2018 -0500 Removed skx from code snippet in previous commit. Details: - The docs/ConfigurationHowTo.md document was written with examples that did not yet contain the skx sub-configuration, but the previous commit included bli_arch.c code copied and pasted from a recent commit that does support skx. To keep things consistent, I've removed skx from the recently-added ConfigurationHowTo.md code snippet. commit 48211a980d78673133076e8eced1007b1980f5e6 Author: Field G. Van Zee Date: Wed Aug 22 14:55:02 2018 -0500 Update to docs/ConfigurationHowTo.md. Details: - Added missing language directing the reader to modify the config_name string array in bli_arch.c when adding a new sub-configuration. Thanks to Devangi Parikh for reporting this missing section. commit 65c9096c6e21f3dc2947fa12be9ea3034f8662dc Author: Field G. Van Zee Date: Fri Aug 17 11:44:12 2018 -0500 Fixed broken -p option to configure. Details: - Fixed some stale code that was preventing the -p option to configure from working as expected (though the --prefix option was unaffected). This bug was was most likely introduced in 7e5648c (May 7 2018). Thanks to Dave Love for reporting this issue. commit e358d5e497c77b305af462f44266370a596445e2 Author: Field G. Van Zee Date: Thu Aug 16 12:18:45 2018 -0500 README.md update (Funding section). commit a61dd5e7bcf23f7237d407a5e06dd44e1bec9ad0 Author: Field G. Van Zee Date: Tue Aug 14 17:08:03 2018 -0500 Changed 'test' target to be more like 'check'. Details: - Redefined the 'test' make target in the top-level Makefile so that the final result ("everything passed" or at "least one failure") is echoed to stdout. Note that 'check' is unchanged, and thus is now effectively a fast version of 'test'. - Updated docs/BuildSystem.md to reflect the above change. commit ce5c3a198a7ae1ca676c27da4541d51ed19d16e1 Merge: 4f6745d6 0bbe69d5 Author: Field G. Van Zee Date: Tue Aug 14 16:52:19 2018 -0500 Merge branch 'master' of github.com:flame/blis commit 4f6745d68a2c66511695eff0beb00a82ffc6bbbe Author: Field G. Van Zee Date: Tue Aug 14 16:50:47 2018 -0500 Fixed link error when building only shared library. Details: - Fixed a linker error that occurred when attempting to compile and link the testsuite and/or BLAS test drivers after having configured BLIS to only generate a shared library (no static library). The chosen solution involved (1) adding the local library path, $(BASE_LIB_PATH), to the search paths for the shared library via the link option -Wl,-rpath,$(BASE_LIB_PATH). (2) adding a local symlink to $(BASE_LIB_PATH) that uses the .so major version number so that ld would find the shared library at execution time. Thanks to Sajid Ali for reporting this issue, to Devin Matthews for pointing out the need for the -rpath option, and to Devangi Parikh for helping Sajid isolate the problem. - Added #include to bli_system.h to avoid a compiler warning resulting from using toupper() from bli_string.c without a prototype. Thanks again to Sajid Ali, whose build log revealed this compiler warning. - Added '*.so.*' to .gitignore. - CREDITS file update. commit 0bbe69d5ed260849297d8f2d35b7668d167482ed Author: Devangi N. Parikh Date: Tue Aug 14 14:49:58 2018 -0500 Updated plotting scripts in test/studies. Details: - Fixed indexing on plots to correspond to the removal of dtime in the test drivers. commit e93e0e149e087e08eca2885f1a748a4e88ffe55d Author: Field G. Van Zee Date: Tue Aug 7 15:54:30 2018 -0500 Removed redefinition of axpyv, scal2v func types. Details: - Removed a stray/accidental redefinition of axpyv and scal2v function types in frame/1d/bli_l1d_ft.h (probably a copy/paste leftover during development). commit 1deb33bd16349aaa643694d1bd685ff8a9a5f476 Author: Field G. Van Zee Date: Tue Aug 7 15:02:50 2018 -0500 Updated penryn kernels to use new _ker_ft type names. Details: - Updated older _ft kernel type suffixes used within penryn level-1v and -1f kernels to use the newer _ker_ft suffix that was introduced in 0175483. (Thank you Travis CI.) commit 9cb0b023ca91abdc056d726cdc070062e4954611 Author: Field G. Van Zee Date: Tue Aug 7 14:21:07 2018 -0500 INSTALL file update. commit 017548314f3f78f66fbe3264509ac5302bd8d62b Author: Field G. Van Zee Date: Tue Aug 7 14:13:25 2018 -0500 Replaced function chooser macros w/ func ptr arrays. Details: - Previously, most object API functions (_oapi.c) used a function chooser macro that would expand out to an if-elseif-elseif-else conditional that used a num_t datatype to call the appropriate type-specific API (_tapi.c). This always felt a little hackish, and would get in the way somewhat of addig support for new num_t datatypes in the future. So, I've replaced that functionality with code that queries a function pointer that is then typecast appropriately. This model of function calling was already pervasive for kernels queried from the cntx_t structure. It was also already in use in various other functions, such as macrokernels, and this commit simply extends that pattern. - The above change required many new files, mostly header files, that define the function types (mostly _ft.h) for the queriable functions as well as some source files to define the function pointer arrays and their corresponding query functions (_fpa.c). Various other function types, mostly for kernel function types, were renamed to reduce the potential for confusion with the function types for expert and basic (non-expert) typed API functions. - Removed definitions for all of the "bli_call_ft_*()" function chooser macros from bli_misc_macro_defs.h. commit addce089664561f9f63efa6f107e58fc48d29871 Author: Field G. Van Zee Date: Mon Aug 6 13:18:20 2018 -0500 Format spec and other updates in test, test/3m4m. Details: - Removed the dtime (delta time, or wallclock time) column from the matlab output of all test drivers in test, test/3m4m, test/studies. This value was rarely (if ever) really needed and usually only served to take up screen space. - Updated format specifier in test/studies/skx to use %7.2f instead of %6.3f. - For the test drivers in 'test' directory, added an initial line of output that sets last entry of matlab matrix to zero in order to induce a pre-allocation of the entire array of performance results. commit 94d5ef42c833a4d43e50a80d46dddbd7a56d2db6 Author: Field G. Van Zee Date: Sat Aug 4 15:57:17 2018 -0500 Adjusted gflops format spec in testsuite, test/3m4m. Details: - Changed the format specifier for the gflops column in the testsuite output from %7.3f to %7.2f. This was done mainly to keep the output aligned properly when the expected perfomance exceeded 1000 gflops. Also, two decimal places still conveys plenty of precision for all practical applications, including just eyeballing performance deltas between two executions (let alone two implementations). - Changed the format specifier for gflops in the test/3m4m drivers from %6.3f to %7.2f (for the same reasons listed above). commit c7ff06bae92b9b6c6656f2030d13486b95417821 Merge: 6074082c ebe998d0 Author: Devangi N. Parikh Date: Wed Aug 1 14:20:41 2018 -0500 Merge branch 'master' of https://github.com/flame/blis commit 6074082cd359dd775ef72478f8f3a281c5a6a6f9 Author: Devangi N. Parikh Date: Wed Aug 1 13:30:51 2018 -0500 Fixed bug in bli_cntx_set_packm_ker_dt() implementation. Details: - Fixed bug in static function bli_cntx_set_[packm/unpackm]_ker_dt(), which were incorrectly calling bli_cntx_get_[packm/unpackm]_ker_dt to get the corresponding func_t. commit ebe998d06cc56a9a9d66990b6ebf683d6fd0efdf Author: Field G. Van Zee Date: Wed Aug 1 13:24:00 2018 -0500 Fixed typos in BuildSystem.md from previuos commit. commit e72a344e94c5ae253f69b60f41d92ca89a5d1d1c Author: Field G. Van Zee Date: Wed Aug 1 13:00:38 2018 -0500 Added table of 'make' targets to BuildSystem.md. Details: - Added a new section to BuildSystem.md that describes the most useful make targets defined in the top-level Makefile. commit 4f60d0288e00586dc921ff57db851f1266ff8e70 Author: Field G. Van Zee Date: Mon Jul 30 19:22:57 2018 -0500 README.md, comment updates. Details: - Added links, and sandbox language to README.md. - Adjusted some comments in high-level level-3 object functions to make clear what bli_thread_init_rntm() does. commit 455d3f49e5c8362395be14c79e6adb5123e29623 Author: Field G. Van Zee Date: Sun Jul 29 18:31:29 2018 -0500 Edits to object/typed API, multithreading docs. commit 922a1c05e06f52c97fb369870dce07233e61c4c9 Author: Field G. Van Zee Date: Sat Jul 28 20:15:55 2018 -0500 More tweaks to README.md. commit a7a0cf2b5d9f1dea5061c0f20eeaf371dfd4ea12 Author: Field G. Van Zee Date: Sat Jul 28 16:59:31 2018 -0500 More edits to docs/Multithreading.md. commit be21d0cf68c330fd0d2048465a43ddc59d0b9d6c Author: Field G. Van Zee Date: Sat Jul 28 16:46:51 2018 -0500 Fixed typos in docs/Multithreading.md. commit eac07c7b4f7a41c68d63f1e67141b2b58009609e Author: Field G. Van Zee Date: Sat Jul 28 16:45:28 2018 -0500 Edits to docs/Multithreading.md. commit 5438375a032273b46ae626fee909ffc05f48ab72 Author: Field G. Van Zee Date: Sat Jul 28 16:34:21 2018 -0500 Fixed link in README.md. commit 1f1a237d3f0b24d71ce2d7ee52d8a84f8e6a29ad Author: Field G. Van Zee Date: Sat Jul 28 16:33:28 2018 -0500 Fixed links in BLISTypedAPI.md. commit 89c8806e3aa49310f36c0314c5f6956c83a627a1 Author: Field G. Van Zee Date: Sat Jul 28 16:30:56 2018 -0500 Minor doc fixes to previous commit. commit b8c7574f84873b9c408f70c29c41ce464df57c2d Author: Field G. Van Zee Date: Sat Jul 28 16:27:09 2018 -0500 README.md, typed/object API updates. Details: - Updated the typed and object APIs to include language on the rntm_t parameters in the expert interfaces. - Updated README to include link to object API. commit 29c34c4adb02d91fb34d1ccc0e821d6cfb7ce5c5 Author: Field G. Van Zee Date: Fri Jul 27 16:26:19 2018 -0500 CREDITS file update. commit 55a04edf52ac4f16c51b738bc884684adc1f1777 Author: Field G. Van Zee Date: Fri Jul 27 16:10:46 2018 -0500 CHANGELOG update (0.4.0) commit 4ad61ce905d250dd3ef197f0d06a69ce6d99d309 (tag: 0.4.0) Author: Field G. Van Zee Date: Fri Jul 27 16:10:43 2018 -0500 Version file update (0.4.0) commit b86cf13793b07f35c027a56c9faec8f4b6279d3e Author: Field G. Van Zee Date: Fri Jul 27 16:08:21 2018 -0500 Release Notes update in advance of next version. commit a8b4084a0e04e47ac02ceae93a2018f5363e1205 Author: Field G. Van Zee Date: Fri Jul 27 16:07:26 2018 -0500 CREDITS file update. commit 8e10cac5f388ac961c3d77b0a465214e7c9dc91a Author: Field G. Van Zee Date: Fri Jul 27 14:45:35 2018 -0500 Updates to CREDITS, RELEASING, config/README.md. Details: - Added individuals' github handles to CREDITS file. - Updated RELEASING, config/README.md files. commit 401b69c8f26a86726ac5e1fb4f9fc2d2098ef204 Author: Field G. Van Zee Date: Wed Jul 25 17:55:13 2018 -0500 More indentation in docs/ConfigurationHowTo.md. commit 1c6a1b921ef96999bb449d657cca6d9a556f7245 Author: Field G. Van Zee Date: Wed Jul 25 17:14:58 2018 -0500 Trying new indentation in ConfigurationHowTo.md. Details: - Modified a few sections to take advantage of a feature of markdown that allows a bullet or enumeration to have multiple paragraphs. This is a trial run to make sure the indentation looks good when rendered in a web browser. commit 71f978719527fcf17617cb234e48bf349a76c12d Author: Field G. Van Zee Date: Wed Jul 25 15:55:36 2018 -0500 Whitespace changes to macrokernels' func ptr defs. commit 87d57c31c2bfcf4609dfe31ce915e9345150e613 Author: Field G. Van Zee Date: Wed Jul 25 14:20:18 2018 -0500 Various minor updates to typed, object API docs. commit fb6e16268aaafbab2fd78d47cbf821e2152261fd Author: Field G. Van Zee Date: Wed Jul 25 14:17:28 2018 -0500 Consolidated prototypes in bli_l1v_tapi.h. Details: - Consolidated typed API function prototypes in bli_l1v_tapi.h by leveraging identical function signatures between operations. - Removed 'restrict' keyword since it is not actually present in the function definitions. commit af60d738f21340ccb0903e6c87dbf6af4fc44fc0 Author: Field G. Van Zee Date: Tue Jul 24 15:35:52 2018 -0500 Finished object creation part of BLISObjectAPI.md. Details: - Filled in remaining section on object creation function reference of BLISObjectAPI.md. All object management functions demonstrated as part of the example code in examples/oapi are now documented, as well as some other functions that are not shown in the example code. - Updated variuos links (mostly in function index) to correctly point to the object API reference instead of the typed API reference. - Added documentation to getijm, setijm. commit 8217a6a3b68382c62f016c658d337e6086112fef Author: Field G. Van Zee Date: Tue Jul 24 13:13:10 2018 -0500 Moved sandbox README.md to docs/Sandboxes.md. Details: - Relocated sandbox/ref99/README.md to docs/Sandboxes.md and made minor edits to the document. commit b7db29332394324ffd1a73c3847a75e9a5b38c8d Author: Field G. Van Zee Date: Thu Jul 19 11:14:30 2018 -0500 Explicitly typecast return vals in static funcs. Details: - Added explicit typecasting to various functions (mostly static functions), primarily those in bli_param_macro_defs.h, bli_obj_macro_defs.h, bli_cntx.h, bli_cntl.h, and a few other header files. - This change was prompted by feedback from Jacob Gorm Hansen, who reported that #including "blis.h" from his application caused a gcc to output error messages (relating to types being returned mismatching the declared return types) when used via the C++ compiler front-end. This is the first pass of fixes, and we may need to iterate with additional follow-up commits (#233). commit fa08e5ead95f9d757af6ab5b095a8bf131e3874d Author: Field G. Van Zee Date: Tue Jul 17 19:02:15 2018 -0500 Fixed minor issues in ecbebe7 with mt disabled. Details: - Fixed an unused variable warning in frame/base/bli_rntm.c when multithreading is disabled. - Fixed a missing variable declaration in bli_thread_init_rntm_from_env() when multithreading is disabled. commit ecbebe7c2e43950dfa369f71c2b83cabe348a046 Author: Field G. Van Zee Date: Tue Jul 17 18:37:32 2018 -0500 Defined rntm_t to relocate cntx_t.thrloop (#235). Details: - Defined a new struct datatype, rntm_t (runtime), to house the thrloop field of the cntx_t (context). The thrloop array holds the number of ways of parallelism (thread "splits") to extract per level-3 algorithmic loop until those values can be used to create a corresponding node in the thread control tree (thrinfo_t structure), which (for any given level-3 invocation) usually happens by the time the macrokernel is called for the first time. - Relocating the thrloop from the cntx_t remedies a thread-safety issue when invoking level-3 operations from two or more application threads. The race condition existed because the cntx_t, a pointer to which is usually queried from the global kernel structure (gks), is supposed to be a read-only. However, the previous code would write to the cntx_t's thrloop field *after* it had been queried, thus violating its read-only status. In practice, this would not cause a problem when a sequential application made a multithreaded call to BLIS, nor when two or more application threads used the same parallelization scheme when calling BLIS, because in either case all application theads would be using the same ways of parallelism for each loop. The true effects of the race condition were limited to situations where two or more application theads used *different* parallelization schemes for any given level-3 call. - In remedying the above race condition, the application or calling library can now specify the parallelization scheme on a per-call basis. All that is required is that the thread encode its request for parallelism into the rntm_t struct prior to passing the address of the rntm_t to one of the expert interfaces of either the typed or object APIs. This allows, for example, one application thread to extract 4-way parallelism from a call to gemm while another application thread requests 2-way parallelism. Or, two threads could each request 4-way parallelism, but from different loops. - A rntm_t* parameter has been added to the function signatures of most of the level-3 implementation stack (with the most notable exception being packm) as well as all level-1v, -1d, -1f, -1m, and -2 expert APIs. (A few internal functions gained the rntm_t* parameter even though they currently have no use for it, such as bli_l3_packm().) This required some internal calls to some of those functions to be updated since BLIS was already using those operations internally via the expert interfaces. For situations where a rntm_t object is not available, such as within packm/unpackm implementations, NULL is passed in to the relevant expert interfaces. This is acceptable for now since parallelism is not obtained for non-level-3 operations. - Revamped how global parallelism is encoded. First, the conventional environment variables such as BLIS_NUM_THREADS and BLIS_*_NT are only read once, at library initialization. (Thanks to Nathaniel Smith for suggesting this to avoid repeated calls getenv(), which can be slow.) Those values are recorded to a global rntm_t object. Public APIs, in bli_thread.c, are still available to get/set these values from the global rntm_t, though now the "set" functions have additional logic to ensure that the values are set in a synchronous manner via a mutex. If/when NULL is passed into an expert API (meaning the user opted to not provide a custom rntm_t), the values from the global rntm_t are copied to a local rntm_t, which is then passed down the function stack. Calling a basic API is equivalent to calling the expert APIs with NULL for the cntx and rntm parameters, which means the semantic behavior of these basic APIs (vis-a-vis multithreading) is unchanged from before. - Renamed bli_cntx_set_thrloop_from_env() to bli_rntm_set_ways_for_op() and reimplemented, with the function now being able to treat the incoming rntm_t in a manner agnostic to its origin--whether it came from the application or is an internal copy of the global rntm_t. - Removed various global runtime APIs for setting the number of ways of parallelism for individual loops (e.g. bli_thread_set_*_nt()) as well as the corresponding "get" functions. The new model simplifies these interfaces so that one must either set the total number of threads, OR set all of the ways of parallelism for each loop simultaneously (in a single function call). - Updated sandbox/ref99 according to above changes. - Rewrote/augmented docs/Multithreading.md to document the three methods (and two specific ways within each method) of requesting parallelism in BLIS. - Removed old, disabled code from bli_l3_thrinfo.c. - Whitespace changes to code (e.g. bli_obj.c) and docs/BuildSystem.md. commit 323eaaab99752858b12e81e2eb8e416f009a3028 Author: Devangi N. Parikh Date: Fri Jul 13 11:40:06 2018 -0500 Removed left over code from plotting scripts. commit 60c197736495b47ce974ffb9b43874d1ebcfe78c Author: Field G. Van Zee Date: Thu Jul 12 19:22:14 2018 -0500 Documented accessor functions in BLISObjectAPI.md. Details: - Added documentation to docs/BLISObjectAPI.md for a handful of commonly-used obj_t accessor functions. - Minor updates to docs/BLISTypedAPI.md. commit 77327ad796e11ef67df0cc91d45ed663598ba4df Merge: 73b0b2a3 9fef8575 Author: Devangi N. Parikh Date: Thu Jul 12 17:09:33 2018 -0500 Merge branch 'master' of https://github.com/flame/blis commit 73b0b2a3ac1be6dfbe85c116886b4e29d98ac945 Author: Devangi N. Parikh Date: Thu Jul 12 16:53:10 2018 -0500 Created hardware-specific test driver directory. Details: - Created a 'studies' subdirectory within 'test' to be used to house test drivers, makefiles, run scripts, matlab plot code, and related files that have been customized for collecting performance data on specific host machines or product lines. This new setup will help us catalog, track, and share test driver materials over time, and in a way that facilitates reproducibility. - Created an 'skx' subdirectory within 'test/studies' to house various level-3 test driver files used to measure performance on SkylakeX nodes (specifically, those nodes used by TACC's stampede2 system). commit 9fef85756d15ee0f977fff6e57acd01c20cba184 Author: Field G. Van Zee Date: Wed Jul 11 18:40:30 2018 -0500 Cleaned up loose ends in BLISObjectAPI.md. Details: - Deleted some lines from the API function signatures that did not belong (and were only left over from the copy-paste of the typed API). - Fixed some paragraph-in-bullet indentation. commit 80ddeae4629022b69fdf1f1b053a1fcba643c40c Author: Field G. Van Zee Date: Wed Jul 11 18:31:57 2018 -0500 Added BLISObjectAPI.md to docs. Details: - Added first draft of BLISObjectAPI.md. (Object management section is still missing.) - Small fixes to BLISTypedAPI.md found while writing BLISObjectAPI.md. - In various .md files, changed ``` verbatim blocks to language attributes (e.g. ```c for C code). commit 038442add39ce629fee0d960b212ce0c95138d46 Author: Field G. Van Zee Date: Wed Jul 11 12:24:18 2018 -0500 Added -lpthread to makefile example in BuildSystem.md. Details: - Added missing pthreads library linking to example makefile in docs/BuildSystem.md, as well as similar language to build requirements at the beginning of the document. Thanks to Stefanos Mavros for bringing this to our attention. - Updated CREDITS file. commit bf10d8624e7b5902c9d9189c7c93f318b8e1b9a5 Author: Field G. Van Zee Date: Mon Jul 9 18:40:13 2018 -0500 Small updates to KernelsHowTo.md, BLISTypedAPI.md. Details: - Minor updates to BLISTypedAPI.md, mostly to bring terminology up-to-date with the new "typed API" classification. - Added contents section to KernelsHowTo.md. commit 1fd3bce59e43b422e62f9684bca9d1296a29edc3 Author: Field G. Van Zee Date: Mon Jul 9 18:20:11 2018 -0500 Further updates to KernelsHowTo.md, BLISTypedAPI.md. Details: - Added missing level-1v operations to BLISTypedAPI (e.g. axpbyv, xpbyv). - Updated broken linkes in KernelsHowTo.md based on misnamed anchors. - Other minor changes. commit c40d30a6c920bd2e5a8353a3cd07a7e2b2265758 Author: Field G. Van Zee Date: Mon Jul 9 17:55:54 2018 -0500 Updated KernelsHowTo.md, BLISTypedAPI.md. Details; - Added missing (basic) information in KernelsHowTo.md for level-1f and level-1v kernels. - Updated section regarding contexts. commit f8913c2bf91c0e0fb4e68aedf64a242a19db92a0 Author: Field G. Van Zee Date: Sat Jul 7 20:35:13 2018 -0500 Fixed outdated scalv() calls in penryn l1f kernels. Details: - Fixed stale calls to dscalv() from the dotxf and dotxaxpyf penryn kernels that were not updated during the basic/expert API separation in e88aeda. commit e78e71d549ac17ecd52c7b33008df1cd78f1b59e Author: Field G. Van Zee Date: Sat Jul 7 20:18:09 2018 -0500 Added README.md mention/link to examples/tapi. Details: - Added language to README.md to bring the reader's attention to the example code for the typed API (in addition to those for the object API). commit 419ffb158573a26bfec47bac73e4394e7926a7b8 Author: Field G. Van Zee Date: Sat Jul 7 20:14:23 2018 -0500 Updates to README.md. Details: - Updated wiki links according to renamed/relocated files in 'docs'. - Converted links to relative paths. - Added link to docs/Multithreading.md. commit 7d3e8a7e5f1ec299d009fb6c9071f0c1b089b460 Author: Field G. Van Zee Date: Sat Jul 7 20:01:29 2018 -0500 Reverted docs/*.md links to relative paths. Details: - Within the documents in docs/*.md, reverted links to other local documents to relative paths. - Fixed some links/documents that did not yet have the '.md' suffix. - Testing whether we can use relative links ('docs/BLISTypedAPI.md') from within README.md. commit d97c862c2b9170d774f414e63ae365488fffb4f5 Author: Field G. Van Zee Date: Sat Jul 7 19:40:41 2018 -0500 Updated links (URLs) in docs/*.md. Details: - Updated most markdown links in the documents/wikis to use absolute paths instead of the relative paths that were in use previously. A few links were not updated, except for adding a ".md" to reflect the documents' new names, in order to test whether relative linking still works. commit 3a0c12135875e0fb04de9798664e4fae632d994e Merge: 2c7960c8 bcacddfa Author: Field G. Van Zee Date: Sat Jul 7 16:51:38 2018 -0500 Merge branch 'dev' commit bcacddfad75b20969660606751eea6ead6c42ca9 Author: Field G. Van Zee Date: Sat Jul 7 16:45:29 2018 -0500 Added 'docs' directory with wiki markdown files. Details: - Exported all github wikis to a new 'docs' directory. - Renamed 'BLISAPIQuickReference' wiki to 'BLISTypedAPI' and removed all cntx_t* arguments from the (now non-expert) APIs (with the exception of the kernel APIs). - Added section to BuildSystem documenting new ARG_MAX hack. commit 3ee2bc0f7aa3b08da92331d64271bee99eaf8c1d Author: Field G. Van Zee Date: Sat Jul 7 16:02:16 2018 -0500 Renamed files that distinguish basic/expert APIs. Details: - Renamed various files that were previously named according to a "with context" or "without context" convention. For example, the following files in frame/3 were renamed: frame/3/bli_l3_oapi_woc.c -> frame/3/bli_l3_oapi_ba.c frame/3/bli_l3_oapi_wc.c -> frame/3/bli_l3_oapi_ex.c frame/3/bli_l3_tapi_woc.c -> frame/3/bli_l3_tapi_ba.c frame/3/bli_l3_tapi_wc.c -> frame/3/bli_l3_tapi_ex.c Here, the "ba" is for "basic" and "ex" is for "expert". This new naming scheme will make more sense especially if/when additional expert parameters are added to the expert APIs (typed and object). commit e88aedae735dfeb6fa5ac28d4527eb3ca58c6510 Author: Field G. Van Zee Date: Fri Jul 6 19:14:02 2018 -0500 Separated expert, non-expert typed APIs. Details: - Split existing typed APIs into two subsets of interfaces: one for use with expert parameters, such as the cntx_t*, and one without. This separation was already in place for the object APIs, and after this commit the typed and object APIs will have similar expert and non- expert APIs. The expert functions will be suffixed with "_ex" just as is the case for expert interfaces in the object APIs. - Updated internal invocations of typed APIs (functions such as bli_?setm() and bli_?scalv()) throughout BLIS to reflect use of the new explictly expert APIs. - Updated example code in examples/tapi to reflect the existence (and usage) of non-expert APIs. - Bumped the major soname version number in 'so_version'. While code compiled against a previous version/commit will likely still work (since the old typed function symbol names still exist in the new API, just with one less function argument) the semantics of the function have changed if the cntx_t* parameter the application passes in is non-NULL. For example, calling bli_daxpyv() with a non-NULL context does not behave the same way now as it did before; before, the context would be used in the computation, and now the context would be ignored since the interace for that function no longer expects a context argument. commit 331694e52414c0cd50048daf880a9ace9e29b94a Author: Isuru Fernando Date: Fri Jul 6 09:07:38 2018 -0600 Fix windows build and enable x86_64 on appveyor (#230) * Upload artifacts built on appveyor (#228) * Upload artifacts * Fix install in appveyor * Remove windows.h in bli_winsys.c (#229) Looks like it is unneeded. * Implemented ARG_MAX hack in configure, Makefile. Details: - Added support for --enable-arg-max-hack to configure, which will change the behavior of make when building BLIS so that rather than invoke the archiver/linker with all of the object files as command line arguments, those object files are echoed to a temporary file and then the archiver/linker is fed that temporary file via the @ notation. An example of this can be found in the GNU make docs at https://www.gnu.org/software/make/manual/make.html#File-Function - Thanks to Isuru Fernando for prompting this feature. * Enable x86_64 and arg-max-hack on appveyor * Use gas style assembly for clang on windows commit a64a780d28c99d35f237f59212772e9beff35b3e Merge: 89e178ce 3cb396d1 Author: Devin Matthews Date: Fri Jul 6 09:38:42 2018 -0500 Merge pull request #231 from flame/travis-pr Disable SDE for PRs commit 3cb396d1ae4ee569f862db201c6a976712fd128e Author: Devin Matthews Date: Fri Jul 6 09:19:44 2018 -0500 Disable SDE for PRs Pull requests cannot use Travis secret variables, so SDE needs to be disabled. This PR should suffice as a test. commit 2c7960c8416ee9b67364be5f2b210fd7a0aec4b5 Author: Field G. Van Zee Date: Thu Jul 5 14:38:33 2018 -0500 Implemented ARG_MAX hack in configure, Makefile. Details: - Added support for --enable-arg-max-hack to configure, which will change the behavior of make when building BLIS so that rather than invoke the archiver/linker with all of the object files as command line arguments, those object files are echoed to a temporary file and then the archiver/linker is fed that temporary file via the @ notation. An example of this can be found in the GNU make docs at https://www.gnu.org/software/make/manual/make.html#File-Function - Thanks to Isuru Fernando for prompting this feature. commit c422a5cd191d47e6aeb9cea6de0e348f46e3e318 Merge: b6470262 89e178ce Author: Field G. Van Zee Date: Thu Jul 5 12:33:35 2018 -0500 Merge branch 'dev' commit b6470262ea66c0f48a5b4d85ca4bf85c1fb2b3af Author: Isuru Fernando Date: Wed Jul 4 19:14:29 2018 -0600 Remove windows.h in bli_winsys.c (#229) Looks like it is unneeded. commit eac4bdf98691c5ec784af0dc11d1ad2269840661 Author: Isuru Fernando Date: Wed Jul 4 18:31:01 2018 -0600 Upload artifacts built on appveyor (#228) * Upload artifacts * Fix install in appveyor commit 89e178ce380439dea951925e33703dc4b979e914 Merge: d868eb3e e32b2ef9 Author: Field G. Van Zee Date: Wed Jul 4 17:51:16 2018 -0500 Merge branch 'master' into dev commit e32b2ef983ea1c3521dd3821116c0078690f125e Author: Field G. Van Zee Date: Wed Jul 4 17:49:39 2018 -0500 Update to CREDITS file. commit 14648e137696484e0ff04f89b16c6b4183ea42b8 Author: Isuru Fernando Date: Wed Jul 4 16:48:42 2018 -0600 Native windows support using clang (#227) * Add appveyor file * Build script * Remove fPIC for now * copy as * set CC and CXX * Change the order of immintrin.h * Fix testsuite header * Move testsuite defs to .c * Fix appveyor file * Remove fPIC again and fix strerror_r missing bug * Remove appveyor script * cd to blis directory * Fix sleep implementation * Add f2c_types_win.h * Fix f2c compilation * Remove rdp and rename appveyor.yml * Remove setenv declaration in test header * set CPICFLAGS to empty * Fix another immintrin.h issue * Escape CFLAGS and LDFLAGS * Fix more ?mmintrin.h issues * Build x86_64 in appveyor * override LIBM LIBPTHREAD AR AS * override pthreads in configure * Move windows definitions to bli_winsys.h * Fix LIBPTHREAD default value * Build intel64 in appveyor for now commit b45ea92fc6f77f2313b50dbe95922f838cbead07 Author: Field G. Van Zee Date: Tue Jul 3 18:27:29 2018 -0500 Added typed (BLAS-like) API code examples. Details: - Added new example code to examples/tapi demonstrating how to use the BLIS typed API. These code examples directly mirror the corresponding example code files in examples/oapi. This setup provides a convenient opportunity for newcomers to BLIS to compare and contrast the typed and object APIs when they are used to perform the same tasks. - Minor cleanups to examples/oapi. commit d868eb3e200f657a1284c4cc933e7a4d25260dce Author: Field G. Van Zee Date: Fri Jun 29 12:36:04 2018 -0500 Implemented bli_obj_scalar_cast_to(). Details: - Implemented bli_obj_scalar_cast_to(), which will typecast the value in the internal scalar of an obj_t to a specified datatype. - Changed bli_obj_scalar_attach() so that the scalar value being attached is first typecast to the storage datatype of the destination object rather than the target datatype. - Reformatted function type signatures in bli_obj_scalar.c as well as prototypes in its corresponding header file. commit 52d80b5f09517d80ac8a7c96983a576c1ec2080b Author: Field G. Van Zee Date: Fri Jun 29 12:30:44 2018 -0500 Fixed static funcs related to target and exec dts. Details: - Fixed incorrect bit shifts in the following static functions: bli_obj_set_target_domain() bli_obj_set_target_prec() bli_obj_set_exec_domain() bli_obj_set_exec_prec() - Fixed incorrect bitmask in bli_dt_proj_to_single_prec(). - Updated bli_obj_real_part() and bli_obj_imag_part() so that it updates the target and exec datatypes (in addition to the storage datatypes). commit e006f2d0eeb229c1cd05a424496a774c29bdc5d7 Merge: bd8c55fe dafca7a0 Author: Field G. Van Zee Date: Wed Jun 27 15:54:38 2018 -0500 Merge branch 'dev' of github.com:flame/blis into dev commit bd8c55fe268e8e352508341ebd739ef4fc68eb92 Author: Field G. Van Zee Date: Wed Jun 27 15:52:37 2018 -0500 Added dt_on_output field to auxinfo_t. Details: - Added a new field to the auxinfo_t struct that can be used, in theory, to request type conversion before the microkernel stores/accumulates its microtile back to memory. - Added the appropriate get/set static functions to bli_type_defs.h. commit dafca7a0c2c72aaf15cb588b2bef6f246abb1905 Author: Devin Matthews Date: Mon Jun 25 16:20:10 2018 -0500 Fix botched memory addressing in Penryn kernel (no effect for GAS output). commit de493b0f349efebab98ab17f063d4d3d932c24c3 Merge: 195480be a7166feb Author: Devin Matthews Date: Mon Jun 25 14:26:06 2018 -0500 Merge pull request #226 from devinamatthews/dev Finish macroization of assembly ukernels. commit 195480beb589db7d582646f556e855c611d4c3a9 Merge: 07c3d0a9 3f387ca3 Author: Field G. Van Zee Date: Mon Jun 25 13:24:21 2018 -0500 Merge branch 'master' into dev commit 3f387ca35e42519f0d6a154814e4c8800fa2acb8 Author: Field G. Van Zee Date: Mon Jun 25 12:32:03 2018 -0500 Fixed bugs in configure's select_cc() function. Details: - This commit fixes several bugs in configure relating to selecting a C compiler. By dumb luck, two of the two bugs sort of cancelled each other out in most use cases, which manifested as the expected behavior. Thanks to Mathieu Poumeyrol for bringing this issue to our attention, and to Devin Matthews for suggesting the more portable way of capturing both stdout and stderr and suggesting a return code check instead of testing stdout/stderr. - The first bug: As the values of the compiler search list are iterated over, only stderr is captured when querying a compiler with --version rather than both stdout and stderr. - The second bug: After each query, a conditional attempted to test whether the query resulted in anything being output. That conditional erroneously was using "-z" instead of "-n" for non-emptiness. Thus, most of the time, stderr was empty (because the --version info was being output on stdout), and since it was empty, the -z conditional (intended to execute only when a compiler was found to be responsive) executed. - A third bug was also fixed in the way that the merged stdout/stderr output was tested for non-emptiness (moving the 'cat' invocation to another line and testing the contents of a variable instead). - The three bugs above have been fixed as part of a partial rewrite of the select_cc() function in terms of a return code check, which obviated the need to save the output of stdout and stderr. - The fourth bug involved a misnamed variable in the right-hand side of a statement intended to prepend CC to search_list when CC was non-empty. This typically did not manifest as a bug since usually CC (if it was set) was set to a value that was known to work. commit a7166feb1053814b7dd27f3879ae38acfc9637fc Author: Devin Matthews Date: Mon Jun 25 12:09:18 2018 -0500 Finish macroization of assembly ukernels. commit f986396c2af5de06283b9834112782afd0a8907e Author: Field G. Van Zee Date: Fri Jun 22 18:12:40 2018 -0500 Added 'configure --help' text for CFLAGS, LDFLAGS. Details: - Added mention of the new support for preset CFLAGS, LDFLAGS to the bottom of the text output by './configure --help'. - Updated usage example to use 'haswell' instead of 'sandybridge'. commit 884175d9ffb62e49535e6c1f7d58fb3b83e7e78f Author: Field G. Van Zee Date: Fri Jun 22 18:08:43 2018 -0500 Added configure support for preset CFLAGS, LDFLAGS. Details: - Any preexisting values set to the CFLAGS environment variable (or the CFLAGS variable if given on the command line) are saved by configure for later inclusion (prepending, to be precise) along with the compiler flags automatically determined by the BLIS build system. LDFLAGS is treated in a similar manner.) Thanks to Dave Love for requesting this feature in issue #223 and Mathieu Poumeyrol for his support on this and a previous related issue. - Comment updates to build/config.mk.in. - Strip whitespace from return value of various cflags functions in common.mk. commit 07c3d0a95190bd23f0cd2ef220deb3384d8378d1 Author: Field G. Van Zee Date: Thu Jun 21 12:35:07 2018 -0500 Update to CREDITS file. commit a1ebbbf158c7b34c9032ef45431bc610b6f14858 Merge: 17928b1c c81c6f23 Author: Devin Matthews Date: Wed Jun 20 15:37:53 2018 -0500 Merge pull request #224 from devinamatthews/asm-macros Asm macros commit c81c6f23b9547b5d55ae68fd5a3bbd8a78290b6b Author: Devin Matthews Date: Wed Jun 20 15:20:44 2018 -0500 Fix problem with inc and dec macros. commit 5a63971c822fd452f97ba869625c8e87f6cbeebc Merge: b4d94e54 17928b1c Author: Devin Matthews Date: Wed Jun 20 14:07:49 2018 -0500 Merge remote-tracking branch 'upstream/dev' into asm-macros commit b4d94e54d44cf30e4bb452ca5263be3473c0582d Author: Devin Matthews Date: Wed Jun 20 14:07:24 2018 -0500 Convert x86 microkernels to assembly macros. commit 17928b1c9941aa58aef1f122c793e2b14e705267 Author: Field G. Van Zee Date: Tue Jun 19 17:59:03 2018 -0500 Added static funcs bli_dt_domain(), bli_dt_prec(). Details: - Added definitions of static functions bli_dt_domain()/bli_dt_prec(), which extract a dom_t domain or prec_t precision value, respectively, from a num_t datatype. - Changed the return types of bli_obj_domain() and bli_obj_prec() from objbits_t to dom_t and prec_t. (Not sure why they were ever set to return objbits_t.) commit 5f7fbb7115b1bf532c169dfd9adef84c41a95031 Author: Field G. Van Zee Date: Tue Jun 19 15:38:55 2018 -0500 Static funcs for projecting dt to single/double. Details: - Added static functions for projecting a datatype to single precision or double precision, both for obj_t's storage datatypes and standalone datatypes. commit d4a22702c7a90273dc14f271db465c2e11e5b87e Author: Field G. Van Zee Date: Tue Jun 19 14:54:57 2018 -0500 Set up haswell config for optional col-pref ukrs. Details: - Added two presently-disabled cpp blocks in bli_cntx_init_haswell.c to easily allow one to switch to a set of column-preferential gemm microkernels (in the haswell subconfiguration). The second column- preferring block sets the the register blocksizes to their appropriate values. However, cache blocksizes are left unchanged, and therefore are likely suboptimal. This should be addressed later. commit f317c2e31bfc329cb6bb4e06005e45b9c8a9d6a7 Author: Field G. Van Zee Date: Tue Jun 19 12:21:23 2018 -0500 Added get/set static funcs for exec dt/dom/prec. Details: - Added functions to bli_obj_macro_defs.h to get and set the target domain and target precision bits in the obj_t, and also added the appropriate support in bli_type_defs.h. commit e88a5b8da8c26caebd2b0fb73b30836fb5417c9c Author: Field G. Van Zee Date: Mon Jun 18 15:56:26 2018 -0500 Implemented castm, castv operations. Details: - Implemented castm and castv operations, which behave like copym and copyv except where the obj_t operands can be of different datatypes. These new operations, however, unlike copym/copyv, do not build upon existing level-1v kernels. - Reorganized projm, projv into a 'proj' subdirectory of frame/base (to match the newly added frame/base/cast directory). - Added new macros to bli_gentfunc_macro_defs.h, _gentprot_macro_defs.h that insert GENTFUNC2/GENTPROT2 macros for all non-homogeneous datatype combinations. Previously, one had to invoke two additional macros--one which mixed domains only and another that included all remaining cases--in order to get full type combination coverage. - Defined a new static function, bli_set_dims_incs_2m(), to aid in the setting of various variables in the implementations of bli_??castm(). This static function joins others like it in bli_param_macro_defs.h. - Comment update to bli_copysc.h. commit 2000cdff59272974438e88e0e82d8e1a32710325 Author: Field G. Van Zee Date: Mon Jun 18 14:17:28 2018 -0500 Update to CREDITS file. commit ed2c8aed848ba2dede18df090cf2e0b6e4cc059f Author: Field G. Van Zee Date: Mon Jun 18 11:49:34 2018 -0500 Temporarily disabled small matrix handling on zen. Details: - Disabled small matrix handling in config/zen/bli_family_zen.h due to what appears to be a bug that manifests as failures in the single and double precision real level-3 BLAS test drivers (visible via out.sblat3 and out.dblat3). Thanks to Robin Christ for reporting this issue. commit ed20392c500940bfc0947795c1ff7c8c24f8e26f Author: Field G. Van Zee Date: Fri Jun 15 16:31:22 2018 -0500 Added get/set static funcs for exec dt/dom/prec. Details: - Added functions to bli_obj_macro_defs.h to get and set the execution domain and execution precision bits in the obj_t. - Added/rearranged a few functions in bli_obj_macro_defs.h. - Renamed some macros in bli_type_defs.h: EXECUTION -> EXEC. commit 22594e8e9ab55f5bc0e69d96a23e128502849999 Author: Field G. Van Zee Date: Thu Jun 14 17:35:23 2018 -0500 Updated sandbox/ref99 according to f97a86f. Details: - Applied changes to ref99 sandbox analagous to those applied to framework code in f97a86f. This involves setting the pack schemas of A and B objects temporarily to communicate those desired schemas to the control tree creation function in blx_gemm_cntl.c. This allows us to (henceforth) query the schemas from the control tree rather than the context. commit 1b5d0424d2c7e5eac33e02359c12917ef280949f Author: Field G. Van Zee Date: Wed Jun 13 18:41:32 2018 -0500 Prototype column-preferential zen gemm ukernels. Details: - Added prototypes to bli_kernels_zen.h for each of the four gemm microkernels that prefer outputting to column storage. commit f88c2e7a539e383297e846e6d4647058dd3db128 Author: Field G. Van Zee Date: Wed Jun 13 18:27:46 2018 -0500 Defined static function bli_blksz_scale_def_max(). Details: - Added a new static function to bli_blksz.h that scales both the default (regular) blocksize as well as the maximum blocksize in the blksz_t object. Reminder: maximum blocksizes have different meanings in different contexts. For register blocksizes, they refer to the packing register blocksizes (PACKMR or PACKNR) while for cache blocksizes, they refer to the maximum blocksize to use during the final iteration of a loop. commit 87db5c048e0c7f37351fda486abaf7d19fc5821c Author: Field G. Van Zee Date: Tue Jun 12 19:38:37 2018 -0500 Changed usage of virtual microkernel slots in cntx. Details: - Changed the way virtual microkernels are handled in the context. Previously, there were query routines such as bli_cntx_get_l3_ukr_dt() which returned the native ukernel for a datatype if the method was equal to BLIS_NAT, or the virtual ukernel for that datatype if the method was some other value. Going forward, the context native and virtual ukernel slots will both be initialized to native ukernel function pointers for native execution, and for non-native execution the virtual ukernel pointer will be something else. This allows us to always query the virtual ukernel slot (from within, say, the macrokernel) without needing any logic in the query routine to decide which function pointer (native or virtual) to return. (Essentially, the logic has been shifted to init-time instead of compute-time.) This scheme will also allow generalized virtual ukernels as a way to insert extra logic in between the macrokernel and the native microkernel. - Initialize native contexts (in bli_cntx_ref.c) with native ukernel function addresses stored to the virtual ukernel slots pursuant to the above policy change. - Renamed all static functions that were native/virtual-ambiguous, such as bli_cntx_get_l3_ukr_dt() or bli_cntx_l3_ukr_prefers_cols_dt() pursuant to the above polilcy change. Those routines now use the substring "get_l3_vir_ukr" in their name instead of "get_l3_ukr". All of these functions were static functions defined in bli_cntx.h, and most uses were in level-3 front-ends and macrokernels. - Deprecated anti_pref bool_t in context, along with related functions such as bli_cntx_l3_ukr_eff_dislikes_storage_of(), now that 1m's panel-block execution is disabled. commit dbaf440540837b03643190cd685ed889fa7fd212 Merge: 22aa44eb 2610fff0 Author: Field G. Van Zee Date: Mon Jun 11 12:37:04 2018 -0500 Merge branch 'master' into dev commit 2610fff0b07bdb345cb2e334ef6bea0c63c8cead Author: Field G. Van Zee Date: Mon Jun 11 12:32:54 2018 -0500 Renamed 1m packm kernels from _1e to _1er. Details: - Renamed the reference packm kernels used by 1m. Previously, they used a _1e suffix, which was confusing since they packed to both 1e and 1r schemas. This was likely an artifact of the time when there were separate kernels for each schema before I decided to combine them into a single function (per datatype and panel dimension), and the 1e functions were the ones to inherit the 1r functionality. The kernels have now been renamed to use a _1er suffix. commit 7af5283dcc3dded114852d6013d33134021b81aa Author: sraut Date: Mon Jun 11 15:00:22 2018 +0530 added check condition on n-dimension for XA'=B intrinsic code to process till 128 size Change-Id: I95d020a5ca3ea21d446b8c2e379d56e1eea18530 commit 712de9b371a8727682352a2f52cd4880de905f0b Author: Field G. Van Zee Date: Sat Jun 9 14:36:30 2018 -0500 Added missing semicolon in 03obj_view.c Details: - Thanks to Tony Skjellum for pointing out this typo due to a last-minute change to the source prior to committing. commit 043d0cd37ef4a27b1901eeb89d40083cfb2a57ba Author: Field G. Van Zee Date: Sat Jun 9 13:46:49 2018 -0500 Implemented bli_acquire_mpart(), added example code. Details: - Implemented bli_acquire_mpart(), a general-purpose submatrix view function that will alias an obj_t to be a submatrix "view" of an existing obj_t. - Renumbered examples in examples/oapi and inserted a new example file, 03obj_view.c, which shows how to use bli_acquire_mpart() to obtain submatrix views of existing objects, which can then be used to indirectly modify the parent object. commit f1908d39767baef56077def69126d96f805ee27e Author: Field G. Van Zee Date: Fri Jun 8 14:22:22 2018 -0500 Fixed broken input.operations.fast. Details: - Removed three input lines from input.operations.fast (labeled "test sequential micro-kernel") that I intended to remove in bd02c4e. These lines prevented 'make check' (and 'make checkblis-fast') from completing correctly. Note: This bug was fixed in 3df39b3, but that commit has not yet been merged into master, hence this redundant commit. Thanks to Robert van de Geijn for reporting this issue. commit 262a62e3482c5caa947a89cabb562b5887555bd6 Author: Field G. Van Zee Date: Fri Jun 8 12:10:54 2018 -0500 Fixed undefined ref in steamroller/excavator configs. Details: - Fixed erroneous calls to bli_cntx_init_piledriver_ref() in bli_cntx_init_steamroller() and bli_cntx_init_excavator(), which should have been to their respectively-named bli_cntx_init_*() functions instead. Thanks to qnerd for bringing these bugs to our attention. commit 22aa44ebec2c7884bdc944775a1aa7534ab53f0d Merge: 65fae950 b65d0b84 Author: Field G. Van Zee Date: Thu Jun 7 17:42:59 2018 -0500 Merge branch 'dev' of github.com:flame/blis into dev commit 65fae95074d239354737355bbe6f202d4f8b2871 Author: Field G. Van Zee Date: Thu Jun 7 17:41:09 2018 -0500 Implemented bli_setrm, _setim, _setrv, _setiv. Details: - Defined new wrappers to setm/setv operations in frame/base/bli_setri.c that will target only the real or only the imaginary parts of a matrix/vector object. - Updated bli_obj_real_part() so that the complex-specific portions of the function are not executed if the object is real. - Defined bli_obj_imag_part(). - Caveat: If bli_obj_imag_part() is called on a real object, it does nothing, leaving the destination object untouched. The caller must take care to only call the function on complex objects. - Reordered some of the static functions in bli_obj_macro_defs.h related to aliasing. commit b65d0b841b7e4357bc2cf743bbb03384a3ab0bfa Author: Field G. Van Zee Date: Thu Jun 7 14:38:41 2018 -0500 Fixed bug in bli_dt_proj_to_complex(). Details: - Fixed a bug identical to the one fixed in 0a4a27e, except this time in the bli_obj_param_defs.h header file. It looks like the only consumers of this static function were in bli_l0_oapi.c, and so this may not have been manifesting (yet). commit 55b6abdf7458e31df3ad01796d67c2332c776948 Author: Field G. Van Zee Date: Thu Jun 7 14:08:12 2018 -0500 Enforce consistent datatypes in most object APIs. Details: - Added logic to level-1v, -1d, -1f, -1m, -2, and -3 operations' _check() functions to ensure that all operands are of the same datatype. There are some exceptions that were left out, such as the _check() function for the various norm operations since they have a different idea of datatype consistency (ie: the norm object must be the real projection of the primary input vector/matrix object). commit 513138b1a1ecebd015580423c779810cae5c67f2 Author: Field G. Van Zee Date: Thu Jun 7 12:24:47 2018 -0500 Defined/implemented bli_projv(). Details: - Added an implementation for bli_projv() to go along with the implementation of bli_projm() added in 0a4a27e. The only difference between the two is that bli_projv() may only be used on vectors, whereas bli_projm() is general-purpose. - Added a _check() function corresponding to bli_projv(). commit 5f71c1e719eb482b2a4e40daa280c4f7d05b6963 Merge: b5a641e9 3df39b37 Author: Field G. Van Zee Date: Wed Jun 6 19:06:14 2018 -0500 Merge branch 'dev' of github.com:flame/blis into dev commit b5a641e968469805906eb2c971384d12ad1beac5 Author: Field G. Van Zee Date: Wed Jun 6 19:05:37 2018 -0500 Added char-to-dt and dt-to-char mapping functions. Details: - Defined additional functions in bli_param_map.c: bli_param_map_char_to_blis_dt() bli_param_map_blis_to_char_dt() which will map a char to its corresponding num_t, or vice versa. commit 0a4a27e1a4487480410bc0b1bb034bcf97583214 Author: Field G. Van Zee Date: Wed Jun 6 19:02:29 2018 -0500 Defined/implemented bli_projm(). Details: - Defined a new operation in frame/base/bli_proj.c, bli_projm(), which behaves like bli_copym(), except that operands a and b are allowed to contain data of differing domains (e.g. a is real while b is complex, or vice versa). The file is named bli_proj.c, rather than bli_projm.c, with the intention that a 'v' vector version of the function may be added to the same file (at some point in the future). - Added supporting bli_check_*() functions in bli_check.c to confirm consistent precisions between to datatypes/objects, as well as the appropriate error message in bli_error.c and a new error code in bli_type_defs.h. - Wrote a bli_projm_check() function to go along with bli_projm(). - Defined static function bli_obj_real_part() in bli_obj_macro_defs.h, which will initialize an obj_t alias to the real part of the source object. - Fixed a bug in the static function bli_dt_proj_to_complex(), found in bli_param_macro_defs.h. Thankfully, there were no calls to the function to produce buggy behavior. commit 3df39b37a0134befa34b6b6259db98467c7bc965 Author: Field G. Van Zee Date: Wed Jun 6 15:35:05 2018 -0500 Fixed recently broken input.operations.fast. Details: - Removed "test sequential front-end" lines from microkernel test entries of input.operations.fast. This change was meant for inclusion in bd02c4e but was missed due to slightly different wording of the comment (I used "sed //d" to remove the lines). This fixes the broken 'make checkblis-fast' (and 'make check') targets. commit 695cd520e2f5eab938f66afe9fe36201ab2700c5 Author: sraut Date: Wed Jun 6 11:48:56 2018 +0530 AMD Copyright information changed to 2018 Change-Id: Idfd11afd5d252f8063d0158680d24bf7e2854469 commit df1dd24fd896821de60917b429f303bab7fd0d4b Author: sraut Date: Wed Jun 6 11:24:33 2018 +0530 small matrix trsm intrinsics optimization code for AX=B and XA'=B Change-Id: I90123c4d9adbd314c867995cd19dc975150b448c commit 3f48c38164b4135515b5c752c506fdccc4480be2 Author: Field G. Van Zee Date: Tue Jun 5 16:52:35 2018 -0500 Cosmetic fix to configure output in config.mk. Details: - Fixed configure so that MK_ENABLE_MEMKIND is assigned "no" when the option is disabled due to libmemkind not being present. This wasn't affecting anything since the one use of the variable (in common.mk) was formulated as "ifeq ($(MK_ENABLE_MEMKIND),yes)". That is, the variable being empty was effectively equivalent to it being set to "no". - Comment updates to build/config.mk.in, common.mk. commit 5df201260f64aa98a365931f6d2da70144d69932 Merge: 1b9af85e 96d2774b Author: Field G. Van Zee Date: Tue Jun 5 16:14:19 2018 -0500 Merge branch 'master' into dev commit 1b9af85ec98d91bb2b27aadaa3df344d18faff35 Author: Field G. Van Zee Date: Tue Jun 5 16:07:13 2018 -0500 Updated ref99 call to _cntx_set_thrloop_from_env(). Details: - Reordered the arguments in the ref99 sandbox's call to bli_cntx_set_thrloop_from_env() to be consistent with the updated function signature from f97a86f. Thanks to Devangi Parikh for reporting this issue. commit 96d2774b4cb44ff1e8b5798d7cfc83154a607624 Author: Tyler Michael Smith Date: Tue Jun 5 14:17:39 2018 +0200 Make bli_auxinfo_next_b() return b_next, not a_next (#216) commit d4c24ea5f644eb635046e7fe249d3e8e58b4c98a Author: sraut Date: Tue Jun 5 15:42:59 2018 +0530 copyright message changed to 2018 Change-Id: I33c1ebda41bc7f1973ff19e3b1947bdad62b4d44 commit 3f1ba4e646776699ebfaa042fe24691d9e2f55d0 Author: sraut Date: Tue Jun 5 14:21:13 2018 +0530 copyright changed to 2018 Change-Id: Ie916c7cd6f95aedc3cab6eec3a703c9ddb333bc3 commit bd02c4e9f7fe07487276e61507335d48c8e05f35 Author: Field G. Van Zee Date: Mon Jun 4 13:42:17 2018 -0500 Cleanups to testsuite, input.operations format. Details: - Removed the line in each operation entry in input.operations titled "test sequential front-end" and the corresponding support for the lines in the testsuite input parsing code. This line was included in the some of the earliest versions of the testsuite, back when I intended to eventually have separate multithreaded APIs. Specifically, I envisioned that multithreaded and sequential testing could be enabled or disabled on an operation level. However, BLIS evolved in a different direction and still does not have multithreaded-specific APIs (even if it will eventually someday). But even if it did have such APIs, I doubt I would allow the user to enable/disable them on an operation level. Thus, this was a zombie future parameter that was never used and never made sense to begin with. The one instance of the front_seq variable, used in the various libblis_test_() functions to guard the call to the operation test driver, that remains was commented out instead of deleted so that someday it could be easily changed via sed, if desired. - Various minor cleanups to the testsuite code, including consolidating use of DISABLE and DISABLE_ALL and reexpressing certain conditional expressions in the libblis_test_() functions in terms of boolean functions. commit 2c6d99b99e50d70f904da298a0c59be16cc5c180 Author: Field G. Van Zee Date: Sun Jun 3 18:13:36 2018 -0500 Fixed names out of alphabetical order in CREDITS. commit 7a207e8f2c5046f8b295a78e029ff2de765c7409 Author: Field G. Van Zee Date: Sun Jun 3 18:04:27 2018 -0500 Disabled indirect blacklisting (issue #214). Details: - Return early from function, pass_config_kernel_registries(), that implements indirect blacklisting of subconfigurations (during pass 0). In short, I realized that indirect blacklisting is not needed in the situations I envisioned, and can actually cause problems under certain circumstances. Thanks to Tony Skjellum for reporting the issue (#214) that led to this commit, and to Devin Matthews for prompting me to realize that indirect blacklisting was unnecessary, at least as originally envisioned. commit d7fb32682057c7458c8891c0eedafc374fd9beef Author: Field G. Van Zee Date: Sun Jun 3 13:20:37 2018 -0500 Fixed syntax artifacts from 4b36e85 in examples. Details: - Fixed artifacts of malformed recursive sed expressions used when preparing 4b36e85, in which most function-like macros were converted to static functions. The syntactically defective code was contained entirely in examples/oapi. Thanks to Tony Skjellum for reporting this issue. - Update to CREDITS file. commit ed7dedfd4a07eefeb5a038f9899afb8053b45383 Merge: f97a86f3 469727d4 Author: Field G. Van Zee Date: Sat Jun 2 20:29:53 2018 -0500 Merge branch 'master' into dev commit f97a86f322a6e3e31f33c89befc66189b0b8c64f Author: Field G. Van Zee Date: Sat Jun 2 20:28:20 2018 -0500 Updated setting/querying pack schema (cntx->cntl). - Query pack schemas in level-3 bli_*_front() functions and store those values in the schema bitfields of the correponding obj_t's when the cntx's method is not BLIS_NAT. (When method is BLIS_NAT, the default native schemas are stored to the obj_t's.) - In bli_l3_cntl_create_if(), query the schemas stored to the obj_t's in bli_*_front(), clear the schema bitfields, and pass the queried values into bli_gemm_cntl_create() and bli_trsm_cntl_create(). - Updated APIs for bli_gemm_cntl_create() and bli_trsm_cntl_create() to take schemas for A and B, and use these values to initialize the appropriate control tree nodes. (Also cpp-disabled the panel-block cntl tree creation variant, bli_gemmpb_cntl_create(), as it has not been employed by BLIS in quite some time.) - Simplified querying of schema in bli_packm_init() thanks to above changes. - Updated openmp and pthreads definitions of bli_l3_thread_decorator() so that thread-local aliases of matrix operands are guaranteed, even if aliasing is disabled within the internal back-end functions (e.g. bli_gemm_int.c). Also added a comment to bli_thrcomm_single.c explaining why the extra aliasing is not needed there. - Change bli_gemm() and level-3 friends so that the operation's ind() function is called only if all matrix operands have the same datatype, and only if that datatype is complex. The former condition is needed in preparation for work related to mixed domain operands, while the latter helps with readability, especially for those who don't want to venture into frame/ind. - Reshuffled arguments in bli_cntx_set_thrloop_from_env() to be consistent with BLIS calling conventions (modified argument(s) are last), and updated all invocations in the level-3 _front() functions. - Comment updates to bli_cntx_set_thrloop_from_env(). commit 965db85d29977d228ea744581edf2b682eb8e8a8 Author: Field G. Van Zee Date: Fri Jun 1 12:32:15 2018 -0500 Updated macro invocations in bli_gemm_ker_var2.c. Details: - Updated "get next a/b micropanel" macro invocations in bli_gemm_ker_var2.c according to changes in 9588625. - Comment update in bli_cntx.c. commit 8749fa0b48a7710f4115023e2c46bc80167bc8f9 Author: Field G. Van Zee Date: Thu May 31 12:34:01 2018 -0500 Cleanups to ref99/README.md, test/3m4m/Makefile. Details: - Minor edits to sandbox/ref99/README.md. - Removed cpp guards in sandbox/ref99/thread/blx_gemm_thread.h to be consistent with other headers in sandbox/ref99. - Additional targets and related cleanups in test/3m4m/Makefile. commit 9588625c43c86ef1bde8140f620a30f52420e6a6 Author: Field G. Van Zee Date: Wed May 30 15:19:53 2018 -0500 Renamed "next micropanel" macros in _l3_thrinfo.h. Details: - Renamed several macros defined in bli_l3_thrinfo.h designed to compute the values of a_next and b_next to insert into an auxinfo_t struct in level-3 macrokernels. (Previously, the macros did not use a bli_ prefix.) - Updated instances of above macro usage within various macrokernels. commit e4420591225fca2f63ca74ef6a23b962fcd4bec0 Merge: 34f974d1 850a8a46 Author: Field G. Van Zee Date: Tue May 29 17:12:22 2018 -0500 Merge branch 'dev' of github.com:flame/blis into dev commit 34f974d1a83a7d29ba09f67e392d361231fdf99c Author: Field G. Van Zee Date: Tue May 29 17:11:52 2018 -0500 More tweaks/updates to sandbox/ref99/README.md. commit 850a8a46c0a569a2652d8c200e5c53b61bcf988d Author: Devin Matthews Date: Tue May 29 13:51:21 2018 -0500 Test all x86_64 configurations*... (#212) * Add custom SDE cpuid files. * Set up testing of all x86_64 architectures (except bulldozer) using SDE. * Update .travis.yml [ci skip] * Update do_testsuite.sh [ci skip] * Updated .travis.yml with my secret token. Details: - Replaced Devin's temporary secret token with my own, which is used by Travis when accessing the Intel SDE via Dropbox. * Work around CPUID dispatch in glibc/libm by patching ld.so. * Detect path of loader at runtime. * Attempt to make SDE run on Travis * Allow unpatched ld.so if we don't know how to patch it. I *think* this only happens for older glibc without the multi-arch stuff (e.g. Ubuntu 14.04 on Travis), but who knows? * Upgrade Travis to gcc-6 and binutils-2.26. * Try to get Travis to use the right assembler. * Apparently you need ld-2.26 too. * Try to also patch ld.so from Ubuntu 14.04. * Take the nuclear option. * Account for non-absolute dependencies in ldd output. * String manipulation fail. * Update patch-ld-so.py * Add Zen to SDE testing. * Removed dead variable from travis/do_testsuite.sh. Details: - Removed 'BLIS_ENABLE_TEST_OUTPUT=yes' from make invocations in travis/do_testsuite.sh. This variable is no longer present in the BLIS build system (if it ever was?), and therefore has no effect. commit 42ea02a34e5c144893fe239ae55daef895d92677 Author: Field G. Van Zee Date: Tue May 29 12:48:14 2018 -0500 Renamed c99 sandbox to ref99. Details: - Renamed sandbox/c99 to sandbox/ref99. I wanted to name the sandbox so that it would be thought of as a "reference" sandbox. I kept the "99" to differientiate it from future reference sandboxes that may be written in another language (such as C++). - Updates to sandbox/ref99/README.md. commit 0e7205ccef50dccd4306cf427a63633396472813 Author: Field G. Van Zee Date: Tue May 29 12:36:13 2018 -0500 Remove sandbox/.gitkeep now that dir is non-empty. commit 3a4603858e3819cbd6ed7dd67d0fc0b3f89ed254 Author: Field G. Van Zee Date: Sat May 26 15:51:08 2018 -0500 More README.md updates to sandbox/c99. Details: - Added a section that walks the reader through how to configure BLIS to use a gemm sandbox. commit 2bad97f6bdf4642884d60fc03970549902a54d74 Author: Field G. Van Zee Date: Sat May 26 15:31:16 2018 -0500 Updates to CREDITS, sandbox/c99/README.md. commit 2b4a447526effa3e847a7e5c15c3758573f12318 Author: Field G. Van Zee Date: Fri May 25 18:51:23 2018 -0500 Initial implementation of c99 "reference" sandbox. Details: - Added a c99 sandbox (in sandbox/c99) to serve as a starting point for others looking to experiment with alternative implementations of gemm in BLIS. Note that this sandbox implementation is a first draft and will be refined over time. - Minor updates to Makefile and common.mk to restrict what source files get recompiled when sandbox files are touched. - Added an initial draft of a README.md in sandbox/c99. commit 469727d4f8a976d8713afb4d0b6235c322498db0 Author: Field G. Van Zee Date: Fri May 25 16:17:13 2018 -0500 Very minor comment updates. commit 66dbe69a0f9359bf1e39b5672ee365213de2e3ee Author: Field G. Van Zee Date: Fri May 25 15:45:53 2018 -0500 Converted macros to static funcs in _packm_cntl.h. Details: - Converted various macros in frame/1m/packm/bli_packm_cntl.h (designed to access fields of a packm_params_t struct) to static functions. commit 22deef2f5463a47e3b3c37fc313d17550f10ee06 Author: Field G. Van Zee Date: Thu May 24 14:28:55 2018 -0500 Support alternative gemm implementation sandboxes. Detail: - configure: - add support for --enable-sandbox=NAME to configure script, where NAME is a subdirectory of a new 'sandbox' directory that contains an alternative implementation of gemm. (For now, only implementations of gemm may be provided via a sandbox.); - add support for C++ compiler. C++ compilers are handled in a manner similar to that of C compilers, in that a default search order is used, and that CXX is searched for first, if the variable is set. In practice, the C++ compiler that is selected should correspond to the selected C compiler. (Example: If gcc is selected for C, g++ should be selected for C++.) The result of the search is output to config.mk via build/config.mk.in. NOTE: The use of C++ in BLIS is still hypothetical, but may eventually move to being experimental. This support was intended only for use of C++ within a gemm sandbox. - build/config.mk.in: - define SANDBOX variable containing sandbox subdirectory name. - build/bli_config.in: - define either of the BLIS_ENABLE_SANDBOX or BLIS_DISABLE_SANDBOX macros in bli_config.h. - common.mk: - include makefile fragments that were propagated into the specified sandbox subdirectory; - generate different CFLAGS for sandboxes, as well as a separate CXXFLAGS variable for sandboxes when C++ source files are compiled; - isolate into a single location lists of file suffixes for various purposes. - reorganized/clean up code related to identifying header files and paths. - Makefile: - generate object filepaths for and compile source code files found in sandbox sub-directory; - remove makefile fragments placed in sandbox sub-directory (cleanmk); - various other cleanups. - Added .cc, .cpp, and .cxx to list of suffixes of files to recognize in makefile fragments (via build/gen-make-frags/suffix_list). - Updated blis.h to conditionally #include bli_sandbox.h (via a new file, bli_sbox.h), which each sandbox is assumed to use for any type definitions and function prototypes it wishes to export out to blis.h. - Conditionally disable bli_gemmnat() implementation in frame/3 when BLIS_ENABLE_SANDBOX is defined. commit 25e3501ed57a0db7f860c88b7199b36049aec12a Merge: 216a4cb9 5140ee34 Author: Field G. Van Zee Date: Thu May 24 13:57:16 2018 -0500 Merge branch 'master' into dev commit 5140ee3424c744981a3fed3b5a748ebbfc111388 Author: Field G. Van Zee Date: Wed May 23 16:56:14 2018 -0500 Updated types of bli_is_[un]aligned_to() functions. Details: - Changed the void* arguments of the following static functions: bli_is_aligned_to() bli_is_unaligned_to() bli_offset_past_alignment() to siz_t, and the return type of bli_offset_past_alignment() from guint_t to siz_t. This allows for more versatile usage of these functions (e.g. when aligning both pointers and leading dimension). - Updated all invocations of these functions, mostly in kernels/penryn but also in kernels/bgq, to include explicit typecasts to siz_t when pointer arguments are passed in. - Thanks to Devin Matthews for pointing out this potential bug (via issue #211). - Deleted a few trailing spaces in various penryn kernels. - Removed duplicate instances of the words "derived" and "THEORY" from various kernel license headers, likely from a malformed recursive sed performed long ago. commit 216a4cb9cb87fa4c93f6ceb6ae90602e5018b305 Author: Field G. Van Zee Date: Fri May 18 18:47:03 2018 -0500 Minor update to flatten-headers.[py|sh] help text. Details: - Fixed a typo and removed some outdated language from the help text of flatten-headers.py and flatten-headers.sh. commit 962a706a6f56ea070ac4683f0af69c7e59af8ecb Author: Field G. Van Zee Date: Fri May 18 18:19:40 2018 -0500 Updated LICENSE file to mention HP Enterprise. Details: - Added HP Enterprise to the LICENSE file. Previously, only the source files touched by HPE contained the corresponding copyright notices. (This oversight was unintentional.) - Updated file-level copyright notices to include a comma, to match the formatting used for UT and AMD copyrights. commit efa43e13effe901ad31e734ac90f027e89473bd9 Author: Field G. Van Zee Date: Fri May 18 12:20:40 2018 -0500 More updates to CREDITS and RELEASING files. commit f94ab97af8e86baf9ee9a9cbaef8bb3712df2e11 Author: Field G. Van Zee Date: Thu May 17 17:45:31 2018 -0500 Update to CREDITS file. commit 4919b10c005e006a6d818eb8f865f9dbd8aa16df Author: Field G. Van Zee Date: Thu May 17 16:38:49 2018 -0500 Minor changes to README.md and CONTRIBUTING.md. commit b89451187e8321b673a1cf7603c8d48028d9d4c8 Author: Field G. Van Zee Date: Thu May 17 16:23:06 2018 -0500 README.md update. Details: - Added "Contributing" section with relevant links. commit af244194e7d76276a1b90fe59f9307dde0429e1d Author: Field G. Van Zee Date: Thu May 17 15:38:02 2018 -0500 Removed explicit critical sec. from bli_memsys.c. Details: - Removed critical sections protecting the initialization/finalization of bli_memsys.c. These synchronization mechanisms are no longer needed now that BLIS initializes all APIs via pthread_once(). commit 10c9e8f95254d8c6436c4d3cb093fa5544b45c90 Author: Field G. Van Zee Date: Thu May 17 15:22:51 2018 -0500 Cache hardware's arch_t id after querying once. Details: - Added logic to bli_arch.c that will call what was previously the body of bli_arch_query_id() only once and then cache the value in a static variable local to the file. (Previously, the arch_t associated with the hardware/configuration was queried every time bli_arch_query_id() was called, which was at least once per level-3 function call. Thanks to Devin Matthews for suggesting this feature via issue #175. - Added -lpthread to the compile/link command line of the compiler invocation that compiles build/detect/config/config_detect.c, which prints the string identifying the detected configuration, since it is now needed due to new pthread_once() logic in bli_arch.c. - Implementation note: I chose to implement this arch_t caching feature via pthread_once(), using a separate pthread_once_t variable local to the file, rather than calling bli_init_once(). The reason is that I did not want to require bli_init() as a prerequisite to this function. bli_init() already calls several sub-components, some of which make use of bli_arch_query_id(), and therefore it would be easy to fall into a circular self-init situation (which usually causes pthreads to hang indefinitely). commit f28a15293890ac6fbceac229fd204dbc9fec6e27 Author: Francisco Igual Date: Thu May 17 09:26:14 2018 +0000 Fixed clobber list bug in ARMv8 ukernel commit 2e31dd7852b4d6a9355899cf9659d4b8130461cb Author: Field G. Van Zee Date: Wed May 16 17:28:33 2018 -0500 Inserted missing integer typecasting into ukernels. Details: - Inserted missing safeguards into most microkernels to ensure that the integers read by the microkernel's assembly instructions are of the appropriate size. In many cases, this bug was going undetected likely because the compiler was inserting zero padding before the integers in the calling function, allowing the assembly code to read 64-bits in a way that did not corrupt the "lower" 32 integer bits with garbage in the higher bits. Thanks to Francisco Igual and Devangi Parikh for finding this issue. commit 12dfa9516428b4092554f0ce70b07571d35de222 Author: Field G. Van Zee Date: Wed May 16 12:46:57 2018 -0500 Fixed a bug in determining default integer size. Details: - Fixed a bug that would cause configurations to inadvertantly define their integers to be 32 bits when those environments actually call for 64-bit integers. While either BLIS_ARCH_64 or BLIS_ARCH_32 is defined in bli_system.h (based on whether preprocessor macros such as __x86_64 or __aarch64__ are defined by the environment), bli_system.h was being #included *after* bli_config_macro_defs.h, in which the BLIS_ARCH_64 macro was used to choose an integer type size in the event that BLIS_INT_TYPE_SIZE was not already defined by configure via bli_config.h. And due to the structure of the cpp code in that file, the 32-bit integer case was being chosen. Thanks to Francisco Igual and Devangi Parikh for their help in isolating this bug. - Moved the #include of hbwmalloc.h and related preprocessor code to bli_kernel_macro_defs.h to facilitate the reshuffling of the #include for bli_system.h in blis.h. commit f930cec0f35824c0f9ebbd218614209217d491cb Author: Field G. Van Zee Date: Tue May 15 17:47:08 2018 -0500 More tweaks to CONTRIBUTING.md. commit 173e30ff7d293ba31f3fab8ab0c0a695eda3d4fd Author: Field G. Van Zee Date: Tue May 15 14:48:34 2018 -0500 Added initial draft of CONTRIBUTING.md file. Details: - Thanks to the Ruby on Rails project for providing a good template off of which to build. commit 6e25e758b444bf725046674e1e64c6a52421749d Author: Nico Schlömer Date: Tue May 15 14:03:20 2018 +0200 Debian config (#206) * add debian config * correct wording in the README commit fcf6c6a3c87da08a7cdb92b102489b991ef7a644 Author: Alex Arslan Date: Mon May 14 18:41:03 2018 -0700 Fix shared library builds on platforms other than Linux and macOS (#209) * Fix detection of systems other than Linux and macOS The way the logic is currently laid out, any platform that isn't Linux gets assigned the .dylib shared library extension and the macOS-specific compiler flags. This reverses the logic to check for macOS first, and have the fallback use the Linux definitions, which apply to most other systems as well. * Use SHLIB_EXT instead of SO_SUF The former is more standard, as jakirkham pointed out in a comment. commit 6f7f51048c48f31d691c06451d0fd2cbc453ad03 Author: Field G. Van Zee Date: Mon May 14 18:41:56 2018 -0500 Echo cc_vendor when printing compiler version. Details: - Echo the ${cc_vendor} when informing the user of the compiler's version. Previously, the actual ${cc} (which could be a path to the executable) was being printed, which has already been printed by that point in the configure script. commit ad67dc4e348b0a381efc057573a6b03cc7e26db0 Author: Field G. Van Zee Date: Mon May 14 18:35:28 2018 -0500 Communicate cc, cc_vendor to make via config.mk. Details: - Historically, the compiler selection has happened statically in the various make_defs.mk and would only be overriden by setting CC (either prior to running configure or as a configure argument). However, in the last couple months, configure has evolved to contain rather sophisticated compiler detection logic for the purposes of blacklisting sub-configurations. It only makes sense that configure now fully take over the responsibility of selecting a compiler from the GNU make side of the build system. Thanks to Alex Arslan for his help exposing this issue. - Substitute found_cc into CC in config.mk via configure. - Set a new variable, CC_VENDOR, in config.mk via substitution from configure, and disable the corresponding CC_VENDOR code in common.mk. - Disabled default compiler selection (usually gcc) in the sub-configs' various make_def.mk files. commit 20af119fc97ec6120017a7a5ba5f9aaa920c7640 Author: Field G. Van Zee Date: Mon May 14 17:44:58 2018 -0500 Added README.md to 'config' directory. Details: - Added a brief README.md file to the config directory to redirect those who may be exploring the source tree to the ConfigurationHowTo wiki. (Included is a very brief explanation of configurations for those who don't have time to read the wiki.) Thanks to Nico Schlömer for this suggestion. commit 9dbce16269c3e1f27c7a0d64372cc76aed30dfc1 Author: Field G. Van Zee Date: Mon May 14 17:04:54 2018 -0500 Search for 'cc clang gcc' on OpenBSD, FreeBSD. Details: - Swapped gcc and clang in the compiler search list for OpenBSD. - Use the same search list for FreeBSD as above. commit 55ebf24d63128b5fd15b10160485667415a02a55 Author: Field G. Van Zee Date: Mon May 14 16:19:08 2018 -0500 Change compiler search order on OpenBSD. Details: - Set a compiler search list (and order) as a function of the OS detected via 'uname -s'. By default, this list and order is 'gcc clang cc' for Linux and Darwin (OS X), and any other OS except OpenBSD). On OpenBSD, we use 'cc gcc clang' because OpenBSD's default installation of gcc (4.2.1) is too old for BLIS. Thanks to Alex Arslan for reporting this issue and suggesting a fix. commit 4fb353bd90e6642c8aeffd1b1e6329f54eee4bb4 Merge: 4b36e85b 8a2857b5 Author: Field G. Van Zee Date: Sun May 13 17:50:51 2018 -0500 Merge branch 'master' into dev commit 8a2857b5e3c633b18c24f2275110437a702a71d0 Author: Field G. Van Zee Date: Fri May 11 18:42:05 2018 -0500 Fixed README.md typo; mention 'make check'. commit 543935c02f9335142d2e485a15f37dbaebe012ed Author: Field G. Van Zee Date: Fri May 11 18:35:32 2018 -0500 Updated README.md with Ubuntu packages link. Details: - Created a separate section of README.md for external packages, with one bullet each for Dave Love's rpms and Nico Schlömer's Ubuntu apt packages. Thanks to Dave and Nico for their contributions. commit af1d8470b56d3b2a1c8513d366d788dddcb84baa Author: Field G. Van Zee Date: Fri May 11 17:49:58 2018 -0500 Better handling of shared libraries on OS X. Details: - Use the .dylib shared library suffix on OS X (instead of .so in Linux). - Link with the -dynamiclib and -install_name options on OS X (instead of -shared and -soname in Linux). - Determine operating system (e.g. Linux, Darwin) during configure and substitute into config.mk.in rather than run 'uname -s' during make. - Echo operating system during configure. commit 4b72a462d7467cf815422aafac7b05037d2e3b13 Author: Field G. Van Zee Date: Thu May 10 18:35:38 2018 -0500 Enable building shared library by default. Details: - Tweaked configure so that the shared library is generated by default. - Updated --help text and configure's feedback messages reporting the status of the static/shared builds. - Changed the order of build product installation so that headers are installed last, after libraries and symlinks. commit b699bb1ff03c6e9baaa054805b4939983ae7145b Author: Field G. Van Zee Date: Thu May 10 15:54:17 2018 -0500 Adopt Linux-like .so versioning at install-time. Details: - Changed the naming conventions used for installed libraries and symlinks to more closely mirror patterns used by typical GNU/Linux libraries. Whereas previously static and shared libraries were installed and symlinked as follows: (library) libblis-0.3.2-15-haswell.a (library) libblis-0.3.2-15-haswell.so (symlink) libblis.a -> libblis-0.3.2-15-haswell.a (symlink) libblis.so -> libblis-0.3.2-15-haswell.so we now use the following naming conventions: (library) libblis.a (symlink) libblis.so -> libblis.so.0.1.2 (symlink) libblis.so.0 -> libblis.so.0.1.2 (library) libblis.so.0.1.2 where 0.1.2 indicates shared library major, minor, and build versions of 0, 1, and 2, respectively. The conventional version string can still be queried by linking to the library in question and then calling bli_info_get_version_str(). (The testsuite binary does this automatically at startup.) - Added logic to common.mk to set the soname field in the shared library via the -soname linker flag. - Added a 'so_version' file to the top-level directory containing two lines. The first line specifies the .so major version number, and the second line specifies the minor and build version numbers joined with a '.'. This file is read by configure and those values substituted into build/config.mk.in to define SO_MAJOR, SO_MINORB, and SO_MMB variables. commit fc2d9ec6bf46f6e5b19d196208415ce433e95b10 Author: Field G. Van Zee Date: Wed May 9 15:19:28 2018 -0500 Tweaks to top-level clean and distclean targets. Details: - Moved the removal of bli_config.h from cleanh to distclean. - Removed cleantest as a dependency of clean. commit bf0350305971e3991861b5117a13fda31ff97b6d Author: Field G. Van Zee Date: Tue May 8 16:49:22 2018 -0500 Renamed (shortened) a few build system variables. Details: - Renamed the following variables in config.mk (via build/config.mk.in): BLIS_ENABLE_VERBOSE_MAKE_OUTPUT -> ENABLE_VERBOSE BLIS_ENABLE_STATIC_BUILD -> MK_ENABLE_STATIC BLIS_ENABLE_SHARED_BUILD -> MK_ENABLE_SHARED BLIS_ENABLE_BLAS2BLIS -> MK_ENABLE_BLAS BLIS_ENABLE_CBLAS -> MK_ENABLE_CBLAS BLIS_ENABLE_MEMKIND -> MK_ENABLE_MEMKIND and also renamed all uses of these variables in makefiles and makefile fragments. Notice that we use the "MK_" prefix so that those variables can be easily differentiated (such as via grep) from their "BLIS_" C preprocessor macro counterparts. - Other whitespace changes to build/config.mk.in. - Renamed the following C preprocessor macros in bli_config.h (via build/bli_config.h.in): BLIS_ENABLE_BLAS2BLIS -> BLIS_ENABLE_BLAS BLIS_DISABLE_BLAS2BLIS -> BLIS_DISABLE_BLAS BLIS_BLAS2BLIS_INT_TYPE_SIZE -> BLIS_BLAS_INT_TYPE_SIZE and also renamed all relevant uses of these macros in BLIS source files. - Renamed "blas2blis" variable occurrences in configure to "blas", as was done in build/config.mk.in and build/bli_config.h.in. - Renamed the following functions in frame/base/bli_info.c: bli_info_get_enable_blas2blis() -> bli_info_get_enable_blas() bli_info_get_blas2blis_int_type_size() -> bli_info_get_blas_int_type_size() - Remove bli_config.h during 'make cleanh' target of top-level Makefile. commit 4b36e85be9b516b4089b24768f881dd976668997 Author: Field G. Van Zee Date: Tue May 8 14:26:30 2018 -0500 Converted function-like macros to static functions. Details: - Converted most C preprocessor macros in bli_param_macro_defs.h and bli_obj_macro_defs.h to static functions. - Reshuffled some functions/macros to bli_misc_macro_defs.h and also between bli_param_macro_defs.h and bli_obj_macro_defs.h. - Changed obj_t-initializing macros in bli_type_defs.h to static functions. - Removed some old references to BLIS_TWO and BLIS_MINUS_TWO from bli_constants.h. - Whitespace changes in select files (four spaces to single tab). commit 7e5648ca150757b874f6823da832f3798c40b9f9 Author: Field G. Van Zee Date: Mon May 7 18:59:19 2018 -0500 Add configure support for --libdir, --includedir. Details: - Added support for two new configure options: --libdir and --includedir. They specify the precise install directories for libraries and header files, respectively, and override any location implied by the --prefix option (including the default install prefix, if --prefix was not given). Thanks to Nico Schlömer for suggesting this via issue #195. - Removed the INSTALL_PREFIX definition/anchor from build/config.mk.in and replaced it with corresponding definitions/anchors for libdir and includedir. - Updated top-level Makefile to use the new variables, INSTALL_LIBDIR and INSTALL_INCDIR, instead of INSTALL_PREFIX (which is now no longer needed by make). - Set default sane values for INSTALL_LIBDIR and INSTALL_INCDIR in common.mk when configure has not been run, as is already done for DIST_PATH. This is to safeguard against statements in the top-level Makefile that use 'find' to locate old libraries and headers for the uninstall targets, which run regardless of make target. Without setting INSTALL_LIBDIR and INSTALL_INCDIR, those variables are empty and the 'find' ends up looking at '/', which is obviously not what we want. (Also enclosed those definitions in an IS_CONFIGURED guard so that they won't get evaluated unless configure has been run.) - Rearranged "ifeq ($(IS_CONFIGURED),yes)" conditionals in Makefile to reduce occurrences and separated "local" and top-level components of cleanblastest and cleanblistest targets to improve readability. - Adjusted out-of-tree builds so that they are no longer oblivious to the .git directories, if present, and thus now properly augment version strings with the appropriate patch number. - Include missing version string in 'configure --help' output. commit b09e4e8852a6c42895910e3bcb9041124dc8bf9f Author: Field G. Van Zee Date: Mon May 7 14:37:50 2018 -0500 Allow 'make clean' and friends without configuring. Details: - Modified top-level Makefile so that a user can run 'make distclean', 'make clean', or any of the other clean-related targets prior to running configure (or after a previous 'make distclean'). Thanks to Nico Schlömer for suggesting this via issue #197. - Made the cleanblastest and cleanblistest more comprehensive in that they now clean out build products that would have resulted from local compilation (ie: builds performed within the 'blastest' or 'testsuite' directories). - Added "cc" to list of expected compiler "vendors" since the CC variable seems to automatically be set to "cc" on Ubuntu 16.04 (which is just an alias to gcc). - Comment update to build/config.mk.in. commit 35c5a1449c3efe0b2ec43cdefcfdf00e71828149 Author: Field G. Van Zee Date: Mon May 7 12:04:57 2018 -0500 No longer update version file during configure. Details: - Recycled the core functionality of build/update-version-file.sh into a function in configure, disabling the updating of the 'version' file in the process. Instead of writing the patched version string back to the version file and then reading it again from within configure, the patched version string is now saved directly to a variable in the main() function in configure. This will prevent developers from accidentally committing configure-induced changes to the version file in between releases. commit 8adb2f919b62da4a2885ae04a10925e0e6a2e304 Author: Mathieu Poumeyrol Date: Sun May 6 19:58:16 2018 +0200 Some cross compilations fixes (#198) * cross-compilation fixes * add doc ranlib variable * icc support -dumpversion, posix compatible test, plus one stupid mistake * retab * revert version as requested commit 89acd9ebe516eeb97006dba344354bfc98826645 Merge: 4cff432d 0557eba7 Author: Field G. Van Zee Date: Wed May 2 12:53:35 2018 -0500 Merge branch 'amd' commit 4cff432d707891ada705b039a7e043558bbf3c51 Author: Nisanth M P <31736542+nisanthmpamd@users.noreply.github.com> Date: Wed May 2 23:20:42 2018 +0530 AMD specific optimizations for target 'zen' (#194) Re-enabled AMD-specific optimizations for zen. Details: - Re-enabled Zen-specific cache blocksizes for 'zen' sub-configuration. - Re-enabled small matrix gemm optimization for 'zen'. - These were both temporarily disabled during a previous merge simply due to lack of Zen hardware for testing. commit 8eda5fe7f678b413cb274bd84716995a7d0b87a9 Author: Field G. Van Zee Date: Wed May 2 12:20:37 2018 -0500 Typo fix in README.md. commit 0557eba78f5fcf28f0f039f28da79498ffde848c Author: Nisanth M P Date: Mon Mar 19 12:49:26 2018 +0530 Re-enabling the small matrix gemm optimization for target zen Change-Id: I13872784586984634d728cd99a00f71c3f904395 commit df78ceb3d6f33a27fe69017854405edaea7c40e5 Author: Nisanth M P Date: Mon Mar 19 11:34:32 2018 +0530 Re-enabling Zen optimized cache block sizes for config target zen Change-Id: I8191421b876755b31590323c66156d4a814575f1 commit 5e515f9a76f4aaf43dc21315a34d797726ca8069 Author: Field G. Van Zee Date: Tue May 1 13:44:10 2018 -0500 Tweaked new language in README.md. commit 1ddd9e316ad5024af8b606dfcebd1e7d587a130f Author: Field G. Van Zee Date: Tue May 1 13:36:28 2018 -0500 Added link to Dave Love's Fedora Copr page. Details: - Added a blurb to README.md advertising Dave Love's Copr homepage, which contains rpm packages for RHEL/Fedora-like distributions. commit 078a852f738c66c6468bd5e64b06467edc9057fd Author: Field G. Van Zee Date: Mon Apr 30 16:15:26 2018 -0500 Minor tweaks to top-level 'make clean' target. Details: - Execute 'cleanh' target as part of 'clean' - Remove cblas.h file from 'include//' as part of 'cleanh' target. - Updated the echoed (non-verbose) text for uniformity. commit 75d0d1057dda69c655bd1cd8f791cb39b54d99b8 Author: Field G. Van Zee Date: Mon Apr 30 14:57:33 2018 -0500 Renamed various datatype-related macros/functions. Details: - Renamed the following macros in bli_obj_macro_defs.h and bli_param_macro_defs.h: - bli_obj_datatype() -> bli_obj_dt() - bli_obj_target_datatype() -> bli_obj_target_dt() - bli_obj_execution_datatype() -> bli_obj_exec_dt() - bli_obj_set_datatype() -> bli_obj_set_dt() - bli_obj_set_target_datatype() -> bli_obj_set_target_dt() - bli_obj_set_execution_datatype() -> bli_obj_set_exec_dt() - bli_obj_datatype_proj_to_real() -> bli_obj_dt_proj_to_real() - bli_obj_datatype_proj_to_complex() -> bli_obj_dt_proj_to_complex() - bli_datatype_proj_to_real() -> bli_dt_proj_to_real() - bli_datatype_proj_to_complex() -> bli_dt_proj_to_complex() - Renamed the following functions in bli_obj.c: - bli_datatype_size() -> bli_dt_size() - bli_datatype_string() -> bli_dt_string() - bli_datatype_union() -> bli_dt_union() - Removed a pair of old level-1f penryn intrinsics kernels that were no longer in use. commit 01c4173238baf08e7f6700a3f91a2ea58cca50c1 Author: Field G. Van Zee Date: Sat Apr 28 14:07:34 2018 -0500 CHANGELOG update (0.3.2) commit 2fb440876690bdcec0c11a30e2b33ad100bab529 (tag: 0.3.2) Author: Field G. Van Zee Date: Sat Apr 28 14:07:31 2018 -0500 Version file update (0.3.2) commit cdf041ddadd8725e578e2f59f37ae341f26655af Author: Field G. Van Zee Date: Sat Apr 28 14:05:00 2018 -0500 Use config.mk instead of common.mk in bump-version.sh. Details: - Fixed inadvertent targeting of common.mk when testing whether configure had already been run, rather than config.mk. commit 6ded8f9f0364b3c07255e2532ada3eeb2ed2a715 Author: Field G. Van Zee Date: Sat Apr 28 14:01:29 2018 -0500 Account for recent 'make distclean' in bump-version.sh. Details: - Added logic to build/bump-version.sh that will run './configure auto' if 'common.mk' is not present (usually because 'make distclean' was run recently). commit 7c16fdce433f5dea0e83d5047553c955d8e46fd2 Author: Field G. Van Zee Date: Sat Apr 28 13:50:55 2018 -0500 Fixed typo in RELEASING file. commit 5e5ca4984fcf6d72d3036c338bb9cdc64520a325 Author: Field G. Van Zee Date: Sat Apr 28 13:48:01 2018 -0500 README updates. Details: - Updates to the top-level README files in the top-level directory as well as the 'examples/oapi' directory. commit 627b045e301defea6770dc5b64e1110cbec25153 Author: Field G. Van Zee Date: Fri Apr 27 18:11:19 2018 -0500 Added an example of using transposition with gemm. Details: - Added an example to examples/oapi/8level3.c to show how to indicate transposition when performing a gemm operation. commit 13a0eadc69d72933e322901f5b44944834e3c787 Author: Field G. Van Zee Date: Fri Apr 27 18:00:07 2018 -0500 Added more transposition/conjugation examples. Details: - Added code to examples/oapi/5level1m.c that demonstrates transposing (and conjugate-transposing) unstructured matrices. - Comment updates to 6level1m_diag.c to maintain consistency with new examples in 5level1m.c. commit 5606cd8881e75264a96af45dc8ea1905bab054f5 Author: Field G. Van Zee Date: Fri Apr 27 17:13:10 2018 -0500 Added utility module to examples/oapi. Details: - Added a new code example file to examples/oapi demonstrating how to use various utility operations. - Comment updates to other example files. - README updates. commit ff26c94c6486374c709f93c6965ea18903bd6a18 Author: Field G. Van Zee Date: Fri Apr 27 12:31:34 2018 -0500 Added missing gcc version constraint for knl. Details: - Previously forgot to add explicit enforcement of a minimum gcc version in configure script when 'knl' sub-configuration is requested. - Comment updates to configure. commit 4d97574e477b3e55ddbb6044b0542a92cd9bab30 Author: Field G. Van Zee Date: Tue Apr 24 18:48:09 2018 -0500 Added object API example code. Details: - Added an 'examples' directory at the top level. - Added an 'oapi' subdirectory in 'examples' that contains a tutorial-like sequence of example code demostrating the core functionality of BLIS's object-based API, along with a Makefile and README. Thanks to Victor Eijkhout for being the first to suggest including such code in BLIS. commit d6ab25a3232aa52b9b855088fb4b0b46ff2c00c8 Author: Field G. Van Zee Date: Tue Apr 24 18:43:03 2018 -0500 Add setijm, getijm operations. Details: - Added bli_setgetijm.c, which defines bli_setijm(), bli_getijm(), and related functions that can be used to read and write individual elements of an obj_t. - Defined a new function, bli_obj_create_conf_to(), in bli_obj.c that will create a new object with dimensions conformal to an existing object. Transposition and conjugation states on the existing object are ignored, as are structure and uplo fields. - Defined a new function, bli_datatype_string(), in bli_obj.c that returns a char* to a string representation of the name of each num_t datatype. For example, BLIS_DOUBLE is "double" and BLIS_DCOMPLEX is "dcomplex". BLIS_INT is included (as "int"), but BLIS_CONSTANT is not, and thus is not a valid input argument to bli_datatype_string(). - Added calls to bli_init_once() to various functions in bli_obj.c, the most important of which was bli_obj_create_without_buffer(). - Removed unintended/extra newline from the end of printv output. - Whitespace changes to - frame/base/bli_machval.c - frame/base/bli_machval.h - frame/0/copysc/bli_copysc.c - Trivial changes to README.md and common.mk. commit a731a428f7fc02fd6ab4f953ead828c1d06fb5a1 Author: Field G. Van Zee Date: Tue Apr 17 16:44:55 2018 -0500 Another README.md update. commit c734ee928a824b27d280a9a67b1b4bc8423d5795 Author: Field G. Van Zee Date: Tue Apr 17 16:40:05 2018 -0500 README.md update. commit 03ecad372d8eb603ee905a7b944d0544a813460a Author: Field G. Van Zee Date: Tue Apr 17 14:16:59 2018 -0500 Added RELEASING file. Details: - Added a file named 'RELEASING' that contains basic notes on how to create a new version/release of BLIS. This is mostly just a reminder to myself, but also may become useful if/when others take over development and administration of the project. commit 24b3c3149ce66546b9a1afc2cc794a637a86aa60 Merge: 60366a3f 817b67c0 Author: Field G. Van Zee Date: Mon Apr 16 18:49:38 2018 -0500 Merge branch 'dev' of github.com:flame/blis into dev commit 60366a3faba4e60cee85c3b87a3f69625f4b9026 Author: Field G. Van Zee Date: Mon Apr 16 18:46:21 2018 -0500 Updates to knl kernels and related code. Details: - Imported the 24x16 knl sgemm microkernel (and its corresonding spackm kernel) from TBLIS and enabled its use in the knl sub-config. Also Added sgemm microkernel prototype to bli_kernels_knl.h. - Updated dgemm and dpackm microkernels from TBLIS, which included an important change regarding the offsets array (changed from extern declaration to static declaration/definition). - Activated use of level-1v and -1f zen kernels in skx and knl sub-configs. - Removed some old macros no longer needed in bli_family_skx.h now that libmemkind support exists in configure. - Moved bli_avx512_macros.h to frame/include and adjusted #includes in skx and knl kernels accordingly. - Moved unused kernels in kernels/knl/3 to kernels/knl/3/other directory. - Fixed a minor bug in the 'make' output per compile when verboseness is not turned on. The rule-generating function 'make-kernel-rule' was previously passing in the name of the config, rather than the name of the kernel set returned by get-config-for-kset, which could give misleading information to the user when the kconfig_map mapped a kernel set to a sub-configuration that did not share the same name. (This didn't affect the CFLAGS that were actually used.) - Updated test/3m4m/Makefile, removing acml targets and renaming the remaining targets. commit 817b67c01752e0ca8fe230bb8ad23afc7bd0f64e Merge: 67c9c2f8 2b7108a8 Author: Field G. Van Zee Date: Mon Apr 16 14:06:26 2018 -0500 Merge branch 'dev' of github.com:flame/blis into dev commit 67c9c2f86d5ef2accc439b21581d73d82754a2e3 Author: Field G. Van Zee Date: Mon Apr 16 14:03:12 2018 -0500 Retired haswell gemm microkernels. Details: - Moved microkernels in kernels/haswell/3 to kernels/haswell/3/old. These microkernels were no longer being used and only sowed confusion to anyone inspecting the repository without being fully cognizant of the build system and how it works (and sometimes even to those who wrote the build system). Note that the haswell configuration currently employs the zen microkernels. commit 2b7108a8ef8ce958b3acad028ff07c85ff97fd63 Author: Field G. Van Zee Date: Mon Apr 16 12:35:53 2018 -0500 Minor updates to test driver makefiles. Details: - Cleaned up and homogenized the various test driver Makefiles in testsuite and test directories. - Very minor updates to test driver code. commit 9f56df95570a24587b910b169f342bd356ccbfb6 Author: Field G. Van Zee Date: Wed Apr 11 14:51:36 2018 -0500 Trivial tweaks to configure blacklisting output. Details: - Updated output of information vis-a-vis configuration blacklisting. commit f56481efebd9a7785c0618f3a12c0bec36f46333 Author: Field G. Van Zee Date: Tue Apr 10 19:02:21 2018 -0500 Cleaned up assembler version query on OS X. Details: - Swiched from querying version of 'objdump' to 'as' (e.g. the assembler). - Fixed the outputting of the version of 'as' on OS X, which required this beauty: ...=$(as -v /dev/null -o /dev/null 2>&1) - Only add sub-configs to blacklist if the sub-config hasn't already been added. commit 088c474e629535affbe111f141f895af50d109be Author: Field G. Van Zee Date: Tue Apr 10 18:09:56 2018 -0500 Added support for blacklisting via the assembler. Details: - Added logic to configure that attempts to assemble various small files containing select instructions designed to reveal whether binutils (specifically, the assembler) supports emitting those instruction sets. This information provides additional opportunities to blacklist sub- configurations that are unsupported by the environment. Thanks to Devin Matthews for pointing me towards a similar solution in TBLIS as an example. - Various other cleanups in configure. - Reorganized the detection code in the 'build' directory, bringing the "auto-detect" configuration detection, libmemkind detection, and new instruction set detection codes into a single new subdirectory named 'detect'. commit 78a24e7dada52a3582f8488795bd1a44993989d9 Author: Field G. Van Zee Date: Mon Apr 9 17:02:13 2018 -0500 Updated bli_avx512_macros.h in knl and skx configs. Details: - Downloaded updated version of bli_avx512_macros.h from TBLIS [1] in attempt to address issue #192. [1] https://github.com/devinamatthews/tblis/ commit 388f64d6ade14caa4a6c286845ad2d565378b2bb Author: Field G. Van Zee Date: Mon Apr 9 15:33:10 2018 -0500 Fixed failure to honor CC= argument to configure. Details: - Fixed a failure to observe the value of CC when selecting the compiler in configure. Thanks to Devangi Parikh for reporting this bug. - The semantics now also work for the CC environment variable. That is, if CC is set prior to running configure, that value is used, but will be overridden by specifying the CC= argument to configure. If the CC environment variable is not set, the CC= value is used. If neither the environment variable nor CC= are specified, then the choice is made internally to configure: first attempting to find gcc, then clang, and then cc. commit 45fbe66b3e2ab92f0b4fdf437d57c5d06603803d Author: Field G. Van Zee Date: Mon Apr 9 14:01:08 2018 -0500 Fixed libmemkind dependency for x86_64. Details: - Removed some old conditional code in config/knl/make_defs.mk that added -lmemkind to LDFLAGS if DEBUG_TYPE was not 'sde' and inserted code into common.mk that affirmatively filters out -lmemkind from LDFLAGS if DEBUG_TYPE is 'sde'. (Thanks to Dave Love for reporting this issue.) Other minor cleanups to neighboring code in common.mk. - Updated CRVECFLAGS in knl/make_defs.mk to be based on -march=knl, and then AVX-512 functionality is manually removed via various -mno-avx512* flags. Also, make the setting of CRVECFLAGS conditional on CC_VENDOR. Similar change to skx/make_defs.mk. - Comment/whitespace updates. commit ca982148b3b419db063cad2fa74376ec383a5c80 Author: dnp Date: Sun Apr 8 21:27:10 2018 -0500 Fixed bug in SKX sgemm microkernel. Modified SKX dgemm mircokernel to be consistent with the sgemm microkernel commit bd0276752ccdd56ff897b1a5ae022f2ffe6e0b38 Author: Field G. Van Zee Date: Fri Apr 6 18:51:43 2018 -0500 Track separate ref kernel flags for each sub-config. Details: - Renamed CVECFLAGS variables in sub-configurations' make_defs.mk files to CKVECFLAGS. - Added default defintions of two new make variables to most sub- configurations' make_defs.mk files--CROPTFLAGS and CRVECFLAGS-- which correspond to reference kernel analogues of the CKOPTFLAGS and CKVECFLAGS, which track optimization and vectorization flags for optimized kernels. Currently, two sub-configurations (knl and skx) explicitly set CRVECFLAGS to non-default values (using AVX2 instead of AVX-512 for reference kernels. Thanks to Jeff Hammond, whose feedback prompted me to make this change (issue #187). - Changed common.mk so that the get-refkern-cflags-for function returns the flags associated with the given sub-configuration's CROPTFLAGS and CRVECFLAGS (instead of CKOPTFLAGS and CKVECFLAGS). commit b9aebce19480448817373e2df2b36bd090eae41a Author: Field G. Van Zee Date: Fri Apr 6 18:37:33 2018 -0500 De-verbosify makefile fragment generation. Details: - Changed from -v1 to -v0 when calling gen-make-frag.sh from configure. The directory-by-directory recursive output didn't add much value to the user, so now we just echo a line for each top-level directory into which we will recurse (e.g. 'config', 'ref_kernels', 'frame', etc.). This also helps keep more interesting information (from earlier in the execution of configure) from scrolling out of the terminal window. commit b549b91f26948991e13364f1f26a878da0f43aa0 Author: Field G. Van Zee Date: Fri Apr 6 16:31:33 2018 -0500 Added 64-bit integer support to BLAS test drivers. Details: - Updated the build system and BLAS test drivers to use 64-bit integers when BLIS is configured for 64-bit integers in the BLAS layer. Also updated blastest/Makefile accordingly. Thanks to Dave Love for reporting the need for this feature. - Added a 'check' target to blastest/Makefile so that the user can see a summary of the tests. - Commented out the initial definition of INCLUDE_PATHS in common.mk, which was used pre-monolithic header, back when BLIS needed paths to *all* headers, rather than just a select few. This line is no longer needed since the value of INCLUDE_PATHS is overwritten by a later definition limited to only the header paths that are needed now. commit d39fa1c04265869bdf8b6f453076359eec2f3c59 Author: Field G. Van Zee Date: Thu Apr 5 19:38:35 2018 -0500 Adjusted CFLAGS used to compile bli_cntx_ref.c. Details: - Removed CKOPTFLAGS and CVECFLAGS from the set of CFLAGS used to compile bli_cntx_ref.c for each configuration. This is necessary because the file defines functions like bli_cntx_init_skx_ref(), which are called during BLIS's initialization of the global kernel structure, potentially being executed by an architecture that lacks the instruction set used to compile the kernels for, in this example, skx, which would lead to an illegal instruction error. Thanks to Dave Love for reporting this issue. - Further adjusted CFLAGS used when compiling code in the 'config' directory (e.g. bli_cntx_init_skx.c) as well as code in 'frame' so as to avoid the aforementioned issue. commit 08b123084d35680beab379012f8f5a5a8b44a443 Author: Field G. Van Zee Date: Thu Apr 5 14:25:39 2018 -0500 Added color-coding to 'make check' output. Details: - Added color coding to output of check-blistest.sh, check-blastest.sh scripts. Success messages are coded green and failure are coded red. This helps draw the eye toward those messages as the 'make checkblis', 'make checkblis-fast', and 'make checkblas' targets are executed. - Changed top-level Makefile so that execution will not halt if 'checkblis', 'checkblis-fast', or 'checkblas' targets fail, which means that the second of the two tests (BLIS and BLAS) run by 'make check' will run even if the first test fails. commit c9e4d7db7410b03c1ffe8c9727e9f1b2ba7fecfe Author: Field G. Van Zee Date: Wed Apr 4 17:13:15 2018 -0500 CHANGELOG update (0.3.1) commit 1f28d7c86e17730f05bd239c8e8d67e3e7510a4f (tag: 0.3.1) Author: Field G. Van Zee Date: Wed Apr 4 17:13:15 2018 -0500 Version file update (0.3.1) commit e6cc9ee26bcf0450f1120d5d12985b04d9fb8516 Merge: 786d15c5 3c91c7ae Author: Field G. Van Zee Date: Wed Apr 4 16:08:18 2018 -0500 Merge branch 'dev' of github.com:flame/blis into dev commit 786d15c5ef09f1f647b126b63d57e76d5810c58e Author: Field G. Van Zee Date: Wed Apr 4 16:06:47 2018 -0500 Added skx, knl to x86_64 configuration family. Details: - Added 'skx' and 'knl' sub-configurations to the 'x86_64' configuration family in the config_registry file. - Added logic to configure that avoids committing certain sub-configs to the configuration/kernel registries if those sub-configs cannot be handled properly by the chosen compiler. (This was modeled after similar logic in TBLIS's configure; thanks to Devin Matthews for pointing this out.) First, the compiler and its version are inspected and, based on the results, certain configurations are added to a "blacklist". Then, as the configuration registries are being created, configurations and/or kernels that match items in the blacklist are skipped over and not commited to the registries. Under certain circumstances, omitting a blacklisted configuration will indirectly invalidate other configurations due to the loss of availability of the original blacklisted configuration's kernel set. This additional indirect blacklist is also accounted for. - Added output to the beginning of configure that echos information about the chosen compiler as well as the configurations that are blacklisted and must be stripped from the registries. - Various other cleanups in configure, especially with respect to explicitly declaring local variables in functions. - Comment updates to config/zen/make_defs.mk regarding choice of -march flags based on compiler version. commit 3c91c7aebafb446a2582267beb3b22c8bb475b3b Author: Field G. Van Zee Date: Mon Apr 2 12:40:25 2018 -0500 Fixed 64b type mismatch warning in cblas_xerbla.c. Details: - Fixed a compiler warning concerning a type mismatch between the format specifier of the printf() call in cblas_xerbla.c and its corresponding (info) argument. The warning manifested when the CBLAS layer was enabled and the BLAS/CBLAS integer type siwas is set to 64 (the default is 32). The warning was fixed by changing the specifier from %d to %jd and typecasting the argument to intmax_t. Thanks to Dave Love for reporting this issue and submitting the patch. commit 71eaf449a812fe2bd640d21513ec83974b2edb45 Merge: 6a628184 ae9a5be5 Author: Field G. Van Zee Date: Tue Mar 27 17:21:43 2018 -0500 Merge branch 'dev' commit ae9a5be56d6f9b87278d6032154d2dcf3fb7d54f Author: dnp Date: Tue Mar 27 17:01:23 2018 -0500 Fixed bug in skx sgemm microkernel commit 3f02af0905b1e2e2e065862f8afe5e9a52f282b2 Author: Field G. Van Zee Date: Mon Mar 26 17:40:04 2018 -0500 Row storage optimizations to zen dotxf kernels. Details: - Split the main loop bodies of zen's [sd]dotxf kernels into two cases: one to handle a column-stored matrix A and one to handle a row-stored matrix A. This allows vector instructions to be employed even if A is stored by rows (and A^T appears stored as columns). Both storage cases use a common edge case loop. Thanks to Devin Matthews for this idea and for prototyping the change needed for sdotxf kernel. commit 679dcc331dd870ec680e135a3fb65ffa6e3a91c2 Author: Field G. Van Zee Date: Mon Mar 26 15:35:17 2018 -0500 Make k_iter/k_left uint64_t in bulldozer fma ukrs. Details: - Changed the declaration of k_iter and k_left for d, c, z microkernels from dim_t to uint64_t. This is needed to ensure compatibility with the movq instruction used to load the value into registers. This change should have been made a long time ago, but for some reason only recently began showing up via Travis CI. commit 6a628184f6938673440e4cdd4fed0208c51fd1f9 Author: Field G. Van Zee Date: Mon Mar 26 14:48:16 2018 -0500 Fixed a memkind-related compile-time bug on knl. Details: - Fixed a compile-time error that occurred due to the fact that BLIS_ENABLE_MEMKIND, defined in bli_config.h, was not being defined soon enough to be used in bli_system.h where it is needed to determine whether hbwmalloc.h should be #included. bli_system.h is now included after bli_config.h (and bli_config_macro_defs.h). Thanks to Dave Love for reporting this issue. - Tweaked the language used by configure to echo the status of the --with[out]-memkind option. commit e2192a8fd58ec3657434ddd407033e097edad8f4 Author: Field G. Van Zee Date: Fri Mar 23 12:53:48 2018 -0500 Removed vzeroupper intrinsics from zen kenels. Details: - Fixed a bug in the zen (also used by haswell) dotxf kernels whereby a vzeroupper instruction destoryed part of the intermediate result stored by the vdpps instructions that came right before. (The vzeroupper instrinsic was removed.) - Removed remaining vzeroupper instrinsics from other zen kernels. Previously, the vzeroupper instructions were included because BLIS is typically compiled with -mfpmath=sse. But it was brought to my attention that inserting these vzeroupper instructions is unnecessary for our purposes, since (a) -mfpmath=sse results in VEX-encoded scalar code rather than literal SSE instructions, and (b) compilers already (likely) insert vzeroupper instructions where necessary. Thanks to Devin Matthews for zeroing in on the dotxf bug. - Removed -malign-double from bulldozer make_defs.mk. This alignment was already happening by default since bulldozer is an x86_64 system. commit 22289ad23cd10b81451ce82f60d84b5f97e7fd85 Author: Field G. Van Zee Date: Thu Mar 22 18:21:30 2018 -0500 Added build system support for libmemkind. Details: - Added support for libmemkind to configure. configure attempts to detect the presence of libmemkind by compiling a small program containing #include and a call to hbw_malloc(). If successful, it is assumed that libmemkind is present and available. If present, use of libmemkind is enabled by default, and otherwise use is disabled by default. If libmemkind is present, the user may explicitly disable use of the library by running configure with the --without-memkind option. Furthermore, a configuration may disable libmemkind, perhaps conditional on some aspect of the build system, by including -DBLIS_DISABLE_MEMKIND in the configuration's CPPROCFLAGS make variable and setting the BLIS_ENABLE_MEMKIND makefile variable, set in config.mk, to 'no'. (The knl configuration makes use of this latter feature; see below.) - If enabled at configure-time, bli_system.h will #include and bli_kernel_macro_defs.h will define BLIS_MALLOC_POOL and BLIS_FREE_POOL to use hbw_malloc() and hbw_free(), respectively. - Deprecated explicit use of BLIS_NO_HBWMALLOC in config/knl/bli_family.knl.h and replaced use of -DBLIS_NO_HBWMALLOC in config/knl/make_defs.mk with -DBLIS_DISABLE_MEMKIND, which overrides (#undefs) the definition of BLIS_ENABLE_MEMKIND in bli_system.h, if it would otherwise be defined. Also, set the BLIS_ENABLE_MEMKIND makefile variable to 'no'. - common.mk now adds libmemkind to LDFLAGS if libmemkind is enabled. commit 7dc40eafdd9af3e8c4519a8d1b04d25830b4ca7a Author: Field G. Van Zee Date: Wed Mar 21 18:39:16 2018 -0500 Updates to top-level and test driver Makefiles. Details: - Added logic to common.mk that will choose a BLIS library against which to link (LIBBLIS_LINK). The default choice is the static (.a) library; the shared (.so) library is chosen only if the shared library build was enabled and the static one was disabled. - Updated the various test driver Makefiles to reference this common, pre-chosen library against which to link. (Previously, these drivers unconditionally linked against the static library and would have failed if the static library build was disabled at configure-time.) - Renamed many of the variables in common.mk and the top-level Makefile so that variables relating to the libblis.[a|so] files, including paths to those files, begin with "LIBBLIS". - Shuffled around some of the library definitions from the top-level Makefile to common.mk. - Renamed BLIS_ENABLE_DYNAMIC_BUILD to BLIS_ENABLE_SHARED_BUILD, and the @enable_dynamic@ anchor to @enable_shared@ in build/config.mk.in and in configure. - A few other cleanups in the top-level Makefile. commit 97e1eeade3c51df1bae574a9bc1da34b05bf2bd3 Author: Field G. Van Zee Date: Wed Mar 21 15:47:11 2018 -0500 Added input.operations.fast file for 'make check'. Details: - Added an 'input.operations.fast' file to testsuite directory to go along with the 'input.general.fast' file used by the 'make check' target in the top-level Makefile. This will allow the "fast" check to prune operations and/or parameter combinations from the test space in order to save time. - Currently, input.operations.fast prunes trmm3 and all transposition and conjugation parameters from the level-3 test space. - Reduced problem size tested in input.general.fast to 100 and disabled testing of 1m method. commit c441caa95aabe69f54e2160eb67bf4ca76a66c34 Author: Field G. Van Zee Date: Tue Mar 20 17:56:02 2018 -0500 README update. Details: - Minor updates to README.md. - Minor change to blastest/Makefile. commit 6fe018eb4ac8c16f2edc916c24f5994848017b7f Author: Field G. Van Zee Date: Tue Mar 20 15:35:45 2018 -0500 Added .gitkeep file to blastest/obj. Details: - Added an empty file named '.gitkeep' to blastest/obj/ so that git will track the otherwise empty directory. (This is already done for the BLIS testsuite in testsuite/obj.) commit 0e6d000db9291342913dc5f8590a28c67bbcbc95 Author: Field G. Van Zee Date: Tue Mar 20 15:08:43 2018 -0500 Updated .gitignore to ignore BLAS test out.* files. commit 40c040a31d96fbadff11f761d0cad1ef03ef2cc5 Author: Field G. Van Zee Date: Tue Mar 20 14:33:50 2018 -0500 Fixes to .travis.yml. Details: - Invoke the full BLIS testsuite via 'make testblis' instead of the fast version via 'blistest-fast' (which was wrong anyway, since the correct fast traget is 'testblis-fast'). - Invoke the BLAS tests via 'make testblas' instead of 'blastest'. commit 664ec4813d8b53121cce7a68bef47da656ece9cb Author: Field G. Van Zee Date: Tue Mar 20 13:54:58 2018 -0500 Integrated f2c'ed netlib BLAS test suite. Details: - Created a new test suite that exercises only the BLAS compatibility found in BLIS. The test suite is a straightforward port of code obtained from netlib LAPACK, run through f2c and linked to a stripped- down version of libf2c that is compiled along with the test drivers (to prevent any obvious ABI issues). The new BLAS test suite can be run from within its new local directory, 'blastest' (through its local 'make ; make run' targets) or from the top-level Makefile (via the 'make testblas' target). Output files are created in whatever directory the test drivers are run, whether it be the 'blastest' directory, the top-level source distribution directory, or the out-of-tree directory in which 'configure' was run. Also, the results of the BLAS test suite can be checked via 'make checkblas', which summarizes the presence or absence of test failures in a single line printed to stdout. - Updated the 'test' target to run both 'testblis' and 'testblas'. - Added a new 'testblis-fast' target that runs the BLIS testsuite with smaller problem sizes, allowing it to finish more quickly. - Added a 'make check' target, which runs 'checkblis-fast' and 'checkblas'. - Changed .travis.yml so that Travis CI runs 'testblis-fast' instead of 'testblis' before (calling the check-blistest.sh script to check the result manually). - Renamed some targets in the top-level Makefile to be consistent between BLAS and BLIS. commit fc53ad6c5b2e39238b1bbbf625cc0c638b9da4e1 Author: Nisanth M P Date: Mon Mar 19 12:49:26 2018 +0530 Re-enabling the small matrix gemm optimization for target zen Change-Id: I13872784586984634d728cd99a00f71c3f904395 commit d12d34e167d7dc32732c0ed135f8065a55088106 Author: Nisanth M P Date: Mon Mar 19 11:34:32 2018 +0530 Re-enabling Zen optimized cache block sizes for config target zen Change-Id: I8191421b876755b31590323c66156d4a814575f1 commit 40fa10396c0a3f9601cf49f6b6cd9922185c932e Author: Field G. Van Zee Date: Mon Mar 19 18:19:43 2018 -0500 Fixed a few obscure bugs in the BLAS API. Details: - Fixed a missing parameter in the definition of sdsdot_(). The 'sb' argument was missing. Strangely, the argument is omitted from dsdot_() in the BLAS API. - Fixed the missing 'c' or 'u' in the "?gerc" or "?geru" operation string passed to xerbla_() by the bla_ger_check() macro. - For bla_syrk_check() and bla_syr2k_check() macros, only allow conjugate-transpose (trans='c') as a valid argument for the real domain functions [sd]syrk_() and [sd]syr2k_(). (Previously, the argument was allowed even for the complex domain equivalents, which was inconsistent with the BLAS API.) commit fe7d7f1e43e4c26249eed83d4188beee1ba96202 Author: Field G. Van Zee Date: Sun Mar 18 19:43:06 2018 -0500 Fixed cpp macro parameter "ch" typo in bla_ger.c. Details: - Previously, the BLAS routine-generating macro in bla_ger.c was incorrectly passing MKSTR(ch) into the _check() macro when it should have been passing in the char that was available, chxy. I've instead changed the name of the macro parameter from chxy to ch. Similar change as made to bla_ger.h for consistency. Thanks to Dave Love in helping track this down. (NOTE: This is actually the root cause of the bug that was first patched by increasing the length of the operation name strings passed into xerbla_(), as defined by the constant BLIS_MAX_BLAS_FUNC_STR_LENGTH, in 3d1a5a7. In theory, that change could be backed out now.) - Applied aforementioned chxy->ch change to bla_dot.[ch], as well as frame/compat/cblas/f77_sub/f77_dot_sub.[ch] (not because it needed to happen, but for naming consistency). - Reformatted function signatures/prototypes of CBLAS functions and function calls to BLAS in frame/compat/cblas/f77_sub/*.c. commit cb7ed90752d1ddbac11368c4510641ca4f3a02eb Author: Field G. Van Zee Date: Fri Mar 16 13:05:56 2018 -0500 Convert op names to uppercase before calling xerbla_(). Details: - Defined a new function, bli_string_mkupper(), that calls toupper() on every non-NULL character in a string. - Call bli_string_mkupper() prior to calling xerbla_() in the level-2/-3 BLAS _check() macros. This prevents the BLAS testsuite from complaining that the operation name (e.g. "dgemm") does not match the expected value (e.g. "DGEMM"). Thanks to Dave Love for reporting this issue. commit 3d1a5a7c08fed3ba29f060fe1db2b0dc42dde223 Author: Field G. Van Zee Date: Fri Mar 16 12:24:07 2018 -0500 Fixed printf() format overflow. Details: - Increased the length of operation name strings passed to xerbla_() in the level-2 and level-3 operation _check() functions, found in frame/compat/check. This avoids a format specifier overflow warning by gcc 7. Thanks to Dave Love for reporting this issue and suggesting the fix. commit c73055f028684d998e03b2392093c393782bbfe7 Author: Field G. Van Zee Date: Thu Mar 15 16:08:21 2018 -0500 Return after non-zero info in BLAS checks. Details: - Previously, when calling the BLAS compatibility layer, discovering a parameter check failure would result in the proper setting of the info parameter (printed by xerbla_()), but would also come with an immediate abort() rather than a return. This was incorrect behavior for two overlapping reasons. (1) BLAS should return gracefully to the caller in the event of a bad set of parameters, not abort(). (2) When BLIS was being tested via the BLAS testsuite, BLIS's xerbla_() would correctly get preempted/overridden by the xerbla_() in the BLAS testsuite, but execution would then erroneously continue on to the BLIS implementation with bad parameter values. - The previous issue was addressed by disabling the abort() in BLIS's xerbla_(), changing all of the BLAS _check() functions to cpp macros, and adding a return statement to the end of each _check() macro's "if ( info != 0 )" conditional. Thanks to Dave Love for reporting this issue. commit c4f1d18b97a6a8c3ea0366aa759db597a664062a Author: Field G. Van Zee Date: Wed Mar 14 19:10:09 2018 -0500 Minor typo fix to printing arch in testsuite. Details: - Mistakenly was calling bli_cpuid_query_id() instead of bli_arch_query_id() in the recent addition to the testsuite output that prints the active sub-configuration. The former function is only used for multi-architecture builds, whereas the latter is the more general option that also works for single configuration (including 'configure auto') builds. commit 8f2fabec800a720b3e94b33c0048cc8c4ead436d Author: Devin Matthews Date: Wed Mar 14 17:43:42 2018 -0500 Make arm32 and arm64 families work. (#176) commit fc6a1842518a0820c6708c285611346d5a1419da Author: Field G. Van Zee Date: Wed Mar 14 15:31:17 2018 -0500 Print sub-configuration name in testsuite output. Details: - Added a line to the testsuite output that prints the name of the current/active sub-configuration. This is useful when linking the testsuite against multi-configuration builds because it confirms the sub-configuration that is actually being employed at runtime. Thanks to Devin Matthews for suggesting this feature. commit 9943a899d64bf7ec4a24106f6f4c70629bbe1f6e Merge: 290dd4a9 b1a15ae6 Author: Devin Matthews Date: Wed Mar 14 13:27:44 2018 -0500 Merge pull request #173 from devinamatthews/dev Fix Cortex-A9 and Cortex-A15 configs. commit b1a15ae6ee0f46c9a95cf59f9555925e0e8e21ff Author: Devin Matthews Date: Wed Mar 14 13:26:44 2018 -0500 Use BLIS_H_FLAT commit 290dd4a9feee447e69b40ad108954af78e196f7e Author: Field G. Van Zee Date: Wed Mar 14 13:15:37 2018 -0500 Allow arbitrarily deep configuration families. Details: - Updated configure so that configuration families specified in the config_registry are no longer constrained as being only one level deep. For example, previously the x86_64 family could not be defined concisely in terms of, say, intel64 and amd64 families, and instead had to be defined as containing "haswell, sandybridge, penryn, zen, etc." In other words, families were constrained to only having singleton configurations as their members. That constraint is now lifted. - Redefined x86_64 family in config_registry in terms of intel64 and amd64. commit 9cee78e006d56543ac02fc9c488905c0434e60ae Author: Devin Matthews Date: Wed Mar 14 13:09:48 2018 -0500 Fix Cortex-A9 and Cortex-A15 configs. Tested with QEMU. commit 1a3031740f7fcbbcc2c99d5c4cb50d0413407455 Author: Field G. Van Zee Date: Tue Mar 13 16:04:40 2018 -0500 Updates to ARM hardware detection support. Details: - Updated/clarified the ARM preprocessor macro branch of bli_cpuid.c. Going forward, cortexa57 (64-bit), cortexa15, and cortexa9 (32-bit) sub-configurations are supported. However, the functions that detect features specific to a15 and a9 are identical, and since a15 is tested first, it will always be chosen for arm32 hardware (even if both sub-configurations were enabled at configure-time and the library is linked and run on an a9). Thus, more work needs to be done to distinguish these two. - Added cpp guard around x86_64 portions of bli_cpuid.c. Now, either the x86_64 or ARM code will be compiled (or neither, if neither environment is detected). - In bli_arch_query_id(), call bli_cpuid_query_id() when the BLIS_FAMILY_ARM64 or BLIS_FAMILY_ARM32 macros are defined. - Added arm64 and arm32 configuration families to config_registry. - Added a note to the arch_t typedef enum in bli_type_defs.h reminding the developer to update the string array in bli_arch.c whenever new enum values are added or existing values are reordered. commit 1442d06886ebdc34d8f1cb620229ddc6062c2ce8 Author: Field G. Van Zee Date: Sun Mar 11 16:59:50 2018 -0500 Fixed misnamed kernels in _cntx_init_cortexa57.c. Details: - Changed incorrect kernel function names in bli_cntx_init_cortexa57.c: bli_sgemm_cortexa57_asm_8x12 -> bli_sgemm_armv8a_asm_8x12 bli_dgemm_cortexa57_asm_6x8 -> bli_dgemm_armv8a_asm_6x8 Thanks to Jacob Gorm Hansen for reporting this issue. commit 28bcea37dfcf0eb99a99da6f46de2a2830393d1d Merge: b1ea3092 8b0475a8 Author: praveeng Date: Fri Mar 9 19:13:08 2018 +0530 Merge master code till 06_mar_2018 to amd-staging Change-Id: I12267e5999c92417e3715fef4f36ac2131d00f1a commit 48da9f5805f0a49f6ad181ae2bf57b4fde8e1b0a Author: Field G. Van Zee Date: Wed Mar 7 12:54:06 2018 -0600 Tweaked common.mk, Makefile, skx/knl make_defs.mk. Details: - Reorganized linker-related section of common.mk so that LDFLAGS set in a sub-configuration's make_defs.mk file will not be immediately (and erroneously) overridden by the default values. - Re-enabled redirected (to file) output of the testsuite when run from the top-level Makefile via 'make test'. (For some reason, it was commented-out for the non-verbose case.) - Removed old/unnecessary code from the make_defs.mk files of skx and knl sub-configurations. commit 8b0475a87daa177916e2caac0e530c6a57fa07cf Author: Field G. Van Zee Date: Tue Mar 6 06:39:44 2018 -0600 Fixed typo in attempted fix in 1a8350f7. Details: - Mistakenly entered 148 as knl mc blocksize for double real when the value should have been 144. Thanks to Dave Love for reporting this. commit 8912e6886b97eabb4ce0c35a3609a0fd994d347b Author: Field G. Van Zee Date: Mon Mar 5 18:00:45 2018 -0600 Fixed missing flags during shared object build. Details: - Fixed a bug in common.mk that caused warning, position-independent code, miscellaneous, and general preprocessor flags to be omitted from the configuration family-specific variables that hold those values, as registered by the family's make_defs.mk file. This would most obviously manifest when targeting a configuration family such as 'intel64' while simultaneously configuring for a shared object build, as the key '-fPIC' flag would be omitted at compile-time and prevent successful linking. Thanks to Dave Love for reporting this bug. - Other cleanups to common.mk for readability and clarity. commit 1a8350f70557fc53ca0c2eadf2076710dd0d9bc9 Author: Field G. Van Zee Date: Mon Mar 5 13:32:00 2018 -0600 Fixed cache blocksize bug in knl configuration. Details: - Changed the mc blocksize for double real execution in the knl sub- configuration from 160 to 148. The old value was not a multiple of mr (which is 24), and thus the safeguards in bli_gks_register_cntx() were tripping. Thanks for Dave Love for reporting this issue. - Switch knl sub-configuration to use default blocksizes for datatypes not supported by native kernels. - Fixed typos in bli_error.c that prevented certain error strings (which report maximum cache blocksizes not being multiples of their corresponding register blocksize) from properly initializing. commit c09fffa827fe6241dc20193a1c404496664220de Author: Field G. Van Zee Date: Sat Mar 3 13:13:39 2018 -0600 Added missing cntx_t* arg in knl packm kernels. Details: - Added the missing cntx_t* argument to the function signature of packm kernels in kernels/knl/1m/. Thanks to Dave Love for reporting this issue. commit b1ea30925dff751eced23dfa94ff578a20ea0b94 Author: Field G. Van Zee Date: Fri Feb 23 17:42:48 2018 -0600 CHANGELOG update (0.3.0) Change-Id: Id038b00a62de51c9818ad249651ec5dc662f4415 commit 1ef9360b1fd0209fbeb5766f7a35402fbd080fcb Author: Field G. Van Zee Date: Thu Mar 1 14:36:39 2018 -0600 Enable non-unit vector stride tests by default. Details: - Change "vector storage schemes to test" parameter in testsuite's input.general file to "cj". This means that both unit stride column vectors and non-unit stride column vectors will be tested in operations with vector operands (e.g. level-1v, level-1f, level-2). - Very minor comment (typo) changes to input.operations. commit 8c4e55a1a1ead9a5e970200fee027ffd2c7e8454 Author: Field G. Van Zee Date: Wed Feb 28 17:01:47 2018 -0600 Added individual operation overrides in testsuite. Details: - Updated the testsuite driver so that setting one or more individual operation test switches to "2" in input.operations will enable ONLY those operations and disable all others, regardless of the values of the section overrides and other operation switches. This makes it every easy to quickly test only one or two operations, and equally easy to revert back to the previous combination of operation tests. - Added more comments to input.operations describing the use of individual "enable only" overrides. commit 34862aed89e5d5a8f35aeecd49f3052ada1f337b Author: Field G. Van Zee Date: Wed Feb 28 15:30:14 2018 -0600 Use zen kernels in haswell sub-configuration. Details: - Register use of level-1v zen intrinsic kernels for amaxv, axpyv, dotv, dotxv, and scalv, as well asl level-1f zen intrinsic kernels for axpyf and dotxf. This works because these kernels simply target AVX/AVX2, and therefore work without modification on haswell hardware. - Switch to use of zen microkernels in bli_cntx_init_haswell.c. The zen kernels are essentially identical to those used by haswell, except that now zen kernels are a bit more up-to-date. In the future, I may continue to maintain duplicates, or I may keep the kernels named after one architecture (zen or haswell) but used by both sub-configurations. - In config_registry, enable use of both haswell and zen kernels for the haswell sub-configuration. This is necessary in order to make zen kernels visible when registering kernels in bli_cntx_init_haswell.c. - Enable use of assembly-based complex gemm microkernels for zen, bli_cgemm_zen_asm_3x8() and bli_zgemm_zen_asm_3x4(), in bli_cntx_init_zen.c. This was actually intended for 1681333. commit 709f8361ebc90b96b02ebe5c5ffb6fc3b1b25e58 (tag: 0.3.0) Author: Field G. Van Zee Date: Fri Feb 23 17:42:48 2018 -0600 Version file update (0.3.0) commit d9079655c9cbb903c6761d79194a21b7c0a322bc Author: Field G. Van Zee Date: Fri Feb 23 17:42:48 2018 -0600 CHANGELOG update (0.3.0) commit 3defc7265c12cf85e9de2d7a1f243c5e090a6f9d Author: Field G. Van Zee Date: Fri Feb 23 17:38:19 2018 -0600 Applied 34b72a3 to non-active/unused microkernels. Details: - Applied the read-beyond-bounds bugfix in 34b72a3 to other haswell and zen kernels (ie: other microtile shapes) which are not used by default. This was done mostly in case someone decided to pick up these kernels and start using them, not because it affects BLIS's behavior out-of-the-box. commit 34b72a351745aa0d47bb0b74ebcd0f0a616d613d Author: Field G. Van Zee Date: Fri Feb 23 16:33:32 2018 -0600 Fixed obscure read-beyond-bounds bug in sgemm ukrs. Details: - Fixed an obscure bug in the bli_sgemm_haswell_asm_6x16 and bli_sgemm_zen_asm_6x16 microkernels when the input/output matrix C is stored with general stride (ie: both rs and cs are non-unit). The bug was rooted in the way those microkernels read from matrix C-- namely, they used vmovlps/vmovhps instead of movss. By loading two floats at a time, even if one of them was treated as junk, the assembly code could be written in a more concise manner. However, under certain conditions--if m % mr == 0 and n % nr == 0 and the underlying matrix is not an internal "view" into a larger matrix-- this could result in the very last vmovhps of the last (bottom-right) microkernel invocation reading beyond valid memory. Specifically, the low 32 bits read would always be valid, but the high 32 bits could reside beyond the bounds of the array in which the output C matrix is contained. To remedy this situation, we now selectively use movss to load any element that could be the last element in the matrix. commit 5112e1859e7f8888f5555eb7bc02bd9fab9b4442 (origin/rt) Author: Field G. Van Zee Date: Fri Feb 23 14:31:26 2018 -0600 Added missing 'restrict' to some kernels' cntx_t*. Details: - Added missing 'restrict' keyword to cntx_t* argument of function signatures corresponding to level-1v, level-1f, and level-1m kernels. This affected bli_l1v_ker_prot.h, bli_l1f_ker_prot.h, and bli_l1m_ker_prot.h. (The 'restrict' was already being used to qualify cntx_t* arguments for kernels defined in bli_l3_ker_prot.h.) - Added comments to bli_l1v_ker.h, bli_l1f_ker.h, bli_l1m_ker.h, and bli_l3_ukr.h that help explain how those headers function to produce kernel prototypes using the prototype macros defined in the files mentioned above. commit 1fa8af95d807168e0849adb668492601e7009be0 Merge: c084b03b 16813335 Author: Field G. Van Zee Date: Wed Feb 21 17:54:02 2018 -0600 Merge branch 'rt' commit c084b03b31d84427a120e391963db5419f1911ee Merge: 5d03b6e6 fa74af4e Author: Field G. Van Zee Date: Wed Feb 21 17:52:17 2018 -0600 Merge branch 'rt' commit 16813335bdb5978bc9a26cd00a32bd5a130130c4 Merge: fa74af4e 5a7005dd Author: Field G. Van Zee Date: Wed Feb 21 17:43:32 2018 -0600 Merge branch 'amd' into rt Details: - Merged contributions made by AMD via 'amd' branch (see summary below). Special thanks to AMD for their contributions to-date, especially with regard to intrinsic- and assembly-based kernels. - Added column storage output cases to microkernels in bli_gemm_zen_asm_d6x8.c and bli_gemmtrsm_l_zen_asm_d6x8.c. Even with the extra cost of transposing the microtile in registers, this is much faster than using the general storage case when the underlying matrix is column-stored. - Added s and d assembly-based zen gemmtrsm_u microkernel (including column storage optimization mentioned above). - Updated zen sub-configuration to reflect presence of new native kernels. - Temporarily reverted zen sub-configuration's level-3 cache blocksizes to smaller haswell values. - Temporarily disabled small matrix handling for zen configuration family in config/zen/bli_family_zen.h. - Updated zen CFLAGS according to changes in 1e4365b. - Updated haswell microkernels such that: - only one vzeroupper instruction is called prior to returning - movapd/movupd are used in leiu of movaps/movups for double-real microkernels. (Note that single-real microkernels still use movaps/movups.) - Added kernel prototypes to kernels/zen/bli_kernels_zen.h, which is now included via frame/include/bli_arch_config.h. - Minor updates to bli_amaxv_ref.c (and to inlined "test" implementation in testsuite/src/test_amaxv.c). - Added early return for alpha == 0 in bli_dotxv_ref.c. - Integrated changes from f07b176, including a fix for undefined behavior when executing the 1m method under certain conditions. - Updated config_registry; no longer need haswell kernels for zen sub-configuration. - Tweaked marginal and pass thresholds for dotxf. - Reformatted level-1v, -1f, and -3 amd kernels and inserted additional comments. - Updated LICENSE file to explicitly mention that parts are copyright UT-Austin and AMD. - Added AMD copyright to header templates in build/templates. Summary of previous changes from 'amd' branch. - Added s and d assembly-based zen gemm microkernels (d6x8 and d8x6) and s and d assembly-based zen gemmtrsm_l microkernels (d6x8). - Added s and d intrinsics-based zen kernels for amaxv, axpyv, dotv, dotxv, and scalv, with extra-unrolling variants for axpyv and scalv. - Added a small matrix handler to bli_gemm_front(), with the handler implemented in kernels/zen/3/bli_gemm_small_matrix.c. - Added additional logic to sumsqv that first attempts to compute the sum of the squares via dotv(). If there is a floating-point exception (FE_OVERFLOW), then the previous (numerically conservative) code is used; otherwise, the result of dotv() is square-rooted and stored as the result. This new implementation is only enabled when FE_OVERFLOW is #defined. If the macro is not #defined, then the previous implementation is used. - Added axpyv and dotv standalone test drivers to test directory. - Added zen support to old cpuid_x86.c driver in build/auto-detect/old. - Added thread-local and __attribute__-related macros to bli_macro_defs.h. commit 5d03b6e6e19d5a07f0cccf1a158f02fbd62dfd99 Author: Devin Matthews Date: Mon Feb 19 11:31:30 2018 -0600 Fix asm macro include line for KNL. Fixes #167. commit f07b176c84dc9ca38fb0d68805c28b69287c938a Author: Field G. Van Zee Date: Thu Feb 15 18:36:54 2018 -0600 Fixed an obscure bug in the 1m implementation. Details: - Fixed a bug in the way the bli_gemm1m_cntx_ref() function (defined in ref_kernels/bli_cntx_ref.c) initializes its context for 1m execution. Previously, the function probed the context that was in the process of being updated for use with 1m--this context being previously initialized/copied from a native context--for its storage preference to determine which "variant" (row- or column-oriented) of 1m would be needed. However, the _cntx_ref() function was not updating the method field of the context until AFTER this query, and the conditional which depended on it, had taken place, meaning the storage preference query function would mistakenly think the context was for native execution, since the context's method field would still be set to BLIS_NAT. This would lead it to incorrectly grab the storage preference of the complex domain microkernel rather than the corresponding real domain microkernel, which could cause the storage preference predicate to evaluate to the wrong value, which would lead to the _cntx_ref() function choosing the wrong variant. This could lead to undefined behavior at runtime. The method is now explicitly set within the context prior to calling the storage preference query function. - Updated comments in frame/ind/oapi/bli_l3_3m4m1m_oapi.c. - Fixed a typo in the commented-out CFLAGS in config/zen/make_defs.mk, which are appropriate for gcc 6.x and newer. (Mistakenly used -march=bdver4 instead of -march=znver1.) commit 1f94bb7b96eb2b67257e6c4df89e29c73e9ab386 Author: Field G. Van Zee Date: Fri Jan 19 12:46:53 2018 -0600 Document how to enable zen-specific instructions. Details: - Added as a comment in config/zen/make_defs.mk the list of compiler flags that could be added to manually enable the instructions provided by the Zen microarchitecture that are not already implied by -march=bdver4. This information, along with the previous commit's flags to selectively disable Bulldozer instructions no longer present in Zen, was gathered from [1]. I hesitate to enable use of these instructions since I don't have any Zen hardware to test on yet. [1] https://wiki.gentoo.org/wiki/Ryzen commit 1e4365b21bafa02bd108c5ac4705a25671fb9441 Author: Field G. Van Zee Date: Thu Jan 18 12:03:51 2018 -0600 Augment zen CFLAGS to prevent illegal instruction. Details: - Added various compiler flags (-mno-fma4 -mno-tbm -mno-xop -mno-lwp) so that compiling with -march=bdver4 on zen-based architectures does not result in an illegal instruction error at runtime. Note: This fix is only needed for gcc 5.4; gcc 6.3 or later supports the use of -march=znver1, which can be used in lieu of the augmented set of flags based on bdver4. Thanks to Nisanth Padinharepatt for reporting this error. commit fa74af4e1fa7385ac3f3089fe1ea7bb88c906029 Author: Field G. Van Zee Date: Tue Jan 9 13:43:15 2018 -0600 Minor labeling update for './configure -c' output. Details: - Print the name of the configuration in the output of the kernel-to-config map (and chosen pairs list) as a subtle way to remind the user that these only apply to the targeted configuration (whereas the config list and kernel list are printed without regard to which configuration was actually targeted). commit 5cdea756c7391e2c6cbfb38436ef9a205f860237 Merge: 9d8858b5 1e7a4896 Author: Field G. Van Zee Date: Sun Jan 7 19:45:20 2018 -0600 Merge branch 'rt' commit 9d8858b5cff4a4b078b87872847a5710073fff0a Merge: 0b3ca3cf f7df64da Author: Devin Matthews Date: Sun Jan 7 10:03:25 2018 -0600 Merge pull request #164 from devinamatthews/master Don't use memkind for skx configuration. commit f7df64daf6bbe6431effada6e13d8d1fab5aa221 Author: Devin Matthews Date: Sun Jan 7 09:37:25 2018 -0600 Don't use memkind for skx configuration. Fixes #163. commit 1e7a4896e0cbe73c4685fa956278e3f28273cdf9 Author: Field G. Van Zee Date: Fri Jan 5 12:33:48 2018 -0600 Minor error handling in update-version-file.sh. Details: - Added explicit handling of situations when 'git describe --tags' returns an error. This command is used by update-version-file.sh when deciding whether or not to update the version file prior to configuration. - Removed bli_packm.c and bli_unpackm.c, as they contained no source code. commit 0b3ca3cfb682715a3686fd93ebb10d4a695d1162 Author: Field G. Van Zee Date: Thu Jan 4 20:51:35 2018 -0600 Intelligently select compiler for auto-detection. Details: - Rewrote code that selects the compiler for the purposes of compiling the auto-detection executable. CC (if specified) is tried first. Then gcc. Then clang. The absolute fallback is cc. The previous code was sort of broken, and seemed to unintentionally always use gcc. - Moved various configuration-agnostic flags from config/*/make_defs.mk files to common.mk. The new mechanism appends the configuration- agnostic flags to the various compiler flag variables initialized in make_defs.mk. Flags specific to the sub-configuration are still set in make_defs.mk. - Added -Wno-tautological-compare to CMISCFLAGS when clang is in use. Also added the flag to the compiler instantiation during configure- time hardware detection (when clang is selected). - Added some missing (but mostly-optional) quotes to configure script. commit 5a7005dd44ed3174abbe360981e367fd41c99b4b Merge: 7be88705 3bc99a96 Author: Nisanth M P Date: Wed Jan 3 12:05:12 2018 +0530 Merge changes in AMD beta release 0.95 into amd branch commit 0b9c5127e91508c115228ca604ee2dac8de8f477 Author: Field G. Van Zee Date: Sat Dec 23 15:53:44 2017 -0600 Enabled C99, added stdint.h to auto-detect build. Details: - Added "-std=c99" to compiler arguments when building auto-detection driver in configure script. - Added #include to all three source files needed by auto- detection program. commit 0ce5e19c318e04909d3e664d69accb3a0fc6b988 Author: Field G. Van Zee Date: Sat Dec 23 15:32:03 2017 -0600 Reimplemented configure-time hardware detection. Details: - Reimplemented the hardware detection functionality invoked when running "./configure auto". Previously, a standalone script in build/auto-detect that used CPUID was used. However, the script attempted to enumerate all models for each microarchitecture supported. The new approach recycles the same code used for runtime hardware detection introduced in 2c51356. This has two immediate benefits. First, it reduces and consolidates the code required to detect microarchitectures via the CPUID instruction. Second, it provides an indirect way of testing at configure-time the code that is used to detect hardware at runtime. This code is (a) only activated when targeting a configuration family (such as intel64 or amd64) at configure-time and (b) somewhat difficult to test in practice, since it relies on having access to older microarchitectures. - The above change required placing conditional cpp macro blocks in bli_arch.c and bli_cpuid.c which either #include "blis.h" or #include a bare-bones set of headers that does not rely on the presence of a bli_config.h header. This is needed because bli_config.h has not been created yet when configure-time auto-detection takes places. - Defined a new function in bli_arch.c, bli_arch_string(), which takes an arch_t id and returns a pointer to a string that contains the lowercase name of the corresponding microarchitecture. This function is used by the auto-detection script to printf() the name of the sub-configuration corresponding to the detected hardware. commit 9804adfd405056ec332bb8e13d68c7b52bd3a6c1 (origin/selfinit) Author: Field G. Van Zee Date: Thu Dec 21 19:22:57 2017 -0600 Added option to disable pack buffer memory pools. Details: - Added a new configure option, --[en|dis]able-packbuf-pools, which will enable or disable the use of internal memory pools for managing buffers used for packing. When disabled, the function specified by the cpp macro BLIS_MALLOC_POOL is called whenever a packing buffer is needed (and BLIS_FREE_POOL is called when the buffer is ready to be released, usually at the end of a loop). When enabled, which was the status quo prior to this commit, a memory pool data structure is created and managed to provide threads with packing buffers. The memory pool minimizes calls to bli_malloc_pool() (i.e., the wrapper that calls BLIS_MALLOC_POOL), but does so through a somewhat more complex mechanism that may incur additional overhead in some (but not all) situations. The new option defaults to --enable-packbuf-pools. - Removed the reinitialization of the memory pools from the level-3 front-ends and replaced it with automatic reinitialization within the pool API's implementation. This required an extra argument to bli_pool_checkout_block() in the form of a requested size, but hides the complexity entirely from BLIS. And since bli_pool_checkout_block() is only ever called within a critical section, this change fixes a potential race condition in which threads using contexts with different cache blocksizes--most likely a heterogeneous environment--can check out pool blocks that are too small for the submatrices it wishes to pack. Thanks to Nisanth Padinharepatt for reporting this potential issue. - Removed several functions in light of the relocation of pool reinit, including bli_membrk_reinit_pools(), bli_memsys_reinit(), bli_pool_reinit_if(), and bli_check_requested_block_size_for_pool(). - Updated the testsuite to print whether the memory pools are enabled or disabled. commit 107801aaae180c00022f1b990bc59038c14949d2 Merge: d9c05745 0084531d Author: Field G. Van Zee Date: Mon Dec 18 16:29:28 2017 -0600 Merge branch 'master' into selfinit commit 0084531d3eea730a319ecd7018428148c81bbba7 Author: Field G. Van Zee Date: Sun Dec 17 18:58:25 2017 -0600 Updated flatten-headers.py for python3. Details: - Modifed flatten-headers.py to work with python 3.x. This mostly amounted to removing print statements (which I replaced with calls to my_print(), a wrapper to sys.stdout.write()). Thanks to Stefan Husmann for pointing out the script's incompatibility with python 3. - Other minor changes/cleanups. commit 90b11b79c302f208791bdfb1ed754873103c7ce5 Author: Field G. Van Zee Date: Sun Dec 17 17:34:32 2017 -0600 Modest performance boost to flatten-headers.py. Details: - Updated flatten-headers.py to pre-compile the main regular expression used to isolate #include directives and the header filenames they reference. The compiled regex object is then used over and over on each header file in the tree of referenced headers. This appears to have provided a 1.7-2x performance increase in the best case. - Other minor tweaks, such as renaming the main recursive function from replace_pass() to flatten_header(). commit 99dee87f30b4d437fa6b5e4ba862526d07b9f08b Author: Field G. Van Zee Date: Sun Dec 17 16:47:27 2017 -0600 Reimplemented flatten-headers.sh in python. Details: - Added flatten-headers.py, a python implementation of the bash script flatten-headers.sh. The new script appears to be 25-100x faster, depending on the operating system, filesystem, etc. The python script abides by the same command line interface as its predecessor and targets python 2.7 or later. (Thanks to Devin Matthews for suggesting that I look into a python replacement for higher performance.) - Activated use of flatten-headers.py in common.mk via the FLATTEN_H variable. - Made minor tweaks to flatten-headers.sh such as spelling corrections in comments. commit d9c0574599c3f97c0f9b6c334a077bab9452e1f4 Author: Field G. Van Zee Date: Thu Dec 14 17:13:42 2017 -0600 Allow travis failures of OS X builds that run testsuite. Details: - Added an allowance for OS X builds that run the testsuite to fail. There seems to be an issue with 1m when running in Travis CI under OS X and clang, but only in double-precision. Haven't been able to reproduce the error on my own, and thus, I can't debug it. (Hopefully it is simply a version-specific compiler bug.) commit 86cd23b7379b00a42b4ecc04fa668f1e3f9b54ee Author: Field G. Van Zee Date: Thu Dec 14 15:47:41 2017 -0600 Fixed testsuite Makefile brokenness from 9091a207. Details: - Fixed a makefile error encountered when building the testsuite directly in its directory (as opposed to indirectly via 'make test'). The fix involves introducing a new variable, BUILD_PATH, alongside the existing DIST_PATH variable. By default, BUILD_PATH is set to the current directory, and is overridden by other Makefiles used by, for example, the testsuite and standalone test drivers in testsuite or test, respectively. - Some files/directories in common.mk were redefined in terms of BUILD_DIR, such as the locations of config.mk file and the intermediate include directory. commit 6a3a8924c04d25507fc4aa593df30c56c7dc12f7 Author: Field G. Van Zee Date: Thu Dec 14 13:20:02 2017 -0600 Temporarily show Makefile's testsuite output. Details: - Disabled redirection of testsuite output for 'test' target. This is part of an attempt to debug a segmentation fault on OS X via Travis. commit 9a01080dd426915bed18229f70401bfa639dc283 Merge: 83316485 a32e8a47 Author: Field G. Van Zee Date: Thu Dec 14 11:27:19 2017 -0600 Merge branch 'master' into selfinit commit a32e8a47c022b6071302b2956af5728976c83ca9 (origin/travis) Author: Field G. Van Zee Date: Wed Dec 13 16:31:36 2017 -0600 Added an exclusion to .travis.yml. Details: - Added exclusion for out-of-tree builds on OS X (clang). commit b9f7d987df548965c86e16e0ba94d5cad0d9b399 Author: Field G. Van Zee Date: Wed Dec 13 16:22:09 2017 -0600 Cleaned up after previous travis oot debugging. Details: - Removed debugging output from common.mk related to Travis CI out-of-tree builds. - Other minor cleanups to common.mk. commit 9091a207aa8c49e279676ea02be533480b3b0d5a Author: Field G. Van Zee Date: Wed Dec 13 16:12:34 2017 -0600 Attempted fix to travis oot build failure. Details: - Found the likely cause of the Travis CI out-of-tree build failures: config.mk was being read from DIST_PATH, rather than the current directory. commit c01c71c33e236e6c91f5ddd3ec1e3faec89368c1 Author: Field G. Van Zee Date: Wed Dec 13 15:58:50 2017 -0600 Added debugging output to Makefile. Details: - Added $(info ...) statements in key locations in an attempt to reveal why Travis CI doesn't like building BLIS out-of-tree. commit 784289d69dd6b3692444d3b3e290f6a014465b72 Author: Field G. Van Zee Date: Wed Dec 13 15:31:27 2017 -0600 Updated SHELL in common.mk from /bin/bash to bash. commit d9bb1d1d4ebc89ea75d9d927d09882162a914f77 Author: Field G. Van Zee Date: Wed Dec 13 15:27:54 2017 -0600 Defined SHELL in common.mk so "echo -n" works. Details: - Defined the SHELL variable in common.mk as "/bin/bash" so that the -n option can be used with echo in the Makefile rule for flattening blis.h. Thanks to Devin Matthews for suggesting this fix. commit 9289a08667df2044f3a37af54d893efe2b56d555 Author: Field G. Van Zee Date: Wed Dec 13 15:14:27 2017 -0600 Attempt 3 on .travis.yml. commit 720bfcf0ef54fdc41df0dcaa94503edb0d5c8972 Author: Field G. Van Zee Date: Wed Dec 13 14:52:28 2017 -0600 More fixes to .travis.yml. Details: - Fixed a mistake (hopefully) in d0c4dd0 that resulted in many more osx/clang sub-tests than intended. - Shortened the variable names in an effort to make them more readable via the Travis CI web interface. commit 8717c9c97fe9b1ecd3b3192049a73976f8390ca7 Author: Field G. Van Zee Date: Wed Dec 13 14:36:37 2017 -0600 Added 'pwd' commands to .travis.yml for debugging. Details: - Added 'pwd' commands to the script portion of the .travis.yml file in an attempt to uncover the problem with the recent out-of-tree build testing changes made in d0c4dd0. commit 83316485ce10f6fcafe92a1c146282de0dd8068a Author: Field G. Van Zee Date: Wed Dec 13 14:14:50 2017 -0600 Simplified/fixed self-initialization. Details: - Fixed a race condition in self-initialization whereby the bli_is_init static variable could be erroneously read as TRUE by thread 1 while thread 0 is still executing bli_init_apis(), thus allowing thread 1 to use the library before it is actually ready. Thanks to to Minh Quan Ho and Devin Matthews for pointing out this issue. - Part of the solution to the aforementioned race condition was involved replacing the runtime initialization of the global scalar constants (e.g., BLIS_ONE, BLIS_ZERO, etc.) in bli_const.c with a static initialization of those same constants. This eliminates the need for bli_const_init() altogether. (The static initialization is made concise via preprocess macros.) - Defined bli_gks_query_cntx_noinit(), which behaves just like bli_gks_query_cntx(), except that it does not call bli_init_once(). This function is called in lieu of bli_gks_query_cntx() in bli_ind_init() and bli_memsys_init() so as to not result in any recursion into bli_init_once(). - Removed BLIS_ONE_HALF, BLIS_MINUS_ONE_HALF global scalar constants. They have no use in BLIS or its test products, and we have little reason to believe they are used by others. - Removed testsuite/out file, which was accidentally committed as part of 70640a3. commit 6526d1d4ae6dbfa854ca8d1e5f224cd6ab3fa958 Author: Field G. Van Zee Date: Tue Dec 12 13:50:43 2017 -0600 Added temp_dir argument to flatten-headers.sh. Details: - Added "temp_dir" argument to flatten-headers.sh so that the caller can specify where intermediate files should be created as the script runs. - Updated flatten-headers.sh to create intermediate files in temp_dir instead of alongside the corresponding source files. This should now (once again) allow out-of-tree builds where the BLIS distribution is read-only, or where the out-of-tree build is running concurrently with another out-of-tree build. (Thanks to Devin Matthews for pointing out the possibility of simultaneous out-of-tree builds.) commit 94755017c967630daf2e31c1f63ed5e88ab0d6ab Merge: d0c4dd00 5cf7b0c4 Author: Field G. Van Zee Date: Tue Dec 12 12:50:41 2017 -0600 Merge branch 'master' of github.com:flame/blis commit d0c4dd000ff38acc249e8acf7e0655a523991695 Author: Field G. Van Zee Date: Tue Dec 12 12:47:53 2017 -0600 Added out-of-tree build test to .travis.yml file. Details: - Modified .travis.yml file to include an out-of-tree build test (using the "auto" configure target). Thanks to Devin Matthews for this suggestion. commit 5cf7b0c4e52922069183a87dc2aa177419644e04 Author: Devin Matthews Date: Tue Dec 12 12:38:48 2017 -0600 Ignore blis.h.interm [ci skip] commit 8d8ff74d15b4a584929cec36034ba6d3c53f7d27 Author: Field G. Van Zee Date: Tue Dec 12 12:32:50 2017 -0600 Further attempt to fix out-of-tree builds. Details: - Fix applied in 87978f6 was necessary but not sufficient to fix out-of-tree builds. It turns out that using a source tree that had already built the target erroneously gave the impression that out-of-tree builds were working again, when in fact they were still broken. The additional changes in this commit should complete the fix that was started in the aforementioned commit. Thanks to Devin Matthews and Shaden Smith for their help in isolating this issue. commit 70640a37109290b57c344083c00624e13c496e30 Author: Field G. Van Zee Date: Mon Dec 11 17:18:43 2017 -0600 Implemented library self-initialization. Details: - Defined two new functions in bli_init.c: bli_init_once() and bli_finalize_once(). Each is implemented with pthread_once(), which guarantees that, among the threads that pass in the same pthread_once_t data structure, exactly one thread will execute a user-defined function. (Thus, there is now a runtime dependency against libpthread even when multithreading is not enabled at configure-time.) - Added calls to bli_init_once() to top-level user APIs for all computational operations as well as many other functions in BLIS to all but guarantee that BLIS will self-initialize through the normal use of its functions. - Rewrote and simplified bli_init() and bli_finalize() and related functions. - Added -lpthread to LDFLAGS in common.mk. - Modified the bli_init_auto()/_finalize_auto() functions used by the BLAS compatibility layer to take and return no arguments. (The previous API that tracked whether BLIS was initialized, and then only finalized if it was initialized in the same function, was too cute by half and borderline useless because by default BLIS stays initialized when auto-initialized via the compatibility layer.) - Removed static variables that track initialization of the sub-APIs in bli_const.c, bli_error.c, bli_init.c, bli_memsys.c, bli_thread, and bli_ind.c. We don't need to track initialization at the sub-API level, especially now that BLIS can self-initialize. - Added a critical section around the changing of the error checking level in bli_error.c. - Deprecated bli_ind_oper_has_avail() as well as all functions bli__ind_get_avail(), where is a level-3 operation name. These functions had no use cases within BLIS and likely none outside of BLIS. - Commented out calls to bli_init() and bli_finalize() in testsuite's main() function, and likewise for standalone test drivers in 'test' directory, so that self-initialization is exercised by default. commit 70a64432ee5a7adbee10fb7ff6d7b608c1940a7a Author: Field G. Van Zee Date: Mon Dec 11 13:14:20 2017 -0600 Fixed off-by-one indexing in bli_cpuid.c. Details: - In bli_cpuid.c, fixed an off-by-one indexing statement in vpu_count() whereby a string-terminating NULL character, '\0', is written beyond the bounds of the model_num string. - Minor whitespace and formatting edits to bli_cpuid.c. commit 87978f6261a080d261d01f9acf4e9cc18855c833 Author: Field G. Van Zee Date: Mon Dec 11 12:49:03 2017 -0600 Fixed broken out-of-tree builds since 52f9e6f. Details: - Added missing $(DIST_PATH)/ prefix to relative path to flatten-headers.sh script in common.mk so that the script could be found during out-of-tree builds. Thanks to Devin Matthews for reporting this bug. commit 513ef4d040f89a18dda5154e8c4cf1aaf7463999 Author: Field G. Van Zee Date: Mon Dec 11 12:35:59 2017 -0600 Various typecasting fixes, mis-typed enums, etc. Details: - Fixed implicit typecasting of conj_t to trans_t in bli_[un]packm_cxk.c. - Properly typecast integer arguments to match format specifier in various calls to printf() in bli_l3_thrinfo.c, bli_cntx.c, bli_pool.c, and bli_util_oapi.c. - Fixed "unsigned less-than-comparison with zero" checks in bli_check.c, bli_cntx.h. - Fixed mis-typed enums in bli_cntx.c (e.g., l1mkr_t that should have been l1fkr_t or l1vkr_t). - Fixed instances of opid_t value BLIS_GEMM that should have been l3ukr_t value BLIS_GEMM_UKR in bli_cntx_ref.c. - NOTE: These issues were identified via compiler warnings when building BLIS with clang on a rather old installation of OS X: $ clang --version Apple LLVM version 5.0 (clang-500.2.79) (based on LLVM 3.3svn) Target: x86_64-apple-darwin15.2.0 Thread model: posix commit 3bc99a96a3648f51b9acdc8a8c7e1cf4eb815459 Merge: 3a441183 78199c53 Author: prangana Date: Mon Dec 11 12:53:03 2017 +0530 Fix merge conflicts after rebase with release branch Change-Id: I581b26c6d515f717ff0dce91c7c0c92553aa2630 commit 3a44118398955d6f872e01f73ae5bb4a4f8500f7 Author: Nisanth M P Date: Wed Nov 15 11:11:17 2017 +0530 Added AMD copyright line to the changed files in last 3 commits Change-Id: I37d5dbbbe1b199e07529610a5e9cc9e49d067c66 commit 268a56c06e94d1c388766dbfe81d54efbe432809 Author: Field G. Van Zee Date: Wed Nov 1 11:51:41 2017 -0500 Revert to default SIMD alignment for bulldozer. Details: - Removed the default-overriding #define of BLIS_SIMD_ALIGN_SIZE set in config/bulldozer/bli_kernel.h. Not sure where this value came from, but it would seem to allow for insufficient starting address alignment for any matrices created via bli_malloc_user(), such as via bli_obj_create(). Thanks to Rene Sitt for reporting the behavior that led us to this bug. - This commit is a manual patch of the same fix made to the 'rt' branch in 8f150f2. commit 510a6863e28277f9446abfb77f1aea9f01d37e7a Author: Devin Matthews Date: Mon Oct 30 10:04:42 2017 -0500 Fix CVECFLAGS for bulldozer config. commit c669716790bdda5d2b11ea0a026cbc121b228842 Author: Nisanth M P Date: Tue Oct 24 16:36:36 2017 +0530 Adding __attribute__((constructor/destructor)) for CLANG case. CLANG supports __attribute__, but its documentation doesn't mention support for constructor/destructor. Compiling with clang and testing shows that it does support this. Change-Id: Ie115b20634c26bda475cc09c20960d687fb7050b commit 24e64a9d0877d788357fc63d4b947e977f8697f7 Author: Field G. Van Zee Date: Wed Oct 18 13:41:25 2017 -0500 Removed a duplicate bli_avx512_macros.h header. Details: - Removed a duplicate header file that was causing problems during installation for the 'knl' configuration. Thanks to Victor Eijkhout for reporting this issue. commit 9c0a3c4c0260cbfefb9f11532f46508b4fd19ec2 Author: Nisanth M P Date: Mon Oct 16 22:06:57 2017 +0530 Thread Safety: Move bli_init() before and bli_finalize() after main() BLIS provides APIs to initialize and finalize its global context. One application thread can finalize BLIS, while other threads in the application are stil using BLIS. This issue can be solved by removing bli_finalize() from API. One way to do this is by getting bli_finalize() to execute by default after application exits from main(). GCC supports this behaviour with the help of __attribute__((destructor)) added to the function that need to be executed after main exits. Similarly bli_init() can be made to run before application enters main() so that application need not call it. Change-Id: I7ce6cfa28b384e92c0bdf772f3baea373fd9feac commit 83f31253eb21c5ecd8a5907835e57720daae0b8b Author: Nisanth M P Date: Mon Oct 16 21:07:50 2017 +0530 Thread safety: Make the global induced method status array local to thread BLIS retains a global status array for induced methods, and provides APIs to modify this state during runtime. So, one application thread can modify the state, before another starts the corresponding BLIS operation. This patch solves this issue by making the induced method status array local to threads. Change-Id: Iff59b6f473771344054c010b4eda51b7aa4317fe commit e923402e68029be379a4297de3ac6fb155ffd928 Author: sthangar Date: Thu Sep 28 12:15:36 2017 +0530 The inner loop paralleization is turned off by default, the JR and IR loop parameters are set to 1 by default Change-Id: I8c3c2ecbbd636259f6ffb92768ec04148205c3e5 commit a64c15de19327c7595376d699be676c7003e850e Author: Field G. Van Zee Date: Tue Sep 26 19:02:53 2017 -0500 Fixed a pthread typo in previous commit. Details: - Misnamed 'pthread_mutex_t' type in bli_memsys.c as 'thread_mutex_t'. commit 42dcd589c37e1a2473ab2e1539207da97aebc07f Author: Field G. Van Zee Date: Tue Sep 26 17:00:04 2017 -0500 Fixed bugs in gemm/gemmtrsm ukr tests in testsuite. Details: - Fixed a bug in gemmtrsm test module that was due to improper partitioning into a k x k triangular matrix for the purposes of obtaining an mr x k micropanel of A with which to test. - Fixed a bug in gemm and gemmtrsm test modules that would only manifest for very large k (depending on the product of mr x kc on that architecture). The bug arose from the fact that the test module was triggering the allocation of blocks from the internal memory pools, which are limited in size. This allocation imposes an implicit assumption that the micro- panel being tested with will fit inside, and this assumption is violated for large values of k. Arbitrarily large k may now be tested for both operation tests. - Added OpenMP/pthread critical sections around the setting or getting of statuses from the induced method operation lookup table in bli_l3_ind.c. - Added the 'static' keyword to all pthread_mutex_t global variables in BLIS. - Thanks to Nisanth Padinharepatt of AMD for reporting the first and third issues. commit 206beb68ff73b75f5c382413967aacbb8a0aac3a Author: Field G. Van Zee Date: Sat Sep 9 14:10:15 2017 -0500 Updated bibtex info for BLIS5 (3m4m) article. commit 0c8c0363aeb1f4aa88f7ec2d02403dab05a6e014 Author: sthangar Date: Mon Aug 28 16:44:42 2017 +0530 Bug fix for the testsuite build failing Change-Id: I7cd8c9d187387c48b2564e45cbfb8df985e93d77 commit 63d1c84465b50f64787808dd3e8494e683c16821 Author: sthangar Date: Wed Aug 23 13:01:14 2017 +0530 Adding auto hardware detection for Zen Change-Id: I40ce6705dd66b35000c4ccddffad1c5b65998caf commit 537fb2a895b09be94b11947696fd2da629be24dd Author: Devin Matthews Date: Tue Aug 15 10:02:25 2017 -0500 Add vzeroupper to Intel AVX kernels. commit 7628de3f76f78a44788807605a4601ddda445854 Author: Field G. Van Zee Date: Thu Aug 10 16:24:28 2017 -0500 Removed trailing enum commas from bli_type_defs.h. Details: - Removed trailing commas from enums in bli_type_defs.h. Thanks to Erling Andersen for pointing out this inconsistency and suggesting the change. commit a666fd4e267ffae3d4b21f38d569c61ff56adc9e Author: Field G. Van Zee Date: Sat Aug 5 13:04:31 2017 -0500 Added edge handling to _determine_blocksize_b(). Details: - Added explicit handling of situations where i == dim to bli_determine_blocksize_b_sub(). This isn't actually needed by any current use case within BLIS, but handling the situation is nonetheless prudent. Thanks to Minh Quan for reporting this issue and requesting the fix. commit 0c8afa546d7f33760415519ba328d7c49eb7aa06 Author: Field G. Van Zee Date: Fri Aug 4 14:17:44 2017 -0500 Fixed a minor bug in level-3 packm management. Details: - Fixed a bug in bli_l3_packm() that caused cntl_t-cached packed mem_t entries to be released and then re-acquired unnecessarily. (In essence, the "<" operands in the conditional that guards the release-and-reacquire code block simply needed to be swapped.) The bug should have only affected performance (rather than the computed result). Thanks to Minh Quan for identifying and reporting the bug. commit 6cf68a185d83fa46d438fcef65258ace78e24b13 Author: Devin Matthews Date: Mon Jul 31 15:19:51 2017 -0500 Change lsame_ signature to match lapacke. commit 6a9bd97295cc4fb1cbcd28f69824a43c073c9a76 Author: Field G. Van Zee Date: Sat Jul 29 20:17:05 2017 -0500 Fixed pthreads compile bug with previous commit. Details: - Erroneously passed family parameter into l3int_t function despite that function not taking the parameter. Oops. commit 95adc43d800431dc0a02ca83a51426dbef641ad6 Author: Field G. Van Zee Date: Sat Jul 29 14:53:39 2017 -0500 Moved 'family' field from cntx_t to cntl_t. Details: - Removed the family field inside the cntx_t struct and re-added it to the cntl_t struct. Updated all accessor functions/macros accordingly, as well as all consumers and intermediaries of the family parameter (such as bli_l3_thread_decorator(), bli_l3_direct(), and bli_l3_prune_*()). This change was motivated by the desire to keep the context limited, as much as possible, to information about the computing environment. (The family field, by contrast, is a descriptor about the operation being executed.) - Added additional functions to bli_blksz_*() API. - Added additional functions to bli_cntx_*() API. - Minor updates to bli_func.c, bli_mbool.c. - Removed 'obj' from bli_blksz_*() API names. - Removed 'obj' from bli_cntx_*() API names. - Removed 'obj' from bli_cntl_*(), bli_*_cntl_*() API names. Renamed routines that operate only on a single struct to contain the "_node" suffix to differentiate with those routines that operate on the entire tree. - Added enums for packm and unpackm kernels to bli_type_defs.h. - Removed BLIS_1F and BLIS_VF from bszid_t definition in bli_type_defs.h. They weren't being used and probably never will be. commit a98e4aa547f61ab09dd91d11478c2a2ef9882e11 Author: Devin Matthews Date: Thu Jul 20 14:50:13 2017 -0500 Clang can't make up it's mind what to support. commit 32eb36c3e8c2add2528514272044de16faed0c8f Author: Devin Matthews Date: Thu Jul 20 12:54:58 2017 -0500 Add default #define for __has_extension. commit 2a9aa134f7c29d3d4fdc160022ff257e61885a95 Author: Devin Matthews Date: Thu Jul 20 10:04:34 2017 -0500 Add fallbacks to __sync_* or __c11_atomic_* builtins when __atomic_* is not supported. Fixes #143. commit 6f07a034d575e1e9e30bb6417b8fcb77cf301297 Author: Field G. Van Zee Date: Wed Jul 19 15:40:48 2017 -0500 Updated ar option list used by all configurations. Details: - Dropped 'u' from the list of modifiers passed into the library archiver ar. Previously, "cru" was used, while now we employ only "cr". This change was prompted by a warning observed on Ubuntu 16.04: ar: `u' modifier ignored since `D' is the default (see `U') This caused me to realize that the default mode causes timestamps to be zero, and thus the 'u' option, which causes only changed object files to be inserted, is not applicable. commit 32bc03f9eed8795cfd2f2615d1c9f8673e039c57 Author: Field G. Van Zee Date: Wed Jul 19 13:51:53 2017 -0500 Added --force-version=STRING option to configure. Details: - Added an option to configure that allows the user to force an arbitrary version string at configure-time. The help text also now describes the usage information. - Changed the way the version string is communicated to the Makefile. Previously, it was read into the VERSION variable from the 'version' file via $(shell cat ...). Now, the VERSION variable is instead set in config.mk (via a configure-substituted anchor from config.mk.in). commit befaee6dd8b2a72de9e0461fe2ec1f36e9f88f3c Author: Field G. Van Zee Date: Tue Jul 18 17:56:00 2017 -0500 Updated openmp/pthread barriers with GNU atomics. Details: - Updated the non-tree openmp and pthreads barriers defined in bli_thrcomm_openmp.c and bli_thrcomm_pthreads.c to instead call a common implementation in bli_thrcomm.c, bli_thrcomm_barrier_atomic(). This new implementation goes through the same motions as the previous codes, but protects its loads and increments with GNU atomic built-ins. These atomic statements take memory ordering parameters that allow us to specify just enough constraints for the barrier to work as intended on weakly-ordered hardware. The prior implementation was only guaranteed to work on systems with strongly- ordered memory. (Thanks to Devin Matthews for suggesting this change and his crash-course in atomics and memory ordering.) - Removed 'volatile' from structs' barrier field declarations in bli_thrcomm_*.h. - Updated bli_thrcomm_pthread.? files to use renamed struct barrier fields consistent with that of the _openmp.? files. - Updated other bli_thrcomm_* files to rename "communicator" variables to simply "comm". commit 8f739cc847fcff2ddeeb336f8b2b9d080eb16f6c Author: Field G. Van Zee Date: Mon Jul 17 19:03:22 2017 -0500 Added API to set mt environment variables. Details: - Renamed bli_env_get_nway() -> bli_thread_get_env(). - Added bli_thread_set_env() to allow setting environment variables pertaining to multithreading, such as BLIS_JC_NT or BLIS_NUM_THREADS. - Added the following convenience wrapper routines: bli_thread_get_jc_nt() bli_thread_get_ic_nt() bli_thread_get_jr_nt() bli_thread_get_ir_nt() bli_thread_get_num_threads() bli_thread_set_jc_nt() bli_thread_set_ic_nt() bli_thread_set_jr_nt() bli_thread_set_ir_nt() bli_thread_set_num_threads() - Added #include "errno.h" to bli_system.h. - This commit addresses issue #140. - Thanks to Chris Goodyer for inspiring these updates. commit 10163833075fd42be5b5b503acc855f91a484cfd Author: Marat Dukhan Date: Thu Jul 13 21:39:24 2017 -0700 Fix Emscripten builds commit c09b30d115eade72f44f37bf90aa848c9c0e79af Author: Minh Quan HO Date: Fri Jul 7 10:52:05 2017 +0200 set missing free_fp in bli_membrk_init for free-ing GEN_USE buffers The membrk's free_fp is called when releasing GEN_USE buffers, but this free_fp is not set in bli_membrk_init commit 997628ed9793c72e9ef576dd8d715cfec27c4862 Author: sthangar Date: Fri Jun 30 12:23:19 2017 +0530 Reducing the framework overhead of GEMV routines Change-Id: I83607ad767bff74e305e915b54b0ea34ec3e5684 commit ee869066168239b710ad9938bb0e1ae454883f3a Author: Kiran Varaganti Date: Tue Jul 4 12:57:32 2017 +0530 Improved efficiency of dGEMM for large matrices by reducing TLB load misses and majorly L3 cache misses. This is achieved by changing the packed block sizes of matrix A & B. Now the optimum values are MC_D = 510 and KC_D = 1024. Change-Id: I2d8bdd5f62f2d1f8782ae2997f3d7a26587d1ca4 commit 7b933b90b1859c96de49a402d48de82909bc73e5 Author: Devin Matthews Date: Tue Jun 6 20:23:17 2017 -0500 Add new SSI acknowledgment commit 3485abba4b426fbf42b146a9611a0841f6d236c6 Author: sthangar Date: Wed May 24 11:48:16 2017 +0530 Checked in the small matrix code to compute GEMM called with A transpose case Change-Id: I29f40046d43d7a4b037c1cb322503ee26495f462 commit de16beb83b29b4b9748f70db985b0fe04db85f7d Author: Devin Matthews Date: Fri May 26 14:49:31 2017 -0400 PACKDIM_MR=8 didn't work out, but messing with the prefetching helps 2%. commit 25d0e618544b6eea7d3f13c7aec513ac0139801d Author: Devin Matthews Date: Fri May 26 14:47:36 2017 -0400 Revert "Change PACKDIM_MR (double) for haswell to 8." This reverts commit 681eec913d7c2ebcff637cec5c1627ced9a92b99. commit c5bdd84b35bc2a8ebf55b7763fb56c0c945be0cb Author: Devin Matthews Date: Fri May 26 12:28:09 2017 -0500 Change PACKDIM_MR (double) for haswell to 8. commit 172789d562001293b973bbdd8015bd27d37292e8 Author: Field G. Van Zee Date: Wed May 17 13:03:52 2017 -0500 Restored deleted lines from makefile fragments. commit 3ea9bd2c8e90dbd35655fa6a5b953dfea1f308fe Author: Devin Matthews Date: Wed May 17 12:29:44 2017 -0500 Change to /bin/sh. All scripts checked with Debian's checkbashisms. Also check for clang first in auto-detect.sh. commit 49438409eedb98d3f0ebf00b8d1eee0ae45f4f8c Author: Devin Matthews Date: Wed May 17 12:27:14 2017 -0500 Remove shebangs from makefiles. commit 497e2640474c016d576dce3530fa6a66891642a0 Author: J M Dieterich Date: Tue May 16 23:11:22 2017 -0400 Fix if/else structure. Thanks to TravisCI. commit 835035c56a8de36ad25bb8d1375db170d489ef57 Author: J M Dieterich Date: Tue May 16 22:23:27 2017 -0400 Mark piledriver compilable w/ clang. commit 6cdb533472ee61af297c1f948307abbf45828887 Author: J M Dieterich Date: Tue May 16 22:12:12 2017 -0400 Mark bulldozer compilable w/ clang. commit a85697d62272da06d28cd1c947f6cf1098df6467 Author: J M Dieterich Date: Tue May 16 22:06:59 2017 -0400 Correct error message. commit e0c64cad271058688a2b999caf8c2767dc3aef7e Author: J M Dieterich Date: Tue May 16 22:03:23 2017 -0400 Indeed once can compile for carrizo also using clang. commit 4aafe0505d3f0954d095ded5459a76976e5093b4 Author: J M Dieterich Date: Tue May 16 21:50:49 2017 -0400 A bunch of shebang fixes from unportable /bin/bash to portable /usr/bin/env bash commit abaeaa68ea11e84be1810f564d6f38d506cbeb6a Author: Field G. Van Zee Date: Fri May 5 15:06:56 2017 -0500 Fixed a bug in norm1v, norm1m. Details: - Fixed a bug that manifested as improperly-computed 1-norm for vectors and matrices. This is one of the few operations in BLIS that does not have its own test module within the testsuite, hence why it went undetected for so long. The bad 1-norms were being used to normalize matrices in the testsuite after initialization, which led to some matrices containing a combination of "large" and "small" values. This tended to push the residuals computed after each test away from zero. In some cases, they were off *just* enough to the testsuite to label it a "failure". Many thanks to Jeff Hammond for reporting this bug. (Wonky details: the bug was due to improperly-defined level-0 scalar macros for abval2, an operation that computes the absolute square, or complex magnitude/modulus. Certain complex domain instances of abval2 were being incorrectly defined in terms of real-only solutions, leading to bad results. This level-0 operation forms the basis of norm1v/norm1m. absq2 was also affected, but almost nothing uses this operation.) commit cc3107ae1c2074f72b724aa748d2e5b4cb290ed5 Author: Devin Matthews Date: Thu May 4 10:35:22 2017 -0500 Setting any one of BLIS_NT_[IJ][CR] overrides BLIS_NUM_THEADS. Missing BLIS_NT_XX's are defaulted to 1. Fixes #123. commit c8ab91f70d399ee14edd30a3a5c46b24c5d2f910 Author: Field G. Van Zee Date: Wed May 3 15:04:51 2017 -0500 Disable complex 3m/4m in testsuite by default. Details: - Disabled testsuite tests of all level-3 implementations based on 3m and 4m. This will improve testing runtime on Travis CI as well as for anyone manually running the testsuite using default test parameters. Thanks to Devin Matthews for suggesting this change. commit 9700f0e5785007ddafb72a5ca83800dee61fd35c Author: Jeff Hammond Date: Tue May 2 19:25:21 2017 -0700 allow KNL build without hbwmalloc.h (i.e. emulated) we want to be able to run BLIS KNL binaries on non-KNL machines via SDE. although it is possible to install hbwmalloc implementation on such systems, it is easier not to, since obviously the performance of SDE execution is not representative so there is no reason to emulate HBW allocation. commit 17dcd5a33ff91967f67e7c0ba09b4f18754609a4 Author: Field G. Van Zee Date: Tue May 2 16:48:43 2017 -0500 Fixed stray parentheses in README citations. commit 2910d44ff9e1d951d3249313f4ab39d18ea1b48d Author: Field G. Van Zee Date: Tue May 2 16:38:43 2017 -0500 CHANGELOG update (0.2.2) commit 5ca3863220e07972fcefc6682ddd3f6e54fe4a94 Author: Field G. Van Zee Date: Tue May 2 15:48:30 2017 -0500 Fixed a trsm1m bug that affected right-side cases. Details: - Fixed a bug introduced in 1c732d3 that affected trsm1m_r. The result was nondeterministic behavior (usually segmentation faults) for certain problem sizes beyond the 1m instance of kc (e.g. 128 on haswell). The cause of the bug was my commenting out lines in bli_gemm1m_ukr_ref.c which explicitly directed the virtual gemm micro-kernel to use temporary space if the storage preference of the [real domain] gemm ukernel did not match the storage of the output matrix C. In the context of gemm, this handling is not needed because agreement between the storage pref and the matrix is guaranteed by a high-level optimization in BLIS. However, this optimization is not applied to trsm because the storage of C is not necessarily the same as the storage of the micro-panels of B--both of which are updated by the micro-kernel during a trsm operation. Thus, the guarantee of storage/preference agreement is not in place for trsm, which means we must handle that case within the virtual gemm micro-kernel. - Comment updates and a minor macro change to bli_trsm*_cntx_init() for 3m1, 4m1a, and 1m. commit 1af0b09f5c275ee7bac896cc6f36f42af721d9b5 Author: Field G. Van Zee Date: Tue May 2 12:09:39 2017 -0500 README.md update. Details: - Updated bibtex entries for 4th BLIS paper, and adds entries for 5th and 6th BLIS papers. commit db4a0bb8ba7cd697d68be8e5632371ee3e59fd63 Author: Field G. Van Zee Date: Fri Mar 17 12:07:27 2017 -0500 Whitespace reformatting to armv8a kernels file. Details: - Updated formatting of function signature/header in kernels/armv8a/3/bli_gemm_opt_4x4.c. commit e3eb01f6b990e205b15edcbaffd3d54b3ddd1ca4 Author: Field G. Van Zee Date: Tue Feb 21 15:33:39 2017 -0600 Disabled experiment-related 1m code. Details: - Commented out code in frame/ind/oapi/bli_l3_3m4m1m_oapi.c that was specifically inserted to facilitate the benchmarking of 1m block-panel and panel-block algorithms. - Updates to test/3m4m/Makefile, runme.sh script, and test_gemm.c to reflect changes used/needed during benchmarking. commit 4f61528d56eed6a139eeac9db0c44e56f2d2d136 Author: Field G. Van Zee Date: Wed Jan 25 16:25:46 2017 -0600 Added 1m-specific APIs for bp, pb gemm algorithms. Details: - Defined bli_gemmbp_cntl_create(), bli_gemmpb_cntl_create(), with the body of bli_gemm_cntl_create() replaced with a call to the former. - Defined bli_cntl_free_w_thrinfo(), bli_cntl_free_wo_thrinfo(). Now, bli_cntl_free() can check if the thread parameter is NULL, and if so, call the latter, and otherwise call the former. - Defined bli_gemm1mbp_cntx_init(), bli_gemm1mpb_cntx_init(), both in terms of bli_gemm1mxx_cntx_init(), which behaves the same as bli_gemm1m_cntx_init() did before, except that an extra bool parameter (is_pb) is used to support both bp and pb algorithms (including to support the anti-preference field described below). - Added support for "anti-preference" in context. The anti_pref field, when true, will toggle the boolean return value of routines such as bli_cntx_l3_ukr_eff_prefers_storage_of(), which has the net effect of causing BLIS to transpose the operation to achieve disagreement (rather than agreement) between the storage of C and the micro-kernel output preference. This disagreement is needed for panel-block implementations, since they induce a transposition of the suboperation immediately before the macro-kernel is called, which changes the apparent storage of C. For now, anti-preference is used only with the pb algorithm for 1m (and not with any other non-1m implementation). - Defined new functions, bli_cntx_l3_ukr_eff_prefers_storage_of() bli_cntx_l3_ukr_eff_dislikes_storage_of() bli_cntx_l3_nat_ukr_eff_prefers_storage_of() bli_cntx_l3_nat_ukr_eff_dislikes_storage_of() which are identical to their non-"eff" (effectively) counterparts except that they take the anti-preference field of the context into account. - Explicitly initialize the anti-pref field to FALSE in bli_gks_cntx_set_l3_nat_ukr_prefs(). - Added bli_gemm_ker_var1.c, which implements a panel-block macro-kernel in terms of the existing block-panel macro-kernel _ker_var2(). This technique requires inducing transposes on all operands and swapping the A and B. - Changed bli_obj_induce_trans() macro so that pack-related fields are also changed to reflect the induced transposition. - Added a temporary hack to bli_l3_3m4m1m_oapi.c that allows us to easily specify the 1m algorithm (block-panel or panel-block). - Renamed the following cntx_t-related macros: bli_cntx_get_pack_schema_a() -> bli_cntx_get_pack_schema_a_block() bli_cntx_get_pack_schema_b() -> bli_cntx_get_pack_schema_b_panel() bli_cntx_get_pack_schema_c() -> bli_cntx_get_pack_schema_c_panel() and updated all instantiations. Also updated the field names in the cntx_t struct. - Comment updates. commit 1d728ccb2394e77365e7c42683db6579c5fba014 Author: Field G. Van Zee Date: Fri Nov 25 18:29:49 2016 -0600 Implemented the 1m method. Details: - Implemented the 1m method for inducing complex domain matrix multiplication. 1m support has been added to all level-3 operations, including trsm, and is now the default induced method when native complex domain gemm microkernels are omitted from the configuration. - Updated _cntx_init() operations to take a datatype parameter. This was needed for the corresponding function for 1m (because 1m requires us to choose between column-oriented or row-oriented execution, which requires us to query the context for the storage preference of the gemm microkernel, which requires knowing the datatype) but I decided that it made sense for consistency to add the parameter to all other cntx initialization functions as well, even though those functions don't use the parameter. - Updated bli_cntx_set_blkszs() and bli_gks_cntx_set_blkszs() to take a second scalar for each blocksize entry. The semantic meaning of the two scalars now is that the first will scale the default blocksize while the second will scale the maximum blocksize. This allows scaling the two independently, and was needed to support 1m, which requires scaling for a register blocksize but not the register storage blocksize (ie: "packdim") analogue. - Deprecated bli_blksz_reduce_dt_to() and defined two new functions, bli_blksz_reduce_def_to() and bli_blksz_reduce_max_to(), for reducing default and maximum blocksizes to some desired blocksize multiple. These functions are needed in the updated definitions of bli_cntx_set_blkszs() and bli_gks_cntx_set_blkszs(). - Added support for the 1e and 1r packing schemas to packm, including 1e/1r packing kernels. - Added a minor optimization to bli_gemm_ker_var2() that allows, under certain circumstances (specifically, real domain beta and row- or column-stored matrix C), the real domain macrokernel and microkernel to be called directly, rather than using the virtual microkernel via the complex domain macrokernel, which carries a slight additional amount of overhead. - Added 1m support to the testsuite. - Added 1m support to Makefile and runme.sh in test/3m4m. Also simplified some code in test_gemm.c driver. commit 0d1b90286e29aa8b768e280b5286d92c02ad87a1 Author: Jeff Hammond Date: Tue Oct 25 21:15:26 2016 -0700 never use libm with Intel compilers Intel compilers include a highly optimized math library (libimf) that should be used instead of GNU libm. yes, this change is for ALL targets, including those that are not supported by the Intel compiler. there is no harm in doing this, and it is future-proof in the event that the Intel compilers support other architectures. commit b150870397e7aee558e61d1bd72a0c0d1d99bee8 Author: Field G. Van Zee Date: Fri Dec 8 16:08:41 2017 -0600 Removed most "old" directories. Details: - Removed the vast majority of directories named "old", which contained deprecated code that I wasn't quite ready to jettison from the source tree. commit 270c65985df849297ba1951aa3b56c03948d7775 Author: Field G. Van Zee Date: Fri Dec 8 15:21:18 2017 -0600 Modified bli_getopt() for thread-safety. Details: - Changed the interface of bli_getopt() to take a new argument, a getopt_t struct, that stores the values of optarg, optind, opterr, and optopt, and updated the implementation accordingly. (Previously, these variables were assumed to be global.) - Added a function for initializing a getopt_t struct. - Changed test_libblis.c--currently the only consumer of bli_getopt()--to utilize the new getopt_t state object. commit ce4d8fabc2e39371f89c12192fb707be82ae021a Merge: 39be59f2 e05a8dfa Author: Field G. Van Zee Date: Thu Dec 7 17:36:44 2017 -0600 Merge branch 'master' of github.com:flame/blis commit 39be59f2a8470f40475907d9dd52639b8a911a92 Author: Field G. Van Zee Date: Thu Dec 7 17:35:20 2017 -0600 Replaced several macros with static function APIs. Details: - Reimplemented several sets of get/set-style preprocessor macros with static functions, including those in the following frame/base headers: auxinfo, cntl, mbool, mem, membrk, opid, and pool. A few headers in frame/thread were touched as well: mutex_*, thrcomm, and thrinfo. commit e05a8dfa7cc7df41e966c1ad04e51c482b308b23 Merge: 79507337 4423e33d Author: dnp Date: Wed Dec 6 16:45:24 2017 -0600 Merge branch 'rt' commit 4423e33dc593115cda92c5763d756d7ad1298aa9 Author: dnp Date: Wed Dec 6 16:35:03 2017 -0600 Adding SKX kernels and configuration. commit 79507337e140daec7639f6eb3ed9cfe6e123d342 Author: Field G. Van Zee Date: Wed Dec 6 16:21:35 2017 -0600 Various checks to ensure that arch_t id is in range. Details: - Expanded checking of the arch_t id in bli_gks.c--either passed in from the caller or as returned from bli_arch_query_id()--against the expected range of id values. Thanks to Devangi Parikh for suggesting these additional sanity checks. commit fde7c1126c58373ecde83471890b257399144876 Author: Field G. Van Zee Date: Mon Dec 4 16:11:01 2017 -0600 Added 'uninstall-old-headers' target to Makefile. Details: - Defined a new 'uninstall-old-headers' target that allows users of BLIS to uninstall no-longer-needed headers left over from previous installations. - Fixed the 'uninstall-old' target so that it will install both .a and .so libraries. - Renamed 'uninstall-old' to 'uninstall-old-libs'. - Added 'uninstall-old' target (different from previous 'uninstall-old' target) that combines 'uninstall-old-libs' and 'uninstall-old-headers'. commit d4ee770bde213a87aa6049245145318324dc6b51 Author: Field G. Van Zee Date: Mon Dec 4 14:53:43 2017 -0600 Create/install monolithic cblas.h. Details: - When CBLAS is enabled at configure-time, BLIS now creates a monolithic cblas.h using the same flatten-header.sh script that was recently introduced for creating monolithic blis.h header files. The top-level Makefile will also install this cblas.h file into the install prefix alongside blis.h when the 'install' target is invoked. The two header files are compatible with one another. Regardless whether the user's source #includes cblas.h, both blis.h and cblas.h, or just blis.h, the user will get the CBLAS function prototypes and enums, as expected. commit 52f9e6f1b6468785af8947317656445d4729fc8b Merge: ab57b979 21360dd8 Author: Field G. Van Zee Date: Fri Dec 1 12:28:09 2017 -0600 Merge branch 'rt' commit 21360dd8e2c7287100645e109acaabcc6ba1140c Author: Field G. Van Zee Date: Wed Nov 29 14:11:34 2017 -0600 Fixed cntx_t packm query when ker_id > _NUM_PACKM_KERS. Details: - Fixed a subtle bug in bli_cntx_get_[un]packm_ker_dt() in which the function fails to return NULL when passed a kernel id argument that is equal to or beyond BLIS_NUM_[UN]PACKM_KERS. Instead, the function was attempting to index into the cntx_t's packm kernel array, which resulted in undefined behvaior. Thanks to Devangi Parikh for finding this bug. commit 244a6f4e66e8ff091e995f8090ce779c1928aa8b Author: Field G. Van Zee Date: Tue Nov 28 17:48:48 2017 -0600 Fixed POSIX sed non-compliance in flatten-header.sh. Details: - Changed GNU usage of 'i' and 'a' sed commands used in flatten-header.sh to POSIX-compliant usage that will work on OS X's sed. commit 45078621676833e53a2878af8f89479c4f93b8ab Author: Field G. Van Zee Date: Tue Nov 28 15:16:22 2017 -0600 Generate/compile with/install monolithic blis.h. Details: - Rewrote monolithify-header.sh (and renamed to flatten-header.sh) so that headers are inserted recursively. This improves performance by a factor of 3-4x. - Modified configure to create an 'include/' directory in which make can create a monolithic header. - Modified the top-level Makefile so that a monolithic header is generated unconditionally prior to compilation (stored in include/) and so that the single header is installed instead of the 450 or so header files that reside throughout the framework source tree. - Added "include/*/*.h" to .gitignore file. - Removed some pnacl/emscripten leftovers that I intended to include in a1caeba (mostly in testsuite/Makefile). - Trivial comment changes to frame/include/bli_f2c.h. commit 1f30b1301bf6d6047ec29e57a5fde8eb1072a0ee Author: Field G. Van Zee Date: Sat Nov 25 16:54:26 2017 -0600 Added missing framework support for x86_64 family. Details: - Added support for the x86_64 configuration family to bli_arch.c and bli_arch_config.h. Thanks to Johannes Dieterich for reporting this issue. - Bumped the default value for BLIS_SIMD_NUM_REGISTERS from 16 to 32 and the default value for BLIS_SIMD_SIZE from 32 to 64. This will support configuration families that include Skylake and newer processors without any supported needed in the bli_family_*.h file. The semantics of these values have always been "maximum" and not exact values; comments in bli_kernel_macro_defs.h and the github wiki have been adjusted accordingly. commit 9f39806c4ed484c9ed13edf96005838d977722a9 Author: Field G. Van Zee Date: Tue Nov 21 16:03:56 2017 -0600 Fixed a bug in e31f0b3/b131b9a. Details: - Erroneously placed the "don't overwrite existing blocksize" logic in bli_blksz_init*() rather than in bli_cntx_set_blkszs(). It belongs in the latter because that function copies blocksizes as-is from the blksz_t function argument to the appropriate field in the cntx_t. If the blksz_t was previously initialized selectively, based on the sign of the blocksize value passed into bli_blksz_init*(), that just leaves some fields possibly uninitialized (with garbage values), which definitely will not work. - The aforementioned logic has been moved to bli_cntx_set_blkszs() via a new function bli_blksz_copy_if_pos(), which selectively copies only the blocksizes that are greater than zero. commit b131b9a025c15f548d4c2952a9ec85eee3d139b1 Author: Field G. Van Zee Date: Tue Nov 21 14:30:26 2017 -0600 Updated configs to omit setting some blocksizes. Details: - Employ the new semantics of bli_blksz_init*() in e31f0b3 in various sub-configurations' bli_cntx_init_*() functions by passing in 0 for register and cache blocksizes that correpond to gemm microkernel datatypes that were not registered, allowing the default values set by the bli_cntx_init_*_ref() function call to remain. commit 499a4c002f895744ecaf81ef7f62d2d6d0d7d594 Merge: e31f0b3e 6c3ba502 Author: Field G. Van Zee Date: Tue Nov 21 14:25:08 2017 -0600 Merge branch 'rt' of github.com:flame/blis into rt commit e31f0b3e2dba19ca8a2946bc21beb136a42d0f57 Author: Field G. Van Zee Date: Tue Nov 21 14:21:25 2017 -0600 Subtle update to bli_blksz_init*() API. Details: - Updated the semantics of bli_blksz_init() and bli_blksz_init_ed() so that non-positive blocksize values are ignored entirely. This provides an easy way to indicate that certain existing values should not be touched by the update. Thanks to Devangi Parikh for feedback that led to these changes. commit 6c3ba502a11f87bc67555d26154cfd39d0af1bac Author: Field G. Van Zee Date: Tue Nov 21 13:50:53 2017 -0600 Added 'x86_64' sub-config directory. Details: - Added missing x86_64 configuration directory, which was intended to be part of b7ca580. - Added -Wfatal-errors compiler warning flag to all configurations so that compilation stops after the first error. - Changed the vectorization flags for intel64 configuration to be compatible with 'penryn', the oldest sub-config included in that family. - Changed the vectorization flags for penryn to target the 'core2' microarchitecture and ssse3. commit 25eee3cc49b0631812485d4d5ceef0c23ed1b6dd Author: Field G. Van Zee Date: Tue Nov 21 12:34:20 2017 -0600 Added a dummy file to kernels/generic. Details: - Added a dummy file to kernels/generic, which was previously empty, so that git would begin tracking the otherwise-empty directory. This directory's existence is necessary for proper execution of configure for any configuration family that contains the 'generic' sub-configuration. Thanks to Johannes Dieterich for reporting the issue that led to this fix. commit ef024ce4cafa217669eaabb31ff8ab6df93cca05 Author: Field G. Van Zee Date: Mon Nov 20 18:08:29 2017 -0600 More tweaks to monolithify-header.sh Details: - Further fixes monolithify-header.sh script. - Removed unnecessary #include "blis.h" from frame/3/bli_l3_packm.h. commit 5028e7dec269b62895511453272585da36e591b5 Author: Field G. Van Zee Date: Mon Nov 20 17:00:37 2017 -0600 Second attempt to implement travis_wait. Details: - Corrected accidental misplacement of the travis_wait prefix (on the wrong line of the .travis.yml file) in commit 13e5d91. commit 13e5d9107b3763cba46fb1bae87476852601b47c Author: Field G. Van Zee Date: Mon Nov 20 15:57:06 2017 -0600 Added travis_wait prefix to testsuite via Travis. Details: - It appears that Travis CL has implemented a new policy that results in a test failing if it does not produce any output for more than 10 minutes. (Two test instances are now failing in Travis despite the most recent commit not affecting the library or testsuite.) This issue can be worked around by executing the test run via travis_wait, which takes an optional time parameter. This commit attempts to use 'travis_wait 30' in the .travis.yml file to prevent the early failure at 10 minutes. commit a1caeba0ea79c8fecb1abadca1f91c6367ab3afb Author: Field G. Van Zee Date: Mon Nov 20 13:31:20 2017 -0600 Removed pnacl, emscripten support from Makefile. commit 78199c539beaa50f37893add220261ce0dcb921a Merge: b3d8ab2e ab57b979 Author: praveeng Date: Mon Nov 20 15:51:20 2017 +0530 Merge master code till 01-Nov-2017 to amd-staging Change-Id: I40b53f876db84c8b947b3f2385c9b882245c6603 commit 9df6dda9ec51a0d40166169d2d8a2f84b42266e6 Author: Field G. Van Zee Date: Sat Nov 18 19:03:26 2017 -0600 Improvements, bugfixes to monolithify-header.sh. commit 21d26201f90b884eb8d5de279ed74bbd244ffcb5 Merge: 43baa3b3 b7ca5806 Author: Field G. Van Zee Date: Sat Nov 18 14:16:53 2017 -0600 Merge branch 'rt' of github.com:flame/blis into rt commit 43baa3b327d5ae1e2ba619432687b4dd849b05e3 Author: Field G. Van Zee Date: Sat Nov 18 14:14:44 2017 -0600 Removed unnecessary flags for generic config. Details: - Removed -D_POSIX_C_SOURCE=200112L and -m64 flags from make_defs.mk file of generic sub-configuration. These flags are generally not necessary, and particularly not desirable for the generic configuration since they unnecessarily restrict the environments in which the configuration can be built. commit b7ca580618f9382b7982168fd035ed058f83e4c2 Author: iotamudelta Date: Sat Nov 18 14:56:05 2017 -0500 [WIP] Add x86 and x86_64 processor families. (#154) * Add x86 and x86_64 processor families. * Use generic config as fallback for more families. After discussion with fgvanzee, a) it's "generic" and 2) use it for all the families as a fallback. Goal is that if a specific CPU is not yet supported by a family (say a new Intel microarchitecture on x86_64), it'll fall through to still work with the slower "generic" kernels commit 870597d1663aaba1b74d7654b1d4946280aa0d3f Author: Field G. Van Zee Date: Fri Nov 17 17:06:42 2017 -0600 Added bash script for creating monolithic headers. Details: - Added a new script, monolithify-header.sh, to the 'build' directory. This script recursively replaces all #include directives in a selected file with the contents of the header files referenced by each directive. The idea is to "flatten" a tree of .h files into a single file, with the script acting as a C preprocessor that only processes #include directives. commit c76f77f4cc1e71988251c5e63cf6ef137477bf9c Author: Field G. Van Zee Date: Fri Nov 17 15:10:52 2017 -0600 Removed unnecessary #include "blis.h" from header. Details: - Removed an errant #include "blis.h directive from bli_cntx_ind_stage.h. The generaly policy is that no header file in BLIS should include blis.h. This will be important in the near future when using a tool to recursively create a monolithic blis.h file from its consitutent headers. commit 2bb9bc6e9536fa239fbc19a7efaaf151116e15b4 Author: Field G. Van Zee Date: Fri Nov 17 13:50:14 2017 -0600 Miscellaneous tweaks to gks, rt functionality. Details: - Updated bli_cpuid_query_id() so that BLIS_ARCH_GENERIC is always returned if the hardware fails to test positive for any supported sub-configuration. - Defined bli_gks_init_ref_cntx(), which will call the context initialization function bli_cntx_init_configname() for the sub-configuration 'configname' associated with the arch_t id returned by bli_arch_query_id(). This makes initializing a reference context easy for experts who wish to construct those contexts. commit b3d8ab2ea02c127ab241532abc214624f35bfaab Merge: 189ffbb0 fe71c06e Author: Santanu Thangaraj Date: Wed Nov 15 01:33:12 2017 -0500 Merge "Added AMD copyright line to the changed files in last 3 commits" into amd-staging commit fe71c06e42b072407c83112779055b0afb67173d Author: Nisanth M P Date: Wed Nov 15 11:11:17 2017 +0530 Added AMD copyright line to the changed files in last 3 commits Change-Id: I37d5dbbbe1b199e07529610a5e9cc9e49d067c66 commit d5bf79e50bf97072bbe7117c86b7c45e6e707ea0 Author: Field G. Van Zee Date: Mon Nov 13 14:24:29 2017 -0600 Miscellaneous tweaks and fixes. Details: - Fixed incorrect calling sequence in bli_cntx_init_knl.c--an instance of bli_blksz_init_easy() that should have been bli_blksz_init(). - Fixed a bug in code that is supposed to output the list of sub-directories in the 'config' directory when configure script is run with no arguments. - Expanded the output of "make showconfig" to include more info from config.mk. - Minor changes to build/auto-detect/cpuid_x86.c, mostly in preparation for someone to add excavator and zen support. - Added a link to the ConfigurationHowTo wiki to config_registry. - Other minor tweaks to configure. commit 673e5184030532c4ebd9fdeecbaa6442bb3ad54f Merge: 2c51356a 8f150f28 Author: Field G. Van Zee Date: Wed Nov 1 17:37:42 2017 -0500 Merge branch 'rt' of github.com:flame/blis into rt commit 2c51356a8b2699c99f9507c80d69c08a35d45fe3 Author: Field G. Van Zee Date: Wed Nov 1 17:37:02 2017 -0500 Implemented runtime hardware detection via cpuid. Details: - Added runtime support for selecting an appropriate arch_t value based on the results of the cpuid instruction (for x86_64). This allows deferral of choosing a context (kernels, blocksizes, etc.) until runtime, which allows BLIS to be built with support for multiple microarchitectures. Currently, only amd64 and intel64 configurations are registered in the config_registry; however, one could create custom configuration families to support arbitrary sets of x86_64 microarchitectures. - Current Intel microarchitectures supported via cpuid are knl, haswell, sandybridge, and penryn. - Current AMD microarchitectures supported via cpuid are: zen, excavator, steamroller, piledriver, and bulldozer. commit ab57b979046479bcda7f83165838a80117c2ad95 Author: Field G. Van Zee Date: Wed Nov 1 11:51:41 2017 -0500 Revert to default SIMD alignment for bulldozer. Details: - Removed the default-overriding #define of BLIS_SIMD_ALIGN_SIZE set in config/bulldozer/bli_kernel.h. Not sure where this value came from, but it would seem to allow for insufficient starting address alignment for any matrices created via bli_malloc_user(), such as via bli_obj_create(). Thanks to Rene Sitt for reporting the behavior that led us to this bug. - This commit is a manual patch of the same fix made to the 'rt' branch in 8f150f2. commit 8f150f28a678c4a0c1591400177ad7cca81fcaec Author: Field G. Van Zee Date: Wed Nov 1 11:41:45 2017 -0500 Revert to default SIMD alignment for bulldozer. Details: - Removed the default-overriding #define of BLIS_SIMD_ALIGN_SIZE set in bli_family_bulldozer.h. Not sure where this value came from, but it would seem to allow for insufficient starting address alignment for any matrices created via bli_malloc_user(), such as via bli_obj_create(). Thanks to Rene Sitt for reporting the behavior that led us to this bug. commit e3f10557caf114441fbfff990e3ce3576c177bdc Author: Field G. Van Zee Date: Mon Oct 30 13:37:54 2017 -0500 Use perl for some substitution for OS X compatibility. Details: - Discovered that sed commands where the replacement string contains '\n' are problematic with the version of sed present in OS X. For these cases cases in the configure script, we instead use 'perl -pe' for search-and-replace functionality. - Various other minor comment/whitespace tweaks to configure. - Removed remaining lines of code related to setting/checking variables to track "unregistered" configurations. commit dd45cfdfc3d8f9acf4cf7f69138d9b83dafc8842 Merge: 3e4f42a4 f60c827b Author: Field G. Van Zee Date: Mon Oct 30 12:23:05 2017 -0500 Merge branch 'master' into rt commit f60c827ba95f452c8454fb914f5564f4895bf644 Author: Devin Matthews Date: Mon Oct 30 10:04:42 2017 -0500 Fix CVECFLAGS for bulldozer config. commit 3e4f42a4d2ebb37b95988933d92e561c5b2cc201 Author: Field G. Van Zee Date: Fri Oct 27 11:41:37 2017 -0500 Typecast l1mkr_t enum value prior to comparison. Details: - Typecast l1mkr_t enum value in bli_cntx.h to guint_t before testing for out-of-range value. This is an attempt to pacify a strange warning from clang on OS X that is seemingly the result of the following compiler warning flag: -Wtautological-constant-out-of-range-compare commit aec6e038d942d35b81bbd723a640cce2c054fb8e Author: Field G. Van Zee Date: Thu Oct 26 16:12:36 2017 -0500 Removed associative arrays from configure. Details: - Implemented a replacement for associative arrays in the configure script that does not utilize arrays, and therefore works in pre-4.0 versions of bash. (It appears that Mac OS X will be stuck with version 3.2 indefinitely due to bash switching to the GPL 3.0 license starting with version 4.0.) commit 189ffbb0d37262b21acddc0d35b4a22f2cbbca94 Merge: 06e0e635 3eb44f67 Author: Santanu Thangaraj Date: Wed Oct 25 02:00:30 2017 -0400 Merge changes Ie115b206,I7ce6cfa2,Iff59b6f4 into amd-staging * changes: Adding __attribute__((constructor/destructor)) for CLANG case. Thread Safety: Move bli_init() before and bli_finalize() after main() Thread safety: Make the global induced method status array local to thread commit 3eb44f67618b91ae5f5f0aaaba67e38f16042ee4 Author: Nisanth M P Date: Tue Oct 24 16:36:36 2017 +0530 Adding __attribute__((constructor/destructor)) for CLANG case. CLANG supports __attribute__, but its documentation doesn't mention support for constructor/destructor. Compiling with clang and testing shows that it does support this. Change-Id: Ie115b20634c26bda475cc09c20960d687fb7050b commit 07c352188bf5265af242255f8e6fcb97050d973d Author: Field G. Van Zee Date: Mon Oct 23 16:59:22 2017 -0500 Added "generic" configuration. Details: - Added a "generic" configuration that leaves the default blocksizes and kernels unchanged. This replaces the older "reference" configuration. Updated auto-detect script and code accordingly. - Added support for generic configuration to arch_t (bli_type_defs.h), bli_gks_init() (bli_gks.c), and bli_arch_config.h - Moved bli_arch_query_id() to bli_arch.c (and prototype to bli_arch.h). - Whitespace changes to configurations' make_defs.mk files. commit c1a98d6f70608b02a1e6bcad6ba020a60773dace Author: Field G. Van Zee Date: Mon Oct 23 14:24:41 2017 -0500 Minor update to .travis.yml file. commit 75b9383f01caa8b83f8be0117e15085b0d807ba6 Author: Field G. Van Zee Date: Fri Oct 20 16:41:22 2017 -0500 Minor header renaming ahead of bli_arch.c. Details: - Renamed the various configurations' "bli_arch_.h" header files (replacing "arch" with "family") to free up the 'bli_arch' namespace for a different purpose (hardware detection). - Renamed "bli_arch.h" and "bli_arch_pre_macro_defs.h" in frame/include to "bli_arch_config.h" and "bli_arch_config_pre.h", respectively. commit 482af51add26d5ed103c3e3f167657f273b32c7a Author: Field G. Van Zee Date: Fri Oct 20 15:44:26 2017 -0500 Fixed 'make test' target from top-level Makefile. Details: - Updated the top-level Makefile's build rule for testsuite object files to properly obtain CFLAGS via get-frame-cflags-for() function instead of simply using the $(CFLAGS) variable (which is empty). This means that 'make test' should now work as expected. commit 3c269f700d207efe6c04193f09d519c88c1d4045 Author: Field G. Van Zee Date: Fri Oct 20 13:57:21 2017 -0500 Makefile updates for test drivers, testsuite. Details: - Fixed semi-broken testsuite Makefile and very-broken test driver Makefiles, as well as those for test/3m4m, test/thread_ranges, and test/exec_sizes sub-directories. - Factored out much of the top-level Makefile into common.mk. A Makefile needs only set DIST_PATH to the relative path to the top level of the BLIS source distribution before including common.mk in order to acquire all of the definitions typically needed in a Makefile that tests BLIS. commit 0557189d463446b4c32077cdcf0467fa71ca68dc Author: Field G. Van Zee Date: Wed Oct 18 15:05:27 2017 -0500 Minor updates to .travis.yml, configure script. commit 2553734d1d62043793f4e783a027349ef6d4d563 Merge: 453deb29 37534279 Author: Field G. Van Zee Date: Wed Oct 18 13:46:50 2017 -0500 Merge branch 'master' into rt commit 375342799cbae981c28d831793af588d7951f3f6 Author: Field G. Van Zee Date: Wed Oct 18 13:41:25 2017 -0500 Removed a duplicate bli_avx512_macros.h header. Details: - Removed a duplicate header file that was causing problems during installation for the 'knl' configuration. Thanks to Victor Eijkhout for reporting this issue. commit 453deb29068889698e274f269c9aa90eea99b527 Author: Field G. Van Zee Date: Wed Oct 18 13:29:32 2017 -0500 Implemented runtime kernel management. Details: - Reworked the build system around a configuration registry file, named config_registry', that identifies valid configuration targets, their constituent sub-configurations, and the kernel sets that are needed by those sub-configurations. The build system now facilitates the building of a single library that can contains kernels and cache/register blocksizes for multiple configurations (microarchitectures). Reference kernels are also built on a per-configuration basis. - Updated the Makefile to use new variables set by configure via the config.mk.in template, such as CONFIG_LIST, KERNEL_LIST, and KCONFIG_MAP, in determining which sub-configurations (CONFIG_LIST) and kernel sets (KERNEL_LIST) are included in the library, and which make_defs.mk files' CFLAGS (KCONFIG_MAP) are used when compiling kernels. - Reorganized 'kernels' directory into a "flat" structure. Renamed kernel functions into a standard format that includes the kernel set name (e.g. 'haswell'). Created a "bli_kernels_.h" file in each kernels sub-directory. These files exist to provide prototypes for the kernels present in those directories. - Reorganized reference kernels into a top-level 'ref_kernels' directory. This directory includes a new source file, bli_cntx_ref.c (compiled on a per-configuration basis), that defines the code needed to initialize a reference context and a context for induced methods for the microarchitecture in question. - Rewrote make_defs.mk files in each configuration so that the compiler variables (e.g. CFLAGS) are "stored" (renamed) on a per-configuration basis. - Modified bli_config.h.in template so that bli_config.h is generated with #defines for the config (family) name, the sub-configurations that are associated with the family, and the kernel sets needed by those sub-configurations. - Deprecated all kernel-related information in bli_kernel.h and transferred what remains to new header files named "bli_arch_.h", which are conditionally #included from a new header bli_arch.h. These files are still needed to set library-wide parameters such as custom malloc()/free() functions or SIMD alignment values. - Added bli_cntx_init_.c files to each configuration directory. The files contain a function, named the same as the file, that initializes a "native" context for a particular configuration (microarchitecture). The idea is that optimized kernels, if available, will be initialized into these contexts. Other fields will retain pointers to reference functions, which will be compiled on a per-configuration basis. These bli_cntx_init_*() functions will be called during the initialization of the global kernel structure. They are thought of as initializing for "native" execution, but they also form the basis for contexts that use induced methods. These functions are prototyped, along with their _ref() and _ind() brethren, by prototype-generating macros in bli_arch.h. - Added a new typedef enum in bli_type_defs.h to define an arch_t, which identifies the various sub-configurations. - Redesigned the global kernel structure (gks) around a 2D array of cntx_t structures (pointers to cntx_t, actually). The first dimension is indexed over arch_t and the inner dimension is the ind_t (induced method) for each microarchitecture. When a microarchitecture (configuration) is "registered" at init-time, the inner array for that configuration in the 2D array is initialized (and allocated, if it hasn't been already). The cntx_t slot for BLIS_NAT is initialized immediately and those for other induced method types are initialized and cached on-demand, as needed. At cntx_t registration, we also store function pointers to cntx_init functions that will initialize (a) "reference" contexts and (b) contexts for use with induced methods. We don't cache the full contexts for reference contexts since they are rarely needed. The functions that initialize these two kinds of contexts are generated automatically for each targeted sub-configuration from cpp-templatized code at compile-time. Induced method contexts that need "stage" adjustments can still obtain them via functions in bli_cntx_ind_stage.c. - Added new functions and functionality to bli_cntx.c, such as for setting the level-1f, level-1v, and packm kernels, and for converting a native context into one for executing an induced method. - Moved the checking of register/cache blocksize consistency from being cpp macros in bli_kernel_macro_defs.h to being runtime checks defined in bli_check.c and called from bli_gks_register_cntx() at the time that the global kernel structure's internal context is initialized for a given microarchitecture/configuration. - Deprecated all of the old per-operation bli_*_cntx.c files and removed the previous operation-level cntx_t_init()/_finalize() invocations. Instead, we now query the gks for a suitable context, usually via bli_gks_query_cntx(). - Deprecated support for the 3m2 and 3m3 induced methods. (They required hackery that I was no longer willing to support.) - Consolidated the 1e and 1r packm kernels for any given register blocksize into a single kernel that will branch on the schema and support packing to both formats. - Added the cntx_t* argument to all packm kernel signatures. - Deprecated the local function pointer array in all bli_packm_cxk*.c files and instead obtain the packm kernel from the cntx_t. - Added bli_calloc_intl(), which serves as the calloc-equivalent to to bli_malloc_intl(). Useful when we wish to allocate and initialize to zero/NULL. - Converted existing cpp macro functions defined in bli_blksz.h, bli_func.h, bli_cntx.h into static functions. commit 4607aac297e55ad540cbe5fffbe02e6b1889c181 Author: Nisanth M P Date: Mon Oct 16 22:06:57 2017 +0530 Thread Safety: Move bli_init() before and bli_finalize() after main() BLIS provides APIs to initialize and finalize its global context. One application thread can finalize BLIS, while other threads in the application are stil using BLIS. This issue can be solved by removing bli_finalize() from API. One way to do this is by getting bli_finalize() to execute by default after application exits from main(). GCC supports this behaviour with the help of __attribute__((destructor)) added to the function that need to be executed after main exits. Similarly bli_init() can be made to run before application enters main() so that application need not call it. Change-Id: I7ce6cfa28b384e92c0bdf772f3baea373fd9feac commit 0f5ce26fc597cda6e8ae93a7526f52eb8cba01e9 Author: Nisanth M P Date: Mon Oct 16 21:07:50 2017 +0530 Thread safety: Make the global induced method status array local to thread BLIS retains a global status array for induced methods, and provides APIs to modify this state during runtime. So, one application thread can modify the state, before another starts the corresponding BLIS operation. This patch solves this issue by making the induced method status array local to threads. Change-Id: Iff59b6f473771344054c010b4eda51b7aa4317fe commit b882648af87deb1b365fc6b3e94151e69c5ccfa4 Merge: 8b379069 e02d3cb8 Author: Field G. Van Zee Date: Wed Oct 11 16:32:21 2017 -0500 Merge branch 'master' into rt commit 06e0e6351acb9481225975ad9a4e0b8925336621 Author: sthangar Date: Thu Sep 28 12:15:36 2017 +0530 The inner loop paralleization is turned off by default, the JR and IR loop parameters are set to 1 by default Change-Id: I8c3c2ecbbd636259f6ffb92768ec04148205c3e5 commit e02d3cb84190a345ebe9b32f53db03a1838976b1 Author: Field G. Van Zee Date: Tue Sep 26 19:02:53 2017 -0500 Fixed a pthread typo in previous commit. Details: - Misnamed 'pthread_mutex_t' type in bli_memsys.c as 'thread_mutex_t'. commit f5962a1aae0fb3c9be104d0035c0d73210e7f670 Author: Field G. Van Zee Date: Tue Sep 26 17:00:04 2017 -0500 Fixed bugs in gemm/gemmtrsm ukr tests in testsuite. Details: - Fixed a bug in gemmtrsm test module that was due to improper partitioning into a k x k triangular matrix for the purposes of obtaining an mr x k micropanel of A with which to test. - Fixed a bug in gemm and gemmtrsm test modules that would only manifest for very large k (depending on the product of mr x kc on that architecture). The bug arose from the fact that the test module was triggering the allocation of blocks from the internal memory pools, which are limited in size. This allocation imposes an implicit assumption that the micro- panel being tested with will fit inside, and this assumption is violated for large values of k. Arbitrarily large k may now be tested for both operation tests. - Added OpenMP/pthread critical sections around the setting or getting of statuses from the induced method operation lookup table in bli_l3_ind.c. - Added the 'static' keyword to all pthread_mutex_t global variables in BLIS. - Thanks to Nisanth Padinharepatt of AMD for reporting the first and third issues. commit 8e917b256ca2d4bcdc059fe98d86be8775c69561 Author: Field G. Van Zee Date: Sat Sep 9 14:10:15 2017 -0500 Updated bibtex info for BLIS5 (3m4m) article. commit 7be887057358df4978a4833eeae0c17e15acd9d1 Author: Nisanth M P Date: Mon Aug 28 17:38:22 2017 +0530 Merging "Adding auto hardware detection for Zen" Change-Id: Id450fb0c4f91a5cd5cbdc06970f4f9ed28dd8520 commit e056d810d16621891ead032603de0c2105cfc0f7 Author: sthangar Date: Mon Aug 28 16:44:42 2017 +0530 Bug fix for the testsuite build failing Change-Id: I7cd8c9d187387c48b2564e45cbfb8df985e93d77 commit 83796b7caf745fafc263e9e5e1bfcf5eff00c025 Merge: 8176f4e4 d1ee7762 Author: Kiran Varaganti Date: Mon Aug 28 05:23:28 2017 -0400 Merge "Adding auto hardware detection for Zen" into amd-staging commit d1ee776202b26874333af7a91b6d2686342c4c81 Author: sthangar Date: Wed Aug 23 13:01:14 2017 +0530 Adding auto hardware detection for Zen Change-Id: I40ce6705dd66b35000c4ccddffad1c5b65998caf commit 8176f4e43872714b997f1a5f83056daadb0ff1a5 Merge: 12413018 adafe974 Author: praveeng Date: Mon Aug 28 12:21:16 2017 +0530 resolving conflicts bli_gemm_front.c and LICENCE Change-Id: Id24ce53896d4c1c7ceccc3e004014a0ecceb5474 commit 57e1e5cd51e7ffe8612c96a20b6a041b55426ddb Merge: f86ce54d d6ef56c6 Author: Nisanth M P Date: Tue Aug 22 17:07:44 2017 +0530 Merge AMD authored changes commit adafe974b4bc3fc0663bc2f6f4ce2fde71a97988 Merge: f86ce54d 7dc78b49 Author: Devin Matthews Date: Tue Aug 15 15:17:21 2017 -0500 Merge pull request #150 from devinamatthews/vzeroupper Add vzeroupper to Intel AVX kernels. commit 7dc78b49f97e6b3cd6d72fcdc588ace534d0e700 Author: Devin Matthews Date: Tue Aug 15 10:02:25 2017 -0500 Add vzeroupper to Intel AVX kernels. commit f86ce54d6f315006984534fe29e47a2deaacc9f5 Author: Field G. Van Zee Date: Thu Aug 10 16:24:28 2017 -0500 Removed trailing enum commas from bli_type_defs.h. Details: - Removed trailing commas from enums in bli_type_defs.h. Thanks to Erling Andersen for pointing out this inconsistency and suggesting the change. commit 60a1eeb2317939d732b9eb6ff1e0d6d668c9a1e5 Author: Field G. Van Zee Date: Sat Aug 5 13:04:31 2017 -0500 Added edge handling to _determine_blocksize_b(). Details: - Added explicit handling of situations where i == dim to bli_determine_blocksize_b_sub(). This isn't actually needed by any current use case within BLIS, but handling the situation is nonetheless prudent. Thanks to Minh Quan for reporting this issue and requesting the fix. commit b01c80829907d50ec79977fba8e7b53cfe7db80a Author: Field G. Van Zee Date: Fri Aug 4 14:17:44 2017 -0500 Fixed a minor bug in level-3 packm management. Details: - Fixed a bug in bli_l3_packm() that caused cntl_t-cached packed mem_t entries to be released and then re-acquired unnecessarily. (In essence, the "<" operands in the conditional that guards the release-and-reacquire code block simply needed to be swapped.) The bug should have only affected performance (rather than the computed result). Thanks to Minh Quan for identifying and reporting the bug. commit 8b379069fcd4811669855b1248ece831f190dff6 Merge: 1f3a5819 05925dd5 Author: Field G. Van Zee Date: Tue Aug 1 15:30:40 2017 -0500 Merge branch 'master' into rt commit 05925dd5d30e8f403bb671ce33029170d65ce7c0 Merge: 803bbef0 cecdc05d Author: Devin Matthews Date: Tue Aug 1 09:31:02 2017 -0500 Merge pull request #146 from devinamatthews/master Change lsame_ signature to match lapacke. commit cecdc05d2834786a84ff85775d3f99a958c0765a Author: Devin Matthews Date: Mon Jul 31 15:19:51 2017 -0500 Change lsame_ signature to match lapacke. commit 803bbef0a386dd0571ad389f69d55154dbfe3c50 Author: Field G. Van Zee Date: Sat Jul 29 20:17:05 2017 -0500 Fixed pthreads compile bug with previous commit. Details: - Erroneously passed family parameter into l3int_t function despite that function not taking the parameter. Oops. commit c63980f4ca750618f359031d0691289b1abf5146 Author: Field G. Van Zee Date: Sat Jul 29 14:53:39 2017 -0500 Moved 'family' field from cntx_t to cntl_t. Details: - Removed the family field inside the cntx_t struct and re-added it to the cntl_t struct. Updated all accessor functions/macros accordingly, as well as all consumers and intermediaries of the family parameter (such as bli_l3_thread_decorator(), bli_l3_direct(), and bli_l3_prune_*()). This change was motivated by the desire to keep the context limited, as much as possible, to information about the computing environment. (The family field, by contrast, is a descriptor about the operation being executed.) - Added additional functions to bli_blksz_*() API. - Added additional functions to bli_cntx_*() API. - Minor updates to bli_func.c, bli_mbool.c. - Removed 'obj' from bli_blksz_*() API names. - Removed 'obj' from bli_cntx_*() API names. - Removed 'obj' from bli_cntl_*(), bli_*_cntl_*() API names. Renamed routines that operate only on a single struct to contain the "_node" suffix to differentiate with those routines that operate on the entire tree. - Added enums for packm and unpackm kernels to bli_type_defs.h. - Removed BLIS_1F and BLIS_VF from bszid_t definition in bli_type_defs.h. They weren't being used and probably never will be. commit 07837395560d413a1ba828163b41186e21a7bcfe Merge: ca1d1d85 ad8610b4 Author: Field G. Van Zee Date: Fri Jul 21 16:49:48 2017 -0500 Merge pull request #139 from Maratyszcza/emscripten Fix Emscripten builds commit ad8610b4415cc7982804d74f9aba29875e9e2b6c Merge: 8772a0b3 ca1d1d85 Author: Field G. Van Zee Date: Fri Jul 21 15:18:33 2017 -0500 Merge branch 'master' into emscripten commit ca1d1d8560c9ab1a7e3b0ac43ac70d08075bf904 Merge: b537b5bb 733faf84 Author: Devin Matthews Date: Fri Jul 21 09:49:50 2017 -0500 Merge pull request #144 from devinamatthews/fix_atomics_on_bgq Add fallbacks to __sync_* or __c11_atomic_* builtins... commit 733faf848dcc54834fcdfbb0185dc644978d8864 Author: Devin Matthews Date: Thu Jul 20 14:50:13 2017 -0500 Clang can't make up it's mind what to support. commit 7425d0744d9e9cd29a887120e57c2b43ba287040 Author: Devin Matthews Date: Thu Jul 20 12:54:58 2017 -0500 Add default #define for __has_extension. commit b537b5bbe8cbee459a85bac11458498ae2bce4de Merge: 1f1ec0db 7f41bb0a Author: Devin Matthews Date: Thu Jul 20 10:58:39 2017 -0500 Merge pull request #133 from devinamatthews/haswell-packdim Fix prefetching in haswell ukernel commit 8823f91a14638ce6f4e45e67df03212bb61609d6 Author: Devin Matthews Date: Thu Jul 20 10:04:34 2017 -0500 Add fallbacks to __sync_* or __c11_atomic_* builtins when __atomic_* is not supported. Fixes #143. commit 1f1ec0db9380b87679d5c771c4594daa1cfc5f0d Author: Field G. Van Zee Date: Wed Jul 19 15:40:48 2017 -0500 Updated ar option list used by all configurations. Details: - Dropped 'u' from the list of modifiers passed into the library archiver ar. Previously, "cru" was used, while now we employ only "cr". This change was prompted by a warning observed on Ubuntu 16.04: ar: `u' modifier ignored since `D' is the default (see `U') This caused me to realize that the default mode causes timestamps to be zero, and thus the 'u' option, which causes only changed object files to be inserted, is not applicable. commit 5caaba2d61cbbc36d63102a0786ece28ff797f72 Author: Field G. Van Zee Date: Wed Jul 19 13:51:53 2017 -0500 Added --force-version=STRING option to configure. Details: - Added an option to configure that allows the user to force an arbitrary version string at configure-time. The help text also now describes the usage information. - Changed the way the version string is communicated to the Makefile. Previously, it was read into the VERSION variable from the 'version' file via $(shell cat ...). Now, the VERSION variable is instead set in config.mk (via a configure-substituted anchor from config.mk.in). commit 13175c5fb70fb6a378d5fff6ecede62e5ea6a1f6 Author: Field G. Van Zee Date: Tue Jul 18 17:56:00 2017 -0500 Updated openmp/pthread barriers with GNU atomics. Details: - Updated the non-tree openmp and pthreads barriers defined in bli_thrcomm_openmp.c and bli_thrcomm_pthreads.c to instead call a common implementation in bli_thrcomm.c, bli_thrcomm_barrier_atomic(). This new implementation goes through the same motions as the previous codes, but protects its loads and increments with GNU atomic built-ins. These atomic statements take memory ordering parameters that allow us to specify just enough constraints for the barrier to work as intended on weakly-ordered hardware. The prior implementation was only guaranteed to work on systems with strongly- ordered memory. (Thanks to Devin Matthews for suggesting this change and his crash-course in atomics and memory ordering.) - Removed 'volatile' from structs' barrier field declarations in bli_thrcomm_*.h. - Updated bli_thrcomm_pthread.? files to use renamed struct barrier fields consistent with that of the _openmp.? files. - Updated other bli_thrcomm_* files to rename "communicator" variables to simply "comm". commit 0e58ba1b3aa84700ca51a96f1c0eed6067562fba Author: Field G. Van Zee Date: Mon Jul 17 19:03:22 2017 -0500 Added API to set mt environment variables. Details: - Renamed bli_env_get_nway() -> bli_thread_get_env(). - Added bli_thread_set_env() to allow setting environment variables pertaining to multithreading, such as BLIS_JC_NT or BLIS_NUM_THREADS. - Added the following convenience wrapper routines: bli_thread_get_jc_nt() bli_thread_get_ic_nt() bli_thread_get_jr_nt() bli_thread_get_ir_nt() bli_thread_get_num_threads() bli_thread_set_jc_nt() bli_thread_set_ic_nt() bli_thread_set_jr_nt() bli_thread_set_ir_nt() bli_thread_set_num_threads() - Added #include "errno.h" to bli_system.h. - This commit addresses issue #140. - Thanks to Chris Goodyer for inspiring these updates. commit 8772a0b33a90154c80d88b381dcdd66f824e041f Author: Marat Dukhan Date: Thu Jul 13 21:39:24 2017 -0700 Fix Emscripten builds commit 72c8b49bb8d3b9370b2cc37718da22f065de9c57 Merge: 70cc825b ba7cada5 Author: Field G. Van Zee Date: Wed Jul 12 14:58:12 2017 -0500 Merge pull request #138 from hominhquan/membrk_set_free_fp Set missing free_fp in bli_membrk_init for free-ing GEN_USE buffers commit ba7cada51a238d320528e3504ed0f0a17a6b022a Author: Minh Quan HO Date: Fri Jul 7 10:52:05 2017 +0200 set missing free_fp in bli_membrk_init for free-ing GEN_USE buffers The membrk's free_fp is called when releasing GEN_USE buffers, but this free_fp is not set in bli_membrk_init commit 1241301869957c96f16a2c6567e3ad70afa547de Merge: 969b67e8 25ead66f Author: Kiran Varaganti Date: Wed Jul 5 02:24:00 2017 -0400 Merge "Reducing the framework overhead of GEMV routines" into amd-staging commit 25ead66fb78557f73af48bac305724d5d8aa3309 Author: sthangar Date: Fri Jun 30 12:23:19 2017 +0530 Reducing the framework overhead of GEMV routines Change-Id: I83607ad767bff74e305e915b54b0ea34ec3e5684 commit 969b67e8800fbd5d14a086606f3b5afbf66ed093 Author: Kiran Varaganti Date: Tue Jul 4 12:57:32 2017 +0530 Improved efficiency of dGEMM for large matrices by reducing TLB load misses and majorly L3 cache misses. This is achieved by changing the packed block sizes of matrix A & B. Now the optimum values are MC_D = 510 and KC_D = 1024. Change-Id: I2d8bdd5f62f2d1f8782ae2997f3d7a26587d1ca4 commit 70cc825b552dec05165b9d70f9e6eb33d8abb118 Author: Devin Matthews Date: Tue Jun 6 21:58:21 2017 -0500 Update LICENSE Remove totally unnecessary first 9 lines and hopefully get Github to recognize it as 3BSD [ci skip]. commit cf54c77bc79a0f33a514be72c80a654c4e6e6f63 Author: Devin Matthews Date: Tue Jun 6 20:23:17 2017 -0500 Add new SSI acknowledgment commit d6ef56c6dbaf6df8ee1af1ca6a0f0792a811396a Author: prangana Date: Thu Jun 1 16:11:09 2017 +0530 Update version number Change-Id: Ib6e52d1d34c0791367ab9152dfab31f94deedeb4 commit 897bfa0e92082c30bbb74229562d7d7327cbbac8 Author: prangana Date: Thu Jun 1 16:11:09 2017 +0530 Update version number Change-Id: Ib6e52d1d34c0791367ab9152dfab31f94deedeb4 commit 99d0ba5606d4b63e6a9c639aa78d4defc2455f79 Merge: be2c7eb8 6d17e012 Author: Santanu Thangaraj Date: Thu Jun 1 02:19:02 2017 -0400 Merge "Checked in the small matrix code to compute GEMM called with A transpose case" into amd-staging commit 6d17e0120fe5c127b941136ad2c0c08e91439535 Author: sthangar Date: Wed May 24 11:48:16 2017 +0530 Checked in the small matrix code to compute GEMM called with A transpose case Change-Id: I29f40046d43d7a4b037c1cb322503ee26495f462 commit 9d93f8481a1404695f7b78a3ced8ca47e890b649 Author: prangana Date: Tue May 30 09:58:10 2017 +0530 Update Licence File Change-Id: I4c5cf1690d0cef92a68400f9a89e454ab6856ad2 commit be2c7eb85168937bd4318f4d05ded37620119310 Author: prangana Date: Tue May 30 09:58:10 2017 +0530 Update Licence File Change-Id: I4c5cf1690d0cef92a68400f9a89e454ab6856ad2 commit 7f41bb0a0becde6a7de7df0f99668d7b4686c3b0 Author: Devin Matthews Date: Fri May 26 14:49:31 2017 -0400 PACKDIM_MR=8 didn't work out, but messing with the prefetching helps 2%. commit d87614af3f3d9187be94d6e77984b282bf890928 Author: Devin Matthews Date: Fri May 26 14:47:36 2017 -0400 Revert "Change PACKDIM_MR (double) for haswell to 8." This reverts commit 681eec913d7c2ebcff637cec5c1627ced9a92b99. commit 681eec913d7c2ebcff637cec5c1627ced9a92b99 Author: Devin Matthews Date: Fri May 26 12:28:09 2017 -0500 Change PACKDIM_MR (double) for haswell to 8. commit 0a3ae0ecaa0ddcb5887005d7051fa234499f1120 Merge: 0f4e6652 6e04f9df Author: praveeng Date: Sat May 20 16:53:50 2017 +0530 frame/3/gemm/bli_gemm_front.c Change-Id: I52a0fbc1d33bb948d430942323bbc5fe44e3ca13 commit 6e04f9df01d79c1b0e673943ca0d5d0a6095eb2e Author: Field G. Van Zee Date: Wed May 17 13:03:52 2017 -0500 Restored deleted lines from makefile fragments. commit ec5c0c0448275280dca0991f6f33afeb73650450 Author: Devin Matthews Date: Wed May 17 12:29:44 2017 -0500 Change to /bin/sh. All scripts checked with Debian's checkbashisms. Also check for clang first in auto-detect.sh. commit 555ddc30d4c7e44f3f335e436c98606f56e1598b Author: Devin Matthews Date: Wed May 17 12:27:14 2017 -0500 Remove shebangs from makefiles. commit f26bd7f42e0c2a47fe321b2c452644990b689654 Merge: cbf8710a 169fb05f Author: Devin Matthews Date: Wed May 17 11:58:41 2017 -0500 Merge pull request #128 from iotamudelta/master Portability and clang commit 169fb05f225c2f060265bcaa872f7f80dc638b70 Author: J M Dieterich Date: Tue May 16 23:11:22 2017 -0400 Fix if/else structure. Thanks to TravisCI. commit 0579dfea0bcfbb90ebc073fcf78b92a5cf7238e1 Author: J M Dieterich Date: Tue May 16 22:58:07 2017 -0400 Restore version. commit a75b05c23dc786a1fdc45dc1627a5ce2299f1a7b Author: J M Dieterich Date: Tue May 16 22:23:27 2017 -0400 Mark piledriver compilable w/ clang. commit 7541d46e2ba8659bb2e36b444edef112fefa1345 Author: J M Dieterich Date: Tue May 16 22:12:12 2017 -0400 Mark bulldozer compilable w/ clang. commit 91f897073ec0df3330ede449c4d6af8158266ae3 Author: J M Dieterich Date: Tue May 16 22:06:59 2017 -0400 Correct error message. commit f5131e1e49167f948bddd714bb1af1761829c212 Author: J M Dieterich Date: Tue May 16 22:03:23 2017 -0400 Indeed once can compile for carrizo also using clang. commit 5fa4e9439c04f35f89dd7d26ff742cb2dadc3180 Author: J M Dieterich Date: Tue May 16 21:50:49 2017 -0400 A bunch of shebang fixes from unportable /bin/bash to portable /usr/bin/env bash commit 1f3a58197e5d5f9ac862bda91e7527cbfbab5d76 Author: Field G. Van Zee Date: Mon May 8 16:10:03 2017 -0500 Housekeeping, induced method file/function renames. Details: - Renamed all level-3 induced method files to use the "_vir.c" suffix instead of "_ref.c". Also renamed functions within these files accordingly. - Renamed cpp macro definitions in frame/ind/include according to the above changes. - Removed frame/3/old. commit cbf8710a1ba63e25aadaa6fc5da51ea81b3d596d Merge: cf39d3ef fdc66f12 Author: Tyler Michael Smith Date: Mon May 8 11:21:20 2017 -0500 Merge pull request #127 from devinamatthews/fix_blis_nt_xx Setting any one of BLIS_NT_[IJ][CR] overrides BLIS_NUM_THEADS commit cf39d3ef3b29b8058c39fb4638c1a734fe64aaed Author: Field G. Van Zee Date: Fri May 5 15:06:56 2017 -0500 Fixed a bug in norm1v, norm1m. Details: - Fixed a bug that manifested as improperly-computed 1-norm for vectors and matrices. This is one of the few operations in BLIS that does not have its own test module within the testsuite, hence why it went undetected for so long. The bad 1-norms were being used to normalize matrices in the testsuite after initialization, which led to some matrices containing a combination of "large" and "small" values. This tended to push the residuals computed after each test away from zero. In some cases, they were off *just* enough to the testsuite to label it a "failure". Many thanks to Jeff Hammond for reporting this bug. (Wonky details: the bug was due to improperly-defined level-0 scalar macros for abval2, an operation that computes the absolute square, or complex magnitude/modulus. Certain complex domain instances of abval2 were being incorrectly defined in terms of real-only solutions, leading to bad results. This level-0 operation forms the basis of norm1v/norm1m. absq2 was also affected, but almost nothing uses this operation.) commit 799485124f4d823e908d2e5d38b0c3a1e6172ade Merge: 773a24ef 0df3541f Author: Devin Matthews Date: Thu May 4 10:52:09 2017 -0500 Merge pull request #121 from jeffhammond/not-real-knl allow KNL build without hbwmalloc (i.e. emulated) commit fdc66f12d40754ff46179804bff592fddafbca02 Author: Devin Matthews Date: Thu May 4 10:35:22 2017 -0500 Setting any one of BLIS_NT_[IJ][CR] overrides BLIS_NUM_THEADS. Missing BLIS_NT_XX's are defaulted to 1. Fixes #123. commit 773a24efb2fa1c3a220bf0ce1dd621a3176196da Merge: dd58c954 b8854259 Author: Field G. Van Zee Date: Wed May 3 15:07:59 2017 -0500 Merge branch 'master' of github.com:flame/blis commit dd58c9545c877c3f7553eaebca7b5e9720a66f5d Author: Field G. Van Zee Date: Wed May 3 15:04:51 2017 -0500 Disable complex 3m/4m in testsuite by default. Details: - Disabled testsuite tests of all level-3 implementations based on 3m and 4m. This will improve testing runtime on Travis CI as well as for anyone manually running the testsuite using default test parameters. Thanks to Devin Matthews for suggesting this change. commit 0df3541f54b7fe0c604ab2ec47ba814f12391798 Author: Jeff Hammond Date: Tue May 2 19:25:21 2017 -0700 allow KNL build without hbwmalloc.h (i.e. emulated) we want to be able to run BLIS KNL binaries on non-KNL machines via SDE. although it is possible to install hbwmalloc implementation on such systems, it is easier not to, since obviously the performance of SDE execution is not representative so there is no reason to emulate HBW allocation. commit b88542591d4dd0cde366e5ae35afd3205cb81bdc Merge: 43007f7b c2c91e09 Author: Field G. Van Zee Date: Tue May 2 19:22:41 2017 -0500 Merge pull request #107 from jeffhammond/intel-compilers-no-use-libm never use libm with Intel compilers commit 43007f7b65ec7926cbbfc39965ff733fa251c15f Author: Field G. Van Zee Date: Tue May 2 16:48:43 2017 -0500 Fixed stray parentheses in README citations. commit a4f1d0b8801c114e9ef8be39df01e1b8d27ebcb3 Author: Field G. Van Zee Date: Tue May 2 16:38:43 2017 -0500 CHANGELOG update (0.2.2) commit 940a707ac78de975110e17c95765e65b89aa5e10 (tag: 0.2.2) Author: Field G. Van Zee Date: Tue May 2 16:38:42 2017 -0500 Version file update (0.2.2) commit d5a5e003ea9b24bb6abf12e88862e8eb61ffb03d Author: Field G. Van Zee Date: Tue May 2 15:48:30 2017 -0500 Fixed a trsm1m bug that affected right-side cases. Details: - Fixed a bug introduced in 1c732d3 that affected trsm1m_r. The result was nondeterministic behavior (usually segmentation faults) for certain problem sizes beyond the 1m instance of kc (e.g. 128 on haswell). The cause of the bug was my commenting out lines in bli_gemm1m_ukr_ref.c which explicitly directed the virtual gemm micro-kernel to use temporary space if the storage preference of the [real domain] gemm ukernel did not match the storage of the output matrix C. In the context of gemm, this handling is not needed because agreement between the storage pref and the matrix is guaranteed by a high-level optimization in BLIS. However, this optimization is not applied to trsm because the storage of C is not necessarily the same as the storage of the micro-panels of B--both of which are updated by the micro-kernel during a trsm operation. Thus, the guarantee of storage/preference agreement is not in place for trsm, which means we must handle that case within the virtual gemm micro-kernel. - Comment updates and a minor macro change to bli_trsm*_cntx_init() for 3m1, 4m1a, and 1m. commit e80993e71f4d571e9650a8e90ed386e32059eae5 Merge: a509fbd5 ca3a7924 Author: Field G. Van Zee Date: Tue May 2 12:30:28 2017 -0500 Merge branch 'master' into 1m commit ca3a7924770d6cf203cce4ca9f5482e1d0d4e961 Author: Field G. Van Zee Date: Tue May 2 12:09:39 2017 -0500 README.md update. Details: - Updated bibtex entries for 4th BLIS paper, and adds entries for 5th and 6th BLIS papers. commit 0f4e6652dfe9b30105d3bab328ac26d9d5c11182 Merge: 42e7f6fb 6e7de6ef Author: praveeng Date: Wed Apr 19 17:54:10 2017 +0530 Merge master code till 2017_04_19 to amd-staging Change-Id: Ibebe83c8ea2e7eb15798c2bcf214b7228a1c9518 commit 42e7f6fb2a531429ee600b2fe0293b67371c7ccb Author: sthangar Date: Tue Mar 28 18:10:03 2017 +0530 fixed license attribute issues in AMD added files Change-Id: I303f870a777c7cd1c1af29ea0b93f3e0a27948e4 commit 5600001e973c6cea048bd3fdb28117f1d7c98b9d Merge: 0b190293 b3ed4933 Author: prangana Date: Mon Mar 20 13:56:33 2017 +0530 Fix merge conflicts after sync with release branch Change-Id: Icf14a09f728befb69a73fff9fa79c4128e728310 commit 6e7de6ef84babb273dc5528a9b9d01f0febe394b Author: Field G. Van Zee Date: Fri Mar 17 12:10:24 2017 -0500 Minor updates to test/3m4m. Details: - Updated initial problem size and increment in Makefile. - Updated code in test_gemm.c to correctly query kc from context. commit f484c6cd4389dc7ae5b972849e12e98ad5bbf9a4 Author: Field G. Van Zee Date: Fri Mar 17 12:07:27 2017 -0500 Whitespace reformatting to armv8a kernels file. Details: - Updated formatting of function signature/header in kernels/armv8a/3/bli_gemm_opt_4x4.c. commit 0b19029342ffc530fa22ef20398a26221cb8f6ec Author: Kiran Varaganti Date: Tue Mar 14 14:51:31 2017 +0530 Code cleanup, removed warnings from trsm, removed unused routines in axpyv & scalv Change-Id: I02867f394c5f416194c4b1769a6c75f39243ec81 commit 825363bd2a5a60a923d4a6d9691dc143845a9cab Merge: 093bdb80 513944e4 Author: praveeng Date: Wed Mar 8 15:42:49 2017 +0530 Merge code from master to amd-staging as on 2017_03_08 by praveeng Change-Id: I80740081b2cb54c9b77a3e78b9fe540e170be23d commit 093bdb80c86b06367e595aa17487139ae983822f Author: sthangar Date: Tue Mar 7 13:35:50 2017 +0530 Checked in Unpacked DGEMM code Change-Id: I39dcc7b238b328f73ee2675d21a5e521d0488723 commit 33923da9a108854590d386e74b6ee66b971e7796 Author: Kiran Varaganti Date: Mon Mar 6 14:31:31 2017 +0530 Added variant 10 for double precision axpyv microkernel Change-Id: I7a20cc113a422603250bc450825c965136354974 commit bc828f7f8e3ddb9f58af07edc0b935b21759fb0f Author: Kiran Varaganti Date: Fri Mar 3 14:45:35 2017 +0530 Added new axpyv (single precision) microkernel where it performs 10 FMAs per loop- This gives better performance than all other implementations of axpyv Change-Id: Ic4f0e4c67e367d67d0b24febcf34f81a70a39972 commit c9949f4603419267c10973adf1d63ec38497475d Author: sthangar Date: Fri Feb 17 14:16:33 2017 +0530 Checked in DGEMMTRSM and edge case handling routine in DDOTXF Change-Id: I65f00661af6c09b2507294fd43e0a10641c0597e commit a509fbd5ac04fafd4e51b43d2f59ca56432dc212 Merge: 69b4846a 513944e4 Author: Field G. Van Zee Date: Tue Feb 21 17:06:16 2017 -0600 Merge branch 'master' into 1m commit 69b4846ae9adb157c4171b52e159684db2867853 Author: Field G. Van Zee Date: Tue Feb 21 15:33:39 2017 -0600 Disabled experiment-related 1m code. Details: - Commented out code in frame/ind/oapi/bli_l3_3m4m1m_oapi.c that was specifically inserted to facilitate the benchmarking of 1m block-panel and panel-block algorithms. - Updates to test/3m4m/Makefile, runme.sh script, and test_gemm.c to reflect changes used/needed during benchmarking. commit 513944e4a951d8823b4de161b86ad7a965b4d99b Merge: 8b462a0e 0e18f68c Author: Devin Matthews Date: Mon Feb 20 10:04:33 2017 -0500 Merge pull request #118 from devinamatthews/master Handle k=0 correctly in KNL dgemm ukernel. commit 0e18f68cf12eb9189ba901a20040b1cdae417670 Author: Devin Matthews Date: Mon Feb 20 09:03:21 2017 -0600 Handle k=0 correctly in KNL dgemm ukernel. commit 8b462a0e8c3e9252f0401940849e53cc772256fa Merge: c362afc5 7d42fc07 Author: Devin Matthews Date: Sun Feb 19 23:03:03 2017 -0500 Merge pull request #117 from devinamatthews/master Cast dim_t and inc_t parameters to 64-bit in KNL microkernels. commit 7d42fc0796ef0c010375fd8e59b1240ba41ce4d2 Author: Devin Matthews Date: Sun Feb 19 21:10:55 2017 -0500 Cast dim_t and inc_t parameters to 64-bit in KNL microkernels. commit 04245c9ff7f8b3c70d61003029c964bb9a4320ee Author: Kiran Varaganti Date: Fri Feb 10 14:24:30 2017 +0530 Reoptimized scalv routines - two vector multiplies are done per iteration, and these routines are enabled in bli_kernel.h Change-Id: Ic5654508573d1f6bde2edef06aefe117e581feb5 commit c362afc525bab4050581d1b0fcea2fe4d582c608 Author: Field G. Van Zee Date: Thu Feb 9 11:54:59 2017 -0600 Added missing "level-0" BLAS [sd]cabs1_(). Details: - Fixed issue #115 by adding implementations for scabs1_() and dcabs1_() to the BLAS compatibility layer. Thanks to heroxbd for pointing out their absence. commit 018180c938c32efbeaaf626ba71ec5b780664db1 Author: Field G. Van Zee Date: Wed Feb 8 11:20:52 2017 -0600 Fixed a minor bug in configure (issue #114). Details: - Fixed a bug in the configure script whereby a non-preferred value for --enable-threading would cause problems in common.mk vis-a-vis detecting which threading model was chosen. Thanks to heroxbd for reporting this issue. commit 58b5b77e5fdb179ea465e398e416e6a00d917e05 Author: Kiran Varaganti Date: Wed Feb 8 21:43:34 2017 +0530 Fixed a bug in axpyv, the arguments passed to intrinsic fmad instruction are corrected Change-Id: If12f24c6bc74b22ac9e4acd6b9378e06d79f2f5e commit 85de4ebf74d0a5587d5a12724eb5489d51674db3 Author: Kiran Varaganti Date: Wed Feb 8 14:41:04 2017 +0530 variant 4 axpyv single precision modified: explicitly used FMA intrinsics, replaced vector multiply and add operations Change-Id: I975feef56696d479d2b9e9441b0660021cf4f6ff commit 3fa53e8af31d634779f40258c51483ae8af494fa Merge: b5291a44 95be7b04 Author: Kiran Varaganti Date: Wed Feb 8 11:46:34 2017 +0530 Merged axpyv and gemm small in bli_kernel.h Merge branch 'amd-staging' of ssh://git.amd.com:29418/cpulibraries/er/blis into amd-staging modified: config/zen/bli_kernel.h modified: frame/3/gemm/bli_gemm_front.c modified: kernels/x86_64/zen/3/bli_gemm_small_matrix.c Change-Id: If181cf9345178c448b3530beb8bef453917fe295 commit 95be7b04709e688a4cb01fba680081e30f4258ef Author: sthangar Date: Tue Feb 7 14:01:27 2017 +0530 Added logic for packing matrix A and prefetching matrix C in Unpacked SGEMM code Change-Id: I99efeca9eb5b4449286ec0ec133fd554ef1bb4f0 commit b5291a445b1313e01f1e0e8102c5f3660ab07f69 Author: Kiran Varaganti Date: Tue Feb 7 12:39:31 2017 +0530 Added optimization variant 4 for axpyv single precision - this performs 5 FMA per loop, keeping the IPC always full Change-Id: Ie77ed22584271136a257e673bcd3b1ba71136bc9 commit f4bfc1662af82aa4b98185334c44835e51f1cbec Author: Kiran Varaganti Date: Mon Feb 6 15:04:27 2017 +0530 New routines implemented for axpyv to improve performance for small vector sizes, vectorization is done for vectors as small as 8 (single precision) 4(double precision), since this operation has low compute to memory ratio, higher matrix sizes memory operations are dominating and hence not much gain - This still needs some work- added saxpyv and daxpyv var 3 routines in the file bli_axpyv_opt_var1.c Change-Id: Ic1b33bd5516e10113b00e44ab41b97eb19d46072 commit ddf45e71770c55ea4a58ca24ea4913fe5d8beb9b Merge: a6ab91bc 78e1b16e Author: Devin Matthews Date: Fri Jan 27 14:25:40 2017 -0600 Merge pull request #113 from devinamatthews/knl_thread_params Change default threading parameters for KNL. commit 78e1b16e16d589ed31b2e712115ee282097f114d Author: Devin Matthews Date: Fri Jan 27 14:22:20 2017 -0600 Change default threading parameters for KNL. commit 574472ba5a89924eca7dbd10055d0e1dcd7f4c71 Author: sthangar Date: Tue Jan 10 14:51:46 2017 +0530 checked in unpacked SGEMM optimization Change-Id: I8e4ea374415c0c402c660b656fb076af15354181 commit 1c732d3ddc4ac0861d3b0e0dd15eb7e071615502 Author: Field G. Van Zee Date: Wed Jan 25 16:25:46 2017 -0600 Added 1m-specific APIs for bp, pb gemm algorithms. Details: - Defined bli_gemmbp_cntl_create(), bli_gemmpb_cntl_create(), with the body of bli_gemm_cntl_create() replaced with a call to the former. - Defined bli_cntl_free_w_thrinfo(), bli_cntl_free_wo_thrinfo(). Now, bli_cntl_free() can check if the thread parameter is NULL, and if so, call the latter, and otherwise call the former. - Defined bli_gemm1mbp_cntx_init(), bli_gemm1mpb_cntx_init(), both in terms of bli_gemm1mxx_cntx_init(), which behaves the same as bli_gemm1m_cntx_init() did before, except that an extra bool parameter (is_pb) is used to support both bp and pb algorithms (including to support the anti-preference field described below). - Added support for "anti-preference" in context. The anti_pref field, when true, will toggle the boolean return value of routines such as bli_cntx_l3_ukr_eff_prefers_storage_of(), which has the net effect of causing BLIS to transpose the operation to achieve disagreement (rather than agreement) between the storage of C and the micro-kernel output preference. This disagreement is needed for panel-block implementations, since they induce a transposition of the suboperation immediately before the macro-kernel is called, which changes the apparent storage of C. For now, anti-preference is used only with the pb algorithm for 1m (and not with any other non-1m implementation). - Defined new functions, bli_cntx_l3_ukr_eff_prefers_storage_of() bli_cntx_l3_ukr_eff_dislikes_storage_of() bli_cntx_l3_nat_ukr_eff_prefers_storage_of() bli_cntx_l3_nat_ukr_eff_dislikes_storage_of() which are identical to their non-"eff" (effectively) counterparts except that they take the anti-preference field of the context into account. - Explicitly initialize the anti-pref field to FALSE in bli_gks_cntx_set_l3_nat_ukr_prefs(). - Added bli_gemm_ker_var1.c, which implements a panel-block macro-kernel in terms of the existing block-panel macro-kernel _ker_var2(). This technique requires inducing transposes on all operands and swapping the A and B. - Changed bli_obj_induce_trans() macro so that pack-related fields are also changed to reflect the induced transposition. - Added a temporary hack to bli_l3_3m4m1m_oapi.c that allows us to easily specify the 1m algorithm (block-panel or panel-block). - Renamed the following cntx_t-related macros: bli_cntx_get_pack_schema_a() -> bli_cntx_get_pack_schema_a_block() bli_cntx_get_pack_schema_b() -> bli_cntx_get_pack_schema_b_panel() bli_cntx_get_pack_schema_c() -> bli_cntx_get_pack_schema_c_panel() and updated all instantiations. Also updated the field names in the cntx_t struct. - Comment updates. commit 41595e98eedaf3f1f93802c14dcae490402f933f Merge: d625c49e a6ab91bc Author: praveeng Date: Wed Dec 7 15:13:21 2016 +0530 Merge master code as on 2016_12_07 to amd-staging Change-Id: I5d9ecef9bff960aeb9b51ca4e4b21714e789e44f commit d625c49e20bd3c50d6d44e330e34076cced114a3 Author: sthangar Date: Tue Nov 29 15:05:19 2016 +0530 checked-in SGEMMTRSM microkernel for Zen Change-Id: Ib61936418dea911b2154aa99f703b66e9669f94f commit a6ab91bc61432490fadf18d596de4589645f37dd Merge: 145a551d 7f31a630 Author: Field G. Van Zee Date: Wed Nov 30 09:26:58 2016 -0600 Merge pull request #111 from figual/master Fixed missing cntx argument in ARMv8 microkernels. commit 7f31a6307b7bd35f913c895947552c3a176f789b Author: Francisco Igual Date: Sun Nov 27 14:40:47 2016 +0100 Fixed missing cntx argument in ARMv8 microkernels. commit 126482a3b609b9ad7026ba348f6c4bf6a29be8a1 Author: Field G. Van Zee Date: Fri Nov 25 18:29:49 2016 -0600 Implemented the 1m method. Details: - Implemented the 1m method for inducing complex domain matrix multiplication. 1m support has been added to all level-3 operations, including trsm, and is now the default induced method when native complex domain gemm microkernels are omitted from the configuration. - Updated _cntx_init() operations to take a datatype parameter. This was needed for the corresponding function for 1m (because 1m requires us to choose between column-oriented or row-oriented execution, which requires us to query the context for the storage preference of the gemm microkernel, which requires knowing the datatype) but I decided that it made sense for consistency to add the parameter to all other cntx initialization functions as well, even though those functions don't use the parameter. - Updated bli_cntx_set_blkszs() and bli_gks_cntx_set_blkszs() to take a second scalar for each blocksize entry. The semantic meaning of the two scalars now is that the first will scale the default blocksize while the second will scale the maximum blocksize. This allows scaling the two independently, and was needed to support 1m, which requires scaling for a register blocksize but not the register storage blocksize (ie: "packdim") analogue. - Deprecated bli_blksz_reduce_dt_to() and defined two new functions, bli_blksz_reduce_def_to() and bli_blksz_reduce_max_to(), for reducing default and maximum blocksizes to some desired blocksize multiple. These functions are needed in the updated definitions of bli_cntx_set_blkszs() and bli_gks_cntx_set_blkszs(). - Added support for the 1e and 1r packing schemas to packm, including 1e/1r packing kernels. - Added a minor optimization to bli_gemm_ker_var2() that allows, under certain circumstances (specifically, real domain beta and row- or column-stored matrix C), the real domain macrokernel and microkernel to be called directly, rather than using the virtual microkernel via the complex domain macrokernel, which carries a slight additional amount of overhead. - Added 1m support to the testsuite. - Added 1m support to Makefile and runme.sh in test/3m4m. Also simplified some code in test_gemm.c driver. commit d8f13beeea90338e0ecb0a3aeaa2d59d8ebd6c36 Merge: c25a9205 145a551d Author: praveeng Date: Fri Nov 25 17:31:08 2016 +0530 Merge master code till 2016_11_25 to amd-staging commit c25a9205fd8c8d8de7fd81b1e5621e7ac79f4e87 Merge: 65298762 bdc0a264 Author: praveeng Date: Fri Nov 25 17:06:36 2016 +0530 Merge master code till Switched to simpler trsm_r 2016_11_25 to amd-staging Change-Id: Ibf71d224d8fb6cf0bc497f84d50c27d276512cc1 commit 145a551d524ae5492667a05fc248923d922df850 Author: Field G. Van Zee Date: Wed Nov 23 17:59:06 2016 -0600 Switched to simpler trsm_r implementation. Details: - Disabled the implementation of trsm_r that allows the right-hand matrix B to be trianglar, and switched to the implementation that simply transposes the operation (and thus the storage of C) in order to recast the operation as trsm_l. This avoids the need to use trsm_rl and trsm_ru macrokernels, which require an awkward swapping of MR and NR. For now, the support for trsm_r macrokernels, via separate control trees, remains. - Modified bli_config_macro_defs.h so that BLIS_RELAX_MCNR_NCMR_CONSTRAINTS is defined by default. This is mostly a safety precaution in case someone tries to switch back to the previous trsm_r implementation, but also serves as a convenience on some systems where one does not naturally choose blocksizes in a way that satisfies MC % NR = 0 and NC % MR = 0. commit b3e58ee30307cf1e11529f2113acb9abbeda25af Author: Field G. Van Zee Date: Wed Nov 23 17:58:26 2016 -0600 Reimplemented 4x12 haswell ukernels (real only). Details: - Replaced permutation-based implementations in bli_gemm_asm_d4x12.c, which defines 4x24 single real and 4x12 double real gemm microkernels, with broadcast-based implementations. (The previous microkernel file has been moved to an 'old' subdirectory.) commit 65298762ff15c45e8588e0c279a9feaa98c927a0 Author: sthangar Date: Tue Nov 22 12:15:33 2016 +0530 removed a redundant copy operation in DNRM2 Change-Id: I673b08efde4480e871779716f7715566740ad9ce commit d6863e851adeef037e4d1476fe63bb293fb9d987 Author: sthangar Date: Mon Nov 21 11:30:30 2016 +0530 checked-in DNRM2 optimizations Change-Id: I3b31d768bd7f4fbf43042aa5a0762995c73c4522 commit bdc0a264d2fb5940bfd09298b1de823674a39053 Author: Field G. Van Zee Date: Wed Nov 16 14:13:08 2016 -0600 Adjusted stride selection of ct in macrokernels. Details: - Updated the changes introduced in 618f433 so that the strides of the temporary microtile ct used in the macrokernels is determined based on the storage preference of the microkernel (via the new functions below), rather than the strides of c. In almost all cases, presently, this change results in no net effect, as a high-level optimization in the _front() functions aligns the storage of c to that of the microkernel's preference. However, I encountered some cases where this is not always the case in some development code that has yet to be committed, and therefore I'm generalizing the framework code in advance. - Defined two new functions in bli_cntx.c: bli_cntx_l3_ukr_prefers_rows_dt() bli_cntx_l3_ukr_prefers_cols_dt() which return bool_t's based on the current micro-kernel's storage preferences. For induced methods, the preference of the underlying real domain microkernel is returned. - Updated definition of bli_cntx_l3_ukr_dislikes_storage_of(), and by proxy bli_cntx_l3_ukr_prefers_storage_of(), to be in terms of the above functions, rather than querying the preferences of the native microkernel directly (which did the wrong thing for induced methods). commit 031978d2647cf08316858baf29c84ebba9c3133e Author: Field G. Van Zee Date: Wed Nov 16 14:04:33 2016 -0600 Fixed inactive trsm_r blocksize constraint code. Details: - Changed a cpp macro that was meant to prevent using certain trsm_r code if BLIS_RELAX_MCNR_NCMR_CONSTRAINTS was defined. It was actually coded incorrectly at first. I've now fixed its location and changed its consequence to a compile-time #error message. commit 9772218cae57d55c252595b01e3669d8bed84944 Author: sthangar Date: Wed Nov 16 15:19:19 2016 +0530 Added optimized DAMAX routines for Zen Change-Id: I499c0c8f0f4ce6c19235c47b86d5608db6ba50f8 commit 9c448e30174e5eb76a94b43b30819704a5dfcb3f Merge: 998d8240 e35d3c23 Author: Santanu Thangaraj Date: Wed Nov 16 04:18:57 2016 -0500 Merge "Added new optimized micro-kernel for dotxv routine" into amd-staging commit 998d824044adac0d54c921dcd44fb58f3d54aad2 Merge: 0d13e9a4 6b5a4032 Author: praveeng Date: Wed Nov 16 14:22:42 2016 +0530 Merge master code till devinamatthews/omp_num_thrds 2016_11_16 to amd-staging Change-Id: I601ff1d3ec8a680e1be039ffc7b299744e8a27c5 commit 6b5a4032d2e3ed29a272c7f738b7e3ed6657e556 Merge: 3b524a08 a8220e3a Author: Field G. Van Zee Date: Thu Nov 10 15:28:24 2016 -0600 Merge pull request #109 from devinamatthews/omp_num_threads Add automatic loop thread assignment. commit a8220e3a86433b5d76789e32ea7ca014a11b6d17 Author: Devin Matthews Date: Thu Nov 10 14:19:34 2016 -0600 - Fix typo in bli_cntx.c - Bump BLIS_DEFAULT_NR_THREAD_MAX to 4 commit e35d3c23f28784e50ee13d2e77a69d60e0c24c1f Author: Kiran Varaganti Date: Thu Nov 10 14:30:53 2016 +0530 Added new optimized micro-kernel for dotxv routine Change-Id: I2c544e9b25a454d971ad690353502a55cd668391 commit 0d13e9a4f6f2fcda08f205215240cdf86442d6c6 Merge: e044fa62 3b524a08 Author: praveeng Date: Mon Nov 7 14:40:41 2016 +0530 bli_kernel.h Change-Id: I425d089f79497a0de7d1622e829c3ca9edf7f091 commit c05b3862f6241486442b313eff0c8bee7b5e1274 Author: Devin Matthews Date: Fri Nov 4 15:48:02 2016 -0500 Add automatic loop thread assignment. - Number of threads is determined by BLIS_NUM_THREADS or OMP_NUM_THREADS, but can be overridden by BLIS_XX_NT as before. - Threads are assigned to loops (ic, jc, ir, and jc) automatically by weighted partitioning and heuristics, both of which are tunable via bli_kernel.h. - All level-3 BLAS covered. commit 3b524a08e3fb8380e7b8b2ba835312c51a331570 Author: Field G. Van Zee Date: Wed Nov 2 17:45:18 2016 -0500 Consolidated 3m1/4m1 gemmtrsm, trsm ukernel code. Details: - Consolidated the macros that define the lower and upper versions of the gemmtrsm microkernels into a single macro that is instantiated twice. Did this for both 3m1 and 4m1 microkernels. - Consolidated lower and upper versions of the trsm microkernels for 3m1 and 4m1 into single files (each). commit ead231aca635deb3db270f118454e4222c627f31 Merge: d25e6f8b 62987f60 Author: Field G. Van Zee Date: Wed Nov 2 13:03:50 2016 -0500 Merge pull request #108 from devinamatthews/patch-2 Update .travis.yml with additional tests commit 62987f60a6a6ff0a75b31d0404f493593ce35ccc Author: Devin Matthews Date: Wed Nov 2 11:20:37 2016 -0500 Allow KNL to fail commit 8f9010542c751ae3cbfe6121cb011d8985c1e00d Author: Devin Matthews Date: Wed Nov 2 11:18:32 2016 -0500 Fix some problems with OSX builds: - Update CPU detection for Intel archs (esp. Skylake) - Allow clang for the reference config commit d25e6f8b63c57f30b8a67dffbf4995977cf9f235 Author: Field G. Van Zee Date: Tue Nov 1 14:35:15 2016 -0500 Can disable trsm_r-specific blocksize constraints. Details: - Added cpp guards around the constraints in bli_kernel_macro_defs.h that enforce MC % NR = 0 and NC % MR = 0. These constraints are ONLY needed when handling right-side trsm by allowing the matrix on the right (matrix B) to be triangular, because it involves swapping register, but not cache, blocksizes (packing A by NR and B by MR) and then swapping the operands to gemmtrsm just before that kernel is called. It may be useful to disable these constraints if, for example, the developer wishes to test the configuration with a different set of cache blocksizes where only MC % MR = 0 and NC % NR = 0 are enforced. - In summary, #defining BLIS_RELAX_MCNR_NCMR_CONSTRAINTS will bypass the enforcement of MC % NR = 0 and NC % MR = 0. commit 1a67e3688edb073a9d44c160e7b0798e08796b8a Author: Devin Matthews Date: Tue Nov 1 13:53:18 2016 -0500 Bogus commit Need to trigger another Travis build. commit 2cd82d67b372cad1bed50cfd99e524f1f40b4e24 Author: Devin Matthews Date: Tue Nov 1 13:25:50 2016 -0500 Some fixes for .travis.yml - Switch to gcc-5 to support knl - Don't run tests in parallel -- it is super slow. - Use clang on OSX since gcc is only a zombie husk. commit a3db4e6bdfe745083acf704ab0f51f74ea869538 Author: Devin Matthews Date: Tue Nov 1 10:33:18 2016 -0500 Update .travis.yml with additional tests - Test knl configuration (without running of course). - Test openmp and pthreads threading for auto configuration with 4 threads. - Test auto configuration with and without pthreads on OSX. - Also, run make in parallel. I don't know how the `addons:` section works on OSX; hopefully it is just ignored. commit 8a11a2174a1a5b9426f13bbc5338dc86ab138cdd Author: Field G. Van Zee Date: Mon Oct 31 19:07:55 2016 -0500 Updates to non-default haswell microkernels. Details: - Updated s and d microkernels in bli_gemm_asm_d8x6.c to relax alignment constraints. - Added missing c and z microkernels, which are based on the corresponding kernels in the d6x8 set. - This completes the d8x6 set (which may be used for situations when it is desirable to have a microkernel with a column preference). commit 618f4331eba209803ecab99747872eceb1b5f091 Author: Field G. Van Zee Date: Mon Oct 31 14:40:51 2016 -0500 Align strides of ct in macrokernels to that of c. Details: - Previously, rs_ct and cs_ct, the strides of the temporary microtile used primarily in the macrokernels' edge case handling, were unconditionally set to 1 and MR, respectively. However, Devin Matthews noted that this ought to be changed so that the strides of ct were in agreement with the strides of C. (That is, if C was row-stored, then ct should be accessed as by rows as well.) The implicit assumption is that the strides of C have already been adjusted, via induced transposition, if the storage preference of the microkernel is at odds with the storage of C. So, if the microkernel prefers row storage, the macrokernel's interior cases would present row-stored (ideal) microkernel subproblems to the microkernel, but for edge cases, it would still see column-stored subproblems (not ideal). This commit fixes this issue. Thanks to Devin for his suggestion. commit c2c91e09b4893cb81314774557f728a95080f81e Author: Jeff Hammond Date: Tue Oct 25 21:15:26 2016 -0700 never use libm with Intel compilers Intel compilers include a highly optimized math library (libimf) that should be used instead of GNU libm. yes, this change is for ALL targets, including those that are not supported by the Intel compiler. there is no harm in doing this, and it is future-proof in the event that the Intel compilers support other architectures. commit 630391002325a589063aec2ab0a7d89ef2e178c0 Merge: 956b3edf 216206c1 Author: Field G. Van Zee Date: Tue Oct 25 19:34:51 2016 -0500 Merge pull request #105 from devinamatthews/knl Support for Intel Knight's Landing. commit 216206c1d328a865c2192e35a4df6e9aff79a85b Author: Devin Matthews Date: Tue Oct 25 13:56:18 2016 -0500 Fix up for merge to master. commit 11eb7957abbcdf02d5e312898e094260eadb1209 Merge: cd5b6681 956b3edf Author: Devin Matthews Date: Tue Oct 25 13:51:07 2016 -0500 Merge branch 'master' into knl # Conflicts: # frame/thread/bli_thread.h commit cd5b6681838899283cd94e5427dfda206e7fbabe Author: Devin Matthews Date: Tue Oct 25 13:49:27 2016 -0500 Don't use %rbp in KNL packing kernels. commit 956b3edf8eb09480f31f2e861c1b10f9ecbb2e52 Merge: b7e41d71 0662a3c1 Author: Field G. Van Zee Date: Tue Oct 25 13:02:57 2016 -0500 Merge pull request #104 from devinamatthews/misspellings Add flexible options for thread model (pthread/posix for pthreads etc.). commit 0662a3c1b1f4644a86bf8e5073d1391808c91b4a Author: Devin Matthews Date: Tue Oct 25 12:42:44 2016 -0500 Add flexible options for thread model (pthread/posix for pthreads etc.). commit e044fa624008c161de32a39d734cddf1dd22dd41 Author: Kiran Varaganti Date: Tue Oct 25 13:03:05 2016 +0530 Changed double precision trsm kernel macro definition to bli_dtrsm_l_int_6x8 from 6x16 : it fixes the seg fault Change-Id: Ia8c1de5fe13a370d691570a50136d55ffb18908a commit b3ed4933aa0da72ad771fb0fdf1727e5ba9ad7b4 Author: Kiran Varaganti Date: Tue Oct 25 13:03:05 2016 +0530 Changed double precision trsm kernel macro definition to bli_dtrsm_l_int_6x8 from 6x16 : it fixes the seg fault Change-Id: Ia8c1de5fe13a370d691570a50136d55ffb18908a commit b7e41d71b07d2af6d22d632c70e0c5f7ce46852c Merge: 4bd905bd 5117d444 Author: Field G. Van Zee Date: Mon Oct 24 16:47:46 2016 -0500 Merge pull request #103 from devinamatthews/patch-1 Change .align to .p2align in Bulldozer ukernels. commit 5117d444f7f3a2bc327f067926eaf2398212edda Author: Devin Matthews Date: Mon Oct 24 16:20:47 2016 -0500 Change .align to .p2align in Bulldozer ukernels Apparently OSX doesn't allow .align directives for >16B, so I've changed these to their .p2align counterparts. commit 4bd905bd4597e0ad7bedf31e25e779d3e2dfda29 Merge: 936d5fdc 7f32dd57 Author: Field G. Van Zee Date: Fri Oct 21 14:48:44 2016 -0500 Merge pull request #93 from ShadenSmith/config_check Adds sanity check to configuration choice. commit 936d5fdc26c6c4dab199a8d11fde948975cfa1d6 Author: Field G. Van Zee Date: Fri Oct 21 14:34:27 2016 -0500 Fixed multithreading compilation bug in 970745a. Details: - Moved the definition of the cpp macro BLIS_ENABLE_MULTITHREADING from bli_thread.h to bli_config_macro_defs.h. Also moved the sanity check that OpenMP and POSIX threads are not both enabled. - Thanks to Krzysztof Drewniak for reporting this bug. commit d250e6a3af3af8beedcda28f508ac03e94efb3c8 Author: Kiran Varaganti Date: Thu Oct 20 14:34:39 2016 +0530 Merged TRSM and scalv routines into zen folder Change-Id: Ice897bc83e8fb70b90f23cc3ce892c39883aceb9 commit 8feb0f85a674e84bec2417486e3bcea584b14c04 Author: Field G. Van Zee Date: Wed Oct 19 16:05:41 2016 -0500 Removed auto-prototyping of malloc()/free() substitutes. Details: - Removed the header file, bli_malloc_prototypes.h, which automatically generated prototypes for the functions specified by the following cpp macros: BLIS_MALLOC_INTL BLIS_FREE_INTL BLIS_MALLOC_POOL BLIS_FREE_POOL BLIS_MALLOC_USER BLIS_FREE_USER These prototypes were originally provided primarily as a convenience to those developers who specified their own malloc()/free() substitutes for one or more of the following. However, we generated these prototypes regardless, even when the default values (malloc and free) of the macros above were used. A problem arose under certain circumstances (e.g., gcc in C++ mode on Linux with glibc) when including blis.h that stemmed from the "throw" specification which was added to the glibc's malloc() prototype, resulting in a prototype mismatch. Therefore, going forward, developers who specify their own custom malloc()/free() substitutes must also prototype those substitutes via bli_kernel.h. Thanks to Krzysztof Drewniak for reporting this bug, and Devin Matthews for researching the nature and potential solutions. commit 970745a5fc7c29de3e202988e5eb104fabca4fdc Author: Field G. Van Zee Date: Wed Oct 19 15:58:03 2016 -0500 Reorganized typedefs to avoid compiler warnings. Details: - Relocated membrk_t definition from bli_membrk.h to bli_type_defs.h. - Moved #include of bli_malloc.h from blis.h to bli_type_defs.h. - Removed standalone mtx_t and mutex_t typedefs in bli_type_defs.h. - Moved #include of bli_mutex.h from bli_thread.h to bli_typedefs.h. - The redundant typedefs of membrk_t and mtx_t caused a warning on some C compilers. Thanks to Tyler Smith for reporting this issue. commit 1c2f7b57d557c05f5ef6148cccafaf0f70d910da Author: sthangar Date: Tue Oct 18 15:06:35 2016 +0530 Removed symlinks to zen kernels from haswell kernel folder and also modified the bli_kernel.h file accordingly Change-Id: Ib3736af48e851c8243bbe10d937fb942c49ad048 commit d864ea9f4f039fe2b2dc395d0015bd9e8902bc8e Merge: 7045fcbf 28b2af8a Author: praveeng Date: Fri Oct 14 17:00:57 2016 +0530 Merge master code 2016_10_14 till Added disabled code thrinfo_t structures Change-Id: If7db98d286c1471fcd30f00757abee9b253ef987 commit 28b2af8a71133ce68774e153b6e05afb05affba8 Author: Field G. Van Zee Date: Thu Oct 13 14:50:08 2016 -0500 Added disabled code to print thrinfo_t structures. Details: - Added cpp-guarded code to bli_thrcomm_openmp.c that allows a curious developer to print the contents of the thrinfo_t structures of each thread, for verification purposes or just to study the way thread information and communicators are used in BLIS. - Enabled some previously-disabled code in bli_l3_thrinfo.c for freeing an array of thrinfo_t* values that is used in the new, cpp-guarde code mentioned above. - Removed some old commented lines from bli_gemm_front.c. commit 11eed3f683d09e65f721567b346b0f733bff9a64 Author: Field G. Van Zee Date: Thu Oct 13 14:23:23 2016 -0500 Fixed a configure -t omp/openmp bug from fd04869. Details: - Forgot to update certain occurrences of "omp" in common.mk during commit fd04869, which changed the preferred configure option string for enabling OpenMP from "omp" to "openmp". commit 7045fcbf0bd349ebe6cb9ac4508c6a387bb05966 Merge: 7e044900 9cda6057 Author: praveeng Date: Thu Oct 13 12:02:28 2016 +0530 Merge master code 2016_10_13 Removed previously renamed/old files Change-Id: I8106d371afaa0af474a8967388d44481b05de923 commit 7e04490002206d3557fcfb7dd893838a7f36916f Author: sthangar Date: Wed Oct 12 16:43:02 2016 +0530 Checked in the SAMAX optimizations Change-Id: I7faf8c3adf52ff01432188ad3b9866ee4b9a9dfd commit 9cda6057eaa16a24ac8785a9fa167df6c9edba44 Author: Field G. Van Zee Date: Tue Oct 11 13:21:26 2016 -0500 Removed previously renamed/old files. Details: - Removed frame/base/bli_mem.c and frame/include/bli_auxinfo_macro_defs.h, both of which were renamed/removed in 701b9aa. For some reason, these files survived when the compose branch was merged back into master. (Clearly, git's merging algorithm is not perfect.) - Removed frame/base/bli_mem.c.prev (an artifact of the long-ago changed memory allocator that I was keeping around for no particular reason). commit 22377abd84b9e560ffe1c4e4d284eb443ddb7133 Author: Field G. Van Zee Date: Mon Oct 10 13:43:56 2016 -0500 Fixed bli_gemm() segfault on empty C matrices. Details: - Fixed a bug that would manifest in the form of a segmentation fault in bli_cntl_free() when calling any level-3 operation on an empty output matrix (ie: m = n = 0). Specifically, the code previously assumed that the entire control tree was built prior to it being freed. However, if the level-3 operation performs an early exit, the control tree will be incomplete, and this scenario is now handled. Thanks to Elmar Peise for reporting this bug. commit 0b571cd94d9b175331c9453258a6b1389a718ae8 Author: Field G. Van Zee Date: Thu Oct 6 14:48:15 2016 -0500 Fixed segfault in bli_free_align() for NULL ptrs. Details: - Fixed a bug in bli_free_align() caused by failing to handle NULL pointers up-front, which led to performing pointer arithmetic on NULL pointers in order to free the address immediately before the pointer. Thanks to Devin Matthews for reporting this bug. commit cd84fb95182514601d72c78ee0e36a394d0284d7 Author: praveeng Date: Thu Oct 6 15:08:21 2016 +0530 syntax erros in configure file Change-Id: Ibe8a6071aad97df550df64c009fec33a9d8f43a1 commit f2e7ea113aa93b74f1d42408d5db2c5a7b00a653 Merge: 133983c3 86969873 Author: praveeng Date: Thu Oct 6 12:35:30 2016 +0530 conflicts merge for bli_kernel.h Change-Id: I15d846bd34e11f86ebfd7ed091ff671a1f3366a0 commit 133983c36fa01c7acb6d666b3744f77f216314a5 Author: sthangar Date: Thu Oct 6 11:26:22 2016 +0530 code clean up in bli_kernel.h Change-Id: I11d9cdf2af8e8199209eb084f6c3a7c910b83d5d commit 4fb9b4ef2e4cf2626a6e000a41628fb823f16da8 Author: Field G. Van Zee Date: Wed Oct 5 14:41:35 2016 -0500 CHANGELOG update (0.2.1) commit 866b2dde3f41760121115fb25f096d4344e8b4f9 (tag: 0.2.1) Author: Field G. Van Zee Date: Wed Oct 5 14:41:34 2016 -0500 Version file update (0.2.1) commit 87fddeab3c8a5ccb1bbf02e5f89db1464e459ba9 Merge: 86969873 6f71cd34 Author: Field G. Van Zee Date: Wed Oct 5 13:35:01 2016 -0500 Merge branch 'compose' commit 6f71cd344951854e4cff9ea21bbdfe536e72611d (origin/compose) Merge: c0630c40 8d55033c Author: Field G. Van Zee Date: Tue Oct 4 15:53:46 2016 -0500 Merge pull request #94 from flame/distcomm Implemented distributed thrinfo_t management. commit 86969873b5b861966d717d8f9f370af39e3d9de6 Author: Field G. Van Zee Date: Tue Oct 4 14:24:59 2016 -0500 Reclassified amaxv operation as a level-1v kernel. Details: - Moved amaxv from being a utility operation to being a level-1v operation. This includes the establishment of a new amaxv kernel to live beside all of the other level-1v kernels. - Added two new functions to bli_part.c: bli_acquire_mij() bli_acquire_vi() The first acquires a scalar object for the (i,j) element of a matrix, and the second acquires a scalar object for the ith element of a vector. - Added integer support to bli_getsc level-0 operation. This involved adding integer support to the bli_*gets level-0 scalar macros. - Added a new test module to test amaxv as a level-1v operation. The test module works by comparing the value identified by bli_amaxv() to the the value found from a reference-like code local to the test module source file. In other words, it (intentionally) does not guarantee the same index is found; only the same value. This allows for different implementations in the case where a vector contains two or more elements containing exactly the same floating point value (or values, in the case of the complex domain). - Removed the directory frame/include/old/. commit 8d55033c966feed99fcca2a58017c3ab5b1646dc Author: Field G. Van Zee Date: Tue Sep 27 15:20:58 2016 -0500 Implemented distributed thrinfo_t management. Details: - Implemented Ricardo Magana's distributed thread info/communicator management. Rather that fully construct the thrinfo_t structures, from root to leaf, prior to spawning threads, the threads individually construct their thrinfo_t trees (or, chains), and do so incrementally, as needed, reusing the same structure nodes during subsequent blocked variant iterations. This required moving the initial creation of the thrinfo_t structure (now, the root nodes) from the _front() functions to the bli_l3_thread_decorator(). The incremental "growing" of the tree is performed in the internal back-end (ie: _int()) function, and so mostly invisible. Also, the incremental growth of the thrinfo_t tree is done as a function of the current and parent control tree nodes (as well as the parent thrinfo_t node), further reinforcing the parallel relationship between the two data structures. - Removed the "inner" communicator from thrinfo_t structure definition, as well as its id. Changed all APIs accordingly. Renamed bli_thrinfo_needs_free_comms() to bli_thrinfo_needs_free_comm(). - Defined bli_l3_thrinfo_print_paths(), which prints the information in an array of thrinfo_t* structure pointers. (Used only as a debugging/verification tool.) - Deprecated the following thrinfo_t creation functions: bli_packm_thrinfo_create() bli_l3_thrinfo_create() because they are no longer used. bli_thrinfo_create() is now called directly when creating thrinfo_t nodes. commit fd04869ae4d4a3b0ebb9052557c296456bce7c0d Author: Field G. Van Zee Date: Tue Sep 27 14:14:11 2016 -0500 Changed configure's 'omp' threading to 'openmp'. Details: - Changed the configure script so that the expected string argument to the -t (or --enable-threading=) option that enables OpenMP multithreading is 'openmp'. The previous expected string, 'omp', is still supported but should be considered deprecated. commit 9424af87209e4e435e2e742430945152690170b0 Merge: efa7341d c0630c40 Author: Field G. Van Zee Date: Tue Sep 27 12:51:08 2016 -0500 Merge branch 'compose' commit 7f32dd57c6bd41c0704341752842277dd6a4c8eb Author: Shaden Smith Date: Sat Sep 17 11:33:57 2016 -0500 Adds sanity check to configuration choice. commit efa7341df0b0115926aa8a6e8a4ebfb24fdbf11e Merge: 121c39d4 e1453f68 Author: Field G. Van Zee Date: Fri Sep 16 11:01:57 2016 -0500 Merge pull request #92 from ShadenSmith/readme_fix Fixes broken URL in README.md commit e1453f68f6afd90ae9a29b7a5faa46aa79bbf741 Author: Shaden Smith Date: Fri Sep 16 09:29:28 2016 -0500 Fixes broken URL in README.md commit b922d7563422e14c49a4677bc6ae088a408861ed Author: Field G. Van Zee Date: Tue Aug 23 13:38:36 2016 -0500 Avoid compiling BLAS/CBLAS files when disabled. Details: - Updated the top-level Makefile, build/config.mk.in template, and configure script so that object files corresponding to source files belonging to the BLAS compatibility layer are not compiled (or archived) when the compatibility layer is disabled. (Same for CBLAS.) Thanks to Devin Matthews for suggesting this optimization. - Slight change to the way configure handles internal variables. Instead of converting (overwriting) some, such as enable_blas2blis and enable_cblas, from a "yes" or "no" to a "1" or "0" value, the latter are now stored in new variables that live alongside the originals (with the suffix "_01"). This is convenient since some values need to be sed-substituted into the config.mk.in template, which requires "yes" or "no", while some need to be written to the bli_config.h.in template, which requires "0" or "1". Updated BLIS4 TOMS citation in README.md. Added complex gemm micro-kernels for haswell. Details: - Defined cgemm (3x8) and zgemm (3x4) micro-kernels for haswell-based architectures. As with their real domain brethren, these kernels perfer row storage, (though this doesn't affect most users due to high-level optimizations in most level-3 operations that induce a transpose to whatever storage preference the kernel may have). Change-Id: I512ab90784ecbb7cdaee24928d2ccebb544ba5c1 commit 69826110bab2a064ec76457c24843d28f2581281 Merge: 64598ee4 a58dd35e Author: Pradeep Rao Date: Wed Sep 14 03:26:25 2016 -0400 Merge "Implemented trsm single precision for lower triangular matrices, files added bli_trsm_l_int_6x16.cfiles modified bli_kernel.h to enable optimized trsm microkernel and test_trsm.c is modified to test trsm single precision" into amd-staging commit c0630c4024b08750043a2942a3e8a037aa6b6259 Author: Field G. Van Zee Date: Mon Sep 12 13:59:02 2016 -0500 Added debugging printf()'s to bli_l3_thrinfo.c. Details: - Added optional printf() statements to print out thread communicator info as the thrinfo_t structure is built in bli_l3_thrinfo.c. - Minor changes to frame/thread/bli_thrinfo.h. commit 7b3bf1ffcd7160ccbf6c2518af6d88f6742e4977 Merge: 35509818 121c39d4 Author: Field G. Van Zee Date: Tue Sep 6 15:47:13 2016 -0500 Merge branch 'master' into compose commit 121c39d455f2db6f7ce6802ba7f73ad5e088c68c Author: Field G. Van Zee Date: Mon Sep 5 13:11:42 2016 -0500 Added complex gemm micro-kernels for haswell. Details: - Defined cgemm (3x8) and zgemm (3x4) micro-kernels for haswell-based architectures. As with their real domain brethren, these kernels perfer row storage, (though this doesn't affect most users due to high-level optimizations in most level-3 operations that induce a transpose to whatever storage preference the kernel may have). commit 35509818cbea1598b123421f81c42120889a03c3 Author: Field G. Van Zee Date: Wed Aug 31 17:34:15 2016 -0500 Added, moved some thread barriers. Details: - Removed thread barriers from the end of the loop bodies of bli_gemm_blk_var1(), bli_gemm_blk_var2(), bli_trsm_blk_var1(), and bli_trsm_blk_var2(). - Moved the thread barrier at the end of bli_packm_int() to the end of bli_l3_packm(), and added missing barriers to that function. - Removed the no longer necessary (and now incorrect) ochief guard in bli_gemm3m3_packa() on the bli_obj_scalar_reset() on C. - Thanks to Tyler Smith for help with these changes. commit 64598ee4cfb86f64abbd4bcef5a82ba0d5565b67 Author: sthangar Date: Wed Aug 31 12:54:50 2016 +0530 fixed the symlink issue Change-Id: I2186d529f295c576597c189e1ae219bc1a83f955 commit abd61f9fa75d77a96d1491b3e035451ee73238fe Author: Field G. Van Zee Date: Tue Aug 30 12:34:19 2016 -0500 Updated BLIS4 TOMS citation in README.md. commit 8a2373f26ba8fcd5b2d7b2cc72cb8b2e1f841a03 Author: sthangar Date: Mon Aug 29 14:10:45 2016 +0530 Norm 2 optimization Change-Id: Ide9decaccd20bf0ccc32c9abb6556e038dceed2b commit fdc663902347aa252ea88cf09ce24ab748958dff Author: sthangar Date: Mon Aug 29 10:43:38 2016 +0530 Placed 1 and 1f AMD optimized AVX routines under zen folder Change-Id: I26795211ef11d232ed794ce36dd0a9c1f8706328 commit 701b9aa3ff028decbf90efac0dca5bd64fe26269 Author: Field G. Van Zee Date: Fri Aug 26 19:04:45 2016 -0500 Redesigned control tree infrastructure. Details: - Altered control tree node struct definitions so that all nodes have the same struct definition, whose primary fields consist of a blocksize id, a variant function pointer, a pointer to an optional parameter struct, and a pointer to a (single) sub-node. This unified control tree type is now named cntl_t. - Changed the way control tree nodes are connected, and what computation they represent, such that, for example, packing operations are now associated with nodes that are "inline" in the tree, rather than off- shoot braches. The original tree for the classic Goto gemm algorithm was expressed (roughly) as: blk_var2 -> blk_var3 -> blk_var1 -> ker_var2 | | -> packb -> packa and now, the same tree would look like: blk_var2 -> blk_var3 -> packb -> blk_var1 -> packa -> ker_var2 Specifically, the packb and packa nodes perform their respective packing operations and then recurse (without any loop) to a subproblem. This means there are now two kinds of level-3 control tree nodes: partitioning and non-partitioning. The blocked variants are members of the former, because they iteratively partition off submatrices and perform suboperations on those partitions, while the packing variants belong to the latter group. (This change has the effect of allowing greatly simplified initialization of the nodes, which previously involved setting many unused node fields to NULL.) - Changed the way thrinfo_t tree nodes are arranged to mirror the new connective structure of control trees. That is, packm nodes are no longer off-shoot branches of the main algorithmic nodes, but rather connected "inline". - Simplified control tree creation functions. Partitioning nodes are created concisely with just a few fields needing initialization. By contrast, the packing nodes require additional parameters, which are stored in a packm-specific struct that is tracked via the optional parameters pointer within the control tree struct. (This parameter struct must always begin with a uint64_t that contains the byte size of the struct. This allows us to use a generic function to recursively copy control trees.) gemm, herk, and trmm control tree creation continues to be consolidated into a single function, with the operation family being used to select among the parameter-agnostic macro-kernel wrappers. A single routine, bli_cntl_free(), is provided to free control trees recursively, whereby the chief thread within a groups release the blocks associated with mem_t entries back to the memory broker from which they were acquired. - Updated internal back-ends, e.g. bli_gemm_int(), to query and call the function pointer stored in the current control tree node (rather than index into a local function pointer array). Before being invoked, these function pointers are first cast to a gemm_voft (for gemm, herk, or trmm families) or trsm_voft (for trsm family) type, which is defined in frame/3/bli_l3_var_oft.h. - Retired herk and trmm internal back-ends, since all execution now flows through gemm or trsm blocked variants. - Merged forwards- and backwards-moving variants by querying the direction from routines as a function of the variant's matrix operands. gemm and herk always move forward, while trmm and trsm move in a direction that is dependent on which operand (a or b) is triangular. - Added functions bli_thread_get_range_mdim(), bli_thread_get_range_ndim(), each of which takes additional arguments and hides complexity in managing the difference between the way ranges are computed for the four families of operations. - Simplified level-3 blocked variants according to the above changes, so that the only steps taken are: 1. Query partitioning direction (forwards or backwards). 2. Prune unreferenced regions, if they exist. 3. Determine the thread partitioning sub-ranges. 4. Determine the partitioning blocksize (passing in the partitioning direction) 5. Acquire the curren iteration's partitions for the matrices affected by the current variants's partitioning dimension (m, k, n). 6. Call the subproblem. - Instantiate control trees once per thread, per operation invocation. (This is a change from the previous regime in which control trees were treated as stateless objects, initialized with the library, and shared as read-only objects between threads.) This once-per-thread allocation is done primarily to allow threads to use the control tree as as place to cache certain data for use in subsequent loop iterations. Presently, the only application of this caching is a mem_t entry for the packing blocks checked out from the memory broker (allocator). If a non-NULL control tree is passed in by the (expert) user, then the tree is copied by each thread. This is done in bli_l3_thread_decorator(), in bli_thrcomm_*.c. - Added a new field to the context, and opid_t which tracks the "family" of the operation being executed. For example, gemm, hemm, and symm are all part of the gemm family, while herk, syrk, her2k, and syr2k are all part of the herk family. Knowing the operation's family is necessary when conditionally executing the internal (beta) scalar reset on on C in blocked variant 3, which is needed for gemm and herk families, but must not be performed for the trmm family (because beta has only been applied to the current row-panel of C after the first rank-kc iteration). - Reexpressed 3m3 induced method blocked variant in frame/3/gemm/ind to comform with the new control tree design, and renamed the macro- kernel codes corresponding to 3m2 and 4m1b. - Renamed bli_mem.c (and its APIs) to bli_memsys.c, and renamed/relocated bli_mem_macro_defs.h from frame/include to frame/base/bli_mem.h. - Renamed/relocated bli_auxinfo_macro_defs.h from frame/include to frame/base/bli_auxinfo.h. - Fixed a minor bug whereby the storage-to-ukr-preference matching optimization in the various level-3 front-ends was not being applied properly when the context indicated that execution would be via an induced method. (Before, we always checked the native micro-kernel corresponding to the datatype being executed, whereas now we check the native micro-kernel corresponding to the datatype's real projection, since that is the micro-kernel that is actually used by induced methods. - Added an option to the testsuite to skip the testing of native level-3 complex implementations. Previously, it was always tested, provided that the c/z datatypes were enabled. However, some configurations use reference micro-kernels for complex datatypes, and testing these implementations can slow down the testsuite considerably. commit a58dd35ed7b5b77a6b272655d2edd7a822b8fa87 Author: Kiran Varaganti Date: Fri Aug 26 14:55:12 2016 +0530 Implemented trsm single precision for lower triangular matrices, files added bli_trsm_l_int_6x16.cfiles modified bli_kernel.h to enable optimized trsm microkernel and test_trsm.c is modified to test trsm single precision Change-Id: Ibddf989f4aad577e89558673e1038cf6ece654d9 commit 73517f522b69de429dd7f3df60a70c068149ab28 Merge: c6f5c215 50293da3 Author: Field G. Van Zee Date: Tue Aug 23 13:46:59 2016 -0500 Merge branch 'master' into compose commit 50293da38d5f2b7be9bbc94b9e85aacb6a10f672 Author: Field G. Van Zee Date: Tue Aug 23 13:38:36 2016 -0500 Avoid compiling BLAS/CBLAS files when disabled. Details: - Updated the top-level Makefile, build/config.mk.in template, and configure script so that object files corresponding to source files belonging to the BLAS compatibility layer are not compiled (or archived) when the compatibility layer is disabled. (Same for CBLAS.) Thanks to Devin Matthews for suggesting this optimization. - Slight change to the way configure handles internal variables. Instead of converting (overwriting) some, such as enable_blas2blis and enable_cblas, from a "yes" or "no" to a "1" or "0" value, the latter are now stored in new variables that live alongside the originals (with the suffix "_01"). This is convenient since some values need to be sed-substituted into the config.mk.in template, which requires "yes" or "no", while some need to be written to the bli_config.h.in template, which requires "0" or "1". commit 22dd6a353ddb56614309c01533b1a94c9fd32bca Merge: cdfb3c3f f20ed388 Author: praveeng Date: Tue Aug 23 15:15:35 2016 +0530 Merge master code as on 2016_08_23 to amd-staging branch by praveeng Changes to be committed: modified: frame/thread/bli_mutex_openmp.h modified: frame/thread/bli_mutex_pthreads.h Change-Id: Ica522edbb1d0173f53f38d5057b1f7aef73666be commit c6f5c215ee793d03ea834469fc2adc53feaffc42 Merge: d52cb767 16a4c7a8 Author: Field G. Van Zee Date: Mon Aug 22 17:33:02 2016 -0500 Merge branch 'master' into compose commit f20ed3885d628992fab88690f629a5a2bab3eb88 Merge: 02ac597e 4bc842ca Author: praveeng Date: Mon Aug 22 15:27:33 2016 +0530 Merge branch 'master' of https://github.com/clMathLibraries/blis-amd for "Fixed bugs in bli_mutex_init() and friends." commit 02ac597e4b9be2670d9fff65d28552f8e1ec81b3 Author: praveeng Date: Thu Jul 28 15:11:08 2016 +0530 Revert commits 357c990bdd7bd5667aac5adf1bab3712973e7414 Change-Id: I12a34456d7eed93fda4369e76bcddb42ba7ccb99 commit 84e41cc73c9c87ce64582acd4264b8e1b5316482 Author: praveeng Date: Thu Jul 28 15:01:36 2016 +0530 Revert commits 8aee306 Change-Id: I3dd999c77c6779332a40dbb84371ca487216f189 commit 30ccfcee82db93d0109d1571242e2db925e95d0a Author: praveeng Date: Mon Jul 25 14:14:00 2016 +0530 removed changes from readme file which are giving confilcts Change-Id: Ic71ad1313e1404fed444e899466043704d875af6 commit aeca25cd63fc8971f8fe7809599c57853f976548 Author: praveeng Date: Tue Jul 5 16:51:23 2016 +0530 first commit Change-Id: Ib50c81acda3b2c1583da3d421efc0ca547ef68e2 commit 6b2274864b36fd1019d97bcc4ca6dd7a57ef16d9 Author: praveeng Date: Tue Jul 5 15:00:31 2016 +0530 small modification to readme for git push test Change-Id: I68506a49586b07eaa907f3f85304ee40d4c92d0a commit daa7a9ecb25982f2551adbd95e65f8ba97cfe944 Author: praveeng Date: Tue Jul 5 16:51:23 2016 +0530 first commit Change-Id: Ib50c81acda3b2c1583da3d421efc0ca547ef68e2 commit 5f66a4aa05aeffcb6eb587851d78d9527319466c Author: praveeng Date: Tue Jul 5 15:00:31 2016 +0530 small modification to readme for git push test Change-Id: I68506a49586b07eaa907f3f85304ee40d4c92d0a commit c6cbd78d2388c08824822b91a1c36ac4349bb67f Author: praveeng Date: Thu Jul 28 15:11:08 2016 +0530 Revert commits 357c990bdd7bd5667aac5adf1bab3712973e7414 Change-Id: I12a34456d7eed93fda4369e76bcddb42ba7ccb99 commit 9219a9060762525f87ebbf556d78fe8621858513 Author: praveeng Date: Thu Jul 28 15:01:36 2016 +0530 Revert commits 8aee306 Change-Id: I3dd999c77c6779332a40dbb84371ca487216f189 commit 728573296efa7cf14d2381570e116509dfe2a240 Author: praveeng Date: Mon Jul 25 14:14:00 2016 +0530 removed changes from readme file which are giving confilcts Change-Id: Ic71ad1313e1404fed444e899466043704d875af6 commit ad7862e291c240505c733a41d231b1a126ade73c Author: praveeng Date: Tue Jul 5 16:51:23 2016 +0530 first commit Change-Id: Ib50c81acda3b2c1583da3d421efc0ca547ef68e2 commit ad4b471a25ce77867295e5529dfc787e7c18b03f Author: praveeng Date: Tue Jul 5 15:00:31 2016 +0530 small modification to readme for git push test Change-Id: I68506a49586b07eaa907f3f85304ee40d4c92d0a commit 55d641363fcd8bdfdabbd7c22822fa2d0b7f3fa6 Author: praveeng Date: Tue Jul 5 16:51:23 2016 +0530 first commit Change-Id: Ib50c81acda3b2c1583da3d421efc0ca547ef68e2 commit f3b6b15f6d591d323802bd6c81c522a02056506d Author: praveeng Date: Tue Jul 5 15:00:31 2016 +0530 small modification to readme for git push test Change-Id: I68506a49586b07eaa907f3f85304ee40d4c92d0a commit 16a4c7a823d60707ed9272f5d36e5c5d54c0ba4b Author: Field G. Van Zee Date: Fri Aug 19 11:38:36 2016 -0500 Fixed bugs in bli_mutex_init() and friends. Details: - Fixed a couple of bugs that affected OpenMP and POSIX threads configurations that resulted in compiler errors and warnings due to type mismatch, and in the case of pthreads, a missing function argument. The bugs are fairly recent, introduced in a017062. commit c8e4ef93953ba2b79fb7e0973c08469c0e28a2cd Author: Devin Matthews Date: Wed Aug 3 16:13:03 2016 -0500 Add prefetchw to 30x8 kernel. commit 4b5a2f3d6e7ffeb5cc2be8448554f5c2083ad68f Merge: 380736bf 9f52a587 Author: Devin Matthews Date: Wed Aug 3 16:09:51 2016 -0500 Merge remote-tracking branch 'origin/knl' into knl # Conflicts: # kernels/x86_64/knl/3/bli_dgemm_opt_24x8.c commit 380736bfe955efbdd7274c90b6fd635688e83bc4 Author: Devin Matthews Date: Wed Aug 3 16:08:28 2016 -0500 Add (new) 30x8 KNL kernel and fix non-scatter prefetch bug. commit 9f52a587dee855daa73c194e41b6951416544e9a Author: Devin Matthews Date: Wed Aug 3 16:03:53 2016 -0500 Try prefetchw[t1] instead of regular prefetch for C. commit 8945a1512d366bc6a8a85718d12cbf5de6f2898b Author: Devin Matthews Date: Wed Aug 3 11:28:24 2016 -0500 This version gets ~1550 GFLOPs on KNL wuth 16x4. commit cdfb3c3f29d321033fca106aa58ab67ead90a95d Merge: 50a2f2ef 4bc842ca Author: praveeng Date: Fri Jul 29 12:45:04 2016 +0530 Merge master code as on 2016_07_29 to amd-staging branch by praveeng Change-Id: Ic78b84d8b8d10158fb2a612f9a64bbc7b1f9b486 commit 4bc842ca3a64e658c0808bfe4c5693a5ace97923 Merge: 117f8838 b0d510bf Author: praveeng Date: Thu Jul 28 17:32:12 2016 +0530 Merge branch 'master' of publicrepo commit 117f8838511a478aa16137e770d27dd21f4227c5 Author: praveeng Date: Thu Jul 28 15:11:08 2016 +0530 Revert commits 357c990bdd7bd5667aac5adf1bab3712973e7414 Change-Id: I12a34456d7eed93fda4369e76bcddb42ba7ccb99 commit 2fcdc28f1055d385b2e662aa920fb97c472394d7 Author: praveeng Date: Thu Jul 28 15:01:36 2016 +0530 Revert commits 8aee306 Change-Id: I3dd999c77c6779332a40dbb84371ca487216f189 commit 1b5d104afe0628b8b6c0650f1e58cfb08be67004 Author: praveeng Date: Mon Jul 25 14:14:00 2016 +0530 removed changes from readme file which are giving confilcts Change-Id: Ic71ad1313e1404fed444e899466043704d875af6 commit d81273047bff56501e9413a90991d3d1f8b56a06 Author: praveeng Date: Tue Jul 5 16:51:23 2016 +0530 first commit Change-Id: Ib50c81acda3b2c1583da3d421efc0ca547ef68e2 commit 65905c3011a11cda95761681d4ae84337e46bdb5 Author: praveeng Date: Tue Jul 5 15:00:31 2016 +0530 small modification to readme for git push test Change-Id: I68506a49586b07eaa907f3f85304ee40d4c92d0a commit 23cca231be10fe1797aed451bcbc69d38c78bc0c Author: praveeng Date: Tue Jul 5 16:51:23 2016 +0530 first commit Change-Id: Ib50c81acda3b2c1583da3d421efc0ca547ef68e2 commit 922e3091702f25e3287b417719a33adbd5bbf138 Author: praveeng Date: Tue Jul 5 15:00:31 2016 +0530 small modification to readme for git push test Change-Id: I68506a49586b07eaa907f3f85304ee40d4c92d0a commit b0d510bf0e4dfd177f9e4ae0069f41921e2ecdc1 Author: praveeng Date: Thu Jul 28 15:11:08 2016 +0530 Revert commits 357c990bdd7bd5667aac5adf1bab3712973e7414 Change-Id: I12a34456d7eed93fda4369e76bcddb42ba7ccb99 commit 5ebeece5b4a8df81d59ca7558b278a4263d15128 Author: praveeng Date: Thu Jul 28 15:01:36 2016 +0530 Revert commits 8aee306 Change-Id: I3dd999c77c6779332a40dbb84371ca487216f189 commit 6ce4c022ebdea00c2b951090e3c2e9e88735b9ce Author: Devin Matthews Date: Wed Jul 27 16:26:36 2016 -0500 Switch back to 24x8. I could only squeeze 24.5GFLOP out of 8x24, and scalability is not improved. commit d52cb7671509592a8078729477b40b60380518a2 Merge: 95abea46 c31b1e7b Author: Field G. Van Zee Date: Wed Jul 27 16:04:55 2016 -0500 Merge branch 'master' into compose commit c31b1e7b9d659b96433a87e5aecb90e457a104cc Author: Field G. Van Zee Date: Wed Jul 27 15:58:07 2016 -0500 Relax alignment restrictions for sandybridge ukrs. Details: - Relaxed the base pointer and leading dimension alignment restrictions in the sandybridge gemm microkernels, allowing the use of vmovups/vmovupd instead of vmovaps/vmovapd. These change mimic those made to the haswell microkernels in e0d2fa0 and ee2c139. - Updated testsuite modules as well as standalone test drivers in 'test' directory to use DBL_MAX as the initial time candidate. Thanks to Devin Matthews for suggesting this change. - Inserted #include "float.h" into bli_system.h (to gain access to DBL_MAX). - Minor update (vis-a-vis contexts) to driver code in test/3m4m. commit b8f2b55532849d45d379afbdd05a52ff6100800d Author: Devin Matthews Date: Wed Jul 27 15:22:55 2016 -0500 Try an 8x24 kernel for the hell of it. commit 7ede5863ae3567f7c0852efc2d5cd649ca19e0f3 Author: Devin Matthews Date: Wed Jul 27 13:41:27 2016 -0600 Allocate pack buffer on MCDRAM for KNL. commit ad89ed2e829c7b261d8ba0998a3cb83ad576ee04 Merge: 2c9de740 81e2b05f Author: Devin Matthews Date: Wed Jul 27 11:45:40 2016 -0500 Merge branch 'knl' of github.com:devinamatthews/blis into knl commit 2c9de740edb66c4692c200731763bbd1d3171ccb Author: Devin Matthews Date: Wed Jul 27 11:44:54 2016 -0500 This version gets ~26GF on one core. commit 81e2b05f31bca4e1e1676e7b533d1868d9f9be33 Author: Devin Matthews Date: Wed Jul 27 11:39:05 2016 -0500 Add optimized packing kernels for KNL. commit a7d8ca97b8d835c32d90ff20a565c82733f014a8 Author: Devin Matthews Date: Mon Jul 25 15:15:13 2016 -0500 All fixed. commit 963d0393b023f4134bb0c682923faf9964c0e645 Author: Devin Matthews Date: Mon Jul 25 14:40:53 2016 -0500 Add 24xk pack kernel. commit 117b76739afba481768897d2580f8365d3345417 Author: Devin Matthews Date: Mon Jul 25 13:53:07 2016 -0500 In the midst of debugging. commit 8c0a4fd1d3535d608a9a309a61ffee0a73c3646f Author: Devin Matthews Date: Mon Jul 25 13:09:24 2016 -0500 Fix some row/column confusion. commit c44f9f96930312125b15e64c326ab5ab5cc02633 Author: Devin Matthews Date: Mon Jul 25 12:02:24 2016 -0500 Simplify displacements -- clang assembler was badly botching EVEX compressed displacements giving false alarms for instruction length. commit e0cce177cc1b47ec9f11ac0556241feaa3564df1 Author: Devin Matthews Date: Mon Jul 25 10:02:25 2016 -0500 Minor fixes for 8x24 KNL kernel. commit 50a2f2efcbeb46537f1deaa8e44dc579a4e49eb8 Merge: 1aa77dfc cfd46c88 Author: praveeng Date: Mon Jul 25 17:01:20 2016 +0530 Merge master code as on 2016_07_25 to amd-staging branch by praveeng Change-Id: I84886ae241db2aac0bef6b7ef399f04aa8bca16d commit cfd46c88d59c8f61d5e7cf768d606e4c44623584 Merge: f493bf4d a017062f Author: praveeng Date: Mon Jul 25 15:38:13 2016 +0530 Merge remote-tracking branch 'publicrepo/master' commit f493bf4d704fe0e967783cd6e6877d3302c056a1 Author: praveeng Date: Mon Jul 25 14:14:00 2016 +0530 removed changes from readme file which are giving confilcts Change-Id: Ic71ad1313e1404fed444e899466043704d875af6 commit 65735bbedf75784c48bd11e05b3fdc98fc66b4bc Author: Devin Matthews Date: Sun Jul 24 21:50:32 2016 -0500 Switch to 24x8 kernel, unrolled by 16. commit 45d5dc97177117220bd9dd0abf85aafc185acad1 Author: Devin Matthews Date: Sun Jul 24 14:25:26 2016 -0500 Add 24x8 "KNC-style" kernel for KNL. commit 95abea46f86816fddfc9ff0abfa52880801461be Merge: d0dfe5b5 a017062f Author: Field G. Van Zee Date: Sat Jul 23 15:38:33 2016 -0500 Merge branch 'master' into compose commit a017062fdf763037da9d971a028bb07d47aa1c8a Author: Field G. Van Zee Date: Fri Jul 22 17:02:59 2016 -0500 Integrated "memory broker" (membrk_t) abstraction. Details: - Integrated a patch originally authored and submitted by Ricardo Magana of HP Enterprise. The changeset inserts use of a new object type, membrk_t, (memory broker) that allows multiple sets of memory pools on, for example, separate NUMA nodes, each of which has a separate memory space. - Added membrk field to cntx_t and defined corresponding accessor macros. - Added membrk field to mem_t object and defined corresponding accessor macros. - Created new bli_membrk.c file, which contains the new memory broker API, including: bli_membrk_init(), bli_membrk_finalize() bli_membrk_acquire_[mv](), bli_membrk_release(), bli_membrk_init_pools(), bli_membrk_reinit_pools(), bli_membrk_finalize_pools(), bli_membrk_pool_size() - In bli_mem.c, changed function calls to bli_mem_init_pools() -> bli_membrk_init() bli_mem_reinit_pools() -> bli_membrk_reinit() bli_mem_finalize_pools() -> bli_membrk_finalize() - In bli_packv_init.c, bli_packm_init.c, changed function calls to: bli_mem_acquire_[mv]() -> bli_membrk_acquire_[mv]() bli_mem_release() -> bli_membrk_release() - Added bli_mutex.c and related files to frame/thread. These files define abstract mutexes (locks) and corresponding APIs for pthreads, openmp, or single-threaded execution. This new API is employed within functions such as bli_membrk_acquire_[mv]() and bli_membrk_release(). commit 8ff2e069c48c12fd06b9c48c6b3aeb4ea9b0e6e1 Author: Devin Matthews Date: Fri Jul 22 16:22:26 2016 -0500 Add 4x unrolled variant for KNL microkernel. commit 9cb2ed9b0c25f31a22c1c9719b062fa665ad7adf Author: Devin Matthews Date: Fri Jul 22 16:10:30 2016 -0500 Git rid of one RBX update. commit 451bde076f0320d60cd2475cfb048ac4a2b798bb Author: Devin Matthews Date: Fri Jul 22 15:43:00 2016 -0500 Add some more knobs to twiddle for KNL microkernel. commit 8c6e621c099521e7a4d87e007bb8224faa5f33a3 Author: Devin Matthews Date: Fri Jul 22 15:05:15 2016 -0500 Make knl conform to new kernel dir structure. commit ce7214c6618d6f22f4ce2ee452336236916d1f30 Merge: 119d0399 ce59f811 Author: Devin Matthews Date: Fri Jul 22 14:59:53 2016 -0500 Merge remote-tracking branch 'origin/master' into knl commit ce59f81108ec9aea918a7e77030da8acfdd397ce Merge: ff41153f 707a2b7f Author: Field G. Van Zee Date: Fri Jul 22 14:48:14 2016 -0500 Merge pull request #88 from devinamatthews/32bit-dim_t Handle 32-bit dim_t in 64-bit microkernels. commit 707a2b7faca137cca7cab7b11a12c44ddaf7ad53 Author: Devin Matthews Date: Fri Jul 22 13:49:44 2016 -0500 Somehow forgot the most important microkernel. commit 47ec045056351ac4f0791c071fa0daaa81699c8c Merge: 08f1d6b6 ff41153f Author: Devin Matthews Date: Fri Jul 22 13:45:23 2016 -0500 Merge remote-tracking branch 'upstream/master' into 32bit-dim_t commit 08f1d6b6fa344275de0f675f69737145ccf6646a Author: Devin Matthews Date: Fri Jul 22 13:44:37 2016 -0500 Use 64-bit intermediate variable for k for architectures that do 64-bit loads in case dim_t is 32-bit. commit ff41153f4eb7f38ed94bdd9a3fd81fb979f3f401 Merge: f9214ced e0d2fa0d Author: Field G. Van Zee Date: Fri Jul 22 13:21:03 2016 -0500 Merge pull request #86 from devinamatthews/haswell-vmovups Remove alignment restrictions on C in haswell kernel. commit e0d2fa0d835ab49366aeb790363bb2b571d36ed8 Author: Devin Matthews Date: Fri Jul 22 12:56:51 2016 -0500 Relax alignment restrictions for haswell sgemm. commit f9214ced97392861f5a0ea72abfcf6f41faf674c Merge: 413d62ac 08666eaa Author: Field G. Van Zee Date: Fri Jul 22 12:16:39 2016 -0500 Merge pull request #85 from devinamatthews/qopenmp Change -openmp to -fopenmp for icc. commit ee2c139df6ad53c6aec8a67ab23b3b1912e8d259 Author: Devin Matthews Date: Fri Jul 22 12:06:03 2016 -0500 Remove alignment restrictions on C in haswell kernel. commit 08666eaa20d8a31f2f92f944e5bfa7c1558c53e4 Author: Devin Matthews Date: Fri Jul 22 11:07:34 2016 -0500 Change -openmp to -fopenmp for icc. commit 119d0399428905053265f3aca1cc8cc1fde3b363 Author: Devin Matthews Date: Fri Jul 22 10:23:31 2016 -0500 Add 8x24 KNL kernel. commit 1aa77dfc1dc183d16e0b6a1196d9c263f021e83d Merge: 9101a9c8 ec9f5983 Author: praveeng Date: Thu Jul 21 14:22:40 2016 +0530 Merge master code as on 2016_07_21 to amd-staging branch by praveeng Change-Id: Ic7d0a21101358f08147736e7f1884e7409937344 commit b58cda9eba0c1e175460aae109baf792d29ba5bf Merge: 318f063d 413d62ac Author: Devin Matthews Date: Tue Jul 19 14:09:09 2016 -0500 Merge remote-tracking branch 'origin/master' into knl # Conflicts: # frame/base/bli_threading.h # frame/include/blis.h # frame/thread/bli_thread.c commit ec9f59836b32260c29ff1cd24e629c7d8de14992 Merge: 197e182f 763babe4 Author: praveeng Date: Mon Jul 18 12:56:25 2016 +0530 Merge branch 'master' of https://github.com/clMathLibraries/blis-amd commit 197e182fcbf1340fd4a202fac58bea6cfcfa9e2f Author: praveeng Date: Tue Jul 5 16:51:23 2016 +0530 first commit Change-Id: Ib50c81acda3b2c1583da3d421efc0ca547ef68e2 commit 41fb32711031e7ec86b062aa7f53255d1f5905e2 Author: praveeng Date: Tue Jul 5 15:00:31 2016 +0530 small modification to readme for git push test Change-Id: I68506a49586b07eaa907f3f85304ee40d4c92d0a commit d0dfe5b5372cc7558ee9c4104b29f82eecc7ed61 Merge: 31def12e 413d62ac Author: Field G. Van Zee Date: Thu Jul 14 11:01:06 2016 -0500 Merge branch 'master' into compose commit 9101a9c880e3934f8a63ffc7fe15f5fc1077a73d Author: sthangar Date: Wed Jul 13 16:51:14 2016 +0530 Checked in optimized 1V kernels along with benchmark codes. Also incorporated review comments for 1F kernels Change-Id: I035c0d39e6b0bed28e6e2041242186c49f6ed55b commit 763babe488880b42c86c7fc207aa7665bd0ff9f7 Merge: 357c990b 413d62ac Author: praveeng Date: Wed Jul 13 11:57:19 2016 +0530 Merge remote-tracking branch 'publirepo/master' commit 413d62aca28edabba56605a9f87d5b715831e1db Author: Field G. Van Zee Date: Tue Jul 12 15:02:52 2016 -0500 README update (use official ACM TOMS links). commit dfa431f696db2df4065ea454df268a2e0bc02eac Author: Field G. Van Zee Date: Tue Jul 12 14:21:19 2016 -0500 README update (BLIS2 TOMS article now in-print). commit 357c990bdd7bd5667aac5adf1bab3712973e7414 Author: praveeng Date: Tue Jul 5 16:51:23 2016 +0530 first commit Change-Id: Ib50c81acda3b2c1583da3d421efc0ca547ef68e2 commit 8aee306300adb099b66036f2c2f7f3996433cf49 Author: praveeng Date: Tue Jul 5 15:00:31 2016 +0530 small modification to readme for git push test Change-Id: I68506a49586b07eaa907f3f85304ee40d4c92d0a commit 31def12e2629f187e40f93f6bae9e26a6c2660e2 Author: Field G. Van Zee Date: Thu Jun 30 15:19:20 2016 -0500 First phase of control tree redesign. Details: - These changes constitute the first set of changes in preparation to revamping the structure and use of control trees in BLIS. Modifications in this commit don't affect the control tree code yet, but rather lay the groundwork. - Defined wrappers for the following functions, where the the wrappers each take a direction parameter of a new enumerated type (BLIS_BWD or BLIS_FWD), dir_t, and executes the correct underlying function. - bli_acquire_mpart_*() and _vpart_*() - bli_*_determine_kc_[fb]() - bli_thread_get_range_*() and bli_thread_get_range_weighted_*() - Consolidated all 'f' (forwards-moving) and 'b' (backwards-moving) blocked variants for trmm and trsm, and renamed gemm and herk variants accordingly. The direction is now queried via routines such as bli_trmm_direct(), which deterines the direction from the implied side and uplo parameters. For gemm and herk, it is uncondtionally BLIS_FWD. - Defined wrappers to parameter-specific macrokernels for herk, trmm, and trsm, e.g. bli_trmm_xx_ker_var2(), that execute the correct underlying macrokernel based on the implied parameters. The same logic used to choose the dir_t in _direct() functions is used here. - Simplified the function pointer arrays in _int() functions given the consolidation and dir_t querying mentioned above. - Function signature (whitespace) reformatting for various functions. - Removed old code in various 'old' directories. commit 405c9d46344d93c3eab5572b233900b50ca50d68 Author: sthangar Date: Wed Jun 22 12:18:54 2016 +0530 Check-in the fused kernels optimized for Zen Change-Id: I7b2f467b960e7b9a285f06e47be87de122e5fa24 commit 232754feecf29452987666b9f5ebba2619bfd0b0 Author: Field G. Van Zee Date: Tue Jun 21 14:25:39 2016 -0500 Fixed compiler warning in rand[vm], randn[vm]. Details: - Fixed compiler warnings about unused variables related to the disabling of normalization in the structured cases of the rand[vm] and randn[vm] operations. commit a89555d1605574f3685813dcc972b636dd61264d Author: Field G. Van Zee Date: Fri Jun 17 14:08:35 2016 -0500 Added randn[vm] operations, support in testsuite. Details: - Defined a new randomization operation, randn, on vectors and matrices. The randnv and randnm operations randomize each element of the target object with values from a narrow range of values. Presently, those values are all integer powers of two, but they do not need to be powers of two in order to achieve the primary goal, which is to initialize objects that can be operated on with plenty of precision "slack" available to allow computations that avoid roundoff. Using this method of randomization makes it much more likely that testsuite residuals of properly-functioning operations are close to zero, if not exactly zero. - Updated existing randomization operations randv and randm to skip special diagonal handling and normalization for matrices with structure. This is now handled by the testsuite modules by explicitly calling a testsuite function that loads the diagonal (and scales off-diagonal elements). - Added support for randnv and randnm in the testsuite with a new switch in input.general that universally toggles between use of the classic randv/randm, which use real values on the interval [-1,1], and randnv/randnm, which use only values from a narrow range. Currently, the narrow range is: +/-{2^0, 2^-1, 2^-2, 2^-3, 2^-4, 2^-5, 2^-6}, as well as 0.0. - Updated testsuite modules so that a testsutie wrapper function is called instead of directly calling the randomization operations (such as bli_randv() and bli_randm()). This wrapper also takes a bool_t that indicates whether the object's elements should be normalized. (NOTE: As alluded to above, in the test modules of triangular solve operations such as trsv and trsm, we perform the extra step of loading the diagonal.) - Defined a new level-0 operation, invertsc, which inverts a scalar. - Updated the abval2ris and sqrt2ris level-0 macros to avoid an unlikely but possible divide-by-zero. - Updated function signature and prototype formatting in testsuite. commit 318f063dcbd8b594969e401bc99146d24b01066a Author: Devin Matthews Date: Wed Jun 8 17:46:50 2016 -0500 Add new KNL microkernel derived from Haswell. commit 096895c5d538a7f8817603d7cf28c52e99340def Author: Field G. Van Zee Date: Mon Jun 6 13:32:04 2016 -0500 Reorganized code, APIs related to multithreading. Details: - Reorganized code and renamed files defining APIs related to multithreading. All code that is not specific to a particular operation is now located in a new directory: frame/thread. Code is now organized, roughly, by the namespace to which it belongs (see below). - Consolidated all operation-specific *_thrinfo_t object types into a single thrinfo_t object type. Operation-specific level-3 *_thrinfo_t APIs were also consolidated, leaving bli_l3_thrinfo_*() and bli_packm_thrinfo_*() functions (aside from a few general purpose bli_thrinfo_*() functions). - Renamed thread_comm_t object type to thrcomm_t. - Renamed many of the routines and functions (and macros) for multithreading. We now have the following API namespaces: - bli_thrinfo_*(): functions related to thrinfo_t objects - bli_thrcomm_*(): functions related to thrcomm_t objects. - bli_thread_*(): general-purpose functions, such as initialization, finalization, and computing ranges. (For now, some macros, such as bli_thread_[io]broadcast() and bli_thread_[io]barrier() use the bli_thread_ namespace prefix, even though bli_thrinfo_ may be more appropriate.) - Renamed thread-related macros so that they use a bli_ prefix. - Renamed control tree-related macros so that they use a bli_ prefix (to be consistent with the thread-related macros that were also renamed). - Removed #undef BLIS_SIMD_ALIGN_SIZE from dunnington's bli_kernel.h. This #undef was a temporary fix to some macro defaults which were being applied in the wrong order, which was recently fixed. commit 232530e88ff99f37abcae5b6fb5319a9a375a45f Merge: 4bcabd1b eef37f8b Author: Tyler Michael Smith Date: Wed Jun 1 15:14:10 2016 -0500 Merge commit 'refs/pull/81/head' of https://github.com/flame/blis Conflicts: frame/base/bli_threading_pthreads.c frame/base/bli_threading_pthreads.h commit 4bcabd1bf60688c38cf562459fc5e8be8b831756 Author: Tyler Michael Smith Date: Wed Jun 1 13:27:28 2016 -0500 Use spin locks instead of pthread barriers commit eef37f8b4d81845a6ba4bf25586d32b50c3e8a68 Author: Jeff Hammond Date: Sun May 29 22:28:13 2016 -0700 use GCC intrinsic instead of pthread_mutex for atomic increment and fetch commit 9dcd6f05c4c3ff2ce7cd87a9951a96ebef22681e Author: Field G. Van Zee Date: Tue May 24 13:15:32 2016 -0500 Implemented developer-configurable malloc()/free(). Details: - Replaced all instances of bli_malloc() and bli_free() with one of: - bli_malloc_pool()/bli_free_pool() - bli_malloc_user()/bli_free_user() - bli_malloc_intl()/bli_free_intl() each of which can be configured to call malloc()/free() substitutes, so long as the substitute functions have the same function type signatures as malloc() and free() defined by C's stdlib.h. The _pool() function is called when allocating blocks for the memory pools (used for packing buffers, primarily), the _user() function is called when obj_t's are created (via bli_obj_create() and friends), and the _intl() function is called for internal use by BLIS, such as when creating control tree nodes or temporary buffers for manipulating internal data structures. Substitutes for any of the three types of bli_malloc() may be specified by #defining the following pairs of cpp macros in bli_kernel.h: - BLIS_MALLOC_POOL/BLIS_FREE_POOL - BLIS_MALLOC_USER/BLIS_FREE_USER - BLIS_MALLOC_INTL/BLIS_FREE_INTL to be the name of the substitute functions. (Obviously, the object code that contains these functions must be provided at link-time.) These macros default to malloc() and free(). Subsitute functions are also automatically prototyped by BLIS (in bli_malloc_prototypes.h). - Removed definitions for bli_malloc() and bli_free(). - Note that bli_malloc_pool() and bli_malloc_user() are now defined in terms of a new function, bli_malloc_align(), which aligns memory to an arbitrary (power of two) alignment boundary, but does so manually, whereas before alignment was performed behind the scenes by posix_memalign(). Currently, bli_malloc_intl() is defined in terms of bli_malloc_noalign(), which serves as a simple wrapper to the designated function that is passed in (e.g. BLIS_MALLOC_INTL). Similarly, there are bli_free_align() and bli_free_noalign(), which are used in concert with their bli_malloc_*() counterparts. commit 9dd440109a9d964f5cd286e9f83c487ad703e1e4 Author: Jeff Hammond Date: Sat May 21 15:21:58 2016 -0700 fix 404 link to BuildSystem Google Code is dead. Long live GitHub! commit d309f20b7376a68efa3b864ad790c2021c071655 Author: Field G. Van Zee Date: Wed May 18 15:13:53 2016 -0500 Added alignment switch to testsuite. Details: - Added a new input parameter to input.general that globally toggles whether testsuite tests are performed on objects whose buffers and leading dimensions have been aligned, and changed the implementation of libblis_test_mobj_create() to employ alignment (or not) regardless of whether row, column, or general storage is being tested. - Updated configure script's "--help" text to indicate default behavior for internal integer type size and BLAS/CBLAS integer type size options. commit 32db0adc218ea4ae370164dbe8d23b41cd3526d3 Author: Field G. Van Zee Date: Tue May 17 15:20:16 2016 -0500 Generate prototypes for user-defined packm kernels. Details: - Created template prototypes for packm kernels (in bli_l1m_ker.h), and then redefined reference packm kernels' prototyping headers in terms of this template, as is already done for level-1v, -1f, and -3 kernels. - Automatically generate prototypes for user-defined packm kernels in bli_kernel_prototypes.h (using the new template prototypes in bli_l1m_ker.h). - Defined packm kernel function types in bli_l1m_ft.h, including for packm kernels specific to induced methods, which are now used in bli_packm_cxk.c and friends rather than using a locally-defined function type. - In bli_packm_cxk.c, extended function pointer for packm kernels array from out to index 31 (from previous maximum of 17). This allows us to store the unrolled 30xk kernel in the array for use (on knc, for example). Note: This should have been done a long time ago. commit e3bd5ca64ae7c190ba689396c0de687b829a11fe Author: Devin Matthews Date: Thu May 12 20:54:13 2016 -0500 Fix SIMD definitions in KNL config, and a couple of fixes to C update. commit 4fe02e3d497995d94d34d3fcf5af895084cfc8b9 Author: Devin Matthews Date: Thu May 12 20:53:58 2016 -0500 Move bli_kernel.h before bli_threading.h in order of inclusion in blis.h. commit 4bcf1b35abea3f3dfc8f2fe462dcf155cf199e55 Author: Field G. Van Zee Date: Wed May 11 16:09:49 2016 -0500 Fixed bli_get_range_*() bugs in trsm variants. Details: - Fixed incorrect calls to bli_get_range_*() from within trsm blocked variants 1f, 2b, and 2f. The bug somehow went undetected since the big commit (537a1f4), and, strangely, did not manifest via the BLIS testsuite. The bug finally came to our attention when running thei libflame test suite while linking to BLIS. Thanks to Kiran Varaganti for submitting the initial report that led to this bug. commit 9cfa33023f123a6c17e987f72fba174ce073f0b6 Author: Field G. Van Zee Date: Wed May 11 16:02:30 2016 -0500 Minor updates to bli_f2c.h. Details: - Added #undef guards to certain #define statements in bli_f2c.h, and renamed the file guard to BLIS_F2C_H. This helps when #including "blis.h" from an application or library that already #includes an "f2c.h" header. commit a09a2e23eacf5328858c8318bb637c5ff3b71d08 Merge: 4dcd37eb 7c604e1c Author: Tyler Michael Smith Date: Wed May 11 10:47:11 2016 -0500 Merge pull request #76 from devinamatthews/move_simd_defs Move default SIMD-related definitions to bli_kernel_macro_defs.h commit 4dcd37eb1b12a6e08cc13df7b61391ef8363f5d8 Author: Tyler Smith Date: Tue May 10 16:28:59 2016 -0500 fixing knc simd align size commit 619dee0daec3474b4e5a55df90a61aabcae194f2 Merge: b790b3d9 7c604e1c Author: Devin Matthews Date: Tue May 10 12:13:24 2016 -0500 Merge branch 'move_simd_defs' into knl commit 7c604e1cbc1609b6e12d3ee973c08b7af5035be4 Author: Devin Matthews Date: Tue May 10 12:11:55 2016 -0500 Move default SIMD-related definitions to bli_kernel_macro_defs.h. Otherwise, configurations which customize these fail as these are now defined in bli_kernel.h. commit b790b3d9e1820f3b691676de48c291cae083452d Merge: 4f8c05c9 a7be2d28 Author: Devin Matthews Date: Tue May 10 11:49:47 2016 -0500 Merge branch 'master' into knl commit a7be2d28e8930b154d0da1d6929b54a96e210af6 Merge: 97b512ef 4b1e55ed Author: Field G. Van Zee Date: Tue May 10 11:48:51 2016 -0500 Merge pull request #74 from devinamatthews/fix_common_symbols Default-initialize all extern global variables to avoid generating common symbols. commit 4b1e55edbfe0e1cb2e7b9428424903497cb7a841 Author: Devin Matthews Date: Tue May 10 10:08:47 2016 -0500 Default-initialize all extern global variables to avoid generating common symbols. Fixes #73. commit 97b512ef62c7e25c97ed5e9eca81cd7015b2ac91 Author: Field G. Van Zee Date: Fri May 6 10:24:30 2016 -0500 Include headers from cblas.h to pull in f77_int. Details: - Added #include statements for certain key BLIS headers so that the definition of f77_int is pulled in when a user compiles application code with only #include "cblas.h" (and no other BLIS header). This is necessary since f77_int is now used within the cblas API. commit c3a4d39d03665135f1616588b5ef7c3e9ef5688d Author: Field G. Van Zee Date: Wed May 4 17:22:56 2016 -0500 Updates to haswell gemm micro-kernels. Details: - Added two new sets of [sd]gemm micro-kernels for haswell architectures, one that is 4x24/4x12 (s and d) and one that is 6x16/6x8. - Changed the haswell configuration to use the 6x16/6x8 micro-kernels by default. - Updated various Makefiles, in test, test/3m4m, and testsuite. commit 0b01d355ae861754ae2da6c9a545474af010f02e Author: Field G. Van Zee Date: Wed Apr 27 15:21:10 2016 -0500 Miscellaneous cleanups, fixes to recent commits. Details: - Fixed a typo in bli_l1f_ref.h, introduced into bbb8569, that only manifested when non-reference level-1f kernels were used. - Added an #undef BLIS_SIMD_ALIGN_SIZE to bli_kernel.h of dunnington configuration to prevent a compile-time warning until I can figure out the proper permanent fix. - Moved frame/1f/kernels/bli_dotxaxpyf_ref_var1.c out of the compilation path (into 'other' directory). _ref_var2 is used by default, which is the variant that is built on axpyf and dotxf instead of dotaxpyv. - Removed section of frame/include/bli_config_macro_defs.h pertaining to mixed datatype support. commit ed7326c836f427e2f8420b015220ce293207b10c Author: Field G. Van Zee Date: Wed Apr 27 14:57:40 2016 -0500 Added 'restrict' to l1v/l1f code in 'kernels' dir. Details: - Added 'restrict' keyword to existing kernel definitions in 'kernels' directory. These changes were meant for inclusion in bbb8569. commit bbb8569b2a08c3bcd631d5a05eb389d01d94ac07 Author: Field G. Van Zee Date: Wed Apr 27 14:13:46 2016 -0500 Use 'restrict' in all kernel APIs; wspace changes. Details: - Updated level-1v, level-1f kernel function types (bli_l1?_ft.h) and generic kernel prototypes (bli_l1?_ker.h) to use 'restrict' for all numerical operand pointers (ie: all pointers except the cntx_t). - Updated level-1f reference kernel definitions to use 'restrict' for all numerical operand pointers. (Level-1v reference kernel definitions were already updated in bdbda6e.) - Rewrote the level-1v and level-1f reference kernel prototypes in bli_l1v_ref.h and bli_l1f_ref.h, respectively, to simply #include bli_l1v_ker.h and bli_l1f_ker.h with redefined function base names (as was already being done for the level-3 micro-kernel prototypes in bli_l3_ref.h), rather than duplicate the signatures from the _ker.h files. - Added definitions to frame/include/bli_kernel_prototypes.h for axpbyv and xpbyv, which were probably meant for inclusion in bdbda6e. - Converted a number of instances of four spaces, as introduced in bdbda6e, to tabs. commit 4ea419c72c789825e1f93a1eee88219bbf873930 Merge: f1e9be2a bdbda6e6 Author: Field G. Van Zee Date: Tue Apr 26 12:50:45 2016 -0500 Merge pull request #70 from devinamatthews/daxpby Give the level1v operations some love commit bdbda6e6acc682ab1b6ca680edebd09ae12a832c Author: Devin Matthews Date: Mon Apr 25 11:05:57 2016 -0500 Give the level1v operations some love: - Add missing axpby and xpby operations (plus test cases). - Add special case for scal2v with alpha=1. - Add restrict qualifiers. - Add special-case algorithms for incx=incy=1. commit f1e9be2aba1a057eedb947bbae96848597777408 Author: Field G. Van Zee Date: Fri Apr 22 15:34:02 2016 -0500 Minor tweak to test/Makefile. Details: - Just committing a minor change to test/Makefile that has been lingering in my local working copy for longer than I can remember. commit aa0bceec277938328dabeb744680623f24fb0b61 Merge: 4136553f e2784b4c Author: Field G. Van Zee Date: Fri Apr 22 12:01:31 2016 -0500 Merge branch 'master' of github.com:flame/blis commit 4136553f0d0661a668dfdb9edcd7ce1c5773dde7 Author: Field G. Van Zee Date: Fri Apr 22 11:53:53 2016 -0500 Clear level-3 cntx_t's via memset() before use. Details: - In all level-3 operations' _cntx_init() functions, replaced calls to bli_cntx_obj_init() with calls to bli_cntx_obj_clear(), and in all level-3 operations' _cntx_finalize() functions, removed calls to bli_cntx_obj_finalize(), leaving those function definitions empty. - Changed the definition of bli_cntx_obj_clear() so that the clearing occurs via a single call to memset(). commit 4f8c05c9e2ef4cbb82b35a3ebf1f0a0ac665830e Author: Devin Matthews Date: Thu Apr 21 10:00:59 2016 -0500 Rearrange KNL dgemm kernel again to streamline usage of ymm register. sgemm and dgemm now both working with Intel SDE. commit e2784b4c921f706e756df3e146e20a4cb63f53e3 Merge: dd0ab1d9 a9b6c3ab Author: Field G. Van Zee Date: Wed Apr 20 18:34:09 2016 -0500 Merge pull request #67 from devinamatthews/cblas-f77-int Change CBLAS integer type to f77_int commit a9b6c3abda6222a8b240361643932e83cf726c4f Merge: e4c54c81 dd0ab1d9 Author: Devin Matthews Date: Wed Apr 20 16:00:10 2016 -0500 Merge remote-tracking branch 'origin/master' into cblas-f77-int # Conflicts: # config/haswell/bli_config.h commit e4c54c81463c2a19c9bb6b1f0f1be3fa9d018a45 Author: Devin Matthews Date: Wed Apr 20 15:56:46 2016 -0500 Change integer type in CBLAS function signatures to f77_int, and add proper const-correctness to BLAS layer. commit dd0ab1d93f33abca6af9edd7b8e52da62dcfa5b1 Author: Field G. Van Zee Date: Wed Apr 20 14:38:23 2016 -0500 Converted some bli_cntx query functions to macros. Details: - Commented out several datatype-aware query functions (those ending in _dt) from bli_cntx.c, as well as their prototypes in bli_cntx.h, and added equivalent cpp query macros to bli_cntx.h. - Added 'bli_config.h' to .gitignore. commit 7193230f7d35edbd1d2f77842a613971f1603463 Author: Devin Matthews Date: Wed Apr 20 09:37:30 2016 -0500 Work around missing VPMULLQ on KNL. commit a30ccbc4c6a6e6460e78af6b5c530ee0d06f98fb Merge: eb2f18e4 0e1a9821 Author: Field G. Van Zee Date: Tue Apr 19 15:04:33 2016 -0500 Merge pull request #66 from devinamatthews/blas-configure Add configure options and generate bli_config.h automatically. commit bd44cf13e886069bc66c10ac0db178be96629a0d Author: Devin Matthews Date: Tue Apr 19 13:43:04 2016 -0500 Fix copy-paste errors in KNL kernels. commit eb2f18e4844d985715df20798f50f9cc12e3b5ad Author: Field G. Van Zee Date: Tue Apr 19 12:50:32 2016 -0500 More compile-time fixes to bgq gemm ukernel code. commit 0e1a9821d860f6c1d818baf4c48d21a23726c132 Author: Devin Matthews Date: Tue Apr 19 11:44:37 2016 -0500 Add configure options and generate bli_config.h automatically. Options to configure have been added for: - Setting the internal BLIS and BLAS/CBLAS integer sizes. - Enabling and disabling the BLAS and CBLAS layers. Additionally, configure options which require defining macros (the above plus the threading model), write their macros to the automatically-generated bli_config.h file in the top-level build directory. The old bli_config.h files in the config dirs were removed, and any kernel-related macros (SIMD size and alignment etc.) were moved to bli_kernel.h. The Makefiles were also modified to find the new bli_config.h file. Lastly, support for OMP in clang has been added (closes #56). commit a11eec05928ddc5c43fa5dbcd35f2edd24ff35a1 Author: Devin Matthews Date: Mon Apr 18 13:13:36 2016 -0500 Add sgemm ukernels for KNL. vpmullq is not implemented on KNL -- needs workaround. commit ff84469a4575f1ef8a0010046fde52240a312cae Author: Field G. Van Zee Date: Mon Apr 18 12:29:09 2016 -0500 Applied various compilation fixes to bgq kernels. commit c38e0dab05b2dc36672eab96e1248fb7fb2d785b Merge: bd5e2296 cbcd0b73 Author: Devin Matthews Date: Mon Apr 18 10:21:35 2016 -0500 Merge remote-tracking branch 'origin/master' into knl commit bd5e2296e98e042c31f1e8ece2c1ca8e4bdc2d4c Merge: 4745def0 49f85177 Author: Devin Matthews Date: Mon Apr 18 10:15:22 2016 -0500 Merge remote-tracking branch 'origin/knl' into knl commit 4745def0c87377ae83ad73ac514d7de08a96b2ac Author: Devin Matthews Date: Mon Apr 18 10:15:05 2016 -0500 Add 64-bit offset vector so we can use vgatherqpd. commit 49f85177f886f38889b60503a4e12fa7f04be1fd Author: Devin Matthews Date: Mon Apr 18 10:14:11 2016 -0500 KNL ukernel compiles with gcc. commit cbcd0b739dc54bd14fbb46aeda267c26725cd70f Author: Tyler Michael Smith Date: Mon Apr 18 03:12:57 2016 -0500 Changing ifdef for OSX pthread barriers commit 58b2c3cf040134d1be913c585a3c6905629116c0 Author: Devin Matthews Date: Sat Apr 16 16:12:24 2016 -0500 Rewrite of KNL kernel in GNU extended asm syntax. commit dd62080cea78f3a23616200d6640e52c102b2bb9 Author: Field G. Van Zee Date: Fri Apr 15 11:15:41 2016 -0500 Compile-time fix to bgq l1f kernels. Details: - Fixed an old reference to bli_daxpyf_fusefac, which no longer exists, by replacing it with the axpyf fusing factor (8), and cleaned up the relevant section of config/bgq/bli_kernel.h. - Removed most of the details of the level-3 kernels from the template kernel code in config/template/kernels/3 and replaced it with a reference to the relevant kernel wiki maintained on the BLIS github website. commit d5a915dd8d7a6ead42a68772e4420eb3647e6f1a Merge: 4320b725 41694675 Author: Field G. Van Zee Date: Thu Apr 14 12:56:36 2016 -0500 Merge branch 'master' of github.com:flame/blis commit 4320b725a1f8fd34101470b6cf52ad504a79c517 Author: Field G. Van Zee Date: Thu Apr 14 12:51:29 2016 -0500 Use kernel CFLAGS on "ukernels" directories. Details: - Updated the top-level Makefile so that the CFLAGS variable designated for kernel source code is applied not only to source code in directories named "kernels" but source code in any directory that contains the substring "kernels", such as "ukernels". - Formally disabled some code in gen-make-frag.sh script that was already effectively disabled. The code was related to handling "noopt" and "kernel" directories, which is now handled independently within the top-level Makefile without needing to place these source files into a spearate makefile variable. commit 41694675e4cb56e2e0323c7a7db48e0819606a31 Author: Tyler Smith Date: Wed Apr 13 15:51:08 2016 -0500 pthreads bugfixes Getting pthreads to work on my Mac Implemented a pthread barrier when _POSIX_BARRIER isn't defined Now spawn n-1 threads instead of n threads so that master thread isn't just spinning the whole time Add -lpthread instead of -pthread to LDFLAGS (for clang) commit f756dbfa0d542cbc497724981520c83abf049c4b Author: Field G. Van Zee Date: Wed Apr 13 11:25:33 2016 -0500 Removed stale #include from bgq configuration. Details: - Removed an old #include statement ("bli_gemm_8x8.h") from the bli_kernel.h file in the bgq configuration. It turns out this file was no longer needed even prior to 537a1f4. commit 0bd4169ea75f690714e7d2912229932a75d8a7e2 Author: Field G. Van Zee Date: Mon Apr 11 18:08:32 2016 -0500 Fixed context-broken dunnington/penryn kernels. Details: - Added missing context parameters to several instances where simpler kernels, or reference kernels, are called instead of executing the main body code contained in the kernel function in question. - Renamed axpyv and dotv kernel files to use "opt" instead of "int" substring, for consistency with level-1f kernels. commit 7912af5db45b7372d19a9a3dfeb82df302a05628 Author: Field G. Van Zee Date: Mon Apr 11 17:32:13 2016 -0500 CHANGELOG update (0.2.0) commit 898614a555ea0aa7de4ca07bb3cb8f5708b6a002 (tag: 0.2.0) Author: Field G. Van Zee Date: Mon Apr 11 17:32:09 2016 -0500 Version file update (0.2.0) commit 537a1f4f85ce1aa008901857cb3182e6b4546d7f Author: Field G. Van Zee Date: Mon Apr 11 17:21:28 2016 -0500 Implemented runtime contexts and reorganized code. Details: - Retrofitted a new data structure, known as a context, into virtually all internal APIs for computational operations in BLIS. The structure is now present within the type-aware APIs, as well as many supporting utility functions that require information stored in the context. User- level object APIs were unaffected and continue to be "context-free," however, these APIs were duplicated/mirrored so that "context-aware" APIs now also exist, differentiated with an "_ex" suffix (for "expert"). These new context-aware object APIs (along with the lower-level, type- aware, BLAS-like APIs) contain the the address of a context as a last parameter, after all other operands. Contexts, or specifically, cntx_t object pointers, are passed all the way down the function stack into the kernels and allow the code at any level to query information about the runtime, such as kernel addresses and blocksizes, in a thread- friendly manner--that is, one that allows thread-safety, even if the original source of the information stored in the context changes at run-time; see next bullet for more on this "original source" of info). (Special thanks go to Lee Killough for suggesting the use of this kind of data structure in discussions that transpired during the early planning stages of BLIS, and also for suggesting such a perfectly appropriate name.) - Added a new API, in frame/base/bli_gks.c, to define a "global kernel structure" (gks). This data structure and API will allow the caller to initialize a context with the kernel addresses, blocksizes, and other information associated with the currently active kernel configuration. The currently active kernel configuration within the gks cannot be changed (for now), and is initialized with the traditional cpp macros that define kernel function names, blocksizes, and the like. However, in the future, the gks API will be expanded to allow runtime management of kernels and runtime parameters. The most obvious application of this new infrastructure is the runtime detection of hardware (and the implied selection of appropriate kernels). With contexts in place, kernels may even be "hot swapped" at runtime within the gks. Once execution enters a level-3 _front() function, the memory allocator will be reinitialized on-the-fly, if necessary, to accommodate the new kernels' blocksizes. If another application thread is executing with another (previously loaded) kernel, it will finish in a deterministic fashion because its kernel information was loaded into its context before computation began, and also because the blocks it checked out from the internal memory pools will be unaffected by the newer threads' reinitialization of the allocator. - Reorganized and streamlined the 'ind' directory, which contains much of the code enabling use of induced methods for complex domain matrix multiplication; deprecated bli_bsv_query.c and bli_ukr_query.c, as those APIs' functionality is now mostly subsumed within the global kernel structure. - Updated bli_pool.c to define a new function, bli_pool_reinit_if(), that will reinitialize a memory pool if the necessary pool block size has increased. - Updated bli_mem.c to use bli_pool_reinit_if() instead of bli_pool_reinit() in the definition of bli_mem_pool_init(), and placed usage of contexts where appropriate to communicate cache and register blocksizes to bli_mem_compute_pool_block_sizes(). - Simplified control trees now that much of the information resides in the context and/or the global kernel structure: - Removed blocksize object pointers (blksz_t*) fields from all control tree node definitions and replaced them with blocksize id (bszid_t) values instead, which may be passed into a context query routine in order to extract the corresponding blocksize from the given context. - Removed micro-kernel function pointers (func_t*) fields from all control tree node definitions. Now, any code that needs these function pointers can query them from the local context, as identified by a level-3 micro-kernel id (l3ukr_t), level-1f kernel id, (l1fkr_t), or level-1v kernel id (l1vkr_t). - Removed blksz_t object creation and initialization, as well as kernel function object creation and initialization, from all operation- specific control tree initialization files (bli_*_cntl.c), since this information will now live in the gks and, secondarily, in the context. - Removed blocksize multiples from blksz_t objects. Now, we track blocksize multiples for each blocksize id (bszid_t) in the context object. - Removed the bool_t's that were required when a func_t was initialized. These bools are meant to allow one to track the micro-kernel's storage preferences (by rows or columns). This preference is now tracked separately within the gks and contexts. - Merged and reorganized many separate-but-related functions into single files. This reorganization affects frame/0, 1, 1d, 1m, 1f, 2, 3, and util directories, but has the most obvious effect of allowing BLIS to compile noticeably faster. - Reorganized execution paths for level-1v, -1d, -1m, and -2 operations in an attempt to reduce overhead for memory-bound operations. This includes removal of default use of object-based variants for level-2 operations. Now, by default, level-2 operations will directly call a low-level (non-object based) loop over a level-1v or -1f kernel. - Converted many common query functions in blk_blksz.c (renamed from bli_blocksize.c) and bli_func.c into cpp macros, now defined in their respective header files. - Defined bli_mbool.c API to create and query "multi-bools", or heterogeneous bool_t's (one for each floating-point datatype), in the same spirit as blksz_t and func_t. - Introduced two key parameters of the hardware: BLIS_SIMD_NUM_REGISTERS and BLIS_SIMD_SIZE. These values are needed in order to compute a third new parameter, which may be set indirectly via the aforementioned macros or directly: BLIS_STACK_BUF_MAX_SIZE. This value is used to statically allocate memory in macro-kernels and the induced methods' virtual kernels to be used as temporary space to hold a single micro-tile. These values are now output by the testsuite. The default value of BLIS_STACK_BUF_MAX_SIZE is computed as "2 * BLIS_SIMD_NUM_REGISTERS * BLIS_SIMD_SIZE". - Cleaned up top-level 'kernels' directory (for example, renaming the embarrassingly misleading "avx" and "avx2" directories to "sandybridge" and "haswell," respectively, and gave more consistent and meaningful names to many kernel files (as well as updating their interfaces to conform to the new context-aware kernel APIs). - Updated the testsuite to query blocksizes from a locally-initialized context for test modules that need those values: axpyf, dotxf, dotxaxpyf, gemm_ukr, gemmtrsm_ukr, and trsm_ukr. - Reformatted many function signatures into a standard format that will more easily facilitate future API-wide changes. - Updated many "mxn" level-0 macros (ie: those used to inline double loops for level-1m-like operations on small matrices) in frame/include/level0 to use more obscure local variable names in an effort to avoid variable shaddowing. (Thanks to Devin Matthews for pointing these gcc warnings, which are only output using -Wshadow.) - Added a conj argument to setm, so that its interface now mirrors that of scalm. The semantic meaning of the conj argument is to optionally allow implicit conjugation of the scalar prior to being populated into the object. - Deprecated all type-aware mixed domain and mixed precision APIs. Note that this does not preclude supporting mixed types via the object APIs, where it produces absolutely zero API code bloat. commit dd856c2cb75a2221a503a73dde27790c34b91570 Author: Devin Matthews Date: Mon Apr 11 10:39:18 2016 -0500 Translated MIC kernel to KNL and cleaned up a bit. Only real change is lack of swizzle modifiers for FMA instructions (used bcast from memory instead). commit 7f27431d3fffdda99c282ec412731d0a90cb32a7 Author: Devin Matthews Date: Fri Apr 8 10:04:39 2016 -0500 Copy mic kernel to knl for transliteration. commit f8f02f0334ac020021e15a415bcd33aeea01deb4 Merge: 32c92d94 d1f8e5d9 Author: Devin Matthews Date: Wed Apr 6 11:37:05 2016 -0500 Merge branch 'master' into const_correctness commit 32c92d945c55708da0eb63be1771f8c5430e3910 Merge: 62914ccb 20af937b Author: Devin Matthews Date: Wed Apr 6 11:36:02 2016 -0500 Merge branch 'master' into const_correctness commit d1f8e5d9b2ecd054ed103f4d642d748db2d4f173 Merge: 20af937b c11d28ee Author: Field G. Van Zee Date: Tue Apr 5 12:21:27 2016 -0500 Merge pull request #60 from esauvage/master sgemm µkernel for bulldozer : bug correction for k%4 != 0 commit c11d28eed89d65494bc4019f04d046520866c0ff Author: Etienne Sauvage Date: Sat Apr 2 21:15:48 2016 +0200 cgemm µkernel for bulldozer : bug correction for k%4 != 0 commit 20af937b57f82bb3acb09418d5c0206e1b24f2c7 Merge: 36c3abb0 fc61a114 Author: Field G. Van Zee Date: Thu Mar 31 14:37:30 2016 -0500 Merge pull request #59 from devinamatthews/fix_testsuite_makefile Fix testsuite makefile commit fc61a1143edeba4946d4b9915f1775bb08e643fc Author: Devin Matthews Date: Thu Mar 31 10:53:01 2016 -0500 Fix formatting in configure. commit 26379b14de630e3a6c6eef5dfe87ff001558a8a6 Author: Devin Matthews Date: Thu Mar 31 10:45:48 2016 -0500 Adjust paths in common.mk to support building from testsuite dir. commit 36c3abb05fecb02d4a9ab13b2b69d133adf34583 Merge: 64b41fa5 917ce754 Author: Field G. Van Zee Date: Thu Mar 31 10:26:17 2016 -0500 Merge pull request #58 from esauvage/master cgemm & zgemm micro-kernels for FMA4 instruction set (bulldozer confi… commit 356d854fc9e34642cc46e0e02a8ceb56114878af Author: Devin Matthews Date: Wed Mar 30 16:33:15 2016 -0500 Make symlink to common.mk in build directory. commit edbb8470044f82ef959583ee09613a5a985292b5 Author: Devin Matthews Date: Wed Mar 30 16:27:11 2016 -0500 Refactor out some definitions which moved from make_defs.mk to Makefile for use in testsuite Makefile. commit 917ce75482a543fef46553efff6c246939761e59 Author: Etienne Sauvage Date: Wed Mar 30 22:03:09 2016 +0200 cgemm & zgemm micro-kernels for FMA4 instruction set (bulldozer configuration), based on x86_64/avx micro-kernel commit 62914ccbcdb3c594f065dcfa65bd7e7b95c79283 Merge: bbf704bf 64b41fa5 Author: Devin Matthews Date: Tue Mar 29 15:24:25 2016 -0500 Merge branch 'master' into const_correctness commit 64b41fa554dff44b2f9ad48901b67c63836407a8 Merge: 1b09e343 0171ad58 Author: Field G. Van Zee Date: Tue Mar 29 15:19:41 2016 -0500 Merge pull request #54 from devinamatthews/more_config_opts More config opts commit 1b09e343dfe5b48b4842e2cb96f41c8cc249bad0 Author: Field G. Van Zee Date: Tue Mar 29 12:55:28 2016 -0500 Updated gcc version from 4.8 to 4.9 in .travis.yml. commit 0171ad58997b3a5a9b76301511dbe0751fffc940 Author: Devin Matthews Date: Mon Mar 28 13:55:06 2016 -0500 Add icc and clang support for Intel architectures, fixes #47. 2bd036f fixes #49 BTW. commit 3090fff64cc87ff2519a09f38e6b8699cf3cba11 Merge: 8624e365 4ca5d5b1 Author: Field G. Van Zee Date: Mon Mar 28 12:36:25 2016 -0500 Merge pull request #44 from esauvage/master sgemm micro-kernel for FMA4 instruction set commit e6e566426ac3ded7ef87cd8ff9be98accfdc4acc Merge: 469429ec 8624e365 Author: Devin Matthews Date: Sat Mar 26 14:10:15 2016 -0500 Merge branch 'master' into more_config_opts commit 8624e36543160739d954c4dbcc5a5594458f3a12 Merge: a315833f 2bd036f1 Author: Field G. Van Zee Date: Sat Mar 26 13:56:28 2016 -0500 Merge pull request #50 from devinamatthews/fix_noopt_avx Fix configuration issue where instruction set flags are not specified for debug builds. commit 469429ec34e5b1a172ce35596f9c7afdaacac131 Author: Devin Matthews Date: Fri Mar 25 20:45:41 2016 -0500 Fix LD_FLAGS -> LDFLAGS. commit 8442d65c9ead0376fc5f2dfad62fd4862ab9b2b3 Author: Devin Matthews Date: Fri Mar 25 20:06:48 2016 -0500 Replace -march=native with specific architecture flags to support cross-compiling, and add icc support for Intel architectures. commit 76099f20be1b49ac960f7e3c5a8296bbf4e1782d Author: Devin Matthews Date: Fri Mar 25 17:22:58 2016 -0500 Add threading option to configure. commit ad43eab4c7899d56d8d7caa6e2d92bc0581ea5a5 Merge: 9452bdb3 2bd036f1 Author: Devin Matthews Date: Fri Mar 25 15:00:02 2016 -0500 Merge branch 'fix_noopt_avx' into more_config_opts commit 9452bdb3afbf2d7f898134a091d7790817e7be9c Author: Devin Matthews Date: Fri Mar 25 14:59:50 2016 -0500 Add options for verbose make output and static/shared linking to configure. commit 2bd036f1f9ce1ee0864365557f66d9415dd42de3 Author: Devin Matthews Date: Fri Mar 25 12:16:49 2016 -0500 Fix configuration issue where instruction set flags are not specified for debug builds. commit bbf704bf7501411964a63a68f1af541f612cf92d Author: Devin Matthews Date: Fri Mar 25 09:55:35 2016 -0500 Add missing const to bli_read_nway_from_env. commit a315833f067944fb0bc14cf60f0c7dcb5dc897b6 Merge: 1d1a426d af92773f Author: Field G. Van Zee Date: Thu Mar 24 12:30:21 2016 -0500 Merge pull request #48 from figual/master Updated and improved ARMv8 micro-kernels. commit af92773f4f85a2441fe0c6e3a52c31b07253d08e Author: figual Date: Wed Mar 23 22:07:02 2016 +0100 Updated and improved ARMv8 micro-kernels. commit a4d7729776d17d9bdf2341eacd70b9770b9ba8d2 Author: Devin Matthews Date: Mon Mar 21 09:55:21 2016 -0500 Set default value for debug_type variable. commit 0e2447fa55d8c5fa2b1fc4150073512495c5f9eb Author: Devin Matthews Date: Thu Mar 17 16:32:05 2016 -0500 Add const correctness to auxinfo_t struct (microkernels need update theoretically). commit 1d1a426d18ec03754021456862a1f4d1dfec1fbf Merge: 5a978fff d226dfa0 Author: Field G. Van Zee Date: Mon Mar 7 15:17:53 2016 -0600 Merge pull request #46 from devinamatthews/new-config-opts Add several changes to the build system. commit d226dfa05190eb477b33563b1edccf8603973336 Author: Devin Matthews Date: Sat Mar 5 16:18:14 2016 -0600 Add several changes to the build system. 1) Add -- options. 2) Add -d/--enable-debug option to enable debugging symbols with and without optimization. 3) Allow user to specify CC at configure time, and determine vendor (gcc/icc/etc.). For now configurations enforce a particular vendor. 4) Add make V=[0,1] option to control build verbosity. commit 5a978fffdb8f09a81c89541d541d4a6830cd70a4 Merge: adb2b4e0 63e26423 Author: Field G. Van Zee Date: Fri Mar 4 17:26:58 2016 -0600 Merge pull request #45 from devinamatthews/high_prec_timers Use clock_gettime(CLOCK_MONOTONIC) and mach_absolute_time instead of gettimeofday commit 63e264239053b913164a849dd8a45829087eaddc Author: Devin Matthews Date: Fri Mar 4 13:17:50 2016 -0600 Make sure that -lrt is linked on Linux. commit 44fddd48dc1708a956803d1948f04429ec0d8700 Author: Devin Matthews Date: Fri Mar 4 12:36:38 2016 -0600 Add missing \. commit 7cabd2131f953de23e7015d760b0ddfda51b1251 Author: Devin Matthews Date: Thu Mar 3 11:43:07 2016 -0600 Use clock_gettime(CLOCK_MONOTONIC) and mach_absolute_time instead of gettimeofday. commit adb2b4e096c78e8b2f85fd372cf0d5eb04af5be8 Author: Tyler Smith Date: Wed Mar 2 14:48:12 2016 -0600 Fixing guard for non implemented partitioning through packed matrices commit 4ca5d5b1fd6f2e4a8b2e139c5405475239581e51 Author: Etienne Sauvage Date: Tue Mar 1 21:33:01 2016 +0100 sgemm micro-kernel for FMA4 instruction set (bulldozer configuration), based on x86_64/avx micro-kernel commit 627d59b5ba06866b26f46e4434a0435b600925e3 Author: Etienne Sauvage Date: Mon Feb 29 21:53:12 2016 +0100 symbolic link for bulldozer configuration to kernels commit 2dc5c0ae038ed175fab85751803ada05734d1ba1 Merge: f2809fc5 3d0fae81 Author: Field G. Van Zee Date: Mon Feb 29 12:22:51 2016 -0600 Merge pull request #40 from tkelman/bulldozer-symlink Add symlink from config/bulldozer/kernels to kernels/x86_64/bulldozer commit f2809fc5f74466c755da6a5b4632853e634060b5 Merge: f86b94f2 8624a33c Author: Field G. Van Zee Date: Sat Feb 27 13:06:03 2016 -0600 Merge pull request #39 from devinamatthews/fix_f2c_conflicts Devin's f2c type namespace update. Details: - Added "bla_" prefix to f2c type names to prevent conflicts with external user code. - Removed most of the body of bli_f2c.h, which was unused. commit 3d0fae810d942085d8f2d389820b4e0027577db8 Author: Tony Kelman Date: Thu Feb 25 23:24:03 2016 -0800 Add symlink from config/bulldozer/kernels to kernels/x86_64/bulldozer to fix linking issue mentioned in #37 and https://groups.google.com/forum/#!topic/blis-devel/iypwljcaeEI commit 8624a33ccc12dff6f6c4f92992ca5636af1576a6 Author: Devin Matthews Date: Thu Feb 25 13:51:26 2016 -0600 Fix remaining f2c conflicts. commit 372eef0b6c0a535bf88d4b46b72f61266e8491ba Author: Devin Matthews Date: Thu Feb 25 12:01:58 2016 -0600 Fixed most conflicts after hack-n-slash ofr bli_f2c.h, cleanup in progress. commit f86b94f206e2e09fa3221cc55c3dc5b05ca4775a Author: Field G. Van Zee Date: Tue Feb 23 18:12:34 2016 -0600 Included missing blas2blis integer def to CBLAS. Details: - Added #include "bli_config_macro_defs" to all cblas_*.c files in compat/cblas/src. This has the effect of defining BLIS_BLAS2BLIS_INT_TYPE_SIZE to the default value if bli_config.h does not define it. Thanks to Tony Kelman for reporting this bug. - In cblas_i?amax.c, changed the type of the variable 'iamax' from 'int' to 'f77_int'. This eliminates a compiler warning and a potential runtime bug and/or crash when the size of an int differs from the size of f77_int (as determined by BLIS_BLAS2BLIS_INT_TYPE_SIZE). commit 0b126de1342c11c65623bcb38e258e21e9244e3d Author: Field G. Van Zee Date: Fri Nov 13 16:29:12 2015 -0600 Consolidated packm_blk_var1 and packm_blk_var2. Details: - Consolidated the two blocked variants for packm into a single implementation (packm_blk_var1) and removed the other variant. - Updated all induced method _cntl_init() functions in frame/cntl/ind/ to use the new blocked variant 1. - Defined two new macros, bli_is_ind_packed() and bli_is_nat_packed(), to detect pack_t schemas for induced methods and native execution, respectively. commit 30e5eb29e060b97752f702d2ea5d101d950f53b2 Author: Field G. Van Zee Date: Fri Nov 13 12:14:19 2015 -0600 Minor changes to treatment of rs, cs in bli_obj.c. Details: - Applied a patch submitted by Devin Matthews that: - implements subtle changes to handling of somewhat unusual cases of row and column strides to accommodate certail tensor cases, which includes adding dimension parameters to _is_col_tilted() and _is_row_tilted() macros, - simplifies how buffers are sized when requested BLIS-allocated objects, - re-consolidates bli_adjust_strides_*() into one function, and - defines 'restrict' keyword as a "nothing" macro for C++ and pre-C99 environments. commit f0a4f41b5acf55b41707ec821c4c5f9076dfbc24 Author: Field G. Van Zee Date: Thu Nov 12 15:22:50 2015 -0600 Fixed unimplemented case in core2 sgemm ukernel. Details: - Implemented the "beta == 0" case for general stride output for the dunnington sgemm micro-kernel. This case had been, up until now, identical to the "beta != 0" case, which does not work when the output matrix has nan's and inf's. It had manifested as nan residuals in the test suite for right-side tests of ctrsm4m1a. Thanks to Devin Matthews for reporting this bug. commit 42810bbfa0b8f006ecc5128d903909ec13ea63f9 Author: Field G. Van Zee Date: Thu Nov 12 12:07:46 2015 -0600 Fixed minor bugs for uncommon obj_create cases. Details: - Separated bli_adjust_strides() into _alloc() and _attach() flavors so that the latter can avoid a test performed by the former, in which the rs and cs are overridden and set to zero if either matrix dimension is zero. Actually, we also disable this overridding behavior, even for the _alloc() case, since keeping the original strides (probably) does not hurt anything. The original code has been kept commented-out, though, in case an unintended consequence is later discovered. - Fixed a typo in an error check for general stride cases where rs == cs. commit 3e6dd11467643fbc2cb45c13cec8dd6024232833 Author: Field G. Van Zee Date: Tue Nov 3 10:30:08 2015 -0600 Minor re-expression in quadratic partitioning code. Details: - Minor change to quadratic equation solution code that avoids recomputation of the sqrt() parameter when the compiler is not smart enough to perform this optimization automatically. commit 0694b722f7e4df00efb32639095a2aca80e67f52 Merge: 3e116f0a 33557ecc Author: Field G. Van Zee Date: Mon Nov 2 17:24:25 2015 -0600 Merge branch 'master' of github.com:flame/blis commit 3e116f0a2953f50b3c068759a775ad7ffae04e49 Author: Field G. Van Zee Date: Mon Nov 2 17:18:23 2015 -0600 Fixed imaginary bug in quadratic partitioning code. Details: - Fixed a bug in the relatively new quadratic partitioning code that, under the right conditions, would perform sqrt() on a negative value. If the solution is imaginary, we discard it and use an alternate partition width that assumes no diagonal intersection. That alternate width is actually already computed, so, the fix was quite simple. Thanks to Devangi Parikh for reporting this bug. commit 33557ecccaf49b2569b7f3d7bcea52c2aab94c68 Author: Jeff Hammond Date: Mon Nov 2 12:18:43 2015 -0800 add Travis CI build status icon to the README commit 4a502fbe77bd0f701108baaa559d9cfb483f88de Author: Field G. Van Zee Date: Mon Nov 2 13:28:34 2015 -0600 Laid groundwork for runtime memory pool resizing. Details: - Changed bli_pool_finalize() so that the freeing begins with the block at top_index instead of block 0. This allows us to use the function for terminal finalization as well as temporary cleanup prior to reinitialization. Also, clear the pool_t struct upon _pool_finalize() in case it is called in the terminal case with some blocks still checked out to threads (in which case the threads will see the new block size as 0 and thus release the block as intended). - Added bli_pool_reinit(), which calls _pool_finalize() followed by _pool_init() with new parameters. - Added bli_mem_reinit(), which is based on bli_pool_reinit(). - Added new wrapper, _mem_compute_pool_block_sizes(), which calls _mem_compute_pool_block_sizes_dt(). - Updated bli_mem_release() so that the pblk_t is freed, via _pool_free_block(), if the block size recorded in the mem_t at the time the pblk_t was acquired is now different from the value in the pool_t. commit 37e55ca39bdbddaec03ad30d43e8ad2b3e549c96 Author: Field G. Van Zee Date: Fri Oct 30 18:25:04 2015 -0500 Fixed obscure 3m1/4m1a bugs in trmm[3] and trsm. Details: - Fixed a family of bugs in the triangular level-3 operations for certain complex implementations (3m1 and 4m1a) that only manifest if one of the register blocksizes (PACKMR/PACKNR, actually) is odd: - Fixed incorrect imaginary stride computation in bli_packm_blk_var2() for the triangular case. - Fixed the incorrect computation of imaginary stride, as stored in the auxinfo_t struct in trmm and trsm macro-kernels. - Fixed incorrect pointer arithmetic in the trsm macro-kernels in the cases where the the register blocksize for the triangular matrix is odd. Introduced a new byte-granular pointer arithmetic macro, bli_ptr_add(), that computes the correct value. - Added cpp macro to bli_macro_defs.h for typeof() operator, defined in terms of __typeof__, which is used by bli_ptr_add() macro. - Disabled the row- vs. column-storage optimization in bli_trmm_front() for singleton problems because the inherent ambiguity of whether a scalar is row-stored or column-stored causes the wrong parameter combination code to be executed (by dumb luck of our checking for row storage first). - Added commented-out debugging lines to 3m1/4m1a and reference micro-kernels, and trsm_ll macro-kernel. commit 46294d80e5a79c598e200e1c8ec2a642ff839971 Merge: d3159c57 a0a7b85a Author: Field G. Van Zee Date: Tue Oct 27 12:41:23 2015 -0500 Merge pull request #35 from figual/master Fixed incomplete code in the double precision ARMv8 microkernel. commit a0a7b85ac3e157af53cff8db0e008f4a3f90372c Author: Francisco Igual Date: Tue Oct 27 08:59:15 2015 +0000 Fixed incomplete code in the double precision ARMv8 microkernel. commit d3159c5740c9ee7f8c0b661003aab6f00646ad6f Merge: b489152e 7e03e45b Author: Field G. Van Zee Date: Wed Oct 21 14:54:00 2015 -0500 Merge branch 'master' of github.com:flame/blis commit b489152e112644ec3b6d19e687231a9607f7694f Author: Field G. Van Zee Date: Wed Oct 21 14:53:17 2015 -0500 Use vzeroall in haswell micro-kernels. commit 7e03e45bfe6c27c4fdbf06b1caa7f49e9a5fef49 Merge: 77ddb0b1 4f88c29f Author: Field G. Van Zee Date: Wed Oct 14 13:26:07 2015 -0500 Merge pull request #33 from xianyi/master Enable Travis CI commit 4f88c29f9e634cbb6fb22d8c88931f0ec78ad7db Author: Zhang Xianyi Date: Wed Oct 14 12:57:50 2015 -0500 Detect Intel Broadwell (using Haswell config). commit 4b0ac1a9984a93f7ad4369b10fca63991107d9f5 Merge: fe3e355c 77ddb0b1 Author: Zhang Xianyi Date: Wed Oct 14 12:51:05 2015 -0500 Merge branch 'upstream_master' commit 77ddb0b1d31ada111dadf392766ba6d9210ed9fb Author: Field G. Van Zee Date: Tue Oct 13 12:53:06 2015 -0500 Removed flop-counting mechanism. Details: - Removed the optional flop-counting feature introduced in commit 7574c994. commit 276da366187460a4c8e6e0910e79cb39ce780bfe Author: Field G. Van Zee Date: Mon Oct 12 11:43:03 2015 -0500 Minor formatting change to README.md. commit d17057446f5404824478e8a6cd08f242ab75544a Author: Field G. Van Zee Date: Mon Oct 12 11:39:49 2015 -0500 Added "Getting Started" section to README.md. Details: - Added section to README.md file containing links to wikis with brief descriptions. commit e7e1f2f7b601b21b50e3cdad8972cb3fe11018d3 Author: Field G. Van Zee Date: Fri Oct 2 16:51:52 2015 -0500 Minor updates to CREDITS, README files. commit 55329906ecd7ce1ab910e4d30a29354a9172e7ea Author: Field G. Van Zee Date: Sat Sep 26 20:47:19 2015 -0500 Minor edits to README.md, testsuite. Details: - Fixed typos in README.md. - Fixed column heading alignment for testsuite when matlab output is enabled. - Minor updates to test/3m4m/runme.sh and test/3m4m/Makefile. commit bbebdb5793a8fd6aaf257012ab0272beaa04a0de Author: Field G. Van Zee Date: Fri Sep 25 14:47:27 2015 -0500 Replaced README with README.md. Details: - Replaced the old (and short) README file with a much more comprehensive version written in github-flavored markdown. The new file is based on content taken from the old Google Code homepage. commit e2e9d64a63485461192d9c2a6dd0183a8b71013c Author: Field G. Van Zee Date: Thu Sep 24 12:14:03 2015 -0500 Load balance thread ranges for arbitrary diagonals. Details: - Expanded/updated interface for bli_get_range_weighted() and bli_get_range() so that the direction of movement is specified in the function name (e.g. bli_get_range_l2r(), bli_get_range_weighted_t2b()) and also so that the object being partitioned is passed instead of an uplo parameter. Updated invocations in level-3 blocked variants, as appropriate. - (Re)implemented bli_get_range_*() and bli_get_range_weighted_*() to carefully take into account the location of the diagonal when computing ranges so that the area of each subpartition (which, in all present level-3 operations, is proportional to the amount of computation engendered) is as equal as possible. - Added calls to a new class of routines to all non-gemm level-3 blocked variants: bli__prune_unref_mparts_[mnk]() where is herk, trmm, or trsm and [mnk] is chosen based on which dimension is being partitioned. These routines call a more basic routine, bli_prune_unref_mparts(), to prune unreferenced/unstored regions from matrices and simultaneously adjust other matrices which share the same dimension accordingly. - Simplified herk_blk_var2f, trmm_blk_var1f/b as a result of more the new pruning routines. - Fixed incorrect blocking factors passed into bli_get_range_*() in bli_trsm_blk_var[12][fb].c - Added a new test driver in test/thread_ranges that can exercise the new bli_get_range_*() and bli_get_range_weighted_*() under a range of conditions. - Reimplemented m and n fields of obj_t as elements in a "dim" array field so that dimensions could be queried via index constant (e.g. BLIS_M, BLIS_N). Adjusted/added query and modification macros accordingly. - Defined mdim_t type to enumerate BLIS_M and BLIS_N indexing values. - Added bli_round() macro, which calls C math library function round(), and bli_round_to_mult(), which rounds a value to the nearest multiple of some other value. - Added miscellaneous pruning- and mdim_t-related macros. - Renamed bli_obj_row_offset(), bli_obj_col_offset() macros to bli_obj_row_off(), bli_obj_col_off(). commit fe3e355c9c5a6f65b8736b009e2d501b62a83ea1 Merge: efa641e3 4dd9dd3e Author: Zhang Xianyi Date: Fri Aug 21 14:38:36 2015 -0500 Merge branch 'upstream_master' commit efa641e36b73abee34166a252e90e28a6281d92d Author: Zhang Xianyi Date: Sat Aug 22 03:15:50 2015 +0800 Try to fix the compiling bug on travis. commit 4dd9dd3e1de626b51bfe85d9ee65f193d60e8d38 Author: Field G. Van Zee Date: Fri Aug 21 11:52:37 2015 -0500 Fixed minor alignment ambiguity bug in bli_pool.c. Details: - Fixed a typecasting ambiguity in bli_pool_alloc_block() in which pointer arithmetic was performed on a void* as if it were a byte pointer (such as char*). Some compilers may have already been interpreting this situation as intended, despite the sloppiness. Thanks to Aleksei Rechinskii for reporting this issue. - Redefined pointer alignment macros to typecast to uintptr_t instead of siz_t. commit 12ffd568b04feda57147c13b67717416a01c82f8 Author: Zhang Xianyi Date: Sat Aug 22 00:24:28 2015 +0800 Add Travis CI. commit ecc3ebb749e0861c27deda52b5f87236ede4901b Author: Field G. Van Zee Date: Wed Jul 29 13:31:12 2015 -0500 CHANGELOG update (0.1.8) commit 47caa33485b91ea6f2a5e386e61210c90c5f489f (tag: 0.1.8) Author: Field G. Van Zee Date: Wed Jul 29 13:31:09 2015 -0500 Version file update (0.1.8) commit ef0fbbbdb6148b96938733fce72cb4ed7dad685e Merge: fdfe14f1 d4b89136 Author: Field G. Van Zee Date: Thu Jul 9 13:54:54 2015 -0500 Merge branch 'master' of github.com:flame/blis commit fdfe14f1e17ba5a2f8dfa0bdb799c6b0e730211b Author: Field G. Van Zee Date: Thu Jul 9 13:52:39 2015 -0500 Added support for Intel Haswell/Broadwell. Details: - Added sgemm and dgemm micro-kernels, which employ 256-bit AVX vectors and FMA instructions. (Complex support is currently provided by default induced method, 4m1a.) - Added a 'haswell' configuration, which uses the aforementioned kernels. - Inserted auto-detection support for haswell configuration in build/auto-detect/cpuid_x86.c. - Modified configure script to explicitly echo when automatic or manual configuration is in progress. - Changed beta scalar in test_gemm.c module of test suite to -1.0 to 0.9. commit d4b891369c1eb0879ade662ff896a5b9a7fca207 Author: Field G. Van Zee Date: Tue Jul 7 10:06:53 2015 -0500 Added 'carrizo' configuration. Details: - Added a new configuration for AMD Excavator-based hardware also known as Carrizo when referring to the entire APU. This configuration uses the same micro-kernels as the piledriver, but with different cache blocksizes. commit 0b7255a642d56723f02d7ca1f8f21809967b8515 Author: Field G. Van Zee Date: Fri Jun 19 12:01:50 2015 -0500 CHANGELOG update (0.1.7) commit 267253de8a7be546ce87626443ee38701c1d411f (tag: 0.1.7) Author: Field G. Van Zee Date: Fri Jun 19 12:01:49 2015 -0500 Version file update (0.1.7) commit 7cd01b71b5e757a6774625b3c9f427f5e7664a76 Author: Field G. Van Zee Date: Fri Jun 19 11:31:53 2015 -0500 Implemented dynamic allocation for packing buffers. Details: - Replaced the old memory allocator, which was based on statically- allocated arrays, with one based on a new internal pool_t type, which, combined with a new bli_pool_*() API, provides a new abstract data type that implements the same memory pool functionality but with blocks from the heap (ie: malloc() or equivalent). Hiding the details of the pool in a separate API also allows for a much simpler bli_mem.c family of functions. - Added a new internal header, bli_config_macro_defs.h, which enables sane defaults for the values previously found in bli_config. Those values can be overridden by #defining them in bli_config.h the same way kernel defaults can be overridden in bli_kernel.h. This file most resembles what was previously a typical configuration's bli_config.h. - Added a new configuration macro, BLIS_POOL_ADDR_ALIGN_SIZE, which defaults to BLIS_PAGE_SIZE, to specify the alignment of individual blocks in the memory pool. Also added a corresponding query routine to the bli_info API. - Deprecated (once again) the micro-panel alignment feature. Upon further reflection, it seems that the goal of more predictable L1 cache replacement behavior is outweighed by the harm caused by non-contiguous micro-panels when k % kc != 0. I honestly don't think anyone will even miss this feature. - Changed bli_ukr_get_funcs() and bli_ukr_get_ref_funcs() to call bli_cntl_init() instead of bli_init(). - Removed query functions from bli_info.c that are no longer applicable given the dynamic memory allocator. - Removed unnecessary definitions from configurations' bli_config.h files, which are now pleasantly sparse. - Fixed incorrect flop counts in addv, subv, scal2v, scal2m testsuite modules. Thanks to Devangi Parikh for pointing out these miscalculations. - Comment, whitespace changes. commit 9848f255a3bab17d1139c391cca13ff3f1ffe6ed Author: Field G. Van Zee Date: Thu Jun 11 19:14:22 2015 -0500 Added early return to API-level _init() routines. Details: - Added conditional code that returns early from the API-level _init() routines if the API is already initialized. Actually meant for this to be included in 5f93cbe8. commit 5f93cbe870f3478870e15581e7fd450dad5bba1e Author: Field G. Van Zee Date: Thu Jun 11 18:52:12 2015 -0500 Introduced API-level initialization. Details: - Added API-level initialization state to _const, _error, _mem, _thread, _ind, and _cntl APIs. While this functionality will mostly go unused, adding miniscule overhead at init-time, there will be at least once instance in the near future where, in order to avoid an infinite loop, a certain portion of the initialization will call a query function that itself attempts to call bli_init(). API-level initialization will allow this later stage to verify that an earlier stage of initialization has completed, even if the overall call to bli_init() has not yet returned. - Added _is_initialized() functions for each API, setting the underlying bool_t during _init() and unsetting it during _finalize(). - Comment, whitespace changes. commit ee129c6b028bc5ac88da7c74fde72c49803742ff Author: Field G. Van Zee Date: Wed Jun 10 12:53:28 2015 -0500 Fixed bugs in _get_range(), _get_range_weighted(). Details: - Fixed some bugs that only manifested in multithreaded instances of some (non-gemm) level-3 operations. The bugs were related to invalid allocation of "edge" cases to thread subpartitions. (Here, we define an "edge" case to be one where the dimension being partitioned for parallelism is not a whole multiple of whatever register blocksize is needed in that dimension.) In BLIS, we always require edge cases to be part of the bottom, right, or bottom-right subpartitions. (This is so that zero-padding only has to happen at the bottom, right, or bottom-right edges of micro-panels.) The previous implementations of bli_get_range() and _get_range_weighted() did not adhere to this implicit policy and thus produced bad ranges for some combinations of operation, parameter cases, problem sizes, and n-way parallelism. - As part of the above fix, the functions bli_get_range() and _get_range_weighted() have been renamed to use _l2r, _r2l, _t2b, and _b2t suffixes, similar to the partitioning functions. This is an easy way to make sure that the variants are calling the right version of each function. The function signatures have also been changed slightly. - Comment/whitespace updates. - Removed unnecessary '/' from macros in bli_obj_macro_defs.h. commit 9135dfd69d39f3bbd75034f479f27a78dbfebcce Author: Field G. Van Zee Date: Fri Jun 5 13:37:44 2015 -0500 Minor updates to test/3m4m files. commit d62ceece943b20537ec4dd99f25136b9ba2ae340 Author: Field G. Van Zee Date: Wed Jun 3 12:56:45 2015 -0500 Minor update to test/3m4m/runme.sh. Details: - Removed some stale script code that should have been removed during 590bb3b8c. commit b6ee82a3d421c9c4f1eb6848c7c6e37aa46de799 Author: Field G. Van Zee Date: Wed Jun 3 12:14:23 2015 -0500 Minor cleanup to bli_init() and friends. Details: - Spun-off initialization of global scalar constants to bli_const_init() and of threading stuff to bli_thread_init(). - Added some missing _finalize() functions, even when there is nothing to do. commit 1213f5cebabc1637ce9dd45c4bfa87bb93677c29 Author: Field G. Van Zee Date: Tue Jun 2 13:27:47 2015 -0500 POSIX thread bugfixes/edits to bli_init.c, _mem.c. Details: - Fixed a sort-of bug in bli_init.c whereby the wrong pthread mutex was used to lock access to initialization/finalization actions. But everything worked out okay as long as bli_init() was called by single-threaded code. - Changed to static initialization for memory allocator mutex in bli_mem.c, and moved mutex to that file (from bli_init.c). - Fixed some type mismatches in bli_threading_pthreads.c that resulted in compiler warnings. - Fixed a small memory leak with allocated-but-never-freed (and unused) pthread_attr_t objects. - Whitespace changes to bli_init.c and bli_mem.c. commit 590bb3b8c5c0389159c5a9451b6c156c5f237e8a Author: Field G. Van Zee Date: Sun May 24 16:02:53 2015 -0500 Backed-out adjusted dim changes to test/3m4m. Details: - Reverted most changes applied during commit ec25807b. commit ec25807b26da943868f0d0517c3720e50181b8f9 Author: Field G. Van Zee Date: Fri Apr 10 13:23:50 2015 -0500 Tweaks to test/3m4m to test with adjusted dims. Details: - Updated test/3m4m driver files to build test drivers that allow comparision of real "asm_blis" results to complex "asm_blis" results, except with the latter's problem sizes adjusted so that problems are generated with equal flop counts. commit 426b6488580a92bf071a62dc319a9c837ce39821 Author: Field G. Van Zee Date: Wed Apr 8 15:12:21 2015 -0500 Fixed a packing bug that manifested in trsm_r. Details: - Fixed a bug that caused a memory leak in the contiguous memory allocator. Because packm_init() was using simple aliasing when a subpartition object was marked as zeros by bli_acquire_mpart_*(), the "destination" pack object's mem_t entry was being overwritten by the corresponding field of the "source" object (which was likely NULL). This prevented the block from being released back to the memory allocator. But this bug only manifested when changing the location of packing B from outside the var1 loop to inside the var3 loop, and only for trsm with triangular B (side = right). The bug was fixed by changing the type of alias used in packm_init() when handling zero partition cases. Specifically, we now use bli_obj_alias_for_packing(), which does not clobber the destination (pack) object's mem_t field. Thanks to Devangi Parikh for this bug report. commit c84286d5cef48f16d83831baac1f46b9856b9a36 Author: Field G. Van Zee Date: Sat Apr 4 15:39:14 2015 -0500 More minor tweaks to test/3m4m. Details: - Added a line of output that forces matlab to allocate the entire array up-front. - Re-enabled real domain benchmarks in runme.sh, which were temporarily disabled. commit 309717c8ebf4ef1369f15cf41340e13c25b41573 Author: Field G. Van Zee Date: Fri Apr 3 19:28:49 2015 -0500 More tweaks to test/3m4m, configurations. Details: - Fixed incorrect number of mc_x_kc memory blocks in sandybridge/bli_config.h. - Enabled OpenMP multithreding in piledriver/bli_config.h. - More updates to test/3m4m driver files. commit 4baf3b9c69b2f648be9e46e07ccc9859dd675828 Author: Field G. Van Zee Date: Fri Apr 3 16:44:32 2015 -0500 Tweaked test/3m4m driver, including acml support. Details: - Added ACML support to test/3m4m driver Makefile and runme.sh script. commit a32f7c49ca4ea869d2a6c66818780f4321743d67 Merge: 349e075a 4bfd1ce8 Author: Field G. Van Zee Date: Fri Apr 3 08:28:11 2015 -0500 Merge pull request #23 from xianyi/master Add auto-detecting CPU on configure stage. commit 349e075ad6a8e2a1211d94f36d24828c9d44b052 Author: Field G. Van Zee Date: Thu Apr 2 18:12:28 2015 -0500 Tweaks to sandybridge config, test/3m4m driver. Details: - Enable OpenMP support by default in sandybridge's bli_config.h. - Reorganized sandybridge's bli_kernel.h. - Updated 3m4m Makefile, runme.sh to also test MKL implementation. commit 4bfd1ce8ca93f93d170dd2715f0a32027b417b46 Author: Zhang Xianyi Date: Thu Apr 2 16:40:21 2015 -0500 Detect NEON for cortex-a9 and cortex-a15. commit aa6eec4f43137057276fe6119bdbfb5c52682527 Author: Zhang Xianyi Date: Thu Apr 2 16:03:44 2015 -0500 Detect the CPU architecture. Support ARM cores. Detect the CPU architecture by compiler's predefined macros. Then, detect the CPU cores. Support detecting x86 and ARM architectures. commit 2947cfb749c937b0f62fac36cc92f123bd45b53c Author: Zhang Xianyi Date: Wed Apr 1 12:24:00 2015 -0500 Add auto-detecting CPU on configure stage. e.g. /Path_to_BLIS/configure auto Now, it only support detecting x86 CPUs. commit 26a4b8f6f985597f80e0174990bf541f1d9bafac Author: Field G. Van Zee Date: Wed Apr 1 10:44:54 2015 -0500 Implemented 3m2, 3m3 induced algorithms (gemm only). Details: - Defined a new "3ms" (separated 3m) pack schema and added appropriate support in packm_init(), packm_blk_var2(). - Generalized packm_struc_cxk_3mi to take the imaginary stride (is_p) as an argument instead of computing it locally. Exception: for trmm, is_p must be computed locally, since it changes for triangular packed matrices. Also exposed is_p in interface to dt-specific packm_blk_var2 (and _var1, even though it does not use imaginary stride). - Renamed many functions/variables from _3mi to _3mis to indicate that they work for either interleaved or separated 3m pack schemas. - Generalized gemm and herk macro-kernels to pass in imaginary stride rather than compute them locally. - Added support for 3m2 and 3m3 algorithms to frame/ind, including 3m2- and 3m3-specific virtual micro-kernels. - Added special gemm macro-kernels to support 3m2 and 3m3. - Added support for 3m2 and 3m3 to testsuite. - Corrected the type of the panel dimension (pd_) in various macro- kernels from inc_t to dim_t. - Renamed many functions defined in bli_blocksize.c. - Moved most induced-related macro defs from frame/include to frame/ind/include. - Updated the _ukernel.c files so that the micro-kernel function pointers are obtained from the func_t objects rather than the cpp macros that define the function names. - Updated test/3m4m driver, Makefile, and run script. commit ddf62ba7d2da08225b201585b85e06c967767dea Author: Tyler Smith Date: Fri Mar 27 14:27:51 2015 -0500 Refuse to free the packm thread info if it uses the single threaded version commit 016fc587584d958a0e430a56a5e2c05022ac2f17 Author: Tyler Smith Date: Fri Mar 27 14:23:02 2015 -0500 Don't free packm thread info if it is null commit 00a443c529a60862a57b93e303a0b3212c9b1df4 Author: Tyler Smith Date: Fri Mar 27 14:11:07 2015 -0500 Use bli_malloc instead of malloc for the thread info paths commit f1a6b7d02861ccebdc500ea98778cc0f6cddad17 Author: Field G. Van Zee Date: Wed Mar 18 15:37:10 2015 -0500 Reorganized code for induced complex methods. Details: - Consolidated most of the code relating to induced complex methods (e.g. 4mh, 4m1, 3mh, 3m1, etc.) into frame/ind. Induced methods are now enabled on a per-operation basis. The current "available" (enabled and implemented) implementation can then be queried on an operation basis. Micro-kernel func_t objects as well as blksz_t objects can also be queried in a similar maner. - Redefined several micro-kernel and operation-related functions in bli_info_*() API, in accordance with above changes. - Added mr and nr fields to blksz_t object, which point to the mr and nr blksz_t objects for each cache blocksize (and are NULL for register blocksizes). Renamed the sub-blocksize field "sub" to "mult" since it is really expressing a blocksize multiple. - Updated bli_*_determine_kc_[fb]() for gemm/hemm/symm, trmm, and trsm to correctly query mr and nr (for purposes of nudging kc). - Introduced an enumerated opid_t in bli_type_defs.h that uniquely identifies an operation. For now, only level-3 id values are defined, along with a generic, catch-all BLIS_NOID value. - Reworked testsuite so that all induced methods that are enabled are tested (one at a time) rather than only testing the first available method. - Reformated summary at the beginning of testsuite output so that blocksize and micro-kernel info is shown for each induced method that was requested (as well as native execution). - Reduced the number of columns needed to display non-matlab testsuite output (from approx. 90 to 80). commit 8d5169ccda954e5f72944308a036dcb7ebfc9097 Author: Field G. Van Zee Date: Wed Mar 18 11:38:08 2015 -0500 Fixed bug in release of mem_t buffer. Details: - Fixed a bug that affects all level-2 and level-3 blocked variants. The bug only manifested, however, if the packing of operands (A and B in gemm, for example) spanned multiple nodes in the control tree. Until recently, the main consumers of packm were level-3 operations, all of which packed both input operands from blocked variant 1 (B outside of the loop, and A within the loop). This particular usage masked a flaw in the code whereby bli_obj_release_pack() would always release the underlying mem_t buffer (provided it was allocated), even if the buffer was not allocated in the current variant. This has been fixed by replacing all calls to bli_obj_release_pack() with calls to a new function, bli_packm_release(), which takes the same control tree node argument passed into the object's corresponding call to packm_init() or packv_init(). bli_packm_release() then proceeds to invoke bli_obj_release_pack() only if the control tree node indicates that packing was requested. Thanks to Devangi Parikh for identifying this bug. commit c0acca0f5182ba96fd39c9d10b34a896a6e74206 Author: Field G. Van Zee Date: Tue Mar 3 10:56:22 2015 -0600 Clarified comments in testsuite input.operations. commit 03ba9a6b17861d9e1adc0cf924439c4d7e860d19 Author: Field G. Van Zee Date: Tue Feb 24 10:33:28 2015 -0600 Removed some 'old' directories. commit a86db60ee270cdeb745ae7cf68f9e0becc9f522d Author: Field G. Van Zee Date: Mon Feb 23 18:42:39 2015 -0600 Extensive renaming of 3m/4m-related files, symbols. Details: - Renamed all remaining 3m/4m packing files and symbols to 3mi/4mi ('i' for "interleaved"). Similar changes to 3M/4M macros. - Renamed all 3m/4m files and functions to 3m1/4m1. - Whitespace changes. commit 8cf8da291a0fb2f491f410969a76ec0fbda47faf Author: Field G. Van Zee Date: Fri Feb 20 15:24:27 2015 -0600 Minor updates to induced complex mode management. Details: - Relocated bli_4mh.c, bli_4mb.c, bli_4m.c, bli_3mh.c, bli_3m.c (and associated headers) from frame/base to frame/base/induced. - Added bli_xm.? to frame/base/induced, which implements bli_xm_is_enabled(), which detects whether ANY induced complex method is currently enabled. - The new function bli_xm_is_enabled() is now used in bli_info.c to detect when an induced complex method is used, so we know when to return blocksizes from one of the induced methods' blocksize objects. commit 411e637ee7d1083a84f58f08938d51e63d7c3c9a Merge: c2569b88 fc0b7712 Author: Tyler Michael Smith Date: Fri Feb 20 20:39:25 2015 -0600 Merge branch 'master' of http://github.com/flame/blis commit c2569b8803d4ccc1d7b6f391713461b51443601d Author: Tyler Michael Smith Date: Fri Feb 20 20:38:19 2015 -0600 Fixed a memory leak in freeing the thread infos commit fc0b771227abf86d81f505b324f69f6e83db1d8f Author: Field G. Van Zee Date: Fri Feb 20 11:47:44 2015 -0600 Added max(mr,nr) to kc in static mem pools. Details: - Changed the static memory definitions to compute the maximum register blocksize for each datatype and add it to kc when computing the size of blocks of A and B. This formally accounts for the nudging of kc up to a multiple of mr or nr at runtime for triangular operations (e.g. trmm). commit af32e3a608631953ef770341df10a14a991bf290 Author: Tyler Michael Smith Date: Thu Feb 19 22:51:11 2015 -0600 Fixed a bug with get_range_weighted would return end = 0 for small problem sizes commit 441d47542a64e131578d00da7404c1ed387a721c Author: Field G. Van Zee Date: Thu Feb 19 17:06:10 2015 -0600 Renamed 3m and 4m symbols/macros to 3mi and 4mi. Details: - Renamed several variables and macros from 3m/4m to 3mi/4mi. This is because those packing schemas were always implicitly "interleaved". This new naming scheme will make way for new schemas that separate instead of interleve the real and imaginary (and summed) parts. - Expanded the pack format sub-field of the pack schema field of the info_t to 4 bits (from 3). This will allow for more schema types going forward. - Removed old _cntl.c files for herk3m, herk4m, trmm3m, trmm4m. commit 518a1756ccf02122b96fc437b538604a597df42a Author: Field G. Van Zee Date: Thu Feb 19 14:27:09 2015 -0600 Fixed indexing bug for trmm3 via 3mh, 4mh. Details: - Fixed a bug that only affected trmm3 when performed via 3mh or 4mh, whereby micro-panels of the triangular matrix were packed with "dead space" between them due to failing to adjust for the fact that pointer arithmetic was occurring in units of complex elements while the data being packed consisted of real elements. It turns out that the macro- kernel suffered from the same bug, meaning the panels were actually being packed and read consistently. The only way I was able to discover the bug in the first place was because the packed block of A was overflowing into the beginning of the packed row panel of B using the sandybridge configuration. commit 493087d730f01d5169434f461644e5633f48a42f Merge: 650d2a6f 25021299 Author: Field G. Van Zee Date: Wed Feb 18 09:45:51 2015 -0600 Merge branch 'master' of github.com:flame/blis commit 25021299b670775df8ca9c87910c63d7e74ed946 Merge: fe2b8d39 f05a5763 Author: Field G. Van Zee Date: Wed Feb 11 20:03:21 2015 -0600 Merge branch 'master' of github.com:flame/blis commit fe2b8d39a445ac848686e78c7540fd046cb95492 Author: Field G. Van Zee Date: Wed Feb 11 19:33:10 2015 -0600 Fixed an obscure bug in 3mh/3m/4mh/4m packing. Details: - Modified bli_packm_blk_var1.c and _var2.c to increase the triangular case's panel increment by 1 if it would otherwise be odd. This is particularly necessary in _var2.c when handling the interleaved 3m or ro/io/rpi pack schemas, since division of an odd number by 2 can happen if both the panel length and the panel packing dimension (register packing blocksize) are odd, thus making their product odd. - Modified bli_packm_init.c so that panel strides are increased by 1 if they would otherwise be odd, even for non-3m related packing. - Modified the trmm and trsm macro-kernels so that triangular packed micro-panels are traversed with this new "increment by 1 if odd" policy. - Added sanity checks in trmm and trsm macro-kernels that would result in an abort() if the conditions that would lead to a "divide odd integer by 2" scenario ever manifest. - Defined bli_is_odd(), _is_even() macros in bli_scalar_macro_defs.h. commit 650d2a6ff2e593151a296ca86b5214afcc747afc Author: Field G. Van Zee Date: Mon Feb 9 14:59:20 2015 -0600 Added initial support for imaginary stride. Details: - Added an imaginary stride field ("is") to obj_t. - Renamed bli_obj_set_incs() macro to bli_obj_set_strides(). - Defined bli_obj_imag_stride() and bli_obj_set_imag_stride() and added invocations in key locations. - Added some basic error-checking related to imaginary stride. - For now, imaginary stride will not be exposed into the most-used BLIS APIs such as bli_obj_create(), and certainly not the computational APIs such as bli_dgemm(). commit f05a57634a7c8e3864b25b3335d1194c1ea1aeb9 Author: Field G. Van Zee Date: Sun Feb 8 19:40:34 2015 -0600 Defined gemm cntl function to query ukrs func_t. Details: - Added a new function, bli_gemm_cntl_ukrs(), that returns the func_t* for the gemm micro-kernels from the leaf node of the control tree. This allows all the func_t* fields from higher-level nodes in the tree to be NULL, which makes the function that builds the control trees slightly easier to read. - Call bli_gemm_cntl_ukrs() instead of the cntl_gemm_ukrs() macro in all bli_*_front() functions (which is needed to apply the row/column preference optimization). - In all level-3 bli_*_cntl_init() functions, changed the _obj_create() function arguments corresponding to the gemm_ukrs fields in higher- level cntl tree nodes to NULL. - Removed some old her2k macro-kernels. commit cefd3d5d2001264de17cf63dae541f890cb9daaf Author: Tyler Smith Date: Thu Feb 5 11:09:12 2015 -0600 A couple of functions were incorrectly ifdeffed away on Xeon Phi. Fixed this commit 7574c9947d57a19f613880e3b9f62f8c8f6df4ec Author: Field G. Van Zee Date: Wed Feb 4 12:11:55 2015 -0600 Added basic flop-counting mechanism (level-3 only). Details: - Added optional flop counting to all level-3 front-ends, which is enabled via BLIS_ENABLE_FLOP_COUNT. The flop count can be reset at any time via bli_flop_count_reset() and queried via bli_flop_count(). Caveats: - flop counts are approximate for her[2]k, syr[2]k, trmm, and trsm operations; - flop counts ignore extra flops due to non-unit alpha; - flop counts do not account for situations where beta is zero. commit ceda4f27d1f1bcf19320e09848e0f2e3b9941e6c Author: Field G. Van Zee Date: Thu Jan 29 13:22:54 2015 -0600 Implemented bli_obj_imag_equals(). Details: - Implemented a new function, bli_obj_imag_equals(), which compares the imaginary part of the first argument to the second argument, which may be a BLIS_CONSTANT or of a regular real datatype. commit 81114824a05a9053229efd577a8a94a856deda93 Author: Field G. Van Zee Date: Tue Jan 6 12:15:21 2015 -0600 Minor 4m/3m consolidation to mem_pool_macro_defs.h. Details: - Merged the 4m and 3m definitions in bli_mem_pool_macro_defs.h to reduce code and improve readability. commit 36a9b7b7436d9423ba4de2a9f85cfcd43577b783 Author: Tyler Michael Smith Date: Wed Dec 17 21:53:50 2014 +0000 reduced the default number of MC by KC blocks for bgq commit c60619c7c3568f044a849abbab60209aa7455423 Author: Field G. Van Zee Date: Tue Dec 16 17:08:22 2014 -0600 Minor tweaks for 3m4m test drivers. Details: - Changed gemm_kc blocksizes to be reduced by two-thirds instead of half. - Changed 3m4m/test_gemm.c driver to divide by 3 instead of 2 when computing the fixed k dimension. - Fixed runme.sh so that it would use multiple threads for s/dgemm cases. commit c6929ba6a5e6f633a7295e979a2b8df8c7ecdb1b Author: Field G. Van Zee Date: Tue Dec 16 11:27:50 2014 -0600 Added 4m_1b to test/3m4m test driver and script. commit 785d480805fc0d6f4251b5499933515740b6b2a7 Merge: 9456f330 4156c088 Author: Field G. Van Zee Date: Fri Dec 12 14:34:19 2014 -0600 Merge branch 'master' of github.com:flame/blis commit 9456f330af4617f9ee32972d51f974aa2d84f97b Author: Field G. Van Zee Date: Fri Dec 12 14:31:57 2014 -0600 Added 4m_1b implementation for gemm. Details: - Added yet another 4m-based implementation for complex domain level-3 operations. This method, which the 3m/4m paper identifies as Algorithm "4m_1b" fissures the first loop around the micro-kernel so that the real sub-panel of the current micro-panel of B is multiplied against (both sub-panels of) all micro-panels of A, before doing the same for the imaginary sub-panel of the micro-panel of B. For now, only gemm is supported, and 4m_1b (labeled "4mb" within the framework) is not yet integrated into the test suite. commit 4156c0880d9aea4ff04a9c4fa139ba8c437d8bfb Author: Field G. Van Zee Date: Tue Dec 9 16:03:14 2014 -0600 Fixed obscure level-2 packing / general stride bug. Details: - Fixed a bug in certain structured level-2 operations that manifested only when the structured matrix was provided to BLIS as matrix stored with general stride. The bug was introduced in c472993b when the densify field was removed from the packm control tree node and associated APIs. Since then, the packed object was unconditionally marked with an uplo field of BLIS_DENSE. This is fine for level-3 operations where micro-panels are always densified, but in level-2 contexts, the underlying unblocked variant (fused or unfused) of structured operations (e.g. trmv) still needs to know whether to execute its "lower" or "upper" branches of code. Since this field was unconditionally being set to BLIS_DENSE, the unblocked variants were always executed the "else" branch, which happened to be the "lower" case code. Thus, running an upper case produced the wrong answer. This most obviously manifested in the form of failures for trmm, trmm3, and trsm in the test suite. The bug was fixed by setting the packed object's uplo field to BLIS_DENSE only if the schema indicated that micro-panels were to be packed. Otherwise, we can assume we are packing to regular row or column storage, as is the case with level-2 packing. Thanks to Francisco Igual for reporting the testsuite failures and ultimately leading us to this bug. commit 689f60a578b461119e9ea90c74f642b9eb79addb Merge: bef24e67 483e4d6a Author: Field G. Van Zee Date: Sun Dec 7 14:03:30 2014 -0600 Merge pull request #21 from figual/master Adding armv8a configuration and micro-kernels. commit 483e4d6a3fdbef9d9ab47fb674c9476c70ca9f0f Author: Francisco D. Igual Date: Sun Dec 7 20:27:49 2014 +0100 Adding armv8a configuration and micro-kernels. Only sgemm micro-kernel is fully functional at this point. commit bef24e67e0f93579c2a80315348dc2e227f72a72 Author: Tyler Smith Date: Wed Nov 26 18:00:56 2014 -0600 Fixed a type of race condition exposed by pthreads implementation. Lead thread of the inner thread communicator could exit subproblem, move on the next iteration of the loop and modify a1_pack, b1_pack, or c1_pack while other threads were still using those. Barriers were inserted to fix this. commit 76bde44411f0e34266bab9d666a54ef22be97320 Merge: e56e6143 f3d729e5 Author: Field G. Van Zee Date: Wed Nov 26 17:25:24 2014 -0600 Merge branch 'master' of github.com:flame/blis commit f3d729e504ec012e7dc7e02b2ecd42e004c6894d Author: Tyler Michael Smith Date: Wed Nov 26 22:25:24 2014 -0600 Added static mutex to bli_init and bli_finalize commit d71cc797866ff502ad1127527016f463267eef80 Author: Tyler Michael Smith Date: Wed Nov 26 21:35:39 2014 -0600 Refactored bli_threading files and added support for pthreads commit e56e61438ff7fcf25a48c0b7603f18df782b50b6 Author: Field G. Van Zee Date: Wed Nov 26 17:20:35 2014 -0600 Minor cleanups to bli_threading.h and friends. Details: - No longer need to define BLIS_ENABLE_MULTITHREADING manually in bli_config.h; it now gets defined when BLIS_ENABLE_OPENMP or BLIS_ENABLE_PTHREADS is defined. - Added sanity check to prevent both BLIS__ENABLE_OPENMP and BLIS_ENABLE_PTHREADS from being enabled simultaneously. - Reorganization of bli_threading*.h header files, which led to simplification of threading-related part of blis.h. - added "-fopenmp -lpthread" to LDFLAGS of sandybridge make_defs.mk file. commit 3be2744cbe2c56d38c23fd818aa5c1f10cc7ea51 Author: Field G. Van Zee Date: Fri Nov 21 12:28:08 2014 -0600 Update to template gemm ukernel comments. Details: - Updated comments on alignment of a1 and b1 to match wiki. commit 994429c6881b2ade92d9d7949bcaebfbf2cc65eb Merge: 58796abd 694029d9 Author: Field G. Van Zee Date: Thu Nov 20 13:55:35 2014 -0600 Merge pull request #20 from TimmyLiu/master #define PASTEF773 required by cblas compatibility layer commit 694029d9d7db857d642ab536955c0621791108c8 Author: Timmy Date: Wed Nov 19 15:25:14 2014 -0600 #define PASTEF773 required by cblas compatiility layer commit 58796abda66b133346f8d523b39178afc336351f Author: Field G. Van Zee Date: Thu Nov 6 14:31:52 2014 -0600 Removed KC constraint comments from _kernel.h files. Details: - Since 4674ca8c, the constraint that KC be a multiple of both MR and NR have been relaxed, and thus it was time to remove the comments from the top of the bli_kernel.h files of all configurations. commit 7bbc95a54f706d43c7f7951f0e5995f86130cd52 Author: Field G. Van Zee Date: Wed Oct 29 10:52:23 2014 -0500 Added new piledriver micro-kernels. Details: - Added new micro-kernels for the AMD piledriver architecture (one for each datatype). - Updates and tweaks to piledriver configuration. - Added 3xk packm micro-kernel support. - Explicitly unrolled some of the smaller packm micro-kernels. - Added notes to avx/sandybridge and piledriver micro-kernel files acknowledging the influence of the corresponding kernel code in OpenBLAS. commit 59613f1d5500f6279963327db2fbc84bc9135183 Author: Field G. Van Zee Date: Thu Oct 23 17:21:37 2014 -0500 Added separeate micro-panel alignment for A and B. Details: - Changed the recently-added micro-panel alignment macros so that we now have two sets--one for micro-panels of matrix A and one for micro- panels of matrix B: BLIS_UPANEL_[AB]_ALIGN_SIZE_?. - Store each set of alignment values into a separate blksz_t object in bli_gemm_cntl_init(). - Adjusted packm_init() to use the separate alignment values. - Added query routines for the new alignment values to bli_info.c. - Modified test suite output accordingly. commit a8e12884ee1fddd3fd77ca5a68aa0cb857f3af57 Author: Field G. Van Zee Date: Thu Oct 23 11:35:48 2014 -0500 CHANGELOG update (0.1.6) commit 38ea5022e4ed846112198c4e1672fcdaeb90dc71 (tag: 0.1.6) Author: Field G. Van Zee Date: Thu Oct 23 11:35:45 2014 -0500 Version file update (0.1.6) commit a3e6341bdb0e28411f935d6b4708a6389663e004 Author: Field G. Van Zee Date: Thu Oct 23 11:13:28 2014 -0500 Factored common code from blocksize functions. Details: - Split bli_determine_blocksize_[fb]() into two functions each, the newer ones ending with the _sub suffix. These new sub-functions are now called from bli_[gemm|trmm|trsm]_determine_kc_[fb](), which eliminates redundant code and will allow any future tweaks to the core sub-functions to automatically be inherited by the operation- specific versions. commit 4674ca8cffb58331ff7edf23bbe0e3f6a7558489 Author: Field G. Van Zee Date: Thu Oct 23 10:50:59 2014 -0500 Extended newly relaxed KC to hemm, symm. Details: - These changes were intended for the previous commit. - Defined bli_gemm_determine_kc_[fb]() and bli_gemm_determine_kc_[fb](), which determine blocksizes for gemm-based operations, taking special care to "nudge" the kc dimension up to a multiple of MR or NR for hemm and symm operations, as needed. - Changed bli_gemm_blk_var3f.c to call bli_gemm_determine_kc_f(). instead of bli_determine_blocksize_f(). - Comment updates to bli_trmm_blocksize.c, bli_trsm_blocksize.c. commit ab954ba6f874eaca7b001804491f866ef6b9b327 Author: Field G. Van Zee Date: Wed Oct 22 17:21:58 2014 -0500 Relaxed constraint that KC be multiple of MR, NR. Details: - Relaxed a long-held requirement in register blocksizes that required the kernel programmer to choose a KC that was divisible by both MR and NR. This was very constraining on some architectures that did not use register blocksizes that were powers of two. The constraint is now enforced only for trmm and trsm, where it is needed, and it is now handled by "nudging" kc upward at runtime, if necessary, to be a multiple of MR or NR, as needed. - Defined bli_trmm_determine_kc_[fb]() and bli_trsm_determine_kc_[fb](), which determine blocksizes for trmm and trsm, taking special care to "nudge" the kc dimension up to a multiple of MR or NR, as needed. - Changed bli_trmm_blk_var3[fb].c to call bli_trmm_determine_kc_[fb]() instead of bli_determine_blocksize_[fb](). - Added safeguard to bli_align_dim_to_mult() that returns the dimension unmodified if the dimension multiple is zero (to avoid division by zero). - Removed cpp guard/check for KC % MR == 0 and KC % NR == 0 from bli_kernel_macro_defs.h. - Whitespace, variable name changes to bli_blocksize.c. - Removed old commented code from bli_gemm_cntl.c. commit 95cdae65d6b88e043ee14bcd53cd2e800d7aecb4 Author: Tyler Smith Date: Wed Oct 22 16:30:16 2014 -0500 Fixed bug in KNC microkernel where k=0 and beta != 1 commit e64dba5633fc49b768b5edc7762f2b5d8a4d0588 Author: Field G. Van Zee Date: Mon Oct 20 19:23:06 2014 -0500 Re-implemented micro-panel alignment. Details: - This commit re-implements a feature that was removed in commit c2b2ab62. It was removed because, at the time, I wasn't sure how the micro-panel alignment feature would interact with the 4m method (when applied at the micro-kernrel level), and so it seemed safer to disable the feature entirely rather than allow possible breakage. This commit revisits the issue and safely re-implements the feature in a way that is compatible with 4m, 3m, 4mh, and 3mh (and native execution). - Modified the static memory pool to account for micro-panel alignment space. - Modified packm_init and blocked variants to align whole micro-panels by a datatype-specific alignment value that may be set by the configuration. (If it is not set by the configuration, it will default to BLIS_SIZEOF_?.) - Modified macro-kernels so that: - storage stride is handled properly given the new micro-panel alignment behavior; - indexing through 3m/4m/rih-type sub-panels, as is done by trmm and trsm, is more robust (e.g. will work if the applicable packing register blocksize is odd); - imaginary strides are computed and stored within auxinfo_t structs, which allows the virtual micro-kernels to more easily determine how to index into the micro-panel operands. - Modified virtual 3m and 4m micro-kernels to use the imaginary strides within the auxinfo_t structs instead of panel strides. - Deprecated the panel stride fields from the auxinfo_t structs. - Updated test suite to print out the micro-panel alignment values. commit add16b0e5402924301e7078e4ca5e3ef725bff0b Author: Field G. Van Zee Date: Fri Oct 17 11:49:24 2014 -0500 Added 3m4m test driver subdir of 'test'. Details: - Added a modified test driver for [cz]gemm that will test all 3m/4m as well as assembly-based and OpenBLAS implementations of gemm in single and multithreaded modes. commit e171504a72406c61a173241d8bccf0a5ceb10582 Author: Field G. Van Zee Date: Fri Oct 17 11:25:59 2014 -0500 Use correct definition of bli_is_last_iter(). Details: - As intended for previous commit, the new definition of bli_is_last_iter() is now disabled in favor of the old definition. commit 0d954087b2b55d2f5f3c5e57d702b318ca2300f6 Author: Field G. Van Zee Date: Fri Oct 17 11:19:34 2014 -0500 Minor changes and fixes. Details: - Redefined bli_is_last_iter() to take thread_id and num_thread arguments, which allows the macro to correctly compute whether a given iteration is the last that the thread will compute in that particular loop. The new definition, however, remains disabled (commented out) until someone can look at this more closely, as the new definition seems to actually hurt performance slightly. - Whitespace and related updates to level-3 macro-kernels. - Updated test suite so that performance results in the hundreds of gigaflops does not disrupt the column alignment of the output. commit d1e86e1876e433f54b501ec5a005b4ba7c5ce4e6 Author: Field G. Van Zee Date: Sun Oct 12 13:43:47 2014 -0500 More minor tweaks to sandybridge/avx micro-kernel. Details: - Re-enabled use of b_next for dgemm and cgemm micro-kernels. commit 7b6fe4cae57cb22c09c1a97595e1a201a02cbcd2 Author: Field G. Van Zee Date: Sun Oct 12 12:01:51 2014 -0500 Minor tweaks to sandybridge/avx micro-kernels. Details: - Changed the MC blocksize for zgemm micro-kernel from 128 to 64. - Removed usage of b_next in all x86_64/avx gemm micro-kernels. commit a6a156e9feec47154e7a0fd43bcc006b1fc04aba Author: Field G. Van Zee Date: Fri Oct 10 14:26:41 2014 -0500 Added cgemm ukernel for avx/sandybridge. Details: - Implemented AVX-based cgemm micro-kernel (via GNU extended inline assembly syntax). - Updated sandybridge configuration accordingly. commit 6f8575ab2580e167a022293b76ddf0514f71b613 Author: Field G. Van Zee Date: Fri Oct 10 10:01:45 2014 -0500 Added zgemm ukernel for avx/sandybridge. Details: - Implemented AVX-based zgemm micro-kernel (via GNU extended inline assembly syntax). - Updated sandybridge configuration accordingly. commit 23ce7ee542a12ca40b4b6090ad2558d180e16d37 Merge: 99fd9a39 7a8ad47f Author: Field G. Van Zee Date: Thu Oct 9 16:41:22 2014 -0500 Merge branch 'master' of github.com:flame/blis commit 99fd9a39718cb7281f6fb23f9fef7cca4fe514f4 Author: Field G. Van Zee Date: Thu Oct 9 16:38:04 2014 -0500 Fixed two minor bugs. Details: - Fixed a bug in the test suite for the trsm_ukr and gemmtrsm_ukr test modules whereby the uplo bits of some packed matrix objects were not being set properly, resulting in false FAILURE results for those tests. Thanks to Tyler Smith for bringing this issue to my attention. - Fixed a bug in bli_obj_alloc_buffer() that caused an unnecessary "not yet implemented" abort() when creating a 1x1 object with non-unit strides. commit 7a8ad47fb2d100a9da93aa8cab774fcceeaab733 Author: Tyler Smith Date: Wed Oct 8 15:52:13 2014 -0500 Minor changes to knc configuration, including preference row major storage Also fixed a bug in the knc micro-kernel where it would fail if k == 0 commit 76b7c34af0c09f47d9615b18857a356acddc788a Author: Field G. Van Zee Date: Thu Oct 2 14:15:38 2014 -0500 Fixed a bug in the pack schema-related bit macros. Details: - Expanded the BLIS_PACK_SCHEMA_BITS value in bli_type_defs.h to include all six bits presently used in the pack schema bitfield of the info field of obj_t structs. Prior to this commit, the macro constant only included the lowest five bits, which excluded the "is or is not packed" bit. This manifested as a strange bug in probably many level-2 codes that invoked packing, though we only observed it in ger before fixing. Thanks to Devin Matthews for finding and reporting this bug. commit a5763e332226598d70c47dfa9cad4578e15ef5f4 Author: Field G. Van Zee Date: Thu Oct 2 13:28:17 2014 -0500 Added extra output to bli_obj_print(). Details: - Print extra values from info field of obj_t struct within bli_obj_print(). commit 9bba209fc44fbfce943ba6a51cd8278a0cb6b159 Author: Tyler Smith Date: Mon Sep 29 14:56:36 2014 -0500 Fixed bug when packing anywhere besides in blk_var_1 for gemm. commit 614a4afc9272adb47e5a8b83b39d56c2804d95d6 Merge: b541b667 4a7df04e Author: Tyler Smith Date: Fri Sep 26 10:49:57 2014 -0500 Merge branch 'master' of http://github.com/flame/blis commit 4a7df04e8a4ffdb9561d26426afd35e4fe15b013 Author: Field G. Van Zee Date: Mon Sep 22 16:06:15 2014 -0500 Added 30xk support for packm ukernels. Details: - Updated bli_kernel_*_macro_defs.h headers to include default definitions for 30xk packm kernels. - Extended function pointer arrays in bli_packm_cxk_*() out to 31 and included 30xk kernels. - Addex 30xk kernels to frame/1m/packm/ukernels/bli_packm_ref_cxk_*.c. commit b6d4bd792e0d44ce4b28afef343f5ff3ba89c285 Author: Field G. Van Zee Date: Mon Sep 22 16:02:37 2014 -0500 Fixed missing tabs from Makefile patch. commit 32630f9b6f0d5ba28d5b56dae4c7288a37158743 Author: Field G. Van Zee Date: Fri Sep 19 17:18:20 2014 -0500 Comment update to virtual micro-kernels. commit 13447cffead7c6d137a7a3ccbf9e552ed0477467 Author: Field G. Van Zee Date: Fri Sep 19 13:00:48 2014 -0500 Minor bugfix to top-level Makefile. Details: - Applied a patch that allows the top-level Makefile to work on certain systems. The patch simply separates out the source-to-object code generation rules for .c and .S files into two separate rules. Thanks to Devin Matthews for submitting this patch. commit e80a4537846416719c067ae08a53aeda978c572d Author: Field G. Van Zee Date: Thu Sep 18 10:24:20 2014 -0500 Fixed bug introduced by bugfix in 25b258d. Details: - We actually need to check alignment of lda*sizeof(double) and NOT a+lda because in the latter case, alignment could cancel out and still allow the optimized code to run when it shouldn't. Thanks to Devin for pointing this out. commit 25b258d61f9c8cee64e922f4131784b6edb196dd Author: Field G. Van Zee Date: Thu Sep 18 10:10:49 2014 -0500 Fixed a non-fatal problem with bugfix in a68b316c. Details: - The bugfix in a68b316c was inadvertantly checkin alignment of the leading dimension itself, rather than the byte size of the leading dimension. Now, we simply check alignment of a+lda. commit 96302d4fc81363410e41c3a3c43a65df44d97ad9 Author: Field G. Van Zee Date: Thu Sep 18 09:43:40 2014 -0500 Renamed bli_info_get_*_ukr_type() functions. Details: - Added _string() suffix to bli_info_get_*_ukr_type() function names. This makes them consistent with the bli_info_get_*_impl_string() functions. commit a68b316ca4852509f84ed50e01afac486bf70f58 Author: Field G. Van Zee Date: Wed Sep 17 11:10:07 2014 -0500 Fixed alignment bugs in level-1f kernels. Details: - Fixed bugs whereby the level-1f dotxf, axpyxf, and dotxaxpyf kernels were attempting to compute problems with unaligned leading dimensions with optimized code, rather than (correctly) using the reference implementations. Thanks to Devin Matthews for reporting this bug. commit 870761eb902e4866090d1d3446a345df3d6d4599 Merge: e9899be0 a2b59a37 Author: Field G. Van Zee Date: Tue Sep 16 18:20:49 2014 -0500 Merge branch 'master' of github.com:flame/blis commit e9899be09044829e23386bd73e394f1dd7778210 Author: Field G. Van Zee Date: Tue Sep 16 18:19:32 2014 -0500 Added high-level implementations of 4m, 3m. Details: - Added "4mh" and "3mh" APIs, which implement the 4m and 3m methods at high levels, respectively. APIs for trmm and trsm were NOT added due to the fact that these approaches are inherently incompatible with implementing 4m or 3m at high levels (because the input right-hand side matrix is overwritten). - Added 4mh, 3mh virtual micro-kernels, and updated the existing 4m and 3m so that all are stylistically consistent. - Added new "rih" packing kernels (both low-level and structure-aware) to support both 4mh and 3mh. - Defined new pack_t schemas to support real-only, imaginary-only, and real+imaginary packing formats. - Added various level0 scalar macros to support the rih packm kernels. - Minor tweaks to trmm macro-kernels to facilitate 4mh and 3mh. - Added the ability to enable/disable 4mh, 3m, and 3mh, and adjusted level-3 front-ends to check enabledness of 3mh, 3m, 4mh, and 4m (in that order) and execute the first one that is enabled, or the native implementation if none are enabled. - Added implementation query functions for each level-3 operation so that the user can query a string that describes the implementation that is currently enabled. - Updated test suite to output implementation types for reach level-3 operation, as well as micro-kernel types for each of the five micro- kernels. - Renamed BLIS_ENABLE_?COMPLEX_VIA_4M macros to _ENABLE_VIRTUAL_?COMPLEX. - Fixed an obscure bug when packing Hermitian matrices (regular packing type) whereby the diagonal elements of the packed micro-panels could get tainted if the source matrix's imaginary diagonal part contained garbage. commit a2b59a37f166f70a6dd5793db2530823ef590c2b Author: Tyler Smith Date: Mon Sep 15 10:44:44 2014 -0500 Fixed make defs so that they actually compile for bulldozer commit 86fc7e40764f78ec217f50216ef4fa5b57dbfbc7 Author: Tyler Smith Date: Mon Sep 15 10:35:46 2014 -0500 Added bulldozer configuration and updated piledriver micro-kernel commit 0644e61a79a57f136be5f4c47b9099cff2af06e0 Author: Field G. Van Zee Date: Thu Sep 11 12:55:34 2014 -0500 Minor updates to bli_packm_init.c. commit 9dc9b44a057a08e20ad4d423344f0ecad54c1eb2 Author: Field G. Van Zee Date: Thu Sep 11 12:03:28 2014 -0500 Renamed bli_obj_pack_status() to _pack_schema(). Details: - Renamed the bli_obj_pack_status() macro to bli_obj_pack_schema() in order to help avoid confusion as to what the macro returns. commit cf5efdde0588a0d5b6ea57fe7d7be5000be06f8e Author: Field G. Van Zee Date: Thu Sep 11 11:47:56 2014 -0500 Pass pack_t schemas into ukernels via auxinfo_t. Details: - Modified macro-kernels to pass the pack_t schema values for matrices A and B into the datatype-specific functions, where they are now inserted into a newly-expanded auxinfo_t struct. This gives gives the micro-kernels access to the pack_t schema values embedded in the control trees, which determine the precise format into which the matrix elements are packed. - Updated a call to bli_packm_init_pack() in src/test_libblis.c to remove densify argument. Meant to include this in commit c472993b. commit cc8d2b82775cca3c2d51bf427f4e77c8024a6d15 Author: Field G. Van Zee Date: Tue Sep 9 13:48:22 2014 -0500 Updated old test drivers in 'test'. commit c472993bbccb69e9ffc409c79b742426c8ad2ad4 Author: Field G. Van Zee Date: Tue Sep 9 13:42:04 2014 -0500 Removed densify argument to packm_cntl_obj_create(). Details: - Removed the "densify" bool_t argument to bli_packm_cntl_obj_create(). This argument was inserted very early in BLIS's development, when it was anticipated that the developer may sometimes wish to pack a Hermitian, symmetric, or triangular matrix without making it dense. But as it turns out, if we are packing a matrix, we always want to make it dense in some way or another due to the fact that the micro- kernel only multiplies dense micro-panels. Thus, unless/until there is a real need for the feature, it seems reasonable to remove it from the packm_cntl API. commit 5c43ee387146cd76dc59b730dac6683a8446b834 Author: Field G. Van Zee Date: Mon Sep 8 15:19:29 2014 -0500 Moved trmm4m/3m_cntl files to 'old' directory. Details: - Meant to include this in previous commit. commit 7b2f469d5465ed73b1ca88124bc9a1987388aa27 Author: Field G. Van Zee Date: Mon Sep 8 14:49:50 2014 -0500 Retired trmm_t control tree definitions, usage. Details: - Replaced all trmm_t control tree instances and usage with that of gemm_t. This change is similar to the recent retirement of the herk_t control tree. - Tweaked packm blocked variants so that the triangular code does NOT assume that k is a multiple of MR (when A is triangular) or NR (when B is triangular). This means that bottom-right micro-panels packed for trmm will have different zero-padding when k is not already a multiple of the relevant register blocksize. While this creates a seemingly arbitrary and unnecessary distinction between trmm and trsm packing, it actually allows trmm to be handled with one control tree, instead of one for left and one for right side cases. Furthermore, since only one tree is required, it can now be handled by the gemm tree, and thus the trmm control tree definitions can be disposed of entirely. - Tweaked trmm macro-kernels so that they do NOT inflate k up to a multiple of MR (when A is triangular) or NR (when B is triangular). - Misc. tweaks and cleanups to bli_packm_struc_cxk_4m.c and _3m.c, some of which are to facilitate above-mentioned changes whereby k is no longer required to be a multiple of register blocksize when packing triangular micro-panels. - Adjusted trmm3 according to above changes. - Retired trmm_t control tree creation/initialization functions. commit 576e9e9255a79dba9cd3c804267f51e0b4aa6e8a Author: Field G. Van Zee Date: Sun Sep 7 16:12:52 2014 -0500 Retired herk_t control tree definitions, usage. Details: - Replaced all herk_t control tree instances and usage with that of gemm_t, since the two types presently have the same fields. This means that herk, her2k, syrk, and syr2k can simply use the gemm control tree as-is, just as hemm and symm have been doing for some time now. - Retired herk_t control tree creation/initialization functions. - Retired many _target.c and .h files into 'old' directories. commit b2fed052c9a23d858ef0afbe220b342bce9aa7f7 Author: Field G. Van Zee Date: Wed Sep 3 17:07:25 2014 -0500 Minor code cleanup to bli_packm_struc_cxk*.c Details: - Realized that we don't need to track rs_p11 and cs_p11 for Hermitian/symmetric case of bli_packm_struc_cxk*(). They are always equal to rs_p and cs_p. commit 023ce770966b3b5a98bba729c5af1f45e15ebb97 Author: Field G. Van Zee Date: Wed Sep 3 10:47:53 2014 -0500 Minor update to packm_cxk kernels. Details: - Changed m and n dimension parameter names to panel_dim and panel_len, respectively, in packm_cxk, packm_cxk_3m, packm_cxk_4m kernel wrapper functions. This makes the code a little easier to read since "m" and "n" have connotations that are not applicable here. - Comment updates. commit 189def3667d9218adbeec45e2801fd074341a679 Author: Field G. Van Zee Date: Mon Sep 1 16:23:17 2014 -0500 Retired portions of bli_kernel_3m/4m_macro_defs.h. Details: - Removed sections of bli_kernel_[4m|3m]_macro_defs.h that defined 4m/3m-specific blocksizes after realizing that this can be done in bli_gemm[4m|3m]_cntl.c, since that is (mostly) the only place they are used. - The maximum cache values for 4m/3m are stll needed when computing mem pool dimensions in bli_mem_pool_macro_defs.h. As a workaround, "local" definitions in terms of the regular cache blocksizes are now in place. - Similarly, the register blocksizes for 4m/3m are still needed in bli_kernel_post_macro_defs.h. As a workaround, "local" definitions in terms of the regular register blocksizes are now in place. commit af521ee6f2a77d61c98b833e85c09969987bc00d Author: Field G. Van Zee Date: Mon Sep 1 14:06:46 2014 -0500 Changed semantics of blocksize extensions. Details: - Changed semantics of cache and register blocksize extensions so that the extended values are tracked, rather than just the marginal extensions. - BLIS_EXTEND_[MKN]C_? has been renamed BLIS_MAXIMUM_[MKN]C_?. - BLIS_EXTEND_[MKN]R_? has been renamed BLIS_PACKDIM_[MKN]R_?. - bli_blksz_ext_*() APIs have been renamed to bli_blksz_max_*(). Note that these "max" query routines grab the maximum value for cache blocksizes and the packdim value for register blocksizes. - bli_info_*() API has been updated accordingly. - All configurations have been updated accordingly. commit 07f23aefd52f5ba4960dbd46e59b180a2136b8e9 Author: Field G. Van Zee Date: Sun Aug 31 11:58:50 2014 -0500 Pass pack schema into packm_struc_cxk*(). Details: - Changed the interface to the packm_struc_cxk*() kernels to include the pack_t schema. This allows the implementation to more easily determine how the micro-panel is stored (row-stored column panel or column-stored row panel). - Updated packm blocked variants to pass in the schema. - Updated packm_ker_t function pointer definition accordingly. commit f032ba9b1186cb02184574d339565f53d733aa42 Author: Field G. Van Zee Date: Sat Aug 30 16:21:20 2014 -0500 Reorganized packm implementation. Details: - Reorganized packm variants and structure-aware kernels so that all routines for a given pack format (4m, 3m, regular) reside in a single file. - Renamed _blk_var4 to _blk_var2 and generalized so that it will work for both 4m and 3m, and adjusted 4m/3m _cntl_init() functions accordingly. - Added a new packm_ker_t function pointer type to bli_kernel_type_defs.h to facilitate function pointer typecasting in the datatype-specific packm_blk_var2() functions. - Deprecated _blk_var3. - Fixed a bug in the triangular micro-panel packing facility that affected trmm and trmm3 with unit diagonals. commit c6793cecb70788bdf2c76ab8102504ea97be9d2a Author: Field G. Van Zee Date: Thu Aug 28 17:14:48 2014 -0500 Reorganized #includes for scalar macro headers. Details: - Reordered the #include statements in bli_scalar_macro_defs.h so that conventional, ri-, and ri3-based macros are grouped together. - Renamed bli_eqri.h (and macros within) to end with 'ris' suffix. commit b4da8907284345be4374f87a88679c4886ab866e Author: Field G. Van Zee Date: Thu Aug 28 14:10:32 2014 -0500 Whitespace, comments updates on packm_blk_var?.c. commit 46e46a1d83da586c3dd9fd7a01eb16067abbaee1 Author: Field G. Van Zee Date: Thu Aug 28 12:05:45 2014 -0500 Minor updates to packm blocked, cxk_3m/4m code. Details: - Added 'const' qualifier to inlined packing code that handles micro-panel packing that is too large for an existing packm ukernel. - Comment updates. commit 908dc688b5979995eaacb3aa937f241551a8df00 Author: Field G. Van Zee Date: Thu Aug 28 11:55:12 2014 -0500 Pass pack schema into blocked packm routines. Details: - Rather than passing the packm blocked routines a boolean value that represents whether the matrix is being packed to row or column storage, we now pass in the pack schema itself. commit a0ff6066e06075ab5f92b19247b39b92ed15f1bf Merge: c4c99c48 d40b32bc Author: Field G. Van Zee Date: Sun Aug 24 15:56:21 2014 -0500 Merge branch 'master' of github.com:flame/blis commit c4c99c4813bf9817592a7899c5d33412fe22313f Author: Field G. Van Zee Date: Sun Aug 24 15:52:22 2014 -0500 Renamed packm scalar from beta to kappa. Details: - The packm implementation (i.e. sources files in frame/1m/packm and frame/1m/packm/ukernels), interchangeably used the names "beta" and "kappa" to refer to the optional scalar to be applied during packing. This commit renames all uses of "beta" to be "kappa", since "beta" sometimes evokes the scalar specifically on the output matrix of a level-2 or level-3 operation. commit d40b32bc24ffbae24123e054307b3138969bb095 Merge: 9331f794 6c25c379 Author: Field G. Van Zee Date: Sun Aug 24 13:46:36 2014 -0500 Merge branch 'master' of github.com:flame/blis commit 6c25c379fadb50834146e1614f7b80c093c2aad0 Author: Field G. Van Zee Date: Sun Aug 24 13:44:10 2014 -0500 Consolidated unpackm ukernels into single file. Details: - Reorganized unpackm ukernels into a single file, bli_unpackm_ref_cxk.c, in a manner similar to what was done for packm ukernels in commit 4cc2b46. commit 9331f79443223fe267676ee54c439e1ed320380c Merge: 7fc48a7d 670b6392 Author: Field G. Van Zee Date: Sun Aug 24 10:54:21 2014 -0500 Merge branch 'master' of github.com:flame/blis commit 670b63926a7f4fc694abc5b1582ef8a4f367f5a8 Author: Field G. Van Zee Date: Sun Aug 24 10:46:27 2014 -0500 Added whitespace to bli_obj_scalar_ routine calls. Details: - Added extra spaces to align arguments of bli_obj_scalar_init_detached_copy_of(). This misalignment was due to the fact that the function was previously named bli_obj_init_scalar_copy_of() and the name change, performed in b444489f, was done via recursive sed commands which left subsequent lines untouched. commit 7fc48a7d920e07fd8e9528ab2565123f8f4e67f9 Author: Field G. Van Zee Date: Sat Aug 23 16:50:58 2014 -0500 Combined 4m/3m bits into an expanded bitfield. Details: - Combined the 4m/3m bits into an expanded bitfield, which will encode the packing "format" of the micro-panels. This will allow for more easily and compactly encoding additional formats. - Other minor comment/whitespace updates to bli_type_defs.h. - Updated bli_obj_macro_defs.h and bli_param_macro_defs.h to use the new format bitfield. - Comment update to bli_kernel_post_macro_defs.h. - Whitespace changes to bli_kernel_3m_macro_defs.h, _4m_macro_defs.h. commit ef0143cc1417e4815e4cafd5a464cc83fe7a1e86 Author: Field G. Van Zee Date: Sat Aug 23 14:02:27 2014 -0500 Renamed _ri, _ri3 packm ukernels to _4m, _3m. Details: - Renamed packm ukernels, _cxk dispatcher, and structure-aware _cxk helper functions to use _4m and _3m instead of _ri and _ri3 suffixes. - Updated names of cpp macros that correspond to packm ukernels. commit b0ccac116158b5ed3316d34798748ba0c6d78672 Author: Field G. Van Zee Date: Thu Aug 21 19:21:52 2014 -0500 Cleaned up front-end layering for 4m/3m. Details: - Added an extra layer to level-3 front-ends (examples: bli_gemm_entry() and bli_gemm4m_entry()) to hide the control trees from the code that decides whether to execute native or 4m-based implementations. The layering was also applied to 3m. - Branch to 4m code based on the return value of bli_4m_is_enabled(), rather than the cpp macros BLIS_ENABLE_?COMPLEX_VIA_4M. This lays the groundwork for users to be able to change at runtime which implementation is called by the main front-ends (e.g. bli_gemm()). - Retired some experimental gemm code that hadn't been touched in months. commit bedec95451cabfa7a8906b51018a5e0572998a5e Author: Field G. Van Zee Date: Thu Aug 21 18:25:48 2014 -0500 Added bli_4m API for querying 4m enabled state. Details: - Added bli_4m.c (and header), which defines a simple API that can be used to query, enable, and disable 4m-based complex support in BLIS. The macros BLIS_ENABLE_?COMPLEX_VIA_4M are now used to initialize the variable that determines the state (enabled or disabled). - Changed bli_info*() API so that all cache and register blocksize- related query routines return the blksz_t objects' values as they exist at runtime, rather than return the values as determined by the configuration system (e.g. bli_kernel.h, or defaults for those values not specified). This sets the foundation for being able to change those blocksizes at runtime. commit b541b667cabfa6d41b50ad1e49209651ee6812cc Merge: 699a8151 dd61307f Author: Tyler Smith Date: Wed Aug 20 14:44:51 2014 -0500 Merge branch 'master' of http://github.com/flame/blis Conflicts: frame/3/trsm/bli_trsm_blk_var2b.c frame/3/trsm/bli_trsm_blk_var2f.c commit 699a8151ca3d5021e834a1784ef45dcc3a3d17cd Author: Tyler Smith Date: Wed Aug 20 14:43:17 2014 -0500 Some improvements to trsm parallelism commit dd61307f55bb6bc762fe0ef0446479d6c0536723 Author: Field G. Van Zee Date: Wed Aug 20 09:52:16 2014 -0500 Minor update to sandybridge MC_S, KC_S. Details: - Changed sandybridge MC and KC for single-precision real to 128 and 384, respectively. - Updated comments in template configuration's gemm micro-kernel file to document the new "contiguous row preference" macro. commit d0eec4bddd740ce360d0f655362c551287cf925b Author: Field G. Van Zee Date: Tue Aug 19 15:49:19 2014 -0500 Added optional row preference to ukernel config. Details: - Added the ability for the kernel developer to indicate the gemm micro- kernel as having a preference for accessing the micro-tile of C via contiguous rows (as opposed to contiguous columns). This property may be encoded in bli_kernel.h as BLIS_?GEMM_UKERNEL_PREFERS_CONTIG_ROWS, which may be defined or left undefined. Leaving it undefined leads to the default assumption of column preference. - Changed conditionals in frame/3/*/*_front.c that induce transposition of the operation so that the transposition is induced only if there is disagreement between the storage of C and the preference of the micro-kernel. Previously, the only conditional that needed to be met was that C was row-stored, which is to say that we assumed the micro- kernel preferred column-contiguous access on C. - Added a "prefers_contig_rows" property to func_t objects, and updated calls to bli_func_obj_create() in _cntl.c files in order to support the above changes. - Removed the row-storage optimization from bli_trsm_front.c because it is actually ineffective. This is because the right-side case of trsm flips the A and B micro-panel operands (since BLIS only requires left-side gemmtrsm/trsm kernels), meaning any transposition done at the high level is then undone at the low level. - Tweaked trmm, trmm3 _front.c files to eliminate a possible redundant invocation of the bli_obj_swap() macro. commit 4cc2b464f29cafbfef9295b073b857fe0752f710 Author: Field G. Van Zee Date: Fri Aug 15 11:49:15 2014 -0500 Reorganized packm ukernels. Details: - Previously, packm micro-kernels were organized by the implied register blocksize (panel dimension) assumed by the kernel, meaning conventional, ri, and ri3 variations of some micro-kernel size were housed in the same file. This commit reorganizes the micro-kernels so that all sizes reside in the same file for each format type (conventional, ri, and ri3). commit fcc10054a11b6fc3976986f57feccf741596cbf6 Author: Field G. Van Zee Date: Wed Aug 13 12:32:06 2014 -0500 Tweaks to gemm4m, gemm3m virtual ukernels. Details: - Fixed a potential, but as-yet unobserved bug in gemm3m that would allow undesirable inf/NaN propogation, since C was being scaled by beta even if it was equal to zero. - In gemm3m micro-kernel, we now avoid copying C to the temporary micro-tile if beta is zero. - Rearranged computation in gemm4m so that the temporary C micro-tile is accessed less, and C is accessed only after the micro-kernel calls. This improves performance marginally in most situations. - Comment updates to both gemm4m and gemm3m micro-kernels. commit cdcbacc2fa871317c8e7ef961ecc6d70ab22dc34 Author: Field G. Van Zee Date: Tue Aug 12 12:45:38 2014 -0500 Removed redundant redef of packm ukr prototypes. Details: - Removed redundant macro code that redefined packm ukernel prototypes when the previous macro was already sufficient. This helps de-clutter the packm ukernel prototyping headers a little bit. commit 82dac98d9032ccb598068a55ddf23d7898491e9e Author: Field G. Van Zee Date: Tue Aug 12 12:36:25 2014 -0500 Relocated packm ukernel #includes. Details: - Consolidated the #include statements for packm ukernel headers from bli_packm_cxk.h, bli_packm_cxk_ri.h, and bli_packm_cxk_ri3.h to bli_packm.h. - Comment/whitespace updates to bli_packm_blk_var3.c, _var4.c. commit 7f77856e25aad5fc6f172ed3e57b6351804e31a4 Author: Field G. Van Zee Date: Tue Aug 12 12:20:15 2014 -0500 Removed unused 4m/3m-related packm macro defs. Details: - Removed unused and unneeded s- and d-flavored macro definitions for packm ukernels related to the complex 4m and 3m methods, as implemented in BLIS. commit bc1d86b2d4d436b1dfba2d0098501aaca9cbb8b5 Author: Field G. Van Zee Date: Thu Aug 7 19:01:20 2014 -0500 Sandy Bridge configuration, micro-kernel update. Details: - Minor updates to bli_config and bli_kernel.h for sandybridge configuration. - Renamed existing AVX intrinsic-based micro-kernel file to bli_gemm_int_d8x4.c. - Added new file, bli_gemm_asm_d8x4.c, which provides assembly-based gemm micro-kernels for single- and double-precision real. commit 98ec95877a95242e159b2bf0c879115a59e4c6e2 Author: Field G. Van Zee Date: Thu Aug 7 18:28:32 2014 -0500 Corrected comment for _obj_is_[row|col]_stored(). Details: - Fixed a mistake in the comments introduced in the previous commit for bli_obj_is_row_stored() and bli_obj_is_col_stored(). commit 43d5e419e1b424d2143817103dbee8ead797e8aa Author: Field G. Van Zee Date: Thu Aug 7 18:20:40 2014 -0500 Reverted _obj_is_[row|col]_stored() macros. Details: - Rolled back recent changes to bli_obj_is_row_stored() and bli_obj_is_col_stored() so that those macros now only inspect the strides (row or column). It turns out that the more sophisticated definitions introduced in a51e32e are not necessary, because these "obj" macros are virtually never used on packed matrices, and when they are, they can use bli_obj_is_[row|col}_packed() macros, which inspect the info bitfield. commit 45692e3ad4b7e1d05ac4302398df4efce04b4284 Author: Field G. Van Zee Date: Thu Aug 7 13:21:15 2014 -0500 Reverted some accidental changes. Details: - Reverted some changes that were unintentionally included in the previous commit (9526ce98). Thanks to Tony Kelman for pointing this out. (Note: a few select changes were not reverted.) commit 9526ce98812be908bc4915f2849b657fb6ce1b49 Author: Field G. Van Zee Date: Wed Aug 6 14:13:46 2014 -0500 Updated copyright headers of emscripten configuration files. commit 30833ed71d56f231ddba21e632bcbbc90b12a97c Author: Field G. Van Zee Date: Wed Aug 6 12:12:03 2014 -0500 Minor edits to configurations' make_defs.mk files. Details: - Redefined CFLAGS, CFLAGS_NOOPT, and CFLAGS_KERNELS so that CFLAGS_NOOPT is defined first and then the other two are defined in terms of CFLAGS_NOOPT. This textually cleans up the definitions and makes them a little easier to read. commit 9d61afeae2ba70fe1df07e7546f6954ea83aed12 Author: Field G. Van Zee Date: Mon Aug 4 16:01:59 2014 -0500 CHANGELOG update (0.1.5) commit bde56d0ecfd0ec20330fac290b91a6dca0cf94e9 (tag: 0.1.5) Author: Field G. Van Zee Date: Mon Aug 4 16:01:58 2014 -0500 Version file update (0.1.5) commit 4c6ceea4be35d089630986eb5b959b9e97214077 Author: Field G. Van Zee Date: Mon Aug 4 15:49:59 2014 -0500 Added CBLAS compatibility layer. Details: - Added a new section in bli_config.h files of all configurations for enabling CBLAS support. (Currently, the default is for the CBLAS layer to be disabled.) - Added a directory, frame/compat/cblas, to house CBLAS source code. A subdirectory 'f77_sub' holds subroutine wrappers corresponding to subroutines found in CBLAS that allow calling some BLAS routines with the return value passed as the last argument rather than as an actual (function) return value. This was probably intended to allow CBLAS to avoid the whole f2c debacle altogether. However, since BLIS does not assume the presence of a Fortran compiler, we had to provide similar routines in C. - A script, integrate-cblas-tarball.sh, is included to streamline the integration of future revisions of the CBLAS source code. - The current tarball, cblas.tgz, that was used with the above script to generate the present set of CBLAS source code is also included. - Updated blis.h to include necessary CBLAS-related headers. commit caab62dac0fb0bd0d674118f409c81680db94d29 Merge: 383631b5 db97ce97 Author: Field G. Van Zee Date: Sun Aug 3 14:36:18 2014 -0500 Merge pull request #19 from kevinoid/fix-install-perms-error Fix permissions error installing to non-owned directory commit db97ce979b88c051922c2f946ce52d523c7a12c6 Author: Kevin Locke Date: Sun Aug 3 12:48:04 2014 -0600 Fix permissions error installing to non-owned directory When installing to a directory which is not owned by the installing user, even when the user has write permission for the directory, the installation can fail with an error similar to the following: Installing libblis-0.1.4-7-sandybridge.a into /usr/local/lib/ install: cannot change permissions of ‘/usr/local/lib’: Operation not permitted Makefile:658: recipe for target '/usr/local/lib/libblis-0.1.4-7-sandybridge.a' failed make: *** [/usr/local/lib/libblis-0.1.4-7-sandybridge.a] Error 1 In the example case, the error occurred because the user attempted to install to /usr/local and /usr/local/lib is owned by root with mode 2755 which the Makefile unsuccessfully attempted to change to 0755. Given that installing to /usr/local is likely to be quite common and the ownership/permissions are the default for Debian and Debian-derived Linux distributions (perhaps others as well), this commit attempts to support that use case by using mkdir rather than install to create the directory (which is the same approach as Automake). Signed-off-by: Kevin Locke commit 383631b514c3d42b724640f57644eea276cc418c Author: Field G. Van Zee Date: Thu Jul 31 14:51:48 2014 -0500 Redefined bit field macros with bitshift operator. Details: - Redefined many of the macros that define bit fields and bit values in the obj_t info field using the bitshift operator (<<). This makes it easier to reorder bit fields, or expand existing bit fields, or add new fields. The bitshifting should be evaluated by the compiler at compile-time. commit 137143345dc93cc9a83da5ba88b25bac7502de86 Author: Field G. Van Zee Date: Thu Jul 31 12:12:45 2014 -0500 Reimplemented unit blocksize fix in prev commit. Details: - Instead of inferring the storage format of the micro-panels from within the packm variants, we now pass in a bool_t value that denotes whether the packed matrix contains row-stored column panels or column-stored row panels. This value can then be tested more easily inside the main packm variant loop. - Renumbered pack_t schema values in bli_type_defs.h so that there are now five bits, each with different meaning: - 4: packed or not packed? - 3: packed for 3m? - 2: packed for 4m? - 1: packed to panels? - 0: stored by rows or columns? - Added new macros that test for status of above bits in schema bit subfield, and renamed some existing macros related to 4m/3m. commit a51e32ec061941cd10119ea80115c82a40b1673f Author: Field G. Van Zee Date: Wed Jul 30 10:41:48 2014 -0500 Fixed unit register blocksize brokenness. Details: - Fixed a breakdown in BLIS's ability to differentiate between row-stored and column-stored micro-panels when MR or NR is unit. When either register blocksize (or both) is equal to one, inspecting the strides of the affected packed micro-panel is no longer sufficient to determine whether the micro-panel is a row-stored column panel or a column-stored row panel (because both strides are unit). At that point, dimension information is necessary when invoking the bli_is_row_stored_f() and bli_is_col_stored_f() macros (and their "obj" counterparts). Thanks to Ilya Polkovnichenko for reporting this bug. - Added panel dimensions (m and n) to obj_t, which are set in packm_init() and then passed into the blocked variants to support the aforementioned update. commit c2732272f0ac680a0ad19fa9db5d587398a1479a Author: Field G. Van Zee Date: Tue Jul 29 16:37:18 2014 -0500 Removed old/unused packm variants. commit b97fa9a5a70fe0123e5eebd999b947461d38445f Author: Field G. Van Zee Date: Sun Jul 27 18:54:09 2014 -0500 Minor usage update to build/bump-version.sh. commit b18ba5f62d98629cdd519ff4c96fc67ec1a62fb9 Author: Field G. Van Zee Date: Sun Jul 27 18:52:05 2014 -0500 Added missing 'bla_' prefix to r_imag(), d_imag(). Details: - Added "bla_" to f2c functions r_imag() and d_imag(). Thanks to Murtaza Ali for pointing the mis-named functions. commit af7a8e6c042cade452130a6729377f1a3ef4e19e Author: Field G. Van Zee Date: Sun Jul 27 18:20:13 2014 -0500 CHANGELOG update (0.1.4) commit a7537071b152ecff671f8716595d37dc09e4fd51 (tag: 0.1.4) Author: Field G. Van Zee Date: Sun Jul 27 18:20:12 2014 -0500 Version file update (0.1.4) commit acff74041bf02c7b9fdfa24b507bca782a4c5fce Merge: cdb9413e 47b243ef Author: Tyler Smith Date: Wed Jul 23 15:07:30 2014 -0500 Merge branch 'master' of https://github.com/flame/blis commit cdb9413e140f8a198666250ec88fa34b5425a9c3 Author: Tyler Smith Date: Wed Jul 23 15:05:15 2014 -0500 Enabled threading for a couple more loops in TRSM JC loop is now enabled for the left-sided case IC loop is now enabled for the right-sided case commit 47b243ef08f4101de3d936f2373343e67eaa4dd5 Author: Field G. Van Zee Date: Wed Jul 23 13:41:13 2014 -0500 Call setid for early return from herk/her2k. Details: - Added setid call (to zero imaginary parts of diagonal elements) to early return branches of herk_front() and her2k_front() for cases where alpha is zero. Thanks to Murtaza Ali for suggesting this fix. - Comment update. commit 3e7b0db5b0e24f5fd66c60bacabc019885ddbec5 Merge: 2f8a357d ed3e33d5 Author: Tyler Smith Date: Wed Jul 23 13:40:44 2014 -0500 Merge branch 'master' of https://github.com/flame/blis commit 2f8a357de5fb55163a969d888cf059f24b78125c Author: Tyler Smith Date: Wed Jul 23 13:40:12 2014 -0500 Some TRSM threading fixes/additions commit ed3e33d548047be3283ff41268fdf716563bc542 Author: Field G. Van Zee Date: Tue Jul 22 14:40:43 2014 -0500 Tweaked behavior of herk, her2k for BLAS compat. Details: - Updated herk_front() and her2k_front() to explicitly set the imaginary components of the diagonal entries of C to zero after the computation is complete. This is needed in case downstream applications read the full diagonal entries (i.e., including imaginary part), which could, in the absence of this modification, accumulate numerical error from subsequent rank-k/rank-2k updates. - Updated BLAS compatibility wrappers for herk and her2k to return early if: n == 0 || ( ( alpha == 0 || k == 0 ) && beta == 1 ) This also results in the imaginary components of diagonal entries NOT being set to zero (see above), which is consistent with BLAS. - Updated mkherm to use setid instead of an inlined loop over the diagonal. commit ea59a5c93cde1467a3715abc53dda4aecf961873 Author: Field G. Van Zee Date: Tue Jul 22 14:36:02 2014 -0500 Added new level-1d operation: setid. Details: - Defined a new level-1d operation, setid, which sets the imaginary elements of an object's diagonal to a single scalar. This can be useful, for example, when trying to make the diagonal of a Hermitian matrix real-valued. commit 8965a965931318619ceaebd7c32edccf3022d0c7 Merge: 1785efb5 5b73e80b Author: Field G. Van Zee Date: Tue Jul 22 14:34:32 2014 -0500 Merge branch 'master' of github.com:flame/blis commit 1785efb5420bc7b9c850a068cb5d99837071e877 Author: Field G. Van Zee Date: Tue Jul 22 14:33:01 2014 -0500 Minor improvements to invertd and setd. Details: - Added missing call to invertd_check() from front-end. - Changed setd front-end call of scald_check() to setd_check(). commit 5b73e80b71c054c1945a06aff044ef629bc1a9a0 Merge: a41e68e0 20690fe3 Author: Field G. Van Zee Date: Fri Jul 18 12:21:20 2014 -0500 Merge pull request #16 from Maratyszcza/emscripten Emscripten port commit a41e68e09e73b999fab0bb430a43dccfc63aab45 Author: Field G. Van Zee Date: Thu Jul 17 13:25:56 2014 -0500 Reimplemented BLIS initialization/finalization. Details: - Rewrote bli_init() and bli_finalize() with OpenMP critical sections for thread-safety. Also added lots of explanatory comments. - Renamed bli_init_safe() and bli_finalize_safe() with the _auto() suffix, and reimplemented for simplicity. Updated all invocations in BLAS compatibility layer to use _auto() suffix. commit 36358948ea75074bda32a9f8c008f835b87d21db Author: Field G. Van Zee Date: Thu Jul 17 10:58:10 2014 -0500 Retired frame/3/gemm/other directory. Details: - Removed frame/3/gemm/other directory, which contained some outdated and/or experimental variants. commit c73261f17edf589e76bdbe297702a1fbbd69275f Author: Field G. Van Zee Date: Mon Jul 14 16:23:51 2014 -0500 More minor cleanups post-copyright update. commit 2a09d24463d358be6243b24f112fad057c2aefe0 Author: Field G. Van Zee Date: Mon Jul 14 16:17:09 2014 -0500 Reverted power7 symlinks destroyed by sed script. Details: - Reverted two symlinks, in kernels/power7/3/test, back to being symlinks after recursive-sed.sh mistakenly replaced them with copies of the actual files to which they referred. Meant to include this in previous commit. commit 7ed415824d3b2e78541b6f64e404ca5347c06d3d Author: Field G. Van Zee Date: Mon Jul 14 16:14:33 2014 -0500 Updated copyright headers (continued). Details: - Inserted "at Austin" into third clause of license declarations. Meant to include this change in previous commit. commit 5c2c6c85616834ff2716ece083118201d9df6dde Author: Field G. Van Zee Date: Mon Jul 14 16:05:03 2014 -0500 Updated copyright headers to contain "at Austin". Details: - Updated copyright headers to include "at Austin" in the name of the University of Texas. - Updated the copyright years of a few headers to 2014 (from 2011 and 2012). commit fcec68cda3f6e90ae055e7304e6674c1c5c8d010 Merge: 94c0df79 4a20ed1a Author: Field G. Van Zee Date: Mon Jul 14 11:35:34 2014 -0500 Merge branch 'master' of github.com:flame/blis commit 94c0df797eda377931f29a41ba6a89c0ed58daca Author: Field G. Van Zee Date: Mon Jul 14 11:24:36 2014 -0500 Changed order of zero dim / error checking. Details: - Updated level-2 and level-3 internal back-ends so that the operation's _check() function is called BEFORE any attempt to return early due to the presence of zero dimensions. This ordering makes more sense because (for example) object dimensions should match even if one of them is zero. Previously, a dimension mismatch could result in an early return with no error message. - Updated bli_check_object_buffer() so that NULL buffers result in an error only if the object is dimensionally non-empty (i.e., only if both of the object's dimensions are non-zero). This allows BLIS operations to be performed on dimensionally empty objects (i.e., where at least one dimension is zero). - Updated the error message associated with bli_check_object_buffer() to mention the newly relaxed constraint mentioned above, vis-a-vis non-zero dimensions. commit 20690fe3018ce17c8df61ce0bffecaa7911dc3a5 Author: Marat Dukhan Date: Sun Jul 13 22:50:56 2014 -0700 Emscripten port commit 4a20ed1a3f5e9e5232df30aa0e568e6c00c56ce1 Merge: 6a515e98 8ccdfaef Author: Field G. Van Zee Date: Sun Jul 13 17:45:01 2014 -0500 Merge pull request #14 from Maratyszcza/master Support "make test" for PNaCl configuration commit 6a515e988f2ae1628258a6dec2c0e9cf2d04790f Author: Field G. Van Zee Date: Sun Jul 13 17:38:33 2014 -0500 Implemented dsdot() and sdsdot() in compat layer. Details: - Replaced "not yet implemented" error messages in dsdot() and sdsdot() with actual implementations. (These routines are so rarely used that this log message will probably lead to some people learning of their existence for the first time.) commit 255668ddd1004552c6cc65035ec6486671ce99bb Author: Field G. Van Zee Date: Sun Jul 13 17:30:44 2014 -0500 Inserted gemv beta-scaling bug into compat layer. Details: - BLAS has a peculiar bug (or feature) whereby calling gemv on a vector y of non-zero length and a vector x of zero length results in no action. Given that the operation is y := beta*y + A*x, many (most?) individuals would expect vector y to still be scaled by beta. BLIS, when called natively, handles these cases intuitively (with beta scaling). Unfortunately, many BLAS test suites actually check for the way this situation is handled. Therefore, we have decided to implement this "bug" in the compatibility layer so as to provide "bug-for-bug" compatibility with BLAS. commit 570a154581bdb353fa13a219c7cb3c81d3dceffd Author: Field G. Van Zee Date: Sat Jul 12 17:51:05 2014 -0500 Comment/formatting updates to build scripts. Details: - Minor updates to comments and formatting in bump-version.sh and update-version-file.sh scripts. commit 26cd81990631ff799791629206e068126ff9e3a1 Author: Field G. Van Zee Date: Thu Jul 10 13:16:07 2014 -0500 Added bli_info_*() query functions. Details: - Added a new API family, bli_info_*(), which can be used to query information about how BLIS was configured. Most of these values are returned as gint_t, with the exception of the version string which is char*. - Changed how the testsuite driver queries information about how BLIS was configured (from using macro constants directly to using the new bli_info API). - Removed bli_version.c and its header file. - Added STRINGIFY_INT() macro to bli_macro_defs.h - Renamed info_t type in bli_type_defs.h to objbits_t (not because of an actual naming conflict, but because the name 'info_t' would now be somewhat misleading in the presence of the new bli_info API, as the two are unrelated). commit 970b43141697d8c31a033f59513bb59d7cc78ab0 Author: Field G. Van Zee Date: Thu Jul 10 09:30:00 2014 -0500 Minor bugfixes to BLAS compatibility layer. Details: - Changed bla_amax.c so that i?amax() routines now correctly return 0 if ( n < 1 || incx <= 0 ). - Changed bla_rotg.c and bla_rotmg.c to use bli_fabs() macro instead of f2c's abs() macro for float and double cases. - Thanks to Murtaza Ali for suggesting the two fixes above. - Updated label of fnormv to normfv in testsuite/input.operations. commit 8ccdfaef4c42ad8957af8607a1a9ee29b9277d4b Author: Marat Dukhan Date: Tue Jul 8 23:14:36 2014 -0700 Replicated logic from testsuite/Makefile in top-level Makefile to support make test commit caa6507ff3724c80d60987f309b8bbc5b50a9841 Author: Field G. Van Zee Date: Tue Jul 8 10:25:27 2014 -0500 Minor cleanup to standalone test drivers. Details: - Very minor code changes to standalone test drivers in 'test' directory. - Added *.so files to '.gitignore'. commit 6c65e9a58fe55990ebb99ec3986443e18af35338 Merge: cb12e456 daca500d Author: Field G. Van Zee Date: Tue Jul 8 10:13:49 2014 -0500 Merge branch 'master' of github.com:flame/blis commit cb12e456f94c196c093e52f02a7cbca0032fc86e Author: Field G. Van Zee Date: Tue Jul 8 10:07:46 2014 -0500 Fixed possible level-3 inf/NaN issue when beta=0. Details: - Redefined xpbys_mxn and xpbys_mxn_u/_l macros to employ a copy (instead of scaling by beta) when beta is zero. This will stamp out any possible infs or NaNs in the output matrix, if it happens to be uninitialized. Thanks to Tony Kelman for isolating this bug. commit daca500db5e2448ba0da8047b75eb0f88d9f40e3 Merge: ab3bc915 47023502 Author: Tyler Smith Date: Thu Jul 3 12:52:52 2014 -0500 Merge branch 'master' of http://github.com/flame/blis commit 4702350278af31f662b458127777dd4d85a3192f Author: Field G. Van Zee Date: Thu Jul 3 11:48:23 2014 -0500 Defined _ukernel_void() wrappers to micro-kernels. Details: - Added wrappers for micro-kernels so that users may invoke the micro-kernels without knowing what the function names actually are. This is useful when an application wishes to call the micro-kernel from a shared library instance of BLIS, where the application may not necessarily have the luxury of grabbing the micro-kernel name(s) from C preprocessor macros at compile-time. Also, since the wrappers use void* pointers, one's environment does not need to be aware of some BLIS types such as scomplex and dcomplex. These wrappers now join the level-1 and level-1f kernel wrappers, which pre-dated this commit. - Removed the wrapper definitions and prototypes from the micro-kernel test suite modules, and replaced calls to them with calls to the new wrappers mentioned above. commit ab3bc9153b914fbaf259e15b66c91d628e7c8661 Author: Tyler Smith Date: Thu Jul 3 11:19:43 2014 -0500 Fixed a bug for TRSM when BLIS_ENABLE_MULTITHREADING is not set but the multithreading environment variables are turned on commit b8134b720b985783ee6a582a3eb5d6c51f00d051 Author: Tyler Smith Date: Wed Jul 2 16:02:39 2014 -0500 Quick and dirty multithreading for TRSM Should work fine for small number of threads (up to 8 or maybe even 16). However, performance is yet untested. This parallelizes the "JR" loop for the left sided cases and the "IR" loop for the right sided cases. Future work is to parallelize the outer loops as well. commit e8ef69692831db07ddbe9485a5e504ac3f03e496 Author: Field G. Van Zee Date: Wed Jul 2 14:59:27 2014 -0500 Added shared library support to build system. Details: - Modified top-level Makefile to support building shared (dynamic) libraries. - Updated most configurations' make_defs.mk files to include necessary compiler/linker flags needed by top-level Makefile. - Note that by default, all configurations presently do NOT build shared libraries. To enable, one must change the value of BLIS_ENABLE_DYNAMIC_BUILD to 'yes'. commit b80df0f2cffb015da02e70a82b8512da9891ab67 Author: Field G. Van Zee Date: Mon Jun 23 13:52:39 2014 -0500 Added bump-version.sh script to 'build' directory. Details: - Added a bash script, bump-version.sh, to aid in incrementing the BLIS version string. commit 9ef1f1e21d083697fc730e48d7d9169c201f3da2 Author: Field G. Van Zee Date: Mon Jun 23 13:48:17 2014 -0500 CHANGELOG update (0.1.3) commit 036cc634918463b1caa0fd89c9a211f2f5639af7 (tag: 0.1.3) Author: Field G. Van Zee Date: Mon Jun 23 13:48:17 2014 -0500 Version file update (0.1.3) commit 09d9a3bf6763932d9f571085b2cfd1b8631eccba Author: Field G. Van Zee Date: Mon Jun 23 13:43:26 2014 -0500 Reverting version file to test new version script. Details: - Changed version file contents to 0.1.2 so that I can test out a new version file bumping script. commit ebb33965981dcb2b0bdee5fc7fdf6c959420f311 Author: Field G. Van Zee Date: Mon Jun 23 11:22:50 2014 -0500 Added 'version' file. commit 2cb9a5501a3cbeb6692cf68e896087ba73b6af69 Author: Field G. Van Zee Date: Mon Jun 23 10:42:29 2014 -0500 Removed 'version' from .gitignore file. commit b40dcefc5ee31f67aa3990e2e9d2ef8ed1386a25 Merge: 7101a8ee b693b0cd Author: Field G. Van Zee Date: Mon Jun 23 10:39:05 2014 -0500 Merge pull request #11 from Maratyszcza/stable [sc]axpy kernels for PNaCl commit b693b0cddcfb41450e3c09a3ab97acb44c1ccdec Author: Marat Dukhan Date: Sun Jun 22 13:44:25 2014 -0700 [SC]AXPY kernels for PNaCl commit 7101a8eec0327d6c3a7eb36eb4b0fd45c1c6d162 Merge: ad48dca2 020a831b Author: Field G. Van Zee Date: Thu Jun 19 21:46:50 2014 -0500 Merge pull request #10 from Maratyszcza/stable Portable Native Client port commit 020a831bc5f61744cb8354886aa679b99b1285f6 Author: Marat Dukhan Date: Thu Jun 19 00:58:26 2014 -0700 Code clean-up in PNaCl port commit 491be4f91ed725522f5cc7184053857c6c376ada Author: Marat Dukhan Date: Thu Jun 19 00:45:44 2014 -0700 Optimized dot product kernels for PNaCl commit 4b8e71aab80182873a2e138eb07902b8d8fd5480 Author: Marat Dukhan Date: Thu Jun 19 00:43:25 2014 -0700 Use AR rcs flags for PNaCl target to avoid warning commit 031deb2a5c718d569bde842590a791b812f4cf1d Author: Marat Dukhan Date: Wed Jun 18 03:11:34 2014 -0700 PNaCl configuration: use pnacl-ar instead or ar (fixes build issue on Mac) commit 68a02976e3c3638f0a9821342e269a1743e3ace3 Author: Marat Dukhan Date: Wed Jun 18 03:10:25 2014 -0700 Compile pnacl configuration in GNU11 mode to avoid warning about non-standard features commit 6f8462eb0ec278b89731e73ef583386a3371d095 Author: Marat Dukhan Date: Wed Jun 18 03:08:46 2014 -0700 Fix inconsistent VERBOSE macro in Makefile commit b2ffb4de8b6872cb23537ad282e557d11dcd9c8b Author: Marat Dukhan Date: Sun Jun 15 18:41:30 2014 -0400 Reformatted PNaCl GEMM kernels commit 6de2d472d98baa215264a776f3d5291780a6a085 Author: Marat Dukhan Date: Sun Jun 15 08:44:31 2014 -0400 CGEMM and ZGEMM kernels for PNaCl commit f064711a5e6fb3852c17c7520909b09dc27665f2 Author: Marat Dukhan Date: Sun Jun 15 06:27:37 2014 -0400 SGEMM and DGEMM kernels for PNaCl commit ad48dca22913a363899f0bef45553898718eebb1 Merge: ee2b6792 7118f87e Author: Field G. Van Zee Date: Sat Jun 14 15:10:13 2014 -0500 Merge pull request #9 from tkelman/memalign_windows Use _aligned_malloc instead of posix_memalign on Windows commit 7118f87e18b4941423472afc00215c1d1f2a1fcd Author: Tony Kelman Date: Sat Jun 14 06:53:20 2014 -0700 Use _aligned_malloc instead of posix_memalign on Windows commit ee2b679281ca45fb40b2198e293bc3bc3d446632 Author: Tyler Smith Date: Fri Jun 6 12:41:55 2014 -0500 Only include omp.h if BLIS_ENABLE_OPENMP is set commit 19c05dfaac43c627f86e897c8c00f1f9440754aa Author: Field G. Van Zee Date: Thu Jun 5 10:54:16 2014 -0500 CHANGELOG update (for 0.1.2). commit 00f232f8ed1f7c41619b12ebf779ebe2c3b2d3cd (tag: 0.1.2) Author: Tyler Smith Date: Mon Jun 2 13:40:57 2014 -0500 Added single-precision micro-kernel for Knights Corner aka MIC aka Xeon Phi commit 3fc60e491426f6248c0feae88d971e4d1f88fb95 Author: Field G. Van Zee Date: Wed May 21 11:34:42 2014 -0500 Fixed ldim alignment bug in core2 gemm ukernel. Details: - Fixed a bug in the dunnington/core2 gemm micro-kernels that resulted in a segmentation fault if a column-stored matrix's starting address was aligned, but its leading dimension was such that its second column was unaligned. Basically, the micro-kernel was assuming that aligned load instructions were safe when they actually were not. An extra condition that checks the alignment of cs_c (ie: the leading dimension in the column storage case) has now been added. Thanks to Michael Lehn for reporting this bug. commit 77a2d8dac8b242d7a202c9aabda3927ab68cf987 Merge: 8c5d6071 21fb0893 Author: Field G. Van Zee Date: Tue May 20 09:53:19 2014 -0500 Merge pull request #8 from tlrmchlsmth/master Added multithreading to most level-3 operations. commit 21fb089387ee7c87f6dc53b0f60f68b48d3ff3e8 Author: Tyler Smith Date: Mon May 19 20:38:55 2014 -0700 Reverting changes dunnington and reference configs Now they are unchanged from the main branch of BLIS commit 8a0ef0e0db5880730425926f8ba56b457a2ba764 Author: Tyler Smith Date: Fri May 16 13:44:14 2014 -0500 Fixed rounding error in bli_get_range_weighted commit 0b4b1680334528b1b60bc696537600f763198e92 Author: Tyler Smith Date: Fri May 16 12:23:37 2014 -0500 Fixed bug with disabling JC loop threading for right sided trmm commit 5c048a90d8dfa1dbde4e45fbc10ffcbdfe59d960 Author: Tyler Smith Date: Wed May 14 16:20:06 2014 -0500 Disabled parallelism for right-sided TRMM JC loop The loop has dependent iterations. commit 13a4c717ed0e273359dbaf5554cc4fa70b087d71 Author: Tyler Smith Date: Wed May 14 14:59:04 2014 -0500 Fixed bug with bli_get_range_weighted commit 45957cc7745e9bb1698408d72f53ef192e960820 Author: Tyler Smith Date: Tue May 13 17:14:46 2014 -0500 Allowed threading to be turned off No longer requires OpenMP to compile Define the following in bli_config.h in order to enable multithreading: BLIS_ENABLE_MULTITHREADING BLIS_ENABLE_OPENMP Also fixes a bug with bli_get_range_weighted commit bd1dc98ce599d74513a553fe3b37a2ebca1c3812 Author: Tyler Smith Date: Mon May 12 17:26:19 2014 -0500 Disabled multithreading of the kc loop commit 456df0372170bd7ca2c7e2d85365a69f1f04de88 Author: Tyler Smith Date: Wed Apr 30 12:28:00 2014 -0500 Replaced register blocksize hack with querying the register blocksize for determining parallelism granularity commit f4fdfe8fc573553eb36795b79cdf681270dab71b Merge: 31bb065b 8c5d6071 Author: Tyler Smith Date: Wed Apr 30 11:46:35 2014 -0500 Merge http://github.com/flame/blis commit 8c5d6071e24ba10a53669390a47287e86ff354ce Author: Field G. Van Zee Date: Tue Apr 29 12:26:12 2014 -0500 Added _check() routines for fprint[mv], rand[mv]. Details: - Added _check() routines for fprintm, fprintv, randm, and randv. - Added invocations to the above routines from their respective front-ends. commit 262cdabcc885bcf6636f4d8bb7d320f95e81d820 Author: Field G. Van Zee Date: Mon Apr 28 16:48:25 2014 -0500 Changed treatment of NULL object buffers. Details: - Relaxed the constraint in bli_obj_attach_buffer_check(), which required the buffer address being attached to be non-NULL. This is acceptable because the user was already able to create and use objects with NULL buffers (via bli_obj_create_without_buffer(), which initializes the buffer to NULL). - Inserted calls to newly defined function, bli_check_object_buffer(), into nearly all operations' _check() or _int_check() functions. This allows BLIS to abort peacefully if a computational routine is called with an object containing a NULL buffer. By contrast, under such conditions, BLAS would typically fail with a segmentation fault. - Within operation front-ends, moved the calls to _check()/_int_check() so that zero dimensions are checked first (and if found, execution returns with trivial or no computation). This resolves issue #7. Thanks to Jack Poulson for reporting this bug. commit 31bb065ba40ae0c5a614e743b8025abca012b99e Merge: 20e24430 7c619599 Author: Tyler Smith Date: Wed Apr 23 12:30:19 2014 -0500 Merge http://github.com/flame/blis commit 7c61959955c8ba78160d0ed4d1979022029d963b Author: Field G. Van Zee Date: Thu Apr 10 17:18:36 2014 -0500 Can now query register blocksizes from blk algs. Details: - Added a new field to blksz_t objects that allows one to attach a sub-object. Doing this allows us to associate a register blocksize with any given cache blocksize. That way, the register blocksize can be queried wherever the cache blocksize would normally be accessible (e.g. a blocked algorithm). - Modified bli_gemm_cntl.c (and 4m/3m variants) so that the register blocksizes are attached to the cache blocksizes after they are created. commit 58671597d3d450817b2eda576c05ed6dadd8af6d Author: Field G. Van Zee Date: Thu Apr 10 15:35:30 2014 -0500 Minor cleanups to level-2 _cntl.c files. Details: - Changed level-2 _cntl.c files so that the blocksizes for gemv are imported and used, rather than blocksizes being declared locally. - Whitespace changes to gemv_cntl.c and gemm_cntl.c files (as well as 4m/3m variants). - Removed test/old/test_blis2.c. commit 20e24430a772bc0fbaf24dec2f8c544096fd3f4e Author: Tyler Michael Smith Date: Tue Apr 8 17:50:44 2014 +0000 Some fixes for the bgq kernels commit bde697f75ec1e7f2decebee0c9bd620b4c134cd5 Author: Tyler Smith Date: Fri Apr 4 16:43:44 2014 -0500 Add -openmp to ldflags as well commit c332be8cd471eeace7b4fa4ae7443088b6a68ec3 Author: Tyler Smith Date: Fri Apr 4 16:37:50 2014 -0500 Added -openmp flag to Xeon Phi build for convenience commit e7ca9e4b4a24d585c9aec8293fc7bb79e4171ad0 Author: Tyler Smith Date: Fri Apr 4 16:31:15 2014 -0500 Used BLIS_DEFAULT_*_MR for rounding partitioning instead of BLIS_DEFAULT_*_MC commit 7b9b228c6fa4cfb70b1ebb855b009a036e85fac3 Author: Tyler Smith Date: Fri Apr 4 16:29:10 2014 -0500 Fix for tree barrier freeing bug commit 5ec93bd9a76096312d51c326ccde1e9bd0a436ab Author: Tyler Smith Date: Fri Apr 4 15:09:10 2014 -0500 Bunch of minor fixes Removed barrier after unpackm in all level3 blocked variants Now there is an implicit barrier inside unpackm that only occurs if C is packed (which is usually not the case) Moved the enabling of the tree barriers into bli_config.h Fed the default MR and NR for double precision into bli_get_range instead of the number 8 commit 575fb9b0b08f3bdb56ccde056da619d1585617c1 Author: Tyler Smith Date: Fri Apr 4 12:13:29 2014 -0500 Changed default blocking factor to default double precision MR and NR commit ab9c7880335c281432d5809fe0dec46753d22569 Author: Tyler Smith Date: Fri Apr 4 11:38:11 2014 -0500 Added faster tree barriers necessary for performance for Xeon Phi Fixed up some stuff in the thread info free functions Disabled threading for TRSM so that it actually works when threading environment variables are set commit ec58a7923cccac08632670caadf3cf6ff5dce766 Author: Tyler Smith Date: Fri Apr 4 10:22:48 2014 -0500 Freeing thread info paths. Also made herk IC and JC loops do weighted partitioning commit 2b6848b2397d6d84ca4e5f792fc51ad05e351a36 Merge: 4e3eb39a 21a0efb3 Author: Tyler Smith Date: Fri Apr 4 09:54:54 2014 -0500 Merge http://github.com/flame/blis Conflicts: kernels/bgq/1/bli_axpyv_opt_var1.c kernels/bgq/1/bli_dotv_opt_var1.c commit 4e3eb39aca4df0b9fdc003d468f368a2f2ba597d Author: Tyler Michael Smith Date: Fri Apr 4 14:50:03 2014 +0000 Some fixes to the bgq config MR and NR for double complex were wrong Default fusing factor for double precision was wrong as well commit 21a0efb33d7435139e9c43c1a4787a6bff533e26 Author: Field G. Van Zee Date: Thu Apr 3 16:38:44 2014 -0500 Fixed follow-up to issue #6. commit c318157a9bee8ea6e59be16f99f65d9271fe0d27 Author: Field G. Van Zee Date: Thu Apr 3 16:24:34 2014 -0500 Fixed issue #6 (incorrect 'restrict' usage). Details: - Fixed improper usage of restrict keyword in axpyv and dotv bgq kernels. (However, there may be other instances of similar misuse elsewhere in BLIS.) Thanks to Jeff Hammond for reporting this issue. commit b5150a1bf3bd89598e2b3aeac110eb5b44ac6c12 Author: Field G. Van Zee Date: Thu Apr 3 12:25:45 2014 -0500 Added #include "arm_neon.h" to ARM gemm ukernel. Details: - Inserted #include "arm_neon.h" into gemm ukernel source file for arm/neon. Thanks to Jean-Michel Hautbois for suggesting this fix. commit 2041c264517b6c590fd4f7e8253e6911b622d1c3 Author: Tyler Smith Date: Thu Apr 3 10:30:03 2014 -0500 Added barriers needed prior to doing scalar reset for rank-k updates. commit 47a90e69dfde3f4f8fdf90654248a6b499fbadbc Author: Field G. Van Zee Date: Tue Apr 1 14:34:31 2014 -0500 Attempted to fix uninitialized variable warnings. Details: - Added initialization statements to various macros used in level 1m and 1m-like operations. I wasn't able to reproduce the reported behavior, so hopefully this takes care of it. Thanks to Jeff Hammond for the report. commit d27b4f690c14b1f836f8c7a3c0e91e09d852f02e Author: Field G. Van Zee Date: Tue Apr 1 12:57:24 2014 -0500 Use generic paths for toolchain in POWER7. Details: - Fixed issue #4. Thanks to Jeff Hammond for contributing changes. commit 1584ae1c83c3a8c1af76acb46404747507650f19 Author: Tyler Smith Date: Fri Mar 28 15:15:48 2014 -0500 Fixed race condition involving scalar reset commit 459dde4acc09e49380da58fb7b246db488884ad9 Author: Tyler Smith Date: Thu Mar 27 17:06:45 2014 -0500 Made barrier after packing implicit. This also fixed a bug where barriers in the blocked variants were inserted after the inner packing routines, but not the outer packing routines. This allowed, for instance, the block of B to not be finished being packed before computation to occur. commit 9f78ec6e7e95fcad89a167b27cad7e2d74b6d122 Author: Tyler Smith Date: Thu Mar 27 14:18:46 2014 -0500 Some fixes for the internal functions, was innappropriately only having thread chief do some things. commit a6fd48345424e097f71652be013aa897e098b41e Author: Tyler Michael Smith Date: Wed Mar 26 17:19:46 2014 +0000 Added test drivers for level 3 BLAS that run tests in parallel using MPI commit 73b3db594864be0f9be9a0eb29bf961fa9c95f29 Author: Tyler Michael Smith Date: Wed Mar 26 15:39:05 2014 +0000 Some fixes for the bgq configuration commit f0824a04fc75e231c3a3d7757fa4e7294173282f Author: Tyler Smith Date: Mon Mar 24 15:21:42 2014 -0500 Initial commit to enable threading in TRSM, Also enabled weighted partitioning for herk, trmm Fixed bug where multiple threads would try to modify the same state in the internal level 3 functions Correctly computed a_next and b_next for gemm, herk macrokernels a_next and b_next point to the current micropanels in trmm commit 23d9eab354fbc88165889832955e126772bf8488 Merge: 5d5dc2ee fd3e32a5 Author: Tyler Smith Date: Thu Mar 20 16:54:35 2014 -0500 Merge https://github.com/flame/blis commit 5d5dc2eedef2f7c90d61371a1b457be5c06cf583 Author: Tyler Smith Date: Thu Mar 20 16:43:36 2014 -0500 Parallelized trmm and trmm3 Also fixed bugs in packm commit fd3e32a5f419fa412f46afe4dd1c3a26e15f3eb4 Author: Field G. Van Zee Date: Thu Mar 20 13:59:48 2014 -0500 Refined INSERT_GENTFUNC macro usage. Details: - Defined new INSERT_GENTFUNC macros so that the macro always takes exactly the number of arguments needed for the particular operation or variant being defined. Many operations were using INSERT_GENTFUNC macros that expected one auxiliary argument even though none were needed. Those instances have now been updated. Most of these instances were in the level-0 and -1v operations, as well as some operations defined in frame/util. commit 9b0e715f29338a1a1d6445907d2445c35f011121 Author: Field G. Van Zee Date: Wed Mar 19 15:47:54 2014 -0500 Minor simplifications to trmm, trsm macro-kernels. Details: - Simplified some code that would have allowed the diagonal of a trmm or trsm triangular matrix to intersect the short end of a micro-panel. This is disallowed via higher-level constraints on cache blocksizes, so this code was never needed and only served to obfuscate. - Updated some comments in trmm, trsm macro-kernels. commit a3902750b9ab4923433f7e353f3669c3c419f8e4 Author: Field G. Van Zee Date: Wed Mar 19 12:35:17 2014 -0500 Reorganized norm operations. Details: - Completely reoganized norm operations: - Renames: - fnormsc, fnormv, fnormm -> normfsc, normfv, normfm (2-norm) - absumv -> norm1v (vector 1-norm) - New operations: - norm1m (matrix 1-norm) - normiv, normim (infinity-norm) - amaxv (BLAS-like absolute maximum value index) - asumv (BLAS-like absolute sum) - Deprecated absumm, as it did not correspond to any actual norm. (However, an inlined version now exists in the testsuite module for randm.) commit c0140cb752f27e99742f85d23be2181c00a1335e Author: Tyler Smith Date: Wed Mar 19 11:21:16 2014 -0500 Fixed packm variants 3 and 4 where every thread was trying to manipulate the same state Now just performed by the master thread. commit fb42983bd9943711baa7d1c6496de1215bb816ef Author: Tyler Smith Date: Tue Mar 18 16:37:28 2014 -0500 Fixed a barrier bug and a thread decorator bug commit aa2405f8b23d0f8d2ec04790882f2176ef2e8fd8 Author: Tyler Smith Date: Tue Mar 18 15:23:09 2014 -0500 Fixing function pointer issues with thread decorator commit ec8b88f93533942d3711191873310e7ff281bda6 Author: Tyler Smith Date: Tue Mar 18 14:35:37 2014 -0500 Enabled threading for packm blocked variants 3 and 4 commit 0ac534cdf657bbf04601abfe719ba2887aab5da7 Author: Tyler Smith Date: Tue Mar 18 13:26:27 2014 -0500 Added decorator for calling parallelized intermal functions Will allow for easy support for different threading models commit 5296f58975f7d351f88909cc80b6d0cffd73def7 Author: Tyler Smith Date: Mon Mar 17 17:15:35 2014 -0500 Fixing some bugs with herk parallelization commit c51d0110831eb89361b4720bf7ed75edbd26ebce Author: Tyler Smith Date: Mon Mar 17 15:00:47 2014 -0500 Initial multithreading support for HERK commit c720b141568d1f289146bf34ded08001f2c0dfbb Author: Tyler Smith Date: Mon Mar 17 11:39:32 2014 -0500 Switched to using environment variables to control threading. The environment variables all follow the format BLIS_X_NT, where X is the index of the loop as described in our paper Anatomy of High Performance Many-Threaded Matrix Multiplication. These indices are IR, JR, IC, KC, and JC. Also enabled parallelism for hemm and symm, but these are currently untested. commit 92233cf64274b27b2217c5cfffe75443ff6137a4 Author: Tyler Smith Date: Tue Mar 11 14:16:08 2014 -0500 Some fixes to gemm thread info tree creation, Changed microkernel tests to use the new BLIS_PACKM_SINGLE_THREADED instead of BLIS_SINGLE_THREADED commit 020f80c30289d8bcaa688bf600b01fae9b23b54f Author: Tyler Smith Date: Tue Mar 11 12:08:17 2014 -0500 Added files specific to threading for gemm and packm operations commit 8d8f4352a41926bc923e47be836365b6b726aff2 Author: Tyler Smith Date: Mon Mar 10 15:47:28 2014 -0500 Added single threaded thread info data structures specifically for gemm and packm commit 0e8677761175189583ca7d855e24b2bbdd2dada8 Merge: 2e727a02 b3bff631 Author: Tyler Smith Date: Mon Mar 10 15:16:21 2014 -0500 Merge branch 'master' of https://github.com/tlrmchlsmth/blis commit 2e727a025a8f796d2b6bd14f489d0ee72e7d1fc7 Author: Tyler Smith Date: Mon Mar 10 15:14:33 2014 -0500 Modifying the thread info data structures This change makes each operation have its own thread info type, allowing more fine control of threading in operations that have different types of suboperations commit a770590cf21a459f04bf941c58ee2afd272cc441 Author: Field G. Van Zee Date: Mon Mar 3 14:31:44 2014 -0600 Minor fixes to sumsqv, abmaxv. Details: - Minor update to bli_sumsqv_unb_var1() to bring it up-to-date with LAPACK 3.5.0's zlassq.f, which, starting with 3.4.2, returns NaN when the vector (or matrix) contains a NaN. - Minor change to bli_abmaxv_unb_var1() to more closely mimic the behavior of netlib BLAS's izamax(). There, a "less than or equal to" operator is used in the search instead of "less than", which would change the element index returned if there were multiple maximum values. - Added macro function definitions for bli_isinf() and bli_isnan(), which are currently implemented in terms of isinf() and isnan() from math.h. commit b3bff631eadf98b15cb422fb4a8e2f855c23e8a7 Merge: 2c158fb8 e8757b03 Author: Tyler Smith Date: Thu Feb 27 16:53:24 2014 -0600 Merge https://github.com/flame/blis commit 2c158fb885c27f7b599dc1e85b57edd684f19223 Merge: e4738c48 c2b2ab62 Author: Tyler Smith Date: Thu Feb 27 16:46:23 2014 -0600 Merge https://github.com/flame/blis Conflicts: frame/1m/packm/bli_packm_blk_var1.c commit e8757b03a74f9891632242e9a90efb32150826f5 Author: Field G. Van Zee Date: Thu Feb 27 16:40:07 2014 -0600 Use "%ld" as int format specifier in fprintm. Details: - Changed "%d" to "%ld" when printing integers via bli_fprintm(). - Meant to include this in previous commit. commit c663ce3b5170fee7dfb5b528b650d70c8e932cac Author: Field G. Van Zee Date: Thu Feb 27 16:32:57 2014 -0600 Fixed various bugs when C99 complex is enabled. Details: - Fixed various bugs in packm_*_cxk(), the 4m/3m micro-kernels, and elsewhere in the framework that were not yet set up to work properly when BLIS_ENABLE_C99_COMPLEX is defined in bli_config.h - Extensive changes to f2c-derived files in frame/compat/f2c to allow C99 complex storage. Most of these changes center around accessing real and imaginary components via bli_?real()/bli_?imag() accessor macros, and setting of values via bli_?sets() assignment macros. (Thanks to Vladimir Sukarev for pointing out that _ENABLE_C99_COMPLEX was broken.) commit e4738c48e00b89391d9baa1fd0aa62d1ea2f95e6 Author: Tyler Smith Date: Thu Feb 27 16:29:46 2014 -0600 Added support for parallelism in gemm micro-kernel commit bfe214b633765ed40b57b330fbb84c332663aa40 Author: Tyler Smith Date: Thu Feb 27 15:53:10 2014 -0600 Fixed bug with parallel packing, and bug with allocating an array of thread infos In packm variant 1, the variable p_begin was incremented each iteration, causing a dependency. This dependeny was removed, allowing each iteration to be executed in parallel. Somewhere in bli_threading.c, I was allocating an array of pointers instead of an array of structs. commit 6193d9ceea552e67170dba45abde04c64271c705 Author: Tyler Smith Date: Thu Feb 27 14:09:19 2014 -0600 Fixed bug in thread trees commit ac5a2de1d17ffd460b00fee9757898525a09abae Merge: 01b125e8 bd3c7ecf Author: Tyler Smith Date: Thu Feb 27 11:59:33 2014 -0600 Merge branch 'master' of https://github.com/tlrmchlsmth/blis commit 01b125e815f19410e8e0611d088b84570e499e93 Author: Tyler Smith Date: Thu Feb 27 11:55:45 2014 -0600 First pass at adding parallelism to BLIS. Added a multithreading infrastructure that should be independent of multithreading implementation in the future. Currently, gemm blocked variants 1f and 2f, and packm variant blocked variant 1 is parallelized. commit c2b2ab62707e4174892aff3ce65f36f54878fae5 Author: Field G. Van Zee Date: Wed Feb 26 12:46:45 2014 -0600 Deprecated panel stride alignment in bli_config.h. Details: - Removed BLIS_CONTIG_STRIDE_ALIGN_SIZE from bli_config.h of all configurations. It was already going unused in packm_init() since the recent 4m/3m commit. This setting was rarely, if ever, useful, and its existence only posed a potential risk for 4m/3m-based implementations. - Removed BLIS_CONTIG_STRIDE_ALIGN_SIZE usage from mem_pool_macro_defs.h. - Updated comments regarding CONTIG_STRIDE_ALIGN_SIZE in template micro-kernels. commit f18aee83a5ac1b14808686fc3c5a3c846a1d99b9 Author: Field G. Van Zee Date: Tue Feb 25 17:58:42 2014 -0600 CHANGELOG update (for 0.1.1). commit fde5f1fdece19881f50b142e8611b772a647e6d2 (tag: 0.1.1) Author: Field G. Van Zee Date: Tue Feb 25 13:34:56 2014 -0600 Added extensive support for configuration defaults. Details: - Standard names for reference kernels (levels-1v, -1f and 3) are now macro constants. Examples: BLIS_SAXPYV_KERNEL_REF BLIS_DDOTXF_KERNEL_REF BLIS_ZGEMM_UKERNEL_REF - Developers no longer have to name all datatype instances of a kernel with a common base name; [sdcz] datatype flavors of each kernel or micro-kernel (level-1v, -1f, or 3) may now be named independently. This means you can now, if you wish, encode the datatype-specific register blocksizes in the name of the micro-kernel functions. - Any datatype instances of any kernel (1v, 1f, or 3) that is left undefined in bli_kernel.h will default to the corresponding reference implementation. For example, if BLIS_DGEMM_UKERNEL is left undefined, it will be defined to be BLIS_DGEMM_UKERNEL_REF. - Developers no longer need to name level-1v/-1f kernels with multiple datatype chars to match the number of types the kernel WOULD take in a mixed type environment, as in bli_dddaxpyv_opt(). Now, one char is sufficient, as in bli_daxpyv_opt(). - There is no longer a need to define an obj_t wrapper to go along with your level-1v/-1f kernels. The framework now prvides a _kernel() function which serves as the obj_t wrapper for whatever kernels are specified (or defaulted to) via bli_kernel.h - Developers no longer need to prototype their kernels, and thus no longer need to include any prototyping headers from within bli_kernel.h. The framework now generates kernel prototypes, with the proper type signature, based on the kernel names defined (or defaulted to) via bli_kernel.h. - If the complex datatype x (of [cz]) implementation of the gemm micro- kernel is left undefined by bli_kernel.h, but its same-precision real domain equivalent IS defined, BLIS will use a 4m-based implementation for the datatype x implementations of all level-3 operations, using only the real gemm micro-kernel. commit 15b51e990f1d21333b5f7af97c211756247336e5 Merge: 6363a9f6 fc04b5eb Author: Field G. Van Zee Date: Fri Feb 21 09:04:32 2014 -0600 Merge branch 'master' of github.com:fgvanzee/blis commit fc04b5eb69868c341ce03f5ef1f02de4b8c121b0 Merge: b29e1c2b d1813c9d Author: Field G. Van Zee Date: Fri Feb 21 09:04:13 2014 -0600 Merge pull request #3 from figual/master New ARM armv7a kernels and Assembly file consideration in Makefile commit d1813c9dee34410833db5061e6588ec1a6c9ecd4 Author: Francisco Igual Date: Fri Feb 21 15:14:31 2014 +0100 Added new armv7a micro-kernels and configuration files from Werner Saar. commit 0cd098c03a000ed9426a7e9135190696da8cadbc Author: Francisco Igual Date: Fri Feb 21 15:12:30 2014 +0100 o Modified Makefile to consider .S assembly microkernels. commit 6363a9f658257fe3d814a3dce5308f807adb54a2 Author: Field G. Van Zee Date: Wed Feb 19 17:00:52 2014 -0600 Added level-3 support for complex via 4m-/3m. Details: - Added the ability to induce complex domain level-3 operations via new virtual complex micro-kernels which are implemented via only real domain micro-kernels. Two new implementations are provided: 4m and 3m. 4m implements complex matrix multiplication in terms of four real matrix multiplications, where as 3m uses only three and thus is capable of even higher (than peak) performance. However, the 3m method has somewhat weaker numerical properties, making it less desirable in general. - Further refined packing routines, which were recently revamped, and added packing functionality for 4m and 3m. - Some modifications to trmm and trsm macro-kernels to facilitate indexing into micro-panels which were packed for 4m/3m virtual kernels. - Added 4m and 3m interfaces for each level-3 operation. - Various other minor changes to facilitate 4m/3m methods. commit b29e1c2b278c177e104c84ba462820ee8296df6c Merge: ee60377e bd3c7ecf Author: Field G. Van Zee Date: Fri Feb 14 14:11:54 2014 -0600 Merge pull request #2 from tlrmchlsmth/master Fixes and improvements to xeon phi implementation. commit bd3c7ecfb54a9b9851c7d364f41c21e4cff52f6f Author: Tyler Smith Date: Fri Feb 14 14:05:57 2014 -0600 Removing changes to input.general and input.operations commit ce066863683cb4e910270cf8ab8e138b01ff3358 Author: Tyler Smith Date: Fri Feb 14 13:40:24 2014 -0600 Fixed more Xeon Phi bugs, especially with scattered update commit 31134b5c7076423aee1b4f494e925f27171d97e6 Author: Tyler Smith Date: Fri Feb 14 11:19:44 2014 -0600 Some fixes, changes, and improvements to the microkernel to the Xeon Phi commit ee60377e467862b9d8a7205c45dce5cf66c78c46 Author: Field G. Van Zee Date: Thu Feb 13 14:03:31 2014 -0600 Shifted some fields in info_t. Details: - Shifted the pack order, pack buffer type, and structure type fields to make room for an extra bit in the pack type/status field. commit bd3ab1ad4cf42f8bc30ab262acf8eccb49bb1a08 Author: Field G. Van Zee Date: Thu Feb 13 09:29:55 2014 -0600 Minor fixes to trsm consistent with prev on trmm. Details: - Removed use of bli_min() and bli_max() that were only being used to try to support situations where the diagonal would intersect the short end of some micro-panels, which is situation that is disallowed at a higher level by various constraints on the register and cache blocksize. This only affected trsm_ll and trsm_lu. - Use panel stride as passed into the macro-kernel rather than compute it via k and PACKMR/PACKNR. This affects all macro-kernels of trsm. commit 6260b0b5f8bd248f3f66e5a1c6854bdbd9d02ad0 Author: Field G. Van Zee Date: Thu Feb 13 09:19:56 2014 -0600 Fixed obscure bug in trmm_ll, trmm_lu. Details: - Fixed an obscure bug in left-hand trmm that would only manifest when non-zero register blocksize extensions (PACKMR > MR or PACKNR > NR) are used. - Removed use of bli_min() and bli_max() that were only being used to try to support situations where the diagonal would intersect the short end of some micro-panels, which is situation that is disallowed at a higher level by various constraints on the register and cache blocksize. This only affected trmm_ll and trmm_lu. - Use panel stride as passed into the macro-kernel rather than compute it via k and PACKMR/PACKNR. This affects all macro-kernels of trmm. commit 16915c1c1e55c660bf82141cdadf7c0860d5b464 Author: Field G. Van Zee Date: Tue Feb 11 10:54:19 2014 -0600 Fixed an obscure bug in packm_cxk(). Details: - Fixed a bug in packm_cxk() whereby the packm ukernel was being chosen from ldp, which is always equal to PACKMR or PACKNR. The problem with this is that the pack ukernels were implicitly assuming that the panel dimension of the panel being packed was equal to ldp, which is not the case when the register blocksizes extensions are non-zero (ie: when PACKMR > MR or PACKNR > NR, whichever is applicable). This problem has been fixed by passing ldp into the pack ukernels, which now walk through the packed micro-panel region by incrementing by this value, rather than incrementing by the inherent panel dimension value assumed by each packm ukernel (e.g. 4 in the case of packm_ref_4xk). - Also fixed a very minor edge case inefficiency whereby pack ukernels smaller than the default were not being used in edge cases, and instead those situations were being handled by scal2m. This is related to the issue above, because the pack ukernel itself was being chosen based on ldp instead of the panel dimension. commit b7da57b282c5a5e2208946e60309d2352f55351d Author: Field G. Van Zee Date: Tue Feb 11 10:28:23 2014 -0600 Updated calls to packm_blk_var2() in testsuite. Details: - In ukernel testsuite modules, replaced calls to packm_blk_var2() with _var1(). Meant to include this in previous commit. commit c255a293e25b2223c88e8800267cd06ad2a90041 Author: Field G. Van Zee Date: Mon Feb 10 14:31:24 2014 -0600 Consolidated packm_blk_var2 and var3. Details: - Consolidated the functionality previously supported by packm_blk_var2() and packm_blk_var3() into a new variant, packm_blk_var1(). - Updates to packm_gen_cxk(), packm_herm_cxk.c(), and packm_tri_cxk() to accommodate above changes. - Removed packm_blk_var3() and retired packm_blk_var2() to frame/1m/packm/old. - Updated all level-3 _cntl_init() functions so that the new, more versatile packm_blk_var1 is used for all level-3 matrix packing. commit 32d8f264ae7b28155f5d7b21dcc5ecb78da2e0ab Author: Field G. Van Zee Date: Sun Feb 9 10:07:37 2014 -0600 Refactored packm variants. Details: - Revised packm_blk_var2() and _var3() by encapsulating the general, hermitian/symmetric, and triangular panel-packing subproblems into separate functions: packm_gen_cxk(), packm_herm_cxk(), and packm_tri_cxk(), respectively. Also, homogenized the packm code as well as the new specialized packm_*_cxk() code to further improve readability. commit 6c8067028707947fcdf4f856a272e15bb9ed91e3 Author: Field G. Van Zee Date: Fri Feb 7 11:27:15 2014 -0600 Renamed enumerated type in testsuite and modules. Details: - Renamed the test suite's "mt_impl_t" enumerated type to "iface_t", and renamed all corresponding "impl" variables to "iface". commit 6c12598b1bc567f0b08f58aebdc753a1c1390378 Author: Field G. Van Zee Date: Thu Feb 6 18:26:35 2014 -0600 Employ simpler INSERT_ macro for ref ukernels. Details: - Defined a new macro, INSERT_GENTFUNC_BASIC0, which takes only one argument--the base name of the function--and employed this macro in the reference micro-kernel files instead of the _BASIC macro, which takes one auxiliary argument. That argument was not being used and probably just acted to unnecessarily obfuscate. commit 32cae66326b68706d0e695cfd60c9ca5bc32c534 Author: Field G. Van Zee Date: Thu Feb 6 18:06:42 2014 -0600 Fixed some instances of sloppy 'restrict' usage. Details: - Fixed some technical incorrectness with some usage of the 'restrict' keyword in the reference trsm micro-kernels. - Tweak to testsuite/Makefile that causes rebuild if libblis was touched. commit 7aceef7683e2a2aff3c7ec2a73508036af2e19e2 Author: Field G. Van Zee Date: Thu Feb 6 17:31:19 2014 -0600 Updated comments in macro-kernels. Details: - Updated (and fixed some errors in) the "Assumptions/assertions" comment section of macro-kernels. - Changed register blocksizes of reference configuration to MR = 8 and NR = 4. It's always good for MR != NR in the reference configuration since it may help uncover bugs related to non-square micro-kernels. commit 8fd292aa78950bcdf556605718f09d13f9575abc Author: Field G. Van Zee Date: Thu Feb 6 14:32:21 2014 -0600 Pass panel dimensions into macro-kernels. Details: - Modified the interfaces to the datatype-specific macro-kernels so that: - pd_a and pd_b are passed in (which contain the panel dimensions of packed panels of a and b). - rs_a and cs_b are no longer passed in (they were guaranteed to be 1). - Modified implementations of datatype-specific macro-kernels so pd_a, pd_b, cs_a, and rs_b are used instead of cpp macros for MR, NR, PACKMR, and PACKNR, respectively. - Declare temporary c matrices (ct) as being maxmr-by-maxnr, which for now is equivalent to being mr-by-nr. maxmr and maxnr are declared in a new header file bli_kernel_post_macro_defs.h. commit 3404e6657eabb017cd1580a2f1dd8e6fb13df923 Author: Field G. Van Zee Date: Wed Feb 5 11:19:10 2014 -0600 Deprecated incremental blocksize macro const defs. Details: - Removed macro constant definitions related to incremental blocksizes from all configurations' bli_kernel.h files. This change is minor and is mostly a cleanup related to a previous commit. commit 1e9afd39a63e0a58167d4439c1a0a880a4a35657 Author: Field G. Van Zee Date: Tue Feb 4 20:15:19 2014 -0600 Comment updates (removed vestiges of "bd"). commit 5cf58f7c2d5bc0d2d94d9576f7158d8f133b7aac Author: Field G. Van Zee Date: Tue Feb 4 09:15:19 2014 -0600 Added early returns for "object is zeros" case. Details: - Added some logic to packm_init(), pack_int() and gemm_int() so that (a) objects marked as BLIS_ZEROS are not packed, and (b) those objects are not computed with. This functionality is not currently needed by any existing implementations, but may be used in the future. commit 6bbd4be769a9b344a55abe5ddaca1a99fd29f7b4 Author: Field G. Van Zee Date: Mon Feb 3 13:15:25 2014 -0600 Added 'f' on some gemm and trmm blocked variants. Details: - Added 'f' to some block variant files/functions to be consistent with other file/functions' naming convention. Here, the f indicates partitioning in the "forward" direction. commit eb13cb2c6b182df5e2a9b88c76f50e2cee25b9e0 Author: Field G. Van Zee Date: Mon Feb 3 11:07:01 2014 -0600 Removed redundant non-gemm blksz_t creation. Details: - Removed code that creates duplicate blksz_t objects for herk, trmm, and trsm. Instead, the gemm blksz_t objects are accessed via extern and used directly. This reduces the amount of code associated with each of the three _cntl_init() and _cntl_finalize() function. commit 0a023a7d9e58e53b8c204a5f49aa8ca9afeba938 Author: Field G. Van Zee Date: Wed Jan 29 14:02:08 2014 -0600 Introduced new level-3 front-end layer. Details: - Added new _front() functions for each level-3 operation. This is done so that the choosing of the control tree (and *only* the choosing of the control tree) happens in what was previously the "front end" (e.g. bli_gemm()). That control tree is then passed into the _front() function, which then performs up-front tasks such as parameter checking. commit 251c5d112196d37b183e554bc9d406104aed65fb Author: Field G. Van Zee Date: Tue Jan 28 19:40:29 2014 -0600 Removed redundant hemm, her2k control trees. Details: - Removed code that generated a control tree specifically for hemm and symm. Instead, the gemm control tree is now configured so that it works for gemm, hemm, or symm. - Retired most her2k code, as it was not being used. (Currently, her2k is implemented as two invocations of herk.) I couldn't think of many situations where her2k variants were needed. - Removed some older her2k code. commit 5a36e5bf2f59d1e85d6dbce32a07d604c5e82d11 Author: Field G. Van Zee Date: Mon Jan 27 11:13:00 2014 -0600 Embed func_t microkernel objects in control trees. Details: - Modified all control tree node definitions to include a new field of type func_t*, which is similar to a blksz_t except that it contains one function pointer (each typed simply as void*) for each datatype. We use the func_t* to embed pointers to the micro-kernels to use for the leaf-level nodes of each control tree. This change is a natural extension of control trees and will allow more flexibility in the future. - Modified all macro-kernel wrappers to obtain the micro-kernel pointers from the incomming (previously ignored) control tree node and then pass the queried pointer into the datatype-specific macro-kernel code, which then casts the pointer to the appropriate type (new typedefs residing in bli_kernel_type_defs.h) and then uses the pointer to call the micro- kernel. Thus, the micro-kernel function is no longer "hard-coded" (that is, determined when the datatype-specific macro-kernel functions are instantiated by the C preprocessor). - Added macros to bli_kernel_macro_defs.h that build datatype-specific base names if they do not exist already, and then uses those to build datatype-specific micro-kernel function names. This will allow developers extra flexibility if they wanted to, for example, name each of their datatype-specific micro-kernels differently (e.g. double real might be named bli_dgemm_opt_4x4() while double complex might be named bli_zgemm_opt_2x2()). - Inserted appropriate code into _cntl_init() functions that allocates and initializes a func_t object for the corresponding micro-kernels. The gemm ukernel func_t object is created once, in bli_gemm_cntl_init(), and then reused via extern wherever possible. commit 6cbd6f1c7f1915180aa28939833afde48665c5ae Author: Field G. Van Zee Date: Fri Jan 24 10:38:29 2014 -0600 Removed commented mixed domain macro-kernel code. Details: - Removed commented-out code from macro-kernels that was supposed to facilitate implementing mixed domain (complex times real) matrix multiplication. This functionality is still (probably possible), but I'm getting tired of looking at the code every time I edit a macro-kernel. Plus, there are probably ways of doing it at a higher level, via control trees. commit 29778be1119f1a884330d7f8dc424a2df4101d58 Author: Field G. Van Zee Date: Wed Jan 22 16:03:11 2014 -0600 Removed b_aux field from cntl nodes. Details: - Removed b_aux field from all control tree node definitions. This field was being used in certain optimizations (incremental blocking) that were not actually being employed within BLIS, and are probably not employed by others. - Updated all _cntl_obj_create() function definitions and invocations according to above change. - Retired bli_gemm_blk_var4.c, which was one such function that employed incremental blocking, but which was never called by BLIS itself. commit 06ac727a42ec9e832c7832745036702014638f99 Author: Field G. Van Zee Date: Wed Jan 15 16:44:52 2014 -0600 Updated some comments in level-3 front ends. commit d628bf1da1560f1f5126a1ddfed8714f0a4b8da3 Author: Field G. Van Zee Date: Wed Jan 15 11:40:12 2014 -0600 Consolidated pack_t enums; retired VECTOR value. Details: - Changed the pack_t enumerations so that BLIS_PACKED_VECTOR no longer has its own value, and instead simply aliases to BLIS_PACKED_UNSPEC. This makes room in the three pack_t bits of the info field of obj_t so that two values are now unused, and may be used for other future purposes. - Updated sloppy terminology usage in comments in level-2 front-ends. (Replaced "is contiguous" with more accurate "has unit stride".) commit ddc8c1c379b4787be5954802906593d7ea144452 Author: Field G. Van Zee Date: Mon Jan 13 14:55:43 2014 -0600 Suppress warning in Makefile (UNINSTALL_LIBS). Details: - Redirect errors to /dev/null when using 'find' to locate libraries that would be uninstalled upon executing "make uninstall-old". Before, if the Makefile was read before $(INSTALL_PREFIX)/lib existed, a "No such file or directory" message was emitted. This message was harmless, but is now suppressed in this situation. commit f8f67d7251bffc05020e20527c100c8115fd5e55 Author: Field G. Van Zee Date: Fri Jan 10 09:06:11 2014 -0600 Typecast bli_getopt() return value in testsuite. Details: - In the test suite driver, inserted an explicit typecast of the return value of bli_getopt() prior parsing. The lack of typecast caused a problem on at least one system whereby a return value of -1 was interpreted as garbage character. Thanks to Francisco Igual for finding and submitting this fix. commit e7f154fe2ed3e10e2323cefe5d25c2c23ac902c4 Author: Field G. Van Zee Date: Fri Jan 10 08:48:07 2014 -0600 Applied edge case fix to arm/neon microkernel. Details: - Applied an edge case bugfix, courtesy of Francisco Igual, to the current double precision real gemm microkernel in kernels/arm/neon/3. commit 89c76a8a51d070d263c13bfa5ace65769509f2b4 Author: Field G. Van Zee Date: Thu Jan 9 12:08:37 2014 -0600 Allow building outside source distribution. Details: - Modified build system (mostly configure and top-level Makefile) so that a user can build a BLIS library outside of the top-level directory of the source distribution. - Added "test" target to Makefile so that the user can run "make test", which will compile, link, and run the testsuite binary. This works even if the build directory is externally located, thanks to the test suite binary's new -g and -o command-line options. Also, when creating the test suite via the top-level Makefile, the linking is against the local archive, in lib/, rather than at /lib. - Modified testsuite/Makefile so that it links against the library built locally, in ../lib/. - Added "-lm" to LDFLAGS of most configurations' make_defs.mk. - Various other cleanups to build system. commit 12fa82ec12cc340ab28552997d9d50f7c98691f8 Author: Field G. Van Zee Date: Wed Jan 8 16:09:26 2014 -0600 Implemented bli_getopt(). Details: - Added bli_getopt.c and .h files to frame/base. These files implement a custom version of getopt(), which may be used to parse command line options passed into a program via argc/argv. I am implementing this function myself, as opposed to using the version available via unistd.h, for portability reasons, as the only requirements are string.h (which is available via the standard C library). - Modified test suite to allow the user to specify the file name (and/or path) to the parameters and operations input files: -g may be used to specify the general input file and -o to specify the operations input file). If -g or -o or both are not given, default filenames are assumed (as well as their existence in the current directory). commit cafb58e86ea5cfb21b9eedc57ca8ebbf24252098 Author: Field G. Van Zee Date: Mon Jan 6 13:28:36 2014 -0600 Updated template micro-kernels to use auxinfo_t. Details: - Updated template micro-kernel implementations (located in config/template/kernels), to adhere to the new auxinfo_t interface. Meant to include this change in a0331fb1. - Changed template configuration to use 64-bit integers (for both BLIS and the BLAS compatibility layer). commit 9ab126b499c3805045020cb89a8a5848e28d3bf5 Author: Field G. Van Zee Date: Mon Jan 6 12:13:26 2014 -0600 Removed error checks in netlib->BLIS param mapping Details: - Disabled error checking in netlib-to-BLIS parameter mapping functions. If the char value input to these functions was not one of the defined values, bli_check_error_code() with the appropriate error code value would be called, resulting in an abort(). This was unnecessary and redundant since these routines are currently only used within the BLAS compatibility layer, and they are only called AFTER parameter checking has already been performed on the original BLAS char values. If the application tried to override xerbla() to prevent an abort() from being called, this error checking would still get in the way. Thus, instead of reporting the error situation to the framework (ie: calling abort()), an arbitrary BLIS parameter value is now chosen and the function returns normally. Thanks to Jeff Hammond for finding and reporting this issue. commit 2cb13600f9f9601c60e7f96f4ca159d169ade9cb Author: Field G. Van Zee Date: Fri Jan 3 12:29:13 2014 -0600 Updated year in copyright headers to 2014. commit 290fa54e0083c9c837188b8321b13b1b282e7b0c Author: Field G. Van Zee Date: Fri Dec 20 14:10:26 2013 -0600 Store variable panel strides in trmm/trsm auxinfo. Details: - Changed the value being stored into the auxinfo_t structure in trmm and trsm macro-kernels. Whereas before we stored whatever value was provided to the macro-kernel implementation via ps_a/ps_b, now we store the stride that will advance to the next variable-length micro-panel of the triangular matrix A (left) or B (right). - Whitespace changes to the files affected above. commit e3a6c7e77667fd749248df3f75f880266c3136ec Author: Field G. Van Zee Date: Thu Dec 19 16:29:31 2013 -0600 Macroized conditionals for a2/b2 in macro-kernels. Details: - Replaced conditional expressions in macro-kernels related to computing the addresses a2 and b2 (a_next and b_next) with a preprocessor macro invocation, bli_is_last_iter(), that tests the same condition. - Updated gemm_ukr module to use auxinfo_t argument. - Whitespace changes in test suite ukr modules. commit a0331fb10a50393e31d16339053b75b944132da1 Author: Field G. Van Zee Date: Thu Dec 19 14:50:11 2013 -0600 Introduced auxinfo_t argument to micro-kernels. Details: - Removed a_next and b_next arguments to micro-kernels and replaced them with a pointer to a new datatype, auxinfo_t, which is simply a struct that holds a_next and b_next. The struct may hold other auxiliary information that may be useful to a micro-kernel, such as micro-panel stride. Micro-kernels may access struct fields via accessor macros defined in bli_auxinfo_macro_defs.h. - Updated all instances of micro-kernel definitions, micro-kernel calls, as well as macro-kernels (for declaring and initializing the structs) according to above change. commit 392428dea4001fe4384efe29f6cde32f8abeeb35 Author: Field G. Van Zee Date: Thu Dec 12 19:01:47 2013 -0600 Added "ri" scalar macros. Details: - Added set of basic scalar macros that take arguments' real and imaginary components separately, named like the previous set except with the "ris" (instead of "s") suffix. - Redefined the previous set of scalar macros (those that take arguments "whole") in terms of the new "ri" set. - Renamed setris and getris macros to sets and gets. - Renamed setimag0 macros to seti0s. - Use bli_?1 macro instead of a local constant in bla_trmv.c, bla_trsv.c. commit f60c8adc2f61eaba06b892f4e73000159de93056 Author: Field G. Van Zee Date: Tue Dec 10 14:39:56 2013 -0600 Minor updates to dunnington configuration. Details: - Added commented alternatives to dunnington configuration's bli_kernel.h. - Minor reformatting of optimization flag variables in make_defs.mk. commit 4ef20150492db254b5baf2368add62e19b0ac11b Author: Field G. Van Zee Date: Mon Dec 9 18:53:03 2013 -0600 Tweaks to dunnington configuration (x86_64/core2). Details: - Updated BLIS_DEFAULT_KC_D from 256 to 384. - Enabled cache blocksize extension of up to 25% for MC and KC (for double-precision real). commit 5ad2ce7bf5ba3ea955e6d517bfd270e02820263b Author: Field G. Van Zee Date: Mon Dec 9 18:30:49 2013 -0600 Minor x86_64 (core2) kernel fixes. Details: - Fixed copy-and-paste bug whereby [scz]gemmtrsm_u_opt_d4x4 kernels for x86_64/core2 were calling the wrong reference code (l instead of u). - Fixed some unused variables in x86_64/core2 dotaxpyv and dotxaxpyf kernels. - Minor typecasting fix in testsuite/src/test_libblis.c. - Makefile updates. commit d289f5d3a9c0e1a68a17c1c32b736e282a289c4c Author: Field G. Van Zee Date: Thu Dec 5 10:56:13 2013 -0600 Whitespace changes to level-2 blocked variants. Details: - Joined some lines in level-2 blocked variants to match formatting used in level-3 blocked variants. - Streamlined implementation of bli_obj_equals() in bli_query.c. commit b444489f100d218bc8ef29b01ff8489c358559f9 Author: Field G. Van Zee Date: Tue Dec 3 16:08:30 2013 -0600 Added new "attached" scalar representation. Details: - Added infrastructure to support a new scalar representation, whereby every object contains an internal scalar that defaults to 1.0. This facilitates passing scalars around without having to house them in separate objects. These "attached" scalars are stored in the internal atom_t field of the obj_t struct, and are always stored to be the same datatype as the object to which they are attached. Level-3 variants no longer take scalar arguments, however, level-3 internal back-ends stll do; this is so that the calling function can perform subproblems such as C := C - alpha * A * B on-the-fly without needing to change either of the scalars attached to A or B. - Removed scalar argument from packm_int(). - Observe and apply attached scalars in scalm_int(), and removed scalar from interface of scalm_unb_var1(). - Renamed the following functions (and corresponding invocations): bli_obj_init_scalar_copy_of() -> bli_obj_scalar_init_detached_copy_of() bli_obj_init_scalar() -> bli_obj_scalar_init_detached() bli_obj_create_scalar_with_attached_buffer() -> bli_obj_create_1x1_with_attached_buffer() bli_obj_scalar_equals() -> bli_obj_equals() - Defined new functions: bli_obj_scalar_detach() bli_obj_scalar_attach() bli_obj_scalar_apply_scalar() bli_obj_scalar_reset() bli_obj_scalar_has_nonzero_imag() bli_obj_scalar_equals() - Placed all bli_obj_scalar_* functions in a new file, bli_obj_scalar.c. - Renamed the following macros: bli_obj_scalar_buffer() -> bli_obj_buffer_for_1x1() bli_obj_is_scalar() -> bli_obj_is_1x1() - Defined new macros to set and copy internal scalars between objects: bli_obj_set_internal_scalar() bli_obj_copy_internal_scalar() - In level-3 internal back-ends, added conditional blocks where alpha and beta are checked for non-unit-ness. Those values for alpha and beta are applied to the scalars attached to aliases of A/B/C, as appropriate, before being passed into the variant specified by the control tree. - In level-3 blocked variants, pass BLIS_ONE into subproblems instead of alpha and/or beta. - In level-3 macro-kernels, changed how scalars are obtained. Now, scalars attached to A and B are multiplied together to obtain alpha, while beta is obtained directly from C. - In level-3 front-ends, removed old function calls meant to provide future support for mixed domain/precision. These can be added back later once that functionality is given proper treatment. Also, removed the creating of copy-casts of alpha and beta since typecasting of scalars is now implicitly handled in the internal back-ends when alpha and beta are applied to the attached scalars. commit 992de486d6f23e69a623abd15ae77d7881d13871 Merge: 9552e6ee fd4ac636 Author: Field G. Van Zee Date: Mon Dec 2 13:58:46 2013 -0600 Unimplemented kernels now call reference. Details: - Updated arm, bgq, loongson3a, and x86_64 kernels so that unimplemented datatypes call the corresponding reference kernel. Previously, these kernel functions called abort() with a "not yet implemented" error message. commit fd4ac636d9a55cec1476a444bd4e70def219dc8f Author: Field G. Van Zee Date: Mon Dec 2 13:50:36 2013 -0600 Unimplemented kernels now call reference. Details: - Updated micro-kernels for arm, bgq, loongson3a, and x86_64 so that unimplemented kernel functions simply call the corresponding reference implementation. (Previously, these unimplemented functions would abort() with a "not yet implemented" message.) commit 9552e6ee824d4345d5e908e869e071d19829819a Author: Field G. Van Zee Date: Sun Nov 24 11:40:31 2013 -0600 Removed optional scaling from packm control tree. Details: - Removed does_scale field from packm control tree node and bli_packm_cntl_obj_create() interface. Adjusted all invocations of _cntl_obj_create() accordingly. - Redefined/renamted macros that are used in aliasing so that now, bli_obj_alias_to() does a full alias (shallow copy) while bli_obj_alias_for_packing() does a partial alias that preserves the pack_mem-related fields of the aliasing (destination) object. - Removed bli_trmm3_cntl.c, .h after realizing that the trmm control tree will work just fine for bli_trmm3(). - Removed some commented vestiges of the typecasting functionality needed to support heterogeneous datatypes. commit e65c476284db9ef64b23191a21c2584b1083342f Author: Field G. Van Zee Date: Tue Nov 19 10:05:35 2013 -0600 Minor updates to packm_blk_var2.c and _blk_var3.c. Details: - Comment updates to packm_blk_var2.c and packm_blk_var3.c. - In packm_blk_var2(), call setm_unb_var1(), scal2m_unb_var1() directly instead of setm(), scal2m(). commit 9e1d0d4bca48eda54301d8976f203e2544c9df3a Author: Field G. Van Zee Date: Mon Nov 18 18:11:07 2013 -0600 Added trsm_l, trsm_u ukernels for x86_64/core2. Details: - Added standalone trsm_l/trsm_u micro-kernels for x86_64 (core2). These kernels are based on the gemmtrsm_l/gemmtrsm_u micro-kernels that already existed in kernels/x86_64/core2-sse3/3. commit 85e7e02ea3a9190b6fcff5d46b00d41c79cb1242 Merge: 67761e22 70720054 Author: Field G. Van Zee Date: Mon Nov 18 12:02:00 2013 -0600 Merge branch 'master'. Forgot to git-pull. commit 67761e224c92500eecf9c1540cc72bdd2fb27679 Author: Field G. Van Zee Date: Mon Nov 18 11:57:40 2013 -0600 Attempting to fix errors in bgq build. Details: - Removed restrict declaration from b_cast and c_cast from bli_trsm_lu_ker_var2.c and bli_trsm_rl_ker_var2.c. Curiously, they are causing problems for xlc only in those two files and no other macro-kernels. - Fixed (hopefully) kernel function parameter type declarations in kernels/bgq/1f/bli_axpyf_opt_var1.c and kernels/bgq/3/bli_gemm_8x8.c. commit 707200541d344f98cf34c9801954dbb36fbe0447 Author: Field G. Van Zee Date: Mon Nov 18 11:17:31 2013 -0600 Syntax error fix in x86_64/core2 gemmtrsm_u ukr. commit bbe2b84a49e7785d4d0c514cda34adfbe66478b0 Author: Field G. Van Zee Date: Mon Nov 18 11:11:06 2013 -0600 Updated Makefile in test, testsuite. Details: - Updated Makefiles in test and testsuite directories to use the new BLIS header installation directory scheme, which is to compile with -I/include/blis instead of -I/include. commit 9bd7fcfd436625ca2108128086671319362f4d92 Author: Field G. Van Zee Date: Mon Nov 18 10:58:09 2013 -0600 Outer-to-inner 'restrict' fix in macro-kernels. Details: - Fixed sloppy placement of 'restrict' pointer declarations in level-3 macro-kernels. Previously, all restricted pointers were being declared at the outer-most function scope level. While this violates the C99 standard, very few of the compilers used with BLIS so far have seemed to care. The lone exception has been IBM's xlc. Thanks to Tyler Smith for identifying this bug (and suggesting the fix). commit 50549a6a31dd26cf63a013e0ede16b2c7ce835b6 Author: Field G. Van Zee Date: Sun Nov 17 18:31:27 2013 -0600 Changed header install directory to include/blis. Details: - Changed top-level Makefile so that headers are installed to $(INSTALL_PREFIX)/include/blis/. (Header directories are no longer named by version/configuration and then symlinked.) - Added uninstall targets, including uninstall-old to clean out old library archives. - Added GREP makefile definitions to all configurations' make_defs.mk. commit d70733abddfb9a95661897e1e4f3c1f3cfa7cbaa Author: Field G. Van Zee Date: Sat Nov 16 17:34:25 2013 -0600 Added ARM kernels, configurations. Details: - Added kernels for ARM, and configurations for Cortex-A9 and Cortex-A15. Thanks to Francisco Igual for contributing these kernels and configurations. commit d37c2cff62089c86983c2f79762f4b5329037373 Author: Field G. Van Zee Date: Wed Nov 13 10:47:11 2013 -0600 Minor comment and Makefile changes. Details: - Added missing 'check-config' and 'check-make-defs' targets to testsuite/Makefile. - Removed unused 'test' target from top-level Makefile. - Comment changes to testsuite input files. commit 19885f893a17b91ee79bead0620d0f913392d4c5 Author: Field G. Van Zee Date: Mon Nov 11 12:09:21 2013 -0600 Updated some kernel comment headers. Details: - Updated bgq and piledriver comment headers to use BLIS copyright header instead of libflame. commit 1a4d698f42981d74fe5f29b980031e1ee7dc42d5 Author: Field G. Van Zee Date: Mon Nov 11 10:15:40 2013 -0600 CHANGELOG update (for 0.1.0). commit 089048d5895a30221b6b1976c9be93ad6443420d (tag: 0.1.0) Author: Field G. Van Zee Date: Sat Nov 9 17:18:00 2013 -0600 Added object wrappers to 1f test suite modules. Details: - Added missing object wrappers to level-1f test suite modules. This was only apparent if you were configuring with something other than the reference configuration. - Commented out object-wrappers in level-1f front-ends. These were not working as intended the reference configuration was selected, because most kernel sets, such as those in the template set, do not have object wrappers. - Whitespace changes to template micro-kernels. - Comment changes to template level-1f kernel headers. commit 9ef3752079de10124bed906b5d28479d04aa8187 Author: Field G. Van Zee Date: Fri Nov 8 17:20:47 2013 -0600 Updated template kernels wrt KernelsHowTo wiki. Details: - Merged latest state of KernelsHowTo wiki into template micro-kernels located in config/template/kernels/3. commit 376bbb59c8944e29c5c1ff6637920d8451370afa Author: Field G. Van Zee Date: Fri Nov 8 11:17:34 2013 -0600 Removed support for duplication. Details: - Removed support for duplication from the gemmtrsm/trsm micro-kernels and all framework code. - Updated test suite modules according to above changes. commit 68a5910974b62b4df853fae2a68cb04df9d5a19c Author: Field G. Van Zee Date: Thu Nov 7 11:36:11 2013 -0600 Added comments to testsuite/input.operations. Details: - Added extensive comments to the top of testsuite/input.operations, which describe how to edit the file. - Removed input.operations.0 and input.operations.1. - Changed input.general to test all datatypes ("sdcz") by default. commit a98f78b715fb256a519870071bb5266130d70b21 Author: Field G. Van Zee Date: Wed Nov 6 15:32:47 2013 -0600 Changed dim_t and inc_t to be signed integers. Details: - Redefined dim_t and inc_t in terms of gint_t (instead of guint_t). This will facilitate interoperability with Fortran in the future. (Fortran does not support unsigned integers.) - Redefined many instances of stride-related macros so that they return or use the absolute value of the strides, rather than the raw strides which may now be signed. Added new macros bli_is_row_stored_f() and bli_is_col_stored_f(), which assume positive (forward-oriented) strides, and changed the packm_blk_var[23] variants to use these macros instead of the existing bli_is_row_stored(), bli_is_col_stored(). - Added/adjusted typecasting to to various functions/macros, including bli_obj_alloc_buffer(), bli_obj_buffer_at_off(), and various pointer- related macros in bli_param_macro_defs.h. - Redefined bli_convert_blas_incv() macro so that the BLAS compatibility layer properly handles situations where vector increments are negative. Thanks to Vladimir Sukharev for pointing out this issue. - Changed type of increment parameters in bli_adjust_strides() from dim_t to inc_t. Likewise in bli_check_matrix_strides(). - Defined bli_check_matrix_object(), which checks for negative strides. - Redefined bli_check_scalar_object() and bli_check_vector_object() so that they also check for negative stride. - Added instances of bli_check_matrix_object() to various operations' _check routines. commit 1f8afc3e08a4312cfe810be86aedeacbc57275c5 Author: Field G. Van Zee Date: Wed Nov 6 10:09:10 2013 -0600 Minor comment update to BLAS compat files. commit 1abbf768afafc158d44e4d5c4a135cfd9e277f13 Author: Field G. Van Zee Date: Mon Nov 4 15:50:00 2013 -0600 Fixed bugs in scalv and setv. Details: - Fixed bugs similar to those addressed in cca1e1f51dc6, whereby a segmentation fault may occur if beta is not the same type as the vector operand for scalv and setv. - Changed axpyv and scal2v front-ends in a similar fashion. commit f5953259a1842ee48e5833c22ac86e68a337bfe1 Author: Field G. Van Zee Date: Mon Nov 4 14:43:55 2013 -0600 Fixed a bug related to Hermitian matrix diagonals. Details: - Fixed a bug whereby BLIS assumed that the imaginary components of the diagonal elements of Hermitian matrices were already zero. This property is now enforced when the matrix is packed (bli_packm_blk_var2). Thanks to Vladimir Sukharev for reporting this bug. - Minor comment updates to template kernels. commit d70f2b089dac8b9e4c19295dfa6014c36afee2ec Author: Field G. Van Zee Date: Sat Nov 2 17:19:40 2013 -0500 Added scaling to abval2s, sqrt2s macros. Details: - Re-defined abval2s and sqrt2s macros to use scaling to avoid underflow and overflow from squaring the real and imaginary components. (This is the same technique used to fix recent bugs in invscals/invscaljs and inverts.) commit c5b1ed9409ae2f71d04041eef5da9a0080b5784a Author: Field G. Van Zee Date: Fri Nov 1 10:28:04 2013 -0500 Added new dotxaxpyf variant 2. Details: - Added a new variant for dotxaxpyf that is based on dotxf and axpyf kernels. By default, this variant is not used by any other operation. commit 97f89fbcf202d72fc440b614708e352ea31633e2 Author: Field G. Van Zee Date: Fri Nov 1 10:16:39 2013 -0500 Fixed bug in complex invscals. Details: - Fixed complex inversion in invscals and invscaljs whereby the imaginary component was being computed incorrectly. - Use bli_fmaxabs() instead of bli_fabs() when choosing the scalar in inverts, invscals, and invscaljs. - Changed bli_abs() and bli_fabs() macro definitions to use "<=" operator instead of "<". commit eda42a21d17a2742eab69ab801ed530b82488c8a Author: Field G. Van Zee Date: Thu Oct 31 18:00:44 2013 -0500 Defined missing symbols in bla_rotg.c Details: - Defined local equivalents of libf2c's r_sign(), d_sign(), c_abs(), and z_abs(), which are needed by bla_rotg.c. Also defined r_abs() and d_abs() for completeness. Thanks to Vladimir Sukharev for reporting these bugs. commit cca1e1f51dc67a2c3725d5c1837256831aaf70f8 Author: Field G. Van Zee Date: Wed Oct 30 14:39:01 2013 -0500 Fixed bugs in scalm and setm. Details: - Fixed bugs in scalm and setm that resulted in segmentation faults when beta is not the same type as the matrix operand. Thanks to Vladimir Sukharev for reporting this bug. - Changed axpym and scal2m front-ends in fashion similar to that of scalm and setm; namely, the alpha scalar is copy-cast the type of the first matrix operand. - Changed the template and reference configurations' bli_config.h files so that the number of memory allocator blocks of A and B are set based on BLIS_MAX_NUM_THREADS. - Comment updates to bli_obj.c and variable rename in bla_nrm2.c. commit 2807013a4761c2b84b3944de64d23483ad7ef2fb Author: Field G. Van Zee Date: Thu Oct 24 14:32:20 2013 -0500 Fixed over/under-flow in complex inversion. Details: - Fixed the complex bli_?inverts() macros, which were inverting elements in an "unsafe" manner, such that very large and very small values were unnecessarily over/under-flowing. Thanks for Vladimir Sukharev for reporting this bug. - Comment update to bli_sumsqv_unb_var1.c. - Removed redundant bli_min() macro in bli_scalar_macro_defs.h. - Changed 1.0F to 1.0 for bli_drands() macro. commit 45a80c625f84edb2ade6ac25efe2b9c589d7e0df Author: Field G. Van Zee Date: Wed Oct 23 12:15:25 2013 -0500 Fixed parameter checking issue in BLAS syr[2]k. Details: - Fixed a minor parameter checking bug in the BLAS compatibility layer for [sd]syrk and [sd]syr2k. Specifically, if 'C' is passed in for the trans parameter of either operation, it is (a) allowed, and (b) treated as 'T' (whereas previously it was disallowed). Thanks for Vladimir Sukharev for finding and reporting this bug. commit a091a219bda55e56817acd4930c2aa4472e53ba5 Author: Field G. Van Zee Date: Mon Oct 14 10:11:29 2013 -0500 Minor fixes to piledriver configuration, ukernel. Details: - Applied a patch from Tyler that fixes minor staleness in the piledriver configuration and gemm micro-kernel. - Very minor changes to test suite input files. commit dacdde27aee4fb90b14880136d7f20c6b234e2c6 Author: Field G. Van Zee Date: Fri Oct 11 11:37:19 2013 -0500 Added Fran's Sandy Bridge kernels/configuration. Details: - Added a kernel directory for kernels developed by Francisco Igual for the Sandy Bridge architecture, including a dgemm ukernel coded with AVX intrinsics. - Added a configuration for Sandy Bridge using values supplied by Fran. commit 03106d650e4030d4c9831683448376f92fc52d41 Author: Field G. Van Zee Date: Fri Oct 11 10:40:38 2013 -0500 Fixed minor perf bug in gemm_ker_var2. Details: - Fixed a minor performance bug in bli_gemm_ker_var2.c (and the experimental bli_gemm_ker_var5.c) whereby the addresses for a_next and b_next are not computed correctly (ie: do not wraparound) at the edge cases. Thanks to Tze Meng for helping me identify this bug. commit b053337387dbdef9035be03538222670a21707ca Author: Field G. Van Zee Date: Thu Oct 10 18:26:55 2013 -0500 Added fusing factors, MR/NR to test suite output. Details: - Updated the test suite driver (and modules where appropriate) so that the level-1f fusing factors are output along with the variable dimension. While this is not strictly necessary, since the fusing factors are output in the initial parameter summary, it allows extra reassurance to the user since the fusing factors appear alongside the variable dimension, which together give a complete picture of the problem size. Similar changes were made for outputting the register blocksizes when reporting results for the micro-kernel test modules. commit be4833bd91c5a58d0bfc52daaadf7ba543a77acf Author: Field G. Van Zee Date: Thu Oct 10 14:20:06 2013 -0500 Added test suite modules for level-1f, 3 kernels. Details: - Added test modules in test suite for level-1f kernels and level-3 micro-kernels. (Duplication in the micro-kernels, for now, is NOT supported by these test modules.) - Added section override switches to test suite's input.operations file. - Added obj_t APIs for level-1f front-ends and their unblocked variants to facilitate the level-1f test modules. Also added front-end for dupl operation. - Added obj_t-based check routines for level-1f operations, which are called from the new front-ends mentioned above. - Added query routines for axpyf, dotxf, and dotxaxpyf that return fusing factors as a function of datatype, which is needed by their respective test modules. - Whitespace changes to bli_kernel.h of all existing configurations. commit 680188d46bb15b9a1a2867638104939dc77ca2a1 Author: Field G. Van Zee Date: Thu Oct 10 13:23:37 2013 -0500 Cleaned up old test drivers. Details: - Minor updates to old test drivers in preparation for our participation in ACM TOMS's replicated results initiative. commit 3690bdd4f95769c935c410414112102cc3e108b1 Author: Field G. Van Zee Date: Thu Oct 10 11:45:33 2013 -0500 More updates to level-1f kernels for core2-sse3. Details: - Changed types in function signatures to match new prototypes. Meant to include this in previous commit. commit 661d5120cd7071f9b0c5cefc95f99f1361370ade Author: Field G. Van Zee Date: Thu Oct 10 11:27:27 2013 -0500 Fixed outdated fusing factor macros in 1f kernels. Details: - Updated level-1f kernels for x86_64 and bgq to use renamed fusing factor macros. Meant to include this in 5e54f46c. Thanks to Fran for pointing this out. commit 73aa1e9f31d1b2a319c7e711ced6db3f9835c832 Author: Field G. Van Zee Date: Tue Oct 1 17:01:18 2013 -0500 Added section overrides to test suite. Details: - Added new lines of input to the test suite's input.operations file, which allows the user to disable entire sections (levels) of tests. Before this change, the user had to manually disable each operation tests's "master switch". (This is why input.operations.0 existed: to allow a more convenient starting point for someone who only wanted to test one or a few operations.) commit 5e54f46ccb76beab892d530b693e07c6bf6db7cf Author: Field G. Van Zee Date: Mon Sep 30 12:58:18 2013 -0500 Added template implementations and other tweaks. Details: - Added a 'template' configuration, which contains stub implementations of the level 1, 1f, and 3 kernels with one datatype implemented in C for each, with lots of in-file comments and documentation. - Modified some variable/parameter names for some 1/1f operations. (e.g. renaming vector length parameter from m to n.) - Moved level-1f fusing factors from axpyf, dotxf, and dotxaxpyf header files to bli_kernel.h. - Modifed test suite to print out fusing factors for axpyf, dotxf, and dotxaxpyf, as well as the default fusing factor (which are all equal in the reference and template implementations). - Cleaned up some sloppiness in the level-1f unb_var1.c files whereby these reference variants were implemented in terms of front-end routines rather that directly in terms of the kernels. (For example, axpy2v was implemented as two calls to axpyv rather than two calls to AXPYV_KERNEL.) - Changed the interface to dotxf so that it matches that of axpyf, in that A is assumed to be m x b_n in both cases, and for dotxf A is actually used as A^T. - Minor variable naming and comment changes to reference micro-kernels in frame/3/gemm/ukernels and frame/3/trsm/ukernels. commit 97aaf220a847363b4da35935eca17790c0ef71f6 Author: Field G. Van Zee Date: Tue Sep 17 10:51:36 2013 -0500 Added new kernels, configurations. Details: - Added various micro-kernels for the following architectures: Intel MIC IBM BG/Q IBM Power7 AMD Piledriver Loogson 3A and reorganized kernels directory. Thanks to Tyler Smith, Mike Kistler, and Xianyi Zhang for contributing these kernels. - Added configurations corresponding to above architectures, and renamed "clarksville" configuration to "dunnington". commit fe979c5a114c877506a5697cdab1fc8cf2bcd303 Author: Field G. Van Zee Date: Fri Sep 13 14:31:53 2013 -0500 Removed default configuration behavior. Details: - Changed the configure script so that it no longer defaults to the reference configuration. This change is being made so that the developer has a firm awareness of which configuration is being used to configure BLIS. Thanks to Mike Kistler and Bryan Marker for this suggested change. commit da77e9614f54f92f703f01e3b9bd67a83280150c Author: Field G. Van Zee Date: Fri Sep 13 12:00:37 2013 -0500 Minor improvements to static memory allocator. Details: - Expanded on cpp macro definitions from bli_mem.c and relocated them to a new header file, frame/include/bli_mem_pool_macro_defs.h. The expanded functionality includes computing the pool size for each datatype (using that datatype's cache blocksizes) and using the maximum to size the actual pool array. This addresses the somewhat common pitfall whereby a developer updates cache blocksizes in bli_kernel.h for only one datatype (say, single-precision real), while the memory pools are sized using the double-precision real values. Then, when the developer attempts to link to and run a level-3 BLIS routine (e.g. dgemm), the library aborts with a message saying the static memory pool was exhausted. Clearly, this message is misleading when the pool was not sized properly to begin with. - Removed previously disabled code in bli_kernel_macro_defs.h that was meant to check for size consistency among the various cache blocksizes. (Obviously the memory pool size-based solution mentioned above is better.) - Added BLIS_SIZEOF_? cpp macros to bli_type_defs.h. This seemed like a reasonable place to put these constants, rather than further crowd up bli_config.h. - Updated testsuite driver to output memory pool sizes for A, B, and C. - Minor comment updates to bli_config.h. - Removed 'flame' configuration. It was beginning to get out-of-date, and I hadn't used it in months. We can always re-create it later. commit 631f347b7a99cb02757c534fd3ec5f723a2fdb0e Author: Field G. Van Zee Date: Tue Sep 10 17:17:28 2013 -0500 Added ESSL and Accelerate targets to test drivers. Details: - Added ESSL and Accelerate (OS X) targets to standalone test drivers' Makefile in "test" directory. Thanks to Jeff Hammond for suggesting / providing this patch. commit 7ae4d7a41d13ef5f1ceee217c000a5cf77a11128 Author: Field G. Van Zee Date: Tue Sep 10 16:35:12 2013 -0500 Various changes to treatment of integers. Details: - Added a new cpp macro in bli_config.h, BLIS_INT_TYPE_SIZE, which can be assigned values of 32, 64, or some other value. The former two result in defining gint_t/guint_t in terms of 32- or 64-bit integers, while the latter causes integers to be defined in terms of a default type (e.g. long int). - Updated bli_config.h in reference and clarksville configurations according to above changes. - Updated test drivers in test and testsuite to avoid type warnings associated with format specifiers not matching the types of their arguments to printf() and scanf(). - Inserted missing #include "bli_system.h" into blis.h (which was slated for inclusion in d141f9eeb6d1). - Added explicit typecasting of dim_t and inc_t to macros in bli_blas_macro_defs.h (which are used in BLAS compatibility layer). - Slight changes to CREDITS and INSTALL files. - Slight tweaks to Windows build system, mostly in the form of switching to Windows-style CRLF newlines for certain files. commit 068437736b41d51a1f5ec47839f059bf58a20413 Author: Field G. Van Zee Date: Mon Sep 9 14:07:58 2013 -0500 Fixed set-but-not-used compiler (gcc) warnings. Details: - Used void-casts of certain variables to appease gcc (and perhaps other compilers) when such variables are only used in the complex instances of the functions. Special thanks to Karl Rupp for suggesting a portable fix for these warnings. commit 6dc85f63dcd5282340c9e00d585e97d70a21edc3 Author: Field G. Van Zee Date: Mon Sep 9 13:48:52 2013 -0500 Small fix to Windows defs.mk makefile fragment. Details: - Commented out a !include statement that was attempting to include a version file that does not yet exist. For now, the version string is hard-coded into defs.mk. commit d141f9eeb6d1de7044b7429adf52d11c6fca620c Author: Field G. Van Zee Date: Mon Sep 9 13:09:16 2013 -0500 Added Windows build system. Details: - Added a 'windows' directory, which contains a Windows build system similar to that of libflame's. Thanks to Martin for getting this up and running. - Spun off system header #includes into bli_system.h, which is included in blis.h - Added a Windows section to bli_clock.c (similar to libflame's). commit 9b320e7406fb69e8b61a0085abe2ed89a96bdb68 Author: Field G. Van Zee Date: Mon Sep 9 11:04:46 2013 -0500 Edited bli_?lamch.c to avoid Windows keyword. Details: - Renamed "small" variable to "smnum" to avoid collision with Windows type by the same name. This change is needed in advance of the upcoming Windows build system. commit 9013ad6ff2e9ace35e0cf44c32795c2f3d5be628 Author: Field G. Van Zee Date: Wed Sep 4 13:36:07 2013 -0500 Switched integer typedefs (again) to C types. Details: - Redefined gint_t and guint_t in terms of the standard C types long int and unsigned long int, respectively. - Changed testsuite default max problem size to 500. - Changed testsuite input.operations to use square problems for level-3 operation tests. commit 981a60cfa07abac2e93697dfe12b0f076ab00a38 Author: Field G. Van Zee Date: Wed Sep 4 12:09:11 2013 -0500 Falling back to 32-bit integers for dim_t, etc. Details: - In light of recent segfaulting issues when compiling on 32-bit systems, I've changed the default typedef for gint_t and guint_t from int64_t and uint64_t to int32_t and uint32_t, respectively. - Disabled 64-bit integers in the blas2blis layer for the reference configuration. - Added type sizes of gint_t, guint_t, and the four floating-point datatypes to introductory output of the testsuite. commit b776ddcd4338b34f172ef78da0ac1d771a771ab4 Author: Field G. Van Zee Date: Tue Sep 3 21:58:07 2013 -0500 Applied temp fix to typecasting bug in testsuite. Details: - Applied a temporary fix to the typecasting bug in the testsuite driver. The fix involves casting both numerator and denominator to unsigned long. This fix is more voodoo than science, as I can't be sure why it even works. commit 9ee6e125373869c4213c017ce772c38ecefba103 Author: Field G. Van Zee Date: Tue Sep 3 21:53:27 2013 -0500 Changed dimension spec for gemm in testsuite. Details: - Encounted a bizarre typecasting bug whereby the test suite was not computing the proper dimension from the problem size and dimension specification when the latter was set to -3. Will investigate. Thanks to Fran for finding this "bug". commit e8be081e68c385ab44d0fea8dade21d40c200b79 Author: Field G. Van Zee Date: Wed Aug 28 15:52:34 2013 -0500 Generalized matlab and file output in testsuite. Details: - Added a new option in input.general that allows outputting in matlab/octave format so that one can output in matlab format independently from outputting to files. - Adjusted input.operations according to above. - Added input.operations.0 and input.operations.1 with all options disabled and enabled, respectively. commit d352c746e5683037d41b5061dfb5ce08e1d0843b Author: Field G. Van Zee Date: Tue Aug 27 13:41:46 2013 -0500 Added single/real gemm micro-kernel for x86_64. Details: - Added a single-precision real gemm micro-kernel in kernels/x86_64/3/bli_gemm_opt_d4x4.c. - Adjusted the single-precision real register blocksizes in config/clarksville/bli_kernel.h to be 8x4. - Added a missing comment to bli_packm_blk_var2.c that was present in bli_packm_blk_var3.c commit dedda523dc5dc779ecc34e6a03dc74cb8eb220de Author: Field G. Van Zee Date: Mon Aug 19 12:07:41 2013 -0500 Fixed bug in bli_acquire_mpart_t2b(), _l2r(). Details: - Fixed a bug in bli_acquire_mpart_t2b() and bli_acquire_mpart_l2r() that cause incorrect partitioning when SUBPART0 was requested. This bug was introduced in 46d3d09d49ad. Thanks to Bryan for isolating this bug. - Removed dupl kernels from kernels/x86_64/3 directory. - Uncommented beta == 0 optimizaition code in kernels/x86_64/3/bli_gemm_opt_d4x4.c. commit 12dbd2f33455e9384fe2070cbdd660fd4a7fceb5 Author: Field G. Van Zee Date: Thu Aug 8 14:39:35 2013 -0500 Moved init_safe(), finalize_safe() to BLAS compat. Details: - Moved the bli_init_safe() and bli_finalize_safe() function calls from the BLAS-like BLIS layer to the BLAS compatibility layer. Having these auto- initializers in the BLIS layer wasn't buying us anything because the user could still call the library with uninitialized global scalar constants, for example. Thus, we will just have to live with the constraint that bli_init() MUST be called before calling ANY routine with a bli_ prefix. - Added the missing _init_safe() and finalize_safe() calls to the level-1 BLAS compatibility wrappers. commit 8abfe55f2ae5d89df18e1b26a5a28d94b0936683 Author: Field G. Van Zee Date: Thu Aug 8 13:30:19 2013 -0500 Miscellaneous updates. Details: - Changed the BLIS_HEAP_STRIDE_ALIGN_SIZE in the configurations from 16 to BLIS_CACHE_LINE_SIZE (typically 64). - Changed the use of nr in sizing of bd buffer to packnr in level-3 macro- kernels. - Reformulated gemm_ker_var2 to look more like the other level-3 macro- kernels, in that the interior and edge-case handling is expressed once inside the loops in the n and m dimensions, rather than the edge-case handling being "unrolled" and expressed as distinct code regions. The previous macro-kernel now lives in retired form in the subdirectory other/bli_gemm_ker_var2.c.old. - Updated experimental gemm_ker_var5 according to above change. - Fixed bug in bli_her2k.c whereby incorrect transformations were being applied to optimize the macro-kernel accesses pattern on C when C is row-stored. - Various updates inside of test/exec_sizes. commit 1aa05736ff49e7cc5f121acf615460fe9a87852c Author: Field G. Van Zee Date: Wed Aug 7 12:27:04 2013 -0500 Fixed bug in interface of bla_ger_check(). Details: - Fixed the misplaced lda parameter in the function signature of bla_ger_check(). Thanks to Tyler for finding this bug. commit 685aad25353fb200de4ca97a8bc0feeebde51d0f Author: Field G. Van Zee Date: Tue Aug 6 12:25:51 2013 -0500 Fixed cpp guard typos in frame/compat/check files. Details: - Fixed instances of BLIS_ENABLE_BLIS2BLAS that should have been BLIS_ENABLE_BLAS2BLIS. Thanks to Tyler for catching this. - Fixed various syntax errors in the code that had yet to be compiled due to the aforementioned bug. commit f4ec28e723d28d998f1038f82da6986e44320ef6 Author: Field G. Van Zee Date: Thu Aug 1 11:24:23 2013 -0500 Added basic OpenMP-based gemm and packm files. Details: - Integrated Tyler's parallelized packm_blk_var2 and gemm_ker_var2 into the following auxiliary files frame/1m/packm/other/bli_packm_blk_var2.c frame/3/gemm/other/bli_gemm_ker_var2.c The routine in the first file uses a basic OpenMP parallel region to parallelize the packing of blocks of A and panels of B, while the second uses a similar parallel region to parallelize along the n dimension of the gemm macro-kernel. commit f8980edf9c318453bb1962ac4939c06bf11e6d5e Merge: 67a8b949 6e7e4523 Author: Field G. Van Zee Date: Fri Jul 26 11:14:27 2013 -0500 Merge branch 'master' of https://code.google.com/p/blis commit 67a8b9498d13b038deb316ac163e62c5b17da2ec Author: Field G. Van Zee Date: Fri Jul 26 11:12:37 2013 -0500 Added missing cpp kernel blocksize constraints. Details: - Added missing C preprocessor guards in bli_kernel_macro_defs.h that enforce constraints on the register blocksizes relative to the cache blocksizes. Thanks to Tyler for helping me stumble across this issue. commit 6e7e452343014e8f86640874dc1dbadca4a642a1 Author: Field G. Van Zee Date: Mon Jul 22 14:50:57 2013 -0500 Fixed minor warnings and misc issues. Details: - Fixed various warnings output by gcc 4.6.3-1, including removing some set-but-not-used variables and addressing some instances of typecasting of pointer types to integer types of different sizes. commit 03f6c3599743bc837a7d40eb5b415b1bf4f2a4e9 Author: Field G. Van Zee Date: Mon Jul 22 12:54:32 2013 -0500 Tightened some macros that detect datatypes. Details: - Modified the definitions of some macros, such as bli_is_real(), so that the "special" bit is taken into account so that BLIS_INT is differentiated from BLIS_FLOAT. - Whitespace changes to bli_obj_macro_defs.h. - Removed BLIS_SPECIAL_BIT definition from bli_type_defs.h, since it wasn't being used. commit b33e2f4443b9043b554963320280ff7783773652 Author: Field G. Van Zee Date: Fri Jul 19 17:15:03 2013 -0500 CHANGELOG update (for 0.0.9). commit 0680916fdd532f7a4716b11a2515243b2c08d00f (tag: 0.0.9) Author: Field G. Van Zee Date: Thu Jul 18 18:04:34 2013 -0500 Added BLAS error checking to compatibility layer. Details: - Added frame/compat/check directory, which now houses companion _check() routines for each of the BLAS wrappers in frame/compat. These _check() routines are called from the compatibility wrappers and mimic the error-checking present in the netlib BLAS. - Edited bla_xerbla.c so that xerbla() translates the operation string to uppercase before printing. - Redefined util routines in frame/compat/f2c/util in terms of level0 macros. - Added prototypes for util routines, f2c routines, lsame(), and xerbla(). - Commented out prototypes in test/test_*.c since Fortran integers are now int64_t by default (and the prototypes that were present in the files used int). - Removed redundant #include "bli_f2c.h" in bli_?lamch.c and bli_lsame.c, since blis.h was already being included. - Other minor changes to code in frame/compat/f2c. commit 4e80ad28c97273db3366428ec44020da7944964d Author: Field G. Van Zee Date: Thu Jul 18 17:53:31 2013 -0500 Added support for C99 complex types/arithmetic. Details: - Added support for C99 complex types to bli_type_defs.h and overloaded complex arithmetic to the scalar-level macros in include/level0. This includes a somewhat substantial reorganization and re-layering of much of the existing machinery present in the level0 macros. - Added new #define for BLIS_ENABLE_C99_COMPLEX to bli_config.h files, commented-out by default, which optionally enables the use of built-in C99 complex types and arithmetic. - Minor changes to clarksville and reference configs' make_defs.mk files. - Removed macro definitions from bli_param_macro_defs.h which was not being used (bli_proj_dt_to_real_if_imag_eq0). commit 6072d7c848e837ba20d607f7b727438ada31bdcf Author: Field G. Van Zee Date: Wed Jul 17 12:27:45 2013 -0500 Fixed bugs in trsm, trmm macro-kernels. Details: - Fixed a bug in trsm_rl_ker_var2() caused by incorrect edge case handling. - Fixed a bug in trsm_rl_ker_var2() and trsm_ru_ker_var2() whereby k was incorrectly being adjusted upward by MR, instead of NR. The rl and ru trmm macro-kernels were updated in a similar fashion. - Fixed a bug in trsm_ru_ker_var2() that was due to a missing negation on diagoffb when recomputing k to skip a zero region below where the diagonal intersects the right side of the block. The corresponding trmm macro-kernel was also updated. - Fixed a bug in trsm_ru_ker_var2() where the the adjustment of k (by NR) needed to be placed AFTER the block that recomputes k to skip the zero region (if present). The other three trsm macro-kernels, as well as the trmm macro-kernels, were updated in the same manner, for consistency. - Fixed a bug in trmm_lu_ker_var2() in which the wrong dimension (n) was being updated to skip a zero region to the left of where the diagonal of A intersects the top edge of the block. - Comment updates to all trsm and trmm macro-kernels. - Comment updates to bli_packm_init.c. commit 47410a48f9b91e94ce4c67633686ffd1f2ad0275 Author: Field G. Van Zee Date: Wed Jul 10 14:53:59 2013 -0500 Added f2c'ed Givens rotation wrappers. Details: - Retired (for now) existing ?rot*() BLAS compatibility wrappers to 'attic' along with other wrappers for which no BLIS implementation exists. - Added f2c-generated codes for applicable datatype flavors of rot, rotg, rotm, and rotmg operations. commit e5f90f3a8dbe671104bcb9d8b4e3409de01805da Author: Field G. Van Zee Date: Wed Jul 10 13:40:12 2013 -0500 Removed copynz defs from bli_kernel.h files. Details: - Removed COPYNZ_KERNEL definition from the bli_kernel.h files in each configuration. (Meant to include this in previous commit.) commit aec12d90f596e8c04b1ad178258a1cd38108f59d Author: Field G. Van Zee Date: Wed Jul 10 13:33:30 2013 -0500 Removed copynzv, copynzm and related codes. Details: - Removed copynzv and copynzm operation directories. These operations implemented a variation of copyv/m that, in the case of real source and complex destination operands, leaves the imaginary component untouched (rather than setting it to zero). I realize now that the special case(s) (e.g. gemm with real A and B but complex C) that I thought required this operation actually can be handled more simply. - Removed level0 scalar macros implementing copynzs, copynzjs. commit b0a0a0f274a761788531b5d281cc3b411b7124ed Author: Field G. Van Zee Date: Tue Jul 9 17:15:38 2013 -0500 Added handling of restrict, stdint.h for non-C99. Details: - Removed the #include from blis.h and inserted a cpp macro block in bli_type_defs.h that #includes for C++ and C99, and otherwise manually typedefs the types we need (which, for now, are unconditionally int64_t and uint64_t). - Moved basic typedefs to top of bli_type_defs.h, and comment changes. - Added cpp macro block to bli_macro_defs.h that #defines restrict as nothing for C++ and non-C99. commit 4b7e7970f1af4a1ab121e07657e2b78b9fcd7671 Author: Field G. Van Zee Date: Mon Jul 8 15:20:34 2013 -0500 Migrated integer usage to stdint.h types. Details: - Changed the way bli_type_defs.h defines integer types so that dim_t, inc_t, doff_t, etc. are all defined in terms of gint_t (general signed integer) or guint_t (general unsigned integer). - Renamed Fortran types fchar and fint to f77_char and f77_int. - Define f77_int as int64_t if a new configuration variable, BLIS_ENABLE_BLIS2BLAS_INT64, is defined, and int32_t otherwise. These types are defined in stdint.h, which is now included in blis.h. - Renamed "complex" type in f2c files to "singlecomplex" and typedef'ed in terms of scomplex. - Renamed "char" type in f2c files to "character" and typedef'ed in terms of char. - Updated bla_amax() wrappers so that the return type is defined directly as f77_int, rather than letting the prototype-generating macro decide the type. This was the only use of GENTFUNC2I/GENTPROT2I-related macros, so I removed them. Also, changed the body of the wrapper so that a gint_t is passed into abmaxv, which is THEN typecast to an f77_int before returning the value. - Updated f2c code that accessed .r and .i fields of complex and doublecomplex types so that they use .real and .imag instead (now that we are using scomplex and dcomplex). commit 372501398564fdba3d5a3db86c30bc1039b185ff Author: Field G. Van Zee Date: Mon Jul 8 11:24:18 2013 -0500 Added experimental bli_gemm_ker_var5(). Details: - Added support for an experimental gemm macro-kernel incrementally packs one micro-panel of B at a time. This is useful for certain special cases of gemm where m is small. - Minor changes to default values of clarksville configuration. - Defined BLIS_PACKED_BLOCKS as part of pack_t type, even though we do not yet have any use (or implementation support) for block storage. - Comment update to bli_packm_init.c. commit 9915d667a79f23e3a2a2516247c560e9063a1646 Author: Field G. Van Zee Date: Sun Jul 7 13:28:39 2013 -0500 Defined "total" blocksize query functions. Details: - Defined bli_blksz_total_for_type() and bli_blksz_total_for_obj() to query the default blocksize plus blocksize extension (using the type or the type of an object). - Comment update in bli_packm_cxk.c. commit 46d3d09d49aded1d9f1b468c83fce75e07d631dc Author: Field G. Van Zee Date: Thu Jun 27 13:19:56 2013 -0500 Consolidated lower/upper her[2]k blocked variants. Details: - Consolidated lower and upper blocked variants for herk and her2k, and renamed the resulting variants, according to the same changes recently made to trmm and trsm. - Implemented support for four new subpartitions types: BLIS_SUBPART1T BLIS_SUBPART1B BLIS_SUBPART1L BLIS_SUBPART1R which correspond to "merged" partitions that include the middle "1" partition as well as either the neighboring "0" or "2" partition. This is used to clean up code in herk/her2k var2 that attempts to partition away the strictly zero region above or below the diagonal of a matrix operand that is being marched through diagonally. - Added safeguards to herk macro-kernels that skip any leading or trailing zero region in the panel of C that is passed in. This is now needed given that herk/her2k var1 no longer partitions off this zero region before calling the macro-kernel (via bli_her[2]k_int()). - Updated comments and other whitespace changes to trmm/trsm macro-kernels. commit 02002ef6f3d2746665982793db36714bd69bccc9 Author: Field G. Van Zee Date: Mon Jun 24 17:08:14 2013 -0500 Added row-storage optimizations for trmm, trsm. Details: - Implemented algorithmic optimizations for trmm and trsm whereby the right side case is now handled explicitly, rather than induced indirectly by transposing and swapping strides on operands. This allows us to walk through the output matrix with favorable access patterns no matter how it is stored, for all parameter combinations. - Renamed trmm and trsm blocked variants so that there is no longer a lower/upper distinction. Instead, we simply label the variants by which dimension is partitioned and whether the variant marches forwards or backwards through the corresponding partitioned operands. - Added support for row-stored packing of lower and upper triangular matrices (as provided by bli_packm_blk_var3.c). - Fixed a performance bug in bli_determine_blocksize_b() whereby the cache blocksize extensions (if non-zero) were not being used to appropriately size the first iteration (ie: the bottom/right edge case). - Updated comments in bli_kernel.h to indicate that both MC and NC must be whole multiples of MR AND NR. This is needed for the case of trsm_r where, in order to reuse existing left-side gemmtrsm fused micro-kernels, the packing of A (left-hand operand) and B (right-hand operand) is done with NR and MR, respectively (instead of MR and NR). commit d1e81ddc848ee47bc188735883d14582bdd0cabc Author: Field G. Van Zee Date: Thu Jun 13 11:14:21 2013 -0500 Minor generalizing tweaks to trmm blk var1, var2. commit 0efb7974f104206ba3985276f2180a9b14fe9f9b Author: Field G. Van Zee Date: Wed Jun 12 16:40:04 2013 -0500 CHANGELOG update. commit 5b641c3bab31eac6a1795b9f6e3f86c59651ca50 (tag: 0.0.8) Author: Field G. Van Zee Date: Wed Jun 12 16:02:12 2013 -0500 Use separate CFLAGS for "kernels" directories. Details: - Added a new "special" directory type: any source code within directories named "kernels" will be compiled with a separate CFLAGS_KERNELS set of compiler flags. This allows the developer to specify a separate set of flags (e.g. optimization flags) for compiling kernels while maintaining a standard set for regular framework code. - Fixed a bug in the top-level Makefile that was causing "noopt" code to be compiled with the standard set of compilation flags. - Updated make_defs.mk in reference, flame, and clarksville configurations according to above changes. commit 08475e7c7653ba598665071a617d10f0d8f763c2 Author: Field G. Van Zee Date: Tue Jun 11 12:18:39 2013 -0500 Various level-3 optimizations for row storage. Details: - Implemented remaining two cases within bli_packm_blk_var2(), which allow packing from a lower or upper-stored symmetric/Hermitian matrix to column panels (which are row-stored). Previously one could only pack to row panels (which are column-stored). - Implemented various optimizations in the level-3 front-ends that allow more favorable access through row-stored matrices for gemm, hemm, herk, her2k, symm, syrk, and syr2k. - Cleaned up code in level-3 front-ends that has to do with setting target and execution datatypes. commit 05a657a6b92e8d34efa5c57ae6a18a4f35ec0841 Author: Field G. Van Zee Date: Fri Jun 7 11:04:10 2013 -0500 Added beta == 0 optimization to x86_64 ukernel. Details: - Modified x86_64 gemm microkernel so that when beta is zero, C is not read from memory (nor scaled by beta). - Fixed minor bug in test suite driver when "Test all combinations of storage schemes?" switch is disabled, which would result in redundant tests being executed for matrix-only (e.g. level-1m, level-3) operations if multiple vector storage schemes were specified. - Restored debug flags as default in clarksville configuration. commit f1aa6b81cc421516dd77dd0f18f7c432724e6ef2 Author: Field G. Van Zee Date: Thu Jun 6 13:36:06 2013 -0500 Whitespace changes to old test drivers. Details: - Replaced tabs with four spaces in places where indention was already in place. commit 9feb4c23d2e36f3d8b5417a3802c69f94b29f749 Author: Field G. Van Zee Date: Tue Jun 4 14:57:46 2013 -0500 Fixed unaligned handling in axpyf, dotxaxpyf. Details: - Fixed over-cautious handling of unaligned operands in vector instrinsic implementation of axpyf kernel. - Fixed over- and under-cautious handling of unaligned operands in vector intrinsic implementation of dotxaxpyf kernel. commit 22b06cfcd2e3205c8325a246c2279e4b1047c066 Author: Field G. Van Zee Date: Mon Jun 3 16:54:52 2013 -0500 Updated level-1/-1f [vector intrinsic] kernels. Details: - Updated level-1/-1f kernels so that non-unit and un-aligned cases are handled by reference implementation (rather than aborted). - Added -fomit-frame-pointer to default make_defs.mk for clarksville configuration. - Defined bli_offset_from_alignment() macro. - Minor edits to old test drivers. commit 0288c827d3659bb225ac9c10f168b623ed0106a2 Author: Field G. Van Zee Date: Sat Jun 1 08:02:23 2013 -0500 Updated ukernels for x86_64. Details: - Tweaked micro-kernels and configuration for clarksville. - Updated/cleaned up old test drivers in test directory. - Fixed syntax bug in trsv_unb_var1 and trsv_unf_var1 (introduced recently). commit 85a6d1c9a52c2b27c71a3a3e341c51d7ba263749 Author: Field G. Van Zee Date: Mon May 6 11:05:08 2013 -0500 Replaced axpys usage with subs in trsv. Details: - Replaced instances of axpys with alpha equal to -1 with subs. - Use BLIS_MAX_TYPE_SIZE to define BLIS_CONSTANT_SLOT_SIZE instead of sizeof(dcomplex). commit 2d9c667f3c48a12cab64e5ad09d5fcb9f4c19d78 Author: Field G. Van Zee Date: Fri May 24 16:28:10 2013 -0500 Fixed x86_64 kernel bugs and other minor issues. Details: - Fixed bugs in trmv_l and trsv_u due to backwards iteration resulting in unaligned subpartitions. We were already going out of our way a bit to handle edge cases in the first iteration for blocked variants, and this was simply the unblocked-fused extension of that idea. - Fixed control tree handling in her/her2/syr/syr2 that was not taking into account how the choice of variant needed to be altered for upper-stored matrices (given that only lower-stored algorithms are explicitly implemented). - Added bli_determine_blocksize_dim_f(), bli_determine_blocksize_dim_b() macros to provide inlined versions of bli_determine_blocksize_[fb]() for use by unblocked-fused variants. - Integrated new blocksize_dim macros into gemv/hemv unf variants for consistency with that of the bugfix for trmv/trsv (both of which now use the same macros). - Modified bli_obj_vector_inc() so that 1 is returned if the object is a vector of length 1 (ie: 1 x 1). This fixes a bug whereby under certain conditions (e.g. dotv_opt_var1), an invalid increment was returned, which was invalid only because the code was expecting 1 (for purposes of performing contiguous vector loads) but got a value greater than 1 because the column stride of the object (e.g. rho) was inflated for alignment purposes (albeit unnecessarily since there is only one element in the object). - Replaced some old invocations of set0 with set0s. - Added alpha parameter to gemmtrsm ukernels for x86_64 and use accordingly. - Fixed increment bug in cleanup loop of gemm ukernel for x86_64. - Added safeguard to test modules so that testing a problem with a zero dimension does not result in a failure. - Tweaked handling of zero dimensions in level-2 and level-3 operations' internal back-ends to correctly handle cases where output operand still needs to be scaled (e.g. by beta, in the case of gemm with k = 0). commit d57ec42b34f8447c88adeffa95cf22f8c115ad51 Author: Field G. Van Zee Date: Fri May 3 17:35:32 2013 -0500 Renamed _trans_status() macro. Details: - Mistakenly forgot to rename the _trans_status() macro and instances in previous commit. commit 9e2b227866af429a4a6fb7dbb8c457bbdda2f136 Author: Field G. Van Zee Date: Fri May 3 17:24:58 2013 -0500 Renamed _set_trans(), _trans_status() macros. Details: - Renamed the following macros: bli_obj_set_trans() -> bli_obj_set_onlytrans() bli_obj_trans_status() -> bli_obj_onlytrans_status() to remove ambiguity as to which bits are read/updated. commit 2f8174509ea9f844db11ebd9389de5168e85b132 Author: Field G. Van Zee Date: Wed May 1 15:06:30 2013 -0500 Unconditionally check memory pool(s) for errors. Details: - Changed bli_mem_acquire_m() in bli_mem.c so that we still check if the memory pool is exhausted before checking out and returning a block, even if BLIS error checking has been disabled. These errors are useful because they likely indicate that BLIS was improperly configured for the code being run. commit 75405a2b83679b6aff38d7e7425199d623a7b0a9 Author: Field G. Van Zee Date: Wed May 1 15:00:30 2013 -0500 CHANGELOG update. commit 6bfa96f84887dec0b4cf8be5d38dd634c2f8951d (tag: 0.0.7) Author: Field G. Van Zee Date: Tue Apr 30 19:35:54 2013 -0500 Absorbed blocksize extensions into main objects. Details: - Revamped some parts of commit b6ef84fad1c9 by adding blocksize extension fields to the blksz_t object rather than have them as separate structs. - Updated all packm interfaces/invocations according to above change. - Generalized bli_determine_blocksize_?() so that edge case optimization happens if and only if cache blocksizes are created with non-zero extensions. - Updated comments in bli_kernel.h files to indicate that the edge case blocksize extension mechanism is now available for use. commit bc7c8005cedbe50961ac2a99aeeabf4e9f9a8e9e Author: Field G. Van Zee Date: Thu Apr 25 17:16:59 2013 -0500 Added option to disable err checking in testsuite. Details: - Added a new line to input.general that allows one to specify the error- checking level to use for each BLIS experiment. The only two levels supported for now are "no error checking" and "full error checking". commit 096b366ddcfe386f44419ef84d8df8be13825f86 Author: Field G. Van Zee Date: Thu Apr 25 16:43:43 2013 -0500 Use cntl trees that block in n dimension. Details: - Updated _cntl.c files for each level-3 operation to induce blocked algorithms that first paritition in the n dimension with a blocksize of NC. Typically this is not an issue since only very large problems exceed that of NC. But developers often run very large problems, and so this extra blocking should be the default. - Removed some recently introduced but now unused macros from bli_param_macro_defs.h. commit b6e24b23cb4dfc488c1c9c70d596539c2287f72e Author: Field G. Van Zee Date: Thu Apr 25 12:06:12 2013 -0500 Use PASTEMAC in macro-kernels (over MAC2 or MAC3). Details: - Replaced multi-type invocations of copys_mxn, xpbys_mxn, etc. (PASTEMAC2 and PASTEMAC3) with those that only use a single type (PASTEMAC). - Added extra macros to bli_adds_mxn_uplo.h and bli_xpbys_mxn_uplo.h to accommodate above change. - Fixed comment typo in bli_config.h files. - Added .nfs* pattern to .gitignore. commit df80acf517dde180ddcc5835c6136b2fa7556d4b Author: Field G. Van Zee Date: Tue Apr 23 19:43:23 2013 -0500 Fixed computation of b_next in L3 macro-kernels. Details: - Restructured herk_l and herk_u macro-kernels in the imagine of trmm and trsm, in that the edge cases are captured by the main loop, rather than trying to have "cleanup" sections that result in four distinct parts (interior, bottom edge, right edge, bottom-right edge) of the code. - Fixed the way b_next was being computed in the non-gemm level-3 macro-kernels (herk, trmm, trsm). The way they are computed now matches that of gemm. commit 3671528cf8efe4b445d196665143a5c50c2c6048 Author: Field G. Van Zee Date: Tue Apr 23 19:12:14 2013 -0500 Fixed minor bug in computing b_next in gemm. commit db072a5b4a039a9a668ef951333ecfb5bd3a74b9 Author: Field G. Van Zee Date: Tue Apr 23 17:49:10 2013 -0500 Fixed rare edge case bug in herk_l macro-kernel. Details: - Fixed a potential bug in herk_l at the m_left edge case. If MR was chosen to be much larger than NR, then one could encounter edge cases in the the MC dimension that fall entirely below the diagonal, which the previous implementation of the herk_l macro-kernel was not allowing for. commit 1dab11e37d1cb403cbe75b73a644c00de534f104 Author: Field G. Van Zee Date: Tue Apr 23 17:17:11 2013 -0500 Updated x86 gemmtrsm ukernels to use alpha. commit 9d10d7dd9bc92a993fea7162bfa5983f75506f49 Author: Field G. Van Zee Date: Tue Apr 23 16:00:18 2013 -0500 Added a_next, b_next arguments to micro-kernels. Details: - Added two more arguments to the gemm and gemmtrsm microkernels: the addresses of the next micro-panels of A and B. By passing these pointers into the micro-kernel, we allow the micro-kernel author to prefetch micro-panels of A and B as necessary (though this is completely optional; these addresses may also be safely ignored). - Updated all seven macro-kernels so that they compute and pass in a_next and b_next. Note that ONLY the gemm macro-kernel computes a_next and b_next with the precise semantics we want. I will go back and fix the other macro-kernels in the near future. - Added 'restrict' to various micro-kernels from which it was missing. commit f3815dc84d385c514a5acaf1e925424a57be2f51 Author: Field G. Van Zee Date: Tue Apr 23 11:12:33 2013 -0500 Added code for backward edge-case blocking. Disabled: - Edited bli_determine_blocksize_b() to include experimental (and currently disabled) code that computes extended blocks. - Updated commnts relate to above changes. - Enabled use of x86 gemmtrsm ukernel in config/flame/bli_kernel.h. commit 4fe1435f20e8fc7dd72f795ac58c8e236e6c631b Author: Field G. Van Zee Date: Mon Apr 22 19:00:43 2013 -0500 Updated dupl implementation to use PACKNR and NR. Details: - Updated frame/util/dupl/bli_dupl_unb_var1.c to utilize PACKNR and NR explicitly so navigate b1 so that situations where PACKNR > NR are supported. - Moved the 4x2 and 4x4 reference micro-kernels in frame/3/gemm/ukernels and frame/3/trsm/ukernels to kernels/c99/. - Updated clarksville and flame configurations. commit 2d6f9e83799a46d52d7901e275f8fd67f0a0edc6 Author: Field G. Van Zee Date: Sun Apr 21 15:10:34 2013 -0500 Disabled blocksize checks for memory pools. Details: - Temporarily disabled checks that ensure that enough memory will be allocated by the contiguous memory allocator for all types, given that the values for double precision real are the ones used to allocate the space. These checks can easily go awry in certain situations, especially if you are developing for only one datatype. So for now, they are probably more trouble than they are worth. commit b6ef84fad1c9884c84b7f1350a0bcdfe1737e8f2 Author: Field G. Van Zee Date: Sun Apr 21 15:00:24 2013 -0500 Allow ldim of packed micro-panels != MR, NR. Details: - Made substantial changes throughout the framework to decouple the leading dimension (row or column stride) used within each packed micro-panel from the corresponding register blocksize. It appears advantageous on some systems to use, for example, packed micro-panels of A where the column stride is greater than MR (whereas previously it was always equal to MR). - Changes include: - Added BLIS_EXTEND_[MNK]R_? macros, which specify how much extra padding to use when packing micro-panels of A and B. - Adjusted all packing routines and macro-kernels to use PACKMR and PACKNR where appropriate, instead of MR and NR. - Added pd field (panel dimension) to obj_t. - New interface to bli_packm_cntl_obj_create(). - Renamed bli_obj_packed_length()/_width() macros to bli_obj_padded_length()/_width(). - Removed local #defines for cache/register blocksizes in level-3 *_cntl.c. - Print out new cache and register blocksize extensions in test suite. - Also added new BLIS_EXTEND_[MNK]C_? macros for future use in using a larger blocksize for edge cases, which can improve performance at the margins. commit 59fca58dbe678d79c1df0916b022afbeac7c48fa Author: Field G. Van Zee Date: Fri Apr 19 15:26:29 2013 -0500 Fixed bug in compatibility layer (her2k/syr2k). Details: - Fixed a bug in the BLAS compatibility layer, specifically in bla_her2k.c and bla_syr2k.c, that caused incorrect computation to occur when the BLAS interface caller requests the [conjugate-]transpose case. Thanks to Bryan Marker for reporting the behavior that led to this bug. commit 09eacbd1ab1380a95a0e9625726b45e43ed102d6 Author: Field G. Van Zee Date: Thu Apr 18 19:39:13 2013 -0500 Changed old level3 test drivers to call front-ends. Details: - Changed old level-3 test drivers, in 'test' directory, to always call the front-end object API instead of the internal back-end with the locally defined control tree. commit 83e45de23e565138b8fde06fb11cfedc973b7246 Author: Field G. Van Zee Date: Thu Apr 18 18:33:03 2013 -0500 Allow packm_init() to reacquire a too-small mem_t. Details: - Changed bli_packm_init() to react differently to a situation where a pack obj_t has an already-allocated mem_t entry that has a buffer that is smaller than what will be needed to hold the block/panel that now needs to be packed. Previously, this situation was treated with an abort() since I assumed something was horribly wrong. I have changed the code so that it now reacts by releasing the previous mem_t and re-acquires a new mem_t with the new information. (This change was done at the request of Bryan Marker to facilitate code generation via DxT.) commit a6990434173b0cf651f8521194f3aef738deb7d2 Author: Field G. Van Zee Date: Thu Apr 18 13:52:47 2013 -0500 Fixed bug in packing block of A for hemm/symm. Details: - Fixed a bug in bli_packm_blk_var2() that affected the packing functionality of hemm and symm. The bug occurs whenever attempting to pack a Hermitian or symmetric matrix where the block of A being packed intersects the diagonal, but some of its micro-panels do not intersect the diagonal and lie completely in the unstored region. Thanks to Francisco Igual for reporting this bug. - Comment updates to both _blk_var2.c and _blk_var3.c. commit c92e7590e1934f830814ab614c794215ebe0c415 Author: Field G. Van Zee Date: Wed Apr 17 20:53:29 2013 -0500 Activated bli_packm_acquire_mpart_t2b(). Details: - Removed the overly-paranoid bli_abort() from the end of bli_packm_acquire_mpart_t2b(), to allow others to experiment with partitioning through packed blocks of A. Also, and more importantly, changed an earlier check that was causing an erroneous (but coincidentally redundant) abort(). Also, updated some of the comments in bli_packm_part.c. commit bea579e9f009a44e08008eb14d09f38748ab2b53 Author: Field G. Van Zee Date: Tue Apr 16 19:43:14 2013 -0500 Allow creation of "empty" objects. Details: - Modified bli_obj_alloc_buffer() to allow allocating an empty buffer, and modified bli_adjust_strides() to explicitly handle m = n = 0. - Updated bli_check_matrix_strides() to allow cases where m = n = 0. commit 7904e20f2e6908571ee5008da2a08084198eefae Author: Field G. Van Zee Date: Tue Apr 16 17:37:16 2013 -0500 Fixed "root" object bug in bli_her[2]k/syr[2]k. Details: - Fixed an obscure bug in the front-ends for herk, her2k, syrk, and syr2k, that manifested as the incorrect triangle being updated. It occurred when the user would pass in a matrix object that was correctly marked as symmetric/Hermitian and lower-stored, but whose root object was never marked as lower (or upper). We now alias and re-assign root status for matrix C within the front-ends. Note that trmm and trsm were already doing this, albeit for a slightly different reason (to allow the internal back-end to choose which algorithm to run--lower or upper--based on the uplo of the root object for both left and right side cases). Thanks to Bryan Marker for leading me to this bug. commit 19155a768dd97b57cfb59c32fa8e54a344ec66e1 Author: Field G. Van Zee Date: Tue Apr 16 11:24:03 2013 -0500 Fixed overzealous type-checking in bli_getsc(). Details: - Relaxed type checking in getsc so that the input object could be a constant and not just a proper floating-point type. (If it is a constant, default to extracting the dcomplex values.) Thanks to Bryan Marker for reporting this bug. - Added definition for bli_is_constant() in bli_param_macro_defs.h - Comment updates to various level-0 scalar routines. commit 2ee6bbca2953d04c967685da9735b3eaf8a4b813 Author: Field G. Van Zee Date: Mon Apr 15 19:27:57 2013 -0500 Fixed bug in bli_obj_is_packed() and renamed. Details: - This macro is used to determine whether the partitioning routines should call a corresponding packm_part routine instead. However, it was unintentionally catching matrices that were marked as "packed" by virtue of them simply being marked as BLIS_PACKED_UNSPEC in, say, bli_gemv(). The macro has now been renamed to bli_obj_is_panel_packed(), and now only checks for row or column panel packing. (Note that I first attempted to fix this bug in a571af816d72.) Thanks to Bryan Marker for reporting the erroneous behavior that led me to this bug. commit 99b99eebe70336b5f28039a4a084aa7f5fa7059d Author: Field G. Van Zee Date: Mon Apr 15 17:54:43 2013 -0500 Removed local reference ukernel blocksize macros. Details: - Removed locally defined gemm microkernel blocksize macros from _mxn reference microkernel definition and header. Meant to include this in a recent/previous commit (0020ef7c8271). commit 6a538fa7b164655f41cea5b9c8d3902438bda66b Author: Field G. Van Zee Date: Mon Apr 15 14:40:31 2013 -0500 Formatting change to mods in previous commit. commit ea079d35591e808971d2d98a1a7d9f89bc1f7c2f Author: Field G. Van Zee Date: Mon Apr 15 14:31:40 2013 -0500 Set structure of objects in level-2 BLIS APIs. Details: - Added missing statement to set structure field of local objects in top-level BLIS (BLAS-like) API wrappers. Thanks to Bryan Marker for reporting this bug. commit d9948c541c0446e20e249a1ccc83709ce51b7aa8 Author: Field G. Van Zee Date: Mon Apr 15 10:21:26 2013 -0500 Tweak to test suite function string construction. Details: - Fixed a minor bug in the way that the test suite would construct function name strings when the user anchored all parameters in input.operations. In this case, the test driver would mistake this situation for one where the operation simply had no parameters to begin with, and thus would not include the parameter string in the function string that is output for every result. commit ca9e435c57c5c7a000d2a32681dd8070ba850abd Author: Field G. Van Zee Date: Mon Apr 15 09:59:46 2013 -0500 Fixed a bug in reference implementation of dupl. Details: - Fixed a bug in reference implementation of dupl (bli_dupl_unb_var1.c), which resulted in incorrect duplication. - Updated old test drivers according to recently updated packm control tree creation interface. - Added 'restrict' to x86 gemm microkernel interface. commit 26cbd52e364bbe439e3744101cd5a6cbcb82dffd Author: Field G. Van Zee Date: Sun Apr 14 19:05:33 2013 -0500 Modified bli_kernel.h include order in blis.h. Details: - Delayed #include of bli_kernel.h in blis.h to prevent a situation where _kernel.h includes an optimized microkernel header, which uses BLIS types such as dim_t and inc_t, which would precede the definition of those types in bli_type_defs.h. - Moved the #include of bli_kernel_macro_defs.h in bli_macro_defs.h to blis.h (immediately after that of bli_kernel.h). commit 3414a23c38b0de45a8034b3dda2fc4b5a755e4e1 Author: Field G. Van Zee Date: Sat Apr 13 16:53:16 2013 -0500 CHANGELOG update. commit ec16c52f2ecf419c749175ce0a297441c10f1c68 (tag: 0.0.6) Author: Field G. Van Zee Date: Sat Apr 13 16:41:16 2013 -0500 Updated INSTALL file (now redirects to website). commit 0020ef7c82711a7ebf08e5174f939bee2563184c Author: Field G. Van Zee Date: Sat Apr 13 15:26:35 2013 -0500 Removed gemmtrsm-, trsm-specific blocksize macros. Details: - Modified gemmtrsm micro-kernel wrappers to use new aliased blocksize macros instead of operation-specific ones. - Removed local, gemmtrsm-specific blocksize macro definitions found in micro-kernel header files. (Meant to include above changes in 31b100e7bf4a.) - Added comments to reference gemmtrsm micro-kernel wrapper implementation. commit 1a9f427b85bb95aaa9e54c8ff8ecad8734b361ee Author: Field G. Van Zee Date: Fri Apr 12 15:25:54 2013 -0500 Added/renamed alignment constants to _config.h. Details: - Added new memory alignment constants: BLIS_HEAP_STRIDE_ALIGN_SIZE (previously assumed to be same as SYSTEM_MEM) BLIS_CONTIG_ADDR_ALIGN_SIZE (previously assumed to be same as PAGE_SIZE) BLIS_STACK_BUF_ALIGN_SIZE (previously not enforced) and renamed existing ones BLIS_SYSTEM_MEM_ALIGN_SIZE -> BLIS_HEAP_ADDR_ALIGN_SIZE BLIS_CONTIG_MEM_ALIGN_SIZE -> BLIS_CONTIG_STRIDE_ALIGN_SIZE to better convey what the alignment factor is used for (and what it is not used for). - Removed BLIS_ENABLE_SYSTEM_MEM_ALIGN. Dynamic memory alignment is now disabled by setting BLIS_HEAP_STRIDE_ALIGN_SIZE to 1. - Inserted instances of __attribute__((aligned(BLIS_STACK_BUF_ALIGN_SIZE))) into macro-kernels to specify stack alignment of temporary buffers. - Modified test suite driver to output new constants. - Removed bli_align_dim_to_sys() and bli_align_dim_to_cmem(). Instead, we now use bli_align_dim_to_size(), which takes a third argument (the desired alignment). commit a77d10e87e3c0ab55ec14d74c285bc95c06285c3 Author: Field G. Van Zee Date: Fri Apr 12 11:40:55 2013 -0500 Fixed an bug in axpyv/axpym when alpha is unit. Details: - Fixed bug whereby axpyv and axpym were incorrectly simplifying to a copy, rather than an add, when alpha = 1. Thanks to Bryan Marker for identifying this bug. commit 0495bd1d6de5995fe2fb79b321eec79e961eb7a5 Author: Field G. Van Zee Date: Thu Apr 11 16:39:25 2013 -0500 Moved _POSIX_C_SOURCE def to compiler cmd line. Details: - Removed the #define of _POSIX_C_SOURCE in bli_config.h (for both reference and clarksville configurations) and added "-D_POSIX_C_SOURCE=200112L" to the compiler command line arguments in make_defs.mk (for both configs). Thanks to Devin Matthews for suggesting this change. commit d43d1a0a2ef6de4bc57627566aef8e3fdb458b8c Author: Field G. Van Zee Date: Thu Apr 11 16:28:17 2013 -0500 Appended 'f2c_' to abs, min, max macros in f2c.h. Details: - Renamed abs, min, max, dmin, and dmax macros in bli_f2c.h so that they would not conflict with anything defined by the user (or the language). Thanks to Devin Matthews for suggesting this fix. - Updated all instances of the above macros accordingly. commit 31b100e7bf4aeaa4ceafefd2b6c3102d5fbc4cbb Author: Field G. Van Zee Date: Thu Apr 11 11:11:52 2013 -0500 Added new kernel blocksize macro aliases. Details: - Added new macros that alias level-3 cache and register blocksize macros to names that can be constructed via the PASTEMAC macro. These aliased macro definitions live inside bli_kernel_macro_defs.h, which is now #included after bli_kernel.h. - Modified macro-kernels to use new aliased blocksize macros instead of operation-specific ones. - Removed local, operation-specific kernel blocksize macro definitions (found in macro-kernel header files). commit bd2b24ba65b36d7c07c5918a3838ce2ff57c4b48 Author: Field G. Van Zee Date: Thu Apr 11 10:35:39 2013 -0500 Updated CREDITS file. commit 79328c15410215737f3f14cd069328cf52aa11fd Author: Field G. Van Zee Date: Thu Apr 11 10:32:14 2013 -0500 Reverted testsuite object files' home to 'obj'. Details: - Removed 'obj' and 'lib' from .gitignore. - Added testsuite/obj/.gitkeep (which is an empty file). - Updated testsuite/Makefile accordingly. - Thanks to Vernon Austel for pointing out the .gitkeep trick to tracking empty directories in git. commit 4afe3bfd82c03e1e97b58b7d250588a0d28541e5 Author: Field G. Van Zee Date: Tue Apr 9 17:45:39 2013 -0500 Renamed/moved object scalar constant macros. Details: - Replaced scalar constant macro definitions in bli_const_defs.h with a single, simplier macro in bli_obj_macro_defs.h. - Updated invocations of old macros accordingly. - Removed bli_const_defs.h. commit 357893f5be5c56ab7b062874005e77e614b23f06 Author: Field G. Van Zee Date: Tue Apr 9 14:48:15 2013 -0500 Applied fix from prev commit to gemmtrsm_?_ref_4x4 Details: - Fixed hard-coded kernels in bli_gemmtrsm_l_ref_4x4.c and bli_gemmtrsm_u_ref_4x4.c. commit 54988e8dca44475610bcaee5a7bc1c40e8921402 Author: Field G. Van Zee Date: Mon Apr 8 19:08:43 2013 -0500 Fixed a performance bug in trsm. Details: - Fixed a bug in the reference implementations of the gemmtrsm wrappers (bli_gemmtrsm_l_ref_mxn.c and bli_gemmtrsm_u_ref_mxn.c) whereby the reference gemm microkernel was hard-coded, and thus always called, even when GEMM_UKERNEL was defined to point to an optimzied microkernel. This manifested as artificially low trsm performance for all problem sizes, but especially for small problem sizes as it only affected blocks of A that intersected the diagonal. Thanks to Mike Kistler of IBM for helping me find this bug. commit a7252e40b5c351eef9a1df531ea0ef25cb5fb705 Author: Field G. Van Zee Date: Mon Apr 8 16:08:22 2013 -0500 Generate testsuite objects 'src'. Details: - Tweaked the testsuite makefile so that object files are stored in 'src' rather than 'obj', since (a) the top-level .gitignore dictates that obj directories are to be ignored, and (b) since git has problems tracking empty directories. Now, users do not need to create their own obj directories within their own local clones of BLIS. commit 803871c55b60d3c225ad9a0607fa507a9c16aab7 Author: Field G. Van Zee Date: Mon Apr 8 15:18:42 2013 -0500 Minor formatting changes. commit a571af816d72727e16cad37007e7043b9d6fa362 Author: Field G. Van Zee Date: Mon Apr 8 15:00:13 2013 -0500 Fixed definition of bli_is_packed_object() macro. Details: - Changed the definition of bli_is_packed_object() so that it keys off of the value of the pack schema bits in the info field of obj_t, rather than comparing the obj_t buffer with that of the mem_t entry. This was the cause of a very low probability bug whereby uninitialized memory caused the macro to evaluate to TRUE even though the object in question was not packed. Thanks to Vernon Austel of IBM for helping discover this bug. - Changed an abort() in bli_packm_part() to a not-yet-implemented. commit 3be14c32f735ecc6169d3ab6370cf8b69162acec Author: Field G. Van Zee Date: Sat Apr 6 12:54:45 2013 -0500 Updated information in testsuite output header. Details: - Added to the information that is echoed at the beginning of the test suite's output, and also re-labeled some existing information. commit 874707c1b183a4dd9a91dbfd4ea1522384c190df Author: Field G. Van Zee Date: Fri Apr 5 17:19:43 2013 -0500 Fixed edge case handling bug in herk macrokernels. Details: - Fixed a bug present in bli_herk_l_ker_var2() and bli_herk_u_ker_var2() that only manifests when BLIS is configured such that MR != NR. The bug involves incorrectly detecting edge cases, which resulted in some parts of matrix C potentially being skipped and not updated, depending on the problem size. - Updated the default values of MR and NR in config/reference/bli_kernel.h to 8 and 4, respectively, so that I can better stress the framework on a day-to-day basis. (The fact that they were both equal to 4 for so long is why I did not stumble upon this bug much sooner.) commit 7cbda15291d3e01300e71c286b9657b7ef0708bf Author: Field G. Van Zee Date: Thu Apr 4 15:25:43 2013 -0500 Added reference microkernels for arbitrary MR, NR. Details: - Added a new set of reference gemm, gemmtrsm, and trsm micro-kernels that contain explicit loops over MR and NR, thus allowing them to be used unmodified by developers who want to build a reference library with custom register blocksizes. - Changed config/reference/bli_kernel.h to use above ukernels by default. - Changed interfaces of new and existing gemm, gemmtrsm, and trsm micro-kernels to use 'restrict' keyword. - Added -funroll-loops option to config/reference/make_defs.mk. - Updated comments in bli_kernel.h describing constraints on register and cache blocksizes. - Updated _adds_mxn.h, _copys_mxn.h, and _xpbys_mxn.h macros files so that single-char macros are also defined. commit 6684b73d5501f91d24a79e26655a42819c9b3114 Author: Field G. Van Zee Date: Tue Apr 2 13:06:20 2013 -0500 Implemented amax operation and related changes. Details: - Implemented amax operation in BLIS. - Activated BLAS2BLIS routine mapping for new amax BLIS implementation. - Added integer support to [f]printv, [f]printm. - Added integer support to level-0 copys macros. - Updated printing of configuration information in test suite driver. - Comment changes to _config.h files. - Added comments to bla_dot.c to reminder reader what sdsdot()/dsdot() are used for. commit fb68087f8727cd5fd656a742a110e54fb1c91db9 Author: Field G. Van Zee Date: Tue Mar 26 15:10:16 2013 -0500 More memory alignment-related tweaks. Details: - Renamed BLIS_MEMORY_ALIGNMENT_SIZE to BLIS_CONTIG_MEM_ALIGN_SIZE. - Renamed BLIS_ENABLE_MEMORY_ALIGNMENT to BLIS_ENABLE_SYSTEM_MEM_ALIGN. - Added BLIS_SYSTEM_MEM_ALIGN_SIZE, which controls only the alignment passed into posix_memalign() or equivalent. - Defined new function, bli_align_dim_to_cmem(), which applies the contiguous memory alignment (rather than the system/malloc alignment). commit 9682ef61dbf9a8846c8b0826d4de24bc216cd641 Author: Field G. Van Zee Date: Tue Mar 26 14:14:53 2013 -0500 Always define memory alignment size cpp constant. Details: - Removed guard around #define for memory alignment size constant. Memory alignment should always be enabled, and so this value should always be defined. commit 3a787cccaae16531474f34398e3c0cf4f49b8cd8 Author: Field G. Van Zee Date: Tue Mar 26 13:59:19 2013 -0500 Renamed memory alignment macro constant. Details: - Renamed all occurrences of BLIS_MEMORY_ALIGNMENT_BOUNDARY to BLIS_MEMORY_ALIGNMENT_SIZE. commit 37308f9a502b56d94fa52a7df71c676a46c3be3d Author: Field G. Van Zee Date: Tue Mar 26 12:43:14 2013 -0500 Align packed panel strides with system alignment. Details: - Pass panel strides through bli_align_dim_to_sys() to ensure that each subsequent packed panel of A and B begins at an aligned address. (The first panel is presumably aligned to system alignment because it is aligned to a page boundary, which is typically much larger.) - Rearranged code in packm_init_pack() to prevent additional conditional blocks as a result of the aforementioned change. - Adjusted contiguous memory allocator so that the system memory alignment is used to allocate enough space for each block no matter what kind of register blocking is used (even if register blocksize is unit and every row/column needs maximal padding). - Adjusted default blocksizes in reference configuration so that MC*KC and KC*NC result in identical footprints for all datatypes. commit 40a0654ada5f256beb3da80ebba015a3c71fb61f Author: Field G. Van Zee Date: Sun Mar 24 20:18:12 2013 -0500 CHANGELOG update. commit b65cdc57d9e51fa00e3c03539cfb7e045707d0f4 (tag: 0.0.5) Author: Field G. Van Zee Date: Sun Mar 24 20:01:49 2013 -0500 Migrated 'bl2' prefix to 'bli'. Details: - Changed all filename and function prefixes from 'bl2' to 'bli'. - Changed the "blis2.h" header filename to "blis.h" and changed all corresponding #include statements accordingly. - Fixed incorrect association for Fran in CREDITS file. commit 132bffcef7441f32d02cc7485aef6a0648e0ef1e Author: Field G. Van Zee Date: Sun Mar 24 18:49:36 2013 -0500 Removed several 'old' directories and files. Details: - Removed most of the 'old' directories scattered throughout the framework, which includes alternate/half-baked/broken implementations. commit 551ea4767a3ea6c263f12aaca94bc2642cee4cfa Author: Field G. Van Zee Date: Sun Mar 24 18:00:10 2013 -0500 Removed #include "blis2.h" from low-level headers. Details: - Removed #include of "blis2.h" from various lower-level, operation-specific header files throughout the framework. Given that these low-level headers are included within #blis2.h in a very specific order, #include'ing blis2.h within them directly is unnecessary. commit bc7b318ed0960edeb4537797dd8c91de0d942ca9 Author: Field G. Van Zee Date: Fri Mar 22 17:18:58 2013 -0500 Added cpp guards to conflicting libflame typedefs. Details: - Added cpp guards around the definitions of dim_t, scomplex, and dcomplex. This is a temporary hack to allow interoperability with libflame. (Similarly temporary changes are being made to libflame's type definitions file.) commit f469907503fcdc24dff0174c569170e6e756e045 Author: Field G. Van Zee Date: Fri Mar 22 15:20:15 2013 -0500 Renamed MAX_PREFETCH_BYTE_OFFSET to MAX_PRELOAD_. Details: - Renamed BLIS_MAX_PREFETCH_BYTE_OFFSET to BLIS_MAX_PRELOAD_BYTE_OFFSET since "prefetch" is kind of a loaded word (e.g. "prefetch" instructions, which are different than the particular kind of prefetching/preloading referred to by this constant). commit d1023bfbc6668a58a01ee4f82ded2319911e7b19 Author: Field G. Van Zee Date: Fri Mar 22 15:09:59 2013 -0500 Removed build/old directory. commit 718888849c48d99f83eea6b8f83bc1998cffef7e Author: Field G. Van Zee Date: Fri Mar 22 15:07:01 2013 -0500 Deprecated 'flame' configuration. Details: - Removed 'flame' configuration, as it was horribly out-of-date. - Comment changes to bl2_blocksize.c and bl2_mem.c. commit bba38cf4e9d28058c14483f44fa074a6d2852ad9 Author: Field G. Van Zee Date: Tue Mar 19 18:07:40 2013 -0500 Added missing conjbeta argument to scald. commit 1f82b51d06d0279dded3f2b87ba59403f3ed0af6 Author: Field G. Van Zee Date: Mon Mar 18 15:37:20 2013 -0500 Relocated packed mem_t dimension fields to obj_t. Details: - Removed the m and n (and elem_size) fields from the mem_t object, and added m_packed and n_packed fields to obj_t. These new fields track the same as the old ones. From an abstraction standpoint, it seemed awkward to store those dimensions inside the mem_t. - Updated interfaces to bl2_mem_acquire_*() so that only a byte size argument is passed in, instead of m, n, and elem_size. - Updated bl2_packm_init_pack() and bl2_packv_init_pack() to inline the functionality of bl2_mem_alloc_update_m() and bl2_mem_alloc_update_v(), respectively. - Updated packm variants to access the packed length and width fields from their new locations. commit 36c782857bf9b8ac1b1dac47a70f689a4407e2cc Author: Field G. Van Zee Date: Mon Mar 18 10:37:03 2013 -0500 CHANGELOG update. commit e7d41229d3b1674e74f47d7f29fae004a745201a (tag: 0.0.4) Author: Field G. Van Zee Date: Fri Mar 15 17:12:36 2013 -0500 Re-implemented contiguous memory allocator. Details: - Completely re-wrote the contiguous memory allocator (bl2_mem.c). The new allocator instantiates and initializes three separate memory pool objects, each one associated with a separate array of contiguous memory blocks, each block of fixed and uniform size. (The three pools are for allocating mc-by-kc blocks of A, kc-by-nc panels of B, and mc-by-nc panels of C.) The pool objects use a stack structure internally to track which blocks in the region have been "checked out" to a thread and which are still available. Critical regions are now clearly marked and adaptable to parallel environments (e.g. OpenMP). Memory pools are set up when bl2_init() is called. - Added a new field to the packm control tree node, which indicates what kind of packed buffer is being allocated. The enumerated type for this argument is defined as packbuf_t in bl2_type_defs.h. - Updated level-3 _cntl.c files to pass in the appropriate value for a new packbuf_t argument to bl2_packm_cntl_obj_create(). - Moved some macros called by packm_init_pack() from bl2_obj_macro_defs.h to bl2_mem_macro_defs.h. - Added BLIS_MAX_NUM_THREADS to bl2_config.h, which we use as the default number of blocks of A reserved for the memory allocator. - Deprecated bl2_align_dim(). Replaced usage with that of bl2_align_dim_to_mult(). Turns out that typically we don't need to align a dimension to the system alignment, since that value has to do with starting addresses, whereas the values we are dealing with are unitless dimensions. commit 1e76cae00cb0a04544aaae1ade878686b238d283 Author: Field G. Van Zee Date: Fri Mar 15 12:21:42 2013 -0500 Perform her2k var1 loops in sequence. Details: - Changed variant 1 of her2k so that the two rank-k products are computed and accumulated in sequence rather than fused into one loop. This is necessary if BLIS is to be configured to provide only enough contiguous memory for one panel of B. commit c95c270eba91ae4efc26603beddfd0292caa919b Author: Field G. Van Zee Date: Thu Mar 7 14:42:15 2013 -0600 Enhanced tracking of dimensions for mem_t objects. Details: - Added new fields to mem_t struct definition to track the allocated (as opposed to the currently used) dimensions of the memory region. This allows packm_init() to be more robust in situations where memory is already allocated but is more than needed for the current packing job. - Updated logic in bl2_obj_set_buffer_with_cached_packm_mem() macro, used in packm_init(), to update the "currently used" dimensions of the mem_t object if the requested dimensions are smaller than the allocated dimensions. commit e99281a0f41d482fddeffa239bfc8e13e6d13d4b Author: Field G. Van Zee Date: Thu Mar 7 14:00:10 2013 -0600 Fixed test suite flop formulas for ops with side. Details: - Fixed incorrect flop counts in test suite modules for hemm, symm, trmm, trmm3, and trsm. - Comment updates in herk macro-kernels. commit ef8cbfc44dd620fdcbdb51cdb173217194bebe31 Author: Field G. Van Zee Date: Sat Mar 2 12:47:06 2013 -0600 Added "version" to .gitignore. Details: - Added "version" to .gitignore file so that the file does not show up when running 'git status', or accidentally get pulled into the index when running 'git add' or 'git add --all'. commit e9e0747c2f6c178f53ac46ab794acbb7b8c4fea8 Author: Field G. Van Zee Date: Sat Mar 2 12:43:54 2013 -0600 Removed version file from version control. Details: - Removed version file from version control to prevent git errors that occur when trying to pull new commits. commit bb612f864e9c17dd9805e9446840f02259619469 Author: Field G. Van Zee Date: Fri Mar 1 12:55:42 2013 -0600 Updated behavior of bl2_obj_induce_trans() macro. Details: - Changed bl2_obj_induce_trans() so that the transposition bit is no longer updated as part of the macro. All current uses of the macro have been coupled with instances of bl2_obj_set_trans() to clear the bit. - Added Jed to CREDITS file. commit f24e29b789e7314764a818ceb3063126936c986f Author: Field G. Van Zee Date: Fri Feb 22 18:15:41 2013 -0600 Replaced banded/packed BLAS2 stubs with f2c code. Details: - Retired the blas2blis wrappers that simply called abort with a "not yet implemented" message. This includes all of the level-2 banded and packed routines. - Replaced the aforementioned with the corresponding netlib implementations having been run through f2c (with some customization). - Added directories named 'attic' to build/gen-make-frags/ignore_list. commit 1454c1a14207766dfed372b8e38b47fa384f5198 Author: Field G. Van Zee Date: Fri Feb 22 12:38:45 2013 -0600 Moved Fortran name-mangling macro to bl2_config.h. Details: - Moved the Fortran-77 name-mangling macros from bl2_blas_macro_defs.h to the configuration directory (bl2_config.h, specifically) given that it can be expected to be tweaked by some developers. commit ede75693e5a36c6006087c4a7df834175b604504 (tag: 0.0.3) Author: Field G. Van Zee Date: Fri Feb 22 12:11:24 2013 -0600 Implemented blas2blis compatibility layer. Details: - Added the blas2blis compatibility layer, located in frame/compat. This includes virtually all of the BLAS, including banded and packed level-2 operations. - Defined bl2_init_safe(), bl2_finalize_safe(). The former allows a conditional initialization, which stores the "exit status" in an err_t, which is then read by the latter function to determine whether finalization should actually take place. - Added calls to bl2_init_safe(), bl2_finalize_safe() to all level-2 and level-3 BLAS-like wrappers. - Added configuration option to instruct BLIS to remain initialized whenever it automatically initializes itself (via bl2_init_safe()), until/unless the application code explicitly calls bl2_finalize(). - Added INSERT_GENTFUNC* and INSERT_GENTPROT* macros to facilitate type templatization of blas2blis wrappers. - Defined level-0 scalar macro bl2_??swaps(). - Defined level-1v operation bl2_swapv(). - Defined some "Fortran" types to bl2_type_defs.h for use with BLAS wrappers. commit 995edf43e21c1868732dbdd7fee14b08730218bd Author: Field G. Van Zee Date: Thu Feb 21 14:30:50 2013 -0600 Updated version file. (Forgot to in prev commit). commit e823b08aaf7b65ecc6ddc30570709ea8a4b52aa7 Author: Field G. Van Zee Date: Thu Feb 21 12:00:17 2013 -0600 Fixed some scalar types in BLAS-like Herm APIs. Details: - Some of the scalars of Hermitian operations, such as alpha in her, alpha and beta in herk, and beta in her2k, need to be real. These arguments were typed incorrectly as the complex types. This has been fixed. Note the issue was only present in the BLAS-like APIs for these operations (not the native object-based interfaces). commit 5ece050a669e74ba4a711d1d4669239d22d45642 Author: Field G. Van Zee Date: Wed Feb 20 15:50:54 2013 -0600 Updated version file. (Forgot to in prev commit). commit f243034b8b430d4684680ea8eddfd246e73fefc0 Author: Field G. Van Zee Date: Wed Feb 20 14:11:36 2013 -0600 Changed API of packm_init_pack() to use blksz_t. Details: - Changed the interface of packm_init_pack() so that mult_m and mult_n are passed in as type blksz_t* instead of dim_t. - Make similar change for packv_init_pack(). commit da0c22f24107be9f33e0ea2dae52e5534b1fd0e5 Author: Field G. Van Zee Date: Fri Feb 15 09:59:48 2013 -0600 Minor changes to lower levels of scalm and setm. Details: - Removed diagx parameter from lower-level interfaces of scalm. - Modified scalm_basic_check() to expect an object with a nonunit diagonal. - Changed setm_unb_var1() so that having an implicit unit diagonal results in only the strictly lower or upper triangle of the matrix being modified. commit 2c836adadcd2a7d7f217033ac4d7fcad03d5bd55 Author: Field G. Van Zee Date: Thu Feb 14 10:42:56 2013 -0600 Updated beta == zero semantics of mulsc. Details: - Updated beta == zero semantics of mulsc. Hopefully this is the last operation that needed updating. - Added Devin to CREDITS file. commit 722b66c7dcaaaa1b109e7c8b1d53fd71a9af8240 Author: Field G. Van Zee Date: Thu Feb 14 10:18:00 2013 -0600 Removed some calls to setv() in test modules. Details: - Removed calls to setv() in test modules whose sole purpose was to initialize vectors to zero to ensure that nan's and inf's would not taint the computation. Now that beta == zero semantics have been updated to clear the output operand (when beta is zero), rather than multiply against it, these setv() calls are no longer needed. commit e6ac623a902f776c42f85eadbf76996d9770a0db Author: Field G. Van Zee Date: Wed Feb 13 18:44:59 2013 -0600 Properly implemented beta == 0 semantics. Details: - Changed name of set0 and set0_mxn macros to set0s and set0s_mxn, respectively. - Added code to the following operations that sets the output operand to zero if the corresponding scalar is zero (rather than performing the floating-point multiply, or in the case of setv, copying the value). This will prevent nan's and inf's from creeping into results from uninitialized memory. - axpy - dotxv - scalv - scal2v - setv - gemv - ger - hemv - her - her2 - gemm reference ukernels commit aedccbc85d491e41711a0c6eb0d246d8700a199a Author: Field G. Van Zee Date: Wed Feb 13 18:29:53 2013 -0600 Fixed stale interface to packm_unb_var1(). Details: - Removed the control tree from the interface to packm_unb_var1(), which I meant to do when it was un-deprecated. commit c23135669f7a8a545e2e11ef559bf284be8bc65c Author: Field G. Van Zee Date: Wed Feb 13 13:21:00 2013 -0600 Un-deprecated packm_unb_var1.c (needed by l2 ops). Details: - Added bl2_packm_unb_var1() back into the mix once I realized that level-2 operations still need this routine for packing matrices. Now, whether level-2 operations should be packing matrices to begin with is another matter. But this fixes the segmentation fault one would have gotten when running bl2_gemv() on a general stride matrix. commit cf49e35f9819f9d93ebdca4703ade5abab28f6f6 Author: Field G. Van Zee Date: Tue Feb 12 18:39:35 2013 -0600 Removed cntl tree usage from packm implementation. Details: - Added new fields to obj_t info field: - invert_diag - pack_order_if_upper - pack_order_if_lower These fields allow packm_init() to embed information that begins in the control tree into the object so that the packm implementation does not need to use control trees at all. This is being done to aid Bryan's DxT code generation. - Added macros that operate on above fields. - Changed packm_init(), packm_blk_var2(), and packm_blk_var3() according to above changes. - Made similar (but much simpler) changes to packv. - Deprecated packm_blk_var1(), packm_unb_var1(), and packm_densify(). These were part of prototype implementations and are no longer needed. commit eb139ae256651af7820b93ef982626180195b87f Author: Field G. Van Zee Date: Tue Feb 12 12:39:30 2013 -0600 Replaced bl2_abs() with _fabs() where appropriate. commit 474bac30c99928f9e87315972bcb45c632c0b7ec Author: Field G. Van Zee Date: Tue Feb 12 12:23:48 2013 -0600 Removed level-0 macros projrs, grabis. Details: - Replaced instances of projrs and grabis macros with newer, more general-purpose getris. commit 03a260a457c8964e4603a655cee0d40ac17affba Author: Field G. Van Zee Date: Tue Feb 12 11:45:34 2013 -0600 Restored executable permissions to scripts. Details: - Restored executable (0755) permissions to scripts that were touched by the recursive sed script that updated the copyright headers in the previous commit. commit 1274e1243775e5e705114257a43176f63635227f Author: Field G. Van Zee Date: Mon Feb 11 14:37:47 2013 -0600 Updated copyright headers from 2012 to 2013. commit 3b620cc8e90c53c79129bd9dd89ae6b77c2446f1 Author: Field G. Van Zee Date: Mon Feb 11 13:38:07 2013 -0600 CHANGELOG update. commit 768fcebaa8be0eb936a6e7a02cd8a19438c79d99 (tag: 0.0.2) Author: Field G. Van Zee Date: Mon Feb 11 13:20:44 2013 -0600 Added unified test suite, and many fixes. Details: - Added a highly configurable, unified test suite. - Removed DUPB configuration constant from bl2_kernel.h and macro-kernel header files. Now, instead, DUPB is computed as (NDUP != 1) within each macro-kernel. This fixes a bug in trmm/trsm whereby bp was indexed into incorrectly when DUPB was set to FALSE but the NDUP was still non-unit. By encoding both pieces of information into one constant in _kernel.h, it seems somewhat less likely others will encounter this bug in the future. - Added level-2 cache blocksizes to _kernel.h for reference configuration, and defined blocksizes in _cntl.c files to these default values. - Changed semantics of her2k and syr2k such that these operations no longer expect the B matrix to already be conjugate-transposed (or just transposed for syr2k). However, these semantics are preserved for the internal mechanics of the implementations, including the internal back-end and all blocked variants. - Inserted checks for real-valued alpha and beta for herk/her2k and herk, respectively. - Relaxed general object structure constraints in _basic_check() for gemv, ger. - Changed her front-end to NOT copy-cast to real projection; instead, this is replaced by selecting either the real part or both parts within the unblocked algorithm implementation, depending on the value of conjh. - Added conjh to all _check routines for her so that the code knows when to verify that alpha has an imaginary component equal to zero (for her, but not syr). - Changed control tree for her to forgo packing. - Added unit diagonal support to fnormm. - Redefined real versions of abval2s macros in terms of fabs(), fabsf(). - Redefined complex versions of sqrt2s macros using the actual "complex square root" formula. - Created new level-0 object-based routines, suffixed with "sc" (for "scalar"). - Defined new level-1v, -1d, and -1m versions of add and sub operations (two-operand add and subtract). - Added new scalar macros: - getris: acquire real and imaginary components. - setris: set real and imaginary components. - addjs: addition with conjugated x. - subjs: subtraction with conjugated x. - Defined new utility operations: - absumv: element-wise sum of absolute values for vector elements. - absumm: element-wise sum of absolute values for matrix elements. - mkherm: convert existing matrix to Hermitian. - mksymm: convert existing matrix to symmetric. - mktrim: convert existing matrix to triangular. - Added various error checking routines. - Added bl2_clock_min_diff(), which is used to more cleanly measure the wall clock time of a code block. - Added general stride support to bl2_obj_alloc_buffer(). - Added bl2_obj_init_scalar(). - Updated parameter mapping in bl2_param_map.c. - Added support for queriable version string. - Fixed a bug in the her2k macro-kernels (which currently are simply implemented in terms of two invocations of herk) whereby beta was being applied to both the first and second rank-k updates, rather than only the first. - Fixed a bug in trmm/trsm whereby transpose and right side cases were not properly implemented due to erroneous assumptions regarding aliasing and root objects. - Fixed a bug in the upper triangular trsm macro-kernel in which the wrong MR x NR block of B was being updated. - Fixed a bug in the inverts macro in the double real case whereby the value was typecast to float before inversion. This affected non-unit cases of dtrsm. - Fixed a bug in the reference kernels for gemmtrsm whereby the minus one constant was being applied incorrectly. - Fixed a bug in the overall treatment of non-unit alpha for trsm. The code now mimics the rank-k strategy of gemm, whereby alpah is applied during the first iteration of variant 3, with BLIS_ONE passed in instead for subsequent iterations. This also required passing alpha into the macro- kernels as well as the fused gemmtrsm micro-kernels. - Fixed a bug in trsm_u_blk_var1 whereby the gemm macro-kernel was being called for blocks strictly above the diagonal. While this sounds good in theory, this cannot be done because gemm_ker_var2 expects row panels of A to be packed from top to bottom, while for trsm_u, A is actually packed from bottom to top due to the reverse (BR->TL) nature of the algorithm. - Fixed a bug in packm_cxk() whereby panel packings with unit panel dimensions were mishandled due to incorrect arguments to the copyv kernel. Also changed the copyv kernel invocation to scal2v so that these edge cases are properly handled when scaling is requested. - Fixed a bug in packv_int() whereby an uninitialized object is passed in instead of the source object. - Fixed a bug whereby level-2 code could allocate memory dynamically via bl2_malloc() and then attempt to free it via bl2_mm_release(). Also fixed a potential future bug whereby a mem_t object that is actually no longer "allocated" from the static pool is mistaken for being allocated due to failure to NULLify the buffer when the block was most recently released. - Fixed a bug in bl2_acquire_mpart_*() whreby the uplo field was mistakenly toggled when the requested subpartition needed to be "reflected" due to it residing in an unstored region. commit be94fb84c0351602d7585269f29998e3bf83f899 Author: Field G. Van Zee Date: Fri Jan 4 10:55:21 2013 -0600 Added missing 'd' to fused gemmtrsm function name. commit 879a179e1dee36f0c56765f2ab91a26861019b34 Author: Field G. Van Zee Date: Fri Jan 4 10:37:27 2013 -0600 Added debug statements to bl2_mm_acquire_m(). Details: - Added printf() statements to bl2_mm_acquire_m() to help debug issues with prematurely exhausted memory pool. - Removed 'd' from kernel names of reference kernels in clarksville configuration's bl2_kernel.h commit 806e74beb4eafeef620a555ffbb3f6779e29c7b6 Author: Field G. Van Zee Date: Thu Dec 20 17:07:50 2012 -0600 Defined Frobenius norm operations. Details: - Added level-0 grabis macro operation to grab imaginary component of one variable and copy it to the real component of another variable. - Defined sumsqv operation, which computes the sum of the absolute squares of the elements of a vector. This implementation is modeled after ?lassq in netlib LAPACK. - Defined fnormv and fnormm operations, which compute the Frobenius norm on vectors and matrices, respectively. These operations are treated as one- operand operations where the output norm value is the real projection of the datatype of the input operand. Both operations are implemented in terms of sumsqv. commit 66e80ce1aec099b2b2b0c4f295e38add2c921383 Author: Field G. Van Zee Date: Thu Dec 20 17:02:55 2012 -0600 Added GENT*R macros; tweaked bl2_machval defs. Details: - Added function and prototype macro-generating macros for GENTFUNCR and GENTPROTR, which are one-operand macros with auxiliary real projection types. - Tweaked bl2_machval files to use new macros. commit 2fecc88ca22142020573f168da715e8e9f3dd7de Author: Field G. Van Zee Date: Thu Dec 20 11:35:14 2012 -0600 Fixed harmless macro bug in level-1m operations. Details: - Fixed some inconsistent usage of n_iter_max and n_iter in the two bl2_set_dims_incs_uplo_[12]m macros. The right thing ended up happening despite the bug, which is why I had not discovered it until now. commit 8945db6ec9f82168cf72411ad408b4fdb44ae0d1 Author: Field G. Van Zee Date: Tue Dec 18 15:07:36 2012 -0600 Renamed x86,x86_64 kernels to indicate 'd' fusing. Details: - Renamed x86 and x86_64 kernels to contain a 'd' before the fusing shape to emphasize that the fusing shape is not for all datatype instances, but rather just for one (that of double-precision real). Other fusing shapes would be proportional to their precision and domain "byte footprints". - Corresponding changes to config/clarksville/bl2_kernel.h. commit 6fbbdd4e194d06096ad08c5db61127be338067db Author: Field G. Van Zee Date: Tue Dec 18 14:34:02 2012 -0600 More tweaks to _config.h, _kernel.h; smem tweaks. Details: - Moved kernel-related definitions form bl2_config.h to bl2_kernel.h. - Replaced #define of _GNU_SOURCE with #define of _POSIX_C_SOURCE. This accomplishes the same thing (enabling posix_memalign()) without enabling all of the GNU extensions we don't need. - Defined the size of the static memory pool in terms of MC, KC, and NC, as well as two new constants that determine how many MCxKC blocks and how many KCxNC blocks should be allocated (defined in bl2_config.h). - In the case of static memory pool exhaustion, replaced the generic bl2_abort() with a specific error code call. commit 5d8bdb21c48e8fb11bef6128a242122cc1470a99 Author: Field G. Van Zee Date: Mon Dec 17 16:07:36 2012 -0600 Minor reordering of bl2_config.h definitions. commit 4a83f67490136a898f558e273b76a687aed8b893 Author: Field G. Van Zee Date: Mon Dec 17 12:35:54 2012 -0600 Consolidated configuration headers. Details: - Merged contents of bl2_arch.h into bl2_config.h for reference and clarksville configurations. - Updated CREDITS, INSTALL, LICENSE, README files. commit 0670c33cc14612f636ef09ede4133404ae0af6ba Author: Field G. Van Zee Date: Fri Dec 14 12:45:26 2012 -0600 Fixed bug in reference gemm ukernels. Details: - Fixed a bug whereby, for the reference gemm ukernels, the matrix product was not correctly accumulated and scaled (by alpha) into the output matrix C. (Thanks to Fran for finding this bug.) - Whitespace changes to reference trsm kernels. commit e2e7cb2fbe615be4d375bc2dce88d03d98fadc9e Author: Field G. Van Zee Date: Thu Dec 13 18:17:54 2012 -0600 Expanded reference packm/unpackm kernel set to 16. Details: - Added 10xk, 12xk, 14xk, and 16xk reference kernels for packm and unpackm. - Updated bl2_[un]packm_cxk() to silently use scal2m if "out of range" kernel size is requested. (Thanks to Tyler for finding this bug.) - Updated bl2_kernel.h to contain new _KERNEL definitions, according to above changes, for 'reference' and 'clarksville' configurations. - Updated CHANGELOG. - Removed "output*.m" from .gitignore. commit 17455a8bce038dd570356ab0c5c11d9a89f20248 Author: Field G. Van Zee Date: Mon Dec 10 17:23:32 2012 -0600 Minor updates towards to 0.0.1. commit 7ad4ebef38b8e6eea9b6091844ba7294ec870271 (tag: 0.0.1) Author: Field G. Van Zee Date: Mon Dec 10 16:18:40 2012 -0600 Tweaks to get BLIS compiling again on clarksville. Details: - Updated header files and make_defs.mk in config/clarksville. - Fixes to bl2_mem.c (now that SMEM_M, SMEM_N are gone). - Moved definition of blksz_t from bl2_cntl.h to bl2_type_defs.h. - Shuffled include statements in blis2.h. commit cc58ea86010b1f046134d13b546c878389df9af5 Author: Field G. Van Zee Date: Mon Dec 10 14:55:12 2012 -0600 Added template fragment.mk; updated .gitignore. commit 714c527b0eb153b7e2040b79349edc8372f743fd Author: Field G. Van Zee Date: Fri Dec 7 19:54:04 2012 -0600 Added 'changelog' make target; other tweaks. Details: - Updated CHANGELOG. - Added 'changelog' target to Makefile that runs 'git log --decorate' and overwrites CHANGELOG with the output. - Other trivial changes. commit e4e5404d26aded4873278e85faf6f14ac32115b5 Author: Field G. Van Zee Date: Fri Dec 7 17:34:53 2012 -0600 Define static memory pool size in bl2_config.h. commit 19bb507d0de6a2bd3ce37cf616bdcd6b419ed641 Author: Field G. Van Zee Date: Fri Dec 7 17:18:00 2012 -0600 Refined INSTALL text; added 'showconfig' target. Details: - Added 'showconfig' target to Makefile. - Added header files and ./config//make_defs.mk as prerequisites to object file rules. - Added config.mk as prerequisite to library install rules. - Edited and added to INSTALL file. commit 26cb659dd79636489db5a051aa60fff80273a7b9 Author: Field G. Van Zee Date: Thu Dec 6 15:34:53 2012 -0600 Added auto-detection of version string (via git). Details: - Added build/update-version-file.sh script for auto-detecting "version" string and updating 'version' file accordingly. (If .git directory is not present, then it is assumed this copy of BLIS is a downloaded release, in which case 'version' file is left unchanged.) - Added invocation of update-version-file.sh to configure script. commit b0ecd0ff52fa6ffc9e1d9eb44c365f7f009a6204 Author: Field G. Van Zee Date: Thu Dec 6 14:27:11 2012 -0600 Wrote first draft of INSTALL file. commit bcbe81235a35ccfdbcc2f2319a0ca6e04f75a785 (tag: 0.0.0) Author: Field G. Van Zee Date: Thu Dec 6 12:42:35 2012 -0600 Updated standalone test Makefile and other fixes. Details: - Major edits to test/Makefile to bring up-to-date wrt new build system; should no longer be broken. - Minor edits to top-level Makefile. - Fixed copy-and-paste bugs in - frame/1m/packm/ukernels/bl2_packm_ref_?xk.c - frame/1m/unpackm/ukernels/bl2_unpackm_ref_?xk.c commit 2f272b40f43307909736327f49d17737c7a05d37 Author: Field G. Van Zee Date: Tue Dec 4 19:22:14 2012 -0600 Added build system and continued reorganization. Details: - Added/renamed packm, unpackm kernels. - Added machine value routines. - Added param_map facility. - Renamed AUTHORS to CREDITS. - Added Makefile; continued to expand upon existing configure script. - #define fuse_fac macros in operation headers if not defined already (by the user in bl2_kernels.h). commit 00f3498a8943be1b387f0d5c029c8c7891687ad5 Author: Field G. Van Zee Date: Mon Dec 3 12:36:11 2012 -0600 Initial commit. blis-0.9.0/CONTRIBUTING.md000066400000000000000000000114051422157504600147110ustar00rootroot00000000000000## How to contribute to BLIS First, we want to thank you for your interest in contributing to BLIS! Please read through the following guidelines to help you better understand how to best contribute your potential bug report, bugfix, feature, etc. #### **Did you find a bug?** * **Check if the bug has already been reported** by searching on GitHub under [Issues](https://github.com/flame/blis/issues). * If you can't find an open issue addressing the problem, please feel free to [open a new one](https://github.com/flame/blis/issues/new). Some things to keep in mind as you create your issue: * Be sure to include a **meaningful title**. Aim for a title that is neither overly general nor overly specific. * Putting some time into writing a **clear description** will help us understand your bug and how you found it. * You are welcome to include the BLIS version number (e.g. 0.3.2-15) if you wish, but please supplement it with the **actual git commit number** corresponding to the code that exhibits your reported behavior (the first seven or eight hex digits is fine). * Unless you are confident that it's not relevant, it's usually recommended that you **tell us how you configured BLIS** and **about your environment in general**. Your hardware microarchitecture, OS, compiler (including version), `configure` options, configuration target are all good examples of things to you may wish to include. If the bug involves elements of the build system such as bash or python functionality, please include those versions numbers, too. * If your bug involves behavior observed after linking to BLIS and running an application, please provide a minimally illustrative **code sample** that developers can run to (hopefully) reproduce the error or other concerning behavior. #### **Did you write a patch that fixes a bug?** If so, great, and thanks for your efforts! Please submit a new GitHub [pull request](https://github.com/flame/blis/pulls) with the patch. * Ensure the PR description clearly describes the problem and solution. Include any relevant issue numbers, if applicable. * Please limit your PR to addressing one issue at a time. For example, if you are fixing a bug and in the process you find a second, unrelated bug, please open a separate PR for the second bug (or, if the bugfix to the second bug is not obvious, you can simply open an [issue](https://github.com/flame/blis/issues/new) for the second bug). * Before submitting new code, please read the [coding conventions](https://github.com/flame/blis/wiki/CodingConventions) guide to learn more about our preferred coding conventions. (It's unlikely that we will turn away your contributed code due to mismatched coding styles, but it will be **highly** appreciated by project maintainers since it will save them the time of digressing from their work--whether now or later--to reformat your code.) #### **Did you fix whitespace or reformat code?** Unlike some other projects, if you find code that does not abide by the project's [coding conventions](https://github.com/flame/blis/wiki/CodingConventions) and you would like to bring that code up to our standards, we will be happy to accept your contribution. Please note in the commit log the fixing of whitespace, formatting, etc. as applicable. If you are making a more substantial contribution and in the vicinity of the affected code (i.e., within the same file) you stumble upon other code that works but could use some trivial changes or reformatting, you may combine the latter into the commit for the former. Just note in your commit log that you also fixed whitespace or applied reformatting. #### **Do you intend to add a new feature or change an existing one?** That's fine, we are interested to hear your ideas! * You may wish to introduce your idea by opening an [issue](https://github.com/flame/blis/issues/new) to describe your new feature, or how an existing feature is not sufficiently general-purpose. This allows you the chance to open a dialogue with other developers, who may provide you with useful feedback. * Before submitting new code, please read the [coding conventions](https://github.com/flame/blis/wiki/CodingConventions) guide to learn more about our preferred coding conventions. (See comments above regarding mismatched coding styles.) #### **Do you have questions about the source code?** * Feel free to ask questions on the [blis-devel mailing list](https://groups.google.com/d/forum/blis-devel). You'll have to join to post, but don't be shy! Most of the interesting discussion (outside of GitHub) happens on blis-devel. We also have a [blis-discuss mailing list](https://groups.google.com/d/forum/blis-discuss), but it is not the preferred venue for discussion these days. Here at the BLIS project, we :heart: our community. :) Thanks for helping to make BLIS better! Field blis-0.9.0/CREDITS000066400000000000000000000144211422157504600135010ustar00rootroot00000000000000 BLIS framework Acknowledgements --- The BLIS framework was primarily authored by Field Van Zee @fgvanzee (The University of Texas at Austin) but many others have contributed code and feedback, including Sameer Agarwal @sandwichmaker (Google) Murtaza Ali (Texas Instruments) Sajid Ali @s-sajid-ali (Northwestern University) Erling Andersen @erling-d-andersen Alex Arslan @ararslan Vernon Austel (IBM, T.J. Watson Research Center) Satish Balay @balay (Argonne National Laboratory) Matthew Brett @matthew-brett (University of Birmingham) Jérémie du Boisberranger @jeremiedbb Jed Brown @jedbrown (Argonne National Laboratory) Robin Christ @robinchrist Dilyn Corner @dilyn-corner Mat Cross @matcross (NAG) @decandia50 Kay Dewhurst @jkd2016 (Max Planck Institute, Halle, Germany) Jeff Diamond (Oracle) Johannes Dieterich @iotamudelta Krzysztof Drewniak @krzysz00 Marat Dukhan @Maratyszcza (Google) Victor Eijkhout @VictorEijkhout (Texas Advanced Computing Center) Evgeny Epifanovsky @epifanovsky (Q-Chem) Isuru Fernando @isuruf Roman Gareev @gareevroman Richard Goldschmidt @SuperFluffy Chris Goodyer John Gunnels @jagunnels (IBM, T.J. Watson Research Center) Ali Emre Gülcü @Lephar Jeff Hammond @jeffhammond (Intel) Jacob Gorm Hansen @jacobgorm Shivaprashanth H (Global Edge) Jean-Michel Hautbois @jhautbois Ian Henriksen @insertinterestingnamehere (The University of Texas at Austin) Greg Henry (Intel) Minh Quan Ho @hominhquan Matthew Honnibal @honnibal Stefan Husmann @stefanhusmann Francisco Igual @figual (Universidad Complutense de Madrid) Tony Kelman @tkelman Lee Killough @leekillough (Cray) Mike Kistler @mkistler (IBM, Austin Research Laboratory) Ivan Korostelev @ivan23kor (University of Alberta) Kyungmin Lee @kyungminlee (Ohio State University) Michael Lehn @michael-lehn Shmuel Levine @ShmuelLevine @lschork2 Dave Love @loveshack Tze Meng Low (The University of Texas at Austin) Ye Luo @ye-luo (Argonne National Laboratory) Ricardo Magana @magania (Hewlett Packard Enterprise) Madan mohan Manokar @madanm3 (AMD) Giorgos Margaritis Bryan Marker @bamarker (The University of Texas at Austin) Simon Lukas Märtens @ACSimon33 (RWTH Aachen University) Devin Matthews @devinamatthews (The University of Texas at Austin) Stefanos Mavros @smavros Mithun Mohan @MithunMohanKadavil (AMD) Ilknur Mustafazade @Runkli @nagsingh Bhaskar Nallani @BhaskarNallani (AMD) Stepan Nassyr @stepannassyr (Jülich Supercomputing Centre) Nisanth Padinharepatt (AMD) Ajay Panyala @ajaypanyala Marc-Antoine Parent @maparent (Conversence) Devangi Parikh @dnparikh (The University of Texas at Austin) Elmar Peise @elmar-peise (RWTH-Aachen) Clément Pernet @ClementPernet Ilya Polkovnichenko Jack Poulson @poulson (Stanford) Mathieu Poumeyrol @kali Christos Psarras @ChrisPsa (RWTH Aachen University) @pkubaj @qnerd Michael Rader @mrader1248 Pradeep Rao @pradeeptrgit (AMD) Aleksei Rechinskii Karl Rupp @karlrupp Martin Schatz (The University of Texas at Austin) Nico Schlömer @nschloe Rene Sitt Tony Skjellum @tonyskjellum (The University of Tennessee at Chattanooga) Mikhail Smelyanskiy (Intel, Parallel Computing Lab) Nathaniel Smith @njsmith Shaden Smith @ShadenSmith Tyler Smith @tlrmchlsmth (The University of Texas at Austin) Snehith @ArcadioN09 Paul Springer @springer13 (RWTH Aachen University) Adam J. Stewart @adamjstewart (University of Illinois at Urbana-Champaign) Vladimir Sukarev Chengguo Sun @chengguosun Santanu Thangaraj (AMD) Nicholai Tukanov @nicholaiTukanov (The University of Texas at Austin) Rhys Ulerich @RhysU (The University of Texas at Austin) Robert van de Geijn @rvdg (The University of Texas at Austin) Meghana Vankadari @Meghana-vankadari (AMD) Kiran Varaganti @kvaragan (AMD) Natalia Vassilieva (Hewlett Packard Enterprise) @h-vetinari Andrew Wildman @awild82 (University of Washington) Zhang Xianyi @xianyi (Chinese Academy of Sciences) Benda Xu @heroxbd Guodong Xu @docularxu (Linaro.org) RuQing Xu @xrq-phys (The University of Tokyo) Costas Yamin @cosstas Chenhan Yu @ChenhanYu (The University of Texas at Austin) Roman Yurchak @rth (Symerio) Stefano Zampini @stefanozampini M. Zhou @cdluminate BLIS's development was partially funded by grants from industry partners, including AMD Hewlett Packard Enterprise Huawei Intel Microsoft Oracle Texas Instruments as well as the National Science Foundation (NSF Awards CCF-0917167, ACI-1148125/1340293, ACI-1550493, and CCF-1320112). blis-0.9.0/INSTALL000066400000000000000000000014651422157504600135160ustar00rootroot00000000000000 BLIS framework INSTALL --- For a detailed description of how to configure, compile, install, and link to a BLIS library on your local system, please read the build system documentation located in: docs/BuildSystem.md Note that the document's markdown content can be conveniently rendered by viewing the file over GitHub via a web browser: https://github.com/flame/blis/blob/master/docs/BuildSystem.md This document will always contain the most up-to-date information related to instantiating a BLIS library from the framework source code. If you have any further questions or wish to provide feedback, please contact the BLIS community by posting your message to the BLIS developer's mailing list: https://groups.google.com/d/forum/blis-devel Thanks for your interest in the BLIS framework! Field Van Zee blis-0.9.0/LICENSE000066400000000000000000000037451422157504600134750ustar00rootroot00000000000000NOTE: Portions of this project's code are copyrighted by The University of Texas at Austin while other portions are copyrighted by Hewlett Packard Enterprise Development LP Advanced Micro Devices, Inc. with some overlap. Please see file-level license headers for file-specific copyright info. All parties provide their portions of the code under the 3-clause BSD license, found below. --- Copyright (C) 2018, The University of Texas at Austin Copyright (C) 2016, Hewlett Packard Enterprise Development LP Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. blis-0.9.0/Makefile000066400000000000000000001367651422157504600141410ustar00rootroot00000000000000# # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2014, The University of Texas at Austin # Copyright (C) 2022, Advanced Micro Devices, Inc. # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # # # Makefile # # Field G. Van Zee # # Top-level makefile for libflame linear algebra library. # # # # --- Makefile PHONY target definitions ---------------------------------------- # .PHONY: all \ libs libblis \ check-env check-env-mk check-env-fragments check-env-make-defs \ flat-header flat-cblas-header \ test \ testblas blastest-f2c blastest-bin blastest-run \ testsuite testsuite-bin \ testsuite-run testsuite-run-fast testsuite-run-md testsuite-run-salt \ testblis testblis-fast testblis-md testblis-salt \ check checkblas \ checkblis checkblis-fast checkblis-md checkblis-salt \ install-headers install-libs install-lib-symlinks \ showconfig \ clean cleanmk cleanh cleanlib distclean \ cleantest cleanblastest cleanblistest \ changelog \ install uninstall uninstall-old \ uninstall-libs uninstall-lib-symlinks uninstall-headers \ uninstall-old-libs uninstall-lib-symlinks uninstall-old-headers # # --- Determine makefile fragment location ------------------------------------- # # Comments: # - We don't need to define DIST_PATH, LIB_PATH, INC_PATH, or SHARE_PATH since # the defaults in common.mk (and config.mk) are designed to work with the # top-level Makefile. #DIST_PATH := . #LIB_PATH = ./lib/$(CONFIG_NAME) #INC_PATH = ./include/$(CONFIG_NAME) #SHARE_PATH := . # # --- Include common makefile definitions -------------------------------------- # # Define the name of the common makefile. COMMON_MK_FILE := common.mk # Include the configuration file. -include $(COMMON_MK_FILE) # Detect whether we actually got the configuration file. If we didn't, then # it is likely that the user has not yet generated it (via configure). ifeq ($(strip $(COMMON_MK_INCLUDED)),yes) COMMON_MK_PRESENT := yes else COMMON_MK_PRESENT := no endif # # --- Main target variable definitions ----------------------------------------- # # --- Object file paths --- # Construct the base object file path for the current configuration. BASE_OBJ_PATH := ./$(OBJ_DIR)/$(CONFIG_NAME) # Construct base object file paths corresponding to the four locations # of source code. BASE_OBJ_CONFIG_PATH := $(BASE_OBJ_PATH)/$(CONFIG_DIR) BASE_OBJ_FRAME_PATH := $(BASE_OBJ_PATH)/$(FRAME_DIR) BASE_OBJ_REFKERN_PATH := $(BASE_OBJ_PATH)/$(REFKERN_DIR) BASE_OBJ_KERNELS_PATH := $(BASE_OBJ_PATH)/$(KERNELS_DIR) BASE_OBJ_ADDON_PATH := $(BASE_OBJ_PATH)/$(ADDON_DIR) BASE_OBJ_SANDBOX_PATH := $(BASE_OBJ_PATH)/$(SANDBOX_DIR) # --- Define install target names for static libraries --- LIBBLIS_A_INST := $(INSTALL_LIBDIR)/$(LIBBLIS_A) # --- Define install target names for shared libraries --- LIBBLIS_SO_INST := $(INSTALL_LIBDIR)/$(LIBBLIS_SO) LIBBLIS_SO_MAJ_INST := $(INSTALL_LIBDIR)/$(LIBBLIS_SONAME) ifeq ($(IS_WIN),yes) # The 'install' target does not create symlinks for Windows builds, so we don't # bother defining LIBBLIS_SO_MMB_INST. LIBBLIS_SO_MMB_INST := else LIBBLIS_SO_MMB_INST := $(INSTALL_LIBDIR)/$(LIBBLIS).$(LIBBLIS_SO_MMB_EXT) endif # --- Determine which libraries to build --- MK_LIBS := MK_LIBS_INST := MK_LIBS_SYML := ifeq ($(MK_ENABLE_STATIC),yes) MK_LIBS += $(LIBBLIS_A_PATH) MK_LIBS_INST += $(LIBBLIS_A_INST) MK_LIBS_SYML += endif ifeq ($(MK_ENABLE_SHARED),yes) MK_LIBS += $(LIBBLIS_SO_PATH) \ $(LIBBLIS_SO_MAJ_PATH) MK_LIBS_INST += $(LIBBLIS_SO_MMB_INST) MK_LIBS_SYML += $(LIBBLIS_SO_INST) \ $(LIBBLIS_SO_MAJ_INST) endif # Strip leading, internal, and trailing whitespace. MK_LIBS_INST := $(strip $(MK_LIBS_INST)) MK_LIBS_SYML := $(strip $(MK_LIBS_SYML)) # --- Define install directory for headers --- # Set the path to the subdirectory of the include installation directory. MK_INCL_DIR_INST := $(INSTALL_INCDIR)/blis # --- Define install directory for public makefile fragments --- # Set the path to the subdirectory of the share installation directory. MK_SHARE_DIR_INST := $(INSTALL_SHAREDIR)/blis PC_SHARE_DIR_INST := $(INSTALL_SHAREDIR)/pkgconfig # # --- Library object definitions ----------------------------------------------- # # In this section, we will isolate the relevant source code filepaths and # convert them to lists of object filepaths. Relevant source code falls into # four categories: configuration source; architecture-specific kernel source; # reference kernel source; and general framework source. # $(call gen-obj-paths-from-src file_exts, src_files, base_src_path, base_obj_path) gen-obj-paths-from-src = $(foreach ch, $(1), \ $(patsubst $(3)/%.$(ch), \ $(4)/%.o, \ $(filter %.$(ch), $(2)) ) ) # Generate object file paths for source code found in the sub-configuration # directories. MK_CONFIG_OBJS := $(call gen-obj-paths-from-src,$(CONFIG_SRC_SUFS),$(MK_CONFIG_SRC),$(CONFIG_PATH),$(BASE_OBJ_CONFIG_PATH)) # Generate object file paths for architecture-specific kernel source code. # We target only .c, .s, and .S files. Note that MK_KERNELS_SRC is already # limited to the kernel source corresponding to the kernel sets in # KERNEL_LIST. This is because the configure script only propogated makefile # fragments into those specific kernel subdirectories. MK_KERNELS_OBJS := $(call gen-obj-paths-from-src,$(KERNELS_SRC_SUFS),$(MK_KERNELS_SRC),$(KERNELS_PATH),$(BASE_OBJ_KERNELS_PATH)) # Generate object file paths for reference kernels, with one set of object # files for each sub-configuration in CONFIG_LIST. Note that due to the # nuances of naming the reference kernel files, we can't use the function # gen-obj-paths-from-src as we do above and below. MK_REFKERN_C := $(filter %.c, $(MK_REFKERN_SRC)) MK_REFKERN_OBJS := $(foreach arch, $(CONFIG_LIST), \ $(patsubst $(REFKERN_PATH)/%_$(REFNM).c, \ $(BASE_OBJ_REFKERN_PATH)/$(arch)/%_$(arch)_$(REFNM).o, \ $(MK_REFKERN_C) \ ) \ ) # Generate object file paths for all of the portable framework source code. MK_FRAME_OBJS := $(call gen-obj-paths-from-src,$(FRAME_SRC_SUFS),$(MK_FRAME_SRC),$(FRAME_PATH),$(BASE_OBJ_FRAME_PATH)) # Generate object file paths for the addon source code. If one or more addons # were not enabled a configure-time, this variable will we empty. MK_ADDON_OBJS := $(call gen-obj-paths-from-src,$(ADDON_SRC_SUFS),$(MK_ADDON_SRC),$(ADDON_PATH),$(BASE_OBJ_ADDON_PATH)) # Generate object file paths for the sandbox source code. If a sandbox was not # enabled a configure-time, this variable will we empty. MK_SANDBOX_OBJS := $(call gen-obj-paths-from-src,$(SANDBOX_SRC_SUFS),$(MK_SANDBOX_SRC),$(SANDBOX_PATH),$(BASE_OBJ_SANDBOX_PATH)) # AMD has chosen to introduce AOCL-specific optimizations to certain BLIS # framework files that are otherwise intended to remain generic. Upstream # developers of vanilla BLIS have agreed to integrate some of these # optimizations, but in a way that keeps the AOCL-specific code segregated # in separate files containing the suffix '_amd'. For example, the BLAS # compatibility layer in vanilla BLIS contains a generic file named # 'bla_gemm.c'. AMD's version of this file is named 'bla_gemm_amd.c'. # Only one or the other is ever built and included in libblis. Currently, # these files are chosen automatically based on the target configuration. ifeq ($(ENABLE_AMD_FRAME_TWEAKS),yes) # Build is being done for AMD platforms; remove the objects which DO NOT have # an "_amd" suffix. MK_FRAME_AMD_OBJS := $(filter $(BASE_OBJ_FRAME_PATH)/%amd.o, $(MK_FRAME_OBJS)) FILES_TO_REMOVE := $(subst _amd.o,.o, $(MK_FRAME_AMD_OBJS)) MK_FRAME_OBJS := $(filter-out $(FILES_TO_REMOVE), $(MK_FRAME_OBJS)) else # Build is being done for non-AMD platforms; remove the objects which DO have # an "_amd" suffix. MK_FRAME_AMD_OBJS := $(filter $(BASE_OBJ_FRAME_PATH)/%amd.o, $(MK_FRAME_OBJS)) MK_FRAME_OBJS := $(filter-out $(MK_FRAME_AMD_OBJS), $(MK_FRAME_OBJS)) endif # Combine all of the object files into some readily-accessible variables. MK_BLIS_OBJS := $(MK_CONFIG_OBJS) \ $(MK_KERNELS_OBJS) \ $(MK_REFKERN_OBJS) \ $(MK_FRAME_OBJS) \ $(MK_ADDON_OBJS) \ $(MK_SANDBOX_OBJS) # Optionally filter out the BLAS and CBLAS compatibility layer object files. # This is not actually necessary, since each affected file is guarded by C # preprocessor macros, but it but prevents "empty" object files from being # added into the library (and reduces compilation time). BASE_OBJ_BLAS_PATH := $(BASE_OBJ_FRAME_PATH)/compat BASE_OBJ_CBLAS_PATH := $(BASE_OBJ_FRAME_PATH)/compat/cblas ifeq ($(MK_ENABLE_CBLAS),no) MK_BLIS_OBJS := $(filter-out $(BASE_OBJ_CBLAS_PATH)/%.o, $(MK_BLIS_OBJS) ) endif ifeq ($(MK_ENABLE_BLAS),no) MK_BLIS_OBJS := $(filter-out $(BASE_OBJ_BLAS_PATH)/%.o, $(MK_BLIS_OBJS) ) endif # # --- Monolithic header definitions -------------------------------------------- # # Define a list of headers to install. The default is to only install blis.h. HEADERS_TO_INSTALL := $(BLIS_H_FLAT) # If CBLAS is enabled, we also install cblas.h so the user does not need to # change their source code to #include "blis.h" in order to access the CBLAS # function prototypes and enums. ifeq ($(MK_ENABLE_CBLAS),yes) HEADERS_TO_INSTALL += $(CBLAS_H_FLAT) endif # If requested, include AMD's C++ template header files in the list of headers # to install. ifeq ($(INSTALL_HH),yes) HEADERS_TO_INSTALL += $(wildcard $(VEND_CPP_PATH)/*.hh) endif # # --- public makefile fragment definitions ------------------------------------- # # Define a list of makefile fragments to install. FRAGS_TO_INSTALL := $(CONFIG_MK_FILE) \ $(COMMON_MK_FILE) PC_IN_FILE := blis.pc.in PC_OUT_FILE := blis.pc # # --- BLAS test drivers definitions -------------------------------------------- # # The location of the BLAS test suite's input files. BLASTEST_INPUT_PATH := $(DIST_PATH)/$(BLASTEST_DIR)/input # The location of the BLAS test suite object directory. BASE_OBJ_BLASTEST_PATH := $(BASE_OBJ_PATH)/$(BLASTEST_DIR) # The locations of the BLAS test suite source code (f2c and drivers). BLASTEST_F2C_SRC_PATH := $(DIST_PATH)/$(BLASTEST_DIR)/f2c BLASTEST_DRV_SRC_PATH := $(DIST_PATH)/$(BLASTEST_DIR)/src # The paths to object files we will create (f2c and drivers). BLASTEST_F2C_OBJS := $(sort \ $(patsubst $(BLASTEST_F2C_SRC_PATH)/%.c, \ $(BASE_OBJ_BLASTEST_PATH)/%.o, \ $(wildcard $(BLASTEST_F2C_SRC_PATH)/*.c)) \ ) BLASTEST_DRV_OBJS := $(sort \ $(patsubst $(BLASTEST_DRV_SRC_PATH)/%.c, \ $(BASE_OBJ_BLASTEST_PATH)/%.o, \ $(wildcard $(BLASTEST_DRV_SRC_PATH)/*.c)) \ ) # libf2c name and location. BLASTEST_F2C_LIB_NAME := libf2c.a BLASTEST_F2C_LIB := $(BASE_OBJ_BLASTEST_PATH)/$(BLASTEST_F2C_LIB_NAME) # The base names of each driver source file (ie: filename minus suffix). BLASTEST_DRV_BASES := $(basename $(notdir $(BLASTEST_DRV_OBJS))) # The binary executable driver names. BLASTEST_DRV_BINS := $(addsuffix .x,$(BLASTEST_DRV_BASES)) BLASTEST_DRV_BIN_PATHS := $(addprefix $(BASE_OBJ_BLASTEST_PATH)/,$(BLASTEST_DRV_BINS)) # Binary executable driver "run-" names BLASTEST_DRV_BINS_R := $(addprefix run-,$(BLASTEST_DRV_BASES)) # Filter level-1, level-2, and level-3 names to different variables. BLASTEST_DRV1_BASES := $(filter %1,$(BLASTEST_DRV_BASES)) BLASTEST_DRV2_BASES := $(filter %2,$(BLASTEST_DRV_BASES)) BLASTEST_DRV3_BASES := $(filter %3,$(BLASTEST_DRV_BASES)) # Define some CFLAGS that we'll only use when compiling BLAS test suite # files. BLAT_CFLAGS := -Wno-parentheses \ -I$(BLASTEST_F2C_SRC_PATH) \ -I. -DHAVE_BLIS_H # Suppress warnings about possibly uninitialized variables for the BLAS # test driver code (as output from f2c), which is riddled with such # variables, but only if the option to do so is supported. ifeq ($(CC_VENDOR),gcc) BLAT_CFLAGS += -Wno-maybe-uninitialized endif # The location of the script that checks the BLAS test output. BLASTEST_CHECK_PATH := $(DIST_PATH)/$(BLASTEST_DIR)/$(BLASTEST_CHECK) # # --- BLIS testsuite definitions ----------------------------------------------- # # The location of the test suite's general and operations-specific # input/configuration files. TESTSUITE_CONF_GEN_PATH := $(DIST_PATH)/$(TESTSUITE_DIR)/$(TESTSUITE_CONF_GEN) TESTSUITE_CONF_OPS_PATH := $(DIST_PATH)/$(TESTSUITE_DIR)/$(TESTSUITE_CONF_OPS) TESTSUITE_FAST_GEN_PATH := $(DIST_PATH)/$(TESTSUITE_DIR)/$(TESTSUITE_FAST_GEN) TESTSUITE_FAST_OPS_PATH := $(DIST_PATH)/$(TESTSUITE_DIR)/$(TESTSUITE_FAST_OPS) TESTSUITE_MIXD_GEN_PATH := $(DIST_PATH)/$(TESTSUITE_DIR)/$(TESTSUITE_MIXD_GEN) TESTSUITE_MIXD_OPS_PATH := $(DIST_PATH)/$(TESTSUITE_DIR)/$(TESTSUITE_MIXD_OPS) TESTSUITE_SALT_GEN_PATH := $(DIST_PATH)/$(TESTSUITE_DIR)/$(TESTSUITE_SALT_GEN) TESTSUITE_SALT_OPS_PATH := $(DIST_PATH)/$(TESTSUITE_DIR)/$(TESTSUITE_SALT_OPS) # The locations of the test suite source directory and the local object # directory. TESTSUITE_SRC_PATH := $(DIST_PATH)/$(TESTSUITE_DIR)/src BASE_OBJ_TESTSUITE_PATH := $(BASE_OBJ_PATH)/$(TESTSUITE_DIR) # Convert source file paths to object file paths by replacing the base source # directories with the base object directories, and also replacing the source # file suffix (eg: '.c') with '.o'. MK_TESTSUITE_OBJS := $(sort \ $(patsubst $(TESTSUITE_SRC_PATH)/%.c, \ $(BASE_OBJ_TESTSUITE_PATH)/%.o, \ $(wildcard $(TESTSUITE_SRC_PATH)/*.c)) \ ) # The test suite binary executable filename. # NOTE: The TESTSUITE_WRAPPER variable defaults to the empty string if it # is not already set, in which case it has no effect lateron when the # testsuite binary is executed via lines such as # # $(TESTSUITE_WRAPPER) ./$(TESTSUITE_BIN) ... > $(TESTSUITE_OUT_FILE) # # The reason TESTSUITE_WRAPPER is employed in this way is so that some # unusual environments (e.g. ARM) can run the testsuite through some other # binary. See .travis.yml for details on how the variable is employed in # practice. TESTSUITE_BIN := test_$(LIBBLIS).x TESTSUITE_WRAPPER ?= # The location of the script that checks the BLIS testsuite output. TESTSUITE_CHECK_PATH := $(DIST_PATH)/$(TESTSUITE_DIR)/$(TESTSUITE_CHECK) # # --- Uninstall definitions ---------------------------------------------------- # ifeq ($(IS_CONFIGURED),yes) # These shell commands gather the filepaths to any library in the current # LIBDIR that might be left over from an old installation. We start with # including nothing for static libraries, since older static libraries are # always overwritten by newer ones. Then we add shared libraries, which are # named with three .so version numbers. UNINSTALL_OLD_LIBS := UNINSTALL_OLD_LIBS += $(filter-out $(INSTALL_LIBDIR)/$(LIBBLIS).$(LIBBLIS_SO_MMB_EXT),$(wildcard $(INSTALL_LIBDIR)/$(LIBBLIS_SO).?.?.?)) # These shell commands gather the filepaths to any library symlink in the # current LIBDIR that might be left over from an old installation. We start # with symlinks named using the .so major version number. UNINSTALL_OLD_SYML := $(filter-out $(INSTALL_LIBDIR)/$(LIBBLIS_SO).$(SO_MAJOR),$(wildcard $(INSTALL_LIBDIR)/$(LIBBLIS_SO).?)) # We also prepare to uninstall older-style symlinks whose names contain the # BLIS version number and configuration family. UNINSTALL_OLD_SYML += $(wildcard $(INSTALL_LIBDIR)/$(LIBBLIS)-*.a) UNINSTALL_OLD_SYML += $(wildcard $(INSTALL_LIBDIR)/$(LIBBLIS)-*.$(SHLIB_EXT)) # This shell command grabs all files named "*.h" that are not blis.h or cblas.h # in the installation directory. We consider this set of headers to be "old" and # eligible for removal upon running of the uninstall-old-headers target. UNINSTALL_OLD_HEADERS := $(filter-out $(BLIS_H),$(filter-out $(CBLAS_H),$(wildcard $(INSTALL_INCDIR)/blis/*.h))) endif # IS_CONFIGURED # # --- Targets/rules ------------------------------------------------------------ # # --- Primary targets --- all: libs libs: libblis test: checkblis checkblas check: checkblis-fast checkblas install: libs install-libs install-lib-symlinks install-headers install-share uninstall: uninstall-libs uninstall-lib-symlinks uninstall-headers uninstall-share uninstall-old: uninstall-old-libs uninstall-old-symlinks uninstall-old-headers clean: cleanh cleanlib # --- Environment check rules --- check-env: check-env-make-defs check-env-fragments check-env-mk check-env-mk: ifeq ($(CONFIG_MK_PRESENT),no) $(error Cannot proceed: config.mk not detected! Run configure first) endif check-env-fragments: check-env-mk ifeq ($(MAKEFILE_FRAGMENTS_PRESENT),no) $(error Cannot proceed: makefile fragments not detected! Run configure first) endif check-env-make-defs: check-env-fragments ifeq ($(ALL_MAKE_DEFS_MK_PRESENT),no) $(error Cannot proceed: Some make_defs.mk files not found or mislabeled!) endif # --- Consolidated blis.h header creation --- flat-header: check-env $(BLIS_H_FLAT) $(BLIS_H_FLAT): $(ALL_H99_FILES) ifeq ($(ENABLE_VERBOSE),yes) $(FLATTEN_H) -c -v1 $(BLIS_H_SRC_PATH) $@ "./$(INCLUDE_DIR)" "$(ALL_H99_DIRPATHS)" else @echo -n "Generating monolithic blis.h" @$(FLATTEN_H) -c -v1 $(BLIS_H_SRC_PATH) $@ "./$(INCLUDE_DIR)" "$(ALL_H99_DIRPATHS)" @echo "Generated $@" endif # --- Consolidated cblas.h header creation --- flat-cblas-header: check-env $(CBLAS_H_FLAT) $(CBLAS_H_FLAT): $(FRAME_H99_FILES) ifeq ($(ENABLE_VERBOSE),yes) $(FLATTEN_H) -c -v1 $(CBLAS_H_SRC_PATH) $@ "./$(INCLUDE_DIR)" "$(ALL_H99_DIRPATHS)" else @echo -n "Generating monolithic cblas.h" @$(FLATTEN_H) -c -v1 $(CBLAS_H_SRC_PATH) $@ "./$(INCLUDE_DIR)" "$(ALL_H99_DIRPATHS)" @echo "Generated $@" endif # --- General source code / object code rules --- # FGVZ: Add support for compiling .s and .S files in 'config'/'kernels' # directories. # - May want to add an extra foreach loop around function eval/call. # first argument: a configuration name from config_list, used to look up the # CFLAGS to use during compilation. define make-config-rule $(BASE_OBJ_CONFIG_PATH)/$(1)/%.o: $(CONFIG_PATH)/$(1)/%.c $(BLIS_H_FLAT) $(MAKE_DEFS_MK_PATHS) ifeq ($(ENABLE_VERBOSE),yes) $(CC) $(call get-config-cflags-for,$(1)) -c $$< -o $$@ else @echo "Compiling $$@" $(call get-config-text-for,$(1)) @$(CC) $(call get-config-cflags-for,$(1)) -c $$< -o $$@ endif endef # first argument: a configuration name from the union of config_list and # config_name, used to look up the CFLAGS to use during compilation. define make-frame-rule $(BASE_OBJ_FRAME_PATH)/%.o: $(FRAME_PATH)/%.c $(BLIS_H_FLAT) $(MAKE_DEFS_MK_PATHS) ifeq ($(ENABLE_VERBOSE),yes) $(CC) $(call get-frame-cflags-for,$(1)) -c $$< -o $$@ else @echo "Compiling $$@" $(call get-frame-text-for,$(1)) @$(CC) $(call get-frame-cflags-for,$(1)) -c $$< -o $$@ endif endef # first argument: a kernel set (name) being targeted (e.g. haswell). define make-refinit-rule $(BASE_OBJ_REFKERN_PATH)/$(1)/bli_cntx_$(1)_ref.o: $(REFKERN_PATH)/bli_cntx_ref.c $(BLIS_H_FLAT) $(MAKE_DEFS_MK_PATHS) ifeq ($(ENABLE_VERBOSE),yes) $(CC) $(call get-refinit-cflags-for,$(1)) -c $$< -o $$@ else @echo "Compiling $$@" $(call get-refinit-text-for,$(1)) @$(CC) $(call get-refinit-cflags-for,$(1)) -c $$< -o $$@ endif endef # first argument: a kernel set (name) being targeted (e.g. haswell). define make-refkern-rule $(BASE_OBJ_REFKERN_PATH)/$(1)/%_$(1)_ref.o: $(REFKERN_PATH)/%_ref.c $(BLIS_H_FLAT) $(MAKE_DEFS_MK_PATHS) ifeq ($(ENABLE_VERBOSE),yes) $(CC) $(call get-refkern-cflags-for,$(1)) -c $$< -o $$@ else @echo "Compiling $$@" $(call get-refkern-text-for,$(1)) @$(CC) $(call get-refkern-cflags-for,$(1)) -c $$< -o $$@ endif endef # first argument: a kernel set (name) being targeted (e.g. haswell). # second argument: the configuration whose CFLAGS we should use in compilation. # third argument: the kernel file suffix being considered. define make-kernels-rule $(BASE_OBJ_KERNELS_PATH)/$(1)/%.o: $(KERNELS_PATH)/$(1)/%.$(3) $(BLIS_H_FLAT) $(MAKE_DEFS_MK_PATHS) ifeq ($(ENABLE_VERBOSE),yes) $(CC) $(call get-kernel-cflags-for,$(2)) -c $$< -o $$@ else @echo "Compiling $$@" $(call get-kernel-text-for,$(2)) @$(CC) $(call get-kernel-cflags-for,$(2)) -c $$< -o $$@ endif endef # first argument: a configuration name from the union of config_list and # config_name, used to look up the CFLAGS to use during compilation. define make-c99-addon-rule $(BASE_OBJ_ADDON_PATH)/%.o: $(ADDON_PATH)/%.$(2) $(BLIS_H_FLAT) $(ADDON_H99_FILES) $(MAKE_DEFS_MK_PATHS) ifeq ($(ENABLE_VERBOSE),yes) $(CC) $(call get-addon-c99flags-for,$(1)) -c $$< -o $$@ else @echo "Compiling $$@" $(call get-addon-c99text-for,$(1)) @$(CC) $(call get-addon-c99flags-for,$(1)) -c $$< -o $$@ endif endef define make-cxx-addon-rule $(BASE_OBJ_ADDON_PATH)/%.o: $(ADDON_PATH)/%.$(2) $(BLIS_H_FLAT) $(ADDON_HXX_FILES) $(MAKE_DEFS_MK_PATHS) ifeq ($(ENABLE_VERBOSE),yes) $(CXX) $(call get-addon-cxxflags-for,$(1)) -c $$< -o $$@ else @echo "Compiling $$@" $(call get-addon-cxxtext-for,$(1)) @$(CXX) $(call get-addon-cxxflags-for,$(1)) -c $$< -o $$@ endif endef # first argument: a configuration name from the union of config_list and # config_name, used to look up the CFLAGS to use during compilation. define make-c99-sandbox-rule $(BASE_OBJ_SANDBOX_PATH)/%.o: $(SANDBOX_PATH)/%.$(2) $(BLIS_H_FLAT) $(SANDBOX_H99_FILES) $(MAKE_DEFS_MK_PATHS) ifeq ($(ENABLE_VERBOSE),yes) $(CC) $(call get-sandbox-c99flags-for,$(1)) -c $$< -o $$@ else @echo "Compiling $$@" $(call get-sandbox-c99text-for,$(1)) @$(CC) $(call get-sandbox-c99flags-for,$(1)) -c $$< -o $$@ endif endef define make-cxx-sandbox-rule $(BASE_OBJ_SANDBOX_PATH)/%.o: $(SANDBOX_PATH)/%.$(2) $(BLIS_H_FLAT) $(SANDBOX_HXX_FILES) $(MAKE_DEFS_MK_PATHS) ifeq ($(ENABLE_VERBOSE),yes) $(CXX) $(call get-sandbox-cxxflags-for,$(1)) -c $$< -o $$@ else @echo "Compiling $$@" $(call get-sandbox-cxxtext-for,$(1)) @$(CXX) $(call get-sandbox-cxxflags-for,$(1)) -c $$< -o $$@ endif endef # Define functions to choose the correct sub-configuration name for the # given kernel set. This function is called when instantiating the # make-kernels-rule. get-config-for-kset = $(lastword $(subst :, ,$(filter $(1):%,$(KCONFIG_MAP)))) # Instantiate the build rule for files in the configuration directory for # each of the sub-configurations in CONFIG_LIST with the CFLAGS designated # for that sub-configuration. $(foreach conf, $(CONFIG_LIST), $(eval $(call make-config-rule,$(conf)))) # Instantiate the build rule for framework files. Use the CFLAGS for the # configuration family, which exists in the directory whose name is equal to # CONFIG_NAME. Note that this doesn't need to be in a loop since we expect # CONFIG_NAME to only ever contain a single name. (BTW: If CONFIG_NAME refers # to a singleton family, then CONFIG_LIST contains CONFIG_NAME as its only # item.) $(foreach conf, $(CONFIG_NAME), $(eval $(call make-frame-rule,$(conf)))) # Instantiate the build rule for reference kernel initialization and # reference kernels for each of the sub-configurations in CONFIG_LIST with # the CFLAGS designated for that sub-configuration. $(foreach conf, $(CONFIG_LIST), $(eval $(call make-refinit-rule,$(conf)))) $(foreach conf, $(CONFIG_LIST), $(eval $(call make-refkern-rule,$(conf)))) # Instantiate the build rule for optimized kernels for each of the kernel # sets in KERNEL_LIST with the CFLAGS designated for the sub-configuration # specified by the KCONFIG_MAP. $(foreach suf, $(KERNELS_SRC_SUFS), \ $(foreach kset, $(KERNEL_LIST), $(eval $(call make-kernels-rule,$(kset),$(call get-config-for-kset,$(kset)),$(suf))))) # Instantiate the build rule for C addon files. Use the CFLAGS for the # configuration family. $(foreach suf, $(ADDON_C99_SUFS), \ $(foreach conf, $(CONFIG_NAME), $(eval $(call make-c99-addon-rule,$(conf),$(suf))))) # Instantiate the build rule for C++ addon files. Use the CFLAGS for the # configuration family. $(foreach suf, $(ADDON_CXX_SUFS), \ $(foreach conf, $(CONFIG_NAME), $(eval $(call make-cxx-addon-rule,$(conf),$(suf))))) # Instantiate the build rule for C sandbox files. Use the CFLAGS for the # configuration family. $(foreach suf, $(SANDBOX_C99_SUFS), \ $(foreach conf, $(CONFIG_NAME), $(eval $(call make-c99-sandbox-rule,$(conf),$(suf))))) # Instantiate the build rule for C++ sandbox files. Use the CXXFLAGS for the # configuration family. $(foreach suf, $(SANDBOX_CXX_SUFS), \ $(foreach conf, $(CONFIG_NAME), $(eval $(call make-cxx-sandbox-rule,$(conf),$(suf))))) # --- All-purpose library rule (static and shared) --- libblis: check-env $(MK_LIBS) # --- Static library archiver rules --- $(LIBBLIS_A_PATH): $(MK_BLIS_OBJS) ifeq ($(ENABLE_VERBOSE),yes) ifeq ($(ARG_MAX_HACK),yes) $(file > $@.in,$^) $(AR) $(ARFLAGS) $@ @$@.in $(RM_F) $@.in $(RANLIB) $@ else $(AR) $(ARFLAGS) $@ $? $(RANLIB) $@ endif else # ifeq ($(ENABLE_VERBOSE),no) ifeq ($(ARG_MAX_HACK),yes) @echo "Archiving $@" @$(file > $@.in,$^) @$(AR) $(ARFLAGS) $@ @$@.in @$(RM_F) $@.in @$(RANLIB) $@ else @echo "Archiving $@" @$(AR) $(ARFLAGS) $@ $? @$(RANLIB) $@ endif endif # --- Shared library linker rules --- $(LIBBLIS_SO_PATH): $(MK_BLIS_OBJS) ifeq ($(ENABLE_VERBOSE),yes) ifeq ($(ARG_MAX_HACK),yes) $(file > $@.in,$^) $(LINKER) $(SOFLAGS) -o $(LIBBLIS_SO_OUTPUT_NAME) @$@.in $(LDFLAGS) $(RM_F) $@.in else $(LINKER) $(SOFLAGS) -o $(LIBBLIS_SO_OUTPUT_NAME) $^ $(LDFLAGS) endif else # ifeq ($(ENABLE_VERBOSE),no) ifeq ($(ARG_MAX_HACK),yes) @echo "Dynamically linking $@" @$(file > $@.in,$^) @$(LINKER) $(SOFLAGS) -o $(LIBBLIS_SO_OUTPUT_NAME) @$@.in $(LDFLAGS) @$(RM_F) $@.in else @echo "Dynamically linking $@" @$(LINKER) $(SOFLAGS) -o $(LIBBLIS_SO_OUTPUT_NAME) $^ $(LDFLAGS) endif endif # Local symlink for shared library. # NOTE: We use a '.loc' suffix to avoid filename collisions in case this # rule is executed concurrently with the install-lib-symlinks rule, which # also creates symlinks in the current directory (before installing them). # NOTE: We don't create any symlinks during Windows builds. $(LIBBLIS_SO_MAJ_PATH): $(LIBBLIS_SO_PATH) ifeq ($(IS_WIN),no) ifeq ($(ENABLE_VERBOSE),yes) $(SYMLINK) $( out.$(1) else @echo "Running $(1).x > 'out.$(1)'" @$(TESTSUITE_WRAPPER) $(BASE_OBJ_BLASTEST_PATH)/$(1).x > out.$(1) endif endef # Instantiate the rule above for each level-1 driver file. $(foreach name, $(BLASTEST_DRV1_BASES), $(eval $(call make-run-blat1-rule,$(name)))) # A rule to run ?blat2.x and ?blat3.x driver files. define make-run-blat23-rule run-$(1): $(BASE_OBJ_BLASTEST_PATH)/$(1).x ifeq ($(ENABLE_VERBOSE),yes) $(TESTSUITE_WRAPPER) $(BASE_OBJ_BLASTEST_PATH)/$(1).x < $(BLASTEST_INPUT_PATH)/$(1).in else @echo "Running $(1).x < '$(BLASTEST_INPUT_PATH)/$(1).in' (output to 'out.$(1)')" @$(TESTSUITE_WRAPPER) $(BASE_OBJ_BLASTEST_PATH)/$(1).x < $(BLASTEST_INPUT_PATH)/$(1).in endif endef # Instantiate the rule above for each level-2 driver file. $(foreach name, $(BLASTEST_DRV2_BASES), $(eval $(call make-run-blat23-rule,$(name)))) # Instantiate the rule above for each level-3 driver file. $(foreach name, $(BLASTEST_DRV3_BASES), $(eval $(call make-run-blat23-rule,$(name)))) # Check the results of the BLAS test suite drivers. checkblas: blastest-run ifeq ($(ENABLE_VERBOSE),yes) - $(BLASTEST_CHECK_PATH) else @- $(BLASTEST_CHECK_PATH) endif # --- BLIS test suite rules --- testblis: testsuite testblis-fast: testsuite-run-fast testblis-md: testsuite-run-md testblis-salt: testsuite-run-salt testsuite: testsuite-run testsuite-bin: check-env $(TESTSUITE_BIN) # Object file rule. $(BASE_OBJ_TESTSUITE_PATH)/%.o: $(TESTSUITE_SRC_PATH)/%.c $(BLIS_H_FLAT) ifeq ($(ENABLE_VERBOSE),yes) $(CC) $(call get-user-cflags-for,$(CONFIG_NAME)) -c $< -o $@ else @echo "Compiling $@" @$(CC) $(call get-user-cflags-for,$(CONFIG_NAME)) -c $< -o $@ endif # Testsuite binary rule. $(TESTSUITE_BIN): $(MK_TESTSUITE_OBJS) $(LIBBLIS_LINK) ifeq ($(ENABLE_VERBOSE),yes) $(LINKER) $(MK_TESTSUITE_OBJS) $(LIBBLIS_LINK) $(LDFLAGS) -o $@ else @echo "Linking $@ against '$(LIBBLIS_LINK) "$(LDFLAGS)"'" @$(LINKER) $(MK_TESTSUITE_OBJS) $(LIBBLIS_LINK) $(LDFLAGS) -o $@ endif # A rule to run the testsuite using the normal input.* files. testsuite-run: testsuite-bin ifeq ($(ENABLE_VERBOSE),yes) $(TESTSUITE_WRAPPER) ./$(TESTSUITE_BIN) -g $(TESTSUITE_CONF_GEN_PATH) \ -o $(TESTSUITE_CONF_OPS_PATH) \ > $(TESTSUITE_OUT_FILE) else @echo "Running $(TESTSUITE_BIN) with output redirected to '$(TESTSUITE_OUT_FILE)'" @$(TESTSUITE_WRAPPER) ./$(TESTSUITE_BIN) -g $(TESTSUITE_CONF_GEN_PATH) \ -o $(TESTSUITE_CONF_OPS_PATH) \ > $(TESTSUITE_OUT_FILE) endif # A rule to run the testsuite using the input.*.fast files, which # run a set of tests designed to finish much more quickly. testsuite-run-fast: testsuite-bin ifeq ($(ENABLE_VERBOSE),yes) $(TESTSUITE_WRAPPER) ./$(TESTSUITE_BIN) -g $(TESTSUITE_FAST_GEN_PATH) \ -o $(TESTSUITE_FAST_OPS_PATH) \ > $(TESTSUITE_OUT_FILE) else @echo "Running $(TESTSUITE_BIN) (fast) with output redirected to '$(TESTSUITE_OUT_FILE)'" @$(TESTSUITE_WRAPPER) ./$(TESTSUITE_BIN) -g $(TESTSUITE_FAST_GEN_PATH) \ -o $(TESTSUITE_FAST_OPS_PATH) \ > $(TESTSUITE_OUT_FILE) endif # A rule to run the testsuite using the input.*.md files, which # run a set of tests designed to only exercise mixed-datatype gemm. testsuite-run-md: testsuite-bin ifeq ($(ENABLE_VERBOSE),yes) $(TESTSUITE_WRAPPER) ./$(TESTSUITE_BIN) -g $(TESTSUITE_MIXD_GEN_PATH) \ -o $(TESTSUITE_MIXD_OPS_PATH) \ > $(TESTSUITE_OUT_FILE) else @echo "Running $(TESTSUITE_BIN) (mixed dt) with output redirected to '$(TESTSUITE_OUT_FILE)'" @$(TESTSUITE_WRAPPER) ./$(TESTSUITE_BIN) -g $(TESTSUITE_MIXD_GEN_PATH) \ -o $(TESTSUITE_MIXD_OPS_PATH) \ > $(TESTSUITE_OUT_FILE) endif # A rule to run the testsuite using the input.*.salt files, which # simulates application-level threading across operation tests. testsuite-run-salt: testsuite-bin ifeq ($(ENABLE_VERBOSE),yes) $(TESTSUITE_WRAPPER) ./$(TESTSUITE_BIN) -g $(TESTSUITE_SALT_GEN_PATH) \ -o $(TESTSUITE_SALT_OPS_PATH) \ > $(TESTSUITE_OUT_FILE) else @echo "Running $(TESTSUITE_BIN) (salt) with output redirected to '$(TESTSUITE_OUT_FILE)'" @$(TESTSUITE_WRAPPER) ./$(TESTSUITE_BIN) -g $(TESTSUITE_SALT_GEN_PATH) \ -o $(TESTSUITE_SALT_OPS_PATH) \ > $(TESTSUITE_OUT_FILE) endif # Check the results of the BLIS testsuite. checkblis: testsuite-run ifeq ($(ENABLE_VERBOSE),yes) - $(TESTSUITE_CHECK_PATH) $(TESTSUITE_OUT_FILE) else @- $(TESTSUITE_CHECK_PATH) $(TESTSUITE_OUT_FILE) endif # Check the results of the BLIS testsuite (fast). checkblis-fast: testsuite-run-fast ifeq ($(ENABLE_VERBOSE),yes) - $(TESTSUITE_CHECK_PATH) $(TESTSUITE_OUT_FILE) else @- $(TESTSUITE_CHECK_PATH) $(TESTSUITE_OUT_FILE) endif # Check the results of the BLIS testsuite (mixed-datatype). checkblis-md: testsuite-run-md ifeq ($(ENABLE_VERBOSE),yes) - $(TESTSUITE_CHECK_PATH) $(TESTSUITE_OUT_FILE) else @- $(TESTSUITE_CHECK_PATH) $(TESTSUITE_OUT_FILE) endif # Check the results of the BLIS testsuite (salt). checkblis-salt: testsuite-run-salt ifeq ($(ENABLE_VERBOSE),yes) - $(TESTSUITE_CHECK_PATH) $(TESTSUITE_OUT_FILE) else @- $(TESTSUITE_CHECK_PATH) $(TESTSUITE_OUT_FILE) endif # --- AMD's C++ template header test rules --- # NOTE: The targets below won't work as intended for an out-of-tree build, # and so it's disabled for now. #testcpp: testvendcpp # Recursively run the test for AMD's C++ template header. #testvendcpp: # $(MAKE) -C $(VEND_TESTCPP_PATH) # --- Install header rules --- install-headers: check-env $(MK_INCL_DIR_INST) $(MK_INCL_DIR_INST): $(HEADERS_TO_INSTALL) $(CONFIG_MK_FILE) ifeq ($(ENABLE_VERBOSE),yes) $(MKDIR) $(@) $(INSTALL) -m 0644 $(HEADERS_TO_INSTALL) $(@) else @$(MKDIR) $(@) @echo "Installing $(notdir $(HEADERS_TO_INSTALL)) into $(@)/" @$(INSTALL) -m 0644 $(HEADERS_TO_INSTALL) $(@) endif # --- Install share rules --- install-share: check-env $(MK_SHARE_DIR_INST) $(PC_SHARE_DIR_INST) $(MK_SHARE_DIR_INST): $(FRAGS_TO_INSTALL) $(CONFIG_MK_FILE) ifeq ($(ENABLE_VERBOSE),yes) $(MKDIR) $(@) $(INSTALL) -m 0644 $(FRAGS_TO_INSTALL) $(@) $(MKDIR) -p $(@)/$(CONFIG_DIR)/$(CONFIG_NAME) $(INSTALL) -m 0644 $(CONFIG_DIR)/$(CONFIG_NAME)/$(MAKE_DEFS_FILE) \ $(@)/$(CONFIG_DIR)/$(CONFIG_NAME) else @$(MKDIR) $(@) @echo "Installing $(notdir $(FRAGS_TO_INSTALL)) into $(@)/" @$(INSTALL) -m 0644 $(FRAGS_TO_INSTALL) $(@) @$(MKDIR) -p $(@)/$(CONFIG_DIR)/$(CONFIG_NAME) @echo "Installing $(CONFIG_DIR)/$(CONFIG_NAME)/$(MAKE_DEFS_FILE) into $(@)/$(CONFIG_DIR)/$(CONFIG_NAME)" @$(INSTALL) -m 0644 $(CONFIG_DIR)/$(CONFIG_NAME)/$(MAKE_DEFS_FILE) \ $(@)/$(CONFIG_DIR)/$(CONFIG_NAME)/ endif $(PC_SHARE_DIR_INST): $(PC_IN_FILE) $(MKDIR) $(@) ifeq ($(ENABLE_VERBOSE),no) @echo "Installing $(PC_OUT_FILE) into $(@)/" endif $(shell cat "$(PC_IN_FILE)" \ | sed -e "s#@PACKAGE_VERSION@#$(VERSION)#g" \ | sed -e "s#@prefix@#$(prefix)#g" \ | sed -e "s#@exec_prefix@#$(exec_prefix)#g" \ | sed -e "s#@libdir@#$(libdir)#g" \ | sed -e "s#@includedir@#$(includedir)#g" \ | sed -e "s#@LDFLAGS@#$(LDFLAGS)#g" \ > "$(PC_OUT_FILE)" ) $(INSTALL) -m 0644 $(PC_OUT_FILE) $(@) # --- Install library rules --- install-libs: check-env $(MK_LIBS_INST) # Install static library. $(INSTALL_LIBDIR)/%.a: $(BASE_LIB_PATH)/%.a $(CONFIG_MK_FILE) ifeq ($(ENABLE_VERBOSE),yes) $(MKDIR) $(@D) $(INSTALL) -m 0644 $< $@ else @echo "Installing $(@F) into $(INSTALL_LIBDIR)/" @$(MKDIR) $(@D) @$(INSTALL) -m 0644 $< $@ endif # Install shared library containing .so major, minor, and build versions. # Note: Installation rules for Windows does not include major, minor, and # build version numbers. ifeq ($(IS_WIN),no) # Linux/OSX library (.so OR .dylib) installation rules. $(INSTALL_LIBDIR)/%.$(LIBBLIS_SO_MMB_EXT): $(BASE_LIB_PATH)/%.$(SHLIB_EXT) $(CONFIG_MK_FILE) ifeq ($(ENABLE_VERBOSE),yes) $(MKDIR) $(@D) $(INSTALL) -m 0755 $< $@ else @echo "Installing $(@F) into $(INSTALL_LIBDIR)/" @$(MKDIR) $(@D) @$(INSTALL) -m 0755 $< $@ endif else # ifeq ($(IS_WIN),yes) # Windows library (.dll and .lib) installation rules. $(INSTALL_LIBDIR)/%.$(SHLIB_EXT): $(BASE_LIB_PATH)/%.$(SHLIB_EXT) ifeq ($(ENABLE_VERBOSE),yes) @$(MKDIR) $(@D) @$(INSTALL) -m 0644 $(BASE_LIB_PATH)/$(@F) $@ else @echo "Installing $(@F) into $(INSTALL_LIBDIR)/" @$(MKDIR) $(@D) @$(INSTALL) -m 0644 $(BASE_LIB_PATH)/$(@F) $@ endif $(INSTALL_LIBDIR)/%.$(LIBBLIS_SO_MAJ_EXT): $(BASE_LIB_PATH)/%.$(LIBBLIS_SO_MAJ_EXT) ifeq ($(ENABLE_VERBOSE),yes) @$(MKDIR) $(@D) @$(INSTALL) -m 0644 $(BASE_LIB_PATH)/$(@F) $@ else @echo "Installing $(@F) into $(INSTALL_LIBDIR)/" @$(MKDIR) $(@D) @$(INSTALL) -m 0644 $(BASE_LIB_PATH)/$(@F) $@ endif endif # ifeq ($(IS_WIN),no) # --- Install-symlinks rules --- install-lib-symlinks: check-env $(MK_LIBS_SYML) # Note: Symlinks are not installed on Windows. ifeq ($(IS_WIN),no) # Install generic shared library symlink. $(INSTALL_LIBDIR)/%.$(SHLIB_EXT): $(INSTALL_LIBDIR)/%.$(LIBBLIS_SO_MMB_EXT) ifeq ($(ENABLE_VERBOSE),yes) $(SYMLINK) $( $(DIST_PATH)/$(CHANGELOG) # --- Uninstall rules --- # NOTE: We can't write these uninstall rules directly in terms of targets # $(MK_LIBS_VERS_CONF_INST), $(MK_LIBS_INST), and $(MK_INCL_DIR_INST) # because those targets are already defined in terms of rules that *build* # those products. uninstall-libs: check-env ifeq ($(ENABLE_VERBOSE),yes) - $(RM_F) $(MK_LIBS_INST) else @echo "Uninstalling libraries $(notdir $(MK_LIBS_INST)) from $(dir $(firstword $(MK_LIBS_INST)))" @- $(RM_F) $(MK_LIBS_INST) endif uninstall-lib-symlinks: check-env ifeq ($(ENABLE_VERBOSE),yes) - $(RM_F) $(MK_LIBS_SYML) else @echo "Uninstalling symlinks $(notdir $(MK_LIBS_SYML)) from $(dir $(firstword $(MK_LIBS_SYML)))" @- $(RM_F) $(MK_LIBS_SYML) endif uninstall-headers: check-env ifeq ($(ENABLE_VERBOSE),yes) - $(RM_RF) $(MK_INCL_DIR_INST) else @echo "Uninstalling directory '$(notdir $(MK_INCL_DIR_INST))' from $(dir $(MK_INCL_DIR_INST))" @- $(RM_RF) $(MK_INCL_DIR_INST) endif uninstall-share: check-env ifeq ($(ENABLE_VERBOSE),yes) - $(RM_RF) $(MK_SHARE_DIR_INST) else @echo "Uninstalling directory '$(notdir $(MK_SHARE_DIR_INST))' from $(dir $(MK_SHARE_DIR_INST))" @- $(RM_RF) $(MK_SHARE_DIR_INST) endif # --- Uninstall old rules --- uninstall-old-libs: $(UNINSTALL_OLD_LIBS) check-env uninstall-old-symlinks: $(UNINSTALL_OLD_SYML) check-env uninstall-old-headers: $(UNINSTALL_OLD_HEADERS) check-env $(UNINSTALL_OLD_LIBS) $(UNINSTALL_OLD_SYML) $(UNINSTALL_OLD_HEADERS): check-env ifeq ($(ENABLE_VERBOSE),yes) - $(RM_F) $@ else @echo "Uninstalling $(@F) from $(@D)/" @- $(RM_F) $@ endif blis-0.9.0/README.md000066400000000000000000001211731422157504600137430ustar00rootroot00000000000000![The BLIS cat is sleeping.](http://www.cs.utexas.edu/users/field/blis_cat.png) [![Build Status](https://api.travis-ci.com/flame/blis.svg?branch=master)](https://app.travis-ci.com/github/flame/blis) [![Build Status](https://ci.appveyor.com/api/projects/status/github/flame/blis?branch=master&svg=true)](https://ci.appveyor.com/project/shpc/blis/branch/master) Contents -------- * **[Introduction](#introduction)** * **[Education and Learning](#education-and-learning)** * **[What's New](#whats-new)** * **[What People Are Saying About BLIS](#what-people-are-saying-about-blis)** * **[Key Features](#key-features)** * **[How to Download BLIS](#how-to-download-blis)** * **[Getting Started](#getting-started)** * **[Example Code](#example-code)** * **[Documentation](#documentation)** * **[Performance](#performance)** * **[External Packages](#external-packages)** * **[Discussion](#discussion)** * **[Contributing](#contributing)** * **[Citations](#citations)** * **[Funding](#funding)** Introduction ------------ BLIS is a portable software framework for instantiating high-performance BLAS-like dense linear algebra libraries. The framework was designed to isolate essential kernels of computation that, when optimized, immediately enable optimized implementations of most of its commonly used and computationally intensive operations. BLIS is written in [ISO C99](http://en.wikipedia.org/wiki/C99) and available under a [new/modified/3-clause BSD license](http://opensource.org/licenses/BSD-3-Clause). While BLIS exports a [new BLAS-like API](docs/BLISTypedAPI.md), it also includes a BLAS compatibility layer which gives application developers access to BLIS implementations via traditional [BLAS routine calls](http://www.netlib.org/lapack/lug/node145.html). An [object-based API](docs/BLISObjectAPI.md) unique to BLIS is also available. For a thorough presentation of our framework, please read our [ACM Transactions on Mathematical Software (TOMS)](https://toms.acm.org/) journal article, ["BLIS: A Framework for Rapidly Instantiating BLAS Functionality"](http://dl.acm.org/authorize?N91172). For those who just want an executive summary, please see the [Key Features](#key-features) section below. In a follow-up article (also in [ACM TOMS](https://toms.acm.org/)), ["The BLIS Framework: Experiments in Portability"](http://dl.acm.org/authorize?N16240), we investigate using BLIS to instantiate level-3 BLAS implementations on a variety of general-purpose, low-power, and multicore architectures. An IPDPS'14 conference paper titled ["Anatomy of High-Performance Many-Threaded Matrix Multiplication"](http://www.cs.utexas.edu/users/flame/pubs/blis3_ipdps14.pdf) systematically explores the opportunities for parallelism within the five loops that BLIS exposes in its matrix multiplication algorithm. For other papers related to BLIS, please see the [Citations section](#citations) below. It is our belief that BLIS offers substantial benefits in productivity when compared to conventional approaches to developing BLAS libraries, as well as a much-needed refinement of the BLAS interface, and thus constitutes a major advance in dense linear algebra computation. While BLIS remains a work-in-progress, we are excited to continue its development and further cultivate its use within the community. The BLIS framework is primarily developed and maintained by individuals in the [Science of High-Performance Computing](http://shpc.ices.utexas.edu/) (SHPC) group in the [Oden Institute for Computational Engineering and Sciences](https://www.oden.utexas.edu/) at [The University of Texas at Austin](https://www.utexas.edu/). Please visit the [SHPC](http://shpc.ices.utexas.edu/) website for more information about our research group, such as a list of [people](http://shpc.ices.utexas.edu/people.html) and [collaborators](http://shpc.ices.utexas.edu/collaborators.html), [funding sources](http://shpc.ices.utexas.edu/funding.html), [publications](http://shpc.ices.utexas.edu/publications.html), and [other educational projects](http://www.ulaff.net/) (such as MOOCs). Education and Learning ---------------------- Want to understand what's under the hood? Many of the same concepts and principles employed when developing BLIS are introduced and taught in a basic pedagogical setting as part of [LAFF-On Programming for High Performance (LAFF-On-PfHP)](http://www.ulaff.net/), one of several massive open online courses (MOOCs) in the [Linear Algebra: Foundations to Frontiers](http://www.ulaff.net/) series, all of which are available for free via the [edX platform](http://www.edx.org/). What's New ---------- * **Addons feature now available!** Have you ever wanted to quickly extend BLIS's operation support or define new custom BLIS APIs for your application, but were unsure of how to add your source code to BLIS? Do you want to isolate your custom code so that it only gets enabled when the user requests it? Do you like [sandboxes](docs/Sandboxes.md), but wish you didn't have to provide an implementation of `gemm`? If so, you should check out our new [addons](docs/Addons.md) feature. Addons act like optional extensions that can be created, enabled, and combined to suit your application's needs, all without formally integrating your code into the core BLIS framework. * **Multithreaded small/skinny matrix support for sgemm now available!** Thanks to funding and hardware support from Oracle, we have now accelerated `gemm` for single-precision real matrix problems where one or two dimensions is exceedingly small. This work is similar to the `gemm` optimization announced last year. For now, we have only gathered performance results on an AMD Epyc Zen2 system, but we hope to publish additional graphs for other architectures in the future. You may find these Zen2 graphs via the [PerformanceSmall](docs/PerformanceSmall.md) document. * **BLIS awarded SIAM Activity Group on Supercomputing Best Paper Prize for 2020!** We are thrilled to announce that the paper that we internally refer to as the second BLIS paper, "The BLIS Framework: Experiments in Portability." Field G. Van Zee, Tyler Smith, Bryan Marker, Tze Meng Low, Robert A. van de Geijn, Francisco Igual, Mikhail Smelyanskiy, Xianyi Zhang, Michael Kistler, Vernon Austel, John A. Gunnels, Lee Killough. ACM Transactions on Mathematical Software (TOMS), 42(2):12:1--12:19, 2016. was selected for the [SIAM Activity Group on Supercomputing Best Paper Prize](https://www.siam.org/prizes-recognition/activity-group-prizes/detail/siag-sc-best-paper-prize) for 2020. The prize is awarded once every two years to a paper judged to be the most outstanding paper in the field of parallel scientific and engineering computing, and has only been awarded once before (in 2016) since its inception in 2015 (the committee did not award the prize in 2018). The prize [was awarded](https://www.oden.utexas.edu/about/news/ScienceHighPerfomanceComputingSIAMBestPaperPrize/) at the [2020 SIAM Conference on Parallel Processing for Scientific Computing](https://www.siam.org/conferences/cm/conference/pp20) in Seattle. Robert was present at the conference to give [a talk on BLIS](https://meetings.siam.org/sess/dsp_programsess.cfm?SESSIONCODE=68266) and accept the prize alongside other coauthors. The selection committee sought to recognize the paper, "which validates BLIS, a framework relying on the notion of microkernels that enables both productivity and high performance." Their statement continues, "The framework will continue having an important influence on the design and the instantiation of dense linear algebra libraries." * **Multithreaded small/skinny matrix support for dgemm now available!** Thanks to contributions made possible by our partnership with AMD, we have dramatically accelerated `gemm` for double-precision real matrix problems where one or two dimensions is exceedingly small. A natural byproduct of this optimization is that the traditional case of small _m = n = k_ (i.e. square matrices) is also accelerated, even though it was not targeted specifically. And though only `dgemm` was optimized for now, support for other datatypes and/or other operations may be implemented in the future. We've also added new graphs to the [PerformanceSmall](docs/PerformanceSmall.md) document to showcase multithreaded performance when one or more matrix dimensions are small. * **Performance comparisons now available!** We recently measured the performance of various level-3 operations on a variety of hardware architectures, as implemented within BLIS and other BLAS libraries for all four of the standard floating-point datatypes. The results speak for themselves! Check out our extensive performance graphs and background info in our new [Performance](docs/Performance.md) document. * **BLIS is now in Debian Unstable!** Thanks to Debian developer-maintainers [M. Zhou](https://github.com/cdluminate) and [Nico Schlömer](https://github.com/nschloe) for sponsoring our package in Debian. Their participation, contributions, and advocacy were key to getting BLIS into the second-most popular Linux distribution (behind Ubuntu, which Debian packages feed into). The Debian tracker page may be found [here](https://tracker.debian.org/pkg/blis). * **BLIS now supports mixed-datatype gemm!** The `gemm` operation may now be executed on operands of mixed domains and/or mixed precisions. Any combination of storage datatype for A, B, and C is now supported, along with a separate computation precision that can differ from the storage precision of A and B. And even the 1m method now supports mixed-precision computation. For more details, please see our [ACM TOMS](https://toms.acm.org/) journal article submission ([current draft](http://www.cs.utexas.edu/users/flame/pubs/blis7_toms_rev0.pdf)). * **BLIS now implements the 1m method.** Let's face it: writing complex assembly `gemm` microkernels for a new architecture is never a priority--and now, it almost never needs to be. The 1m method leverages existing real domain `gemm` microkernels to implement all complex domain level-3 operations. For more details, please see our [ACM TOMS](https://toms.acm.org/) journal article submission ([current draft](http://www.cs.utexas.edu/users/flame/pubs/blis6_toms_rev2.pdf)). What People Are Saying About BLIS --------------------------------- *["I noticed a substantial increase in multithreaded performance on my own machine, which was extremely satisfying."](https://groups.google.com/d/msg/blis-discuss/8iu9B5KCxpA/uftpjgIsBwAJ)* ... *["[I was] happy it worked so well!"](https://groups.google.com/d/msg/blis-discuss/8iu9B5KCxpA/uftpjgIsBwAJ)* (Justin Shea) *["This is an awesome library."](https://github.com/flame/blis/issues/288#issuecomment-447488637)* ... *["I want to thank you and the blis team for your efforts."](https://github.com/flame/blis/issues/288#issuecomment-448074704)* ([@Lephar](https://github.com/Lephar)) *["Any time somebody outside Intel beats MKL by a nontrivial amount, I report it to the MKL team. It is fantastic for any open-source project to get within 10% of MKL... [T]his is why Intel funds BLIS development."](https://github.com/flame/blis/issues/264#issuecomment-428673275)* ([@jeffhammond](https://github.com/jeffhammond)) *["So BLIS is now a part of Elk."](https://github.com/flame/blis/issues/267#issuecomment-429303902)* ... *["We have found that zgemm applied to a 15000x15000 matrix with multi-threaded BLIS on a 32-core Ryzen 2990WX processor is about twice as fast as MKL"](https://github.com/flame/blis/issues/264#issuecomment-428373946)* ... *["I'm starting to like this a lot."](https://github.com/flame/blis/issues/264#issuecomment-428926191)* ([@jdk2016](https://github.com/jdk2016)) *["I [found] BLIS because I was looking for BLAS operations on C-ordered arrays for NumPy. BLIS has that, but even better is the fact that it's developed in the open using a more modern language than Fortran."](https://github.com/flame/blis/issues/254#issuecomment-423838345)* ([@nschloe](https://github.com/nschloe)) *["The specific reason to have BLIS included [in Linux distributions] is the KNL and SKX [AVX-512] BLAS support, which OpenBLAS doesn't have."](https://github.com/flame/blis/issues/210#issuecomment-393126303)* ([@loveshack](https://github.com/loveshack)) *["All tests pass without errors on OpenBSD. Thanks!"](https://github.com/flame/blis/issues/202#issuecomment-389691543)* ([@ararslan](https://github.com/ararslan)) *["Thank you very much for your great help!... Looking forward to benchmarking."](https://github.com/flame/blis/issues/180#issuecomment-375895449)* ([@mrader1248](https://github.com/mrader1248)) *["Thanks for the beautiful work."](https://github.com/flame/blis/issues/163#issue-286575452)* ([@mmrmo](https://github.com/mmrmo)) *["[M]y software currently uses BLIS for its BLAS interface..."](https://github.com/flame/blis/issues/129#issuecomment-302904805)* ([@ShadenSmith](https://github.com/ShadenSmith)) *["[T]hanks so much for your work on this! Excited to test."](https://github.com/flame/blis/issues/129#issuecomment-341565071)* ... *["[On AMD Excavator], BLIS is competitive to / slightly faster than OpenBLAS for dgemms in my tests."](https://github.com/flame/blis/issues/129#issuecomment-341608673)* ([@iotamudelta](https://github.com/iotamudelta)) *["BLIS provided the only viable option on KNL, whose ecosystem is at present dominated by blackbox toolchains. Thanks again. Keep on this great work."](https://github.com/flame/blis/issues/116#issuecomment-281225101)* ([@heroxbd](https://github.com/heroxbd)) *["I want to definitely try this out..."](https://github.com/flame/blis/issues/12#issuecomment-48086295)* ([@ViralBShah](https://github.com/ViralBShah)) Key Features ------------ BLIS offers several advantages over traditional BLAS libraries: * **Portability that doesn't impede high performance.** Portability was a top priority of ours when creating BLIS. With virtually no additional effort on the part of the developer, BLIS is configurable as a fully-functional reference implementation. But more importantly, the framework identifies and isolates a key set of computational kernels which, when optimized, immediately and automatically optimize performance across virtually all level-2 and level-3 BLIS operations. In this way, the framework acts as a productivity multiplier. And since the optimized (non-portable) code is compartmentalized within these few kernels, instantiating a high-performance BLIS library on a new architecture is a relatively straightforward endeavor. * **Generalized matrix storage.** The BLIS framework exports interfaces that allow one to specify both the row stride and column stride of a matrix. This allows one to compute with matrices stored in column-major order, row-major order, or by general stride. (This latter storage format is important for those seeking to implement tensor contractions on multidimensional arrays.) Furthermore, since BLIS tracks stride information for each matrix, operands of different storage formats can be used within the same operation invocation. By contrast, BLAS requires column-major storage. And while the CBLAS interface supports row-major storage, it does not allow mixing storage formats. * **Rich support for the complex domain.** BLIS operations are developed and expressed in their most general form, which is typically in the complex domain. These formulations then simplify elegantly down to the real domain, with conjugations becoming no-ops. Unlike the BLAS, all input operands in BLIS that allow transposition and conjugate-transposition also support conjugation (without transposition), which obviates the need for thread-unsafe workarounds. Also, where applicable, both complex symmetric and complex Hermitian forms are supported. (BLAS omits some complex symmetric operations, such as `symv`, `syr`, and `syr2`.) Another great example of BLIS serving as a portability lever is its implementation of the 1m method for complex matrix multiplication, a novel mechanism of providing high-performance complex level-3 operations using only real domain microkernels. This new innovation guarantees automatic level-3 support in the complex domain even when the kernel developers entirely forgo writing complex kernels. * **Advanced multithreading support.** BLIS allows multiple levels of symmetric multithreading for nearly all level-3 operations. (Currently, users may choose to obtain parallelism via either OpenMP or POSIX threads). This means that matrices may be partitioned in multiple dimensions simultaneously to attain scalable, high-performance parallelism on multicore and many-core architectures. The key to this innovation is a thread-specific control tree infrastructure which encodes information about the logical thread topology and allows threads to query and communicate data amongst one another. BLIS also employs so-called "quadratic partitioning" when computing dimension sub-ranges for each thread, so that arbitrary diagonal offsets of structured matrices with unreferenced regions are taken into account to achieve proper load balance. More recently, BLIS introduced a runtime abstraction to specify parallelism on a per-call basis, which is useful for applications that want to handle most of the parallelism. * **Ease of use.** The BLIS framework, and the library of routines it generates, are easy to use for end users, experts, and vendors alike. An optional BLAS compatibility layer provides application developers with backwards compatibility to existing BLAS-dependent codes. Or, one may adjust or write their application to take advantage of new BLIS functionality (such as generalized storage formats or additional complex operations) by calling one of BLIS's native APIs directly. BLIS's typed API will feel familiar to many veterans of BLAS since these interfaces use BLAS-like calling sequences. And many will find BLIS's object-based APIs a delight to use when customizing or writing their own BLIS operations. (Objects are relatively lightweight `structs` and passed by address, which helps tame function calling overhead.) * **Multilayered API and exposed kernels.** The BLIS framework exposes its implementations in various layers, allowing expert developers to access exactly the functionality desired. This layered interface includes that of the lowest-level kernels, for those who wish to bypass the bulk of the framework. Optimizations can occur at various levels, in part thanks to exposed packing and unpacking facilities, which by default are highly parameterized and flexible. * **Functionality that grows with the community's needs.** As its name suggests, the BLIS framework is not a single library or static API, but rather a nearly-complete template for instantiating high-performance BLAS-like libraries. Furthermore, the framework is extensible, allowing developers to leverage existing components to support new operations as they are identified. If such operations require new kernels for optimal efficiency, the framework and its APIs will be adjusted and extended accordingly. Community developers who wish to experiment with creating new operations or APIs in BLIS can quickly and easily do so via the [Addons](docs/Addons.md) feature. * **Code re-use.** Auto-generation approaches to achieving the aforementioned goals tend to quickly lead to code bloat due to the multiple dimensions of variation supported: operation (i.e. `gemm`, `herk`, `trmm`, etc.); parameter case (i.e. side, [conjugate-]transposition, upper/lower storage, unit/non-unit diagonal); datatype (i.e. single-/double-precision real/complex); matrix storage (i.e. row-major, column-major, generalized); and algorithm (i.e. partitioning path and kernel shape). These "brute force" approaches often consider and optimize each operation or case combination in isolation, which is less than ideal when the goal is to provide entire libraries. BLIS was designed to be a complete framework for implementing basic linear algebra operations, but supporting this vast amount of functionality in a manageable way required a holistic design that employed careful abstractions, layering, and recycling of generic (highly parameterized) codes, subject to the constraint that high performance remain attainable. * **A foundation for mixed domain and/or mixed precision operations.** BLIS was designed with the hope of one day allowing computation on real and complex operands within the same operation. Similarly, we wanted to allow mixing operands' numerical domains, floating-point precisions, or both domain and precision, and to optionally compute in a precision different than one or both operands' storage precisions. This feature has been implemented for the general matrix multiplication (`gemm`) operation, providing 128 different possible type combinations, which, when combined with existing transposition, conjugation, and storage parameters, enables 55,296 different `gemm` use cases. For more details, please see the documentation on [mixed datatype](docs/MixedDatatypes.md) support and/or our [ACM TOMS](https://toms.acm.org/) journal paper on mixed-domain/mixed-precision `gemm` ([linked below](#citations)). How to Download BLIS -------------------- There are a few ways to download BLIS. We list the most common four ways below. We **highly recommend** using either Option 1 or 2. Otherwise, we recommend Option 3 (over Option 4) so your compiler can perform optimizations specific to your hardware. 1. **Download a source repository with `git clone`.** Generally speaking, we prefer using `git clone` to clone a `git` repository. Having a repository allows the user to periodically pull in the latest changes and quickly rebuild BLIS whenever they wish. Also, implicit in cloning a repository is that the repository defaults to using the `master` branch, which contains the latest "stable" commits since the most recent release. (This is in contrast to Option 3 in which the user is opting for code that may be slightly out of date.) In order to clone a `git` repository of BLIS, please obtain a repository URL by clicking on the green button above the file/directory listing near the top of this page (as rendered by GitHub). Generally speaking, it will amount to executing the following command in your terminal shell: ``` git clone https://github.com/flame/blis.git ``` 2. **Download a source repository via a zip file.** If you are uncomfortable with using `git` but would still like the latest stable commits, we recommend that you download BLIS as a zip file. In order to download a zip file of the BLIS source distribution, please click on the green button above the file listing near the top of this page. This should reveal a link for downloading the zip file. 3. **Download a source release via a tarball/zip file.** Alternatively, if you would like to stick to the code that is included in official releases, you may download either a tarball or zip file of any of BLIS's previous [tagged releases](https://github.com/flame/blis/releases). We consider this option to be less than ideal for most people since it will likely mean you miss out on the latest bugfix or feature commits (in contrast to Options 1 or 2), and you also will not be able to update your code with a simple `git pull` command (in contrast to Option 1). 4. **Download a binary package specific to your OS.** While we don't recommend this as the first choice for most users, we provide links to community members who generously maintain BLIS packages for various Linux distributions such as Debian Unstable and EPEL/Fedora. Please see the [External Packages](#external-packages) section below for more information. Getting Started --------------- *NOTE: This section assumes you've either cloned a BLIS source code repository via `git`, downloaded the latest source code via a zip file, or downloaded the source code for a tagged version release---Options 1, 2, or 3, respectively, as discussed in [the previous section](#how-to-download-blis).* If you just want to build a sequential (not parallelized) version of BLIS in a hurry and come back and explore other topics later, you can configure and build BLIS as follows: ``` $ ./configure auto $ make [-j] ``` You can then verify your build by running BLAS- and BLIS-specific test drivers via `make check`: ``` $ make check [-j] ``` And if you would like to install BLIS to the directory specified to `configure` via the `--prefix` option, run the `install` target: ``` $ make install ``` Please read the output of `./configure --help` for a full list of configure-time options. If/when you have time, we *strongly* encourage you to read the detailed walkthrough of the build system found in our [Build System](docs/BuildSystem.md) guide. Example Code ------------ The BLIS source distribution provides example code in the `examples` directory. Example code focuses on using BLIS APIs (not BLAS or CBLAS), and resides in two subdirectories: [examples/oapi](examples/oapi) (which demonstrates the [object API](docs/BLISObjectAPI.md)) and [examples/tapi](examples/tapi) (which demonstrates the [typed API](docs/BLISTypedAPI.md)). Either directory contains several files, each containing various pieces of code that exercise core functionality of the BLIS API in question (object or typed). These example files should be thought of collectively like a tutorial, and therefore it is recommended to start from the beginning (the file that starts in `00`). You can build all of the examples by simply running `make` from either example subdirectory (`examples/oapi` or `examples/tapi`). (You can also run `make clean`.) The local `Makefile` assumes that you've already configured and built (but not necessarily installed) BLIS two directories up, in `../..`. If you have already installed BLIS to some permanent directory, you may refer to that installation by setting the environment variable `BLIS_INSTALL_PATH` prior to running make: ``` export BLIS_INSTALL_PATH=/usr/local; make ``` or by setting the same variable as part of the make command: ``` make BLIS_INSTALL_PATH=/usr/local ``` **Once the executable files have been built, we recommend reading the code and the corresponding executable output side by side. This will help you see the effects of each section of code.** This tutorial is not exhaustive or complete; several object API functions were omitted (mostly for brevity's sake) and thus more examples could be written. Documentation ------------- We provide extensive documentation on the BLIS build system, APIs, test infrastructure, and other important topics. All documentation is formatted in markdown and included in the BLIS source distribution (usually in the `docs` directory). Slightly longer descriptions of each document may be found via in the project's [wiki](https://github.com/flame/blis/wiki) section. **Documents for everyone:** * **[Build System](docs/BuildSystem.md).** This document covers the basics of configuring and building BLIS libraries, as well as related topics. * **[Testsuite](docs/Testsuite.md).** This document describes how to run BLIS's highly parameterized and configurable test suite, as well as the included BLAS test drivers. * **[BLIS Typed API Reference](docs/BLISTypedAPI.md).** Here we document the so-called "typed" (or BLAS-like) API. This is the API that many users who are already familiar with the BLAS will likely want to use. * **[BLIS Object API Reference](docs/BLISObjectAPI.md).** Here we document the object API. This is API abstracts away properties of vectors and matrices within `obj_t` structs that can be queried with accessor functions. Many developers and experts prefer this API over the typed API. * **[Hardware Support](docs/HardwareSupport.md).** This document maintains a table of supported microarchitectures. * **[Multithreading](docs/Multithreading.md).** This document describes how to use the multithreading features of BLIS. * **[Mixed-Datatypes](docs/MixedDatatypes.md).** This document provides an overview of BLIS's mixed-datatype functionality and provides a brief example of how to take advantage of this new code. * **[Performance](docs/Performance.md).** This document reports empirically measured performance of a representative set of level-3 operations on a variety of hardware architectures, as implemented within BLIS and other BLAS libraries for all four of the standard floating-point datatypes. * **[PerformanceSmall](docs/PerformanceSmall.md).** This document reports empirically measured performance of `gemm` on select hardware architectures within BLIS and other BLAS libraries when performing matrix problems where one or two dimensions is exceedingly small. * **[Release Notes](docs/ReleaseNotes.md).** This document tracks a summary of changes included with each new version of BLIS, along with contributor credits for key features. * **[Frequently Asked Questions](docs/FAQ.md).** If you have general questions about BLIS, please read this FAQ. If you can't find the answer to your question, please feel free to join the [blis-devel](https://groups.google.com/group/blis-devel) mailing list and post a question. We also have a [blis-discuss](https://groups.google.com/group/blis-discuss) mailing list that anyone can post to (even without joining). **Documents for github contributors:** * **[Contributing bug reports, feature requests, PRs, etc](CONTRIBUTING.md).** Interested in contributing to BLIS? Please read this document before getting started. It provides a general overview of how best to report bugs, propose new features, and offer code patches. * **[Coding Conventions](docs/CodingConventions.md).** If you are interested or planning on contributing code to BLIS, please read this document so that you can format your code in accordance with BLIS's standards. **Documents for BLIS developers:** * **[Kernels Guide](docs/KernelsHowTo.md).** If you would like to learn more about the types of kernels that BLIS exposes, their semantics, the operations that each kernel accelerates, and various implementation issues, please read this guide. * **[Configuration Guide](docs/ConfigurationHowTo.md).** If you would like to learn how to add new sub-configurations or configuration families, or are simply interested in learning how BLIS organizes its configurations and kernel sets, please read this thorough walkthrough of the configuration system. * **[Addon Guide](docs/Addons.md).** If you are interested in learning about using BLIS addons--that is, enabling existing (or creating new) bundles of operation or API code that are built into a BLIS library--please read this document. * **[Sandbox Guide](docs/Sandboxes.md).** If you are interested in learning about using sandboxes in BLIS--that is, providing alternative implementations of the `gemm` operation--please read this document. Performance ----------- We provide graphs that report performance of several implementations across a range of hardware types, multithreading configurations, problem sizes, operations, and datatypes. These pages also document most of the details needed to reproduce these experiments. * **[Performance](docs/Performance.md).** This document reports empirically measured performance of a representative set of level-3 operations on a variety of hardware architectures, as implemented within BLIS and other BLAS libraries for all four of the standard floating-point datatypes. * **[PerformanceSmall](docs/PerformanceSmall.md).** This document reports empirically measured performance of `gemm` on select hardware architectures within BLIS and other BLAS libraries when performing matrix problems where one or two dimensions is exceedingly small. External Packages ----------------- Generally speaking, we **highly recommend** building from source whenever possible using the latest `git` clone. (Tarballs of each [tagged release](https://github.com/flame/blis/releases) are also available, but we consider them to be less ideal since they are not as easy to upgrade as `git` clones.) That said, some users may prefer binary and/or source packages through their Linux distribution. Thanks to generous involvement/contributions from our community members, the following BLIS packages are now available: * **Debian**. [M. Zhou](https://github.com/cdluminate) has volunteered to sponsor and maintain BLIS packages within the Debian Linux distribution. The Debian package tracker can be found [here](https://tracker.debian.org/pkg/blis). (Also, thanks to [Nico Schlömer](https://github.com/nschloe) for previously volunteering his time to set up a standalone PPA.) * **Gentoo**. [M. Zhou](https://github.com/cdluminate) also maintains the [BLIS package](https://packages.gentoo.org/packages/sci-libs/blis) entry for [Gentoo](https://www.gentoo.org/), a Linux distribution known for its source-based [portage](https://wiki.gentoo.org/wiki/Portage) package manager and distribution system. * **EPEL/Fedora**. There are official BLIS packages in Fedora and EPEL (for RHEL7+ and compatible distributions) with versions for 64-bit integers, OpenMP, and pthreads, and shims which can be dynamically linked instead of reference BLAS. (NOTE: For architectures other than intel64, amd64, and maybe arm64, the performance of packaged BLIS will be low because it uses unoptimized generic kernels; for those architectures, [OpenBLAS](https://github.com/xianyi/OpenBLAS) may be a better solution.) [Dave Love](https://github.com/loveshack) provides additional packages for EPEL6 in a [Fedora Copr](https://copr.fedorainfracloud.org/coprs/loveshack/blis/), and possibly versions more recent than the official repo for other EPEL/Fedora releases. The source packages may build on other rpm-based distributions. * **OpenSuSE**. The copr referred to above has rpms for some OpenSuSE releases; the source rpms may build for others. * **GNU Guix**. Guix has BLIS packages, provides builds only for the generic target and some specific x86_64 micro-architectures. * **Conda**. conda channel [conda-forge](https://github.com/conda-forge/blis-feedstock) has Linux, OSX and Windows binary packages for x86_64. Discussion ---------- You can keep in touch with developers and other users of the project by joining one of the following mailing lists: * [blis-devel](https://groups.google.com/group/blis-devel): Please join and post to this mailing list if you are a BLIS developer, or if you are trying to use BLIS beyond simply linking to it as a BLAS library. **Note:** Most of the interesting discussions happen here; don't be afraid to join! If you would like to submit a bug report, or discuss a possible bug, please consider opening a [new issue](https://github.com/flame/blis/issues) on github. * [blis-discuss](https://groups.google.com/group/blis-discuss): Please join and post to this mailing list if you have general questions or feedback regarding BLIS. Application developers (end users) may wish to post here, unless they have bug reports, in which case they should open a [new issue](https://github.com/flame/blis/issues) on github. Contributing ------------ For information on how to contribute to our project, including preferred [coding conventions](docs/CodingConventions.md), please refer to the [CONTRIBUTING](CONTRIBUTING.md) file at the top-level of the BLIS source distribution. Citations --------- For those of you looking for the appropriate article to cite regarding BLIS, we recommend citing our [first ACM TOMS journal paper](https://dl.acm.org/doi/10.1145/2764454?cid=81314495332) ([unofficial backup link](https://www.cs.utexas.edu/users/flame/pubs/blis1_toms_rev3.pdf)): ``` @article{BLIS1, author = {Field G. {V}an~{Z}ee and Robert A. {v}an~{d}e~{G}eijn}, title = {{BLIS}: A Framework for Rapidly Instantiating {BLAS} Functionality}, journal = {ACM Transactions on Mathematical Software}, volume = {41}, number = {3}, pages = {14:1--14:33}, month = {June}, year = {2015}, issue_date = {June 2015}, url = {https://doi.acm.org/10.1145/2764454}, } ``` You may also cite the [second ACM TOMS journal paper](https://dl.acm.org/doi/10.1145/2755561?cid=81314495332) ([unofficial backup link](https://www.cs.utexas.edu/users/flame/pubs/blis2_toms_rev3.pdf)): ``` @article{BLIS2, author = {Field G. {V}an~{Z}ee and Tyler Smith and Francisco D. Igual and Mikhail Smelyanskiy and Xianyi Zhang and Michael Kistler and Vernon Austel and John Gunnels and Tze Meng Low and Bryan Marker and Lee Killough and Robert A. {v}an~{d}e~{G}eijn}, title = {The {BLIS} Framework: Experiments in Portability}, journal = {ACM Transactions on Mathematical Software}, volume = {42}, number = {2}, pages = {12:1--12:19}, month = {June}, year = {2016}, issue_date = {June 2016}, url = {https://doi.acm.org/10.1145/2755561}, } ``` We also have a third paper, submitted to IPDPS 2014, on achieving [multithreaded parallelism in BLIS](https://dl.acm.org/doi/10.1109/IPDPS.2014.110) ([unofficial backup link](https://www.cs.utexas.edu/users/flame/pubs/blis3_ipdps14.pdf)): ``` @inproceedings{BLIS3, author = {Tyler M. Smith and Robert A. {v}an~{d}e~{G}eijn and Mikhail Smelyanskiy and Jeff R. Hammond and Field G. {V}an~{Z}ee}, title = {Anatomy of High-Performance Many-Threaded Matrix Multiplication}, booktitle = {28th IEEE International Parallel \& Distributed Processing Symposium (IPDPS 2014)}, year = {2014}, url = {https://doi.org/10.1109/IPDPS.2014.110}, } ``` A fourth paper, submitted to ACM TOMS, also exists, which proposes an [analytical model](https://dl.acm.org/doi/10.1145/2925987) for determining blocksize parameters in BLIS ([unofficial backup link](https://www.cs.utexas.edu/users/flame/pubs/TOMS-BLIS-Analytical.pdf)): ``` @article{BLIS4, author = {Tze Meng Low and Francisco D. Igual and Tyler M. Smith and Enrique S. Quintana-Ort\'{\i}}, title = {Analytical Modeling Is Enough for High-Performance {BLIS}}, journal = {ACM Transactions on Mathematical Software}, volume = {43}, number = {2}, pages = {12:1--12:18}, month = {August}, year = {2016}, issue_date = {August 2016}, url = {https://doi.acm.org/10.1145/2925987}, } ``` A fifth paper, submitted to ACM TOMS, begins the study of so-called [induced methods for complex matrix multiplication](https://dl.acm.org/doi/10.1145/3086466?cid=81314495332) ([unofficial backup link](https://www.cs.utexas.edu/users/flame/pubs/blis5_toms_rev2.pdf)): ``` @article{BLIS5, author = {Field G. {V}an~{Z}ee and Tyler Smith}, title = {Implementing High-performance Complex Matrix Multiplication via the 3m and 4m Methods}, journal = {ACM Transactions on Mathematical Software}, volume = {44}, number = {1}, pages = {7:1--7:36}, month = {July}, year = {2017}, issue_date = {July 2017}, url = {https://doi.acm.org/10.1145/3086466}, } ``` A sixth paper, submitted to ACM TOMS, revisits the topic of the previous article and derives a [superior induced method](https://epubs.siam.org/doi/10.1137/19M1282040) ([unofficial backup link](https://www.cs.utexas.edu/users/flame/pubs/blis6_sisc_rev3.pdf)): ``` @article{BLIS6, author = {Field G. {V}an~{Z}ee}, title = {Implementing High-Performance Complex Matrix Multiplication via the 1m Method}, journal = {SIAM Journal on Scientific Computing}, volume = {42}, number = {5}, pages = {C221--C244}, month = {September} year = {2020}, issue_date = {September 2020}, url = {https://doi.org/10.1137/19M1282040} } ``` A seventh paper, submitted to ACM TOMS, explores the implementation of `gemm` for [mixed-domain and/or mixed-precision](https://dl.acm.org/doi/10.1145/3402225?cid=81314495332) operands ([unofficial backup link](https://www.cs.utexas.edu/users/flame/pubs/blis7_toms_rev0.pdf)): ``` @article{BLIS7, author = {Field G. {V}an~{Z}ee and Devangi N. Parikh and Robert A. van~de~{G}eijn}, title = {Supporting Mixed-domain Mixed-precision Matrix Multiplication within the BLIS Framework}, journal = {ACM Transactions on Mathematical Software}, volume = {47}, number = {2}, pages = {12:1--12:26}, month = {April}, year = {2021}, issue_date = {April 2021}, url = {https://doi.org/10.1145/3402225}, } ``` Funding ------- This project and its associated research were partially sponsored by grants from [Microsoft](https://www.microsoft.com/), [Intel](https://www.intel.com/), [Texas Instruments](https://www.ti.com/), [AMD](https://www.amd.com/), [HPE](https://www.hpe.com/), [Oracle](https://www.oracle.com/), [Huawei](https://www.huawei.com/), [Facebook](https://www.facebook.com/), and [ARM](https://www.arm.com/), as well as grants from the [National Science Foundation](https://www.nsf.gov/) (Awards CCF-0917167, ACI-1148125/1340293, CCF-1320112, and ACI-1550493). _Any opinions, findings and conclusions or recommendations expressed in this material are those of the author(s) and do not necessarily reflect the views of the National Science Foundation (NSF)._ blis-0.9.0/RELEASING000066400000000000000000000023751422157504600137220ustar00rootroot00000000000000Here are the steps to follow to create a new release (version) of BLIS: 1. Make sure there are no commits that have yet to be pulled into local repository. $ git pull If there are any commits upstream, merge them as appropriate. 2. Verify that the code builds properly. $ ./configure auto; make 3. Verify that the code passes BLIS and BLAS tests: $ make check # BLIS testsuite (fast) + BLAS test drivers $ make checkblis # BLIS testsuite (full ex. mixed-datatype) $ make checkblis-md # BLIS testsuite (mixed-datatype only) $ make checkblis-salt # BLIS testsuite (fast + salt) 4. Draft a new announcement to blis-devel, crediting those who contributed towards this version by browsing 'git log'. 5. Update CREDITS file if 'git log' reveals any new contributors. 6. Update docs/ReleaseNotes.md file with body of finalized announcement and the date of the release. 7. Commit changes from steps 5 and 6. 8. Bump the version number: $ ./build/bump-version.sh "0.3.2" This will result in two new commits: a version file update and a CHANGELOG file update. 9. Push the new commits and new tag associated with the new version: $ git push $ git push --tag 10. Send finalized announcement to blis-devel. blis-0.9.0/addon/000077500000000000000000000000001422157504600135445ustar00rootroot00000000000000blis-0.9.0/addon/gemmd/000077500000000000000000000000001422157504600146355ustar00rootroot00000000000000blis-0.9.0/addon/gemmd/attic/000077500000000000000000000000001422157504600157415ustar00rootroot00000000000000blis-0.9.0/addon/gemmd/attic/bao_gemmd_bp_var2.c000066400000000000000000000475521422157504600214470ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2021, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define FUNCPTR_T gemmd_fp typedef void (*FUNCPTR_T) ( conj_t conja, conj_t conjb, dim_t m, dim_t n, dim_t k, void* restrict alpha, void* restrict a, inc_t rs_a, inc_t cs_a, void* restrict d, inc_t incd, void* restrict b, inc_t rs_b, inc_t cs_b, void* restrict beta, void* restrict c, inc_t rs_c, inc_t cs_c, cntx_t* restrict cntx, rntm_t* restrict rntm, thrinfo_t* restrict thread ); // // -- gemmd-like block-panel algorithm (object interface) ---------------------- // // Define a function pointer array named ftypes and initialize its contents with // the addresses of the typed functions defined below, bao_?gemmd_bp_var2(). static FUNCPTR_T GENARRAY_PREF(ftypes,bao_,gemmd_bp_var2); void bao_gemmd_bp_var2 ( obj_t* alpha, obj_t* a, obj_t* d, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, rntm_t* rntm, thrinfo_t* thread ) { const num_t dt = bli_obj_dt( c ); const conj_t conja = bli_obj_conj_status( a ); const conj_t conjb = bli_obj_conj_status( b ); const dim_t m = bli_obj_length( c ); const dim_t n = bli_obj_width( c ); const dim_t k = bli_obj_width( a ); void* restrict buf_a = bli_obj_buffer_at_off( a ); const inc_t rs_a = bli_obj_row_stride( a ); const inc_t cs_a = bli_obj_col_stride( a ); void* restrict buf_d = bli_obj_buffer_at_off( d ); const inc_t incd = bli_obj_vector_inc( d ); void* restrict buf_b = bli_obj_buffer_at_off( b ); const inc_t rs_b = bli_obj_row_stride( b ); const inc_t cs_b = bli_obj_col_stride( b ); void* restrict buf_c = bli_obj_buffer_at_off( c ); const inc_t rs_c = bli_obj_row_stride( c ); const inc_t cs_c = bli_obj_col_stride( c ); void* restrict buf_alpha = bli_obj_buffer_for_1x1( dt, alpha ); void* restrict buf_beta = bli_obj_buffer_for_1x1( dt, beta ); // Index into the function pointer array to extract the correct // typed function pointer based on the chosen datatype. FUNCPTR_T f = ftypes[dt]; // Invoke the function. f ( conja, conjb, m, n, k, buf_alpha, buf_a, rs_a, cs_a, buf_d, incd, buf_b, rs_b, cs_b, buf_beta, buf_c, rs_c, cs_c, cntx, rntm, thread ); } // // -- gemmd-like block-panel algorithm (typed interface) ----------------------- // #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTECH2(bao_,ch,varname) \ ( \ conj_t conja, \ conj_t conjb, \ dim_t m, \ dim_t n, \ dim_t k, \ void* restrict alpha, \ void* restrict a, inc_t rs_a, inc_t cs_a, \ void* restrict d, inc_t incd, \ void* restrict b, inc_t rs_b, inc_t cs_b, \ void* restrict beta, \ void* restrict c, inc_t rs_c, inc_t cs_c, \ cntx_t* restrict cntx, \ rntm_t* restrict rntm, \ thrinfo_t* restrict thread \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ /* Query the context for various blocksizes. */ \ const dim_t NR = bli_cntx_get_blksz_def_dt( dt, BLIS_NR, cntx ); \ const dim_t MR = bli_cntx_get_blksz_def_dt( dt, BLIS_MR, cntx ); \ const dim_t NC = bli_cntx_get_blksz_def_dt( dt, BLIS_NC, cntx ); \ const dim_t MC = bli_cntx_get_blksz_def_dt( dt, BLIS_MC, cntx ); \ const dim_t KC = bli_cntx_get_blksz_def_dt( dt, BLIS_KC, cntx ); \ \ /* Query the context for the microkernel address and cast it to its function pointer type. */ \ /* PASTECH(ch,gemm_ukr_ft) \ gemm_ukr = bli_cntx_get_l3_nat_ukr_dt( dt, BLIS_GEMM_UKR, cntx ); \ */ \ \ /* Temporary C buffer for edge cases. Note that the strides of this temporary buffer are set so that they match the storage of the original C matrix. For example, if C is column-stored, ct will be column-stored as well. */ \ /* ctype ct[ BLIS_STACK_BUF_MAX_SIZE \ / sizeof( ctype ) ] \ __attribute__((aligned(BLIS_STACK_BUF_ALIGN_SIZE))); \ const bool col_pref = bli_cntx_l3_nat_ukr_prefers_cols_dt( dt, BLIS_GEMM_UKR, cntx ); \ const inc_t rs_ct = ( col_pref ? 1 : NR ); \ const inc_t cs_ct = ( col_pref ? MR : 1 ); \ */ \ \ /* Compute partitioning step values for each matrix of each loop. */ \ const inc_t jcstep_c = cs_c; \ const inc_t jcstep_b = cs_b; \ \ const inc_t pcstep_a = cs_a; \ const inc_t pcstep_d = incd; \ const inc_t pcstep_b = rs_b; \ \ const inc_t icstep_c = rs_c; \ const inc_t icstep_a = rs_a; \ \ const inc_t jrstep_c = cs_c * NR; \ \ const inc_t irstep_c = rs_c * MR; \ \ ctype* restrict a_00 = a; \ ctype* restrict d_00 = d; \ ctype* restrict b_00 = b; \ ctype* restrict c_00 = c; \ ctype* restrict alpha_cast = alpha; \ ctype* restrict beta_cast = beta; \ \ /* Make local copies of the scalars to prevent any unnecessary sharing of cache lines between the cores' caches. */ \ ctype alpha_local = *alpha_cast; \ ctype beta_local = *beta_cast; \ ctype one_local = *PASTEMAC(ch,1); \ /*ctype zero_local = *PASTEMAC(ch,0);*/ \ \ auxinfo_t aux; \ \ /* Initialize a mem_t entry for A and B. Strictly speaking, this is only needed for the matrix we will be packing (if any), but we do it unconditionally to be safe. */ \ mem_t mem_a = BLIS_MEM_INITIALIZER; \ mem_t mem_b = BLIS_MEM_INITIALIZER; \ \ /* Define an array of bszid_t ids, which will act as our substitute for the cntl_t tree. */ \ bszid_t bszids[8] = { BLIS_NC, /* 5th loop */ \ BLIS_KC, /* 4th loop */ \ BLIS_NO_PART, /* pack B */ \ BLIS_MC, /* 3rd loop */ \ BLIS_NO_PART, /* pack A */ \ BLIS_NR, /* 2nd loop */ \ BLIS_MR, /* 1st loop */ \ BLIS_KR }; /* microkernel loop */ \ \ bszid_t* restrict bszids_jc = &bszids[0]; \ bszid_t* restrict bszids_pc = &bszids[1]; \ /*bszid_t* restrict bszids_pb = &bszids[2];*/ \ bszid_t* restrict bszids_ic = &bszids[3]; \ /*bszid_t* restrict bszids_pa = &bszids[4];*/ \ bszid_t* restrict bszids_jr = &bszids[5]; \ /*bszid_t* restrict bszids_ir = &bszids[6];*/ \ \ thrinfo_t* restrict thread_jc = NULL; \ thrinfo_t* restrict thread_pc = NULL; \ thrinfo_t* restrict thread_pb = NULL; \ thrinfo_t* restrict thread_ic = NULL; \ thrinfo_t* restrict thread_pa = NULL; \ thrinfo_t* restrict thread_jr = NULL; \ thrinfo_t* restrict thread_ir = NULL; \ \ /* Identify the current thrinfo_t node and then grow the tree. */ \ thread_jc = thread; \ bli_thrinfo_sup_grow( rntm, bszids_jc, thread_jc ); \ \ /* Compute the JC loop thread range for the current thread. */ \ dim_t jc_start, jc_end; \ bli_thread_range_sub( thread_jc, n, NR, FALSE, &jc_start, &jc_end ); \ const dim_t n_local = jc_end - jc_start; \ \ /* Compute number of primary and leftover components of the JC loop. */ \ /*const dim_t jc_iter = ( n_local + NC - 1 ) / NC;*/ \ const dim_t jc_left = n_local % NC; \ \ /* Loop over the n dimension (NC rows/columns at a time). */ \ for ( dim_t jj = jc_start; jj < jc_end; jj += NC ) \ { \ /* Calculate the thread's current JC block dimension. */ \ const dim_t nc_cur = ( NC <= jc_end - jj ? NC : jc_left ); \ \ ctype* restrict b_jc = b_00 + jj * jcstep_b; \ ctype* restrict c_jc = c_00 + jj * jcstep_c; \ \ /* Identify the current thrinfo_t node and then grow the tree. */ \ thread_pc = bli_thrinfo_sub_node( thread_jc ); \ bli_thrinfo_sup_grow( rntm, bszids_pc, thread_pc ); \ \ /* Compute the PC loop thread range for the current thread. */ \ const dim_t pc_start = 0, pc_end = k; \ const dim_t k_local = k; \ \ /* Compute number of primary and leftover components of the PC loop. */ \ /*const dim_t pc_iter = ( k_local + KC - 1 ) / KC;*/ \ const dim_t pc_left = k_local % KC; \ \ /* Loop over the k dimension (KC rows/columns at a time). */ \ for ( dim_t pp = pc_start; pp < pc_end; pp += KC ) \ { \ /* Calculate the thread's current PC block dimension. */ \ const dim_t kc_cur = ( KC <= pc_end - pp ? KC : pc_left ); \ \ ctype* restrict a_pc = a_00 + pp * pcstep_a; \ ctype* restrict d_pc = d_00 + pp * pcstep_d; \ ctype* restrict b_pc = b_jc + pp * pcstep_b; \ \ /* Only apply beta to the first iteration of the pc loop. */ \ ctype* restrict beta_use = ( pp == 0 ? &beta_local : &one_local ); \ \ ctype* b_use; \ inc_t rs_b_use, cs_b_use, ps_b_use; \ \ /* Identify the current thrinfo_t node. Note that the thrinfo_t node will have already been created by a previous call to bli_thrinfo_sup_grow() since bszid_t values of BLIS_NO_PART cause the tree to grow by two (e.g. to the next bszid that is a normal bszid_t value). */ \ thread_pb = bli_thrinfo_sub_node( thread_pc ); \ /*bli_thrinfo_sup_grow( rntm, bszids_pb, thread_pb );*/ \ \ /* Determine the packing buffer and related parameters for matrix B. Then call the packm implementation. */ \ PASTECH2(bao_,ch,packm_b) \ ( \ conjb, \ KC, NC, \ kc_cur, nc_cur, NR, \ &one_local, \ d_pc, incd, \ b_pc, rs_b, cs_b, \ &b_use, &rs_b_use, &cs_b_use, \ &ps_b_use, \ cntx, \ rntm, \ &mem_b, \ thread_pb \ ); \ \ /* Alias b_use so that it's clear this is our current block of matrix B. */ \ ctype* restrict b_pc_use = b_use; \ \ /* Identify the current thrinfo_t node and then grow the tree. */ \ thread_ic = bli_thrinfo_sub_node( thread_pb ); \ bli_thrinfo_sup_grow( rntm, bszids_ic, thread_ic ); \ \ /* Compute the IC loop thread range for the current thread. */ \ dim_t ic_start, ic_end; \ bli_thread_range_sub( thread_ic, m, MR, FALSE, &ic_start, &ic_end ); \ const dim_t m_local = ic_end - ic_start; \ \ /* Compute number of primary and leftover components of the IC loop. */ \ /*const dim_t ic_iter = ( m_local + MC - 1 ) / MC;*/ \ const dim_t ic_left = m_local % MC; \ \ /* Loop over the m dimension (MC rows at a time). */ \ for ( dim_t ii = ic_start; ii < ic_end; ii += MC ) \ { \ /* Calculate the thread's current IC block dimension. */ \ const dim_t mc_cur = ( MC <= ic_end - ii ? MC : ic_left ); \ \ ctype* restrict a_ic = a_pc + ii * icstep_a; \ ctype* restrict c_ic = c_jc + ii * icstep_c; \ \ ctype* a_use; \ inc_t rs_a_use, cs_a_use, ps_a_use; \ \ /* Identify the current thrinfo_t node. Note that the thrinfo_t node will have already been created by a previous call to bli_thrinfo_sup_grow() since bszid_t values of BLIS_NO_PART cause the tree to grow by two (e.g. to the next bszid that is a normal bszid_t value). */ \ thread_pa = bli_thrinfo_sub_node( thread_ic ); \ /*bli_thrinfo_sup_grow( rntm, bszids_pa, thread_pa );*/ \ \ /* Determine the packing buffer and related parameters for matrix A. Then call the packm implementation. */ \ PASTECH2(bao_,ch,packm_a) \ ( \ conja, \ MC, KC, \ mc_cur, kc_cur, MR, \ &one_local, \ d_pc, incd, \ a_ic, rs_a, cs_a, \ &a_use, &rs_a_use, &cs_a_use, \ &ps_a_use, \ cntx, \ rntm, \ &mem_a, \ thread_pa \ ); \ \ /* Alias a_use so that it's clear this is our current block of matrix A. */ \ ctype* restrict a_ic_use = a_use; \ \ /* Identify the current thrinfo_t node and then grow the tree. */ \ thread_jr = bli_thrinfo_sub_node( thread_pa ); \ bli_thrinfo_sup_grow( rntm, bszids_jr, thread_jr ); \ \ /* Query the number of threads and thread ids for the JR loop. NOTE: These values are only needed when computing the next micropanel of B. */ \ const dim_t jr_nt = bli_thread_n_way( thread_jr ); \ const dim_t jr_tid = bli_thread_work_id( thread_jr ); \ \ /* Compute number of primary and leftover components of the JR loop. */ \ dim_t jr_iter = ( nc_cur + NR - 1 ) / NR; \ dim_t jr_left = nc_cur % NR; \ \ /* Compute the JR loop thread range for the current thread. */ \ dim_t jr_start, jr_end; \ bli_thread_range_sub( thread_jr, jr_iter, 1, FALSE, &jr_start, &jr_end ); \ \ /* Loop over the n dimension (NR columns at a time). */ \ for ( dim_t j = jr_start; j < jr_end; j += 1 ) \ { \ const dim_t nr_cur \ = ( bli_is_not_edge_f( j, jr_iter, jr_left ) ? NR : jr_left ); \ \ ctype* restrict b_jr = b_pc_use + j * ps_b_use; \ ctype* restrict c_jr = c_ic + j * jrstep_c; \ \ /* Assume for now that our next panel of B to be the current panel of B. */ \ ctype* restrict b2 = b_jr; \ \ /* Identify the current thrinfo_t node. */ \ thread_ir = bli_thrinfo_sub_node( thread_jr ); \ \ /* Query the number of threads and thread ids for the IR loop. NOTE: These values are only needed when computing the next micropanel of A. */ \ const dim_t ir_nt = bli_thread_n_way( thread_ir ); \ const dim_t ir_tid = bli_thread_work_id( thread_ir ); \ \ /* Compute number of primary and leftover components of the IR loop. */ \ dim_t ir_iter = ( mc_cur + MR - 1 ) / MR; \ dim_t ir_left = mc_cur % MR; \ \ /* Compute the IR loop thread range for the current thread. */ \ dim_t ir_start, ir_end; \ bli_thread_range_sub( thread_ir, ir_iter, 1, FALSE, &ir_start, &ir_end ); \ \ /* Loop over the m dimension (MR rows at a time). */ \ for ( dim_t i = ir_start; i < ir_end; i += 1 ) \ { \ const dim_t mr_cur \ = ( bli_is_not_edge_f( i, ir_iter, ir_left ) ? MR : ir_left ); \ \ ctype* restrict a_ir = a_ic_use + i * ps_a_use; \ ctype* restrict c_ir = c_jr + i * irstep_c; \ \ ctype* restrict a2; \ \ /* Compute the addresses of the next micropanels of A and B. */ \ a2 = bli_gemm_get_next_a_upanel( a_ir, ps_a_use, 1 ); \ if ( bli_is_last_iter( i, ir_end, ir_tid, ir_nt ) ) \ { \ a2 = a_ic_use; \ b2 = bli_gemm_get_next_b_upanel( b_jr, ps_b_use, 1 ); \ if ( bli_is_last_iter( j, jr_end, jr_tid, jr_nt ) ) \ b2 = b_pc_use; \ } \ \ /* Save the addresses of next micropanels of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_next_a( a2, &aux ); \ bli_auxinfo_set_next_b( b2, &aux ); \ \ /* Call a wrapper to the kernel (which handles edge cases). */ \ PASTECH2(bao_,ch,gemm_kernel) \ ( \ MR, \ NR, \ mr_cur, \ nr_cur, \ kc_cur, \ &alpha_local, \ a_ir, rs_a_use, cs_a_use, \ b_jr, rs_b_use, cs_b_use, \ beta_use, \ c_ir, rs_c, cs_c, \ &aux, \ cntx \ ); \ } \ } \ } \ \ /* This barrier is needed to prevent threads from starting to pack the next row panel of B before the current row panel is fully computed upon. */ \ bli_thread_barrier( thread_pb ); \ } \ } \ \ /* Release any memory that was acquired for packing matrices A and B. */ \ PASTECH2(bao_,ch,packm_finalize_mem_a) \ ( \ rntm, \ &mem_a, \ thread_pa \ ); \ PASTECH2(bao_,ch,packm_finalize_mem_b) \ ( \ rntm, \ &mem_b, \ thread_pb \ ); \ \ /* PASTEMAC(ch,fprintm)( stdout, "gemmd_bp_var2: a1_packed", mr_cur, kc_cur, a_ir, rs_a_use, cs_a_use, "%5.2f", "" ); \ PASTEMAC(ch,fprintm)( stdout, "gemmd_bp_var2: b1_packed", kc_cur, nr_cur, b_jr, rs_b_use, cs_b_use, "%5.2f", "" ); \ PASTEMAC(ch,fprintm)( stdout, "gemmd_bp_var2: c ", mr_cur, nr_cur, c_ir, rs_c, cs_c, "%5.2f", "" ); \ */ \ } //INSERT_GENTFUNC_BASIC0( gemmd_bp_var2 ) GENTFUNC( float, s, gemmd_bp_var2 ) GENTFUNC( double, d, gemmd_bp_var2 ) GENTFUNC( scomplex, c, gemmd_bp_var2 ) GENTFUNC( dcomplex, z, gemmd_bp_var2 ) // // -- gemm-like microkernel wrapper -------------------------------------------- // #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTECH2(bao_,ch,varname) \ ( \ const dim_t MR, \ const dim_t NR, \ dim_t mr_cur, \ dim_t nr_cur, \ dim_t kc_cur, \ ctype* restrict alpha, \ ctype* restrict a, inc_t rs_a, inc_t cs_a, \ ctype* restrict b, inc_t rs_b, inc_t cs_b, \ ctype* restrict beta, \ ctype* restrict c, inc_t rs_c, inc_t cs_c, \ auxinfo_t* restrict aux, \ cntx_t* restrict cntx \ ) \ { \ /* Infer the datatype from the ctype. */ \ const num_t dt = PASTEMAC(ch,type); \ \ /* Query the context for the microkernel address and cast it to its function pointer type. */ \ PASTECH(ch,gemm_ukr_ft) \ gemm_ukr = bli_cntx_get_l3_nat_ukr_dt( dt, BLIS_GEMM_UKR, cntx ); \ \ /* Temporary C buffer for edge cases. Note that the strides of this temporary buffer are set so that they match the storage of the original C matrix. For example, if C is column-stored, ct will be column-stored as well. */ \ ctype ct[ BLIS_STACK_BUF_MAX_SIZE \ / sizeof( ctype ) ] \ __attribute__((aligned(BLIS_STACK_BUF_ALIGN_SIZE))); \ const bool col_pref = bli_cntx_l3_nat_ukr_prefers_cols_dt( dt, BLIS_GEMM_UKR, cntx ); \ const inc_t rs_ct = ( col_pref ? 1 : NR ); \ const inc_t cs_ct = ( col_pref ? MR : 1 ); \ \ ctype zero = *PASTEMAC(ch,0); \ \ /* Handle interior and edge cases separately. */ \ if ( mr_cur == MR && nr_cur == NR ) \ { \ /* Invoke the gemm microkernel. */ \ gemm_ukr \ ( \ kc_cur, \ alpha, \ a, \ b, \ beta, \ c, rs_c, cs_c, \ aux, \ cntx \ ); \ } \ else \ { \ /* Invoke the gemm microkernel. */ \ gemm_ukr \ ( \ kc_cur, \ alpha, \ a, \ b, \ &zero, \ ct, rs_ct, cs_ct, \ aux, \ cntx \ ); \ \ /* Scale the bottom edge of C and add the result from above. */ \ PASTEMAC(ch,xpbys_mxn) \ ( \ mr_cur, \ nr_cur, \ ct, rs_ct, cs_ct, \ beta, \ c, rs_c, cs_c \ ); \ } \ } //INSERT_GENTFUNC_BASIC0( gemm_kernel ) GENTFUNC( float, s, gemm_kernel ) GENTFUNC( double, d, gemm_kernel ) GENTFUNC( scomplex, c, gemm_kernel ) GENTFUNC( dcomplex, z, gemm_kernel ) blis-0.9.0/addon/gemmd/attic/bli_gemm_ex.c000066400000000000000000000057271422157504600203670ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_gemm_ex ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, rntm_t* rntm ) { bli_init_once(); // A switch to easily toggle whether we use the addon implementation // of bao_gemmd() as the implementation for bli_gemm(). (This allows for // easy testing of bao_gemmd() via the testsuite.) if ( 1 ) { const dim_t k = bli_obj_width_after_trans( a ); const num_t dt = bli_obj_dt( c ); obj_t d; bli_obj_create( dt, k, 1, 1, k, &d ); bli_setv( &BLIS_ONE, &d ); //bli_randv( &d ); bao_gemmd_ex( alpha, a, &d, b, beta, c, cntx, rntm ); bli_obj_free( &d ); return; } // Initialize a local runtime with global settings if necessary. Note // that in the case that a runtime is passed in, we make a local copy. rntm_t rntm_l; if ( rntm == NULL ) { bli_rntm_init_from_global( &rntm_l ); rntm = &rntm_l; } else { rntm_l = *rntm; rntm = &rntm_l; } // Obtain a valid (native) context from the gks if necessary. if ( cntx == NULL ) cntx = bli_gks_query_cntx(); // Check the operands. if ( bli_error_checking_is_enabled() ) bli_gemm_check( alpha, a, b, beta, c, cntx ); // Invoke the operation's front end. bli_gemm_front ( alpha, a, b, beta, c, cntx, rntm, NULL ); } blis-0.9.0/addon/gemmd/bao_gemmd.c000066400000000000000000000175761422157504600167330ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2021, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // -- Define the gemmd operation's object API ---------------------------------- // void bao_gemmd ( obj_t* alpha, obj_t* a, obj_t* d, obj_t* b, obj_t* beta, obj_t* c ) { bao_gemmd_ex ( alpha, a, d, b, beta, c, NULL, NULL ); } void bao_gemmd_ex ( obj_t* alpha, obj_t* a, obj_t* d, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, rntm_t* rntm ) { bli_init_once(); // Initialize a local runtime with global settings if necessary. Note // that in the case that a runtime is passed in, we make a local copy. rntm_t rntm_l; if ( rntm == NULL ) { bli_rntm_init_from_global( &rntm_l ); rntm = &rntm_l; } else { rntm_l = *rntm; rntm = &rntm_l; } // Obtain a valid (native) context from the gks if necessary. // NOTE: This must be done before calling the _check() function, since // that function assumes the context pointer is valid. if ( cntx == NULL ) cntx = bli_gks_query_cntx(); // Check parameters. if ( bli_error_checking_is_enabled() ) bao_gemmd_check( alpha, a, d, b, beta, c, cntx ); // -- bli_gemmd_front() ---------------------------------------------------- obj_t a_local; obj_t b_local; obj_t c_local; // If C has a zero dimension, return early. if ( bli_obj_has_zero_dim( c ) ) { return; } // If alpha is zero, or if A or B has a zero dimension, scale C by beta // and return early. if ( bli_obj_equals( alpha, &BLIS_ZERO ) || bli_obj_has_zero_dim( a ) || bli_obj_has_zero_dim( b ) ) { bli_scalm( beta, c ); return; } // Alias A, B, and C in case we need to apply transformations. bli_obj_alias_to( a, &a_local ); bli_obj_alias_to( b, &b_local ); bli_obj_alias_to( c, &c_local ); // Induce a transposition of A if it has its transposition property set. // Then clear the transposition bit in the object. if ( bli_obj_has_trans( &a_local ) ) { bli_obj_induce_trans( &a_local ); bli_obj_set_onlytrans( BLIS_NO_TRANSPOSE, &a_local ); } // Induce a transposition of B if it has its transposition property set. // Then clear the transposition bit in the object. if ( bli_obj_has_trans( &b_local ) ) { bli_obj_induce_trans( &b_local ); bli_obj_set_onlytrans( BLIS_NO_TRANSPOSE, &b_local ); } // An optimization: If C is stored by rows and the micro-kernel prefers // contiguous columns, or if C is stored by columns and the micro-kernel // prefers contiguous rows, transpose the entire operation to allow the // micro-kernel to access elements of C in its preferred manner. if ( bli_cntx_l3_vir_ukr_dislikes_storage_of( &c_local, BLIS_GEMM_UKR, cntx ) ) { bli_obj_swap( &a_local, &b_local ); bli_obj_induce_trans( &a_local ); bli_obj_induce_trans( &b_local ); bli_obj_induce_trans( &c_local ); } // Parse and interpret the contents of the rntm_t object to properly // set the ways of parallelism for each loop, and then make any // additional modifications necessary for the current operation. bli_rntm_set_ways_for_op ( BLIS_GEMM, BLIS_LEFT, // ignored for gemm/hemm/symm bli_obj_length( &c_local ), bli_obj_width( &c_local ), bli_obj_width( &a_local ), rntm ); // Spawn threads (if applicable), where bao_gemmd_int() is the thread entry // point function for each thread. This also begins the process of creating // the thrinfo_t tree, which contains thread communicators. bao_l3_thread_decorator ( bao_gemmd_int, BLIS_GEMM, // operation family id alpha, &a_local, d, &b_local, beta, &c_local, cntx, rntm ); } // // -- Define the gemmd operation's thread entry point -------------------------- // void bao_gemmd_int ( obj_t* alpha, obj_t* a, obj_t* d, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, rntm_t* rntm, thrinfo_t* thread ) { // In this function, we choose the gemmd implementation that is executed // on each thread. // Call the block-panel algorithm. bao_gemmd_bp_var1 ( alpha, a, d, b, beta, c, cntx, rntm, thread ); } // // -- Define the gemmd operation's typed API ----------------------------------- // #undef GENTFUNC #define GENTFUNC( ctype, ch, opname ) \ \ void PASTECH2(bao_,ch,opname) \ ( \ trans_t transa, \ trans_t transb, \ dim_t m, \ dim_t n, \ dim_t k, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* d, inc_t incd, \ ctype* b, inc_t rs_b, inc_t cs_b, \ ctype* beta, \ ctype* c, inc_t rs_c, inc_t cs_c \ ) \ { \ bli_init_once(); \ \ /* Determine the datatype (e.g. BLIS_FLOAT, BLIS_DOUBLE, etc.) based on the macro parameter 'ch' (e.g. s, d, etc). */ \ const num_t dt = PASTEMAC(ch,type); \ \ obj_t alphao, ao, dd, bo, betao, co; \ \ dim_t m_a, n_a; \ dim_t m_b, n_b; \ \ /* Adjust the dimensions of matrices A and B according to the transa and transb parameters. */ \ bli_set_dims_with_trans( transa, m, k, &m_a, &n_a ); \ bli_set_dims_with_trans( transb, k, n, &m_b, &n_b ); \ \ /* Create bufferless scalar objects and attach the provided scalar pointers to those scalar objects. */ \ bli_obj_create_1x1_with_attached_buffer( dt, alpha, &alphao ); \ bli_obj_create_1x1_with_attached_buffer( dt, beta, &betao ); \ \ /* Create bufferless matrix objects and attach the provided matrix pointers to those matrix objects. */ \ bli_obj_create_with_attached_buffer( dt, m_a, n_a, a, rs_a, cs_a, &ao ); \ bli_obj_create_with_attached_buffer( dt, k, 1, d, incd, k, &dd ); \ bli_obj_create_with_attached_buffer( dt, m_b, n_b, b, rs_b, cs_b, &bo ); \ bli_obj_create_with_attached_buffer( dt, m, n, c, rs_c, cs_c, &co ); \ \ /* Set the transposition/conjugation properties of the objects for matrices A and B. */ \ bli_obj_set_conjtrans( transa, &ao ); \ bli_obj_set_conjtrans( transb, &bo ); \ \ /* Call the object interface. */ \ PASTECH(bao_,opname) \ ( \ &alphao, \ &ao, \ &dd, \ &bo, \ &betao, \ &co \ ); \ } //INSERT_GENTFUNC_BASIC0( gemmd ) GENTFUNC( float, s, gemmd ) GENTFUNC( double, d, gemmd ) GENTFUNC( scomplex, c, gemmd ) GENTFUNC( dcomplex, z, gemmd ) blis-0.9.0/addon/gemmd/bao_gemmd.h000066400000000000000000000060741422157504600167270ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2021, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // -- Prototype the gemmd operation's object API ------------------------------- // BLIS_EXPORT_ADDON void bao_gemmd ( obj_t* alpha, obj_t* a, obj_t* d, obj_t* b, obj_t* beta, obj_t* c ); BLIS_EXPORT_ADDON void bao_gemmd_ex ( obj_t* alpha, obj_t* a, obj_t* d, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, rntm_t* rntm ); // // -- Prototype the gemmd operation's thread entry point ----------------------- // void bao_gemmd_int ( obj_t* alpha, obj_t* a, obj_t* d, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, rntm_t* rntm, thrinfo_t* thread ); // // -- Prototype the gemmd operation's typed API -------------------------------- // #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ BLIS_EXPORT_ADDON void PASTECH2(bao_,ch,opname) \ ( \ trans_t transa, \ trans_t transb, \ dim_t m, \ dim_t n, \ dim_t k, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* d, inc_t incd, \ ctype* b, inc_t rs_b, inc_t cs_b, \ ctype* beta, \ ctype* c, inc_t rs_c, inc_t cs_c \ ); //INSERT_GENTPROT_BASIC0( gemmd ) GENTPROT( float, s, gemmd ) GENTPROT( double, d, gemmd ) GENTPROT( scomplex, c, gemmd ) GENTPROT( dcomplex, z, gemmd ) blis-0.9.0/addon/gemmd/bao_gemmd_bp_var1.c000066400000000000000000000413201422157504600203250ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2021, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define FUNCPTR_T gemmd_fp typedef void (*FUNCPTR_T) ( conj_t conja, conj_t conjb, dim_t m, dim_t n, dim_t k, void* restrict alpha, void* restrict a, inc_t rs_a, inc_t cs_a, void* restrict d, inc_t incd, void* restrict b, inc_t rs_b, inc_t cs_b, void* restrict beta, void* restrict c, inc_t rs_c, inc_t cs_c, cntx_t* restrict cntx, rntm_t* restrict rntm, thrinfo_t* restrict thread ); // // -- gemmd-like block-panel algorithm (object interface) ---------------------- // // Define a function pointer array named ftypes and initialize its contents with // the addresses of the typed functions defined below, bao_?gemmd_bp_var1(). static FUNCPTR_T GENARRAY_PREF(ftypes,bao_,gemmd_bp_var1); void bao_gemmd_bp_var1 ( obj_t* alpha, obj_t* a, obj_t* d, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, rntm_t* rntm, thrinfo_t* thread ) { const num_t dt = bli_obj_dt( c ); const conj_t conja = bli_obj_conj_status( a ); const conj_t conjb = bli_obj_conj_status( b ); const dim_t m = bli_obj_length( c ); const dim_t n = bli_obj_width( c ); const dim_t k = bli_obj_width( a ); void* restrict buf_a = bli_obj_buffer_at_off( a ); const inc_t rs_a = bli_obj_row_stride( a ); const inc_t cs_a = bli_obj_col_stride( a ); void* restrict buf_d = bli_obj_buffer_at_off( d ); const inc_t incd = bli_obj_vector_inc( d ); void* restrict buf_b = bli_obj_buffer_at_off( b ); const inc_t rs_b = bli_obj_row_stride( b ); const inc_t cs_b = bli_obj_col_stride( b ); void* restrict buf_c = bli_obj_buffer_at_off( c ); const inc_t rs_c = bli_obj_row_stride( c ); const inc_t cs_c = bli_obj_col_stride( c ); void* restrict buf_alpha = bli_obj_buffer_for_1x1( dt, alpha ); void* restrict buf_beta = bli_obj_buffer_for_1x1( dt, beta ); // Index into the function pointer array to extract the correct // typed function pointer based on the chosen datatype. FUNCPTR_T f = ftypes[dt]; // Invoke the function. f ( conja, conjb, m, n, k, buf_alpha, buf_a, rs_a, cs_a, buf_d, incd, buf_b, rs_b, cs_b, buf_beta, buf_c, rs_c, cs_c, cntx, rntm, thread ); } // // -- gemmd-like block-panel algorithm (typed interface) ----------------------- // #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTECH2(bao_,ch,varname) \ ( \ conj_t conja, \ conj_t conjb, \ dim_t m, \ dim_t n, \ dim_t k, \ void* restrict alpha, \ void* restrict a, inc_t rs_a, inc_t cs_a, \ void* restrict d, inc_t incd, \ void* restrict b, inc_t rs_b, inc_t cs_b, \ void* restrict beta, \ void* restrict c, inc_t rs_c, inc_t cs_c, \ cntx_t* restrict cntx, \ rntm_t* restrict rntm, \ thrinfo_t* restrict thread \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ /* Query the context for various blocksizes. */ \ const dim_t NR = bli_cntx_get_blksz_def_dt( dt, BLIS_NR, cntx ); \ const dim_t MR = bli_cntx_get_blksz_def_dt( dt, BLIS_MR, cntx ); \ const dim_t NC = bli_cntx_get_blksz_def_dt( dt, BLIS_NC, cntx ); \ const dim_t MC = bli_cntx_get_blksz_def_dt( dt, BLIS_MC, cntx ); \ const dim_t KC = bli_cntx_get_blksz_def_dt( dt, BLIS_KC, cntx ); \ \ /* Query the context for the microkernel address and cast it to its function pointer type. */ \ PASTECH(ch,gemm_ukr_ft) \ gemm_ukr = bli_cntx_get_l3_nat_ukr_dt( dt, BLIS_GEMM_UKR, cntx ); \ \ /* Compute partitioning step values for each matrix of each loop. */ \ const inc_t jcstep_c = cs_c; \ const inc_t jcstep_b = cs_b; \ \ const inc_t pcstep_a = cs_a; \ const inc_t pcstep_d = incd; \ const inc_t pcstep_b = rs_b; \ \ const inc_t icstep_c = rs_c; \ const inc_t icstep_a = rs_a; \ \ const inc_t jrstep_c = cs_c * NR; \ \ const inc_t irstep_c = rs_c * MR; \ \ ctype* restrict a_00 = a; \ ctype* restrict d_00 = d; \ ctype* restrict b_00 = b; \ ctype* restrict c_00 = c; \ ctype* restrict alpha_cast = alpha; \ ctype* restrict beta_cast = beta; \ \ /* Make local copies of the scalars to prevent any unnecessary sharing of cache lines between the cores' caches. */ \ ctype alpha_local = *alpha_cast; \ ctype beta_local = *beta_cast; \ ctype one_local = *PASTEMAC(ch,1); \ \ auxinfo_t aux; \ \ /* Initialize a mem_t entry for A and B. Strictly speaking, this is only needed for the matrix we will be packing (if any), but we do it unconditionally to be safe. */ \ mem_t mem_a = BLIS_MEM_INITIALIZER; \ mem_t mem_b = BLIS_MEM_INITIALIZER; \ \ /* Define an array of bszid_t ids, which will act as our substitute for the cntl_t tree. */ \ bszid_t bszids[8] = { BLIS_NC, /* 5th loop */ \ BLIS_KC, /* 4th loop */ \ BLIS_NO_PART, /* pack B */ \ BLIS_MC, /* 3rd loop */ \ BLIS_NO_PART, /* pack A */ \ BLIS_NR, /* 2nd loop */ \ BLIS_MR, /* 1st loop */ \ BLIS_KR }; /* microkernel loop */ \ \ bszid_t* restrict bszids_jc = &bszids[0]; \ bszid_t* restrict bszids_pc = &bszids[1]; \ /*bszid_t* restrict bszids_pb = &bszids[2];*/ \ bszid_t* restrict bszids_ic = &bszids[3]; \ /*bszid_t* restrict bszids_pa = &bszids[4];*/ \ bszid_t* restrict bszids_jr = &bszids[5]; \ /*bszid_t* restrict bszids_ir = &bszids[6];*/ \ \ thrinfo_t* restrict thread_jc = NULL; \ thrinfo_t* restrict thread_pc = NULL; \ thrinfo_t* restrict thread_pb = NULL; \ thrinfo_t* restrict thread_ic = NULL; \ thrinfo_t* restrict thread_pa = NULL; \ thrinfo_t* restrict thread_jr = NULL; \ thrinfo_t* restrict thread_ir = NULL; \ \ /* Identify the current thrinfo_t node and then grow the tree. */ \ thread_jc = thread; \ bli_thrinfo_sup_grow( rntm, bszids_jc, thread_jc ); \ \ /* Compute the JC loop thread range for the current thread. */ \ dim_t jc_start, jc_end; \ bli_thread_range_sub( thread_jc, n, NR, FALSE, &jc_start, &jc_end ); \ const dim_t n_local = jc_end - jc_start; \ \ /* Compute number of primary and leftover components of the JC loop. */ \ /*const dim_t jc_iter = ( n_local + NC - 1 ) / NC;*/ \ const dim_t jc_left = n_local % NC; \ \ /* Loop over the n dimension (NC rows/columns at a time). */ \ for ( dim_t jj = jc_start; jj < jc_end; jj += NC ) \ { \ /* Calculate the thread's current JC block dimension. */ \ const dim_t nc_cur = ( NC <= jc_end - jj ? NC : jc_left ); \ \ ctype* restrict b_jc = b_00 + jj * jcstep_b; \ ctype* restrict c_jc = c_00 + jj * jcstep_c; \ \ /* Identify the current thrinfo_t node and then grow the tree. */ \ thread_pc = bli_thrinfo_sub_node( thread_jc ); \ bli_thrinfo_sup_grow( rntm, bszids_pc, thread_pc ); \ \ /* Compute the PC loop thread range for the current thread. */ \ const dim_t pc_start = 0, pc_end = k; \ const dim_t k_local = k; \ \ /* Compute number of primary and leftover components of the PC loop. */ \ /*const dim_t pc_iter = ( k_local + KC - 1 ) / KC;*/ \ const dim_t pc_left = k_local % KC; \ \ /* Loop over the k dimension (KC rows/columns at a time). */ \ for ( dim_t pp = pc_start; pp < pc_end; pp += KC ) \ { \ /* Calculate the thread's current PC block dimension. */ \ const dim_t kc_cur = ( KC <= pc_end - pp ? KC : pc_left ); \ \ ctype* restrict a_pc = a_00 + pp * pcstep_a; \ ctype* restrict d_pc = d_00 + pp * pcstep_d; \ ctype* restrict b_pc = b_jc + pp * pcstep_b; \ \ /* Only apply beta to the first iteration of the pc loop. */ \ ctype* restrict beta_use = ( pp == 0 ? &beta_local : &one_local ); \ \ ctype* b_use; \ inc_t rs_b_use, cs_b_use, ps_b_use; \ \ /* Identify the current thrinfo_t node. Note that the thrinfo_t node will have already been created by a previous call to bli_thrinfo_sup_grow() since bszid_t values of BLIS_NO_PART cause the tree to grow by two (e.g. to the next bszid that is a normal bszid_t value). */ \ thread_pb = bli_thrinfo_sub_node( thread_pc ); \ /*bli_thrinfo_sup_grow( rntm, bszids_pb, thread_pb );*/ \ \ /* Determine the packing buffer and related parameters for matrix B. Then call the packm implementation. */ \ PASTECH2(bao_,ch,packm_b) \ ( \ conjb, \ KC, NC, \ kc_cur, nc_cur, NR, \ &one_local, \ d_pc, incd, \ b_pc, rs_b, cs_b, \ &b_use, &rs_b_use, &cs_b_use, \ &ps_b_use, \ cntx, \ rntm, \ &mem_b, \ thread_pb \ ); \ \ /* Alias b_use so that it's clear this is our current block of matrix B. */ \ ctype* restrict b_pc_use = b_use; \ \ /* Identify the current thrinfo_t node and then grow the tree. */ \ thread_ic = bli_thrinfo_sub_node( thread_pb ); \ bli_thrinfo_sup_grow( rntm, bszids_ic, thread_ic ); \ \ /* Compute the IC loop thread range for the current thread. */ \ dim_t ic_start, ic_end; \ bli_thread_range_sub( thread_ic, m, MR, FALSE, &ic_start, &ic_end ); \ const dim_t m_local = ic_end - ic_start; \ \ /* Compute number of primary and leftover components of the IC loop. */ \ /*const dim_t ic_iter = ( m_local + MC - 1 ) / MC;*/ \ const dim_t ic_left = m_local % MC; \ \ /* Loop over the m dimension (MC rows at a time). */ \ for ( dim_t ii = ic_start; ii < ic_end; ii += MC ) \ { \ /* Calculate the thread's current IC block dimension. */ \ const dim_t mc_cur = ( MC <= ic_end - ii ? MC : ic_left ); \ \ ctype* restrict a_ic = a_pc + ii * icstep_a; \ ctype* restrict c_ic = c_jc + ii * icstep_c; \ \ ctype* a_use; \ inc_t rs_a_use, cs_a_use, ps_a_use; \ \ /* Identify the current thrinfo_t node. Note that the thrinfo_t node will have already been created by a previous call to bli_thrinfo_sup_grow() since bszid_t values of BLIS_NO_PART cause the tree to grow by two (e.g. to the next bszid that is a normal bszid_t value). */ \ thread_pa = bli_thrinfo_sub_node( thread_ic ); \ /*bli_thrinfo_sup_grow( rntm, bszids_pa, thread_pa );*/ \ \ /* Determine the packing buffer and related parameters for matrix A. Then call the packm implementation. */ \ PASTECH2(bao_,ch,packm_a) \ ( \ conja, \ MC, KC, \ mc_cur, kc_cur, MR, \ &one_local, \ d_pc, incd, \ a_ic, rs_a, cs_a, \ &a_use, &rs_a_use, &cs_a_use, \ &ps_a_use, \ cntx, \ rntm, \ &mem_a, \ thread_pa \ ); \ \ /* Alias a_use so that it's clear this is our current block of matrix A. */ \ ctype* restrict a_ic_use = a_use; \ \ /* Identify the current thrinfo_t node and then grow the tree. */ \ thread_jr = bli_thrinfo_sub_node( thread_pa ); \ bli_thrinfo_sup_grow( rntm, bszids_jr, thread_jr ); \ \ /* Query the number of threads and thread ids for the JR loop. NOTE: These values are only needed when computing the next micropanel of B. */ \ const dim_t jr_nt = bli_thread_n_way( thread_jr ); \ const dim_t jr_tid = bli_thread_work_id( thread_jr ); \ \ /* Compute number of primary and leftover components of the JR loop. */ \ dim_t jr_iter = ( nc_cur + NR - 1 ) / NR; \ dim_t jr_left = nc_cur % NR; \ \ /* Compute the JR loop thread range for the current thread. */ \ dim_t jr_start, jr_end; \ bli_thread_range_sub( thread_jr, jr_iter, 1, FALSE, &jr_start, &jr_end ); \ \ /* Loop over the n dimension (NR columns at a time). */ \ for ( dim_t j = jr_start; j < jr_end; j += 1 ) \ { \ const dim_t nr_cur \ = ( bli_is_not_edge_f( j, jr_iter, jr_left ) ? NR : jr_left ); \ \ ctype* restrict b_jr = b_pc_use + j * ps_b_use; \ ctype* restrict c_jr = c_ic + j * jrstep_c; \ \ /* Assume for now that our next panel of B to be the current panel of B. */ \ ctype* restrict b2 = b_jr; \ \ /* Identify the current thrinfo_t node. */ \ thread_ir = bli_thrinfo_sub_node( thread_jr ); \ \ /* Query the number of threads and thread ids for the IR loop. NOTE: These values are only needed when computing the next micropanel of A. */ \ const dim_t ir_nt = bli_thread_n_way( thread_ir ); \ const dim_t ir_tid = bli_thread_work_id( thread_ir ); \ \ /* Compute number of primary and leftover components of the IR loop. */ \ dim_t ir_iter = ( mc_cur + MR - 1 ) / MR; \ dim_t ir_left = mc_cur % MR; \ \ /* Compute the IR loop thread range for the current thread. */ \ dim_t ir_start, ir_end; \ bli_thread_range_sub( thread_ir, ir_iter, 1, FALSE, &ir_start, &ir_end ); \ \ /* Loop over the m dimension (MR rows at a time). */ \ for ( dim_t i = ir_start; i < ir_end; i += 1 ) \ { \ const dim_t mr_cur \ = ( bli_is_not_edge_f( i, ir_iter, ir_left ) ? MR : ir_left ); \ \ ctype* restrict a_ir = a_ic_use + i * ps_a_use; \ ctype* restrict c_ir = c_jr + i * irstep_c; \ \ ctype* restrict a2; \ \ /* Compute the addresses of the next micropanels of A and B. */ \ a2 = bli_gemm_get_next_a_upanel( a_ir, ps_a_use, 1 ); \ if ( bli_is_last_iter( i, ir_end, ir_tid, ir_nt ) ) \ { \ a2 = a_ic_use; \ b2 = bli_gemm_get_next_b_upanel( b_jr, ps_b_use, 1 ); \ if ( bli_is_last_iter( j, jr_end, jr_tid, jr_nt ) ) \ b2 = b_pc_use; \ } \ \ /* Save the addresses of next micropanels of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_next_a( a2, &aux ); \ bli_auxinfo_set_next_b( b2, &aux ); \ \ /* Invoke the gemm microkernel. */ \ gemm_ukr \ ( \ mr_cur, \ nr_cur, \ kc_cur, \ &alpha_local, \ a_ir, \ b_jr, \ beta_use, \ c_ir, rs_c, cs_c, \ &aux, \ cntx \ ); \ } \ } \ } \ \ /* This barrier is needed to prevent threads from starting to pack the next row panel of B before the current row panel is fully computed upon. */ \ bli_thread_barrier( thread_pb ); \ } \ } \ \ /* Release any memory that was acquired for packing matrices A and B. */ \ PASTECH2(bao_,ch,packm_finalize_mem_a) \ ( \ rntm, \ &mem_a, \ thread_pa \ ); \ PASTECH2(bao_,ch,packm_finalize_mem_b) \ ( \ rntm, \ &mem_b, \ thread_pb \ ); \ \ /* PASTEMAC(ch,fprintm)( stdout, "gemmd_bp_var1: a1_packed", mr_cur, kc_cur, a_ir, rs_a_use, cs_a_use, "%5.2f", "" ); \ PASTEMAC(ch,fprintm)( stdout, "gemmd_bp_var1: b1_packed", kc_cur, nr_cur, b_jr, rs_b_use, cs_b_use, "%5.2f", "" ); \ PASTEMAC(ch,fprintm)( stdout, "gemmd_bp_var1: c ", mr_cur, nr_cur, c_ir, rs_c, cs_c, "%5.2f", "" ); \ */ \ } //INSERT_GENTFUNC_BASIC0( gemmd_bp_var1 ) GENTFUNC( float, s, gemmd_bp_var1 ) GENTFUNC( double, d, gemmd_bp_var1 ) GENTFUNC( scomplex, c, gemmd_bp_var1 ) GENTFUNC( dcomplex, z, gemmd_bp_var1 ) blis-0.9.0/addon/gemmd/bao_gemmd_check.c000066400000000000000000000075301422157504600200550ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bao_gemmd_check ( obj_t* alpha, obj_t* a, obj_t* d, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx ) { err_t e_val; // Check object datatypes. e_val = bli_check_noninteger_object( alpha ); bli_check_error_code( e_val ); e_val = bli_check_noninteger_object( beta ); bli_check_error_code( e_val ); e_val = bli_check_floating_object( a ); bli_check_error_code( e_val ); e_val = bli_check_floating_object( d ); bli_check_error_code( e_val ); e_val = bli_check_floating_object( b ); bli_check_error_code( e_val ); e_val = bli_check_floating_object( c ); bli_check_error_code( e_val ); // Check scalar/vector/matrix type. e_val = bli_check_scalar_object( alpha ); bli_check_error_code( e_val ); e_val = bli_check_scalar_object( beta ); bli_check_error_code( e_val ); e_val = bli_check_matrix_object( a ); bli_check_error_code( e_val ); e_val = bli_check_vector_object( d ); bli_check_error_code( e_val ); e_val = bli_check_matrix_object( b ); bli_check_error_code( e_val ); e_val = bli_check_matrix_object( c ); bli_check_error_code( e_val ); // Check object buffers (for non-NULLness). e_val = bli_check_object_buffer( alpha ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( a ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( d ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( b ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( beta ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( c ); bli_check_error_code( e_val ); // Check object dimensions. e_val = bli_check_level3_dims( a, b, c ); bli_check_error_code( e_val ); e_val = bli_check_vector_dim_equals( d, bli_obj_width_after_trans( a ) ); bli_check_error_code( e_val ); // Check for consistent datatypes. // NOTE: We only perform these tests when mixed datatype support is // disabled. e_val = bli_check_consistent_object_datatypes( c, a ); bli_check_error_code( e_val ); e_val = bli_check_consistent_object_datatypes( c, d ); bli_check_error_code( e_val ); e_val = bli_check_consistent_object_datatypes( c, b ); bli_check_error_code( e_val ); } blis-0.9.0/addon/gemmd/bao_gemmd_check.h000066400000000000000000000035471422157504600200660ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype object-based check functions. // void bao_gemmd_check ( obj_t* alpha, obj_t* a, obj_t* d, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx ); blis-0.9.0/addon/gemmd/bao_gemmd_var.h000066400000000000000000000072601422157504600175750ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2021, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype the object-based variant interfaces. // #undef GENPROT #define GENPROT( opname ) \ \ void PASTECH(bao_,opname) \ ( \ obj_t* alpha, \ obj_t* a, \ obj_t* d, \ obj_t* b, \ obj_t* beta, \ obj_t* c, \ cntx_t* cntx, \ rntm_t* rntm, \ thrinfo_t* thread \ ); GENPROT( gemmd_bp_var1 ) // // Prototype the typed variant interfaces. // #undef GENTPROT #define GENTPROT( ctype, ch, varname ) \ \ void PASTECH2(bao_,ch,varname) \ ( \ conj_t conja, \ conj_t conjb, \ dim_t m, \ dim_t n, \ dim_t k, \ void* restrict alpha, \ void* restrict a, inc_t rs_a, inc_t cs_a, \ void* restrict d, inc_t incd, \ void* restrict b, inc_t rs_b, inc_t cs_b, \ void* restrict beta, \ void* restrict c, inc_t rs_c, inc_t cs_c, \ cntx_t* restrict cntx, \ rntm_t* restrict rntm, \ thrinfo_t* restrict thread \ ); //INSERT_GENTPROT_BASIC0( gemmd_bp_var1 ) GENTPROT( float, s, gemmd_bp_var1 ) GENTPROT( double, d, gemmd_bp_var1 ) GENTPROT( scomplex, c, gemmd_bp_var1 ) GENTPROT( dcomplex, z, gemmd_bp_var1 ) // // Prototype the typed kernel interfaces. // #undef GENTPROT #define GENTPROT( ctype, ch, varname ) \ \ void PASTECH2(bao_,ch,varname) \ ( \ const dim_t MR, \ const dim_t NR, \ dim_t mr_cur, \ dim_t nr_cur, \ dim_t k, \ ctype* restrict alpha, \ ctype* restrict a, inc_t rs_a, inc_t cs_a, \ ctype* restrict b, inc_t rs_b, inc_t cs_b, \ ctype* restrict beta, \ ctype* restrict c, inc_t rs_c, inc_t cs_c, \ auxinfo_t* restrict aux, \ cntx_t* restrict cntx \ ); //INSERT_GENTPROT_BASIC0( gemm_kernel ) GENTPROT( float, s, gemm_kernel ) GENTPROT( double, d, gemm_kernel ) GENTPROT( scomplex, c, gemm_kernel ) GENTPROT( dcomplex, z, gemm_kernel ) blis-0.9.0/addon/gemmd/bao_l3_packm_a.c000066400000000000000000000241021422157504600176120ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2021, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENTFUNC #define GENTFUNC( ctype, ch, opname ) \ \ void PASTECH2(bao_,ch,opname) \ ( \ dim_t m, \ dim_t k, \ dim_t mr, \ cntx_t* restrict cntx, \ rntm_t* restrict rntm, \ mem_t* restrict mem, \ thrinfo_t* restrict thread \ ) \ { \ /* Set the pack buffer type so that we are obtaining memory blocks from the pool dedicated to blocks of A. */ \ const packbuf_t pack_buf_type = BLIS_BUFFER_FOR_A_BLOCK; \ \ /* NOTE: This "rounding up" of the last upanel is absolutely necessary since we NEED that last micropanel to have the same ldim (cs_p) as the other micropanels. Why? Because the microkernel assumes that the register (MR, NR) AND storage (PACKMR, PACKNR) blocksizes do not change. */ \ const dim_t m_pack = ( m / mr + ( m % mr ? 1 : 0 ) ) * mr; \ const dim_t k_pack = k; \ \ /* Barrier to make sure all threads are caught up and ready to begin the packm stage. */ \ bli_thread_barrier( thread ); \ \ /* Compute the size of the memory block eneded. */ \ siz_t size_needed = sizeof( ctype ) * m_pack * k_pack; \ \ /* Check the mem_t entry provided by the caller. If it is unallocated, then we need to acquire a block from the packed block allocator. */ \ if ( bli_mem_is_unalloc( mem ) ) \ { \ if ( bli_thread_am_ochief( thread ) ) \ { \ /* Acquire directly to the chief thread's mem_t that was passed in. It needs to be that mem_t struct, and not a local (temporary) mem_t, since there is no barrier until after packing is finished, which could allow a race condition whereby the chief thread exits the current function before the other threads have a chance to copy from it. (A barrier would fix that race condition, but then again, I prefer to keep barriers to a minimum.) */ \ bli_pba_acquire_m \ ( \ rntm, \ size_needed, \ pack_buf_type, \ mem \ ); \ } \ \ /* Broadcast the address of the chief thread's passed-in mem_t to all threads. */ \ mem_t* mem_p = bli_thread_broadcast( thread, mem ); \ \ /* Non-chief threads: Copy the contents of the chief thread's passed-in mem_t to the passed-in mem_t for this thread. (The chief thread already has the mem_t, so it does not need to perform any copy.) */ \ if ( !bli_thread_am_ochief( thread ) ) \ { \ *mem = *mem_p; \ } \ } \ else /* if ( bli_mem_is_alloc( mem ) ) */ \ { \ /* If the mem_t entry provided by the caller does NOT contain a NULL buffer, then a block has already been acquired from the packed block allocator and cached by the caller. */ \ \ /* As a sanity check, we should make sure that the mem_t object isn't associated with a block that is too small compared to the size of the packed matrix buffer that is needed, according to the value computed above. */ \ siz_t mem_size = bli_mem_size( mem ); \ \ if ( mem_size < size_needed ) \ { \ if ( bli_thread_am_ochief( thread ) ) \ { \ /* The chief thread releases the existing block associated with the mem_t, and then re-acquires a new block, saving the associated mem_t to its passed-in mem_t. (See coment above for why the acquisition needs to be directly to the chief thread's passed-in mem_t and not a local (temporary) mem_t. */ \ bli_pba_release \ ( \ rntm, \ mem \ ); \ bli_pba_acquire_m \ ( \ rntm, \ size_needed, \ pack_buf_type, \ mem \ ); \ } \ \ /* Broadcast the address of the chief thread's passed-in mem_t to all threads. */ \ mem_t* mem_p = bli_thread_broadcast( thread, mem ); \ \ /* Non-chief threads: Copy the contents of the chief thread's passed-in mem_t to the passed-in mem_t for this thread. (The chief thread already has the mem_t, so it does not need to perform any copy.) */ \ if ( !bli_thread_am_ochief( thread ) ) \ { \ *mem = *mem_p; \ } \ } \ else \ { \ /* If the mem_t entry is already allocated and sufficiently large, then we use it as-is. No action is needed. */ \ } \ } \ } //INSERT_GENTFUNC_BASIC0( packm_init_mem_a ) GENTFUNC( float, s, packm_init_mem_a ) GENTFUNC( double, d, packm_init_mem_a ) GENTFUNC( scomplex, c, packm_init_mem_a ) GENTFUNC( dcomplex, z, packm_init_mem_a ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname ) \ \ void PASTECH2(bao_,ch,opname) \ ( \ rntm_t* restrict rntm, \ mem_t* restrict mem, \ thrinfo_t* restrict thread \ ) \ { \ if ( thread != NULL ) \ if ( bli_thread_am_ochief( thread ) ) \ { \ /* Check the mem_t entry provided by the caller. Only proceed if it is allocated, which it should be. */ \ if ( bli_mem_is_alloc( mem ) ) \ { \ bli_pba_release \ ( \ rntm, \ mem \ ); \ } \ } \ } //INSERT_GENTFUNC_BASIC0( packm_finalize_mem_a ) GENTFUNC( float, s, packm_finalize_mem_a ) GENTFUNC( double, d, packm_finalize_mem_a ) GENTFUNC( scomplex, c, packm_finalize_mem_a ) GENTFUNC( dcomplex, z, packm_finalize_mem_a ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname ) \ \ void PASTECH2(bao_,ch,opname) \ ( \ pack_t* restrict schema, \ dim_t m, \ dim_t k, \ dim_t mr, \ dim_t* restrict m_max, \ dim_t* restrict k_max, \ ctype** p, inc_t* restrict rs_p, inc_t* restrict cs_p, \ dim_t* restrict pd_p, inc_t* restrict ps_p, \ mem_t* restrict mem \ ) \ { \ /* NOTE: This "rounding up" of the last upanel is absolutely necessary since we NEED that last micropanel to have the same ldim (cs_p) as the other micropanels. Why? Because the microkernel assumes that the register (MR, NR) AND storage (PACKMR, PACKNR) blocksizes do not change. */ \ *m_max = ( m / mr + ( m % mr ? 1 : 0 ) ) * mr; \ *k_max = k; \ \ /* Determine the dimensions and strides for the packed matrix A. */ \ { \ /* Pack A to column-stored row-panels. */ \ *rs_p = 1; \ *cs_p = mr; \ \ *pd_p = mr; \ *ps_p = mr * k; \ \ /* Set the schema to "packed row panels" to indicate packing to conventional column-stored row panels. */ \ *schema = BLIS_PACKED_ROW_PANELS; \ } \ \ /* Set the buffer address provided by the caller to point to the memory associated with the mem_t entry acquired from the memory pool. */ \ *p = bli_mem_buffer( mem ); \ } //INSERT_GENTFUNC_BASIC0( packm_init_a ) GENTFUNC( float, s, packm_init_a ) GENTFUNC( double, d, packm_init_a ) GENTFUNC( scomplex, c, packm_init_a ) GENTFUNC( dcomplex, z, packm_init_a ) // // Define BLAS-like interfaces to the variant chooser. // #undef GENTFUNC #define GENTFUNC( ctype, ch, opname ) \ \ void PASTECH2(bao_,ch,opname) \ ( \ conj_t conj, \ dim_t m_alloc, \ dim_t k_alloc, \ dim_t m, \ dim_t k, \ dim_t mr, \ ctype* restrict kappa, \ ctype* restrict d, inc_t incd, \ ctype* restrict a, inc_t rs_a, inc_t cs_a, \ ctype** restrict p, inc_t* restrict rs_p, inc_t* restrict cs_p, \ inc_t* restrict ps_p, \ cntx_t* restrict cntx, \ rntm_t* restrict rntm, \ mem_t* restrict mem, \ thrinfo_t* restrict thread \ ) \ { \ pack_t schema; \ dim_t m_max; \ dim_t k_max; \ dim_t pd_p; \ \ /* Prepare the packing destination buffer. */ \ PASTECH2(bao_,ch,packm_init_mem_a) \ ( \ m_alloc, k_alloc, mr, \ cntx, \ rntm, \ mem, \ thread \ ); \ \ /* Determine the packing buffer and related parameters for matrix A. */ \ PASTECH2(bao_,ch,packm_init_a) \ ( \ &schema, \ m, k, mr, \ &m_max, &k_max, \ p, rs_p, cs_p, \ &pd_p, ps_p, \ mem \ ); \ \ /* Pack matrix A to the destination buffer chosen above. Here, the packed matrix is stored to column-stored MR x k micropanels. */ \ PASTECH2(bao_,ch,packm_var1) \ ( \ conj, \ schema, \ m, \ k, \ m_max, \ k_max, \ kappa, \ d, incd, \ a, rs_a, cs_a, \ *p, *rs_p, *cs_p, \ pd_p, *ps_p, \ cntx, \ thread \ ); \ \ /* Barrier so that packing is done before computation. */ \ bli_thread_barrier( thread ); \ } //INSERT_GENTFUNC_BASIC0( packm_a ) GENTFUNC( float, s, packm_a ) GENTFUNC( double, d, packm_a ) GENTFUNC( scomplex, c, packm_a ) GENTFUNC( dcomplex, z, packm_a ) blis-0.9.0/addon/gemmd/bao_l3_packm_a.h000066400000000000000000000102211422157504600176140ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2021, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ void PASTECH2(bao_,ch,opname) \ ( \ dim_t m, \ dim_t k, \ dim_t mr, \ cntx_t* restrict cntx, \ rntm_t* restrict rntm, \ mem_t* restrict mem, \ thrinfo_t* restrict thread \ ); \ //INSERT_GENTPROT_BASIC0( packm_init_mem_a ) GENTPROT( float, s, packm_init_mem_a ) GENTPROT( double, d, packm_init_mem_a ) GENTPROT( scomplex, c, packm_init_mem_a ) GENTPROT( dcomplex, z, packm_init_mem_a ) #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ void PASTECH2(bao_,ch,opname) \ ( \ rntm_t* restrict rntm, \ mem_t* restrict mem, \ thrinfo_t* restrict thread \ ); \ //INSERT_GENTPROT_BASIC0( packm_finalize_mem_a ) GENTPROT( float, s, packm_finalize_mem_a ) GENTPROT( double, d, packm_finalize_mem_a ) GENTPROT( scomplex, c, packm_finalize_mem_a ) GENTPROT( dcomplex, z, packm_finalize_mem_a ) #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ void PASTECH2(bao_,ch,opname) \ ( \ pack_t* restrict schema, \ dim_t m, \ dim_t k, \ dim_t mr, \ dim_t* restrict m_max, \ dim_t* restrict k_max, \ ctype** p, inc_t* restrict rs_p, inc_t* restrict cs_p, \ dim_t* restrict pd_p, inc_t* restrict ps_p, \ mem_t* restrict mem \ ); \ //INSERT_GENTPROT_BASIC0( packm_init_a ) GENTPROT( float, s, packm_init_a ) GENTPROT( double, d, packm_init_a ) GENTPROT( scomplex, c, packm_init_a ) GENTPROT( dcomplex, z, packm_init_a ) #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ void PASTECH2(bao_,ch,opname) \ ( \ conj_t conj, \ dim_t m_alloc, \ dim_t k_alloc, \ dim_t m, \ dim_t k, \ dim_t mr, \ ctype* restrict kappa, \ ctype* restrict d, inc_t incd, \ ctype* restrict a, inc_t rs_a, inc_t cs_a, \ ctype** restrict p, inc_t* restrict rs_p, inc_t* restrict cs_p, \ inc_t* restrict ps_p, \ cntx_t* restrict cntx, \ rntm_t* restrict rntm, \ mem_t* restrict mem, \ thrinfo_t* restrict thread \ ); \ //INSERT_GENTPROT_BASIC0( packm_a ) GENTPROT( float, s, packm_a ) GENTPROT( double, d, packm_a ) GENTPROT( scomplex, c, packm_a ) GENTPROT( dcomplex, z, packm_a ) blis-0.9.0/addon/gemmd/bao_l3_packm_b.c000066400000000000000000000241021422157504600176130ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2021, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENTFUNC #define GENTFUNC( ctype, ch, opname ) \ \ void PASTECH2(bao_,ch,opname) \ ( \ dim_t k, \ dim_t n, \ dim_t nr, \ cntx_t* restrict cntx, \ rntm_t* restrict rntm, \ mem_t* restrict mem, \ thrinfo_t* restrict thread \ ) \ { \ /* Set the pack buffer type so that we are obtaining memory blocks from the pool dedicated to panels of B. */ \ const packbuf_t pack_buf_type = BLIS_BUFFER_FOR_B_PANEL; \ \ /* NOTE: This "rounding up" of the last upanel is absolutely necessary since we NEED that last micropanel to have the same ldim (cs_p) as the other micropanels. Why? Because the microkernel assumes that the register (MR, NR) AND storage (PACKMR, PACKNR) blocksizes do not change. */ \ const dim_t k_pack = k; \ const dim_t n_pack = ( n / nr + ( n % nr ? 1 : 0 ) ) * nr; \ \ /* Barrier to make sure all threads are caught up and ready to begin the packm stage. */ \ bli_thread_barrier( thread ); \ \ /* Compute the size of the memory block eneded. */ \ siz_t size_needed = sizeof( ctype ) * k_pack * n_pack; \ \ /* Check the mem_t entry provided by the caller. If it is unallocated, then we need to acquire a block from the packed block allocator. */ \ if ( bli_mem_is_unalloc( mem ) ) \ { \ if ( bli_thread_am_ochief( thread ) ) \ { \ /* Acquire directly to the chief thread's mem_t that was passed in. It needs to be that mem_t struct, and not a local (temporary) mem_t, since there is no barrier until after packing is finished, which could allow a race condition whereby the chief thread exits the current function before the other threads have a chance to copy from it. (A barrier would fix that race condition, but then again, I prefer to keep barriers to a minimum.) */ \ bli_pba_acquire_m \ ( \ rntm, \ size_needed, \ pack_buf_type, \ mem \ ); \ } \ \ /* Broadcast the address of the chief thread's passed-in mem_t to all threads. */ \ mem_t* mem_p = bli_thread_broadcast( thread, mem ); \ \ /* Non-chief threads: Copy the contents of the chief thread's passed-in mem_t to the passed-in mem_t for this thread. (The chief thread already has the mem_t, so it does not need to perform any copy.) */ \ if ( !bli_thread_am_ochief( thread ) ) \ { \ *mem = *mem_p; \ } \ } \ else /* if ( bli_mem_is_alloc( mem ) ) */ \ { \ /* If the mem_t entry provided by the caller does NOT contain a NULL buffer, then a block has already been acquired from the packed block allocator and cached by the caller. */ \ \ /* As a sanity check, we should make sure that the mem_t object isn't associated with a block that is too small compared to the size of the packed matrix buffer that is needed, according to the value computed above. */ \ siz_t mem_size = bli_mem_size( mem ); \ \ if ( mem_size < size_needed ) \ { \ if ( bli_thread_am_ochief( thread ) ) \ { \ /* The chief thread releases the existing block associated with the mem_t, and then re-acquires a new block, saving the associated mem_t to its passed-in mem_t. (See coment above for why the acquisition needs to be directly to the chief thread's passed-in mem_t and not a local (temporary) mem_t. */ \ bli_pba_release \ ( \ rntm, \ mem \ ); \ bli_pba_acquire_m \ ( \ rntm, \ size_needed, \ pack_buf_type, \ mem \ ); \ } \ \ /* Broadcast the address of the chief thread's passed-in mem_t to all threads. */ \ mem_t* mem_p = bli_thread_broadcast( thread, mem ); \ \ /* Non-chief threads: Copy the contents of the chief thread's passed-in mem_t to the passed-in mem_t for this thread. (The chief thread already has the mem_t, so it does not need to perform any copy.) */ \ if ( !bli_thread_am_ochief( thread ) ) \ { \ *mem = *mem_p; \ } \ } \ else \ { \ /* If the mem_t entry is already allocated and sufficiently large, then we use it as-is. No action is needed. */ \ } \ } \ } //INSERT_GENTFUNC_BASIC0( packm_init_mem_b ) GENTFUNC( float, s, packm_init_mem_b ) GENTFUNC( double, d, packm_init_mem_b ) GENTFUNC( scomplex, c, packm_init_mem_b ) GENTFUNC( dcomplex, z, packm_init_mem_b ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname ) \ \ void PASTECH2(bao_,ch,opname) \ ( \ rntm_t* restrict rntm, \ mem_t* restrict mem, \ thrinfo_t* restrict thread \ ) \ { \ if ( thread != NULL ) \ if ( bli_thread_am_ochief( thread ) ) \ { \ /* Check the mem_t entry provided by the caller. Only proceed if it is allocated, which it should be. */ \ if ( bli_mem_is_alloc( mem ) ) \ { \ bli_pba_release \ ( \ rntm, \ mem \ ); \ } \ } \ } //INSERT_GENTFUNC_BASIC0( packm_finalize_mem_b ) GENTFUNC( float, s, packm_finalize_mem_b ) GENTFUNC( double, d, packm_finalize_mem_b ) GENTFUNC( scomplex, c, packm_finalize_mem_b ) GENTFUNC( dcomplex, z, packm_finalize_mem_b ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname ) \ \ void PASTECH2(bao_,ch,opname) \ ( \ pack_t* restrict schema, \ dim_t k, \ dim_t n, \ dim_t nr, \ dim_t* restrict k_max, \ dim_t* restrict n_max, \ ctype** p, inc_t* restrict rs_p, inc_t* restrict cs_p, \ dim_t* restrict pd_p, inc_t* restrict ps_p, \ mem_t* restrict mem \ ) \ { \ /* NOTE: This "rounding up" of the last upanel is absolutely necessary since we NEED that last micropanel to have the same ldim (cs_p) as the other micropanels. Why? Because the microkernel assumes that the register (MR, NR) AND storage (PACKMR, PACKNR) blocksizes do not change. */ \ *k_max = k; \ *n_max = ( n / nr + ( n % nr ? 1 : 0 ) ) * nr; \ \ /* Determine the dimensions and strides for the packed matrix B. */ \ { \ /* Pack B to row-stored column-panels. */ \ *rs_p = nr; \ *cs_p = 1; \ \ *pd_p = nr; \ *ps_p = k * nr; \ \ /* Set the schema to "packed column panels" to indicate packing to conventional row-stored column panels. */ \ *schema = BLIS_PACKED_COL_PANELS; \ } \ \ /* Set the buffer address provided by the caller to point to the memory associated with the mem_t entry acquired from the memory pool. */ \ *p = bli_mem_buffer( mem ); \ } //INSERT_GENTFUNC_BASIC0( packm_init_b ) GENTFUNC( float, s, packm_init_b ) GENTFUNC( double, d, packm_init_b ) GENTFUNC( scomplex, c, packm_init_b ) GENTFUNC( dcomplex, z, packm_init_b ) // // Define BLAS-like interfaces to the variant chooser. // #undef GENTFUNC #define GENTFUNC( ctype, ch, opname ) \ \ void PASTECH2(bao_,ch,opname) \ ( \ conj_t conj, \ dim_t k_alloc, \ dim_t n_alloc, \ dim_t k, \ dim_t n, \ dim_t nr, \ ctype* restrict kappa, \ ctype* restrict d, inc_t incd, \ ctype* restrict b, inc_t rs_b, inc_t cs_b, \ ctype** restrict p, inc_t* restrict rs_p, inc_t* restrict cs_p, \ inc_t* restrict ps_p, \ cntx_t* restrict cntx, \ rntm_t* restrict rntm, \ mem_t* restrict mem, \ thrinfo_t* restrict thread \ ) \ { \ pack_t schema; \ dim_t k_max; \ dim_t n_max; \ dim_t pd_p; \ \ /* Prepare the packing destination buffer. */ \ PASTECH2(bao_,ch,packm_init_mem_b) \ ( \ k_alloc, n_alloc, nr, \ cntx, \ rntm, \ mem, \ thread \ ); \ \ /* Determine the packing buffer and related parameters for matrix B. */ \ PASTECH2(bao_,ch,packm_init_b) \ ( \ &schema, \ k, n, nr, \ &k_max, &n_max, \ p, rs_p, cs_p, \ &pd_p, ps_p, \ mem \ ); \ \ /* Pack matrix B to the destination buffer chosen above. Here, the packed matrix is stored to row-stored k x NR micropanels. */ \ PASTECH2(bao_,ch,packm_var1) \ ( \ conj, \ schema, \ k, \ n, \ k_max, \ n_max, \ kappa, \ d, incd, \ b, rs_b, cs_b, \ *p, *rs_p, *cs_p, \ pd_p, *ps_p, \ cntx, \ thread \ ); \ \ /* Barrier so that packing is done before computation. */ \ bli_thread_barrier( thread ); \ } //INSERT_GENTFUNC_BASIC0( packm_b ) GENTFUNC( float, s, packm_b ) GENTFUNC( double, d, packm_b ) GENTFUNC( scomplex, c, packm_b ) GENTFUNC( dcomplex, z, packm_b ) blis-0.9.0/addon/gemmd/bao_l3_packm_b.h000066400000000000000000000102211422157504600176150ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2021, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ void PASTECH2(bao_,ch,opname) \ ( \ dim_t k, \ dim_t n, \ dim_t nr, \ cntx_t* restrict cntx, \ rntm_t* restrict rntm, \ mem_t* restrict mem, \ thrinfo_t* restrict thread \ ); \ //INSERT_GENTPROT_BASIC0( packm_init_mem_b ) GENTPROT( float, s, packm_init_mem_b ) GENTPROT( double, d, packm_init_mem_b ) GENTPROT( scomplex, c, packm_init_mem_b ) GENTPROT( dcomplex, z, packm_init_mem_b ) #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ void PASTECH2(bao_,ch,opname) \ ( \ rntm_t* restrict rntm, \ mem_t* restrict mem, \ thrinfo_t* restrict thread \ ); \ //INSERT_GENTPROT_BASIC0( packm_finalize_mem_b ) GENTPROT( float, s, packm_finalize_mem_b ) GENTPROT( double, d, packm_finalize_mem_b ) GENTPROT( scomplex, c, packm_finalize_mem_b ) GENTPROT( dcomplex, z, packm_finalize_mem_b ) #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ void PASTECH2(bao_,ch,opname) \ ( \ pack_t* restrict schema, \ dim_t k, \ dim_t n, \ dim_t nr, \ dim_t* restrict k_max, \ dim_t* restrict n_max, \ ctype** p, inc_t* restrict rs_p, inc_t* restrict cs_p, \ dim_t* restrict pd_p, inc_t* restrict ps_p, \ mem_t* restrict mem \ ); \ //INSERT_GENTPROT_BASIC0( packm_init_b ) GENTPROT( float, s, packm_init_b ) GENTPROT( double, d, packm_init_b ) GENTPROT( scomplex, c, packm_init_b ) GENTPROT( dcomplex, z, packm_init_b ) #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ void PASTECH2(bao_,ch,opname) \ ( \ conj_t conj, \ dim_t k_alloc, \ dim_t n_alloc, \ dim_t k, \ dim_t n, \ dim_t nr, \ ctype* restrict kappa, \ ctype* restrict d, inc_t incd, \ ctype* restrict b, inc_t rs_b, inc_t cs_b, \ ctype** restrict p, inc_t* restrict rs_p, inc_t* restrict cs_p, \ inc_t* restrict ps_p, \ cntx_t* restrict cntx, \ rntm_t* restrict rntm, \ mem_t* restrict mem, \ thrinfo_t* restrict thread \ ); \ //INSERT_GENTPROT_BASIC0( packm_b ) GENTPROT( float, s, packm_b ) GENTPROT( double, d, packm_b ) GENTPROT( scomplex, c, packm_b ) GENTPROT( dcomplex, z, packm_b ) blis-0.9.0/addon/gemmd/bao_l3_packm_var.h000066400000000000000000000052171422157504600201750ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2021, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype BLAS-like interfaces to the variants. // #undef GENTPROT #define GENTPROT( ctype, ch, varname ) \ \ void PASTECH2(bao_,ch,varname) \ ( \ trans_t transc, \ pack_t schema, \ dim_t m, \ dim_t n, \ dim_t m_max, \ dim_t n_max, \ ctype* restrict kappa, \ ctype* restrict d, inc_t incd, \ ctype* restrict c, inc_t rs_c, inc_t cs_c, \ ctype* restrict p, inc_t rs_p, inc_t cs_p, \ dim_t pd_p, inc_t ps_p, \ cntx_t* restrict cntx, \ thrinfo_t* restrict thread \ ); //INSERT_GENTPROT_BASIC0( packm_var1 ) GENTPROT( float, s, packm_var1 ) GENTPROT( double, d, packm_var1 ) GENTPROT( scomplex, c, packm_var1 ) GENTPROT( dcomplex, z, packm_var1 ) //INSERT_GENTPROT_BASIC0( packm_var2 ) GENTPROT( float, s, packm_var2 ) GENTPROT( double, d, packm_var2 ) GENTPROT( scomplex, c, packm_var2 ) GENTPROT( dcomplex, z, packm_var2 ) blis-0.9.0/addon/gemmd/bao_l3_packm_var1.c000066400000000000000000000145661422157504600202600ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2021, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // Variant 1 provides basic support for packing by calling packm_cxk(). // #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTECH2(bao_,ch,varname) \ ( \ trans_t transc, \ pack_t schema, \ dim_t m, \ dim_t n, \ dim_t m_max, \ dim_t n_max, \ ctype* restrict kappa, \ ctype* restrict d, inc_t incd, \ ctype* restrict c, inc_t rs_c, inc_t cs_c, \ ctype* restrict p, inc_t rs_p, inc_t cs_p, \ dim_t pd_p, inc_t ps_p, \ cntx_t* restrict cntx, \ thrinfo_t* restrict thread \ ) \ { \ ctype* restrict kappa_cast = kappa; \ ctype* restrict c_cast = c; \ ctype* restrict p_cast = p; \ \ dim_t iter_dim; \ dim_t n_iter; \ dim_t it, ic; \ dim_t ic0; \ doff_t ic_inc; \ dim_t panel_len; \ dim_t panel_len_max; \ dim_t panel_dim; \ dim_t panel_dim_max; \ inc_t incc; \ inc_t ldc; \ inc_t ldp; \ conj_t conjc; \ \ \ /* Extract the conjugation bit from the transposition argument. */ \ conjc = bli_extract_conj( transc ); \ \ /* Create flags to incidate row or column storage. Note that the schema bit that encodes row or column is describing the form of micro-panel, not the storage in the micro-panel. Hence the mismatch in "row" and "column" semantics. */ \ bool row_stored = bli_is_col_packed( schema ); \ /*bool col_stored = bli_is_row_packed( schema );*/ \ \ /* If the row storage flag indicates row storage, then we are packing to column panels; otherwise, if the strides indicate column storage, we are packing to row panels. */ \ if ( row_stored ) \ { \ /* Prepare to pack to row-stored column panels. */ \ iter_dim = n; \ panel_len = m; \ panel_len_max = m_max; \ panel_dim_max = pd_p; \ incc = cs_c; \ ldc = rs_c; \ ldp = rs_p; \ } \ else /* if ( col_stored ) */ \ { \ /* Prepare to pack to column-stored row panels. */ \ iter_dim = m; \ panel_len = n; \ panel_len_max = n_max; \ panel_dim_max = pd_p; \ incc = rs_c; \ ldc = cs_c; \ ldp = cs_p; \ } \ \ /* Compute the total number of iterations we'll need. */ \ n_iter = iter_dim / panel_dim_max + ( iter_dim % panel_dim_max ? 1 : 0 ); \ \ /* Set the initial values and increments for indices related to C and P based on whether reverse iteration was requested. */ \ { \ ic0 = 0; \ ic_inc = panel_dim_max; \ } \ \ ctype* restrict p_begin = p_cast; \ \ /* Query the number of threads and thread ids from the current thread's packm thrinfo_t node. */ \ const dim_t nt = bli_thread_n_way( thread ); \ const dim_t tid = bli_thread_work_id( thread ); \ \ /* Suppress warnings in case tid isn't used (ie: as in slab partitioning). */ \ ( void )nt; \ ( void )tid; \ \ dim_t it_start, it_end, it_inc; \ \ /* Determine the thread range and increment using the current thread's packm thrinfo_t node. NOTE: The definition of bli_thread_range_jrir() will depend on whether slab or round-robin partitioning was requested at configure-time. */ \ bli_thread_range_jrir( thread, n_iter, 1, FALSE, &it_start, &it_end, &it_inc ); \ \ /* Iterate over every logical micropanel in the source matrix. */ \ for ( ic = ic0, it = 0; it < n_iter; \ ic += ic_inc, it += 1 ) \ { \ panel_dim = bli_min( panel_dim_max, iter_dim - ic ); \ \ ctype* restrict c_begin = c_cast + (ic )*incc; \ \ ctype* restrict c_use = c_begin; \ ctype* restrict p_use = p_begin; \ \ /* The definition of bli_packm_my_iter() will depend on whether slab or round-robin partitioning was requested at configure-time. (The default is slab.) */ \ if ( bli_packm_my_iter( it, it_start, it_end, tid, nt ) ) \ { \ PASTECH2(bao_,ch,packm_cxk) \ ( \ conjc, \ schema, \ panel_dim, \ panel_dim_max, \ panel_len, \ panel_len_max, \ kappa_cast, \ d, incd, \ c_use, incc, ldc, \ p_use, ldp, \ cntx \ ); \ } \ \ /* if ( !row_stored ) \ PASTEMAC(ch,fprintm)( stdout, "packm_var1: a packed", panel_dim_max, panel_len_max, \ p_use, rs_p, cs_p, "%5.2f", "" ); \ else \ PASTEMAC(ch,fprintm)( stdout, "packm_var1: b packed", panel_len_max, panel_dim_max, \ p_use, rs_p, cs_p, "%5.2f", "" ); \ */ \ \ p_begin += ps_p; \ } \ } //INSERT_GENTFUNC_BASIC0( packm_var1 ) GENTFUNC( float, s, packm_var1 ) GENTFUNC( double, d, packm_var1 ) GENTFUNC( scomplex, c, packm_var1 ) GENTFUNC( dcomplex, z, packm_var1 ) blis-0.9.0/addon/gemmd/bao_l3_packm_var2.c000066400000000000000000000174731422157504600202610ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2021, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // Variant 2 is similar to variant 1, but inlines the contents of packm_cxk(). // #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTECH2(bao_,ch,varname) \ ( \ trans_t transc, \ pack_t schema, \ dim_t m, \ dim_t n, \ dim_t m_max, \ dim_t n_max, \ ctype* restrict kappa, \ ctype* restrict d, inc_t incd, \ ctype* restrict c, inc_t rs_c, inc_t cs_c, \ ctype* restrict p, inc_t rs_p, inc_t cs_p, \ dim_t pd_p, inc_t ps_p, \ cntx_t* restrict cntx, \ thrinfo_t* restrict thread \ ) \ { \ ctype* restrict kappa_cast = kappa; \ ctype* restrict c_cast = c; \ ctype* restrict p_cast = p; \ \ dim_t iter_dim; \ dim_t n_iter; \ dim_t it, ic; \ dim_t ic0; \ doff_t ic_inc; \ dim_t panel_len; \ dim_t panel_len_max; \ dim_t panel_dim; \ dim_t panel_dim_max; \ inc_t incc; \ inc_t ldc; \ inc_t ldp; \ conj_t conjc; \ \ \ /* Extract the conjugation bit from the transposition argument. */ \ conjc = bli_extract_conj( transc ); \ \ /* Create flags to incidate row or column storage. Note that the schema bit that encodes row or column is describing the form of micro-panel, not the storage in the micro-panel. Hence the mismatch in "row" and "column" semantics. */ \ bool row_stored = bli_is_col_packed( schema ); \ /*bool col_stored = bli_is_row_packed( schema );*/ \ \ /* If the row storage flag indicates row storage, then we are packing to column panels; otherwise, if the strides indicate column storage, we are packing to row panels. */ \ if ( row_stored ) \ { \ /* Prepare to pack to row-stored column panels. */ \ iter_dim = n; \ panel_len = m; \ panel_len_max = m_max; \ panel_dim_max = pd_p; \ incc = cs_c; \ ldc = rs_c; \ ldp = rs_p; \ } \ else /* if ( col_stored ) */ \ { \ /* Prepare to pack to column-stored row panels. */ \ iter_dim = m; \ panel_len = n; \ panel_len_max = n_max; \ panel_dim_max = pd_p; \ incc = rs_c; \ ldc = cs_c; \ ldp = cs_p; \ } \ \ /* Compute the total number of iterations we'll need. */ \ n_iter = iter_dim / panel_dim_max + ( iter_dim % panel_dim_max ? 1 : 0 ); \ \ /* Set the initial values and increments for indices related to C and P based on whether reverse iteration was requested. */ \ { \ ic0 = 0; \ ic_inc = panel_dim_max; \ } \ \ ctype* restrict p_begin = p_cast; \ \ /* Query the number of threads and thread ids from the current thread's packm thrinfo_t node. */ \ const dim_t nt = bli_thread_n_way( thread ); \ const dim_t tid = bli_thread_work_id( thread ); \ \ /* Suppress warnings in case tid isn't used (ie: as in slab partitioning). */ \ ( void )nt; \ ( void )tid; \ \ dim_t it_start, it_end, it_inc; \ \ /* Determine the thread range and increment using the current thread's packm thrinfo_t node. NOTE: The definition of bli_thread_range_jrir() will depend on whether slab or round-robin partitioning was requested at configure-time. */ \ bli_thread_range_jrir( thread, n_iter, 1, FALSE, &it_start, &it_end, &it_inc ); \ \ /* Iterate over every logical micropanel in the source matrix. */ \ for ( ic = ic0, it = 0; it < n_iter; \ ic += ic_inc, it += 1 ) \ { \ panel_dim = bli_min( panel_dim_max, iter_dim - ic ); \ \ ctype* restrict c_begin = c_cast + (ic )*incc; \ \ ctype* restrict c_use = c_begin; \ ctype* restrict p_use = p_begin; \ \ /* The definition of bli_packm_my_iter() will depend on whether slab or round-robin partitioning was requested at configure-time. (The default is slab.) */ \ if ( bli_packm_my_iter( it, it_start, it_end, tid, nt ) ) \ { \ /* NOTE: We assume here that kappa = 1 and therefore ignore it. If we're wrong, this will get someone's attention. */ \ if ( !PASTEMAC(ch,eq1)( *kappa_cast ) ) \ bli_abort(); \ \ /* Perform the packing, taking conjc into account. */ \ if ( bli_is_conj( conjc ) ) \ { \ for ( dim_t l = 0; l < panel_len; ++l ) \ { \ for ( dim_t d = 0; d < panel_dim; ++d ) \ { \ ctype* cld = c_use + (l )*ldc + (d )*incc; \ ctype* pld = p_use + (l )*ldp + (d )*1; \ \ PASTEMAC(ch,copyjs)( *cld, *pld ); \ } \ } \ } \ else \ { \ for ( dim_t l = 0; l < panel_len; ++l ) \ { \ for ( dim_t d = 0; d < panel_dim; ++d ) \ { \ ctype* cld = c_use + (l )*ldc + (d )*incc; \ ctype* pld = p_use + (l )*ldp + (d )*1; \ \ PASTEMAC(ch,copys)( *cld, *pld ); \ } \ } \ } \ \ /* If panel_dim < panel_dim_max, then we zero those unused rows. */ \ if ( panel_dim < panel_dim_max ) \ { \ const dim_t i = panel_dim; \ const dim_t m_edge = panel_dim_max - panel_dim; \ const dim_t n_edge = panel_len_max; \ ctype* restrict p_edge = p_use + (i )*1; \ \ PASTEMAC(ch,set0s_mxn) \ ( \ m_edge, \ n_edge, \ p_edge, 1, ldp \ ); \ } \ \ /* If panel_len < panel_len_max, then we zero those unused columns. */ \ if ( panel_len < panel_len_max ) \ { \ const dim_t j = panel_len; \ const dim_t m_edge = panel_dim_max; \ const dim_t n_edge = panel_len_max - panel_len; \ ctype* restrict p_edge = p_use + (j )*ldp; \ \ PASTEMAC(ch,set0s_mxn) \ ( \ m_edge, \ n_edge, \ p_edge, 1, ldp \ ); \ } \ } \ \ /* if ( !row_stored ) \ PASTEMAC(ch,fprintm)( stdout, "packm_var1: a packed", panel_dim_max, panel_len_max, \ p_use, rs_p, cs_p, "%5.2f", "" ); \ else \ PASTEMAC(ch,fprintm)( stdout, "packm_var1: b packed", panel_len_max, panel_dim_max, \ p_use, rs_p, cs_p, "%5.2f", "" ); \ */ \ \ p_begin += ps_p; \ } \ } //INSERT_GENTFUNC_BASIC0( packm_var1 ) GENTFUNC( float, s, packm_var2 ) GENTFUNC( double, d, packm_var2 ) GENTFUNC( scomplex, c, packm_var2 ) GENTFUNC( dcomplex, z, packm_var2 ) blis-0.9.0/addon/gemmd/bao_packm_cxk.c000066400000000000000000000135431422157504600175700ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENTFUNC #define GENTFUNC( ctype, ch, opname ) \ \ void PASTECH2(bao_,ch,opname) \ ( \ conj_t conja, \ pack_t schema, \ dim_t panel_dim, \ dim_t panel_dim_max, \ dim_t panel_len, \ dim_t panel_len_max, \ ctype* kappa, \ ctype* d, inc_t incd, \ ctype* a, inc_t inca, inc_t lda, \ ctype* p, inc_t ldp, \ cntx_t* cntx \ ) \ { \ /* Note that we use panel_dim_max, not panel_dim, to query the packm kernel function pointer. This means that we always use the same kernel, even for edge cases. */ \ num_t dt = PASTEMAC(ch,type); \ l1mkr_t ker_id = panel_dim_max; \ \ PASTECH2(ch,opname,_ker_ft) f; \ \ /* Query the context for the packm kernel corresponding to the current panel dimension, or kernel id. If the id is invalid, the function will return NULL. */ \ f = bli_cntx_get_packm_ker_dt( dt, ker_id, cntx ); \ \ /* If there exists a kernel implementation for the micro-panel dimension provided, we invoke the implementation. Otherwise, we use scal2m. */ \ /* NOTE: We've disabled calling packm micro-kernels from the context for this implementation. To re-enable, change FALSE to TRUE in the conditional below. */ \ if ( f != NULL && FALSE ) \ { \ f \ ( \ conja, \ schema, \ panel_dim, \ panel_len, \ panel_len_max, \ kappa, \ a, inca, lda, \ p, ldp, \ cntx \ ); \ } \ else \ { \ /* NOTE: We assume here that kappa = 1 and therefore ignore it. If we're wrong, this will get someone's attention. */ \ if ( !PASTEMAC(ch,eq1)( *kappa ) ) \ bli_abort(); \ \ if ( d == NULL ) \ { \ /* Perform the packing, taking conja into account. */ \ if ( bli_is_conj( conja ) ) \ { \ for ( dim_t l = 0; l < panel_len; ++l ) \ { \ for ( dim_t i = 0; i < panel_dim; ++i ) \ { \ ctype* ali = a + (l )*lda + (i )*inca; \ ctype* pli = p + (l )*ldp + (i )*1; \ \ PASTEMAC(ch,copyjs)( *ali, *pli ); \ } \ } \ } \ else \ { \ for ( dim_t l = 0; l < panel_len; ++l ) \ { \ for ( dim_t i = 0; i < panel_dim; ++i ) \ { \ ctype* ali = a + (l )*lda + (i )*inca; \ ctype* pli = p + (l )*ldp + (i )*1; \ \ PASTEMAC(ch,copys)( *ali, *pli ); \ } \ } \ } \ } \ else /* if ( d != NULL ) */ \ { \ /* Perform the packing, taking conja into account. */ \ if ( bli_is_conj( conja ) ) \ { \ for ( dim_t l = 0; l < panel_len; ++l ) \ { \ for ( dim_t i = 0; i < panel_dim; ++i ) \ { \ ctype* ali = a + (l )*lda + (i )*inca; \ ctype* dl = d + (l )*incd; \ ctype* pli = p + (l )*ldp + (i )*1; \ \ /* Note that ali must be the second operand here since that is what is conjugated by scal2js. */ \ PASTEMAC(ch,scal2js)( *dl, *ali, *pli ); \ } \ } \ } \ else \ { \ for ( dim_t l = 0; l < panel_len; ++l ) \ { \ for ( dim_t i = 0; i < panel_dim; ++i ) \ { \ ctype* ali = a + (l )*lda + (i )*inca; \ ctype* dl = d + (l )*incd; \ ctype* pli = p + (l )*ldp + (i )*1; \ \ PASTEMAC(ch,scal2s)( *ali, *dl, *pli ); \ } \ } \ } \ } \ \ /* If panel_dim < panel_dim_max, then we zero those unused rows. */ \ if ( panel_dim < panel_dim_max ) \ { \ const dim_t i = panel_dim; \ const dim_t m_edge = panel_dim_max - panel_dim; \ const dim_t n_edge = panel_len_max; \ ctype* restrict p_edge = p + (i )*1; \ \ PASTEMAC(ch,set0s_mxn) \ ( \ m_edge, \ n_edge, \ p_edge, 1, ldp \ ); \ } \ \ /* If panel_len < panel_len_max, then we zero those unused columns. */ \ if ( panel_len < panel_len_max ) \ { \ const dim_t j = panel_len; \ const dim_t m_edge = panel_dim_max; \ const dim_t n_edge = panel_len_max - panel_len; \ ctype* restrict p_edge = p + (j )*ldp; \ \ PASTEMAC(ch,set0s_mxn) \ ( \ m_edge, \ n_edge, \ p_edge, 1, ldp \ ); \ } \ } \ } //INSERT_GENTFUNC_BASIC0( packm_cxk ) GENTFUNC( float, s, packm_cxk ) GENTFUNC( double, d, packm_cxk ) GENTFUNC( scomplex, c, packm_cxk ) GENTFUNC( dcomplex, z, packm_cxk ) blis-0.9.0/addon/gemmd/bao_packm_cxk.h000066400000000000000000000043721422157504600175750ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #undef GENTPROT #define GENTPROT( ctype, ch, varname ) \ \ void PASTECH2(bao_,ch,varname) \ ( \ conj_t conja, \ pack_t schema, \ dim_t panel_dim, \ dim_t panel_dim_max, \ dim_t panel_len, \ dim_t panel_len_max, \ ctype* kappa, \ ctype* d, inc_t incd, \ ctype* a, inc_t inca, inc_t lda, \ ctype* p, inc_t ldp, \ cntx_t* cntx \ ); //INSERT_GENTPROT_BASIC0( packm_cxk ) GENTPROT( float, s, packm_cxk ) GENTPROT( double, d, packm_cxk ) GENTPROT( scomplex, c, packm_cxk ) GENTPROT( dcomplex, z, packm_cxk ) blis-0.9.0/addon/gemmd/gemmd.h000066400000000000000000000037431422157504600161060ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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 copyright holder(s) nor the names 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 COPYRIGHT HOLDER 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. */ #ifndef GEMMD_H #define GEMMD_H // This header should contain (or #include) any definitions that must be // folded into blis.h. #include "bao_gemmd.h" #include "bao_gemmd_check.h" #include "bao_gemmd_var.h" #include "bao_l3_packm_a.h" #include "bao_l3_packm_b.h" #include "bao_l3_packm_var.h" #include "bao_packm_cxk.h" #include "bao_l3_decor.h" #endif blis-0.9.0/addon/gemmd/thread/000077500000000000000000000000001422157504600161045ustar00rootroot00000000000000blis-0.9.0/addon/gemmd/thread/bao_l3_decor.h000066400000000000000000000050411422157504600205700ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2021, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_SBX_L3_DECOR_H #define BLIS_SBX_L3_DECOR_H // -- sup definitions ---------------------------------------------------------- // Level-3 sup internal function type. typedef void (*l3sbxint_t) ( obj_t* alpha, obj_t* a, obj_t* d, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, rntm_t* rntm, thrinfo_t* thread ); // Level-3 sup thread decorator prototype. void bao_l3_thread_decorator ( l3sbxint_t func, opid_t family, obj_t* alpha, obj_t* a, obj_t* d, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, rntm_t* rntm ); // Include definitions specific to the method of multithreading. #include "bao_l3_decor_single.h" #include "bao_l3_decor_openmp.h" #include "bao_l3_decor_pthreads.h" #endif blis-0.9.0/addon/gemmd/thread/bao_l3_decor_openmp.c000066400000000000000000000117031422157504600221430ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2021, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #ifdef BLIS_ENABLE_OPENMP // Define a dummy thread entry function, which is needed in the pthreads // version, so that when building Windows DLLs (with OpenMP enabled or with // no multithreading) we don't risk having an unresolved symbol. void* bao_l3_thread_entry( void* data_void ) { return NULL; } //#define PRINT_THRINFO void bao_l3_thread_decorator ( l3sbxint_t func, opid_t family, obj_t* alpha, obj_t* a, obj_t* d, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, rntm_t* rntm ) { // Query the total number of threads from the rntm_t object. const dim_t n_threads = bli_rntm_num_threads( rntm ); // NOTE: The sba was initialized in bli_init(). // Check out an array_t from the small block allocator. This is done // with an internal lock to ensure only one application thread accesses // the sba at a time. bli_sba_checkout_array() will also automatically // resize the array_t, if necessary. array_t* restrict array = bli_sba_checkout_array( n_threads ); // Access the pool_t* for thread 0 and embed it into the rntm. We do // this up-front only so that we have the rntm_t.sba_pool field // initialized and ready for the global communicator creation below. bli_sba_rntm_set_pool( 0, array, rntm ); // Set the packing block allocator field of the rntm. This will be // inherited by all of the child threads when they make local copies of // the rntm below. bli_pba_rntm_set_pba( rntm ); // Allcoate a global communicator for the root thrinfo_t structures. thrcomm_t* restrict gl_comm = bli_thrcomm_create( rntm, n_threads ); _Pragma( "omp parallel num_threads(n_threads)" ) { // Create a thread-local copy of the master thread's rntm_t. This is // necessary since we want each thread to be able to track its own // small block pool_t as it executes down the function stack. rntm_t rntm_l = *rntm; rntm_t* restrict rntm_p = &rntm_l; // Query the thread's id from OpenMP. const dim_t tid = omp_get_thread_num(); // Check for a somewhat obscure OpenMP thread-mistmatch issue. // NOTE: This calls the same function used for the conventional/large // code path. bli_l3_thread_decorator_thread_check( n_threads, tid, gl_comm, rntm_p ); // Use the thread id to access the appropriate pool_t* within the // array_t, and use it to set the sba_pool field within the rntm_t. // If the pool_t* element within the array_t is NULL, it will first // be allocated/initialized. bli_sba_rntm_set_pool( tid, array, rntm_p ); thrinfo_t* thread = NULL; // Create the root node of the thread's thrinfo_t structure. bli_l3_sup_thrinfo_create_root( tid, gl_comm, rntm_p, &thread ); func ( alpha, a, d, b, beta, c, cntx, rntm_p, thread ); // Free the current thread's thrinfo_t structure. bli_l3_sup_thrinfo_free( rntm_p, thread ); } // We shouldn't free the global communicator since it was already freed // by the global communicator's chief thread in bli_l3_thrinfo_free() // (called from the thread entry function). // Check the array_t back into the small block allocator. Similar to the // check-out, this is done using a lock embedded within the sba to ensure // mutual exclusion. bli_sba_checkin_array( array ); } #endif blis-0.9.0/addon/gemmd/thread/bao_l3_decor_openmp.h000066400000000000000000000035101422157504600221450ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2021, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_SBX_L3_DECOR_OPENMP_H #define BLIS_SBX_L3_DECOR_OPENMP_H // Definitions specific to situations when OpenMP multithreading is enabled. #ifdef BLIS_ENABLE_OPENMP #endif #endif blis-0.9.0/addon/gemmd/thread/bao_l3_decor_pthreads.c000066400000000000000000000157121422157504600224630ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2021, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #ifdef BLIS_ENABLE_PTHREADS // A data structure to assist in passing operands to additional threads. typedef struct thread_data { l3sbxint_t func; opid_t family; obj_t* alpha; obj_t* a; obj_t* d; obj_t* b; obj_t* beta; obj_t* c; cntx_t* cntx; rntm_t* rntm; dim_t tid; thrcomm_t* gl_comm; array_t* array; } thread_data_t; // Entry point function for additional threads. void* bao_l3_thread_entry( void* data_void ) { thread_data_t* data = data_void; l3sbxint_t func = data->func; opid_t family = data->family; obj_t* alpha = data->alpha; obj_t* a = data->a; obj_t* d = data->d; obj_t* b = data->b; obj_t* beta = data->beta; obj_t* c = data->c; cntx_t* cntx = data->cntx; rntm_t* rntm = data->rntm; dim_t tid = data->tid; array_t* array = data->array; thrcomm_t* gl_comm = data->gl_comm; ( void )family; // Create a thread-local copy of the master thread's rntm_t. This is // necessary since we want each thread to be able to track its own // small block pool_t as it executes down the function stack. rntm_t rntm_l = *rntm; rntm_t* restrict rntm_p = &rntm_l; // Use the thread id to access the appropriate pool_t* within the // array_t, and use it to set the sba_pool field within the rntm_t. // If the pool_t* element within the array_t is NULL, it will first // be allocated/initialized. bli_sba_rntm_set_pool( tid, array, rntm_p ); thrinfo_t* thread = NULL; // Create the root node of the current thread's thrinfo_t structure. bli_l3_sup_thrinfo_create_root( tid, gl_comm, rntm_p, &thread ); func ( alpha, a, d, b, beta, c, cntx, rntm_p, thread ); // Free the current thread's thrinfo_t structure. bli_l3_sup_thrinfo_free( rntm_p, thread ); return NULL; } void bao_l3_thread_decorator ( l3sbxint_t func, opid_t family, obj_t* alpha, obj_t* a, obj_t* d, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, rntm_t* rntm ) { err_t r_val; // Query the total number of threads from the context. const dim_t n_threads = bli_rntm_num_threads( rntm ); // NOTE: The sba was initialized in bli_init(). // Check out an array_t from the small block allocator. This is done // with an internal lock to ensure only one application thread accesses // the sba at a time. bli_sba_checkout_array() will also automatically // resize the array_t, if necessary. array_t* restrict array = bli_sba_checkout_array( n_threads ); // Access the pool_t* for thread 0 and embed it into the rntm. We do // this up-front only so that we have the rntm_t.sba_pool field // initialized and ready for the global communicator creation below. bli_sba_rntm_set_pool( 0, array, rntm ); // Set the packing block allocator field of the rntm. This will be // inherited by all of the child threads when they make local copies of // the rntm below. bli_pba_rntm_set_pba( rntm ); // Allocate a global communicator for the root thrinfo_t structures. thrcomm_t* restrict gl_comm = bli_thrcomm_create( rntm, n_threads ); // Allocate an array of pthread objects and auxiliary data structs to pass // to the thread entry functions. #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_l3_thread_decorator().pth: " ); #endif bli_pthread_t* pthreads = bli_malloc_intl( sizeof( bli_pthread_t ) * n_threads, &r_val ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_l3_thread_decorator().pth: " ); #endif thread_data_t* datas = bli_malloc_intl( sizeof( thread_data_t ) * n_threads, &r_val ); // NOTE: We must iterate backwards so that the chief thread (thread id 0) // can spawn all other threads before proceeding with its own computation. for ( dim_t tid = n_threads - 1; 0 <= tid; tid-- ) { // Set up thread data for additional threads (beyond thread 0). datas[tid].func = func; datas[tid].family = family; datas[tid].alpha = alpha; datas[tid].a = a; datas[tid].d = d; datas[tid].b = b; datas[tid].beta = beta; datas[tid].c = c; datas[tid].cntx = cntx; datas[tid].rntm = rntm; datas[tid].tid = tid; datas[tid].gl_comm = gl_comm; datas[tid].array = array; // Spawn additional threads for ids greater than 1. if ( tid != 0 ) bli_pthread_create( &pthreads[tid], NULL, &bao_l3_thread_entry, &datas[tid] ); else bao_l3_thread_entry( ( void* )(&datas[0]) ); } // We shouldn't free the global communicator since it was already freed // by the global communicator's chief thread in bli_l3_thrinfo_free() // (called from the thread entry function). // Thread 0 waits for additional threads to finish. for ( dim_t tid = 1; tid < n_threads; tid++ ) { bli_pthread_join( pthreads[tid], NULL ); } // Check the array_t back into the small block allocator. Similar to the // check-out, this is done using a lock embedded within the sba to ensure // mutual exclusion. bli_sba_checkin_array( array ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_l3_thread_decorator().pth: " ); #endif bli_free_intl( pthreads ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_l3_thread_decorator().pth: " ); #endif bli_free_intl( datas ); } #endif blis-0.9.0/addon/gemmd/thread/bao_l3_decor_pthreads.h000066400000000000000000000036351422157504600224710ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2021, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_SBX_L3_DECOR_PTHREADS_H #define BLIS_SBX_L3_DECOR_PTHREADS_H // Definitions specific to situations when POSIX multithreading is enabled. #ifdef BLIS_ENABLE_PTHREADS // Thread entry point prototype. void* bao_l3_thread_entry( void* data_void ); #endif #endif blis-0.9.0/addon/gemmd/thread/bao_l3_decor_single.c000066400000000000000000000113641422157504600221310ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2021, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #ifndef BLIS_ENABLE_MULTITHREADING #define SKIP_THRINFO_TREE void bao_l3_thread_decorator ( l3sbxint_t func, opid_t family, //pack_t schema_a, //pack_t schema_b, obj_t* alpha, obj_t* a, obj_t* d, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, rntm_t* rntm ) { // For sequential execution, we use only one thread. const dim_t n_threads = 1; // NOTE: The sba was initialized in bli_init(). // Check out an array_t from the small block allocator. This is done // with an internal lock to ensure only one application thread accesses // the sba at a time. bli_sba_checkout_array() will also automatically // resize the array_t, if necessary. array_t* restrict array = bli_sba_checkout_array( n_threads ); // Access the pool_t* for thread 0 and embed it into the rntm. bli_sba_rntm_set_pool( 0, array, rntm ); // Set the packing block allocator field of the rntm. bli_pba_rntm_set_pba( rntm ); #ifndef SKIP_THRINFO_TREE // Allcoate a global communicator for the root thrinfo_t structures. thrcomm_t* restrict gl_comm = bli_thrcomm_create( rntm, n_threads ); #endif { // NOTE: We don't need to create another copy of the rntm_t since // it was already copied in one of the high-level oapi functions. rntm_t* restrict rntm_p = rntm; // There is only one thread id (for the thief thread). const dim_t tid = 0; // Use the thread id to access the appropriate pool_t* within the // array_t, and use it to set the sba_pool field within the rntm_t. // If the pool_t* element within the array_t is NULL, it will first // be allocated/initialized. // NOTE: This is commented out because, in the single-threaded case, // this is redundant since it's already been done above. //bli_sba_rntm_set_pool( tid, array, rntm_p ); #ifndef SKIP_THRINFO_TREE thrinfo_t* thread = NULL; // Create the root node of the thread's thrinfo_t structure. bli_l3_sup_thrinfo_create_root( tid, gl_comm, rntm_p, &thread ); #else // This optimization allows us to use one of the global thrinfo_t // objects for single-threaded execution rather than grow one from // scratch. The key is that bli_thrinfo_sup_grow(), which is called // from within the variants, will immediately return if it detects // that the thrinfo_t* passed into it is either // &BLIS_GEMM_SINGLE_THREADED or &BLIS_PACKM_SINGLE_THREADED. thrinfo_t* thread = &BLIS_GEMM_SINGLE_THREADED; ( void )tid; #endif func ( alpha, a, d, b, beta, c, cntx, rntm_p, thread ); #ifndef SKIP_THRINFO_TREE // Free the current thread's thrinfo_t structure. bli_l3_sup_thrinfo_free( rntm_p, thread ); #endif } // We shouldn't free the global communicator since it was already freed // by the global communicator's chief thread in bli_l3_thrinfo_free() // (called above). // Check the array_t back into the small block allocator. Similar to the // check-out, this is done using a lock embedded within the sba to ensure // mutual exclusion. bli_sba_checkin_array( array ); } #endif blis-0.9.0/addon/gemmd/thread/bao_l3_decor_single.h000066400000000000000000000035131422157504600221330ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2021, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_SBX_L3_DECOR_SINGLE_H #define BLIS_SBX_L3_DECOR_SINGLE_H // Definitions specific to situations when multithreading is disabled. #ifndef BLIS_ENABLE_MULTITHREADING #endif #endif blis-0.9.0/blastest/000077500000000000000000000000001422157504600143005ustar00rootroot00000000000000blis-0.9.0/blastest/Makefile000066400000000000000000000165471422157504600157550ustar00rootroot00000000000000# # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2014, The University of Texas at Austin # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # # # Makefile # # Field G. Van Zee # # Makefile for BLAS test drivers. # # # --- Makefile PHONY target definitions ---------------------------------------- # .PHONY: all f2c bin \ clean cleanf2c cleanobj cleanbin cleanout \ check-env check-env-mk check-env-fragments check-env-make-defs \ run check # # --- Determine makefile fragment location ------------------------------------- # # Comments: # - DIST_PATH is assumed to not exist if BLIS_INSTALL_PATH is given. # - We must use recursively expanded assignment for LIB_PATH and INC_PATH in # the second case because CONFIG_NAME is not yet set. ifneq ($(strip $(BLIS_INSTALL_PATH)),) LIB_PATH := $(BLIS_INSTALL_PATH)/lib INC_PATH := $(BLIS_INSTALL_PATH)/include/blis SHARE_PATH := $(BLIS_INSTALL_PATH)/share/blis else DIST_PATH := .. LIB_PATH = ../lib/$(CONFIG_NAME) INC_PATH = ../include/$(CONFIG_NAME) SHARE_PATH := .. endif # # --- Include common makefile definitions -------------------------------------- # # Include the common makefile fragment. -include $(SHARE_PATH)/common.mk # # --- General build definitions ------------------------------------------------ # TEST_OBJ_PATH := obj F2C_LIB := libf2c.a F2C_PATH := f2c DRIVER_PATH := src BLIS_H_PATH := $(BUILD_PATH)/$(BASE_INC_PATH) INPUT_DIR := input # Gather all local object files. F2C_OBJS := $(sort $(patsubst $(F2C_PATH)/%.c, \ $(TEST_OBJ_PATH)/%.o, \ $(wildcard $(F2C_PATH)/*.c))) DRIVER_OBJS := $(sort $(patsubst $(DRIVER_PATH)/%.c, \ $(TEST_OBJ_PATH)/%.o, \ $(wildcard $(DRIVER_PATH)/*.c))) # Extract base names for each test driver file. DRIVER_BASES := $(basename $(notdir $(DRIVER_OBJS))) # Binary executable names. DRIVER_BINS := $(addsuffix .x,$(DRIVER_BASES)) # Binary run-rule names DRIVER_BINS_R := $(addprefix run-,$(DRIVER_BASES)) # Filter level-1, level-2, and level-3 names to different variables. DRIVER1_BASES := $(filter %1,$(DRIVER_BASES)) DRIVER2_BASES := $(filter %2,$(DRIVER_BASES)) DRIVER3_BASES := $(filter %3,$(DRIVER_BASES)) # The location of the script that checks the BLAS test output. #BLASTEST_CHECK := $(DIST_PATH)/$(BUILD_DIR)/check-blastest.sh # Override the value of CINCFLAGS so that the value of CFLAGS returned by # get-user-cflags-for() is not cluttered up with include paths needed only # while building BLIS. CINCFLAGS := -I$(INC_PATH) # Use the CFLAGS for the configuration family. CFLAGS := $(call get-user-cflags-for,$(CONFIG_NAME)) # Suppress warnings about uninitialized functions, add local header # paths and the path to blis.h to CFLAGS. CFLAGS += -Wno-maybe-uninitialized -Wno-parentheses -Wfatal-errors \ -I$(F2C_PATH) \ -I$(INC_PATH) -DHAVE_BLIS_H # Locate the libblis library to which we will link. #LIBBLIS_LINK := $(LIB_PATH)/$(LIBBLIS_L) # Override the location of the check-blastest.sh script. #BLASTEST_CHECK := ./check-blastest.sh TESTSUITE_WRAPPER ?= # # --- Targets/rules ------------------------------------------------------------ # # --- Primary targets --- all: check-env f2c bin f2c: check-env $(F2C_LIB) bin: check-env $(DRIVER_BINS) # --Object file rules -- $(TEST_OBJ_PATH)/%.o: $(F2C_PATH)/%.c ifeq ($(ENABLE_VERBOSE),yes) $(CC) $(CFLAGS) -c $< -o $@ else @echo "Compiling $@" @$(CC) $(CFLAGS) -c $< -o $@ endif $(TEST_OBJ_PATH)/%.o: $(DRIVER_PATH)/%.c ifeq ($(ENABLE_VERBOSE),yes) $(CC) $(CFLAGS) -c $< -o $@ else @echo "Compiling $@" @$(CC) $(CFLAGS) -c $< -o $@ endif # -- libf2c library archive rule -- $(F2C_LIB): $(F2C_OBJS) ifeq ($(ENABLE_VERBOSE),yes) $(AR) $(ARFLAGS) $@ $? $(RANLIB) $@ else @echo "Archiving $@" @$(AR) $(ARFLAGS) $@ $? @$(RANLIB) $@ endif # -- Executable file rules -- # first argument: the base name of the BLAS test driver. define make-blat-rule $(1).x: $(TEST_OBJ_PATH)/$(1).o $(F2C_LIB) $(LIBBLIS_LINK) ifeq ($(ENABLE_VERBOSE),yes) $(LINKER) $(TEST_OBJ_PATH)/$(1).o $(F2C_OBJS) $(LIBBLIS_LINK) $(LDFLAGS) -o $$@ else @echo "Linking $$@ against '$(F2C_LIB) $(LIBBLIS_LINK) $(LDFLAGS)'" @$(LINKER) $(TEST_OBJ_PATH)/$(1).o $(F2C_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $$@ endif endef # Instantiate the rule above for each driver file. $(foreach name, $(DRIVER_BASES), $(eval $(call make-blat-rule,$(name)))) # -- Test run rules -- run: $(DRIVER_BINS_R) # A rule to run ?blat1.x driver files. define make-run-blat1-rule run-$(1): $(1).x ifeq ($(ENABLE_VERBOSE),yes) $(TESTSUITE_WRAPPER) ./$(1).x > out.$(1) else @echo "Running $(1).x > 'out.$(1)'" @$(TESTSUITE_WRAPPER) ./$(1).x > out.$(1) endif endef # Instantiate the rule above for each level-1 driver file. $(foreach name, $(DRIVER1_BASES), $(eval $(call make-run-blat1-rule,$(name)))) # A rule to run ?blat2.x and ?blat3.x driver files. define make-run-blat23-rule run-$(1): $(1).x ifeq ($(ENABLE_VERBOSE),yes) $(TESTSUITE_WRAPPER) ./$(1).x < $(INPUT_DIR)/$(1).in else @echo "Running $(1).x < '$(INPUT_DIR)/$(1).in' (output to 'out.$(1)')" @$(TESTSUITE_WRAPPER) ./$(1).x < $(INPUT_DIR)/$(1).in endif endef # Instantiate the rule above for each level-2 driver file. $(foreach name, $(DRIVER2_BASES), $(eval $(call make-run-blat23-rule,$(name)))) # Instantiate the rule above for each level-3 driver file. $(foreach name, $(DRIVER3_BASES), $(eval $(call make-run-blat23-rule,$(name)))) check: run ifeq ($(ENABLE_VERBOSE),yes) - $(BLASTEST_CHECK) else @- $(BLASTEST_CHECK) endif # -- Clean rules -- cleanf2c: - $(RM_F) $(F2C_OBJS) $(F2C_LIB) cleanobj: - $(RM_F) $(DRIVER_OBJS) cleanbin: - $(RM_F) $(DRIVER_BINS) cleanout: - $(RM_F) $(addprefix out.,$(DRIVER_BASES)) clean: cleanf2c cleanobj cleanbin cleanout blis-0.9.0/blastest/check-blastest.sh000077500000000000000000000042141422157504600175340ustar00rootroot00000000000000#!/bin/sh # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2018, The University of Texas at Austin # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # script_name=${0##*/} ansi_red="\033[0;31m" ansi_green="\033[0;32m" ansi_normal="\033[0m" passmsg="All BLAS tests passed!" failmsg0="At least one BLAS test failed. :(" failmsg1="Please see out.* files for details." grep -q '\*\*\*\*' ./out.* if [ $? -eq 0 ]; then printf "${ansi_red}""${script_name}: ${failmsg0}""${ansi_normal}\n" printf "${ansi_red}""${script_name}: ${failmsg1}""${ansi_normal}\n" exit 1 else printf "${ansi_green}""${script_name}: ${passmsg}""${ansi_normal}\n" exit 0 fi blis-0.9.0/blastest/f2c/000077500000000000000000000000001422157504600147525ustar00rootroot00000000000000blis-0.9.0/blastest/f2c/abs.c000066400000000000000000000041311422157504600156620ustar00rootroot00000000000000/**************************************************************** Copyright 1990 - 1997 by AT&T, Lucent Technologies and Bellcore. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that the copyright notice and this permission notice and warranty disclaimer appear in supporting documentation, and that the names of AT&T, Bell Laboratories, Lucent or Bellcore or any of their entities not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. AT&T, Lucent and Bellcore disclaim all warranties with regard to this software, including all implied warranties of merchantability and fitness. In no event shall AT&T, Lucent or Bellcore be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software. ****************************************************************/ #include "f2c.h" #ifdef __cplusplus extern "C" { #endif /* Integer */ shortint h_abs(const shortint *x) { return ( shortint )( *x >= 0 ? (*x) : (- *x) ); //return ( shortint )abs( ( int )*x ); } integer i_abs(const integer *x) { return ( integer )( *x >= 0 ? (*x) : (- *x) ); //return ( integer )abs( ( int )*x ); } /* Double */ double r_abs(real *x) { return ( double )( *x >= 0 ? (*x) : (- *x) ); //return ( double )fabsf( ( float )*x ); } double d_abs(const doublereal *x) { return ( double )( *x >= 0 ? (*x) : (- *x) ); //return ( double )fabs( ( double )*x ); } /* Complex */ double c_abs(const complex *z) { return ( double )hypot(z->r, z->i); } double z_abs(const doublecomplex *z) { return ( double )hypot(z->r, z->i); } #ifdef __cplusplus } #endif blis-0.9.0/blastest/f2c/acos.c000066400000000000000000000026441422157504600160510ustar00rootroot00000000000000/**************************************************************** Copyright 1990 - 1997 by AT&T, Lucent Technologies and Bellcore. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that the copyright notice and this permission notice and warranty disclaimer appear in supporting documentation, and that the names of AT&T, Bell Laboratories, Lucent or Bellcore or any of their entities not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. AT&T, Lucent and Bellcore disclaim all warranties with regard to this software, including all implied warranties of merchantability and fitness. In no event shall AT&T, Lucent or Bellcore be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software. ****************************************************************/ #include "f2c.h" #ifdef __cplusplus extern "C" { #endif double r_acos(real *x) { return( acos(*x) ); } double d_acos(const doublereal *x) { return( acos(*x) ); } #ifdef __cplusplus } #endif blis-0.9.0/blastest/f2c/arith.h000066400000000000000000000042761422157504600162430ustar00rootroot00000000000000/**************************************************************** Copyright 1990 - 1997 by AT&T, Lucent Technologies and Bellcore. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that the copyright notice and this permission notice and warranty disclaimer appear in supporting documentation, and that the names of AT&T, Bell Laboratories, Lucent or Bellcore or any of their entities not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. AT&T, Lucent and Bellcore disclaim all warranties with regard to this software, including all implied warranties of merchantability and fitness. In no event shall AT&T, Lucent or Bellcore be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software. ****************************************************************/ #ifndef F2C_ARITH_H #define F2C_ARITH_H #include #include #ifdef _MSC_VER #define isnan _isnan #define isinf(x) (!_finite(x)) #endif #ifndef isnan # define isnan(x) \ (sizeof (x) == sizeof (long double) ? isnan_ld (x) \ : sizeof (x) == sizeof (double) ? isnan_d (x) \ : isnan_f (x)) static inline int isnan_f (float x) { return x != x; } static inline int isnan_d (double x) { return x != x; } static inline int isnan_ld (long double x) { return x != x; } #endif #ifndef isinf # define isinf(x) \ (sizeof (x) == sizeof (long double) ? isinf_ld (x) \ : sizeof (x) == sizeof (double) ? isinf_d (x) \ : isinf_f (x)) static inline int isinf_f (float x) { return !isnan (x) && isnan (x - x); } static inline int isinf_d (double x) { return !isnan (x) && isnan (x - x); } static inline int isinf_ld (long double x) { return !isnan (x) && isnan (x - x); } #endif #ifndef signbit #define signbit(x) (((x) < 0)? 1 : 0) #endif #endif blis-0.9.0/blastest/f2c/asin.c000066400000000000000000000026441422157504600160560ustar00rootroot00000000000000/**************************************************************** Copyright 1990 - 1997 by AT&T, Lucent Technologies and Bellcore. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that the copyright notice and this permission notice and warranty disclaimer appear in supporting documentation, and that the names of AT&T, Bell Laboratories, Lucent or Bellcore or any of their entities not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. AT&T, Lucent and Bellcore disclaim all warranties with regard to this software, including all implied warranties of merchantability and fitness. In no event shall AT&T, Lucent or Bellcore be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software. ****************************************************************/ #include "f2c.h" #ifdef __cplusplus extern "C" { #endif double r_asin(real *x) { return( asin(*x) ); } double d_asin(const doublereal *x) { return( asin(*x) ); } #ifdef __cplusplus } #endif blis-0.9.0/blastest/f2c/atan.c000066400000000000000000000026441422157504600160470ustar00rootroot00000000000000/**************************************************************** Copyright 1990 - 1997 by AT&T, Lucent Technologies and Bellcore. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that the copyright notice and this permission notice and warranty disclaimer appear in supporting documentation, and that the names of AT&T, Bell Laboratories, Lucent or Bellcore or any of their entities not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. AT&T, Lucent and Bellcore disclaim all warranties with regard to this software, including all implied warranties of merchantability and fitness. In no event shall AT&T, Lucent or Bellcore be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software. ****************************************************************/ #include "f2c.h" #ifdef __cplusplus extern "C" { #endif double r_atan(real *x) { return( atan(*x) ); } double d_atan(const doublereal *x) { return( atan(*x) ); } #ifdef __cplusplus } #endif blis-0.9.0/blastest/f2c/atn2.c000066400000000000000000000027121422157504600157640ustar00rootroot00000000000000/**************************************************************** Copyright 1990 - 1997 by AT&T, Lucent Technologies and Bellcore. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that the copyright notice and this permission notice and warranty disclaimer appear in supporting documentation, and that the names of AT&T, Bell Laboratories, Lucent or Bellcore or any of their entities not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. AT&T, Lucent and Bellcore disclaim all warranties with regard to this software, including all implied warranties of merchantability and fitness. In no event shall AT&T, Lucent or Bellcore be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software. ****************************************************************/ #include "f2c.h" #ifdef __cplusplus extern "C" { #endif double r_atn2(real *x, real *y) { return( atan2(*x,*y) ); } double d_atn2(const doublereal *x, const doublereal *y) { return( atan2(*x,*y) ); } #ifdef __cplusplus } #endif blis-0.9.0/blastest/f2c/close.c000066400000000000000000000046101422157504600162240ustar00rootroot00000000000000/**************************************************************** Copyright 1990 - 1997 by AT&T, Lucent Technologies and Bellcore. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that the copyright notice and this permission notice and warranty disclaimer appear in supporting documentation, and that the names of AT&T, Bell Laboratories, Lucent or Bellcore or any of their entities not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. AT&T, Lucent and Bellcore disclaim all warranties with regard to this software, including all implied warranties of merchantability and fitness. In no event shall AT&T, Lucent or Bellcore be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software. ****************************************************************/ #include #include "f2c.h" #include "fio.h" #undef abs #undef min #undef max #include #if defined(NON_UNIX_STDIO) || defined(_MSC_VER) || defined(__MINGW32__) # include # define unlink remove #else # include #endif integer f_clos(cllist *a) { unit *b; if(a->cunit >= MXUNIT) return(0); b= &f__units[a->cunit]; if(b->ufd==NULL) goto done; if (b->uscrtch == 1) goto Delete; if (!a->csta) goto Keep; switch(*a->csta) { default: Keep: case 'k': case 'K': if(b->uwrt == 1) t_runc((alist *)a); if(b->ufnm) { fclose(b->ufd); free(b->ufnm); } break; case 'd': case 'D': Delete: fclose(b->ufd); if(b->ufnm) { unlink(b->ufnm); /*SYSDEP*/ free(b->ufnm); } } b->ufd=NULL; done: b->uend=0; b->ufnm=NULL; return(0); } void f_exit(void) { static int run = 0; int i; static cllist xx; /* Do not execute f_exit() twice */ if (run) return; run = 1; if (!xx.cerr) { xx.cerr=1; xx.csta=NULL; for(i=0;ii; r->r = z->r; r->i = -zi; } void r_cnjg(complex *r, complex *z) { real zi = z->i; r->r = z->r; r->i = -zi; } #ifdef __cplusplus } #endif blis-0.9.0/blastest/f2c/cos.c000066400000000000000000000033611422157504600157050ustar00rootroot00000000000000/**************************************************************** Copyright 1990 - 1997 by AT&T, Lucent Technologies and Bellcore. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that the copyright notice and this permission notice and warranty disclaimer appear in supporting documentation, and that the names of AT&T, Bell Laboratories, Lucent or Bellcore or any of their entities not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. AT&T, Lucent and Bellcore disclaim all warranties with regard to this software, including all implied warranties of merchantability and fitness. In no event shall AT&T, Lucent or Bellcore be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software. ****************************************************************/ #include "f2c.h" #ifdef __cplusplus extern "C" { #endif double r_cos(real *x) { return( cos(*x) ); } double d_cos(const doublereal *x) { return( cos(*x) ); } void c_cos(complex *r, complex *z) { double zi = z->i, zr = z->r; r->r = cos(zr) * cosh(zi); r->i = - sin(zr) * sinh(zi); } void z_cos(doublecomplex *r, doublecomplex *z) { double zi = z->i, zr = z->r; r->r = cos(zr) * cosh(zi); r->i = - sin(zr) * sinh(zi); } #ifdef __cplusplus } #endif blis-0.9.0/blastest/f2c/cosh.c000066400000000000000000000026451422157504600160610ustar00rootroot00000000000000/**************************************************************** Copyright 1990 - 1997 by AT&T, Lucent Technologies and Bellcore. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that the copyright notice and this permission notice and warranty disclaimer appear in supporting documentation, and that the names of AT&T, Bell Laboratories, Lucent or Bellcore or any of their entities not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. AT&T, Lucent and Bellcore disclaim all warranties with regard to this software, including all implied warranties of merchantability and fitness. In no event shall AT&T, Lucent or Bellcore be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software. ****************************************************************/ #include "f2c.h" #ifdef __cplusplus extern "C" { #endif double r_cosh(real *x) { return( cosh(*x) ); } double d_cosh(const doublereal *x) { return( cosh(*x) ); } #ifdef __cplusplus } #endif blis-0.9.0/blastest/f2c/dim.c000066400000000000000000000032611422157504600156710ustar00rootroot00000000000000/**************************************************************** Copyright 1990 - 1997 by AT&T, Lucent Technologies and Bellcore. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that the copyright notice and this permission notice and warranty disclaimer appear in supporting documentation, and that the names of AT&T, Bell Laboratories, Lucent or Bellcore or any of their entities not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. AT&T, Lucent and Bellcore disclaim all warranties with regard to this software, including all implied warranties of merchantability and fitness. In no event shall AT&T, Lucent or Bellcore be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software. ****************************************************************/ #include "f2c.h" #ifdef __cplusplus extern "C" { #endif shortint h_dim(const shortint *a, const shortint *b) { return( *a > *b ? *a - *b : 0); } integer i_dim(const integer *a, const integer *b) { return( *a > *b ? *a - *b : 0); } double r_dim(real *a, real *b) { return( *a > *b ? *a - *b : 0); } double d_dim(const doublereal *a, const doublereal *b) { return( *a > *b ? *a - *b : 0); } #ifdef __cplusplus } #endif blis-0.9.0/blastest/f2c/div.c000066400000000000000000000063631422157504600157100ustar00rootroot00000000000000/**************************************************************** Copyright 1990 - 1997 by AT&T, Lucent Technologies and Bellcore. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that the copyright notice and this permission notice and warranty disclaimer appear in supporting documentation, and that the names of AT&T, Bell Laboratories, Lucent or Bellcore or any of their entities not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. AT&T, Lucent and Bellcore disclaim all warranties with regard to this software, including all implied warranties of merchantability and fitness. In no event shall AT&T, Lucent or Bellcore be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software. ****************************************************************/ #include "f2c.h" #ifdef __cplusplus extern "C" { #endif void c_div(complex *c, complex *a, complex *b) { double ratio, den; double abr, abi, cr; if( (abr = b->r) < 0.) abr = - abr; if( (abi = b->i) < 0.) abi = - abi; if( abr <= abi ) { if(abi == 0) { #ifdef IEEE_COMPLEX_DIVIDE float af, bf; af = bf = abr; if (a->i != 0 || a->r != 0) af = 1.; c->i = c->r = af / bf; return; #else sig_die("complex division by zero", 1); #endif } ratio = (double)b->r / b->i ; den = b->i * (1 + ratio*ratio); cr = (a->r*ratio + a->i) / den; c->i = (a->i*ratio - a->r) / den; } else { ratio = (double)b->i / b->r ; den = b->r * (1 + ratio*ratio); cr = (a->r + a->i*ratio) / den; c->i = (a->i - a->r*ratio) / den; } c->r = cr; } void z_div(doublecomplex *c, doublecomplex *a, doublecomplex *b) { double ratio, den; double abr, abi, cr; if( (abr = b->r) < 0.) abr = - abr; if( (abi = b->i) < 0.) abi = - abi; if( abr <= abi ) { if(abi == 0) { #ifdef IEEE_COMPLEX_DIVIDE if (a->i != 0 || a->r != 0) abi = 1.; c->i = c->r = abi / abr; return; #else sig_die("complex division by zero", 1); #endif } ratio = b->r / b->i ; den = b->i * (1 + ratio*ratio); cr = (a->r*ratio + a->i) / den; c->i = (a->i*ratio - a->r) / den; } else { ratio = b->i / b->r ; den = b->r * (1 + ratio*ratio); cr = (a->r + a->i*ratio) / den; c->i = (a->i - a->r*ratio) / den; } c->r = cr; } #ifdef __cplusplus } #endif blis-0.9.0/blastest/f2c/dolio.c000066400000000000000000000025551422157504600162330ustar00rootroot00000000000000/**************************************************************** Copyright 1990 - 1997 by AT&T, Lucent Technologies and Bellcore. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that the copyright notice and this permission notice and warranty disclaimer appear in supporting documentation, and that the names of AT&T, Bell Laboratories, Lucent or Bellcore or any of their entities not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. AT&T, Lucent and Bellcore disclaim all warranties with regard to this software, including all implied warranties of merchantability and fitness. In no event shall AT&T, Lucent or Bellcore be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software. ****************************************************************/ #include #include "f2c.h" #include "fio.h" integer do_lio(ftnint *type, ftnint *number, char *ptr, ftnlen len) { return((*f__lioproc)(number,ptr,len,*type)); } blis-0.9.0/blastest/f2c/endfile.c000066400000000000000000000066221422157504600165320ustar00rootroot00000000000000/**************************************************************** Copyright 1990 - 1997 by AT&T, Lucent Technologies and Bellcore. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that the copyright notice and this permission notice and warranty disclaimer appear in supporting documentation, and that the names of AT&T, Bell Laboratories, Lucent or Bellcore or any of their entities not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. AT&T, Lucent and Bellcore disclaim all warranties with regard to this software, including all implied warranties of merchantability and fitness. In no event shall AT&T, Lucent or Bellcore be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software. ****************************************************************/ #include #include "f2c.h" #include "fio.h" #ifdef HAVE_FTRUNCATE #include #endif #undef abs #undef min #undef max #include "stdlib.h" #include "string.h" integer f_end(alist *a) { unit *b; FILE *tf; if(a->aunit>=MXUNIT || a->aunit<0) err(a->aerr,101,"endfile"); b = &f__units[a->aunit]; if(b->ufd==NULL) { char nbuf[10]; sprintf(nbuf,"fort.%ld",(long)a->aunit); if (tf = fopen(nbuf, f__w_mode[0])) fclose(tf); return(0); } b->uend=1; return(b->useek ? t_runc(a) : 0); } #if !defined(HAVE_FTRUNCATE) static int copy(FILE *from, register long len, FILE *to) { int len1; char buf[BUFSIZ]; while(fread(buf, len1 = len > BUFSIZ ? BUFSIZ : (int)len, 1, from)) { if (!fwrite(buf, len1, 1, to)) return 1; if ((len -= len1) <= 0) break; } return 0; } #endif /* !HAVE_FTRUNCATE */ int t_runc(alist *a) { OFF_T loc, len; unit *b; int rc; FILE *bf; #if !defined(HAVE_FTRUNCATE) FILE *tf; #endif b = &f__units[a->aunit]; if(b->url) return(0); /*don't truncate direct files*/ loc=FTELL(bf = b->ufd); FSEEK(bf,(OFF_T)0,SEEK_END); len=FTELL(bf); if (loc >= len || b->useek == 0) return(0); #ifndef HAVE_FTRUNCATE if (b->ufnm == NULL) return 0; rc = 0; fclose(b->ufd); if (!loc) { if (!(bf = fopen(b->ufnm, f__w_mode[b->ufmt]))) rc = 1; if (b->uwrt) b->uwrt = 1; goto done; } if (!(bf = fopen(b->ufnm, f__r_mode[0])) || !(tf = tmpfile())) { #ifdef NON_UNIX_STDIO bad: #endif rc = 1; goto done; } if (copy(bf, (long)loc, tf)) { bad1: rc = 1; goto done1; } if (!(bf = freopen(b->ufnm, f__w_mode[0], bf))) goto bad1; rewind(tf); if (copy(tf, (long)loc, bf)) goto bad1; b->uwrt = 1; b->urw = 2; #ifdef NON_UNIX_STDIO if (b->ufmt) { fclose(bf); if (!(bf = fopen(b->ufnm, f__w_mode[3]))) goto bad; FSEEK(bf,(OFF_T)0,SEEK_END); b->urw = 3; } #endif done1: fclose(tf); done: f__cf = b->ufd = bf; #else /* !HAVE_TRUNCATE */ if (b->urw & 2) fflush(b->ufd); /* necessary on some Linux systems */ rc = ftruncate(fileno(b->ufd), loc); /* The following FSEEK is unnecessary on some systems, */ /* but should be harmless. */ FSEEK(b->ufd, (OFF_T)0, SEEK_END); #endif /* HAVE_TRUNCATE */ if (rc) err(a->aerr,111,"endfile"); return 0; } blis-0.9.0/blastest/f2c/epsilon.c000066400000000000000000000026421422157504600165730ustar00rootroot00000000000000/**************************************************************** Copyright 1990 - 1997 by AT&T, Lucent Technologies and Bellcore. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that the copyright notice and this permission notice and warranty disclaimer appear in supporting documentation, and that the names of AT&T, Bell Laboratories, Lucent or Bellcore or any of their entities not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. AT&T, Lucent and Bellcore disclaim all warranties with regard to this software, including all implied warranties of merchantability and fitness. In no event shall AT&T, Lucent or Bellcore be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software. ****************************************************************/ #include "f2c.h" #include "float.h" #ifdef __cplusplus extern "C" { #endif real s_epsilon_( real* x ) { return FLT_EPSILON; } doublereal d_epsilon_( doublereal* x ) { return DBL_EPSILON; } #ifdef __cplusplus } #endif blis-0.9.0/blastest/f2c/err.c000066400000000000000000000153711422157504600157150ustar00rootroot00000000000000/**************************************************************** Copyright 1990 - 1997 by AT&T, Lucent Technologies and Bellcore. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that the copyright notice and this permission notice and warranty disclaimer appear in supporting documentation, and that the names of AT&T, Bell Laboratories, Lucent or Bellcore or any of their entities not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. AT&T, Lucent and Bellcore disclaim all warranties with regard to this software, including all implied warranties of merchantability and fitness. In no event shall AT&T, Lucent or Bellcore be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software. ****************************************************************/ #include #include #if defined(_MSC_VER) || defined(__MINGW32__) # include # include #else # ifdef HAVE_ISATTY # include # else # define isatty(x) 0 # endif #endif #include "f2c.h" #include "fio.h" #include "fmt.h" /* for struct syl */ /*global definitions*/ unit f__units[MXUNIT]; /*unit table*/ flag f__init; /*0 on entry, 1 after initializations*/ cilist *f__elist; /*active external io list*/ icilist *f__svic; /*active internal io list*/ flag f__reading; /*1 if reading, 0 if writing*/ flag f__cplus,f__cblank; const char *f__fmtbuf; flag f__external; /*1 if external io, 0 if internal */ int (*f__getn)(void); /* for formatted input */ void (*f__putn)(int); /* for formatted output */ int (*f__doed)(struct syl*, char*, ftnlen),(*f__doned)(struct syl*); int (*f__dorevert)(void),(*f__donewrec)(void),(*f__doend)(void); flag f__sequential; /*1 if sequential io, 0 if direct*/ flag f__formatted; /*1 if formatted io, 0 if unformatted*/ FILE *f__cf; /*current file*/ unit *f__curunit; /*current unit*/ int f__recpos; /*place in current record*/ OFF_T f__cursor, f__hiwater; int f__scale; char *f__icptr; /*error messages*/ const char *F_err[] = { "error in format", /* 100 */ "illegal unit number", /* 101 */ "formatted io not allowed", /* 102 */ "unformatted io not allowed", /* 103 */ "direct io not allowed", /* 104 */ "sequential io not allowed", /* 105 */ "can't backspace file", /* 106 */ "null file name", /* 107 */ "can't stat file", /* 108 */ "unit not connected", /* 109 */ "off end of record", /* 110 */ "truncation failed in endfile", /* 111 */ "incomprehensible list input", /* 112 */ "out of free space", /* 113 */ "unit not connected", /* 114 */ "read unexpected character", /* 115 */ "bad logical input field", /* 116 */ "bad variable type", /* 117 */ "bad namelist name", /* 118 */ "variable not in namelist", /* 119 */ "no end record", /* 120 */ "variable count incorrect", /* 121 */ "subscript for scalar variable", /* 122 */ "invalid array section", /* 123 */ "substring out of bounds", /* 124 */ "subscript out of bounds", /* 125 */ "can't read file", /* 126 */ "can't write file", /* 127 */ "'new' file exists", /* 128 */ "can't append to file", /* 129 */ "non-positive record number", /* 130 */ "nmLbuf overflow" /* 131 */ }; #define MAXERR (sizeof(F_err)/sizeof(char *)+100) #if defined(_MSC_VER) || defined(__MINGW32__) #undef isatty #define isatty _isatty #undef fileno #define fileno _fileno #endif int f__canseek(FILE *f) /*SYSDEP*/ { #ifdef NON_UNIX_STDIO return !isatty(fileno(f)); #else struct stat x; if (fstat(fileno(f),&x) < 0) return(0); #ifdef S_IFMT switch(x.st_mode & S_IFMT) { case S_IFDIR: case S_IFREG: if(x.st_nlink > 0) /* !pipe */ return(1); else return(0); case S_IFCHR: if(isatty(fileno(f))) return(0); return(1); #ifdef S_IFBLK case S_IFBLK: return(1); #endif } #else #ifdef S_ISDIR /* POSIX version */ if (S_ISREG(x.st_mode) || S_ISDIR(x.st_mode)) { if(x.st_nlink > 0) /* !pipe */ return(1); else return(0); } if (S_ISCHR(x.st_mode)) { if(isatty(fileno(f))) return(0); return(1); } if (S_ISBLK(x.st_mode)) return(1); #else Help! How does fstat work on this system? #endif #endif return(0); /* who knows what it is? */ #endif } void f__fatal(int n, const char *s) { if(n<100 && n>=0) perror(s); /*SYSDEP*/ else if(n >= (int)MAXERR || n < -1) { fprintf(stderr,"%s: illegal error number %d\n",s,n); } else if(n == -1) fprintf(stderr,"%s: end of file\n",s); else fprintf(stderr,"%s: %s\n",s,F_err[n-100]); if (f__curunit) { fprintf(stderr,"apparent state: unit %d ", (int)(f__curunit-f__units)); fprintf(stderr, f__curunit->ufnm ? "named %s\n" : "(unnamed)\n", f__curunit->ufnm); } else fprintf(stderr,"apparent state: internal I/O\n"); if (f__fmtbuf) fprintf(stderr,"last format: %s\n",f__fmtbuf); fprintf(stderr,"lately %s %s %s %s",f__reading?"reading":"writing", f__sequential?"sequential":"direct",f__formatted?"formatted":"unformatted", f__external?"external":"internal"); sig_die(" IO", 1); } void f_init(void) { unit *p; f__init=1; p= &f__units[0]; p->ufd=stderr; p->useek=f__canseek(stderr); p->ufmt=1; p->uwrt=1; p = &f__units[5]; p->ufd=stdin; p->useek=f__canseek(stdin); p->ufmt=1; p->uwrt=0; p= &f__units[6]; p->ufd=stdout; p->useek=f__canseek(stdout); p->ufmt=1; p->uwrt=1; } int f__nowreading(unit *x) { OFF_T loc; int ufmt, urw; if (x->urw & 1) goto done; if (!x->ufnm) goto cantread; ufmt = x->url ? 0 : x->ufmt; loc = FTELL(x->ufd); urw = 3; if (!freopen(x->ufnm, f__w_mode[ufmt|2], x->ufd)) { urw = 1; if(!freopen(x->ufnm, f__r_mode[ufmt], x->ufd)) { cantread: errno = 126; return 1; } } FSEEK(x->ufd,loc,SEEK_SET); x->urw = urw; done: x->uwrt = 0; return 0; } int f__nowwriting(unit *x) { OFF_T loc; int ufmt; if (x->urw & 2) { if (x->urw & 1) FSEEK(x->ufd, (OFF_T)0, SEEK_CUR); goto done; } if (!x->ufnm) goto cantwrite; ufmt = x->url ? 0 : x->ufmt; if (x->uwrt == 3) { /* just did write, rewind */ if (!(f__cf = x->ufd = freopen(x->ufnm,f__w_mode[ufmt],x->ufd))) goto cantwrite; x->urw = 2; } else { loc=FTELL(x->ufd); if (!(f__cf = x->ufd = freopen(x->ufnm, f__w_mode[ufmt | 2], x->ufd))) { x->ufd = NULL; cantwrite: errno = 127; return(1); } x->urw = 3; FSEEK(x->ufd,loc,SEEK_SET); } done: x->uwrt = 1; return 0; } int err__fl(int f, int m, const char *s) { if (!f) f__fatal(m, s); if (f__doend) (*f__doend)(); return errno = m; } blis-0.9.0/blastest/f2c/exit_.c000066400000000000000000000027631422157504600162360ustar00rootroot00000000000000/**************************************************************** Copyright 1990 - 1997 by AT&T, Lucent Technologies and Bellcore. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that the copyright notice and this permission notice and warranty disclaimer appear in supporting documentation, and that the names of AT&T, Bell Laboratories, Lucent or Bellcore or any of their entities not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. AT&T, Lucent and Bellcore disclaim all warranties with regard to this software, including all implied warranties of merchantability and fitness. In no event shall AT&T, Lucent or Bellcore be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software. ****************************************************************/ /* This gives the effect of subroutine exit(rc) integer*4 rc stop end * with the added side effect of supplying rc as the program's exit code. */ #include #include "f2c.h" #ifdef __cplusplus extern "C" { #endif void exit_(integer *rc) { exit(*rc); } #ifdef __cplusplus } #endif blis-0.9.0/blastest/f2c/exp.c000066400000000000000000000034051422157504600157140ustar00rootroot00000000000000/**************************************************************** Copyright 1990 - 1997 by AT&T, Lucent Technologies and Bellcore. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that the copyright notice and this permission notice and warranty disclaimer appear in supporting documentation, and that the names of AT&T, Bell Laboratories, Lucent or Bellcore or any of their entities not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. AT&T, Lucent and Bellcore disclaim all warranties with regard to this software, including all implied warranties of merchantability and fitness. In no event shall AT&T, Lucent or Bellcore be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software. ****************************************************************/ #include "f2c.h" #ifdef __cplusplus extern "C" { #endif double r_exp(real *x) { return( exp(*x) ); } double d_exp(const doublereal *x) { return( exp(*x) ); } void c_exp(complex *r, complex *z) { double expx, zi = z->i; expx = exp(z->r); r->r = expx * cos(zi); r->i = expx * sin(zi); } void z_exp(doublecomplex *r, doublecomplex *z) { double expx, zi = z->i; expx = exp(z->r); r->r = expx * cos(zi); r->i = expx * sin(zi); } #ifdef __cplusplus } #endif blis-0.9.0/blastest/f2c/f2c.h000066400000000000000000000265261422157504600156100ustar00rootroot00000000000000/**************************************************************** Copyright 1990 - 1997 by AT&T, Lucent Technologies and Bellcore. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that the copyright notice and this permission notice and warranty disclaimer appear in supporting documentation, and that the names of AT&T, Bell Laboratories, Lucent or Bellcore or any of their entities not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. AT&T, Lucent and Bellcore disclaim all warranties with regard to this software, including all implied warranties of merchantability and fitness. In no event shall AT&T, Lucent or Bellcore be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software. ****************************************************************/ /* include/f2c.h. Generated from f2c.h.in by configure. */ /* f2c.h -- Standard Fortran to C header file */ /** barf [ba:rf] 2. "He suggested using FORTRAN, and everybody barfed." - From The Shogakukan DICTIONARY OF NEW ENGLISH (Second edition) */ #ifndef F2C_INCLUDE #define F2C_INCLUDE #include #include #ifdef _MSC_VER # include #else # include #endif #ifdef __cplusplus extern "C" { #endif #ifdef INTEGER_STAR_8 /* Adjust for integer*8. */ #define qbit_clear(a,b) ((a) & ~((ulongint)1 << (b))) #define qbit_set(a,b) ((a) | ((ulongint)1 << (b))) #endif #define TRUE_ (1) #define FALSE_ (0) /* Extern is for use with -E */ #ifndef Extern #define Extern extern #endif /* I/O stuff */ /*external read, write*/ typedef struct { flag cierr; ftnint ciunit; flag ciend; char *cifmt; ftnint cirec; } cilist; /*internal read, write*/ typedef struct { flag icierr; char *iciunit; flag iciend; char *icifmt; ftnint icirlen; ftnint icirnum; } icilist; /*open*/ typedef struct { flag oerr; ftnint ounit; char *ofnm; ftnlen ofnmlen; char *osta; char *oacc; char *ofm; ftnint orl; char *oblnk; } olist; /*close*/ typedef struct { flag cerr; ftnint cunit; char *csta; } cllist; /*rewind, backspace, endfile*/ typedef struct { flag aerr; ftnint aunit; } alist; /* inquire */ typedef struct { flag inerr; ftnint inunit; char *infile; ftnlen infilen; ftnint *inex; /*parameters in standard's order*/ ftnint *inopen; ftnint *innum; ftnint *innamed; char *inname; ftnlen innamlen; char *inacc; ftnlen inacclen; char *inseq; ftnlen inseqlen; char *indir; ftnlen indirlen; char *infmt; ftnlen infmtlen; char *inform; ftnint informlen; char *inunf; ftnlen inunflen; ftnint *inrecl; ftnint *innrec; char *inblank; ftnlen inblanklen; } inlist; union Multitype { /* for multiple entry points */ integer1 g; shortint h; integer i; /* longint j; */ real r; doublereal d; complex c; doublecomplex z; }; typedef union Multitype Multitype; struct Vardesc { /* for Namelist */ char *name; char *addr; ftnlen *dims; int type; }; typedef struct Vardesc Vardesc; struct Namelist { char *name; Vardesc **vars; int nvars; }; typedef struct Namelist Namelist; #define abs(x) ((x) >= 0 ? (x) : -(x)) #define dabs(x) (doublereal)abs(x) #define min(a,b) ((a) <= (b) ? (a) : (b)) #define max(a,b) ((a) >= (b) ? (a) : (b)) #define dmin(a,b) (doublereal)min(a,b) #define dmax(a,b) (doublereal)max(a,b) #define bit_test(a,b) ((a) >> (b) & 1) #define bit_clear(a,b) ((a) & ~((uinteger)1 << (b))) #define bit_set(a,b) ((a) | ((uinteger)1 << (b))) /* undef any lower-case symbols that your C compiler predefines, e.g.: */ #ifndef Skip_f2c_Undefs /* #undef cray */ /* #undef gcos */ /* #undef mc68010 */ /* #undef mc68020 */ /* #undef mips */ /* #undef pdp11 */ /* #undef sgi */ /* #undef sparc */ /* #undef sun */ /* #undef sun2 */ /* #undef sun3 */ /* #undef sun4 */ /* #undef u370 */ /* #undef u3b */ /* #undef u3b2 */ /* #undef u3b5 */ /* #undef unix */ /* #undef vax */ #endif void libf2c_init(int argc, char **argv); void libf2c_close(); /************************************************************* * LIBF77 */ /* * Private functions and variables in libF77 */ extern int xargc; extern char **xargv; extern doublereal _0; double f__cabs(double, double); char *F77_aloc(integer Len, const char *whence); void sig_die(const char*, int); void _uninit_f2c(void *x, int type, long len); /* * Public functions in libF77 */ int abort_(void); void c_cos(complex *r, complex *z); void c_div(complex *c, complex *a, complex *b); void c_exp(complex *r, complex *z); void c_log(complex *r, complex *z); void c_sin(complex *r, complex *z); void c_sqrt(complex *r, complex *z); double dtime_(float *tarray); int ef1asc_(ftnint *a, ftnlen *la, ftnint *b, ftnlen *lb); integer ef1cmc_(ftnint *a, ftnlen *la, ftnint *b, ftnlen *lb); real etime_(real *tarray); int getarg_(ftnint *n, char *s, ftnlen ls); int getenv_(char *fname, char *value, ftnlen flen, ftnlen vlen); shortint h_indx(char *a, char *b, ftnlen la, ftnlen lb); integer i_indx(char *a, char *b, ftnlen la, ftnlen lb); logical l_ge(char *a, char *b, ftnlen la, ftnlen lb); logical l_gt(char *a, char *b, ftnlen la, ftnlen lb); logical l_le(char *a, char *b, ftnlen la, ftnlen lb); logical l_lt(char *a, char *b, ftnlen la, ftnlen lb); integer lbit_bits(integer a, integer b, integer len); integer lbit_shift(integer a, integer b); integer lbit_cshift(integer a, integer b, integer len); void pow_ci(complex *p, complex *a, integer *b); double pow_dd(doublereal *ap, doublereal *bp); double pow_di(doublereal *ap, integer *bp); shortint pow_hh(shortint *ap, shortint *bp); integer pow_ii(integer *ap, integer *bp); #ifdef INTEGER_STAR_8 longint pow_qq(longint *ap, longint *bp); #endif double pow_ri(real *ap, integer *bp); void pow_zi(doublecomplex*, doublecomplex*, integer*); void pow_zz(doublecomplex *r, doublecomplex *a, doublecomplex *b); #ifdef INTEGER_STAR_8 longint qbit_bits(longint a, integer b, integer len); longint qbit_cshift(longint a, integer b, integer len); longint qbit_shift(longint a, integer b); #endif double r_abs(real *x); double r_acos(real *x); double r_asin(real *x); double r_atan(real *x); double r_atn2(real *x, real *y); void r_cnjg(complex *r, complex *z); double r_cos(real *x); double r_cosh(real *x); double r_dim(real *a, real *b); double r_exp(real *x); double r_imag(complex *z); double r_int(real *x); double r_lg10(real *x); double r_log(real *x); double r_mod(real *x, real *y); double r_nint(real *x); double r_sign(real *a, real *b); double r_sin(real *x); double r_sinh(real *x); double r_sqrt(real *x); double r_tan(real *x); double r_tanh(real *x); int s_cat(char *lp, char *rpp[], ftnint rnp[], ftnint *np, ftnlen ll); integer s_cmp(const char *a0, const char *b0, ftnlen la, ftnlen lb); int s_paus(char *s, ftnlen n); integer s_rnge(char *varn, ftnint offset, char *procn, ftnint line); int s_stop(char *s, ftnlen n); ftnint signal_(integer *sigp, void *proc); integer system_(register char *s, ftnlen n); void z_div(doublecomplex*, doublecomplex*, doublecomplex*); void z_cos(doublecomplex *r, doublecomplex *z); void z_exp(doublecomplex *r, doublecomplex *z); void z_log(doublecomplex *r, doublecomplex *z); void z_sin(doublecomplex *r, doublecomplex *z); void z_sqrt(doublecomplex *r, doublecomplex *z); /* #ifndef F2C_NO_INLINE_H # if defined(__GNUC__) # include # endif #endif */ #if !defined(F2C_INLINE_H) double c_abs(const complex *z); double d_abs(const doublereal *x); double d_acos(const doublereal *x); double d_asin(const doublereal *x); double d_atan(const doublereal *x); double d_atn2(const doublereal *x, const doublereal *y); void d_cnjg(doublecomplex *r, const doublecomplex *z); double d_cos(const doublereal *x); double d_cosh(const doublereal *x); double d_dim(const doublereal *a, const doublereal *b); double d_exp(const doublereal *x); double d_imag(const doublecomplex *z); double d_int(const doublereal *x); double d_lg10(const doublereal *x); double d_log(const doublereal *x); double d_mod(const doublereal *x, const doublereal *y); double d_nint(const doublereal *x); double d_prod(const real *x, const real *y); double d_sign(const doublereal *a, const doublereal *b); double d_sin(const doublereal *x); double d_sinh(const doublereal *x); double d_sqrt(const doublereal *x); double d_tan(const doublereal *x); double d_tanh(const doublereal *x); double derf_(const doublereal *x); double derfc_(const doublereal *x); double erf_(const real *x); double erfc_(const real *x); shortint h_abs(const shortint *x); shortint h_dim(const shortint *a, const shortint *b); shortint h_dnnt(const doublereal *x); shortint h_len(const char *s, ftnlen n); shortint h_mod(const short *a, const short *b); shortint h_nint(const real *x); shortint h_sign(const shortint *a, const shortint *b); shortlogical hl_ge(const char *a, const char *b, ftnlen la, ftnlen lb); shortlogical hl_gt(const char *a, const char *b, ftnlen la, ftnlen lb); shortlogical hl_le(const char *a, const char *b, ftnlen la, ftnlen lb); shortlogical hl_lt(const char *a, const char *b, ftnlen la, ftnlen lb); integer i_abs(const integer *x); integer i_dceiling(const doublereal *x); integer i_dim(const integer *a, const integer *b); integer i_dnnt(const doublereal *x); integer i_len(const char *s, ftnlen n); integer i_len_trim(const char *s, ftnlen n); integer i_mod(const integer *a, const integer *b); integer i_nint(const real *x); integer i_sign(const integer *a, const integer *b); integer i_sceiling(const real *x); ftnint iargc_(void); int s_copy(char *a, const char *b, ftnlen la, ftnlen lb); double z_abs(const doublecomplex *z); #endif /* !F2C_INLINE_H */ /************************************************************* * LIBI77 * * Public functions */ int c_dfe(cilist *a); int c_due(cilist *a); int c_sfe(cilist *a); int c_sue(cilist *a); integer e_rdfe(void); integer e_rdue(void); integer e_rsfe(void); integer e_rsfi(void); integer e_rsle(void); integer e_rsli(void); integer e_rsue(void); integer e_wdfe(void); integer e_wdue(void); integer e_wsfi(void); integer e_wsfe(void); integer e_wsle(void); integer e_wsli(void); integer e_wsue(void); void exit_(integer *rc); integer f_back(alist *a); integer f_clos(cllist *a); integer f_end(alist *a); void f_exit(void); integer f_inqu(inlist *a); integer f_open(olist *a); integer f_rew(alist *a); int flush_(void); integer ftell_(integer *Unit); int fseek_(integer *Unit, integer *offset, integer *whence); #ifdef INTEGER_STAR_8 longint ftell64_(integer *Unit); int fseek64_(integer *Unit, longint *offset, integer *whence); #endif integer s_rdfe(cilist *a); integer s_rdue(cilist *a); integer s_rsfi(icilist *a); integer s_rsle(cilist *a); integer s_rsli(icilist *a); integer s_rsne(cilist *a); integer s_rsni(icilist *a); integer s_rsue(cilist *a); integer s_wdfe(cilist *a); integer s_wdue(cilist *a); integer s_wsfe(cilist *a); integer s_wsfi(icilist *a); integer s_wsle(cilist *a); integer s_wsli(icilist *a); integer s_wsne(cilist *a); integer s_wsni(icilist *a); integer s_wsue(cilist *a); real s_epsilon_( real* x ); double d_epsilon_( doublereal* x ); /* * Private functions in the F2C library */ extern const ftnlen f__typesize[]; #ifdef __cplusplus } #endif #endif blis-0.9.0/blastest/f2c/f2c_config.h000066400000000000000000000121211422157504600171170ustar00rootroot00000000000000/* config_aux/config.h. Generated from f2c_config.h.in by configure. */ /* config_aux/config.h.in. Generated from configure.ac by autoheader. */ /* Bit size of 'int' */ #define F2C_INT_BITS 32 /* Bit size of 'long' */ #define F2C_LONG_BITS 64 /* Bit sizze of long long */ #define F2C_LONG_LONG_BITS 64 /* Define to 1 if you have the `atexit' function. */ #define HAVE_ATEXIT 1 /* Define to 1 if you have the header file. */ #define HAVE_DLFCN_H 1 /* Define to 1 if you have the header file. */ #define HAVE_FENV_H 1 /* Define to 1 if you have the `floor' function. */ /* #undef HAVE_FLOOR */ /* Define to 1 if you have the `fork' function. */ #define HAVE_FORK 1 /* Define to 1 if fseeko (and presumably ftello) exists and is declared. */ #if !defined(_MSC_VER) #define HAVE_FSEEKO 1 #endif /* Define to 1 if you have the `ftruncate' function. */ #if !defined(_MSC_VER) #define HAVE_FTRUNCATE 1 #endif /* Define to 1 if you have the header file. */ #define HAVE_INTTYPES_H 1 /* Define to 1 if you have the `isascii' function. */ #define HAVE_ISASCII 1 /* Define to 1 if you have the `isatty' function. */ #define HAVE_ISATTY 1 /* Define to 1 if your system has a GNU libc compatible `malloc' function, and to 0 otherwise. */ #define HAVE_MALLOC 1 /* Define to 1 if you have the header file. */ #define HAVE_MEMORY_H 1 /* Define to 1 if you have the `memset' function. */ #define HAVE_MEMSET 1 /* Define to 1 if you have the `mkdir' function. */ #define HAVE_MKDIR 1 /* Define to 1 if you have the `mkdtemp' function. */ #define HAVE_MKDTEMP 1 /* Define to 1 if you have the `mkstemp' function. */ #define HAVE_MKSTEMP 1 /* Define to 1 if you have the `onexit' function. */ /* #undef HAVE_ONEXIT */ /* Define to 1 if you have the `pow' function. */ /* #undef HAVE_POW */ /* Define to 1 if your system has a GNU libc compatible `realloc' function, and to 0 otherwise. */ #define HAVE_REALLOC 1 /* Define to 1 if you have the `rmdir' function. */ #define HAVE_RMDIR 1 /* Define to 1 if you have the `sqrt' function. */ /* #undef HAVE_SQRT */ /* Define to 1 if you have the header file. */ #define HAVE_STDDEF_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STDINT_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STDLIB_H 1 /* Define to 1 if you have the `strchr' function. */ #define HAVE_STRCHR 1 /* Define to 1 if you have the header file. */ #define HAVE_STRINGS_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STRING_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_STAT_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_TYPES_H 1 /* Define to 1 if you have the `tmpfile' function. */ #define HAVE_TMPFILE 1 /* Define to 1 if you have the header file. */ #define HAVE_UNISTD_H 1 /* Define to 1 if you have the `vfork' function. */ #define HAVE_VFORK 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_VFORK_H */ /* Define to 1 if `fork' works. */ #define HAVE_WORKING_FORK 1 /* Define to 1 if `vfork' works. */ #define HAVE_WORKING_VFORK 1 /* Define to the sub-directory where libtool stores uninstalled libraries. */ #define LT_OBJDIR ".libs/" /* Name of package */ #define PACKAGE "f2c" /* Define to the address where bug reports for this package should be sent. */ #define PACKAGE_BUGREPORT "jjgarcia@users.sourceforge.net" /* Define to the full name of this package. */ #define PACKAGE_NAME "F2C Fortran to C99 compiler" /* Define to the full name and version of this package. */ #define PACKAGE_STRING "F2C Fortran to C99 compiler 12.02.01" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "f2c" /* Define to the home page for this package. */ #define PACKAGE_URL "" /* Define to the version of this package. */ #define PACKAGE_VERSION "12.02.01" /* Define to 1 if you have the ANSI C header files. */ #define STDC_HEADERS 1 /* Version number of package */ #define VERSION "12.02.01" /* Enable large inode numbers on Mac OS X 10.5. */ #ifndef _DARWIN_USE_64_BIT_INODE # define _DARWIN_USE_64_BIT_INODE 1 #endif /* Number of bits in a file offset, on hosts where this is settable. */ /* #undef _FILE_OFFSET_BITS */ /* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */ /* #undef _LARGEFILE_SOURCE */ /* Define for large files, on AIX-style hosts. */ /* #undef _LARGE_FILES */ /* Define to `__inline__' or `__inline' if that's what the C compiler calls it, or to nothing if 'inline' is not supported under any name. */ #ifndef __cplusplus /* #undef inline */ #endif /* Define to rpl_malloc if the replacement function should be used. */ /* #undef malloc */ /* Define to `int' if does not define. */ /* #undef pid_t */ /* Define to rpl_realloc if the replacement function should be used. */ /* #undef realloc */ /* Define to `unsigned int' if does not define. */ /* #undef size_t */ /* Define as `fork' if `vfork' does not work. */ /* #undef vfork */ #ifdef _MSC_VER #define NON_UNIX_STDIO 1 #endifblis-0.9.0/blastest/f2c/f2c_inline.h000066400000000000000000000135271422157504600171430ustar00rootroot00000000000000/**************************************************************** Copyright 1990 - 1997 by AT&T, Lucent Technologies and Bellcore. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that the copyright notice and this permission notice and warranty disclaimer appear in supporting documentation, and that the names of AT&T, Bell Laboratories, Lucent or Bellcore or any of their entities not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. AT&T, Lucent and Bellcore disclaim all warranties with regard to this software, including all implied warranties of merchantability and fitness. In no event shall AT&T, Lucent or Bellcore be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software. ****************************************************************/ /* f2c_inline.h -- Standard Fortran to C header file */ #ifndef F2C_INLINE_H #define F2C_INLINE_H #ifndef F2C_INCLUDE #error f2c_include.h cannot be included as is #endif static inline double c_abs(const complex *z) { return hypot(z->r, z->i); } static inline double d_abs(const double *x) { return fabs(*x); } static inline double d_acos(const double *x) { return acos(*x); } static inline double d_acosh(const double *x) { return acosh(*x); } static inline double d_asin(const double *x) { return asin(*x); } static inline double d_asinh(const double *x) { return asinh(*x); } static inline double d_atan(const double *x) { return atan(*x); } static inline double d_atanh(const double *x) { return atanh(*x); } static inline double d_atn2(const double *x, double *y) { return atan2(*x, *y); } static inline void d_cnjg(doublecomplex *r, const doublecomplex *z) { r->r = z->r; r->i = -z->i; } static inline double d_cos(const double *x) { return cos(*x); } static inline double d_cosh(const double *x) { return cosh(*x); } static inline double d_dim(const double *a, double *b) { double d = (*a - *b); return (d > 0)? d : 0; } static inline double d_exp(const double *x) { return exp(*x); } static inline double d_imag(doublecomplex *x) { return x->i; } static inline double d_int(const double *x) { double y = *x; return (y < 0)? floor(y) : -floor(-y); } static inline double d_lg10(const double *x) { return log10(*x); } static inline double d_log(const double *x) { return log(*x); } static inline double d_nint(const double *x) { return round(*x); } static inline double d_prod(const float *x, const float *y) { return ((double)*x) * ((double)*x); } static inline double d_sin(const double *x) { return sin(*x); } static inline double d_tan(const double *x) { return tan(*x); } static inline double d_sinh(const double *x) { return sinh(*x); } static inline double d_sqrt(const double *x) { return sqrt(*x); } static inline double d_tanh(const double *x) { return tanh(*x); } static inline double d_sign(const double *a, const double *b) { double x = fabs(*a); return (*b >= 0 ? x : -x); } static inline double derfc_(const double *x) { return erfc(*x); } static inline double derf_(const double *x) { return erf(*x); } static inline double erf_(const float *x) { return erf((double)(*x)); } static inline double erfc_(const float *x) { return erfc((double)(*x)); } static inline shortint h_abs(const shortint *x) { return abs(*x); } static inline shortint h_dim(const shortint *a, const shortint *b) { shortint d = (*a - *b); return (d > 0)? d : 0; } static inline shortint h_len(const char *s, ftnlen n) { return n; } static inline shortint h_mod(const shortint *a, const shortint *b) { return *a % *b; } static inline shortint h_nint(const float *x) { return (shortint)round(*x); } static inline shortint h_dnnt(const doublereal *x) { return (shortint)round(*x); } static inline shortint h_sign(const shortint *a, const shortint *b) { shortint x = abs(*a); return *b >= 0 ? x : -x; } static inline shortlogical hl_ge(const char *a, const char *b, ftnlen la, ftnlen lb) { return s_cmp(a,b,la,lb) >= 0; } static inline shortlogical hl_le(const char *a, const char *b, ftnlen la, ftnlen lb) { return s_cmp(a,b,la,lb) >= 0; } static inline shortlogical hl_gt(const char *a, const char *b, ftnlen la, ftnlen lb) { return s_cmp(a,b,la,lb) > 0; } static inline shortlogical hl_lt(const char *a, const char *b, ftnlen la, ftnlen lb) { return s_cmp(a,b,la,lb) < 0; } static inline integer i_abs(const integer *x) { return abs(*x); } static inline integer i_dim(const integer *a, const integer *b) { integer d = (*a - *b); return (d > 0)? d : 0; } static inline integer i_len(const char *s, ftnlen n) { return n; } static inline integer i_mod(const integer *a, const integer *b) { return *a % *b; } static inline integer i_nint(const float *x) { return (integer)round(*x); } static inline integer i_dnnt(const doublereal *x) { return (integer)round(*x); } static inline integer i_sign(const integer *a, const integer *b) { integer x = abs(*a); return *b >= 0 ? x : -x; } static inline ftnint iargc_(void) { return xargc - 1; } static inline double z_abs(const doublecomplex *z) { return hypot(z->r, z->i); } static int s_copy(char *a, const char *b, ftnlen la, ftnlen lb) { if (la <= lb) { memmove(a, b, la); } else { memmove(a, b, lb); memset(a, ' ', la - lb); } return 0; } static inline integer i_sceiling(const real *r) { real x = *r; return ((integer)(x) + ((x) > 0 && (x) != (integer)(x))); } static inline integer i_dceiling(const doublereal *r) { doublereal x = *r; return ((integer)(x) + ((x) > 0 && (x) != (integer)(x))); } #endif /* !F2C_INLINE_H */ blis-0.9.0/blastest/f2c/f2c_types.h000066400000000000000000000104511422157504600170220ustar00rootroot00000000000000/**************************************************************** Copyright 1990 - 1997 by AT&T, Lucent Technologies and Bellcore. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that the copyright notice and this permission notice and warranty disclaimer appear in supporting documentation, and that the names of AT&T, Bell Laboratories, Lucent or Bellcore or any of their entities not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. AT&T, Lucent and Bellcore disclaim all warranties with regard to this software, including all implied warranties of merchantability and fitness. In no event shall AT&T, Lucent or Bellcore be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software. ****************************************************************/ /* include/f2c_types.h. Generated from f2c_types.h.in by configure. */ /* include/f2c.h. Generated from f2c.h.in by configure. */ /* f2c.h -- Standard Fortran to C header file */ /** barf [ba:rf] 2. "He suggested using FORTRAN, and everybody barfed." - From The Shogakukan DICTIONARY OF NEW ENGLISH (Second edition) */ #ifndef F2C_TYPES_H #define F2C_TYPES_H #ifdef HAVE_BLIS_H #include #define BLIS_VIA_BLASTEST #include "blis.h" #endif #ifdef __cplusplus extern "C" { #endif /* Define to the number of bits in an integer */ #define F2C_INT_BITS 32 /* Define to the number of bits in a long integer */ #define F2C_LONG_BITS 64 /* Define to the number of bits in a long long integer, if it exists */ #define F2C_LONG_LONG_BITS 64 #ifdef HAVE_BLIS_H #if BLIS_BLAS_INT_TYPE_SIZE == 32 typedef int32_t integer; #elif BLIS_BLAS_INT_TYPE_SIZE == 64 typedef int64_t integer; #else typedef long int integer; #endif //typedef int integer; typedef unsigned int uinteger; #endif #if F2C_INT_BITS == 32 # if F2C_LONG_BITS == 64 typedef long int longint; typedef unsigned long int ulongint; # define INTEGER_STAR_8 # elif defined(F2C_LONG_LONG_BITS) # if F2C_LONG_LONG_BITS == 64 typedef long long int longint; typedef unsigned long long int ulongint; # define INTEGER_STAR_8 # endif # endif #endif typedef char integer1; typedef char *address; typedef short int shortint; typedef float real; typedef double doublereal; typedef struct { real r, i; } complex; typedef struct { doublereal r, i; } doublecomplex; typedef integer logical; typedef shortint shortlogical; typedef integer1 logical1; #ifdef f2c_i2 /* for -i2 */ typedef short flag; #ifndef HAVE_BLIS_H // don't re-typedef ftnlen typedef short ftnlen; #endif typedef short ftnint; #else typedef integer flag; #ifndef HAVE_BLIS_H // don't re-typedef ftnlen typedef integer ftnlen; #endif typedef integer ftnint; #endif /* procedure parameter types for -A and -C++ */ #define F2C_proc_par_types 1 #ifdef __cplusplus typedef int /* Unknown procedure type */ (*U_fp)(...); typedef shortint (*J_fp)(...); typedef integer (*I_fp)(...); typedef real (*R_fp)(...); typedef doublereal (*D_fp)(...), (*E_fp)(...); typedef /* Complex */ void (*C_fp)(...); typedef /* Double Complex */ void (*Z_fp)(...); typedef logical (*L_fp)(...); typedef shortlogical (*K_fp)(...); typedef /* Character */ void (*H_fp)(...); typedef /* Subroutine */ int (*S_fp)(...); #else typedef int /* Unknown procedure type */ (*U_fp)(); typedef shortint (*J_fp)(); typedef integer (*I_fp)(); typedef real (*R_fp)(); typedef doublereal (*D_fp)(), (*E_fp)(); typedef /* Complex */ void (*C_fp)(); typedef /* Double Complex */ void (*Z_fp)(); typedef logical (*L_fp)(); typedef shortlogical (*K_fp)(); typedef /* Character */ void (*H_fp)(); typedef /* Subroutine */ int (*S_fp)(); #endif /* E_fp is for real functions when -R is not specified */ typedef void C_f; /* complex function */ typedef void H_f; /* character function */ typedef void Z_f; /* double complex function */ typedef doublereal E_f; /* real function with -R not specified */ #ifdef __cplusplus } #endif #endif /* F2C_TYPES_H */ blis-0.9.0/blastest/f2c/f2c_types_win.h000066400000000000000000000044701422157504600177030ustar00rootroot00000000000000/* include/f2c.h. Generated from f2c.h.in by configure. */ /* f2c.h -- Standard Fortran to C header file */ /** barf [ba:rf] 2. "He suggested using FORTRAN, and everybody barfed." - From The Shogakukan DICTIONARY OF NEW ENGLISH (Second edition) */ #ifndef F2C_TYPES_WIN_H #define F2C_TYPES_WIN_H #ifdef __cplusplus extern "C" { #endif /* Define to the number of bits in an integer */ #define F2C_INT_BITS 32 /* Define to the number of bits in a long integer */ #define F2C_LONG_BITS 64 typedef int integer; typedef unsigned int uinteger; typedef __int64 longint; typedef unsigned __int64 ulongint; /*#define INTEGER_STAR_8*/ typedef char integer1; typedef char *address; typedef short int shortint; typedef float real; typedef double doublereal; typedef struct { real r, i; } complex; typedef struct { doublereal r, i; } doublecomplex; typedef integer logical; typedef shortint shortlogical; typedef integer1 logical1; #ifdef f2c_i2 /* for -i2 */ typedef short flag; typedef short ftnlen; typedef short ftnint; #else typedef integer flag; typedef integer ftnlen; typedef integer ftnint; #endif /* procedure parameter types for -A and -C++ */ #define F2C_proc_par_types 1 #ifdef __cplusplus typedef int /* Unknown procedure type */ (*U_fp)(...); typedef shortint (*J_fp)(...); typedef integer (*I_fp)(...); typedef real (*R_fp)(...); typedef doublereal (*D_fp)(...), (*E_fp)(...); typedef /* Complex */ void (*C_fp)(...); typedef /* Double Complex */ void (*Z_fp)(...); typedef logical (*L_fp)(...); typedef shortlogical (*K_fp)(...); typedef /* Character */ void (*H_fp)(...); typedef /* Subroutine */ int (*S_fp)(...); #else typedef int /* Unknown procedure type */ (*U_fp)(); typedef shortint (*J_fp)(); typedef integer (*I_fp)(); typedef real (*R_fp)(); typedef doublereal (*D_fp)(), (*E_fp)(); typedef /* Complex */ void (*C_fp)(); typedef /* Double Complex */ void (*Z_fp)(); typedef logical (*L_fp)(); typedef shortlogical (*K_fp)(); typedef /* Character */ void (*H_fp)(); typedef /* Subroutine */ int (*S_fp)(); #endif /* E_fp is for real functions when -R is not specified */ typedef void C_f; /* complex function */ typedef void H_f; /* character function */ typedef void Z_f; /* double complex function */ typedef doublereal E_f; /* real function with -R not specified */ #ifdef __cplusplus } #endif #endif /* F2C_TYPES_H */ blis-0.9.0/blastest/f2c/fio.h000066400000000000000000000114521422157504600157030ustar00rootroot00000000000000/**************************************************************** Copyright 1990 - 1997 by AT&T, Lucent Technologies and Bellcore. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that the copyright notice and this permission notice and warranty disclaimer appear in supporting documentation, and that the names of AT&T, Bell Laboratories, Lucent or Bellcore or any of their entities not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. AT&T, Lucent and Bellcore disclaim all warranties with regard to this software, including all implied warranties of merchantability and fitness. In no event shall AT&T, Lucent or Bellcore be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software. ****************************************************************/ #include #include #include #include #include #include #ifdef HAVE_FSEEKO #define OFF_T off_t #define FSEEK fseeko #define FTELL ftello #else #define OFF_T long #define FSEEK fseek #define FTELL ftell #endif #ifdef MSDOS #ifndef NON_UNIX_STDIO #define NON_UNIX_STDIO #endif #endif typedef long uiolen; /*units*/ typedef struct { FILE *ufd; /*0=unconnected*/ char *ufnm; #ifndef MSDOS long uinode; int udev; #endif int url; /*0=sequential*/ flag useek; /*true=can backspace, use dir, ...*/ flag ufmt; flag urw; /* (1 for can read) | (2 for can write) */ flag ublnk; flag uend; flag uwrt; /*last io was write*/ flag uscrtch; } unit; extern int (*f__getn)(void); /* for formatted input */ extern void (*f__putn)(int); /* for formatted output */ extern void x_putc(int); extern long f__inode(char*,int*); extern void sig_die(const char*,int); extern void f__fatal(int, const char*); extern int t_runc(alist*); extern int f__nowreading(unit*), f__nowwriting(unit*); extern int fk_open(int,int,ftnint); extern int en_fio(void); extern void f_init(void); extern int (*f__donewrec)(void), t_putc(int), x_wSL(void); extern void b_char(const char*,char*,ftnlen), g_char(const char*,ftnlen,char*); extern int c_sfe(cilist*); extern int z_rnew(void); extern int err__fl(int,int,const char*); extern int xrd_SL(void); extern int f__putbuf(int); extern int f__canseek(FILE *f); extern int z_getc(void); extern void z_putc(int c); extern integer f_open(olist *a); #ifdef INTEGER_STAR_8 extern char *f__icvt(longint value, int *ndigit, int *sign, int base); #else extern char *f__icvt(integer value, int *ndigit, int *sign, int base); #endif extern int t_getc(void); extern flag f__init; extern cilist *f__elist; /*active external io list*/ extern flag f__reading,f__external,f__sequential,f__formatted; extern int (*f__doend)(void); extern FILE *f__cf; /*current file*/ extern unit *f__curunit; /*current unit*/ extern unit f__units[]; extern char *f__icptr; extern char *f__icend; extern icilist *f__svic; extern int f__icnum; #define err(f,m,s) {if(f) errno= m; else f__fatal(m,s); return(m);} #define errfl(f,m,s) return err__fl((int)f,m,s) /*Table sizes*/ #define MXUNIT 100 extern int f__recpos; /*position in current record*/ extern OFF_T f__cursor; /* offset to move to */ extern OFF_T f__hiwater; /* so TL doesn't confuse us */ #define WRITE 1 #define READ 2 #define SEQ 3 #define DIR 4 #define FMT 5 #define UNF 6 #define EXT 7 #define INT 8 #define buf_end(x) (x->_flag & _IONBF ? x->_ptr : x->_base + BUFSIZ) extern const char *f__fmtbuf; extern const char *f__r_mode[2]; extern const char *f__w_mode[]; extern int l_eof; extern int c_le(cilist *a); extern int l_read(ftnint *number, char *ptr, ftnlen len, ftnint type); extern int l_write(ftnint *number, char *ptr, ftnlen len, ftnint type); extern flag f__lquit; extern int f__lcount; extern char *f__icptr; extern char *f__icend; extern icilist *f__svic; extern int f__icnum, f__recpos; extern int f__Aquote; extern int x_rsne(cilist*); extern void x_wsne(cilist *a); extern flag f__lquit; extern int f__lcount, nml_read; extern int t_getc(void); extern uiolen f__reclen; extern ftnint L_len; extern int f__scale; extern int (*l_getc)(void); extern int (*l_ungetc)(int,FILE*); extern int (*f__lioproc)(ftnint*, char*, ftnlen, ftnint); int do_us(ftnint *number, char *ptr, ftnlen len); integer do_ud(ftnint *number, char *ptr, ftnlen len); integer do_uio(ftnint *number, char *ptr, ftnlen len); integer do_fio(ftnint *number, char *ptr, ftnlen len); int en_fio(void); extern int x_wSL(void); extern int x_getc(void); extern int x_endp(void); blis-0.9.0/blastest/f2c/fmt.c000066400000000000000000000214211422157504600157040ustar00rootroot00000000000000/**************************************************************** Copyright 1990 - 1997 by AT&T, Lucent Technologies and Bellcore. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that the copyright notice and this permission notice and warranty disclaimer appear in supporting documentation, and that the names of AT&T, Bell Laboratories, Lucent or Bellcore or any of their entities not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. AT&T, Lucent and Bellcore disclaim all warranties with regard to this software, including all implied warranties of merchantability and fitness. In no event shall AT&T, Lucent or Bellcore be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software. ****************************************************************/ #include #include "f2c.h" #include "fio.h" #include "fmt.h" #define skip(s) while(*s==' ') s++ #ifdef interdata #define SYLMX 300 #endif #ifdef pdp11 #define SYLMX 300 #endif #ifdef vax #define SYLMX 300 #endif #ifndef SYLMX #define SYLMX 300 #endif #define GLITCH '\2' /* special quote character for stu */ extern flag f__cblank,f__cplus; /*blanks in I and compulsory plus*/ static struct syl f__syl[SYLMX]; int f__parenlvl,f__pc,f__revloc; static const char *ap_end(const char *s) { char quote; quote= *s++; for(;*s;s++) { if(*s!=quote) continue; if(*++s!=quote) return(s); } if(f__elist->cierr) { errno = 100; return(NULL); } f__fatal(100, "bad string"); /*NOTREACHED*/ return 0; } static int op_gen(int a, int b, int c, int d) { struct syl *p= &f__syl[f__pc]; if(f__pc>=SYLMX) { fprintf(stderr,"format too complicated:\n"); sig_die(f__fmtbuf, 1); } p->op=a; p->p1=b; p->p2.i[0]=c; p->p2.i[1]=d; return(f__pc++); } static const char *f_list(const char*); static const char *gt_num(const char *s, int *n, int n1) { int m=0,f__cnt=0; char c; for(c= *s;;c = *s) { if(c==' ') { s++; continue; } if(c>'9' || c<'0') break; m=10*m+c-'0'; f__cnt++; s++; } if(f__cnt==0) { if (!n1) s = 0; *n=n1; } else *n=m; return(s); } static const char *f_s(const char *s, int curloc) { skip(s); if(*s++!='(') { return(NULL); } if(f__parenlvl++ ==1) f__revloc=curloc; if(op_gen(RET1,curloc,0,0)<0 || (s=f_list(s))==NULL) { return(NULL); } skip(s); return(s); } static int ne_d(const char *s, const char **p) { int n,x,sign=0; struct syl *sp; switch(*s) { default: return(0); case ':': (void) op_gen(COLON,0,0,0); break; case '$': (void) op_gen(NONL, 0, 0, 0); break; case 'B': case 'b': if(*++s=='z' || *s == 'Z') (void) op_gen(BZ,0,0,0); else (void) op_gen(BN,0,0,0); break; case 'S': case 's': if(*(s+1)=='s' || *(s+1) == 'S') { x=SS; s++; } else if(*(s+1)=='p' || *(s+1) == 'P') { x=SP; s++; } else x=S; (void) op_gen(x,0,0,0); break; case '/': (void) op_gen(SLASH,0,0,0); break; case '-': sign=1; case '+': s++; /*OUTRAGEOUS CODING TRICK*/ case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if (!(s=gt_num(s,&n,0))) { bad: *p = 0; return 1; } switch(*s) { default: return(0); case 'P': case 'p': if(sign) n= -n; (void) op_gen(P,n,0,0); break; case 'X': case 'x': (void) op_gen(X,n,0,0); break; case 'H': case 'h': sp = &f__syl[op_gen(H,n,0,0)]; sp->p2.s = (char*)s + 1; s+=n; break; } break; case GLITCH: case '"': case '\'': sp = &f__syl[op_gen(APOS,0,0,0)]; sp->p2.s = (char*)s; if((*p = ap_end(s)) == NULL) return(0); return(1); case 'T': case 't': if(*(s+1)=='l' || *(s+1) == 'L') { x=TL; s++; } else if(*(s+1)=='r'|| *(s+1) == 'R') { x=TR; s++; } else x=T; if (!(s=gt_num(s+1,&n,0))) goto bad; s--; (void) op_gen(x,n,0,0); break; case 'X': case 'x': (void) op_gen(X,1,0,0); break; case 'P': case 'p': (void) op_gen(P,1,0,0); break; } s++; *p=s; return(1); } static int e_d(const char *s, const char **p) { int i,im,n,w,d,e,found=0,x=0; const char *sv=s; s=gt_num(s,&n,1); (void) op_gen(STACK,n,0,0); switch(*s++) { default: break; case 'E': case 'e': x=1; case 'G': case 'g': found=1; if (!(s=gt_num(s,&w,0))) { bad: *p = 0; return 1; } if(w==0) break; if(*s=='.') { if (!(s=gt_num(s+1,&d,0))) goto bad; } else d=0; if(*s!='E' && *s != 'e') (void) op_gen(x==1?E:G,w,d,0); /* default is Ew.dE2 */ else { if (!(s=gt_num(s+1,&e,0))) goto bad; (void) op_gen(x==1?EE:GE,w,d,e); } break; case 'O': case 'o': i = O; im = OM; goto finish_I; case 'Z': case 'z': i = Z; im = ZM; goto finish_I; case 'L': case 'l': found=1; if (!(s=gt_num(s,&w,0))) goto bad; if(w==0) break; (void) op_gen(L,w,0,0); break; case 'A': case 'a': found=1; skip(s); if(*s>='0' && *s<='9') { s=gt_num(s,&w,1); if(w==0) break; (void) op_gen(AW,w,0,0); break; } (void) op_gen(A,0,0,0); break; case 'F': case 'f': if (!(s=gt_num(s,&w,0))) goto bad; found=1; if(w==0) break; if(*s=='.') { if (!(s=gt_num(s+1,&d,0))) goto bad; } else d=0; (void) op_gen(F,w,d,0); break; case 'D': case 'd': found=1; if (!(s=gt_num(s,&w,0))) goto bad; if(w==0) break; if(*s=='.') { if (!(s=gt_num(s+1,&d,0))) goto bad; } else d=0; (void) op_gen(D,w,d,0); break; case 'I': case 'i': i = I; im = IM; finish_I: if (!(s=gt_num(s,&w,0))) goto bad; found=1; if(w==0) break; if(*s!='.') { (void) op_gen(i,w,0,0); break; } if (!(s=gt_num(s+1,&d,0))) goto bad; (void) op_gen(im,w,d,0); break; } if(found==0) { f__pc--; /*unSTACK*/ *p=sv; return(0); } *p=s; return(1); } static const char *i_tem(const char *s) { const char *t; int n,curloc; if(*s==')') return(s); if(ne_d(s,&t)) return(t); if(e_d(s,&t)) return(t); s=gt_num(s,&n,1); if((curloc=op_gen(STACK,n,0,0))<0) return(NULL); return(f_s(s,curloc)); } static const char *f_list(const char *s) { for(;*s!=0;) { skip(s); if((s=i_tem(s))==NULL) return(NULL); skip(s); if(*s==',') s++; else if(*s==')') { if(--f__parenlvl==0) { (void) op_gen(REVERT,f__revloc,0,0); return(++s); } (void) op_gen(GOTO,0,0,0); return(++s); } } return(NULL); } int pars_f(const char *s) { f__parenlvl=f__revloc=f__pc=0; if(f_s(s,0) == NULL) { return(-1); } return(0); } #define STKSZ 10 int f__cnt[STKSZ],f__ret[STKSZ],f__cp,f__rp; flag f__workdone, f__nonl; static int type_f(int n) { switch(n) { default: return(n); case RET1: return(RET1); case REVERT: return(REVERT); case GOTO: return(GOTO); case STACK: return(STACK); case X: case SLASH: case APOS: case H: case T: case TL: case TR: return(NED); case F: case I: case IM: case A: case AW: case O: case OM: case L: case E: case EE: case D: case G: case GE: case Z: case ZM: return(ED); } } integer do_fio(ftnint *number, char *ptr, ftnlen len) { struct syl *p; int n,i; for(i=0;i<*number;i++,ptr+=len) { loop: switch(type_f((p= &f__syl[f__pc])->op)) { default: fprintf(stderr,"unknown code in do_fio: %d\n%s\n", p->op,f__fmtbuf); err(f__elist->cierr,100,"do_fio"); case NED: if((*f__doned)(p)) { f__pc++; goto loop; } f__pc++; continue; case ED: if(f__cnt[f__cp]<=0) { f__cp--; f__pc++; goto loop; } if(ptr==NULL) return((*f__doend)()); f__cnt[f__cp]--; f__workdone=1; if((n=(*f__doed)(p,ptr,len))>0) errfl(f__elist->cierr,errno,"fmt"); if(n<0) err(f__elist->ciend,(EOF),"fmt"); continue; case STACK: f__cnt[++f__cp]=p->p1; f__pc++; goto loop; case RET1: f__ret[++f__rp]=p->p1; f__pc++; goto loop; case GOTO: if(--f__cnt[f__cp]<=0) { f__cp--; f__rp--; f__pc++; goto loop; } f__pc=1+f__ret[f__rp--]; goto loop; case REVERT: f__rp=f__cp=0; f__pc = p->p1; if(ptr==NULL) return((*f__doend)()); if(!f__workdone) return(0); if((n=(*f__dorevert)()) != 0) return(n); goto loop; case COLON: if(ptr==NULL) return((*f__doend)()); f__pc++; goto loop; case NONL: f__nonl = 1; f__pc++; goto loop; case S: case SS: f__cplus=0; f__pc++; goto loop; case SP: f__cplus = 1; f__pc++; goto loop; case P: f__scale=p->p1; f__pc++; goto loop; case BN: f__cblank=0; f__pc++; goto loop; case BZ: f__cblank=1; f__pc++; goto loop; } } return(0); } int en_fio(void) { ftnint one=1; return(do_fio(&one,(char *)NULL,(ftnint)0)); } void fmt_bg(void) { f__workdone=f__cp=f__rp=f__pc=f__cursor=0; f__cnt[0]=f__ret[0]=0; } blis-0.9.0/blastest/f2c/fmt.h000066400000000000000000000054631422157504600157210ustar00rootroot00000000000000/**************************************************************** Copyright 1990 - 1997 by AT&T, Lucent Technologies and Bellcore. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that the copyright notice and this permission notice and warranty disclaimer appear in supporting documentation, and that the names of AT&T, Bell Laboratories, Lucent or Bellcore or any of their entities not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. AT&T, Lucent and Bellcore disclaim all warranties with regard to this software, including all implied warranties of merchantability and fitness. In no event shall AT&T, Lucent or Bellcore be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software. ****************************************************************/ struct syl { int op; int p1; union { int i[2]; char *s;} p2; }; #define RET1 1 #define REVERT 2 #define GOTO 3 #define X 4 #define SLASH 5 #define STACK 6 #define I 7 #define ED 8 #define NED 9 #define IM 10 #define APOS 11 #define H 12 #define TL 13 #define TR 14 #define T 15 #define COLON 16 #define S 17 #define SP 18 #define SS 19 #define P 20 #define BN 21 #define BZ 22 #define F 23 #define E 24 #define EE 25 #define D 26 #define G 27 #define GE 28 #define L 29 #define A 30 #define AW 31 #define O 32 #define NONL 33 #define OM 34 #define Z 35 #define ZM 36 typedef union { real pf; doublereal pd; } ufloat; typedef union { short is; signed char ic; integer il; #ifdef Allow_TYQUAD longint ili; #endif } Uint; #ifdef __cplusplus extern "C" { #define Cextern extern "C" #else #define Cextern extern #endif /* __cplusplus */ extern const char *f__fmtbuf; extern int (*f__doed)(struct syl*, char*, ftnlen),(*f__doned)(struct syl*); extern int (*f__dorevert)(void); extern void fmt_bg(void); extern int pars_f(const char*); extern int rd_ed(struct syl*, char*, ftnlen),rd_ned(struct syl*); extern int w_ed(struct syl*, char*, ftnlen),w_ned(struct syl*); extern int wrt_E(ufloat*, int, int, int, ftnlen); extern int wrt_F(ufloat*, int, int, ftnlen); extern int wrt_L(Uint*, int, ftnlen); extern int f__pc,f__parenlvl,f__revloc; extern flag f__cblank,f__cplus,f__workdone, f__nonl; extern int f__scale; #ifdef __cplusplus } #endif #define GET(x) if((x=(*f__getn)())<0) return(x) #define VAL(x) (x!='\n'?x:' ') #define PUT(x) (*f__putn)(x) #undef TYQUAD #ifndef Allow_TYQUAD #undef longint #define longint long #else #define TYQUAD 14 #endif blis-0.9.0/blastest/f2c/fmtlib.c000066400000000000000000000037271422157504600164040ustar00rootroot00000000000000/**************************************************************** Copyright 1990 - 1997 by AT&T, Lucent Technologies and Bellcore. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that the copyright notice and this permission notice and warranty disclaimer appear in supporting documentation, and that the names of AT&T, Bell Laboratories, Lucent or Bellcore or any of their entities not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. AT&T, Lucent and Bellcore disclaim all warranties with regard to this software, including all implied warranties of merchantability and fitness. In no event shall AT&T, Lucent or Bellcore be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software. ****************************************************************/ #include /* @(#)fmtlib.c 1.2 */ #define MAXINTLENGTH 23 #include "f2c.h" #ifndef Allow_TYQUAD #undef longint #define longint long #undef ulongint #define ulongint unsigned long #endif #ifdef INTEGER_STAR_8 char *f__icvt(longint value, int *ndigit, int *sign, int base) #else char *f__icvt(integer value, int *ndigit, int *sign, int base) #endif { static char buf[MAXINTLENGTH+1]; register int i; ulongint uvalue; if(value > 0) { uvalue = value; *sign = 0; } else if (value < 0) { uvalue = -value; *sign = 1; } else { *sign = 0; *ndigit = 1; buf[MAXINTLENGTH-1] = '0'; return &buf[MAXINTLENGTH-1]; } i = MAXINTLENGTH; do { buf[--i] = (uvalue%base) + '0'; uvalue /= base; } while(uvalue > 0); *ndigit = MAXINTLENGTH - i; return &buf[i]; } blis-0.9.0/blastest/f2c/fp.h000066400000000000000000000035251422157504600155350ustar00rootroot00000000000000/**************************************************************** Copyright 1990 - 1997 by AT&T, Lucent Technologies and Bellcore. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that the copyright notice and this permission notice and warranty disclaimer appear in supporting documentation, and that the names of AT&T, Bell Laboratories, Lucent or Bellcore or any of their entities not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. AT&T, Lucent and Bellcore disclaim all warranties with regard to this software, including all implied warranties of merchantability and fitness. In no event shall AT&T, Lucent or Bellcore be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software. ****************************************************************/ #define FMAX 40 #define EXPMAXDIGS 8 #define EXPMAX 99999999 /* FMAX = max number of nonzero digits passed to atof() */ /* EXPMAX = 10^EXPMAXDIGS - 1 = largest allowed exponent absolute value */ #ifdef V10 /* Research Tenth-Edition Unix */ #include "local.h" #endif /* MAXFRACDIGS and MAXINTDIGS are for wrt_F -- bounds (not necessarily tight) on the maximum number of digits to the right and left of * the decimal point. */ #ifdef VAX #define MAXFRACDIGS 56 #define MAXINTDIGS 38 #else #ifdef CRAY #define MAXFRACDIGS 9880 #define MAXINTDIGS 9864 #else /* values that suffice for IEEE double */ #define MAXFRACDIGS 344 #define MAXINTDIGS 308 #endif #endif blis-0.9.0/blastest/f2c/h_dnnt.c000066400000000000000000000025421422157504600163730ustar00rootroot00000000000000/**************************************************************** Copyright 1990 - 1997 by AT&T, Lucent Technologies and Bellcore. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that the copyright notice and this permission notice and warranty disclaimer appear in supporting documentation, and that the names of AT&T, Bell Laboratories, Lucent or Bellcore or any of their entities not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. AT&T, Lucent and Bellcore disclaim all warranties with regard to this software, including all implied warranties of merchantability and fitness. In no event shall AT&T, Lucent or Bellcore be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software. ****************************************************************/ #include "f2c.h" #ifdef __cplusplus extern "C" { #endif shortint h_dnnt(const doublereal *x) { return (shortint)round(*x); } #ifdef __cplusplus } #endif blis-0.9.0/blastest/f2c/hl_cmp.c000066400000000000000000000035201422157504600163600ustar00rootroot00000000000000/**************************************************************** Copyright 1990 - 1997 by AT&T, Lucent Technologies and Bellcore. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that the copyright notice and this permission notice and warranty disclaimer appear in supporting documentation, and that the names of AT&T, Bell Laboratories, Lucent or Bellcore or any of their entities not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. AT&T, Lucent and Bellcore disclaim all warranties with regard to this software, including all implied warranties of merchantability and fitness. In no event shall AT&T, Lucent or Bellcore be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software. ****************************************************************/ #include "f2c.h" #ifdef __cplusplus extern "C" { #endif extern integer s_cmp(const char *, const char *, ftnlen, ftnlen); shortlogical hl_ge(const char *a, const char *b, ftnlen la, ftnlen lb) { return(s_cmp(a,b,la,lb) >= 0); } shortlogical hl_gt(const char *a, const char *b, ftnlen la, ftnlen lb) { return(s_cmp(a,b,la,lb) > 0); } shortlogical hl_le(const char *a, const char *b, ftnlen la, ftnlen lb) { return(s_cmp(a,b,la,lb) <= 0); } shortlogical hl_lt(const char *a, const char *b, ftnlen la, ftnlen lb) { return(s_cmp(a,b,la,lb) < 0); } #ifdef __cplusplus } #endif blis-0.9.0/blastest/f2c/i_dnnt.c000066400000000000000000000025401422157504600163720ustar00rootroot00000000000000/**************************************************************** Copyright 1990 - 1997 by AT&T, Lucent Technologies and Bellcore. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that the copyright notice and this permission notice and warranty disclaimer appear in supporting documentation, and that the names of AT&T, Bell Laboratories, Lucent or Bellcore or any of their entities not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. AT&T, Lucent and Bellcore disclaim all warranties with regard to this software, including all implied warranties of merchantability and fitness. In no event shall AT&T, Lucent or Bellcore be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software. ****************************************************************/ #include "f2c.h" #ifdef __cplusplus extern "C" { #endif integer i_dnnt(const doublereal *x) { return (integer)round(*x); } #ifdef __cplusplus } #endif blis-0.9.0/blastest/f2c/i_len.c000066400000000000000000000025151422157504600162070ustar00rootroot00000000000000/**************************************************************** Copyright 1990 - 1997 by AT&T, Lucent Technologies and Bellcore. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that the copyright notice and this permission notice and warranty disclaimer appear in supporting documentation, and that the names of AT&T, Bell Laboratories, Lucent or Bellcore or any of their entities not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. AT&T, Lucent and Bellcore disclaim all warranties with regard to this software, including all implied warranties of merchantability and fitness. In no event shall AT&T, Lucent or Bellcore be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software. ****************************************************************/ #include "f2c.h" #ifdef __cplusplus extern "C" { #endif integer i_len(const char *s, ftnlen n) { return(n); } #ifdef __cplusplus } #endif blis-0.9.0/blastest/f2c/imag.c000066400000000000000000000025671422157504600160450ustar00rootroot00000000000000/**************************************************************** Copyright 1990 - 1997 by AT&T, Lucent Technologies and Bellcore. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that the copyright notice and this permission notice and warranty disclaimer appear in supporting documentation, and that the names of AT&T, Bell Laboratories, Lucent or Bellcore or any of their entities not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. AT&T, Lucent and Bellcore disclaim all warranties with regard to this software, including all implied warranties of merchantability and fitness. In no event shall AT&T, Lucent or Bellcore be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software. ****************************************************************/ #include "f2c.h" #ifdef __cplusplus extern "C" { #endif double r_imag(complex *z) { return z->i; } double d_imag(const doublecomplex *z) { return z->i; } #ifdef __cplusplus } #endif blis-0.9.0/blastest/f2c/int.c000066400000000000000000000027251422157504600157160ustar00rootroot00000000000000/**************************************************************** Copyright 1990 - 1997 by AT&T, Lucent Technologies and Bellcore. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that the copyright notice and this permission notice and warranty disclaimer appear in supporting documentation, and that the names of AT&T, Bell Laboratories, Lucent or Bellcore or any of their entities not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. AT&T, Lucent and Bellcore disclaim all warranties with regard to this software, including all implied warranties of merchantability and fitness. In no event shall AT&T, Lucent or Bellcore be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software. ****************************************************************/ #include "f2c.h" #ifdef __cplusplus extern "C" { #endif double d_int(const doublereal *x) { return( (*x>0) ? floor(*x) : -floor(- *x) ); } double r_int(real *x) { return( (*x>0) ? floor(*x) : -floor(- *x) ); } #ifdef __cplusplus } #endif blis-0.9.0/blastest/f2c/l_cmp.c000066400000000000000000000034221422157504600162110ustar00rootroot00000000000000/**************************************************************** Copyright 1990 - 1997 by AT&T, Lucent Technologies and Bellcore. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that the copyright notice and this permission notice and warranty disclaimer appear in supporting documentation, and that the names of AT&T, Bell Laboratories, Lucent or Bellcore or any of their entities not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. AT&T, Lucent and Bellcore disclaim all warranties with regard to this software, including all implied warranties of merchantability and fitness. In no event shall AT&T, Lucent or Bellcore be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software. ****************************************************************/ #include "f2c.h" #ifdef __cplusplus extern "C" { #endif extern integer s_cmp(const char *a0, const char *b0, ftnlen la, ftnlen lb); logical l_ge(char *a, char *b, ftnlen la, ftnlen lb) { return(s_cmp(a,b,la,lb) >= 0); } logical l_gt(char *a, char *b, ftnlen la, ftnlen lb) { return(s_cmp(a,b,la,lb) > 0); } logical l_le(char *a, char *b, ftnlen la, ftnlen lb) { return(s_cmp(a,b,la,lb) <= 0); } logical l_lt(char *a, char *b, ftnlen la, ftnlen lb) { return(s_cmp(a,b,la,lb) < 0); } #ifdef __cplusplus } #endif blis-0.9.0/blastest/f2c/lg10.c000066400000000000000000000026471422157504600156720ustar00rootroot00000000000000/**************************************************************** Copyright 1990 - 1997 by AT&T, Lucent Technologies and Bellcore. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that the copyright notice and this permission notice and warranty disclaimer appear in supporting documentation, and that the names of AT&T, Bell Laboratories, Lucent or Bellcore or any of their entities not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. AT&T, Lucent and Bellcore disclaim all warranties with regard to this software, including all implied warranties of merchantability and fitness. In no event shall AT&T, Lucent or Bellcore be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software. ****************************************************************/ #include "f2c.h" #ifdef __cplusplus extern "C" { #endif double r_lg10(real *x) { return( log10(*x) ); } double d_lg10(const doublereal *x) { return( log10(*x) ); } #ifdef __cplusplus } #endif blis-0.9.0/blastest/f2c/lio.h000066400000000000000000000040501422157504600157050ustar00rootroot00000000000000/**************************************************************** Copyright 1990 - 1997 by AT&T, Lucent Technologies and Bellcore. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that the copyright notice and this permission notice and warranty disclaimer appear in supporting documentation, and that the names of AT&T, Bell Laboratories, Lucent or Bellcore or any of their entities not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. AT&T, Lucent and Bellcore disclaim all warranties with regard to this software, including all implied warranties of merchantability and fitness. In no event shall AT&T, Lucent or Bellcore be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software. ****************************************************************/ /* copy of ftypes from the compiler */ /* variable types * numeric assumptions: * int < reals < complexes * TYDREAL-TYREAL = TYDCOMPLEX-TYCOMPLEX */ /* 0-10 retain their old (pre LOGICAL*1, etc.) */ /* values to allow mixing old and new objects. */ #define TYUNKNOWN 0 #define TYADDR 1 #define TYSHORT 2 #define TYLONG 3 #define TYREAL 4 #define TYDREAL 5 #define TYCOMPLEX 6 #define TYDCOMPLEX 7 #define TYLOGICAL 8 #define TYCHAR 9 #define TYSUBR 10 #define TYINT1 11 #define TYLOGICAL1 12 #define TYLOGICAL2 13 #ifdef Allow_TYQUAD #undef TYQUAD #define TYQUAD 14 #endif #define LINTW 24 #define LINE 80 #define LLOGW 2 #define LGFMT "%.9G" /* LEFBL 20 should suffice; 24 overcomes a NeXT bug. */ #define LEFBL 24 typedef union { char flchar; short flshort; ftnint flint; #ifdef Allow_TYQUAD longint fllongint; #endif real flreal; doublereal fldouble; } flex; blis-0.9.0/blastest/f2c/log.c000066400000000000000000000033431422157504600157020ustar00rootroot00000000000000/**************************************************************** Copyright 1990 - 1997 by AT&T, Lucent Technologies and Bellcore. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that the copyright notice and this permission notice and warranty disclaimer appear in supporting documentation, and that the names of AT&T, Bell Laboratories, Lucent or Bellcore or any of their entities not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. AT&T, Lucent and Bellcore disclaim all warranties with regard to this software, including all implied warranties of merchantability and fitness. In no event shall AT&T, Lucent or Bellcore be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software. ****************************************************************/ #include "f2c.h" #ifdef __cplusplus extern "C" { #endif double r_log(real *x) { return( log(*x) ); } double d_log(const doublereal *x) { return( log(*x) ); } void c_log(complex *r, complex *z) { double zi, zr; r->i = atan2(zi = z->i, zr = z->r); r->r = log( hypot(zr, zi) ); } void z_log(doublecomplex *r, doublecomplex *z) { double zi, zr; r->i = atan2(zi = z->i, zr = z->r); r->r = log( hypot(zr, zi) ); } #ifdef __cplusplus } #endif blis-0.9.0/blastest/f2c/lread.c000066400000000000000000000351371422157504600162160ustar00rootroot00000000000000/**************************************************************** Copyright 1990 - 1997 by AT&T, Lucent Technologies and Bellcore. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that the copyright notice and this permission notice and warranty disclaimer appear in supporting documentation, and that the names of AT&T, Bell Laboratories, Lucent or Bellcore or any of their entities not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. AT&T, Lucent and Bellcore disclaim all warranties with regard to this software, including all implied warranties of merchantability and fitness. In no event shall AT&T, Lucent or Bellcore be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software. ****************************************************************/ #include #include #include "f2c.h" #include "fio.h" /* Compile with -DF8X_NML_ELIDE_QUOTES to permit eliding quotation */ /* marks in namelist input a la the Fortran 8X Draft published in */ /* the May 1989 issue of Fortran Forum. */ #ifdef Allow_TYQUAD static longint f__llx; #endif #undef abs #undef min #undef max #include #include "fmt.h" #include "lio.h" #include "fp.h" int l_eof; int (*l_getc)(void); int (*l_ungetc)(int,FILE*); int (*f__lioproc)(ftnint*, char*, ftnlen, ftnint); #define isblnk(x) (f__ltab[x+1]&B) #define issep(x) (f__ltab[x+1]&SX) #define isapos(x) (f__ltab[x+1]&AX) #define isexp(x) (f__ltab[x+1]&EX) #define issign(x) (f__ltab[x+1]&SG) #define iswhit(x) (f__ltab[x+1]&WH) #define SX 1 #define B 2 #define AX 4 #define EX 8 #define SG 16 #define WH 32 static char f__ltab[128+1] = { /* offset one for EOF */ 0, 0,0,AX,0,0,0,0,0,0,WH|B,SX|WH,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, SX|B|WH,0,AX,0,0,0,0,AX,0,0,0,SG,SX,SG,0,SX, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,EX,EX,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, AX,0,0,0,EX,EX,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; #ifdef ungetc static int un_getc(int x, FILE *f__cf) { return ungetc(x,f__cf); } #else #define un_getc ungetc #endif int t_getc(void) { int ch; if(f__curunit->uend) return(EOF); if((ch=getc(f__cf))!=EOF) return(ch); if(feof(f__cf)) f__curunit->uend = l_eof = 1; return(EOF); } integer e_rsle(void) { int ch; if(f__curunit->uend) return(0); while((ch=t_getc())!='\n') if (ch == EOF) { if(feof(f__cf)) f__curunit->uend = l_eof = 1; return EOF; } return(0); } flag f__lquit; int f__lcount,f__ltype,nml_read; char *f__lchar; double f__lx,f__ly; #define ERR(x) if(n=(x)) return(n) #define GETC(x) (x=(*l_getc)()) #define Ungetc(x,y) (*l_ungetc)(x,y) static int l_R(int poststar, int reqint) { char s[FMAX+EXPMAXDIGS+4]; register int ch; register char *sp, *spe, *sp1; long e, exp; int havenum, havestar, se; if (!poststar) { if (f__lcount > 0) return(0); f__lcount = 1; } #ifdef Allow_TYQUAD f__llx = 0; #endif f__ltype = 0; exp = 0; havestar = 0; retry: sp1 = sp = s; spe = sp + FMAX; havenum = 0; switch(GETC(ch)) { case '-': *sp++ = ch; sp1++; spe++; case '+': GETC(ch); } while(ch == '0') { ++havenum; GETC(ch); } while(isdigit(ch)) { if (sp < spe) *sp++ = ch; else ++exp; GETC(ch); } if (ch == '*' && !poststar) { if (sp == sp1 || exp || *s == '-') { errfl(f__elist->cierr,112,"bad repetition count"); } poststar = havestar = 1; *sp = 0; f__lcount = atoi(s); goto retry; } if (ch == '.') { #ifndef ALLOW_FLOAT_IN_INTEGER_LIST_INPUT if (reqint) errfl(f__elist->cierr,115,"invalid integer"); #endif GETC(ch); if (sp == sp1) while(ch == '0') { ++havenum; --exp; GETC(ch); } while(isdigit(ch)) { if (sp < spe) { *sp++ = ch; --exp; } GETC(ch); } } havenum += sp - sp1; se = 0; if (issign(ch)) goto signonly; if (havenum && isexp(ch)) { #ifndef ALLOW_FLOAT_IN_INTEGER_LIST_INPUT if (reqint) errfl(f__elist->cierr,115,"invalid integer"); #endif GETC(ch); if (issign(ch)) { signonly: if (ch == '-') se = 1; GETC(ch); } if (!isdigit(ch)) { bad: errfl(f__elist->cierr,112,"exponent field"); } e = ch - '0'; while(isdigit(GETC(ch))) { e = 10*e + ch - '0'; if (e > EXPMAX) goto bad; } if (se) exp -= e; else exp += e; } (void) Ungetc(ch, f__cf); if (sp > sp1) { ++havenum; while(*--sp == '0') ++exp; if (exp) sprintf(sp+1, "e%ld", exp); else sp[1] = 0; f__lx = atof(s); #ifdef Allow_TYQUAD if (reqint&2 && (se = sp - sp1 + exp) > 14 && se < 20) { /* Assuming 64-bit longint and 32-bit long. */ if (exp < 0) sp += exp; if (sp1 <= sp) { f__llx = *sp1 - '0'; while(++sp1 <= sp) f__llx = 10*f__llx + (*sp1 - '0'); } while(--exp >= 0) f__llx *= 10; if (*s == '-') f__llx = -f__llx; } #endif } else f__lx = 0.; if (havenum) f__ltype = TYLONG; else switch(ch) { case ',': case '/': break; default: if (havestar && ( ch == ' ' ||ch == '\t' ||ch == '\n')) break; if (nml_read > 1) { f__lquit = 2; return 0; } errfl(f__elist->cierr,112,"invalid number"); } return 0; } static int rd_count(register int ch) { if (ch < '0' || ch > '9') return 1; f__lcount = ch - '0'; while(GETC(ch) >= '0' && ch <= '9') f__lcount = 10*f__lcount + ch - '0'; Ungetc(ch,f__cf); return f__lcount <= 0; } static int l_C(void) { int ch, nml_save; double lz; if(f__lcount>0) return(0); f__ltype=0; GETC(ch); if(ch!='(') { if (nml_read > 1 && (ch < '0' || ch > '9')) { Ungetc(ch,f__cf); f__lquit = 2; return 0; } if (rd_count(ch)) if(!f__cf || !feof(f__cf)) errfl(f__elist->cierr,112,"complex format"); else err(f__elist->cierr,(EOF),"lread"); if(GETC(ch)!='*') { if(!f__cf || !feof(f__cf)) errfl(f__elist->cierr,112,"no star"); else err(f__elist->cierr,(EOF),"lread"); } if(GETC(ch)!='(') { Ungetc(ch,f__cf); return(0); } } else f__lcount = 1; while(iswhit(GETC(ch))); Ungetc(ch,f__cf); nml_save = nml_read; nml_read = 0; if (ch = l_R(1,0)) return ch; if (!f__ltype) errfl(f__elist->cierr,112,"no real part"); lz = f__lx; while(iswhit(GETC(ch))); if(ch!=',') { (void) Ungetc(ch,f__cf); errfl(f__elist->cierr,112,"no comma"); } while(iswhit(GETC(ch))); (void) Ungetc(ch,f__cf); if (ch = l_R(1,0)) return ch; if (!f__ltype) errfl(f__elist->cierr,112,"no imaginary part"); while(iswhit(GETC(ch))); if(ch!=')') errfl(f__elist->cierr,112,"no )"); f__ly = f__lx; f__lx = lz; #ifdef Allow_TYQUAD f__llx = 0; #endif nml_read = nml_save; return(0); } static char nmLbuf[256], *nmL_next; static int (*nmL_getc_save)(void); static int (*nmL_ungetc_save)(int, FILE*); static int nmL_getc(void) { int rv; if (rv = *nmL_next++) return rv; l_getc = nmL_getc_save; l_ungetc = nmL_ungetc_save; return (*l_getc)(); } static int nmL_ungetc(int x, FILE *f) { /* f = f;*/ /* banish non-use warning */ ( void )f; return *--nmL_next = x; } static int Lfinish(int ch, int dot, int *rvp) { char *s, *se; static char what[] = "namelist input"; s = nmLbuf + 2; se = nmLbuf + sizeof(nmLbuf) - 1; *s++ = ch; while(!issep(GETC(ch)) && ch!=EOF) { if (s >= se) { nmLbuf_ovfl: return *rvp = err__fl(f__elist->cierr,131,what); } *s++ = ch; if (ch != '=') continue; if (dot) return *rvp = err__fl(f__elist->cierr,112,what); got_eq: *s = 0; nmL_getc_save = l_getc; l_getc = nmL_getc; nmL_ungetc_save = l_ungetc; l_ungetc = nmL_ungetc; nmLbuf[1] = *(nmL_next = nmLbuf) = ','; *rvp = f__lcount = 0; return 1; } if (dot) goto done; for(;;) { if (s >= se) goto nmLbuf_ovfl; *s++ = ch; if (!isblnk(ch)) break; if (GETC(ch) == EOF) goto done; } if (ch == '=') goto got_eq; done: Ungetc(ch, f__cf); return 0; } static int l_L(void) { int ch, rv, sawdot; if(f__lcount>0) return(0); f__lcount = 1; f__ltype=0; GETC(ch); if(isdigit(ch)) { rd_count(ch); if(GETC(ch)!='*') if(!f__cf || !feof(f__cf)) errfl(f__elist->cierr,112,"no star"); else err(f__elist->cierr,(EOF),"lread"); GETC(ch); } sawdot = 0; if(ch == '.') { sawdot = 1; GETC(ch); } switch(ch) { case 't': case 'T': if (nml_read && Lfinish(ch, sawdot, &rv)) return rv; f__lx=1; break; case 'f': case 'F': if (nml_read && Lfinish(ch, sawdot, &rv)) return rv; f__lx=0; break; default: if(isblnk(ch) || issep(ch) || ch==EOF) { (void) Ungetc(ch,f__cf); return(0); } if (nml_read > 1) { Ungetc(ch,f__cf); f__lquit = 2; return 0; } errfl(f__elist->cierr,112,"logical"); } f__ltype=TYLONG; while(!issep(GETC(ch)) && ch!=EOF); Ungetc(ch, f__cf); return(0); } #define BUFSIZE 128 static int l_CHAR(void) { int ch,size,i; static char rafail[] = "realloc failure"; char quote,*p; if(f__lcount>0) return(0); f__ltype=0; if(f__lchar!=NULL) free(f__lchar); size=BUFSIZE; p=f__lchar = (char *)malloc((unsigned int)size); if(f__lchar == NULL) errfl(f__elist->cierr,113,"no space"); GETC(ch); if(isdigit(ch)) { /* allow Fortran 8x-style unquoted string... */ /* either find a repetition count or the string */ f__lcount = ch - '0'; *p++ = ch; for(i = 1;;) { switch(GETC(ch)) { case '*': if (f__lcount == 0) { f__lcount = 1; #ifndef F8X_NML_ELIDE_QUOTES if (nml_read) goto no_quote; #endif goto noquote; } p = f__lchar; goto have_lcount; case ',': case ' ': case '\t': case '\n': case '/': Ungetc(ch,f__cf); /* no break */ case EOF: f__lcount = 1; f__ltype = TYCHAR; return *p = 0; } if (!isdigit(ch)) { f__lcount = 1; #ifndef F8X_NML_ELIDE_QUOTES if (nml_read) { no_quote: errfl(f__elist->cierr,112, "undelimited character string"); } #endif goto noquote; } *p++ = ch; f__lcount = 10*f__lcount + ch - '0'; if (++i == size) { f__lchar = (char *)realloc(f__lchar, (unsigned int)(size += BUFSIZE)); if(f__lchar == NULL) errfl(f__elist->cierr,113,rafail); p = f__lchar + i; } } } else (void) Ungetc(ch,f__cf); have_lcount: if(GETC(ch)=='\'' || ch=='"') quote=ch; else if(isblnk(ch) || (issep(ch) && ch != '\n') || ch==EOF) { Ungetc(ch,f__cf); return 0; } #ifndef F8X_NML_ELIDE_QUOTES else if (nml_read > 1) { Ungetc(ch,f__cf); f__lquit = 2; return 0; } #endif else { /* Fortran 8x-style unquoted string */ *p++ = ch; for(i = 1;;) { switch(GETC(ch)) { case ',': case ' ': case '\t': case '\n': case '/': Ungetc(ch,f__cf); /* no break */ case EOF: f__ltype = TYCHAR; return *p = 0; } noquote: *p++ = ch; if (++i == size) { f__lchar = (char *)realloc(f__lchar, (unsigned int)(size += BUFSIZE)); if(f__lchar == NULL) errfl(f__elist->cierr,113,rafail); p = f__lchar + i; } } } f__ltype=TYCHAR; for(i=0;;) { while(GETC(ch)!=quote && ch!='\n' && ch!=EOF && ++icierr,113,rafail); p=f__lchar+i-1; *p++ = ch; } else if(ch==EOF) return(EOF); else if(ch=='\n') { if(*(p-1) != '\\') continue; i--; p--; if(++iciunit]; if(a->ciunit>=MXUNIT || a->ciunit<0) err(a->cierr,101,"stler"); f__scale=f__recpos=0; f__elist=a; if(f__curunit->ufd==NULL && fk_open(SEQ,FMT,a->ciunit)) err(a->cierr,102,"lio"); f__cf=f__curunit->ufd; if(!f__curunit->ufmt) err(a->cierr,103,"lio") return(0); } int l_read(ftnint *number, char *ptr, ftnlen len, ftnint type) { #define Ptr ((flex *)ptr) int i,n,ch; doublereal *yy; real *xx; for(i=0;i<*number;i++) { if(f__lquit) return(0); if(l_eof) err(f__elist->ciend, EOF, "list in") if(f__lcount == 0) { f__ltype = 0; for(;;) { GETC(ch); switch(ch) { case EOF: err(f__elist->ciend,(EOF),"list in") case ' ': case '\t': case '\n': continue; case '/': f__lquit = 1; goto loopend; case ',': f__lcount = 1; goto loopend; default: (void) Ungetc(ch, f__cf); goto rddata; } } } rddata: switch((int)type) { case TYINT1: case TYSHORT: case TYLONG: #ifndef ALLOW_FLOAT_IN_INTEGER_LIST_INPUT ERR(l_R(0,1)); break; #endif case TYREAL: case TYDREAL: ERR(l_R(0,0)); break; #ifdef TYQUAD case TYQUAD: n = l_R(0,2); if (n) return n; break; #endif case TYCOMPLEX: case TYDCOMPLEX: ERR(l_C()); break; case TYLOGICAL1: case TYLOGICAL2: case TYLOGICAL: ERR(l_L()); break; case TYCHAR: ERR(l_CHAR()); break; } while (GETC(ch) == ' ' || ch == '\t'); if (ch != ',' || f__lcount > 1) Ungetc(ch,f__cf); loopend: if(f__lquit) return(0); if(f__cf && ferror(f__cf)) { clearerr(f__cf); errfl(f__elist->cierr,errno,"list in"); } if(f__ltype==0) goto bump; switch((int)type) { case TYINT1: case TYLOGICAL1: Ptr->flchar = (char)f__lx; break; case TYLOGICAL2: case TYSHORT: Ptr->flshort = (short)f__lx; break; case TYLOGICAL: case TYLONG: Ptr->flint = (ftnint)f__lx; break; #ifdef Allow_TYQUAD case TYQUAD: if (!(Ptr->fllongint = f__llx)) Ptr->fllongint = f__lx; break; #endif case TYREAL: Ptr->flreal=f__lx; break; case TYDREAL: Ptr->fldouble=f__lx; break; case TYCOMPLEX: xx=(real *)ptr; *xx++ = f__lx; *xx = f__ly; break; case TYDCOMPLEX: yy=(doublereal *)ptr; *yy++ = f__lx; *yy = f__ly; break; case TYCHAR: b_char(f__lchar,ptr,len); break; } bump: if(f__lcount>0) f__lcount--; ptr += len; if (nml_read) nml_read++; } return(0); #undef Ptr } integer s_rsle(cilist *a) { int n; f__reading=1; f__external=1; f__formatted=1; if(n=c_le(a)) return(n); f__lioproc = l_read; f__lquit = 0; f__lcount = 0; l_eof = 0; if(f__curunit->uwrt && f__nowreading(f__curunit)) err(a->cierr,errno,"read start"); if(f__curunit->uend) err(f__elist->ciend,(EOF),"read start"); l_getc = t_getc; l_ungetc = un_getc; f__doend = xrd_SL; return(0); } blis-0.9.0/blastest/f2c/lwrite.c000066400000000000000000000116141422157504600164270ustar00rootroot00000000000000/**************************************************************** Copyright 1990 - 1997 by AT&T, Lucent Technologies and Bellcore. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that the copyright notice and this permission notice and warranty disclaimer appear in supporting documentation, and that the names of AT&T, Bell Laboratories, Lucent or Bellcore or any of their entities not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. AT&T, Lucent and Bellcore disclaim all warranties with regard to this software, including all implied warranties of merchantability and fitness. In no event shall AT&T, Lucent or Bellcore be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software. ****************************************************************/ #include #include "f2c.h" #include "fio.h" #include "fmt.h" #include "lio.h" #include "arith.h" ftnint L_len; int f__Aquote; static void donewrec(void) { if (f__recpos) (*f__donewrec)(); } static void lwrt_I(longint n) { char *p; int ndigit, sign; p = f__icvt(n, &ndigit, &sign, 10); if(f__recpos + ndigit >= L_len) donewrec(); PUT(' '); if (sign) PUT('-'); while(*p) PUT(*p++); } static void lwrt_L(ftnint n, ftnlen len) { if(f__recpos+LLOGW>=L_len) donewrec(); wrt_L((Uint *)&n,LLOGW, len); } static void lwrt_A(char *p, ftnlen len) { int a; char *p1, *pe; a = 0; pe = p + len; if (f__Aquote) { a = 3; if (len > 1 && p[len-1] == ' ') { while(--len > 1 && p[len-1] == ' '); pe = p + len; } p1 = p; while(p1 < pe) if (*p1++ == '\'') a++; } if(f__recpos+len+a >= L_len) donewrec(); if (a #ifndef OMIT_BLANK_CC || !f__recpos #endif ) PUT(' '); if (a) { PUT('\''); while(p < pe) { if (*p == '\'') PUT('\''); PUT(*p++); } PUT('\''); } else while(p < pe) PUT(*p++); } static int l_g(char *buf, double n) { register char *b, c, c1; b = buf; *b++ = ' '; if (n < 0) { *b++ = '-'; n = -n; } else *b++ = ' '; if (n == 0) { #ifdef SIGNED_ZEROS if (signbit(n)) *b++ = '-'; #endif *b++ = '0'; *b++ = '.'; *b = 0; goto f__ret; } sprintf(b, LGFMT, n); switch(*b) { #ifndef WANT_LEAD_0 case '0': while(b[0] = b[1]) b++; break; #endif case 'i': case 'I': /* Infinity */ case 'n': case 'N': /* NaN */ while(*++b); break; default: /* Fortran 77 insists on having a decimal point... */ for(;; b++) switch(*b) { case 0: *b++ = '.'; *b = 0; goto f__ret; case '.': while(*++b); goto f__ret; case 'E': for(c1 = '.', c = 'E'; *b = c1; c1 = c, c = *++b); goto f__ret; } } f__ret: return b - buf; } static void l_put(register char *s) { #ifdef KR_headers register void (*pn)() = f__putn; #else register void (*pn)(int) = f__putn; #endif register int c; while(c = *s++) (*pn)(c); } static void lwrt_F(double n) { char buf[LEFBL]; if(f__recpos + l_g(buf,n) >= L_len) donewrec(); l_put(buf); } static void lwrt_C(double a, double b) { char *ba, *bb, bufa[LEFBL], bufb[LEFBL]; int al, bl; al = l_g(bufa, a); for(ba = bufa; *ba == ' '; ba++) --al; bl = l_g(bufb, b) + 1; /* intentionally high by 1 */ for(bb = bufb; *bb == ' '; bb++) --bl; if(f__recpos + al + bl + 3 >= L_len) donewrec(); #ifdef OMIT_BLANK_CC else #endif PUT(' '); PUT('('); l_put(ba); PUT(','); if (f__recpos + bl >= L_len) { (*f__donewrec)(); #ifndef OMIT_BLANK_CC PUT(' '); #endif } l_put(bb); PUT(')'); } int l_write(ftnint *number, char *ptr, ftnlen len, ftnint type) { #define Ptr ((flex *)ptr) int i; longint x; double y,z; real *xx; doublereal *yy; for(i=0;i< *number; i++) { switch((int)type) { default: f__fatal(117,"unknown type in lio"); case TYINT1: x = Ptr->flchar; goto xint; case TYSHORT: x=Ptr->flshort; goto xint; #ifdef Allow_TYQUAD case TYQUAD: x = Ptr->fllongint; goto xint; #endif case TYLONG: x=Ptr->flint; xint: lwrt_I(x); break; case TYREAL: y=Ptr->flreal; goto xfloat; case TYDREAL: y=Ptr->fldouble; xfloat: lwrt_F(y); break; case TYCOMPLEX: xx= &Ptr->flreal; y = *xx++; z = *xx; goto xcomplex; case TYDCOMPLEX: yy = &Ptr->fldouble; y= *yy++; z = *yy; xcomplex: lwrt_C(y,z); break; case TYLOGICAL1: x = Ptr->flchar; goto xlog; case TYLOGICAL2: x = Ptr->flshort; goto xlog; case TYLOGICAL: x = Ptr->flint; xlog: lwrt_L(Ptr->flint, len); break; case TYCHAR: lwrt_A(ptr,len); break; } ptr += len; } return(0); } blis-0.9.0/blastest/f2c/mod.c000066400000000000000000000037241422157504600157030ustar00rootroot00000000000000/**************************************************************** Copyright 1990 - 1997 by AT&T, Lucent Technologies and Bellcore. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that the copyright notice and this permission notice and warranty disclaimer appear in supporting documentation, and that the names of AT&T, Bell Laboratories, Lucent or Bellcore or any of their entities not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. AT&T, Lucent and Bellcore disclaim all warranties with regard to this software, including all implied warranties of merchantability and fitness. In no event shall AT&T, Lucent or Bellcore be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software. ****************************************************************/ #include "f2c.h" #ifdef __cplusplus extern "C" { #endif shortint h_mod(const short *a, const short *b) { return( *a % *b); } integer i_mod(const integer *a, const integer *b) { return( *a % *b); } double r_mod(real *x, real *y) { double quotient; if( (quotient = (double)*x / *y) >= 0) quotient = floor(quotient); else quotient = -floor(-quotient); return(*x - (*y) * quotient ); } double d_mod(const doublereal *x, const doublereal *y) { double quotient; if( (quotient = *x / *y) >= 0) quotient = floor(quotient); else quotient = -floor(-quotient); return(*x - (*y) * quotient ); } #ifdef __cplusplus } #endif blis-0.9.0/blastest/f2c/nint.c000066400000000000000000000033231422157504600160670ustar00rootroot00000000000000/**************************************************************** Copyright 1990 - 1997 by AT&T, Lucent Technologies and Bellcore. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that the copyright notice and this permission notice and warranty disclaimer appear in supporting documentation, and that the names of AT&T, Bell Laboratories, Lucent or Bellcore or any of their entities not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. AT&T, Lucent and Bellcore disclaim all warranties with regard to this software, including all implied warranties of merchantability and fitness. In no event shall AT&T, Lucent or Bellcore be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software. ****************************************************************/ #include "f2c.h" #ifdef __cplusplus extern "C" { #endif double d_nint(const doublereal *x) { return( (*x)>=0 ? floor(*x + .5) : -floor(.5 - *x) ); } shortint h_nint(const real *x) { return (shortint)(*x >= 0 ? floor(*x + .5) : -floor(.5 - *x)); } integer i_nint(const real *x) { return (integer)(*x >= 0 ? floor(*x + .5) : -floor(.5 - *x)); } double r_nint(real *x) { return( (*x)>=0 ? floor(*x + .5) : -floor(.5 - *x) ); } #ifdef __cplusplus } #endif blis-0.9.0/blastest/f2c/open.c000066400000000000000000000141011422157504600160540ustar00rootroot00000000000000/**************************************************************** Copyright 1990 - 1997 by AT&T, Lucent Technologies and Bellcore. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that the copyright notice and this permission notice and warranty disclaimer appear in supporting documentation, and that the names of AT&T, Bell Laboratories, Lucent or Bellcore or any of their entities not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. AT&T, Lucent and Bellcore disclaim all warranties with regard to this software, including all implied warranties of merchantability and fitness. In no event shall AT&T, Lucent or Bellcore be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software. ****************************************************************/ #include #include #include #ifndef NON_UNIX_STDIO #include #endif #ifdef _MSC_VER #define access _access #endif #include "f2c.h" #include "fio.h" const char *f__r_mode[2] = {"rb", "r"}; const char *f__w_mode[4] = {"wb", "w", "r+b", "r+"}; static char f__buf0[400], *f__buf = f__buf0; static int f__buflen = (int)sizeof(f__buf0); static void f__bufadj(int n, int c) { unsigned int len; char *nbuf, *s, *t, *te; if (f__buf == f__buf0) f__buflen = 1024; while(f__buflen <= n) f__buflen <<= 1; len = (unsigned int)f__buflen; if (len != f__buflen || !(nbuf = (char*)malloc(len))) { f__fatal(113, "malloc failure"); } else { s = nbuf; t = f__buf; te = t + c; while (t < te) *s++ = *t++; if (f__buf != f__buf0) free(f__buf); f__buf = nbuf; } } int f__putbuf(int c) { char *s, *se; int n; if (f__hiwater > f__recpos) f__recpos = f__hiwater; n = f__recpos + 1; if (n >= f__buflen) f__bufadj(n, f__recpos); s = f__buf; se = s + f__recpos; if (c) *se++ = c; *se = 0; for(;;) { fputs(s, f__cf); s += strlen(s); if (s >= se) break; /* normally happens the first time */ putc(*s++, f__cf); } return 0; } void x_putc(int c) { if (f__recpos >= f__buflen) f__bufadj(f__recpos, f__buflen); f__buf[f__recpos++] = c; } #define opnerr(f,m,s) {if(f) errno= m; else opn_err(m,s,a); return(m);} static void opn_err(int m, const char *s, olist *a) { if (a->ofnm) { /* supply file name to error message */ if (a->ofnmlen >= f__buflen) f__bufadj((int)a->ofnmlen, 0); g_char(a->ofnm, a->ofnmlen, f__curunit->ufnm = f__buf); } f__fatal(m, s); } integer f_open(olist *a) { unit *b; integer rv; char buf[256], *s; cllist x; int ufmt; FILE *tf; #ifndef NON_UNIX_STDIO int n; #endif f__external = 1; if(a->ounit>=MXUNIT || a->ounit<0) err(a->oerr,101,"open") if (!f__init) f_init(); f__curunit = b = &f__units[a->ounit]; if(b->ufd) { if(a->ofnm==0) { same: if (a->oblnk) b->ublnk = *a->oblnk == 'z' || *a->oblnk == 'Z'; return(0); } #ifdef NON_UNIX_STDIO if (b->ufnm && strlen(b->ufnm) == a->ofnmlen && !strncmp(b->ufnm, a->ofnm, (unsigned)a->ofnmlen)) goto same; #else g_char(a->ofnm,a->ofnmlen,buf); if (f__inode(buf,&n) == b->uinode && n == b->udev) goto same; #endif x.cunit=a->ounit; x.csta=0; x.cerr=a->oerr; if ((rv = f_clos(&x)) != 0) return rv; } b->url = (int)a->orl; b->ublnk = a->oblnk && (*a->oblnk == 'z' || *a->oblnk == 'Z'); if(a->ofm==0) { if(b->url>0) b->ufmt=0; else b->ufmt=1; } else if(*a->ofm=='f' || *a->ofm == 'F') b->ufmt=1; else b->ufmt=0; ufmt = b->ufmt; #ifdef url_Adjust if (b->url && !ufmt) url_Adjust(b->url); #endif if (a->ofnm) { g_char(a->ofnm,a->ofnmlen,buf); if (!buf[0]) opnerr(a->oerr,107,"open") } else sprintf(buf, "fort.%ld", (long)a->ounit); b->uscrtch = 0; b->uend=0; b->uwrt = 0; b->ufd = 0; b->urw = 3; switch(a->osta ? *a->osta : 'u') { case 'o': case 'O': if (access(buf,0)) opnerr(a->oerr,errno,"open") break; case 's': case 'S': b->uscrtch=1; #ifdef HAVE_TMPFILE if (!(b->ufd = tmpfile())) opnerr(a->oerr,errno,"open") b->ufnm = 0; #ifndef NON_UNIX_STDIO b->uinode = b->udev = -1; #endif b->useek = 1; return 0; #else (void) strcpy(buf,"tmp.FXXXXXX"); (void) mktemp(buf); goto replace; #endif case 'n': case 'N': if (!access(buf,0)) opnerr(a->oerr,128,"open") /* no break */ case 'r': /* Fortran 90 replace option */ case 'R': #ifndef HAVE_TMPFILE replace: #endif if (tf = fopen(buf,f__w_mode[0])) fclose(tf); } b->ufnm=(char *) malloc((unsigned int)(strlen(buf)+1)); if(b->ufnm==NULL) opnerr(a->oerr,113,"no space"); (void) strcpy(b->ufnm,buf); if ((s = a->oacc) && b->url) ufmt = 0; if(!(tf = fopen(buf, f__w_mode[ufmt|2]))) { if (tf = fopen(buf, f__r_mode[ufmt])) b->urw = 1; else if (tf = fopen(buf, f__w_mode[ufmt])) { b->uwrt = 1; b->urw = 2; } else err(a->oerr, errno, "open"); } b->useek = f__canseek(b->ufd = tf); #ifndef NON_UNIX_STDIO if((b->uinode = f__inode(buf,&b->udev)) == -1) opnerr(a->oerr,108,"open") #endif if(b->useek) if (a->orl) rewind(b->ufd); else if ((s = a->oacc) && (*s == 'a' || *s == 'A') && FSEEK(b->ufd, 0L, SEEK_END)) opnerr(a->oerr,129,"open"); return(0); } int fk_open(int seq, int fmt, ftnint n) { char nbuf[10]; olist a; // FGVZ: gcc 7.3 outputs a warning that the integer value corresponding // to the "%ld" format specifier could (in theory) use up 11 bytes in a // string that only allows for five additional bytes. I use the modulo // operator to reassure gcc that the integer will be very small. //(void) sprintf(nbuf,"fort.%ld",(long)n); (void) sprintf(nbuf,"fort.%ld",(long)n % 20); a.oerr=1; a.ounit=n; a.ofnm=nbuf; a.ofnmlen=strlen(nbuf); a.osta=NULL; a.oacc= (char*)(seq==SEQ?"s":"d"); a.ofm = (char*)(fmt==FMT?"f":"u"); a.orl = seq==DIR?1:0; a.oblnk=NULL; return(f_open(&a)); } blis-0.9.0/blastest/f2c/pow.c000066400000000000000000000066141422157504600157320ustar00rootroot00000000000000/**************************************************************** Copyright 1990 - 1997 by AT&T, Lucent Technologies and Bellcore. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that the copyright notice and this permission notice and warranty disclaimer appear in supporting documentation, and that the names of AT&T, Bell Laboratories, Lucent or Bellcore or any of their entities not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. AT&T, Lucent and Bellcore disclaim all warranties with regard to this software, including all implied warranties of merchantability and fitness. In no event shall AT&T, Lucent or Bellcore be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software. ****************************************************************/ #include "f2c.h" #ifdef __cplusplus extern "C" { #endif /* Integer */ shortint pow_hh(shortint *ap, shortint *bp) { return (shortint)(pow(*ap, *bp)); } integer pow_ii(integer *ap, integer *bp) { return (integer)(pow(*ap, *bp)); } #ifdef INTEGER_STAR_8 longint pow_qq(longint *ap, longint *bp) { return (longint)(pow(*ap, *bp)); } #endif /* Double */ double pow_ri(real *ap, integer *bp) { return (pow(*ap, *bp)); } double pow_dd(doublereal *ap, doublereal *bp) { return (pow(*ap, *bp)); } double pow_di(doublereal *ap, integer *bp) { return (pow(*ap, *bp)); } /* Complex */ void pow_ci(complex *p, complex *a, integer *b) { doublecomplex p1, a1; a1.r = a->r; a1.i = a->i; pow_zi(&p1, &a1, b); p->r = p1.r; p->i = p1.i; } void pow_zz(doublecomplex *r, doublecomplex *a, doublecomplex *b) { double logr, logi, x, y; logr = log( hypot(a->r, a->i) ); logi = atan2(a->i, a->r); x = exp( logr * b->r - logi * b->i ); y = logr * b->i + logi * b->r; r->r = x * cos(y); r->i = x * sin(y); } void pow_zi(doublecomplex *p, doublecomplex *a, integer *b) { integer n; unsigned long u; double t; doublecomplex q, x; static doublecomplex one = {1.0, 0.0}; n = *b; q.r = 1; q.i = 0; if(n == 0) goto done; if(n < 0) { n = -n; z_div(&x, &one, a); } else { x.r = a->r; x.i = a->i; } for(u = n; ; ) { if(u & 01) { t = q.r * x.r - q.i * x.i; q.i = q.r * x.i + q.i * x.r; q.r = t; } if(u >>= 1) { t = x.r * x.r - x.i * x.i; x.i = 2 * x.r * x.i; x.r = t; } else break; } done: p->i = q.i; p->r = q.r; } #ifdef __cplusplus } #endif blis-0.9.0/blastest/f2c/prod.c000066400000000000000000000025761422157504600160740ustar00rootroot00000000000000/**************************************************************** Copyright 1990 - 1997 by AT&T, Lucent Technologies and Bellcore. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that the copyright notice and this permission notice and warranty disclaimer appear in supporting documentation, and that the names of AT&T, Bell Laboratories, Lucent or Bellcore or any of their entities not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. AT&T, Lucent and Bellcore disclaim all warranties with regard to this software, including all implied warranties of merchantability and fitness. In no event shall AT&T, Lucent or Bellcore be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software. ****************************************************************/ #include "f2c.h" #ifdef __cplusplus extern "C" { #endif double d_prod(const real *x, const real *y) { return( (double)(*x) * (double)(*y) ); } #ifdef __cplusplus } #endif blis-0.9.0/blastest/f2c/rdfmt.c000066400000000000000000000220711422157504600162340ustar00rootroot00000000000000/**************************************************************** Copyright 1990 - 1997 by AT&T, Lucent Technologies and Bellcore. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that the copyright notice and this permission notice and warranty disclaimer appear in supporting documentation, and that the names of AT&T, Bell Laboratories, Lucent or Bellcore or any of their entities not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. AT&T, Lucent and Bellcore disclaim all warranties with regard to this software, including all implied warranties of merchantability and fitness. In no event shall AT&T, Lucent or Bellcore be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software. ****************************************************************/ #include #include #include #include "f2c.h" #include "fio.h" #include "fmt.h" #include "fp.h" static int rd_Z(Uint *n, int w, ftnlen len) { long x[9]; char *s, *s0, *s1, *se, *t; const char *sc; int ch, i, w1, w2; static char hex[256]; static int one = 1; int bad = 0; if (!hex['0']) { sc = "0123456789"; while(ch = *sc++) hex[ch] = ch - '0' + 1; sc = "ABCDEF"; while(ch = *sc++) hex[ch] = hex[ch + 'a' - 'A'] = ch - 'A' + 11; } s = s0 = (char *)x; s1 = (char *)&x[4]; se = (char *)&x[8]; if (len > 4*sizeof(long)) return errno = 117; while (w) { GET(ch); if (ch==',' || ch=='\n') break; w--; if (ch > ' ') { if (!hex[ch & 0xff]) bad++; *s++ = ch; if (s == se) { /* discard excess characters */ for(t = s0, s = s1; t < s1;) *t++ = *s++; s = s1; } } } if (bad) return errno = 115; w = (int)len; w1 = s - s0; w2 = w1+1 >> 1; t = (char *)n; if (*(char *)&one) { /* little endian */ t += w - 1; i = -1; } else i = 1; for(; w > w2; t += i, --w) *t = 0; if (!w) return 0; if (w < w2) s0 = s - (w << 1); else if (w1 & 1) { *t = hex[*s0++ & 0xff] - 1; if (!--w) return 0; t += i; } do { *t = hex[*s0 & 0xff]-1 << 4 | hex[s0[1] & 0xff]-1; t += i; s0 += 2; } while(--w); return 0; } static int rd_I(Uint *n, int w, ftnlen len, register int base) { int ch, sign; longint x = 0; if (w <= 0) goto have_x; for(;;) { GET(ch); if (ch != ' ') break; if (!--w) goto have_x; } sign = 0; switch(ch) { case ',': case '\n': w = 0; goto have_x; case '-': sign = 1; case '+': break; default: if (ch >= '0' && ch <= '9') { x = ch - '0'; break; } goto have_x; } while(--w) { GET(ch); if (ch >= '0' && ch <= '9') { x = x*base + ch - '0'; continue; } if (ch != ' ') { if (ch == '\n' || ch == ',') w = 0; break; } if (f__cblank) x *= base; } if (sign) x = -x; have_x: if(len == sizeof(integer)) n->il=x; else if(len == sizeof(char)) n->ic = (char)x; #ifdef Allow_TYQUAD else if (len == sizeof(longint)) n->ili = x; #endif else n->is = (short)x; if (w) { while(--w) GET(ch); return errno = 115; } return 0; } static int rd_L(ftnint *n, int w, ftnlen len) { int ch, dot, lv; if (w <= 0) goto bad; for(;;) { GET(ch); --w; if (ch != ' ') break; if (!w) goto bad; } dot = 0; retry: switch(ch) { case '.': if (dot++ || !w) goto bad; GET(ch); --w; goto retry; case 't': case 'T': lv = 1; break; case 'f': case 'F': lv = 0; break; default: bad: for(; w > 0; --w) GET(ch); /* no break */ case ',': case '\n': return errno = 116; } switch(len) { case sizeof(char): *(char *)n = (char)lv; break; case sizeof(short): *(short *)n = (short)lv; break; default: *n = lv; } while(w-- > 0) { GET(ch); if (ch == ',' || ch == '\n') break; } return 0; } static int rd_F(ufloat *p, int w, int d, ftnlen len) { char s[FMAX+EXPMAXDIGS+4]; register int ch; register char *sp, *spe, *sp1; double x; int scale1, se; long e, exp; sp1 = sp = s; spe = sp + FMAX; exp = -d; x = 0.; do { GET(ch); w--; } while (ch == ' ' && w); switch(ch) { case '-': *sp++ = ch; sp1++; spe++; case '+': if (!w) goto zero; --w; GET(ch); } while(ch == ' ') { blankdrop: if (!w--) goto zero; GET(ch); } while(ch == '0') { if (!w--) goto zero; GET(ch); } if (ch == ' ' && f__cblank) goto blankdrop; scale1 = f__scale; while(isdigit(ch)) { digloop1: if (sp < spe) *sp++ = ch; else ++exp; digloop1e: if (!w--) goto done; GET(ch); } if (ch == ' ') { if (f__cblank) { ch = '0'; goto digloop1; } goto digloop1e; } if (ch == '.') { exp += d; if (!w--) goto done; GET(ch); if (sp == sp1) { /* no digits yet */ while(ch == '0') { skip01: --exp; skip0: if (!w--) goto done; GET(ch); } if (ch == ' ') { if (f__cblank) goto skip01; goto skip0; } } while(isdigit(ch)) { digloop2: if (sp < spe) { *sp++ = ch; --exp; } digloop2e: if (!w--) goto done; GET(ch); } if (ch == ' ') { if (f__cblank) { ch = '0'; goto digloop2; } goto digloop2e; } } switch(ch) { default: break; case '-': se = 1; goto signonly; case '+': se = 0; goto signonly; case 'e': case 'E': case 'd': case 'D': if (!w--) goto bad; GET(ch); while(ch == ' ') { if (!w--) goto bad; GET(ch); } se = 0; switch(ch) { case '-': se = 1; case '+': signonly: if (!w--) goto bad; GET(ch); } while(ch == ' ') { if (!w--) goto bad; GET(ch); } if (!isdigit(ch)) goto bad; e = ch - '0'; for(;;) { if (!w--) { ch = '\n'; break; } GET(ch); if (!isdigit(ch)) { if (ch == ' ') { if (f__cblank) ch = '0'; else continue; } else break; } e = 10*e + ch - '0'; if (e > EXPMAX && sp > sp1) goto bad; } if (se) exp -= e; else exp += e; scale1 = 0; } switch(ch) { case '\n': case ',': break; default: bad: return (errno = 115); } done: if (sp > sp1) { while(*--sp == '0') ++exp; if (exp -= scale1) sprintf(sp+1, "e%ld", exp); else sp[1] = 0; x = atof(s); } zero: if (len == sizeof(real)) p->pf = x; else p->pd = x; return(0); } static int rd_A(char *p, ftnlen len) { int i,ch; for(i=0;i=len) { for(i=0;i0;f__cursor--) if((ch=(*f__getn)())<0) return(ch); if(f__cursor<0) { if(f__recpos+f__cursor < 0) /*err(elist->cierr,110,"fmt")*/ f__cursor = -f__recpos; /* is this in the standard? */ if(f__external == 0) { extern char *f__icptr; f__icptr += f__cursor; } else if(f__curunit && f__curunit->useek) (void) FSEEK(f__cf, f__cursor,SEEK_CUR); else err(f__elist->cierr,106,"fmt"); f__recpos += f__cursor; f__cursor=0; } switch(p->op) { default: fprintf(stderr,"rd_ed, unexpected code: %d\n", p->op); sig_die(f__fmtbuf, 1); case IM: case I: ch = rd_I((Uint *)ptr,p->p1,len, 10); break; /* O and OM don't work right for character, double, complex, */ /* or doublecomplex, and they differ from Fortran 90 in */ /* showing a minus sign for negative values. */ case OM: case O: ch = rd_I((Uint *)ptr, p->p1, len, 8); break; case L: ch = rd_L((ftnint *)ptr,p->p1,len); break; case A: ch = rd_A(ptr,len); break; case AW: ch = rd_AW(ptr,p->p1,len); break; case E: case EE: case D: case G: case GE: case F: ch = rd_F((ufloat *)ptr,p->p1,p->p2.i[0],len); break; /* Z and ZM assume 8-bit bytes. */ case ZM: case Z: ch = rd_Z((Uint *)ptr, p->p1, len); break; } if(ch == 0) return(ch); else if(ch == EOF) return(EOF); if (f__cf) clearerr(f__cf); return(errno); } int rd_ned(struct syl *p) { switch(p->op) { default: fprintf(stderr,"rd_ned, unexpected code: %d\n", p->op); sig_die(f__fmtbuf, 1); case APOS: return(rd_POS(p->p2.s)); case H: return(rd_H(p->p1,p->p2.s)); case SLASH: return((*f__donewrec)()); case TR: case X: f__cursor += p->p1; return(1); case T: f__cursor=p->p1-f__recpos - 1; return(1); case TL: f__cursor -= p->p1; if(f__cursor < -f__recpos) /* TL1000, 1X */ f__cursor = -f__recpos; return(1); } } blis-0.9.0/blastest/f2c/rewind.c000066400000000000000000000030601422157504600164050ustar00rootroot00000000000000/**************************************************************** Copyright 1990 - 1997 by AT&T, Lucent Technologies and Bellcore. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that the copyright notice and this permission notice and warranty disclaimer appear in supporting documentation, and that the names of AT&T, Bell Laboratories, Lucent or Bellcore or any of their entities not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. AT&T, Lucent and Bellcore disclaim all warranties with regard to this software, including all implied warranties of merchantability and fitness. In no event shall AT&T, Lucent or Bellcore be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software. ****************************************************************/ //#include #include "f2c.h" #include "fio.h" integer f_rew(alist *a) { unit *b; if(a->aunit>=MXUNIT || a->aunit<0) err(a->aerr,101,"rewind"); b = &f__units[a->aunit]; if(b->ufd == NULL || b->uwrt == 3) return(0); if(!b->useek) err(a->aerr,106,"rewind") if(b->uwrt) { (void) t_runc(a); b->uwrt = 3; } rewind(b->ufd); b->uend=0; return 0; } blis-0.9.0/blastest/f2c/rsfe.c000066400000000000000000000050211422157504600160530ustar00rootroot00000000000000/**************************************************************** Copyright 1990 - 1997 by AT&T, Lucent Technologies and Bellcore. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that the copyright notice and this permission notice and warranty disclaimer appear in supporting documentation, and that the names of AT&T, Bell Laboratories, Lucent or Bellcore or any of their entities not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. AT&T, Lucent and Bellcore disclaim all warranties with regard to this software, including all implied warranties of merchantability and fitness. In no event shall AT&T, Lucent or Bellcore be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software. ****************************************************************/ /* read sequential formatted external */ #include #include "f2c.h" #include "fio.h" #include "fmt.h" int xrd_SL(void) { int ch; if(!f__curunit->uend) while((ch=getc(f__cf))!='\n') if (ch == EOF) { f__curunit->uend = 1; break; } f__cursor=f__recpos=0; return 1; } int x_getc(void) { int ch; if(f__curunit->uend) return EOF; ch = getc(f__cf); if(ch!=EOF && ch!='\n') { f__recpos++; return ch; } if(ch=='\n') { (void) ungetc(ch,f__cf); return ch; } if(f__curunit->uend || feof(f__cf)) { errno=0; f__curunit->uend=1; return -1; } return -1; } int x_endp(void) { xrd_SL(); return f__curunit->uend == 1 ? EOF : 0; } int x_rev(void) { (void) xrd_SL(); return 0; } integer s_rsfe(cilist *a) /* start */ { int n; if(!f__init) f_init(); f__reading=1; f__sequential=1; f__formatted=1; f__external=1; if(n=c_sfe(a)) return n; f__elist=a; f__cursor=f__recpos=0; f__scale=0; f__fmtbuf=a->cifmt; f__cf=f__curunit->ufd; if(pars_f(f__fmtbuf)<0) err(a->cierr,100,"startio"); f__getn= x_getc; f__doed= rd_ed; f__doned= rd_ned; fmt_bg(); f__doend=x_endp; f__donewrec=xrd_SL; f__dorevert=x_rev; f__cblank=f__curunit->ublnk; f__cplus=0; if(f__curunit->uwrt && f__nowreading(f__curunit)) err(a->cierr,errno,"read start"); if(f__curunit->uend) err(f__elist->ciend,(EOF),"read start"); return 0; } blis-0.9.0/blastest/f2c/s_cmp.c000066400000000000000000000044241422157504600162230ustar00rootroot00000000000000/**************************************************************** Copyright 1990 - 1997 by AT&T, Lucent Technologies and Bellcore. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that the copyright notice and this permission notice and warranty disclaimer appear in supporting documentation, and that the names of AT&T, Bell Laboratories, Lucent or Bellcore or any of their entities not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. AT&T, Lucent and Bellcore disclaim all warranties with regard to this software, including all implied warranties of merchantability and fitness. In no event shall AT&T, Lucent or Bellcore be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software. ****************************************************************/ #include "f2c.h" #ifdef __cplusplus extern "C" { #endif /* compare two strings */ integer s_cmp(const char *a0, const char *b0, ftnlen la, ftnlen lb) { register unsigned char *a, *aend, *b, *bend; a = (unsigned char *)a0; b = (unsigned char *)b0; aend = a + la; bend = b + lb; if(la <= lb) { while(a < aend) if(*a != *b) return( *a - *b ); else { ++a; ++b; } while(b < bend) if(*b != ' ') return( ' ' - *b ); else ++b; } else { while(b < bend) if(*a == *b) { ++a; ++b; } else return( *a - *b ); while(a < aend) if(*a != ' ') return(*a - ' '); else ++a; } return(0); } #ifdef __cplusplus } #endif blis-0.9.0/blastest/f2c/s_copy.c000066400000000000000000000034021422157504600164110ustar00rootroot00000000000000/**************************************************************** Copyright 1990 - 1997 by AT&T, Lucent Technologies and Bellcore. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that the copyright notice and this permission notice and warranty disclaimer appear in supporting documentation, and that the names of AT&T, Bell Laboratories, Lucent or Bellcore or any of their entities not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. AT&T, Lucent and Bellcore disclaim all warranties with regard to this software, including all implied warranties of merchantability and fitness. In no event shall AT&T, Lucent or Bellcore be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software. ****************************************************************/ /* Unless compiled with -DNO_OVERWRITE, this variant of s_copy allows the * target of an assignment to appear on its right-hand side (contrary * to the Fortran 77 Standard, but in accordance with Fortran 90), * as in a(2:5) = a(4:7) . */ #include "f2c.h" #ifdef __cplusplus extern "C" { #endif /* assign strings: a = b */ int s_copy(char *a, const char *b, ftnlen la, ftnlen lb) { if (la <= lb) { memmove(a, b, la); } else { memset((char *)memmove(a, b, lb) + lb, ' ', la - lb); } return 0; } #ifdef __cplusplus } #endif blis-0.9.0/blastest/f2c/s_stop.c000066400000000000000000000032511422157504600164260ustar00rootroot00000000000000/**************************************************************** Copyright 1990 - 1997 by AT&T, Lucent Technologies and Bellcore. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that the copyright notice and this permission notice and warranty disclaimer appear in supporting documentation, and that the names of AT&T, Bell Laboratories, Lucent or Bellcore or any of their entities not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. AT&T, Lucent and Bellcore disclaim all warranties with regard to this software, including all implied warranties of merchantability and fitness. In no event shall AT&T, Lucent or Bellcore be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software. ****************************************************************/ //#include #include #include #include "f2c.h" int s_stop(char *s, ftnlen n) { int i; if(n > 0) { fprintf(stderr, "STOP "); for(i = 0; i #include "f2c.h" #include "fio.h" integer e_rsfe(void) { int n; n=en_fio(); f__fmtbuf=NULL; return(n); } int c_sfe(cilist *a) { unit *p; f__curunit = p = &f__units[a->ciunit]; if(a->ciunit >= MXUNIT || a->ciunit<0) err(a->cierr,101,"startio"); if(p->ufd==NULL && fk_open(SEQ,FMT,a->ciunit)) err(a->cierr,114,"sfe") if(!p->ufmt) err(a->cierr,102,"sfe") return(0); } integer e_wsfe(void) { int n = en_fio(); f__fmtbuf = NULL; #ifdef ALWAYS_FLUSH if (!n && fflush(f__cf)) err(f__elist->cierr, errno, "write end"); #endif return n; } blis-0.9.0/blastest/f2c/sig_die.c000066400000000000000000000032231422157504600165210ustar00rootroot00000000000000/**************************************************************** Copyright 1990 - 1997 by AT&T, Lucent Technologies and Bellcore. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that the copyright notice and this permission notice and warranty disclaimer appear in supporting documentation, and that the names of AT&T, Bell Laboratories, Lucent or Bellcore or any of their entities not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. AT&T, Lucent and Bellcore disclaim all warranties with regard to this software, including all implied warranties of merchantability and fitness. In no event shall AT&T, Lucent or Bellcore be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software. ****************************************************************/ #include #include #include #include #include "f2c.h" #ifndef SIGIOT #ifdef SIGABRT #define SIGIOT SIGABRT #endif #endif void sig_die(const char *s, int kill) { /* print error message, then clear buffers */ fprintf(stderr, "%s\n", s); if(kill) { fflush(stderr); f_exit(); fflush(stderr); /* now get a core */ #ifdef SIGIOT signal(SIGIOT, SIG_DFL); #endif abort(); } else { f_exit(); exit(1); } } blis-0.9.0/blastest/f2c/sign.c000066400000000000000000000035171422157504600160640ustar00rootroot00000000000000/**************************************************************** Copyright 1990 - 1997 by AT&T, Lucent Technologies and Bellcore. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that the copyright notice and this permission notice and warranty disclaimer appear in supporting documentation, and that the names of AT&T, Bell Laboratories, Lucent or Bellcore or any of their entities not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. AT&T, Lucent and Bellcore disclaim all warranties with regard to this software, including all implied warranties of merchantability and fitness. In no event shall AT&T, Lucent or Bellcore be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software. ****************************************************************/ #include "f2c.h" #ifdef __cplusplus extern "C" { #endif shortint h_sign(const shortint *a, const shortint *b) { shortint x = (*a >= 0 ? *a : - *a); return ( *b >= 0 ? x : -x); } integer i_sign(const integer *a, const integer *b) { integer x = (*a >= 0 ? *a : - *a); return ( *b >= 0 ? x : -x); } double r_sign(real *a, real *b) { double x = (*a >= 0 ? *a : - *a); return ( *b >= 0 ? x : -x); } double d_sign(const doublereal *a, const doublereal *b) { double x = (*a >= 0 ? *a : - *a); return ( *b >= 0 ? x : -x); } #ifdef __cplusplus } #endif blis-0.9.0/blastest/f2c/sin.c000066400000000000000000000033511422157504600157110ustar00rootroot00000000000000/**************************************************************** Copyright 1990 - 1997 by AT&T, Lucent Technologies and Bellcore. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that the copyright notice and this permission notice and warranty disclaimer appear in supporting documentation, and that the names of AT&T, Bell Laboratories, Lucent or Bellcore or any of their entities not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. AT&T, Lucent and Bellcore disclaim all warranties with regard to this software, including all implied warranties of merchantability and fitness. In no event shall AT&T, Lucent or Bellcore be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software. ****************************************************************/ #include "f2c.h" #ifdef __cplusplus extern "C" { #endif double r_sin(real *x) { return( sin(*x) ); } double d_sin(const doublereal *x) { return( sin(*x) ); } void c_sin(complex *r, complex *z) { double zi = z->i, zr = z->r; r->r = sin(zr) * cosh(zi); r->i = cos(zr) * sinh(zi); } void z_sin(doublecomplex *r, doublecomplex *z) { double zi = z->i, zr = z->r; r->r = sin(zr) * cosh(zi); r->i = cos(zr) * sinh(zi); } #ifdef __cplusplus } #endif blis-0.9.0/blastest/f2c/sinh.c000066400000000000000000000026451422157504600160660ustar00rootroot00000000000000/**************************************************************** Copyright 1990 - 1997 by AT&T, Lucent Technologies and Bellcore. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that the copyright notice and this permission notice and warranty disclaimer appear in supporting documentation, and that the names of AT&T, Bell Laboratories, Lucent or Bellcore or any of their entities not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. AT&T, Lucent and Bellcore disclaim all warranties with regard to this software, including all implied warranties of merchantability and fitness. In no event shall AT&T, Lucent or Bellcore be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software. ****************************************************************/ #include "f2c.h" #ifdef __cplusplus extern "C" { #endif double r_sinh(real *x) { return( sinh(*x) ); } double d_sinh(const doublereal *x) { return( sinh(*x) ); } #ifdef __cplusplus } #endif blis-0.9.0/blastest/f2c/sqrt.c000066400000000000000000000030331422157504600161060ustar00rootroot00000000000000/**************************************************************** Copyright 1990 - 1997 by AT&T, Lucent Technologies and Bellcore. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that the copyright notice and this permission notice and warranty disclaimer appear in supporting documentation, and that the names of AT&T, Bell Laboratories, Lucent or Bellcore or any of their entities not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. AT&T, Lucent and Bellcore disclaim all warranties with regard to this software, including all implied warranties of merchantability and fitness. In no event shall AT&T, Lucent or Bellcore be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software. ****************************************************************/ #include "f2c.h" #ifdef __cplusplus extern "C" { #endif double r_sqrt(real *x) { return ( sqrt(*x) ); } double d_sqrt(const doublereal *x) { return ( sqrt(*x) ); } void c_sqrt(complex *r, complex *z) { } void z_sqrt(doublecomplex *r, doublecomplex *z) { } #ifdef __cplusplus } #endif blis-0.9.0/blastest/f2c/tan.c000066400000000000000000000026411422157504600157030ustar00rootroot00000000000000/**************************************************************** Copyright 1990 - 1997 by AT&T, Lucent Technologies and Bellcore. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that the copyright notice and this permission notice and warranty disclaimer appear in supporting documentation, and that the names of AT&T, Bell Laboratories, Lucent or Bellcore or any of their entities not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. AT&T, Lucent and Bellcore disclaim all warranties with regard to this software, including all implied warranties of merchantability and fitness. In no event shall AT&T, Lucent or Bellcore be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software. ****************************************************************/ #include "f2c.h" #ifdef __cplusplus extern "C" { #endif double r_tan(real *x) { return( tan(*x) ); } double d_tan(const doublereal *x) { return( tan(*x) ); } #ifdef __cplusplus } #endif blis-0.9.0/blastest/f2c/tanh.c000066400000000000000000000026451422157504600160570ustar00rootroot00000000000000/**************************************************************** Copyright 1990 - 1997 by AT&T, Lucent Technologies and Bellcore. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that the copyright notice and this permission notice and warranty disclaimer appear in supporting documentation, and that the names of AT&T, Bell Laboratories, Lucent or Bellcore or any of their entities not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. AT&T, Lucent and Bellcore disclaim all warranties with regard to this software, including all implied warranties of merchantability and fitness. In no event shall AT&T, Lucent or Bellcore be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software. ****************************************************************/ #include "f2c.h" #ifdef __cplusplus extern "C" { #endif double r_tanh(real *x) { return( tanh(*x) ); } double d_tanh(const doublereal *x) { return( tanh(*x) ); } #ifdef __cplusplus } #endif blis-0.9.0/blastest/f2c/util.c000066400000000000000000000033751422157504600161030ustar00rootroot00000000000000/**************************************************************** Copyright 1990 - 1997 by AT&T, Lucent Technologies and Bellcore. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that the copyright notice and this permission notice and warranty disclaimer appear in supporting documentation, and that the names of AT&T, Bell Laboratories, Lucent or Bellcore or any of their entities not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. AT&T, Lucent and Bellcore disclaim all warranties with regard to this software, including all implied warranties of merchantability and fitness. In no event shall AT&T, Lucent or Bellcore be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software. ****************************************************************/ #include #include "f2c.h" #include "fio.h" void g_char(const char *a, ftnlen alen, char *b) { const char *x = a + alen; char *y = b + alen; for(;; y--) { if (x <= a) { *b = 0; return; } if (*--x != ' ') break; } *y-- = 0; do *y-- = *x; while(x-- > a); } void b_char(const char *a, char *b, ftnlen blen) { int i; for(i=0;i #include #include #include #include "f2c.h" #include "fio.h" #include "arith.h" #include "fmt.h" #include "fp.h" int wrt_E(ufloat *p, int w, int d, int e, ftnlen len) { char buf[FMAX+EXPMAXDIGS+4], *s, *se; int d1, delta, e1, i, sign, signspace; double dd; #ifdef WANT_LEAD_0 int insert0 = 0; #endif int e0 = e; if(e <= 0) e = 2; if(f__scale) { if(f__scale >= d + 2 || f__scale <= -d) goto nogood; } if(f__scale <= 0) --d; if (len == sizeof(real)) dd = p->pf; else dd = p->pd; if (dd < 0.) { signspace = sign = 1; dd = -dd; } else { sign = 0; signspace = (int)f__cplus; if (!dd) { #ifdef SIGNED_ZEROS if (signbit(dd)) signspace = sign = 1; #endif dd = 0.; /* avoid -0 */ } } delta = w - (2 /* for the . and the d adjustment above */ + 2 /* for the E+ */ + signspace + d + e); #ifdef WANT_LEAD_0 if (f__scale <= 0 && delta > 0) { delta--; insert0 = 1; } else #endif if (delta < 0) { nogood: while(--w >= 0) PUT('*'); return(0); } if (f__scale < 0) d += f__scale; if (d > FMAX) { d1 = d - FMAX; d = FMAX; } else d1 = 0; sprintf(buf,"%#.*E", d, dd); /* check for NaN, Infinity */ if (!isdigit(buf[0])) { switch(buf[0]) { case 'n': case 'N': signspace = 0; /* no sign for NaNs */ } delta = w - strlen(buf) - signspace; if (delta < 0) goto nogood; while(--delta >= 0) PUT(' '); if (signspace) PUT(sign ? '-' : '+'); for(s = buf; *s; s++) PUT(*s); return 0; } se = buf + d + 3; #ifdef GOOD_SPRINTF_EXPONENT /* When possible, exponent has 2 digits. */ if (f__scale != 1 && dd) sprintf(se, "%+.2d", atoi(se) + 1 - f__scale); #else if (dd) sprintf(se, "%+.2d", atoi(se) + 1 - f__scale); else strcpy(se, "+00"); #endif s = ++se; if (e < 2) { if (*s != '0') goto nogood; } /* accommodate 3 significant digits in exponent */ if (s[2]) { #ifdef Pedantic if (!e0 && !s[3]) for(s -= 2, e1 = 2; s[0] = s[1]; s++); /* Pedantic gives the behavior that Fortran 77 specifies, */ /* i.e., requires that E be specified for exponent fields */ /* of more than 3 digits. With Pedantic undefined, we get */ /* the behavior that Cray displays -- you get a bigger */ /* exponent field if it fits. */ #else if (!e0) { for(s -= 2, e1 = 2; s[0] = s[1]; s++) #ifdef CRAY delta--; if ((delta += 4) < 0) goto nogood #endif ; } #endif else if (e0 >= 0) goto shift; else e1 = e; } else shift: for(s += 2, e1 = 2; *s; ++e1, ++s) if (e1 >= e) goto nogood; while(--delta >= 0) PUT(' '); if (signspace) PUT(sign ? '-' : '+'); s = buf; i = f__scale; if (f__scale <= 0) { #ifdef WANT_LEAD_0 if (insert0) PUT('0'); #endif PUT('.'); for(; i < 0; ++i) PUT('0'); PUT(*s); s += 2; } else if (f__scale > 1) { PUT(*s); s += 2; while(--i > 0) PUT(*s++); PUT('.'); } if (d1) { se -= 2; while(s < se) PUT(*s++); se += 2; do PUT('0'); while(--d1 > 0); } while(s < se) PUT(*s++); if (e < 2) PUT(s[1]); else { while(++e1 <= e) PUT('0'); while(*s) PUT(*s++); } return 0; } int wrt_F(ufloat *p, int w, int d, ftnlen len) { int d1, sign, n; double x; char *b, buf[MAXINTDIGS+MAXFRACDIGS+4], *s; x= (len==sizeof(real)?p->pf:p->pd); if (d < MAXFRACDIGS) d1 = 0; else { d1 = d - MAXFRACDIGS; d = MAXFRACDIGS; } if (x < 0.) { x = -x; sign = 1; } else { sign = 0; if (!x) { #ifdef SIGNED_ZEROS if (signbit(x)) sign = 2; #endif x = 0.; } } if (n = f__scale) if (n > 0) do x *= 10.; while(--n > 0); else do x *= 0.1; while(++n < 0); n = sprintf(b = buf, "%#.*f", d, x) + d1; #ifndef WANT_LEAD_0 if (buf[0] == '0' && d) { ++b; --n; } #endif if (sign == 1) { /* check for all zeros */ for(s = b;;) { while(*s == '0') s++; switch(*s) { case '.': s++; continue; case 0: sign = 0; } break; } } if (sign || f__cplus) ++n; if (n > w) { #ifdef WANT_LEAD_0 if (buf[0] == '0' && --n == w) ++b; else #endif { while(--w >= 0) PUT('*'); return 0; } } for(w -= n; --w >= 0; ) PUT(' '); if (sign) PUT('-'); else if (f__cplus) PUT('+'); while(n = *b++) PUT(n); while(--d1 >= 0) PUT('0'); return 0; } blis-0.9.0/blastest/f2c/wrtfmt.c000066400000000000000000000172341422157504600164500ustar00rootroot00000000000000/**************************************************************** Copyright 1990 - 1997 by AT&T, Lucent Technologies and Bellcore. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that the copyright notice and this permission notice and warranty disclaimer appear in supporting documentation, and that the names of AT&T, Bell Laboratories, Lucent or Bellcore or any of their entities not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. AT&T, Lucent and Bellcore disclaim all warranties with regard to this software, including all implied warranties of merchantability and fitness. In no event shall AT&T, Lucent or Bellcore be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software. ****************************************************************/ #include #include "f2c.h" #include "fio.h" #include "fmt.h" static int mv_cur(void) /* shouldn't use fseek because it insists on calling fflush */ /* instead we know too much about stdio */ { int cursor = f__cursor; f__cursor = 0; if(f__external == 0) { if(cursor < 0) { if(f__hiwater < f__recpos) f__hiwater = f__recpos; f__recpos += cursor; f__icptr += cursor; if(f__recpos < 0) err(f__elist->cierr, 110, "left off"); } else if(cursor > 0) { if(f__recpos + cursor >= f__svic->icirlen) err(f__elist->cierr, 110, "recend"); if(f__hiwater <= f__recpos) for(; cursor > 0; cursor--) (*f__putn)(' '); else if(f__hiwater <= f__recpos + cursor) { cursor -= f__hiwater - f__recpos; f__icptr += f__hiwater - f__recpos; f__recpos = f__hiwater; for(; cursor > 0; cursor--) (*f__putn)(' '); } else { f__icptr += cursor; f__recpos += cursor; } } return(0); } if (cursor > 0) { if(f__hiwater <= f__recpos) for(;cursor>0;cursor--) (*f__putn)(' '); else if(f__hiwater <= f__recpos + cursor) { cursor -= f__hiwater - f__recpos; f__recpos = f__hiwater; for(; cursor > 0; cursor--) (*f__putn)(' '); } else { f__recpos += cursor; } } else if (cursor < 0) { if(cursor + f__recpos < 0) err(f__elist->cierr,110,"left off"); if(f__hiwater < f__recpos) f__hiwater = f__recpos; f__recpos += cursor; } return(0); } static int wrt_Z(Uint *n, int w, int minlen, ftnlen len) { register char *s, *se; register int i, w1; static int one = 1; static char hex[] = "0123456789ABCDEF"; s = (char *)n; --len; if (*(char *)&one) { /* little endian */ se = s; s += len; i = -1; } else { se = s + len; i = 1; } for(;; s += i) if (s == se || *s) break; w1 = (i*(se-s) << 1) + 1; if (*s & 0xf0) w1++; if (w1 > w) for(i = 0; i < w; i++) (*f__putn)('*'); else { if ((minlen -= w1) > 0) w1 += minlen; while(--w >= w1) (*f__putn)(' '); while(--minlen >= 0) (*f__putn)('0'); if (!(*s & 0xf0)) { (*f__putn)(hex[*s & 0xf]); if (s == se) return 0; s += i; } for(;; s += i) { (*f__putn)(hex[*s >> 4 & 0xf]); (*f__putn)(hex[*s & 0xf]); if (s == se) break; } } return 0; } static int wrt_I(Uint *n, int w, ftnlen len, register int base) { int ndigit,sign,spare,i; longint x; char *ans; if(len==sizeof(integer)) x=n->il; else if(len == sizeof(char)) x = n->ic; #ifdef Allow_TYQUAD else if (len == sizeof(longint)) x = n->ili; #endif else x=n->is; ans=f__icvt(x,&ndigit,&sign, base); spare=w-ndigit; if(sign || f__cplus) spare--; if(spare<0) for(i=0;iil; else if(len == sizeof(char)) x = n->ic; #ifdef Allow_TYQUAD else if (len == sizeof(longint)) x = n->ili; #endif else x=n->is; ans=f__icvt(x,&ndigit,&sign, base); if(sign || f__cplus) xsign=1; else xsign=0; if(ndigit+xsign>w || m+xsign>w) { for(i=0;i=m) spare=w-ndigit-xsign; else spare=w-m-xsign; for(i=0;iil; else if(sz == sizeof(char)) x = n->ic; else x=n->is; for(i=0;i 0) (*f__putn)(*p++); return(0); } static int wrt_AW(char * p, int w, ftnlen len) { while(w>len) { w--; (*f__putn)(' '); } while(w-- > 0) (*f__putn)(*p++); return(0); } static int wrt_G(ufloat *p, int w, int d, int e, ftnlen len) { double up = 1,x; int i=0,oldscale,n,j; x = len==sizeof(real)?p->pf:p->pd; if(x < 0 ) x = -x; if(x<.1) { if (x != 0.) return(wrt_E(p,w,d,e,len)); i = 1; goto have_i; } for(;i<=d;i++,up*=10) { if(x>=up) continue; have_i: oldscale = f__scale; f__scale = 0; if(e==0) n=4; else n=e+2; i=wrt_F(p,w-n,d-i,len); for(j=0;jop) { default: fprintf(stderr,"w_ed, unexpected code: %d\n", p->op); sig_die(f__fmtbuf, 1); case I: return(wrt_I((Uint *)ptr,p->p1,len, 10)); case IM: return(wrt_IM((Uint *)ptr,p->p1,p->p2.i[0],len,10)); /* O and OM don't work right for character, double, complex, */ /* or doublecomplex, and they differ from Fortran 90 in */ /* showing a minus sign for negative values. */ case O: return(wrt_I((Uint *)ptr, p->p1, len, 8)); case OM: return(wrt_IM((Uint *)ptr,p->p1,p->p2.i[0],len,8)); case L: return(wrt_L((Uint *)ptr,p->p1, len)); case A: return(wrt_A(ptr,len)); case AW: return(wrt_AW(ptr,p->p1,len)); case D: case E: case EE: return(wrt_E((ufloat *)ptr,p->p1,p->p2.i[0],p->p2.i[1],len)); case G: case GE: return(wrt_G((ufloat *)ptr,p->p1,p->p2.i[0],p->p2.i[1],len)); case F: return(wrt_F((ufloat *)ptr,p->p1,p->p2.i[0],len)); /* Z and ZM assume 8-bit bytes. */ case Z: return(wrt_Z((Uint *)ptr,p->p1,0,len)); case ZM: return(wrt_Z((Uint *)ptr,p->p1,p->p2.i[0],len)); } } int w_ned(struct syl *p) { switch(p->op) { default: fprintf(stderr,"w_ned, unexpected code: %d\n", p->op); sig_die(f__fmtbuf, 1); case SLASH: return((*f__donewrec)()); case T: f__cursor = p->p1-f__recpos - 1; return(1); case TL: f__cursor -= p->p1; if(f__cursor < -f__recpos) /* TL1000, 1X */ f__cursor = -f__recpos; return(1); case TR: case X: f__cursor += p->p1; return(1); case APOS: return(wrt_AP(p->p2.s)); case H: return(wrt_H(p->p1,p->p2.s)); } } blis-0.9.0/blastest/f2c/wsfe.c000066400000000000000000000045101422157504600160620ustar00rootroot00000000000000/**************************************************************** Copyright 1990 - 1997 by AT&T, Lucent Technologies and Bellcore. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that the copyright notice and this permission notice and warranty disclaimer appear in supporting documentation, and that the names of AT&T, Bell Laboratories, Lucent or Bellcore or any of their entities not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. AT&T, Lucent and Bellcore disclaim all warranties with regard to this software, including all implied warranties of merchantability and fitness. In no event shall AT&T, Lucent or Bellcore be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software. ****************************************************************/ /*write sequential formatted external*/ #include #include "f2c.h" #include "fio.h" #include "fmt.h" int x_wSL(void) { int n = f__putbuf('\n'); f__hiwater = f__recpos = f__cursor = 0; return(n == 0); } static int xw_end(void) { int n; if(f__nonl) { f__putbuf(n = 0); fflush(f__cf); } else n = f__putbuf('\n'); f__hiwater = f__recpos = f__cursor = 0; return n; } static int xw_rev(void) { int n = 0; if(f__workdone) { n = f__putbuf('\n'); f__workdone = 0; } f__hiwater = f__recpos = f__cursor = 0; return n; } integer s_wsfe(cilist *a) /*start*/ { int n; if(!f__init) f_init(); f__reading=0; f__sequential=1; f__formatted=1; f__external=1; if(n=c_sfe(a)) return(n); f__elist=a; f__hiwater = f__cursor=f__recpos=0; f__nonl = 0; f__scale=0; f__fmtbuf=a->cifmt; f__cf=f__curunit->ufd; if(pars_f(f__fmtbuf)<0) err(a->cierr,100,"startio"); f__putn= x_putc; f__doed= w_ed; f__doned= w_ned; f__doend=xw_end; f__dorevert=xw_rev; f__donewrec=x_wSL; fmt_bg(); f__cplus=0; f__cblank=f__curunit->ublnk; if(f__curunit->uwrt != 1 && f__nowwriting(f__curunit)) err(a->cierr,errno,"write start"); return(0); } blis-0.9.0/blastest/f2c/wsle.c000066400000000000000000000034141422157504600160720ustar00rootroot00000000000000/**************************************************************** Copyright 1990 - 1997 by AT&T, Lucent Technologies and Bellcore. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that the copyright notice and this permission notice and warranty disclaimer appear in supporting documentation, and that the names of AT&T, Bell Laboratories, Lucent or Bellcore or any of their entities not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. AT&T, Lucent and Bellcore disclaim all warranties with regard to this software, including all implied warranties of merchantability and fitness. In no event shall AT&T, Lucent or Bellcore be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software. ****************************************************************/ #include #include #include "f2c.h" #include "fio.h" #include "fmt.h" #include "lio.h" integer s_wsle(cilist *a) { int n; if(n=c_le(a)) return(n); f__reading=0; f__external=1; f__formatted=1; f__putn = x_putc; f__lioproc = l_write; L_len = LINE; f__donewrec = x_wSL; if(f__curunit->uwrt != 1 && f__nowwriting(f__curunit)) err(a->cierr, errno, "list output start"); return(0); } integer e_wsle(void) { int n = f__putbuf('\n'); f__recpos=0; #ifdef ALWAYS_FLUSH if (!n && fflush(f__cf)) err(f__elist->cierr, errno, "write end"); #endif return(n); } blis-0.9.0/blastest/input/000077500000000000000000000000001422157504600154375ustar00rootroot00000000000000blis-0.9.0/blastest/input/cblat2.in000066400000000000000000000030121422157504600171320ustar00rootroot00000000000000'out.cblat2' NAME OF SUMMARY OUTPUT FILE 6 UNIT NUMBER OF SUMMARY FILE 'CBLA2T.SNAP' NAME OF SNAPSHOT OUTPUT FILE -1 UNIT NUMBER OF SNAPSHOT FILE (NOT USED IF .LT. 0) F LOGICAL FLAG, T TO REWIND SNAPSHOT FILE AFTER EACH RECORD. F LOGICAL FLAG, T TO STOP ON FAILURES. T LOGICAL FLAG, T TO TEST ERROR EXITS. 16.0 THRESHOLD VALUE OF TEST RATIO 6 NUMBER OF VALUES OF N 0 1 2 3 5 9 VALUES OF N 4 NUMBER OF VALUES OF K 0 1 2 4 VALUES OF K 4 NUMBER OF VALUES OF INCX AND INCY 1 2 -1 -2 VALUES OF INCX AND INCY 3 NUMBER OF VALUES OF ALPHA (0.0,0.0) (1.0,0.0) (0.7,-0.9) VALUES OF ALPHA 3 NUMBER OF VALUES OF BETA (0.0,0.0) (1.0,0.0) (1.3,-1.1) VALUES OF BETA CGEMV T PUT F FOR NO TEST. SAME COLUMNS. CGBMV T PUT F FOR NO TEST. SAME COLUMNS. CHEMV T PUT F FOR NO TEST. SAME COLUMNS. CHBMV T PUT F FOR NO TEST. SAME COLUMNS. CHPMV T PUT F FOR NO TEST. SAME COLUMNS. CTRMV T PUT F FOR NO TEST. SAME COLUMNS. CTBMV T PUT F FOR NO TEST. SAME COLUMNS. CTPMV T PUT F FOR NO TEST. SAME COLUMNS. CTRSV T PUT F FOR NO TEST. SAME COLUMNS. CTBSV T PUT F FOR NO TEST. SAME COLUMNS. CTPSV T PUT F FOR NO TEST. SAME COLUMNS. CGERC T PUT F FOR NO TEST. SAME COLUMNS. CGERU T PUT F FOR NO TEST. SAME COLUMNS. CHER T PUT F FOR NO TEST. SAME COLUMNS. CHPR T PUT F FOR NO TEST. SAME COLUMNS. CHER2 T PUT F FOR NO TEST. SAME COLUMNS. CHPR2 T PUT F FOR NO TEST. SAME COLUMNS. blis-0.9.0/blastest/input/cblat3.in000066400000000000000000000020261422157504600171370ustar00rootroot00000000000000'out.cblat3' NAME OF SUMMARY OUTPUT FILE 6 UNIT NUMBER OF SUMMARY FILE 'CBLAT3.SNAP' NAME OF SNAPSHOT OUTPUT FILE -1 UNIT NUMBER OF SNAPSHOT FILE (NOT USED IF .LT. 0) F LOGICAL FLAG, T TO REWIND SNAPSHOT FILE AFTER EACH RECORD. F LOGICAL FLAG, T TO STOP ON FAILURES. T LOGICAL FLAG, T TO TEST ERROR EXITS. 16.0 THRESHOLD VALUE OF TEST RATIO 6 NUMBER OF VALUES OF N 0 1 2 3 5 9 VALUES OF N 3 NUMBER OF VALUES OF ALPHA (0.0,0.0) (1.0,0.0) (0.7,-0.9) VALUES OF ALPHA 3 NUMBER OF VALUES OF BETA (0.0,0.0) (1.0,0.0) (1.3,-1.1) VALUES OF BETA CGEMM T PUT F FOR NO TEST. SAME COLUMNS. CHEMM T PUT F FOR NO TEST. SAME COLUMNS. CSYMM T PUT F FOR NO TEST. SAME COLUMNS. CTRMM T PUT F FOR NO TEST. SAME COLUMNS. CTRSM T PUT F FOR NO TEST. SAME COLUMNS. CHERK T PUT F FOR NO TEST. SAME COLUMNS. CSYRK T PUT F FOR NO TEST. SAME COLUMNS. CHER2K T PUT F FOR NO TEST. SAME COLUMNS. CSYR2K T PUT F FOR NO TEST. SAME COLUMNS. blis-0.9.0/blastest/input/dblat2.in000066400000000000000000000026721422157504600171460ustar00rootroot00000000000000'out.dblat2' NAME OF SUMMARY OUTPUT FILE 6 UNIT NUMBER OF SUMMARY FILE 'DBLAT2.SNAP' NAME OF SNAPSHOT OUTPUT FILE -1 UNIT NUMBER OF SNAPSHOT FILE (NOT USED IF .LT. 0) F LOGICAL FLAG, T TO REWIND SNAPSHOT FILE AFTER EACH RECORD. F LOGICAL FLAG, T TO STOP ON FAILURES. T LOGICAL FLAG, T TO TEST ERROR EXITS. 16.0 THRESHOLD VALUE OF TEST RATIO 6 NUMBER OF VALUES OF N 0 1 2 3 5 9 VALUES OF N 4 NUMBER OF VALUES OF K 0 1 2 4 VALUES OF K 4 NUMBER OF VALUES OF INCX AND INCY 1 2 -1 -2 VALUES OF INCX AND INCY 3 NUMBER OF VALUES OF ALPHA 0.0 1.0 0.7 VALUES OF ALPHA 3 NUMBER OF VALUES OF BETA 0.0 1.0 0.9 VALUES OF BETA DGEMV T PUT F FOR NO TEST. SAME COLUMNS. DGBMV T PUT F FOR NO TEST. SAME COLUMNS. DSYMV T PUT F FOR NO TEST. SAME COLUMNS. DSBMV T PUT F FOR NO TEST. SAME COLUMNS. DSPMV T PUT F FOR NO TEST. SAME COLUMNS. DTRMV T PUT F FOR NO TEST. SAME COLUMNS. DTBMV T PUT F FOR NO TEST. SAME COLUMNS. DTPMV T PUT F FOR NO TEST. SAME COLUMNS. DTRSV T PUT F FOR NO TEST. SAME COLUMNS. DTBSV T PUT F FOR NO TEST. SAME COLUMNS. DTPSV T PUT F FOR NO TEST. SAME COLUMNS. DGER T PUT F FOR NO TEST. SAME COLUMNS. DSYR T PUT F FOR NO TEST. SAME COLUMNS. DSPR T PUT F FOR NO TEST. SAME COLUMNS. DSYR2 T PUT F FOR NO TEST. SAME COLUMNS. DSPR2 T PUT F FOR NO TEST. SAME COLUMNS. blis-0.9.0/blastest/input/dblat3.in000066400000000000000000000015621422157504600171440ustar00rootroot00000000000000'out.dblat3' NAME OF SUMMARY OUTPUT FILE 6 UNIT NUMBER OF SUMMARY FILE 'DBLAT3.SNAP' NAME OF SNAPSHOT OUTPUT FILE -1 UNIT NUMBER OF SNAPSHOT FILE (NOT USED IF .LT. 0) F LOGICAL FLAG, T TO REWIND SNAPSHOT FILE AFTER EACH RECORD. F LOGICAL FLAG, T TO STOP ON FAILURES. T LOGICAL FLAG, T TO TEST ERROR EXITS. 16.0 THRESHOLD VALUE OF TEST RATIO 6 NUMBER OF VALUES OF N 0 1 2 3 5 9 VALUES OF N 3 NUMBER OF VALUES OF ALPHA 0.0 1.0 0.7 VALUES OF ALPHA 3 NUMBER OF VALUES OF BETA 0.0 1.0 1.3 VALUES OF BETA DGEMM T PUT F FOR NO TEST. SAME COLUMNS. DSYMM T PUT F FOR NO TEST. SAME COLUMNS. DTRMM T PUT F FOR NO TEST. SAME COLUMNS. DTRSM T PUT F FOR NO TEST. SAME COLUMNS. DSYRK T PUT F FOR NO TEST. SAME COLUMNS. DSYR2K T PUT F FOR NO TEST. SAME COLUMNS. blis-0.9.0/blastest/input/sblat2.in000066400000000000000000000026721422157504600171650ustar00rootroot00000000000000'out.sblat2' NAME OF SUMMARY OUTPUT FILE 6 UNIT NUMBER OF SUMMARY FILE 'SBLAT2.SNAP' NAME OF SNAPSHOT OUTPUT FILE -1 UNIT NUMBER OF SNAPSHOT FILE (NOT USED IF .LT. 0) F LOGICAL FLAG, T TO REWIND SNAPSHOT FILE AFTER EACH RECORD. F LOGICAL FLAG, T TO STOP ON FAILURES. T LOGICAL FLAG, T TO TEST ERROR EXITS. 16.0 THRESHOLD VALUE OF TEST RATIO 6 NUMBER OF VALUES OF N 0 1 2 3 5 9 VALUES OF N 4 NUMBER OF VALUES OF K 0 1 2 4 VALUES OF K 4 NUMBER OF VALUES OF INCX AND INCY 1 2 -1 -2 VALUES OF INCX AND INCY 3 NUMBER OF VALUES OF ALPHA 0.0 1.0 0.7 VALUES OF ALPHA 3 NUMBER OF VALUES OF BETA 0.0 1.0 0.9 VALUES OF BETA SGEMV T PUT F FOR NO TEST. SAME COLUMNS. SGBMV T PUT F FOR NO TEST. SAME COLUMNS. SSYMV T PUT F FOR NO TEST. SAME COLUMNS. SSBMV T PUT F FOR NO TEST. SAME COLUMNS. SSPMV T PUT F FOR NO TEST. SAME COLUMNS. STRMV T PUT F FOR NO TEST. SAME COLUMNS. STBMV T PUT F FOR NO TEST. SAME COLUMNS. STPMV T PUT F FOR NO TEST. SAME COLUMNS. STRSV T PUT F FOR NO TEST. SAME COLUMNS. STBSV T PUT F FOR NO TEST. SAME COLUMNS. STPSV T PUT F FOR NO TEST. SAME COLUMNS. SGER T PUT F FOR NO TEST. SAME COLUMNS. SSYR T PUT F FOR NO TEST. SAME COLUMNS. SSPR T PUT F FOR NO TEST. SAME COLUMNS. SSYR2 T PUT F FOR NO TEST. SAME COLUMNS. SSPR2 T PUT F FOR NO TEST. SAME COLUMNS. blis-0.9.0/blastest/input/sblat3.in000066400000000000000000000015621422157504600171630ustar00rootroot00000000000000'out.sblat3' NAME OF SUMMARY OUTPUT FILE 6 UNIT NUMBER OF SUMMARY FILE 'SBLAT3.SNAP' NAME OF SNAPSHOT OUTPUT FILE -1 UNIT NUMBER OF SNAPSHOT FILE (NOT USED IF .LT. 0) F LOGICAL FLAG, T TO REWIND SNAPSHOT FILE AFTER EACH RECORD. F LOGICAL FLAG, T TO STOP ON FAILURES. T LOGICAL FLAG, T TO TEST ERROR EXITS. 16.0 THRESHOLD VALUE OF TEST RATIO 6 NUMBER OF VALUES OF N 0 1 2 3 5 9 VALUES OF N 3 NUMBER OF VALUES OF ALPHA 0.0 1.0 0.7 VALUES OF ALPHA 3 NUMBER OF VALUES OF BETA 0.0 1.0 1.3 VALUES OF BETA SGEMM T PUT F FOR NO TEST. SAME COLUMNS. SSYMM T PUT F FOR NO TEST. SAME COLUMNS. STRMM T PUT F FOR NO TEST. SAME COLUMNS. STRSM T PUT F FOR NO TEST. SAME COLUMNS. SSYRK T PUT F FOR NO TEST. SAME COLUMNS. SSYR2K T PUT F FOR NO TEST. SAME COLUMNS. blis-0.9.0/blastest/input/zblat2.in000066400000000000000000000030121422157504600171610ustar00rootroot00000000000000'out.zblat2' NAME OF SUMMARY OUTPUT FILE 6 UNIT NUMBER OF SUMMARY FILE 'CBLA2T.SNAP' NAME OF SNAPSHOT OUTPUT FILE -1 UNIT NUMBER OF SNAPSHOT FILE (NOT USED IF .LT. 0) F LOGICAL FLAG, T TO REWIND SNAPSHOT FILE AFTER EACH RECORD. F LOGICAL FLAG, T TO STOP ON FAILURES. T LOGICAL FLAG, T TO TEST ERROR EXITS. 16.0 THRESHOLD VALUE OF TEST RATIO 6 NUMBER OF VALUES OF N 0 1 2 3 5 9 VALUES OF N 4 NUMBER OF VALUES OF K 0 1 2 4 VALUES OF K 4 NUMBER OF VALUES OF INCX AND INCY 1 2 -1 -2 VALUES OF INCX AND INCY 3 NUMBER OF VALUES OF ALPHA (0.0,0.0) (1.0,0.0) (0.7,-0.9) VALUES OF ALPHA 3 NUMBER OF VALUES OF BETA (0.0,0.0) (1.0,0.0) (1.3,-1.1) VALUES OF BETA ZGEMV T PUT F FOR NO TEST. SAME COLUMNS. ZGBMV T PUT F FOR NO TEST. SAME COLUMNS. ZHEMV T PUT F FOR NO TEST. SAME COLUMNS. ZHBMV T PUT F FOR NO TEST. SAME COLUMNS. ZHPMV T PUT F FOR NO TEST. SAME COLUMNS. ZTRMV T PUT F FOR NO TEST. SAME COLUMNS. ZTBMV T PUT F FOR NO TEST. SAME COLUMNS. ZTPMV T PUT F FOR NO TEST. SAME COLUMNS. ZTRSV T PUT F FOR NO TEST. SAME COLUMNS. ZTBSV T PUT F FOR NO TEST. SAME COLUMNS. ZTPSV T PUT F FOR NO TEST. SAME COLUMNS. ZGERC T PUT F FOR NO TEST. SAME COLUMNS. ZGERU T PUT F FOR NO TEST. SAME COLUMNS. ZHER T PUT F FOR NO TEST. SAME COLUMNS. ZHPR T PUT F FOR NO TEST. SAME COLUMNS. ZHER2 T PUT F FOR NO TEST. SAME COLUMNS. ZHPR2 T PUT F FOR NO TEST. SAME COLUMNS. blis-0.9.0/blastest/input/zblat3.in000066400000000000000000000020261422157504600171660ustar00rootroot00000000000000'out.zblat3' NAME OF SUMMARY OUTPUT FILE 6 UNIT NUMBER OF SUMMARY FILE 'ZBLAT3.SNAP' NAME OF SNAPSHOT OUTPUT FILE -1 UNIT NUMBER OF SNAPSHOT FILE (NOT USED IF .LT. 0) F LOGICAL FLAG, T TO REWIND SNAPSHOT FILE AFTER EACH RECORD. F LOGICAL FLAG, T TO STOP ON FAILURES. T LOGICAL FLAG, T TO TEST ERROR EXITS. 16.0 THRESHOLD VALUE OF TEST RATIO 6 NUMBER OF VALUES OF N 0 1 2 3 5 9 VALUES OF N 3 NUMBER OF VALUES OF ALPHA (0.0,0.0) (1.0,0.0) (0.7,-0.9) VALUES OF ALPHA 3 NUMBER OF VALUES OF BETA (0.0,0.0) (1.0,0.0) (1.3,-1.1) VALUES OF BETA ZGEMM T PUT F FOR NO TEST. SAME COLUMNS. ZHEMM T PUT F FOR NO TEST. SAME COLUMNS. ZSYMM T PUT F FOR NO TEST. SAME COLUMNS. ZTRMM T PUT F FOR NO TEST. SAME COLUMNS. ZTRSM T PUT F FOR NO TEST. SAME COLUMNS. ZHERK T PUT F FOR NO TEST. SAME COLUMNS. ZSYRK T PUT F FOR NO TEST. SAME COLUMNS. ZHER2K T PUT F FOR NO TEST. SAME COLUMNS. ZSYR2K T PUT F FOR NO TEST. SAME COLUMNS. blis-0.9.0/blastest/obj/000077500000000000000000000000001422157504600150525ustar00rootroot00000000000000blis-0.9.0/blastest/obj/.gitkeep000066400000000000000000000000001422157504600164710ustar00rootroot00000000000000blis-0.9.0/blastest/src/000077500000000000000000000000001422157504600150675ustar00rootroot00000000000000blis-0.9.0/blastest/src/cblat1.c000066400000000000000000000706401422157504600164100ustar00rootroot00000000000000/* cblat1.f -- translated by f2c (version 20100827). You must link the resulting object file with libf2c: on Microsoft Windows system, link with libf2c.lib; on Linux or Unix systems, link with .../path/to/libf2c.a -lm or, if you install libf2c.a in a standard place, with -lf2c -lm -- in that order, at the end of the command line, as in cc *.o -lf2c -lm Source for libf2c is in /netlib/f2c/libf2c.zip, e.g., http://www.netlib.org/f2c/libf2c.zip */ #include "f2c.h" /* Common Block Declarations */ struct { integer icase, n, incx, incy, mode; logical pass; } combla_; #define combla_1 combla_ /* Table of constant values */ static integer c__1 = 1; static integer c__9 = 9; static integer c__5 = 5; static real c_b43 = 1.f; static real c_b52 = 0.f; /* > \brief \b CBLAT1 */ /* =========== DOCUMENTATION =========== */ /* Online html documentation available at */ /* http://www.netlib.org/lapack/explore-html/ */ /* Definition: */ /* =========== */ /* PROGRAM CBLAT1 */ /* > \par Purpose: */ /* ============= */ /* > */ /* > \verbatim */ /* > */ /* > Test program for the COMPLEX Level 1 BLAS. */ /* > Based upon the original BLAS test routine together with: */ /* > */ /* > F06GAF Example Program Text */ /* > \endverbatim */ /* Authors: */ /* ======== */ /* > \author Univ. of Tennessee */ /* > \author Univ. of California Berkeley */ /* > \author Univ. of Colorado Denver */ /* > \author NAG Ltd. */ /* > \date April 2012 */ /* > \ingroup complex_blas_testing */ /* ===================================================================== */ /* Main program */ int main(void) { /* Initialized data */ static real sfac = 9.765625e-4f; /* Format strings */ static char fmt_99999[] = "(\002 Complex BLAS Test Program Results\002,/" "1x)"; static char fmt_99998[] = "(\002 ----" "- PASS -----\002)"; /* Builtin functions */ integer s_wsfe(cilist *), e_wsfe(void); /* Subroutine */ int s_stop(char *, ftnlen); /* Local variables */ integer ic; extern /* Subroutine */ int check1_(real *), check2_(real *), header_( void); /* Fortran I/O blocks */ static cilist io___2 = { 0, 6, 0, fmt_99999, 0 }; static cilist io___4 = { 0, 6, 0, fmt_99998, 0 }; /* -- Reference BLAS test routine (version 3.4.1) -- */ /* -- Reference BLAS is a software package provided by Univ. of Tennessee, -- */ /* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- */ /* April 2012 */ /* ===================================================================== */ /* .. Parameters .. */ /* .. Scalars in Common .. */ /* .. Local Scalars .. */ /* .. External Subroutines .. */ /* .. Common blocks .. */ /* .. Data statements .. */ /* .. Executable Statements .. */ s_wsfe(&io___2); e_wsfe(); for (ic = 1; ic <= 10; ++ic) { combla_1.icase = ic; header_(); /* Initialize PASS, INCX, INCY, and MODE for a new case. */ /* The value 9999 for INCX, INCY or MODE will appear in the */ /* detailed output, if any, for cases that do not involve */ /* these parameters. */ combla_1.pass = TRUE_; combla_1.incx = 9999; combla_1.incy = 9999; combla_1.mode = 9999; if (combla_1.icase <= 5) { check2_(&sfac); } else if (combla_1.icase >= 6) { check1_(&sfac); } /* -- Print */ if (combla_1.pass) { s_wsfe(&io___4); e_wsfe(); } /* L20: */ } s_stop("", (ftnlen)0); return 0; } /* main */ /* Subroutine */ int header_(void) { /* Initialized data */ static char l[6*10] = "CDOTC " "CDOTU " "CAXPY " "CCOPY " "CSWAP " "SCNR" "M2" "SCASUM" "CSCAL " "CSSCAL" "ICAMAX"; /* Format strings */ static char fmt_99999[] = "(/\002 Test of subprogram number\002,i3,12x,a" "6)"; /* Builtin functions */ integer s_wsfe(cilist *), do_fio(integer *, char *, ftnlen), e_wsfe(void); /* Fortran I/O blocks */ static cilist io___6 = { 0, 6, 0, fmt_99999, 0 }; /* .. Parameters .. */ /* .. Scalars in Common .. */ /* .. Local Arrays .. */ /* .. Common blocks .. */ /* .. Data statements .. */ /* .. Executable Statements .. */ s_wsfe(&io___6); do_fio(&c__1, (char *)&combla_1.icase, (ftnlen)sizeof(integer)); do_fio(&c__1, l + (0 + (0 + (combla_1.icase - 1) * 6)), (ftnlen)6); e_wsfe(); return 0; } /* header_ */ /* Subroutine */ int check1_(real *sfac) { /* Initialized data */ static real strue2[5] = { 0.f,.5f,.6f,.7f,.8f }; static real strue4[5] = { 0.f,.7f,1.f,1.3f,1.6f }; static complex ctrue5[80] /* was [8][5][2] */ = { {.1f,.1f},{1.f,2.f},{ 1.f,2.f},{1.f,2.f},{1.f,2.f},{1.f,2.f},{1.f,2.f},{1.f,2.f},{-.16f, -.37f},{3.f,4.f},{3.f,4.f},{3.f,4.f},{3.f,4.f},{3.f,4.f},{3.f,4.f} ,{3.f,4.f},{-.17f,-.19f},{.13f,-.39f},{5.f,6.f},{5.f,6.f},{5.f, 6.f},{5.f,6.f},{5.f,6.f},{5.f,6.f},{.11f,-.03f},{-.17f,.46f},{ -.17f,-.19f},{7.f,8.f},{7.f,8.f},{7.f,8.f},{7.f,8.f},{7.f,8.f},{ .19f,-.17f},{.2f,-.35f},{.35f,.2f},{.14f,.08f},{2.f,3.f},{2.f,3.f} ,{2.f,3.f},{2.f,3.f},{.1f,.1f},{4.f,5.f},{4.f,5.f},{4.f,5.f},{4.f, 5.f},{4.f,5.f},{4.f,5.f},{4.f,5.f},{-.16f,-.37f},{6.f,7.f},{6.f, 7.f},{6.f,7.f},{6.f,7.f},{6.f,7.f},{6.f,7.f},{6.f,7.f},{-.17f, -.19f},{8.f,9.f},{.13f,-.39f},{2.f,5.f},{2.f,5.f},{2.f,5.f},{2.f, 5.f},{2.f,5.f},{.11f,-.03f},{3.f,6.f},{-.17f,.46f},{4.f,7.f},{ -.17f,-.19f},{7.f,2.f},{7.f,2.f},{7.f,2.f},{.19f,-.17f},{5.f,8.f}, {.2f,-.35f},{6.f,9.f},{.35f,.2f},{8.f,3.f},{.14f,.08f},{9.f,4.f} } ; static complex ctrue6[80] /* was [8][5][2] */ = { {.1f,.1f},{1.f,2.f},{ 1.f,2.f},{1.f,2.f},{1.f,2.f},{1.f,2.f},{1.f,2.f},{1.f,2.f},{.09f, -.12f},{3.f,4.f},{3.f,4.f},{3.f,4.f},{3.f,4.f},{3.f,4.f},{3.f,4.f} ,{3.f,4.f},{.03f,-.09f},{.15f,-.03f},{5.f,6.f},{5.f,6.f},{5.f,6.f} ,{5.f,6.f},{5.f,6.f},{5.f,6.f},{.03f,.03f},{-.18f,.03f},{.03f, -.09f},{7.f,8.f},{7.f,8.f},{7.f,8.f},{7.f,8.f},{7.f,8.f},{.09f, .03f},{.15f,0.f},{0.f,.15f},{0.f,.06f},{2.f,3.f},{2.f,3.f},{2.f, 3.f},{2.f,3.f},{.1f,.1f},{4.f,5.f},{4.f,5.f},{4.f,5.f},{4.f,5.f},{ 4.f,5.f},{4.f,5.f},{4.f,5.f},{.09f,-.12f},{6.f,7.f},{6.f,7.f},{ 6.f,7.f},{6.f,7.f},{6.f,7.f},{6.f,7.f},{6.f,7.f},{.03f,-.09f},{ 8.f,9.f},{.15f,-.03f},{2.f,5.f},{2.f,5.f},{2.f,5.f},{2.f,5.f},{ 2.f,5.f},{.03f,.03f},{3.f,6.f},{-.18f,.03f},{4.f,7.f},{.03f,-.09f} ,{7.f,2.f},{7.f,2.f},{7.f,2.f},{.09f,.03f},{5.f,8.f},{.15f,0.f},{ 6.f,9.f},{0.f,.15f},{8.f,3.f},{0.f,.06f},{9.f,4.f} }; static integer itrue3[5] = { 0,1,2,2,2 }; static real sa = .3f; static complex ca = {.4f,-.7f}; static complex cv[80] /* was [8][5][2] */ = { {.1f,.1f},{1.f,2.f},{ 1.f,2.f},{1.f,2.f},{1.f,2.f},{1.f,2.f},{1.f,2.f},{1.f,2.f},{.3f, -.4f},{3.f,4.f},{3.f,4.f},{3.f,4.f},{3.f,4.f},{3.f,4.f},{3.f,4.f}, {3.f,4.f},{.1f,-.3f},{.5f,-.1f},{5.f,6.f},{5.f,6.f},{5.f,6.f},{ 5.f,6.f},{5.f,6.f},{5.f,6.f},{.1f,.1f},{-.6f,.1f},{.1f,-.3f},{7.f, 8.f},{7.f,8.f},{7.f,8.f},{7.f,8.f},{7.f,8.f},{.3f,.1f},{.5f,0.f},{ 0.f,.5f},{0.f,.2f},{2.f,3.f},{2.f,3.f},{2.f,3.f},{2.f,3.f},{.1f, .1f},{4.f,5.f},{4.f,5.f},{4.f,5.f},{4.f,5.f},{4.f,5.f},{4.f,5.f},{ 4.f,5.f},{.3f,-.4f},{6.f,7.f},{6.f,7.f},{6.f,7.f},{6.f,7.f},{6.f, 7.f},{6.f,7.f},{6.f,7.f},{.1f,-.3f},{8.f,9.f},{.5f,-.1f},{2.f,5.f} ,{2.f,5.f},{2.f,5.f},{2.f,5.f},{2.f,5.f},{.1f,.1f},{3.f,6.f},{ -.6f,.1f},{4.f,7.f},{.1f,-.3f},{7.f,2.f},{7.f,2.f},{7.f,2.f},{.3f, .1f},{5.f,8.f},{.5f,0.f},{6.f,9.f},{0.f,.5f},{8.f,3.f},{0.f,.2f},{ 9.f,4.f} }; /* System generated locals */ integer i__1, i__2, i__3; real r__1; complex q__1; /* Builtin functions */ integer s_wsle(cilist *), do_lio(integer *, integer *, char *, ftnlen), e_wsle(void); /* Subroutine */ int s_stop(char *, ftnlen); /* Local variables */ integer i__; complex cx[8]; integer np1, len; extern /* Subroutine */ int cscal_(integer *, complex *, complex *, integer *), ctest_(integer *, complex *, complex *, complex *, real *); complex mwpcs[5], mwpct[5]; extern real scnrm2_(integer *, complex *, integer *); extern /* Subroutine */ int itest1_(integer *, integer *), stest1_(real *, real *, real *, real *); extern integer icamax_(integer *, complex *, integer *); extern /* Subroutine */ int csscal_(integer *, real *, complex *, integer *); extern real scasum_(integer *, complex *, integer *); /* Fortran I/O blocks */ static cilist io___19 = { 0, 6, 0, 0, 0 }; /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Scalars in Common .. */ /* .. Local Scalars .. */ /* .. Local Arrays .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. Common blocks .. */ /* .. Data statements .. */ /* .. Executable Statements .. */ for (combla_1.incx = 1; combla_1.incx <= 2; ++combla_1.incx) { for (np1 = 1; np1 <= 5; ++np1) { combla_1.n = np1 - 1; len = max(combla_1.n,1) << 1; /* .. Set vector arguments .. */ i__1 = len; for (i__ = 1; i__ <= i__1; ++i__) { i__2 = i__ - 1; i__3 = i__ + (np1 + combla_1.incx * 5 << 3) - 49; cx[i__2].r = cv[i__3].r, cx[i__2].i = cv[i__3].i; /* L20: */ } if (combla_1.icase == 6) { /* .. SCNRM2 .. */ r__1 = scnrm2_(&combla_1.n, cx, &combla_1.incx); stest1_(&r__1, &strue2[np1 - 1], &strue2[np1 - 1], sfac); } else if (combla_1.icase == 7) { /* .. SCASUM .. */ r__1 = scasum_(&combla_1.n, cx, &combla_1.incx); stest1_(&r__1, &strue4[np1 - 1], &strue4[np1 - 1], sfac); } else if (combla_1.icase == 8) { /* .. CSCAL .. */ cscal_(&combla_1.n, &ca, cx, &combla_1.incx); ctest_(&len, cx, &ctrue5[(np1 + combla_1.incx * 5 << 3) - 48], &ctrue5[(np1 + combla_1.incx * 5 << 3) - 48], sfac); } else if (combla_1.icase == 9) { /* .. CSSCAL .. */ csscal_(&combla_1.n, &sa, cx, &combla_1.incx); ctest_(&len, cx, &ctrue6[(np1 + combla_1.incx * 5 << 3) - 48], &ctrue6[(np1 + combla_1.incx * 5 << 3) - 48], sfac); } else if (combla_1.icase == 10) { /* .. ICAMAX .. */ i__1 = icamax_(&combla_1.n, cx, &combla_1.incx); itest1_(&i__1, &itrue3[np1 - 1]); } else { s_wsle(&io___19); do_lio(&c__9, &c__1, " Shouldn't be here in CHECK1", (ftnlen) 28); e_wsle(); s_stop("", (ftnlen)0); } /* L40: */ } /* L60: */ } combla_1.incx = 1; if (combla_1.icase == 8) { /* CSCAL */ /* Add a test for alpha equal to zero. */ ca.r = 0.f, ca.i = 0.f; for (i__ = 1; i__ <= 5; ++i__) { i__1 = i__ - 1; mwpct[i__1].r = 0.f, mwpct[i__1].i = 0.f; i__1 = i__ - 1; mwpcs[i__1].r = 1.f, mwpcs[i__1].i = 1.f; /* L80: */ } cscal_(&c__5, &ca, cx, &combla_1.incx); ctest_(&c__5, cx, mwpct, mwpcs, sfac); } else if (combla_1.icase == 9) { /* CSSCAL */ /* Add a test for alpha equal to zero. */ sa = 0.f; for (i__ = 1; i__ <= 5; ++i__) { i__1 = i__ - 1; mwpct[i__1].r = 0.f, mwpct[i__1].i = 0.f; i__1 = i__ - 1; mwpcs[i__1].r = 1.f, mwpcs[i__1].i = 1.f; /* L100: */ } csscal_(&c__5, &sa, cx, &combla_1.incx); ctest_(&c__5, cx, mwpct, mwpcs, sfac); /* Add a test for alpha equal to one. */ sa = 1.f; for (i__ = 1; i__ <= 5; ++i__) { i__1 = i__ - 1; i__2 = i__ - 1; mwpct[i__1].r = cx[i__2].r, mwpct[i__1].i = cx[i__2].i; i__1 = i__ - 1; i__2 = i__ - 1; mwpcs[i__1].r = cx[i__2].r, mwpcs[i__1].i = cx[i__2].i; /* L120: */ } csscal_(&c__5, &sa, cx, &combla_1.incx); ctest_(&c__5, cx, mwpct, mwpcs, sfac); /* Add a test for alpha equal to minus one. */ sa = -1.f; for (i__ = 1; i__ <= 5; ++i__) { i__1 = i__ - 1; i__2 = i__ - 1; q__1.r = -cx[i__2].r, q__1.i = -cx[i__2].i; mwpct[i__1].r = q__1.r, mwpct[i__1].i = q__1.i; i__1 = i__ - 1; i__2 = i__ - 1; q__1.r = -cx[i__2].r, q__1.i = -cx[i__2].i; mwpcs[i__1].r = q__1.r, mwpcs[i__1].i = q__1.i; /* L140: */ } csscal_(&c__5, &sa, cx, &combla_1.incx); ctest_(&c__5, cx, mwpct, mwpcs, sfac); } return 0; } /* check1_ */ /* Subroutine */ int check2_(real *sfac) { /* Initialized data */ static complex ca = {.4f,-.7f}; static integer incxs[4] = { 1,2,-2,-1 }; static integer incys[4] = { 1,-2,1,-2 }; static integer lens[8] /* was [4][2] */ = { 1,1,2,4,1,1,3,7 }; static integer ns[4] = { 0,1,2,4 }; static complex cx1[7] = { {.7f,-.8f},{-.4f,-.7f},{-.1f,-.9f},{.2f,-.8f},{ -.9f,-.4f},{.1f,.4f},{-.6f,.6f} }; static complex cy1[7] = { {.6f,-.6f},{-.9f,.5f},{.7f,-.6f},{.1f,-.5f},{ -.1f,-.2f},{-.5f,-.3f},{.8f,-.7f} }; static complex ct8[112] /* was [7][4][4] */ = { {.6f,-.6f},{0.f,0.f},{ 0.f,0.f},{0.f,0.f},{0.f,0.f},{0.f,0.f},{0.f,0.f},{.32f,-1.41f},{ 0.f,0.f},{0.f,0.f},{0.f,0.f},{0.f,0.f},{0.f,0.f},{0.f,0.f},{.32f, -1.41f},{-1.55f,.5f},{0.f,0.f},{0.f,0.f},{0.f,0.f},{0.f,0.f},{0.f, 0.f},{.32f,-1.41f},{-1.55f,.5f},{.03f,-.89f},{-.38f,-.96f},{0.f, 0.f},{0.f,0.f},{0.f,0.f},{.6f,-.6f},{0.f,0.f},{0.f,0.f},{0.f,0.f}, {0.f,0.f},{0.f,0.f},{0.f,0.f},{.32f,-1.41f},{0.f,0.f},{0.f,0.f},{ 0.f,0.f},{0.f,0.f},{0.f,0.f},{0.f,0.f},{-.07f,-.89f},{-.9f,.5f},{ .42f,-1.41f},{0.f,0.f},{0.f,0.f},{0.f,0.f},{0.f,0.f},{.78f,.06f},{ -.9f,.5f},{.06f,-.13f},{.1f,-.5f},{-.77f,-.49f},{-.5f,-.3f},{.52f, -1.51f},{.6f,-.6f},{0.f,0.f},{0.f,0.f},{0.f,0.f},{0.f,0.f},{0.f, 0.f},{0.f,0.f},{.32f,-1.41f},{0.f,0.f},{0.f,0.f},{0.f,0.f},{0.f, 0.f},{0.f,0.f},{0.f,0.f},{-.07f,-.89f},{-1.18f,-.31f},{0.f,0.f},{ 0.f,0.f},{0.f,0.f},{0.f,0.f},{0.f,0.f},{.78f,.06f},{-1.54f,.97f},{ .03f,-.89f},{-.18f,-1.31f},{0.f,0.f},{0.f,0.f},{0.f,0.f},{.6f, -.6f},{0.f,0.f},{0.f,0.f},{0.f,0.f},{0.f,0.f},{0.f,0.f},{0.f,0.f}, {.32f,-1.41f},{0.f,0.f},{0.f,0.f},{0.f,0.f},{0.f,0.f},{0.f,0.f},{ 0.f,0.f},{.32f,-1.41f},{-.9f,.5f},{.05f,-.6f},{0.f,0.f},{0.f,0.f}, {0.f,0.f},{0.f,0.f},{.32f,-1.41f},{-.9f,.5f},{.05f,-.6f},{.1f, -.5f},{-.77f,-.49f},{-.5f,-.3f},{.32f,-1.16f} }; static complex ct7[16] /* was [4][4] */ = { {0.f,0.f},{-.06f,-.9f},{ .65f,-.47f},{-.34f,-1.22f},{0.f,0.f},{-.06f,-.9f},{-.59f,-1.46f},{ -1.04f,-.04f},{0.f,0.f},{-.06f,-.9f},{-.83f,.59f},{.07f,-.37f},{ 0.f,0.f},{-.06f,-.9f},{-.76f,-1.15f},{-1.33f,-1.82f} }; static complex ct6[16] /* was [4][4] */ = { {0.f,0.f},{.9f,.06f},{ .91f,-.77f},{1.8f,-.1f},{0.f,0.f},{.9f,.06f},{1.45f,.74f},{.2f, .9f},{0.f,0.f},{.9f,.06f},{-.55f,.23f},{.83f,-.39f},{0.f,0.f},{ .9f,.06f},{1.04f,.79f},{1.95f,1.22f} }; static complex ct10x[112] /* was [7][4][4] */ = { {.7f,-.8f},{0.f,0.f},{ 0.f,0.f},{0.f,0.f},{0.f,0.f},{0.f,0.f},{0.f,0.f},{.6f,-.6f},{0.f, 0.f},{0.f,0.f},{0.f,0.f},{0.f,0.f},{0.f,0.f},{0.f,0.f},{.6f,-.6f}, {-.9f,.5f},{0.f,0.f},{0.f,0.f},{0.f,0.f},{0.f,0.f},{0.f,0.f},{.6f, -.6f},{-.9f,.5f},{.7f,-.6f},{.1f,-.5f},{0.f,0.f},{0.f,0.f},{0.f, 0.f},{.7f,-.8f},{0.f,0.f},{0.f,0.f},{0.f,0.f},{0.f,0.f},{0.f,0.f}, {0.f,0.f},{.6f,-.6f},{0.f,0.f},{0.f,0.f},{0.f,0.f},{0.f,0.f},{0.f, 0.f},{0.f,0.f},{.7f,-.6f},{-.4f,-.7f},{.6f,-.6f},{0.f,0.f},{0.f, 0.f},{0.f,0.f},{0.f,0.f},{.8f,-.7f},{-.4f,-.7f},{-.1f,-.2f},{.2f, -.8f},{.7f,-.6f},{.1f,.4f},{.6f,-.6f},{.7f,-.8f},{0.f,0.f},{0.f, 0.f},{0.f,0.f},{0.f,0.f},{0.f,0.f},{0.f,0.f},{.6f,-.6f},{0.f,0.f}, {0.f,0.f},{0.f,0.f},{0.f,0.f},{0.f,0.f},{0.f,0.f},{-.9f,.5f},{ -.4f,-.7f},{.6f,-.6f},{0.f,0.f},{0.f,0.f},{0.f,0.f},{0.f,0.f},{ .1f,-.5f},{-.4f,-.7f},{.7f,-.6f},{.2f,-.8f},{-.9f,.5f},{.1f,.4f},{ .6f,-.6f},{.7f,-.8f},{0.f,0.f},{0.f,0.f},{0.f,0.f},{0.f,0.f},{0.f, 0.f},{0.f,0.f},{.6f,-.6f},{0.f,0.f},{0.f,0.f},{0.f,0.f},{0.f,0.f}, {0.f,0.f},{0.f,0.f},{.6f,-.6f},{.7f,-.6f},{0.f,0.f},{0.f,0.f},{ 0.f,0.f},{0.f,0.f},{0.f,0.f},{.6f,-.6f},{.7f,-.6f},{-.1f,-.2f},{ .8f,-.7f},{0.f,0.f},{0.f,0.f},{0.f,0.f} }; static complex ct10y[112] /* was [7][4][4] */ = { {.6f,-.6f},{0.f,0.f},{ 0.f,0.f},{0.f,0.f},{0.f,0.f},{0.f,0.f},{0.f,0.f},{.7f,-.8f},{0.f, 0.f},{0.f,0.f},{0.f,0.f},{0.f,0.f},{0.f,0.f},{0.f,0.f},{.7f,-.8f}, {-.4f,-.7f},{0.f,0.f},{0.f,0.f},{0.f,0.f},{0.f,0.f},{0.f,0.f},{ .7f,-.8f},{-.4f,-.7f},{-.1f,-.9f},{.2f,-.8f},{0.f,0.f},{0.f,0.f},{ 0.f,0.f},{.6f,-.6f},{0.f,0.f},{0.f,0.f},{0.f,0.f},{0.f,0.f},{0.f, 0.f},{0.f,0.f},{.7f,-.8f},{0.f,0.f},{0.f,0.f},{0.f,0.f},{0.f,0.f}, {0.f,0.f},{0.f,0.f},{-.1f,-.9f},{-.9f,.5f},{.7f,-.8f},{0.f,0.f},{ 0.f,0.f},{0.f,0.f},{0.f,0.f},{-.6f,.6f},{-.9f,.5f},{-.9f,-.4f},{ .1f,-.5f},{-.1f,-.9f},{-.5f,-.3f},{.7f,-.8f},{.6f,-.6f},{0.f,0.f}, {0.f,0.f},{0.f,0.f},{0.f,0.f},{0.f,0.f},{0.f,0.f},{.7f,-.8f},{0.f, 0.f},{0.f,0.f},{0.f,0.f},{0.f,0.f},{0.f,0.f},{0.f,0.f},{-.1f,-.9f} ,{.7f,-.8f},{0.f,0.f},{0.f,0.f},{0.f,0.f},{0.f,0.f},{0.f,0.f},{ -.6f,.6f},{-.9f,-.4f},{-.1f,-.9f},{.7f,-.8f},{0.f,0.f},{0.f,0.f},{ 0.f,0.f},{.6f,-.6f},{0.f,0.f},{0.f,0.f},{0.f,0.f},{0.f,0.f},{0.f, 0.f},{0.f,0.f},{.7f,-.8f},{0.f,0.f},{0.f,0.f},{0.f,0.f},{0.f,0.f}, {0.f,0.f},{0.f,0.f},{.7f,-.8f},{-.9f,.5f},{-.4f,-.7f},{0.f,0.f},{ 0.f,0.f},{0.f,0.f},{0.f,0.f},{.7f,-.8f},{-.9f,.5f},{-.4f,-.7f},{ .1f,-.5f},{-.1f,-.9f},{-.5f,-.3f},{.2f,-.8f} }; static complex csize1[4] = { {0.f,0.f},{.9f,.9f},{1.63f,1.73f},{2.9f, 2.78f} }; static complex csize3[14] = { {0.f,0.f},{0.f,0.f},{0.f,0.f},{0.f,0.f},{ 0.f,0.f},{0.f,0.f},{0.f,0.f},{1.17f,1.17f},{1.17f,1.17f},{1.17f, 1.17f},{1.17f,1.17f},{1.17f,1.17f},{1.17f,1.17f},{1.17f,1.17f} }; static complex csize2[14] /* was [7][2] */ = { {0.f,0.f},{0.f,0.f},{0.f, 0.f},{0.f,0.f},{0.f,0.f},{0.f,0.f},{0.f,0.f},{1.54f,1.54f},{1.54f, 1.54f},{1.54f,1.54f},{1.54f,1.54f},{1.54f,1.54f},{1.54f,1.54f},{ 1.54f,1.54f} }; /* System generated locals */ integer i__1, i__2; complex q__1; /* Builtin functions */ integer s_wsle(cilist *), do_lio(integer *, integer *, char *, ftnlen), e_wsle(void); /* Subroutine */ int s_stop(char *, ftnlen); /* Local variables */ integer i__, ki, kn; complex cx[7], cy[7]; integer mx, my; complex cdot[1]; integer lenx, leny; extern /* Complex */ complex cdotc_(integer *, complex *, integer *, complex *, integer *); extern /* Subroutine */ int ccopy_(integer *, complex *, integer *, complex *, integer *); extern /* Complex */ complex cdotu_(integer *, complex *, integer *, complex *, integer *); extern /* Subroutine */ int cswap_(integer *, complex *, integer *, complex *, integer *), ctest_(integer *, complex *, complex *, complex *, real *); integer ksize; extern /* Subroutine */ int caxpy_(integer *, complex *, complex *, integer *, complex *, integer *); /* Fortran I/O blocks */ static cilist io___48 = { 0, 6, 0, 0, 0 }; /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Scalars in Common .. */ /* .. Local Scalars .. */ /* .. Local Arrays .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. Common blocks .. */ /* .. Data statements .. */ /* .. Executable Statements .. */ for (ki = 1; ki <= 4; ++ki) { combla_1.incx = incxs[ki - 1]; combla_1.incy = incys[ki - 1]; mx = abs(combla_1.incx); my = abs(combla_1.incy); for (kn = 1; kn <= 4; ++kn) { combla_1.n = ns[kn - 1]; ksize = min(2,kn); lenx = lens[kn + (mx << 2) - 5]; leny = lens[kn + (my << 2) - 5]; /* .. initialize all argument arrays .. */ for (i__ = 1; i__ <= 7; ++i__) { i__1 = i__ - 1; i__2 = i__ - 1; cx[i__1].r = cx1[i__2].r, cx[i__1].i = cx1[i__2].i; i__1 = i__ - 1; i__2 = i__ - 1; cy[i__1].r = cy1[i__2].r, cy[i__1].i = cy1[i__2].i; /* L20: */ } if (combla_1.icase == 1) { /* .. CDOTC .. */ q__1 = cdotc_(&combla_1.n, cx, &combla_1.incx, cy, & combla_1.incy); cdot[0].r = q__1.r, cdot[0].i = q__1.i; ctest_(&c__1, cdot, &ct6[kn + (ki << 2) - 5], &csize1[kn - 1], sfac); } else if (combla_1.icase == 2) { /* .. CDOTU .. */ q__1 = cdotu_(&combla_1.n, cx, &combla_1.incx, cy, & combla_1.incy); cdot[0].r = q__1.r, cdot[0].i = q__1.i; ctest_(&c__1, cdot, &ct7[kn + (ki << 2) - 5], &csize1[kn - 1], sfac); } else if (combla_1.icase == 3) { /* .. CAXPY .. */ caxpy_(&combla_1.n, &ca, cx, &combla_1.incx, cy, & combla_1.incy); ctest_(&leny, cy, &ct8[(kn + (ki << 2)) * 7 - 35], &csize2[ ksize * 7 - 7], sfac); } else if (combla_1.icase == 4) { /* .. CCOPY .. */ ccopy_(&combla_1.n, cx, &combla_1.incx, cy, &combla_1.incy); ctest_(&leny, cy, &ct10y[(kn + (ki << 2)) * 7 - 35], csize3, & c_b43); } else if (combla_1.icase == 5) { /* .. CSWAP .. */ cswap_(&combla_1.n, cx, &combla_1.incx, cy, &combla_1.incy); ctest_(&lenx, cx, &ct10x[(kn + (ki << 2)) * 7 - 35], csize3, & c_b43); ctest_(&leny, cy, &ct10y[(kn + (ki << 2)) * 7 - 35], csize3, & c_b43); } else { s_wsle(&io___48); do_lio(&c__9, &c__1, " Shouldn't be here in CHECK2", (ftnlen) 28); e_wsle(); s_stop("", (ftnlen)0); } /* L40: */ } /* L60: */ } return 0; } /* check2_ */ /* Subroutine */ int stest_(integer *len, real *scomp, real *strue, real * ssize, real *sfac) { /* Format strings */ static char fmt_99999[] = "(\002 F" "AIL\002)"; static char fmt_99998[] = "(/\002 CASE N INCX INCY MODE I " " \002,\002 COMP(I) TRU" "E(I) DIFFERENCE\002,\002 SIZE(I)\002,/1x)"; static char fmt_99997[] = "(1x,i4,i3,3i5,i3,2e36.8,2e12.4)"; /* System generated locals */ integer i__1; real r__1, r__2; /* Builtin functions */ integer s_wsfe(cilist *), e_wsfe(void), do_fio(integer *, char *, ftnlen); /* Local variables */ integer i__; real sd; extern real s_epsilon_(real *); /* Fortran I/O blocks */ static cilist io___51 = { 0, 6, 0, fmt_99999, 0 }; static cilist io___52 = { 0, 6, 0, fmt_99998, 0 }; static cilist io___53 = { 0, 6, 0, fmt_99997, 0 }; /* ********************************* STEST ************************** */ /* THIS SUBR COMPARES ARRAYS SCOMP() AND STRUE() OF LENGTH LEN TO */ /* SEE IF THE TERM BY TERM DIFFERENCES, MULTIPLIED BY SFAC, ARE */ /* NEGLIGIBLE. */ /* C. L. LAWSON, JPL, 1974 DEC 10 */ /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Scalars in Common .. */ /* .. Local Scalars .. */ /* .. External Functions .. */ /* .. Intrinsic Functions .. */ /* .. Common blocks .. */ /* .. Executable Statements .. */ /* Parameter adjustments */ --ssize; --strue; --scomp; /* Function Body */ i__1 = *len; for (i__ = 1; i__ <= i__1; ++i__) { sd = scomp[i__] - strue[i__]; if ((r__2 = *sfac * sd, abs(r__2)) <= (r__1 = ssize[i__], abs(r__1)) * s_epsilon_(&c_b52)) { goto L40; } /* HERE SCOMP(I) IS NOT CLOSE TO STRUE(I). */ if (! combla_1.pass) { goto L20; } /* PRINT FAIL MESSAGE AND HEADER. */ combla_1.pass = FALSE_; s_wsfe(&io___51); e_wsfe(); s_wsfe(&io___52); e_wsfe(); L20: s_wsfe(&io___53); do_fio(&c__1, (char *)&combla_1.icase, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&combla_1.n, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&combla_1.incx, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&combla_1.incy, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&combla_1.mode, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&i__, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&scomp[i__], (ftnlen)sizeof(real)); do_fio(&c__1, (char *)&strue[i__], (ftnlen)sizeof(real)); do_fio(&c__1, (char *)&sd, (ftnlen)sizeof(real)); do_fio(&c__1, (char *)&ssize[i__], (ftnlen)sizeof(real)); e_wsfe(); L40: ; } return 0; } /* stest_ */ /* Subroutine */ int stest1_(real *scomp1, real *strue1, real *ssize, real * sfac) { real scomp[1], strue[1]; extern /* Subroutine */ int stest_(integer *, real *, real *, real *, real *); /* ************************* STEST1 ***************************** */ /* THIS IS AN INTERFACE SUBROUTINE TO ACCOMODATE THE FORTRAN */ /* REQUIREMENT THAT WHEN A DUMMY ARGUMENT IS AN ARRAY, THE */ /* ACTUAL ARGUMENT MUST ALSO BE AN ARRAY OR AN ARRAY ELEMENT. */ /* C.L. LAWSON, JPL, 1978 DEC 6 */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Arrays .. */ /* .. External Subroutines .. */ /* .. Executable Statements .. */ /* Parameter adjustments */ --ssize; /* Function Body */ scomp[0] = *scomp1; strue[0] = *strue1; stest_(&c__1, scomp, strue, &ssize[1], sfac); return 0; } /* stest1_ */ real sdiff_(real *sa, real *sb) { /* System generated locals */ real ret_val; /* ********************************* SDIFF ************************** */ /* COMPUTES DIFFERENCE OF TWO NUMBERS. C. L. LAWSON, JPL 1974 FEB 15 */ /* .. Scalar Arguments .. */ /* .. Executable Statements .. */ ret_val = *sa - *sb; return ret_val; } /* sdiff_ */ /* Subroutine */ int ctest_(integer *len, complex *ccomp, complex *ctrue, complex *csize, real *sfac) { /* System generated locals */ integer i__1, i__2; /* Builtin functions */ double r_imag(complex *); /* Local variables */ integer i__; real scomp[20], ssize[20], strue[20]; extern /* Subroutine */ int stest_(integer *, real *, real *, real *, real *); /* **************************** CTEST ***************************** */ /* C.L. LAWSON, JPL, 1978 DEC 6 */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Scalars .. */ /* .. Local Arrays .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. Executable Statements .. */ /* Parameter adjustments */ --csize; --ctrue; --ccomp; /* Function Body */ i__1 = *len; for (i__ = 1; i__ <= i__1; ++i__) { i__2 = i__; scomp[(i__ << 1) - 2] = ccomp[i__2].r; scomp[(i__ << 1) - 1] = r_imag(&ccomp[i__]); i__2 = i__; strue[(i__ << 1) - 2] = ctrue[i__2].r; strue[(i__ << 1) - 1] = r_imag(&ctrue[i__]); i__2 = i__; ssize[(i__ << 1) - 2] = csize[i__2].r; ssize[(i__ << 1) - 1] = r_imag(&csize[i__]); /* L20: */ } i__1 = *len << 1; stest_(&i__1, scomp, strue, ssize, sfac); return 0; } /* ctest_ */ /* Subroutine */ int itest1_(integer *icomp, integer *itrue) { /* Format strings */ static char fmt_99999[] = "(\002 F" "AIL\002)"; static char fmt_99998[] = "(/\002 CASE N INCX INCY MODE " " \002,\002 COMP TRU" "E DIFFERENCE\002,/1x)"; static char fmt_99997[] = "(1x,i4,i3,3i5,2i36,i12)"; /* Builtin functions */ integer s_wsfe(cilist *), e_wsfe(void), do_fio(integer *, char *, ftnlen); /* Local variables */ integer id; /* Fortran I/O blocks */ static cilist io___60 = { 0, 6, 0, fmt_99999, 0 }; static cilist io___61 = { 0, 6, 0, fmt_99998, 0 }; static cilist io___63 = { 0, 6, 0, fmt_99997, 0 }; /* ********************************* ITEST1 ************************* */ /* THIS SUBROUTINE COMPARES THE VARIABLES ICOMP AND ITRUE FOR */ /* EQUALITY. */ /* C. L. LAWSON, JPL, 1974 DEC 10 */ /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Scalars in Common .. */ /* .. Local Scalars .. */ /* .. Common blocks .. */ /* .. Executable Statements .. */ if (*icomp == *itrue) { goto L40; } /* HERE ICOMP IS NOT EQUAL TO ITRUE. */ if (! combla_1.pass) { goto L20; } /* PRINT FAIL MESSAGE AND HEADER. */ combla_1.pass = FALSE_; s_wsfe(&io___60); e_wsfe(); s_wsfe(&io___61); e_wsfe(); L20: id = *icomp - *itrue; s_wsfe(&io___63); do_fio(&c__1, (char *)&combla_1.icase, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&combla_1.n, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&combla_1.incx, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&combla_1.incy, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&combla_1.mode, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&(*icomp), (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&(*itrue), (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&id, (ftnlen)sizeof(integer)); e_wsfe(); L40: return 0; } /* itest1_ */ /* Main program alias */ int cblat1_ () { main (); return 0; } blis-0.9.0/blastest/src/cblat2.c000066400000000000000000004766721422157504600164300ustar00rootroot00000000000000/* cblat2.f -- translated by f2c (version 20100827). You must link the resulting object file with libf2c: on Microsoft Windows system, link with libf2c.lib; on Linux or Unix systems, link with .../path/to/libf2c.a -lm or, if you install libf2c.a in a standard place, with -lf2c -lm -- in that order, at the end of the command line, as in cc *.o -lf2c -lm Source for libf2c is in /netlib/f2c/libf2c.zip, e.g., http://www.netlib.org/f2c/libf2c.zip */ #include "f2c.h" /* Common Block Declarations */ union { struct { integer infot, noutc; logical ok, lerr; } _1; struct { integer infot, nout; logical ok, lerr; } _2; } infoc_; #define infoc_1 (infoc_._1) #define infoc_2 (infoc_._2) struct { char srnamt[6]; } srnamc_; #define srnamc_1 srnamc_ /* Table of constant values */ static complex c_b1 = {0.f,0.f}; static complex c_b2 = {1.f,0.f}; static integer c__9 = 9; static integer c__1 = 1; static integer c__3 = 3; static integer c__8 = 8; static integer c__4 = 4; static integer c__65 = 65; static integer c__7 = 7; static integer c__2 = 2; static integer c__6 = 6; static real c_b122 = 0.f; static logical c_true = TRUE_; static integer c_n1 = -1; static integer c__0 = 0; static logical c_false = FALSE_; /* > \brief \b CBLAT2 */ /* =========== DOCUMENTATION =========== */ /* Online html documentation available at */ /* http://www.netlib.org/lapack/explore-html/ */ /* Definition: */ /* =========== */ /* PROGRAM CBLAT2 */ /* > \par Purpose: */ /* ============= */ /* > */ /* > \verbatim */ /* > */ /* > Test program for the COMPLEX Level 2 Blas. */ /* > */ /* > The program must be driven by a short data file. The first 18 records */ /* > of the file are read using list-directed input, the last 17 records */ /* > are read using the format ( A6, L2 ). An annotated example of a data */ /* > file can be obtained by deleting the first 3 characters from the */ /* > following 35 lines: */ /* > 'cblat2.out' NAME OF SUMMARY OUTPUT FILE */ /* > 6 UNIT NUMBER OF SUMMARY FILE */ /* > 'CBLA2T.SNAP' NAME OF SNAPSHOT OUTPUT FILE */ /* > -1 UNIT NUMBER OF SNAPSHOT FILE (NOT USED IF .LT. 0) */ /* > F LOGICAL FLAG, T TO REWIND SNAPSHOT FILE AFTER EACH RECORD. */ /* > F LOGICAL FLAG, T TO STOP ON FAILURES. */ /* > T LOGICAL FLAG, T TO TEST ERROR EXITS. */ /* > 16.0 THRESHOLD VALUE OF TEST RATIO */ /* > 6 NUMBER OF VALUES OF N */ /* > 0 1 2 3 5 9 VALUES OF N */ /* > 4 NUMBER OF VALUES OF K */ /* > 0 1 2 4 VALUES OF K */ /* > 4 NUMBER OF VALUES OF INCX AND INCY */ /* > 1 2 -1 -2 VALUES OF INCX AND INCY */ /* > 3 NUMBER OF VALUES OF ALPHA */ /* > (0.0,0.0) (1.0,0.0) (0.7,-0.9) VALUES OF ALPHA */ /* > 3 NUMBER OF VALUES OF BETA */ /* > (0.0,0.0) (1.0,0.0) (1.3,-1.1) VALUES OF BETA */ /* > CGEMV T PUT F FOR NO TEST. SAME COLUMNS. */ /* > CGBMV T PUT F FOR NO TEST. SAME COLUMNS. */ /* > CHEMV T PUT F FOR NO TEST. SAME COLUMNS. */ /* > CHBMV T PUT F FOR NO TEST. SAME COLUMNS. */ /* > CHPMV T PUT F FOR NO TEST. SAME COLUMNS. */ /* > CTRMV T PUT F FOR NO TEST. SAME COLUMNS. */ /* > CTBMV T PUT F FOR NO TEST. SAME COLUMNS. */ /* > CTPMV T PUT F FOR NO TEST. SAME COLUMNS. */ /* > CTRSV T PUT F FOR NO TEST. SAME COLUMNS. */ /* > CTBSV T PUT F FOR NO TEST. SAME COLUMNS. */ /* > CTPSV T PUT F FOR NO TEST. SAME COLUMNS. */ /* > CGERC T PUT F FOR NO TEST. SAME COLUMNS. */ /* > CGERU T PUT F FOR NO TEST. SAME COLUMNS. */ /* > CHER T PUT F FOR NO TEST. SAME COLUMNS. */ /* > CHPR T PUT F FOR NO TEST. SAME COLUMNS. */ /* > CHER2 T PUT F FOR NO TEST. SAME COLUMNS. */ /* > CHPR2 T PUT F FOR NO TEST. SAME COLUMNS. */ /* > */ /* > Further Details */ /* > =============== */ /* > */ /* > See: */ /* > */ /* > Dongarra J. J., Du Croz J. J., Hammarling S. and Hanson R. J.. */ /* > An extended set of Fortran Basic Linear Algebra Subprograms. */ /* > */ /* > Technical Memoranda Nos. 41 (revision 3) and 81, Mathematics */ /* > and Computer Science Division, Argonne National Laboratory, */ /* > 9700 South Cass Avenue, Argonne, Illinois 60439, US. */ /* > */ /* > Or */ /* > */ /* > NAG Technical Reports TR3/87 and TR4/87, Numerical Algorithms */ /* > Group Ltd., NAG Central Office, 256 Banbury Road, Oxford */ /* > OX2 7DE, UK, and Numerical Algorithms Group Inc., 1101 31st */ /* > Street, Suite 100, Downers Grove, Illinois 60515-1263, USA. */ /* > */ /* > */ /* > -- Written on 10-August-1987. */ /* > Richard Hanson, Sandia National Labs. */ /* > Jeremy Du Croz, NAG Central Office. */ /* > */ /* > 10-9-00: Change STATUS='NEW' to 'UNKNOWN' so that the testers */ /* > can be run multiple times without deleting generated */ /* > output files (susan) */ /* > \endverbatim */ /* Authors: */ /* ======== */ /* > \author Univ. of Tennessee */ /* > \author Univ. of California Berkeley */ /* > \author Univ. of Colorado Denver */ /* > \author NAG Ltd. */ /* > \date April 2012 */ /* > \ingroup complex_blas_testing */ /* ===================================================================== */ /* Main program */ int main(void) { /* Initialized data */ static char snames[6*17] = "CGEMV " "CGBMV " "CHEMV " "CHBMV " "CHPMV " "CTRMV " "CTBMV " "CTPMV " "CTRSV " "CTBSV " "CTPSV " "CGERC " "CGERU " "CHER " "CHPR " "CHER2 " "CHPR2 "; /* Format strings */ static char fmt_9997[] = "(\002 NUMBER OF VALUES OF \002,a,\002 IS LESS " "THAN 1 OR GREATER \002,\002THAN \002,i2)"; static char fmt_9996[] = "(\002 VALUE OF N IS LESS THAN 0 OR GREATER THA" "N \002,i2)"; static char fmt_9995[] = "(\002 VALUE OF K IS LESS THAN 0\002)"; static char fmt_9994[] = "(\002 ABSOLUTE VALUE OF INCX OR INCY IS 0 OR G" "REATER THAN \002,i2)"; static char fmt_9993[] = "(\002 TESTS OF THE COMPLEX LEVEL 2 BL" "AS\002,//\002 THE F\002,\002OLLOWING PARAMETER VALUES WILL BE US" "ED:\002)"; static char fmt_9992[] = "(\002 FOR N \002,9i6)"; static char fmt_9991[] = "(\002 FOR K \002,7i6)"; static char fmt_9990[] = "(\002 FOR INCX AND INCY \002,7i6)"; static char fmt_9989[] = "(\002 FOR ALPHA \002,7(\002(\002,f4" ".1,\002,\002,f4.1,\002) \002,:))"; static char fmt_9988[] = "(\002 FOR BETA \002,7(\002(\002,f4" ".1,\002,\002,f4.1,\002) \002,:))"; static char fmt_9980[] = "(\002 ERROR-EXITS WILL NOT BE TESTED\002)"; static char fmt_9999[] = "(\002 ROUTINES PASS COMPUTATIONAL TESTS IF TES" "T RATIO IS LES\002,\002S THAN\002,f8.2)"; static char fmt_9984[] = "(a6,l2)"; static char fmt_9986[] = "(\002 SUBPROGRAM NAME \002,a6,\002 NOT RECOGNI" "ZED\002,/\002 ******* T\002,\002ESTS ABANDONED *******\002)"; static char fmt_9998[] = "(\002 RELATIVE MACHINE PRECISION IS TAKEN TO" " BE\002,1p,e9.1)"; static char fmt_9985[] = "(\002 ERROR IN CMVCH - IN-LINE DOT PRODUCTS A" "RE BEING EVALU\002,\002ATED WRONGLY.\002,/\002 CMVCH WAS CALLED " "WITH TRANS = \002,a1,\002 AND RETURNED SAME = \002,l1,\002 AND E" "RR = \002,f12.3,\002.\002,/\002 THIS MAY BE DUE TO FAULTS IN THE" " ARITHMETIC OR THE COMPILER.\002,/\002 ******* TESTS ABANDONED *" "******\002)"; static char fmt_9983[] = "(1x,a6,\002 WAS NOT TESTED\002)"; static char fmt_9982[] = "(/\002 END OF TESTS\002)"; static char fmt_9981[] = "(/\002 ******* FATAL ERROR - TESTS ABANDONED *" "******\002)"; static char fmt_9987[] = "(\002 AMEND DATA FILE OR INCREASE ARRAY SIZES " "IN PROGRAM\002,/\002 ******* TESTS ABANDONED *******\002)"; /* System generated locals */ integer i__1, i__2, i__3, i__4, i__5; olist o__1; cllist cl__1; /* Builtin functions */ integer s_rsle(cilist *), do_lio(integer *, integer *, char *, ftnlen), e_rsle(void), f_open(olist *), s_wsfe(cilist *), do_fio(integer *, char *, ftnlen), e_wsfe(void), s_wsle(cilist *), e_wsle(void), s_rsfe(cilist *), e_rsfe(void), s_cmp(const char *, const char *, ftnlen, ftnlen); /* Subroutine */ int s_stop(char *, ftnlen); integer f_clos(cllist *); /* Subroutine */ int s_copy(char *, const char *, ftnlen, ftnlen); /* Local variables */ complex a[4225] /* was [65][65] */; real g[65]; integer i__, j, n; complex x[65], y[65], z__[130], aa[4225]; integer kb[7]; complex as[4225], xs[130], ys[130], yt[65], xx[130], yy[130], alf[7]; extern logical lce_(complex *, complex *, integer *); integer inc[7], nkb; complex bet[7]; real eps, err; integer nalf, idim[9]; logical same; integer ninc, nbet, ntra; logical rewi; integer nout; extern /* Subroutine */ int cchk1_(char *, real *, real *, integer *, integer *, logical *, logical *, logical *, integer *, integer *, integer *, integer *, integer *, complex *, integer *, complex *, integer *, integer *, integer *, integer *, complex *, complex *, complex *, complex *, complex *, complex *, complex *, complex *, complex *, complex *, real *, ftnlen), cchk2_(char *, real *, real *, integer *, integer *, logical *, logical *, logical *, integer *, integer *, integer *, integer *, integer *, complex *, integer *, complex *, integer *, integer *, integer *, integer *, complex *, complex *, complex *, complex *, complex *, complex *, complex *, complex *, complex *, complex *, real *, ftnlen), cchk3_(char *, real *, real *, integer *, integer *, logical *, logical *, logical *, integer *, integer *, integer *, integer *, integer *, integer *, integer *, integer *, complex *, complex *, complex *, complex *, complex *, complex *, complex *, real *, complex *, ftnlen), cchk4_(char *, real *, real *, integer *, integer *, logical *, logical *, logical *, integer *, integer *, integer *, complex *, integer *, integer *, integer *, integer *, complex *, complex *, complex *, complex *, complex *, complex *, complex *, complex *, complex *, complex *, real *, complex *, ftnlen), cchk5_(char *, real *, real *, integer *, integer *, logical *, logical *, logical *, integer *, integer *, integer *, complex *, integer *, integer *, integer *, integer *, complex *, complex *, complex *, complex *, complex *, complex *, complex *, complex *, complex *, complex *, real *, complex *, ftnlen), cchk6_(char *, real *, real *, integer *, integer *, logical *, logical *, logical *, integer *, integer *, integer *, complex *, integer *, integer *, integer *, integer *, complex *, complex *, complex *, complex *, complex *, complex *, complex *, complex *, complex *, complex *, real *, complex *, ftnlen), cchke_(integer * , char *, integer *, ftnlen); logical fatal, trace; integer nidim; extern /* Subroutine */ int cmvch_(char *, integer *, integer *, complex * , complex *, integer *, complex *, integer *, complex *, complex * , integer *, complex *, real *, complex *, real *, real *, logical *, integer *, logical *, ftnlen); char snaps[32], trans[1]; integer isnum; logical ltest[17], sfatal; char snamet[6]; real thresh; logical ltestt, tsterr; char summry[32]; extern real s_epsilon_(real *); /* Fortran I/O blocks */ static cilist io___2 = { 0, 5, 0, 0, 0 }; static cilist io___4 = { 0, 5, 0, 0, 0 }; static cilist io___6 = { 0, 5, 0, 0, 0 }; static cilist io___8 = { 0, 5, 0, 0, 0 }; static cilist io___11 = { 0, 5, 0, 0, 0 }; static cilist io___13 = { 0, 5, 0, 0, 0 }; static cilist io___15 = { 0, 5, 0, 0, 0 }; static cilist io___17 = { 0, 5, 0, 0, 0 }; static cilist io___19 = { 0, 5, 0, 0, 0 }; static cilist io___21 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___22 = { 0, 5, 0, 0, 0 }; static cilist io___25 = { 0, 0, 0, fmt_9996, 0 }; static cilist io___26 = { 0, 5, 0, 0, 0 }; static cilist io___28 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___29 = { 0, 5, 0, 0, 0 }; static cilist io___31 = { 0, 0, 0, fmt_9995, 0 }; static cilist io___32 = { 0, 5, 0, 0, 0 }; static cilist io___34 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___35 = { 0, 5, 0, 0, 0 }; static cilist io___37 = { 0, 0, 0, fmt_9994, 0 }; static cilist io___38 = { 0, 5, 0, 0, 0 }; static cilist io___40 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___41 = { 0, 5, 0, 0, 0 }; static cilist io___43 = { 0, 5, 0, 0, 0 }; static cilist io___45 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___46 = { 0, 5, 0, 0, 0 }; static cilist io___48 = { 0, 0, 0, fmt_9993, 0 }; static cilist io___49 = { 0, 0, 0, fmt_9992, 0 }; static cilist io___50 = { 0, 0, 0, fmt_9991, 0 }; static cilist io___51 = { 0, 0, 0, fmt_9990, 0 }; static cilist io___52 = { 0, 0, 0, fmt_9989, 0 }; static cilist io___53 = { 0, 0, 0, fmt_9988, 0 }; static cilist io___54 = { 0, 0, 0, 0, 0 }; static cilist io___55 = { 0, 0, 0, fmt_9980, 0 }; static cilist io___56 = { 0, 0, 0, 0, 0 }; static cilist io___57 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___58 = { 0, 0, 0, 0, 0 }; static cilist io___60 = { 0, 5, 1, fmt_9984, 0 }; static cilist io___63 = { 0, 0, 0, fmt_9986, 0 }; static cilist io___65 = { 0, 0, 0, fmt_9998, 0 }; static cilist io___78 = { 0, 0, 0, fmt_9985, 0 }; static cilist io___79 = { 0, 0, 0, fmt_9985, 0 }; static cilist io___81 = { 0, 0, 0, 0, 0 }; static cilist io___82 = { 0, 0, 0, fmt_9983, 0 }; static cilist io___83 = { 0, 0, 0, 0, 0 }; static cilist io___90 = { 0, 0, 0, fmt_9982, 0 }; static cilist io___91 = { 0, 0, 0, fmt_9981, 0 }; static cilist io___92 = { 0, 0, 0, fmt_9987, 0 }; /* -- Reference BLAS test routine (version 3.4.1) -- */ /* -- Reference BLAS is a software package provided by Univ. of Tennessee, -- */ /* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- */ /* April 2012 */ /* ===================================================================== */ /* .. Parameters .. */ /* .. Local Scalars .. */ /* .. Local Arrays .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. Scalars in Common .. */ /* .. Common blocks .. */ /* .. Data statements .. */ /* .. Executable Statements .. */ /* Read name and unit number for summary output file and open file. */ s_rsle(&io___2); do_lio(&c__9, &c__1, summry, (ftnlen)32); e_rsle(); s_rsle(&io___4); do_lio(&c__3, &c__1, (char *)&nout, (ftnlen)sizeof(integer)); e_rsle(); o__1.oerr = 0; o__1.ounit = nout; o__1.ofnmlen = 32; o__1.ofnm = summry; o__1.orl = 0; o__1.osta = "UNKNOWN"; o__1.oacc = 0; o__1.ofm = 0; o__1.oblnk = 0; f_open(&o__1); infoc_1.noutc = nout; /* Read name and unit number for snapshot output file and open file. */ s_rsle(&io___6); do_lio(&c__9, &c__1, snaps, (ftnlen)32); e_rsle(); s_rsle(&io___8); do_lio(&c__3, &c__1, (char *)&ntra, (ftnlen)sizeof(integer)); e_rsle(); trace = ntra >= 0; if (trace) { o__1.oerr = 0; o__1.ounit = ntra; o__1.ofnmlen = 32; o__1.ofnm = snaps; o__1.orl = 0; o__1.osta = "UNKNOWN"; o__1.oacc = 0; o__1.ofm = 0; o__1.oblnk = 0; f_open(&o__1); } /* Read the flag that directs rewinding of the snapshot file. */ s_rsle(&io___11); do_lio(&c__8, &c__1, (char *)&rewi, (ftnlen)sizeof(logical)); e_rsle(); rewi = rewi && trace; /* Read the flag that directs stopping on any failure. */ s_rsle(&io___13); do_lio(&c__8, &c__1, (char *)&sfatal, (ftnlen)sizeof(logical)); e_rsle(); /* Read the flag that indicates whether error exits are to be tested. */ s_rsle(&io___15); do_lio(&c__8, &c__1, (char *)&tsterr, (ftnlen)sizeof(logical)); e_rsle(); /* Read the threshold value of the test ratio */ s_rsle(&io___17); do_lio(&c__4, &c__1, (char *)&thresh, (ftnlen)sizeof(real)); e_rsle(); /* Read and check the parameter values for the tests. */ /* Values of N */ s_rsle(&io___19); do_lio(&c__3, &c__1, (char *)&nidim, (ftnlen)sizeof(integer)); e_rsle(); if (nidim < 1 || nidim > 9) { io___21.ciunit = nout; s_wsfe(&io___21); do_fio(&c__1, "N", (ftnlen)1); do_fio(&c__1, (char *)&c__9, (ftnlen)sizeof(integer)); e_wsfe(); goto L230; } s_rsle(&io___22); i__1 = nidim; for (i__ = 1; i__ <= i__1; ++i__) { do_lio(&c__3, &c__1, (char *)&idim[i__ - 1], (ftnlen)sizeof(integer)); } e_rsle(); i__1 = nidim; for (i__ = 1; i__ <= i__1; ++i__) { if (idim[i__ - 1] < 0 || idim[i__ - 1] > 65) { io___25.ciunit = nout; s_wsfe(&io___25); do_fio(&c__1, (char *)&c__65, (ftnlen)sizeof(integer)); e_wsfe(); goto L230; } /* L10: */ } /* Values of K */ s_rsle(&io___26); do_lio(&c__3, &c__1, (char *)&nkb, (ftnlen)sizeof(integer)); e_rsle(); if (nkb < 1 || nkb > 7) { io___28.ciunit = nout; s_wsfe(&io___28); do_fio(&c__1, "K", (ftnlen)1); do_fio(&c__1, (char *)&c__7, (ftnlen)sizeof(integer)); e_wsfe(); goto L230; } s_rsle(&io___29); i__1 = nkb; for (i__ = 1; i__ <= i__1; ++i__) { do_lio(&c__3, &c__1, (char *)&kb[i__ - 1], (ftnlen)sizeof(integer)); } e_rsle(); i__1 = nkb; for (i__ = 1; i__ <= i__1; ++i__) { if (kb[i__ - 1] < 0) { io___31.ciunit = nout; s_wsfe(&io___31); e_wsfe(); goto L230; } /* L20: */ } /* Values of INCX and INCY */ s_rsle(&io___32); do_lio(&c__3, &c__1, (char *)&ninc, (ftnlen)sizeof(integer)); e_rsle(); if (ninc < 1 || ninc > 7) { io___34.ciunit = nout; s_wsfe(&io___34); do_fio(&c__1, "INCX AND INCY", (ftnlen)13); do_fio(&c__1, (char *)&c__7, (ftnlen)sizeof(integer)); e_wsfe(); goto L230; } s_rsle(&io___35); i__1 = ninc; for (i__ = 1; i__ <= i__1; ++i__) { do_lio(&c__3, &c__1, (char *)&inc[i__ - 1], (ftnlen)sizeof(integer)); } e_rsle(); i__1 = ninc; for (i__ = 1; i__ <= i__1; ++i__) { if (inc[i__ - 1] == 0 || (i__2 = inc[i__ - 1], abs(i__2)) > 2) { io___37.ciunit = nout; s_wsfe(&io___37); do_fio(&c__1, (char *)&c__2, (ftnlen)sizeof(integer)); e_wsfe(); goto L230; } /* L30: */ } /* Values of ALPHA */ s_rsle(&io___38); do_lio(&c__3, &c__1, (char *)&nalf, (ftnlen)sizeof(integer)); e_rsle(); if (nalf < 1 || nalf > 7) { io___40.ciunit = nout; s_wsfe(&io___40); do_fio(&c__1, "ALPHA", (ftnlen)5); do_fio(&c__1, (char *)&c__7, (ftnlen)sizeof(integer)); e_wsfe(); goto L230; } s_rsle(&io___41); i__1 = nalf; for (i__ = 1; i__ <= i__1; ++i__) { do_lio(&c__6, &c__1, (char *)&alf[i__ - 1], (ftnlen)sizeof(complex)); } e_rsle(); /* Values of BETA */ s_rsle(&io___43); do_lio(&c__3, &c__1, (char *)&nbet, (ftnlen)sizeof(integer)); e_rsle(); if (nbet < 1 || nbet > 7) { io___45.ciunit = nout; s_wsfe(&io___45); do_fio(&c__1, "BETA", (ftnlen)4); do_fio(&c__1, (char *)&c__7, (ftnlen)sizeof(integer)); e_wsfe(); goto L230; } s_rsle(&io___46); i__1 = nbet; for (i__ = 1; i__ <= i__1; ++i__) { do_lio(&c__6, &c__1, (char *)&bet[i__ - 1], (ftnlen)sizeof(complex)); } e_rsle(); /* Report values of parameters. */ io___48.ciunit = nout; s_wsfe(&io___48); e_wsfe(); io___49.ciunit = nout; s_wsfe(&io___49); i__1 = nidim; for (i__ = 1; i__ <= i__1; ++i__) { do_fio(&c__1, (char *)&idim[i__ - 1], (ftnlen)sizeof(integer)); } e_wsfe(); io___50.ciunit = nout; s_wsfe(&io___50); i__1 = nkb; for (i__ = 1; i__ <= i__1; ++i__) { do_fio(&c__1, (char *)&kb[i__ - 1], (ftnlen)sizeof(integer)); } e_wsfe(); io___51.ciunit = nout; s_wsfe(&io___51); i__1 = ninc; for (i__ = 1; i__ <= i__1; ++i__) { do_fio(&c__1, (char *)&inc[i__ - 1], (ftnlen)sizeof(integer)); } e_wsfe(); io___52.ciunit = nout; s_wsfe(&io___52); i__1 = nalf; for (i__ = 1; i__ <= i__1; ++i__) { do_fio(&c__2, (char *)&alf[i__ - 1], (ftnlen)sizeof(real)); } e_wsfe(); io___53.ciunit = nout; s_wsfe(&io___53); i__1 = nbet; for (i__ = 1; i__ <= i__1; ++i__) { do_fio(&c__2, (char *)&bet[i__ - 1], (ftnlen)sizeof(real)); } e_wsfe(); if (! tsterr) { io___54.ciunit = nout; s_wsle(&io___54); e_wsle(); io___55.ciunit = nout; s_wsfe(&io___55); e_wsfe(); } io___56.ciunit = nout; s_wsle(&io___56); e_wsle(); io___57.ciunit = nout; s_wsfe(&io___57); do_fio(&c__1, (char *)&thresh, (ftnlen)sizeof(real)); e_wsfe(); io___58.ciunit = nout; s_wsle(&io___58); e_wsle(); /* Read names of subroutines and flags which indicate */ /* whether they are to be tested. */ for (i__ = 1; i__ <= 17; ++i__) { ltest[i__ - 1] = FALSE_; /* L40: */ } L50: i__1 = s_rsfe(&io___60); if (i__1 != 0) { goto L80; } i__1 = do_fio(&c__1, snamet, (ftnlen)6); if (i__1 != 0) { goto L80; } i__1 = do_fio(&c__1, (char *)<estt, (ftnlen)sizeof(logical)); if (i__1 != 0) { goto L80; } i__1 = e_rsfe(); if (i__1 != 0) { goto L80; } for (i__ = 1; i__ <= 17; ++i__) { if (s_cmp(snamet, snames + (i__ - 1) * 6, (ftnlen)6, (ftnlen)6) == 0) { goto L70; } /* L60: */ } io___63.ciunit = nout; s_wsfe(&io___63); do_fio(&c__1, snamet, (ftnlen)6); e_wsfe(); s_stop("", (ftnlen)0); L70: ltest[i__ - 1] = ltestt; goto L50; L80: cl__1.cerr = 0; cl__1.cunit = 5; cl__1.csta = 0; f_clos(&cl__1); /* Compute EPS (the machine precision). */ eps = s_epsilon_(&c_b122); io___65.ciunit = nout; s_wsfe(&io___65); do_fio(&c__1, (char *)&eps, (ftnlen)sizeof(real)); e_wsfe(); /* Check the reliability of CMVCH using exact data. */ n = 32; i__1 = n; for (j = 1; j <= i__1; ++j) { i__2 = n; for (i__ = 1; i__ <= i__2; ++i__) { i__3 = i__ + j * 65 - 66; /* Computing MAX */ i__5 = i__ - j + 1; i__4 = max(i__5,0); a[i__3].r = (real) i__4, a[i__3].i = 0.f; /* L110: */ } i__2 = j - 1; x[i__2].r = (real) j, x[i__2].i = 0.f; i__2 = j - 1; y[i__2].r = 0.f, y[i__2].i = 0.f; /* L120: */ } i__1 = n; for (j = 1; j <= i__1; ++j) { i__2 = j - 1; i__3 = j * ((j + 1) * j) / 2 - (j + 1) * j * (j - 1) / 3; yy[i__2].r = (real) i__3, yy[i__2].i = 0.f; /* L130: */ } /* YY holds the exact result. On exit from CMVCH YT holds */ /* the result computed by CMVCH. */ *(unsigned char *)trans = 'N'; cmvch_(trans, &n, &n, &c_b2, a, &c__65, x, &c__1, &c_b1, y, &c__1, yt, g, yy, &eps, &err, &fatal, &nout, &c_true, (ftnlen)1); same = lce_(yy, yt, &n); if (! same || err != 0.f) { io___78.ciunit = nout; s_wsfe(&io___78); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, (char *)&same, (ftnlen)sizeof(logical)); do_fio(&c__1, (char *)&err, (ftnlen)sizeof(real)); e_wsfe(); s_stop("", (ftnlen)0); } *(unsigned char *)trans = 'T'; cmvch_(trans, &n, &n, &c_b2, a, &c__65, x, &c_n1, &c_b1, y, &c_n1, yt, g, yy, &eps, &err, &fatal, &nout, &c_true, (ftnlen)1); same = lce_(yy, yt, &n); if (! same || err != 0.f) { io___79.ciunit = nout; s_wsfe(&io___79); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, (char *)&same, (ftnlen)sizeof(logical)); do_fio(&c__1, (char *)&err, (ftnlen)sizeof(real)); e_wsfe(); s_stop("", (ftnlen)0); } /* Test each subroutine in turn. */ for (isnum = 1; isnum <= 17; ++isnum) { io___81.ciunit = nout; s_wsle(&io___81); e_wsle(); if (! ltest[isnum - 1]) { /* Subprogram is not to be tested. */ io___82.ciunit = nout; s_wsfe(&io___82); do_fio(&c__1, snames + (isnum - 1) * 6, (ftnlen)6); e_wsfe(); } else { s_copy(srnamc_1.srnamt, snames + (isnum - 1) * 6, (ftnlen)6, ( ftnlen)6); /* Test error exits. */ if (tsterr) { cchke_(&isnum, snames + (isnum - 1) * 6, &nout, (ftnlen)6); io___83.ciunit = nout; s_wsle(&io___83); e_wsle(); } /* Test computations. */ infoc_1.infot = 0; infoc_1.ok = TRUE_; fatal = FALSE_; switch (isnum) { case 1: goto L140; case 2: goto L140; case 3: goto L150; case 4: goto L150; case 5: goto L150; case 6: goto L160; case 7: goto L160; case 8: goto L160; case 9: goto L160; case 10: goto L160; case 11: goto L160; case 12: goto L170; case 13: goto L170; case 14: goto L180; case 15: goto L180; case 16: goto L190; case 17: goto L190; } /* Test CGEMV, 01, and CGBMV, 02. */ L140: cchk1_(snames + (isnum - 1) * 6, &eps, &thresh, &nout, &ntra, & trace, &rewi, &fatal, &nidim, idim, &nkb, kb, &nalf, alf, &nbet, bet, &ninc, inc, &c__65, &c__2, a, aa, as, x, xx, xs, y, yy, ys, yt, g, (ftnlen)6); goto L200; /* Test CHEMV, 03, CHBMV, 04, and CHPMV, 05. */ L150: cchk2_(snames + (isnum - 1) * 6, &eps, &thresh, &nout, &ntra, & trace, &rewi, &fatal, &nidim, idim, &nkb, kb, &nalf, alf, &nbet, bet, &ninc, inc, &c__65, &c__2, a, aa, as, x, xx, xs, y, yy, ys, yt, g, (ftnlen)6); goto L200; /* Test CTRMV, 06, CTBMV, 07, CTPMV, 08, */ /* CTRSV, 09, CTBSV, 10, and CTPSV, 11. */ L160: cchk3_(snames + (isnum - 1) * 6, &eps, &thresh, &nout, &ntra, & trace, &rewi, &fatal, &nidim, idim, &nkb, kb, &ninc, inc, &c__65, &c__2, a, aa, as, y, yy, ys, yt, g, z__, (ftnlen) 6); goto L200; /* Test CGERC, 12, CGERU, 13. */ L170: cchk4_(snames + (isnum - 1) * 6, &eps, &thresh, &nout, &ntra, & trace, &rewi, &fatal, &nidim, idim, &nalf, alf, &ninc, inc, &c__65, &c__2, a, aa, as, x, xx, xs, y, yy, ys, yt, g, z__, (ftnlen)6); goto L200; /* Test CHER, 14, and CHPR, 15. */ L180: cchk5_(snames + (isnum - 1) * 6, &eps, &thresh, &nout, &ntra, & trace, &rewi, &fatal, &nidim, idim, &nalf, alf, &ninc, inc, &c__65, &c__2, a, aa, as, x, xx, xs, y, yy, ys, yt, g, z__, (ftnlen)6); goto L200; /* Test CHER2, 16, and CHPR2, 17. */ L190: cchk6_(snames + (isnum - 1) * 6, &eps, &thresh, &nout, &ntra, & trace, &rewi, &fatal, &nidim, idim, &nalf, alf, &ninc, inc, &c__65, &c__2, a, aa, as, x, xx, xs, y, yy, ys, yt, g, z__, (ftnlen)6); L200: if (fatal && sfatal) { goto L220; } } /* L210: */ } io___90.ciunit = nout; s_wsfe(&io___90); e_wsfe(); goto L240; L220: io___91.ciunit = nout; s_wsfe(&io___91); e_wsfe(); goto L240; L230: io___92.ciunit = nout; s_wsfe(&io___92); e_wsfe(); L240: if (trace) { cl__1.cerr = 0; cl__1.cunit = ntra; cl__1.csta = 0; f_clos(&cl__1); } cl__1.cerr = 0; cl__1.cunit = nout; cl__1.csta = 0; f_clos(&cl__1); s_stop("", (ftnlen)0); /* End of CBLAT2. */ return 0; } /* main */ /* Subroutine */ int cchk1_(char *sname, real *eps, real *thresh, integer * nout, integer *ntra, logical *trace, logical *rewi, logical *fatal, integer *nidim, integer *idim, integer *nkb, integer *kb, integer * nalf, complex *alf, integer *nbet, complex *bet, integer *ninc, integer *inc, integer *nmax, integer *incmax, complex *a, complex *aa, complex *as, complex *x, complex *xx, complex *xs, complex *y, complex *yy, complex *ys, complex *yt, real *g, ftnlen sname_len) { /* Initialized data */ static char ich[3] = "NTC"; /* Format strings */ static char fmt_9994[] = "(1x,i6,\002: \002,a6,\002('\002,a1,\002',\002," "2(i3,\002,\002),\002(\002,f4.1,\002,\002,f4.1,\002), A,\002,i3" ",\002, X,\002,i2,\002,(\002,f4.1,\002,\002,f4.1,\002), Y,\002,i2," "\002) .\002)"; static char fmt_9995[] = "(1x,i6,\002: \002,a6,\002('\002,a1,\002',\002," "4(i3,\002,\002),\002(\002,f4.1,\002,\002,f4.1,\002), A,\002,i3" ",\002, X,\002,i2,\002,(\002,f4.1,\002,\002,f4.1,\002), Y,\002,i2," "\002) .\002)"; static char fmt_9993[] = "(\002 ******* FATAL ERROR - ERROR-EXIT TAKEN O" "N VALID CALL *\002,\002******\002)"; static char fmt_9998[] = "(\002 ******* FATAL ERROR - PARAMETER NUMBER" " \002,i2,\002 WAS CH\002,\002ANGED INCORRECTLY *******\002)"; static char fmt_9999[] = "(\002 \002,a6,\002 PASSED THE COMPUTATIONAL TE" "STS (\002,i6,\002 CALL\002,\002S)\002)"; static char fmt_9997[] = "(\002 \002,a6,\002 COMPLETED THE COMPUTATIONAL" " TESTS (\002,i6,\002 C\002,\002ALLS)\002,/\002 ******* BUT WITH " "MAXIMUM TEST RATIO\002,f8.2,\002 - SUSPECT *******\002)"; static char fmt_9996[] = "(\002 ******* \002,a6,\002 FAILED ON CALL NUMB" "ER:\002)"; /* System generated locals */ integer a_dim1, a_offset, i__1, i__2, i__3, i__4, i__5, i__6, i__7, i__8, i__9; alist al__1; /* Builtin functions */ integer s_wsfe(cilist *), do_fio(integer *, char *, ftnlen), e_wsfe(void), f_rew(alist *); /* Local variables */ integer i__, m, n, ia, ib, ic, nc, nd, im, in, kl, ml, nk, nl, ku, ix, iy, ms, lx, ly, ns, laa, lda; extern logical lce_(complex *, complex *, integer *); complex als, bls; real err; integer iku, kls, kus; complex beta; integer ldas; logical same; integer incx, incy; logical full, tran, null; extern /* Subroutine */ int cmake_(char *, char *, char *, integer *, integer *, complex *, integer *, complex *, integer *, integer *, integer *, logical *, complex *, ftnlen, ftnlen, ftnlen); complex alpha; logical isame[13]; extern /* Subroutine */ int cgbmv_(char *, integer *, integer *, integer * , integer *, complex *, complex *, integer *, complex *, integer * , complex *, complex *, integer *, ftnlen), cgemv_(char *, integer *, integer *, complex *, complex *, integer *, complex *, integer *, complex *, complex *, integer *, ftnlen), cmvch_(char * , integer *, integer *, complex *, complex *, integer *, complex * , integer *, complex *, complex *, integer *, complex *, real *, complex *, real *, real *, logical *, integer *, logical *, ftnlen); integer nargs; logical reset; integer incxs, incys; char trans[1]; logical banded; extern logical lceres_(char *, char *, integer *, integer *, complex *, complex *, integer *, ftnlen, ftnlen); real errmax; complex transl; char transs[1]; /* Fortran I/O blocks */ static cilist io___139 = { 0, 0, 0, fmt_9994, 0 }; static cilist io___140 = { 0, 0, 0, fmt_9995, 0 }; static cilist io___141 = { 0, 0, 0, fmt_9993, 0 }; static cilist io___144 = { 0, 0, 0, fmt_9998, 0 }; static cilist io___146 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___147 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___148 = { 0, 0, 0, fmt_9996, 0 }; static cilist io___149 = { 0, 0, 0, fmt_9994, 0 }; static cilist io___150 = { 0, 0, 0, fmt_9995, 0 }; /* Tests CGEMV and CGBMV. */ /* Auxiliary routine for test program for Level 2 Blas. */ /* -- Written on 10-August-1987. */ /* Richard Hanson, Sandia National Labs. */ /* Jeremy Du Croz, NAG Central Office. */ /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Scalars .. */ /* .. Local Arrays .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. Scalars in Common .. */ /* .. Common blocks .. */ /* .. Data statements .. */ /* Parameter adjustments */ --idim; --kb; --alf; --bet; --inc; --g; --yt; --y; --x; --as; --aa; a_dim1 = *nmax; a_offset = 1 + a_dim1; a -= a_offset; --ys; --yy; --xs; --xx; /* Function Body */ /* .. Executable Statements .. */ full = *(unsigned char *)&sname[2] == 'E'; banded = *(unsigned char *)&sname[2] == 'B'; /* Define the number of arguments. */ if (full) { nargs = 11; } else if (banded) { nargs = 13; } nc = 0; reset = TRUE_; errmax = 0.f; i__1 = *nidim; for (in = 1; in <= i__1; ++in) { n = idim[in]; nd = n / 2 + 1; for (im = 1; im <= 2; ++im) { if (im == 1) { /* Computing MAX */ i__2 = n - nd; m = max(i__2,0); } if (im == 2) { /* Computing MIN */ i__2 = n + nd; m = min(i__2,*nmax); } if (banded) { nk = *nkb; } else { nk = 1; } i__2 = nk; for (iku = 1; iku <= i__2; ++iku) { if (banded) { ku = kb[iku]; /* Computing MAX */ i__3 = ku - 1; kl = max(i__3,0); } else { ku = n - 1; kl = m - 1; } /* Set LDA to 1 more than minimum value if room. */ if (banded) { lda = kl + ku + 1; } else { lda = m; } if (lda < *nmax) { ++lda; } /* Skip tests if not enough room. */ if (lda > *nmax) { goto L100; } laa = lda * n; null = n <= 0 || m <= 0; /* Generate the matrix A. */ transl.r = 0.f, transl.i = 0.f; cmake_(sname + 1, " ", " ", &m, &n, &a[a_offset], nmax, &aa[1] , &lda, &kl, &ku, &reset, &transl, (ftnlen)2, (ftnlen) 1, (ftnlen)1); for (ic = 1; ic <= 3; ++ic) { *(unsigned char *)trans = *(unsigned char *)&ich[ic - 1]; tran = *(unsigned char *)trans == 'T' || *(unsigned char * )trans == 'C'; if (tran) { ml = n; nl = m; } else { ml = m; nl = n; } i__3 = *ninc; for (ix = 1; ix <= i__3; ++ix) { incx = inc[ix]; lx = abs(incx) * nl; /* Generate the vector X. */ transl.r = .5f, transl.i = 0.f; i__4 = abs(incx); i__5 = nl - 1; cmake_("GE", " ", " ", &c__1, &nl, &x[1], &c__1, &xx[ 1], &i__4, &c__0, &i__5, &reset, &transl, ( ftnlen)2, (ftnlen)1, (ftnlen)1); if (nl > 1) { i__4 = nl / 2; x[i__4].r = 0.f, x[i__4].i = 0.f; i__4 = abs(incx) * (nl / 2 - 1) + 1; xx[i__4].r = 0.f, xx[i__4].i = 0.f; } i__4 = *ninc; for (iy = 1; iy <= i__4; ++iy) { incy = inc[iy]; ly = abs(incy) * ml; i__5 = *nalf; for (ia = 1; ia <= i__5; ++ia) { i__6 = ia; alpha.r = alf[i__6].r, alpha.i = alf[i__6].i; i__6 = *nbet; for (ib = 1; ib <= i__6; ++ib) { i__7 = ib; beta.r = bet[i__7].r, beta.i = bet[i__7] .i; /* Generate the vector Y. */ transl.r = 0.f, transl.i = 0.f; i__7 = abs(incy); i__8 = ml - 1; cmake_("GE", " ", " ", &c__1, &ml, &y[1], &c__1, &yy[1], &i__7, &c__0, & i__8, &reset, &transl, (ftnlen)2, (ftnlen)1, (ftnlen)1); ++nc; /* Save every datum before calling the */ /* subroutine. */ *(unsigned char *)transs = *(unsigned char *)trans; ms = m; ns = n; kls = kl; kus = ku; als.r = alpha.r, als.i = alpha.i; i__7 = laa; for (i__ = 1; i__ <= i__7; ++i__) { i__8 = i__; i__9 = i__; as[i__8].r = aa[i__9].r, as[i__8].i = aa[i__9].i; /* L10: */ } ldas = lda; i__7 = lx; for (i__ = 1; i__ <= i__7; ++i__) { i__8 = i__; i__9 = i__; xs[i__8].r = xx[i__9].r, xs[i__8].i = xx[i__9].i; /* L20: */ } incxs = incx; bls.r = beta.r, bls.i = beta.i; i__7 = ly; for (i__ = 1; i__ <= i__7; ++i__) { i__8 = i__; i__9 = i__; ys[i__8].r = yy[i__9].r, ys[i__8].i = yy[i__9].i; /* L30: */ } incys = incy; /* Call the subroutine. */ if (full) { if (*trace) { io___139.ciunit = *ntra; s_wsfe(&io___139); do_fio(&c__1, (char *)&nc, ( ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, (char *)&m, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&n, (ftnlen) sizeof(integer)); do_fio(&c__2, (char *)&alpha, ( ftnlen)sizeof(real)); do_fio(&c__1, (char *)&lda, ( ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&incx, ( ftnlen)sizeof(integer)); do_fio(&c__2, (char *)&beta, ( ftnlen)sizeof(real)); do_fio(&c__1, (char *)&incy, ( ftnlen)sizeof(integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } cgemv_(trans, &m, &n, &alpha, &aa[1], &lda, &xx[1], &incx, &beta, & yy[1], &incy, (ftnlen)1); } else if (banded) { if (*trace) { io___140.ciunit = *ntra; s_wsfe(&io___140); do_fio(&c__1, (char *)&nc, ( ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, (char *)&m, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&n, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&kl, ( ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&ku, ( ftnlen)sizeof(integer)); do_fio(&c__2, (char *)&alpha, ( ftnlen)sizeof(real)); do_fio(&c__1, (char *)&lda, ( ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&incx, ( ftnlen)sizeof(integer)); do_fio(&c__2, (char *)&beta, ( ftnlen)sizeof(real)); do_fio(&c__1, (char *)&incy, ( ftnlen)sizeof(integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } cgbmv_(trans, &m, &n, &kl, &ku, & alpha, &aa[1], &lda, &xx[1], & incx, &beta, &yy[1], &incy, ( ftnlen)1); } /* Check if error-exit was taken incorrectly. */ if (! infoc_1.ok) { io___141.ciunit = *nout; s_wsfe(&io___141); e_wsfe(); *fatal = TRUE_; goto L130; } /* See what data changed inside subroutines. */ isame[0] = *(unsigned char *)trans == *( unsigned char *)transs; isame[1] = ms == m; isame[2] = ns == n; if (full) { isame[3] = als.r == alpha.r && als.i == alpha.i; isame[4] = lce_(&as[1], &aa[1], &laa); isame[5] = ldas == lda; isame[6] = lce_(&xs[1], &xx[1], &lx); isame[7] = incxs == incx; isame[8] = bls.r == beta.r && bls.i == beta.i; if (null) { isame[9] = lce_(&ys[1], &yy[1], & ly); } else { i__7 = abs(incy); isame[9] = lceres_("GE", " ", & c__1, &ml, &ys[1], &yy[1], &i__7, (ftnlen)2, ( ftnlen)1); } isame[10] = incys == incy; } else if (banded) { isame[3] = kls == kl; isame[4] = kus == ku; isame[5] = als.r == alpha.r && als.i == alpha.i; isame[6] = lce_(&as[1], &aa[1], &laa); isame[7] = ldas == lda; isame[8] = lce_(&xs[1], &xx[1], &lx); isame[9] = incxs == incx; isame[10] = bls.r == beta.r && bls.i == beta.i; if (null) { isame[11] = lce_(&ys[1], &yy[1], & ly); } else { i__7 = abs(incy); isame[11] = lceres_("GE", " ", & c__1, &ml, &ys[1], &yy[1], &i__7, (ftnlen)2, ( ftnlen)1); } isame[12] = incys == incy; } /* If data was incorrectly changed, report */ /* and return. */ same = TRUE_; i__7 = nargs; for (i__ = 1; i__ <= i__7; ++i__) { same = same && isame[i__ - 1]; if (! isame[i__ - 1]) { io___144.ciunit = *nout; s_wsfe(&io___144); do_fio(&c__1, (char *)&i__, ( ftnlen)sizeof(integer)); e_wsfe(); } /* L40: */ } if (! same) { *fatal = TRUE_; goto L130; } if (! null) { /* Check the result. */ cmvch_(trans, &m, &n, &alpha, &a[ a_offset], nmax, &x[1], &incx, &beta, &y[1], &incy, &yt[1], &g[1], &yy[1], eps, &err, fatal, nout, &c_true, (ftnlen) 1); errmax = max(errmax,err); /* If got really bad answer, report and */ /* return. */ if (*fatal) { goto L130; } } else { /* Avoid repeating tests with M.le.0 or */ /* N.le.0. */ goto L110; } /* L50: */ } /* L60: */ } /* L70: */ } /* L80: */ } /* L90: */ } L100: ; } L110: ; } /* L120: */ } /* Report result. */ if (errmax < *thresh) { io___146.ciunit = *nout; s_wsfe(&io___146); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); e_wsfe(); } else { io___147.ciunit = *nout; s_wsfe(&io___147); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&errmax, (ftnlen)sizeof(real)); e_wsfe(); } goto L140; L130: io___148.ciunit = *nout; s_wsfe(&io___148); do_fio(&c__1, sname, (ftnlen)6); e_wsfe(); if (full) { io___149.ciunit = *nout; s_wsfe(&io___149); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, (char *)&m, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)); do_fio(&c__2, (char *)&alpha, (ftnlen)sizeof(real)); do_fio(&c__1, (char *)&lda, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&incx, (ftnlen)sizeof(integer)); do_fio(&c__2, (char *)&beta, (ftnlen)sizeof(real)); do_fio(&c__1, (char *)&incy, (ftnlen)sizeof(integer)); e_wsfe(); } else if (banded) { io___150.ciunit = *nout; s_wsfe(&io___150); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, (char *)&m, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&kl, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&ku, (ftnlen)sizeof(integer)); do_fio(&c__2, (char *)&alpha, (ftnlen)sizeof(real)); do_fio(&c__1, (char *)&lda, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&incx, (ftnlen)sizeof(integer)); do_fio(&c__2, (char *)&beta, (ftnlen)sizeof(real)); do_fio(&c__1, (char *)&incy, (ftnlen)sizeof(integer)); e_wsfe(); } L140: return 0; /* End of CCHK1. */ } /* cchk1_ */ /* Subroutine */ int cchk2_(char *sname, real *eps, real *thresh, integer * nout, integer *ntra, logical *trace, logical *rewi, logical *fatal, integer *nidim, integer *idim, integer *nkb, integer *kb, integer * nalf, complex *alf, integer *nbet, complex *bet, integer *ninc, integer *inc, integer *nmax, integer *incmax, complex *a, complex *aa, complex *as, complex *x, complex *xx, complex *xs, complex *y, complex *yy, complex *ys, complex *yt, real *g, ftnlen sname_len) { /* Initialized data */ static char ich[2] = "UL"; /* Format strings */ static char fmt_9993[] = "(1x,i6,\002: \002,a6,\002('\002,a1,\002',\002," "i3,\002,(\002,f4.1,\002,\002,f4.1,\002), A,\002,i3,\002, X,\002," "i2,\002,(\002,f4.1,\002,\002,f4.1,\002), \002,\002Y,\002,i2,\002" ") .\002)"; static char fmt_9994[] = "(1x,i6,\002: \002,a6,\002('\002,a1,\002',\002," "2(i3,\002,\002),\002(\002,f4.1,\002,\002,f4.1,\002), A,\002,i3" ",\002, X,\002,i2,\002,(\002,f4.1,\002,\002,f4.1,\002), Y,\002,i2," "\002) .\002)"; static char fmt_9995[] = "(1x,i6,\002: \002,a6,\002('\002,a1,\002',\002," "i3,\002,(\002,f4.1,\002,\002,f4.1,\002), AP, X,\002,i2,\002,(" "\002,f4.1,\002,\002,f4.1,\002), Y,\002,i2,\002) " ".\002)"; static char fmt_9992[] = "(\002 ******* FATAL ERROR - ERROR-EXIT TAKEN O" "N VALID CALL *\002,\002******\002)"; static char fmt_9998[] = "(\002 ******* FATAL ERROR - PARAMETER NUMBER" " \002,i2,\002 WAS CH\002,\002ANGED INCORRECTLY *******\002)"; static char fmt_9999[] = "(\002 \002,a6,\002 PASSED THE COMPUTATIONAL TE" "STS (\002,i6,\002 CALL\002,\002S)\002)"; static char fmt_9997[] = "(\002 \002,a6,\002 COMPLETED THE COMPUTATIONAL" " TESTS (\002,i6,\002 C\002,\002ALLS)\002,/\002 ******* BUT WITH " "MAXIMUM TEST RATIO\002,f8.2,\002 - SUSPECT *******\002)"; static char fmt_9996[] = "(\002 ******* \002,a6,\002 FAILED ON CALL NUMB" "ER:\002)"; /* System generated locals */ integer a_dim1, a_offset, i__1, i__2, i__3, i__4, i__5, i__6, i__7, i__8, i__9; alist al__1; /* Builtin functions */ integer s_wsfe(cilist *), do_fio(integer *, char *, ftnlen), e_wsfe(void), f_rew(alist *); /* Local variables */ integer i__, k, n, ia, ib, ic, nc, ik, in, nk, ks, ix, iy, ns, lx, ly, laa, lda; extern logical lce_(complex *, complex *, integer *); complex als, bls; real err; complex beta; integer ldas; logical same; integer incx, incy; logical full, null; char uplo[1]; extern /* Subroutine */ int cmake_(char *, char *, char *, integer *, integer *, complex *, integer *, complex *, integer *, integer *, integer *, logical *, complex *, ftnlen, ftnlen, ftnlen); complex alpha; logical isame[13]; extern /* Subroutine */ int chbmv_(char *, integer *, integer *, complex * , complex *, integer *, complex *, integer *, complex *, complex * , integer *, ftnlen), chemv_(char *, integer *, complex *, complex *, integer *, complex *, integer *, complex *, complex *, integer *, ftnlen), cmvch_(char *, integer *, integer *, complex * , complex *, integer *, complex *, integer *, complex *, complex * , integer *, complex *, real *, complex *, real *, real *, logical *, integer *, logical *, ftnlen); integer nargs; extern /* Subroutine */ int chpmv_(char *, integer *, complex *, complex * , complex *, integer *, complex *, complex *, integer *, ftnlen); logical reset; integer incxs, incys; char uplos[1]; logical banded, packed; extern logical lceres_(char *, char *, integer *, integer *, complex *, complex *, integer *, ftnlen, ftnlen); real errmax; complex transl; /* Fortran I/O blocks */ static cilist io___189 = { 0, 0, 0, fmt_9993, 0 }; static cilist io___190 = { 0, 0, 0, fmt_9994, 0 }; static cilist io___191 = { 0, 0, 0, fmt_9995, 0 }; static cilist io___192 = { 0, 0, 0, fmt_9992, 0 }; static cilist io___195 = { 0, 0, 0, fmt_9998, 0 }; static cilist io___197 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___198 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___199 = { 0, 0, 0, fmt_9996, 0 }; static cilist io___200 = { 0, 0, 0, fmt_9993, 0 }; static cilist io___201 = { 0, 0, 0, fmt_9994, 0 }; static cilist io___202 = { 0, 0, 0, fmt_9995, 0 }; /* Tests CHEMV, CHBMV and CHPMV. */ /* Auxiliary routine for test program for Level 2 Blas. */ /* -- Written on 10-August-1987. */ /* Richard Hanson, Sandia National Labs. */ /* Jeremy Du Croz, NAG Central Office. */ /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Scalars .. */ /* .. Local Arrays .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. Scalars in Common .. */ /* .. Common blocks .. */ /* .. Data statements .. */ /* Parameter adjustments */ --idim; --kb; --alf; --bet; --inc; --g; --yt; --y; --x; --as; --aa; a_dim1 = *nmax; a_offset = 1 + a_dim1; a -= a_offset; --ys; --yy; --xs; --xx; /* Function Body */ /* .. Executable Statements .. */ full = *(unsigned char *)&sname[2] == 'E'; banded = *(unsigned char *)&sname[2] == 'B'; packed = *(unsigned char *)&sname[2] == 'P'; /* Define the number of arguments. */ if (full) { nargs = 10; } else if (banded) { nargs = 11; } else if (packed) { nargs = 9; } nc = 0; reset = TRUE_; errmax = 0.f; i__1 = *nidim; for (in = 1; in <= i__1; ++in) { n = idim[in]; if (banded) { nk = *nkb; } else { nk = 1; } i__2 = nk; for (ik = 1; ik <= i__2; ++ik) { if (banded) { k = kb[ik]; } else { k = n - 1; } /* Set LDA to 1 more than minimum value if room. */ if (banded) { lda = k + 1; } else { lda = n; } if (lda < *nmax) { ++lda; } /* Skip tests if not enough room. */ if (lda > *nmax) { goto L100; } if (packed) { laa = n * (n + 1) / 2; } else { laa = lda * n; } null = n <= 0; for (ic = 1; ic <= 2; ++ic) { *(unsigned char *)uplo = *(unsigned char *)&ich[ic - 1]; /* Generate the matrix A. */ transl.r = 0.f, transl.i = 0.f; cmake_(sname + 1, uplo, " ", &n, &n, &a[a_offset], nmax, &aa[ 1], &lda, &k, &k, &reset, &transl, (ftnlen)2, (ftnlen) 1, (ftnlen)1); i__3 = *ninc; for (ix = 1; ix <= i__3; ++ix) { incx = inc[ix]; lx = abs(incx) * n; /* Generate the vector X. */ transl.r = .5f, transl.i = 0.f; i__4 = abs(incx); i__5 = n - 1; cmake_("GE", " ", " ", &c__1, &n, &x[1], &c__1, &xx[1], & i__4, &c__0, &i__5, &reset, &transl, (ftnlen)2, ( ftnlen)1, (ftnlen)1); if (n > 1) { i__4 = n / 2; x[i__4].r = 0.f, x[i__4].i = 0.f; i__4 = abs(incx) * (n / 2 - 1) + 1; xx[i__4].r = 0.f, xx[i__4].i = 0.f; } i__4 = *ninc; for (iy = 1; iy <= i__4; ++iy) { incy = inc[iy]; ly = abs(incy) * n; i__5 = *nalf; for (ia = 1; ia <= i__5; ++ia) { i__6 = ia; alpha.r = alf[i__6].r, alpha.i = alf[i__6].i; i__6 = *nbet; for (ib = 1; ib <= i__6; ++ib) { i__7 = ib; beta.r = bet[i__7].r, beta.i = bet[i__7].i; /* Generate the vector Y. */ transl.r = 0.f, transl.i = 0.f; i__7 = abs(incy); i__8 = n - 1; cmake_("GE", " ", " ", &c__1, &n, &y[1], & c__1, &yy[1], &i__7, &c__0, &i__8, & reset, &transl, (ftnlen)2, (ftnlen)1, (ftnlen)1); ++nc; /* Save every datum before calling the */ /* subroutine. */ *(unsigned char *)uplos = *(unsigned char *) uplo; ns = n; ks = k; als.r = alpha.r, als.i = alpha.i; i__7 = laa; for (i__ = 1; i__ <= i__7; ++i__) { i__8 = i__; i__9 = i__; as[i__8].r = aa[i__9].r, as[i__8].i = aa[ i__9].i; /* L10: */ } ldas = lda; i__7 = lx; for (i__ = 1; i__ <= i__7; ++i__) { i__8 = i__; i__9 = i__; xs[i__8].r = xx[i__9].r, xs[i__8].i = xx[ i__9].i; /* L20: */ } incxs = incx; bls.r = beta.r, bls.i = beta.i; i__7 = ly; for (i__ = 1; i__ <= i__7; ++i__) { i__8 = i__; i__9 = i__; ys[i__8].r = yy[i__9].r, ys[i__8].i = yy[ i__9].i; /* L30: */ } incys = incy; /* Call the subroutine. */ if (full) { if (*trace) { io___189.ciunit = *ntra; s_wsfe(&io___189); do_fio(&c__1, (char *)&nc, (ftnlen) sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen) sizeof(integer)); do_fio(&c__2, (char *)&alpha, (ftnlen) sizeof(real)); do_fio(&c__1, (char *)&lda, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&incx, (ftnlen) sizeof(integer)); do_fio(&c__2, (char *)&beta, (ftnlen) sizeof(real)); do_fio(&c__1, (char *)&incy, (ftnlen) sizeof(integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } chemv_(uplo, &n, &alpha, &aa[1], &lda, & xx[1], &incx, &beta, &yy[1], & incy, (ftnlen)1); } else if (banded) { if (*trace) { io___190.ciunit = *ntra; s_wsfe(&io___190); do_fio(&c__1, (char *)&nc, (ftnlen) sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&k, (ftnlen) sizeof(integer)); do_fio(&c__2, (char *)&alpha, (ftnlen) sizeof(real)); do_fio(&c__1, (char *)&lda, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&incx, (ftnlen) sizeof(integer)); do_fio(&c__2, (char *)&beta, (ftnlen) sizeof(real)); do_fio(&c__1, (char *)&incy, (ftnlen) sizeof(integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } chbmv_(uplo, &n, &k, &alpha, &aa[1], &lda, &xx[1], &incx, &beta, &yy[1], & incy, (ftnlen)1); } else if (packed) { if (*trace) { io___191.ciunit = *ntra; s_wsfe(&io___191); do_fio(&c__1, (char *)&nc, (ftnlen) sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen) sizeof(integer)); do_fio(&c__2, (char *)&alpha, (ftnlen) sizeof(real)); do_fio(&c__1, (char *)&incx, (ftnlen) sizeof(integer)); do_fio(&c__2, (char *)&beta, (ftnlen) sizeof(real)); do_fio(&c__1, (char *)&incy, (ftnlen) sizeof(integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } chpmv_(uplo, &n, &alpha, &aa[1], &xx[1], & incx, &beta, &yy[1], &incy, ( ftnlen)1); } /* Check if error-exit was taken incorrectly. */ if (! infoc_1.ok) { io___192.ciunit = *nout; s_wsfe(&io___192); e_wsfe(); *fatal = TRUE_; goto L120; } /* See what data changed inside subroutines. */ isame[0] = *(unsigned char *)uplo == *( unsigned char *)uplos; isame[1] = ns == n; if (full) { isame[2] = als.r == alpha.r && als.i == alpha.i; isame[3] = lce_(&as[1], &aa[1], &laa); isame[4] = ldas == lda; isame[5] = lce_(&xs[1], &xx[1], &lx); isame[6] = incxs == incx; isame[7] = bls.r == beta.r && bls.i == beta.i; if (null) { isame[8] = lce_(&ys[1], &yy[1], &ly); } else { i__7 = abs(incy); isame[8] = lceres_("GE", " ", &c__1, & n, &ys[1], &yy[1], &i__7, ( ftnlen)2, (ftnlen)1); } isame[9] = incys == incy; } else if (banded) { isame[2] = ks == k; isame[3] = als.r == alpha.r && als.i == alpha.i; isame[4] = lce_(&as[1], &aa[1], &laa); isame[5] = ldas == lda; isame[6] = lce_(&xs[1], &xx[1], &lx); isame[7] = incxs == incx; isame[8] = bls.r == beta.r && bls.i == beta.i; if (null) { isame[9] = lce_(&ys[1], &yy[1], &ly); } else { i__7 = abs(incy); isame[9] = lceres_("GE", " ", &c__1, & n, &ys[1], &yy[1], &i__7, ( ftnlen)2, (ftnlen)1); } isame[10] = incys == incy; } else if (packed) { isame[2] = als.r == alpha.r && als.i == alpha.i; isame[3] = lce_(&as[1], &aa[1], &laa); isame[4] = lce_(&xs[1], &xx[1], &lx); isame[5] = incxs == incx; isame[6] = bls.r == beta.r && bls.i == beta.i; if (null) { isame[7] = lce_(&ys[1], &yy[1], &ly); } else { i__7 = abs(incy); isame[7] = lceres_("GE", " ", &c__1, & n, &ys[1], &yy[1], &i__7, ( ftnlen)2, (ftnlen)1); } isame[8] = incys == incy; } /* If data was incorrectly changed, report and */ /* return. */ same = TRUE_; i__7 = nargs; for (i__ = 1; i__ <= i__7; ++i__) { same = same && isame[i__ - 1]; if (! isame[i__ - 1]) { io___195.ciunit = *nout; s_wsfe(&io___195); do_fio(&c__1, (char *)&i__, (ftnlen) sizeof(integer)); e_wsfe(); } /* L40: */ } if (! same) { *fatal = TRUE_; goto L120; } if (! null) { /* Check the result. */ cmvch_("N", &n, &n, &alpha, &a[a_offset], nmax, &x[1], &incx, &beta, &y[1], &incy, &yt[1], &g[1], &yy[1], eps, &err, fatal, nout, &c_true, ( ftnlen)1); errmax = max(errmax,err); /* If got really bad answer, report and */ /* return. */ if (*fatal) { goto L120; } } else { /* Avoid repeating tests with N.le.0 */ goto L110; } /* L50: */ } /* L60: */ } /* L70: */ } /* L80: */ } /* L90: */ } L100: ; } L110: ; } /* Report result. */ if (errmax < *thresh) { io___197.ciunit = *nout; s_wsfe(&io___197); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); e_wsfe(); } else { io___198.ciunit = *nout; s_wsfe(&io___198); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&errmax, (ftnlen)sizeof(real)); e_wsfe(); } goto L130; L120: io___199.ciunit = *nout; s_wsfe(&io___199); do_fio(&c__1, sname, (ftnlen)6); e_wsfe(); if (full) { io___200.ciunit = *nout; s_wsfe(&io___200); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)); do_fio(&c__2, (char *)&alpha, (ftnlen)sizeof(real)); do_fio(&c__1, (char *)&lda, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&incx, (ftnlen)sizeof(integer)); do_fio(&c__2, (char *)&beta, (ftnlen)sizeof(real)); do_fio(&c__1, (char *)&incy, (ftnlen)sizeof(integer)); e_wsfe(); } else if (banded) { io___201.ciunit = *nout; s_wsfe(&io___201); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&k, (ftnlen)sizeof(integer)); do_fio(&c__2, (char *)&alpha, (ftnlen)sizeof(real)); do_fio(&c__1, (char *)&lda, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&incx, (ftnlen)sizeof(integer)); do_fio(&c__2, (char *)&beta, (ftnlen)sizeof(real)); do_fio(&c__1, (char *)&incy, (ftnlen)sizeof(integer)); e_wsfe(); } else if (packed) { io___202.ciunit = *nout; s_wsfe(&io___202); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)); do_fio(&c__2, (char *)&alpha, (ftnlen)sizeof(real)); do_fio(&c__1, (char *)&incx, (ftnlen)sizeof(integer)); do_fio(&c__2, (char *)&beta, (ftnlen)sizeof(real)); do_fio(&c__1, (char *)&incy, (ftnlen)sizeof(integer)); e_wsfe(); } L130: return 0; /* End of CCHK2. */ } /* cchk2_ */ /* Subroutine */ int cchk3_(char *sname, real *eps, real *thresh, integer * nout, integer *ntra, logical *trace, logical *rewi, logical *fatal, integer *nidim, integer *idim, integer *nkb, integer *kb, integer * ninc, integer *inc, integer *nmax, integer *incmax, complex *a, complex *aa, complex *as, complex *x, complex *xx, complex *xs, complex *xt, real *g, complex *z__, ftnlen sname_len) { /* Initialized data */ static char ichu[2] = "UL"; static char icht[3] = "NTC"; static char ichd[2] = "UN"; /* Format strings */ static char fmt_9993[] = "(1x,i6,\002: \002,a6,\002(\002,3(\002'\002,a1" ",\002',\002),i3,\002, A,\002,i3,\002, X,\002,i2,\002) " " .\002)"; static char fmt_9994[] = "(1x,i6,\002: \002,a6,\002(\002,3(\002'\002,a1" ",\002',\002),2(i3,\002,\002),\002 A,\002,i3,\002, X,\002,i2,\002" ") .\002)"; static char fmt_9995[] = "(1x,i6,\002: \002,a6,\002(\002,3(\002'\002,a1" ",\002',\002),i3,\002, AP, \002,\002X,\002,i2,\002) " " .\002)"; static char fmt_9992[] = "(\002 ******* FATAL ERROR - ERROR-EXIT TAKEN O" "N VALID CALL *\002,\002******\002)"; static char fmt_9998[] = "(\002 ******* FATAL ERROR - PARAMETER NUMBER" " \002,i2,\002 WAS CH\002,\002ANGED INCORRECTLY *******\002)"; static char fmt_9999[] = "(\002 \002,a6,\002 PASSED THE COMPUTATIONAL TE" "STS (\002,i6,\002 CALL\002,\002S)\002)"; static char fmt_9997[] = "(\002 \002,a6,\002 COMPLETED THE COMPUTATIONAL" " TESTS (\002,i6,\002 C\002,\002ALLS)\002,/\002 ******* BUT WITH " "MAXIMUM TEST RATIO\002,f8.2,\002 - SUSPECT *******\002)"; static char fmt_9996[] = "(\002 ******* \002,a6,\002 FAILED ON CALL NUMB" "ER:\002)"; /* System generated locals */ integer a_dim1, a_offset, i__1, i__2, i__3, i__4, i__5, i__6; alist al__1; /* Builtin functions */ integer s_cmp(const char *, const char *, ftnlen, ftnlen), s_wsfe(cilist *), do_fio( integer *, char *, ftnlen), e_wsfe(void), f_rew(alist *); /* Local variables */ integer i__, k, n, nc, ik, in, nk, ks, ix, ns, lx, laa, icd, lda; extern logical lce_(complex *, complex *, integer *); integer ict, icu; real err; char diag[1]; integer ldas; logical same; integer incx; logical full, null; char uplo[1]; extern /* Subroutine */ int cmake_(char *, char *, char *, integer *, integer *, complex *, integer *, complex *, integer *, integer *, integer *, logical *, complex *, ftnlen, ftnlen, ftnlen); char diags[1]; logical isame[13]; extern /* Subroutine */ int cmvch_(char *, integer *, integer *, complex * , complex *, integer *, complex *, integer *, complex *, complex * , integer *, complex *, real *, complex *, real *, real *, logical *, integer *, logical *, ftnlen); integer nargs; extern /* Subroutine */ int ctbmv_(char *, char *, char *, integer *, integer *, complex *, integer *, complex *, integer *, ftnlen, ftnlen, ftnlen), ctbsv_(char *, char *, char *, integer *, integer *, complex *, integer *, complex *, integer *, ftnlen, ftnlen, ftnlen); logical reset; integer incxs; char trans[1]; extern /* Subroutine */ int ctpmv_(char *, char *, char *, integer *, complex *, complex *, integer *, ftnlen, ftnlen, ftnlen), ctrmv_( char *, char *, char *, integer *, complex *, integer *, complex * , integer *, ftnlen, ftnlen, ftnlen), ctpsv_(char *, char *, char *, integer *, complex *, complex *, integer *, ftnlen, ftnlen, ftnlen); char uplos[1]; extern /* Subroutine */ int ctrsv_(char *, char *, char *, integer *, complex *, integer *, complex *, integer *, ftnlen, ftnlen, ftnlen); logical banded, packed; extern logical lceres_(char *, char *, integer *, integer *, complex *, complex *, integer *, ftnlen, ftnlen); real errmax; complex transl; char transs[1]; /* Fortran I/O blocks */ static cilist io___239 = { 0, 0, 0, fmt_9993, 0 }; static cilist io___240 = { 0, 0, 0, fmt_9994, 0 }; static cilist io___241 = { 0, 0, 0, fmt_9995, 0 }; static cilist io___242 = { 0, 0, 0, fmt_9993, 0 }; static cilist io___243 = { 0, 0, 0, fmt_9994, 0 }; static cilist io___244 = { 0, 0, 0, fmt_9995, 0 }; static cilist io___245 = { 0, 0, 0, fmt_9992, 0 }; static cilist io___248 = { 0, 0, 0, fmt_9998, 0 }; static cilist io___250 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___251 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___252 = { 0, 0, 0, fmt_9996, 0 }; static cilist io___253 = { 0, 0, 0, fmt_9993, 0 }; static cilist io___254 = { 0, 0, 0, fmt_9994, 0 }; static cilist io___255 = { 0, 0, 0, fmt_9995, 0 }; /* Tests CTRMV, CTBMV, CTPMV, CTRSV, CTBSV and CTPSV. */ /* Auxiliary routine for test program for Level 2 Blas. */ /* -- Written on 10-August-1987. */ /* Richard Hanson, Sandia National Labs. */ /* Jeremy Du Croz, NAG Central Office. */ /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Scalars .. */ /* .. Local Arrays .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. Scalars in Common .. */ /* .. Common blocks .. */ /* .. Data statements .. */ /* Parameter adjustments */ --idim; --kb; --inc; --z__; --g; --xt; --x; --as; --aa; a_dim1 = *nmax; a_offset = 1 + a_dim1; a -= a_offset; --xs; --xx; /* Function Body */ /* .. Executable Statements .. */ full = *(unsigned char *)&sname[2] == 'R'; banded = *(unsigned char *)&sname[2] == 'B'; packed = *(unsigned char *)&sname[2] == 'P'; /* Define the number of arguments. */ if (full) { nargs = 8; } else if (banded) { nargs = 9; } else if (packed) { nargs = 7; } nc = 0; reset = TRUE_; errmax = 0.f; /* Set up zero vector for CMVCH. */ i__1 = *nmax; for (i__ = 1; i__ <= i__1; ++i__) { i__2 = i__; z__[i__2].r = 0.f, z__[i__2].i = 0.f; /* L10: */ } i__1 = *nidim; for (in = 1; in <= i__1; ++in) { n = idim[in]; if (banded) { nk = *nkb; } else { nk = 1; } i__2 = nk; for (ik = 1; ik <= i__2; ++ik) { if (banded) { k = kb[ik]; } else { k = n - 1; } /* Set LDA to 1 more than minimum value if room. */ if (banded) { lda = k + 1; } else { lda = n; } if (lda < *nmax) { ++lda; } /* Skip tests if not enough room. */ if (lda > *nmax) { goto L100; } if (packed) { laa = n * (n + 1) / 2; } else { laa = lda * n; } null = n <= 0; for (icu = 1; icu <= 2; ++icu) { *(unsigned char *)uplo = *(unsigned char *)&ichu[icu - 1]; for (ict = 1; ict <= 3; ++ict) { *(unsigned char *)trans = *(unsigned char *)&icht[ict - 1] ; for (icd = 1; icd <= 2; ++icd) { *(unsigned char *)diag = *(unsigned char *)&ichd[icd - 1]; /* Generate the matrix A. */ transl.r = 0.f, transl.i = 0.f; cmake_(sname + 1, uplo, diag, &n, &n, &a[a_offset], nmax, &aa[1], &lda, &k, &k, &reset, &transl, ( ftnlen)2, (ftnlen)1, (ftnlen)1); i__3 = *ninc; for (ix = 1; ix <= i__3; ++ix) { incx = inc[ix]; lx = abs(incx) * n; /* Generate the vector X. */ transl.r = .5f, transl.i = 0.f; i__4 = abs(incx); i__5 = n - 1; cmake_("GE", " ", " ", &c__1, &n, &x[1], &c__1, & xx[1], &i__4, &c__0, &i__5, &reset, & transl, (ftnlen)2, (ftnlen)1, (ftnlen)1); if (n > 1) { i__4 = n / 2; x[i__4].r = 0.f, x[i__4].i = 0.f; i__4 = abs(incx) * (n / 2 - 1) + 1; xx[i__4].r = 0.f, xx[i__4].i = 0.f; } ++nc; /* Save every datum before calling the subroutine. */ *(unsigned char *)uplos = *(unsigned char *)uplo; *(unsigned char *)transs = *(unsigned char *) trans; *(unsigned char *)diags = *(unsigned char *)diag; ns = n; ks = k; i__4 = laa; for (i__ = 1; i__ <= i__4; ++i__) { i__5 = i__; i__6 = i__; as[i__5].r = aa[i__6].r, as[i__5].i = aa[i__6] .i; /* L20: */ } ldas = lda; i__4 = lx; for (i__ = 1; i__ <= i__4; ++i__) { i__5 = i__; i__6 = i__; xs[i__5].r = xx[i__6].r, xs[i__5].i = xx[i__6] .i; /* L30: */ } incxs = incx; /* Call the subroutine. */ if (s_cmp(sname + 3, "MV", (ftnlen)2, (ftnlen)2) == 0) { if (full) { if (*trace) { io___239.ciunit = *ntra; s_wsfe(&io___239); do_fio(&c__1, (char *)&nc, (ftnlen) sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, diag, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&lda, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&incx, (ftnlen) sizeof(integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } ctrmv_(uplo, trans, diag, &n, &aa[1], & lda, &xx[1], &incx, (ftnlen)1, ( ftnlen)1, (ftnlen)1); } else if (banded) { if (*trace) { io___240.ciunit = *ntra; s_wsfe(&io___240); do_fio(&c__1, (char *)&nc, (ftnlen) sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, diag, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&k, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&lda, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&incx, (ftnlen) sizeof(integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } ctbmv_(uplo, trans, diag, &n, &k, &aa[1], &lda, &xx[1], &incx, (ftnlen)1, ( ftnlen)1, (ftnlen)1); } else if (packed) { if (*trace) { io___241.ciunit = *ntra; s_wsfe(&io___241); do_fio(&c__1, (char *)&nc, (ftnlen) sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, diag, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&incx, (ftnlen) sizeof(integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } ctpmv_(uplo, trans, diag, &n, &aa[1], &xx[ 1], &incx, (ftnlen)1, (ftnlen)1, ( ftnlen)1); } } else if (s_cmp(sname + 3, "SV", (ftnlen)2, ( ftnlen)2) == 0) { if (full) { if (*trace) { io___242.ciunit = *ntra; s_wsfe(&io___242); do_fio(&c__1, (char *)&nc, (ftnlen) sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, diag, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&lda, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&incx, (ftnlen) sizeof(integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } ctrsv_(uplo, trans, diag, &n, &aa[1], & lda, &xx[1], &incx, (ftnlen)1, ( ftnlen)1, (ftnlen)1); } else if (banded) { if (*trace) { io___243.ciunit = *ntra; s_wsfe(&io___243); do_fio(&c__1, (char *)&nc, (ftnlen) sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, diag, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&k, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&lda, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&incx, (ftnlen) sizeof(integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } ctbsv_(uplo, trans, diag, &n, &k, &aa[1], &lda, &xx[1], &incx, (ftnlen)1, ( ftnlen)1, (ftnlen)1); } else if (packed) { if (*trace) { io___244.ciunit = *ntra; s_wsfe(&io___244); do_fio(&c__1, (char *)&nc, (ftnlen) sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, diag, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&incx, (ftnlen) sizeof(integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } ctpsv_(uplo, trans, diag, &n, &aa[1], &xx[ 1], &incx, (ftnlen)1, (ftnlen)1, ( ftnlen)1); } } /* Check if error-exit was taken incorrectly. */ if (! infoc_1.ok) { io___245.ciunit = *nout; s_wsfe(&io___245); e_wsfe(); *fatal = TRUE_; goto L120; } /* See what data changed inside subroutines. */ isame[0] = *(unsigned char *)uplo == *(unsigned char *)uplos; isame[1] = *(unsigned char *)trans == *(unsigned char *)transs; isame[2] = *(unsigned char *)diag == *(unsigned char *)diags; isame[3] = ns == n; if (full) { isame[4] = lce_(&as[1], &aa[1], &laa); isame[5] = ldas == lda; if (null) { isame[6] = lce_(&xs[1], &xx[1], &lx); } else { i__4 = abs(incx); isame[6] = lceres_("GE", " ", &c__1, &n, & xs[1], &xx[1], &i__4, (ftnlen)2, ( ftnlen)1); } isame[7] = incxs == incx; } else if (banded) { isame[4] = ks == k; isame[5] = lce_(&as[1], &aa[1], &laa); isame[6] = ldas == lda; if (null) { isame[7] = lce_(&xs[1], &xx[1], &lx); } else { i__4 = abs(incx); isame[7] = lceres_("GE", " ", &c__1, &n, & xs[1], &xx[1], &i__4, (ftnlen)2, ( ftnlen)1); } isame[8] = incxs == incx; } else if (packed) { isame[4] = lce_(&as[1], &aa[1], &laa); if (null) { isame[5] = lce_(&xs[1], &xx[1], &lx); } else { i__4 = abs(incx); isame[5] = lceres_("GE", " ", &c__1, &n, & xs[1], &xx[1], &i__4, (ftnlen)2, ( ftnlen)1); } isame[6] = incxs == incx; } /* If data was incorrectly changed, report and */ /* return. */ same = TRUE_; i__4 = nargs; for (i__ = 1; i__ <= i__4; ++i__) { same = same && isame[i__ - 1]; if (! isame[i__ - 1]) { io___248.ciunit = *nout; s_wsfe(&io___248); do_fio(&c__1, (char *)&i__, (ftnlen) sizeof(integer)); e_wsfe(); } /* L40: */ } if (! same) { *fatal = TRUE_; goto L120; } if (! null) { if (s_cmp(sname + 3, "MV", (ftnlen)2, (ftnlen) 2) == 0) { /* Check the result. */ cmvch_(trans, &n, &n, &c_b2, &a[a_offset], nmax, &x[1], &incx, &c_b1, &z__[ 1], &incx, &xt[1], &g[1], &xx[1], eps, &err, fatal, nout, &c_true, ( ftnlen)1); } else if (s_cmp(sname + 3, "SV", (ftnlen)2, ( ftnlen)2) == 0) { /* Compute approximation to original vector. */ i__4 = n; for (i__ = 1; i__ <= i__4; ++i__) { i__5 = i__; i__6 = (i__ - 1) * abs(incx) + 1; z__[i__5].r = xx[i__6].r, z__[i__5].i = xx[i__6].i; i__5 = (i__ - 1) * abs(incx) + 1; i__6 = i__; xx[i__5].r = x[i__6].r, xx[i__5].i = x[i__6].i; /* L50: */ } cmvch_(trans, &n, &n, &c_b2, &a[a_offset], nmax, &z__[1], &incx, &c_b1, &x[ 1], &incx, &xt[1], &g[1], &xx[1], eps, &err, fatal, nout, &c_false, (ftnlen)1); } errmax = max(errmax,err); /* If got really bad answer, report and return. */ if (*fatal) { goto L120; } } else { /* Avoid repeating tests with N.le.0. */ goto L110; } /* L60: */ } /* L70: */ } /* L80: */ } /* L90: */ } L100: ; } L110: ; } /* Report result. */ if (errmax < *thresh) { io___250.ciunit = *nout; s_wsfe(&io___250); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); e_wsfe(); } else { io___251.ciunit = *nout; s_wsfe(&io___251); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&errmax, (ftnlen)sizeof(real)); e_wsfe(); } goto L130; L120: io___252.ciunit = *nout; s_wsfe(&io___252); do_fio(&c__1, sname, (ftnlen)6); e_wsfe(); if (full) { io___253.ciunit = *nout; s_wsfe(&io___253); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, diag, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&lda, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&incx, (ftnlen)sizeof(integer)); e_wsfe(); } else if (banded) { io___254.ciunit = *nout; s_wsfe(&io___254); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, diag, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&k, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&lda, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&incx, (ftnlen)sizeof(integer)); e_wsfe(); } else if (packed) { io___255.ciunit = *nout; s_wsfe(&io___255); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, diag, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&incx, (ftnlen)sizeof(integer)); e_wsfe(); } L130: return 0; /* End of CCHK3. */ } /* cchk3_ */ /* Subroutine */ int cchk4_(char *sname, real *eps, real *thresh, integer * nout, integer *ntra, logical *trace, logical *rewi, logical *fatal, integer *nidim, integer *idim, integer *nalf, complex *alf, integer * ninc, integer *inc, integer *nmax, integer *incmax, complex *a, complex *aa, complex *as, complex *x, complex *xx, complex *xs, complex *y, complex *yy, complex *ys, complex *yt, real *g, complex * z__, ftnlen sname_len) { /* Format strings */ static char fmt_9994[] = "(1x,i6,\002: \002,a6,\002(\002,2(i3,\002," "\002),\002(\002,f4.1,\002,\002,f4.1,\002), X,\002,i2,\002, Y," "\002,i2,\002, A,\002,i3,\002) \002,\002 " ".\002)"; static char fmt_9993[] = "(\002 ******* FATAL ERROR - ERROR-EXIT TAKEN O" "N VALID CALL *\002,\002******\002)"; static char fmt_9998[] = "(\002 ******* FATAL ERROR - PARAMETER NUMBER" " \002,i2,\002 WAS CH\002,\002ANGED INCORRECTLY *******\002)"; static char fmt_9999[] = "(\002 \002,a6,\002 PASSED THE COMPUTATIONAL TE" "STS (\002,i6,\002 CALL\002,\002S)\002)"; static char fmt_9997[] = "(\002 \002,a6,\002 COMPLETED THE COMPUTATIONAL" " TESTS (\002,i6,\002 C\002,\002ALLS)\002,/\002 ******* BUT WITH " "MAXIMUM TEST RATIO\002,f8.2,\002 - SUSPECT *******\002)"; static char fmt_9995[] = "(\002 THESE ARE THE RESULTS FOR COLUMN" " \002,i3)"; static char fmt_9996[] = "(\002 ******* \002,a6,\002 FAILED ON CALL NUMB" "ER:\002)"; /* System generated locals */ integer a_dim1, a_offset, i__1, i__2, i__3, i__4, i__5, i__6, i__7; complex q__1; alist al__1; /* Builtin functions */ integer s_wsfe(cilist *), do_fio(integer *, char *, ftnlen), e_wsfe(void), f_rew(alist *); void r_cnjg(complex *, complex *); /* Local variables */ integer i__, j, m, n; complex w[1]; integer ia, nc, nd, im, in, ms, ix, iy, ns, lx, ly, laa, lda; extern logical lce_(complex *, complex *, integer *); complex als; real err; integer ldas; logical same, conj; integer incx, incy; logical null; extern /* Subroutine */ int cmake_(char *, char *, char *, integer *, integer *, complex *, integer *, complex *, integer *, integer *, integer *, logical *, complex *, ftnlen, ftnlen, ftnlen), cgerc_( integer *, integer *, complex *, complex *, integer *, complex *, integer *, complex *, integer *); complex alpha; logical isame[13]; extern /* Subroutine */ int cmvch_(char *, integer *, integer *, complex * , complex *, integer *, complex *, integer *, complex *, complex * , integer *, complex *, real *, complex *, real *, real *, logical *, integer *, logical *, ftnlen), cgeru_(integer *, integer *, complex *, complex *, integer *, complex *, integer *, complex *, integer *); integer nargs; logical reset; integer incxs, incys; extern logical lceres_(char *, char *, integer *, integer *, complex *, complex *, integer *, ftnlen, ftnlen); real errmax; complex transl; /* Fortran I/O blocks */ static cilist io___285 = { 0, 0, 0, fmt_9994, 0 }; static cilist io___286 = { 0, 0, 0, fmt_9993, 0 }; static cilist io___289 = { 0, 0, 0, fmt_9998, 0 }; static cilist io___293 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___294 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___295 = { 0, 0, 0, fmt_9995, 0 }; static cilist io___296 = { 0, 0, 0, fmt_9996, 0 }; static cilist io___297 = { 0, 0, 0, fmt_9994, 0 }; /* Tests CGERC and CGERU. */ /* Auxiliary routine for test program for Level 2 Blas. */ /* -- Written on 10-August-1987. */ /* Richard Hanson, Sandia National Labs. */ /* Jeremy Du Croz, NAG Central Office. */ /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Scalars .. */ /* .. Local Arrays .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. Scalars in Common .. */ /* .. Common blocks .. */ /* .. Executable Statements .. */ /* Parameter adjustments */ --idim; --alf; --inc; --z__; --g; --yt; --y; --x; --as; --aa; a_dim1 = *nmax; a_offset = 1 + a_dim1; a -= a_offset; --ys; --yy; --xs; --xx; /* Function Body */ conj = *(unsigned char *)&sname[4] == 'C'; /* Define the number of arguments. */ nargs = 9; nc = 0; reset = TRUE_; errmax = 0.f; i__1 = *nidim; for (in = 1; in <= i__1; ++in) { n = idim[in]; nd = n / 2 + 1; for (im = 1; im <= 2; ++im) { if (im == 1) { /* Computing MAX */ i__2 = n - nd; m = max(i__2,0); } if (im == 2) { /* Computing MIN */ i__2 = n + nd; m = min(i__2,*nmax); } /* Set LDA to 1 more than minimum value if room. */ lda = m; if (lda < *nmax) { ++lda; } /* Skip tests if not enough room. */ if (lda > *nmax) { goto L110; } laa = lda * n; null = n <= 0 || m <= 0; i__2 = *ninc; for (ix = 1; ix <= i__2; ++ix) { incx = inc[ix]; lx = abs(incx) * m; /* Generate the vector X. */ transl.r = .5f, transl.i = 0.f; i__3 = abs(incx); i__4 = m - 1; cmake_("GE", " ", " ", &c__1, &m, &x[1], &c__1, &xx[1], &i__3, &c__0, &i__4, &reset, &transl, (ftnlen)2, (ftnlen)1, (ftnlen)1); if (m > 1) { i__3 = m / 2; x[i__3].r = 0.f, x[i__3].i = 0.f; i__3 = abs(incx) * (m / 2 - 1) + 1; xx[i__3].r = 0.f, xx[i__3].i = 0.f; } i__3 = *ninc; for (iy = 1; iy <= i__3; ++iy) { incy = inc[iy]; ly = abs(incy) * n; /* Generate the vector Y. */ transl.r = 0.f, transl.i = 0.f; i__4 = abs(incy); i__5 = n - 1; cmake_("GE", " ", " ", &c__1, &n, &y[1], &c__1, &yy[1], & i__4, &c__0, &i__5, &reset, &transl, (ftnlen)2, ( ftnlen)1, (ftnlen)1); if (n > 1) { i__4 = n / 2; y[i__4].r = 0.f, y[i__4].i = 0.f; i__4 = abs(incy) * (n / 2 - 1) + 1; yy[i__4].r = 0.f, yy[i__4].i = 0.f; } i__4 = *nalf; for (ia = 1; ia <= i__4; ++ia) { i__5 = ia; alpha.r = alf[i__5].r, alpha.i = alf[i__5].i; /* Generate the matrix A. */ transl.r = 0.f, transl.i = 0.f; i__5 = m - 1; i__6 = n - 1; cmake_(sname + 1, " ", " ", &m, &n, &a[a_offset], nmax, &aa[1], &lda, &i__5, &i__6, &reset, & transl, (ftnlen)2, (ftnlen)1, (ftnlen)1); ++nc; /* Save every datum before calling the subroutine. */ ms = m; ns = n; als.r = alpha.r, als.i = alpha.i; i__5 = laa; for (i__ = 1; i__ <= i__5; ++i__) { i__6 = i__; i__7 = i__; as[i__6].r = aa[i__7].r, as[i__6].i = aa[i__7].i; /* L10: */ } ldas = lda; i__5 = lx; for (i__ = 1; i__ <= i__5; ++i__) { i__6 = i__; i__7 = i__; xs[i__6].r = xx[i__7].r, xs[i__6].i = xx[i__7].i; /* L20: */ } incxs = incx; i__5 = ly; for (i__ = 1; i__ <= i__5; ++i__) { i__6 = i__; i__7 = i__; ys[i__6].r = yy[i__7].r, ys[i__6].i = yy[i__7].i; /* L30: */ } incys = incy; /* Call the subroutine. */ if (*trace) { io___285.ciunit = *ntra; s_wsfe(&io___285); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer) ); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&m, (ftnlen)sizeof(integer)) ; do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)) ; do_fio(&c__2, (char *)&alpha, (ftnlen)sizeof(real) ); do_fio(&c__1, (char *)&incx, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&incy, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&lda, (ftnlen)sizeof( integer)); e_wsfe(); } if (conj) { if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } cgerc_(&m, &n, &alpha, &xx[1], &incx, &yy[1], & incy, &aa[1], &lda); } else { if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } cgeru_(&m, &n, &alpha, &xx[1], &incx, &yy[1], & incy, &aa[1], &lda); } /* Check if error-exit was taken incorrectly. */ if (! infoc_1.ok) { io___286.ciunit = *nout; s_wsfe(&io___286); e_wsfe(); *fatal = TRUE_; goto L140; } /* See what data changed inside subroutine. */ isame[0] = ms == m; isame[1] = ns == n; isame[2] = als.r == alpha.r && als.i == alpha.i; isame[3] = lce_(&xs[1], &xx[1], &lx); isame[4] = incxs == incx; isame[5] = lce_(&ys[1], &yy[1], &ly); isame[6] = incys == incy; if (null) { isame[7] = lce_(&as[1], &aa[1], &laa); } else { isame[7] = lceres_("GE", " ", &m, &n, &as[1], &aa[ 1], &lda, (ftnlen)2, (ftnlen)1); } isame[8] = ldas == lda; /* If data was incorrectly changed, report and return. */ same = TRUE_; i__5 = nargs; for (i__ = 1; i__ <= i__5; ++i__) { same = same && isame[i__ - 1]; if (! isame[i__ - 1]) { io___289.ciunit = *nout; s_wsfe(&io___289); do_fio(&c__1, (char *)&i__, (ftnlen)sizeof( integer)); e_wsfe(); } /* L40: */ } if (! same) { *fatal = TRUE_; goto L140; } if (! null) { /* Check the result column by column. */ if (incx > 0) { i__5 = m; for (i__ = 1; i__ <= i__5; ++i__) { i__6 = i__; i__7 = i__; z__[i__6].r = x[i__7].r, z__[i__6].i = x[ i__7].i; /* L50: */ } } else { i__5 = m; for (i__ = 1; i__ <= i__5; ++i__) { i__6 = i__; i__7 = m - i__ + 1; z__[i__6].r = x[i__7].r, z__[i__6].i = x[ i__7].i; /* L60: */ } } i__5 = n; for (j = 1; j <= i__5; ++j) { if (incy > 0) { i__6 = j; w[0].r = y[i__6].r, w[0].i = y[i__6].i; } else { i__6 = n - j + 1; w[0].r = y[i__6].r, w[0].i = y[i__6].i; } if (conj) { r_cnjg(&q__1, w); w[0].r = q__1.r, w[0].i = q__1.i; } cmvch_("N", &m, &c__1, &alpha, &z__[1], nmax, w, &c__1, &c_b2, &a[j * a_dim1 + 1], & c__1, &yt[1], &g[1], &aa[(j - 1) * lda + 1], eps, &err, fatal, nout, & c_true, (ftnlen)1); errmax = max(errmax,err); /* If got really bad answer, report and return. */ if (*fatal) { goto L130; } /* L70: */ } } else { /* Avoid repeating tests with M.le.0 or N.le.0. */ goto L110; } /* L80: */ } /* L90: */ } /* L100: */ } L110: ; } /* L120: */ } /* Report result. */ if (errmax < *thresh) { io___293.ciunit = *nout; s_wsfe(&io___293); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); e_wsfe(); } else { io___294.ciunit = *nout; s_wsfe(&io___294); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&errmax, (ftnlen)sizeof(real)); e_wsfe(); } goto L150; L130: io___295.ciunit = *nout; s_wsfe(&io___295); do_fio(&c__1, (char *)&j, (ftnlen)sizeof(integer)); e_wsfe(); L140: io___296.ciunit = *nout; s_wsfe(&io___296); do_fio(&c__1, sname, (ftnlen)6); e_wsfe(); io___297.ciunit = *nout; s_wsfe(&io___297); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&m, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)); do_fio(&c__2, (char *)&alpha, (ftnlen)sizeof(real)); do_fio(&c__1, (char *)&incx, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&incy, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&lda, (ftnlen)sizeof(integer)); e_wsfe(); L150: return 0; /* End of CCHK4. */ } /* cchk4_ */ /* Subroutine */ int cchk5_(char *sname, real *eps, real *thresh, integer * nout, integer *ntra, logical *trace, logical *rewi, logical *fatal, integer *nidim, integer *idim, integer *nalf, complex *alf, integer * ninc, integer *inc, integer *nmax, integer *incmax, complex *a, complex *aa, complex *as, complex *x, complex *xx, complex *xs, complex *y, complex *yy, complex *ys, complex *yt, real *g, complex * z__, ftnlen sname_len) { /* Initialized data */ static char ich[2] = "UL"; /* Format strings */ static char fmt_9993[] = "(1x,i6,\002: \002,a6,\002('\002,a1,\002',\002," "i3,\002,\002,f4.1,\002, X,\002,i2,\002, A,\002,i3,\002) " " .\002)"; static char fmt_9994[] = "(1x,i6,\002: \002,a6,\002('\002,a1,\002',\002," "i3,\002,\002,f4.1,\002, X,\002,i2,\002, AP) " " .\002)"; static char fmt_9992[] = "(\002 ******* FATAL ERROR - ERROR-EXIT TAKEN O" "N VALID CALL *\002,\002******\002)"; static char fmt_9998[] = "(\002 ******* FATAL ERROR - PARAMETER NUMBER" " \002,i2,\002 WAS CH\002,\002ANGED INCORRECTLY *******\002)"; static char fmt_9999[] = "(\002 \002,a6,\002 PASSED THE COMPUTATIONAL TE" "STS (\002,i6,\002 CALL\002,\002S)\002)"; static char fmt_9997[] = "(\002 \002,a6,\002 COMPLETED THE COMPUTATIONAL" " TESTS (\002,i6,\002 C\002,\002ALLS)\002,/\002 ******* BUT WITH " "MAXIMUM TEST RATIO\002,f8.2,\002 - SUSPECT *******\002)"; static char fmt_9995[] = "(\002 THESE ARE THE RESULTS FOR COLUMN" " \002,i3)"; static char fmt_9996[] = "(\002 ******* \002,a6,\002 FAILED ON CALL NUMB" "ER:\002)"; /* System generated locals */ integer a_dim1, a_offset, i__1, i__2, i__3, i__4, i__5, i__6; complex q__1; alist al__1; /* Builtin functions */ integer s_wsfe(cilist *), do_fio(integer *, char *, ftnlen), e_wsfe(void), f_rew(alist *); void r_cnjg(complex *, complex *); /* Local variables */ integer i__, j, n; complex w[1]; integer ia, ja, ic, nc, jj, lj, in, ix, ns, lx, laa, lda; extern logical lce_(complex *, complex *, integer *); real err; extern /* Subroutine */ int cher_(char *, integer *, real *, complex *, integer *, complex *, integer *, ftnlen); integer ldas; logical same; extern /* Subroutine */ int chpr_(char *, integer *, real *, complex *, integer *, complex *, ftnlen); real rals; integer incx; logical full, null; char uplo[1]; extern /* Subroutine */ int cmake_(char *, char *, char *, integer *, integer *, complex *, integer *, complex *, integer *, integer *, integer *, logical *, complex *, ftnlen, ftnlen, ftnlen); complex alpha; logical isame[13]; extern /* Subroutine */ int cmvch_(char *, integer *, integer *, complex * , complex *, integer *, complex *, integer *, complex *, complex * , integer *, complex *, real *, complex *, real *, real *, logical *, integer *, logical *, ftnlen); integer nargs; logical reset; integer incxs; logical upper; char uplos[1]; logical packed; real ralpha; extern logical lceres_(char *, char *, integer *, integer *, complex *, complex *, integer *, ftnlen, ftnlen); real errmax; complex transl; /* Fortran I/O blocks */ static cilist io___326 = { 0, 0, 0, fmt_9993, 0 }; static cilist io___327 = { 0, 0, 0, fmt_9994, 0 }; static cilist io___328 = { 0, 0, 0, fmt_9992, 0 }; static cilist io___331 = { 0, 0, 0, fmt_9998, 0 }; static cilist io___338 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___339 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___340 = { 0, 0, 0, fmt_9995, 0 }; static cilist io___341 = { 0, 0, 0, fmt_9996, 0 }; static cilist io___342 = { 0, 0, 0, fmt_9993, 0 }; static cilist io___343 = { 0, 0, 0, fmt_9994, 0 }; /* Tests CHER and CHPR. */ /* Auxiliary routine for test program for Level 2 Blas. */ /* -- Written on 10-August-1987. */ /* Richard Hanson, Sandia National Labs. */ /* Jeremy Du Croz, NAG Central Office. */ /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Scalars .. */ /* .. Local Arrays .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. Scalars in Common .. */ /* .. Common blocks .. */ /* .. Data statements .. */ /* Parameter adjustments */ --idim; --alf; --inc; --z__; --g; --yt; --y; --x; --as; --aa; a_dim1 = *nmax; a_offset = 1 + a_dim1; a -= a_offset; --ys; --yy; --xs; --xx; /* Function Body */ /* .. Executable Statements .. */ full = *(unsigned char *)&sname[2] == 'E'; packed = *(unsigned char *)&sname[2] == 'P'; /* Define the number of arguments. */ if (full) { nargs = 7; } else if (packed) { nargs = 6; } nc = 0; reset = TRUE_; errmax = 0.f; i__1 = *nidim; for (in = 1; in <= i__1; ++in) { n = idim[in]; /* Set LDA to 1 more than minimum value if room. */ lda = n; if (lda < *nmax) { ++lda; } /* Skip tests if not enough room. */ if (lda > *nmax) { goto L100; } if (packed) { laa = n * (n + 1) / 2; } else { laa = lda * n; } for (ic = 1; ic <= 2; ++ic) { *(unsigned char *)uplo = *(unsigned char *)&ich[ic - 1]; upper = *(unsigned char *)uplo == 'U'; i__2 = *ninc; for (ix = 1; ix <= i__2; ++ix) { incx = inc[ix]; lx = abs(incx) * n; /* Generate the vector X. */ transl.r = .5f, transl.i = 0.f; i__3 = abs(incx); i__4 = n - 1; cmake_("GE", " ", " ", &c__1, &n, &x[1], &c__1, &xx[1], &i__3, &c__0, &i__4, &reset, &transl, (ftnlen)2, (ftnlen)1, (ftnlen)1); if (n > 1) { i__3 = n / 2; x[i__3].r = 0.f, x[i__3].i = 0.f; i__3 = abs(incx) * (n / 2 - 1) + 1; xx[i__3].r = 0.f, xx[i__3].i = 0.f; } i__3 = *nalf; for (ia = 1; ia <= i__3; ++ia) { i__4 = ia; ralpha = alf[i__4].r; q__1.r = ralpha, q__1.i = 0.f; alpha.r = q__1.r, alpha.i = q__1.i; null = n <= 0 || ralpha == 0.f; /* Generate the matrix A. */ transl.r = 0.f, transl.i = 0.f; i__4 = n - 1; i__5 = n - 1; cmake_(sname + 1, uplo, " ", &n, &n, &a[a_offset], nmax, & aa[1], &lda, &i__4, &i__5, &reset, &transl, ( ftnlen)2, (ftnlen)1, (ftnlen)1); ++nc; /* Save every datum before calling the subroutine. */ *(unsigned char *)uplos = *(unsigned char *)uplo; ns = n; rals = ralpha; i__4 = laa; for (i__ = 1; i__ <= i__4; ++i__) { i__5 = i__; i__6 = i__; as[i__5].r = aa[i__6].r, as[i__5].i = aa[i__6].i; /* L10: */ } ldas = lda; i__4 = lx; for (i__ = 1; i__ <= i__4; ++i__) { i__5 = i__; i__6 = i__; xs[i__5].r = xx[i__6].r, xs[i__5].i = xx[i__6].i; /* L20: */ } incxs = incx; /* Call the subroutine. */ if (full) { if (*trace) { io___326.ciunit = *ntra; s_wsfe(&io___326); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer) ); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)) ; do_fio(&c__1, (char *)&ralpha, (ftnlen)sizeof( real)); do_fio(&c__1, (char *)&incx, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&lda, (ftnlen)sizeof( integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } cher_(uplo, &n, &ralpha, &xx[1], &incx, &aa[1], &lda, (ftnlen)1); } else if (packed) { if (*trace) { io___327.ciunit = *ntra; s_wsfe(&io___327); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer) ); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)) ; do_fio(&c__1, (char *)&ralpha, (ftnlen)sizeof( real)); do_fio(&c__1, (char *)&incx, (ftnlen)sizeof( integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } chpr_(uplo, &n, &ralpha, &xx[1], &incx, &aa[1], ( ftnlen)1); } /* Check if error-exit was taken incorrectly. */ if (! infoc_1.ok) { io___328.ciunit = *nout; s_wsfe(&io___328); e_wsfe(); *fatal = TRUE_; goto L120; } /* See what data changed inside subroutines. */ isame[0] = *(unsigned char *)uplo == *(unsigned char *) uplos; isame[1] = ns == n; isame[2] = rals == ralpha; isame[3] = lce_(&xs[1], &xx[1], &lx); isame[4] = incxs == incx; if (null) { isame[5] = lce_(&as[1], &aa[1], &laa); } else { isame[5] = lceres_(sname + 1, uplo, &n, &n, &as[1], & aa[1], &lda, (ftnlen)2, (ftnlen)1); } if (! packed) { isame[6] = ldas == lda; } /* If data was incorrectly changed, report and return. */ same = TRUE_; i__4 = nargs; for (i__ = 1; i__ <= i__4; ++i__) { same = same && isame[i__ - 1]; if (! isame[i__ - 1]) { io___331.ciunit = *nout; s_wsfe(&io___331); do_fio(&c__1, (char *)&i__, (ftnlen)sizeof( integer)); e_wsfe(); } /* L30: */ } if (! same) { *fatal = TRUE_; goto L120; } if (! null) { /* Check the result column by column. */ if (incx > 0) { i__4 = n; for (i__ = 1; i__ <= i__4; ++i__) { i__5 = i__; i__6 = i__; z__[i__5].r = x[i__6].r, z__[i__5].i = x[i__6] .i; /* L40: */ } } else { i__4 = n; for (i__ = 1; i__ <= i__4; ++i__) { i__5 = i__; i__6 = n - i__ + 1; z__[i__5].r = x[i__6].r, z__[i__5].i = x[i__6] .i; /* L50: */ } } ja = 1; i__4 = n; for (j = 1; j <= i__4; ++j) { r_cnjg(&q__1, &z__[j]); w[0].r = q__1.r, w[0].i = q__1.i; if (upper) { jj = 1; lj = j; } else { jj = j; lj = n - j + 1; } cmvch_("N", &lj, &c__1, &alpha, &z__[jj], &lj, w, &c__1, &c_b2, &a[jj + j * a_dim1], &c__1, &yt[1], &g[1], &aa[ja], eps, &err, fatal, nout, &c_true, (ftnlen)1); if (full) { if (upper) { ja += lda; } else { ja = ja + lda + 1; } } else { ja += lj; } errmax = max(errmax,err); /* If got really bad answer, report and return. */ if (*fatal) { goto L110; } /* L60: */ } } else { /* Avoid repeating tests if N.le.0. */ if (n <= 0) { goto L100; } } /* L70: */ } /* L80: */ } /* L90: */ } L100: ; } /* Report result. */ if (errmax < *thresh) { io___338.ciunit = *nout; s_wsfe(&io___338); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); e_wsfe(); } else { io___339.ciunit = *nout; s_wsfe(&io___339); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&errmax, (ftnlen)sizeof(real)); e_wsfe(); } goto L130; L110: io___340.ciunit = *nout; s_wsfe(&io___340); do_fio(&c__1, (char *)&j, (ftnlen)sizeof(integer)); e_wsfe(); L120: io___341.ciunit = *nout; s_wsfe(&io___341); do_fio(&c__1, sname, (ftnlen)6); e_wsfe(); if (full) { io___342.ciunit = *nout; s_wsfe(&io___342); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&ralpha, (ftnlen)sizeof(real)); do_fio(&c__1, (char *)&incx, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&lda, (ftnlen)sizeof(integer)); e_wsfe(); } else if (packed) { io___343.ciunit = *nout; s_wsfe(&io___343); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&ralpha, (ftnlen)sizeof(real)); do_fio(&c__1, (char *)&incx, (ftnlen)sizeof(integer)); e_wsfe(); } L130: return 0; /* End of CCHK5. */ } /* cchk5_ */ /* Subroutine */ int cchk6_(char *sname, real *eps, real *thresh, integer * nout, integer *ntra, logical *trace, logical *rewi, logical *fatal, integer *nidim, integer *idim, integer *nalf, complex *alf, integer * ninc, integer *inc, integer *nmax, integer *incmax, complex *a, complex *aa, complex *as, complex *x, complex *xx, complex *xs, complex *y, complex *yy, complex *ys, complex *yt, real *g, complex * z__, ftnlen sname_len) { /* Initialized data */ static char ich[2] = "UL"; /* Format strings */ static char fmt_9993[] = "(1x,i6,\002: \002,a6,\002('\002,a1,\002',\002," "i3,\002,(\002,f4.1,\002,\002,f4.1,\002), X,\002,i2,\002, Y,\002," "i2,\002, A,\002,i3,\002) \002,\002 .\002)"; static char fmt_9994[] = "(1x,i6,\002: \002,a6,\002('\002,a1,\002',\002," "i3,\002,(\002,f4.1,\002,\002,f4.1,\002), X,\002,i2,\002, Y,\002," "i2,\002, AP) \002,\002 .\002)"; static char fmt_9992[] = "(\002 ******* FATAL ERROR - ERROR-EXIT TAKEN O" "N VALID CALL *\002,\002******\002)"; static char fmt_9998[] = "(\002 ******* FATAL ERROR - PARAMETER NUMBER" " \002,i2,\002 WAS CH\002,\002ANGED INCORRECTLY *******\002)"; static char fmt_9999[] = "(\002 \002,a6,\002 PASSED THE COMPUTATIONAL TE" "STS (\002,i6,\002 CALL\002,\002S)\002)"; static char fmt_9997[] = "(\002 \002,a6,\002 COMPLETED THE COMPUTATIONAL" " TESTS (\002,i6,\002 C\002,\002ALLS)\002,/\002 ******* BUT WITH " "MAXIMUM TEST RATIO\002,f8.2,\002 - SUSPECT *******\002)"; static char fmt_9995[] = "(\002 THESE ARE THE RESULTS FOR COLUMN" " \002,i3)"; static char fmt_9996[] = "(\002 ******* \002,a6,\002 FAILED ON CALL NUMB" "ER:\002)"; /* System generated locals */ integer a_dim1, a_offset, z_dim1, z_offset, i__1, i__2, i__3, i__4, i__5, i__6, i__7; complex q__1, q__2, q__3; alist al__1; /* Builtin functions */ integer s_wsfe(cilist *), do_fio(integer *, char *, ftnlen), e_wsfe(void), f_rew(alist *); void r_cnjg(complex *, complex *); /* Local variables */ integer i__, j, n; complex w[2]; integer ia, ja, ic, nc, jj, lj, in, ix, iy, ns, lx, ly, laa, lda; extern logical lce_(complex *, complex *, integer *); complex als; real err; integer ldas; logical same; integer incx, incy; logical full, null; char uplo[1]; extern /* Subroutine */ int cher2_(char *, integer *, complex *, complex * , integer *, complex *, integer *, complex *, integer *, ftnlen), chpr2_(char *, integer *, complex *, complex *, integer *, complex *, integer *, complex *, ftnlen), cmake_(char *, char *, char *, integer *, integer *, complex *, integer *, complex *, integer *, integer *, integer *, logical *, complex *, ftnlen, ftnlen, ftnlen); complex alpha; logical isame[13]; extern /* Subroutine */ int cmvch_(char *, integer *, integer *, complex * , complex *, integer *, complex *, integer *, complex *, complex * , integer *, complex *, real *, complex *, real *, real *, logical *, integer *, logical *, ftnlen); integer nargs; logical reset; integer incxs, incys; logical upper; char uplos[1]; logical packed; extern logical lceres_(char *, char *, integer *, integer *, complex *, complex *, integer *, ftnlen, ftnlen); real errmax; complex transl; /* Fortran I/O blocks */ static cilist io___375 = { 0, 0, 0, fmt_9993, 0 }; static cilist io___376 = { 0, 0, 0, fmt_9994, 0 }; static cilist io___377 = { 0, 0, 0, fmt_9992, 0 }; static cilist io___380 = { 0, 0, 0, fmt_9998, 0 }; static cilist io___387 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___388 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___389 = { 0, 0, 0, fmt_9995, 0 }; static cilist io___390 = { 0, 0, 0, fmt_9996, 0 }; static cilist io___391 = { 0, 0, 0, fmt_9993, 0 }; static cilist io___392 = { 0, 0, 0, fmt_9994, 0 }; /* Tests CHER2 and CHPR2. */ /* Auxiliary routine for test program for Level 2 Blas. */ /* -- Written on 10-August-1987. */ /* Richard Hanson, Sandia National Labs. */ /* Jeremy Du Croz, NAG Central Office. */ /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Scalars .. */ /* .. Local Arrays .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. Scalars in Common .. */ /* .. Common blocks .. */ /* .. Data statements .. */ /* Parameter adjustments */ --idim; --alf; --inc; z_dim1 = *nmax; z_offset = 1 + z_dim1; z__ -= z_offset; --g; --yt; --y; --x; --as; --aa; a_dim1 = *nmax; a_offset = 1 + a_dim1; a -= a_offset; --ys; --yy; --xs; --xx; /* Function Body */ /* .. Executable Statements .. */ full = *(unsigned char *)&sname[2] == 'E'; packed = *(unsigned char *)&sname[2] == 'P'; /* Define the number of arguments. */ if (full) { nargs = 9; } else if (packed) { nargs = 8; } nc = 0; reset = TRUE_; errmax = 0.f; i__1 = *nidim; for (in = 1; in <= i__1; ++in) { n = idim[in]; /* Set LDA to 1 more than minimum value if room. */ lda = n; if (lda < *nmax) { ++lda; } /* Skip tests if not enough room. */ if (lda > *nmax) { goto L140; } if (packed) { laa = n * (n + 1) / 2; } else { laa = lda * n; } for (ic = 1; ic <= 2; ++ic) { *(unsigned char *)uplo = *(unsigned char *)&ich[ic - 1]; upper = *(unsigned char *)uplo == 'U'; i__2 = *ninc; for (ix = 1; ix <= i__2; ++ix) { incx = inc[ix]; lx = abs(incx) * n; /* Generate the vector X. */ transl.r = .5f, transl.i = 0.f; i__3 = abs(incx); i__4 = n - 1; cmake_("GE", " ", " ", &c__1, &n, &x[1], &c__1, &xx[1], &i__3, &c__0, &i__4, &reset, &transl, (ftnlen)2, (ftnlen)1, (ftnlen)1); if (n > 1) { i__3 = n / 2; x[i__3].r = 0.f, x[i__3].i = 0.f; i__3 = abs(incx) * (n / 2 - 1) + 1; xx[i__3].r = 0.f, xx[i__3].i = 0.f; } i__3 = *ninc; for (iy = 1; iy <= i__3; ++iy) { incy = inc[iy]; ly = abs(incy) * n; /* Generate the vector Y. */ transl.r = 0.f, transl.i = 0.f; i__4 = abs(incy); i__5 = n - 1; cmake_("GE", " ", " ", &c__1, &n, &y[1], &c__1, &yy[1], & i__4, &c__0, &i__5, &reset, &transl, (ftnlen)2, ( ftnlen)1, (ftnlen)1); if (n > 1) { i__4 = n / 2; y[i__4].r = 0.f, y[i__4].i = 0.f; i__4 = abs(incy) * (n / 2 - 1) + 1; yy[i__4].r = 0.f, yy[i__4].i = 0.f; } i__4 = *nalf; for (ia = 1; ia <= i__4; ++ia) { i__5 = ia; alpha.r = alf[i__5].r, alpha.i = alf[i__5].i; null = n <= 0 || alpha.r == 0.f && alpha.i == 0.f; /* Generate the matrix A. */ transl.r = 0.f, transl.i = 0.f; i__5 = n - 1; i__6 = n - 1; cmake_(sname + 1, uplo, " ", &n, &n, &a[a_offset], nmax, &aa[1], &lda, &i__5, &i__6, &reset, & transl, (ftnlen)2, (ftnlen)1, (ftnlen)1); ++nc; /* Save every datum before calling the subroutine. */ *(unsigned char *)uplos = *(unsigned char *)uplo; ns = n; als.r = alpha.r, als.i = alpha.i; i__5 = laa; for (i__ = 1; i__ <= i__5; ++i__) { i__6 = i__; i__7 = i__; as[i__6].r = aa[i__7].r, as[i__6].i = aa[i__7].i; /* L10: */ } ldas = lda; i__5 = lx; for (i__ = 1; i__ <= i__5; ++i__) { i__6 = i__; i__7 = i__; xs[i__6].r = xx[i__7].r, xs[i__6].i = xx[i__7].i; /* L20: */ } incxs = incx; i__5 = ly; for (i__ = 1; i__ <= i__5; ++i__) { i__6 = i__; i__7 = i__; ys[i__6].r = yy[i__7].r, ys[i__6].i = yy[i__7].i; /* L30: */ } incys = incy; /* Call the subroutine. */ if (full) { if (*trace) { io___375.ciunit = *ntra; s_wsfe(&io___375); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof( integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof( integer)); do_fio(&c__2, (char *)&alpha, (ftnlen)sizeof( real)); do_fio(&c__1, (char *)&incx, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&incy, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&lda, (ftnlen)sizeof( integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } cher2_(uplo, &n, &alpha, &xx[1], &incx, &yy[1], & incy, &aa[1], &lda, (ftnlen)1); } else if (packed) { if (*trace) { io___376.ciunit = *ntra; s_wsfe(&io___376); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof( integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof( integer)); do_fio(&c__2, (char *)&alpha, (ftnlen)sizeof( real)); do_fio(&c__1, (char *)&incx, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&incy, (ftnlen)sizeof( integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } chpr2_(uplo, &n, &alpha, &xx[1], &incx, &yy[1], & incy, &aa[1], (ftnlen)1); } /* Check if error-exit was taken incorrectly. */ if (! infoc_1.ok) { io___377.ciunit = *nout; s_wsfe(&io___377); e_wsfe(); *fatal = TRUE_; goto L160; } /* See what data changed inside subroutines. */ isame[0] = *(unsigned char *)uplo == *(unsigned char * )uplos; isame[1] = ns == n; isame[2] = als.r == alpha.r && als.i == alpha.i; isame[3] = lce_(&xs[1], &xx[1], &lx); isame[4] = incxs == incx; isame[5] = lce_(&ys[1], &yy[1], &ly); isame[6] = incys == incy; if (null) { isame[7] = lce_(&as[1], &aa[1], &laa); } else { isame[7] = lceres_(sname + 1, uplo, &n, &n, &as[1] , &aa[1], &lda, (ftnlen)2, (ftnlen)1); } if (! packed) { isame[8] = ldas == lda; } /* If data was incorrectly changed, report and return. */ same = TRUE_; i__5 = nargs; for (i__ = 1; i__ <= i__5; ++i__) { same = same && isame[i__ - 1]; if (! isame[i__ - 1]) { io___380.ciunit = *nout; s_wsfe(&io___380); do_fio(&c__1, (char *)&i__, (ftnlen)sizeof( integer)); e_wsfe(); } /* L40: */ } if (! same) { *fatal = TRUE_; goto L160; } if (! null) { /* Check the result column by column. */ if (incx > 0) { i__5 = n; for (i__ = 1; i__ <= i__5; ++i__) { i__6 = i__ + z_dim1; i__7 = i__; z__[i__6].r = x[i__7].r, z__[i__6].i = x[ i__7].i; /* L50: */ } } else { i__5 = n; for (i__ = 1; i__ <= i__5; ++i__) { i__6 = i__ + z_dim1; i__7 = n - i__ + 1; z__[i__6].r = x[i__7].r, z__[i__6].i = x[ i__7].i; /* L60: */ } } if (incy > 0) { i__5 = n; for (i__ = 1; i__ <= i__5; ++i__) { i__6 = i__ + (z_dim1 << 1); i__7 = i__; z__[i__6].r = y[i__7].r, z__[i__6].i = y[ i__7].i; /* L70: */ } } else { i__5 = n; for (i__ = 1; i__ <= i__5; ++i__) { i__6 = i__ + (z_dim1 << 1); i__7 = n - i__ + 1; z__[i__6].r = y[i__7].r, z__[i__6].i = y[ i__7].i; /* L80: */ } } ja = 1; i__5 = n; for (j = 1; j <= i__5; ++j) { r_cnjg(&q__2, &z__[j + (z_dim1 << 1)]); q__1.r = alpha.r * q__2.r - alpha.i * q__2.i, q__1.i = alpha.r * q__2.i + alpha.i * q__2.r; w[0].r = q__1.r, w[0].i = q__1.i; r_cnjg(&q__2, &alpha); r_cnjg(&q__3, &z__[j + z_dim1]); q__1.r = q__2.r * q__3.r - q__2.i * q__3.i, q__1.i = q__2.r * q__3.i + q__2.i * q__3.r; w[1].r = q__1.r, w[1].i = q__1.i; if (upper) { jj = 1; lj = j; } else { jj = j; lj = n - j + 1; } cmvch_("N", &lj, &c__2, &c_b2, &z__[jj + z_dim1], nmax, w, &c__1, &c_b2, &a[jj + j * a_dim1], &c__1, &yt[1], &g[1], & aa[ja], eps, &err, fatal, nout, & c_true, (ftnlen)1); if (full) { if (upper) { ja += lda; } else { ja = ja + lda + 1; } } else { ja += lj; } errmax = max(errmax,err); /* If got really bad answer, report and return. */ if (*fatal) { goto L150; } /* L90: */ } } else { /* Avoid repeating tests with N.le.0. */ if (n <= 0) { goto L140; } } /* L100: */ } /* L110: */ } /* L120: */ } /* L130: */ } L140: ; } /* Report result. */ if (errmax < *thresh) { io___387.ciunit = *nout; s_wsfe(&io___387); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); e_wsfe(); } else { io___388.ciunit = *nout; s_wsfe(&io___388); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&errmax, (ftnlen)sizeof(real)); e_wsfe(); } goto L170; L150: io___389.ciunit = *nout; s_wsfe(&io___389); do_fio(&c__1, (char *)&j, (ftnlen)sizeof(integer)); e_wsfe(); L160: io___390.ciunit = *nout; s_wsfe(&io___390); do_fio(&c__1, sname, (ftnlen)6); e_wsfe(); if (full) { io___391.ciunit = *nout; s_wsfe(&io___391); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)); do_fio(&c__2, (char *)&alpha, (ftnlen)sizeof(real)); do_fio(&c__1, (char *)&incx, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&incy, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&lda, (ftnlen)sizeof(integer)); e_wsfe(); } else if (packed) { io___392.ciunit = *nout; s_wsfe(&io___392); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)); do_fio(&c__2, (char *)&alpha, (ftnlen)sizeof(real)); do_fio(&c__1, (char *)&incx, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&incy, (ftnlen)sizeof(integer)); e_wsfe(); } L170: return 0; /* End of CCHK6. */ } /* cchk6_ */ /* Subroutine */ int cchke_(integer *isnum, char *srnamt, integer *nout, ftnlen srnamt_len) { /* Format strings */ static char fmt_9999[] = "(\002 \002,a6,\002 PASSED THE TESTS OF ERROR-E" "XITS\002)"; static char fmt_9998[] = "(\002 ******* \002,a6,\002 FAILED THE TESTS OF" " ERROR-EXITS *****\002,\002**\002)"; /* Builtin functions */ integer s_wsfe(cilist *), do_fio(integer *, char *, ftnlen), e_wsfe(void); /* Local variables */ complex a[1] /* was [1][1] */, x[1], y[1], beta; extern /* Subroutine */ int cher_(char *, integer *, real *, complex *, integer *, complex *, integer *, ftnlen), chpr_(char *, integer *, real *, complex *, integer *, complex *, ftnlen), cher2_(char *, integer *, complex *, complex *, integer *, complex *, integer *, complex *, integer *, ftnlen), chpr2_(char *, integer *, complex * , complex *, integer *, complex *, integer *, complex *, ftnlen), cgerc_(integer *, integer *, complex *, complex *, integer *, complex *, integer *, complex *, integer *); complex alpha; extern /* Subroutine */ int cgbmv_(char *, integer *, integer *, integer * , integer *, complex *, complex *, integer *, complex *, integer * , complex *, complex *, integer *, ftnlen), chbmv_(char *, integer *, integer *, complex *, complex *, integer *, complex *, integer *, complex *, complex *, integer *, ftnlen), cgemv_(char * , integer *, integer *, complex *, complex *, integer *, complex * , integer *, complex *, complex *, integer *, ftnlen), chemv_( char *, integer *, complex *, complex *, integer *, complex *, integer *, complex *, complex *, integer *, ftnlen), cgeru_( integer *, integer *, complex *, complex *, integer *, complex *, integer *, complex *, integer *), ctbmv_(char *, char *, char *, integer *, integer *, complex *, integer *, complex *, integer *, ftnlen, ftnlen, ftnlen), chpmv_(char *, integer *, complex *, complex *, complex *, integer *, complex *, complex *, integer *, ftnlen), ctbsv_(char *, char *, char *, integer *, integer *, complex *, integer *, complex *, integer *, ftnlen, ftnlen, ftnlen), ctpmv_(char *, char *, char *, integer *, complex *, complex *, integer *, ftnlen, ftnlen, ftnlen), ctrmv_(char *, char *, char *, integer *, complex *, integer *, complex *, integer *, ftnlen, ftnlen, ftnlen), ctpsv_(char *, char *, char *, integer *, complex *, complex *, integer *, ftnlen, ftnlen, ftnlen), ctrsv_(char *, char *, char *, integer *, complex *, integer *, complex *, integer *, ftnlen, ftnlen, ftnlen); real ralpha; extern /* Subroutine */ int chkxer_(char *, integer *, integer *, logical *, logical *, ftnlen); /* Fortran I/O blocks */ static cilist io___399 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___400 = { 0, 0, 0, fmt_9998, 0 }; /* Tests the error exits from the Level 2 Blas. */ /* Requires a special version of the error-handling routine XERBLA. */ /* ALPHA, RALPHA, BETA, A, X and Y should not need to be defined. */ /* Auxiliary routine for test program for Level 2 Blas. */ /* -- Written on 10-August-1987. */ /* Richard Hanson, Sandia National Labs. */ /* Jeremy Du Croz, NAG Central Office. */ /* .. Scalar Arguments .. */ /* .. Scalars in Common .. */ /* .. Local Scalars .. */ /* .. Local Arrays .. */ /* .. External Subroutines .. */ /* .. Common blocks .. */ /* .. Executable Statements .. */ /* OK is set to .FALSE. by the special version of XERBLA or by CHKXER */ /* if anything is wrong. */ infoc_1.ok = TRUE_; /* LERR is set to .TRUE. by the special version of XERBLA each time */ /* it is called, and is then tested and re-set by CHKXER. */ infoc_1.lerr = FALSE_; switch (*isnum) { case 1: goto L10; case 2: goto L20; case 3: goto L30; case 4: goto L40; case 5: goto L50; case 6: goto L60; case 7: goto L70; case 8: goto L80; case 9: goto L90; case 10: goto L100; case 11: goto L110; case 12: goto L120; case 13: goto L130; case 14: goto L140; case 15: goto L150; case 16: goto L160; case 17: goto L170; } L10: infoc_1.infot = 1; cgemv_("/", &c__0, &c__0, &alpha, a, &c__1, x, &c__1, &beta, y, &c__1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; cgemv_("N", &c_n1, &c__0, &alpha, a, &c__1, x, &c__1, &beta, y, &c__1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; cgemv_("N", &c__0, &c_n1, &alpha, a, &c__1, x, &c__1, &beta, y, &c__1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; cgemv_("N", &c__2, &c__0, &alpha, a, &c__1, x, &c__1, &beta, y, &c__1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 8; cgemv_("N", &c__0, &c__0, &alpha, a, &c__1, x, &c__0, &beta, y, &c__1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; cgemv_("N", &c__0, &c__0, &alpha, a, &c__1, x, &c__1, &beta, y, &c__0, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L180; L20: infoc_1.infot = 1; cgbmv_("/", &c__0, &c__0, &c__0, &c__0, &alpha, a, &c__1, x, &c__1, &beta, y, &c__1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; cgbmv_("N", &c_n1, &c__0, &c__0, &c__0, &alpha, a, &c__1, x, &c__1, &beta, y, &c__1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; cgbmv_("N", &c__0, &c_n1, &c__0, &c__0, &alpha, a, &c__1, x, &c__1, &beta, y, &c__1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; cgbmv_("N", &c__0, &c__0, &c_n1, &c__0, &alpha, a, &c__1, x, &c__1, &beta, y, &c__1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; cgbmv_("N", &c__2, &c__0, &c__0, &c_n1, &alpha, a, &c__1, x, &c__1, &beta, y, &c__1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 8; cgbmv_("N", &c__0, &c__0, &c__1, &c__0, &alpha, a, &c__1, x, &c__1, &beta, y, &c__1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 10; cgbmv_("N", &c__0, &c__0, &c__0, &c__0, &alpha, a, &c__1, x, &c__0, &beta, y, &c__1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 13; cgbmv_("N", &c__0, &c__0, &c__0, &c__0, &alpha, a, &c__1, x, &c__1, &beta, y, &c__0, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L180; L30: infoc_1.infot = 1; chemv_("/", &c__0, &alpha, a, &c__1, x, &c__1, &beta, y, &c__1, (ftnlen)1) ; chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; chemv_("U", &c_n1, &alpha, a, &c__1, x, &c__1, &beta, y, &c__1, (ftnlen)1) ; chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; chemv_("U", &c__2, &alpha, a, &c__1, x, &c__1, &beta, y, &c__1, (ftnlen)1) ; chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; chemv_("U", &c__0, &alpha, a, &c__1, x, &c__0, &beta, y, &c__1, (ftnlen)1) ; chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 10; chemv_("U", &c__0, &alpha, a, &c__1, x, &c__1, &beta, y, &c__0, (ftnlen)1) ; chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L180; L40: infoc_1.infot = 1; chbmv_("/", &c__0, &c__0, &alpha, a, &c__1, x, &c__1, &beta, y, &c__1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; chbmv_("U", &c_n1, &c__0, &alpha, a, &c__1, x, &c__1, &beta, y, &c__1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; chbmv_("U", &c__0, &c_n1, &alpha, a, &c__1, x, &c__1, &beta, y, &c__1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; chbmv_("U", &c__0, &c__1, &alpha, a, &c__1, x, &c__1, &beta, y, &c__1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 8; chbmv_("U", &c__0, &c__0, &alpha, a, &c__1, x, &c__0, &beta, y, &c__1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; chbmv_("U", &c__0, &c__0, &alpha, a, &c__1, x, &c__1, &beta, y, &c__0, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L180; L50: infoc_1.infot = 1; chpmv_("/", &c__0, &alpha, a, x, &c__1, &beta, y, &c__1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; chpmv_("U", &c_n1, &alpha, a, x, &c__1, &beta, y, &c__1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; chpmv_("U", &c__0, &alpha, a, x, &c__0, &beta, y, &c__1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; chpmv_("U", &c__0, &alpha, a, x, &c__1, &beta, y, &c__0, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L180; L60: infoc_1.infot = 1; ctrmv_("/", "N", "N", &c__0, a, &c__1, x, &c__1, (ftnlen)1, (ftnlen)1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; ctrmv_("U", "/", "N", &c__0, a, &c__1, x, &c__1, (ftnlen)1, (ftnlen)1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; ctrmv_("U", "N", "/", &c__0, a, &c__1, x, &c__1, (ftnlen)1, (ftnlen)1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; ctrmv_("U", "N", "N", &c_n1, a, &c__1, x, &c__1, (ftnlen)1, (ftnlen)1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; ctrmv_("U", "N", "N", &c__2, a, &c__1, x, &c__1, (ftnlen)1, (ftnlen)1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 8; ctrmv_("U", "N", "N", &c__0, a, &c__1, x, &c__0, (ftnlen)1, (ftnlen)1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L180; L70: infoc_1.infot = 1; ctbmv_("/", "N", "N", &c__0, &c__0, a, &c__1, x, &c__1, (ftnlen)1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; ctbmv_("U", "/", "N", &c__0, &c__0, a, &c__1, x, &c__1, (ftnlen)1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; ctbmv_("U", "N", "/", &c__0, &c__0, a, &c__1, x, &c__1, (ftnlen)1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; ctbmv_("U", "N", "N", &c_n1, &c__0, a, &c__1, x, &c__1, (ftnlen)1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; ctbmv_("U", "N", "N", &c__0, &c_n1, a, &c__1, x, &c__1, (ftnlen)1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; ctbmv_("U", "N", "N", &c__0, &c__1, a, &c__1, x, &c__1, (ftnlen)1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; ctbmv_("U", "N", "N", &c__0, &c__0, a, &c__1, x, &c__0, (ftnlen)1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L180; L80: infoc_1.infot = 1; ctpmv_("/", "N", "N", &c__0, a, x, &c__1, (ftnlen)1, (ftnlen)1, (ftnlen)1) ; chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; ctpmv_("U", "/", "N", &c__0, a, x, &c__1, (ftnlen)1, (ftnlen)1, (ftnlen)1) ; chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; ctpmv_("U", "N", "/", &c__0, a, x, &c__1, (ftnlen)1, (ftnlen)1, (ftnlen)1) ; chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; ctpmv_("U", "N", "N", &c_n1, a, x, &c__1, (ftnlen)1, (ftnlen)1, (ftnlen)1) ; chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; ctpmv_("U", "N", "N", &c__0, a, x, &c__0, (ftnlen)1, (ftnlen)1, (ftnlen)1) ; chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L180; L90: infoc_1.infot = 1; ctrsv_("/", "N", "N", &c__0, a, &c__1, x, &c__1, (ftnlen)1, (ftnlen)1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; ctrsv_("U", "/", "N", &c__0, a, &c__1, x, &c__1, (ftnlen)1, (ftnlen)1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; ctrsv_("U", "N", "/", &c__0, a, &c__1, x, &c__1, (ftnlen)1, (ftnlen)1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; ctrsv_("U", "N", "N", &c_n1, a, &c__1, x, &c__1, (ftnlen)1, (ftnlen)1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; ctrsv_("U", "N", "N", &c__2, a, &c__1, x, &c__1, (ftnlen)1, (ftnlen)1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 8; ctrsv_("U", "N", "N", &c__0, a, &c__1, x, &c__0, (ftnlen)1, (ftnlen)1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L180; L100: infoc_1.infot = 1; ctbsv_("/", "N", "N", &c__0, &c__0, a, &c__1, x, &c__1, (ftnlen)1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; ctbsv_("U", "/", "N", &c__0, &c__0, a, &c__1, x, &c__1, (ftnlen)1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; ctbsv_("U", "N", "/", &c__0, &c__0, a, &c__1, x, &c__1, (ftnlen)1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; ctbsv_("U", "N", "N", &c_n1, &c__0, a, &c__1, x, &c__1, (ftnlen)1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; ctbsv_("U", "N", "N", &c__0, &c_n1, a, &c__1, x, &c__1, (ftnlen)1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; ctbsv_("U", "N", "N", &c__0, &c__1, a, &c__1, x, &c__1, (ftnlen)1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; ctbsv_("U", "N", "N", &c__0, &c__0, a, &c__1, x, &c__0, (ftnlen)1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L180; L110: infoc_1.infot = 1; ctpsv_("/", "N", "N", &c__0, a, x, &c__1, (ftnlen)1, (ftnlen)1, (ftnlen)1) ; chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; ctpsv_("U", "/", "N", &c__0, a, x, &c__1, (ftnlen)1, (ftnlen)1, (ftnlen)1) ; chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; ctpsv_("U", "N", "/", &c__0, a, x, &c__1, (ftnlen)1, (ftnlen)1, (ftnlen)1) ; chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; ctpsv_("U", "N", "N", &c_n1, a, x, &c__1, (ftnlen)1, (ftnlen)1, (ftnlen)1) ; chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; ctpsv_("U", "N", "N", &c__0, a, x, &c__0, (ftnlen)1, (ftnlen)1, (ftnlen)1) ; chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L180; L120: infoc_1.infot = 1; cgerc_(&c_n1, &c__0, &alpha, x, &c__1, y, &c__1, a, &c__1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; cgerc_(&c__0, &c_n1, &alpha, x, &c__1, y, &c__1, a, &c__1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; cgerc_(&c__0, &c__0, &alpha, x, &c__0, y, &c__1, a, &c__1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; cgerc_(&c__0, &c__0, &alpha, x, &c__1, y, &c__0, a, &c__1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; cgerc_(&c__2, &c__0, &alpha, x, &c__1, y, &c__1, a, &c__1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L180; L130: infoc_1.infot = 1; cgeru_(&c_n1, &c__0, &alpha, x, &c__1, y, &c__1, a, &c__1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; cgeru_(&c__0, &c_n1, &alpha, x, &c__1, y, &c__1, a, &c__1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; cgeru_(&c__0, &c__0, &alpha, x, &c__0, y, &c__1, a, &c__1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; cgeru_(&c__0, &c__0, &alpha, x, &c__1, y, &c__0, a, &c__1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; cgeru_(&c__2, &c__0, &alpha, x, &c__1, y, &c__1, a, &c__1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L180; L140: infoc_1.infot = 1; cher_("/", &c__0, &ralpha, x, &c__1, a, &c__1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; cher_("U", &c_n1, &ralpha, x, &c__1, a, &c__1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; cher_("U", &c__0, &ralpha, x, &c__0, a, &c__1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; cher_("U", &c__2, &ralpha, x, &c__1, a, &c__1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L180; L150: infoc_1.infot = 1; chpr_("/", &c__0, &ralpha, x, &c__1, a, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; chpr_("U", &c_n1, &ralpha, x, &c__1, a, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; chpr_("U", &c__0, &ralpha, x, &c__0, a, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L180; L160: infoc_1.infot = 1; cher2_("/", &c__0, &alpha, x, &c__1, y, &c__1, a, &c__1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; cher2_("U", &c_n1, &alpha, x, &c__1, y, &c__1, a, &c__1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; cher2_("U", &c__0, &alpha, x, &c__0, y, &c__1, a, &c__1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; cher2_("U", &c__0, &alpha, x, &c__1, y, &c__0, a, &c__1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; cher2_("U", &c__2, &alpha, x, &c__1, y, &c__1, a, &c__1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L180; L170: infoc_1.infot = 1; chpr2_("/", &c__0, &alpha, x, &c__1, y, &c__1, a, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; chpr2_("U", &c_n1, &alpha, x, &c__1, y, &c__1, a, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; chpr2_("U", &c__0, &alpha, x, &c__0, y, &c__1, a, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; chpr2_("U", &c__0, &alpha, x, &c__1, y, &c__0, a, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); L180: if (infoc_1.ok) { io___399.ciunit = *nout; s_wsfe(&io___399); do_fio(&c__1, srnamt, (ftnlen)6); e_wsfe(); } else { io___400.ciunit = *nout; s_wsfe(&io___400); do_fio(&c__1, srnamt, (ftnlen)6); e_wsfe(); } return 0; /* End of CCHKE. */ } /* cchke_ */ /* Subroutine */ int cmake_(char *type__, char *uplo, char *diag, integer *m, integer *n, complex *a, integer *nmax, complex *aa, integer *lda, integer *kl, integer *ku, logical *reset, complex *transl, ftnlen type_len, ftnlen uplo_len, ftnlen diag_len) { /* System generated locals */ integer a_dim1, a_offset, i__1, i__2, i__3, i__4; real r__1; complex q__1, q__2; /* Builtin functions */ void r_cnjg(complex *, complex *); integer s_cmp(const char *, const char *, ftnlen, ftnlen); /* Local variables */ integer i__, j, i1, i2, i3, jj, kk; logical gen, tri, sym; extern /* Complex */ void cbeg_(complex *, logical *); integer ibeg, iend, ioff; logical unit, lower, upper; /* Generates values for an M by N matrix A within the bandwidth */ /* defined by KL and KU. */ /* Stores the values in the array AA in the data structure required */ /* by the routine, with unwanted elements set to rogue value. */ /* TYPE is 'GE', 'GB', 'HE', 'HB', 'HP', 'TR', 'TB' OR 'TP'. */ /* Auxiliary routine for test program for Level 2 Blas. */ /* -- Written on 10-August-1987. */ /* Richard Hanson, Sandia National Labs. */ /* Jeremy Du Croz, NAG Central Office. */ /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Scalars .. */ /* .. External Functions .. */ /* .. Intrinsic Functions .. */ /* .. Executable Statements .. */ /* Parameter adjustments */ a_dim1 = *nmax; a_offset = 1 + a_dim1; a -= a_offset; --aa; /* Function Body */ gen = *(unsigned char *)type__ == 'G'; sym = *(unsigned char *)type__ == 'H'; tri = *(unsigned char *)type__ == 'T'; upper = (sym || tri) && *(unsigned char *)uplo == 'U'; lower = (sym || tri) && *(unsigned char *)uplo == 'L'; unit = tri && *(unsigned char *)diag == 'U'; /* Generate data in array A. */ i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = *m; for (i__ = 1; i__ <= i__2; ++i__) { if (gen || upper && i__ <= j || lower && i__ >= j) { if (i__ <= j && j - i__ <= *ku || i__ >= j && i__ - j <= *kl) { i__3 = i__ + j * a_dim1; cbeg_(&q__2, reset); q__1.r = q__2.r + transl->r, q__1.i = q__2.i + transl->i; a[i__3].r = q__1.r, a[i__3].i = q__1.i; } else { i__3 = i__ + j * a_dim1; a[i__3].r = 0.f, a[i__3].i = 0.f; } if (i__ != j) { if (sym) { i__3 = j + i__ * a_dim1; r_cnjg(&q__1, &a[i__ + j * a_dim1]); a[i__3].r = q__1.r, a[i__3].i = q__1.i; } else if (tri) { i__3 = j + i__ * a_dim1; a[i__3].r = 0.f, a[i__3].i = 0.f; } } } /* L10: */ } if (sym) { i__2 = j + j * a_dim1; i__3 = j + j * a_dim1; r__1 = a[i__3].r; q__1.r = r__1, q__1.i = 0.f; a[i__2].r = q__1.r, a[i__2].i = q__1.i; } if (tri) { i__2 = j + j * a_dim1; i__3 = j + j * a_dim1; q__1.r = a[i__3].r + 1.f, q__1.i = a[i__3].i + 0.f; a[i__2].r = q__1.r, a[i__2].i = q__1.i; } if (unit) { i__2 = j + j * a_dim1; a[i__2].r = 1.f, a[i__2].i = 0.f; } /* L20: */ } /* Store elements in array AS in data structure required by routine. */ if (s_cmp(type__, "GE", (ftnlen)2, (ftnlen)2) == 0) { i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = *m; for (i__ = 1; i__ <= i__2; ++i__) { i__3 = i__ + (j - 1) * *lda; i__4 = i__ + j * a_dim1; aa[i__3].r = a[i__4].r, aa[i__3].i = a[i__4].i; /* L30: */ } i__2 = *lda; for (i__ = *m + 1; i__ <= i__2; ++i__) { i__3 = i__ + (j - 1) * *lda; aa[i__3].r = -1e10f, aa[i__3].i = 1e10f; /* L40: */ } /* L50: */ } } else if (s_cmp(type__, "GB", (ftnlen)2, (ftnlen)2) == 0) { i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = *ku + 1 - j; for (i1 = 1; i1 <= i__2; ++i1) { i__3 = i1 + (j - 1) * *lda; aa[i__3].r = -1e10f, aa[i__3].i = 1e10f; /* L60: */ } /* Computing MIN */ i__3 = *kl + *ku + 1, i__4 = *ku + 1 + *m - j; i__2 = min(i__3,i__4); for (i2 = i1; i2 <= i__2; ++i2) { i__3 = i2 + (j - 1) * *lda; i__4 = i2 + j - *ku - 1 + j * a_dim1; aa[i__3].r = a[i__4].r, aa[i__3].i = a[i__4].i; /* L70: */ } i__2 = *lda; for (i3 = i2; i3 <= i__2; ++i3) { i__3 = i3 + (j - 1) * *lda; aa[i__3].r = -1e10f, aa[i__3].i = 1e10f; /* L80: */ } /* L90: */ } } else if (s_cmp(type__, "HE", (ftnlen)2, (ftnlen)2) == 0 || s_cmp(type__, "TR", (ftnlen)2, (ftnlen)2) == 0) { i__1 = *n; for (j = 1; j <= i__1; ++j) { if (upper) { ibeg = 1; if (unit) { iend = j - 1; } else { iend = j; } } else { if (unit) { ibeg = j + 1; } else { ibeg = j; } iend = *n; } i__2 = ibeg - 1; for (i__ = 1; i__ <= i__2; ++i__) { i__3 = i__ + (j - 1) * *lda; aa[i__3].r = -1e10f, aa[i__3].i = 1e10f; /* L100: */ } i__2 = iend; for (i__ = ibeg; i__ <= i__2; ++i__) { i__3 = i__ + (j - 1) * *lda; i__4 = i__ + j * a_dim1; aa[i__3].r = a[i__4].r, aa[i__3].i = a[i__4].i; /* L110: */ } i__2 = *lda; for (i__ = iend + 1; i__ <= i__2; ++i__) { i__3 = i__ + (j - 1) * *lda; aa[i__3].r = -1e10f, aa[i__3].i = 1e10f; /* L120: */ } if (sym) { jj = j + (j - 1) * *lda; i__2 = jj; i__3 = jj; r__1 = aa[i__3].r; q__1.r = r__1, q__1.i = -1e10f; aa[i__2].r = q__1.r, aa[i__2].i = q__1.i; } /* L130: */ } } else if (s_cmp(type__, "HB", (ftnlen)2, (ftnlen)2) == 0 || s_cmp(type__, "TB", (ftnlen)2, (ftnlen)2) == 0) { i__1 = *n; for (j = 1; j <= i__1; ++j) { if (upper) { kk = *kl + 1; /* Computing MAX */ i__2 = 1, i__3 = *kl + 2 - j; ibeg = max(i__2,i__3); if (unit) { iend = *kl; } else { iend = *kl + 1; } } else { kk = 1; if (unit) { ibeg = 2; } else { ibeg = 1; } /* Computing MIN */ i__2 = *kl + 1, i__3 = *m + 1 - j; iend = min(i__2,i__3); } i__2 = ibeg - 1; for (i__ = 1; i__ <= i__2; ++i__) { i__3 = i__ + (j - 1) * *lda; aa[i__3].r = -1e10f, aa[i__3].i = 1e10f; /* L140: */ } i__2 = iend; for (i__ = ibeg; i__ <= i__2; ++i__) { i__3 = i__ + (j - 1) * *lda; i__4 = i__ + j - kk + j * a_dim1; aa[i__3].r = a[i__4].r, aa[i__3].i = a[i__4].i; /* L150: */ } i__2 = *lda; for (i__ = iend + 1; i__ <= i__2; ++i__) { i__3 = i__ + (j - 1) * *lda; aa[i__3].r = -1e10f, aa[i__3].i = 1e10f; /* L160: */ } if (sym) { jj = kk + (j - 1) * *lda; i__2 = jj; i__3 = jj; r__1 = aa[i__3].r; q__1.r = r__1, q__1.i = -1e10f; aa[i__2].r = q__1.r, aa[i__2].i = q__1.i; } /* L170: */ } } else if (s_cmp(type__, "HP", (ftnlen)2, (ftnlen)2) == 0 || s_cmp(type__, "TP", (ftnlen)2, (ftnlen)2) == 0) { ioff = 0; i__1 = *n; for (j = 1; j <= i__1; ++j) { if (upper) { ibeg = 1; iend = j; } else { ibeg = j; iend = *n; } i__2 = iend; for (i__ = ibeg; i__ <= i__2; ++i__) { ++ioff; i__3 = ioff; i__4 = i__ + j * a_dim1; aa[i__3].r = a[i__4].r, aa[i__3].i = a[i__4].i; if (i__ == j) { if (unit) { i__3 = ioff; aa[i__3].r = -1e10f, aa[i__3].i = 1e10f; } if (sym) { i__3 = ioff; i__4 = ioff; r__1 = aa[i__4].r; q__1.r = r__1, q__1.i = -1e10f; aa[i__3].r = q__1.r, aa[i__3].i = q__1.i; } } /* L180: */ } /* L190: */ } } return 0; /* End of CMAKE. */ } /* cmake_ */ /* Subroutine */ int cmvch_(char *trans, integer *m, integer *n, complex * alpha, complex *a, integer *nmax, complex *x, integer *incx, complex * beta, complex *y, integer *incy, complex *yt, real *g, complex *yy, real *eps, real *err, logical *fatal, integer *nout, logical *mv, ftnlen trans_len) { /* Format strings */ static char fmt_9999[] = "(\002 ******* FATAL ERROR - COMPUTED RESULT IS" " LESS THAN HAL\002,\002F ACCURATE *******\002,/\002 " " EXPECTED RE\002,\002SULT COMPUTED R" "ESULT\002)"; static char fmt_9998[] = "(1x,i7,2(\002 (\002,g15.6,\002,\002,g15.6," "\002)\002))"; /* System generated locals */ integer a_dim1, a_offset, i__1, i__2, i__3, i__4, i__5, i__6; real r__1, r__2, r__3, r__4, r__5, r__6; complex q__1, q__2, q__3; /* Builtin functions */ double r_imag(complex *); void r_cnjg(complex *, complex *); double c_abs(const complex *), sqrt(doublereal); integer s_wsfe(cilist *), e_wsfe(void), do_fio(integer *, char *, ftnlen); /* Local variables */ integer i__, j, ml, nl, iy, jx, kx, ky; real erri; logical tran, ctran; integer incxl, incyl; /* Fortran I/O blocks */ static cilist io___430 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___431 = { 0, 0, 0, fmt_9998, 0 }; static cilist io___432 = { 0, 0, 0, fmt_9998, 0 }; /* Checks the results of the computational tests. */ /* Auxiliary routine for test program for Level 2 Blas. */ /* -- Written on 10-August-1987. */ /* Richard Hanson, Sandia National Labs. */ /* Jeremy Du Croz, NAG Central Office. */ /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Scalars .. */ /* .. Intrinsic Functions .. */ /* .. Statement Functions .. */ /* .. Statement Function definitions .. */ /* .. Executable Statements .. */ /* Parameter adjustments */ a_dim1 = *nmax; a_offset = 1 + a_dim1; a -= a_offset; --x; --y; --yt; --g; --yy; /* Function Body */ tran = *(unsigned char *)trans == 'T'; ctran = *(unsigned char *)trans == 'C'; if (tran || ctran) { ml = *n; nl = *m; } else { ml = *m; nl = *n; } if (*incx < 0) { kx = nl; incxl = -1; } else { kx = 1; incxl = 1; } if (*incy < 0) { ky = ml; incyl = -1; } else { ky = 1; incyl = 1; } /* Compute expected result in YT using data in A, X and Y. */ /* Compute gauges in G. */ iy = ky; i__1 = ml; for (i__ = 1; i__ <= i__1; ++i__) { i__2 = iy; yt[i__2].r = 0.f, yt[i__2].i = 0.f; g[iy] = 0.f; jx = kx; if (tran) { i__2 = nl; for (j = 1; j <= i__2; ++j) { i__3 = iy; i__4 = iy; i__5 = j + i__ * a_dim1; i__6 = jx; q__2.r = a[i__5].r * x[i__6].r - a[i__5].i * x[i__6].i, q__2.i = a[i__5].r * x[i__6].i + a[i__5].i * x[i__6] .r; q__1.r = yt[i__4].r + q__2.r, q__1.i = yt[i__4].i + q__2.i; yt[i__3].r = q__1.r, yt[i__3].i = q__1.i; i__3 = j + i__ * a_dim1; i__4 = jx; g[iy] += ((r__1 = a[i__3].r, abs(r__1)) + (r__2 = r_imag(&a[j + i__ * a_dim1]), abs(r__2))) * ((r__3 = x[i__4].r, abs(r__3)) + (r__4 = r_imag(&x[jx]), abs(r__4))); jx += incxl; /* L10: */ } } else if (ctran) { i__2 = nl; for (j = 1; j <= i__2; ++j) { i__3 = iy; i__4 = iy; r_cnjg(&q__3, &a[j + i__ * a_dim1]); i__5 = jx; q__2.r = q__3.r * x[i__5].r - q__3.i * x[i__5].i, q__2.i = q__3.r * x[i__5].i + q__3.i * x[i__5].r; q__1.r = yt[i__4].r + q__2.r, q__1.i = yt[i__4].i + q__2.i; yt[i__3].r = q__1.r, yt[i__3].i = q__1.i; i__3 = j + i__ * a_dim1; i__4 = jx; g[iy] += ((r__1 = a[i__3].r, abs(r__1)) + (r__2 = r_imag(&a[j + i__ * a_dim1]), abs(r__2))) * ((r__3 = x[i__4].r, abs(r__3)) + (r__4 = r_imag(&x[jx]), abs(r__4))); jx += incxl; /* L20: */ } } else { i__2 = nl; for (j = 1; j <= i__2; ++j) { i__3 = iy; i__4 = iy; i__5 = i__ + j * a_dim1; i__6 = jx; q__2.r = a[i__5].r * x[i__6].r - a[i__5].i * x[i__6].i, q__2.i = a[i__5].r * x[i__6].i + a[i__5].i * x[i__6] .r; q__1.r = yt[i__4].r + q__2.r, q__1.i = yt[i__4].i + q__2.i; yt[i__3].r = q__1.r, yt[i__3].i = q__1.i; i__3 = i__ + j * a_dim1; i__4 = jx; g[iy] += ((r__1 = a[i__3].r, abs(r__1)) + (r__2 = r_imag(&a[ i__ + j * a_dim1]), abs(r__2))) * ((r__3 = x[i__4].r, abs(r__3)) + (r__4 = r_imag(&x[jx]), abs(r__4))); jx += incxl; /* L30: */ } } i__2 = iy; i__3 = iy; q__2.r = alpha->r * yt[i__3].r - alpha->i * yt[i__3].i, q__2.i = alpha->r * yt[i__3].i + alpha->i * yt[i__3].r; i__4 = iy; q__3.r = beta->r * y[i__4].r - beta->i * y[i__4].i, q__3.i = beta->r * y[i__4].i + beta->i * y[i__4].r; q__1.r = q__2.r + q__3.r, q__1.i = q__2.i + q__3.i; yt[i__2].r = q__1.r, yt[i__2].i = q__1.i; i__2 = iy; g[iy] = ((r__1 = alpha->r, abs(r__1)) + (r__2 = r_imag(alpha), abs( r__2))) * g[iy] + ((r__3 = beta->r, abs(r__3)) + (r__4 = r_imag(beta), abs(r__4))) * ((r__5 = y[i__2].r, abs(r__5)) + ( r__6 = r_imag(&y[iy]), abs(r__6))); iy += incyl; /* L40: */ } /* Compute the error ratio for this result. */ *err = 0.f; i__1 = ml; for (i__ = 1; i__ <= i__1; ++i__) { i__2 = i__; i__3 = (i__ - 1) * abs(*incy) + 1; q__1.r = yt[i__2].r - yy[i__3].r, q__1.i = yt[i__2].i - yy[i__3].i; erri = c_abs(&q__1) / *eps; if (g[i__] != 0.f) { erri /= g[i__]; } *err = max(*err,erri); if (*err * sqrt(*eps) >= 1.f) { goto L60; } /* L50: */ } /* If the loop completes, all results are at least half accurate. */ goto L80; /* Report fatal error. */ L60: *fatal = TRUE_; io___430.ciunit = *nout; s_wsfe(&io___430); e_wsfe(); i__1 = ml; for (i__ = 1; i__ <= i__1; ++i__) { if (*mv) { io___431.ciunit = *nout; s_wsfe(&io___431); do_fio(&c__1, (char *)&i__, (ftnlen)sizeof(integer)); do_fio(&c__2, (char *)&yt[i__], (ftnlen)sizeof(real)); do_fio(&c__2, (char *)&yy[(i__ - 1) * abs(*incy) + 1], (ftnlen) sizeof(real)); e_wsfe(); } else { io___432.ciunit = *nout; s_wsfe(&io___432); do_fio(&c__1, (char *)&i__, (ftnlen)sizeof(integer)); do_fio(&c__2, (char *)&yy[(i__ - 1) * abs(*incy) + 1], (ftnlen) sizeof(real)); do_fio(&c__2, (char *)&yt[i__], (ftnlen)sizeof(real)); e_wsfe(); } /* L70: */ } L80: return 0; /* End of CMVCH. */ } /* cmvch_ */ logical lce_(complex *ri, complex *rj, integer *lr) { /* System generated locals */ integer i__1, i__2, i__3; logical ret_val; /* Local variables */ integer i__; /* Tests if two arrays are identical. */ /* Auxiliary routine for test program for Level 2 Blas. */ /* -- Written on 10-August-1987. */ /* Richard Hanson, Sandia National Labs. */ /* Jeremy Du Croz, NAG Central Office. */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Scalars .. */ /* .. Executable Statements .. */ /* Parameter adjustments */ --rj; --ri; /* Function Body */ i__1 = *lr; for (i__ = 1; i__ <= i__1; ++i__) { i__2 = i__; i__3 = i__; if (ri[i__2].r != rj[i__3].r || ri[i__2].i != rj[i__3].i) { goto L20; } /* L10: */ } ret_val = TRUE_; goto L30; L20: ret_val = FALSE_; L30: return ret_val; /* End of LCE. */ } /* lce_ */ logical lceres_(char *type__, char *uplo, integer *m, integer *n, complex *aa, complex *as, integer *lda, ftnlen type_len, ftnlen uplo_len) { /* System generated locals */ integer aa_dim1, aa_offset, as_dim1, as_offset, i__1, i__2, i__3, i__4; logical ret_val; /* Builtin functions */ integer s_cmp(const char *, const char *, ftnlen, ftnlen); /* Local variables */ integer i__, j, ibeg, iend; logical upper; /* Tests if selected elements in two arrays are equal. */ /* TYPE is 'GE', 'HE' or 'HP'. */ /* Auxiliary routine for test program for Level 2 Blas. */ /* -- Written on 10-August-1987. */ /* Richard Hanson, Sandia National Labs. */ /* Jeremy Du Croz, NAG Central Office. */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Scalars .. */ /* .. Executable Statements .. */ /* Parameter adjustments */ as_dim1 = *lda; as_offset = 1 + as_dim1; as -= as_offset; aa_dim1 = *lda; aa_offset = 1 + aa_dim1; aa -= aa_offset; /* Function Body */ upper = *(unsigned char *)uplo == 'U'; if (s_cmp(type__, "GE", (ftnlen)2, (ftnlen)2) == 0) { i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = *lda; for (i__ = *m + 1; i__ <= i__2; ++i__) { i__3 = i__ + j * aa_dim1; i__4 = i__ + j * as_dim1; if (aa[i__3].r != as[i__4].r || aa[i__3].i != as[i__4].i) { goto L70; } /* L10: */ } /* L20: */ } } else if (s_cmp(type__, "HE", (ftnlen)2, (ftnlen)2) == 0) { i__1 = *n; for (j = 1; j <= i__1; ++j) { if (upper) { ibeg = 1; iend = j; } else { ibeg = j; iend = *n; } i__2 = ibeg - 1; for (i__ = 1; i__ <= i__2; ++i__) { i__3 = i__ + j * aa_dim1; i__4 = i__ + j * as_dim1; if (aa[i__3].r != as[i__4].r || aa[i__3].i != as[i__4].i) { goto L70; } /* L30: */ } i__2 = *lda; for (i__ = iend + 1; i__ <= i__2; ++i__) { i__3 = i__ + j * aa_dim1; i__4 = i__ + j * as_dim1; if (aa[i__3].r != as[i__4].r || aa[i__3].i != as[i__4].i) { goto L70; } /* L40: */ } /* L50: */ } } ret_val = TRUE_; goto L80; L70: ret_val = FALSE_; L80: return ret_val; /* End of LCERES. */ } /* lceres_ */ /* Complex */ void cbeg_(complex * ret_val, logical *reset) { /* System generated locals */ real r__1, r__2; complex q__1; /* Local variables */ static integer i__, j, ic, mi, mj; /* Generates complex numbers as pairs of random numbers uniformly */ /* distributed between -0.5 and 0.5. */ /* Auxiliary routine for test program for Level 2 Blas. */ /* -- Written on 10-August-1987. */ /* Richard Hanson, Sandia National Labs. */ /* Jeremy Du Croz, NAG Central Office. */ /* .. Scalar Arguments .. */ /* .. Local Scalars .. */ /* .. Save statement .. */ /* .. Intrinsic Functions .. */ /* .. Executable Statements .. */ if (*reset) { /* Initialize local variables. */ mi = 891; mj = 457; i__ = 7; j = 7; ic = 0; *reset = FALSE_; } /* The sequence of values of I or J is bounded between 1 and 999. */ /* If initial I or J = 1,2,3,6,7 or 9, the period will be 50. */ /* If initial I or J = 4 or 8, the period will be 25. */ /* If initial I or J = 5, the period will be 10. */ /* IC is used to break up the period by skipping 1 value of I or J */ /* in 6. */ ++ic; L10: i__ *= mi; j *= mj; i__ -= i__ / 1000 * 1000; j -= j / 1000 * 1000; if (ic >= 5) { ic = 0; goto L10; } r__1 = (i__ - 500) / 1001.f; r__2 = (j - 500) / 1001.f; q__1.r = r__1, q__1.i = r__2; ret_val->r = q__1.r, ret_val->i = q__1.i; return ; /* End of CBEG. */ } /* cbeg_ */ real sdiff_(real *x, real *y) { /* System generated locals */ real ret_val; /* Auxiliary routine for test program for Level 2 Blas. */ /* -- Written on 10-August-1987. */ /* Richard Hanson, Sandia National Labs. */ /* .. Scalar Arguments .. */ /* .. Executable Statements .. */ ret_val = *x - *y; return ret_val; /* End of SDIFF. */ } /* sdiff_ */ /* Subroutine */ int chkxer_(char *srnamt, integer *infot, integer *nout, logical *lerr, logical *ok, ftnlen srnamt_len) { /* Format strings */ static char fmt_9999[] = "(\002 ***** ILLEGAL VALUE OF PARAMETER NUMBER" " \002,i2,\002 NOT D\002,\002ETECTED BY \002,a6,\002 *****\002)"; /* Builtin functions */ integer s_wsfe(cilist *), do_fio(integer *, char *, ftnlen), e_wsfe(void); /* Fortran I/O blocks */ static cilist io___444 = { 0, 0, 0, fmt_9999, 0 }; /* Tests whether XERBLA has detected an error when it should. */ /* Auxiliary routine for test program for Level 2 Blas. */ /* -- Written on 10-August-1987. */ /* Richard Hanson, Sandia National Labs. */ /* Jeremy Du Croz, NAG Central Office. */ /* .. Scalar Arguments .. */ /* .. Executable Statements .. */ if (! (*lerr)) { io___444.ciunit = *nout; s_wsfe(&io___444); do_fio(&c__1, (char *)&(*infot), (ftnlen)sizeof(integer)); do_fio(&c__1, srnamt, (ftnlen)6); e_wsfe(); *ok = FALSE_; } *lerr = FALSE_; return 0; /* End of CHKXER. */ } /* chkxer_ */ /* Subroutine */ int xerbla_(char *srname, integer *info, ftnlen srname_len) { /* Format strings */ static char fmt_9999[] = "(\002 ******* XERBLA WAS CALLED WITH INFO =" " \002,i6,\002 INSTEAD\002,\002 OF \002,i2,\002 *******\002)"; static char fmt_9997[] = "(\002 ******* XERBLA WAS CALLED WITH INFO =" " \002,i6,\002 *******\002)"; static char fmt_9998[] = "(\002 ******* XERBLA WAS CALLED WITH SRNAME =" " \002,a6,\002 INSTE\002,\002AD OF \002,a6,\002 *******\002)"; /* Builtin functions */ integer s_wsfe(cilist *), do_fio(integer *, char *, ftnlen), e_wsfe(void), s_cmp(const char *, const char *, ftnlen, ftnlen); /* Fortran I/O blocks */ static cilist io___445 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___446 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___447 = { 0, 0, 0, fmt_9998, 0 }; /* This is a special version of XERBLA to be used only as part of */ /* the test program for testing error exits from the Level 2 BLAS */ /* routines. */ /* XERBLA is an error handler for the Level 2 BLAS routines. */ /* It is called by the Level 2 BLAS routines if an input parameter is */ /* invalid. */ /* Auxiliary routine for test program for Level 2 Blas. */ /* -- Written on 10-August-1987. */ /* Richard Hanson, Sandia National Labs. */ /* Jeremy Du Croz, NAG Central Office. */ /* .. Scalar Arguments .. */ /* .. Scalars in Common .. */ /* .. Common blocks .. */ /* .. Executable Statements .. */ infoc_2.lerr = TRUE_; if (*info != infoc_2.infot) { if (infoc_2.infot != 0) { io___445.ciunit = infoc_2.nout; s_wsfe(&io___445); do_fio(&c__1, (char *)&(*info), (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&infoc_2.infot, (ftnlen)sizeof(integer)); e_wsfe(); } else { io___446.ciunit = infoc_2.nout; s_wsfe(&io___446); do_fio(&c__1, (char *)&(*info), (ftnlen)sizeof(integer)); e_wsfe(); } infoc_2.ok = FALSE_; } if (s_cmp(srname, srnamc_1.srnamt, (ftnlen)6, (ftnlen)6) != 0) { io___447.ciunit = infoc_2.nout; s_wsfe(&io___447); do_fio(&c__1, srname, (ftnlen)6); do_fio(&c__1, srnamc_1.srnamt, (ftnlen)6); e_wsfe(); infoc_2.ok = FALSE_; } return 0; /* End of XERBLA */ } /* xerbla_ */ /* Main program alias */ int cblat2_ () { main (); return 0; } blis-0.9.0/blastest/src/cblat3.c000066400000000000000000005737351422157504600164270ustar00rootroot00000000000000/* cblat3.f -- translated by f2c (version 20100827). You must link the resulting object file with libf2c: on Microsoft Windows system, link with libf2c.lib; on Linux or Unix systems, link with .../path/to/libf2c.a -lm or, if you install libf2c.a in a standard place, with -lf2c -lm -- in that order, at the end of the command line, as in cc *.o -lf2c -lm Source for libf2c is in /netlib/f2c/libf2c.zip, e.g., http://www.netlib.org/f2c/libf2c.zip */ #include "f2c.h" /* Common Block Declarations */ union { struct { integer infot, noutc; logical ok, lerr; } _1; struct { integer infot, nout; logical ok, lerr; } _2; } infoc_; #define infoc_1 (infoc_._1) #define infoc_2 (infoc_._2) struct { char srnamt[6]; } srnamc_; #define srnamc_1 srnamc_ /* Table of constant values */ static complex c_b1 = {0.f,0.f}; static complex c_b2 = {1.f,0.f}; static integer c__9 = 9; static integer c__1 = 1; static integer c__3 = 3; static integer c__8 = 8; static integer c__4 = 4; static integer c__65 = 65; static integer c__7 = 7; static integer c__6 = 6; static integer c__2 = 2; static real c_b86 = 0.f; static logical c_true = TRUE_; static logical c_false = FALSE_; static integer c__0 = 0; static integer c_n1 = -1; /* > \brief \b CBLAT3 */ /* =========== DOCUMENTATION =========== */ /* Online html documentation available at */ /* http://www.netlib.org/lapack/explore-html/ */ /* Definition: */ /* =========== */ /* PROGRAM CBLAT3 */ /* > \par Purpose: */ /* ============= */ /* > */ /* > \verbatim */ /* > */ /* > Test program for the COMPLEX Level 3 Blas. */ /* > */ /* > The program must be driven by a short data file. The first 14 records */ /* > of the file are read using list-directed input, the last 9 records */ /* > are read using the format ( A6, L2 ). An annotated example of a data */ /* > file can be obtained by deleting the first 3 characters from the */ /* > following 23 lines: */ /* > 'cblat3.out' NAME OF SUMMARY OUTPUT FILE */ /* > 6 UNIT NUMBER OF SUMMARY FILE */ /* > 'CBLAT3.SNAP' NAME OF SNAPSHOT OUTPUT FILE */ /* > -1 UNIT NUMBER OF SNAPSHOT FILE (NOT USED IF .LT. 0) */ /* > F LOGICAL FLAG, T TO REWIND SNAPSHOT FILE AFTER EACH RECORD. */ /* > F LOGICAL FLAG, T TO STOP ON FAILURES. */ /* > T LOGICAL FLAG, T TO TEST ERROR EXITS. */ /* > 16.0 THRESHOLD VALUE OF TEST RATIO */ /* > 6 NUMBER OF VALUES OF N */ /* > 0 1 2 3 5 9 VALUES OF N */ /* > 3 NUMBER OF VALUES OF ALPHA */ /* > (0.0,0.0) (1.0,0.0) (0.7,-0.9) VALUES OF ALPHA */ /* > 3 NUMBER OF VALUES OF BETA */ /* > (0.0,0.0) (1.0,0.0) (1.3,-1.1) VALUES OF BETA */ /* > CGEMM T PUT F FOR NO TEST. SAME COLUMNS. */ /* > CHEMM T PUT F FOR NO TEST. SAME COLUMNS. */ /* > CSYMM T PUT F FOR NO TEST. SAME COLUMNS. */ /* > CTRMM T PUT F FOR NO TEST. SAME COLUMNS. */ /* > CTRSM T PUT F FOR NO TEST. SAME COLUMNS. */ /* > CHERK T PUT F FOR NO TEST. SAME COLUMNS. */ /* > CSYRK T PUT F FOR NO TEST. SAME COLUMNS. */ /* > CHER2K T PUT F FOR NO TEST. SAME COLUMNS. */ /* > CSYR2K T PUT F FOR NO TEST. SAME COLUMNS. */ /* > */ /* > Further Details */ /* > =============== */ /* > */ /* > See: */ /* > */ /* > Dongarra J. J., Du Croz J. J., Duff I. S. and Hammarling S. */ /* > A Set of Level 3 Basic Linear Algebra Subprograms. */ /* > */ /* > Technical Memorandum No.88 (Revision 1), Mathematics and */ /* > Computer Science Division, Argonne National Laboratory, 9700 */ /* > South Cass Avenue, Argonne, Illinois 60439, US. */ /* > */ /* > -- Written on 8-February-1989. */ /* > Jack Dongarra, Argonne National Laboratory. */ /* > Iain Duff, AERE Harwell. */ /* > Jeremy Du Croz, Numerical Algorithms Group Ltd. */ /* > Sven Hammarling, Numerical Algorithms Group Ltd. */ /* > */ /* > 10-9-00: Change STATUS='NEW' to 'UNKNOWN' so that the testers */ /* > can be run multiple times without deleting generated */ /* > output files (susan) */ /* > \endverbatim */ /* Authors: */ /* ======== */ /* > \author Univ. of Tennessee */ /* > \author Univ. of California Berkeley */ /* > \author Univ. of Colorado Denver */ /* > \author NAG Ltd. */ /* > \date April 2012 */ /* > \ingroup complex_blas_testing */ /* ===================================================================== */ /* Main program */ int main(void) { /* Initialized data */ static char snames[6*9] = "CGEMM " "CHEMM " "CSYMM " "CTRMM " "CTRSM " "CHERK " "CSYRK " "CHER2K" "CSYR2K"; /* Format strings */ static char fmt_9997[] = "(\002 NUMBER OF VALUES OF \002,a,\002 IS LESS " "THAN 1 OR GREATER \002,\002THAN \002,i2)"; static char fmt_9996[] = "(\002 VALUE OF N IS LESS THAN 0 OR GREATER THA" "N \002,i2)"; static char fmt_9995[] = "(\002 TESTS OF THE COMPLEX LEVEL 3 BL" "AS\002,//\002 THE F\002,\002OLLOWING PARAMETER VALUES WILL BE US" "ED:\002)"; static char fmt_9994[] = "(\002 FOR N \002,9i6)"; static char fmt_9993[] = "(\002 FOR ALPHA \002,7(\002(\002,f4" ".1,\002,\002,f4.1,\002) \002,:))"; static char fmt_9992[] = "(\002 FOR BETA \002,7(\002(\002,f4" ".1,\002,\002,f4.1,\002) \002,:))"; static char fmt_9984[] = "(\002 ERROR-EXITS WILL NOT BE TESTED\002)"; static char fmt_9999[] = "(\002 ROUTINES PASS COMPUTATIONAL TESTS IF TES" "T RATIO IS LES\002,\002S THAN\002,f8.2)"; static char fmt_9988[] = "(a6,l2)"; static char fmt_9990[] = "(\002 SUBPROGRAM NAME \002,a6,\002 NOT RECOGNI" "ZED\002,/\002 ******* T\002,\002ESTS ABANDONED *******\002)"; static char fmt_9998[] = "(\002 RELATIVE MACHINE PRECISION IS TAKEN TO" " BE\002,1p,e9.1)"; static char fmt_9989[] = "(\002 ERROR IN CMMCH - IN-LINE DOT PRODUCTS A" "RE BEING EVALU\002,\002ATED WRONGLY.\002,/\002 CMMCH WAS CALLED " "WITH TRANSA = \002,a1,\002 AND TRANSB = \002,a1,/\002 AND RETURN" "ED SAME = \002,l1,\002 AND \002,\002ERR = \002,f12.3,\002.\002," "/\002 THIS MAY BE DUE TO FAULTS IN THE \002,\002ARITHMETIC OR TH" "E COMPILER.\002,/\002 ******* TESTS ABANDONED \002,\002******" "*\002)"; static char fmt_9987[] = "(1x,a6,\002 WAS NOT TESTED\002)"; static char fmt_9986[] = "(/\002 END OF TESTS\002)"; static char fmt_9985[] = "(/\002 ******* FATAL ERROR - TESTS ABANDONED *" "******\002)"; static char fmt_9991[] = "(\002 AMEND DATA FILE OR INCREASE ARRAY SIZES " "IN PROGRAM\002,/\002 ******* TESTS ABANDONED *******\002)"; /* System generated locals */ integer i__1, i__2, i__3, i__4, i__5; olist o__1; cllist cl__1; /* Builtin functions */ integer s_rsle(cilist *), do_lio(integer *, integer *, char *, ftnlen), e_rsle(void), f_open(olist *), s_wsfe(cilist *), do_fio(integer *, char *, ftnlen), e_wsfe(void), s_wsle(cilist *), e_wsle(void), s_rsfe(cilist *), e_rsfe(void), s_cmp(const char *, const char *, ftnlen, ftnlen); /* Subroutine */ int s_stop(char *, ftnlen); integer f_clos(cllist *); /* Subroutine */ int s_copy(char *, const char *, ftnlen, ftnlen); /* Local variables */ complex c__[4225] /* was [65][65] */; real g[65]; integer i__, j, n; complex w[130], aa[4225], ab[8450] /* was [65][130] */, bb[4225], cc[ 4225], as[4225], bs[4225], cs[4225], ct[65], alf[7]; extern logical lce_(complex *, complex *, integer *); complex bet[7]; real eps, err; integer nalf, idim[9]; logical same; integer nbet, ntra; logical rewi; integer nout; extern /* Subroutine */ int cchk1_(char *, real *, real *, integer *, integer *, logical *, logical *, logical *, integer *, integer *, integer *, complex *, integer *, complex *, integer *, complex *, complex *, complex *, complex *, complex *, complex *, complex *, complex *, complex *, complex *, real *, ftnlen), cchk2_(char *, real *, real *, integer *, integer *, logical *, logical *, logical *, integer *, integer *, integer *, complex *, integer *, complex *, integer *, complex *, complex *, complex *, complex *, complex *, complex *, complex *, complex *, complex *, complex *, real *, ftnlen), cchk3_(char *, real *, real *, integer *, integer *, logical *, logical *, logical *, integer *, integer *, integer *, complex *, integer *, complex *, complex *, complex *, complex *, complex *, complex *, complex *, real *, complex *, ftnlen), cchk4_(char *, real *, real *, integer *, integer *, logical *, logical *, logical *, integer *, integer *, integer *, complex *, integer *, complex *, integer *, complex *, complex *, complex *, complex *, complex *, complex *, complex *, complex *, complex *, complex *, real *, ftnlen), cchk5_(char *, real *, real *, integer *, integer *, logical *, logical *, logical *, integer *, integer *, integer *, complex *, integer *, complex *, integer *, complex *, complex *, complex *, complex *, complex *, complex *, complex *, complex *, complex *, real *, complex *, ftnlen), cchke_(integer *, char *, integer *, ftnlen); logical fatal; extern /* Subroutine */ int cmmch_(char *, char *, integer *, integer *, integer *, complex *, complex *, integer *, complex *, integer *, complex *, complex *, integer *, complex *, real *, complex *, integer *, real *, real *, logical *, integer *, logical *, ftnlen, ftnlen); logical trace; integer nidim; char snaps[32]; integer isnum; logical ltest[9], sfatal; char snamet[6], transa[1], transb[1]; real thresh; logical ltestt, tsterr; char summry[32]; extern real s_epsilon_(real *); /* Fortran I/O blocks */ static cilist io___2 = { 0, 5, 0, 0, 0 }; static cilist io___4 = { 0, 5, 0, 0, 0 }; static cilist io___6 = { 0, 5, 0, 0, 0 }; static cilist io___8 = { 0, 5, 0, 0, 0 }; static cilist io___11 = { 0, 5, 0, 0, 0 }; static cilist io___13 = { 0, 5, 0, 0, 0 }; static cilist io___15 = { 0, 5, 0, 0, 0 }; static cilist io___17 = { 0, 5, 0, 0, 0 }; static cilist io___19 = { 0, 5, 0, 0, 0 }; static cilist io___21 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___22 = { 0, 5, 0, 0, 0 }; static cilist io___25 = { 0, 0, 0, fmt_9996, 0 }; static cilist io___26 = { 0, 5, 0, 0, 0 }; static cilist io___28 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___29 = { 0, 5, 0, 0, 0 }; static cilist io___31 = { 0, 5, 0, 0, 0 }; static cilist io___33 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___34 = { 0, 5, 0, 0, 0 }; static cilist io___36 = { 0, 0, 0, fmt_9995, 0 }; static cilist io___37 = { 0, 0, 0, fmt_9994, 0 }; static cilist io___38 = { 0, 0, 0, fmt_9993, 0 }; static cilist io___39 = { 0, 0, 0, fmt_9992, 0 }; static cilist io___40 = { 0, 0, 0, 0, 0 }; static cilist io___41 = { 0, 0, 0, fmt_9984, 0 }; static cilist io___42 = { 0, 0, 0, 0, 0 }; static cilist io___43 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___44 = { 0, 0, 0, 0, 0 }; static cilist io___46 = { 0, 5, 1, fmt_9988, 0 }; static cilist io___49 = { 0, 0, 0, fmt_9990, 0 }; static cilist io___51 = { 0, 0, 0, fmt_9998, 0 }; static cilist io___64 = { 0, 0, 0, fmt_9989, 0 }; static cilist io___65 = { 0, 0, 0, fmt_9989, 0 }; static cilist io___66 = { 0, 0, 0, fmt_9989, 0 }; static cilist io___67 = { 0, 0, 0, fmt_9989, 0 }; static cilist io___69 = { 0, 0, 0, 0, 0 }; static cilist io___70 = { 0, 0, 0, fmt_9987, 0 }; static cilist io___71 = { 0, 0, 0, 0, 0 }; static cilist io___78 = { 0, 0, 0, fmt_9986, 0 }; static cilist io___79 = { 0, 0, 0, fmt_9985, 0 }; static cilist io___80 = { 0, 0, 0, fmt_9991, 0 }; /* -- Reference BLAS test routine (version 3.4.1) -- */ /* -- Reference BLAS is a software package provided by Univ. of Tennessee, -- */ /* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- */ /* April 2012 */ /* ===================================================================== */ /* .. Parameters .. */ /* .. Local Scalars .. */ /* .. Local Arrays .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. Scalars in Common .. */ /* .. Common blocks .. */ /* .. Data statements .. */ /* .. Executable Statements .. */ /* Read name and unit number for summary output file and open file. */ s_rsle(&io___2); do_lio(&c__9, &c__1, summry, (ftnlen)32); e_rsle(); s_rsle(&io___4); do_lio(&c__3, &c__1, (char *)&nout, (ftnlen)sizeof(integer)); e_rsle(); o__1.oerr = 0; o__1.ounit = nout; o__1.ofnmlen = 32; o__1.ofnm = summry; o__1.orl = 0; o__1.osta = 0; o__1.oacc = 0; o__1.ofm = 0; o__1.oblnk = 0; f_open(&o__1); infoc_1.noutc = nout; /* Read name and unit number for snapshot output file and open file. */ s_rsle(&io___6); do_lio(&c__9, &c__1, snaps, (ftnlen)32); e_rsle(); s_rsle(&io___8); do_lio(&c__3, &c__1, (char *)&ntra, (ftnlen)sizeof(integer)); e_rsle(); trace = ntra >= 0; if (trace) { o__1.oerr = 0; o__1.ounit = ntra; o__1.ofnmlen = 32; o__1.ofnm = snaps; o__1.orl = 0; o__1.osta = 0; o__1.oacc = 0; o__1.ofm = 0; o__1.oblnk = 0; f_open(&o__1); } /* Read the flag that directs rewinding of the snapshot file. */ s_rsle(&io___11); do_lio(&c__8, &c__1, (char *)&rewi, (ftnlen)sizeof(logical)); e_rsle(); rewi = rewi && trace; /* Read the flag that directs stopping on any failure. */ s_rsle(&io___13); do_lio(&c__8, &c__1, (char *)&sfatal, (ftnlen)sizeof(logical)); e_rsle(); /* Read the flag that indicates whether error exits are to be tested. */ s_rsle(&io___15); do_lio(&c__8, &c__1, (char *)&tsterr, (ftnlen)sizeof(logical)); e_rsle(); /* Read the threshold value of the test ratio */ s_rsle(&io___17); do_lio(&c__4, &c__1, (char *)&thresh, (ftnlen)sizeof(real)); e_rsle(); /* Read and check the parameter values for the tests. */ /* Values of N */ s_rsle(&io___19); do_lio(&c__3, &c__1, (char *)&nidim, (ftnlen)sizeof(integer)); e_rsle(); if (nidim < 1 || nidim > 9) { io___21.ciunit = nout; s_wsfe(&io___21); do_fio(&c__1, "N", (ftnlen)1); do_fio(&c__1, (char *)&c__9, (ftnlen)sizeof(integer)); e_wsfe(); goto L220; } s_rsle(&io___22); i__1 = nidim; for (i__ = 1; i__ <= i__1; ++i__) { do_lio(&c__3, &c__1, (char *)&idim[i__ - 1], (ftnlen)sizeof(integer)); } e_rsle(); i__1 = nidim; for (i__ = 1; i__ <= i__1; ++i__) { if (idim[i__ - 1] < 0 || idim[i__ - 1] > 65) { io___25.ciunit = nout; s_wsfe(&io___25); do_fio(&c__1, (char *)&c__65, (ftnlen)sizeof(integer)); e_wsfe(); goto L220; } /* L10: */ } /* Values of ALPHA */ s_rsle(&io___26); do_lio(&c__3, &c__1, (char *)&nalf, (ftnlen)sizeof(integer)); e_rsle(); if (nalf < 1 || nalf > 7) { io___28.ciunit = nout; s_wsfe(&io___28); do_fio(&c__1, "ALPHA", (ftnlen)5); do_fio(&c__1, (char *)&c__7, (ftnlen)sizeof(integer)); e_wsfe(); goto L220; } s_rsle(&io___29); i__1 = nalf; for (i__ = 1; i__ <= i__1; ++i__) { do_lio(&c__6, &c__1, (char *)&alf[i__ - 1], (ftnlen)sizeof(complex)); } e_rsle(); /* Values of BETA */ s_rsle(&io___31); do_lio(&c__3, &c__1, (char *)&nbet, (ftnlen)sizeof(integer)); e_rsle(); if (nbet < 1 || nbet > 7) { io___33.ciunit = nout; s_wsfe(&io___33); do_fio(&c__1, "BETA", (ftnlen)4); do_fio(&c__1, (char *)&c__7, (ftnlen)sizeof(integer)); e_wsfe(); goto L220; } s_rsle(&io___34); i__1 = nbet; for (i__ = 1; i__ <= i__1; ++i__) { do_lio(&c__6, &c__1, (char *)&bet[i__ - 1], (ftnlen)sizeof(complex)); } e_rsle(); /* Report values of parameters. */ io___36.ciunit = nout; s_wsfe(&io___36); e_wsfe(); io___37.ciunit = nout; s_wsfe(&io___37); i__1 = nidim; for (i__ = 1; i__ <= i__1; ++i__) { do_fio(&c__1, (char *)&idim[i__ - 1], (ftnlen)sizeof(integer)); } e_wsfe(); io___38.ciunit = nout; s_wsfe(&io___38); i__1 = nalf; for (i__ = 1; i__ <= i__1; ++i__) { do_fio(&c__2, (char *)&alf[i__ - 1], (ftnlen)sizeof(real)); } e_wsfe(); io___39.ciunit = nout; s_wsfe(&io___39); i__1 = nbet; for (i__ = 1; i__ <= i__1; ++i__) { do_fio(&c__2, (char *)&bet[i__ - 1], (ftnlen)sizeof(real)); } e_wsfe(); if (! tsterr) { io___40.ciunit = nout; s_wsle(&io___40); e_wsle(); io___41.ciunit = nout; s_wsfe(&io___41); e_wsfe(); } io___42.ciunit = nout; s_wsle(&io___42); e_wsle(); io___43.ciunit = nout; s_wsfe(&io___43); do_fio(&c__1, (char *)&thresh, (ftnlen)sizeof(real)); e_wsfe(); io___44.ciunit = nout; s_wsle(&io___44); e_wsle(); /* Read names of subroutines and flags which indicate */ /* whether they are to be tested. */ for (i__ = 1; i__ <= 9; ++i__) { ltest[i__ - 1] = FALSE_; /* L20: */ } L30: i__1 = s_rsfe(&io___46); if (i__1 != 0) { goto L60; } i__1 = do_fio(&c__1, snamet, (ftnlen)6); if (i__1 != 0) { goto L60; } i__1 = do_fio(&c__1, (char *)<estt, (ftnlen)sizeof(logical)); if (i__1 != 0) { goto L60; } i__1 = e_rsfe(); if (i__1 != 0) { goto L60; } for (i__ = 1; i__ <= 9; ++i__) { if (s_cmp(snamet, snames + (i__ - 1) * 6, (ftnlen)6, (ftnlen)6) == 0) { goto L50; } /* L40: */ } io___49.ciunit = nout; s_wsfe(&io___49); do_fio(&c__1, snamet, (ftnlen)6); e_wsfe(); s_stop("", (ftnlen)0); L50: ltest[i__ - 1] = ltestt; goto L30; L60: cl__1.cerr = 0; cl__1.cunit = 5; cl__1.csta = 0; f_clos(&cl__1); /* Compute EPS (the machine precision). */ eps = s_epsilon_(&c_b86); io___51.ciunit = nout; s_wsfe(&io___51); do_fio(&c__1, (char *)&eps, (ftnlen)sizeof(real)); e_wsfe(); /* Check the reliability of CMMCH using exact data. */ n = 32; i__1 = n; for (j = 1; j <= i__1; ++j) { i__2 = n; for (i__ = 1; i__ <= i__2; ++i__) { i__3 = i__ + j * 65 - 66; /* Computing MAX */ i__5 = i__ - j + 1; i__4 = max(i__5,0); ab[i__3].r = (real) i__4, ab[i__3].i = 0.f; /* L90: */ } i__2 = j + 4224; ab[i__2].r = (real) j, ab[i__2].i = 0.f; i__2 = (j + 65) * 65 - 65; ab[i__2].r = (real) j, ab[i__2].i = 0.f; i__2 = j - 1; c__[i__2].r = 0.f, c__[i__2].i = 0.f; /* L100: */ } i__1 = n; for (j = 1; j <= i__1; ++j) { i__2 = j - 1; i__3 = j * ((j + 1) * j) / 2 - (j + 1) * j * (j - 1) / 3; cc[i__2].r = (real) i__3, cc[i__2].i = 0.f; /* L110: */ } /* CC holds the exact result. On exit from CMMCH CT holds */ /* the result computed by CMMCH. */ *(unsigned char *)transa = 'N'; *(unsigned char *)transb = 'N'; cmmch_(transa, transb, &n, &c__1, &n, &c_b2, ab, &c__65, &ab[4225], & c__65, &c_b1, c__, &c__65, ct, g, cc, &c__65, &eps, &err, &fatal, &nout, &c_true, (ftnlen)1, (ftnlen)1); same = lce_(cc, ct, &n); if (! same || err != 0.f) { io___64.ciunit = nout; s_wsfe(&io___64); do_fio(&c__1, transa, (ftnlen)1); do_fio(&c__1, transb, (ftnlen)1); do_fio(&c__1, (char *)&same, (ftnlen)sizeof(logical)); do_fio(&c__1, (char *)&err, (ftnlen)sizeof(real)); e_wsfe(); s_stop("", (ftnlen)0); } *(unsigned char *)transb = 'C'; cmmch_(transa, transb, &n, &c__1, &n, &c_b2, ab, &c__65, &ab[4225], & c__65, &c_b1, c__, &c__65, ct, g, cc, &c__65, &eps, &err, &fatal, &nout, &c_true, (ftnlen)1, (ftnlen)1); same = lce_(cc, ct, &n); if (! same || err != 0.f) { io___65.ciunit = nout; s_wsfe(&io___65); do_fio(&c__1, transa, (ftnlen)1); do_fio(&c__1, transb, (ftnlen)1); do_fio(&c__1, (char *)&same, (ftnlen)sizeof(logical)); do_fio(&c__1, (char *)&err, (ftnlen)sizeof(real)); e_wsfe(); s_stop("", (ftnlen)0); } i__1 = n; for (j = 1; j <= i__1; ++j) { i__2 = j + 4224; i__3 = n - j + 1; ab[i__2].r = (real) i__3, ab[i__2].i = 0.f; i__2 = (j + 65) * 65 - 65; i__3 = n - j + 1; ab[i__2].r = (real) i__3, ab[i__2].i = 0.f; /* L120: */ } i__1 = n; for (j = 1; j <= i__1; ++j) { i__2 = n - j; i__3 = j * ((j + 1) * j) / 2 - (j + 1) * j * (j - 1) / 3; cc[i__2].r = (real) i__3, cc[i__2].i = 0.f; /* L130: */ } *(unsigned char *)transa = 'C'; *(unsigned char *)transb = 'N'; cmmch_(transa, transb, &n, &c__1, &n, &c_b2, ab, &c__65, &ab[4225], & c__65, &c_b1, c__, &c__65, ct, g, cc, &c__65, &eps, &err, &fatal, &nout, &c_true, (ftnlen)1, (ftnlen)1); same = lce_(cc, ct, &n); if (! same || err != 0.f) { io___66.ciunit = nout; s_wsfe(&io___66); do_fio(&c__1, transa, (ftnlen)1); do_fio(&c__1, transb, (ftnlen)1); do_fio(&c__1, (char *)&same, (ftnlen)sizeof(logical)); do_fio(&c__1, (char *)&err, (ftnlen)sizeof(real)); e_wsfe(); s_stop("", (ftnlen)0); } *(unsigned char *)transb = 'C'; cmmch_(transa, transb, &n, &c__1, &n, &c_b2, ab, &c__65, &ab[4225], & c__65, &c_b1, c__, &c__65, ct, g, cc, &c__65, &eps, &err, &fatal, &nout, &c_true, (ftnlen)1, (ftnlen)1); same = lce_(cc, ct, &n); if (! same || err != 0.f) { io___67.ciunit = nout; s_wsfe(&io___67); do_fio(&c__1, transa, (ftnlen)1); do_fio(&c__1, transb, (ftnlen)1); do_fio(&c__1, (char *)&same, (ftnlen)sizeof(logical)); do_fio(&c__1, (char *)&err, (ftnlen)sizeof(real)); e_wsfe(); s_stop("", (ftnlen)0); } /* Test each subroutine in turn. */ for (isnum = 1; isnum <= 9; ++isnum) { io___69.ciunit = nout; s_wsle(&io___69); e_wsle(); if (! ltest[isnum - 1]) { /* Subprogram is not to be tested. */ io___70.ciunit = nout; s_wsfe(&io___70); do_fio(&c__1, snames + (isnum - 1) * 6, (ftnlen)6); e_wsfe(); } else { s_copy(srnamc_1.srnamt, snames + (isnum - 1) * 6, (ftnlen)6, ( ftnlen)6); /* Test error exits. */ if (tsterr) { cchke_(&isnum, snames + (isnum - 1) * 6, &nout, (ftnlen)6); io___71.ciunit = nout; s_wsle(&io___71); e_wsle(); } /* Test computations. */ infoc_1.infot = 0; infoc_1.ok = TRUE_; fatal = FALSE_; switch (isnum) { case 1: goto L140; case 2: goto L150; case 3: goto L150; case 4: goto L160; case 5: goto L160; case 6: goto L170; case 7: goto L170; case 8: goto L180; case 9: goto L180; } /* Test CGEMM, 01. */ L140: cchk1_(snames + (isnum - 1) * 6, &eps, &thresh, &nout, &ntra, & trace, &rewi, &fatal, &nidim, idim, &nalf, alf, &nbet, bet, &c__65, ab, aa, as, &ab[4225], bb, bs, c__, cc, cs, ct, g, (ftnlen)6); goto L190; /* Test CHEMM, 02, CSYMM, 03. */ L150: cchk2_(snames + (isnum - 1) * 6, &eps, &thresh, &nout, &ntra, & trace, &rewi, &fatal, &nidim, idim, &nalf, alf, &nbet, bet, &c__65, ab, aa, as, &ab[4225], bb, bs, c__, cc, cs, ct, g, (ftnlen)6); goto L190; /* Test CTRMM, 04, CTRSM, 05. */ L160: cchk3_(snames + (isnum - 1) * 6, &eps, &thresh, &nout, &ntra, & trace, &rewi, &fatal, &nidim, idim, &nalf, alf, &c__65, ab, aa, as, &ab[4225], bb, bs, ct, g, c__, (ftnlen)6); goto L190; /* Test CHERK, 06, CSYRK, 07. */ L170: cchk4_(snames + (isnum - 1) * 6, &eps, &thresh, &nout, &ntra, & trace, &rewi, &fatal, &nidim, idim, &nalf, alf, &nbet, bet, &c__65, ab, aa, as, &ab[4225], bb, bs, c__, cc, cs, ct, g, (ftnlen)6); goto L190; /* Test CHER2K, 08, CSYR2K, 09. */ L180: cchk5_(snames + (isnum - 1) * 6, &eps, &thresh, &nout, &ntra, & trace, &rewi, &fatal, &nidim, idim, &nalf, alf, &nbet, bet, &c__65, ab, aa, as, bb, bs, c__, cc, cs, ct, g, w, ( ftnlen)6); goto L190; L190: if (fatal && sfatal) { goto L210; } } /* L200: */ } io___78.ciunit = nout; s_wsfe(&io___78); e_wsfe(); goto L230; L210: io___79.ciunit = nout; s_wsfe(&io___79); e_wsfe(); goto L230; L220: io___80.ciunit = nout; s_wsfe(&io___80); e_wsfe(); L230: if (trace) { cl__1.cerr = 0; cl__1.cunit = ntra; cl__1.csta = 0; f_clos(&cl__1); } cl__1.cerr = 0; cl__1.cunit = nout; cl__1.csta = 0; f_clos(&cl__1); s_stop("", (ftnlen)0); /* End of CBLAT3. */ return 0; } /* main */ /* Subroutine */ int cchk1_(char *sname, real *eps, real *thresh, integer * nout, integer *ntra, logical *trace, logical *rewi, logical *fatal, integer *nidim, integer *idim, integer *nalf, complex *alf, integer * nbet, complex *bet, integer *nmax, complex *a, complex *aa, complex * as, complex *b, complex *bb, complex *bs, complex *c__, complex *cc, complex *cs, complex *ct, real *g, ftnlen sname_len) { /* Initialized data */ static char ich[3] = "NTC"; /* Format strings */ static char fmt_9995[] = "(1x,i6,\002: \002,a6,\002('\002,a1,\002','\002" ",a1,\002',\002,3(i3,\002,\002),\002(\002,f4.1,\002,\002,f4.1," "\002), A,\002,i3,\002, B,\002,i3,\002,(\002,f4.1,\002,\002,f4.1" ",\002), C,\002,i3,\002).\002)"; static char fmt_9994[] = "(\002 ******* FATAL ERROR - ERROR-EXIT TAKEN O" "N VALID CALL *\002,\002******\002)"; static char fmt_9998[] = "(\002 ******* FATAL ERROR - PARAMETER NUMBER" " \002,i2,\002 WAS CH\002,\002ANGED INCORRECTLY *******\002)"; static char fmt_9999[] = "(\002 \002,a6,\002 PASSED THE COMPUTATIONAL TE" "STS (\002,i6,\002 CALL\002,\002S)\002)"; static char fmt_9997[] = "(\002 \002,a6,\002 COMPLETED THE COMPUTATIONAL" " TESTS (\002,i6,\002 C\002,\002ALLS)\002,/\002 ******* BUT WITH " "MAXIMUM TEST RATIO\002,f8.2,\002 - SUSPECT *******\002)"; static char fmt_9996[] = "(\002 ******* \002,a6,\002 FAILED ON CALL NUMB" "ER:\002)"; /* System generated locals */ integer a_dim1, a_offset, b_dim1, b_offset, c_dim1, c_offset, i__1, i__2, i__3, i__4, i__5, i__6, i__7, i__8; alist al__1; /* Builtin functions */ integer s_wsfe(cilist *), do_fio(integer *, char *, ftnlen), e_wsfe(void), f_rew(alist *); /* Local variables */ integer i__, k, m, n, ia, ib, ma, mb, na, nb, nc, ik, im, in, ks, ms, ns, ica, icb, laa, lbb, lda, lcc, ldb, ldc; extern logical lce_(complex *, complex *, integer *); complex als, bls; real err; complex beta; integer ldas, ldbs, ldcs; logical same, null; extern /* Subroutine */ int cmake_(char *, char *, char *, integer *, integer *, complex *, integer *, complex *, integer *, logical *, complex *, ftnlen, ftnlen, ftnlen); complex alpha; extern /* Subroutine */ int cgemm_(char *, char *, integer *, integer *, integer *, complex *, complex *, integer *, complex *, integer *, complex *, complex *, integer *, ftnlen, ftnlen), cmmch_(char *, char *, integer *, integer *, integer *, complex *, complex *, integer *, complex *, integer *, complex *, complex *, integer *, complex *, real *, complex *, integer *, real *, real *, logical * , integer *, logical *, ftnlen, ftnlen); logical isame[13], trana, tranb; integer nargs; logical reset; extern logical lceres_(char *, char *, integer *, integer *, complex *, complex *, integer *, ftnlen, ftnlen); char tranas[1], tranbs[1], transa[1], transb[1]; real errmax; /* Fortran I/O blocks */ static cilist io___124 = { 0, 0, 0, fmt_9995, 0 }; static cilist io___125 = { 0, 0, 0, fmt_9994, 0 }; static cilist io___128 = { 0, 0, 0, fmt_9998, 0 }; static cilist io___130 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___131 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___132 = { 0, 0, 0, fmt_9996, 0 }; static cilist io___133 = { 0, 0, 0, fmt_9995, 0 }; /* Tests CGEMM. */ /* Auxiliary routine for test program for Level 3 Blas. */ /* -- Written on 8-February-1989. */ /* Jack Dongarra, Argonne National Laboratory. */ /* Iain Duff, AERE Harwell. */ /* Jeremy Du Croz, Numerical Algorithms Group Ltd. */ /* Sven Hammarling, Numerical Algorithms Group Ltd. */ /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Scalars .. */ /* .. Local Arrays .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. Scalars in Common .. */ /* .. Common blocks .. */ /* .. Data statements .. */ /* Parameter adjustments */ --idim; --alf; --bet; --g; --ct; --cs; --cc; c_dim1 = *nmax; c_offset = 1 + c_dim1; c__ -= c_offset; --bs; --bb; b_dim1 = *nmax; b_offset = 1 + b_dim1; b -= b_offset; --as; --aa; a_dim1 = *nmax; a_offset = 1 + a_dim1; a -= a_offset; /* Function Body */ /* .. Executable Statements .. */ nargs = 13; nc = 0; reset = TRUE_; errmax = 0.f; i__1 = *nidim; for (im = 1; im <= i__1; ++im) { m = idim[im]; i__2 = *nidim; for (in = 1; in <= i__2; ++in) { n = idim[in]; /* Set LDC to 1 more than minimum value if room. */ ldc = m; if (ldc < *nmax) { ++ldc; } /* Skip tests if not enough room. */ if (ldc > *nmax) { goto L100; } lcc = ldc * n; null = n <= 0 || m <= 0; i__3 = *nidim; for (ik = 1; ik <= i__3; ++ik) { k = idim[ik]; for (ica = 1; ica <= 3; ++ica) { *(unsigned char *)transa = *(unsigned char *)&ich[ica - 1] ; trana = *(unsigned char *)transa == 'T' || *(unsigned char *)transa == 'C'; if (trana) { ma = k; na = m; } else { ma = m; na = k; } /* Set LDA to 1 more than minimum value if room. */ lda = ma; if (lda < *nmax) { ++lda; } /* Skip tests if not enough room. */ if (lda > *nmax) { goto L80; } laa = lda * na; /* Generate the matrix A. */ cmake_("GE", " ", " ", &ma, &na, &a[a_offset], nmax, &aa[ 1], &lda, &reset, &c_b1, (ftnlen)2, (ftnlen)1, ( ftnlen)1); for (icb = 1; icb <= 3; ++icb) { *(unsigned char *)transb = *(unsigned char *)&ich[icb - 1]; tranb = *(unsigned char *)transb == 'T' || *(unsigned char *)transb == 'C'; if (tranb) { mb = n; nb = k; } else { mb = k; nb = n; } /* Set LDB to 1 more than minimum value if room. */ ldb = mb; if (ldb < *nmax) { ++ldb; } /* Skip tests if not enough room. */ if (ldb > *nmax) { goto L70; } lbb = ldb * nb; /* Generate the matrix B. */ cmake_("GE", " ", " ", &mb, &nb, &b[b_offset], nmax, & bb[1], &ldb, &reset, &c_b1, (ftnlen)2, ( ftnlen)1, (ftnlen)1); i__4 = *nalf; for (ia = 1; ia <= i__4; ++ia) { i__5 = ia; alpha.r = alf[i__5].r, alpha.i = alf[i__5].i; i__5 = *nbet; for (ib = 1; ib <= i__5; ++ib) { i__6 = ib; beta.r = bet[i__6].r, beta.i = bet[i__6].i; /* Generate the matrix C. */ cmake_("GE", " ", " ", &m, &n, &c__[c_offset], nmax, &cc[1], &ldc, &reset, &c_b1, ( ftnlen)2, (ftnlen)1, (ftnlen)1); ++nc; /* Save every datum before calling the */ /* subroutine. */ *(unsigned char *)tranas = *(unsigned char *) transa; *(unsigned char *)tranbs = *(unsigned char *) transb; ms = m; ns = n; ks = k; als.r = alpha.r, als.i = alpha.i; i__6 = laa; for (i__ = 1; i__ <= i__6; ++i__) { i__7 = i__; i__8 = i__; as[i__7].r = aa[i__8].r, as[i__7].i = aa[ i__8].i; /* L10: */ } ldas = lda; i__6 = lbb; for (i__ = 1; i__ <= i__6; ++i__) { i__7 = i__; i__8 = i__; bs[i__7].r = bb[i__8].r, bs[i__7].i = bb[ i__8].i; /* L20: */ } ldbs = ldb; bls.r = beta.r, bls.i = beta.i; i__6 = lcc; for (i__ = 1; i__ <= i__6; ++i__) { i__7 = i__; i__8 = i__; cs[i__7].r = cc[i__8].r, cs[i__7].i = cc[ i__8].i; /* L30: */ } ldcs = ldc; /* Call the subroutine. */ if (*trace) { io___124.ciunit = *ntra; s_wsfe(&io___124); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof( integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, transa, (ftnlen)1); do_fio(&c__1, transb, (ftnlen)1); do_fio(&c__1, (char *)&m, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&n, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&k, (ftnlen)sizeof( integer)); do_fio(&c__2, (char *)&alpha, (ftnlen) sizeof(real)); do_fio(&c__1, (char *)&lda, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&ldb, (ftnlen) sizeof(integer)); do_fio(&c__2, (char *)&beta, (ftnlen) sizeof(real)); do_fio(&c__1, (char *)&ldc, (ftnlen) sizeof(integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } cgemm_(transa, transb, &m, &n, &k, &alpha, & aa[1], &lda, &bb[1], &ldb, &beta, &cc[ 1], &ldc, (ftnlen)1, (ftnlen)1); /* Check if error-exit was taken incorrectly. */ if (! infoc_1.ok) { io___125.ciunit = *nout; s_wsfe(&io___125); e_wsfe(); *fatal = TRUE_; goto L120; } /* See what data changed inside subroutines. */ isame[0] = *(unsigned char *)transa == *( unsigned char *)tranas; isame[1] = *(unsigned char *)transb == *( unsigned char *)tranbs; isame[2] = ms == m; isame[3] = ns == n; isame[4] = ks == k; isame[5] = als.r == alpha.r && als.i == alpha.i; isame[6] = lce_(&as[1], &aa[1], &laa); isame[7] = ldas == lda; isame[8] = lce_(&bs[1], &bb[1], &lbb); isame[9] = ldbs == ldb; isame[10] = bls.r == beta.r && bls.i == beta.i; if (null) { isame[11] = lce_(&cs[1], &cc[1], &lcc); } else { isame[11] = lceres_("GE", " ", &m, &n, & cs[1], &cc[1], &ldc, (ftnlen)2, ( ftnlen)1); } isame[12] = ldcs == ldc; /* If data was incorrectly changed, report */ /* and return. */ same = TRUE_; i__6 = nargs; for (i__ = 1; i__ <= i__6; ++i__) { same = same && isame[i__ - 1]; if (! isame[i__ - 1]) { io___128.ciunit = *nout; s_wsfe(&io___128); do_fio(&c__1, (char *)&i__, (ftnlen) sizeof(integer)); e_wsfe(); } /* L40: */ } if (! same) { *fatal = TRUE_; goto L120; } if (! null) { /* Check the result. */ cmmch_(transa, transb, &m, &n, &k, &alpha, &a[a_offset], nmax, &b[b_offset], nmax, &beta, &c__[c_offset], nmax, &ct[1], &g[1], &cc[1], &ldc, eps, &err, fatal, nout, &c_true, (ftnlen)1, (ftnlen)1); errmax = max(errmax,err); /* If got really bad answer, report and */ /* return. */ if (*fatal) { goto L120; } } /* L50: */ } /* L60: */ } L70: ; } L80: ; } /* L90: */ } L100: ; } /* L110: */ } /* Report result. */ if (errmax < *thresh) { io___130.ciunit = *nout; s_wsfe(&io___130); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); e_wsfe(); } else { io___131.ciunit = *nout; s_wsfe(&io___131); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&errmax, (ftnlen)sizeof(real)); e_wsfe(); } goto L130; L120: io___132.ciunit = *nout; s_wsfe(&io___132); do_fio(&c__1, sname, (ftnlen)6); e_wsfe(); io___133.ciunit = *nout; s_wsfe(&io___133); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, transa, (ftnlen)1); do_fio(&c__1, transb, (ftnlen)1); do_fio(&c__1, (char *)&m, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&k, (ftnlen)sizeof(integer)); do_fio(&c__2, (char *)&alpha, (ftnlen)sizeof(real)); do_fio(&c__1, (char *)&lda, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&ldb, (ftnlen)sizeof(integer)); do_fio(&c__2, (char *)&beta, (ftnlen)sizeof(real)); do_fio(&c__1, (char *)&ldc, (ftnlen)sizeof(integer)); e_wsfe(); L130: return 0; /* End of CCHK1. */ } /* cchk1_ */ /* Subroutine */ int cchk2_(char *sname, real *eps, real *thresh, integer * nout, integer *ntra, logical *trace, logical *rewi, logical *fatal, integer *nidim, integer *idim, integer *nalf, complex *alf, integer * nbet, complex *bet, integer *nmax, complex *a, complex *aa, complex * as, complex *b, complex *bb, complex *bs, complex *c__, complex *cc, complex *cs, complex *ct, real *g, ftnlen sname_len) { /* Initialized data */ static char ichs[2] = "LR"; static char ichu[2] = "UL"; /* Format strings */ static char fmt_9995[] = "(1x,i6,\002: \002,a6,\002(\002,2(\002'\002,a1" ",\002',\002),2(i3,\002,\002),\002(\002,f4.1,\002,\002,f4.1,\002)" ", A,\002,i3,\002, B,\002,i3,\002,(\002,f4.1,\002,\002,f4.1,\002)" ", C,\002,i3,\002) .\002)"; static char fmt_9994[] = "(\002 ******* FATAL ERROR - ERROR-EXIT TAKEN O" "N VALID CALL *\002,\002******\002)"; static char fmt_9998[] = "(\002 ******* FATAL ERROR - PARAMETER NUMBER" " \002,i2,\002 WAS CH\002,\002ANGED INCORRECTLY *******\002)"; static char fmt_9999[] = "(\002 \002,a6,\002 PASSED THE COMPUTATIONAL TE" "STS (\002,i6,\002 CALL\002,\002S)\002)"; static char fmt_9997[] = "(\002 \002,a6,\002 COMPLETED THE COMPUTATIONAL" " TESTS (\002,i6,\002 C\002,\002ALLS)\002,/\002 ******* BUT WITH " "MAXIMUM TEST RATIO\002,f8.2,\002 - SUSPECT *******\002)"; static char fmt_9996[] = "(\002 ******* \002,a6,\002 FAILED ON CALL NUMB" "ER:\002)"; /* System generated locals */ integer a_dim1, a_offset, b_dim1, b_offset, c_dim1, c_offset, i__1, i__2, i__3, i__4, i__5, i__6, i__7; alist al__1; /* Builtin functions */ integer s_cmp(const char *, const char *, ftnlen, ftnlen), s_wsfe(cilist *), do_fio( integer *, char *, ftnlen), e_wsfe(void), f_rew(alist *); /* Local variables */ integer i__, m, n, ia, ib, na, nc, im, in, ms, ns, laa, lbb, lda, lcc, ldb, ldc; extern logical lce_(complex *, complex *, integer *); integer ics; complex als, bls; integer icu; real err; complex beta; integer ldas, ldbs, ldcs; logical same; char side[1]; logical conj, left, null; char uplo[1]; extern /* Subroutine */ int cmake_(char *, char *, char *, integer *, integer *, complex *, integer *, complex *, integer *, logical *, complex *, ftnlen, ftnlen, ftnlen); complex alpha; extern /* Subroutine */ int cmmch_(char *, char *, integer *, integer *, integer *, complex *, complex *, integer *, complex *, integer *, complex *, complex *, integer *, complex *, real *, complex *, integer *, real *, real *, logical *, integer *, logical *, ftnlen, ftnlen), chemm_(char *, char *, integer *, integer *, complex *, complex *, integer *, complex *, integer *, complex *, complex *, integer *, ftnlen, ftnlen); logical isame[13]; char sides[1]; integer nargs; logical reset; extern /* Subroutine */ int csymm_(char *, char *, integer *, integer *, complex *, complex *, integer *, complex *, integer *, complex *, complex *, integer *, ftnlen, ftnlen); char uplos[1]; extern logical lceres_(char *, char *, integer *, integer *, complex *, complex *, integer *, ftnlen, ftnlen); real errmax; /* Fortran I/O blocks */ static cilist io___172 = { 0, 0, 0, fmt_9995, 0 }; static cilist io___173 = { 0, 0, 0, fmt_9994, 0 }; static cilist io___176 = { 0, 0, 0, fmt_9998, 0 }; static cilist io___178 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___179 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___180 = { 0, 0, 0, fmt_9996, 0 }; static cilist io___181 = { 0, 0, 0, fmt_9995, 0 }; /* Tests CHEMM and CSYMM. */ /* Auxiliary routine for test program for Level 3 Blas. */ /* -- Written on 8-February-1989. */ /* Jack Dongarra, Argonne National Laboratory. */ /* Iain Duff, AERE Harwell. */ /* Jeremy Du Croz, Numerical Algorithms Group Ltd. */ /* Sven Hammarling, Numerical Algorithms Group Ltd. */ /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Scalars .. */ /* .. Local Arrays .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. Scalars in Common .. */ /* .. Common blocks .. */ /* .. Data statements .. */ /* Parameter adjustments */ --idim; --alf; --bet; --g; --ct; --cs; --cc; c_dim1 = *nmax; c_offset = 1 + c_dim1; c__ -= c_offset; --bs; --bb; b_dim1 = *nmax; b_offset = 1 + b_dim1; b -= b_offset; --as; --aa; a_dim1 = *nmax; a_offset = 1 + a_dim1; a -= a_offset; /* Function Body */ /* .. Executable Statements .. */ conj = s_cmp(sname + 1, "HE", (ftnlen)2, (ftnlen)2) == 0; nargs = 12; nc = 0; reset = TRUE_; errmax = 0.f; i__1 = *nidim; for (im = 1; im <= i__1; ++im) { m = idim[im]; i__2 = *nidim; for (in = 1; in <= i__2; ++in) { n = idim[in]; /* Set LDC to 1 more than minimum value if room. */ ldc = m; if (ldc < *nmax) { ++ldc; } /* Skip tests if not enough room. */ if (ldc > *nmax) { goto L90; } lcc = ldc * n; null = n <= 0 || m <= 0; /* Set LDB to 1 more than minimum value if room. */ ldb = m; if (ldb < *nmax) { ++ldb; } /* Skip tests if not enough room. */ if (ldb > *nmax) { goto L90; } lbb = ldb * n; /* Generate the matrix B. */ cmake_("GE", " ", " ", &m, &n, &b[b_offset], nmax, &bb[1], &ldb, & reset, &c_b1, (ftnlen)2, (ftnlen)1, (ftnlen)1); for (ics = 1; ics <= 2; ++ics) { *(unsigned char *)side = *(unsigned char *)&ichs[ics - 1]; left = *(unsigned char *)side == 'L'; if (left) { na = m; } else { na = n; } /* Set LDA to 1 more than minimum value if room. */ lda = na; if (lda < *nmax) { ++lda; } /* Skip tests if not enough room. */ if (lda > *nmax) { goto L80; } laa = lda * na; for (icu = 1; icu <= 2; ++icu) { *(unsigned char *)uplo = *(unsigned char *)&ichu[icu - 1]; /* Generate the hermitian or symmetric matrix A. */ cmake_(sname + 1, uplo, " ", &na, &na, &a[a_offset], nmax, &aa[1], &lda, &reset, &c_b1, (ftnlen)2, (ftnlen) 1, (ftnlen)1); i__3 = *nalf; for (ia = 1; ia <= i__3; ++ia) { i__4 = ia; alpha.r = alf[i__4].r, alpha.i = alf[i__4].i; i__4 = *nbet; for (ib = 1; ib <= i__4; ++ib) { i__5 = ib; beta.r = bet[i__5].r, beta.i = bet[i__5].i; /* Generate the matrix C. */ cmake_("GE", " ", " ", &m, &n, &c__[c_offset], nmax, &cc[1], &ldc, &reset, &c_b1, ( ftnlen)2, (ftnlen)1, (ftnlen)1); ++nc; /* Save every datum before calling the */ /* subroutine. */ *(unsigned char *)sides = *(unsigned char *)side; *(unsigned char *)uplos = *(unsigned char *)uplo; ms = m; ns = n; als.r = alpha.r, als.i = alpha.i; i__5 = laa; for (i__ = 1; i__ <= i__5; ++i__) { i__6 = i__; i__7 = i__; as[i__6].r = aa[i__7].r, as[i__6].i = aa[i__7] .i; /* L10: */ } ldas = lda; i__5 = lbb; for (i__ = 1; i__ <= i__5; ++i__) { i__6 = i__; i__7 = i__; bs[i__6].r = bb[i__7].r, bs[i__6].i = bb[i__7] .i; /* L20: */ } ldbs = ldb; bls.r = beta.r, bls.i = beta.i; i__5 = lcc; for (i__ = 1; i__ <= i__5; ++i__) { i__6 = i__; i__7 = i__; cs[i__6].r = cc[i__7].r, cs[i__6].i = cc[i__7] .i; /* L30: */ } ldcs = ldc; /* Call the subroutine. */ if (*trace) { io___172.ciunit = *ntra; s_wsfe(&io___172); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof( integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, side, (ftnlen)1); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, (char *)&m, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&n, (ftnlen)sizeof( integer)); do_fio(&c__2, (char *)&alpha, (ftnlen)sizeof( real)); do_fio(&c__1, (char *)&lda, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&ldb, (ftnlen)sizeof( integer)); do_fio(&c__2, (char *)&beta, (ftnlen)sizeof( real)); do_fio(&c__1, (char *)&ldc, (ftnlen)sizeof( integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } if (conj) { chemm_(side, uplo, &m, &n, &alpha, &aa[1], & lda, &bb[1], &ldb, &beta, &cc[1], & ldc, (ftnlen)1, (ftnlen)1); } else { csymm_(side, uplo, &m, &n, &alpha, &aa[1], & lda, &bb[1], &ldb, &beta, &cc[1], & ldc, (ftnlen)1, (ftnlen)1); } /* Check if error-exit was taken incorrectly. */ if (! infoc_1.ok) { io___173.ciunit = *nout; s_wsfe(&io___173); e_wsfe(); *fatal = TRUE_; goto L110; } /* See what data changed inside subroutines. */ isame[0] = *(unsigned char *)sides == *(unsigned char *)side; isame[1] = *(unsigned char *)uplos == *(unsigned char *)uplo; isame[2] = ms == m; isame[3] = ns == n; isame[4] = als.r == alpha.r && als.i == alpha.i; isame[5] = lce_(&as[1], &aa[1], &laa); isame[6] = ldas == lda; isame[7] = lce_(&bs[1], &bb[1], &lbb); isame[8] = ldbs == ldb; isame[9] = bls.r == beta.r && bls.i == beta.i; if (null) { isame[10] = lce_(&cs[1], &cc[1], &lcc); } else { isame[10] = lceres_("GE", " ", &m, &n, &cs[1], &cc[1], &ldc, (ftnlen)2, (ftnlen)1); } isame[11] = ldcs == ldc; /* If data was incorrectly changed, report and */ /* return. */ same = TRUE_; i__5 = nargs; for (i__ = 1; i__ <= i__5; ++i__) { same = same && isame[i__ - 1]; if (! isame[i__ - 1]) { io___176.ciunit = *nout; s_wsfe(&io___176); do_fio(&c__1, (char *)&i__, (ftnlen) sizeof(integer)); e_wsfe(); } /* L40: */ } if (! same) { *fatal = TRUE_; goto L110; } if (! null) { /* Check the result. */ if (left) { cmmch_("N", "N", &m, &n, &m, &alpha, &a[ a_offset], nmax, &b[b_offset], nmax, &beta, &c__[c_offset], nmax, &ct[1], &g[1], &cc[1], &ldc, eps, &err, fatal, nout, &c_true, ( ftnlen)1, (ftnlen)1); } else { cmmch_("N", "N", &m, &n, &n, &alpha, &b[ b_offset], nmax, &a[a_offset], nmax, &beta, &c__[c_offset], nmax, &ct[1], &g[1], &cc[1], &ldc, eps, &err, fatal, nout, &c_true, ( ftnlen)1, (ftnlen)1); } errmax = max(errmax,err); /* If got really bad answer, report and */ /* return. */ if (*fatal) { goto L110; } } /* L50: */ } /* L60: */ } /* L70: */ } L80: ; } L90: ; } /* L100: */ } /* Report result. */ if (errmax < *thresh) { io___178.ciunit = *nout; s_wsfe(&io___178); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); e_wsfe(); } else { io___179.ciunit = *nout; s_wsfe(&io___179); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&errmax, (ftnlen)sizeof(real)); e_wsfe(); } goto L120; L110: io___180.ciunit = *nout; s_wsfe(&io___180); do_fio(&c__1, sname, (ftnlen)6); e_wsfe(); io___181.ciunit = *nout; s_wsfe(&io___181); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, side, (ftnlen)1); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, (char *)&m, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)); do_fio(&c__2, (char *)&alpha, (ftnlen)sizeof(real)); do_fio(&c__1, (char *)&lda, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&ldb, (ftnlen)sizeof(integer)); do_fio(&c__2, (char *)&beta, (ftnlen)sizeof(real)); do_fio(&c__1, (char *)&ldc, (ftnlen)sizeof(integer)); e_wsfe(); L120: return 0; /* End of CCHK2. */ } /* cchk2_ */ /* Subroutine */ int cchk3_(char *sname, real *eps, real *thresh, integer * nout, integer *ntra, logical *trace, logical *rewi, logical *fatal, integer *nidim, integer *idim, integer *nalf, complex *alf, integer * nmax, complex *a, complex *aa, complex *as, complex *b, complex *bb, complex *bs, complex *ct, real *g, complex *c__, ftnlen sname_len) { /* Initialized data */ static char ichu[2] = "UL"; static char icht[3] = "NTC"; static char ichd[2] = "UN"; static char ichs[2] = "LR"; /* Format strings */ static char fmt_9995[] = "(1x,i6,\002: \002,a6,\002(\002,4(\002'\002,a1" ",\002',\002),2(i3,\002,\002),\002(\002,f4.1,\002,\002,f4.1,\002)" ", A,\002,i3,\002, B,\002,i3,\002) \002,\002 .\002)"; static char fmt_9994[] = "(\002 ******* FATAL ERROR - ERROR-EXIT TAKEN O" "N VALID CALL *\002,\002******\002)"; static char fmt_9998[] = "(\002 ******* FATAL ERROR - PARAMETER NUMBER" " \002,i2,\002 WAS CH\002,\002ANGED INCORRECTLY *******\002)"; static char fmt_9999[] = "(\002 \002,a6,\002 PASSED THE COMPUTATIONAL TE" "STS (\002,i6,\002 CALL\002,\002S)\002)"; static char fmt_9997[] = "(\002 \002,a6,\002 COMPLETED THE COMPUTATIONAL" " TESTS (\002,i6,\002 C\002,\002ALLS)\002,/\002 ******* BUT WITH " "MAXIMUM TEST RATIO\002,f8.2,\002 - SUSPECT *******\002)"; static char fmt_9996[] = "(\002 ******* \002,a6,\002 FAILED ON CALL NUMB" "ER:\002)"; /* System generated locals */ integer a_dim1, a_offset, b_dim1, b_offset, c_dim1, c_offset, i__1, i__2, i__3, i__4, i__5, i__6, i__7; complex q__1; alist al__1; /* Builtin functions */ integer s_cmp(const char *, const char *, ftnlen, ftnlen), s_wsfe(cilist *), do_fio( integer *, char *, ftnlen), e_wsfe(void), f_rew(alist *); /* Local variables */ integer i__, j, m, n, ia, na, nc, im, in, ms, ns, laa, icd, lbb, lda, ldb; extern logical lce_(complex *, complex *, integer *); integer ics; complex als; integer ict, icu; real err; char diag[1]; integer ldas, ldbs; logical same; char side[1]; logical left, null; char uplo[1]; extern /* Subroutine */ int cmake_(char *, char *, char *, integer *, integer *, complex *, integer *, complex *, integer *, logical *, complex *, ftnlen, ftnlen, ftnlen); complex alpha; char diags[1]; extern /* Subroutine */ int cmmch_(char *, char *, integer *, integer *, integer *, complex *, complex *, integer *, complex *, integer *, complex *, complex *, integer *, complex *, real *, complex *, integer *, real *, real *, logical *, integer *, logical *, ftnlen, ftnlen); logical isame[13]; char sides[1]; integer nargs; logical reset; extern /* Subroutine */ int ctrmm_(char *, char *, char *, char *, integer *, integer *, complex *, complex *, integer *, complex *, integer *, ftnlen, ftnlen, ftnlen, ftnlen), ctrsm_(char *, char *, char *, char *, integer *, integer *, complex *, complex *, integer *, complex *, integer *, ftnlen, ftnlen, ftnlen, ftnlen); char uplos[1]; extern logical lceres_(char *, char *, integer *, integer *, complex *, complex *, integer *, ftnlen, ftnlen); char tranas[1], transa[1]; real errmax; /* Fortran I/O blocks */ static cilist io___222 = { 0, 0, 0, fmt_9995, 0 }; static cilist io___223 = { 0, 0, 0, fmt_9995, 0 }; static cilist io___224 = { 0, 0, 0, fmt_9994, 0 }; static cilist io___227 = { 0, 0, 0, fmt_9998, 0 }; static cilist io___229 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___230 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___231 = { 0, 0, 0, fmt_9996, 0 }; static cilist io___232 = { 0, 0, 0, fmt_9995, 0 }; /* Tests CTRMM and CTRSM. */ /* Auxiliary routine for test program for Level 3 Blas. */ /* -- Written on 8-February-1989. */ /* Jack Dongarra, Argonne National Laboratory. */ /* Iain Duff, AERE Harwell. */ /* Jeremy Du Croz, Numerical Algorithms Group Ltd. */ /* Sven Hammarling, Numerical Algorithms Group Ltd. */ /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Scalars .. */ /* .. Local Arrays .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. Scalars in Common .. */ /* .. Common blocks .. */ /* .. Data statements .. */ /* Parameter adjustments */ --idim; --alf; c_dim1 = *nmax; c_offset = 1 + c_dim1; c__ -= c_offset; --g; --ct; --bs; --bb; b_dim1 = *nmax; b_offset = 1 + b_dim1; b -= b_offset; --as; --aa; a_dim1 = *nmax; a_offset = 1 + a_dim1; a -= a_offset; /* Function Body */ /* .. Executable Statements .. */ nargs = 11; nc = 0; reset = TRUE_; errmax = 0.f; /* Set up zero matrix for CMMCH. */ i__1 = *nmax; for (j = 1; j <= i__1; ++j) { i__2 = *nmax; for (i__ = 1; i__ <= i__2; ++i__) { i__3 = i__ + j * c_dim1; c__[i__3].r = 0.f, c__[i__3].i = 0.f; /* L10: */ } /* L20: */ } i__1 = *nidim; for (im = 1; im <= i__1; ++im) { m = idim[im]; i__2 = *nidim; for (in = 1; in <= i__2; ++in) { n = idim[in]; /* Set LDB to 1 more than minimum value if room. */ ldb = m; if (ldb < *nmax) { ++ldb; } /* Skip tests if not enough room. */ if (ldb > *nmax) { goto L130; } lbb = ldb * n; null = m <= 0 || n <= 0; for (ics = 1; ics <= 2; ++ics) { *(unsigned char *)side = *(unsigned char *)&ichs[ics - 1]; left = *(unsigned char *)side == 'L'; if (left) { na = m; } else { na = n; } /* Set LDA to 1 more than minimum value if room. */ lda = na; if (lda < *nmax) { ++lda; } /* Skip tests if not enough room. */ if (lda > *nmax) { goto L130; } laa = lda * na; for (icu = 1; icu <= 2; ++icu) { *(unsigned char *)uplo = *(unsigned char *)&ichu[icu - 1]; for (ict = 1; ict <= 3; ++ict) { *(unsigned char *)transa = *(unsigned char *)&icht[ ict - 1]; for (icd = 1; icd <= 2; ++icd) { *(unsigned char *)diag = *(unsigned char *)&ichd[ icd - 1]; i__3 = *nalf; for (ia = 1; ia <= i__3; ++ia) { i__4 = ia; alpha.r = alf[i__4].r, alpha.i = alf[i__4].i; /* Generate the matrix A. */ cmake_("TR", uplo, diag, &na, &na, &a[ a_offset], nmax, &aa[1], &lda, &reset, &c_b1, (ftnlen)2, (ftnlen)1, (ftnlen) 1); /* Generate the matrix B. */ cmake_("GE", " ", " ", &m, &n, &b[b_offset], nmax, &bb[1], &ldb, &reset, &c_b1, ( ftnlen)2, (ftnlen)1, (ftnlen)1); ++nc; /* Save every datum before calling the */ /* subroutine. */ *(unsigned char *)sides = *(unsigned char *) side; *(unsigned char *)uplos = *(unsigned char *) uplo; *(unsigned char *)tranas = *(unsigned char *) transa; *(unsigned char *)diags = *(unsigned char *) diag; ms = m; ns = n; als.r = alpha.r, als.i = alpha.i; i__4 = laa; for (i__ = 1; i__ <= i__4; ++i__) { i__5 = i__; i__6 = i__; as[i__5].r = aa[i__6].r, as[i__5].i = aa[ i__6].i; /* L30: */ } ldas = lda; i__4 = lbb; for (i__ = 1; i__ <= i__4; ++i__) { i__5 = i__; i__6 = i__; bs[i__5].r = bb[i__6].r, bs[i__5].i = bb[ i__6].i; /* L40: */ } ldbs = ldb; /* Call the subroutine. */ if (s_cmp(sname + 3, "MM", (ftnlen)2, (ftnlen) 2) == 0) { if (*trace) { io___222.ciunit = *ntra; s_wsfe(&io___222); do_fio(&c__1, (char *)&nc, (ftnlen) sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, side, (ftnlen)1); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, transa, (ftnlen)1); do_fio(&c__1, diag, (ftnlen)1); do_fio(&c__1, (char *)&m, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&n, (ftnlen) sizeof(integer)); do_fio(&c__2, (char *)&alpha, (ftnlen) sizeof(real)); do_fio(&c__1, (char *)&lda, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&ldb, (ftnlen) sizeof(integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } ctrmm_(side, uplo, transa, diag, &m, &n, & alpha, &aa[1], &lda, &bb[1], &ldb, (ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); } else if (s_cmp(sname + 3, "SM", (ftnlen)2, ( ftnlen)2) == 0) { if (*trace) { io___223.ciunit = *ntra; s_wsfe(&io___223); do_fio(&c__1, (char *)&nc, (ftnlen) sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, side, (ftnlen)1); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, transa, (ftnlen)1); do_fio(&c__1, diag, (ftnlen)1); do_fio(&c__1, (char *)&m, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&n, (ftnlen) sizeof(integer)); do_fio(&c__2, (char *)&alpha, (ftnlen) sizeof(real)); do_fio(&c__1, (char *)&lda, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&ldb, (ftnlen) sizeof(integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } ctrsm_(side, uplo, transa, diag, &m, &n, & alpha, &aa[1], &lda, &bb[1], &ldb, (ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); } /* Check if error-exit was taken incorrectly. */ if (! infoc_1.ok) { io___224.ciunit = *nout; s_wsfe(&io___224); e_wsfe(); *fatal = TRUE_; goto L150; } /* See what data changed inside subroutines. */ isame[0] = *(unsigned char *)sides == *( unsigned char *)side; isame[1] = *(unsigned char *)uplos == *( unsigned char *)uplo; isame[2] = *(unsigned char *)tranas == *( unsigned char *)transa; isame[3] = *(unsigned char *)diags == *( unsigned char *)diag; isame[4] = ms == m; isame[5] = ns == n; isame[6] = als.r == alpha.r && als.i == alpha.i; isame[7] = lce_(&as[1], &aa[1], &laa); isame[8] = ldas == lda; if (null) { isame[9] = lce_(&bs[1], &bb[1], &lbb); } else { isame[9] = lceres_("GE", " ", &m, &n, &bs[ 1], &bb[1], &ldb, (ftnlen)2, ( ftnlen)1); } isame[10] = ldbs == ldb; /* If data was incorrectly changed, report and */ /* return. */ same = TRUE_; i__4 = nargs; for (i__ = 1; i__ <= i__4; ++i__) { same = same && isame[i__ - 1]; if (! isame[i__ - 1]) { io___227.ciunit = *nout; s_wsfe(&io___227); do_fio(&c__1, (char *)&i__, (ftnlen) sizeof(integer)); e_wsfe(); } /* L50: */ } if (! same) { *fatal = TRUE_; goto L150; } if (! null) { if (s_cmp(sname + 3, "MM", (ftnlen)2, ( ftnlen)2) == 0) { /* Check the result. */ if (left) { cmmch_(transa, "N", &m, &n, &m, & alpha, &a[a_offset], nmax, &b[b_offset], nmax, & c_b1, &c__[c_offset], nmax, &ct[1], &g[1], &bb[ 1], &ldb, eps, &err, fatal, nout, &c_true, ( ftnlen)1, (ftnlen)1); } else { cmmch_("N", transa, &m, &n, &n, & alpha, &b[b_offset], nmax, &a[a_offset], nmax, & c_b1, &c__[c_offset], nmax, &ct[1], &g[1], &bb[ 1], &ldb, eps, &err, fatal, nout, &c_true, ( ftnlen)1, (ftnlen)1); } } else if (s_cmp(sname + 3, "SM", (ftnlen) 2, (ftnlen)2) == 0) { /* Compute approximation to original */ /* matrix. */ i__4 = n; for (j = 1; j <= i__4; ++j) { i__5 = m; for (i__ = 1; i__ <= i__5; ++i__) { i__6 = i__ + j * c_dim1; i__7 = i__ + (j - 1) * ldb; c__[i__6].r = bb[i__7].r, c__[i__6].i = bb[i__7].i; i__6 = i__ + (j - 1) * ldb; i__7 = i__ + j * b_dim1; q__1.r = alpha.r * b[i__7].r - alpha.i * b[i__7].i, q__1.i = alpha.r * b[i__7].i + alpha.i * b[ i__7].r; bb[i__6].r = q__1.r, bb[i__6].i = q__1.i; /* L60: */ } /* L70: */ } if (left) { cmmch_(transa, "N", &m, &n, &m, & c_b2, &a[a_offset], nmax, &c__[c_offset], nmax, & c_b1, &b[b_offset], nmax, &ct[1], &g[1], &bb[1], & ldb, eps, &err, fatal, nout, &c_false, (ftnlen)1, (ftnlen)1); } else { cmmch_("N", transa, &m, &n, &n, & c_b2, &c__[c_offset], nmax, &a[a_offset], nmax, &c_b1, &b[b_offset], nmax, &ct[1], &g[1], &bb[1], & ldb, eps, &err, fatal, nout, &c_false, (ftnlen)1, (ftnlen)1); } } errmax = max(errmax,err); /* If got really bad answer, report and */ /* return. */ if (*fatal) { goto L150; } } /* L80: */ } /* L90: */ } /* L100: */ } /* L110: */ } /* L120: */ } L130: ; } /* L140: */ } /* Report result. */ if (errmax < *thresh) { io___229.ciunit = *nout; s_wsfe(&io___229); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); e_wsfe(); } else { io___230.ciunit = *nout; s_wsfe(&io___230); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&errmax, (ftnlen)sizeof(real)); e_wsfe(); } goto L160; L150: io___231.ciunit = *nout; s_wsfe(&io___231); do_fio(&c__1, sname, (ftnlen)6); e_wsfe(); io___232.ciunit = *nout; s_wsfe(&io___232); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, side, (ftnlen)1); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, transa, (ftnlen)1); do_fio(&c__1, diag, (ftnlen)1); do_fio(&c__1, (char *)&m, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)); do_fio(&c__2, (char *)&alpha, (ftnlen)sizeof(real)); do_fio(&c__1, (char *)&lda, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&ldb, (ftnlen)sizeof(integer)); e_wsfe(); L160: return 0; /* End of CCHK3. */ } /* cchk3_ */ /* Subroutine */ int cchk4_(char *sname, real *eps, real *thresh, integer * nout, integer *ntra, logical *trace, logical *rewi, logical *fatal, integer *nidim, integer *idim, integer *nalf, complex *alf, integer * nbet, complex *bet, integer *nmax, complex *a, complex *aa, complex * as, complex *b, complex *bb, complex *bs, complex *c__, complex *cc, complex *cs, complex *ct, real *g, ftnlen sname_len) { /* Initialized data */ static char icht[2] = "NC"; static char ichu[2] = "UL"; /* Format strings */ static char fmt_9994[] = "(1x,i6,\002: \002,a6,\002(\002,2(\002'\002,a1" ",\002',\002),2(i3,\002,\002),f4.1,\002, A,\002,i3,\002,\002,f4.1," "\002, C,\002,i3,\002) \002,\002 .\002)"; static char fmt_9993[] = "(1x,i6,\002: \002,a6,\002(\002,2(\002'\002,a1" ",\002',\002),2(i3,\002,\002),\002(\002,f4.1,\002,\002,f4.1,\002)" " , A,\002,i3,\002,(\002,f4.1,\002,\002,f4.1,\002), C,\002,i3," "\002) .\002)"; static char fmt_9992[] = "(\002 ******* FATAL ERROR - ERROR-EXIT TAKEN O" "N VALID CALL *\002,\002******\002)"; static char fmt_9998[] = "(\002 ******* FATAL ERROR - PARAMETER NUMBER" " \002,i2,\002 WAS CH\002,\002ANGED INCORRECTLY *******\002)"; static char fmt_9999[] = "(\002 \002,a6,\002 PASSED THE COMPUTATIONAL TE" "STS (\002,i6,\002 CALL\002,\002S)\002)"; static char fmt_9997[] = "(\002 \002,a6,\002 COMPLETED THE COMPUTATIONAL" " TESTS (\002,i6,\002 C\002,\002ALLS)\002,/\002 ******* BUT WITH " "MAXIMUM TEST RATIO\002,f8.2,\002 - SUSPECT *******\002)"; static char fmt_9995[] = "(\002 THESE ARE THE RESULTS FOR COLUMN" " \002,i3)"; static char fmt_9996[] = "(\002 ******* \002,a6,\002 FAILED ON CALL NUMB" "ER:\002)"; /* System generated locals */ integer a_dim1, a_offset, b_dim1, b_offset, c_dim1, c_offset, i__1, i__2, i__3, i__4, i__5, i__6, i__7; complex q__1; alist al__1; /* Builtin functions */ integer s_cmp(const char *, const char *, ftnlen, ftnlen), s_wsfe(cilist *), do_fio( integer *, char *, ftnlen), e_wsfe(void), f_rew(alist *); /* Local variables */ integer i__, j, k, n, ia, ib, jc, ma, na, nc, ik, in, jj, lj, ks, ns, laa, lda, lcc, ldc; extern logical lce_(complex *, complex *, integer *); complex als; integer ict, icu; real err; complex beta; integer ldas, ldcs; logical same, conj; complex bets; real rals; logical tran, null; char uplo[1]; extern /* Subroutine */ int cmake_(char *, char *, char *, integer *, integer *, complex *, integer *, complex *, integer *, logical *, complex *, ftnlen, ftnlen, ftnlen); complex alpha; extern /* Subroutine */ int cmmch_(char *, char *, integer *, integer *, integer *, complex *, complex *, integer *, complex *, integer *, complex *, complex *, integer *, complex *, real *, complex *, integer *, real *, real *, logical *, integer *, logical *, ftnlen, ftnlen), cherk_(char *, char *, integer *, integer *, real *, complex *, integer *, real *, complex *, integer *, ftnlen, ftnlen); real rbeta; logical isame[13]; integer nargs; real rbets; logical reset; char trans[1]; logical upper; extern /* Subroutine */ int csyrk_(char *, char *, integer *, integer *, complex *, complex *, integer *, complex *, complex *, integer *, ftnlen, ftnlen); char uplos[1]; real ralpha; extern logical lceres_(char *, char *, integer *, integer *, complex *, complex *, integer *, ftnlen, ftnlen); real errmax; char transs[1], transt[1]; /* Fortran I/O blocks */ static cilist io___274 = { 0, 0, 0, fmt_9994, 0 }; static cilist io___275 = { 0, 0, 0, fmt_9993, 0 }; static cilist io___276 = { 0, 0, 0, fmt_9992, 0 }; static cilist io___279 = { 0, 0, 0, fmt_9998, 0 }; static cilist io___286 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___287 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___288 = { 0, 0, 0, fmt_9995, 0 }; static cilist io___289 = { 0, 0, 0, fmt_9996, 0 }; static cilist io___290 = { 0, 0, 0, fmt_9994, 0 }; static cilist io___291 = { 0, 0, 0, fmt_9993, 0 }; /* Tests CHERK and CSYRK. */ /* Auxiliary routine for test program for Level 3 Blas. */ /* -- Written on 8-February-1989. */ /* Jack Dongarra, Argonne National Laboratory. */ /* Iain Duff, AERE Harwell. */ /* Jeremy Du Croz, Numerical Algorithms Group Ltd. */ /* Sven Hammarling, Numerical Algorithms Group Ltd. */ /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Scalars .. */ /* .. Local Arrays .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. Scalars in Common .. */ /* .. Common blocks .. */ /* .. Data statements .. */ /* Parameter adjustments */ --idim; --alf; --bet; --g; --ct; --cs; --cc; c_dim1 = *nmax; c_offset = 1 + c_dim1; c__ -= c_offset; --bs; --bb; b_dim1 = *nmax; b_offset = 1 + b_dim1; b -= b_offset; --as; --aa; a_dim1 = *nmax; a_offset = 1 + a_dim1; a -= a_offset; /* Function Body */ /* .. Executable Statements .. */ conj = s_cmp(sname + 1, "HE", (ftnlen)2, (ftnlen)2) == 0; nargs = 10; nc = 0; reset = TRUE_; errmax = 0.f; i__1 = *nidim; for (in = 1; in <= i__1; ++in) { n = idim[in]; /* Set LDC to 1 more than minimum value if room. */ ldc = n; if (ldc < *nmax) { ++ldc; } /* Skip tests if not enough room. */ if (ldc > *nmax) { goto L100; } lcc = ldc * n; i__2 = *nidim; for (ik = 1; ik <= i__2; ++ik) { k = idim[ik]; for (ict = 1; ict <= 2; ++ict) { *(unsigned char *)trans = *(unsigned char *)&icht[ict - 1]; tran = *(unsigned char *)trans == 'C'; if (tran && ! conj) { *(unsigned char *)trans = 'T'; } if (tran) { ma = k; na = n; } else { ma = n; na = k; } /* Set LDA to 1 more than minimum value if room. */ lda = ma; if (lda < *nmax) { ++lda; } /* Skip tests if not enough room. */ if (lda > *nmax) { goto L80; } laa = lda * na; /* Generate the matrix A. */ cmake_("GE", " ", " ", &ma, &na, &a[a_offset], nmax, &aa[1], & lda, &reset, &c_b1, (ftnlen)2, (ftnlen)1, (ftnlen)1); for (icu = 1; icu <= 2; ++icu) { *(unsigned char *)uplo = *(unsigned char *)&ichu[icu - 1]; upper = *(unsigned char *)uplo == 'U'; i__3 = *nalf; for (ia = 1; ia <= i__3; ++ia) { i__4 = ia; alpha.r = alf[i__4].r, alpha.i = alf[i__4].i; if (conj) { ralpha = alpha.r; q__1.r = ralpha, q__1.i = 0.f; alpha.r = q__1.r, alpha.i = q__1.i; } i__4 = *nbet; for (ib = 1; ib <= i__4; ++ib) { i__5 = ib; beta.r = bet[i__5].r, beta.i = bet[i__5].i; if (conj) { rbeta = beta.r; q__1.r = rbeta, q__1.i = 0.f; beta.r = q__1.r, beta.i = q__1.i; } null = n <= 0; if (conj) { null = null || (k <= 0 || ralpha == 0.f) && rbeta == 1.f; } /* Generate the matrix C. */ cmake_(sname + 1, uplo, " ", &n, &n, &c__[ c_offset], nmax, &cc[1], &ldc, &reset, & c_b1, (ftnlen)2, (ftnlen)1, (ftnlen)1); ++nc; /* Save every datum before calling the subroutine. */ *(unsigned char *)uplos = *(unsigned char *)uplo; *(unsigned char *)transs = *(unsigned char *) trans; ns = n; ks = k; if (conj) { rals = ralpha; } else { als.r = alpha.r, als.i = alpha.i; } i__5 = laa; for (i__ = 1; i__ <= i__5; ++i__) { i__6 = i__; i__7 = i__; as[i__6].r = aa[i__7].r, as[i__6].i = aa[i__7] .i; /* L10: */ } ldas = lda; if (conj) { rbets = rbeta; } else { bets.r = beta.r, bets.i = beta.i; } i__5 = lcc; for (i__ = 1; i__ <= i__5; ++i__) { i__6 = i__; i__7 = i__; cs[i__6].r = cc[i__7].r, cs[i__6].i = cc[i__7] .i; /* L20: */ } ldcs = ldc; /* Call the subroutine. */ if (conj) { if (*trace) { io___274.ciunit = *ntra; s_wsfe(&io___274); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof( integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&k, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&ralpha, (ftnlen) sizeof(real)); do_fio(&c__1, (char *)&lda, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&rbeta, (ftnlen) sizeof(real)); do_fio(&c__1, (char *)&ldc, (ftnlen) sizeof(integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } cherk_(uplo, trans, &n, &k, &ralpha, &aa[1], & lda, &rbeta, &cc[1], &ldc, (ftnlen)1, (ftnlen)1); } else { if (*trace) { io___275.ciunit = *ntra; s_wsfe(&io___275); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof( integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&k, (ftnlen)sizeof( integer)); do_fio(&c__2, (char *)&alpha, (ftnlen) sizeof(real)); do_fio(&c__1, (char *)&lda, (ftnlen) sizeof(integer)); do_fio(&c__2, (char *)&beta, (ftnlen) sizeof(real)); do_fio(&c__1, (char *)&ldc, (ftnlen) sizeof(integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } csyrk_(uplo, trans, &n, &k, &alpha, &aa[1], & lda, &beta, &cc[1], &ldc, (ftnlen)1, ( ftnlen)1); } /* Check if error-exit was taken incorrectly. */ if (! infoc_1.ok) { io___276.ciunit = *nout; s_wsfe(&io___276); e_wsfe(); *fatal = TRUE_; goto L120; } /* See what data changed inside subroutines. */ isame[0] = *(unsigned char *)uplos == *(unsigned char *)uplo; isame[1] = *(unsigned char *)transs == *(unsigned char *)trans; isame[2] = ns == n; isame[3] = ks == k; if (conj) { isame[4] = rals == ralpha; } else { isame[4] = als.r == alpha.r && als.i == alpha.i; } isame[5] = lce_(&as[1], &aa[1], &laa); isame[6] = ldas == lda; if (conj) { isame[7] = rbets == rbeta; } else { isame[7] = bets.r == beta.r && bets.i == beta.i; } if (null) { isame[8] = lce_(&cs[1], &cc[1], &lcc); } else { isame[8] = lceres_(sname + 1, uplo, &n, &n, & cs[1], &cc[1], &ldc, (ftnlen)2, ( ftnlen)1); } isame[9] = ldcs == ldc; /* If data was incorrectly changed, report and */ /* return. */ same = TRUE_; i__5 = nargs; for (i__ = 1; i__ <= i__5; ++i__) { same = same && isame[i__ - 1]; if (! isame[i__ - 1]) { io___279.ciunit = *nout; s_wsfe(&io___279); do_fio(&c__1, (char *)&i__, (ftnlen) sizeof(integer)); e_wsfe(); } /* L30: */ } if (! same) { *fatal = TRUE_; goto L120; } if (! null) { /* Check the result column by column. */ if (conj) { *(unsigned char *)transt = 'C'; } else { *(unsigned char *)transt = 'T'; } jc = 1; i__5 = n; for (j = 1; j <= i__5; ++j) { if (upper) { jj = 1; lj = j; } else { jj = j; lj = n - j + 1; } if (tran) { cmmch_(transt, "N", &lj, &c__1, &k, & alpha, &a[jj * a_dim1 + 1], nmax, &a[j * a_dim1 + 1], nmax, &beta, &c__[jj + j * c_dim1], nmax, &ct[1], &g[1], &cc[jc], &ldc, eps, &err, fatal, nout, &c_true, (ftnlen) 1, (ftnlen)1); } else { cmmch_("N", transt, &lj, &c__1, &k, & alpha, &a[jj + a_dim1], nmax, &a[j + a_dim1], nmax, &beta, & c__[jj + j * c_dim1], nmax, & ct[1], &g[1], &cc[jc], &ldc, eps, &err, fatal, nout, & c_true, (ftnlen)1, (ftnlen)1); } if (upper) { jc += ldc; } else { jc = jc + ldc + 1; } errmax = max(errmax,err); /* If got really bad answer, report and */ /* return. */ if (*fatal) { goto L110; } /* L40: */ } } /* L50: */ } /* L60: */ } /* L70: */ } L80: ; } /* L90: */ } L100: ; } /* Report result. */ if (errmax < *thresh) { io___286.ciunit = *nout; s_wsfe(&io___286); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); e_wsfe(); } else { io___287.ciunit = *nout; s_wsfe(&io___287); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&errmax, (ftnlen)sizeof(real)); e_wsfe(); } goto L130; L110: if (n > 1) { io___288.ciunit = *nout; s_wsfe(&io___288); do_fio(&c__1, (char *)&j, (ftnlen)sizeof(integer)); e_wsfe(); } L120: io___289.ciunit = *nout; s_wsfe(&io___289); do_fio(&c__1, sname, (ftnlen)6); e_wsfe(); if (conj) { io___290.ciunit = *nout; s_wsfe(&io___290); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&k, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&ralpha, (ftnlen)sizeof(real)); do_fio(&c__1, (char *)&lda, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&rbeta, (ftnlen)sizeof(real)); do_fio(&c__1, (char *)&ldc, (ftnlen)sizeof(integer)); e_wsfe(); } else { io___291.ciunit = *nout; s_wsfe(&io___291); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&k, (ftnlen)sizeof(integer)); do_fio(&c__2, (char *)&alpha, (ftnlen)sizeof(real)); do_fio(&c__1, (char *)&lda, (ftnlen)sizeof(integer)); do_fio(&c__2, (char *)&beta, (ftnlen)sizeof(real)); do_fio(&c__1, (char *)&ldc, (ftnlen)sizeof(integer)); e_wsfe(); } L130: return 0; /* End of CCHK4. */ } /* cchk4_ */ /* Subroutine */ int cchk5_(char *sname, real *eps, real *thresh, integer * nout, integer *ntra, logical *trace, logical *rewi, logical *fatal, integer *nidim, integer *idim, integer *nalf, complex *alf, integer * nbet, complex *bet, integer *nmax, complex *ab, complex *aa, complex * as, complex *bb, complex *bs, complex *c__, complex *cc, complex *cs, complex *ct, real *g, complex *w, ftnlen sname_len) { /* Initialized data */ static char icht[2] = "NC"; static char ichu[2] = "UL"; /* Format strings */ static char fmt_9994[] = "(1x,i6,\002: \002,a6,\002(\002,2(\002'\002,a1" ",\002',\002),2(i3,\002,\002),\002(\002,f4.1,\002,\002,f4.1,\002)" ", A,\002,i3,\002, B,\002,i3,\002,\002,f4.1,\002, C,\002,i3,\002)" " .\002)"; static char fmt_9993[] = "(1x,i6,\002: \002,a6,\002(\002,2(\002'\002,a1" ",\002',\002),2(i3,\002,\002),\002(\002,f4.1,\002,\002,f4.1,\002)" ", A,\002,i3,\002, B,\002,i3,\002,(\002,f4.1,\002,\002,f4.1,\002)" ", C,\002,i3,\002) .\002)"; static char fmt_9992[] = "(\002 ******* FATAL ERROR - ERROR-EXIT TAKEN O" "N VALID CALL *\002,\002******\002)"; static char fmt_9998[] = "(\002 ******* FATAL ERROR - PARAMETER NUMBER" " \002,i2,\002 WAS CH\002,\002ANGED INCORRECTLY *******\002)"; static char fmt_9999[] = "(\002 \002,a6,\002 PASSED THE COMPUTATIONAL TE" "STS (\002,i6,\002 CALL\002,\002S)\002)"; static char fmt_9997[] = "(\002 \002,a6,\002 COMPLETED THE COMPUTATIONAL" " TESTS (\002,i6,\002 C\002,\002ALLS)\002,/\002 ******* BUT WITH " "MAXIMUM TEST RATIO\002,f8.2,\002 - SUSPECT *******\002)"; static char fmt_9995[] = "(\002 THESE ARE THE RESULTS FOR COLUMN" " \002,i3)"; static char fmt_9996[] = "(\002 ******* \002,a6,\002 FAILED ON CALL NUMB" "ER:\002)"; /* System generated locals */ integer c_dim1, c_offset, i__1, i__2, i__3, i__4, i__5, i__6, i__7, i__8; complex q__1, q__2; alist al__1; /* Builtin functions */ integer s_cmp(const char *, const char *, ftnlen, ftnlen), s_wsfe(cilist *), do_fio( integer *, char *, ftnlen), e_wsfe(void), f_rew(alist *); void r_cnjg(complex *, complex *); /* Local variables */ integer i__, j, k, n, ia, ib, jc, ma, na, nc, ik, in, jj, lj, ks, ns, laa, lbb, lda, lcc, ldb, ldc; extern logical lce_(complex *, complex *, integer *); complex als; integer ict, icu; real err; integer jjab; complex beta; integer ldas, ldbs, ldcs; logical same, conj; complex bets; logical tran, null; char uplo[1]; extern /* Subroutine */ int cmake_(char *, char *, char *, integer *, integer *, complex *, integer *, complex *, integer *, logical *, complex *, ftnlen, ftnlen, ftnlen); complex alpha; extern /* Subroutine */ int cmmch_(char *, char *, integer *, integer *, integer *, complex *, complex *, integer *, complex *, integer *, complex *, complex *, integer *, complex *, real *, complex *, integer *, real *, real *, logical *, integer *, logical *, ftnlen, ftnlen); real rbeta; logical isame[13]; integer nargs; real rbets; logical reset; char trans[1]; logical upper; char uplos[1]; extern /* Subroutine */ int cher2k_(char *, char *, integer *, integer *, complex *, complex *, integer *, complex *, integer *, real *, complex *, integer *, ftnlen, ftnlen), csyr2k_(char *, char *, integer *, integer *, complex *, complex *, integer *, complex *, integer *, complex *, complex *, integer *, ftnlen, ftnlen); extern logical lceres_(char *, char *, integer *, integer *, complex *, complex *, integer *, ftnlen, ftnlen); real errmax; char transs[1], transt[1]; /* Fortran I/O blocks */ static cilist io___334 = { 0, 0, 0, fmt_9994, 0 }; static cilist io___335 = { 0, 0, 0, fmt_9993, 0 }; static cilist io___336 = { 0, 0, 0, fmt_9992, 0 }; static cilist io___339 = { 0, 0, 0, fmt_9998, 0 }; static cilist io___347 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___348 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___349 = { 0, 0, 0, fmt_9995, 0 }; static cilist io___350 = { 0, 0, 0, fmt_9996, 0 }; static cilist io___351 = { 0, 0, 0, fmt_9994, 0 }; static cilist io___352 = { 0, 0, 0, fmt_9993, 0 }; /* Tests CHER2K and CSYR2K. */ /* Auxiliary routine for test program for Level 3 Blas. */ /* -- Written on 8-February-1989. */ /* Jack Dongarra, Argonne National Laboratory. */ /* Iain Duff, AERE Harwell. */ /* Jeremy Du Croz, Numerical Algorithms Group Ltd. */ /* Sven Hammarling, Numerical Algorithms Group Ltd. */ /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Scalars .. */ /* .. Local Arrays .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. Scalars in Common .. */ /* .. Common blocks .. */ /* .. Data statements .. */ /* Parameter adjustments */ --idim; --alf; --bet; --w; --g; --ct; --cs; --cc; c_dim1 = *nmax; c_offset = 1 + c_dim1; c__ -= c_offset; --bs; --bb; --as; --aa; --ab; /* Function Body */ /* .. Executable Statements .. */ conj = s_cmp(sname + 1, "HE", (ftnlen)2, (ftnlen)2) == 0; nargs = 12; nc = 0; reset = TRUE_; errmax = 0.f; i__1 = *nidim; for (in = 1; in <= i__1; ++in) { n = idim[in]; /* Set LDC to 1 more than minimum value if room. */ ldc = n; if (ldc < *nmax) { ++ldc; } /* Skip tests if not enough room. */ if (ldc > *nmax) { goto L130; } lcc = ldc * n; i__2 = *nidim; for (ik = 1; ik <= i__2; ++ik) { k = idim[ik]; for (ict = 1; ict <= 2; ++ict) { *(unsigned char *)trans = *(unsigned char *)&icht[ict - 1]; tran = *(unsigned char *)trans == 'C'; if (tran && ! conj) { *(unsigned char *)trans = 'T'; } if (tran) { ma = k; na = n; } else { ma = n; na = k; } /* Set LDA to 1 more than minimum value if room. */ lda = ma; if (lda < *nmax) { ++lda; } /* Skip tests if not enough room. */ if (lda > *nmax) { goto L110; } laa = lda * na; /* Generate the matrix A. */ if (tran) { i__3 = *nmax << 1; cmake_("GE", " ", " ", &ma, &na, &ab[1], &i__3, &aa[1], & lda, &reset, &c_b1, (ftnlen)2, (ftnlen)1, (ftnlen) 1); } else { cmake_("GE", " ", " ", &ma, &na, &ab[1], nmax, &aa[1], & lda, &reset, &c_b1, (ftnlen)2, (ftnlen)1, (ftnlen) 1); } /* Generate the matrix B. */ ldb = lda; lbb = laa; if (tran) { i__3 = *nmax << 1; cmake_("GE", " ", " ", &ma, &na, &ab[k + 1], &i__3, &bb[1] , &ldb, &reset, &c_b1, (ftnlen)2, (ftnlen)1, ( ftnlen)1); } else { cmake_("GE", " ", " ", &ma, &na, &ab[k * *nmax + 1], nmax, &bb[1], &ldb, &reset, &c_b1, (ftnlen)2, (ftnlen) 1, (ftnlen)1); } for (icu = 1; icu <= 2; ++icu) { *(unsigned char *)uplo = *(unsigned char *)&ichu[icu - 1]; upper = *(unsigned char *)uplo == 'U'; i__3 = *nalf; for (ia = 1; ia <= i__3; ++ia) { i__4 = ia; alpha.r = alf[i__4].r, alpha.i = alf[i__4].i; i__4 = *nbet; for (ib = 1; ib <= i__4; ++ib) { i__5 = ib; beta.r = bet[i__5].r, beta.i = bet[i__5].i; if (conj) { rbeta = beta.r; q__1.r = rbeta, q__1.i = 0.f; beta.r = q__1.r, beta.i = q__1.i; } null = n <= 0; if (conj) { null = null || (k <= 0 || alpha.r == 0.f && alpha.i == 0.f) && rbeta == 1.f; } /* Generate the matrix C. */ cmake_(sname + 1, uplo, " ", &n, &n, &c__[ c_offset], nmax, &cc[1], &ldc, &reset, & c_b1, (ftnlen)2, (ftnlen)1, (ftnlen)1); ++nc; /* Save every datum before calling the subroutine. */ *(unsigned char *)uplos = *(unsigned char *)uplo; *(unsigned char *)transs = *(unsigned char *) trans; ns = n; ks = k; als.r = alpha.r, als.i = alpha.i; i__5 = laa; for (i__ = 1; i__ <= i__5; ++i__) { i__6 = i__; i__7 = i__; as[i__6].r = aa[i__7].r, as[i__6].i = aa[i__7] .i; /* L10: */ } ldas = lda; i__5 = lbb; for (i__ = 1; i__ <= i__5; ++i__) { i__6 = i__; i__7 = i__; bs[i__6].r = bb[i__7].r, bs[i__6].i = bb[i__7] .i; /* L20: */ } ldbs = ldb; if (conj) { rbets = rbeta; } else { bets.r = beta.r, bets.i = beta.i; } i__5 = lcc; for (i__ = 1; i__ <= i__5; ++i__) { i__6 = i__; i__7 = i__; cs[i__6].r = cc[i__7].r, cs[i__6].i = cc[i__7] .i; /* L30: */ } ldcs = ldc; /* Call the subroutine. */ if (conj) { if (*trace) { io___334.ciunit = *ntra; s_wsfe(&io___334); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof( integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&k, (ftnlen)sizeof( integer)); do_fio(&c__2, (char *)&alpha, (ftnlen) sizeof(real)); do_fio(&c__1, (char *)&lda, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&ldb, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&rbeta, (ftnlen) sizeof(real)); do_fio(&c__1, (char *)&ldc, (ftnlen) sizeof(integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } cher2k_(uplo, trans, &n, &k, &alpha, &aa[1], & lda, &bb[1], &ldb, &rbeta, &cc[1], & ldc, (ftnlen)1, (ftnlen)1); } else { if (*trace) { io___335.ciunit = *ntra; s_wsfe(&io___335); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof( integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&k, (ftnlen)sizeof( integer)); do_fio(&c__2, (char *)&alpha, (ftnlen) sizeof(real)); do_fio(&c__1, (char *)&lda, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&ldb, (ftnlen) sizeof(integer)); do_fio(&c__2, (char *)&beta, (ftnlen) sizeof(real)); do_fio(&c__1, (char *)&ldc, (ftnlen) sizeof(integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } csyr2k_(uplo, trans, &n, &k, &alpha, &aa[1], & lda, &bb[1], &ldb, &beta, &cc[1], & ldc, (ftnlen)1, (ftnlen)1); } /* Check if error-exit was taken incorrectly. */ if (! infoc_1.ok) { io___336.ciunit = *nout; s_wsfe(&io___336); e_wsfe(); *fatal = TRUE_; goto L150; } /* See what data changed inside subroutines. */ isame[0] = *(unsigned char *)uplos == *(unsigned char *)uplo; isame[1] = *(unsigned char *)transs == *(unsigned char *)trans; isame[2] = ns == n; isame[3] = ks == k; isame[4] = als.r == alpha.r && als.i == alpha.i; isame[5] = lce_(&as[1], &aa[1], &laa); isame[6] = ldas == lda; isame[7] = lce_(&bs[1], &bb[1], &lbb); isame[8] = ldbs == ldb; if (conj) { isame[9] = rbets == rbeta; } else { isame[9] = bets.r == beta.r && bets.i == beta.i; } if (null) { isame[10] = lce_(&cs[1], &cc[1], &lcc); } else { isame[10] = lceres_("HE", uplo, &n, &n, &cs[1] , &cc[1], &ldc, (ftnlen)2, (ftnlen)1); } isame[11] = ldcs == ldc; /* If data was incorrectly changed, report and */ /* return. */ same = TRUE_; i__5 = nargs; for (i__ = 1; i__ <= i__5; ++i__) { same = same && isame[i__ - 1]; if (! isame[i__ - 1]) { io___339.ciunit = *nout; s_wsfe(&io___339); do_fio(&c__1, (char *)&i__, (ftnlen) sizeof(integer)); e_wsfe(); } /* L40: */ } if (! same) { *fatal = TRUE_; goto L150; } if (! null) { /* Check the result column by column. */ if (conj) { *(unsigned char *)transt = 'C'; } else { *(unsigned char *)transt = 'T'; } jjab = 1; jc = 1; i__5 = n; for (j = 1; j <= i__5; ++j) { if (upper) { jj = 1; lj = j; } else { jj = j; lj = n - j + 1; } if (tran) { i__6 = k; for (i__ = 1; i__ <= i__6; ++i__) { i__7 = i__; i__8 = (j - 1 << 1) * *nmax + k + i__; q__1.r = alpha.r * ab[i__8].r - alpha.i * ab[i__8].i, q__1.i = alpha.r * ab[ i__8].i + alpha.i * ab[ i__8].r; w[i__7].r = q__1.r, w[i__7].i = q__1.i; if (conj) { i__7 = k + i__; r_cnjg(&q__2, &alpha); i__8 = (j - 1 << 1) * *nmax + i__; q__1.r = q__2.r * ab[i__8].r - q__2.i * ab[i__8].i, q__1.i = q__2.r * ab[i__8].i + q__2.i * ab[ i__8].r; w[i__7].r = q__1.r, w[i__7].i = q__1.i; } else { i__7 = k + i__; i__8 = (j - 1 << 1) * *nmax + i__; q__1.r = alpha.r * ab[i__8].r - alpha.i * ab[i__8] .i, q__1.i = alpha.r * ab[i__8].i + alpha.i * ab[i__8].r; w[i__7].r = q__1.r, w[i__7].i = q__1.i; } /* L50: */ } i__6 = k << 1; i__7 = *nmax << 1; i__8 = *nmax << 1; cmmch_(transt, "N", &lj, &c__1, &i__6, &c_b2, &ab[jjab], &i__7, &w[ 1], &i__8, &beta, &c__[jj + j * c_dim1], nmax, &ct[1], &g[1] , &cc[jc], &ldc, eps, &err, fatal, nout, &c_true, (ftnlen) 1, (ftnlen)1); } else { i__6 = k; for (i__ = 1; i__ <= i__6; ++i__) { if (conj) { i__7 = i__; r_cnjg(&q__2, &ab[(k + i__ - 1) * *nmax + j]); q__1.r = alpha.r * q__2.r - alpha.i * q__2.i, q__1.i = alpha.r * q__2.i + alpha.i * q__2.r; w[i__7].r = q__1.r, w[i__7].i = q__1.i; i__7 = k + i__; i__8 = (i__ - 1) * *nmax + j; q__2.r = alpha.r * ab[i__8].r - alpha.i * ab[i__8] .i, q__2.i = alpha.r * ab[i__8].i + alpha.i * ab[i__8].r; r_cnjg(&q__1, &q__2); w[i__7].r = q__1.r, w[i__7].i = q__1.i; } else { i__7 = i__; i__8 = (k + i__ - 1) * *nmax + j; q__1.r = alpha.r * ab[i__8].r - alpha.i * ab[i__8] .i, q__1.i = alpha.r * ab[i__8].i + alpha.i * ab[i__8].r; w[i__7].r = q__1.r, w[i__7].i = q__1.i; i__7 = k + i__; i__8 = (i__ - 1) * *nmax + j; q__1.r = alpha.r * ab[i__8].r - alpha.i * ab[i__8] .i, q__1.i = alpha.r * ab[i__8].i + alpha.i * ab[i__8].r; w[i__7].r = q__1.r, w[i__7].i = q__1.i; } /* L60: */ } i__6 = k << 1; i__7 = *nmax << 1; cmmch_("N", "N", &lj, &c__1, &i__6, & c_b2, &ab[jj], nmax, &w[1], & i__7, &beta, &c__[jj + j * c_dim1], nmax, &ct[1], &g[1], &cc[jc], &ldc, eps, &err, fatal, nout, &c_true, (ftnlen) 1, (ftnlen)1); } if (upper) { jc += ldc; } else { jc = jc + ldc + 1; if (tran) { jjab += *nmax << 1; } } errmax = max(errmax,err); /* If got really bad answer, report and */ /* return. */ if (*fatal) { goto L140; } /* L70: */ } } /* L80: */ } /* L90: */ } /* L100: */ } L110: ; } /* L120: */ } L130: ; } /* Report result. */ if (errmax < *thresh) { io___347.ciunit = *nout; s_wsfe(&io___347); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); e_wsfe(); } else { io___348.ciunit = *nout; s_wsfe(&io___348); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&errmax, (ftnlen)sizeof(real)); e_wsfe(); } goto L160; L140: if (n > 1) { io___349.ciunit = *nout; s_wsfe(&io___349); do_fio(&c__1, (char *)&j, (ftnlen)sizeof(integer)); e_wsfe(); } L150: io___350.ciunit = *nout; s_wsfe(&io___350); do_fio(&c__1, sname, (ftnlen)6); e_wsfe(); if (conj) { io___351.ciunit = *nout; s_wsfe(&io___351); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&k, (ftnlen)sizeof(integer)); do_fio(&c__2, (char *)&alpha, (ftnlen)sizeof(real)); do_fio(&c__1, (char *)&lda, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&ldb, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&rbeta, (ftnlen)sizeof(real)); do_fio(&c__1, (char *)&ldc, (ftnlen)sizeof(integer)); e_wsfe(); } else { io___352.ciunit = *nout; s_wsfe(&io___352); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&k, (ftnlen)sizeof(integer)); do_fio(&c__2, (char *)&alpha, (ftnlen)sizeof(real)); do_fio(&c__1, (char *)&lda, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&ldb, (ftnlen)sizeof(integer)); do_fio(&c__2, (char *)&beta, (ftnlen)sizeof(real)); do_fio(&c__1, (char *)&ldc, (ftnlen)sizeof(integer)); e_wsfe(); } L160: return 0; /* End of CCHK5. */ } /* cchk5_ */ /* Subroutine */ int cchke_(integer *isnum, char *srnamt, integer *nout, ftnlen srnamt_len) { /* Format strings */ static char fmt_9999[] = "(\002 \002,a6,\002 PASSED THE TESTS OF ERROR-E" "XITS\002)"; static char fmt_9998[] = "(\002 ******* \002,a6,\002 FAILED THE TESTS OF" " ERROR-EXITS *****\002,\002**\002)"; /* Builtin functions */ integer s_wsfe(cilist *), do_fio(integer *, char *, ftnlen), e_wsfe(void); /* Local variables */ complex a[2] /* was [2][1] */, b[2] /* was [2][1] */, c__[2] /* was [2][1] */, beta, alpha; extern /* Subroutine */ int cgemm_(char *, char *, integer *, integer *, integer *, complex *, complex *, integer *, complex *, integer *, complex *, complex *, integer *, ftnlen, ftnlen), chemm_(char *, char *, integer *, integer *, complex *, complex *, integer *, complex *, integer *, complex *, complex *, integer *, ftnlen, ftnlen), cherk_(char *, char *, integer *, integer *, real *, complex *, integer *, real *, complex *, integer *, ftnlen, ftnlen); real rbeta; extern /* Subroutine */ int ctrmm_(char *, char *, char *, char *, integer *, integer *, complex *, complex *, integer *, complex *, integer *, ftnlen, ftnlen, ftnlen, ftnlen), csymm_(char *, char *, integer *, integer *, complex *, complex *, integer *, complex *, integer *, complex *, complex *, integer *, ftnlen, ftnlen), ctrsm_(char *, char *, char *, char *, integer *, integer *, complex *, complex *, integer *, complex *, integer *, ftnlen, ftnlen, ftnlen, ftnlen), csyrk_(char *, char *, integer *, integer *, complex *, complex *, integer *, complex *, complex *, integer *, ftnlen, ftnlen), cher2k_(char *, char *, integer *, integer *, complex *, complex *, integer *, complex *, integer *, real *, complex *, integer *, ftnlen, ftnlen), csyr2k_(char *, char *, integer *, integer *, complex *, complex *, integer *, complex *, integer *, complex *, complex *, integer *, ftnlen, ftnlen); real ralpha; extern /* Subroutine */ int chkxer_(char *, integer *, integer *, logical *, logical *, ftnlen); /* Fortran I/O blocks */ static cilist io___360 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___361 = { 0, 0, 0, fmt_9998, 0 }; /* Tests the error exits from the Level 3 Blas. */ /* Requires a special version of the error-handling routine XERBLA. */ /* A, B and C should not need to be defined. */ /* Auxiliary routine for test program for Level 3 Blas. */ /* -- Written on 8-February-1989. */ /* Jack Dongarra, Argonne National Laboratory. */ /* Iain Duff, AERE Harwell. */ /* Jeremy Du Croz, Numerical Algorithms Group Ltd. */ /* Sven Hammarling, Numerical Algorithms Group Ltd. */ /* 3-19-92: Initialize ALPHA, BETA, RALPHA, and RBETA (eca) */ /* 3-19-92: Fix argument 12 in calls to CSYMM and CHEMM */ /* with INFOT = 9 (eca) */ /* .. Scalar Arguments .. */ /* .. Scalars in Common .. */ /* .. Parameters .. */ /* .. Local Scalars .. */ /* .. Local Arrays .. */ /* .. External Subroutines .. */ /* .. Common blocks .. */ /* .. Executable Statements .. */ /* OK is set to .FALSE. by the special version of XERBLA or by CHKXER */ /* if anything is wrong. */ infoc_1.ok = TRUE_; /* LERR is set to .TRUE. by the special version of XERBLA each time */ /* it is called, and is then tested and re-set by CHKXER. */ infoc_1.lerr = FALSE_; /* Initialize ALPHA, BETA, RALPHA, and RBETA. */ alpha.r = 1.f, alpha.i = -1.f; beta.r = 2.f, beta.i = -2.f; ralpha = 1.f; rbeta = 2.f; switch (*isnum) { case 1: goto L10; case 2: goto L20; case 3: goto L30; case 4: goto L40; case 5: goto L50; case 6: goto L60; case 7: goto L70; case 8: goto L80; case 9: goto L90; } L10: infoc_1.infot = 1; cgemm_("/", "N", &c__0, &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 1; cgemm_("/", "C", &c__0, &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 1; cgemm_("/", "T", &c__0, &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; cgemm_("N", "/", &c__0, &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; cgemm_("C", "/", &c__0, &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; cgemm_("T", "/", &c__0, &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; cgemm_("N", "N", &c_n1, &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; cgemm_("N", "C", &c_n1, &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; cgemm_("N", "T", &c_n1, &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; cgemm_("C", "N", &c_n1, &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; cgemm_("C", "C", &c_n1, &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; cgemm_("C", "T", &c_n1, &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; cgemm_("T", "N", &c_n1, &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; cgemm_("T", "C", &c_n1, &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; cgemm_("T", "T", &c_n1, &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; cgemm_("N", "N", &c__0, &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; cgemm_("N", "C", &c__0, &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; cgemm_("N", "T", &c__0, &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; cgemm_("C", "N", &c__0, &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; cgemm_("C", "C", &c__0, &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; cgemm_("C", "T", &c__0, &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; cgemm_("T", "N", &c__0, &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; cgemm_("T", "C", &c__0, &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; cgemm_("T", "T", &c__0, &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; cgemm_("N", "N", &c__0, &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; cgemm_("N", "C", &c__0, &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; cgemm_("N", "T", &c__0, &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; cgemm_("C", "N", &c__0, &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; cgemm_("C", "C", &c__0, &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; cgemm_("C", "T", &c__0, &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; cgemm_("T", "N", &c__0, &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; cgemm_("T", "C", &c__0, &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; cgemm_("T", "T", &c__0, &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 8; cgemm_("N", "N", &c__2, &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__2, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 8; cgemm_("N", "C", &c__2, &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__2, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 8; cgemm_("N", "T", &c__2, &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__2, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 8; cgemm_("C", "N", &c__0, &c__0, &c__2, &alpha, a, &c__1, b, &c__2, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 8; cgemm_("C", "C", &c__0, &c__0, &c__2, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 8; cgemm_("C", "T", &c__0, &c__0, &c__2, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 8; cgemm_("T", "N", &c__0, &c__0, &c__2, &alpha, a, &c__1, b, &c__2, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 8; cgemm_("T", "C", &c__0, &c__0, &c__2, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 8; cgemm_("T", "T", &c__0, &c__0, &c__2, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 10; cgemm_("N", "N", &c__0, &c__0, &c__2, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 10; cgemm_("C", "N", &c__0, &c__0, &c__2, &alpha, a, &c__2, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 10; cgemm_("T", "N", &c__0, &c__0, &c__2, &alpha, a, &c__2, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 10; cgemm_("N", "C", &c__0, &c__2, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 10; cgemm_("C", "C", &c__0, &c__2, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 10; cgemm_("T", "C", &c__0, &c__2, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 10; cgemm_("N", "T", &c__0, &c__2, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 10; cgemm_("C", "T", &c__0, &c__2, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 10; cgemm_("T", "T", &c__0, &c__2, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 13; cgemm_("N", "N", &c__2, &c__0, &c__0, &alpha, a, &c__2, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 13; cgemm_("N", "C", &c__2, &c__0, &c__0, &alpha, a, &c__2, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 13; cgemm_("N", "T", &c__2, &c__0, &c__0, &alpha, a, &c__2, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 13; cgemm_("C", "N", &c__2, &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 13; cgemm_("C", "C", &c__2, &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 13; cgemm_("C", "T", &c__2, &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 13; cgemm_("T", "N", &c__2, &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 13; cgemm_("T", "C", &c__2, &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 13; cgemm_("T", "T", &c__2, &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L100; L20: infoc_1.infot = 1; chemm_("/", "U", &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; chemm_("L", "/", &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; chemm_("L", "U", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; chemm_("R", "U", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; chemm_("L", "L", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; chemm_("R", "L", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; chemm_("L", "U", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; chemm_("R", "U", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; chemm_("L", "L", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; chemm_("R", "L", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; chemm_("L", "U", &c__2, &c__0, &alpha, a, &c__1, b, &c__2, &beta, c__, & c__2, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; chemm_("R", "U", &c__0, &c__2, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; chemm_("L", "L", &c__2, &c__0, &alpha, a, &c__1, b, &c__2, &beta, c__, & c__2, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; chemm_("R", "L", &c__0, &c__2, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; chemm_("L", "U", &c__2, &c__0, &alpha, a, &c__2, b, &c__1, &beta, c__, & c__2, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; chemm_("R", "U", &c__2, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__2, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; chemm_("L", "L", &c__2, &c__0, &alpha, a, &c__2, b, &c__1, &beta, c__, & c__2, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; chemm_("R", "L", &c__2, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__2, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 12; chemm_("L", "U", &c__2, &c__0, &alpha, a, &c__2, b, &c__2, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 12; chemm_("R", "U", &c__2, &c__0, &alpha, a, &c__1, b, &c__2, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 12; chemm_("L", "L", &c__2, &c__0, &alpha, a, &c__2, b, &c__2, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 12; chemm_("R", "L", &c__2, &c__0, &alpha, a, &c__1, b, &c__2, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L100; L30: infoc_1.infot = 1; csymm_("/", "U", &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; csymm_("L", "/", &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; csymm_("L", "U", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; csymm_("R", "U", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; csymm_("L", "L", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; csymm_("R", "L", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; csymm_("L", "U", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; csymm_("R", "U", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; csymm_("L", "L", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; csymm_("R", "L", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; csymm_("L", "U", &c__2, &c__0, &alpha, a, &c__1, b, &c__2, &beta, c__, & c__2, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; csymm_("R", "U", &c__0, &c__2, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; csymm_("L", "L", &c__2, &c__0, &alpha, a, &c__1, b, &c__2, &beta, c__, & c__2, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; csymm_("R", "L", &c__0, &c__2, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; csymm_("L", "U", &c__2, &c__0, &alpha, a, &c__2, b, &c__1, &beta, c__, & c__2, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; csymm_("R", "U", &c__2, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__2, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; csymm_("L", "L", &c__2, &c__0, &alpha, a, &c__2, b, &c__1, &beta, c__, & c__2, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; csymm_("R", "L", &c__2, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__2, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 12; csymm_("L", "U", &c__2, &c__0, &alpha, a, &c__2, b, &c__2, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 12; csymm_("R", "U", &c__2, &c__0, &alpha, a, &c__1, b, &c__2, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 12; csymm_("L", "L", &c__2, &c__0, &alpha, a, &c__2, b, &c__2, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 12; csymm_("R", "L", &c__2, &c__0, &alpha, a, &c__1, b, &c__2, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L100; L40: infoc_1.infot = 1; ctrmm_("/", "U", "N", "N", &c__0, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; ctrmm_("L", "/", "N", "N", &c__0, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; ctrmm_("L", "U", "/", "N", &c__0, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; ctrmm_("L", "U", "N", "/", &c__0, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; ctrmm_("L", "U", "N", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; ctrmm_("L", "U", "C", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; ctrmm_("L", "U", "T", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; ctrmm_("R", "U", "N", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; ctrmm_("R", "U", "C", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; ctrmm_("R", "U", "T", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; ctrmm_("L", "L", "N", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; ctrmm_("L", "L", "C", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; ctrmm_("L", "L", "T", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; ctrmm_("R", "L", "N", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; ctrmm_("R", "L", "C", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; ctrmm_("R", "L", "T", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; ctrmm_("L", "U", "N", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; ctrmm_("L", "U", "C", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; ctrmm_("L", "U", "T", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; ctrmm_("R", "U", "N", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; ctrmm_("R", "U", "C", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; ctrmm_("R", "U", "T", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; ctrmm_("L", "L", "N", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; ctrmm_("L", "L", "C", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; ctrmm_("L", "L", "T", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; ctrmm_("R", "L", "N", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; ctrmm_("R", "L", "C", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; ctrmm_("R", "L", "T", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; ctrmm_("L", "U", "N", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__2, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; ctrmm_("L", "U", "C", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__2, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; ctrmm_("L", "U", "T", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__2, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; ctrmm_("R", "U", "N", "N", &c__0, &c__2, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; ctrmm_("R", "U", "C", "N", &c__0, &c__2, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; ctrmm_("R", "U", "T", "N", &c__0, &c__2, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; ctrmm_("L", "L", "N", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__2, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; ctrmm_("L", "L", "C", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__2, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; ctrmm_("L", "L", "T", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__2, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; ctrmm_("R", "L", "N", "N", &c__0, &c__2, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; ctrmm_("R", "L", "C", "N", &c__0, &c__2, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; ctrmm_("R", "L", "T", "N", &c__0, &c__2, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; ctrmm_("L", "U", "N", "N", &c__2, &c__0, &alpha, a, &c__2, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; ctrmm_("L", "U", "C", "N", &c__2, &c__0, &alpha, a, &c__2, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; ctrmm_("L", "U", "T", "N", &c__2, &c__0, &alpha, a, &c__2, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; ctrmm_("R", "U", "N", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; ctrmm_("R", "U", "C", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; ctrmm_("R", "U", "T", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; ctrmm_("L", "L", "N", "N", &c__2, &c__0, &alpha, a, &c__2, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; ctrmm_("L", "L", "C", "N", &c__2, &c__0, &alpha, a, &c__2, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; ctrmm_("L", "L", "T", "N", &c__2, &c__0, &alpha, a, &c__2, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; ctrmm_("R", "L", "N", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; ctrmm_("R", "L", "C", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; ctrmm_("R", "L", "T", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L100; L50: infoc_1.infot = 1; ctrsm_("/", "U", "N", "N", &c__0, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; ctrsm_("L", "/", "N", "N", &c__0, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; ctrsm_("L", "U", "/", "N", &c__0, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; ctrsm_("L", "U", "N", "/", &c__0, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; ctrsm_("L", "U", "N", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; ctrsm_("L", "U", "C", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; ctrsm_("L", "U", "T", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; ctrsm_("R", "U", "N", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; ctrsm_("R", "U", "C", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; ctrsm_("R", "U", "T", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; ctrsm_("L", "L", "N", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; ctrsm_("L", "L", "C", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; ctrsm_("L", "L", "T", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; ctrsm_("R", "L", "N", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; ctrsm_("R", "L", "C", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; ctrsm_("R", "L", "T", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; ctrsm_("L", "U", "N", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; ctrsm_("L", "U", "C", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; ctrsm_("L", "U", "T", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; ctrsm_("R", "U", "N", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; ctrsm_("R", "U", "C", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; ctrsm_("R", "U", "T", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; ctrsm_("L", "L", "N", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; ctrsm_("L", "L", "C", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; ctrsm_("L", "L", "T", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; ctrsm_("R", "L", "N", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; ctrsm_("R", "L", "C", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; ctrsm_("R", "L", "T", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; ctrsm_("L", "U", "N", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__2, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; ctrsm_("L", "U", "C", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__2, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; ctrsm_("L", "U", "T", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__2, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; ctrsm_("R", "U", "N", "N", &c__0, &c__2, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; ctrsm_("R", "U", "C", "N", &c__0, &c__2, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; ctrsm_("R", "U", "T", "N", &c__0, &c__2, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; ctrsm_("L", "L", "N", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__2, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; ctrsm_("L", "L", "C", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__2, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; ctrsm_("L", "L", "T", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__2, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; ctrsm_("R", "L", "N", "N", &c__0, &c__2, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; ctrsm_("R", "L", "C", "N", &c__0, &c__2, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; ctrsm_("R", "L", "T", "N", &c__0, &c__2, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; ctrsm_("L", "U", "N", "N", &c__2, &c__0, &alpha, a, &c__2, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; ctrsm_("L", "U", "C", "N", &c__2, &c__0, &alpha, a, &c__2, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; ctrsm_("L", "U", "T", "N", &c__2, &c__0, &alpha, a, &c__2, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; ctrsm_("R", "U", "N", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; ctrsm_("R", "U", "C", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; ctrsm_("R", "U", "T", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; ctrsm_("L", "L", "N", "N", &c__2, &c__0, &alpha, a, &c__2, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; ctrsm_("L", "L", "C", "N", &c__2, &c__0, &alpha, a, &c__2, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; ctrsm_("L", "L", "T", "N", &c__2, &c__0, &alpha, a, &c__2, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; ctrsm_("R", "L", "N", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; ctrsm_("R", "L", "C", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; ctrsm_("R", "L", "T", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L100; L60: infoc_1.infot = 1; cherk_("/", "N", &c__0, &c__0, &ralpha, a, &c__1, &rbeta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; cherk_("U", "T", &c__0, &c__0, &ralpha, a, &c__1, &rbeta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; cherk_("U", "N", &c_n1, &c__0, &ralpha, a, &c__1, &rbeta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; cherk_("U", "C", &c_n1, &c__0, &ralpha, a, &c__1, &rbeta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; cherk_("L", "N", &c_n1, &c__0, &ralpha, a, &c__1, &rbeta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; cherk_("L", "C", &c_n1, &c__0, &ralpha, a, &c__1, &rbeta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; cherk_("U", "N", &c__0, &c_n1, &ralpha, a, &c__1, &rbeta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; cherk_("U", "C", &c__0, &c_n1, &ralpha, a, &c__1, &rbeta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; cherk_("L", "N", &c__0, &c_n1, &ralpha, a, &c__1, &rbeta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; cherk_("L", "C", &c__0, &c_n1, &ralpha, a, &c__1, &rbeta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; cherk_("U", "N", &c__2, &c__0, &ralpha, a, &c__1, &rbeta, c__, &c__2, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; cherk_("U", "C", &c__0, &c__2, &ralpha, a, &c__1, &rbeta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; cherk_("L", "N", &c__2, &c__0, &ralpha, a, &c__1, &rbeta, c__, &c__2, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; cherk_("L", "C", &c__0, &c__2, &ralpha, a, &c__1, &rbeta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 10; cherk_("U", "N", &c__2, &c__0, &ralpha, a, &c__2, &rbeta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 10; cherk_("U", "C", &c__2, &c__0, &ralpha, a, &c__1, &rbeta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 10; cherk_("L", "N", &c__2, &c__0, &ralpha, a, &c__2, &rbeta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 10; cherk_("L", "C", &c__2, &c__0, &ralpha, a, &c__1, &rbeta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L100; L70: infoc_1.infot = 1; csyrk_("/", "N", &c__0, &c__0, &alpha, a, &c__1, &beta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; csyrk_("U", "C", &c__0, &c__0, &alpha, a, &c__1, &beta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; csyrk_("U", "N", &c_n1, &c__0, &alpha, a, &c__1, &beta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; csyrk_("U", "T", &c_n1, &c__0, &alpha, a, &c__1, &beta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; csyrk_("L", "N", &c_n1, &c__0, &alpha, a, &c__1, &beta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; csyrk_("L", "T", &c_n1, &c__0, &alpha, a, &c__1, &beta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; csyrk_("U", "N", &c__0, &c_n1, &alpha, a, &c__1, &beta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; csyrk_("U", "T", &c__0, &c_n1, &alpha, a, &c__1, &beta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; csyrk_("L", "N", &c__0, &c_n1, &alpha, a, &c__1, &beta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; csyrk_("L", "T", &c__0, &c_n1, &alpha, a, &c__1, &beta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; csyrk_("U", "N", &c__2, &c__0, &alpha, a, &c__1, &beta, c__, &c__2, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; csyrk_("U", "T", &c__0, &c__2, &alpha, a, &c__1, &beta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; csyrk_("L", "N", &c__2, &c__0, &alpha, a, &c__1, &beta, c__, &c__2, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; csyrk_("L", "T", &c__0, &c__2, &alpha, a, &c__1, &beta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 10; csyrk_("U", "N", &c__2, &c__0, &alpha, a, &c__2, &beta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 10; csyrk_("U", "T", &c__2, &c__0, &alpha, a, &c__1, &beta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 10; csyrk_("L", "N", &c__2, &c__0, &alpha, a, &c__2, &beta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 10; csyrk_("L", "T", &c__2, &c__0, &alpha, a, &c__1, &beta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L100; L80: infoc_1.infot = 1; cher2k_("/", "N", &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &rbeta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; cher2k_("U", "T", &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &rbeta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; cher2k_("U", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, &rbeta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; cher2k_("U", "C", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, &rbeta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; cher2k_("L", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, &rbeta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; cher2k_("L", "C", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, &rbeta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; cher2k_("U", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, &rbeta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; cher2k_("U", "C", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, &rbeta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; cher2k_("L", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, &rbeta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; cher2k_("L", "C", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, &rbeta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; cher2k_("U", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__1, &rbeta, c__, & c__2, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; cher2k_("U", "C", &c__0, &c__2, &alpha, a, &c__1, b, &c__1, &rbeta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; cher2k_("L", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__1, &rbeta, c__, & c__2, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; cher2k_("L", "C", &c__0, &c__2, &alpha, a, &c__1, b, &c__1, &rbeta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; cher2k_("U", "N", &c__2, &c__0, &alpha, a, &c__2, b, &c__1, &rbeta, c__, & c__2, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; cher2k_("U", "C", &c__0, &c__2, &alpha, a, &c__2, b, &c__1, &rbeta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; cher2k_("L", "N", &c__2, &c__0, &alpha, a, &c__2, b, &c__1, &rbeta, c__, & c__2, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; cher2k_("L", "C", &c__0, &c__2, &alpha, a, &c__2, b, &c__1, &rbeta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 12; cher2k_("U", "N", &c__2, &c__0, &alpha, a, &c__2, b, &c__2, &rbeta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 12; cher2k_("U", "C", &c__2, &c__0, &alpha, a, &c__1, b, &c__1, &rbeta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 12; cher2k_("L", "N", &c__2, &c__0, &alpha, a, &c__2, b, &c__2, &rbeta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 12; cher2k_("L", "C", &c__2, &c__0, &alpha, a, &c__1, b, &c__1, &rbeta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L100; L90: infoc_1.infot = 1; csyr2k_("/", "N", &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; csyr2k_("U", "C", &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; csyr2k_("U", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; csyr2k_("U", "T", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; csyr2k_("L", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; csyr2k_("L", "T", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; csyr2k_("U", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; csyr2k_("U", "T", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; csyr2k_("L", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; csyr2k_("L", "T", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; csyr2k_("U", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__2, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; csyr2k_("U", "T", &c__0, &c__2, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; csyr2k_("L", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__2, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; csyr2k_("L", "T", &c__0, &c__2, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; csyr2k_("U", "N", &c__2, &c__0, &alpha, a, &c__2, b, &c__1, &beta, c__, & c__2, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; csyr2k_("U", "T", &c__0, &c__2, &alpha, a, &c__2, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; csyr2k_("L", "N", &c__2, &c__0, &alpha, a, &c__2, b, &c__1, &beta, c__, & c__2, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; csyr2k_("L", "T", &c__0, &c__2, &alpha, a, &c__2, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 12; csyr2k_("U", "N", &c__2, &c__0, &alpha, a, &c__2, b, &c__2, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 12; csyr2k_("U", "T", &c__2, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 12; csyr2k_("L", "N", &c__2, &c__0, &alpha, a, &c__2, b, &c__2, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 12; csyr2k_("L", "T", &c__2, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); L100: if (infoc_1.ok) { io___360.ciunit = *nout; s_wsfe(&io___360); do_fio(&c__1, srnamt, (ftnlen)6); e_wsfe(); } else { io___361.ciunit = *nout; s_wsfe(&io___361); do_fio(&c__1, srnamt, (ftnlen)6); e_wsfe(); } return 0; /* End of CCHKE. */ } /* cchke_ */ /* Subroutine */ int cmake_(char *type__, char *uplo, char *diag, integer *m, integer *n, complex *a, integer *nmax, complex *aa, integer *lda, logical *reset, complex *transl, ftnlen type_len, ftnlen uplo_len, ftnlen diag_len) { /* System generated locals */ integer a_dim1, a_offset, i__1, i__2, i__3, i__4; real r__1; complex q__1, q__2; /* Builtin functions */ integer s_cmp(const char *, const char *, ftnlen, ftnlen); void r_cnjg(complex *, complex *); /* Local variables */ integer i__, j, jj; logical gen, her, tri, sym; extern /* Complex */ void cbeg_(complex *, logical *); integer ibeg, iend; logical unit, lower, upper; /* Generates values for an M by N matrix A. */ /* Stores the values in the array AA in the data structure required */ /* by the routine, with unwanted elements set to rogue value. */ /* TYPE is 'GE', 'HE', 'SY' or 'TR'. */ /* Auxiliary routine for test program for Level 3 Blas. */ /* -- Written on 8-February-1989. */ /* Jack Dongarra, Argonne National Laboratory. */ /* Iain Duff, AERE Harwell. */ /* Jeremy Du Croz, Numerical Algorithms Group Ltd. */ /* Sven Hammarling, Numerical Algorithms Group Ltd. */ /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Scalars .. */ /* .. External Functions .. */ /* .. Intrinsic Functions .. */ /* .. Executable Statements .. */ /* Parameter adjustments */ a_dim1 = *nmax; a_offset = 1 + a_dim1; a -= a_offset; --aa; /* Function Body */ gen = s_cmp(type__, "GE", (ftnlen)2, (ftnlen)2) == 0; her = s_cmp(type__, "HE", (ftnlen)2, (ftnlen)2) == 0; sym = s_cmp(type__, "SY", (ftnlen)2, (ftnlen)2) == 0; tri = s_cmp(type__, "TR", (ftnlen)2, (ftnlen)2) == 0; upper = (her || sym || tri) && *(unsigned char *)uplo == 'U'; lower = (her || sym || tri) && *(unsigned char *)uplo == 'L'; unit = tri && *(unsigned char *)diag == 'U'; /* Generate data in array A. */ i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = *m; for (i__ = 1; i__ <= i__2; ++i__) { if (gen || upper && i__ <= j || lower && i__ >= j) { i__3 = i__ + j * a_dim1; cbeg_(&q__2, reset); q__1.r = q__2.r + transl->r, q__1.i = q__2.i + transl->i; a[i__3].r = q__1.r, a[i__3].i = q__1.i; if (i__ != j) { /* Set some elements to zero */ if (*n > 3 && j == *n / 2) { i__3 = i__ + j * a_dim1; a[i__3].r = 0.f, a[i__3].i = 0.f; } if (her) { i__3 = j + i__ * a_dim1; r_cnjg(&q__1, &a[i__ + j * a_dim1]); a[i__3].r = q__1.r, a[i__3].i = q__1.i; } else if (sym) { i__3 = j + i__ * a_dim1; i__4 = i__ + j * a_dim1; a[i__3].r = a[i__4].r, a[i__3].i = a[i__4].i; } else if (tri) { i__3 = j + i__ * a_dim1; a[i__3].r = 0.f, a[i__3].i = 0.f; } } } /* L10: */ } if (her) { i__2 = j + j * a_dim1; i__3 = j + j * a_dim1; r__1 = a[i__3].r; q__1.r = r__1, q__1.i = 0.f; a[i__2].r = q__1.r, a[i__2].i = q__1.i; } if (tri) { i__2 = j + j * a_dim1; i__3 = j + j * a_dim1; q__1.r = a[i__3].r + 1.f, q__1.i = a[i__3].i + 0.f; a[i__2].r = q__1.r, a[i__2].i = q__1.i; } if (unit) { i__2 = j + j * a_dim1; a[i__2].r = 1.f, a[i__2].i = 0.f; } /* L20: */ } /* Store elements in array AS in data structure required by routine. */ if (s_cmp(type__, "GE", (ftnlen)2, (ftnlen)2) == 0) { i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = *m; for (i__ = 1; i__ <= i__2; ++i__) { i__3 = i__ + (j - 1) * *lda; i__4 = i__ + j * a_dim1; aa[i__3].r = a[i__4].r, aa[i__3].i = a[i__4].i; /* L30: */ } i__2 = *lda; for (i__ = *m + 1; i__ <= i__2; ++i__) { i__3 = i__ + (j - 1) * *lda; aa[i__3].r = -1e10f, aa[i__3].i = 1e10f; /* L40: */ } /* L50: */ } } else if (s_cmp(type__, "HE", (ftnlen)2, (ftnlen)2) == 0 || s_cmp(type__, "SY", (ftnlen)2, (ftnlen)2) == 0 || s_cmp(type__, "TR", (ftnlen) 2, (ftnlen)2) == 0) { i__1 = *n; for (j = 1; j <= i__1; ++j) { if (upper) { ibeg = 1; if (unit) { iend = j - 1; } else { iend = j; } } else { if (unit) { ibeg = j + 1; } else { ibeg = j; } iend = *n; } i__2 = ibeg - 1; for (i__ = 1; i__ <= i__2; ++i__) { i__3 = i__ + (j - 1) * *lda; aa[i__3].r = -1e10f, aa[i__3].i = 1e10f; /* L60: */ } i__2 = iend; for (i__ = ibeg; i__ <= i__2; ++i__) { i__3 = i__ + (j - 1) * *lda; i__4 = i__ + j * a_dim1; aa[i__3].r = a[i__4].r, aa[i__3].i = a[i__4].i; /* L70: */ } i__2 = *lda; for (i__ = iend + 1; i__ <= i__2; ++i__) { i__3 = i__ + (j - 1) * *lda; aa[i__3].r = -1e10f, aa[i__3].i = 1e10f; /* L80: */ } if (her) { jj = j + (j - 1) * *lda; i__2 = jj; i__3 = jj; r__1 = aa[i__3].r; q__1.r = r__1, q__1.i = -1e10f; aa[i__2].r = q__1.r, aa[i__2].i = q__1.i; } /* L90: */ } } return 0; /* End of CMAKE. */ } /* cmake_ */ /* Subroutine */ int cmmch_(char *transa, char *transb, integer *m, integer * n, integer *kk, complex *alpha, complex *a, integer *lda, complex *b, integer *ldb, complex *beta, complex *c__, integer *ldc, complex *ct, real *g, complex *cc, integer *ldcc, real *eps, real *err, logical * fatal, integer *nout, logical *mv, ftnlen transa_len, ftnlen transb_len) { /* Format strings */ static char fmt_9999[] = "(\002 ******* FATAL ERROR - COMPUTED RESULT IS" " LESS THAN HAL\002,\002F ACCURATE *******\002,/\002 " " EXPECTED RE\002,\002SULT COMPUTED R" "ESULT\002)"; static char fmt_9998[] = "(1x,i7,2(\002 (\002,g15.6,\002,\002,g15.6," "\002)\002))"; static char fmt_9997[] = "(\002 THESE ARE THE RESULTS FOR COLUMN" " \002,i3)"; /* System generated locals */ integer a_dim1, a_offset, b_dim1, b_offset, c_dim1, c_offset, cc_dim1, cc_offset, i__1, i__2, i__3, i__4, i__5, i__6, i__7; real r__1, r__2, r__3, r__4, r__5, r__6; complex q__1, q__2, q__3, q__4; /* Builtin functions */ double r_imag(complex *); void r_cnjg(complex *, complex *); double sqrt(doublereal); integer s_wsfe(cilist *), e_wsfe(void), do_fio(integer *, char *, ftnlen); /* Local variables */ integer i__, j, k; real erri; logical trana, tranb, ctrana, ctranb; /* Fortran I/O blocks */ static cilist io___382 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___383 = { 0, 0, 0, fmt_9998, 0 }; static cilist io___384 = { 0, 0, 0, fmt_9998, 0 }; static cilist io___385 = { 0, 0, 0, fmt_9997, 0 }; /* Checks the results of the computational tests. */ /* Auxiliary routine for test program for Level 3 Blas. */ /* -- Written on 8-February-1989. */ /* Jack Dongarra, Argonne National Laboratory. */ /* Iain Duff, AERE Harwell. */ /* Jeremy Du Croz, Numerical Algorithms Group Ltd. */ /* Sven Hammarling, Numerical Algorithms Group Ltd. */ /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Scalars .. */ /* .. Intrinsic Functions .. */ /* .. Statement Functions .. */ /* .. Statement Function definitions .. */ /* .. Executable Statements .. */ /* Parameter adjustments */ a_dim1 = *lda; a_offset = 1 + a_dim1; a -= a_offset; b_dim1 = *ldb; b_offset = 1 + b_dim1; b -= b_offset; c_dim1 = *ldc; c_offset = 1 + c_dim1; c__ -= c_offset; --ct; --g; cc_dim1 = *ldcc; cc_offset = 1 + cc_dim1; cc -= cc_offset; /* Function Body */ trana = *(unsigned char *)transa == 'T' || *(unsigned char *)transa == 'C'; tranb = *(unsigned char *)transb == 'T' || *(unsigned char *)transb == 'C'; ctrana = *(unsigned char *)transa == 'C'; ctranb = *(unsigned char *)transb == 'C'; /* Compute expected result, one column at a time, in CT using data */ /* in A, B and C. */ /* Compute gauges in G. */ i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = *m; for (i__ = 1; i__ <= i__2; ++i__) { i__3 = i__; ct[i__3].r = 0.f, ct[i__3].i = 0.f; g[i__] = 0.f; /* L10: */ } if (! trana && ! tranb) { i__2 = *kk; for (k = 1; k <= i__2; ++k) { i__3 = *m; for (i__ = 1; i__ <= i__3; ++i__) { i__4 = i__; i__5 = i__; i__6 = i__ + k * a_dim1; i__7 = k + j * b_dim1; q__2.r = a[i__6].r * b[i__7].r - a[i__6].i * b[i__7].i, q__2.i = a[i__6].r * b[i__7].i + a[i__6].i * b[ i__7].r; q__1.r = ct[i__5].r + q__2.r, q__1.i = ct[i__5].i + q__2.i; ct[i__4].r = q__1.r, ct[i__4].i = q__1.i; i__4 = i__ + k * a_dim1; i__5 = k + j * b_dim1; g[i__] += ((r__1 = a[i__4].r, abs(r__1)) + (r__2 = r_imag( &a[i__ + k * a_dim1]), abs(r__2))) * ((r__3 = b[ i__5].r, abs(r__3)) + (r__4 = r_imag(&b[k + j * b_dim1]), abs(r__4))); /* L20: */ } /* L30: */ } } else if (trana && ! tranb) { if (ctrana) { i__2 = *kk; for (k = 1; k <= i__2; ++k) { i__3 = *m; for (i__ = 1; i__ <= i__3; ++i__) { i__4 = i__; i__5 = i__; r_cnjg(&q__3, &a[k + i__ * a_dim1]); i__6 = k + j * b_dim1; q__2.r = q__3.r * b[i__6].r - q__3.i * b[i__6].i, q__2.i = q__3.r * b[i__6].i + q__3.i * b[i__6] .r; q__1.r = ct[i__5].r + q__2.r, q__1.i = ct[i__5].i + q__2.i; ct[i__4].r = q__1.r, ct[i__4].i = q__1.i; i__4 = k + i__ * a_dim1; i__5 = k + j * b_dim1; g[i__] += ((r__1 = a[i__4].r, abs(r__1)) + (r__2 = r_imag(&a[k + i__ * a_dim1]), abs(r__2))) * (( r__3 = b[i__5].r, abs(r__3)) + (r__4 = r_imag( &b[k + j * b_dim1]), abs(r__4))); /* L40: */ } /* L50: */ } } else { i__2 = *kk; for (k = 1; k <= i__2; ++k) { i__3 = *m; for (i__ = 1; i__ <= i__3; ++i__) { i__4 = i__; i__5 = i__; i__6 = k + i__ * a_dim1; i__7 = k + j * b_dim1; q__2.r = a[i__6].r * b[i__7].r - a[i__6].i * b[i__7] .i, q__2.i = a[i__6].r * b[i__7].i + a[i__6] .i * b[i__7].r; q__1.r = ct[i__5].r + q__2.r, q__1.i = ct[i__5].i + q__2.i; ct[i__4].r = q__1.r, ct[i__4].i = q__1.i; i__4 = k + i__ * a_dim1; i__5 = k + j * b_dim1; g[i__] += ((r__1 = a[i__4].r, abs(r__1)) + (r__2 = r_imag(&a[k + i__ * a_dim1]), abs(r__2))) * (( r__3 = b[i__5].r, abs(r__3)) + (r__4 = r_imag( &b[k + j * b_dim1]), abs(r__4))); /* L60: */ } /* L70: */ } } } else if (! trana && tranb) { if (ctranb) { i__2 = *kk; for (k = 1; k <= i__2; ++k) { i__3 = *m; for (i__ = 1; i__ <= i__3; ++i__) { i__4 = i__; i__5 = i__; i__6 = i__ + k * a_dim1; r_cnjg(&q__3, &b[j + k * b_dim1]); q__2.r = a[i__6].r * q__3.r - a[i__6].i * q__3.i, q__2.i = a[i__6].r * q__3.i + a[i__6].i * q__3.r; q__1.r = ct[i__5].r + q__2.r, q__1.i = ct[i__5].i + q__2.i; ct[i__4].r = q__1.r, ct[i__4].i = q__1.i; i__4 = i__ + k * a_dim1; i__5 = j + k * b_dim1; g[i__] += ((r__1 = a[i__4].r, abs(r__1)) + (r__2 = r_imag(&a[i__ + k * a_dim1]), abs(r__2))) * (( r__3 = b[i__5].r, abs(r__3)) + (r__4 = r_imag( &b[j + k * b_dim1]), abs(r__4))); /* L80: */ } /* L90: */ } } else { i__2 = *kk; for (k = 1; k <= i__2; ++k) { i__3 = *m; for (i__ = 1; i__ <= i__3; ++i__) { i__4 = i__; i__5 = i__; i__6 = i__ + k * a_dim1; i__7 = j + k * b_dim1; q__2.r = a[i__6].r * b[i__7].r - a[i__6].i * b[i__7] .i, q__2.i = a[i__6].r * b[i__7].i + a[i__6] .i * b[i__7].r; q__1.r = ct[i__5].r + q__2.r, q__1.i = ct[i__5].i + q__2.i; ct[i__4].r = q__1.r, ct[i__4].i = q__1.i; i__4 = i__ + k * a_dim1; i__5 = j + k * b_dim1; g[i__] += ((r__1 = a[i__4].r, abs(r__1)) + (r__2 = r_imag(&a[i__ + k * a_dim1]), abs(r__2))) * (( r__3 = b[i__5].r, abs(r__3)) + (r__4 = r_imag( &b[j + k * b_dim1]), abs(r__4))); /* L100: */ } /* L110: */ } } } else if (trana && tranb) { if (ctrana) { if (ctranb) { i__2 = *kk; for (k = 1; k <= i__2; ++k) { i__3 = *m; for (i__ = 1; i__ <= i__3; ++i__) { i__4 = i__; i__5 = i__; r_cnjg(&q__3, &a[k + i__ * a_dim1]); r_cnjg(&q__4, &b[j + k * b_dim1]); q__2.r = q__3.r * q__4.r - q__3.i * q__4.i, q__2.i = q__3.r * q__4.i + q__3.i * q__4.r; q__1.r = ct[i__5].r + q__2.r, q__1.i = ct[i__5].i + q__2.i; ct[i__4].r = q__1.r, ct[i__4].i = q__1.i; i__4 = k + i__ * a_dim1; i__5 = j + k * b_dim1; g[i__] += ((r__1 = a[i__4].r, abs(r__1)) + (r__2 = r_imag(&a[k + i__ * a_dim1]), abs(r__2))) * ((r__3 = b[i__5].r, abs(r__3)) + (r__4 = r_imag(&b[j + k * b_dim1]), abs(r__4))); /* L120: */ } /* L130: */ } } else { i__2 = *kk; for (k = 1; k <= i__2; ++k) { i__3 = *m; for (i__ = 1; i__ <= i__3; ++i__) { i__4 = i__; i__5 = i__; r_cnjg(&q__3, &a[k + i__ * a_dim1]); i__6 = j + k * b_dim1; q__2.r = q__3.r * b[i__6].r - q__3.i * b[i__6].i, q__2.i = q__3.r * b[i__6].i + q__3.i * b[ i__6].r; q__1.r = ct[i__5].r + q__2.r, q__1.i = ct[i__5].i + q__2.i; ct[i__4].r = q__1.r, ct[i__4].i = q__1.i; i__4 = k + i__ * a_dim1; i__5 = j + k * b_dim1; g[i__] += ((r__1 = a[i__4].r, abs(r__1)) + (r__2 = r_imag(&a[k + i__ * a_dim1]), abs(r__2))) * ((r__3 = b[i__5].r, abs(r__3)) + (r__4 = r_imag(&b[j + k * b_dim1]), abs(r__4))); /* L140: */ } /* L150: */ } } } else { if (ctranb) { i__2 = *kk; for (k = 1; k <= i__2; ++k) { i__3 = *m; for (i__ = 1; i__ <= i__3; ++i__) { i__4 = i__; i__5 = i__; i__6 = k + i__ * a_dim1; r_cnjg(&q__3, &b[j + k * b_dim1]); q__2.r = a[i__6].r * q__3.r - a[i__6].i * q__3.i, q__2.i = a[i__6].r * q__3.i + a[i__6].i * q__3.r; q__1.r = ct[i__5].r + q__2.r, q__1.i = ct[i__5].i + q__2.i; ct[i__4].r = q__1.r, ct[i__4].i = q__1.i; i__4 = k + i__ * a_dim1; i__5 = j + k * b_dim1; g[i__] += ((r__1 = a[i__4].r, abs(r__1)) + (r__2 = r_imag(&a[k + i__ * a_dim1]), abs(r__2))) * ((r__3 = b[i__5].r, abs(r__3)) + (r__4 = r_imag(&b[j + k * b_dim1]), abs(r__4))); /* L160: */ } /* L170: */ } } else { i__2 = *kk; for (k = 1; k <= i__2; ++k) { i__3 = *m; for (i__ = 1; i__ <= i__3; ++i__) { i__4 = i__; i__5 = i__; i__6 = k + i__ * a_dim1; i__7 = j + k * b_dim1; q__2.r = a[i__6].r * b[i__7].r - a[i__6].i * b[ i__7].i, q__2.i = a[i__6].r * b[i__7].i + a[i__6].i * b[i__7].r; q__1.r = ct[i__5].r + q__2.r, q__1.i = ct[i__5].i + q__2.i; ct[i__4].r = q__1.r, ct[i__4].i = q__1.i; i__4 = k + i__ * a_dim1; i__5 = j + k * b_dim1; g[i__] += ((r__1 = a[i__4].r, abs(r__1)) + (r__2 = r_imag(&a[k + i__ * a_dim1]), abs(r__2))) * ((r__3 = b[i__5].r, abs(r__3)) + (r__4 = r_imag(&b[j + k * b_dim1]), abs(r__4))); /* L180: */ } /* L190: */ } } } } i__2 = *m; for (i__ = 1; i__ <= i__2; ++i__) { i__3 = i__; i__4 = i__; q__2.r = alpha->r * ct[i__4].r - alpha->i * ct[i__4].i, q__2.i = alpha->r * ct[i__4].i + alpha->i * ct[i__4].r; i__5 = i__ + j * c_dim1; q__3.r = beta->r * c__[i__5].r - beta->i * c__[i__5].i, q__3.i = beta->r * c__[i__5].i + beta->i * c__[i__5].r; q__1.r = q__2.r + q__3.r, q__1.i = q__2.i + q__3.i; ct[i__3].r = q__1.r, ct[i__3].i = q__1.i; i__3 = i__ + j * c_dim1; g[i__] = ((r__1 = alpha->r, abs(r__1)) + (r__2 = r_imag(alpha), abs(r__2))) * g[i__] + ((r__3 = beta->r, abs(r__3)) + ( r__4 = r_imag(beta), abs(r__4))) * ((r__5 = c__[i__3].r, abs(r__5)) + (r__6 = r_imag(&c__[i__ + j * c_dim1]), abs( r__6))); /* L200: */ } /* Compute the error ratio for this result. */ *err = 0.f; i__2 = *m; for (i__ = 1; i__ <= i__2; ++i__) { i__3 = i__; i__4 = i__ + j * cc_dim1; q__2.r = ct[i__3].r - cc[i__4].r, q__2.i = ct[i__3].i - cc[i__4] .i; q__1.r = q__2.r, q__1.i = q__2.i; erri = ((r__1 = q__1.r, abs(r__1)) + (r__2 = r_imag(&q__1), abs( r__2))) / *eps; if (g[i__] != 0.f) { erri /= g[i__]; } *err = max(*err,erri); if (*err * sqrt(*eps) >= 1.f) { goto L230; } /* L210: */ } /* L220: */ } /* If the loop completes, all results are at least half accurate. */ goto L250; /* Report fatal error. */ L230: *fatal = TRUE_; io___382.ciunit = *nout; s_wsfe(&io___382); e_wsfe(); i__1 = *m; for (i__ = 1; i__ <= i__1; ++i__) { if (*mv) { io___383.ciunit = *nout; s_wsfe(&io___383); do_fio(&c__1, (char *)&i__, (ftnlen)sizeof(integer)); do_fio(&c__2, (char *)&ct[i__], (ftnlen)sizeof(real)); do_fio(&c__2, (char *)&cc[i__ + j * cc_dim1], (ftnlen)sizeof(real) ); e_wsfe(); } else { io___384.ciunit = *nout; s_wsfe(&io___384); do_fio(&c__1, (char *)&i__, (ftnlen)sizeof(integer)); do_fio(&c__2, (char *)&cc[i__ + j * cc_dim1], (ftnlen)sizeof(real) ); do_fio(&c__2, (char *)&ct[i__], (ftnlen)sizeof(real)); e_wsfe(); } /* L240: */ } if (*n > 1) { io___385.ciunit = *nout; s_wsfe(&io___385); do_fio(&c__1, (char *)&j, (ftnlen)sizeof(integer)); e_wsfe(); } L250: return 0; /* End of CMMCH. */ } /* cmmch_ */ logical lce_(complex *ri, complex *rj, integer *lr) { /* System generated locals */ integer i__1, i__2, i__3; logical ret_val; /* Local variables */ integer i__; /* Tests if two arrays are identical. */ /* Auxiliary routine for test program for Level 3 Blas. */ /* -- Written on 8-February-1989. */ /* Jack Dongarra, Argonne National Laboratory. */ /* Iain Duff, AERE Harwell. */ /* Jeremy Du Croz, Numerical Algorithms Group Ltd. */ /* Sven Hammarling, Numerical Algorithms Group Ltd. */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Scalars .. */ /* .. Executable Statements .. */ /* Parameter adjustments */ --rj; --ri; /* Function Body */ i__1 = *lr; for (i__ = 1; i__ <= i__1; ++i__) { i__2 = i__; i__3 = i__; if (ri[i__2].r != rj[i__3].r || ri[i__2].i != rj[i__3].i) { goto L20; } /* L10: */ } ret_val = TRUE_; goto L30; L20: ret_val = FALSE_; L30: return ret_val; /* End of LCE. */ } /* lce_ */ logical lceres_(char *type__, char *uplo, integer *m, integer *n, complex *aa, complex *as, integer *lda, ftnlen type_len, ftnlen uplo_len) { /* System generated locals */ integer aa_dim1, aa_offset, as_dim1, as_offset, i__1, i__2, i__3, i__4; logical ret_val; /* Builtin functions */ integer s_cmp(const char *, const char *, ftnlen, ftnlen); /* Local variables */ integer i__, j, ibeg, iend; logical upper; /* Tests if selected elements in two arrays are equal. */ /* TYPE is 'GE' or 'HE' or 'SY'. */ /* Auxiliary routine for test program for Level 3 Blas. */ /* -- Written on 8-February-1989. */ /* Jack Dongarra, Argonne National Laboratory. */ /* Iain Duff, AERE Harwell. */ /* Jeremy Du Croz, Numerical Algorithms Group Ltd. */ /* Sven Hammarling, Numerical Algorithms Group Ltd. */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Scalars .. */ /* .. Executable Statements .. */ /* Parameter adjustments */ as_dim1 = *lda; as_offset = 1 + as_dim1; as -= as_offset; aa_dim1 = *lda; aa_offset = 1 + aa_dim1; aa -= aa_offset; /* Function Body */ upper = *(unsigned char *)uplo == 'U'; if (s_cmp(type__, "GE", (ftnlen)2, (ftnlen)2) == 0) { i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = *lda; for (i__ = *m + 1; i__ <= i__2; ++i__) { i__3 = i__ + j * aa_dim1; i__4 = i__ + j * as_dim1; if (aa[i__3].r != as[i__4].r || aa[i__3].i != as[i__4].i) { goto L70; } /* L10: */ } /* L20: */ } } else if (s_cmp(type__, "HE", (ftnlen)2, (ftnlen)2) == 0 || s_cmp(type__, "SY", (ftnlen)2, (ftnlen)2) == 0) { i__1 = *n; for (j = 1; j <= i__1; ++j) { if (upper) { ibeg = 1; iend = j; } else { ibeg = j; iend = *n; } i__2 = ibeg - 1; for (i__ = 1; i__ <= i__2; ++i__) { i__3 = i__ + j * aa_dim1; i__4 = i__ + j * as_dim1; if (aa[i__3].r != as[i__4].r || aa[i__3].i != as[i__4].i) { goto L70; } /* L30: */ } i__2 = *lda; for (i__ = iend + 1; i__ <= i__2; ++i__) { i__3 = i__ + j * aa_dim1; i__4 = i__ + j * as_dim1; if (aa[i__3].r != as[i__4].r || aa[i__3].i != as[i__4].i) { goto L70; } /* L40: */ } /* L50: */ } } ret_val = TRUE_; goto L80; L70: ret_val = FALSE_; L80: return ret_val; /* End of LCERES. */ } /* lceres_ */ /* Complex */ void cbeg_(complex * ret_val, logical *reset) { /* System generated locals */ real r__1, r__2; complex q__1; /* Local variables */ static integer i__, j, ic, mi, mj; /* Generates complex numbers as pairs of random numbers uniformly */ /* distributed between -0.5 and 0.5. */ /* Auxiliary routine for test program for Level 3 Blas. */ /* -- Written on 8-February-1989. */ /* Jack Dongarra, Argonne National Laboratory. */ /* Iain Duff, AERE Harwell. */ /* Jeremy Du Croz, Numerical Algorithms Group Ltd. */ /* Sven Hammarling, Numerical Algorithms Group Ltd. */ /* .. Scalar Arguments .. */ /* .. Local Scalars .. */ /* .. Save statement .. */ /* .. Intrinsic Functions .. */ /* .. Executable Statements .. */ if (*reset) { /* Initialize local variables. */ mi = 891; mj = 457; i__ = 7; j = 7; ic = 0; *reset = FALSE_; } /* The sequence of values of I or J is bounded between 1 and 999. */ /* If initial I or J = 1,2,3,6,7 or 9, the period will be 50. */ /* If initial I or J = 4 or 8, the period will be 25. */ /* If initial I or J = 5, the period will be 10. */ /* IC is used to break up the period by skipping 1 value of I or J */ /* in 6. */ ++ic; L10: i__ *= mi; j *= mj; i__ -= i__ / 1000 * 1000; j -= j / 1000 * 1000; if (ic >= 5) { ic = 0; goto L10; } r__1 = (i__ - 500) / 1001.f; r__2 = (j - 500) / 1001.f; q__1.r = r__1, q__1.i = r__2; ret_val->r = q__1.r, ret_val->i = q__1.i; return ; /* End of CBEG. */ } /* cbeg_ */ real sdiff_(real *x, real *y) { /* System generated locals */ real ret_val; /* Auxiliary routine for test program for Level 3 Blas. */ /* -- Written on 8-February-1989. */ /* Jack Dongarra, Argonne National Laboratory. */ /* Iain Duff, AERE Harwell. */ /* Jeremy Du Croz, Numerical Algorithms Group Ltd. */ /* Sven Hammarling, Numerical Algorithms Group Ltd. */ /* .. Scalar Arguments .. */ /* .. Executable Statements .. */ ret_val = *x - *y; return ret_val; /* End of SDIFF. */ } /* sdiff_ */ /* Subroutine */ int chkxer_(char *srnamt, integer *infot, integer *nout, logical *lerr, logical *ok, ftnlen srnamt_len) { /* Format strings */ static char fmt_9999[] = "(\002 ***** ILLEGAL VALUE OF PARAMETER NUMBER" " \002,i2,\002 NOT D\002,\002ETECTED BY \002,a6,\002 *****\002)"; /* Builtin functions */ integer s_wsfe(cilist *), do_fio(integer *, char *, ftnlen), e_wsfe(void); /* Fortran I/O blocks */ static cilist io___397 = { 0, 0, 0, fmt_9999, 0 }; /* Tests whether XERBLA has detected an error when it should. */ /* Auxiliary routine for test program for Level 3 Blas. */ /* -- Written on 8-February-1989. */ /* Jack Dongarra, Argonne National Laboratory. */ /* Iain Duff, AERE Harwell. */ /* Jeremy Du Croz, Numerical Algorithms Group Ltd. */ /* Sven Hammarling, Numerical Algorithms Group Ltd. */ /* .. Scalar Arguments .. */ /* .. Executable Statements .. */ if (! (*lerr)) { io___397.ciunit = *nout; s_wsfe(&io___397); do_fio(&c__1, (char *)&(*infot), (ftnlen)sizeof(integer)); do_fio(&c__1, srnamt, (ftnlen)6); e_wsfe(); *ok = FALSE_; } *lerr = FALSE_; return 0; /* End of CHKXER. */ } /* chkxer_ */ /* Subroutine */ int xerbla_(char *srname, integer *info, ftnlen srname_len) { /* Format strings */ static char fmt_9999[] = "(\002 ******* XERBLA WAS CALLED WITH INFO =" " \002,i6,\002 INSTEAD\002,\002 OF \002,i2,\002 *******\002)"; static char fmt_9997[] = "(\002 ******* XERBLA WAS CALLED WITH INFO =" " \002,i6,\002 *******\002)"; static char fmt_9998[] = "(\002 ******* XERBLA WAS CALLED WITH SRNAME =" " \002,a6,\002 INSTE\002,\002AD OF \002,a6,\002 *******\002)"; /* Builtin functions */ integer s_wsfe(cilist *), do_fio(integer *, char *, ftnlen), e_wsfe(void), s_cmp(const char *, const char *, ftnlen, ftnlen); /* Fortran I/O blocks */ static cilist io___398 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___399 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___400 = { 0, 0, 0, fmt_9998, 0 }; /* This is a special version of XERBLA to be used only as part of */ /* the test program for testing error exits from the Level 3 BLAS */ /* routines. */ /* XERBLA is an error handler for the Level 3 BLAS routines. */ /* It is called by the Level 3 BLAS routines if an input parameter is */ /* invalid. */ /* Auxiliary routine for test program for Level 3 Blas. */ /* -- Written on 8-February-1989. */ /* Jack Dongarra, Argonne National Laboratory. */ /* Iain Duff, AERE Harwell. */ /* Jeremy Du Croz, Numerical Algorithms Group Ltd. */ /* Sven Hammarling, Numerical Algorithms Group Ltd. */ /* .. Scalar Arguments .. */ /* .. Scalars in Common .. */ /* .. Common blocks .. */ /* .. Executable Statements .. */ infoc_2.lerr = TRUE_; if (*info != infoc_2.infot) { if (infoc_2.infot != 0) { io___398.ciunit = infoc_2.nout; s_wsfe(&io___398); do_fio(&c__1, (char *)&(*info), (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&infoc_2.infot, (ftnlen)sizeof(integer)); e_wsfe(); } else { io___399.ciunit = infoc_2.nout; s_wsfe(&io___399); do_fio(&c__1, (char *)&(*info), (ftnlen)sizeof(integer)); e_wsfe(); } infoc_2.ok = FALSE_; } if (s_cmp(srname, srnamc_1.srnamt, (ftnlen)6, (ftnlen)6) != 0) { io___400.ciunit = infoc_2.nout; s_wsfe(&io___400); do_fio(&c__1, srname, (ftnlen)6); do_fio(&c__1, srnamc_1.srnamt, (ftnlen)6); e_wsfe(); infoc_2.ok = FALSE_; } return 0; /* End of XERBLA */ } /* xerbla_ */ /* Main program alias */ int cblat3_ () { main (); return 0; } blis-0.9.0/blastest/src/dblat1.c000066400000000000000000001172761422157504600164200ustar00rootroot00000000000000/* dblat1.f -- translated by f2c (version 20100827). You must link the resulting object file with libf2c: on Microsoft Windows system, link with libf2c.lib; on Linux or Unix systems, link with .../path/to/libf2c.a -lm or, if you install libf2c.a in a standard place, with -lf2c -lm -- in that order, at the end of the command line, as in cc *.o -lf2c -lm Source for libf2c is in /netlib/f2c/libf2c.zip, e.g., http://www.netlib.org/f2c/libf2c.zip */ #include "f2c.h" /* Common Block Declarations */ struct { integer icase, n, incx, incy; logical pass; } combla_; #define combla_1 combla_ /* Table of constant values */ static integer c__1 = 1; static integer c__9 = 9; static doublereal c_b35 = 1.; static real c_b39 = .03125f; static integer c__5 = 5; static doublereal c_b63 = 0.; static real c_b81 = 0.f; /* > \brief \b DBLAT1 */ /* =========== DOCUMENTATION =========== */ /* Online html documentation available at */ /* http://www.netlib.org/lapack/explore-html/ */ /* Definition: */ /* =========== */ /* PROGRAM DBLAT1 */ /* > \par Purpose: */ /* ============= */ /* > */ /* > \verbatim */ /* > */ /* > Test program for the DOUBLE PRECISION Level 1 BLAS. */ /* > */ /* > Based upon the original BLAS test routine together with: */ /* > F06EAF Example Program Text */ /* > \endverbatim */ /* Authors: */ /* ======== */ /* > \author Univ. of Tennessee */ /* > \author Univ. of California Berkeley */ /* > \author Univ. of Colorado Denver */ /* > \author NAG Ltd. */ /* > \date April 2012 */ /* > \ingroup double_blas_testing */ /* ===================================================================== */ /* Main program */ int main(void) { /* Initialized data */ static doublereal sfac = 9.765625e-4; /* Format strings */ static char fmt_99999[] = "(\002 Real BLAS Test Program Results\002,/1x)"; static char fmt_99998[] = "(\002 ----" "- PASS -----\002)"; /* Builtin functions */ integer s_wsfe(cilist *), e_wsfe(void); /* Subroutine */ int s_stop(char *, ftnlen); /* Local variables */ integer ic; extern /* Subroutine */ int check0_(doublereal *), check1_(doublereal *), check2_(doublereal *), check3_(doublereal *), header_(void); /* Fortran I/O blocks */ static cilist io___2 = { 0, 6, 0, fmt_99999, 0 }; static cilist io___4 = { 0, 6, 0, fmt_99998, 0 }; /* -- Reference BLAS test routine (version 3.4.1) -- */ /* -- Reference BLAS is a software package provided by Univ. of Tennessee, -- */ /* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- */ /* April 2012 */ /* ===================================================================== */ /* .. Parameters .. */ /* .. Scalars in Common .. */ /* .. Local Scalars .. */ /* .. External Subroutines .. */ /* .. Common blocks .. */ /* .. Data statements .. */ /* .. Executable Statements .. */ s_wsfe(&io___2); e_wsfe(); for (ic = 1; ic <= 13; ++ic) { combla_1.icase = ic; header_(); /* .. Initialize PASS, INCX, and INCY for a new case. .. */ /* .. the value 9999 for INCX or INCY will appear in the .. */ /* .. detailed output, if any, for cases that do not involve .. */ /* .. these parameters .. */ combla_1.pass = TRUE_; combla_1.incx = 9999; combla_1.incy = 9999; if (combla_1.icase == 3 || combla_1.icase == 11) { check0_(&sfac); } else if (combla_1.icase == 7 || combla_1.icase == 8 || combla_1.icase == 9 || combla_1.icase == 10) { check1_(&sfac); } else if (combla_1.icase == 1 || combla_1.icase == 2 || combla_1.icase == 5 || combla_1.icase == 6 || combla_1.icase == 12 || combla_1.icase == 13) { check2_(&sfac); } else if (combla_1.icase == 4) { check3_(&sfac); } /* -- Print */ if (combla_1.pass) { s_wsfe(&io___4); e_wsfe(); } /* L20: */ } s_stop("", (ftnlen)0); return 0; } /* main */ /* Subroutine */ int header_(void) { /* Initialized data */ static char l[6*13] = " DDOT " "DAXPY " "DROTG " " DROT " "DCOPY " "DSWA" "P " "DNRM2 " "DASUM " "DSCAL " "IDAMAX" "DROTMG" "DROTM " "DSDOT " ; /* Format strings */ static char fmt_99999[] = "(/\002 Test of subprogram number\002,i3,12x,a" "6)"; /* Builtin functions */ integer s_wsfe(cilist *), do_fio(integer *, char *, ftnlen), e_wsfe(void); /* Fortran I/O blocks */ static cilist io___6 = { 0, 6, 0, fmt_99999, 0 }; /* .. Parameters .. */ /* .. Scalars in Common .. */ /* .. Local Arrays .. */ /* .. Common blocks .. */ /* .. Data statements .. */ /* .. Executable Statements .. */ s_wsfe(&io___6); do_fio(&c__1, (char *)&combla_1.icase, (ftnlen)sizeof(integer)); do_fio(&c__1, l + (0 + (0 + (combla_1.icase - 1) * 6)), (ftnlen)6); e_wsfe(); return 0; } /* header_ */ /* Subroutine */ int check0_(doublereal *sfac) { /* Initialized data */ static doublereal ds1[8] = { .8,.6,.8,-.6,.8,0.,1.,0. }; static doublereal datrue[8] = { .5,.5,.5,-.5,-.5,0.,1.,1. }; static doublereal dbtrue[8] = { 0.,.6,0.,-.6,0.,0.,1.,0. }; static doublereal dab[36] /* was [4][9] */ = { .1,.3,1.2,.2,.7,.2,.6, 4.2,0.,0.,0.,0.,4.,-1.,2.,4.,6e-10,.02,1e5,10.,4e10,.02,1e-5,10., 2e-10,.04,1e5,10.,2e10,.04,1e-5,10.,4.,-2.,8.,4. }; static doublereal dtrue[81] /* was [9][9] */ = { 0.,0.,1.3,.2,0.,0.,0.,.5, 0.,0.,0.,4.5,4.2,1.,.5,0.,0.,0.,0.,0.,0.,0.,-2.,0.,0.,0.,0.,0.,0., 0.,4.,-1.,0.,0.,0.,0.,0.,.015,0.,10.,-1.,0.,-1e-4,0.,1.,0.,0., .06144,10.,-1.,4096.,-1e6,0.,1.,0.,0.,15.,10.,-1.,5e-5,0.,1.,0., 0.,0.,15.,10.,-1.,5e5,-4096.,1.,.004096,0.,0.,7.,4.,0.,0.,-.5, -.25,0. }; static doublereal d12 = 4096.; static doublereal da1[8] = { .3,.4,-.3,-.4,-.3,0.,0.,1. }; static doublereal db1[8] = { .4,.3,.4,.3,-.4,0.,1.,0. }; static doublereal dc1[8] = { .6,.8,-.6,.8,.6,1.,0.,1. }; /* Builtin functions */ integer s_wsle(cilist *), do_lio(integer *, integer *, char *, ftnlen), e_wsle(void); /* Subroutine */ int s_stop(char *, ftnlen); /* Local variables */ integer i__, k; doublereal sa, sb, sc, ss, dtemp[9]; extern /* Subroutine */ int drotg_(doublereal *, doublereal *, doublereal *, doublereal *), stest_(integer *, doublereal *, doublereal *, doublereal *, doublereal *), stest1_(doublereal *, doublereal *, doublereal *, doublereal *), drotmg_(doublereal *, doublereal *, doublereal *, doublereal *, doublereal *); /* Fortran I/O blocks */ static cilist io___23 = { 0, 6, 0, 0, 0 }; /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Scalars in Common .. */ /* .. Local Scalars .. */ /* .. Local Arrays .. */ /* .. External Subroutines .. */ /* .. Common blocks .. */ /* .. Data statements .. */ /* INPUT FOR MODIFIED GIVENS */ /* TRUE RESULTS FOR MODIFIED GIVENS */ /* 4096 = 2 ** 12 */ dtrue[0] = .092307692307692313; dtrue[1] = .27692307692307694; dtrue[6] = -.16666666666666666; dtrue[9] = .18666666666666668; dtrue[10] = .65333333333333332; dtrue[17] = .14285714285714285; dtrue[36] = d12 * d12 * 4.5e-10; dtrue[38] = 4e5 / (d12 * 3.); dtrue[41] = 1. / d12; dtrue[43] = 1e4 / (d12 * 3.); dtrue[45] = 4e10 / (d12 * 1.5 * d12); dtrue[46] = .013333333333333334; dtrue[52] = d12 * 5e-7; dtrue[54] = .026666666666666668; dtrue[55] = d12 * d12 * 1.3333333333333334e-10; dtrue[60] = -dtrue[41]; dtrue[62] = 1e4 / d12; dtrue[63] = dtrue[54]; dtrue[64] = 2e10 / (d12 * 1.5 * d12); dtrue[72] = 4.5714285714285712; dtrue[73] = -2.2857142857142856; /* .. Executable Statements .. */ /* Compute true values which cannot be prestored */ /* in decimal notation */ dbtrue[0] = 1.6666666666666667; dbtrue[2] = -1.6666666666666667; dbtrue[4] = 1.6666666666666667; for (k = 1; k <= 8; ++k) { /* .. Set N=K for identification in output if any .. */ combla_1.n = k; if (combla_1.icase == 3) { /* .. DROTG .. */ if (k > 8) { goto L40; } sa = da1[k - 1]; sb = db1[k - 1]; drotg_(&sa, &sb, &sc, &ss); stest1_(&sa, &datrue[k - 1], &datrue[k - 1], sfac); stest1_(&sb, &dbtrue[k - 1], &dbtrue[k - 1], sfac); stest1_(&sc, &dc1[k - 1], &dc1[k - 1], sfac); stest1_(&ss, &ds1[k - 1], &ds1[k - 1], sfac); } else if (combla_1.icase == 11) { /* .. DROTMG .. */ for (i__ = 1; i__ <= 4; ++i__) { dtemp[i__ - 1] = dab[i__ + (k << 2) - 5]; dtemp[i__ + 3] = 0.f; } dtemp[8] = 0.f; drotmg_(dtemp, &dtemp[1], &dtemp[2], &dtemp[3], &dtemp[4]); stest_(&c__9, dtemp, &dtrue[k * 9 - 9], &dtrue[k * 9 - 9], sfac); } else { s_wsle(&io___23); do_lio(&c__9, &c__1, " Shouldn't be here in CHECK0", (ftnlen)28); e_wsle(); s_stop("", (ftnlen)0); } /* L20: */ } L40: return 0; } /* check0_ */ /* Subroutine */ int check1_(doublereal *sfac) { /* Initialized data */ static doublereal sa[10] = { .3,-1.,0.,1.,.3,.3,.3,.3,.3,.3 }; static doublereal dv[80] /* was [8][5][2] */ = { .1,2.,2.,2.,2.,2.,2., 2.,.3,3.,3.,3.,3.,3.,3.,3.,.3,-.4,4.,4.,4.,4.,4.,4.,.2,-.6,.3,5., 5.,5.,5.,5.,.1,-.3,.5,-.1,6.,6.,6.,6.,.1,8.,8.,8.,8.,8.,8.,8.,.3, 9.,9.,9.,9.,9.,9.,9.,.3,2.,-.4,2.,2.,2.,2.,2.,.2,3.,-.6,5.,.3,2., 2.,2.,.1,4.,-.3,6.,-.5,7.,-.1,3. }; static doublereal dtrue1[5] = { 0.,.3,.5,.7,.6 }; static doublereal dtrue3[5] = { 0.,.3,.7,1.1,1. }; static doublereal dtrue5[80] /* was [8][5][2] */ = { .1,2.,2.,2., 2.,2.,2.,2.,-.3,3.,3.,3.,3.,3.,3.,3.,0.,0.,4.,4.,4.,4.,4.,4.,.2, -.6,.3,5.,5.,5.,5.,5.,.03,-.09,.15,-.03,6.,6.,6.,6.,.1,8.,8.,8., 8.,8.,8.,8.,.09,9.,9.,9.,9.,9.,9.,9.,.09,2.,-.12,2.,2.,2.,2.,2., .06,3.,-.18,5.,.09,2.,2.,2.,.03,4.,-.09,6.,-.15,7.,-.03,3. }; static integer itrue2[5] = { 0,1,2,2,3 }; /* System generated locals */ integer i__1; doublereal d__1; /* Builtin functions */ integer s_wsle(cilist *), do_lio(integer *, integer *, char *, ftnlen), e_wsle(void); /* Subroutine */ int s_stop(char *, ftnlen); /* Local variables */ integer i__; doublereal sx[8]; integer np1, len; extern doublereal dnrm2_(integer *, doublereal *, integer *); extern /* Subroutine */ int dscal_(integer *, doublereal *, doublereal *, integer *); extern doublereal dasum_(integer *, doublereal *, integer *); doublereal stemp[1], strue[8]; extern /* Subroutine */ int stest_(integer *, doublereal *, doublereal *, doublereal *, doublereal *), itest1_(integer *, integer *), stest1_(doublereal *, doublereal *, doublereal *, doublereal *); extern integer idamax_(integer *, doublereal *, integer *); /* Fortran I/O blocks */ static cilist io___36 = { 0, 6, 0, 0, 0 }; /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Scalars in Common .. */ /* .. Local Scalars .. */ /* .. Local Arrays .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. Common blocks .. */ /* .. Data statements .. */ /* .. Executable Statements .. */ for (combla_1.incx = 1; combla_1.incx <= 2; ++combla_1.incx) { for (np1 = 1; np1 <= 5; ++np1) { combla_1.n = np1 - 1; len = max(combla_1.n,1) << 1; /* .. Set vector arguments .. */ i__1 = len; for (i__ = 1; i__ <= i__1; ++i__) { sx[i__ - 1] = dv[i__ + (np1 + combla_1.incx * 5 << 3) - 49]; /* L20: */ } if (combla_1.icase == 7) { /* .. DNRM2 .. */ stemp[0] = dtrue1[np1 - 1]; d__1 = dnrm2_(&combla_1.n, sx, &combla_1.incx); stest1_(&d__1, stemp, stemp, sfac); } else if (combla_1.icase == 8) { /* .. DASUM .. */ stemp[0] = dtrue3[np1 - 1]; d__1 = dasum_(&combla_1.n, sx, &combla_1.incx); stest1_(&d__1, stemp, stemp, sfac); } else if (combla_1.icase == 9) { /* .. DSCAL .. */ dscal_(&combla_1.n, &sa[(combla_1.incx - 1) * 5 + np1 - 1], sx, &combla_1.incx); i__1 = len; for (i__ = 1; i__ <= i__1; ++i__) { strue[i__ - 1] = dtrue5[i__ + (np1 + combla_1.incx * 5 << 3) - 49]; /* L40: */ } stest_(&len, sx, strue, strue, sfac); } else if (combla_1.icase == 10) { /* .. IDAMAX .. */ i__1 = idamax_(&combla_1.n, sx, &combla_1.incx); itest1_(&i__1, &itrue2[np1 - 1]); } else { s_wsle(&io___36); do_lio(&c__9, &c__1, " Shouldn't be here in CHECK1", (ftnlen) 28); e_wsle(); s_stop("", (ftnlen)0); } /* L60: */ } /* L80: */ } return 0; } /* check1_ */ /* Subroutine */ int check2_(doublereal *sfac) { /* Initialized data */ static doublereal sa = .3; static integer incxs[4] = { 1,2,-2,-1 }; static integer incys[4] = { 1,-2,1,-2 }; static integer lens[8] /* was [4][2] */ = { 1,1,2,4,1,1,3,7 }; static integer ns[4] = { 0,1,2,4 }; static doublereal dx1[7] = { .6,.1,-.5,.8,.9,-.3,-.4 }; static doublereal dy1[7] = { .5,-.9,.3,.7,-.6,.2,.8 }; static real sx1[7] = { .6f,.1f,-.5f,.8f,.9f,-.3f,-.4f }; static real sy1[7] = { .5f,-.9f,.3f,.7f,-.6f,.2f,.8f }; static doublereal dt7[16] /* was [4][4] */ = { 0.,.3,.21,.62,0.,.3,-.07, .85,0.,.3,-.79,-.74,0.,.3,.33,1.27 }; static doublereal dt8[112] /* was [7][4][4] */ = { .5,0.,0.,0.,0.,0.,0., .68,0.,0.,0.,0.,0.,0.,.68,-.87,0.,0.,0.,0.,0.,.68,-.87,.15,.94,0., 0.,0.,.5,0.,0.,0.,0.,0.,0.,.68,0.,0.,0.,0.,0.,0.,.35,-.9,.48,0., 0.,0.,0.,.38,-.9,.57,.7,-.75,.2,.98,.5,0.,0.,0.,0.,0.,0.,.68,0., 0.,0.,0.,0.,0.,.35,-.72,0.,0.,0.,0.,0.,.38,-.63,.15,.88,0.,0.,0., .5,0.,0.,0.,0.,0.,0.,.68,0.,0.,0.,0.,0.,0.,.68,-.9,.33,0.,0.,0., 0.,.68,-.9,.33,.7,-.75,.2,1.04 }; static doublereal dt10x[112] /* was [7][4][4] */ = { .6,0.,0.,0., 0.,0.,0.,.5,0.,0.,0.,0.,0.,0.,.5,-.9,0.,0.,0.,0.,0.,.5,-.9,.3,.7, 0.,0.,0.,.6,0.,0.,0.,0.,0.,0.,.5,0.,0.,0.,0.,0.,0.,.3,.1,.5,0.,0., 0.,0.,.8,.1,-.6,.8,.3,-.3,.5,.6,0.,0.,0.,0.,0.,0.,.5,0.,0.,0.,0., 0.,0.,-.9,.1,.5,0.,0.,0.,0.,.7,.1,.3,.8,-.9,-.3,.5,.6,0.,0.,0.,0., 0.,0.,.5,0.,0.,0.,0.,0.,0.,.5,.3,0.,0.,0.,0.,0.,.5,.3,-.6,.8,0., 0.,0. }; static doublereal dt10y[112] /* was [7][4][4] */ = { .5,0.,0.,0., 0.,0.,0.,.6,0.,0.,0.,0.,0.,0.,.6,.1,0.,0.,0.,0.,0.,.6,.1,-.5,.8, 0.,0.,0.,.5,0.,0.,0.,0.,0.,0.,.6,0.,0.,0.,0.,0.,0.,-.5,-.9,.6,0., 0.,0.,0.,-.4,-.9,.9,.7,-.5,.2,.6,.5,0.,0.,0.,0.,0.,0.,.6,0.,0.,0., 0.,0.,0.,-.5,.6,0.,0.,0.,0.,0.,-.4,.9,-.5,.6,0.,0.,0.,.5,0.,0.,0., 0.,0.,0.,.6,0.,0.,0.,0.,0.,0.,.6,-.9,.1,0.,0.,0.,0.,.6,-.9,.1,.7, -.5,.2,.8 }; static doublereal ssize1[4] = { 0.,.3,1.6,3.2 }; static doublereal ssize2[28] /* was [14][2] */ = { 0.,0.,0.,0.,0., 0.,0.,0.,0.,0.,0.,0.,0.,0.,1.17,1.17,1.17,1.17,1.17,1.17,1.17, 1.17,1.17,1.17,1.17,1.17,1.17,1.17 }; static doublereal dpar[20] /* was [5][4] */ = { -2.,0.,0.,0.,0.,-1.,2., -3.,-4.,5.,0.,0.,2.,-3.,0.,1.,5.,2.,0.,-4. }; static struct { doublereal e_1[448]; } equiv_3 = {{ .6, 0., 0., 0., 0., 0., 0., .6, 0., 0., 0., 0., 0., 0., .6, 0., 0., 0., 0., 0., 0., .6, 0., 0., 0., 0., 0., 0., .6, 0., 0., 0., 0., 0., 0., -.8, 0., 0., 0., 0., 0., 0., -.9, 0., 0., 0., 0., 0., 0., 3.5, 0., 0., 0., 0., 0., 0., .6, .1, 0., 0., 0., 0., 0., -.8, 3.8, 0., 0., 0., 0., 0., -.9, 2.8, 0., 0., 0., 0., 0., 3.5, -.4, 0., 0., 0., 0., 0., .6, .1, -.5, .8, 0., 0., 0., -.8, 3.8, -2.2, -1.2, 0., 0., 0., -.9, 2.8, -1.4, -1.3, 0., 0., 0., 3.5, -.4, -2.2, 4.7, 0., 0., 0., .6, 0., 0., 0., 0., 0., 0., .6, 0., 0., 0., 0., 0., 0., .6, 0., 0., 0., 0., 0., 0., .6, 0., 0., 0., 0., 0., 0., .6, 0., 0., 0., 0., 0., 0., -.8, 0., 0., 0., 0., 0., 0., -.9, 0., 0., 0., 0., 0., 0., 3.5, 0., 0., 0., 0., 0., 0., .6, .1, -.5, 0., 0., 0., 0., 0., .1, -3., 0., 0., 0., 0., -.3, .1, -2., 0., 0., 0., 0., 3.3, .1, -2., 0., 0., 0., 0., .6, .1, -.5, .8, .9, -.3, -.4, -2., .1, 1.4, .8, .6, -.3, -2.8, -1.8, .1, 1.3, .8, 0., -.3, -1.9, 3.8, .1, -3.1, .8, 4.8, -.3, -1.5, .6, 0., 0., 0., 0., 0., 0., .6, 0., 0., 0., 0., 0., 0., .6, 0., 0., 0., 0., 0., 0., .6, 0., 0., 0., 0., 0., 0., .6, 0., 0., 0., 0., 0., 0., -.8, 0., 0., 0., 0., 0., 0., -.9, 0., 0., 0., 0., 0., 0., 3.5, 0., 0., 0., 0., 0., 0., .6, .1, -.5, 0., 0., 0., 0., 4.8, .1, -3., 0., 0., 0., 0., 3.3, .1, -2., 0., 0., 0., 0., 2.1, .1, -2., 0., 0., 0., 0., .6, .1, -.5, .8, .9, -.3, -.4, -1.6, .1, -2.2, .8, 5.4, -.3, -2.8, -1.5, .1, -1.4, .8, 3.6, -.3, -1.9, 3.7, .1, -2.2, .8, 3.6, -.3, -1.5, .6, 0., 0., 0., 0., 0., 0., .6, 0., 0., 0., 0., 0., 0., .6, 0., 0., 0., 0., 0., 0., .6, 0., 0., 0., 0., 0., 0., .6, 0., 0., 0., 0., 0., 0., -.8, 0., 0., 0., 0., 0., 0., -.9, 0., 0., 0., 0., 0., 0., 3.5, 0., 0., 0., 0., 0., 0., .6, .1, 0., 0., 0., 0., 0., -.8, -1., 0., 0., 0., 0., 0., -.9, -.8, 0., 0., 0., 0., 0., 3.5, .8, 0., 0., 0., 0., 0., .6, .1, -.5, .8, 0., 0., 0., -.8, -1., 1.4, -1.6, 0., 0., 0., -.9, -.8, 1.3, -1.6, 0., 0., 0., 3.5, .8, -3.1, 4.8, 0., 0., 0. }}; static struct { doublereal e_1[448]; } equiv_7 = {{ .5, 0., 0., 0., 0., 0., 0., .5, 0., 0., 0., 0., 0., 0., .5, 0., 0., 0., 0., 0., 0., .5, 0., 0., 0., 0., 0., 0., .5, 0., 0., 0., 0., 0., 0., .7, 0., 0., 0., 0., 0., 0., 1.7, 0., 0., 0., 0., 0., 0., -2.6, 0., 0., 0., 0., 0., 0., .5, -.9, 0., 0., 0., 0., 0., .7, -4.8, 0., 0., 0., 0., 0., 1.7, -.7, 0., 0., 0., 0., 0., -2.6, 3.5, 0., 0., 0., 0., 0., .5, -.9, .3, .7, 0., 0., 0., .7, -4.8, 3., 1.1, 0., 0., 0., 1.7, -.7, -.7, 2.3, 0., 0., 0., -2.6, 3.5, -.7, -3.6, 0., 0., 0., .5, 0., 0., 0., 0., 0., 0., .5, 0., 0., 0., 0., 0., 0., .5, 0., 0., 0., 0., 0., 0., .5, 0., 0., 0., 0., 0., 0., .5, 0., 0., 0., 0., 0., 0., .7, 0., 0., 0., 0., 0., 0., 1.7, 0., 0., 0., 0., 0., 0., -2.6, 0., 0., 0., 0., 0., 0., .5, -.9, .3, 0., 0., 0., 0., 4., -.9, -.3, 0., 0., 0., 0., -.5, -.9, 1.5, 0., 0., 0., 0., -1.5, -.9, -1.8, 0., 0., 0., 0., .5, -.9, .3, .7, -.6, .2, .8, 3.7, -.9, -1.2, .7, -1.5, .2, 2.2, -.3, -.9, 2.1, .7, -1.6, .2, 2., -1.6, -.9, -2.1, .7, 2.9, .2, -3.8, .5, 0., 0., 0., 0., 0., 0., .5, 0., 0., 0., 0., 0., 0., .5, 0., 0., 0., 0., 0., 0., .5, 0., 0., 0., 0., 0., 0., .5, 0., 0., 0., 0., 0., 0., .7, 0., 0., 0., 0., 0., 0., 1.7, 0., 0., 0., 0., 0., 0., -2.6, 0., 0., 0., 0., 0., 0., .5, -.9, 0., 0., 0., 0., 0., 4., -6.3, 0., 0., 0., 0., 0., -.5, .3, 0., 0., 0., 0., 0., -1.5, 3., 0., 0., 0., 0., 0., .5, -.9, .3, .7, 0., 0., 0., 3.7, -7.2, 3., 1.7, 0., 0., 0., -.3, .9, -.7, 1.9, 0., 0., 0., -1.6, 2.7, -.7, -3.4, 0., 0., 0., .5, 0., 0., 0., 0., 0., 0., .5, 0., 0., 0., 0., 0., 0., .5, 0., 0., 0., 0., 0., 0., .5, 0., 0., 0., 0., 0., 0., .5, 0., 0., 0., 0., 0., 0., .7, 0., 0., 0., 0., 0., 0., 1.7, 0., 0., 0., 0., 0., 0., -2.6, 0., 0., 0., 0., 0., 0., .5, -.9, .3, 0., 0., 0., 0., .7, -.9, 1.2, 0., 0., 0., 0., 1.7, -.9, .5, 0., 0., 0., 0., -2.6, -.9, -1.3, 0., 0., 0., 0., .5, -.9, .3, .7, -.6, .2, .8, .7, -.9, 1.2, .7, -1.5, .2, 1.6, 1.7, -.9, .5, .7, -1.6, .2, 2.4, -2.6, -.9, -1.3, .7, 2.9, .2, -4. }}; /* System generated locals */ integer i__1; real r__1, r__2, r__3; doublereal d__1; /* Builtin functions */ integer s_wsle(cilist *), do_lio(integer *, integer *, char *, ftnlen), e_wsle(void); /* Subroutine */ int s_stop(char *, ftnlen); /* Local variables */ integer i__, j; extern /* Subroutine */ int testdsdot_(real *, real *, real *, real *); integer ki, kn, mx, my; doublereal sx[7], sy[7]; integer kni; doublereal stx[7], sty[7]; extern doublereal ddot_(integer *, doublereal *, integer *, doublereal *, integer *); integer kpar, lenx, leny; #define dt19x ((doublereal *)&equiv_3) #define dt19y ((doublereal *)&equiv_7) doublereal dtemp[5]; #define dt19xa ((doublereal *)&equiv_3) #define dt19xb ((doublereal *)&equiv_3 + 112) #define dt19xc ((doublereal *)&equiv_3 + 224) #define dt19xd ((doublereal *)&equiv_3 + 336) #define dt19ya ((doublereal *)&equiv_7) #define dt19yb ((doublereal *)&equiv_7 + 112) #define dt19yc ((doublereal *)&equiv_7 + 224) #define dt19yd ((doublereal *)&equiv_7 + 336) extern doublereal dsdot_(integer *, real *, integer *, real *, integer *); extern /* Subroutine */ int dcopy_(integer *, doublereal *, integer *, doublereal *, integer *); integer ksize; extern /* Subroutine */ int daxpy_(integer *, doublereal *, doublereal *, integer *, doublereal *, integer *), drotm_(integer *, doublereal *, integer *, doublereal *, integer *, doublereal *), dswap_( integer *, doublereal *, integer *, doublereal *, integer *); doublereal ssize[7]; extern /* Subroutine */ int stest_(integer *, doublereal *, doublereal *, doublereal *, doublereal *), stest1_(doublereal *, doublereal *, doublereal *, doublereal *); /* Fortran I/O blocks */ static cilist io___80 = { 0, 6, 0, 0, 0 }; /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Scalars in Common .. */ /* .. Local Scalars .. */ /* .. Local Arrays .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. Common blocks .. */ /* .. Data statements .. */ /* **** FGVZ: We have to add separate REAL arrays for DSDOT() because */ /* **** REAL() on an array argument does not translate via f2c. */ /* FOR DROTM */ /* TRUE X RESULTS F0R ROTATIONS DROTM */ /* TRUE Y RESULTS FOR ROTATIONS DROTM */ /* .. Executable Statements .. */ for (ki = 1; ki <= 4; ++ki) { combla_1.incx = incxs[ki - 1]; combla_1.incy = incys[ki - 1]; mx = abs(combla_1.incx); my = abs(combla_1.incy); for (kn = 1; kn <= 4; ++kn) { combla_1.n = ns[kn - 1]; ksize = min(2,kn); lenx = lens[kn + (mx << 2) - 5]; leny = lens[kn + (my << 2) - 5]; /* .. Initialize all argument arrays .. */ for (i__ = 1; i__ <= 7; ++i__) { sx[i__ - 1] = dx1[i__ - 1]; sy[i__ - 1] = dy1[i__ - 1]; /* **** FGVZ: We have to add a loop to initialize separate REAL arrays */ /* **** for DSDOT() because REAL() on an array argument does not */ /* **** translate via f2c. */ sx1[i__ - 1] = dx1[i__ - 1]; sy1[i__ - 1] = dy1[i__ - 1]; /* L20: */ } if (combla_1.icase == 1) { /* .. DDOT .. */ d__1 = ddot_(&combla_1.n, sx, &combla_1.incx, sy, & combla_1.incy); stest1_(&d__1, &dt7[kn + (ki << 2) - 5], &ssize1[kn - 1], sfac); } else if (combla_1.icase == 2) { /* .. DAXPY .. */ daxpy_(&combla_1.n, &sa, sx, &combla_1.incx, sy, & combla_1.incy); i__1 = leny; for (j = 1; j <= i__1; ++j) { sty[j - 1] = dt8[j + (kn + (ki << 2)) * 7 - 36]; /* L40: */ } stest_(&leny, sy, sty, &ssize2[ksize * 14 - 14], sfac); } else if (combla_1.icase == 5) { /* .. DCOPY .. */ for (i__ = 1; i__ <= 7; ++i__) { sty[i__ - 1] = dt10y[i__ + (kn + (ki << 2)) * 7 - 36]; /* L60: */ } dcopy_(&combla_1.n, sx, &combla_1.incx, sy, &combla_1.incy); stest_(&leny, sy, sty, ssize2, &c_b35); } else if (combla_1.icase == 6) { /* .. DSWAP .. */ dswap_(&combla_1.n, sx, &combla_1.incx, sy, &combla_1.incy); for (i__ = 1; i__ <= 7; ++i__) { stx[i__ - 1] = dt10x[i__ + (kn + (ki << 2)) * 7 - 36]; sty[i__ - 1] = dt10y[i__ + (kn + (ki << 2)) * 7 - 36]; /* L80: */ } stest_(&lenx, sx, stx, ssize2, &c_b35); stest_(&leny, sy, sty, ssize2, &c_b35); } else if (combla_1.icase == 12) { /* .. DROTM .. */ kni = kn + (ki - 1 << 2); for (kpar = 1; kpar <= 4; ++kpar) { for (i__ = 1; i__ <= 7; ++i__) { sx[i__ - 1] = dx1[i__ - 1]; sy[i__ - 1] = dy1[i__ - 1]; stx[i__ - 1] = dt19x[i__ + (kpar + (kni << 2)) * 7 - 36]; sty[i__ - 1] = dt19y[i__ + (kpar + (kni << 2)) * 7 - 36]; } for (i__ = 1; i__ <= 5; ++i__) { dtemp[i__ - 1] = dpar[i__ + kpar * 5 - 6]; } i__1 = lenx; for (i__ = 1; i__ <= i__1; ++i__) { ssize[i__ - 1] = stx[i__ - 1]; } /* SEE REMARK ABOVE ABOUT DT11X(1,2,7) */ /* AND DT11X(5,3,8). */ if (kpar == 2 && kni == 7) { ssize[0] = 2.4; } if (kpar == 3 && kni == 8) { ssize[4] = 1.8; } drotm_(&combla_1.n, sx, &combla_1.incx, sy, & combla_1.incy, dtemp); stest_(&lenx, sx, stx, ssize, sfac); stest_(&leny, sy, sty, sty, sfac); } } else if (combla_1.icase == 13) { /* .. DSDOT .. */ /* **** CALL TESTDSDOT(REAL(DSDOT(N,REAL(SX),INCX,REAL(SY),INCY)), */ r__1 = (real) dsdot_(&combla_1.n, sx1, &combla_1.incx, sy1, & combla_1.incy); r__2 = (real) dt7[kn + (ki << 2) - 5]; r__3 = (real) ssize1[kn - 1]; testdsdot_(&r__1, &r__2, &r__3, &c_b39); } else { s_wsle(&io___80); do_lio(&c__9, &c__1, " Shouldn't be here in CHECK2", (ftnlen) 28); e_wsle(); s_stop("", (ftnlen)0); } /* L100: */ } /* L120: */ } return 0; } /* check2_ */ #undef dt19yd #undef dt19yc #undef dt19yb #undef dt19ya #undef dt19xd #undef dt19xc #undef dt19xb #undef dt19xa #undef dt19y #undef dt19x /* Subroutine */ int check3_(doublereal *sfac) { /* Initialized data */ static integer incxs[4] = { 1,2,-2,-1 }; static integer incys[4] = { 1,-2,1,-2 }; static integer lens[8] /* was [4][2] */ = { 1,1,2,4,1,1,3,7 }; static integer ns[4] = { 0,1,2,4 }; static doublereal dx1[7] = { .6,.1,-.5,.8,.9,-.3,-.4 }; static doublereal dy1[7] = { .5,-.9,.3,.7,-.6,.2,.8 }; static doublereal sc = .8; static doublereal ss = .6; static doublereal dt9x[112] /* was [7][4][4] */ = { .6,0.,0.,0.,0.,0.,0., .78,0.,0.,0.,0.,0.,0.,.78,-.46,0.,0.,0.,0.,0.,.78,-.46,-.22,1.06, 0.,0.,0.,.6,0.,0.,0.,0.,0.,0.,.78,0.,0.,0.,0.,0.,0.,.66,.1,-.1,0., 0.,0.,0.,.96,.1,-.76,.8,.9,-.3,-.02,.6,0.,0.,0.,0.,0.,0.,.78,0., 0.,0.,0.,0.,0.,-.06,.1,-.1,0.,0.,0.,0.,.9,.1,-.22,.8,.18,-.3,-.02, .6,0.,0.,0.,0.,0.,0.,.78,0.,0.,0.,0.,0.,0.,.78,.26,0.,0.,0.,0.,0., .78,.26,-.76,1.12,0.,0.,0. }; static doublereal dt9y[112] /* was [7][4][4] */ = { .5,0.,0.,0.,0.,0.,0., .04,0.,0.,0.,0.,0.,0.,.04,-.78,0.,0.,0.,0.,0.,.04,-.78,.54,.08,0., 0.,0.,.5,0.,0.,0.,0.,0.,0.,.04,0.,0.,0.,0.,0.,0.,.7,-.9,-.12,0., 0.,0.,0.,.64,-.9,-.3,.7,-.18,.2,.28,.5,0.,0.,0.,0.,0.,0.,.04,0., 0.,0.,0.,0.,0.,.7,-1.08,0.,0.,0.,0.,0.,.64,-1.26,.54,.2,0.,0.,0., .5,0.,0.,0.,0.,0.,0.,.04,0.,0.,0.,0.,0.,0.,.04,-.9,.18,0.,0.,0., 0.,.04,-.9,.18,.7,-.18,.2,.16 }; static doublereal ssize2[28] /* was [14][2] */ = { 0.,0.,0.,0.,0., 0.,0.,0.,0.,0.,0.,0.,0.,0.,1.17,1.17,1.17,1.17,1.17,1.17,1.17, 1.17,1.17,1.17,1.17,1.17,1.17,1.17 }; /* Builtin functions */ integer s_wsle(cilist *), do_lio(integer *, integer *, char *, ftnlen), e_wsle(void); /* Subroutine */ int s_stop(char *, ftnlen); /* Local variables */ integer i__, k, ki, kn, mx, my; doublereal sx[7], sy[7], stx[7], sty[7]; integer lenx, leny; doublereal mwpc[11]; extern /* Subroutine */ int drot_(integer *, doublereal *, integer *, doublereal *, integer *, doublereal *, doublereal *); integer mwpn[11]; doublereal mwps[11], mwpx[5], mwpy[5]; integer ksize; doublereal copyx[5], copyy[5]; extern /* Subroutine */ int stest_(integer *, doublereal *, doublereal *, doublereal *, doublereal *); doublereal mwptx[55] /* was [11][5] */, mwpty[55] /* was [11][5] */; integer mwpinx[11], mwpiny[11]; doublereal mwpstx[5], mwpsty[5]; /* Fortran I/O blocks */ static cilist io___104 = { 0, 6, 0, 0, 0 }; /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Scalars in Common .. */ /* .. Local Scalars .. */ /* .. Local Arrays .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. Common blocks .. */ /* .. Data statements .. */ /* .. Executable Statements .. */ for (ki = 1; ki <= 4; ++ki) { combla_1.incx = incxs[ki - 1]; combla_1.incy = incys[ki - 1]; mx = abs(combla_1.incx); my = abs(combla_1.incy); for (kn = 1; kn <= 4; ++kn) { combla_1.n = ns[kn - 1]; ksize = min(2,kn); lenx = lens[kn + (mx << 2) - 5]; leny = lens[kn + (my << 2) - 5]; if (combla_1.icase == 4) { /* .. DROT .. */ for (i__ = 1; i__ <= 7; ++i__) { sx[i__ - 1] = dx1[i__ - 1]; sy[i__ - 1] = dy1[i__ - 1]; stx[i__ - 1] = dt9x[i__ + (kn + (ki << 2)) * 7 - 36]; sty[i__ - 1] = dt9y[i__ + (kn + (ki << 2)) * 7 - 36]; /* L20: */ } drot_(&combla_1.n, sx, &combla_1.incx, sy, &combla_1.incy, & sc, &ss); stest_(&lenx, sx, stx, &ssize2[ksize * 14 - 14], sfac); stest_(&leny, sy, sty, &ssize2[ksize * 14 - 14], sfac); } else { s_wsle(&io___104); do_lio(&c__9, &c__1, " Shouldn't be here in CHECK3", (ftnlen) 28); e_wsle(); s_stop("", (ftnlen)0); } /* L40: */ } /* L60: */ } mwpc[0] = 1.; for (i__ = 2; i__ <= 11; ++i__) { mwpc[i__ - 1] = 0.; /* L80: */ } mwps[0] = 0.; for (i__ = 2; i__ <= 6; ++i__) { mwps[i__ - 1] = 1.; /* L100: */ } for (i__ = 7; i__ <= 11; ++i__) { mwps[i__ - 1] = -1.; /* L120: */ } mwpinx[0] = 1; mwpinx[1] = 1; mwpinx[2] = 1; mwpinx[3] = -1; mwpinx[4] = 1; mwpinx[5] = -1; mwpinx[6] = 1; mwpinx[7] = 1; mwpinx[8] = -1; mwpinx[9] = 1; mwpinx[10] = -1; mwpiny[0] = 1; mwpiny[1] = 1; mwpiny[2] = -1; mwpiny[3] = -1; mwpiny[4] = 2; mwpiny[5] = 1; mwpiny[6] = 1; mwpiny[7] = -1; mwpiny[8] = -1; mwpiny[9] = 2; mwpiny[10] = 1; for (i__ = 1; i__ <= 11; ++i__) { mwpn[i__ - 1] = 5; /* L140: */ } mwpn[4] = 3; mwpn[9] = 3; for (i__ = 1; i__ <= 5; ++i__) { mwpx[i__ - 1] = (doublereal) i__; mwpy[i__ - 1] = (doublereal) i__; mwptx[i__ * 11 - 11] = (doublereal) i__; mwpty[i__ * 11 - 11] = (doublereal) i__; mwptx[i__ * 11 - 10] = (doublereal) i__; mwpty[i__ * 11 - 10] = (doublereal) (-i__); mwptx[i__ * 11 - 9] = (doublereal) (6 - i__); mwpty[i__ * 11 - 9] = (doublereal) (i__ - 6); mwptx[i__ * 11 - 8] = (doublereal) i__; mwpty[i__ * 11 - 8] = (doublereal) (-i__); mwptx[i__ * 11 - 6] = (doublereal) (6 - i__); mwpty[i__ * 11 - 6] = (doublereal) (i__ - 6); mwptx[i__ * 11 - 5] = (doublereal) (-i__); mwpty[i__ * 11 - 5] = (doublereal) i__; mwptx[i__ * 11 - 4] = (doublereal) (i__ - 6); mwpty[i__ * 11 - 4] = (doublereal) (6 - i__); mwptx[i__ * 11 - 3] = (doublereal) (-i__); mwpty[i__ * 11 - 3] = (doublereal) i__; mwptx[i__ * 11 - 1] = (doublereal) (i__ - 6); mwpty[i__ * 11 - 1] = (doublereal) (6 - i__); /* L160: */ } mwptx[4] = 1.; mwptx[15] = 3.; mwptx[26] = 5.; mwptx[37] = 4.; mwptx[48] = 5.; mwpty[4] = -1.; mwpty[15] = 2.; mwpty[26] = -2.; mwpty[37] = 4.; mwpty[48] = -3.; mwptx[9] = -1.; mwptx[20] = -3.; mwptx[31] = -5.; mwptx[42] = 4.; mwptx[53] = 5.; mwpty[9] = 1.; mwpty[20] = 2.; mwpty[31] = 2.; mwpty[42] = 4.; mwpty[53] = 3.; for (i__ = 1; i__ <= 11; ++i__) { combla_1.incx = mwpinx[i__ - 1]; combla_1.incy = mwpiny[i__ - 1]; for (k = 1; k <= 5; ++k) { copyx[k - 1] = mwpx[k - 1]; copyy[k - 1] = mwpy[k - 1]; mwpstx[k - 1] = mwptx[i__ + k * 11 - 12]; mwpsty[k - 1] = mwpty[i__ + k * 11 - 12]; /* L180: */ } drot_(&mwpn[i__ - 1], copyx, &combla_1.incx, copyy, &combla_1.incy, & mwpc[i__ - 1], &mwps[i__ - 1]); stest_(&c__5, copyx, mwpstx, mwpstx, sfac); stest_(&c__5, copyy, mwpsty, mwpsty, sfac); /* L200: */ } return 0; } /* check3_ */ /* Subroutine */ int stest_(integer *len, doublereal *scomp, doublereal * strue, doublereal *ssize, doublereal *sfac) { /* Format strings */ static char fmt_99999[] = "(\002 F" "AIL\002)"; static char fmt_99998[] = "(/\002 CASE N INCX INCY I " " \002,\002 COMP(I) TRUE(I) " " DIFFERENCE\002,\002 SIZE(I)\002,/1x)"; static char fmt_99997[] = "(1x,i4,i3,2i5,i3,2d36.8,2d12.4)"; /* System generated locals */ integer i__1; doublereal d__1, d__2; /* Builtin functions */ integer s_wsfe(cilist *), e_wsfe(void), do_fio(integer *, char *, ftnlen); /* Local variables */ integer i__; doublereal sd; extern double d_epsilon_(doublereal *); /* Fortran I/O blocks */ static cilist io___121 = { 0, 6, 0, fmt_99999, 0 }; static cilist io___122 = { 0, 6, 0, fmt_99998, 0 }; static cilist io___123 = { 0, 6, 0, fmt_99997, 0 }; /* ********************************* STEST ************************** */ /* THIS SUBR COMPARES ARRAYS SCOMP() AND STRUE() OF LENGTH LEN TO */ /* SEE IF THE TERM BY TERM DIFFERENCES, MULTIPLIED BY SFAC, ARE */ /* NEGLIGIBLE. */ /* C. L. LAWSON, JPL, 1974 DEC 10 */ /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Scalars in Common .. */ /* .. Local Scalars .. */ /* .. External Functions .. */ /* .. Intrinsic Functions .. */ /* .. Common blocks .. */ /* .. Executable Statements .. */ /* Parameter adjustments */ --ssize; --strue; --scomp; /* Function Body */ i__1 = *len; for (i__ = 1; i__ <= i__1; ++i__) { sd = scomp[i__] - strue[i__]; if ((d__2 = *sfac * sd, abs(d__2)) <= (d__1 = ssize[i__], abs(d__1)) * d_epsilon_(&c_b63)) { goto L40; } /* HERE SCOMP(I) IS NOT CLOSE TO STRUE(I). */ if (! combla_1.pass) { goto L20; } /* PRINT FAIL MESSAGE AND HEADER. */ combla_1.pass = FALSE_; s_wsfe(&io___121); e_wsfe(); s_wsfe(&io___122); e_wsfe(); L20: s_wsfe(&io___123); do_fio(&c__1, (char *)&combla_1.icase, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&combla_1.n, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&combla_1.incx, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&combla_1.incy, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&i__, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&scomp[i__], (ftnlen)sizeof(doublereal)); do_fio(&c__1, (char *)&strue[i__], (ftnlen)sizeof(doublereal)); do_fio(&c__1, (char *)&sd, (ftnlen)sizeof(doublereal)); do_fio(&c__1, (char *)&ssize[i__], (ftnlen)sizeof(doublereal)); e_wsfe(); L40: ; } return 0; } /* stest_ */ /* Subroutine */ int testdsdot_(real *scomp, real *strue, real *ssize, real * sfac) { /* Format strings */ static char fmt_99999[] = "(\002 F" "AIL\002)"; static char fmt_99998[] = "(/\002 CASE N INCX INCY " " \002,\002 COMP(I) TRUE(I) DIF" "FERENCE\002,\002 SIZE(I)\002,/1x)"; static char fmt_99997[] = "(1x,i4,i3,1i5,i3,2e36.8,2e12.4)"; /* System generated locals */ real r__1; /* Builtin functions */ integer s_wsfe(cilist *), e_wsfe(void), do_fio(integer *, char *, ftnlen); /* Local variables */ real sd; extern real s_epsilon_(); /* Fortran I/O blocks */ static cilist io___125 = { 0, 6, 0, fmt_99999, 0 }; static cilist io___126 = { 0, 6, 0, fmt_99998, 0 }; static cilist io___127 = { 0, 6, 0, fmt_99997, 0 }; /* ********************************* STEST ************************** */ /* THIS SUBR COMPARES ARRAYS SCOMP() AND STRUE() OF LENGTH LEN TO */ /* SEE IF THE TERM BY TERM DIFFERENCES, MULTIPLIED BY SFAC, ARE */ /* NEGLIGIBLE. */ /* C. L. LAWSON, JPL, 1974 DEC 10 */ /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Scalars in Common .. */ /* .. Local Scalars .. */ /* .. Intrinsic Functions .. */ /* .. Common blocks .. */ /* .. Executable Statements .. */ sd = *scomp - *strue; if ((r__1 = *sfac * sd, abs(r__1)) <= abs(*ssize) * s_epsilon_(&c_b81)) { goto L40; } /* HERE SCOMP(I) IS NOT CLOSE TO STRUE(I). */ if (! combla_1.pass) { goto L20; } /* PRINT FAIL MESSAGE AND HEADER. */ combla_1.pass = FALSE_; s_wsfe(&io___125); e_wsfe(); s_wsfe(&io___126); e_wsfe(); L20: s_wsfe(&io___127); do_fio(&c__1, (char *)&combla_1.icase, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&combla_1.n, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&combla_1.incx, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&combla_1.incy, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&(*scomp), (ftnlen)sizeof(real)); do_fio(&c__1, (char *)&(*strue), (ftnlen)sizeof(real)); do_fio(&c__1, (char *)&sd, (ftnlen)sizeof(real)); do_fio(&c__1, (char *)&(*ssize), (ftnlen)sizeof(real)); e_wsfe(); L40: return 0; } /* testdsdot_ */ /* Subroutine */ int stest1_(doublereal *scomp1, doublereal *strue1, doublereal *ssize, doublereal *sfac) { doublereal scomp[1], strue[1]; extern /* Subroutine */ int stest_(integer *, doublereal *, doublereal *, doublereal *, doublereal *); /* ************************* STEST1 ***************************** */ /* THIS IS AN INTERFACE SUBROUTINE TO ACCOMODATE THE FORTRAN */ /* REQUIREMENT THAT WHEN A DUMMY ARGUMENT IS AN ARRAY, THE */ /* ACTUAL ARGUMENT MUST ALSO BE AN ARRAY OR AN ARRAY ELEMENT. */ /* C.L. LAWSON, JPL, 1978 DEC 6 */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Arrays .. */ /* .. External Subroutines .. */ /* .. Executable Statements .. */ /* Parameter adjustments */ --ssize; /* Function Body */ scomp[0] = *scomp1; strue[0] = *strue1; stest_(&c__1, scomp, strue, &ssize[1], sfac); return 0; } /* stest1_ */ doublereal sdiff_(doublereal *sa, doublereal *sb) { /* System generated locals */ doublereal ret_val; /* ********************************* SDIFF ************************** */ /* COMPUTES DIFFERENCE OF TWO NUMBERS. C. L. LAWSON, JPL 1974 FEB 15 */ /* .. Scalar Arguments .. */ /* .. Executable Statements .. */ ret_val = *sa - *sb; return ret_val; } /* sdiff_ */ /* Subroutine */ int itest1_(integer *icomp, integer *itrue) { /* Format strings */ static char fmt_99999[] = "(\002 F" "AIL\002)"; static char fmt_99998[] = "(/\002 CASE N INCX INCY " " \002,\002 COMP TRUE " " DIFFERENCE\002,/1x)"; static char fmt_99997[] = "(1x,i4,i3,2i5,2i36,i12)"; /* Builtin functions */ integer s_wsfe(cilist *), e_wsfe(void), do_fio(integer *, char *, ftnlen); /* Local variables */ integer id; /* Fortran I/O blocks */ static cilist io___130 = { 0, 6, 0, fmt_99999, 0 }; static cilist io___131 = { 0, 6, 0, fmt_99998, 0 }; static cilist io___133 = { 0, 6, 0, fmt_99997, 0 }; /* ********************************* ITEST1 ************************* */ /* THIS SUBROUTINE COMPARES THE VARIABLES ICOMP AND ITRUE FOR */ /* EQUALITY. */ /* C. L. LAWSON, JPL, 1974 DEC 10 */ /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Scalars in Common .. */ /* .. Local Scalars .. */ /* .. Common blocks .. */ /* .. Executable Statements .. */ if (*icomp == *itrue) { goto L40; } /* HERE ICOMP IS NOT EQUAL TO ITRUE. */ if (! combla_1.pass) { goto L20; } /* PRINT FAIL MESSAGE AND HEADER. */ combla_1.pass = FALSE_; s_wsfe(&io___130); e_wsfe(); s_wsfe(&io___131); e_wsfe(); L20: id = *icomp - *itrue; s_wsfe(&io___133); do_fio(&c__1, (char *)&combla_1.icase, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&combla_1.n, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&combla_1.incx, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&combla_1.incy, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&(*icomp), (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&(*itrue), (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&id, (ftnlen)sizeof(integer)); e_wsfe(); L40: return 0; } /* itest1_ */ /* Main program alias */ int dblat1_ () { main (); return 0; } blis-0.9.0/blastest/src/dblat2.c000066400000000000000000004540561422157504600164210ustar00rootroot00000000000000/* dblat2.f -- translated by f2c (version 20100827). You must link the resulting object file with libf2c: on Microsoft Windows system, link with libf2c.lib; on Linux or Unix systems, link with .../path/to/libf2c.a -lm or, if you install libf2c.a in a standard place, with -lf2c -lm -- in that order, at the end of the command line, as in cc *.o -lf2c -lm Source for libf2c is in /netlib/f2c/libf2c.zip, e.g., http://www.netlib.org/f2c/libf2c.zip */ #include "f2c.h" /* Common Block Declarations */ union { struct { integer infot, noutc; logical ok, lerr; } _1; struct { integer infot, nout; logical ok, lerr; } _2; } infoc_; #define infoc_1 (infoc_._1) #define infoc_2 (infoc_._2) struct { char srnamt[6]; } srnamc_; #define srnamc_1 srnamc_ /* Table of constant values */ static integer c__9 = 9; static integer c__1 = 1; static integer c__3 = 3; static integer c__8 = 8; static integer c__5 = 5; static integer c__65 = 65; static integer c__7 = 7; static integer c__2 = 2; static doublereal c_b120 = 0.; static doublereal c_b128 = 1.; static logical c_true = TRUE_; static integer c_n1 = -1; static integer c__0 = 0; static logical c_false = FALSE_; /* > \brief \b DBLAT2 */ /* =========== DOCUMENTATION =========== */ /* Online html documentation available at */ /* http://www.netlib.org/lapack/explore-html/ */ /* Definition: */ /* =========== */ /* PROGRAM DBLAT2 */ /* > \par Purpose: */ /* ============= */ /* > */ /* > \verbatim */ /* > */ /* > Test program for the DOUBLE PRECISION Level 2 Blas. */ /* > */ /* > The program must be driven by a short data file. The first 18 records */ /* > of the file are read using list-directed input, the last 16 records */ /* > are read using the format ( A6, L2 ). An annotated example of a data */ /* > file can be obtained by deleting the first 3 characters from the */ /* > following 34 lines: */ /* > 'dblat2.out' NAME OF SUMMARY OUTPUT FILE */ /* > 6 UNIT NUMBER OF SUMMARY FILE */ /* > 'DBLAT2.SNAP' NAME OF SNAPSHOT OUTPUT FILE */ /* > -1 UNIT NUMBER OF SNAPSHOT FILE (NOT USED IF .LT. 0) */ /* > F LOGICAL FLAG, T TO REWIND SNAPSHOT FILE AFTER EACH RECORD. */ /* > F LOGICAL FLAG, T TO STOP ON FAILURES. */ /* > T LOGICAL FLAG, T TO TEST ERROR EXITS. */ /* > 16.0 THRESHOLD VALUE OF TEST RATIO */ /* > 6 NUMBER OF VALUES OF N */ /* > 0 1 2 3 5 9 VALUES OF N */ /* > 4 NUMBER OF VALUES OF K */ /* > 0 1 2 4 VALUES OF K */ /* > 4 NUMBER OF VALUES OF INCX AND INCY */ /* > 1 2 -1 -2 VALUES OF INCX AND INCY */ /* > 3 NUMBER OF VALUES OF ALPHA */ /* > 0.0 1.0 0.7 VALUES OF ALPHA */ /* > 3 NUMBER OF VALUES OF BETA */ /* > 0.0 1.0 0.9 VALUES OF BETAC */ /* > DGEMV T PUT F FOR NO TEST. SAME COLUMNS. */ /* > DGBMV T PUT F FOR NO TEST. SAME COLUMNS. */ /* > DSYMV T PUT F FOR NO TEST. SAME COLUMNS. */ /* > DSBMV T PUT F FOR NO TEST. SAME COLUMNS. */ /* > DSPMV T PUT F FOR NO TEST. SAME COLUMNS. */ /* > DTRMV T PUT F FOR NO TEST. SAME COLUMNS. */ /* > DTBMV T PUT F FOR NO TEST. SAME COLUMNS. */ /* > DTPMV T PUT F FOR NO TEST. SAME COLUMNS. */ /* > DTRSV T PUT F FOR NO TEST. SAME COLUMNS. */ /* > DTBSV T PUT F FOR NO TEST. SAME COLUMNS. */ /* > DTPSV T PUT F FOR NO TEST. SAME COLUMNS. */ /* > DGER T PUT F FOR NO TEST. SAME COLUMNS. */ /* > DSYR T PUT F FOR NO TEST. SAME COLUMNS. */ /* > DSPR T PUT F FOR NO TEST. SAME COLUMNS. */ /* > DSYR2 T PUT F FOR NO TEST. SAME COLUMNS. */ /* > DSPR2 T PUT F FOR NO TEST. SAME COLUMNS. */ /* > */ /* > Further Details */ /* > =============== */ /* > */ /* > See: */ /* > */ /* > Dongarra J. J., Du Croz J. J., Hammarling S. and Hanson R. J.. */ /* > An extended set of Fortran Basic Linear Algebra Subprograms. */ /* > */ /* > Technical Memoranda Nos. 41 (revision 3) and 81, Mathematics */ /* > and Computer Science Division, Argonne National Laboratory, */ /* > 9700 South Cass Avenue, Argonne, Illinois 60439, US. */ /* > */ /* > Or */ /* > */ /* > NAG Technical Reports TR3/87 and TR4/87, Numerical Algorithms */ /* > Group Ltd., NAG Central Office, 256 Banbury Road, Oxford */ /* > OX2 7DE, UK, and Numerical Algorithms Group Inc., 1101 31st */ /* > Street, Suite 100, Downers Grove, Illinois 60515-1263, USA. */ /* > */ /* > */ /* > -- Written on 10-August-1987. */ /* > Richard Hanson, Sandia National Labs. */ /* > Jeremy Du Croz, NAG Central Office. */ /* > */ /* > 10-9-00: Change STATUS='NEW' to 'UNKNOWN' so that the testers */ /* > can be run multiple times without deleting generated */ /* > output files (susan) */ /* > \endverbatim */ /* Authors: */ /* ======== */ /* > \author Univ. of Tennessee */ /* > \author Univ. of California Berkeley */ /* > \author Univ. of Colorado Denver */ /* > \author NAG Ltd. */ /* > \date April 2012 */ /* > \ingroup double_blas_testing */ /* ===================================================================== */ /* Main program */ int main(void) { /* Initialized data */ static char snames[6*16] = "DGEMV " "DGBMV " "DSYMV " "DSBMV " "DSPMV " "DTRMV " "DTBMV " "DTPMV " "DTRSV " "DTBSV " "DTPSV " "DGER " "DSYR " "DSPR " "DSYR2 " "DSPR2 "; /* Format strings */ static char fmt_9997[] = "(\002 NUMBER OF VALUES OF \002,a,\002 IS LESS " "THAN 1 OR GREATER \002,\002THAN \002,i2)"; static char fmt_9996[] = "(\002 VALUE OF N IS LESS THAN 0 OR GREATER THA" "N \002,i2)"; static char fmt_9995[] = "(\002 VALUE OF K IS LESS THAN 0\002)"; static char fmt_9994[] = "(\002 ABSOLUTE VALUE OF INCX OR INCY IS 0 OR G" "REATER THAN \002,i2)"; static char fmt_9993[] = "(\002 TESTS OF THE DOUBLE PRECISION LEVEL 2 BL" "AS\002,//\002 THE F\002,\002OLLOWING PARAMETER VALUES WILL BE US" "ED:\002)"; static char fmt_9992[] = "(\002 FOR N \002,9i6)"; static char fmt_9991[] = "(\002 FOR K \002,7i6)"; static char fmt_9990[] = "(\002 FOR INCX AND INCY \002,7i6)"; static char fmt_9989[] = "(\002 FOR ALPHA \002,7f6.1)"; static char fmt_9988[] = "(\002 FOR BETA \002,7f6.1)"; static char fmt_9980[] = "(\002 ERROR-EXITS WILL NOT BE TESTED\002)"; static char fmt_9999[] = "(\002 ROUTINES PASS COMPUTATIONAL TESTS IF TES" "T RATIO IS LES\002,\002S THAN\002,f8.2)"; static char fmt_9984[] = "(a6,l2)"; static char fmt_9986[] = "(\002 SUBPROGRAM NAME \002,a6,\002 NOT RECOGNI" "ZED\002,/\002 ******* T\002,\002ESTS ABANDONED *******\002)"; static char fmt_9998[] = "(\002 RELATIVE MACHINE PRECISION IS TAKEN TO" " BE\002,1p,d9.1)"; static char fmt_9985[] = "(\002 ERROR IN DMVCH - IN-LINE DOT PRODUCTS A" "RE BEING EVALU\002,\002ATED WRONGLY.\002,/\002 DMVCH WAS CALLED " "WITH TRANS = \002,a1,\002 AND RETURNED SAME = \002,l1,\002 AND E" "RR = \002,f12.3,\002.\002,/\002 THIS MAY BE DUE TO FAULTS IN THE" " ARITHMETIC OR THE COMPILER.\002,/\002 ******* TESTS ABANDONED *" "******\002)"; static char fmt_9983[] = "(1x,a6,\002 WAS NOT TESTED\002)"; static char fmt_9982[] = "(/\002 END OF TESTS\002)"; static char fmt_9981[] = "(/\002 ******* FATAL ERROR - TESTS ABANDONED *" "******\002)"; static char fmt_9987[] = "(\002 AMEND DATA FILE OR INCREASE ARRAY SIZES " "IN PROGRAM\002,/\002 ******* TESTS ABANDONED *******\002)"; /* System generated locals */ integer i__1, i__2, i__3; olist o__1; cllist cl__1; /* Builtin functions */ integer s_rsle(cilist *), do_lio(integer *, integer *, char *, ftnlen), e_rsle(void), f_open(olist *), s_wsfe(cilist *), do_fio(integer *, char *, ftnlen), e_wsfe(void), s_wsle(cilist *), e_wsle(void), s_rsfe(cilist *), e_rsfe(void), s_cmp(const char *, const char *, ftnlen, ftnlen); /* Subroutine */ int s_stop(char *, ftnlen); integer f_clos(cllist *); /* Subroutine */ int s_copy(char *, const char *, ftnlen, ftnlen); /* Local variables */ doublereal a[4225] /* was [65][65] */, g[65]; integer i__, j, n; doublereal x[65], y[65], z__[130], aa[4225]; integer kb[7]; doublereal as[4225], xs[130], ys[130], yt[65], xx[130], yy[130], alf[7]; extern logical lde_(doublereal *, doublereal *, integer *); integer inc[7], nkb; doublereal bet[7], eps, err; integer nalf, idim[9]; logical same; integer ninc, nbet, ntra; logical rewi; integer nout; extern /* Subroutine */ int dchk1_(char *, doublereal *, doublereal *, integer *, integer *, logical *, logical *, logical *, integer *, integer *, integer *, integer *, integer *, doublereal *, integer *, doublereal *, integer *, integer *, integer *, integer *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, ftnlen), dchk2_(char *, doublereal *, doublereal *, integer *, integer *, logical *, logical *, logical *, integer *, integer *, integer *, integer *, integer *, doublereal *, integer *, doublereal *, integer *, integer *, integer *, integer *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, ftnlen), dchk3_(char *, doublereal *, doublereal *, integer *, integer *, logical *, logical *, logical *, integer *, integer *, integer *, integer *, integer *, integer *, integer *, integer *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, ftnlen), dchk4_(char *, doublereal *, doublereal *, integer *, integer *, logical *, logical *, logical *, integer *, integer *, integer *, doublereal *, integer *, integer *, integer *, integer *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, ftnlen), dchk5_(char *, doublereal *, doublereal *, integer *, integer *, logical *, logical *, logical *, integer *, integer *, integer *, doublereal *, integer *, integer *, integer *, integer *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, ftnlen), dchk6_(char *, doublereal *, doublereal *, integer *, integer *, logical *, logical *, logical *, integer *, integer *, integer *, doublereal *, integer *, integer *, integer *, integer *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, ftnlen), dchke_(integer *, char *, integer *, ftnlen); logical fatal, trace; integer nidim; extern /* Subroutine */ int dmvch_(char *, integer *, integer *, doublereal *, doublereal *, integer *, doublereal *, integer *, doublereal *, doublereal *, integer *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, logical *, integer *, logical *, ftnlen); char snaps[32], trans[1]; integer isnum; logical ltest[16], sfatal; char snamet[6]; doublereal thresh; logical ltestt, tsterr; char summry[32]; extern double d_epsilon_(doublereal *); /* Fortran I/O blocks */ static cilist io___2 = { 0, 5, 0, 0, 0 }; static cilist io___4 = { 0, 5, 0, 0, 0 }; static cilist io___6 = { 0, 5, 0, 0, 0 }; static cilist io___8 = { 0, 5, 0, 0, 0 }; static cilist io___11 = { 0, 5, 0, 0, 0 }; static cilist io___13 = { 0, 5, 0, 0, 0 }; static cilist io___15 = { 0, 5, 0, 0, 0 }; static cilist io___17 = { 0, 5, 0, 0, 0 }; static cilist io___19 = { 0, 5, 0, 0, 0 }; static cilist io___21 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___22 = { 0, 5, 0, 0, 0 }; static cilist io___25 = { 0, 0, 0, fmt_9996, 0 }; static cilist io___26 = { 0, 5, 0, 0, 0 }; static cilist io___28 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___29 = { 0, 5, 0, 0, 0 }; static cilist io___31 = { 0, 0, 0, fmt_9995, 0 }; static cilist io___32 = { 0, 5, 0, 0, 0 }; static cilist io___34 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___35 = { 0, 5, 0, 0, 0 }; static cilist io___37 = { 0, 0, 0, fmt_9994, 0 }; static cilist io___38 = { 0, 5, 0, 0, 0 }; static cilist io___40 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___41 = { 0, 5, 0, 0, 0 }; static cilist io___43 = { 0, 5, 0, 0, 0 }; static cilist io___45 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___46 = { 0, 5, 0, 0, 0 }; static cilist io___48 = { 0, 0, 0, fmt_9993, 0 }; static cilist io___49 = { 0, 0, 0, fmt_9992, 0 }; static cilist io___50 = { 0, 0, 0, fmt_9991, 0 }; static cilist io___51 = { 0, 0, 0, fmt_9990, 0 }; static cilist io___52 = { 0, 0, 0, fmt_9989, 0 }; static cilist io___53 = { 0, 0, 0, fmt_9988, 0 }; static cilist io___54 = { 0, 0, 0, 0, 0 }; static cilist io___55 = { 0, 0, 0, fmt_9980, 0 }; static cilist io___56 = { 0, 0, 0, 0, 0 }; static cilist io___57 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___58 = { 0, 0, 0, 0, 0 }; static cilist io___60 = { 0, 5, 1, fmt_9984, 0 }; static cilist io___63 = { 0, 0, 0, fmt_9986, 0 }; static cilist io___65 = { 0, 0, 0, fmt_9998, 0 }; static cilist io___78 = { 0, 0, 0, fmt_9985, 0 }; static cilist io___79 = { 0, 0, 0, fmt_9985, 0 }; static cilist io___81 = { 0, 0, 0, 0, 0 }; static cilist io___82 = { 0, 0, 0, fmt_9983, 0 }; static cilist io___83 = { 0, 0, 0, 0, 0 }; static cilist io___90 = { 0, 0, 0, fmt_9982, 0 }; static cilist io___91 = { 0, 0, 0, fmt_9981, 0 }; static cilist io___92 = { 0, 0, 0, fmt_9987, 0 }; /* -- Reference BLAS test routine (version 3.4.1) -- */ /* -- Reference BLAS is a software package provided by Univ. of Tennessee, -- */ /* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- */ /* April 2012 */ /* ===================================================================== */ /* .. Parameters .. */ /* .. Local Scalars .. */ /* .. Local Arrays .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. Scalars in Common .. */ /* .. Common blocks .. */ /* .. Data statements .. */ /* .. Executable Statements .. */ /* Read name and unit number for summary output file and open file. */ s_rsle(&io___2); do_lio(&c__9, &c__1, summry, (ftnlen)32); e_rsle(); s_rsle(&io___4); do_lio(&c__3, &c__1, (char *)&nout, (ftnlen)sizeof(integer)); e_rsle(); o__1.oerr = 0; o__1.ounit = nout; o__1.ofnmlen = 32; o__1.ofnm = summry; o__1.orl = 0; o__1.osta = "UNKNOWN"; o__1.oacc = 0; o__1.ofm = 0; o__1.oblnk = 0; f_open(&o__1); infoc_1.noutc = nout; /* Read name and unit number for snapshot output file and open file. */ s_rsle(&io___6); do_lio(&c__9, &c__1, snaps, (ftnlen)32); e_rsle(); s_rsle(&io___8); do_lio(&c__3, &c__1, (char *)&ntra, (ftnlen)sizeof(integer)); e_rsle(); trace = ntra >= 0; if (trace) { o__1.oerr = 0; o__1.ounit = ntra; o__1.ofnmlen = 32; o__1.ofnm = snaps; o__1.orl = 0; o__1.osta = "UNKNOWN"; o__1.oacc = 0; o__1.ofm = 0; o__1.oblnk = 0; f_open(&o__1); } /* Read the flag that directs rewinding of the snapshot file. */ s_rsle(&io___11); do_lio(&c__8, &c__1, (char *)&rewi, (ftnlen)sizeof(logical)); e_rsle(); rewi = rewi && trace; /* Read the flag that directs stopping on any failure. */ s_rsle(&io___13); do_lio(&c__8, &c__1, (char *)&sfatal, (ftnlen)sizeof(logical)); e_rsle(); /* Read the flag that indicates whether error exits are to be tested. */ s_rsle(&io___15); do_lio(&c__8, &c__1, (char *)&tsterr, (ftnlen)sizeof(logical)); e_rsle(); /* Read the threshold value of the test ratio */ s_rsle(&io___17); do_lio(&c__5, &c__1, (char *)&thresh, (ftnlen)sizeof(doublereal)); e_rsle(); /* Read and check the parameter values for the tests. */ /* Values of N */ s_rsle(&io___19); do_lio(&c__3, &c__1, (char *)&nidim, (ftnlen)sizeof(integer)); e_rsle(); if (nidim < 1 || nidim > 9) { io___21.ciunit = nout; s_wsfe(&io___21); do_fio(&c__1, "N", (ftnlen)1); do_fio(&c__1, (char *)&c__9, (ftnlen)sizeof(integer)); e_wsfe(); goto L230; } s_rsle(&io___22); i__1 = nidim; for (i__ = 1; i__ <= i__1; ++i__) { do_lio(&c__3, &c__1, (char *)&idim[i__ - 1], (ftnlen)sizeof(integer)); } e_rsle(); i__1 = nidim; for (i__ = 1; i__ <= i__1; ++i__) { if (idim[i__ - 1] < 0 || idim[i__ - 1] > 65) { io___25.ciunit = nout; s_wsfe(&io___25); do_fio(&c__1, (char *)&c__65, (ftnlen)sizeof(integer)); e_wsfe(); goto L230; } /* L10: */ } /* Values of K */ s_rsle(&io___26); do_lio(&c__3, &c__1, (char *)&nkb, (ftnlen)sizeof(integer)); e_rsle(); if (nkb < 1 || nkb > 7) { io___28.ciunit = nout; s_wsfe(&io___28); do_fio(&c__1, "K", (ftnlen)1); do_fio(&c__1, (char *)&c__7, (ftnlen)sizeof(integer)); e_wsfe(); goto L230; } s_rsle(&io___29); i__1 = nkb; for (i__ = 1; i__ <= i__1; ++i__) { do_lio(&c__3, &c__1, (char *)&kb[i__ - 1], (ftnlen)sizeof(integer)); } e_rsle(); i__1 = nkb; for (i__ = 1; i__ <= i__1; ++i__) { if (kb[i__ - 1] < 0) { io___31.ciunit = nout; s_wsfe(&io___31); e_wsfe(); goto L230; } /* L20: */ } /* Values of INCX and INCY */ s_rsle(&io___32); do_lio(&c__3, &c__1, (char *)&ninc, (ftnlen)sizeof(integer)); e_rsle(); if (ninc < 1 || ninc > 7) { io___34.ciunit = nout; s_wsfe(&io___34); do_fio(&c__1, "INCX AND INCY", (ftnlen)13); do_fio(&c__1, (char *)&c__7, (ftnlen)sizeof(integer)); e_wsfe(); goto L230; } s_rsle(&io___35); i__1 = ninc; for (i__ = 1; i__ <= i__1; ++i__) { do_lio(&c__3, &c__1, (char *)&inc[i__ - 1], (ftnlen)sizeof(integer)); } e_rsle(); i__1 = ninc; for (i__ = 1; i__ <= i__1; ++i__) { if (inc[i__ - 1] == 0 || (i__2 = inc[i__ - 1], abs(i__2)) > 2) { io___37.ciunit = nout; s_wsfe(&io___37); do_fio(&c__1, (char *)&c__2, (ftnlen)sizeof(integer)); e_wsfe(); goto L230; } /* L30: */ } /* Values of ALPHA */ s_rsle(&io___38); do_lio(&c__3, &c__1, (char *)&nalf, (ftnlen)sizeof(integer)); e_rsle(); if (nalf < 1 || nalf > 7) { io___40.ciunit = nout; s_wsfe(&io___40); do_fio(&c__1, "ALPHA", (ftnlen)5); do_fio(&c__1, (char *)&c__7, (ftnlen)sizeof(integer)); e_wsfe(); goto L230; } s_rsle(&io___41); i__1 = nalf; for (i__ = 1; i__ <= i__1; ++i__) { do_lio(&c__5, &c__1, (char *)&alf[i__ - 1], (ftnlen)sizeof(doublereal) ); } e_rsle(); /* Values of BETA */ s_rsle(&io___43); do_lio(&c__3, &c__1, (char *)&nbet, (ftnlen)sizeof(integer)); e_rsle(); if (nbet < 1 || nbet > 7) { io___45.ciunit = nout; s_wsfe(&io___45); do_fio(&c__1, "BETA", (ftnlen)4); do_fio(&c__1, (char *)&c__7, (ftnlen)sizeof(integer)); e_wsfe(); goto L230; } s_rsle(&io___46); i__1 = nbet; for (i__ = 1; i__ <= i__1; ++i__) { do_lio(&c__5, &c__1, (char *)&bet[i__ - 1], (ftnlen)sizeof(doublereal) ); } e_rsle(); /* Report values of parameters. */ io___48.ciunit = nout; s_wsfe(&io___48); e_wsfe(); io___49.ciunit = nout; s_wsfe(&io___49); i__1 = nidim; for (i__ = 1; i__ <= i__1; ++i__) { do_fio(&c__1, (char *)&idim[i__ - 1], (ftnlen)sizeof(integer)); } e_wsfe(); io___50.ciunit = nout; s_wsfe(&io___50); i__1 = nkb; for (i__ = 1; i__ <= i__1; ++i__) { do_fio(&c__1, (char *)&kb[i__ - 1], (ftnlen)sizeof(integer)); } e_wsfe(); io___51.ciunit = nout; s_wsfe(&io___51); i__1 = ninc; for (i__ = 1; i__ <= i__1; ++i__) { do_fio(&c__1, (char *)&inc[i__ - 1], (ftnlen)sizeof(integer)); } e_wsfe(); io___52.ciunit = nout; s_wsfe(&io___52); i__1 = nalf; for (i__ = 1; i__ <= i__1; ++i__) { do_fio(&c__1, (char *)&alf[i__ - 1], (ftnlen)sizeof(doublereal)); } e_wsfe(); io___53.ciunit = nout; s_wsfe(&io___53); i__1 = nbet; for (i__ = 1; i__ <= i__1; ++i__) { do_fio(&c__1, (char *)&bet[i__ - 1], (ftnlen)sizeof(doublereal)); } e_wsfe(); if (! tsterr) { io___54.ciunit = nout; s_wsle(&io___54); e_wsle(); io___55.ciunit = nout; s_wsfe(&io___55); e_wsfe(); } io___56.ciunit = nout; s_wsle(&io___56); e_wsle(); io___57.ciunit = nout; s_wsfe(&io___57); do_fio(&c__1, (char *)&thresh, (ftnlen)sizeof(doublereal)); e_wsfe(); io___58.ciunit = nout; s_wsle(&io___58); e_wsle(); /* Read names of subroutines and flags which indicate */ /* whether they are to be tested. */ for (i__ = 1; i__ <= 16; ++i__) { ltest[i__ - 1] = FALSE_; /* L40: */ } L50: i__1 = s_rsfe(&io___60); if (i__1 != 0) { goto L80; } i__1 = do_fio(&c__1, snamet, (ftnlen)6); if (i__1 != 0) { goto L80; } i__1 = do_fio(&c__1, (char *)<estt, (ftnlen)sizeof(logical)); if (i__1 != 0) { goto L80; } i__1 = e_rsfe(); if (i__1 != 0) { goto L80; } for (i__ = 1; i__ <= 16; ++i__) { if (s_cmp(snamet, snames + (i__ - 1) * 6, (ftnlen)6, (ftnlen)6) == 0) { goto L70; } /* L60: */ } io___63.ciunit = nout; s_wsfe(&io___63); do_fio(&c__1, snamet, (ftnlen)6); e_wsfe(); s_stop("", (ftnlen)0); L70: ltest[i__ - 1] = ltestt; goto L50; L80: cl__1.cerr = 0; cl__1.cunit = 5; cl__1.csta = 0; f_clos(&cl__1); /* Compute EPS (the machine precision). */ eps = d_epsilon_(&c_b120); io___65.ciunit = nout; s_wsfe(&io___65); do_fio(&c__1, (char *)&eps, (ftnlen)sizeof(doublereal)); e_wsfe(); /* Check the reliability of DMVCH using exact data. */ n = 32; i__1 = n; for (j = 1; j <= i__1; ++j) { i__2 = n; for (i__ = 1; i__ <= i__2; ++i__) { /* Computing MAX */ i__3 = i__ - j + 1; a[i__ + j * 65 - 66] = (doublereal) max(i__3,0); /* L110: */ } x[j - 1] = (doublereal) j; y[j - 1] = 0.; /* L120: */ } i__1 = n; for (j = 1; j <= i__1; ++j) { yy[j - 1] = (doublereal) (j * ((j + 1) * j) / 2 - (j + 1) * j * (j - 1) / 3); /* L130: */ } /* YY holds the exact result. On exit from DMVCH YT holds */ /* the result computed by DMVCH. */ *(unsigned char *)trans = 'N'; dmvch_(trans, &n, &n, &c_b128, a, &c__65, x, &c__1, &c_b120, y, &c__1, yt, g, yy, &eps, &err, &fatal, &nout, &c_true, (ftnlen)1); same = lde_(yy, yt, &n); if (! same || err != 0.) { io___78.ciunit = nout; s_wsfe(&io___78); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, (char *)&same, (ftnlen)sizeof(logical)); do_fio(&c__1, (char *)&err, (ftnlen)sizeof(doublereal)); e_wsfe(); s_stop("", (ftnlen)0); } *(unsigned char *)trans = 'T'; dmvch_(trans, &n, &n, &c_b128, a, &c__65, x, &c_n1, &c_b120, y, &c_n1, yt, g, yy, &eps, &err, &fatal, &nout, &c_true, (ftnlen)1); same = lde_(yy, yt, &n); if (! same || err != 0.) { io___79.ciunit = nout; s_wsfe(&io___79); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, (char *)&same, (ftnlen)sizeof(logical)); do_fio(&c__1, (char *)&err, (ftnlen)sizeof(doublereal)); e_wsfe(); s_stop("", (ftnlen)0); } /* Test each subroutine in turn. */ for (isnum = 1; isnum <= 16; ++isnum) { io___81.ciunit = nout; s_wsle(&io___81); e_wsle(); if (! ltest[isnum - 1]) { /* Subprogram is not to be tested. */ io___82.ciunit = nout; s_wsfe(&io___82); do_fio(&c__1, snames + (isnum - 1) * 6, (ftnlen)6); e_wsfe(); } else { s_copy(srnamc_1.srnamt, snames + (isnum - 1) * 6, (ftnlen)6, ( ftnlen)6); /* Test error exits. */ if (tsterr) { dchke_(&isnum, snames + (isnum - 1) * 6, &nout, (ftnlen)6); io___83.ciunit = nout; s_wsle(&io___83); e_wsle(); } /* Test computations. */ infoc_1.infot = 0; infoc_1.ok = TRUE_; fatal = FALSE_; switch (isnum) { case 1: goto L140; case 2: goto L140; case 3: goto L150; case 4: goto L150; case 5: goto L150; case 6: goto L160; case 7: goto L160; case 8: goto L160; case 9: goto L160; case 10: goto L160; case 11: goto L160; case 12: goto L170; case 13: goto L180; case 14: goto L180; case 15: goto L190; case 16: goto L190; } /* Test DGEMV, 01, and DGBMV, 02. */ L140: dchk1_(snames + (isnum - 1) * 6, &eps, &thresh, &nout, &ntra, & trace, &rewi, &fatal, &nidim, idim, &nkb, kb, &nalf, alf, &nbet, bet, &ninc, inc, &c__65, &c__2, a, aa, as, x, xx, xs, y, yy, ys, yt, g, (ftnlen)6); goto L200; /* Test DSYMV, 03, DSBMV, 04, and DSPMV, 05. */ L150: dchk2_(snames + (isnum - 1) * 6, &eps, &thresh, &nout, &ntra, & trace, &rewi, &fatal, &nidim, idim, &nkb, kb, &nalf, alf, &nbet, bet, &ninc, inc, &c__65, &c__2, a, aa, as, x, xx, xs, y, yy, ys, yt, g, (ftnlen)6); goto L200; /* Test DTRMV, 06, DTBMV, 07, DTPMV, 08, */ /* DTRSV, 09, DTBSV, 10, and DTPSV, 11. */ L160: dchk3_(snames + (isnum - 1) * 6, &eps, &thresh, &nout, &ntra, & trace, &rewi, &fatal, &nidim, idim, &nkb, kb, &ninc, inc, &c__65, &c__2, a, aa, as, y, yy, ys, yt, g, z__, (ftnlen) 6); goto L200; /* Test DGER, 12. */ L170: dchk4_(snames + (isnum - 1) * 6, &eps, &thresh, &nout, &ntra, & trace, &rewi, &fatal, &nidim, idim, &nalf, alf, &ninc, inc, &c__65, &c__2, a, aa, as, x, xx, xs, y, yy, ys, yt, g, z__, (ftnlen)6); goto L200; /* Test DSYR, 13, and DSPR, 14. */ L180: dchk5_(snames + (isnum - 1) * 6, &eps, &thresh, &nout, &ntra, & trace, &rewi, &fatal, &nidim, idim, &nalf, alf, &ninc, inc, &c__65, &c__2, a, aa, as, x, xx, xs, y, yy, ys, yt, g, z__, (ftnlen)6); goto L200; /* Test DSYR2, 15, and DSPR2, 16. */ L190: dchk6_(snames + (isnum - 1) * 6, &eps, &thresh, &nout, &ntra, & trace, &rewi, &fatal, &nidim, idim, &nalf, alf, &ninc, inc, &c__65, &c__2, a, aa, as, x, xx, xs, y, yy, ys, yt, g, z__, (ftnlen)6); L200: if (fatal && sfatal) { goto L220; } } /* L210: */ } io___90.ciunit = nout; s_wsfe(&io___90); e_wsfe(); goto L240; L220: io___91.ciunit = nout; s_wsfe(&io___91); e_wsfe(); goto L240; L230: io___92.ciunit = nout; s_wsfe(&io___92); e_wsfe(); L240: if (trace) { cl__1.cerr = 0; cl__1.cunit = ntra; cl__1.csta = 0; f_clos(&cl__1); } cl__1.cerr = 0; cl__1.cunit = nout; cl__1.csta = 0; f_clos(&cl__1); s_stop("", (ftnlen)0); /* End of DBLAT2. */ return 0; } /* main */ /* Subroutine */ int dchk1_(char *sname, doublereal *eps, doublereal *thresh, integer *nout, integer *ntra, logical *trace, logical *rewi, logical * fatal, integer *nidim, integer *idim, integer *nkb, integer *kb, integer *nalf, doublereal *alf, integer *nbet, doublereal *bet, integer *ninc, integer *inc, integer *nmax, integer *incmax, doublereal *a, doublereal *aa, doublereal *as, doublereal *x, doublereal *xx, doublereal *xs, doublereal *y, doublereal *yy, doublereal *ys, doublereal *yt, doublereal *g, ftnlen sname_len) { /* Initialized data */ static char ich[3] = "NTC"; /* Format strings */ static char fmt_9994[] = "(1x,i6,\002: \002,a6,\002('\002,a1,\002',\002," "2(i3,\002,\002),f4.1,\002, A,\002,i3,\002, X,\002,i2,\002,\002,f" "4.1,\002, Y,\002,i2,\002) .\002)"; static char fmt_9995[] = "(1x,i6,\002: \002,a6,\002('\002,a1,\002',\002," "4(i3,\002,\002),f4.1,\002, A,\002,i3,\002, X,\002,i2,\002,\002,f" "4.1,\002, Y,\002,i2,\002) .\002)"; static char fmt_9993[] = "(\002 ******* FATAL ERROR - ERROR-EXIT TAKEN O" "N VALID CALL *\002,\002******\002)"; static char fmt_9998[] = "(\002 ******* FATAL ERROR - PARAMETER NUMBER" " \002,i2,\002 WAS CH\002,\002ANGED INCORRECTLY *******\002)"; static char fmt_9999[] = "(\002 \002,a6,\002 PASSED THE COMPUTATIONAL TE" "STS (\002,i6,\002 CALL\002,\002S)\002)"; static char fmt_9997[] = "(\002 \002,a6,\002 COMPLETED THE COMPUTATIONAL" " TESTS (\002,i6,\002 C\002,\002ALLS)\002,/\002 ******* BUT WITH " "MAXIMUM TEST RATIO\002,f8.2,\002 - SUSPECT *******\002)"; static char fmt_9996[] = "(\002 ******* \002,a6,\002 FAILED ON CALL NUMB" "ER:\002)"; /* System generated locals */ integer a_dim1, a_offset, i__1, i__2, i__3, i__4, i__5, i__6, i__7, i__8; alist al__1; /* Builtin functions */ integer s_wsfe(cilist *), do_fio(integer *, char *, ftnlen), e_wsfe(void), f_rew(alist *); /* Local variables */ integer i__, m, n, ia, ib, ic, nc, nd, im, in, kl, ml, nk, nl, ku, ix, iy, ms, lx, ly, ns, laa, lda; extern logical lde_(doublereal *, doublereal *, integer *); doublereal als, bls, err; integer iku, kls, kus; doublereal beta; integer ldas; logical same; integer incx, incy; logical full, tran, null; extern /* Subroutine */ int dmake_(char *, char *, char *, integer *, integer *, doublereal *, integer *, doublereal *, integer *, integer *, integer *, logical *, doublereal *, ftnlen, ftnlen, ftnlen); doublereal alpha; logical isame[13]; extern /* Subroutine */ int dgbmv_(char *, integer *, integer *, integer * , integer *, doublereal *, doublereal *, integer *, doublereal *, integer *, doublereal *, doublereal *, integer *, ftnlen), dgemv_( char *, integer *, integer *, doublereal *, doublereal *, integer *, doublereal *, integer *, doublereal *, doublereal *, integer *, ftnlen), dmvch_(char *, integer *, integer *, doublereal *, doublereal *, integer *, doublereal *, integer *, doublereal *, doublereal *, integer *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, logical *, integer *, logical *, ftnlen); integer nargs; logical reset; integer incxs, incys; char trans[1]; logical banded; extern logical lderes_(char *, char *, integer *, integer *, doublereal *, doublereal *, integer *, ftnlen, ftnlen); doublereal errmax, transl; char transs[1]; /* Fortran I/O blocks */ static cilist io___139 = { 0, 0, 0, fmt_9994, 0 }; static cilist io___140 = { 0, 0, 0, fmt_9995, 0 }; static cilist io___141 = { 0, 0, 0, fmt_9993, 0 }; static cilist io___144 = { 0, 0, 0, fmt_9998, 0 }; static cilist io___146 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___147 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___148 = { 0, 0, 0, fmt_9996, 0 }; static cilist io___149 = { 0, 0, 0, fmt_9994, 0 }; static cilist io___150 = { 0, 0, 0, fmt_9995, 0 }; /* Tests DGEMV and DGBMV. */ /* Auxiliary routine for test program for Level 2 Blas. */ /* -- Written on 10-August-1987. */ /* Richard Hanson, Sandia National Labs. */ /* Jeremy Du Croz, NAG Central Office. */ /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Scalars .. */ /* .. Local Arrays .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. Scalars in Common .. */ /* .. Common blocks .. */ /* .. Data statements .. */ /* Parameter adjustments */ --idim; --kb; --alf; --bet; --inc; --g; --yt; --y; --x; --as; --aa; a_dim1 = *nmax; a_offset = 1 + a_dim1; a -= a_offset; --ys; --yy; --xs; --xx; /* Function Body */ /* .. Executable Statements .. */ full = *(unsigned char *)&sname[2] == 'E'; banded = *(unsigned char *)&sname[2] == 'B'; /* Define the number of arguments. */ if (full) { nargs = 11; } else if (banded) { nargs = 13; } nc = 0; reset = TRUE_; errmax = 0.; i__1 = *nidim; for (in = 1; in <= i__1; ++in) { n = idim[in]; nd = n / 2 + 1; for (im = 1; im <= 2; ++im) { if (im == 1) { /* Computing MAX */ i__2 = n - nd; m = max(i__2,0); } if (im == 2) { /* Computing MIN */ i__2 = n + nd; m = min(i__2,*nmax); } if (banded) { nk = *nkb; } else { nk = 1; } i__2 = nk; for (iku = 1; iku <= i__2; ++iku) { if (banded) { ku = kb[iku]; /* Computing MAX */ i__3 = ku - 1; kl = max(i__3,0); } else { ku = n - 1; kl = m - 1; } /* Set LDA to 1 more than minimum value if room. */ if (banded) { lda = kl + ku + 1; } else { lda = m; } if (lda < *nmax) { ++lda; } /* Skip tests if not enough room. */ if (lda > *nmax) { goto L100; } laa = lda * n; null = n <= 0 || m <= 0; /* Generate the matrix A. */ transl = 0.; dmake_(sname + 1, " ", " ", &m, &n, &a[a_offset], nmax, &aa[1] , &lda, &kl, &ku, &reset, &transl, (ftnlen)2, (ftnlen) 1, (ftnlen)1); for (ic = 1; ic <= 3; ++ic) { *(unsigned char *)trans = *(unsigned char *)&ich[ic - 1]; tran = *(unsigned char *)trans == 'T' || *(unsigned char * )trans == 'C'; if (tran) { ml = n; nl = m; } else { ml = m; nl = n; } i__3 = *ninc; for (ix = 1; ix <= i__3; ++ix) { incx = inc[ix]; lx = abs(incx) * nl; /* Generate the vector X. */ transl = .5; i__4 = abs(incx); i__5 = nl - 1; dmake_("GE", " ", " ", &c__1, &nl, &x[1], &c__1, &xx[ 1], &i__4, &c__0, &i__5, &reset, &transl, ( ftnlen)2, (ftnlen)1, (ftnlen)1); if (nl > 1) { x[nl / 2] = 0.; xx[abs(incx) * (nl / 2 - 1) + 1] = 0.; } i__4 = *ninc; for (iy = 1; iy <= i__4; ++iy) { incy = inc[iy]; ly = abs(incy) * ml; i__5 = *nalf; for (ia = 1; ia <= i__5; ++ia) { alpha = alf[ia]; i__6 = *nbet; for (ib = 1; ib <= i__6; ++ib) { beta = bet[ib]; /* Generate the vector Y. */ transl = 0.; i__7 = abs(incy); i__8 = ml - 1; dmake_("GE", " ", " ", &c__1, &ml, &y[1], &c__1, &yy[1], &i__7, &c__0, & i__8, &reset, &transl, (ftnlen)2, (ftnlen)1, (ftnlen)1); ++nc; /* Save every datum before calling the */ /* subroutine. */ *(unsigned char *)transs = *(unsigned char *)trans; ms = m; ns = n; kls = kl; kus = ku; als = alpha; i__7 = laa; for (i__ = 1; i__ <= i__7; ++i__) { as[i__] = aa[i__]; /* L10: */ } ldas = lda; i__7 = lx; for (i__ = 1; i__ <= i__7; ++i__) { xs[i__] = xx[i__]; /* L20: */ } incxs = incx; bls = beta; i__7 = ly; for (i__ = 1; i__ <= i__7; ++i__) { ys[i__] = yy[i__]; /* L30: */ } incys = incy; /* Call the subroutine. */ if (full) { if (*trace) { io___139.ciunit = *ntra; s_wsfe(&io___139); do_fio(&c__1, (char *)&nc, ( ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, (char *)&m, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&n, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&alpha, ( ftnlen)sizeof(doublereal)) ; do_fio(&c__1, (char *)&lda, ( ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&incx, ( ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&beta, ( ftnlen)sizeof(doublereal)) ; do_fio(&c__1, (char *)&incy, ( ftnlen)sizeof(integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } dgemv_(trans, &m, &n, &alpha, &aa[1], &lda, &xx[1], &incx, &beta, & yy[1], &incy, (ftnlen)1); } else if (banded) { if (*trace) { io___140.ciunit = *ntra; s_wsfe(&io___140); do_fio(&c__1, (char *)&nc, ( ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, (char *)&m, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&n, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&kl, ( ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&ku, ( ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&alpha, ( ftnlen)sizeof(doublereal)) ; do_fio(&c__1, (char *)&lda, ( ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&incx, ( ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&beta, ( ftnlen)sizeof(doublereal)) ; do_fio(&c__1, (char *)&incy, ( ftnlen)sizeof(integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } dgbmv_(trans, &m, &n, &kl, &ku, & alpha, &aa[1], &lda, &xx[1], & incx, &beta, &yy[1], &incy, ( ftnlen)1); } /* Check if error-exit was taken incorrectly. */ if (! infoc_1.ok) { io___141.ciunit = *nout; s_wsfe(&io___141); e_wsfe(); *fatal = TRUE_; goto L130; } /* See what data changed inside subroutines. */ isame[0] = *(unsigned char *)trans == *( unsigned char *)transs; isame[1] = ms == m; isame[2] = ns == n; if (full) { isame[3] = als == alpha; isame[4] = lde_(&as[1], &aa[1], &laa); isame[5] = ldas == lda; isame[6] = lde_(&xs[1], &xx[1], &lx); isame[7] = incxs == incx; isame[8] = bls == beta; if (null) { isame[9] = lde_(&ys[1], &yy[1], & ly); } else { i__7 = abs(incy); isame[9] = lderes_("GE", " ", & c__1, &ml, &ys[1], &yy[1], &i__7, (ftnlen)2, ( ftnlen)1); } isame[10] = incys == incy; } else if (banded) { isame[3] = kls == kl; isame[4] = kus == ku; isame[5] = als == alpha; isame[6] = lde_(&as[1], &aa[1], &laa); isame[7] = ldas == lda; isame[8] = lde_(&xs[1], &xx[1], &lx); isame[9] = incxs == incx; isame[10] = bls == beta; if (null) { isame[11] = lde_(&ys[1], &yy[1], & ly); } else { i__7 = abs(incy); isame[11] = lderes_("GE", " ", & c__1, &ml, &ys[1], &yy[1], &i__7, (ftnlen)2, ( ftnlen)1); } isame[12] = incys == incy; } /* If data was incorrectly changed, report */ /* and return. */ same = TRUE_; i__7 = nargs; for (i__ = 1; i__ <= i__7; ++i__) { same = same && isame[i__ - 1]; if (! isame[i__ - 1]) { io___144.ciunit = *nout; s_wsfe(&io___144); do_fio(&c__1, (char *)&i__, ( ftnlen)sizeof(integer)); e_wsfe(); } /* L40: */ } if (! same) { *fatal = TRUE_; goto L130; } if (! null) { /* Check the result. */ dmvch_(trans, &m, &n, &alpha, &a[ a_offset], nmax, &x[1], &incx, &beta, &y[1], &incy, &yt[1], &g[1], &yy[1], eps, &err, fatal, nout, &c_true, (ftnlen) 1); errmax = max(errmax,err); /* If got really bad answer, report and */ /* return. */ if (*fatal) { goto L130; } } else { /* Avoid repeating tests with M.le.0 or */ /* N.le.0. */ goto L110; } /* L50: */ } /* L60: */ } /* L70: */ } /* L80: */ } /* L90: */ } L100: ; } L110: ; } /* L120: */ } /* Report result. */ if (errmax < *thresh) { io___146.ciunit = *nout; s_wsfe(&io___146); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); e_wsfe(); } else { io___147.ciunit = *nout; s_wsfe(&io___147); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&errmax, (ftnlen)sizeof(doublereal)); e_wsfe(); } goto L140; L130: io___148.ciunit = *nout; s_wsfe(&io___148); do_fio(&c__1, sname, (ftnlen)6); e_wsfe(); if (full) { io___149.ciunit = *nout; s_wsfe(&io___149); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, (char *)&m, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&alpha, (ftnlen)sizeof(doublereal)); do_fio(&c__1, (char *)&lda, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&incx, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&beta, (ftnlen)sizeof(doublereal)); do_fio(&c__1, (char *)&incy, (ftnlen)sizeof(integer)); e_wsfe(); } else if (banded) { io___150.ciunit = *nout; s_wsfe(&io___150); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, (char *)&m, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&kl, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&ku, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&alpha, (ftnlen)sizeof(doublereal)); do_fio(&c__1, (char *)&lda, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&incx, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&beta, (ftnlen)sizeof(doublereal)); do_fio(&c__1, (char *)&incy, (ftnlen)sizeof(integer)); e_wsfe(); } L140: return 0; /* End of DCHK1. */ } /* dchk1_ */ /* Subroutine */ int dchk2_(char *sname, doublereal *eps, doublereal *thresh, integer *nout, integer *ntra, logical *trace, logical *rewi, logical * fatal, integer *nidim, integer *idim, integer *nkb, integer *kb, integer *nalf, doublereal *alf, integer *nbet, doublereal *bet, integer *ninc, integer *inc, integer *nmax, integer *incmax, doublereal *a, doublereal *aa, doublereal *as, doublereal *x, doublereal *xx, doublereal *xs, doublereal *y, doublereal *yy, doublereal *ys, doublereal *yt, doublereal *g, ftnlen sname_len) { /* Initialized data */ static char ich[2] = "UL"; /* Format strings */ static char fmt_9993[] = "(1x,i6,\002: \002,a6,\002('\002,a1,\002',\002," "i3,\002,\002,f4.1,\002, A,\002,i3,\002, X,\002,i2,\002,\002,f4.1," "\002, Y,\002,i2,\002) .\002)"; static char fmt_9994[] = "(1x,i6,\002: \002,a6,\002('\002,a1,\002',\002," "2(i3,\002,\002),f4.1,\002, A,\002,i3,\002, X,\002,i2,\002,\002,f" "4.1,\002, Y,\002,i2,\002) .\002)"; static char fmt_9995[] = "(1x,i6,\002: \002,a6,\002('\002,a1,\002',\002," "i3,\002,\002,f4.1,\002, AP\002,\002, X,\002,i2,\002,\002,f4.1" ",\002, Y,\002,i2,\002) .\002)"; static char fmt_9992[] = "(\002 ******* FATAL ERROR - ERROR-EXIT TAKEN O" "N VALID CALL *\002,\002******\002)"; static char fmt_9998[] = "(\002 ******* FATAL ERROR - PARAMETER NUMBER" " \002,i2,\002 WAS CH\002,\002ANGED INCORRECTLY *******\002)"; static char fmt_9999[] = "(\002 \002,a6,\002 PASSED THE COMPUTATIONAL TE" "STS (\002,i6,\002 CALL\002,\002S)\002)"; static char fmt_9997[] = "(\002 \002,a6,\002 COMPLETED THE COMPUTATIONAL" " TESTS (\002,i6,\002 C\002,\002ALLS)\002,/\002 ******* BUT WITH " "MAXIMUM TEST RATIO\002,f8.2,\002 - SUSPECT *******\002)"; static char fmt_9996[] = "(\002 ******* \002,a6,\002 FAILED ON CALL NUMB" "ER:\002)"; /* System generated locals */ integer a_dim1, a_offset, i__1, i__2, i__3, i__4, i__5, i__6, i__7, i__8; alist al__1; /* Builtin functions */ integer s_wsfe(cilist *), do_fio(integer *, char *, ftnlen), e_wsfe(void), f_rew(alist *); /* Local variables */ integer i__, k, n, ia, ib, ic, nc, ik, in, nk, ks, ix, iy, ns, lx, ly, laa, lda; extern logical lde_(doublereal *, doublereal *, integer *); doublereal als, bls, err, beta; integer ldas; logical same; integer incx, incy; logical full, null; char uplo[1]; extern /* Subroutine */ int dmake_(char *, char *, char *, integer *, integer *, doublereal *, integer *, doublereal *, integer *, integer *, integer *, logical *, doublereal *, ftnlen, ftnlen, ftnlen); doublereal alpha; logical isame[13]; extern /* Subroutine */ int dmvch_(char *, integer *, integer *, doublereal *, doublereal *, integer *, doublereal *, integer *, doublereal *, doublereal *, integer *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, logical *, integer *, logical *, ftnlen); integer nargs; extern /* Subroutine */ int dsbmv_(char *, integer *, integer *, doublereal *, doublereal *, integer *, doublereal *, integer *, doublereal *, doublereal *, integer *, ftnlen); logical reset; integer incxs, incys; extern /* Subroutine */ int dspmv_(char *, integer *, doublereal *, doublereal *, doublereal *, integer *, doublereal *, doublereal *, integer *, ftnlen); char uplos[1]; extern /* Subroutine */ int dsymv_(char *, integer *, doublereal *, doublereal *, integer *, doublereal *, integer *, doublereal *, doublereal *, integer *, ftnlen); logical banded, packed; extern logical lderes_(char *, char *, integer *, integer *, doublereal *, doublereal *, integer *, ftnlen, ftnlen); doublereal errmax, transl; /* Fortran I/O blocks */ static cilist io___189 = { 0, 0, 0, fmt_9993, 0 }; static cilist io___190 = { 0, 0, 0, fmt_9994, 0 }; static cilist io___191 = { 0, 0, 0, fmt_9995, 0 }; static cilist io___192 = { 0, 0, 0, fmt_9992, 0 }; static cilist io___195 = { 0, 0, 0, fmt_9998, 0 }; static cilist io___197 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___198 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___199 = { 0, 0, 0, fmt_9996, 0 }; static cilist io___200 = { 0, 0, 0, fmt_9993, 0 }; static cilist io___201 = { 0, 0, 0, fmt_9994, 0 }; static cilist io___202 = { 0, 0, 0, fmt_9995, 0 }; /* Tests DSYMV, DSBMV and DSPMV. */ /* Auxiliary routine for test program for Level 2 Blas. */ /* -- Written on 10-August-1987. */ /* Richard Hanson, Sandia National Labs. */ /* Jeremy Du Croz, NAG Central Office. */ /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Scalars .. */ /* .. Local Arrays .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. Scalars in Common .. */ /* .. Common blocks .. */ /* .. Data statements .. */ /* Parameter adjustments */ --idim; --kb; --alf; --bet; --inc; --g; --yt; --y; --x; --as; --aa; a_dim1 = *nmax; a_offset = 1 + a_dim1; a -= a_offset; --ys; --yy; --xs; --xx; /* Function Body */ /* .. Executable Statements .. */ full = *(unsigned char *)&sname[2] == 'Y'; banded = *(unsigned char *)&sname[2] == 'B'; packed = *(unsigned char *)&sname[2] == 'P'; /* Define the number of arguments. */ if (full) { nargs = 10; } else if (banded) { nargs = 11; } else if (packed) { nargs = 9; } nc = 0; reset = TRUE_; errmax = 0.; i__1 = *nidim; for (in = 1; in <= i__1; ++in) { n = idim[in]; if (banded) { nk = *nkb; } else { nk = 1; } i__2 = nk; for (ik = 1; ik <= i__2; ++ik) { if (banded) { k = kb[ik]; } else { k = n - 1; } /* Set LDA to 1 more than minimum value if room. */ if (banded) { lda = k + 1; } else { lda = n; } if (lda < *nmax) { ++lda; } /* Skip tests if not enough room. */ if (lda > *nmax) { goto L100; } if (packed) { laa = n * (n + 1) / 2; } else { laa = lda * n; } null = n <= 0; for (ic = 1; ic <= 2; ++ic) { *(unsigned char *)uplo = *(unsigned char *)&ich[ic - 1]; /* Generate the matrix A. */ transl = 0.; dmake_(sname + 1, uplo, " ", &n, &n, &a[a_offset], nmax, &aa[ 1], &lda, &k, &k, &reset, &transl, (ftnlen)2, (ftnlen) 1, (ftnlen)1); i__3 = *ninc; for (ix = 1; ix <= i__3; ++ix) { incx = inc[ix]; lx = abs(incx) * n; /* Generate the vector X. */ transl = .5; i__4 = abs(incx); i__5 = n - 1; dmake_("GE", " ", " ", &c__1, &n, &x[1], &c__1, &xx[1], & i__4, &c__0, &i__5, &reset, &transl, (ftnlen)2, ( ftnlen)1, (ftnlen)1); if (n > 1) { x[n / 2] = 0.; xx[abs(incx) * (n / 2 - 1) + 1] = 0.; } i__4 = *ninc; for (iy = 1; iy <= i__4; ++iy) { incy = inc[iy]; ly = abs(incy) * n; i__5 = *nalf; for (ia = 1; ia <= i__5; ++ia) { alpha = alf[ia]; i__6 = *nbet; for (ib = 1; ib <= i__6; ++ib) { beta = bet[ib]; /* Generate the vector Y. */ transl = 0.; i__7 = abs(incy); i__8 = n - 1; dmake_("GE", " ", " ", &c__1, &n, &y[1], & c__1, &yy[1], &i__7, &c__0, &i__8, & reset, &transl, (ftnlen)2, (ftnlen)1, (ftnlen)1); ++nc; /* Save every datum before calling the */ /* subroutine. */ *(unsigned char *)uplos = *(unsigned char *) uplo; ns = n; ks = k; als = alpha; i__7 = laa; for (i__ = 1; i__ <= i__7; ++i__) { as[i__] = aa[i__]; /* L10: */ } ldas = lda; i__7 = lx; for (i__ = 1; i__ <= i__7; ++i__) { xs[i__] = xx[i__]; /* L20: */ } incxs = incx; bls = beta; i__7 = ly; for (i__ = 1; i__ <= i__7; ++i__) { ys[i__] = yy[i__]; /* L30: */ } incys = incy; /* Call the subroutine. */ if (full) { if (*trace) { io___189.ciunit = *ntra; s_wsfe(&io___189); do_fio(&c__1, (char *)&nc, (ftnlen) sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&alpha, (ftnlen) sizeof(doublereal)); do_fio(&c__1, (char *)&lda, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&incx, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&beta, (ftnlen) sizeof(doublereal)); do_fio(&c__1, (char *)&incy, (ftnlen) sizeof(integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } dsymv_(uplo, &n, &alpha, &aa[1], &lda, & xx[1], &incx, &beta, &yy[1], & incy, (ftnlen)1); } else if (banded) { if (*trace) { io___190.ciunit = *ntra; s_wsfe(&io___190); do_fio(&c__1, (char *)&nc, (ftnlen) sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&k, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&alpha, (ftnlen) sizeof(doublereal)); do_fio(&c__1, (char *)&lda, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&incx, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&beta, (ftnlen) sizeof(doublereal)); do_fio(&c__1, (char *)&incy, (ftnlen) sizeof(integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } dsbmv_(uplo, &n, &k, &alpha, &aa[1], &lda, &xx[1], &incx, &beta, &yy[1], & incy, (ftnlen)1); } else if (packed) { if (*trace) { io___191.ciunit = *ntra; s_wsfe(&io___191); do_fio(&c__1, (char *)&nc, (ftnlen) sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&alpha, (ftnlen) sizeof(doublereal)); do_fio(&c__1, (char *)&incx, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&beta, (ftnlen) sizeof(doublereal)); do_fio(&c__1, (char *)&incy, (ftnlen) sizeof(integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } dspmv_(uplo, &n, &alpha, &aa[1], &xx[1], & incx, &beta, &yy[1], &incy, ( ftnlen)1); } /* Check if error-exit was taken incorrectly. */ if (! infoc_1.ok) { io___192.ciunit = *nout; s_wsfe(&io___192); e_wsfe(); *fatal = TRUE_; goto L120; } /* See what data changed inside subroutines. */ isame[0] = *(unsigned char *)uplo == *( unsigned char *)uplos; isame[1] = ns == n; if (full) { isame[2] = als == alpha; isame[3] = lde_(&as[1], &aa[1], &laa); isame[4] = ldas == lda; isame[5] = lde_(&xs[1], &xx[1], &lx); isame[6] = incxs == incx; isame[7] = bls == beta; if (null) { isame[8] = lde_(&ys[1], &yy[1], &ly); } else { i__7 = abs(incy); isame[8] = lderes_("GE", " ", &c__1, & n, &ys[1], &yy[1], &i__7, ( ftnlen)2, (ftnlen)1); } isame[9] = incys == incy; } else if (banded) { isame[2] = ks == k; isame[3] = als == alpha; isame[4] = lde_(&as[1], &aa[1], &laa); isame[5] = ldas == lda; isame[6] = lde_(&xs[1], &xx[1], &lx); isame[7] = incxs == incx; isame[8] = bls == beta; if (null) { isame[9] = lde_(&ys[1], &yy[1], &ly); } else { i__7 = abs(incy); isame[9] = lderes_("GE", " ", &c__1, & n, &ys[1], &yy[1], &i__7, ( ftnlen)2, (ftnlen)1); } isame[10] = incys == incy; } else if (packed) { isame[2] = als == alpha; isame[3] = lde_(&as[1], &aa[1], &laa); isame[4] = lde_(&xs[1], &xx[1], &lx); isame[5] = incxs == incx; isame[6] = bls == beta; if (null) { isame[7] = lde_(&ys[1], &yy[1], &ly); } else { i__7 = abs(incy); isame[7] = lderes_("GE", " ", &c__1, & n, &ys[1], &yy[1], &i__7, ( ftnlen)2, (ftnlen)1); } isame[8] = incys == incy; } /* If data was incorrectly changed, report and */ /* return. */ same = TRUE_; i__7 = nargs; for (i__ = 1; i__ <= i__7; ++i__) { same = same && isame[i__ - 1]; if (! isame[i__ - 1]) { io___195.ciunit = *nout; s_wsfe(&io___195); do_fio(&c__1, (char *)&i__, (ftnlen) sizeof(integer)); e_wsfe(); } /* L40: */ } if (! same) { *fatal = TRUE_; goto L120; } if (! null) { /* Check the result. */ dmvch_("N", &n, &n, &alpha, &a[a_offset], nmax, &x[1], &incx, &beta, &y[1], &incy, &yt[1], &g[1], &yy[1], eps, &err, fatal, nout, &c_true, ( ftnlen)1); errmax = max(errmax,err); /* If got really bad answer, report and */ /* return. */ if (*fatal) { goto L120; } } else { /* Avoid repeating tests with N.le.0 */ goto L110; } /* L50: */ } /* L60: */ } /* L70: */ } /* L80: */ } /* L90: */ } L100: ; } L110: ; } /* Report result. */ if (errmax < *thresh) { io___197.ciunit = *nout; s_wsfe(&io___197); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); e_wsfe(); } else { io___198.ciunit = *nout; s_wsfe(&io___198); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&errmax, (ftnlen)sizeof(doublereal)); e_wsfe(); } goto L130; L120: io___199.ciunit = *nout; s_wsfe(&io___199); do_fio(&c__1, sname, (ftnlen)6); e_wsfe(); if (full) { io___200.ciunit = *nout; s_wsfe(&io___200); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&alpha, (ftnlen)sizeof(doublereal)); do_fio(&c__1, (char *)&lda, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&incx, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&beta, (ftnlen)sizeof(doublereal)); do_fio(&c__1, (char *)&incy, (ftnlen)sizeof(integer)); e_wsfe(); } else if (banded) { io___201.ciunit = *nout; s_wsfe(&io___201); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&k, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&alpha, (ftnlen)sizeof(doublereal)); do_fio(&c__1, (char *)&lda, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&incx, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&beta, (ftnlen)sizeof(doublereal)); do_fio(&c__1, (char *)&incy, (ftnlen)sizeof(integer)); e_wsfe(); } else if (packed) { io___202.ciunit = *nout; s_wsfe(&io___202); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&alpha, (ftnlen)sizeof(doublereal)); do_fio(&c__1, (char *)&incx, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&beta, (ftnlen)sizeof(doublereal)); do_fio(&c__1, (char *)&incy, (ftnlen)sizeof(integer)); e_wsfe(); } L130: return 0; /* End of DCHK2. */ } /* dchk2_ */ /* Subroutine */ int dchk3_(char *sname, doublereal *eps, doublereal *thresh, integer *nout, integer *ntra, logical *trace, logical *rewi, logical * fatal, integer *nidim, integer *idim, integer *nkb, integer *kb, integer *ninc, integer *inc, integer *nmax, integer *incmax, doublereal *a, doublereal *aa, doublereal *as, doublereal *x, doublereal *xx, doublereal *xs, doublereal *xt, doublereal *g, doublereal *z__, ftnlen sname_len) { /* Initialized data */ static char ichu[2] = "UL"; static char icht[3] = "NTC"; static char ichd[2] = "UN"; /* Format strings */ static char fmt_9993[] = "(1x,i6,\002: \002,a6,\002(\002,3(\002'\002,a1" ",\002',\002),i3,\002, A,\002,i3,\002, X,\002,i2,\002) " " .\002)"; static char fmt_9994[] = "(1x,i6,\002: \002,a6,\002(\002,3(\002'\002,a1" ",\002',\002),2(i3,\002,\002),\002 A,\002,i3,\002, X,\002,i2,\002" ") .\002)"; static char fmt_9995[] = "(1x,i6,\002: \002,a6,\002(\002,3(\002'\002,a1" ",\002',\002),i3,\002, AP, \002,\002X,\002,i2,\002) " " .\002)"; static char fmt_9992[] = "(\002 ******* FATAL ERROR - ERROR-EXIT TAKEN O" "N VALID CALL *\002,\002******\002)"; static char fmt_9998[] = "(\002 ******* FATAL ERROR - PARAMETER NUMBER" " \002,i2,\002 WAS CH\002,\002ANGED INCORRECTLY *******\002)"; static char fmt_9999[] = "(\002 \002,a6,\002 PASSED THE COMPUTATIONAL TE" "STS (\002,i6,\002 CALL\002,\002S)\002)"; static char fmt_9997[] = "(\002 \002,a6,\002 COMPLETED THE COMPUTATIONAL" " TESTS (\002,i6,\002 C\002,\002ALLS)\002,/\002 ******* BUT WITH " "MAXIMUM TEST RATIO\002,f8.2,\002 - SUSPECT *******\002)"; static char fmt_9996[] = "(\002 ******* \002,a6,\002 FAILED ON CALL NUMB" "ER:\002)"; /* System generated locals */ integer a_dim1, a_offset, i__1, i__2, i__3, i__4, i__5; alist al__1; /* Builtin functions */ integer s_cmp(const char *, const char *, ftnlen, ftnlen), s_wsfe(cilist *), do_fio( integer *, char *, ftnlen), e_wsfe(void), f_rew(alist *); /* Local variables */ integer i__, k, n, nc, ik, in, nk, ks, ix, ns, lx, laa, icd, lda; extern logical lde_(doublereal *, doublereal *, integer *); integer ict, icu; doublereal err; char diag[1]; integer ldas; logical same; integer incx; logical full, null; char uplo[1]; extern /* Subroutine */ int dmake_(char *, char *, char *, integer *, integer *, doublereal *, integer *, doublereal *, integer *, integer *, integer *, logical *, doublereal *, ftnlen, ftnlen, ftnlen); char diags[1]; logical isame[13]; extern /* Subroutine */ int dmvch_(char *, integer *, integer *, doublereal *, doublereal *, integer *, doublereal *, integer *, doublereal *, doublereal *, integer *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, logical *, integer *, logical *, ftnlen); integer nargs; extern /* Subroutine */ int dtbmv_(char *, char *, char *, integer *, integer *, doublereal *, integer *, doublereal *, integer *, ftnlen, ftnlen, ftnlen); logical reset; extern /* Subroutine */ int dtbsv_(char *, char *, char *, integer *, integer *, doublereal *, integer *, doublereal *, integer *, ftnlen, ftnlen, ftnlen); integer incxs; char trans[1]; extern /* Subroutine */ int dtpmv_(char *, char *, char *, integer *, doublereal *, doublereal *, integer *, ftnlen, ftnlen, ftnlen), dtrmv_(char *, char *, char *, integer *, doublereal *, integer *, doublereal *, integer *, ftnlen, ftnlen, ftnlen), dtpsv_(char *, char *, char *, integer *, doublereal *, doublereal *, integer *, ftnlen, ftnlen, ftnlen); char uplos[1]; extern /* Subroutine */ int dtrsv_(char *, char *, char *, integer *, doublereal *, integer *, doublereal *, integer *, ftnlen, ftnlen, ftnlen); logical banded, packed; extern logical lderes_(char *, char *, integer *, integer *, doublereal *, doublereal *, integer *, ftnlen, ftnlen); doublereal errmax, transl; char transs[1]; /* Fortran I/O blocks */ static cilist io___239 = { 0, 0, 0, fmt_9993, 0 }; static cilist io___240 = { 0, 0, 0, fmt_9994, 0 }; static cilist io___241 = { 0, 0, 0, fmt_9995, 0 }; static cilist io___242 = { 0, 0, 0, fmt_9993, 0 }; static cilist io___243 = { 0, 0, 0, fmt_9994, 0 }; static cilist io___244 = { 0, 0, 0, fmt_9995, 0 }; static cilist io___245 = { 0, 0, 0, fmt_9992, 0 }; static cilist io___248 = { 0, 0, 0, fmt_9998, 0 }; static cilist io___250 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___251 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___252 = { 0, 0, 0, fmt_9996, 0 }; static cilist io___253 = { 0, 0, 0, fmt_9993, 0 }; static cilist io___254 = { 0, 0, 0, fmt_9994, 0 }; static cilist io___255 = { 0, 0, 0, fmt_9995, 0 }; /* Tests DTRMV, DTBMV, DTPMV, DTRSV, DTBSV and DTPSV. */ /* Auxiliary routine for test program for Level 2 Blas. */ /* -- Written on 10-August-1987. */ /* Richard Hanson, Sandia National Labs. */ /* Jeremy Du Croz, NAG Central Office. */ /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Scalars .. */ /* .. Local Arrays .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. Scalars in Common .. */ /* .. Common blocks .. */ /* .. Data statements .. */ /* Parameter adjustments */ --idim; --kb; --inc; --z__; --g; --xt; --x; --as; --aa; a_dim1 = *nmax; a_offset = 1 + a_dim1; a -= a_offset; --xs; --xx; /* Function Body */ /* .. Executable Statements .. */ full = *(unsigned char *)&sname[2] == 'R'; banded = *(unsigned char *)&sname[2] == 'B'; packed = *(unsigned char *)&sname[2] == 'P'; /* Define the number of arguments. */ if (full) { nargs = 8; } else if (banded) { nargs = 9; } else if (packed) { nargs = 7; } nc = 0; reset = TRUE_; errmax = 0.; /* Set up zero vector for DMVCH. */ i__1 = *nmax; for (i__ = 1; i__ <= i__1; ++i__) { z__[i__] = 0.; /* L10: */ } i__1 = *nidim; for (in = 1; in <= i__1; ++in) { n = idim[in]; if (banded) { nk = *nkb; } else { nk = 1; } i__2 = nk; for (ik = 1; ik <= i__2; ++ik) { if (banded) { k = kb[ik]; } else { k = n - 1; } /* Set LDA to 1 more than minimum value if room. */ if (banded) { lda = k + 1; } else { lda = n; } if (lda < *nmax) { ++lda; } /* Skip tests if not enough room. */ if (lda > *nmax) { goto L100; } if (packed) { laa = n * (n + 1) / 2; } else { laa = lda * n; } null = n <= 0; for (icu = 1; icu <= 2; ++icu) { *(unsigned char *)uplo = *(unsigned char *)&ichu[icu - 1]; for (ict = 1; ict <= 3; ++ict) { *(unsigned char *)trans = *(unsigned char *)&icht[ict - 1] ; for (icd = 1; icd <= 2; ++icd) { *(unsigned char *)diag = *(unsigned char *)&ichd[icd - 1]; /* Generate the matrix A. */ transl = 0.; dmake_(sname + 1, uplo, diag, &n, &n, &a[a_offset], nmax, &aa[1], &lda, &k, &k, &reset, &transl, ( ftnlen)2, (ftnlen)1, (ftnlen)1); i__3 = *ninc; for (ix = 1; ix <= i__3; ++ix) { incx = inc[ix]; lx = abs(incx) * n; /* Generate the vector X. */ transl = .5; i__4 = abs(incx); i__5 = n - 1; dmake_("GE", " ", " ", &c__1, &n, &x[1], &c__1, & xx[1], &i__4, &c__0, &i__5, &reset, & transl, (ftnlen)2, (ftnlen)1, (ftnlen)1); if (n > 1) { x[n / 2] = 0.; xx[abs(incx) * (n / 2 - 1) + 1] = 0.; } ++nc; /* Save every datum before calling the subroutine. */ *(unsigned char *)uplos = *(unsigned char *)uplo; *(unsigned char *)transs = *(unsigned char *) trans; *(unsigned char *)diags = *(unsigned char *)diag; ns = n; ks = k; i__4 = laa; for (i__ = 1; i__ <= i__4; ++i__) { as[i__] = aa[i__]; /* L20: */ } ldas = lda; i__4 = lx; for (i__ = 1; i__ <= i__4; ++i__) { xs[i__] = xx[i__]; /* L30: */ } incxs = incx; /* Call the subroutine. */ if (s_cmp(sname + 3, "MV", (ftnlen)2, (ftnlen)2) == 0) { if (full) { if (*trace) { io___239.ciunit = *ntra; s_wsfe(&io___239); do_fio(&c__1, (char *)&nc, (ftnlen) sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, diag, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&lda, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&incx, (ftnlen) sizeof(integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } dtrmv_(uplo, trans, diag, &n, &aa[1], & lda, &xx[1], &incx, (ftnlen)1, ( ftnlen)1, (ftnlen)1); } else if (banded) { if (*trace) { io___240.ciunit = *ntra; s_wsfe(&io___240); do_fio(&c__1, (char *)&nc, (ftnlen) sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, diag, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&k, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&lda, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&incx, (ftnlen) sizeof(integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } dtbmv_(uplo, trans, diag, &n, &k, &aa[1], &lda, &xx[1], &incx, (ftnlen)1, ( ftnlen)1, (ftnlen)1); } else if (packed) { if (*trace) { io___241.ciunit = *ntra; s_wsfe(&io___241); do_fio(&c__1, (char *)&nc, (ftnlen) sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, diag, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&incx, (ftnlen) sizeof(integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } dtpmv_(uplo, trans, diag, &n, &aa[1], &xx[ 1], &incx, (ftnlen)1, (ftnlen)1, ( ftnlen)1); } } else if (s_cmp(sname + 3, "SV", (ftnlen)2, ( ftnlen)2) == 0) { if (full) { if (*trace) { io___242.ciunit = *ntra; s_wsfe(&io___242); do_fio(&c__1, (char *)&nc, (ftnlen) sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, diag, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&lda, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&incx, (ftnlen) sizeof(integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } dtrsv_(uplo, trans, diag, &n, &aa[1], & lda, &xx[1], &incx, (ftnlen)1, ( ftnlen)1, (ftnlen)1); } else if (banded) { if (*trace) { io___243.ciunit = *ntra; s_wsfe(&io___243); do_fio(&c__1, (char *)&nc, (ftnlen) sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, diag, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&k, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&lda, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&incx, (ftnlen) sizeof(integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } dtbsv_(uplo, trans, diag, &n, &k, &aa[1], &lda, &xx[1], &incx, (ftnlen)1, ( ftnlen)1, (ftnlen)1); } else if (packed) { if (*trace) { io___244.ciunit = *ntra; s_wsfe(&io___244); do_fio(&c__1, (char *)&nc, (ftnlen) sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, diag, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&incx, (ftnlen) sizeof(integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } dtpsv_(uplo, trans, diag, &n, &aa[1], &xx[ 1], &incx, (ftnlen)1, (ftnlen)1, ( ftnlen)1); } } /* Check if error-exit was taken incorrectly. */ if (! infoc_1.ok) { io___245.ciunit = *nout; s_wsfe(&io___245); e_wsfe(); *fatal = TRUE_; goto L120; } /* See what data changed inside subroutines. */ isame[0] = *(unsigned char *)uplo == *(unsigned char *)uplos; isame[1] = *(unsigned char *)trans == *(unsigned char *)transs; isame[2] = *(unsigned char *)diag == *(unsigned char *)diags; isame[3] = ns == n; if (full) { isame[4] = lde_(&as[1], &aa[1], &laa); isame[5] = ldas == lda; if (null) { isame[6] = lde_(&xs[1], &xx[1], &lx); } else { i__4 = abs(incx); isame[6] = lderes_("GE", " ", &c__1, &n, & xs[1], &xx[1], &i__4, (ftnlen)2, ( ftnlen)1); } isame[7] = incxs == incx; } else if (banded) { isame[4] = ks == k; isame[5] = lde_(&as[1], &aa[1], &laa); isame[6] = ldas == lda; if (null) { isame[7] = lde_(&xs[1], &xx[1], &lx); } else { i__4 = abs(incx); isame[7] = lderes_("GE", " ", &c__1, &n, & xs[1], &xx[1], &i__4, (ftnlen)2, ( ftnlen)1); } isame[8] = incxs == incx; } else if (packed) { isame[4] = lde_(&as[1], &aa[1], &laa); if (null) { isame[5] = lde_(&xs[1], &xx[1], &lx); } else { i__4 = abs(incx); isame[5] = lderes_("GE", " ", &c__1, &n, & xs[1], &xx[1], &i__4, (ftnlen)2, ( ftnlen)1); } isame[6] = incxs == incx; } /* If data was incorrectly changed, report and */ /* return. */ same = TRUE_; i__4 = nargs; for (i__ = 1; i__ <= i__4; ++i__) { same = same && isame[i__ - 1]; if (! isame[i__ - 1]) { io___248.ciunit = *nout; s_wsfe(&io___248); do_fio(&c__1, (char *)&i__, (ftnlen) sizeof(integer)); e_wsfe(); } /* L40: */ } if (! same) { *fatal = TRUE_; goto L120; } if (! null) { if (s_cmp(sname + 3, "MV", (ftnlen)2, (ftnlen) 2) == 0) { /* Check the result. */ dmvch_(trans, &n, &n, &c_b128, &a[ a_offset], nmax, &x[1], &incx, & c_b120, &z__[1], &incx, &xt[1], & g[1], &xx[1], eps, &err, fatal, nout, &c_true, (ftnlen)1); } else if (s_cmp(sname + 3, "SV", (ftnlen)2, ( ftnlen)2) == 0) { /* Compute approximation to original vector. */ i__4 = n; for (i__ = 1; i__ <= i__4; ++i__) { z__[i__] = xx[(i__ - 1) * abs(incx) + 1]; xx[(i__ - 1) * abs(incx) + 1] = x[i__] ; /* L50: */ } dmvch_(trans, &n, &n, &c_b128, &a[ a_offset], nmax, &z__[1], &incx, & c_b120, &x[1], &incx, &xt[1], &g[ 1], &xx[1], eps, &err, fatal, nout, &c_false, (ftnlen)1); } errmax = max(errmax,err); /* If got really bad answer, report and return. */ if (*fatal) { goto L120; } } else { /* Avoid repeating tests with N.le.0. */ goto L110; } /* L60: */ } /* L70: */ } /* L80: */ } /* L90: */ } L100: ; } L110: ; } /* Report result. */ if (errmax < *thresh) { io___250.ciunit = *nout; s_wsfe(&io___250); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); e_wsfe(); } else { io___251.ciunit = *nout; s_wsfe(&io___251); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&errmax, (ftnlen)sizeof(doublereal)); e_wsfe(); } goto L130; L120: io___252.ciunit = *nout; s_wsfe(&io___252); do_fio(&c__1, sname, (ftnlen)6); e_wsfe(); if (full) { io___253.ciunit = *nout; s_wsfe(&io___253); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, diag, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&lda, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&incx, (ftnlen)sizeof(integer)); e_wsfe(); } else if (banded) { io___254.ciunit = *nout; s_wsfe(&io___254); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, diag, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&k, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&lda, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&incx, (ftnlen)sizeof(integer)); e_wsfe(); } else if (packed) { io___255.ciunit = *nout; s_wsfe(&io___255); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, diag, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&incx, (ftnlen)sizeof(integer)); e_wsfe(); } L130: return 0; /* End of DCHK3. */ } /* dchk3_ */ /* Subroutine */ int dchk4_(char *sname, doublereal *eps, doublereal *thresh, integer *nout, integer *ntra, logical *trace, logical *rewi, logical * fatal, integer *nidim, integer *idim, integer *nalf, doublereal *alf, integer *ninc, integer *inc, integer *nmax, integer *incmax, doublereal *a, doublereal *aa, doublereal *as, doublereal *x, doublereal *xx, doublereal *xs, doublereal *y, doublereal *yy, doublereal *ys, doublereal *yt, doublereal *g, doublereal *z__, ftnlen sname_len) { /* Format strings */ static char fmt_9994[] = "(1x,i6,\002: \002,a6,\002(\002,2(i3,\002,\002)" ",f4.1,\002, X,\002,i2,\002, Y,\002,i2,\002, A,\002,i3,\002) " " .\002)"; static char fmt_9993[] = "(\002 ******* FATAL ERROR - ERROR-EXIT TAKEN O" "N VALID CALL *\002,\002******\002)"; static char fmt_9998[] = "(\002 ******* FATAL ERROR - PARAMETER NUMBER" " \002,i2,\002 WAS CH\002,\002ANGED INCORRECTLY *******\002)"; static char fmt_9999[] = "(\002 \002,a6,\002 PASSED THE COMPUTATIONAL TE" "STS (\002,i6,\002 CALL\002,\002S)\002)"; static char fmt_9997[] = "(\002 \002,a6,\002 COMPLETED THE COMPUTATIONAL" " TESTS (\002,i6,\002 C\002,\002ALLS)\002,/\002 ******* BUT WITH " "MAXIMUM TEST RATIO\002,f8.2,\002 - SUSPECT *******\002)"; static char fmt_9995[] = "(\002 THESE ARE THE RESULTS FOR COLUMN" " \002,i3)"; static char fmt_9996[] = "(\002 ******* \002,a6,\002 FAILED ON CALL NUMB" "ER:\002)"; /* System generated locals */ integer a_dim1, a_offset, i__1, i__2, i__3, i__4, i__5, i__6; alist al__1; /* Builtin functions */ integer s_wsfe(cilist *), do_fio(integer *, char *, ftnlen), e_wsfe(void), f_rew(alist *); /* Local variables */ integer i__, j, m, n; doublereal w[1]; integer ia, nc, nd, im, in, ms, ix, iy, ns, lx, ly, laa, lda; extern logical lde_(doublereal *, doublereal *, integer *); doublereal als, err; extern /* Subroutine */ int dger_(integer *, integer *, doublereal *, doublereal *, integer *, doublereal *, integer *, doublereal *, integer *); integer ldas; logical same; integer incx, incy; logical null; extern /* Subroutine */ int dmake_(char *, char *, char *, integer *, integer *, doublereal *, integer *, doublereal *, integer *, integer *, integer *, logical *, doublereal *, ftnlen, ftnlen, ftnlen); doublereal alpha; logical isame[13]; extern /* Subroutine */ int dmvch_(char *, integer *, integer *, doublereal *, doublereal *, integer *, doublereal *, integer *, doublereal *, doublereal *, integer *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, logical *, integer *, logical *, ftnlen); integer nargs; logical reset; integer incxs, incys; extern logical lderes_(char *, char *, integer *, integer *, doublereal *, doublereal *, integer *, ftnlen, ftnlen); doublereal errmax, transl; /* Fortran I/O blocks */ static cilist io___284 = { 0, 0, 0, fmt_9994, 0 }; static cilist io___285 = { 0, 0, 0, fmt_9993, 0 }; static cilist io___288 = { 0, 0, 0, fmt_9998, 0 }; static cilist io___292 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___293 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___294 = { 0, 0, 0, fmt_9995, 0 }; static cilist io___295 = { 0, 0, 0, fmt_9996, 0 }; static cilist io___296 = { 0, 0, 0, fmt_9994, 0 }; /* Tests DGER. */ /* Auxiliary routine for test program for Level 2 Blas. */ /* -- Written on 10-August-1987. */ /* Richard Hanson, Sandia National Labs. */ /* Jeremy Du Croz, NAG Central Office. */ /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Scalars .. */ /* .. Local Arrays .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. Scalars in Common .. */ /* .. Common blocks .. */ /* .. Executable Statements .. */ /* Define the number of arguments. */ /* Parameter adjustments */ --idim; --alf; --inc; --z__; --g; --yt; --y; --x; --as; --aa; a_dim1 = *nmax; a_offset = 1 + a_dim1; a -= a_offset; --ys; --yy; --xs; --xx; /* Function Body */ nargs = 9; nc = 0; reset = TRUE_; errmax = 0.; i__1 = *nidim; for (in = 1; in <= i__1; ++in) { n = idim[in]; nd = n / 2 + 1; for (im = 1; im <= 2; ++im) { if (im == 1) { /* Computing MAX */ i__2 = n - nd; m = max(i__2,0); } if (im == 2) { /* Computing MIN */ i__2 = n + nd; m = min(i__2,*nmax); } /* Set LDA to 1 more than minimum value if room. */ lda = m; if (lda < *nmax) { ++lda; } /* Skip tests if not enough room. */ if (lda > *nmax) { goto L110; } laa = lda * n; null = n <= 0 || m <= 0; i__2 = *ninc; for (ix = 1; ix <= i__2; ++ix) { incx = inc[ix]; lx = abs(incx) * m; /* Generate the vector X. */ transl = .5; i__3 = abs(incx); i__4 = m - 1; dmake_("GE", " ", " ", &c__1, &m, &x[1], &c__1, &xx[1], &i__3, &c__0, &i__4, &reset, &transl, (ftnlen)2, (ftnlen)1, (ftnlen)1); if (m > 1) { x[m / 2] = 0.; xx[abs(incx) * (m / 2 - 1) + 1] = 0.; } i__3 = *ninc; for (iy = 1; iy <= i__3; ++iy) { incy = inc[iy]; ly = abs(incy) * n; /* Generate the vector Y. */ transl = 0.; i__4 = abs(incy); i__5 = n - 1; dmake_("GE", " ", " ", &c__1, &n, &y[1], &c__1, &yy[1], & i__4, &c__0, &i__5, &reset, &transl, (ftnlen)2, ( ftnlen)1, (ftnlen)1); if (n > 1) { y[n / 2] = 0.; yy[abs(incy) * (n / 2 - 1) + 1] = 0.; } i__4 = *nalf; for (ia = 1; ia <= i__4; ++ia) { alpha = alf[ia]; /* Generate the matrix A. */ transl = 0.; i__5 = m - 1; i__6 = n - 1; dmake_(sname + 1, " ", " ", &m, &n, &a[a_offset], nmax, &aa[1], &lda, &i__5, &i__6, &reset, & transl, (ftnlen)2, (ftnlen)1, (ftnlen)1); ++nc; /* Save every datum before calling the subroutine. */ ms = m; ns = n; als = alpha; i__5 = laa; for (i__ = 1; i__ <= i__5; ++i__) { as[i__] = aa[i__]; /* L10: */ } ldas = lda; i__5 = lx; for (i__ = 1; i__ <= i__5; ++i__) { xs[i__] = xx[i__]; /* L20: */ } incxs = incx; i__5 = ly; for (i__ = 1; i__ <= i__5; ++i__) { ys[i__] = yy[i__]; /* L30: */ } incys = incy; /* Call the subroutine. */ if (*trace) { io___284.ciunit = *ntra; s_wsfe(&io___284); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer) ); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&m, (ftnlen)sizeof(integer)) ; do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)) ; do_fio(&c__1, (char *)&alpha, (ftnlen)sizeof( doublereal)); do_fio(&c__1, (char *)&incx, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&incy, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&lda, (ftnlen)sizeof( integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } dger_(&m, &n, &alpha, &xx[1], &incx, &yy[1], &incy, & aa[1], &lda); /* Check if error-exit was taken incorrectly. */ if (! infoc_1.ok) { io___285.ciunit = *nout; s_wsfe(&io___285); e_wsfe(); *fatal = TRUE_; goto L140; } /* See what data changed inside subroutine. */ isame[0] = ms == m; isame[1] = ns == n; isame[2] = als == alpha; isame[3] = lde_(&xs[1], &xx[1], &lx); isame[4] = incxs == incx; isame[5] = lde_(&ys[1], &yy[1], &ly); isame[6] = incys == incy; if (null) { isame[7] = lde_(&as[1], &aa[1], &laa); } else { isame[7] = lderes_("GE", " ", &m, &n, &as[1], &aa[ 1], &lda, (ftnlen)2, (ftnlen)1); } isame[8] = ldas == lda; /* If data was incorrectly changed, report and return. */ same = TRUE_; i__5 = nargs; for (i__ = 1; i__ <= i__5; ++i__) { same = same && isame[i__ - 1]; if (! isame[i__ - 1]) { io___288.ciunit = *nout; s_wsfe(&io___288); do_fio(&c__1, (char *)&i__, (ftnlen)sizeof( integer)); e_wsfe(); } /* L40: */ } if (! same) { *fatal = TRUE_; goto L140; } if (! null) { /* Check the result column by column. */ if (incx > 0) { i__5 = m; for (i__ = 1; i__ <= i__5; ++i__) { z__[i__] = x[i__]; /* L50: */ } } else { i__5 = m; for (i__ = 1; i__ <= i__5; ++i__) { z__[i__] = x[m - i__ + 1]; /* L60: */ } } i__5 = n; for (j = 1; j <= i__5; ++j) { if (incy > 0) { w[0] = y[j]; } else { w[0] = y[n - j + 1]; } dmvch_("N", &m, &c__1, &alpha, &z__[1], nmax, w, &c__1, &c_b128, &a[j * a_dim1 + 1], &c__1, &yt[1], &g[1], &aa[(j - 1) * lda + 1], eps, &err, fatal, nout, & c_true, (ftnlen)1); errmax = max(errmax,err); /* If got really bad answer, report and return. */ if (*fatal) { goto L130; } /* L70: */ } } else { /* Avoid repeating tests with M.le.0 or N.le.0. */ goto L110; } /* L80: */ } /* L90: */ } /* L100: */ } L110: ; } /* L120: */ } /* Report result. */ if (errmax < *thresh) { io___292.ciunit = *nout; s_wsfe(&io___292); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); e_wsfe(); } else { io___293.ciunit = *nout; s_wsfe(&io___293); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&errmax, (ftnlen)sizeof(doublereal)); e_wsfe(); } goto L150; L130: io___294.ciunit = *nout; s_wsfe(&io___294); do_fio(&c__1, (char *)&j, (ftnlen)sizeof(integer)); e_wsfe(); L140: io___295.ciunit = *nout; s_wsfe(&io___295); do_fio(&c__1, sname, (ftnlen)6); e_wsfe(); io___296.ciunit = *nout; s_wsfe(&io___296); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&m, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&alpha, (ftnlen)sizeof(doublereal)); do_fio(&c__1, (char *)&incx, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&incy, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&lda, (ftnlen)sizeof(integer)); e_wsfe(); L150: return 0; /* End of DCHK4. */ } /* dchk4_ */ /* Subroutine */ int dchk5_(char *sname, doublereal *eps, doublereal *thresh, integer *nout, integer *ntra, logical *trace, logical *rewi, logical * fatal, integer *nidim, integer *idim, integer *nalf, doublereal *alf, integer *ninc, integer *inc, integer *nmax, integer *incmax, doublereal *a, doublereal *aa, doublereal *as, doublereal *x, doublereal *xx, doublereal *xs, doublereal *y, doublereal *yy, doublereal *ys, doublereal *yt, doublereal *g, doublereal *z__, ftnlen sname_len) { /* Initialized data */ static char ich[2] = "UL"; /* Format strings */ static char fmt_9993[] = "(1x,i6,\002: \002,a6,\002('\002,a1,\002',\002," "i3,\002,\002,f4.1,\002, X,\002,i2,\002, A,\002,i3,\002) " " .\002)"; static char fmt_9994[] = "(1x,i6,\002: \002,a6,\002('\002,a1,\002',\002," "i3,\002,\002,f4.1,\002, X,\002,i2,\002, AP) " " .\002)"; static char fmt_9992[] = "(\002 ******* FATAL ERROR - ERROR-EXIT TAKEN O" "N VALID CALL *\002,\002******\002)"; static char fmt_9998[] = "(\002 ******* FATAL ERROR - PARAMETER NUMBER" " \002,i2,\002 WAS CH\002,\002ANGED INCORRECTLY *******\002)"; static char fmt_9999[] = "(\002 \002,a6,\002 PASSED THE COMPUTATIONAL TE" "STS (\002,i6,\002 CALL\002,\002S)\002)"; static char fmt_9997[] = "(\002 \002,a6,\002 COMPLETED THE COMPUTATIONAL" " TESTS (\002,i6,\002 C\002,\002ALLS)\002,/\002 ******* BUT WITH " "MAXIMUM TEST RATIO\002,f8.2,\002 - SUSPECT *******\002)"; static char fmt_9995[] = "(\002 THESE ARE THE RESULTS FOR COLUMN" " \002,i3)"; static char fmt_9996[] = "(\002 ******* \002,a6,\002 FAILED ON CALL NUMB" "ER:\002)"; /* System generated locals */ integer a_dim1, a_offset, i__1, i__2, i__3, i__4, i__5; alist al__1; /* Builtin functions */ integer s_wsfe(cilist *), do_fio(integer *, char *, ftnlen), e_wsfe(void), f_rew(alist *); /* Local variables */ integer i__, j, n; doublereal w[1]; integer ia, ja, ic, nc, jj, lj, in, ix, ns, lx, laa, lda; extern logical lde_(doublereal *, doublereal *, integer *); doublereal als, err; integer ldas; logical same; integer incx; logical full; extern /* Subroutine */ int dspr_(char *, integer *, doublereal *, doublereal *, integer *, doublereal *, ftnlen); logical null; char uplo[1]; extern /* Subroutine */ int dsyr_(char *, integer *, doublereal *, doublereal *, integer *, doublereal *, integer *, ftnlen), dmake_( char *, char *, char *, integer *, integer *, doublereal *, integer *, doublereal *, integer *, integer *, integer *, logical *, doublereal *, ftnlen, ftnlen, ftnlen); doublereal alpha; logical isame[13]; extern /* Subroutine */ int dmvch_(char *, integer *, integer *, doublereal *, doublereal *, integer *, doublereal *, integer *, doublereal *, doublereal *, integer *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, logical *, integer *, logical *, ftnlen); integer nargs; logical reset; integer incxs; logical upper; char uplos[1]; logical packed; extern logical lderes_(char *, char *, integer *, integer *, doublereal *, doublereal *, integer *, ftnlen, ftnlen); doublereal errmax, transl; /* Fortran I/O blocks */ static cilist io___324 = { 0, 0, 0, fmt_9993, 0 }; static cilist io___325 = { 0, 0, 0, fmt_9994, 0 }; static cilist io___326 = { 0, 0, 0, fmt_9992, 0 }; static cilist io___329 = { 0, 0, 0, fmt_9998, 0 }; static cilist io___336 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___337 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___338 = { 0, 0, 0, fmt_9995, 0 }; static cilist io___339 = { 0, 0, 0, fmt_9996, 0 }; static cilist io___340 = { 0, 0, 0, fmt_9993, 0 }; static cilist io___341 = { 0, 0, 0, fmt_9994, 0 }; /* Tests DSYR and DSPR. */ /* Auxiliary routine for test program for Level 2 Blas. */ /* -- Written on 10-August-1987. */ /* Richard Hanson, Sandia National Labs. */ /* Jeremy Du Croz, NAG Central Office. */ /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Scalars .. */ /* .. Local Arrays .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. Scalars in Common .. */ /* .. Common blocks .. */ /* .. Data statements .. */ /* Parameter adjustments */ --idim; --alf; --inc; --z__; --g; --yt; --y; --x; --as; --aa; a_dim1 = *nmax; a_offset = 1 + a_dim1; a -= a_offset; --ys; --yy; --xs; --xx; /* Function Body */ /* .. Executable Statements .. */ full = *(unsigned char *)&sname[2] == 'Y'; packed = *(unsigned char *)&sname[2] == 'P'; /* Define the number of arguments. */ if (full) { nargs = 7; } else if (packed) { nargs = 6; } nc = 0; reset = TRUE_; errmax = 0.; i__1 = *nidim; for (in = 1; in <= i__1; ++in) { n = idim[in]; /* Set LDA to 1 more than minimum value if room. */ lda = n; if (lda < *nmax) { ++lda; } /* Skip tests if not enough room. */ if (lda > *nmax) { goto L100; } if (packed) { laa = n * (n + 1) / 2; } else { laa = lda * n; } for (ic = 1; ic <= 2; ++ic) { *(unsigned char *)uplo = *(unsigned char *)&ich[ic - 1]; upper = *(unsigned char *)uplo == 'U'; i__2 = *ninc; for (ix = 1; ix <= i__2; ++ix) { incx = inc[ix]; lx = abs(incx) * n; /* Generate the vector X. */ transl = .5; i__3 = abs(incx); i__4 = n - 1; dmake_("GE", " ", " ", &c__1, &n, &x[1], &c__1, &xx[1], &i__3, &c__0, &i__4, &reset, &transl, (ftnlen)2, (ftnlen)1, (ftnlen)1); if (n > 1) { x[n / 2] = 0.; xx[abs(incx) * (n / 2 - 1) + 1] = 0.; } i__3 = *nalf; for (ia = 1; ia <= i__3; ++ia) { alpha = alf[ia]; null = n <= 0 || alpha == 0.; /* Generate the matrix A. */ transl = 0.; i__4 = n - 1; i__5 = n - 1; dmake_(sname + 1, uplo, " ", &n, &n, &a[a_offset], nmax, & aa[1], &lda, &i__4, &i__5, &reset, &transl, ( ftnlen)2, (ftnlen)1, (ftnlen)1); ++nc; /* Save every datum before calling the subroutine. */ *(unsigned char *)uplos = *(unsigned char *)uplo; ns = n; als = alpha; i__4 = laa; for (i__ = 1; i__ <= i__4; ++i__) { as[i__] = aa[i__]; /* L10: */ } ldas = lda; i__4 = lx; for (i__ = 1; i__ <= i__4; ++i__) { xs[i__] = xx[i__]; /* L20: */ } incxs = incx; /* Call the subroutine. */ if (full) { if (*trace) { io___324.ciunit = *ntra; s_wsfe(&io___324); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer) ); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)) ; do_fio(&c__1, (char *)&alpha, (ftnlen)sizeof( doublereal)); do_fio(&c__1, (char *)&incx, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&lda, (ftnlen)sizeof( integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } dsyr_(uplo, &n, &alpha, &xx[1], &incx, &aa[1], &lda, ( ftnlen)1); } else if (packed) { if (*trace) { io___325.ciunit = *ntra; s_wsfe(&io___325); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer) ); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)) ; do_fio(&c__1, (char *)&alpha, (ftnlen)sizeof( doublereal)); do_fio(&c__1, (char *)&incx, (ftnlen)sizeof( integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } dspr_(uplo, &n, &alpha, &xx[1], &incx, &aa[1], ( ftnlen)1); } /* Check if error-exit was taken incorrectly. */ if (! infoc_1.ok) { io___326.ciunit = *nout; s_wsfe(&io___326); e_wsfe(); *fatal = TRUE_; goto L120; } /* See what data changed inside subroutines. */ isame[0] = *(unsigned char *)uplo == *(unsigned char *) uplos; isame[1] = ns == n; isame[2] = als == alpha; isame[3] = lde_(&xs[1], &xx[1], &lx); isame[4] = incxs == incx; if (null) { isame[5] = lde_(&as[1], &aa[1], &laa); } else { isame[5] = lderes_(sname + 1, uplo, &n, &n, &as[1], & aa[1], &lda, (ftnlen)2, (ftnlen)1); } if (! packed) { isame[6] = ldas == lda; } /* If data was incorrectly changed, report and return. */ same = TRUE_; i__4 = nargs; for (i__ = 1; i__ <= i__4; ++i__) { same = same && isame[i__ - 1]; if (! isame[i__ - 1]) { io___329.ciunit = *nout; s_wsfe(&io___329); do_fio(&c__1, (char *)&i__, (ftnlen)sizeof( integer)); e_wsfe(); } /* L30: */ } if (! same) { *fatal = TRUE_; goto L120; } if (! null) { /* Check the result column by column. */ if (incx > 0) { i__4 = n; for (i__ = 1; i__ <= i__4; ++i__) { z__[i__] = x[i__]; /* L40: */ } } else { i__4 = n; for (i__ = 1; i__ <= i__4; ++i__) { z__[i__] = x[n - i__ + 1]; /* L50: */ } } ja = 1; i__4 = n; for (j = 1; j <= i__4; ++j) { w[0] = z__[j]; if (upper) { jj = 1; lj = j; } else { jj = j; lj = n - j + 1; } dmvch_("N", &lj, &c__1, &alpha, &z__[jj], &lj, w, &c__1, &c_b128, &a[jj + j * a_dim1], & c__1, &yt[1], &g[1], &aa[ja], eps, &err, fatal, nout, &c_true, (ftnlen)1); if (full) { if (upper) { ja += lda; } else { ja = ja + lda + 1; } } else { ja += lj; } errmax = max(errmax,err); /* If got really bad answer, report and return. */ if (*fatal) { goto L110; } /* L60: */ } } else { /* Avoid repeating tests if N.le.0. */ if (n <= 0) { goto L100; } } /* L70: */ } /* L80: */ } /* L90: */ } L100: ; } /* Report result. */ if (errmax < *thresh) { io___336.ciunit = *nout; s_wsfe(&io___336); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); e_wsfe(); } else { io___337.ciunit = *nout; s_wsfe(&io___337); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&errmax, (ftnlen)sizeof(doublereal)); e_wsfe(); } goto L130; L110: io___338.ciunit = *nout; s_wsfe(&io___338); do_fio(&c__1, (char *)&j, (ftnlen)sizeof(integer)); e_wsfe(); L120: io___339.ciunit = *nout; s_wsfe(&io___339); do_fio(&c__1, sname, (ftnlen)6); e_wsfe(); if (full) { io___340.ciunit = *nout; s_wsfe(&io___340); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&alpha, (ftnlen)sizeof(doublereal)); do_fio(&c__1, (char *)&incx, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&lda, (ftnlen)sizeof(integer)); e_wsfe(); } else if (packed) { io___341.ciunit = *nout; s_wsfe(&io___341); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&alpha, (ftnlen)sizeof(doublereal)); do_fio(&c__1, (char *)&incx, (ftnlen)sizeof(integer)); e_wsfe(); } L130: return 0; /* End of DCHK5. */ } /* dchk5_ */ /* Subroutine */ int dchk6_(char *sname, doublereal *eps, doublereal *thresh, integer *nout, integer *ntra, logical *trace, logical *rewi, logical * fatal, integer *nidim, integer *idim, integer *nalf, doublereal *alf, integer *ninc, integer *inc, integer *nmax, integer *incmax, doublereal *a, doublereal *aa, doublereal *as, doublereal *x, doublereal *xx, doublereal *xs, doublereal *y, doublereal *yy, doublereal *ys, doublereal *yt, doublereal *g, doublereal *z__, ftnlen sname_len) { /* Initialized data */ static char ich[2] = "UL"; /* Format strings */ static char fmt_9993[] = "(1x,i6,\002: \002,a6,\002('\002,a1,\002',\002," "i3,\002,\002,f4.1,\002, X,\002,i2,\002, Y,\002,i2,\002, A,\002,i" "3,\002) .\002)"; static char fmt_9994[] = "(1x,i6,\002: \002,a6,\002('\002,a1,\002',\002," "i3,\002,\002,f4.1,\002, X,\002,i2,\002, Y,\002,i2,\002, AP) " " .\002)"; static char fmt_9992[] = "(\002 ******* FATAL ERROR - ERROR-EXIT TAKEN O" "N VALID CALL *\002,\002******\002)"; static char fmt_9998[] = "(\002 ******* FATAL ERROR - PARAMETER NUMBER" " \002,i2,\002 WAS CH\002,\002ANGED INCORRECTLY *******\002)"; static char fmt_9999[] = "(\002 \002,a6,\002 PASSED THE COMPUTATIONAL TE" "STS (\002,i6,\002 CALL\002,\002S)\002)"; static char fmt_9997[] = "(\002 \002,a6,\002 COMPLETED THE COMPUTATIONAL" " TESTS (\002,i6,\002 C\002,\002ALLS)\002,/\002 ******* BUT WITH " "MAXIMUM TEST RATIO\002,f8.2,\002 - SUSPECT *******\002)"; static char fmt_9995[] = "(\002 THESE ARE THE RESULTS FOR COLUMN" " \002,i3)"; static char fmt_9996[] = "(\002 ******* \002,a6,\002 FAILED ON CALL NUMB" "ER:\002)"; /* System generated locals */ integer a_dim1, a_offset, z_dim1, z_offset, i__1, i__2, i__3, i__4, i__5, i__6; alist al__1; /* Builtin functions */ integer s_wsfe(cilist *), do_fio(integer *, char *, ftnlen), e_wsfe(void), f_rew(alist *); /* Local variables */ integer i__, j, n; doublereal w[2]; integer ia, ja, ic, nc, jj, lj, in, ix, iy, ns, lx, ly, laa, lda; extern logical lde_(doublereal *, doublereal *, integer *); doublereal als, err; integer ldas; logical same; integer incx, incy; logical full, null; char uplo[1]; extern /* Subroutine */ int dspr2_(char *, integer *, doublereal *, doublereal *, integer *, doublereal *, integer *, doublereal *, ftnlen), dsyr2_(char *, integer *, doublereal *, doublereal *, integer *, doublereal *, integer *, doublereal *, integer *, ftnlen), dmake_(char *, char *, char *, integer *, integer *, doublereal *, integer *, doublereal *, integer *, integer *, integer *, logical *, doublereal *, ftnlen, ftnlen, ftnlen); doublereal alpha; logical isame[13]; extern /* Subroutine */ int dmvch_(char *, integer *, integer *, doublereal *, doublereal *, integer *, doublereal *, integer *, doublereal *, doublereal *, integer *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, logical *, integer *, logical *, ftnlen); integer nargs; logical reset; integer incxs, incys; logical upper; char uplos[1]; logical packed; extern logical lderes_(char *, char *, integer *, integer *, doublereal *, doublereal *, integer *, ftnlen, ftnlen); doublereal errmax, transl; /* Fortran I/O blocks */ static cilist io___373 = { 0, 0, 0, fmt_9993, 0 }; static cilist io___374 = { 0, 0, 0, fmt_9994, 0 }; static cilist io___375 = { 0, 0, 0, fmt_9992, 0 }; static cilist io___378 = { 0, 0, 0, fmt_9998, 0 }; static cilist io___385 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___386 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___387 = { 0, 0, 0, fmt_9995, 0 }; static cilist io___388 = { 0, 0, 0, fmt_9996, 0 }; static cilist io___389 = { 0, 0, 0, fmt_9993, 0 }; static cilist io___390 = { 0, 0, 0, fmt_9994, 0 }; /* Tests DSYR2 and DSPR2. */ /* Auxiliary routine for test program for Level 2 Blas. */ /* -- Written on 10-August-1987. */ /* Richard Hanson, Sandia National Labs. */ /* Jeremy Du Croz, NAG Central Office. */ /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Scalars .. */ /* .. Local Arrays .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. Scalars in Common .. */ /* .. Common blocks .. */ /* .. Data statements .. */ /* Parameter adjustments */ --idim; --alf; --inc; z_dim1 = *nmax; z_offset = 1 + z_dim1; z__ -= z_offset; --g; --yt; --y; --x; --as; --aa; a_dim1 = *nmax; a_offset = 1 + a_dim1; a -= a_offset; --ys; --yy; --xs; --xx; /* Function Body */ /* .. Executable Statements .. */ full = *(unsigned char *)&sname[2] == 'Y'; packed = *(unsigned char *)&sname[2] == 'P'; /* Define the number of arguments. */ if (full) { nargs = 9; } else if (packed) { nargs = 8; } nc = 0; reset = TRUE_; errmax = 0.; i__1 = *nidim; for (in = 1; in <= i__1; ++in) { n = idim[in]; /* Set LDA to 1 more than minimum value if room. */ lda = n; if (lda < *nmax) { ++lda; } /* Skip tests if not enough room. */ if (lda > *nmax) { goto L140; } if (packed) { laa = n * (n + 1) / 2; } else { laa = lda * n; } for (ic = 1; ic <= 2; ++ic) { *(unsigned char *)uplo = *(unsigned char *)&ich[ic - 1]; upper = *(unsigned char *)uplo == 'U'; i__2 = *ninc; for (ix = 1; ix <= i__2; ++ix) { incx = inc[ix]; lx = abs(incx) * n; /* Generate the vector X. */ transl = .5; i__3 = abs(incx); i__4 = n - 1; dmake_("GE", " ", " ", &c__1, &n, &x[1], &c__1, &xx[1], &i__3, &c__0, &i__4, &reset, &transl, (ftnlen)2, (ftnlen)1, (ftnlen)1); if (n > 1) { x[n / 2] = 0.; xx[abs(incx) * (n / 2 - 1) + 1] = 0.; } i__3 = *ninc; for (iy = 1; iy <= i__3; ++iy) { incy = inc[iy]; ly = abs(incy) * n; /* Generate the vector Y. */ transl = 0.; i__4 = abs(incy); i__5 = n - 1; dmake_("GE", " ", " ", &c__1, &n, &y[1], &c__1, &yy[1], & i__4, &c__0, &i__5, &reset, &transl, (ftnlen)2, ( ftnlen)1, (ftnlen)1); if (n > 1) { y[n / 2] = 0.; yy[abs(incy) * (n / 2 - 1) + 1] = 0.; } i__4 = *nalf; for (ia = 1; ia <= i__4; ++ia) { alpha = alf[ia]; null = n <= 0 || alpha == 0.; /* Generate the matrix A. */ transl = 0.; i__5 = n - 1; i__6 = n - 1; dmake_(sname + 1, uplo, " ", &n, &n, &a[a_offset], nmax, &aa[1], &lda, &i__5, &i__6, &reset, & transl, (ftnlen)2, (ftnlen)1, (ftnlen)1); ++nc; /* Save every datum before calling the subroutine. */ *(unsigned char *)uplos = *(unsigned char *)uplo; ns = n; als = alpha; i__5 = laa; for (i__ = 1; i__ <= i__5; ++i__) { as[i__] = aa[i__]; /* L10: */ } ldas = lda; i__5 = lx; for (i__ = 1; i__ <= i__5; ++i__) { xs[i__] = xx[i__]; /* L20: */ } incxs = incx; i__5 = ly; for (i__ = 1; i__ <= i__5; ++i__) { ys[i__] = yy[i__]; /* L30: */ } incys = incy; /* Call the subroutine. */ if (full) { if (*trace) { io___373.ciunit = *ntra; s_wsfe(&io___373); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof( integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&alpha, (ftnlen)sizeof( doublereal)); do_fio(&c__1, (char *)&incx, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&incy, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&lda, (ftnlen)sizeof( integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } dsyr2_(uplo, &n, &alpha, &xx[1], &incx, &yy[1], & incy, &aa[1], &lda, (ftnlen)1); } else if (packed) { if (*trace) { io___374.ciunit = *ntra; s_wsfe(&io___374); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof( integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&alpha, (ftnlen)sizeof( doublereal)); do_fio(&c__1, (char *)&incx, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&incy, (ftnlen)sizeof( integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } dspr2_(uplo, &n, &alpha, &xx[1], &incx, &yy[1], & incy, &aa[1], (ftnlen)1); } /* Check if error-exit was taken incorrectly. */ if (! infoc_1.ok) { io___375.ciunit = *nout; s_wsfe(&io___375); e_wsfe(); *fatal = TRUE_; goto L160; } /* See what data changed inside subroutines. */ isame[0] = *(unsigned char *)uplo == *(unsigned char * )uplos; isame[1] = ns == n; isame[2] = als == alpha; isame[3] = lde_(&xs[1], &xx[1], &lx); isame[4] = incxs == incx; isame[5] = lde_(&ys[1], &yy[1], &ly); isame[6] = incys == incy; if (null) { isame[7] = lde_(&as[1], &aa[1], &laa); } else { isame[7] = lderes_(sname + 1, uplo, &n, &n, &as[1] , &aa[1], &lda, (ftnlen)2, (ftnlen)1); } if (! packed) { isame[8] = ldas == lda; } /* If data was incorrectly changed, report and return. */ same = TRUE_; i__5 = nargs; for (i__ = 1; i__ <= i__5; ++i__) { same = same && isame[i__ - 1]; if (! isame[i__ - 1]) { io___378.ciunit = *nout; s_wsfe(&io___378); do_fio(&c__1, (char *)&i__, (ftnlen)sizeof( integer)); e_wsfe(); } /* L40: */ } if (! same) { *fatal = TRUE_; goto L160; } if (! null) { /* Check the result column by column. */ if (incx > 0) { i__5 = n; for (i__ = 1; i__ <= i__5; ++i__) { z__[i__ + z_dim1] = x[i__]; /* L50: */ } } else { i__5 = n; for (i__ = 1; i__ <= i__5; ++i__) { z__[i__ + z_dim1] = x[n - i__ + 1]; /* L60: */ } } if (incy > 0) { i__5 = n; for (i__ = 1; i__ <= i__5; ++i__) { z__[i__ + (z_dim1 << 1)] = y[i__]; /* L70: */ } } else { i__5 = n; for (i__ = 1; i__ <= i__5; ++i__) { z__[i__ + (z_dim1 << 1)] = y[n - i__ + 1]; /* L80: */ } } ja = 1; i__5 = n; for (j = 1; j <= i__5; ++j) { w[0] = z__[j + (z_dim1 << 1)]; w[1] = z__[j + z_dim1]; if (upper) { jj = 1; lj = j; } else { jj = j; lj = n - j + 1; } dmvch_("N", &lj, &c__2, &alpha, &z__[jj + z_dim1], nmax, w, &c__1, &c_b128, &a[ jj + j * a_dim1], &c__1, &yt[1], &g[1] , &aa[ja], eps, &err, fatal, nout, & c_true, (ftnlen)1); if (full) { if (upper) { ja += lda; } else { ja = ja + lda + 1; } } else { ja += lj; } errmax = max(errmax,err); /* If got really bad answer, report and return. */ if (*fatal) { goto L150; } /* L90: */ } } else { /* Avoid repeating tests with N.le.0. */ if (n <= 0) { goto L140; } } /* L100: */ } /* L110: */ } /* L120: */ } /* L130: */ } L140: ; } /* Report result. */ if (errmax < *thresh) { io___385.ciunit = *nout; s_wsfe(&io___385); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); e_wsfe(); } else { io___386.ciunit = *nout; s_wsfe(&io___386); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&errmax, (ftnlen)sizeof(doublereal)); e_wsfe(); } goto L170; L150: io___387.ciunit = *nout; s_wsfe(&io___387); do_fio(&c__1, (char *)&j, (ftnlen)sizeof(integer)); e_wsfe(); L160: io___388.ciunit = *nout; s_wsfe(&io___388); do_fio(&c__1, sname, (ftnlen)6); e_wsfe(); if (full) { io___389.ciunit = *nout; s_wsfe(&io___389); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&alpha, (ftnlen)sizeof(doublereal)); do_fio(&c__1, (char *)&incx, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&incy, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&lda, (ftnlen)sizeof(integer)); e_wsfe(); } else if (packed) { io___390.ciunit = *nout; s_wsfe(&io___390); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&alpha, (ftnlen)sizeof(doublereal)); do_fio(&c__1, (char *)&incx, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&incy, (ftnlen)sizeof(integer)); e_wsfe(); } L170: return 0; /* End of DCHK6. */ } /* dchk6_ */ /* Subroutine */ int dchke_(integer *isnum, char *srnamt, integer *nout, ftnlen srnamt_len) { /* Format strings */ static char fmt_9999[] = "(\002 \002,a6,\002 PASSED THE TESTS OF ERROR-E" "XITS\002)"; static char fmt_9998[] = "(\002 ******* \002,a6,\002 FAILED THE TESTS OF" " ERROR-EXITS *****\002,\002**\002)"; /* Builtin functions */ integer s_wsfe(cilist *), do_fio(integer *, char *, ftnlen), e_wsfe(void); /* Local variables */ doublereal a[1] /* was [1][1] */, x[1], y[1], beta; extern /* Subroutine */ int dger_(integer *, integer *, doublereal *, doublereal *, integer *, doublereal *, integer *, doublereal *, integer *), dspr_(char *, integer *, doublereal *, doublereal *, integer *, doublereal *, ftnlen), dsyr_(char *, integer *, doublereal *, doublereal *, integer *, doublereal *, integer *, ftnlen), dspr2_(char *, integer *, doublereal *, doublereal *, integer *, doublereal *, integer *, doublereal *, ftnlen), dsyr2_( char *, integer *, doublereal *, doublereal *, integer *, doublereal *, integer *, doublereal *, integer *, ftnlen); doublereal alpha; extern /* Subroutine */ int dgbmv_(char *, integer *, integer *, integer * , integer *, doublereal *, doublereal *, integer *, doublereal *, integer *, doublereal *, doublereal *, integer *, ftnlen), dgemv_( char *, integer *, integer *, doublereal *, doublereal *, integer *, doublereal *, integer *, doublereal *, doublereal *, integer *, ftnlen), dsbmv_(char *, integer *, integer *, doublereal *, doublereal *, integer *, doublereal *, integer *, doublereal *, doublereal *, integer *, ftnlen), dtbmv_(char *, char *, char *, integer *, integer *, doublereal *, integer *, doublereal *, integer *, ftnlen, ftnlen, ftnlen), dtbsv_(char *, char *, char *, integer *, integer *, doublereal *, integer *, doublereal *, integer *, ftnlen, ftnlen, ftnlen), dspmv_(char *, integer *, doublereal *, doublereal *, doublereal *, integer *, doublereal *, doublereal *, integer *, ftnlen), dtpmv_(char *, char *, char *, integer *, doublereal *, doublereal *, integer *, ftnlen, ftnlen, ftnlen), dtrmv_(char *, char *, char *, integer *, doublereal *, integer *, doublereal *, integer *, ftnlen, ftnlen, ftnlen), dtpsv_(char *, char *, char *, integer *, doublereal *, doublereal *, integer *, ftnlen, ftnlen, ftnlen), dsymv_(char *, integer *, doublereal *, doublereal *, integer *, doublereal *, integer *, doublereal *, doublereal *, integer *, ftnlen), dtrsv_( char *, char *, char *, integer *, doublereal *, integer *, doublereal *, integer *, ftnlen, ftnlen, ftnlen), chkxer_(char *, integer *, integer *, logical *, logical *, ftnlen); /* Fortran I/O blocks */ static cilist io___396 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___397 = { 0, 0, 0, fmt_9998, 0 }; /* Tests the error exits from the Level 2 Blas. */ /* Requires a special version of the error-handling routine XERBLA. */ /* ALPHA, BETA, A, X and Y should not need to be defined. */ /* Auxiliary routine for test program for Level 2 Blas. */ /* -- Written on 10-August-1987. */ /* Richard Hanson, Sandia National Labs. */ /* Jeremy Du Croz, NAG Central Office. */ /* .. Scalar Arguments .. */ /* .. Scalars in Common .. */ /* .. Local Scalars .. */ /* .. Local Arrays .. */ /* .. External Subroutines .. */ /* .. Common blocks .. */ /* .. Executable Statements .. */ /* OK is set to .FALSE. by the special version of XERBLA or by CHKXER */ /* if anything is wrong. */ infoc_1.ok = TRUE_; /* LERR is set to .TRUE. by the special version of XERBLA each time */ /* it is called, and is then tested and re-set by CHKXER. */ infoc_1.lerr = FALSE_; switch (*isnum) { case 1: goto L10; case 2: goto L20; case 3: goto L30; case 4: goto L40; case 5: goto L50; case 6: goto L60; case 7: goto L70; case 8: goto L80; case 9: goto L90; case 10: goto L100; case 11: goto L110; case 12: goto L120; case 13: goto L130; case 14: goto L140; case 15: goto L150; case 16: goto L160; } L10: infoc_1.infot = 1; dgemv_("/", &c__0, &c__0, &alpha, a, &c__1, x, &c__1, &beta, y, &c__1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; dgemv_("N", &c_n1, &c__0, &alpha, a, &c__1, x, &c__1, &beta, y, &c__1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; dgemv_("N", &c__0, &c_n1, &alpha, a, &c__1, x, &c__1, &beta, y, &c__1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; dgemv_("N", &c__2, &c__0, &alpha, a, &c__1, x, &c__1, &beta, y, &c__1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 8; dgemv_("N", &c__0, &c__0, &alpha, a, &c__1, x, &c__0, &beta, y, &c__1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; dgemv_("N", &c__0, &c__0, &alpha, a, &c__1, x, &c__1, &beta, y, &c__0, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L170; L20: infoc_1.infot = 1; dgbmv_("/", &c__0, &c__0, &c__0, &c__0, &alpha, a, &c__1, x, &c__1, &beta, y, &c__1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; dgbmv_("N", &c_n1, &c__0, &c__0, &c__0, &alpha, a, &c__1, x, &c__1, &beta, y, &c__1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; dgbmv_("N", &c__0, &c_n1, &c__0, &c__0, &alpha, a, &c__1, x, &c__1, &beta, y, &c__1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; dgbmv_("N", &c__0, &c__0, &c_n1, &c__0, &alpha, a, &c__1, x, &c__1, &beta, y, &c__1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; dgbmv_("N", &c__2, &c__0, &c__0, &c_n1, &alpha, a, &c__1, x, &c__1, &beta, y, &c__1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 8; dgbmv_("N", &c__0, &c__0, &c__1, &c__0, &alpha, a, &c__1, x, &c__1, &beta, y, &c__1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 10; dgbmv_("N", &c__0, &c__0, &c__0, &c__0, &alpha, a, &c__1, x, &c__0, &beta, y, &c__1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 13; dgbmv_("N", &c__0, &c__0, &c__0, &c__0, &alpha, a, &c__1, x, &c__1, &beta, y, &c__0, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L170; L30: infoc_1.infot = 1; dsymv_("/", &c__0, &alpha, a, &c__1, x, &c__1, &beta, y, &c__1, (ftnlen)1) ; chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; dsymv_("U", &c_n1, &alpha, a, &c__1, x, &c__1, &beta, y, &c__1, (ftnlen)1) ; chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; dsymv_("U", &c__2, &alpha, a, &c__1, x, &c__1, &beta, y, &c__1, (ftnlen)1) ; chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; dsymv_("U", &c__0, &alpha, a, &c__1, x, &c__0, &beta, y, &c__1, (ftnlen)1) ; chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 10; dsymv_("U", &c__0, &alpha, a, &c__1, x, &c__1, &beta, y, &c__0, (ftnlen)1) ; chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L170; L40: infoc_1.infot = 1; dsbmv_("/", &c__0, &c__0, &alpha, a, &c__1, x, &c__1, &beta, y, &c__1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; dsbmv_("U", &c_n1, &c__0, &alpha, a, &c__1, x, &c__1, &beta, y, &c__1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; dsbmv_("U", &c__0, &c_n1, &alpha, a, &c__1, x, &c__1, &beta, y, &c__1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; dsbmv_("U", &c__0, &c__1, &alpha, a, &c__1, x, &c__1, &beta, y, &c__1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 8; dsbmv_("U", &c__0, &c__0, &alpha, a, &c__1, x, &c__0, &beta, y, &c__1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; dsbmv_("U", &c__0, &c__0, &alpha, a, &c__1, x, &c__1, &beta, y, &c__0, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L170; L50: infoc_1.infot = 1; dspmv_("/", &c__0, &alpha, a, x, &c__1, &beta, y, &c__1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; dspmv_("U", &c_n1, &alpha, a, x, &c__1, &beta, y, &c__1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; dspmv_("U", &c__0, &alpha, a, x, &c__0, &beta, y, &c__1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; dspmv_("U", &c__0, &alpha, a, x, &c__1, &beta, y, &c__0, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L170; L60: infoc_1.infot = 1; dtrmv_("/", "N", "N", &c__0, a, &c__1, x, &c__1, (ftnlen)1, (ftnlen)1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; dtrmv_("U", "/", "N", &c__0, a, &c__1, x, &c__1, (ftnlen)1, (ftnlen)1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; dtrmv_("U", "N", "/", &c__0, a, &c__1, x, &c__1, (ftnlen)1, (ftnlen)1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; dtrmv_("U", "N", "N", &c_n1, a, &c__1, x, &c__1, (ftnlen)1, (ftnlen)1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; dtrmv_("U", "N", "N", &c__2, a, &c__1, x, &c__1, (ftnlen)1, (ftnlen)1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 8; dtrmv_("U", "N", "N", &c__0, a, &c__1, x, &c__0, (ftnlen)1, (ftnlen)1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L170; L70: infoc_1.infot = 1; dtbmv_("/", "N", "N", &c__0, &c__0, a, &c__1, x, &c__1, (ftnlen)1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; dtbmv_("U", "/", "N", &c__0, &c__0, a, &c__1, x, &c__1, (ftnlen)1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; dtbmv_("U", "N", "/", &c__0, &c__0, a, &c__1, x, &c__1, (ftnlen)1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; dtbmv_("U", "N", "N", &c_n1, &c__0, a, &c__1, x, &c__1, (ftnlen)1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; dtbmv_("U", "N", "N", &c__0, &c_n1, a, &c__1, x, &c__1, (ftnlen)1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; dtbmv_("U", "N", "N", &c__0, &c__1, a, &c__1, x, &c__1, (ftnlen)1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; dtbmv_("U", "N", "N", &c__0, &c__0, a, &c__1, x, &c__0, (ftnlen)1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L170; L80: infoc_1.infot = 1; dtpmv_("/", "N", "N", &c__0, a, x, &c__1, (ftnlen)1, (ftnlen)1, (ftnlen)1) ; chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; dtpmv_("U", "/", "N", &c__0, a, x, &c__1, (ftnlen)1, (ftnlen)1, (ftnlen)1) ; chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; dtpmv_("U", "N", "/", &c__0, a, x, &c__1, (ftnlen)1, (ftnlen)1, (ftnlen)1) ; chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; dtpmv_("U", "N", "N", &c_n1, a, x, &c__1, (ftnlen)1, (ftnlen)1, (ftnlen)1) ; chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; dtpmv_("U", "N", "N", &c__0, a, x, &c__0, (ftnlen)1, (ftnlen)1, (ftnlen)1) ; chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L170; L90: infoc_1.infot = 1; dtrsv_("/", "N", "N", &c__0, a, &c__1, x, &c__1, (ftnlen)1, (ftnlen)1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; dtrsv_("U", "/", "N", &c__0, a, &c__1, x, &c__1, (ftnlen)1, (ftnlen)1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; dtrsv_("U", "N", "/", &c__0, a, &c__1, x, &c__1, (ftnlen)1, (ftnlen)1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; dtrsv_("U", "N", "N", &c_n1, a, &c__1, x, &c__1, (ftnlen)1, (ftnlen)1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; dtrsv_("U", "N", "N", &c__2, a, &c__1, x, &c__1, (ftnlen)1, (ftnlen)1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 8; dtrsv_("U", "N", "N", &c__0, a, &c__1, x, &c__0, (ftnlen)1, (ftnlen)1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L170; L100: infoc_1.infot = 1; dtbsv_("/", "N", "N", &c__0, &c__0, a, &c__1, x, &c__1, (ftnlen)1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; dtbsv_("U", "/", "N", &c__0, &c__0, a, &c__1, x, &c__1, (ftnlen)1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; dtbsv_("U", "N", "/", &c__0, &c__0, a, &c__1, x, &c__1, (ftnlen)1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; dtbsv_("U", "N", "N", &c_n1, &c__0, a, &c__1, x, &c__1, (ftnlen)1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; dtbsv_("U", "N", "N", &c__0, &c_n1, a, &c__1, x, &c__1, (ftnlen)1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; dtbsv_("U", "N", "N", &c__0, &c__1, a, &c__1, x, &c__1, (ftnlen)1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; dtbsv_("U", "N", "N", &c__0, &c__0, a, &c__1, x, &c__0, (ftnlen)1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L170; L110: infoc_1.infot = 1; dtpsv_("/", "N", "N", &c__0, a, x, &c__1, (ftnlen)1, (ftnlen)1, (ftnlen)1) ; chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; dtpsv_("U", "/", "N", &c__0, a, x, &c__1, (ftnlen)1, (ftnlen)1, (ftnlen)1) ; chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; dtpsv_("U", "N", "/", &c__0, a, x, &c__1, (ftnlen)1, (ftnlen)1, (ftnlen)1) ; chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; dtpsv_("U", "N", "N", &c_n1, a, x, &c__1, (ftnlen)1, (ftnlen)1, (ftnlen)1) ; chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; dtpsv_("U", "N", "N", &c__0, a, x, &c__0, (ftnlen)1, (ftnlen)1, (ftnlen)1) ; chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L170; L120: infoc_1.infot = 1; dger_(&c_n1, &c__0, &alpha, x, &c__1, y, &c__1, a, &c__1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; dger_(&c__0, &c_n1, &alpha, x, &c__1, y, &c__1, a, &c__1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; dger_(&c__0, &c__0, &alpha, x, &c__0, y, &c__1, a, &c__1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; dger_(&c__0, &c__0, &alpha, x, &c__1, y, &c__0, a, &c__1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; dger_(&c__2, &c__0, &alpha, x, &c__1, y, &c__1, a, &c__1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L170; L130: infoc_1.infot = 1; dsyr_("/", &c__0, &alpha, x, &c__1, a, &c__1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; dsyr_("U", &c_n1, &alpha, x, &c__1, a, &c__1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; dsyr_("U", &c__0, &alpha, x, &c__0, a, &c__1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; dsyr_("U", &c__2, &alpha, x, &c__1, a, &c__1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L170; L140: infoc_1.infot = 1; dspr_("/", &c__0, &alpha, x, &c__1, a, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; dspr_("U", &c_n1, &alpha, x, &c__1, a, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; dspr_("U", &c__0, &alpha, x, &c__0, a, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L170; L150: infoc_1.infot = 1; dsyr2_("/", &c__0, &alpha, x, &c__1, y, &c__1, a, &c__1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; dsyr2_("U", &c_n1, &alpha, x, &c__1, y, &c__1, a, &c__1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; dsyr2_("U", &c__0, &alpha, x, &c__0, y, &c__1, a, &c__1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; dsyr2_("U", &c__0, &alpha, x, &c__1, y, &c__0, a, &c__1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; dsyr2_("U", &c__2, &alpha, x, &c__1, y, &c__1, a, &c__1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L170; L160: infoc_1.infot = 1; dspr2_("/", &c__0, &alpha, x, &c__1, y, &c__1, a, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; dspr2_("U", &c_n1, &alpha, x, &c__1, y, &c__1, a, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; dspr2_("U", &c__0, &alpha, x, &c__0, y, &c__1, a, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; dspr2_("U", &c__0, &alpha, x, &c__1, y, &c__0, a, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); L170: if (infoc_1.ok) { io___396.ciunit = *nout; s_wsfe(&io___396); do_fio(&c__1, srnamt, (ftnlen)6); e_wsfe(); } else { io___397.ciunit = *nout; s_wsfe(&io___397); do_fio(&c__1, srnamt, (ftnlen)6); e_wsfe(); } return 0; /* End of DCHKE. */ } /* dchke_ */ /* Subroutine */ int dmake_(char *type__, char *uplo, char *diag, integer *m, integer *n, doublereal *a, integer *nmax, doublereal *aa, integer * lda, integer *kl, integer *ku, logical *reset, doublereal *transl, ftnlen type_len, ftnlen uplo_len, ftnlen diag_len) { /* System generated locals */ integer a_dim1, a_offset, i__1, i__2, i__3, i__4; /* Builtin functions */ integer s_cmp(const char *, const char *, ftnlen, ftnlen); /* Local variables */ integer i__, j, i1, i2, i3, kk; logical gen, tri, sym; extern doublereal dbeg_(logical *); integer ibeg, iend, ioff; logical unit, lower, upper; /* Generates values for an M by N matrix A within the bandwidth */ /* defined by KL and KU. */ /* Stores the values in the array AA in the data structure required */ /* by the routine, with unwanted elements set to rogue value. */ /* TYPE is 'GE', 'GB', 'SY', 'SB', 'SP', 'TR', 'TB' OR 'TP'. */ /* Auxiliary routine for test program for Level 2 Blas. */ /* -- Written on 10-August-1987. */ /* Richard Hanson, Sandia National Labs. */ /* Jeremy Du Croz, NAG Central Office. */ /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Scalars .. */ /* .. External Functions .. */ /* .. Intrinsic Functions .. */ /* .. Executable Statements .. */ /* Parameter adjustments */ a_dim1 = *nmax; a_offset = 1 + a_dim1; a -= a_offset; --aa; /* Function Body */ gen = *(unsigned char *)type__ == 'G'; sym = *(unsigned char *)type__ == 'S'; tri = *(unsigned char *)type__ == 'T'; upper = (sym || tri) && *(unsigned char *)uplo == 'U'; lower = (sym || tri) && *(unsigned char *)uplo == 'L'; unit = tri && *(unsigned char *)diag == 'U'; /* Generate data in array A. */ i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = *m; for (i__ = 1; i__ <= i__2; ++i__) { if (gen || upper && i__ <= j || lower && i__ >= j) { if (i__ <= j && j - i__ <= *ku || i__ >= j && i__ - j <= *kl) { a[i__ + j * a_dim1] = dbeg_(reset) + *transl; } else { a[i__ + j * a_dim1] = 0.; } if (i__ != j) { if (sym) { a[j + i__ * a_dim1] = a[i__ + j * a_dim1]; } else if (tri) { a[j + i__ * a_dim1] = 0.; } } } /* L10: */ } if (tri) { a[j + j * a_dim1] += 1.; } if (unit) { a[j + j * a_dim1] = 1.; } /* L20: */ } /* Store elements in array AS in data structure required by routine. */ if (s_cmp(type__, "GE", (ftnlen)2, (ftnlen)2) == 0) { i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = *m; for (i__ = 1; i__ <= i__2; ++i__) { aa[i__ + (j - 1) * *lda] = a[i__ + j * a_dim1]; /* L30: */ } i__2 = *lda; for (i__ = *m + 1; i__ <= i__2; ++i__) { aa[i__ + (j - 1) * *lda] = -1e10; /* L40: */ } /* L50: */ } } else if (s_cmp(type__, "GB", (ftnlen)2, (ftnlen)2) == 0) { i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = *ku + 1 - j; for (i1 = 1; i1 <= i__2; ++i1) { aa[i1 + (j - 1) * *lda] = -1e10; /* L60: */ } /* Computing MIN */ i__3 = *kl + *ku + 1, i__4 = *ku + 1 + *m - j; i__2 = min(i__3,i__4); for (i2 = i1; i2 <= i__2; ++i2) { aa[i2 + (j - 1) * *lda] = a[i2 + j - *ku - 1 + j * a_dim1]; /* L70: */ } i__2 = *lda; for (i3 = i2; i3 <= i__2; ++i3) { aa[i3 + (j - 1) * *lda] = -1e10; /* L80: */ } /* L90: */ } } else if (s_cmp(type__, "SY", (ftnlen)2, (ftnlen)2) == 0 || s_cmp(type__, "TR", (ftnlen)2, (ftnlen)2) == 0) { i__1 = *n; for (j = 1; j <= i__1; ++j) { if (upper) { ibeg = 1; if (unit) { iend = j - 1; } else { iend = j; } } else { if (unit) { ibeg = j + 1; } else { ibeg = j; } iend = *n; } i__2 = ibeg - 1; for (i__ = 1; i__ <= i__2; ++i__) { aa[i__ + (j - 1) * *lda] = -1e10; /* L100: */ } i__2 = iend; for (i__ = ibeg; i__ <= i__2; ++i__) { aa[i__ + (j - 1) * *lda] = a[i__ + j * a_dim1]; /* L110: */ } i__2 = *lda; for (i__ = iend + 1; i__ <= i__2; ++i__) { aa[i__ + (j - 1) * *lda] = -1e10; /* L120: */ } /* L130: */ } } else if (s_cmp(type__, "SB", (ftnlen)2, (ftnlen)2) == 0 || s_cmp(type__, "TB", (ftnlen)2, (ftnlen)2) == 0) { i__1 = *n; for (j = 1; j <= i__1; ++j) { if (upper) { kk = *kl + 1; /* Computing MAX */ i__2 = 1, i__3 = *kl + 2 - j; ibeg = max(i__2,i__3); if (unit) { iend = *kl; } else { iend = *kl + 1; } } else { kk = 1; if (unit) { ibeg = 2; } else { ibeg = 1; } /* Computing MIN */ i__2 = *kl + 1, i__3 = *m + 1 - j; iend = min(i__2,i__3); } i__2 = ibeg - 1; for (i__ = 1; i__ <= i__2; ++i__) { aa[i__ + (j - 1) * *lda] = -1e10; /* L140: */ } i__2 = iend; for (i__ = ibeg; i__ <= i__2; ++i__) { aa[i__ + (j - 1) * *lda] = a[i__ + j - kk + j * a_dim1]; /* L150: */ } i__2 = *lda; for (i__ = iend + 1; i__ <= i__2; ++i__) { aa[i__ + (j - 1) * *lda] = -1e10; /* L160: */ } /* L170: */ } } else if (s_cmp(type__, "SP", (ftnlen)2, (ftnlen)2) == 0 || s_cmp(type__, "TP", (ftnlen)2, (ftnlen)2) == 0) { ioff = 0; i__1 = *n; for (j = 1; j <= i__1; ++j) { if (upper) { ibeg = 1; iend = j; } else { ibeg = j; iend = *n; } i__2 = iend; for (i__ = ibeg; i__ <= i__2; ++i__) { ++ioff; aa[ioff] = a[i__ + j * a_dim1]; if (i__ == j) { if (unit) { aa[ioff] = -1e10; } } /* L180: */ } /* L190: */ } } return 0; /* End of DMAKE. */ } /* dmake_ */ /* Subroutine */ int dmvch_(char *trans, integer *m, integer *n, doublereal * alpha, doublereal *a, integer *nmax, doublereal *x, integer *incx, doublereal *beta, doublereal *y, integer *incy, doublereal *yt, doublereal *g, doublereal *yy, doublereal *eps, doublereal *err, logical *fatal, integer *nout, logical *mv, ftnlen trans_len) { /* Format strings */ static char fmt_9999[] = "(\002 ******* FATAL ERROR - COMPUTED RESULT IS" " LESS THAN HAL\002,\002F ACCURATE *******\002,/\002 EX" "PECTED RESULT COMPU\002,\002TED RESULT\002)"; static char fmt_9998[] = "(1x,i7,2g18.6)"; /* System generated locals */ integer a_dim1, a_offset, i__1, i__2; doublereal d__1; /* Builtin functions */ double sqrt(doublereal); integer s_wsfe(cilist *), e_wsfe(void), do_fio(integer *, char *, ftnlen); /* Local variables */ integer i__, j, ml, nl, iy, jx, kx, ky; doublereal erri; logical tran; integer incxl, incyl; /* Fortran I/O blocks */ static cilist io___425 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___426 = { 0, 0, 0, fmt_9998, 0 }; static cilist io___427 = { 0, 0, 0, fmt_9998, 0 }; /* Checks the results of the computational tests. */ /* Auxiliary routine for test program for Level 2 Blas. */ /* -- Written on 10-August-1987. */ /* Richard Hanson, Sandia National Labs. */ /* Jeremy Du Croz, NAG Central Office. */ /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Scalars .. */ /* .. Intrinsic Functions .. */ /* .. Executable Statements .. */ /* Parameter adjustments */ a_dim1 = *nmax; a_offset = 1 + a_dim1; a -= a_offset; --x; --y; --yt; --g; --yy; /* Function Body */ tran = *(unsigned char *)trans == 'T' || *(unsigned char *)trans == 'C'; if (tran) { ml = *n; nl = *m; } else { ml = *m; nl = *n; } if (*incx < 0) { kx = nl; incxl = -1; } else { kx = 1; incxl = 1; } if (*incy < 0) { ky = ml; incyl = -1; } else { ky = 1; incyl = 1; } /* Compute expected result in YT using data in A, X and Y. */ /* Compute gauges in G. */ iy = ky; i__1 = ml; for (i__ = 1; i__ <= i__1; ++i__) { yt[iy] = 0.; g[iy] = 0.; jx = kx; if (tran) { i__2 = nl; for (j = 1; j <= i__2; ++j) { yt[iy] += a[j + i__ * a_dim1] * x[jx]; g[iy] += (d__1 = a[j + i__ * a_dim1] * x[jx], abs(d__1)); jx += incxl; /* L10: */ } } else { i__2 = nl; for (j = 1; j <= i__2; ++j) { yt[iy] += a[i__ + j * a_dim1] * x[jx]; g[iy] += (d__1 = a[i__ + j * a_dim1] * x[jx], abs(d__1)); jx += incxl; /* L20: */ } } yt[iy] = *alpha * yt[iy] + *beta * y[iy]; g[iy] = abs(*alpha) * g[iy] + (d__1 = *beta * y[iy], abs(d__1)); iy += incyl; /* L30: */ } /* Compute the error ratio for this result. */ *err = 0.; i__1 = ml; for (i__ = 1; i__ <= i__1; ++i__) { erri = (d__1 = yt[i__] - yy[(i__ - 1) * abs(*incy) + 1], abs(d__1)) / *eps; if (g[i__] != 0.) { erri /= g[i__]; } *err = max(*err,erri); if (*err * sqrt(*eps) >= 1.) { goto L50; } /* L40: */ } /* If the loop completes, all results are at least half accurate. */ goto L70; /* Report fatal error. */ L50: *fatal = TRUE_; io___425.ciunit = *nout; s_wsfe(&io___425); e_wsfe(); i__1 = ml; for (i__ = 1; i__ <= i__1; ++i__) { if (*mv) { io___426.ciunit = *nout; s_wsfe(&io___426); do_fio(&c__1, (char *)&i__, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&yt[i__], (ftnlen)sizeof(doublereal)); do_fio(&c__1, (char *)&yy[(i__ - 1) * abs(*incy) + 1], (ftnlen) sizeof(doublereal)); e_wsfe(); } else { io___427.ciunit = *nout; s_wsfe(&io___427); do_fio(&c__1, (char *)&i__, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&yy[(i__ - 1) * abs(*incy) + 1], (ftnlen) sizeof(doublereal)); do_fio(&c__1, (char *)&yt[i__], (ftnlen)sizeof(doublereal)); e_wsfe(); } /* L60: */ } L70: return 0; /* End of DMVCH. */ } /* dmvch_ */ logical lde_(doublereal *ri, doublereal *rj, integer *lr) { /* System generated locals */ integer i__1; logical ret_val; /* Local variables */ integer i__; /* Tests if two arrays are identical. */ /* Auxiliary routine for test program for Level 2 Blas. */ /* -- Written on 10-August-1987. */ /* Richard Hanson, Sandia National Labs. */ /* Jeremy Du Croz, NAG Central Office. */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Scalars .. */ /* .. Executable Statements .. */ /* Parameter adjustments */ --rj; --ri; /* Function Body */ i__1 = *lr; for (i__ = 1; i__ <= i__1; ++i__) { if (ri[i__] != rj[i__]) { goto L20; } /* L10: */ } ret_val = TRUE_; goto L30; L20: ret_val = FALSE_; L30: return ret_val; /* End of LDE. */ } /* lde_ */ logical lderes_(char *type__, char *uplo, integer *m, integer *n, doublereal * aa, doublereal *as, integer *lda, ftnlen type_len, ftnlen uplo_len) { /* System generated locals */ integer aa_dim1, aa_offset, as_dim1, as_offset, i__1, i__2; logical ret_val; /* Builtin functions */ integer s_cmp(const char *, const char *, ftnlen, ftnlen); /* Local variables */ integer i__, j, ibeg, iend; logical upper; /* Tests if selected elements in two arrays are equal. */ /* TYPE is 'GE', 'SY' or 'SP'. */ /* Auxiliary routine for test program for Level 2 Blas. */ /* -- Written on 10-August-1987. */ /* Richard Hanson, Sandia National Labs. */ /* Jeremy Du Croz, NAG Central Office. */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Scalars .. */ /* .. Executable Statements .. */ /* Parameter adjustments */ as_dim1 = *lda; as_offset = 1 + as_dim1; as -= as_offset; aa_dim1 = *lda; aa_offset = 1 + aa_dim1; aa -= aa_offset; /* Function Body */ upper = *(unsigned char *)uplo == 'U'; if (s_cmp(type__, "GE", (ftnlen)2, (ftnlen)2) == 0) { i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = *lda; for (i__ = *m + 1; i__ <= i__2; ++i__) { if (aa[i__ + j * aa_dim1] != as[i__ + j * as_dim1]) { goto L70; } /* L10: */ } /* L20: */ } } else if (s_cmp(type__, "SY", (ftnlen)2, (ftnlen)2) == 0) { i__1 = *n; for (j = 1; j <= i__1; ++j) { if (upper) { ibeg = 1; iend = j; } else { ibeg = j; iend = *n; } i__2 = ibeg - 1; for (i__ = 1; i__ <= i__2; ++i__) { if (aa[i__ + j * aa_dim1] != as[i__ + j * as_dim1]) { goto L70; } /* L30: */ } i__2 = *lda; for (i__ = iend + 1; i__ <= i__2; ++i__) { if (aa[i__ + j * aa_dim1] != as[i__ + j * as_dim1]) { goto L70; } /* L40: */ } /* L50: */ } } ret_val = TRUE_; goto L80; L70: ret_val = FALSE_; L80: return ret_val; /* End of LDERES. */ } /* lderes_ */ doublereal dbeg_(logical *reset) { /* System generated locals */ doublereal ret_val; /* Local variables */ static integer i__, ic, mi; /* Generates random numbers uniformly distributed between -0.5 and 0.5. */ /* Auxiliary routine for test program for Level 2 Blas. */ /* -- Written on 10-August-1987. */ /* Richard Hanson, Sandia National Labs. */ /* Jeremy Du Croz, NAG Central Office. */ /* .. Scalar Arguments .. */ /* .. Local Scalars .. */ /* .. Save statement .. */ /* .. Intrinsic Functions .. */ /* .. Executable Statements .. */ if (*reset) { /* Initialize local variables. */ mi = 891; i__ = 7; ic = 0; *reset = FALSE_; } /* The sequence of values of I is bounded between 1 and 999. */ /* If initial I = 1,2,3,6,7 or 9, the period will be 50. */ /* If initial I = 4 or 8, the period will be 25. */ /* If initial I = 5, the period will be 10. */ /* IC is used to break up the period by skipping 1 value of I in 6. */ ++ic; L10: i__ *= mi; i__ -= i__ / 1000 * 1000; if (ic >= 5) { ic = 0; goto L10; } ret_val = (doublereal) (i__ - 500) / 1001.; return ret_val; /* End of DBEG. */ } /* dbeg_ */ doublereal ddiff_(doublereal *x, doublereal *y) { /* System generated locals */ doublereal ret_val; /* Auxiliary routine for test program for Level 2 Blas. */ /* -- Written on 10-August-1987. */ /* Richard Hanson, Sandia National Labs. */ /* .. Scalar Arguments .. */ /* .. Executable Statements .. */ ret_val = *x - *y; return ret_val; /* End of DDIFF. */ } /* ddiff_ */ /* Subroutine */ int chkxer_(char *srnamt, integer *infot, integer *nout, logical *lerr, logical *ok, ftnlen srnamt_len) { /* Format strings */ static char fmt_9999[] = "(\002 ***** ILLEGAL VALUE OF PARAMETER NUMBER" " \002,i2,\002 NOT D\002,\002ETECTED BY \002,a6,\002 *****\002)"; /* Builtin functions */ integer s_wsfe(cilist *), do_fio(integer *, char *, ftnlen), e_wsfe(void); /* Fortran I/O blocks */ static cilist io___437 = { 0, 0, 0, fmt_9999, 0 }; /* Tests whether XERBLA has detected an error when it should. */ /* Auxiliary routine for test program for Level 2 Blas. */ /* -- Written on 10-August-1987. */ /* Richard Hanson, Sandia National Labs. */ /* Jeremy Du Croz, NAG Central Office. */ /* .. Scalar Arguments .. */ /* .. Executable Statements .. */ if (! (*lerr)) { io___437.ciunit = *nout; s_wsfe(&io___437); do_fio(&c__1, (char *)&(*infot), (ftnlen)sizeof(integer)); do_fio(&c__1, srnamt, (ftnlen)6); e_wsfe(); *ok = FALSE_; } *lerr = FALSE_; return 0; /* End of CHKXER. */ } /* chkxer_ */ /* Subroutine */ int xerbla_(char *srname, integer *info, ftnlen srname_len) { /* Format strings */ static char fmt_9999[] = "(\002 ******* XERBLA WAS CALLED WITH INFO =" " \002,i6,\002 INSTEAD\002,\002 OF \002,i2,\002 *******\002)"; static char fmt_9997[] = "(\002 ******* XERBLA WAS CALLED WITH INFO =" " \002,i6,\002 *******\002)"; static char fmt_9998[] = "(\002 ******* XERBLA WAS CALLED WITH SRNAME =" " \002,a6,\002 INSTE\002,\002AD OF \002,a6,\002 *******\002)"; /* Builtin functions */ integer s_wsfe(cilist *), do_fio(integer *, char *, ftnlen), e_wsfe(void), s_cmp(const char *, const char *, ftnlen, ftnlen); /* Fortran I/O blocks */ static cilist io___438 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___439 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___440 = { 0, 0, 0, fmt_9998, 0 }; /* This is a special version of XERBLA to be used only as part of */ /* the test program for testing error exits from the Level 2 BLAS */ /* routines. */ /* XERBLA is an error handler for the Level 2 BLAS routines. */ /* It is called by the Level 2 BLAS routines if an input parameter is */ /* invalid. */ /* Auxiliary routine for test program for Level 2 Blas. */ /* -- Written on 10-August-1987. */ /* Richard Hanson, Sandia National Labs. */ /* Jeremy Du Croz, NAG Central Office. */ /* .. Scalar Arguments .. */ /* .. Scalars in Common .. */ /* .. Common blocks .. */ /* .. Executable Statements .. */ infoc_2.lerr = TRUE_; if (*info != infoc_2.infot) { if (infoc_2.infot != 0) { io___438.ciunit = infoc_2.nout; s_wsfe(&io___438); do_fio(&c__1, (char *)&(*info), (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&infoc_2.infot, (ftnlen)sizeof(integer)); e_wsfe(); } else { io___439.ciunit = infoc_2.nout; s_wsfe(&io___439); do_fio(&c__1, (char *)&(*info), (ftnlen)sizeof(integer)); e_wsfe(); } infoc_2.ok = FALSE_; } if (s_cmp(srname, srnamc_1.srnamt, (ftnlen)6, (ftnlen)6) != 0) { io___440.ciunit = infoc_2.nout; s_wsfe(&io___440); do_fio(&c__1, srname, (ftnlen)6); do_fio(&c__1, srnamc_1.srnamt, (ftnlen)6); e_wsfe(); infoc_2.ok = FALSE_; } return 0; /* End of XERBLA */ } /* xerbla_ */ /* Main program alias */ int dblat2_ () { main (); return 0; } blis-0.9.0/blastest/src/dblat3.c000066400000000000000000004360641422157504600164210ustar00rootroot00000000000000/* dblat3.f -- translated by f2c (version 20100827). You must link the resulting object file with libf2c: on Microsoft Windows system, link with libf2c.lib; on Linux or Unix systems, link with .../path/to/libf2c.a -lm or, if you install libf2c.a in a standard place, with -lf2c -lm -- in that order, at the end of the command line, as in cc *.o -lf2c -lm Source for libf2c is in /netlib/f2c/libf2c.zip, e.g., http://www.netlib.org/f2c/libf2c.zip */ #include "f2c.h" /* Common Block Declarations */ union { struct { integer infot, noutc; logical ok, lerr; } _1; struct { integer infot, nout; logical ok, lerr; } _2; } infoc_; #define infoc_1 (infoc_._1) #define infoc_2 (infoc_._2) struct { char srnamt[6]; } srnamc_; #define srnamc_1 srnamc_ /* Table of constant values */ static integer c__9 = 9; static integer c__1 = 1; static integer c__3 = 3; static integer c__8 = 8; static integer c__5 = 5; static integer c__65 = 65; static integer c__7 = 7; static doublereal c_b86 = 0.; static doublereal c_b96 = 1.; static logical c_true = TRUE_; static logical c_false = FALSE_; static integer c__0 = 0; static integer c_n1 = -1; static integer c__2 = 2; /* > \brief \b DBLAT3 */ /* =========== DOCUMENTATION =========== */ /* Online html documentation available at */ /* http://www.netlib.org/lapack/explore-html/ */ /* Definition: */ /* =========== */ /* PROGRAM DBLAT3 */ /* > \par Purpose: */ /* ============= */ /* > */ /* > \verbatim */ /* > */ /* > Test program for the DOUBLE PRECISION Level 3 Blas. */ /* > */ /* > The program must be driven by a short data file. The first 14 records */ /* > of the file are read using list-directed input, the last 6 records */ /* > are read using the format ( A6, L2 ). An annotated example of a data */ /* > file can be obtained by deleting the first 3 characters from the */ /* > following 20 lines: */ /* > 'dblat3.out' NAME OF SUMMARY OUTPUT FILE */ /* > 6 UNIT NUMBER OF SUMMARY FILE */ /* > 'DBLAT3.SNAP' NAME OF SNAPSHOT OUTPUT FILE */ /* > -1 UNIT NUMBER OF SNAPSHOT FILE (NOT USED IF .LT. 0) */ /* > F LOGICAL FLAG, T TO REWIND SNAPSHOT FILE AFTER EACH RECORD. */ /* > F LOGICAL FLAG, T TO STOP ON FAILURES. */ /* > T LOGICAL FLAG, T TO TEST ERROR EXITS. */ /* > 16.0 THRESHOLD VALUE OF TEST RATIO */ /* > 6 NUMBER OF VALUES OF N */ /* > 0 1 2 3 5 9 VALUES OF N */ /* > 3 NUMBER OF VALUES OF ALPHA */ /* > 0.0 1.0 0.7 VALUES OF ALPHA */ /* > 3 NUMBER OF VALUES OF BETA */ /* > 0.0 1.0 1.3 VALUES OF BETA */ /* > DGEMM T PUT F FOR NO TEST. SAME COLUMNS. */ /* > DSYMM T PUT F FOR NO TEST. SAME COLUMNS. */ /* > DTRMM T PUT F FOR NO TEST. SAME COLUMNS. */ /* > DTRSM T PUT F FOR NO TEST. SAME COLUMNS. */ /* > DSYRK T PUT F FOR NO TEST. SAME COLUMNS. */ /* > DSYR2K T PUT F FOR NO TEST. SAME COLUMNS. */ /* > */ /* > Further Details */ /* > =============== */ /* > */ /* > See: */ /* > */ /* > Dongarra J. J., Du Croz J. J., Duff I. S. and Hammarling S. */ /* > A Set of Level 3 Basic Linear Algebra Subprograms. */ /* > */ /* > Technical Memorandum No.88 (Revision 1), Mathematics and */ /* > Computer Science Division, Argonne National Laboratory, 9700 */ /* > South Cass Avenue, Argonne, Illinois 60439, US. */ /* > */ /* > -- Written on 8-February-1989. */ /* > Jack Dongarra, Argonne National Laboratory. */ /* > Iain Duff, AERE Harwell. */ /* > Jeremy Du Croz, Numerical Algorithms Group Ltd. */ /* > Sven Hammarling, Numerical Algorithms Group Ltd. */ /* > */ /* > 10-9-00: Change STATUS='NEW' to 'UNKNOWN' so that the testers */ /* > can be run multiple times without deleting generated */ /* > output files (susan) */ /* > \endverbatim */ /* Authors: */ /* ======== */ /* > \author Univ. of Tennessee */ /* > \author Univ. of California Berkeley */ /* > \author Univ. of Colorado Denver */ /* > \author NAG Ltd. */ /* > \date April 2012 */ /* > \ingroup double_blas_testing */ /* ===================================================================== */ /* Main program */ int main(void) { /* Initialized data */ static char snames[6*6] = "DGEMM " "DSYMM " "DTRMM " "DTRSM " "DSYRK " "DSYR2K"; /* Format strings */ static char fmt_9997[] = "(\002 NUMBER OF VALUES OF \002,a,\002 IS LESS " "THAN 1 OR GREATER \002,\002THAN \002,i2)"; static char fmt_9996[] = "(\002 VALUE OF N IS LESS THAN 0 OR GREATER THA" "N \002,i2)"; static char fmt_9995[] = "(\002 TESTS OF THE DOUBLE PRECISION LEVEL 3 BL" "AS\002,//\002 THE F\002,\002OLLOWING PARAMETER VALUES WILL BE US" "ED:\002)"; static char fmt_9994[] = "(\002 FOR N \002,9i6)"; static char fmt_9993[] = "(\002 FOR ALPHA \002,7f6.1)"; static char fmt_9992[] = "(\002 FOR BETA \002,7f6.1)"; static char fmt_9984[] = "(\002 ERROR-EXITS WILL NOT BE TESTED\002)"; static char fmt_9999[] = "(\002 ROUTINES PASS COMPUTATIONAL TESTS IF TES" "T RATIO IS LES\002,\002S THAN\002,f8.2)"; static char fmt_9988[] = "(a6,l2)"; static char fmt_9990[] = "(\002 SUBPROGRAM NAME \002,a6,\002 NOT RECOGNI" "ZED\002,/\002 ******* T\002,\002ESTS ABANDONED *******\002)"; static char fmt_9998[] = "(\002 RELATIVE MACHINE PRECISION IS TAKEN TO" " BE\002,1p,d9.1)"; static char fmt_9989[] = "(\002 ERROR IN DMMCH - IN-LINE DOT PRODUCTS A" "RE BEING EVALU\002,\002ATED WRONGLY.\002,/\002 DMMCH WAS CALLED " "WITH TRANSA = \002,a1,\002 AND TRANSB = \002,a1,/\002 AND RETURN" "ED SAME = \002,l1,\002 AND \002,\002ERR = \002,f12.3,\002.\002," "/\002 THIS MAY BE DUE TO FAULTS IN THE \002,\002ARITHMETIC OR TH" "E COMPILER.\002,/\002 ******* TESTS ABANDONED \002,\002******" "*\002)"; static char fmt_9987[] = "(1x,a6,\002 WAS NOT TESTED\002)"; static char fmt_9986[] = "(/\002 END OF TESTS\002)"; static char fmt_9985[] = "(/\002 ******* FATAL ERROR - TESTS ABANDONED *" "******\002)"; static char fmt_9991[] = "(\002 AMEND DATA FILE OR INCREASE ARRAY SIZES " "IN PROGRAM\002,/\002 ******* TESTS ABANDONED *******\002)"; /* System generated locals */ integer i__1, i__2, i__3; olist o__1; cllist cl__1; /* Builtin functions */ integer s_rsle(cilist *), do_lio(integer *, integer *, char *, ftnlen), e_rsle(void), f_open(olist *), s_wsfe(cilist *), do_fio(integer *, char *, ftnlen), e_wsfe(void), s_wsle(cilist *), e_wsle(void), s_rsfe(cilist *), e_rsfe(void), s_cmp(const char *, const char *, ftnlen, ftnlen); /* Subroutine */ int s_stop(char *, ftnlen); integer f_clos(cllist *); /* Subroutine */ int s_copy(char *, const char *, ftnlen, ftnlen); /* Local variables */ doublereal c__[4225] /* was [65][65] */, g[65]; integer i__, j, n; doublereal w[130], aa[4225], ab[8450] /* was [65][130] */, bb[4225], cc[4225], as[4225], bs[4225], cs[4225], ct[65], alf[7]; extern logical lde_(doublereal *, doublereal *, integer *); doublereal bet[7], eps, err; integer nalf, idim[9]; logical same; integer nbet, ntra; logical rewi; integer nout; extern /* Subroutine */ int dchk1_(char *, doublereal *, doublereal *, integer *, integer *, logical *, logical *, logical *, integer *, integer *, integer *, doublereal *, integer *, doublereal *, integer *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, ftnlen), dchk2_(char *, doublereal *, doublereal *, integer *, integer *, logical *, logical *, logical *, integer *, integer *, integer *, doublereal *, integer *, doublereal *, integer *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, ftnlen), dchk3_(char *, doublereal *, doublereal *, integer *, integer *, logical *, logical *, logical *, integer *, integer *, integer *, doublereal *, integer *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, ftnlen), dchk4_(char *, doublereal *, doublereal *, integer *, integer *, logical *, logical *, logical *, integer *, integer *, integer *, doublereal *, integer *, doublereal *, integer *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, ftnlen), dchk5_(char *, doublereal *, doublereal *, integer *, integer *, logical *, logical *, logical *, integer *, integer *, integer *, doublereal *, integer *, doublereal *, integer *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, ftnlen), dchke_(integer *, char *, integer *, ftnlen); logical fatal; extern /* Subroutine */ int dmmch_(char *, char *, integer *, integer *, integer *, doublereal *, doublereal *, integer *, doublereal *, integer *, doublereal *, doublereal *, integer *, doublereal *, doublereal *, doublereal *, integer *, doublereal *, doublereal *, logical *, integer *, logical *, ftnlen, ftnlen); logical trace; integer nidim; char snaps[32]; integer isnum; logical ltest[6], sfatal; char snamet[6], transa[1], transb[1]; doublereal thresh; logical ltestt, tsterr; char summry[32]; extern double d_epsilon_(doublereal *); /* Fortran I/O blocks */ static cilist io___2 = { 0, 5, 0, 0, 0 }; static cilist io___4 = { 0, 5, 0, 0, 0 }; static cilist io___6 = { 0, 5, 0, 0, 0 }; static cilist io___8 = { 0, 5, 0, 0, 0 }; static cilist io___11 = { 0, 5, 0, 0, 0 }; static cilist io___13 = { 0, 5, 0, 0, 0 }; static cilist io___15 = { 0, 5, 0, 0, 0 }; static cilist io___17 = { 0, 5, 0, 0, 0 }; static cilist io___19 = { 0, 5, 0, 0, 0 }; static cilist io___21 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___22 = { 0, 5, 0, 0, 0 }; static cilist io___25 = { 0, 0, 0, fmt_9996, 0 }; static cilist io___26 = { 0, 5, 0, 0, 0 }; static cilist io___28 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___29 = { 0, 5, 0, 0, 0 }; static cilist io___31 = { 0, 5, 0, 0, 0 }; static cilist io___33 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___34 = { 0, 5, 0, 0, 0 }; static cilist io___36 = { 0, 0, 0, fmt_9995, 0 }; static cilist io___37 = { 0, 0, 0, fmt_9994, 0 }; static cilist io___38 = { 0, 0, 0, fmt_9993, 0 }; static cilist io___39 = { 0, 0, 0, fmt_9992, 0 }; static cilist io___40 = { 0, 0, 0, 0, 0 }; static cilist io___41 = { 0, 0, 0, fmt_9984, 0 }; static cilist io___42 = { 0, 0, 0, 0, 0 }; static cilist io___43 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___44 = { 0, 0, 0, 0, 0 }; static cilist io___46 = { 0, 5, 1, fmt_9988, 0 }; static cilist io___49 = { 0, 0, 0, fmt_9990, 0 }; static cilist io___51 = { 0, 0, 0, fmt_9998, 0 }; static cilist io___64 = { 0, 0, 0, fmt_9989, 0 }; static cilist io___65 = { 0, 0, 0, fmt_9989, 0 }; static cilist io___66 = { 0, 0, 0, fmt_9989, 0 }; static cilist io___67 = { 0, 0, 0, fmt_9989, 0 }; static cilist io___69 = { 0, 0, 0, 0, 0 }; static cilist io___70 = { 0, 0, 0, fmt_9987, 0 }; static cilist io___71 = { 0, 0, 0, 0, 0 }; static cilist io___78 = { 0, 0, 0, fmt_9986, 0 }; static cilist io___79 = { 0, 0, 0, fmt_9985, 0 }; static cilist io___80 = { 0, 0, 0, fmt_9991, 0 }; /* -- Reference BLAS test routine (version 3.4.1) -- */ /* -- Reference BLAS is a software package provided by Univ. of Tennessee, -- */ /* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- */ /* April 2012 */ /* ===================================================================== */ /* .. Parameters .. */ /* .. Local Scalars .. */ /* .. Local Arrays .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. Scalars in Common .. */ /* .. Common blocks .. */ /* .. Data statements .. */ /* .. Executable Statements .. */ /* Read name and unit number for summary output file and open file. */ s_rsle(&io___2); do_lio(&c__9, &c__1, summry, (ftnlen)32); e_rsle(); s_rsle(&io___4); do_lio(&c__3, &c__1, (char *)&nout, (ftnlen)sizeof(integer)); e_rsle(); o__1.oerr = 0; o__1.ounit = nout; o__1.ofnmlen = 32; o__1.ofnm = summry; o__1.orl = 0; o__1.osta = "UNKNOWN"; o__1.oacc = 0; o__1.ofm = 0; o__1.oblnk = 0; f_open(&o__1); infoc_1.noutc = nout; /* Read name and unit number for snapshot output file and open file. */ s_rsle(&io___6); do_lio(&c__9, &c__1, snaps, (ftnlen)32); e_rsle(); s_rsle(&io___8); do_lio(&c__3, &c__1, (char *)&ntra, (ftnlen)sizeof(integer)); e_rsle(); trace = ntra >= 0; if (trace) { o__1.oerr = 0; o__1.ounit = ntra; o__1.ofnmlen = 32; o__1.ofnm = snaps; o__1.orl = 0; o__1.osta = "UNKNOWN"; o__1.oacc = 0; o__1.ofm = 0; o__1.oblnk = 0; f_open(&o__1); } /* Read the flag that directs rewinding of the snapshot file. */ s_rsle(&io___11); do_lio(&c__8, &c__1, (char *)&rewi, (ftnlen)sizeof(logical)); e_rsle(); rewi = rewi && trace; /* Read the flag that directs stopping on any failure. */ s_rsle(&io___13); do_lio(&c__8, &c__1, (char *)&sfatal, (ftnlen)sizeof(logical)); e_rsle(); /* Read the flag that indicates whether error exits are to be tested. */ s_rsle(&io___15); do_lio(&c__8, &c__1, (char *)&tsterr, (ftnlen)sizeof(logical)); e_rsle(); /* Read the threshold value of the test ratio */ s_rsle(&io___17); do_lio(&c__5, &c__1, (char *)&thresh, (ftnlen)sizeof(doublereal)); e_rsle(); /* Read and check the parameter values for the tests. */ /* Values of N */ s_rsle(&io___19); do_lio(&c__3, &c__1, (char *)&nidim, (ftnlen)sizeof(integer)); e_rsle(); if (nidim < 1 || nidim > 9) { io___21.ciunit = nout; s_wsfe(&io___21); do_fio(&c__1, "N", (ftnlen)1); do_fio(&c__1, (char *)&c__9, (ftnlen)sizeof(integer)); e_wsfe(); goto L220; } s_rsle(&io___22); i__1 = nidim; for (i__ = 1; i__ <= i__1; ++i__) { do_lio(&c__3, &c__1, (char *)&idim[i__ - 1], (ftnlen)sizeof(integer)); } e_rsle(); i__1 = nidim; for (i__ = 1; i__ <= i__1; ++i__) { if (idim[i__ - 1] < 0 || idim[i__ - 1] > 65) { io___25.ciunit = nout; s_wsfe(&io___25); do_fio(&c__1, (char *)&c__65, (ftnlen)sizeof(integer)); e_wsfe(); goto L220; } /* L10: */ } /* Values of ALPHA */ s_rsle(&io___26); do_lio(&c__3, &c__1, (char *)&nalf, (ftnlen)sizeof(integer)); e_rsle(); if (nalf < 1 || nalf > 7) { io___28.ciunit = nout; s_wsfe(&io___28); do_fio(&c__1, "ALPHA", (ftnlen)5); do_fio(&c__1, (char *)&c__7, (ftnlen)sizeof(integer)); e_wsfe(); goto L220; } s_rsle(&io___29); i__1 = nalf; for (i__ = 1; i__ <= i__1; ++i__) { do_lio(&c__5, &c__1, (char *)&alf[i__ - 1], (ftnlen)sizeof(doublereal) ); } e_rsle(); /* Values of BETA */ s_rsle(&io___31); do_lio(&c__3, &c__1, (char *)&nbet, (ftnlen)sizeof(integer)); e_rsle(); if (nbet < 1 || nbet > 7) { io___33.ciunit = nout; s_wsfe(&io___33); do_fio(&c__1, "BETA", (ftnlen)4); do_fio(&c__1, (char *)&c__7, (ftnlen)sizeof(integer)); e_wsfe(); goto L220; } s_rsle(&io___34); i__1 = nbet; for (i__ = 1; i__ <= i__1; ++i__) { do_lio(&c__5, &c__1, (char *)&bet[i__ - 1], (ftnlen)sizeof(doublereal) ); } e_rsle(); /* Report values of parameters. */ io___36.ciunit = nout; s_wsfe(&io___36); e_wsfe(); io___37.ciunit = nout; s_wsfe(&io___37); i__1 = nidim; for (i__ = 1; i__ <= i__1; ++i__) { do_fio(&c__1, (char *)&idim[i__ - 1], (ftnlen)sizeof(integer)); } e_wsfe(); io___38.ciunit = nout; s_wsfe(&io___38); i__1 = nalf; for (i__ = 1; i__ <= i__1; ++i__) { do_fio(&c__1, (char *)&alf[i__ - 1], (ftnlen)sizeof(doublereal)); } e_wsfe(); io___39.ciunit = nout; s_wsfe(&io___39); i__1 = nbet; for (i__ = 1; i__ <= i__1; ++i__) { do_fio(&c__1, (char *)&bet[i__ - 1], (ftnlen)sizeof(doublereal)); } e_wsfe(); if (! tsterr) { io___40.ciunit = nout; s_wsle(&io___40); e_wsle(); io___41.ciunit = nout; s_wsfe(&io___41); e_wsfe(); } io___42.ciunit = nout; s_wsle(&io___42); e_wsle(); io___43.ciunit = nout; s_wsfe(&io___43); do_fio(&c__1, (char *)&thresh, (ftnlen)sizeof(doublereal)); e_wsfe(); io___44.ciunit = nout; s_wsle(&io___44); e_wsle(); /* Read names of subroutines and flags which indicate */ /* whether they are to be tested. */ for (i__ = 1; i__ <= 6; ++i__) { ltest[i__ - 1] = FALSE_; /* L20: */ } L30: i__1 = s_rsfe(&io___46); if (i__1 != 0) { goto L60; } i__1 = do_fio(&c__1, snamet, (ftnlen)6); if (i__1 != 0) { goto L60; } i__1 = do_fio(&c__1, (char *)<estt, (ftnlen)sizeof(logical)); if (i__1 != 0) { goto L60; } i__1 = e_rsfe(); if (i__1 != 0) { goto L60; } for (i__ = 1; i__ <= 6; ++i__) { if (s_cmp(snamet, snames + (i__ - 1) * 6, (ftnlen)6, (ftnlen)6) == 0) { goto L50; } /* L40: */ } io___49.ciunit = nout; s_wsfe(&io___49); do_fio(&c__1, snamet, (ftnlen)6); e_wsfe(); s_stop("", (ftnlen)0); L50: ltest[i__ - 1] = ltestt; goto L30; L60: cl__1.cerr = 0; cl__1.cunit = 5; cl__1.csta = 0; f_clos(&cl__1); /* Compute EPS (the machine precision). */ eps = d_epsilon_(&c_b86); io___51.ciunit = nout; s_wsfe(&io___51); do_fio(&c__1, (char *)&eps, (ftnlen)sizeof(doublereal)); e_wsfe(); /* Check the reliability of DMMCH using exact data. */ n = 32; i__1 = n; for (j = 1; j <= i__1; ++j) { i__2 = n; for (i__ = 1; i__ <= i__2; ++i__) { /* Computing MAX */ i__3 = i__ - j + 1; ab[i__ + j * 65 - 66] = (doublereal) max(i__3,0); /* L90: */ } ab[j + 4224] = (doublereal) j; ab[(j + 65) * 65 - 65] = (doublereal) j; c__[j - 1] = 0.; /* L100: */ } i__1 = n; for (j = 1; j <= i__1; ++j) { cc[j - 1] = (doublereal) (j * ((j + 1) * j) / 2 - (j + 1) * j * (j - 1) / 3); /* L110: */ } /* CC holds the exact result. On exit from DMMCH CT holds */ /* the result computed by DMMCH. */ *(unsigned char *)transa = 'N'; *(unsigned char *)transb = 'N'; dmmch_(transa, transb, &n, &c__1, &n, &c_b96, ab, &c__65, &ab[4225], & c__65, &c_b86, c__, &c__65, ct, g, cc, &c__65, &eps, &err, &fatal, &nout, &c_true, (ftnlen)1, (ftnlen)1); same = lde_(cc, ct, &n); if (! same || err != 0.) { io___64.ciunit = nout; s_wsfe(&io___64); do_fio(&c__1, transa, (ftnlen)1); do_fio(&c__1, transb, (ftnlen)1); do_fio(&c__1, (char *)&same, (ftnlen)sizeof(logical)); do_fio(&c__1, (char *)&err, (ftnlen)sizeof(doublereal)); e_wsfe(); s_stop("", (ftnlen)0); } *(unsigned char *)transb = 'T'; dmmch_(transa, transb, &n, &c__1, &n, &c_b96, ab, &c__65, &ab[4225], & c__65, &c_b86, c__, &c__65, ct, g, cc, &c__65, &eps, &err, &fatal, &nout, &c_true, (ftnlen)1, (ftnlen)1); same = lde_(cc, ct, &n); if (! same || err != 0.) { io___65.ciunit = nout; s_wsfe(&io___65); do_fio(&c__1, transa, (ftnlen)1); do_fio(&c__1, transb, (ftnlen)1); do_fio(&c__1, (char *)&same, (ftnlen)sizeof(logical)); do_fio(&c__1, (char *)&err, (ftnlen)sizeof(doublereal)); e_wsfe(); s_stop("", (ftnlen)0); } i__1 = n; for (j = 1; j <= i__1; ++j) { ab[j + 4224] = (doublereal) (n - j + 1); ab[(j + 65) * 65 - 65] = (doublereal) (n - j + 1); /* L120: */ } i__1 = n; for (j = 1; j <= i__1; ++j) { cc[n - j] = (doublereal) (j * ((j + 1) * j) / 2 - (j + 1) * j * (j - 1) / 3); /* L130: */ } *(unsigned char *)transa = 'T'; *(unsigned char *)transb = 'N'; dmmch_(transa, transb, &n, &c__1, &n, &c_b96, ab, &c__65, &ab[4225], & c__65, &c_b86, c__, &c__65, ct, g, cc, &c__65, &eps, &err, &fatal, &nout, &c_true, (ftnlen)1, (ftnlen)1); same = lde_(cc, ct, &n); if (! same || err != 0.) { io___66.ciunit = nout; s_wsfe(&io___66); do_fio(&c__1, transa, (ftnlen)1); do_fio(&c__1, transb, (ftnlen)1); do_fio(&c__1, (char *)&same, (ftnlen)sizeof(logical)); do_fio(&c__1, (char *)&err, (ftnlen)sizeof(doublereal)); e_wsfe(); s_stop("", (ftnlen)0); } *(unsigned char *)transb = 'T'; dmmch_(transa, transb, &n, &c__1, &n, &c_b96, ab, &c__65, &ab[4225], & c__65, &c_b86, c__, &c__65, ct, g, cc, &c__65, &eps, &err, &fatal, &nout, &c_true, (ftnlen)1, (ftnlen)1); same = lde_(cc, ct, &n); if (! same || err != 0.) { io___67.ciunit = nout; s_wsfe(&io___67); do_fio(&c__1, transa, (ftnlen)1); do_fio(&c__1, transb, (ftnlen)1); do_fio(&c__1, (char *)&same, (ftnlen)sizeof(logical)); do_fio(&c__1, (char *)&err, (ftnlen)sizeof(doublereal)); e_wsfe(); s_stop("", (ftnlen)0); } /* Test each subroutine in turn. */ for (isnum = 1; isnum <= 6; ++isnum) { io___69.ciunit = nout; s_wsle(&io___69); e_wsle(); if (! ltest[isnum - 1]) { /* Subprogram is not to be tested. */ io___70.ciunit = nout; s_wsfe(&io___70); do_fio(&c__1, snames + (isnum - 1) * 6, (ftnlen)6); e_wsfe(); } else { s_copy(srnamc_1.srnamt, snames + (isnum - 1) * 6, (ftnlen)6, ( ftnlen)6); /* Test error exits. */ if (tsterr) { dchke_(&isnum, snames + (isnum - 1) * 6, &nout, (ftnlen)6); io___71.ciunit = nout; s_wsle(&io___71); e_wsle(); } /* Test computations. */ infoc_1.infot = 0; infoc_1.ok = TRUE_; fatal = FALSE_; switch (isnum) { case 1: goto L140; case 2: goto L150; case 3: goto L160; case 4: goto L160; case 5: goto L170; case 6: goto L180; } /* Test DGEMM, 01. */ L140: dchk1_(snames + (isnum - 1) * 6, &eps, &thresh, &nout, &ntra, & trace, &rewi, &fatal, &nidim, idim, &nalf, alf, &nbet, bet, &c__65, ab, aa, as, &ab[4225], bb, bs, c__, cc, cs, ct, g, (ftnlen)6); goto L190; /* Test DSYMM, 02. */ L150: dchk2_(snames + (isnum - 1) * 6, &eps, &thresh, &nout, &ntra, & trace, &rewi, &fatal, &nidim, idim, &nalf, alf, &nbet, bet, &c__65, ab, aa, as, &ab[4225], bb, bs, c__, cc, cs, ct, g, (ftnlen)6); goto L190; /* Test DTRMM, 03, DTRSM, 04. */ L160: dchk3_(snames + (isnum - 1) * 6, &eps, &thresh, &nout, &ntra, & trace, &rewi, &fatal, &nidim, idim, &nalf, alf, &c__65, ab, aa, as, &ab[4225], bb, bs, ct, g, c__, (ftnlen)6); goto L190; /* Test DSYRK, 05. */ L170: dchk4_(snames + (isnum - 1) * 6, &eps, &thresh, &nout, &ntra, & trace, &rewi, &fatal, &nidim, idim, &nalf, alf, &nbet, bet, &c__65, ab, aa, as, &ab[4225], bb, bs, c__, cc, cs, ct, g, (ftnlen)6); goto L190; /* Test DSYR2K, 06. */ L180: dchk5_(snames + (isnum - 1) * 6, &eps, &thresh, &nout, &ntra, & trace, &rewi, &fatal, &nidim, idim, &nalf, alf, &nbet, bet, &c__65, ab, aa, as, bb, bs, c__, cc, cs, ct, g, w, ( ftnlen)6); goto L190; L190: if (fatal && sfatal) { goto L210; } } /* L200: */ } io___78.ciunit = nout; s_wsfe(&io___78); e_wsfe(); goto L230; L210: io___79.ciunit = nout; s_wsfe(&io___79); e_wsfe(); goto L230; L220: io___80.ciunit = nout; s_wsfe(&io___80); e_wsfe(); L230: if (trace) { cl__1.cerr = 0; cl__1.cunit = ntra; cl__1.csta = 0; f_clos(&cl__1); } cl__1.cerr = 0; cl__1.cunit = nout; cl__1.csta = 0; f_clos(&cl__1); s_stop("", (ftnlen)0); /* End of DBLAT3. */ return 0; } /* main */ /* Subroutine */ int dchk1_(char *sname, doublereal *eps, doublereal *thresh, integer *nout, integer *ntra, logical *trace, logical *rewi, logical * fatal, integer *nidim, integer *idim, integer *nalf, doublereal *alf, integer *nbet, doublereal *bet, integer *nmax, doublereal *a, doublereal *aa, doublereal *as, doublereal *b, doublereal *bb, doublereal *bs, doublereal *c__, doublereal *cc, doublereal *cs, doublereal *ct, doublereal *g, ftnlen sname_len) { /* Initialized data */ static char ich[3] = "NTC"; /* Format strings */ static char fmt_9995[] = "(1x,i6,\002: \002,a6,\002('\002,a1,\002','\002" ",a1,\002',\002,3(i3,\002,\002),f4.1,\002, A,\002,i3,\002, B,\002" ",i3,\002,\002,f4.1,\002, \002,\002C,\002,i3,\002).\002)"; static char fmt_9994[] = "(\002 ******* FATAL ERROR - ERROR-EXIT TAKEN O" "N VALID CALL *\002,\002******\002)"; static char fmt_9998[] = "(\002 ******* FATAL ERROR - PARAMETER NUMBER" " \002,i2,\002 WAS CH\002,\002ANGED INCORRECTLY *******\002)"; static char fmt_9999[] = "(\002 \002,a6,\002 PASSED THE COMPUTATIONAL TE" "STS (\002,i6,\002 CALL\002,\002S)\002)"; static char fmt_9997[] = "(\002 \002,a6,\002 COMPLETED THE COMPUTATIONAL" " TESTS (\002,i6,\002 C\002,\002ALLS)\002,/\002 ******* BUT WITH " "MAXIMUM TEST RATIO\002,f8.2,\002 - SUSPECT *******\002)"; static char fmt_9996[] = "(\002 ******* \002,a6,\002 FAILED ON CALL NUMB" "ER:\002)"; /* System generated locals */ integer a_dim1, a_offset, b_dim1, b_offset, c_dim1, c_offset, i__1, i__2, i__3, i__4, i__5, i__6; alist al__1; /* Builtin functions */ integer s_wsfe(cilist *), do_fio(integer *, char *, ftnlen), e_wsfe(void), f_rew(alist *); /* Local variables */ integer i__, k, m, n, ia, ib, ma, mb, na, nb, nc, ik, im, in, ks, ms, ns, ica, icb, laa, lbb, lda, lcc, ldb, ldc; extern logical lde_(doublereal *, doublereal *, integer *); doublereal als, bls, err, beta; integer ldas, ldbs, ldcs; logical same, null; extern /* Subroutine */ int dmake_(char *, char *, char *, integer *, integer *, doublereal *, integer *, doublereal *, integer *, logical *, doublereal *, ftnlen, ftnlen, ftnlen); doublereal alpha; extern /* Subroutine */ int dmmch_(char *, char *, integer *, integer *, integer *, doublereal *, doublereal *, integer *, doublereal *, integer *, doublereal *, doublereal *, integer *, doublereal *, doublereal *, doublereal *, integer *, doublereal *, doublereal *, logical *, integer *, logical *, ftnlen, ftnlen), dgemm_(char *, char *, integer *, integer *, integer *, doublereal *, doublereal *, integer *, doublereal *, integer *, doublereal *, doublereal *, integer *, ftnlen, ftnlen); logical isame[13], trana, tranb; integer nargs; logical reset; extern logical lderes_(char *, char *, integer *, integer *, doublereal *, doublereal *, integer *, ftnlen, ftnlen); char tranas[1], tranbs[1], transa[1], transb[1]; doublereal errmax; /* Fortran I/O blocks */ static cilist io___124 = { 0, 0, 0, fmt_9995, 0 }; static cilist io___125 = { 0, 0, 0, fmt_9994, 0 }; static cilist io___128 = { 0, 0, 0, fmt_9998, 0 }; static cilist io___130 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___131 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___132 = { 0, 0, 0, fmt_9996, 0 }; static cilist io___133 = { 0, 0, 0, fmt_9995, 0 }; /* Tests DGEMM. */ /* Auxiliary routine for test program for Level 3 Blas. */ /* -- Written on 8-February-1989. */ /* Jack Dongarra, Argonne National Laboratory. */ /* Iain Duff, AERE Harwell. */ /* Jeremy Du Croz, Numerical Algorithms Group Ltd. */ /* Sven Hammarling, Numerical Algorithms Group Ltd. */ /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Scalars .. */ /* .. Local Arrays .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. Scalars in Common .. */ /* .. Common blocks .. */ /* .. Data statements .. */ /* Parameter adjustments */ --idim; --alf; --bet; --g; --ct; --cs; --cc; c_dim1 = *nmax; c_offset = 1 + c_dim1; c__ -= c_offset; --bs; --bb; b_dim1 = *nmax; b_offset = 1 + b_dim1; b -= b_offset; --as; --aa; a_dim1 = *nmax; a_offset = 1 + a_dim1; a -= a_offset; /* Function Body */ /* .. Executable Statements .. */ nargs = 13; nc = 0; reset = TRUE_; errmax = 0.; i__1 = *nidim; for (im = 1; im <= i__1; ++im) { m = idim[im]; i__2 = *nidim; for (in = 1; in <= i__2; ++in) { n = idim[in]; /* Set LDC to 1 more than minimum value if room. */ ldc = m; if (ldc < *nmax) { ++ldc; } /* Skip tests if not enough room. */ if (ldc > *nmax) { goto L100; } lcc = ldc * n; null = n <= 0 || m <= 0; i__3 = *nidim; for (ik = 1; ik <= i__3; ++ik) { k = idim[ik]; for (ica = 1; ica <= 3; ++ica) { *(unsigned char *)transa = *(unsigned char *)&ich[ica - 1] ; trana = *(unsigned char *)transa == 'T' || *(unsigned char *)transa == 'C'; if (trana) { ma = k; na = m; } else { ma = m; na = k; } /* Set LDA to 1 more than minimum value if room. */ lda = ma; if (lda < *nmax) { ++lda; } /* Skip tests if not enough room. */ if (lda > *nmax) { goto L80; } laa = lda * na; /* Generate the matrix A. */ dmake_("GE", " ", " ", &ma, &na, &a[a_offset], nmax, &aa[ 1], &lda, &reset, &c_b86, (ftnlen)2, (ftnlen)1, ( ftnlen)1); for (icb = 1; icb <= 3; ++icb) { *(unsigned char *)transb = *(unsigned char *)&ich[icb - 1]; tranb = *(unsigned char *)transb == 'T' || *(unsigned char *)transb == 'C'; if (tranb) { mb = n; nb = k; } else { mb = k; nb = n; } /* Set LDB to 1 more than minimum value if room. */ ldb = mb; if (ldb < *nmax) { ++ldb; } /* Skip tests if not enough room. */ if (ldb > *nmax) { goto L70; } lbb = ldb * nb; /* Generate the matrix B. */ dmake_("GE", " ", " ", &mb, &nb, &b[b_offset], nmax, & bb[1], &ldb, &reset, &c_b86, (ftnlen)2, ( ftnlen)1, (ftnlen)1); i__4 = *nalf; for (ia = 1; ia <= i__4; ++ia) { alpha = alf[ia]; i__5 = *nbet; for (ib = 1; ib <= i__5; ++ib) { beta = bet[ib]; /* Generate the matrix C. */ dmake_("GE", " ", " ", &m, &n, &c__[c_offset], nmax, &cc[1], &ldc, &reset, &c_b86, ( ftnlen)2, (ftnlen)1, (ftnlen)1); ++nc; /* Save every datum before calling the */ /* subroutine. */ *(unsigned char *)tranas = *(unsigned char *) transa; *(unsigned char *)tranbs = *(unsigned char *) transb; ms = m; ns = n; ks = k; als = alpha; i__6 = laa; for (i__ = 1; i__ <= i__6; ++i__) { as[i__] = aa[i__]; /* L10: */ } ldas = lda; i__6 = lbb; for (i__ = 1; i__ <= i__6; ++i__) { bs[i__] = bb[i__]; /* L20: */ } ldbs = ldb; bls = beta; i__6 = lcc; for (i__ = 1; i__ <= i__6; ++i__) { cs[i__] = cc[i__]; /* L30: */ } ldcs = ldc; /* Call the subroutine. */ if (*trace) { io___124.ciunit = *ntra; s_wsfe(&io___124); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof( integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, transa, (ftnlen)1); do_fio(&c__1, transb, (ftnlen)1); do_fio(&c__1, (char *)&m, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&n, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&k, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&alpha, (ftnlen) sizeof(doublereal)); do_fio(&c__1, (char *)&lda, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&ldb, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&beta, (ftnlen) sizeof(doublereal)); do_fio(&c__1, (char *)&ldc, (ftnlen) sizeof(integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } dgemm_(transa, transb, &m, &n, &k, &alpha, & aa[1], &lda, &bb[1], &ldb, &beta, &cc[ 1], &ldc, (ftnlen)1, (ftnlen)1); /* Check if error-exit was taken incorrectly. */ if (! infoc_1.ok) { io___125.ciunit = *nout; s_wsfe(&io___125); e_wsfe(); *fatal = TRUE_; goto L120; } /* See what data changed inside subroutines. */ isame[0] = *(unsigned char *)transa == *( unsigned char *)tranas; isame[1] = *(unsigned char *)transb == *( unsigned char *)tranbs; isame[2] = ms == m; isame[3] = ns == n; isame[4] = ks == k; isame[5] = als == alpha; isame[6] = lde_(&as[1], &aa[1], &laa); isame[7] = ldas == lda; isame[8] = lde_(&bs[1], &bb[1], &lbb); isame[9] = ldbs == ldb; isame[10] = bls == beta; if (null) { isame[11] = lde_(&cs[1], &cc[1], &lcc); } else { isame[11] = lderes_("GE", " ", &m, &n, & cs[1], &cc[1], &ldc, (ftnlen)2, ( ftnlen)1); } isame[12] = ldcs == ldc; /* If data was incorrectly changed, report */ /* and return. */ same = TRUE_; i__6 = nargs; for (i__ = 1; i__ <= i__6; ++i__) { same = same && isame[i__ - 1]; if (! isame[i__ - 1]) { io___128.ciunit = *nout; s_wsfe(&io___128); do_fio(&c__1, (char *)&i__, (ftnlen) sizeof(integer)); e_wsfe(); } /* L40: */ } if (! same) { *fatal = TRUE_; goto L120; } if (! null) { /* Check the result. */ dmmch_(transa, transb, &m, &n, &k, &alpha, &a[a_offset], nmax, &b[b_offset], nmax, &beta, &c__[c_offset], nmax, &ct[1], &g[1], &cc[1], &ldc, eps, &err, fatal, nout, &c_true, (ftnlen)1, (ftnlen)1); errmax = max(errmax,err); /* If got really bad answer, report and */ /* return. */ if (*fatal) { goto L120; } } /* L50: */ } /* L60: */ } L70: ; } L80: ; } /* L90: */ } L100: ; } /* L110: */ } /* Report result. */ if (errmax < *thresh) { io___130.ciunit = *nout; s_wsfe(&io___130); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); e_wsfe(); } else { io___131.ciunit = *nout; s_wsfe(&io___131); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&errmax, (ftnlen)sizeof(doublereal)); e_wsfe(); } goto L130; L120: io___132.ciunit = *nout; s_wsfe(&io___132); do_fio(&c__1, sname, (ftnlen)6); e_wsfe(); io___133.ciunit = *nout; s_wsfe(&io___133); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, transa, (ftnlen)1); do_fio(&c__1, transb, (ftnlen)1); do_fio(&c__1, (char *)&m, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&k, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&alpha, (ftnlen)sizeof(doublereal)); do_fio(&c__1, (char *)&lda, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&ldb, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&beta, (ftnlen)sizeof(doublereal)); do_fio(&c__1, (char *)&ldc, (ftnlen)sizeof(integer)); e_wsfe(); L130: return 0; /* End of DCHK1. */ } /* dchk1_ */ /* Subroutine */ int dchk2_(char *sname, doublereal *eps, doublereal *thresh, integer *nout, integer *ntra, logical *trace, logical *rewi, logical * fatal, integer *nidim, integer *idim, integer *nalf, doublereal *alf, integer *nbet, doublereal *bet, integer *nmax, doublereal *a, doublereal *aa, doublereal *as, doublereal *b, doublereal *bb, doublereal *bs, doublereal *c__, doublereal *cc, doublereal *cs, doublereal *ct, doublereal *g, ftnlen sname_len) { /* Initialized data */ static char ichs[2] = "LR"; static char ichu[2] = "UL"; /* Format strings */ static char fmt_9995[] = "(1x,i6,\002: \002,a6,\002(\002,2(\002'\002,a1" ",\002',\002),2(i3,\002,\002),f4.1,\002, A,\002,i3,\002, B,\002,i" "3,\002,\002,f4.1,\002, C,\002,i3,\002) \002,\002 .\002)"; static char fmt_9994[] = "(\002 ******* FATAL ERROR - ERROR-EXIT TAKEN O" "N VALID CALL *\002,\002******\002)"; static char fmt_9998[] = "(\002 ******* FATAL ERROR - PARAMETER NUMBER" " \002,i2,\002 WAS CH\002,\002ANGED INCORRECTLY *******\002)"; static char fmt_9999[] = "(\002 \002,a6,\002 PASSED THE COMPUTATIONAL TE" "STS (\002,i6,\002 CALL\002,\002S)\002)"; static char fmt_9997[] = "(\002 \002,a6,\002 COMPLETED THE COMPUTATIONAL" " TESTS (\002,i6,\002 C\002,\002ALLS)\002,/\002 ******* BUT WITH " "MAXIMUM TEST RATIO\002,f8.2,\002 - SUSPECT *******\002)"; static char fmt_9996[] = "(\002 ******* \002,a6,\002 FAILED ON CALL NUMB" "ER:\002)"; /* System generated locals */ integer a_dim1, a_offset, b_dim1, b_offset, c_dim1, c_offset, i__1, i__2, i__3, i__4, i__5; alist al__1; /* Builtin functions */ integer s_wsfe(cilist *), do_fio(integer *, char *, ftnlen), e_wsfe(void), f_rew(alist *); /* Local variables */ integer i__, m, n, ia, ib, na, nc, im, in, ms, ns, laa, lbb, lda, lcc, ldb, ldc; extern logical lde_(doublereal *, doublereal *, integer *); integer ics; doublereal als, bls; integer icu; doublereal err, beta; integer ldas, ldbs, ldcs; logical same; char side[1]; logical left, null; char uplo[1]; extern /* Subroutine */ int dmake_(char *, char *, char *, integer *, integer *, doublereal *, integer *, doublereal *, integer *, logical *, doublereal *, ftnlen, ftnlen, ftnlen); doublereal alpha; extern /* Subroutine */ int dmmch_(char *, char *, integer *, integer *, integer *, doublereal *, doublereal *, integer *, doublereal *, integer *, doublereal *, doublereal *, integer *, doublereal *, doublereal *, doublereal *, integer *, doublereal *, doublereal *, logical *, integer *, logical *, ftnlen, ftnlen); logical isame[13]; char sides[1]; integer nargs; logical reset; extern /* Subroutine */ int dsymm_(char *, char *, integer *, integer *, doublereal *, doublereal *, integer *, doublereal *, integer *, doublereal *, doublereal *, integer *, ftnlen, ftnlen); char uplos[1]; extern logical lderes_(char *, char *, integer *, integer *, doublereal *, doublereal *, integer *, ftnlen, ftnlen); doublereal errmax; /* Fortran I/O blocks */ static cilist io___171 = { 0, 0, 0, fmt_9995, 0 }; static cilist io___172 = { 0, 0, 0, fmt_9994, 0 }; static cilist io___175 = { 0, 0, 0, fmt_9998, 0 }; static cilist io___177 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___178 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___179 = { 0, 0, 0, fmt_9996, 0 }; static cilist io___180 = { 0, 0, 0, fmt_9995, 0 }; /* Tests DSYMM. */ /* Auxiliary routine for test program for Level 3 Blas. */ /* -- Written on 8-February-1989. */ /* Jack Dongarra, Argonne National Laboratory. */ /* Iain Duff, AERE Harwell. */ /* Jeremy Du Croz, Numerical Algorithms Group Ltd. */ /* Sven Hammarling, Numerical Algorithms Group Ltd. */ /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Scalars .. */ /* .. Local Arrays .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. Scalars in Common .. */ /* .. Common blocks .. */ /* .. Data statements .. */ /* Parameter adjustments */ --idim; --alf; --bet; --g; --ct; --cs; --cc; c_dim1 = *nmax; c_offset = 1 + c_dim1; c__ -= c_offset; --bs; --bb; b_dim1 = *nmax; b_offset = 1 + b_dim1; b -= b_offset; --as; --aa; a_dim1 = *nmax; a_offset = 1 + a_dim1; a -= a_offset; /* Function Body */ /* .. Executable Statements .. */ nargs = 12; nc = 0; reset = TRUE_; errmax = 0.; i__1 = *nidim; for (im = 1; im <= i__1; ++im) { m = idim[im]; i__2 = *nidim; for (in = 1; in <= i__2; ++in) { n = idim[in]; /* Set LDC to 1 more than minimum value if room. */ ldc = m; if (ldc < *nmax) { ++ldc; } /* Skip tests if not enough room. */ if (ldc > *nmax) { goto L90; } lcc = ldc * n; null = n <= 0 || m <= 0; /* Set LDB to 1 more than minimum value if room. */ ldb = m; if (ldb < *nmax) { ++ldb; } /* Skip tests if not enough room. */ if (ldb > *nmax) { goto L90; } lbb = ldb * n; /* Generate the matrix B. */ dmake_("GE", " ", " ", &m, &n, &b[b_offset], nmax, &bb[1], &ldb, & reset, &c_b86, (ftnlen)2, (ftnlen)1, (ftnlen)1); for (ics = 1; ics <= 2; ++ics) { *(unsigned char *)side = *(unsigned char *)&ichs[ics - 1]; left = *(unsigned char *)side == 'L'; if (left) { na = m; } else { na = n; } /* Set LDA to 1 more than minimum value if room. */ lda = na; if (lda < *nmax) { ++lda; } /* Skip tests if not enough room. */ if (lda > *nmax) { goto L80; } laa = lda * na; for (icu = 1; icu <= 2; ++icu) { *(unsigned char *)uplo = *(unsigned char *)&ichu[icu - 1]; /* Generate the symmetric matrix A. */ dmake_("SY", uplo, " ", &na, &na, &a[a_offset], nmax, &aa[ 1], &lda, &reset, &c_b86, (ftnlen)2, (ftnlen)1, ( ftnlen)1); i__3 = *nalf; for (ia = 1; ia <= i__3; ++ia) { alpha = alf[ia]; i__4 = *nbet; for (ib = 1; ib <= i__4; ++ib) { beta = bet[ib]; /* Generate the matrix C. */ dmake_("GE", " ", " ", &m, &n, &c__[c_offset], nmax, &cc[1], &ldc, &reset, &c_b86, ( ftnlen)2, (ftnlen)1, (ftnlen)1); ++nc; /* Save every datum before calling the */ /* subroutine. */ *(unsigned char *)sides = *(unsigned char *)side; *(unsigned char *)uplos = *(unsigned char *)uplo; ms = m; ns = n; als = alpha; i__5 = laa; for (i__ = 1; i__ <= i__5; ++i__) { as[i__] = aa[i__]; /* L10: */ } ldas = lda; i__5 = lbb; for (i__ = 1; i__ <= i__5; ++i__) { bs[i__] = bb[i__]; /* L20: */ } ldbs = ldb; bls = beta; i__5 = lcc; for (i__ = 1; i__ <= i__5; ++i__) { cs[i__] = cc[i__]; /* L30: */ } ldcs = ldc; /* Call the subroutine. */ if (*trace) { io___171.ciunit = *ntra; s_wsfe(&io___171); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof( integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, side, (ftnlen)1); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, (char *)&m, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&n, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&alpha, (ftnlen)sizeof( doublereal)); do_fio(&c__1, (char *)&lda, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&ldb, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&beta, (ftnlen)sizeof( doublereal)); do_fio(&c__1, (char *)&ldc, (ftnlen)sizeof( integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } dsymm_(side, uplo, &m, &n, &alpha, &aa[1], &lda, & bb[1], &ldb, &beta, &cc[1], &ldc, (ftnlen) 1, (ftnlen)1); /* Check if error-exit was taken incorrectly. */ if (! infoc_1.ok) { io___172.ciunit = *nout; s_wsfe(&io___172); e_wsfe(); *fatal = TRUE_; goto L110; } /* See what data changed inside subroutines. */ isame[0] = *(unsigned char *)sides == *(unsigned char *)side; isame[1] = *(unsigned char *)uplos == *(unsigned char *)uplo; isame[2] = ms == m; isame[3] = ns == n; isame[4] = als == alpha; isame[5] = lde_(&as[1], &aa[1], &laa); isame[6] = ldas == lda; isame[7] = lde_(&bs[1], &bb[1], &lbb); isame[8] = ldbs == ldb; isame[9] = bls == beta; if (null) { isame[10] = lde_(&cs[1], &cc[1], &lcc); } else { isame[10] = lderes_("GE", " ", &m, &n, &cs[1], &cc[1], &ldc, (ftnlen)2, (ftnlen)1); } isame[11] = ldcs == ldc; /* If data was incorrectly changed, report and */ /* return. */ same = TRUE_; i__5 = nargs; for (i__ = 1; i__ <= i__5; ++i__) { same = same && isame[i__ - 1]; if (! isame[i__ - 1]) { io___175.ciunit = *nout; s_wsfe(&io___175); do_fio(&c__1, (char *)&i__, (ftnlen) sizeof(integer)); e_wsfe(); } /* L40: */ } if (! same) { *fatal = TRUE_; goto L110; } if (! null) { /* Check the result. */ if (left) { dmmch_("N", "N", &m, &n, &m, &alpha, &a[ a_offset], nmax, &b[b_offset], nmax, &beta, &c__[c_offset], nmax, &ct[1], &g[1], &cc[1], &ldc, eps, &err, fatal, nout, &c_true, ( ftnlen)1, (ftnlen)1); } else { dmmch_("N", "N", &m, &n, &n, &alpha, &b[ b_offset], nmax, &a[a_offset], nmax, &beta, &c__[c_offset], nmax, &ct[1], &g[1], &cc[1], &ldc, eps, &err, fatal, nout, &c_true, ( ftnlen)1, (ftnlen)1); } errmax = max(errmax,err); /* If got really bad answer, report and */ /* return. */ if (*fatal) { goto L110; } } /* L50: */ } /* L60: */ } /* L70: */ } L80: ; } L90: ; } /* L100: */ } /* Report result. */ if (errmax < *thresh) { io___177.ciunit = *nout; s_wsfe(&io___177); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); e_wsfe(); } else { io___178.ciunit = *nout; s_wsfe(&io___178); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&errmax, (ftnlen)sizeof(doublereal)); e_wsfe(); } goto L120; L110: io___179.ciunit = *nout; s_wsfe(&io___179); do_fio(&c__1, sname, (ftnlen)6); e_wsfe(); io___180.ciunit = *nout; s_wsfe(&io___180); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, side, (ftnlen)1); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, (char *)&m, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&alpha, (ftnlen)sizeof(doublereal)); do_fio(&c__1, (char *)&lda, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&ldb, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&beta, (ftnlen)sizeof(doublereal)); do_fio(&c__1, (char *)&ldc, (ftnlen)sizeof(integer)); e_wsfe(); L120: return 0; /* End of DCHK2. */ } /* dchk2_ */ /* Subroutine */ int dchk3_(char *sname, doublereal *eps, doublereal *thresh, integer *nout, integer *ntra, logical *trace, logical *rewi, logical * fatal, integer *nidim, integer *idim, integer *nalf, doublereal *alf, integer *nmax, doublereal *a, doublereal *aa, doublereal *as, doublereal *b, doublereal *bb, doublereal *bs, doublereal *ct, doublereal *g, doublereal *c__, ftnlen sname_len) { /* Initialized data */ static char ichu[2] = "UL"; static char icht[3] = "NTC"; static char ichd[2] = "UN"; static char ichs[2] = "LR"; /* Format strings */ static char fmt_9995[] = "(1x,i6,\002: \002,a6,\002(\002,4(\002'\002,a1" ",\002',\002),2(i3,\002,\002),f4.1,\002, A,\002,i3,\002, B,\002,i" "3,\002) .\002)"; static char fmt_9994[] = "(\002 ******* FATAL ERROR - ERROR-EXIT TAKEN O" "N VALID CALL *\002,\002******\002)"; static char fmt_9998[] = "(\002 ******* FATAL ERROR - PARAMETER NUMBER" " \002,i2,\002 WAS CH\002,\002ANGED INCORRECTLY *******\002)"; static char fmt_9999[] = "(\002 \002,a6,\002 PASSED THE COMPUTATIONAL TE" "STS (\002,i6,\002 CALL\002,\002S)\002)"; static char fmt_9997[] = "(\002 \002,a6,\002 COMPLETED THE COMPUTATIONAL" " TESTS (\002,i6,\002 C\002,\002ALLS)\002,/\002 ******* BUT WITH " "MAXIMUM TEST RATIO\002,f8.2,\002 - SUSPECT *******\002)"; static char fmt_9996[] = "(\002 ******* \002,a6,\002 FAILED ON CALL NUMB" "ER:\002)"; /* System generated locals */ integer a_dim1, a_offset, b_dim1, b_offset, c_dim1, c_offset, i__1, i__2, i__3, i__4, i__5; alist al__1; /* Builtin functions */ integer s_cmp(const char *, const char *, ftnlen, ftnlen), s_wsfe(cilist *), do_fio( integer *, char *, ftnlen), e_wsfe(void), f_rew(alist *); /* Local variables */ integer i__, j, m, n, ia, na, nc, im, in, ms, ns, laa, icd, lbb, lda, ldb; extern logical lde_(doublereal *, doublereal *, integer *); integer ics; doublereal als; integer ict, icu; doublereal err; char diag[1]; integer ldas, ldbs; logical same; char side[1]; logical left, null; char uplo[1]; extern /* Subroutine */ int dmake_(char *, char *, char *, integer *, integer *, doublereal *, integer *, doublereal *, integer *, logical *, doublereal *, ftnlen, ftnlen, ftnlen); doublereal alpha; char diags[1]; extern /* Subroutine */ int dmmch_(char *, char *, integer *, integer *, integer *, doublereal *, doublereal *, integer *, doublereal *, integer *, doublereal *, doublereal *, integer *, doublereal *, doublereal *, doublereal *, integer *, doublereal *, doublereal *, logical *, integer *, logical *, ftnlen, ftnlen); logical isame[13]; char sides[1]; integer nargs; logical reset; extern /* Subroutine */ int dtrmm_(char *, char *, char *, char *, integer *, integer *, doublereal *, doublereal *, integer *, doublereal *, integer *, ftnlen, ftnlen, ftnlen, ftnlen), dtrsm_( char *, char *, char *, char *, integer *, integer *, doublereal * , doublereal *, integer *, doublereal *, integer *, ftnlen, ftnlen, ftnlen, ftnlen); char uplos[1]; extern logical lderes_(char *, char *, integer *, integer *, doublereal *, doublereal *, integer *, ftnlen, ftnlen); char tranas[1], transa[1]; doublereal errmax; /* Fortran I/O blocks */ static cilist io___221 = { 0, 0, 0, fmt_9995, 0 }; static cilist io___222 = { 0, 0, 0, fmt_9995, 0 }; static cilist io___223 = { 0, 0, 0, fmt_9994, 0 }; static cilist io___226 = { 0, 0, 0, fmt_9998, 0 }; static cilist io___228 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___229 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___230 = { 0, 0, 0, fmt_9996, 0 }; static cilist io___231 = { 0, 0, 0, fmt_9995, 0 }; /* Tests DTRMM and DTRSM. */ /* Auxiliary routine for test program for Level 3 Blas. */ /* -- Written on 8-February-1989. */ /* Jack Dongarra, Argonne National Laboratory. */ /* Iain Duff, AERE Harwell. */ /* Jeremy Du Croz, Numerical Algorithms Group Ltd. */ /* Sven Hammarling, Numerical Algorithms Group Ltd. */ /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Scalars .. */ /* .. Local Arrays .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. Scalars in Common .. */ /* .. Common blocks .. */ /* .. Data statements .. */ /* Parameter adjustments */ --idim; --alf; c_dim1 = *nmax; c_offset = 1 + c_dim1; c__ -= c_offset; --g; --ct; --bs; --bb; b_dim1 = *nmax; b_offset = 1 + b_dim1; b -= b_offset; --as; --aa; a_dim1 = *nmax; a_offset = 1 + a_dim1; a -= a_offset; /* Function Body */ /* .. Executable Statements .. */ nargs = 11; nc = 0; reset = TRUE_; errmax = 0.; /* Set up zero matrix for DMMCH. */ i__1 = *nmax; for (j = 1; j <= i__1; ++j) { i__2 = *nmax; for (i__ = 1; i__ <= i__2; ++i__) { c__[i__ + j * c_dim1] = 0.; /* L10: */ } /* L20: */ } i__1 = *nidim; for (im = 1; im <= i__1; ++im) { m = idim[im]; i__2 = *nidim; for (in = 1; in <= i__2; ++in) { n = idim[in]; /* Set LDB to 1 more than minimum value if room. */ ldb = m; if (ldb < *nmax) { ++ldb; } /* Skip tests if not enough room. */ if (ldb > *nmax) { goto L130; } lbb = ldb * n; null = m <= 0 || n <= 0; for (ics = 1; ics <= 2; ++ics) { *(unsigned char *)side = *(unsigned char *)&ichs[ics - 1]; left = *(unsigned char *)side == 'L'; if (left) { na = m; } else { na = n; } /* Set LDA to 1 more than minimum value if room. */ lda = na; if (lda < *nmax) { ++lda; } /* Skip tests if not enough room. */ if (lda > *nmax) { goto L130; } laa = lda * na; for (icu = 1; icu <= 2; ++icu) { *(unsigned char *)uplo = *(unsigned char *)&ichu[icu - 1]; for (ict = 1; ict <= 3; ++ict) { *(unsigned char *)transa = *(unsigned char *)&icht[ ict - 1]; for (icd = 1; icd <= 2; ++icd) { *(unsigned char *)diag = *(unsigned char *)&ichd[ icd - 1]; i__3 = *nalf; for (ia = 1; ia <= i__3; ++ia) { alpha = alf[ia]; /* Generate the matrix A. */ dmake_("TR", uplo, diag, &na, &na, &a[ a_offset], nmax, &aa[1], &lda, &reset, &c_b86, (ftnlen)2, (ftnlen)1, ( ftnlen)1); /* Generate the matrix B. */ dmake_("GE", " ", " ", &m, &n, &b[b_offset], nmax, &bb[1], &ldb, &reset, &c_b86, ( ftnlen)2, (ftnlen)1, (ftnlen)1); ++nc; /* Save every datum before calling the */ /* subroutine. */ *(unsigned char *)sides = *(unsigned char *) side; *(unsigned char *)uplos = *(unsigned char *) uplo; *(unsigned char *)tranas = *(unsigned char *) transa; *(unsigned char *)diags = *(unsigned char *) diag; ms = m; ns = n; als = alpha; i__4 = laa; for (i__ = 1; i__ <= i__4; ++i__) { as[i__] = aa[i__]; /* L30: */ } ldas = lda; i__4 = lbb; for (i__ = 1; i__ <= i__4; ++i__) { bs[i__] = bb[i__]; /* L40: */ } ldbs = ldb; /* Call the subroutine. */ if (s_cmp(sname + 3, "MM", (ftnlen)2, (ftnlen) 2) == 0) { if (*trace) { io___221.ciunit = *ntra; s_wsfe(&io___221); do_fio(&c__1, (char *)&nc, (ftnlen) sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, side, (ftnlen)1); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, transa, (ftnlen)1); do_fio(&c__1, diag, (ftnlen)1); do_fio(&c__1, (char *)&m, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&n, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&alpha, (ftnlen) sizeof(doublereal)); do_fio(&c__1, (char *)&lda, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&ldb, (ftnlen) sizeof(integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } dtrmm_(side, uplo, transa, diag, &m, &n, & alpha, &aa[1], &lda, &bb[1], &ldb, (ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); } else if (s_cmp(sname + 3, "SM", (ftnlen)2, ( ftnlen)2) == 0) { if (*trace) { io___222.ciunit = *ntra; s_wsfe(&io___222); do_fio(&c__1, (char *)&nc, (ftnlen) sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, side, (ftnlen)1); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, transa, (ftnlen)1); do_fio(&c__1, diag, (ftnlen)1); do_fio(&c__1, (char *)&m, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&n, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&alpha, (ftnlen) sizeof(doublereal)); do_fio(&c__1, (char *)&lda, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&ldb, (ftnlen) sizeof(integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } dtrsm_(side, uplo, transa, diag, &m, &n, & alpha, &aa[1], &lda, &bb[1], &ldb, (ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); } /* Check if error-exit was taken incorrectly. */ if (! infoc_1.ok) { io___223.ciunit = *nout; s_wsfe(&io___223); e_wsfe(); *fatal = TRUE_; goto L150; } /* See what data changed inside subroutines. */ isame[0] = *(unsigned char *)sides == *( unsigned char *)side; isame[1] = *(unsigned char *)uplos == *( unsigned char *)uplo; isame[2] = *(unsigned char *)tranas == *( unsigned char *)transa; isame[3] = *(unsigned char *)diags == *( unsigned char *)diag; isame[4] = ms == m; isame[5] = ns == n; isame[6] = als == alpha; isame[7] = lde_(&as[1], &aa[1], &laa); isame[8] = ldas == lda; if (null) { isame[9] = lde_(&bs[1], &bb[1], &lbb); } else { isame[9] = lderes_("GE", " ", &m, &n, &bs[ 1], &bb[1], &ldb, (ftnlen)2, ( ftnlen)1); } isame[10] = ldbs == ldb; /* If data was incorrectly changed, report and */ /* return. */ same = TRUE_; i__4 = nargs; for (i__ = 1; i__ <= i__4; ++i__) { same = same && isame[i__ - 1]; if (! isame[i__ - 1]) { io___226.ciunit = *nout; s_wsfe(&io___226); do_fio(&c__1, (char *)&i__, (ftnlen) sizeof(integer)); e_wsfe(); } /* L50: */ } if (! same) { *fatal = TRUE_; goto L150; } if (! null) { if (s_cmp(sname + 3, "MM", (ftnlen)2, ( ftnlen)2) == 0) { /* Check the result. */ if (left) { dmmch_(transa, "N", &m, &n, &m, & alpha, &a[a_offset], nmax, &b[b_offset], nmax, & c_b86, &c__[c_offset], nmax, &ct[1], &g[1], &bb[ 1], &ldb, eps, &err, fatal, nout, &c_true, ( ftnlen)1, (ftnlen)1); } else { dmmch_("N", transa, &m, &n, &n, & alpha, &b[b_offset], nmax, &a[a_offset], nmax, & c_b86, &c__[c_offset], nmax, &ct[1], &g[1], &bb[ 1], &ldb, eps, &err, fatal, nout, &c_true, ( ftnlen)1, (ftnlen)1); } } else if (s_cmp(sname + 3, "SM", (ftnlen) 2, (ftnlen)2) == 0) { /* Compute approximation to original */ /* matrix. */ i__4 = n; for (j = 1; j <= i__4; ++j) { i__5 = m; for (i__ = 1; i__ <= i__5; ++i__) { c__[i__ + j * c_dim1] = bb[i__ + (j - 1) * ldb]; bb[i__ + (j - 1) * ldb] = alpha * b[i__ + j * b_dim1]; /* L60: */ } /* L70: */ } if (left) { dmmch_(transa, "N", &m, &n, &m, & c_b96, &a[a_offset], nmax, &c__[c_offset], nmax, & c_b86, &b[b_offset], nmax, &ct[1], &g[1], &bb[1], & ldb, eps, &err, fatal, nout, &c_false, (ftnlen)1, (ftnlen)1); } else { dmmch_("N", transa, &m, &n, &n, & c_b96, &c__[c_offset], nmax, &a[a_offset], nmax, &c_b86, &b[b_offset], nmax, &ct[1], &g[1], &bb[ 1], &ldb, eps, &err, fatal, nout, &c_false, ( ftnlen)1, (ftnlen)1); } } errmax = max(errmax,err); /* If got really bad answer, report and */ /* return. */ if (*fatal) { goto L150; } } /* L80: */ } /* L90: */ } /* L100: */ } /* L110: */ } /* L120: */ } L130: ; } /* L140: */ } /* Report result. */ if (errmax < *thresh) { io___228.ciunit = *nout; s_wsfe(&io___228); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); e_wsfe(); } else { io___229.ciunit = *nout; s_wsfe(&io___229); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&errmax, (ftnlen)sizeof(doublereal)); e_wsfe(); } goto L160; L150: io___230.ciunit = *nout; s_wsfe(&io___230); do_fio(&c__1, sname, (ftnlen)6); e_wsfe(); io___231.ciunit = *nout; s_wsfe(&io___231); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, side, (ftnlen)1); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, transa, (ftnlen)1); do_fio(&c__1, diag, (ftnlen)1); do_fio(&c__1, (char *)&m, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&alpha, (ftnlen)sizeof(doublereal)); do_fio(&c__1, (char *)&lda, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&ldb, (ftnlen)sizeof(integer)); e_wsfe(); L160: return 0; /* End of DCHK3. */ } /* dchk3_ */ /* Subroutine */ int dchk4_(char *sname, doublereal *eps, doublereal *thresh, integer *nout, integer *ntra, logical *trace, logical *rewi, logical * fatal, integer *nidim, integer *idim, integer *nalf, doublereal *alf, integer *nbet, doublereal *bet, integer *nmax, doublereal *a, doublereal *aa, doublereal *as, doublereal *b, doublereal *bb, doublereal *bs, doublereal *c__, doublereal *cc, doublereal *cs, doublereal *ct, doublereal *g, ftnlen sname_len) { /* Initialized data */ static char icht[3] = "NTC"; static char ichu[2] = "UL"; /* Format strings */ static char fmt_9994[] = "(1x,i6,\002: \002,a6,\002(\002,2(\002'\002,a1" ",\002',\002),2(i3,\002,\002),f4.1,\002, A,\002,i3,\002,\002,f4.1," "\002, C,\002,i3,\002) .\002)"; static char fmt_9993[] = "(\002 ******* FATAL ERROR - ERROR-EXIT TAKEN O" "N VALID CALL *\002,\002******\002)"; static char fmt_9998[] = "(\002 ******* FATAL ERROR - PARAMETER NUMBER" " \002,i2,\002 WAS CH\002,\002ANGED INCORRECTLY *******\002)"; static char fmt_9999[] = "(\002 \002,a6,\002 PASSED THE COMPUTATIONAL TE" "STS (\002,i6,\002 CALL\002,\002S)\002)"; static char fmt_9997[] = "(\002 \002,a6,\002 COMPLETED THE COMPUTATIONAL" " TESTS (\002,i6,\002 C\002,\002ALLS)\002,/\002 ******* BUT WITH " "MAXIMUM TEST RATIO\002,f8.2,\002 - SUSPECT *******\002)"; static char fmt_9995[] = "(\002 THESE ARE THE RESULTS FOR COLUMN" " \002,i3)"; static char fmt_9996[] = "(\002 ******* \002,a6,\002 FAILED ON CALL NUMB" "ER:\002)"; /* System generated locals */ integer a_dim1, a_offset, b_dim1, b_offset, c_dim1, c_offset, i__1, i__2, i__3, i__4, i__5; alist al__1; /* Builtin functions */ integer s_wsfe(cilist *), do_fio(integer *, char *, ftnlen), e_wsfe(void), f_rew(alist *); /* Local variables */ integer i__, j, k, n, ia, ib, jc, ma, na, nc, ik, in, jj, lj, ks, ns, laa, lda, lcc, ldc; extern logical lde_(doublereal *, doublereal *, integer *); doublereal als; integer ict, icu; doublereal err, beta; integer ldas, ldcs; logical same; doublereal bets; logical tran, null; char uplo[1]; extern /* Subroutine */ int dmake_(char *, char *, char *, integer *, integer *, doublereal *, integer *, doublereal *, integer *, logical *, doublereal *, ftnlen, ftnlen, ftnlen); doublereal alpha; extern /* Subroutine */ int dmmch_(char *, char *, integer *, integer *, integer *, doublereal *, doublereal *, integer *, doublereal *, integer *, doublereal *, doublereal *, integer *, doublereal *, doublereal *, doublereal *, integer *, doublereal *, doublereal *, logical *, integer *, logical *, ftnlen, ftnlen); logical isame[13]; integer nargs; logical reset; char trans[1]; logical upper; extern /* Subroutine */ int dsyrk_(char *, char *, integer *, integer *, doublereal *, doublereal *, integer *, doublereal *, doublereal *, integer *, ftnlen, ftnlen); char uplos[1]; extern logical lderes_(char *, char *, integer *, integer *, doublereal *, doublereal *, integer *, ftnlen, ftnlen); doublereal errmax; char transs[1]; /* Fortran I/O blocks */ static cilist io___268 = { 0, 0, 0, fmt_9994, 0 }; static cilist io___269 = { 0, 0, 0, fmt_9993, 0 }; static cilist io___272 = { 0, 0, 0, fmt_9998, 0 }; static cilist io___278 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___279 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___280 = { 0, 0, 0, fmt_9995, 0 }; static cilist io___281 = { 0, 0, 0, fmt_9996, 0 }; static cilist io___282 = { 0, 0, 0, fmt_9994, 0 }; /* Tests DSYRK. */ /* Auxiliary routine for test program for Level 3 Blas. */ /* -- Written on 8-February-1989. */ /* Jack Dongarra, Argonne National Laboratory. */ /* Iain Duff, AERE Harwell. */ /* Jeremy Du Croz, Numerical Algorithms Group Ltd. */ /* Sven Hammarling, Numerical Algorithms Group Ltd. */ /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Scalars .. */ /* .. Local Arrays .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. Scalars in Common .. */ /* .. Common blocks .. */ /* .. Data statements .. */ /* Parameter adjustments */ --idim; --alf; --bet; --g; --ct; --cs; --cc; c_dim1 = *nmax; c_offset = 1 + c_dim1; c__ -= c_offset; --bs; --bb; b_dim1 = *nmax; b_offset = 1 + b_dim1; b -= b_offset; --as; --aa; a_dim1 = *nmax; a_offset = 1 + a_dim1; a -= a_offset; /* Function Body */ /* .. Executable Statements .. */ nargs = 10; nc = 0; reset = TRUE_; errmax = 0.; i__1 = *nidim; for (in = 1; in <= i__1; ++in) { n = idim[in]; /* Set LDC to 1 more than minimum value if room. */ ldc = n; if (ldc < *nmax) { ++ldc; } /* Skip tests if not enough room. */ if (ldc > *nmax) { goto L100; } lcc = ldc * n; null = n <= 0; i__2 = *nidim; for (ik = 1; ik <= i__2; ++ik) { k = idim[ik]; for (ict = 1; ict <= 3; ++ict) { *(unsigned char *)trans = *(unsigned char *)&icht[ict - 1]; tran = *(unsigned char *)trans == 'T' || *(unsigned char *) trans == 'C'; if (tran) { ma = k; na = n; } else { ma = n; na = k; } /* Set LDA to 1 more than minimum value if room. */ lda = ma; if (lda < *nmax) { ++lda; } /* Skip tests if not enough room. */ if (lda > *nmax) { goto L80; } laa = lda * na; /* Generate the matrix A. */ dmake_("GE", " ", " ", &ma, &na, &a[a_offset], nmax, &aa[1], & lda, &reset, &c_b86, (ftnlen)2, (ftnlen)1, (ftnlen)1); for (icu = 1; icu <= 2; ++icu) { *(unsigned char *)uplo = *(unsigned char *)&ichu[icu - 1]; upper = *(unsigned char *)uplo == 'U'; i__3 = *nalf; for (ia = 1; ia <= i__3; ++ia) { alpha = alf[ia]; i__4 = *nbet; for (ib = 1; ib <= i__4; ++ib) { beta = bet[ib]; /* Generate the matrix C. */ dmake_("SY", uplo, " ", &n, &n, &c__[c_offset], nmax, &cc[1], &ldc, &reset, &c_b86, ( ftnlen)2, (ftnlen)1, (ftnlen)1); ++nc; /* Save every datum before calling the subroutine. */ *(unsigned char *)uplos = *(unsigned char *)uplo; *(unsigned char *)transs = *(unsigned char *) trans; ns = n; ks = k; als = alpha; i__5 = laa; for (i__ = 1; i__ <= i__5; ++i__) { as[i__] = aa[i__]; /* L10: */ } ldas = lda; bets = beta; i__5 = lcc; for (i__ = 1; i__ <= i__5; ++i__) { cs[i__] = cc[i__]; /* L20: */ } ldcs = ldc; /* Call the subroutine. */ if (*trace) { io___268.ciunit = *ntra; s_wsfe(&io___268); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof( integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&k, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&alpha, (ftnlen)sizeof( doublereal)); do_fio(&c__1, (char *)&lda, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&beta, (ftnlen)sizeof( doublereal)); do_fio(&c__1, (char *)&ldc, (ftnlen)sizeof( integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } dsyrk_(uplo, trans, &n, &k, &alpha, &aa[1], &lda, &beta, &cc[1], &ldc, (ftnlen)1, (ftnlen)1) ; /* Check if error-exit was taken incorrectly. */ if (! infoc_1.ok) { io___269.ciunit = *nout; s_wsfe(&io___269); e_wsfe(); *fatal = TRUE_; goto L120; } /* See what data changed inside subroutines. */ isame[0] = *(unsigned char *)uplos == *(unsigned char *)uplo; isame[1] = *(unsigned char *)transs == *(unsigned char *)trans; isame[2] = ns == n; isame[3] = ks == k; isame[4] = als == alpha; isame[5] = lde_(&as[1], &aa[1], &laa); isame[6] = ldas == lda; isame[7] = bets == beta; if (null) { isame[8] = lde_(&cs[1], &cc[1], &lcc); } else { isame[8] = lderes_("SY", uplo, &n, &n, &cs[1], &cc[1], &ldc, (ftnlen)2, (ftnlen)1); } isame[9] = ldcs == ldc; /* If data was incorrectly changed, report and */ /* return. */ same = TRUE_; i__5 = nargs; for (i__ = 1; i__ <= i__5; ++i__) { same = same && isame[i__ - 1]; if (! isame[i__ - 1]) { io___272.ciunit = *nout; s_wsfe(&io___272); do_fio(&c__1, (char *)&i__, (ftnlen) sizeof(integer)); e_wsfe(); } /* L30: */ } if (! same) { *fatal = TRUE_; goto L120; } if (! null) { /* Check the result column by column. */ jc = 1; i__5 = n; for (j = 1; j <= i__5; ++j) { if (upper) { jj = 1; lj = j; } else { jj = j; lj = n - j + 1; } if (tran) { dmmch_("T", "N", &lj, &c__1, &k, & alpha, &a[jj * a_dim1 + 1], nmax, &a[j * a_dim1 + 1], nmax, &beta, &c__[jj + j * c_dim1], nmax, &ct[1], &g[1], &cc[jc], &ldc, eps, &err, fatal, nout, &c_true, (ftnlen) 1, (ftnlen)1); } else { dmmch_("N", "T", &lj, &c__1, &k, & alpha, &a[jj + a_dim1], nmax, &a[j + a_dim1], nmax, &beta, & c__[jj + j * c_dim1], nmax, & ct[1], &g[1], &cc[jc], &ldc, eps, &err, fatal, nout, & c_true, (ftnlen)1, (ftnlen)1); } if (upper) { jc += ldc; } else { jc = jc + ldc + 1; } errmax = max(errmax,err); /* If got really bad answer, report and */ /* return. */ if (*fatal) { goto L110; } /* L40: */ } } /* L50: */ } /* L60: */ } /* L70: */ } L80: ; } /* L90: */ } L100: ; } /* Report result. */ if (errmax < *thresh) { io___278.ciunit = *nout; s_wsfe(&io___278); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); e_wsfe(); } else { io___279.ciunit = *nout; s_wsfe(&io___279); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&errmax, (ftnlen)sizeof(doublereal)); e_wsfe(); } goto L130; L110: if (n > 1) { io___280.ciunit = *nout; s_wsfe(&io___280); do_fio(&c__1, (char *)&j, (ftnlen)sizeof(integer)); e_wsfe(); } L120: io___281.ciunit = *nout; s_wsfe(&io___281); do_fio(&c__1, sname, (ftnlen)6); e_wsfe(); io___282.ciunit = *nout; s_wsfe(&io___282); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&k, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&alpha, (ftnlen)sizeof(doublereal)); do_fio(&c__1, (char *)&lda, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&beta, (ftnlen)sizeof(doublereal)); do_fio(&c__1, (char *)&ldc, (ftnlen)sizeof(integer)); e_wsfe(); L130: return 0; /* End of DCHK4. */ } /* dchk4_ */ /* Subroutine */ int dchk5_(char *sname, doublereal *eps, doublereal *thresh, integer *nout, integer *ntra, logical *trace, logical *rewi, logical * fatal, integer *nidim, integer *idim, integer *nalf, doublereal *alf, integer *nbet, doublereal *bet, integer *nmax, doublereal *ab, doublereal *aa, doublereal *as, doublereal *bb, doublereal *bs, doublereal *c__, doublereal *cc, doublereal *cs, doublereal *ct, doublereal *g, doublereal *w, ftnlen sname_len) { /* Initialized data */ static char icht[3] = "NTC"; static char ichu[2] = "UL"; /* Format strings */ static char fmt_9994[] = "(1x,i6,\002: \002,a6,\002(\002,2(\002'\002,a1" ",\002',\002),2(i3,\002,\002),f4.1,\002, A,\002,i3,\002, B,\002,i" "3,\002,\002,f4.1,\002, C,\002,i3,\002) \002,\002 .\002)"; static char fmt_9993[] = "(\002 ******* FATAL ERROR - ERROR-EXIT TAKEN O" "N VALID CALL *\002,\002******\002)"; static char fmt_9998[] = "(\002 ******* FATAL ERROR - PARAMETER NUMBER" " \002,i2,\002 WAS CH\002,\002ANGED INCORRECTLY *******\002)"; static char fmt_9999[] = "(\002 \002,a6,\002 PASSED THE COMPUTATIONAL TE" "STS (\002,i6,\002 CALL\002,\002S)\002)"; static char fmt_9997[] = "(\002 \002,a6,\002 COMPLETED THE COMPUTATIONAL" " TESTS (\002,i6,\002 C\002,\002ALLS)\002,/\002 ******* BUT WITH " "MAXIMUM TEST RATIO\002,f8.2,\002 - SUSPECT *******\002)"; static char fmt_9995[] = "(\002 THESE ARE THE RESULTS FOR COLUMN" " \002,i3)"; static char fmt_9996[] = "(\002 ******* \002,a6,\002 FAILED ON CALL NUMB" "ER:\002)"; /* System generated locals */ integer c_dim1, c_offset, i__1, i__2, i__3, i__4, i__5, i__6, i__7, i__8; alist al__1; /* Builtin functions */ integer s_wsfe(cilist *), do_fio(integer *, char *, ftnlen), e_wsfe(void), f_rew(alist *); /* Local variables */ integer i__, j, k, n, ia, ib, jc, ma, na, nc, ik, in, jj, lj, ks, ns, laa, lbb, lda, lcc, ldb, ldc; extern logical lde_(doublereal *, doublereal *, integer *); doublereal als; integer ict, icu; doublereal err; integer jjab; doublereal beta; integer ldas, ldbs, ldcs; logical same; doublereal bets; logical tran, null; char uplo[1]; extern /* Subroutine */ int dmake_(char *, char *, char *, integer *, integer *, doublereal *, integer *, doublereal *, integer *, logical *, doublereal *, ftnlen, ftnlen, ftnlen); doublereal alpha; extern /* Subroutine */ int dmmch_(char *, char *, integer *, integer *, integer *, doublereal *, doublereal *, integer *, doublereal *, integer *, doublereal *, doublereal *, integer *, doublereal *, doublereal *, doublereal *, integer *, doublereal *, doublereal *, logical *, integer *, logical *, ftnlen, ftnlen); logical isame[13]; integer nargs; logical reset; char trans[1]; logical upper; char uplos[1]; extern /* Subroutine */ int dsyr2k_(char *, char *, integer *, integer *, doublereal *, doublereal *, integer *, doublereal *, integer *, doublereal *, doublereal *, integer *, ftnlen, ftnlen); extern logical lderes_(char *, char *, integer *, integer *, doublereal *, doublereal *, integer *, ftnlen, ftnlen); doublereal errmax; char transs[1]; /* Fortran I/O blocks */ static cilist io___322 = { 0, 0, 0, fmt_9994, 0 }; static cilist io___323 = { 0, 0, 0, fmt_9993, 0 }; static cilist io___326 = { 0, 0, 0, fmt_9998, 0 }; static cilist io___333 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___334 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___335 = { 0, 0, 0, fmt_9995, 0 }; static cilist io___336 = { 0, 0, 0, fmt_9996, 0 }; static cilist io___337 = { 0, 0, 0, fmt_9994, 0 }; /* Tests DSYR2K. */ /* Auxiliary routine for test program for Level 3 Blas. */ /* -- Written on 8-February-1989. */ /* Jack Dongarra, Argonne National Laboratory. */ /* Iain Duff, AERE Harwell. */ /* Jeremy Du Croz, Numerical Algorithms Group Ltd. */ /* Sven Hammarling, Numerical Algorithms Group Ltd. */ /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Scalars .. */ /* .. Local Arrays .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. Scalars in Common .. */ /* .. Common blocks .. */ /* .. Data statements .. */ /* Parameter adjustments */ --idim; --alf; --bet; --w; --g; --ct; --cs; --cc; c_dim1 = *nmax; c_offset = 1 + c_dim1; c__ -= c_offset; --bs; --bb; --as; --aa; --ab; /* Function Body */ /* .. Executable Statements .. */ nargs = 12; nc = 0; reset = TRUE_; errmax = 0.; i__1 = *nidim; for (in = 1; in <= i__1; ++in) { n = idim[in]; /* Set LDC to 1 more than minimum value if room. */ ldc = n; if (ldc < *nmax) { ++ldc; } /* Skip tests if not enough room. */ if (ldc > *nmax) { goto L130; } lcc = ldc * n; null = n <= 0; i__2 = *nidim; for (ik = 1; ik <= i__2; ++ik) { k = idim[ik]; for (ict = 1; ict <= 3; ++ict) { *(unsigned char *)trans = *(unsigned char *)&icht[ict - 1]; tran = *(unsigned char *)trans == 'T' || *(unsigned char *) trans == 'C'; if (tran) { ma = k; na = n; } else { ma = n; na = k; } /* Set LDA to 1 more than minimum value if room. */ lda = ma; if (lda < *nmax) { ++lda; } /* Skip tests if not enough room. */ if (lda > *nmax) { goto L110; } laa = lda * na; /* Generate the matrix A. */ if (tran) { i__3 = *nmax << 1; dmake_("GE", " ", " ", &ma, &na, &ab[1], &i__3, &aa[1], & lda, &reset, &c_b86, (ftnlen)2, (ftnlen)1, ( ftnlen)1); } else { dmake_("GE", " ", " ", &ma, &na, &ab[1], nmax, &aa[1], & lda, &reset, &c_b86, (ftnlen)2, (ftnlen)1, ( ftnlen)1); } /* Generate the matrix B. */ ldb = lda; lbb = laa; if (tran) { i__3 = *nmax << 1; dmake_("GE", " ", " ", &ma, &na, &ab[k + 1], &i__3, &bb[1] , &ldb, &reset, &c_b86, (ftnlen)2, (ftnlen)1, ( ftnlen)1); } else { dmake_("GE", " ", " ", &ma, &na, &ab[k * *nmax + 1], nmax, &bb[1], &ldb, &reset, &c_b86, (ftnlen)2, (ftnlen) 1, (ftnlen)1); } for (icu = 1; icu <= 2; ++icu) { *(unsigned char *)uplo = *(unsigned char *)&ichu[icu - 1]; upper = *(unsigned char *)uplo == 'U'; i__3 = *nalf; for (ia = 1; ia <= i__3; ++ia) { alpha = alf[ia]; i__4 = *nbet; for (ib = 1; ib <= i__4; ++ib) { beta = bet[ib]; /* Generate the matrix C. */ dmake_("SY", uplo, " ", &n, &n, &c__[c_offset], nmax, &cc[1], &ldc, &reset, &c_b86, ( ftnlen)2, (ftnlen)1, (ftnlen)1); ++nc; /* Save every datum before calling the subroutine. */ *(unsigned char *)uplos = *(unsigned char *)uplo; *(unsigned char *)transs = *(unsigned char *) trans; ns = n; ks = k; als = alpha; i__5 = laa; for (i__ = 1; i__ <= i__5; ++i__) { as[i__] = aa[i__]; /* L10: */ } ldas = lda; i__5 = lbb; for (i__ = 1; i__ <= i__5; ++i__) { bs[i__] = bb[i__]; /* L20: */ } ldbs = ldb; bets = beta; i__5 = lcc; for (i__ = 1; i__ <= i__5; ++i__) { cs[i__] = cc[i__]; /* L30: */ } ldcs = ldc; /* Call the subroutine. */ if (*trace) { io___322.ciunit = *ntra; s_wsfe(&io___322); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof( integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&k, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&alpha, (ftnlen)sizeof( doublereal)); do_fio(&c__1, (char *)&lda, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&ldb, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&beta, (ftnlen)sizeof( doublereal)); do_fio(&c__1, (char *)&ldc, (ftnlen)sizeof( integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } dsyr2k_(uplo, trans, &n, &k, &alpha, &aa[1], &lda, &bb[1], &ldb, &beta, &cc[1], &ldc, ( ftnlen)1, (ftnlen)1); /* Check if error-exit was taken incorrectly. */ if (! infoc_1.ok) { io___323.ciunit = *nout; s_wsfe(&io___323); e_wsfe(); *fatal = TRUE_; goto L150; } /* See what data changed inside subroutines. */ isame[0] = *(unsigned char *)uplos == *(unsigned char *)uplo; isame[1] = *(unsigned char *)transs == *(unsigned char *)trans; isame[2] = ns == n; isame[3] = ks == k; isame[4] = als == alpha; isame[5] = lde_(&as[1], &aa[1], &laa); isame[6] = ldas == lda; isame[7] = lde_(&bs[1], &bb[1], &lbb); isame[8] = ldbs == ldb; isame[9] = bets == beta; if (null) { isame[10] = lde_(&cs[1], &cc[1], &lcc); } else { isame[10] = lderes_("SY", uplo, &n, &n, &cs[1] , &cc[1], &ldc, (ftnlen)2, (ftnlen)1); } isame[11] = ldcs == ldc; /* If data was incorrectly changed, report and */ /* return. */ same = TRUE_; i__5 = nargs; for (i__ = 1; i__ <= i__5; ++i__) { same = same && isame[i__ - 1]; if (! isame[i__ - 1]) { io___326.ciunit = *nout; s_wsfe(&io___326); do_fio(&c__1, (char *)&i__, (ftnlen) sizeof(integer)); e_wsfe(); } /* L40: */ } if (! same) { *fatal = TRUE_; goto L150; } if (! null) { /* Check the result column by column. */ jjab = 1; jc = 1; i__5 = n; for (j = 1; j <= i__5; ++j) { if (upper) { jj = 1; lj = j; } else { jj = j; lj = n - j + 1; } if (tran) { i__6 = k; for (i__ = 1; i__ <= i__6; ++i__) { w[i__] = ab[(j - 1 << 1) * *nmax + k + i__]; w[k + i__] = ab[(j - 1 << 1) * * nmax + i__]; /* L50: */ } i__6 = k << 1; i__7 = *nmax << 1; i__8 = *nmax << 1; dmmch_("T", "N", &lj, &c__1, &i__6, & alpha, &ab[jjab], &i__7, &w[1] , &i__8, &beta, &c__[jj + j * c_dim1], nmax, &ct[1], &g[1], &cc[jc], &ldc, eps, &err, fatal, nout, &c_true, (ftnlen) 1, (ftnlen)1); } else { i__6 = k; for (i__ = 1; i__ <= i__6; ++i__) { w[i__] = ab[(k + i__ - 1) * *nmax + j]; w[k + i__] = ab[(i__ - 1) * *nmax + j]; /* L60: */ } i__6 = k << 1; i__7 = *nmax << 1; dmmch_("N", "N", &lj, &c__1, &i__6, & alpha, &ab[jj], nmax, &w[1], & i__7, &beta, &c__[jj + j * c_dim1], nmax, &ct[1], &g[1], &cc[jc], &ldc, eps, &err, fatal, nout, &c_true, (ftnlen) 1, (ftnlen)1); } if (upper) { jc += ldc; } else { jc = jc + ldc + 1; if (tran) { jjab += *nmax << 1; } } errmax = max(errmax,err); /* If got really bad answer, report and */ /* return. */ if (*fatal) { goto L140; } /* L70: */ } } /* L80: */ } /* L90: */ } /* L100: */ } L110: ; } /* L120: */ } L130: ; } /* Report result. */ if (errmax < *thresh) { io___333.ciunit = *nout; s_wsfe(&io___333); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); e_wsfe(); } else { io___334.ciunit = *nout; s_wsfe(&io___334); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&errmax, (ftnlen)sizeof(doublereal)); e_wsfe(); } goto L160; L140: if (n > 1) { io___335.ciunit = *nout; s_wsfe(&io___335); do_fio(&c__1, (char *)&j, (ftnlen)sizeof(integer)); e_wsfe(); } L150: io___336.ciunit = *nout; s_wsfe(&io___336); do_fio(&c__1, sname, (ftnlen)6); e_wsfe(); io___337.ciunit = *nout; s_wsfe(&io___337); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&k, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&alpha, (ftnlen)sizeof(doublereal)); do_fio(&c__1, (char *)&lda, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&ldb, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&beta, (ftnlen)sizeof(doublereal)); do_fio(&c__1, (char *)&ldc, (ftnlen)sizeof(integer)); e_wsfe(); L160: return 0; /* End of DCHK5. */ } /* dchk5_ */ /* Subroutine */ int dchke_(integer *isnum, char *srnamt, integer *nout, ftnlen srnamt_len) { /* Format strings */ static char fmt_9999[] = "(\002 \002,a6,\002 PASSED THE TESTS OF ERROR-E" "XITS\002)"; static char fmt_9998[] = "(\002 ******* \002,a6,\002 FAILED THE TESTS OF" " ERROR-EXITS *****\002,\002**\002)"; /* Builtin functions */ integer s_wsfe(cilist *), do_fio(integer *, char *, ftnlen), e_wsfe(void); /* Local variables */ doublereal a[2] /* was [2][1] */, b[2] /* was [2][1] */, c__[2] /* was [2][1] */, beta, alpha; extern /* Subroutine */ int dgemm_(char *, char *, integer *, integer *, integer *, doublereal *, doublereal *, integer *, doublereal *, integer *, doublereal *, doublereal *, integer *, ftnlen, ftnlen), dtrmm_(char *, char *, char *, char *, integer *, integer *, doublereal *, doublereal *, integer *, doublereal *, integer *, ftnlen, ftnlen, ftnlen, ftnlen), dsymm_(char *, char *, integer *, integer *, doublereal *, doublereal *, integer *, doublereal *, integer *, doublereal *, doublereal *, integer *, ftnlen, ftnlen), dtrsm_(char *, char *, char *, char *, integer *, integer *, doublereal *, doublereal *, integer *, doublereal *, integer *, ftnlen, ftnlen, ftnlen, ftnlen), dsyrk_(char *, char *, integer *, integer *, doublereal *, doublereal *, integer *, doublereal *, doublereal *, integer *, ftnlen, ftnlen), dsyr2k_(char *, char *, integer *, integer *, doublereal *, doublereal *, integer *, doublereal *, integer *, doublereal *, doublereal *, integer *, ftnlen, ftnlen), chkxer_(char *, integer *, integer *, logical *, logical *, ftnlen); /* Fortran I/O blocks */ static cilist io___343 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___344 = { 0, 0, 0, fmt_9998, 0 }; /* Tests the error exits from the Level 3 Blas. */ /* Requires a special version of the error-handling routine XERBLA. */ /* A, B and C should not need to be defined. */ /* Auxiliary routine for test program for Level 3 Blas. */ /* -- Written on 8-February-1989. */ /* Jack Dongarra, Argonne National Laboratory. */ /* Iain Duff, AERE Harwell. */ /* Jeremy Du Croz, Numerical Algorithms Group Ltd. */ /* Sven Hammarling, Numerical Algorithms Group Ltd. */ /* 3-19-92: Initialize ALPHA and BETA (eca) */ /* 3-19-92: Fix argument 12 in calls to SSYMM with INFOT = 9 (eca) */ /* .. Scalar Arguments .. */ /* .. Scalars in Common .. */ /* .. Parameters .. */ /* .. Local Scalars .. */ /* .. Local Arrays .. */ /* .. External Subroutines .. */ /* .. Common blocks .. */ /* .. Executable Statements .. */ /* OK is set to .FALSE. by the special version of XERBLA or by CHKXER */ /* if anything is wrong. */ infoc_1.ok = TRUE_; /* LERR is set to .TRUE. by the special version of XERBLA each time */ /* it is called, and is then tested and re-set by CHKXER. */ infoc_1.lerr = FALSE_; /* Initialize ALPHA and BETA. */ alpha = 1.; beta = 2.; switch (*isnum) { case 1: goto L10; case 2: goto L20; case 3: goto L30; case 4: goto L40; case 5: goto L50; case 6: goto L60; } L10: infoc_1.infot = 1; dgemm_("/", "N", &c__0, &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 1; dgemm_("/", "T", &c__0, &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; dgemm_("N", "/", &c__0, &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; dgemm_("T", "/", &c__0, &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; dgemm_("N", "N", &c_n1, &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; dgemm_("N", "T", &c_n1, &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; dgemm_("T", "N", &c_n1, &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; dgemm_("T", "T", &c_n1, &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; dgemm_("N", "N", &c__0, &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; dgemm_("N", "T", &c__0, &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; dgemm_("T", "N", &c__0, &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; dgemm_("T", "T", &c__0, &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; dgemm_("N", "N", &c__0, &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; dgemm_("N", "T", &c__0, &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; dgemm_("T", "N", &c__0, &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; dgemm_("T", "T", &c__0, &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 8; dgemm_("N", "N", &c__2, &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__2, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 8; dgemm_("N", "T", &c__2, &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__2, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 8; dgemm_("T", "N", &c__0, &c__0, &c__2, &alpha, a, &c__1, b, &c__2, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 8; dgemm_("T", "T", &c__0, &c__0, &c__2, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 10; dgemm_("N", "N", &c__0, &c__0, &c__2, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 10; dgemm_("T", "N", &c__0, &c__0, &c__2, &alpha, a, &c__2, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 10; dgemm_("N", "T", &c__0, &c__2, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 10; dgemm_("T", "T", &c__0, &c__2, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 13; dgemm_("N", "N", &c__2, &c__0, &c__0, &alpha, a, &c__2, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 13; dgemm_("N", "T", &c__2, &c__0, &c__0, &alpha, a, &c__2, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 13; dgemm_("T", "N", &c__2, &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 13; dgemm_("T", "T", &c__2, &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L70; L20: infoc_1.infot = 1; dsymm_("/", "U", &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; dsymm_("L", "/", &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; dsymm_("L", "U", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; dsymm_("R", "U", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; dsymm_("L", "L", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; dsymm_("R", "L", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; dsymm_("L", "U", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; dsymm_("R", "U", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; dsymm_("L", "L", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; dsymm_("R", "L", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; dsymm_("L", "U", &c__2, &c__0, &alpha, a, &c__1, b, &c__2, &beta, c__, & c__2, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; dsymm_("R", "U", &c__0, &c__2, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; dsymm_("L", "L", &c__2, &c__0, &alpha, a, &c__1, b, &c__2, &beta, c__, & c__2, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; dsymm_("R", "L", &c__0, &c__2, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; dsymm_("L", "U", &c__2, &c__0, &alpha, a, &c__2, b, &c__1, &beta, c__, & c__2, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; dsymm_("R", "U", &c__2, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__2, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; dsymm_("L", "L", &c__2, &c__0, &alpha, a, &c__2, b, &c__1, &beta, c__, & c__2, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; dsymm_("R", "L", &c__2, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__2, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 12; dsymm_("L", "U", &c__2, &c__0, &alpha, a, &c__2, b, &c__2, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 12; dsymm_("R", "U", &c__2, &c__0, &alpha, a, &c__1, b, &c__2, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 12; dsymm_("L", "L", &c__2, &c__0, &alpha, a, &c__2, b, &c__2, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 12; dsymm_("R", "L", &c__2, &c__0, &alpha, a, &c__1, b, &c__2, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L70; L30: infoc_1.infot = 1; dtrmm_("/", "U", "N", "N", &c__0, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; dtrmm_("L", "/", "N", "N", &c__0, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; dtrmm_("L", "U", "/", "N", &c__0, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; dtrmm_("L", "U", "N", "/", &c__0, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; dtrmm_("L", "U", "N", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; dtrmm_("L", "U", "T", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; dtrmm_("R", "U", "N", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; dtrmm_("R", "U", "T", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; dtrmm_("L", "L", "N", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; dtrmm_("L", "L", "T", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; dtrmm_("R", "L", "N", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; dtrmm_("R", "L", "T", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; dtrmm_("L", "U", "N", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; dtrmm_("L", "U", "T", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; dtrmm_("R", "U", "N", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; dtrmm_("R", "U", "T", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; dtrmm_("L", "L", "N", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; dtrmm_("L", "L", "T", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; dtrmm_("R", "L", "N", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; dtrmm_("R", "L", "T", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; dtrmm_("L", "U", "N", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__2, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; dtrmm_("L", "U", "T", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__2, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; dtrmm_("R", "U", "N", "N", &c__0, &c__2, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; dtrmm_("R", "U", "T", "N", &c__0, &c__2, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; dtrmm_("L", "L", "N", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__2, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; dtrmm_("L", "L", "T", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__2, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; dtrmm_("R", "L", "N", "N", &c__0, &c__2, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; dtrmm_("R", "L", "T", "N", &c__0, &c__2, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; dtrmm_("L", "U", "N", "N", &c__2, &c__0, &alpha, a, &c__2, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; dtrmm_("L", "U", "T", "N", &c__2, &c__0, &alpha, a, &c__2, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; dtrmm_("R", "U", "N", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; dtrmm_("R", "U", "T", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; dtrmm_("L", "L", "N", "N", &c__2, &c__0, &alpha, a, &c__2, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; dtrmm_("L", "L", "T", "N", &c__2, &c__0, &alpha, a, &c__2, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; dtrmm_("R", "L", "N", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; dtrmm_("R", "L", "T", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L70; L40: infoc_1.infot = 1; dtrsm_("/", "U", "N", "N", &c__0, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; dtrsm_("L", "/", "N", "N", &c__0, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; dtrsm_("L", "U", "/", "N", &c__0, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; dtrsm_("L", "U", "N", "/", &c__0, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; dtrsm_("L", "U", "N", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; dtrsm_("L", "U", "T", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; dtrsm_("R", "U", "N", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; dtrsm_("R", "U", "T", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; dtrsm_("L", "L", "N", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; dtrsm_("L", "L", "T", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; dtrsm_("R", "L", "N", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; dtrsm_("R", "L", "T", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; dtrsm_("L", "U", "N", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; dtrsm_("L", "U", "T", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; dtrsm_("R", "U", "N", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; dtrsm_("R", "U", "T", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; dtrsm_("L", "L", "N", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; dtrsm_("L", "L", "T", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; dtrsm_("R", "L", "N", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; dtrsm_("R", "L", "T", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; dtrsm_("L", "U", "N", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__2, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; dtrsm_("L", "U", "T", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__2, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; dtrsm_("R", "U", "N", "N", &c__0, &c__2, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; dtrsm_("R", "U", "T", "N", &c__0, &c__2, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; dtrsm_("L", "L", "N", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__2, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; dtrsm_("L", "L", "T", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__2, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; dtrsm_("R", "L", "N", "N", &c__0, &c__2, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; dtrsm_("R", "L", "T", "N", &c__0, &c__2, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; dtrsm_("L", "U", "N", "N", &c__2, &c__0, &alpha, a, &c__2, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; dtrsm_("L", "U", "T", "N", &c__2, &c__0, &alpha, a, &c__2, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; dtrsm_("R", "U", "N", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; dtrsm_("R", "U", "T", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; dtrsm_("L", "L", "N", "N", &c__2, &c__0, &alpha, a, &c__2, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; dtrsm_("L", "L", "T", "N", &c__2, &c__0, &alpha, a, &c__2, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; dtrsm_("R", "L", "N", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; dtrsm_("R", "L", "T", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L70; L50: infoc_1.infot = 1; dsyrk_("/", "N", &c__0, &c__0, &alpha, a, &c__1, &beta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; dsyrk_("U", "/", &c__0, &c__0, &alpha, a, &c__1, &beta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; dsyrk_("U", "N", &c_n1, &c__0, &alpha, a, &c__1, &beta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; dsyrk_("U", "T", &c_n1, &c__0, &alpha, a, &c__1, &beta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; dsyrk_("L", "N", &c_n1, &c__0, &alpha, a, &c__1, &beta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; dsyrk_("L", "T", &c_n1, &c__0, &alpha, a, &c__1, &beta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; dsyrk_("U", "N", &c__0, &c_n1, &alpha, a, &c__1, &beta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; dsyrk_("U", "T", &c__0, &c_n1, &alpha, a, &c__1, &beta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; dsyrk_("L", "N", &c__0, &c_n1, &alpha, a, &c__1, &beta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; dsyrk_("L", "T", &c__0, &c_n1, &alpha, a, &c__1, &beta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; dsyrk_("U", "N", &c__2, &c__0, &alpha, a, &c__1, &beta, c__, &c__2, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; dsyrk_("U", "T", &c__0, &c__2, &alpha, a, &c__1, &beta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; dsyrk_("L", "N", &c__2, &c__0, &alpha, a, &c__1, &beta, c__, &c__2, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; dsyrk_("L", "T", &c__0, &c__2, &alpha, a, &c__1, &beta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 10; dsyrk_("U", "N", &c__2, &c__0, &alpha, a, &c__2, &beta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 10; dsyrk_("U", "T", &c__2, &c__0, &alpha, a, &c__1, &beta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 10; dsyrk_("L", "N", &c__2, &c__0, &alpha, a, &c__2, &beta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 10; dsyrk_("L", "T", &c__2, &c__0, &alpha, a, &c__1, &beta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L70; L60: infoc_1.infot = 1; dsyr2k_("/", "N", &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; dsyr2k_("U", "/", &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; dsyr2k_("U", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; dsyr2k_("U", "T", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; dsyr2k_("L", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; dsyr2k_("L", "T", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; dsyr2k_("U", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; dsyr2k_("U", "T", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; dsyr2k_("L", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; dsyr2k_("L", "T", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; dsyr2k_("U", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__2, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; dsyr2k_("U", "T", &c__0, &c__2, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; dsyr2k_("L", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__2, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; dsyr2k_("L", "T", &c__0, &c__2, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; dsyr2k_("U", "N", &c__2, &c__0, &alpha, a, &c__2, b, &c__1, &beta, c__, & c__2, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; dsyr2k_("U", "T", &c__0, &c__2, &alpha, a, &c__2, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; dsyr2k_("L", "N", &c__2, &c__0, &alpha, a, &c__2, b, &c__1, &beta, c__, & c__2, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; dsyr2k_("L", "T", &c__0, &c__2, &alpha, a, &c__2, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 12; dsyr2k_("U", "N", &c__2, &c__0, &alpha, a, &c__2, b, &c__2, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 12; dsyr2k_("U", "T", &c__2, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 12; dsyr2k_("L", "N", &c__2, &c__0, &alpha, a, &c__2, b, &c__2, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 12; dsyr2k_("L", "T", &c__2, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); L70: if (infoc_1.ok) { io___343.ciunit = *nout; s_wsfe(&io___343); do_fio(&c__1, srnamt, (ftnlen)6); e_wsfe(); } else { io___344.ciunit = *nout; s_wsfe(&io___344); do_fio(&c__1, srnamt, (ftnlen)6); e_wsfe(); } return 0; /* End of DCHKE. */ } /* dchke_ */ /* Subroutine */ int dmake_(char *type__, char *uplo, char *diag, integer *m, integer *n, doublereal *a, integer *nmax, doublereal *aa, integer * lda, logical *reset, doublereal *transl, ftnlen type_len, ftnlen uplo_len, ftnlen diag_len) { /* System generated locals */ integer a_dim1, a_offset, i__1, i__2; /* Builtin functions */ integer s_cmp(const char *, const char *, ftnlen, ftnlen); /* Local variables */ integer i__, j; logical gen, tri, sym; extern doublereal dbeg_(logical *); integer ibeg, iend; logical unit, lower, upper; /* Generates values for an M by N matrix A. */ /* Stores the values in the array AA in the data structure required */ /* by the routine, with unwanted elements set to rogue value. */ /* TYPE is 'GE', 'SY' or 'TR'. */ /* Auxiliary routine for test program for Level 3 Blas. */ /* -- Written on 8-February-1989. */ /* Jack Dongarra, Argonne National Laboratory. */ /* Iain Duff, AERE Harwell. */ /* Jeremy Du Croz, Numerical Algorithms Group Ltd. */ /* Sven Hammarling, Numerical Algorithms Group Ltd. */ /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Scalars .. */ /* .. External Functions .. */ /* .. Executable Statements .. */ /* Parameter adjustments */ a_dim1 = *nmax; a_offset = 1 + a_dim1; a -= a_offset; --aa; /* Function Body */ gen = s_cmp(type__, "GE", (ftnlen)2, (ftnlen)2) == 0; sym = s_cmp(type__, "SY", (ftnlen)2, (ftnlen)2) == 0; tri = s_cmp(type__, "TR", (ftnlen)2, (ftnlen)2) == 0; upper = (sym || tri) && *(unsigned char *)uplo == 'U'; lower = (sym || tri) && *(unsigned char *)uplo == 'L'; unit = tri && *(unsigned char *)diag == 'U'; /* Generate data in array A. */ i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = *m; for (i__ = 1; i__ <= i__2; ++i__) { if (gen || upper && i__ <= j || lower && i__ >= j) { a[i__ + j * a_dim1] = dbeg_(reset) + *transl; if (i__ != j) { /* Set some elements to zero */ if (*n > 3 && j == *n / 2) { a[i__ + j * a_dim1] = 0.; } if (sym) { a[j + i__ * a_dim1] = a[i__ + j * a_dim1]; } else if (tri) { a[j + i__ * a_dim1] = 0.; } } } /* L10: */ } if (tri) { a[j + j * a_dim1] += 1.; } if (unit) { a[j + j * a_dim1] = 1.; } /* L20: */ } /* Store elements in array AS in data structure required by routine. */ if (s_cmp(type__, "GE", (ftnlen)2, (ftnlen)2) == 0) { i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = *m; for (i__ = 1; i__ <= i__2; ++i__) { aa[i__ + (j - 1) * *lda] = a[i__ + j * a_dim1]; /* L30: */ } i__2 = *lda; for (i__ = *m + 1; i__ <= i__2; ++i__) { aa[i__ + (j - 1) * *lda] = -1e10; /* L40: */ } /* L50: */ } } else if (s_cmp(type__, "SY", (ftnlen)2, (ftnlen)2) == 0 || s_cmp(type__, "TR", (ftnlen)2, (ftnlen)2) == 0) { i__1 = *n; for (j = 1; j <= i__1; ++j) { if (upper) { ibeg = 1; if (unit) { iend = j - 1; } else { iend = j; } } else { if (unit) { ibeg = j + 1; } else { ibeg = j; } iend = *n; } i__2 = ibeg - 1; for (i__ = 1; i__ <= i__2; ++i__) { aa[i__ + (j - 1) * *lda] = -1e10; /* L60: */ } i__2 = iend; for (i__ = ibeg; i__ <= i__2; ++i__) { aa[i__ + (j - 1) * *lda] = a[i__ + j * a_dim1]; /* L70: */ } i__2 = *lda; for (i__ = iend + 1; i__ <= i__2; ++i__) { aa[i__ + (j - 1) * *lda] = -1e10; /* L80: */ } /* L90: */ } } return 0; /* End of DMAKE. */ } /* dmake_ */ /* Subroutine */ int dmmch_(char *transa, char *transb, integer *m, integer * n, integer *kk, doublereal *alpha, doublereal *a, integer *lda, doublereal *b, integer *ldb, doublereal *beta, doublereal *c__, integer *ldc, doublereal *ct, doublereal *g, doublereal *cc, integer * ldcc, doublereal *eps, doublereal *err, logical *fatal, integer *nout, logical *mv, ftnlen transa_len, ftnlen transb_len) { /* Format strings */ static char fmt_9999[] = "(\002 ******* FATAL ERROR - COMPUTED RESULT IS" " LESS THAN HAL\002,\002F ACCURATE *******\002,/\002 EX" "PECTED RESULT COMPU\002,\002TED RESULT\002)"; static char fmt_9998[] = "(1x,i7,2g18.6)"; static char fmt_9997[] = "(\002 THESE ARE THE RESULTS FOR COLUMN" " \002,i3)"; /* System generated locals */ integer a_dim1, a_offset, b_dim1, b_offset, c_dim1, c_offset, cc_dim1, cc_offset, i__1, i__2, i__3; doublereal d__1, d__2; /* Builtin functions */ double sqrt(doublereal); integer s_wsfe(cilist *), e_wsfe(void), do_fio(integer *, char *, ftnlen); /* Local variables */ integer i__, j, k; doublereal erri; logical trana, tranb; /* Fortran I/O blocks */ static cilist io___361 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___362 = { 0, 0, 0, fmt_9998, 0 }; static cilist io___363 = { 0, 0, 0, fmt_9998, 0 }; static cilist io___364 = { 0, 0, 0, fmt_9997, 0 }; /* Checks the results of the computational tests. */ /* Auxiliary routine for test program for Level 3 Blas. */ /* -- Written on 8-February-1989. */ /* Jack Dongarra, Argonne National Laboratory. */ /* Iain Duff, AERE Harwell. */ /* Jeremy Du Croz, Numerical Algorithms Group Ltd. */ /* Sven Hammarling, Numerical Algorithms Group Ltd. */ /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Scalars .. */ /* .. Intrinsic Functions .. */ /* .. Executable Statements .. */ /* Parameter adjustments */ a_dim1 = *lda; a_offset = 1 + a_dim1; a -= a_offset; b_dim1 = *ldb; b_offset = 1 + b_dim1; b -= b_offset; c_dim1 = *ldc; c_offset = 1 + c_dim1; c__ -= c_offset; --ct; --g; cc_dim1 = *ldcc; cc_offset = 1 + cc_dim1; cc -= cc_offset; /* Function Body */ trana = *(unsigned char *)transa == 'T' || *(unsigned char *)transa == 'C'; tranb = *(unsigned char *)transb == 'T' || *(unsigned char *)transb == 'C'; /* Compute expected result, one column at a time, in CT using data */ /* in A, B and C. */ /* Compute gauges in G. */ i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = *m; for (i__ = 1; i__ <= i__2; ++i__) { ct[i__] = 0.; g[i__] = 0.; /* L10: */ } if (! trana && ! tranb) { i__2 = *kk; for (k = 1; k <= i__2; ++k) { i__3 = *m; for (i__ = 1; i__ <= i__3; ++i__) { ct[i__] += a[i__ + k * a_dim1] * b[k + j * b_dim1]; g[i__] += (d__1 = a[i__ + k * a_dim1], abs(d__1)) * (d__2 = b[k + j * b_dim1], abs(d__2)); /* L20: */ } /* L30: */ } } else if (trana && ! tranb) { i__2 = *kk; for (k = 1; k <= i__2; ++k) { i__3 = *m; for (i__ = 1; i__ <= i__3; ++i__) { ct[i__] += a[k + i__ * a_dim1] * b[k + j * b_dim1]; g[i__] += (d__1 = a[k + i__ * a_dim1], abs(d__1)) * (d__2 = b[k + j * b_dim1], abs(d__2)); /* L40: */ } /* L50: */ } } else if (! trana && tranb) { i__2 = *kk; for (k = 1; k <= i__2; ++k) { i__3 = *m; for (i__ = 1; i__ <= i__3; ++i__) { ct[i__] += a[i__ + k * a_dim1] * b[j + k * b_dim1]; g[i__] += (d__1 = a[i__ + k * a_dim1], abs(d__1)) * (d__2 = b[j + k * b_dim1], abs(d__2)); /* L60: */ } /* L70: */ } } else if (trana && tranb) { i__2 = *kk; for (k = 1; k <= i__2; ++k) { i__3 = *m; for (i__ = 1; i__ <= i__3; ++i__) { ct[i__] += a[k + i__ * a_dim1] * b[j + k * b_dim1]; g[i__] += (d__1 = a[k + i__ * a_dim1], abs(d__1)) * (d__2 = b[j + k * b_dim1], abs(d__2)); /* L80: */ } /* L90: */ } } i__2 = *m; for (i__ = 1; i__ <= i__2; ++i__) { ct[i__] = *alpha * ct[i__] + *beta * c__[i__ + j * c_dim1]; g[i__] = abs(*alpha) * g[i__] + abs(*beta) * (d__1 = c__[i__ + j * c_dim1], abs(d__1)); /* L100: */ } /* Compute the error ratio for this result. */ *err = 0.; i__2 = *m; for (i__ = 1; i__ <= i__2; ++i__) { erri = (d__1 = ct[i__] - cc[i__ + j * cc_dim1], abs(d__1)) / *eps; if (g[i__] != 0.) { erri /= g[i__]; } *err = max(*err,erri); if (*err * sqrt(*eps) >= 1.) { goto L130; } /* L110: */ } /* L120: */ } /* If the loop completes, all results are at least half accurate. */ goto L150; /* Report fatal error. */ L130: *fatal = TRUE_; io___361.ciunit = *nout; s_wsfe(&io___361); e_wsfe(); i__1 = *m; for (i__ = 1; i__ <= i__1; ++i__) { if (*mv) { io___362.ciunit = *nout; s_wsfe(&io___362); do_fio(&c__1, (char *)&i__, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&ct[i__], (ftnlen)sizeof(doublereal)); do_fio(&c__1, (char *)&cc[i__ + j * cc_dim1], (ftnlen)sizeof( doublereal)); e_wsfe(); } else { io___363.ciunit = *nout; s_wsfe(&io___363); do_fio(&c__1, (char *)&i__, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&cc[i__ + j * cc_dim1], (ftnlen)sizeof( doublereal)); do_fio(&c__1, (char *)&ct[i__], (ftnlen)sizeof(doublereal)); e_wsfe(); } /* L140: */ } if (*n > 1) { io___364.ciunit = *nout; s_wsfe(&io___364); do_fio(&c__1, (char *)&j, (ftnlen)sizeof(integer)); e_wsfe(); } L150: return 0; /* End of DMMCH. */ } /* dmmch_ */ logical lde_(doublereal *ri, doublereal *rj, integer *lr) { /* System generated locals */ integer i__1; logical ret_val; /* Local variables */ integer i__; /* Tests if two arrays are identical. */ /* Auxiliary routine for test program for Level 3 Blas. */ /* -- Written on 8-February-1989. */ /* Jack Dongarra, Argonne National Laboratory. */ /* Iain Duff, AERE Harwell. */ /* Jeremy Du Croz, Numerical Algorithms Group Ltd. */ /* Sven Hammarling, Numerical Algorithms Group Ltd. */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Scalars .. */ /* .. Executable Statements .. */ /* Parameter adjustments */ --rj; --ri; /* Function Body */ i__1 = *lr; for (i__ = 1; i__ <= i__1; ++i__) { if (ri[i__] != rj[i__]) { goto L20; } /* L10: */ } ret_val = TRUE_; goto L30; L20: ret_val = FALSE_; L30: return ret_val; /* End of LDE. */ } /* lde_ */ logical lderes_(char *type__, char *uplo, integer *m, integer *n, doublereal * aa, doublereal *as, integer *lda, ftnlen type_len, ftnlen uplo_len) { /* System generated locals */ integer aa_dim1, aa_offset, as_dim1, as_offset, i__1, i__2; logical ret_val; /* Builtin functions */ integer s_cmp(const char *, const char *, ftnlen, ftnlen); /* Local variables */ integer i__, j, ibeg, iend; logical upper; /* Tests if selected elements in two arrays are equal. */ /* TYPE is 'GE' or 'SY'. */ /* Auxiliary routine for test program for Level 3 Blas. */ /* -- Written on 8-February-1989. */ /* Jack Dongarra, Argonne National Laboratory. */ /* Iain Duff, AERE Harwell. */ /* Jeremy Du Croz, Numerical Algorithms Group Ltd. */ /* Sven Hammarling, Numerical Algorithms Group Ltd. */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Scalars .. */ /* .. Executable Statements .. */ /* Parameter adjustments */ as_dim1 = *lda; as_offset = 1 + as_dim1; as -= as_offset; aa_dim1 = *lda; aa_offset = 1 + aa_dim1; aa -= aa_offset; /* Function Body */ upper = *(unsigned char *)uplo == 'U'; if (s_cmp(type__, "GE", (ftnlen)2, (ftnlen)2) == 0) { i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = *lda; for (i__ = *m + 1; i__ <= i__2; ++i__) { if (aa[i__ + j * aa_dim1] != as[i__ + j * as_dim1]) { goto L70; } /* L10: */ } /* L20: */ } } else if (s_cmp(type__, "SY", (ftnlen)2, (ftnlen)2) == 0) { i__1 = *n; for (j = 1; j <= i__1; ++j) { if (upper) { ibeg = 1; iend = j; } else { ibeg = j; iend = *n; } i__2 = ibeg - 1; for (i__ = 1; i__ <= i__2; ++i__) { if (aa[i__ + j * aa_dim1] != as[i__ + j * as_dim1]) { goto L70; } /* L30: */ } i__2 = *lda; for (i__ = iend + 1; i__ <= i__2; ++i__) { if (aa[i__ + j * aa_dim1] != as[i__ + j * as_dim1]) { goto L70; } /* L40: */ } /* L50: */ } } ret_val = TRUE_; goto L80; L70: ret_val = FALSE_; L80: return ret_val; /* End of LDERES. */ } /* lderes_ */ doublereal dbeg_(logical *reset) { /* System generated locals */ doublereal ret_val; /* Local variables */ static integer i__, ic, mi; /* Generates random numbers uniformly distributed between -0.5 and 0.5. */ /* Auxiliary routine for test program for Level 3 Blas. */ /* -- Written on 8-February-1989. */ /* Jack Dongarra, Argonne National Laboratory. */ /* Iain Duff, AERE Harwell. */ /* Jeremy Du Croz, Numerical Algorithms Group Ltd. */ /* Sven Hammarling, Numerical Algorithms Group Ltd. */ /* .. Scalar Arguments .. */ /* .. Local Scalars .. */ /* .. Save statement .. */ /* .. Executable Statements .. */ if (*reset) { /* Initialize local variables. */ mi = 891; i__ = 7; ic = 0; *reset = FALSE_; } /* The sequence of values of I is bounded between 1 and 999. */ /* If initial I = 1,2,3,6,7 or 9, the period will be 50. */ /* If initial I = 4 or 8, the period will be 25. */ /* If initial I = 5, the period will be 10. */ /* IC is used to break up the period by skipping 1 value of I in 6. */ ++ic; L10: i__ *= mi; i__ -= i__ / 1000 * 1000; if (ic >= 5) { ic = 0; goto L10; } ret_val = (i__ - 500) / 1001.; return ret_val; /* End of DBEG. */ } /* dbeg_ */ doublereal ddiff_(doublereal *x, doublereal *y) { /* System generated locals */ doublereal ret_val; /* Auxiliary routine for test program for Level 3 Blas. */ /* -- Written on 8-February-1989. */ /* Jack Dongarra, Argonne National Laboratory. */ /* Iain Duff, AERE Harwell. */ /* Jeremy Du Croz, Numerical Algorithms Group Ltd. */ /* Sven Hammarling, Numerical Algorithms Group Ltd. */ /* .. Scalar Arguments .. */ /* .. Executable Statements .. */ ret_val = *x - *y; return ret_val; /* End of DDIFF. */ } /* ddiff_ */ /* Subroutine */ int chkxer_(char *srnamt, integer *infot, integer *nout, logical *lerr, logical *ok, ftnlen srnamt_len) { /* Format strings */ static char fmt_9999[] = "(\002 ***** ILLEGAL VALUE OF PARAMETER NUMBER" " \002,i2,\002 NOT D\002,\002ETECTED BY \002,a6,\002 *****\002)"; /* Builtin functions */ integer s_wsfe(cilist *), do_fio(integer *, char *, ftnlen), e_wsfe(void); /* Fortran I/O blocks */ static cilist io___374 = { 0, 0, 0, fmt_9999, 0 }; /* Tests whether XERBLA has detected an error when it should. */ /* Auxiliary routine for test program for Level 3 Blas. */ /* -- Written on 8-February-1989. */ /* Jack Dongarra, Argonne National Laboratory. */ /* Iain Duff, AERE Harwell. */ /* Jeremy Du Croz, Numerical Algorithms Group Ltd. */ /* Sven Hammarling, Numerical Algorithms Group Ltd. */ /* .. Scalar Arguments .. */ /* .. Executable Statements .. */ if (! (*lerr)) { io___374.ciunit = *nout; s_wsfe(&io___374); do_fio(&c__1, (char *)&(*infot), (ftnlen)sizeof(integer)); do_fio(&c__1, srnamt, (ftnlen)6); e_wsfe(); *ok = FALSE_; } *lerr = FALSE_; return 0; /* End of CHKXER. */ } /* chkxer_ */ /* Subroutine */ int xerbla_(char *srname, integer *info, ftnlen srname_len) { /* Format strings */ static char fmt_9999[] = "(\002 ******* XERBLA WAS CALLED WITH INFO =" " \002,i6,\002 INSTEAD\002,\002 OF \002,i2,\002 *******\002)"; static char fmt_9997[] = "(\002 ******* XERBLA WAS CALLED WITH INFO =" " \002,i6,\002 *******\002)"; static char fmt_9998[] = "(\002 ******* XERBLA WAS CALLED WITH SRNAME =" " \002,a6,\002 INSTE\002,\002AD OF \002,a6,\002 *******\002)"; /* Builtin functions */ integer s_wsfe(cilist *), do_fio(integer *, char *, ftnlen), e_wsfe(void), s_cmp(const char *, const char *, ftnlen, ftnlen); /* Fortran I/O blocks */ static cilist io___375 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___376 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___377 = { 0, 0, 0, fmt_9998, 0 }; /* This is a special version of XERBLA to be used only as part of */ /* the test program for testing error exits from the Level 3 BLAS */ /* routines. */ /* XERBLA is an error handler for the Level 3 BLAS routines. */ /* It is called by the Level 3 BLAS routines if an input parameter is */ /* invalid. */ /* Auxiliary routine for test program for Level 3 Blas. */ /* -- Written on 8-February-1989. */ /* Jack Dongarra, Argonne National Laboratory. */ /* Iain Duff, AERE Harwell. */ /* Jeremy Du Croz, Numerical Algorithms Group Ltd. */ /* Sven Hammarling, Numerical Algorithms Group Ltd. */ /* .. Scalar Arguments .. */ /* .. Scalars in Common .. */ /* .. Common blocks .. */ /* .. Executable Statements .. */ infoc_2.lerr = TRUE_; if (*info != infoc_2.infot) { if (infoc_2.infot != 0) { io___375.ciunit = infoc_2.nout; s_wsfe(&io___375); do_fio(&c__1, (char *)&(*info), (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&infoc_2.infot, (ftnlen)sizeof(integer)); e_wsfe(); } else { io___376.ciunit = infoc_2.nout; s_wsfe(&io___376); do_fio(&c__1, (char *)&(*info), (ftnlen)sizeof(integer)); e_wsfe(); } infoc_2.ok = FALSE_; } if (s_cmp(srname, srnamc_1.srnamt, (ftnlen)6, (ftnlen)6) != 0) { io___377.ciunit = infoc_2.nout; s_wsfe(&io___377); do_fio(&c__1, srname, (ftnlen)6); do_fio(&c__1, srnamc_1.srnamt, (ftnlen)6); e_wsfe(); infoc_2.ok = FALSE_; } return 0; /* End of XERBLA */ } /* xerbla_ */ /* Main program alias */ int dblat3_ () { main (); return 0; } blis-0.9.0/blastest/src/fortran/000077500000000000000000000000001422157504600165425ustar00rootroot00000000000000blis-0.9.0/blastest/src/fortran/cblat1.f000066400000000000000000000765551422157504600201010ustar00rootroot00000000000000*> \brief \b CBLAT1 * * =========== DOCUMENTATION =========== * * Online html documentation available at * http://www.netlib.org/lapack/explore-html/ * * Definition: * =========== * * PROGRAM CBLAT1 * * *> \par Purpose: * ============= *> *> \verbatim *> *> Test program for the COMPLEX Level 1 BLAS. *> Based upon the original BLAS test routine together with: *> *> F06GAF Example Program Text *> \endverbatim * * Authors: * ======== * *> \author Univ. of Tennessee *> \author Univ. of California Berkeley *> \author Univ. of Colorado Denver *> \author NAG Ltd. * *> \date April 2012 * *> \ingroup complex_blas_testing * * ===================================================================== PROGRAM CBLAT1 * * -- Reference BLAS test routine (version 3.4.1) -- * -- Reference BLAS is a software package provided by Univ. of Tennessee, -- * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- * April 2012 * * ===================================================================== * * .. Parameters .. INTEGER NOUT PARAMETER (NOUT=6) * .. Scalars in Common .. INTEGER ICASE, INCX, INCY, MODE, N LOGICAL PASS * .. Local Scalars .. REAL SFAC INTEGER IC * .. External Subroutines .. EXTERNAL CHECK1, CHECK2, HEADER * .. Common blocks .. COMMON /COMBLA/ICASE, N, INCX, INCY, MODE, PASS * .. Data statements .. DATA SFAC/9.765625E-4/ * .. Executable Statements .. WRITE (NOUT,99999) DO 20 IC = 1, 10 ICASE = IC CALL HEADER * * Initialize PASS, INCX, INCY, and MODE for a new case. * The value 9999 for INCX, INCY or MODE will appear in the * detailed output, if any, for cases that do not involve * these parameters. * PASS = .TRUE. INCX = 9999 INCY = 9999 MODE = 9999 IF (ICASE.LE.5) THEN CALL CHECK2(SFAC) ELSE IF (ICASE.GE.6) THEN CALL CHECK1(SFAC) END IF * -- Print IF (PASS) WRITE (NOUT,99998) 20 CONTINUE STOP * 99999 FORMAT (' Complex BLAS Test Program Results',/1X) 99998 FORMAT (' ----- PASS -----') END SUBROUTINE HEADER * .. Parameters .. INTEGER NOUT PARAMETER (NOUT=6) * .. Scalars in Common .. INTEGER ICASE, INCX, INCY, MODE, N LOGICAL PASS * .. Local Arrays .. CHARACTER*6 L(10) * .. Common blocks .. COMMON /COMBLA/ICASE, N, INCX, INCY, MODE, PASS * .. Data statements .. DATA L(1)/'CDOTC '/ DATA L(2)/'CDOTU '/ DATA L(3)/'CAXPY '/ DATA L(4)/'CCOPY '/ DATA L(5)/'CSWAP '/ DATA L(6)/'SCNRM2'/ DATA L(7)/'SCASUM'/ DATA L(8)/'CSCAL '/ DATA L(9)/'CSSCAL'/ DATA L(10)/'ICAMAX'/ * .. Executable Statements .. WRITE (NOUT,99999) ICASE, L(ICASE) RETURN * 99999 FORMAT (/' Test of subprogram number',I3,12X,A6) END SUBROUTINE CHECK1(SFAC) * .. Parameters .. INTEGER NOUT PARAMETER (NOUT=6) * .. Scalar Arguments .. REAL SFAC * .. Scalars in Common .. INTEGER ICASE, INCX, INCY, MODE, N LOGICAL PASS * .. Local Scalars .. COMPLEX CA REAL SA INTEGER I, J, LEN, NP1 * .. Local Arrays .. COMPLEX CTRUE5(8,5,2), CTRUE6(8,5,2), CV(8,5,2), CX(8), + MWPCS(5), MWPCT(5) REAL STRUE2(5), STRUE4(5) INTEGER ITRUE3(5) * .. External Functions .. REAL SCASUM, SCNRM2 INTEGER ICAMAX EXTERNAL SCASUM, SCNRM2, ICAMAX * .. External Subroutines .. EXTERNAL CSCAL, CSSCAL, CTEST, ITEST1, STEST1 * .. Intrinsic Functions .. INTRINSIC MAX * .. Common blocks .. COMMON /COMBLA/ICASE, N, INCX, INCY, MODE, PASS * .. Data statements .. DATA SA, CA/0.3E0, (0.4E0,-0.7E0)/ DATA ((CV(I,J,1),I=1,8),J=1,5)/(0.1E0,0.1E0), + (1.0E0,2.0E0), (1.0E0,2.0E0), (1.0E0,2.0E0), + (1.0E0,2.0E0), (1.0E0,2.0E0), (1.0E0,2.0E0), + (1.0E0,2.0E0), (0.3E0,-0.4E0), (3.0E0,4.0E0), + (3.0E0,4.0E0), (3.0E0,4.0E0), (3.0E0,4.0E0), + (3.0E0,4.0E0), (3.0E0,4.0E0), (3.0E0,4.0E0), + (0.1E0,-0.3E0), (0.5E0,-0.1E0), (5.0E0,6.0E0), + (5.0E0,6.0E0), (5.0E0,6.0E0), (5.0E0,6.0E0), + (5.0E0,6.0E0), (5.0E0,6.0E0), (0.1E0,0.1E0), + (-0.6E0,0.1E0), (0.1E0,-0.3E0), (7.0E0,8.0E0), + (7.0E0,8.0E0), (7.0E0,8.0E0), (7.0E0,8.0E0), + (7.0E0,8.0E0), (0.3E0,0.1E0), (0.5E0,0.0E0), + (0.0E0,0.5E0), (0.0E0,0.2E0), (2.0E0,3.0E0), + (2.0E0,3.0E0), (2.0E0,3.0E0), (2.0E0,3.0E0)/ DATA ((CV(I,J,2),I=1,8),J=1,5)/(0.1E0,0.1E0), + (4.0E0,5.0E0), (4.0E0,5.0E0), (4.0E0,5.0E0), + (4.0E0,5.0E0), (4.0E0,5.0E0), (4.0E0,5.0E0), + (4.0E0,5.0E0), (0.3E0,-0.4E0), (6.0E0,7.0E0), + (6.0E0,7.0E0), (6.0E0,7.0E0), (6.0E0,7.0E0), + (6.0E0,7.0E0), (6.0E0,7.0E0), (6.0E0,7.0E0), + (0.1E0,-0.3E0), (8.0E0,9.0E0), (0.5E0,-0.1E0), + (2.0E0,5.0E0), (2.0E0,5.0E0), (2.0E0,5.0E0), + (2.0E0,5.0E0), (2.0E0,5.0E0), (0.1E0,0.1E0), + (3.0E0,6.0E0), (-0.6E0,0.1E0), (4.0E0,7.0E0), + (0.1E0,-0.3E0), (7.0E0,2.0E0), (7.0E0,2.0E0), + (7.0E0,2.0E0), (0.3E0,0.1E0), (5.0E0,8.0E0), + (0.5E0,0.0E0), (6.0E0,9.0E0), (0.0E0,0.5E0), + (8.0E0,3.0E0), (0.0E0,0.2E0), (9.0E0,4.0E0)/ DATA STRUE2/0.0E0, 0.5E0, 0.6E0, 0.7E0, 0.8E0/ DATA STRUE4/0.0E0, 0.7E0, 1.0E0, 1.3E0, 1.6E0/ DATA ((CTRUE5(I,J,1),I=1,8),J=1,5)/(0.1E0,0.1E0), + (1.0E0,2.0E0), (1.0E0,2.0E0), (1.0E0,2.0E0), + (1.0E0,2.0E0), (1.0E0,2.0E0), (1.0E0,2.0E0), + (1.0E0,2.0E0), (-0.16E0,-0.37E0), (3.0E0,4.0E0), + (3.0E0,4.0E0), (3.0E0,4.0E0), (3.0E0,4.0E0), + (3.0E0,4.0E0), (3.0E0,4.0E0), (3.0E0,4.0E0), + (-0.17E0,-0.19E0), (0.13E0,-0.39E0), + (5.0E0,6.0E0), (5.0E0,6.0E0), (5.0E0,6.0E0), + (5.0E0,6.0E0), (5.0E0,6.0E0), (5.0E0,6.0E0), + (0.11E0,-0.03E0), (-0.17E0,0.46E0), + (-0.17E0,-0.19E0), (7.0E0,8.0E0), (7.0E0,8.0E0), + (7.0E0,8.0E0), (7.0E0,8.0E0), (7.0E0,8.0E0), + (0.19E0,-0.17E0), (0.20E0,-0.35E0), + (0.35E0,0.20E0), (0.14E0,0.08E0), + (2.0E0,3.0E0), (2.0E0,3.0E0), (2.0E0,3.0E0), + (2.0E0,3.0E0)/ DATA ((CTRUE5(I,J,2),I=1,8),J=1,5)/(0.1E0,0.1E0), + (4.0E0,5.0E0), (4.0E0,5.0E0), (4.0E0,5.0E0), + (4.0E0,5.0E0), (4.0E0,5.0E0), (4.0E0,5.0E0), + (4.0E0,5.0E0), (-0.16E0,-0.37E0), (6.0E0,7.0E0), + (6.0E0,7.0E0), (6.0E0,7.0E0), (6.0E0,7.0E0), + (6.0E0,7.0E0), (6.0E0,7.0E0), (6.0E0,7.0E0), + (-0.17E0,-0.19E0), (8.0E0,9.0E0), + (0.13E0,-0.39E0), (2.0E0,5.0E0), (2.0E0,5.0E0), + (2.0E0,5.0E0), (2.0E0,5.0E0), (2.0E0,5.0E0), + (0.11E0,-0.03E0), (3.0E0,6.0E0), + (-0.17E0,0.46E0), (4.0E0,7.0E0), + (-0.17E0,-0.19E0), (7.0E0,2.0E0), (7.0E0,2.0E0), + (7.0E0,2.0E0), (0.19E0,-0.17E0), (5.0E0,8.0E0), + (0.20E0,-0.35E0), (6.0E0,9.0E0), + (0.35E0,0.20E0), (8.0E0,3.0E0), + (0.14E0,0.08E0), (9.0E0,4.0E0)/ DATA ((CTRUE6(I,J,1),I=1,8),J=1,5)/(0.1E0,0.1E0), + (1.0E0,2.0E0), (1.0E0,2.0E0), (1.0E0,2.0E0), + (1.0E0,2.0E0), (1.0E0,2.0E0), (1.0E0,2.0E0), + (1.0E0,2.0E0), (0.09E0,-0.12E0), (3.0E0,4.0E0), + (3.0E0,4.0E0), (3.0E0,4.0E0), (3.0E0,4.0E0), + (3.0E0,4.0E0), (3.0E0,4.0E0), (3.0E0,4.0E0), + (0.03E0,-0.09E0), (0.15E0,-0.03E0), + (5.0E0,6.0E0), (5.0E0,6.0E0), (5.0E0,6.0E0), + (5.0E0,6.0E0), (5.0E0,6.0E0), (5.0E0,6.0E0), + (0.03E0,0.03E0), (-0.18E0,0.03E0), + (0.03E0,-0.09E0), (7.0E0,8.0E0), (7.0E0,8.0E0), + (7.0E0,8.0E0), (7.0E0,8.0E0), (7.0E0,8.0E0), + (0.09E0,0.03E0), (0.15E0,0.00E0), + (0.00E0,0.15E0), (0.00E0,0.06E0), (2.0E0,3.0E0), + (2.0E0,3.0E0), (2.0E0,3.0E0), (2.0E0,3.0E0)/ DATA ((CTRUE6(I,J,2),I=1,8),J=1,5)/(0.1E0,0.1E0), + (4.0E0,5.0E0), (4.0E0,5.0E0), (4.0E0,5.0E0), + (4.0E0,5.0E0), (4.0E0,5.0E0), (4.0E0,5.0E0), + (4.0E0,5.0E0), (0.09E0,-0.12E0), (6.0E0,7.0E0), + (6.0E0,7.0E0), (6.0E0,7.0E0), (6.0E0,7.0E0), + (6.0E0,7.0E0), (6.0E0,7.0E0), (6.0E0,7.0E0), + (0.03E0,-0.09E0), (8.0E0,9.0E0), + (0.15E0,-0.03E0), (2.0E0,5.0E0), (2.0E0,5.0E0), + (2.0E0,5.0E0), (2.0E0,5.0E0), (2.0E0,5.0E0), + (0.03E0,0.03E0), (3.0E0,6.0E0), + (-0.18E0,0.03E0), (4.0E0,7.0E0), + (0.03E0,-0.09E0), (7.0E0,2.0E0), (7.0E0,2.0E0), + (7.0E0,2.0E0), (0.09E0,0.03E0), (5.0E0,8.0E0), + (0.15E0,0.00E0), (6.0E0,9.0E0), (0.00E0,0.15E0), + (8.0E0,3.0E0), (0.00E0,0.06E0), (9.0E0,4.0E0)/ DATA ITRUE3/0, 1, 2, 2, 2/ * .. Executable Statements .. DO 60 INCX = 1, 2 DO 40 NP1 = 1, 5 N = NP1 - 1 LEN = 2*MAX(N,1) * .. Set vector arguments .. DO 20 I = 1, LEN CX(I) = CV(I,NP1,INCX) 20 CONTINUE IF (ICASE.EQ.6) THEN * .. SCNRM2 .. CALL STEST1(SCNRM2(N,CX,INCX),STRUE2(NP1),STRUE2(NP1), + SFAC) ELSE IF (ICASE.EQ.7) THEN * .. SCASUM .. CALL STEST1(SCASUM(N,CX,INCX),STRUE4(NP1),STRUE4(NP1), + SFAC) ELSE IF (ICASE.EQ.8) THEN * .. CSCAL .. CALL CSCAL(N,CA,CX,INCX) CALL CTEST(LEN,CX,CTRUE5(1,NP1,INCX),CTRUE5(1,NP1,INCX), + SFAC) ELSE IF (ICASE.EQ.9) THEN * .. CSSCAL .. CALL CSSCAL(N,SA,CX,INCX) CALL CTEST(LEN,CX,CTRUE6(1,NP1,INCX),CTRUE6(1,NP1,INCX), + SFAC) ELSE IF (ICASE.EQ.10) THEN * .. ICAMAX .. CALL ITEST1(ICAMAX(N,CX,INCX),ITRUE3(NP1)) ELSE WRITE (NOUT,*) ' Shouldn''t be here in CHECK1' STOP END IF * 40 CONTINUE 60 CONTINUE * INCX = 1 IF (ICASE.EQ.8) THEN * CSCAL * Add a test for alpha equal to zero. CA = (0.0E0,0.0E0) DO 80 I = 1, 5 MWPCT(I) = (0.0E0,0.0E0) MWPCS(I) = (1.0E0,1.0E0) 80 CONTINUE CALL CSCAL(5,CA,CX,INCX) CALL CTEST(5,CX,MWPCT,MWPCS,SFAC) ELSE IF (ICASE.EQ.9) THEN * CSSCAL * Add a test for alpha equal to zero. SA = 0.0E0 DO 100 I = 1, 5 MWPCT(I) = (0.0E0,0.0E0) MWPCS(I) = (1.0E0,1.0E0) 100 CONTINUE CALL CSSCAL(5,SA,CX,INCX) CALL CTEST(5,CX,MWPCT,MWPCS,SFAC) * Add a test for alpha equal to one. SA = 1.0E0 DO 120 I = 1, 5 MWPCT(I) = CX(I) MWPCS(I) = CX(I) 120 CONTINUE CALL CSSCAL(5,SA,CX,INCX) CALL CTEST(5,CX,MWPCT,MWPCS,SFAC) * Add a test for alpha equal to minus one. SA = -1.0E0 DO 140 I = 1, 5 MWPCT(I) = -CX(I) MWPCS(I) = -CX(I) 140 CONTINUE CALL CSSCAL(5,SA,CX,INCX) CALL CTEST(5,CX,MWPCT,MWPCS,SFAC) END IF RETURN END SUBROUTINE CHECK2(SFAC) * .. Parameters .. INTEGER NOUT PARAMETER (NOUT=6) * .. Scalar Arguments .. REAL SFAC * .. Scalars in Common .. INTEGER ICASE, INCX, INCY, MODE, N LOGICAL PASS * .. Local Scalars .. COMPLEX CA INTEGER I, J, KI, KN, KSIZE, LENX, LENY, MX, MY * .. Local Arrays .. COMPLEX CDOT(1), CSIZE1(4), CSIZE2(7,2), CSIZE3(14), + CT10X(7,4,4), CT10Y(7,4,4), CT6(4,4), CT7(4,4), + CT8(7,4,4), CX(7), CX1(7), CY(7), CY1(7) INTEGER INCXS(4), INCYS(4), LENS(4,2), NS(4) * .. External Functions .. COMPLEX CDOTC, CDOTU EXTERNAL CDOTC, CDOTU * .. External Subroutines .. EXTERNAL CAXPY, CCOPY, CSWAP, CTEST * .. Intrinsic Functions .. INTRINSIC ABS, MIN * .. Common blocks .. COMMON /COMBLA/ICASE, N, INCX, INCY, MODE, PASS * .. Data statements .. DATA CA/(0.4E0,-0.7E0)/ DATA INCXS/1, 2, -2, -1/ DATA INCYS/1, -2, 1, -2/ DATA LENS/1, 1, 2, 4, 1, 1, 3, 7/ DATA NS/0, 1, 2, 4/ DATA CX1/(0.7E0,-0.8E0), (-0.4E0,-0.7E0), + (-0.1E0,-0.9E0), (0.2E0,-0.8E0), + (-0.9E0,-0.4E0), (0.1E0,0.4E0), (-0.6E0,0.6E0)/ DATA CY1/(0.6E0,-0.6E0), (-0.9E0,0.5E0), + (0.7E0,-0.6E0), (0.1E0,-0.5E0), (-0.1E0,-0.2E0), + (-0.5E0,-0.3E0), (0.8E0,-0.7E0)/ DATA ((CT8(I,J,1),I=1,7),J=1,4)/(0.6E0,-0.6E0), + (0.0E0,0.0E0), (0.0E0,0.0E0), (0.0E0,0.0E0), + (0.0E0,0.0E0), (0.0E0,0.0E0), (0.0E0,0.0E0), + (0.32E0,-1.41E0), (0.0E0,0.0E0), (0.0E0,0.0E0), + (0.0E0,0.0E0), (0.0E0,0.0E0), (0.0E0,0.0E0), + (0.0E0,0.0E0), (0.32E0,-1.41E0), + (-1.55E0,0.5E0), (0.0E0,0.0E0), (0.0E0,0.0E0), + (0.0E0,0.0E0), (0.0E0,0.0E0), (0.0E0,0.0E0), + (0.32E0,-1.41E0), (-1.55E0,0.5E0), + (0.03E0,-0.89E0), (-0.38E0,-0.96E0), + (0.0E0,0.0E0), (0.0E0,0.0E0), (0.0E0,0.0E0)/ DATA ((CT8(I,J,2),I=1,7),J=1,4)/(0.6E0,-0.6E0), + (0.0E0,0.0E0), (0.0E0,0.0E0), (0.0E0,0.0E0), + (0.0E0,0.0E0), (0.0E0,0.0E0), (0.0E0,0.0E0), + (0.32E0,-1.41E0), (0.0E0,0.0E0), (0.0E0,0.0E0), + (0.0E0,0.0E0), (0.0E0,0.0E0), (0.0E0,0.0E0), + (0.0E0,0.0E0), (-0.07E0,-0.89E0), + (-0.9E0,0.5E0), (0.42E0,-1.41E0), (0.0E0,0.0E0), + (0.0E0,0.0E0), (0.0E0,0.0E0), (0.0E0,0.0E0), + (0.78E0,0.06E0), (-0.9E0,0.5E0), + (0.06E0,-0.13E0), (0.1E0,-0.5E0), + (-0.77E0,-0.49E0), (-0.5E0,-0.3E0), + (0.52E0,-1.51E0)/ DATA ((CT8(I,J,3),I=1,7),J=1,4)/(0.6E0,-0.6E0), + (0.0E0,0.0E0), (0.0E0,0.0E0), (0.0E0,0.0E0), + (0.0E0,0.0E0), (0.0E0,0.0E0), (0.0E0,0.0E0), + (0.32E0,-1.41E0), (0.0E0,0.0E0), (0.0E0,0.0E0), + (0.0E0,0.0E0), (0.0E0,0.0E0), (0.0E0,0.0E0), + (0.0E0,0.0E0), (-0.07E0,-0.89E0), + (-1.18E0,-0.31E0), (0.0E0,0.0E0), (0.0E0,0.0E0), + (0.0E0,0.0E0), (0.0E0,0.0E0), (0.0E0,0.0E0), + (0.78E0,0.06E0), (-1.54E0,0.97E0), + (0.03E0,-0.89E0), (-0.18E0,-1.31E0), + (0.0E0,0.0E0), (0.0E0,0.0E0), (0.0E0,0.0E0)/ DATA ((CT8(I,J,4),I=1,7),J=1,4)/(0.6E0,-0.6E0), + (0.0E0,0.0E0), (0.0E0,0.0E0), (0.0E0,0.0E0), + (0.0E0,0.0E0), (0.0E0,0.0E0), (0.0E0,0.0E0), + (0.32E0,-1.41E0), (0.0E0,0.0E0), (0.0E0,0.0E0), + (0.0E0,0.0E0), (0.0E0,0.0E0), (0.0E0,0.0E0), + (0.0E0,0.0E0), (0.32E0,-1.41E0), (-0.9E0,0.5E0), + (0.05E0,-0.6E0), (0.0E0,0.0E0), (0.0E0,0.0E0), + (0.0E0,0.0E0), (0.0E0,0.0E0), (0.32E0,-1.41E0), + (-0.9E0,0.5E0), (0.05E0,-0.6E0), (0.1E0,-0.5E0), + (-0.77E0,-0.49E0), (-0.5E0,-0.3E0), + (0.32E0,-1.16E0)/ DATA CT7/(0.0E0,0.0E0), (-0.06E0,-0.90E0), + (0.65E0,-0.47E0), (-0.34E0,-1.22E0), + (0.0E0,0.0E0), (-0.06E0,-0.90E0), + (-0.59E0,-1.46E0), (-1.04E0,-0.04E0), + (0.0E0,0.0E0), (-0.06E0,-0.90E0), + (-0.83E0,0.59E0), (0.07E0,-0.37E0), + (0.0E0,0.0E0), (-0.06E0,-0.90E0), + (-0.76E0,-1.15E0), (-1.33E0,-1.82E0)/ DATA CT6/(0.0E0,0.0E0), (0.90E0,0.06E0), + (0.91E0,-0.77E0), (1.80E0,-0.10E0), + (0.0E0,0.0E0), (0.90E0,0.06E0), (1.45E0,0.74E0), + (0.20E0,0.90E0), (0.0E0,0.0E0), (0.90E0,0.06E0), + (-0.55E0,0.23E0), (0.83E0,-0.39E0), + (0.0E0,0.0E0), (0.90E0,0.06E0), (1.04E0,0.79E0), + (1.95E0,1.22E0)/ DATA ((CT10X(I,J,1),I=1,7),J=1,4)/(0.7E0,-0.8E0), + (0.0E0,0.0E0), (0.0E0,0.0E0), (0.0E0,0.0E0), + (0.0E0,0.0E0), (0.0E0,0.0E0), (0.0E0,0.0E0), + (0.6E0,-0.6E0), (0.0E0,0.0E0), (0.0E0,0.0E0), + (0.0E0,0.0E0), (0.0E0,0.0E0), (0.0E0,0.0E0), + (0.0E0,0.0E0), (0.6E0,-0.6E0), (-0.9E0,0.5E0), + (0.0E0,0.0E0), (0.0E0,0.0E0), (0.0E0,0.0E0), + (0.0E0,0.0E0), (0.0E0,0.0E0), (0.6E0,-0.6E0), + (-0.9E0,0.5E0), (0.7E0,-0.6E0), (0.1E0,-0.5E0), + (0.0E0,0.0E0), (0.0E0,0.0E0), (0.0E0,0.0E0)/ DATA ((CT10X(I,J,2),I=1,7),J=1,4)/(0.7E0,-0.8E0), + (0.0E0,0.0E0), (0.0E0,0.0E0), (0.0E0,0.0E0), + (0.0E0,0.0E0), (0.0E0,0.0E0), (0.0E0,0.0E0), + (0.6E0,-0.6E0), (0.0E0,0.0E0), (0.0E0,0.0E0), + (0.0E0,0.0E0), (0.0E0,0.0E0), (0.0E0,0.0E0), + (0.0E0,0.0E0), (0.7E0,-0.6E0), (-0.4E0,-0.7E0), + (0.6E0,-0.6E0), (0.0E0,0.0E0), (0.0E0,0.0E0), + (0.0E0,0.0E0), (0.0E0,0.0E0), (0.8E0,-0.7E0), + (-0.4E0,-0.7E0), (-0.1E0,-0.2E0), + (0.2E0,-0.8E0), (0.7E0,-0.6E0), (0.1E0,0.4E0), + (0.6E0,-0.6E0)/ DATA ((CT10X(I,J,3),I=1,7),J=1,4)/(0.7E0,-0.8E0), + (0.0E0,0.0E0), (0.0E0,0.0E0), (0.0E0,0.0E0), + (0.0E0,0.0E0), (0.0E0,0.0E0), (0.0E0,0.0E0), + (0.6E0,-0.6E0), (0.0E0,0.0E0), (0.0E0,0.0E0), + (0.0E0,0.0E0), (0.0E0,0.0E0), (0.0E0,0.0E0), + (0.0E0,0.0E0), (-0.9E0,0.5E0), (-0.4E0,-0.7E0), + (0.6E0,-0.6E0), (0.0E0,0.0E0), (0.0E0,0.0E0), + (0.0E0,0.0E0), (0.0E0,0.0E0), (0.1E0,-0.5E0), + (-0.4E0,-0.7E0), (0.7E0,-0.6E0), (0.2E0,-0.8E0), + (-0.9E0,0.5E0), (0.1E0,0.4E0), (0.6E0,-0.6E0)/ DATA ((CT10X(I,J,4),I=1,7),J=1,4)/(0.7E0,-0.8E0), + (0.0E0,0.0E0), (0.0E0,0.0E0), (0.0E0,0.0E0), + (0.0E0,0.0E0), (0.0E0,0.0E0), (0.0E0,0.0E0), + (0.6E0,-0.6E0), (0.0E0,0.0E0), (0.0E0,0.0E0), + (0.0E0,0.0E0), (0.0E0,0.0E0), (0.0E0,0.0E0), + (0.0E0,0.0E0), (0.6E0,-0.6E0), (0.7E0,-0.6E0), + (0.0E0,0.0E0), (0.0E0,0.0E0), (0.0E0,0.0E0), + (0.0E0,0.0E0), (0.0E0,0.0E0), (0.6E0,-0.6E0), + (0.7E0,-0.6E0), (-0.1E0,-0.2E0), (0.8E0,-0.7E0), + (0.0E0,0.0E0), (0.0E0,0.0E0), (0.0E0,0.0E0)/ DATA ((CT10Y(I,J,1),I=1,7),J=1,4)/(0.6E0,-0.6E0), + (0.0E0,0.0E0), (0.0E0,0.0E0), (0.0E0,0.0E0), + (0.0E0,0.0E0), (0.0E0,0.0E0), (0.0E0,0.0E0), + (0.7E0,-0.8E0), (0.0E0,0.0E0), (0.0E0,0.0E0), + (0.0E0,0.0E0), (0.0E0,0.0E0), (0.0E0,0.0E0), + (0.0E0,0.0E0), (0.7E0,-0.8E0), (-0.4E0,-0.7E0), + (0.0E0,0.0E0), (0.0E0,0.0E0), (0.0E0,0.0E0), + (0.0E0,0.0E0), (0.0E0,0.0E0), (0.7E0,-0.8E0), + (-0.4E0,-0.7E0), (-0.1E0,-0.9E0), + (0.2E0,-0.8E0), (0.0E0,0.0E0), (0.0E0,0.0E0), + (0.0E0,0.0E0)/ DATA ((CT10Y(I,J,2),I=1,7),J=1,4)/(0.6E0,-0.6E0), + (0.0E0,0.0E0), (0.0E0,0.0E0), (0.0E0,0.0E0), + (0.0E0,0.0E0), (0.0E0,0.0E0), (0.0E0,0.0E0), + (0.7E0,-0.8E0), (0.0E0,0.0E0), (0.0E0,0.0E0), + (0.0E0,0.0E0), (0.0E0,0.0E0), (0.0E0,0.0E0), + (0.0E0,0.0E0), (-0.1E0,-0.9E0), (-0.9E0,0.5E0), + (0.7E0,-0.8E0), (0.0E0,0.0E0), (0.0E0,0.0E0), + (0.0E0,0.0E0), (0.0E0,0.0E0), (-0.6E0,0.6E0), + (-0.9E0,0.5E0), (-0.9E0,-0.4E0), (0.1E0,-0.5E0), + (-0.1E0,-0.9E0), (-0.5E0,-0.3E0), + (0.7E0,-0.8E0)/ DATA ((CT10Y(I,J,3),I=1,7),J=1,4)/(0.6E0,-0.6E0), + (0.0E0,0.0E0), (0.0E0,0.0E0), (0.0E0,0.0E0), + (0.0E0,0.0E0), (0.0E0,0.0E0), (0.0E0,0.0E0), + (0.7E0,-0.8E0), (0.0E0,0.0E0), (0.0E0,0.0E0), + (0.0E0,0.0E0), (0.0E0,0.0E0), (0.0E0,0.0E0), + (0.0E0,0.0E0), (-0.1E0,-0.9E0), (0.7E0,-0.8E0), + (0.0E0,0.0E0), (0.0E0,0.0E0), (0.0E0,0.0E0), + (0.0E0,0.0E0), (0.0E0,0.0E0), (-0.6E0,0.6E0), + (-0.9E0,-0.4E0), (-0.1E0,-0.9E0), + (0.7E0,-0.8E0), (0.0E0,0.0E0), (0.0E0,0.0E0), + (0.0E0,0.0E0)/ DATA ((CT10Y(I,J,4),I=1,7),J=1,4)/(0.6E0,-0.6E0), + (0.0E0,0.0E0), (0.0E0,0.0E0), (0.0E0,0.0E0), + (0.0E0,0.0E0), (0.0E0,0.0E0), (0.0E0,0.0E0), + (0.7E0,-0.8E0), (0.0E0,0.0E0), (0.0E0,0.0E0), + (0.0E0,0.0E0), (0.0E0,0.0E0), (0.0E0,0.0E0), + (0.0E0,0.0E0), (0.7E0,-0.8E0), (-0.9E0,0.5E0), + (-0.4E0,-0.7E0), (0.0E0,0.0E0), (0.0E0,0.0E0), + (0.0E0,0.0E0), (0.0E0,0.0E0), (0.7E0,-0.8E0), + (-0.9E0,0.5E0), (-0.4E0,-0.7E0), (0.1E0,-0.5E0), + (-0.1E0,-0.9E0), (-0.5E0,-0.3E0), + (0.2E0,-0.8E0)/ DATA CSIZE1/(0.0E0,0.0E0), (0.9E0,0.9E0), + (1.63E0,1.73E0), (2.90E0,2.78E0)/ DATA CSIZE3/(0.0E0,0.0E0), (0.0E0,0.0E0), + (0.0E0,0.0E0), (0.0E0,0.0E0), (0.0E0,0.0E0), + (0.0E0,0.0E0), (0.0E0,0.0E0), (1.17E0,1.17E0), + (1.17E0,1.17E0), (1.17E0,1.17E0), + (1.17E0,1.17E0), (1.17E0,1.17E0), + (1.17E0,1.17E0), (1.17E0,1.17E0)/ DATA CSIZE2/(0.0E0,0.0E0), (0.0E0,0.0E0), + (0.0E0,0.0E0), (0.0E0,0.0E0), (0.0E0,0.0E0), + (0.0E0,0.0E0), (0.0E0,0.0E0), (1.54E0,1.54E0), + (1.54E0,1.54E0), (1.54E0,1.54E0), + (1.54E0,1.54E0), (1.54E0,1.54E0), + (1.54E0,1.54E0), (1.54E0,1.54E0)/ * .. Executable Statements .. DO 60 KI = 1, 4 INCX = INCXS(KI) INCY = INCYS(KI) MX = ABS(INCX) MY = ABS(INCY) * DO 40 KN = 1, 4 N = NS(KN) KSIZE = MIN(2,KN) LENX = LENS(KN,MX) LENY = LENS(KN,MY) * .. initialize all argument arrays .. DO 20 I = 1, 7 CX(I) = CX1(I) CY(I) = CY1(I) 20 CONTINUE IF (ICASE.EQ.1) THEN * .. CDOTC .. CDOT(1) = CDOTC(N,CX,INCX,CY,INCY) CALL CTEST(1,CDOT,CT6(KN,KI),CSIZE1(KN),SFAC) ELSE IF (ICASE.EQ.2) THEN * .. CDOTU .. CDOT(1) = CDOTU(N,CX,INCX,CY,INCY) CALL CTEST(1,CDOT,CT7(KN,KI),CSIZE1(KN),SFAC) ELSE IF (ICASE.EQ.3) THEN * .. CAXPY .. CALL CAXPY(N,CA,CX,INCX,CY,INCY) CALL CTEST(LENY,CY,CT8(1,KN,KI),CSIZE2(1,KSIZE),SFAC) ELSE IF (ICASE.EQ.4) THEN * .. CCOPY .. CALL CCOPY(N,CX,INCX,CY,INCY) CALL CTEST(LENY,CY,CT10Y(1,KN,KI),CSIZE3,1.0E0) ELSE IF (ICASE.EQ.5) THEN * .. CSWAP .. CALL CSWAP(N,CX,INCX,CY,INCY) CALL CTEST(LENX,CX,CT10X(1,KN,KI),CSIZE3,1.0E0) CALL CTEST(LENY,CY,CT10Y(1,KN,KI),CSIZE3,1.0E0) ELSE WRITE (NOUT,*) ' Shouldn''t be here in CHECK2' STOP END IF * 40 CONTINUE 60 CONTINUE RETURN END SUBROUTINE STEST(LEN,SCOMP,STRUE,SSIZE,SFAC) * ********************************* STEST ************************** * * THIS SUBR COMPARES ARRAYS SCOMP() AND STRUE() OF LENGTH LEN TO * SEE IF THE TERM BY TERM DIFFERENCES, MULTIPLIED BY SFAC, ARE * NEGLIGIBLE. * * C. L. LAWSON, JPL, 1974 DEC 10 * * .. Parameters .. INTEGER NOUT REAL ZERO PARAMETER (NOUT=6, ZERO=0.0E0) * .. Scalar Arguments .. REAL SFAC INTEGER LEN * .. Array Arguments .. REAL SCOMP(LEN), SSIZE(LEN), STRUE(LEN) * .. Scalars in Common .. INTEGER ICASE, INCX, INCY, MODE, N LOGICAL PASS * .. Local Scalars .. REAL SD INTEGER I * .. External Functions .. REAL SDIFF EXTERNAL SDIFF * .. Intrinsic Functions .. INTRINSIC ABS * .. Common blocks .. COMMON /COMBLA/ICASE, N, INCX, INCY, MODE, PASS * .. Executable Statements .. * DO 40 I = 1, LEN SD = SCOMP(I) - STRUE(I) IF (ABS(SFAC*SD) .LE. ABS(SSIZE(I))*EPSILON(ZERO)) + GO TO 40 * * HERE SCOMP(I) IS NOT CLOSE TO STRUE(I). * IF ( .NOT. PASS) GO TO 20 * PRINT FAIL MESSAGE AND HEADER. PASS = .FALSE. WRITE (NOUT,99999) WRITE (NOUT,99998) 20 WRITE (NOUT,99997) ICASE, N, INCX, INCY, MODE, I, SCOMP(I), + STRUE(I), SD, SSIZE(I) 40 CONTINUE RETURN * 99999 FORMAT (' FAIL') 99998 FORMAT (/' CASE N INCX INCY MODE I ', + ' COMP(I) TRUE(I) DIFFERENCE', + ' SIZE(I)',/1X) 99997 FORMAT (1X,I4,I3,3I5,I3,2E36.8,2E12.4) END SUBROUTINE STEST1(SCOMP1,STRUE1,SSIZE,SFAC) * ************************* STEST1 ***************************** * * THIS IS AN INTERFACE SUBROUTINE TO ACCOMODATE THE FORTRAN * REQUIREMENT THAT WHEN A DUMMY ARGUMENT IS AN ARRAY, THE * ACTUAL ARGUMENT MUST ALSO BE AN ARRAY OR AN ARRAY ELEMENT. * * C.L. LAWSON, JPL, 1978 DEC 6 * * .. Scalar Arguments .. REAL SCOMP1, SFAC, STRUE1 * .. Array Arguments .. REAL SSIZE(*) * .. Local Arrays .. REAL SCOMP(1), STRUE(1) * .. External Subroutines .. EXTERNAL STEST * .. Executable Statements .. * SCOMP(1) = SCOMP1 STRUE(1) = STRUE1 CALL STEST(1,SCOMP,STRUE,SSIZE,SFAC) * RETURN END REAL FUNCTION SDIFF(SA,SB) * ********************************* SDIFF ************************** * COMPUTES DIFFERENCE OF TWO NUMBERS. C. L. LAWSON, JPL 1974 FEB 15 * * .. Scalar Arguments .. REAL SA, SB * .. Executable Statements .. SDIFF = SA - SB RETURN END SUBROUTINE CTEST(LEN,CCOMP,CTRUE,CSIZE,SFAC) * **************************** CTEST ***************************** * * C.L. LAWSON, JPL, 1978 DEC 6 * * .. Scalar Arguments .. REAL SFAC INTEGER LEN * .. Array Arguments .. COMPLEX CCOMP(LEN), CSIZE(LEN), CTRUE(LEN) * .. Local Scalars .. INTEGER I * .. Local Arrays .. REAL SCOMP(20), SSIZE(20), STRUE(20) * .. External Subroutines .. EXTERNAL STEST * .. Intrinsic Functions .. INTRINSIC AIMAG, REAL * .. Executable Statements .. DO 20 I = 1, LEN SCOMP(2*I-1) = REAL(CCOMP(I)) SCOMP(2*I) = AIMAG(CCOMP(I)) STRUE(2*I-1) = REAL(CTRUE(I)) STRUE(2*I) = AIMAG(CTRUE(I)) SSIZE(2*I-1) = REAL(CSIZE(I)) SSIZE(2*I) = AIMAG(CSIZE(I)) 20 CONTINUE * CALL STEST(2*LEN,SCOMP,STRUE,SSIZE,SFAC) RETURN END SUBROUTINE ITEST1(ICOMP,ITRUE) * ********************************* ITEST1 ************************* * * THIS SUBROUTINE COMPARES THE VARIABLES ICOMP AND ITRUE FOR * EQUALITY. * C. L. LAWSON, JPL, 1974 DEC 10 * * .. Parameters .. INTEGER NOUT PARAMETER (NOUT=6) * .. Scalar Arguments .. INTEGER ICOMP, ITRUE * .. Scalars in Common .. INTEGER ICASE, INCX, INCY, MODE, N LOGICAL PASS * .. Local Scalars .. INTEGER ID * .. Common blocks .. COMMON /COMBLA/ICASE, N, INCX, INCY, MODE, PASS * .. Executable Statements .. IF (ICOMP.EQ.ITRUE) GO TO 40 * * HERE ICOMP IS NOT EQUAL TO ITRUE. * IF ( .NOT. PASS) GO TO 20 * PRINT FAIL MESSAGE AND HEADER. PASS = .FALSE. WRITE (NOUT,99999) WRITE (NOUT,99998) 20 ID = ICOMP - ITRUE WRITE (NOUT,99997) ICASE, N, INCX, INCY, MODE, ICOMP, ITRUE, ID 40 CONTINUE RETURN * 99999 FORMAT (' FAIL') 99998 FORMAT (/' CASE N INCX INCY MODE ', + ' COMP TRUE DIFFERENCE', + /1X) 99997 FORMAT (1X,I4,I3,3I5,2I36,I12) END blis-0.9.0/blastest/src/fortran/cblat2.f000066400000000000000000003436611422157504600200750ustar00rootroot00000000000000*> \brief \b CBLAT2 * * =========== DOCUMENTATION =========== * * Online html documentation available at * http://www.netlib.org/lapack/explore-html/ * * Definition: * =========== * * PROGRAM CBLAT2 * * *> \par Purpose: * ============= *> *> \verbatim *> *> Test program for the COMPLEX Level 2 Blas. *> *> The program must be driven by a short data file. The first 18 records *> of the file are read using list-directed input, the last 17 records *> are read using the format ( A6, L2 ). An annotated example of a data *> file can be obtained by deleting the first 3 characters from the *> following 35 lines: *> 'cblat2.out' NAME OF SUMMARY OUTPUT FILE *> 6 UNIT NUMBER OF SUMMARY FILE *> 'CBLA2T.SNAP' NAME OF SNAPSHOT OUTPUT FILE *> -1 UNIT NUMBER OF SNAPSHOT FILE (NOT USED IF .LT. 0) *> F LOGICAL FLAG, T TO REWIND SNAPSHOT FILE AFTER EACH RECORD. *> F LOGICAL FLAG, T TO STOP ON FAILURES. *> T LOGICAL FLAG, T TO TEST ERROR EXITS. *> 16.0 THRESHOLD VALUE OF TEST RATIO *> 6 NUMBER OF VALUES OF N *> 0 1 2 3 5 9 VALUES OF N *> 4 NUMBER OF VALUES OF K *> 0 1 2 4 VALUES OF K *> 4 NUMBER OF VALUES OF INCX AND INCY *> 1 2 -1 -2 VALUES OF INCX AND INCY *> 3 NUMBER OF VALUES OF ALPHA *> (0.0,0.0) (1.0,0.0) (0.7,-0.9) VALUES OF ALPHA *> 3 NUMBER OF VALUES OF BETA *> (0.0,0.0) (1.0,0.0) (1.3,-1.1) VALUES OF BETA *> CGEMV T PUT F FOR NO TEST. SAME COLUMNS. *> CGBMV T PUT F FOR NO TEST. SAME COLUMNS. *> CHEMV T PUT F FOR NO TEST. SAME COLUMNS. *> CHBMV T PUT F FOR NO TEST. SAME COLUMNS. *> CHPMV T PUT F FOR NO TEST. SAME COLUMNS. *> CTRMV T PUT F FOR NO TEST. SAME COLUMNS. *> CTBMV T PUT F FOR NO TEST. SAME COLUMNS. *> CTPMV T PUT F FOR NO TEST. SAME COLUMNS. *> CTRSV T PUT F FOR NO TEST. SAME COLUMNS. *> CTBSV T PUT F FOR NO TEST. SAME COLUMNS. *> CTPSV T PUT F FOR NO TEST. SAME COLUMNS. *> CGERC T PUT F FOR NO TEST. SAME COLUMNS. *> CGERU T PUT F FOR NO TEST. SAME COLUMNS. *> CHER T PUT F FOR NO TEST. SAME COLUMNS. *> CHPR T PUT F FOR NO TEST. SAME COLUMNS. *> CHER2 T PUT F FOR NO TEST. SAME COLUMNS. *> CHPR2 T PUT F FOR NO TEST. SAME COLUMNS. *> *> Further Details *> =============== *> *> See: *> *> Dongarra J. J., Du Croz J. J., Hammarling S. and Hanson R. J.. *> An extended set of Fortran Basic Linear Algebra Subprograms. *> *> Technical Memoranda Nos. 41 (revision 3) and 81, Mathematics *> and Computer Science Division, Argonne National Laboratory, *> 9700 South Cass Avenue, Argonne, Illinois 60439, US. *> *> Or *> *> NAG Technical Reports TR3/87 and TR4/87, Numerical Algorithms *> Group Ltd., NAG Central Office, 256 Banbury Road, Oxford *> OX2 7DE, UK, and Numerical Algorithms Group Inc., 1101 31st *> Street, Suite 100, Downers Grove, Illinois 60515-1263, USA. *> *> *> -- Written on 10-August-1987. *> Richard Hanson, Sandia National Labs. *> Jeremy Du Croz, NAG Central Office. *> *> 10-9-00: Change STATUS='NEW' to 'UNKNOWN' so that the testers *> can be run multiple times without deleting generated *> output files (susan) *> \endverbatim * * Authors: * ======== * *> \author Univ. of Tennessee *> \author Univ. of California Berkeley *> \author Univ. of Colorado Denver *> \author NAG Ltd. * *> \date April 2012 * *> \ingroup complex_blas_testing * * ===================================================================== PROGRAM CBLAT2 * * -- Reference BLAS test routine (version 3.4.1) -- * -- Reference BLAS is a software package provided by Univ. of Tennessee, -- * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- * April 2012 * * ===================================================================== * * .. Parameters .. INTEGER NIN PARAMETER ( NIN = 5 ) INTEGER NSUBS PARAMETER ( NSUBS = 17 ) COMPLEX ZERO, ONE PARAMETER ( ZERO = ( 0.0, 0.0 ), ONE = ( 1.0, 0.0 ) ) REAL RZERO PARAMETER ( RZERO = 0.0 ) INTEGER NMAX, INCMAX PARAMETER ( NMAX = 65, INCMAX = 2 ) INTEGER NINMAX, NIDMAX, NKBMAX, NALMAX, NBEMAX PARAMETER ( NINMAX = 7, NIDMAX = 9, NKBMAX = 7, $ NALMAX = 7, NBEMAX = 7 ) * .. Local Scalars .. REAL EPS, ERR, THRESH INTEGER I, ISNUM, J, N, NALF, NBET, NIDIM, NINC, NKB, $ NOUT, NTRA LOGICAL FATAL, LTESTT, REWI, SAME, SFATAL, TRACE, $ TSTERR CHARACTER*1 TRANS CHARACTER*6 SNAMET CHARACTER*32 SNAPS, SUMMRY * .. Local Arrays .. COMPLEX A( NMAX, NMAX ), AA( NMAX*NMAX ), $ ALF( NALMAX ), AS( NMAX*NMAX ), BET( NBEMAX ), $ X( NMAX ), XS( NMAX*INCMAX ), $ XX( NMAX*INCMAX ), Y( NMAX ), $ YS( NMAX*INCMAX ), YT( NMAX ), $ YY( NMAX*INCMAX ), Z( 2*NMAX ) REAL G( NMAX ) INTEGER IDIM( NIDMAX ), INC( NINMAX ), KB( NKBMAX ) LOGICAL LTEST( NSUBS ) CHARACTER*6 SNAMES( NSUBS ) * .. External Functions .. REAL SDIFF LOGICAL LCE EXTERNAL SDIFF, LCE * .. External Subroutines .. EXTERNAL CCHK1, CCHK2, CCHK3, CCHK4, CCHK5, CCHK6, $ CCHKE, CMVCH * .. Intrinsic Functions .. INTRINSIC ABS, MAX, MIN * .. Scalars in Common .. INTEGER INFOT, NOUTC LOGICAL LERR, OK CHARACTER*6 SRNAMT * .. Common blocks .. COMMON /INFOC/INFOT, NOUTC, OK, LERR COMMON /SRNAMC/SRNAMT * .. Data statements .. DATA SNAMES/'CGEMV ', 'CGBMV ', 'CHEMV ', 'CHBMV ', $ 'CHPMV ', 'CTRMV ', 'CTBMV ', 'CTPMV ', $ 'CTRSV ', 'CTBSV ', 'CTPSV ', 'CGERC ', $ 'CGERU ', 'CHER ', 'CHPR ', 'CHER2 ', $ 'CHPR2 '/ * .. Executable Statements .. * * Read name and unit number for summary output file and open file. * READ( NIN, FMT = * )SUMMRY READ( NIN, FMT = * )NOUT OPEN( NOUT, FILE = SUMMRY, STATUS = 'UNKNOWN' ) NOUTC = NOUT * * Read name and unit number for snapshot output file and open file. * READ( NIN, FMT = * )SNAPS READ( NIN, FMT = * )NTRA TRACE = NTRA.GE.0 IF( TRACE )THEN OPEN( NTRA, FILE = SNAPS, STATUS = 'UNKNOWN' ) END IF * Read the flag that directs rewinding of the snapshot file. READ( NIN, FMT = * )REWI REWI = REWI.AND.TRACE * Read the flag that directs stopping on any failure. READ( NIN, FMT = * )SFATAL * Read the flag that indicates whether error exits are to be tested. READ( NIN, FMT = * )TSTERR * Read the threshold value of the test ratio READ( NIN, FMT = * )THRESH * * Read and check the parameter values for the tests. * * Values of N READ( NIN, FMT = * )NIDIM IF( NIDIM.LT.1.OR.NIDIM.GT.NIDMAX )THEN WRITE( NOUT, FMT = 9997 )'N', NIDMAX GO TO 230 END IF READ( NIN, FMT = * )( IDIM( I ), I = 1, NIDIM ) DO 10 I = 1, NIDIM IF( IDIM( I ).LT.0.OR.IDIM( I ).GT.NMAX )THEN WRITE( NOUT, FMT = 9996 )NMAX GO TO 230 END IF 10 CONTINUE * Values of K READ( NIN, FMT = * )NKB IF( NKB.LT.1.OR.NKB.GT.NKBMAX )THEN WRITE( NOUT, FMT = 9997 )'K', NKBMAX GO TO 230 END IF READ( NIN, FMT = * )( KB( I ), I = 1, NKB ) DO 20 I = 1, NKB IF( KB( I ).LT.0 )THEN WRITE( NOUT, FMT = 9995 ) GO TO 230 END IF 20 CONTINUE * Values of INCX and INCY READ( NIN, FMT = * )NINC IF( NINC.LT.1.OR.NINC.GT.NINMAX )THEN WRITE( NOUT, FMT = 9997 )'INCX AND INCY', NINMAX GO TO 230 END IF READ( NIN, FMT = * )( INC( I ), I = 1, NINC ) DO 30 I = 1, NINC IF( INC( I ).EQ.0.OR.ABS( INC( I ) ).GT.INCMAX )THEN WRITE( NOUT, FMT = 9994 )INCMAX GO TO 230 END IF 30 CONTINUE * Values of ALPHA READ( NIN, FMT = * )NALF IF( NALF.LT.1.OR.NALF.GT.NALMAX )THEN WRITE( NOUT, FMT = 9997 )'ALPHA', NALMAX GO TO 230 END IF READ( NIN, FMT = * )( ALF( I ), I = 1, NALF ) * Values of BETA READ( NIN, FMT = * )NBET IF( NBET.LT.1.OR.NBET.GT.NBEMAX )THEN WRITE( NOUT, FMT = 9997 )'BETA', NBEMAX GO TO 230 END IF READ( NIN, FMT = * )( BET( I ), I = 1, NBET ) * * Report values of parameters. * WRITE( NOUT, FMT = 9993 ) WRITE( NOUT, FMT = 9992 )( IDIM( I ), I = 1, NIDIM ) WRITE( NOUT, FMT = 9991 )( KB( I ), I = 1, NKB ) WRITE( NOUT, FMT = 9990 )( INC( I ), I = 1, NINC ) WRITE( NOUT, FMT = 9989 )( ALF( I ), I = 1, NALF ) WRITE( NOUT, FMT = 9988 )( BET( I ), I = 1, NBET ) IF( .NOT.TSTERR )THEN WRITE( NOUT, FMT = * ) WRITE( NOUT, FMT = 9980 ) END IF WRITE( NOUT, FMT = * ) WRITE( NOUT, FMT = 9999 )THRESH WRITE( NOUT, FMT = * ) * * Read names of subroutines and flags which indicate * whether they are to be tested. * DO 40 I = 1, NSUBS LTEST( I ) = .FALSE. 40 CONTINUE 50 READ( NIN, FMT = 9984, END = 80 )SNAMET, LTESTT DO 60 I = 1, NSUBS IF( SNAMET.EQ.SNAMES( I ) ) $ GO TO 70 60 CONTINUE WRITE( NOUT, FMT = 9986 )SNAMET STOP 70 LTEST( I ) = LTESTT GO TO 50 * 80 CONTINUE CLOSE ( NIN ) * * Compute EPS (the machine precision). * EPS = EPSILON(RZERO) WRITE( NOUT, FMT = 9998 )EPS * * Check the reliability of CMVCH using exact data. * N = MIN( 32, NMAX ) DO 120 J = 1, N DO 110 I = 1, N A( I, J ) = MAX( I - J + 1, 0 ) 110 CONTINUE X( J ) = J Y( J ) = ZERO 120 CONTINUE DO 130 J = 1, N YY( J ) = J*( ( J + 1 )*J )/2 - ( ( J + 1 )*J*( J - 1 ) )/3 130 CONTINUE * YY holds the exact result. On exit from CMVCH YT holds * the result computed by CMVCH. TRANS = 'N' CALL CMVCH( TRANS, N, N, ONE, A, NMAX, X, 1, ZERO, Y, 1, YT, G, $ YY, EPS, ERR, FATAL, NOUT, .TRUE. ) SAME = LCE( YY, YT, N ) IF( .NOT.SAME.OR.ERR.NE.RZERO )THEN WRITE( NOUT, FMT = 9985 )TRANS, SAME, ERR STOP END IF TRANS = 'T' CALL CMVCH( TRANS, N, N, ONE, A, NMAX, X, -1, ZERO, Y, -1, YT, G, $ YY, EPS, ERR, FATAL, NOUT, .TRUE. ) SAME = LCE( YY, YT, N ) IF( .NOT.SAME.OR.ERR.NE.RZERO )THEN WRITE( NOUT, FMT = 9985 )TRANS, SAME, ERR STOP END IF * * Test each subroutine in turn. * DO 210 ISNUM = 1, NSUBS WRITE( NOUT, FMT = * ) IF( .NOT.LTEST( ISNUM ) )THEN * Subprogram is not to be tested. WRITE( NOUT, FMT = 9983 )SNAMES( ISNUM ) ELSE SRNAMT = SNAMES( ISNUM ) * Test error exits. IF( TSTERR )THEN CALL CCHKE( ISNUM, SNAMES( ISNUM ), NOUT ) WRITE( NOUT, FMT = * ) END IF * Test computations. INFOT = 0 OK = .TRUE. FATAL = .FALSE. GO TO ( 140, 140, 150, 150, 150, 160, 160, $ 160, 160, 160, 160, 170, 170, 180, $ 180, 190, 190 )ISNUM * Test CGEMV, 01, and CGBMV, 02. 140 CALL CCHK1( SNAMES( ISNUM ), EPS, THRESH, NOUT, NTRA, TRACE, $ REWI, FATAL, NIDIM, IDIM, NKB, KB, NALF, ALF, $ NBET, BET, NINC, INC, NMAX, INCMAX, A, AA, AS, $ X, XX, XS, Y, YY, YS, YT, G ) GO TO 200 * Test CHEMV, 03, CHBMV, 04, and CHPMV, 05. 150 CALL CCHK2( SNAMES( ISNUM ), EPS, THRESH, NOUT, NTRA, TRACE, $ REWI, FATAL, NIDIM, IDIM, NKB, KB, NALF, ALF, $ NBET, BET, NINC, INC, NMAX, INCMAX, A, AA, AS, $ X, XX, XS, Y, YY, YS, YT, G ) GO TO 200 * Test CTRMV, 06, CTBMV, 07, CTPMV, 08, * CTRSV, 09, CTBSV, 10, and CTPSV, 11. 160 CALL CCHK3( SNAMES( ISNUM ), EPS, THRESH, NOUT, NTRA, TRACE, $ REWI, FATAL, NIDIM, IDIM, NKB, KB, NINC, INC, $ NMAX, INCMAX, A, AA, AS, Y, YY, YS, YT, G, Z ) GO TO 200 * Test CGERC, 12, CGERU, 13. 170 CALL CCHK4( SNAMES( ISNUM ), EPS, THRESH, NOUT, NTRA, TRACE, $ REWI, FATAL, NIDIM, IDIM, NALF, ALF, NINC, INC, $ NMAX, INCMAX, A, AA, AS, X, XX, XS, Y, YY, YS, $ YT, G, Z ) GO TO 200 * Test CHER, 14, and CHPR, 15. 180 CALL CCHK5( SNAMES( ISNUM ), EPS, THRESH, NOUT, NTRA, TRACE, $ REWI, FATAL, NIDIM, IDIM, NALF, ALF, NINC, INC, $ NMAX, INCMAX, A, AA, AS, X, XX, XS, Y, YY, YS, $ YT, G, Z ) GO TO 200 * Test CHER2, 16, and CHPR2, 17. 190 CALL CCHK6( SNAMES( ISNUM ), EPS, THRESH, NOUT, NTRA, TRACE, $ REWI, FATAL, NIDIM, IDIM, NALF, ALF, NINC, INC, $ NMAX, INCMAX, A, AA, AS, X, XX, XS, Y, YY, YS, $ YT, G, Z ) * 200 IF( FATAL.AND.SFATAL ) $ GO TO 220 END IF 210 CONTINUE WRITE( NOUT, FMT = 9982 ) GO TO 240 * 220 CONTINUE WRITE( NOUT, FMT = 9981 ) GO TO 240 * 230 CONTINUE WRITE( NOUT, FMT = 9987 ) * 240 CONTINUE IF( TRACE ) $ CLOSE ( NTRA ) CLOSE ( NOUT ) STOP * 9999 FORMAT( ' ROUTINES PASS COMPUTATIONAL TESTS IF TEST RATIO IS LES', $ 'S THAN', F8.2 ) 9998 FORMAT( ' RELATIVE MACHINE PRECISION IS TAKEN TO BE', 1P, E9.1 ) 9997 FORMAT( ' NUMBER OF VALUES OF ', A, ' IS LESS THAN 1 OR GREATER ', $ 'THAN ', I2 ) 9996 FORMAT( ' VALUE OF N IS LESS THAN 0 OR GREATER THAN ', I2 ) 9995 FORMAT( ' VALUE OF K IS LESS THAN 0' ) 9994 FORMAT( ' ABSOLUTE VALUE OF INCX OR INCY IS 0 OR GREATER THAN ', $ I2 ) 9993 FORMAT( ' TESTS OF THE COMPLEX LEVEL 2 BLAS', //' THE F', $ 'OLLOWING PARAMETER VALUES WILL BE USED:' ) 9992 FORMAT( ' FOR N ', 9I6 ) 9991 FORMAT( ' FOR K ', 7I6 ) 9990 FORMAT( ' FOR INCX AND INCY ', 7I6 ) 9989 FORMAT( ' FOR ALPHA ', $ 7( '(', F4.1, ',', F4.1, ') ', : ) ) 9988 FORMAT( ' FOR BETA ', $ 7( '(', F4.1, ',', F4.1, ') ', : ) ) 9987 FORMAT( ' AMEND DATA FILE OR INCREASE ARRAY SIZES IN PROGRAM', $ /' ******* TESTS ABANDONED *******' ) 9986 FORMAT( ' SUBPROGRAM NAME ', A6, ' NOT RECOGNIZED', /' ******* T', $ 'ESTS ABANDONED *******' ) 9985 FORMAT( ' ERROR IN CMVCH - IN-LINE DOT PRODUCTS ARE BEING EVALU', $ 'ATED WRONGLY.', /' CMVCH WAS CALLED WITH TRANS = ', A1, $ ' AND RETURNED SAME = ', L1, ' AND ERR = ', F12.3, '.', / $ ' THIS MAY BE DUE TO FAULTS IN THE ARITHMETIC OR THE COMPILER.' $ , /' ******* TESTS ABANDONED *******' ) 9984 FORMAT( A6, L2 ) 9983 FORMAT( 1X, A6, ' WAS NOT TESTED' ) 9982 FORMAT( /' END OF TESTS' ) 9981 FORMAT( /' ******* FATAL ERROR - TESTS ABANDONED *******' ) 9980 FORMAT( ' ERROR-EXITS WILL NOT BE TESTED' ) * * End of CBLAT2. * END SUBROUTINE CCHK1( SNAME, EPS, THRESH, NOUT, NTRA, TRACE, REWI, $ FATAL, NIDIM, IDIM, NKB, KB, NALF, ALF, NBET, $ BET, NINC, INC, NMAX, INCMAX, A, AA, AS, X, XX, $ XS, Y, YY, YS, YT, G ) * * Tests CGEMV and CGBMV. * * Auxiliary routine for test program for Level 2 Blas. * * -- Written on 10-August-1987. * Richard Hanson, Sandia National Labs. * Jeremy Du Croz, NAG Central Office. * * .. Parameters .. COMPLEX ZERO, HALF PARAMETER ( ZERO = ( 0.0, 0.0 ), HALF = ( 0.5, 0.0 ) ) REAL RZERO PARAMETER ( RZERO = 0.0 ) * .. Scalar Arguments .. REAL EPS, THRESH INTEGER INCMAX, NALF, NBET, NIDIM, NINC, NKB, NMAX, $ NOUT, NTRA LOGICAL FATAL, REWI, TRACE CHARACTER*6 SNAME * .. Array Arguments .. COMPLEX A( NMAX, NMAX ), AA( NMAX*NMAX ), ALF( NALF ), $ AS( NMAX*NMAX ), BET( NBET ), X( NMAX ), $ XS( NMAX*INCMAX ), XX( NMAX*INCMAX ), $ Y( NMAX ), YS( NMAX*INCMAX ), YT( NMAX ), $ YY( NMAX*INCMAX ) REAL G( NMAX ) INTEGER IDIM( NIDIM ), INC( NINC ), KB( NKB ) * .. Local Scalars .. COMPLEX ALPHA, ALS, BETA, BLS, TRANSL REAL ERR, ERRMAX INTEGER I, IA, IB, IC, IKU, IM, IN, INCX, INCXS, INCY, $ INCYS, IX, IY, KL, KLS, KU, KUS, LAA, LDA, $ LDAS, LX, LY, M, ML, MS, N, NARGS, NC, ND, NK, $ NL, NS LOGICAL BANDED, FULL, NULL, RESET, SAME, TRAN CHARACTER*1 TRANS, TRANSS CHARACTER*3 ICH * .. Local Arrays .. LOGICAL ISAME( 13 ) * .. External Functions .. LOGICAL LCE, LCERES EXTERNAL LCE, LCERES * .. External Subroutines .. EXTERNAL CGBMV, CGEMV, CMAKE, CMVCH * .. Intrinsic Functions .. INTRINSIC ABS, MAX, MIN * .. Scalars in Common .. INTEGER INFOT, NOUTC LOGICAL LERR, OK * .. Common blocks .. COMMON /INFOC/INFOT, NOUTC, OK, LERR * .. Data statements .. DATA ICH/'NTC'/ * .. Executable Statements .. FULL = SNAME( 3: 3 ).EQ.'E' BANDED = SNAME( 3: 3 ).EQ.'B' * Define the number of arguments. IF( FULL )THEN NARGS = 11 ELSE IF( BANDED )THEN NARGS = 13 END IF * NC = 0 RESET = .TRUE. ERRMAX = RZERO * DO 120 IN = 1, NIDIM N = IDIM( IN ) ND = N/2 + 1 * DO 110 IM = 1, 2 IF( IM.EQ.1 ) $ M = MAX( N - ND, 0 ) IF( IM.EQ.2 ) $ M = MIN( N + ND, NMAX ) * IF( BANDED )THEN NK = NKB ELSE NK = 1 END IF DO 100 IKU = 1, NK IF( BANDED )THEN KU = KB( IKU ) KL = MAX( KU - 1, 0 ) ELSE KU = N - 1 KL = M - 1 END IF * Set LDA to 1 more than minimum value if room. IF( BANDED )THEN LDA = KL + KU + 1 ELSE LDA = M END IF IF( LDA.LT.NMAX ) $ LDA = LDA + 1 * Skip tests if not enough room. IF( LDA.GT.NMAX ) $ GO TO 100 LAA = LDA*N NULL = N.LE.0.OR.M.LE.0 * * Generate the matrix A. * TRANSL = ZERO CALL CMAKE( SNAME( 2: 3 ), ' ', ' ', M, N, A, NMAX, AA, $ LDA, KL, KU, RESET, TRANSL ) * DO 90 IC = 1, 3 TRANS = ICH( IC: IC ) TRAN = TRANS.EQ.'T'.OR.TRANS.EQ.'C' * IF( TRAN )THEN ML = N NL = M ELSE ML = M NL = N END IF * DO 80 IX = 1, NINC INCX = INC( IX ) LX = ABS( INCX )*NL * * Generate the vector X. * TRANSL = HALF CALL CMAKE( 'GE', ' ', ' ', 1, NL, X, 1, XX, $ ABS( INCX ), 0, NL - 1, RESET, TRANSL ) IF( NL.GT.1 )THEN X( NL/2 ) = ZERO XX( 1 + ABS( INCX )*( NL/2 - 1 ) ) = ZERO END IF * DO 70 IY = 1, NINC INCY = INC( IY ) LY = ABS( INCY )*ML * DO 60 IA = 1, NALF ALPHA = ALF( IA ) * DO 50 IB = 1, NBET BETA = BET( IB ) * * Generate the vector Y. * TRANSL = ZERO CALL CMAKE( 'GE', ' ', ' ', 1, ML, Y, 1, $ YY, ABS( INCY ), 0, ML - 1, $ RESET, TRANSL ) * NC = NC + 1 * * Save every datum before calling the * subroutine. * TRANSS = TRANS MS = M NS = N KLS = KL KUS = KU ALS = ALPHA DO 10 I = 1, LAA AS( I ) = AA( I ) 10 CONTINUE LDAS = LDA DO 20 I = 1, LX XS( I ) = XX( I ) 20 CONTINUE INCXS = INCX BLS = BETA DO 30 I = 1, LY YS( I ) = YY( I ) 30 CONTINUE INCYS = INCY * * Call the subroutine. * IF( FULL )THEN IF( TRACE ) $ WRITE( NTRA, FMT = 9994 )NC, SNAME, $ TRANS, M, N, ALPHA, LDA, INCX, BETA, $ INCY IF( REWI ) $ REWIND NTRA CALL CGEMV( TRANS, M, N, ALPHA, AA, $ LDA, XX, INCX, BETA, YY, $ INCY ) ELSE IF( BANDED )THEN IF( TRACE ) $ WRITE( NTRA, FMT = 9995 )NC, SNAME, $ TRANS, M, N, KL, KU, ALPHA, LDA, $ INCX, BETA, INCY IF( REWI ) $ REWIND NTRA CALL CGBMV( TRANS, M, N, KL, KU, ALPHA, $ AA, LDA, XX, INCX, BETA, $ YY, INCY ) END IF * * Check if error-exit was taken incorrectly. * IF( .NOT.OK )THEN WRITE( NOUT, FMT = 9993 ) FATAL = .TRUE. GO TO 130 END IF * * See what data changed inside subroutines. * ISAME( 1 ) = TRANS.EQ.TRANSS ISAME( 2 ) = MS.EQ.M ISAME( 3 ) = NS.EQ.N IF( FULL )THEN ISAME( 4 ) = ALS.EQ.ALPHA ISAME( 5 ) = LCE( AS, AA, LAA ) ISAME( 6 ) = LDAS.EQ.LDA ISAME( 7 ) = LCE( XS, XX, LX ) ISAME( 8 ) = INCXS.EQ.INCX ISAME( 9 ) = BLS.EQ.BETA IF( NULL )THEN ISAME( 10 ) = LCE( YS, YY, LY ) ELSE ISAME( 10 ) = LCERES( 'GE', ' ', 1, $ ML, YS, YY, $ ABS( INCY ) ) END IF ISAME( 11 ) = INCYS.EQ.INCY ELSE IF( BANDED )THEN ISAME( 4 ) = KLS.EQ.KL ISAME( 5 ) = KUS.EQ.KU ISAME( 6 ) = ALS.EQ.ALPHA ISAME( 7 ) = LCE( AS, AA, LAA ) ISAME( 8 ) = LDAS.EQ.LDA ISAME( 9 ) = LCE( XS, XX, LX ) ISAME( 10 ) = INCXS.EQ.INCX ISAME( 11 ) = BLS.EQ.BETA IF( NULL )THEN ISAME( 12 ) = LCE( YS, YY, LY ) ELSE ISAME( 12 ) = LCERES( 'GE', ' ', 1, $ ML, YS, YY, $ ABS( INCY ) ) END IF ISAME( 13 ) = INCYS.EQ.INCY END IF * * If data was incorrectly changed, report * and return. * SAME = .TRUE. DO 40 I = 1, NARGS SAME = SAME.AND.ISAME( I ) IF( .NOT.ISAME( I ) ) $ WRITE( NOUT, FMT = 9998 )I 40 CONTINUE IF( .NOT.SAME )THEN FATAL = .TRUE. GO TO 130 END IF * IF( .NOT.NULL )THEN * * Check the result. * CALL CMVCH( TRANS, M, N, ALPHA, A, $ NMAX, X, INCX, BETA, Y, $ INCY, YT, G, YY, EPS, ERR, $ FATAL, NOUT, .TRUE. ) ERRMAX = MAX( ERRMAX, ERR ) * If got really bad answer, report and * return. IF( FATAL ) $ GO TO 130 ELSE * Avoid repeating tests with M.le.0 or * N.le.0. GO TO 110 END IF * 50 CONTINUE * 60 CONTINUE * 70 CONTINUE * 80 CONTINUE * 90 CONTINUE * 100 CONTINUE * 110 CONTINUE * 120 CONTINUE * * Report result. * IF( ERRMAX.LT.THRESH )THEN WRITE( NOUT, FMT = 9999 )SNAME, NC ELSE WRITE( NOUT, FMT = 9997 )SNAME, NC, ERRMAX END IF GO TO 140 * 130 CONTINUE WRITE( NOUT, FMT = 9996 )SNAME IF( FULL )THEN WRITE( NOUT, FMT = 9994 )NC, SNAME, TRANS, M, N, ALPHA, LDA, $ INCX, BETA, INCY ELSE IF( BANDED )THEN WRITE( NOUT, FMT = 9995 )NC, SNAME, TRANS, M, N, KL, KU, $ ALPHA, LDA, INCX, BETA, INCY END IF * 140 CONTINUE RETURN * 9999 FORMAT( ' ', A6, ' PASSED THE COMPUTATIONAL TESTS (', I6, ' CALL', $ 'S)' ) 9998 FORMAT( ' ******* FATAL ERROR - PARAMETER NUMBER ', I2, ' WAS CH', $ 'ANGED INCORRECTLY *******' ) 9997 FORMAT( ' ', A6, ' COMPLETED THE COMPUTATIONAL TESTS (', I6, ' C', $ 'ALLS)', /' ******* BUT WITH MAXIMUM TEST RATIO', F8.2, $ ' - SUSPECT *******' ) 9996 FORMAT( ' ******* ', A6, ' FAILED ON CALL NUMBER:' ) 9995 FORMAT( 1X, I6, ': ', A6, '(''', A1, ''',', 4( I3, ',' ), '(', $ F4.1, ',', F4.1, '), A,', I3, ', X,', I2, ',(', F4.1, ',', $ F4.1, '), Y,', I2, ') .' ) 9994 FORMAT( 1X, I6, ': ', A6, '(''', A1, ''',', 2( I3, ',' ), '(', $ F4.1, ',', F4.1, '), A,', I3, ', X,', I2, ',(', F4.1, ',', $ F4.1, '), Y,', I2, ') .' ) 9993 FORMAT( ' ******* FATAL ERROR - ERROR-EXIT TAKEN ON VALID CALL *', $ '******' ) * * End of CCHK1. * END SUBROUTINE CCHK2( SNAME, EPS, THRESH, NOUT, NTRA, TRACE, REWI, $ FATAL, NIDIM, IDIM, NKB, KB, NALF, ALF, NBET, $ BET, NINC, INC, NMAX, INCMAX, A, AA, AS, X, XX, $ XS, Y, YY, YS, YT, G ) * * Tests CHEMV, CHBMV and CHPMV. * * Auxiliary routine for test program for Level 2 Blas. * * -- Written on 10-August-1987. * Richard Hanson, Sandia National Labs. * Jeremy Du Croz, NAG Central Office. * * .. Parameters .. COMPLEX ZERO, HALF PARAMETER ( ZERO = ( 0.0, 0.0 ), HALF = ( 0.5, 0.0 ) ) REAL RZERO PARAMETER ( RZERO = 0.0 ) * .. Scalar Arguments .. REAL EPS, THRESH INTEGER INCMAX, NALF, NBET, NIDIM, NINC, NKB, NMAX, $ NOUT, NTRA LOGICAL FATAL, REWI, TRACE CHARACTER*6 SNAME * .. Array Arguments .. COMPLEX A( NMAX, NMAX ), AA( NMAX*NMAX ), ALF( NALF ), $ AS( NMAX*NMAX ), BET( NBET ), X( NMAX ), $ XS( NMAX*INCMAX ), XX( NMAX*INCMAX ), $ Y( NMAX ), YS( NMAX*INCMAX ), YT( NMAX ), $ YY( NMAX*INCMAX ) REAL G( NMAX ) INTEGER IDIM( NIDIM ), INC( NINC ), KB( NKB ) * .. Local Scalars .. COMPLEX ALPHA, ALS, BETA, BLS, TRANSL REAL ERR, ERRMAX INTEGER I, IA, IB, IC, IK, IN, INCX, INCXS, INCY, $ INCYS, IX, IY, K, KS, LAA, LDA, LDAS, LX, LY, $ N, NARGS, NC, NK, NS LOGICAL BANDED, FULL, NULL, PACKED, RESET, SAME CHARACTER*1 UPLO, UPLOS CHARACTER*2 ICH * .. Local Arrays .. LOGICAL ISAME( 13 ) * .. External Functions .. LOGICAL LCE, LCERES EXTERNAL LCE, LCERES * .. External Subroutines .. EXTERNAL CHBMV, CHEMV, CHPMV, CMAKE, CMVCH * .. Intrinsic Functions .. INTRINSIC ABS, MAX * .. Scalars in Common .. INTEGER INFOT, NOUTC LOGICAL LERR, OK * .. Common blocks .. COMMON /INFOC/INFOT, NOUTC, OK, LERR * .. Data statements .. DATA ICH/'UL'/ * .. Executable Statements .. FULL = SNAME( 3: 3 ).EQ.'E' BANDED = SNAME( 3: 3 ).EQ.'B' PACKED = SNAME( 3: 3 ).EQ.'P' * Define the number of arguments. IF( FULL )THEN NARGS = 10 ELSE IF( BANDED )THEN NARGS = 11 ELSE IF( PACKED )THEN NARGS = 9 END IF * NC = 0 RESET = .TRUE. ERRMAX = RZERO * DO 110 IN = 1, NIDIM N = IDIM( IN ) * IF( BANDED )THEN NK = NKB ELSE NK = 1 END IF DO 100 IK = 1, NK IF( BANDED )THEN K = KB( IK ) ELSE K = N - 1 END IF * Set LDA to 1 more than minimum value if room. IF( BANDED )THEN LDA = K + 1 ELSE LDA = N END IF IF( LDA.LT.NMAX ) $ LDA = LDA + 1 * Skip tests if not enough room. IF( LDA.GT.NMAX ) $ GO TO 100 IF( PACKED )THEN LAA = ( N*( N + 1 ) )/2 ELSE LAA = LDA*N END IF NULL = N.LE.0 * DO 90 IC = 1, 2 UPLO = ICH( IC: IC ) * * Generate the matrix A. * TRANSL = ZERO CALL CMAKE( SNAME( 2: 3 ), UPLO, ' ', N, N, A, NMAX, AA, $ LDA, K, K, RESET, TRANSL ) * DO 80 IX = 1, NINC INCX = INC( IX ) LX = ABS( INCX )*N * * Generate the vector X. * TRANSL = HALF CALL CMAKE( 'GE', ' ', ' ', 1, N, X, 1, XX, $ ABS( INCX ), 0, N - 1, RESET, TRANSL ) IF( N.GT.1 )THEN X( N/2 ) = ZERO XX( 1 + ABS( INCX )*( N/2 - 1 ) ) = ZERO END IF * DO 70 IY = 1, NINC INCY = INC( IY ) LY = ABS( INCY )*N * DO 60 IA = 1, NALF ALPHA = ALF( IA ) * DO 50 IB = 1, NBET BETA = BET( IB ) * * Generate the vector Y. * TRANSL = ZERO CALL CMAKE( 'GE', ' ', ' ', 1, N, Y, 1, YY, $ ABS( INCY ), 0, N - 1, RESET, $ TRANSL ) * NC = NC + 1 * * Save every datum before calling the * subroutine. * UPLOS = UPLO NS = N KS = K ALS = ALPHA DO 10 I = 1, LAA AS( I ) = AA( I ) 10 CONTINUE LDAS = LDA DO 20 I = 1, LX XS( I ) = XX( I ) 20 CONTINUE INCXS = INCX BLS = BETA DO 30 I = 1, LY YS( I ) = YY( I ) 30 CONTINUE INCYS = INCY * * Call the subroutine. * IF( FULL )THEN IF( TRACE ) $ WRITE( NTRA, FMT = 9993 )NC, SNAME, $ UPLO, N, ALPHA, LDA, INCX, BETA, INCY IF( REWI ) $ REWIND NTRA CALL CHEMV( UPLO, N, ALPHA, AA, LDA, XX, $ INCX, BETA, YY, INCY ) ELSE IF( BANDED )THEN IF( TRACE ) $ WRITE( NTRA, FMT = 9994 )NC, SNAME, $ UPLO, N, K, ALPHA, LDA, INCX, BETA, $ INCY IF( REWI ) $ REWIND NTRA CALL CHBMV( UPLO, N, K, ALPHA, AA, LDA, $ XX, INCX, BETA, YY, INCY ) ELSE IF( PACKED )THEN IF( TRACE ) $ WRITE( NTRA, FMT = 9995 )NC, SNAME, $ UPLO, N, ALPHA, INCX, BETA, INCY IF( REWI ) $ REWIND NTRA CALL CHPMV( UPLO, N, ALPHA, AA, XX, INCX, $ BETA, YY, INCY ) END IF * * Check if error-exit was taken incorrectly. * IF( .NOT.OK )THEN WRITE( NOUT, FMT = 9992 ) FATAL = .TRUE. GO TO 120 END IF * * See what data changed inside subroutines. * ISAME( 1 ) = UPLO.EQ.UPLOS ISAME( 2 ) = NS.EQ.N IF( FULL )THEN ISAME( 3 ) = ALS.EQ.ALPHA ISAME( 4 ) = LCE( AS, AA, LAA ) ISAME( 5 ) = LDAS.EQ.LDA ISAME( 6 ) = LCE( XS, XX, LX ) ISAME( 7 ) = INCXS.EQ.INCX ISAME( 8 ) = BLS.EQ.BETA IF( NULL )THEN ISAME( 9 ) = LCE( YS, YY, LY ) ELSE ISAME( 9 ) = LCERES( 'GE', ' ', 1, N, $ YS, YY, ABS( INCY ) ) END IF ISAME( 10 ) = INCYS.EQ.INCY ELSE IF( BANDED )THEN ISAME( 3 ) = KS.EQ.K ISAME( 4 ) = ALS.EQ.ALPHA ISAME( 5 ) = LCE( AS, AA, LAA ) ISAME( 6 ) = LDAS.EQ.LDA ISAME( 7 ) = LCE( XS, XX, LX ) ISAME( 8 ) = INCXS.EQ.INCX ISAME( 9 ) = BLS.EQ.BETA IF( NULL )THEN ISAME( 10 ) = LCE( YS, YY, LY ) ELSE ISAME( 10 ) = LCERES( 'GE', ' ', 1, N, $ YS, YY, ABS( INCY ) ) END IF ISAME( 11 ) = INCYS.EQ.INCY ELSE IF( PACKED )THEN ISAME( 3 ) = ALS.EQ.ALPHA ISAME( 4 ) = LCE( AS, AA, LAA ) ISAME( 5 ) = LCE( XS, XX, LX ) ISAME( 6 ) = INCXS.EQ.INCX ISAME( 7 ) = BLS.EQ.BETA IF( NULL )THEN ISAME( 8 ) = LCE( YS, YY, LY ) ELSE ISAME( 8 ) = LCERES( 'GE', ' ', 1, N, $ YS, YY, ABS( INCY ) ) END IF ISAME( 9 ) = INCYS.EQ.INCY END IF * * If data was incorrectly changed, report and * return. * SAME = .TRUE. DO 40 I = 1, NARGS SAME = SAME.AND.ISAME( I ) IF( .NOT.ISAME( I ) ) $ WRITE( NOUT, FMT = 9998 )I 40 CONTINUE IF( .NOT.SAME )THEN FATAL = .TRUE. GO TO 120 END IF * IF( .NOT.NULL )THEN * * Check the result. * CALL CMVCH( 'N', N, N, ALPHA, A, NMAX, X, $ INCX, BETA, Y, INCY, YT, G, $ YY, EPS, ERR, FATAL, NOUT, $ .TRUE. ) ERRMAX = MAX( ERRMAX, ERR ) * If got really bad answer, report and * return. IF( FATAL ) $ GO TO 120 ELSE * Avoid repeating tests with N.le.0 GO TO 110 END IF * 50 CONTINUE * 60 CONTINUE * 70 CONTINUE * 80 CONTINUE * 90 CONTINUE * 100 CONTINUE * 110 CONTINUE * * Report result. * IF( ERRMAX.LT.THRESH )THEN WRITE( NOUT, FMT = 9999 )SNAME, NC ELSE WRITE( NOUT, FMT = 9997 )SNAME, NC, ERRMAX END IF GO TO 130 * 120 CONTINUE WRITE( NOUT, FMT = 9996 )SNAME IF( FULL )THEN WRITE( NOUT, FMT = 9993 )NC, SNAME, UPLO, N, ALPHA, LDA, INCX, $ BETA, INCY ELSE IF( BANDED )THEN WRITE( NOUT, FMT = 9994 )NC, SNAME, UPLO, N, K, ALPHA, LDA, $ INCX, BETA, INCY ELSE IF( PACKED )THEN WRITE( NOUT, FMT = 9995 )NC, SNAME, UPLO, N, ALPHA, INCX, $ BETA, INCY END IF * 130 CONTINUE RETURN * 9999 FORMAT( ' ', A6, ' PASSED THE COMPUTATIONAL TESTS (', I6, ' CALL', $ 'S)' ) 9998 FORMAT( ' ******* FATAL ERROR - PARAMETER NUMBER ', I2, ' WAS CH', $ 'ANGED INCORRECTLY *******' ) 9997 FORMAT( ' ', A6, ' COMPLETED THE COMPUTATIONAL TESTS (', I6, ' C', $ 'ALLS)', /' ******* BUT WITH MAXIMUM TEST RATIO', F8.2, $ ' - SUSPECT *******' ) 9996 FORMAT( ' ******* ', A6, ' FAILED ON CALL NUMBER:' ) 9995 FORMAT( 1X, I6, ': ', A6, '(''', A1, ''',', I3, ',(', F4.1, ',', $ F4.1, '), AP, X,', I2, ',(', F4.1, ',', F4.1, '), Y,', I2, $ ') .' ) 9994 FORMAT( 1X, I6, ': ', A6, '(''', A1, ''',', 2( I3, ',' ), '(', $ F4.1, ',', F4.1, '), A,', I3, ', X,', I2, ',(', F4.1, ',', $ F4.1, '), Y,', I2, ') .' ) 9993 FORMAT( 1X, I6, ': ', A6, '(''', A1, ''',', I3, ',(', F4.1, ',', $ F4.1, '), A,', I3, ', X,', I2, ',(', F4.1, ',', F4.1, '), ', $ 'Y,', I2, ') .' ) 9992 FORMAT( ' ******* FATAL ERROR - ERROR-EXIT TAKEN ON VALID CALL *', $ '******' ) * * End of CCHK2. * END SUBROUTINE CCHK3( SNAME, EPS, THRESH, NOUT, NTRA, TRACE, REWI, $ FATAL, NIDIM, IDIM, NKB, KB, NINC, INC, NMAX, $ INCMAX, A, AA, AS, X, XX, XS, XT, G, Z ) * * Tests CTRMV, CTBMV, CTPMV, CTRSV, CTBSV and CTPSV. * * Auxiliary routine for test program for Level 2 Blas. * * -- Written on 10-August-1987. * Richard Hanson, Sandia National Labs. * Jeremy Du Croz, NAG Central Office. * * .. Parameters .. COMPLEX ZERO, HALF, ONE PARAMETER ( ZERO = ( 0.0, 0.0 ), HALF = ( 0.5, 0.0 ), $ ONE = ( 1.0, 0.0 ) ) REAL RZERO PARAMETER ( RZERO = 0.0 ) * .. Scalar Arguments .. REAL EPS, THRESH INTEGER INCMAX, NIDIM, NINC, NKB, NMAX, NOUT, NTRA LOGICAL FATAL, REWI, TRACE CHARACTER*6 SNAME * .. Array Arguments .. COMPLEX A( NMAX, NMAX ), AA( NMAX*NMAX ), $ AS( NMAX*NMAX ), X( NMAX ), XS( NMAX*INCMAX ), $ XT( NMAX ), XX( NMAX*INCMAX ), Z( NMAX ) REAL G( NMAX ) INTEGER IDIM( NIDIM ), INC( NINC ), KB( NKB ) * .. Local Scalars .. COMPLEX TRANSL REAL ERR, ERRMAX INTEGER I, ICD, ICT, ICU, IK, IN, INCX, INCXS, IX, K, $ KS, LAA, LDA, LDAS, LX, N, NARGS, NC, NK, NS LOGICAL BANDED, FULL, NULL, PACKED, RESET, SAME CHARACTER*1 DIAG, DIAGS, TRANS, TRANSS, UPLO, UPLOS CHARACTER*2 ICHD, ICHU CHARACTER*3 ICHT * .. Local Arrays .. LOGICAL ISAME( 13 ) * .. External Functions .. LOGICAL LCE, LCERES EXTERNAL LCE, LCERES * .. External Subroutines .. EXTERNAL CMAKE, CMVCH, CTBMV, CTBSV, CTPMV, CTPSV, $ CTRMV, CTRSV * .. Intrinsic Functions .. INTRINSIC ABS, MAX * .. Scalars in Common .. INTEGER INFOT, NOUTC LOGICAL LERR, OK * .. Common blocks .. COMMON /INFOC/INFOT, NOUTC, OK, LERR * .. Data statements .. DATA ICHU/'UL'/, ICHT/'NTC'/, ICHD/'UN'/ * .. Executable Statements .. FULL = SNAME( 3: 3 ).EQ.'R' BANDED = SNAME( 3: 3 ).EQ.'B' PACKED = SNAME( 3: 3 ).EQ.'P' * Define the number of arguments. IF( FULL )THEN NARGS = 8 ELSE IF( BANDED )THEN NARGS = 9 ELSE IF( PACKED )THEN NARGS = 7 END IF * NC = 0 RESET = .TRUE. ERRMAX = RZERO * Set up zero vector for CMVCH. DO 10 I = 1, NMAX Z( I ) = ZERO 10 CONTINUE * DO 110 IN = 1, NIDIM N = IDIM( IN ) * IF( BANDED )THEN NK = NKB ELSE NK = 1 END IF DO 100 IK = 1, NK IF( BANDED )THEN K = KB( IK ) ELSE K = N - 1 END IF * Set LDA to 1 more than minimum value if room. IF( BANDED )THEN LDA = K + 1 ELSE LDA = N END IF IF( LDA.LT.NMAX ) $ LDA = LDA + 1 * Skip tests if not enough room. IF( LDA.GT.NMAX ) $ GO TO 100 IF( PACKED )THEN LAA = ( N*( N + 1 ) )/2 ELSE LAA = LDA*N END IF NULL = N.LE.0 * DO 90 ICU = 1, 2 UPLO = ICHU( ICU: ICU ) * DO 80 ICT = 1, 3 TRANS = ICHT( ICT: ICT ) * DO 70 ICD = 1, 2 DIAG = ICHD( ICD: ICD ) * * Generate the matrix A. * TRANSL = ZERO CALL CMAKE( SNAME( 2: 3 ), UPLO, DIAG, N, N, A, $ NMAX, AA, LDA, K, K, RESET, TRANSL ) * DO 60 IX = 1, NINC INCX = INC( IX ) LX = ABS( INCX )*N * * Generate the vector X. * TRANSL = HALF CALL CMAKE( 'GE', ' ', ' ', 1, N, X, 1, XX, $ ABS( INCX ), 0, N - 1, RESET, $ TRANSL ) IF( N.GT.1 )THEN X( N/2 ) = ZERO XX( 1 + ABS( INCX )*( N/2 - 1 ) ) = ZERO END IF * NC = NC + 1 * * Save every datum before calling the subroutine. * UPLOS = UPLO TRANSS = TRANS DIAGS = DIAG NS = N KS = K DO 20 I = 1, LAA AS( I ) = AA( I ) 20 CONTINUE LDAS = LDA DO 30 I = 1, LX XS( I ) = XX( I ) 30 CONTINUE INCXS = INCX * * Call the subroutine. * IF( SNAME( 4: 5 ).EQ.'MV' )THEN IF( FULL )THEN IF( TRACE ) $ WRITE( NTRA, FMT = 9993 )NC, SNAME, $ UPLO, TRANS, DIAG, N, LDA, INCX IF( REWI ) $ REWIND NTRA CALL CTRMV( UPLO, TRANS, DIAG, N, AA, LDA, $ XX, INCX ) ELSE IF( BANDED )THEN IF( TRACE ) $ WRITE( NTRA, FMT = 9994 )NC, SNAME, $ UPLO, TRANS, DIAG, N, K, LDA, INCX IF( REWI ) $ REWIND NTRA CALL CTBMV( UPLO, TRANS, DIAG, N, K, AA, $ LDA, XX, INCX ) ELSE IF( PACKED )THEN IF( TRACE ) $ WRITE( NTRA, FMT = 9995 )NC, SNAME, $ UPLO, TRANS, DIAG, N, INCX IF( REWI ) $ REWIND NTRA CALL CTPMV( UPLO, TRANS, DIAG, N, AA, XX, $ INCX ) END IF ELSE IF( SNAME( 4: 5 ).EQ.'SV' )THEN IF( FULL )THEN IF( TRACE ) $ WRITE( NTRA, FMT = 9993 )NC, SNAME, $ UPLO, TRANS, DIAG, N, LDA, INCX IF( REWI ) $ REWIND NTRA CALL CTRSV( UPLO, TRANS, DIAG, N, AA, LDA, $ XX, INCX ) ELSE IF( BANDED )THEN IF( TRACE ) $ WRITE( NTRA, FMT = 9994 )NC, SNAME, $ UPLO, TRANS, DIAG, N, K, LDA, INCX IF( REWI ) $ REWIND NTRA CALL CTBSV( UPLO, TRANS, DIAG, N, K, AA, $ LDA, XX, INCX ) ELSE IF( PACKED )THEN IF( TRACE ) $ WRITE( NTRA, FMT = 9995 )NC, SNAME, $ UPLO, TRANS, DIAG, N, INCX IF( REWI ) $ REWIND NTRA CALL CTPSV( UPLO, TRANS, DIAG, N, AA, XX, $ INCX ) END IF END IF * * Check if error-exit was taken incorrectly. * IF( .NOT.OK )THEN WRITE( NOUT, FMT = 9992 ) FATAL = .TRUE. GO TO 120 END IF * * See what data changed inside subroutines. * ISAME( 1 ) = UPLO.EQ.UPLOS ISAME( 2 ) = TRANS.EQ.TRANSS ISAME( 3 ) = DIAG.EQ.DIAGS ISAME( 4 ) = NS.EQ.N IF( FULL )THEN ISAME( 5 ) = LCE( AS, AA, LAA ) ISAME( 6 ) = LDAS.EQ.LDA IF( NULL )THEN ISAME( 7 ) = LCE( XS, XX, LX ) ELSE ISAME( 7 ) = LCERES( 'GE', ' ', 1, N, XS, $ XX, ABS( INCX ) ) END IF ISAME( 8 ) = INCXS.EQ.INCX ELSE IF( BANDED )THEN ISAME( 5 ) = KS.EQ.K ISAME( 6 ) = LCE( AS, AA, LAA ) ISAME( 7 ) = LDAS.EQ.LDA IF( NULL )THEN ISAME( 8 ) = LCE( XS, XX, LX ) ELSE ISAME( 8 ) = LCERES( 'GE', ' ', 1, N, XS, $ XX, ABS( INCX ) ) END IF ISAME( 9 ) = INCXS.EQ.INCX ELSE IF( PACKED )THEN ISAME( 5 ) = LCE( AS, AA, LAA ) IF( NULL )THEN ISAME( 6 ) = LCE( XS, XX, LX ) ELSE ISAME( 6 ) = LCERES( 'GE', ' ', 1, N, XS, $ XX, ABS( INCX ) ) END IF ISAME( 7 ) = INCXS.EQ.INCX END IF * * If data was incorrectly changed, report and * return. * SAME = .TRUE. DO 40 I = 1, NARGS SAME = SAME.AND.ISAME( I ) IF( .NOT.ISAME( I ) ) $ WRITE( NOUT, FMT = 9998 )I 40 CONTINUE IF( .NOT.SAME )THEN FATAL = .TRUE. GO TO 120 END IF * IF( .NOT.NULL )THEN IF( SNAME( 4: 5 ).EQ.'MV' )THEN * * Check the result. * CALL CMVCH( TRANS, N, N, ONE, A, NMAX, X, $ INCX, ZERO, Z, INCX, XT, G, $ XX, EPS, ERR, FATAL, NOUT, $ .TRUE. ) ELSE IF( SNAME( 4: 5 ).EQ.'SV' )THEN * * Compute approximation to original vector. * DO 50 I = 1, N Z( I ) = XX( 1 + ( I - 1 )* $ ABS( INCX ) ) XX( 1 + ( I - 1 )*ABS( INCX ) ) $ = X( I ) 50 CONTINUE CALL CMVCH( TRANS, N, N, ONE, A, NMAX, Z, $ INCX, ZERO, X, INCX, XT, G, $ XX, EPS, ERR, FATAL, NOUT, $ .FALSE. ) END IF ERRMAX = MAX( ERRMAX, ERR ) * If got really bad answer, report and return. IF( FATAL ) $ GO TO 120 ELSE * Avoid repeating tests with N.le.0. GO TO 110 END IF * 60 CONTINUE * 70 CONTINUE * 80 CONTINUE * 90 CONTINUE * 100 CONTINUE * 110 CONTINUE * * Report result. * IF( ERRMAX.LT.THRESH )THEN WRITE( NOUT, FMT = 9999 )SNAME, NC ELSE WRITE( NOUT, FMT = 9997 )SNAME, NC, ERRMAX END IF GO TO 130 * 120 CONTINUE WRITE( NOUT, FMT = 9996 )SNAME IF( FULL )THEN WRITE( NOUT, FMT = 9993 )NC, SNAME, UPLO, TRANS, DIAG, N, LDA, $ INCX ELSE IF( BANDED )THEN WRITE( NOUT, FMT = 9994 )NC, SNAME, UPLO, TRANS, DIAG, N, K, $ LDA, INCX ELSE IF( PACKED )THEN WRITE( NOUT, FMT = 9995 )NC, SNAME, UPLO, TRANS, DIAG, N, INCX END IF * 130 CONTINUE RETURN * 9999 FORMAT( ' ', A6, ' PASSED THE COMPUTATIONAL TESTS (', I6, ' CALL', $ 'S)' ) 9998 FORMAT( ' ******* FATAL ERROR - PARAMETER NUMBER ', I2, ' WAS CH', $ 'ANGED INCORRECTLY *******' ) 9997 FORMAT( ' ', A6, ' COMPLETED THE COMPUTATIONAL TESTS (', I6, ' C', $ 'ALLS)', /' ******* BUT WITH MAXIMUM TEST RATIO', F8.2, $ ' - SUSPECT *******' ) 9996 FORMAT( ' ******* ', A6, ' FAILED ON CALL NUMBER:' ) 9995 FORMAT( 1X, I6, ': ', A6, '(', 3( '''', A1, ''',' ), I3, ', AP, ', $ 'X,', I2, ') .' ) 9994 FORMAT( 1X, I6, ': ', A6, '(', 3( '''', A1, ''',' ), 2( I3, ',' ), $ ' A,', I3, ', X,', I2, ') .' ) 9993 FORMAT( 1X, I6, ': ', A6, '(', 3( '''', A1, ''',' ), I3, ', A,', $ I3, ', X,', I2, ') .' ) 9992 FORMAT( ' ******* FATAL ERROR - ERROR-EXIT TAKEN ON VALID CALL *', $ '******' ) * * End of CCHK3. * END SUBROUTINE CCHK4( SNAME, EPS, THRESH, NOUT, NTRA, TRACE, REWI, $ FATAL, NIDIM, IDIM, NALF, ALF, NINC, INC, NMAX, $ INCMAX, A, AA, AS, X, XX, XS, Y, YY, YS, YT, G, $ Z ) * * Tests CGERC and CGERU. * * Auxiliary routine for test program for Level 2 Blas. * * -- Written on 10-August-1987. * Richard Hanson, Sandia National Labs. * Jeremy Du Croz, NAG Central Office. * * .. Parameters .. COMPLEX ZERO, HALF, ONE PARAMETER ( ZERO = ( 0.0, 0.0 ), HALF = ( 0.5, 0.0 ), $ ONE = ( 1.0, 0.0 ) ) REAL RZERO PARAMETER ( RZERO = 0.0 ) * .. Scalar Arguments .. REAL EPS, THRESH INTEGER INCMAX, NALF, NIDIM, NINC, NMAX, NOUT, NTRA LOGICAL FATAL, REWI, TRACE CHARACTER*6 SNAME * .. Array Arguments .. COMPLEX A( NMAX, NMAX ), AA( NMAX*NMAX ), ALF( NALF ), $ AS( NMAX*NMAX ), X( NMAX ), XS( NMAX*INCMAX ), $ XX( NMAX*INCMAX ), Y( NMAX ), $ YS( NMAX*INCMAX ), YT( NMAX ), $ YY( NMAX*INCMAX ), Z( NMAX ) REAL G( NMAX ) INTEGER IDIM( NIDIM ), INC( NINC ) * .. Local Scalars .. COMPLEX ALPHA, ALS, TRANSL REAL ERR, ERRMAX INTEGER I, IA, IM, IN, INCX, INCXS, INCY, INCYS, IX, $ IY, J, LAA, LDA, LDAS, LX, LY, M, MS, N, NARGS, $ NC, ND, NS LOGICAL CONJ, NULL, RESET, SAME * .. Local Arrays .. COMPLEX W( 1 ) LOGICAL ISAME( 13 ) * .. External Functions .. LOGICAL LCE, LCERES EXTERNAL LCE, LCERES * .. External Subroutines .. EXTERNAL CGERC, CGERU, CMAKE, CMVCH * .. Intrinsic Functions .. INTRINSIC ABS, CONJG, MAX, MIN * .. Scalars in Common .. INTEGER INFOT, NOUTC LOGICAL LERR, OK * .. Common blocks .. COMMON /INFOC/INFOT, NOUTC, OK, LERR * .. Executable Statements .. CONJ = SNAME( 5: 5 ).EQ.'C' * Define the number of arguments. NARGS = 9 * NC = 0 RESET = .TRUE. ERRMAX = RZERO * DO 120 IN = 1, NIDIM N = IDIM( IN ) ND = N/2 + 1 * DO 110 IM = 1, 2 IF( IM.EQ.1 ) $ M = MAX( N - ND, 0 ) IF( IM.EQ.2 ) $ M = MIN( N + ND, NMAX ) * * Set LDA to 1 more than minimum value if room. LDA = M IF( LDA.LT.NMAX ) $ LDA = LDA + 1 * Skip tests if not enough room. IF( LDA.GT.NMAX ) $ GO TO 110 LAA = LDA*N NULL = N.LE.0.OR.M.LE.0 * DO 100 IX = 1, NINC INCX = INC( IX ) LX = ABS( INCX )*M * * Generate the vector X. * TRANSL = HALF CALL CMAKE( 'GE', ' ', ' ', 1, M, X, 1, XX, ABS( INCX ), $ 0, M - 1, RESET, TRANSL ) IF( M.GT.1 )THEN X( M/2 ) = ZERO XX( 1 + ABS( INCX )*( M/2 - 1 ) ) = ZERO END IF * DO 90 IY = 1, NINC INCY = INC( IY ) LY = ABS( INCY )*N * * Generate the vector Y. * TRANSL = ZERO CALL CMAKE( 'GE', ' ', ' ', 1, N, Y, 1, YY, $ ABS( INCY ), 0, N - 1, RESET, TRANSL ) IF( N.GT.1 )THEN Y( N/2 ) = ZERO YY( 1 + ABS( INCY )*( N/2 - 1 ) ) = ZERO END IF * DO 80 IA = 1, NALF ALPHA = ALF( IA ) * * Generate the matrix A. * TRANSL = ZERO CALL CMAKE( SNAME( 2: 3 ), ' ', ' ', M, N, A, NMAX, $ AA, LDA, M - 1, N - 1, RESET, TRANSL ) * NC = NC + 1 * * Save every datum before calling the subroutine. * MS = M NS = N ALS = ALPHA DO 10 I = 1, LAA AS( I ) = AA( I ) 10 CONTINUE LDAS = LDA DO 20 I = 1, LX XS( I ) = XX( I ) 20 CONTINUE INCXS = INCX DO 30 I = 1, LY YS( I ) = YY( I ) 30 CONTINUE INCYS = INCY * * Call the subroutine. * IF( TRACE ) $ WRITE( NTRA, FMT = 9994 )NC, SNAME, M, N, $ ALPHA, INCX, INCY, LDA IF( CONJ )THEN IF( REWI ) $ REWIND NTRA CALL CGERC( M, N, ALPHA, XX, INCX, YY, INCY, AA, $ LDA ) ELSE IF( REWI ) $ REWIND NTRA CALL CGERU( M, N, ALPHA, XX, INCX, YY, INCY, AA, $ LDA ) END IF * * Check if error-exit was taken incorrectly. * IF( .NOT.OK )THEN WRITE( NOUT, FMT = 9993 ) FATAL = .TRUE. GO TO 140 END IF * * See what data changed inside subroutine. * ISAME( 1 ) = MS.EQ.M ISAME( 2 ) = NS.EQ.N ISAME( 3 ) = ALS.EQ.ALPHA ISAME( 4 ) = LCE( XS, XX, LX ) ISAME( 5 ) = INCXS.EQ.INCX ISAME( 6 ) = LCE( YS, YY, LY ) ISAME( 7 ) = INCYS.EQ.INCY IF( NULL )THEN ISAME( 8 ) = LCE( AS, AA, LAA ) ELSE ISAME( 8 ) = LCERES( 'GE', ' ', M, N, AS, AA, $ LDA ) END IF ISAME( 9 ) = LDAS.EQ.LDA * * If data was incorrectly changed, report and return. * SAME = .TRUE. DO 40 I = 1, NARGS SAME = SAME.AND.ISAME( I ) IF( .NOT.ISAME( I ) ) $ WRITE( NOUT, FMT = 9998 )I 40 CONTINUE IF( .NOT.SAME )THEN FATAL = .TRUE. GO TO 140 END IF * IF( .NOT.NULL )THEN * * Check the result column by column. * IF( INCX.GT.0 )THEN DO 50 I = 1, M Z( I ) = X( I ) 50 CONTINUE ELSE DO 60 I = 1, M Z( I ) = X( M - I + 1 ) 60 CONTINUE END IF DO 70 J = 1, N IF( INCY.GT.0 )THEN W( 1 ) = Y( J ) ELSE W( 1 ) = Y( N - J + 1 ) END IF IF( CONJ ) $ W( 1 ) = CONJG( W( 1 ) ) CALL CMVCH( 'N', M, 1, ALPHA, Z, NMAX, W, 1, $ ONE, A( 1, J ), 1, YT, G, $ AA( 1 + ( J - 1 )*LDA ), EPS, $ ERR, FATAL, NOUT, .TRUE. ) ERRMAX = MAX( ERRMAX, ERR ) * If got really bad answer, report and return. IF( FATAL ) $ GO TO 130 70 CONTINUE ELSE * Avoid repeating tests with M.le.0 or N.le.0. GO TO 110 END IF * 80 CONTINUE * 90 CONTINUE * 100 CONTINUE * 110 CONTINUE * 120 CONTINUE * * Report result. * IF( ERRMAX.LT.THRESH )THEN WRITE( NOUT, FMT = 9999 )SNAME, NC ELSE WRITE( NOUT, FMT = 9997 )SNAME, NC, ERRMAX END IF GO TO 150 * 130 CONTINUE WRITE( NOUT, FMT = 9995 )J * 140 CONTINUE WRITE( NOUT, FMT = 9996 )SNAME WRITE( NOUT, FMT = 9994 )NC, SNAME, M, N, ALPHA, INCX, INCY, LDA * 150 CONTINUE RETURN * 9999 FORMAT( ' ', A6, ' PASSED THE COMPUTATIONAL TESTS (', I6, ' CALL', $ 'S)' ) 9998 FORMAT( ' ******* FATAL ERROR - PARAMETER NUMBER ', I2, ' WAS CH', $ 'ANGED INCORRECTLY *******' ) 9997 FORMAT( ' ', A6, ' COMPLETED THE COMPUTATIONAL TESTS (', I6, ' C', $ 'ALLS)', /' ******* BUT WITH MAXIMUM TEST RATIO', F8.2, $ ' - SUSPECT *******' ) 9996 FORMAT( ' ******* ', A6, ' FAILED ON CALL NUMBER:' ) 9995 FORMAT( ' THESE ARE THE RESULTS FOR COLUMN ', I3 ) 9994 FORMAT( 1X, I6, ': ', A6, '(', 2( I3, ',' ), '(', F4.1, ',', F4.1, $ '), X,', I2, ', Y,', I2, ', A,', I3, ') ', $ ' .' ) 9993 FORMAT( ' ******* FATAL ERROR - ERROR-EXIT TAKEN ON VALID CALL *', $ '******' ) * * End of CCHK4. * END SUBROUTINE CCHK5( SNAME, EPS, THRESH, NOUT, NTRA, TRACE, REWI, $ FATAL, NIDIM, IDIM, NALF, ALF, NINC, INC, NMAX, $ INCMAX, A, AA, AS, X, XX, XS, Y, YY, YS, YT, G, $ Z ) * * Tests CHER and CHPR. * * Auxiliary routine for test program for Level 2 Blas. * * -- Written on 10-August-1987. * Richard Hanson, Sandia National Labs. * Jeremy Du Croz, NAG Central Office. * * .. Parameters .. COMPLEX ZERO, HALF, ONE PARAMETER ( ZERO = ( 0.0, 0.0 ), HALF = ( 0.5, 0.0 ), $ ONE = ( 1.0, 0.0 ) ) REAL RZERO PARAMETER ( RZERO = 0.0 ) * .. Scalar Arguments .. REAL EPS, THRESH INTEGER INCMAX, NALF, NIDIM, NINC, NMAX, NOUT, NTRA LOGICAL FATAL, REWI, TRACE CHARACTER*6 SNAME * .. Array Arguments .. COMPLEX A( NMAX, NMAX ), AA( NMAX*NMAX ), ALF( NALF ), $ AS( NMAX*NMAX ), X( NMAX ), XS( NMAX*INCMAX ), $ XX( NMAX*INCMAX ), Y( NMAX ), $ YS( NMAX*INCMAX ), YT( NMAX ), $ YY( NMAX*INCMAX ), Z( NMAX ) REAL G( NMAX ) INTEGER IDIM( NIDIM ), INC( NINC ) * .. Local Scalars .. COMPLEX ALPHA, TRANSL REAL ERR, ERRMAX, RALPHA, RALS INTEGER I, IA, IC, IN, INCX, INCXS, IX, J, JA, JJ, LAA, $ LDA, LDAS, LJ, LX, N, NARGS, NC, NS LOGICAL FULL, NULL, PACKED, RESET, SAME, UPPER CHARACTER*1 UPLO, UPLOS CHARACTER*2 ICH * .. Local Arrays .. COMPLEX W( 1 ) LOGICAL ISAME( 13 ) * .. External Functions .. LOGICAL LCE, LCERES EXTERNAL LCE, LCERES * .. External Subroutines .. EXTERNAL CHER, CHPR, CMAKE, CMVCH * .. Intrinsic Functions .. INTRINSIC ABS, CMPLX, CONJG, MAX, REAL * .. Scalars in Common .. INTEGER INFOT, NOUTC LOGICAL LERR, OK * .. Common blocks .. COMMON /INFOC/INFOT, NOUTC, OK, LERR * .. Data statements .. DATA ICH/'UL'/ * .. Executable Statements .. FULL = SNAME( 3: 3 ).EQ.'E' PACKED = SNAME( 3: 3 ).EQ.'P' * Define the number of arguments. IF( FULL )THEN NARGS = 7 ELSE IF( PACKED )THEN NARGS = 6 END IF * NC = 0 RESET = .TRUE. ERRMAX = RZERO * DO 100 IN = 1, NIDIM N = IDIM( IN ) * Set LDA to 1 more than minimum value if room. LDA = N IF( LDA.LT.NMAX ) $ LDA = LDA + 1 * Skip tests if not enough room. IF( LDA.GT.NMAX ) $ GO TO 100 IF( PACKED )THEN LAA = ( N*( N + 1 ) )/2 ELSE LAA = LDA*N END IF * DO 90 IC = 1, 2 UPLO = ICH( IC: IC ) UPPER = UPLO.EQ.'U' * DO 80 IX = 1, NINC INCX = INC( IX ) LX = ABS( INCX )*N * * Generate the vector X. * TRANSL = HALF CALL CMAKE( 'GE', ' ', ' ', 1, N, X, 1, XX, ABS( INCX ), $ 0, N - 1, RESET, TRANSL ) IF( N.GT.1 )THEN X( N/2 ) = ZERO XX( 1 + ABS( INCX )*( N/2 - 1 ) ) = ZERO END IF * DO 70 IA = 1, NALF RALPHA = REAL( ALF( IA ) ) ALPHA = CMPLX( RALPHA, RZERO ) NULL = N.LE.0.OR.RALPHA.EQ.RZERO * * Generate the matrix A. * TRANSL = ZERO CALL CMAKE( SNAME( 2: 3 ), UPLO, ' ', N, N, A, NMAX, $ AA, LDA, N - 1, N - 1, RESET, TRANSL ) * NC = NC + 1 * * Save every datum before calling the subroutine. * UPLOS = UPLO NS = N RALS = RALPHA DO 10 I = 1, LAA AS( I ) = AA( I ) 10 CONTINUE LDAS = LDA DO 20 I = 1, LX XS( I ) = XX( I ) 20 CONTINUE INCXS = INCX * * Call the subroutine. * IF( FULL )THEN IF( TRACE ) $ WRITE( NTRA, FMT = 9993 )NC, SNAME, UPLO, N, $ RALPHA, INCX, LDA IF( REWI ) $ REWIND NTRA CALL CHER( UPLO, N, RALPHA, XX, INCX, AA, LDA ) ELSE IF( PACKED )THEN IF( TRACE ) $ WRITE( NTRA, FMT = 9994 )NC, SNAME, UPLO, N, $ RALPHA, INCX IF( REWI ) $ REWIND NTRA CALL CHPR( UPLO, N, RALPHA, XX, INCX, AA ) END IF * * Check if error-exit was taken incorrectly. * IF( .NOT.OK )THEN WRITE( NOUT, FMT = 9992 ) FATAL = .TRUE. GO TO 120 END IF * * See what data changed inside subroutines. * ISAME( 1 ) = UPLO.EQ.UPLOS ISAME( 2 ) = NS.EQ.N ISAME( 3 ) = RALS.EQ.RALPHA ISAME( 4 ) = LCE( XS, XX, LX ) ISAME( 5 ) = INCXS.EQ.INCX IF( NULL )THEN ISAME( 6 ) = LCE( AS, AA, LAA ) ELSE ISAME( 6 ) = LCERES( SNAME( 2: 3 ), UPLO, N, N, AS, $ AA, LDA ) END IF IF( .NOT.PACKED )THEN ISAME( 7 ) = LDAS.EQ.LDA END IF * * If data was incorrectly changed, report and return. * SAME = .TRUE. DO 30 I = 1, NARGS SAME = SAME.AND.ISAME( I ) IF( .NOT.ISAME( I ) ) $ WRITE( NOUT, FMT = 9998 )I 30 CONTINUE IF( .NOT.SAME )THEN FATAL = .TRUE. GO TO 120 END IF * IF( .NOT.NULL )THEN * * Check the result column by column. * IF( INCX.GT.0 )THEN DO 40 I = 1, N Z( I ) = X( I ) 40 CONTINUE ELSE DO 50 I = 1, N Z( I ) = X( N - I + 1 ) 50 CONTINUE END IF JA = 1 DO 60 J = 1, N W( 1 ) = CONJG( Z( J ) ) IF( UPPER )THEN JJ = 1 LJ = J ELSE JJ = J LJ = N - J + 1 END IF CALL CMVCH( 'N', LJ, 1, ALPHA, Z( JJ ), LJ, W, $ 1, ONE, A( JJ, J ), 1, YT, G, $ AA( JA ), EPS, ERR, FATAL, NOUT, $ .TRUE. ) IF( FULL )THEN IF( UPPER )THEN JA = JA + LDA ELSE JA = JA + LDA + 1 END IF ELSE JA = JA + LJ END IF ERRMAX = MAX( ERRMAX, ERR ) * If got really bad answer, report and return. IF( FATAL ) $ GO TO 110 60 CONTINUE ELSE * Avoid repeating tests if N.le.0. IF( N.LE.0 ) $ GO TO 100 END IF * 70 CONTINUE * 80 CONTINUE * 90 CONTINUE * 100 CONTINUE * * Report result. * IF( ERRMAX.LT.THRESH )THEN WRITE( NOUT, FMT = 9999 )SNAME, NC ELSE WRITE( NOUT, FMT = 9997 )SNAME, NC, ERRMAX END IF GO TO 130 * 110 CONTINUE WRITE( NOUT, FMT = 9995 )J * 120 CONTINUE WRITE( NOUT, FMT = 9996 )SNAME IF( FULL )THEN WRITE( NOUT, FMT = 9993 )NC, SNAME, UPLO, N, RALPHA, INCX, LDA ELSE IF( PACKED )THEN WRITE( NOUT, FMT = 9994 )NC, SNAME, UPLO, N, RALPHA, INCX END IF * 130 CONTINUE RETURN * 9999 FORMAT( ' ', A6, ' PASSED THE COMPUTATIONAL TESTS (', I6, ' CALL', $ 'S)' ) 9998 FORMAT( ' ******* FATAL ERROR - PARAMETER NUMBER ', I2, ' WAS CH', $ 'ANGED INCORRECTLY *******' ) 9997 FORMAT( ' ', A6, ' COMPLETED THE COMPUTATIONAL TESTS (', I6, ' C', $ 'ALLS)', /' ******* BUT WITH MAXIMUM TEST RATIO', F8.2, $ ' - SUSPECT *******' ) 9996 FORMAT( ' ******* ', A6, ' FAILED ON CALL NUMBER:' ) 9995 FORMAT( ' THESE ARE THE RESULTS FOR COLUMN ', I3 ) 9994 FORMAT( 1X, I6, ': ', A6, '(''', A1, ''',', I3, ',', F4.1, ', X,', $ I2, ', AP) .' ) 9993 FORMAT( 1X, I6, ': ', A6, '(''', A1, ''',', I3, ',', F4.1, ', X,', $ I2, ', A,', I3, ') .' ) 9992 FORMAT( ' ******* FATAL ERROR - ERROR-EXIT TAKEN ON VALID CALL *', $ '******' ) * * End of CCHK5. * END SUBROUTINE CCHK6( SNAME, EPS, THRESH, NOUT, NTRA, TRACE, REWI, $ FATAL, NIDIM, IDIM, NALF, ALF, NINC, INC, NMAX, $ INCMAX, A, AA, AS, X, XX, XS, Y, YY, YS, YT, G, $ Z ) * * Tests CHER2 and CHPR2. * * Auxiliary routine for test program for Level 2 Blas. * * -- Written on 10-August-1987. * Richard Hanson, Sandia National Labs. * Jeremy Du Croz, NAG Central Office. * * .. Parameters .. COMPLEX ZERO, HALF, ONE PARAMETER ( ZERO = ( 0.0, 0.0 ), HALF = ( 0.5, 0.0 ), $ ONE = ( 1.0, 0.0 ) ) REAL RZERO PARAMETER ( RZERO = 0.0 ) * .. Scalar Arguments .. REAL EPS, THRESH INTEGER INCMAX, NALF, NIDIM, NINC, NMAX, NOUT, NTRA LOGICAL FATAL, REWI, TRACE CHARACTER*6 SNAME * .. Array Arguments .. COMPLEX A( NMAX, NMAX ), AA( NMAX*NMAX ), ALF( NALF ), $ AS( NMAX*NMAX ), X( NMAX ), XS( NMAX*INCMAX ), $ XX( NMAX*INCMAX ), Y( NMAX ), $ YS( NMAX*INCMAX ), YT( NMAX ), $ YY( NMAX*INCMAX ), Z( NMAX, 2 ) REAL G( NMAX ) INTEGER IDIM( NIDIM ), INC( NINC ) * .. Local Scalars .. COMPLEX ALPHA, ALS, TRANSL REAL ERR, ERRMAX INTEGER I, IA, IC, IN, INCX, INCXS, INCY, INCYS, IX, $ IY, J, JA, JJ, LAA, LDA, LDAS, LJ, LX, LY, N, $ NARGS, NC, NS LOGICAL FULL, NULL, PACKED, RESET, SAME, UPPER CHARACTER*1 UPLO, UPLOS CHARACTER*2 ICH * .. Local Arrays .. COMPLEX W( 2 ) LOGICAL ISAME( 13 ) * .. External Functions .. LOGICAL LCE, LCERES EXTERNAL LCE, LCERES * .. External Subroutines .. EXTERNAL CHER2, CHPR2, CMAKE, CMVCH * .. Intrinsic Functions .. INTRINSIC ABS, CONJG, MAX * .. Scalars in Common .. INTEGER INFOT, NOUTC LOGICAL LERR, OK * .. Common blocks .. COMMON /INFOC/INFOT, NOUTC, OK, LERR * .. Data statements .. DATA ICH/'UL'/ * .. Executable Statements .. FULL = SNAME( 3: 3 ).EQ.'E' PACKED = SNAME( 3: 3 ).EQ.'P' * Define the number of arguments. IF( FULL )THEN NARGS = 9 ELSE IF( PACKED )THEN NARGS = 8 END IF * NC = 0 RESET = .TRUE. ERRMAX = RZERO * DO 140 IN = 1, NIDIM N = IDIM( IN ) * Set LDA to 1 more than minimum value if room. LDA = N IF( LDA.LT.NMAX ) $ LDA = LDA + 1 * Skip tests if not enough room. IF( LDA.GT.NMAX ) $ GO TO 140 IF( PACKED )THEN LAA = ( N*( N + 1 ) )/2 ELSE LAA = LDA*N END IF * DO 130 IC = 1, 2 UPLO = ICH( IC: IC ) UPPER = UPLO.EQ.'U' * DO 120 IX = 1, NINC INCX = INC( IX ) LX = ABS( INCX )*N * * Generate the vector X. * TRANSL = HALF CALL CMAKE( 'GE', ' ', ' ', 1, N, X, 1, XX, ABS( INCX ), $ 0, N - 1, RESET, TRANSL ) IF( N.GT.1 )THEN X( N/2 ) = ZERO XX( 1 + ABS( INCX )*( N/2 - 1 ) ) = ZERO END IF * DO 110 IY = 1, NINC INCY = INC( IY ) LY = ABS( INCY )*N * * Generate the vector Y. * TRANSL = ZERO CALL CMAKE( 'GE', ' ', ' ', 1, N, Y, 1, YY, $ ABS( INCY ), 0, N - 1, RESET, TRANSL ) IF( N.GT.1 )THEN Y( N/2 ) = ZERO YY( 1 + ABS( INCY )*( N/2 - 1 ) ) = ZERO END IF * DO 100 IA = 1, NALF ALPHA = ALF( IA ) NULL = N.LE.0.OR.ALPHA.EQ.ZERO * * Generate the matrix A. * TRANSL = ZERO CALL CMAKE( SNAME( 2: 3 ), UPLO, ' ', N, N, A, $ NMAX, AA, LDA, N - 1, N - 1, RESET, $ TRANSL ) * NC = NC + 1 * * Save every datum before calling the subroutine. * UPLOS = UPLO NS = N ALS = ALPHA DO 10 I = 1, LAA AS( I ) = AA( I ) 10 CONTINUE LDAS = LDA DO 20 I = 1, LX XS( I ) = XX( I ) 20 CONTINUE INCXS = INCX DO 30 I = 1, LY YS( I ) = YY( I ) 30 CONTINUE INCYS = INCY * * Call the subroutine. * IF( FULL )THEN IF( TRACE ) $ WRITE( NTRA, FMT = 9993 )NC, SNAME, UPLO, N, $ ALPHA, INCX, INCY, LDA IF( REWI ) $ REWIND NTRA CALL CHER2( UPLO, N, ALPHA, XX, INCX, YY, INCY, $ AA, LDA ) ELSE IF( PACKED )THEN IF( TRACE ) $ WRITE( NTRA, FMT = 9994 )NC, SNAME, UPLO, N, $ ALPHA, INCX, INCY IF( REWI ) $ REWIND NTRA CALL CHPR2( UPLO, N, ALPHA, XX, INCX, YY, INCY, $ AA ) END IF * * Check if error-exit was taken incorrectly. * IF( .NOT.OK )THEN WRITE( NOUT, FMT = 9992 ) FATAL = .TRUE. GO TO 160 END IF * * See what data changed inside subroutines. * ISAME( 1 ) = UPLO.EQ.UPLOS ISAME( 2 ) = NS.EQ.N ISAME( 3 ) = ALS.EQ.ALPHA ISAME( 4 ) = LCE( XS, XX, LX ) ISAME( 5 ) = INCXS.EQ.INCX ISAME( 6 ) = LCE( YS, YY, LY ) ISAME( 7 ) = INCYS.EQ.INCY IF( NULL )THEN ISAME( 8 ) = LCE( AS, AA, LAA ) ELSE ISAME( 8 ) = LCERES( SNAME( 2: 3 ), UPLO, N, N, $ AS, AA, LDA ) END IF IF( .NOT.PACKED )THEN ISAME( 9 ) = LDAS.EQ.LDA END IF * * If data was incorrectly changed, report and return. * SAME = .TRUE. DO 40 I = 1, NARGS SAME = SAME.AND.ISAME( I ) IF( .NOT.ISAME( I ) ) $ WRITE( NOUT, FMT = 9998 )I 40 CONTINUE IF( .NOT.SAME )THEN FATAL = .TRUE. GO TO 160 END IF * IF( .NOT.NULL )THEN * * Check the result column by column. * IF( INCX.GT.0 )THEN DO 50 I = 1, N Z( I, 1 ) = X( I ) 50 CONTINUE ELSE DO 60 I = 1, N Z( I, 1 ) = X( N - I + 1 ) 60 CONTINUE END IF IF( INCY.GT.0 )THEN DO 70 I = 1, N Z( I, 2 ) = Y( I ) 70 CONTINUE ELSE DO 80 I = 1, N Z( I, 2 ) = Y( N - I + 1 ) 80 CONTINUE END IF JA = 1 DO 90 J = 1, N W( 1 ) = ALPHA*CONJG( Z( J, 2 ) ) W( 2 ) = CONJG( ALPHA )*CONJG( Z( J, 1 ) ) IF( UPPER )THEN JJ = 1 LJ = J ELSE JJ = J LJ = N - J + 1 END IF CALL CMVCH( 'N', LJ, 2, ONE, Z( JJ, 1 ), $ NMAX, W, 1, ONE, A( JJ, J ), 1, $ YT, G, AA( JA ), EPS, ERR, FATAL, $ NOUT, .TRUE. ) IF( FULL )THEN IF( UPPER )THEN JA = JA + LDA ELSE JA = JA + LDA + 1 END IF ELSE JA = JA + LJ END IF ERRMAX = MAX( ERRMAX, ERR ) * If got really bad answer, report and return. IF( FATAL ) $ GO TO 150 90 CONTINUE ELSE * Avoid repeating tests with N.le.0. IF( N.LE.0 ) $ GO TO 140 END IF * 100 CONTINUE * 110 CONTINUE * 120 CONTINUE * 130 CONTINUE * 140 CONTINUE * * Report result. * IF( ERRMAX.LT.THRESH )THEN WRITE( NOUT, FMT = 9999 )SNAME, NC ELSE WRITE( NOUT, FMT = 9997 )SNAME, NC, ERRMAX END IF GO TO 170 * 150 CONTINUE WRITE( NOUT, FMT = 9995 )J * 160 CONTINUE WRITE( NOUT, FMT = 9996 )SNAME IF( FULL )THEN WRITE( NOUT, FMT = 9993 )NC, SNAME, UPLO, N, ALPHA, INCX, $ INCY, LDA ELSE IF( PACKED )THEN WRITE( NOUT, FMT = 9994 )NC, SNAME, UPLO, N, ALPHA, INCX, INCY END IF * 170 CONTINUE RETURN * 9999 FORMAT( ' ', A6, ' PASSED THE COMPUTATIONAL TESTS (', I6, ' CALL', $ 'S)' ) 9998 FORMAT( ' ******* FATAL ERROR - PARAMETER NUMBER ', I2, ' WAS CH', $ 'ANGED INCORRECTLY *******' ) 9997 FORMAT( ' ', A6, ' COMPLETED THE COMPUTATIONAL TESTS (', I6, ' C', $ 'ALLS)', /' ******* BUT WITH MAXIMUM TEST RATIO', F8.2, $ ' - SUSPECT *******' ) 9996 FORMAT( ' ******* ', A6, ' FAILED ON CALL NUMBER:' ) 9995 FORMAT( ' THESE ARE THE RESULTS FOR COLUMN ', I3 ) 9994 FORMAT( 1X, I6, ': ', A6, '(''', A1, ''',', I3, ',(', F4.1, ',', $ F4.1, '), X,', I2, ', Y,', I2, ', AP) ', $ ' .' ) 9993 FORMAT( 1X, I6, ': ', A6, '(''', A1, ''',', I3, ',(', F4.1, ',', $ F4.1, '), X,', I2, ', Y,', I2, ', A,', I3, ') ', $ ' .' ) 9992 FORMAT( ' ******* FATAL ERROR - ERROR-EXIT TAKEN ON VALID CALL *', $ '******' ) * * End of CCHK6. * END SUBROUTINE CCHKE( ISNUM, SRNAMT, NOUT ) * * Tests the error exits from the Level 2 Blas. * Requires a special version of the error-handling routine XERBLA. * ALPHA, RALPHA, BETA, A, X and Y should not need to be defined. * * Auxiliary routine for test program for Level 2 Blas. * * -- Written on 10-August-1987. * Richard Hanson, Sandia National Labs. * Jeremy Du Croz, NAG Central Office. * * .. Scalar Arguments .. INTEGER ISNUM, NOUT CHARACTER*6 SRNAMT * .. Scalars in Common .. INTEGER INFOT, NOUTC LOGICAL LERR, OK * .. Local Scalars .. COMPLEX ALPHA, BETA REAL RALPHA * .. Local Arrays .. COMPLEX A( 1, 1 ), X( 1 ), Y( 1 ) * .. External Subroutines .. EXTERNAL CGBMV, CGEMV, CGERC, CGERU, CHBMV, CHEMV, CHER, $ CHER2, CHKXER, CHPMV, CHPR, CHPR2, CTBMV, $ CTBSV, CTPMV, CTPSV, CTRMV, CTRSV * .. Common blocks .. COMMON /INFOC/INFOT, NOUTC, OK, LERR * .. Executable Statements .. * OK is set to .FALSE. by the special version of XERBLA or by CHKXER * if anything is wrong. OK = .TRUE. * LERR is set to .TRUE. by the special version of XERBLA each time * it is called, and is then tested and re-set by CHKXER. LERR = .FALSE. GO TO ( 10, 20, 30, 40, 50, 60, 70, 80, $ 90, 100, 110, 120, 130, 140, 150, 160, $ 170 )ISNUM 10 INFOT = 1 CALL CGEMV( '/', 0, 0, ALPHA, A, 1, X, 1, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL CGEMV( 'N', -1, 0, ALPHA, A, 1, X, 1, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL CGEMV( 'N', 0, -1, ALPHA, A, 1, X, 1, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL CGEMV( 'N', 2, 0, ALPHA, A, 1, X, 1, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 8 CALL CGEMV( 'N', 0, 0, ALPHA, A, 1, X, 0, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL CGEMV( 'N', 0, 0, ALPHA, A, 1, X, 1, BETA, Y, 0 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 180 20 INFOT = 1 CALL CGBMV( '/', 0, 0, 0, 0, ALPHA, A, 1, X, 1, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL CGBMV( 'N', -1, 0, 0, 0, ALPHA, A, 1, X, 1, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL CGBMV( 'N', 0, -1, 0, 0, ALPHA, A, 1, X, 1, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL CGBMV( 'N', 0, 0, -1, 0, ALPHA, A, 1, X, 1, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL CGBMV( 'N', 2, 0, 0, -1, ALPHA, A, 1, X, 1, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 8 CALL CGBMV( 'N', 0, 0, 1, 0, ALPHA, A, 1, X, 1, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 10 CALL CGBMV( 'N', 0, 0, 0, 0, ALPHA, A, 1, X, 0, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 13 CALL CGBMV( 'N', 0, 0, 0, 0, ALPHA, A, 1, X, 1, BETA, Y, 0 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 180 30 INFOT = 1 CALL CHEMV( '/', 0, ALPHA, A, 1, X, 1, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL CHEMV( 'U', -1, ALPHA, A, 1, X, 1, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL CHEMV( 'U', 2, ALPHA, A, 1, X, 1, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL CHEMV( 'U', 0, ALPHA, A, 1, X, 0, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 10 CALL CHEMV( 'U', 0, ALPHA, A, 1, X, 1, BETA, Y, 0 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 180 40 INFOT = 1 CALL CHBMV( '/', 0, 0, ALPHA, A, 1, X, 1, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL CHBMV( 'U', -1, 0, ALPHA, A, 1, X, 1, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL CHBMV( 'U', 0, -1, ALPHA, A, 1, X, 1, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL CHBMV( 'U', 0, 1, ALPHA, A, 1, X, 1, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 8 CALL CHBMV( 'U', 0, 0, ALPHA, A, 1, X, 0, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL CHBMV( 'U', 0, 0, ALPHA, A, 1, X, 1, BETA, Y, 0 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 180 50 INFOT = 1 CALL CHPMV( '/', 0, ALPHA, A, X, 1, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL CHPMV( 'U', -1, ALPHA, A, X, 1, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL CHPMV( 'U', 0, ALPHA, A, X, 0, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL CHPMV( 'U', 0, ALPHA, A, X, 1, BETA, Y, 0 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 180 60 INFOT = 1 CALL CTRMV( '/', 'N', 'N', 0, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL CTRMV( 'U', '/', 'N', 0, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL CTRMV( 'U', 'N', '/', 0, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL CTRMV( 'U', 'N', 'N', -1, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL CTRMV( 'U', 'N', 'N', 2, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 8 CALL CTRMV( 'U', 'N', 'N', 0, A, 1, X, 0 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 180 70 INFOT = 1 CALL CTBMV( '/', 'N', 'N', 0, 0, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL CTBMV( 'U', '/', 'N', 0, 0, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL CTBMV( 'U', 'N', '/', 0, 0, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL CTBMV( 'U', 'N', 'N', -1, 0, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL CTBMV( 'U', 'N', 'N', 0, -1, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL CTBMV( 'U', 'N', 'N', 0, 1, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL CTBMV( 'U', 'N', 'N', 0, 0, A, 1, X, 0 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 180 80 INFOT = 1 CALL CTPMV( '/', 'N', 'N', 0, A, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL CTPMV( 'U', '/', 'N', 0, A, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL CTPMV( 'U', 'N', '/', 0, A, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL CTPMV( 'U', 'N', 'N', -1, A, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL CTPMV( 'U', 'N', 'N', 0, A, X, 0 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 180 90 INFOT = 1 CALL CTRSV( '/', 'N', 'N', 0, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL CTRSV( 'U', '/', 'N', 0, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL CTRSV( 'U', 'N', '/', 0, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL CTRSV( 'U', 'N', 'N', -1, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL CTRSV( 'U', 'N', 'N', 2, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 8 CALL CTRSV( 'U', 'N', 'N', 0, A, 1, X, 0 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 180 100 INFOT = 1 CALL CTBSV( '/', 'N', 'N', 0, 0, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL CTBSV( 'U', '/', 'N', 0, 0, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL CTBSV( 'U', 'N', '/', 0, 0, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL CTBSV( 'U', 'N', 'N', -1, 0, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL CTBSV( 'U', 'N', 'N', 0, -1, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL CTBSV( 'U', 'N', 'N', 0, 1, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL CTBSV( 'U', 'N', 'N', 0, 0, A, 1, X, 0 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 180 110 INFOT = 1 CALL CTPSV( '/', 'N', 'N', 0, A, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL CTPSV( 'U', '/', 'N', 0, A, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL CTPSV( 'U', 'N', '/', 0, A, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL CTPSV( 'U', 'N', 'N', -1, A, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL CTPSV( 'U', 'N', 'N', 0, A, X, 0 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 180 120 INFOT = 1 CALL CGERC( -1, 0, ALPHA, X, 1, Y, 1, A, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL CGERC( 0, -1, ALPHA, X, 1, Y, 1, A, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL CGERC( 0, 0, ALPHA, X, 0, Y, 1, A, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL CGERC( 0, 0, ALPHA, X, 1, Y, 0, A, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL CGERC( 2, 0, ALPHA, X, 1, Y, 1, A, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 180 130 INFOT = 1 CALL CGERU( -1, 0, ALPHA, X, 1, Y, 1, A, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL CGERU( 0, -1, ALPHA, X, 1, Y, 1, A, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL CGERU( 0, 0, ALPHA, X, 0, Y, 1, A, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL CGERU( 0, 0, ALPHA, X, 1, Y, 0, A, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL CGERU( 2, 0, ALPHA, X, 1, Y, 1, A, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 180 140 INFOT = 1 CALL CHER( '/', 0, RALPHA, X, 1, A, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL CHER( 'U', -1, RALPHA, X, 1, A, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL CHER( 'U', 0, RALPHA, X, 0, A, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL CHER( 'U', 2, RALPHA, X, 1, A, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 180 150 INFOT = 1 CALL CHPR( '/', 0, RALPHA, X, 1, A ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL CHPR( 'U', -1, RALPHA, X, 1, A ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL CHPR( 'U', 0, RALPHA, X, 0, A ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 180 160 INFOT = 1 CALL CHER2( '/', 0, ALPHA, X, 1, Y, 1, A, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL CHER2( 'U', -1, ALPHA, X, 1, Y, 1, A, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL CHER2( 'U', 0, ALPHA, X, 0, Y, 1, A, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL CHER2( 'U', 0, ALPHA, X, 1, Y, 0, A, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL CHER2( 'U', 2, ALPHA, X, 1, Y, 1, A, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 180 170 INFOT = 1 CALL CHPR2( '/', 0, ALPHA, X, 1, Y, 1, A ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL CHPR2( 'U', -1, ALPHA, X, 1, Y, 1, A ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL CHPR2( 'U', 0, ALPHA, X, 0, Y, 1, A ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL CHPR2( 'U', 0, ALPHA, X, 1, Y, 0, A ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) * 180 IF( OK )THEN WRITE( NOUT, FMT = 9999 )SRNAMT ELSE WRITE( NOUT, FMT = 9998 )SRNAMT END IF RETURN * 9999 FORMAT( ' ', A6, ' PASSED THE TESTS OF ERROR-EXITS' ) 9998 FORMAT( ' ******* ', A6, ' FAILED THE TESTS OF ERROR-EXITS *****', $ '**' ) * * End of CCHKE. * END SUBROUTINE CMAKE( TYPE, UPLO, DIAG, M, N, A, NMAX, AA, LDA, KL, $ KU, RESET, TRANSL ) * * Generates values for an M by N matrix A within the bandwidth * defined by KL and KU. * Stores the values in the array AA in the data structure required * by the routine, with unwanted elements set to rogue value. * * TYPE is 'GE', 'GB', 'HE', 'HB', 'HP', 'TR', 'TB' OR 'TP'. * * Auxiliary routine for test program for Level 2 Blas. * * -- Written on 10-August-1987. * Richard Hanson, Sandia National Labs. * Jeremy Du Croz, NAG Central Office. * * .. Parameters .. COMPLEX ZERO, ONE PARAMETER ( ZERO = ( 0.0, 0.0 ), ONE = ( 1.0, 0.0 ) ) COMPLEX ROGUE PARAMETER ( ROGUE = ( -1.0E10, 1.0E10 ) ) REAL RZERO PARAMETER ( RZERO = 0.0 ) REAL RROGUE PARAMETER ( RROGUE = -1.0E10 ) * .. Scalar Arguments .. COMPLEX TRANSL INTEGER KL, KU, LDA, M, N, NMAX LOGICAL RESET CHARACTER*1 DIAG, UPLO CHARACTER*2 TYPE * .. Array Arguments .. COMPLEX A( NMAX, * ), AA( * ) * .. Local Scalars .. INTEGER I, I1, I2, I3, IBEG, IEND, IOFF, J, JJ, KK LOGICAL GEN, LOWER, SYM, TRI, UNIT, UPPER * .. External Functions .. COMPLEX CBEG EXTERNAL CBEG * .. Intrinsic Functions .. INTRINSIC CMPLX, CONJG, MAX, MIN, REAL * .. Executable Statements .. GEN = TYPE( 1: 1 ).EQ.'G' SYM = TYPE( 1: 1 ).EQ.'H' TRI = TYPE( 1: 1 ).EQ.'T' UPPER = ( SYM.OR.TRI ).AND.UPLO.EQ.'U' LOWER = ( SYM.OR.TRI ).AND.UPLO.EQ.'L' UNIT = TRI.AND.DIAG.EQ.'U' * * Generate data in array A. * DO 20 J = 1, N DO 10 I = 1, M IF( GEN.OR.( UPPER.AND.I.LE.J ).OR.( LOWER.AND.I.GE.J ) ) $ THEN IF( ( I.LE.J.AND.J - I.LE.KU ).OR. $ ( I.GE.J.AND.I - J.LE.KL ) )THEN A( I, J ) = CBEG( RESET ) + TRANSL ELSE A( I, J ) = ZERO END IF IF( I.NE.J )THEN IF( SYM )THEN A( J, I ) = CONJG( A( I, J ) ) ELSE IF( TRI )THEN A( J, I ) = ZERO END IF END IF END IF 10 CONTINUE IF( SYM ) $ A( J, J ) = CMPLX( REAL( A( J, J ) ), RZERO ) IF( TRI ) $ A( J, J ) = A( J, J ) + ONE IF( UNIT ) $ A( J, J ) = ONE 20 CONTINUE * * Store elements in array AS in data structure required by routine. * IF( TYPE.EQ.'GE' )THEN DO 50 J = 1, N DO 30 I = 1, M AA( I + ( J - 1 )*LDA ) = A( I, J ) 30 CONTINUE DO 40 I = M + 1, LDA AA( I + ( J - 1 )*LDA ) = ROGUE 40 CONTINUE 50 CONTINUE ELSE IF( TYPE.EQ.'GB' )THEN DO 90 J = 1, N DO 60 I1 = 1, KU + 1 - J AA( I1 + ( J - 1 )*LDA ) = ROGUE 60 CONTINUE DO 70 I2 = I1, MIN( KL + KU + 1, KU + 1 + M - J ) AA( I2 + ( J - 1 )*LDA ) = A( I2 + J - KU - 1, J ) 70 CONTINUE DO 80 I3 = I2, LDA AA( I3 + ( J - 1 )*LDA ) = ROGUE 80 CONTINUE 90 CONTINUE ELSE IF( TYPE.EQ.'HE'.OR.TYPE.EQ.'TR' )THEN DO 130 J = 1, N IF( UPPER )THEN IBEG = 1 IF( UNIT )THEN IEND = J - 1 ELSE IEND = J END IF ELSE IF( UNIT )THEN IBEG = J + 1 ELSE IBEG = J END IF IEND = N END IF DO 100 I = 1, IBEG - 1 AA( I + ( J - 1 )*LDA ) = ROGUE 100 CONTINUE DO 110 I = IBEG, IEND AA( I + ( J - 1 )*LDA ) = A( I, J ) 110 CONTINUE DO 120 I = IEND + 1, LDA AA( I + ( J - 1 )*LDA ) = ROGUE 120 CONTINUE IF( SYM )THEN JJ = J + ( J - 1 )*LDA AA( JJ ) = CMPLX( REAL( AA( JJ ) ), RROGUE ) END IF 130 CONTINUE ELSE IF( TYPE.EQ.'HB'.OR.TYPE.EQ.'TB' )THEN DO 170 J = 1, N IF( UPPER )THEN KK = KL + 1 IBEG = MAX( 1, KL + 2 - J ) IF( UNIT )THEN IEND = KL ELSE IEND = KL + 1 END IF ELSE KK = 1 IF( UNIT )THEN IBEG = 2 ELSE IBEG = 1 END IF IEND = MIN( KL + 1, 1 + M - J ) END IF DO 140 I = 1, IBEG - 1 AA( I + ( J - 1 )*LDA ) = ROGUE 140 CONTINUE DO 150 I = IBEG, IEND AA( I + ( J - 1 )*LDA ) = A( I + J - KK, J ) 150 CONTINUE DO 160 I = IEND + 1, LDA AA( I + ( J - 1 )*LDA ) = ROGUE 160 CONTINUE IF( SYM )THEN JJ = KK + ( J - 1 )*LDA AA( JJ ) = CMPLX( REAL( AA( JJ ) ), RROGUE ) END IF 170 CONTINUE ELSE IF( TYPE.EQ.'HP'.OR.TYPE.EQ.'TP' )THEN IOFF = 0 DO 190 J = 1, N IF( UPPER )THEN IBEG = 1 IEND = J ELSE IBEG = J IEND = N END IF DO 180 I = IBEG, IEND IOFF = IOFF + 1 AA( IOFF ) = A( I, J ) IF( I.EQ.J )THEN IF( UNIT ) $ AA( IOFF ) = ROGUE IF( SYM ) $ AA( IOFF ) = CMPLX( REAL( AA( IOFF ) ), RROGUE ) END IF 180 CONTINUE 190 CONTINUE END IF RETURN * * End of CMAKE. * END SUBROUTINE CMVCH( TRANS, M, N, ALPHA, A, NMAX, X, INCX, BETA, Y, $ INCY, YT, G, YY, EPS, ERR, FATAL, NOUT, MV ) * * Checks the results of the computational tests. * * Auxiliary routine for test program for Level 2 Blas. * * -- Written on 10-August-1987. * Richard Hanson, Sandia National Labs. * Jeremy Du Croz, NAG Central Office. * * .. Parameters .. COMPLEX ZERO PARAMETER ( ZERO = ( 0.0, 0.0 ) ) REAL RZERO, RONE PARAMETER ( RZERO = 0.0, RONE = 1.0 ) * .. Scalar Arguments .. COMPLEX ALPHA, BETA REAL EPS, ERR INTEGER INCX, INCY, M, N, NMAX, NOUT LOGICAL FATAL, MV CHARACTER*1 TRANS * .. Array Arguments .. COMPLEX A( NMAX, * ), X( * ), Y( * ), YT( * ), YY( * ) REAL G( * ) * .. Local Scalars .. COMPLEX C REAL ERRI INTEGER I, INCXL, INCYL, IY, J, JX, KX, KY, ML, NL LOGICAL CTRAN, TRAN * .. Intrinsic Functions .. INTRINSIC ABS, AIMAG, CONJG, MAX, REAL, SQRT * .. Statement Functions .. REAL ABS1 * .. Statement Function definitions .. ABS1( C ) = ABS( REAL( C ) ) + ABS( AIMAG( C ) ) * .. Executable Statements .. TRAN = TRANS.EQ.'T' CTRAN = TRANS.EQ.'C' IF( TRAN.OR.CTRAN )THEN ML = N NL = M ELSE ML = M NL = N END IF IF( INCX.LT.0 )THEN KX = NL INCXL = -1 ELSE KX = 1 INCXL = 1 END IF IF( INCY.LT.0 )THEN KY = ML INCYL = -1 ELSE KY = 1 INCYL = 1 END IF * * Compute expected result in YT using data in A, X and Y. * Compute gauges in G. * IY = KY DO 40 I = 1, ML YT( IY ) = ZERO G( IY ) = RZERO JX = KX IF( TRAN )THEN DO 10 J = 1, NL YT( IY ) = YT( IY ) + A( J, I )*X( JX ) G( IY ) = G( IY ) + ABS1( A( J, I ) )*ABS1( X( JX ) ) JX = JX + INCXL 10 CONTINUE ELSE IF( CTRAN )THEN DO 20 J = 1, NL YT( IY ) = YT( IY ) + CONJG( A( J, I ) )*X( JX ) G( IY ) = G( IY ) + ABS1( A( J, I ) )*ABS1( X( JX ) ) JX = JX + INCXL 20 CONTINUE ELSE DO 30 J = 1, NL YT( IY ) = YT( IY ) + A( I, J )*X( JX ) G( IY ) = G( IY ) + ABS1( A( I, J ) )*ABS1( X( JX ) ) JX = JX + INCXL 30 CONTINUE END IF YT( IY ) = ALPHA*YT( IY ) + BETA*Y( IY ) G( IY ) = ABS1( ALPHA )*G( IY ) + ABS1( BETA )*ABS1( Y( IY ) ) IY = IY + INCYL 40 CONTINUE * * Compute the error ratio for this result. * ERR = ZERO DO 50 I = 1, ML ERRI = ABS( YT( I ) - YY( 1 + ( I - 1 )*ABS( INCY ) ) )/EPS IF( G( I ).NE.RZERO ) $ ERRI = ERRI/G( I ) ERR = MAX( ERR, ERRI ) IF( ERR*SQRT( EPS ).GE.RONE ) $ GO TO 60 50 CONTINUE * If the loop completes, all results are at least half accurate. GO TO 80 * * Report fatal error. * 60 FATAL = .TRUE. WRITE( NOUT, FMT = 9999 ) DO 70 I = 1, ML IF( MV )THEN WRITE( NOUT, FMT = 9998 )I, YT( I ), $ YY( 1 + ( I - 1 )*ABS( INCY ) ) ELSE WRITE( NOUT, FMT = 9998 )I, $ YY( 1 + ( I - 1 )*ABS( INCY ) ), YT( I ) END IF 70 CONTINUE * 80 CONTINUE RETURN * 9999 FORMAT( ' ******* FATAL ERROR - COMPUTED RESULT IS LESS THAN HAL', $ 'F ACCURATE *******', /' EXPECTED RE', $ 'SULT COMPUTED RESULT' ) 9998 FORMAT( 1X, I7, 2( ' (', G15.6, ',', G15.6, ')' ) ) * * End of CMVCH. * END LOGICAL FUNCTION LCE( RI, RJ, LR ) * * Tests if two arrays are identical. * * Auxiliary routine for test program for Level 2 Blas. * * -- Written on 10-August-1987. * Richard Hanson, Sandia National Labs. * Jeremy Du Croz, NAG Central Office. * * .. Scalar Arguments .. INTEGER LR * .. Array Arguments .. COMPLEX RI( * ), RJ( * ) * .. Local Scalars .. INTEGER I * .. Executable Statements .. DO 10 I = 1, LR IF( RI( I ).NE.RJ( I ) ) $ GO TO 20 10 CONTINUE LCE = .TRUE. GO TO 30 20 CONTINUE LCE = .FALSE. 30 RETURN * * End of LCE. * END LOGICAL FUNCTION LCERES( TYPE, UPLO, M, N, AA, AS, LDA ) * * Tests if selected elements in two arrays are equal. * * TYPE is 'GE', 'HE' or 'HP'. * * Auxiliary routine for test program for Level 2 Blas. * * -- Written on 10-August-1987. * Richard Hanson, Sandia National Labs. * Jeremy Du Croz, NAG Central Office. * * .. Scalar Arguments .. INTEGER LDA, M, N CHARACTER*1 UPLO CHARACTER*2 TYPE * .. Array Arguments .. COMPLEX AA( LDA, * ), AS( LDA, * ) * .. Local Scalars .. INTEGER I, IBEG, IEND, J LOGICAL UPPER * .. Executable Statements .. UPPER = UPLO.EQ.'U' IF( TYPE.EQ.'GE' )THEN DO 20 J = 1, N DO 10 I = M + 1, LDA IF( AA( I, J ).NE.AS( I, J ) ) $ GO TO 70 10 CONTINUE 20 CONTINUE ELSE IF( TYPE.EQ.'HE' )THEN DO 50 J = 1, N IF( UPPER )THEN IBEG = 1 IEND = J ELSE IBEG = J IEND = N END IF DO 30 I = 1, IBEG - 1 IF( AA( I, J ).NE.AS( I, J ) ) $ GO TO 70 30 CONTINUE DO 40 I = IEND + 1, LDA IF( AA( I, J ).NE.AS( I, J ) ) $ GO TO 70 40 CONTINUE 50 CONTINUE END IF * LCERES = .TRUE. GO TO 80 70 CONTINUE LCERES = .FALSE. 80 RETURN * * End of LCERES. * END COMPLEX FUNCTION CBEG( RESET ) * * Generates complex numbers as pairs of random numbers uniformly * distributed between -0.5 and 0.5. * * Auxiliary routine for test program for Level 2 Blas. * * -- Written on 10-August-1987. * Richard Hanson, Sandia National Labs. * Jeremy Du Croz, NAG Central Office. * * .. Scalar Arguments .. LOGICAL RESET * .. Local Scalars .. INTEGER I, IC, J, MI, MJ * .. Save statement .. SAVE I, IC, J, MI, MJ * .. Intrinsic Functions .. INTRINSIC CMPLX * .. Executable Statements .. IF( RESET )THEN * Initialize local variables. MI = 891 MJ = 457 I = 7 J = 7 IC = 0 RESET = .FALSE. END IF * * The sequence of values of I or J is bounded between 1 and 999. * If initial I or J = 1,2,3,6,7 or 9, the period will be 50. * If initial I or J = 4 or 8, the period will be 25. * If initial I or J = 5, the period will be 10. * IC is used to break up the period by skipping 1 value of I or J * in 6. * IC = IC + 1 10 I = I*MI J = J*MJ I = I - 1000*( I/1000 ) J = J - 1000*( J/1000 ) IF( IC.GE.5 )THEN IC = 0 GO TO 10 END IF CBEG = CMPLX( ( I - 500 )/1001.0, ( J - 500 )/1001.0 ) RETURN * * End of CBEG. * END REAL FUNCTION SDIFF( X, Y ) * * Auxiliary routine for test program for Level 2 Blas. * * -- Written on 10-August-1987. * Richard Hanson, Sandia National Labs. * * .. Scalar Arguments .. REAL X, Y * .. Executable Statements .. SDIFF = X - Y RETURN * * End of SDIFF. * END SUBROUTINE CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) * * Tests whether XERBLA has detected an error when it should. * * Auxiliary routine for test program for Level 2 Blas. * * -- Written on 10-August-1987. * Richard Hanson, Sandia National Labs. * Jeremy Du Croz, NAG Central Office. * * .. Scalar Arguments .. INTEGER INFOT, NOUT LOGICAL LERR, OK CHARACTER*6 SRNAMT * .. Executable Statements .. IF( .NOT.LERR )THEN WRITE( NOUT, FMT = 9999 )INFOT, SRNAMT OK = .FALSE. END IF LERR = .FALSE. RETURN * 9999 FORMAT( ' ***** ILLEGAL VALUE OF PARAMETER NUMBER ', I2, ' NOT D', $ 'ETECTED BY ', A6, ' *****' ) * * End of CHKXER. * END SUBROUTINE XERBLA( SRNAME, INFO ) * * This is a special version of XERBLA to be used only as part of * the test program for testing error exits from the Level 2 BLAS * routines. * * XERBLA is an error handler for the Level 2 BLAS routines. * * It is called by the Level 2 BLAS routines if an input parameter is * invalid. * * Auxiliary routine for test program for Level 2 Blas. * * -- Written on 10-August-1987. * Richard Hanson, Sandia National Labs. * Jeremy Du Croz, NAG Central Office. * * .. Scalar Arguments .. INTEGER INFO CHARACTER*6 SRNAME * .. Scalars in Common .. INTEGER INFOT, NOUT LOGICAL LERR, OK CHARACTER*6 SRNAMT * .. Common blocks .. COMMON /INFOC/INFOT, NOUT, OK, LERR COMMON /SRNAMC/SRNAMT * .. Executable Statements .. LERR = .TRUE. IF( INFO.NE.INFOT )THEN IF( INFOT.NE.0 )THEN WRITE( NOUT, FMT = 9999 )INFO, INFOT ELSE WRITE( NOUT, FMT = 9997 )INFO END IF OK = .FALSE. END IF IF( SRNAME.NE.SRNAMT )THEN WRITE( NOUT, FMT = 9998 )SRNAME, SRNAMT OK = .FALSE. END IF RETURN * 9999 FORMAT( ' ******* XERBLA WAS CALLED WITH INFO = ', I6, ' INSTEAD', $ ' OF ', I2, ' *******' ) 9998 FORMAT( ' ******* XERBLA WAS CALLED WITH SRNAME = ', A6, ' INSTE', $ 'AD OF ', A6, ' *******' ) 9997 FORMAT( ' ******* XERBLA WAS CALLED WITH INFO = ', I6, $ ' *******' ) * * End of XERBLA * END blis-0.9.0/blastest/src/fortran/cblat3.f000066400000000000000000004007361422157504600200730ustar00rootroot00000000000000*> \brief \b CBLAT3 * * =========== DOCUMENTATION =========== * * Online html documentation available at * http://www.netlib.org/lapack/explore-html/ * * Definition: * =========== * * PROGRAM CBLAT3 * * *> \par Purpose: * ============= *> *> \verbatim *> *> Test program for the COMPLEX Level 3 Blas. *> *> The program must be driven by a short data file. The first 14 records *> of the file are read using list-directed input, the last 9 records *> are read using the format ( A6, L2 ). An annotated example of a data *> file can be obtained by deleting the first 3 characters from the *> following 23 lines: *> 'cblat3.out' NAME OF SUMMARY OUTPUT FILE *> 6 UNIT NUMBER OF SUMMARY FILE *> 'CBLAT3.SNAP' NAME OF SNAPSHOT OUTPUT FILE *> -1 UNIT NUMBER OF SNAPSHOT FILE (NOT USED IF .LT. 0) *> F LOGICAL FLAG, T TO REWIND SNAPSHOT FILE AFTER EACH RECORD. *> F LOGICAL FLAG, T TO STOP ON FAILURES. *> T LOGICAL FLAG, T TO TEST ERROR EXITS. *> 16.0 THRESHOLD VALUE OF TEST RATIO *> 6 NUMBER OF VALUES OF N *> 0 1 2 3 5 9 VALUES OF N *> 3 NUMBER OF VALUES OF ALPHA *> (0.0,0.0) (1.0,0.0) (0.7,-0.9) VALUES OF ALPHA *> 3 NUMBER OF VALUES OF BETA *> (0.0,0.0) (1.0,0.0) (1.3,-1.1) VALUES OF BETA *> CGEMM T PUT F FOR NO TEST. SAME COLUMNS. *> CHEMM T PUT F FOR NO TEST. SAME COLUMNS. *> CSYMM T PUT F FOR NO TEST. SAME COLUMNS. *> CTRMM T PUT F FOR NO TEST. SAME COLUMNS. *> CTRSM T PUT F FOR NO TEST. SAME COLUMNS. *> CHERK T PUT F FOR NO TEST. SAME COLUMNS. *> CSYRK T PUT F FOR NO TEST. SAME COLUMNS. *> CHER2K T PUT F FOR NO TEST. SAME COLUMNS. *> CSYR2K T PUT F FOR NO TEST. SAME COLUMNS. *> *> Further Details *> =============== *> *> See: *> *> Dongarra J. J., Du Croz J. J., Duff I. S. and Hammarling S. *> A Set of Level 3 Basic Linear Algebra Subprograms. *> *> Technical Memorandum No.88 (Revision 1), Mathematics and *> Computer Science Division, Argonne National Laboratory, 9700 *> South Cass Avenue, Argonne, Illinois 60439, US. *> *> -- Written on 8-February-1989. *> Jack Dongarra, Argonne National Laboratory. *> Iain Duff, AERE Harwell. *> Jeremy Du Croz, Numerical Algorithms Group Ltd. *> Sven Hammarling, Numerical Algorithms Group Ltd. *> *> 10-9-00: Change STATUS='NEW' to 'UNKNOWN' so that the testers *> can be run multiple times without deleting generated *> output files (susan) *> \endverbatim * * Authors: * ======== * *> \author Univ. of Tennessee *> \author Univ. of California Berkeley *> \author Univ. of Colorado Denver *> \author NAG Ltd. * *> \date April 2012 * *> \ingroup complex_blas_testing * * ===================================================================== PROGRAM CBLAT3 * * -- Reference BLAS test routine (version 3.4.1) -- * -- Reference BLAS is a software package provided by Univ. of Tennessee, -- * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- * April 2012 * * ===================================================================== * * .. Parameters .. INTEGER NIN PARAMETER ( NIN = 5 ) INTEGER NSUBS PARAMETER ( NSUBS = 9 ) COMPLEX ZERO, ONE PARAMETER ( ZERO = ( 0.0, 0.0 ), ONE = ( 1.0, 0.0 ) ) REAL RZERO PARAMETER ( RZERO = 0.0 ) INTEGER NMAX PARAMETER ( NMAX = 65 ) INTEGER NIDMAX, NALMAX, NBEMAX PARAMETER ( NIDMAX = 9, NALMAX = 7, NBEMAX = 7 ) * .. Local Scalars .. REAL EPS, ERR, THRESH INTEGER I, ISNUM, J, N, NALF, NBET, NIDIM, NOUT, NTRA LOGICAL FATAL, LTESTT, REWI, SAME, SFATAL, TRACE, $ TSTERR CHARACTER*1 TRANSA, TRANSB CHARACTER*6 SNAMET CHARACTER*32 SNAPS, SUMMRY * .. Local Arrays .. COMPLEX AA( NMAX*NMAX ), AB( NMAX, 2*NMAX ), $ ALF( NALMAX ), AS( NMAX*NMAX ), $ BB( NMAX*NMAX ), BET( NBEMAX ), $ BS( NMAX*NMAX ), C( NMAX, NMAX ), $ CC( NMAX*NMAX ), CS( NMAX*NMAX ), CT( NMAX ), $ W( 2*NMAX ) REAL G( NMAX ) INTEGER IDIM( NIDMAX ) LOGICAL LTEST( NSUBS ) CHARACTER*6 SNAMES( NSUBS ) * .. External Functions .. REAL SDIFF LOGICAL LCE EXTERNAL SDIFF, LCE * .. External Subroutines .. EXTERNAL CCHK1, CCHK2, CCHK3, CCHK4, CCHK5, CCHKE, CMMCH * .. Intrinsic Functions .. INTRINSIC MAX, MIN * .. Scalars in Common .. INTEGER INFOT, NOUTC LOGICAL LERR, OK CHARACTER*6 SRNAMT * .. Common blocks .. COMMON /INFOC/INFOT, NOUTC, OK, LERR COMMON /SRNAMC/SRNAMT * .. Data statements .. DATA SNAMES/'CGEMM ', 'CHEMM ', 'CSYMM ', 'CTRMM ', $ 'CTRSM ', 'CHERK ', 'CSYRK ', 'CHER2K', $ 'CSYR2K'/ * .. Executable Statements .. * * Read name and unit number for summary output file and open file. * READ( NIN, FMT = * )SUMMRY READ( NIN, FMT = * )NOUT OPEN( NOUT, FILE = SUMMRY ) NOUTC = NOUT * * Read name and unit number for snapshot output file and open file. * READ( NIN, FMT = * )SNAPS READ( NIN, FMT = * )NTRA TRACE = NTRA.GE.0 IF( TRACE )THEN OPEN( NTRA, FILE = SNAPS ) END IF * Read the flag that directs rewinding of the snapshot file. READ( NIN, FMT = * )REWI REWI = REWI.AND.TRACE * Read the flag that directs stopping on any failure. READ( NIN, FMT = * )SFATAL * Read the flag that indicates whether error exits are to be tested. READ( NIN, FMT = * )TSTERR * Read the threshold value of the test ratio READ( NIN, FMT = * )THRESH * * Read and check the parameter values for the tests. * * Values of N READ( NIN, FMT = * )NIDIM IF( NIDIM.LT.1.OR.NIDIM.GT.NIDMAX )THEN WRITE( NOUT, FMT = 9997 )'N', NIDMAX GO TO 220 END IF READ( NIN, FMT = * )( IDIM( I ), I = 1, NIDIM ) DO 10 I = 1, NIDIM IF( IDIM( I ).LT.0.OR.IDIM( I ).GT.NMAX )THEN WRITE( NOUT, FMT = 9996 )NMAX GO TO 220 END IF 10 CONTINUE * Values of ALPHA READ( NIN, FMT = * )NALF IF( NALF.LT.1.OR.NALF.GT.NALMAX )THEN WRITE( NOUT, FMT = 9997 )'ALPHA', NALMAX GO TO 220 END IF READ( NIN, FMT = * )( ALF( I ), I = 1, NALF ) * Values of BETA READ( NIN, FMT = * )NBET IF( NBET.LT.1.OR.NBET.GT.NBEMAX )THEN WRITE( NOUT, FMT = 9997 )'BETA', NBEMAX GO TO 220 END IF READ( NIN, FMT = * )( BET( I ), I = 1, NBET ) * * Report values of parameters. * WRITE( NOUT, FMT = 9995 ) WRITE( NOUT, FMT = 9994 )( IDIM( I ), I = 1, NIDIM ) WRITE( NOUT, FMT = 9993 )( ALF( I ), I = 1, NALF ) WRITE( NOUT, FMT = 9992 )( BET( I ), I = 1, NBET ) IF( .NOT.TSTERR )THEN WRITE( NOUT, FMT = * ) WRITE( NOUT, FMT = 9984 ) END IF WRITE( NOUT, FMT = * ) WRITE( NOUT, FMT = 9999 )THRESH WRITE( NOUT, FMT = * ) * * Read names of subroutines and flags which indicate * whether they are to be tested. * DO 20 I = 1, NSUBS LTEST( I ) = .FALSE. 20 CONTINUE 30 READ( NIN, FMT = 9988, END = 60 )SNAMET, LTESTT DO 40 I = 1, NSUBS IF( SNAMET.EQ.SNAMES( I ) ) $ GO TO 50 40 CONTINUE WRITE( NOUT, FMT = 9990 )SNAMET STOP 50 LTEST( I ) = LTESTT GO TO 30 * 60 CONTINUE CLOSE ( NIN ) * * Compute EPS (the machine precision). * EPS = EPSILON(RZERO) WRITE( NOUT, FMT = 9998 )EPS * * Check the reliability of CMMCH using exact data. * N = MIN( 32, NMAX ) DO 100 J = 1, N DO 90 I = 1, N AB( I, J ) = MAX( I - J + 1, 0 ) 90 CONTINUE AB( J, NMAX + 1 ) = J AB( 1, NMAX + J ) = J C( J, 1 ) = ZERO 100 CONTINUE DO 110 J = 1, N CC( J ) = J*( ( J + 1 )*J )/2 - ( ( J + 1 )*J*( J - 1 ) )/3 110 CONTINUE * CC holds the exact result. On exit from CMMCH CT holds * the result computed by CMMCH. TRANSA = 'N' TRANSB = 'N' CALL CMMCH( TRANSA, TRANSB, N, 1, N, ONE, AB, NMAX, $ AB( 1, NMAX + 1 ), NMAX, ZERO, C, NMAX, CT, G, CC, $ NMAX, EPS, ERR, FATAL, NOUT, .TRUE. ) SAME = LCE( CC, CT, N ) IF( .NOT.SAME.OR.ERR.NE.RZERO )THEN WRITE( NOUT, FMT = 9989 )TRANSA, TRANSB, SAME, ERR STOP END IF TRANSB = 'C' CALL CMMCH( TRANSA, TRANSB, N, 1, N, ONE, AB, NMAX, $ AB( 1, NMAX + 1 ), NMAX, ZERO, C, NMAX, CT, G, CC, $ NMAX, EPS, ERR, FATAL, NOUT, .TRUE. ) SAME = LCE( CC, CT, N ) IF( .NOT.SAME.OR.ERR.NE.RZERO )THEN WRITE( NOUT, FMT = 9989 )TRANSA, TRANSB, SAME, ERR STOP END IF DO 120 J = 1, N AB( J, NMAX + 1 ) = N - J + 1 AB( 1, NMAX + J ) = N - J + 1 120 CONTINUE DO 130 J = 1, N CC( N - J + 1 ) = J*( ( J + 1 )*J )/2 - $ ( ( J + 1 )*J*( J - 1 ) )/3 130 CONTINUE TRANSA = 'C' TRANSB = 'N' CALL CMMCH( TRANSA, TRANSB, N, 1, N, ONE, AB, NMAX, $ AB( 1, NMAX + 1 ), NMAX, ZERO, C, NMAX, CT, G, CC, $ NMAX, EPS, ERR, FATAL, NOUT, .TRUE. ) SAME = LCE( CC, CT, N ) IF( .NOT.SAME.OR.ERR.NE.RZERO )THEN WRITE( NOUT, FMT = 9989 )TRANSA, TRANSB, SAME, ERR STOP END IF TRANSB = 'C' CALL CMMCH( TRANSA, TRANSB, N, 1, N, ONE, AB, NMAX, $ AB( 1, NMAX + 1 ), NMAX, ZERO, C, NMAX, CT, G, CC, $ NMAX, EPS, ERR, FATAL, NOUT, .TRUE. ) SAME = LCE( CC, CT, N ) IF( .NOT.SAME.OR.ERR.NE.RZERO )THEN WRITE( NOUT, FMT = 9989 )TRANSA, TRANSB, SAME, ERR STOP END IF * * Test each subroutine in turn. * DO 200 ISNUM = 1, NSUBS WRITE( NOUT, FMT = * ) IF( .NOT.LTEST( ISNUM ) )THEN * Subprogram is not to be tested. WRITE( NOUT, FMT = 9987 )SNAMES( ISNUM ) ELSE SRNAMT = SNAMES( ISNUM ) * Test error exits. IF( TSTERR )THEN CALL CCHKE( ISNUM, SNAMES( ISNUM ), NOUT ) WRITE( NOUT, FMT = * ) END IF * Test computations. INFOT = 0 OK = .TRUE. FATAL = .FALSE. GO TO ( 140, 150, 150, 160, 160, 170, 170, $ 180, 180 )ISNUM * Test CGEMM, 01. 140 CALL CCHK1( SNAMES( ISNUM ), EPS, THRESH, NOUT, NTRA, TRACE, $ REWI, FATAL, NIDIM, IDIM, NALF, ALF, NBET, BET, $ NMAX, AB, AA, AS, AB( 1, NMAX + 1 ), BB, BS, C, $ CC, CS, CT, G ) GO TO 190 * Test CHEMM, 02, CSYMM, 03. 150 CALL CCHK2( SNAMES( ISNUM ), EPS, THRESH, NOUT, NTRA, TRACE, $ REWI, FATAL, NIDIM, IDIM, NALF, ALF, NBET, BET, $ NMAX, AB, AA, AS, AB( 1, NMAX + 1 ), BB, BS, C, $ CC, CS, CT, G ) GO TO 190 * Test CTRMM, 04, CTRSM, 05. 160 CALL CCHK3( SNAMES( ISNUM ), EPS, THRESH, NOUT, NTRA, TRACE, $ REWI, FATAL, NIDIM, IDIM, NALF, ALF, NMAX, AB, $ AA, AS, AB( 1, NMAX + 1 ), BB, BS, CT, G, C ) GO TO 190 * Test CHERK, 06, CSYRK, 07. 170 CALL CCHK4( SNAMES( ISNUM ), EPS, THRESH, NOUT, NTRA, TRACE, $ REWI, FATAL, NIDIM, IDIM, NALF, ALF, NBET, BET, $ NMAX, AB, AA, AS, AB( 1, NMAX + 1 ), BB, BS, C, $ CC, CS, CT, G ) GO TO 190 * Test CHER2K, 08, CSYR2K, 09. 180 CALL CCHK5( SNAMES( ISNUM ), EPS, THRESH, NOUT, NTRA, TRACE, $ REWI, FATAL, NIDIM, IDIM, NALF, ALF, NBET, BET, $ NMAX, AB, AA, AS, BB, BS, C, CC, CS, CT, G, W ) GO TO 190 * 190 IF( FATAL.AND.SFATAL ) $ GO TO 210 END IF 200 CONTINUE WRITE( NOUT, FMT = 9986 ) GO TO 230 * 210 CONTINUE WRITE( NOUT, FMT = 9985 ) GO TO 230 * 220 CONTINUE WRITE( NOUT, FMT = 9991 ) * 230 CONTINUE IF( TRACE ) $ CLOSE ( NTRA ) CLOSE ( NOUT ) STOP * 9999 FORMAT( ' ROUTINES PASS COMPUTATIONAL TESTS IF TEST RATIO IS LES', $ 'S THAN', F8.2 ) 9998 FORMAT( ' RELATIVE MACHINE PRECISION IS TAKEN TO BE', 1P, E9.1 ) 9997 FORMAT( ' NUMBER OF VALUES OF ', A, ' IS LESS THAN 1 OR GREATER ', $ 'THAN ', I2 ) 9996 FORMAT( ' VALUE OF N IS LESS THAN 0 OR GREATER THAN ', I2 ) 9995 FORMAT( ' TESTS OF THE COMPLEX LEVEL 3 BLAS', //' THE F', $ 'OLLOWING PARAMETER VALUES WILL BE USED:' ) 9994 FORMAT( ' FOR N ', 9I6 ) 9993 FORMAT( ' FOR ALPHA ', $ 7( '(', F4.1, ',', F4.1, ') ', : ) ) 9992 FORMAT( ' FOR BETA ', $ 7( '(', F4.1, ',', F4.1, ') ', : ) ) 9991 FORMAT( ' AMEND DATA FILE OR INCREASE ARRAY SIZES IN PROGRAM', $ /' ******* TESTS ABANDONED *******' ) 9990 FORMAT( ' SUBPROGRAM NAME ', A6, ' NOT RECOGNIZED', /' ******* T', $ 'ESTS ABANDONED *******' ) 9989 FORMAT( ' ERROR IN CMMCH - IN-LINE DOT PRODUCTS ARE BEING EVALU', $ 'ATED WRONGLY.', /' CMMCH WAS CALLED WITH TRANSA = ', A1, $ ' AND TRANSB = ', A1, /' AND RETURNED SAME = ', L1, ' AND ', $ 'ERR = ', F12.3, '.', /' THIS MAY BE DUE TO FAULTS IN THE ', $ 'ARITHMETIC OR THE COMPILER.', /' ******* TESTS ABANDONED ', $ '*******' ) 9988 FORMAT( A6, L2 ) 9987 FORMAT( 1X, A6, ' WAS NOT TESTED' ) 9986 FORMAT( /' END OF TESTS' ) 9985 FORMAT( /' ******* FATAL ERROR - TESTS ABANDONED *******' ) 9984 FORMAT( ' ERROR-EXITS WILL NOT BE TESTED' ) * * End of CBLAT3. * END SUBROUTINE CCHK1( SNAME, EPS, THRESH, NOUT, NTRA, TRACE, REWI, $ FATAL, NIDIM, IDIM, NALF, ALF, NBET, BET, NMAX, $ A, AA, AS, B, BB, BS, C, CC, CS, CT, G ) * * Tests CGEMM. * * Auxiliary routine for test program for Level 3 Blas. * * -- Written on 8-February-1989. * Jack Dongarra, Argonne National Laboratory. * Iain Duff, AERE Harwell. * Jeremy Du Croz, Numerical Algorithms Group Ltd. * Sven Hammarling, Numerical Algorithms Group Ltd. * * .. Parameters .. COMPLEX ZERO PARAMETER ( ZERO = ( 0.0, 0.0 ) ) REAL RZERO PARAMETER ( RZERO = 0.0 ) * .. Scalar Arguments .. REAL EPS, THRESH INTEGER NALF, NBET, NIDIM, NMAX, NOUT, NTRA LOGICAL FATAL, REWI, TRACE CHARACTER*6 SNAME * .. Array Arguments .. COMPLEX A( NMAX, NMAX ), AA( NMAX*NMAX ), ALF( NALF ), $ AS( NMAX*NMAX ), B( NMAX, NMAX ), $ BB( NMAX*NMAX ), BET( NBET ), BS( NMAX*NMAX ), $ C( NMAX, NMAX ), CC( NMAX*NMAX ), $ CS( NMAX*NMAX ), CT( NMAX ) REAL G( NMAX ) INTEGER IDIM( NIDIM ) * .. Local Scalars .. COMPLEX ALPHA, ALS, BETA, BLS REAL ERR, ERRMAX INTEGER I, IA, IB, ICA, ICB, IK, IM, IN, K, KS, LAA, $ LBB, LCC, LDA, LDAS, LDB, LDBS, LDC, LDCS, M, $ MA, MB, MS, N, NA, NARGS, NB, NC, NS LOGICAL NULL, RESET, SAME, TRANA, TRANB CHARACTER*1 TRANAS, TRANBS, TRANSA, TRANSB CHARACTER*3 ICH * .. Local Arrays .. LOGICAL ISAME( 13 ) * .. External Functions .. LOGICAL LCE, LCERES EXTERNAL LCE, LCERES * .. External Subroutines .. EXTERNAL CGEMM, CMAKE, CMMCH * .. Intrinsic Functions .. INTRINSIC MAX * .. Scalars in Common .. INTEGER INFOT, NOUTC LOGICAL LERR, OK * .. Common blocks .. COMMON /INFOC/INFOT, NOUTC, OK, LERR * .. Data statements .. DATA ICH/'NTC'/ * .. Executable Statements .. * NARGS = 13 NC = 0 RESET = .TRUE. ERRMAX = RZERO * DO 110 IM = 1, NIDIM M = IDIM( IM ) * DO 100 IN = 1, NIDIM N = IDIM( IN ) * Set LDC to 1 more than minimum value if room. LDC = M IF( LDC.LT.NMAX ) $ LDC = LDC + 1 * Skip tests if not enough room. IF( LDC.GT.NMAX ) $ GO TO 100 LCC = LDC*N NULL = N.LE.0.OR.M.LE.0 * DO 90 IK = 1, NIDIM K = IDIM( IK ) * DO 80 ICA = 1, 3 TRANSA = ICH( ICA: ICA ) TRANA = TRANSA.EQ.'T'.OR.TRANSA.EQ.'C' * IF( TRANA )THEN MA = K NA = M ELSE MA = M NA = K END IF * Set LDA to 1 more than minimum value if room. LDA = MA IF( LDA.LT.NMAX ) $ LDA = LDA + 1 * Skip tests if not enough room. IF( LDA.GT.NMAX ) $ GO TO 80 LAA = LDA*NA * * Generate the matrix A. * CALL CMAKE( 'GE', ' ', ' ', MA, NA, A, NMAX, AA, LDA, $ RESET, ZERO ) * DO 70 ICB = 1, 3 TRANSB = ICH( ICB: ICB ) TRANB = TRANSB.EQ.'T'.OR.TRANSB.EQ.'C' * IF( TRANB )THEN MB = N NB = K ELSE MB = K NB = N END IF * Set LDB to 1 more than minimum value if room. LDB = MB IF( LDB.LT.NMAX ) $ LDB = LDB + 1 * Skip tests if not enough room. IF( LDB.GT.NMAX ) $ GO TO 70 LBB = LDB*NB * * Generate the matrix B. * CALL CMAKE( 'GE', ' ', ' ', MB, NB, B, NMAX, BB, $ LDB, RESET, ZERO ) * DO 60 IA = 1, NALF ALPHA = ALF( IA ) * DO 50 IB = 1, NBET BETA = BET( IB ) * * Generate the matrix C. * CALL CMAKE( 'GE', ' ', ' ', M, N, C, NMAX, $ CC, LDC, RESET, ZERO ) * NC = NC + 1 * * Save every datum before calling the * subroutine. * TRANAS = TRANSA TRANBS = TRANSB MS = M NS = N KS = K ALS = ALPHA DO 10 I = 1, LAA AS( I ) = AA( I ) 10 CONTINUE LDAS = LDA DO 20 I = 1, LBB BS( I ) = BB( I ) 20 CONTINUE LDBS = LDB BLS = BETA DO 30 I = 1, LCC CS( I ) = CC( I ) 30 CONTINUE LDCS = LDC * * Call the subroutine. * IF( TRACE ) $ WRITE( NTRA, FMT = 9995 )NC, SNAME, $ TRANSA, TRANSB, M, N, K, ALPHA, LDA, LDB, $ BETA, LDC IF( REWI ) $ REWIND NTRA CALL CGEMM( TRANSA, TRANSB, M, N, K, ALPHA, $ AA, LDA, BB, LDB, BETA, CC, LDC ) * * Check if error-exit was taken incorrectly. * IF( .NOT.OK )THEN WRITE( NOUT, FMT = 9994 ) FATAL = .TRUE. GO TO 120 END IF * * See what data changed inside subroutines. * ISAME( 1 ) = TRANSA.EQ.TRANAS ISAME( 2 ) = TRANSB.EQ.TRANBS ISAME( 3 ) = MS.EQ.M ISAME( 4 ) = NS.EQ.N ISAME( 5 ) = KS.EQ.K ISAME( 6 ) = ALS.EQ.ALPHA ISAME( 7 ) = LCE( AS, AA, LAA ) ISAME( 8 ) = LDAS.EQ.LDA ISAME( 9 ) = LCE( BS, BB, LBB ) ISAME( 10 ) = LDBS.EQ.LDB ISAME( 11 ) = BLS.EQ.BETA IF( NULL )THEN ISAME( 12 ) = LCE( CS, CC, LCC ) ELSE ISAME( 12 ) = LCERES( 'GE', ' ', M, N, CS, $ CC, LDC ) END IF ISAME( 13 ) = LDCS.EQ.LDC * * If data was incorrectly changed, report * and return. * SAME = .TRUE. DO 40 I = 1, NARGS SAME = SAME.AND.ISAME( I ) IF( .NOT.ISAME( I ) ) $ WRITE( NOUT, FMT = 9998 )I 40 CONTINUE IF( .NOT.SAME )THEN FATAL = .TRUE. GO TO 120 END IF * IF( .NOT.NULL )THEN * * Check the result. * CALL CMMCH( TRANSA, TRANSB, M, N, K, $ ALPHA, A, NMAX, B, NMAX, BETA, $ C, NMAX, CT, G, CC, LDC, EPS, $ ERR, FATAL, NOUT, .TRUE. ) ERRMAX = MAX( ERRMAX, ERR ) * If got really bad answer, report and * return. IF( FATAL ) $ GO TO 120 END IF * 50 CONTINUE * 60 CONTINUE * 70 CONTINUE * 80 CONTINUE * 90 CONTINUE * 100 CONTINUE * 110 CONTINUE * * Report result. * IF( ERRMAX.LT.THRESH )THEN WRITE( NOUT, FMT = 9999 )SNAME, NC ELSE WRITE( NOUT, FMT = 9997 )SNAME, NC, ERRMAX END IF GO TO 130 * 120 CONTINUE WRITE( NOUT, FMT = 9996 )SNAME WRITE( NOUT, FMT = 9995 )NC, SNAME, TRANSA, TRANSB, M, N, K, $ ALPHA, LDA, LDB, BETA, LDC * 130 CONTINUE RETURN * 9999 FORMAT( ' ', A6, ' PASSED THE COMPUTATIONAL TESTS (', I6, ' CALL', $ 'S)' ) 9998 FORMAT( ' ******* FATAL ERROR - PARAMETER NUMBER ', I2, ' WAS CH', $ 'ANGED INCORRECTLY *******' ) 9997 FORMAT( ' ', A6, ' COMPLETED THE COMPUTATIONAL TESTS (', I6, ' C', $ 'ALLS)', /' ******* BUT WITH MAXIMUM TEST RATIO', F8.2, $ ' - SUSPECT *******' ) 9996 FORMAT( ' ******* ', A6, ' FAILED ON CALL NUMBER:' ) 9995 FORMAT( 1X, I6, ': ', A6, '(''', A1, ''',''', A1, ''',', $ 3( I3, ',' ), '(', F4.1, ',', F4.1, '), A,', I3, ', B,', I3, $ ',(', F4.1, ',', F4.1, '), C,', I3, ').' ) 9994 FORMAT( ' ******* FATAL ERROR - ERROR-EXIT TAKEN ON VALID CALL *', $ '******' ) * * End of CCHK1. * END SUBROUTINE CCHK2( SNAME, EPS, THRESH, NOUT, NTRA, TRACE, REWI, $ FATAL, NIDIM, IDIM, NALF, ALF, NBET, BET, NMAX, $ A, AA, AS, B, BB, BS, C, CC, CS, CT, G ) * * Tests CHEMM and CSYMM. * * Auxiliary routine for test program for Level 3 Blas. * * -- Written on 8-February-1989. * Jack Dongarra, Argonne National Laboratory. * Iain Duff, AERE Harwell. * Jeremy Du Croz, Numerical Algorithms Group Ltd. * Sven Hammarling, Numerical Algorithms Group Ltd. * * .. Parameters .. COMPLEX ZERO PARAMETER ( ZERO = ( 0.0, 0.0 ) ) REAL RZERO PARAMETER ( RZERO = 0.0 ) * .. Scalar Arguments .. REAL EPS, THRESH INTEGER NALF, NBET, NIDIM, NMAX, NOUT, NTRA LOGICAL FATAL, REWI, TRACE CHARACTER*6 SNAME * .. Array Arguments .. COMPLEX A( NMAX, NMAX ), AA( NMAX*NMAX ), ALF( NALF ), $ AS( NMAX*NMAX ), B( NMAX, NMAX ), $ BB( NMAX*NMAX ), BET( NBET ), BS( NMAX*NMAX ), $ C( NMAX, NMAX ), CC( NMAX*NMAX ), $ CS( NMAX*NMAX ), CT( NMAX ) REAL G( NMAX ) INTEGER IDIM( NIDIM ) * .. Local Scalars .. COMPLEX ALPHA, ALS, BETA, BLS REAL ERR, ERRMAX INTEGER I, IA, IB, ICS, ICU, IM, IN, LAA, LBB, LCC, $ LDA, LDAS, LDB, LDBS, LDC, LDCS, M, MS, N, NA, $ NARGS, NC, NS LOGICAL CONJ, LEFT, NULL, RESET, SAME CHARACTER*1 SIDE, SIDES, UPLO, UPLOS CHARACTER*2 ICHS, ICHU * .. Local Arrays .. LOGICAL ISAME( 13 ) * .. External Functions .. LOGICAL LCE, LCERES EXTERNAL LCE, LCERES * .. External Subroutines .. EXTERNAL CHEMM, CMAKE, CMMCH, CSYMM * .. Intrinsic Functions .. INTRINSIC MAX * .. Scalars in Common .. INTEGER INFOT, NOUTC LOGICAL LERR, OK * .. Common blocks .. COMMON /INFOC/INFOT, NOUTC, OK, LERR * .. Data statements .. DATA ICHS/'LR'/, ICHU/'UL'/ * .. Executable Statements .. CONJ = SNAME( 2: 3 ).EQ.'HE' * NARGS = 12 NC = 0 RESET = .TRUE. ERRMAX = RZERO * DO 100 IM = 1, NIDIM M = IDIM( IM ) * DO 90 IN = 1, NIDIM N = IDIM( IN ) * Set LDC to 1 more than minimum value if room. LDC = M IF( LDC.LT.NMAX ) $ LDC = LDC + 1 * Skip tests if not enough room. IF( LDC.GT.NMAX ) $ GO TO 90 LCC = LDC*N NULL = N.LE.0.OR.M.LE.0 * Set LDB to 1 more than minimum value if room. LDB = M IF( LDB.LT.NMAX ) $ LDB = LDB + 1 * Skip tests if not enough room. IF( LDB.GT.NMAX ) $ GO TO 90 LBB = LDB*N * * Generate the matrix B. * CALL CMAKE( 'GE', ' ', ' ', M, N, B, NMAX, BB, LDB, RESET, $ ZERO ) * DO 80 ICS = 1, 2 SIDE = ICHS( ICS: ICS ) LEFT = SIDE.EQ.'L' * IF( LEFT )THEN NA = M ELSE NA = N END IF * Set LDA to 1 more than minimum value if room. LDA = NA IF( LDA.LT.NMAX ) $ LDA = LDA + 1 * Skip tests if not enough room. IF( LDA.GT.NMAX ) $ GO TO 80 LAA = LDA*NA * DO 70 ICU = 1, 2 UPLO = ICHU( ICU: ICU ) * * Generate the hermitian or symmetric matrix A. * CALL CMAKE( SNAME( 2: 3 ), UPLO, ' ', NA, NA, A, NMAX, $ AA, LDA, RESET, ZERO ) * DO 60 IA = 1, NALF ALPHA = ALF( IA ) * DO 50 IB = 1, NBET BETA = BET( IB ) * * Generate the matrix C. * CALL CMAKE( 'GE', ' ', ' ', M, N, C, NMAX, CC, $ LDC, RESET, ZERO ) * NC = NC + 1 * * Save every datum before calling the * subroutine. * SIDES = SIDE UPLOS = UPLO MS = M NS = N ALS = ALPHA DO 10 I = 1, LAA AS( I ) = AA( I ) 10 CONTINUE LDAS = LDA DO 20 I = 1, LBB BS( I ) = BB( I ) 20 CONTINUE LDBS = LDB BLS = BETA DO 30 I = 1, LCC CS( I ) = CC( I ) 30 CONTINUE LDCS = LDC * * Call the subroutine. * IF( TRACE ) $ WRITE( NTRA, FMT = 9995 )NC, SNAME, SIDE, $ UPLO, M, N, ALPHA, LDA, LDB, BETA, LDC IF( REWI ) $ REWIND NTRA IF( CONJ )THEN CALL CHEMM( SIDE, UPLO, M, N, ALPHA, AA, LDA, $ BB, LDB, BETA, CC, LDC ) ELSE CALL CSYMM( SIDE, UPLO, M, N, ALPHA, AA, LDA, $ BB, LDB, BETA, CC, LDC ) END IF * * Check if error-exit was taken incorrectly. * IF( .NOT.OK )THEN WRITE( NOUT, FMT = 9994 ) FATAL = .TRUE. GO TO 110 END IF * * See what data changed inside subroutines. * ISAME( 1 ) = SIDES.EQ.SIDE ISAME( 2 ) = UPLOS.EQ.UPLO ISAME( 3 ) = MS.EQ.M ISAME( 4 ) = NS.EQ.N ISAME( 5 ) = ALS.EQ.ALPHA ISAME( 6 ) = LCE( AS, AA, LAA ) ISAME( 7 ) = LDAS.EQ.LDA ISAME( 8 ) = LCE( BS, BB, LBB ) ISAME( 9 ) = LDBS.EQ.LDB ISAME( 10 ) = BLS.EQ.BETA IF( NULL )THEN ISAME( 11 ) = LCE( CS, CC, LCC ) ELSE ISAME( 11 ) = LCERES( 'GE', ' ', M, N, CS, $ CC, LDC ) END IF ISAME( 12 ) = LDCS.EQ.LDC * * If data was incorrectly changed, report and * return. * SAME = .TRUE. DO 40 I = 1, NARGS SAME = SAME.AND.ISAME( I ) IF( .NOT.ISAME( I ) ) $ WRITE( NOUT, FMT = 9998 )I 40 CONTINUE IF( .NOT.SAME )THEN FATAL = .TRUE. GO TO 110 END IF * IF( .NOT.NULL )THEN * * Check the result. * IF( LEFT )THEN CALL CMMCH( 'N', 'N', M, N, M, ALPHA, A, $ NMAX, B, NMAX, BETA, C, NMAX, $ CT, G, CC, LDC, EPS, ERR, $ FATAL, NOUT, .TRUE. ) ELSE CALL CMMCH( 'N', 'N', M, N, N, ALPHA, B, $ NMAX, A, NMAX, BETA, C, NMAX, $ CT, G, CC, LDC, EPS, ERR, $ FATAL, NOUT, .TRUE. ) END IF ERRMAX = MAX( ERRMAX, ERR ) * If got really bad answer, report and * return. IF( FATAL ) $ GO TO 110 END IF * 50 CONTINUE * 60 CONTINUE * 70 CONTINUE * 80 CONTINUE * 90 CONTINUE * 100 CONTINUE * * Report result. * IF( ERRMAX.LT.THRESH )THEN WRITE( NOUT, FMT = 9999 )SNAME, NC ELSE WRITE( NOUT, FMT = 9997 )SNAME, NC, ERRMAX END IF GO TO 120 * 110 CONTINUE WRITE( NOUT, FMT = 9996 )SNAME WRITE( NOUT, FMT = 9995 )NC, SNAME, SIDE, UPLO, M, N, ALPHA, LDA, $ LDB, BETA, LDC * 120 CONTINUE RETURN * 9999 FORMAT( ' ', A6, ' PASSED THE COMPUTATIONAL TESTS (', I6, ' CALL', $ 'S)' ) 9998 FORMAT( ' ******* FATAL ERROR - PARAMETER NUMBER ', I2, ' WAS CH', $ 'ANGED INCORRECTLY *******' ) 9997 FORMAT( ' ', A6, ' COMPLETED THE COMPUTATIONAL TESTS (', I6, ' C', $ 'ALLS)', /' ******* BUT WITH MAXIMUM TEST RATIO', F8.2, $ ' - SUSPECT *******' ) 9996 FORMAT( ' ******* ', A6, ' FAILED ON CALL NUMBER:' ) 9995 FORMAT( 1X, I6, ': ', A6, '(', 2( '''', A1, ''',' ), 2( I3, ',' ), $ '(', F4.1, ',', F4.1, '), A,', I3, ', B,', I3, ',(', F4.1, $ ',', F4.1, '), C,', I3, ') .' ) 9994 FORMAT( ' ******* FATAL ERROR - ERROR-EXIT TAKEN ON VALID CALL *', $ '******' ) * * End of CCHK2. * END SUBROUTINE CCHK3( SNAME, EPS, THRESH, NOUT, NTRA, TRACE, REWI, $ FATAL, NIDIM, IDIM, NALF, ALF, NMAX, A, AA, AS, $ B, BB, BS, CT, G, C ) * * Tests CTRMM and CTRSM. * * Auxiliary routine for test program for Level 3 Blas. * * -- Written on 8-February-1989. * Jack Dongarra, Argonne National Laboratory. * Iain Duff, AERE Harwell. * Jeremy Du Croz, Numerical Algorithms Group Ltd. * Sven Hammarling, Numerical Algorithms Group Ltd. * * .. Parameters .. COMPLEX ZERO, ONE PARAMETER ( ZERO = ( 0.0, 0.0 ), ONE = ( 1.0, 0.0 ) ) REAL RZERO PARAMETER ( RZERO = 0.0 ) * .. Scalar Arguments .. REAL EPS, THRESH INTEGER NALF, NIDIM, NMAX, NOUT, NTRA LOGICAL FATAL, REWI, TRACE CHARACTER*6 SNAME * .. Array Arguments .. COMPLEX A( NMAX, NMAX ), AA( NMAX*NMAX ), ALF( NALF ), $ AS( NMAX*NMAX ), B( NMAX, NMAX ), $ BB( NMAX*NMAX ), BS( NMAX*NMAX ), $ C( NMAX, NMAX ), CT( NMAX ) REAL G( NMAX ) INTEGER IDIM( NIDIM ) * .. Local Scalars .. COMPLEX ALPHA, ALS REAL ERR, ERRMAX INTEGER I, IA, ICD, ICS, ICT, ICU, IM, IN, J, LAA, LBB, $ LDA, LDAS, LDB, LDBS, M, MS, N, NA, NARGS, NC, $ NS LOGICAL LEFT, NULL, RESET, SAME CHARACTER*1 DIAG, DIAGS, SIDE, SIDES, TRANAS, TRANSA, UPLO, $ UPLOS CHARACTER*2 ICHD, ICHS, ICHU CHARACTER*3 ICHT * .. Local Arrays .. LOGICAL ISAME( 13 ) * .. External Functions .. LOGICAL LCE, LCERES EXTERNAL LCE, LCERES * .. External Subroutines .. EXTERNAL CMAKE, CMMCH, CTRMM, CTRSM * .. Intrinsic Functions .. INTRINSIC MAX * .. Scalars in Common .. INTEGER INFOT, NOUTC LOGICAL LERR, OK * .. Common blocks .. COMMON /INFOC/INFOT, NOUTC, OK, LERR * .. Data statements .. DATA ICHU/'UL'/, ICHT/'NTC'/, ICHD/'UN'/, ICHS/'LR'/ * .. Executable Statements .. * NARGS = 11 NC = 0 RESET = .TRUE. ERRMAX = RZERO * Set up zero matrix for CMMCH. DO 20 J = 1, NMAX DO 10 I = 1, NMAX C( I, J ) = ZERO 10 CONTINUE 20 CONTINUE * DO 140 IM = 1, NIDIM M = IDIM( IM ) * DO 130 IN = 1, NIDIM N = IDIM( IN ) * Set LDB to 1 more than minimum value if room. LDB = M IF( LDB.LT.NMAX ) $ LDB = LDB + 1 * Skip tests if not enough room. IF( LDB.GT.NMAX ) $ GO TO 130 LBB = LDB*N NULL = M.LE.0.OR.N.LE.0 * DO 120 ICS = 1, 2 SIDE = ICHS( ICS: ICS ) LEFT = SIDE.EQ.'L' IF( LEFT )THEN NA = M ELSE NA = N END IF * Set LDA to 1 more than minimum value if room. LDA = NA IF( LDA.LT.NMAX ) $ LDA = LDA + 1 * Skip tests if not enough room. IF( LDA.GT.NMAX ) $ GO TO 130 LAA = LDA*NA * DO 110 ICU = 1, 2 UPLO = ICHU( ICU: ICU ) * DO 100 ICT = 1, 3 TRANSA = ICHT( ICT: ICT ) * DO 90 ICD = 1, 2 DIAG = ICHD( ICD: ICD ) * DO 80 IA = 1, NALF ALPHA = ALF( IA ) * * Generate the matrix A. * CALL CMAKE( 'TR', UPLO, DIAG, NA, NA, A, $ NMAX, AA, LDA, RESET, ZERO ) * * Generate the matrix B. * CALL CMAKE( 'GE', ' ', ' ', M, N, B, NMAX, $ BB, LDB, RESET, ZERO ) * NC = NC + 1 * * Save every datum before calling the * subroutine. * SIDES = SIDE UPLOS = UPLO TRANAS = TRANSA DIAGS = DIAG MS = M NS = N ALS = ALPHA DO 30 I = 1, LAA AS( I ) = AA( I ) 30 CONTINUE LDAS = LDA DO 40 I = 1, LBB BS( I ) = BB( I ) 40 CONTINUE LDBS = LDB * * Call the subroutine. * IF( SNAME( 4: 5 ).EQ.'MM' )THEN IF( TRACE ) $ WRITE( NTRA, FMT = 9995 )NC, SNAME, $ SIDE, UPLO, TRANSA, DIAG, M, N, ALPHA, $ LDA, LDB IF( REWI ) $ REWIND NTRA CALL CTRMM( SIDE, UPLO, TRANSA, DIAG, M, $ N, ALPHA, AA, LDA, BB, LDB ) ELSE IF( SNAME( 4: 5 ).EQ.'SM' )THEN IF( TRACE ) $ WRITE( NTRA, FMT = 9995 )NC, SNAME, $ SIDE, UPLO, TRANSA, DIAG, M, N, ALPHA, $ LDA, LDB IF( REWI ) $ REWIND NTRA CALL CTRSM( SIDE, UPLO, TRANSA, DIAG, M, $ N, ALPHA, AA, LDA, BB, LDB ) END IF * * Check if error-exit was taken incorrectly. * IF( .NOT.OK )THEN WRITE( NOUT, FMT = 9994 ) FATAL = .TRUE. GO TO 150 END IF * * See what data changed inside subroutines. * ISAME( 1 ) = SIDES.EQ.SIDE ISAME( 2 ) = UPLOS.EQ.UPLO ISAME( 3 ) = TRANAS.EQ.TRANSA ISAME( 4 ) = DIAGS.EQ.DIAG ISAME( 5 ) = MS.EQ.M ISAME( 6 ) = NS.EQ.N ISAME( 7 ) = ALS.EQ.ALPHA ISAME( 8 ) = LCE( AS, AA, LAA ) ISAME( 9 ) = LDAS.EQ.LDA IF( NULL )THEN ISAME( 10 ) = LCE( BS, BB, LBB ) ELSE ISAME( 10 ) = LCERES( 'GE', ' ', M, N, BS, $ BB, LDB ) END IF ISAME( 11 ) = LDBS.EQ.LDB * * If data was incorrectly changed, report and * return. * SAME = .TRUE. DO 50 I = 1, NARGS SAME = SAME.AND.ISAME( I ) IF( .NOT.ISAME( I ) ) $ WRITE( NOUT, FMT = 9998 )I 50 CONTINUE IF( .NOT.SAME )THEN FATAL = .TRUE. GO TO 150 END IF * IF( .NOT.NULL )THEN IF( SNAME( 4: 5 ).EQ.'MM' )THEN * * Check the result. * IF( LEFT )THEN CALL CMMCH( TRANSA, 'N', M, N, M, $ ALPHA, A, NMAX, B, NMAX, $ ZERO, C, NMAX, CT, G, $ BB, LDB, EPS, ERR, $ FATAL, NOUT, .TRUE. ) ELSE CALL CMMCH( 'N', TRANSA, M, N, N, $ ALPHA, B, NMAX, A, NMAX, $ ZERO, C, NMAX, CT, G, $ BB, LDB, EPS, ERR, $ FATAL, NOUT, .TRUE. ) END IF ELSE IF( SNAME( 4: 5 ).EQ.'SM' )THEN * * Compute approximation to original * matrix. * DO 70 J = 1, N DO 60 I = 1, M C( I, J ) = BB( I + ( J - 1 )* $ LDB ) BB( I + ( J - 1 )*LDB ) = ALPHA* $ B( I, J ) 60 CONTINUE 70 CONTINUE * IF( LEFT )THEN CALL CMMCH( TRANSA, 'N', M, N, M, $ ONE, A, NMAX, C, NMAX, $ ZERO, B, NMAX, CT, G, $ BB, LDB, EPS, ERR, $ FATAL, NOUT, .FALSE. ) ELSE CALL CMMCH( 'N', TRANSA, M, N, N, $ ONE, C, NMAX, A, NMAX, $ ZERO, B, NMAX, CT, G, $ BB, LDB, EPS, ERR, $ FATAL, NOUT, .FALSE. ) END IF END IF ERRMAX = MAX( ERRMAX, ERR ) * If got really bad answer, report and * return. IF( FATAL ) $ GO TO 150 END IF * 80 CONTINUE * 90 CONTINUE * 100 CONTINUE * 110 CONTINUE * 120 CONTINUE * 130 CONTINUE * 140 CONTINUE * * Report result. * IF( ERRMAX.LT.THRESH )THEN WRITE( NOUT, FMT = 9999 )SNAME, NC ELSE WRITE( NOUT, FMT = 9997 )SNAME, NC, ERRMAX END IF GO TO 160 * 150 CONTINUE WRITE( NOUT, FMT = 9996 )SNAME WRITE( NOUT, FMT = 9995 )NC, SNAME, SIDE, UPLO, TRANSA, DIAG, M, $ N, ALPHA, LDA, LDB * 160 CONTINUE RETURN * 9999 FORMAT( ' ', A6, ' PASSED THE COMPUTATIONAL TESTS (', I6, ' CALL', $ 'S)' ) 9998 FORMAT( ' ******* FATAL ERROR - PARAMETER NUMBER ', I2, ' WAS CH', $ 'ANGED INCORRECTLY *******' ) 9997 FORMAT( ' ', A6, ' COMPLETED THE COMPUTATIONAL TESTS (', I6, ' C', $ 'ALLS)', /' ******* BUT WITH MAXIMUM TEST RATIO', F8.2, $ ' - SUSPECT *******' ) 9996 FORMAT( ' ******* ', A6, ' FAILED ON CALL NUMBER:' ) 9995 FORMAT( 1X, I6, ': ', A6, '(', 4( '''', A1, ''',' ), 2( I3, ',' ), $ '(', F4.1, ',', F4.1, '), A,', I3, ', B,', I3, ') ', $ ' .' ) 9994 FORMAT( ' ******* FATAL ERROR - ERROR-EXIT TAKEN ON VALID CALL *', $ '******' ) * * End of CCHK3. * END SUBROUTINE CCHK4( SNAME, EPS, THRESH, NOUT, NTRA, TRACE, REWI, $ FATAL, NIDIM, IDIM, NALF, ALF, NBET, BET, NMAX, $ A, AA, AS, B, BB, BS, C, CC, CS, CT, G ) * * Tests CHERK and CSYRK. * * Auxiliary routine for test program for Level 3 Blas. * * -- Written on 8-February-1989. * Jack Dongarra, Argonne National Laboratory. * Iain Duff, AERE Harwell. * Jeremy Du Croz, Numerical Algorithms Group Ltd. * Sven Hammarling, Numerical Algorithms Group Ltd. * * .. Parameters .. COMPLEX ZERO PARAMETER ( ZERO = ( 0.0, 0.0 ) ) REAL RONE, RZERO PARAMETER ( RONE = 1.0, RZERO = 0.0 ) * .. Scalar Arguments .. REAL EPS, THRESH INTEGER NALF, NBET, NIDIM, NMAX, NOUT, NTRA LOGICAL FATAL, REWI, TRACE CHARACTER*6 SNAME * .. Array Arguments .. COMPLEX A( NMAX, NMAX ), AA( NMAX*NMAX ), ALF( NALF ), $ AS( NMAX*NMAX ), B( NMAX, NMAX ), $ BB( NMAX*NMAX ), BET( NBET ), BS( NMAX*NMAX ), $ C( NMAX, NMAX ), CC( NMAX*NMAX ), $ CS( NMAX*NMAX ), CT( NMAX ) REAL G( NMAX ) INTEGER IDIM( NIDIM ) * .. Local Scalars .. COMPLEX ALPHA, ALS, BETA, BETS REAL ERR, ERRMAX, RALPHA, RALS, RBETA, RBETS INTEGER I, IA, IB, ICT, ICU, IK, IN, J, JC, JJ, K, KS, $ LAA, LCC, LDA, LDAS, LDC, LDCS, LJ, MA, N, NA, $ NARGS, NC, NS LOGICAL CONJ, NULL, RESET, SAME, TRAN, UPPER CHARACTER*1 TRANS, TRANSS, TRANST, UPLO, UPLOS CHARACTER*2 ICHT, ICHU * .. Local Arrays .. LOGICAL ISAME( 13 ) * .. External Functions .. LOGICAL LCE, LCERES EXTERNAL LCE, LCERES * .. External Subroutines .. EXTERNAL CHERK, CMAKE, CMMCH, CSYRK * .. Intrinsic Functions .. INTRINSIC CMPLX, MAX, REAL * .. Scalars in Common .. INTEGER INFOT, NOUTC LOGICAL LERR, OK * .. Common blocks .. COMMON /INFOC/INFOT, NOUTC, OK, LERR * .. Data statements .. DATA ICHT/'NC'/, ICHU/'UL'/ * .. Executable Statements .. CONJ = SNAME( 2: 3 ).EQ.'HE' * NARGS = 10 NC = 0 RESET = .TRUE. ERRMAX = RZERO * DO 100 IN = 1, NIDIM N = IDIM( IN ) * Set LDC to 1 more than minimum value if room. LDC = N IF( LDC.LT.NMAX ) $ LDC = LDC + 1 * Skip tests if not enough room. IF( LDC.GT.NMAX ) $ GO TO 100 LCC = LDC*N * DO 90 IK = 1, NIDIM K = IDIM( IK ) * DO 80 ICT = 1, 2 TRANS = ICHT( ICT: ICT ) TRAN = TRANS.EQ.'C' IF( TRAN.AND..NOT.CONJ ) $ TRANS = 'T' IF( TRAN )THEN MA = K NA = N ELSE MA = N NA = K END IF * Set LDA to 1 more than minimum value if room. LDA = MA IF( LDA.LT.NMAX ) $ LDA = LDA + 1 * Skip tests if not enough room. IF( LDA.GT.NMAX ) $ GO TO 80 LAA = LDA*NA * * Generate the matrix A. * CALL CMAKE( 'GE', ' ', ' ', MA, NA, A, NMAX, AA, LDA, $ RESET, ZERO ) * DO 70 ICU = 1, 2 UPLO = ICHU( ICU: ICU ) UPPER = UPLO.EQ.'U' * DO 60 IA = 1, NALF ALPHA = ALF( IA ) IF( CONJ )THEN RALPHA = REAL( ALPHA ) ALPHA = CMPLX( RALPHA, RZERO ) END IF * DO 50 IB = 1, NBET BETA = BET( IB ) IF( CONJ )THEN RBETA = REAL( BETA ) BETA = CMPLX( RBETA, RZERO ) END IF NULL = N.LE.0 IF( CONJ ) $ NULL = NULL.OR.( ( K.LE.0.OR.RALPHA.EQ. $ RZERO ).AND.RBETA.EQ.RONE ) * * Generate the matrix C. * CALL CMAKE( SNAME( 2: 3 ), UPLO, ' ', N, N, C, $ NMAX, CC, LDC, RESET, ZERO ) * NC = NC + 1 * * Save every datum before calling the subroutine. * UPLOS = UPLO TRANSS = TRANS NS = N KS = K IF( CONJ )THEN RALS = RALPHA ELSE ALS = ALPHA END IF DO 10 I = 1, LAA AS( I ) = AA( I ) 10 CONTINUE LDAS = LDA IF( CONJ )THEN RBETS = RBETA ELSE BETS = BETA END IF DO 20 I = 1, LCC CS( I ) = CC( I ) 20 CONTINUE LDCS = LDC * * Call the subroutine. * IF( CONJ )THEN IF( TRACE ) $ WRITE( NTRA, FMT = 9994 )NC, SNAME, UPLO, $ TRANS, N, K, RALPHA, LDA, RBETA, LDC IF( REWI ) $ REWIND NTRA CALL CHERK( UPLO, TRANS, N, K, RALPHA, AA, $ LDA, RBETA, CC, LDC ) ELSE IF( TRACE ) $ WRITE( NTRA, FMT = 9993 )NC, SNAME, UPLO, $ TRANS, N, K, ALPHA, LDA, BETA, LDC IF( REWI ) $ REWIND NTRA CALL CSYRK( UPLO, TRANS, N, K, ALPHA, AA, $ LDA, BETA, CC, LDC ) END IF * * Check if error-exit was taken incorrectly. * IF( .NOT.OK )THEN WRITE( NOUT, FMT = 9992 ) FATAL = .TRUE. GO TO 120 END IF * * See what data changed inside subroutines. * ISAME( 1 ) = UPLOS.EQ.UPLO ISAME( 2 ) = TRANSS.EQ.TRANS ISAME( 3 ) = NS.EQ.N ISAME( 4 ) = KS.EQ.K IF( CONJ )THEN ISAME( 5 ) = RALS.EQ.RALPHA ELSE ISAME( 5 ) = ALS.EQ.ALPHA END IF ISAME( 6 ) = LCE( AS, AA, LAA ) ISAME( 7 ) = LDAS.EQ.LDA IF( CONJ )THEN ISAME( 8 ) = RBETS.EQ.RBETA ELSE ISAME( 8 ) = BETS.EQ.BETA END IF IF( NULL )THEN ISAME( 9 ) = LCE( CS, CC, LCC ) ELSE ISAME( 9 ) = LCERES( SNAME( 2: 3 ), UPLO, N, $ N, CS, CC, LDC ) END IF ISAME( 10 ) = LDCS.EQ.LDC * * If data was incorrectly changed, report and * return. * SAME = .TRUE. DO 30 I = 1, NARGS SAME = SAME.AND.ISAME( I ) IF( .NOT.ISAME( I ) ) $ WRITE( NOUT, FMT = 9998 )I 30 CONTINUE IF( .NOT.SAME )THEN FATAL = .TRUE. GO TO 120 END IF * IF( .NOT.NULL )THEN * * Check the result column by column. * IF( CONJ )THEN TRANST = 'C' ELSE TRANST = 'T' END IF JC = 1 DO 40 J = 1, N IF( UPPER )THEN JJ = 1 LJ = J ELSE JJ = J LJ = N - J + 1 END IF IF( TRAN )THEN CALL CMMCH( TRANST, 'N', LJ, 1, K, $ ALPHA, A( 1, JJ ), NMAX, $ A( 1, J ), NMAX, BETA, $ C( JJ, J ), NMAX, CT, G, $ CC( JC ), LDC, EPS, ERR, $ FATAL, NOUT, .TRUE. ) ELSE CALL CMMCH( 'N', TRANST, LJ, 1, K, $ ALPHA, A( JJ, 1 ), NMAX, $ A( J, 1 ), NMAX, BETA, $ C( JJ, J ), NMAX, CT, G, $ CC( JC ), LDC, EPS, ERR, $ FATAL, NOUT, .TRUE. ) END IF IF( UPPER )THEN JC = JC + LDC ELSE JC = JC + LDC + 1 END IF ERRMAX = MAX( ERRMAX, ERR ) * If got really bad answer, report and * return. IF( FATAL ) $ GO TO 110 40 CONTINUE END IF * 50 CONTINUE * 60 CONTINUE * 70 CONTINUE * 80 CONTINUE * 90 CONTINUE * 100 CONTINUE * * Report result. * IF( ERRMAX.LT.THRESH )THEN WRITE( NOUT, FMT = 9999 )SNAME, NC ELSE WRITE( NOUT, FMT = 9997 )SNAME, NC, ERRMAX END IF GO TO 130 * 110 CONTINUE IF( N.GT.1 ) $ WRITE( NOUT, FMT = 9995 )J * 120 CONTINUE WRITE( NOUT, FMT = 9996 )SNAME IF( CONJ )THEN WRITE( NOUT, FMT = 9994 )NC, SNAME, UPLO, TRANS, N, K, RALPHA, $ LDA, RBETA, LDC ELSE WRITE( NOUT, FMT = 9993 )NC, SNAME, UPLO, TRANS, N, K, ALPHA, $ LDA, BETA, LDC END IF * 130 CONTINUE RETURN * 9999 FORMAT( ' ', A6, ' PASSED THE COMPUTATIONAL TESTS (', I6, ' CALL', $ 'S)' ) 9998 FORMAT( ' ******* FATAL ERROR - PARAMETER NUMBER ', I2, ' WAS CH', $ 'ANGED INCORRECTLY *******' ) 9997 FORMAT( ' ', A6, ' COMPLETED THE COMPUTATIONAL TESTS (', I6, ' C', $ 'ALLS)', /' ******* BUT WITH MAXIMUM TEST RATIO', F8.2, $ ' - SUSPECT *******' ) 9996 FORMAT( ' ******* ', A6, ' FAILED ON CALL NUMBER:' ) 9995 FORMAT( ' THESE ARE THE RESULTS FOR COLUMN ', I3 ) 9994 FORMAT( 1X, I6, ': ', A6, '(', 2( '''', A1, ''',' ), 2( I3, ',' ), $ F4.1, ', A,', I3, ',', F4.1, ', C,', I3, ') ', $ ' .' ) 9993 FORMAT( 1X, I6, ': ', A6, '(', 2( '''', A1, ''',' ), 2( I3, ',' ), $ '(', F4.1, ',', F4.1, ') , A,', I3, ',(', F4.1, ',', F4.1, $ '), C,', I3, ') .' ) 9992 FORMAT( ' ******* FATAL ERROR - ERROR-EXIT TAKEN ON VALID CALL *', $ '******' ) * * End of CCHK4. * END SUBROUTINE CCHK5( SNAME, EPS, THRESH, NOUT, NTRA, TRACE, REWI, $ FATAL, NIDIM, IDIM, NALF, ALF, NBET, BET, NMAX, $ AB, AA, AS, BB, BS, C, CC, CS, CT, G, W ) * * Tests CHER2K and CSYR2K. * * Auxiliary routine for test program for Level 3 Blas. * * -- Written on 8-February-1989. * Jack Dongarra, Argonne National Laboratory. * Iain Duff, AERE Harwell. * Jeremy Du Croz, Numerical Algorithms Group Ltd. * Sven Hammarling, Numerical Algorithms Group Ltd. * * .. Parameters .. COMPLEX ZERO, ONE PARAMETER ( ZERO = ( 0.0, 0.0 ), ONE = ( 1.0, 0.0 ) ) REAL RONE, RZERO PARAMETER ( RONE = 1.0, RZERO = 0.0 ) * .. Scalar Arguments .. REAL EPS, THRESH INTEGER NALF, NBET, NIDIM, NMAX, NOUT, NTRA LOGICAL FATAL, REWI, TRACE CHARACTER*6 SNAME * .. Array Arguments .. COMPLEX AA( NMAX*NMAX ), AB( 2*NMAX*NMAX ), $ ALF( NALF ), AS( NMAX*NMAX ), BB( NMAX*NMAX ), $ BET( NBET ), BS( NMAX*NMAX ), C( NMAX, NMAX ), $ CC( NMAX*NMAX ), CS( NMAX*NMAX ), CT( NMAX ), $ W( 2*NMAX ) REAL G( NMAX ) INTEGER IDIM( NIDIM ) * .. Local Scalars .. COMPLEX ALPHA, ALS, BETA, BETS REAL ERR, ERRMAX, RBETA, RBETS INTEGER I, IA, IB, ICT, ICU, IK, IN, J, JC, JJ, JJAB, $ K, KS, LAA, LBB, LCC, LDA, LDAS, LDB, LDBS, $ LDC, LDCS, LJ, MA, N, NA, NARGS, NC, NS LOGICAL CONJ, NULL, RESET, SAME, TRAN, UPPER CHARACTER*1 TRANS, TRANSS, TRANST, UPLO, UPLOS CHARACTER*2 ICHT, ICHU * .. Local Arrays .. LOGICAL ISAME( 13 ) * .. External Functions .. LOGICAL LCE, LCERES EXTERNAL LCE, LCERES * .. External Subroutines .. EXTERNAL CHER2K, CMAKE, CMMCH, CSYR2K * .. Intrinsic Functions .. INTRINSIC CMPLX, CONJG, MAX, REAL * .. Scalars in Common .. INTEGER INFOT, NOUTC LOGICAL LERR, OK * .. Common blocks .. COMMON /INFOC/INFOT, NOUTC, OK, LERR * .. Data statements .. DATA ICHT/'NC'/, ICHU/'UL'/ * .. Executable Statements .. CONJ = SNAME( 2: 3 ).EQ.'HE' * NARGS = 12 NC = 0 RESET = .TRUE. ERRMAX = RZERO * DO 130 IN = 1, NIDIM N = IDIM( IN ) * Set LDC to 1 more than minimum value if room. LDC = N IF( LDC.LT.NMAX ) $ LDC = LDC + 1 * Skip tests if not enough room. IF( LDC.GT.NMAX ) $ GO TO 130 LCC = LDC*N * DO 120 IK = 1, NIDIM K = IDIM( IK ) * DO 110 ICT = 1, 2 TRANS = ICHT( ICT: ICT ) TRAN = TRANS.EQ.'C' IF( TRAN.AND..NOT.CONJ ) $ TRANS = 'T' IF( TRAN )THEN MA = K NA = N ELSE MA = N NA = K END IF * Set LDA to 1 more than minimum value if room. LDA = MA IF( LDA.LT.NMAX ) $ LDA = LDA + 1 * Skip tests if not enough room. IF( LDA.GT.NMAX ) $ GO TO 110 LAA = LDA*NA * * Generate the matrix A. * IF( TRAN )THEN CALL CMAKE( 'GE', ' ', ' ', MA, NA, AB, 2*NMAX, AA, $ LDA, RESET, ZERO ) ELSE CALL CMAKE( 'GE', ' ', ' ', MA, NA, AB, NMAX, AA, LDA, $ RESET, ZERO ) END IF * * Generate the matrix B. * LDB = LDA LBB = LAA IF( TRAN )THEN CALL CMAKE( 'GE', ' ', ' ', MA, NA, AB( K + 1 ), $ 2*NMAX, BB, LDB, RESET, ZERO ) ELSE CALL CMAKE( 'GE', ' ', ' ', MA, NA, AB( K*NMAX + 1 ), $ NMAX, BB, LDB, RESET, ZERO ) END IF * DO 100 ICU = 1, 2 UPLO = ICHU( ICU: ICU ) UPPER = UPLO.EQ.'U' * DO 90 IA = 1, NALF ALPHA = ALF( IA ) * DO 80 IB = 1, NBET BETA = BET( IB ) IF( CONJ )THEN RBETA = REAL( BETA ) BETA = CMPLX( RBETA, RZERO ) END IF NULL = N.LE.0 IF( CONJ ) $ NULL = NULL.OR.( ( K.LE.0.OR.ALPHA.EQ. $ ZERO ).AND.RBETA.EQ.RONE ) * * Generate the matrix C. * CALL CMAKE( SNAME( 2: 3 ), UPLO, ' ', N, N, C, $ NMAX, CC, LDC, RESET, ZERO ) * NC = NC + 1 * * Save every datum before calling the subroutine. * UPLOS = UPLO TRANSS = TRANS NS = N KS = K ALS = ALPHA DO 10 I = 1, LAA AS( I ) = AA( I ) 10 CONTINUE LDAS = LDA DO 20 I = 1, LBB BS( I ) = BB( I ) 20 CONTINUE LDBS = LDB IF( CONJ )THEN RBETS = RBETA ELSE BETS = BETA END IF DO 30 I = 1, LCC CS( I ) = CC( I ) 30 CONTINUE LDCS = LDC * * Call the subroutine. * IF( CONJ )THEN IF( TRACE ) $ WRITE( NTRA, FMT = 9994 )NC, SNAME, UPLO, $ TRANS, N, K, ALPHA, LDA, LDB, RBETA, LDC IF( REWI ) $ REWIND NTRA CALL CHER2K( UPLO, TRANS, N, K, ALPHA, AA, $ LDA, BB, LDB, RBETA, CC, LDC ) ELSE IF( TRACE ) $ WRITE( NTRA, FMT = 9993 )NC, SNAME, UPLO, $ TRANS, N, K, ALPHA, LDA, LDB, BETA, LDC IF( REWI ) $ REWIND NTRA CALL CSYR2K( UPLO, TRANS, N, K, ALPHA, AA, $ LDA, BB, LDB, BETA, CC, LDC ) END IF * * Check if error-exit was taken incorrectly. * IF( .NOT.OK )THEN WRITE( NOUT, FMT = 9992 ) FATAL = .TRUE. GO TO 150 END IF * * See what data changed inside subroutines. * ISAME( 1 ) = UPLOS.EQ.UPLO ISAME( 2 ) = TRANSS.EQ.TRANS ISAME( 3 ) = NS.EQ.N ISAME( 4 ) = KS.EQ.K ISAME( 5 ) = ALS.EQ.ALPHA ISAME( 6 ) = LCE( AS, AA, LAA ) ISAME( 7 ) = LDAS.EQ.LDA ISAME( 8 ) = LCE( BS, BB, LBB ) ISAME( 9 ) = LDBS.EQ.LDB IF( CONJ )THEN ISAME( 10 ) = RBETS.EQ.RBETA ELSE ISAME( 10 ) = BETS.EQ.BETA END IF IF( NULL )THEN ISAME( 11 ) = LCE( CS, CC, LCC ) ELSE ISAME( 11 ) = LCERES( 'HE', UPLO, N, N, CS, $ CC, LDC ) END IF ISAME( 12 ) = LDCS.EQ.LDC * * If data was incorrectly changed, report and * return. * SAME = .TRUE. DO 40 I = 1, NARGS SAME = SAME.AND.ISAME( I ) IF( .NOT.ISAME( I ) ) $ WRITE( NOUT, FMT = 9998 )I 40 CONTINUE IF( .NOT.SAME )THEN FATAL = .TRUE. GO TO 150 END IF * IF( .NOT.NULL )THEN * * Check the result column by column. * IF( CONJ )THEN TRANST = 'C' ELSE TRANST = 'T' END IF JJAB = 1 JC = 1 DO 70 J = 1, N IF( UPPER )THEN JJ = 1 LJ = J ELSE JJ = J LJ = N - J + 1 END IF IF( TRAN )THEN DO 50 I = 1, K W( I ) = ALPHA*AB( ( J - 1 )*2* $ NMAX + K + I ) IF( CONJ )THEN W( K + I ) = CONJG( ALPHA )* $ AB( ( J - 1 )*2* $ NMAX + I ) ELSE W( K + I ) = ALPHA* $ AB( ( J - 1 )*2* $ NMAX + I ) END IF 50 CONTINUE CALL CMMCH( TRANST, 'N', LJ, 1, 2*K, $ ONE, AB( JJAB ), 2*NMAX, W, $ 2*NMAX, BETA, C( JJ, J ), $ NMAX, CT, G, CC( JC ), LDC, $ EPS, ERR, FATAL, NOUT, $ .TRUE. ) ELSE DO 60 I = 1, K IF( CONJ )THEN W( I ) = ALPHA*CONJG( AB( ( K + $ I - 1 )*NMAX + J ) ) W( K + I ) = CONJG( ALPHA* $ AB( ( I - 1 )*NMAX + $ J ) ) ELSE W( I ) = ALPHA*AB( ( K + I - 1 )* $ NMAX + J ) W( K + I ) = ALPHA* $ AB( ( I - 1 )*NMAX + $ J ) END IF 60 CONTINUE CALL CMMCH( 'N', 'N', LJ, 1, 2*K, ONE, $ AB( JJ ), NMAX, W, 2*NMAX, $ BETA, C( JJ, J ), NMAX, CT, $ G, CC( JC ), LDC, EPS, ERR, $ FATAL, NOUT, .TRUE. ) END IF IF( UPPER )THEN JC = JC + LDC ELSE JC = JC + LDC + 1 IF( TRAN ) $ JJAB = JJAB + 2*NMAX END IF ERRMAX = MAX( ERRMAX, ERR ) * If got really bad answer, report and * return. IF( FATAL ) $ GO TO 140 70 CONTINUE END IF * 80 CONTINUE * 90 CONTINUE * 100 CONTINUE * 110 CONTINUE * 120 CONTINUE * 130 CONTINUE * * Report result. * IF( ERRMAX.LT.THRESH )THEN WRITE( NOUT, FMT = 9999 )SNAME, NC ELSE WRITE( NOUT, FMT = 9997 )SNAME, NC, ERRMAX END IF GO TO 160 * 140 CONTINUE IF( N.GT.1 ) $ WRITE( NOUT, FMT = 9995 )J * 150 CONTINUE WRITE( NOUT, FMT = 9996 )SNAME IF( CONJ )THEN WRITE( NOUT, FMT = 9994 )NC, SNAME, UPLO, TRANS, N, K, ALPHA, $ LDA, LDB, RBETA, LDC ELSE WRITE( NOUT, FMT = 9993 )NC, SNAME, UPLO, TRANS, N, K, ALPHA, $ LDA, LDB, BETA, LDC END IF * 160 CONTINUE RETURN * 9999 FORMAT( ' ', A6, ' PASSED THE COMPUTATIONAL TESTS (', I6, ' CALL', $ 'S)' ) 9998 FORMAT( ' ******* FATAL ERROR - PARAMETER NUMBER ', I2, ' WAS CH', $ 'ANGED INCORRECTLY *******' ) 9997 FORMAT( ' ', A6, ' COMPLETED THE COMPUTATIONAL TESTS (', I6, ' C', $ 'ALLS)', /' ******* BUT WITH MAXIMUM TEST RATIO', F8.2, $ ' - SUSPECT *******' ) 9996 FORMAT( ' ******* ', A6, ' FAILED ON CALL NUMBER:' ) 9995 FORMAT( ' THESE ARE THE RESULTS FOR COLUMN ', I3 ) 9994 FORMAT( 1X, I6, ': ', A6, '(', 2( '''', A1, ''',' ), 2( I3, ',' ), $ '(', F4.1, ',', F4.1, '), A,', I3, ', B,', I3, ',', F4.1, $ ', C,', I3, ') .' ) 9993 FORMAT( 1X, I6, ': ', A6, '(', 2( '''', A1, ''',' ), 2( I3, ',' ), $ '(', F4.1, ',', F4.1, '), A,', I3, ', B,', I3, ',(', F4.1, $ ',', F4.1, '), C,', I3, ') .' ) 9992 FORMAT( ' ******* FATAL ERROR - ERROR-EXIT TAKEN ON VALID CALL *', $ '******' ) * * End of CCHK5. * END SUBROUTINE CCHKE( ISNUM, SRNAMT, NOUT ) * * Tests the error exits from the Level 3 Blas. * Requires a special version of the error-handling routine XERBLA. * A, B and C should not need to be defined. * * Auxiliary routine for test program for Level 3 Blas. * * -- Written on 8-February-1989. * Jack Dongarra, Argonne National Laboratory. * Iain Duff, AERE Harwell. * Jeremy Du Croz, Numerical Algorithms Group Ltd. * Sven Hammarling, Numerical Algorithms Group Ltd. * * 3-19-92: Initialize ALPHA, BETA, RALPHA, and RBETA (eca) * 3-19-92: Fix argument 12 in calls to CSYMM and CHEMM * with INFOT = 9 (eca) * * .. Scalar Arguments .. INTEGER ISNUM, NOUT CHARACTER*6 SRNAMT * .. Scalars in Common .. INTEGER INFOT, NOUTC LOGICAL LERR, OK * .. Parameters .. REAL ONE, TWO PARAMETER ( ONE = 1.0E0, TWO = 2.0E0 ) * .. Local Scalars .. COMPLEX ALPHA, BETA REAL RALPHA, RBETA * .. Local Arrays .. COMPLEX A( 2, 1 ), B( 2, 1 ), C( 2, 1 ) * .. External Subroutines .. EXTERNAL CGEMM, CHEMM, CHER2K, CHERK, CHKXER, CSYMM, $ CSYR2K, CSYRK, CTRMM, CTRSM * .. Common blocks .. COMMON /INFOC/INFOT, NOUTC, OK, LERR * .. Executable Statements .. * OK is set to .FALSE. by the special version of XERBLA or by CHKXER * if anything is wrong. OK = .TRUE. * LERR is set to .TRUE. by the special version of XERBLA each time * it is called, and is then tested and re-set by CHKXER. LERR = .FALSE. * * Initialize ALPHA, BETA, RALPHA, and RBETA. * ALPHA = CMPLX( ONE, -ONE ) BETA = CMPLX( TWO, -TWO ) RALPHA = ONE RBETA = TWO * GO TO ( 10, 20, 30, 40, 50, 60, 70, 80, $ 90 )ISNUM 10 INFOT = 1 CALL CGEMM( '/', 'N', 0, 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 1 CALL CGEMM( '/', 'C', 0, 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 1 CALL CGEMM( '/', 'T', 0, 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL CGEMM( 'N', '/', 0, 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL CGEMM( 'C', '/', 0, 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL CGEMM( 'T', '/', 0, 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL CGEMM( 'N', 'N', -1, 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL CGEMM( 'N', 'C', -1, 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL CGEMM( 'N', 'T', -1, 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL CGEMM( 'C', 'N', -1, 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL CGEMM( 'C', 'C', -1, 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL CGEMM( 'C', 'T', -1, 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL CGEMM( 'T', 'N', -1, 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL CGEMM( 'T', 'C', -1, 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL CGEMM( 'T', 'T', -1, 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL CGEMM( 'N', 'N', 0, -1, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL CGEMM( 'N', 'C', 0, -1, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL CGEMM( 'N', 'T', 0, -1, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL CGEMM( 'C', 'N', 0, -1, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL CGEMM( 'C', 'C', 0, -1, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL CGEMM( 'C', 'T', 0, -1, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL CGEMM( 'T', 'N', 0, -1, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL CGEMM( 'T', 'C', 0, -1, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL CGEMM( 'T', 'T', 0, -1, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL CGEMM( 'N', 'N', 0, 0, -1, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL CGEMM( 'N', 'C', 0, 0, -1, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL CGEMM( 'N', 'T', 0, 0, -1, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL CGEMM( 'C', 'N', 0, 0, -1, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL CGEMM( 'C', 'C', 0, 0, -1, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL CGEMM( 'C', 'T', 0, 0, -1, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL CGEMM( 'T', 'N', 0, 0, -1, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL CGEMM( 'T', 'C', 0, 0, -1, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL CGEMM( 'T', 'T', 0, 0, -1, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 8 CALL CGEMM( 'N', 'N', 2, 0, 0, ALPHA, A, 1, B, 1, BETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 8 CALL CGEMM( 'N', 'C', 2, 0, 0, ALPHA, A, 1, B, 1, BETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 8 CALL CGEMM( 'N', 'T', 2, 0, 0, ALPHA, A, 1, B, 1, BETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 8 CALL CGEMM( 'C', 'N', 0, 0, 2, ALPHA, A, 1, B, 2, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 8 CALL CGEMM( 'C', 'C', 0, 0, 2, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 8 CALL CGEMM( 'C', 'T', 0, 0, 2, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 8 CALL CGEMM( 'T', 'N', 0, 0, 2, ALPHA, A, 1, B, 2, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 8 CALL CGEMM( 'T', 'C', 0, 0, 2, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 8 CALL CGEMM( 'T', 'T', 0, 0, 2, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 10 CALL CGEMM( 'N', 'N', 0, 0, 2, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 10 CALL CGEMM( 'C', 'N', 0, 0, 2, ALPHA, A, 2, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 10 CALL CGEMM( 'T', 'N', 0, 0, 2, ALPHA, A, 2, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 10 CALL CGEMM( 'N', 'C', 0, 2, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 10 CALL CGEMM( 'C', 'C', 0, 2, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 10 CALL CGEMM( 'T', 'C', 0, 2, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 10 CALL CGEMM( 'N', 'T', 0, 2, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 10 CALL CGEMM( 'C', 'T', 0, 2, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 10 CALL CGEMM( 'T', 'T', 0, 2, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 13 CALL CGEMM( 'N', 'N', 2, 0, 0, ALPHA, A, 2, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 13 CALL CGEMM( 'N', 'C', 2, 0, 0, ALPHA, A, 2, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 13 CALL CGEMM( 'N', 'T', 2, 0, 0, ALPHA, A, 2, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 13 CALL CGEMM( 'C', 'N', 2, 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 13 CALL CGEMM( 'C', 'C', 2, 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 13 CALL CGEMM( 'C', 'T', 2, 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 13 CALL CGEMM( 'T', 'N', 2, 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 13 CALL CGEMM( 'T', 'C', 2, 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 13 CALL CGEMM( 'T', 'T', 2, 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 100 20 INFOT = 1 CALL CHEMM( '/', 'U', 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL CHEMM( 'L', '/', 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL CHEMM( 'L', 'U', -1, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL CHEMM( 'R', 'U', -1, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL CHEMM( 'L', 'L', -1, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL CHEMM( 'R', 'L', -1, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL CHEMM( 'L', 'U', 0, -1, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL CHEMM( 'R', 'U', 0, -1, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL CHEMM( 'L', 'L', 0, -1, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL CHEMM( 'R', 'L', 0, -1, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL CHEMM( 'L', 'U', 2, 0, ALPHA, A, 1, B, 2, BETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL CHEMM( 'R', 'U', 0, 2, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL CHEMM( 'L', 'L', 2, 0, ALPHA, A, 1, B, 2, BETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL CHEMM( 'R', 'L', 0, 2, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL CHEMM( 'L', 'U', 2, 0, ALPHA, A, 2, B, 1, BETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL CHEMM( 'R', 'U', 2, 0, ALPHA, A, 1, B, 1, BETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL CHEMM( 'L', 'L', 2, 0, ALPHA, A, 2, B, 1, BETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL CHEMM( 'R', 'L', 2, 0, ALPHA, A, 1, B, 1, BETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 12 CALL CHEMM( 'L', 'U', 2, 0, ALPHA, A, 2, B, 2, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 12 CALL CHEMM( 'R', 'U', 2, 0, ALPHA, A, 1, B, 2, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 12 CALL CHEMM( 'L', 'L', 2, 0, ALPHA, A, 2, B, 2, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 12 CALL CHEMM( 'R', 'L', 2, 0, ALPHA, A, 1, B, 2, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 100 30 INFOT = 1 CALL CSYMM( '/', 'U', 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL CSYMM( 'L', '/', 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL CSYMM( 'L', 'U', -1, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL CSYMM( 'R', 'U', -1, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL CSYMM( 'L', 'L', -1, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL CSYMM( 'R', 'L', -1, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL CSYMM( 'L', 'U', 0, -1, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL CSYMM( 'R', 'U', 0, -1, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL CSYMM( 'L', 'L', 0, -1, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL CSYMM( 'R', 'L', 0, -1, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL CSYMM( 'L', 'U', 2, 0, ALPHA, A, 1, B, 2, BETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL CSYMM( 'R', 'U', 0, 2, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL CSYMM( 'L', 'L', 2, 0, ALPHA, A, 1, B, 2, BETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL CSYMM( 'R', 'L', 0, 2, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL CSYMM( 'L', 'U', 2, 0, ALPHA, A, 2, B, 1, BETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL CSYMM( 'R', 'U', 2, 0, ALPHA, A, 1, B, 1, BETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL CSYMM( 'L', 'L', 2, 0, ALPHA, A, 2, B, 1, BETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL CSYMM( 'R', 'L', 2, 0, ALPHA, A, 1, B, 1, BETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 12 CALL CSYMM( 'L', 'U', 2, 0, ALPHA, A, 2, B, 2, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 12 CALL CSYMM( 'R', 'U', 2, 0, ALPHA, A, 1, B, 2, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 12 CALL CSYMM( 'L', 'L', 2, 0, ALPHA, A, 2, B, 2, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 12 CALL CSYMM( 'R', 'L', 2, 0, ALPHA, A, 1, B, 2, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 100 40 INFOT = 1 CALL CTRMM( '/', 'U', 'N', 'N', 0, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL CTRMM( 'L', '/', 'N', 'N', 0, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL CTRMM( 'L', 'U', '/', 'N', 0, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL CTRMM( 'L', 'U', 'N', '/', 0, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL CTRMM( 'L', 'U', 'N', 'N', -1, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL CTRMM( 'L', 'U', 'C', 'N', -1, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL CTRMM( 'L', 'U', 'T', 'N', -1, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL CTRMM( 'R', 'U', 'N', 'N', -1, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL CTRMM( 'R', 'U', 'C', 'N', -1, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL CTRMM( 'R', 'U', 'T', 'N', -1, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL CTRMM( 'L', 'L', 'N', 'N', -1, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL CTRMM( 'L', 'L', 'C', 'N', -1, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL CTRMM( 'L', 'L', 'T', 'N', -1, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL CTRMM( 'R', 'L', 'N', 'N', -1, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL CTRMM( 'R', 'L', 'C', 'N', -1, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL CTRMM( 'R', 'L', 'T', 'N', -1, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL CTRMM( 'L', 'U', 'N', 'N', 0, -1, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL CTRMM( 'L', 'U', 'C', 'N', 0, -1, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL CTRMM( 'L', 'U', 'T', 'N', 0, -1, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL CTRMM( 'R', 'U', 'N', 'N', 0, -1, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL CTRMM( 'R', 'U', 'C', 'N', 0, -1, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL CTRMM( 'R', 'U', 'T', 'N', 0, -1, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL CTRMM( 'L', 'L', 'N', 'N', 0, -1, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL CTRMM( 'L', 'L', 'C', 'N', 0, -1, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL CTRMM( 'L', 'L', 'T', 'N', 0, -1, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL CTRMM( 'R', 'L', 'N', 'N', 0, -1, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL CTRMM( 'R', 'L', 'C', 'N', 0, -1, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL CTRMM( 'R', 'L', 'T', 'N', 0, -1, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL CTRMM( 'L', 'U', 'N', 'N', 2, 0, ALPHA, A, 1, B, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL CTRMM( 'L', 'U', 'C', 'N', 2, 0, ALPHA, A, 1, B, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL CTRMM( 'L', 'U', 'T', 'N', 2, 0, ALPHA, A, 1, B, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL CTRMM( 'R', 'U', 'N', 'N', 0, 2, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL CTRMM( 'R', 'U', 'C', 'N', 0, 2, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL CTRMM( 'R', 'U', 'T', 'N', 0, 2, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL CTRMM( 'L', 'L', 'N', 'N', 2, 0, ALPHA, A, 1, B, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL CTRMM( 'L', 'L', 'C', 'N', 2, 0, ALPHA, A, 1, B, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL CTRMM( 'L', 'L', 'T', 'N', 2, 0, ALPHA, A, 1, B, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL CTRMM( 'R', 'L', 'N', 'N', 0, 2, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL CTRMM( 'R', 'L', 'C', 'N', 0, 2, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL CTRMM( 'R', 'L', 'T', 'N', 0, 2, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL CTRMM( 'L', 'U', 'N', 'N', 2, 0, ALPHA, A, 2, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL CTRMM( 'L', 'U', 'C', 'N', 2, 0, ALPHA, A, 2, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL CTRMM( 'L', 'U', 'T', 'N', 2, 0, ALPHA, A, 2, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL CTRMM( 'R', 'U', 'N', 'N', 2, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL CTRMM( 'R', 'U', 'C', 'N', 2, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL CTRMM( 'R', 'U', 'T', 'N', 2, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL CTRMM( 'L', 'L', 'N', 'N', 2, 0, ALPHA, A, 2, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL CTRMM( 'L', 'L', 'C', 'N', 2, 0, ALPHA, A, 2, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL CTRMM( 'L', 'L', 'T', 'N', 2, 0, ALPHA, A, 2, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL CTRMM( 'R', 'L', 'N', 'N', 2, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL CTRMM( 'R', 'L', 'C', 'N', 2, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL CTRMM( 'R', 'L', 'T', 'N', 2, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 100 50 INFOT = 1 CALL CTRSM( '/', 'U', 'N', 'N', 0, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL CTRSM( 'L', '/', 'N', 'N', 0, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL CTRSM( 'L', 'U', '/', 'N', 0, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL CTRSM( 'L', 'U', 'N', '/', 0, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL CTRSM( 'L', 'U', 'N', 'N', -1, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL CTRSM( 'L', 'U', 'C', 'N', -1, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL CTRSM( 'L', 'U', 'T', 'N', -1, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL CTRSM( 'R', 'U', 'N', 'N', -1, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL CTRSM( 'R', 'U', 'C', 'N', -1, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL CTRSM( 'R', 'U', 'T', 'N', -1, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL CTRSM( 'L', 'L', 'N', 'N', -1, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL CTRSM( 'L', 'L', 'C', 'N', -1, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL CTRSM( 'L', 'L', 'T', 'N', -1, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL CTRSM( 'R', 'L', 'N', 'N', -1, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL CTRSM( 'R', 'L', 'C', 'N', -1, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL CTRSM( 'R', 'L', 'T', 'N', -1, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL CTRSM( 'L', 'U', 'N', 'N', 0, -1, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL CTRSM( 'L', 'U', 'C', 'N', 0, -1, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL CTRSM( 'L', 'U', 'T', 'N', 0, -1, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL CTRSM( 'R', 'U', 'N', 'N', 0, -1, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL CTRSM( 'R', 'U', 'C', 'N', 0, -1, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL CTRSM( 'R', 'U', 'T', 'N', 0, -1, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL CTRSM( 'L', 'L', 'N', 'N', 0, -1, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL CTRSM( 'L', 'L', 'C', 'N', 0, -1, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL CTRSM( 'L', 'L', 'T', 'N', 0, -1, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL CTRSM( 'R', 'L', 'N', 'N', 0, -1, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL CTRSM( 'R', 'L', 'C', 'N', 0, -1, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL CTRSM( 'R', 'L', 'T', 'N', 0, -1, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL CTRSM( 'L', 'U', 'N', 'N', 2, 0, ALPHA, A, 1, B, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL CTRSM( 'L', 'U', 'C', 'N', 2, 0, ALPHA, A, 1, B, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL CTRSM( 'L', 'U', 'T', 'N', 2, 0, ALPHA, A, 1, B, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL CTRSM( 'R', 'U', 'N', 'N', 0, 2, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL CTRSM( 'R', 'U', 'C', 'N', 0, 2, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL CTRSM( 'R', 'U', 'T', 'N', 0, 2, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL CTRSM( 'L', 'L', 'N', 'N', 2, 0, ALPHA, A, 1, B, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL CTRSM( 'L', 'L', 'C', 'N', 2, 0, ALPHA, A, 1, B, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL CTRSM( 'L', 'L', 'T', 'N', 2, 0, ALPHA, A, 1, B, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL CTRSM( 'R', 'L', 'N', 'N', 0, 2, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL CTRSM( 'R', 'L', 'C', 'N', 0, 2, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL CTRSM( 'R', 'L', 'T', 'N', 0, 2, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL CTRSM( 'L', 'U', 'N', 'N', 2, 0, ALPHA, A, 2, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL CTRSM( 'L', 'U', 'C', 'N', 2, 0, ALPHA, A, 2, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL CTRSM( 'L', 'U', 'T', 'N', 2, 0, ALPHA, A, 2, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL CTRSM( 'R', 'U', 'N', 'N', 2, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL CTRSM( 'R', 'U', 'C', 'N', 2, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL CTRSM( 'R', 'U', 'T', 'N', 2, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL CTRSM( 'L', 'L', 'N', 'N', 2, 0, ALPHA, A, 2, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL CTRSM( 'L', 'L', 'C', 'N', 2, 0, ALPHA, A, 2, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL CTRSM( 'L', 'L', 'T', 'N', 2, 0, ALPHA, A, 2, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL CTRSM( 'R', 'L', 'N', 'N', 2, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL CTRSM( 'R', 'L', 'C', 'N', 2, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL CTRSM( 'R', 'L', 'T', 'N', 2, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 100 60 INFOT = 1 CALL CHERK( '/', 'N', 0, 0, RALPHA, A, 1, RBETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL CHERK( 'U', 'T', 0, 0, RALPHA, A, 1, RBETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL CHERK( 'U', 'N', -1, 0, RALPHA, A, 1, RBETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL CHERK( 'U', 'C', -1, 0, RALPHA, A, 1, RBETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL CHERK( 'L', 'N', -1, 0, RALPHA, A, 1, RBETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL CHERK( 'L', 'C', -1, 0, RALPHA, A, 1, RBETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL CHERK( 'U', 'N', 0, -1, RALPHA, A, 1, RBETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL CHERK( 'U', 'C', 0, -1, RALPHA, A, 1, RBETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL CHERK( 'L', 'N', 0, -1, RALPHA, A, 1, RBETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL CHERK( 'L', 'C', 0, -1, RALPHA, A, 1, RBETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL CHERK( 'U', 'N', 2, 0, RALPHA, A, 1, RBETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL CHERK( 'U', 'C', 0, 2, RALPHA, A, 1, RBETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL CHERK( 'L', 'N', 2, 0, RALPHA, A, 1, RBETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL CHERK( 'L', 'C', 0, 2, RALPHA, A, 1, RBETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 10 CALL CHERK( 'U', 'N', 2, 0, RALPHA, A, 2, RBETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 10 CALL CHERK( 'U', 'C', 2, 0, RALPHA, A, 1, RBETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 10 CALL CHERK( 'L', 'N', 2, 0, RALPHA, A, 2, RBETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 10 CALL CHERK( 'L', 'C', 2, 0, RALPHA, A, 1, RBETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 100 70 INFOT = 1 CALL CSYRK( '/', 'N', 0, 0, ALPHA, A, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL CSYRK( 'U', 'C', 0, 0, ALPHA, A, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL CSYRK( 'U', 'N', -1, 0, ALPHA, A, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL CSYRK( 'U', 'T', -1, 0, ALPHA, A, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL CSYRK( 'L', 'N', -1, 0, ALPHA, A, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL CSYRK( 'L', 'T', -1, 0, ALPHA, A, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL CSYRK( 'U', 'N', 0, -1, ALPHA, A, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL CSYRK( 'U', 'T', 0, -1, ALPHA, A, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL CSYRK( 'L', 'N', 0, -1, ALPHA, A, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL CSYRK( 'L', 'T', 0, -1, ALPHA, A, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL CSYRK( 'U', 'N', 2, 0, ALPHA, A, 1, BETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL CSYRK( 'U', 'T', 0, 2, ALPHA, A, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL CSYRK( 'L', 'N', 2, 0, ALPHA, A, 1, BETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL CSYRK( 'L', 'T', 0, 2, ALPHA, A, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 10 CALL CSYRK( 'U', 'N', 2, 0, ALPHA, A, 2, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 10 CALL CSYRK( 'U', 'T', 2, 0, ALPHA, A, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 10 CALL CSYRK( 'L', 'N', 2, 0, ALPHA, A, 2, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 10 CALL CSYRK( 'L', 'T', 2, 0, ALPHA, A, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 100 80 INFOT = 1 CALL CHER2K( '/', 'N', 0, 0, ALPHA, A, 1, B, 1, RBETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL CHER2K( 'U', 'T', 0, 0, ALPHA, A, 1, B, 1, RBETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL CHER2K( 'U', 'N', -1, 0, ALPHA, A, 1, B, 1, RBETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL CHER2K( 'U', 'C', -1, 0, ALPHA, A, 1, B, 1, RBETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL CHER2K( 'L', 'N', -1, 0, ALPHA, A, 1, B, 1, RBETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL CHER2K( 'L', 'C', -1, 0, ALPHA, A, 1, B, 1, RBETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL CHER2K( 'U', 'N', 0, -1, ALPHA, A, 1, B, 1, RBETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL CHER2K( 'U', 'C', 0, -1, ALPHA, A, 1, B, 1, RBETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL CHER2K( 'L', 'N', 0, -1, ALPHA, A, 1, B, 1, RBETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL CHER2K( 'L', 'C', 0, -1, ALPHA, A, 1, B, 1, RBETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL CHER2K( 'U', 'N', 2, 0, ALPHA, A, 1, B, 1, RBETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL CHER2K( 'U', 'C', 0, 2, ALPHA, A, 1, B, 1, RBETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL CHER2K( 'L', 'N', 2, 0, ALPHA, A, 1, B, 1, RBETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL CHER2K( 'L', 'C', 0, 2, ALPHA, A, 1, B, 1, RBETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL CHER2K( 'U', 'N', 2, 0, ALPHA, A, 2, B, 1, RBETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL CHER2K( 'U', 'C', 0, 2, ALPHA, A, 2, B, 1, RBETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL CHER2K( 'L', 'N', 2, 0, ALPHA, A, 2, B, 1, RBETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL CHER2K( 'L', 'C', 0, 2, ALPHA, A, 2, B, 1, RBETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 12 CALL CHER2K( 'U', 'N', 2, 0, ALPHA, A, 2, B, 2, RBETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 12 CALL CHER2K( 'U', 'C', 2, 0, ALPHA, A, 1, B, 1, RBETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 12 CALL CHER2K( 'L', 'N', 2, 0, ALPHA, A, 2, B, 2, RBETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 12 CALL CHER2K( 'L', 'C', 2, 0, ALPHA, A, 1, B, 1, RBETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 100 90 INFOT = 1 CALL CSYR2K( '/', 'N', 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL CSYR2K( 'U', 'C', 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL CSYR2K( 'U', 'N', -1, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL CSYR2K( 'U', 'T', -1, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL CSYR2K( 'L', 'N', -1, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL CSYR2K( 'L', 'T', -1, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL CSYR2K( 'U', 'N', 0, -1, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL CSYR2K( 'U', 'T', 0, -1, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL CSYR2K( 'L', 'N', 0, -1, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL CSYR2K( 'L', 'T', 0, -1, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL CSYR2K( 'U', 'N', 2, 0, ALPHA, A, 1, B, 1, BETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL CSYR2K( 'U', 'T', 0, 2, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL CSYR2K( 'L', 'N', 2, 0, ALPHA, A, 1, B, 1, BETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL CSYR2K( 'L', 'T', 0, 2, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL CSYR2K( 'U', 'N', 2, 0, ALPHA, A, 2, B, 1, BETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL CSYR2K( 'U', 'T', 0, 2, ALPHA, A, 2, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL CSYR2K( 'L', 'N', 2, 0, ALPHA, A, 2, B, 1, BETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL CSYR2K( 'L', 'T', 0, 2, ALPHA, A, 2, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 12 CALL CSYR2K( 'U', 'N', 2, 0, ALPHA, A, 2, B, 2, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 12 CALL CSYR2K( 'U', 'T', 2, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 12 CALL CSYR2K( 'L', 'N', 2, 0, ALPHA, A, 2, B, 2, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 12 CALL CSYR2K( 'L', 'T', 2, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) * 100 IF( OK )THEN WRITE( NOUT, FMT = 9999 )SRNAMT ELSE WRITE( NOUT, FMT = 9998 )SRNAMT END IF RETURN * 9999 FORMAT( ' ', A6, ' PASSED THE TESTS OF ERROR-EXITS' ) 9998 FORMAT( ' ******* ', A6, ' FAILED THE TESTS OF ERROR-EXITS *****', $ '**' ) * * End of CCHKE. * END SUBROUTINE CMAKE( TYPE, UPLO, DIAG, M, N, A, NMAX, AA, LDA, RESET, $ TRANSL ) * * Generates values for an M by N matrix A. * Stores the values in the array AA in the data structure required * by the routine, with unwanted elements set to rogue value. * * TYPE is 'GE', 'HE', 'SY' or 'TR'. * * Auxiliary routine for test program for Level 3 Blas. * * -- Written on 8-February-1989. * Jack Dongarra, Argonne National Laboratory. * Iain Duff, AERE Harwell. * Jeremy Du Croz, Numerical Algorithms Group Ltd. * Sven Hammarling, Numerical Algorithms Group Ltd. * * .. Parameters .. COMPLEX ZERO, ONE PARAMETER ( ZERO = ( 0.0, 0.0 ), ONE = ( 1.0, 0.0 ) ) COMPLEX ROGUE PARAMETER ( ROGUE = ( -1.0E10, 1.0E10 ) ) REAL RZERO PARAMETER ( RZERO = 0.0 ) REAL RROGUE PARAMETER ( RROGUE = -1.0E10 ) * .. Scalar Arguments .. COMPLEX TRANSL INTEGER LDA, M, N, NMAX LOGICAL RESET CHARACTER*1 DIAG, UPLO CHARACTER*2 TYPE * .. Array Arguments .. COMPLEX A( NMAX, * ), AA( * ) * .. Local Scalars .. INTEGER I, IBEG, IEND, J, JJ LOGICAL GEN, HER, LOWER, SYM, TRI, UNIT, UPPER * .. External Functions .. COMPLEX CBEG EXTERNAL CBEG * .. Intrinsic Functions .. INTRINSIC CMPLX, CONJG, REAL * .. Executable Statements .. GEN = TYPE.EQ.'GE' HER = TYPE.EQ.'HE' SYM = TYPE.EQ.'SY' TRI = TYPE.EQ.'TR' UPPER = ( HER.OR.SYM.OR.TRI ).AND.UPLO.EQ.'U' LOWER = ( HER.OR.SYM.OR.TRI ).AND.UPLO.EQ.'L' UNIT = TRI.AND.DIAG.EQ.'U' * * Generate data in array A. * DO 20 J = 1, N DO 10 I = 1, M IF( GEN.OR.( UPPER.AND.I.LE.J ).OR.( LOWER.AND.I.GE.J ) ) $ THEN A( I, J ) = CBEG( RESET ) + TRANSL IF( I.NE.J )THEN * Set some elements to zero IF( N.GT.3.AND.J.EQ.N/2 ) $ A( I, J ) = ZERO IF( HER )THEN A( J, I ) = CONJG( A( I, J ) ) ELSE IF( SYM )THEN A( J, I ) = A( I, J ) ELSE IF( TRI )THEN A( J, I ) = ZERO END IF END IF END IF 10 CONTINUE IF( HER ) $ A( J, J ) = CMPLX( REAL( A( J, J ) ), RZERO ) IF( TRI ) $ A( J, J ) = A( J, J ) + ONE IF( UNIT ) $ A( J, J ) = ONE 20 CONTINUE * * Store elements in array AS in data structure required by routine. * IF( TYPE.EQ.'GE' )THEN DO 50 J = 1, N DO 30 I = 1, M AA( I + ( J - 1 )*LDA ) = A( I, J ) 30 CONTINUE DO 40 I = M + 1, LDA AA( I + ( J - 1 )*LDA ) = ROGUE 40 CONTINUE 50 CONTINUE ELSE IF( TYPE.EQ.'HE'.OR.TYPE.EQ.'SY'.OR.TYPE.EQ.'TR' )THEN DO 90 J = 1, N IF( UPPER )THEN IBEG = 1 IF( UNIT )THEN IEND = J - 1 ELSE IEND = J END IF ELSE IF( UNIT )THEN IBEG = J + 1 ELSE IBEG = J END IF IEND = N END IF DO 60 I = 1, IBEG - 1 AA( I + ( J - 1 )*LDA ) = ROGUE 60 CONTINUE DO 70 I = IBEG, IEND AA( I + ( J - 1 )*LDA ) = A( I, J ) 70 CONTINUE DO 80 I = IEND + 1, LDA AA( I + ( J - 1 )*LDA ) = ROGUE 80 CONTINUE IF( HER )THEN JJ = J + ( J - 1 )*LDA AA( JJ ) = CMPLX( REAL( AA( JJ ) ), RROGUE ) END IF 90 CONTINUE END IF RETURN * * End of CMAKE. * END SUBROUTINE CMMCH( TRANSA, TRANSB, M, N, KK, ALPHA, A, LDA, B, LDB, $ BETA, C, LDC, CT, G, CC, LDCC, EPS, ERR, FATAL, $ NOUT, MV ) * * Checks the results of the computational tests. * * Auxiliary routine for test program for Level 3 Blas. * * -- Written on 8-February-1989. * Jack Dongarra, Argonne National Laboratory. * Iain Duff, AERE Harwell. * Jeremy Du Croz, Numerical Algorithms Group Ltd. * Sven Hammarling, Numerical Algorithms Group Ltd. * * .. Parameters .. COMPLEX ZERO PARAMETER ( ZERO = ( 0.0, 0.0 ) ) REAL RZERO, RONE PARAMETER ( RZERO = 0.0, RONE = 1.0 ) * .. Scalar Arguments .. COMPLEX ALPHA, BETA REAL EPS, ERR INTEGER KK, LDA, LDB, LDC, LDCC, M, N, NOUT LOGICAL FATAL, MV CHARACTER*1 TRANSA, TRANSB * .. Array Arguments .. COMPLEX A( LDA, * ), B( LDB, * ), C( LDC, * ), $ CC( LDCC, * ), CT( * ) REAL G( * ) * .. Local Scalars .. COMPLEX CL REAL ERRI INTEGER I, J, K LOGICAL CTRANA, CTRANB, TRANA, TRANB * .. Intrinsic Functions .. INTRINSIC ABS, AIMAG, CONJG, MAX, REAL, SQRT * .. Statement Functions .. REAL ABS1 * .. Statement Function definitions .. ABS1( CL ) = ABS( REAL( CL ) ) + ABS( AIMAG( CL ) ) * .. Executable Statements .. TRANA = TRANSA.EQ.'T'.OR.TRANSA.EQ.'C' TRANB = TRANSB.EQ.'T'.OR.TRANSB.EQ.'C' CTRANA = TRANSA.EQ.'C' CTRANB = TRANSB.EQ.'C' * * Compute expected result, one column at a time, in CT using data * in A, B and C. * Compute gauges in G. * DO 220 J = 1, N * DO 10 I = 1, M CT( I ) = ZERO G( I ) = RZERO 10 CONTINUE IF( .NOT.TRANA.AND..NOT.TRANB )THEN DO 30 K = 1, KK DO 20 I = 1, M CT( I ) = CT( I ) + A( I, K )*B( K, J ) G( I ) = G( I ) + ABS1( A( I, K ) )*ABS1( B( K, J ) ) 20 CONTINUE 30 CONTINUE ELSE IF( TRANA.AND..NOT.TRANB )THEN IF( CTRANA )THEN DO 50 K = 1, KK DO 40 I = 1, M CT( I ) = CT( I ) + CONJG( A( K, I ) )*B( K, J ) G( I ) = G( I ) + ABS1( A( K, I ) )* $ ABS1( B( K, J ) ) 40 CONTINUE 50 CONTINUE ELSE DO 70 K = 1, KK DO 60 I = 1, M CT( I ) = CT( I ) + A( K, I )*B( K, J ) G( I ) = G( I ) + ABS1( A( K, I ) )* $ ABS1( B( K, J ) ) 60 CONTINUE 70 CONTINUE END IF ELSE IF( .NOT.TRANA.AND.TRANB )THEN IF( CTRANB )THEN DO 90 K = 1, KK DO 80 I = 1, M CT( I ) = CT( I ) + A( I, K )*CONJG( B( J, K ) ) G( I ) = G( I ) + ABS1( A( I, K ) )* $ ABS1( B( J, K ) ) 80 CONTINUE 90 CONTINUE ELSE DO 110 K = 1, KK DO 100 I = 1, M CT( I ) = CT( I ) + A( I, K )*B( J, K ) G( I ) = G( I ) + ABS1( A( I, K ) )* $ ABS1( B( J, K ) ) 100 CONTINUE 110 CONTINUE END IF ELSE IF( TRANA.AND.TRANB )THEN IF( CTRANA )THEN IF( CTRANB )THEN DO 130 K = 1, KK DO 120 I = 1, M CT( I ) = CT( I ) + CONJG( A( K, I ) )* $ CONJG( B( J, K ) ) G( I ) = G( I ) + ABS1( A( K, I ) )* $ ABS1( B( J, K ) ) 120 CONTINUE 130 CONTINUE ELSE DO 150 K = 1, KK DO 140 I = 1, M CT( I ) = CT( I ) + CONJG( A( K, I ) )*B( J, K ) G( I ) = G( I ) + ABS1( A( K, I ) )* $ ABS1( B( J, K ) ) 140 CONTINUE 150 CONTINUE END IF ELSE IF( CTRANB )THEN DO 170 K = 1, KK DO 160 I = 1, M CT( I ) = CT( I ) + A( K, I )*CONJG( B( J, K ) ) G( I ) = G( I ) + ABS1( A( K, I ) )* $ ABS1( B( J, K ) ) 160 CONTINUE 170 CONTINUE ELSE DO 190 K = 1, KK DO 180 I = 1, M CT( I ) = CT( I ) + A( K, I )*B( J, K ) G( I ) = G( I ) + ABS1( A( K, I ) )* $ ABS1( B( J, K ) ) 180 CONTINUE 190 CONTINUE END IF END IF END IF DO 200 I = 1, M CT( I ) = ALPHA*CT( I ) + BETA*C( I, J ) G( I ) = ABS1( ALPHA )*G( I ) + $ ABS1( BETA )*ABS1( C( I, J ) ) 200 CONTINUE * * Compute the error ratio for this result. * ERR = ZERO DO 210 I = 1, M ERRI = ABS1( CT( I ) - CC( I, J ) )/EPS IF( G( I ).NE.RZERO ) $ ERRI = ERRI/G( I ) ERR = MAX( ERR, ERRI ) IF( ERR*SQRT( EPS ).GE.RONE ) $ GO TO 230 210 CONTINUE * 220 CONTINUE * * If the loop completes, all results are at least half accurate. GO TO 250 * * Report fatal error. * 230 FATAL = .TRUE. WRITE( NOUT, FMT = 9999 ) DO 240 I = 1, M IF( MV )THEN WRITE( NOUT, FMT = 9998 )I, CT( I ), CC( I, J ) ELSE WRITE( NOUT, FMT = 9998 )I, CC( I, J ), CT( I ) END IF 240 CONTINUE IF( N.GT.1 ) $ WRITE( NOUT, FMT = 9997 )J * 250 CONTINUE RETURN * 9999 FORMAT( ' ******* FATAL ERROR - COMPUTED RESULT IS LESS THAN HAL', $ 'F ACCURATE *******', /' EXPECTED RE', $ 'SULT COMPUTED RESULT' ) 9998 FORMAT( 1X, I7, 2( ' (', G15.6, ',', G15.6, ')' ) ) 9997 FORMAT( ' THESE ARE THE RESULTS FOR COLUMN ', I3 ) * * End of CMMCH. * END LOGICAL FUNCTION LCE( RI, RJ, LR ) * * Tests if two arrays are identical. * * Auxiliary routine for test program for Level 3 Blas. * * -- Written on 8-February-1989. * Jack Dongarra, Argonne National Laboratory. * Iain Duff, AERE Harwell. * Jeremy Du Croz, Numerical Algorithms Group Ltd. * Sven Hammarling, Numerical Algorithms Group Ltd. * * .. Scalar Arguments .. INTEGER LR * .. Array Arguments .. COMPLEX RI( * ), RJ( * ) * .. Local Scalars .. INTEGER I * .. Executable Statements .. DO 10 I = 1, LR IF( RI( I ).NE.RJ( I ) ) $ GO TO 20 10 CONTINUE LCE = .TRUE. GO TO 30 20 CONTINUE LCE = .FALSE. 30 RETURN * * End of LCE. * END LOGICAL FUNCTION LCERES( TYPE, UPLO, M, N, AA, AS, LDA ) * * Tests if selected elements in two arrays are equal. * * TYPE is 'GE' or 'HE' or 'SY'. * * Auxiliary routine for test program for Level 3 Blas. * * -- Written on 8-February-1989. * Jack Dongarra, Argonne National Laboratory. * Iain Duff, AERE Harwell. * Jeremy Du Croz, Numerical Algorithms Group Ltd. * Sven Hammarling, Numerical Algorithms Group Ltd. * * .. Scalar Arguments .. INTEGER LDA, M, N CHARACTER*1 UPLO CHARACTER*2 TYPE * .. Array Arguments .. COMPLEX AA( LDA, * ), AS( LDA, * ) * .. Local Scalars .. INTEGER I, IBEG, IEND, J LOGICAL UPPER * .. Executable Statements .. UPPER = UPLO.EQ.'U' IF( TYPE.EQ.'GE' )THEN DO 20 J = 1, N DO 10 I = M + 1, LDA IF( AA( I, J ).NE.AS( I, J ) ) $ GO TO 70 10 CONTINUE 20 CONTINUE ELSE IF( TYPE.EQ.'HE'.OR.TYPE.EQ.'SY' )THEN DO 50 J = 1, N IF( UPPER )THEN IBEG = 1 IEND = J ELSE IBEG = J IEND = N END IF DO 30 I = 1, IBEG - 1 IF( AA( I, J ).NE.AS( I, J ) ) $ GO TO 70 30 CONTINUE DO 40 I = IEND + 1, LDA IF( AA( I, J ).NE.AS( I, J ) ) $ GO TO 70 40 CONTINUE 50 CONTINUE END IF * LCERES = .TRUE. GO TO 80 70 CONTINUE LCERES = .FALSE. 80 RETURN * * End of LCERES. * END COMPLEX FUNCTION CBEG( RESET ) * * Generates complex numbers as pairs of random numbers uniformly * distributed between -0.5 and 0.5. * * Auxiliary routine for test program for Level 3 Blas. * * -- Written on 8-February-1989. * Jack Dongarra, Argonne National Laboratory. * Iain Duff, AERE Harwell. * Jeremy Du Croz, Numerical Algorithms Group Ltd. * Sven Hammarling, Numerical Algorithms Group Ltd. * * .. Scalar Arguments .. LOGICAL RESET * .. Local Scalars .. INTEGER I, IC, J, MI, MJ * .. Save statement .. SAVE I, IC, J, MI, MJ * .. Intrinsic Functions .. INTRINSIC CMPLX * .. Executable Statements .. IF( RESET )THEN * Initialize local variables. MI = 891 MJ = 457 I = 7 J = 7 IC = 0 RESET = .FALSE. END IF * * The sequence of values of I or J is bounded between 1 and 999. * If initial I or J = 1,2,3,6,7 or 9, the period will be 50. * If initial I or J = 4 or 8, the period will be 25. * If initial I or J = 5, the period will be 10. * IC is used to break up the period by skipping 1 value of I or J * in 6. * IC = IC + 1 10 I = I*MI J = J*MJ I = I - 1000*( I/1000 ) J = J - 1000*( J/1000 ) IF( IC.GE.5 )THEN IC = 0 GO TO 10 END IF CBEG = CMPLX( ( I - 500 )/1001.0, ( J - 500 )/1001.0 ) RETURN * * End of CBEG. * END REAL FUNCTION SDIFF( X, Y ) * * Auxiliary routine for test program for Level 3 Blas. * * -- Written on 8-February-1989. * Jack Dongarra, Argonne National Laboratory. * Iain Duff, AERE Harwell. * Jeremy Du Croz, Numerical Algorithms Group Ltd. * Sven Hammarling, Numerical Algorithms Group Ltd. * * .. Scalar Arguments .. REAL X, Y * .. Executable Statements .. SDIFF = X - Y RETURN * * End of SDIFF. * END SUBROUTINE CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) * * Tests whether XERBLA has detected an error when it should. * * Auxiliary routine for test program for Level 3 Blas. * * -- Written on 8-February-1989. * Jack Dongarra, Argonne National Laboratory. * Iain Duff, AERE Harwell. * Jeremy Du Croz, Numerical Algorithms Group Ltd. * Sven Hammarling, Numerical Algorithms Group Ltd. * * .. Scalar Arguments .. INTEGER INFOT, NOUT LOGICAL LERR, OK CHARACTER*6 SRNAMT * .. Executable Statements .. IF( .NOT.LERR )THEN WRITE( NOUT, FMT = 9999 )INFOT, SRNAMT OK = .FALSE. END IF LERR = .FALSE. RETURN * 9999 FORMAT( ' ***** ILLEGAL VALUE OF PARAMETER NUMBER ', I2, ' NOT D', $ 'ETECTED BY ', A6, ' *****' ) * * End of CHKXER. * END SUBROUTINE XERBLA( SRNAME, INFO ) * * This is a special version of XERBLA to be used only as part of * the test program for testing error exits from the Level 3 BLAS * routines. * * XERBLA is an error handler for the Level 3 BLAS routines. * * It is called by the Level 3 BLAS routines if an input parameter is * invalid. * * Auxiliary routine for test program for Level 3 Blas. * * -- Written on 8-February-1989. * Jack Dongarra, Argonne National Laboratory. * Iain Duff, AERE Harwell. * Jeremy Du Croz, Numerical Algorithms Group Ltd. * Sven Hammarling, Numerical Algorithms Group Ltd. * * .. Scalar Arguments .. INTEGER INFO CHARACTER*6 SRNAME * .. Scalars in Common .. INTEGER INFOT, NOUT LOGICAL LERR, OK CHARACTER*6 SRNAMT * .. Common blocks .. COMMON /INFOC/INFOT, NOUT, OK, LERR COMMON /SRNAMC/SRNAMT * .. Executable Statements .. LERR = .TRUE. IF( INFO.NE.INFOT )THEN IF( INFOT.NE.0 )THEN WRITE( NOUT, FMT = 9999 )INFO, INFOT ELSE WRITE( NOUT, FMT = 9997 )INFO END IF OK = .FALSE. END IF IF( SRNAME.NE.SRNAMT )THEN WRITE( NOUT, FMT = 9998 )SRNAME, SRNAMT OK = .FALSE. END IF RETURN * 9999 FORMAT( ' ******* XERBLA WAS CALLED WITH INFO = ', I6, ' INSTEAD', $ ' OF ', I2, ' *******' ) 9998 FORMAT( ' ******* XERBLA WAS CALLED WITH SRNAME = ', A6, ' INSTE', $ 'AD OF ', A6, ' *******' ) 9997 FORMAT( ' ******* XERBLA WAS CALLED WITH INFO = ', I6, $ ' *******' ) * * End of XERBLA * END blis-0.9.0/blastest/src/fortran/dblat1.f000066400000000000000000001306651422157504600200730ustar00rootroot00000000000000*> \brief \b DBLAT1 * * =========== DOCUMENTATION =========== * * Online html documentation available at * http://www.netlib.org/lapack/explore-html/ * * Definition: * =========== * * PROGRAM DBLAT1 * * *> \par Purpose: * ============= *> *> \verbatim *> *> Test program for the DOUBLE PRECISION Level 1 BLAS. *> *> Based upon the original BLAS test routine together with: *> F06EAF Example Program Text *> \endverbatim * * Authors: * ======== * *> \author Univ. of Tennessee *> \author Univ. of California Berkeley *> \author Univ. of Colorado Denver *> \author NAG Ltd. * *> \date April 2012 * *> \ingroup double_blas_testing * * ===================================================================== PROGRAM DBLAT1 * * -- Reference BLAS test routine (version 3.4.1) -- * -- Reference BLAS is a software package provided by Univ. of Tennessee, -- * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- * April 2012 * * ===================================================================== * * .. Parameters .. INTEGER NOUT PARAMETER (NOUT=6) * .. Scalars in Common .. INTEGER ICASE, INCX, INCY, N LOGICAL PASS * .. Local Scalars .. DOUBLE PRECISION SFAC INTEGER IC * .. External Subroutines .. EXTERNAL CHECK0, CHECK1, CHECK2, CHECK3, HEADER * .. Common blocks .. COMMON /COMBLA/ICASE, N, INCX, INCY, PASS * .. Data statements .. DATA SFAC/9.765625D-4/ * .. Executable Statements .. WRITE (NOUT,99999) DO 20 IC = 1, 13 ICASE = IC CALL HEADER * * .. Initialize PASS, INCX, and INCY for a new case. .. * .. the value 9999 for INCX or INCY will appear in the .. * .. detailed output, if any, for cases that do not involve .. * .. these parameters .. * PASS = .TRUE. INCX = 9999 INCY = 9999 IF (ICASE.EQ.3 .OR. ICASE.EQ.11) THEN CALL CHECK0(SFAC) ELSE IF (ICASE.EQ.7 .OR. ICASE.EQ.8 .OR. ICASE.EQ.9 .OR. + ICASE.EQ.10) THEN CALL CHECK1(SFAC) ELSE IF (ICASE.EQ.1 .OR. ICASE.EQ.2 .OR. ICASE.EQ.5 .OR. + ICASE.EQ.6 .OR. ICASE.EQ.12 .OR. ICASE.EQ.13) THEN CALL CHECK2(SFAC) ELSE IF (ICASE.EQ.4) THEN CALL CHECK3(SFAC) END IF * -- Print IF (PASS) WRITE (NOUT,99998) 20 CONTINUE STOP * 99999 FORMAT (' Real BLAS Test Program Results',/1X) 99998 FORMAT (' ----- PASS -----') END SUBROUTINE HEADER * .. Parameters .. INTEGER NOUT PARAMETER (NOUT=6) * .. Scalars in Common .. INTEGER ICASE, INCX, INCY, N LOGICAL PASS * .. Local Arrays .. CHARACTER*6 L(13) * .. Common blocks .. COMMON /COMBLA/ICASE, N, INCX, INCY, PASS * .. Data statements .. DATA L(1)/' DDOT '/ DATA L(2)/'DAXPY '/ DATA L(3)/'DROTG '/ DATA L(4)/' DROT '/ DATA L(5)/'DCOPY '/ DATA L(6)/'DSWAP '/ DATA L(7)/'DNRM2 '/ DATA L(8)/'DASUM '/ DATA L(9)/'DSCAL '/ DATA L(10)/'IDAMAX'/ DATA L(11)/'DROTMG'/ DATA L(12)/'DROTM '/ DATA L(13)/'DSDOT '/ * .. Executable Statements .. WRITE (NOUT,99999) ICASE, L(ICASE) RETURN * 99999 FORMAT (/' Test of subprogram number',I3,12X,A6) END SUBROUTINE CHECK0(SFAC) * .. Parameters .. INTEGER NOUT PARAMETER (NOUT=6) * .. Scalar Arguments .. DOUBLE PRECISION SFAC * .. Scalars in Common .. INTEGER ICASE, INCX, INCY, N LOGICAL PASS * .. Local Scalars .. DOUBLE PRECISION SA, SB, SC, SS, D12 INTEGER I, K * .. Local Arrays .. DOUBLE PRECISION DA1(8), DATRUE(8), DB1(8), DBTRUE(8), DC1(8), $ DS1(8), DAB(4,9), DTEMP(9), DTRUE(9,9) * .. External Subroutines .. EXTERNAL DROTG, DROTMG, STEST1 * .. Common blocks .. COMMON /COMBLA/ICASE, N, INCX, INCY, PASS * .. Data statements .. DATA DA1/0.3D0, 0.4D0, -0.3D0, -0.4D0, -0.3D0, 0.0D0, + 0.0D0, 1.0D0/ DATA DB1/0.4D0, 0.3D0, 0.4D0, 0.3D0, -0.4D0, 0.0D0, + 1.0D0, 0.0D0/ DATA DC1/0.6D0, 0.8D0, -0.6D0, 0.8D0, 0.6D0, 1.0D0, + 0.0D0, 1.0D0/ DATA DS1/0.8D0, 0.6D0, 0.8D0, -0.6D0, 0.8D0, 0.0D0, + 1.0D0, 0.0D0/ DATA DATRUE/0.5D0, 0.5D0, 0.5D0, -0.5D0, -0.5D0, + 0.0D0, 1.0D0, 1.0D0/ DATA DBTRUE/0.0D0, 0.6D0, 0.0D0, -0.6D0, 0.0D0, + 0.0D0, 1.0D0, 0.0D0/ * INPUT FOR MODIFIED GIVENS DATA DAB/ .1D0,.3D0,1.2D0,.2D0, A .7D0, .2D0, .6D0, 4.2D0, B 0.D0,0.D0,0.D0,0.D0, C 4.D0, -1.D0, 2.D0, 4.D0, D 6.D-10, 2.D-2, 1.D5, 10.D0, E 4.D10, 2.D-2, 1.D-5, 10.D0, F 2.D-10, 4.D-2, 1.D5, 10.D0, G 2.D10, 4.D-2, 1.D-5, 10.D0, H 4.D0, -2.D0, 8.D0, 4.D0 / * TRUE RESULTS FOR MODIFIED GIVENS DATA DTRUE/0.D0,0.D0, 1.3D0, .2D0, 0.D0,0.D0,0.D0, .5D0, 0.D0, A 0.D0,0.D0, 4.5D0, 4.2D0, 1.D0, .5D0, 0.D0,0.D0,0.D0, B 0.D0,0.D0,0.D0,0.D0, -2.D0, 0.D0,0.D0,0.D0,0.D0, C 0.D0,0.D0,0.D0, 4.D0, -1.D0, 0.D0,0.D0,0.D0,0.D0, D 0.D0, 15.D-3, 0.D0, 10.D0, -1.D0, 0.D0, -1.D-4, E 0.D0, 1.D0, F 0.D0,0.D0, 6144.D-5, 10.D0, -1.D0, 4096.D0, -1.D6, G 0.D0, 1.D0, H 0.D0,0.D0,15.D0,10.D0,-1.D0, 5.D-5, 0.D0,1.D0,0.D0, I 0.D0,0.D0, 15.D0, 10.D0, -1. D0, 5.D5, -4096.D0, J 1.D0, 4096.D-6, K 0.D0,0.D0, 7.D0, 4.D0, 0.D0,0.D0, -.5D0, -.25D0, 0.D0/ * 4096 = 2 ** 12 DATA D12 /4096.D0/ DTRUE(1,1) = 12.D0 / 130.D0 DTRUE(2,1) = 36.D0 / 130.D0 DTRUE(7,1) = -1.D0 / 6.D0 DTRUE(1,2) = 14.D0 / 75.D0 DTRUE(2,2) = 49.D0 / 75.D0 DTRUE(9,2) = 1.D0 / 7.D0 DTRUE(1,5) = 45.D-11 * (D12 * D12) DTRUE(3,5) = 4.D5 / (3.D0 * D12) DTRUE(6,5) = 1.D0 / D12 DTRUE(8,5) = 1.D4 / (3.D0 * D12) DTRUE(1,6) = 4.D10 / (1.5D0 * D12 * D12) DTRUE(2,6) = 2.D-2 / 1.5D0 DTRUE(8,6) = 5.D-7 * D12 DTRUE(1,7) = 4.D0 / 150.D0 DTRUE(2,7) = (2.D-10 / 1.5D0) * (D12 * D12) DTRUE(7,7) = -DTRUE(6,5) DTRUE(9,7) = 1.D4 / D12 DTRUE(1,8) = DTRUE(1,7) DTRUE(2,8) = 2.D10 / (1.5D0 * D12 * D12) DTRUE(1,9) = 32.D0 / 7.D0 DTRUE(2,9) = -16.D0 / 7.D0 * .. Executable Statements .. * * Compute true values which cannot be prestored * in decimal notation * DBTRUE(1) = 1.0D0/0.6D0 DBTRUE(3) = -1.0D0/0.6D0 DBTRUE(5) = 1.0D0/0.6D0 * DO 20 K = 1, 8 * .. Set N=K for identification in output if any .. N = K IF (ICASE.EQ.3) THEN * .. DROTG .. IF (K.GT.8) GO TO 40 SA = DA1(K) SB = DB1(K) CALL DROTG(SA,SB,SC,SS) CALL STEST1(SA,DATRUE(K),DATRUE(K),SFAC) CALL STEST1(SB,DBTRUE(K),DBTRUE(K),SFAC) CALL STEST1(SC,DC1(K),DC1(K),SFAC) CALL STEST1(SS,DS1(K),DS1(K),SFAC) ELSEIF (ICASE.EQ.11) THEN * .. DROTMG .. DO I=1,4 DTEMP(I)= DAB(I,K) DTEMP(I+4) = 0.0 END DO DTEMP(9) = 0.0 CALL DROTMG(DTEMP(1),DTEMP(2),DTEMP(3),DTEMP(4),DTEMP(5)) CALL STEST(9,DTEMP,DTRUE(1,K),DTRUE(1,K),SFAC) ELSE WRITE (NOUT,*) ' Shouldn''t be here in CHECK0' STOP END IF 20 CONTINUE 40 RETURN END SUBROUTINE CHECK1(SFAC) * .. Parameters .. INTEGER NOUT PARAMETER (NOUT=6) * .. Scalar Arguments .. DOUBLE PRECISION SFAC * .. Scalars in Common .. INTEGER ICASE, INCX, INCY, N LOGICAL PASS * .. Local Scalars .. INTEGER I, LEN, NP1 * .. Local Arrays .. DOUBLE PRECISION DTRUE1(5), DTRUE3(5), DTRUE5(8,5,2), DV(8,5,2), + SA(10), STEMP(1), STRUE(8), SX(8) INTEGER ITRUE2(5) * .. External Functions .. DOUBLE PRECISION DASUM, DNRM2 INTEGER IDAMAX EXTERNAL DASUM, DNRM2, IDAMAX * .. External Subroutines .. EXTERNAL ITEST1, DSCAL, STEST, STEST1 * .. Intrinsic Functions .. INTRINSIC MAX * .. Common blocks .. COMMON /COMBLA/ICASE, N, INCX, INCY, PASS * .. Data statements .. DATA SA/0.3D0, -1.0D0, 0.0D0, 1.0D0, 0.3D0, 0.3D0, + 0.3D0, 0.3D0, 0.3D0, 0.3D0/ DATA DV/0.1D0, 2.0D0, 2.0D0, 2.0D0, 2.0D0, 2.0D0, + 2.0D0, 2.0D0, 0.3D0, 3.0D0, 3.0D0, 3.0D0, 3.0D0, + 3.0D0, 3.0D0, 3.0D0, 0.3D0, -0.4D0, 4.0D0, + 4.0D0, 4.0D0, 4.0D0, 4.0D0, 4.0D0, 0.2D0, + -0.6D0, 0.3D0, 5.0D0, 5.0D0, 5.0D0, 5.0D0, + 5.0D0, 0.1D0, -0.3D0, 0.5D0, -0.1D0, 6.0D0, + 6.0D0, 6.0D0, 6.0D0, 0.1D0, 8.0D0, 8.0D0, 8.0D0, + 8.0D0, 8.0D0, 8.0D0, 8.0D0, 0.3D0, 9.0D0, 9.0D0, + 9.0D0, 9.0D0, 9.0D0, 9.0D0, 9.0D0, 0.3D0, 2.0D0, + -0.4D0, 2.0D0, 2.0D0, 2.0D0, 2.0D0, 2.0D0, + 0.2D0, 3.0D0, -0.6D0, 5.0D0, 0.3D0, 2.0D0, + 2.0D0, 2.0D0, 0.1D0, 4.0D0, -0.3D0, 6.0D0, + -0.5D0, 7.0D0, -0.1D0, 3.0D0/ DATA DTRUE1/0.0D0, 0.3D0, 0.5D0, 0.7D0, 0.6D0/ DATA DTRUE3/0.0D0, 0.3D0, 0.7D0, 1.1D0, 1.0D0/ DATA DTRUE5/0.10D0, 2.0D0, 2.0D0, 2.0D0, 2.0D0, + 2.0D0, 2.0D0, 2.0D0, -0.3D0, 3.0D0, 3.0D0, + 3.0D0, 3.0D0, 3.0D0, 3.0D0, 3.0D0, 0.0D0, 0.0D0, + 4.0D0, 4.0D0, 4.0D0, 4.0D0, 4.0D0, 4.0D0, + 0.20D0, -0.60D0, 0.30D0, 5.0D0, 5.0D0, 5.0D0, + 5.0D0, 5.0D0, 0.03D0, -0.09D0, 0.15D0, -0.03D0, + 6.0D0, 6.0D0, 6.0D0, 6.0D0, 0.10D0, 8.0D0, + 8.0D0, 8.0D0, 8.0D0, 8.0D0, 8.0D0, 8.0D0, + 0.09D0, 9.0D0, 9.0D0, 9.0D0, 9.0D0, 9.0D0, + 9.0D0, 9.0D0, 0.09D0, 2.0D0, -0.12D0, 2.0D0, + 2.0D0, 2.0D0, 2.0D0, 2.0D0, 0.06D0, 3.0D0, + -0.18D0, 5.0D0, 0.09D0, 2.0D0, 2.0D0, 2.0D0, + 0.03D0, 4.0D0, -0.09D0, 6.0D0, -0.15D0, 7.0D0, + -0.03D0, 3.0D0/ DATA ITRUE2/0, 1, 2, 2, 3/ * .. Executable Statements .. DO 80 INCX = 1, 2 DO 60 NP1 = 1, 5 N = NP1 - 1 LEN = 2*MAX(N,1) * .. Set vector arguments .. DO 20 I = 1, LEN SX(I) = DV(I,NP1,INCX) 20 CONTINUE * IF (ICASE.EQ.7) THEN * .. DNRM2 .. STEMP(1) = DTRUE1(NP1) CALL STEST1(DNRM2(N,SX,INCX),STEMP(1),STEMP,SFAC) ELSE IF (ICASE.EQ.8) THEN * .. DASUM .. STEMP(1) = DTRUE3(NP1) CALL STEST1(DASUM(N,SX,INCX),STEMP(1),STEMP,SFAC) ELSE IF (ICASE.EQ.9) THEN * .. DSCAL .. CALL DSCAL(N,SA((INCX-1)*5+NP1),SX,INCX) DO 40 I = 1, LEN STRUE(I) = DTRUE5(I,NP1,INCX) 40 CONTINUE CALL STEST(LEN,SX,STRUE,STRUE,SFAC) ELSE IF (ICASE.EQ.10) THEN * .. IDAMAX .. CALL ITEST1(IDAMAX(N,SX,INCX),ITRUE2(NP1)) ELSE WRITE (NOUT,*) ' Shouldn''t be here in CHECK1' STOP END IF 60 CONTINUE 80 CONTINUE RETURN END SUBROUTINE CHECK2(SFAC) * .. Parameters .. INTEGER NOUT PARAMETER (NOUT=6) * .. Scalar Arguments .. DOUBLE PRECISION SFAC * .. Scalars in Common .. INTEGER ICASE, INCX, INCY, N LOGICAL PASS * .. Local Scalars .. DOUBLE PRECISION SA INTEGER I, J, KI, KN, KNI, KPAR, KSIZE, LENX, LENY, $ MX, MY * .. Local Arrays .. DOUBLE PRECISION DT10X(7,4,4), DT10Y(7,4,4), DT7(4,4), $ DT8(7,4,4), DX1(7), $ DY1(7), SSIZE1(4), SSIZE2(14,2), SSIZE(7), $ STX(7), STY(7), SX(7), SY(7), $ DPAR(5,4), DT19X(7,4,16),DT19XA(7,4,4), $ DT19XB(7,4,4), DT19XC(7,4,4),DT19XD(7,4,4), $ DT19Y(7,4,16), DT19YA(7,4,4),DT19YB(7,4,4), $ DT19YC(7,4,4), DT19YD(7,4,4), DTEMP(5) REAL SX1(7), SY1(7) INTEGER INCXS(4), INCYS(4), LENS(4,2), NS(4) * .. External Functions .. DOUBLE PRECISION DDOT, DSDOT EXTERNAL DDOT, DSDOT * .. External Subroutines .. EXTERNAL DAXPY, DCOPY, DROTM, DSWAP, STEST, STEST1 * .. Intrinsic Functions .. INTRINSIC ABS, MIN * .. Common blocks .. COMMON /COMBLA/ICASE, N, INCX, INCY, PASS * .. Data statements .. EQUIVALENCE (DT19X(1,1,1),DT19XA(1,1,1)),(DT19X(1,1,5), A DT19XB(1,1,1)),(DT19X(1,1,9),DT19XC(1,1,1)), B (DT19X(1,1,13),DT19XD(1,1,1)) EQUIVALENCE (DT19Y(1,1,1),DT19YA(1,1,1)),(DT19Y(1,1,5), A DT19YB(1,1,1)),(DT19Y(1,1,9),DT19YC(1,1,1)), B (DT19Y(1,1,13),DT19YD(1,1,1)) DATA SA/0.3D0/ DATA INCXS/1, 2, -2, -1/ DATA INCYS/1, -2, 1, -2/ DATA LENS/1, 1, 2, 4, 1, 1, 3, 7/ DATA NS/0, 1, 2, 4/ DATA DX1/0.6D0, 0.1D0, -0.5D0, 0.8D0, 0.9D0, -0.3D0, + -0.4D0/ DATA DY1/0.5D0, -0.9D0, 0.3D0, 0.7D0, -0.6D0, 0.2D0, + 0.8D0/ ***** FGVZ: We have to add separate REAL arrays for DSDOT() because ***** REAL() on an array argument does not translate via f2c. DATA SX1/0.6E0, 0.1E0, -0.5E0, 0.8E0, 0.9E0, -0.3E0, + -0.4E0/ DATA SY1/0.5E0, -0.9E0, 0.3E0, 0.7E0, -0.6E0, 0.2E0, + 0.8E0/ DATA DT7/0.0D0, 0.30D0, 0.21D0, 0.62D0, 0.0D0, + 0.30D0, -0.07D0, 0.85D0, 0.0D0, 0.30D0, -0.79D0, + -0.74D0, 0.0D0, 0.30D0, 0.33D0, 1.27D0/ DATA DT8/0.5D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, + 0.0D0, 0.68D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, + 0.0D0, 0.0D0, 0.68D0, -0.87D0, 0.0D0, 0.0D0, + 0.0D0, 0.0D0, 0.0D0, 0.68D0, -0.87D0, 0.15D0, + 0.94D0, 0.0D0, 0.0D0, 0.0D0, 0.5D0, 0.0D0, + 0.0D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, 0.68D0, + 0.0D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, + 0.35D0, -0.9D0, 0.48D0, 0.0D0, 0.0D0, 0.0D0, + 0.0D0, 0.38D0, -0.9D0, 0.57D0, 0.7D0, -0.75D0, + 0.2D0, 0.98D0, 0.5D0, 0.0D0, 0.0D0, 0.0D0, + 0.0D0, 0.0D0, 0.0D0, 0.68D0, 0.0D0, 0.0D0, + 0.0D0, 0.0D0, 0.0D0, 0.0D0, 0.35D0, -0.72D0, + 0.0D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, 0.38D0, + -0.63D0, 0.15D0, 0.88D0, 0.0D0, 0.0D0, 0.0D0, + 0.5D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, + 0.68D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, + 0.0D0, 0.68D0, -0.9D0, 0.33D0, 0.0D0, 0.0D0, + 0.0D0, 0.0D0, 0.68D0, -0.9D0, 0.33D0, 0.7D0, + -0.75D0, 0.2D0, 1.04D0/ DATA DT10X/0.6D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, + 0.0D0, 0.5D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, + 0.0D0, 0.5D0, -0.9D0, 0.0D0, 0.0D0, 0.0D0, + 0.0D0, 0.0D0, 0.5D0, -0.9D0, 0.3D0, 0.7D0, + 0.0D0, 0.0D0, 0.0D0, 0.6D0, 0.0D0, 0.0D0, 0.0D0, + 0.0D0, 0.0D0, 0.0D0, 0.5D0, 0.0D0, 0.0D0, 0.0D0, + 0.0D0, 0.0D0, 0.0D0, 0.3D0, 0.1D0, 0.5D0, 0.0D0, + 0.0D0, 0.0D0, 0.0D0, 0.8D0, 0.1D0, -0.6D0, + 0.8D0, 0.3D0, -0.3D0, 0.5D0, 0.6D0, 0.0D0, + 0.0D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, 0.5D0, 0.0D0, + 0.0D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, -0.9D0, + 0.1D0, 0.5D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, 0.7D0, + 0.1D0, 0.3D0, 0.8D0, -0.9D0, -0.3D0, 0.5D0, + 0.6D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, + 0.5D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, + 0.5D0, 0.3D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, + 0.5D0, 0.3D0, -0.6D0, 0.8D0, 0.0D0, 0.0D0, + 0.0D0/ DATA DT10Y/0.5D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, + 0.0D0, 0.6D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, + 0.0D0, 0.6D0, 0.1D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, + 0.0D0, 0.6D0, 0.1D0, -0.5D0, 0.8D0, 0.0D0, + 0.0D0, 0.0D0, 0.5D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, + 0.0D0, 0.0D0, 0.6D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, + 0.0D0, 0.0D0, -0.5D0, -0.9D0, 0.6D0, 0.0D0, + 0.0D0, 0.0D0, 0.0D0, -0.4D0, -0.9D0, 0.9D0, + 0.7D0, -0.5D0, 0.2D0, 0.6D0, 0.5D0, 0.0D0, + 0.0D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, 0.6D0, 0.0D0, + 0.0D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, -0.5D0, + 0.6D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, + -0.4D0, 0.9D0, -0.5D0, 0.6D0, 0.0D0, 0.0D0, + 0.0D0, 0.5D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, + 0.0D0, 0.6D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, + 0.0D0, 0.6D0, -0.9D0, 0.1D0, 0.0D0, 0.0D0, + 0.0D0, 0.0D0, 0.6D0, -0.9D0, 0.1D0, 0.7D0, + -0.5D0, 0.2D0, 0.8D0/ DATA SSIZE1/0.0D0, 0.3D0, 1.6D0, 3.2D0/ DATA SSIZE2/0.0D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, + 0.0D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, + 0.0D0, 1.17D0, 1.17D0, 1.17D0, 1.17D0, 1.17D0, + 1.17D0, 1.17D0, 1.17D0, 1.17D0, 1.17D0, 1.17D0, + 1.17D0, 1.17D0, 1.17D0/ * * FOR DROTM * DATA DPAR/-2.D0, 0.D0,0.D0,0.D0,0.D0, A -1.D0, 2.D0, -3.D0, -4.D0, 5.D0, B 0.D0, 0.D0, 2.D0, -3.D0, 0.D0, C 1.D0, 5.D0, 2.D0, 0.D0, -4.D0/ * TRUE X RESULTS F0R ROTATIONS DROTM DATA DT19XA/.6D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0, A .6D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0, B .6D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0, C .6D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0, D .6D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0, E -.8D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0, F -.9D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0, G 3.5D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0, H .6D0, .1D0, 0.D0,0.D0,0.D0,0.D0,0.D0, I -.8D0, 3.8D0, 0.D0,0.D0,0.D0,0.D0,0.D0, J -.9D0, 2.8D0, 0.D0,0.D0,0.D0,0.D0,0.D0, K 3.5D0, -.4D0, 0.D0,0.D0,0.D0,0.D0,0.D0, L .6D0, .1D0, -.5D0, .8D0, 0.D0,0.D0,0.D0, M -.8D0, 3.8D0, -2.2D0, -1.2D0, 0.D0,0.D0,0.D0, N -.9D0, 2.8D0, -1.4D0, -1.3D0, 0.D0,0.D0,0.D0, O 3.5D0, -.4D0, -2.2D0, 4.7D0, 0.D0,0.D0,0.D0/ * DATA DT19XB/.6D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0, A .6D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0, B .6D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0, C .6D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0, D .6D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0, E -.8D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0, F -.9D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0, G 3.5D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0, H .6D0, .1D0, -.5D0, 0.D0,0.D0,0.D0,0.D0, I 0.D0, .1D0, -3.0D0, 0.D0,0.D0,0.D0,0.D0, J -.3D0, .1D0, -2.0D0, 0.D0,0.D0,0.D0,0.D0, K 3.3D0, .1D0, -2.0D0, 0.D0,0.D0,0.D0,0.D0, L .6D0, .1D0, -.5D0, .8D0, .9D0, -.3D0, -.4D0, M -2.0D0, .1D0, 1.4D0, .8D0, .6D0, -.3D0, -2.8D0, N -1.8D0, .1D0, 1.3D0, .8D0, 0.D0, -.3D0, -1.9D0, O 3.8D0, .1D0, -3.1D0, .8D0, 4.8D0, -.3D0, -1.5D0 / * DATA DT19XC/.6D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0, A .6D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0, B .6D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0, C .6D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0, D .6D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0, E -.8D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0, F -.9D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0, G 3.5D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0, H .6D0, .1D0, -.5D0, 0.D0,0.D0,0.D0,0.D0, I 4.8D0, .1D0, -3.0D0, 0.D0,0.D0,0.D0,0.D0, J 3.3D0, .1D0, -2.0D0, 0.D0,0.D0,0.D0,0.D0, K 2.1D0, .1D0, -2.0D0, 0.D0,0.D0,0.D0,0.D0, L .6D0, .1D0, -.5D0, .8D0, .9D0, -.3D0, -.4D0, M -1.6D0, .1D0, -2.2D0, .8D0, 5.4D0, -.3D0, -2.8D0, N -1.5D0, .1D0, -1.4D0, .8D0, 3.6D0, -.3D0, -1.9D0, O 3.7D0, .1D0, -2.2D0, .8D0, 3.6D0, -.3D0, -1.5D0 / * DATA DT19XD/.6D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0, A .6D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0, B .6D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0, C .6D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0, D .6D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0, E -.8D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0, F -.9D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0, G 3.5D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0, H .6D0, .1D0, 0.D0,0.D0,0.D0,0.D0,0.D0, I -.8D0, -1.0D0, 0.D0,0.D0,0.D0,0.D0,0.D0, J -.9D0, -.8D0, 0.D0,0.D0,0.D0,0.D0,0.D0, K 3.5D0, .8D0, 0.D0,0.D0,0.D0,0.D0,0.D0, L .6D0, .1D0, -.5D0, .8D0, 0.D0,0.D0,0.D0, M -.8D0, -1.0D0, 1.4D0, -1.6D0, 0.D0,0.D0,0.D0, N -.9D0, -.8D0, 1.3D0, -1.6D0, 0.D0,0.D0,0.D0, O 3.5D0, .8D0, -3.1D0, 4.8D0, 0.D0,0.D0,0.D0/ * TRUE Y RESULTS FOR ROTATIONS DROTM DATA DT19YA/.5D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0, A .5D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0, B .5D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0, C .5D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0, D .5D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0, E .7D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0, F 1.7D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0, G -2.6D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0, H .5D0, -.9D0, 0.D0,0.D0,0.D0,0.D0,0.D0, I .7D0, -4.8D0, 0.D0,0.D0,0.D0,0.D0,0.D0, J 1.7D0, -.7D0, 0.D0,0.D0,0.D0,0.D0,0.D0, K -2.6D0, 3.5D0, 0.D0,0.D0,0.D0,0.D0,0.D0, L .5D0, -.9D0, .3D0, .7D0, 0.D0,0.D0,0.D0, M .7D0, -4.8D0, 3.0D0, 1.1D0, 0.D0,0.D0,0.D0, N 1.7D0, -.7D0, -.7D0, 2.3D0, 0.D0,0.D0,0.D0, O -2.6D0, 3.5D0, -.7D0, -3.6D0, 0.D0,0.D0,0.D0/ * DATA DT19YB/.5D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0, A .5D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0, B .5D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0, C .5D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0, D .5D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0, E .7D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0, F 1.7D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0, G -2.6D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0, H .5D0, -.9D0, .3D0, 0.D0,0.D0,0.D0,0.D0, I 4.0D0, -.9D0, -.3D0, 0.D0,0.D0,0.D0,0.D0, J -.5D0, -.9D0, 1.5D0, 0.D0,0.D0,0.D0,0.D0, K -1.5D0, -.9D0, -1.8D0, 0.D0,0.D0,0.D0,0.D0, L .5D0, -.9D0, .3D0, .7D0, -.6D0, .2D0, .8D0, M 3.7D0, -.9D0, -1.2D0, .7D0, -1.5D0, .2D0, 2.2D0, N -.3D0, -.9D0, 2.1D0, .7D0, -1.6D0, .2D0, 2.0D0, O -1.6D0, -.9D0, -2.1D0, .7D0, 2.9D0, .2D0, -3.8D0 / * DATA DT19YC/.5D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0, A .5D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0, B .5D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0, C .5D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0, D .5D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0, E .7D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0, F 1.7D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0, G -2.6D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0, H .5D0, -.9D0, 0.D0,0.D0,0.D0,0.D0,0.D0, I 4.0D0, -6.3D0, 0.D0,0.D0,0.D0,0.D0,0.D0, J -.5D0, .3D0, 0.D0,0.D0,0.D0,0.D0,0.D0, K -1.5D0, 3.0D0, 0.D0,0.D0,0.D0,0.D0,0.D0, L .5D0, -.9D0, .3D0, .7D0, 0.D0,0.D0,0.D0, M 3.7D0, -7.2D0, 3.0D0, 1.7D0, 0.D0,0.D0,0.D0, N -.3D0, .9D0, -.7D0, 1.9D0, 0.D0,0.D0,0.D0, O -1.6D0, 2.7D0, -.7D0, -3.4D0, 0.D0,0.D0,0.D0/ * DATA DT19YD/.5D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0, A .5D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0, B .5D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0, C .5D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0, D .5D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0, E .7D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0, F 1.7D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0, G -2.6D0, 0.D0,0.D0,0.D0,0.D0,0.D0,0.D0, H .5D0, -.9D0, .3D0, 0.D0,0.D0,0.D0,0.D0, I .7D0, -.9D0, 1.2D0, 0.D0,0.D0,0.D0,0.D0, J 1.7D0, -.9D0, .5D0, 0.D0,0.D0,0.D0,0.D0, K -2.6D0, -.9D0, -1.3D0, 0.D0,0.D0,0.D0,0.D0, L .5D0, -.9D0, .3D0, .7D0, -.6D0, .2D0, .8D0, M .7D0, -.9D0, 1.2D0, .7D0, -1.5D0, .2D0, 1.6D0, N 1.7D0, -.9D0, .5D0, .7D0, -1.6D0, .2D0, 2.4D0, O -2.6D0, -.9D0, -1.3D0, .7D0, 2.9D0, .2D0, -4.0D0 / * * .. Executable Statements .. * DO 120 KI = 1, 4 INCX = INCXS(KI) INCY = INCYS(KI) MX = ABS(INCX) MY = ABS(INCY) * DO 100 KN = 1, 4 N = NS(KN) KSIZE = MIN(2,KN) LENX = LENS(KN,MX) LENY = LENS(KN,MY) * .. Initialize all argument arrays .. DO 20 I = 1, 7 SX(I) = DX1(I) SY(I) = DY1(I) ***** FGVZ: We have to add a loop to initialize separate REAL arrays ***** for DSDOT() because REAL() on an array argument does not ***** translate via f2c. SX1(I) = DX1(I) SY1(I) = DY1(I) 20 CONTINUE * IF (ICASE.EQ.1) THEN * .. DDOT .. CALL STEST1(DDOT(N,SX,INCX,SY,INCY),DT7(KN,KI),SSIZE1(KN) + ,SFAC) ELSE IF (ICASE.EQ.2) THEN * .. DAXPY .. CALL DAXPY(N,SA,SX,INCX,SY,INCY) DO 40 J = 1, LENY STY(J) = DT8(J,KN,KI) 40 CONTINUE CALL STEST(LENY,SY,STY,SSIZE2(1,KSIZE),SFAC) ELSE IF (ICASE.EQ.5) THEN * .. DCOPY .. DO 60 I = 1, 7 STY(I) = DT10Y(I,KN,KI) 60 CONTINUE CALL DCOPY(N,SX,INCX,SY,INCY) CALL STEST(LENY,SY,STY,SSIZE2(1,1),1.0D0) ELSE IF (ICASE.EQ.6) THEN * .. DSWAP .. CALL DSWAP(N,SX,INCX,SY,INCY) DO 80 I = 1, 7 STX(I) = DT10X(I,KN,KI) STY(I) = DT10Y(I,KN,KI) 80 CONTINUE CALL STEST(LENX,SX,STX,SSIZE2(1,1),1.0D0) CALL STEST(LENY,SY,STY,SSIZE2(1,1),1.0D0) ELSE IF (ICASE.EQ.12) THEN * .. DROTM .. KNI=KN+4*(KI-1) DO KPAR=1,4 DO I=1,7 SX(I) = DX1(I) SY(I) = DY1(I) STX(I)= DT19X(I,KPAR,KNI) STY(I)= DT19Y(I,KPAR,KNI) END DO * DO I=1,5 DTEMP(I) = DPAR(I,KPAR) END DO * DO I=1,LENX SSIZE(I)=STX(I) END DO * SEE REMARK ABOVE ABOUT DT11X(1,2,7) * AND DT11X(5,3,8). IF ((KPAR .EQ. 2) .AND. (KNI .EQ. 7)) $ SSIZE(1) = 2.4D0 IF ((KPAR .EQ. 3) .AND. (KNI .EQ. 8)) $ SSIZE(5) = 1.8D0 * CALL DROTM(N,SX,INCX,SY,INCY,DTEMP) CALL STEST(LENX,SX,STX,SSIZE,SFAC) CALL STEST(LENY,SY,STY,STY,SFAC) END DO ELSE IF (ICASE.EQ.13) THEN * .. DSDOT .. ***** CALL TESTDSDOT(REAL(DSDOT(N,REAL(SX),INCX,REAL(SY),INCY)), CALL TESTDSDOT(REAL(DSDOT(N,SX1,INCX,SY1,INCY)), $ REAL(DT7(KN,KI)),REAL(SSIZE1(KN)), .3125E-1) ELSE WRITE (NOUT,*) ' Shouldn''t be here in CHECK2' STOP END IF 100 CONTINUE 120 CONTINUE RETURN END SUBROUTINE CHECK3(SFAC) * .. Parameters .. INTEGER NOUT PARAMETER (NOUT=6) * .. Scalar Arguments .. DOUBLE PRECISION SFAC * .. Scalars in Common .. INTEGER ICASE, INCX, INCY, N LOGICAL PASS * .. Local Scalars .. DOUBLE PRECISION SC, SS INTEGER I, K, KI, KN, KSIZE, LENX, LENY, MX, MY * .. Local Arrays .. DOUBLE PRECISION COPYX(5), COPYY(5), DT9X(7,4,4), DT9Y(7,4,4), + DX1(7), DY1(7), MWPC(11), MWPS(11), MWPSTX(5), + MWPSTY(5), MWPTX(11,5), MWPTY(11,5), MWPX(5), + MWPY(5), SSIZE2(14,2), STX(7), STY(7), SX(7), + SY(7) INTEGER INCXS(4), INCYS(4), LENS(4,2), MWPINX(11), + MWPINY(11), MWPN(11), NS(4) * .. External Subroutines .. EXTERNAL DROT, STEST * .. Intrinsic Functions .. INTRINSIC ABS, MIN * .. Common blocks .. COMMON /COMBLA/ICASE, N, INCX, INCY, PASS * .. Data statements .. DATA INCXS/1, 2, -2, -1/ DATA INCYS/1, -2, 1, -2/ DATA LENS/1, 1, 2, 4, 1, 1, 3, 7/ DATA NS/0, 1, 2, 4/ DATA DX1/0.6D0, 0.1D0, -0.5D0, 0.8D0, 0.9D0, -0.3D0, + -0.4D0/ DATA DY1/0.5D0, -0.9D0, 0.3D0, 0.7D0, -0.6D0, 0.2D0, + 0.8D0/ DATA SC, SS/0.8D0, 0.6D0/ DATA DT9X/0.6D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, + 0.0D0, 0.78D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, + 0.0D0, 0.0D0, 0.78D0, -0.46D0, 0.0D0, 0.0D0, + 0.0D0, 0.0D0, 0.0D0, 0.78D0, -0.46D0, -0.22D0, + 1.06D0, 0.0D0, 0.0D0, 0.0D0, 0.6D0, 0.0D0, + 0.0D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, 0.78D0, + 0.0D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, + 0.66D0, 0.1D0, -0.1D0, 0.0D0, 0.0D0, 0.0D0, + 0.0D0, 0.96D0, 0.1D0, -0.76D0, 0.8D0, 0.90D0, + -0.3D0, -0.02D0, 0.6D0, 0.0D0, 0.0D0, 0.0D0, + 0.0D0, 0.0D0, 0.0D0, 0.78D0, 0.0D0, 0.0D0, + 0.0D0, 0.0D0, 0.0D0, 0.0D0, -0.06D0, 0.1D0, + -0.1D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, 0.90D0, + 0.1D0, -0.22D0, 0.8D0, 0.18D0, -0.3D0, -0.02D0, + 0.6D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, + 0.78D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, + 0.0D0, 0.78D0, 0.26D0, 0.0D0, 0.0D0, 0.0D0, + 0.0D0, 0.0D0, 0.78D0, 0.26D0, -0.76D0, 1.12D0, + 0.0D0, 0.0D0, 0.0D0/ DATA DT9Y/0.5D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, + 0.0D0, 0.04D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, + 0.0D0, 0.0D0, 0.04D0, -0.78D0, 0.0D0, 0.0D0, + 0.0D0, 0.0D0, 0.0D0, 0.04D0, -0.78D0, 0.54D0, + 0.08D0, 0.0D0, 0.0D0, 0.0D0, 0.5D0, 0.0D0, + 0.0D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, 0.04D0, + 0.0D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, 0.7D0, + -0.9D0, -0.12D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, + 0.64D0, -0.9D0, -0.30D0, 0.7D0, -0.18D0, 0.2D0, + 0.28D0, 0.5D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, + 0.0D0, 0.0D0, 0.04D0, 0.0D0, 0.0D0, 0.0D0, + 0.0D0, 0.0D0, 0.0D0, 0.7D0, -1.08D0, 0.0D0, + 0.0D0, 0.0D0, 0.0D0, 0.0D0, 0.64D0, -1.26D0, + 0.54D0, 0.20D0, 0.0D0, 0.0D0, 0.0D0, 0.5D0, + 0.0D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, + 0.04D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, + 0.0D0, 0.04D0, -0.9D0, 0.18D0, 0.0D0, 0.0D0, + 0.0D0, 0.0D0, 0.04D0, -0.9D0, 0.18D0, 0.7D0, + -0.18D0, 0.2D0, 0.16D0/ DATA SSIZE2/0.0D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, + 0.0D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, 0.0D0, + 0.0D0, 1.17D0, 1.17D0, 1.17D0, 1.17D0, 1.17D0, + 1.17D0, 1.17D0, 1.17D0, 1.17D0, 1.17D0, 1.17D0, + 1.17D0, 1.17D0, 1.17D0/ * .. Executable Statements .. * DO 60 KI = 1, 4 INCX = INCXS(KI) INCY = INCYS(KI) MX = ABS(INCX) MY = ABS(INCY) * DO 40 KN = 1, 4 N = NS(KN) KSIZE = MIN(2,KN) LENX = LENS(KN,MX) LENY = LENS(KN,MY) * IF (ICASE.EQ.4) THEN * .. DROT .. DO 20 I = 1, 7 SX(I) = DX1(I) SY(I) = DY1(I) STX(I) = DT9X(I,KN,KI) STY(I) = DT9Y(I,KN,KI) 20 CONTINUE CALL DROT(N,SX,INCX,SY,INCY,SC,SS) CALL STEST(LENX,SX,STX,SSIZE2(1,KSIZE),SFAC) CALL STEST(LENY,SY,STY,SSIZE2(1,KSIZE),SFAC) ELSE WRITE (NOUT,*) ' Shouldn''t be here in CHECK3' STOP END IF 40 CONTINUE 60 CONTINUE * MWPC(1) = 1 DO 80 I = 2, 11 MWPC(I) = 0 80 CONTINUE MWPS(1) = 0 DO 100 I = 2, 6 MWPS(I) = 1 100 CONTINUE DO 120 I = 7, 11 MWPS(I) = -1 120 CONTINUE MWPINX(1) = 1 MWPINX(2) = 1 MWPINX(3) = 1 MWPINX(4) = -1 MWPINX(5) = 1 MWPINX(6) = -1 MWPINX(7) = 1 MWPINX(8) = 1 MWPINX(9) = -1 MWPINX(10) = 1 MWPINX(11) = -1 MWPINY(1) = 1 MWPINY(2) = 1 MWPINY(3) = -1 MWPINY(4) = -1 MWPINY(5) = 2 MWPINY(6) = 1 MWPINY(7) = 1 MWPINY(8) = -1 MWPINY(9) = -1 MWPINY(10) = 2 MWPINY(11) = 1 DO 140 I = 1, 11 MWPN(I) = 5 140 CONTINUE MWPN(5) = 3 MWPN(10) = 3 DO 160 I = 1, 5 MWPX(I) = I MWPY(I) = I MWPTX(1,I) = I MWPTY(1,I) = I MWPTX(2,I) = I MWPTY(2,I) = -I MWPTX(3,I) = 6 - I MWPTY(3,I) = I - 6 MWPTX(4,I) = I MWPTY(4,I) = -I MWPTX(6,I) = 6 - I MWPTY(6,I) = I - 6 MWPTX(7,I) = -I MWPTY(7,I) = I MWPTX(8,I) = I - 6 MWPTY(8,I) = 6 - I MWPTX(9,I) = -I MWPTY(9,I) = I MWPTX(11,I) = I - 6 MWPTY(11,I) = 6 - I 160 CONTINUE MWPTX(5,1) = 1 MWPTX(5,2) = 3 MWPTX(5,3) = 5 MWPTX(5,4) = 4 MWPTX(5,5) = 5 MWPTY(5,1) = -1 MWPTY(5,2) = 2 MWPTY(5,3) = -2 MWPTY(5,4) = 4 MWPTY(5,5) = -3 MWPTX(10,1) = -1 MWPTX(10,2) = -3 MWPTX(10,3) = -5 MWPTX(10,4) = 4 MWPTX(10,5) = 5 MWPTY(10,1) = 1 MWPTY(10,2) = 2 MWPTY(10,3) = 2 MWPTY(10,4) = 4 MWPTY(10,5) = 3 DO 200 I = 1, 11 INCX = MWPINX(I) INCY = MWPINY(I) DO 180 K = 1, 5 COPYX(K) = MWPX(K) COPYY(K) = MWPY(K) MWPSTX(K) = MWPTX(I,K) MWPSTY(K) = MWPTY(I,K) 180 CONTINUE CALL DROT(MWPN(I),COPYX,INCX,COPYY,INCY,MWPC(I),MWPS(I)) CALL STEST(5,COPYX,MWPSTX,MWPSTX,SFAC) CALL STEST(5,COPYY,MWPSTY,MWPSTY,SFAC) 200 CONTINUE RETURN END SUBROUTINE STEST(LEN,SCOMP,STRUE,SSIZE,SFAC) * ********************************* STEST ************************** * * THIS SUBR COMPARES ARRAYS SCOMP() AND STRUE() OF LENGTH LEN TO * SEE IF THE TERM BY TERM DIFFERENCES, MULTIPLIED BY SFAC, ARE * NEGLIGIBLE. * * C. L. LAWSON, JPL, 1974 DEC 10 * * .. Parameters .. INTEGER NOUT DOUBLE PRECISION ZERO PARAMETER (NOUT=6, ZERO=0.0D0) * .. Scalar Arguments .. DOUBLE PRECISION SFAC INTEGER LEN * .. Array Arguments .. DOUBLE PRECISION SCOMP(LEN), SSIZE(LEN), STRUE(LEN) * .. Scalars in Common .. INTEGER ICASE, INCX, INCY, N LOGICAL PASS * .. Local Scalars .. DOUBLE PRECISION SD INTEGER I * .. External Functions .. DOUBLE PRECISION SDIFF EXTERNAL SDIFF * .. Intrinsic Functions .. INTRINSIC ABS * .. Common blocks .. COMMON /COMBLA/ICASE, N, INCX, INCY, PASS * .. Executable Statements .. * DO 40 I = 1, LEN SD = SCOMP(I) - STRUE(I) IF (ABS(SFAC*SD) .LE. ABS(SSIZE(I))*EPSILON(ZERO)) + GO TO 40 * * HERE SCOMP(I) IS NOT CLOSE TO STRUE(I). * IF ( .NOT. PASS) GO TO 20 * PRINT FAIL MESSAGE AND HEADER. PASS = .FALSE. WRITE (NOUT,99999) WRITE (NOUT,99998) 20 WRITE (NOUT,99997) ICASE, N, INCX, INCY, I, SCOMP(I), + STRUE(I), SD, SSIZE(I) 40 CONTINUE RETURN * 99999 FORMAT (' FAIL') 99998 FORMAT (/' CASE N INCX INCY I ', + ' COMP(I) TRUE(I) DIFFERENCE', + ' SIZE(I)',/1X) 99997 FORMAT (1X,I4,I3,2I5,I3,2D36.8,2D12.4) END SUBROUTINE TESTDSDOT(SCOMP,STRUE,SSIZE,SFAC) * ********************************* STEST ************************** * * THIS SUBR COMPARES ARRAYS SCOMP() AND STRUE() OF LENGTH LEN TO * SEE IF THE TERM BY TERM DIFFERENCES, MULTIPLIED BY SFAC, ARE * NEGLIGIBLE. * * C. L. LAWSON, JPL, 1974 DEC 10 * * .. Parameters .. INTEGER NOUT REAL ZERO PARAMETER (NOUT=6, ZERO=0.0E0) * .. Scalar Arguments .. REAL SFAC, SCOMP, SSIZE, STRUE * .. Scalars in Common .. INTEGER ICASE, INCX, INCY, N LOGICAL PASS * .. Local Scalars .. REAL SD * .. Intrinsic Functions .. INTRINSIC ABS * .. Common blocks .. COMMON /COMBLA/ICASE, N, INCX, INCY, PASS * .. Executable Statements .. * SD = SCOMP - STRUE IF (ABS(SFAC*SD) .LE. ABS(SSIZE) * EPSILON(ZERO)) + GO TO 40 * * HERE SCOMP(I) IS NOT CLOSE TO STRUE(I). * IF ( .NOT. PASS) GO TO 20 * PRINT FAIL MESSAGE AND HEADER. PASS = .FALSE. WRITE (NOUT,99999) WRITE (NOUT,99998) 20 WRITE (NOUT,99997) ICASE, N, INCX, INCY, SCOMP, + STRUE, SD, SSIZE 40 CONTINUE RETURN * 99999 FORMAT (' FAIL') 99998 FORMAT (/' CASE N INCX INCY ', + ' COMP(I) TRUE(I) DIFFERENCE', + ' SIZE(I)',/1X) 99997 FORMAT (1X,I4,I3,1I5,I3,2E36.8,2E12.4) END SUBROUTINE STEST1(SCOMP1,STRUE1,SSIZE,SFAC) * ************************* STEST1 ***************************** * * THIS IS AN INTERFACE SUBROUTINE TO ACCOMODATE THE FORTRAN * REQUIREMENT THAT WHEN A DUMMY ARGUMENT IS AN ARRAY, THE * ACTUAL ARGUMENT MUST ALSO BE AN ARRAY OR AN ARRAY ELEMENT. * * C.L. LAWSON, JPL, 1978 DEC 6 * * .. Scalar Arguments .. DOUBLE PRECISION SCOMP1, SFAC, STRUE1 * .. Array Arguments .. DOUBLE PRECISION SSIZE(*) * .. Local Arrays .. DOUBLE PRECISION SCOMP(1), STRUE(1) * .. External Subroutines .. EXTERNAL STEST * .. Executable Statements .. * SCOMP(1) = SCOMP1 STRUE(1) = STRUE1 CALL STEST(1,SCOMP,STRUE,SSIZE,SFAC) * RETURN END DOUBLE PRECISION FUNCTION SDIFF(SA,SB) * ********************************* SDIFF ************************** * COMPUTES DIFFERENCE OF TWO NUMBERS. C. L. LAWSON, JPL 1974 FEB 15 * * .. Scalar Arguments .. DOUBLE PRECISION SA, SB * .. Executable Statements .. SDIFF = SA - SB RETURN END SUBROUTINE ITEST1(ICOMP,ITRUE) * ********************************* ITEST1 ************************* * * THIS SUBROUTINE COMPARES THE VARIABLES ICOMP AND ITRUE FOR * EQUALITY. * C. L. LAWSON, JPL, 1974 DEC 10 * * .. Parameters .. INTEGER NOUT PARAMETER (NOUT=6) * .. Scalar Arguments .. INTEGER ICOMP, ITRUE * .. Scalars in Common .. INTEGER ICASE, INCX, INCY, N LOGICAL PASS * .. Local Scalars .. INTEGER ID * .. Common blocks .. COMMON /COMBLA/ICASE, N, INCX, INCY, PASS * .. Executable Statements .. * IF (ICOMP.EQ.ITRUE) GO TO 40 * * HERE ICOMP IS NOT EQUAL TO ITRUE. * IF ( .NOT. PASS) GO TO 20 * PRINT FAIL MESSAGE AND HEADER. PASS = .FALSE. WRITE (NOUT,99999) WRITE (NOUT,99998) 20 ID = ICOMP - ITRUE WRITE (NOUT,99997) ICASE, N, INCX, INCY, ICOMP, ITRUE, ID 40 CONTINUE RETURN * 99999 FORMAT (' FAIL') 99998 FORMAT (/' CASE N INCX INCY ', + ' COMP TRUE DIFFERENCE', + /1X) 99997 FORMAT (1X,I4,I3,2I5,2I36,I12) END blis-0.9.0/blastest/src/fortran/dblat2.f000066400000000000000000003333171422157504600200730ustar00rootroot00000000000000*> \brief \b DBLAT2 * * =========== DOCUMENTATION =========== * * Online html documentation available at * http://www.netlib.org/lapack/explore-html/ * * Definition: * =========== * * PROGRAM DBLAT2 * * *> \par Purpose: * ============= *> *> \verbatim *> *> Test program for the DOUBLE PRECISION Level 2 Blas. *> *> The program must be driven by a short data file. The first 18 records *> of the file are read using list-directed input, the last 16 records *> are read using the format ( A6, L2 ). An annotated example of a data *> file can be obtained by deleting the first 3 characters from the *> following 34 lines: *> 'dblat2.out' NAME OF SUMMARY OUTPUT FILE *> 6 UNIT NUMBER OF SUMMARY FILE *> 'DBLAT2.SNAP' NAME OF SNAPSHOT OUTPUT FILE *> -1 UNIT NUMBER OF SNAPSHOT FILE (NOT USED IF .LT. 0) *> F LOGICAL FLAG, T TO REWIND SNAPSHOT FILE AFTER EACH RECORD. *> F LOGICAL FLAG, T TO STOP ON FAILURES. *> T LOGICAL FLAG, T TO TEST ERROR EXITS. *> 16.0 THRESHOLD VALUE OF TEST RATIO *> 6 NUMBER OF VALUES OF N *> 0 1 2 3 5 9 VALUES OF N *> 4 NUMBER OF VALUES OF K *> 0 1 2 4 VALUES OF K *> 4 NUMBER OF VALUES OF INCX AND INCY *> 1 2 -1 -2 VALUES OF INCX AND INCY *> 3 NUMBER OF VALUES OF ALPHA *> 0.0 1.0 0.7 VALUES OF ALPHA *> 3 NUMBER OF VALUES OF BETA *> 0.0 1.0 0.9 VALUES OF BETAC *> DGEMV T PUT F FOR NO TEST. SAME COLUMNS. *> DGBMV T PUT F FOR NO TEST. SAME COLUMNS. *> DSYMV T PUT F FOR NO TEST. SAME COLUMNS. *> DSBMV T PUT F FOR NO TEST. SAME COLUMNS. *> DSPMV T PUT F FOR NO TEST. SAME COLUMNS. *> DTRMV T PUT F FOR NO TEST. SAME COLUMNS. *> DTBMV T PUT F FOR NO TEST. SAME COLUMNS. *> DTPMV T PUT F FOR NO TEST. SAME COLUMNS. *> DTRSV T PUT F FOR NO TEST. SAME COLUMNS. *> DTBSV T PUT F FOR NO TEST. SAME COLUMNS. *> DTPSV T PUT F FOR NO TEST. SAME COLUMNS. *> DGER T PUT F FOR NO TEST. SAME COLUMNS. *> DSYR T PUT F FOR NO TEST. SAME COLUMNS. *> DSPR T PUT F FOR NO TEST. SAME COLUMNS. *> DSYR2 T PUT F FOR NO TEST. SAME COLUMNS. *> DSPR2 T PUT F FOR NO TEST. SAME COLUMNS. *> *> Further Details *> =============== *> *> See: *> *> Dongarra J. J., Du Croz J. J., Hammarling S. and Hanson R. J.. *> An extended set of Fortran Basic Linear Algebra Subprograms. *> *> Technical Memoranda Nos. 41 (revision 3) and 81, Mathematics *> and Computer Science Division, Argonne National Laboratory, *> 9700 South Cass Avenue, Argonne, Illinois 60439, US. *> *> Or *> *> NAG Technical Reports TR3/87 and TR4/87, Numerical Algorithms *> Group Ltd., NAG Central Office, 256 Banbury Road, Oxford *> OX2 7DE, UK, and Numerical Algorithms Group Inc., 1101 31st *> Street, Suite 100, Downers Grove, Illinois 60515-1263, USA. *> *> *> -- Written on 10-August-1987. *> Richard Hanson, Sandia National Labs. *> Jeremy Du Croz, NAG Central Office. *> *> 10-9-00: Change STATUS='NEW' to 'UNKNOWN' so that the testers *> can be run multiple times without deleting generated *> output files (susan) *> \endverbatim * * Authors: * ======== * *> \author Univ. of Tennessee *> \author Univ. of California Berkeley *> \author Univ. of Colorado Denver *> \author NAG Ltd. * *> \date April 2012 * *> \ingroup double_blas_testing * * ===================================================================== PROGRAM DBLAT2 * * -- Reference BLAS test routine (version 3.4.1) -- * -- Reference BLAS is a software package provided by Univ. of Tennessee, -- * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- * April 2012 * * ===================================================================== * * .. Parameters .. INTEGER NIN PARAMETER ( NIN = 5 ) INTEGER NSUBS PARAMETER ( NSUBS = 16 ) DOUBLE PRECISION ZERO, ONE PARAMETER ( ZERO = 0.0D0, ONE = 1.0D0 ) INTEGER NMAX, INCMAX PARAMETER ( NMAX = 65, INCMAX = 2 ) INTEGER NINMAX, NIDMAX, NKBMAX, NALMAX, NBEMAX PARAMETER ( NINMAX = 7, NIDMAX = 9, NKBMAX = 7, $ NALMAX = 7, NBEMAX = 7 ) * .. Local Scalars .. DOUBLE PRECISION EPS, ERR, THRESH INTEGER I, ISNUM, J, N, NALF, NBET, NIDIM, NINC, NKB, $ NOUT, NTRA LOGICAL FATAL, LTESTT, REWI, SAME, SFATAL, TRACE, $ TSTERR CHARACTER*1 TRANS CHARACTER*6 SNAMET CHARACTER*32 SNAPS, SUMMRY * .. Local Arrays .. DOUBLE PRECISION A( NMAX, NMAX ), AA( NMAX*NMAX ), $ ALF( NALMAX ), AS( NMAX*NMAX ), BET( NBEMAX ), $ G( NMAX ), X( NMAX ), XS( NMAX*INCMAX ), $ XX( NMAX*INCMAX ), Y( NMAX ), $ YS( NMAX*INCMAX ), YT( NMAX ), $ YY( NMAX*INCMAX ), Z( 2*NMAX ) INTEGER IDIM( NIDMAX ), INC( NINMAX ), KB( NKBMAX ) LOGICAL LTEST( NSUBS ) CHARACTER*6 SNAMES( NSUBS ) * .. External Functions .. DOUBLE PRECISION DDIFF LOGICAL LDE EXTERNAL DDIFF, LDE * .. External Subroutines .. EXTERNAL DCHK1, DCHK2, DCHK3, DCHK4, DCHK5, DCHK6, $ DCHKE, DMVCH * .. Intrinsic Functions .. INTRINSIC ABS, MAX, MIN * .. Scalars in Common .. INTEGER INFOT, NOUTC LOGICAL LERR, OK CHARACTER*6 SRNAMT * .. Common blocks .. COMMON /INFOC/INFOT, NOUTC, OK, LERR COMMON /SRNAMC/SRNAMT * .. Data statements .. DATA SNAMES/'DGEMV ', 'DGBMV ', 'DSYMV ', 'DSBMV ', $ 'DSPMV ', 'DTRMV ', 'DTBMV ', 'DTPMV ', $ 'DTRSV ', 'DTBSV ', 'DTPSV ', 'DGER ', $ 'DSYR ', 'DSPR ', 'DSYR2 ', 'DSPR2 '/ * .. Executable Statements .. * * Read name and unit number for summary output file and open file. * READ( NIN, FMT = * )SUMMRY READ( NIN, FMT = * )NOUT OPEN( NOUT, FILE = SUMMRY, STATUS = 'UNKNOWN' ) NOUTC = NOUT * * Read name and unit number for snapshot output file and open file. * READ( NIN, FMT = * )SNAPS READ( NIN, FMT = * )NTRA TRACE = NTRA.GE.0 IF( TRACE )THEN OPEN( NTRA, FILE = SNAPS, STATUS = 'UNKNOWN' ) END IF * Read the flag that directs rewinding of the snapshot file. READ( NIN, FMT = * )REWI REWI = REWI.AND.TRACE * Read the flag that directs stopping on any failure. READ( NIN, FMT = * )SFATAL * Read the flag that indicates whether error exits are to be tested. READ( NIN, FMT = * )TSTERR * Read the threshold value of the test ratio READ( NIN, FMT = * )THRESH * * Read and check the parameter values for the tests. * * Values of N READ( NIN, FMT = * )NIDIM IF( NIDIM.LT.1.OR.NIDIM.GT.NIDMAX )THEN WRITE( NOUT, FMT = 9997 )'N', NIDMAX GO TO 230 END IF READ( NIN, FMT = * )( IDIM( I ), I = 1, NIDIM ) DO 10 I = 1, NIDIM IF( IDIM( I ).LT.0.OR.IDIM( I ).GT.NMAX )THEN WRITE( NOUT, FMT = 9996 )NMAX GO TO 230 END IF 10 CONTINUE * Values of K READ( NIN, FMT = * )NKB IF( NKB.LT.1.OR.NKB.GT.NKBMAX )THEN WRITE( NOUT, FMT = 9997 )'K', NKBMAX GO TO 230 END IF READ( NIN, FMT = * )( KB( I ), I = 1, NKB ) DO 20 I = 1, NKB IF( KB( I ).LT.0 )THEN WRITE( NOUT, FMT = 9995 ) GO TO 230 END IF 20 CONTINUE * Values of INCX and INCY READ( NIN, FMT = * )NINC IF( NINC.LT.1.OR.NINC.GT.NINMAX )THEN WRITE( NOUT, FMT = 9997 )'INCX AND INCY', NINMAX GO TO 230 END IF READ( NIN, FMT = * )( INC( I ), I = 1, NINC ) DO 30 I = 1, NINC IF( INC( I ).EQ.0.OR.ABS( INC( I ) ).GT.INCMAX )THEN WRITE( NOUT, FMT = 9994 )INCMAX GO TO 230 END IF 30 CONTINUE * Values of ALPHA READ( NIN, FMT = * )NALF IF( NALF.LT.1.OR.NALF.GT.NALMAX )THEN WRITE( NOUT, FMT = 9997 )'ALPHA', NALMAX GO TO 230 END IF READ( NIN, FMT = * )( ALF( I ), I = 1, NALF ) * Values of BETA READ( NIN, FMT = * )NBET IF( NBET.LT.1.OR.NBET.GT.NBEMAX )THEN WRITE( NOUT, FMT = 9997 )'BETA', NBEMAX GO TO 230 END IF READ( NIN, FMT = * )( BET( I ), I = 1, NBET ) * * Report values of parameters. * WRITE( NOUT, FMT = 9993 ) WRITE( NOUT, FMT = 9992 )( IDIM( I ), I = 1, NIDIM ) WRITE( NOUT, FMT = 9991 )( KB( I ), I = 1, NKB ) WRITE( NOUT, FMT = 9990 )( INC( I ), I = 1, NINC ) WRITE( NOUT, FMT = 9989 )( ALF( I ), I = 1, NALF ) WRITE( NOUT, FMT = 9988 )( BET( I ), I = 1, NBET ) IF( .NOT.TSTERR )THEN WRITE( NOUT, FMT = * ) WRITE( NOUT, FMT = 9980 ) END IF WRITE( NOUT, FMT = * ) WRITE( NOUT, FMT = 9999 )THRESH WRITE( NOUT, FMT = * ) * * Read names of subroutines and flags which indicate * whether they are to be tested. * DO 40 I = 1, NSUBS LTEST( I ) = .FALSE. 40 CONTINUE 50 READ( NIN, FMT = 9984, END = 80 )SNAMET, LTESTT DO 60 I = 1, NSUBS IF( SNAMET.EQ.SNAMES( I ) ) $ GO TO 70 60 CONTINUE WRITE( NOUT, FMT = 9986 )SNAMET STOP 70 LTEST( I ) = LTESTT GO TO 50 * 80 CONTINUE CLOSE ( NIN ) * * Compute EPS (the machine precision). * EPS = EPSILON(ZERO) WRITE( NOUT, FMT = 9998 )EPS * * Check the reliability of DMVCH using exact data. * N = MIN( 32, NMAX ) DO 120 J = 1, N DO 110 I = 1, N A( I, J ) = MAX( I - J + 1, 0 ) 110 CONTINUE X( J ) = J Y( J ) = ZERO 120 CONTINUE DO 130 J = 1, N YY( J ) = J*( ( J + 1 )*J )/2 - ( ( J + 1 )*J*( J - 1 ) )/3 130 CONTINUE * YY holds the exact result. On exit from DMVCH YT holds * the result computed by DMVCH. TRANS = 'N' CALL DMVCH( TRANS, N, N, ONE, A, NMAX, X, 1, ZERO, Y, 1, YT, G, $ YY, EPS, ERR, FATAL, NOUT, .TRUE. ) SAME = LDE( YY, YT, N ) IF( .NOT.SAME.OR.ERR.NE.ZERO )THEN WRITE( NOUT, FMT = 9985 )TRANS, SAME, ERR STOP END IF TRANS = 'T' CALL DMVCH( TRANS, N, N, ONE, A, NMAX, X, -1, ZERO, Y, -1, YT, G, $ YY, EPS, ERR, FATAL, NOUT, .TRUE. ) SAME = LDE( YY, YT, N ) IF( .NOT.SAME.OR.ERR.NE.ZERO )THEN WRITE( NOUT, FMT = 9985 )TRANS, SAME, ERR STOP END IF * * Test each subroutine in turn. * DO 210 ISNUM = 1, NSUBS WRITE( NOUT, FMT = * ) IF( .NOT.LTEST( ISNUM ) )THEN * Subprogram is not to be tested. WRITE( NOUT, FMT = 9983 )SNAMES( ISNUM ) ELSE SRNAMT = SNAMES( ISNUM ) * Test error exits. IF( TSTERR )THEN CALL DCHKE( ISNUM, SNAMES( ISNUM ), NOUT ) WRITE( NOUT, FMT = * ) END IF * Test computations. INFOT = 0 OK = .TRUE. FATAL = .FALSE. GO TO ( 140, 140, 150, 150, 150, 160, 160, $ 160, 160, 160, 160, 170, 180, 180, $ 190, 190 )ISNUM * Test DGEMV, 01, and DGBMV, 02. 140 CALL DCHK1( SNAMES( ISNUM ), EPS, THRESH, NOUT, NTRA, TRACE, $ REWI, FATAL, NIDIM, IDIM, NKB, KB, NALF, ALF, $ NBET, BET, NINC, INC, NMAX, INCMAX, A, AA, AS, $ X, XX, XS, Y, YY, YS, YT, G ) GO TO 200 * Test DSYMV, 03, DSBMV, 04, and DSPMV, 05. 150 CALL DCHK2( SNAMES( ISNUM ), EPS, THRESH, NOUT, NTRA, TRACE, $ REWI, FATAL, NIDIM, IDIM, NKB, KB, NALF, ALF, $ NBET, BET, NINC, INC, NMAX, INCMAX, A, AA, AS, $ X, XX, XS, Y, YY, YS, YT, G ) GO TO 200 * Test DTRMV, 06, DTBMV, 07, DTPMV, 08, * DTRSV, 09, DTBSV, 10, and DTPSV, 11. 160 CALL DCHK3( SNAMES( ISNUM ), EPS, THRESH, NOUT, NTRA, TRACE, $ REWI, FATAL, NIDIM, IDIM, NKB, KB, NINC, INC, $ NMAX, INCMAX, A, AA, AS, Y, YY, YS, YT, G, Z ) GO TO 200 * Test DGER, 12. 170 CALL DCHK4( SNAMES( ISNUM ), EPS, THRESH, NOUT, NTRA, TRACE, $ REWI, FATAL, NIDIM, IDIM, NALF, ALF, NINC, INC, $ NMAX, INCMAX, A, AA, AS, X, XX, XS, Y, YY, YS, $ YT, G, Z ) GO TO 200 * Test DSYR, 13, and DSPR, 14. 180 CALL DCHK5( SNAMES( ISNUM ), EPS, THRESH, NOUT, NTRA, TRACE, $ REWI, FATAL, NIDIM, IDIM, NALF, ALF, NINC, INC, $ NMAX, INCMAX, A, AA, AS, X, XX, XS, Y, YY, YS, $ YT, G, Z ) GO TO 200 * Test DSYR2, 15, and DSPR2, 16. 190 CALL DCHK6( SNAMES( ISNUM ), EPS, THRESH, NOUT, NTRA, TRACE, $ REWI, FATAL, NIDIM, IDIM, NALF, ALF, NINC, INC, $ NMAX, INCMAX, A, AA, AS, X, XX, XS, Y, YY, YS, $ YT, G, Z ) * 200 IF( FATAL.AND.SFATAL ) $ GO TO 220 END IF 210 CONTINUE WRITE( NOUT, FMT = 9982 ) GO TO 240 * 220 CONTINUE WRITE( NOUT, FMT = 9981 ) GO TO 240 * 230 CONTINUE WRITE( NOUT, FMT = 9987 ) * 240 CONTINUE IF( TRACE ) $ CLOSE ( NTRA ) CLOSE ( NOUT ) STOP * 9999 FORMAT( ' ROUTINES PASS COMPUTATIONAL TESTS IF TEST RATIO IS LES', $ 'S THAN', F8.2 ) 9998 FORMAT( ' RELATIVE MACHINE PRECISION IS TAKEN TO BE', 1P, D9.1 ) 9997 FORMAT( ' NUMBER OF VALUES OF ', A, ' IS LESS THAN 1 OR GREATER ', $ 'THAN ', I2 ) 9996 FORMAT( ' VALUE OF N IS LESS THAN 0 OR GREATER THAN ', I2 ) 9995 FORMAT( ' VALUE OF K IS LESS THAN 0' ) 9994 FORMAT( ' ABSOLUTE VALUE OF INCX OR INCY IS 0 OR GREATER THAN ', $ I2 ) 9993 FORMAT( ' TESTS OF THE DOUBLE PRECISION LEVEL 2 BLAS', //' THE F', $ 'OLLOWING PARAMETER VALUES WILL BE USED:' ) 9992 FORMAT( ' FOR N ', 9I6 ) 9991 FORMAT( ' FOR K ', 7I6 ) 9990 FORMAT( ' FOR INCX AND INCY ', 7I6 ) 9989 FORMAT( ' FOR ALPHA ', 7F6.1 ) 9988 FORMAT( ' FOR BETA ', 7F6.1 ) 9987 FORMAT( ' AMEND DATA FILE OR INCREASE ARRAY SIZES IN PROGRAM', $ /' ******* TESTS ABANDONED *******' ) 9986 FORMAT( ' SUBPROGRAM NAME ', A6, ' NOT RECOGNIZED', /' ******* T', $ 'ESTS ABANDONED *******' ) 9985 FORMAT( ' ERROR IN DMVCH - IN-LINE DOT PRODUCTS ARE BEING EVALU', $ 'ATED WRONGLY.', /' DMVCH WAS CALLED WITH TRANS = ', A1, $ ' AND RETURNED SAME = ', L1, ' AND ERR = ', F12.3, '.', / $ ' THIS MAY BE DUE TO FAULTS IN THE ARITHMETIC OR THE COMPILER.' $ , /' ******* TESTS ABANDONED *******' ) 9984 FORMAT( A6, L2 ) 9983 FORMAT( 1X, A6, ' WAS NOT TESTED' ) 9982 FORMAT( /' END OF TESTS' ) 9981 FORMAT( /' ******* FATAL ERROR - TESTS ABANDONED *******' ) 9980 FORMAT( ' ERROR-EXITS WILL NOT BE TESTED' ) * * End of DBLAT2. * END SUBROUTINE DCHK1( SNAME, EPS, THRESH, NOUT, NTRA, TRACE, REWI, $ FATAL, NIDIM, IDIM, NKB, KB, NALF, ALF, NBET, $ BET, NINC, INC, NMAX, INCMAX, A, AA, AS, X, XX, $ XS, Y, YY, YS, YT, G ) * * Tests DGEMV and DGBMV. * * Auxiliary routine for test program for Level 2 Blas. * * -- Written on 10-August-1987. * Richard Hanson, Sandia National Labs. * Jeremy Du Croz, NAG Central Office. * * .. Parameters .. DOUBLE PRECISION ZERO, HALF PARAMETER ( ZERO = 0.0D0, HALF = 0.5D0 ) * .. Scalar Arguments .. DOUBLE PRECISION EPS, THRESH INTEGER INCMAX, NALF, NBET, NIDIM, NINC, NKB, NMAX, $ NOUT, NTRA LOGICAL FATAL, REWI, TRACE CHARACTER*6 SNAME * .. Array Arguments .. DOUBLE PRECISION A( NMAX, NMAX ), AA( NMAX*NMAX ), ALF( NALF ), $ AS( NMAX*NMAX ), BET( NBET ), G( NMAX ), $ X( NMAX ), XS( NMAX*INCMAX ), $ XX( NMAX*INCMAX ), Y( NMAX ), $ YS( NMAX*INCMAX ), YT( NMAX ), $ YY( NMAX*INCMAX ) INTEGER IDIM( NIDIM ), INC( NINC ), KB( NKB ) * .. Local Scalars .. DOUBLE PRECISION ALPHA, ALS, BETA, BLS, ERR, ERRMAX, TRANSL INTEGER I, IA, IB, IC, IKU, IM, IN, INCX, INCXS, INCY, $ INCYS, IX, IY, KL, KLS, KU, KUS, LAA, LDA, $ LDAS, LX, LY, M, ML, MS, N, NARGS, NC, ND, NK, $ NL, NS LOGICAL BANDED, FULL, NULL, RESET, SAME, TRAN CHARACTER*1 TRANS, TRANSS CHARACTER*3 ICH * .. Local Arrays .. LOGICAL ISAME( 13 ) * .. External Functions .. LOGICAL LDE, LDERES EXTERNAL LDE, LDERES * .. External Subroutines .. EXTERNAL DGBMV, DGEMV, DMAKE, DMVCH * .. Intrinsic Functions .. INTRINSIC ABS, MAX, MIN * .. Scalars in Common .. INTEGER INFOT, NOUTC LOGICAL LERR, OK * .. Common blocks .. COMMON /INFOC/INFOT, NOUTC, OK, LERR * .. Data statements .. DATA ICH/'NTC'/ * .. Executable Statements .. FULL = SNAME( 3: 3 ).EQ.'E' BANDED = SNAME( 3: 3 ).EQ.'B' * Define the number of arguments. IF( FULL )THEN NARGS = 11 ELSE IF( BANDED )THEN NARGS = 13 END IF * NC = 0 RESET = .TRUE. ERRMAX = ZERO * DO 120 IN = 1, NIDIM N = IDIM( IN ) ND = N/2 + 1 * DO 110 IM = 1, 2 IF( IM.EQ.1 ) $ M = MAX( N - ND, 0 ) IF( IM.EQ.2 ) $ M = MIN( N + ND, NMAX ) * IF( BANDED )THEN NK = NKB ELSE NK = 1 END IF DO 100 IKU = 1, NK IF( BANDED )THEN KU = KB( IKU ) KL = MAX( KU - 1, 0 ) ELSE KU = N - 1 KL = M - 1 END IF * Set LDA to 1 more than minimum value if room. IF( BANDED )THEN LDA = KL + KU + 1 ELSE LDA = M END IF IF( LDA.LT.NMAX ) $ LDA = LDA + 1 * Skip tests if not enough room. IF( LDA.GT.NMAX ) $ GO TO 100 LAA = LDA*N NULL = N.LE.0.OR.M.LE.0 * * Generate the matrix A. * TRANSL = ZERO CALL DMAKE( SNAME( 2: 3 ), ' ', ' ', M, N, A, NMAX, AA, $ LDA, KL, KU, RESET, TRANSL ) * DO 90 IC = 1, 3 TRANS = ICH( IC: IC ) TRAN = TRANS.EQ.'T'.OR.TRANS.EQ.'C' * IF( TRAN )THEN ML = N NL = M ELSE ML = M NL = N END IF * DO 80 IX = 1, NINC INCX = INC( IX ) LX = ABS( INCX )*NL * * Generate the vector X. * TRANSL = HALF CALL DMAKE( 'GE', ' ', ' ', 1, NL, X, 1, XX, $ ABS( INCX ), 0, NL - 1, RESET, TRANSL ) IF( NL.GT.1 )THEN X( NL/2 ) = ZERO XX( 1 + ABS( INCX )*( NL/2 - 1 ) ) = ZERO END IF * DO 70 IY = 1, NINC INCY = INC( IY ) LY = ABS( INCY )*ML * DO 60 IA = 1, NALF ALPHA = ALF( IA ) * DO 50 IB = 1, NBET BETA = BET( IB ) * * Generate the vector Y. * TRANSL = ZERO CALL DMAKE( 'GE', ' ', ' ', 1, ML, Y, 1, $ YY, ABS( INCY ), 0, ML - 1, $ RESET, TRANSL ) * NC = NC + 1 * * Save every datum before calling the * subroutine. * TRANSS = TRANS MS = M NS = N KLS = KL KUS = KU ALS = ALPHA DO 10 I = 1, LAA AS( I ) = AA( I ) 10 CONTINUE LDAS = LDA DO 20 I = 1, LX XS( I ) = XX( I ) 20 CONTINUE INCXS = INCX BLS = BETA DO 30 I = 1, LY YS( I ) = YY( I ) 30 CONTINUE INCYS = INCY * * Call the subroutine. * IF( FULL )THEN IF( TRACE ) $ WRITE( NTRA, FMT = 9994 )NC, SNAME, $ TRANS, M, N, ALPHA, LDA, INCX, BETA, $ INCY IF( REWI ) $ REWIND NTRA CALL DGEMV( TRANS, M, N, ALPHA, AA, $ LDA, XX, INCX, BETA, YY, $ INCY ) ELSE IF( BANDED )THEN IF( TRACE ) $ WRITE( NTRA, FMT = 9995 )NC, SNAME, $ TRANS, M, N, KL, KU, ALPHA, LDA, $ INCX, BETA, INCY IF( REWI ) $ REWIND NTRA CALL DGBMV( TRANS, M, N, KL, KU, ALPHA, $ AA, LDA, XX, INCX, BETA, $ YY, INCY ) END IF * * Check if error-exit was taken incorrectly. * IF( .NOT.OK )THEN WRITE( NOUT, FMT = 9993 ) FATAL = .TRUE. GO TO 130 END IF * * See what data changed inside subroutines. * ISAME( 1 ) = TRANS.EQ.TRANSS ISAME( 2 ) = MS.EQ.M ISAME( 3 ) = NS.EQ.N IF( FULL )THEN ISAME( 4 ) = ALS.EQ.ALPHA ISAME( 5 ) = LDE( AS, AA, LAA ) ISAME( 6 ) = LDAS.EQ.LDA ISAME( 7 ) = LDE( XS, XX, LX ) ISAME( 8 ) = INCXS.EQ.INCX ISAME( 9 ) = BLS.EQ.BETA IF( NULL )THEN ISAME( 10 ) = LDE( YS, YY, LY ) ELSE ISAME( 10 ) = LDERES( 'GE', ' ', 1, $ ML, YS, YY, $ ABS( INCY ) ) END IF ISAME( 11 ) = INCYS.EQ.INCY ELSE IF( BANDED )THEN ISAME( 4 ) = KLS.EQ.KL ISAME( 5 ) = KUS.EQ.KU ISAME( 6 ) = ALS.EQ.ALPHA ISAME( 7 ) = LDE( AS, AA, LAA ) ISAME( 8 ) = LDAS.EQ.LDA ISAME( 9 ) = LDE( XS, XX, LX ) ISAME( 10 ) = INCXS.EQ.INCX ISAME( 11 ) = BLS.EQ.BETA IF( NULL )THEN ISAME( 12 ) = LDE( YS, YY, LY ) ELSE ISAME( 12 ) = LDERES( 'GE', ' ', 1, $ ML, YS, YY, $ ABS( INCY ) ) END IF ISAME( 13 ) = INCYS.EQ.INCY END IF * * If data was incorrectly changed, report * and return. * SAME = .TRUE. DO 40 I = 1, NARGS SAME = SAME.AND.ISAME( I ) IF( .NOT.ISAME( I ) ) $ WRITE( NOUT, FMT = 9998 )I 40 CONTINUE IF( .NOT.SAME )THEN FATAL = .TRUE. GO TO 130 END IF * IF( .NOT.NULL )THEN * * Check the result. * CALL DMVCH( TRANS, M, N, ALPHA, A, $ NMAX, X, INCX, BETA, Y, $ INCY, YT, G, YY, EPS, ERR, $ FATAL, NOUT, .TRUE. ) ERRMAX = MAX( ERRMAX, ERR ) * If got really bad answer, report and * return. IF( FATAL ) $ GO TO 130 ELSE * Avoid repeating tests with M.le.0 or * N.le.0. GO TO 110 END IF * 50 CONTINUE * 60 CONTINUE * 70 CONTINUE * 80 CONTINUE * 90 CONTINUE * 100 CONTINUE * 110 CONTINUE * 120 CONTINUE * * Report result. * IF( ERRMAX.LT.THRESH )THEN WRITE( NOUT, FMT = 9999 )SNAME, NC ELSE WRITE( NOUT, FMT = 9997 )SNAME, NC, ERRMAX END IF GO TO 140 * 130 CONTINUE WRITE( NOUT, FMT = 9996 )SNAME IF( FULL )THEN WRITE( NOUT, FMT = 9994 )NC, SNAME, TRANS, M, N, ALPHA, LDA, $ INCX, BETA, INCY ELSE IF( BANDED )THEN WRITE( NOUT, FMT = 9995 )NC, SNAME, TRANS, M, N, KL, KU, $ ALPHA, LDA, INCX, BETA, INCY END IF * 140 CONTINUE RETURN * 9999 FORMAT( ' ', A6, ' PASSED THE COMPUTATIONAL TESTS (', I6, ' CALL', $ 'S)' ) 9998 FORMAT( ' ******* FATAL ERROR - PARAMETER NUMBER ', I2, ' WAS CH', $ 'ANGED INCORRECTLY *******' ) 9997 FORMAT( ' ', A6, ' COMPLETED THE COMPUTATIONAL TESTS (', I6, ' C', $ 'ALLS)', /' ******* BUT WITH MAXIMUM TEST RATIO', F8.2, $ ' - SUSPECT *******' ) 9996 FORMAT( ' ******* ', A6, ' FAILED ON CALL NUMBER:' ) 9995 FORMAT( 1X, I6, ': ', A6, '(''', A1, ''',', 4( I3, ',' ), F4.1, $ ', A,', I3, ', X,', I2, ',', F4.1, ', Y,', I2, ') .' ) 9994 FORMAT( 1X, I6, ': ', A6, '(''', A1, ''',', 2( I3, ',' ), F4.1, $ ', A,', I3, ', X,', I2, ',', F4.1, ', Y,', I2, $ ') .' ) 9993 FORMAT( ' ******* FATAL ERROR - ERROR-EXIT TAKEN ON VALID CALL *', $ '******' ) * * End of DCHK1. * END SUBROUTINE DCHK2( SNAME, EPS, THRESH, NOUT, NTRA, TRACE, REWI, $ FATAL, NIDIM, IDIM, NKB, KB, NALF, ALF, NBET, $ BET, NINC, INC, NMAX, INCMAX, A, AA, AS, X, XX, $ XS, Y, YY, YS, YT, G ) * * Tests DSYMV, DSBMV and DSPMV. * * Auxiliary routine for test program for Level 2 Blas. * * -- Written on 10-August-1987. * Richard Hanson, Sandia National Labs. * Jeremy Du Croz, NAG Central Office. * * .. Parameters .. DOUBLE PRECISION ZERO, HALF PARAMETER ( ZERO = 0.0D0, HALF = 0.5D0 ) * .. Scalar Arguments .. DOUBLE PRECISION EPS, THRESH INTEGER INCMAX, NALF, NBET, NIDIM, NINC, NKB, NMAX, $ NOUT, NTRA LOGICAL FATAL, REWI, TRACE CHARACTER*6 SNAME * .. Array Arguments .. DOUBLE PRECISION A( NMAX, NMAX ), AA( NMAX*NMAX ), ALF( NALF ), $ AS( NMAX*NMAX ), BET( NBET ), G( NMAX ), $ X( NMAX ), XS( NMAX*INCMAX ), $ XX( NMAX*INCMAX ), Y( NMAX ), $ YS( NMAX*INCMAX ), YT( NMAX ), $ YY( NMAX*INCMAX ) INTEGER IDIM( NIDIM ), INC( NINC ), KB( NKB ) * .. Local Scalars .. DOUBLE PRECISION ALPHA, ALS, BETA, BLS, ERR, ERRMAX, TRANSL INTEGER I, IA, IB, IC, IK, IN, INCX, INCXS, INCY, $ INCYS, IX, IY, K, KS, LAA, LDA, LDAS, LX, LY, $ N, NARGS, NC, NK, NS LOGICAL BANDED, FULL, NULL, PACKED, RESET, SAME CHARACTER*1 UPLO, UPLOS CHARACTER*2 ICH * .. Local Arrays .. LOGICAL ISAME( 13 ) * .. External Functions .. LOGICAL LDE, LDERES EXTERNAL LDE, LDERES * .. External Subroutines .. EXTERNAL DMAKE, DMVCH, DSBMV, DSPMV, DSYMV * .. Intrinsic Functions .. INTRINSIC ABS, MAX * .. Scalars in Common .. INTEGER INFOT, NOUTC LOGICAL LERR, OK * .. Common blocks .. COMMON /INFOC/INFOT, NOUTC, OK, LERR * .. Data statements .. DATA ICH/'UL'/ * .. Executable Statements .. FULL = SNAME( 3: 3 ).EQ.'Y' BANDED = SNAME( 3: 3 ).EQ.'B' PACKED = SNAME( 3: 3 ).EQ.'P' * Define the number of arguments. IF( FULL )THEN NARGS = 10 ELSE IF( BANDED )THEN NARGS = 11 ELSE IF( PACKED )THEN NARGS = 9 END IF * NC = 0 RESET = .TRUE. ERRMAX = ZERO * DO 110 IN = 1, NIDIM N = IDIM( IN ) * IF( BANDED )THEN NK = NKB ELSE NK = 1 END IF DO 100 IK = 1, NK IF( BANDED )THEN K = KB( IK ) ELSE K = N - 1 END IF * Set LDA to 1 more than minimum value if room. IF( BANDED )THEN LDA = K + 1 ELSE LDA = N END IF IF( LDA.LT.NMAX ) $ LDA = LDA + 1 * Skip tests if not enough room. IF( LDA.GT.NMAX ) $ GO TO 100 IF( PACKED )THEN LAA = ( N*( N + 1 ) )/2 ELSE LAA = LDA*N END IF NULL = N.LE.0 * DO 90 IC = 1, 2 UPLO = ICH( IC: IC ) * * Generate the matrix A. * TRANSL = ZERO CALL DMAKE( SNAME( 2: 3 ), UPLO, ' ', N, N, A, NMAX, AA, $ LDA, K, K, RESET, TRANSL ) * DO 80 IX = 1, NINC INCX = INC( IX ) LX = ABS( INCX )*N * * Generate the vector X. * TRANSL = HALF CALL DMAKE( 'GE', ' ', ' ', 1, N, X, 1, XX, $ ABS( INCX ), 0, N - 1, RESET, TRANSL ) IF( N.GT.1 )THEN X( N/2 ) = ZERO XX( 1 + ABS( INCX )*( N/2 - 1 ) ) = ZERO END IF * DO 70 IY = 1, NINC INCY = INC( IY ) LY = ABS( INCY )*N * DO 60 IA = 1, NALF ALPHA = ALF( IA ) * DO 50 IB = 1, NBET BETA = BET( IB ) * * Generate the vector Y. * TRANSL = ZERO CALL DMAKE( 'GE', ' ', ' ', 1, N, Y, 1, YY, $ ABS( INCY ), 0, N - 1, RESET, $ TRANSL ) * NC = NC + 1 * * Save every datum before calling the * subroutine. * UPLOS = UPLO NS = N KS = K ALS = ALPHA DO 10 I = 1, LAA AS( I ) = AA( I ) 10 CONTINUE LDAS = LDA DO 20 I = 1, LX XS( I ) = XX( I ) 20 CONTINUE INCXS = INCX BLS = BETA DO 30 I = 1, LY YS( I ) = YY( I ) 30 CONTINUE INCYS = INCY * * Call the subroutine. * IF( FULL )THEN IF( TRACE ) $ WRITE( NTRA, FMT = 9993 )NC, SNAME, $ UPLO, N, ALPHA, LDA, INCX, BETA, INCY IF( REWI ) $ REWIND NTRA CALL DSYMV( UPLO, N, ALPHA, AA, LDA, XX, $ INCX, BETA, YY, INCY ) ELSE IF( BANDED )THEN IF( TRACE ) $ WRITE( NTRA, FMT = 9994 )NC, SNAME, $ UPLO, N, K, ALPHA, LDA, INCX, BETA, $ INCY IF( REWI ) $ REWIND NTRA CALL DSBMV( UPLO, N, K, ALPHA, AA, LDA, $ XX, INCX, BETA, YY, INCY ) ELSE IF( PACKED )THEN IF( TRACE ) $ WRITE( NTRA, FMT = 9995 )NC, SNAME, $ UPLO, N, ALPHA, INCX, BETA, INCY IF( REWI ) $ REWIND NTRA CALL DSPMV( UPLO, N, ALPHA, AA, XX, INCX, $ BETA, YY, INCY ) END IF * * Check if error-exit was taken incorrectly. * IF( .NOT.OK )THEN WRITE( NOUT, FMT = 9992 ) FATAL = .TRUE. GO TO 120 END IF * * See what data changed inside subroutines. * ISAME( 1 ) = UPLO.EQ.UPLOS ISAME( 2 ) = NS.EQ.N IF( FULL )THEN ISAME( 3 ) = ALS.EQ.ALPHA ISAME( 4 ) = LDE( AS, AA, LAA ) ISAME( 5 ) = LDAS.EQ.LDA ISAME( 6 ) = LDE( XS, XX, LX ) ISAME( 7 ) = INCXS.EQ.INCX ISAME( 8 ) = BLS.EQ.BETA IF( NULL )THEN ISAME( 9 ) = LDE( YS, YY, LY ) ELSE ISAME( 9 ) = LDERES( 'GE', ' ', 1, N, $ YS, YY, ABS( INCY ) ) END IF ISAME( 10 ) = INCYS.EQ.INCY ELSE IF( BANDED )THEN ISAME( 3 ) = KS.EQ.K ISAME( 4 ) = ALS.EQ.ALPHA ISAME( 5 ) = LDE( AS, AA, LAA ) ISAME( 6 ) = LDAS.EQ.LDA ISAME( 7 ) = LDE( XS, XX, LX ) ISAME( 8 ) = INCXS.EQ.INCX ISAME( 9 ) = BLS.EQ.BETA IF( NULL )THEN ISAME( 10 ) = LDE( YS, YY, LY ) ELSE ISAME( 10 ) = LDERES( 'GE', ' ', 1, N, $ YS, YY, ABS( INCY ) ) END IF ISAME( 11 ) = INCYS.EQ.INCY ELSE IF( PACKED )THEN ISAME( 3 ) = ALS.EQ.ALPHA ISAME( 4 ) = LDE( AS, AA, LAA ) ISAME( 5 ) = LDE( XS, XX, LX ) ISAME( 6 ) = INCXS.EQ.INCX ISAME( 7 ) = BLS.EQ.BETA IF( NULL )THEN ISAME( 8 ) = LDE( YS, YY, LY ) ELSE ISAME( 8 ) = LDERES( 'GE', ' ', 1, N, $ YS, YY, ABS( INCY ) ) END IF ISAME( 9 ) = INCYS.EQ.INCY END IF * * If data was incorrectly changed, report and * return. * SAME = .TRUE. DO 40 I = 1, NARGS SAME = SAME.AND.ISAME( I ) IF( .NOT.ISAME( I ) ) $ WRITE( NOUT, FMT = 9998 )I 40 CONTINUE IF( .NOT.SAME )THEN FATAL = .TRUE. GO TO 120 END IF * IF( .NOT.NULL )THEN * * Check the result. * CALL DMVCH( 'N', N, N, ALPHA, A, NMAX, X, $ INCX, BETA, Y, INCY, YT, G, $ YY, EPS, ERR, FATAL, NOUT, $ .TRUE. ) ERRMAX = MAX( ERRMAX, ERR ) * If got really bad answer, report and * return. IF( FATAL ) $ GO TO 120 ELSE * Avoid repeating tests with N.le.0 GO TO 110 END IF * 50 CONTINUE * 60 CONTINUE * 70 CONTINUE * 80 CONTINUE * 90 CONTINUE * 100 CONTINUE * 110 CONTINUE * * Report result. * IF( ERRMAX.LT.THRESH )THEN WRITE( NOUT, FMT = 9999 )SNAME, NC ELSE WRITE( NOUT, FMT = 9997 )SNAME, NC, ERRMAX END IF GO TO 130 * 120 CONTINUE WRITE( NOUT, FMT = 9996 )SNAME IF( FULL )THEN WRITE( NOUT, FMT = 9993 )NC, SNAME, UPLO, N, ALPHA, LDA, INCX, $ BETA, INCY ELSE IF( BANDED )THEN WRITE( NOUT, FMT = 9994 )NC, SNAME, UPLO, N, K, ALPHA, LDA, $ INCX, BETA, INCY ELSE IF( PACKED )THEN WRITE( NOUT, FMT = 9995 )NC, SNAME, UPLO, N, ALPHA, INCX, $ BETA, INCY END IF * 130 CONTINUE RETURN * 9999 FORMAT( ' ', A6, ' PASSED THE COMPUTATIONAL TESTS (', I6, ' CALL', $ 'S)' ) 9998 FORMAT( ' ******* FATAL ERROR - PARAMETER NUMBER ', I2, ' WAS CH', $ 'ANGED INCORRECTLY *******' ) 9997 FORMAT( ' ', A6, ' COMPLETED THE COMPUTATIONAL TESTS (', I6, ' C', $ 'ALLS)', /' ******* BUT WITH MAXIMUM TEST RATIO', F8.2, $ ' - SUSPECT *******' ) 9996 FORMAT( ' ******* ', A6, ' FAILED ON CALL NUMBER:' ) 9995 FORMAT( 1X, I6, ': ', A6, '(''', A1, ''',', I3, ',', F4.1, ', AP', $ ', X,', I2, ',', F4.1, ', Y,', I2, ') .' ) 9994 FORMAT( 1X, I6, ': ', A6, '(''', A1, ''',', 2( I3, ',' ), F4.1, $ ', A,', I3, ', X,', I2, ',', F4.1, ', Y,', I2, $ ') .' ) 9993 FORMAT( 1X, I6, ': ', A6, '(''', A1, ''',', I3, ',', F4.1, ', A,', $ I3, ', X,', I2, ',', F4.1, ', Y,', I2, ') .' ) 9992 FORMAT( ' ******* FATAL ERROR - ERROR-EXIT TAKEN ON VALID CALL *', $ '******' ) * * End of DCHK2. * END SUBROUTINE DCHK3( SNAME, EPS, THRESH, NOUT, NTRA, TRACE, REWI, $ FATAL, NIDIM, IDIM, NKB, KB, NINC, INC, NMAX, $ INCMAX, A, AA, AS, X, XX, XS, XT, G, Z ) * * Tests DTRMV, DTBMV, DTPMV, DTRSV, DTBSV and DTPSV. * * Auxiliary routine for test program for Level 2 Blas. * * -- Written on 10-August-1987. * Richard Hanson, Sandia National Labs. * Jeremy Du Croz, NAG Central Office. * * .. Parameters .. DOUBLE PRECISION ZERO, HALF, ONE PARAMETER ( ZERO = 0.0D0, HALF = 0.5D0, ONE = 1.0D0 ) * .. Scalar Arguments .. DOUBLE PRECISION EPS, THRESH INTEGER INCMAX, NIDIM, NINC, NKB, NMAX, NOUT, NTRA LOGICAL FATAL, REWI, TRACE CHARACTER*6 SNAME * .. Array Arguments .. DOUBLE PRECISION A( NMAX, NMAX ), AA( NMAX*NMAX ), $ AS( NMAX*NMAX ), G( NMAX ), X( NMAX ), $ XS( NMAX*INCMAX ), XT( NMAX ), $ XX( NMAX*INCMAX ), Z( NMAX ) INTEGER IDIM( NIDIM ), INC( NINC ), KB( NKB ) * .. Local Scalars .. DOUBLE PRECISION ERR, ERRMAX, TRANSL INTEGER I, ICD, ICT, ICU, IK, IN, INCX, INCXS, IX, K, $ KS, LAA, LDA, LDAS, LX, N, NARGS, NC, NK, NS LOGICAL BANDED, FULL, NULL, PACKED, RESET, SAME CHARACTER*1 DIAG, DIAGS, TRANS, TRANSS, UPLO, UPLOS CHARACTER*2 ICHD, ICHU CHARACTER*3 ICHT * .. Local Arrays .. LOGICAL ISAME( 13 ) * .. External Functions .. LOGICAL LDE, LDERES EXTERNAL LDE, LDERES * .. External Subroutines .. EXTERNAL DMAKE, DMVCH, DTBMV, DTBSV, DTPMV, DTPSV, $ DTRMV, DTRSV * .. Intrinsic Functions .. INTRINSIC ABS, MAX * .. Scalars in Common .. INTEGER INFOT, NOUTC LOGICAL LERR, OK * .. Common blocks .. COMMON /INFOC/INFOT, NOUTC, OK, LERR * .. Data statements .. DATA ICHU/'UL'/, ICHT/'NTC'/, ICHD/'UN'/ * .. Executable Statements .. FULL = SNAME( 3: 3 ).EQ.'R' BANDED = SNAME( 3: 3 ).EQ.'B' PACKED = SNAME( 3: 3 ).EQ.'P' * Define the number of arguments. IF( FULL )THEN NARGS = 8 ELSE IF( BANDED )THEN NARGS = 9 ELSE IF( PACKED )THEN NARGS = 7 END IF * NC = 0 RESET = .TRUE. ERRMAX = ZERO * Set up zero vector for DMVCH. DO 10 I = 1, NMAX Z( I ) = ZERO 10 CONTINUE * DO 110 IN = 1, NIDIM N = IDIM( IN ) * IF( BANDED )THEN NK = NKB ELSE NK = 1 END IF DO 100 IK = 1, NK IF( BANDED )THEN K = KB( IK ) ELSE K = N - 1 END IF * Set LDA to 1 more than minimum value if room. IF( BANDED )THEN LDA = K + 1 ELSE LDA = N END IF IF( LDA.LT.NMAX ) $ LDA = LDA + 1 * Skip tests if not enough room. IF( LDA.GT.NMAX ) $ GO TO 100 IF( PACKED )THEN LAA = ( N*( N + 1 ) )/2 ELSE LAA = LDA*N END IF NULL = N.LE.0 * DO 90 ICU = 1, 2 UPLO = ICHU( ICU: ICU ) * DO 80 ICT = 1, 3 TRANS = ICHT( ICT: ICT ) * DO 70 ICD = 1, 2 DIAG = ICHD( ICD: ICD ) * * Generate the matrix A. * TRANSL = ZERO CALL DMAKE( SNAME( 2: 3 ), UPLO, DIAG, N, N, A, $ NMAX, AA, LDA, K, K, RESET, TRANSL ) * DO 60 IX = 1, NINC INCX = INC( IX ) LX = ABS( INCX )*N * * Generate the vector X. * TRANSL = HALF CALL DMAKE( 'GE', ' ', ' ', 1, N, X, 1, XX, $ ABS( INCX ), 0, N - 1, RESET, $ TRANSL ) IF( N.GT.1 )THEN X( N/2 ) = ZERO XX( 1 + ABS( INCX )*( N/2 - 1 ) ) = ZERO END IF * NC = NC + 1 * * Save every datum before calling the subroutine. * UPLOS = UPLO TRANSS = TRANS DIAGS = DIAG NS = N KS = K DO 20 I = 1, LAA AS( I ) = AA( I ) 20 CONTINUE LDAS = LDA DO 30 I = 1, LX XS( I ) = XX( I ) 30 CONTINUE INCXS = INCX * * Call the subroutine. * IF( SNAME( 4: 5 ).EQ.'MV' )THEN IF( FULL )THEN IF( TRACE ) $ WRITE( NTRA, FMT = 9993 )NC, SNAME, $ UPLO, TRANS, DIAG, N, LDA, INCX IF( REWI ) $ REWIND NTRA CALL DTRMV( UPLO, TRANS, DIAG, N, AA, LDA, $ XX, INCX ) ELSE IF( BANDED )THEN IF( TRACE ) $ WRITE( NTRA, FMT = 9994 )NC, SNAME, $ UPLO, TRANS, DIAG, N, K, LDA, INCX IF( REWI ) $ REWIND NTRA CALL DTBMV( UPLO, TRANS, DIAG, N, K, AA, $ LDA, XX, INCX ) ELSE IF( PACKED )THEN IF( TRACE ) $ WRITE( NTRA, FMT = 9995 )NC, SNAME, $ UPLO, TRANS, DIAG, N, INCX IF( REWI ) $ REWIND NTRA CALL DTPMV( UPLO, TRANS, DIAG, N, AA, XX, $ INCX ) END IF ELSE IF( SNAME( 4: 5 ).EQ.'SV' )THEN IF( FULL )THEN IF( TRACE ) $ WRITE( NTRA, FMT = 9993 )NC, SNAME, $ UPLO, TRANS, DIAG, N, LDA, INCX IF( REWI ) $ REWIND NTRA CALL DTRSV( UPLO, TRANS, DIAG, N, AA, LDA, $ XX, INCX ) ELSE IF( BANDED )THEN IF( TRACE ) $ WRITE( NTRA, FMT = 9994 )NC, SNAME, $ UPLO, TRANS, DIAG, N, K, LDA, INCX IF( REWI ) $ REWIND NTRA CALL DTBSV( UPLO, TRANS, DIAG, N, K, AA, $ LDA, XX, INCX ) ELSE IF( PACKED )THEN IF( TRACE ) $ WRITE( NTRA, FMT = 9995 )NC, SNAME, $ UPLO, TRANS, DIAG, N, INCX IF( REWI ) $ REWIND NTRA CALL DTPSV( UPLO, TRANS, DIAG, N, AA, XX, $ INCX ) END IF END IF * * Check if error-exit was taken incorrectly. * IF( .NOT.OK )THEN WRITE( NOUT, FMT = 9992 ) FATAL = .TRUE. GO TO 120 END IF * * See what data changed inside subroutines. * ISAME( 1 ) = UPLO.EQ.UPLOS ISAME( 2 ) = TRANS.EQ.TRANSS ISAME( 3 ) = DIAG.EQ.DIAGS ISAME( 4 ) = NS.EQ.N IF( FULL )THEN ISAME( 5 ) = LDE( AS, AA, LAA ) ISAME( 6 ) = LDAS.EQ.LDA IF( NULL )THEN ISAME( 7 ) = LDE( XS, XX, LX ) ELSE ISAME( 7 ) = LDERES( 'GE', ' ', 1, N, XS, $ XX, ABS( INCX ) ) END IF ISAME( 8 ) = INCXS.EQ.INCX ELSE IF( BANDED )THEN ISAME( 5 ) = KS.EQ.K ISAME( 6 ) = LDE( AS, AA, LAA ) ISAME( 7 ) = LDAS.EQ.LDA IF( NULL )THEN ISAME( 8 ) = LDE( XS, XX, LX ) ELSE ISAME( 8 ) = LDERES( 'GE', ' ', 1, N, XS, $ XX, ABS( INCX ) ) END IF ISAME( 9 ) = INCXS.EQ.INCX ELSE IF( PACKED )THEN ISAME( 5 ) = LDE( AS, AA, LAA ) IF( NULL )THEN ISAME( 6 ) = LDE( XS, XX, LX ) ELSE ISAME( 6 ) = LDERES( 'GE', ' ', 1, N, XS, $ XX, ABS( INCX ) ) END IF ISAME( 7 ) = INCXS.EQ.INCX END IF * * If data was incorrectly changed, report and * return. * SAME = .TRUE. DO 40 I = 1, NARGS SAME = SAME.AND.ISAME( I ) IF( .NOT.ISAME( I ) ) $ WRITE( NOUT, FMT = 9998 )I 40 CONTINUE IF( .NOT.SAME )THEN FATAL = .TRUE. GO TO 120 END IF * IF( .NOT.NULL )THEN IF( SNAME( 4: 5 ).EQ.'MV' )THEN * * Check the result. * CALL DMVCH( TRANS, N, N, ONE, A, NMAX, X, $ INCX, ZERO, Z, INCX, XT, G, $ XX, EPS, ERR, FATAL, NOUT, $ .TRUE. ) ELSE IF( SNAME( 4: 5 ).EQ.'SV' )THEN * * Compute approximation to original vector. * DO 50 I = 1, N Z( I ) = XX( 1 + ( I - 1 )* $ ABS( INCX ) ) XX( 1 + ( I - 1 )*ABS( INCX ) ) $ = X( I ) 50 CONTINUE CALL DMVCH( TRANS, N, N, ONE, A, NMAX, Z, $ INCX, ZERO, X, INCX, XT, G, $ XX, EPS, ERR, FATAL, NOUT, $ .FALSE. ) END IF ERRMAX = MAX( ERRMAX, ERR ) * If got really bad answer, report and return. IF( FATAL ) $ GO TO 120 ELSE * Avoid repeating tests with N.le.0. GO TO 110 END IF * 60 CONTINUE * 70 CONTINUE * 80 CONTINUE * 90 CONTINUE * 100 CONTINUE * 110 CONTINUE * * Report result. * IF( ERRMAX.LT.THRESH )THEN WRITE( NOUT, FMT = 9999 )SNAME, NC ELSE WRITE( NOUT, FMT = 9997 )SNAME, NC, ERRMAX END IF GO TO 130 * 120 CONTINUE WRITE( NOUT, FMT = 9996 )SNAME IF( FULL )THEN WRITE( NOUT, FMT = 9993 )NC, SNAME, UPLO, TRANS, DIAG, N, LDA, $ INCX ELSE IF( BANDED )THEN WRITE( NOUT, FMT = 9994 )NC, SNAME, UPLO, TRANS, DIAG, N, K, $ LDA, INCX ELSE IF( PACKED )THEN WRITE( NOUT, FMT = 9995 )NC, SNAME, UPLO, TRANS, DIAG, N, INCX END IF * 130 CONTINUE RETURN * 9999 FORMAT( ' ', A6, ' PASSED THE COMPUTATIONAL TESTS (', I6, ' CALL', $ 'S)' ) 9998 FORMAT( ' ******* FATAL ERROR - PARAMETER NUMBER ', I2, ' WAS CH', $ 'ANGED INCORRECTLY *******' ) 9997 FORMAT( ' ', A6, ' COMPLETED THE COMPUTATIONAL TESTS (', I6, ' C', $ 'ALLS)', /' ******* BUT WITH MAXIMUM TEST RATIO', F8.2, $ ' - SUSPECT *******' ) 9996 FORMAT( ' ******* ', A6, ' FAILED ON CALL NUMBER:' ) 9995 FORMAT( 1X, I6, ': ', A6, '(', 3( '''', A1, ''',' ), I3, ', AP, ', $ 'X,', I2, ') .' ) 9994 FORMAT( 1X, I6, ': ', A6, '(', 3( '''', A1, ''',' ), 2( I3, ',' ), $ ' A,', I3, ', X,', I2, ') .' ) 9993 FORMAT( 1X, I6, ': ', A6, '(', 3( '''', A1, ''',' ), I3, ', A,', $ I3, ', X,', I2, ') .' ) 9992 FORMAT( ' ******* FATAL ERROR - ERROR-EXIT TAKEN ON VALID CALL *', $ '******' ) * * End of DCHK3. * END SUBROUTINE DCHK4( SNAME, EPS, THRESH, NOUT, NTRA, TRACE, REWI, $ FATAL, NIDIM, IDIM, NALF, ALF, NINC, INC, NMAX, $ INCMAX, A, AA, AS, X, XX, XS, Y, YY, YS, YT, G, $ Z ) * * Tests DGER. * * Auxiliary routine for test program for Level 2 Blas. * * -- Written on 10-August-1987. * Richard Hanson, Sandia National Labs. * Jeremy Du Croz, NAG Central Office. * * .. Parameters .. DOUBLE PRECISION ZERO, HALF, ONE PARAMETER ( ZERO = 0.0D0, HALF = 0.5D0, ONE = 1.0D0 ) * .. Scalar Arguments .. DOUBLE PRECISION EPS, THRESH INTEGER INCMAX, NALF, NIDIM, NINC, NMAX, NOUT, NTRA LOGICAL FATAL, REWI, TRACE CHARACTER*6 SNAME * .. Array Arguments .. DOUBLE PRECISION A( NMAX, NMAX ), AA( NMAX*NMAX ), ALF( NALF ), $ AS( NMAX*NMAX ), G( NMAX ), X( NMAX ), $ XS( NMAX*INCMAX ), XX( NMAX*INCMAX ), $ Y( NMAX ), YS( NMAX*INCMAX ), YT( NMAX ), $ YY( NMAX*INCMAX ), Z( NMAX ) INTEGER IDIM( NIDIM ), INC( NINC ) * .. Local Scalars .. DOUBLE PRECISION ALPHA, ALS, ERR, ERRMAX, TRANSL INTEGER I, IA, IM, IN, INCX, INCXS, INCY, INCYS, IX, $ IY, J, LAA, LDA, LDAS, LX, LY, M, MS, N, NARGS, $ NC, ND, NS LOGICAL NULL, RESET, SAME * .. Local Arrays .. DOUBLE PRECISION W( 1 ) LOGICAL ISAME( 13 ) * .. External Functions .. LOGICAL LDE, LDERES EXTERNAL LDE, LDERES * .. External Subroutines .. EXTERNAL DGER, DMAKE, DMVCH * .. Intrinsic Functions .. INTRINSIC ABS, MAX, MIN * .. Scalars in Common .. INTEGER INFOT, NOUTC LOGICAL LERR, OK * .. Common blocks .. COMMON /INFOC/INFOT, NOUTC, OK, LERR * .. Executable Statements .. * Define the number of arguments. NARGS = 9 * NC = 0 RESET = .TRUE. ERRMAX = ZERO * DO 120 IN = 1, NIDIM N = IDIM( IN ) ND = N/2 + 1 * DO 110 IM = 1, 2 IF( IM.EQ.1 ) $ M = MAX( N - ND, 0 ) IF( IM.EQ.2 ) $ M = MIN( N + ND, NMAX ) * * Set LDA to 1 more than minimum value if room. LDA = M IF( LDA.LT.NMAX ) $ LDA = LDA + 1 * Skip tests if not enough room. IF( LDA.GT.NMAX ) $ GO TO 110 LAA = LDA*N NULL = N.LE.0.OR.M.LE.0 * DO 100 IX = 1, NINC INCX = INC( IX ) LX = ABS( INCX )*M * * Generate the vector X. * TRANSL = HALF CALL DMAKE( 'GE', ' ', ' ', 1, M, X, 1, XX, ABS( INCX ), $ 0, M - 1, RESET, TRANSL ) IF( M.GT.1 )THEN X( M/2 ) = ZERO XX( 1 + ABS( INCX )*( M/2 - 1 ) ) = ZERO END IF * DO 90 IY = 1, NINC INCY = INC( IY ) LY = ABS( INCY )*N * * Generate the vector Y. * TRANSL = ZERO CALL DMAKE( 'GE', ' ', ' ', 1, N, Y, 1, YY, $ ABS( INCY ), 0, N - 1, RESET, TRANSL ) IF( N.GT.1 )THEN Y( N/2 ) = ZERO YY( 1 + ABS( INCY )*( N/2 - 1 ) ) = ZERO END IF * DO 80 IA = 1, NALF ALPHA = ALF( IA ) * * Generate the matrix A. * TRANSL = ZERO CALL DMAKE( SNAME( 2: 3 ), ' ', ' ', M, N, A, NMAX, $ AA, LDA, M - 1, N - 1, RESET, TRANSL ) * NC = NC + 1 * * Save every datum before calling the subroutine. * MS = M NS = N ALS = ALPHA DO 10 I = 1, LAA AS( I ) = AA( I ) 10 CONTINUE LDAS = LDA DO 20 I = 1, LX XS( I ) = XX( I ) 20 CONTINUE INCXS = INCX DO 30 I = 1, LY YS( I ) = YY( I ) 30 CONTINUE INCYS = INCY * * Call the subroutine. * IF( TRACE ) $ WRITE( NTRA, FMT = 9994 )NC, SNAME, M, N, $ ALPHA, INCX, INCY, LDA IF( REWI ) $ REWIND NTRA CALL DGER( M, N, ALPHA, XX, INCX, YY, INCY, AA, $ LDA ) * * Check if error-exit was taken incorrectly. * IF( .NOT.OK )THEN WRITE( NOUT, FMT = 9993 ) FATAL = .TRUE. GO TO 140 END IF * * See what data changed inside subroutine. * ISAME( 1 ) = MS.EQ.M ISAME( 2 ) = NS.EQ.N ISAME( 3 ) = ALS.EQ.ALPHA ISAME( 4 ) = LDE( XS, XX, LX ) ISAME( 5 ) = INCXS.EQ.INCX ISAME( 6 ) = LDE( YS, YY, LY ) ISAME( 7 ) = INCYS.EQ.INCY IF( NULL )THEN ISAME( 8 ) = LDE( AS, AA, LAA ) ELSE ISAME( 8 ) = LDERES( 'GE', ' ', M, N, AS, AA, $ LDA ) END IF ISAME( 9 ) = LDAS.EQ.LDA * * If data was incorrectly changed, report and return. * SAME = .TRUE. DO 40 I = 1, NARGS SAME = SAME.AND.ISAME( I ) IF( .NOT.ISAME( I ) ) $ WRITE( NOUT, FMT = 9998 )I 40 CONTINUE IF( .NOT.SAME )THEN FATAL = .TRUE. GO TO 140 END IF * IF( .NOT.NULL )THEN * * Check the result column by column. * IF( INCX.GT.0 )THEN DO 50 I = 1, M Z( I ) = X( I ) 50 CONTINUE ELSE DO 60 I = 1, M Z( I ) = X( M - I + 1 ) 60 CONTINUE END IF DO 70 J = 1, N IF( INCY.GT.0 )THEN W( 1 ) = Y( J ) ELSE W( 1 ) = Y( N - J + 1 ) END IF CALL DMVCH( 'N', M, 1, ALPHA, Z, NMAX, W, 1, $ ONE, A( 1, J ), 1, YT, G, $ AA( 1 + ( J - 1 )*LDA ), EPS, $ ERR, FATAL, NOUT, .TRUE. ) ERRMAX = MAX( ERRMAX, ERR ) * If got really bad answer, report and return. IF( FATAL ) $ GO TO 130 70 CONTINUE ELSE * Avoid repeating tests with M.le.0 or N.le.0. GO TO 110 END IF * 80 CONTINUE * 90 CONTINUE * 100 CONTINUE * 110 CONTINUE * 120 CONTINUE * * Report result. * IF( ERRMAX.LT.THRESH )THEN WRITE( NOUT, FMT = 9999 )SNAME, NC ELSE WRITE( NOUT, FMT = 9997 )SNAME, NC, ERRMAX END IF GO TO 150 * 130 CONTINUE WRITE( NOUT, FMT = 9995 )J * 140 CONTINUE WRITE( NOUT, FMT = 9996 )SNAME WRITE( NOUT, FMT = 9994 )NC, SNAME, M, N, ALPHA, INCX, INCY, LDA * 150 CONTINUE RETURN * 9999 FORMAT( ' ', A6, ' PASSED THE COMPUTATIONAL TESTS (', I6, ' CALL', $ 'S)' ) 9998 FORMAT( ' ******* FATAL ERROR - PARAMETER NUMBER ', I2, ' WAS CH', $ 'ANGED INCORRECTLY *******' ) 9997 FORMAT( ' ', A6, ' COMPLETED THE COMPUTATIONAL TESTS (', I6, ' C', $ 'ALLS)', /' ******* BUT WITH MAXIMUM TEST RATIO', F8.2, $ ' - SUSPECT *******' ) 9996 FORMAT( ' ******* ', A6, ' FAILED ON CALL NUMBER:' ) 9995 FORMAT( ' THESE ARE THE RESULTS FOR COLUMN ', I3 ) 9994 FORMAT( 1X, I6, ': ', A6, '(', 2( I3, ',' ), F4.1, ', X,', I2, $ ', Y,', I2, ', A,', I3, ') .' ) 9993 FORMAT( ' ******* FATAL ERROR - ERROR-EXIT TAKEN ON VALID CALL *', $ '******' ) * * End of DCHK4. * END SUBROUTINE DCHK5( SNAME, EPS, THRESH, NOUT, NTRA, TRACE, REWI, $ FATAL, NIDIM, IDIM, NALF, ALF, NINC, INC, NMAX, $ INCMAX, A, AA, AS, X, XX, XS, Y, YY, YS, YT, G, $ Z ) * * Tests DSYR and DSPR. * * Auxiliary routine for test program for Level 2 Blas. * * -- Written on 10-August-1987. * Richard Hanson, Sandia National Labs. * Jeremy Du Croz, NAG Central Office. * * .. Parameters .. DOUBLE PRECISION ZERO, HALF, ONE PARAMETER ( ZERO = 0.0D0, HALF = 0.5D0, ONE = 1.0D0 ) * .. Scalar Arguments .. DOUBLE PRECISION EPS, THRESH INTEGER INCMAX, NALF, NIDIM, NINC, NMAX, NOUT, NTRA LOGICAL FATAL, REWI, TRACE CHARACTER*6 SNAME * .. Array Arguments .. DOUBLE PRECISION A( NMAX, NMAX ), AA( NMAX*NMAX ), ALF( NALF ), $ AS( NMAX*NMAX ), G( NMAX ), X( NMAX ), $ XS( NMAX*INCMAX ), XX( NMAX*INCMAX ), $ Y( NMAX ), YS( NMAX*INCMAX ), YT( NMAX ), $ YY( NMAX*INCMAX ), Z( NMAX ) INTEGER IDIM( NIDIM ), INC( NINC ) * .. Local Scalars .. DOUBLE PRECISION ALPHA, ALS, ERR, ERRMAX, TRANSL INTEGER I, IA, IC, IN, INCX, INCXS, IX, J, JA, JJ, LAA, $ LDA, LDAS, LJ, LX, N, NARGS, NC, NS LOGICAL FULL, NULL, PACKED, RESET, SAME, UPPER CHARACTER*1 UPLO, UPLOS CHARACTER*2 ICH * .. Local Arrays .. DOUBLE PRECISION W( 1 ) LOGICAL ISAME( 13 ) * .. External Functions .. LOGICAL LDE, LDERES EXTERNAL LDE, LDERES * .. External Subroutines .. EXTERNAL DMAKE, DMVCH, DSPR, DSYR * .. Intrinsic Functions .. INTRINSIC ABS, MAX * .. Scalars in Common .. INTEGER INFOT, NOUTC LOGICAL LERR, OK * .. Common blocks .. COMMON /INFOC/INFOT, NOUTC, OK, LERR * .. Data statements .. DATA ICH/'UL'/ * .. Executable Statements .. FULL = SNAME( 3: 3 ).EQ.'Y' PACKED = SNAME( 3: 3 ).EQ.'P' * Define the number of arguments. IF( FULL )THEN NARGS = 7 ELSE IF( PACKED )THEN NARGS = 6 END IF * NC = 0 RESET = .TRUE. ERRMAX = ZERO * DO 100 IN = 1, NIDIM N = IDIM( IN ) * Set LDA to 1 more than minimum value if room. LDA = N IF( LDA.LT.NMAX ) $ LDA = LDA + 1 * Skip tests if not enough room. IF( LDA.GT.NMAX ) $ GO TO 100 IF( PACKED )THEN LAA = ( N*( N + 1 ) )/2 ELSE LAA = LDA*N END IF * DO 90 IC = 1, 2 UPLO = ICH( IC: IC ) UPPER = UPLO.EQ.'U' * DO 80 IX = 1, NINC INCX = INC( IX ) LX = ABS( INCX )*N * * Generate the vector X. * TRANSL = HALF CALL DMAKE( 'GE', ' ', ' ', 1, N, X, 1, XX, ABS( INCX ), $ 0, N - 1, RESET, TRANSL ) IF( N.GT.1 )THEN X( N/2 ) = ZERO XX( 1 + ABS( INCX )*( N/2 - 1 ) ) = ZERO END IF * DO 70 IA = 1, NALF ALPHA = ALF( IA ) NULL = N.LE.0.OR.ALPHA.EQ.ZERO * * Generate the matrix A. * TRANSL = ZERO CALL DMAKE( SNAME( 2: 3 ), UPLO, ' ', N, N, A, NMAX, $ AA, LDA, N - 1, N - 1, RESET, TRANSL ) * NC = NC + 1 * * Save every datum before calling the subroutine. * UPLOS = UPLO NS = N ALS = ALPHA DO 10 I = 1, LAA AS( I ) = AA( I ) 10 CONTINUE LDAS = LDA DO 20 I = 1, LX XS( I ) = XX( I ) 20 CONTINUE INCXS = INCX * * Call the subroutine. * IF( FULL )THEN IF( TRACE ) $ WRITE( NTRA, FMT = 9993 )NC, SNAME, UPLO, N, $ ALPHA, INCX, LDA IF( REWI ) $ REWIND NTRA CALL DSYR( UPLO, N, ALPHA, XX, INCX, AA, LDA ) ELSE IF( PACKED )THEN IF( TRACE ) $ WRITE( NTRA, FMT = 9994 )NC, SNAME, UPLO, N, $ ALPHA, INCX IF( REWI ) $ REWIND NTRA CALL DSPR( UPLO, N, ALPHA, XX, INCX, AA ) END IF * * Check if error-exit was taken incorrectly. * IF( .NOT.OK )THEN WRITE( NOUT, FMT = 9992 ) FATAL = .TRUE. GO TO 120 END IF * * See what data changed inside subroutines. * ISAME( 1 ) = UPLO.EQ.UPLOS ISAME( 2 ) = NS.EQ.N ISAME( 3 ) = ALS.EQ.ALPHA ISAME( 4 ) = LDE( XS, XX, LX ) ISAME( 5 ) = INCXS.EQ.INCX IF( NULL )THEN ISAME( 6 ) = LDE( AS, AA, LAA ) ELSE ISAME( 6 ) = LDERES( SNAME( 2: 3 ), UPLO, N, N, AS, $ AA, LDA ) END IF IF( .NOT.PACKED )THEN ISAME( 7 ) = LDAS.EQ.LDA END IF * * If data was incorrectly changed, report and return. * SAME = .TRUE. DO 30 I = 1, NARGS SAME = SAME.AND.ISAME( I ) IF( .NOT.ISAME( I ) ) $ WRITE( NOUT, FMT = 9998 )I 30 CONTINUE IF( .NOT.SAME )THEN FATAL = .TRUE. GO TO 120 END IF * IF( .NOT.NULL )THEN * * Check the result column by column. * IF( INCX.GT.0 )THEN DO 40 I = 1, N Z( I ) = X( I ) 40 CONTINUE ELSE DO 50 I = 1, N Z( I ) = X( N - I + 1 ) 50 CONTINUE END IF JA = 1 DO 60 J = 1, N W( 1 ) = Z( J ) IF( UPPER )THEN JJ = 1 LJ = J ELSE JJ = J LJ = N - J + 1 END IF CALL DMVCH( 'N', LJ, 1, ALPHA, Z( JJ ), LJ, W, $ 1, ONE, A( JJ, J ), 1, YT, G, $ AA( JA ), EPS, ERR, FATAL, NOUT, $ .TRUE. ) IF( FULL )THEN IF( UPPER )THEN JA = JA + LDA ELSE JA = JA + LDA + 1 END IF ELSE JA = JA + LJ END IF ERRMAX = MAX( ERRMAX, ERR ) * If got really bad answer, report and return. IF( FATAL ) $ GO TO 110 60 CONTINUE ELSE * Avoid repeating tests if N.le.0. IF( N.LE.0 ) $ GO TO 100 END IF * 70 CONTINUE * 80 CONTINUE * 90 CONTINUE * 100 CONTINUE * * Report result. * IF( ERRMAX.LT.THRESH )THEN WRITE( NOUT, FMT = 9999 )SNAME, NC ELSE WRITE( NOUT, FMT = 9997 )SNAME, NC, ERRMAX END IF GO TO 130 * 110 CONTINUE WRITE( NOUT, FMT = 9995 )J * 120 CONTINUE WRITE( NOUT, FMT = 9996 )SNAME IF( FULL )THEN WRITE( NOUT, FMT = 9993 )NC, SNAME, UPLO, N, ALPHA, INCX, LDA ELSE IF( PACKED )THEN WRITE( NOUT, FMT = 9994 )NC, SNAME, UPLO, N, ALPHA, INCX END IF * 130 CONTINUE RETURN * 9999 FORMAT( ' ', A6, ' PASSED THE COMPUTATIONAL TESTS (', I6, ' CALL', $ 'S)' ) 9998 FORMAT( ' ******* FATAL ERROR - PARAMETER NUMBER ', I2, ' WAS CH', $ 'ANGED INCORRECTLY *******' ) 9997 FORMAT( ' ', A6, ' COMPLETED THE COMPUTATIONAL TESTS (', I6, ' C', $ 'ALLS)', /' ******* BUT WITH MAXIMUM TEST RATIO', F8.2, $ ' - SUSPECT *******' ) 9996 FORMAT( ' ******* ', A6, ' FAILED ON CALL NUMBER:' ) 9995 FORMAT( ' THESE ARE THE RESULTS FOR COLUMN ', I3 ) 9994 FORMAT( 1X, I6, ': ', A6, '(''', A1, ''',', I3, ',', F4.1, ', X,', $ I2, ', AP) .' ) 9993 FORMAT( 1X, I6, ': ', A6, '(''', A1, ''',', I3, ',', F4.1, ', X,', $ I2, ', A,', I3, ') .' ) 9992 FORMAT( ' ******* FATAL ERROR - ERROR-EXIT TAKEN ON VALID CALL *', $ '******' ) * * End of DCHK5. * END SUBROUTINE DCHK6( SNAME, EPS, THRESH, NOUT, NTRA, TRACE, REWI, $ FATAL, NIDIM, IDIM, NALF, ALF, NINC, INC, NMAX, $ INCMAX, A, AA, AS, X, XX, XS, Y, YY, YS, YT, G, $ Z ) * * Tests DSYR2 and DSPR2. * * Auxiliary routine for test program for Level 2 Blas. * * -- Written on 10-August-1987. * Richard Hanson, Sandia National Labs. * Jeremy Du Croz, NAG Central Office. * * .. Parameters .. DOUBLE PRECISION ZERO, HALF, ONE PARAMETER ( ZERO = 0.0D0, HALF = 0.5D0, ONE = 1.0D0 ) * .. Scalar Arguments .. DOUBLE PRECISION EPS, THRESH INTEGER INCMAX, NALF, NIDIM, NINC, NMAX, NOUT, NTRA LOGICAL FATAL, REWI, TRACE CHARACTER*6 SNAME * .. Array Arguments .. DOUBLE PRECISION A( NMAX, NMAX ), AA( NMAX*NMAX ), ALF( NALF ), $ AS( NMAX*NMAX ), G( NMAX ), X( NMAX ), $ XS( NMAX*INCMAX ), XX( NMAX*INCMAX ), $ Y( NMAX ), YS( NMAX*INCMAX ), YT( NMAX ), $ YY( NMAX*INCMAX ), Z( NMAX, 2 ) INTEGER IDIM( NIDIM ), INC( NINC ) * .. Local Scalars .. DOUBLE PRECISION ALPHA, ALS, ERR, ERRMAX, TRANSL INTEGER I, IA, IC, IN, INCX, INCXS, INCY, INCYS, IX, $ IY, J, JA, JJ, LAA, LDA, LDAS, LJ, LX, LY, N, $ NARGS, NC, NS LOGICAL FULL, NULL, PACKED, RESET, SAME, UPPER CHARACTER*1 UPLO, UPLOS CHARACTER*2 ICH * .. Local Arrays .. DOUBLE PRECISION W( 2 ) LOGICAL ISAME( 13 ) * .. External Functions .. LOGICAL LDE, LDERES EXTERNAL LDE, LDERES * .. External Subroutines .. EXTERNAL DMAKE, DMVCH, DSPR2, DSYR2 * .. Intrinsic Functions .. INTRINSIC ABS, MAX * .. Scalars in Common .. INTEGER INFOT, NOUTC LOGICAL LERR, OK * .. Common blocks .. COMMON /INFOC/INFOT, NOUTC, OK, LERR * .. Data statements .. DATA ICH/'UL'/ * .. Executable Statements .. FULL = SNAME( 3: 3 ).EQ.'Y' PACKED = SNAME( 3: 3 ).EQ.'P' * Define the number of arguments. IF( FULL )THEN NARGS = 9 ELSE IF( PACKED )THEN NARGS = 8 END IF * NC = 0 RESET = .TRUE. ERRMAX = ZERO * DO 140 IN = 1, NIDIM N = IDIM( IN ) * Set LDA to 1 more than minimum value if room. LDA = N IF( LDA.LT.NMAX ) $ LDA = LDA + 1 * Skip tests if not enough room. IF( LDA.GT.NMAX ) $ GO TO 140 IF( PACKED )THEN LAA = ( N*( N + 1 ) )/2 ELSE LAA = LDA*N END IF * DO 130 IC = 1, 2 UPLO = ICH( IC: IC ) UPPER = UPLO.EQ.'U' * DO 120 IX = 1, NINC INCX = INC( IX ) LX = ABS( INCX )*N * * Generate the vector X. * TRANSL = HALF CALL DMAKE( 'GE', ' ', ' ', 1, N, X, 1, XX, ABS( INCX ), $ 0, N - 1, RESET, TRANSL ) IF( N.GT.1 )THEN X( N/2 ) = ZERO XX( 1 + ABS( INCX )*( N/2 - 1 ) ) = ZERO END IF * DO 110 IY = 1, NINC INCY = INC( IY ) LY = ABS( INCY )*N * * Generate the vector Y. * TRANSL = ZERO CALL DMAKE( 'GE', ' ', ' ', 1, N, Y, 1, YY, $ ABS( INCY ), 0, N - 1, RESET, TRANSL ) IF( N.GT.1 )THEN Y( N/2 ) = ZERO YY( 1 + ABS( INCY )*( N/2 - 1 ) ) = ZERO END IF * DO 100 IA = 1, NALF ALPHA = ALF( IA ) NULL = N.LE.0.OR.ALPHA.EQ.ZERO * * Generate the matrix A. * TRANSL = ZERO CALL DMAKE( SNAME( 2: 3 ), UPLO, ' ', N, N, A, $ NMAX, AA, LDA, N - 1, N - 1, RESET, $ TRANSL ) * NC = NC + 1 * * Save every datum before calling the subroutine. * UPLOS = UPLO NS = N ALS = ALPHA DO 10 I = 1, LAA AS( I ) = AA( I ) 10 CONTINUE LDAS = LDA DO 20 I = 1, LX XS( I ) = XX( I ) 20 CONTINUE INCXS = INCX DO 30 I = 1, LY YS( I ) = YY( I ) 30 CONTINUE INCYS = INCY * * Call the subroutine. * IF( FULL )THEN IF( TRACE ) $ WRITE( NTRA, FMT = 9993 )NC, SNAME, UPLO, N, $ ALPHA, INCX, INCY, LDA IF( REWI ) $ REWIND NTRA CALL DSYR2( UPLO, N, ALPHA, XX, INCX, YY, INCY, $ AA, LDA ) ELSE IF( PACKED )THEN IF( TRACE ) $ WRITE( NTRA, FMT = 9994 )NC, SNAME, UPLO, N, $ ALPHA, INCX, INCY IF( REWI ) $ REWIND NTRA CALL DSPR2( UPLO, N, ALPHA, XX, INCX, YY, INCY, $ AA ) END IF * * Check if error-exit was taken incorrectly. * IF( .NOT.OK )THEN WRITE( NOUT, FMT = 9992 ) FATAL = .TRUE. GO TO 160 END IF * * See what data changed inside subroutines. * ISAME( 1 ) = UPLO.EQ.UPLOS ISAME( 2 ) = NS.EQ.N ISAME( 3 ) = ALS.EQ.ALPHA ISAME( 4 ) = LDE( XS, XX, LX ) ISAME( 5 ) = INCXS.EQ.INCX ISAME( 6 ) = LDE( YS, YY, LY ) ISAME( 7 ) = INCYS.EQ.INCY IF( NULL )THEN ISAME( 8 ) = LDE( AS, AA, LAA ) ELSE ISAME( 8 ) = LDERES( SNAME( 2: 3 ), UPLO, N, N, $ AS, AA, LDA ) END IF IF( .NOT.PACKED )THEN ISAME( 9 ) = LDAS.EQ.LDA END IF * * If data was incorrectly changed, report and return. * SAME = .TRUE. DO 40 I = 1, NARGS SAME = SAME.AND.ISAME( I ) IF( .NOT.ISAME( I ) ) $ WRITE( NOUT, FMT = 9998 )I 40 CONTINUE IF( .NOT.SAME )THEN FATAL = .TRUE. GO TO 160 END IF * IF( .NOT.NULL )THEN * * Check the result column by column. * IF( INCX.GT.0 )THEN DO 50 I = 1, N Z( I, 1 ) = X( I ) 50 CONTINUE ELSE DO 60 I = 1, N Z( I, 1 ) = X( N - I + 1 ) 60 CONTINUE END IF IF( INCY.GT.0 )THEN DO 70 I = 1, N Z( I, 2 ) = Y( I ) 70 CONTINUE ELSE DO 80 I = 1, N Z( I, 2 ) = Y( N - I + 1 ) 80 CONTINUE END IF JA = 1 DO 90 J = 1, N W( 1 ) = Z( J, 2 ) W( 2 ) = Z( J, 1 ) IF( UPPER )THEN JJ = 1 LJ = J ELSE JJ = J LJ = N - J + 1 END IF CALL DMVCH( 'N', LJ, 2, ALPHA, Z( JJ, 1 ), $ NMAX, W, 1, ONE, A( JJ, J ), 1, $ YT, G, AA( JA ), EPS, ERR, FATAL, $ NOUT, .TRUE. ) IF( FULL )THEN IF( UPPER )THEN JA = JA + LDA ELSE JA = JA + LDA + 1 END IF ELSE JA = JA + LJ END IF ERRMAX = MAX( ERRMAX, ERR ) * If got really bad answer, report and return. IF( FATAL ) $ GO TO 150 90 CONTINUE ELSE * Avoid repeating tests with N.le.0. IF( N.LE.0 ) $ GO TO 140 END IF * 100 CONTINUE * 110 CONTINUE * 120 CONTINUE * 130 CONTINUE * 140 CONTINUE * * Report result. * IF( ERRMAX.LT.THRESH )THEN WRITE( NOUT, FMT = 9999 )SNAME, NC ELSE WRITE( NOUT, FMT = 9997 )SNAME, NC, ERRMAX END IF GO TO 170 * 150 CONTINUE WRITE( NOUT, FMT = 9995 )J * 160 CONTINUE WRITE( NOUT, FMT = 9996 )SNAME IF( FULL )THEN WRITE( NOUT, FMT = 9993 )NC, SNAME, UPLO, N, ALPHA, INCX, $ INCY, LDA ELSE IF( PACKED )THEN WRITE( NOUT, FMT = 9994 )NC, SNAME, UPLO, N, ALPHA, INCX, INCY END IF * 170 CONTINUE RETURN * 9999 FORMAT( ' ', A6, ' PASSED THE COMPUTATIONAL TESTS (', I6, ' CALL', $ 'S)' ) 9998 FORMAT( ' ******* FATAL ERROR - PARAMETER NUMBER ', I2, ' WAS CH', $ 'ANGED INCORRECTLY *******' ) 9997 FORMAT( ' ', A6, ' COMPLETED THE COMPUTATIONAL TESTS (', I6, ' C', $ 'ALLS)', /' ******* BUT WITH MAXIMUM TEST RATIO', F8.2, $ ' - SUSPECT *******' ) 9996 FORMAT( ' ******* ', A6, ' FAILED ON CALL NUMBER:' ) 9995 FORMAT( ' THESE ARE THE RESULTS FOR COLUMN ', I3 ) 9994 FORMAT( 1X, I6, ': ', A6, '(''', A1, ''',', I3, ',', F4.1, ', X,', $ I2, ', Y,', I2, ', AP) .' ) 9993 FORMAT( 1X, I6, ': ', A6, '(''', A1, ''',', I3, ',', F4.1, ', X,', $ I2, ', Y,', I2, ', A,', I3, ') .' ) 9992 FORMAT( ' ******* FATAL ERROR - ERROR-EXIT TAKEN ON VALID CALL *', $ '******' ) * * End of DCHK6. * END SUBROUTINE DCHKE( ISNUM, SRNAMT, NOUT ) * * Tests the error exits from the Level 2 Blas. * Requires a special version of the error-handling routine XERBLA. * ALPHA, BETA, A, X and Y should not need to be defined. * * Auxiliary routine for test program for Level 2 Blas. * * -- Written on 10-August-1987. * Richard Hanson, Sandia National Labs. * Jeremy Du Croz, NAG Central Office. * * .. Scalar Arguments .. INTEGER ISNUM, NOUT CHARACTER*6 SRNAMT * .. Scalars in Common .. INTEGER INFOT, NOUTC LOGICAL LERR, OK * .. Local Scalars .. DOUBLE PRECISION ALPHA, BETA * .. Local Arrays .. DOUBLE PRECISION A( 1, 1 ), X( 1 ), Y( 1 ) * .. External Subroutines .. EXTERNAL CHKXER, DGBMV, DGEMV, DGER, DSBMV, DSPMV, DSPR, $ DSPR2, DSYMV, DSYR, DSYR2, DTBMV, DTBSV, DTPMV, $ DTPSV, DTRMV, DTRSV * .. Common blocks .. COMMON /INFOC/INFOT, NOUTC, OK, LERR * .. Executable Statements .. * OK is set to .FALSE. by the special version of XERBLA or by CHKXER * if anything is wrong. OK = .TRUE. * LERR is set to .TRUE. by the special version of XERBLA each time * it is called, and is then tested and re-set by CHKXER. LERR = .FALSE. GO TO ( 10, 20, 30, 40, 50, 60, 70, 80, $ 90, 100, 110, 120, 130, 140, 150, $ 160 )ISNUM 10 INFOT = 1 CALL DGEMV( '/', 0, 0, ALPHA, A, 1, X, 1, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL DGEMV( 'N', -1, 0, ALPHA, A, 1, X, 1, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL DGEMV( 'N', 0, -1, ALPHA, A, 1, X, 1, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL DGEMV( 'N', 2, 0, ALPHA, A, 1, X, 1, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 8 CALL DGEMV( 'N', 0, 0, ALPHA, A, 1, X, 0, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL DGEMV( 'N', 0, 0, ALPHA, A, 1, X, 1, BETA, Y, 0 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 170 20 INFOT = 1 CALL DGBMV( '/', 0, 0, 0, 0, ALPHA, A, 1, X, 1, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL DGBMV( 'N', -1, 0, 0, 0, ALPHA, A, 1, X, 1, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL DGBMV( 'N', 0, -1, 0, 0, ALPHA, A, 1, X, 1, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL DGBMV( 'N', 0, 0, -1, 0, ALPHA, A, 1, X, 1, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL DGBMV( 'N', 2, 0, 0, -1, ALPHA, A, 1, X, 1, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 8 CALL DGBMV( 'N', 0, 0, 1, 0, ALPHA, A, 1, X, 1, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 10 CALL DGBMV( 'N', 0, 0, 0, 0, ALPHA, A, 1, X, 0, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 13 CALL DGBMV( 'N', 0, 0, 0, 0, ALPHA, A, 1, X, 1, BETA, Y, 0 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 170 30 INFOT = 1 CALL DSYMV( '/', 0, ALPHA, A, 1, X, 1, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL DSYMV( 'U', -1, ALPHA, A, 1, X, 1, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL DSYMV( 'U', 2, ALPHA, A, 1, X, 1, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL DSYMV( 'U', 0, ALPHA, A, 1, X, 0, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 10 CALL DSYMV( 'U', 0, ALPHA, A, 1, X, 1, BETA, Y, 0 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 170 40 INFOT = 1 CALL DSBMV( '/', 0, 0, ALPHA, A, 1, X, 1, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL DSBMV( 'U', -1, 0, ALPHA, A, 1, X, 1, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL DSBMV( 'U', 0, -1, ALPHA, A, 1, X, 1, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL DSBMV( 'U', 0, 1, ALPHA, A, 1, X, 1, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 8 CALL DSBMV( 'U', 0, 0, ALPHA, A, 1, X, 0, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL DSBMV( 'U', 0, 0, ALPHA, A, 1, X, 1, BETA, Y, 0 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 170 50 INFOT = 1 CALL DSPMV( '/', 0, ALPHA, A, X, 1, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL DSPMV( 'U', -1, ALPHA, A, X, 1, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL DSPMV( 'U', 0, ALPHA, A, X, 0, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL DSPMV( 'U', 0, ALPHA, A, X, 1, BETA, Y, 0 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 170 60 INFOT = 1 CALL DTRMV( '/', 'N', 'N', 0, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL DTRMV( 'U', '/', 'N', 0, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL DTRMV( 'U', 'N', '/', 0, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL DTRMV( 'U', 'N', 'N', -1, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL DTRMV( 'U', 'N', 'N', 2, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 8 CALL DTRMV( 'U', 'N', 'N', 0, A, 1, X, 0 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 170 70 INFOT = 1 CALL DTBMV( '/', 'N', 'N', 0, 0, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL DTBMV( 'U', '/', 'N', 0, 0, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL DTBMV( 'U', 'N', '/', 0, 0, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL DTBMV( 'U', 'N', 'N', -1, 0, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL DTBMV( 'U', 'N', 'N', 0, -1, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL DTBMV( 'U', 'N', 'N', 0, 1, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL DTBMV( 'U', 'N', 'N', 0, 0, A, 1, X, 0 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 170 80 INFOT = 1 CALL DTPMV( '/', 'N', 'N', 0, A, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL DTPMV( 'U', '/', 'N', 0, A, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL DTPMV( 'U', 'N', '/', 0, A, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL DTPMV( 'U', 'N', 'N', -1, A, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL DTPMV( 'U', 'N', 'N', 0, A, X, 0 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 170 90 INFOT = 1 CALL DTRSV( '/', 'N', 'N', 0, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL DTRSV( 'U', '/', 'N', 0, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL DTRSV( 'U', 'N', '/', 0, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL DTRSV( 'U', 'N', 'N', -1, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL DTRSV( 'U', 'N', 'N', 2, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 8 CALL DTRSV( 'U', 'N', 'N', 0, A, 1, X, 0 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 170 100 INFOT = 1 CALL DTBSV( '/', 'N', 'N', 0, 0, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL DTBSV( 'U', '/', 'N', 0, 0, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL DTBSV( 'U', 'N', '/', 0, 0, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL DTBSV( 'U', 'N', 'N', -1, 0, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL DTBSV( 'U', 'N', 'N', 0, -1, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL DTBSV( 'U', 'N', 'N', 0, 1, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL DTBSV( 'U', 'N', 'N', 0, 0, A, 1, X, 0 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 170 110 INFOT = 1 CALL DTPSV( '/', 'N', 'N', 0, A, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL DTPSV( 'U', '/', 'N', 0, A, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL DTPSV( 'U', 'N', '/', 0, A, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL DTPSV( 'U', 'N', 'N', -1, A, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL DTPSV( 'U', 'N', 'N', 0, A, X, 0 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 170 120 INFOT = 1 CALL DGER( -1, 0, ALPHA, X, 1, Y, 1, A, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL DGER( 0, -1, ALPHA, X, 1, Y, 1, A, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL DGER( 0, 0, ALPHA, X, 0, Y, 1, A, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL DGER( 0, 0, ALPHA, X, 1, Y, 0, A, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL DGER( 2, 0, ALPHA, X, 1, Y, 1, A, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 170 130 INFOT = 1 CALL DSYR( '/', 0, ALPHA, X, 1, A, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL DSYR( 'U', -1, ALPHA, X, 1, A, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL DSYR( 'U', 0, ALPHA, X, 0, A, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL DSYR( 'U', 2, ALPHA, X, 1, A, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 170 140 INFOT = 1 CALL DSPR( '/', 0, ALPHA, X, 1, A ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL DSPR( 'U', -1, ALPHA, X, 1, A ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL DSPR( 'U', 0, ALPHA, X, 0, A ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 170 150 INFOT = 1 CALL DSYR2( '/', 0, ALPHA, X, 1, Y, 1, A, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL DSYR2( 'U', -1, ALPHA, X, 1, Y, 1, A, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL DSYR2( 'U', 0, ALPHA, X, 0, Y, 1, A, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL DSYR2( 'U', 0, ALPHA, X, 1, Y, 0, A, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL DSYR2( 'U', 2, ALPHA, X, 1, Y, 1, A, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 170 160 INFOT = 1 CALL DSPR2( '/', 0, ALPHA, X, 1, Y, 1, A ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL DSPR2( 'U', -1, ALPHA, X, 1, Y, 1, A ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL DSPR2( 'U', 0, ALPHA, X, 0, Y, 1, A ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL DSPR2( 'U', 0, ALPHA, X, 1, Y, 0, A ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) * 170 IF( OK )THEN WRITE( NOUT, FMT = 9999 )SRNAMT ELSE WRITE( NOUT, FMT = 9998 )SRNAMT END IF RETURN * 9999 FORMAT( ' ', A6, ' PASSED THE TESTS OF ERROR-EXITS' ) 9998 FORMAT( ' ******* ', A6, ' FAILED THE TESTS OF ERROR-EXITS *****', $ '**' ) * * End of DCHKE. * END SUBROUTINE DMAKE( TYPE, UPLO, DIAG, M, N, A, NMAX, AA, LDA, KL, $ KU, RESET, TRANSL ) * * Generates values for an M by N matrix A within the bandwidth * defined by KL and KU. * Stores the values in the array AA in the data structure required * by the routine, with unwanted elements set to rogue value. * * TYPE is 'GE', 'GB', 'SY', 'SB', 'SP', 'TR', 'TB' OR 'TP'. * * Auxiliary routine for test program for Level 2 Blas. * * -- Written on 10-August-1987. * Richard Hanson, Sandia National Labs. * Jeremy Du Croz, NAG Central Office. * * .. Parameters .. DOUBLE PRECISION ZERO, ONE PARAMETER ( ZERO = 0.0D0, ONE = 1.0D0 ) DOUBLE PRECISION ROGUE PARAMETER ( ROGUE = -1.0D10 ) * .. Scalar Arguments .. DOUBLE PRECISION TRANSL INTEGER KL, KU, LDA, M, N, NMAX LOGICAL RESET CHARACTER*1 DIAG, UPLO CHARACTER*2 TYPE * .. Array Arguments .. DOUBLE PRECISION A( NMAX, * ), AA( * ) * .. Local Scalars .. INTEGER I, I1, I2, I3, IBEG, IEND, IOFF, J, KK LOGICAL GEN, LOWER, SYM, TRI, UNIT, UPPER * .. External Functions .. DOUBLE PRECISION DBEG EXTERNAL DBEG * .. Intrinsic Functions .. INTRINSIC MAX, MIN * .. Executable Statements .. GEN = TYPE( 1: 1 ).EQ.'G' SYM = TYPE( 1: 1 ).EQ.'S' TRI = TYPE( 1: 1 ).EQ.'T' UPPER = ( SYM.OR.TRI ).AND.UPLO.EQ.'U' LOWER = ( SYM.OR.TRI ).AND.UPLO.EQ.'L' UNIT = TRI.AND.DIAG.EQ.'U' * * Generate data in array A. * DO 20 J = 1, N DO 10 I = 1, M IF( GEN.OR.( UPPER.AND.I.LE.J ).OR.( LOWER.AND.I.GE.J ) ) $ THEN IF( ( I.LE.J.AND.J - I.LE.KU ).OR. $ ( I.GE.J.AND.I - J.LE.KL ) )THEN A( I, J ) = DBEG( RESET ) + TRANSL ELSE A( I, J ) = ZERO END IF IF( I.NE.J )THEN IF( SYM )THEN A( J, I ) = A( I, J ) ELSE IF( TRI )THEN A( J, I ) = ZERO END IF END IF END IF 10 CONTINUE IF( TRI ) $ A( J, J ) = A( J, J ) + ONE IF( UNIT ) $ A( J, J ) = ONE 20 CONTINUE * * Store elements in array AS in data structure required by routine. * IF( TYPE.EQ.'GE' )THEN DO 50 J = 1, N DO 30 I = 1, M AA( I + ( J - 1 )*LDA ) = A( I, J ) 30 CONTINUE DO 40 I = M + 1, LDA AA( I + ( J - 1 )*LDA ) = ROGUE 40 CONTINUE 50 CONTINUE ELSE IF( TYPE.EQ.'GB' )THEN DO 90 J = 1, N DO 60 I1 = 1, KU + 1 - J AA( I1 + ( J - 1 )*LDA ) = ROGUE 60 CONTINUE DO 70 I2 = I1, MIN( KL + KU + 1, KU + 1 + M - J ) AA( I2 + ( J - 1 )*LDA ) = A( I2 + J - KU - 1, J ) 70 CONTINUE DO 80 I3 = I2, LDA AA( I3 + ( J - 1 )*LDA ) = ROGUE 80 CONTINUE 90 CONTINUE ELSE IF( TYPE.EQ.'SY'.OR.TYPE.EQ.'TR' )THEN DO 130 J = 1, N IF( UPPER )THEN IBEG = 1 IF( UNIT )THEN IEND = J - 1 ELSE IEND = J END IF ELSE IF( UNIT )THEN IBEG = J + 1 ELSE IBEG = J END IF IEND = N END IF DO 100 I = 1, IBEG - 1 AA( I + ( J - 1 )*LDA ) = ROGUE 100 CONTINUE DO 110 I = IBEG, IEND AA( I + ( J - 1 )*LDA ) = A( I, J ) 110 CONTINUE DO 120 I = IEND + 1, LDA AA( I + ( J - 1 )*LDA ) = ROGUE 120 CONTINUE 130 CONTINUE ELSE IF( TYPE.EQ.'SB'.OR.TYPE.EQ.'TB' )THEN DO 170 J = 1, N IF( UPPER )THEN KK = KL + 1 IBEG = MAX( 1, KL + 2 - J ) IF( UNIT )THEN IEND = KL ELSE IEND = KL + 1 END IF ELSE KK = 1 IF( UNIT )THEN IBEG = 2 ELSE IBEG = 1 END IF IEND = MIN( KL + 1, 1 + M - J ) END IF DO 140 I = 1, IBEG - 1 AA( I + ( J - 1 )*LDA ) = ROGUE 140 CONTINUE DO 150 I = IBEG, IEND AA( I + ( J - 1 )*LDA ) = A( I + J - KK, J ) 150 CONTINUE DO 160 I = IEND + 1, LDA AA( I + ( J - 1 )*LDA ) = ROGUE 160 CONTINUE 170 CONTINUE ELSE IF( TYPE.EQ.'SP'.OR.TYPE.EQ.'TP' )THEN IOFF = 0 DO 190 J = 1, N IF( UPPER )THEN IBEG = 1 IEND = J ELSE IBEG = J IEND = N END IF DO 180 I = IBEG, IEND IOFF = IOFF + 1 AA( IOFF ) = A( I, J ) IF( I.EQ.J )THEN IF( UNIT ) $ AA( IOFF ) = ROGUE END IF 180 CONTINUE 190 CONTINUE END IF RETURN * * End of DMAKE. * END SUBROUTINE DMVCH( TRANS, M, N, ALPHA, A, NMAX, X, INCX, BETA, Y, $ INCY, YT, G, YY, EPS, ERR, FATAL, NOUT, MV ) * * Checks the results of the computational tests. * * Auxiliary routine for test program for Level 2 Blas. * * -- Written on 10-August-1987. * Richard Hanson, Sandia National Labs. * Jeremy Du Croz, NAG Central Office. * * .. Parameters .. DOUBLE PRECISION ZERO, ONE PARAMETER ( ZERO = 0.0D0, ONE = 1.0D0 ) * .. Scalar Arguments .. DOUBLE PRECISION ALPHA, BETA, EPS, ERR INTEGER INCX, INCY, M, N, NMAX, NOUT LOGICAL FATAL, MV CHARACTER*1 TRANS * .. Array Arguments .. DOUBLE PRECISION A( NMAX, * ), G( * ), X( * ), Y( * ), YT( * ), $ YY( * ) * .. Local Scalars .. DOUBLE PRECISION ERRI INTEGER I, INCXL, INCYL, IY, J, JX, KX, KY, ML, NL LOGICAL TRAN * .. Intrinsic Functions .. INTRINSIC ABS, MAX, SQRT * .. Executable Statements .. TRAN = TRANS.EQ.'T'.OR.TRANS.EQ.'C' IF( TRAN )THEN ML = N NL = M ELSE ML = M NL = N END IF IF( INCX.LT.0 )THEN KX = NL INCXL = -1 ELSE KX = 1 INCXL = 1 END IF IF( INCY.LT.0 )THEN KY = ML INCYL = -1 ELSE KY = 1 INCYL = 1 END IF * * Compute expected result in YT using data in A, X and Y. * Compute gauges in G. * IY = KY DO 30 I = 1, ML YT( IY ) = ZERO G( IY ) = ZERO JX = KX IF( TRAN )THEN DO 10 J = 1, NL YT( IY ) = YT( IY ) + A( J, I )*X( JX ) G( IY ) = G( IY ) + ABS( A( J, I )*X( JX ) ) JX = JX + INCXL 10 CONTINUE ELSE DO 20 J = 1, NL YT( IY ) = YT( IY ) + A( I, J )*X( JX ) G( IY ) = G( IY ) + ABS( A( I, J )*X( JX ) ) JX = JX + INCXL 20 CONTINUE END IF YT( IY ) = ALPHA*YT( IY ) + BETA*Y( IY ) G( IY ) = ABS( ALPHA )*G( IY ) + ABS( BETA*Y( IY ) ) IY = IY + INCYL 30 CONTINUE * * Compute the error ratio for this result. * ERR = ZERO DO 40 I = 1, ML ERRI = ABS( YT( I ) - YY( 1 + ( I - 1 )*ABS( INCY ) ) )/EPS IF( G( I ).NE.ZERO ) $ ERRI = ERRI/G( I ) ERR = MAX( ERR, ERRI ) IF( ERR*SQRT( EPS ).GE.ONE ) $ GO TO 50 40 CONTINUE * If the loop completes, all results are at least half accurate. GO TO 70 * * Report fatal error. * 50 FATAL = .TRUE. WRITE( NOUT, FMT = 9999 ) DO 60 I = 1, ML IF( MV )THEN WRITE( NOUT, FMT = 9998 )I, YT( I ), $ YY( 1 + ( I - 1 )*ABS( INCY ) ) ELSE WRITE( NOUT, FMT = 9998 )I, $ YY( 1 + ( I - 1 )*ABS( INCY ) ), YT( I ) END IF 60 CONTINUE * 70 CONTINUE RETURN * 9999 FORMAT( ' ******* FATAL ERROR - COMPUTED RESULT IS LESS THAN HAL', $ 'F ACCURATE *******', /' EXPECTED RESULT COMPU', $ 'TED RESULT' ) 9998 FORMAT( 1X, I7, 2G18.6 ) * * End of DMVCH. * END LOGICAL FUNCTION LDE( RI, RJ, LR ) * * Tests if two arrays are identical. * * Auxiliary routine for test program for Level 2 Blas. * * -- Written on 10-August-1987. * Richard Hanson, Sandia National Labs. * Jeremy Du Croz, NAG Central Office. * * .. Scalar Arguments .. INTEGER LR * .. Array Arguments .. DOUBLE PRECISION RI( * ), RJ( * ) * .. Local Scalars .. INTEGER I * .. Executable Statements .. DO 10 I = 1, LR IF( RI( I ).NE.RJ( I ) ) $ GO TO 20 10 CONTINUE LDE = .TRUE. GO TO 30 20 CONTINUE LDE = .FALSE. 30 RETURN * * End of LDE. * END LOGICAL FUNCTION LDERES( TYPE, UPLO, M, N, AA, AS, LDA ) * * Tests if selected elements in two arrays are equal. * * TYPE is 'GE', 'SY' or 'SP'. * * Auxiliary routine for test program for Level 2 Blas. * * -- Written on 10-August-1987. * Richard Hanson, Sandia National Labs. * Jeremy Du Croz, NAG Central Office. * * .. Scalar Arguments .. INTEGER LDA, M, N CHARACTER*1 UPLO CHARACTER*2 TYPE * .. Array Arguments .. DOUBLE PRECISION AA( LDA, * ), AS( LDA, * ) * .. Local Scalars .. INTEGER I, IBEG, IEND, J LOGICAL UPPER * .. Executable Statements .. UPPER = UPLO.EQ.'U' IF( TYPE.EQ.'GE' )THEN DO 20 J = 1, N DO 10 I = M + 1, LDA IF( AA( I, J ).NE.AS( I, J ) ) $ GO TO 70 10 CONTINUE 20 CONTINUE ELSE IF( TYPE.EQ.'SY' )THEN DO 50 J = 1, N IF( UPPER )THEN IBEG = 1 IEND = J ELSE IBEG = J IEND = N END IF DO 30 I = 1, IBEG - 1 IF( AA( I, J ).NE.AS( I, J ) ) $ GO TO 70 30 CONTINUE DO 40 I = IEND + 1, LDA IF( AA( I, J ).NE.AS( I, J ) ) $ GO TO 70 40 CONTINUE 50 CONTINUE END IF * LDERES = .TRUE. GO TO 80 70 CONTINUE LDERES = .FALSE. 80 RETURN * * End of LDERES. * END DOUBLE PRECISION FUNCTION DBEG( RESET ) * * Generates random numbers uniformly distributed between -0.5 and 0.5. * * Auxiliary routine for test program for Level 2 Blas. * * -- Written on 10-August-1987. * Richard Hanson, Sandia National Labs. * Jeremy Du Croz, NAG Central Office. * * .. Scalar Arguments .. LOGICAL RESET * .. Local Scalars .. INTEGER I, IC, MI * .. Save statement .. SAVE I, IC, MI * .. Intrinsic Functions .. INTRINSIC DBLE * .. Executable Statements .. IF( RESET )THEN * Initialize local variables. MI = 891 I = 7 IC = 0 RESET = .FALSE. END IF * * The sequence of values of I is bounded between 1 and 999. * If initial I = 1,2,3,6,7 or 9, the period will be 50. * If initial I = 4 or 8, the period will be 25. * If initial I = 5, the period will be 10. * IC is used to break up the period by skipping 1 value of I in 6. * IC = IC + 1 10 I = I*MI I = I - 1000*( I/1000 ) IF( IC.GE.5 )THEN IC = 0 GO TO 10 END IF DBEG = DBLE( I - 500 )/1001.0D0 RETURN * * End of DBEG. * END DOUBLE PRECISION FUNCTION DDIFF( X, Y ) * * Auxiliary routine for test program for Level 2 Blas. * * -- Written on 10-August-1987. * Richard Hanson, Sandia National Labs. * * .. Scalar Arguments .. DOUBLE PRECISION X, Y * .. Executable Statements .. DDIFF = X - Y RETURN * * End of DDIFF. * END SUBROUTINE CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) * * Tests whether XERBLA has detected an error when it should. * * Auxiliary routine for test program for Level 2 Blas. * * -- Written on 10-August-1987. * Richard Hanson, Sandia National Labs. * Jeremy Du Croz, NAG Central Office. * * .. Scalar Arguments .. INTEGER INFOT, NOUT LOGICAL LERR, OK CHARACTER*6 SRNAMT * .. Executable Statements .. IF( .NOT.LERR )THEN WRITE( NOUT, FMT = 9999 )INFOT, SRNAMT OK = .FALSE. END IF LERR = .FALSE. RETURN * 9999 FORMAT( ' ***** ILLEGAL VALUE OF PARAMETER NUMBER ', I2, ' NOT D', $ 'ETECTED BY ', A6, ' *****' ) * * End of CHKXER. * END SUBROUTINE XERBLA( SRNAME, INFO ) * * This is a special version of XERBLA to be used only as part of * the test program for testing error exits from the Level 2 BLAS * routines. * * XERBLA is an error handler for the Level 2 BLAS routines. * * It is called by the Level 2 BLAS routines if an input parameter is * invalid. * * Auxiliary routine for test program for Level 2 Blas. * * -- Written on 10-August-1987. * Richard Hanson, Sandia National Labs. * Jeremy Du Croz, NAG Central Office. * * .. Scalar Arguments .. INTEGER INFO CHARACTER*6 SRNAME * .. Scalars in Common .. INTEGER INFOT, NOUT LOGICAL LERR, OK CHARACTER*6 SRNAMT * .. Common blocks .. COMMON /INFOC/INFOT, NOUT, OK, LERR COMMON /SRNAMC/SRNAMT * .. Executable Statements .. LERR = .TRUE. IF( INFO.NE.INFOT )THEN IF( INFOT.NE.0 )THEN WRITE( NOUT, FMT = 9999 )INFO, INFOT ELSE WRITE( NOUT, FMT = 9997 )INFO END IF OK = .FALSE. END IF IF( SRNAME.NE.SRNAMT )THEN WRITE( NOUT, FMT = 9998 )SRNAME, SRNAMT OK = .FALSE. END IF RETURN * 9999 FORMAT( ' ******* XERBLA WAS CALLED WITH INFO = ', I6, ' INSTEAD', $ ' OF ', I2, ' *******' ) 9998 FORMAT( ' ******* XERBLA WAS CALLED WITH SRNAME = ', A6, ' INSTE', $ 'AD OF ', A6, ' *******' ) 9997 FORMAT( ' ******* XERBLA WAS CALLED WITH INFO = ', I6, $ ' *******' ) * * End of XERBLA * END blis-0.9.0/blastest/src/fortran/dblat3.f000066400000000000000000003135061422157504600200720ustar00rootroot00000000000000*> \brief \b DBLAT3 * * =========== DOCUMENTATION =========== * * Online html documentation available at * http://www.netlib.org/lapack/explore-html/ * * Definition: * =========== * * PROGRAM DBLAT3 * * *> \par Purpose: * ============= *> *> \verbatim *> *> Test program for the DOUBLE PRECISION Level 3 Blas. *> *> The program must be driven by a short data file. The first 14 records *> of the file are read using list-directed input, the last 6 records *> are read using the format ( A6, L2 ). An annotated example of a data *> file can be obtained by deleting the first 3 characters from the *> following 20 lines: *> 'dblat3.out' NAME OF SUMMARY OUTPUT FILE *> 6 UNIT NUMBER OF SUMMARY FILE *> 'DBLAT3.SNAP' NAME OF SNAPSHOT OUTPUT FILE *> -1 UNIT NUMBER OF SNAPSHOT FILE (NOT USED IF .LT. 0) *> F LOGICAL FLAG, T TO REWIND SNAPSHOT FILE AFTER EACH RECORD. *> F LOGICAL FLAG, T TO STOP ON FAILURES. *> T LOGICAL FLAG, T TO TEST ERROR EXITS. *> 16.0 THRESHOLD VALUE OF TEST RATIO *> 6 NUMBER OF VALUES OF N *> 0 1 2 3 5 9 VALUES OF N *> 3 NUMBER OF VALUES OF ALPHA *> 0.0 1.0 0.7 VALUES OF ALPHA *> 3 NUMBER OF VALUES OF BETA *> 0.0 1.0 1.3 VALUES OF BETA *> DGEMM T PUT F FOR NO TEST. SAME COLUMNS. *> DSYMM T PUT F FOR NO TEST. SAME COLUMNS. *> DTRMM T PUT F FOR NO TEST. SAME COLUMNS. *> DTRSM T PUT F FOR NO TEST. SAME COLUMNS. *> DSYRK T PUT F FOR NO TEST. SAME COLUMNS. *> DSYR2K T PUT F FOR NO TEST. SAME COLUMNS. *> *> Further Details *> =============== *> *> See: *> *> Dongarra J. J., Du Croz J. J., Duff I. S. and Hammarling S. *> A Set of Level 3 Basic Linear Algebra Subprograms. *> *> Technical Memorandum No.88 (Revision 1), Mathematics and *> Computer Science Division, Argonne National Laboratory, 9700 *> South Cass Avenue, Argonne, Illinois 60439, US. *> *> -- Written on 8-February-1989. *> Jack Dongarra, Argonne National Laboratory. *> Iain Duff, AERE Harwell. *> Jeremy Du Croz, Numerical Algorithms Group Ltd. *> Sven Hammarling, Numerical Algorithms Group Ltd. *> *> 10-9-00: Change STATUS='NEW' to 'UNKNOWN' so that the testers *> can be run multiple times without deleting generated *> output files (susan) *> \endverbatim * * Authors: * ======== * *> \author Univ. of Tennessee *> \author Univ. of California Berkeley *> \author Univ. of Colorado Denver *> \author NAG Ltd. * *> \date April 2012 * *> \ingroup double_blas_testing * * ===================================================================== PROGRAM DBLAT3 * * -- Reference BLAS test routine (version 3.4.1) -- * -- Reference BLAS is a software package provided by Univ. of Tennessee, -- * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- * April 2012 * * ===================================================================== * * .. Parameters .. INTEGER NIN PARAMETER ( NIN = 5 ) INTEGER NSUBS PARAMETER ( NSUBS = 6 ) DOUBLE PRECISION ZERO, ONE PARAMETER ( ZERO = 0.0D0, ONE = 1.0D0 ) INTEGER NMAX PARAMETER ( NMAX = 65 ) INTEGER NIDMAX, NALMAX, NBEMAX PARAMETER ( NIDMAX = 9, NALMAX = 7, NBEMAX = 7 ) * .. Local Scalars .. DOUBLE PRECISION EPS, ERR, THRESH INTEGER I, ISNUM, J, N, NALF, NBET, NIDIM, NOUT, NTRA LOGICAL FATAL, LTESTT, REWI, SAME, SFATAL, TRACE, $ TSTERR CHARACTER*1 TRANSA, TRANSB CHARACTER*6 SNAMET CHARACTER*32 SNAPS, SUMMRY * .. Local Arrays .. DOUBLE PRECISION AA( NMAX*NMAX ), AB( NMAX, 2*NMAX ), $ ALF( NALMAX ), AS( NMAX*NMAX ), $ BB( NMAX*NMAX ), BET( NBEMAX ), $ BS( NMAX*NMAX ), C( NMAX, NMAX ), $ CC( NMAX*NMAX ), CS( NMAX*NMAX ), CT( NMAX ), $ G( NMAX ), W( 2*NMAX ) INTEGER IDIM( NIDMAX ) LOGICAL LTEST( NSUBS ) CHARACTER*6 SNAMES( NSUBS ) * .. External Functions .. DOUBLE PRECISION DDIFF LOGICAL LDE EXTERNAL DDIFF, LDE * .. External Subroutines .. EXTERNAL DCHK1, DCHK2, DCHK3, DCHK4, DCHK5, DCHKE, DMMCH * .. Intrinsic Functions .. INTRINSIC MAX, MIN * .. Scalars in Common .. INTEGER INFOT, NOUTC LOGICAL LERR, OK CHARACTER*6 SRNAMT * .. Common blocks .. COMMON /INFOC/INFOT, NOUTC, OK, LERR COMMON /SRNAMC/SRNAMT * .. Data statements .. DATA SNAMES/'DGEMM ', 'DSYMM ', 'DTRMM ', 'DTRSM ', $ 'DSYRK ', 'DSYR2K'/ * .. Executable Statements .. * * Read name and unit number for summary output file and open file. * READ( NIN, FMT = * )SUMMRY READ( NIN, FMT = * )NOUT OPEN( NOUT, FILE = SUMMRY, STATUS = 'UNKNOWN' ) NOUTC = NOUT * * Read name and unit number for snapshot output file and open file. * READ( NIN, FMT = * )SNAPS READ( NIN, FMT = * )NTRA TRACE = NTRA.GE.0 IF( TRACE )THEN OPEN( NTRA, FILE = SNAPS, STATUS = 'UNKNOWN' ) END IF * Read the flag that directs rewinding of the snapshot file. READ( NIN, FMT = * )REWI REWI = REWI.AND.TRACE * Read the flag that directs stopping on any failure. READ( NIN, FMT = * )SFATAL * Read the flag that indicates whether error exits are to be tested. READ( NIN, FMT = * )TSTERR * Read the threshold value of the test ratio READ( NIN, FMT = * )THRESH * * Read and check the parameter values for the tests. * * Values of N READ( NIN, FMT = * )NIDIM IF( NIDIM.LT.1.OR.NIDIM.GT.NIDMAX )THEN WRITE( NOUT, FMT = 9997 )'N', NIDMAX GO TO 220 END IF READ( NIN, FMT = * )( IDIM( I ), I = 1, NIDIM ) DO 10 I = 1, NIDIM IF( IDIM( I ).LT.0.OR.IDIM( I ).GT.NMAX )THEN WRITE( NOUT, FMT = 9996 )NMAX GO TO 220 END IF 10 CONTINUE * Values of ALPHA READ( NIN, FMT = * )NALF IF( NALF.LT.1.OR.NALF.GT.NALMAX )THEN WRITE( NOUT, FMT = 9997 )'ALPHA', NALMAX GO TO 220 END IF READ( NIN, FMT = * )( ALF( I ), I = 1, NALF ) * Values of BETA READ( NIN, FMT = * )NBET IF( NBET.LT.1.OR.NBET.GT.NBEMAX )THEN WRITE( NOUT, FMT = 9997 )'BETA', NBEMAX GO TO 220 END IF READ( NIN, FMT = * )( BET( I ), I = 1, NBET ) * * Report values of parameters. * WRITE( NOUT, FMT = 9995 ) WRITE( NOUT, FMT = 9994 )( IDIM( I ), I = 1, NIDIM ) WRITE( NOUT, FMT = 9993 )( ALF( I ), I = 1, NALF ) WRITE( NOUT, FMT = 9992 )( BET( I ), I = 1, NBET ) IF( .NOT.TSTERR )THEN WRITE( NOUT, FMT = * ) WRITE( NOUT, FMT = 9984 ) END IF WRITE( NOUT, FMT = * ) WRITE( NOUT, FMT = 9999 )THRESH WRITE( NOUT, FMT = * ) * * Read names of subroutines and flags which indicate * whether they are to be tested. * DO 20 I = 1, NSUBS LTEST( I ) = .FALSE. 20 CONTINUE 30 READ( NIN, FMT = 9988, END = 60 )SNAMET, LTESTT DO 40 I = 1, NSUBS IF( SNAMET.EQ.SNAMES( I ) ) $ GO TO 50 40 CONTINUE WRITE( NOUT, FMT = 9990 )SNAMET STOP 50 LTEST( I ) = LTESTT GO TO 30 * 60 CONTINUE CLOSE ( NIN ) * * Compute EPS (the machine precision). * EPS = EPSILON(ZERO) WRITE( NOUT, FMT = 9998 )EPS * * Check the reliability of DMMCH using exact data. * N = MIN( 32, NMAX ) DO 100 J = 1, N DO 90 I = 1, N AB( I, J ) = MAX( I - J + 1, 0 ) 90 CONTINUE AB( J, NMAX + 1 ) = J AB( 1, NMAX + J ) = J C( J, 1 ) = ZERO 100 CONTINUE DO 110 J = 1, N CC( J ) = J*( ( J + 1 )*J )/2 - ( ( J + 1 )*J*( J - 1 ) )/3 110 CONTINUE * CC holds the exact result. On exit from DMMCH CT holds * the result computed by DMMCH. TRANSA = 'N' TRANSB = 'N' CALL DMMCH( TRANSA, TRANSB, N, 1, N, ONE, AB, NMAX, $ AB( 1, NMAX + 1 ), NMAX, ZERO, C, NMAX, CT, G, CC, $ NMAX, EPS, ERR, FATAL, NOUT, .TRUE. ) SAME = LDE( CC, CT, N ) IF( .NOT.SAME.OR.ERR.NE.ZERO )THEN WRITE( NOUT, FMT = 9989 )TRANSA, TRANSB, SAME, ERR STOP END IF TRANSB = 'T' CALL DMMCH( TRANSA, TRANSB, N, 1, N, ONE, AB, NMAX, $ AB( 1, NMAX + 1 ), NMAX, ZERO, C, NMAX, CT, G, CC, $ NMAX, EPS, ERR, FATAL, NOUT, .TRUE. ) SAME = LDE( CC, CT, N ) IF( .NOT.SAME.OR.ERR.NE.ZERO )THEN WRITE( NOUT, FMT = 9989 )TRANSA, TRANSB, SAME, ERR STOP END IF DO 120 J = 1, N AB( J, NMAX + 1 ) = N - J + 1 AB( 1, NMAX + J ) = N - J + 1 120 CONTINUE DO 130 J = 1, N CC( N - J + 1 ) = J*( ( J + 1 )*J )/2 - $ ( ( J + 1 )*J*( J - 1 ) )/3 130 CONTINUE TRANSA = 'T' TRANSB = 'N' CALL DMMCH( TRANSA, TRANSB, N, 1, N, ONE, AB, NMAX, $ AB( 1, NMAX + 1 ), NMAX, ZERO, C, NMAX, CT, G, CC, $ NMAX, EPS, ERR, FATAL, NOUT, .TRUE. ) SAME = LDE( CC, CT, N ) IF( .NOT.SAME.OR.ERR.NE.ZERO )THEN WRITE( NOUT, FMT = 9989 )TRANSA, TRANSB, SAME, ERR STOP END IF TRANSB = 'T' CALL DMMCH( TRANSA, TRANSB, N, 1, N, ONE, AB, NMAX, $ AB( 1, NMAX + 1 ), NMAX, ZERO, C, NMAX, CT, G, CC, $ NMAX, EPS, ERR, FATAL, NOUT, .TRUE. ) SAME = LDE( CC, CT, N ) IF( .NOT.SAME.OR.ERR.NE.ZERO )THEN WRITE( NOUT, FMT = 9989 )TRANSA, TRANSB, SAME, ERR STOP END IF * * Test each subroutine in turn. * DO 200 ISNUM = 1, NSUBS WRITE( NOUT, FMT = * ) IF( .NOT.LTEST( ISNUM ) )THEN * Subprogram is not to be tested. WRITE( NOUT, FMT = 9987 )SNAMES( ISNUM ) ELSE SRNAMT = SNAMES( ISNUM ) * Test error exits. IF( TSTERR )THEN CALL DCHKE( ISNUM, SNAMES( ISNUM ), NOUT ) WRITE( NOUT, FMT = * ) END IF * Test computations. INFOT = 0 OK = .TRUE. FATAL = .FALSE. GO TO ( 140, 150, 160, 160, 170, 180 )ISNUM * Test DGEMM, 01. 140 CALL DCHK1( SNAMES( ISNUM ), EPS, THRESH, NOUT, NTRA, TRACE, $ REWI, FATAL, NIDIM, IDIM, NALF, ALF, NBET, BET, $ NMAX, AB, AA, AS, AB( 1, NMAX + 1 ), BB, BS, C, $ CC, CS, CT, G ) GO TO 190 * Test DSYMM, 02. 150 CALL DCHK2( SNAMES( ISNUM ), EPS, THRESH, NOUT, NTRA, TRACE, $ REWI, FATAL, NIDIM, IDIM, NALF, ALF, NBET, BET, $ NMAX, AB, AA, AS, AB( 1, NMAX + 1 ), BB, BS, C, $ CC, CS, CT, G ) GO TO 190 * Test DTRMM, 03, DTRSM, 04. 160 CALL DCHK3( SNAMES( ISNUM ), EPS, THRESH, NOUT, NTRA, TRACE, $ REWI, FATAL, NIDIM, IDIM, NALF, ALF, NMAX, AB, $ AA, AS, AB( 1, NMAX + 1 ), BB, BS, CT, G, C ) GO TO 190 * Test DSYRK, 05. 170 CALL DCHK4( SNAMES( ISNUM ), EPS, THRESH, NOUT, NTRA, TRACE, $ REWI, FATAL, NIDIM, IDIM, NALF, ALF, NBET, BET, $ NMAX, AB, AA, AS, AB( 1, NMAX + 1 ), BB, BS, C, $ CC, CS, CT, G ) GO TO 190 * Test DSYR2K, 06. 180 CALL DCHK5( SNAMES( ISNUM ), EPS, THRESH, NOUT, NTRA, TRACE, $ REWI, FATAL, NIDIM, IDIM, NALF, ALF, NBET, BET, $ NMAX, AB, AA, AS, BB, BS, C, CC, CS, CT, G, W ) GO TO 190 * 190 IF( FATAL.AND.SFATAL ) $ GO TO 210 END IF 200 CONTINUE WRITE( NOUT, FMT = 9986 ) GO TO 230 * 210 CONTINUE WRITE( NOUT, FMT = 9985 ) GO TO 230 * 220 CONTINUE WRITE( NOUT, FMT = 9991 ) * 230 CONTINUE IF( TRACE ) $ CLOSE ( NTRA ) CLOSE ( NOUT ) STOP * 9999 FORMAT( ' ROUTINES PASS COMPUTATIONAL TESTS IF TEST RATIO IS LES', $ 'S THAN', F8.2 ) 9998 FORMAT( ' RELATIVE MACHINE PRECISION IS TAKEN TO BE', 1P, D9.1 ) 9997 FORMAT( ' NUMBER OF VALUES OF ', A, ' IS LESS THAN 1 OR GREATER ', $ 'THAN ', I2 ) 9996 FORMAT( ' VALUE OF N IS LESS THAN 0 OR GREATER THAN ', I2 ) 9995 FORMAT( ' TESTS OF THE DOUBLE PRECISION LEVEL 3 BLAS', //' THE F', $ 'OLLOWING PARAMETER VALUES WILL BE USED:' ) 9994 FORMAT( ' FOR N ', 9I6 ) 9993 FORMAT( ' FOR ALPHA ', 7F6.1 ) 9992 FORMAT( ' FOR BETA ', 7F6.1 ) 9991 FORMAT( ' AMEND DATA FILE OR INCREASE ARRAY SIZES IN PROGRAM', $ /' ******* TESTS ABANDONED *******' ) 9990 FORMAT( ' SUBPROGRAM NAME ', A6, ' NOT RECOGNIZED', /' ******* T', $ 'ESTS ABANDONED *******' ) 9989 FORMAT( ' ERROR IN DMMCH - IN-LINE DOT PRODUCTS ARE BEING EVALU', $ 'ATED WRONGLY.', /' DMMCH WAS CALLED WITH TRANSA = ', A1, $ ' AND TRANSB = ', A1, /' AND RETURNED SAME = ', L1, ' AND ', $ 'ERR = ', F12.3, '.', /' THIS MAY BE DUE TO FAULTS IN THE ', $ 'ARITHMETIC OR THE COMPILER.', /' ******* TESTS ABANDONED ', $ '*******' ) 9988 FORMAT( A6, L2 ) 9987 FORMAT( 1X, A6, ' WAS NOT TESTED' ) 9986 FORMAT( /' END OF TESTS' ) 9985 FORMAT( /' ******* FATAL ERROR - TESTS ABANDONED *******' ) 9984 FORMAT( ' ERROR-EXITS WILL NOT BE TESTED' ) * * End of DBLAT3. * END SUBROUTINE DCHK1( SNAME, EPS, THRESH, NOUT, NTRA, TRACE, REWI, $ FATAL, NIDIM, IDIM, NALF, ALF, NBET, BET, NMAX, $ A, AA, AS, B, BB, BS, C, CC, CS, CT, G ) * * Tests DGEMM. * * Auxiliary routine for test program for Level 3 Blas. * * -- Written on 8-February-1989. * Jack Dongarra, Argonne National Laboratory. * Iain Duff, AERE Harwell. * Jeremy Du Croz, Numerical Algorithms Group Ltd. * Sven Hammarling, Numerical Algorithms Group Ltd. * * .. Parameters .. DOUBLE PRECISION ZERO PARAMETER ( ZERO = 0.0D0 ) * .. Scalar Arguments .. DOUBLE PRECISION EPS, THRESH INTEGER NALF, NBET, NIDIM, NMAX, NOUT, NTRA LOGICAL FATAL, REWI, TRACE CHARACTER*6 SNAME * .. Array Arguments .. DOUBLE PRECISION A( NMAX, NMAX ), AA( NMAX*NMAX ), ALF( NALF ), $ AS( NMAX*NMAX ), B( NMAX, NMAX ), $ BB( NMAX*NMAX ), BET( NBET ), BS( NMAX*NMAX ), $ C( NMAX, NMAX ), CC( NMAX*NMAX ), $ CS( NMAX*NMAX ), CT( NMAX ), G( NMAX ) INTEGER IDIM( NIDIM ) * .. Local Scalars .. DOUBLE PRECISION ALPHA, ALS, BETA, BLS, ERR, ERRMAX INTEGER I, IA, IB, ICA, ICB, IK, IM, IN, K, KS, LAA, $ LBB, LCC, LDA, LDAS, LDB, LDBS, LDC, LDCS, M, $ MA, MB, MS, N, NA, NARGS, NB, NC, NS LOGICAL NULL, RESET, SAME, TRANA, TRANB CHARACTER*1 TRANAS, TRANBS, TRANSA, TRANSB CHARACTER*3 ICH * .. Local Arrays .. LOGICAL ISAME( 13 ) * .. External Functions .. LOGICAL LDE, LDERES EXTERNAL LDE, LDERES * .. External Subroutines .. EXTERNAL DGEMM, DMAKE, DMMCH * .. Intrinsic Functions .. INTRINSIC MAX * .. Scalars in Common .. INTEGER INFOT, NOUTC LOGICAL LERR, OK * .. Common blocks .. COMMON /INFOC/INFOT, NOUTC, OK, LERR * .. Data statements .. DATA ICH/'NTC'/ * .. Executable Statements .. * NARGS = 13 NC = 0 RESET = .TRUE. ERRMAX = ZERO * DO 110 IM = 1, NIDIM M = IDIM( IM ) * DO 100 IN = 1, NIDIM N = IDIM( IN ) * Set LDC to 1 more than minimum value if room. LDC = M IF( LDC.LT.NMAX ) $ LDC = LDC + 1 * Skip tests if not enough room. IF( LDC.GT.NMAX ) $ GO TO 100 LCC = LDC*N NULL = N.LE.0.OR.M.LE.0 * DO 90 IK = 1, NIDIM K = IDIM( IK ) * DO 80 ICA = 1, 3 TRANSA = ICH( ICA: ICA ) TRANA = TRANSA.EQ.'T'.OR.TRANSA.EQ.'C' * IF( TRANA )THEN MA = K NA = M ELSE MA = M NA = K END IF * Set LDA to 1 more than minimum value if room. LDA = MA IF( LDA.LT.NMAX ) $ LDA = LDA + 1 * Skip tests if not enough room. IF( LDA.GT.NMAX ) $ GO TO 80 LAA = LDA*NA * * Generate the matrix A. * CALL DMAKE( 'GE', ' ', ' ', MA, NA, A, NMAX, AA, LDA, $ RESET, ZERO ) * DO 70 ICB = 1, 3 TRANSB = ICH( ICB: ICB ) TRANB = TRANSB.EQ.'T'.OR.TRANSB.EQ.'C' * IF( TRANB )THEN MB = N NB = K ELSE MB = K NB = N END IF * Set LDB to 1 more than minimum value if room. LDB = MB IF( LDB.LT.NMAX ) $ LDB = LDB + 1 * Skip tests if not enough room. IF( LDB.GT.NMAX ) $ GO TO 70 LBB = LDB*NB * * Generate the matrix B. * CALL DMAKE( 'GE', ' ', ' ', MB, NB, B, NMAX, BB, $ LDB, RESET, ZERO ) * DO 60 IA = 1, NALF ALPHA = ALF( IA ) * DO 50 IB = 1, NBET BETA = BET( IB ) * * Generate the matrix C. * CALL DMAKE( 'GE', ' ', ' ', M, N, C, NMAX, $ CC, LDC, RESET, ZERO ) * NC = NC + 1 * * Save every datum before calling the * subroutine. * TRANAS = TRANSA TRANBS = TRANSB MS = M NS = N KS = K ALS = ALPHA DO 10 I = 1, LAA AS( I ) = AA( I ) 10 CONTINUE LDAS = LDA DO 20 I = 1, LBB BS( I ) = BB( I ) 20 CONTINUE LDBS = LDB BLS = BETA DO 30 I = 1, LCC CS( I ) = CC( I ) 30 CONTINUE LDCS = LDC * * Call the subroutine. * IF( TRACE ) $ WRITE( NTRA, FMT = 9995 )NC, SNAME, $ TRANSA, TRANSB, M, N, K, ALPHA, LDA, LDB, $ BETA, LDC IF( REWI ) $ REWIND NTRA CALL DGEMM( TRANSA, TRANSB, M, N, K, ALPHA, $ AA, LDA, BB, LDB, BETA, CC, LDC ) * * Check if error-exit was taken incorrectly. * IF( .NOT.OK )THEN WRITE( NOUT, FMT = 9994 ) FATAL = .TRUE. GO TO 120 END IF * * See what data changed inside subroutines. * ISAME( 1 ) = TRANSA.EQ.TRANAS ISAME( 2 ) = TRANSB.EQ.TRANBS ISAME( 3 ) = MS.EQ.M ISAME( 4 ) = NS.EQ.N ISAME( 5 ) = KS.EQ.K ISAME( 6 ) = ALS.EQ.ALPHA ISAME( 7 ) = LDE( AS, AA, LAA ) ISAME( 8 ) = LDAS.EQ.LDA ISAME( 9 ) = LDE( BS, BB, LBB ) ISAME( 10 ) = LDBS.EQ.LDB ISAME( 11 ) = BLS.EQ.BETA IF( NULL )THEN ISAME( 12 ) = LDE( CS, CC, LCC ) ELSE ISAME( 12 ) = LDERES( 'GE', ' ', M, N, CS, $ CC, LDC ) END IF ISAME( 13 ) = LDCS.EQ.LDC * * If data was incorrectly changed, report * and return. * SAME = .TRUE. DO 40 I = 1, NARGS SAME = SAME.AND.ISAME( I ) IF( .NOT.ISAME( I ) ) $ WRITE( NOUT, FMT = 9998 )I 40 CONTINUE IF( .NOT.SAME )THEN FATAL = .TRUE. GO TO 120 END IF * IF( .NOT.NULL )THEN * * Check the result. * CALL DMMCH( TRANSA, TRANSB, M, N, K, $ ALPHA, A, NMAX, B, NMAX, BETA, $ C, NMAX, CT, G, CC, LDC, EPS, $ ERR, FATAL, NOUT, .TRUE. ) ERRMAX = MAX( ERRMAX, ERR ) * If got really bad answer, report and * return. IF( FATAL ) $ GO TO 120 END IF * 50 CONTINUE * 60 CONTINUE * 70 CONTINUE * 80 CONTINUE * 90 CONTINUE * 100 CONTINUE * 110 CONTINUE * * Report result. * IF( ERRMAX.LT.THRESH )THEN WRITE( NOUT, FMT = 9999 )SNAME, NC ELSE WRITE( NOUT, FMT = 9997 )SNAME, NC, ERRMAX END IF GO TO 130 * 120 CONTINUE WRITE( NOUT, FMT = 9996 )SNAME WRITE( NOUT, FMT = 9995 )NC, SNAME, TRANSA, TRANSB, M, N, K, $ ALPHA, LDA, LDB, BETA, LDC * 130 CONTINUE RETURN * 9999 FORMAT( ' ', A6, ' PASSED THE COMPUTATIONAL TESTS (', I6, ' CALL', $ 'S)' ) 9998 FORMAT( ' ******* FATAL ERROR - PARAMETER NUMBER ', I2, ' WAS CH', $ 'ANGED INCORRECTLY *******' ) 9997 FORMAT( ' ', A6, ' COMPLETED THE COMPUTATIONAL TESTS (', I6, ' C', $ 'ALLS)', /' ******* BUT WITH MAXIMUM TEST RATIO', F8.2, $ ' - SUSPECT *******' ) 9996 FORMAT( ' ******* ', A6, ' FAILED ON CALL NUMBER:' ) 9995 FORMAT( 1X, I6, ': ', A6, '(''', A1, ''',''', A1, ''',', $ 3( I3, ',' ), F4.1, ', A,', I3, ', B,', I3, ',', F4.1, ', ', $ 'C,', I3, ').' ) 9994 FORMAT( ' ******* FATAL ERROR - ERROR-EXIT TAKEN ON VALID CALL *', $ '******' ) * * End of DCHK1. * END SUBROUTINE DCHK2( SNAME, EPS, THRESH, NOUT, NTRA, TRACE, REWI, $ FATAL, NIDIM, IDIM, NALF, ALF, NBET, BET, NMAX, $ A, AA, AS, B, BB, BS, C, CC, CS, CT, G ) * * Tests DSYMM. * * Auxiliary routine for test program for Level 3 Blas. * * -- Written on 8-February-1989. * Jack Dongarra, Argonne National Laboratory. * Iain Duff, AERE Harwell. * Jeremy Du Croz, Numerical Algorithms Group Ltd. * Sven Hammarling, Numerical Algorithms Group Ltd. * * .. Parameters .. DOUBLE PRECISION ZERO PARAMETER ( ZERO = 0.0D0 ) * .. Scalar Arguments .. DOUBLE PRECISION EPS, THRESH INTEGER NALF, NBET, NIDIM, NMAX, NOUT, NTRA LOGICAL FATAL, REWI, TRACE CHARACTER*6 SNAME * .. Array Arguments .. DOUBLE PRECISION A( NMAX, NMAX ), AA( NMAX*NMAX ), ALF( NALF ), $ AS( NMAX*NMAX ), B( NMAX, NMAX ), $ BB( NMAX*NMAX ), BET( NBET ), BS( NMAX*NMAX ), $ C( NMAX, NMAX ), CC( NMAX*NMAX ), $ CS( NMAX*NMAX ), CT( NMAX ), G( NMAX ) INTEGER IDIM( NIDIM ) * .. Local Scalars .. DOUBLE PRECISION ALPHA, ALS, BETA, BLS, ERR, ERRMAX INTEGER I, IA, IB, ICS, ICU, IM, IN, LAA, LBB, LCC, $ LDA, LDAS, LDB, LDBS, LDC, LDCS, M, MS, N, NA, $ NARGS, NC, NS LOGICAL LEFT, NULL, RESET, SAME CHARACTER*1 SIDE, SIDES, UPLO, UPLOS CHARACTER*2 ICHS, ICHU * .. Local Arrays .. LOGICAL ISAME( 13 ) * .. External Functions .. LOGICAL LDE, LDERES EXTERNAL LDE, LDERES * .. External Subroutines .. EXTERNAL DMAKE, DMMCH, DSYMM * .. Intrinsic Functions .. INTRINSIC MAX * .. Scalars in Common .. INTEGER INFOT, NOUTC LOGICAL LERR, OK * .. Common blocks .. COMMON /INFOC/INFOT, NOUTC, OK, LERR * .. Data statements .. DATA ICHS/'LR'/, ICHU/'UL'/ * .. Executable Statements .. * NARGS = 12 NC = 0 RESET = .TRUE. ERRMAX = ZERO * DO 100 IM = 1, NIDIM M = IDIM( IM ) * DO 90 IN = 1, NIDIM N = IDIM( IN ) * Set LDC to 1 more than minimum value if room. LDC = M IF( LDC.LT.NMAX ) $ LDC = LDC + 1 * Skip tests if not enough room. IF( LDC.GT.NMAX ) $ GO TO 90 LCC = LDC*N NULL = N.LE.0.OR.M.LE.0 * * Set LDB to 1 more than minimum value if room. LDB = M IF( LDB.LT.NMAX ) $ LDB = LDB + 1 * Skip tests if not enough room. IF( LDB.GT.NMAX ) $ GO TO 90 LBB = LDB*N * * Generate the matrix B. * CALL DMAKE( 'GE', ' ', ' ', M, N, B, NMAX, BB, LDB, RESET, $ ZERO ) * DO 80 ICS = 1, 2 SIDE = ICHS( ICS: ICS ) LEFT = SIDE.EQ.'L' * IF( LEFT )THEN NA = M ELSE NA = N END IF * Set LDA to 1 more than minimum value if room. LDA = NA IF( LDA.LT.NMAX ) $ LDA = LDA + 1 * Skip tests if not enough room. IF( LDA.GT.NMAX ) $ GO TO 80 LAA = LDA*NA * DO 70 ICU = 1, 2 UPLO = ICHU( ICU: ICU ) * * Generate the symmetric matrix A. * CALL DMAKE( 'SY', UPLO, ' ', NA, NA, A, NMAX, AA, LDA, $ RESET, ZERO ) * DO 60 IA = 1, NALF ALPHA = ALF( IA ) * DO 50 IB = 1, NBET BETA = BET( IB ) * * Generate the matrix C. * CALL DMAKE( 'GE', ' ', ' ', M, N, C, NMAX, CC, $ LDC, RESET, ZERO ) * NC = NC + 1 * * Save every datum before calling the * subroutine. * SIDES = SIDE UPLOS = UPLO MS = M NS = N ALS = ALPHA DO 10 I = 1, LAA AS( I ) = AA( I ) 10 CONTINUE LDAS = LDA DO 20 I = 1, LBB BS( I ) = BB( I ) 20 CONTINUE LDBS = LDB BLS = BETA DO 30 I = 1, LCC CS( I ) = CC( I ) 30 CONTINUE LDCS = LDC * * Call the subroutine. * IF( TRACE ) $ WRITE( NTRA, FMT = 9995 )NC, SNAME, SIDE, $ UPLO, M, N, ALPHA, LDA, LDB, BETA, LDC IF( REWI ) $ REWIND NTRA CALL DSYMM( SIDE, UPLO, M, N, ALPHA, AA, LDA, $ BB, LDB, BETA, CC, LDC ) * * Check if error-exit was taken incorrectly. * IF( .NOT.OK )THEN WRITE( NOUT, FMT = 9994 ) FATAL = .TRUE. GO TO 110 END IF * * See what data changed inside subroutines. * ISAME( 1 ) = SIDES.EQ.SIDE ISAME( 2 ) = UPLOS.EQ.UPLO ISAME( 3 ) = MS.EQ.M ISAME( 4 ) = NS.EQ.N ISAME( 5 ) = ALS.EQ.ALPHA ISAME( 6 ) = LDE( AS, AA, LAA ) ISAME( 7 ) = LDAS.EQ.LDA ISAME( 8 ) = LDE( BS, BB, LBB ) ISAME( 9 ) = LDBS.EQ.LDB ISAME( 10 ) = BLS.EQ.BETA IF( NULL )THEN ISAME( 11 ) = LDE( CS, CC, LCC ) ELSE ISAME( 11 ) = LDERES( 'GE', ' ', M, N, CS, $ CC, LDC ) END IF ISAME( 12 ) = LDCS.EQ.LDC * * If data was incorrectly changed, report and * return. * SAME = .TRUE. DO 40 I = 1, NARGS SAME = SAME.AND.ISAME( I ) IF( .NOT.ISAME( I ) ) $ WRITE( NOUT, FMT = 9998 )I 40 CONTINUE IF( .NOT.SAME )THEN FATAL = .TRUE. GO TO 110 END IF * IF( .NOT.NULL )THEN * * Check the result. * IF( LEFT )THEN CALL DMMCH( 'N', 'N', M, N, M, ALPHA, A, $ NMAX, B, NMAX, BETA, C, NMAX, $ CT, G, CC, LDC, EPS, ERR, $ FATAL, NOUT, .TRUE. ) ELSE CALL DMMCH( 'N', 'N', M, N, N, ALPHA, B, $ NMAX, A, NMAX, BETA, C, NMAX, $ CT, G, CC, LDC, EPS, ERR, $ FATAL, NOUT, .TRUE. ) END IF ERRMAX = MAX( ERRMAX, ERR ) * If got really bad answer, report and * return. IF( FATAL ) $ GO TO 110 END IF * 50 CONTINUE * 60 CONTINUE * 70 CONTINUE * 80 CONTINUE * 90 CONTINUE * 100 CONTINUE * * Report result. * IF( ERRMAX.LT.THRESH )THEN WRITE( NOUT, FMT = 9999 )SNAME, NC ELSE WRITE( NOUT, FMT = 9997 )SNAME, NC, ERRMAX END IF GO TO 120 * 110 CONTINUE WRITE( NOUT, FMT = 9996 )SNAME WRITE( NOUT, FMT = 9995 )NC, SNAME, SIDE, UPLO, M, N, ALPHA, LDA, $ LDB, BETA, LDC * 120 CONTINUE RETURN * 9999 FORMAT( ' ', A6, ' PASSED THE COMPUTATIONAL TESTS (', I6, ' CALL', $ 'S)' ) 9998 FORMAT( ' ******* FATAL ERROR - PARAMETER NUMBER ', I2, ' WAS CH', $ 'ANGED INCORRECTLY *******' ) 9997 FORMAT( ' ', A6, ' COMPLETED THE COMPUTATIONAL TESTS (', I6, ' C', $ 'ALLS)', /' ******* BUT WITH MAXIMUM TEST RATIO', F8.2, $ ' - SUSPECT *******' ) 9996 FORMAT( ' ******* ', A6, ' FAILED ON CALL NUMBER:' ) 9995 FORMAT( 1X, I6, ': ', A6, '(', 2( '''', A1, ''',' ), 2( I3, ',' ), $ F4.1, ', A,', I3, ', B,', I3, ',', F4.1, ', C,', I3, ') ', $ ' .' ) 9994 FORMAT( ' ******* FATAL ERROR - ERROR-EXIT TAKEN ON VALID CALL *', $ '******' ) * * End of DCHK2. * END SUBROUTINE DCHK3( SNAME, EPS, THRESH, NOUT, NTRA, TRACE, REWI, $ FATAL, NIDIM, IDIM, NALF, ALF, NMAX, A, AA, AS, $ B, BB, BS, CT, G, C ) * * Tests DTRMM and DTRSM. * * Auxiliary routine for test program for Level 3 Blas. * * -- Written on 8-February-1989. * Jack Dongarra, Argonne National Laboratory. * Iain Duff, AERE Harwell. * Jeremy Du Croz, Numerical Algorithms Group Ltd. * Sven Hammarling, Numerical Algorithms Group Ltd. * * .. Parameters .. DOUBLE PRECISION ZERO, ONE PARAMETER ( ZERO = 0.0D0, ONE = 1.0D0 ) * .. Scalar Arguments .. DOUBLE PRECISION EPS, THRESH INTEGER NALF, NIDIM, NMAX, NOUT, NTRA LOGICAL FATAL, REWI, TRACE CHARACTER*6 SNAME * .. Array Arguments .. DOUBLE PRECISION A( NMAX, NMAX ), AA( NMAX*NMAX ), ALF( NALF ), $ AS( NMAX*NMAX ), B( NMAX, NMAX ), $ BB( NMAX*NMAX ), BS( NMAX*NMAX ), $ C( NMAX, NMAX ), CT( NMAX ), G( NMAX ) INTEGER IDIM( NIDIM ) * .. Local Scalars .. DOUBLE PRECISION ALPHA, ALS, ERR, ERRMAX INTEGER I, IA, ICD, ICS, ICT, ICU, IM, IN, J, LAA, LBB, $ LDA, LDAS, LDB, LDBS, M, MS, N, NA, NARGS, NC, $ NS LOGICAL LEFT, NULL, RESET, SAME CHARACTER*1 DIAG, DIAGS, SIDE, SIDES, TRANAS, TRANSA, UPLO, $ UPLOS CHARACTER*2 ICHD, ICHS, ICHU CHARACTER*3 ICHT * .. Local Arrays .. LOGICAL ISAME( 13 ) * .. External Functions .. LOGICAL LDE, LDERES EXTERNAL LDE, LDERES * .. External Subroutines .. EXTERNAL DMAKE, DMMCH, DTRMM, DTRSM * .. Intrinsic Functions .. INTRINSIC MAX * .. Scalars in Common .. INTEGER INFOT, NOUTC LOGICAL LERR, OK * .. Common blocks .. COMMON /INFOC/INFOT, NOUTC, OK, LERR * .. Data statements .. DATA ICHU/'UL'/, ICHT/'NTC'/, ICHD/'UN'/, ICHS/'LR'/ * .. Executable Statements .. * NARGS = 11 NC = 0 RESET = .TRUE. ERRMAX = ZERO * Set up zero matrix for DMMCH. DO 20 J = 1, NMAX DO 10 I = 1, NMAX C( I, J ) = ZERO 10 CONTINUE 20 CONTINUE * DO 140 IM = 1, NIDIM M = IDIM( IM ) * DO 130 IN = 1, NIDIM N = IDIM( IN ) * Set LDB to 1 more than minimum value if room. LDB = M IF( LDB.LT.NMAX ) $ LDB = LDB + 1 * Skip tests if not enough room. IF( LDB.GT.NMAX ) $ GO TO 130 LBB = LDB*N NULL = M.LE.0.OR.N.LE.0 * DO 120 ICS = 1, 2 SIDE = ICHS( ICS: ICS ) LEFT = SIDE.EQ.'L' IF( LEFT )THEN NA = M ELSE NA = N END IF * Set LDA to 1 more than minimum value if room. LDA = NA IF( LDA.LT.NMAX ) $ LDA = LDA + 1 * Skip tests if not enough room. IF( LDA.GT.NMAX ) $ GO TO 130 LAA = LDA*NA * DO 110 ICU = 1, 2 UPLO = ICHU( ICU: ICU ) * DO 100 ICT = 1, 3 TRANSA = ICHT( ICT: ICT ) * DO 90 ICD = 1, 2 DIAG = ICHD( ICD: ICD ) * DO 80 IA = 1, NALF ALPHA = ALF( IA ) * * Generate the matrix A. * CALL DMAKE( 'TR', UPLO, DIAG, NA, NA, A, $ NMAX, AA, LDA, RESET, ZERO ) * * Generate the matrix B. * CALL DMAKE( 'GE', ' ', ' ', M, N, B, NMAX, $ BB, LDB, RESET, ZERO ) * NC = NC + 1 * * Save every datum before calling the * subroutine. * SIDES = SIDE UPLOS = UPLO TRANAS = TRANSA DIAGS = DIAG MS = M NS = N ALS = ALPHA DO 30 I = 1, LAA AS( I ) = AA( I ) 30 CONTINUE LDAS = LDA DO 40 I = 1, LBB BS( I ) = BB( I ) 40 CONTINUE LDBS = LDB * * Call the subroutine. * IF( SNAME( 4: 5 ).EQ.'MM' )THEN IF( TRACE ) $ WRITE( NTRA, FMT = 9995 )NC, SNAME, $ SIDE, UPLO, TRANSA, DIAG, M, N, ALPHA, $ LDA, LDB IF( REWI ) $ REWIND NTRA CALL DTRMM( SIDE, UPLO, TRANSA, DIAG, M, $ N, ALPHA, AA, LDA, BB, LDB ) ELSE IF( SNAME( 4: 5 ).EQ.'SM' )THEN IF( TRACE ) $ WRITE( NTRA, FMT = 9995 )NC, SNAME, $ SIDE, UPLO, TRANSA, DIAG, M, N, ALPHA, $ LDA, LDB IF( REWI ) $ REWIND NTRA CALL DTRSM( SIDE, UPLO, TRANSA, DIAG, M, $ N, ALPHA, AA, LDA, BB, LDB ) END IF * * Check if error-exit was taken incorrectly. * IF( .NOT.OK )THEN WRITE( NOUT, FMT = 9994 ) FATAL = .TRUE. GO TO 150 END IF * * See what data changed inside subroutines. * ISAME( 1 ) = SIDES.EQ.SIDE ISAME( 2 ) = UPLOS.EQ.UPLO ISAME( 3 ) = TRANAS.EQ.TRANSA ISAME( 4 ) = DIAGS.EQ.DIAG ISAME( 5 ) = MS.EQ.M ISAME( 6 ) = NS.EQ.N ISAME( 7 ) = ALS.EQ.ALPHA ISAME( 8 ) = LDE( AS, AA, LAA ) ISAME( 9 ) = LDAS.EQ.LDA IF( NULL )THEN ISAME( 10 ) = LDE( BS, BB, LBB ) ELSE ISAME( 10 ) = LDERES( 'GE', ' ', M, N, BS, $ BB, LDB ) END IF ISAME( 11 ) = LDBS.EQ.LDB * * If data was incorrectly changed, report and * return. * SAME = .TRUE. DO 50 I = 1, NARGS SAME = SAME.AND.ISAME( I ) IF( .NOT.ISAME( I ) ) $ WRITE( NOUT, FMT = 9998 )I 50 CONTINUE IF( .NOT.SAME )THEN FATAL = .TRUE. GO TO 150 END IF * IF( .NOT.NULL )THEN IF( SNAME( 4: 5 ).EQ.'MM' )THEN * * Check the result. * IF( LEFT )THEN CALL DMMCH( TRANSA, 'N', M, N, M, $ ALPHA, A, NMAX, B, NMAX, $ ZERO, C, NMAX, CT, G, $ BB, LDB, EPS, ERR, $ FATAL, NOUT, .TRUE. ) ELSE CALL DMMCH( 'N', TRANSA, M, N, N, $ ALPHA, B, NMAX, A, NMAX, $ ZERO, C, NMAX, CT, G, $ BB, LDB, EPS, ERR, $ FATAL, NOUT, .TRUE. ) END IF ELSE IF( SNAME( 4: 5 ).EQ.'SM' )THEN * * Compute approximation to original * matrix. * DO 70 J = 1, N DO 60 I = 1, M C( I, J ) = BB( I + ( J - 1 )* $ LDB ) BB( I + ( J - 1 )*LDB ) = ALPHA* $ B( I, J ) 60 CONTINUE 70 CONTINUE * IF( LEFT )THEN CALL DMMCH( TRANSA, 'N', M, N, M, $ ONE, A, NMAX, C, NMAX, $ ZERO, B, NMAX, CT, G, $ BB, LDB, EPS, ERR, $ FATAL, NOUT, .FALSE. ) ELSE CALL DMMCH( 'N', TRANSA, M, N, N, $ ONE, C, NMAX, A, NMAX, $ ZERO, B, NMAX, CT, G, $ BB, LDB, EPS, ERR, $ FATAL, NOUT, .FALSE. ) END IF END IF ERRMAX = MAX( ERRMAX, ERR ) * If got really bad answer, report and * return. IF( FATAL ) $ GO TO 150 END IF * 80 CONTINUE * 90 CONTINUE * 100 CONTINUE * 110 CONTINUE * 120 CONTINUE * 130 CONTINUE * 140 CONTINUE * * Report result. * IF( ERRMAX.LT.THRESH )THEN WRITE( NOUT, FMT = 9999 )SNAME, NC ELSE WRITE( NOUT, FMT = 9997 )SNAME, NC, ERRMAX END IF GO TO 160 * 150 CONTINUE WRITE( NOUT, FMT = 9996 )SNAME WRITE( NOUT, FMT = 9995 )NC, SNAME, SIDE, UPLO, TRANSA, DIAG, M, $ N, ALPHA, LDA, LDB * 160 CONTINUE RETURN * 9999 FORMAT( ' ', A6, ' PASSED THE COMPUTATIONAL TESTS (', I6, ' CALL', $ 'S)' ) 9998 FORMAT( ' ******* FATAL ERROR - PARAMETER NUMBER ', I2, ' WAS CH', $ 'ANGED INCORRECTLY *******' ) 9997 FORMAT( ' ', A6, ' COMPLETED THE COMPUTATIONAL TESTS (', I6, ' C', $ 'ALLS)', /' ******* BUT WITH MAXIMUM TEST RATIO', F8.2, $ ' - SUSPECT *******' ) 9996 FORMAT( ' ******* ', A6, ' FAILED ON CALL NUMBER:' ) 9995 FORMAT( 1X, I6, ': ', A6, '(', 4( '''', A1, ''',' ), 2( I3, ',' ), $ F4.1, ', A,', I3, ', B,', I3, ') .' ) 9994 FORMAT( ' ******* FATAL ERROR - ERROR-EXIT TAKEN ON VALID CALL *', $ '******' ) * * End of DCHK3. * END SUBROUTINE DCHK4( SNAME, EPS, THRESH, NOUT, NTRA, TRACE, REWI, $ FATAL, NIDIM, IDIM, NALF, ALF, NBET, BET, NMAX, $ A, AA, AS, B, BB, BS, C, CC, CS, CT, G ) * * Tests DSYRK. * * Auxiliary routine for test program for Level 3 Blas. * * -- Written on 8-February-1989. * Jack Dongarra, Argonne National Laboratory. * Iain Duff, AERE Harwell. * Jeremy Du Croz, Numerical Algorithms Group Ltd. * Sven Hammarling, Numerical Algorithms Group Ltd. * * .. Parameters .. DOUBLE PRECISION ZERO PARAMETER ( ZERO = 0.0D0 ) * .. Scalar Arguments .. DOUBLE PRECISION EPS, THRESH INTEGER NALF, NBET, NIDIM, NMAX, NOUT, NTRA LOGICAL FATAL, REWI, TRACE CHARACTER*6 SNAME * .. Array Arguments .. DOUBLE PRECISION A( NMAX, NMAX ), AA( NMAX*NMAX ), ALF( NALF ), $ AS( NMAX*NMAX ), B( NMAX, NMAX ), $ BB( NMAX*NMAX ), BET( NBET ), BS( NMAX*NMAX ), $ C( NMAX, NMAX ), CC( NMAX*NMAX ), $ CS( NMAX*NMAX ), CT( NMAX ), G( NMAX ) INTEGER IDIM( NIDIM ) * .. Local Scalars .. DOUBLE PRECISION ALPHA, ALS, BETA, BETS, ERR, ERRMAX INTEGER I, IA, IB, ICT, ICU, IK, IN, J, JC, JJ, K, KS, $ LAA, LCC, LDA, LDAS, LDC, LDCS, LJ, MA, N, NA, $ NARGS, NC, NS LOGICAL NULL, RESET, SAME, TRAN, UPPER CHARACTER*1 TRANS, TRANSS, UPLO, UPLOS CHARACTER*2 ICHU CHARACTER*3 ICHT * .. Local Arrays .. LOGICAL ISAME( 13 ) * .. External Functions .. LOGICAL LDE, LDERES EXTERNAL LDE, LDERES * .. External Subroutines .. EXTERNAL DMAKE, DMMCH, DSYRK * .. Intrinsic Functions .. INTRINSIC MAX * .. Scalars in Common .. INTEGER INFOT, NOUTC LOGICAL LERR, OK * .. Common blocks .. COMMON /INFOC/INFOT, NOUTC, OK, LERR * .. Data statements .. DATA ICHT/'NTC'/, ICHU/'UL'/ * .. Executable Statements .. * NARGS = 10 NC = 0 RESET = .TRUE. ERRMAX = ZERO * DO 100 IN = 1, NIDIM N = IDIM( IN ) * Set LDC to 1 more than minimum value if room. LDC = N IF( LDC.LT.NMAX ) $ LDC = LDC + 1 * Skip tests if not enough room. IF( LDC.GT.NMAX ) $ GO TO 100 LCC = LDC*N NULL = N.LE.0 * DO 90 IK = 1, NIDIM K = IDIM( IK ) * DO 80 ICT = 1, 3 TRANS = ICHT( ICT: ICT ) TRAN = TRANS.EQ.'T'.OR.TRANS.EQ.'C' IF( TRAN )THEN MA = K NA = N ELSE MA = N NA = K END IF * Set LDA to 1 more than minimum value if room. LDA = MA IF( LDA.LT.NMAX ) $ LDA = LDA + 1 * Skip tests if not enough room. IF( LDA.GT.NMAX ) $ GO TO 80 LAA = LDA*NA * * Generate the matrix A. * CALL DMAKE( 'GE', ' ', ' ', MA, NA, A, NMAX, AA, LDA, $ RESET, ZERO ) * DO 70 ICU = 1, 2 UPLO = ICHU( ICU: ICU ) UPPER = UPLO.EQ.'U' * DO 60 IA = 1, NALF ALPHA = ALF( IA ) * DO 50 IB = 1, NBET BETA = BET( IB ) * * Generate the matrix C. * CALL DMAKE( 'SY', UPLO, ' ', N, N, C, NMAX, CC, $ LDC, RESET, ZERO ) * NC = NC + 1 * * Save every datum before calling the subroutine. * UPLOS = UPLO TRANSS = TRANS NS = N KS = K ALS = ALPHA DO 10 I = 1, LAA AS( I ) = AA( I ) 10 CONTINUE LDAS = LDA BETS = BETA DO 20 I = 1, LCC CS( I ) = CC( I ) 20 CONTINUE LDCS = LDC * * Call the subroutine. * IF( TRACE ) $ WRITE( NTRA, FMT = 9994 )NC, SNAME, UPLO, $ TRANS, N, K, ALPHA, LDA, BETA, LDC IF( REWI ) $ REWIND NTRA CALL DSYRK( UPLO, TRANS, N, K, ALPHA, AA, LDA, $ BETA, CC, LDC ) * * Check if error-exit was taken incorrectly. * IF( .NOT.OK )THEN WRITE( NOUT, FMT = 9993 ) FATAL = .TRUE. GO TO 120 END IF * * See what data changed inside subroutines. * ISAME( 1 ) = UPLOS.EQ.UPLO ISAME( 2 ) = TRANSS.EQ.TRANS ISAME( 3 ) = NS.EQ.N ISAME( 4 ) = KS.EQ.K ISAME( 5 ) = ALS.EQ.ALPHA ISAME( 6 ) = LDE( AS, AA, LAA ) ISAME( 7 ) = LDAS.EQ.LDA ISAME( 8 ) = BETS.EQ.BETA IF( NULL )THEN ISAME( 9 ) = LDE( CS, CC, LCC ) ELSE ISAME( 9 ) = LDERES( 'SY', UPLO, N, N, CS, $ CC, LDC ) END IF ISAME( 10 ) = LDCS.EQ.LDC * * If data was incorrectly changed, report and * return. * SAME = .TRUE. DO 30 I = 1, NARGS SAME = SAME.AND.ISAME( I ) IF( .NOT.ISAME( I ) ) $ WRITE( NOUT, FMT = 9998 )I 30 CONTINUE IF( .NOT.SAME )THEN FATAL = .TRUE. GO TO 120 END IF * IF( .NOT.NULL )THEN * * Check the result column by column. * JC = 1 DO 40 J = 1, N IF( UPPER )THEN JJ = 1 LJ = J ELSE JJ = J LJ = N - J + 1 END IF IF( TRAN )THEN CALL DMMCH( 'T', 'N', LJ, 1, K, ALPHA, $ A( 1, JJ ), NMAX, $ A( 1, J ), NMAX, BETA, $ C( JJ, J ), NMAX, CT, G, $ CC( JC ), LDC, EPS, ERR, $ FATAL, NOUT, .TRUE. ) ELSE CALL DMMCH( 'N', 'T', LJ, 1, K, ALPHA, $ A( JJ, 1 ), NMAX, $ A( J, 1 ), NMAX, BETA, $ C( JJ, J ), NMAX, CT, G, $ CC( JC ), LDC, EPS, ERR, $ FATAL, NOUT, .TRUE. ) END IF IF( UPPER )THEN JC = JC + LDC ELSE JC = JC + LDC + 1 END IF ERRMAX = MAX( ERRMAX, ERR ) * If got really bad answer, report and * return. IF( FATAL ) $ GO TO 110 40 CONTINUE END IF * 50 CONTINUE * 60 CONTINUE * 70 CONTINUE * 80 CONTINUE * 90 CONTINUE * 100 CONTINUE * * Report result. * IF( ERRMAX.LT.THRESH )THEN WRITE( NOUT, FMT = 9999 )SNAME, NC ELSE WRITE( NOUT, FMT = 9997 )SNAME, NC, ERRMAX END IF GO TO 130 * 110 CONTINUE IF( N.GT.1 ) $ WRITE( NOUT, FMT = 9995 )J * 120 CONTINUE WRITE( NOUT, FMT = 9996 )SNAME WRITE( NOUT, FMT = 9994 )NC, SNAME, UPLO, TRANS, N, K, ALPHA, $ LDA, BETA, LDC * 130 CONTINUE RETURN * 9999 FORMAT( ' ', A6, ' PASSED THE COMPUTATIONAL TESTS (', I6, ' CALL', $ 'S)' ) 9998 FORMAT( ' ******* FATAL ERROR - PARAMETER NUMBER ', I2, ' WAS CH', $ 'ANGED INCORRECTLY *******' ) 9997 FORMAT( ' ', A6, ' COMPLETED THE COMPUTATIONAL TESTS (', I6, ' C', $ 'ALLS)', /' ******* BUT WITH MAXIMUM TEST RATIO', F8.2, $ ' - SUSPECT *******' ) 9996 FORMAT( ' ******* ', A6, ' FAILED ON CALL NUMBER:' ) 9995 FORMAT( ' THESE ARE THE RESULTS FOR COLUMN ', I3 ) 9994 FORMAT( 1X, I6, ': ', A6, '(', 2( '''', A1, ''',' ), 2( I3, ',' ), $ F4.1, ', A,', I3, ',', F4.1, ', C,', I3, ') .' ) 9993 FORMAT( ' ******* FATAL ERROR - ERROR-EXIT TAKEN ON VALID CALL *', $ '******' ) * * End of DCHK4. * END SUBROUTINE DCHK5( SNAME, EPS, THRESH, NOUT, NTRA, TRACE, REWI, $ FATAL, NIDIM, IDIM, NALF, ALF, NBET, BET, NMAX, $ AB, AA, AS, BB, BS, C, CC, CS, CT, G, W ) * * Tests DSYR2K. * * Auxiliary routine for test program for Level 3 Blas. * * -- Written on 8-February-1989. * Jack Dongarra, Argonne National Laboratory. * Iain Duff, AERE Harwell. * Jeremy Du Croz, Numerical Algorithms Group Ltd. * Sven Hammarling, Numerical Algorithms Group Ltd. * * .. Parameters .. DOUBLE PRECISION ZERO PARAMETER ( ZERO = 0.0D0 ) * .. Scalar Arguments .. DOUBLE PRECISION EPS, THRESH INTEGER NALF, NBET, NIDIM, NMAX, NOUT, NTRA LOGICAL FATAL, REWI, TRACE CHARACTER*6 SNAME * .. Array Arguments .. DOUBLE PRECISION AA( NMAX*NMAX ), AB( 2*NMAX*NMAX ), $ ALF( NALF ), AS( NMAX*NMAX ), BB( NMAX*NMAX ), $ BET( NBET ), BS( NMAX*NMAX ), C( NMAX, NMAX ), $ CC( NMAX*NMAX ), CS( NMAX*NMAX ), CT( NMAX ), $ G( NMAX ), W( 2*NMAX ) INTEGER IDIM( NIDIM ) * .. Local Scalars .. DOUBLE PRECISION ALPHA, ALS, BETA, BETS, ERR, ERRMAX INTEGER I, IA, IB, ICT, ICU, IK, IN, J, JC, JJ, JJAB, $ K, KS, LAA, LBB, LCC, LDA, LDAS, LDB, LDBS, $ LDC, LDCS, LJ, MA, N, NA, NARGS, NC, NS LOGICAL NULL, RESET, SAME, TRAN, UPPER CHARACTER*1 TRANS, TRANSS, UPLO, UPLOS CHARACTER*2 ICHU CHARACTER*3 ICHT * .. Local Arrays .. LOGICAL ISAME( 13 ) * .. External Functions .. LOGICAL LDE, LDERES EXTERNAL LDE, LDERES * .. External Subroutines .. EXTERNAL DMAKE, DMMCH, DSYR2K * .. Intrinsic Functions .. INTRINSIC MAX * .. Scalars in Common .. INTEGER INFOT, NOUTC LOGICAL LERR, OK * .. Common blocks .. COMMON /INFOC/INFOT, NOUTC, OK, LERR * .. Data statements .. DATA ICHT/'NTC'/, ICHU/'UL'/ * .. Executable Statements .. * NARGS = 12 NC = 0 RESET = .TRUE. ERRMAX = ZERO * DO 130 IN = 1, NIDIM N = IDIM( IN ) * Set LDC to 1 more than minimum value if room. LDC = N IF( LDC.LT.NMAX ) $ LDC = LDC + 1 * Skip tests if not enough room. IF( LDC.GT.NMAX ) $ GO TO 130 LCC = LDC*N NULL = N.LE.0 * DO 120 IK = 1, NIDIM K = IDIM( IK ) * DO 110 ICT = 1, 3 TRANS = ICHT( ICT: ICT ) TRAN = TRANS.EQ.'T'.OR.TRANS.EQ.'C' IF( TRAN )THEN MA = K NA = N ELSE MA = N NA = K END IF * Set LDA to 1 more than minimum value if room. LDA = MA IF( LDA.LT.NMAX ) $ LDA = LDA + 1 * Skip tests if not enough room. IF( LDA.GT.NMAX ) $ GO TO 110 LAA = LDA*NA * * Generate the matrix A. * IF( TRAN )THEN CALL DMAKE( 'GE', ' ', ' ', MA, NA, AB, 2*NMAX, AA, $ LDA, RESET, ZERO ) ELSE CALL DMAKE( 'GE', ' ', ' ', MA, NA, AB, NMAX, AA, LDA, $ RESET, ZERO ) END IF * * Generate the matrix B. * LDB = LDA LBB = LAA IF( TRAN )THEN CALL DMAKE( 'GE', ' ', ' ', MA, NA, AB( K + 1 ), $ 2*NMAX, BB, LDB, RESET, ZERO ) ELSE CALL DMAKE( 'GE', ' ', ' ', MA, NA, AB( K*NMAX + 1 ), $ NMAX, BB, LDB, RESET, ZERO ) END IF * DO 100 ICU = 1, 2 UPLO = ICHU( ICU: ICU ) UPPER = UPLO.EQ.'U' * DO 90 IA = 1, NALF ALPHA = ALF( IA ) * DO 80 IB = 1, NBET BETA = BET( IB ) * * Generate the matrix C. * CALL DMAKE( 'SY', UPLO, ' ', N, N, C, NMAX, CC, $ LDC, RESET, ZERO ) * NC = NC + 1 * * Save every datum before calling the subroutine. * UPLOS = UPLO TRANSS = TRANS NS = N KS = K ALS = ALPHA DO 10 I = 1, LAA AS( I ) = AA( I ) 10 CONTINUE LDAS = LDA DO 20 I = 1, LBB BS( I ) = BB( I ) 20 CONTINUE LDBS = LDB BETS = BETA DO 30 I = 1, LCC CS( I ) = CC( I ) 30 CONTINUE LDCS = LDC * * Call the subroutine. * IF( TRACE ) $ WRITE( NTRA, FMT = 9994 )NC, SNAME, UPLO, $ TRANS, N, K, ALPHA, LDA, LDB, BETA, LDC IF( REWI ) $ REWIND NTRA CALL DSYR2K( UPLO, TRANS, N, K, ALPHA, AA, LDA, $ BB, LDB, BETA, CC, LDC ) * * Check if error-exit was taken incorrectly. * IF( .NOT.OK )THEN WRITE( NOUT, FMT = 9993 ) FATAL = .TRUE. GO TO 150 END IF * * See what data changed inside subroutines. * ISAME( 1 ) = UPLOS.EQ.UPLO ISAME( 2 ) = TRANSS.EQ.TRANS ISAME( 3 ) = NS.EQ.N ISAME( 4 ) = KS.EQ.K ISAME( 5 ) = ALS.EQ.ALPHA ISAME( 6 ) = LDE( AS, AA, LAA ) ISAME( 7 ) = LDAS.EQ.LDA ISAME( 8 ) = LDE( BS, BB, LBB ) ISAME( 9 ) = LDBS.EQ.LDB ISAME( 10 ) = BETS.EQ.BETA IF( NULL )THEN ISAME( 11 ) = LDE( CS, CC, LCC ) ELSE ISAME( 11 ) = LDERES( 'SY', UPLO, N, N, CS, $ CC, LDC ) END IF ISAME( 12 ) = LDCS.EQ.LDC * * If data was incorrectly changed, report and * return. * SAME = .TRUE. DO 40 I = 1, NARGS SAME = SAME.AND.ISAME( I ) IF( .NOT.ISAME( I ) ) $ WRITE( NOUT, FMT = 9998 )I 40 CONTINUE IF( .NOT.SAME )THEN FATAL = .TRUE. GO TO 150 END IF * IF( .NOT.NULL )THEN * * Check the result column by column. * JJAB = 1 JC = 1 DO 70 J = 1, N IF( UPPER )THEN JJ = 1 LJ = J ELSE JJ = J LJ = N - J + 1 END IF IF( TRAN )THEN DO 50 I = 1, K W( I ) = AB( ( J - 1 )*2*NMAX + K + $ I ) W( K + I ) = AB( ( J - 1 )*2*NMAX + $ I ) 50 CONTINUE CALL DMMCH( 'T', 'N', LJ, 1, 2*K, $ ALPHA, AB( JJAB ), 2*NMAX, $ W, 2*NMAX, BETA, $ C( JJ, J ), NMAX, CT, G, $ CC( JC ), LDC, EPS, ERR, $ FATAL, NOUT, .TRUE. ) ELSE DO 60 I = 1, K W( I ) = AB( ( K + I - 1 )*NMAX + $ J ) W( K + I ) = AB( ( I - 1 )*NMAX + $ J ) 60 CONTINUE CALL DMMCH( 'N', 'N', LJ, 1, 2*K, $ ALPHA, AB( JJ ), NMAX, W, $ 2*NMAX, BETA, C( JJ, J ), $ NMAX, CT, G, CC( JC ), LDC, $ EPS, ERR, FATAL, NOUT, $ .TRUE. ) END IF IF( UPPER )THEN JC = JC + LDC ELSE JC = JC + LDC + 1 IF( TRAN ) $ JJAB = JJAB + 2*NMAX END IF ERRMAX = MAX( ERRMAX, ERR ) * If got really bad answer, report and * return. IF( FATAL ) $ GO TO 140 70 CONTINUE END IF * 80 CONTINUE * 90 CONTINUE * 100 CONTINUE * 110 CONTINUE * 120 CONTINUE * 130 CONTINUE * * Report result. * IF( ERRMAX.LT.THRESH )THEN WRITE( NOUT, FMT = 9999 )SNAME, NC ELSE WRITE( NOUT, FMT = 9997 )SNAME, NC, ERRMAX END IF GO TO 160 * 140 CONTINUE IF( N.GT.1 ) $ WRITE( NOUT, FMT = 9995 )J * 150 CONTINUE WRITE( NOUT, FMT = 9996 )SNAME WRITE( NOUT, FMT = 9994 )NC, SNAME, UPLO, TRANS, N, K, ALPHA, $ LDA, LDB, BETA, LDC * 160 CONTINUE RETURN * 9999 FORMAT( ' ', A6, ' PASSED THE COMPUTATIONAL TESTS (', I6, ' CALL', $ 'S)' ) 9998 FORMAT( ' ******* FATAL ERROR - PARAMETER NUMBER ', I2, ' WAS CH', $ 'ANGED INCORRECTLY *******' ) 9997 FORMAT( ' ', A6, ' COMPLETED THE COMPUTATIONAL TESTS (', I6, ' C', $ 'ALLS)', /' ******* BUT WITH MAXIMUM TEST RATIO', F8.2, $ ' - SUSPECT *******' ) 9996 FORMAT( ' ******* ', A6, ' FAILED ON CALL NUMBER:' ) 9995 FORMAT( ' THESE ARE THE RESULTS FOR COLUMN ', I3 ) 9994 FORMAT( 1X, I6, ': ', A6, '(', 2( '''', A1, ''',' ), 2( I3, ',' ), $ F4.1, ', A,', I3, ', B,', I3, ',', F4.1, ', C,', I3, ') ', $ ' .' ) 9993 FORMAT( ' ******* FATAL ERROR - ERROR-EXIT TAKEN ON VALID CALL *', $ '******' ) * * End of DCHK5. * END SUBROUTINE DCHKE( ISNUM, SRNAMT, NOUT ) * * Tests the error exits from the Level 3 Blas. * Requires a special version of the error-handling routine XERBLA. * A, B and C should not need to be defined. * * Auxiliary routine for test program for Level 3 Blas. * * -- Written on 8-February-1989. * Jack Dongarra, Argonne National Laboratory. * Iain Duff, AERE Harwell. * Jeremy Du Croz, Numerical Algorithms Group Ltd. * Sven Hammarling, Numerical Algorithms Group Ltd. * * 3-19-92: Initialize ALPHA and BETA (eca) * 3-19-92: Fix argument 12 in calls to SSYMM with INFOT = 9 (eca) * * .. Scalar Arguments .. INTEGER ISNUM, NOUT CHARACTER*6 SRNAMT * .. Scalars in Common .. INTEGER INFOT, NOUTC LOGICAL LERR, OK * .. Parameters .. DOUBLE PRECISION ONE, TWO PARAMETER ( ONE = 1.0D0, TWO = 2.0D0 ) * .. Local Scalars .. DOUBLE PRECISION ALPHA, BETA * .. Local Arrays .. DOUBLE PRECISION A( 2, 1 ), B( 2, 1 ), C( 2, 1 ) * .. External Subroutines .. EXTERNAL CHKXER, DGEMM, DSYMM, DSYR2K, DSYRK, DTRMM, $ DTRSM * .. Common blocks .. COMMON /INFOC/INFOT, NOUTC, OK, LERR * .. Executable Statements .. * OK is set to .FALSE. by the special version of XERBLA or by CHKXER * if anything is wrong. OK = .TRUE. * LERR is set to .TRUE. by the special version of XERBLA each time * it is called, and is then tested and re-set by CHKXER. LERR = .FALSE. * * Initialize ALPHA and BETA. * ALPHA = ONE BETA = TWO * GO TO ( 10, 20, 30, 40, 50, 60 )ISNUM 10 INFOT = 1 CALL DGEMM( '/', 'N', 0, 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 1 CALL DGEMM( '/', 'T', 0, 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL DGEMM( 'N', '/', 0, 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL DGEMM( 'T', '/', 0, 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL DGEMM( 'N', 'N', -1, 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL DGEMM( 'N', 'T', -1, 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL DGEMM( 'T', 'N', -1, 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL DGEMM( 'T', 'T', -1, 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL DGEMM( 'N', 'N', 0, -1, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL DGEMM( 'N', 'T', 0, -1, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL DGEMM( 'T', 'N', 0, -1, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL DGEMM( 'T', 'T', 0, -1, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL DGEMM( 'N', 'N', 0, 0, -1, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL DGEMM( 'N', 'T', 0, 0, -1, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL DGEMM( 'T', 'N', 0, 0, -1, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL DGEMM( 'T', 'T', 0, 0, -1, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 8 CALL DGEMM( 'N', 'N', 2, 0, 0, ALPHA, A, 1, B, 1, BETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 8 CALL DGEMM( 'N', 'T', 2, 0, 0, ALPHA, A, 1, B, 1, BETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 8 CALL DGEMM( 'T', 'N', 0, 0, 2, ALPHA, A, 1, B, 2, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 8 CALL DGEMM( 'T', 'T', 0, 0, 2, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 10 CALL DGEMM( 'N', 'N', 0, 0, 2, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 10 CALL DGEMM( 'T', 'N', 0, 0, 2, ALPHA, A, 2, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 10 CALL DGEMM( 'N', 'T', 0, 2, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 10 CALL DGEMM( 'T', 'T', 0, 2, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 13 CALL DGEMM( 'N', 'N', 2, 0, 0, ALPHA, A, 2, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 13 CALL DGEMM( 'N', 'T', 2, 0, 0, ALPHA, A, 2, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 13 CALL DGEMM( 'T', 'N', 2, 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 13 CALL DGEMM( 'T', 'T', 2, 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 70 20 INFOT = 1 CALL DSYMM( '/', 'U', 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL DSYMM( 'L', '/', 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL DSYMM( 'L', 'U', -1, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL DSYMM( 'R', 'U', -1, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL DSYMM( 'L', 'L', -1, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL DSYMM( 'R', 'L', -1, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL DSYMM( 'L', 'U', 0, -1, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL DSYMM( 'R', 'U', 0, -1, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL DSYMM( 'L', 'L', 0, -1, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL DSYMM( 'R', 'L', 0, -1, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL DSYMM( 'L', 'U', 2, 0, ALPHA, A, 1, B, 2, BETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL DSYMM( 'R', 'U', 0, 2, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL DSYMM( 'L', 'L', 2, 0, ALPHA, A, 1, B, 2, BETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL DSYMM( 'R', 'L', 0, 2, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL DSYMM( 'L', 'U', 2, 0, ALPHA, A, 2, B, 1, BETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL DSYMM( 'R', 'U', 2, 0, ALPHA, A, 1, B, 1, BETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL DSYMM( 'L', 'L', 2, 0, ALPHA, A, 2, B, 1, BETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL DSYMM( 'R', 'L', 2, 0, ALPHA, A, 1, B, 1, BETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 12 CALL DSYMM( 'L', 'U', 2, 0, ALPHA, A, 2, B, 2, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 12 CALL DSYMM( 'R', 'U', 2, 0, ALPHA, A, 1, B, 2, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 12 CALL DSYMM( 'L', 'L', 2, 0, ALPHA, A, 2, B, 2, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 12 CALL DSYMM( 'R', 'L', 2, 0, ALPHA, A, 1, B, 2, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 70 30 INFOT = 1 CALL DTRMM( '/', 'U', 'N', 'N', 0, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL DTRMM( 'L', '/', 'N', 'N', 0, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL DTRMM( 'L', 'U', '/', 'N', 0, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL DTRMM( 'L', 'U', 'N', '/', 0, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL DTRMM( 'L', 'U', 'N', 'N', -1, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL DTRMM( 'L', 'U', 'T', 'N', -1, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL DTRMM( 'R', 'U', 'N', 'N', -1, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL DTRMM( 'R', 'U', 'T', 'N', -1, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL DTRMM( 'L', 'L', 'N', 'N', -1, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL DTRMM( 'L', 'L', 'T', 'N', -1, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL DTRMM( 'R', 'L', 'N', 'N', -1, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL DTRMM( 'R', 'L', 'T', 'N', -1, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL DTRMM( 'L', 'U', 'N', 'N', 0, -1, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL DTRMM( 'L', 'U', 'T', 'N', 0, -1, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL DTRMM( 'R', 'U', 'N', 'N', 0, -1, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL DTRMM( 'R', 'U', 'T', 'N', 0, -1, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL DTRMM( 'L', 'L', 'N', 'N', 0, -1, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL DTRMM( 'L', 'L', 'T', 'N', 0, -1, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL DTRMM( 'R', 'L', 'N', 'N', 0, -1, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL DTRMM( 'R', 'L', 'T', 'N', 0, -1, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL DTRMM( 'L', 'U', 'N', 'N', 2, 0, ALPHA, A, 1, B, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL DTRMM( 'L', 'U', 'T', 'N', 2, 0, ALPHA, A, 1, B, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL DTRMM( 'R', 'U', 'N', 'N', 0, 2, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL DTRMM( 'R', 'U', 'T', 'N', 0, 2, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL DTRMM( 'L', 'L', 'N', 'N', 2, 0, ALPHA, A, 1, B, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL DTRMM( 'L', 'L', 'T', 'N', 2, 0, ALPHA, A, 1, B, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL DTRMM( 'R', 'L', 'N', 'N', 0, 2, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL DTRMM( 'R', 'L', 'T', 'N', 0, 2, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL DTRMM( 'L', 'U', 'N', 'N', 2, 0, ALPHA, A, 2, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL DTRMM( 'L', 'U', 'T', 'N', 2, 0, ALPHA, A, 2, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL DTRMM( 'R', 'U', 'N', 'N', 2, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL DTRMM( 'R', 'U', 'T', 'N', 2, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL DTRMM( 'L', 'L', 'N', 'N', 2, 0, ALPHA, A, 2, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL DTRMM( 'L', 'L', 'T', 'N', 2, 0, ALPHA, A, 2, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL DTRMM( 'R', 'L', 'N', 'N', 2, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL DTRMM( 'R', 'L', 'T', 'N', 2, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 70 40 INFOT = 1 CALL DTRSM( '/', 'U', 'N', 'N', 0, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL DTRSM( 'L', '/', 'N', 'N', 0, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL DTRSM( 'L', 'U', '/', 'N', 0, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL DTRSM( 'L', 'U', 'N', '/', 0, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL DTRSM( 'L', 'U', 'N', 'N', -1, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL DTRSM( 'L', 'U', 'T', 'N', -1, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL DTRSM( 'R', 'U', 'N', 'N', -1, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL DTRSM( 'R', 'U', 'T', 'N', -1, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL DTRSM( 'L', 'L', 'N', 'N', -1, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL DTRSM( 'L', 'L', 'T', 'N', -1, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL DTRSM( 'R', 'L', 'N', 'N', -1, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL DTRSM( 'R', 'L', 'T', 'N', -1, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL DTRSM( 'L', 'U', 'N', 'N', 0, -1, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL DTRSM( 'L', 'U', 'T', 'N', 0, -1, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL DTRSM( 'R', 'U', 'N', 'N', 0, -1, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL DTRSM( 'R', 'U', 'T', 'N', 0, -1, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL DTRSM( 'L', 'L', 'N', 'N', 0, -1, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL DTRSM( 'L', 'L', 'T', 'N', 0, -1, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL DTRSM( 'R', 'L', 'N', 'N', 0, -1, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL DTRSM( 'R', 'L', 'T', 'N', 0, -1, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL DTRSM( 'L', 'U', 'N', 'N', 2, 0, ALPHA, A, 1, B, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL DTRSM( 'L', 'U', 'T', 'N', 2, 0, ALPHA, A, 1, B, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL DTRSM( 'R', 'U', 'N', 'N', 0, 2, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL DTRSM( 'R', 'U', 'T', 'N', 0, 2, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL DTRSM( 'L', 'L', 'N', 'N', 2, 0, ALPHA, A, 1, B, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL DTRSM( 'L', 'L', 'T', 'N', 2, 0, ALPHA, A, 1, B, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL DTRSM( 'R', 'L', 'N', 'N', 0, 2, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL DTRSM( 'R', 'L', 'T', 'N', 0, 2, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL DTRSM( 'L', 'U', 'N', 'N', 2, 0, ALPHA, A, 2, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL DTRSM( 'L', 'U', 'T', 'N', 2, 0, ALPHA, A, 2, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL DTRSM( 'R', 'U', 'N', 'N', 2, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL DTRSM( 'R', 'U', 'T', 'N', 2, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL DTRSM( 'L', 'L', 'N', 'N', 2, 0, ALPHA, A, 2, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL DTRSM( 'L', 'L', 'T', 'N', 2, 0, ALPHA, A, 2, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL DTRSM( 'R', 'L', 'N', 'N', 2, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL DTRSM( 'R', 'L', 'T', 'N', 2, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 70 50 INFOT = 1 CALL DSYRK( '/', 'N', 0, 0, ALPHA, A, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL DSYRK( 'U', '/', 0, 0, ALPHA, A, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL DSYRK( 'U', 'N', -1, 0, ALPHA, A, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL DSYRK( 'U', 'T', -1, 0, ALPHA, A, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL DSYRK( 'L', 'N', -1, 0, ALPHA, A, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL DSYRK( 'L', 'T', -1, 0, ALPHA, A, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL DSYRK( 'U', 'N', 0, -1, ALPHA, A, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL DSYRK( 'U', 'T', 0, -1, ALPHA, A, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL DSYRK( 'L', 'N', 0, -1, ALPHA, A, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL DSYRK( 'L', 'T', 0, -1, ALPHA, A, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL DSYRK( 'U', 'N', 2, 0, ALPHA, A, 1, BETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL DSYRK( 'U', 'T', 0, 2, ALPHA, A, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL DSYRK( 'L', 'N', 2, 0, ALPHA, A, 1, BETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL DSYRK( 'L', 'T', 0, 2, ALPHA, A, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 10 CALL DSYRK( 'U', 'N', 2, 0, ALPHA, A, 2, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 10 CALL DSYRK( 'U', 'T', 2, 0, ALPHA, A, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 10 CALL DSYRK( 'L', 'N', 2, 0, ALPHA, A, 2, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 10 CALL DSYRK( 'L', 'T', 2, 0, ALPHA, A, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 70 60 INFOT = 1 CALL DSYR2K( '/', 'N', 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL DSYR2K( 'U', '/', 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL DSYR2K( 'U', 'N', -1, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL DSYR2K( 'U', 'T', -1, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL DSYR2K( 'L', 'N', -1, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL DSYR2K( 'L', 'T', -1, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL DSYR2K( 'U', 'N', 0, -1, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL DSYR2K( 'U', 'T', 0, -1, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL DSYR2K( 'L', 'N', 0, -1, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL DSYR2K( 'L', 'T', 0, -1, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL DSYR2K( 'U', 'N', 2, 0, ALPHA, A, 1, B, 1, BETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL DSYR2K( 'U', 'T', 0, 2, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL DSYR2K( 'L', 'N', 2, 0, ALPHA, A, 1, B, 1, BETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL DSYR2K( 'L', 'T', 0, 2, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL DSYR2K( 'U', 'N', 2, 0, ALPHA, A, 2, B, 1, BETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL DSYR2K( 'U', 'T', 0, 2, ALPHA, A, 2, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL DSYR2K( 'L', 'N', 2, 0, ALPHA, A, 2, B, 1, BETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL DSYR2K( 'L', 'T', 0, 2, ALPHA, A, 2, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 12 CALL DSYR2K( 'U', 'N', 2, 0, ALPHA, A, 2, B, 2, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 12 CALL DSYR2K( 'U', 'T', 2, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 12 CALL DSYR2K( 'L', 'N', 2, 0, ALPHA, A, 2, B, 2, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 12 CALL DSYR2K( 'L', 'T', 2, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) * 70 IF( OK )THEN WRITE( NOUT, FMT = 9999 )SRNAMT ELSE WRITE( NOUT, FMT = 9998 )SRNAMT END IF RETURN * 9999 FORMAT( ' ', A6, ' PASSED THE TESTS OF ERROR-EXITS' ) 9998 FORMAT( ' ******* ', A6, ' FAILED THE TESTS OF ERROR-EXITS *****', $ '**' ) * * End of DCHKE. * END SUBROUTINE DMAKE( TYPE, UPLO, DIAG, M, N, A, NMAX, AA, LDA, RESET, $ TRANSL ) * * Generates values for an M by N matrix A. * Stores the values in the array AA in the data structure required * by the routine, with unwanted elements set to rogue value. * * TYPE is 'GE', 'SY' or 'TR'. * * Auxiliary routine for test program for Level 3 Blas. * * -- Written on 8-February-1989. * Jack Dongarra, Argonne National Laboratory. * Iain Duff, AERE Harwell. * Jeremy Du Croz, Numerical Algorithms Group Ltd. * Sven Hammarling, Numerical Algorithms Group Ltd. * * .. Parameters .. DOUBLE PRECISION ZERO, ONE PARAMETER ( ZERO = 0.0D0, ONE = 1.0D0 ) DOUBLE PRECISION ROGUE PARAMETER ( ROGUE = -1.0D10 ) * .. Scalar Arguments .. DOUBLE PRECISION TRANSL INTEGER LDA, M, N, NMAX LOGICAL RESET CHARACTER*1 DIAG, UPLO CHARACTER*2 TYPE * .. Array Arguments .. DOUBLE PRECISION A( NMAX, * ), AA( * ) * .. Local Scalars .. INTEGER I, IBEG, IEND, J LOGICAL GEN, LOWER, SYM, TRI, UNIT, UPPER * .. External Functions .. DOUBLE PRECISION DBEG EXTERNAL DBEG * .. Executable Statements .. GEN = TYPE.EQ.'GE' SYM = TYPE.EQ.'SY' TRI = TYPE.EQ.'TR' UPPER = ( SYM.OR.TRI ).AND.UPLO.EQ.'U' LOWER = ( SYM.OR.TRI ).AND.UPLO.EQ.'L' UNIT = TRI.AND.DIAG.EQ.'U' * * Generate data in array A. * DO 20 J = 1, N DO 10 I = 1, M IF( GEN.OR.( UPPER.AND.I.LE.J ).OR.( LOWER.AND.I.GE.J ) ) $ THEN A( I, J ) = DBEG( RESET ) + TRANSL IF( I.NE.J )THEN * Set some elements to zero IF( N.GT.3.AND.J.EQ.N/2 ) $ A( I, J ) = ZERO IF( SYM )THEN A( J, I ) = A( I, J ) ELSE IF( TRI )THEN A( J, I ) = ZERO END IF END IF END IF 10 CONTINUE IF( TRI ) $ A( J, J ) = A( J, J ) + ONE IF( UNIT ) $ A( J, J ) = ONE 20 CONTINUE * * Store elements in array AS in data structure required by routine. * IF( TYPE.EQ.'GE' )THEN DO 50 J = 1, N DO 30 I = 1, M AA( I + ( J - 1 )*LDA ) = A( I, J ) 30 CONTINUE DO 40 I = M + 1, LDA AA( I + ( J - 1 )*LDA ) = ROGUE 40 CONTINUE 50 CONTINUE ELSE IF( TYPE.EQ.'SY'.OR.TYPE.EQ.'TR' )THEN DO 90 J = 1, N IF( UPPER )THEN IBEG = 1 IF( UNIT )THEN IEND = J - 1 ELSE IEND = J END IF ELSE IF( UNIT )THEN IBEG = J + 1 ELSE IBEG = J END IF IEND = N END IF DO 60 I = 1, IBEG - 1 AA( I + ( J - 1 )*LDA ) = ROGUE 60 CONTINUE DO 70 I = IBEG, IEND AA( I + ( J - 1 )*LDA ) = A( I, J ) 70 CONTINUE DO 80 I = IEND + 1, LDA AA( I + ( J - 1 )*LDA ) = ROGUE 80 CONTINUE 90 CONTINUE END IF RETURN * * End of DMAKE. * END SUBROUTINE DMMCH( TRANSA, TRANSB, M, N, KK, ALPHA, A, LDA, B, LDB, $ BETA, C, LDC, CT, G, CC, LDCC, EPS, ERR, FATAL, $ NOUT, MV ) * * Checks the results of the computational tests. * * Auxiliary routine for test program for Level 3 Blas. * * -- Written on 8-February-1989. * Jack Dongarra, Argonne National Laboratory. * Iain Duff, AERE Harwell. * Jeremy Du Croz, Numerical Algorithms Group Ltd. * Sven Hammarling, Numerical Algorithms Group Ltd. * * .. Parameters .. DOUBLE PRECISION ZERO, ONE PARAMETER ( ZERO = 0.0D0, ONE = 1.0D0 ) * .. Scalar Arguments .. DOUBLE PRECISION ALPHA, BETA, EPS, ERR INTEGER KK, LDA, LDB, LDC, LDCC, M, N, NOUT LOGICAL FATAL, MV CHARACTER*1 TRANSA, TRANSB * .. Array Arguments .. DOUBLE PRECISION A( LDA, * ), B( LDB, * ), C( LDC, * ), $ CC( LDCC, * ), CT( * ), G( * ) * .. Local Scalars .. DOUBLE PRECISION ERRI INTEGER I, J, K LOGICAL TRANA, TRANB * .. Intrinsic Functions .. INTRINSIC ABS, MAX, SQRT * .. Executable Statements .. TRANA = TRANSA.EQ.'T'.OR.TRANSA.EQ.'C' TRANB = TRANSB.EQ.'T'.OR.TRANSB.EQ.'C' * * Compute expected result, one column at a time, in CT using data * in A, B and C. * Compute gauges in G. * DO 120 J = 1, N * DO 10 I = 1, M CT( I ) = ZERO G( I ) = ZERO 10 CONTINUE IF( .NOT.TRANA.AND..NOT.TRANB )THEN DO 30 K = 1, KK DO 20 I = 1, M CT( I ) = CT( I ) + A( I, K )*B( K, J ) G( I ) = G( I ) + ABS( A( I, K ) )*ABS( B( K, J ) ) 20 CONTINUE 30 CONTINUE ELSE IF( TRANA.AND..NOT.TRANB )THEN DO 50 K = 1, KK DO 40 I = 1, M CT( I ) = CT( I ) + A( K, I )*B( K, J ) G( I ) = G( I ) + ABS( A( K, I ) )*ABS( B( K, J ) ) 40 CONTINUE 50 CONTINUE ELSE IF( .NOT.TRANA.AND.TRANB )THEN DO 70 K = 1, KK DO 60 I = 1, M CT( I ) = CT( I ) + A( I, K )*B( J, K ) G( I ) = G( I ) + ABS( A( I, K ) )*ABS( B( J, K ) ) 60 CONTINUE 70 CONTINUE ELSE IF( TRANA.AND.TRANB )THEN DO 90 K = 1, KK DO 80 I = 1, M CT( I ) = CT( I ) + A( K, I )*B( J, K ) G( I ) = G( I ) + ABS( A( K, I ) )*ABS( B( J, K ) ) 80 CONTINUE 90 CONTINUE END IF DO 100 I = 1, M CT( I ) = ALPHA*CT( I ) + BETA*C( I, J ) G( I ) = ABS( ALPHA )*G( I ) + ABS( BETA )*ABS( C( I, J ) ) 100 CONTINUE * * Compute the error ratio for this result. * ERR = ZERO DO 110 I = 1, M ERRI = ABS( CT( I ) - CC( I, J ) )/EPS IF( G( I ).NE.ZERO ) $ ERRI = ERRI/G( I ) ERR = MAX( ERR, ERRI ) IF( ERR*SQRT( EPS ).GE.ONE ) $ GO TO 130 110 CONTINUE * 120 CONTINUE * * If the loop completes, all results are at least half accurate. GO TO 150 * * Report fatal error. * 130 FATAL = .TRUE. WRITE( NOUT, FMT = 9999 ) DO 140 I = 1, M IF( MV )THEN WRITE( NOUT, FMT = 9998 )I, CT( I ), CC( I, J ) ELSE WRITE( NOUT, FMT = 9998 )I, CC( I, J ), CT( I ) END IF 140 CONTINUE IF( N.GT.1 ) $ WRITE( NOUT, FMT = 9997 )J * 150 CONTINUE RETURN * 9999 FORMAT( ' ******* FATAL ERROR - COMPUTED RESULT IS LESS THAN HAL', $ 'F ACCURATE *******', /' EXPECTED RESULT COMPU', $ 'TED RESULT' ) 9998 FORMAT( 1X, I7, 2G18.6 ) 9997 FORMAT( ' THESE ARE THE RESULTS FOR COLUMN ', I3 ) * * End of DMMCH. * END LOGICAL FUNCTION LDE( RI, RJ, LR ) * * Tests if two arrays are identical. * * Auxiliary routine for test program for Level 3 Blas. * * -- Written on 8-February-1989. * Jack Dongarra, Argonne National Laboratory. * Iain Duff, AERE Harwell. * Jeremy Du Croz, Numerical Algorithms Group Ltd. * Sven Hammarling, Numerical Algorithms Group Ltd. * * .. Scalar Arguments .. INTEGER LR * .. Array Arguments .. DOUBLE PRECISION RI( * ), RJ( * ) * .. Local Scalars .. INTEGER I * .. Executable Statements .. DO 10 I = 1, LR IF( RI( I ).NE.RJ( I ) ) $ GO TO 20 10 CONTINUE LDE = .TRUE. GO TO 30 20 CONTINUE LDE = .FALSE. 30 RETURN * * End of LDE. * END LOGICAL FUNCTION LDERES( TYPE, UPLO, M, N, AA, AS, LDA ) * * Tests if selected elements in two arrays are equal. * * TYPE is 'GE' or 'SY'. * * Auxiliary routine for test program for Level 3 Blas. * * -- Written on 8-February-1989. * Jack Dongarra, Argonne National Laboratory. * Iain Duff, AERE Harwell. * Jeremy Du Croz, Numerical Algorithms Group Ltd. * Sven Hammarling, Numerical Algorithms Group Ltd. * * .. Scalar Arguments .. INTEGER LDA, M, N CHARACTER*1 UPLO CHARACTER*2 TYPE * .. Array Arguments .. DOUBLE PRECISION AA( LDA, * ), AS( LDA, * ) * .. Local Scalars .. INTEGER I, IBEG, IEND, J LOGICAL UPPER * .. Executable Statements .. UPPER = UPLO.EQ.'U' IF( TYPE.EQ.'GE' )THEN DO 20 J = 1, N DO 10 I = M + 1, LDA IF( AA( I, J ).NE.AS( I, J ) ) $ GO TO 70 10 CONTINUE 20 CONTINUE ELSE IF( TYPE.EQ.'SY' )THEN DO 50 J = 1, N IF( UPPER )THEN IBEG = 1 IEND = J ELSE IBEG = J IEND = N END IF DO 30 I = 1, IBEG - 1 IF( AA( I, J ).NE.AS( I, J ) ) $ GO TO 70 30 CONTINUE DO 40 I = IEND + 1, LDA IF( AA( I, J ).NE.AS( I, J ) ) $ GO TO 70 40 CONTINUE 50 CONTINUE END IF * LDERES = .TRUE. GO TO 80 70 CONTINUE LDERES = .FALSE. 80 RETURN * * End of LDERES. * END DOUBLE PRECISION FUNCTION DBEG( RESET ) * * Generates random numbers uniformly distributed between -0.5 and 0.5. * * Auxiliary routine for test program for Level 3 Blas. * * -- Written on 8-February-1989. * Jack Dongarra, Argonne National Laboratory. * Iain Duff, AERE Harwell. * Jeremy Du Croz, Numerical Algorithms Group Ltd. * Sven Hammarling, Numerical Algorithms Group Ltd. * * .. Scalar Arguments .. LOGICAL RESET * .. Local Scalars .. INTEGER I, IC, MI * .. Save statement .. SAVE I, IC, MI * .. Executable Statements .. IF( RESET )THEN * Initialize local variables. MI = 891 I = 7 IC = 0 RESET = .FALSE. END IF * * The sequence of values of I is bounded between 1 and 999. * If initial I = 1,2,3,6,7 or 9, the period will be 50. * If initial I = 4 or 8, the period will be 25. * If initial I = 5, the period will be 10. * IC is used to break up the period by skipping 1 value of I in 6. * IC = IC + 1 10 I = I*MI I = I - 1000*( I/1000 ) IF( IC.GE.5 )THEN IC = 0 GO TO 10 END IF DBEG = ( I - 500 )/1001.0D0 RETURN * * End of DBEG. * END DOUBLE PRECISION FUNCTION DDIFF( X, Y ) * * Auxiliary routine for test program for Level 3 Blas. * * -- Written on 8-February-1989. * Jack Dongarra, Argonne National Laboratory. * Iain Duff, AERE Harwell. * Jeremy Du Croz, Numerical Algorithms Group Ltd. * Sven Hammarling, Numerical Algorithms Group Ltd. * * .. Scalar Arguments .. DOUBLE PRECISION X, Y * .. Executable Statements .. DDIFF = X - Y RETURN * * End of DDIFF. * END SUBROUTINE CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) * * Tests whether XERBLA has detected an error when it should. * * Auxiliary routine for test program for Level 3 Blas. * * -- Written on 8-February-1989. * Jack Dongarra, Argonne National Laboratory. * Iain Duff, AERE Harwell. * Jeremy Du Croz, Numerical Algorithms Group Ltd. * Sven Hammarling, Numerical Algorithms Group Ltd. * * .. Scalar Arguments .. INTEGER INFOT, NOUT LOGICAL LERR, OK CHARACTER*6 SRNAMT * .. Executable Statements .. IF( .NOT.LERR )THEN WRITE( NOUT, FMT = 9999 )INFOT, SRNAMT OK = .FALSE. END IF LERR = .FALSE. RETURN * 9999 FORMAT( ' ***** ILLEGAL VALUE OF PARAMETER NUMBER ', I2, ' NOT D', $ 'ETECTED BY ', A6, ' *****' ) * * End of CHKXER. * END SUBROUTINE XERBLA( SRNAME, INFO ) * * This is a special version of XERBLA to be used only as part of * the test program for testing error exits from the Level 3 BLAS * routines. * * XERBLA is an error handler for the Level 3 BLAS routines. * * It is called by the Level 3 BLAS routines if an input parameter is * invalid. * * Auxiliary routine for test program for Level 3 Blas. * * -- Written on 8-February-1989. * Jack Dongarra, Argonne National Laboratory. * Iain Duff, AERE Harwell. * Jeremy Du Croz, Numerical Algorithms Group Ltd. * Sven Hammarling, Numerical Algorithms Group Ltd. * * .. Scalar Arguments .. INTEGER INFO CHARACTER*6 SRNAME * .. Scalars in Common .. INTEGER INFOT, NOUT LOGICAL LERR, OK CHARACTER*6 SRNAMT * .. Common blocks .. COMMON /INFOC/INFOT, NOUT, OK, LERR COMMON /SRNAMC/SRNAMT * .. Executable Statements .. LERR = .TRUE. IF( INFO.NE.INFOT )THEN IF( INFOT.NE.0 )THEN WRITE( NOUT, FMT = 9999 )INFO, INFOT ELSE WRITE( NOUT, FMT = 9997 )INFO END IF OK = .FALSE. END IF IF( SRNAME.NE.SRNAMT )THEN WRITE( NOUT, FMT = 9998 )SRNAME, SRNAMT OK = .FALSE. END IF RETURN * 9999 FORMAT( ' ******* XERBLA WAS CALLED WITH INFO = ', I6, ' INSTEAD', $ ' OF ', I2, ' *******' ) 9998 FORMAT( ' ******* XERBLA WAS CALLED WITH SRNAME = ', A6, ' INSTE', $ 'AD OF ', A6, ' *******' ) 9997 FORMAT( ' ******* XERBLA WAS CALLED WITH INFO = ', I6, $ ' *******' ) * * End of XERBLA * END blis-0.9.0/blastest/src/fortran/run-f2c.sh000077500000000000000000000060661422157504600203650ustar00rootroot00000000000000#!/bin/bash # This script converts netlib [sdcz]blat[123].f files from Fortran to C. # # Start by converting to C with f2c. # Options used: # -A Produce ANSI C (instead of old-style C). # -R Do not promote REAL functions and operations to DOUBLE PRECISION. # -a Make local variables automatic rather than static (unless they # appear in a DATA, EQUIVALENCE, NAMELIST, or SAVE statement). f2c -A -R -a *.f # Add 'const' qualifier to certain function delcarations so they match # the prototypes taken from libf2c. recursive-sed.sh -c "s/s_cmp(char \*, char/s_cmp(const char \*, const char/g" -p "*.c" recursive-sed.sh -c "s/s_copy(char \*, char/s_copy(char \*, const char/g" -p "*.c" recursive-sed.sh -c "s/d_cnjg(doublecomplex \*, doublecomplex/d_cnjg(doublecomplex *, const doublecomplex/g" -p "*.c" recursive-sed.sh -c "s/d_imag(doublecomplex/d_imag(const doublecomplex/g" -p "*.c" recursive-sed.sh -c "s/c_abs(complex/c_abs(const complex/g" -p "*.c" recursive-sed.sh -c "s/z_abs(doublecomplex/c_abs(const doublecomplex/g" -p "*.c" # Use main() and 'void' instead of MAIN__ and VOID. recursive-sed.sh -c "s/MAIN__/main/g" -p "*.c" recursive-sed.sh -c "s/VOID/void/g" -p "*.c" # Add prefix to calls to epsilon_() based on the file in which the # function is called. [sd]_epsilon_() are not libf2c functions, but # they are present in the local subset of libf2c used to link the # BLAS testsuite drivers. recursive-sed.sh -c "s/epsilon_/s_epsilon_/g" -p "[sc]*.c" recursive-sed.sh -c "s/epsilon_/d_epsilon_/g" -p "[dz]*.c" # The dsdot_() check needs s_epsilon_(), not d_epsilon_(). recursive-sed.sh -c "s/real d_epsilon_()/real s_epsilon_()/g" -p "d*1.c" recursive-sed.sh -c "s/d_epsilon_(\&c_b81)/s_epsilon_(\&c_b81)/g" -p "d*1.c" # Fix type inconsistencies in the original Fortran file vis-a-vis # epsilon() and abs(). recursive-sed.sh -c "s/real d_epsilon_(doublereal/double d_epsilon_(doublereal/g" -p "[dz]*.c" recursive-sed.sh -c "s/c_abs/z_abs/g" -p "z*.c" # Fix missing braces around struct initializers. recursive-sed.sh -c "s/equiv_3 = {/equiv_3 = {{/g" -p "[sd]*1.c" recursive-sed.sh -c "s/equiv_7 = {/equiv_7 = {{/g" -p "[sd]*1.c" recursive-sed.sh -c "s/0., 0., 0. }/0., 0., 0. }}/g" -p "d*1.c" recursive-sed.sh -c "s/2.9, .2, -4. }/2.9, .2, -4. }}/g" -p "d*1.c" recursive-sed.sh -c "s/0.f, 0.f, 0.f }/0.f, 0.f, 0.f }}/g" -p "s*1.c" recursive-sed.sh -c "s/-4.f };/-4.f }};/g" -p "s*1.c" # Convert from brain-dead f2c complex calling conventions to normal # return-based conventions. recursive-sed.sh -c "s/void cdotc_(complex \*, /complex cdotc_(/g" -p "c*1.c" recursive-sed.sh -c "s/void cdotu_(complex \*, /complex cdotu_(/g" -p "c*1.c" recursive-sed.sh -c "s/cdotc_(&q__1, /q__1 = cdotc_(/g" -p "c*1.c" recursive-sed.sh -c "s/cdotu_(&q__1, /q__1 = cdotu_(/g" -p "c*1.c" recursive-sed.sh -c "s/void zdotc_(doublecomplex \*, /doublecomplex zdotc_(/g" -p "z*1.c" recursive-sed.sh -c "s/void zdotu_(doublecomplex \*, /doublecomplex zdotu_(/g" -p "z*1.c" recursive-sed.sh -c "s/zdotc_(\&z__1, /z__1 = zdotc_(/g" -p "z*1.c" recursive-sed.sh -c "s/zdotu_(\&z__1, /z__1 = zdotu_(/g" -p "z*1.c" blis-0.9.0/blastest/src/fortran/sblat1.f000066400000000000000000001245741422157504600201140ustar00rootroot00000000000000*> \brief \b SBLAT1 * * =========== DOCUMENTATION =========== * * Online html documentation available at * http://www.netlib.org/lapack/explore-html/ * * Definition: * =========== * * PROGRAM SBLAT1 * * *> \par Purpose: * ============= *> *> \verbatim *> *> Test program for the REAL Level 1 BLAS. *> *> Based upon the original BLAS test routine together with: *> F06EAF Example Program Text *> \endverbatim * * Authors: * ======== * *> \author Univ. of Tennessee *> \author Univ. of California Berkeley *> \author Univ. of Colorado Denver *> \author NAG Ltd. * *> \date April 2012 * *> \ingroup single_blas_testing * * ===================================================================== PROGRAM SBLAT1 * * -- Reference BLAS test routine (version 3.4.1) -- * -- Reference BLAS is a software package provided by Univ. of Tennessee, -- * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- * April 2012 * * ===================================================================== * * .. Parameters .. INTEGER NOUT PARAMETER (NOUT=6) * .. Scalars in Common .. INTEGER ICASE, INCX, INCY, N LOGICAL PASS * .. Local Scalars .. REAL SFAC INTEGER IC * .. External Subroutines .. EXTERNAL CHECK0, CHECK1, CHECK2, CHECK3, HEADER * .. Common blocks .. COMMON /COMBLA/ICASE, N, INCX, INCY, PASS * .. Data statements .. DATA SFAC/9.765625E-4/ * .. Executable Statements .. WRITE (NOUT,99999) DO 20 IC = 1, 13 ICASE = IC CALL HEADER * * .. Initialize PASS, INCX, and INCY for a new case. .. * .. the value 9999 for INCX or INCY will appear in the .. * .. detailed output, if any, for cases that do not involve .. * .. these parameters .. * PASS = .TRUE. INCX = 9999 INCY = 9999 IF (ICASE.EQ.3 .OR. ICASE.EQ.11) THEN CALL CHECK0(SFAC) ELSE IF (ICASE.EQ.7 .OR. ICASE.EQ.8 .OR. ICASE.EQ.9 .OR. + ICASE.EQ.10) THEN CALL CHECK1(SFAC) ELSE IF (ICASE.EQ.1 .OR. ICASE.EQ.2 .OR. ICASE.EQ.5 .OR. + ICASE.EQ.6 .OR. ICASE.EQ.12 .OR. ICASE.EQ.13) THEN CALL CHECK2(SFAC) ELSE IF (ICASE.EQ.4) THEN CALL CHECK3(SFAC) END IF * -- Print IF (PASS) WRITE (NOUT,99998) 20 CONTINUE STOP * 99999 FORMAT (' Real BLAS Test Program Results',/1X) 99998 FORMAT (' ----- PASS -----') END SUBROUTINE HEADER * .. Parameters .. INTEGER NOUT PARAMETER (NOUT=6) * .. Scalars in Common .. INTEGER ICASE, INCX, INCY, N LOGICAL PASS * .. Local Arrays .. CHARACTER*6 L(13) * .. Common blocks .. COMMON /COMBLA/ICASE, N, INCX, INCY, PASS * .. Data statements .. DATA L(1)/' SDOT '/ DATA L(2)/'SAXPY '/ DATA L(3)/'SROTG '/ DATA L(4)/' SROT '/ DATA L(5)/'SCOPY '/ DATA L(6)/'SSWAP '/ DATA L(7)/'SNRM2 '/ DATA L(8)/'SASUM '/ DATA L(9)/'SSCAL '/ DATA L(10)/'ISAMAX'/ DATA L(11)/'SROTMG'/ DATA L(12)/'SROTM '/ DATA L(13)/'SDSDOT'/ * .. Executable Statements .. WRITE (NOUT,99999) ICASE, L(ICASE) RETURN * 99999 FORMAT (/' Test of subprogram number',I3,12X,A6) END SUBROUTINE CHECK0(SFAC) * .. Parameters .. INTEGER NOUT PARAMETER (NOUT=6) * .. Scalar Arguments .. REAL SFAC * .. Scalars in Common .. INTEGER ICASE, INCX, INCY, N LOGICAL PASS * .. Local Scalars .. REAL D12, SA, SB, SC, SS INTEGER I, K * .. Local Arrays .. REAL DA1(8), DATRUE(8), DB1(8), DBTRUE(8), DC1(8), + DS1(8), DAB(4,9), DTEMP(9), DTRUE(9,9) * .. External Subroutines .. EXTERNAL SROTG, SROTMG, STEST1 * .. Common blocks .. COMMON /COMBLA/ICASE, N, INCX, INCY, PASS * .. Data statements .. DATA DA1/0.3E0, 0.4E0, -0.3E0, -0.4E0, -0.3E0, 0.0E0, + 0.0E0, 1.0E0/ DATA DB1/0.4E0, 0.3E0, 0.4E0, 0.3E0, -0.4E0, 0.0E0, + 1.0E0, 0.0E0/ DATA DC1/0.6E0, 0.8E0, -0.6E0, 0.8E0, 0.6E0, 1.0E0, + 0.0E0, 1.0E0/ DATA DS1/0.8E0, 0.6E0, 0.8E0, -0.6E0, 0.8E0, 0.0E0, + 1.0E0, 0.0E0/ DATA DATRUE/0.5E0, 0.5E0, 0.5E0, -0.5E0, -0.5E0, + 0.0E0, 1.0E0, 1.0E0/ DATA DBTRUE/0.0E0, 0.6E0, 0.0E0, -0.6E0, 0.0E0, + 0.0E0, 1.0E0, 0.0E0/ * INPUT FOR MODIFIED GIVENS DATA DAB/ .1E0,.3E0,1.2E0,.2E0, A .7E0, .2E0, .6E0, 4.2E0, B 0.E0,0.E0,0.E0,0.E0, C 4.E0, -1.E0, 2.E0, 4.E0, D 6.E-10, 2.E-2, 1.E5, 10.E0, E 4.E10, 2.E-2, 1.E-5, 10.E0, F 2.E-10, 4.E-2, 1.E5, 10.E0, G 2.E10, 4.E-2, 1.E-5, 10.E0, H 4.E0, -2.E0, 8.E0, 4.E0 / * TRUE RESULTS FOR MODIFIED GIVENS DATA DTRUE/0.E0,0.E0, 1.3E0, .2E0, 0.E0,0.E0,0.E0, .5E0, 0.E0, A 0.E0,0.E0, 4.5E0, 4.2E0, 1.E0, .5E0, 0.E0,0.E0,0.E0, B 0.E0,0.E0,0.E0,0.E0, -2.E0, 0.E0,0.E0,0.E0,0.E0, C 0.E0,0.E0,0.E0, 4.E0, -1.E0, 0.E0,0.E0,0.E0,0.E0, D 0.E0, 15.E-3, 0.E0, 10.E0, -1.E0, 0.E0, -1.E-4, E 0.E0, 1.E0, F 0.E0,0.E0, 6144.E-5, 10.E0, -1.E0, 4096.E0, -1.E6, G 0.E0, 1.E0, H 0.E0,0.E0,15.E0,10.E0,-1.E0, 5.E-5, 0.E0,1.E0,0.E0, I 0.E0,0.E0, 15.E0, 10.E0, -1. E0, 5.E5, -4096.E0, J 1.E0, 4096.E-6, K 0.E0,0.E0, 7.E0, 4.E0, 0.E0,0.E0, -.5E0, -.25E0, 0.E0/ * 4096 = 2 ** 12 DATA D12 /4096.E0/ DTRUE(1,1) = 12.E0 / 130.E0 DTRUE(2,1) = 36.E0 / 130.E0 DTRUE(7,1) = -1.E0 / 6.E0 DTRUE(1,2) = 14.E0 / 75.E0 DTRUE(2,2) = 49.E0 / 75.E0 DTRUE(9,2) = 1.E0 / 7.E0 DTRUE(1,5) = 45.E-11 * (D12 * D12) DTRUE(3,5) = 4.E5 / (3.E0 * D12) DTRUE(6,5) = 1.E0 / D12 DTRUE(8,5) = 1.E4 / (3.E0 * D12) DTRUE(1,6) = 4.E10 / (1.5E0 * D12 * D12) DTRUE(2,6) = 2.E-2 / 1.5E0 DTRUE(8,6) = 5.E-7 * D12 DTRUE(1,7) = 4.E0 / 150.E0 DTRUE(2,7) = (2.E-10 / 1.5E0) * (D12 * D12) DTRUE(7,7) = -DTRUE(6,5) DTRUE(9,7) = 1.E4 / D12 DTRUE(1,8) = DTRUE(1,7) DTRUE(2,8) = 2.E10 / (1.5E0 * D12 * D12) DTRUE(1,9) = 32.E0 / 7.E0 DTRUE(2,9) = -16.E0 / 7.E0 * .. Executable Statements .. * * Compute true values which cannot be prestored * in decimal notation * DBTRUE(1) = 1.0E0/0.6E0 DBTRUE(3) = -1.0E0/0.6E0 DBTRUE(5) = 1.0E0/0.6E0 * DO 20 K = 1, 8 * .. Set N=K for identification in output if any .. N = K IF (ICASE.EQ.3) THEN * .. SROTG .. IF (K.GT.8) GO TO 40 SA = DA1(K) SB = DB1(K) CALL SROTG(SA,SB,SC,SS) CALL STEST1(SA,DATRUE(K),DATRUE(K),SFAC) CALL STEST1(SB,DBTRUE(K),DBTRUE(K),SFAC) CALL STEST1(SC,DC1(K),DC1(K),SFAC) CALL STEST1(SS,DS1(K),DS1(K),SFAC) ELSEIF (ICASE.EQ.11) THEN * .. SROTMG .. DO I=1,4 DTEMP(I)= DAB(I,K) DTEMP(I+4) = 0.0 END DO DTEMP(9) = 0.0 CALL SROTMG(DTEMP(1),DTEMP(2),DTEMP(3),DTEMP(4),DTEMP(5)) CALL STEST(9,DTEMP,DTRUE(1,K),DTRUE(1,K),SFAC) ELSE WRITE (NOUT,*) ' Shouldn''t be here in CHECK0' STOP END IF 20 CONTINUE 40 RETURN END SUBROUTINE CHECK1(SFAC) * .. Parameters .. INTEGER NOUT PARAMETER (NOUT=6) * .. Scalar Arguments .. REAL SFAC * .. Scalars in Common .. INTEGER ICASE, INCX, INCY, N LOGICAL PASS * .. Local Scalars .. INTEGER I, LEN, NP1 * .. Local Arrays .. REAL DTRUE1(5), DTRUE3(5), DTRUE5(8,5,2), DV(8,5,2), + SA(10), STEMP(1), STRUE(8), SX(8) INTEGER ITRUE2(5) * .. External Functions .. REAL SASUM, SNRM2 INTEGER ISAMAX EXTERNAL SASUM, SNRM2, ISAMAX * .. External Subroutines .. EXTERNAL ITEST1, SSCAL, STEST, STEST1 * .. Intrinsic Functions .. INTRINSIC MAX * .. Common blocks .. COMMON /COMBLA/ICASE, N, INCX, INCY, PASS * .. Data statements .. DATA SA/0.3E0, -1.0E0, 0.0E0, 1.0E0, 0.3E0, 0.3E0, + 0.3E0, 0.3E0, 0.3E0, 0.3E0/ DATA DV/0.1E0, 2.0E0, 2.0E0, 2.0E0, 2.0E0, 2.0E0, + 2.0E0, 2.0E0, 0.3E0, 3.0E0, 3.0E0, 3.0E0, 3.0E0, + 3.0E0, 3.0E0, 3.0E0, 0.3E0, -0.4E0, 4.0E0, + 4.0E0, 4.0E0, 4.0E0, 4.0E0, 4.0E0, 0.2E0, + -0.6E0, 0.3E0, 5.0E0, 5.0E0, 5.0E0, 5.0E0, + 5.0E0, 0.1E0, -0.3E0, 0.5E0, -0.1E0, 6.0E0, + 6.0E0, 6.0E0, 6.0E0, 0.1E0, 8.0E0, 8.0E0, 8.0E0, + 8.0E0, 8.0E0, 8.0E0, 8.0E0, 0.3E0, 9.0E0, 9.0E0, + 9.0E0, 9.0E0, 9.0E0, 9.0E0, 9.0E0, 0.3E0, 2.0E0, + -0.4E0, 2.0E0, 2.0E0, 2.0E0, 2.0E0, 2.0E0, + 0.2E0, 3.0E0, -0.6E0, 5.0E0, 0.3E0, 2.0E0, + 2.0E0, 2.0E0, 0.1E0, 4.0E0, -0.3E0, 6.0E0, + -0.5E0, 7.0E0, -0.1E0, 3.0E0/ DATA DTRUE1/0.0E0, 0.3E0, 0.5E0, 0.7E0, 0.6E0/ DATA DTRUE3/0.0E0, 0.3E0, 0.7E0, 1.1E0, 1.0E0/ DATA DTRUE5/0.10E0, 2.0E0, 2.0E0, 2.0E0, 2.0E0, + 2.0E0, 2.0E0, 2.0E0, -0.3E0, 3.0E0, 3.0E0, + 3.0E0, 3.0E0, 3.0E0, 3.0E0, 3.0E0, 0.0E0, 0.0E0, + 4.0E0, 4.0E0, 4.0E0, 4.0E0, 4.0E0, 4.0E0, + 0.20E0, -0.60E0, 0.30E0, 5.0E0, 5.0E0, 5.0E0, + 5.0E0, 5.0E0, 0.03E0, -0.09E0, 0.15E0, -0.03E0, + 6.0E0, 6.0E0, 6.0E0, 6.0E0, 0.10E0, 8.0E0, + 8.0E0, 8.0E0, 8.0E0, 8.0E0, 8.0E0, 8.0E0, + 0.09E0, 9.0E0, 9.0E0, 9.0E0, 9.0E0, 9.0E0, + 9.0E0, 9.0E0, 0.09E0, 2.0E0, -0.12E0, 2.0E0, + 2.0E0, 2.0E0, 2.0E0, 2.0E0, 0.06E0, 3.0E0, + -0.18E0, 5.0E0, 0.09E0, 2.0E0, 2.0E0, 2.0E0, + 0.03E0, 4.0E0, -0.09E0, 6.0E0, -0.15E0, 7.0E0, + -0.03E0, 3.0E0/ DATA ITRUE2/0, 1, 2, 2, 3/ * .. Executable Statements .. DO 80 INCX = 1, 2 DO 60 NP1 = 1, 5 N = NP1 - 1 LEN = 2*MAX(N,1) * .. Set vector arguments .. DO 20 I = 1, LEN SX(I) = DV(I,NP1,INCX) 20 CONTINUE * IF (ICASE.EQ.7) THEN * .. SNRM2 .. STEMP(1) = DTRUE1(NP1) CALL STEST1(SNRM2(N,SX,INCX),STEMP(1),STEMP,SFAC) ELSE IF (ICASE.EQ.8) THEN * .. SASUM .. STEMP(1) = DTRUE3(NP1) CALL STEST1(SASUM(N,SX,INCX),STEMP(1),STEMP,SFAC) ELSE IF (ICASE.EQ.9) THEN * .. SSCAL .. CALL SSCAL(N,SA((INCX-1)*5+NP1),SX,INCX) DO 40 I = 1, LEN STRUE(I) = DTRUE5(I,NP1,INCX) 40 CONTINUE CALL STEST(LEN,SX,STRUE,STRUE,SFAC) ELSE IF (ICASE.EQ.10) THEN * .. ISAMAX .. CALL ITEST1(ISAMAX(N,SX,INCX),ITRUE2(NP1)) ELSE WRITE (NOUT,*) ' Shouldn''t be here in CHECK1' STOP END IF 60 CONTINUE 80 CONTINUE RETURN END SUBROUTINE CHECK2(SFAC) * .. Parameters .. INTEGER NOUT PARAMETER (NOUT=6) * .. Scalar Arguments .. REAL SFAC * .. Scalars in Common .. INTEGER ICASE, INCX, INCY, N LOGICAL PASS * .. Local Scalars .. REAL SA INTEGER I, J, KI, KN, KNI, KPAR, KSIZE, LENX, LENY, $ MX, MY * .. Local Arrays .. REAL DT10X(7,4,4), DT10Y(7,4,4), DT7(4,4), $ DT8(7,4,4), DX1(7), $ DY1(7), SSIZE1(4), SSIZE2(14,2), SSIZE3(4), $ SSIZE(7), STX(7), STY(7), SX(7), SY(7), $ DPAR(5,4), DT19X(7,4,16),DT19XA(7,4,4), $ DT19XB(7,4,4), DT19XC(7,4,4),DT19XD(7,4,4), $ DT19Y(7,4,16), DT19YA(7,4,4),DT19YB(7,4,4), $ DT19YC(7,4,4), DT19YD(7,4,4), DTEMP(5), $ ST7B(4,4) INTEGER INCXS(4), INCYS(4), LENS(4,2), NS(4) * .. External Functions .. REAL SDOT, SDSDOT EXTERNAL SDOT, SDSDOT * .. External Subroutines .. EXTERNAL SAXPY, SCOPY, SROTM, SSWAP, STEST, STEST1 * .. Intrinsic Functions .. INTRINSIC ABS, MIN * .. Common blocks .. COMMON /COMBLA/ICASE, N, INCX, INCY, PASS * .. Data statements .. EQUIVALENCE (DT19X(1,1,1),DT19XA(1,1,1)),(DT19X(1,1,5), A DT19XB(1,1,1)),(DT19X(1,1,9),DT19XC(1,1,1)), B (DT19X(1,1,13),DT19XD(1,1,1)) EQUIVALENCE (DT19Y(1,1,1),DT19YA(1,1,1)),(DT19Y(1,1,5), A DT19YB(1,1,1)),(DT19Y(1,1,9),DT19YC(1,1,1)), B (DT19Y(1,1,13),DT19YD(1,1,1)) DATA SA/0.3E0/ DATA INCXS/1, 2, -2, -1/ DATA INCYS/1, -2, 1, -2/ DATA LENS/1, 1, 2, 4, 1, 1, 3, 7/ DATA NS/0, 1, 2, 4/ DATA DX1/0.6E0, 0.1E0, -0.5E0, 0.8E0, 0.9E0, -0.3E0, + -0.4E0/ DATA DY1/0.5E0, -0.9E0, 0.3E0, 0.7E0, -0.6E0, 0.2E0, + 0.8E0/ DATA DT7/0.0E0, 0.30E0, 0.21E0, 0.62E0, 0.0E0, + 0.30E0, -0.07E0, 0.85E0, 0.0E0, 0.30E0, -0.79E0, + -0.74E0, 0.0E0, 0.30E0, 0.33E0, 1.27E0/ DATA ST7B/ .1, .4, .31, .72, .1, .4, .03, .95, + .1, .4, -.69, -.64, .1, .4, .43, 1.37/ DATA DT8/0.5E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, + 0.0E0, 0.68E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, + 0.0E0, 0.0E0, 0.68E0, -0.87E0, 0.0E0, 0.0E0, + 0.0E0, 0.0E0, 0.0E0, 0.68E0, -0.87E0, 0.15E0, + 0.94E0, 0.0E0, 0.0E0, 0.0E0, 0.5E0, 0.0E0, + 0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.68E0, + 0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, + 0.35E0, -0.9E0, 0.48E0, 0.0E0, 0.0E0, 0.0E0, + 0.0E0, 0.38E0, -0.9E0, 0.57E0, 0.7E0, -0.75E0, + 0.2E0, 0.98E0, 0.5E0, 0.0E0, 0.0E0, 0.0E0, + 0.0E0, 0.0E0, 0.0E0, 0.68E0, 0.0E0, 0.0E0, + 0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.35E0, -0.72E0, + 0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.38E0, + -0.63E0, 0.15E0, 0.88E0, 0.0E0, 0.0E0, 0.0E0, + 0.5E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, + 0.68E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, + 0.0E0, 0.68E0, -0.9E0, 0.33E0, 0.0E0, 0.0E0, + 0.0E0, 0.0E0, 0.68E0, -0.9E0, 0.33E0, 0.7E0, + -0.75E0, 0.2E0, 1.04E0/ DATA DT10X/0.6E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, + 0.0E0, 0.5E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, + 0.0E0, 0.5E0, -0.9E0, 0.0E0, 0.0E0, 0.0E0, + 0.0E0, 0.0E0, 0.5E0, -0.9E0, 0.3E0, 0.7E0, + 0.0E0, 0.0E0, 0.0E0, 0.6E0, 0.0E0, 0.0E0, 0.0E0, + 0.0E0, 0.0E0, 0.0E0, 0.5E0, 0.0E0, 0.0E0, 0.0E0, + 0.0E0, 0.0E0, 0.0E0, 0.3E0, 0.1E0, 0.5E0, 0.0E0, + 0.0E0, 0.0E0, 0.0E0, 0.8E0, 0.1E0, -0.6E0, + 0.8E0, 0.3E0, -0.3E0, 0.5E0, 0.6E0, 0.0E0, + 0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.5E0, 0.0E0, + 0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, -0.9E0, + 0.1E0, 0.5E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.7E0, + 0.1E0, 0.3E0, 0.8E0, -0.9E0, -0.3E0, 0.5E0, + 0.6E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, + 0.5E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, + 0.5E0, 0.3E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, + 0.5E0, 0.3E0, -0.6E0, 0.8E0, 0.0E0, 0.0E0, + 0.0E0/ DATA DT10Y/0.5E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, + 0.0E0, 0.6E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, + 0.0E0, 0.6E0, 0.1E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, + 0.0E0, 0.6E0, 0.1E0, -0.5E0, 0.8E0, 0.0E0, + 0.0E0, 0.0E0, 0.5E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, + 0.0E0, 0.0E0, 0.6E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, + 0.0E0, 0.0E0, -0.5E0, -0.9E0, 0.6E0, 0.0E0, + 0.0E0, 0.0E0, 0.0E0, -0.4E0, -0.9E0, 0.9E0, + 0.7E0, -0.5E0, 0.2E0, 0.6E0, 0.5E0, 0.0E0, + 0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.6E0, 0.0E0, + 0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, -0.5E0, + 0.6E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, + -0.4E0, 0.9E0, -0.5E0, 0.6E0, 0.0E0, 0.0E0, + 0.0E0, 0.5E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, + 0.0E0, 0.6E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, + 0.0E0, 0.6E0, -0.9E0, 0.1E0, 0.0E0, 0.0E0, + 0.0E0, 0.0E0, 0.6E0, -0.9E0, 0.1E0, 0.7E0, + -0.5E0, 0.2E0, 0.8E0/ DATA SSIZE1/0.0E0, 0.3E0, 1.6E0, 3.2E0/ DATA SSIZE2/0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, + 0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, + 0.0E0, 1.17E0, 1.17E0, 1.17E0, 1.17E0, 1.17E0, + 1.17E0, 1.17E0, 1.17E0, 1.17E0, 1.17E0, 1.17E0, + 1.17E0, 1.17E0, 1.17E0/ DATA SSIZE3/ .1, .4, 1.7, 3.3 / * * FOR DROTM * DATA DPAR/-2.E0, 0.E0,0.E0,0.E0,0.E0, A -1.E0, 2.E0, -3.E0, -4.E0, 5.E0, B 0.E0, 0.E0, 2.E0, -3.E0, 0.E0, C 1.E0, 5.E0, 2.E0, 0.E0, -4.E0/ * TRUE X RESULTS F0R ROTATIONS DROTM DATA DT19XA/.6E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0, A .6E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0, B .6E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0, C .6E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0, D .6E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0, E -.8E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0, F -.9E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0, G 3.5E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0, H .6E0, .1E0, 0.E0,0.E0,0.E0,0.E0,0.E0, I -.8E0, 3.8E0, 0.E0,0.E0,0.E0,0.E0,0.E0, J -.9E0, 2.8E0, 0.E0,0.E0,0.E0,0.E0,0.E0, K 3.5E0, -.4E0, 0.E0,0.E0,0.E0,0.E0,0.E0, L .6E0, .1E0, -.5E0, .8E0, 0.E0,0.E0,0.E0, M -.8E0, 3.8E0, -2.2E0, -1.2E0, 0.E0,0.E0,0.E0, N -.9E0, 2.8E0, -1.4E0, -1.3E0, 0.E0,0.E0,0.E0, O 3.5E0, -.4E0, -2.2E0, 4.7E0, 0.E0,0.E0,0.E0/ * DATA DT19XB/.6E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0, A .6E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0, B .6E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0, C .6E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0, D .6E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0, E -.8E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0, F -.9E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0, G 3.5E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0, H .6E0, .1E0, -.5E0, 0.E0,0.E0,0.E0,0.E0, I 0.E0, .1E0, -3.0E0, 0.E0,0.E0,0.E0,0.E0, J -.3E0, .1E0, -2.0E0, 0.E0,0.E0,0.E0,0.E0, K 3.3E0, .1E0, -2.0E0, 0.E0,0.E0,0.E0,0.E0, L .6E0, .1E0, -.5E0, .8E0, .9E0, -.3E0, -.4E0, M -2.0E0, .1E0, 1.4E0, .8E0, .6E0, -.3E0, -2.8E0, N -1.8E0, .1E0, 1.3E0, .8E0, 0.E0, -.3E0, -1.9E0, O 3.8E0, .1E0, -3.1E0, .8E0, 4.8E0, -.3E0, -1.5E0 / * DATA DT19XC/.6E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0, A .6E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0, B .6E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0, C .6E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0, D .6E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0, E -.8E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0, F -.9E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0, G 3.5E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0, H .6E0, .1E0, -.5E0, 0.E0,0.E0,0.E0,0.E0, I 4.8E0, .1E0, -3.0E0, 0.E0,0.E0,0.E0,0.E0, J 3.3E0, .1E0, -2.0E0, 0.E0,0.E0,0.E0,0.E0, K 2.1E0, .1E0, -2.0E0, 0.E0,0.E0,0.E0,0.E0, L .6E0, .1E0, -.5E0, .8E0, .9E0, -.3E0, -.4E0, M -1.6E0, .1E0, -2.2E0, .8E0, 5.4E0, -.3E0, -2.8E0, N -1.5E0, .1E0, -1.4E0, .8E0, 3.6E0, -.3E0, -1.9E0, O 3.7E0, .1E0, -2.2E0, .8E0, 3.6E0, -.3E0, -1.5E0 / * DATA DT19XD/.6E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0, A .6E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0, B .6E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0, C .6E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0, D .6E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0, E -.8E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0, F -.9E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0, G 3.5E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0, H .6E0, .1E0, 0.E0,0.E0,0.E0,0.E0,0.E0, I -.8E0, -1.0E0, 0.E0,0.E0,0.E0,0.E0,0.E0, J -.9E0, -.8E0, 0.E0,0.E0,0.E0,0.E0,0.E0, K 3.5E0, .8E0, 0.E0,0.E0,0.E0,0.E0,0.E0, L .6E0, .1E0, -.5E0, .8E0, 0.E0,0.E0,0.E0, M -.8E0, -1.0E0, 1.4E0, -1.6E0, 0.E0,0.E0,0.E0, N -.9E0, -.8E0, 1.3E0, -1.6E0, 0.E0,0.E0,0.E0, O 3.5E0, .8E0, -3.1E0, 4.8E0, 0.E0,0.E0,0.E0/ * TRUE Y RESULTS FOR ROTATIONS DROTM DATA DT19YA/.5E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0, A .5E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0, B .5E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0, C .5E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0, D .5E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0, E .7E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0, F 1.7E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0, G -2.6E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0, H .5E0, -.9E0, 0.E0,0.E0,0.E0,0.E0,0.E0, I .7E0, -4.8E0, 0.E0,0.E0,0.E0,0.E0,0.E0, J 1.7E0, -.7E0, 0.E0,0.E0,0.E0,0.E0,0.E0, K -2.6E0, 3.5E0, 0.E0,0.E0,0.E0,0.E0,0.E0, L .5E0, -.9E0, .3E0, .7E0, 0.E0,0.E0,0.E0, M .7E0, -4.8E0, 3.0E0, 1.1E0, 0.E0,0.E0,0.E0, N 1.7E0, -.7E0, -.7E0, 2.3E0, 0.E0,0.E0,0.E0, O -2.6E0, 3.5E0, -.7E0, -3.6E0, 0.E0,0.E0,0.E0/ * DATA DT19YB/.5E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0, A .5E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0, B .5E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0, C .5E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0, D .5E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0, E .7E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0, F 1.7E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0, G -2.6E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0, H .5E0, -.9E0, .3E0, 0.E0,0.E0,0.E0,0.E0, I 4.0E0, -.9E0, -.3E0, 0.E0,0.E0,0.E0,0.E0, J -.5E0, -.9E0, 1.5E0, 0.E0,0.E0,0.E0,0.E0, K -1.5E0, -.9E0, -1.8E0, 0.E0,0.E0,0.E0,0.E0, L .5E0, -.9E0, .3E0, .7E0, -.6E0, .2E0, .8E0, M 3.7E0, -.9E0, -1.2E0, .7E0, -1.5E0, .2E0, 2.2E0, N -.3E0, -.9E0, 2.1E0, .7E0, -1.6E0, .2E0, 2.0E0, O -1.6E0, -.9E0, -2.1E0, .7E0, 2.9E0, .2E0, -3.8E0 / * DATA DT19YC/.5E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0, A .5E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0, B .5E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0, C .5E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0, D .5E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0, E .7E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0, F 1.7E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0, G -2.6E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0, H .5E0, -.9E0, 0.E0,0.E0,0.E0,0.E0,0.E0, I 4.0E0, -6.3E0, 0.E0,0.E0,0.E0,0.E0,0.E0, J -.5E0, .3E0, 0.E0,0.E0,0.E0,0.E0,0.E0, K -1.5E0, 3.0E0, 0.E0,0.E0,0.E0,0.E0,0.E0, L .5E0, -.9E0, .3E0, .7E0, 0.E0,0.E0,0.E0, M 3.7E0, -7.2E0, 3.0E0, 1.7E0, 0.E0,0.E0,0.E0, N -.3E0, .9E0, -.7E0, 1.9E0, 0.E0,0.E0,0.E0, O -1.6E0, 2.7E0, -.7E0, -3.4E0, 0.E0,0.E0,0.E0/ * DATA DT19YD/.5E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0, A .5E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0, B .5E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0, C .5E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0, D .5E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0, E .7E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0, F 1.7E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0, G -2.6E0, 0.E0,0.E0,0.E0,0.E0,0.E0,0.E0, H .5E0, -.9E0, .3E0, 0.E0,0.E0,0.E0,0.E0, I .7E0, -.9E0, 1.2E0, 0.E0,0.E0,0.E0,0.E0, J 1.7E0, -.9E0, .5E0, 0.E0,0.E0,0.E0,0.E0, K -2.6E0, -.9E0, -1.3E0, 0.E0,0.E0,0.E0,0.E0, L .5E0, -.9E0, .3E0, .7E0, -.6E0, .2E0, .8E0, M .7E0, -.9E0, 1.2E0, .7E0, -1.5E0, .2E0, 1.6E0, N 1.7E0, -.9E0, .5E0, .7E0, -1.6E0, .2E0, 2.4E0, O -2.6E0, -.9E0, -1.3E0, .7E0, 2.9E0, .2E0, -4.0E0 / * * .. Executable Statements .. * DO 120 KI = 1, 4 INCX = INCXS(KI) INCY = INCYS(KI) MX = ABS(INCX) MY = ABS(INCY) * DO 100 KN = 1, 4 N = NS(KN) KSIZE = MIN(2,KN) LENX = LENS(KN,MX) LENY = LENS(KN,MY) * .. Initialize all argument arrays .. DO 20 I = 1, 7 SX(I) = DX1(I) SY(I) = DY1(I) 20 CONTINUE * IF (ICASE.EQ.1) THEN * .. SDOT .. CALL STEST1(SDOT(N,SX,INCX,SY,INCY),DT7(KN,KI),SSIZE1(KN) + ,SFAC) ELSE IF (ICASE.EQ.2) THEN * .. SAXPY .. CALL SAXPY(N,SA,SX,INCX,SY,INCY) DO 40 J = 1, LENY STY(J) = DT8(J,KN,KI) 40 CONTINUE CALL STEST(LENY,SY,STY,SSIZE2(1,KSIZE),SFAC) ELSE IF (ICASE.EQ.5) THEN * .. SCOPY .. DO 60 I = 1, 7 STY(I) = DT10Y(I,KN,KI) 60 CONTINUE CALL SCOPY(N,SX,INCX,SY,INCY) CALL STEST(LENY,SY,STY,SSIZE2(1,1),1.0E0) ELSE IF (ICASE.EQ.6) THEN * .. SSWAP .. CALL SSWAP(N,SX,INCX,SY,INCY) DO 80 I = 1, 7 STX(I) = DT10X(I,KN,KI) STY(I) = DT10Y(I,KN,KI) 80 CONTINUE CALL STEST(LENX,SX,STX,SSIZE2(1,1),1.0E0) CALL STEST(LENY,SY,STY,SSIZE2(1,1),1.0E0) ELSEIF (ICASE.EQ.12) THEN * .. SROTM .. KNI=KN+4*(KI-1) DO KPAR=1,4 DO I=1,7 SX(I) = DX1(I) SY(I) = DY1(I) STX(I)= DT19X(I,KPAR,KNI) STY(I)= DT19Y(I,KPAR,KNI) END DO * DO I=1,5 DTEMP(I) = DPAR(I,KPAR) END DO * DO I=1,LENX SSIZE(I)=STX(I) END DO * SEE REMARK ABOVE ABOUT DT11X(1,2,7) * AND DT11X(5,3,8). IF ((KPAR .EQ. 2) .AND. (KNI .EQ. 7)) $ SSIZE(1) = 2.4E0 IF ((KPAR .EQ. 3) .AND. (KNI .EQ. 8)) $ SSIZE(5) = 1.8E0 * CALL SROTM(N,SX,INCX,SY,INCY,DTEMP) CALL STEST(LENX,SX,STX,SSIZE,SFAC) CALL STEST(LENY,SY,STY,STY,SFAC) END DO ELSEIF (ICASE.EQ.13) THEN * .. SDSROT .. CALL STEST1 (SDSDOT(N,.1,SX,INCX,SY,INCY), $ ST7B(KN,KI),SSIZE3(KN),SFAC) ELSE WRITE (NOUT,*) ' Shouldn''t be here in CHECK2' STOP END IF 100 CONTINUE 120 CONTINUE RETURN END SUBROUTINE CHECK3(SFAC) * .. Parameters .. INTEGER NOUT PARAMETER (NOUT=6) * .. Scalar Arguments .. REAL SFAC * .. Scalars in Common .. INTEGER ICASE, INCX, INCY, N LOGICAL PASS * .. Local Scalars .. REAL SC, SS INTEGER I, K, KI, KN, KSIZE, LENX, LENY, MX, MY * .. Local Arrays .. REAL COPYX(5), COPYY(5), DT9X(7,4,4), DT9Y(7,4,4), + DX1(7), DY1(7), MWPC(11), MWPS(11), MWPSTX(5), + MWPSTY(5), MWPTX(11,5), MWPTY(11,5), MWPX(5), + MWPY(5), SSIZE2(14,2), STX(7), STY(7), SX(7), + SY(7) INTEGER INCXS(4), INCYS(4), LENS(4,2), MWPINX(11), + MWPINY(11), MWPN(11), NS(4) * .. External Subroutines .. EXTERNAL SROT, STEST * .. Intrinsic Functions .. INTRINSIC ABS, MIN * .. Common blocks .. COMMON /COMBLA/ICASE, N, INCX, INCY, PASS * .. Data statements .. DATA INCXS/1, 2, -2, -1/ DATA INCYS/1, -2, 1, -2/ DATA LENS/1, 1, 2, 4, 1, 1, 3, 7/ DATA NS/0, 1, 2, 4/ DATA DX1/0.6E0, 0.1E0, -0.5E0, 0.8E0, 0.9E0, -0.3E0, + -0.4E0/ DATA DY1/0.5E0, -0.9E0, 0.3E0, 0.7E0, -0.6E0, 0.2E0, + 0.8E0/ DATA SC, SS/0.8E0, 0.6E0/ DATA DT9X/0.6E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, + 0.0E0, 0.78E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, + 0.0E0, 0.0E0, 0.78E0, -0.46E0, 0.0E0, 0.0E0, + 0.0E0, 0.0E0, 0.0E0, 0.78E0, -0.46E0, -0.22E0, + 1.06E0, 0.0E0, 0.0E0, 0.0E0, 0.6E0, 0.0E0, + 0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.78E0, + 0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, + 0.66E0, 0.1E0, -0.1E0, 0.0E0, 0.0E0, 0.0E0, + 0.0E0, 0.96E0, 0.1E0, -0.76E0, 0.8E0, 0.90E0, + -0.3E0, -0.02E0, 0.6E0, 0.0E0, 0.0E0, 0.0E0, + 0.0E0, 0.0E0, 0.0E0, 0.78E0, 0.0E0, 0.0E0, + 0.0E0, 0.0E0, 0.0E0, 0.0E0, -0.06E0, 0.1E0, + -0.1E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.90E0, + 0.1E0, -0.22E0, 0.8E0, 0.18E0, -0.3E0, -0.02E0, + 0.6E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, + 0.78E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, + 0.0E0, 0.78E0, 0.26E0, 0.0E0, 0.0E0, 0.0E0, + 0.0E0, 0.0E0, 0.78E0, 0.26E0, -0.76E0, 1.12E0, + 0.0E0, 0.0E0, 0.0E0/ DATA DT9Y/0.5E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, + 0.0E0, 0.04E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, + 0.0E0, 0.0E0, 0.04E0, -0.78E0, 0.0E0, 0.0E0, + 0.0E0, 0.0E0, 0.0E0, 0.04E0, -0.78E0, 0.54E0, + 0.08E0, 0.0E0, 0.0E0, 0.0E0, 0.5E0, 0.0E0, + 0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.04E0, + 0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.7E0, + -0.9E0, -0.12E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, + 0.64E0, -0.9E0, -0.30E0, 0.7E0, -0.18E0, 0.2E0, + 0.28E0, 0.5E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, + 0.0E0, 0.0E0, 0.04E0, 0.0E0, 0.0E0, 0.0E0, + 0.0E0, 0.0E0, 0.0E0, 0.7E0, -1.08E0, 0.0E0, + 0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.64E0, -1.26E0, + 0.54E0, 0.20E0, 0.0E0, 0.0E0, 0.0E0, 0.5E0, + 0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, + 0.04E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, + 0.0E0, 0.04E0, -0.9E0, 0.18E0, 0.0E0, 0.0E0, + 0.0E0, 0.0E0, 0.04E0, -0.9E0, 0.18E0, 0.7E0, + -0.18E0, 0.2E0, 0.16E0/ DATA SSIZE2/0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, + 0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, 0.0E0, + 0.0E0, 1.17E0, 1.17E0, 1.17E0, 1.17E0, 1.17E0, + 1.17E0, 1.17E0, 1.17E0, 1.17E0, 1.17E0, 1.17E0, + 1.17E0, 1.17E0, 1.17E0/ * .. Executable Statements .. * DO 60 KI = 1, 4 INCX = INCXS(KI) INCY = INCYS(KI) MX = ABS(INCX) MY = ABS(INCY) * DO 40 KN = 1, 4 N = NS(KN) KSIZE = MIN(2,KN) LENX = LENS(KN,MX) LENY = LENS(KN,MY) * IF (ICASE.EQ.4) THEN * .. SROT .. DO 20 I = 1, 7 SX(I) = DX1(I) SY(I) = DY1(I) STX(I) = DT9X(I,KN,KI) STY(I) = DT9Y(I,KN,KI) 20 CONTINUE CALL SROT(N,SX,INCX,SY,INCY,SC,SS) CALL STEST(LENX,SX,STX,SSIZE2(1,KSIZE),SFAC) CALL STEST(LENY,SY,STY,SSIZE2(1,KSIZE),SFAC) ELSE WRITE (NOUT,*) ' Shouldn''t be here in CHECK3' STOP END IF 40 CONTINUE 60 CONTINUE * MWPC(1) = 1 DO 80 I = 2, 11 MWPC(I) = 0 80 CONTINUE MWPS(1) = 0 DO 100 I = 2, 6 MWPS(I) = 1 100 CONTINUE DO 120 I = 7, 11 MWPS(I) = -1 120 CONTINUE MWPINX(1) = 1 MWPINX(2) = 1 MWPINX(3) = 1 MWPINX(4) = -1 MWPINX(5) = 1 MWPINX(6) = -1 MWPINX(7) = 1 MWPINX(8) = 1 MWPINX(9) = -1 MWPINX(10) = 1 MWPINX(11) = -1 MWPINY(1) = 1 MWPINY(2) = 1 MWPINY(3) = -1 MWPINY(4) = -1 MWPINY(5) = 2 MWPINY(6) = 1 MWPINY(7) = 1 MWPINY(8) = -1 MWPINY(9) = -1 MWPINY(10) = 2 MWPINY(11) = 1 DO 140 I = 1, 11 MWPN(I) = 5 140 CONTINUE MWPN(5) = 3 MWPN(10) = 3 DO 160 I = 1, 5 MWPX(I) = I MWPY(I) = I MWPTX(1,I) = I MWPTY(1,I) = I MWPTX(2,I) = I MWPTY(2,I) = -I MWPTX(3,I) = 6 - I MWPTY(3,I) = I - 6 MWPTX(4,I) = I MWPTY(4,I) = -I MWPTX(6,I) = 6 - I MWPTY(6,I) = I - 6 MWPTX(7,I) = -I MWPTY(7,I) = I MWPTX(8,I) = I - 6 MWPTY(8,I) = 6 - I MWPTX(9,I) = -I MWPTY(9,I) = I MWPTX(11,I) = I - 6 MWPTY(11,I) = 6 - I 160 CONTINUE MWPTX(5,1) = 1 MWPTX(5,2) = 3 MWPTX(5,3) = 5 MWPTX(5,4) = 4 MWPTX(5,5) = 5 MWPTY(5,1) = -1 MWPTY(5,2) = 2 MWPTY(5,3) = -2 MWPTY(5,4) = 4 MWPTY(5,5) = -3 MWPTX(10,1) = -1 MWPTX(10,2) = -3 MWPTX(10,3) = -5 MWPTX(10,4) = 4 MWPTX(10,5) = 5 MWPTY(10,1) = 1 MWPTY(10,2) = 2 MWPTY(10,3) = 2 MWPTY(10,4) = 4 MWPTY(10,5) = 3 DO 200 I = 1, 11 INCX = MWPINX(I) INCY = MWPINY(I) DO 180 K = 1, 5 COPYX(K) = MWPX(K) COPYY(K) = MWPY(K) MWPSTX(K) = MWPTX(I,K) MWPSTY(K) = MWPTY(I,K) 180 CONTINUE CALL SROT(MWPN(I),COPYX,INCX,COPYY,INCY,MWPC(I),MWPS(I)) CALL STEST(5,COPYX,MWPSTX,MWPSTX,SFAC) CALL STEST(5,COPYY,MWPSTY,MWPSTY,SFAC) 200 CONTINUE RETURN END SUBROUTINE STEST(LEN,SCOMP,STRUE,SSIZE,SFAC) * ********************************* STEST ************************** * * THIS SUBR COMPARES ARRAYS SCOMP() AND STRUE() OF LENGTH LEN TO * SEE IF THE TERM BY TERM DIFFERENCES, MULTIPLIED BY SFAC, ARE * NEGLIGIBLE. * * C. L. LAWSON, JPL, 1974 DEC 10 * * .. Parameters .. INTEGER NOUT REAL ZERO PARAMETER (NOUT=6, ZERO=0.0E0) * .. Scalar Arguments .. REAL SFAC INTEGER LEN * .. Array Arguments .. REAL SCOMP(LEN), SSIZE(LEN), STRUE(LEN) * .. Scalars in Common .. INTEGER ICASE, INCX, INCY, N LOGICAL PASS * .. Local Scalars .. REAL SD INTEGER I * .. External Functions .. REAL SDIFF EXTERNAL SDIFF * .. Intrinsic Functions .. INTRINSIC ABS * .. Common blocks .. COMMON /COMBLA/ICASE, N, INCX, INCY, PASS * .. Executable Statements .. * DO 40 I = 1, LEN SD = SCOMP(I) - STRUE(I) IF (ABS(SFAC*SD) .LE. ABS(SSIZE(I))*EPSILON(ZERO)) + GO TO 40 * * HERE SCOMP(I) IS NOT CLOSE TO STRUE(I). * IF ( .NOT. PASS) GO TO 20 * PRINT FAIL MESSAGE AND HEADER. PASS = .FALSE. WRITE (NOUT,99999) WRITE (NOUT,99998) 20 WRITE (NOUT,99997) ICASE, N, INCX, INCY, I, SCOMP(I), + STRUE(I), SD, SSIZE(I) 40 CONTINUE RETURN * 99999 FORMAT (' FAIL') 99998 FORMAT (/' CASE N INCX INCY I ', + ' COMP(I) TRUE(I) DIFFERENCE', + ' SIZE(I)',/1X) 99997 FORMAT (1X,I4,I3,2I5,I3,2E36.8,2E12.4) END SUBROUTINE STEST1(SCOMP1,STRUE1,SSIZE,SFAC) * ************************* STEST1 ***************************** * * THIS IS AN INTERFACE SUBROUTINE TO ACCOMODATE THE FORTRAN * REQUIREMENT THAT WHEN A DUMMY ARGUMENT IS AN ARRAY, THE * ACTUAL ARGUMENT MUST ALSO BE AN ARRAY OR AN ARRAY ELEMENT. * * C.L. LAWSON, JPL, 1978 DEC 6 * * .. Scalar Arguments .. REAL SCOMP1, SFAC, STRUE1 * .. Array Arguments .. REAL SSIZE(*) * .. Local Arrays .. REAL SCOMP(1), STRUE(1) * .. External Subroutines .. EXTERNAL STEST * .. Executable Statements .. * SCOMP(1) = SCOMP1 STRUE(1) = STRUE1 CALL STEST(1,SCOMP,STRUE,SSIZE,SFAC) * RETURN END REAL FUNCTION SDIFF(SA,SB) * ********************************* SDIFF ************************** * COMPUTES DIFFERENCE OF TWO NUMBERS. C. L. LAWSON, JPL 1974 FEB 15 * * .. Scalar Arguments .. REAL SA, SB * .. Executable Statements .. SDIFF = SA - SB RETURN END SUBROUTINE ITEST1(ICOMP,ITRUE) * ********************************* ITEST1 ************************* * * THIS SUBROUTINE COMPARES THE VARIABLES ICOMP AND ITRUE FOR * EQUALITY. * C. L. LAWSON, JPL, 1974 DEC 10 * * .. Parameters .. INTEGER NOUT PARAMETER (NOUT=6) * .. Scalar Arguments .. INTEGER ICOMP, ITRUE * .. Scalars in Common .. INTEGER ICASE, INCX, INCY, N LOGICAL PASS * .. Local Scalars .. INTEGER ID * .. Common blocks .. COMMON /COMBLA/ICASE, N, INCX, INCY, PASS * .. Executable Statements .. * IF (ICOMP.EQ.ITRUE) GO TO 40 * * HERE ICOMP IS NOT EQUAL TO ITRUE. * IF ( .NOT. PASS) GO TO 20 * PRINT FAIL MESSAGE AND HEADER. PASS = .FALSE. WRITE (NOUT,99999) WRITE (NOUT,99998) 20 ID = ICOMP - ITRUE WRITE (NOUT,99997) ICASE, N, INCX, INCY, ICOMP, ITRUE, ID 40 CONTINUE RETURN * 99999 FORMAT (' FAIL') 99998 FORMAT (/' CASE N INCX INCY ', + ' COMP TRUE DIFFERENCE', + /1X) 99997 FORMAT (1X,I4,I3,2I5,2I36,I12) END blis-0.9.0/blastest/src/fortran/sblat2.f000066400000000000000000003331731422157504600201120ustar00rootroot00000000000000*> \brief \b SBLAT2 * * =========== DOCUMENTATION =========== * * Online html documentation available at * http://www.netlib.org/lapack/explore-html/ * * Definition: * =========== * * PROGRAM SBLAT2 * * *> \par Purpose: * ============= *> *> \verbatim *> *> Test program for the REAL Level 2 Blas. *> *> The program must be driven by a short data file. The first 18 records *> of the file are read using list-directed input, the last 16 records *> are read using the format ( A6, L2 ). An annotated example of a data *> file can be obtained by deleting the first 3 characters from the *> following 34 lines: *> 'sblat2.out' NAME OF SUMMARY OUTPUT FILE *> 6 UNIT NUMBER OF SUMMARY FILE *> 'SBLAT2.SNAP' NAME OF SNAPSHOT OUTPUT FILE *> -1 UNIT NUMBER OF SNAPSHOT FILE (NOT USED IF .LT. 0) *> F LOGICAL FLAG, T TO REWIND SNAPSHOT FILE AFTER EACH RECORD. *> F LOGICAL FLAG, T TO STOP ON FAILURES. *> T LOGICAL FLAG, T TO TEST ERROR EXITS. *> 16.0 THRESHOLD VALUE OF TEST RATIO *> 6 NUMBER OF VALUES OF N *> 0 1 2 3 5 9 VALUES OF N *> 4 NUMBER OF VALUES OF K *> 0 1 2 4 VALUES OF K *> 4 NUMBER OF VALUES OF INCX AND INCY *> 1 2 -1 -2 VALUES OF INCX AND INCY *> 3 NUMBER OF VALUES OF ALPHA *> 0.0 1.0 0.7 VALUES OF ALPHA *> 3 NUMBER OF VALUES OF BETA *> 0.0 1.0 0.9 VALUES OF BETA *> SGEMV T PUT F FOR NO TEST. SAME COLUMNS. *> SGBMV T PUT F FOR NO TEST. SAME COLUMNS. *> SSYMV T PUT F FOR NO TEST. SAME COLUMNS. *> SSBMV T PUT F FOR NO TEST. SAME COLUMNS. *> SSPMV T PUT F FOR NO TEST. SAME COLUMNS. *> STRMV T PUT F FOR NO TEST. SAME COLUMNS. *> STBMV T PUT F FOR NO TEST. SAME COLUMNS. *> STPMV T PUT F FOR NO TEST. SAME COLUMNS. *> STRSV T PUT F FOR NO TEST. SAME COLUMNS. *> STBSV T PUT F FOR NO TEST. SAME COLUMNS. *> STPSV T PUT F FOR NO TEST. SAME COLUMNS. *> SGER T PUT F FOR NO TEST. SAME COLUMNS. *> SSYR T PUT F FOR NO TEST. SAME COLUMNS. *> SSPR T PUT F FOR NO TEST. SAME COLUMNS. *> SSYR2 T PUT F FOR NO TEST. SAME COLUMNS. *> SSPR2 T PUT F FOR NO TEST. SAME COLUMNS. *> *> Further Details *> =============== *> *> See: *> *> Dongarra J. J., Du Croz J. J., Hammarling S. and Hanson R. J.. *> An extended set of Fortran Basic Linear Algebra Subprograms. *> *> Technical Memoranda Nos. 41 (revision 3) and 81, Mathematics *> and Computer Science Division, Argonne National Laboratory, *> 9700 South Cass Avenue, Argonne, Illinois 60439, US. *> *> Or *> *> NAG Technical Reports TR3/87 and TR4/87, Numerical Algorithms *> Group Ltd., NAG Central Office, 256 Banbury Road, Oxford *> OX2 7DE, UK, and Numerical Algorithms Group Inc., 1101 31st *> Street, Suite 100, Downers Grove, Illinois 60515-1263, USA. *> *> *> -- Written on 10-August-1987. *> Richard Hanson, Sandia National Labs. *> Jeremy Du Croz, NAG Central Office. *> *> 10-9-00: Change STATUS='NEW' to 'UNKNOWN' so that the testers *> can be run multiple times without deleting generated *> output files (susan) *> \endverbatim * * Authors: * ======== * *> \author Univ. of Tennessee *> \author Univ. of California Berkeley *> \author Univ. of Colorado Denver *> \author NAG Ltd. * *> \date April 2012 * *> \ingroup single_blas_testing * * ===================================================================== PROGRAM SBLAT2 * * -- Reference BLAS test routine (version 3.4.1) -- * -- Reference BLAS is a software package provided by Univ. of Tennessee, -- * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- * April 2012 * * ===================================================================== * * .. Parameters .. INTEGER NIN PARAMETER ( NIN = 5 ) INTEGER NSUBS PARAMETER ( NSUBS = 16 ) REAL ZERO, ONE PARAMETER ( ZERO = 0.0, ONE = 1.0 ) INTEGER NMAX, INCMAX PARAMETER ( NMAX = 65, INCMAX = 2 ) INTEGER NINMAX, NIDMAX, NKBMAX, NALMAX, NBEMAX PARAMETER ( NINMAX = 7, NIDMAX = 9, NKBMAX = 7, $ NALMAX = 7, NBEMAX = 7 ) * .. Local Scalars .. REAL EPS, ERR, THRESH INTEGER I, ISNUM, J, N, NALF, NBET, NIDIM, NINC, NKB, $ NOUT, NTRA LOGICAL FATAL, LTESTT, REWI, SAME, SFATAL, TRACE, $ TSTERR CHARACTER*1 TRANS CHARACTER*6 SNAMET CHARACTER*32 SNAPS, SUMMRY * .. Local Arrays .. REAL A( NMAX, NMAX ), AA( NMAX*NMAX ), $ ALF( NALMAX ), AS( NMAX*NMAX ), BET( NBEMAX ), $ G( NMAX ), X( NMAX ), XS( NMAX*INCMAX ), $ XX( NMAX*INCMAX ), Y( NMAX ), $ YS( NMAX*INCMAX ), YT( NMAX ), $ YY( NMAX*INCMAX ), Z( 2*NMAX ) INTEGER IDIM( NIDMAX ), INC( NINMAX ), KB( NKBMAX ) LOGICAL LTEST( NSUBS ) CHARACTER*6 SNAMES( NSUBS ) * .. External Functions .. REAL SDIFF LOGICAL LSE EXTERNAL SDIFF, LSE * .. External Subroutines .. EXTERNAL SCHK1, SCHK2, SCHK3, SCHK4, SCHK5, SCHK6, $ SCHKE, SMVCH * .. Intrinsic Functions .. INTRINSIC ABS, MAX, MIN * .. Scalars in Common .. INTEGER INFOT, NOUTC LOGICAL LERR, OK CHARACTER*6 SRNAMT * .. Common blocks .. COMMON /INFOC/INFOT, NOUTC, OK, LERR COMMON /SRNAMC/SRNAMT * .. Data statements .. DATA SNAMES/'SGEMV ', 'SGBMV ', 'SSYMV ', 'SSBMV ', $ 'SSPMV ', 'STRMV ', 'STBMV ', 'STPMV ', $ 'STRSV ', 'STBSV ', 'STPSV ', 'SGER ', $ 'SSYR ', 'SSPR ', 'SSYR2 ', 'SSPR2 '/ * .. Executable Statements .. * * Read name and unit number for summary output file and open file. * READ( NIN, FMT = * )SUMMRY READ( NIN, FMT = * )NOUT OPEN( NOUT, FILE = SUMMRY, STATUS = 'UNKNOWN' ) NOUTC = NOUT * * Read name and unit number for snapshot output file and open file. * READ( NIN, FMT = * )SNAPS READ( NIN, FMT = * )NTRA TRACE = NTRA.GE.0 IF( TRACE )THEN OPEN( NTRA, FILE = SNAPS, STATUS = 'UNKNOWN' ) END IF * Read the flag that directs rewinding of the snapshot file. READ( NIN, FMT = * )REWI REWI = REWI.AND.TRACE * Read the flag that directs stopping on any failure. READ( NIN, FMT = * )SFATAL * Read the flag that indicates whether error exits are to be tested. READ( NIN, FMT = * )TSTERR * Read the threshold value of the test ratio READ( NIN, FMT = * )THRESH * * Read and check the parameter values for the tests. * * Values of N READ( NIN, FMT = * )NIDIM IF( NIDIM.LT.1.OR.NIDIM.GT.NIDMAX )THEN WRITE( NOUT, FMT = 9997 )'N', NIDMAX GO TO 230 END IF READ( NIN, FMT = * )( IDIM( I ), I = 1, NIDIM ) DO 10 I = 1, NIDIM IF( IDIM( I ).LT.0.OR.IDIM( I ).GT.NMAX )THEN WRITE( NOUT, FMT = 9996 )NMAX GO TO 230 END IF 10 CONTINUE * Values of K READ( NIN, FMT = * )NKB IF( NKB.LT.1.OR.NKB.GT.NKBMAX )THEN WRITE( NOUT, FMT = 9997 )'K', NKBMAX GO TO 230 END IF READ( NIN, FMT = * )( KB( I ), I = 1, NKB ) DO 20 I = 1, NKB IF( KB( I ).LT.0 )THEN WRITE( NOUT, FMT = 9995 ) GO TO 230 END IF 20 CONTINUE * Values of INCX and INCY READ( NIN, FMT = * )NINC IF( NINC.LT.1.OR.NINC.GT.NINMAX )THEN WRITE( NOUT, FMT = 9997 )'INCX AND INCY', NINMAX GO TO 230 END IF READ( NIN, FMT = * )( INC( I ), I = 1, NINC ) DO 30 I = 1, NINC IF( INC( I ).EQ.0.OR.ABS( INC( I ) ).GT.INCMAX )THEN WRITE( NOUT, FMT = 9994 )INCMAX GO TO 230 END IF 30 CONTINUE * Values of ALPHA READ( NIN, FMT = * )NALF IF( NALF.LT.1.OR.NALF.GT.NALMAX )THEN WRITE( NOUT, FMT = 9997 )'ALPHA', NALMAX GO TO 230 END IF READ( NIN, FMT = * )( ALF( I ), I = 1, NALF ) * Values of BETA READ( NIN, FMT = * )NBET IF( NBET.LT.1.OR.NBET.GT.NBEMAX )THEN WRITE( NOUT, FMT = 9997 )'BETA', NBEMAX GO TO 230 END IF READ( NIN, FMT = * )( BET( I ), I = 1, NBET ) * * Report values of parameters. * WRITE( NOUT, FMT = 9993 ) WRITE( NOUT, FMT = 9992 )( IDIM( I ), I = 1, NIDIM ) WRITE( NOUT, FMT = 9991 )( KB( I ), I = 1, NKB ) WRITE( NOUT, FMT = 9990 )( INC( I ), I = 1, NINC ) WRITE( NOUT, FMT = 9989 )( ALF( I ), I = 1, NALF ) WRITE( NOUT, FMT = 9988 )( BET( I ), I = 1, NBET ) IF( .NOT.TSTERR )THEN WRITE( NOUT, FMT = * ) WRITE( NOUT, FMT = 9980 ) END IF WRITE( NOUT, FMT = * ) WRITE( NOUT, FMT = 9999 )THRESH WRITE( NOUT, FMT = * ) * * Read names of subroutines and flags which indicate * whether they are to be tested. * DO 40 I = 1, NSUBS LTEST( I ) = .FALSE. 40 CONTINUE 50 READ( NIN, FMT = 9984, END = 80 )SNAMET, LTESTT DO 60 I = 1, NSUBS IF( SNAMET.EQ.SNAMES( I ) ) $ GO TO 70 60 CONTINUE WRITE( NOUT, FMT = 9986 )SNAMET STOP 70 LTEST( I ) = LTESTT GO TO 50 * 80 CONTINUE CLOSE ( NIN ) * * Compute EPS (the machine precision). * EPS = EPSILON(ZERO) WRITE( NOUT, FMT = 9998 )EPS * * Check the reliability of SMVCH using exact data. * N = MIN( 32, NMAX ) DO 120 J = 1, N DO 110 I = 1, N A( I, J ) = MAX( I - J + 1, 0 ) 110 CONTINUE X( J ) = J Y( J ) = ZERO 120 CONTINUE DO 130 J = 1, N YY( J ) = J*( ( J + 1 )*J )/2 - ( ( J + 1 )*J*( J - 1 ) )/3 130 CONTINUE * YY holds the exact result. On exit from SMVCH YT holds * the result computed by SMVCH. TRANS = 'N' CALL SMVCH( TRANS, N, N, ONE, A, NMAX, X, 1, ZERO, Y, 1, YT, G, $ YY, EPS, ERR, FATAL, NOUT, .TRUE. ) SAME = LSE( YY, YT, N ) IF( .NOT.SAME.OR.ERR.NE.ZERO )THEN WRITE( NOUT, FMT = 9985 )TRANS, SAME, ERR STOP END IF TRANS = 'T' CALL SMVCH( TRANS, N, N, ONE, A, NMAX, X, -1, ZERO, Y, -1, YT, G, $ YY, EPS, ERR, FATAL, NOUT, .TRUE. ) SAME = LSE( YY, YT, N ) IF( .NOT.SAME.OR.ERR.NE.ZERO )THEN WRITE( NOUT, FMT = 9985 )TRANS, SAME, ERR STOP END IF * * Test each subroutine in turn. * DO 210 ISNUM = 1, NSUBS WRITE( NOUT, FMT = * ) IF( .NOT.LTEST( ISNUM ) )THEN * Subprogram is not to be tested. WRITE( NOUT, FMT = 9983 )SNAMES( ISNUM ) ELSE SRNAMT = SNAMES( ISNUM ) * Test error exits. IF( TSTERR )THEN CALL SCHKE( ISNUM, SNAMES( ISNUM ), NOUT ) WRITE( NOUT, FMT = * ) END IF * Test computations. INFOT = 0 OK = .TRUE. FATAL = .FALSE. GO TO ( 140, 140, 150, 150, 150, 160, 160, $ 160, 160, 160, 160, 170, 180, 180, $ 190, 190 )ISNUM * Test SGEMV, 01, and SGBMV, 02. 140 CALL SCHK1( SNAMES( ISNUM ), EPS, THRESH, NOUT, NTRA, TRACE, $ REWI, FATAL, NIDIM, IDIM, NKB, KB, NALF, ALF, $ NBET, BET, NINC, INC, NMAX, INCMAX, A, AA, AS, $ X, XX, XS, Y, YY, YS, YT, G ) GO TO 200 * Test SSYMV, 03, SSBMV, 04, and SSPMV, 05. 150 CALL SCHK2( SNAMES( ISNUM ), EPS, THRESH, NOUT, NTRA, TRACE, $ REWI, FATAL, NIDIM, IDIM, NKB, KB, NALF, ALF, $ NBET, BET, NINC, INC, NMAX, INCMAX, A, AA, AS, $ X, XX, XS, Y, YY, YS, YT, G ) GO TO 200 * Test STRMV, 06, STBMV, 07, STPMV, 08, * STRSV, 09, STBSV, 10, and STPSV, 11. 160 CALL SCHK3( SNAMES( ISNUM ), EPS, THRESH, NOUT, NTRA, TRACE, $ REWI, FATAL, NIDIM, IDIM, NKB, KB, NINC, INC, $ NMAX, INCMAX, A, AA, AS, Y, YY, YS, YT, G, Z ) GO TO 200 * Test SGER, 12. 170 CALL SCHK4( SNAMES( ISNUM ), EPS, THRESH, NOUT, NTRA, TRACE, $ REWI, FATAL, NIDIM, IDIM, NALF, ALF, NINC, INC, $ NMAX, INCMAX, A, AA, AS, X, XX, XS, Y, YY, YS, $ YT, G, Z ) GO TO 200 * Test SSYR, 13, and SSPR, 14. 180 CALL SCHK5( SNAMES( ISNUM ), EPS, THRESH, NOUT, NTRA, TRACE, $ REWI, FATAL, NIDIM, IDIM, NALF, ALF, NINC, INC, $ NMAX, INCMAX, A, AA, AS, X, XX, XS, Y, YY, YS, $ YT, G, Z ) GO TO 200 * Test SSYR2, 15, and SSPR2, 16. 190 CALL SCHK6( SNAMES( ISNUM ), EPS, THRESH, NOUT, NTRA, TRACE, $ REWI, FATAL, NIDIM, IDIM, NALF, ALF, NINC, INC, $ NMAX, INCMAX, A, AA, AS, X, XX, XS, Y, YY, YS, $ YT, G, Z ) * 200 IF( FATAL.AND.SFATAL ) $ GO TO 220 END IF 210 CONTINUE WRITE( NOUT, FMT = 9982 ) GO TO 240 * 220 CONTINUE WRITE( NOUT, FMT = 9981 ) GO TO 240 * 230 CONTINUE WRITE( NOUT, FMT = 9987 ) * 240 CONTINUE IF( TRACE ) $ CLOSE ( NTRA ) CLOSE ( NOUT ) STOP * 9999 FORMAT( ' ROUTINES PASS COMPUTATIONAL TESTS IF TEST RATIO IS LES', $ 'S THAN', F8.2 ) 9998 FORMAT( ' RELATIVE MACHINE PRECISION IS TAKEN TO BE', 1P, E9.1 ) 9997 FORMAT( ' NUMBER OF VALUES OF ', A, ' IS LESS THAN 1 OR GREATER ', $ 'THAN ', I2 ) 9996 FORMAT( ' VALUE OF N IS LESS THAN 0 OR GREATER THAN ', I2 ) 9995 FORMAT( ' VALUE OF K IS LESS THAN 0' ) 9994 FORMAT( ' ABSOLUTE VALUE OF INCX OR INCY IS 0 OR GREATER THAN ', $ I2 ) 9993 FORMAT( ' TESTS OF THE REAL LEVEL 2 BLAS', //' THE F', $ 'OLLOWING PARAMETER VALUES WILL BE USED:' ) 9992 FORMAT( ' FOR N ', 9I6 ) 9991 FORMAT( ' FOR K ', 7I6 ) 9990 FORMAT( ' FOR INCX AND INCY ', 7I6 ) 9989 FORMAT( ' FOR ALPHA ', 7F6.1 ) 9988 FORMAT( ' FOR BETA ', 7F6.1 ) 9987 FORMAT( ' AMEND DATA FILE OR INCREASE ARRAY SIZES IN PROGRAM', $ /' ******* TESTS ABANDONED *******' ) 9986 FORMAT( ' SUBPROGRAM NAME ', A6, ' NOT RECOGNIZED', /' ******* T', $ 'ESTS ABANDONED *******' ) 9985 FORMAT( ' ERROR IN SMVCH - IN-LINE DOT PRODUCTS ARE BEING EVALU', $ 'ATED WRONGLY.', /' SMVCH WAS CALLED WITH TRANS = ', A1, $ ' AND RETURNED SAME = ', L1, ' AND ERR = ', F12.3, '.', / $ ' THIS MAY BE DUE TO FAULTS IN THE ARITHMETIC OR THE COMPILER.' $ , /' ******* TESTS ABANDONED *******' ) 9984 FORMAT( A6, L2 ) 9983 FORMAT( 1X, A6, ' WAS NOT TESTED' ) 9982 FORMAT( /' END OF TESTS' ) 9981 FORMAT( /' ******* FATAL ERROR - TESTS ABANDONED *******' ) 9980 FORMAT( ' ERROR-EXITS WILL NOT BE TESTED' ) * * End of SBLAT2. * END SUBROUTINE SCHK1( SNAME, EPS, THRESH, NOUT, NTRA, TRACE, REWI, $ FATAL, NIDIM, IDIM, NKB, KB, NALF, ALF, NBET, $ BET, NINC, INC, NMAX, INCMAX, A, AA, AS, X, XX, $ XS, Y, YY, YS, YT, G ) * * Tests SGEMV and SGBMV. * * Auxiliary routine for test program for Level 2 Blas. * * -- Written on 10-August-1987. * Richard Hanson, Sandia National Labs. * Jeremy Du Croz, NAG Central Office. * * .. Parameters .. REAL ZERO, HALF PARAMETER ( ZERO = 0.0, HALF = 0.5 ) * .. Scalar Arguments .. REAL EPS, THRESH INTEGER INCMAX, NALF, NBET, NIDIM, NINC, NKB, NMAX, $ NOUT, NTRA LOGICAL FATAL, REWI, TRACE CHARACTER*6 SNAME * .. Array Arguments .. REAL A( NMAX, NMAX ), AA( NMAX*NMAX ), ALF( NALF ), $ AS( NMAX*NMAX ), BET( NBET ), G( NMAX ), $ X( NMAX ), XS( NMAX*INCMAX ), $ XX( NMAX*INCMAX ), Y( NMAX ), $ YS( NMAX*INCMAX ), YT( NMAX ), $ YY( NMAX*INCMAX ) INTEGER IDIM( NIDIM ), INC( NINC ), KB( NKB ) * .. Local Scalars .. REAL ALPHA, ALS, BETA, BLS, ERR, ERRMAX, TRANSL INTEGER I, IA, IB, IC, IKU, IM, IN, INCX, INCXS, INCY, $ INCYS, IX, IY, KL, KLS, KU, KUS, LAA, LDA, $ LDAS, LX, LY, M, ML, MS, N, NARGS, NC, ND, NK, $ NL, NS LOGICAL BANDED, FULL, NULL, RESET, SAME, TRAN CHARACTER*1 TRANS, TRANSS CHARACTER*3 ICH * .. Local Arrays .. LOGICAL ISAME( 13 ) * .. External Functions .. LOGICAL LSE, LSERES EXTERNAL LSE, LSERES * .. External Subroutines .. EXTERNAL SGBMV, SGEMV, SMAKE, SMVCH * .. Intrinsic Functions .. INTRINSIC ABS, MAX, MIN * .. Scalars in Common .. INTEGER INFOT, NOUTC LOGICAL LERR, OK * .. Common blocks .. COMMON /INFOC/INFOT, NOUTC, OK, LERR * .. Data statements .. DATA ICH/'NTC'/ * .. Executable Statements .. FULL = SNAME( 3: 3 ).EQ.'E' BANDED = SNAME( 3: 3 ).EQ.'B' * Define the number of arguments. IF( FULL )THEN NARGS = 11 ELSE IF( BANDED )THEN NARGS = 13 END IF * NC = 0 RESET = .TRUE. ERRMAX = ZERO * DO 120 IN = 1, NIDIM N = IDIM( IN ) ND = N/2 + 1 * DO 110 IM = 1, 2 IF( IM.EQ.1 ) $ M = MAX( N - ND, 0 ) IF( IM.EQ.2 ) $ M = MIN( N + ND, NMAX ) * IF( BANDED )THEN NK = NKB ELSE NK = 1 END IF DO 100 IKU = 1, NK IF( BANDED )THEN KU = KB( IKU ) KL = MAX( KU - 1, 0 ) ELSE KU = N - 1 KL = M - 1 END IF * Set LDA to 1 more than minimum value if room. IF( BANDED )THEN LDA = KL + KU + 1 ELSE LDA = M END IF IF( LDA.LT.NMAX ) $ LDA = LDA + 1 * Skip tests if not enough room. IF( LDA.GT.NMAX ) $ GO TO 100 LAA = LDA*N NULL = N.LE.0.OR.M.LE.0 * * Generate the matrix A. * TRANSL = ZERO CALL SMAKE( SNAME( 2: 3 ), ' ', ' ', M, N, A, NMAX, AA, $ LDA, KL, KU, RESET, TRANSL ) * DO 90 IC = 1, 3 TRANS = ICH( IC: IC ) TRAN = TRANS.EQ.'T'.OR.TRANS.EQ.'C' * IF( TRAN )THEN ML = N NL = M ELSE ML = M NL = N END IF * DO 80 IX = 1, NINC INCX = INC( IX ) LX = ABS( INCX )*NL * * Generate the vector X. * TRANSL = HALF CALL SMAKE( 'GE', ' ', ' ', 1, NL, X, 1, XX, $ ABS( INCX ), 0, NL - 1, RESET, TRANSL ) IF( NL.GT.1 )THEN X( NL/2 ) = ZERO XX( 1 + ABS( INCX )*( NL/2 - 1 ) ) = ZERO END IF * DO 70 IY = 1, NINC INCY = INC( IY ) LY = ABS( INCY )*ML * DO 60 IA = 1, NALF ALPHA = ALF( IA ) * DO 50 IB = 1, NBET BETA = BET( IB ) * * Generate the vector Y. * TRANSL = ZERO CALL SMAKE( 'GE', ' ', ' ', 1, ML, Y, 1, $ YY, ABS( INCY ), 0, ML - 1, $ RESET, TRANSL ) * NC = NC + 1 * * Save every datum before calling the * subroutine. * TRANSS = TRANS MS = M NS = N KLS = KL KUS = KU ALS = ALPHA DO 10 I = 1, LAA AS( I ) = AA( I ) 10 CONTINUE LDAS = LDA DO 20 I = 1, LX XS( I ) = XX( I ) 20 CONTINUE INCXS = INCX BLS = BETA DO 30 I = 1, LY YS( I ) = YY( I ) 30 CONTINUE INCYS = INCY * * Call the subroutine. * IF( FULL )THEN IF( TRACE ) $ WRITE( NTRA, FMT = 9994 )NC, SNAME, $ TRANS, M, N, ALPHA, LDA, INCX, BETA, $ INCY IF( REWI ) $ REWIND NTRA CALL SGEMV( TRANS, M, N, ALPHA, AA, $ LDA, XX, INCX, BETA, YY, $ INCY ) ELSE IF( BANDED )THEN IF( TRACE ) $ WRITE( NTRA, FMT = 9995 )NC, SNAME, $ TRANS, M, N, KL, KU, ALPHA, LDA, $ INCX, BETA, INCY IF( REWI ) $ REWIND NTRA CALL SGBMV( TRANS, M, N, KL, KU, ALPHA, $ AA, LDA, XX, INCX, BETA, $ YY, INCY ) END IF * * Check if error-exit was taken incorrectly. * IF( .NOT.OK )THEN WRITE( NOUT, FMT = 9993 ) FATAL = .TRUE. GO TO 130 END IF * * See what data changed inside subroutines. * ISAME( 1 ) = TRANS.EQ.TRANSS ISAME( 2 ) = MS.EQ.M ISAME( 3 ) = NS.EQ.N IF( FULL )THEN ISAME( 4 ) = ALS.EQ.ALPHA ISAME( 5 ) = LSE( AS, AA, LAA ) ISAME( 6 ) = LDAS.EQ.LDA ISAME( 7 ) = LSE( XS, XX, LX ) ISAME( 8 ) = INCXS.EQ.INCX ISAME( 9 ) = BLS.EQ.BETA IF( NULL )THEN ISAME( 10 ) = LSE( YS, YY, LY ) ELSE ISAME( 10 ) = LSERES( 'GE', ' ', 1, $ ML, YS, YY, $ ABS( INCY ) ) END IF ISAME( 11 ) = INCYS.EQ.INCY ELSE IF( BANDED )THEN ISAME( 4 ) = KLS.EQ.KL ISAME( 5 ) = KUS.EQ.KU ISAME( 6 ) = ALS.EQ.ALPHA ISAME( 7 ) = LSE( AS, AA, LAA ) ISAME( 8 ) = LDAS.EQ.LDA ISAME( 9 ) = LSE( XS, XX, LX ) ISAME( 10 ) = INCXS.EQ.INCX ISAME( 11 ) = BLS.EQ.BETA IF( NULL )THEN ISAME( 12 ) = LSE( YS, YY, LY ) ELSE ISAME( 12 ) = LSERES( 'GE', ' ', 1, $ ML, YS, YY, $ ABS( INCY ) ) END IF ISAME( 13 ) = INCYS.EQ.INCY END IF * * If data was incorrectly changed, report * and return. * SAME = .TRUE. DO 40 I = 1, NARGS SAME = SAME.AND.ISAME( I ) IF( .NOT.ISAME( I ) ) $ WRITE( NOUT, FMT = 9998 )I 40 CONTINUE IF( .NOT.SAME )THEN FATAL = .TRUE. GO TO 130 END IF * IF( .NOT.NULL )THEN * * Check the result. * CALL SMVCH( TRANS, M, N, ALPHA, A, $ NMAX, X, INCX, BETA, Y, $ INCY, YT, G, YY, EPS, ERR, $ FATAL, NOUT, .TRUE. ) ERRMAX = MAX( ERRMAX, ERR ) * If got really bad answer, report and * return. IF( FATAL ) $ GO TO 130 ELSE * Avoid repeating tests with M.le.0 or * N.le.0. GO TO 110 END IF * 50 CONTINUE * 60 CONTINUE * 70 CONTINUE * 80 CONTINUE * 90 CONTINUE * 100 CONTINUE * 110 CONTINUE * 120 CONTINUE * * Report result. * IF( ERRMAX.LT.THRESH )THEN WRITE( NOUT, FMT = 9999 )SNAME, NC ELSE WRITE( NOUT, FMT = 9997 )SNAME, NC, ERRMAX END IF GO TO 140 * 130 CONTINUE WRITE( NOUT, FMT = 9996 )SNAME IF( FULL )THEN WRITE( NOUT, FMT = 9994 )NC, SNAME, TRANS, M, N, ALPHA, LDA, $ INCX, BETA, INCY ELSE IF( BANDED )THEN WRITE( NOUT, FMT = 9995 )NC, SNAME, TRANS, M, N, KL, KU, $ ALPHA, LDA, INCX, BETA, INCY END IF * 140 CONTINUE RETURN * 9999 FORMAT( ' ', A6, ' PASSED THE COMPUTATIONAL TESTS (', I6, ' CALL', $ 'S)' ) 9998 FORMAT( ' ******* FATAL ERROR - PARAMETER NUMBER ', I2, ' WAS CH', $ 'ANGED INCORRECTLY *******' ) 9997 FORMAT( ' ', A6, ' COMPLETED THE COMPUTATIONAL TESTS (', I6, ' C', $ 'ALLS)', /' ******* BUT WITH MAXIMUM TEST RATIO', F8.2, $ ' - SUSPECT *******' ) 9996 FORMAT( ' ******* ', A6, ' FAILED ON CALL NUMBER:' ) 9995 FORMAT( 1X, I6, ': ', A6, '(''', A1, ''',', 4( I3, ',' ), F4.1, $ ', A,', I3, ', X,', I2, ',', F4.1, ', Y,', I2, ') .' ) 9994 FORMAT( 1X, I6, ': ', A6, '(''', A1, ''',', 2( I3, ',' ), F4.1, $ ', A,', I3, ', X,', I2, ',', F4.1, ', Y,', I2, $ ') .' ) 9993 FORMAT( ' ******* FATAL ERROR - ERROR-EXIT TAKEN ON VALID CALL *', $ '******' ) * * End of SCHK1. * END SUBROUTINE SCHK2( SNAME, EPS, THRESH, NOUT, NTRA, TRACE, REWI, $ FATAL, NIDIM, IDIM, NKB, KB, NALF, ALF, NBET, $ BET, NINC, INC, NMAX, INCMAX, A, AA, AS, X, XX, $ XS, Y, YY, YS, YT, G ) * * Tests SSYMV, SSBMV and SSPMV. * * Auxiliary routine for test program for Level 2 Blas. * * -- Written on 10-August-1987. * Richard Hanson, Sandia National Labs. * Jeremy Du Croz, NAG Central Office. * * .. Parameters .. REAL ZERO, HALF PARAMETER ( ZERO = 0.0, HALF = 0.5 ) * .. Scalar Arguments .. REAL EPS, THRESH INTEGER INCMAX, NALF, NBET, NIDIM, NINC, NKB, NMAX, $ NOUT, NTRA LOGICAL FATAL, REWI, TRACE CHARACTER*6 SNAME * .. Array Arguments .. REAL A( NMAX, NMAX ), AA( NMAX*NMAX ), ALF( NALF ), $ AS( NMAX*NMAX ), BET( NBET ), G( NMAX ), $ X( NMAX ), XS( NMAX*INCMAX ), $ XX( NMAX*INCMAX ), Y( NMAX ), $ YS( NMAX*INCMAX ), YT( NMAX ), $ YY( NMAX*INCMAX ) INTEGER IDIM( NIDIM ), INC( NINC ), KB( NKB ) * .. Local Scalars .. REAL ALPHA, ALS, BETA, BLS, ERR, ERRMAX, TRANSL INTEGER I, IA, IB, IC, IK, IN, INCX, INCXS, INCY, $ INCYS, IX, IY, K, KS, LAA, LDA, LDAS, LX, LY, $ N, NARGS, NC, NK, NS LOGICAL BANDED, FULL, NULL, PACKED, RESET, SAME CHARACTER*1 UPLO, UPLOS CHARACTER*2 ICH * .. Local Arrays .. LOGICAL ISAME( 13 ) * .. External Functions .. LOGICAL LSE, LSERES EXTERNAL LSE, LSERES * .. External Subroutines .. EXTERNAL SMAKE, SMVCH, SSBMV, SSPMV, SSYMV * .. Intrinsic Functions .. INTRINSIC ABS, MAX * .. Scalars in Common .. INTEGER INFOT, NOUTC LOGICAL LERR, OK * .. Common blocks .. COMMON /INFOC/INFOT, NOUTC, OK, LERR * .. Data statements .. DATA ICH/'UL'/ * .. Executable Statements .. FULL = SNAME( 3: 3 ).EQ.'Y' BANDED = SNAME( 3: 3 ).EQ.'B' PACKED = SNAME( 3: 3 ).EQ.'P' * Define the number of arguments. IF( FULL )THEN NARGS = 10 ELSE IF( BANDED )THEN NARGS = 11 ELSE IF( PACKED )THEN NARGS = 9 END IF * NC = 0 RESET = .TRUE. ERRMAX = ZERO * DO 110 IN = 1, NIDIM N = IDIM( IN ) * IF( BANDED )THEN NK = NKB ELSE NK = 1 END IF DO 100 IK = 1, NK IF( BANDED )THEN K = KB( IK ) ELSE K = N - 1 END IF * Set LDA to 1 more than minimum value if room. IF( BANDED )THEN LDA = K + 1 ELSE LDA = N END IF IF( LDA.LT.NMAX ) $ LDA = LDA + 1 * Skip tests if not enough room. IF( LDA.GT.NMAX ) $ GO TO 100 IF( PACKED )THEN LAA = ( N*( N + 1 ) )/2 ELSE LAA = LDA*N END IF NULL = N.LE.0 * DO 90 IC = 1, 2 UPLO = ICH( IC: IC ) * * Generate the matrix A. * TRANSL = ZERO CALL SMAKE( SNAME( 2: 3 ), UPLO, ' ', N, N, A, NMAX, AA, $ LDA, K, K, RESET, TRANSL ) * DO 80 IX = 1, NINC INCX = INC( IX ) LX = ABS( INCX )*N * * Generate the vector X. * TRANSL = HALF CALL SMAKE( 'GE', ' ', ' ', 1, N, X, 1, XX, $ ABS( INCX ), 0, N - 1, RESET, TRANSL ) IF( N.GT.1 )THEN X( N/2 ) = ZERO XX( 1 + ABS( INCX )*( N/2 - 1 ) ) = ZERO END IF * DO 70 IY = 1, NINC INCY = INC( IY ) LY = ABS( INCY )*N * DO 60 IA = 1, NALF ALPHA = ALF( IA ) * DO 50 IB = 1, NBET BETA = BET( IB ) * * Generate the vector Y. * TRANSL = ZERO CALL SMAKE( 'GE', ' ', ' ', 1, N, Y, 1, YY, $ ABS( INCY ), 0, N - 1, RESET, $ TRANSL ) * NC = NC + 1 * * Save every datum before calling the * subroutine. * UPLOS = UPLO NS = N KS = K ALS = ALPHA DO 10 I = 1, LAA AS( I ) = AA( I ) 10 CONTINUE LDAS = LDA DO 20 I = 1, LX XS( I ) = XX( I ) 20 CONTINUE INCXS = INCX BLS = BETA DO 30 I = 1, LY YS( I ) = YY( I ) 30 CONTINUE INCYS = INCY * * Call the subroutine. * IF( FULL )THEN IF( TRACE ) $ WRITE( NTRA, FMT = 9993 )NC, SNAME, $ UPLO, N, ALPHA, LDA, INCX, BETA, INCY IF( REWI ) $ REWIND NTRA CALL SSYMV( UPLO, N, ALPHA, AA, LDA, XX, $ INCX, BETA, YY, INCY ) ELSE IF( BANDED )THEN IF( TRACE ) $ WRITE( NTRA, FMT = 9994 )NC, SNAME, $ UPLO, N, K, ALPHA, LDA, INCX, BETA, $ INCY IF( REWI ) $ REWIND NTRA CALL SSBMV( UPLO, N, K, ALPHA, AA, LDA, $ XX, INCX, BETA, YY, INCY ) ELSE IF( PACKED )THEN IF( TRACE ) $ WRITE( NTRA, FMT = 9995 )NC, SNAME, $ UPLO, N, ALPHA, INCX, BETA, INCY IF( REWI ) $ REWIND NTRA CALL SSPMV( UPLO, N, ALPHA, AA, XX, INCX, $ BETA, YY, INCY ) END IF * * Check if error-exit was taken incorrectly. * IF( .NOT.OK )THEN WRITE( NOUT, FMT = 9992 ) FATAL = .TRUE. GO TO 120 END IF * * See what data changed inside subroutines. * ISAME( 1 ) = UPLO.EQ.UPLOS ISAME( 2 ) = NS.EQ.N IF( FULL )THEN ISAME( 3 ) = ALS.EQ.ALPHA ISAME( 4 ) = LSE( AS, AA, LAA ) ISAME( 5 ) = LDAS.EQ.LDA ISAME( 6 ) = LSE( XS, XX, LX ) ISAME( 7 ) = INCXS.EQ.INCX ISAME( 8 ) = BLS.EQ.BETA IF( NULL )THEN ISAME( 9 ) = LSE( YS, YY, LY ) ELSE ISAME( 9 ) = LSERES( 'GE', ' ', 1, N, $ YS, YY, ABS( INCY ) ) END IF ISAME( 10 ) = INCYS.EQ.INCY ELSE IF( BANDED )THEN ISAME( 3 ) = KS.EQ.K ISAME( 4 ) = ALS.EQ.ALPHA ISAME( 5 ) = LSE( AS, AA, LAA ) ISAME( 6 ) = LDAS.EQ.LDA ISAME( 7 ) = LSE( XS, XX, LX ) ISAME( 8 ) = INCXS.EQ.INCX ISAME( 9 ) = BLS.EQ.BETA IF( NULL )THEN ISAME( 10 ) = LSE( YS, YY, LY ) ELSE ISAME( 10 ) = LSERES( 'GE', ' ', 1, N, $ YS, YY, ABS( INCY ) ) END IF ISAME( 11 ) = INCYS.EQ.INCY ELSE IF( PACKED )THEN ISAME( 3 ) = ALS.EQ.ALPHA ISAME( 4 ) = LSE( AS, AA, LAA ) ISAME( 5 ) = LSE( XS, XX, LX ) ISAME( 6 ) = INCXS.EQ.INCX ISAME( 7 ) = BLS.EQ.BETA IF( NULL )THEN ISAME( 8 ) = LSE( YS, YY, LY ) ELSE ISAME( 8 ) = LSERES( 'GE', ' ', 1, N, $ YS, YY, ABS( INCY ) ) END IF ISAME( 9 ) = INCYS.EQ.INCY END IF * * If data was incorrectly changed, report and * return. * SAME = .TRUE. DO 40 I = 1, NARGS SAME = SAME.AND.ISAME( I ) IF( .NOT.ISAME( I ) ) $ WRITE( NOUT, FMT = 9998 )I 40 CONTINUE IF( .NOT.SAME )THEN FATAL = .TRUE. GO TO 120 END IF * IF( .NOT.NULL )THEN * * Check the result. * CALL SMVCH( 'N', N, N, ALPHA, A, NMAX, X, $ INCX, BETA, Y, INCY, YT, G, $ YY, EPS, ERR, FATAL, NOUT, $ .TRUE. ) ERRMAX = MAX( ERRMAX, ERR ) * If got really bad answer, report and * return. IF( FATAL ) $ GO TO 120 ELSE * Avoid repeating tests with N.le.0 GO TO 110 END IF * 50 CONTINUE * 60 CONTINUE * 70 CONTINUE * 80 CONTINUE * 90 CONTINUE * 100 CONTINUE * 110 CONTINUE * * Report result. * IF( ERRMAX.LT.THRESH )THEN WRITE( NOUT, FMT = 9999 )SNAME, NC ELSE WRITE( NOUT, FMT = 9997 )SNAME, NC, ERRMAX END IF GO TO 130 * 120 CONTINUE WRITE( NOUT, FMT = 9996 )SNAME IF( FULL )THEN WRITE( NOUT, FMT = 9993 )NC, SNAME, UPLO, N, ALPHA, LDA, INCX, $ BETA, INCY ELSE IF( BANDED )THEN WRITE( NOUT, FMT = 9994 )NC, SNAME, UPLO, N, K, ALPHA, LDA, $ INCX, BETA, INCY ELSE IF( PACKED )THEN WRITE( NOUT, FMT = 9995 )NC, SNAME, UPLO, N, ALPHA, INCX, $ BETA, INCY END IF * 130 CONTINUE RETURN * 9999 FORMAT( ' ', A6, ' PASSED THE COMPUTATIONAL TESTS (', I6, ' CALL', $ 'S)' ) 9998 FORMAT( ' ******* FATAL ERROR - PARAMETER NUMBER ', I2, ' WAS CH', $ 'ANGED INCORRECTLY *******' ) 9997 FORMAT( ' ', A6, ' COMPLETED THE COMPUTATIONAL TESTS (', I6, ' C', $ 'ALLS)', /' ******* BUT WITH MAXIMUM TEST RATIO', F8.2, $ ' - SUSPECT *******' ) 9996 FORMAT( ' ******* ', A6, ' FAILED ON CALL NUMBER:' ) 9995 FORMAT( 1X, I6, ': ', A6, '(''', A1, ''',', I3, ',', F4.1, ', AP', $ ', X,', I2, ',', F4.1, ', Y,', I2, ') .' ) 9994 FORMAT( 1X, I6, ': ', A6, '(''', A1, ''',', 2( I3, ',' ), F4.1, $ ', A,', I3, ', X,', I2, ',', F4.1, ', Y,', I2, $ ') .' ) 9993 FORMAT( 1X, I6, ': ', A6, '(''', A1, ''',', I3, ',', F4.1, ', A,', $ I3, ', X,', I2, ',', F4.1, ', Y,', I2, ') .' ) 9992 FORMAT( ' ******* FATAL ERROR - ERROR-EXIT TAKEN ON VALID CALL *', $ '******' ) * * End of SCHK2. * END SUBROUTINE SCHK3( SNAME, EPS, THRESH, NOUT, NTRA, TRACE, REWI, $ FATAL, NIDIM, IDIM, NKB, KB, NINC, INC, NMAX, $ INCMAX, A, AA, AS, X, XX, XS, XT, G, Z ) * * Tests STRMV, STBMV, STPMV, STRSV, STBSV and STPSV. * * Auxiliary routine for test program for Level 2 Blas. * * -- Written on 10-August-1987. * Richard Hanson, Sandia National Labs. * Jeremy Du Croz, NAG Central Office. * * .. Parameters .. REAL ZERO, HALF, ONE PARAMETER ( ZERO = 0.0, HALF = 0.5, ONE = 1.0 ) * .. Scalar Arguments .. REAL EPS, THRESH INTEGER INCMAX, NIDIM, NINC, NKB, NMAX, NOUT, NTRA LOGICAL FATAL, REWI, TRACE CHARACTER*6 SNAME * .. Array Arguments .. REAL A( NMAX, NMAX ), AA( NMAX*NMAX ), $ AS( NMAX*NMAX ), G( NMAX ), X( NMAX ), $ XS( NMAX*INCMAX ), XT( NMAX ), $ XX( NMAX*INCMAX ), Z( NMAX ) INTEGER IDIM( NIDIM ), INC( NINC ), KB( NKB ) * .. Local Scalars .. REAL ERR, ERRMAX, TRANSL INTEGER I, ICD, ICT, ICU, IK, IN, INCX, INCXS, IX, K, $ KS, LAA, LDA, LDAS, LX, N, NARGS, NC, NK, NS LOGICAL BANDED, FULL, NULL, PACKED, RESET, SAME CHARACTER*1 DIAG, DIAGS, TRANS, TRANSS, UPLO, UPLOS CHARACTER*2 ICHD, ICHU CHARACTER*3 ICHT * .. Local Arrays .. LOGICAL ISAME( 13 ) * .. External Functions .. LOGICAL LSE, LSERES EXTERNAL LSE, LSERES * .. External Subroutines .. EXTERNAL SMAKE, SMVCH, STBMV, STBSV, STPMV, STPSV, $ STRMV, STRSV * .. Intrinsic Functions .. INTRINSIC ABS, MAX * .. Scalars in Common .. INTEGER INFOT, NOUTC LOGICAL LERR, OK * .. Common blocks .. COMMON /INFOC/INFOT, NOUTC, OK, LERR * .. Data statements .. DATA ICHU/'UL'/, ICHT/'NTC'/, ICHD/'UN'/ * .. Executable Statements .. FULL = SNAME( 3: 3 ).EQ.'R' BANDED = SNAME( 3: 3 ).EQ.'B' PACKED = SNAME( 3: 3 ).EQ.'P' * Define the number of arguments. IF( FULL )THEN NARGS = 8 ELSE IF( BANDED )THEN NARGS = 9 ELSE IF( PACKED )THEN NARGS = 7 END IF * NC = 0 RESET = .TRUE. ERRMAX = ZERO * Set up zero vector for SMVCH. DO 10 I = 1, NMAX Z( I ) = ZERO 10 CONTINUE * DO 110 IN = 1, NIDIM N = IDIM( IN ) * IF( BANDED )THEN NK = NKB ELSE NK = 1 END IF DO 100 IK = 1, NK IF( BANDED )THEN K = KB( IK ) ELSE K = N - 1 END IF * Set LDA to 1 more than minimum value if room. IF( BANDED )THEN LDA = K + 1 ELSE LDA = N END IF IF( LDA.LT.NMAX ) $ LDA = LDA + 1 * Skip tests if not enough room. IF( LDA.GT.NMAX ) $ GO TO 100 IF( PACKED )THEN LAA = ( N*( N + 1 ) )/2 ELSE LAA = LDA*N END IF NULL = N.LE.0 * DO 90 ICU = 1, 2 UPLO = ICHU( ICU: ICU ) * DO 80 ICT = 1, 3 TRANS = ICHT( ICT: ICT ) * DO 70 ICD = 1, 2 DIAG = ICHD( ICD: ICD ) * * Generate the matrix A. * TRANSL = ZERO CALL SMAKE( SNAME( 2: 3 ), UPLO, DIAG, N, N, A, $ NMAX, AA, LDA, K, K, RESET, TRANSL ) * DO 60 IX = 1, NINC INCX = INC( IX ) LX = ABS( INCX )*N * * Generate the vector X. * TRANSL = HALF CALL SMAKE( 'GE', ' ', ' ', 1, N, X, 1, XX, $ ABS( INCX ), 0, N - 1, RESET, $ TRANSL ) IF( N.GT.1 )THEN X( N/2 ) = ZERO XX( 1 + ABS( INCX )*( N/2 - 1 ) ) = ZERO END IF * NC = NC + 1 * * Save every datum before calling the subroutine. * UPLOS = UPLO TRANSS = TRANS DIAGS = DIAG NS = N KS = K DO 20 I = 1, LAA AS( I ) = AA( I ) 20 CONTINUE LDAS = LDA DO 30 I = 1, LX XS( I ) = XX( I ) 30 CONTINUE INCXS = INCX * * Call the subroutine. * IF( SNAME( 4: 5 ).EQ.'MV' )THEN IF( FULL )THEN IF( TRACE ) $ WRITE( NTRA, FMT = 9993 )NC, SNAME, $ UPLO, TRANS, DIAG, N, LDA, INCX IF( REWI ) $ REWIND NTRA CALL STRMV( UPLO, TRANS, DIAG, N, AA, LDA, $ XX, INCX ) ELSE IF( BANDED )THEN IF( TRACE ) $ WRITE( NTRA, FMT = 9994 )NC, SNAME, $ UPLO, TRANS, DIAG, N, K, LDA, INCX IF( REWI ) $ REWIND NTRA CALL STBMV( UPLO, TRANS, DIAG, N, K, AA, $ LDA, XX, INCX ) ELSE IF( PACKED )THEN IF( TRACE ) $ WRITE( NTRA, FMT = 9995 )NC, SNAME, $ UPLO, TRANS, DIAG, N, INCX IF( REWI ) $ REWIND NTRA CALL STPMV( UPLO, TRANS, DIAG, N, AA, XX, $ INCX ) END IF ELSE IF( SNAME( 4: 5 ).EQ.'SV' )THEN IF( FULL )THEN IF( TRACE ) $ WRITE( NTRA, FMT = 9993 )NC, SNAME, $ UPLO, TRANS, DIAG, N, LDA, INCX IF( REWI ) $ REWIND NTRA CALL STRSV( UPLO, TRANS, DIAG, N, AA, LDA, $ XX, INCX ) ELSE IF( BANDED )THEN IF( TRACE ) $ WRITE( NTRA, FMT = 9994 )NC, SNAME, $ UPLO, TRANS, DIAG, N, K, LDA, INCX IF( REWI ) $ REWIND NTRA CALL STBSV( UPLO, TRANS, DIAG, N, K, AA, $ LDA, XX, INCX ) ELSE IF( PACKED )THEN IF( TRACE ) $ WRITE( NTRA, FMT = 9995 )NC, SNAME, $ UPLO, TRANS, DIAG, N, INCX IF( REWI ) $ REWIND NTRA CALL STPSV( UPLO, TRANS, DIAG, N, AA, XX, $ INCX ) END IF END IF * * Check if error-exit was taken incorrectly. * IF( .NOT.OK )THEN WRITE( NOUT, FMT = 9992 ) FATAL = .TRUE. GO TO 120 END IF * * See what data changed inside subroutines. * ISAME( 1 ) = UPLO.EQ.UPLOS ISAME( 2 ) = TRANS.EQ.TRANSS ISAME( 3 ) = DIAG.EQ.DIAGS ISAME( 4 ) = NS.EQ.N IF( FULL )THEN ISAME( 5 ) = LSE( AS, AA, LAA ) ISAME( 6 ) = LDAS.EQ.LDA IF( NULL )THEN ISAME( 7 ) = LSE( XS, XX, LX ) ELSE ISAME( 7 ) = LSERES( 'GE', ' ', 1, N, XS, $ XX, ABS( INCX ) ) END IF ISAME( 8 ) = INCXS.EQ.INCX ELSE IF( BANDED )THEN ISAME( 5 ) = KS.EQ.K ISAME( 6 ) = LSE( AS, AA, LAA ) ISAME( 7 ) = LDAS.EQ.LDA IF( NULL )THEN ISAME( 8 ) = LSE( XS, XX, LX ) ELSE ISAME( 8 ) = LSERES( 'GE', ' ', 1, N, XS, $ XX, ABS( INCX ) ) END IF ISAME( 9 ) = INCXS.EQ.INCX ELSE IF( PACKED )THEN ISAME( 5 ) = LSE( AS, AA, LAA ) IF( NULL )THEN ISAME( 6 ) = LSE( XS, XX, LX ) ELSE ISAME( 6 ) = LSERES( 'GE', ' ', 1, N, XS, $ XX, ABS( INCX ) ) END IF ISAME( 7 ) = INCXS.EQ.INCX END IF * * If data was incorrectly changed, report and * return. * SAME = .TRUE. DO 40 I = 1, NARGS SAME = SAME.AND.ISAME( I ) IF( .NOT.ISAME( I ) ) $ WRITE( NOUT, FMT = 9998 )I 40 CONTINUE IF( .NOT.SAME )THEN FATAL = .TRUE. GO TO 120 END IF * IF( .NOT.NULL )THEN IF( SNAME( 4: 5 ).EQ.'MV' )THEN * * Check the result. * CALL SMVCH( TRANS, N, N, ONE, A, NMAX, X, $ INCX, ZERO, Z, INCX, XT, G, $ XX, EPS, ERR, FATAL, NOUT, $ .TRUE. ) ELSE IF( SNAME( 4: 5 ).EQ.'SV' )THEN * * Compute approximation to original vector. * DO 50 I = 1, N Z( I ) = XX( 1 + ( I - 1 )* $ ABS( INCX ) ) XX( 1 + ( I - 1 )*ABS( INCX ) ) $ = X( I ) 50 CONTINUE CALL SMVCH( TRANS, N, N, ONE, A, NMAX, Z, $ INCX, ZERO, X, INCX, XT, G, $ XX, EPS, ERR, FATAL, NOUT, $ .FALSE. ) END IF ERRMAX = MAX( ERRMAX, ERR ) * If got really bad answer, report and return. IF( FATAL ) $ GO TO 120 ELSE * Avoid repeating tests with N.le.0. GO TO 110 END IF * 60 CONTINUE * 70 CONTINUE * 80 CONTINUE * 90 CONTINUE * 100 CONTINUE * 110 CONTINUE * * Report result. * IF( ERRMAX.LT.THRESH )THEN WRITE( NOUT, FMT = 9999 )SNAME, NC ELSE WRITE( NOUT, FMT = 9997 )SNAME, NC, ERRMAX END IF GO TO 130 * 120 CONTINUE WRITE( NOUT, FMT = 9996 )SNAME IF( FULL )THEN WRITE( NOUT, FMT = 9993 )NC, SNAME, UPLO, TRANS, DIAG, N, LDA, $ INCX ELSE IF( BANDED )THEN WRITE( NOUT, FMT = 9994 )NC, SNAME, UPLO, TRANS, DIAG, N, K, $ LDA, INCX ELSE IF( PACKED )THEN WRITE( NOUT, FMT = 9995 )NC, SNAME, UPLO, TRANS, DIAG, N, INCX END IF * 130 CONTINUE RETURN * 9999 FORMAT( ' ', A6, ' PASSED THE COMPUTATIONAL TESTS (', I6, ' CALL', $ 'S)' ) 9998 FORMAT( ' ******* FATAL ERROR - PARAMETER NUMBER ', I2, ' WAS CH', $ 'ANGED INCORRECTLY *******' ) 9997 FORMAT( ' ', A6, ' COMPLETED THE COMPUTATIONAL TESTS (', I6, ' C', $ 'ALLS)', /' ******* BUT WITH MAXIMUM TEST RATIO', F8.2, $ ' - SUSPECT *******' ) 9996 FORMAT( ' ******* ', A6, ' FAILED ON CALL NUMBER:' ) 9995 FORMAT( 1X, I6, ': ', A6, '(', 3( '''', A1, ''',' ), I3, ', AP, ', $ 'X,', I2, ') .' ) 9994 FORMAT( 1X, I6, ': ', A6, '(', 3( '''', A1, ''',' ), 2( I3, ',' ), $ ' A,', I3, ', X,', I2, ') .' ) 9993 FORMAT( 1X, I6, ': ', A6, '(', 3( '''', A1, ''',' ), I3, ', A,', $ I3, ', X,', I2, ') .' ) 9992 FORMAT( ' ******* FATAL ERROR - ERROR-EXIT TAKEN ON VALID CALL *', $ '******' ) * * End of SCHK3. * END SUBROUTINE SCHK4( SNAME, EPS, THRESH, NOUT, NTRA, TRACE, REWI, $ FATAL, NIDIM, IDIM, NALF, ALF, NINC, INC, NMAX, $ INCMAX, A, AA, AS, X, XX, XS, Y, YY, YS, YT, G, $ Z ) * * Tests SGER. * * Auxiliary routine for test program for Level 2 Blas. * * -- Written on 10-August-1987. * Richard Hanson, Sandia National Labs. * Jeremy Du Croz, NAG Central Office. * * .. Parameters .. REAL ZERO, HALF, ONE PARAMETER ( ZERO = 0.0, HALF = 0.5, ONE = 1.0 ) * .. Scalar Arguments .. REAL EPS, THRESH INTEGER INCMAX, NALF, NIDIM, NINC, NMAX, NOUT, NTRA LOGICAL FATAL, REWI, TRACE CHARACTER*6 SNAME * .. Array Arguments .. REAL A( NMAX, NMAX ), AA( NMAX*NMAX ), ALF( NALF ), $ AS( NMAX*NMAX ), G( NMAX ), X( NMAX ), $ XS( NMAX*INCMAX ), XX( NMAX*INCMAX ), $ Y( NMAX ), YS( NMAX*INCMAX ), YT( NMAX ), $ YY( NMAX*INCMAX ), Z( NMAX ) INTEGER IDIM( NIDIM ), INC( NINC ) * .. Local Scalars .. REAL ALPHA, ALS, ERR, ERRMAX, TRANSL INTEGER I, IA, IM, IN, INCX, INCXS, INCY, INCYS, IX, $ IY, J, LAA, LDA, LDAS, LX, LY, M, MS, N, NARGS, $ NC, ND, NS LOGICAL NULL, RESET, SAME * .. Local Arrays .. REAL W( 1 ) LOGICAL ISAME( 13 ) * .. External Functions .. LOGICAL LSE, LSERES EXTERNAL LSE, LSERES * .. External Subroutines .. EXTERNAL SGER, SMAKE, SMVCH * .. Intrinsic Functions .. INTRINSIC ABS, MAX, MIN * .. Scalars in Common .. INTEGER INFOT, NOUTC LOGICAL LERR, OK * .. Common blocks .. COMMON /INFOC/INFOT, NOUTC, OK, LERR * .. Executable Statements .. * Define the number of arguments. NARGS = 9 * NC = 0 RESET = .TRUE. ERRMAX = ZERO * DO 120 IN = 1, NIDIM N = IDIM( IN ) ND = N/2 + 1 * DO 110 IM = 1, 2 IF( IM.EQ.1 ) $ M = MAX( N - ND, 0 ) IF( IM.EQ.2 ) $ M = MIN( N + ND, NMAX ) * * Set LDA to 1 more than minimum value if room. LDA = M IF( LDA.LT.NMAX ) $ LDA = LDA + 1 * Skip tests if not enough room. IF( LDA.GT.NMAX ) $ GO TO 110 LAA = LDA*N NULL = N.LE.0.OR.M.LE.0 * DO 100 IX = 1, NINC INCX = INC( IX ) LX = ABS( INCX )*M * * Generate the vector X. * TRANSL = HALF CALL SMAKE( 'GE', ' ', ' ', 1, M, X, 1, XX, ABS( INCX ), $ 0, M - 1, RESET, TRANSL ) IF( M.GT.1 )THEN X( M/2 ) = ZERO XX( 1 + ABS( INCX )*( M/2 - 1 ) ) = ZERO END IF * DO 90 IY = 1, NINC INCY = INC( IY ) LY = ABS( INCY )*N * * Generate the vector Y. * TRANSL = ZERO CALL SMAKE( 'GE', ' ', ' ', 1, N, Y, 1, YY, $ ABS( INCY ), 0, N - 1, RESET, TRANSL ) IF( N.GT.1 )THEN Y( N/2 ) = ZERO YY( 1 + ABS( INCY )*( N/2 - 1 ) ) = ZERO END IF * DO 80 IA = 1, NALF ALPHA = ALF( IA ) * * Generate the matrix A. * TRANSL = ZERO CALL SMAKE( SNAME( 2: 3 ), ' ', ' ', M, N, A, NMAX, $ AA, LDA, M - 1, N - 1, RESET, TRANSL ) * NC = NC + 1 * * Save every datum before calling the subroutine. * MS = M NS = N ALS = ALPHA DO 10 I = 1, LAA AS( I ) = AA( I ) 10 CONTINUE LDAS = LDA DO 20 I = 1, LX XS( I ) = XX( I ) 20 CONTINUE INCXS = INCX DO 30 I = 1, LY YS( I ) = YY( I ) 30 CONTINUE INCYS = INCY * * Call the subroutine. * IF( TRACE ) $ WRITE( NTRA, FMT = 9994 )NC, SNAME, M, N, $ ALPHA, INCX, INCY, LDA IF( REWI ) $ REWIND NTRA CALL SGER( M, N, ALPHA, XX, INCX, YY, INCY, AA, $ LDA ) * * Check if error-exit was taken incorrectly. * IF( .NOT.OK )THEN WRITE( NOUT, FMT = 9993 ) FATAL = .TRUE. GO TO 140 END IF * * See what data changed inside subroutine. * ISAME( 1 ) = MS.EQ.M ISAME( 2 ) = NS.EQ.N ISAME( 3 ) = ALS.EQ.ALPHA ISAME( 4 ) = LSE( XS, XX, LX ) ISAME( 5 ) = INCXS.EQ.INCX ISAME( 6 ) = LSE( YS, YY, LY ) ISAME( 7 ) = INCYS.EQ.INCY IF( NULL )THEN ISAME( 8 ) = LSE( AS, AA, LAA ) ELSE ISAME( 8 ) = LSERES( 'GE', ' ', M, N, AS, AA, $ LDA ) END IF ISAME( 9 ) = LDAS.EQ.LDA * * If data was incorrectly changed, report and return. * SAME = .TRUE. DO 40 I = 1, NARGS SAME = SAME.AND.ISAME( I ) IF( .NOT.ISAME( I ) ) $ WRITE( NOUT, FMT = 9998 )I 40 CONTINUE IF( .NOT.SAME )THEN FATAL = .TRUE. GO TO 140 END IF * IF( .NOT.NULL )THEN * * Check the result column by column. * IF( INCX.GT.0 )THEN DO 50 I = 1, M Z( I ) = X( I ) 50 CONTINUE ELSE DO 60 I = 1, M Z( I ) = X( M - I + 1 ) 60 CONTINUE END IF DO 70 J = 1, N IF( INCY.GT.0 )THEN W( 1 ) = Y( J ) ELSE W( 1 ) = Y( N - J + 1 ) END IF CALL SMVCH( 'N', M, 1, ALPHA, Z, NMAX, W, 1, $ ONE, A( 1, J ), 1, YT, G, $ AA( 1 + ( J - 1 )*LDA ), EPS, $ ERR, FATAL, NOUT, .TRUE. ) ERRMAX = MAX( ERRMAX, ERR ) * If got really bad answer, report and return. IF( FATAL ) $ GO TO 130 70 CONTINUE ELSE * Avoid repeating tests with M.le.0 or N.le.0. GO TO 110 END IF * 80 CONTINUE * 90 CONTINUE * 100 CONTINUE * 110 CONTINUE * 120 CONTINUE * * Report result. * IF( ERRMAX.LT.THRESH )THEN WRITE( NOUT, FMT = 9999 )SNAME, NC ELSE WRITE( NOUT, FMT = 9997 )SNAME, NC, ERRMAX END IF GO TO 150 * 130 CONTINUE WRITE( NOUT, FMT = 9995 )J * 140 CONTINUE WRITE( NOUT, FMT = 9996 )SNAME WRITE( NOUT, FMT = 9994 )NC, SNAME, M, N, ALPHA, INCX, INCY, LDA * 150 CONTINUE RETURN * 9999 FORMAT( ' ', A6, ' PASSED THE COMPUTATIONAL TESTS (', I6, ' CALL', $ 'S)' ) 9998 FORMAT( ' ******* FATAL ERROR - PARAMETER NUMBER ', I2, ' WAS CH', $ 'ANGED INCORRECTLY *******' ) 9997 FORMAT( ' ', A6, ' COMPLETED THE COMPUTATIONAL TESTS (', I6, ' C', $ 'ALLS)', /' ******* BUT WITH MAXIMUM TEST RATIO', F8.2, $ ' - SUSPECT *******' ) 9996 FORMAT( ' ******* ', A6, ' FAILED ON CALL NUMBER:' ) 9995 FORMAT( ' THESE ARE THE RESULTS FOR COLUMN ', I3 ) 9994 FORMAT( 1X, I6, ': ', A6, '(', 2( I3, ',' ), F4.1, ', X,', I2, $ ', Y,', I2, ', A,', I3, ') .' ) 9993 FORMAT( ' ******* FATAL ERROR - ERROR-EXIT TAKEN ON VALID CALL *', $ '******' ) * * End of SCHK4. * END SUBROUTINE SCHK5( SNAME, EPS, THRESH, NOUT, NTRA, TRACE, REWI, $ FATAL, NIDIM, IDIM, NALF, ALF, NINC, INC, NMAX, $ INCMAX, A, AA, AS, X, XX, XS, Y, YY, YS, YT, G, $ Z ) * * Tests SSYR and SSPR. * * Auxiliary routine for test program for Level 2 Blas. * * -- Written on 10-August-1987. * Richard Hanson, Sandia National Labs. * Jeremy Du Croz, NAG Central Office. * * .. Parameters .. REAL ZERO, HALF, ONE PARAMETER ( ZERO = 0.0, HALF = 0.5, ONE = 1.0 ) * .. Scalar Arguments .. REAL EPS, THRESH INTEGER INCMAX, NALF, NIDIM, NINC, NMAX, NOUT, NTRA LOGICAL FATAL, REWI, TRACE CHARACTER*6 SNAME * .. Array Arguments .. REAL A( NMAX, NMAX ), AA( NMAX*NMAX ), ALF( NALF ), $ AS( NMAX*NMAX ), G( NMAX ), X( NMAX ), $ XS( NMAX*INCMAX ), XX( NMAX*INCMAX ), $ Y( NMAX ), YS( NMAX*INCMAX ), YT( NMAX ), $ YY( NMAX*INCMAX ), Z( NMAX ) INTEGER IDIM( NIDIM ), INC( NINC ) * .. Local Scalars .. REAL ALPHA, ALS, ERR, ERRMAX, TRANSL INTEGER I, IA, IC, IN, INCX, INCXS, IX, J, JA, JJ, LAA, $ LDA, LDAS, LJ, LX, N, NARGS, NC, NS LOGICAL FULL, NULL, PACKED, RESET, SAME, UPPER CHARACTER*1 UPLO, UPLOS CHARACTER*2 ICH * .. Local Arrays .. REAL W( 1 ) LOGICAL ISAME( 13 ) * .. External Functions .. LOGICAL LSE, LSERES EXTERNAL LSE, LSERES * .. External Subroutines .. EXTERNAL SMAKE, SMVCH, SSPR, SSYR * .. Intrinsic Functions .. INTRINSIC ABS, MAX * .. Scalars in Common .. INTEGER INFOT, NOUTC LOGICAL LERR, OK * .. Common blocks .. COMMON /INFOC/INFOT, NOUTC, OK, LERR * .. Data statements .. DATA ICH/'UL'/ * .. Executable Statements .. FULL = SNAME( 3: 3 ).EQ.'Y' PACKED = SNAME( 3: 3 ).EQ.'P' * Define the number of arguments. IF( FULL )THEN NARGS = 7 ELSE IF( PACKED )THEN NARGS = 6 END IF * NC = 0 RESET = .TRUE. ERRMAX = ZERO * DO 100 IN = 1, NIDIM N = IDIM( IN ) * Set LDA to 1 more than minimum value if room. LDA = N IF( LDA.LT.NMAX ) $ LDA = LDA + 1 * Skip tests if not enough room. IF( LDA.GT.NMAX ) $ GO TO 100 IF( PACKED )THEN LAA = ( N*( N + 1 ) )/2 ELSE LAA = LDA*N END IF * DO 90 IC = 1, 2 UPLO = ICH( IC: IC ) UPPER = UPLO.EQ.'U' * DO 80 IX = 1, NINC INCX = INC( IX ) LX = ABS( INCX )*N * * Generate the vector X. * TRANSL = HALF CALL SMAKE( 'GE', ' ', ' ', 1, N, X, 1, XX, ABS( INCX ), $ 0, N - 1, RESET, TRANSL ) IF( N.GT.1 )THEN X( N/2 ) = ZERO XX( 1 + ABS( INCX )*( N/2 - 1 ) ) = ZERO END IF * DO 70 IA = 1, NALF ALPHA = ALF( IA ) NULL = N.LE.0.OR.ALPHA.EQ.ZERO * * Generate the matrix A. * TRANSL = ZERO CALL SMAKE( SNAME( 2: 3 ), UPLO, ' ', N, N, A, NMAX, $ AA, LDA, N - 1, N - 1, RESET, TRANSL ) * NC = NC + 1 * * Save every datum before calling the subroutine. * UPLOS = UPLO NS = N ALS = ALPHA DO 10 I = 1, LAA AS( I ) = AA( I ) 10 CONTINUE LDAS = LDA DO 20 I = 1, LX XS( I ) = XX( I ) 20 CONTINUE INCXS = INCX * * Call the subroutine. * IF( FULL )THEN IF( TRACE ) $ WRITE( NTRA, FMT = 9993 )NC, SNAME, UPLO, N, $ ALPHA, INCX, LDA IF( REWI ) $ REWIND NTRA CALL SSYR( UPLO, N, ALPHA, XX, INCX, AA, LDA ) ELSE IF( PACKED )THEN IF( TRACE ) $ WRITE( NTRA, FMT = 9994 )NC, SNAME, UPLO, N, $ ALPHA, INCX IF( REWI ) $ REWIND NTRA CALL SSPR( UPLO, N, ALPHA, XX, INCX, AA ) END IF * * Check if error-exit was taken incorrectly. * IF( .NOT.OK )THEN WRITE( NOUT, FMT = 9992 ) FATAL = .TRUE. GO TO 120 END IF * * See what data changed inside subroutines. * ISAME( 1 ) = UPLO.EQ.UPLOS ISAME( 2 ) = NS.EQ.N ISAME( 3 ) = ALS.EQ.ALPHA ISAME( 4 ) = LSE( XS, XX, LX ) ISAME( 5 ) = INCXS.EQ.INCX IF( NULL )THEN ISAME( 6 ) = LSE( AS, AA, LAA ) ELSE ISAME( 6 ) = LSERES( SNAME( 2: 3 ), UPLO, N, N, AS, $ AA, LDA ) END IF IF( .NOT.PACKED )THEN ISAME( 7 ) = LDAS.EQ.LDA END IF * * If data was incorrectly changed, report and return. * SAME = .TRUE. DO 30 I = 1, NARGS SAME = SAME.AND.ISAME( I ) IF( .NOT.ISAME( I ) ) $ WRITE( NOUT, FMT = 9998 )I 30 CONTINUE IF( .NOT.SAME )THEN FATAL = .TRUE. GO TO 120 END IF * IF( .NOT.NULL )THEN * * Check the result column by column. * IF( INCX.GT.0 )THEN DO 40 I = 1, N Z( I ) = X( I ) 40 CONTINUE ELSE DO 50 I = 1, N Z( I ) = X( N - I + 1 ) 50 CONTINUE END IF JA = 1 DO 60 J = 1, N W( 1 ) = Z( J ) IF( UPPER )THEN JJ = 1 LJ = J ELSE JJ = J LJ = N - J + 1 END IF CALL SMVCH( 'N', LJ, 1, ALPHA, Z( JJ ), LJ, W, $ 1, ONE, A( JJ, J ), 1, YT, G, $ AA( JA ), EPS, ERR, FATAL, NOUT, $ .TRUE. ) IF( FULL )THEN IF( UPPER )THEN JA = JA + LDA ELSE JA = JA + LDA + 1 END IF ELSE JA = JA + LJ END IF ERRMAX = MAX( ERRMAX, ERR ) * If got really bad answer, report and return. IF( FATAL ) $ GO TO 110 60 CONTINUE ELSE * Avoid repeating tests if N.le.0. IF( N.LE.0 ) $ GO TO 100 END IF * 70 CONTINUE * 80 CONTINUE * 90 CONTINUE * 100 CONTINUE * * Report result. * IF( ERRMAX.LT.THRESH )THEN WRITE( NOUT, FMT = 9999 )SNAME, NC ELSE WRITE( NOUT, FMT = 9997 )SNAME, NC, ERRMAX END IF GO TO 130 * 110 CONTINUE WRITE( NOUT, FMT = 9995 )J * 120 CONTINUE WRITE( NOUT, FMT = 9996 )SNAME IF( FULL )THEN WRITE( NOUT, FMT = 9993 )NC, SNAME, UPLO, N, ALPHA, INCX, LDA ELSE IF( PACKED )THEN WRITE( NOUT, FMT = 9994 )NC, SNAME, UPLO, N, ALPHA, INCX END IF * 130 CONTINUE RETURN * 9999 FORMAT( ' ', A6, ' PASSED THE COMPUTATIONAL TESTS (', I6, ' CALL', $ 'S)' ) 9998 FORMAT( ' ******* FATAL ERROR - PARAMETER NUMBER ', I2, ' WAS CH', $ 'ANGED INCORRECTLY *******' ) 9997 FORMAT( ' ', A6, ' COMPLETED THE COMPUTATIONAL TESTS (', I6, ' C', $ 'ALLS)', /' ******* BUT WITH MAXIMUM TEST RATIO', F8.2, $ ' - SUSPECT *******' ) 9996 FORMAT( ' ******* ', A6, ' FAILED ON CALL NUMBER:' ) 9995 FORMAT( ' THESE ARE THE RESULTS FOR COLUMN ', I3 ) 9994 FORMAT( 1X, I6, ': ', A6, '(''', A1, ''',', I3, ',', F4.1, ', X,', $ I2, ', AP) .' ) 9993 FORMAT( 1X, I6, ': ', A6, '(''', A1, ''',', I3, ',', F4.1, ', X,', $ I2, ', A,', I3, ') .' ) 9992 FORMAT( ' ******* FATAL ERROR - ERROR-EXIT TAKEN ON VALID CALL *', $ '******' ) * * End of SCHK5. * END SUBROUTINE SCHK6( SNAME, EPS, THRESH, NOUT, NTRA, TRACE, REWI, $ FATAL, NIDIM, IDIM, NALF, ALF, NINC, INC, NMAX, $ INCMAX, A, AA, AS, X, XX, XS, Y, YY, YS, YT, G, $ Z ) * * Tests SSYR2 and SSPR2. * * Auxiliary routine for test program for Level 2 Blas. * * -- Written on 10-August-1987. * Richard Hanson, Sandia National Labs. * Jeremy Du Croz, NAG Central Office. * * .. Parameters .. REAL ZERO, HALF, ONE PARAMETER ( ZERO = 0.0, HALF = 0.5, ONE = 1.0 ) * .. Scalar Arguments .. REAL EPS, THRESH INTEGER INCMAX, NALF, NIDIM, NINC, NMAX, NOUT, NTRA LOGICAL FATAL, REWI, TRACE CHARACTER*6 SNAME * .. Array Arguments .. REAL A( NMAX, NMAX ), AA( NMAX*NMAX ), ALF( NALF ), $ AS( NMAX*NMAX ), G( NMAX ), X( NMAX ), $ XS( NMAX*INCMAX ), XX( NMAX*INCMAX ), $ Y( NMAX ), YS( NMAX*INCMAX ), YT( NMAX ), $ YY( NMAX*INCMAX ), Z( NMAX, 2 ) INTEGER IDIM( NIDIM ), INC( NINC ) * .. Local Scalars .. REAL ALPHA, ALS, ERR, ERRMAX, TRANSL INTEGER I, IA, IC, IN, INCX, INCXS, INCY, INCYS, IX, $ IY, J, JA, JJ, LAA, LDA, LDAS, LJ, LX, LY, N, $ NARGS, NC, NS LOGICAL FULL, NULL, PACKED, RESET, SAME, UPPER CHARACTER*1 UPLO, UPLOS CHARACTER*2 ICH * .. Local Arrays .. REAL W( 2 ) LOGICAL ISAME( 13 ) * .. External Functions .. LOGICAL LSE, LSERES EXTERNAL LSE, LSERES * .. External Subroutines .. EXTERNAL SMAKE, SMVCH, SSPR2, SSYR2 * .. Intrinsic Functions .. INTRINSIC ABS, MAX * .. Scalars in Common .. INTEGER INFOT, NOUTC LOGICAL LERR, OK * .. Common blocks .. COMMON /INFOC/INFOT, NOUTC, OK, LERR * .. Data statements .. DATA ICH/'UL'/ * .. Executable Statements .. FULL = SNAME( 3: 3 ).EQ.'Y' PACKED = SNAME( 3: 3 ).EQ.'P' * Define the number of arguments. IF( FULL )THEN NARGS = 9 ELSE IF( PACKED )THEN NARGS = 8 END IF * NC = 0 RESET = .TRUE. ERRMAX = ZERO * DO 140 IN = 1, NIDIM N = IDIM( IN ) * Set LDA to 1 more than minimum value if room. LDA = N IF( LDA.LT.NMAX ) $ LDA = LDA + 1 * Skip tests if not enough room. IF( LDA.GT.NMAX ) $ GO TO 140 IF( PACKED )THEN LAA = ( N*( N + 1 ) )/2 ELSE LAA = LDA*N END IF * DO 130 IC = 1, 2 UPLO = ICH( IC: IC ) UPPER = UPLO.EQ.'U' * DO 120 IX = 1, NINC INCX = INC( IX ) LX = ABS( INCX )*N * * Generate the vector X. * TRANSL = HALF CALL SMAKE( 'GE', ' ', ' ', 1, N, X, 1, XX, ABS( INCX ), $ 0, N - 1, RESET, TRANSL ) IF( N.GT.1 )THEN X( N/2 ) = ZERO XX( 1 + ABS( INCX )*( N/2 - 1 ) ) = ZERO END IF * DO 110 IY = 1, NINC INCY = INC( IY ) LY = ABS( INCY )*N * * Generate the vector Y. * TRANSL = ZERO CALL SMAKE( 'GE', ' ', ' ', 1, N, Y, 1, YY, $ ABS( INCY ), 0, N - 1, RESET, TRANSL ) IF( N.GT.1 )THEN Y( N/2 ) = ZERO YY( 1 + ABS( INCY )*( N/2 - 1 ) ) = ZERO END IF * DO 100 IA = 1, NALF ALPHA = ALF( IA ) NULL = N.LE.0.OR.ALPHA.EQ.ZERO * * Generate the matrix A. * TRANSL = ZERO CALL SMAKE( SNAME( 2: 3 ), UPLO, ' ', N, N, A, $ NMAX, AA, LDA, N - 1, N - 1, RESET, $ TRANSL ) * NC = NC + 1 * * Save every datum before calling the subroutine. * UPLOS = UPLO NS = N ALS = ALPHA DO 10 I = 1, LAA AS( I ) = AA( I ) 10 CONTINUE LDAS = LDA DO 20 I = 1, LX XS( I ) = XX( I ) 20 CONTINUE INCXS = INCX DO 30 I = 1, LY YS( I ) = YY( I ) 30 CONTINUE INCYS = INCY * * Call the subroutine. * IF( FULL )THEN IF( TRACE ) $ WRITE( NTRA, FMT = 9993 )NC, SNAME, UPLO, N, $ ALPHA, INCX, INCY, LDA IF( REWI ) $ REWIND NTRA CALL SSYR2( UPLO, N, ALPHA, XX, INCX, YY, INCY, $ AA, LDA ) ELSE IF( PACKED )THEN IF( TRACE ) $ WRITE( NTRA, FMT = 9994 )NC, SNAME, UPLO, N, $ ALPHA, INCX, INCY IF( REWI ) $ REWIND NTRA CALL SSPR2( UPLO, N, ALPHA, XX, INCX, YY, INCY, $ AA ) END IF * * Check if error-exit was taken incorrectly. * IF( .NOT.OK )THEN WRITE( NOUT, FMT = 9992 ) FATAL = .TRUE. GO TO 160 END IF * * See what data changed inside subroutines. * ISAME( 1 ) = UPLO.EQ.UPLOS ISAME( 2 ) = NS.EQ.N ISAME( 3 ) = ALS.EQ.ALPHA ISAME( 4 ) = LSE( XS, XX, LX ) ISAME( 5 ) = INCXS.EQ.INCX ISAME( 6 ) = LSE( YS, YY, LY ) ISAME( 7 ) = INCYS.EQ.INCY IF( NULL )THEN ISAME( 8 ) = LSE( AS, AA, LAA ) ELSE ISAME( 8 ) = LSERES( SNAME( 2: 3 ), UPLO, N, N, $ AS, AA, LDA ) END IF IF( .NOT.PACKED )THEN ISAME( 9 ) = LDAS.EQ.LDA END IF * * If data was incorrectly changed, report and return. * SAME = .TRUE. DO 40 I = 1, NARGS SAME = SAME.AND.ISAME( I ) IF( .NOT.ISAME( I ) ) $ WRITE( NOUT, FMT = 9998 )I 40 CONTINUE IF( .NOT.SAME )THEN FATAL = .TRUE. GO TO 160 END IF * IF( .NOT.NULL )THEN * * Check the result column by column. * IF( INCX.GT.0 )THEN DO 50 I = 1, N Z( I, 1 ) = X( I ) 50 CONTINUE ELSE DO 60 I = 1, N Z( I, 1 ) = X( N - I + 1 ) 60 CONTINUE END IF IF( INCY.GT.0 )THEN DO 70 I = 1, N Z( I, 2 ) = Y( I ) 70 CONTINUE ELSE DO 80 I = 1, N Z( I, 2 ) = Y( N - I + 1 ) 80 CONTINUE END IF JA = 1 DO 90 J = 1, N W( 1 ) = Z( J, 2 ) W( 2 ) = Z( J, 1 ) IF( UPPER )THEN JJ = 1 LJ = J ELSE JJ = J LJ = N - J + 1 END IF CALL SMVCH( 'N', LJ, 2, ALPHA, Z( JJ, 1 ), $ NMAX, W, 1, ONE, A( JJ, J ), 1, $ YT, G, AA( JA ), EPS, ERR, FATAL, $ NOUT, .TRUE. ) IF( FULL )THEN IF( UPPER )THEN JA = JA + LDA ELSE JA = JA + LDA + 1 END IF ELSE JA = JA + LJ END IF ERRMAX = MAX( ERRMAX, ERR ) * If got really bad answer, report and return. IF( FATAL ) $ GO TO 150 90 CONTINUE ELSE * Avoid repeating tests with N.le.0. IF( N.LE.0 ) $ GO TO 140 END IF * 100 CONTINUE * 110 CONTINUE * 120 CONTINUE * 130 CONTINUE * 140 CONTINUE * * Report result. * IF( ERRMAX.LT.THRESH )THEN WRITE( NOUT, FMT = 9999 )SNAME, NC ELSE WRITE( NOUT, FMT = 9997 )SNAME, NC, ERRMAX END IF GO TO 170 * 150 CONTINUE WRITE( NOUT, FMT = 9995 )J * 160 CONTINUE WRITE( NOUT, FMT = 9996 )SNAME IF( FULL )THEN WRITE( NOUT, FMT = 9993 )NC, SNAME, UPLO, N, ALPHA, INCX, $ INCY, LDA ELSE IF( PACKED )THEN WRITE( NOUT, FMT = 9994 )NC, SNAME, UPLO, N, ALPHA, INCX, INCY END IF * 170 CONTINUE RETURN * 9999 FORMAT( ' ', A6, ' PASSED THE COMPUTATIONAL TESTS (', I6, ' CALL', $ 'S)' ) 9998 FORMAT( ' ******* FATAL ERROR - PARAMETER NUMBER ', I2, ' WAS CH', $ 'ANGED INCORRECTLY *******' ) 9997 FORMAT( ' ', A6, ' COMPLETED THE COMPUTATIONAL TESTS (', I6, ' C', $ 'ALLS)', /' ******* BUT WITH MAXIMUM TEST RATIO', F8.2, $ ' - SUSPECT *******' ) 9996 FORMAT( ' ******* ', A6, ' FAILED ON CALL NUMBER:' ) 9995 FORMAT( ' THESE ARE THE RESULTS FOR COLUMN ', I3 ) 9994 FORMAT( 1X, I6, ': ', A6, '(''', A1, ''',', I3, ',', F4.1, ', X,', $ I2, ', Y,', I2, ', AP) .' ) 9993 FORMAT( 1X, I6, ': ', A6, '(''', A1, ''',', I3, ',', F4.1, ', X,', $ I2, ', Y,', I2, ', A,', I3, ') .' ) 9992 FORMAT( ' ******* FATAL ERROR - ERROR-EXIT TAKEN ON VALID CALL *', $ '******' ) * * End of SCHK6. * END SUBROUTINE SCHKE( ISNUM, SRNAMT, NOUT ) * * Tests the error exits from the Level 2 Blas. * Requires a special version of the error-handling routine XERBLA. * ALPHA, BETA, A, X and Y should not need to be defined. * * Auxiliary routine for test program for Level 2 Blas. * * -- Written on 10-August-1987. * Richard Hanson, Sandia National Labs. * Jeremy Du Croz, NAG Central Office. * * .. Scalar Arguments .. INTEGER ISNUM, NOUT CHARACTER*6 SRNAMT * .. Scalars in Common .. INTEGER INFOT, NOUTC LOGICAL LERR, OK * .. Local Scalars .. REAL ALPHA, BETA * .. Local Arrays .. REAL A( 1, 1 ), X( 1 ), Y( 1 ) * .. External Subroutines .. EXTERNAL CHKXER, SGBMV, SGEMV, SGER, SSBMV, SSPMV, SSPR, $ SSPR2, SSYMV, SSYR, SSYR2, STBMV, STBSV, STPMV, $ STPSV, STRMV, STRSV * .. Common blocks .. COMMON /INFOC/INFOT, NOUTC, OK, LERR * .. Executable Statements .. * OK is set to .FALSE. by the special version of XERBLA or by CHKXER * if anything is wrong. OK = .TRUE. * LERR is set to .TRUE. by the special version of XERBLA each time * it is called, and is then tested and re-set by CHKXER. LERR = .FALSE. GO TO ( 10, 20, 30, 40, 50, 60, 70, 80, $ 90, 100, 110, 120, 130, 140, 150, $ 160 )ISNUM 10 INFOT = 1 CALL SGEMV( '/', 0, 0, ALPHA, A, 1, X, 1, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL SGEMV( 'N', -1, 0, ALPHA, A, 1, X, 1, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL SGEMV( 'N', 0, -1, ALPHA, A, 1, X, 1, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL SGEMV( 'N', 2, 0, ALPHA, A, 1, X, 1, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 8 CALL SGEMV( 'N', 0, 0, ALPHA, A, 1, X, 0, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL SGEMV( 'N', 0, 0, ALPHA, A, 1, X, 1, BETA, Y, 0 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 170 20 INFOT = 1 CALL SGBMV( '/', 0, 0, 0, 0, ALPHA, A, 1, X, 1, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL SGBMV( 'N', -1, 0, 0, 0, ALPHA, A, 1, X, 1, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL SGBMV( 'N', 0, -1, 0, 0, ALPHA, A, 1, X, 1, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL SGBMV( 'N', 0, 0, -1, 0, ALPHA, A, 1, X, 1, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL SGBMV( 'N', 2, 0, 0, -1, ALPHA, A, 1, X, 1, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 8 CALL SGBMV( 'N', 0, 0, 1, 0, ALPHA, A, 1, X, 1, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 10 CALL SGBMV( 'N', 0, 0, 0, 0, ALPHA, A, 1, X, 0, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 13 CALL SGBMV( 'N', 0, 0, 0, 0, ALPHA, A, 1, X, 1, BETA, Y, 0 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 170 30 INFOT = 1 CALL SSYMV( '/', 0, ALPHA, A, 1, X, 1, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL SSYMV( 'U', -1, ALPHA, A, 1, X, 1, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL SSYMV( 'U', 2, ALPHA, A, 1, X, 1, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL SSYMV( 'U', 0, ALPHA, A, 1, X, 0, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 10 CALL SSYMV( 'U', 0, ALPHA, A, 1, X, 1, BETA, Y, 0 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 170 40 INFOT = 1 CALL SSBMV( '/', 0, 0, ALPHA, A, 1, X, 1, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL SSBMV( 'U', -1, 0, ALPHA, A, 1, X, 1, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL SSBMV( 'U', 0, -1, ALPHA, A, 1, X, 1, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL SSBMV( 'U', 0, 1, ALPHA, A, 1, X, 1, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 8 CALL SSBMV( 'U', 0, 0, ALPHA, A, 1, X, 0, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL SSBMV( 'U', 0, 0, ALPHA, A, 1, X, 1, BETA, Y, 0 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 170 50 INFOT = 1 CALL SSPMV( '/', 0, ALPHA, A, X, 1, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL SSPMV( 'U', -1, ALPHA, A, X, 1, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL SSPMV( 'U', 0, ALPHA, A, X, 0, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL SSPMV( 'U', 0, ALPHA, A, X, 1, BETA, Y, 0 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 170 60 INFOT = 1 CALL STRMV( '/', 'N', 'N', 0, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL STRMV( 'U', '/', 'N', 0, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL STRMV( 'U', 'N', '/', 0, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL STRMV( 'U', 'N', 'N', -1, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL STRMV( 'U', 'N', 'N', 2, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 8 CALL STRMV( 'U', 'N', 'N', 0, A, 1, X, 0 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 170 70 INFOT = 1 CALL STBMV( '/', 'N', 'N', 0, 0, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL STBMV( 'U', '/', 'N', 0, 0, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL STBMV( 'U', 'N', '/', 0, 0, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL STBMV( 'U', 'N', 'N', -1, 0, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL STBMV( 'U', 'N', 'N', 0, -1, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL STBMV( 'U', 'N', 'N', 0, 1, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL STBMV( 'U', 'N', 'N', 0, 0, A, 1, X, 0 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 170 80 INFOT = 1 CALL STPMV( '/', 'N', 'N', 0, A, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL STPMV( 'U', '/', 'N', 0, A, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL STPMV( 'U', 'N', '/', 0, A, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL STPMV( 'U', 'N', 'N', -1, A, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL STPMV( 'U', 'N', 'N', 0, A, X, 0 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 170 90 INFOT = 1 CALL STRSV( '/', 'N', 'N', 0, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL STRSV( 'U', '/', 'N', 0, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL STRSV( 'U', 'N', '/', 0, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL STRSV( 'U', 'N', 'N', -1, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL STRSV( 'U', 'N', 'N', 2, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 8 CALL STRSV( 'U', 'N', 'N', 0, A, 1, X, 0 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 170 100 INFOT = 1 CALL STBSV( '/', 'N', 'N', 0, 0, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL STBSV( 'U', '/', 'N', 0, 0, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL STBSV( 'U', 'N', '/', 0, 0, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL STBSV( 'U', 'N', 'N', -1, 0, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL STBSV( 'U', 'N', 'N', 0, -1, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL STBSV( 'U', 'N', 'N', 0, 1, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL STBSV( 'U', 'N', 'N', 0, 0, A, 1, X, 0 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 170 110 INFOT = 1 CALL STPSV( '/', 'N', 'N', 0, A, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL STPSV( 'U', '/', 'N', 0, A, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL STPSV( 'U', 'N', '/', 0, A, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL STPSV( 'U', 'N', 'N', -1, A, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL STPSV( 'U', 'N', 'N', 0, A, X, 0 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 170 120 INFOT = 1 CALL SGER( -1, 0, ALPHA, X, 1, Y, 1, A, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL SGER( 0, -1, ALPHA, X, 1, Y, 1, A, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL SGER( 0, 0, ALPHA, X, 0, Y, 1, A, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL SGER( 0, 0, ALPHA, X, 1, Y, 0, A, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL SGER( 2, 0, ALPHA, X, 1, Y, 1, A, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 170 130 INFOT = 1 CALL SSYR( '/', 0, ALPHA, X, 1, A, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL SSYR( 'U', -1, ALPHA, X, 1, A, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL SSYR( 'U', 0, ALPHA, X, 0, A, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL SSYR( 'U', 2, ALPHA, X, 1, A, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 170 140 INFOT = 1 CALL SSPR( '/', 0, ALPHA, X, 1, A ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL SSPR( 'U', -1, ALPHA, X, 1, A ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL SSPR( 'U', 0, ALPHA, X, 0, A ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 170 150 INFOT = 1 CALL SSYR2( '/', 0, ALPHA, X, 1, Y, 1, A, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL SSYR2( 'U', -1, ALPHA, X, 1, Y, 1, A, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL SSYR2( 'U', 0, ALPHA, X, 0, Y, 1, A, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL SSYR2( 'U', 0, ALPHA, X, 1, Y, 0, A, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL SSYR2( 'U', 2, ALPHA, X, 1, Y, 1, A, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 170 160 INFOT = 1 CALL SSPR2( '/', 0, ALPHA, X, 1, Y, 1, A ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL SSPR2( 'U', -1, ALPHA, X, 1, Y, 1, A ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL SSPR2( 'U', 0, ALPHA, X, 0, Y, 1, A ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL SSPR2( 'U', 0, ALPHA, X, 1, Y, 0, A ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) * 170 IF( OK )THEN WRITE( NOUT, FMT = 9999 )SRNAMT ELSE WRITE( NOUT, FMT = 9998 )SRNAMT END IF RETURN * 9999 FORMAT( ' ', A6, ' PASSED THE TESTS OF ERROR-EXITS' ) 9998 FORMAT( ' ******* ', A6, ' FAILED THE TESTS OF ERROR-EXITS *****', $ '**' ) * * End of SCHKE. * END SUBROUTINE SMAKE( TYPE, UPLO, DIAG, M, N, A, NMAX, AA, LDA, KL, $ KU, RESET, TRANSL ) * * Generates values for an M by N matrix A within the bandwidth * defined by KL and KU. * Stores the values in the array AA in the data structure required * by the routine, with unwanted elements set to rogue value. * * TYPE is 'GE', 'GB', 'SY', 'SB', 'SP', 'TR', 'TB' OR 'TP'. * * Auxiliary routine for test program for Level 2 Blas. * * -- Written on 10-August-1987. * Richard Hanson, Sandia National Labs. * Jeremy Du Croz, NAG Central Office. * * .. Parameters .. REAL ZERO, ONE PARAMETER ( ZERO = 0.0, ONE = 1.0 ) REAL ROGUE PARAMETER ( ROGUE = -1.0E10 ) * .. Scalar Arguments .. REAL TRANSL INTEGER KL, KU, LDA, M, N, NMAX LOGICAL RESET CHARACTER*1 DIAG, UPLO CHARACTER*2 TYPE * .. Array Arguments .. REAL A( NMAX, * ), AA( * ) * .. Local Scalars .. INTEGER I, I1, I2, I3, IBEG, IEND, IOFF, J, KK LOGICAL GEN, LOWER, SYM, TRI, UNIT, UPPER * .. External Functions .. REAL SBEG EXTERNAL SBEG * .. Intrinsic Functions .. INTRINSIC MAX, MIN * .. Executable Statements .. GEN = TYPE( 1: 1 ).EQ.'G' SYM = TYPE( 1: 1 ).EQ.'S' TRI = TYPE( 1: 1 ).EQ.'T' UPPER = ( SYM.OR.TRI ).AND.UPLO.EQ.'U' LOWER = ( SYM.OR.TRI ).AND.UPLO.EQ.'L' UNIT = TRI.AND.DIAG.EQ.'U' * * Generate data in array A. * DO 20 J = 1, N DO 10 I = 1, M IF( GEN.OR.( UPPER.AND.I.LE.J ).OR.( LOWER.AND.I.GE.J ) ) $ THEN IF( ( I.LE.J.AND.J - I.LE.KU ).OR. $ ( I.GE.J.AND.I - J.LE.KL ) )THEN A( I, J ) = SBEG( RESET ) + TRANSL ELSE A( I, J ) = ZERO END IF IF( I.NE.J )THEN IF( SYM )THEN A( J, I ) = A( I, J ) ELSE IF( TRI )THEN A( J, I ) = ZERO END IF END IF END IF 10 CONTINUE IF( TRI ) $ A( J, J ) = A( J, J ) + ONE IF( UNIT ) $ A( J, J ) = ONE 20 CONTINUE * * Store elements in array AS in data structure required by routine. * IF( TYPE.EQ.'GE' )THEN DO 50 J = 1, N DO 30 I = 1, M AA( I + ( J - 1 )*LDA ) = A( I, J ) 30 CONTINUE DO 40 I = M + 1, LDA AA( I + ( J - 1 )*LDA ) = ROGUE 40 CONTINUE 50 CONTINUE ELSE IF( TYPE.EQ.'GB' )THEN DO 90 J = 1, N DO 60 I1 = 1, KU + 1 - J AA( I1 + ( J - 1 )*LDA ) = ROGUE 60 CONTINUE DO 70 I2 = I1, MIN( KL + KU + 1, KU + 1 + M - J ) AA( I2 + ( J - 1 )*LDA ) = A( I2 + J - KU - 1, J ) 70 CONTINUE DO 80 I3 = I2, LDA AA( I3 + ( J - 1 )*LDA ) = ROGUE 80 CONTINUE 90 CONTINUE ELSE IF( TYPE.EQ.'SY'.OR.TYPE.EQ.'TR' )THEN DO 130 J = 1, N IF( UPPER )THEN IBEG = 1 IF( UNIT )THEN IEND = J - 1 ELSE IEND = J END IF ELSE IF( UNIT )THEN IBEG = J + 1 ELSE IBEG = J END IF IEND = N END IF DO 100 I = 1, IBEG - 1 AA( I + ( J - 1 )*LDA ) = ROGUE 100 CONTINUE DO 110 I = IBEG, IEND AA( I + ( J - 1 )*LDA ) = A( I, J ) 110 CONTINUE DO 120 I = IEND + 1, LDA AA( I + ( J - 1 )*LDA ) = ROGUE 120 CONTINUE 130 CONTINUE ELSE IF( TYPE.EQ.'SB'.OR.TYPE.EQ.'TB' )THEN DO 170 J = 1, N IF( UPPER )THEN KK = KL + 1 IBEG = MAX( 1, KL + 2 - J ) IF( UNIT )THEN IEND = KL ELSE IEND = KL + 1 END IF ELSE KK = 1 IF( UNIT )THEN IBEG = 2 ELSE IBEG = 1 END IF IEND = MIN( KL + 1, 1 + M - J ) END IF DO 140 I = 1, IBEG - 1 AA( I + ( J - 1 )*LDA ) = ROGUE 140 CONTINUE DO 150 I = IBEG, IEND AA( I + ( J - 1 )*LDA ) = A( I + J - KK, J ) 150 CONTINUE DO 160 I = IEND + 1, LDA AA( I + ( J - 1 )*LDA ) = ROGUE 160 CONTINUE 170 CONTINUE ELSE IF( TYPE.EQ.'SP'.OR.TYPE.EQ.'TP' )THEN IOFF = 0 DO 190 J = 1, N IF( UPPER )THEN IBEG = 1 IEND = J ELSE IBEG = J IEND = N END IF DO 180 I = IBEG, IEND IOFF = IOFF + 1 AA( IOFF ) = A( I, J ) IF( I.EQ.J )THEN IF( UNIT ) $ AA( IOFF ) = ROGUE END IF 180 CONTINUE 190 CONTINUE END IF RETURN * * End of SMAKE. * END SUBROUTINE SMVCH( TRANS, M, N, ALPHA, A, NMAX, X, INCX, BETA, Y, $ INCY, YT, G, YY, EPS, ERR, FATAL, NOUT, MV ) * * Checks the results of the computational tests. * * Auxiliary routine for test program for Level 2 Blas. * * -- Written on 10-August-1987. * Richard Hanson, Sandia National Labs. * Jeremy Du Croz, NAG Central Office. * * .. Parameters .. REAL ZERO, ONE PARAMETER ( ZERO = 0.0, ONE = 1.0 ) * .. Scalar Arguments .. REAL ALPHA, BETA, EPS, ERR INTEGER INCX, INCY, M, N, NMAX, NOUT LOGICAL FATAL, MV CHARACTER*1 TRANS * .. Array Arguments .. REAL A( NMAX, * ), G( * ), X( * ), Y( * ), YT( * ), $ YY( * ) * .. Local Scalars .. REAL ERRI INTEGER I, INCXL, INCYL, IY, J, JX, KX, KY, ML, NL LOGICAL TRAN * .. Intrinsic Functions .. INTRINSIC ABS, MAX, SQRT * .. Executable Statements .. TRAN = TRANS.EQ.'T'.OR.TRANS.EQ.'C' IF( TRAN )THEN ML = N NL = M ELSE ML = M NL = N END IF IF( INCX.LT.0 )THEN KX = NL INCXL = -1 ELSE KX = 1 INCXL = 1 END IF IF( INCY.LT.0 )THEN KY = ML INCYL = -1 ELSE KY = 1 INCYL = 1 END IF * * Compute expected result in YT using data in A, X and Y. * Compute gauges in G. * IY = KY DO 30 I = 1, ML YT( IY ) = ZERO G( IY ) = ZERO JX = KX IF( TRAN )THEN DO 10 J = 1, NL YT( IY ) = YT( IY ) + A( J, I )*X( JX ) G( IY ) = G( IY ) + ABS( A( J, I )*X( JX ) ) JX = JX + INCXL 10 CONTINUE ELSE DO 20 J = 1, NL YT( IY ) = YT( IY ) + A( I, J )*X( JX ) G( IY ) = G( IY ) + ABS( A( I, J )*X( JX ) ) JX = JX + INCXL 20 CONTINUE END IF YT( IY ) = ALPHA*YT( IY ) + BETA*Y( IY ) G( IY ) = ABS( ALPHA )*G( IY ) + ABS( BETA*Y( IY ) ) IY = IY + INCYL 30 CONTINUE * * Compute the error ratio for this result. * ERR = ZERO DO 40 I = 1, ML ERRI = ABS( YT( I ) - YY( 1 + ( I - 1 )*ABS( INCY ) ) )/EPS IF( G( I ).NE.ZERO ) $ ERRI = ERRI/G( I ) ERR = MAX( ERR, ERRI ) IF( ERR*SQRT( EPS ).GE.ONE ) $ GO TO 50 40 CONTINUE * If the loop completes, all results are at least half accurate. GO TO 70 * * Report fatal error. * 50 FATAL = .TRUE. WRITE( NOUT, FMT = 9999 ) DO 60 I = 1, ML IF( MV )THEN WRITE( NOUT, FMT = 9998 )I, YT( I ), $ YY( 1 + ( I - 1 )*ABS( INCY ) ) ELSE WRITE( NOUT, FMT = 9998 )I, $ YY( 1 + ( I - 1 )*ABS( INCY ) ), YT(I) END IF 60 CONTINUE * 70 CONTINUE RETURN * 9999 FORMAT( ' ******* FATAL ERROR - COMPUTED RESULT IS LESS THAN HAL', $ 'F ACCURATE *******', /' EXPECTED RESULT COMPU', $ 'TED RESULT' ) 9998 FORMAT( 1X, I7, 2G18.6 ) * * End of SMVCH. * END LOGICAL FUNCTION LSE( RI, RJ, LR ) * * Tests if two arrays are identical. * * Auxiliary routine for test program for Level 2 Blas. * * -- Written on 10-August-1987. * Richard Hanson, Sandia National Labs. * Jeremy Du Croz, NAG Central Office. * * .. Scalar Arguments .. INTEGER LR * .. Array Arguments .. REAL RI( * ), RJ( * ) * .. Local Scalars .. INTEGER I * .. Executable Statements .. DO 10 I = 1, LR IF( RI( I ).NE.RJ( I ) ) $ GO TO 20 10 CONTINUE LSE = .TRUE. GO TO 30 20 CONTINUE LSE = .FALSE. 30 RETURN * * End of LSE. * END LOGICAL FUNCTION LSERES( TYPE, UPLO, M, N, AA, AS, LDA ) * * Tests if selected elements in two arrays are equal. * * TYPE is 'GE', 'SY' or 'SP'. * * Auxiliary routine for test program for Level 2 Blas. * * -- Written on 10-August-1987. * Richard Hanson, Sandia National Labs. * Jeremy Du Croz, NAG Central Office. * * .. Scalar Arguments .. INTEGER LDA, M, N CHARACTER*1 UPLO CHARACTER*2 TYPE * .. Array Arguments .. REAL AA( LDA, * ), AS( LDA, * ) * .. Local Scalars .. INTEGER I, IBEG, IEND, J LOGICAL UPPER * .. Executable Statements .. UPPER = UPLO.EQ.'U' IF( TYPE.EQ.'GE' )THEN DO 20 J = 1, N DO 10 I = M + 1, LDA IF( AA( I, J ).NE.AS( I, J ) ) $ GO TO 70 10 CONTINUE 20 CONTINUE ELSE IF( TYPE.EQ.'SY' )THEN DO 50 J = 1, N IF( UPPER )THEN IBEG = 1 IEND = J ELSE IBEG = J IEND = N END IF DO 30 I = 1, IBEG - 1 IF( AA( I, J ).NE.AS( I, J ) ) $ GO TO 70 30 CONTINUE DO 40 I = IEND + 1, LDA IF( AA( I, J ).NE.AS( I, J ) ) $ GO TO 70 40 CONTINUE 50 CONTINUE END IF * LSERES = .TRUE. GO TO 80 70 CONTINUE LSERES = .FALSE. 80 RETURN * * End of LSERES. * END REAL FUNCTION SBEG( RESET ) * * Generates random numbers uniformly distributed between -0.5 and 0.5. * * Auxiliary routine for test program for Level 2 Blas. * * -- Written on 10-August-1987. * Richard Hanson, Sandia National Labs. * Jeremy Du Croz, NAG Central Office. * * .. Scalar Arguments .. LOGICAL RESET * .. Local Scalars .. INTEGER I, IC, MI * .. Save statement .. SAVE I, IC, MI * .. Intrinsic Functions .. INTRINSIC REAL * .. Executable Statements .. IF( RESET )THEN * Initialize local variables. MI = 891 I = 7 IC = 0 RESET = .FALSE. END IF * * The sequence of values of I is bounded between 1 and 999. * If initial I = 1,2,3,6,7 or 9, the period will be 50. * If initial I = 4 or 8, the period will be 25. * If initial I = 5, the period will be 10. * IC is used to break up the period by skipping 1 value of I in 6. * IC = IC + 1 10 I = I*MI I = I - 1000*( I/1000 ) IF( IC.GE.5 )THEN IC = 0 GO TO 10 END IF SBEG = REAL( I - 500 )/1001.0 RETURN * * End of SBEG. * END REAL FUNCTION SDIFF( X, Y ) * * Auxiliary routine for test program for Level 2 Blas. * * -- Written on 10-August-1987. * Richard Hanson, Sandia National Labs. * * .. Scalar Arguments .. REAL X, Y * .. Executable Statements .. SDIFF = X - Y RETURN * * End of SDIFF. * END SUBROUTINE CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) * * Tests whether XERBLA has detected an error when it should. * * Auxiliary routine for test program for Level 2 Blas. * * -- Written on 10-August-1987. * Richard Hanson, Sandia National Labs. * Jeremy Du Croz, NAG Central Office. * * .. Scalar Arguments .. INTEGER INFOT, NOUT LOGICAL LERR, OK CHARACTER*6 SRNAMT * .. Executable Statements .. IF( .NOT.LERR )THEN WRITE( NOUT, FMT = 9999 )INFOT, SRNAMT OK = .FALSE. END IF LERR = .FALSE. RETURN * 9999 FORMAT( ' ***** ILLEGAL VALUE OF PARAMETER NUMBER ', I2, ' NOT D', $ 'ETECTED BY ', A6, ' *****' ) * * End of CHKXER. * END SUBROUTINE XERBLA( SRNAME, INFO ) * * This is a special version of XERBLA to be used only as part of * the test program for testing error exits from the Level 2 BLAS * routines. * * XERBLA is an error handler for the Level 2 BLAS routines. * * It is called by the Level 2 BLAS routines if an input parameter is * invalid. * * Auxiliary routine for test program for Level 2 Blas. * * -- Written on 10-August-1987. * Richard Hanson, Sandia National Labs. * Jeremy Du Croz, NAG Central Office. * * .. Scalar Arguments .. INTEGER INFO CHARACTER*6 SRNAME * .. Scalars in Common .. INTEGER INFOT, NOUT LOGICAL LERR, OK CHARACTER*6 SRNAMT * .. Common blocks .. COMMON /INFOC/INFOT, NOUT, OK, LERR COMMON /SRNAMC/SRNAMT * .. Executable Statements .. LERR = .TRUE. IF( INFO.NE.INFOT )THEN IF( INFOT.NE.0 )THEN WRITE( NOUT, FMT = 9999 )INFO, INFOT ELSE WRITE( NOUT, FMT = 9997 )INFO END IF OK = .FALSE. END IF IF( SRNAME.NE.SRNAMT )THEN WRITE( NOUT, FMT = 9998 )SRNAME, SRNAMT OK = .FALSE. END IF RETURN * 9999 FORMAT( ' ******* XERBLA WAS CALLED WITH INFO = ', I6, ' INSTEAD', $ ' OF ', I2, ' *******' ) 9998 FORMAT( ' ******* XERBLA WAS CALLED WITH SRNAME = ', A6, ' INSTE', $ 'AD OF ', A6, ' *******' ) 9997 FORMAT( ' ******* XERBLA WAS CALLED WITH INFO = ', I6, $ ' *******' ) * * End of XERBLA * END blis-0.9.0/blastest/src/fortran/sblat3.f000066400000000000000000003133541422157504600201120ustar00rootroot00000000000000*> \brief \b SBLAT3 * * =========== DOCUMENTATION =========== * * Online html documentation available at * http://www.netlib.org/lapack/explore-html/ * * Definition: * =========== * * PROGRAM SBLAT3 * * *> \par Purpose: * ============= *> *> \verbatim *> *> Test program for the REAL Level 3 Blas. *> *> The program must be driven by a short data file. The first 14 records *> of the file are read using list-directed input, the last 6 records *> are read using the format ( A6, L2 ). An annotated example of a data *> file can be obtained by deleting the first 3 characters from the *> following 20 lines: *> 'sblat3.out' NAME OF SUMMARY OUTPUT FILE *> 6 UNIT NUMBER OF SUMMARY FILE *> 'SBLAT3.SNAP' NAME OF SNAPSHOT OUTPUT FILE *> -1 UNIT NUMBER OF SNAPSHOT FILE (NOT USED IF .LT. 0) *> F LOGICAL FLAG, T TO REWIND SNAPSHOT FILE AFTER EACH RECORD. *> F LOGICAL FLAG, T TO STOP ON FAILURES. *> T LOGICAL FLAG, T TO TEST ERROR EXITS. *> 16.0 THRESHOLD VALUE OF TEST RATIO *> 6 NUMBER OF VALUES OF N *> 0 1 2 3 5 9 VALUES OF N *> 3 NUMBER OF VALUES OF ALPHA *> 0.0 1.0 0.7 VALUES OF ALPHA *> 3 NUMBER OF VALUES OF BETA *> 0.0 1.0 1.3 VALUES OF BETA *> SGEMM T PUT F FOR NO TEST. SAME COLUMNS. *> SSYMM T PUT F FOR NO TEST. SAME COLUMNS. *> STRMM T PUT F FOR NO TEST. SAME COLUMNS. *> STRSM T PUT F FOR NO TEST. SAME COLUMNS. *> SSYRK T PUT F FOR NO TEST. SAME COLUMNS. *> SSYR2K T PUT F FOR NO TEST. SAME COLUMNS. *> *> Further Details *> =============== *> *> See: *> *> Dongarra J. J., Du Croz J. J., Duff I. S. and Hammarling S. *> A Set of Level 3 Basic Linear Algebra Subprograms. *> *> Technical Memorandum No.88 (Revision 1), Mathematics and *> Computer Science Division, Argonne National Laboratory, 9700 *> South Cass Avenue, Argonne, Illinois 60439, US. *> *> -- Written on 8-February-1989. *> Jack Dongarra, Argonne National Laboratory. *> Iain Duff, AERE Harwell. *> Jeremy Du Croz, Numerical Algorithms Group Ltd. *> Sven Hammarling, Numerical Algorithms Group Ltd. *> *> 10-9-00: Change STATUS='NEW' to 'UNKNOWN' so that the testers *> can be run multiple times without deleting generated *> output files (susan) *> \endverbatim * * Authors: * ======== * *> \author Univ. of Tennessee *> \author Univ. of California Berkeley *> \author Univ. of Colorado Denver *> \author NAG Ltd. * *> \date April 2012 * *> \ingroup single_blas_testing * * ===================================================================== PROGRAM SBLAT3 * * -- Reference BLAS test routine (version 3.4.1) -- * -- Reference BLAS is a software package provided by Univ. of Tennessee, -- * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- * April 2012 * * ===================================================================== * * .. Parameters .. INTEGER NIN PARAMETER ( NIN = 5 ) INTEGER NSUBS PARAMETER ( NSUBS = 6 ) REAL ZERO, ONE PARAMETER ( ZERO = 0.0, ONE = 1.0 ) INTEGER NMAX PARAMETER ( NMAX = 65 ) INTEGER NIDMAX, NALMAX, NBEMAX PARAMETER ( NIDMAX = 9, NALMAX = 7, NBEMAX = 7 ) * .. Local Scalars .. REAL EPS, ERR, THRESH INTEGER I, ISNUM, J, N, NALF, NBET, NIDIM, NOUT, NTRA LOGICAL FATAL, LTESTT, REWI, SAME, SFATAL, TRACE, $ TSTERR CHARACTER*1 TRANSA, TRANSB CHARACTER*6 SNAMET CHARACTER*32 SNAPS, SUMMRY * .. Local Arrays .. REAL AA( NMAX*NMAX ), AB( NMAX, 2*NMAX ), $ ALF( NALMAX ), AS( NMAX*NMAX ), $ BB( NMAX*NMAX ), BET( NBEMAX ), $ BS( NMAX*NMAX ), C( NMAX, NMAX ), $ CC( NMAX*NMAX ), CS( NMAX*NMAX ), CT( NMAX ), $ G( NMAX ), W( 2*NMAX ) INTEGER IDIM( NIDMAX ) LOGICAL LTEST( NSUBS ) CHARACTER*6 SNAMES( NSUBS ) * .. External Functions .. REAL SDIFF LOGICAL LSE EXTERNAL SDIFF, LSE * .. External Subroutines .. EXTERNAL SCHK1, SCHK2, SCHK3, SCHK4, SCHK5, SCHKE, SMMCH * .. Intrinsic Functions .. INTRINSIC MAX, MIN * .. Scalars in Common .. INTEGER INFOT, NOUTC LOGICAL LERR, OK CHARACTER*6 SRNAMT * .. Common blocks .. COMMON /INFOC/INFOT, NOUTC, OK, LERR COMMON /SRNAMC/SRNAMT * .. Data statements .. DATA SNAMES/'SGEMM ', 'SSYMM ', 'STRMM ', 'STRSM ', $ 'SSYRK ', 'SSYR2K'/ * .. Executable Statements .. * * Read name and unit number for summary output file and open file. * READ( NIN, FMT = * )SUMMRY READ( NIN, FMT = * )NOUT OPEN( NOUT, FILE = SUMMRY ) NOUTC = NOUT * * Read name and unit number for snapshot output file and open file. * READ( NIN, FMT = * )SNAPS READ( NIN, FMT = * )NTRA TRACE = NTRA.GE.0 IF( TRACE )THEN OPEN( NTRA, FILE = SNAPS ) END IF * Read the flag that directs rewinding of the snapshot file. READ( NIN, FMT = * )REWI REWI = REWI.AND.TRACE * Read the flag that directs stopping on any failure. READ( NIN, FMT = * )SFATAL * Read the flag that indicates whether error exits are to be tested. READ( NIN, FMT = * )TSTERR * Read the threshold value of the test ratio READ( NIN, FMT = * )THRESH * * Read and check the parameter values for the tests. * * Values of N READ( NIN, FMT = * )NIDIM IF( NIDIM.LT.1.OR.NIDIM.GT.NIDMAX )THEN WRITE( NOUT, FMT = 9997 )'N', NIDMAX GO TO 220 END IF READ( NIN, FMT = * )( IDIM( I ), I = 1, NIDIM ) DO 10 I = 1, NIDIM IF( IDIM( I ).LT.0.OR.IDIM( I ).GT.NMAX )THEN WRITE( NOUT, FMT = 9996 )NMAX GO TO 220 END IF 10 CONTINUE * Values of ALPHA READ( NIN, FMT = * )NALF IF( NALF.LT.1.OR.NALF.GT.NALMAX )THEN WRITE( NOUT, FMT = 9997 )'ALPHA', NALMAX GO TO 220 END IF READ( NIN, FMT = * )( ALF( I ), I = 1, NALF ) * Values of BETA READ( NIN, FMT = * )NBET IF( NBET.LT.1.OR.NBET.GT.NBEMAX )THEN WRITE( NOUT, FMT = 9997 )'BETA', NBEMAX GO TO 220 END IF READ( NIN, FMT = * )( BET( I ), I = 1, NBET ) * * Report values of parameters. * WRITE( NOUT, FMT = 9995 ) WRITE( NOUT, FMT = 9994 )( IDIM( I ), I = 1, NIDIM ) WRITE( NOUT, FMT = 9993 )( ALF( I ), I = 1, NALF ) WRITE( NOUT, FMT = 9992 )( BET( I ), I = 1, NBET ) IF( .NOT.TSTERR )THEN WRITE( NOUT, FMT = * ) WRITE( NOUT, FMT = 9984 ) END IF WRITE( NOUT, FMT = * ) WRITE( NOUT, FMT = 9999 )THRESH WRITE( NOUT, FMT = * ) * * Read names of subroutines and flags which indicate * whether they are to be tested. * DO 20 I = 1, NSUBS LTEST( I ) = .FALSE. 20 CONTINUE 30 READ( NIN, FMT = 9988, END = 60 )SNAMET, LTESTT DO 40 I = 1, NSUBS IF( SNAMET.EQ.SNAMES( I ) ) $ GO TO 50 40 CONTINUE WRITE( NOUT, FMT = 9990 )SNAMET STOP 50 LTEST( I ) = LTESTT GO TO 30 * 60 CONTINUE CLOSE ( NIN ) * * Compute EPS (the machine precision). * EPS = EPSILON(ZERO) WRITE( NOUT, FMT = 9998 )EPS * * Check the reliability of SMMCH using exact data. * N = MIN( 32, NMAX ) DO 100 J = 1, N DO 90 I = 1, N AB( I, J ) = MAX( I - J + 1, 0 ) 90 CONTINUE AB( J, NMAX + 1 ) = J AB( 1, NMAX + J ) = J C( J, 1 ) = ZERO 100 CONTINUE DO 110 J = 1, N CC( J ) = J*( ( J + 1 )*J )/2 - ( ( J + 1 )*J*( J - 1 ) )/3 110 CONTINUE * CC holds the exact result. On exit from SMMCH CT holds * the result computed by SMMCH. TRANSA = 'N' TRANSB = 'N' CALL SMMCH( TRANSA, TRANSB, N, 1, N, ONE, AB, NMAX, $ AB( 1, NMAX + 1 ), NMAX, ZERO, C, NMAX, CT, G, CC, $ NMAX, EPS, ERR, FATAL, NOUT, .TRUE. ) SAME = LSE( CC, CT, N ) IF( .NOT.SAME.OR.ERR.NE.ZERO )THEN WRITE( NOUT, FMT = 9989 )TRANSA, TRANSB, SAME, ERR STOP END IF TRANSB = 'T' CALL SMMCH( TRANSA, TRANSB, N, 1, N, ONE, AB, NMAX, $ AB( 1, NMAX + 1 ), NMAX, ZERO, C, NMAX, CT, G, CC, $ NMAX, EPS, ERR, FATAL, NOUT, .TRUE. ) SAME = LSE( CC, CT, N ) IF( .NOT.SAME.OR.ERR.NE.ZERO )THEN WRITE( NOUT, FMT = 9989 )TRANSA, TRANSB, SAME, ERR STOP END IF DO 120 J = 1, N AB( J, NMAX + 1 ) = N - J + 1 AB( 1, NMAX + J ) = N - J + 1 120 CONTINUE DO 130 J = 1, N CC( N - J + 1 ) = J*( ( J + 1 )*J )/2 - $ ( ( J + 1 )*J*( J - 1 ) )/3 130 CONTINUE TRANSA = 'T' TRANSB = 'N' CALL SMMCH( TRANSA, TRANSB, N, 1, N, ONE, AB, NMAX, $ AB( 1, NMAX + 1 ), NMAX, ZERO, C, NMAX, CT, G, CC, $ NMAX, EPS, ERR, FATAL, NOUT, .TRUE. ) SAME = LSE( CC, CT, N ) IF( .NOT.SAME.OR.ERR.NE.ZERO )THEN WRITE( NOUT, FMT = 9989 )TRANSA, TRANSB, SAME, ERR STOP END IF TRANSB = 'T' CALL SMMCH( TRANSA, TRANSB, N, 1, N, ONE, AB, NMAX, $ AB( 1, NMAX + 1 ), NMAX, ZERO, C, NMAX, CT, G, CC, $ NMAX, EPS, ERR, FATAL, NOUT, .TRUE. ) SAME = LSE( CC, CT, N ) IF( .NOT.SAME.OR.ERR.NE.ZERO )THEN WRITE( NOUT, FMT = 9989 )TRANSA, TRANSB, SAME, ERR STOP END IF * * Test each subroutine in turn. * DO 200 ISNUM = 1, NSUBS WRITE( NOUT, FMT = * ) IF( .NOT.LTEST( ISNUM ) )THEN * Subprogram is not to be tested. WRITE( NOUT, FMT = 9987 )SNAMES( ISNUM ) ELSE SRNAMT = SNAMES( ISNUM ) * Test error exits. IF( TSTERR )THEN CALL SCHKE( ISNUM, SNAMES( ISNUM ), NOUT ) WRITE( NOUT, FMT = * ) END IF * Test computations. INFOT = 0 OK = .TRUE. FATAL = .FALSE. GO TO ( 140, 150, 160, 160, 170, 180 )ISNUM * Test SGEMM, 01. 140 CALL SCHK1( SNAMES( ISNUM ), EPS, THRESH, NOUT, NTRA, TRACE, $ REWI, FATAL, NIDIM, IDIM, NALF, ALF, NBET, BET, $ NMAX, AB, AA, AS, AB( 1, NMAX + 1 ), BB, BS, C, $ CC, CS, CT, G ) GO TO 190 * Test SSYMM, 02. 150 CALL SCHK2( SNAMES( ISNUM ), EPS, THRESH, NOUT, NTRA, TRACE, $ REWI, FATAL, NIDIM, IDIM, NALF, ALF, NBET, BET, $ NMAX, AB, AA, AS, AB( 1, NMAX + 1 ), BB, BS, C, $ CC, CS, CT, G ) GO TO 190 * Test STRMM, 03, STRSM, 04. 160 CALL SCHK3( SNAMES( ISNUM ), EPS, THRESH, NOUT, NTRA, TRACE, $ REWI, FATAL, NIDIM, IDIM, NALF, ALF, NMAX, AB, $ AA, AS, AB( 1, NMAX + 1 ), BB, BS, CT, G, C ) GO TO 190 * Test SSYRK, 05. 170 CALL SCHK4( SNAMES( ISNUM ), EPS, THRESH, NOUT, NTRA, TRACE, $ REWI, FATAL, NIDIM, IDIM, NALF, ALF, NBET, BET, $ NMAX, AB, AA, AS, AB( 1, NMAX + 1 ), BB, BS, C, $ CC, CS, CT, G ) GO TO 190 * Test SSYR2K, 06. 180 CALL SCHK5( SNAMES( ISNUM ), EPS, THRESH, NOUT, NTRA, TRACE, $ REWI, FATAL, NIDIM, IDIM, NALF, ALF, NBET, BET, $ NMAX, AB, AA, AS, BB, BS, C, CC, CS, CT, G, W ) GO TO 190 * 190 IF( FATAL.AND.SFATAL ) $ GO TO 210 END IF 200 CONTINUE WRITE( NOUT, FMT = 9986 ) GO TO 230 * 210 CONTINUE WRITE( NOUT, FMT = 9985 ) GO TO 230 * 220 CONTINUE WRITE( NOUT, FMT = 9991 ) * 230 CONTINUE IF( TRACE ) $ CLOSE ( NTRA ) CLOSE ( NOUT ) STOP * 9999 FORMAT( ' ROUTINES PASS COMPUTATIONAL TESTS IF TEST RATIO IS LES', $ 'S THAN', F8.2 ) 9998 FORMAT( ' RELATIVE MACHINE PRECISION IS TAKEN TO BE', 1P, E9.1 ) 9997 FORMAT( ' NUMBER OF VALUES OF ', A, ' IS LESS THAN 1 OR GREATER ', $ 'THAN ', I2 ) 9996 FORMAT( ' VALUE OF N IS LESS THAN 0 OR GREATER THAN ', I2 ) 9995 FORMAT( ' TESTS OF THE REAL LEVEL 3 BLAS', //' THE F', $ 'OLLOWING PARAMETER VALUES WILL BE USED:' ) 9994 FORMAT( ' FOR N ', 9I6 ) 9993 FORMAT( ' FOR ALPHA ', 7F6.1 ) 9992 FORMAT( ' FOR BETA ', 7F6.1 ) 9991 FORMAT( ' AMEND DATA FILE OR INCREASE ARRAY SIZES IN PROGRAM', $ /' ******* TESTS ABANDONED *******' ) 9990 FORMAT( ' SUBPROGRAM NAME ', A6, ' NOT RECOGNIZED', /' ******* T', $ 'ESTS ABANDONED *******' ) 9989 FORMAT( ' ERROR IN SMMCH - IN-LINE DOT PRODUCTS ARE BEING EVALU', $ 'ATED WRONGLY.', /' SMMCH WAS CALLED WITH TRANSA = ', A1, $ ' AND TRANSB = ', A1, /' AND RETURNED SAME = ', L1, ' AND ', $ 'ERR = ', F12.3, '.', /' THIS MAY BE DUE TO FAULTS IN THE ', $ 'ARITHMETIC OR THE COMPILER.', /' ******* TESTS ABANDONED ', $ '*******' ) 9988 FORMAT( A6, L2 ) 9987 FORMAT( 1X, A6, ' WAS NOT TESTED' ) 9986 FORMAT( /' END OF TESTS' ) 9985 FORMAT( /' ******* FATAL ERROR - TESTS ABANDONED *******' ) 9984 FORMAT( ' ERROR-EXITS WILL NOT BE TESTED' ) * * End of SBLAT3. * END SUBROUTINE SCHK1( SNAME, EPS, THRESH, NOUT, NTRA, TRACE, REWI, $ FATAL, NIDIM, IDIM, NALF, ALF, NBET, BET, NMAX, $ A, AA, AS, B, BB, BS, C, CC, CS, CT, G ) * * Tests SGEMM. * * Auxiliary routine for test program for Level 3 Blas. * * -- Written on 8-February-1989. * Jack Dongarra, Argonne National Laboratory. * Iain Duff, AERE Harwell. * Jeremy Du Croz, Numerical Algorithms Group Ltd. * Sven Hammarling, Numerical Algorithms Group Ltd. * * .. Parameters .. REAL ZERO PARAMETER ( ZERO = 0.0 ) * .. Scalar Arguments .. REAL EPS, THRESH INTEGER NALF, NBET, NIDIM, NMAX, NOUT, NTRA LOGICAL FATAL, REWI, TRACE CHARACTER*6 SNAME * .. Array Arguments .. REAL A( NMAX, NMAX ), AA( NMAX*NMAX ), ALF( NALF ), $ AS( NMAX*NMAX ), B( NMAX, NMAX ), $ BB( NMAX*NMAX ), BET( NBET ), BS( NMAX*NMAX ), $ C( NMAX, NMAX ), CC( NMAX*NMAX ), $ CS( NMAX*NMAX ), CT( NMAX ), G( NMAX ) INTEGER IDIM( NIDIM ) * .. Local Scalars .. REAL ALPHA, ALS, BETA, BLS, ERR, ERRMAX INTEGER I, IA, IB, ICA, ICB, IK, IM, IN, K, KS, LAA, $ LBB, LCC, LDA, LDAS, LDB, LDBS, LDC, LDCS, M, $ MA, MB, MS, N, NA, NARGS, NB, NC, NS LOGICAL NULL, RESET, SAME, TRANA, TRANB CHARACTER*1 TRANAS, TRANBS, TRANSA, TRANSB CHARACTER*3 ICH * .. Local Arrays .. LOGICAL ISAME( 13 ) * .. External Functions .. LOGICAL LSE, LSERES EXTERNAL LSE, LSERES * .. External Subroutines .. EXTERNAL SGEMM, SMAKE, SMMCH * .. Intrinsic Functions .. INTRINSIC MAX * .. Scalars in Common .. INTEGER INFOT, NOUTC LOGICAL LERR, OK * .. Common blocks .. COMMON /INFOC/INFOT, NOUTC, OK, LERR * .. Data statements .. DATA ICH/'NTC'/ * .. Executable Statements .. * NARGS = 13 NC = 0 RESET = .TRUE. ERRMAX = ZERO * DO 110 IM = 1, NIDIM M = IDIM( IM ) * DO 100 IN = 1, NIDIM N = IDIM( IN ) * Set LDC to 1 more than minimum value if room. LDC = M IF( LDC.LT.NMAX ) $ LDC = LDC + 1 * Skip tests if not enough room. IF( LDC.GT.NMAX ) $ GO TO 100 LCC = LDC*N NULL = N.LE.0.OR.M.LE.0 * DO 90 IK = 1, NIDIM K = IDIM( IK ) * DO 80 ICA = 1, 3 TRANSA = ICH( ICA: ICA ) TRANA = TRANSA.EQ.'T'.OR.TRANSA.EQ.'C' * IF( TRANA )THEN MA = K NA = M ELSE MA = M NA = K END IF * Set LDA to 1 more than minimum value if room. LDA = MA IF( LDA.LT.NMAX ) $ LDA = LDA + 1 * Skip tests if not enough room. IF( LDA.GT.NMAX ) $ GO TO 80 LAA = LDA*NA * * Generate the matrix A. * CALL SMAKE( 'GE', ' ', ' ', MA, NA, A, NMAX, AA, LDA, $ RESET, ZERO ) * DO 70 ICB = 1, 3 TRANSB = ICH( ICB: ICB ) TRANB = TRANSB.EQ.'T'.OR.TRANSB.EQ.'C' * IF( TRANB )THEN MB = N NB = K ELSE MB = K NB = N END IF * Set LDB to 1 more than minimum value if room. LDB = MB IF( LDB.LT.NMAX ) $ LDB = LDB + 1 * Skip tests if not enough room. IF( LDB.GT.NMAX ) $ GO TO 70 LBB = LDB*NB * * Generate the matrix B. * CALL SMAKE( 'GE', ' ', ' ', MB, NB, B, NMAX, BB, $ LDB, RESET, ZERO ) * DO 60 IA = 1, NALF ALPHA = ALF( IA ) * DO 50 IB = 1, NBET BETA = BET( IB ) * * Generate the matrix C. * CALL SMAKE( 'GE', ' ', ' ', M, N, C, NMAX, $ CC, LDC, RESET, ZERO ) * NC = NC + 1 * * Save every datum before calling the * subroutine. * TRANAS = TRANSA TRANBS = TRANSB MS = M NS = N KS = K ALS = ALPHA DO 10 I = 1, LAA AS( I ) = AA( I ) 10 CONTINUE LDAS = LDA DO 20 I = 1, LBB BS( I ) = BB( I ) 20 CONTINUE LDBS = LDB BLS = BETA DO 30 I = 1, LCC CS( I ) = CC( I ) 30 CONTINUE LDCS = LDC * * Call the subroutine. * IF( TRACE ) $ WRITE( NTRA, FMT = 9995 )NC, SNAME, $ TRANSA, TRANSB, M, N, K, ALPHA, LDA, LDB, $ BETA, LDC IF( REWI ) $ REWIND NTRA CALL SGEMM( TRANSA, TRANSB, M, N, K, ALPHA, $ AA, LDA, BB, LDB, BETA, CC, LDC ) * * Check if error-exit was taken incorrectly. * IF( .NOT.OK )THEN WRITE( NOUT, FMT = 9994 ) FATAL = .TRUE. GO TO 120 END IF * * See what data changed inside subroutines. * ISAME( 1 ) = TRANSA.EQ.TRANAS ISAME( 2 ) = TRANSB.EQ.TRANBS ISAME( 3 ) = MS.EQ.M ISAME( 4 ) = NS.EQ.N ISAME( 5 ) = KS.EQ.K ISAME( 6 ) = ALS.EQ.ALPHA ISAME( 7 ) = LSE( AS, AA, LAA ) ISAME( 8 ) = LDAS.EQ.LDA ISAME( 9 ) = LSE( BS, BB, LBB ) ISAME( 10 ) = LDBS.EQ.LDB ISAME( 11 ) = BLS.EQ.BETA IF( NULL )THEN ISAME( 12 ) = LSE( CS, CC, LCC ) ELSE ISAME( 12 ) = LSERES( 'GE', ' ', M, N, CS, $ CC, LDC ) END IF ISAME( 13 ) = LDCS.EQ.LDC * * If data was incorrectly changed, report * and return. * SAME = .TRUE. DO 40 I = 1, NARGS SAME = SAME.AND.ISAME( I ) IF( .NOT.ISAME( I ) ) $ WRITE( NOUT, FMT = 9998 )I 40 CONTINUE IF( .NOT.SAME )THEN FATAL = .TRUE. GO TO 120 END IF * IF( .NOT.NULL )THEN * * Check the result. * CALL SMMCH( TRANSA, TRANSB, M, N, K, $ ALPHA, A, NMAX, B, NMAX, BETA, $ C, NMAX, CT, G, CC, LDC, EPS, $ ERR, FATAL, NOUT, .TRUE. ) ERRMAX = MAX( ERRMAX, ERR ) * If got really bad answer, report and * return. IF( FATAL ) $ GO TO 120 END IF * 50 CONTINUE * 60 CONTINUE * 70 CONTINUE * 80 CONTINUE * 90 CONTINUE * 100 CONTINUE * 110 CONTINUE * * Report result. * IF( ERRMAX.LT.THRESH )THEN WRITE( NOUT, FMT = 9999 )SNAME, NC ELSE WRITE( NOUT, FMT = 9997 )SNAME, NC, ERRMAX END IF GO TO 130 * 120 CONTINUE WRITE( NOUT, FMT = 9996 )SNAME WRITE( NOUT, FMT = 9995 )NC, SNAME, TRANSA, TRANSB, M, N, K, $ ALPHA, LDA, LDB, BETA, LDC * 130 CONTINUE RETURN * 9999 FORMAT( ' ', A6, ' PASSED THE COMPUTATIONAL TESTS (', I6, ' CALL', $ 'S)' ) 9998 FORMAT( ' ******* FATAL ERROR - PARAMETER NUMBER ', I2, ' WAS CH', $ 'ANGED INCORRECTLY *******' ) 9997 FORMAT( ' ', A6, ' COMPLETED THE COMPUTATIONAL TESTS (', I6, ' C', $ 'ALLS)', /' ******* BUT WITH MAXIMUM TEST RATIO', F8.2, $ ' - SUSPECT *******' ) 9996 FORMAT( ' ******* ', A6, ' FAILED ON CALL NUMBER:' ) 9995 FORMAT( 1X, I6, ': ', A6, '(''', A1, ''',''', A1, ''',', $ 3( I3, ',' ), F4.1, ', A,', I3, ', B,', I3, ',', F4.1, ', ', $ 'C,', I3, ').' ) 9994 FORMAT( ' ******* FATAL ERROR - ERROR-EXIT TAKEN ON VALID CALL *', $ '******' ) * * End of SCHK1. * END SUBROUTINE SCHK2( SNAME, EPS, THRESH, NOUT, NTRA, TRACE, REWI, $ FATAL, NIDIM, IDIM, NALF, ALF, NBET, BET, NMAX, $ A, AA, AS, B, BB, BS, C, CC, CS, CT, G ) * * Tests SSYMM. * * Auxiliary routine for test program for Level 3 Blas. * * -- Written on 8-February-1989. * Jack Dongarra, Argonne National Laboratory. * Iain Duff, AERE Harwell. * Jeremy Du Croz, Numerical Algorithms Group Ltd. * Sven Hammarling, Numerical Algorithms Group Ltd. * * .. Parameters .. REAL ZERO PARAMETER ( ZERO = 0.0 ) * .. Scalar Arguments .. REAL EPS, THRESH INTEGER NALF, NBET, NIDIM, NMAX, NOUT, NTRA LOGICAL FATAL, REWI, TRACE CHARACTER*6 SNAME * .. Array Arguments .. REAL A( NMAX, NMAX ), AA( NMAX*NMAX ), ALF( NALF ), $ AS( NMAX*NMAX ), B( NMAX, NMAX ), $ BB( NMAX*NMAX ), BET( NBET ), BS( NMAX*NMAX ), $ C( NMAX, NMAX ), CC( NMAX*NMAX ), $ CS( NMAX*NMAX ), CT( NMAX ), G( NMAX ) INTEGER IDIM( NIDIM ) * .. Local Scalars .. REAL ALPHA, ALS, BETA, BLS, ERR, ERRMAX INTEGER I, IA, IB, ICS, ICU, IM, IN, LAA, LBB, LCC, $ LDA, LDAS, LDB, LDBS, LDC, LDCS, M, MS, N, NA, $ NARGS, NC, NS LOGICAL LEFT, NULL, RESET, SAME CHARACTER*1 SIDE, SIDES, UPLO, UPLOS CHARACTER*2 ICHS, ICHU * .. Local Arrays .. LOGICAL ISAME( 13 ) * .. External Functions .. LOGICAL LSE, LSERES EXTERNAL LSE, LSERES * .. External Subroutines .. EXTERNAL SMAKE, SMMCH, SSYMM * .. Intrinsic Functions .. INTRINSIC MAX * .. Scalars in Common .. INTEGER INFOT, NOUTC LOGICAL LERR, OK * .. Common blocks .. COMMON /INFOC/INFOT, NOUTC, OK, LERR * .. Data statements .. DATA ICHS/'LR'/, ICHU/'UL'/ * .. Executable Statements .. * NARGS = 12 NC = 0 RESET = .TRUE. ERRMAX = ZERO * DO 100 IM = 1, NIDIM M = IDIM( IM ) * DO 90 IN = 1, NIDIM N = IDIM( IN ) * Set LDC to 1 more than minimum value if room. LDC = M IF( LDC.LT.NMAX ) $ LDC = LDC + 1 * Skip tests if not enough room. IF( LDC.GT.NMAX ) $ GO TO 90 LCC = LDC*N NULL = N.LE.0.OR.M.LE.0 * * Set LDB to 1 more than minimum value if room. LDB = M IF( LDB.LT.NMAX ) $ LDB = LDB + 1 * Skip tests if not enough room. IF( LDB.GT.NMAX ) $ GO TO 90 LBB = LDB*N * * Generate the matrix B. * CALL SMAKE( 'GE', ' ', ' ', M, N, B, NMAX, BB, LDB, RESET, $ ZERO ) * DO 80 ICS = 1, 2 SIDE = ICHS( ICS: ICS ) LEFT = SIDE.EQ.'L' * IF( LEFT )THEN NA = M ELSE NA = N END IF * Set LDA to 1 more than minimum value if room. LDA = NA IF( LDA.LT.NMAX ) $ LDA = LDA + 1 * Skip tests if not enough room. IF( LDA.GT.NMAX ) $ GO TO 80 LAA = LDA*NA * DO 70 ICU = 1, 2 UPLO = ICHU( ICU: ICU ) * * Generate the symmetric matrix A. * CALL SMAKE( 'SY', UPLO, ' ', NA, NA, A, NMAX, AA, LDA, $ RESET, ZERO ) * DO 60 IA = 1, NALF ALPHA = ALF( IA ) * DO 50 IB = 1, NBET BETA = BET( IB ) * * Generate the matrix C. * CALL SMAKE( 'GE', ' ', ' ', M, N, C, NMAX, CC, $ LDC, RESET, ZERO ) * NC = NC + 1 * * Save every datum before calling the * subroutine. * SIDES = SIDE UPLOS = UPLO MS = M NS = N ALS = ALPHA DO 10 I = 1, LAA AS( I ) = AA( I ) 10 CONTINUE LDAS = LDA DO 20 I = 1, LBB BS( I ) = BB( I ) 20 CONTINUE LDBS = LDB BLS = BETA DO 30 I = 1, LCC CS( I ) = CC( I ) 30 CONTINUE LDCS = LDC * * Call the subroutine. * IF( TRACE ) $ WRITE( NTRA, FMT = 9995 )NC, SNAME, SIDE, $ UPLO, M, N, ALPHA, LDA, LDB, BETA, LDC IF( REWI ) $ REWIND NTRA CALL SSYMM( SIDE, UPLO, M, N, ALPHA, AA, LDA, $ BB, LDB, BETA, CC, LDC ) * * Check if error-exit was taken incorrectly. * IF( .NOT.OK )THEN WRITE( NOUT, FMT = 9994 ) FATAL = .TRUE. GO TO 110 END IF * * See what data changed inside subroutines. * ISAME( 1 ) = SIDES.EQ.SIDE ISAME( 2 ) = UPLOS.EQ.UPLO ISAME( 3 ) = MS.EQ.M ISAME( 4 ) = NS.EQ.N ISAME( 5 ) = ALS.EQ.ALPHA ISAME( 6 ) = LSE( AS, AA, LAA ) ISAME( 7 ) = LDAS.EQ.LDA ISAME( 8 ) = LSE( BS, BB, LBB ) ISAME( 9 ) = LDBS.EQ.LDB ISAME( 10 ) = BLS.EQ.BETA IF( NULL )THEN ISAME( 11 ) = LSE( CS, CC, LCC ) ELSE ISAME( 11 ) = LSERES( 'GE', ' ', M, N, CS, $ CC, LDC ) END IF ISAME( 12 ) = LDCS.EQ.LDC * * If data was incorrectly changed, report and * return. * SAME = .TRUE. DO 40 I = 1, NARGS SAME = SAME.AND.ISAME( I ) IF( .NOT.ISAME( I ) ) $ WRITE( NOUT, FMT = 9998 )I 40 CONTINUE IF( .NOT.SAME )THEN FATAL = .TRUE. GO TO 110 END IF * IF( .NOT.NULL )THEN * * Check the result. * IF( LEFT )THEN CALL SMMCH( 'N', 'N', M, N, M, ALPHA, A, $ NMAX, B, NMAX, BETA, C, NMAX, $ CT, G, CC, LDC, EPS, ERR, $ FATAL, NOUT, .TRUE. ) ELSE CALL SMMCH( 'N', 'N', M, N, N, ALPHA, B, $ NMAX, A, NMAX, BETA, C, NMAX, $ CT, G, CC, LDC, EPS, ERR, $ FATAL, NOUT, .TRUE. ) END IF ERRMAX = MAX( ERRMAX, ERR ) * If got really bad answer, report and * return. IF( FATAL ) $ GO TO 110 END IF * 50 CONTINUE * 60 CONTINUE * 70 CONTINUE * 80 CONTINUE * 90 CONTINUE * 100 CONTINUE * * Report result. * IF( ERRMAX.LT.THRESH )THEN WRITE( NOUT, FMT = 9999 )SNAME, NC ELSE WRITE( NOUT, FMT = 9997 )SNAME, NC, ERRMAX END IF GO TO 120 * 110 CONTINUE WRITE( NOUT, FMT = 9996 )SNAME WRITE( NOUT, FMT = 9995 )NC, SNAME, SIDE, UPLO, M, N, ALPHA, LDA, $ LDB, BETA, LDC * 120 CONTINUE RETURN * 9999 FORMAT( ' ', A6, ' PASSED THE COMPUTATIONAL TESTS (', I6, ' CALL', $ 'S)' ) 9998 FORMAT( ' ******* FATAL ERROR - PARAMETER NUMBER ', I2, ' WAS CH', $ 'ANGED INCORRECTLY *******' ) 9997 FORMAT( ' ', A6, ' COMPLETED THE COMPUTATIONAL TESTS (', I6, ' C', $ 'ALLS)', /' ******* BUT WITH MAXIMUM TEST RATIO', F8.2, $ ' - SUSPECT *******' ) 9996 FORMAT( ' ******* ', A6, ' FAILED ON CALL NUMBER:' ) 9995 FORMAT( 1X, I6, ': ', A6, '(', 2( '''', A1, ''',' ), 2( I3, ',' ), $ F4.1, ', A,', I3, ', B,', I3, ',', F4.1, ', C,', I3, ') ', $ ' .' ) 9994 FORMAT( ' ******* FATAL ERROR - ERROR-EXIT TAKEN ON VALID CALL *', $ '******' ) * * End of SCHK2. * END SUBROUTINE SCHK3( SNAME, EPS, THRESH, NOUT, NTRA, TRACE, REWI, $ FATAL, NIDIM, IDIM, NALF, ALF, NMAX, A, AA, AS, $ B, BB, BS, CT, G, C ) * * Tests STRMM and STRSM. * * Auxiliary routine for test program for Level 3 Blas. * * -- Written on 8-February-1989. * Jack Dongarra, Argonne National Laboratory. * Iain Duff, AERE Harwell. * Jeremy Du Croz, Numerical Algorithms Group Ltd. * Sven Hammarling, Numerical Algorithms Group Ltd. * * .. Parameters .. REAL ZERO, ONE PARAMETER ( ZERO = 0.0, ONE = 1.0 ) * .. Scalar Arguments .. REAL EPS, THRESH INTEGER NALF, NIDIM, NMAX, NOUT, NTRA LOGICAL FATAL, REWI, TRACE CHARACTER*6 SNAME * .. Array Arguments .. REAL A( NMAX, NMAX ), AA( NMAX*NMAX ), ALF( NALF ), $ AS( NMAX*NMAX ), B( NMAX, NMAX ), $ BB( NMAX*NMAX ), BS( NMAX*NMAX ), $ C( NMAX, NMAX ), CT( NMAX ), G( NMAX ) INTEGER IDIM( NIDIM ) * .. Local Scalars .. REAL ALPHA, ALS, ERR, ERRMAX INTEGER I, IA, ICD, ICS, ICT, ICU, IM, IN, J, LAA, LBB, $ LDA, LDAS, LDB, LDBS, M, MS, N, NA, NARGS, NC, $ NS LOGICAL LEFT, NULL, RESET, SAME CHARACTER*1 DIAG, DIAGS, SIDE, SIDES, TRANAS, TRANSA, UPLO, $ UPLOS CHARACTER*2 ICHD, ICHS, ICHU CHARACTER*3 ICHT * .. Local Arrays .. LOGICAL ISAME( 13 ) * .. External Functions .. LOGICAL LSE, LSERES EXTERNAL LSE, LSERES * .. External Subroutines .. EXTERNAL SMAKE, SMMCH, STRMM, STRSM * .. Intrinsic Functions .. INTRINSIC MAX * .. Scalars in Common .. INTEGER INFOT, NOUTC LOGICAL LERR, OK * .. Common blocks .. COMMON /INFOC/INFOT, NOUTC, OK, LERR * .. Data statements .. DATA ICHU/'UL'/, ICHT/'NTC'/, ICHD/'UN'/, ICHS/'LR'/ * .. Executable Statements .. * NARGS = 11 NC = 0 RESET = .TRUE. ERRMAX = ZERO * Set up zero matrix for SMMCH. DO 20 J = 1, NMAX DO 10 I = 1, NMAX C( I, J ) = ZERO 10 CONTINUE 20 CONTINUE * DO 140 IM = 1, NIDIM M = IDIM( IM ) * DO 130 IN = 1, NIDIM N = IDIM( IN ) * Set LDB to 1 more than minimum value if room. LDB = M IF( LDB.LT.NMAX ) $ LDB = LDB + 1 * Skip tests if not enough room. IF( LDB.GT.NMAX ) $ GO TO 130 LBB = LDB*N NULL = M.LE.0.OR.N.LE.0 * DO 120 ICS = 1, 2 SIDE = ICHS( ICS: ICS ) LEFT = SIDE.EQ.'L' IF( LEFT )THEN NA = M ELSE NA = N END IF * Set LDA to 1 more than minimum value if room. LDA = NA IF( LDA.LT.NMAX ) $ LDA = LDA + 1 * Skip tests if not enough room. IF( LDA.GT.NMAX ) $ GO TO 130 LAA = LDA*NA * DO 110 ICU = 1, 2 UPLO = ICHU( ICU: ICU ) * DO 100 ICT = 1, 3 TRANSA = ICHT( ICT: ICT ) * DO 90 ICD = 1, 2 DIAG = ICHD( ICD: ICD ) * DO 80 IA = 1, NALF ALPHA = ALF( IA ) * * Generate the matrix A. * CALL SMAKE( 'TR', UPLO, DIAG, NA, NA, A, $ NMAX, AA, LDA, RESET, ZERO ) * * Generate the matrix B. * CALL SMAKE( 'GE', ' ', ' ', M, N, B, NMAX, $ BB, LDB, RESET, ZERO ) * NC = NC + 1 * * Save every datum before calling the * subroutine. * SIDES = SIDE UPLOS = UPLO TRANAS = TRANSA DIAGS = DIAG MS = M NS = N ALS = ALPHA DO 30 I = 1, LAA AS( I ) = AA( I ) 30 CONTINUE LDAS = LDA DO 40 I = 1, LBB BS( I ) = BB( I ) 40 CONTINUE LDBS = LDB * * Call the subroutine. * IF( SNAME( 4: 5 ).EQ.'MM' )THEN IF( TRACE ) $ WRITE( NTRA, FMT = 9995 )NC, SNAME, $ SIDE, UPLO, TRANSA, DIAG, M, N, ALPHA, $ LDA, LDB IF( REWI ) $ REWIND NTRA CALL STRMM( SIDE, UPLO, TRANSA, DIAG, M, $ N, ALPHA, AA, LDA, BB, LDB ) ELSE IF( SNAME( 4: 5 ).EQ.'SM' )THEN IF( TRACE ) $ WRITE( NTRA, FMT = 9995 )NC, SNAME, $ SIDE, UPLO, TRANSA, DIAG, M, N, ALPHA, $ LDA, LDB IF( REWI ) $ REWIND NTRA CALL STRSM( SIDE, UPLO, TRANSA, DIAG, M, $ N, ALPHA, AA, LDA, BB, LDB ) END IF * * Check if error-exit was taken incorrectly. * IF( .NOT.OK )THEN WRITE( NOUT, FMT = 9994 ) FATAL = .TRUE. GO TO 150 END IF * * See what data changed inside subroutines. * ISAME( 1 ) = SIDES.EQ.SIDE ISAME( 2 ) = UPLOS.EQ.UPLO ISAME( 3 ) = TRANAS.EQ.TRANSA ISAME( 4 ) = DIAGS.EQ.DIAG ISAME( 5 ) = MS.EQ.M ISAME( 6 ) = NS.EQ.N ISAME( 7 ) = ALS.EQ.ALPHA ISAME( 8 ) = LSE( AS, AA, LAA ) ISAME( 9 ) = LDAS.EQ.LDA IF( NULL )THEN ISAME( 10 ) = LSE( BS, BB, LBB ) ELSE ISAME( 10 ) = LSERES( 'GE', ' ', M, N, BS, $ BB, LDB ) END IF ISAME( 11 ) = LDBS.EQ.LDB * * If data was incorrectly changed, report and * return. * SAME = .TRUE. DO 50 I = 1, NARGS SAME = SAME.AND.ISAME( I ) IF( .NOT.ISAME( I ) ) $ WRITE( NOUT, FMT = 9998 )I 50 CONTINUE IF( .NOT.SAME )THEN FATAL = .TRUE. GO TO 150 END IF * IF( .NOT.NULL )THEN IF( SNAME( 4: 5 ).EQ.'MM' )THEN * * Check the result. * IF( LEFT )THEN CALL SMMCH( TRANSA, 'N', M, N, M, $ ALPHA, A, NMAX, B, NMAX, $ ZERO, C, NMAX, CT, G, $ BB, LDB, EPS, ERR, $ FATAL, NOUT, .TRUE. ) ELSE CALL SMMCH( 'N', TRANSA, M, N, N, $ ALPHA, B, NMAX, A, NMAX, $ ZERO, C, NMAX, CT, G, $ BB, LDB, EPS, ERR, $ FATAL, NOUT, .TRUE. ) END IF ELSE IF( SNAME( 4: 5 ).EQ.'SM' )THEN * * Compute approximation to original * matrix. * DO 70 J = 1, N DO 60 I = 1, M C( I, J ) = BB( I + ( J - 1 )* $ LDB ) BB( I + ( J - 1 )*LDB ) = ALPHA* $ B( I, J ) 60 CONTINUE 70 CONTINUE * IF( LEFT )THEN CALL SMMCH( TRANSA, 'N', M, N, M, $ ONE, A, NMAX, C, NMAX, $ ZERO, B, NMAX, CT, G, $ BB, LDB, EPS, ERR, $ FATAL, NOUT, .FALSE. ) ELSE CALL SMMCH( 'N', TRANSA, M, N, N, $ ONE, C, NMAX, A, NMAX, $ ZERO, B, NMAX, CT, G, $ BB, LDB, EPS, ERR, $ FATAL, NOUT, .FALSE. ) END IF END IF ERRMAX = MAX( ERRMAX, ERR ) * If got really bad answer, report and * return. IF( FATAL ) $ GO TO 150 END IF * 80 CONTINUE * 90 CONTINUE * 100 CONTINUE * 110 CONTINUE * 120 CONTINUE * 130 CONTINUE * 140 CONTINUE * * Report result. * IF( ERRMAX.LT.THRESH )THEN WRITE( NOUT, FMT = 9999 )SNAME, NC ELSE WRITE( NOUT, FMT = 9997 )SNAME, NC, ERRMAX END IF GO TO 160 * 150 CONTINUE WRITE( NOUT, FMT = 9996 )SNAME WRITE( NOUT, FMT = 9995 )NC, SNAME, SIDE, UPLO, TRANSA, DIAG, M, $ N, ALPHA, LDA, LDB * 160 CONTINUE RETURN * 9999 FORMAT( ' ', A6, ' PASSED THE COMPUTATIONAL TESTS (', I6, ' CALL', $ 'S)' ) 9998 FORMAT( ' ******* FATAL ERROR - PARAMETER NUMBER ', I2, ' WAS CH', $ 'ANGED INCORRECTLY *******' ) 9997 FORMAT( ' ', A6, ' COMPLETED THE COMPUTATIONAL TESTS (', I6, ' C', $ 'ALLS)', /' ******* BUT WITH MAXIMUM TEST RATIO', F8.2, $ ' - SUSPECT *******' ) 9996 FORMAT( ' ******* ', A6, ' FAILED ON CALL NUMBER:' ) 9995 FORMAT( 1X, I6, ': ', A6, '(', 4( '''', A1, ''',' ), 2( I3, ',' ), $ F4.1, ', A,', I3, ', B,', I3, ') .' ) 9994 FORMAT( ' ******* FATAL ERROR - ERROR-EXIT TAKEN ON VALID CALL *', $ '******' ) * * End of SCHK3. * END SUBROUTINE SCHK4( SNAME, EPS, THRESH, NOUT, NTRA, TRACE, REWI, $ FATAL, NIDIM, IDIM, NALF, ALF, NBET, BET, NMAX, $ A, AA, AS, B, BB, BS, C, CC, CS, CT, G ) * * Tests SSYRK. * * Auxiliary routine for test program for Level 3 Blas. * * -- Written on 8-February-1989. * Jack Dongarra, Argonne National Laboratory. * Iain Duff, AERE Harwell. * Jeremy Du Croz, Numerical Algorithms Group Ltd. * Sven Hammarling, Numerical Algorithms Group Ltd. * * .. Parameters .. REAL ZERO PARAMETER ( ZERO = 0.0 ) * .. Scalar Arguments .. REAL EPS, THRESH INTEGER NALF, NBET, NIDIM, NMAX, NOUT, NTRA LOGICAL FATAL, REWI, TRACE CHARACTER*6 SNAME * .. Array Arguments .. REAL A( NMAX, NMAX ), AA( NMAX*NMAX ), ALF( NALF ), $ AS( NMAX*NMAX ), B( NMAX, NMAX ), $ BB( NMAX*NMAX ), BET( NBET ), BS( NMAX*NMAX ), $ C( NMAX, NMAX ), CC( NMAX*NMAX ), $ CS( NMAX*NMAX ), CT( NMAX ), G( NMAX ) INTEGER IDIM( NIDIM ) * .. Local Scalars .. REAL ALPHA, ALS, BETA, BETS, ERR, ERRMAX INTEGER I, IA, IB, ICT, ICU, IK, IN, J, JC, JJ, K, KS, $ LAA, LCC, LDA, LDAS, LDC, LDCS, LJ, MA, N, NA, $ NARGS, NC, NS LOGICAL NULL, RESET, SAME, TRAN, UPPER CHARACTER*1 TRANS, TRANSS, UPLO, UPLOS CHARACTER*2 ICHU CHARACTER*3 ICHT * .. Local Arrays .. LOGICAL ISAME( 13 ) * .. External Functions .. LOGICAL LSE, LSERES EXTERNAL LSE, LSERES * .. External Subroutines .. EXTERNAL SMAKE, SMMCH, SSYRK * .. Intrinsic Functions .. INTRINSIC MAX * .. Scalars in Common .. INTEGER INFOT, NOUTC LOGICAL LERR, OK * .. Common blocks .. COMMON /INFOC/INFOT, NOUTC, OK, LERR * .. Data statements .. DATA ICHT/'NTC'/, ICHU/'UL'/ * .. Executable Statements .. * NARGS = 10 NC = 0 RESET = .TRUE. ERRMAX = ZERO * DO 100 IN = 1, NIDIM N = IDIM( IN ) * Set LDC to 1 more than minimum value if room. LDC = N IF( LDC.LT.NMAX ) $ LDC = LDC + 1 * Skip tests if not enough room. IF( LDC.GT.NMAX ) $ GO TO 100 LCC = LDC*N NULL = N.LE.0 * DO 90 IK = 1, NIDIM K = IDIM( IK ) * DO 80 ICT = 1, 3 TRANS = ICHT( ICT: ICT ) TRAN = TRANS.EQ.'T'.OR.TRANS.EQ.'C' IF( TRAN )THEN MA = K NA = N ELSE MA = N NA = K END IF * Set LDA to 1 more than minimum value if room. LDA = MA IF( LDA.LT.NMAX ) $ LDA = LDA + 1 * Skip tests if not enough room. IF( LDA.GT.NMAX ) $ GO TO 80 LAA = LDA*NA * * Generate the matrix A. * CALL SMAKE( 'GE', ' ', ' ', MA, NA, A, NMAX, AA, LDA, $ RESET, ZERO ) * DO 70 ICU = 1, 2 UPLO = ICHU( ICU: ICU ) UPPER = UPLO.EQ.'U' * DO 60 IA = 1, NALF ALPHA = ALF( IA ) * DO 50 IB = 1, NBET BETA = BET( IB ) * * Generate the matrix C. * CALL SMAKE( 'SY', UPLO, ' ', N, N, C, NMAX, CC, $ LDC, RESET, ZERO ) * NC = NC + 1 * * Save every datum before calling the subroutine. * UPLOS = UPLO TRANSS = TRANS NS = N KS = K ALS = ALPHA DO 10 I = 1, LAA AS( I ) = AA( I ) 10 CONTINUE LDAS = LDA BETS = BETA DO 20 I = 1, LCC CS( I ) = CC( I ) 20 CONTINUE LDCS = LDC * * Call the subroutine. * IF( TRACE ) $ WRITE( NTRA, FMT = 9994 )NC, SNAME, UPLO, $ TRANS, N, K, ALPHA, LDA, BETA, LDC IF( REWI ) $ REWIND NTRA CALL SSYRK( UPLO, TRANS, N, K, ALPHA, AA, LDA, $ BETA, CC, LDC ) * * Check if error-exit was taken incorrectly. * IF( .NOT.OK )THEN WRITE( NOUT, FMT = 9993 ) FATAL = .TRUE. GO TO 120 END IF * * See what data changed inside subroutines. * ISAME( 1 ) = UPLOS.EQ.UPLO ISAME( 2 ) = TRANSS.EQ.TRANS ISAME( 3 ) = NS.EQ.N ISAME( 4 ) = KS.EQ.K ISAME( 5 ) = ALS.EQ.ALPHA ISAME( 6 ) = LSE( AS, AA, LAA ) ISAME( 7 ) = LDAS.EQ.LDA ISAME( 8 ) = BETS.EQ.BETA IF( NULL )THEN ISAME( 9 ) = LSE( CS, CC, LCC ) ELSE ISAME( 9 ) = LSERES( 'SY', UPLO, N, N, CS, $ CC, LDC ) END IF ISAME( 10 ) = LDCS.EQ.LDC * * If data was incorrectly changed, report and * return. * SAME = .TRUE. DO 30 I = 1, NARGS SAME = SAME.AND.ISAME( I ) IF( .NOT.ISAME( I ) ) $ WRITE( NOUT, FMT = 9998 )I 30 CONTINUE IF( .NOT.SAME )THEN FATAL = .TRUE. GO TO 120 END IF * IF( .NOT.NULL )THEN * * Check the result column by column. * JC = 1 DO 40 J = 1, N IF( UPPER )THEN JJ = 1 LJ = J ELSE JJ = J LJ = N - J + 1 END IF IF( TRAN )THEN CALL SMMCH( 'T', 'N', LJ, 1, K, ALPHA, $ A( 1, JJ ), NMAX, $ A( 1, J ), NMAX, BETA, $ C( JJ, J ), NMAX, CT, G, $ CC( JC ), LDC, EPS, ERR, $ FATAL, NOUT, .TRUE. ) ELSE CALL SMMCH( 'N', 'T', LJ, 1, K, ALPHA, $ A( JJ, 1 ), NMAX, $ A( J, 1 ), NMAX, BETA, $ C( JJ, J ), NMAX, CT, G, $ CC( JC ), LDC, EPS, ERR, $ FATAL, NOUT, .TRUE. ) END IF IF( UPPER )THEN JC = JC + LDC ELSE JC = JC + LDC + 1 END IF ERRMAX = MAX( ERRMAX, ERR ) * If got really bad answer, report and * return. IF( FATAL ) $ GO TO 110 40 CONTINUE END IF * 50 CONTINUE * 60 CONTINUE * 70 CONTINUE * 80 CONTINUE * 90 CONTINUE * 100 CONTINUE * * Report result. * IF( ERRMAX.LT.THRESH )THEN WRITE( NOUT, FMT = 9999 )SNAME, NC ELSE WRITE( NOUT, FMT = 9997 )SNAME, NC, ERRMAX END IF GO TO 130 * 110 CONTINUE IF( N.GT.1 ) $ WRITE( NOUT, FMT = 9995 )J * 120 CONTINUE WRITE( NOUT, FMT = 9996 )SNAME WRITE( NOUT, FMT = 9994 )NC, SNAME, UPLO, TRANS, N, K, ALPHA, $ LDA, BETA, LDC * 130 CONTINUE RETURN * 9999 FORMAT( ' ', A6, ' PASSED THE COMPUTATIONAL TESTS (', I6, ' CALL', $ 'S)' ) 9998 FORMAT( ' ******* FATAL ERROR - PARAMETER NUMBER ', I2, ' WAS CH', $ 'ANGED INCORRECTLY *******' ) 9997 FORMAT( ' ', A6, ' COMPLETED THE COMPUTATIONAL TESTS (', I6, ' C', $ 'ALLS)', /' ******* BUT WITH MAXIMUM TEST RATIO', F8.2, $ ' - SUSPECT *******' ) 9996 FORMAT( ' ******* ', A6, ' FAILED ON CALL NUMBER:' ) 9995 FORMAT( ' THESE ARE THE RESULTS FOR COLUMN ', I3 ) 9994 FORMAT( 1X, I6, ': ', A6, '(', 2( '''', A1, ''',' ), 2( I3, ',' ), $ F4.1, ', A,', I3, ',', F4.1, ', C,', I3, ') .' ) 9993 FORMAT( ' ******* FATAL ERROR - ERROR-EXIT TAKEN ON VALID CALL *', $ '******' ) * * End of SCHK4. * END SUBROUTINE SCHK5( SNAME, EPS, THRESH, NOUT, NTRA, TRACE, REWI, $ FATAL, NIDIM, IDIM, NALF, ALF, NBET, BET, NMAX, $ AB, AA, AS, BB, BS, C, CC, CS, CT, G, W ) * * Tests SSYR2K. * * Auxiliary routine for test program for Level 3 Blas. * * -- Written on 8-February-1989. * Jack Dongarra, Argonne National Laboratory. * Iain Duff, AERE Harwell. * Jeremy Du Croz, Numerical Algorithms Group Ltd. * Sven Hammarling, Numerical Algorithms Group Ltd. * * .. Parameters .. REAL ZERO PARAMETER ( ZERO = 0.0 ) * .. Scalar Arguments .. REAL EPS, THRESH INTEGER NALF, NBET, NIDIM, NMAX, NOUT, NTRA LOGICAL FATAL, REWI, TRACE CHARACTER*6 SNAME * .. Array Arguments .. REAL AA( NMAX*NMAX ), AB( 2*NMAX*NMAX ), $ ALF( NALF ), AS( NMAX*NMAX ), BB( NMAX*NMAX ), $ BET( NBET ), BS( NMAX*NMAX ), C( NMAX, NMAX ), $ CC( NMAX*NMAX ), CS( NMAX*NMAX ), CT( NMAX ), $ G( NMAX ), W( 2*NMAX ) INTEGER IDIM( NIDIM ) * .. Local Scalars .. REAL ALPHA, ALS, BETA, BETS, ERR, ERRMAX INTEGER I, IA, IB, ICT, ICU, IK, IN, J, JC, JJ, JJAB, $ K, KS, LAA, LBB, LCC, LDA, LDAS, LDB, LDBS, $ LDC, LDCS, LJ, MA, N, NA, NARGS, NC, NS LOGICAL NULL, RESET, SAME, TRAN, UPPER CHARACTER*1 TRANS, TRANSS, UPLO, UPLOS CHARACTER*2 ICHU CHARACTER*3 ICHT * .. Local Arrays .. LOGICAL ISAME( 13 ) * .. External Functions .. LOGICAL LSE, LSERES EXTERNAL LSE, LSERES * .. External Subroutines .. EXTERNAL SMAKE, SMMCH, SSYR2K * .. Intrinsic Functions .. INTRINSIC MAX * .. Scalars in Common .. INTEGER INFOT, NOUTC LOGICAL LERR, OK * .. Common blocks .. COMMON /INFOC/INFOT, NOUTC, OK, LERR * .. Data statements .. DATA ICHT/'NTC'/, ICHU/'UL'/ * .. Executable Statements .. * NARGS = 12 NC = 0 RESET = .TRUE. ERRMAX = ZERO * DO 130 IN = 1, NIDIM N = IDIM( IN ) * Set LDC to 1 more than minimum value if room. LDC = N IF( LDC.LT.NMAX ) $ LDC = LDC + 1 * Skip tests if not enough room. IF( LDC.GT.NMAX ) $ GO TO 130 LCC = LDC*N NULL = N.LE.0 * DO 120 IK = 1, NIDIM K = IDIM( IK ) * DO 110 ICT = 1, 3 TRANS = ICHT( ICT: ICT ) TRAN = TRANS.EQ.'T'.OR.TRANS.EQ.'C' IF( TRAN )THEN MA = K NA = N ELSE MA = N NA = K END IF * Set LDA to 1 more than minimum value if room. LDA = MA IF( LDA.LT.NMAX ) $ LDA = LDA + 1 * Skip tests if not enough room. IF( LDA.GT.NMAX ) $ GO TO 110 LAA = LDA*NA * * Generate the matrix A. * IF( TRAN )THEN CALL SMAKE( 'GE', ' ', ' ', MA, NA, AB, 2*NMAX, AA, $ LDA, RESET, ZERO ) ELSE CALL SMAKE( 'GE', ' ', ' ', MA, NA, AB, NMAX, AA, LDA, $ RESET, ZERO ) END IF * * Generate the matrix B. * LDB = LDA LBB = LAA IF( TRAN )THEN CALL SMAKE( 'GE', ' ', ' ', MA, NA, AB( K + 1 ), $ 2*NMAX, BB, LDB, RESET, ZERO ) ELSE CALL SMAKE( 'GE', ' ', ' ', MA, NA, AB( K*NMAX + 1 ), $ NMAX, BB, LDB, RESET, ZERO ) END IF * DO 100 ICU = 1, 2 UPLO = ICHU( ICU: ICU ) UPPER = UPLO.EQ.'U' * DO 90 IA = 1, NALF ALPHA = ALF( IA ) * DO 80 IB = 1, NBET BETA = BET( IB ) * * Generate the matrix C. * CALL SMAKE( 'SY', UPLO, ' ', N, N, C, NMAX, CC, $ LDC, RESET, ZERO ) * NC = NC + 1 * * Save every datum before calling the subroutine. * UPLOS = UPLO TRANSS = TRANS NS = N KS = K ALS = ALPHA DO 10 I = 1, LAA AS( I ) = AA( I ) 10 CONTINUE LDAS = LDA DO 20 I = 1, LBB BS( I ) = BB( I ) 20 CONTINUE LDBS = LDB BETS = BETA DO 30 I = 1, LCC CS( I ) = CC( I ) 30 CONTINUE LDCS = LDC * * Call the subroutine. * IF( TRACE ) $ WRITE( NTRA, FMT = 9994 )NC, SNAME, UPLO, $ TRANS, N, K, ALPHA, LDA, LDB, BETA, LDC IF( REWI ) $ REWIND NTRA CALL SSYR2K( UPLO, TRANS, N, K, ALPHA, AA, LDA, $ BB, LDB, BETA, CC, LDC ) * * Check if error-exit was taken incorrectly. * IF( .NOT.OK )THEN WRITE( NOUT, FMT = 9993 ) FATAL = .TRUE. GO TO 150 END IF * * See what data changed inside subroutines. * ISAME( 1 ) = UPLOS.EQ.UPLO ISAME( 2 ) = TRANSS.EQ.TRANS ISAME( 3 ) = NS.EQ.N ISAME( 4 ) = KS.EQ.K ISAME( 5 ) = ALS.EQ.ALPHA ISAME( 6 ) = LSE( AS, AA, LAA ) ISAME( 7 ) = LDAS.EQ.LDA ISAME( 8 ) = LSE( BS, BB, LBB ) ISAME( 9 ) = LDBS.EQ.LDB ISAME( 10 ) = BETS.EQ.BETA IF( NULL )THEN ISAME( 11 ) = LSE( CS, CC, LCC ) ELSE ISAME( 11 ) = LSERES( 'SY', UPLO, N, N, CS, $ CC, LDC ) END IF ISAME( 12 ) = LDCS.EQ.LDC * * If data was incorrectly changed, report and * return. * SAME = .TRUE. DO 40 I = 1, NARGS SAME = SAME.AND.ISAME( I ) IF( .NOT.ISAME( I ) ) $ WRITE( NOUT, FMT = 9998 )I 40 CONTINUE IF( .NOT.SAME )THEN FATAL = .TRUE. GO TO 150 END IF * IF( .NOT.NULL )THEN * * Check the result column by column. * JJAB = 1 JC = 1 DO 70 J = 1, N IF( UPPER )THEN JJ = 1 LJ = J ELSE JJ = J LJ = N - J + 1 END IF IF( TRAN )THEN DO 50 I = 1, K W( I ) = AB( ( J - 1 )*2*NMAX + K + $ I ) W( K + I ) = AB( ( J - 1 )*2*NMAX + $ I ) 50 CONTINUE CALL SMMCH( 'T', 'N', LJ, 1, 2*K, $ ALPHA, AB( JJAB ), 2*NMAX, $ W, 2*NMAX, BETA, $ C( JJ, J ), NMAX, CT, G, $ CC( JC ), LDC, EPS, ERR, $ FATAL, NOUT, .TRUE. ) ELSE DO 60 I = 1, K W( I ) = AB( ( K + I - 1 )*NMAX + $ J ) W( K + I ) = AB( ( I - 1 )*NMAX + $ J ) 60 CONTINUE CALL SMMCH( 'N', 'N', LJ, 1, 2*K, $ ALPHA, AB( JJ ), NMAX, W, $ 2*NMAX, BETA, C( JJ, J ), $ NMAX, CT, G, CC( JC ), LDC, $ EPS, ERR, FATAL, NOUT, $ .TRUE. ) END IF IF( UPPER )THEN JC = JC + LDC ELSE JC = JC + LDC + 1 IF( TRAN ) $ JJAB = JJAB + 2*NMAX END IF ERRMAX = MAX( ERRMAX, ERR ) * If got really bad answer, report and * return. IF( FATAL ) $ GO TO 140 70 CONTINUE END IF * 80 CONTINUE * 90 CONTINUE * 100 CONTINUE * 110 CONTINUE * 120 CONTINUE * 130 CONTINUE * * Report result. * IF( ERRMAX.LT.THRESH )THEN WRITE( NOUT, FMT = 9999 )SNAME, NC ELSE WRITE( NOUT, FMT = 9997 )SNAME, NC, ERRMAX END IF GO TO 160 * 140 CONTINUE IF( N.GT.1 ) $ WRITE( NOUT, FMT = 9995 )J * 150 CONTINUE WRITE( NOUT, FMT = 9996 )SNAME WRITE( NOUT, FMT = 9994 )NC, SNAME, UPLO, TRANS, N, K, ALPHA, $ LDA, LDB, BETA, LDC * 160 CONTINUE RETURN * 9999 FORMAT( ' ', A6, ' PASSED THE COMPUTATIONAL TESTS (', I6, ' CALL', $ 'S)' ) 9998 FORMAT( ' ******* FATAL ERROR - PARAMETER NUMBER ', I2, ' WAS CH', $ 'ANGED INCORRECTLY *******' ) 9997 FORMAT( ' ', A6, ' COMPLETED THE COMPUTATIONAL TESTS (', I6, ' C', $ 'ALLS)', /' ******* BUT WITH MAXIMUM TEST RATIO', F8.2, $ ' - SUSPECT *******' ) 9996 FORMAT( ' ******* ', A6, ' FAILED ON CALL NUMBER:' ) 9995 FORMAT( ' THESE ARE THE RESULTS FOR COLUMN ', I3 ) 9994 FORMAT( 1X, I6, ': ', A6, '(', 2( '''', A1, ''',' ), 2( I3, ',' ), $ F4.1, ', A,', I3, ', B,', I3, ',', F4.1, ', C,', I3, ') ', $ ' .' ) 9993 FORMAT( ' ******* FATAL ERROR - ERROR-EXIT TAKEN ON VALID CALL *', $ '******' ) * * End of SCHK5. * END SUBROUTINE SCHKE( ISNUM, SRNAMT, NOUT ) * * Tests the error exits from the Level 3 Blas. * Requires a special version of the error-handling routine XERBLA. * A, B and C should not need to be defined. * * Auxiliary routine for test program for Level 3 Blas. * * -- Written on 8-February-1989. * Jack Dongarra, Argonne National Laboratory. * Iain Duff, AERE Harwell. * Jeremy Du Croz, Numerical Algorithms Group Ltd. * Sven Hammarling, Numerical Algorithms Group Ltd. * * 3-19-92: Initialize ALPHA and BETA (eca) * 3-19-92: Fix argument 12 in calls to SSYMM with INFOT = 9 (eca) * * .. Scalar Arguments .. INTEGER ISNUM, NOUT CHARACTER*6 SRNAMT * .. Scalars in Common .. INTEGER INFOT, NOUTC LOGICAL LERR, OK * .. Parameters .. REAL ONE, TWO PARAMETER ( ONE = 1.0E0, TWO = 2.0E0 ) * .. Local Scalars .. REAL ALPHA, BETA * .. Local Arrays .. REAL A( 2, 1 ), B( 2, 1 ), C( 2, 1 ) * .. External Subroutines .. EXTERNAL CHKXER, SGEMM, SSYMM, SSYR2K, SSYRK, STRMM, $ STRSM * .. Common blocks .. COMMON /INFOC/INFOT, NOUTC, OK, LERR * .. Executable Statements .. * OK is set to .FALSE. by the special version of XERBLA or by CHKXER * if anything is wrong. OK = .TRUE. * LERR is set to .TRUE. by the special version of XERBLA each time * it is called, and is then tested and re-set by CHKXER. LERR = .FALSE. * * Initialize ALPHA and BETA. * ALPHA = ONE BETA = TWO * GO TO ( 10, 20, 30, 40, 50, 60 )ISNUM 10 INFOT = 1 CALL SGEMM( '/', 'N', 0, 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 1 CALL SGEMM( '/', 'T', 0, 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL SGEMM( 'N', '/', 0, 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL SGEMM( 'T', '/', 0, 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL SGEMM( 'N', 'N', -1, 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL SGEMM( 'N', 'T', -1, 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL SGEMM( 'T', 'N', -1, 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL SGEMM( 'T', 'T', -1, 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL SGEMM( 'N', 'N', 0, -1, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL SGEMM( 'N', 'T', 0, -1, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL SGEMM( 'T', 'N', 0, -1, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL SGEMM( 'T', 'T', 0, -1, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL SGEMM( 'N', 'N', 0, 0, -1, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL SGEMM( 'N', 'T', 0, 0, -1, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL SGEMM( 'T', 'N', 0, 0, -1, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL SGEMM( 'T', 'T', 0, 0, -1, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 8 CALL SGEMM( 'N', 'N', 2, 0, 0, ALPHA, A, 1, B, 1, BETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 8 CALL SGEMM( 'N', 'T', 2, 0, 0, ALPHA, A, 1, B, 1, BETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 8 CALL SGEMM( 'T', 'N', 0, 0, 2, ALPHA, A, 1, B, 2, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 8 CALL SGEMM( 'T', 'T', 0, 0, 2, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 10 CALL SGEMM( 'N', 'N', 0, 0, 2, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 10 CALL SGEMM( 'T', 'N', 0, 0, 2, ALPHA, A, 2, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 10 CALL SGEMM( 'N', 'T', 0, 2, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 10 CALL SGEMM( 'T', 'T', 0, 2, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 13 CALL SGEMM( 'N', 'N', 2, 0, 0, ALPHA, A, 2, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 13 CALL SGEMM( 'N', 'T', 2, 0, 0, ALPHA, A, 2, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 13 CALL SGEMM( 'T', 'N', 2, 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 13 CALL SGEMM( 'T', 'T', 2, 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 70 20 INFOT = 1 CALL SSYMM( '/', 'U', 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL SSYMM( 'L', '/', 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL SSYMM( 'L', 'U', -1, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL SSYMM( 'R', 'U', -1, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL SSYMM( 'L', 'L', -1, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL SSYMM( 'R', 'L', -1, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL SSYMM( 'L', 'U', 0, -1, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL SSYMM( 'R', 'U', 0, -1, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL SSYMM( 'L', 'L', 0, -1, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL SSYMM( 'R', 'L', 0, -1, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL SSYMM( 'L', 'U', 2, 0, ALPHA, A, 1, B, 2, BETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL SSYMM( 'R', 'U', 0, 2, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL SSYMM( 'L', 'L', 2, 0, ALPHA, A, 1, B, 2, BETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL SSYMM( 'R', 'L', 0, 2, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL SSYMM( 'L', 'U', 2, 0, ALPHA, A, 2, B, 1, BETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL SSYMM( 'R', 'U', 2, 0, ALPHA, A, 1, B, 1, BETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL SSYMM( 'L', 'L', 2, 0, ALPHA, A, 2, B, 1, BETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL SSYMM( 'R', 'L', 2, 0, ALPHA, A, 1, B, 1, BETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 12 CALL SSYMM( 'L', 'U', 2, 0, ALPHA, A, 2, B, 2, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 12 CALL SSYMM( 'R', 'U', 2, 0, ALPHA, A, 1, B, 2, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 12 CALL SSYMM( 'L', 'L', 2, 0, ALPHA, A, 2, B, 2, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 12 CALL SSYMM( 'R', 'L', 2, 0, ALPHA, A, 1, B, 2, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 70 30 INFOT = 1 CALL STRMM( '/', 'U', 'N', 'N', 0, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL STRMM( 'L', '/', 'N', 'N', 0, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL STRMM( 'L', 'U', '/', 'N', 0, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL STRMM( 'L', 'U', 'N', '/', 0, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL STRMM( 'L', 'U', 'N', 'N', -1, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL STRMM( 'L', 'U', 'T', 'N', -1, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL STRMM( 'R', 'U', 'N', 'N', -1, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL STRMM( 'R', 'U', 'T', 'N', -1, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL STRMM( 'L', 'L', 'N', 'N', -1, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL STRMM( 'L', 'L', 'T', 'N', -1, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL STRMM( 'R', 'L', 'N', 'N', -1, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL STRMM( 'R', 'L', 'T', 'N', -1, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL STRMM( 'L', 'U', 'N', 'N', 0, -1, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL STRMM( 'L', 'U', 'T', 'N', 0, -1, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL STRMM( 'R', 'U', 'N', 'N', 0, -1, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL STRMM( 'R', 'U', 'T', 'N', 0, -1, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL STRMM( 'L', 'L', 'N', 'N', 0, -1, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL STRMM( 'L', 'L', 'T', 'N', 0, -1, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL STRMM( 'R', 'L', 'N', 'N', 0, -1, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL STRMM( 'R', 'L', 'T', 'N', 0, -1, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL STRMM( 'L', 'U', 'N', 'N', 2, 0, ALPHA, A, 1, B, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL STRMM( 'L', 'U', 'T', 'N', 2, 0, ALPHA, A, 1, B, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL STRMM( 'R', 'U', 'N', 'N', 0, 2, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL STRMM( 'R', 'U', 'T', 'N', 0, 2, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL STRMM( 'L', 'L', 'N', 'N', 2, 0, ALPHA, A, 1, B, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL STRMM( 'L', 'L', 'T', 'N', 2, 0, ALPHA, A, 1, B, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL STRMM( 'R', 'L', 'N', 'N', 0, 2, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL STRMM( 'R', 'L', 'T', 'N', 0, 2, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL STRMM( 'L', 'U', 'N', 'N', 2, 0, ALPHA, A, 2, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL STRMM( 'L', 'U', 'T', 'N', 2, 0, ALPHA, A, 2, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL STRMM( 'R', 'U', 'N', 'N', 2, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL STRMM( 'R', 'U', 'T', 'N', 2, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL STRMM( 'L', 'L', 'N', 'N', 2, 0, ALPHA, A, 2, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL STRMM( 'L', 'L', 'T', 'N', 2, 0, ALPHA, A, 2, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL STRMM( 'R', 'L', 'N', 'N', 2, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL STRMM( 'R', 'L', 'T', 'N', 2, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 70 40 INFOT = 1 CALL STRSM( '/', 'U', 'N', 'N', 0, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL STRSM( 'L', '/', 'N', 'N', 0, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL STRSM( 'L', 'U', '/', 'N', 0, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL STRSM( 'L', 'U', 'N', '/', 0, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL STRSM( 'L', 'U', 'N', 'N', -1, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL STRSM( 'L', 'U', 'T', 'N', -1, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL STRSM( 'R', 'U', 'N', 'N', -1, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL STRSM( 'R', 'U', 'T', 'N', -1, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL STRSM( 'L', 'L', 'N', 'N', -1, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL STRSM( 'L', 'L', 'T', 'N', -1, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL STRSM( 'R', 'L', 'N', 'N', -1, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL STRSM( 'R', 'L', 'T', 'N', -1, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL STRSM( 'L', 'U', 'N', 'N', 0, -1, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL STRSM( 'L', 'U', 'T', 'N', 0, -1, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL STRSM( 'R', 'U', 'N', 'N', 0, -1, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL STRSM( 'R', 'U', 'T', 'N', 0, -1, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL STRSM( 'L', 'L', 'N', 'N', 0, -1, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL STRSM( 'L', 'L', 'T', 'N', 0, -1, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL STRSM( 'R', 'L', 'N', 'N', 0, -1, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL STRSM( 'R', 'L', 'T', 'N', 0, -1, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL STRSM( 'L', 'U', 'N', 'N', 2, 0, ALPHA, A, 1, B, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL STRSM( 'L', 'U', 'T', 'N', 2, 0, ALPHA, A, 1, B, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL STRSM( 'R', 'U', 'N', 'N', 0, 2, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL STRSM( 'R', 'U', 'T', 'N', 0, 2, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL STRSM( 'L', 'L', 'N', 'N', 2, 0, ALPHA, A, 1, B, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL STRSM( 'L', 'L', 'T', 'N', 2, 0, ALPHA, A, 1, B, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL STRSM( 'R', 'L', 'N', 'N', 0, 2, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL STRSM( 'R', 'L', 'T', 'N', 0, 2, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL STRSM( 'L', 'U', 'N', 'N', 2, 0, ALPHA, A, 2, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL STRSM( 'L', 'U', 'T', 'N', 2, 0, ALPHA, A, 2, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL STRSM( 'R', 'U', 'N', 'N', 2, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL STRSM( 'R', 'U', 'T', 'N', 2, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL STRSM( 'L', 'L', 'N', 'N', 2, 0, ALPHA, A, 2, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL STRSM( 'L', 'L', 'T', 'N', 2, 0, ALPHA, A, 2, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL STRSM( 'R', 'L', 'N', 'N', 2, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL STRSM( 'R', 'L', 'T', 'N', 2, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 70 50 INFOT = 1 CALL SSYRK( '/', 'N', 0, 0, ALPHA, A, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL SSYRK( 'U', '/', 0, 0, ALPHA, A, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL SSYRK( 'U', 'N', -1, 0, ALPHA, A, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL SSYRK( 'U', 'T', -1, 0, ALPHA, A, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL SSYRK( 'L', 'N', -1, 0, ALPHA, A, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL SSYRK( 'L', 'T', -1, 0, ALPHA, A, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL SSYRK( 'U', 'N', 0, -1, ALPHA, A, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL SSYRK( 'U', 'T', 0, -1, ALPHA, A, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL SSYRK( 'L', 'N', 0, -1, ALPHA, A, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL SSYRK( 'L', 'T', 0, -1, ALPHA, A, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL SSYRK( 'U', 'N', 2, 0, ALPHA, A, 1, BETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL SSYRK( 'U', 'T', 0, 2, ALPHA, A, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL SSYRK( 'L', 'N', 2, 0, ALPHA, A, 1, BETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL SSYRK( 'L', 'T', 0, 2, ALPHA, A, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 10 CALL SSYRK( 'U', 'N', 2, 0, ALPHA, A, 2, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 10 CALL SSYRK( 'U', 'T', 2, 0, ALPHA, A, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 10 CALL SSYRK( 'L', 'N', 2, 0, ALPHA, A, 2, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 10 CALL SSYRK( 'L', 'T', 2, 0, ALPHA, A, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 70 60 INFOT = 1 CALL SSYR2K( '/', 'N', 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL SSYR2K( 'U', '/', 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL SSYR2K( 'U', 'N', -1, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL SSYR2K( 'U', 'T', -1, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL SSYR2K( 'L', 'N', -1, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL SSYR2K( 'L', 'T', -1, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL SSYR2K( 'U', 'N', 0, -1, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL SSYR2K( 'U', 'T', 0, -1, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL SSYR2K( 'L', 'N', 0, -1, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL SSYR2K( 'L', 'T', 0, -1, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL SSYR2K( 'U', 'N', 2, 0, ALPHA, A, 1, B, 1, BETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL SSYR2K( 'U', 'T', 0, 2, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL SSYR2K( 'L', 'N', 2, 0, ALPHA, A, 1, B, 1, BETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL SSYR2K( 'L', 'T', 0, 2, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL SSYR2K( 'U', 'N', 2, 0, ALPHA, A, 2, B, 1, BETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL SSYR2K( 'U', 'T', 0, 2, ALPHA, A, 2, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL SSYR2K( 'L', 'N', 2, 0, ALPHA, A, 2, B, 1, BETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL SSYR2K( 'L', 'T', 0, 2, ALPHA, A, 2, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 12 CALL SSYR2K( 'U', 'N', 2, 0, ALPHA, A, 2, B, 2, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 12 CALL SSYR2K( 'U', 'T', 2, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 12 CALL SSYR2K( 'L', 'N', 2, 0, ALPHA, A, 2, B, 2, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 12 CALL SSYR2K( 'L', 'T', 2, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) * 70 IF( OK )THEN WRITE( NOUT, FMT = 9999 )SRNAMT ELSE WRITE( NOUT, FMT = 9998 )SRNAMT END IF RETURN * 9999 FORMAT( ' ', A6, ' PASSED THE TESTS OF ERROR-EXITS' ) 9998 FORMAT( ' ******* ', A6, ' FAILED THE TESTS OF ERROR-EXITS *****', $ '**' ) * * End of SCHKE. * END SUBROUTINE SMAKE( TYPE, UPLO, DIAG, M, N, A, NMAX, AA, LDA, RESET, $ TRANSL ) * * Generates values for an M by N matrix A. * Stores the values in the array AA in the data structure required * by the routine, with unwanted elements set to rogue value. * * TYPE is 'GE', 'SY' or 'TR'. * * Auxiliary routine for test program for Level 3 Blas. * * -- Written on 8-February-1989. * Jack Dongarra, Argonne National Laboratory. * Iain Duff, AERE Harwell. * Jeremy Du Croz, Numerical Algorithms Group Ltd. * Sven Hammarling, Numerical Algorithms Group Ltd. * * .. Parameters .. REAL ZERO, ONE PARAMETER ( ZERO = 0.0, ONE = 1.0 ) REAL ROGUE PARAMETER ( ROGUE = -1.0E10 ) * .. Scalar Arguments .. REAL TRANSL INTEGER LDA, M, N, NMAX LOGICAL RESET CHARACTER*1 DIAG, UPLO CHARACTER*2 TYPE * .. Array Arguments .. REAL A( NMAX, * ), AA( * ) * .. Local Scalars .. INTEGER I, IBEG, IEND, J LOGICAL GEN, LOWER, SYM, TRI, UNIT, UPPER * .. External Functions .. REAL SBEG EXTERNAL SBEG * .. Executable Statements .. GEN = TYPE.EQ.'GE' SYM = TYPE.EQ.'SY' TRI = TYPE.EQ.'TR' UPPER = ( SYM.OR.TRI ).AND.UPLO.EQ.'U' LOWER = ( SYM.OR.TRI ).AND.UPLO.EQ.'L' UNIT = TRI.AND.DIAG.EQ.'U' * * Generate data in array A. * DO 20 J = 1, N DO 10 I = 1, M IF( GEN.OR.( UPPER.AND.I.LE.J ).OR.( LOWER.AND.I.GE.J ) ) $ THEN A( I, J ) = SBEG( RESET ) + TRANSL IF( I.NE.J )THEN * Set some elements to zero IF( N.GT.3.AND.J.EQ.N/2 ) $ A( I, J ) = ZERO IF( SYM )THEN A( J, I ) = A( I, J ) ELSE IF( TRI )THEN A( J, I ) = ZERO END IF END IF END IF 10 CONTINUE IF( TRI ) $ A( J, J ) = A( J, J ) + ONE IF( UNIT ) $ A( J, J ) = ONE 20 CONTINUE * * Store elements in array AS in data structure required by routine. * IF( TYPE.EQ.'GE' )THEN DO 50 J = 1, N DO 30 I = 1, M AA( I + ( J - 1 )*LDA ) = A( I, J ) 30 CONTINUE DO 40 I = M + 1, LDA AA( I + ( J - 1 )*LDA ) = ROGUE 40 CONTINUE 50 CONTINUE ELSE IF( TYPE.EQ.'SY'.OR.TYPE.EQ.'TR' )THEN DO 90 J = 1, N IF( UPPER )THEN IBEG = 1 IF( UNIT )THEN IEND = J - 1 ELSE IEND = J END IF ELSE IF( UNIT )THEN IBEG = J + 1 ELSE IBEG = J END IF IEND = N END IF DO 60 I = 1, IBEG - 1 AA( I + ( J - 1 )*LDA ) = ROGUE 60 CONTINUE DO 70 I = IBEG, IEND AA( I + ( J - 1 )*LDA ) = A( I, J ) 70 CONTINUE DO 80 I = IEND + 1, LDA AA( I + ( J - 1 )*LDA ) = ROGUE 80 CONTINUE 90 CONTINUE END IF RETURN * * End of SMAKE. * END SUBROUTINE SMMCH( TRANSA, TRANSB, M, N, KK, ALPHA, A, LDA, B, LDB, $ BETA, C, LDC, CT, G, CC, LDCC, EPS, ERR, FATAL, $ NOUT, MV ) * * Checks the results of the computational tests. * * Auxiliary routine for test program for Level 3 Blas. * * -- Written on 8-February-1989. * Jack Dongarra, Argonne National Laboratory. * Iain Duff, AERE Harwell. * Jeremy Du Croz, Numerical Algorithms Group Ltd. * Sven Hammarling, Numerical Algorithms Group Ltd. * * .. Parameters .. REAL ZERO, ONE PARAMETER ( ZERO = 0.0, ONE = 1.0 ) * .. Scalar Arguments .. REAL ALPHA, BETA, EPS, ERR INTEGER KK, LDA, LDB, LDC, LDCC, M, N, NOUT LOGICAL FATAL, MV CHARACTER*1 TRANSA, TRANSB * .. Array Arguments .. REAL A( LDA, * ), B( LDB, * ), C( LDC, * ), $ CC( LDCC, * ), CT( * ), G( * ) * .. Local Scalars .. REAL ERRI INTEGER I, J, K LOGICAL TRANA, TRANB * .. Intrinsic Functions .. INTRINSIC ABS, MAX, SQRT * .. Executable Statements .. TRANA = TRANSA.EQ.'T'.OR.TRANSA.EQ.'C' TRANB = TRANSB.EQ.'T'.OR.TRANSB.EQ.'C' * * Compute expected result, one column at a time, in CT using data * in A, B and C. * Compute gauges in G. * DO 120 J = 1, N * DO 10 I = 1, M CT( I ) = ZERO G( I ) = ZERO 10 CONTINUE IF( .NOT.TRANA.AND..NOT.TRANB )THEN DO 30 K = 1, KK DO 20 I = 1, M CT( I ) = CT( I ) + A( I, K )*B( K, J ) G( I ) = G( I ) + ABS( A( I, K ) )*ABS( B( K, J ) ) 20 CONTINUE 30 CONTINUE ELSE IF( TRANA.AND..NOT.TRANB )THEN DO 50 K = 1, KK DO 40 I = 1, M CT( I ) = CT( I ) + A( K, I )*B( K, J ) G( I ) = G( I ) + ABS( A( K, I ) )*ABS( B( K, J ) ) 40 CONTINUE 50 CONTINUE ELSE IF( .NOT.TRANA.AND.TRANB )THEN DO 70 K = 1, KK DO 60 I = 1, M CT( I ) = CT( I ) + A( I, K )*B( J, K ) G( I ) = G( I ) + ABS( A( I, K ) )*ABS( B( J, K ) ) 60 CONTINUE 70 CONTINUE ELSE IF( TRANA.AND.TRANB )THEN DO 90 K = 1, KK DO 80 I = 1, M CT( I ) = CT( I ) + A( K, I )*B( J, K ) G( I ) = G( I ) + ABS( A( K, I ) )*ABS( B( J, K ) ) 80 CONTINUE 90 CONTINUE END IF DO 100 I = 1, M CT( I ) = ALPHA*CT( I ) + BETA*C( I, J ) G( I ) = ABS( ALPHA )*G( I ) + ABS( BETA )*ABS( C( I, J ) ) 100 CONTINUE * * Compute the error ratio for this result. * ERR = ZERO DO 110 I = 1, M ERRI = ABS( CT( I ) - CC( I, J ) )/EPS IF( G( I ).NE.ZERO ) $ ERRI = ERRI/G( I ) ERR = MAX( ERR, ERRI ) IF( ERR*SQRT( EPS ).GE.ONE ) $ GO TO 130 110 CONTINUE * 120 CONTINUE * * If the loop completes, all results are at least half accurate. GO TO 150 * * Report fatal error. * 130 FATAL = .TRUE. WRITE( NOUT, FMT = 9999 ) DO 140 I = 1, M IF( MV )THEN WRITE( NOUT, FMT = 9998 )I, CT( I ), CC( I, J ) ELSE WRITE( NOUT, FMT = 9998 )I, CC( I, J ), CT( I ) END IF 140 CONTINUE IF( N.GT.1 ) $ WRITE( NOUT, FMT = 9997 )J * 150 CONTINUE RETURN * 9999 FORMAT( ' ******* FATAL ERROR - COMPUTED RESULT IS LESS THAN HAL', $ 'F ACCURATE *******', /' EXPECTED RESULT COMPU', $ 'TED RESULT' ) 9998 FORMAT( 1X, I7, 2G18.6 ) 9997 FORMAT( ' THESE ARE THE RESULTS FOR COLUMN ', I3 ) * * End of SMMCH. * END LOGICAL FUNCTION LSE( RI, RJ, LR ) * * Tests if two arrays are identical. * * Auxiliary routine for test program for Level 3 Blas. * * -- Written on 8-February-1989. * Jack Dongarra, Argonne National Laboratory. * Iain Duff, AERE Harwell. * Jeremy Du Croz, Numerical Algorithms Group Ltd. * Sven Hammarling, Numerical Algorithms Group Ltd. * * .. Scalar Arguments .. INTEGER LR * .. Array Arguments .. REAL RI( * ), RJ( * ) * .. Local Scalars .. INTEGER I * .. Executable Statements .. DO 10 I = 1, LR IF( RI( I ).NE.RJ( I ) ) $ GO TO 20 10 CONTINUE LSE = .TRUE. GO TO 30 20 CONTINUE LSE = .FALSE. 30 RETURN * * End of LSE. * END LOGICAL FUNCTION LSERES( TYPE, UPLO, M, N, AA, AS, LDA ) * * Tests if selected elements in two arrays are equal. * * TYPE is 'GE' or 'SY'. * * Auxiliary routine for test program for Level 3 Blas. * * -- Written on 8-February-1989. * Jack Dongarra, Argonne National Laboratory. * Iain Duff, AERE Harwell. * Jeremy Du Croz, Numerical Algorithms Group Ltd. * Sven Hammarling, Numerical Algorithms Group Ltd. * * .. Scalar Arguments .. INTEGER LDA, M, N CHARACTER*1 UPLO CHARACTER*2 TYPE * .. Array Arguments .. REAL AA( LDA, * ), AS( LDA, * ) * .. Local Scalars .. INTEGER I, IBEG, IEND, J LOGICAL UPPER * .. Executable Statements .. UPPER = UPLO.EQ.'U' IF( TYPE.EQ.'GE' )THEN DO 20 J = 1, N DO 10 I = M + 1, LDA IF( AA( I, J ).NE.AS( I, J ) ) $ GO TO 70 10 CONTINUE 20 CONTINUE ELSE IF( TYPE.EQ.'SY' )THEN DO 50 J = 1, N IF( UPPER )THEN IBEG = 1 IEND = J ELSE IBEG = J IEND = N END IF DO 30 I = 1, IBEG - 1 IF( AA( I, J ).NE.AS( I, J ) ) $ GO TO 70 30 CONTINUE DO 40 I = IEND + 1, LDA IF( AA( I, J ).NE.AS( I, J ) ) $ GO TO 70 40 CONTINUE 50 CONTINUE END IF * LSERES = .TRUE. GO TO 80 70 CONTINUE LSERES = .FALSE. 80 RETURN * * End of LSERES. * END REAL FUNCTION SBEG( RESET ) * * Generates random numbers uniformly distributed between -0.5 and 0.5. * * Auxiliary routine for test program for Level 3 Blas. * * -- Written on 8-February-1989. * Jack Dongarra, Argonne National Laboratory. * Iain Duff, AERE Harwell. * Jeremy Du Croz, Numerical Algorithms Group Ltd. * Sven Hammarling, Numerical Algorithms Group Ltd. * * .. Scalar Arguments .. LOGICAL RESET * .. Local Scalars .. INTEGER I, IC, MI * .. Save statement .. SAVE I, IC, MI * .. Executable Statements .. IF( RESET )THEN * Initialize local variables. MI = 891 I = 7 IC = 0 RESET = .FALSE. END IF * * The sequence of values of I is bounded between 1 and 999. * If initial I = 1,2,3,6,7 or 9, the period will be 50. * If initial I = 4 or 8, the period will be 25. * If initial I = 5, the period will be 10. * IC is used to break up the period by skipping 1 value of I in 6. * IC = IC + 1 10 I = I*MI I = I - 1000*( I/1000 ) IF( IC.GE.5 )THEN IC = 0 GO TO 10 END IF SBEG = ( I - 500 )/1001.0 RETURN * * End of SBEG. * END REAL FUNCTION SDIFF( X, Y ) * * Auxiliary routine for test program for Level 3 Blas. * * -- Written on 8-February-1989. * Jack Dongarra, Argonne National Laboratory. * Iain Duff, AERE Harwell. * Jeremy Du Croz, Numerical Algorithms Group Ltd. * Sven Hammarling, Numerical Algorithms Group Ltd. * * .. Scalar Arguments .. REAL X, Y * .. Executable Statements .. SDIFF = X - Y RETURN * * End of SDIFF. * END SUBROUTINE CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) * * Tests whether XERBLA has detected an error when it should. * * Auxiliary routine for test program for Level 3 Blas. * * -- Written on 8-February-1989. * Jack Dongarra, Argonne National Laboratory. * Iain Duff, AERE Harwell. * Jeremy Du Croz, Numerical Algorithms Group Ltd. * Sven Hammarling, Numerical Algorithms Group Ltd. * * .. Scalar Arguments .. INTEGER INFOT, NOUT LOGICAL LERR, OK CHARACTER*6 SRNAMT * .. Executable Statements .. IF( .NOT.LERR )THEN WRITE( NOUT, FMT = 9999 )INFOT, SRNAMT OK = .FALSE. END IF LERR = .FALSE. RETURN * 9999 FORMAT( ' ***** ILLEGAL VALUE OF PARAMETER NUMBER ', I2, ' NOT D', $ 'ETECTED BY ', A6, ' *****' ) * * End of CHKXER. * END SUBROUTINE XERBLA( SRNAME, INFO ) * * This is a special version of XERBLA to be used only as part of * the test program for testing error exits from the Level 3 BLAS * routines. * * XERBLA is an error handler for the Level 3 BLAS routines. * * It is called by the Level 3 BLAS routines if an input parameter is * invalid. * * Auxiliary routine for test program for Level 3 Blas. * * -- Written on 8-February-1989. * Jack Dongarra, Argonne National Laboratory. * Iain Duff, AERE Harwell. * Jeremy Du Croz, Numerical Algorithms Group Ltd. * Sven Hammarling, Numerical Algorithms Group Ltd. * * .. Scalar Arguments .. INTEGER INFO CHARACTER*6 SRNAME * .. Scalars in Common .. INTEGER INFOT, NOUT LOGICAL LERR, OK CHARACTER*6 SRNAMT * .. Common blocks .. COMMON /INFOC/INFOT, NOUT, OK, LERR COMMON /SRNAMC/SRNAMT * .. Executable Statements .. LERR = .TRUE. IF( INFO.NE.INFOT )THEN IF( INFOT.NE.0 )THEN WRITE( NOUT, FMT = 9999 )INFO, INFOT ELSE WRITE( NOUT, FMT = 9997 )INFO END IF OK = .FALSE. END IF IF( SRNAME.NE.SRNAMT )THEN WRITE( NOUT, FMT = 9998 )SRNAME, SRNAMT OK = .FALSE. END IF RETURN * 9999 FORMAT( ' ******* XERBLA WAS CALLED WITH INFO = ', I6, ' INSTEAD', $ ' OF ', I2, ' *******' ) 9998 FORMAT( ' ******* XERBLA WAS CALLED WITH SRNAME = ', A6, ' INSTE', $ 'AD OF ', A6, ' *******' ) 9997 FORMAT( ' ******* XERBLA WAS CALLED WITH INFO = ', I6, $ ' *******' ) * * End of XERBLA * END blis-0.9.0/blastest/src/fortran/zblat1.f000066400000000000000000000765621422157504600201260ustar00rootroot00000000000000*> \brief \b ZBLAT1 * * =========== DOCUMENTATION =========== * * Online html documentation available at * http://www.netlib.org/lapack/explore-html/ * * Definition: * =========== * * PROGRAM ZBLAT1 * * *> \par Purpose: * ============= *> *> \verbatim *> *> Test program for the COMPLEX*16 Level 1 BLAS. *> *> Based upon the original BLAS test routine together with: *> F06GAF Example Program Text *> \endverbatim * * Authors: * ======== * *> \author Univ. of Tennessee *> \author Univ. of California Berkeley *> \author Univ. of Colorado Denver *> \author NAG Ltd. * *> \date April 2012 * *> \ingroup complex16_blas_testing * * ===================================================================== PROGRAM ZBLAT1 * * -- Reference BLAS test routine (version 3.4.1) -- * -- Reference BLAS is a software package provided by Univ. of Tennessee, -- * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- * April 2012 * * ===================================================================== * * .. Parameters .. INTEGER NOUT PARAMETER (NOUT=6) * .. Scalars in Common .. INTEGER ICASE, INCX, INCY, MODE, N LOGICAL PASS * .. Local Scalars .. DOUBLE PRECISION SFAC INTEGER IC * .. External Subroutines .. EXTERNAL CHECK1, CHECK2, HEADER * .. Common blocks .. COMMON /COMBLA/ICASE, N, INCX, INCY, MODE, PASS * .. Data statements .. DATA SFAC/9.765625D-4/ * .. Executable Statements .. WRITE (NOUT,99999) DO 20 IC = 1, 10 ICASE = IC CALL HEADER * * Initialize PASS, INCX, INCY, and MODE for a new case. * The value 9999 for INCX, INCY or MODE will appear in the * detailed output, if any, for cases that do not involve * these parameters. * PASS = .TRUE. INCX = 9999 INCY = 9999 MODE = 9999 IF (ICASE.LE.5) THEN CALL CHECK2(SFAC) ELSE IF (ICASE.GE.6) THEN CALL CHECK1(SFAC) END IF * -- Print IF (PASS) WRITE (NOUT,99998) 20 CONTINUE STOP * 99999 FORMAT (' Complex BLAS Test Program Results',/1X) 99998 FORMAT (' ----- PASS -----') END SUBROUTINE HEADER * .. Parameters .. INTEGER NOUT PARAMETER (NOUT=6) * .. Scalars in Common .. INTEGER ICASE, INCX, INCY, MODE, N LOGICAL PASS * .. Local Arrays .. CHARACTER*6 L(10) * .. Common blocks .. COMMON /COMBLA/ICASE, N, INCX, INCY, MODE, PASS * .. Data statements .. DATA L(1)/'ZDOTC '/ DATA L(2)/'ZDOTU '/ DATA L(3)/'ZAXPY '/ DATA L(4)/'ZCOPY '/ DATA L(5)/'ZSWAP '/ DATA L(6)/'DZNRM2'/ DATA L(7)/'DZASUM'/ DATA L(8)/'ZSCAL '/ DATA L(9)/'ZDSCAL'/ DATA L(10)/'IZAMAX'/ * .. Executable Statements .. WRITE (NOUT,99999) ICASE, L(ICASE) RETURN * 99999 FORMAT (/' Test of subprogram number',I3,12X,A6) END SUBROUTINE CHECK1(SFAC) * .. Parameters .. INTEGER NOUT PARAMETER (NOUT=6) * .. Scalar Arguments .. DOUBLE PRECISION SFAC * .. Scalars in Common .. INTEGER ICASE, INCX, INCY, MODE, N LOGICAL PASS * .. Local Scalars .. COMPLEX*16 CA DOUBLE PRECISION SA INTEGER I, J, LEN, NP1 * .. Local Arrays .. COMPLEX*16 CTRUE5(8,5,2), CTRUE6(8,5,2), CV(8,5,2), CX(8), + MWPCS(5), MWPCT(5) DOUBLE PRECISION STRUE2(5), STRUE4(5) INTEGER ITRUE3(5) * .. External Functions .. DOUBLE PRECISION DZASUM, DZNRM2 INTEGER IZAMAX EXTERNAL DZASUM, DZNRM2, IZAMAX * .. External Subroutines .. EXTERNAL ZSCAL, ZDSCAL, CTEST, ITEST1, STEST1 * .. Intrinsic Functions .. INTRINSIC MAX * .. Common blocks .. COMMON /COMBLA/ICASE, N, INCX, INCY, MODE, PASS * .. Data statements .. DATA SA, CA/0.3D0, (0.4D0,-0.7D0)/ DATA ((CV(I,J,1),I=1,8),J=1,5)/(0.1D0,0.1D0), + (1.0D0,2.0D0), (1.0D0,2.0D0), (1.0D0,2.0D0), + (1.0D0,2.0D0), (1.0D0,2.0D0), (1.0D0,2.0D0), + (1.0D0,2.0D0), (0.3D0,-0.4D0), (3.0D0,4.0D0), + (3.0D0,4.0D0), (3.0D0,4.0D0), (3.0D0,4.0D0), + (3.0D0,4.0D0), (3.0D0,4.0D0), (3.0D0,4.0D0), + (0.1D0,-0.3D0), (0.5D0,-0.1D0), (5.0D0,6.0D0), + (5.0D0,6.0D0), (5.0D0,6.0D0), (5.0D0,6.0D0), + (5.0D0,6.0D0), (5.0D0,6.0D0), (0.1D0,0.1D0), + (-0.6D0,0.1D0), (0.1D0,-0.3D0), (7.0D0,8.0D0), + (7.0D0,8.0D0), (7.0D0,8.0D0), (7.0D0,8.0D0), + (7.0D0,8.0D0), (0.3D0,0.1D0), (0.5D0,0.0D0), + (0.0D0,0.5D0), (0.0D0,0.2D0), (2.0D0,3.0D0), + (2.0D0,3.0D0), (2.0D0,3.0D0), (2.0D0,3.0D0)/ DATA ((CV(I,J,2),I=1,8),J=1,5)/(0.1D0,0.1D0), + (4.0D0,5.0D0), (4.0D0,5.0D0), (4.0D0,5.0D0), + (4.0D0,5.0D0), (4.0D0,5.0D0), (4.0D0,5.0D0), + (4.0D0,5.0D0), (0.3D0,-0.4D0), (6.0D0,7.0D0), + (6.0D0,7.0D0), (6.0D0,7.0D0), (6.0D0,7.0D0), + (6.0D0,7.0D0), (6.0D0,7.0D0), (6.0D0,7.0D0), + (0.1D0,-0.3D0), (8.0D0,9.0D0), (0.5D0,-0.1D0), + (2.0D0,5.0D0), (2.0D0,5.0D0), (2.0D0,5.0D0), + (2.0D0,5.0D0), (2.0D0,5.0D0), (0.1D0,0.1D0), + (3.0D0,6.0D0), (-0.6D0,0.1D0), (4.0D0,7.0D0), + (0.1D0,-0.3D0), (7.0D0,2.0D0), (7.0D0,2.0D0), + (7.0D0,2.0D0), (0.3D0,0.1D0), (5.0D0,8.0D0), + (0.5D0,0.0D0), (6.0D0,9.0D0), (0.0D0,0.5D0), + (8.0D0,3.0D0), (0.0D0,0.2D0), (9.0D0,4.0D0)/ DATA STRUE2/0.0D0, 0.5D0, 0.6D0, 0.7D0, 0.8D0/ DATA STRUE4/0.0D0, 0.7D0, 1.0D0, 1.3D0, 1.6D0/ DATA ((CTRUE5(I,J,1),I=1,8),J=1,5)/(0.1D0,0.1D0), + (1.0D0,2.0D0), (1.0D0,2.0D0), (1.0D0,2.0D0), + (1.0D0,2.0D0), (1.0D0,2.0D0), (1.0D0,2.0D0), + (1.0D0,2.0D0), (-0.16D0,-0.37D0), (3.0D0,4.0D0), + (3.0D0,4.0D0), (3.0D0,4.0D0), (3.0D0,4.0D0), + (3.0D0,4.0D0), (3.0D0,4.0D0), (3.0D0,4.0D0), + (-0.17D0,-0.19D0), (0.13D0,-0.39D0), + (5.0D0,6.0D0), (5.0D0,6.0D0), (5.0D0,6.0D0), + (5.0D0,6.0D0), (5.0D0,6.0D0), (5.0D0,6.0D0), + (0.11D0,-0.03D0), (-0.17D0,0.46D0), + (-0.17D0,-0.19D0), (7.0D0,8.0D0), (7.0D0,8.0D0), + (7.0D0,8.0D0), (7.0D0,8.0D0), (7.0D0,8.0D0), + (0.19D0,-0.17D0), (0.20D0,-0.35D0), + (0.35D0,0.20D0), (0.14D0,0.08D0), + (2.0D0,3.0D0), (2.0D0,3.0D0), (2.0D0,3.0D0), + (2.0D0,3.0D0)/ DATA ((CTRUE5(I,J,2),I=1,8),J=1,5)/(0.1D0,0.1D0), + (4.0D0,5.0D0), (4.0D0,5.0D0), (4.0D0,5.0D0), + (4.0D0,5.0D0), (4.0D0,5.0D0), (4.0D0,5.0D0), + (4.0D0,5.0D0), (-0.16D0,-0.37D0), (6.0D0,7.0D0), + (6.0D0,7.0D0), (6.0D0,7.0D0), (6.0D0,7.0D0), + (6.0D0,7.0D0), (6.0D0,7.0D0), (6.0D0,7.0D0), + (-0.17D0,-0.19D0), (8.0D0,9.0D0), + (0.13D0,-0.39D0), (2.0D0,5.0D0), (2.0D0,5.0D0), + (2.0D0,5.0D0), (2.0D0,5.0D0), (2.0D0,5.0D0), + (0.11D0,-0.03D0), (3.0D0,6.0D0), + (-0.17D0,0.46D0), (4.0D0,7.0D0), + (-0.17D0,-0.19D0), (7.0D0,2.0D0), (7.0D0,2.0D0), + (7.0D0,2.0D0), (0.19D0,-0.17D0), (5.0D0,8.0D0), + (0.20D0,-0.35D0), (6.0D0,9.0D0), + (0.35D0,0.20D0), (8.0D0,3.0D0), + (0.14D0,0.08D0), (9.0D0,4.0D0)/ DATA ((CTRUE6(I,J,1),I=1,8),J=1,5)/(0.1D0,0.1D0), + (1.0D0,2.0D0), (1.0D0,2.0D0), (1.0D0,2.0D0), + (1.0D0,2.0D0), (1.0D0,2.0D0), (1.0D0,2.0D0), + (1.0D0,2.0D0), (0.09D0,-0.12D0), (3.0D0,4.0D0), + (3.0D0,4.0D0), (3.0D0,4.0D0), (3.0D0,4.0D0), + (3.0D0,4.0D0), (3.0D0,4.0D0), (3.0D0,4.0D0), + (0.03D0,-0.09D0), (0.15D0,-0.03D0), + (5.0D0,6.0D0), (5.0D0,6.0D0), (5.0D0,6.0D0), + (5.0D0,6.0D0), (5.0D0,6.0D0), (5.0D0,6.0D0), + (0.03D0,0.03D0), (-0.18D0,0.03D0), + (0.03D0,-0.09D0), (7.0D0,8.0D0), (7.0D0,8.0D0), + (7.0D0,8.0D0), (7.0D0,8.0D0), (7.0D0,8.0D0), + (0.09D0,0.03D0), (0.15D0,0.00D0), + (0.00D0,0.15D0), (0.00D0,0.06D0), (2.0D0,3.0D0), + (2.0D0,3.0D0), (2.0D0,3.0D0), (2.0D0,3.0D0)/ DATA ((CTRUE6(I,J,2),I=1,8),J=1,5)/(0.1D0,0.1D0), + (4.0D0,5.0D0), (4.0D0,5.0D0), (4.0D0,5.0D0), + (4.0D0,5.0D0), (4.0D0,5.0D0), (4.0D0,5.0D0), + (4.0D0,5.0D0), (0.09D0,-0.12D0), (6.0D0,7.0D0), + (6.0D0,7.0D0), (6.0D0,7.0D0), (6.0D0,7.0D0), + (6.0D0,7.0D0), (6.0D0,7.0D0), (6.0D0,7.0D0), + (0.03D0,-0.09D0), (8.0D0,9.0D0), + (0.15D0,-0.03D0), (2.0D0,5.0D0), (2.0D0,5.0D0), + (2.0D0,5.0D0), (2.0D0,5.0D0), (2.0D0,5.0D0), + (0.03D0,0.03D0), (3.0D0,6.0D0), + (-0.18D0,0.03D0), (4.0D0,7.0D0), + (0.03D0,-0.09D0), (7.0D0,2.0D0), (7.0D0,2.0D0), + (7.0D0,2.0D0), (0.09D0,0.03D0), (5.0D0,8.0D0), + (0.15D0,0.00D0), (6.0D0,9.0D0), (0.00D0,0.15D0), + (8.0D0,3.0D0), (0.00D0,0.06D0), (9.0D0,4.0D0)/ DATA ITRUE3/0, 1, 2, 2, 2/ * .. Executable Statements .. DO 60 INCX = 1, 2 DO 40 NP1 = 1, 5 N = NP1 - 1 LEN = 2*MAX(N,1) * .. Set vector arguments .. DO 20 I = 1, LEN CX(I) = CV(I,NP1,INCX) 20 CONTINUE IF (ICASE.EQ.6) THEN * .. DZNRM2 .. CALL STEST1(DZNRM2(N,CX,INCX),STRUE2(NP1),STRUE2(NP1), + SFAC) ELSE IF (ICASE.EQ.7) THEN * .. DZASUM .. CALL STEST1(DZASUM(N,CX,INCX),STRUE4(NP1),STRUE4(NP1), + SFAC) ELSE IF (ICASE.EQ.8) THEN * .. ZSCAL .. CALL ZSCAL(N,CA,CX,INCX) CALL CTEST(LEN,CX,CTRUE5(1,NP1,INCX),CTRUE5(1,NP1,INCX), + SFAC) ELSE IF (ICASE.EQ.9) THEN * .. ZDSCAL .. CALL ZDSCAL(N,SA,CX,INCX) CALL CTEST(LEN,CX,CTRUE6(1,NP1,INCX),CTRUE6(1,NP1,INCX), + SFAC) ELSE IF (ICASE.EQ.10) THEN * .. IZAMAX .. CALL ITEST1(IZAMAX(N,CX,INCX),ITRUE3(NP1)) ELSE WRITE (NOUT,*) ' Shouldn''t be here in CHECK1' STOP END IF * 40 CONTINUE 60 CONTINUE * INCX = 1 IF (ICASE.EQ.8) THEN * ZSCAL * Add a test for alpha equal to zero. CA = (0.0D0,0.0D0) DO 80 I = 1, 5 MWPCT(I) = (0.0D0,0.0D0) MWPCS(I) = (1.0D0,1.0D0) 80 CONTINUE CALL ZSCAL(5,CA,CX,INCX) CALL CTEST(5,CX,MWPCT,MWPCS,SFAC) ELSE IF (ICASE.EQ.9) THEN * ZDSCAL * Add a test for alpha equal to zero. SA = 0.0D0 DO 100 I = 1, 5 MWPCT(I) = (0.0D0,0.0D0) MWPCS(I) = (1.0D0,1.0D0) 100 CONTINUE CALL ZDSCAL(5,SA,CX,INCX) CALL CTEST(5,CX,MWPCT,MWPCS,SFAC) * Add a test for alpha equal to one. SA = 1.0D0 DO 120 I = 1, 5 MWPCT(I) = CX(I) MWPCS(I) = CX(I) 120 CONTINUE CALL ZDSCAL(5,SA,CX,INCX) CALL CTEST(5,CX,MWPCT,MWPCS,SFAC) * Add a test for alpha equal to minus one. SA = -1.0D0 DO 140 I = 1, 5 MWPCT(I) = -CX(I) MWPCS(I) = -CX(I) 140 CONTINUE CALL ZDSCAL(5,SA,CX,INCX) CALL CTEST(5,CX,MWPCT,MWPCS,SFAC) END IF RETURN END SUBROUTINE CHECK2(SFAC) * .. Parameters .. INTEGER NOUT PARAMETER (NOUT=6) * .. Scalar Arguments .. DOUBLE PRECISION SFAC * .. Scalars in Common .. INTEGER ICASE, INCX, INCY, MODE, N LOGICAL PASS * .. Local Scalars .. COMPLEX*16 CA INTEGER I, J, KI, KN, KSIZE, LENX, LENY, MX, MY * .. Local Arrays .. COMPLEX*16 CDOT(1), CSIZE1(4), CSIZE2(7,2), CSIZE3(14), + CT10X(7,4,4), CT10Y(7,4,4), CT6(4,4), CT7(4,4), + CT8(7,4,4), CX(7), CX1(7), CY(7), CY1(7) INTEGER INCXS(4), INCYS(4), LENS(4,2), NS(4) * .. External Functions .. COMPLEX*16 ZDOTC, ZDOTU EXTERNAL ZDOTC, ZDOTU * .. External Subroutines .. EXTERNAL ZAXPY, ZCOPY, ZSWAP, CTEST * .. Intrinsic Functions .. INTRINSIC ABS, MIN * .. Common blocks .. COMMON /COMBLA/ICASE, N, INCX, INCY, MODE, PASS * .. Data statements .. DATA CA/(0.4D0,-0.7D0)/ DATA INCXS/1, 2, -2, -1/ DATA INCYS/1, -2, 1, -2/ DATA LENS/1, 1, 2, 4, 1, 1, 3, 7/ DATA NS/0, 1, 2, 4/ DATA CX1/(0.7D0,-0.8D0), (-0.4D0,-0.7D0), + (-0.1D0,-0.9D0), (0.2D0,-0.8D0), + (-0.9D0,-0.4D0), (0.1D0,0.4D0), (-0.6D0,0.6D0)/ DATA CY1/(0.6D0,-0.6D0), (-0.9D0,0.5D0), + (0.7D0,-0.6D0), (0.1D0,-0.5D0), (-0.1D0,-0.2D0), + (-0.5D0,-0.3D0), (0.8D0,-0.7D0)/ DATA ((CT8(I,J,1),I=1,7),J=1,4)/(0.6D0,-0.6D0), + (0.0D0,0.0D0), (0.0D0,0.0D0), (0.0D0,0.0D0), + (0.0D0,0.0D0), (0.0D0,0.0D0), (0.0D0,0.0D0), + (0.32D0,-1.41D0), (0.0D0,0.0D0), (0.0D0,0.0D0), + (0.0D0,0.0D0), (0.0D0,0.0D0), (0.0D0,0.0D0), + (0.0D0,0.0D0), (0.32D0,-1.41D0), + (-1.55D0,0.5D0), (0.0D0,0.0D0), (0.0D0,0.0D0), + (0.0D0,0.0D0), (0.0D0,0.0D0), (0.0D0,0.0D0), + (0.32D0,-1.41D0), (-1.55D0,0.5D0), + (0.03D0,-0.89D0), (-0.38D0,-0.96D0), + (0.0D0,0.0D0), (0.0D0,0.0D0), (0.0D0,0.0D0)/ DATA ((CT8(I,J,2),I=1,7),J=1,4)/(0.6D0,-0.6D0), + (0.0D0,0.0D0), (0.0D0,0.0D0), (0.0D0,0.0D0), + (0.0D0,0.0D0), (0.0D0,0.0D0), (0.0D0,0.0D0), + (0.32D0,-1.41D0), (0.0D0,0.0D0), (0.0D0,0.0D0), + (0.0D0,0.0D0), (0.0D0,0.0D0), (0.0D0,0.0D0), + (0.0D0,0.0D0), (-0.07D0,-0.89D0), + (-0.9D0,0.5D0), (0.42D0,-1.41D0), (0.0D0,0.0D0), + (0.0D0,0.0D0), (0.0D0,0.0D0), (0.0D0,0.0D0), + (0.78D0,0.06D0), (-0.9D0,0.5D0), + (0.06D0,-0.13D0), (0.1D0,-0.5D0), + (-0.77D0,-0.49D0), (-0.5D0,-0.3D0), + (0.52D0,-1.51D0)/ DATA ((CT8(I,J,3),I=1,7),J=1,4)/(0.6D0,-0.6D0), + (0.0D0,0.0D0), (0.0D0,0.0D0), (0.0D0,0.0D0), + (0.0D0,0.0D0), (0.0D0,0.0D0), (0.0D0,0.0D0), + (0.32D0,-1.41D0), (0.0D0,0.0D0), (0.0D0,0.0D0), + (0.0D0,0.0D0), (0.0D0,0.0D0), (0.0D0,0.0D0), + (0.0D0,0.0D0), (-0.07D0,-0.89D0), + (-1.18D0,-0.31D0), (0.0D0,0.0D0), (0.0D0,0.0D0), + (0.0D0,0.0D0), (0.0D0,0.0D0), (0.0D0,0.0D0), + (0.78D0,0.06D0), (-1.54D0,0.97D0), + (0.03D0,-0.89D0), (-0.18D0,-1.31D0), + (0.0D0,0.0D0), (0.0D0,0.0D0), (0.0D0,0.0D0)/ DATA ((CT8(I,J,4),I=1,7),J=1,4)/(0.6D0,-0.6D0), + (0.0D0,0.0D0), (0.0D0,0.0D0), (0.0D0,0.0D0), + (0.0D0,0.0D0), (0.0D0,0.0D0), (0.0D0,0.0D0), + (0.32D0,-1.41D0), (0.0D0,0.0D0), (0.0D0,0.0D0), + (0.0D0,0.0D0), (0.0D0,0.0D0), (0.0D0,0.0D0), + (0.0D0,0.0D0), (0.32D0,-1.41D0), (-0.9D0,0.5D0), + (0.05D0,-0.6D0), (0.0D0,0.0D0), (0.0D0,0.0D0), + (0.0D0,0.0D0), (0.0D0,0.0D0), (0.32D0,-1.41D0), + (-0.9D0,0.5D0), (0.05D0,-0.6D0), (0.1D0,-0.5D0), + (-0.77D0,-0.49D0), (-0.5D0,-0.3D0), + (0.32D0,-1.16D0)/ DATA CT7/(0.0D0,0.0D0), (-0.06D0,-0.90D0), + (0.65D0,-0.47D0), (-0.34D0,-1.22D0), + (0.0D0,0.0D0), (-0.06D0,-0.90D0), + (-0.59D0,-1.46D0), (-1.04D0,-0.04D0), + (0.0D0,0.0D0), (-0.06D0,-0.90D0), + (-0.83D0,0.59D0), (0.07D0,-0.37D0), + (0.0D0,0.0D0), (-0.06D0,-0.90D0), + (-0.76D0,-1.15D0), (-1.33D0,-1.82D0)/ DATA CT6/(0.0D0,0.0D0), (0.90D0,0.06D0), + (0.91D0,-0.77D0), (1.80D0,-0.10D0), + (0.0D0,0.0D0), (0.90D0,0.06D0), (1.45D0,0.74D0), + (0.20D0,0.90D0), (0.0D0,0.0D0), (0.90D0,0.06D0), + (-0.55D0,0.23D0), (0.83D0,-0.39D0), + (0.0D0,0.0D0), (0.90D0,0.06D0), (1.04D0,0.79D0), + (1.95D0,1.22D0)/ DATA ((CT10X(I,J,1),I=1,7),J=1,4)/(0.7D0,-0.8D0), + (0.0D0,0.0D0), (0.0D0,0.0D0), (0.0D0,0.0D0), + (0.0D0,0.0D0), (0.0D0,0.0D0), (0.0D0,0.0D0), + (0.6D0,-0.6D0), (0.0D0,0.0D0), (0.0D0,0.0D0), + (0.0D0,0.0D0), (0.0D0,0.0D0), (0.0D0,0.0D0), + (0.0D0,0.0D0), (0.6D0,-0.6D0), (-0.9D0,0.5D0), + (0.0D0,0.0D0), (0.0D0,0.0D0), (0.0D0,0.0D0), + (0.0D0,0.0D0), (0.0D0,0.0D0), (0.6D0,-0.6D0), + (-0.9D0,0.5D0), (0.7D0,-0.6D0), (0.1D0,-0.5D0), + (0.0D0,0.0D0), (0.0D0,0.0D0), (0.0D0,0.0D0)/ DATA ((CT10X(I,J,2),I=1,7),J=1,4)/(0.7D0,-0.8D0), + (0.0D0,0.0D0), (0.0D0,0.0D0), (0.0D0,0.0D0), + (0.0D0,0.0D0), (0.0D0,0.0D0), (0.0D0,0.0D0), + (0.6D0,-0.6D0), (0.0D0,0.0D0), (0.0D0,0.0D0), + (0.0D0,0.0D0), (0.0D0,0.0D0), (0.0D0,0.0D0), + (0.0D0,0.0D0), (0.7D0,-0.6D0), (-0.4D0,-0.7D0), + (0.6D0,-0.6D0), (0.0D0,0.0D0), (0.0D0,0.0D0), + (0.0D0,0.0D0), (0.0D0,0.0D0), (0.8D0,-0.7D0), + (-0.4D0,-0.7D0), (-0.1D0,-0.2D0), + (0.2D0,-0.8D0), (0.7D0,-0.6D0), (0.1D0,0.4D0), + (0.6D0,-0.6D0)/ DATA ((CT10X(I,J,3),I=1,7),J=1,4)/(0.7D0,-0.8D0), + (0.0D0,0.0D0), (0.0D0,0.0D0), (0.0D0,0.0D0), + (0.0D0,0.0D0), (0.0D0,0.0D0), (0.0D0,0.0D0), + (0.6D0,-0.6D0), (0.0D0,0.0D0), (0.0D0,0.0D0), + (0.0D0,0.0D0), (0.0D0,0.0D0), (0.0D0,0.0D0), + (0.0D0,0.0D0), (-0.9D0,0.5D0), (-0.4D0,-0.7D0), + (0.6D0,-0.6D0), (0.0D0,0.0D0), (0.0D0,0.0D0), + (0.0D0,0.0D0), (0.0D0,0.0D0), (0.1D0,-0.5D0), + (-0.4D0,-0.7D0), (0.7D0,-0.6D0), (0.2D0,-0.8D0), + (-0.9D0,0.5D0), (0.1D0,0.4D0), (0.6D0,-0.6D0)/ DATA ((CT10X(I,J,4),I=1,7),J=1,4)/(0.7D0,-0.8D0), + (0.0D0,0.0D0), (0.0D0,0.0D0), (0.0D0,0.0D0), + (0.0D0,0.0D0), (0.0D0,0.0D0), (0.0D0,0.0D0), + (0.6D0,-0.6D0), (0.0D0,0.0D0), (0.0D0,0.0D0), + (0.0D0,0.0D0), (0.0D0,0.0D0), (0.0D0,0.0D0), + (0.0D0,0.0D0), (0.6D0,-0.6D0), (0.7D0,-0.6D0), + (0.0D0,0.0D0), (0.0D0,0.0D0), (0.0D0,0.0D0), + (0.0D0,0.0D0), (0.0D0,0.0D0), (0.6D0,-0.6D0), + (0.7D0,-0.6D0), (-0.1D0,-0.2D0), (0.8D0,-0.7D0), + (0.0D0,0.0D0), (0.0D0,0.0D0), (0.0D0,0.0D0)/ DATA ((CT10Y(I,J,1),I=1,7),J=1,4)/(0.6D0,-0.6D0), + (0.0D0,0.0D0), (0.0D0,0.0D0), (0.0D0,0.0D0), + (0.0D0,0.0D0), (0.0D0,0.0D0), (0.0D0,0.0D0), + (0.7D0,-0.8D0), (0.0D0,0.0D0), (0.0D0,0.0D0), + (0.0D0,0.0D0), (0.0D0,0.0D0), (0.0D0,0.0D0), + (0.0D0,0.0D0), (0.7D0,-0.8D0), (-0.4D0,-0.7D0), + (0.0D0,0.0D0), (0.0D0,0.0D0), (0.0D0,0.0D0), + (0.0D0,0.0D0), (0.0D0,0.0D0), (0.7D0,-0.8D0), + (-0.4D0,-0.7D0), (-0.1D0,-0.9D0), + (0.2D0,-0.8D0), (0.0D0,0.0D0), (0.0D0,0.0D0), + (0.0D0,0.0D0)/ DATA ((CT10Y(I,J,2),I=1,7),J=1,4)/(0.6D0,-0.6D0), + (0.0D0,0.0D0), (0.0D0,0.0D0), (0.0D0,0.0D0), + (0.0D0,0.0D0), (0.0D0,0.0D0), (0.0D0,0.0D0), + (0.7D0,-0.8D0), (0.0D0,0.0D0), (0.0D0,0.0D0), + (0.0D0,0.0D0), (0.0D0,0.0D0), (0.0D0,0.0D0), + (0.0D0,0.0D0), (-0.1D0,-0.9D0), (-0.9D0,0.5D0), + (0.7D0,-0.8D0), (0.0D0,0.0D0), (0.0D0,0.0D0), + (0.0D0,0.0D0), (0.0D0,0.0D0), (-0.6D0,0.6D0), + (-0.9D0,0.5D0), (-0.9D0,-0.4D0), (0.1D0,-0.5D0), + (-0.1D0,-0.9D0), (-0.5D0,-0.3D0), + (0.7D0,-0.8D0)/ DATA ((CT10Y(I,J,3),I=1,7),J=1,4)/(0.6D0,-0.6D0), + (0.0D0,0.0D0), (0.0D0,0.0D0), (0.0D0,0.0D0), + (0.0D0,0.0D0), (0.0D0,0.0D0), (0.0D0,0.0D0), + (0.7D0,-0.8D0), (0.0D0,0.0D0), (0.0D0,0.0D0), + (0.0D0,0.0D0), (0.0D0,0.0D0), (0.0D0,0.0D0), + (0.0D0,0.0D0), (-0.1D0,-0.9D0), (0.7D0,-0.8D0), + (0.0D0,0.0D0), (0.0D0,0.0D0), (0.0D0,0.0D0), + (0.0D0,0.0D0), (0.0D0,0.0D0), (-0.6D0,0.6D0), + (-0.9D0,-0.4D0), (-0.1D0,-0.9D0), + (0.7D0,-0.8D0), (0.0D0,0.0D0), (0.0D0,0.0D0), + (0.0D0,0.0D0)/ DATA ((CT10Y(I,J,4),I=1,7),J=1,4)/(0.6D0,-0.6D0), + (0.0D0,0.0D0), (0.0D0,0.0D0), (0.0D0,0.0D0), + (0.0D0,0.0D0), (0.0D0,0.0D0), (0.0D0,0.0D0), + (0.7D0,-0.8D0), (0.0D0,0.0D0), (0.0D0,0.0D0), + (0.0D0,0.0D0), (0.0D0,0.0D0), (0.0D0,0.0D0), + (0.0D0,0.0D0), (0.7D0,-0.8D0), (-0.9D0,0.5D0), + (-0.4D0,-0.7D0), (0.0D0,0.0D0), (0.0D0,0.0D0), + (0.0D0,0.0D0), (0.0D0,0.0D0), (0.7D0,-0.8D0), + (-0.9D0,0.5D0), (-0.4D0,-0.7D0), (0.1D0,-0.5D0), + (-0.1D0,-0.9D0), (-0.5D0,-0.3D0), + (0.2D0,-0.8D0)/ DATA CSIZE1/(0.0D0,0.0D0), (0.9D0,0.9D0), + (1.63D0,1.73D0), (2.90D0,2.78D0)/ DATA CSIZE3/(0.0D0,0.0D0), (0.0D0,0.0D0), + (0.0D0,0.0D0), (0.0D0,0.0D0), (0.0D0,0.0D0), + (0.0D0,0.0D0), (0.0D0,0.0D0), (1.17D0,1.17D0), + (1.17D0,1.17D0), (1.17D0,1.17D0), + (1.17D0,1.17D0), (1.17D0,1.17D0), + (1.17D0,1.17D0), (1.17D0,1.17D0)/ DATA CSIZE2/(0.0D0,0.0D0), (0.0D0,0.0D0), + (0.0D0,0.0D0), (0.0D0,0.0D0), (0.0D0,0.0D0), + (0.0D0,0.0D0), (0.0D0,0.0D0), (1.54D0,1.54D0), + (1.54D0,1.54D0), (1.54D0,1.54D0), + (1.54D0,1.54D0), (1.54D0,1.54D0), + (1.54D0,1.54D0), (1.54D0,1.54D0)/ * .. Executable Statements .. DO 60 KI = 1, 4 INCX = INCXS(KI) INCY = INCYS(KI) MX = ABS(INCX) MY = ABS(INCY) * DO 40 KN = 1, 4 N = NS(KN) KSIZE = MIN(2,KN) LENX = LENS(KN,MX) LENY = LENS(KN,MY) * .. initialize all argument arrays .. DO 20 I = 1, 7 CX(I) = CX1(I) CY(I) = CY1(I) 20 CONTINUE IF (ICASE.EQ.1) THEN * .. ZDOTC .. CDOT(1) = ZDOTC(N,CX,INCX,CY,INCY) CALL CTEST(1,CDOT,CT6(KN,KI),CSIZE1(KN),SFAC) ELSE IF (ICASE.EQ.2) THEN * .. ZDOTU .. CDOT(1) = ZDOTU(N,CX,INCX,CY,INCY) CALL CTEST(1,CDOT,CT7(KN,KI),CSIZE1(KN),SFAC) ELSE IF (ICASE.EQ.3) THEN * .. ZAXPY .. CALL ZAXPY(N,CA,CX,INCX,CY,INCY) CALL CTEST(LENY,CY,CT8(1,KN,KI),CSIZE2(1,KSIZE),SFAC) ELSE IF (ICASE.EQ.4) THEN * .. ZCOPY .. CALL ZCOPY(N,CX,INCX,CY,INCY) CALL CTEST(LENY,CY,CT10Y(1,KN,KI),CSIZE3,1.0D0) ELSE IF (ICASE.EQ.5) THEN * .. ZSWAP .. CALL ZSWAP(N,CX,INCX,CY,INCY) CALL CTEST(LENX,CX,CT10X(1,KN,KI),CSIZE3,1.0D0) CALL CTEST(LENY,CY,CT10Y(1,KN,KI),CSIZE3,1.0D0) ELSE WRITE (NOUT,*) ' Shouldn''t be here in CHECK2' STOP END IF * 40 CONTINUE 60 CONTINUE RETURN END SUBROUTINE STEST(LEN,SCOMP,STRUE,SSIZE,SFAC) * ********************************* STEST ************************** * * THIS SUBR COMPARES ARRAYS SCOMP() AND STRUE() OF LENGTH LEN TO * SEE IF THE TERM BY TERM DIFFERENCES, MULTIPLIED BY SFAC, ARE * NEGLIGIBLE. * * C. L. LAWSON, JPL, 1974 DEC 10 * * .. Parameters .. INTEGER NOUT DOUBLE PRECISION ZERO PARAMETER (NOUT=6, ZERO=0.0D0) * .. Scalar Arguments .. DOUBLE PRECISION SFAC INTEGER LEN * .. Array Arguments .. DOUBLE PRECISION SCOMP(LEN), SSIZE(LEN), STRUE(LEN) * .. Scalars in Common .. INTEGER ICASE, INCX, INCY, MODE, N LOGICAL PASS * .. Local Scalars .. DOUBLE PRECISION SD INTEGER I * .. External Functions .. DOUBLE PRECISION SDIFF EXTERNAL SDIFF * .. Intrinsic Functions .. INTRINSIC ABS * .. Common blocks .. COMMON /COMBLA/ICASE, N, INCX, INCY, MODE, PASS * .. Executable Statements .. * DO 40 I = 1, LEN SD = SCOMP(I) - STRUE(I) IF (ABS(SFAC*SD) .LE. ABS(SSIZE(I))*EPSILON(ZERO)) + GO TO 40 * * HERE SCOMP(I) IS NOT CLOSE TO STRUE(I). * IF ( .NOT. PASS) GO TO 20 * PRINT FAIL MESSAGE AND HEADER. PASS = .FALSE. WRITE (NOUT,99999) WRITE (NOUT,99998) 20 WRITE (NOUT,99997) ICASE, N, INCX, INCY, MODE, I, SCOMP(I), + STRUE(I), SD, SSIZE(I) 40 CONTINUE RETURN * 99999 FORMAT (' FAIL') 99998 FORMAT (/' CASE N INCX INCY MODE I ', + ' COMP(I) TRUE(I) DIFFERENCE', + ' SIZE(I)',/1X) 99997 FORMAT (1X,I4,I3,3I5,I3,2D36.8,2D12.4) END SUBROUTINE STEST1(SCOMP1,STRUE1,SSIZE,SFAC) * ************************* STEST1 ***************************** * * THIS IS AN INTERFACE SUBROUTINE TO ACCOMODATE THE FORTRAN * REQUIREMENT THAT WHEN A DUMMY ARGUMENT IS AN ARRAY, THE * ACTUAL ARGUMENT MUST ALSO BE AN ARRAY OR AN ARRAY ELEMENT. * * C.L. LAWSON, JPL, 1978 DEC 6 * * .. Scalar Arguments .. DOUBLE PRECISION SCOMP1, SFAC, STRUE1 * .. Array Arguments .. DOUBLE PRECISION SSIZE(*) * .. Local Arrays .. DOUBLE PRECISION SCOMP(1), STRUE(1) * .. External Subroutines .. EXTERNAL STEST * .. Executable Statements .. * SCOMP(1) = SCOMP1 STRUE(1) = STRUE1 CALL STEST(1,SCOMP,STRUE,SSIZE,SFAC) * RETURN END DOUBLE PRECISION FUNCTION SDIFF(SA,SB) * ********************************* SDIFF ************************** * COMPUTES DIFFERENCE OF TWO NUMBERS. C. L. LAWSON, JPL 1974 FEB 15 * * .. Scalar Arguments .. DOUBLE PRECISION SA, SB * .. Executable Statements .. SDIFF = SA - SB RETURN END SUBROUTINE CTEST(LEN,CCOMP,CTRUE,CSIZE,SFAC) * **************************** CTEST ***************************** * * C.L. LAWSON, JPL, 1978 DEC 6 * * .. Scalar Arguments .. DOUBLE PRECISION SFAC INTEGER LEN * .. Array Arguments .. COMPLEX*16 CCOMP(LEN), CSIZE(LEN), CTRUE(LEN) * .. Local Scalars .. INTEGER I * .. Local Arrays .. DOUBLE PRECISION SCOMP(20), SSIZE(20), STRUE(20) * .. External Subroutines .. EXTERNAL STEST * .. Intrinsic Functions .. INTRINSIC DIMAG, DBLE * .. Executable Statements .. DO 20 I = 1, LEN SCOMP(2*I-1) = DBLE(CCOMP(I)) SCOMP(2*I) = DIMAG(CCOMP(I)) STRUE(2*I-1) = DBLE(CTRUE(I)) STRUE(2*I) = DIMAG(CTRUE(I)) SSIZE(2*I-1) = DBLE(CSIZE(I)) SSIZE(2*I) = DIMAG(CSIZE(I)) 20 CONTINUE * CALL STEST(2*LEN,SCOMP,STRUE,SSIZE,SFAC) RETURN END SUBROUTINE ITEST1(ICOMP,ITRUE) * ********************************* ITEST1 ************************* * * THIS SUBROUTINE COMPARES THE VARIABLES ICOMP AND ITRUE FOR * EQUALITY. * C. L. LAWSON, JPL, 1974 DEC 10 * * .. Parameters .. INTEGER NOUT PARAMETER (NOUT=6) * .. Scalar Arguments .. INTEGER ICOMP, ITRUE * .. Scalars in Common .. INTEGER ICASE, INCX, INCY, MODE, N LOGICAL PASS * .. Local Scalars .. INTEGER ID * .. Common blocks .. COMMON /COMBLA/ICASE, N, INCX, INCY, MODE, PASS * .. Executable Statements .. IF (ICOMP.EQ.ITRUE) GO TO 40 * * HERE ICOMP IS NOT EQUAL TO ITRUE. * IF ( .NOT. PASS) GO TO 20 * PRINT FAIL MESSAGE AND HEADER. PASS = .FALSE. WRITE (NOUT,99999) WRITE (NOUT,99998) 20 ID = ICOMP - ITRUE WRITE (NOUT,99997) ICASE, N, INCX, INCY, MODE, ICOMP, ITRUE, ID 40 CONTINUE RETURN * 99999 FORMAT (' FAIL') 99998 FORMAT (/' CASE N INCX INCY MODE ', + ' COMP TRUE DIFFERENCE', + /1X) 99997 FORMAT (1X,I4,I3,3I5,2I36,I12) END blis-0.9.0/blastest/src/fortran/zblat2.f000066400000000000000000003444131422157504600201200ustar00rootroot00000000000000*> \brief \b ZBLAT2 * * =========== DOCUMENTATION =========== * * Online html documentation available at * http://www.netlib.org/lapack/explore-html/ * * Definition: * =========== * * PROGRAM ZBLAT2 * * *> \par Purpose: * ============= *> *> \verbatim *> *> Test program for the COMPLEX*16 Level 2 Blas. *> *> The program must be driven by a short data file. The first 18 records *> of the file are read using list-directed input, the last 17 records *> are read using the format ( A6, L2 ). An annotated example of a data *> file can be obtained by deleting the first 3 characters from the *> following 35 lines: *> 'zblat2.out' NAME OF SUMMARY OUTPUT FILE *> 6 UNIT NUMBER OF SUMMARY FILE *> 'CBLA2T.SNAP' NAME OF SNAPSHOT OUTPUT FILE *> -1 UNIT NUMBER OF SNAPSHOT FILE (NOT USED IF .LT. 0) *> F LOGICAL FLAG, T TO REWIND SNAPSHOT FILE AFTER EACH RECORD. *> F LOGICAL FLAG, T TO STOP ON FAILURES. *> T LOGICAL FLAG, T TO TEST ERROR EXITS. *> 16.0 THRESHOLD VALUE OF TEST RATIO *> 6 NUMBER OF VALUES OF N *> 0 1 2 3 5 9 VALUES OF N *> 4 NUMBER OF VALUES OF K *> 0 1 2 4 VALUES OF K *> 4 NUMBER OF VALUES OF INCX AND INCY *> 1 2 -1 -2 VALUES OF INCX AND INCY *> 3 NUMBER OF VALUES OF ALPHA *> (0.0,0.0) (1.0,0.0) (0.7,-0.9) VALUES OF ALPHA *> 3 NUMBER OF VALUES OF BETA *> (0.0,0.0) (1.0,0.0) (1.3,-1.1) VALUES OF BETA *> ZGEMV T PUT F FOR NO TEST. SAME COLUMNS. *> ZGBMV T PUT F FOR NO TEST. SAME COLUMNS. *> ZHEMV T PUT F FOR NO TEST. SAME COLUMNS. *> ZHBMV T PUT F FOR NO TEST. SAME COLUMNS. *> ZHPMV T PUT F FOR NO TEST. SAME COLUMNS. *> ZTRMV T PUT F FOR NO TEST. SAME COLUMNS. *> ZTBMV T PUT F FOR NO TEST. SAME COLUMNS. *> ZTPMV T PUT F FOR NO TEST. SAME COLUMNS. *> ZTRSV T PUT F FOR NO TEST. SAME COLUMNS. *> ZTBSV T PUT F FOR NO TEST. SAME COLUMNS. *> ZTPSV T PUT F FOR NO TEST. SAME COLUMNS. *> ZGERC T PUT F FOR NO TEST. SAME COLUMNS. *> ZGERU T PUT F FOR NO TEST. SAME COLUMNS. *> ZHER T PUT F FOR NO TEST. SAME COLUMNS. *> ZHPR T PUT F FOR NO TEST. SAME COLUMNS. *> ZHER2 T PUT F FOR NO TEST. SAME COLUMNS. *> ZHPR2 T PUT F FOR NO TEST. SAME COLUMNS. *> *> Further Details *> =============== *> *> See: *> *> Dongarra J. J., Du Croz J. J., Hammarling S. and Hanson R. J.. *> An extended set of Fortran Basic Linear Algebra Subprograms. *> *> Technical Memoranda Nos. 41 (revision 3) and 81, Mathematics *> and Computer Science Division, Argonne National Laboratory, *> 9700 South Cass Avenue, Argonne, Illinois 60439, US. *> *> Or *> *> NAG Technical Reports TR3/87 and TR4/87, Numerical Algorithms *> Group Ltd., NAG Central Office, 256 Banbury Road, Oxford *> OX2 7DE, UK, and Numerical Algorithms Group Inc., 1101 31st *> Street, Suite 100, Downers Grove, Illinois 60515-1263, USA. *> *> *> -- Written on 10-August-1987. *> Richard Hanson, Sandia National Labs. *> Jeremy Du Croz, NAG Central Office. *> *> 10-9-00: Change STATUS='NEW' to 'UNKNOWN' so that the testers *> can be run multiple times without deleting generated *> output files (susan) *> \endverbatim * * Authors: * ======== * *> \author Univ. of Tennessee *> \author Univ. of California Berkeley *> \author Univ. of Colorado Denver *> \author NAG Ltd. * *> \date April 2012 * *> \ingroup complex16_blas_testing * * ===================================================================== PROGRAM ZBLAT2 * * -- Reference BLAS test routine (version 3.4.1) -- * -- Reference BLAS is a software package provided by Univ. of Tennessee, -- * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- * April 2012 * * ===================================================================== * * .. Parameters .. INTEGER NIN PARAMETER ( NIN = 5 ) INTEGER NSUBS PARAMETER ( NSUBS = 17 ) COMPLEX*16 ZERO, ONE PARAMETER ( ZERO = ( 0.0D0, 0.0D0 ), $ ONE = ( 1.0D0, 0.0D0 ) ) DOUBLE PRECISION RZERO PARAMETER ( RZERO = 0.0D0 ) INTEGER NMAX, INCMAX PARAMETER ( NMAX = 65, INCMAX = 2 ) INTEGER NINMAX, NIDMAX, NKBMAX, NALMAX, NBEMAX PARAMETER ( NINMAX = 7, NIDMAX = 9, NKBMAX = 7, $ NALMAX = 7, NBEMAX = 7 ) * .. Local Scalars .. DOUBLE PRECISION EPS, ERR, THRESH INTEGER I, ISNUM, J, N, NALF, NBET, NIDIM, NINC, NKB, $ NOUT, NTRA LOGICAL FATAL, LTESTT, REWI, SAME, SFATAL, TRACE, $ TSTERR CHARACTER*1 TRANS CHARACTER*6 SNAMET CHARACTER*32 SNAPS, SUMMRY * .. Local Arrays .. COMPLEX*16 A( NMAX, NMAX ), AA( NMAX*NMAX ), $ ALF( NALMAX ), AS( NMAX*NMAX ), BET( NBEMAX ), $ X( NMAX ), XS( NMAX*INCMAX ), $ XX( NMAX*INCMAX ), Y( NMAX ), $ YS( NMAX*INCMAX ), YT( NMAX ), $ YY( NMAX*INCMAX ), Z( 2*NMAX ) DOUBLE PRECISION G( NMAX ) INTEGER IDIM( NIDMAX ), INC( NINMAX ), KB( NKBMAX ) LOGICAL LTEST( NSUBS ) CHARACTER*6 SNAMES( NSUBS ) * .. External Functions .. DOUBLE PRECISION DDIFF LOGICAL LZE EXTERNAL DDIFF, LZE * .. External Subroutines .. EXTERNAL ZCHK1, ZCHK2, ZCHK3, ZCHK4, ZCHK5, ZCHK6, $ ZCHKE, ZMVCH * .. Intrinsic Functions .. INTRINSIC ABS, MAX, MIN * .. Scalars in Common .. INTEGER INFOT, NOUTC LOGICAL LERR, OK CHARACTER*6 SRNAMT * .. Common blocks .. COMMON /INFOC/INFOT, NOUTC, OK, LERR COMMON /SRNAMC/SRNAMT * .. Data statements .. DATA SNAMES/'ZGEMV ', 'ZGBMV ', 'ZHEMV ', 'ZHBMV ', $ 'ZHPMV ', 'ZTRMV ', 'ZTBMV ', 'ZTPMV ', $ 'ZTRSV ', 'ZTBSV ', 'ZTPSV ', 'ZGERC ', $ 'ZGERU ', 'ZHER ', 'ZHPR ', 'ZHER2 ', $ 'ZHPR2 '/ * .. Executable Statements .. * * Read name and unit number for summary output file and open file. * READ( NIN, FMT = * )SUMMRY READ( NIN, FMT = * )NOUT OPEN( NOUT, FILE = SUMMRY, STATUS = 'UNKNOWN' ) NOUTC = NOUT * * Read name and unit number for snapshot output file and open file. * READ( NIN, FMT = * )SNAPS READ( NIN, FMT = * )NTRA TRACE = NTRA.GE.0 IF( TRACE )THEN OPEN( NTRA, FILE = SNAPS, STATUS = 'UNKNOWN' ) END IF * Read the flag that directs rewinding of the snapshot file. READ( NIN, FMT = * )REWI REWI = REWI.AND.TRACE * Read the flag that directs stopping on any failure. READ( NIN, FMT = * )SFATAL * Read the flag that indicates whether error exits are to be tested. READ( NIN, FMT = * )TSTERR * Read the threshold value of the test ratio READ( NIN, FMT = * )THRESH * * Read and check the parameter values for the tests. * * Values of N READ( NIN, FMT = * )NIDIM IF( NIDIM.LT.1.OR.NIDIM.GT.NIDMAX )THEN WRITE( NOUT, FMT = 9997 )'N', NIDMAX GO TO 230 END IF READ( NIN, FMT = * )( IDIM( I ), I = 1, NIDIM ) DO 10 I = 1, NIDIM IF( IDIM( I ).LT.0.OR.IDIM( I ).GT.NMAX )THEN WRITE( NOUT, FMT = 9996 )NMAX GO TO 230 END IF 10 CONTINUE * Values of K READ( NIN, FMT = * )NKB IF( NKB.LT.1.OR.NKB.GT.NKBMAX )THEN WRITE( NOUT, FMT = 9997 )'K', NKBMAX GO TO 230 END IF READ( NIN, FMT = * )( KB( I ), I = 1, NKB ) DO 20 I = 1, NKB IF( KB( I ).LT.0 )THEN WRITE( NOUT, FMT = 9995 ) GO TO 230 END IF 20 CONTINUE * Values of INCX and INCY READ( NIN, FMT = * )NINC IF( NINC.LT.1.OR.NINC.GT.NINMAX )THEN WRITE( NOUT, FMT = 9997 )'INCX AND INCY', NINMAX GO TO 230 END IF READ( NIN, FMT = * )( INC( I ), I = 1, NINC ) DO 30 I = 1, NINC IF( INC( I ).EQ.0.OR.ABS( INC( I ) ).GT.INCMAX )THEN WRITE( NOUT, FMT = 9994 )INCMAX GO TO 230 END IF 30 CONTINUE * Values of ALPHA READ( NIN, FMT = * )NALF IF( NALF.LT.1.OR.NALF.GT.NALMAX )THEN WRITE( NOUT, FMT = 9997 )'ALPHA', NALMAX GO TO 230 END IF READ( NIN, FMT = * )( ALF( I ), I = 1, NALF ) * Values of BETA READ( NIN, FMT = * )NBET IF( NBET.LT.1.OR.NBET.GT.NBEMAX )THEN WRITE( NOUT, FMT = 9997 )'BETA', NBEMAX GO TO 230 END IF READ( NIN, FMT = * )( BET( I ), I = 1, NBET ) * * Report values of parameters. * WRITE( NOUT, FMT = 9993 ) WRITE( NOUT, FMT = 9992 )( IDIM( I ), I = 1, NIDIM ) WRITE( NOUT, FMT = 9991 )( KB( I ), I = 1, NKB ) WRITE( NOUT, FMT = 9990 )( INC( I ), I = 1, NINC ) WRITE( NOUT, FMT = 9989 )( ALF( I ), I = 1, NALF ) WRITE( NOUT, FMT = 9988 )( BET( I ), I = 1, NBET ) IF( .NOT.TSTERR )THEN WRITE( NOUT, FMT = * ) WRITE( NOUT, FMT = 9980 ) END IF WRITE( NOUT, FMT = * ) WRITE( NOUT, FMT = 9999 )THRESH WRITE( NOUT, FMT = * ) * * Read names of subroutines and flags which indicate * whether they are to be tested. * DO 40 I = 1, NSUBS LTEST( I ) = .FALSE. 40 CONTINUE 50 READ( NIN, FMT = 9984, END = 80 )SNAMET, LTESTT DO 60 I = 1, NSUBS IF( SNAMET.EQ.SNAMES( I ) ) $ GO TO 70 60 CONTINUE WRITE( NOUT, FMT = 9986 )SNAMET STOP 70 LTEST( I ) = LTESTT GO TO 50 * 80 CONTINUE CLOSE ( NIN ) * * Compute EPS (the machine precision). * EPS = EPSILON(RZERO) WRITE( NOUT, FMT = 9998 )EPS * * Check the reliability of ZMVCH using exact data. * N = MIN( 32, NMAX ) DO 120 J = 1, N DO 110 I = 1, N A( I, J ) = MAX( I - J + 1, 0 ) 110 CONTINUE X( J ) = J Y( J ) = ZERO 120 CONTINUE DO 130 J = 1, N YY( J ) = J*( ( J + 1 )*J )/2 - ( ( J + 1 )*J*( J - 1 ) )/3 130 CONTINUE * YY holds the exact result. On exit from ZMVCH YT holds * the result computed by ZMVCH. TRANS = 'N' CALL ZMVCH( TRANS, N, N, ONE, A, NMAX, X, 1, ZERO, Y, 1, YT, G, $ YY, EPS, ERR, FATAL, NOUT, .TRUE. ) SAME = LZE( YY, YT, N ) IF( .NOT.SAME.OR.ERR.NE.RZERO )THEN WRITE( NOUT, FMT = 9985 )TRANS, SAME, ERR STOP END IF TRANS = 'T' CALL ZMVCH( TRANS, N, N, ONE, A, NMAX, X, -1, ZERO, Y, -1, YT, G, $ YY, EPS, ERR, FATAL, NOUT, .TRUE. ) SAME = LZE( YY, YT, N ) IF( .NOT.SAME.OR.ERR.NE.RZERO )THEN WRITE( NOUT, FMT = 9985 )TRANS, SAME, ERR STOP END IF * * Test each subroutine in turn. * DO 210 ISNUM = 1, NSUBS WRITE( NOUT, FMT = * ) IF( .NOT.LTEST( ISNUM ) )THEN * Subprogram is not to be tested. WRITE( NOUT, FMT = 9983 )SNAMES( ISNUM ) ELSE SRNAMT = SNAMES( ISNUM ) * Test error exits. IF( TSTERR )THEN CALL ZCHKE( ISNUM, SNAMES( ISNUM ), NOUT ) WRITE( NOUT, FMT = * ) END IF * Test computations. INFOT = 0 OK = .TRUE. FATAL = .FALSE. GO TO ( 140, 140, 150, 150, 150, 160, 160, $ 160, 160, 160, 160, 170, 170, 180, $ 180, 190, 190 )ISNUM * Test ZGEMV, 01, and ZGBMV, 02. 140 CALL ZCHK1( SNAMES( ISNUM ), EPS, THRESH, NOUT, NTRA, TRACE, $ REWI, FATAL, NIDIM, IDIM, NKB, KB, NALF, ALF, $ NBET, BET, NINC, INC, NMAX, INCMAX, A, AA, AS, $ X, XX, XS, Y, YY, YS, YT, G ) GO TO 200 * Test ZHEMV, 03, ZHBMV, 04, and ZHPMV, 05. 150 CALL ZCHK2( SNAMES( ISNUM ), EPS, THRESH, NOUT, NTRA, TRACE, $ REWI, FATAL, NIDIM, IDIM, NKB, KB, NALF, ALF, $ NBET, BET, NINC, INC, NMAX, INCMAX, A, AA, AS, $ X, XX, XS, Y, YY, YS, YT, G ) GO TO 200 * Test ZTRMV, 06, ZTBMV, 07, ZTPMV, 08, * ZTRSV, 09, ZTBSV, 10, and ZTPSV, 11. 160 CALL ZCHK3( SNAMES( ISNUM ), EPS, THRESH, NOUT, NTRA, TRACE, $ REWI, FATAL, NIDIM, IDIM, NKB, KB, NINC, INC, $ NMAX, INCMAX, A, AA, AS, Y, YY, YS, YT, G, Z ) GO TO 200 * Test ZGERC, 12, ZGERU, 13. 170 CALL ZCHK4( SNAMES( ISNUM ), EPS, THRESH, NOUT, NTRA, TRACE, $ REWI, FATAL, NIDIM, IDIM, NALF, ALF, NINC, INC, $ NMAX, INCMAX, A, AA, AS, X, XX, XS, Y, YY, YS, $ YT, G, Z ) GO TO 200 * Test ZHER, 14, and ZHPR, 15. 180 CALL ZCHK5( SNAMES( ISNUM ), EPS, THRESH, NOUT, NTRA, TRACE, $ REWI, FATAL, NIDIM, IDIM, NALF, ALF, NINC, INC, $ NMAX, INCMAX, A, AA, AS, X, XX, XS, Y, YY, YS, $ YT, G, Z ) GO TO 200 * Test ZHER2, 16, and ZHPR2, 17. 190 CALL ZCHK6( SNAMES( ISNUM ), EPS, THRESH, NOUT, NTRA, TRACE, $ REWI, FATAL, NIDIM, IDIM, NALF, ALF, NINC, INC, $ NMAX, INCMAX, A, AA, AS, X, XX, XS, Y, YY, YS, $ YT, G, Z ) * 200 IF( FATAL.AND.SFATAL ) $ GO TO 220 END IF 210 CONTINUE WRITE( NOUT, FMT = 9982 ) GO TO 240 * 220 CONTINUE WRITE( NOUT, FMT = 9981 ) GO TO 240 * 230 CONTINUE WRITE( NOUT, FMT = 9987 ) * 240 CONTINUE IF( TRACE ) $ CLOSE ( NTRA ) CLOSE ( NOUT ) STOP * 9999 FORMAT( ' ROUTINES PASS COMPUTATIONAL TESTS IF TEST RATIO IS LES', $ 'S THAN', F8.2 ) 9998 FORMAT( ' RELATIVE MACHINE PRECISION IS TAKEN TO BE', 1P, D9.1 ) 9997 FORMAT( ' NUMBER OF VALUES OF ', A, ' IS LESS THAN 1 OR GREATER ', $ 'THAN ', I2 ) 9996 FORMAT( ' VALUE OF N IS LESS THAN 0 OR GREATER THAN ', I2 ) 9995 FORMAT( ' VALUE OF K IS LESS THAN 0' ) 9994 FORMAT( ' ABSOLUTE VALUE OF INCX OR INCY IS 0 OR GREATER THAN ', $ I2 ) 9993 FORMAT( ' TESTS OF THE COMPLEX*16 LEVEL 2 BLAS', //' THE F', $ 'OLLOWING PARAMETER VALUES WILL BE USED:' ) 9992 FORMAT( ' FOR N ', 9I6 ) 9991 FORMAT( ' FOR K ', 7I6 ) 9990 FORMAT( ' FOR INCX AND INCY ', 7I6 ) 9989 FORMAT( ' FOR ALPHA ', $ 7( '(', F4.1, ',', F4.1, ') ', : ) ) 9988 FORMAT( ' FOR BETA ', $ 7( '(', F4.1, ',', F4.1, ') ', : ) ) 9987 FORMAT( ' AMEND DATA FILE OR INCREASE ARRAY SIZES IN PROGRAM', $ /' ******* TESTS ABANDONED *******' ) 9986 FORMAT( ' SUBPROGRAM NAME ', A6, ' NOT RECOGNIZED', /' ******* T', $ 'ESTS ABANDONED *******' ) 9985 FORMAT( ' ERROR IN ZMVCH - IN-LINE DOT PRODUCTS ARE BEING EVALU', $ 'ATED WRONGLY.', /' ZMVCH WAS CALLED WITH TRANS = ', A1, $ ' AND RETURNED SAME = ', L1, ' AND ERR = ', F12.3, '.', / $ ' THIS MAY BE DUE TO FAULTS IN THE ARITHMETIC OR THE COMPILER.' $ , /' ******* TESTS ABANDONED *******' ) 9984 FORMAT( A6, L2 ) 9983 FORMAT( 1X, A6, ' WAS NOT TESTED' ) 9982 FORMAT( /' END OF TESTS' ) 9981 FORMAT( /' ******* FATAL ERROR - TESTS ABANDONED *******' ) 9980 FORMAT( ' ERROR-EXITS WILL NOT BE TESTED' ) * * End of ZBLAT2. * END SUBROUTINE ZCHK1( SNAME, EPS, THRESH, NOUT, NTRA, TRACE, REWI, $ FATAL, NIDIM, IDIM, NKB, KB, NALF, ALF, NBET, $ BET, NINC, INC, NMAX, INCMAX, A, AA, AS, X, XX, $ XS, Y, YY, YS, YT, G ) * * Tests ZGEMV and ZGBMV. * * Auxiliary routine for test program for Level 2 Blas. * * -- Written on 10-August-1987. * Richard Hanson, Sandia National Labs. * Jeremy Du Croz, NAG Central Office. * * .. Parameters .. COMPLEX*16 ZERO, HALF PARAMETER ( ZERO = ( 0.0D0, 0.0D0 ), $ HALF = ( 0.5D0, 0.0D0 ) ) DOUBLE PRECISION RZERO PARAMETER ( RZERO = 0.0D0 ) * .. Scalar Arguments .. DOUBLE PRECISION EPS, THRESH INTEGER INCMAX, NALF, NBET, NIDIM, NINC, NKB, NMAX, $ NOUT, NTRA LOGICAL FATAL, REWI, TRACE CHARACTER*6 SNAME * .. Array Arguments .. COMPLEX*16 A( NMAX, NMAX ), AA( NMAX*NMAX ), ALF( NALF ), $ AS( NMAX*NMAX ), BET( NBET ), X( NMAX ), $ XS( NMAX*INCMAX ), XX( NMAX*INCMAX ), $ Y( NMAX ), YS( NMAX*INCMAX ), YT( NMAX ), $ YY( NMAX*INCMAX ) DOUBLE PRECISION G( NMAX ) INTEGER IDIM( NIDIM ), INC( NINC ), KB( NKB ) * .. Local Scalars .. COMPLEX*16 ALPHA, ALS, BETA, BLS, TRANSL DOUBLE PRECISION ERR, ERRMAX INTEGER I, IA, IB, IC, IKU, IM, IN, INCX, INCXS, INCY, $ INCYS, IX, IY, KL, KLS, KU, KUS, LAA, LDA, $ LDAS, LX, LY, M, ML, MS, N, NARGS, NC, ND, NK, $ NL, NS LOGICAL BANDED, FULL, NULL, RESET, SAME, TRAN CHARACTER*1 TRANS, TRANSS CHARACTER*3 ICH * .. Local Arrays .. LOGICAL ISAME( 13 ) * .. External Functions .. LOGICAL LZE, LZERES EXTERNAL LZE, LZERES * .. External Subroutines .. EXTERNAL ZGBMV, ZGEMV, ZMAKE, ZMVCH * .. Intrinsic Functions .. INTRINSIC ABS, MAX, MIN * .. Scalars in Common .. INTEGER INFOT, NOUTC LOGICAL LERR, OK * .. Common blocks .. COMMON /INFOC/INFOT, NOUTC, OK, LERR * .. Data statements .. DATA ICH/'NTC'/ * .. Executable Statements .. FULL = SNAME( 3: 3 ).EQ.'E' BANDED = SNAME( 3: 3 ).EQ.'B' * Define the number of arguments. IF( FULL )THEN NARGS = 11 ELSE IF( BANDED )THEN NARGS = 13 END IF * NC = 0 RESET = .TRUE. ERRMAX = RZERO * DO 120 IN = 1, NIDIM N = IDIM( IN ) ND = N/2 + 1 * DO 110 IM = 1, 2 IF( IM.EQ.1 ) $ M = MAX( N - ND, 0 ) IF( IM.EQ.2 ) $ M = MIN( N + ND, NMAX ) * IF( BANDED )THEN NK = NKB ELSE NK = 1 END IF DO 100 IKU = 1, NK IF( BANDED )THEN KU = KB( IKU ) KL = MAX( KU - 1, 0 ) ELSE KU = N - 1 KL = M - 1 END IF * Set LDA to 1 more than minimum value if room. IF( BANDED )THEN LDA = KL + KU + 1 ELSE LDA = M END IF IF( LDA.LT.NMAX ) $ LDA = LDA + 1 * Skip tests if not enough room. IF( LDA.GT.NMAX ) $ GO TO 100 LAA = LDA*N NULL = N.LE.0.OR.M.LE.0 * * Generate the matrix A. * TRANSL = ZERO CALL ZMAKE( SNAME( 2: 3 ), ' ', ' ', M, N, A, NMAX, AA, $ LDA, KL, KU, RESET, TRANSL ) * DO 90 IC = 1, 3 TRANS = ICH( IC: IC ) TRAN = TRANS.EQ.'T'.OR.TRANS.EQ.'C' * IF( TRAN )THEN ML = N NL = M ELSE ML = M NL = N END IF * DO 80 IX = 1, NINC INCX = INC( IX ) LX = ABS( INCX )*NL * * Generate the vector X. * TRANSL = HALF CALL ZMAKE( 'GE', ' ', ' ', 1, NL, X, 1, XX, $ ABS( INCX ), 0, NL - 1, RESET, TRANSL ) IF( NL.GT.1 )THEN X( NL/2 ) = ZERO XX( 1 + ABS( INCX )*( NL/2 - 1 ) ) = ZERO END IF * DO 70 IY = 1, NINC INCY = INC( IY ) LY = ABS( INCY )*ML * DO 60 IA = 1, NALF ALPHA = ALF( IA ) * DO 50 IB = 1, NBET BETA = BET( IB ) * * Generate the vector Y. * TRANSL = ZERO CALL ZMAKE( 'GE', ' ', ' ', 1, ML, Y, 1, $ YY, ABS( INCY ), 0, ML - 1, $ RESET, TRANSL ) * NC = NC + 1 * * Save every datum before calling the * subroutine. * TRANSS = TRANS MS = M NS = N KLS = KL KUS = KU ALS = ALPHA DO 10 I = 1, LAA AS( I ) = AA( I ) 10 CONTINUE LDAS = LDA DO 20 I = 1, LX XS( I ) = XX( I ) 20 CONTINUE INCXS = INCX BLS = BETA DO 30 I = 1, LY YS( I ) = YY( I ) 30 CONTINUE INCYS = INCY * * Call the subroutine. * IF( FULL )THEN IF( TRACE ) $ WRITE( NTRA, FMT = 9994 )NC, SNAME, $ TRANS, M, N, ALPHA, LDA, INCX, BETA, $ INCY IF( REWI ) $ REWIND NTRA CALL ZGEMV( TRANS, M, N, ALPHA, AA, $ LDA, XX, INCX, BETA, YY, $ INCY ) ELSE IF( BANDED )THEN IF( TRACE ) $ WRITE( NTRA, FMT = 9995 )NC, SNAME, $ TRANS, M, N, KL, KU, ALPHA, LDA, $ INCX, BETA, INCY IF( REWI ) $ REWIND NTRA CALL ZGBMV( TRANS, M, N, KL, KU, ALPHA, $ AA, LDA, XX, INCX, BETA, $ YY, INCY ) END IF * * Check if error-exit was taken incorrectly. * IF( .NOT.OK )THEN WRITE( NOUT, FMT = 9993 ) FATAL = .TRUE. GO TO 130 END IF * * See what data changed inside subroutines. * ISAME( 1 ) = TRANS.EQ.TRANSS ISAME( 2 ) = MS.EQ.M ISAME( 3 ) = NS.EQ.N IF( FULL )THEN ISAME( 4 ) = ALS.EQ.ALPHA ISAME( 5 ) = LZE( AS, AA, LAA ) ISAME( 6 ) = LDAS.EQ.LDA ISAME( 7 ) = LZE( XS, XX, LX ) ISAME( 8 ) = INCXS.EQ.INCX ISAME( 9 ) = BLS.EQ.BETA IF( NULL )THEN ISAME( 10 ) = LZE( YS, YY, LY ) ELSE ISAME( 10 ) = LZERES( 'GE', ' ', 1, $ ML, YS, YY, $ ABS( INCY ) ) END IF ISAME( 11 ) = INCYS.EQ.INCY ELSE IF( BANDED )THEN ISAME( 4 ) = KLS.EQ.KL ISAME( 5 ) = KUS.EQ.KU ISAME( 6 ) = ALS.EQ.ALPHA ISAME( 7 ) = LZE( AS, AA, LAA ) ISAME( 8 ) = LDAS.EQ.LDA ISAME( 9 ) = LZE( XS, XX, LX ) ISAME( 10 ) = INCXS.EQ.INCX ISAME( 11 ) = BLS.EQ.BETA IF( NULL )THEN ISAME( 12 ) = LZE( YS, YY, LY ) ELSE ISAME( 12 ) = LZERES( 'GE', ' ', 1, $ ML, YS, YY, $ ABS( INCY ) ) END IF ISAME( 13 ) = INCYS.EQ.INCY END IF * * If data was incorrectly changed, report * and return. * SAME = .TRUE. DO 40 I = 1, NARGS SAME = SAME.AND.ISAME( I ) IF( .NOT.ISAME( I ) ) $ WRITE( NOUT, FMT = 9998 )I 40 CONTINUE IF( .NOT.SAME )THEN FATAL = .TRUE. GO TO 130 END IF * IF( .NOT.NULL )THEN * * Check the result. * CALL ZMVCH( TRANS, M, N, ALPHA, A, $ NMAX, X, INCX, BETA, Y, $ INCY, YT, G, YY, EPS, ERR, $ FATAL, NOUT, .TRUE. ) ERRMAX = MAX( ERRMAX, ERR ) * If got really bad answer, report and * return. IF( FATAL ) $ GO TO 130 ELSE * Avoid repeating tests with M.le.0 or * N.le.0. GO TO 110 END IF * 50 CONTINUE * 60 CONTINUE * 70 CONTINUE * 80 CONTINUE * 90 CONTINUE * 100 CONTINUE * 110 CONTINUE * 120 CONTINUE * * Report result. * IF( ERRMAX.LT.THRESH )THEN WRITE( NOUT, FMT = 9999 )SNAME, NC ELSE WRITE( NOUT, FMT = 9997 )SNAME, NC, ERRMAX END IF GO TO 140 * 130 CONTINUE WRITE( NOUT, FMT = 9996 )SNAME IF( FULL )THEN WRITE( NOUT, FMT = 9994 )NC, SNAME, TRANS, M, N, ALPHA, LDA, $ INCX, BETA, INCY ELSE IF( BANDED )THEN WRITE( NOUT, FMT = 9995 )NC, SNAME, TRANS, M, N, KL, KU, $ ALPHA, LDA, INCX, BETA, INCY END IF * 140 CONTINUE RETURN * 9999 FORMAT( ' ', A6, ' PASSED THE COMPUTATIONAL TESTS (', I6, ' CALL', $ 'S)' ) 9998 FORMAT( ' ******* FATAL ERROR - PARAMETER NUMBER ', I2, ' WAS CH', $ 'ANGED INCORRECTLY *******' ) 9997 FORMAT( ' ', A6, ' COMPLETED THE COMPUTATIONAL TESTS (', I6, ' C', $ 'ALLS)', /' ******* BUT WITH MAXIMUM TEST RATIO', F8.2, $ ' - SUSPECT *******' ) 9996 FORMAT( ' ******* ', A6, ' FAILED ON CALL NUMBER:' ) 9995 FORMAT( 1X, I6, ': ', A6, '(''', A1, ''',', 4( I3, ',' ), '(', $ F4.1, ',', F4.1, '), A,', I3, ', X,', I2, ',(', F4.1, ',', $ F4.1, '), Y,', I2, ') .' ) 9994 FORMAT( 1X, I6, ': ', A6, '(''', A1, ''',', 2( I3, ',' ), '(', $ F4.1, ',', F4.1, '), A,', I3, ', X,', I2, ',(', F4.1, ',', $ F4.1, '), Y,', I2, ') .' ) 9993 FORMAT( ' ******* FATAL ERROR - ERROR-EXIT TAKEN ON VALID CALL *', $ '******' ) * * End of ZCHK1. * END SUBROUTINE ZCHK2( SNAME, EPS, THRESH, NOUT, NTRA, TRACE, REWI, $ FATAL, NIDIM, IDIM, NKB, KB, NALF, ALF, NBET, $ BET, NINC, INC, NMAX, INCMAX, A, AA, AS, X, XX, $ XS, Y, YY, YS, YT, G ) * * Tests ZHEMV, ZHBMV and ZHPMV. * * Auxiliary routine for test program for Level 2 Blas. * * -- Written on 10-August-1987. * Richard Hanson, Sandia National Labs. * Jeremy Du Croz, NAG Central Office. * * .. Parameters .. COMPLEX*16 ZERO, HALF PARAMETER ( ZERO = ( 0.0D0, 0.0D0 ), $ HALF = ( 0.5D0, 0.0D0 ) ) DOUBLE PRECISION RZERO PARAMETER ( RZERO = 0.0D0 ) * .. Scalar Arguments .. DOUBLE PRECISION EPS, THRESH INTEGER INCMAX, NALF, NBET, NIDIM, NINC, NKB, NMAX, $ NOUT, NTRA LOGICAL FATAL, REWI, TRACE CHARACTER*6 SNAME * .. Array Arguments .. COMPLEX*16 A( NMAX, NMAX ), AA( NMAX*NMAX ), ALF( NALF ), $ AS( NMAX*NMAX ), BET( NBET ), X( NMAX ), $ XS( NMAX*INCMAX ), XX( NMAX*INCMAX ), $ Y( NMAX ), YS( NMAX*INCMAX ), YT( NMAX ), $ YY( NMAX*INCMAX ) DOUBLE PRECISION G( NMAX ) INTEGER IDIM( NIDIM ), INC( NINC ), KB( NKB ) * .. Local Scalars .. COMPLEX*16 ALPHA, ALS, BETA, BLS, TRANSL DOUBLE PRECISION ERR, ERRMAX INTEGER I, IA, IB, IC, IK, IN, INCX, INCXS, INCY, $ INCYS, IX, IY, K, KS, LAA, LDA, LDAS, LX, LY, $ N, NARGS, NC, NK, NS LOGICAL BANDED, FULL, NULL, PACKED, RESET, SAME CHARACTER*1 UPLO, UPLOS CHARACTER*2 ICH * .. Local Arrays .. LOGICAL ISAME( 13 ) * .. External Functions .. LOGICAL LZE, LZERES EXTERNAL LZE, LZERES * .. External Subroutines .. EXTERNAL ZHBMV, ZHEMV, ZHPMV, ZMAKE, ZMVCH * .. Intrinsic Functions .. INTRINSIC ABS, MAX * .. Scalars in Common .. INTEGER INFOT, NOUTC LOGICAL LERR, OK * .. Common blocks .. COMMON /INFOC/INFOT, NOUTC, OK, LERR * .. Data statements .. DATA ICH/'UL'/ * .. Executable Statements .. FULL = SNAME( 3: 3 ).EQ.'E' BANDED = SNAME( 3: 3 ).EQ.'B' PACKED = SNAME( 3: 3 ).EQ.'P' * Define the number of arguments. IF( FULL )THEN NARGS = 10 ELSE IF( BANDED )THEN NARGS = 11 ELSE IF( PACKED )THEN NARGS = 9 END IF * NC = 0 RESET = .TRUE. ERRMAX = RZERO * DO 110 IN = 1, NIDIM N = IDIM( IN ) * IF( BANDED )THEN NK = NKB ELSE NK = 1 END IF DO 100 IK = 1, NK IF( BANDED )THEN K = KB( IK ) ELSE K = N - 1 END IF * Set LDA to 1 more than minimum value if room. IF( BANDED )THEN LDA = K + 1 ELSE LDA = N END IF IF( LDA.LT.NMAX ) $ LDA = LDA + 1 * Skip tests if not enough room. IF( LDA.GT.NMAX ) $ GO TO 100 IF( PACKED )THEN LAA = ( N*( N + 1 ) )/2 ELSE LAA = LDA*N END IF NULL = N.LE.0 * DO 90 IC = 1, 2 UPLO = ICH( IC: IC ) * * Generate the matrix A. * TRANSL = ZERO CALL ZMAKE( SNAME( 2: 3 ), UPLO, ' ', N, N, A, NMAX, AA, $ LDA, K, K, RESET, TRANSL ) * DO 80 IX = 1, NINC INCX = INC( IX ) LX = ABS( INCX )*N * * Generate the vector X. * TRANSL = HALF CALL ZMAKE( 'GE', ' ', ' ', 1, N, X, 1, XX, $ ABS( INCX ), 0, N - 1, RESET, TRANSL ) IF( N.GT.1 )THEN X( N/2 ) = ZERO XX( 1 + ABS( INCX )*( N/2 - 1 ) ) = ZERO END IF * DO 70 IY = 1, NINC INCY = INC( IY ) LY = ABS( INCY )*N * DO 60 IA = 1, NALF ALPHA = ALF( IA ) * DO 50 IB = 1, NBET BETA = BET( IB ) * * Generate the vector Y. * TRANSL = ZERO CALL ZMAKE( 'GE', ' ', ' ', 1, N, Y, 1, YY, $ ABS( INCY ), 0, N - 1, RESET, $ TRANSL ) * NC = NC + 1 * * Save every datum before calling the * subroutine. * UPLOS = UPLO NS = N KS = K ALS = ALPHA DO 10 I = 1, LAA AS( I ) = AA( I ) 10 CONTINUE LDAS = LDA DO 20 I = 1, LX XS( I ) = XX( I ) 20 CONTINUE INCXS = INCX BLS = BETA DO 30 I = 1, LY YS( I ) = YY( I ) 30 CONTINUE INCYS = INCY * * Call the subroutine. * IF( FULL )THEN IF( TRACE ) $ WRITE( NTRA, FMT = 9993 )NC, SNAME, $ UPLO, N, ALPHA, LDA, INCX, BETA, INCY IF( REWI ) $ REWIND NTRA CALL ZHEMV( UPLO, N, ALPHA, AA, LDA, XX, $ INCX, BETA, YY, INCY ) ELSE IF( BANDED )THEN IF( TRACE ) $ WRITE( NTRA, FMT = 9994 )NC, SNAME, $ UPLO, N, K, ALPHA, LDA, INCX, BETA, $ INCY IF( REWI ) $ REWIND NTRA CALL ZHBMV( UPLO, N, K, ALPHA, AA, LDA, $ XX, INCX, BETA, YY, INCY ) ELSE IF( PACKED )THEN IF( TRACE ) $ WRITE( NTRA, FMT = 9995 )NC, SNAME, $ UPLO, N, ALPHA, INCX, BETA, INCY IF( REWI ) $ REWIND NTRA CALL ZHPMV( UPLO, N, ALPHA, AA, XX, INCX, $ BETA, YY, INCY ) END IF * * Check if error-exit was taken incorrectly. * IF( .NOT.OK )THEN WRITE( NOUT, FMT = 9992 ) FATAL = .TRUE. GO TO 120 END IF * * See what data changed inside subroutines. * ISAME( 1 ) = UPLO.EQ.UPLOS ISAME( 2 ) = NS.EQ.N IF( FULL )THEN ISAME( 3 ) = ALS.EQ.ALPHA ISAME( 4 ) = LZE( AS, AA, LAA ) ISAME( 5 ) = LDAS.EQ.LDA ISAME( 6 ) = LZE( XS, XX, LX ) ISAME( 7 ) = INCXS.EQ.INCX ISAME( 8 ) = BLS.EQ.BETA IF( NULL )THEN ISAME( 9 ) = LZE( YS, YY, LY ) ELSE ISAME( 9 ) = LZERES( 'GE', ' ', 1, N, $ YS, YY, ABS( INCY ) ) END IF ISAME( 10 ) = INCYS.EQ.INCY ELSE IF( BANDED )THEN ISAME( 3 ) = KS.EQ.K ISAME( 4 ) = ALS.EQ.ALPHA ISAME( 5 ) = LZE( AS, AA, LAA ) ISAME( 6 ) = LDAS.EQ.LDA ISAME( 7 ) = LZE( XS, XX, LX ) ISAME( 8 ) = INCXS.EQ.INCX ISAME( 9 ) = BLS.EQ.BETA IF( NULL )THEN ISAME( 10 ) = LZE( YS, YY, LY ) ELSE ISAME( 10 ) = LZERES( 'GE', ' ', 1, N, $ YS, YY, ABS( INCY ) ) END IF ISAME( 11 ) = INCYS.EQ.INCY ELSE IF( PACKED )THEN ISAME( 3 ) = ALS.EQ.ALPHA ISAME( 4 ) = LZE( AS, AA, LAA ) ISAME( 5 ) = LZE( XS, XX, LX ) ISAME( 6 ) = INCXS.EQ.INCX ISAME( 7 ) = BLS.EQ.BETA IF( NULL )THEN ISAME( 8 ) = LZE( YS, YY, LY ) ELSE ISAME( 8 ) = LZERES( 'GE', ' ', 1, N, $ YS, YY, ABS( INCY ) ) END IF ISAME( 9 ) = INCYS.EQ.INCY END IF * * If data was incorrectly changed, report and * return. * SAME = .TRUE. DO 40 I = 1, NARGS SAME = SAME.AND.ISAME( I ) IF( .NOT.ISAME( I ) ) $ WRITE( NOUT, FMT = 9998 )I 40 CONTINUE IF( .NOT.SAME )THEN FATAL = .TRUE. GO TO 120 END IF * IF( .NOT.NULL )THEN * * Check the result. * CALL ZMVCH( 'N', N, N, ALPHA, A, NMAX, X, $ INCX, BETA, Y, INCY, YT, G, $ YY, EPS, ERR, FATAL, NOUT, $ .TRUE. ) ERRMAX = MAX( ERRMAX, ERR ) * If got really bad answer, report and * return. IF( FATAL ) $ GO TO 120 ELSE * Avoid repeating tests with N.le.0 GO TO 110 END IF * 50 CONTINUE * 60 CONTINUE * 70 CONTINUE * 80 CONTINUE * 90 CONTINUE * 100 CONTINUE * 110 CONTINUE * * Report result. * IF( ERRMAX.LT.THRESH )THEN WRITE( NOUT, FMT = 9999 )SNAME, NC ELSE WRITE( NOUT, FMT = 9997 )SNAME, NC, ERRMAX END IF GO TO 130 * 120 CONTINUE WRITE( NOUT, FMT = 9996 )SNAME IF( FULL )THEN WRITE( NOUT, FMT = 9993 )NC, SNAME, UPLO, N, ALPHA, LDA, INCX, $ BETA, INCY ELSE IF( BANDED )THEN WRITE( NOUT, FMT = 9994 )NC, SNAME, UPLO, N, K, ALPHA, LDA, $ INCX, BETA, INCY ELSE IF( PACKED )THEN WRITE( NOUT, FMT = 9995 )NC, SNAME, UPLO, N, ALPHA, INCX, $ BETA, INCY END IF * 130 CONTINUE RETURN * 9999 FORMAT( ' ', A6, ' PASSED THE COMPUTATIONAL TESTS (', I6, ' CALL', $ 'S)' ) 9998 FORMAT( ' ******* FATAL ERROR - PARAMETER NUMBER ', I2, ' WAS CH', $ 'ANGED INCORRECTLY *******' ) 9997 FORMAT( ' ', A6, ' COMPLETED THE COMPUTATIONAL TESTS (', I6, ' C', $ 'ALLS)', /' ******* BUT WITH MAXIMUM TEST RATIO', F8.2, $ ' - SUSPECT *******' ) 9996 FORMAT( ' ******* ', A6, ' FAILED ON CALL NUMBER:' ) 9995 FORMAT( 1X, I6, ': ', A6, '(''', A1, ''',', I3, ',(', F4.1, ',', $ F4.1, '), AP, X,', I2, ',(', F4.1, ',', F4.1, '), Y,', I2, $ ') .' ) 9994 FORMAT( 1X, I6, ': ', A6, '(''', A1, ''',', 2( I3, ',' ), '(', $ F4.1, ',', F4.1, '), A,', I3, ', X,', I2, ',(', F4.1, ',', $ F4.1, '), Y,', I2, ') .' ) 9993 FORMAT( 1X, I6, ': ', A6, '(''', A1, ''',', I3, ',(', F4.1, ',', $ F4.1, '), A,', I3, ', X,', I2, ',(', F4.1, ',', F4.1, '), ', $ 'Y,', I2, ') .' ) 9992 FORMAT( ' ******* FATAL ERROR - ERROR-EXIT TAKEN ON VALID CALL *', $ '******' ) * * End of ZCHK2. * END SUBROUTINE ZCHK3( SNAME, EPS, THRESH, NOUT, NTRA, TRACE, REWI, $ FATAL, NIDIM, IDIM, NKB, KB, NINC, INC, NMAX, $ INCMAX, A, AA, AS, X, XX, XS, XT, G, Z ) * * Tests ZTRMV, ZTBMV, ZTPMV, ZTRSV, ZTBSV and ZTPSV. * * Auxiliary routine for test program for Level 2 Blas. * * -- Written on 10-August-1987. * Richard Hanson, Sandia National Labs. * Jeremy Du Croz, NAG Central Office. * * .. Parameters .. COMPLEX*16 ZERO, HALF, ONE PARAMETER ( ZERO = ( 0.0D0, 0.0D0 ), $ HALF = ( 0.5D0, 0.0D0 ), $ ONE = ( 1.0D0, 0.0D0 ) ) DOUBLE PRECISION RZERO PARAMETER ( RZERO = 0.0D0 ) * .. Scalar Arguments .. DOUBLE PRECISION EPS, THRESH INTEGER INCMAX, NIDIM, NINC, NKB, NMAX, NOUT, NTRA LOGICAL FATAL, REWI, TRACE CHARACTER*6 SNAME * .. Array Arguments .. COMPLEX*16 A( NMAX, NMAX ), AA( NMAX*NMAX ), $ AS( NMAX*NMAX ), X( NMAX ), XS( NMAX*INCMAX ), $ XT( NMAX ), XX( NMAX*INCMAX ), Z( NMAX ) DOUBLE PRECISION G( NMAX ) INTEGER IDIM( NIDIM ), INC( NINC ), KB( NKB ) * .. Local Scalars .. COMPLEX*16 TRANSL DOUBLE PRECISION ERR, ERRMAX INTEGER I, ICD, ICT, ICU, IK, IN, INCX, INCXS, IX, K, $ KS, LAA, LDA, LDAS, LX, N, NARGS, NC, NK, NS LOGICAL BANDED, FULL, NULL, PACKED, RESET, SAME CHARACTER*1 DIAG, DIAGS, TRANS, TRANSS, UPLO, UPLOS CHARACTER*2 ICHD, ICHU CHARACTER*3 ICHT * .. Local Arrays .. LOGICAL ISAME( 13 ) * .. External Functions .. LOGICAL LZE, LZERES EXTERNAL LZE, LZERES * .. External Subroutines .. EXTERNAL ZMAKE, ZMVCH, ZTBMV, ZTBSV, ZTPMV, ZTPSV, $ ZTRMV, ZTRSV * .. Intrinsic Functions .. INTRINSIC ABS, MAX * .. Scalars in Common .. INTEGER INFOT, NOUTC LOGICAL LERR, OK * .. Common blocks .. COMMON /INFOC/INFOT, NOUTC, OK, LERR * .. Data statements .. DATA ICHU/'UL'/, ICHT/'NTC'/, ICHD/'UN'/ * .. Executable Statements .. FULL = SNAME( 3: 3 ).EQ.'R' BANDED = SNAME( 3: 3 ).EQ.'B' PACKED = SNAME( 3: 3 ).EQ.'P' * Define the number of arguments. IF( FULL )THEN NARGS = 8 ELSE IF( BANDED )THEN NARGS = 9 ELSE IF( PACKED )THEN NARGS = 7 END IF * NC = 0 RESET = .TRUE. ERRMAX = RZERO * Set up zero vector for ZMVCH. DO 10 I = 1, NMAX Z( I ) = ZERO 10 CONTINUE * DO 110 IN = 1, NIDIM N = IDIM( IN ) * IF( BANDED )THEN NK = NKB ELSE NK = 1 END IF DO 100 IK = 1, NK IF( BANDED )THEN K = KB( IK ) ELSE K = N - 1 END IF * Set LDA to 1 more than minimum value if room. IF( BANDED )THEN LDA = K + 1 ELSE LDA = N END IF IF( LDA.LT.NMAX ) $ LDA = LDA + 1 * Skip tests if not enough room. IF( LDA.GT.NMAX ) $ GO TO 100 IF( PACKED )THEN LAA = ( N*( N + 1 ) )/2 ELSE LAA = LDA*N END IF NULL = N.LE.0 * DO 90 ICU = 1, 2 UPLO = ICHU( ICU: ICU ) * DO 80 ICT = 1, 3 TRANS = ICHT( ICT: ICT ) * DO 70 ICD = 1, 2 DIAG = ICHD( ICD: ICD ) * * Generate the matrix A. * TRANSL = ZERO CALL ZMAKE( SNAME( 2: 3 ), UPLO, DIAG, N, N, A, $ NMAX, AA, LDA, K, K, RESET, TRANSL ) * DO 60 IX = 1, NINC INCX = INC( IX ) LX = ABS( INCX )*N * * Generate the vector X. * TRANSL = HALF CALL ZMAKE( 'GE', ' ', ' ', 1, N, X, 1, XX, $ ABS( INCX ), 0, N - 1, RESET, $ TRANSL ) IF( N.GT.1 )THEN X( N/2 ) = ZERO XX( 1 + ABS( INCX )*( N/2 - 1 ) ) = ZERO END IF * NC = NC + 1 * * Save every datum before calling the subroutine. * UPLOS = UPLO TRANSS = TRANS DIAGS = DIAG NS = N KS = K DO 20 I = 1, LAA AS( I ) = AA( I ) 20 CONTINUE LDAS = LDA DO 30 I = 1, LX XS( I ) = XX( I ) 30 CONTINUE INCXS = INCX * * Call the subroutine. * IF( SNAME( 4: 5 ).EQ.'MV' )THEN IF( FULL )THEN IF( TRACE ) $ WRITE( NTRA, FMT = 9993 )NC, SNAME, $ UPLO, TRANS, DIAG, N, LDA, INCX IF( REWI ) $ REWIND NTRA CALL ZTRMV( UPLO, TRANS, DIAG, N, AA, LDA, $ XX, INCX ) ELSE IF( BANDED )THEN IF( TRACE ) $ WRITE( NTRA, FMT = 9994 )NC, SNAME, $ UPLO, TRANS, DIAG, N, K, LDA, INCX IF( REWI ) $ REWIND NTRA CALL ZTBMV( UPLO, TRANS, DIAG, N, K, AA, $ LDA, XX, INCX ) ELSE IF( PACKED )THEN IF( TRACE ) $ WRITE( NTRA, FMT = 9995 )NC, SNAME, $ UPLO, TRANS, DIAG, N, INCX IF( REWI ) $ REWIND NTRA CALL ZTPMV( UPLO, TRANS, DIAG, N, AA, XX, $ INCX ) END IF ELSE IF( SNAME( 4: 5 ).EQ.'SV' )THEN IF( FULL )THEN IF( TRACE ) $ WRITE( NTRA, FMT = 9993 )NC, SNAME, $ UPLO, TRANS, DIAG, N, LDA, INCX IF( REWI ) $ REWIND NTRA CALL ZTRSV( UPLO, TRANS, DIAG, N, AA, LDA, $ XX, INCX ) ELSE IF( BANDED )THEN IF( TRACE ) $ WRITE( NTRA, FMT = 9994 )NC, SNAME, $ UPLO, TRANS, DIAG, N, K, LDA, INCX IF( REWI ) $ REWIND NTRA CALL ZTBSV( UPLO, TRANS, DIAG, N, K, AA, $ LDA, XX, INCX ) ELSE IF( PACKED )THEN IF( TRACE ) $ WRITE( NTRA, FMT = 9995 )NC, SNAME, $ UPLO, TRANS, DIAG, N, INCX IF( REWI ) $ REWIND NTRA CALL ZTPSV( UPLO, TRANS, DIAG, N, AA, XX, $ INCX ) END IF END IF * * Check if error-exit was taken incorrectly. * IF( .NOT.OK )THEN WRITE( NOUT, FMT = 9992 ) FATAL = .TRUE. GO TO 120 END IF * * See what data changed inside subroutines. * ISAME( 1 ) = UPLO.EQ.UPLOS ISAME( 2 ) = TRANS.EQ.TRANSS ISAME( 3 ) = DIAG.EQ.DIAGS ISAME( 4 ) = NS.EQ.N IF( FULL )THEN ISAME( 5 ) = LZE( AS, AA, LAA ) ISAME( 6 ) = LDAS.EQ.LDA IF( NULL )THEN ISAME( 7 ) = LZE( XS, XX, LX ) ELSE ISAME( 7 ) = LZERES( 'GE', ' ', 1, N, XS, $ XX, ABS( INCX ) ) END IF ISAME( 8 ) = INCXS.EQ.INCX ELSE IF( BANDED )THEN ISAME( 5 ) = KS.EQ.K ISAME( 6 ) = LZE( AS, AA, LAA ) ISAME( 7 ) = LDAS.EQ.LDA IF( NULL )THEN ISAME( 8 ) = LZE( XS, XX, LX ) ELSE ISAME( 8 ) = LZERES( 'GE', ' ', 1, N, XS, $ XX, ABS( INCX ) ) END IF ISAME( 9 ) = INCXS.EQ.INCX ELSE IF( PACKED )THEN ISAME( 5 ) = LZE( AS, AA, LAA ) IF( NULL )THEN ISAME( 6 ) = LZE( XS, XX, LX ) ELSE ISAME( 6 ) = LZERES( 'GE', ' ', 1, N, XS, $ XX, ABS( INCX ) ) END IF ISAME( 7 ) = INCXS.EQ.INCX END IF * * If data was incorrectly changed, report and * return. * SAME = .TRUE. DO 40 I = 1, NARGS SAME = SAME.AND.ISAME( I ) IF( .NOT.ISAME( I ) ) $ WRITE( NOUT, FMT = 9998 )I 40 CONTINUE IF( .NOT.SAME )THEN FATAL = .TRUE. GO TO 120 END IF * IF( .NOT.NULL )THEN IF( SNAME( 4: 5 ).EQ.'MV' )THEN * * Check the result. * CALL ZMVCH( TRANS, N, N, ONE, A, NMAX, X, $ INCX, ZERO, Z, INCX, XT, G, $ XX, EPS, ERR, FATAL, NOUT, $ .TRUE. ) ELSE IF( SNAME( 4: 5 ).EQ.'SV' )THEN * * Compute approximation to original vector. * DO 50 I = 1, N Z( I ) = XX( 1 + ( I - 1 )* $ ABS( INCX ) ) XX( 1 + ( I - 1 )*ABS( INCX ) ) $ = X( I ) 50 CONTINUE CALL ZMVCH( TRANS, N, N, ONE, A, NMAX, Z, $ INCX, ZERO, X, INCX, XT, G, $ XX, EPS, ERR, FATAL, NOUT, $ .FALSE. ) END IF ERRMAX = MAX( ERRMAX, ERR ) * If got really bad answer, report and return. IF( FATAL ) $ GO TO 120 ELSE * Avoid repeating tests with N.le.0. GO TO 110 END IF * 60 CONTINUE * 70 CONTINUE * 80 CONTINUE * 90 CONTINUE * 100 CONTINUE * 110 CONTINUE * * Report result. * IF( ERRMAX.LT.THRESH )THEN WRITE( NOUT, FMT = 9999 )SNAME, NC ELSE WRITE( NOUT, FMT = 9997 )SNAME, NC, ERRMAX END IF GO TO 130 * 120 CONTINUE WRITE( NOUT, FMT = 9996 )SNAME IF( FULL )THEN WRITE( NOUT, FMT = 9993 )NC, SNAME, UPLO, TRANS, DIAG, N, LDA, $ INCX ELSE IF( BANDED )THEN WRITE( NOUT, FMT = 9994 )NC, SNAME, UPLO, TRANS, DIAG, N, K, $ LDA, INCX ELSE IF( PACKED )THEN WRITE( NOUT, FMT = 9995 )NC, SNAME, UPLO, TRANS, DIAG, N, INCX END IF * 130 CONTINUE RETURN * 9999 FORMAT( ' ', A6, ' PASSED THE COMPUTATIONAL TESTS (', I6, ' CALL', $ 'S)' ) 9998 FORMAT( ' ******* FATAL ERROR - PARAMETER NUMBER ', I2, ' WAS CH', $ 'ANGED INCORRECTLY *******' ) 9997 FORMAT( ' ', A6, ' COMPLETED THE COMPUTATIONAL TESTS (', I6, ' C', $ 'ALLS)', /' ******* BUT WITH MAXIMUM TEST RATIO', F8.2, $ ' - SUSPECT *******' ) 9996 FORMAT( ' ******* ', A6, ' FAILED ON CALL NUMBER:' ) 9995 FORMAT( 1X, I6, ': ', A6, '(', 3( '''', A1, ''',' ), I3, ', AP, ', $ 'X,', I2, ') .' ) 9994 FORMAT( 1X, I6, ': ', A6, '(', 3( '''', A1, ''',' ), 2( I3, ',' ), $ ' A,', I3, ', X,', I2, ') .' ) 9993 FORMAT( 1X, I6, ': ', A6, '(', 3( '''', A1, ''',' ), I3, ', A,', $ I3, ', X,', I2, ') .' ) 9992 FORMAT( ' ******* FATAL ERROR - ERROR-EXIT TAKEN ON VALID CALL *', $ '******' ) * * End of ZCHK3. * END SUBROUTINE ZCHK4( SNAME, EPS, THRESH, NOUT, NTRA, TRACE, REWI, $ FATAL, NIDIM, IDIM, NALF, ALF, NINC, INC, NMAX, $ INCMAX, A, AA, AS, X, XX, XS, Y, YY, YS, YT, G, $ Z ) * * Tests ZGERC and ZGERU. * * Auxiliary routine for test program for Level 2 Blas. * * -- Written on 10-August-1987. * Richard Hanson, Sandia National Labs. * Jeremy Du Croz, NAG Central Office. * * .. Parameters .. COMPLEX*16 ZERO, HALF, ONE PARAMETER ( ZERO = ( 0.0D0, 0.0D0 ), $ HALF = ( 0.5D0, 0.0D0 ), $ ONE = ( 1.0D0, 0.0D0 ) ) DOUBLE PRECISION RZERO PARAMETER ( RZERO = 0.0D0 ) * .. Scalar Arguments .. DOUBLE PRECISION EPS, THRESH INTEGER INCMAX, NALF, NIDIM, NINC, NMAX, NOUT, NTRA LOGICAL FATAL, REWI, TRACE CHARACTER*6 SNAME * .. Array Arguments .. COMPLEX*16 A( NMAX, NMAX ), AA( NMAX*NMAX ), ALF( NALF ), $ AS( NMAX*NMAX ), X( NMAX ), XS( NMAX*INCMAX ), $ XX( NMAX*INCMAX ), Y( NMAX ), $ YS( NMAX*INCMAX ), YT( NMAX ), $ YY( NMAX*INCMAX ), Z( NMAX ) DOUBLE PRECISION G( NMAX ) INTEGER IDIM( NIDIM ), INC( NINC ) * .. Local Scalars .. COMPLEX*16 ALPHA, ALS, TRANSL DOUBLE PRECISION ERR, ERRMAX INTEGER I, IA, IM, IN, INCX, INCXS, INCY, INCYS, IX, $ IY, J, LAA, LDA, LDAS, LX, LY, M, MS, N, NARGS, $ NC, ND, NS LOGICAL CONJ, NULL, RESET, SAME * .. Local Arrays .. COMPLEX*16 W( 1 ) LOGICAL ISAME( 13 ) * .. External Functions .. LOGICAL LZE, LZERES EXTERNAL LZE, LZERES * .. External Subroutines .. EXTERNAL ZGERC, ZGERU, ZMAKE, ZMVCH * .. Intrinsic Functions .. INTRINSIC ABS, DCONJG, MAX, MIN * .. Scalars in Common .. INTEGER INFOT, NOUTC LOGICAL LERR, OK * .. Common blocks .. COMMON /INFOC/INFOT, NOUTC, OK, LERR * .. Executable Statements .. CONJ = SNAME( 5: 5 ).EQ.'C' * Define the number of arguments. NARGS = 9 * NC = 0 RESET = .TRUE. ERRMAX = RZERO * DO 120 IN = 1, NIDIM N = IDIM( IN ) ND = N/2 + 1 * DO 110 IM = 1, 2 IF( IM.EQ.1 ) $ M = MAX( N - ND, 0 ) IF( IM.EQ.2 ) $ M = MIN( N + ND, NMAX ) * * Set LDA to 1 more than minimum value if room. LDA = M IF( LDA.LT.NMAX ) $ LDA = LDA + 1 * Skip tests if not enough room. IF( LDA.GT.NMAX ) $ GO TO 110 LAA = LDA*N NULL = N.LE.0.OR.M.LE.0 * DO 100 IX = 1, NINC INCX = INC( IX ) LX = ABS( INCX )*M * * Generate the vector X. * TRANSL = HALF CALL ZMAKE( 'GE', ' ', ' ', 1, M, X, 1, XX, ABS( INCX ), $ 0, M - 1, RESET, TRANSL ) IF( M.GT.1 )THEN X( M/2 ) = ZERO XX( 1 + ABS( INCX )*( M/2 - 1 ) ) = ZERO END IF * DO 90 IY = 1, NINC INCY = INC( IY ) LY = ABS( INCY )*N * * Generate the vector Y. * TRANSL = ZERO CALL ZMAKE( 'GE', ' ', ' ', 1, N, Y, 1, YY, $ ABS( INCY ), 0, N - 1, RESET, TRANSL ) IF( N.GT.1 )THEN Y( N/2 ) = ZERO YY( 1 + ABS( INCY )*( N/2 - 1 ) ) = ZERO END IF * DO 80 IA = 1, NALF ALPHA = ALF( IA ) * * Generate the matrix A. * TRANSL = ZERO CALL ZMAKE( SNAME( 2: 3 ), ' ', ' ', M, N, A, NMAX, $ AA, LDA, M - 1, N - 1, RESET, TRANSL ) * NC = NC + 1 * * Save every datum before calling the subroutine. * MS = M NS = N ALS = ALPHA DO 10 I = 1, LAA AS( I ) = AA( I ) 10 CONTINUE LDAS = LDA DO 20 I = 1, LX XS( I ) = XX( I ) 20 CONTINUE INCXS = INCX DO 30 I = 1, LY YS( I ) = YY( I ) 30 CONTINUE INCYS = INCY * * Call the subroutine. * IF( TRACE ) $ WRITE( NTRA, FMT = 9994 )NC, SNAME, M, N, $ ALPHA, INCX, INCY, LDA IF( CONJ )THEN IF( REWI ) $ REWIND NTRA CALL ZGERC( M, N, ALPHA, XX, INCX, YY, INCY, AA, $ LDA ) ELSE IF( REWI ) $ REWIND NTRA CALL ZGERU( M, N, ALPHA, XX, INCX, YY, INCY, AA, $ LDA ) END IF * * Check if error-exit was taken incorrectly. * IF( .NOT.OK )THEN WRITE( NOUT, FMT = 9993 ) FATAL = .TRUE. GO TO 140 END IF * * See what data changed inside subroutine. * ISAME( 1 ) = MS.EQ.M ISAME( 2 ) = NS.EQ.N ISAME( 3 ) = ALS.EQ.ALPHA ISAME( 4 ) = LZE( XS, XX, LX ) ISAME( 5 ) = INCXS.EQ.INCX ISAME( 6 ) = LZE( YS, YY, LY ) ISAME( 7 ) = INCYS.EQ.INCY IF( NULL )THEN ISAME( 8 ) = LZE( AS, AA, LAA ) ELSE ISAME( 8 ) = LZERES( 'GE', ' ', M, N, AS, AA, $ LDA ) END IF ISAME( 9 ) = LDAS.EQ.LDA * * If data was incorrectly changed, report and return. * SAME = .TRUE. DO 40 I = 1, NARGS SAME = SAME.AND.ISAME( I ) IF( .NOT.ISAME( I ) ) $ WRITE( NOUT, FMT = 9998 )I 40 CONTINUE IF( .NOT.SAME )THEN FATAL = .TRUE. GO TO 140 END IF * IF( .NOT.NULL )THEN * * Check the result column by column. * IF( INCX.GT.0 )THEN DO 50 I = 1, M Z( I ) = X( I ) 50 CONTINUE ELSE DO 60 I = 1, M Z( I ) = X( M - I + 1 ) 60 CONTINUE END IF DO 70 J = 1, N IF( INCY.GT.0 )THEN W( 1 ) = Y( J ) ELSE W( 1 ) = Y( N - J + 1 ) END IF IF( CONJ ) $ W( 1 ) = DCONJG( W( 1 ) ) CALL ZMVCH( 'N', M, 1, ALPHA, Z, NMAX, W, 1, $ ONE, A( 1, J ), 1, YT, G, $ AA( 1 + ( J - 1 )*LDA ), EPS, $ ERR, FATAL, NOUT, .TRUE. ) ERRMAX = MAX( ERRMAX, ERR ) * If got really bad answer, report and return. IF( FATAL ) $ GO TO 130 70 CONTINUE ELSE * Avoid repeating tests with M.le.0 or N.le.0. GO TO 110 END IF * 80 CONTINUE * 90 CONTINUE * 100 CONTINUE * 110 CONTINUE * 120 CONTINUE * * Report result. * IF( ERRMAX.LT.THRESH )THEN WRITE( NOUT, FMT = 9999 )SNAME, NC ELSE WRITE( NOUT, FMT = 9997 )SNAME, NC, ERRMAX END IF GO TO 150 * 130 CONTINUE WRITE( NOUT, FMT = 9995 )J * 140 CONTINUE WRITE( NOUT, FMT = 9996 )SNAME WRITE( NOUT, FMT = 9994 )NC, SNAME, M, N, ALPHA, INCX, INCY, LDA * 150 CONTINUE RETURN * 9999 FORMAT( ' ', A6, ' PASSED THE COMPUTATIONAL TESTS (', I6, ' CALL', $ 'S)' ) 9998 FORMAT( ' ******* FATAL ERROR - PARAMETER NUMBER ', I2, ' WAS CH', $ 'ANGED INCORRECTLY *******' ) 9997 FORMAT( ' ', A6, ' COMPLETED THE COMPUTATIONAL TESTS (', I6, ' C', $ 'ALLS)', /' ******* BUT WITH MAXIMUM TEST RATIO', F8.2, $ ' - SUSPECT *******' ) 9996 FORMAT( ' ******* ', A6, ' FAILED ON CALL NUMBER:' ) 9995 FORMAT( ' THESE ARE THE RESULTS FOR COLUMN ', I3 ) 9994 FORMAT( 1X, I6, ': ', A6, '(', 2( I3, ',' ), '(', F4.1, ',', F4.1, $ '), X,', I2, ', Y,', I2, ', A,', I3, ') ', $ ' .' ) 9993 FORMAT( ' ******* FATAL ERROR - ERROR-EXIT TAKEN ON VALID CALL *', $ '******' ) * * End of ZCHK4. * END SUBROUTINE ZCHK5( SNAME, EPS, THRESH, NOUT, NTRA, TRACE, REWI, $ FATAL, NIDIM, IDIM, NALF, ALF, NINC, INC, NMAX, $ INCMAX, A, AA, AS, X, XX, XS, Y, YY, YS, YT, G, $ Z ) * * Tests ZHER and ZHPR. * * Auxiliary routine for test program for Level 2 Blas. * * -- Written on 10-August-1987. * Richard Hanson, Sandia National Labs. * Jeremy Du Croz, NAG Central Office. * * .. Parameters .. COMPLEX*16 ZERO, HALF, ONE PARAMETER ( ZERO = ( 0.0D0, 0.0D0 ), $ HALF = ( 0.5D0, 0.0D0 ), $ ONE = ( 1.0D0, 0.0D0 ) ) DOUBLE PRECISION RZERO PARAMETER ( RZERO = 0.0D0 ) * .. Scalar Arguments .. DOUBLE PRECISION EPS, THRESH INTEGER INCMAX, NALF, NIDIM, NINC, NMAX, NOUT, NTRA LOGICAL FATAL, REWI, TRACE CHARACTER*6 SNAME * .. Array Arguments .. COMPLEX*16 A( NMAX, NMAX ), AA( NMAX*NMAX ), ALF( NALF ), $ AS( NMAX*NMAX ), X( NMAX ), XS( NMAX*INCMAX ), $ XX( NMAX*INCMAX ), Y( NMAX ), $ YS( NMAX*INCMAX ), YT( NMAX ), $ YY( NMAX*INCMAX ), Z( NMAX ) DOUBLE PRECISION G( NMAX ) INTEGER IDIM( NIDIM ), INC( NINC ) * .. Local Scalars .. COMPLEX*16 ALPHA, TRANSL DOUBLE PRECISION ERR, ERRMAX, RALPHA, RALS INTEGER I, IA, IC, IN, INCX, INCXS, IX, J, JA, JJ, LAA, $ LDA, LDAS, LJ, LX, N, NARGS, NC, NS LOGICAL FULL, NULL, PACKED, RESET, SAME, UPPER CHARACTER*1 UPLO, UPLOS CHARACTER*2 ICH * .. Local Arrays .. COMPLEX*16 W( 1 ) LOGICAL ISAME( 13 ) * .. External Functions .. LOGICAL LZE, LZERES EXTERNAL LZE, LZERES * .. External Subroutines .. EXTERNAL ZHER, ZHPR, ZMAKE, ZMVCH * .. Intrinsic Functions .. INTRINSIC ABS, DBLE, DCMPLX, DCONJG, MAX * .. Scalars in Common .. INTEGER INFOT, NOUTC LOGICAL LERR, OK * .. Common blocks .. COMMON /INFOC/INFOT, NOUTC, OK, LERR * .. Data statements .. DATA ICH/'UL'/ * .. Executable Statements .. FULL = SNAME( 3: 3 ).EQ.'E' PACKED = SNAME( 3: 3 ).EQ.'P' * Define the number of arguments. IF( FULL )THEN NARGS = 7 ELSE IF( PACKED )THEN NARGS = 6 END IF * NC = 0 RESET = .TRUE. ERRMAX = RZERO * DO 100 IN = 1, NIDIM N = IDIM( IN ) * Set LDA to 1 more than minimum value if room. LDA = N IF( LDA.LT.NMAX ) $ LDA = LDA + 1 * Skip tests if not enough room. IF( LDA.GT.NMAX ) $ GO TO 100 IF( PACKED )THEN LAA = ( N*( N + 1 ) )/2 ELSE LAA = LDA*N END IF * DO 90 IC = 1, 2 UPLO = ICH( IC: IC ) UPPER = UPLO.EQ.'U' * DO 80 IX = 1, NINC INCX = INC( IX ) LX = ABS( INCX )*N * * Generate the vector X. * TRANSL = HALF CALL ZMAKE( 'GE', ' ', ' ', 1, N, X, 1, XX, ABS( INCX ), $ 0, N - 1, RESET, TRANSL ) IF( N.GT.1 )THEN X( N/2 ) = ZERO XX( 1 + ABS( INCX )*( N/2 - 1 ) ) = ZERO END IF * DO 70 IA = 1, NALF RALPHA = DBLE( ALF( IA ) ) ALPHA = DCMPLX( RALPHA, RZERO ) NULL = N.LE.0.OR.RALPHA.EQ.RZERO * * Generate the matrix A. * TRANSL = ZERO CALL ZMAKE( SNAME( 2: 3 ), UPLO, ' ', N, N, A, NMAX, $ AA, LDA, N - 1, N - 1, RESET, TRANSL ) * NC = NC + 1 * * Save every datum before calling the subroutine. * UPLOS = UPLO NS = N RALS = RALPHA DO 10 I = 1, LAA AS( I ) = AA( I ) 10 CONTINUE LDAS = LDA DO 20 I = 1, LX XS( I ) = XX( I ) 20 CONTINUE INCXS = INCX * * Call the subroutine. * IF( FULL )THEN IF( TRACE ) $ WRITE( NTRA, FMT = 9993 )NC, SNAME, UPLO, N, $ RALPHA, INCX, LDA IF( REWI ) $ REWIND NTRA CALL ZHER( UPLO, N, RALPHA, XX, INCX, AA, LDA ) ELSE IF( PACKED )THEN IF( TRACE ) $ WRITE( NTRA, FMT = 9994 )NC, SNAME, UPLO, N, $ RALPHA, INCX IF( REWI ) $ REWIND NTRA CALL ZHPR( UPLO, N, RALPHA, XX, INCX, AA ) END IF * * Check if error-exit was taken incorrectly. * IF( .NOT.OK )THEN WRITE( NOUT, FMT = 9992 ) FATAL = .TRUE. GO TO 120 END IF * * See what data changed inside subroutines. * ISAME( 1 ) = UPLO.EQ.UPLOS ISAME( 2 ) = NS.EQ.N ISAME( 3 ) = RALS.EQ.RALPHA ISAME( 4 ) = LZE( XS, XX, LX ) ISAME( 5 ) = INCXS.EQ.INCX IF( NULL )THEN ISAME( 6 ) = LZE( AS, AA, LAA ) ELSE ISAME( 6 ) = LZERES( SNAME( 2: 3 ), UPLO, N, N, AS, $ AA, LDA ) END IF IF( .NOT.PACKED )THEN ISAME( 7 ) = LDAS.EQ.LDA END IF * * If data was incorrectly changed, report and return. * SAME = .TRUE. DO 30 I = 1, NARGS SAME = SAME.AND.ISAME( I ) IF( .NOT.ISAME( I ) ) $ WRITE( NOUT, FMT = 9998 )I 30 CONTINUE IF( .NOT.SAME )THEN FATAL = .TRUE. GO TO 120 END IF * IF( .NOT.NULL )THEN * * Check the result column by column. * IF( INCX.GT.0 )THEN DO 40 I = 1, N Z( I ) = X( I ) 40 CONTINUE ELSE DO 50 I = 1, N Z( I ) = X( N - I + 1 ) 50 CONTINUE END IF JA = 1 DO 60 J = 1, N W( 1 ) = DCONJG( Z( J ) ) IF( UPPER )THEN JJ = 1 LJ = J ELSE JJ = J LJ = N - J + 1 END IF CALL ZMVCH( 'N', LJ, 1, ALPHA, Z( JJ ), LJ, W, $ 1, ONE, A( JJ, J ), 1, YT, G, $ AA( JA ), EPS, ERR, FATAL, NOUT, $ .TRUE. ) IF( FULL )THEN IF( UPPER )THEN JA = JA + LDA ELSE JA = JA + LDA + 1 END IF ELSE JA = JA + LJ END IF ERRMAX = MAX( ERRMAX, ERR ) * If got really bad answer, report and return. IF( FATAL ) $ GO TO 110 60 CONTINUE ELSE * Avoid repeating tests if N.le.0. IF( N.LE.0 ) $ GO TO 100 END IF * 70 CONTINUE * 80 CONTINUE * 90 CONTINUE * 100 CONTINUE * * Report result. * IF( ERRMAX.LT.THRESH )THEN WRITE( NOUT, FMT = 9999 )SNAME, NC ELSE WRITE( NOUT, FMT = 9997 )SNAME, NC, ERRMAX END IF GO TO 130 * 110 CONTINUE WRITE( NOUT, FMT = 9995 )J * 120 CONTINUE WRITE( NOUT, FMT = 9996 )SNAME IF( FULL )THEN WRITE( NOUT, FMT = 9993 )NC, SNAME, UPLO, N, RALPHA, INCX, LDA ELSE IF( PACKED )THEN WRITE( NOUT, FMT = 9994 )NC, SNAME, UPLO, N, RALPHA, INCX END IF * 130 CONTINUE RETURN * 9999 FORMAT( ' ', A6, ' PASSED THE COMPUTATIONAL TESTS (', I6, ' CALL', $ 'S)' ) 9998 FORMAT( ' ******* FATAL ERROR - PARAMETER NUMBER ', I2, ' WAS CH', $ 'ANGED INCORRECTLY *******' ) 9997 FORMAT( ' ', A6, ' COMPLETED THE COMPUTATIONAL TESTS (', I6, ' C', $ 'ALLS)', /' ******* BUT WITH MAXIMUM TEST RATIO', F8.2, $ ' - SUSPECT *******' ) 9996 FORMAT( ' ******* ', A6, ' FAILED ON CALL NUMBER:' ) 9995 FORMAT( ' THESE ARE THE RESULTS FOR COLUMN ', I3 ) 9994 FORMAT( 1X, I6, ': ', A6, '(''', A1, ''',', I3, ',', F4.1, ', X,', $ I2, ', AP) .' ) 9993 FORMAT( 1X, I6, ': ', A6, '(''', A1, ''',', I3, ',', F4.1, ', X,', $ I2, ', A,', I3, ') .' ) 9992 FORMAT( ' ******* FATAL ERROR - ERROR-EXIT TAKEN ON VALID CALL *', $ '******' ) * * End of ZCHK5. * END SUBROUTINE ZCHK6( SNAME, EPS, THRESH, NOUT, NTRA, TRACE, REWI, $ FATAL, NIDIM, IDIM, NALF, ALF, NINC, INC, NMAX, $ INCMAX, A, AA, AS, X, XX, XS, Y, YY, YS, YT, G, $ Z ) * * Tests ZHER2 and ZHPR2. * * Auxiliary routine for test program for Level 2 Blas. * * -- Written on 10-August-1987. * Richard Hanson, Sandia National Labs. * Jeremy Du Croz, NAG Central Office. * * .. Parameters .. COMPLEX*16 ZERO, HALF, ONE PARAMETER ( ZERO = ( 0.0D0, 0.0D0 ), $ HALF = ( 0.5D0, 0.0D0 ), $ ONE = ( 1.0D0, 0.0D0 ) ) DOUBLE PRECISION RZERO PARAMETER ( RZERO = 0.0D0 ) * .. Scalar Arguments .. DOUBLE PRECISION EPS, THRESH INTEGER INCMAX, NALF, NIDIM, NINC, NMAX, NOUT, NTRA LOGICAL FATAL, REWI, TRACE CHARACTER*6 SNAME * .. Array Arguments .. COMPLEX*16 A( NMAX, NMAX ), AA( NMAX*NMAX ), ALF( NALF ), $ AS( NMAX*NMAX ), X( NMAX ), XS( NMAX*INCMAX ), $ XX( NMAX*INCMAX ), Y( NMAX ), $ YS( NMAX*INCMAX ), YT( NMAX ), $ YY( NMAX*INCMAX ), Z( NMAX, 2 ) DOUBLE PRECISION G( NMAX ) INTEGER IDIM( NIDIM ), INC( NINC ) * .. Local Scalars .. COMPLEX*16 ALPHA, ALS, TRANSL DOUBLE PRECISION ERR, ERRMAX INTEGER I, IA, IC, IN, INCX, INCXS, INCY, INCYS, IX, $ IY, J, JA, JJ, LAA, LDA, LDAS, LJ, LX, LY, N, $ NARGS, NC, NS LOGICAL FULL, NULL, PACKED, RESET, SAME, UPPER CHARACTER*1 UPLO, UPLOS CHARACTER*2 ICH * .. Local Arrays .. COMPLEX*16 W( 2 ) LOGICAL ISAME( 13 ) * .. External Functions .. LOGICAL LZE, LZERES EXTERNAL LZE, LZERES * .. External Subroutines .. EXTERNAL ZHER2, ZHPR2, ZMAKE, ZMVCH * .. Intrinsic Functions .. INTRINSIC ABS, DCONJG, MAX * .. Scalars in Common .. INTEGER INFOT, NOUTC LOGICAL LERR, OK * .. Common blocks .. COMMON /INFOC/INFOT, NOUTC, OK, LERR * .. Data statements .. DATA ICH/'UL'/ * .. Executable Statements .. FULL = SNAME( 3: 3 ).EQ.'E' PACKED = SNAME( 3: 3 ).EQ.'P' * Define the number of arguments. IF( FULL )THEN NARGS = 9 ELSE IF( PACKED )THEN NARGS = 8 END IF * NC = 0 RESET = .TRUE. ERRMAX = RZERO * DO 140 IN = 1, NIDIM N = IDIM( IN ) * Set LDA to 1 more than minimum value if room. LDA = N IF( LDA.LT.NMAX ) $ LDA = LDA + 1 * Skip tests if not enough room. IF( LDA.GT.NMAX ) $ GO TO 140 IF( PACKED )THEN LAA = ( N*( N + 1 ) )/2 ELSE LAA = LDA*N END IF * DO 130 IC = 1, 2 UPLO = ICH( IC: IC ) UPPER = UPLO.EQ.'U' * DO 120 IX = 1, NINC INCX = INC( IX ) LX = ABS( INCX )*N * * Generate the vector X. * TRANSL = HALF CALL ZMAKE( 'GE', ' ', ' ', 1, N, X, 1, XX, ABS( INCX ), $ 0, N - 1, RESET, TRANSL ) IF( N.GT.1 )THEN X( N/2 ) = ZERO XX( 1 + ABS( INCX )*( N/2 - 1 ) ) = ZERO END IF * DO 110 IY = 1, NINC INCY = INC( IY ) LY = ABS( INCY )*N * * Generate the vector Y. * TRANSL = ZERO CALL ZMAKE( 'GE', ' ', ' ', 1, N, Y, 1, YY, $ ABS( INCY ), 0, N - 1, RESET, TRANSL ) IF( N.GT.1 )THEN Y( N/2 ) = ZERO YY( 1 + ABS( INCY )*( N/2 - 1 ) ) = ZERO END IF * DO 100 IA = 1, NALF ALPHA = ALF( IA ) NULL = N.LE.0.OR.ALPHA.EQ.ZERO * * Generate the matrix A. * TRANSL = ZERO CALL ZMAKE( SNAME( 2: 3 ), UPLO, ' ', N, N, A, $ NMAX, AA, LDA, N - 1, N - 1, RESET, $ TRANSL ) * NC = NC + 1 * * Save every datum before calling the subroutine. * UPLOS = UPLO NS = N ALS = ALPHA DO 10 I = 1, LAA AS( I ) = AA( I ) 10 CONTINUE LDAS = LDA DO 20 I = 1, LX XS( I ) = XX( I ) 20 CONTINUE INCXS = INCX DO 30 I = 1, LY YS( I ) = YY( I ) 30 CONTINUE INCYS = INCY * * Call the subroutine. * IF( FULL )THEN IF( TRACE ) $ WRITE( NTRA, FMT = 9993 )NC, SNAME, UPLO, N, $ ALPHA, INCX, INCY, LDA IF( REWI ) $ REWIND NTRA CALL ZHER2( UPLO, N, ALPHA, XX, INCX, YY, INCY, $ AA, LDA ) ELSE IF( PACKED )THEN IF( TRACE ) $ WRITE( NTRA, FMT = 9994 )NC, SNAME, UPLO, N, $ ALPHA, INCX, INCY IF( REWI ) $ REWIND NTRA CALL ZHPR2( UPLO, N, ALPHA, XX, INCX, YY, INCY, $ AA ) END IF * * Check if error-exit was taken incorrectly. * IF( .NOT.OK )THEN WRITE( NOUT, FMT = 9992 ) FATAL = .TRUE. GO TO 160 END IF * * See what data changed inside subroutines. * ISAME( 1 ) = UPLO.EQ.UPLOS ISAME( 2 ) = NS.EQ.N ISAME( 3 ) = ALS.EQ.ALPHA ISAME( 4 ) = LZE( XS, XX, LX ) ISAME( 5 ) = INCXS.EQ.INCX ISAME( 6 ) = LZE( YS, YY, LY ) ISAME( 7 ) = INCYS.EQ.INCY IF( NULL )THEN ISAME( 8 ) = LZE( AS, AA, LAA ) ELSE ISAME( 8 ) = LZERES( SNAME( 2: 3 ), UPLO, N, N, $ AS, AA, LDA ) END IF IF( .NOT.PACKED )THEN ISAME( 9 ) = LDAS.EQ.LDA END IF * * If data was incorrectly changed, report and return. * SAME = .TRUE. DO 40 I = 1, NARGS SAME = SAME.AND.ISAME( I ) IF( .NOT.ISAME( I ) ) $ WRITE( NOUT, FMT = 9998 )I 40 CONTINUE IF( .NOT.SAME )THEN FATAL = .TRUE. GO TO 160 END IF * IF( .NOT.NULL )THEN * * Check the result column by column. * IF( INCX.GT.0 )THEN DO 50 I = 1, N Z( I, 1 ) = X( I ) 50 CONTINUE ELSE DO 60 I = 1, N Z( I, 1 ) = X( N - I + 1 ) 60 CONTINUE END IF IF( INCY.GT.0 )THEN DO 70 I = 1, N Z( I, 2 ) = Y( I ) 70 CONTINUE ELSE DO 80 I = 1, N Z( I, 2 ) = Y( N - I + 1 ) 80 CONTINUE END IF JA = 1 DO 90 J = 1, N W( 1 ) = ALPHA*DCONJG( Z( J, 2 ) ) W( 2 ) = DCONJG( ALPHA )*DCONJG( Z( J, 1 ) ) IF( UPPER )THEN JJ = 1 LJ = J ELSE JJ = J LJ = N - J + 1 END IF CALL ZMVCH( 'N', LJ, 2, ONE, Z( JJ, 1 ), $ NMAX, W, 1, ONE, A( JJ, J ), 1, $ YT, G, AA( JA ), EPS, ERR, FATAL, $ NOUT, .TRUE. ) IF( FULL )THEN IF( UPPER )THEN JA = JA + LDA ELSE JA = JA + LDA + 1 END IF ELSE JA = JA + LJ END IF ERRMAX = MAX( ERRMAX, ERR ) * If got really bad answer, report and return. IF( FATAL ) $ GO TO 150 90 CONTINUE ELSE * Avoid repeating tests with N.le.0. IF( N.LE.0 ) $ GO TO 140 END IF * 100 CONTINUE * 110 CONTINUE * 120 CONTINUE * 130 CONTINUE * 140 CONTINUE * * Report result. * IF( ERRMAX.LT.THRESH )THEN WRITE( NOUT, FMT = 9999 )SNAME, NC ELSE WRITE( NOUT, FMT = 9997 )SNAME, NC, ERRMAX END IF GO TO 170 * 150 CONTINUE WRITE( NOUT, FMT = 9995 )J * 160 CONTINUE WRITE( NOUT, FMT = 9996 )SNAME IF( FULL )THEN WRITE( NOUT, FMT = 9993 )NC, SNAME, UPLO, N, ALPHA, INCX, $ INCY, LDA ELSE IF( PACKED )THEN WRITE( NOUT, FMT = 9994 )NC, SNAME, UPLO, N, ALPHA, INCX, INCY END IF * 170 CONTINUE RETURN * 9999 FORMAT( ' ', A6, ' PASSED THE COMPUTATIONAL TESTS (', I6, ' CALL', $ 'S)' ) 9998 FORMAT( ' ******* FATAL ERROR - PARAMETER NUMBER ', I2, ' WAS CH', $ 'ANGED INCORRECTLY *******' ) 9997 FORMAT( ' ', A6, ' COMPLETED THE COMPUTATIONAL TESTS (', I6, ' C', $ 'ALLS)', /' ******* BUT WITH MAXIMUM TEST RATIO', F8.2, $ ' - SUSPECT *******' ) 9996 FORMAT( ' ******* ', A6, ' FAILED ON CALL NUMBER:' ) 9995 FORMAT( ' THESE ARE THE RESULTS FOR COLUMN ', I3 ) 9994 FORMAT( 1X, I6, ': ', A6, '(''', A1, ''',', I3, ',(', F4.1, ',', $ F4.1, '), X,', I2, ', Y,', I2, ', AP) ', $ ' .' ) 9993 FORMAT( 1X, I6, ': ', A6, '(''', A1, ''',', I3, ',(', F4.1, ',', $ F4.1, '), X,', I2, ', Y,', I2, ', A,', I3, ') ', $ ' .' ) 9992 FORMAT( ' ******* FATAL ERROR - ERROR-EXIT TAKEN ON VALID CALL *', $ '******' ) * * End of ZCHK6. * END SUBROUTINE ZCHKE( ISNUM, SRNAMT, NOUT ) * * Tests the error exits from the Level 2 Blas. * Requires a special version of the error-handling routine XERBLA. * ALPHA, RALPHA, BETA, A, X and Y should not need to be defined. * * Auxiliary routine for test program for Level 2 Blas. * * -- Written on 10-August-1987. * Richard Hanson, Sandia National Labs. * Jeremy Du Croz, NAG Central Office. * * .. Scalar Arguments .. INTEGER ISNUM, NOUT CHARACTER*6 SRNAMT * .. Scalars in Common .. INTEGER INFOT, NOUTC LOGICAL LERR, OK * .. Local Scalars .. COMPLEX*16 ALPHA, BETA DOUBLE PRECISION RALPHA * .. Local Arrays .. COMPLEX*16 A( 1, 1 ), X( 1 ), Y( 1 ) * .. External Subroutines .. EXTERNAL CHKXER, ZGBMV, ZGEMV, ZGERC, ZGERU, ZHBMV, $ ZHEMV, ZHER, ZHER2, ZHPMV, ZHPR, ZHPR2, ZTBMV, $ ZTBSV, ZTPMV, ZTPSV, ZTRMV, ZTRSV * .. Common blocks .. COMMON /INFOC/INFOT, NOUTC, OK, LERR * .. Executable Statements .. * OK is set to .FALSE. by the special version of XERBLA or by CHKXER * if anything is wrong. OK = .TRUE. * LERR is set to .TRUE. by the special version of XERBLA each time * it is called, and is then tested and re-set by CHKXER. LERR = .FALSE. GO TO ( 10, 20, 30, 40, 50, 60, 70, 80, $ 90, 100, 110, 120, 130, 140, 150, 160, $ 170 )ISNUM 10 INFOT = 1 CALL ZGEMV( '/', 0, 0, ALPHA, A, 1, X, 1, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL ZGEMV( 'N', -1, 0, ALPHA, A, 1, X, 1, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL ZGEMV( 'N', 0, -1, ALPHA, A, 1, X, 1, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL ZGEMV( 'N', 2, 0, ALPHA, A, 1, X, 1, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 8 CALL ZGEMV( 'N', 0, 0, ALPHA, A, 1, X, 0, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL ZGEMV( 'N', 0, 0, ALPHA, A, 1, X, 1, BETA, Y, 0 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 180 20 INFOT = 1 CALL ZGBMV( '/', 0, 0, 0, 0, ALPHA, A, 1, X, 1, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL ZGBMV( 'N', -1, 0, 0, 0, ALPHA, A, 1, X, 1, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL ZGBMV( 'N', 0, -1, 0, 0, ALPHA, A, 1, X, 1, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL ZGBMV( 'N', 0, 0, -1, 0, ALPHA, A, 1, X, 1, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL ZGBMV( 'N', 2, 0, 0, -1, ALPHA, A, 1, X, 1, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 8 CALL ZGBMV( 'N', 0, 0, 1, 0, ALPHA, A, 1, X, 1, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 10 CALL ZGBMV( 'N', 0, 0, 0, 0, ALPHA, A, 1, X, 0, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 13 CALL ZGBMV( 'N', 0, 0, 0, 0, ALPHA, A, 1, X, 1, BETA, Y, 0 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 180 30 INFOT = 1 CALL ZHEMV( '/', 0, ALPHA, A, 1, X, 1, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL ZHEMV( 'U', -1, ALPHA, A, 1, X, 1, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL ZHEMV( 'U', 2, ALPHA, A, 1, X, 1, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL ZHEMV( 'U', 0, ALPHA, A, 1, X, 0, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 10 CALL ZHEMV( 'U', 0, ALPHA, A, 1, X, 1, BETA, Y, 0 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 180 40 INFOT = 1 CALL ZHBMV( '/', 0, 0, ALPHA, A, 1, X, 1, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL ZHBMV( 'U', -1, 0, ALPHA, A, 1, X, 1, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL ZHBMV( 'U', 0, -1, ALPHA, A, 1, X, 1, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL ZHBMV( 'U', 0, 1, ALPHA, A, 1, X, 1, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 8 CALL ZHBMV( 'U', 0, 0, ALPHA, A, 1, X, 0, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL ZHBMV( 'U', 0, 0, ALPHA, A, 1, X, 1, BETA, Y, 0 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 180 50 INFOT = 1 CALL ZHPMV( '/', 0, ALPHA, A, X, 1, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL ZHPMV( 'U', -1, ALPHA, A, X, 1, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL ZHPMV( 'U', 0, ALPHA, A, X, 0, BETA, Y, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL ZHPMV( 'U', 0, ALPHA, A, X, 1, BETA, Y, 0 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 180 60 INFOT = 1 CALL ZTRMV( '/', 'N', 'N', 0, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL ZTRMV( 'U', '/', 'N', 0, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL ZTRMV( 'U', 'N', '/', 0, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL ZTRMV( 'U', 'N', 'N', -1, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL ZTRMV( 'U', 'N', 'N', 2, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 8 CALL ZTRMV( 'U', 'N', 'N', 0, A, 1, X, 0 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 180 70 INFOT = 1 CALL ZTBMV( '/', 'N', 'N', 0, 0, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL ZTBMV( 'U', '/', 'N', 0, 0, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL ZTBMV( 'U', 'N', '/', 0, 0, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL ZTBMV( 'U', 'N', 'N', -1, 0, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL ZTBMV( 'U', 'N', 'N', 0, -1, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL ZTBMV( 'U', 'N', 'N', 0, 1, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL ZTBMV( 'U', 'N', 'N', 0, 0, A, 1, X, 0 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 180 80 INFOT = 1 CALL ZTPMV( '/', 'N', 'N', 0, A, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL ZTPMV( 'U', '/', 'N', 0, A, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL ZTPMV( 'U', 'N', '/', 0, A, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL ZTPMV( 'U', 'N', 'N', -1, A, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL ZTPMV( 'U', 'N', 'N', 0, A, X, 0 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 180 90 INFOT = 1 CALL ZTRSV( '/', 'N', 'N', 0, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL ZTRSV( 'U', '/', 'N', 0, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL ZTRSV( 'U', 'N', '/', 0, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL ZTRSV( 'U', 'N', 'N', -1, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL ZTRSV( 'U', 'N', 'N', 2, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 8 CALL ZTRSV( 'U', 'N', 'N', 0, A, 1, X, 0 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 180 100 INFOT = 1 CALL ZTBSV( '/', 'N', 'N', 0, 0, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL ZTBSV( 'U', '/', 'N', 0, 0, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL ZTBSV( 'U', 'N', '/', 0, 0, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL ZTBSV( 'U', 'N', 'N', -1, 0, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL ZTBSV( 'U', 'N', 'N', 0, -1, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL ZTBSV( 'U', 'N', 'N', 0, 1, A, 1, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL ZTBSV( 'U', 'N', 'N', 0, 0, A, 1, X, 0 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 180 110 INFOT = 1 CALL ZTPSV( '/', 'N', 'N', 0, A, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL ZTPSV( 'U', '/', 'N', 0, A, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL ZTPSV( 'U', 'N', '/', 0, A, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL ZTPSV( 'U', 'N', 'N', -1, A, X, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL ZTPSV( 'U', 'N', 'N', 0, A, X, 0 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 180 120 INFOT = 1 CALL ZGERC( -1, 0, ALPHA, X, 1, Y, 1, A, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL ZGERC( 0, -1, ALPHA, X, 1, Y, 1, A, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL ZGERC( 0, 0, ALPHA, X, 0, Y, 1, A, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL ZGERC( 0, 0, ALPHA, X, 1, Y, 0, A, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL ZGERC( 2, 0, ALPHA, X, 1, Y, 1, A, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 180 130 INFOT = 1 CALL ZGERU( -1, 0, ALPHA, X, 1, Y, 1, A, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL ZGERU( 0, -1, ALPHA, X, 1, Y, 1, A, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL ZGERU( 0, 0, ALPHA, X, 0, Y, 1, A, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL ZGERU( 0, 0, ALPHA, X, 1, Y, 0, A, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL ZGERU( 2, 0, ALPHA, X, 1, Y, 1, A, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 180 140 INFOT = 1 CALL ZHER( '/', 0, RALPHA, X, 1, A, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL ZHER( 'U', -1, RALPHA, X, 1, A, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL ZHER( 'U', 0, RALPHA, X, 0, A, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL ZHER( 'U', 2, RALPHA, X, 1, A, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 180 150 INFOT = 1 CALL ZHPR( '/', 0, RALPHA, X, 1, A ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL ZHPR( 'U', -1, RALPHA, X, 1, A ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL ZHPR( 'U', 0, RALPHA, X, 0, A ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 180 160 INFOT = 1 CALL ZHER2( '/', 0, ALPHA, X, 1, Y, 1, A, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL ZHER2( 'U', -1, ALPHA, X, 1, Y, 1, A, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL ZHER2( 'U', 0, ALPHA, X, 0, Y, 1, A, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL ZHER2( 'U', 0, ALPHA, X, 1, Y, 0, A, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL ZHER2( 'U', 2, ALPHA, X, 1, Y, 1, A, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 180 170 INFOT = 1 CALL ZHPR2( '/', 0, ALPHA, X, 1, Y, 1, A ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL ZHPR2( 'U', -1, ALPHA, X, 1, Y, 1, A ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL ZHPR2( 'U', 0, ALPHA, X, 0, Y, 1, A ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL ZHPR2( 'U', 0, ALPHA, X, 1, Y, 0, A ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) * 180 IF( OK )THEN WRITE( NOUT, FMT = 9999 )SRNAMT ELSE WRITE( NOUT, FMT = 9998 )SRNAMT END IF RETURN * 9999 FORMAT( ' ', A6, ' PASSED THE TESTS OF ERROR-EXITS' ) 9998 FORMAT( ' ******* ', A6, ' FAILED THE TESTS OF ERROR-EXITS *****', $ '**' ) * * End of ZCHKE. * END SUBROUTINE ZMAKE( TYPE, UPLO, DIAG, M, N, A, NMAX, AA, LDA, KL, $ KU, RESET, TRANSL ) * * Generates values for an M by N matrix A within the bandwidth * defined by KL and KU. * Stores the values in the array AA in the data structure required * by the routine, with unwanted elements set to rogue value. * * TYPE is 'GE', 'GB', 'HE', 'HB', 'HP', 'TR', 'TB' OR 'TP'. * * Auxiliary routine for test program for Level 2 Blas. * * -- Written on 10-August-1987. * Richard Hanson, Sandia National Labs. * Jeremy Du Croz, NAG Central Office. * * .. Parameters .. COMPLEX*16 ZERO, ONE PARAMETER ( ZERO = ( 0.0D0, 0.0D0 ), $ ONE = ( 1.0D0, 0.0D0 ) ) COMPLEX*16 ROGUE PARAMETER ( ROGUE = ( -1.0D10, 1.0D10 ) ) DOUBLE PRECISION RZERO PARAMETER ( RZERO = 0.0D0 ) DOUBLE PRECISION RROGUE PARAMETER ( RROGUE = -1.0D10 ) * .. Scalar Arguments .. COMPLEX*16 TRANSL INTEGER KL, KU, LDA, M, N, NMAX LOGICAL RESET CHARACTER*1 DIAG, UPLO CHARACTER*2 TYPE * .. Array Arguments .. COMPLEX*16 A( NMAX, * ), AA( * ) * .. Local Scalars .. INTEGER I, I1, I2, I3, IBEG, IEND, IOFF, J, JJ, KK LOGICAL GEN, LOWER, SYM, TRI, UNIT, UPPER * .. External Functions .. COMPLEX*16 ZBEG EXTERNAL ZBEG * .. Intrinsic Functions .. INTRINSIC DBLE, DCMPLX, DCONJG, MAX, MIN * .. Executable Statements .. GEN = TYPE( 1: 1 ).EQ.'G' SYM = TYPE( 1: 1 ).EQ.'H' TRI = TYPE( 1: 1 ).EQ.'T' UPPER = ( SYM.OR.TRI ).AND.UPLO.EQ.'U' LOWER = ( SYM.OR.TRI ).AND.UPLO.EQ.'L' UNIT = TRI.AND.DIAG.EQ.'U' * * Generate data in array A. * DO 20 J = 1, N DO 10 I = 1, M IF( GEN.OR.( UPPER.AND.I.LE.J ).OR.( LOWER.AND.I.GE.J ) ) $ THEN IF( ( I.LE.J.AND.J - I.LE.KU ).OR. $ ( I.GE.J.AND.I - J.LE.KL ) )THEN A( I, J ) = ZBEG( RESET ) + TRANSL ELSE A( I, J ) = ZERO END IF IF( I.NE.J )THEN IF( SYM )THEN A( J, I ) = DCONJG( A( I, J ) ) ELSE IF( TRI )THEN A( J, I ) = ZERO END IF END IF END IF 10 CONTINUE IF( SYM ) $ A( J, J ) = DCMPLX( DBLE( A( J, J ) ), RZERO ) IF( TRI ) $ A( J, J ) = A( J, J ) + ONE IF( UNIT ) $ A( J, J ) = ONE 20 CONTINUE * * Store elements in array AS in data structure required by routine. * IF( TYPE.EQ.'GE' )THEN DO 50 J = 1, N DO 30 I = 1, M AA( I + ( J - 1 )*LDA ) = A( I, J ) 30 CONTINUE DO 40 I = M + 1, LDA AA( I + ( J - 1 )*LDA ) = ROGUE 40 CONTINUE 50 CONTINUE ELSE IF( TYPE.EQ.'GB' )THEN DO 90 J = 1, N DO 60 I1 = 1, KU + 1 - J AA( I1 + ( J - 1 )*LDA ) = ROGUE 60 CONTINUE DO 70 I2 = I1, MIN( KL + KU + 1, KU + 1 + M - J ) AA( I2 + ( J - 1 )*LDA ) = A( I2 + J - KU - 1, J ) 70 CONTINUE DO 80 I3 = I2, LDA AA( I3 + ( J - 1 )*LDA ) = ROGUE 80 CONTINUE 90 CONTINUE ELSE IF( TYPE.EQ.'HE'.OR.TYPE.EQ.'TR' )THEN DO 130 J = 1, N IF( UPPER )THEN IBEG = 1 IF( UNIT )THEN IEND = J - 1 ELSE IEND = J END IF ELSE IF( UNIT )THEN IBEG = J + 1 ELSE IBEG = J END IF IEND = N END IF DO 100 I = 1, IBEG - 1 AA( I + ( J - 1 )*LDA ) = ROGUE 100 CONTINUE DO 110 I = IBEG, IEND AA( I + ( J - 1 )*LDA ) = A( I, J ) 110 CONTINUE DO 120 I = IEND + 1, LDA AA( I + ( J - 1 )*LDA ) = ROGUE 120 CONTINUE IF( SYM )THEN JJ = J + ( J - 1 )*LDA AA( JJ ) = DCMPLX( DBLE( AA( JJ ) ), RROGUE ) END IF 130 CONTINUE ELSE IF( TYPE.EQ.'HB'.OR.TYPE.EQ.'TB' )THEN DO 170 J = 1, N IF( UPPER )THEN KK = KL + 1 IBEG = MAX( 1, KL + 2 - J ) IF( UNIT )THEN IEND = KL ELSE IEND = KL + 1 END IF ELSE KK = 1 IF( UNIT )THEN IBEG = 2 ELSE IBEG = 1 END IF IEND = MIN( KL + 1, 1 + M - J ) END IF DO 140 I = 1, IBEG - 1 AA( I + ( J - 1 )*LDA ) = ROGUE 140 CONTINUE DO 150 I = IBEG, IEND AA( I + ( J - 1 )*LDA ) = A( I + J - KK, J ) 150 CONTINUE DO 160 I = IEND + 1, LDA AA( I + ( J - 1 )*LDA ) = ROGUE 160 CONTINUE IF( SYM )THEN JJ = KK + ( J - 1 )*LDA AA( JJ ) = DCMPLX( DBLE( AA( JJ ) ), RROGUE ) END IF 170 CONTINUE ELSE IF( TYPE.EQ.'HP'.OR.TYPE.EQ.'TP' )THEN IOFF = 0 DO 190 J = 1, N IF( UPPER )THEN IBEG = 1 IEND = J ELSE IBEG = J IEND = N END IF DO 180 I = IBEG, IEND IOFF = IOFF + 1 AA( IOFF ) = A( I, J ) IF( I.EQ.J )THEN IF( UNIT ) $ AA( IOFF ) = ROGUE IF( SYM ) $ AA( IOFF ) = DCMPLX( DBLE( AA( IOFF ) ), RROGUE ) END IF 180 CONTINUE 190 CONTINUE END IF RETURN * * End of ZMAKE. * END SUBROUTINE ZMVCH( TRANS, M, N, ALPHA, A, NMAX, X, INCX, BETA, Y, $ INCY, YT, G, YY, EPS, ERR, FATAL, NOUT, MV ) * * Checks the results of the computational tests. * * Auxiliary routine for test program for Level 2 Blas. * * -- Written on 10-August-1987. * Richard Hanson, Sandia National Labs. * Jeremy Du Croz, NAG Central Office. * * .. Parameters .. COMPLEX*16 ZERO PARAMETER ( ZERO = ( 0.0D0, 0.0D0 ) ) DOUBLE PRECISION RZERO, RONE PARAMETER ( RZERO = 0.0D0, RONE = 1.0D0 ) * .. Scalar Arguments .. COMPLEX*16 ALPHA, BETA DOUBLE PRECISION EPS, ERR INTEGER INCX, INCY, M, N, NMAX, NOUT LOGICAL FATAL, MV CHARACTER*1 TRANS * .. Array Arguments .. COMPLEX*16 A( NMAX, * ), X( * ), Y( * ), YT( * ), YY( * ) DOUBLE PRECISION G( * ) * .. Local Scalars .. COMPLEX*16 C DOUBLE PRECISION ERRI INTEGER I, INCXL, INCYL, IY, J, JX, KX, KY, ML, NL LOGICAL CTRAN, TRAN * .. Intrinsic Functions .. INTRINSIC ABS, DBLE, DCONJG, DIMAG, MAX, SQRT * .. Statement Functions .. DOUBLE PRECISION ABS1 * .. Statement Function definitions .. ABS1( C ) = ABS( DBLE( C ) ) + ABS( DIMAG( C ) ) * .. Executable Statements .. TRAN = TRANS.EQ.'T' CTRAN = TRANS.EQ.'C' IF( TRAN.OR.CTRAN )THEN ML = N NL = M ELSE ML = M NL = N END IF IF( INCX.LT.0 )THEN KX = NL INCXL = -1 ELSE KX = 1 INCXL = 1 END IF IF( INCY.LT.0 )THEN KY = ML INCYL = -1 ELSE KY = 1 INCYL = 1 END IF * * Compute expected result in YT using data in A, X and Y. * Compute gauges in G. * IY = KY DO 40 I = 1, ML YT( IY ) = ZERO G( IY ) = RZERO JX = KX IF( TRAN )THEN DO 10 J = 1, NL YT( IY ) = YT( IY ) + A( J, I )*X( JX ) G( IY ) = G( IY ) + ABS1( A( J, I ) )*ABS1( X( JX ) ) JX = JX + INCXL 10 CONTINUE ELSE IF( CTRAN )THEN DO 20 J = 1, NL YT( IY ) = YT( IY ) + DCONJG( A( J, I ) )*X( JX ) G( IY ) = G( IY ) + ABS1( A( J, I ) )*ABS1( X( JX ) ) JX = JX + INCXL 20 CONTINUE ELSE DO 30 J = 1, NL YT( IY ) = YT( IY ) + A( I, J )*X( JX ) G( IY ) = G( IY ) + ABS1( A( I, J ) )*ABS1( X( JX ) ) JX = JX + INCXL 30 CONTINUE END IF YT( IY ) = ALPHA*YT( IY ) + BETA*Y( IY ) G( IY ) = ABS1( ALPHA )*G( IY ) + ABS1( BETA )*ABS1( Y( IY ) ) IY = IY + INCYL 40 CONTINUE * * Compute the error ratio for this result. * ERR = ZERO DO 50 I = 1, ML ERRI = ABS( YT( I ) - YY( 1 + ( I - 1 )*ABS( INCY ) ) )/EPS IF( G( I ).NE.RZERO ) $ ERRI = ERRI/G( I ) ERR = MAX( ERR, ERRI ) IF( ERR*SQRT( EPS ).GE.RONE ) $ GO TO 60 50 CONTINUE * If the loop completes, all results are at least half accurate. GO TO 80 * * Report fatal error. * 60 FATAL = .TRUE. WRITE( NOUT, FMT = 9999 ) DO 70 I = 1, ML IF( MV )THEN WRITE( NOUT, FMT = 9998 )I, YT( I ), $ YY( 1 + ( I - 1 )*ABS( INCY ) ) ELSE WRITE( NOUT, FMT = 9998 )I, $ YY( 1 + ( I - 1 )*ABS( INCY ) ), YT( I ) END IF 70 CONTINUE * 80 CONTINUE RETURN * 9999 FORMAT( ' ******* FATAL ERROR - COMPUTED RESULT IS LESS THAN HAL', $ 'F ACCURATE *******', /' EXPECTED RE', $ 'SULT COMPUTED RESULT' ) 9998 FORMAT( 1X, I7, 2( ' (', G15.6, ',', G15.6, ')' ) ) * * End of ZMVCH. * END LOGICAL FUNCTION LZE( RI, RJ, LR ) * * Tests if two arrays are identical. * * Auxiliary routine for test program for Level 2 Blas. * * -- Written on 10-August-1987. * Richard Hanson, Sandia National Labs. * Jeremy Du Croz, NAG Central Office. * * .. Scalar Arguments .. INTEGER LR * .. Array Arguments .. COMPLEX*16 RI( * ), RJ( * ) * .. Local Scalars .. INTEGER I * .. Executable Statements .. DO 10 I = 1, LR IF( RI( I ).NE.RJ( I ) ) $ GO TO 20 10 CONTINUE LZE = .TRUE. GO TO 30 20 CONTINUE LZE = .FALSE. 30 RETURN * * End of LZE. * END LOGICAL FUNCTION LZERES( TYPE, UPLO, M, N, AA, AS, LDA ) * * Tests if selected elements in two arrays are equal. * * TYPE is 'GE', 'HE' or 'HP'. * * Auxiliary routine for test program for Level 2 Blas. * * -- Written on 10-August-1987. * Richard Hanson, Sandia National Labs. * Jeremy Du Croz, NAG Central Office. * * .. Scalar Arguments .. INTEGER LDA, M, N CHARACTER*1 UPLO CHARACTER*2 TYPE * .. Array Arguments .. COMPLEX*16 AA( LDA, * ), AS( LDA, * ) * .. Local Scalars .. INTEGER I, IBEG, IEND, J LOGICAL UPPER * .. Executable Statements .. UPPER = UPLO.EQ.'U' IF( TYPE.EQ.'GE' )THEN DO 20 J = 1, N DO 10 I = M + 1, LDA IF( AA( I, J ).NE.AS( I, J ) ) $ GO TO 70 10 CONTINUE 20 CONTINUE ELSE IF( TYPE.EQ.'HE' )THEN DO 50 J = 1, N IF( UPPER )THEN IBEG = 1 IEND = J ELSE IBEG = J IEND = N END IF DO 30 I = 1, IBEG - 1 IF( AA( I, J ).NE.AS( I, J ) ) $ GO TO 70 30 CONTINUE DO 40 I = IEND + 1, LDA IF( AA( I, J ).NE.AS( I, J ) ) $ GO TO 70 40 CONTINUE 50 CONTINUE END IF * LZERES = .TRUE. GO TO 80 70 CONTINUE LZERES = .FALSE. 80 RETURN * * End of LZERES. * END COMPLEX*16 FUNCTION ZBEG( RESET ) * * Generates complex numbers as pairs of random numbers uniformly * distributed between -0.5 and 0.5. * * Auxiliary routine for test program for Level 2 Blas. * * -- Written on 10-August-1987. * Richard Hanson, Sandia National Labs. * Jeremy Du Croz, NAG Central Office. * * .. Scalar Arguments .. LOGICAL RESET * .. Local Scalars .. INTEGER I, IC, J, MI, MJ * .. Save statement .. SAVE I, IC, J, MI, MJ * .. Intrinsic Functions .. INTRINSIC DCMPLX * .. Executable Statements .. IF( RESET )THEN * Initialize local variables. MI = 891 MJ = 457 I = 7 J = 7 IC = 0 RESET = .FALSE. END IF * * The sequence of values of I or J is bounded between 1 and 999. * If initial I or J = 1,2,3,6,7 or 9, the period will be 50. * If initial I or J = 4 or 8, the period will be 25. * If initial I or J = 5, the period will be 10. * IC is used to break up the period by skipping 1 value of I or J * in 6. * IC = IC + 1 10 I = I*MI J = J*MJ I = I - 1000*( I/1000 ) J = J - 1000*( J/1000 ) IF( IC.GE.5 )THEN IC = 0 GO TO 10 END IF ZBEG = DCMPLX( ( I - 500 )/1001.0D0, ( J - 500 )/1001.0D0 ) RETURN * * End of ZBEG. * END DOUBLE PRECISION FUNCTION DDIFF( X, Y ) * * Auxiliary routine for test program for Level 2 Blas. * * -- Written on 10-August-1987. * Richard Hanson, Sandia National Labs. * * .. Scalar Arguments .. DOUBLE PRECISION X, Y * .. Executable Statements .. DDIFF = X - Y RETURN * * End of DDIFF. * END SUBROUTINE CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) * * Tests whether XERBLA has detected an error when it should. * * Auxiliary routine for test program for Level 2 Blas. * * -- Written on 10-August-1987. * Richard Hanson, Sandia National Labs. * Jeremy Du Croz, NAG Central Office. * * .. Scalar Arguments .. INTEGER INFOT, NOUT LOGICAL LERR, OK CHARACTER*6 SRNAMT * .. Executable Statements .. IF( .NOT.LERR )THEN WRITE( NOUT, FMT = 9999 )INFOT, SRNAMT OK = .FALSE. END IF LERR = .FALSE. RETURN * 9999 FORMAT( ' ***** ILLEGAL VALUE OF PARAMETER NUMBER ', I2, ' NOT D', $ 'ETECTED BY ', A6, ' *****' ) * * End of CHKXER. * END SUBROUTINE XERBLA( SRNAME, INFO ) * * This is a special version of XERBLA to be used only as part of * the test program for testing error exits from the Level 2 BLAS * routines. * * XERBLA is an error handler for the Level 2 BLAS routines. * * It is called by the Level 2 BLAS routines if an input parameter is * invalid. * * Auxiliary routine for test program for Level 2 Blas. * * -- Written on 10-August-1987. * Richard Hanson, Sandia National Labs. * Jeremy Du Croz, NAG Central Office. * * .. Scalar Arguments .. INTEGER INFO CHARACTER*6 SRNAME * .. Scalars in Common .. INTEGER INFOT, NOUT LOGICAL LERR, OK CHARACTER*6 SRNAMT * .. Common blocks .. COMMON /INFOC/INFOT, NOUT, OK, LERR COMMON /SRNAMC/SRNAMT * .. Executable Statements .. LERR = .TRUE. IF( INFO.NE.INFOT )THEN IF( INFOT.NE.0 )THEN WRITE( NOUT, FMT = 9999 )INFO, INFOT ELSE WRITE( NOUT, FMT = 9997 )INFO END IF OK = .FALSE. END IF IF( SRNAME.NE.SRNAMT )THEN WRITE( NOUT, FMT = 9998 )SRNAME, SRNAMT OK = .FALSE. END IF RETURN * 9999 FORMAT( ' ******* XERBLA WAS CALLED WITH INFO = ', I6, ' INSTEAD', $ ' OF ', I2, ' *******' ) 9998 FORMAT( ' ******* XERBLA WAS CALLED WITH SRNAME = ', A6, ' INSTE', $ 'AD OF ', A6, ' *******' ) 9997 FORMAT( ' ******* XERBLA WAS CALLED WITH INFO = ', I6, $ ' *******' ) * * End of XERBLA * END blis-0.9.0/blastest/src/fortran/zblat3.f000066400000000000000000004016331422157504600201170ustar00rootroot00000000000000*> \brief \b ZBLAT3 * * =========== DOCUMENTATION =========== * * Online html documentation available at * http://www.netlib.org/lapack/explore-html/ * * Definition: * =========== * * PROGRAM ZBLAT3 * * *> \par Purpose: * ============= *> *> \verbatim *> *> Test program for the COMPLEX*16 Level 3 Blas. *> *> The program must be driven by a short data file. The first 14 records *> of the file are read using list-directed input, the last 9 records *> are read using the format ( A6, L2 ). An annotated example of a data *> file can be obtained by deleting the first 3 characters from the *> following 23 lines: *> 'zblat3.out' NAME OF SUMMARY OUTPUT FILE *> 6 UNIT NUMBER OF SUMMARY FILE *> 'ZBLAT3.SNAP' NAME OF SNAPSHOT OUTPUT FILE *> -1 UNIT NUMBER OF SNAPSHOT FILE (NOT USED IF .LT. 0) *> F LOGICAL FLAG, T TO REWIND SNAPSHOT FILE AFTER EACH RECORD. *> F LOGICAL FLAG, T TO STOP ON FAILURES. *> T LOGICAL FLAG, T TO TEST ERROR EXITS. *> 16.0 THRESHOLD VALUE OF TEST RATIO *> 6 NUMBER OF VALUES OF N *> 0 1 2 3 5 9 VALUES OF N *> 3 NUMBER OF VALUES OF ALPHA *> (0.0,0.0) (1.0,0.0) (0.7,-0.9) VALUES OF ALPHA *> 3 NUMBER OF VALUES OF BETA *> (0.0,0.0) (1.0,0.0) (1.3,-1.1) VALUES OF BETA *> ZGEMM T PUT F FOR NO TEST. SAME COLUMNS. *> ZHEMM T PUT F FOR NO TEST. SAME COLUMNS. *> ZSYMM T PUT F FOR NO TEST. SAME COLUMNS. *> ZTRMM T PUT F FOR NO TEST. SAME COLUMNS. *> ZTRSM T PUT F FOR NO TEST. SAME COLUMNS. *> ZHERK T PUT F FOR NO TEST. SAME COLUMNS. *> ZSYRK T PUT F FOR NO TEST. SAME COLUMNS. *> ZHER2K T PUT F FOR NO TEST. SAME COLUMNS. *> ZSYR2K T PUT F FOR NO TEST. SAME COLUMNS. *> *> *> Further Details *> =============== *> *> See: *> *> Dongarra J. J., Du Croz J. J., Duff I. S. and Hammarling S. *> A Set of Level 3 Basic Linear Algebra Subprograms. *> *> Technical Memorandum No.88 (Revision 1), Mathematics and *> Computer Science Division, Argonne National Laboratory, 9700 *> South Cass Avenue, Argonne, Illinois 60439, US. *> *> -- Written on 8-February-1989. *> Jack Dongarra, Argonne National Laboratory. *> Iain Duff, AERE Harwell. *> Jeremy Du Croz, Numerical Algorithms Group Ltd. *> Sven Hammarling, Numerical Algorithms Group Ltd. *> *> 10-9-00: Change STATUS='NEW' to 'UNKNOWN' so that the testers *> can be run multiple times without deleting generated *> output files (susan) *> \endverbatim * * Authors: * ======== * *> \author Univ. of Tennessee *> \author Univ. of California Berkeley *> \author Univ. of Colorado Denver *> \author NAG Ltd. * *> \date April 2012 * *> \ingroup complex16_blas_testing * * ===================================================================== PROGRAM ZBLAT3 * * -- Reference BLAS test routine (version 3.4.1) -- * -- Reference BLAS is a software package provided by Univ. of Tennessee, -- * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- * April 2012 * * ===================================================================== * * .. Parameters .. INTEGER NIN PARAMETER ( NIN = 5 ) INTEGER NSUBS PARAMETER ( NSUBS = 9 ) COMPLEX*16 ZERO, ONE PARAMETER ( ZERO = ( 0.0D0, 0.0D0 ), $ ONE = ( 1.0D0, 0.0D0 ) ) DOUBLE PRECISION RZERO PARAMETER ( RZERO = 0.0D0 ) INTEGER NMAX PARAMETER ( NMAX = 65 ) INTEGER NIDMAX, NALMAX, NBEMAX PARAMETER ( NIDMAX = 9, NALMAX = 7, NBEMAX = 7 ) * .. Local Scalars .. DOUBLE PRECISION EPS, ERR, THRESH INTEGER I, ISNUM, J, N, NALF, NBET, NIDIM, NOUT, NTRA LOGICAL FATAL, LTESTT, REWI, SAME, SFATAL, TRACE, $ TSTERR CHARACTER*1 TRANSA, TRANSB CHARACTER*6 SNAMET CHARACTER*32 SNAPS, SUMMRY * .. Local Arrays .. COMPLEX*16 AA( NMAX*NMAX ), AB( NMAX, 2*NMAX ), $ ALF( NALMAX ), AS( NMAX*NMAX ), $ BB( NMAX*NMAX ), BET( NBEMAX ), $ BS( NMAX*NMAX ), C( NMAX, NMAX ), $ CC( NMAX*NMAX ), CS( NMAX*NMAX ), CT( NMAX ), $ W( 2*NMAX ) DOUBLE PRECISION G( NMAX ) INTEGER IDIM( NIDMAX ) LOGICAL LTEST( NSUBS ) CHARACTER*6 SNAMES( NSUBS ) * .. External Functions .. DOUBLE PRECISION DDIFF LOGICAL LZE EXTERNAL DDIFF, LZE * .. External Subroutines .. EXTERNAL ZCHK1, ZCHK2, ZCHK3, ZCHK4, ZCHK5, ZCHKE, ZMMCH * .. Intrinsic Functions .. INTRINSIC MAX, MIN * .. Scalars in Common .. INTEGER INFOT, NOUTC LOGICAL LERR, OK CHARACTER*6 SRNAMT * .. Common blocks .. COMMON /INFOC/INFOT, NOUTC, OK, LERR COMMON /SRNAMC/SRNAMT * .. Data statements .. DATA SNAMES/'ZGEMM ', 'ZHEMM ', 'ZSYMM ', 'ZTRMM ', $ 'ZTRSM ', 'ZHERK ', 'ZSYRK ', 'ZHER2K', $ 'ZSYR2K'/ * .. Executable Statements .. * * Read name and unit number for summary output file and open file. * READ( NIN, FMT = * )SUMMRY READ( NIN, FMT = * )NOUT OPEN( NOUT, FILE = SUMMRY, STATUS = 'UNKNOWN' ) NOUTC = NOUT * * Read name and unit number for snapshot output file and open file. * READ( NIN, FMT = * )SNAPS READ( NIN, FMT = * )NTRA TRACE = NTRA.GE.0 IF( TRACE )THEN OPEN( NTRA, FILE = SNAPS, STATUS = 'UNKNOWN' ) END IF * Read the flag that directs rewinding of the snapshot file. READ( NIN, FMT = * )REWI REWI = REWI.AND.TRACE * Read the flag that directs stopping on any failure. READ( NIN, FMT = * )SFATAL * Read the flag that indicates whether error exits are to be tested. READ( NIN, FMT = * )TSTERR * Read the threshold value of the test ratio READ( NIN, FMT = * )THRESH * * Read and check the parameter values for the tests. * * Values of N READ( NIN, FMT = * )NIDIM IF( NIDIM.LT.1.OR.NIDIM.GT.NIDMAX )THEN WRITE( NOUT, FMT = 9997 )'N', NIDMAX GO TO 220 END IF READ( NIN, FMT = * )( IDIM( I ), I = 1, NIDIM ) DO 10 I = 1, NIDIM IF( IDIM( I ).LT.0.OR.IDIM( I ).GT.NMAX )THEN WRITE( NOUT, FMT = 9996 )NMAX GO TO 220 END IF 10 CONTINUE * Values of ALPHA READ( NIN, FMT = * )NALF IF( NALF.LT.1.OR.NALF.GT.NALMAX )THEN WRITE( NOUT, FMT = 9997 )'ALPHA', NALMAX GO TO 220 END IF READ( NIN, FMT = * )( ALF( I ), I = 1, NALF ) * Values of BETA READ( NIN, FMT = * )NBET IF( NBET.LT.1.OR.NBET.GT.NBEMAX )THEN WRITE( NOUT, FMT = 9997 )'BETA', NBEMAX GO TO 220 END IF READ( NIN, FMT = * )( BET( I ), I = 1, NBET ) * * Report values of parameters. * WRITE( NOUT, FMT = 9995 ) WRITE( NOUT, FMT = 9994 )( IDIM( I ), I = 1, NIDIM ) WRITE( NOUT, FMT = 9993 )( ALF( I ), I = 1, NALF ) WRITE( NOUT, FMT = 9992 )( BET( I ), I = 1, NBET ) IF( .NOT.TSTERR )THEN WRITE( NOUT, FMT = * ) WRITE( NOUT, FMT = 9984 ) END IF WRITE( NOUT, FMT = * ) WRITE( NOUT, FMT = 9999 )THRESH WRITE( NOUT, FMT = * ) * * Read names of subroutines and flags which indicate * whether they are to be tested. * DO 20 I = 1, NSUBS LTEST( I ) = .FALSE. 20 CONTINUE 30 READ( NIN, FMT = 9988, END = 60 )SNAMET, LTESTT DO 40 I = 1, NSUBS IF( SNAMET.EQ.SNAMES( I ) ) $ GO TO 50 40 CONTINUE WRITE( NOUT, FMT = 9990 )SNAMET STOP 50 LTEST( I ) = LTESTT GO TO 30 * 60 CONTINUE CLOSE ( NIN ) * * Compute EPS (the machine precision). * EPS = EPSILON(RZERO) WRITE( NOUT, FMT = 9998 )EPS * * Check the reliability of ZMMCH using exact data. * N = MIN( 32, NMAX ) DO 100 J = 1, N DO 90 I = 1, N AB( I, J ) = MAX( I - J + 1, 0 ) 90 CONTINUE AB( J, NMAX + 1 ) = J AB( 1, NMAX + J ) = J C( J, 1 ) = ZERO 100 CONTINUE DO 110 J = 1, N CC( J ) = J*( ( J + 1 )*J )/2 - ( ( J + 1 )*J*( J - 1 ) )/3 110 CONTINUE * CC holds the exact result. On exit from ZMMCH CT holds * the result computed by ZMMCH. TRANSA = 'N' TRANSB = 'N' CALL ZMMCH( TRANSA, TRANSB, N, 1, N, ONE, AB, NMAX, $ AB( 1, NMAX + 1 ), NMAX, ZERO, C, NMAX, CT, G, CC, $ NMAX, EPS, ERR, FATAL, NOUT, .TRUE. ) SAME = LZE( CC, CT, N ) IF( .NOT.SAME.OR.ERR.NE.RZERO )THEN WRITE( NOUT, FMT = 9989 )TRANSA, TRANSB, SAME, ERR STOP END IF TRANSB = 'C' CALL ZMMCH( TRANSA, TRANSB, N, 1, N, ONE, AB, NMAX, $ AB( 1, NMAX + 1 ), NMAX, ZERO, C, NMAX, CT, G, CC, $ NMAX, EPS, ERR, FATAL, NOUT, .TRUE. ) SAME = LZE( CC, CT, N ) IF( .NOT.SAME.OR.ERR.NE.RZERO )THEN WRITE( NOUT, FMT = 9989 )TRANSA, TRANSB, SAME, ERR STOP END IF DO 120 J = 1, N AB( J, NMAX + 1 ) = N - J + 1 AB( 1, NMAX + J ) = N - J + 1 120 CONTINUE DO 130 J = 1, N CC( N - J + 1 ) = J*( ( J + 1 )*J )/2 - $ ( ( J + 1 )*J*( J - 1 ) )/3 130 CONTINUE TRANSA = 'C' TRANSB = 'N' CALL ZMMCH( TRANSA, TRANSB, N, 1, N, ONE, AB, NMAX, $ AB( 1, NMAX + 1 ), NMAX, ZERO, C, NMAX, CT, G, CC, $ NMAX, EPS, ERR, FATAL, NOUT, .TRUE. ) SAME = LZE( CC, CT, N ) IF( .NOT.SAME.OR.ERR.NE.RZERO )THEN WRITE( NOUT, FMT = 9989 )TRANSA, TRANSB, SAME, ERR STOP END IF TRANSB = 'C' CALL ZMMCH( TRANSA, TRANSB, N, 1, N, ONE, AB, NMAX, $ AB( 1, NMAX + 1 ), NMAX, ZERO, C, NMAX, CT, G, CC, $ NMAX, EPS, ERR, FATAL, NOUT, .TRUE. ) SAME = LZE( CC, CT, N ) IF( .NOT.SAME.OR.ERR.NE.RZERO )THEN WRITE( NOUT, FMT = 9989 )TRANSA, TRANSB, SAME, ERR STOP END IF * * Test each subroutine in turn. * DO 200 ISNUM = 1, NSUBS WRITE( NOUT, FMT = * ) IF( .NOT.LTEST( ISNUM ) )THEN * Subprogram is not to be tested. WRITE( NOUT, FMT = 9987 )SNAMES( ISNUM ) ELSE SRNAMT = SNAMES( ISNUM ) * Test error exits. IF( TSTERR )THEN CALL ZCHKE( ISNUM, SNAMES( ISNUM ), NOUT ) WRITE( NOUT, FMT = * ) END IF * Test computations. INFOT = 0 OK = .TRUE. FATAL = .FALSE. GO TO ( 140, 150, 150, 160, 160, 170, 170, $ 180, 180 )ISNUM * Test ZGEMM, 01. 140 CALL ZCHK1( SNAMES( ISNUM ), EPS, THRESH, NOUT, NTRA, TRACE, $ REWI, FATAL, NIDIM, IDIM, NALF, ALF, NBET, BET, $ NMAX, AB, AA, AS, AB( 1, NMAX + 1 ), BB, BS, C, $ CC, CS, CT, G ) GO TO 190 * Test ZHEMM, 02, ZSYMM, 03. 150 CALL ZCHK2( SNAMES( ISNUM ), EPS, THRESH, NOUT, NTRA, TRACE, $ REWI, FATAL, NIDIM, IDIM, NALF, ALF, NBET, BET, $ NMAX, AB, AA, AS, AB( 1, NMAX + 1 ), BB, BS, C, $ CC, CS, CT, G ) GO TO 190 * Test ZTRMM, 04, ZTRSM, 05. 160 CALL ZCHK3( SNAMES( ISNUM ), EPS, THRESH, NOUT, NTRA, TRACE, $ REWI, FATAL, NIDIM, IDIM, NALF, ALF, NMAX, AB, $ AA, AS, AB( 1, NMAX + 1 ), BB, BS, CT, G, C ) GO TO 190 * Test ZHERK, 06, ZSYRK, 07. 170 CALL ZCHK4( SNAMES( ISNUM ), EPS, THRESH, NOUT, NTRA, TRACE, $ REWI, FATAL, NIDIM, IDIM, NALF, ALF, NBET, BET, $ NMAX, AB, AA, AS, AB( 1, NMAX + 1 ), BB, BS, C, $ CC, CS, CT, G ) GO TO 190 * Test ZHER2K, 08, ZSYR2K, 09. 180 CALL ZCHK5( SNAMES( ISNUM ), EPS, THRESH, NOUT, NTRA, TRACE, $ REWI, FATAL, NIDIM, IDIM, NALF, ALF, NBET, BET, $ NMAX, AB, AA, AS, BB, BS, C, CC, CS, CT, G, W ) GO TO 190 * 190 IF( FATAL.AND.SFATAL ) $ GO TO 210 END IF 200 CONTINUE WRITE( NOUT, FMT = 9986 ) GO TO 230 * 210 CONTINUE WRITE( NOUT, FMT = 9985 ) GO TO 230 * 220 CONTINUE WRITE( NOUT, FMT = 9991 ) * 230 CONTINUE IF( TRACE ) $ CLOSE ( NTRA ) CLOSE ( NOUT ) STOP * 9999 FORMAT( ' ROUTINES PASS COMPUTATIONAL TESTS IF TEST RATIO IS LES', $ 'S THAN', F8.2 ) 9998 FORMAT( ' RELATIVE MACHINE PRECISION IS TAKEN TO BE', 1P, D9.1 ) 9997 FORMAT( ' NUMBER OF VALUES OF ', A, ' IS LESS THAN 1 OR GREATER ', $ 'THAN ', I2 ) 9996 FORMAT( ' VALUE OF N IS LESS THAN 0 OR GREATER THAN ', I2 ) 9995 FORMAT( ' TESTS OF THE COMPLEX*16 LEVEL 3 BLAS', //' THE F', $ 'OLLOWING PARAMETER VALUES WILL BE USED:' ) 9994 FORMAT( ' FOR N ', 9I6 ) 9993 FORMAT( ' FOR ALPHA ', $ 7( '(', F4.1, ',', F4.1, ') ', : ) ) 9992 FORMAT( ' FOR BETA ', $ 7( '(', F4.1, ',', F4.1, ') ', : ) ) 9991 FORMAT( ' AMEND DATA FILE OR INCREASE ARRAY SIZES IN PROGRAM', $ /' ******* TESTS ABANDONED *******' ) 9990 FORMAT( ' SUBPROGRAM NAME ', A6, ' NOT RECOGNIZED', /' ******* T', $ 'ESTS ABANDONED *******' ) 9989 FORMAT( ' ERROR IN ZMMCH - IN-LINE DOT PRODUCTS ARE BEING EVALU', $ 'ATED WRONGLY.', /' ZMMCH WAS CALLED WITH TRANSA = ', A1, $ ' AND TRANSB = ', A1, /' AND RETURNED SAME = ', L1, ' AND ', $ 'ERR = ', F12.3, '.', /' THIS MAY BE DUE TO FAULTS IN THE ', $ 'ARITHMETIC OR THE COMPILER.', /' ******* TESTS ABANDONED ', $ '*******' ) 9988 FORMAT( A6, L2 ) 9987 FORMAT( 1X, A6, ' WAS NOT TESTED' ) 9986 FORMAT( /' END OF TESTS' ) 9985 FORMAT( /' ******* FATAL ERROR - TESTS ABANDONED *******' ) 9984 FORMAT( ' ERROR-EXITS WILL NOT BE TESTED' ) * * End of ZBLAT3. * END SUBROUTINE ZCHK1( SNAME, EPS, THRESH, NOUT, NTRA, TRACE, REWI, $ FATAL, NIDIM, IDIM, NALF, ALF, NBET, BET, NMAX, $ A, AA, AS, B, BB, BS, C, CC, CS, CT, G ) * * Tests ZGEMM. * * Auxiliary routine for test program for Level 3 Blas. * * -- Written on 8-February-1989. * Jack Dongarra, Argonne National Laboratory. * Iain Duff, AERE Harwell. * Jeremy Du Croz, Numerical Algorithms Group Ltd. * Sven Hammarling, Numerical Algorithms Group Ltd. * * .. Parameters .. COMPLEX*16 ZERO PARAMETER ( ZERO = ( 0.0D0, 0.0D0 ) ) DOUBLE PRECISION RZERO PARAMETER ( RZERO = 0.0D0 ) * .. Scalar Arguments .. DOUBLE PRECISION EPS, THRESH INTEGER NALF, NBET, NIDIM, NMAX, NOUT, NTRA LOGICAL FATAL, REWI, TRACE CHARACTER*6 SNAME * .. Array Arguments .. COMPLEX*16 A( NMAX, NMAX ), AA( NMAX*NMAX ), ALF( NALF ), $ AS( NMAX*NMAX ), B( NMAX, NMAX ), $ BB( NMAX*NMAX ), BET( NBET ), BS( NMAX*NMAX ), $ C( NMAX, NMAX ), CC( NMAX*NMAX ), $ CS( NMAX*NMAX ), CT( NMAX ) DOUBLE PRECISION G( NMAX ) INTEGER IDIM( NIDIM ) * .. Local Scalars .. COMPLEX*16 ALPHA, ALS, BETA, BLS DOUBLE PRECISION ERR, ERRMAX INTEGER I, IA, IB, ICA, ICB, IK, IM, IN, K, KS, LAA, $ LBB, LCC, LDA, LDAS, LDB, LDBS, LDC, LDCS, M, $ MA, MB, MS, N, NA, NARGS, NB, NC, NS LOGICAL NULL, RESET, SAME, TRANA, TRANB CHARACTER*1 TRANAS, TRANBS, TRANSA, TRANSB CHARACTER*3 ICH * .. Local Arrays .. LOGICAL ISAME( 13 ) * .. External Functions .. LOGICAL LZE, LZERES EXTERNAL LZE, LZERES * .. External Subroutines .. EXTERNAL ZGEMM, ZMAKE, ZMMCH * .. Intrinsic Functions .. INTRINSIC MAX * .. Scalars in Common .. INTEGER INFOT, NOUTC LOGICAL LERR, OK * .. Common blocks .. COMMON /INFOC/INFOT, NOUTC, OK, LERR * .. Data statements .. DATA ICH/'NTC'/ * .. Executable Statements .. * NARGS = 13 NC = 0 RESET = .TRUE. ERRMAX = RZERO * DO 110 IM = 1, NIDIM M = IDIM( IM ) * DO 100 IN = 1, NIDIM N = IDIM( IN ) * Set LDC to 1 more than minimum value if room. LDC = M IF( LDC.LT.NMAX ) $ LDC = LDC + 1 * Skip tests if not enough room. IF( LDC.GT.NMAX ) $ GO TO 100 LCC = LDC*N NULL = N.LE.0.OR.M.LE.0 * DO 90 IK = 1, NIDIM K = IDIM( IK ) * DO 80 ICA = 1, 3 TRANSA = ICH( ICA: ICA ) TRANA = TRANSA.EQ.'T'.OR.TRANSA.EQ.'C' * IF( TRANA )THEN MA = K NA = M ELSE MA = M NA = K END IF * Set LDA to 1 more than minimum value if room. LDA = MA IF( LDA.LT.NMAX ) $ LDA = LDA + 1 * Skip tests if not enough room. IF( LDA.GT.NMAX ) $ GO TO 80 LAA = LDA*NA * * Generate the matrix A. * CALL ZMAKE( 'GE', ' ', ' ', MA, NA, A, NMAX, AA, LDA, $ RESET, ZERO ) * DO 70 ICB = 1, 3 TRANSB = ICH( ICB: ICB ) TRANB = TRANSB.EQ.'T'.OR.TRANSB.EQ.'C' * IF( TRANB )THEN MB = N NB = K ELSE MB = K NB = N END IF * Set LDB to 1 more than minimum value if room. LDB = MB IF( LDB.LT.NMAX ) $ LDB = LDB + 1 * Skip tests if not enough room. IF( LDB.GT.NMAX ) $ GO TO 70 LBB = LDB*NB * * Generate the matrix B. * CALL ZMAKE( 'GE', ' ', ' ', MB, NB, B, NMAX, BB, $ LDB, RESET, ZERO ) * DO 60 IA = 1, NALF ALPHA = ALF( IA ) * DO 50 IB = 1, NBET BETA = BET( IB ) * * Generate the matrix C. * CALL ZMAKE( 'GE', ' ', ' ', M, N, C, NMAX, $ CC, LDC, RESET, ZERO ) * NC = NC + 1 * * Save every datum before calling the * subroutine. * TRANAS = TRANSA TRANBS = TRANSB MS = M NS = N KS = K ALS = ALPHA DO 10 I = 1, LAA AS( I ) = AA( I ) 10 CONTINUE LDAS = LDA DO 20 I = 1, LBB BS( I ) = BB( I ) 20 CONTINUE LDBS = LDB BLS = BETA DO 30 I = 1, LCC CS( I ) = CC( I ) 30 CONTINUE LDCS = LDC * * Call the subroutine. * IF( TRACE ) $ WRITE( NTRA, FMT = 9995 )NC, SNAME, $ TRANSA, TRANSB, M, N, K, ALPHA, LDA, LDB, $ BETA, LDC IF( REWI ) $ REWIND NTRA CALL ZGEMM( TRANSA, TRANSB, M, N, K, ALPHA, $ AA, LDA, BB, LDB, BETA, CC, LDC ) * * Check if error-exit was taken incorrectly. * IF( .NOT.OK )THEN WRITE( NOUT, FMT = 9994 ) FATAL = .TRUE. GO TO 120 END IF * * See what data changed inside subroutines. * ISAME( 1 ) = TRANSA.EQ.TRANAS ISAME( 2 ) = TRANSB.EQ.TRANBS ISAME( 3 ) = MS.EQ.M ISAME( 4 ) = NS.EQ.N ISAME( 5 ) = KS.EQ.K ISAME( 6 ) = ALS.EQ.ALPHA ISAME( 7 ) = LZE( AS, AA, LAA ) ISAME( 8 ) = LDAS.EQ.LDA ISAME( 9 ) = LZE( BS, BB, LBB ) ISAME( 10 ) = LDBS.EQ.LDB ISAME( 11 ) = BLS.EQ.BETA IF( NULL )THEN ISAME( 12 ) = LZE( CS, CC, LCC ) ELSE ISAME( 12 ) = LZERES( 'GE', ' ', M, N, CS, $ CC, LDC ) END IF ISAME( 13 ) = LDCS.EQ.LDC * * If data was incorrectly changed, report * and return. * SAME = .TRUE. DO 40 I = 1, NARGS SAME = SAME.AND.ISAME( I ) IF( .NOT.ISAME( I ) ) $ WRITE( NOUT, FMT = 9998 )I 40 CONTINUE IF( .NOT.SAME )THEN FATAL = .TRUE. GO TO 120 END IF * IF( .NOT.NULL )THEN * * Check the result. * CALL ZMMCH( TRANSA, TRANSB, M, N, K, $ ALPHA, A, NMAX, B, NMAX, BETA, $ C, NMAX, CT, G, CC, LDC, EPS, $ ERR, FATAL, NOUT, .TRUE. ) ERRMAX = MAX( ERRMAX, ERR ) * If got really bad answer, report and * return. IF( FATAL ) $ GO TO 120 END IF * 50 CONTINUE * 60 CONTINUE * 70 CONTINUE * 80 CONTINUE * 90 CONTINUE * 100 CONTINUE * 110 CONTINUE * * Report result. * IF( ERRMAX.LT.THRESH )THEN WRITE( NOUT, FMT = 9999 )SNAME, NC ELSE WRITE( NOUT, FMT = 9997 )SNAME, NC, ERRMAX END IF GO TO 130 * 120 CONTINUE WRITE( NOUT, FMT = 9996 )SNAME WRITE( NOUT, FMT = 9995 )NC, SNAME, TRANSA, TRANSB, M, N, K, $ ALPHA, LDA, LDB, BETA, LDC * 130 CONTINUE RETURN * 9999 FORMAT( ' ', A6, ' PASSED THE COMPUTATIONAL TESTS (', I6, ' CALL', $ 'S)' ) 9998 FORMAT( ' ******* FATAL ERROR - PARAMETER NUMBER ', I2, ' WAS CH', $ 'ANGED INCORRECTLY *******' ) 9997 FORMAT( ' ', A6, ' COMPLETED THE COMPUTATIONAL TESTS (', I6, ' C', $ 'ALLS)', /' ******* BUT WITH MAXIMUM TEST RATIO', F8.2, $ ' - SUSPECT *******' ) 9996 FORMAT( ' ******* ', A6, ' FAILED ON CALL NUMBER:' ) 9995 FORMAT( 1X, I6, ': ', A6, '(''', A1, ''',''', A1, ''',', $ 3( I3, ',' ), '(', F4.1, ',', F4.1, '), A,', I3, ', B,', I3, $ ',(', F4.1, ',', F4.1, '), C,', I3, ').' ) 9994 FORMAT( ' ******* FATAL ERROR - ERROR-EXIT TAKEN ON VALID CALL *', $ '******' ) * * End of ZCHK1. * END SUBROUTINE ZCHK2( SNAME, EPS, THRESH, NOUT, NTRA, TRACE, REWI, $ FATAL, NIDIM, IDIM, NALF, ALF, NBET, BET, NMAX, $ A, AA, AS, B, BB, BS, C, CC, CS, CT, G ) * * Tests ZHEMM and ZSYMM. * * Auxiliary routine for test program for Level 3 Blas. * * -- Written on 8-February-1989. * Jack Dongarra, Argonne National Laboratory. * Iain Duff, AERE Harwell. * Jeremy Du Croz, Numerical Algorithms Group Ltd. * Sven Hammarling, Numerical Algorithms Group Ltd. * * .. Parameters .. COMPLEX*16 ZERO PARAMETER ( ZERO = ( 0.0D0, 0.0D0 ) ) DOUBLE PRECISION RZERO PARAMETER ( RZERO = 0.0D0 ) * .. Scalar Arguments .. DOUBLE PRECISION EPS, THRESH INTEGER NALF, NBET, NIDIM, NMAX, NOUT, NTRA LOGICAL FATAL, REWI, TRACE CHARACTER*6 SNAME * .. Array Arguments .. COMPLEX*16 A( NMAX, NMAX ), AA( NMAX*NMAX ), ALF( NALF ), $ AS( NMAX*NMAX ), B( NMAX, NMAX ), $ BB( NMAX*NMAX ), BET( NBET ), BS( NMAX*NMAX ), $ C( NMAX, NMAX ), CC( NMAX*NMAX ), $ CS( NMAX*NMAX ), CT( NMAX ) DOUBLE PRECISION G( NMAX ) INTEGER IDIM( NIDIM ) * .. Local Scalars .. COMPLEX*16 ALPHA, ALS, BETA, BLS DOUBLE PRECISION ERR, ERRMAX INTEGER I, IA, IB, ICS, ICU, IM, IN, LAA, LBB, LCC, $ LDA, LDAS, LDB, LDBS, LDC, LDCS, M, MS, N, NA, $ NARGS, NC, NS LOGICAL CONJ, LEFT, NULL, RESET, SAME CHARACTER*1 SIDE, SIDES, UPLO, UPLOS CHARACTER*2 ICHS, ICHU * .. Local Arrays .. LOGICAL ISAME( 13 ) * .. External Functions .. LOGICAL LZE, LZERES EXTERNAL LZE, LZERES * .. External Subroutines .. EXTERNAL ZHEMM, ZMAKE, ZMMCH, ZSYMM * .. Intrinsic Functions .. INTRINSIC MAX * .. Scalars in Common .. INTEGER INFOT, NOUTC LOGICAL LERR, OK * .. Common blocks .. COMMON /INFOC/INFOT, NOUTC, OK, LERR * .. Data statements .. DATA ICHS/'LR'/, ICHU/'UL'/ * .. Executable Statements .. CONJ = SNAME( 2: 3 ).EQ.'HE' * NARGS = 12 NC = 0 RESET = .TRUE. ERRMAX = RZERO * DO 100 IM = 1, NIDIM M = IDIM( IM ) * DO 90 IN = 1, NIDIM N = IDIM( IN ) * Set LDC to 1 more than minimum value if room. LDC = M IF( LDC.LT.NMAX ) $ LDC = LDC + 1 * Skip tests if not enough room. IF( LDC.GT.NMAX ) $ GO TO 90 LCC = LDC*N NULL = N.LE.0.OR.M.LE.0 * Set LDB to 1 more than minimum value if room. LDB = M IF( LDB.LT.NMAX ) $ LDB = LDB + 1 * Skip tests if not enough room. IF( LDB.GT.NMAX ) $ GO TO 90 LBB = LDB*N * * Generate the matrix B. * CALL ZMAKE( 'GE', ' ', ' ', M, N, B, NMAX, BB, LDB, RESET, $ ZERO ) * DO 80 ICS = 1, 2 SIDE = ICHS( ICS: ICS ) LEFT = SIDE.EQ.'L' * IF( LEFT )THEN NA = M ELSE NA = N END IF * Set LDA to 1 more than minimum value if room. LDA = NA IF( LDA.LT.NMAX ) $ LDA = LDA + 1 * Skip tests if not enough room. IF( LDA.GT.NMAX ) $ GO TO 80 LAA = LDA*NA * DO 70 ICU = 1, 2 UPLO = ICHU( ICU: ICU ) * * Generate the hermitian or symmetric matrix A. * CALL ZMAKE( SNAME( 2: 3 ), UPLO, ' ', NA, NA, A, NMAX, $ AA, LDA, RESET, ZERO ) * DO 60 IA = 1, NALF ALPHA = ALF( IA ) * DO 50 IB = 1, NBET BETA = BET( IB ) * * Generate the matrix C. * CALL ZMAKE( 'GE', ' ', ' ', M, N, C, NMAX, CC, $ LDC, RESET, ZERO ) * NC = NC + 1 * * Save every datum before calling the * subroutine. * SIDES = SIDE UPLOS = UPLO MS = M NS = N ALS = ALPHA DO 10 I = 1, LAA AS( I ) = AA( I ) 10 CONTINUE LDAS = LDA DO 20 I = 1, LBB BS( I ) = BB( I ) 20 CONTINUE LDBS = LDB BLS = BETA DO 30 I = 1, LCC CS( I ) = CC( I ) 30 CONTINUE LDCS = LDC * * Call the subroutine. * IF( TRACE ) $ WRITE( NTRA, FMT = 9995 )NC, SNAME, SIDE, $ UPLO, M, N, ALPHA, LDA, LDB, BETA, LDC IF( REWI ) $ REWIND NTRA IF( CONJ )THEN CALL ZHEMM( SIDE, UPLO, M, N, ALPHA, AA, LDA, $ BB, LDB, BETA, CC, LDC ) ELSE CALL ZSYMM( SIDE, UPLO, M, N, ALPHA, AA, LDA, $ BB, LDB, BETA, CC, LDC ) END IF * * Check if error-exit was taken incorrectly. * IF( .NOT.OK )THEN WRITE( NOUT, FMT = 9994 ) FATAL = .TRUE. GO TO 110 END IF * * See what data changed inside subroutines. * ISAME( 1 ) = SIDES.EQ.SIDE ISAME( 2 ) = UPLOS.EQ.UPLO ISAME( 3 ) = MS.EQ.M ISAME( 4 ) = NS.EQ.N ISAME( 5 ) = ALS.EQ.ALPHA ISAME( 6 ) = LZE( AS, AA, LAA ) ISAME( 7 ) = LDAS.EQ.LDA ISAME( 8 ) = LZE( BS, BB, LBB ) ISAME( 9 ) = LDBS.EQ.LDB ISAME( 10 ) = BLS.EQ.BETA IF( NULL )THEN ISAME( 11 ) = LZE( CS, CC, LCC ) ELSE ISAME( 11 ) = LZERES( 'GE', ' ', M, N, CS, $ CC, LDC ) END IF ISAME( 12 ) = LDCS.EQ.LDC * * If data was incorrectly changed, report and * return. * SAME = .TRUE. DO 40 I = 1, NARGS SAME = SAME.AND.ISAME( I ) IF( .NOT.ISAME( I ) ) $ WRITE( NOUT, FMT = 9998 )I 40 CONTINUE IF( .NOT.SAME )THEN FATAL = .TRUE. GO TO 110 END IF * IF( .NOT.NULL )THEN * * Check the result. * IF( LEFT )THEN CALL ZMMCH( 'N', 'N', M, N, M, ALPHA, A, $ NMAX, B, NMAX, BETA, C, NMAX, $ CT, G, CC, LDC, EPS, ERR, $ FATAL, NOUT, .TRUE. ) ELSE CALL ZMMCH( 'N', 'N', M, N, N, ALPHA, B, $ NMAX, A, NMAX, BETA, C, NMAX, $ CT, G, CC, LDC, EPS, ERR, $ FATAL, NOUT, .TRUE. ) END IF ERRMAX = MAX( ERRMAX, ERR ) * If got really bad answer, report and * return. IF( FATAL ) $ GO TO 110 END IF * 50 CONTINUE * 60 CONTINUE * 70 CONTINUE * 80 CONTINUE * 90 CONTINUE * 100 CONTINUE * * Report result. * IF( ERRMAX.LT.THRESH )THEN WRITE( NOUT, FMT = 9999 )SNAME, NC ELSE WRITE( NOUT, FMT = 9997 )SNAME, NC, ERRMAX END IF GO TO 120 * 110 CONTINUE WRITE( NOUT, FMT = 9996 )SNAME WRITE( NOUT, FMT = 9995 )NC, SNAME, SIDE, UPLO, M, N, ALPHA, LDA, $ LDB, BETA, LDC * 120 CONTINUE RETURN * 9999 FORMAT( ' ', A6, ' PASSED THE COMPUTATIONAL TESTS (', I6, ' CALL', $ 'S)' ) 9998 FORMAT( ' ******* FATAL ERROR - PARAMETER NUMBER ', I2, ' WAS CH', $ 'ANGED INCORRECTLY *******' ) 9997 FORMAT( ' ', A6, ' COMPLETED THE COMPUTATIONAL TESTS (', I6, ' C', $ 'ALLS)', /' ******* BUT WITH MAXIMUM TEST RATIO', F8.2, $ ' - SUSPECT *******' ) 9996 FORMAT( ' ******* ', A6, ' FAILED ON CALL NUMBER:' ) 9995 FORMAT( 1X, I6, ': ', A6, '(', 2( '''', A1, ''',' ), 2( I3, ',' ), $ '(', F4.1, ',', F4.1, '), A,', I3, ', B,', I3, ',(', F4.1, $ ',', F4.1, '), C,', I3, ') .' ) 9994 FORMAT( ' ******* FATAL ERROR - ERROR-EXIT TAKEN ON VALID CALL *', $ '******' ) * * End of ZCHK2. * END SUBROUTINE ZCHK3( SNAME, EPS, THRESH, NOUT, NTRA, TRACE, REWI, $ FATAL, NIDIM, IDIM, NALF, ALF, NMAX, A, AA, AS, $ B, BB, BS, CT, G, C ) * * Tests ZTRMM and ZTRSM. * * Auxiliary routine for test program for Level 3 Blas. * * -- Written on 8-February-1989. * Jack Dongarra, Argonne National Laboratory. * Iain Duff, AERE Harwell. * Jeremy Du Croz, Numerical Algorithms Group Ltd. * Sven Hammarling, Numerical Algorithms Group Ltd. * * .. Parameters .. COMPLEX*16 ZERO, ONE PARAMETER ( ZERO = ( 0.0D0, 0.0D0 ), $ ONE = ( 1.0D0, 0.0D0 ) ) DOUBLE PRECISION RZERO PARAMETER ( RZERO = 0.0D0 ) * .. Scalar Arguments .. DOUBLE PRECISION EPS, THRESH INTEGER NALF, NIDIM, NMAX, NOUT, NTRA LOGICAL FATAL, REWI, TRACE CHARACTER*6 SNAME * .. Array Arguments .. COMPLEX*16 A( NMAX, NMAX ), AA( NMAX*NMAX ), ALF( NALF ), $ AS( NMAX*NMAX ), B( NMAX, NMAX ), $ BB( NMAX*NMAX ), BS( NMAX*NMAX ), $ C( NMAX, NMAX ), CT( NMAX ) DOUBLE PRECISION G( NMAX ) INTEGER IDIM( NIDIM ) * .. Local Scalars .. COMPLEX*16 ALPHA, ALS DOUBLE PRECISION ERR, ERRMAX INTEGER I, IA, ICD, ICS, ICT, ICU, IM, IN, J, LAA, LBB, $ LDA, LDAS, LDB, LDBS, M, MS, N, NA, NARGS, NC, $ NS LOGICAL LEFT, NULL, RESET, SAME CHARACTER*1 DIAG, DIAGS, SIDE, SIDES, TRANAS, TRANSA, UPLO, $ UPLOS CHARACTER*2 ICHD, ICHS, ICHU CHARACTER*3 ICHT * .. Local Arrays .. LOGICAL ISAME( 13 ) * .. External Functions .. LOGICAL LZE, LZERES EXTERNAL LZE, LZERES * .. External Subroutines .. EXTERNAL ZMAKE, ZMMCH, ZTRMM, ZTRSM * .. Intrinsic Functions .. INTRINSIC MAX * .. Scalars in Common .. INTEGER INFOT, NOUTC LOGICAL LERR, OK * .. Common blocks .. COMMON /INFOC/INFOT, NOUTC, OK, LERR * .. Data statements .. DATA ICHU/'UL'/, ICHT/'NTC'/, ICHD/'UN'/, ICHS/'LR'/ * .. Executable Statements .. * NARGS = 11 NC = 0 RESET = .TRUE. ERRMAX = RZERO * Set up zero matrix for ZMMCH. DO 20 J = 1, NMAX DO 10 I = 1, NMAX C( I, J ) = ZERO 10 CONTINUE 20 CONTINUE * DO 140 IM = 1, NIDIM M = IDIM( IM ) * DO 130 IN = 1, NIDIM N = IDIM( IN ) * Set LDB to 1 more than minimum value if room. LDB = M IF( LDB.LT.NMAX ) $ LDB = LDB + 1 * Skip tests if not enough room. IF( LDB.GT.NMAX ) $ GO TO 130 LBB = LDB*N NULL = M.LE.0.OR.N.LE.0 * DO 120 ICS = 1, 2 SIDE = ICHS( ICS: ICS ) LEFT = SIDE.EQ.'L' IF( LEFT )THEN NA = M ELSE NA = N END IF * Set LDA to 1 more than minimum value if room. LDA = NA IF( LDA.LT.NMAX ) $ LDA = LDA + 1 * Skip tests if not enough room. IF( LDA.GT.NMAX ) $ GO TO 130 LAA = LDA*NA * DO 110 ICU = 1, 2 UPLO = ICHU( ICU: ICU ) * DO 100 ICT = 1, 3 TRANSA = ICHT( ICT: ICT ) * DO 90 ICD = 1, 2 DIAG = ICHD( ICD: ICD ) * DO 80 IA = 1, NALF ALPHA = ALF( IA ) * * Generate the matrix A. * CALL ZMAKE( 'TR', UPLO, DIAG, NA, NA, A, $ NMAX, AA, LDA, RESET, ZERO ) * * Generate the matrix B. * CALL ZMAKE( 'GE', ' ', ' ', M, N, B, NMAX, $ BB, LDB, RESET, ZERO ) * NC = NC + 1 * * Save every datum before calling the * subroutine. * SIDES = SIDE UPLOS = UPLO TRANAS = TRANSA DIAGS = DIAG MS = M NS = N ALS = ALPHA DO 30 I = 1, LAA AS( I ) = AA( I ) 30 CONTINUE LDAS = LDA DO 40 I = 1, LBB BS( I ) = BB( I ) 40 CONTINUE LDBS = LDB * * Call the subroutine. * IF( SNAME( 4: 5 ).EQ.'MM' )THEN IF( TRACE ) $ WRITE( NTRA, FMT = 9995 )NC, SNAME, $ SIDE, UPLO, TRANSA, DIAG, M, N, ALPHA, $ LDA, LDB IF( REWI ) $ REWIND NTRA CALL ZTRMM( SIDE, UPLO, TRANSA, DIAG, M, $ N, ALPHA, AA, LDA, BB, LDB ) ELSE IF( SNAME( 4: 5 ).EQ.'SM' )THEN IF( TRACE ) $ WRITE( NTRA, FMT = 9995 )NC, SNAME, $ SIDE, UPLO, TRANSA, DIAG, M, N, ALPHA, $ LDA, LDB IF( REWI ) $ REWIND NTRA CALL ZTRSM( SIDE, UPLO, TRANSA, DIAG, M, $ N, ALPHA, AA, LDA, BB, LDB ) END IF * * Check if error-exit was taken incorrectly. * IF( .NOT.OK )THEN WRITE( NOUT, FMT = 9994 ) FATAL = .TRUE. GO TO 150 END IF * * See what data changed inside subroutines. * ISAME( 1 ) = SIDES.EQ.SIDE ISAME( 2 ) = UPLOS.EQ.UPLO ISAME( 3 ) = TRANAS.EQ.TRANSA ISAME( 4 ) = DIAGS.EQ.DIAG ISAME( 5 ) = MS.EQ.M ISAME( 6 ) = NS.EQ.N ISAME( 7 ) = ALS.EQ.ALPHA ISAME( 8 ) = LZE( AS, AA, LAA ) ISAME( 9 ) = LDAS.EQ.LDA IF( NULL )THEN ISAME( 10 ) = LZE( BS, BB, LBB ) ELSE ISAME( 10 ) = LZERES( 'GE', ' ', M, N, BS, $ BB, LDB ) END IF ISAME( 11 ) = LDBS.EQ.LDB * * If data was incorrectly changed, report and * return. * SAME = .TRUE. DO 50 I = 1, NARGS SAME = SAME.AND.ISAME( I ) IF( .NOT.ISAME( I ) ) $ WRITE( NOUT, FMT = 9998 )I 50 CONTINUE IF( .NOT.SAME )THEN FATAL = .TRUE. GO TO 150 END IF * IF( .NOT.NULL )THEN IF( SNAME( 4: 5 ).EQ.'MM' )THEN * * Check the result. * IF( LEFT )THEN CALL ZMMCH( TRANSA, 'N', M, N, M, $ ALPHA, A, NMAX, B, NMAX, $ ZERO, C, NMAX, CT, G, $ BB, LDB, EPS, ERR, $ FATAL, NOUT, .TRUE. ) ELSE CALL ZMMCH( 'N', TRANSA, M, N, N, $ ALPHA, B, NMAX, A, NMAX, $ ZERO, C, NMAX, CT, G, $ BB, LDB, EPS, ERR, $ FATAL, NOUT, .TRUE. ) END IF ELSE IF( SNAME( 4: 5 ).EQ.'SM' )THEN * * Compute approximation to original * matrix. * DO 70 J = 1, N DO 60 I = 1, M C( I, J ) = BB( I + ( J - 1 )* $ LDB ) BB( I + ( J - 1 )*LDB ) = ALPHA* $ B( I, J ) 60 CONTINUE 70 CONTINUE * IF( LEFT )THEN CALL ZMMCH( TRANSA, 'N', M, N, M, $ ONE, A, NMAX, C, NMAX, $ ZERO, B, NMAX, CT, G, $ BB, LDB, EPS, ERR, $ FATAL, NOUT, .FALSE. ) ELSE CALL ZMMCH( 'N', TRANSA, M, N, N, $ ONE, C, NMAX, A, NMAX, $ ZERO, B, NMAX, CT, G, $ BB, LDB, EPS, ERR, $ FATAL, NOUT, .FALSE. ) END IF END IF ERRMAX = MAX( ERRMAX, ERR ) * If got really bad answer, report and * return. IF( FATAL ) $ GO TO 150 END IF * 80 CONTINUE * 90 CONTINUE * 100 CONTINUE * 110 CONTINUE * 120 CONTINUE * 130 CONTINUE * 140 CONTINUE * * Report result. * IF( ERRMAX.LT.THRESH )THEN WRITE( NOUT, FMT = 9999 )SNAME, NC ELSE WRITE( NOUT, FMT = 9997 )SNAME, NC, ERRMAX END IF GO TO 160 * 150 CONTINUE WRITE( NOUT, FMT = 9996 )SNAME WRITE( NOUT, FMT = 9995 )NC, SNAME, SIDE, UPLO, TRANSA, DIAG, M, $ N, ALPHA, LDA, LDB * 160 CONTINUE RETURN * 9999 FORMAT( ' ', A6, ' PASSED THE COMPUTATIONAL TESTS (', I6, ' CALL', $ 'S)' ) 9998 FORMAT( ' ******* FATAL ERROR - PARAMETER NUMBER ', I2, ' WAS CH', $ 'ANGED INCORRECTLY *******' ) 9997 FORMAT( ' ', A6, ' COMPLETED THE COMPUTATIONAL TESTS (', I6, ' C', $ 'ALLS)', /' ******* BUT WITH MAXIMUM TEST RATIO', F8.2, $ ' - SUSPECT *******' ) 9996 FORMAT( ' ******* ', A6, ' FAILED ON CALL NUMBER:' ) 9995 FORMAT( 1X, I6, ': ', A6, '(', 4( '''', A1, ''',' ), 2( I3, ',' ), $ '(', F4.1, ',', F4.1, '), A,', I3, ', B,', I3, ') ', $ ' .' ) 9994 FORMAT( ' ******* FATAL ERROR - ERROR-EXIT TAKEN ON VALID CALL *', $ '******' ) * * End of ZCHK3. * END SUBROUTINE ZCHK4( SNAME, EPS, THRESH, NOUT, NTRA, TRACE, REWI, $ FATAL, NIDIM, IDIM, NALF, ALF, NBET, BET, NMAX, $ A, AA, AS, B, BB, BS, C, CC, CS, CT, G ) * * Tests ZHERK and ZSYRK. * * Auxiliary routine for test program for Level 3 Blas. * * -- Written on 8-February-1989. * Jack Dongarra, Argonne National Laboratory. * Iain Duff, AERE Harwell. * Jeremy Du Croz, Numerical Algorithms Group Ltd. * Sven Hammarling, Numerical Algorithms Group Ltd. * * .. Parameters .. COMPLEX*16 ZERO PARAMETER ( ZERO = ( 0.0D0, 0.0D0 ) ) DOUBLE PRECISION RONE, RZERO PARAMETER ( RONE = 1.0D0, RZERO = 0.0D0 ) * .. Scalar Arguments .. DOUBLE PRECISION EPS, THRESH INTEGER NALF, NBET, NIDIM, NMAX, NOUT, NTRA LOGICAL FATAL, REWI, TRACE CHARACTER*6 SNAME * .. Array Arguments .. COMPLEX*16 A( NMAX, NMAX ), AA( NMAX*NMAX ), ALF( NALF ), $ AS( NMAX*NMAX ), B( NMAX, NMAX ), $ BB( NMAX*NMAX ), BET( NBET ), BS( NMAX*NMAX ), $ C( NMAX, NMAX ), CC( NMAX*NMAX ), $ CS( NMAX*NMAX ), CT( NMAX ) DOUBLE PRECISION G( NMAX ) INTEGER IDIM( NIDIM ) * .. Local Scalars .. COMPLEX*16 ALPHA, ALS, BETA, BETS DOUBLE PRECISION ERR, ERRMAX, RALPHA, RALS, RBETA, RBETS INTEGER I, IA, IB, ICT, ICU, IK, IN, J, JC, JJ, K, KS, $ LAA, LCC, LDA, LDAS, LDC, LDCS, LJ, MA, N, NA, $ NARGS, NC, NS LOGICAL CONJ, NULL, RESET, SAME, TRAN, UPPER CHARACTER*1 TRANS, TRANSS, TRANST, UPLO, UPLOS CHARACTER*2 ICHT, ICHU * .. Local Arrays .. LOGICAL ISAME( 13 ) * .. External Functions .. LOGICAL LZE, LZERES EXTERNAL LZE, LZERES * .. External Subroutines .. EXTERNAL ZHERK, ZMAKE, ZMMCH, ZSYRK * .. Intrinsic Functions .. INTRINSIC DCMPLX, MAX, DBLE * .. Scalars in Common .. INTEGER INFOT, NOUTC LOGICAL LERR, OK * .. Common blocks .. COMMON /INFOC/INFOT, NOUTC, OK, LERR * .. Data statements .. DATA ICHT/'NC'/, ICHU/'UL'/ * .. Executable Statements .. CONJ = SNAME( 2: 3 ).EQ.'HE' * NARGS = 10 NC = 0 RESET = .TRUE. ERRMAX = RZERO * DO 100 IN = 1, NIDIM N = IDIM( IN ) * Set LDC to 1 more than minimum value if room. LDC = N IF( LDC.LT.NMAX ) $ LDC = LDC + 1 * Skip tests if not enough room. IF( LDC.GT.NMAX ) $ GO TO 100 LCC = LDC*N * DO 90 IK = 1, NIDIM K = IDIM( IK ) * DO 80 ICT = 1, 2 TRANS = ICHT( ICT: ICT ) TRAN = TRANS.EQ.'C' IF( TRAN.AND..NOT.CONJ ) $ TRANS = 'T' IF( TRAN )THEN MA = K NA = N ELSE MA = N NA = K END IF * Set LDA to 1 more than minimum value if room. LDA = MA IF( LDA.LT.NMAX ) $ LDA = LDA + 1 * Skip tests if not enough room. IF( LDA.GT.NMAX ) $ GO TO 80 LAA = LDA*NA * * Generate the matrix A. * CALL ZMAKE( 'GE', ' ', ' ', MA, NA, A, NMAX, AA, LDA, $ RESET, ZERO ) * DO 70 ICU = 1, 2 UPLO = ICHU( ICU: ICU ) UPPER = UPLO.EQ.'U' * DO 60 IA = 1, NALF ALPHA = ALF( IA ) IF( CONJ )THEN RALPHA = DBLE( ALPHA ) ALPHA = DCMPLX( RALPHA, RZERO ) END IF * DO 50 IB = 1, NBET BETA = BET( IB ) IF( CONJ )THEN RBETA = DBLE( BETA ) BETA = DCMPLX( RBETA, RZERO ) END IF NULL = N.LE.0 IF( CONJ ) $ NULL = NULL.OR.( ( K.LE.0.OR.RALPHA.EQ. $ RZERO ).AND.RBETA.EQ.RONE ) * * Generate the matrix C. * CALL ZMAKE( SNAME( 2: 3 ), UPLO, ' ', N, N, C, $ NMAX, CC, LDC, RESET, ZERO ) * NC = NC + 1 * * Save every datum before calling the subroutine. * UPLOS = UPLO TRANSS = TRANS NS = N KS = K IF( CONJ )THEN RALS = RALPHA ELSE ALS = ALPHA END IF DO 10 I = 1, LAA AS( I ) = AA( I ) 10 CONTINUE LDAS = LDA IF( CONJ )THEN RBETS = RBETA ELSE BETS = BETA END IF DO 20 I = 1, LCC CS( I ) = CC( I ) 20 CONTINUE LDCS = LDC * * Call the subroutine. * IF( CONJ )THEN IF( TRACE ) $ WRITE( NTRA, FMT = 9994 )NC, SNAME, UPLO, $ TRANS, N, K, RALPHA, LDA, RBETA, LDC IF( REWI ) $ REWIND NTRA CALL ZHERK( UPLO, TRANS, N, K, RALPHA, AA, $ LDA, RBETA, CC, LDC ) ELSE IF( TRACE ) $ WRITE( NTRA, FMT = 9993 )NC, SNAME, UPLO, $ TRANS, N, K, ALPHA, LDA, BETA, LDC IF( REWI ) $ REWIND NTRA CALL ZSYRK( UPLO, TRANS, N, K, ALPHA, AA, $ LDA, BETA, CC, LDC ) END IF * * Check if error-exit was taken incorrectly. * IF( .NOT.OK )THEN WRITE( NOUT, FMT = 9992 ) FATAL = .TRUE. GO TO 120 END IF * * See what data changed inside subroutines. * ISAME( 1 ) = UPLOS.EQ.UPLO ISAME( 2 ) = TRANSS.EQ.TRANS ISAME( 3 ) = NS.EQ.N ISAME( 4 ) = KS.EQ.K IF( CONJ )THEN ISAME( 5 ) = RALS.EQ.RALPHA ELSE ISAME( 5 ) = ALS.EQ.ALPHA END IF ISAME( 6 ) = LZE( AS, AA, LAA ) ISAME( 7 ) = LDAS.EQ.LDA IF( CONJ )THEN ISAME( 8 ) = RBETS.EQ.RBETA ELSE ISAME( 8 ) = BETS.EQ.BETA END IF IF( NULL )THEN ISAME( 9 ) = LZE( CS, CC, LCC ) ELSE ISAME( 9 ) = LZERES( SNAME( 2: 3 ), UPLO, N, $ N, CS, CC, LDC ) END IF ISAME( 10 ) = LDCS.EQ.LDC * * If data was incorrectly changed, report and * return. * SAME = .TRUE. DO 30 I = 1, NARGS SAME = SAME.AND.ISAME( I ) IF( .NOT.ISAME( I ) ) $ WRITE( NOUT, FMT = 9998 )I 30 CONTINUE IF( .NOT.SAME )THEN FATAL = .TRUE. GO TO 120 END IF * IF( .NOT.NULL )THEN * * Check the result column by column. * IF( CONJ )THEN TRANST = 'C' ELSE TRANST = 'T' END IF JC = 1 DO 40 J = 1, N IF( UPPER )THEN JJ = 1 LJ = J ELSE JJ = J LJ = N - J + 1 END IF IF( TRAN )THEN CALL ZMMCH( TRANST, 'N', LJ, 1, K, $ ALPHA, A( 1, JJ ), NMAX, $ A( 1, J ), NMAX, BETA, $ C( JJ, J ), NMAX, CT, G, $ CC( JC ), LDC, EPS, ERR, $ FATAL, NOUT, .TRUE. ) ELSE CALL ZMMCH( 'N', TRANST, LJ, 1, K, $ ALPHA, A( JJ, 1 ), NMAX, $ A( J, 1 ), NMAX, BETA, $ C( JJ, J ), NMAX, CT, G, $ CC( JC ), LDC, EPS, ERR, $ FATAL, NOUT, .TRUE. ) END IF IF( UPPER )THEN JC = JC + LDC ELSE JC = JC + LDC + 1 END IF ERRMAX = MAX( ERRMAX, ERR ) * If got really bad answer, report and * return. IF( FATAL ) $ GO TO 110 40 CONTINUE END IF * 50 CONTINUE * 60 CONTINUE * 70 CONTINUE * 80 CONTINUE * 90 CONTINUE * 100 CONTINUE * * Report result. * IF( ERRMAX.LT.THRESH )THEN WRITE( NOUT, FMT = 9999 )SNAME, NC ELSE WRITE( NOUT, FMT = 9997 )SNAME, NC, ERRMAX END IF GO TO 130 * 110 CONTINUE IF( N.GT.1 ) $ WRITE( NOUT, FMT = 9995 )J * 120 CONTINUE WRITE( NOUT, FMT = 9996 )SNAME IF( CONJ )THEN WRITE( NOUT, FMT = 9994 )NC, SNAME, UPLO, TRANS, N, K, RALPHA, $ LDA, RBETA, LDC ELSE WRITE( NOUT, FMT = 9993 )NC, SNAME, UPLO, TRANS, N, K, ALPHA, $ LDA, BETA, LDC END IF * 130 CONTINUE RETURN * 9999 FORMAT( ' ', A6, ' PASSED THE COMPUTATIONAL TESTS (', I6, ' CALL', $ 'S)' ) 9998 FORMAT( ' ******* FATAL ERROR - PARAMETER NUMBER ', I2, ' WAS CH', $ 'ANGED INCORRECTLY *******' ) 9997 FORMAT( ' ', A6, ' COMPLETED THE COMPUTATIONAL TESTS (', I6, ' C', $ 'ALLS)', /' ******* BUT WITH MAXIMUM TEST RATIO', F8.2, $ ' - SUSPECT *******' ) 9996 FORMAT( ' ******* ', A6, ' FAILED ON CALL NUMBER:' ) 9995 FORMAT( ' THESE ARE THE RESULTS FOR COLUMN ', I3 ) 9994 FORMAT( 1X, I6, ': ', A6, '(', 2( '''', A1, ''',' ), 2( I3, ',' ), $ F4.1, ', A,', I3, ',', F4.1, ', C,', I3, ') ', $ ' .' ) 9993 FORMAT( 1X, I6, ': ', A6, '(', 2( '''', A1, ''',' ), 2( I3, ',' ), $ '(', F4.1, ',', F4.1, ') , A,', I3, ',(', F4.1, ',', F4.1, $ '), C,', I3, ') .' ) 9992 FORMAT( ' ******* FATAL ERROR - ERROR-EXIT TAKEN ON VALID CALL *', $ '******' ) * * End of ZCHK4. * END SUBROUTINE ZCHK5( SNAME, EPS, THRESH, NOUT, NTRA, TRACE, REWI, $ FATAL, NIDIM, IDIM, NALF, ALF, NBET, BET, NMAX, $ AB, AA, AS, BB, BS, C, CC, CS, CT, G, W ) * * Tests ZHER2K and ZSYR2K. * * Auxiliary routine for test program for Level 3 Blas. * * -- Written on 8-February-1989. * Jack Dongarra, Argonne National Laboratory. * Iain Duff, AERE Harwell. * Jeremy Du Croz, Numerical Algorithms Group Ltd. * Sven Hammarling, Numerical Algorithms Group Ltd. * * .. Parameters .. COMPLEX*16 ZERO, ONE PARAMETER ( ZERO = ( 0.0D0, 0.0D0 ), $ ONE = ( 1.0D0, 0.0D0 ) ) DOUBLE PRECISION RONE, RZERO PARAMETER ( RONE = 1.0D0, RZERO = 0.0D0 ) * .. Scalar Arguments .. DOUBLE PRECISION EPS, THRESH INTEGER NALF, NBET, NIDIM, NMAX, NOUT, NTRA LOGICAL FATAL, REWI, TRACE CHARACTER*6 SNAME * .. Array Arguments .. COMPLEX*16 AA( NMAX*NMAX ), AB( 2*NMAX*NMAX ), $ ALF( NALF ), AS( NMAX*NMAX ), BB( NMAX*NMAX ), $ BET( NBET ), BS( NMAX*NMAX ), C( NMAX, NMAX ), $ CC( NMAX*NMAX ), CS( NMAX*NMAX ), CT( NMAX ), $ W( 2*NMAX ) DOUBLE PRECISION G( NMAX ) INTEGER IDIM( NIDIM ) * .. Local Scalars .. COMPLEX*16 ALPHA, ALS, BETA, BETS DOUBLE PRECISION ERR, ERRMAX, RBETA, RBETS INTEGER I, IA, IB, ICT, ICU, IK, IN, J, JC, JJ, JJAB, $ K, KS, LAA, LBB, LCC, LDA, LDAS, LDB, LDBS, $ LDC, LDCS, LJ, MA, N, NA, NARGS, NC, NS LOGICAL CONJ, NULL, RESET, SAME, TRAN, UPPER CHARACTER*1 TRANS, TRANSS, TRANST, UPLO, UPLOS CHARACTER*2 ICHT, ICHU * .. Local Arrays .. LOGICAL ISAME( 13 ) * .. External Functions .. LOGICAL LZE, LZERES EXTERNAL LZE, LZERES * .. External Subroutines .. EXTERNAL ZHER2K, ZMAKE, ZMMCH, ZSYR2K * .. Intrinsic Functions .. INTRINSIC DCMPLX, DCONJG, MAX, DBLE * .. Scalars in Common .. INTEGER INFOT, NOUTC LOGICAL LERR, OK * .. Common blocks .. COMMON /INFOC/INFOT, NOUTC, OK, LERR * .. Data statements .. DATA ICHT/'NC'/, ICHU/'UL'/ * .. Executable Statements .. CONJ = SNAME( 2: 3 ).EQ.'HE' * NARGS = 12 NC = 0 RESET = .TRUE. ERRMAX = RZERO * DO 130 IN = 1, NIDIM N = IDIM( IN ) * Set LDC to 1 more than minimum value if room. LDC = N IF( LDC.LT.NMAX ) $ LDC = LDC + 1 * Skip tests if not enough room. IF( LDC.GT.NMAX ) $ GO TO 130 LCC = LDC*N * DO 120 IK = 1, NIDIM K = IDIM( IK ) * DO 110 ICT = 1, 2 TRANS = ICHT( ICT: ICT ) TRAN = TRANS.EQ.'C' IF( TRAN.AND..NOT.CONJ ) $ TRANS = 'T' IF( TRAN )THEN MA = K NA = N ELSE MA = N NA = K END IF * Set LDA to 1 more than minimum value if room. LDA = MA IF( LDA.LT.NMAX ) $ LDA = LDA + 1 * Skip tests if not enough room. IF( LDA.GT.NMAX ) $ GO TO 110 LAA = LDA*NA * * Generate the matrix A. * IF( TRAN )THEN CALL ZMAKE( 'GE', ' ', ' ', MA, NA, AB, 2*NMAX, AA, $ LDA, RESET, ZERO ) ELSE CALL ZMAKE( 'GE', ' ', ' ', MA, NA, AB, NMAX, AA, LDA, $ RESET, ZERO ) END IF * * Generate the matrix B. * LDB = LDA LBB = LAA IF( TRAN )THEN CALL ZMAKE( 'GE', ' ', ' ', MA, NA, AB( K + 1 ), $ 2*NMAX, BB, LDB, RESET, ZERO ) ELSE CALL ZMAKE( 'GE', ' ', ' ', MA, NA, AB( K*NMAX + 1 ), $ NMAX, BB, LDB, RESET, ZERO ) END IF * DO 100 ICU = 1, 2 UPLO = ICHU( ICU: ICU ) UPPER = UPLO.EQ.'U' * DO 90 IA = 1, NALF ALPHA = ALF( IA ) * DO 80 IB = 1, NBET BETA = BET( IB ) IF( CONJ )THEN RBETA = DBLE( BETA ) BETA = DCMPLX( RBETA, RZERO ) END IF NULL = N.LE.0 IF( CONJ ) $ NULL = NULL.OR.( ( K.LE.0.OR.ALPHA.EQ. $ ZERO ).AND.RBETA.EQ.RONE ) * * Generate the matrix C. * CALL ZMAKE( SNAME( 2: 3 ), UPLO, ' ', N, N, C, $ NMAX, CC, LDC, RESET, ZERO ) * NC = NC + 1 * * Save every datum before calling the subroutine. * UPLOS = UPLO TRANSS = TRANS NS = N KS = K ALS = ALPHA DO 10 I = 1, LAA AS( I ) = AA( I ) 10 CONTINUE LDAS = LDA DO 20 I = 1, LBB BS( I ) = BB( I ) 20 CONTINUE LDBS = LDB IF( CONJ )THEN RBETS = RBETA ELSE BETS = BETA END IF DO 30 I = 1, LCC CS( I ) = CC( I ) 30 CONTINUE LDCS = LDC * * Call the subroutine. * IF( CONJ )THEN IF( TRACE ) $ WRITE( NTRA, FMT = 9994 )NC, SNAME, UPLO, $ TRANS, N, K, ALPHA, LDA, LDB, RBETA, LDC IF( REWI ) $ REWIND NTRA CALL ZHER2K( UPLO, TRANS, N, K, ALPHA, AA, $ LDA, BB, LDB, RBETA, CC, LDC ) ELSE IF( TRACE ) $ WRITE( NTRA, FMT = 9993 )NC, SNAME, UPLO, $ TRANS, N, K, ALPHA, LDA, LDB, BETA, LDC IF( REWI ) $ REWIND NTRA CALL ZSYR2K( UPLO, TRANS, N, K, ALPHA, AA, $ LDA, BB, LDB, BETA, CC, LDC ) END IF * * Check if error-exit was taken incorrectly. * IF( .NOT.OK )THEN WRITE( NOUT, FMT = 9992 ) FATAL = .TRUE. GO TO 150 END IF * * See what data changed inside subroutines. * ISAME( 1 ) = UPLOS.EQ.UPLO ISAME( 2 ) = TRANSS.EQ.TRANS ISAME( 3 ) = NS.EQ.N ISAME( 4 ) = KS.EQ.K ISAME( 5 ) = ALS.EQ.ALPHA ISAME( 6 ) = LZE( AS, AA, LAA ) ISAME( 7 ) = LDAS.EQ.LDA ISAME( 8 ) = LZE( BS, BB, LBB ) ISAME( 9 ) = LDBS.EQ.LDB IF( CONJ )THEN ISAME( 10 ) = RBETS.EQ.RBETA ELSE ISAME( 10 ) = BETS.EQ.BETA END IF IF( NULL )THEN ISAME( 11 ) = LZE( CS, CC, LCC ) ELSE ISAME( 11 ) = LZERES( 'HE', UPLO, N, N, CS, $ CC, LDC ) END IF ISAME( 12 ) = LDCS.EQ.LDC * * If data was incorrectly changed, report and * return. * SAME = .TRUE. DO 40 I = 1, NARGS SAME = SAME.AND.ISAME( I ) IF( .NOT.ISAME( I ) ) $ WRITE( NOUT, FMT = 9998 )I 40 CONTINUE IF( .NOT.SAME )THEN FATAL = .TRUE. GO TO 150 END IF * IF( .NOT.NULL )THEN * * Check the result column by column. * IF( CONJ )THEN TRANST = 'C' ELSE TRANST = 'T' END IF JJAB = 1 JC = 1 DO 70 J = 1, N IF( UPPER )THEN JJ = 1 LJ = J ELSE JJ = J LJ = N - J + 1 END IF IF( TRAN )THEN DO 50 I = 1, K W( I ) = ALPHA*AB( ( J - 1 )*2* $ NMAX + K + I ) IF( CONJ )THEN W( K + I ) = DCONJG( ALPHA )* $ AB( ( J - 1 )*2* $ NMAX + I ) ELSE W( K + I ) = ALPHA* $ AB( ( J - 1 )*2* $ NMAX + I ) END IF 50 CONTINUE CALL ZMMCH( TRANST, 'N', LJ, 1, 2*K, $ ONE, AB( JJAB ), 2*NMAX, W, $ 2*NMAX, BETA, C( JJ, J ), $ NMAX, CT, G, CC( JC ), LDC, $ EPS, ERR, FATAL, NOUT, $ .TRUE. ) ELSE DO 60 I = 1, K IF( CONJ )THEN W( I ) = ALPHA*DCONJG( AB( ( K + $ I - 1 )*NMAX + J ) ) W( K + I ) = DCONJG( ALPHA* $ AB( ( I - 1 )*NMAX + $ J ) ) ELSE W( I ) = ALPHA*AB( ( K + I - 1 )* $ NMAX + J ) W( K + I ) = ALPHA* $ AB( ( I - 1 )*NMAX + $ J ) END IF 60 CONTINUE CALL ZMMCH( 'N', 'N', LJ, 1, 2*K, ONE, $ AB( JJ ), NMAX, W, 2*NMAX, $ BETA, C( JJ, J ), NMAX, CT, $ G, CC( JC ), LDC, EPS, ERR, $ FATAL, NOUT, .TRUE. ) END IF IF( UPPER )THEN JC = JC + LDC ELSE JC = JC + LDC + 1 IF( TRAN ) $ JJAB = JJAB + 2*NMAX END IF ERRMAX = MAX( ERRMAX, ERR ) * If got really bad answer, report and * return. IF( FATAL ) $ GO TO 140 70 CONTINUE END IF * 80 CONTINUE * 90 CONTINUE * 100 CONTINUE * 110 CONTINUE * 120 CONTINUE * 130 CONTINUE * * Report result. * IF( ERRMAX.LT.THRESH )THEN WRITE( NOUT, FMT = 9999 )SNAME, NC ELSE WRITE( NOUT, FMT = 9997 )SNAME, NC, ERRMAX END IF GO TO 160 * 140 CONTINUE IF( N.GT.1 ) $ WRITE( NOUT, FMT = 9995 )J * 150 CONTINUE WRITE( NOUT, FMT = 9996 )SNAME IF( CONJ )THEN WRITE( NOUT, FMT = 9994 )NC, SNAME, UPLO, TRANS, N, K, ALPHA, $ LDA, LDB, RBETA, LDC ELSE WRITE( NOUT, FMT = 9993 )NC, SNAME, UPLO, TRANS, N, K, ALPHA, $ LDA, LDB, BETA, LDC END IF * 160 CONTINUE RETURN * 9999 FORMAT( ' ', A6, ' PASSED THE COMPUTATIONAL TESTS (', I6, ' CALL', $ 'S)' ) 9998 FORMAT( ' ******* FATAL ERROR - PARAMETER NUMBER ', I2, ' WAS CH', $ 'ANGED INCORRECTLY *******' ) 9997 FORMAT( ' ', A6, ' COMPLETED THE COMPUTATIONAL TESTS (', I6, ' C', $ 'ALLS)', /' ******* BUT WITH MAXIMUM TEST RATIO', F8.2, $ ' - SUSPECT *******' ) 9996 FORMAT( ' ******* ', A6, ' FAILED ON CALL NUMBER:' ) 9995 FORMAT( ' THESE ARE THE RESULTS FOR COLUMN ', I3 ) 9994 FORMAT( 1X, I6, ': ', A6, '(', 2( '''', A1, ''',' ), 2( I3, ',' ), $ '(', F4.1, ',', F4.1, '), A,', I3, ', B,', I3, ',', F4.1, $ ', C,', I3, ') .' ) 9993 FORMAT( 1X, I6, ': ', A6, '(', 2( '''', A1, ''',' ), 2( I3, ',' ), $ '(', F4.1, ',', F4.1, '), A,', I3, ', B,', I3, ',(', F4.1, $ ',', F4.1, '), C,', I3, ') .' ) 9992 FORMAT( ' ******* FATAL ERROR - ERROR-EXIT TAKEN ON VALID CALL *', $ '******' ) * * End of ZCHK5. * END SUBROUTINE ZCHKE( ISNUM, SRNAMT, NOUT ) * * Tests the error exits from the Level 3 Blas. * Requires a special version of the error-handling routine XERBLA. * A, B and C should not need to be defined. * * Auxiliary routine for test program for Level 3 Blas. * * -- Written on 8-February-1989. * Jack Dongarra, Argonne National Laboratory. * Iain Duff, AERE Harwell. * Jeremy Du Croz, Numerical Algorithms Group Ltd. * Sven Hammarling, Numerical Algorithms Group Ltd. * * 3-19-92: Initialize ALPHA, BETA, RALPHA, and RBETA (eca) * 3-19-92: Fix argument 12 in calls to ZSYMM and ZHEMM * with INFOT = 9 (eca) * 10-9-00: Declared INTRINSIC DCMPLX (susan) * * .. Scalar Arguments .. INTEGER ISNUM, NOUT CHARACTER*6 SRNAMT * .. Scalars in Common .. INTEGER INFOT, NOUTC LOGICAL LERR, OK * .. Parameters .. REAL ONE, TWO PARAMETER ( ONE = 1.0D0, TWO = 2.0D0 ) * .. Local Scalars .. COMPLEX*16 ALPHA, BETA DOUBLE PRECISION RALPHA, RBETA * .. Local Arrays .. COMPLEX*16 A( 2, 1 ), B( 2, 1 ), C( 2, 1 ) * .. External Subroutines .. EXTERNAL ZGEMM, ZHEMM, ZHER2K, ZHERK, CHKXER, ZSYMM, $ ZSYR2K, ZSYRK, ZTRMM, ZTRSM * .. Intrinsic Functions .. INTRINSIC DCMPLX * .. Common blocks .. COMMON /INFOC/INFOT, NOUTC, OK, LERR * .. Executable Statements .. * OK is set to .FALSE. by the special version of XERBLA or by CHKXER * if anything is wrong. OK = .TRUE. * LERR is set to .TRUE. by the special version of XERBLA each time * it is called, and is then tested and re-set by CHKXER. LERR = .FALSE. * * Initialize ALPHA, BETA, RALPHA, and RBETA. * ALPHA = DCMPLX( ONE, -ONE ) BETA = DCMPLX( TWO, -TWO ) RALPHA = ONE RBETA = TWO * GO TO ( 10, 20, 30, 40, 50, 60, 70, 80, $ 90 )ISNUM 10 INFOT = 1 CALL ZGEMM( '/', 'N', 0, 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 1 CALL ZGEMM( '/', 'C', 0, 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 1 CALL ZGEMM( '/', 'T', 0, 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL ZGEMM( 'N', '/', 0, 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL ZGEMM( 'C', '/', 0, 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL ZGEMM( 'T', '/', 0, 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL ZGEMM( 'N', 'N', -1, 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL ZGEMM( 'N', 'C', -1, 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL ZGEMM( 'N', 'T', -1, 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL ZGEMM( 'C', 'N', -1, 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL ZGEMM( 'C', 'C', -1, 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL ZGEMM( 'C', 'T', -1, 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL ZGEMM( 'T', 'N', -1, 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL ZGEMM( 'T', 'C', -1, 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL ZGEMM( 'T', 'T', -1, 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL ZGEMM( 'N', 'N', 0, -1, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL ZGEMM( 'N', 'C', 0, -1, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL ZGEMM( 'N', 'T', 0, -1, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL ZGEMM( 'C', 'N', 0, -1, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL ZGEMM( 'C', 'C', 0, -1, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL ZGEMM( 'C', 'T', 0, -1, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL ZGEMM( 'T', 'N', 0, -1, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL ZGEMM( 'T', 'C', 0, -1, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL ZGEMM( 'T', 'T', 0, -1, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL ZGEMM( 'N', 'N', 0, 0, -1, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL ZGEMM( 'N', 'C', 0, 0, -1, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL ZGEMM( 'N', 'T', 0, 0, -1, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL ZGEMM( 'C', 'N', 0, 0, -1, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL ZGEMM( 'C', 'C', 0, 0, -1, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL ZGEMM( 'C', 'T', 0, 0, -1, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL ZGEMM( 'T', 'N', 0, 0, -1, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL ZGEMM( 'T', 'C', 0, 0, -1, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL ZGEMM( 'T', 'T', 0, 0, -1, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 8 CALL ZGEMM( 'N', 'N', 2, 0, 0, ALPHA, A, 1, B, 1, BETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 8 CALL ZGEMM( 'N', 'C', 2, 0, 0, ALPHA, A, 1, B, 1, BETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 8 CALL ZGEMM( 'N', 'T', 2, 0, 0, ALPHA, A, 1, B, 1, BETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 8 CALL ZGEMM( 'C', 'N', 0, 0, 2, ALPHA, A, 1, B, 2, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 8 CALL ZGEMM( 'C', 'C', 0, 0, 2, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 8 CALL ZGEMM( 'C', 'T', 0, 0, 2, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 8 CALL ZGEMM( 'T', 'N', 0, 0, 2, ALPHA, A, 1, B, 2, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 8 CALL ZGEMM( 'T', 'C', 0, 0, 2, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 8 CALL ZGEMM( 'T', 'T', 0, 0, 2, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 10 CALL ZGEMM( 'N', 'N', 0, 0, 2, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 10 CALL ZGEMM( 'C', 'N', 0, 0, 2, ALPHA, A, 2, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 10 CALL ZGEMM( 'T', 'N', 0, 0, 2, ALPHA, A, 2, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 10 CALL ZGEMM( 'N', 'C', 0, 2, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 10 CALL ZGEMM( 'C', 'C', 0, 2, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 10 CALL ZGEMM( 'T', 'C', 0, 2, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 10 CALL ZGEMM( 'N', 'T', 0, 2, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 10 CALL ZGEMM( 'C', 'T', 0, 2, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 10 CALL ZGEMM( 'T', 'T', 0, 2, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 13 CALL ZGEMM( 'N', 'N', 2, 0, 0, ALPHA, A, 2, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 13 CALL ZGEMM( 'N', 'C', 2, 0, 0, ALPHA, A, 2, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 13 CALL ZGEMM( 'N', 'T', 2, 0, 0, ALPHA, A, 2, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 13 CALL ZGEMM( 'C', 'N', 2, 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 13 CALL ZGEMM( 'C', 'C', 2, 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 13 CALL ZGEMM( 'C', 'T', 2, 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 13 CALL ZGEMM( 'T', 'N', 2, 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 13 CALL ZGEMM( 'T', 'C', 2, 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 13 CALL ZGEMM( 'T', 'T', 2, 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 100 20 INFOT = 1 CALL ZHEMM( '/', 'U', 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL ZHEMM( 'L', '/', 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL ZHEMM( 'L', 'U', -1, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL ZHEMM( 'R', 'U', -1, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL ZHEMM( 'L', 'L', -1, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL ZHEMM( 'R', 'L', -1, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL ZHEMM( 'L', 'U', 0, -1, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL ZHEMM( 'R', 'U', 0, -1, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL ZHEMM( 'L', 'L', 0, -1, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL ZHEMM( 'R', 'L', 0, -1, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL ZHEMM( 'L', 'U', 2, 0, ALPHA, A, 1, B, 2, BETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL ZHEMM( 'R', 'U', 0, 2, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL ZHEMM( 'L', 'L', 2, 0, ALPHA, A, 1, B, 2, BETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL ZHEMM( 'R', 'L', 0, 2, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL ZHEMM( 'L', 'U', 2, 0, ALPHA, A, 2, B, 1, BETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL ZHEMM( 'R', 'U', 2, 0, ALPHA, A, 1, B, 1, BETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL ZHEMM( 'L', 'L', 2, 0, ALPHA, A, 2, B, 1, BETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL ZHEMM( 'R', 'L', 2, 0, ALPHA, A, 1, B, 1, BETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 12 CALL ZHEMM( 'L', 'U', 2, 0, ALPHA, A, 2, B, 2, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 12 CALL ZHEMM( 'R', 'U', 2, 0, ALPHA, A, 1, B, 2, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 12 CALL ZHEMM( 'L', 'L', 2, 0, ALPHA, A, 2, B, 2, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 12 CALL ZHEMM( 'R', 'L', 2, 0, ALPHA, A, 1, B, 2, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 100 30 INFOT = 1 CALL ZSYMM( '/', 'U', 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL ZSYMM( 'L', '/', 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL ZSYMM( 'L', 'U', -1, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL ZSYMM( 'R', 'U', -1, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL ZSYMM( 'L', 'L', -1, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL ZSYMM( 'R', 'L', -1, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL ZSYMM( 'L', 'U', 0, -1, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL ZSYMM( 'R', 'U', 0, -1, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL ZSYMM( 'L', 'L', 0, -1, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL ZSYMM( 'R', 'L', 0, -1, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL ZSYMM( 'L', 'U', 2, 0, ALPHA, A, 1, B, 2, BETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL ZSYMM( 'R', 'U', 0, 2, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL ZSYMM( 'L', 'L', 2, 0, ALPHA, A, 1, B, 2, BETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL ZSYMM( 'R', 'L', 0, 2, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL ZSYMM( 'L', 'U', 2, 0, ALPHA, A, 2, B, 1, BETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL ZSYMM( 'R', 'U', 2, 0, ALPHA, A, 1, B, 1, BETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL ZSYMM( 'L', 'L', 2, 0, ALPHA, A, 2, B, 1, BETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL ZSYMM( 'R', 'L', 2, 0, ALPHA, A, 1, B, 1, BETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 12 CALL ZSYMM( 'L', 'U', 2, 0, ALPHA, A, 2, B, 2, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 12 CALL ZSYMM( 'R', 'U', 2, 0, ALPHA, A, 1, B, 2, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 12 CALL ZSYMM( 'L', 'L', 2, 0, ALPHA, A, 2, B, 2, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 12 CALL ZSYMM( 'R', 'L', 2, 0, ALPHA, A, 1, B, 2, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 100 40 INFOT = 1 CALL ZTRMM( '/', 'U', 'N', 'N', 0, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL ZTRMM( 'L', '/', 'N', 'N', 0, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL ZTRMM( 'L', 'U', '/', 'N', 0, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL ZTRMM( 'L', 'U', 'N', '/', 0, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL ZTRMM( 'L', 'U', 'N', 'N', -1, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL ZTRMM( 'L', 'U', 'C', 'N', -1, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL ZTRMM( 'L', 'U', 'T', 'N', -1, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL ZTRMM( 'R', 'U', 'N', 'N', -1, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL ZTRMM( 'R', 'U', 'C', 'N', -1, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL ZTRMM( 'R', 'U', 'T', 'N', -1, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL ZTRMM( 'L', 'L', 'N', 'N', -1, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL ZTRMM( 'L', 'L', 'C', 'N', -1, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL ZTRMM( 'L', 'L', 'T', 'N', -1, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL ZTRMM( 'R', 'L', 'N', 'N', -1, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL ZTRMM( 'R', 'L', 'C', 'N', -1, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL ZTRMM( 'R', 'L', 'T', 'N', -1, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL ZTRMM( 'L', 'U', 'N', 'N', 0, -1, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL ZTRMM( 'L', 'U', 'C', 'N', 0, -1, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL ZTRMM( 'L', 'U', 'T', 'N', 0, -1, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL ZTRMM( 'R', 'U', 'N', 'N', 0, -1, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL ZTRMM( 'R', 'U', 'C', 'N', 0, -1, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL ZTRMM( 'R', 'U', 'T', 'N', 0, -1, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL ZTRMM( 'L', 'L', 'N', 'N', 0, -1, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL ZTRMM( 'L', 'L', 'C', 'N', 0, -1, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL ZTRMM( 'L', 'L', 'T', 'N', 0, -1, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL ZTRMM( 'R', 'L', 'N', 'N', 0, -1, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL ZTRMM( 'R', 'L', 'C', 'N', 0, -1, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL ZTRMM( 'R', 'L', 'T', 'N', 0, -1, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL ZTRMM( 'L', 'U', 'N', 'N', 2, 0, ALPHA, A, 1, B, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL ZTRMM( 'L', 'U', 'C', 'N', 2, 0, ALPHA, A, 1, B, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL ZTRMM( 'L', 'U', 'T', 'N', 2, 0, ALPHA, A, 1, B, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL ZTRMM( 'R', 'U', 'N', 'N', 0, 2, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL ZTRMM( 'R', 'U', 'C', 'N', 0, 2, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL ZTRMM( 'R', 'U', 'T', 'N', 0, 2, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL ZTRMM( 'L', 'L', 'N', 'N', 2, 0, ALPHA, A, 1, B, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL ZTRMM( 'L', 'L', 'C', 'N', 2, 0, ALPHA, A, 1, B, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL ZTRMM( 'L', 'L', 'T', 'N', 2, 0, ALPHA, A, 1, B, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL ZTRMM( 'R', 'L', 'N', 'N', 0, 2, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL ZTRMM( 'R', 'L', 'C', 'N', 0, 2, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL ZTRMM( 'R', 'L', 'T', 'N', 0, 2, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL ZTRMM( 'L', 'U', 'N', 'N', 2, 0, ALPHA, A, 2, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL ZTRMM( 'L', 'U', 'C', 'N', 2, 0, ALPHA, A, 2, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL ZTRMM( 'L', 'U', 'T', 'N', 2, 0, ALPHA, A, 2, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL ZTRMM( 'R', 'U', 'N', 'N', 2, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL ZTRMM( 'R', 'U', 'C', 'N', 2, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL ZTRMM( 'R', 'U', 'T', 'N', 2, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL ZTRMM( 'L', 'L', 'N', 'N', 2, 0, ALPHA, A, 2, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL ZTRMM( 'L', 'L', 'C', 'N', 2, 0, ALPHA, A, 2, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL ZTRMM( 'L', 'L', 'T', 'N', 2, 0, ALPHA, A, 2, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL ZTRMM( 'R', 'L', 'N', 'N', 2, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL ZTRMM( 'R', 'L', 'C', 'N', 2, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL ZTRMM( 'R', 'L', 'T', 'N', 2, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 100 50 INFOT = 1 CALL ZTRSM( '/', 'U', 'N', 'N', 0, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL ZTRSM( 'L', '/', 'N', 'N', 0, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL ZTRSM( 'L', 'U', '/', 'N', 0, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL ZTRSM( 'L', 'U', 'N', '/', 0, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL ZTRSM( 'L', 'U', 'N', 'N', -1, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL ZTRSM( 'L', 'U', 'C', 'N', -1, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL ZTRSM( 'L', 'U', 'T', 'N', -1, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL ZTRSM( 'R', 'U', 'N', 'N', -1, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL ZTRSM( 'R', 'U', 'C', 'N', -1, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL ZTRSM( 'R', 'U', 'T', 'N', -1, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL ZTRSM( 'L', 'L', 'N', 'N', -1, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL ZTRSM( 'L', 'L', 'C', 'N', -1, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL ZTRSM( 'L', 'L', 'T', 'N', -1, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL ZTRSM( 'R', 'L', 'N', 'N', -1, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL ZTRSM( 'R', 'L', 'C', 'N', -1, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 5 CALL ZTRSM( 'R', 'L', 'T', 'N', -1, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL ZTRSM( 'L', 'U', 'N', 'N', 0, -1, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL ZTRSM( 'L', 'U', 'C', 'N', 0, -1, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL ZTRSM( 'L', 'U', 'T', 'N', 0, -1, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL ZTRSM( 'R', 'U', 'N', 'N', 0, -1, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL ZTRSM( 'R', 'U', 'C', 'N', 0, -1, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL ZTRSM( 'R', 'U', 'T', 'N', 0, -1, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL ZTRSM( 'L', 'L', 'N', 'N', 0, -1, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL ZTRSM( 'L', 'L', 'C', 'N', 0, -1, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL ZTRSM( 'L', 'L', 'T', 'N', 0, -1, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL ZTRSM( 'R', 'L', 'N', 'N', 0, -1, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL ZTRSM( 'R', 'L', 'C', 'N', 0, -1, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 6 CALL ZTRSM( 'R', 'L', 'T', 'N', 0, -1, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL ZTRSM( 'L', 'U', 'N', 'N', 2, 0, ALPHA, A, 1, B, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL ZTRSM( 'L', 'U', 'C', 'N', 2, 0, ALPHA, A, 1, B, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL ZTRSM( 'L', 'U', 'T', 'N', 2, 0, ALPHA, A, 1, B, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL ZTRSM( 'R', 'U', 'N', 'N', 0, 2, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL ZTRSM( 'R', 'U', 'C', 'N', 0, 2, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL ZTRSM( 'R', 'U', 'T', 'N', 0, 2, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL ZTRSM( 'L', 'L', 'N', 'N', 2, 0, ALPHA, A, 1, B, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL ZTRSM( 'L', 'L', 'C', 'N', 2, 0, ALPHA, A, 1, B, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL ZTRSM( 'L', 'L', 'T', 'N', 2, 0, ALPHA, A, 1, B, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL ZTRSM( 'R', 'L', 'N', 'N', 0, 2, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL ZTRSM( 'R', 'L', 'C', 'N', 0, 2, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL ZTRSM( 'R', 'L', 'T', 'N', 0, 2, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL ZTRSM( 'L', 'U', 'N', 'N', 2, 0, ALPHA, A, 2, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL ZTRSM( 'L', 'U', 'C', 'N', 2, 0, ALPHA, A, 2, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL ZTRSM( 'L', 'U', 'T', 'N', 2, 0, ALPHA, A, 2, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL ZTRSM( 'R', 'U', 'N', 'N', 2, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL ZTRSM( 'R', 'U', 'C', 'N', 2, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL ZTRSM( 'R', 'U', 'T', 'N', 2, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL ZTRSM( 'L', 'L', 'N', 'N', 2, 0, ALPHA, A, 2, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL ZTRSM( 'L', 'L', 'C', 'N', 2, 0, ALPHA, A, 2, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL ZTRSM( 'L', 'L', 'T', 'N', 2, 0, ALPHA, A, 2, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL ZTRSM( 'R', 'L', 'N', 'N', 2, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL ZTRSM( 'R', 'L', 'C', 'N', 2, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 11 CALL ZTRSM( 'R', 'L', 'T', 'N', 2, 0, ALPHA, A, 1, B, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 100 60 INFOT = 1 CALL ZHERK( '/', 'N', 0, 0, RALPHA, A, 1, RBETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL ZHERK( 'U', 'T', 0, 0, RALPHA, A, 1, RBETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL ZHERK( 'U', 'N', -1, 0, RALPHA, A, 1, RBETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL ZHERK( 'U', 'C', -1, 0, RALPHA, A, 1, RBETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL ZHERK( 'L', 'N', -1, 0, RALPHA, A, 1, RBETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL ZHERK( 'L', 'C', -1, 0, RALPHA, A, 1, RBETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL ZHERK( 'U', 'N', 0, -1, RALPHA, A, 1, RBETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL ZHERK( 'U', 'C', 0, -1, RALPHA, A, 1, RBETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL ZHERK( 'L', 'N', 0, -1, RALPHA, A, 1, RBETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL ZHERK( 'L', 'C', 0, -1, RALPHA, A, 1, RBETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL ZHERK( 'U', 'N', 2, 0, RALPHA, A, 1, RBETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL ZHERK( 'U', 'C', 0, 2, RALPHA, A, 1, RBETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL ZHERK( 'L', 'N', 2, 0, RALPHA, A, 1, RBETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL ZHERK( 'L', 'C', 0, 2, RALPHA, A, 1, RBETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 10 CALL ZHERK( 'U', 'N', 2, 0, RALPHA, A, 2, RBETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 10 CALL ZHERK( 'U', 'C', 2, 0, RALPHA, A, 1, RBETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 10 CALL ZHERK( 'L', 'N', 2, 0, RALPHA, A, 2, RBETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 10 CALL ZHERK( 'L', 'C', 2, 0, RALPHA, A, 1, RBETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 100 70 INFOT = 1 CALL ZSYRK( '/', 'N', 0, 0, ALPHA, A, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL ZSYRK( 'U', 'C', 0, 0, ALPHA, A, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL ZSYRK( 'U', 'N', -1, 0, ALPHA, A, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL ZSYRK( 'U', 'T', -1, 0, ALPHA, A, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL ZSYRK( 'L', 'N', -1, 0, ALPHA, A, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL ZSYRK( 'L', 'T', -1, 0, ALPHA, A, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL ZSYRK( 'U', 'N', 0, -1, ALPHA, A, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL ZSYRK( 'U', 'T', 0, -1, ALPHA, A, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL ZSYRK( 'L', 'N', 0, -1, ALPHA, A, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL ZSYRK( 'L', 'T', 0, -1, ALPHA, A, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL ZSYRK( 'U', 'N', 2, 0, ALPHA, A, 1, BETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL ZSYRK( 'U', 'T', 0, 2, ALPHA, A, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL ZSYRK( 'L', 'N', 2, 0, ALPHA, A, 1, BETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL ZSYRK( 'L', 'T', 0, 2, ALPHA, A, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 10 CALL ZSYRK( 'U', 'N', 2, 0, ALPHA, A, 2, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 10 CALL ZSYRK( 'U', 'T', 2, 0, ALPHA, A, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 10 CALL ZSYRK( 'L', 'N', 2, 0, ALPHA, A, 2, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 10 CALL ZSYRK( 'L', 'T', 2, 0, ALPHA, A, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 100 80 INFOT = 1 CALL ZHER2K( '/', 'N', 0, 0, ALPHA, A, 1, B, 1, RBETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL ZHER2K( 'U', 'T', 0, 0, ALPHA, A, 1, B, 1, RBETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL ZHER2K( 'U', 'N', -1, 0, ALPHA, A, 1, B, 1, RBETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL ZHER2K( 'U', 'C', -1, 0, ALPHA, A, 1, B, 1, RBETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL ZHER2K( 'L', 'N', -1, 0, ALPHA, A, 1, B, 1, RBETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL ZHER2K( 'L', 'C', -1, 0, ALPHA, A, 1, B, 1, RBETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL ZHER2K( 'U', 'N', 0, -1, ALPHA, A, 1, B, 1, RBETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL ZHER2K( 'U', 'C', 0, -1, ALPHA, A, 1, B, 1, RBETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL ZHER2K( 'L', 'N', 0, -1, ALPHA, A, 1, B, 1, RBETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL ZHER2K( 'L', 'C', 0, -1, ALPHA, A, 1, B, 1, RBETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL ZHER2K( 'U', 'N', 2, 0, ALPHA, A, 1, B, 1, RBETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL ZHER2K( 'U', 'C', 0, 2, ALPHA, A, 1, B, 1, RBETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL ZHER2K( 'L', 'N', 2, 0, ALPHA, A, 1, B, 1, RBETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL ZHER2K( 'L', 'C', 0, 2, ALPHA, A, 1, B, 1, RBETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL ZHER2K( 'U', 'N', 2, 0, ALPHA, A, 2, B, 1, RBETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL ZHER2K( 'U', 'C', 0, 2, ALPHA, A, 2, B, 1, RBETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL ZHER2K( 'L', 'N', 2, 0, ALPHA, A, 2, B, 1, RBETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL ZHER2K( 'L', 'C', 0, 2, ALPHA, A, 2, B, 1, RBETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 12 CALL ZHER2K( 'U', 'N', 2, 0, ALPHA, A, 2, B, 2, RBETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 12 CALL ZHER2K( 'U', 'C', 2, 0, ALPHA, A, 1, B, 1, RBETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 12 CALL ZHER2K( 'L', 'N', 2, 0, ALPHA, A, 2, B, 2, RBETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 12 CALL ZHER2K( 'L', 'C', 2, 0, ALPHA, A, 1, B, 1, RBETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) GO TO 100 90 INFOT = 1 CALL ZSYR2K( '/', 'N', 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 2 CALL ZSYR2K( 'U', 'C', 0, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL ZSYR2K( 'U', 'N', -1, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL ZSYR2K( 'U', 'T', -1, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL ZSYR2K( 'L', 'N', -1, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 3 CALL ZSYR2K( 'L', 'T', -1, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL ZSYR2K( 'U', 'N', 0, -1, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL ZSYR2K( 'U', 'T', 0, -1, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL ZSYR2K( 'L', 'N', 0, -1, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 4 CALL ZSYR2K( 'L', 'T', 0, -1, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL ZSYR2K( 'U', 'N', 2, 0, ALPHA, A, 1, B, 1, BETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL ZSYR2K( 'U', 'T', 0, 2, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL ZSYR2K( 'L', 'N', 2, 0, ALPHA, A, 1, B, 1, BETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 7 CALL ZSYR2K( 'L', 'T', 0, 2, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL ZSYR2K( 'U', 'N', 2, 0, ALPHA, A, 2, B, 1, BETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL ZSYR2K( 'U', 'T', 0, 2, ALPHA, A, 2, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL ZSYR2K( 'L', 'N', 2, 0, ALPHA, A, 2, B, 1, BETA, C, 2 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 9 CALL ZSYR2K( 'L', 'T', 0, 2, ALPHA, A, 2, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 12 CALL ZSYR2K( 'U', 'N', 2, 0, ALPHA, A, 2, B, 2, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 12 CALL ZSYR2K( 'U', 'T', 2, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 12 CALL ZSYR2K( 'L', 'N', 2, 0, ALPHA, A, 2, B, 2, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) INFOT = 12 CALL ZSYR2K( 'L', 'T', 2, 0, ALPHA, A, 1, B, 1, BETA, C, 1 ) CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) * 100 IF( OK )THEN WRITE( NOUT, FMT = 9999 )SRNAMT ELSE WRITE( NOUT, FMT = 9998 )SRNAMT END IF RETURN * 9999 FORMAT( ' ', A6, ' PASSED THE TESTS OF ERROR-EXITS' ) 9998 FORMAT( ' ******* ', A6, ' FAILED THE TESTS OF ERROR-EXITS *****', $ '**' ) * * End of ZCHKE. * END SUBROUTINE ZMAKE( TYPE, UPLO, DIAG, M, N, A, NMAX, AA, LDA, RESET, $ TRANSL ) * * Generates values for an M by N matrix A. * Stores the values in the array AA in the data structure required * by the routine, with unwanted elements set to rogue value. * * TYPE is 'GE', 'HE', 'SY' or 'TR'. * * Auxiliary routine for test program for Level 3 Blas. * * -- Written on 8-February-1989. * Jack Dongarra, Argonne National Laboratory. * Iain Duff, AERE Harwell. * Jeremy Du Croz, Numerical Algorithms Group Ltd. * Sven Hammarling, Numerical Algorithms Group Ltd. * * .. Parameters .. COMPLEX*16 ZERO, ONE PARAMETER ( ZERO = ( 0.0D0, 0.0D0 ), $ ONE = ( 1.0D0, 0.0D0 ) ) COMPLEX*16 ROGUE PARAMETER ( ROGUE = ( -1.0D10, 1.0D10 ) ) DOUBLE PRECISION RZERO PARAMETER ( RZERO = 0.0D0 ) DOUBLE PRECISION RROGUE PARAMETER ( RROGUE = -1.0D10 ) * .. Scalar Arguments .. COMPLEX*16 TRANSL INTEGER LDA, M, N, NMAX LOGICAL RESET CHARACTER*1 DIAG, UPLO CHARACTER*2 TYPE * .. Array Arguments .. COMPLEX*16 A( NMAX, * ), AA( * ) * .. Local Scalars .. INTEGER I, IBEG, IEND, J, JJ LOGICAL GEN, HER, LOWER, SYM, TRI, UNIT, UPPER * .. External Functions .. COMPLEX*16 ZBEG EXTERNAL ZBEG * .. Intrinsic Functions .. INTRINSIC DCMPLX, DCONJG, DBLE * .. Executable Statements .. GEN = TYPE.EQ.'GE' HER = TYPE.EQ.'HE' SYM = TYPE.EQ.'SY' TRI = TYPE.EQ.'TR' UPPER = ( HER.OR.SYM.OR.TRI ).AND.UPLO.EQ.'U' LOWER = ( HER.OR.SYM.OR.TRI ).AND.UPLO.EQ.'L' UNIT = TRI.AND.DIAG.EQ.'U' * * Generate data in array A. * DO 20 J = 1, N DO 10 I = 1, M IF( GEN.OR.( UPPER.AND.I.LE.J ).OR.( LOWER.AND.I.GE.J ) ) $ THEN A( I, J ) = ZBEG( RESET ) + TRANSL IF( I.NE.J )THEN * Set some elements to zero IF( N.GT.3.AND.J.EQ.N/2 ) $ A( I, J ) = ZERO IF( HER )THEN A( J, I ) = DCONJG( A( I, J ) ) ELSE IF( SYM )THEN A( J, I ) = A( I, J ) ELSE IF( TRI )THEN A( J, I ) = ZERO END IF END IF END IF 10 CONTINUE IF( HER ) $ A( J, J ) = DCMPLX( DBLE( A( J, J ) ), RZERO ) IF( TRI ) $ A( J, J ) = A( J, J ) + ONE IF( UNIT ) $ A( J, J ) = ONE 20 CONTINUE * * Store elements in array AS in data structure required by routine. * IF( TYPE.EQ.'GE' )THEN DO 50 J = 1, N DO 30 I = 1, M AA( I + ( J - 1 )*LDA ) = A( I, J ) 30 CONTINUE DO 40 I = M + 1, LDA AA( I + ( J - 1 )*LDA ) = ROGUE 40 CONTINUE 50 CONTINUE ELSE IF( TYPE.EQ.'HE'.OR.TYPE.EQ.'SY'.OR.TYPE.EQ.'TR' )THEN DO 90 J = 1, N IF( UPPER )THEN IBEG = 1 IF( UNIT )THEN IEND = J - 1 ELSE IEND = J END IF ELSE IF( UNIT )THEN IBEG = J + 1 ELSE IBEG = J END IF IEND = N END IF DO 60 I = 1, IBEG - 1 AA( I + ( J - 1 )*LDA ) = ROGUE 60 CONTINUE DO 70 I = IBEG, IEND AA( I + ( J - 1 )*LDA ) = A( I, J ) 70 CONTINUE DO 80 I = IEND + 1, LDA AA( I + ( J - 1 )*LDA ) = ROGUE 80 CONTINUE IF( HER )THEN JJ = J + ( J - 1 )*LDA AA( JJ ) = DCMPLX( DBLE( AA( JJ ) ), RROGUE ) END IF 90 CONTINUE END IF RETURN * * End of ZMAKE. * END SUBROUTINE ZMMCH( TRANSA, TRANSB, M, N, KK, ALPHA, A, LDA, B, LDB, $ BETA, C, LDC, CT, G, CC, LDCC, EPS, ERR, FATAL, $ NOUT, MV ) * * Checks the results of the computational tests. * * Auxiliary routine for test program for Level 3 Blas. * * -- Written on 8-February-1989. * Jack Dongarra, Argonne National Laboratory. * Iain Duff, AERE Harwell. * Jeremy Du Croz, Numerical Algorithms Group Ltd. * Sven Hammarling, Numerical Algorithms Group Ltd. * * .. Parameters .. COMPLEX*16 ZERO PARAMETER ( ZERO = ( 0.0D0, 0.0D0 ) ) DOUBLE PRECISION RZERO, RONE PARAMETER ( RZERO = 0.0D0, RONE = 1.0D0 ) * .. Scalar Arguments .. COMPLEX*16 ALPHA, BETA DOUBLE PRECISION EPS, ERR INTEGER KK, LDA, LDB, LDC, LDCC, M, N, NOUT LOGICAL FATAL, MV CHARACTER*1 TRANSA, TRANSB * .. Array Arguments .. COMPLEX*16 A( LDA, * ), B( LDB, * ), C( LDC, * ), $ CC( LDCC, * ), CT( * ) DOUBLE PRECISION G( * ) * .. Local Scalars .. COMPLEX*16 CL DOUBLE PRECISION ERRI INTEGER I, J, K LOGICAL CTRANA, CTRANB, TRANA, TRANB * .. Intrinsic Functions .. INTRINSIC ABS, DIMAG, DCONJG, MAX, DBLE, SQRT * .. Statement Functions .. DOUBLE PRECISION ABS1 * .. Statement Function definitions .. ABS1( CL ) = ABS( DBLE( CL ) ) + ABS( DIMAG( CL ) ) * .. Executable Statements .. TRANA = TRANSA.EQ.'T'.OR.TRANSA.EQ.'C' TRANB = TRANSB.EQ.'T'.OR.TRANSB.EQ.'C' CTRANA = TRANSA.EQ.'C' CTRANB = TRANSB.EQ.'C' * * Compute expected result, one column at a time, in CT using data * in A, B and C. * Compute gauges in G. * DO 220 J = 1, N * DO 10 I = 1, M CT( I ) = ZERO G( I ) = RZERO 10 CONTINUE IF( .NOT.TRANA.AND..NOT.TRANB )THEN DO 30 K = 1, KK DO 20 I = 1, M CT( I ) = CT( I ) + A( I, K )*B( K, J ) G( I ) = G( I ) + ABS1( A( I, K ) )*ABS1( B( K, J ) ) 20 CONTINUE 30 CONTINUE ELSE IF( TRANA.AND..NOT.TRANB )THEN IF( CTRANA )THEN DO 50 K = 1, KK DO 40 I = 1, M CT( I ) = CT( I ) + DCONJG( A( K, I ) )*B( K, J ) G( I ) = G( I ) + ABS1( A( K, I ) )* $ ABS1( B( K, J ) ) 40 CONTINUE 50 CONTINUE ELSE DO 70 K = 1, KK DO 60 I = 1, M CT( I ) = CT( I ) + A( K, I )*B( K, J ) G( I ) = G( I ) + ABS1( A( K, I ) )* $ ABS1( B( K, J ) ) 60 CONTINUE 70 CONTINUE END IF ELSE IF( .NOT.TRANA.AND.TRANB )THEN IF( CTRANB )THEN DO 90 K = 1, KK DO 80 I = 1, M CT( I ) = CT( I ) + A( I, K )*DCONJG( B( J, K ) ) G( I ) = G( I ) + ABS1( A( I, K ) )* $ ABS1( B( J, K ) ) 80 CONTINUE 90 CONTINUE ELSE DO 110 K = 1, KK DO 100 I = 1, M CT( I ) = CT( I ) + A( I, K )*B( J, K ) G( I ) = G( I ) + ABS1( A( I, K ) )* $ ABS1( B( J, K ) ) 100 CONTINUE 110 CONTINUE END IF ELSE IF( TRANA.AND.TRANB )THEN IF( CTRANA )THEN IF( CTRANB )THEN DO 130 K = 1, KK DO 120 I = 1, M CT( I ) = CT( I ) + DCONJG( A( K, I ) )* $ DCONJG( B( J, K ) ) G( I ) = G( I ) + ABS1( A( K, I ) )* $ ABS1( B( J, K ) ) 120 CONTINUE 130 CONTINUE ELSE DO 150 K = 1, KK DO 140 I = 1, M CT( I ) = CT( I ) + DCONJG( A( K, I ) )* $ B( J, K ) G( I ) = G( I ) + ABS1( A( K, I ) )* $ ABS1( B( J, K ) ) 140 CONTINUE 150 CONTINUE END IF ELSE IF( CTRANB )THEN DO 170 K = 1, KK DO 160 I = 1, M CT( I ) = CT( I ) + A( K, I )* $ DCONJG( B( J, K ) ) G( I ) = G( I ) + ABS1( A( K, I ) )* $ ABS1( B( J, K ) ) 160 CONTINUE 170 CONTINUE ELSE DO 190 K = 1, KK DO 180 I = 1, M CT( I ) = CT( I ) + A( K, I )*B( J, K ) G( I ) = G( I ) + ABS1( A( K, I ) )* $ ABS1( B( J, K ) ) 180 CONTINUE 190 CONTINUE END IF END IF END IF DO 200 I = 1, M CT( I ) = ALPHA*CT( I ) + BETA*C( I, J ) G( I ) = ABS1( ALPHA )*G( I ) + $ ABS1( BETA )*ABS1( C( I, J ) ) 200 CONTINUE * * Compute the error ratio for this result. * ERR = ZERO DO 210 I = 1, M ERRI = ABS1( CT( I ) - CC( I, J ) )/EPS IF( G( I ).NE.RZERO ) $ ERRI = ERRI/G( I ) ERR = MAX( ERR, ERRI ) IF( ERR*SQRT( EPS ).GE.RONE ) $ GO TO 230 210 CONTINUE * 220 CONTINUE * * If the loop completes, all results are at least half accurate. GO TO 250 * * Report fatal error. * 230 FATAL = .TRUE. WRITE( NOUT, FMT = 9999 ) DO 240 I = 1, M IF( MV )THEN WRITE( NOUT, FMT = 9998 )I, CT( I ), CC( I, J ) ELSE WRITE( NOUT, FMT = 9998 )I, CC( I, J ), CT( I ) END IF 240 CONTINUE IF( N.GT.1 ) $ WRITE( NOUT, FMT = 9997 )J * 250 CONTINUE RETURN * 9999 FORMAT( ' ******* FATAL ERROR - COMPUTED RESULT IS LESS THAN HAL', $ 'F ACCURATE *******', /' EXPECTED RE', $ 'SULT COMPUTED RESULT' ) 9998 FORMAT( 1X, I7, 2( ' (', G15.6, ',', G15.6, ')' ) ) 9997 FORMAT( ' THESE ARE THE RESULTS FOR COLUMN ', I3 ) * * End of ZMMCH. * END LOGICAL FUNCTION LZE( RI, RJ, LR ) * * Tests if two arrays are identical. * * Auxiliary routine for test program for Level 3 Blas. * * -- Written on 8-February-1989. * Jack Dongarra, Argonne National Laboratory. * Iain Duff, AERE Harwell. * Jeremy Du Croz, Numerical Algorithms Group Ltd. * Sven Hammarling, Numerical Algorithms Group Ltd. * * .. Scalar Arguments .. INTEGER LR * .. Array Arguments .. COMPLEX*16 RI( * ), RJ( * ) * .. Local Scalars .. INTEGER I * .. Executable Statements .. DO 10 I = 1, LR IF( RI( I ).NE.RJ( I ) ) $ GO TO 20 10 CONTINUE LZE = .TRUE. GO TO 30 20 CONTINUE LZE = .FALSE. 30 RETURN * * End of LZE. * END LOGICAL FUNCTION LZERES( TYPE, UPLO, M, N, AA, AS, LDA ) * * Tests if selected elements in two arrays are equal. * * TYPE is 'GE' or 'HE' or 'SY'. * * Auxiliary routine for test program for Level 3 Blas. * * -- Written on 8-February-1989. * Jack Dongarra, Argonne National Laboratory. * Iain Duff, AERE Harwell. * Jeremy Du Croz, Numerical Algorithms Group Ltd. * Sven Hammarling, Numerical Algorithms Group Ltd. * * .. Scalar Arguments .. INTEGER LDA, M, N CHARACTER*1 UPLO CHARACTER*2 TYPE * .. Array Arguments .. COMPLEX*16 AA( LDA, * ), AS( LDA, * ) * .. Local Scalars .. INTEGER I, IBEG, IEND, J LOGICAL UPPER * .. Executable Statements .. UPPER = UPLO.EQ.'U' IF( TYPE.EQ.'GE' )THEN DO 20 J = 1, N DO 10 I = M + 1, LDA IF( AA( I, J ).NE.AS( I, J ) ) $ GO TO 70 10 CONTINUE 20 CONTINUE ELSE IF( TYPE.EQ.'HE'.OR.TYPE.EQ.'SY' )THEN DO 50 J = 1, N IF( UPPER )THEN IBEG = 1 IEND = J ELSE IBEG = J IEND = N END IF DO 30 I = 1, IBEG - 1 IF( AA( I, J ).NE.AS( I, J ) ) $ GO TO 70 30 CONTINUE DO 40 I = IEND + 1, LDA IF( AA( I, J ).NE.AS( I, J ) ) $ GO TO 70 40 CONTINUE 50 CONTINUE END IF * LZERES = .TRUE. GO TO 80 70 CONTINUE LZERES = .FALSE. 80 RETURN * * End of LZERES. * END COMPLEX*16 FUNCTION ZBEG( RESET ) * * Generates complex numbers as pairs of random numbers uniformly * distributed between -0.5 and 0.5. * * Auxiliary routine for test program for Level 3 Blas. * * -- Written on 8-February-1989. * Jack Dongarra, Argonne National Laboratory. * Iain Duff, AERE Harwell. * Jeremy Du Croz, Numerical Algorithms Group Ltd. * Sven Hammarling, Numerical Algorithms Group Ltd. * * .. Scalar Arguments .. LOGICAL RESET * .. Local Scalars .. INTEGER I, IC, J, MI, MJ * .. Save statement .. SAVE I, IC, J, MI, MJ * .. Intrinsic Functions .. INTRINSIC DCMPLX * .. Executable Statements .. IF( RESET )THEN * Initialize local variables. MI = 891 MJ = 457 I = 7 J = 7 IC = 0 RESET = .FALSE. END IF * * The sequence of values of I or J is bounded between 1 and 999. * If initial I or J = 1,2,3,6,7 or 9, the period will be 50. * If initial I or J = 4 or 8, the period will be 25. * If initial I or J = 5, the period will be 10. * IC is used to break up the period by skipping 1 value of I or J * in 6. * IC = IC + 1 10 I = I*MI J = J*MJ I = I - 1000*( I/1000 ) J = J - 1000*( J/1000 ) IF( IC.GE.5 )THEN IC = 0 GO TO 10 END IF ZBEG = DCMPLX( ( I - 500 )/1001.0D0, ( J - 500 )/1001.0D0 ) RETURN * * End of ZBEG. * END DOUBLE PRECISION FUNCTION DDIFF( X, Y ) * * Auxiliary routine for test program for Level 3 Blas. * * -- Written on 8-February-1989. * Jack Dongarra, Argonne National Laboratory. * Iain Duff, AERE Harwell. * Jeremy Du Croz, Numerical Algorithms Group Ltd. * Sven Hammarling, Numerical Algorithms Group Ltd. * * .. Scalar Arguments .. DOUBLE PRECISION X, Y * .. Executable Statements .. DDIFF = X - Y RETURN * * End of DDIFF. * END SUBROUTINE CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) * * Tests whether XERBLA has detected an error when it should. * * Auxiliary routine for test program for Level 3 Blas. * * -- Written on 8-February-1989. * Jack Dongarra, Argonne National Laboratory. * Iain Duff, AERE Harwell. * Jeremy Du Croz, Numerical Algorithms Group Ltd. * Sven Hammarling, Numerical Algorithms Group Ltd. * * .. Scalar Arguments .. INTEGER INFOT, NOUT LOGICAL LERR, OK CHARACTER*6 SRNAMT * .. Executable Statements .. IF( .NOT.LERR )THEN WRITE( NOUT, FMT = 9999 )INFOT, SRNAMT OK = .FALSE. END IF LERR = .FALSE. RETURN * 9999 FORMAT( ' ***** ILLEGAL VALUE OF PARAMETER NUMBER ', I2, ' NOT D', $ 'ETECTED BY ', A6, ' *****' ) * * End of CHKXER. * END SUBROUTINE XERBLA( SRNAME, INFO ) * * This is a special version of XERBLA to be used only as part of * the test program for testing error exits from the Level 3 BLAS * routines. * * XERBLA is an error handler for the Level 3 BLAS routines. * * It is called by the Level 3 BLAS routines if an input parameter is * invalid. * * Auxiliary routine for test program for Level 3 Blas. * * -- Written on 8-February-1989. * Jack Dongarra, Argonne National Laboratory. * Iain Duff, AERE Harwell. * Jeremy Du Croz, Numerical Algorithms Group Ltd. * Sven Hammarling, Numerical Algorithms Group Ltd. * * .. Scalar Arguments .. INTEGER INFO CHARACTER*6 SRNAME * .. Scalars in Common .. INTEGER INFOT, NOUT LOGICAL LERR, OK CHARACTER*6 SRNAMT * .. Common blocks .. COMMON /INFOC/INFOT, NOUT, OK, LERR COMMON /SRNAMC/SRNAMT * .. Executable Statements .. LERR = .TRUE. IF( INFO.NE.INFOT )THEN IF( INFOT.NE.0 )THEN WRITE( NOUT, FMT = 9999 )INFO, INFOT ELSE WRITE( NOUT, FMT = 9997 )INFO END IF OK = .FALSE. END IF IF( SRNAME.NE.SRNAMT )THEN WRITE( NOUT, FMT = 9998 )SRNAME, SRNAMT OK = .FALSE. END IF RETURN * 9999 FORMAT( ' ******* XERBLA WAS CALLED WITH INFO = ', I6, ' INSTEAD', $ ' OF ', I2, ' *******' ) 9998 FORMAT( ' ******* XERBLA WAS CALLED WITH SRNAME = ', A6, ' INSTE', $ 'AD OF ', A6, ' *******' ) 9997 FORMAT( ' ******* XERBLA WAS CALLED WITH INFO = ', I6, $ ' *******' ) * * End of XERBLA * END blis-0.9.0/blastest/src/sblat1.c000066400000000000000000001133361422157504600164300ustar00rootroot00000000000000/* sblat1.f -- translated by f2c (version 20100827). You must link the resulting object file with libf2c: on Microsoft Windows system, link with libf2c.lib; on Linux or Unix systems, link with .../path/to/libf2c.a -lm or, if you install libf2c.a in a standard place, with -lf2c -lm -- in that order, at the end of the command line, as in cc *.o -lf2c -lm Source for libf2c is in /netlib/f2c/libf2c.zip, e.g., http://www.netlib.org/f2c/libf2c.zip */ #include "f2c.h" /* Common Block Declarations */ struct { integer icase, n, incx, incy; logical pass; } combla_; #define combla_1 combla_ /* Table of constant values */ static integer c__1 = 1; static integer c__9 = 9; static real c_b35 = 1.f; static real c_b39 = .1f; static integer c__5 = 5; static real c_b63 = 0.f; /* > \brief \b SBLAT1 */ /* =========== DOCUMENTATION =========== */ /* Online html documentation available at */ /* http://www.netlib.org/lapack/explore-html/ */ /* Definition: */ /* =========== */ /* PROGRAM SBLAT1 */ /* > \par Purpose: */ /* ============= */ /* > */ /* > \verbatim */ /* > */ /* > Test program for the REAL Level 1 BLAS. */ /* > */ /* > Based upon the original BLAS test routine together with: */ /* > F06EAF Example Program Text */ /* > \endverbatim */ /* Authors: */ /* ======== */ /* > \author Univ. of Tennessee */ /* > \author Univ. of California Berkeley */ /* > \author Univ. of Colorado Denver */ /* > \author NAG Ltd. */ /* > \date April 2012 */ /* > \ingroup single_blas_testing */ /* ===================================================================== */ /* Main program */ int main(void) { /* Initialized data */ static real sfac = 9.765625e-4f; /* Format strings */ static char fmt_99999[] = "(\002 Real BLAS Test Program Results\002,/1x)"; static char fmt_99998[] = "(\002 ----" "- PASS -----\002)"; /* Builtin functions */ integer s_wsfe(cilist *), e_wsfe(void); /* Subroutine */ int s_stop(char *, ftnlen); /* Local variables */ integer ic; extern /* Subroutine */ int check0_(real *), check1_(real *), check2_( real *), check3_(real *), header_(void); /* Fortran I/O blocks */ static cilist io___2 = { 0, 6, 0, fmt_99999, 0 }; static cilist io___4 = { 0, 6, 0, fmt_99998, 0 }; /* -- Reference BLAS test routine (version 3.4.1) -- */ /* -- Reference BLAS is a software package provided by Univ. of Tennessee, -- */ /* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- */ /* April 2012 */ /* ===================================================================== */ /* .. Parameters .. */ /* .. Scalars in Common .. */ /* .. Local Scalars .. */ /* .. External Subroutines .. */ /* .. Common blocks .. */ /* .. Data statements .. */ /* .. Executable Statements .. */ s_wsfe(&io___2); e_wsfe(); for (ic = 1; ic <= 13; ++ic) { combla_1.icase = ic; header_(); /* .. Initialize PASS, INCX, and INCY for a new case. .. */ /* .. the value 9999 for INCX or INCY will appear in the .. */ /* .. detailed output, if any, for cases that do not involve .. */ /* .. these parameters .. */ combla_1.pass = TRUE_; combla_1.incx = 9999; combla_1.incy = 9999; if (combla_1.icase == 3 || combla_1.icase == 11) { check0_(&sfac); } else if (combla_1.icase == 7 || combla_1.icase == 8 || combla_1.icase == 9 || combla_1.icase == 10) { check1_(&sfac); } else if (combla_1.icase == 1 || combla_1.icase == 2 || combla_1.icase == 5 || combla_1.icase == 6 || combla_1.icase == 12 || combla_1.icase == 13) { check2_(&sfac); } else if (combla_1.icase == 4) { check3_(&sfac); } /* -- Print */ if (combla_1.pass) { s_wsfe(&io___4); e_wsfe(); } /* L20: */ } s_stop("", (ftnlen)0); return 0; } /* main */ /* Subroutine */ int header_(void) { /* Initialized data */ static char l[6*13] = " SDOT " "SAXPY " "SROTG " " SROT " "SCOPY " "SSWA" "P " "SNRM2 " "SASUM " "SSCAL " "ISAMAX" "SROTMG" "SROTM " "SDSDOT" ; /* Format strings */ static char fmt_99999[] = "(/\002 Test of subprogram number\002,i3,12x,a" "6)"; /* Builtin functions */ integer s_wsfe(cilist *), do_fio(integer *, char *, ftnlen), e_wsfe(void); /* Fortran I/O blocks */ static cilist io___6 = { 0, 6, 0, fmt_99999, 0 }; /* .. Parameters .. */ /* .. Scalars in Common .. */ /* .. Local Arrays .. */ /* .. Common blocks .. */ /* .. Data statements .. */ /* .. Executable Statements .. */ s_wsfe(&io___6); do_fio(&c__1, (char *)&combla_1.icase, (ftnlen)sizeof(integer)); do_fio(&c__1, l + (0 + (0 + (combla_1.icase - 1) * 6)), (ftnlen)6); e_wsfe(); return 0; } /* header_ */ /* Subroutine */ int check0_(real *sfac) { /* Initialized data */ static real ds1[8] = { .8f,.6f,.8f,-.6f,.8f,0.f,1.f,0.f }; static real datrue[8] = { .5f,.5f,.5f,-.5f,-.5f,0.f,1.f,1.f }; static real dbtrue[8] = { 0.f,.6f,0.f,-.6f,0.f,0.f,1.f,0.f }; static real dab[36] /* was [4][9] */ = { .1f,.3f,1.2f,.2f,.7f,.2f,.6f, 4.2f,0.f,0.f,0.f,0.f,4.f,-1.f,2.f,4.f,6e-10f,.02f,1e5f,10.f,4e10f, .02f,1e-5f,10.f,2e-10f,.04f,1e5f,10.f,2e10f,.04f,1e-5f,10.f,4.f, -2.f,8.f,4.f }; static real dtrue[81] /* was [9][9] */ = { 0.f,0.f,1.3f,.2f,0.f,0.f, 0.f,.5f,0.f,0.f,0.f,4.5f,4.2f,1.f,.5f,0.f,0.f,0.f,0.f,0.f,0.f,0.f, -2.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,4.f,-1.f,0.f,0.f,0.f,0.f,0.f, .015f,0.f,10.f,-1.f,0.f,-1e-4f,0.f,1.f,0.f,0.f,.06144f,10.f,-1.f, 4096.f,-1e6f,0.f,1.f,0.f,0.f,15.f,10.f,-1.f,5e-5f,0.f,1.f,0.f,0.f, 0.f,15.f,10.f,-1.f,5e5f,-4096.f,1.f,.004096f,0.f,0.f,7.f,4.f,0.f, 0.f,-.5f,-.25f,0.f }; static real d12 = 4096.f; static real da1[8] = { .3f,.4f,-.3f,-.4f,-.3f,0.f,0.f,1.f }; static real db1[8] = { .4f,.3f,.4f,.3f,-.4f,0.f,1.f,0.f }; static real dc1[8] = { .6f,.8f,-.6f,.8f,.6f,1.f,0.f,1.f }; /* Builtin functions */ integer s_wsle(cilist *), do_lio(integer *, integer *, char *, ftnlen), e_wsle(void); /* Subroutine */ int s_stop(char *, ftnlen); /* Local variables */ integer i__, k; real sa, sb, sc, ss, dtemp[9]; extern /* Subroutine */ int srotg_(real *, real *, real *, real *), stest_(integer *, real *, real *, real *, real *), stest1_(real *, real *, real *, real *), srotmg_(real *, real *, real *, real *, real *); /* Fortran I/O blocks */ static cilist io___23 = { 0, 6, 0, 0, 0 }; /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Scalars in Common .. */ /* .. Local Scalars .. */ /* .. Local Arrays .. */ /* .. External Subroutines .. */ /* .. Common blocks .. */ /* .. Data statements .. */ /* INPUT FOR MODIFIED GIVENS */ /* TRUE RESULTS FOR MODIFIED GIVENS */ /* 4096 = 2 ** 12 */ dtrue[0] = .092307692307692313f; dtrue[1] = .27692307692307694f; dtrue[6] = -.16666666666666666f; dtrue[9] = .18666666666666668f; dtrue[10] = .65333333333333332f; dtrue[17] = .14285714285714285f; dtrue[36] = d12 * d12 * 4.5e-10f; dtrue[38] = 4e5f / (d12 * 3.f); dtrue[41] = 1.f / d12; dtrue[43] = 1e4f / (d12 * 3.f); dtrue[45] = 4e10f / (d12 * 1.5f * d12); dtrue[46] = .013333333333333334f; dtrue[52] = d12 * 5e-7f; dtrue[54] = .026666666666666668f; dtrue[55] = d12 * d12 * 1.3333333333333334e-10f; dtrue[60] = -dtrue[41]; dtrue[62] = 1e4f / d12; dtrue[63] = dtrue[54]; dtrue[64] = 2e10f / (d12 * 1.5f * d12); dtrue[72] = 4.5714285714285712f; dtrue[73] = -2.2857142857142856f; /* .. Executable Statements .. */ /* Compute true values which cannot be prestored */ /* in decimal notation */ dbtrue[0] = 1.6666666666666667f; dbtrue[2] = -1.6666666666666667f; dbtrue[4] = 1.6666666666666667f; for (k = 1; k <= 8; ++k) { /* .. Set N=K for identification in output if any .. */ combla_1.n = k; if (combla_1.icase == 3) { /* .. SROTG .. */ if (k > 8) { goto L40; } sa = da1[k - 1]; sb = db1[k - 1]; srotg_(&sa, &sb, &sc, &ss); stest1_(&sa, &datrue[k - 1], &datrue[k - 1], sfac); stest1_(&sb, &dbtrue[k - 1], &dbtrue[k - 1], sfac); stest1_(&sc, &dc1[k - 1], &dc1[k - 1], sfac); stest1_(&ss, &ds1[k - 1], &ds1[k - 1], sfac); } else if (combla_1.icase == 11) { /* .. SROTMG .. */ for (i__ = 1; i__ <= 4; ++i__) { dtemp[i__ - 1] = dab[i__ + (k << 2) - 5]; dtemp[i__ + 3] = 0.f; } dtemp[8] = 0.f; srotmg_(dtemp, &dtemp[1], &dtemp[2], &dtemp[3], &dtemp[4]); stest_(&c__9, dtemp, &dtrue[k * 9 - 9], &dtrue[k * 9 - 9], sfac); } else { s_wsle(&io___23); do_lio(&c__9, &c__1, " Shouldn't be here in CHECK0", (ftnlen)28); e_wsle(); s_stop("", (ftnlen)0); } /* L20: */ } L40: return 0; } /* check0_ */ /* Subroutine */ int check1_(real *sfac) { /* Initialized data */ static real sa[10] = { .3f,-1.f,0.f,1.f,.3f,.3f,.3f,.3f,.3f,.3f }; static real dv[80] /* was [8][5][2] */ = { .1f,2.f,2.f,2.f,2.f,2.f,2.f, 2.f,.3f,3.f,3.f,3.f,3.f,3.f,3.f,3.f,.3f,-.4f,4.f,4.f,4.f,4.f,4.f, 4.f,.2f,-.6f,.3f,5.f,5.f,5.f,5.f,5.f,.1f,-.3f,.5f,-.1f,6.f,6.f, 6.f,6.f,.1f,8.f,8.f,8.f,8.f,8.f,8.f,8.f,.3f,9.f,9.f,9.f,9.f,9.f, 9.f,9.f,.3f,2.f,-.4f,2.f,2.f,2.f,2.f,2.f,.2f,3.f,-.6f,5.f,.3f,2.f, 2.f,2.f,.1f,4.f,-.3f,6.f,-.5f,7.f,-.1f,3.f }; static real dtrue1[5] = { 0.f,.3f,.5f,.7f,.6f }; static real dtrue3[5] = { 0.f,.3f,.7f,1.1f,1.f }; static real dtrue5[80] /* was [8][5][2] */ = { .1f,2.f,2.f,2.f,2.f, 2.f,2.f,2.f,-.3f,3.f,3.f,3.f,3.f,3.f,3.f,3.f,0.f,0.f,4.f,4.f,4.f, 4.f,4.f,4.f,.2f,-.6f,.3f,5.f,5.f,5.f,5.f,5.f,.03f,-.09f,.15f, -.03f,6.f,6.f,6.f,6.f,.1f,8.f,8.f,8.f,8.f,8.f,8.f,8.f,.09f,9.f, 9.f,9.f,9.f,9.f,9.f,9.f,.09f,2.f,-.12f,2.f,2.f,2.f,2.f,2.f,.06f, 3.f,-.18f,5.f,.09f,2.f,2.f,2.f,.03f,4.f,-.09f,6.f,-.15f,7.f,-.03f, 3.f }; static integer itrue2[5] = { 0,1,2,2,3 }; /* System generated locals */ integer i__1; real r__1; /* Builtin functions */ integer s_wsle(cilist *), do_lio(integer *, integer *, char *, ftnlen), e_wsle(void); /* Subroutine */ int s_stop(char *, ftnlen); /* Local variables */ integer i__; real sx[8]; integer np1, len; extern real snrm2_(integer *, real *, integer *); extern /* Subroutine */ int sscal_(integer *, real *, real *, integer *); real stemp[1]; extern real sasum_(integer *, real *, integer *); real strue[8]; extern /* Subroutine */ int stest_(integer *, real *, real *, real *, real *), itest1_(integer *, integer *), stest1_(real *, real *, real *, real *); extern integer isamax_(integer *, real *, integer *); /* Fortran I/O blocks */ static cilist io___36 = { 0, 6, 0, 0, 0 }; /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Scalars in Common .. */ /* .. Local Scalars .. */ /* .. Local Arrays .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. Common blocks .. */ /* .. Data statements .. */ /* .. Executable Statements .. */ for (combla_1.incx = 1; combla_1.incx <= 2; ++combla_1.incx) { for (np1 = 1; np1 <= 5; ++np1) { combla_1.n = np1 - 1; len = max(combla_1.n,1) << 1; /* .. Set vector arguments .. */ i__1 = len; for (i__ = 1; i__ <= i__1; ++i__) { sx[i__ - 1] = dv[i__ + (np1 + combla_1.incx * 5 << 3) - 49]; /* L20: */ } if (combla_1.icase == 7) { /* .. SNRM2 .. */ stemp[0] = dtrue1[np1 - 1]; r__1 = snrm2_(&combla_1.n, sx, &combla_1.incx); stest1_(&r__1, stemp, stemp, sfac); } else if (combla_1.icase == 8) { /* .. SASUM .. */ stemp[0] = dtrue3[np1 - 1]; r__1 = sasum_(&combla_1.n, sx, &combla_1.incx); stest1_(&r__1, stemp, stemp, sfac); } else if (combla_1.icase == 9) { /* .. SSCAL .. */ sscal_(&combla_1.n, &sa[(combla_1.incx - 1) * 5 + np1 - 1], sx, &combla_1.incx); i__1 = len; for (i__ = 1; i__ <= i__1; ++i__) { strue[i__ - 1] = dtrue5[i__ + (np1 + combla_1.incx * 5 << 3) - 49]; /* L40: */ } stest_(&len, sx, strue, strue, sfac); } else if (combla_1.icase == 10) { /* .. ISAMAX .. */ i__1 = isamax_(&combla_1.n, sx, &combla_1.incx); itest1_(&i__1, &itrue2[np1 - 1]); } else { s_wsle(&io___36); do_lio(&c__9, &c__1, " Shouldn't be here in CHECK1", (ftnlen) 28); e_wsle(); s_stop("", (ftnlen)0); } /* L60: */ } /* L80: */ } return 0; } /* check1_ */ /* Subroutine */ int check2_(real *sfac) { /* Initialized data */ static real sa = .3f; static integer incxs[4] = { 1,2,-2,-1 }; static integer incys[4] = { 1,-2,1,-2 }; static integer lens[8] /* was [4][2] */ = { 1,1,2,4,1,1,3,7 }; static integer ns[4] = { 0,1,2,4 }; static real dx1[7] = { .6f,.1f,-.5f,.8f,.9f,-.3f,-.4f }; static real dy1[7] = { .5f,-.9f,.3f,.7f,-.6f,.2f,.8f }; static real dt7[16] /* was [4][4] */ = { 0.f,.3f,.21f,.62f,0.f,.3f,-.07f, .85f,0.f,.3f,-.79f,-.74f,0.f,.3f,.33f,1.27f }; static real st7b[16] /* was [4][4] */ = { .1f,.4f,.31f,.72f,.1f, .4f,.03f,.95f,.1f,.4f,-.69f,-.64f,.1f,.4f,.43f,1.37f }; static real dt8[112] /* was [7][4][4] */ = { .5f,0.f,0.f,0.f,0.f, 0.f,0.f,.68f,0.f,0.f,0.f,0.f,0.f,0.f,.68f,-.87f,0.f,0.f,0.f,0.f, 0.f,.68f,-.87f,.15f,.94f,0.f,0.f,0.f,.5f,0.f,0.f,0.f,0.f,0.f,0.f, .68f,0.f,0.f,0.f,0.f,0.f,0.f,.35f,-.9f,.48f,0.f,0.f,0.f,0.f,.38f, -.9f,.57f,.7f,-.75f,.2f,.98f,.5f,0.f,0.f,0.f,0.f,0.f,0.f,.68f,0.f, 0.f,0.f,0.f,0.f,0.f,.35f,-.72f,0.f,0.f,0.f,0.f,0.f,.38f,-.63f, .15f,.88f,0.f,0.f,0.f,.5f,0.f,0.f,0.f,0.f,0.f,0.f,.68f,0.f,0.f, 0.f,0.f,0.f,0.f,.68f,-.9f,.33f,0.f,0.f,0.f,0.f,.68f,-.9f,.33f,.7f, -.75f,.2f,1.04f }; static real dt10x[112] /* was [7][4][4] */ = { .6f,0.f,0.f,0.f,0.f, 0.f,0.f,.5f,0.f,0.f,0.f,0.f,0.f,0.f,.5f,-.9f,0.f,0.f,0.f,0.f,0.f, .5f,-.9f,.3f,.7f,0.f,0.f,0.f,.6f,0.f,0.f,0.f,0.f,0.f,0.f,.5f,0.f, 0.f,0.f,0.f,0.f,0.f,.3f,.1f,.5f,0.f,0.f,0.f,0.f,.8f,.1f,-.6f,.8f, .3f,-.3f,.5f,.6f,0.f,0.f,0.f,0.f,0.f,0.f,.5f,0.f,0.f,0.f,0.f,0.f, 0.f,-.9f,.1f,.5f,0.f,0.f,0.f,0.f,.7f,.1f,.3f,.8f,-.9f,-.3f,.5f, .6f,0.f,0.f,0.f,0.f,0.f,0.f,.5f,0.f,0.f,0.f,0.f,0.f,0.f,.5f,.3f, 0.f,0.f,0.f,0.f,0.f,.5f,.3f,-.6f,.8f,0.f,0.f,0.f }; static real dt10y[112] /* was [7][4][4] */ = { .5f,0.f,0.f,0.f,0.f, 0.f,0.f,.6f,0.f,0.f,0.f,0.f,0.f,0.f,.6f,.1f,0.f,0.f,0.f,0.f,0.f, .6f,.1f,-.5f,.8f,0.f,0.f,0.f,.5f,0.f,0.f,0.f,0.f,0.f,0.f,.6f,0.f, 0.f,0.f,0.f,0.f,0.f,-.5f,-.9f,.6f,0.f,0.f,0.f,0.f,-.4f,-.9f,.9f, .7f,-.5f,.2f,.6f,.5f,0.f,0.f,0.f,0.f,0.f,0.f,.6f,0.f,0.f,0.f,0.f, 0.f,0.f,-.5f,.6f,0.f,0.f,0.f,0.f,0.f,-.4f,.9f,-.5f,.6f,0.f,0.f, 0.f,.5f,0.f,0.f,0.f,0.f,0.f,0.f,.6f,0.f,0.f,0.f,0.f,0.f,0.f,.6f, -.9f,.1f,0.f,0.f,0.f,0.f,.6f,-.9f,.1f,.7f,-.5f,.2f,.8f }; static real ssize1[4] = { 0.f,.3f,1.6f,3.2f }; static real ssize2[28] /* was [14][2] */ = { 0.f,0.f,0.f,0.f,0.f,0.f, 0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,1.17f,1.17f,1.17f,1.17f,1.17f, 1.17f,1.17f,1.17f,1.17f,1.17f,1.17f,1.17f,1.17f,1.17f }; static real ssize3[4] = { .1f,.4f,1.7f,3.3f }; static real dpar[20] /* was [5][4] */ = { -2.f,0.f,0.f,0.f,0.f, -1.f,2.f,-3.f,-4.f,5.f,0.f,0.f,2.f,-3.f,0.f,1.f,5.f,2.f,0.f,-4.f } ; static struct { real e_1[448]; } equiv_3 = {{ .6f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, .6f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, .6f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, .6f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, .6f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, -.8f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, -.9f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 3.5f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, .6f, .1f, 0.f, 0.f, 0.f, 0.f, 0.f, -.8f, 3.8f, 0.f, 0.f, 0.f, 0.f, 0.f, -.9f, 2.8f, 0.f, 0.f, 0.f, 0.f, 0.f, 3.5f, -.4f, 0.f, 0.f, 0.f, 0.f, 0.f, .6f, .1f, -.5f, .8f, 0.f, 0.f, 0.f, -.8f, 3.8f, -2.2f, -1.2f, 0.f, 0.f, 0.f, -.9f, 2.8f, -1.4f, -1.3f, 0.f, 0.f, 0.f, 3.5f, -.4f, -2.2f, 4.7f, 0.f, 0.f, 0.f, .6f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, .6f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, .6f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, .6f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, .6f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, -.8f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, -.9f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 3.5f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, .6f, .1f, -.5f, 0.f, 0.f, 0.f, 0.f, 0.f, .1f, -3.f, 0.f, 0.f, 0.f, 0.f, -.3f, .1f, -2.f, 0.f, 0.f, 0.f, 0.f, 3.3f, .1f, -2.f, 0.f, 0.f, 0.f, 0.f, .6f, .1f, -.5f, .8f, .9f, -.3f, -.4f, -2.f, .1f, 1.4f, .8f, .6f, -.3f, -2.8f, -1.8f, .1f, 1.3f, .8f, 0.f, -.3f, -1.9f, 3.8f, .1f, -3.1f, .8f, 4.8f, -.3f, -1.5f, .6f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, .6f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, .6f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, .6f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, .6f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, -.8f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, -.9f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 3.5f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, .6f, .1f, -.5f, 0.f, 0.f, 0.f, 0.f, 4.8f, .1f, -3.f, 0.f, 0.f, 0.f, 0.f, 3.3f, .1f, -2.f, 0.f, 0.f, 0.f, 0.f, 2.1f, .1f, -2.f, 0.f, 0.f, 0.f, 0.f, .6f, .1f, -.5f, .8f, .9f, -.3f, -.4f, -1.6f, .1f, -2.2f, .8f, 5.4f, -.3f, -2.8f, -1.5f, .1f, -1.4f, .8f, 3.6f, -.3f, -1.9f, 3.7f, .1f, -2.2f, .8f, 3.6f, -.3f, -1.5f, .6f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, .6f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, .6f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, .6f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, .6f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, -.8f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, -.9f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 3.5f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, .6f, .1f, 0.f, 0.f, 0.f, 0.f, 0.f, -.8f, -1.f, 0.f, 0.f, 0.f, 0.f, 0.f, -.9f, -.8f, 0.f, 0.f, 0.f, 0.f, 0.f, 3.5f, .8f, 0.f, 0.f, 0.f, 0.f, 0.f, .6f, .1f, -.5f, .8f, 0.f, 0.f, 0.f, -.8f, -1.f, 1.4f, -1.6f, 0.f, 0.f, 0.f, -.9f, -.8f, 1.3f, -1.6f, 0.f, 0.f, 0.f, 3.5f, .8f, -3.1f, 4.8f, 0.f, 0.f, 0.f }}; static struct { real e_1[448]; } equiv_7 = {{ .5f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, .5f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, .5f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, .5f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, .5f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, .7f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 1.7f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, -2.6f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, .5f, -.9f, 0.f, 0.f, 0.f, 0.f, 0.f, .7f, -4.8f, 0.f, 0.f, 0.f, 0.f, 0.f, 1.7f, -.7f, 0.f, 0.f, 0.f, 0.f, 0.f, -2.6f, 3.5f, 0.f, 0.f, 0.f, 0.f, 0.f, .5f, -.9f, .3f, .7f, 0.f, 0.f, 0.f, .7f, -4.8f, 3.f, 1.1f, 0.f, 0.f, 0.f, 1.7f, -.7f, -.7f, 2.3f, 0.f, 0.f, 0.f, -2.6f, 3.5f, -.7f, -3.6f, 0.f, 0.f, 0.f, .5f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, .5f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, .5f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, .5f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, .5f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, .7f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 1.7f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, -2.6f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, .5f, -.9f, .3f, 0.f, 0.f, 0.f, 0.f, 4.f, -.9f, -.3f, 0.f, 0.f, 0.f, 0.f, -.5f, -.9f, 1.5f, 0.f, 0.f, 0.f, 0.f, -1.5f, -.9f, -1.8f, 0.f, 0.f, 0.f, 0.f, .5f, -.9f, .3f, .7f, -.6f, .2f, .8f, 3.7f, -.9f, -1.2f, .7f, -1.5f, .2f, 2.2f, -.3f, -.9f, 2.1f, .7f, -1.6f, .2f, 2.f, -1.6f, -.9f, -2.1f, .7f, 2.9f, .2f, -3.8f, .5f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, .5f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, .5f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, .5f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, .5f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, .7f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 1.7f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, -2.6f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, .5f, -.9f, 0.f, 0.f, 0.f, 0.f, 0.f, 4.f, -6.3f, 0.f, 0.f, 0.f, 0.f, 0.f, -.5f, .3f, 0.f, 0.f, 0.f, 0.f, 0.f, -1.5f, 3.f, 0.f, 0.f, 0.f, 0.f, 0.f, .5f, -.9f, .3f, .7f, 0.f, 0.f, 0.f, 3.7f, -7.2f, 3.f, 1.7f, 0.f, 0.f, 0.f, -.3f, .9f, -.7f, 1.9f, 0.f, 0.f, 0.f, -1.6f, 2.7f, -.7f, -3.4f, 0.f, 0.f, 0.f, .5f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, .5f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, .5f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, .5f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, .5f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, .7f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 1.7f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, -2.6f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, .5f, -.9f, .3f, 0.f, 0.f, 0.f, 0.f, .7f, -.9f, 1.2f, 0.f, 0.f, 0.f, 0.f, 1.7f, -.9f, .5f, 0.f, 0.f, 0.f, 0.f, -2.6f, -.9f, -1.3f, 0.f, 0.f, 0.f, 0.f, .5f, -.9f, .3f, .7f, -.6f, .2f, .8f, .7f, -.9f, 1.2f, .7f, -1.5f, .2f, 1.6f, 1.7f, -.9f, .5f, .7f, -1.6f, .2f, 2.4f, -2.6f, -.9f, -1.3f, .7f, 2.9f, .2f, -4.f }}; /* System generated locals */ integer i__1; real r__1; /* Builtin functions */ integer s_wsle(cilist *), do_lio(integer *, integer *, char *, ftnlen), e_wsle(void); /* Subroutine */ int s_stop(char *, ftnlen); /* Local variables */ integer i__, j, ki, kn, mx, my; real sx[7], sy[7]; integer kni; real stx[7], sty[7]; integer kpar, lenx, leny; #define dt19x ((real *)&equiv_3) #define dt19y ((real *)&equiv_7) extern real sdot_(integer *, real *, integer *, real *, integer *); real dtemp[5]; #define dt19xa ((real *)&equiv_3) #define dt19xb ((real *)&equiv_3 + 112) #define dt19xc ((real *)&equiv_3 + 224) #define dt19xd ((real *)&equiv_3 + 336) #define dt19ya ((real *)&equiv_7) #define dt19yb ((real *)&equiv_7 + 112) #define dt19yc ((real *)&equiv_7 + 224) #define dt19yd ((real *)&equiv_7 + 336) integer ksize; real ssize[7]; extern /* Subroutine */ int scopy_(integer *, real *, integer *, real *, integer *), sswap_(integer *, real *, integer *, real *, integer * ), stest_(integer *, real *, real *, real *, real *), saxpy_( integer *, real *, real *, integer *, real *, integer *), srotm_( integer *, real *, integer *, real *, integer *, real *), stest1_( real *, real *, real *, real *); extern real sdsdot_(integer *, real *, real *, integer *, real *, integer *); /* Fortran I/O blocks */ static cilist io___80 = { 0, 6, 0, 0, 0 }; /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Scalars in Common .. */ /* .. Local Scalars .. */ /* .. Local Arrays .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. Common blocks .. */ /* .. Data statements .. */ /* FOR DROTM */ /* TRUE X RESULTS F0R ROTATIONS DROTM */ /* TRUE Y RESULTS FOR ROTATIONS DROTM */ /* .. Executable Statements .. */ for (ki = 1; ki <= 4; ++ki) { combla_1.incx = incxs[ki - 1]; combla_1.incy = incys[ki - 1]; mx = abs(combla_1.incx); my = abs(combla_1.incy); for (kn = 1; kn <= 4; ++kn) { combla_1.n = ns[kn - 1]; ksize = min(2,kn); lenx = lens[kn + (mx << 2) - 5]; leny = lens[kn + (my << 2) - 5]; /* .. Initialize all argument arrays .. */ for (i__ = 1; i__ <= 7; ++i__) { sx[i__ - 1] = dx1[i__ - 1]; sy[i__ - 1] = dy1[i__ - 1]; /* L20: */ } if (combla_1.icase == 1) { /* .. SDOT .. */ r__1 = sdot_(&combla_1.n, sx, &combla_1.incx, sy, & combla_1.incy); stest1_(&r__1, &dt7[kn + (ki << 2) - 5], &ssize1[kn - 1], sfac); } else if (combla_1.icase == 2) { /* .. SAXPY .. */ saxpy_(&combla_1.n, &sa, sx, &combla_1.incx, sy, & combla_1.incy); i__1 = leny; for (j = 1; j <= i__1; ++j) { sty[j - 1] = dt8[j + (kn + (ki << 2)) * 7 - 36]; /* L40: */ } stest_(&leny, sy, sty, &ssize2[ksize * 14 - 14], sfac); } else if (combla_1.icase == 5) { /* .. SCOPY .. */ for (i__ = 1; i__ <= 7; ++i__) { sty[i__ - 1] = dt10y[i__ + (kn + (ki << 2)) * 7 - 36]; /* L60: */ } scopy_(&combla_1.n, sx, &combla_1.incx, sy, &combla_1.incy); stest_(&leny, sy, sty, ssize2, &c_b35); } else if (combla_1.icase == 6) { /* .. SSWAP .. */ sswap_(&combla_1.n, sx, &combla_1.incx, sy, &combla_1.incy); for (i__ = 1; i__ <= 7; ++i__) { stx[i__ - 1] = dt10x[i__ + (kn + (ki << 2)) * 7 - 36]; sty[i__ - 1] = dt10y[i__ + (kn + (ki << 2)) * 7 - 36]; /* L80: */ } stest_(&lenx, sx, stx, ssize2, &c_b35); stest_(&leny, sy, sty, ssize2, &c_b35); } else if (combla_1.icase == 12) { /* .. SROTM .. */ kni = kn + (ki - 1 << 2); for (kpar = 1; kpar <= 4; ++kpar) { for (i__ = 1; i__ <= 7; ++i__) { sx[i__ - 1] = dx1[i__ - 1]; sy[i__ - 1] = dy1[i__ - 1]; stx[i__ - 1] = dt19x[i__ + (kpar + (kni << 2)) * 7 - 36]; sty[i__ - 1] = dt19y[i__ + (kpar + (kni << 2)) * 7 - 36]; } for (i__ = 1; i__ <= 5; ++i__) { dtemp[i__ - 1] = dpar[i__ + kpar * 5 - 6]; } i__1 = lenx; for (i__ = 1; i__ <= i__1; ++i__) { ssize[i__ - 1] = stx[i__ - 1]; } /* SEE REMARK ABOVE ABOUT DT11X(1,2,7) */ /* AND DT11X(5,3,8). */ if (kpar == 2 && kni == 7) { ssize[0] = 2.4f; } if (kpar == 3 && kni == 8) { ssize[4] = 1.8f; } srotm_(&combla_1.n, sx, &combla_1.incx, sy, & combla_1.incy, dtemp); stest_(&lenx, sx, stx, ssize, sfac); stest_(&leny, sy, sty, sty, sfac); } } else if (combla_1.icase == 13) { /* .. SDSROT .. */ r__1 = sdsdot_(&combla_1.n, &c_b39, sx, &combla_1.incx, sy, & combla_1.incy); stest1_(&r__1, &st7b[kn + (ki << 2) - 5], &ssize3[kn - 1], sfac); } else { s_wsle(&io___80); do_lio(&c__9, &c__1, " Shouldn't be here in CHECK2", (ftnlen) 28); e_wsle(); s_stop("", (ftnlen)0); } /* L100: */ } /* L120: */ } return 0; } /* check2_ */ #undef dt19yd #undef dt19yc #undef dt19yb #undef dt19ya #undef dt19xd #undef dt19xc #undef dt19xb #undef dt19xa #undef dt19y #undef dt19x /* Subroutine */ int check3_(real *sfac) { /* Initialized data */ static integer incxs[4] = { 1,2,-2,-1 }; static integer incys[4] = { 1,-2,1,-2 }; static integer lens[8] /* was [4][2] */ = { 1,1,2,4,1,1,3,7 }; static integer ns[4] = { 0,1,2,4 }; static real dx1[7] = { .6f,.1f,-.5f,.8f,.9f,-.3f,-.4f }; static real dy1[7] = { .5f,-.9f,.3f,.7f,-.6f,.2f,.8f }; static real sc = .8f; static real ss = .6f; static real dt9x[112] /* was [7][4][4] */ = { .6f,0.f,0.f,0.f,0.f, 0.f,0.f,.78f,0.f,0.f,0.f,0.f,0.f,0.f,.78f,-.46f,0.f,0.f,0.f,0.f, 0.f,.78f,-.46f,-.22f,1.06f,0.f,0.f,0.f,.6f,0.f,0.f,0.f,0.f,0.f, 0.f,.78f,0.f,0.f,0.f,0.f,0.f,0.f,.66f,.1f,-.1f,0.f,0.f,0.f,0.f, .96f,.1f,-.76f,.8f,.9f,-.3f,-.02f,.6f,0.f,0.f,0.f,0.f,0.f,0.f, .78f,0.f,0.f,0.f,0.f,0.f,0.f,-.06f,.1f,-.1f,0.f,0.f,0.f,0.f,.9f, .1f,-.22f,.8f,.18f,-.3f,-.02f,.6f,0.f,0.f,0.f,0.f,0.f,0.f,.78f, 0.f,0.f,0.f,0.f,0.f,0.f,.78f,.26f,0.f,0.f,0.f,0.f,0.f,.78f,.26f, -.76f,1.12f,0.f,0.f,0.f }; static real dt9y[112] /* was [7][4][4] */ = { .5f,0.f,0.f,0.f,0.f, 0.f,0.f,.04f,0.f,0.f,0.f,0.f,0.f,0.f,.04f,-.78f,0.f,0.f,0.f,0.f, 0.f,.04f,-.78f,.54f,.08f,0.f,0.f,0.f,.5f,0.f,0.f,0.f,0.f,0.f,0.f, .04f,0.f,0.f,0.f,0.f,0.f,0.f,.7f,-.9f,-.12f,0.f,0.f,0.f,0.f,.64f, -.9f,-.3f,.7f,-.18f,.2f,.28f,.5f,0.f,0.f,0.f,0.f,0.f,0.f,.04f,0.f, 0.f,0.f,0.f,0.f,0.f,.7f,-1.08f,0.f,0.f,0.f,0.f,0.f,.64f,-1.26f, .54f,.2f,0.f,0.f,0.f,.5f,0.f,0.f,0.f,0.f,0.f,0.f,.04f,0.f,0.f,0.f, 0.f,0.f,0.f,.04f,-.9f,.18f,0.f,0.f,0.f,0.f,.04f,-.9f,.18f,.7f, -.18f,.2f,.16f }; static real ssize2[28] /* was [14][2] */ = { 0.f,0.f,0.f,0.f,0.f,0.f, 0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,1.17f,1.17f,1.17f,1.17f,1.17f, 1.17f,1.17f,1.17f,1.17f,1.17f,1.17f,1.17f,1.17f,1.17f }; /* Builtin functions */ integer s_wsle(cilist *), do_lio(integer *, integer *, char *, ftnlen), e_wsle(void); /* Subroutine */ int s_stop(char *, ftnlen); /* Local variables */ integer i__, k, ki, kn, mx, my; real sx[7], sy[7], stx[7], sty[7]; integer lenx, leny; real mwpc[11]; integer mwpn[11]; real mwps[11]; extern /* Subroutine */ int srot_(integer *, real *, integer *, real *, integer *, real *, real *); real mwpx[5], mwpy[5]; integer ksize; real copyx[5], copyy[5]; extern /* Subroutine */ int stest_(integer *, real *, real *, real *, real *); real mwptx[55] /* was [11][5] */, mwpty[55] /* was [11][5] */; integer mwpinx[11], mwpiny[11]; real mwpstx[5], mwpsty[5]; /* Fortran I/O blocks */ static cilist io___104 = { 0, 6, 0, 0, 0 }; /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Scalars in Common .. */ /* .. Local Scalars .. */ /* .. Local Arrays .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. Common blocks .. */ /* .. Data statements .. */ /* .. Executable Statements .. */ for (ki = 1; ki <= 4; ++ki) { combla_1.incx = incxs[ki - 1]; combla_1.incy = incys[ki - 1]; mx = abs(combla_1.incx); my = abs(combla_1.incy); for (kn = 1; kn <= 4; ++kn) { combla_1.n = ns[kn - 1]; ksize = min(2,kn); lenx = lens[kn + (mx << 2) - 5]; leny = lens[kn + (my << 2) - 5]; if (combla_1.icase == 4) { /* .. SROT .. */ for (i__ = 1; i__ <= 7; ++i__) { sx[i__ - 1] = dx1[i__ - 1]; sy[i__ - 1] = dy1[i__ - 1]; stx[i__ - 1] = dt9x[i__ + (kn + (ki << 2)) * 7 - 36]; sty[i__ - 1] = dt9y[i__ + (kn + (ki << 2)) * 7 - 36]; /* L20: */ } srot_(&combla_1.n, sx, &combla_1.incx, sy, &combla_1.incy, & sc, &ss); stest_(&lenx, sx, stx, &ssize2[ksize * 14 - 14], sfac); stest_(&leny, sy, sty, &ssize2[ksize * 14 - 14], sfac); } else { s_wsle(&io___104); do_lio(&c__9, &c__1, " Shouldn't be here in CHECK3", (ftnlen) 28); e_wsle(); s_stop("", (ftnlen)0); } /* L40: */ } /* L60: */ } mwpc[0] = 1.f; for (i__ = 2; i__ <= 11; ++i__) { mwpc[i__ - 1] = 0.f; /* L80: */ } mwps[0] = 0.f; for (i__ = 2; i__ <= 6; ++i__) { mwps[i__ - 1] = 1.f; /* L100: */ } for (i__ = 7; i__ <= 11; ++i__) { mwps[i__ - 1] = -1.f; /* L120: */ } mwpinx[0] = 1; mwpinx[1] = 1; mwpinx[2] = 1; mwpinx[3] = -1; mwpinx[4] = 1; mwpinx[5] = -1; mwpinx[6] = 1; mwpinx[7] = 1; mwpinx[8] = -1; mwpinx[9] = 1; mwpinx[10] = -1; mwpiny[0] = 1; mwpiny[1] = 1; mwpiny[2] = -1; mwpiny[3] = -1; mwpiny[4] = 2; mwpiny[5] = 1; mwpiny[6] = 1; mwpiny[7] = -1; mwpiny[8] = -1; mwpiny[9] = 2; mwpiny[10] = 1; for (i__ = 1; i__ <= 11; ++i__) { mwpn[i__ - 1] = 5; /* L140: */ } mwpn[4] = 3; mwpn[9] = 3; for (i__ = 1; i__ <= 5; ++i__) { mwpx[i__ - 1] = (real) i__; mwpy[i__ - 1] = (real) i__; mwptx[i__ * 11 - 11] = (real) i__; mwpty[i__ * 11 - 11] = (real) i__; mwptx[i__ * 11 - 10] = (real) i__; mwpty[i__ * 11 - 10] = (real) (-i__); mwptx[i__ * 11 - 9] = (real) (6 - i__); mwpty[i__ * 11 - 9] = (real) (i__ - 6); mwptx[i__ * 11 - 8] = (real) i__; mwpty[i__ * 11 - 8] = (real) (-i__); mwptx[i__ * 11 - 6] = (real) (6 - i__); mwpty[i__ * 11 - 6] = (real) (i__ - 6); mwptx[i__ * 11 - 5] = (real) (-i__); mwpty[i__ * 11 - 5] = (real) i__; mwptx[i__ * 11 - 4] = (real) (i__ - 6); mwpty[i__ * 11 - 4] = (real) (6 - i__); mwptx[i__ * 11 - 3] = (real) (-i__); mwpty[i__ * 11 - 3] = (real) i__; mwptx[i__ * 11 - 1] = (real) (i__ - 6); mwpty[i__ * 11 - 1] = (real) (6 - i__); /* L160: */ } mwptx[4] = 1.f; mwptx[15] = 3.f; mwptx[26] = 5.f; mwptx[37] = 4.f; mwptx[48] = 5.f; mwpty[4] = -1.f; mwpty[15] = 2.f; mwpty[26] = -2.f; mwpty[37] = 4.f; mwpty[48] = -3.f; mwptx[9] = -1.f; mwptx[20] = -3.f; mwptx[31] = -5.f; mwptx[42] = 4.f; mwptx[53] = 5.f; mwpty[9] = 1.f; mwpty[20] = 2.f; mwpty[31] = 2.f; mwpty[42] = 4.f; mwpty[53] = 3.f; for (i__ = 1; i__ <= 11; ++i__) { combla_1.incx = mwpinx[i__ - 1]; combla_1.incy = mwpiny[i__ - 1]; for (k = 1; k <= 5; ++k) { copyx[k - 1] = mwpx[k - 1]; copyy[k - 1] = mwpy[k - 1]; mwpstx[k - 1] = mwptx[i__ + k * 11 - 12]; mwpsty[k - 1] = mwpty[i__ + k * 11 - 12]; /* L180: */ } srot_(&mwpn[i__ - 1], copyx, &combla_1.incx, copyy, &combla_1.incy, & mwpc[i__ - 1], &mwps[i__ - 1]); stest_(&c__5, copyx, mwpstx, mwpstx, sfac); stest_(&c__5, copyy, mwpsty, mwpsty, sfac); /* L200: */ } return 0; } /* check3_ */ /* Subroutine */ int stest_(integer *len, real *scomp, real *strue, real * ssize, real *sfac) { /* Format strings */ static char fmt_99999[] = "(\002 F" "AIL\002)"; static char fmt_99998[] = "(/\002 CASE N INCX INCY I " " \002,\002 COMP(I) TRUE(I) " " DIFFERENCE\002,\002 SIZE(I)\002,/1x)"; static char fmt_99997[] = "(1x,i4,i3,2i5,i3,2e36.8,2e12.4)"; /* System generated locals */ integer i__1; real r__1, r__2; /* Builtin functions */ integer s_wsfe(cilist *), e_wsfe(void), do_fio(integer *, char *, ftnlen); /* Local variables */ integer i__; real sd; extern real s_epsilon_(real *); /* Fortran I/O blocks */ static cilist io___121 = { 0, 6, 0, fmt_99999, 0 }; static cilist io___122 = { 0, 6, 0, fmt_99998, 0 }; static cilist io___123 = { 0, 6, 0, fmt_99997, 0 }; /* ********************************* STEST ************************** */ /* THIS SUBR COMPARES ARRAYS SCOMP() AND STRUE() OF LENGTH LEN TO */ /* SEE IF THE TERM BY TERM DIFFERENCES, MULTIPLIED BY SFAC, ARE */ /* NEGLIGIBLE. */ /* C. L. LAWSON, JPL, 1974 DEC 10 */ /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Scalars in Common .. */ /* .. Local Scalars .. */ /* .. External Functions .. */ /* .. Intrinsic Functions .. */ /* .. Common blocks .. */ /* .. Executable Statements .. */ /* Parameter adjustments */ --ssize; --strue; --scomp; /* Function Body */ i__1 = *len; for (i__ = 1; i__ <= i__1; ++i__) { sd = scomp[i__] - strue[i__]; if ((r__2 = *sfac * sd, abs(r__2)) <= (r__1 = ssize[i__], abs(r__1)) * s_epsilon_(&c_b63)) { goto L40; } /* HERE SCOMP(I) IS NOT CLOSE TO STRUE(I). */ if (! combla_1.pass) { goto L20; } /* PRINT FAIL MESSAGE AND HEADER. */ combla_1.pass = FALSE_; s_wsfe(&io___121); e_wsfe(); s_wsfe(&io___122); e_wsfe(); L20: s_wsfe(&io___123); do_fio(&c__1, (char *)&combla_1.icase, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&combla_1.n, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&combla_1.incx, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&combla_1.incy, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&i__, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&scomp[i__], (ftnlen)sizeof(real)); do_fio(&c__1, (char *)&strue[i__], (ftnlen)sizeof(real)); do_fio(&c__1, (char *)&sd, (ftnlen)sizeof(real)); do_fio(&c__1, (char *)&ssize[i__], (ftnlen)sizeof(real)); e_wsfe(); L40: ; } return 0; } /* stest_ */ /* Subroutine */ int stest1_(real *scomp1, real *strue1, real *ssize, real * sfac) { real scomp[1], strue[1]; extern /* Subroutine */ int stest_(integer *, real *, real *, real *, real *); /* ************************* STEST1 ***************************** */ /* THIS IS AN INTERFACE SUBROUTINE TO ACCOMODATE THE FORTRAN */ /* REQUIREMENT THAT WHEN A DUMMY ARGUMENT IS AN ARRAY, THE */ /* ACTUAL ARGUMENT MUST ALSO BE AN ARRAY OR AN ARRAY ELEMENT. */ /* C.L. LAWSON, JPL, 1978 DEC 6 */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Arrays .. */ /* .. External Subroutines .. */ /* .. Executable Statements .. */ /* Parameter adjustments */ --ssize; /* Function Body */ scomp[0] = *scomp1; strue[0] = *strue1; stest_(&c__1, scomp, strue, &ssize[1], sfac); return 0; } /* stest1_ */ real sdiff_(real *sa, real *sb) { /* System generated locals */ real ret_val; /* ********************************* SDIFF ************************** */ /* COMPUTES DIFFERENCE OF TWO NUMBERS. C. L. LAWSON, JPL 1974 FEB 15 */ /* .. Scalar Arguments .. */ /* .. Executable Statements .. */ ret_val = *sa - *sb; return ret_val; } /* sdiff_ */ /* Subroutine */ int itest1_(integer *icomp, integer *itrue) { /* Format strings */ static char fmt_99999[] = "(\002 F" "AIL\002)"; static char fmt_99998[] = "(/\002 CASE N INCX INCY " " \002,\002 COMP TRUE " " DIFFERENCE\002,/1x)"; static char fmt_99997[] = "(1x,i4,i3,2i5,2i36,i12)"; /* Builtin functions */ integer s_wsfe(cilist *), e_wsfe(void), do_fio(integer *, char *, ftnlen); /* Local variables */ integer id; /* Fortran I/O blocks */ static cilist io___126 = { 0, 6, 0, fmt_99999, 0 }; static cilist io___127 = { 0, 6, 0, fmt_99998, 0 }; static cilist io___129 = { 0, 6, 0, fmt_99997, 0 }; /* ********************************* ITEST1 ************************* */ /* THIS SUBROUTINE COMPARES THE VARIABLES ICOMP AND ITRUE FOR */ /* EQUALITY. */ /* C. L. LAWSON, JPL, 1974 DEC 10 */ /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Scalars in Common .. */ /* .. Local Scalars .. */ /* .. Common blocks .. */ /* .. Executable Statements .. */ if (*icomp == *itrue) { goto L40; } /* HERE ICOMP IS NOT EQUAL TO ITRUE. */ if (! combla_1.pass) { goto L20; } /* PRINT FAIL MESSAGE AND HEADER. */ combla_1.pass = FALSE_; s_wsfe(&io___126); e_wsfe(); s_wsfe(&io___127); e_wsfe(); L20: id = *icomp - *itrue; s_wsfe(&io___129); do_fio(&c__1, (char *)&combla_1.icase, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&combla_1.n, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&combla_1.incx, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&combla_1.incy, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&(*icomp), (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&(*itrue), (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&id, (ftnlen)sizeof(integer)); e_wsfe(); L40: return 0; } /* itest1_ */ /* Main program alias */ int sblat1_ () { main (); return 0; } blis-0.9.0/blastest/src/sblat2.c000066400000000000000000004457001422157504600164340ustar00rootroot00000000000000/* sblat2.f -- translated by f2c (version 20100827). You must link the resulting object file with libf2c: on Microsoft Windows system, link with libf2c.lib; on Linux or Unix systems, link with .../path/to/libf2c.a -lm or, if you install libf2c.a in a standard place, with -lf2c -lm -- in that order, at the end of the command line, as in cc *.o -lf2c -lm Source for libf2c is in /netlib/f2c/libf2c.zip, e.g., http://www.netlib.org/f2c/libf2c.zip */ #include "f2c.h" /* Common Block Declarations */ union { struct { integer infot, noutc; logical ok, lerr; } _1; struct { integer infot, nout; logical ok, lerr; } _2; } infoc_; #define infoc_1 (infoc_._1) #define infoc_2 (infoc_._2) struct { char srnamt[6]; } srnamc_; #define srnamc_1 srnamc_ /* Table of constant values */ static integer c__9 = 9; static integer c__1 = 1; static integer c__3 = 3; static integer c__8 = 8; static integer c__4 = 4; static integer c__65 = 65; static integer c__7 = 7; static integer c__2 = 2; static real c_b120 = 0.f; static real c_b128 = 1.f; static logical c_true = TRUE_; static integer c_n1 = -1; static integer c__0 = 0; static logical c_false = FALSE_; /* > \brief \b SBLAT2 */ /* =========== DOCUMENTATION =========== */ /* Online html documentation available at */ /* http://www.netlib.org/lapack/explore-html/ */ /* Definition: */ /* =========== */ /* PROGRAM SBLAT2 */ /* > \par Purpose: */ /* ============= */ /* > */ /* > \verbatim */ /* > */ /* > Test program for the REAL Level 2 Blas. */ /* > */ /* > The program must be driven by a short data file. The first 18 records */ /* > of the file are read using list-directed input, the last 16 records */ /* > are read using the format ( A6, L2 ). An annotated example of a data */ /* > file can be obtained by deleting the first 3 characters from the */ /* > following 34 lines: */ /* > 'sblat2.out' NAME OF SUMMARY OUTPUT FILE */ /* > 6 UNIT NUMBER OF SUMMARY FILE */ /* > 'SBLAT2.SNAP' NAME OF SNAPSHOT OUTPUT FILE */ /* > -1 UNIT NUMBER OF SNAPSHOT FILE (NOT USED IF .LT. 0) */ /* > F LOGICAL FLAG, T TO REWIND SNAPSHOT FILE AFTER EACH RECORD. */ /* > F LOGICAL FLAG, T TO STOP ON FAILURES. */ /* > T LOGICAL FLAG, T TO TEST ERROR EXITS. */ /* > 16.0 THRESHOLD VALUE OF TEST RATIO */ /* > 6 NUMBER OF VALUES OF N */ /* > 0 1 2 3 5 9 VALUES OF N */ /* > 4 NUMBER OF VALUES OF K */ /* > 0 1 2 4 VALUES OF K */ /* > 4 NUMBER OF VALUES OF INCX AND INCY */ /* > 1 2 -1 -2 VALUES OF INCX AND INCY */ /* > 3 NUMBER OF VALUES OF ALPHA */ /* > 0.0 1.0 0.7 VALUES OF ALPHA */ /* > 3 NUMBER OF VALUES OF BETA */ /* > 0.0 1.0 0.9 VALUES OF BETA */ /* > SGEMV T PUT F FOR NO TEST. SAME COLUMNS. */ /* > SGBMV T PUT F FOR NO TEST. SAME COLUMNS. */ /* > SSYMV T PUT F FOR NO TEST. SAME COLUMNS. */ /* > SSBMV T PUT F FOR NO TEST. SAME COLUMNS. */ /* > SSPMV T PUT F FOR NO TEST. SAME COLUMNS. */ /* > STRMV T PUT F FOR NO TEST. SAME COLUMNS. */ /* > STBMV T PUT F FOR NO TEST. SAME COLUMNS. */ /* > STPMV T PUT F FOR NO TEST. SAME COLUMNS. */ /* > STRSV T PUT F FOR NO TEST. SAME COLUMNS. */ /* > STBSV T PUT F FOR NO TEST. SAME COLUMNS. */ /* > STPSV T PUT F FOR NO TEST. SAME COLUMNS. */ /* > SGER T PUT F FOR NO TEST. SAME COLUMNS. */ /* > SSYR T PUT F FOR NO TEST. SAME COLUMNS. */ /* > SSPR T PUT F FOR NO TEST. SAME COLUMNS. */ /* > SSYR2 T PUT F FOR NO TEST. SAME COLUMNS. */ /* > SSPR2 T PUT F FOR NO TEST. SAME COLUMNS. */ /* > */ /* > Further Details */ /* > =============== */ /* > */ /* > See: */ /* > */ /* > Dongarra J. J., Du Croz J. J., Hammarling S. and Hanson R. J.. */ /* > An extended set of Fortran Basic Linear Algebra Subprograms. */ /* > */ /* > Technical Memoranda Nos. 41 (revision 3) and 81, Mathematics */ /* > and Computer Science Division, Argonne National Laboratory, */ /* > 9700 South Cass Avenue, Argonne, Illinois 60439, US. */ /* > */ /* > Or */ /* > */ /* > NAG Technical Reports TR3/87 and TR4/87, Numerical Algorithms */ /* > Group Ltd., NAG Central Office, 256 Banbury Road, Oxford */ /* > OX2 7DE, UK, and Numerical Algorithms Group Inc., 1101 31st */ /* > Street, Suite 100, Downers Grove, Illinois 60515-1263, USA. */ /* > */ /* > */ /* > -- Written on 10-August-1987. */ /* > Richard Hanson, Sandia National Labs. */ /* > Jeremy Du Croz, NAG Central Office. */ /* > */ /* > 10-9-00: Change STATUS='NEW' to 'UNKNOWN' so that the testers */ /* > can be run multiple times without deleting generated */ /* > output files (susan) */ /* > \endverbatim */ /* Authors: */ /* ======== */ /* > \author Univ. of Tennessee */ /* > \author Univ. of California Berkeley */ /* > \author Univ. of Colorado Denver */ /* > \author NAG Ltd. */ /* > \date April 2012 */ /* > \ingroup single_blas_testing */ /* ===================================================================== */ /* Main program */ int main(void) { /* Initialized data */ static char snames[6*16] = "SGEMV " "SGBMV " "SSYMV " "SSBMV " "SSPMV " "STRMV " "STBMV " "STPMV " "STRSV " "STBSV " "STPSV " "SGER " "SSYR " "SSPR " "SSYR2 " "SSPR2 "; /* Format strings */ static char fmt_9997[] = "(\002 NUMBER OF VALUES OF \002,a,\002 IS LESS " "THAN 1 OR GREATER \002,\002THAN \002,i2)"; static char fmt_9996[] = "(\002 VALUE OF N IS LESS THAN 0 OR GREATER THA" "N \002,i2)"; static char fmt_9995[] = "(\002 VALUE OF K IS LESS THAN 0\002)"; static char fmt_9994[] = "(\002 ABSOLUTE VALUE OF INCX OR INCY IS 0 OR G" "REATER THAN \002,i2)"; static char fmt_9993[] = "(\002 TESTS OF THE REAL LEVEL 2 BL" "AS\002,//\002 THE F\002,\002OLLOWING PARAMETER VALUES WILL BE US" "ED:\002)"; static char fmt_9992[] = "(\002 FOR N \002,9i6)"; static char fmt_9991[] = "(\002 FOR K \002,7i6)"; static char fmt_9990[] = "(\002 FOR INCX AND INCY \002,7i6)"; static char fmt_9989[] = "(\002 FOR ALPHA \002,7f6.1)"; static char fmt_9988[] = "(\002 FOR BETA \002,7f6.1)"; static char fmt_9980[] = "(\002 ERROR-EXITS WILL NOT BE TESTED\002)"; static char fmt_9999[] = "(\002 ROUTINES PASS COMPUTATIONAL TESTS IF TES" "T RATIO IS LES\002,\002S THAN\002,f8.2)"; static char fmt_9984[] = "(a6,l2)"; static char fmt_9986[] = "(\002 SUBPROGRAM NAME \002,a6,\002 NOT RECOGNI" "ZED\002,/\002 ******* T\002,\002ESTS ABANDONED *******\002)"; static char fmt_9998[] = "(\002 RELATIVE MACHINE PRECISION IS TAKEN TO" " BE\002,1p,e9.1)"; static char fmt_9985[] = "(\002 ERROR IN SMVCH - IN-LINE DOT PRODUCTS A" "RE BEING EVALU\002,\002ATED WRONGLY.\002,/\002 SMVCH WAS CALLED " "WITH TRANS = \002,a1,\002 AND RETURNED SAME = \002,l1,\002 AND E" "RR = \002,f12.3,\002.\002,/\002 THIS MAY BE DUE TO FAULTS IN THE" " ARITHMETIC OR THE COMPILER.\002,/\002 ******* TESTS ABANDONED *" "******\002)"; static char fmt_9983[] = "(1x,a6,\002 WAS NOT TESTED\002)"; static char fmt_9982[] = "(/\002 END OF TESTS\002)"; static char fmt_9981[] = "(/\002 ******* FATAL ERROR - TESTS ABANDONED *" "******\002)"; static char fmt_9987[] = "(\002 AMEND DATA FILE OR INCREASE ARRAY SIZES " "IN PROGRAM\002,/\002 ******* TESTS ABANDONED *******\002)"; /* System generated locals */ integer i__1, i__2, i__3; olist o__1; cllist cl__1; /* Builtin functions */ integer s_rsle(cilist *), do_lio(integer *, integer *, char *, ftnlen), e_rsle(void), f_open(olist *), s_wsfe(cilist *), do_fio(integer *, char *, ftnlen), e_wsfe(void), s_wsle(cilist *), e_wsle(void), s_rsfe(cilist *), e_rsfe(void), s_cmp(const char *, const char *, ftnlen, ftnlen); /* Subroutine */ int s_stop(char *, ftnlen); integer f_clos(cllist *); /* Subroutine */ int s_copy(char *, const char *, ftnlen, ftnlen); /* Local variables */ real a[4225] /* was [65][65] */, g[65]; integer i__, j, n; real x[65], y[65], z__[130], aa[4225]; integer kb[7]; real as[4225], xs[130], ys[130], yt[65], xx[130], yy[130], alf[7]; integer inc[7], nkb; real bet[7]; extern logical lse_(real *, real *, integer *); real eps, err; integer nalf, idim[9]; logical same; integer ninc, nbet, ntra; logical rewi; integer nout; extern /* Subroutine */ int schk1_(char *, real *, real *, integer *, integer *, logical *, logical *, logical *, integer *, integer *, integer *, integer *, integer *, real *, integer *, real *, integer *, integer *, integer *, integer *, real *, real *, real * , real *, real *, real *, real *, real *, real *, real *, real *, ftnlen), schk2_(char *, real *, real *, integer *, integer *, logical *, logical *, logical *, integer *, integer *, integer *, integer *, integer *, real *, integer *, real *, integer *, integer *, integer *, integer *, real *, real *, real *, real *, real *, real *, real *, real *, real *, real *, real *, ftnlen), schk3_(char *, real *, real *, integer *, integer *, logical *, logical *, logical *, integer *, integer *, integer *, integer *, integer *, integer *, integer *, integer *, real *, real *, real * , real *, real *, real *, real *, real *, real *, ftnlen), schk4_( char *, real *, real *, integer *, integer *, logical *, logical * , logical *, integer *, integer *, integer *, real *, integer *, integer *, integer *, integer *, real *, real *, real *, real *, real *, real *, real *, real *, real *, real *, real *, real *, ftnlen), schk5_(char *, real *, real *, integer *, integer *, logical *, logical *, logical *, integer *, integer *, integer *, real *, integer *, integer *, integer *, integer *, real *, real * , real *, real *, real *, real *, real *, real *, real *, real *, real *, real *, ftnlen), schk6_(char *, real *, real *, integer *, integer *, logical *, logical *, logical *, integer *, integer *, integer *, real *, integer *, integer *, integer *, integer *, real *, real *, real *, real *, real *, real *, real *, real *, real *, real *, real *, real *, ftnlen); logical fatal; extern /* Subroutine */ int schke_(integer *, char *, integer *, ftnlen); logical trace; integer nidim; extern /* Subroutine */ int smvch_(char *, integer *, integer *, real *, real *, integer *, real *, integer *, real *, real *, integer *, real *, real *, real *, real *, real *, logical *, integer *, logical *, ftnlen); char snaps[32], trans[1]; integer isnum; logical ltest[16], sfatal; char snamet[6]; real thresh; logical ltestt, tsterr; char summry[32]; extern real s_epsilon_(real *); /* Fortran I/O blocks */ static cilist io___2 = { 0, 5, 0, 0, 0 }; static cilist io___4 = { 0, 5, 0, 0, 0 }; static cilist io___6 = { 0, 5, 0, 0, 0 }; static cilist io___8 = { 0, 5, 0, 0, 0 }; static cilist io___11 = { 0, 5, 0, 0, 0 }; static cilist io___13 = { 0, 5, 0, 0, 0 }; static cilist io___15 = { 0, 5, 0, 0, 0 }; static cilist io___17 = { 0, 5, 0, 0, 0 }; static cilist io___19 = { 0, 5, 0, 0, 0 }; static cilist io___21 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___22 = { 0, 5, 0, 0, 0 }; static cilist io___25 = { 0, 0, 0, fmt_9996, 0 }; static cilist io___26 = { 0, 5, 0, 0, 0 }; static cilist io___28 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___29 = { 0, 5, 0, 0, 0 }; static cilist io___31 = { 0, 0, 0, fmt_9995, 0 }; static cilist io___32 = { 0, 5, 0, 0, 0 }; static cilist io___34 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___35 = { 0, 5, 0, 0, 0 }; static cilist io___37 = { 0, 0, 0, fmt_9994, 0 }; static cilist io___38 = { 0, 5, 0, 0, 0 }; static cilist io___40 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___41 = { 0, 5, 0, 0, 0 }; static cilist io___43 = { 0, 5, 0, 0, 0 }; static cilist io___45 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___46 = { 0, 5, 0, 0, 0 }; static cilist io___48 = { 0, 0, 0, fmt_9993, 0 }; static cilist io___49 = { 0, 0, 0, fmt_9992, 0 }; static cilist io___50 = { 0, 0, 0, fmt_9991, 0 }; static cilist io___51 = { 0, 0, 0, fmt_9990, 0 }; static cilist io___52 = { 0, 0, 0, fmt_9989, 0 }; static cilist io___53 = { 0, 0, 0, fmt_9988, 0 }; static cilist io___54 = { 0, 0, 0, 0, 0 }; static cilist io___55 = { 0, 0, 0, fmt_9980, 0 }; static cilist io___56 = { 0, 0, 0, 0, 0 }; static cilist io___57 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___58 = { 0, 0, 0, 0, 0 }; static cilist io___60 = { 0, 5, 1, fmt_9984, 0 }; static cilist io___63 = { 0, 0, 0, fmt_9986, 0 }; static cilist io___65 = { 0, 0, 0, fmt_9998, 0 }; static cilist io___78 = { 0, 0, 0, fmt_9985, 0 }; static cilist io___79 = { 0, 0, 0, fmt_9985, 0 }; static cilist io___81 = { 0, 0, 0, 0, 0 }; static cilist io___82 = { 0, 0, 0, fmt_9983, 0 }; static cilist io___83 = { 0, 0, 0, 0, 0 }; static cilist io___90 = { 0, 0, 0, fmt_9982, 0 }; static cilist io___91 = { 0, 0, 0, fmt_9981, 0 }; static cilist io___92 = { 0, 0, 0, fmt_9987, 0 }; /* -- Reference BLAS test routine (version 3.4.1) -- */ /* -- Reference BLAS is a software package provided by Univ. of Tennessee, -- */ /* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- */ /* April 2012 */ /* ===================================================================== */ /* .. Parameters .. */ /* .. Local Scalars .. */ /* .. Local Arrays .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. Scalars in Common .. */ /* .. Common blocks .. */ /* .. Data statements .. */ /* .. Executable Statements .. */ /* Read name and unit number for summary output file and open file. */ s_rsle(&io___2); do_lio(&c__9, &c__1, summry, (ftnlen)32); e_rsle(); s_rsle(&io___4); do_lio(&c__3, &c__1, (char *)&nout, (ftnlen)sizeof(integer)); e_rsle(); o__1.oerr = 0; o__1.ounit = nout; o__1.ofnmlen = 32; o__1.ofnm = summry; o__1.orl = 0; o__1.osta = "UNKNOWN"; o__1.oacc = 0; o__1.ofm = 0; o__1.oblnk = 0; f_open(&o__1); infoc_1.noutc = nout; /* Read name and unit number for snapshot output file and open file. */ s_rsle(&io___6); do_lio(&c__9, &c__1, snaps, (ftnlen)32); e_rsle(); s_rsle(&io___8); do_lio(&c__3, &c__1, (char *)&ntra, (ftnlen)sizeof(integer)); e_rsle(); trace = ntra >= 0; if (trace) { o__1.oerr = 0; o__1.ounit = ntra; o__1.ofnmlen = 32; o__1.ofnm = snaps; o__1.orl = 0; o__1.osta = "UNKNOWN"; o__1.oacc = 0; o__1.ofm = 0; o__1.oblnk = 0; f_open(&o__1); } /* Read the flag that directs rewinding of the snapshot file. */ s_rsle(&io___11); do_lio(&c__8, &c__1, (char *)&rewi, (ftnlen)sizeof(logical)); e_rsle(); rewi = rewi && trace; /* Read the flag that directs stopping on any failure. */ s_rsle(&io___13); do_lio(&c__8, &c__1, (char *)&sfatal, (ftnlen)sizeof(logical)); e_rsle(); /* Read the flag that indicates whether error exits are to be tested. */ s_rsle(&io___15); do_lio(&c__8, &c__1, (char *)&tsterr, (ftnlen)sizeof(logical)); e_rsle(); /* Read the threshold value of the test ratio */ s_rsle(&io___17); do_lio(&c__4, &c__1, (char *)&thresh, (ftnlen)sizeof(real)); e_rsle(); /* Read and check the parameter values for the tests. */ /* Values of N */ s_rsle(&io___19); do_lio(&c__3, &c__1, (char *)&nidim, (ftnlen)sizeof(integer)); e_rsle(); if (nidim < 1 || nidim > 9) { io___21.ciunit = nout; s_wsfe(&io___21); do_fio(&c__1, "N", (ftnlen)1); do_fio(&c__1, (char *)&c__9, (ftnlen)sizeof(integer)); e_wsfe(); goto L230; } s_rsle(&io___22); i__1 = nidim; for (i__ = 1; i__ <= i__1; ++i__) { do_lio(&c__3, &c__1, (char *)&idim[i__ - 1], (ftnlen)sizeof(integer)); } e_rsle(); i__1 = nidim; for (i__ = 1; i__ <= i__1; ++i__) { if (idim[i__ - 1] < 0 || idim[i__ - 1] > 65) { io___25.ciunit = nout; s_wsfe(&io___25); do_fio(&c__1, (char *)&c__65, (ftnlen)sizeof(integer)); e_wsfe(); goto L230; } /* L10: */ } /* Values of K */ s_rsle(&io___26); do_lio(&c__3, &c__1, (char *)&nkb, (ftnlen)sizeof(integer)); e_rsle(); if (nkb < 1 || nkb > 7) { io___28.ciunit = nout; s_wsfe(&io___28); do_fio(&c__1, "K", (ftnlen)1); do_fio(&c__1, (char *)&c__7, (ftnlen)sizeof(integer)); e_wsfe(); goto L230; } s_rsle(&io___29); i__1 = nkb; for (i__ = 1; i__ <= i__1; ++i__) { do_lio(&c__3, &c__1, (char *)&kb[i__ - 1], (ftnlen)sizeof(integer)); } e_rsle(); i__1 = nkb; for (i__ = 1; i__ <= i__1; ++i__) { if (kb[i__ - 1] < 0) { io___31.ciunit = nout; s_wsfe(&io___31); e_wsfe(); goto L230; } /* L20: */ } /* Values of INCX and INCY */ s_rsle(&io___32); do_lio(&c__3, &c__1, (char *)&ninc, (ftnlen)sizeof(integer)); e_rsle(); if (ninc < 1 || ninc > 7) { io___34.ciunit = nout; s_wsfe(&io___34); do_fio(&c__1, "INCX AND INCY", (ftnlen)13); do_fio(&c__1, (char *)&c__7, (ftnlen)sizeof(integer)); e_wsfe(); goto L230; } s_rsle(&io___35); i__1 = ninc; for (i__ = 1; i__ <= i__1; ++i__) { do_lio(&c__3, &c__1, (char *)&inc[i__ - 1], (ftnlen)sizeof(integer)); } e_rsle(); i__1 = ninc; for (i__ = 1; i__ <= i__1; ++i__) { if (inc[i__ - 1] == 0 || (i__2 = inc[i__ - 1], abs(i__2)) > 2) { io___37.ciunit = nout; s_wsfe(&io___37); do_fio(&c__1, (char *)&c__2, (ftnlen)sizeof(integer)); e_wsfe(); goto L230; } /* L30: */ } /* Values of ALPHA */ s_rsle(&io___38); do_lio(&c__3, &c__1, (char *)&nalf, (ftnlen)sizeof(integer)); e_rsle(); if (nalf < 1 || nalf > 7) { io___40.ciunit = nout; s_wsfe(&io___40); do_fio(&c__1, "ALPHA", (ftnlen)5); do_fio(&c__1, (char *)&c__7, (ftnlen)sizeof(integer)); e_wsfe(); goto L230; } s_rsle(&io___41); i__1 = nalf; for (i__ = 1; i__ <= i__1; ++i__) { do_lio(&c__4, &c__1, (char *)&alf[i__ - 1], (ftnlen)sizeof(real)); } e_rsle(); /* Values of BETA */ s_rsle(&io___43); do_lio(&c__3, &c__1, (char *)&nbet, (ftnlen)sizeof(integer)); e_rsle(); if (nbet < 1 || nbet > 7) { io___45.ciunit = nout; s_wsfe(&io___45); do_fio(&c__1, "BETA", (ftnlen)4); do_fio(&c__1, (char *)&c__7, (ftnlen)sizeof(integer)); e_wsfe(); goto L230; } s_rsle(&io___46); i__1 = nbet; for (i__ = 1; i__ <= i__1; ++i__) { do_lio(&c__4, &c__1, (char *)&bet[i__ - 1], (ftnlen)sizeof(real)); } e_rsle(); /* Report values of parameters. */ io___48.ciunit = nout; s_wsfe(&io___48); e_wsfe(); io___49.ciunit = nout; s_wsfe(&io___49); i__1 = nidim; for (i__ = 1; i__ <= i__1; ++i__) { do_fio(&c__1, (char *)&idim[i__ - 1], (ftnlen)sizeof(integer)); } e_wsfe(); io___50.ciunit = nout; s_wsfe(&io___50); i__1 = nkb; for (i__ = 1; i__ <= i__1; ++i__) { do_fio(&c__1, (char *)&kb[i__ - 1], (ftnlen)sizeof(integer)); } e_wsfe(); io___51.ciunit = nout; s_wsfe(&io___51); i__1 = ninc; for (i__ = 1; i__ <= i__1; ++i__) { do_fio(&c__1, (char *)&inc[i__ - 1], (ftnlen)sizeof(integer)); } e_wsfe(); io___52.ciunit = nout; s_wsfe(&io___52); i__1 = nalf; for (i__ = 1; i__ <= i__1; ++i__) { do_fio(&c__1, (char *)&alf[i__ - 1], (ftnlen)sizeof(real)); } e_wsfe(); io___53.ciunit = nout; s_wsfe(&io___53); i__1 = nbet; for (i__ = 1; i__ <= i__1; ++i__) { do_fio(&c__1, (char *)&bet[i__ - 1], (ftnlen)sizeof(real)); } e_wsfe(); if (! tsterr) { io___54.ciunit = nout; s_wsle(&io___54); e_wsle(); io___55.ciunit = nout; s_wsfe(&io___55); e_wsfe(); } io___56.ciunit = nout; s_wsle(&io___56); e_wsle(); io___57.ciunit = nout; s_wsfe(&io___57); do_fio(&c__1, (char *)&thresh, (ftnlen)sizeof(real)); e_wsfe(); io___58.ciunit = nout; s_wsle(&io___58); e_wsle(); /* Read names of subroutines and flags which indicate */ /* whether they are to be tested. */ for (i__ = 1; i__ <= 16; ++i__) { ltest[i__ - 1] = FALSE_; /* L40: */ } L50: i__1 = s_rsfe(&io___60); if (i__1 != 0) { goto L80; } i__1 = do_fio(&c__1, snamet, (ftnlen)6); if (i__1 != 0) { goto L80; } i__1 = do_fio(&c__1, (char *)<estt, (ftnlen)sizeof(logical)); if (i__1 != 0) { goto L80; } i__1 = e_rsfe(); if (i__1 != 0) { goto L80; } for (i__ = 1; i__ <= 16; ++i__) { if (s_cmp(snamet, snames + (i__ - 1) * 6, (ftnlen)6, (ftnlen)6) == 0) { goto L70; } /* L60: */ } io___63.ciunit = nout; s_wsfe(&io___63); do_fio(&c__1, snamet, (ftnlen)6); e_wsfe(); s_stop("", (ftnlen)0); L70: ltest[i__ - 1] = ltestt; goto L50; L80: cl__1.cerr = 0; cl__1.cunit = 5; cl__1.csta = 0; f_clos(&cl__1); /* Compute EPS (the machine precision). */ eps = s_epsilon_(&c_b120); io___65.ciunit = nout; s_wsfe(&io___65); do_fio(&c__1, (char *)&eps, (ftnlen)sizeof(real)); e_wsfe(); /* Check the reliability of SMVCH using exact data. */ n = 32; i__1 = n; for (j = 1; j <= i__1; ++j) { i__2 = n; for (i__ = 1; i__ <= i__2; ++i__) { /* Computing MAX */ i__3 = i__ - j + 1; a[i__ + j * 65 - 66] = (real) max(i__3,0); /* L110: */ } x[j - 1] = (real) j; y[j - 1] = 0.f; /* L120: */ } i__1 = n; for (j = 1; j <= i__1; ++j) { yy[j - 1] = (real) (j * ((j + 1) * j) / 2 - (j + 1) * j * (j - 1) / 3) ; /* L130: */ } /* YY holds the exact result. On exit from SMVCH YT holds */ /* the result computed by SMVCH. */ *(unsigned char *)trans = 'N'; smvch_(trans, &n, &n, &c_b128, a, &c__65, x, &c__1, &c_b120, y, &c__1, yt, g, yy, &eps, &err, &fatal, &nout, &c_true, (ftnlen)1); same = lse_(yy, yt, &n); if (! same || err != 0.f) { io___78.ciunit = nout; s_wsfe(&io___78); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, (char *)&same, (ftnlen)sizeof(logical)); do_fio(&c__1, (char *)&err, (ftnlen)sizeof(real)); e_wsfe(); s_stop("", (ftnlen)0); } *(unsigned char *)trans = 'T'; smvch_(trans, &n, &n, &c_b128, a, &c__65, x, &c_n1, &c_b120, y, &c_n1, yt, g, yy, &eps, &err, &fatal, &nout, &c_true, (ftnlen)1); same = lse_(yy, yt, &n); if (! same || err != 0.f) { io___79.ciunit = nout; s_wsfe(&io___79); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, (char *)&same, (ftnlen)sizeof(logical)); do_fio(&c__1, (char *)&err, (ftnlen)sizeof(real)); e_wsfe(); s_stop("", (ftnlen)0); } /* Test each subroutine in turn. */ for (isnum = 1; isnum <= 16; ++isnum) { io___81.ciunit = nout; s_wsle(&io___81); e_wsle(); if (! ltest[isnum - 1]) { /* Subprogram is not to be tested. */ io___82.ciunit = nout; s_wsfe(&io___82); do_fio(&c__1, snames + (isnum - 1) * 6, (ftnlen)6); e_wsfe(); } else { s_copy(srnamc_1.srnamt, snames + (isnum - 1) * 6, (ftnlen)6, ( ftnlen)6); /* Test error exits. */ if (tsterr) { schke_(&isnum, snames + (isnum - 1) * 6, &nout, (ftnlen)6); io___83.ciunit = nout; s_wsle(&io___83); e_wsle(); } /* Test computations. */ infoc_1.infot = 0; infoc_1.ok = TRUE_; fatal = FALSE_; switch (isnum) { case 1: goto L140; case 2: goto L140; case 3: goto L150; case 4: goto L150; case 5: goto L150; case 6: goto L160; case 7: goto L160; case 8: goto L160; case 9: goto L160; case 10: goto L160; case 11: goto L160; case 12: goto L170; case 13: goto L180; case 14: goto L180; case 15: goto L190; case 16: goto L190; } /* Test SGEMV, 01, and SGBMV, 02. */ L140: schk1_(snames + (isnum - 1) * 6, &eps, &thresh, &nout, &ntra, & trace, &rewi, &fatal, &nidim, idim, &nkb, kb, &nalf, alf, &nbet, bet, &ninc, inc, &c__65, &c__2, a, aa, as, x, xx, xs, y, yy, ys, yt, g, (ftnlen)6); goto L200; /* Test SSYMV, 03, SSBMV, 04, and SSPMV, 05. */ L150: schk2_(snames + (isnum - 1) * 6, &eps, &thresh, &nout, &ntra, & trace, &rewi, &fatal, &nidim, idim, &nkb, kb, &nalf, alf, &nbet, bet, &ninc, inc, &c__65, &c__2, a, aa, as, x, xx, xs, y, yy, ys, yt, g, (ftnlen)6); goto L200; /* Test STRMV, 06, STBMV, 07, STPMV, 08, */ /* STRSV, 09, STBSV, 10, and STPSV, 11. */ L160: schk3_(snames + (isnum - 1) * 6, &eps, &thresh, &nout, &ntra, & trace, &rewi, &fatal, &nidim, idim, &nkb, kb, &ninc, inc, &c__65, &c__2, a, aa, as, y, yy, ys, yt, g, z__, (ftnlen) 6); goto L200; /* Test SGER, 12. */ L170: schk4_(snames + (isnum - 1) * 6, &eps, &thresh, &nout, &ntra, & trace, &rewi, &fatal, &nidim, idim, &nalf, alf, &ninc, inc, &c__65, &c__2, a, aa, as, x, xx, xs, y, yy, ys, yt, g, z__, (ftnlen)6); goto L200; /* Test SSYR, 13, and SSPR, 14. */ L180: schk5_(snames + (isnum - 1) * 6, &eps, &thresh, &nout, &ntra, & trace, &rewi, &fatal, &nidim, idim, &nalf, alf, &ninc, inc, &c__65, &c__2, a, aa, as, x, xx, xs, y, yy, ys, yt, g, z__, (ftnlen)6); goto L200; /* Test SSYR2, 15, and SSPR2, 16. */ L190: schk6_(snames + (isnum - 1) * 6, &eps, &thresh, &nout, &ntra, & trace, &rewi, &fatal, &nidim, idim, &nalf, alf, &ninc, inc, &c__65, &c__2, a, aa, as, x, xx, xs, y, yy, ys, yt, g, z__, (ftnlen)6); L200: if (fatal && sfatal) { goto L220; } } /* L210: */ } io___90.ciunit = nout; s_wsfe(&io___90); e_wsfe(); goto L240; L220: io___91.ciunit = nout; s_wsfe(&io___91); e_wsfe(); goto L240; L230: io___92.ciunit = nout; s_wsfe(&io___92); e_wsfe(); L240: if (trace) { cl__1.cerr = 0; cl__1.cunit = ntra; cl__1.csta = 0; f_clos(&cl__1); } cl__1.cerr = 0; cl__1.cunit = nout; cl__1.csta = 0; f_clos(&cl__1); s_stop("", (ftnlen)0); /* End of SBLAT2. */ return 0; } /* main */ /* Subroutine */ int schk1_(char *sname, real *eps, real *thresh, integer * nout, integer *ntra, logical *trace, logical *rewi, logical *fatal, integer *nidim, integer *idim, integer *nkb, integer *kb, integer * nalf, real *alf, integer *nbet, real *bet, integer *ninc, integer * inc, integer *nmax, integer *incmax, real *a, real *aa, real *as, real *x, real *xx, real *xs, real *y, real *yy, real *ys, real *yt, real *g, ftnlen sname_len) { /* Initialized data */ static char ich[3] = "NTC"; /* Format strings */ static char fmt_9994[] = "(1x,i6,\002: \002,a6,\002('\002,a1,\002',\002," "2(i3,\002,\002),f4.1,\002, A,\002,i3,\002, X,\002,i2,\002,\002,f" "4.1,\002, Y,\002,i2,\002) .\002)"; static char fmt_9995[] = "(1x,i6,\002: \002,a6,\002('\002,a1,\002',\002," "4(i3,\002,\002),f4.1,\002, A,\002,i3,\002, X,\002,i2,\002,\002,f" "4.1,\002, Y,\002,i2,\002) .\002)"; static char fmt_9993[] = "(\002 ******* FATAL ERROR - ERROR-EXIT TAKEN O" "N VALID CALL *\002,\002******\002)"; static char fmt_9998[] = "(\002 ******* FATAL ERROR - PARAMETER NUMBER" " \002,i2,\002 WAS CH\002,\002ANGED INCORRECTLY *******\002)"; static char fmt_9999[] = "(\002 \002,a6,\002 PASSED THE COMPUTATIONAL TE" "STS (\002,i6,\002 CALL\002,\002S)\002)"; static char fmt_9997[] = "(\002 \002,a6,\002 COMPLETED THE COMPUTATIONAL" " TESTS (\002,i6,\002 C\002,\002ALLS)\002,/\002 ******* BUT WITH " "MAXIMUM TEST RATIO\002,f8.2,\002 - SUSPECT *******\002)"; static char fmt_9996[] = "(\002 ******* \002,a6,\002 FAILED ON CALL NUMB" "ER:\002)"; /* System generated locals */ integer a_dim1, a_offset, i__1, i__2, i__3, i__4, i__5, i__6, i__7, i__8; alist al__1; /* Builtin functions */ integer s_wsfe(cilist *), do_fio(integer *, char *, ftnlen), e_wsfe(void), f_rew(alist *); /* Local variables */ integer i__, m, n, ia, ib, ic, nc, nd, im, in, kl, ml, nk, nl, ku, ix, iy, ms, lx, ly, ns, laa, lda; real als, bls; extern logical lse_(real *, real *, integer *); real err; integer iku, kls, kus; real beta; integer ldas; logical same; integer incx, incy; logical full, tran, null; real alpha; logical isame[13]; extern /* Subroutine */ int smake_(char *, char *, char *, integer *, integer *, real *, integer *, real *, integer *, integer *, integer *, logical *, real *, ftnlen, ftnlen, ftnlen); integer nargs; extern /* Subroutine */ int sgbmv_(char *, integer *, integer *, integer * , integer *, real *, real *, integer *, real *, integer *, real *, real *, integer *, ftnlen), smvch_(char *, integer *, integer *, real *, real *, integer *, real *, integer *, real *, real *, integer *, real *, real *, real *, real *, real *, logical *, integer *, logical *, ftnlen), sgemv_(char *, integer *, integer * , real *, real *, integer *, real *, integer *, real *, real *, integer *, ftnlen); logical reset; integer incxs, incys; char trans[1]; logical banded; real errmax; extern logical lseres_(char *, char *, integer *, integer *, real *, real *, integer *, ftnlen, ftnlen); real transl; char transs[1]; /* Fortran I/O blocks */ static cilist io___139 = { 0, 0, 0, fmt_9994, 0 }; static cilist io___140 = { 0, 0, 0, fmt_9995, 0 }; static cilist io___141 = { 0, 0, 0, fmt_9993, 0 }; static cilist io___144 = { 0, 0, 0, fmt_9998, 0 }; static cilist io___146 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___147 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___148 = { 0, 0, 0, fmt_9996, 0 }; static cilist io___149 = { 0, 0, 0, fmt_9994, 0 }; static cilist io___150 = { 0, 0, 0, fmt_9995, 0 }; /* Tests SGEMV and SGBMV. */ /* Auxiliary routine for test program for Level 2 Blas. */ /* -- Written on 10-August-1987. */ /* Richard Hanson, Sandia National Labs. */ /* Jeremy Du Croz, NAG Central Office. */ /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Scalars .. */ /* .. Local Arrays .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. Scalars in Common .. */ /* .. Common blocks .. */ /* .. Data statements .. */ /* Parameter adjustments */ --idim; --kb; --alf; --bet; --inc; --g; --yt; --y; --x; --as; --aa; a_dim1 = *nmax; a_offset = 1 + a_dim1; a -= a_offset; --ys; --yy; --xs; --xx; /* Function Body */ /* .. Executable Statements .. */ full = *(unsigned char *)&sname[2] == 'E'; banded = *(unsigned char *)&sname[2] == 'B'; /* Define the number of arguments. */ if (full) { nargs = 11; } else if (banded) { nargs = 13; } nc = 0; reset = TRUE_; errmax = 0.f; i__1 = *nidim; for (in = 1; in <= i__1; ++in) { n = idim[in]; nd = n / 2 + 1; for (im = 1; im <= 2; ++im) { if (im == 1) { /* Computing MAX */ i__2 = n - nd; m = max(i__2,0); } if (im == 2) { /* Computing MIN */ i__2 = n + nd; m = min(i__2,*nmax); } if (banded) { nk = *nkb; } else { nk = 1; } i__2 = nk; for (iku = 1; iku <= i__2; ++iku) { if (banded) { ku = kb[iku]; /* Computing MAX */ i__3 = ku - 1; kl = max(i__3,0); } else { ku = n - 1; kl = m - 1; } /* Set LDA to 1 more than minimum value if room. */ if (banded) { lda = kl + ku + 1; } else { lda = m; } if (lda < *nmax) { ++lda; } /* Skip tests if not enough room. */ if (lda > *nmax) { goto L100; } laa = lda * n; null = n <= 0 || m <= 0; /* Generate the matrix A. */ transl = 0.f; smake_(sname + 1, " ", " ", &m, &n, &a[a_offset], nmax, &aa[1] , &lda, &kl, &ku, &reset, &transl, (ftnlen)2, (ftnlen) 1, (ftnlen)1); for (ic = 1; ic <= 3; ++ic) { *(unsigned char *)trans = *(unsigned char *)&ich[ic - 1]; tran = *(unsigned char *)trans == 'T' || *(unsigned char * )trans == 'C'; if (tran) { ml = n; nl = m; } else { ml = m; nl = n; } i__3 = *ninc; for (ix = 1; ix <= i__3; ++ix) { incx = inc[ix]; lx = abs(incx) * nl; /* Generate the vector X. */ transl = .5f; i__4 = abs(incx); i__5 = nl - 1; smake_("GE", " ", " ", &c__1, &nl, &x[1], &c__1, &xx[ 1], &i__4, &c__0, &i__5, &reset, &transl, ( ftnlen)2, (ftnlen)1, (ftnlen)1); if (nl > 1) { x[nl / 2] = 0.f; xx[abs(incx) * (nl / 2 - 1) + 1] = 0.f; } i__4 = *ninc; for (iy = 1; iy <= i__4; ++iy) { incy = inc[iy]; ly = abs(incy) * ml; i__5 = *nalf; for (ia = 1; ia <= i__5; ++ia) { alpha = alf[ia]; i__6 = *nbet; for (ib = 1; ib <= i__6; ++ib) { beta = bet[ib]; /* Generate the vector Y. */ transl = 0.f; i__7 = abs(incy); i__8 = ml - 1; smake_("GE", " ", " ", &c__1, &ml, &y[1], &c__1, &yy[1], &i__7, &c__0, & i__8, &reset, &transl, (ftnlen)2, (ftnlen)1, (ftnlen)1); ++nc; /* Save every datum before calling the */ /* subroutine. */ *(unsigned char *)transs = *(unsigned char *)trans; ms = m; ns = n; kls = kl; kus = ku; als = alpha; i__7 = laa; for (i__ = 1; i__ <= i__7; ++i__) { as[i__] = aa[i__]; /* L10: */ } ldas = lda; i__7 = lx; for (i__ = 1; i__ <= i__7; ++i__) { xs[i__] = xx[i__]; /* L20: */ } incxs = incx; bls = beta; i__7 = ly; for (i__ = 1; i__ <= i__7; ++i__) { ys[i__] = yy[i__]; /* L30: */ } incys = incy; /* Call the subroutine. */ if (full) { if (*trace) { io___139.ciunit = *ntra; s_wsfe(&io___139); do_fio(&c__1, (char *)&nc, ( ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, (char *)&m, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&n, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&alpha, ( ftnlen)sizeof(real)); do_fio(&c__1, (char *)&lda, ( ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&incx, ( ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&beta, ( ftnlen)sizeof(real)); do_fio(&c__1, (char *)&incy, ( ftnlen)sizeof(integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } sgemv_(trans, &m, &n, &alpha, &aa[1], &lda, &xx[1], &incx, &beta, & yy[1], &incy, (ftnlen)1); } else if (banded) { if (*trace) { io___140.ciunit = *ntra; s_wsfe(&io___140); do_fio(&c__1, (char *)&nc, ( ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, (char *)&m, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&n, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&kl, ( ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&ku, ( ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&alpha, ( ftnlen)sizeof(real)); do_fio(&c__1, (char *)&lda, ( ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&incx, ( ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&beta, ( ftnlen)sizeof(real)); do_fio(&c__1, (char *)&incy, ( ftnlen)sizeof(integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } sgbmv_(trans, &m, &n, &kl, &ku, & alpha, &aa[1], &lda, &xx[1], & incx, &beta, &yy[1], &incy, ( ftnlen)1); } /* Check if error-exit was taken incorrectly. */ if (! infoc_1.ok) { io___141.ciunit = *nout; s_wsfe(&io___141); e_wsfe(); *fatal = TRUE_; goto L130; } /* See what data changed inside subroutines. */ isame[0] = *(unsigned char *)trans == *( unsigned char *)transs; isame[1] = ms == m; isame[2] = ns == n; if (full) { isame[3] = als == alpha; isame[4] = lse_(&as[1], &aa[1], &laa); isame[5] = ldas == lda; isame[6] = lse_(&xs[1], &xx[1], &lx); isame[7] = incxs == incx; isame[8] = bls == beta; if (null) { isame[9] = lse_(&ys[1], &yy[1], & ly); } else { i__7 = abs(incy); isame[9] = lseres_("GE", " ", & c__1, &ml, &ys[1], &yy[1], &i__7, (ftnlen)2, ( ftnlen)1); } isame[10] = incys == incy; } else if (banded) { isame[3] = kls == kl; isame[4] = kus == ku; isame[5] = als == alpha; isame[6] = lse_(&as[1], &aa[1], &laa); isame[7] = ldas == lda; isame[8] = lse_(&xs[1], &xx[1], &lx); isame[9] = incxs == incx; isame[10] = bls == beta; if (null) { isame[11] = lse_(&ys[1], &yy[1], & ly); } else { i__7 = abs(incy); isame[11] = lseres_("GE", " ", & c__1, &ml, &ys[1], &yy[1], &i__7, (ftnlen)2, ( ftnlen)1); } isame[12] = incys == incy; } /* If data was incorrectly changed, report */ /* and return. */ same = TRUE_; i__7 = nargs; for (i__ = 1; i__ <= i__7; ++i__) { same = same && isame[i__ - 1]; if (! isame[i__ - 1]) { io___144.ciunit = *nout; s_wsfe(&io___144); do_fio(&c__1, (char *)&i__, ( ftnlen)sizeof(integer)); e_wsfe(); } /* L40: */ } if (! same) { *fatal = TRUE_; goto L130; } if (! null) { /* Check the result. */ smvch_(trans, &m, &n, &alpha, &a[ a_offset], nmax, &x[1], &incx, &beta, &y[1], &incy, &yt[1], &g[1], &yy[1], eps, &err, fatal, nout, &c_true, (ftnlen) 1); errmax = max(errmax,err); /* If got really bad answer, report and */ /* return. */ if (*fatal) { goto L130; } } else { /* Avoid repeating tests with M.le.0 or */ /* N.le.0. */ goto L110; } /* L50: */ } /* L60: */ } /* L70: */ } /* L80: */ } /* L90: */ } L100: ; } L110: ; } /* L120: */ } /* Report result. */ if (errmax < *thresh) { io___146.ciunit = *nout; s_wsfe(&io___146); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); e_wsfe(); } else { io___147.ciunit = *nout; s_wsfe(&io___147); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&errmax, (ftnlen)sizeof(real)); e_wsfe(); } goto L140; L130: io___148.ciunit = *nout; s_wsfe(&io___148); do_fio(&c__1, sname, (ftnlen)6); e_wsfe(); if (full) { io___149.ciunit = *nout; s_wsfe(&io___149); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, (char *)&m, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&alpha, (ftnlen)sizeof(real)); do_fio(&c__1, (char *)&lda, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&incx, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&beta, (ftnlen)sizeof(real)); do_fio(&c__1, (char *)&incy, (ftnlen)sizeof(integer)); e_wsfe(); } else if (banded) { io___150.ciunit = *nout; s_wsfe(&io___150); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, (char *)&m, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&kl, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&ku, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&alpha, (ftnlen)sizeof(real)); do_fio(&c__1, (char *)&lda, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&incx, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&beta, (ftnlen)sizeof(real)); do_fio(&c__1, (char *)&incy, (ftnlen)sizeof(integer)); e_wsfe(); } L140: return 0; /* End of SCHK1. */ } /* schk1_ */ /* Subroutine */ int schk2_(char *sname, real *eps, real *thresh, integer * nout, integer *ntra, logical *trace, logical *rewi, logical *fatal, integer *nidim, integer *idim, integer *nkb, integer *kb, integer * nalf, real *alf, integer *nbet, real *bet, integer *ninc, integer * inc, integer *nmax, integer *incmax, real *a, real *aa, real *as, real *x, real *xx, real *xs, real *y, real *yy, real *ys, real *yt, real *g, ftnlen sname_len) { /* Initialized data */ static char ich[2] = "UL"; /* Format strings */ static char fmt_9993[] = "(1x,i6,\002: \002,a6,\002('\002,a1,\002',\002," "i3,\002,\002,f4.1,\002, A,\002,i3,\002, X,\002,i2,\002,\002,f4.1," "\002, Y,\002,i2,\002) .\002)"; static char fmt_9994[] = "(1x,i6,\002: \002,a6,\002('\002,a1,\002',\002," "2(i3,\002,\002),f4.1,\002, A,\002,i3,\002, X,\002,i2,\002,\002,f" "4.1,\002, Y,\002,i2,\002) .\002)"; static char fmt_9995[] = "(1x,i6,\002: \002,a6,\002('\002,a1,\002',\002," "i3,\002,\002,f4.1,\002, AP\002,\002, X,\002,i2,\002,\002,f4.1" ",\002, Y,\002,i2,\002) .\002)"; static char fmt_9992[] = "(\002 ******* FATAL ERROR - ERROR-EXIT TAKEN O" "N VALID CALL *\002,\002******\002)"; static char fmt_9998[] = "(\002 ******* FATAL ERROR - PARAMETER NUMBER" " \002,i2,\002 WAS CH\002,\002ANGED INCORRECTLY *******\002)"; static char fmt_9999[] = "(\002 \002,a6,\002 PASSED THE COMPUTATIONAL TE" "STS (\002,i6,\002 CALL\002,\002S)\002)"; static char fmt_9997[] = "(\002 \002,a6,\002 COMPLETED THE COMPUTATIONAL" " TESTS (\002,i6,\002 C\002,\002ALLS)\002,/\002 ******* BUT WITH " "MAXIMUM TEST RATIO\002,f8.2,\002 - SUSPECT *******\002)"; static char fmt_9996[] = "(\002 ******* \002,a6,\002 FAILED ON CALL NUMB" "ER:\002)"; /* System generated locals */ integer a_dim1, a_offset, i__1, i__2, i__3, i__4, i__5, i__6, i__7, i__8; alist al__1; /* Builtin functions */ integer s_wsfe(cilist *), do_fio(integer *, char *, ftnlen), e_wsfe(void), f_rew(alist *); /* Local variables */ integer i__, k, n, ia, ib, ic, nc, ik, in, nk, ks, ix, iy, ns, lx, ly, laa, lda; real als, bls; extern logical lse_(real *, real *, integer *); real err, beta; integer ldas; logical same; integer incx, incy; logical full, null; char uplo[1]; real alpha; logical isame[13]; extern /* Subroutine */ int smake_(char *, char *, char *, integer *, integer *, real *, integer *, real *, integer *, integer *, integer *, logical *, real *, ftnlen, ftnlen, ftnlen); integer nargs; extern /* Subroutine */ int smvch_(char *, integer *, integer *, real *, real *, integer *, real *, integer *, real *, real *, integer *, real *, real *, real *, real *, real *, logical *, integer *, logical *, ftnlen); logical reset; integer incxs, incys; extern /* Subroutine */ int ssbmv_(char *, integer *, integer *, real *, real *, integer *, real *, integer *, real *, real *, integer *, ftnlen); char uplos[1]; extern /* Subroutine */ int sspmv_(char *, integer *, real *, real *, real *, integer *, real *, real *, integer *, ftnlen), ssymv_( char *, integer *, real *, real *, integer *, real *, integer *, real *, real *, integer *, ftnlen); logical banded, packed; real errmax; extern logical lseres_(char *, char *, integer *, integer *, real *, real *, integer *, ftnlen, ftnlen); real transl; /* Fortran I/O blocks */ static cilist io___189 = { 0, 0, 0, fmt_9993, 0 }; static cilist io___190 = { 0, 0, 0, fmt_9994, 0 }; static cilist io___191 = { 0, 0, 0, fmt_9995, 0 }; static cilist io___192 = { 0, 0, 0, fmt_9992, 0 }; static cilist io___195 = { 0, 0, 0, fmt_9998, 0 }; static cilist io___197 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___198 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___199 = { 0, 0, 0, fmt_9996, 0 }; static cilist io___200 = { 0, 0, 0, fmt_9993, 0 }; static cilist io___201 = { 0, 0, 0, fmt_9994, 0 }; static cilist io___202 = { 0, 0, 0, fmt_9995, 0 }; /* Tests SSYMV, SSBMV and SSPMV. */ /* Auxiliary routine for test program for Level 2 Blas. */ /* -- Written on 10-August-1987. */ /* Richard Hanson, Sandia National Labs. */ /* Jeremy Du Croz, NAG Central Office. */ /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Scalars .. */ /* .. Local Arrays .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. Scalars in Common .. */ /* .. Common blocks .. */ /* .. Data statements .. */ /* Parameter adjustments */ --idim; --kb; --alf; --bet; --inc; --g; --yt; --y; --x; --as; --aa; a_dim1 = *nmax; a_offset = 1 + a_dim1; a -= a_offset; --ys; --yy; --xs; --xx; /* Function Body */ /* .. Executable Statements .. */ full = *(unsigned char *)&sname[2] == 'Y'; banded = *(unsigned char *)&sname[2] == 'B'; packed = *(unsigned char *)&sname[2] == 'P'; /* Define the number of arguments. */ if (full) { nargs = 10; } else if (banded) { nargs = 11; } else if (packed) { nargs = 9; } nc = 0; reset = TRUE_; errmax = 0.f; i__1 = *nidim; for (in = 1; in <= i__1; ++in) { n = idim[in]; if (banded) { nk = *nkb; } else { nk = 1; } i__2 = nk; for (ik = 1; ik <= i__2; ++ik) { if (banded) { k = kb[ik]; } else { k = n - 1; } /* Set LDA to 1 more than minimum value if room. */ if (banded) { lda = k + 1; } else { lda = n; } if (lda < *nmax) { ++lda; } /* Skip tests if not enough room. */ if (lda > *nmax) { goto L100; } if (packed) { laa = n * (n + 1) / 2; } else { laa = lda * n; } null = n <= 0; for (ic = 1; ic <= 2; ++ic) { *(unsigned char *)uplo = *(unsigned char *)&ich[ic - 1]; /* Generate the matrix A. */ transl = 0.f; smake_(sname + 1, uplo, " ", &n, &n, &a[a_offset], nmax, &aa[ 1], &lda, &k, &k, &reset, &transl, (ftnlen)2, (ftnlen) 1, (ftnlen)1); i__3 = *ninc; for (ix = 1; ix <= i__3; ++ix) { incx = inc[ix]; lx = abs(incx) * n; /* Generate the vector X. */ transl = .5f; i__4 = abs(incx); i__5 = n - 1; smake_("GE", " ", " ", &c__1, &n, &x[1], &c__1, &xx[1], & i__4, &c__0, &i__5, &reset, &transl, (ftnlen)2, ( ftnlen)1, (ftnlen)1); if (n > 1) { x[n / 2] = 0.f; xx[abs(incx) * (n / 2 - 1) + 1] = 0.f; } i__4 = *ninc; for (iy = 1; iy <= i__4; ++iy) { incy = inc[iy]; ly = abs(incy) * n; i__5 = *nalf; for (ia = 1; ia <= i__5; ++ia) { alpha = alf[ia]; i__6 = *nbet; for (ib = 1; ib <= i__6; ++ib) { beta = bet[ib]; /* Generate the vector Y. */ transl = 0.f; i__7 = abs(incy); i__8 = n - 1; smake_("GE", " ", " ", &c__1, &n, &y[1], & c__1, &yy[1], &i__7, &c__0, &i__8, & reset, &transl, (ftnlen)2, (ftnlen)1, (ftnlen)1); ++nc; /* Save every datum before calling the */ /* subroutine. */ *(unsigned char *)uplos = *(unsigned char *) uplo; ns = n; ks = k; als = alpha; i__7 = laa; for (i__ = 1; i__ <= i__7; ++i__) { as[i__] = aa[i__]; /* L10: */ } ldas = lda; i__7 = lx; for (i__ = 1; i__ <= i__7; ++i__) { xs[i__] = xx[i__]; /* L20: */ } incxs = incx; bls = beta; i__7 = ly; for (i__ = 1; i__ <= i__7; ++i__) { ys[i__] = yy[i__]; /* L30: */ } incys = incy; /* Call the subroutine. */ if (full) { if (*trace) { io___189.ciunit = *ntra; s_wsfe(&io___189); do_fio(&c__1, (char *)&nc, (ftnlen) sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&alpha, (ftnlen) sizeof(real)); do_fio(&c__1, (char *)&lda, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&incx, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&beta, (ftnlen) sizeof(real)); do_fio(&c__1, (char *)&incy, (ftnlen) sizeof(integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } ssymv_(uplo, &n, &alpha, &aa[1], &lda, & xx[1], &incx, &beta, &yy[1], & incy, (ftnlen)1); } else if (banded) { if (*trace) { io___190.ciunit = *ntra; s_wsfe(&io___190); do_fio(&c__1, (char *)&nc, (ftnlen) sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&k, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&alpha, (ftnlen) sizeof(real)); do_fio(&c__1, (char *)&lda, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&incx, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&beta, (ftnlen) sizeof(real)); do_fio(&c__1, (char *)&incy, (ftnlen) sizeof(integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } ssbmv_(uplo, &n, &k, &alpha, &aa[1], &lda, &xx[1], &incx, &beta, &yy[1], & incy, (ftnlen)1); } else if (packed) { if (*trace) { io___191.ciunit = *ntra; s_wsfe(&io___191); do_fio(&c__1, (char *)&nc, (ftnlen) sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&alpha, (ftnlen) sizeof(real)); do_fio(&c__1, (char *)&incx, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&beta, (ftnlen) sizeof(real)); do_fio(&c__1, (char *)&incy, (ftnlen) sizeof(integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } sspmv_(uplo, &n, &alpha, &aa[1], &xx[1], & incx, &beta, &yy[1], &incy, ( ftnlen)1); } /* Check if error-exit was taken incorrectly. */ if (! infoc_1.ok) { io___192.ciunit = *nout; s_wsfe(&io___192); e_wsfe(); *fatal = TRUE_; goto L120; } /* See what data changed inside subroutines. */ isame[0] = *(unsigned char *)uplo == *( unsigned char *)uplos; isame[1] = ns == n; if (full) { isame[2] = als == alpha; isame[3] = lse_(&as[1], &aa[1], &laa); isame[4] = ldas == lda; isame[5] = lse_(&xs[1], &xx[1], &lx); isame[6] = incxs == incx; isame[7] = bls == beta; if (null) { isame[8] = lse_(&ys[1], &yy[1], &ly); } else { i__7 = abs(incy); isame[8] = lseres_("GE", " ", &c__1, & n, &ys[1], &yy[1], &i__7, ( ftnlen)2, (ftnlen)1); } isame[9] = incys == incy; } else if (banded) { isame[2] = ks == k; isame[3] = als == alpha; isame[4] = lse_(&as[1], &aa[1], &laa); isame[5] = ldas == lda; isame[6] = lse_(&xs[1], &xx[1], &lx); isame[7] = incxs == incx; isame[8] = bls == beta; if (null) { isame[9] = lse_(&ys[1], &yy[1], &ly); } else { i__7 = abs(incy); isame[9] = lseres_("GE", " ", &c__1, & n, &ys[1], &yy[1], &i__7, ( ftnlen)2, (ftnlen)1); } isame[10] = incys == incy; } else if (packed) { isame[2] = als == alpha; isame[3] = lse_(&as[1], &aa[1], &laa); isame[4] = lse_(&xs[1], &xx[1], &lx); isame[5] = incxs == incx; isame[6] = bls == beta; if (null) { isame[7] = lse_(&ys[1], &yy[1], &ly); } else { i__7 = abs(incy); isame[7] = lseres_("GE", " ", &c__1, & n, &ys[1], &yy[1], &i__7, ( ftnlen)2, (ftnlen)1); } isame[8] = incys == incy; } /* If data was incorrectly changed, report and */ /* return. */ same = TRUE_; i__7 = nargs; for (i__ = 1; i__ <= i__7; ++i__) { same = same && isame[i__ - 1]; if (! isame[i__ - 1]) { io___195.ciunit = *nout; s_wsfe(&io___195); do_fio(&c__1, (char *)&i__, (ftnlen) sizeof(integer)); e_wsfe(); } /* L40: */ } if (! same) { *fatal = TRUE_; goto L120; } if (! null) { /* Check the result. */ smvch_("N", &n, &n, &alpha, &a[a_offset], nmax, &x[1], &incx, &beta, &y[1], &incy, &yt[1], &g[1], &yy[1], eps, &err, fatal, nout, &c_true, ( ftnlen)1); errmax = max(errmax,err); /* If got really bad answer, report and */ /* return. */ if (*fatal) { goto L120; } } else { /* Avoid repeating tests with N.le.0 */ goto L110; } /* L50: */ } /* L60: */ } /* L70: */ } /* L80: */ } /* L90: */ } L100: ; } L110: ; } /* Report result. */ if (errmax < *thresh) { io___197.ciunit = *nout; s_wsfe(&io___197); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); e_wsfe(); } else { io___198.ciunit = *nout; s_wsfe(&io___198); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&errmax, (ftnlen)sizeof(real)); e_wsfe(); } goto L130; L120: io___199.ciunit = *nout; s_wsfe(&io___199); do_fio(&c__1, sname, (ftnlen)6); e_wsfe(); if (full) { io___200.ciunit = *nout; s_wsfe(&io___200); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&alpha, (ftnlen)sizeof(real)); do_fio(&c__1, (char *)&lda, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&incx, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&beta, (ftnlen)sizeof(real)); do_fio(&c__1, (char *)&incy, (ftnlen)sizeof(integer)); e_wsfe(); } else if (banded) { io___201.ciunit = *nout; s_wsfe(&io___201); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&k, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&alpha, (ftnlen)sizeof(real)); do_fio(&c__1, (char *)&lda, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&incx, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&beta, (ftnlen)sizeof(real)); do_fio(&c__1, (char *)&incy, (ftnlen)sizeof(integer)); e_wsfe(); } else if (packed) { io___202.ciunit = *nout; s_wsfe(&io___202); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&alpha, (ftnlen)sizeof(real)); do_fio(&c__1, (char *)&incx, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&beta, (ftnlen)sizeof(real)); do_fio(&c__1, (char *)&incy, (ftnlen)sizeof(integer)); e_wsfe(); } L130: return 0; /* End of SCHK2. */ } /* schk2_ */ /* Subroutine */ int schk3_(char *sname, real *eps, real *thresh, integer * nout, integer *ntra, logical *trace, logical *rewi, logical *fatal, integer *nidim, integer *idim, integer *nkb, integer *kb, integer * ninc, integer *inc, integer *nmax, integer *incmax, real *a, real *aa, real *as, real *x, real *xx, real *xs, real *xt, real *g, real *z__, ftnlen sname_len) { /* Initialized data */ static char ichu[2] = "UL"; static char icht[3] = "NTC"; static char ichd[2] = "UN"; /* Format strings */ static char fmt_9993[] = "(1x,i6,\002: \002,a6,\002(\002,3(\002'\002,a1" ",\002',\002),i3,\002, A,\002,i3,\002, X,\002,i2,\002) " " .\002)"; static char fmt_9994[] = "(1x,i6,\002: \002,a6,\002(\002,3(\002'\002,a1" ",\002',\002),2(i3,\002,\002),\002 A,\002,i3,\002, X,\002,i2,\002" ") .\002)"; static char fmt_9995[] = "(1x,i6,\002: \002,a6,\002(\002,3(\002'\002,a1" ",\002',\002),i3,\002, AP, \002,\002X,\002,i2,\002) " " .\002)"; static char fmt_9992[] = "(\002 ******* FATAL ERROR - ERROR-EXIT TAKEN O" "N VALID CALL *\002,\002******\002)"; static char fmt_9998[] = "(\002 ******* FATAL ERROR - PARAMETER NUMBER" " \002,i2,\002 WAS CH\002,\002ANGED INCORRECTLY *******\002)"; static char fmt_9999[] = "(\002 \002,a6,\002 PASSED THE COMPUTATIONAL TE" "STS (\002,i6,\002 CALL\002,\002S)\002)"; static char fmt_9997[] = "(\002 \002,a6,\002 COMPLETED THE COMPUTATIONAL" " TESTS (\002,i6,\002 C\002,\002ALLS)\002,/\002 ******* BUT WITH " "MAXIMUM TEST RATIO\002,f8.2,\002 - SUSPECT *******\002)"; static char fmt_9996[] = "(\002 ******* \002,a6,\002 FAILED ON CALL NUMB" "ER:\002)"; /* System generated locals */ integer a_dim1, a_offset, i__1, i__2, i__3, i__4, i__5; alist al__1; /* Builtin functions */ integer s_cmp(const char *, const char *, ftnlen, ftnlen), s_wsfe(cilist *), do_fio( integer *, char *, ftnlen), e_wsfe(void), f_rew(alist *); /* Local variables */ integer i__, k, n, nc, ik, in, nk, ks, ix, ns, lx, laa, icd, lda, ict, icu; extern logical lse_(real *, real *, integer *); real err; char diag[1]; integer ldas; logical same; integer incx; logical full, null; char uplo[1], diags[1]; logical isame[13]; extern /* Subroutine */ int smake_(char *, char *, char *, integer *, integer *, real *, integer *, real *, integer *, integer *, integer *, logical *, real *, ftnlen, ftnlen, ftnlen); integer nargs; extern /* Subroutine */ int smvch_(char *, integer *, integer *, real *, real *, integer *, real *, integer *, real *, real *, integer *, real *, real *, real *, real *, real *, logical *, integer *, logical *, ftnlen); logical reset; integer incxs; char trans[1]; extern /* Subroutine */ int stbmv_(char *, char *, char *, integer *, integer *, real *, integer *, real *, integer *, ftnlen, ftnlen, ftnlen), stbsv_(char *, char *, char *, integer *, integer *, real *, integer *, real *, integer *, ftnlen, ftnlen, ftnlen); char uplos[1]; extern /* Subroutine */ int stpmv_(char *, char *, char *, integer *, real *, real *, integer *, ftnlen, ftnlen, ftnlen), strmv_(char *, char *, char *, integer *, real *, integer *, real *, integer *, ftnlen, ftnlen, ftnlen), stpsv_(char *, char *, char *, integer *, real *, real *, integer *, ftnlen, ftnlen, ftnlen), strsv_(char * , char *, char *, integer *, real *, integer *, real *, integer *, ftnlen, ftnlen, ftnlen); logical banded, packed; real errmax; extern logical lseres_(char *, char *, integer *, integer *, real *, real *, integer *, ftnlen, ftnlen); real transl; char transs[1]; /* Fortran I/O blocks */ static cilist io___239 = { 0, 0, 0, fmt_9993, 0 }; static cilist io___240 = { 0, 0, 0, fmt_9994, 0 }; static cilist io___241 = { 0, 0, 0, fmt_9995, 0 }; static cilist io___242 = { 0, 0, 0, fmt_9993, 0 }; static cilist io___243 = { 0, 0, 0, fmt_9994, 0 }; static cilist io___244 = { 0, 0, 0, fmt_9995, 0 }; static cilist io___245 = { 0, 0, 0, fmt_9992, 0 }; static cilist io___248 = { 0, 0, 0, fmt_9998, 0 }; static cilist io___250 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___251 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___252 = { 0, 0, 0, fmt_9996, 0 }; static cilist io___253 = { 0, 0, 0, fmt_9993, 0 }; static cilist io___254 = { 0, 0, 0, fmt_9994, 0 }; static cilist io___255 = { 0, 0, 0, fmt_9995, 0 }; /* Tests STRMV, STBMV, STPMV, STRSV, STBSV and STPSV. */ /* Auxiliary routine for test program for Level 2 Blas. */ /* -- Written on 10-August-1987. */ /* Richard Hanson, Sandia National Labs. */ /* Jeremy Du Croz, NAG Central Office. */ /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Scalars .. */ /* .. Local Arrays .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. Scalars in Common .. */ /* .. Common blocks .. */ /* .. Data statements .. */ /* Parameter adjustments */ --idim; --kb; --inc; --z__; --g; --xt; --x; --as; --aa; a_dim1 = *nmax; a_offset = 1 + a_dim1; a -= a_offset; --xs; --xx; /* Function Body */ /* .. Executable Statements .. */ full = *(unsigned char *)&sname[2] == 'R'; banded = *(unsigned char *)&sname[2] == 'B'; packed = *(unsigned char *)&sname[2] == 'P'; /* Define the number of arguments. */ if (full) { nargs = 8; } else if (banded) { nargs = 9; } else if (packed) { nargs = 7; } nc = 0; reset = TRUE_; errmax = 0.f; /* Set up zero vector for SMVCH. */ i__1 = *nmax; for (i__ = 1; i__ <= i__1; ++i__) { z__[i__] = 0.f; /* L10: */ } i__1 = *nidim; for (in = 1; in <= i__1; ++in) { n = idim[in]; if (banded) { nk = *nkb; } else { nk = 1; } i__2 = nk; for (ik = 1; ik <= i__2; ++ik) { if (banded) { k = kb[ik]; } else { k = n - 1; } /* Set LDA to 1 more than minimum value if room. */ if (banded) { lda = k + 1; } else { lda = n; } if (lda < *nmax) { ++lda; } /* Skip tests if not enough room. */ if (lda > *nmax) { goto L100; } if (packed) { laa = n * (n + 1) / 2; } else { laa = lda * n; } null = n <= 0; for (icu = 1; icu <= 2; ++icu) { *(unsigned char *)uplo = *(unsigned char *)&ichu[icu - 1]; for (ict = 1; ict <= 3; ++ict) { *(unsigned char *)trans = *(unsigned char *)&icht[ict - 1] ; for (icd = 1; icd <= 2; ++icd) { *(unsigned char *)diag = *(unsigned char *)&ichd[icd - 1]; /* Generate the matrix A. */ transl = 0.f; smake_(sname + 1, uplo, diag, &n, &n, &a[a_offset], nmax, &aa[1], &lda, &k, &k, &reset, &transl, ( ftnlen)2, (ftnlen)1, (ftnlen)1); i__3 = *ninc; for (ix = 1; ix <= i__3; ++ix) { incx = inc[ix]; lx = abs(incx) * n; /* Generate the vector X. */ transl = .5f; i__4 = abs(incx); i__5 = n - 1; smake_("GE", " ", " ", &c__1, &n, &x[1], &c__1, & xx[1], &i__4, &c__0, &i__5, &reset, & transl, (ftnlen)2, (ftnlen)1, (ftnlen)1); if (n > 1) { x[n / 2] = 0.f; xx[abs(incx) * (n / 2 - 1) + 1] = 0.f; } ++nc; /* Save every datum before calling the subroutine. */ *(unsigned char *)uplos = *(unsigned char *)uplo; *(unsigned char *)transs = *(unsigned char *) trans; *(unsigned char *)diags = *(unsigned char *)diag; ns = n; ks = k; i__4 = laa; for (i__ = 1; i__ <= i__4; ++i__) { as[i__] = aa[i__]; /* L20: */ } ldas = lda; i__4 = lx; for (i__ = 1; i__ <= i__4; ++i__) { xs[i__] = xx[i__]; /* L30: */ } incxs = incx; /* Call the subroutine. */ if (s_cmp(sname + 3, "MV", (ftnlen)2, (ftnlen)2) == 0) { if (full) { if (*trace) { io___239.ciunit = *ntra; s_wsfe(&io___239); do_fio(&c__1, (char *)&nc, (ftnlen) sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, diag, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&lda, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&incx, (ftnlen) sizeof(integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } strmv_(uplo, trans, diag, &n, &aa[1], & lda, &xx[1], &incx, (ftnlen)1, ( ftnlen)1, (ftnlen)1); } else if (banded) { if (*trace) { io___240.ciunit = *ntra; s_wsfe(&io___240); do_fio(&c__1, (char *)&nc, (ftnlen) sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, diag, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&k, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&lda, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&incx, (ftnlen) sizeof(integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } stbmv_(uplo, trans, diag, &n, &k, &aa[1], &lda, &xx[1], &incx, (ftnlen)1, ( ftnlen)1, (ftnlen)1); } else if (packed) { if (*trace) { io___241.ciunit = *ntra; s_wsfe(&io___241); do_fio(&c__1, (char *)&nc, (ftnlen) sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, diag, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&incx, (ftnlen) sizeof(integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } stpmv_(uplo, trans, diag, &n, &aa[1], &xx[ 1], &incx, (ftnlen)1, (ftnlen)1, ( ftnlen)1); } } else if (s_cmp(sname + 3, "SV", (ftnlen)2, ( ftnlen)2) == 0) { if (full) { if (*trace) { io___242.ciunit = *ntra; s_wsfe(&io___242); do_fio(&c__1, (char *)&nc, (ftnlen) sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, diag, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&lda, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&incx, (ftnlen) sizeof(integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } strsv_(uplo, trans, diag, &n, &aa[1], & lda, &xx[1], &incx, (ftnlen)1, ( ftnlen)1, (ftnlen)1); } else if (banded) { if (*trace) { io___243.ciunit = *ntra; s_wsfe(&io___243); do_fio(&c__1, (char *)&nc, (ftnlen) sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, diag, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&k, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&lda, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&incx, (ftnlen) sizeof(integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } stbsv_(uplo, trans, diag, &n, &k, &aa[1], &lda, &xx[1], &incx, (ftnlen)1, ( ftnlen)1, (ftnlen)1); } else if (packed) { if (*trace) { io___244.ciunit = *ntra; s_wsfe(&io___244); do_fio(&c__1, (char *)&nc, (ftnlen) sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, diag, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&incx, (ftnlen) sizeof(integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } stpsv_(uplo, trans, diag, &n, &aa[1], &xx[ 1], &incx, (ftnlen)1, (ftnlen)1, ( ftnlen)1); } } /* Check if error-exit was taken incorrectly. */ if (! infoc_1.ok) { io___245.ciunit = *nout; s_wsfe(&io___245); e_wsfe(); *fatal = TRUE_; goto L120; } /* See what data changed inside subroutines. */ isame[0] = *(unsigned char *)uplo == *(unsigned char *)uplos; isame[1] = *(unsigned char *)trans == *(unsigned char *)transs; isame[2] = *(unsigned char *)diag == *(unsigned char *)diags; isame[3] = ns == n; if (full) { isame[4] = lse_(&as[1], &aa[1], &laa); isame[5] = ldas == lda; if (null) { isame[6] = lse_(&xs[1], &xx[1], &lx); } else { i__4 = abs(incx); isame[6] = lseres_("GE", " ", &c__1, &n, & xs[1], &xx[1], &i__4, (ftnlen)2, ( ftnlen)1); } isame[7] = incxs == incx; } else if (banded) { isame[4] = ks == k; isame[5] = lse_(&as[1], &aa[1], &laa); isame[6] = ldas == lda; if (null) { isame[7] = lse_(&xs[1], &xx[1], &lx); } else { i__4 = abs(incx); isame[7] = lseres_("GE", " ", &c__1, &n, & xs[1], &xx[1], &i__4, (ftnlen)2, ( ftnlen)1); } isame[8] = incxs == incx; } else if (packed) { isame[4] = lse_(&as[1], &aa[1], &laa); if (null) { isame[5] = lse_(&xs[1], &xx[1], &lx); } else { i__4 = abs(incx); isame[5] = lseres_("GE", " ", &c__1, &n, & xs[1], &xx[1], &i__4, (ftnlen)2, ( ftnlen)1); } isame[6] = incxs == incx; } /* If data was incorrectly changed, report and */ /* return. */ same = TRUE_; i__4 = nargs; for (i__ = 1; i__ <= i__4; ++i__) { same = same && isame[i__ - 1]; if (! isame[i__ - 1]) { io___248.ciunit = *nout; s_wsfe(&io___248); do_fio(&c__1, (char *)&i__, (ftnlen) sizeof(integer)); e_wsfe(); } /* L40: */ } if (! same) { *fatal = TRUE_; goto L120; } if (! null) { if (s_cmp(sname + 3, "MV", (ftnlen)2, (ftnlen) 2) == 0) { /* Check the result. */ smvch_(trans, &n, &n, &c_b128, &a[ a_offset], nmax, &x[1], &incx, & c_b120, &z__[1], &incx, &xt[1], & g[1], &xx[1], eps, &err, fatal, nout, &c_true, (ftnlen)1); } else if (s_cmp(sname + 3, "SV", (ftnlen)2, ( ftnlen)2) == 0) { /* Compute approximation to original vector. */ i__4 = n; for (i__ = 1; i__ <= i__4; ++i__) { z__[i__] = xx[(i__ - 1) * abs(incx) + 1]; xx[(i__ - 1) * abs(incx) + 1] = x[i__] ; /* L50: */ } smvch_(trans, &n, &n, &c_b128, &a[ a_offset], nmax, &z__[1], &incx, & c_b120, &x[1], &incx, &xt[1], &g[ 1], &xx[1], eps, &err, fatal, nout, &c_false, (ftnlen)1); } errmax = max(errmax,err); /* If got really bad answer, report and return. */ if (*fatal) { goto L120; } } else { /* Avoid repeating tests with N.le.0. */ goto L110; } /* L60: */ } /* L70: */ } /* L80: */ } /* L90: */ } L100: ; } L110: ; } /* Report result. */ if (errmax < *thresh) { io___250.ciunit = *nout; s_wsfe(&io___250); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); e_wsfe(); } else { io___251.ciunit = *nout; s_wsfe(&io___251); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&errmax, (ftnlen)sizeof(real)); e_wsfe(); } goto L130; L120: io___252.ciunit = *nout; s_wsfe(&io___252); do_fio(&c__1, sname, (ftnlen)6); e_wsfe(); if (full) { io___253.ciunit = *nout; s_wsfe(&io___253); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, diag, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&lda, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&incx, (ftnlen)sizeof(integer)); e_wsfe(); } else if (banded) { io___254.ciunit = *nout; s_wsfe(&io___254); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, diag, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&k, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&lda, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&incx, (ftnlen)sizeof(integer)); e_wsfe(); } else if (packed) { io___255.ciunit = *nout; s_wsfe(&io___255); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, diag, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&incx, (ftnlen)sizeof(integer)); e_wsfe(); } L130: return 0; /* End of SCHK3. */ } /* schk3_ */ /* Subroutine */ int schk4_(char *sname, real *eps, real *thresh, integer * nout, integer *ntra, logical *trace, logical *rewi, logical *fatal, integer *nidim, integer *idim, integer *nalf, real *alf, integer * ninc, integer *inc, integer *nmax, integer *incmax, real *a, real *aa, real *as, real *x, real *xx, real *xs, real *y, real *yy, real *ys, real *yt, real *g, real *z__, ftnlen sname_len) { /* Format strings */ static char fmt_9994[] = "(1x,i6,\002: \002,a6,\002(\002,2(i3,\002,\002)" ",f4.1,\002, X,\002,i2,\002, Y,\002,i2,\002, A,\002,i3,\002) " " .\002)"; static char fmt_9993[] = "(\002 ******* FATAL ERROR - ERROR-EXIT TAKEN O" "N VALID CALL *\002,\002******\002)"; static char fmt_9998[] = "(\002 ******* FATAL ERROR - PARAMETER NUMBER" " \002,i2,\002 WAS CH\002,\002ANGED INCORRECTLY *******\002)"; static char fmt_9999[] = "(\002 \002,a6,\002 PASSED THE COMPUTATIONAL TE" "STS (\002,i6,\002 CALL\002,\002S)\002)"; static char fmt_9997[] = "(\002 \002,a6,\002 COMPLETED THE COMPUTATIONAL" " TESTS (\002,i6,\002 C\002,\002ALLS)\002,/\002 ******* BUT WITH " "MAXIMUM TEST RATIO\002,f8.2,\002 - SUSPECT *******\002)"; static char fmt_9995[] = "(\002 THESE ARE THE RESULTS FOR COLUMN" " \002,i3)"; static char fmt_9996[] = "(\002 ******* \002,a6,\002 FAILED ON CALL NUMB" "ER:\002)"; /* System generated locals */ integer a_dim1, a_offset, i__1, i__2, i__3, i__4, i__5, i__6; alist al__1; /* Builtin functions */ integer s_wsfe(cilist *), do_fio(integer *, char *, ftnlen), e_wsfe(void), f_rew(alist *); /* Local variables */ integer i__, j, m, n; real w[1]; integer ia, nc, nd, im, in, ms, ix, iy, ns, lx, ly, laa, lda; real als; extern logical lse_(real *, real *, integer *); real err; integer ldas; logical same; extern /* Subroutine */ int sger_(integer *, integer *, real *, real *, integer *, real *, integer *, real *, integer *); integer incx, incy; logical null; real alpha; logical isame[13]; extern /* Subroutine */ int smake_(char *, char *, char *, integer *, integer *, real *, integer *, real *, integer *, integer *, integer *, logical *, real *, ftnlen, ftnlen, ftnlen); integer nargs; extern /* Subroutine */ int smvch_(char *, integer *, integer *, real *, real *, integer *, real *, integer *, real *, real *, integer *, real *, real *, real *, real *, real *, logical *, integer *, logical *, ftnlen); logical reset; integer incxs, incys; real errmax; extern logical lseres_(char *, char *, integer *, integer *, real *, real *, integer *, ftnlen, ftnlen); real transl; /* Fortran I/O blocks */ static cilist io___284 = { 0, 0, 0, fmt_9994, 0 }; static cilist io___285 = { 0, 0, 0, fmt_9993, 0 }; static cilist io___288 = { 0, 0, 0, fmt_9998, 0 }; static cilist io___292 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___293 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___294 = { 0, 0, 0, fmt_9995, 0 }; static cilist io___295 = { 0, 0, 0, fmt_9996, 0 }; static cilist io___296 = { 0, 0, 0, fmt_9994, 0 }; /* Tests SGER. */ /* Auxiliary routine for test program for Level 2 Blas. */ /* -- Written on 10-August-1987. */ /* Richard Hanson, Sandia National Labs. */ /* Jeremy Du Croz, NAG Central Office. */ /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Scalars .. */ /* .. Local Arrays .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. Scalars in Common .. */ /* .. Common blocks .. */ /* .. Executable Statements .. */ /* Define the number of arguments. */ /* Parameter adjustments */ --idim; --alf; --inc; --z__; --g; --yt; --y; --x; --as; --aa; a_dim1 = *nmax; a_offset = 1 + a_dim1; a -= a_offset; --ys; --yy; --xs; --xx; /* Function Body */ nargs = 9; nc = 0; reset = TRUE_; errmax = 0.f; i__1 = *nidim; for (in = 1; in <= i__1; ++in) { n = idim[in]; nd = n / 2 + 1; for (im = 1; im <= 2; ++im) { if (im == 1) { /* Computing MAX */ i__2 = n - nd; m = max(i__2,0); } if (im == 2) { /* Computing MIN */ i__2 = n + nd; m = min(i__2,*nmax); } /* Set LDA to 1 more than minimum value if room. */ lda = m; if (lda < *nmax) { ++lda; } /* Skip tests if not enough room. */ if (lda > *nmax) { goto L110; } laa = lda * n; null = n <= 0 || m <= 0; i__2 = *ninc; for (ix = 1; ix <= i__2; ++ix) { incx = inc[ix]; lx = abs(incx) * m; /* Generate the vector X. */ transl = .5f; i__3 = abs(incx); i__4 = m - 1; smake_("GE", " ", " ", &c__1, &m, &x[1], &c__1, &xx[1], &i__3, &c__0, &i__4, &reset, &transl, (ftnlen)2, (ftnlen)1, (ftnlen)1); if (m > 1) { x[m / 2] = 0.f; xx[abs(incx) * (m / 2 - 1) + 1] = 0.f; } i__3 = *ninc; for (iy = 1; iy <= i__3; ++iy) { incy = inc[iy]; ly = abs(incy) * n; /* Generate the vector Y. */ transl = 0.f; i__4 = abs(incy); i__5 = n - 1; smake_("GE", " ", " ", &c__1, &n, &y[1], &c__1, &yy[1], & i__4, &c__0, &i__5, &reset, &transl, (ftnlen)2, ( ftnlen)1, (ftnlen)1); if (n > 1) { y[n / 2] = 0.f; yy[abs(incy) * (n / 2 - 1) + 1] = 0.f; } i__4 = *nalf; for (ia = 1; ia <= i__4; ++ia) { alpha = alf[ia]; /* Generate the matrix A. */ transl = 0.f; i__5 = m - 1; i__6 = n - 1; smake_(sname + 1, " ", " ", &m, &n, &a[a_offset], nmax, &aa[1], &lda, &i__5, &i__6, &reset, & transl, (ftnlen)2, (ftnlen)1, (ftnlen)1); ++nc; /* Save every datum before calling the subroutine. */ ms = m; ns = n; als = alpha; i__5 = laa; for (i__ = 1; i__ <= i__5; ++i__) { as[i__] = aa[i__]; /* L10: */ } ldas = lda; i__5 = lx; for (i__ = 1; i__ <= i__5; ++i__) { xs[i__] = xx[i__]; /* L20: */ } incxs = incx; i__5 = ly; for (i__ = 1; i__ <= i__5; ++i__) { ys[i__] = yy[i__]; /* L30: */ } incys = incy; /* Call the subroutine. */ if (*trace) { io___284.ciunit = *ntra; s_wsfe(&io___284); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer) ); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&m, (ftnlen)sizeof(integer)) ; do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)) ; do_fio(&c__1, (char *)&alpha, (ftnlen)sizeof(real) ); do_fio(&c__1, (char *)&incx, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&incy, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&lda, (ftnlen)sizeof( integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } sger_(&m, &n, &alpha, &xx[1], &incx, &yy[1], &incy, & aa[1], &lda); /* Check if error-exit was taken incorrectly. */ if (! infoc_1.ok) { io___285.ciunit = *nout; s_wsfe(&io___285); e_wsfe(); *fatal = TRUE_; goto L140; } /* See what data changed inside subroutine. */ isame[0] = ms == m; isame[1] = ns == n; isame[2] = als == alpha; isame[3] = lse_(&xs[1], &xx[1], &lx); isame[4] = incxs == incx; isame[5] = lse_(&ys[1], &yy[1], &ly); isame[6] = incys == incy; if (null) { isame[7] = lse_(&as[1], &aa[1], &laa); } else { isame[7] = lseres_("GE", " ", &m, &n, &as[1], &aa[ 1], &lda, (ftnlen)2, (ftnlen)1); } isame[8] = ldas == lda; /* If data was incorrectly changed, report and return. */ same = TRUE_; i__5 = nargs; for (i__ = 1; i__ <= i__5; ++i__) { same = same && isame[i__ - 1]; if (! isame[i__ - 1]) { io___288.ciunit = *nout; s_wsfe(&io___288); do_fio(&c__1, (char *)&i__, (ftnlen)sizeof( integer)); e_wsfe(); } /* L40: */ } if (! same) { *fatal = TRUE_; goto L140; } if (! null) { /* Check the result column by column. */ if (incx > 0) { i__5 = m; for (i__ = 1; i__ <= i__5; ++i__) { z__[i__] = x[i__]; /* L50: */ } } else { i__5 = m; for (i__ = 1; i__ <= i__5; ++i__) { z__[i__] = x[m - i__ + 1]; /* L60: */ } } i__5 = n; for (j = 1; j <= i__5; ++j) { if (incy > 0) { w[0] = y[j]; } else { w[0] = y[n - j + 1]; } smvch_("N", &m, &c__1, &alpha, &z__[1], nmax, w, &c__1, &c_b128, &a[j * a_dim1 + 1], &c__1, &yt[1], &g[1], &aa[(j - 1) * lda + 1], eps, &err, fatal, nout, & c_true, (ftnlen)1); errmax = max(errmax,err); /* If got really bad answer, report and return. */ if (*fatal) { goto L130; } /* L70: */ } } else { /* Avoid repeating tests with M.le.0 or N.le.0. */ goto L110; } /* L80: */ } /* L90: */ } /* L100: */ } L110: ; } /* L120: */ } /* Report result. */ if (errmax < *thresh) { io___292.ciunit = *nout; s_wsfe(&io___292); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); e_wsfe(); } else { io___293.ciunit = *nout; s_wsfe(&io___293); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&errmax, (ftnlen)sizeof(real)); e_wsfe(); } goto L150; L130: io___294.ciunit = *nout; s_wsfe(&io___294); do_fio(&c__1, (char *)&j, (ftnlen)sizeof(integer)); e_wsfe(); L140: io___295.ciunit = *nout; s_wsfe(&io___295); do_fio(&c__1, sname, (ftnlen)6); e_wsfe(); io___296.ciunit = *nout; s_wsfe(&io___296); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&m, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&alpha, (ftnlen)sizeof(real)); do_fio(&c__1, (char *)&incx, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&incy, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&lda, (ftnlen)sizeof(integer)); e_wsfe(); L150: return 0; /* End of SCHK4. */ } /* schk4_ */ /* Subroutine */ int schk5_(char *sname, real *eps, real *thresh, integer * nout, integer *ntra, logical *trace, logical *rewi, logical *fatal, integer *nidim, integer *idim, integer *nalf, real *alf, integer * ninc, integer *inc, integer *nmax, integer *incmax, real *a, real *aa, real *as, real *x, real *xx, real *xs, real *y, real *yy, real *ys, real *yt, real *g, real *z__, ftnlen sname_len) { /* Initialized data */ static char ich[2] = "UL"; /* Format strings */ static char fmt_9993[] = "(1x,i6,\002: \002,a6,\002('\002,a1,\002',\002," "i3,\002,\002,f4.1,\002, X,\002,i2,\002, A,\002,i3,\002) " " .\002)"; static char fmt_9994[] = "(1x,i6,\002: \002,a6,\002('\002,a1,\002',\002," "i3,\002,\002,f4.1,\002, X,\002,i2,\002, AP) " " .\002)"; static char fmt_9992[] = "(\002 ******* FATAL ERROR - ERROR-EXIT TAKEN O" "N VALID CALL *\002,\002******\002)"; static char fmt_9998[] = "(\002 ******* FATAL ERROR - PARAMETER NUMBER" " \002,i2,\002 WAS CH\002,\002ANGED INCORRECTLY *******\002)"; static char fmt_9999[] = "(\002 \002,a6,\002 PASSED THE COMPUTATIONAL TE" "STS (\002,i6,\002 CALL\002,\002S)\002)"; static char fmt_9997[] = "(\002 \002,a6,\002 COMPLETED THE COMPUTATIONAL" " TESTS (\002,i6,\002 C\002,\002ALLS)\002,/\002 ******* BUT WITH " "MAXIMUM TEST RATIO\002,f8.2,\002 - SUSPECT *******\002)"; static char fmt_9995[] = "(\002 THESE ARE THE RESULTS FOR COLUMN" " \002,i3)"; static char fmt_9996[] = "(\002 ******* \002,a6,\002 FAILED ON CALL NUMB" "ER:\002)"; /* System generated locals */ integer a_dim1, a_offset, i__1, i__2, i__3, i__4, i__5; alist al__1; /* Builtin functions */ integer s_wsfe(cilist *), do_fio(integer *, char *, ftnlen), e_wsfe(void), f_rew(alist *); /* Local variables */ integer i__, j, n; real w[1]; integer ia, ja, ic, nc, jj, lj, in, ix, ns, lx, laa, lda; real als; extern logical lse_(real *, real *, integer *); real err; integer ldas; logical same; integer incx; logical full, null; char uplo[1]; extern /* Subroutine */ int sspr_(char *, integer *, real *, real *, integer *, real *, ftnlen), ssyr_(char *, integer *, real *, real *, integer *, real *, integer *, ftnlen); real alpha; logical isame[13]; extern /* Subroutine */ int smake_(char *, char *, char *, integer *, integer *, real *, integer *, real *, integer *, integer *, integer *, logical *, real *, ftnlen, ftnlen, ftnlen); integer nargs; extern /* Subroutine */ int smvch_(char *, integer *, integer *, real *, real *, integer *, real *, integer *, real *, real *, integer *, real *, real *, real *, real *, real *, logical *, integer *, logical *, ftnlen); logical reset; integer incxs; logical upper; char uplos[1]; logical packed; real errmax; extern logical lseres_(char *, char *, integer *, integer *, real *, real *, integer *, ftnlen, ftnlen); real transl; /* Fortran I/O blocks */ static cilist io___324 = { 0, 0, 0, fmt_9993, 0 }; static cilist io___325 = { 0, 0, 0, fmt_9994, 0 }; static cilist io___326 = { 0, 0, 0, fmt_9992, 0 }; static cilist io___329 = { 0, 0, 0, fmt_9998, 0 }; static cilist io___336 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___337 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___338 = { 0, 0, 0, fmt_9995, 0 }; static cilist io___339 = { 0, 0, 0, fmt_9996, 0 }; static cilist io___340 = { 0, 0, 0, fmt_9993, 0 }; static cilist io___341 = { 0, 0, 0, fmt_9994, 0 }; /* Tests SSYR and SSPR. */ /* Auxiliary routine for test program for Level 2 Blas. */ /* -- Written on 10-August-1987. */ /* Richard Hanson, Sandia National Labs. */ /* Jeremy Du Croz, NAG Central Office. */ /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Scalars .. */ /* .. Local Arrays .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. Scalars in Common .. */ /* .. Common blocks .. */ /* .. Data statements .. */ /* Parameter adjustments */ --idim; --alf; --inc; --z__; --g; --yt; --y; --x; --as; --aa; a_dim1 = *nmax; a_offset = 1 + a_dim1; a -= a_offset; --ys; --yy; --xs; --xx; /* Function Body */ /* .. Executable Statements .. */ full = *(unsigned char *)&sname[2] == 'Y'; packed = *(unsigned char *)&sname[2] == 'P'; /* Define the number of arguments. */ if (full) { nargs = 7; } else if (packed) { nargs = 6; } nc = 0; reset = TRUE_; errmax = 0.f; i__1 = *nidim; for (in = 1; in <= i__1; ++in) { n = idim[in]; /* Set LDA to 1 more than minimum value if room. */ lda = n; if (lda < *nmax) { ++lda; } /* Skip tests if not enough room. */ if (lda > *nmax) { goto L100; } if (packed) { laa = n * (n + 1) / 2; } else { laa = lda * n; } for (ic = 1; ic <= 2; ++ic) { *(unsigned char *)uplo = *(unsigned char *)&ich[ic - 1]; upper = *(unsigned char *)uplo == 'U'; i__2 = *ninc; for (ix = 1; ix <= i__2; ++ix) { incx = inc[ix]; lx = abs(incx) * n; /* Generate the vector X. */ transl = .5f; i__3 = abs(incx); i__4 = n - 1; smake_("GE", " ", " ", &c__1, &n, &x[1], &c__1, &xx[1], &i__3, &c__0, &i__4, &reset, &transl, (ftnlen)2, (ftnlen)1, (ftnlen)1); if (n > 1) { x[n / 2] = 0.f; xx[abs(incx) * (n / 2 - 1) + 1] = 0.f; } i__3 = *nalf; for (ia = 1; ia <= i__3; ++ia) { alpha = alf[ia]; null = n <= 0 || alpha == 0.f; /* Generate the matrix A. */ transl = 0.f; i__4 = n - 1; i__5 = n - 1; smake_(sname + 1, uplo, " ", &n, &n, &a[a_offset], nmax, & aa[1], &lda, &i__4, &i__5, &reset, &transl, ( ftnlen)2, (ftnlen)1, (ftnlen)1); ++nc; /* Save every datum before calling the subroutine. */ *(unsigned char *)uplos = *(unsigned char *)uplo; ns = n; als = alpha; i__4 = laa; for (i__ = 1; i__ <= i__4; ++i__) { as[i__] = aa[i__]; /* L10: */ } ldas = lda; i__4 = lx; for (i__ = 1; i__ <= i__4; ++i__) { xs[i__] = xx[i__]; /* L20: */ } incxs = incx; /* Call the subroutine. */ if (full) { if (*trace) { io___324.ciunit = *ntra; s_wsfe(&io___324); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer) ); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)) ; do_fio(&c__1, (char *)&alpha, (ftnlen)sizeof(real) ); do_fio(&c__1, (char *)&incx, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&lda, (ftnlen)sizeof( integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } ssyr_(uplo, &n, &alpha, &xx[1], &incx, &aa[1], &lda, ( ftnlen)1); } else if (packed) { if (*trace) { io___325.ciunit = *ntra; s_wsfe(&io___325); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer) ); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)) ; do_fio(&c__1, (char *)&alpha, (ftnlen)sizeof(real) ); do_fio(&c__1, (char *)&incx, (ftnlen)sizeof( integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } sspr_(uplo, &n, &alpha, &xx[1], &incx, &aa[1], ( ftnlen)1); } /* Check if error-exit was taken incorrectly. */ if (! infoc_1.ok) { io___326.ciunit = *nout; s_wsfe(&io___326); e_wsfe(); *fatal = TRUE_; goto L120; } /* See what data changed inside subroutines. */ isame[0] = *(unsigned char *)uplo == *(unsigned char *) uplos; isame[1] = ns == n; isame[2] = als == alpha; isame[3] = lse_(&xs[1], &xx[1], &lx); isame[4] = incxs == incx; if (null) { isame[5] = lse_(&as[1], &aa[1], &laa); } else { isame[5] = lseres_(sname + 1, uplo, &n, &n, &as[1], & aa[1], &lda, (ftnlen)2, (ftnlen)1); } if (! packed) { isame[6] = ldas == lda; } /* If data was incorrectly changed, report and return. */ same = TRUE_; i__4 = nargs; for (i__ = 1; i__ <= i__4; ++i__) { same = same && isame[i__ - 1]; if (! isame[i__ - 1]) { io___329.ciunit = *nout; s_wsfe(&io___329); do_fio(&c__1, (char *)&i__, (ftnlen)sizeof( integer)); e_wsfe(); } /* L30: */ } if (! same) { *fatal = TRUE_; goto L120; } if (! null) { /* Check the result column by column. */ if (incx > 0) { i__4 = n; for (i__ = 1; i__ <= i__4; ++i__) { z__[i__] = x[i__]; /* L40: */ } } else { i__4 = n; for (i__ = 1; i__ <= i__4; ++i__) { z__[i__] = x[n - i__ + 1]; /* L50: */ } } ja = 1; i__4 = n; for (j = 1; j <= i__4; ++j) { w[0] = z__[j]; if (upper) { jj = 1; lj = j; } else { jj = j; lj = n - j + 1; } smvch_("N", &lj, &c__1, &alpha, &z__[jj], &lj, w, &c__1, &c_b128, &a[jj + j * a_dim1], & c__1, &yt[1], &g[1], &aa[ja], eps, &err, fatal, nout, &c_true, (ftnlen)1); if (full) { if (upper) { ja += lda; } else { ja = ja + lda + 1; } } else { ja += lj; } errmax = max(errmax,err); /* If got really bad answer, report and return. */ if (*fatal) { goto L110; } /* L60: */ } } else { /* Avoid repeating tests if N.le.0. */ if (n <= 0) { goto L100; } } /* L70: */ } /* L80: */ } /* L90: */ } L100: ; } /* Report result. */ if (errmax < *thresh) { io___336.ciunit = *nout; s_wsfe(&io___336); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); e_wsfe(); } else { io___337.ciunit = *nout; s_wsfe(&io___337); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&errmax, (ftnlen)sizeof(real)); e_wsfe(); } goto L130; L110: io___338.ciunit = *nout; s_wsfe(&io___338); do_fio(&c__1, (char *)&j, (ftnlen)sizeof(integer)); e_wsfe(); L120: io___339.ciunit = *nout; s_wsfe(&io___339); do_fio(&c__1, sname, (ftnlen)6); e_wsfe(); if (full) { io___340.ciunit = *nout; s_wsfe(&io___340); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&alpha, (ftnlen)sizeof(real)); do_fio(&c__1, (char *)&incx, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&lda, (ftnlen)sizeof(integer)); e_wsfe(); } else if (packed) { io___341.ciunit = *nout; s_wsfe(&io___341); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&alpha, (ftnlen)sizeof(real)); do_fio(&c__1, (char *)&incx, (ftnlen)sizeof(integer)); e_wsfe(); } L130: return 0; /* End of SCHK5. */ } /* schk5_ */ /* Subroutine */ int schk6_(char *sname, real *eps, real *thresh, integer * nout, integer *ntra, logical *trace, logical *rewi, logical *fatal, integer *nidim, integer *idim, integer *nalf, real *alf, integer * ninc, integer *inc, integer *nmax, integer *incmax, real *a, real *aa, real *as, real *x, real *xx, real *xs, real *y, real *yy, real *ys, real *yt, real *g, real *z__, ftnlen sname_len) { /* Initialized data */ static char ich[2] = "UL"; /* Format strings */ static char fmt_9993[] = "(1x,i6,\002: \002,a6,\002('\002,a1,\002',\002," "i3,\002,\002,f4.1,\002, X,\002,i2,\002, Y,\002,i2,\002, A,\002,i" "3,\002) .\002)"; static char fmt_9994[] = "(1x,i6,\002: \002,a6,\002('\002,a1,\002',\002," "i3,\002,\002,f4.1,\002, X,\002,i2,\002, Y,\002,i2,\002, AP) " " .\002)"; static char fmt_9992[] = "(\002 ******* FATAL ERROR - ERROR-EXIT TAKEN O" "N VALID CALL *\002,\002******\002)"; static char fmt_9998[] = "(\002 ******* FATAL ERROR - PARAMETER NUMBER" " \002,i2,\002 WAS CH\002,\002ANGED INCORRECTLY *******\002)"; static char fmt_9999[] = "(\002 \002,a6,\002 PASSED THE COMPUTATIONAL TE" "STS (\002,i6,\002 CALL\002,\002S)\002)"; static char fmt_9997[] = "(\002 \002,a6,\002 COMPLETED THE COMPUTATIONAL" " TESTS (\002,i6,\002 C\002,\002ALLS)\002,/\002 ******* BUT WITH " "MAXIMUM TEST RATIO\002,f8.2,\002 - SUSPECT *******\002)"; static char fmt_9995[] = "(\002 THESE ARE THE RESULTS FOR COLUMN" " \002,i3)"; static char fmt_9996[] = "(\002 ******* \002,a6,\002 FAILED ON CALL NUMB" "ER:\002)"; /* System generated locals */ integer a_dim1, a_offset, z_dim1, z_offset, i__1, i__2, i__3, i__4, i__5, i__6; alist al__1; /* Builtin functions */ integer s_wsfe(cilist *), do_fio(integer *, char *, ftnlen), e_wsfe(void), f_rew(alist *); /* Local variables */ integer i__, j, n; real w[2]; integer ia, ja, ic, nc, jj, lj, in, ix, iy, ns, lx, ly, laa, lda; real als; extern logical lse_(real *, real *, integer *); real err; integer ldas; logical same; integer incx, incy; logical full, null; char uplo[1]; extern /* Subroutine */ int sspr2_(char *, integer *, real *, real *, integer *, real *, integer *, real *, ftnlen), ssyr2_(char *, integer *, real *, real *, integer *, real *, integer *, real *, integer *, ftnlen); real alpha; logical isame[13]; extern /* Subroutine */ int smake_(char *, char *, char *, integer *, integer *, real *, integer *, real *, integer *, integer *, integer *, logical *, real *, ftnlen, ftnlen, ftnlen); integer nargs; extern /* Subroutine */ int smvch_(char *, integer *, integer *, real *, real *, integer *, real *, integer *, real *, real *, integer *, real *, real *, real *, real *, real *, logical *, integer *, logical *, ftnlen); logical reset; integer incxs, incys; logical upper; char uplos[1]; logical packed; real errmax; extern logical lseres_(char *, char *, integer *, integer *, real *, real *, integer *, ftnlen, ftnlen); real transl; /* Fortran I/O blocks */ static cilist io___373 = { 0, 0, 0, fmt_9993, 0 }; static cilist io___374 = { 0, 0, 0, fmt_9994, 0 }; static cilist io___375 = { 0, 0, 0, fmt_9992, 0 }; static cilist io___378 = { 0, 0, 0, fmt_9998, 0 }; static cilist io___385 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___386 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___387 = { 0, 0, 0, fmt_9995, 0 }; static cilist io___388 = { 0, 0, 0, fmt_9996, 0 }; static cilist io___389 = { 0, 0, 0, fmt_9993, 0 }; static cilist io___390 = { 0, 0, 0, fmt_9994, 0 }; /* Tests SSYR2 and SSPR2. */ /* Auxiliary routine for test program for Level 2 Blas. */ /* -- Written on 10-August-1987. */ /* Richard Hanson, Sandia National Labs. */ /* Jeremy Du Croz, NAG Central Office. */ /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Scalars .. */ /* .. Local Arrays .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. Scalars in Common .. */ /* .. Common blocks .. */ /* .. Data statements .. */ /* Parameter adjustments */ --idim; --alf; --inc; z_dim1 = *nmax; z_offset = 1 + z_dim1; z__ -= z_offset; --g; --yt; --y; --x; --as; --aa; a_dim1 = *nmax; a_offset = 1 + a_dim1; a -= a_offset; --ys; --yy; --xs; --xx; /* Function Body */ /* .. Executable Statements .. */ full = *(unsigned char *)&sname[2] == 'Y'; packed = *(unsigned char *)&sname[2] == 'P'; /* Define the number of arguments. */ if (full) { nargs = 9; } else if (packed) { nargs = 8; } nc = 0; reset = TRUE_; errmax = 0.f; i__1 = *nidim; for (in = 1; in <= i__1; ++in) { n = idim[in]; /* Set LDA to 1 more than minimum value if room. */ lda = n; if (lda < *nmax) { ++lda; } /* Skip tests if not enough room. */ if (lda > *nmax) { goto L140; } if (packed) { laa = n * (n + 1) / 2; } else { laa = lda * n; } for (ic = 1; ic <= 2; ++ic) { *(unsigned char *)uplo = *(unsigned char *)&ich[ic - 1]; upper = *(unsigned char *)uplo == 'U'; i__2 = *ninc; for (ix = 1; ix <= i__2; ++ix) { incx = inc[ix]; lx = abs(incx) * n; /* Generate the vector X. */ transl = .5f; i__3 = abs(incx); i__4 = n - 1; smake_("GE", " ", " ", &c__1, &n, &x[1], &c__1, &xx[1], &i__3, &c__0, &i__4, &reset, &transl, (ftnlen)2, (ftnlen)1, (ftnlen)1); if (n > 1) { x[n / 2] = 0.f; xx[abs(incx) * (n / 2 - 1) + 1] = 0.f; } i__3 = *ninc; for (iy = 1; iy <= i__3; ++iy) { incy = inc[iy]; ly = abs(incy) * n; /* Generate the vector Y. */ transl = 0.f; i__4 = abs(incy); i__5 = n - 1; smake_("GE", " ", " ", &c__1, &n, &y[1], &c__1, &yy[1], & i__4, &c__0, &i__5, &reset, &transl, (ftnlen)2, ( ftnlen)1, (ftnlen)1); if (n > 1) { y[n / 2] = 0.f; yy[abs(incy) * (n / 2 - 1) + 1] = 0.f; } i__4 = *nalf; for (ia = 1; ia <= i__4; ++ia) { alpha = alf[ia]; null = n <= 0 || alpha == 0.f; /* Generate the matrix A. */ transl = 0.f; i__5 = n - 1; i__6 = n - 1; smake_(sname + 1, uplo, " ", &n, &n, &a[a_offset], nmax, &aa[1], &lda, &i__5, &i__6, &reset, & transl, (ftnlen)2, (ftnlen)1, (ftnlen)1); ++nc; /* Save every datum before calling the subroutine. */ *(unsigned char *)uplos = *(unsigned char *)uplo; ns = n; als = alpha; i__5 = laa; for (i__ = 1; i__ <= i__5; ++i__) { as[i__] = aa[i__]; /* L10: */ } ldas = lda; i__5 = lx; for (i__ = 1; i__ <= i__5; ++i__) { xs[i__] = xx[i__]; /* L20: */ } incxs = incx; i__5 = ly; for (i__ = 1; i__ <= i__5; ++i__) { ys[i__] = yy[i__]; /* L30: */ } incys = incy; /* Call the subroutine. */ if (full) { if (*trace) { io___373.ciunit = *ntra; s_wsfe(&io___373); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof( integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&alpha, (ftnlen)sizeof( real)); do_fio(&c__1, (char *)&incx, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&incy, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&lda, (ftnlen)sizeof( integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } ssyr2_(uplo, &n, &alpha, &xx[1], &incx, &yy[1], & incy, &aa[1], &lda, (ftnlen)1); } else if (packed) { if (*trace) { io___374.ciunit = *ntra; s_wsfe(&io___374); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof( integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&alpha, (ftnlen)sizeof( real)); do_fio(&c__1, (char *)&incx, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&incy, (ftnlen)sizeof( integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } sspr2_(uplo, &n, &alpha, &xx[1], &incx, &yy[1], & incy, &aa[1], (ftnlen)1); } /* Check if error-exit was taken incorrectly. */ if (! infoc_1.ok) { io___375.ciunit = *nout; s_wsfe(&io___375); e_wsfe(); *fatal = TRUE_; goto L160; } /* See what data changed inside subroutines. */ isame[0] = *(unsigned char *)uplo == *(unsigned char * )uplos; isame[1] = ns == n; isame[2] = als == alpha; isame[3] = lse_(&xs[1], &xx[1], &lx); isame[4] = incxs == incx; isame[5] = lse_(&ys[1], &yy[1], &ly); isame[6] = incys == incy; if (null) { isame[7] = lse_(&as[1], &aa[1], &laa); } else { isame[7] = lseres_(sname + 1, uplo, &n, &n, &as[1] , &aa[1], &lda, (ftnlen)2, (ftnlen)1); } if (! packed) { isame[8] = ldas == lda; } /* If data was incorrectly changed, report and return. */ same = TRUE_; i__5 = nargs; for (i__ = 1; i__ <= i__5; ++i__) { same = same && isame[i__ - 1]; if (! isame[i__ - 1]) { io___378.ciunit = *nout; s_wsfe(&io___378); do_fio(&c__1, (char *)&i__, (ftnlen)sizeof( integer)); e_wsfe(); } /* L40: */ } if (! same) { *fatal = TRUE_; goto L160; } if (! null) { /* Check the result column by column. */ if (incx > 0) { i__5 = n; for (i__ = 1; i__ <= i__5; ++i__) { z__[i__ + z_dim1] = x[i__]; /* L50: */ } } else { i__5 = n; for (i__ = 1; i__ <= i__5; ++i__) { z__[i__ + z_dim1] = x[n - i__ + 1]; /* L60: */ } } if (incy > 0) { i__5 = n; for (i__ = 1; i__ <= i__5; ++i__) { z__[i__ + (z_dim1 << 1)] = y[i__]; /* L70: */ } } else { i__5 = n; for (i__ = 1; i__ <= i__5; ++i__) { z__[i__ + (z_dim1 << 1)] = y[n - i__ + 1]; /* L80: */ } } ja = 1; i__5 = n; for (j = 1; j <= i__5; ++j) { w[0] = z__[j + (z_dim1 << 1)]; w[1] = z__[j + z_dim1]; if (upper) { jj = 1; lj = j; } else { jj = j; lj = n - j + 1; } smvch_("N", &lj, &c__2, &alpha, &z__[jj + z_dim1], nmax, w, &c__1, &c_b128, &a[ jj + j * a_dim1], &c__1, &yt[1], &g[1] , &aa[ja], eps, &err, fatal, nout, & c_true, (ftnlen)1); if (full) { if (upper) { ja += lda; } else { ja = ja + lda + 1; } } else { ja += lj; } errmax = max(errmax,err); /* If got really bad answer, report and return. */ if (*fatal) { goto L150; } /* L90: */ } } else { /* Avoid repeating tests with N.le.0. */ if (n <= 0) { goto L140; } } /* L100: */ } /* L110: */ } /* L120: */ } /* L130: */ } L140: ; } /* Report result. */ if (errmax < *thresh) { io___385.ciunit = *nout; s_wsfe(&io___385); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); e_wsfe(); } else { io___386.ciunit = *nout; s_wsfe(&io___386); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&errmax, (ftnlen)sizeof(real)); e_wsfe(); } goto L170; L150: io___387.ciunit = *nout; s_wsfe(&io___387); do_fio(&c__1, (char *)&j, (ftnlen)sizeof(integer)); e_wsfe(); L160: io___388.ciunit = *nout; s_wsfe(&io___388); do_fio(&c__1, sname, (ftnlen)6); e_wsfe(); if (full) { io___389.ciunit = *nout; s_wsfe(&io___389); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&alpha, (ftnlen)sizeof(real)); do_fio(&c__1, (char *)&incx, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&incy, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&lda, (ftnlen)sizeof(integer)); e_wsfe(); } else if (packed) { io___390.ciunit = *nout; s_wsfe(&io___390); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&alpha, (ftnlen)sizeof(real)); do_fio(&c__1, (char *)&incx, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&incy, (ftnlen)sizeof(integer)); e_wsfe(); } L170: return 0; /* End of SCHK6. */ } /* schk6_ */ /* Subroutine */ int schke_(integer *isnum, char *srnamt, integer *nout, ftnlen srnamt_len) { /* Format strings */ static char fmt_9999[] = "(\002 \002,a6,\002 PASSED THE TESTS OF ERROR-E" "XITS\002)"; static char fmt_9998[] = "(\002 ******* \002,a6,\002 FAILED THE TESTS OF" " ERROR-EXITS *****\002,\002**\002)"; /* Builtin functions */ integer s_wsfe(cilist *), do_fio(integer *, char *, ftnlen), e_wsfe(void); /* Local variables */ real a[1] /* was [1][1] */, x[1], y[1], beta; extern /* Subroutine */ int sger_(integer *, integer *, real *, real *, integer *, real *, integer *, real *, integer *), sspr_(char *, integer *, real *, real *, integer *, real *, ftnlen), ssyr_(char *, integer *, real *, real *, integer *, real *, integer *, ftnlen), sspr2_(char *, integer *, real *, real *, integer *, real *, integer *, real *, ftnlen), ssyr2_(char *, integer *, real *, real *, integer *, real *, integer *, real *, integer *, ftnlen); real alpha; extern /* Subroutine */ int sgbmv_(char *, integer *, integer *, integer * , integer *, real *, real *, integer *, real *, integer *, real *, real *, integer *, ftnlen), sgemv_(char *, integer *, integer *, real *, real *, integer *, real *, integer *, real *, real *, integer *, ftnlen), ssbmv_(char *, integer *, integer *, real *, real *, integer *, real *, integer *, real *, real *, integer *, ftnlen), stbmv_(char *, char *, char *, integer *, integer *, real *, integer *, real *, integer *, ftnlen, ftnlen, ftnlen), stbsv_(char *, char *, char *, integer *, integer *, real *, integer *, real *, integer *, ftnlen, ftnlen, ftnlen), sspmv_( char *, integer *, real *, real *, real *, integer *, real *, real *, integer *, ftnlen), stpmv_(char *, char *, char *, integer *, real *, real *, integer *, ftnlen, ftnlen, ftnlen), strmv_(char *, char *, char *, integer *, real *, integer *, real *, integer *, ftnlen, ftnlen, ftnlen), stpsv_(char *, char *, char *, integer *, real *, real *, integer *, ftnlen, ftnlen, ftnlen), ssymv_(char *, integer *, real *, real *, integer *, real *, integer *, real *, real *, integer *, ftnlen), strsv_( char *, char *, char *, integer *, real *, integer *, real *, integer *, ftnlen, ftnlen, ftnlen), chkxer_(char *, integer *, integer *, logical *, logical *, ftnlen); /* Fortran I/O blocks */ static cilist io___396 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___397 = { 0, 0, 0, fmt_9998, 0 }; /* Tests the error exits from the Level 2 Blas. */ /* Requires a special version of the error-handling routine XERBLA. */ /* ALPHA, BETA, A, X and Y should not need to be defined. */ /* Auxiliary routine for test program for Level 2 Blas. */ /* -- Written on 10-August-1987. */ /* Richard Hanson, Sandia National Labs. */ /* Jeremy Du Croz, NAG Central Office. */ /* .. Scalar Arguments .. */ /* .. Scalars in Common .. */ /* .. Local Scalars .. */ /* .. Local Arrays .. */ /* .. External Subroutines .. */ /* .. Common blocks .. */ /* .. Executable Statements .. */ /* OK is set to .FALSE. by the special version of XERBLA or by CHKXER */ /* if anything is wrong. */ infoc_1.ok = TRUE_; /* LERR is set to .TRUE. by the special version of XERBLA each time */ /* it is called, and is then tested and re-set by CHKXER. */ infoc_1.lerr = FALSE_; switch (*isnum) { case 1: goto L10; case 2: goto L20; case 3: goto L30; case 4: goto L40; case 5: goto L50; case 6: goto L60; case 7: goto L70; case 8: goto L80; case 9: goto L90; case 10: goto L100; case 11: goto L110; case 12: goto L120; case 13: goto L130; case 14: goto L140; case 15: goto L150; case 16: goto L160; } L10: infoc_1.infot = 1; sgemv_("/", &c__0, &c__0, &alpha, a, &c__1, x, &c__1, &beta, y, &c__1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; sgemv_("N", &c_n1, &c__0, &alpha, a, &c__1, x, &c__1, &beta, y, &c__1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; sgemv_("N", &c__0, &c_n1, &alpha, a, &c__1, x, &c__1, &beta, y, &c__1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; sgemv_("N", &c__2, &c__0, &alpha, a, &c__1, x, &c__1, &beta, y, &c__1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 8; sgemv_("N", &c__0, &c__0, &alpha, a, &c__1, x, &c__0, &beta, y, &c__1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; sgemv_("N", &c__0, &c__0, &alpha, a, &c__1, x, &c__1, &beta, y, &c__0, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L170; L20: infoc_1.infot = 1; sgbmv_("/", &c__0, &c__0, &c__0, &c__0, &alpha, a, &c__1, x, &c__1, &beta, y, &c__1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; sgbmv_("N", &c_n1, &c__0, &c__0, &c__0, &alpha, a, &c__1, x, &c__1, &beta, y, &c__1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; sgbmv_("N", &c__0, &c_n1, &c__0, &c__0, &alpha, a, &c__1, x, &c__1, &beta, y, &c__1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; sgbmv_("N", &c__0, &c__0, &c_n1, &c__0, &alpha, a, &c__1, x, &c__1, &beta, y, &c__1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; sgbmv_("N", &c__2, &c__0, &c__0, &c_n1, &alpha, a, &c__1, x, &c__1, &beta, y, &c__1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 8; sgbmv_("N", &c__0, &c__0, &c__1, &c__0, &alpha, a, &c__1, x, &c__1, &beta, y, &c__1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 10; sgbmv_("N", &c__0, &c__0, &c__0, &c__0, &alpha, a, &c__1, x, &c__0, &beta, y, &c__1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 13; sgbmv_("N", &c__0, &c__0, &c__0, &c__0, &alpha, a, &c__1, x, &c__1, &beta, y, &c__0, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L170; L30: infoc_1.infot = 1; ssymv_("/", &c__0, &alpha, a, &c__1, x, &c__1, &beta, y, &c__1, (ftnlen)1) ; chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; ssymv_("U", &c_n1, &alpha, a, &c__1, x, &c__1, &beta, y, &c__1, (ftnlen)1) ; chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; ssymv_("U", &c__2, &alpha, a, &c__1, x, &c__1, &beta, y, &c__1, (ftnlen)1) ; chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; ssymv_("U", &c__0, &alpha, a, &c__1, x, &c__0, &beta, y, &c__1, (ftnlen)1) ; chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 10; ssymv_("U", &c__0, &alpha, a, &c__1, x, &c__1, &beta, y, &c__0, (ftnlen)1) ; chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L170; L40: infoc_1.infot = 1; ssbmv_("/", &c__0, &c__0, &alpha, a, &c__1, x, &c__1, &beta, y, &c__1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; ssbmv_("U", &c_n1, &c__0, &alpha, a, &c__1, x, &c__1, &beta, y, &c__1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; ssbmv_("U", &c__0, &c_n1, &alpha, a, &c__1, x, &c__1, &beta, y, &c__1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; ssbmv_("U", &c__0, &c__1, &alpha, a, &c__1, x, &c__1, &beta, y, &c__1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 8; ssbmv_("U", &c__0, &c__0, &alpha, a, &c__1, x, &c__0, &beta, y, &c__1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; ssbmv_("U", &c__0, &c__0, &alpha, a, &c__1, x, &c__1, &beta, y, &c__0, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L170; L50: infoc_1.infot = 1; sspmv_("/", &c__0, &alpha, a, x, &c__1, &beta, y, &c__1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; sspmv_("U", &c_n1, &alpha, a, x, &c__1, &beta, y, &c__1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; sspmv_("U", &c__0, &alpha, a, x, &c__0, &beta, y, &c__1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; sspmv_("U", &c__0, &alpha, a, x, &c__1, &beta, y, &c__0, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L170; L60: infoc_1.infot = 1; strmv_("/", "N", "N", &c__0, a, &c__1, x, &c__1, (ftnlen)1, (ftnlen)1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; strmv_("U", "/", "N", &c__0, a, &c__1, x, &c__1, (ftnlen)1, (ftnlen)1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; strmv_("U", "N", "/", &c__0, a, &c__1, x, &c__1, (ftnlen)1, (ftnlen)1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; strmv_("U", "N", "N", &c_n1, a, &c__1, x, &c__1, (ftnlen)1, (ftnlen)1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; strmv_("U", "N", "N", &c__2, a, &c__1, x, &c__1, (ftnlen)1, (ftnlen)1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 8; strmv_("U", "N", "N", &c__0, a, &c__1, x, &c__0, (ftnlen)1, (ftnlen)1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L170; L70: infoc_1.infot = 1; stbmv_("/", "N", "N", &c__0, &c__0, a, &c__1, x, &c__1, (ftnlen)1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; stbmv_("U", "/", "N", &c__0, &c__0, a, &c__1, x, &c__1, (ftnlen)1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; stbmv_("U", "N", "/", &c__0, &c__0, a, &c__1, x, &c__1, (ftnlen)1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; stbmv_("U", "N", "N", &c_n1, &c__0, a, &c__1, x, &c__1, (ftnlen)1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; stbmv_("U", "N", "N", &c__0, &c_n1, a, &c__1, x, &c__1, (ftnlen)1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; stbmv_("U", "N", "N", &c__0, &c__1, a, &c__1, x, &c__1, (ftnlen)1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; stbmv_("U", "N", "N", &c__0, &c__0, a, &c__1, x, &c__0, (ftnlen)1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L170; L80: infoc_1.infot = 1; stpmv_("/", "N", "N", &c__0, a, x, &c__1, (ftnlen)1, (ftnlen)1, (ftnlen)1) ; chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; stpmv_("U", "/", "N", &c__0, a, x, &c__1, (ftnlen)1, (ftnlen)1, (ftnlen)1) ; chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; stpmv_("U", "N", "/", &c__0, a, x, &c__1, (ftnlen)1, (ftnlen)1, (ftnlen)1) ; chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; stpmv_("U", "N", "N", &c_n1, a, x, &c__1, (ftnlen)1, (ftnlen)1, (ftnlen)1) ; chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; stpmv_("U", "N", "N", &c__0, a, x, &c__0, (ftnlen)1, (ftnlen)1, (ftnlen)1) ; chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L170; L90: infoc_1.infot = 1; strsv_("/", "N", "N", &c__0, a, &c__1, x, &c__1, (ftnlen)1, (ftnlen)1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; strsv_("U", "/", "N", &c__0, a, &c__1, x, &c__1, (ftnlen)1, (ftnlen)1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; strsv_("U", "N", "/", &c__0, a, &c__1, x, &c__1, (ftnlen)1, (ftnlen)1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; strsv_("U", "N", "N", &c_n1, a, &c__1, x, &c__1, (ftnlen)1, (ftnlen)1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; strsv_("U", "N", "N", &c__2, a, &c__1, x, &c__1, (ftnlen)1, (ftnlen)1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 8; strsv_("U", "N", "N", &c__0, a, &c__1, x, &c__0, (ftnlen)1, (ftnlen)1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L170; L100: infoc_1.infot = 1; stbsv_("/", "N", "N", &c__0, &c__0, a, &c__1, x, &c__1, (ftnlen)1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; stbsv_("U", "/", "N", &c__0, &c__0, a, &c__1, x, &c__1, (ftnlen)1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; stbsv_("U", "N", "/", &c__0, &c__0, a, &c__1, x, &c__1, (ftnlen)1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; stbsv_("U", "N", "N", &c_n1, &c__0, a, &c__1, x, &c__1, (ftnlen)1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; stbsv_("U", "N", "N", &c__0, &c_n1, a, &c__1, x, &c__1, (ftnlen)1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; stbsv_("U", "N", "N", &c__0, &c__1, a, &c__1, x, &c__1, (ftnlen)1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; stbsv_("U", "N", "N", &c__0, &c__0, a, &c__1, x, &c__0, (ftnlen)1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L170; L110: infoc_1.infot = 1; stpsv_("/", "N", "N", &c__0, a, x, &c__1, (ftnlen)1, (ftnlen)1, (ftnlen)1) ; chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; stpsv_("U", "/", "N", &c__0, a, x, &c__1, (ftnlen)1, (ftnlen)1, (ftnlen)1) ; chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; stpsv_("U", "N", "/", &c__0, a, x, &c__1, (ftnlen)1, (ftnlen)1, (ftnlen)1) ; chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; stpsv_("U", "N", "N", &c_n1, a, x, &c__1, (ftnlen)1, (ftnlen)1, (ftnlen)1) ; chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; stpsv_("U", "N", "N", &c__0, a, x, &c__0, (ftnlen)1, (ftnlen)1, (ftnlen)1) ; chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L170; L120: infoc_1.infot = 1; sger_(&c_n1, &c__0, &alpha, x, &c__1, y, &c__1, a, &c__1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; sger_(&c__0, &c_n1, &alpha, x, &c__1, y, &c__1, a, &c__1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; sger_(&c__0, &c__0, &alpha, x, &c__0, y, &c__1, a, &c__1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; sger_(&c__0, &c__0, &alpha, x, &c__1, y, &c__0, a, &c__1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; sger_(&c__2, &c__0, &alpha, x, &c__1, y, &c__1, a, &c__1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L170; L130: infoc_1.infot = 1; ssyr_("/", &c__0, &alpha, x, &c__1, a, &c__1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; ssyr_("U", &c_n1, &alpha, x, &c__1, a, &c__1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; ssyr_("U", &c__0, &alpha, x, &c__0, a, &c__1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; ssyr_("U", &c__2, &alpha, x, &c__1, a, &c__1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L170; L140: infoc_1.infot = 1; sspr_("/", &c__0, &alpha, x, &c__1, a, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; sspr_("U", &c_n1, &alpha, x, &c__1, a, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; sspr_("U", &c__0, &alpha, x, &c__0, a, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L170; L150: infoc_1.infot = 1; ssyr2_("/", &c__0, &alpha, x, &c__1, y, &c__1, a, &c__1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; ssyr2_("U", &c_n1, &alpha, x, &c__1, y, &c__1, a, &c__1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; ssyr2_("U", &c__0, &alpha, x, &c__0, y, &c__1, a, &c__1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; ssyr2_("U", &c__0, &alpha, x, &c__1, y, &c__0, a, &c__1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; ssyr2_("U", &c__2, &alpha, x, &c__1, y, &c__1, a, &c__1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L170; L160: infoc_1.infot = 1; sspr2_("/", &c__0, &alpha, x, &c__1, y, &c__1, a, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; sspr2_("U", &c_n1, &alpha, x, &c__1, y, &c__1, a, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; sspr2_("U", &c__0, &alpha, x, &c__0, y, &c__1, a, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; sspr2_("U", &c__0, &alpha, x, &c__1, y, &c__0, a, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); L170: if (infoc_1.ok) { io___396.ciunit = *nout; s_wsfe(&io___396); do_fio(&c__1, srnamt, (ftnlen)6); e_wsfe(); } else { io___397.ciunit = *nout; s_wsfe(&io___397); do_fio(&c__1, srnamt, (ftnlen)6); e_wsfe(); } return 0; /* End of SCHKE. */ } /* schke_ */ /* Subroutine */ int smake_(char *type__, char *uplo, char *diag, integer *m, integer *n, real *a, integer *nmax, real *aa, integer *lda, integer * kl, integer *ku, logical *reset, real *transl, ftnlen type_len, ftnlen uplo_len, ftnlen diag_len) { /* System generated locals */ integer a_dim1, a_offset, i__1, i__2, i__3, i__4; /* Builtin functions */ integer s_cmp(const char *, const char *, ftnlen, ftnlen); /* Local variables */ integer i__, j, i1, i2, i3, kk; logical gen, tri, sym; integer ibeg, iend; extern real sbeg_(logical *); integer ioff; logical unit, lower, upper; /* Generates values for an M by N matrix A within the bandwidth */ /* defined by KL and KU. */ /* Stores the values in the array AA in the data structure required */ /* by the routine, with unwanted elements set to rogue value. */ /* TYPE is 'GE', 'GB', 'SY', 'SB', 'SP', 'TR', 'TB' OR 'TP'. */ /* Auxiliary routine for test program for Level 2 Blas. */ /* -- Written on 10-August-1987. */ /* Richard Hanson, Sandia National Labs. */ /* Jeremy Du Croz, NAG Central Office. */ /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Scalars .. */ /* .. External Functions .. */ /* .. Intrinsic Functions .. */ /* .. Executable Statements .. */ /* Parameter adjustments */ a_dim1 = *nmax; a_offset = 1 + a_dim1; a -= a_offset; --aa; /* Function Body */ gen = *(unsigned char *)type__ == 'G'; sym = *(unsigned char *)type__ == 'S'; tri = *(unsigned char *)type__ == 'T'; upper = (sym || tri) && *(unsigned char *)uplo == 'U'; lower = (sym || tri) && *(unsigned char *)uplo == 'L'; unit = tri && *(unsigned char *)diag == 'U'; /* Generate data in array A. */ i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = *m; for (i__ = 1; i__ <= i__2; ++i__) { if (gen || upper && i__ <= j || lower && i__ >= j) { if (i__ <= j && j - i__ <= *ku || i__ >= j && i__ - j <= *kl) { a[i__ + j * a_dim1] = sbeg_(reset) + *transl; } else { a[i__ + j * a_dim1] = 0.f; } if (i__ != j) { if (sym) { a[j + i__ * a_dim1] = a[i__ + j * a_dim1]; } else if (tri) { a[j + i__ * a_dim1] = 0.f; } } } /* L10: */ } if (tri) { a[j + j * a_dim1] += 1.f; } if (unit) { a[j + j * a_dim1] = 1.f; } /* L20: */ } /* Store elements in array AS in data structure required by routine. */ if (s_cmp(type__, "GE", (ftnlen)2, (ftnlen)2) == 0) { i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = *m; for (i__ = 1; i__ <= i__2; ++i__) { aa[i__ + (j - 1) * *lda] = a[i__ + j * a_dim1]; /* L30: */ } i__2 = *lda; for (i__ = *m + 1; i__ <= i__2; ++i__) { aa[i__ + (j - 1) * *lda] = -1e10f; /* L40: */ } /* L50: */ } } else if (s_cmp(type__, "GB", (ftnlen)2, (ftnlen)2) == 0) { i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = *ku + 1 - j; for (i1 = 1; i1 <= i__2; ++i1) { aa[i1 + (j - 1) * *lda] = -1e10f; /* L60: */ } /* Computing MIN */ i__3 = *kl + *ku + 1, i__4 = *ku + 1 + *m - j; i__2 = min(i__3,i__4); for (i2 = i1; i2 <= i__2; ++i2) { aa[i2 + (j - 1) * *lda] = a[i2 + j - *ku - 1 + j * a_dim1]; /* L70: */ } i__2 = *lda; for (i3 = i2; i3 <= i__2; ++i3) { aa[i3 + (j - 1) * *lda] = -1e10f; /* L80: */ } /* L90: */ } } else if (s_cmp(type__, "SY", (ftnlen)2, (ftnlen)2) == 0 || s_cmp(type__, "TR", (ftnlen)2, (ftnlen)2) == 0) { i__1 = *n; for (j = 1; j <= i__1; ++j) { if (upper) { ibeg = 1; if (unit) { iend = j - 1; } else { iend = j; } } else { if (unit) { ibeg = j + 1; } else { ibeg = j; } iend = *n; } i__2 = ibeg - 1; for (i__ = 1; i__ <= i__2; ++i__) { aa[i__ + (j - 1) * *lda] = -1e10f; /* L100: */ } i__2 = iend; for (i__ = ibeg; i__ <= i__2; ++i__) { aa[i__ + (j - 1) * *lda] = a[i__ + j * a_dim1]; /* L110: */ } i__2 = *lda; for (i__ = iend + 1; i__ <= i__2; ++i__) { aa[i__ + (j - 1) * *lda] = -1e10f; /* L120: */ } /* L130: */ } } else if (s_cmp(type__, "SB", (ftnlen)2, (ftnlen)2) == 0 || s_cmp(type__, "TB", (ftnlen)2, (ftnlen)2) == 0) { i__1 = *n; for (j = 1; j <= i__1; ++j) { if (upper) { kk = *kl + 1; /* Computing MAX */ i__2 = 1, i__3 = *kl + 2 - j; ibeg = max(i__2,i__3); if (unit) { iend = *kl; } else { iend = *kl + 1; } } else { kk = 1; if (unit) { ibeg = 2; } else { ibeg = 1; } /* Computing MIN */ i__2 = *kl + 1, i__3 = *m + 1 - j; iend = min(i__2,i__3); } i__2 = ibeg - 1; for (i__ = 1; i__ <= i__2; ++i__) { aa[i__ + (j - 1) * *lda] = -1e10f; /* L140: */ } i__2 = iend; for (i__ = ibeg; i__ <= i__2; ++i__) { aa[i__ + (j - 1) * *lda] = a[i__ + j - kk + j * a_dim1]; /* L150: */ } i__2 = *lda; for (i__ = iend + 1; i__ <= i__2; ++i__) { aa[i__ + (j - 1) * *lda] = -1e10f; /* L160: */ } /* L170: */ } } else if (s_cmp(type__, "SP", (ftnlen)2, (ftnlen)2) == 0 || s_cmp(type__, "TP", (ftnlen)2, (ftnlen)2) == 0) { ioff = 0; i__1 = *n; for (j = 1; j <= i__1; ++j) { if (upper) { ibeg = 1; iend = j; } else { ibeg = j; iend = *n; } i__2 = iend; for (i__ = ibeg; i__ <= i__2; ++i__) { ++ioff; aa[ioff] = a[i__ + j * a_dim1]; if (i__ == j) { if (unit) { aa[ioff] = -1e10f; } } /* L180: */ } /* L190: */ } } return 0; /* End of SMAKE. */ } /* smake_ */ /* Subroutine */ int smvch_(char *trans, integer *m, integer *n, real *alpha, real *a, integer *nmax, real *x, integer *incx, real *beta, real *y, integer *incy, real *yt, real *g, real *yy, real *eps, real *err, logical *fatal, integer *nout, logical *mv, ftnlen trans_len) { /* Format strings */ static char fmt_9999[] = "(\002 ******* FATAL ERROR - COMPUTED RESULT IS" " LESS THAN HAL\002,\002F ACCURATE *******\002,/\002 EX" "PECTED RESULT COMPU\002,\002TED RESULT\002)"; static char fmt_9998[] = "(1x,i7,2g18.6)"; /* System generated locals */ integer a_dim1, a_offset, i__1, i__2; real r__1; /* Builtin functions */ double sqrt(doublereal); integer s_wsfe(cilist *), e_wsfe(void), do_fio(integer *, char *, ftnlen); /* Local variables */ integer i__, j, ml, nl, iy, jx, kx, ky; real erri; logical tran; integer incxl, incyl; /* Fortran I/O blocks */ static cilist io___425 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___426 = { 0, 0, 0, fmt_9998, 0 }; static cilist io___427 = { 0, 0, 0, fmt_9998, 0 }; /* Checks the results of the computational tests. */ /* Auxiliary routine for test program for Level 2 Blas. */ /* -- Written on 10-August-1987. */ /* Richard Hanson, Sandia National Labs. */ /* Jeremy Du Croz, NAG Central Office. */ /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Scalars .. */ /* .. Intrinsic Functions .. */ /* .. Executable Statements .. */ /* Parameter adjustments */ a_dim1 = *nmax; a_offset = 1 + a_dim1; a -= a_offset; --x; --y; --yt; --g; --yy; /* Function Body */ tran = *(unsigned char *)trans == 'T' || *(unsigned char *)trans == 'C'; if (tran) { ml = *n; nl = *m; } else { ml = *m; nl = *n; } if (*incx < 0) { kx = nl; incxl = -1; } else { kx = 1; incxl = 1; } if (*incy < 0) { ky = ml; incyl = -1; } else { ky = 1; incyl = 1; } /* Compute expected result in YT using data in A, X and Y. */ /* Compute gauges in G. */ iy = ky; i__1 = ml; for (i__ = 1; i__ <= i__1; ++i__) { yt[iy] = 0.f; g[iy] = 0.f; jx = kx; if (tran) { i__2 = nl; for (j = 1; j <= i__2; ++j) { yt[iy] += a[j + i__ * a_dim1] * x[jx]; g[iy] += (r__1 = a[j + i__ * a_dim1] * x[jx], abs(r__1)); jx += incxl; /* L10: */ } } else { i__2 = nl; for (j = 1; j <= i__2; ++j) { yt[iy] += a[i__ + j * a_dim1] * x[jx]; g[iy] += (r__1 = a[i__ + j * a_dim1] * x[jx], abs(r__1)); jx += incxl; /* L20: */ } } yt[iy] = *alpha * yt[iy] + *beta * y[iy]; g[iy] = abs(*alpha) * g[iy] + (r__1 = *beta * y[iy], abs(r__1)); iy += incyl; /* L30: */ } /* Compute the error ratio for this result. */ *err = 0.f; i__1 = ml; for (i__ = 1; i__ <= i__1; ++i__) { erri = (r__1 = yt[i__] - yy[(i__ - 1) * abs(*incy) + 1], abs(r__1)) / *eps; if (g[i__] != 0.f) { erri /= g[i__]; } *err = max(*err,erri); if (*err * sqrt(*eps) >= 1.f) { goto L50; } /* L40: */ } /* If the loop completes, all results are at least half accurate. */ goto L70; /* Report fatal error. */ L50: *fatal = TRUE_; io___425.ciunit = *nout; s_wsfe(&io___425); e_wsfe(); i__1 = ml; for (i__ = 1; i__ <= i__1; ++i__) { if (*mv) { io___426.ciunit = *nout; s_wsfe(&io___426); do_fio(&c__1, (char *)&i__, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&yt[i__], (ftnlen)sizeof(real)); do_fio(&c__1, (char *)&yy[(i__ - 1) * abs(*incy) + 1], (ftnlen) sizeof(real)); e_wsfe(); } else { io___427.ciunit = *nout; s_wsfe(&io___427); do_fio(&c__1, (char *)&i__, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&yy[(i__ - 1) * abs(*incy) + 1], (ftnlen) sizeof(real)); do_fio(&c__1, (char *)&yt[i__], (ftnlen)sizeof(real)); e_wsfe(); } /* L60: */ } L70: return 0; /* End of SMVCH. */ } /* smvch_ */ logical lse_(real *ri, real *rj, integer *lr) { /* System generated locals */ integer i__1; logical ret_val; /* Local variables */ integer i__; /* Tests if two arrays are identical. */ /* Auxiliary routine for test program for Level 2 Blas. */ /* -- Written on 10-August-1987. */ /* Richard Hanson, Sandia National Labs. */ /* Jeremy Du Croz, NAG Central Office. */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Scalars .. */ /* .. Executable Statements .. */ /* Parameter adjustments */ --rj; --ri; /* Function Body */ i__1 = *lr; for (i__ = 1; i__ <= i__1; ++i__) { if (ri[i__] != rj[i__]) { goto L20; } /* L10: */ } ret_val = TRUE_; goto L30; L20: ret_val = FALSE_; L30: return ret_val; /* End of LSE. */ } /* lse_ */ logical lseres_(char *type__, char *uplo, integer *m, integer *n, real *aa, real *as, integer *lda, ftnlen type_len, ftnlen uplo_len) { /* System generated locals */ integer aa_dim1, aa_offset, as_dim1, as_offset, i__1, i__2; logical ret_val; /* Builtin functions */ integer s_cmp(const char *, const char *, ftnlen, ftnlen); /* Local variables */ integer i__, j, ibeg, iend; logical upper; /* Tests if selected elements in two arrays are equal. */ /* TYPE is 'GE', 'SY' or 'SP'. */ /* Auxiliary routine for test program for Level 2 Blas. */ /* -- Written on 10-August-1987. */ /* Richard Hanson, Sandia National Labs. */ /* Jeremy Du Croz, NAG Central Office. */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Scalars .. */ /* .. Executable Statements .. */ /* Parameter adjustments */ as_dim1 = *lda; as_offset = 1 + as_dim1; as -= as_offset; aa_dim1 = *lda; aa_offset = 1 + aa_dim1; aa -= aa_offset; /* Function Body */ upper = *(unsigned char *)uplo == 'U'; if (s_cmp(type__, "GE", (ftnlen)2, (ftnlen)2) == 0) { i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = *lda; for (i__ = *m + 1; i__ <= i__2; ++i__) { if (aa[i__ + j * aa_dim1] != as[i__ + j * as_dim1]) { goto L70; } /* L10: */ } /* L20: */ } } else if (s_cmp(type__, "SY", (ftnlen)2, (ftnlen)2) == 0) { i__1 = *n; for (j = 1; j <= i__1; ++j) { if (upper) { ibeg = 1; iend = j; } else { ibeg = j; iend = *n; } i__2 = ibeg - 1; for (i__ = 1; i__ <= i__2; ++i__) { if (aa[i__ + j * aa_dim1] != as[i__ + j * as_dim1]) { goto L70; } /* L30: */ } i__2 = *lda; for (i__ = iend + 1; i__ <= i__2; ++i__) { if (aa[i__ + j * aa_dim1] != as[i__ + j * as_dim1]) { goto L70; } /* L40: */ } /* L50: */ } } ret_val = TRUE_; goto L80; L70: ret_val = FALSE_; L80: return ret_val; /* End of LSERES. */ } /* lseres_ */ real sbeg_(logical *reset) { /* System generated locals */ real ret_val; /* Local variables */ static integer i__, ic, mi; /* Generates random numbers uniformly distributed between -0.5 and 0.5. */ /* Auxiliary routine for test program for Level 2 Blas. */ /* -- Written on 10-August-1987. */ /* Richard Hanson, Sandia National Labs. */ /* Jeremy Du Croz, NAG Central Office. */ /* .. Scalar Arguments .. */ /* .. Local Scalars .. */ /* .. Save statement .. */ /* .. Intrinsic Functions .. */ /* .. Executable Statements .. */ if (*reset) { /* Initialize local variables. */ mi = 891; i__ = 7; ic = 0; *reset = FALSE_; } /* The sequence of values of I is bounded between 1 and 999. */ /* If initial I = 1,2,3,6,7 or 9, the period will be 50. */ /* If initial I = 4 or 8, the period will be 25. */ /* If initial I = 5, the period will be 10. */ /* IC is used to break up the period by skipping 1 value of I in 6. */ ++ic; L10: i__ *= mi; i__ -= i__ / 1000 * 1000; if (ic >= 5) { ic = 0; goto L10; } ret_val = (real) (i__ - 500) / 1001.f; return ret_val; /* End of SBEG. */ } /* sbeg_ */ real sdiff_(real *x, real *y) { /* System generated locals */ real ret_val; /* Auxiliary routine for test program for Level 2 Blas. */ /* -- Written on 10-August-1987. */ /* Richard Hanson, Sandia National Labs. */ /* .. Scalar Arguments .. */ /* .. Executable Statements .. */ ret_val = *x - *y; return ret_val; /* End of SDIFF. */ } /* sdiff_ */ /* Subroutine */ int chkxer_(char *srnamt, integer *infot, integer *nout, logical *lerr, logical *ok, ftnlen srnamt_len) { /* Format strings */ static char fmt_9999[] = "(\002 ***** ILLEGAL VALUE OF PARAMETER NUMBER" " \002,i2,\002 NOT D\002,\002ETECTED BY \002,a6,\002 *****\002)"; /* Builtin functions */ integer s_wsfe(cilist *), do_fio(integer *, char *, ftnlen), e_wsfe(void); /* Fortran I/O blocks */ static cilist io___437 = { 0, 0, 0, fmt_9999, 0 }; /* Tests whether XERBLA has detected an error when it should. */ /* Auxiliary routine for test program for Level 2 Blas. */ /* -- Written on 10-August-1987. */ /* Richard Hanson, Sandia National Labs. */ /* Jeremy Du Croz, NAG Central Office. */ /* .. Scalar Arguments .. */ /* .. Executable Statements .. */ if (! (*lerr)) { io___437.ciunit = *nout; s_wsfe(&io___437); do_fio(&c__1, (char *)&(*infot), (ftnlen)sizeof(integer)); do_fio(&c__1, srnamt, (ftnlen)6); e_wsfe(); *ok = FALSE_; } *lerr = FALSE_; return 0; /* End of CHKXER. */ } /* chkxer_ */ /* Subroutine */ int xerbla_(char *srname, integer *info, ftnlen srname_len) { /* Format strings */ static char fmt_9999[] = "(\002 ******* XERBLA WAS CALLED WITH INFO =" " \002,i6,\002 INSTEAD\002,\002 OF \002,i2,\002 *******\002)"; static char fmt_9997[] = "(\002 ******* XERBLA WAS CALLED WITH INFO =" " \002,i6,\002 *******\002)"; static char fmt_9998[] = "(\002 ******* XERBLA WAS CALLED WITH SRNAME =" " \002,a6,\002 INSTE\002,\002AD OF \002,a6,\002 *******\002)"; /* Builtin functions */ integer s_wsfe(cilist *), do_fio(integer *, char *, ftnlen), e_wsfe(void), s_cmp(const char *, const char *, ftnlen, ftnlen); /* Fortran I/O blocks */ static cilist io___438 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___439 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___440 = { 0, 0, 0, fmt_9998, 0 }; /* This is a special version of XERBLA to be used only as part of */ /* the test program for testing error exits from the Level 2 BLAS */ /* routines. */ /* XERBLA is an error handler for the Level 2 BLAS routines. */ /* It is called by the Level 2 BLAS routines if an input parameter is */ /* invalid. */ /* Auxiliary routine for test program for Level 2 Blas. */ /* -- Written on 10-August-1987. */ /* Richard Hanson, Sandia National Labs. */ /* Jeremy Du Croz, NAG Central Office. */ /* .. Scalar Arguments .. */ /* .. Scalars in Common .. */ /* .. Common blocks .. */ /* .. Executable Statements .. */ infoc_2.lerr = TRUE_; if (*info != infoc_2.infot) { if (infoc_2.infot != 0) { io___438.ciunit = infoc_2.nout; s_wsfe(&io___438); do_fio(&c__1, (char *)&(*info), (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&infoc_2.infot, (ftnlen)sizeof(integer)); e_wsfe(); } else { io___439.ciunit = infoc_2.nout; s_wsfe(&io___439); do_fio(&c__1, (char *)&(*info), (ftnlen)sizeof(integer)); e_wsfe(); } infoc_2.ok = FALSE_; } if (s_cmp(srname, srnamc_1.srnamt, (ftnlen)6, (ftnlen)6) != 0) { io___440.ciunit = infoc_2.nout; s_wsfe(&io___440); do_fio(&c__1, srname, (ftnlen)6); do_fio(&c__1, srnamc_1.srnamt, (ftnlen)6); e_wsfe(); infoc_2.ok = FALSE_; } return 0; /* End of XERBLA */ } /* xerbla_ */ /* Main program alias */ int sblat2_ () { main (); return 0; } blis-0.9.0/blastest/src/sblat3.c000066400000000000000000004311631422157504600164330ustar00rootroot00000000000000/* sblat3.f -- translated by f2c (version 20100827). You must link the resulting object file with libf2c: on Microsoft Windows system, link with libf2c.lib; on Linux or Unix systems, link with .../path/to/libf2c.a -lm or, if you install libf2c.a in a standard place, with -lf2c -lm -- in that order, at the end of the command line, as in cc *.o -lf2c -lm Source for libf2c is in /netlib/f2c/libf2c.zip, e.g., http://www.netlib.org/f2c/libf2c.zip */ #include "f2c.h" /* Common Block Declarations */ union { struct { integer infot, noutc; logical ok, lerr; } _1; struct { integer infot, nout; logical ok, lerr; } _2; } infoc_; #define infoc_1 (infoc_._1) #define infoc_2 (infoc_._2) struct { char srnamt[6]; } srnamc_; #define srnamc_1 srnamc_ /* Table of constant values */ static integer c__9 = 9; static integer c__1 = 1; static integer c__3 = 3; static integer c__8 = 8; static integer c__4 = 4; static integer c__65 = 65; static integer c__7 = 7; static real c_b84 = 0.f; static real c_b94 = 1.f; static logical c_true = TRUE_; static logical c_false = FALSE_; static integer c__0 = 0; static integer c_n1 = -1; static integer c__2 = 2; /* > \brief \b SBLAT3 */ /* =========== DOCUMENTATION =========== */ /* Online html documentation available at */ /* http://www.netlib.org/lapack/explore-html/ */ /* Definition: */ /* =========== */ /* PROGRAM SBLAT3 */ /* > \par Purpose: */ /* ============= */ /* > */ /* > \verbatim */ /* > */ /* > Test program for the REAL Level 3 Blas. */ /* > */ /* > The program must be driven by a short data file. The first 14 records */ /* > of the file are read using list-directed input, the last 6 records */ /* > are read using the format ( A6, L2 ). An annotated example of a data */ /* > file can be obtained by deleting the first 3 characters from the */ /* > following 20 lines: */ /* > 'sblat3.out' NAME OF SUMMARY OUTPUT FILE */ /* > 6 UNIT NUMBER OF SUMMARY FILE */ /* > 'SBLAT3.SNAP' NAME OF SNAPSHOT OUTPUT FILE */ /* > -1 UNIT NUMBER OF SNAPSHOT FILE (NOT USED IF .LT. 0) */ /* > F LOGICAL FLAG, T TO REWIND SNAPSHOT FILE AFTER EACH RECORD. */ /* > F LOGICAL FLAG, T TO STOP ON FAILURES. */ /* > T LOGICAL FLAG, T TO TEST ERROR EXITS. */ /* > 16.0 THRESHOLD VALUE OF TEST RATIO */ /* > 6 NUMBER OF VALUES OF N */ /* > 0 1 2 3 5 9 VALUES OF N */ /* > 3 NUMBER OF VALUES OF ALPHA */ /* > 0.0 1.0 0.7 VALUES OF ALPHA */ /* > 3 NUMBER OF VALUES OF BETA */ /* > 0.0 1.0 1.3 VALUES OF BETA */ /* > SGEMM T PUT F FOR NO TEST. SAME COLUMNS. */ /* > SSYMM T PUT F FOR NO TEST. SAME COLUMNS. */ /* > STRMM T PUT F FOR NO TEST. SAME COLUMNS. */ /* > STRSM T PUT F FOR NO TEST. SAME COLUMNS. */ /* > SSYRK T PUT F FOR NO TEST. SAME COLUMNS. */ /* > SSYR2K T PUT F FOR NO TEST. SAME COLUMNS. */ /* > */ /* > Further Details */ /* > =============== */ /* > */ /* > See: */ /* > */ /* > Dongarra J. J., Du Croz J. J., Duff I. S. and Hammarling S. */ /* > A Set of Level 3 Basic Linear Algebra Subprograms. */ /* > */ /* > Technical Memorandum No.88 (Revision 1), Mathematics and */ /* > Computer Science Division, Argonne National Laboratory, 9700 */ /* > South Cass Avenue, Argonne, Illinois 60439, US. */ /* > */ /* > -- Written on 8-February-1989. */ /* > Jack Dongarra, Argonne National Laboratory. */ /* > Iain Duff, AERE Harwell. */ /* > Jeremy Du Croz, Numerical Algorithms Group Ltd. */ /* > Sven Hammarling, Numerical Algorithms Group Ltd. */ /* > */ /* > 10-9-00: Change STATUS='NEW' to 'UNKNOWN' so that the testers */ /* > can be run multiple times without deleting generated */ /* > output files (susan) */ /* > \endverbatim */ /* Authors: */ /* ======== */ /* > \author Univ. of Tennessee */ /* > \author Univ. of California Berkeley */ /* > \author Univ. of Colorado Denver */ /* > \author NAG Ltd. */ /* > \date April 2012 */ /* > \ingroup single_blas_testing */ /* ===================================================================== */ /* Main program */ int main(void) { /* Initialized data */ static char snames[6*6] = "SGEMM " "SSYMM " "STRMM " "STRSM " "SSYRK " "SSYR2K"; /* Format strings */ static char fmt_9997[] = "(\002 NUMBER OF VALUES OF \002,a,\002 IS LESS " "THAN 1 OR GREATER \002,\002THAN \002,i2)"; static char fmt_9996[] = "(\002 VALUE OF N IS LESS THAN 0 OR GREATER THA" "N \002,i2)"; static char fmt_9995[] = "(\002 TESTS OF THE REAL LEVEL 3 BL" "AS\002,//\002 THE F\002,\002OLLOWING PARAMETER VALUES WILL BE US" "ED:\002)"; static char fmt_9994[] = "(\002 FOR N \002,9i6)"; static char fmt_9993[] = "(\002 FOR ALPHA \002,7f6.1)"; static char fmt_9992[] = "(\002 FOR BETA \002,7f6.1)"; static char fmt_9984[] = "(\002 ERROR-EXITS WILL NOT BE TESTED\002)"; static char fmt_9999[] = "(\002 ROUTINES PASS COMPUTATIONAL TESTS IF TES" "T RATIO IS LES\002,\002S THAN\002,f8.2)"; static char fmt_9988[] = "(a6,l2)"; static char fmt_9990[] = "(\002 SUBPROGRAM NAME \002,a6,\002 NOT RECOGNI" "ZED\002,/\002 ******* T\002,\002ESTS ABANDONED *******\002)"; static char fmt_9998[] = "(\002 RELATIVE MACHINE PRECISION IS TAKEN TO" " BE\002,1p,e9.1)"; static char fmt_9989[] = "(\002 ERROR IN SMMCH - IN-LINE DOT PRODUCTS A" "RE BEING EVALU\002,\002ATED WRONGLY.\002,/\002 SMMCH WAS CALLED " "WITH TRANSA = \002,a1,\002 AND TRANSB = \002,a1,/\002 AND RETURN" "ED SAME = \002,l1,\002 AND \002,\002ERR = \002,f12.3,\002.\002," "/\002 THIS MAY BE DUE TO FAULTS IN THE \002,\002ARITHMETIC OR TH" "E COMPILER.\002,/\002 ******* TESTS ABANDONED \002,\002******" "*\002)"; static char fmt_9987[] = "(1x,a6,\002 WAS NOT TESTED\002)"; static char fmt_9986[] = "(/\002 END OF TESTS\002)"; static char fmt_9985[] = "(/\002 ******* FATAL ERROR - TESTS ABANDONED *" "******\002)"; static char fmt_9991[] = "(\002 AMEND DATA FILE OR INCREASE ARRAY SIZES " "IN PROGRAM\002,/\002 ******* TESTS ABANDONED *******\002)"; /* System generated locals */ integer i__1, i__2, i__3; olist o__1; cllist cl__1; /* Builtin functions */ integer s_rsle(cilist *), do_lio(integer *, integer *, char *, ftnlen), e_rsle(void), f_open(olist *), s_wsfe(cilist *), do_fio(integer *, char *, ftnlen), e_wsfe(void), s_wsle(cilist *), e_wsle(void), s_rsfe(cilist *), e_rsfe(void), s_cmp(const char *, const char *, ftnlen, ftnlen); /* Subroutine */ int s_stop(char *, ftnlen); integer f_clos(cllist *); /* Subroutine */ int s_copy(char *, const char *, ftnlen, ftnlen); /* Local variables */ real c__[4225] /* was [65][65] */, g[65]; integer i__, j, n; real w[130], aa[4225], ab[8450] /* was [65][130] */, bb[4225], cc[ 4225], as[4225], bs[4225], cs[4225], ct[65], alf[7], bet[7]; extern logical lse_(real *, real *, integer *); real eps, err; integer nalf, idim[9]; logical same; integer nbet, ntra; logical rewi; integer nout; extern /* Subroutine */ int schk1_(char *, real *, real *, integer *, integer *, logical *, logical *, logical *, integer *, integer *, integer *, real *, integer *, real *, integer *, real *, real *, real *, real *, real *, real *, real *, real *, real *, real *, real *, ftnlen), schk2_(char *, real *, real *, integer *, integer *, logical *, logical *, logical *, integer *, integer *, integer *, real *, integer *, real *, integer *, real *, real *, real *, real *, real *, real *, real *, real *, real *, real *, real *, ftnlen), schk3_(char *, real *, real *, integer *, integer *, logical *, logical *, logical *, integer *, integer *, integer *, real *, integer *, real *, real *, real *, real *, real *, real *, real *, real *, real *, ftnlen), schk4_(char *, real *, real *, integer *, integer *, logical *, logical *, logical *, integer *, integer *, integer *, real *, integer *, real *, integer *, real *, real *, real *, real *, real *, real *, real *, real *, real *, real *, real *, ftnlen), schk5_(char *, real *, real *, integer *, integer *, logical *, logical *, logical *, integer *, integer *, integer *, real *, integer *, real *, integer *, real *, real *, real *, real *, real *, real *, real *, real *, real *, real *, real *, ftnlen); logical fatal; extern /* Subroutine */ int schke_(integer *, char *, integer *, ftnlen); logical trace; integer nidim; extern /* Subroutine */ int smmch_(char *, char *, integer *, integer *, integer *, real *, real *, integer *, real *, integer *, real *, real *, integer *, real *, real *, real *, integer *, real *, real *, logical *, integer *, logical *, ftnlen, ftnlen); char snaps[32]; integer isnum; logical ltest[6], sfatal; char snamet[6], transa[1], transb[1]; real thresh; logical ltestt, tsterr; char summry[32]; extern real s_epsilon_(real *); /* Fortran I/O blocks */ static cilist io___2 = { 0, 5, 0, 0, 0 }; static cilist io___4 = { 0, 5, 0, 0, 0 }; static cilist io___6 = { 0, 5, 0, 0, 0 }; static cilist io___8 = { 0, 5, 0, 0, 0 }; static cilist io___11 = { 0, 5, 0, 0, 0 }; static cilist io___13 = { 0, 5, 0, 0, 0 }; static cilist io___15 = { 0, 5, 0, 0, 0 }; static cilist io___17 = { 0, 5, 0, 0, 0 }; static cilist io___19 = { 0, 5, 0, 0, 0 }; static cilist io___21 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___22 = { 0, 5, 0, 0, 0 }; static cilist io___25 = { 0, 0, 0, fmt_9996, 0 }; static cilist io___26 = { 0, 5, 0, 0, 0 }; static cilist io___28 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___29 = { 0, 5, 0, 0, 0 }; static cilist io___31 = { 0, 5, 0, 0, 0 }; static cilist io___33 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___34 = { 0, 5, 0, 0, 0 }; static cilist io___36 = { 0, 0, 0, fmt_9995, 0 }; static cilist io___37 = { 0, 0, 0, fmt_9994, 0 }; static cilist io___38 = { 0, 0, 0, fmt_9993, 0 }; static cilist io___39 = { 0, 0, 0, fmt_9992, 0 }; static cilist io___40 = { 0, 0, 0, 0, 0 }; static cilist io___41 = { 0, 0, 0, fmt_9984, 0 }; static cilist io___42 = { 0, 0, 0, 0, 0 }; static cilist io___43 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___44 = { 0, 0, 0, 0, 0 }; static cilist io___46 = { 0, 5, 1, fmt_9988, 0 }; static cilist io___49 = { 0, 0, 0, fmt_9990, 0 }; static cilist io___51 = { 0, 0, 0, fmt_9998, 0 }; static cilist io___64 = { 0, 0, 0, fmt_9989, 0 }; static cilist io___65 = { 0, 0, 0, fmt_9989, 0 }; static cilist io___66 = { 0, 0, 0, fmt_9989, 0 }; static cilist io___67 = { 0, 0, 0, fmt_9989, 0 }; static cilist io___69 = { 0, 0, 0, 0, 0 }; static cilist io___70 = { 0, 0, 0, fmt_9987, 0 }; static cilist io___71 = { 0, 0, 0, 0, 0 }; static cilist io___78 = { 0, 0, 0, fmt_9986, 0 }; static cilist io___79 = { 0, 0, 0, fmt_9985, 0 }; static cilist io___80 = { 0, 0, 0, fmt_9991, 0 }; /* -- Reference BLAS test routine (version 3.4.1) -- */ /* -- Reference BLAS is a software package provided by Univ. of Tennessee, -- */ /* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- */ /* April 2012 */ /* ===================================================================== */ /* .. Parameters .. */ /* .. Local Scalars .. */ /* .. Local Arrays .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. Scalars in Common .. */ /* .. Common blocks .. */ /* .. Data statements .. */ /* .. Executable Statements .. */ /* Read name and unit number for summary output file and open file. */ s_rsle(&io___2); do_lio(&c__9, &c__1, summry, (ftnlen)32); e_rsle(); s_rsle(&io___4); do_lio(&c__3, &c__1, (char *)&nout, (ftnlen)sizeof(integer)); e_rsle(); o__1.oerr = 0; o__1.ounit = nout; o__1.ofnmlen = 32; o__1.ofnm = summry; o__1.orl = 0; o__1.osta = 0; o__1.oacc = 0; o__1.ofm = 0; o__1.oblnk = 0; f_open(&o__1); infoc_1.noutc = nout; /* Read name and unit number for snapshot output file and open file. */ s_rsle(&io___6); do_lio(&c__9, &c__1, snaps, (ftnlen)32); e_rsle(); s_rsle(&io___8); do_lio(&c__3, &c__1, (char *)&ntra, (ftnlen)sizeof(integer)); e_rsle(); trace = ntra >= 0; if (trace) { o__1.oerr = 0; o__1.ounit = ntra; o__1.ofnmlen = 32; o__1.ofnm = snaps; o__1.orl = 0; o__1.osta = 0; o__1.oacc = 0; o__1.ofm = 0; o__1.oblnk = 0; f_open(&o__1); } /* Read the flag that directs rewinding of the snapshot file. */ s_rsle(&io___11); do_lio(&c__8, &c__1, (char *)&rewi, (ftnlen)sizeof(logical)); e_rsle(); rewi = rewi && trace; /* Read the flag that directs stopping on any failure. */ s_rsle(&io___13); do_lio(&c__8, &c__1, (char *)&sfatal, (ftnlen)sizeof(logical)); e_rsle(); /* Read the flag that indicates whether error exits are to be tested. */ s_rsle(&io___15); do_lio(&c__8, &c__1, (char *)&tsterr, (ftnlen)sizeof(logical)); e_rsle(); /* Read the threshold value of the test ratio */ s_rsle(&io___17); do_lio(&c__4, &c__1, (char *)&thresh, (ftnlen)sizeof(real)); e_rsle(); /* Read and check the parameter values for the tests. */ /* Values of N */ s_rsle(&io___19); do_lio(&c__3, &c__1, (char *)&nidim, (ftnlen)sizeof(integer)); e_rsle(); if (nidim < 1 || nidim > 9) { io___21.ciunit = nout; s_wsfe(&io___21); do_fio(&c__1, "N", (ftnlen)1); do_fio(&c__1, (char *)&c__9, (ftnlen)sizeof(integer)); e_wsfe(); goto L220; } s_rsle(&io___22); i__1 = nidim; for (i__ = 1; i__ <= i__1; ++i__) { do_lio(&c__3, &c__1, (char *)&idim[i__ - 1], (ftnlen)sizeof(integer)); } e_rsle(); i__1 = nidim; for (i__ = 1; i__ <= i__1; ++i__) { if (idim[i__ - 1] < 0 || idim[i__ - 1] > 65) { io___25.ciunit = nout; s_wsfe(&io___25); do_fio(&c__1, (char *)&c__65, (ftnlen)sizeof(integer)); e_wsfe(); goto L220; } /* L10: */ } /* Values of ALPHA */ s_rsle(&io___26); do_lio(&c__3, &c__1, (char *)&nalf, (ftnlen)sizeof(integer)); e_rsle(); if (nalf < 1 || nalf > 7) { io___28.ciunit = nout; s_wsfe(&io___28); do_fio(&c__1, "ALPHA", (ftnlen)5); do_fio(&c__1, (char *)&c__7, (ftnlen)sizeof(integer)); e_wsfe(); goto L220; } s_rsle(&io___29); i__1 = nalf; for (i__ = 1; i__ <= i__1; ++i__) { do_lio(&c__4, &c__1, (char *)&alf[i__ - 1], (ftnlen)sizeof(real)); } e_rsle(); /* Values of BETA */ s_rsle(&io___31); do_lio(&c__3, &c__1, (char *)&nbet, (ftnlen)sizeof(integer)); e_rsle(); if (nbet < 1 || nbet > 7) { io___33.ciunit = nout; s_wsfe(&io___33); do_fio(&c__1, "BETA", (ftnlen)4); do_fio(&c__1, (char *)&c__7, (ftnlen)sizeof(integer)); e_wsfe(); goto L220; } s_rsle(&io___34); i__1 = nbet; for (i__ = 1; i__ <= i__1; ++i__) { do_lio(&c__4, &c__1, (char *)&bet[i__ - 1], (ftnlen)sizeof(real)); } e_rsle(); /* Report values of parameters. */ io___36.ciunit = nout; s_wsfe(&io___36); e_wsfe(); io___37.ciunit = nout; s_wsfe(&io___37); i__1 = nidim; for (i__ = 1; i__ <= i__1; ++i__) { do_fio(&c__1, (char *)&idim[i__ - 1], (ftnlen)sizeof(integer)); } e_wsfe(); io___38.ciunit = nout; s_wsfe(&io___38); i__1 = nalf; for (i__ = 1; i__ <= i__1; ++i__) { do_fio(&c__1, (char *)&alf[i__ - 1], (ftnlen)sizeof(real)); } e_wsfe(); io___39.ciunit = nout; s_wsfe(&io___39); i__1 = nbet; for (i__ = 1; i__ <= i__1; ++i__) { do_fio(&c__1, (char *)&bet[i__ - 1], (ftnlen)sizeof(real)); } e_wsfe(); if (! tsterr) { io___40.ciunit = nout; s_wsle(&io___40); e_wsle(); io___41.ciunit = nout; s_wsfe(&io___41); e_wsfe(); } io___42.ciunit = nout; s_wsle(&io___42); e_wsle(); io___43.ciunit = nout; s_wsfe(&io___43); do_fio(&c__1, (char *)&thresh, (ftnlen)sizeof(real)); e_wsfe(); io___44.ciunit = nout; s_wsle(&io___44); e_wsle(); /* Read names of subroutines and flags which indicate */ /* whether they are to be tested. */ for (i__ = 1; i__ <= 6; ++i__) { ltest[i__ - 1] = FALSE_; /* L20: */ } L30: i__1 = s_rsfe(&io___46); if (i__1 != 0) { goto L60; } i__1 = do_fio(&c__1, snamet, (ftnlen)6); if (i__1 != 0) { goto L60; } i__1 = do_fio(&c__1, (char *)<estt, (ftnlen)sizeof(logical)); if (i__1 != 0) { goto L60; } i__1 = e_rsfe(); if (i__1 != 0) { goto L60; } for (i__ = 1; i__ <= 6; ++i__) { if (s_cmp(snamet, snames + (i__ - 1) * 6, (ftnlen)6, (ftnlen)6) == 0) { goto L50; } /* L40: */ } io___49.ciunit = nout; s_wsfe(&io___49); do_fio(&c__1, snamet, (ftnlen)6); e_wsfe(); s_stop("", (ftnlen)0); L50: ltest[i__ - 1] = ltestt; goto L30; L60: cl__1.cerr = 0; cl__1.cunit = 5; cl__1.csta = 0; f_clos(&cl__1); /* Compute EPS (the machine precision). */ eps = s_epsilon_(&c_b84); io___51.ciunit = nout; s_wsfe(&io___51); do_fio(&c__1, (char *)&eps, (ftnlen)sizeof(real)); e_wsfe(); /* Check the reliability of SMMCH using exact data. */ n = 32; i__1 = n; for (j = 1; j <= i__1; ++j) { i__2 = n; for (i__ = 1; i__ <= i__2; ++i__) { /* Computing MAX */ i__3 = i__ - j + 1; ab[i__ + j * 65 - 66] = (real) max(i__3,0); /* L90: */ } ab[j + 4224] = (real) j; ab[(j + 65) * 65 - 65] = (real) j; c__[j - 1] = 0.f; /* L100: */ } i__1 = n; for (j = 1; j <= i__1; ++j) { cc[j - 1] = (real) (j * ((j + 1) * j) / 2 - (j + 1) * j * (j - 1) / 3) ; /* L110: */ } /* CC holds the exact result. On exit from SMMCH CT holds */ /* the result computed by SMMCH. */ *(unsigned char *)transa = 'N'; *(unsigned char *)transb = 'N'; smmch_(transa, transb, &n, &c__1, &n, &c_b94, ab, &c__65, &ab[4225], & c__65, &c_b84, c__, &c__65, ct, g, cc, &c__65, &eps, &err, &fatal, &nout, &c_true, (ftnlen)1, (ftnlen)1); same = lse_(cc, ct, &n); if (! same || err != 0.f) { io___64.ciunit = nout; s_wsfe(&io___64); do_fio(&c__1, transa, (ftnlen)1); do_fio(&c__1, transb, (ftnlen)1); do_fio(&c__1, (char *)&same, (ftnlen)sizeof(logical)); do_fio(&c__1, (char *)&err, (ftnlen)sizeof(real)); e_wsfe(); s_stop("", (ftnlen)0); } *(unsigned char *)transb = 'T'; smmch_(transa, transb, &n, &c__1, &n, &c_b94, ab, &c__65, &ab[4225], & c__65, &c_b84, c__, &c__65, ct, g, cc, &c__65, &eps, &err, &fatal, &nout, &c_true, (ftnlen)1, (ftnlen)1); same = lse_(cc, ct, &n); if (! same || err != 0.f) { io___65.ciunit = nout; s_wsfe(&io___65); do_fio(&c__1, transa, (ftnlen)1); do_fio(&c__1, transb, (ftnlen)1); do_fio(&c__1, (char *)&same, (ftnlen)sizeof(logical)); do_fio(&c__1, (char *)&err, (ftnlen)sizeof(real)); e_wsfe(); s_stop("", (ftnlen)0); } i__1 = n; for (j = 1; j <= i__1; ++j) { ab[j + 4224] = (real) (n - j + 1); ab[(j + 65) * 65 - 65] = (real) (n - j + 1); /* L120: */ } i__1 = n; for (j = 1; j <= i__1; ++j) { cc[n - j] = (real) (j * ((j + 1) * j) / 2 - (j + 1) * j * (j - 1) / 3) ; /* L130: */ } *(unsigned char *)transa = 'T'; *(unsigned char *)transb = 'N'; smmch_(transa, transb, &n, &c__1, &n, &c_b94, ab, &c__65, &ab[4225], & c__65, &c_b84, c__, &c__65, ct, g, cc, &c__65, &eps, &err, &fatal, &nout, &c_true, (ftnlen)1, (ftnlen)1); same = lse_(cc, ct, &n); if (! same || err != 0.f) { io___66.ciunit = nout; s_wsfe(&io___66); do_fio(&c__1, transa, (ftnlen)1); do_fio(&c__1, transb, (ftnlen)1); do_fio(&c__1, (char *)&same, (ftnlen)sizeof(logical)); do_fio(&c__1, (char *)&err, (ftnlen)sizeof(real)); e_wsfe(); s_stop("", (ftnlen)0); } *(unsigned char *)transb = 'T'; smmch_(transa, transb, &n, &c__1, &n, &c_b94, ab, &c__65, &ab[4225], & c__65, &c_b84, c__, &c__65, ct, g, cc, &c__65, &eps, &err, &fatal, &nout, &c_true, (ftnlen)1, (ftnlen)1); same = lse_(cc, ct, &n); if (! same || err != 0.f) { io___67.ciunit = nout; s_wsfe(&io___67); do_fio(&c__1, transa, (ftnlen)1); do_fio(&c__1, transb, (ftnlen)1); do_fio(&c__1, (char *)&same, (ftnlen)sizeof(logical)); do_fio(&c__1, (char *)&err, (ftnlen)sizeof(real)); e_wsfe(); s_stop("", (ftnlen)0); } /* Test each subroutine in turn. */ for (isnum = 1; isnum <= 6; ++isnum) { io___69.ciunit = nout; s_wsle(&io___69); e_wsle(); if (! ltest[isnum - 1]) { /* Subprogram is not to be tested. */ io___70.ciunit = nout; s_wsfe(&io___70); do_fio(&c__1, snames + (isnum - 1) * 6, (ftnlen)6); e_wsfe(); } else { s_copy(srnamc_1.srnamt, snames + (isnum - 1) * 6, (ftnlen)6, ( ftnlen)6); /* Test error exits. */ if (tsterr) { schke_(&isnum, snames + (isnum - 1) * 6, &nout, (ftnlen)6); io___71.ciunit = nout; s_wsle(&io___71); e_wsle(); } /* Test computations. */ infoc_1.infot = 0; infoc_1.ok = TRUE_; fatal = FALSE_; switch (isnum) { case 1: goto L140; case 2: goto L150; case 3: goto L160; case 4: goto L160; case 5: goto L170; case 6: goto L180; } /* Test SGEMM, 01. */ L140: schk1_(snames + (isnum - 1) * 6, &eps, &thresh, &nout, &ntra, & trace, &rewi, &fatal, &nidim, idim, &nalf, alf, &nbet, bet, &c__65, ab, aa, as, &ab[4225], bb, bs, c__, cc, cs, ct, g, (ftnlen)6); goto L190; /* Test SSYMM, 02. */ L150: schk2_(snames + (isnum - 1) * 6, &eps, &thresh, &nout, &ntra, & trace, &rewi, &fatal, &nidim, idim, &nalf, alf, &nbet, bet, &c__65, ab, aa, as, &ab[4225], bb, bs, c__, cc, cs, ct, g, (ftnlen)6); goto L190; /* Test STRMM, 03, STRSM, 04. */ L160: schk3_(snames + (isnum - 1) * 6, &eps, &thresh, &nout, &ntra, & trace, &rewi, &fatal, &nidim, idim, &nalf, alf, &c__65, ab, aa, as, &ab[4225], bb, bs, ct, g, c__, (ftnlen)6); goto L190; /* Test SSYRK, 05. */ L170: schk4_(snames + (isnum - 1) * 6, &eps, &thresh, &nout, &ntra, & trace, &rewi, &fatal, &nidim, idim, &nalf, alf, &nbet, bet, &c__65, ab, aa, as, &ab[4225], bb, bs, c__, cc, cs, ct, g, (ftnlen)6); goto L190; /* Test SSYR2K, 06. */ L180: schk5_(snames + (isnum - 1) * 6, &eps, &thresh, &nout, &ntra, & trace, &rewi, &fatal, &nidim, idim, &nalf, alf, &nbet, bet, &c__65, ab, aa, as, bb, bs, c__, cc, cs, ct, g, w, ( ftnlen)6); goto L190; L190: if (fatal && sfatal) { goto L210; } } /* L200: */ } io___78.ciunit = nout; s_wsfe(&io___78); e_wsfe(); goto L230; L210: io___79.ciunit = nout; s_wsfe(&io___79); e_wsfe(); goto L230; L220: io___80.ciunit = nout; s_wsfe(&io___80); e_wsfe(); L230: if (trace) { cl__1.cerr = 0; cl__1.cunit = ntra; cl__1.csta = 0; f_clos(&cl__1); } cl__1.cerr = 0; cl__1.cunit = nout; cl__1.csta = 0; f_clos(&cl__1); s_stop("", (ftnlen)0); /* End of SBLAT3. */ return 0; } /* main */ /* Subroutine */ int schk1_(char *sname, real *eps, real *thresh, integer * nout, integer *ntra, logical *trace, logical *rewi, logical *fatal, integer *nidim, integer *idim, integer *nalf, real *alf, integer * nbet, real *bet, integer *nmax, real *a, real *aa, real *as, real *b, real *bb, real *bs, real *c__, real *cc, real *cs, real *ct, real *g, ftnlen sname_len) { /* Initialized data */ static char ich[3] = "NTC"; /* Format strings */ static char fmt_9995[] = "(1x,i6,\002: \002,a6,\002('\002,a1,\002','\002" ",a1,\002',\002,3(i3,\002,\002),f4.1,\002, A,\002,i3,\002, B,\002" ",i3,\002,\002,f4.1,\002, \002,\002C,\002,i3,\002).\002)"; static char fmt_9994[] = "(\002 ******* FATAL ERROR - ERROR-EXIT TAKEN O" "N VALID CALL *\002,\002******\002)"; static char fmt_9998[] = "(\002 ******* FATAL ERROR - PARAMETER NUMBER" " \002,i2,\002 WAS CH\002,\002ANGED INCORRECTLY *******\002)"; static char fmt_9999[] = "(\002 \002,a6,\002 PASSED THE COMPUTATIONAL TE" "STS (\002,i6,\002 CALL\002,\002S)\002)"; static char fmt_9997[] = "(\002 \002,a6,\002 COMPLETED THE COMPUTATIONAL" " TESTS (\002,i6,\002 C\002,\002ALLS)\002,/\002 ******* BUT WITH " "MAXIMUM TEST RATIO\002,f8.2,\002 - SUSPECT *******\002)"; static char fmt_9996[] = "(\002 ******* \002,a6,\002 FAILED ON CALL NUMB" "ER:\002)"; /* System generated locals */ integer a_dim1, a_offset, b_dim1, b_offset, c_dim1, c_offset, i__1, i__2, i__3, i__4, i__5, i__6; alist al__1; /* Builtin functions */ integer s_wsfe(cilist *), do_fio(integer *, char *, ftnlen), e_wsfe(void), f_rew(alist *); /* Local variables */ integer i__, k, m, n, ia, ib, ma, mb, na, nb, nc, ik, im, in, ks, ms, ns, ica, icb, laa, lbb, lda, lcc, ldb, ldc; real als, bls; extern logical lse_(real *, real *, integer *); real err, beta; integer ldas, ldbs, ldcs; logical same, null; real alpha; logical isame[13]; extern /* Subroutine */ int smake_(char *, char *, char *, integer *, integer *, real *, integer *, real *, integer *, logical *, real * , ftnlen, ftnlen, ftnlen); logical trana, tranb; extern /* Subroutine */ int smmch_(char *, char *, integer *, integer *, integer *, real *, real *, integer *, real *, integer *, real *, real *, integer *, real *, real *, real *, integer *, real *, real *, logical *, integer *, logical *, ftnlen, ftnlen), sgemm_( char *, char *, integer *, integer *, integer *, real *, real *, integer *, real *, integer *, real *, real *, integer *, ftnlen, ftnlen); integer nargs; logical reset; char tranas[1], tranbs[1], transa[1], transb[1]; real errmax; extern logical lseres_(char *, char *, integer *, integer *, real *, real *, integer *, ftnlen, ftnlen); /* Fortran I/O blocks */ static cilist io___124 = { 0, 0, 0, fmt_9995, 0 }; static cilist io___125 = { 0, 0, 0, fmt_9994, 0 }; static cilist io___128 = { 0, 0, 0, fmt_9998, 0 }; static cilist io___130 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___131 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___132 = { 0, 0, 0, fmt_9996, 0 }; static cilist io___133 = { 0, 0, 0, fmt_9995, 0 }; /* Tests SGEMM. */ /* Auxiliary routine for test program for Level 3 Blas. */ /* -- Written on 8-February-1989. */ /* Jack Dongarra, Argonne National Laboratory. */ /* Iain Duff, AERE Harwell. */ /* Jeremy Du Croz, Numerical Algorithms Group Ltd. */ /* Sven Hammarling, Numerical Algorithms Group Ltd. */ /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Scalars .. */ /* .. Local Arrays .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. Scalars in Common .. */ /* .. Common blocks .. */ /* .. Data statements .. */ /* Parameter adjustments */ --idim; --alf; --bet; --g; --ct; --cs; --cc; c_dim1 = *nmax; c_offset = 1 + c_dim1; c__ -= c_offset; --bs; --bb; b_dim1 = *nmax; b_offset = 1 + b_dim1; b -= b_offset; --as; --aa; a_dim1 = *nmax; a_offset = 1 + a_dim1; a -= a_offset; /* Function Body */ /* .. Executable Statements .. */ nargs = 13; nc = 0; reset = TRUE_; errmax = 0.f; i__1 = *nidim; for (im = 1; im <= i__1; ++im) { m = idim[im]; i__2 = *nidim; for (in = 1; in <= i__2; ++in) { n = idim[in]; /* Set LDC to 1 more than minimum value if room. */ ldc = m; if (ldc < *nmax) { ++ldc; } /* Skip tests if not enough room. */ if (ldc > *nmax) { goto L100; } lcc = ldc * n; null = n <= 0 || m <= 0; i__3 = *nidim; for (ik = 1; ik <= i__3; ++ik) { k = idim[ik]; for (ica = 1; ica <= 3; ++ica) { *(unsigned char *)transa = *(unsigned char *)&ich[ica - 1] ; trana = *(unsigned char *)transa == 'T' || *(unsigned char *)transa == 'C'; if (trana) { ma = k; na = m; } else { ma = m; na = k; } /* Set LDA to 1 more than minimum value if room. */ lda = ma; if (lda < *nmax) { ++lda; } /* Skip tests if not enough room. */ if (lda > *nmax) { goto L80; } laa = lda * na; /* Generate the matrix A. */ smake_("GE", " ", " ", &ma, &na, &a[a_offset], nmax, &aa[ 1], &lda, &reset, &c_b84, (ftnlen)2, (ftnlen)1, ( ftnlen)1); for (icb = 1; icb <= 3; ++icb) { *(unsigned char *)transb = *(unsigned char *)&ich[icb - 1]; tranb = *(unsigned char *)transb == 'T' || *(unsigned char *)transb == 'C'; if (tranb) { mb = n; nb = k; } else { mb = k; nb = n; } /* Set LDB to 1 more than minimum value if room. */ ldb = mb; if (ldb < *nmax) { ++ldb; } /* Skip tests if not enough room. */ if (ldb > *nmax) { goto L70; } lbb = ldb * nb; /* Generate the matrix B. */ smake_("GE", " ", " ", &mb, &nb, &b[b_offset], nmax, & bb[1], &ldb, &reset, &c_b84, (ftnlen)2, ( ftnlen)1, (ftnlen)1); i__4 = *nalf; for (ia = 1; ia <= i__4; ++ia) { alpha = alf[ia]; i__5 = *nbet; for (ib = 1; ib <= i__5; ++ib) { beta = bet[ib]; /* Generate the matrix C. */ smake_("GE", " ", " ", &m, &n, &c__[c_offset], nmax, &cc[1], &ldc, &reset, &c_b84, ( ftnlen)2, (ftnlen)1, (ftnlen)1); ++nc; /* Save every datum before calling the */ /* subroutine. */ *(unsigned char *)tranas = *(unsigned char *) transa; *(unsigned char *)tranbs = *(unsigned char *) transb; ms = m; ns = n; ks = k; als = alpha; i__6 = laa; for (i__ = 1; i__ <= i__6; ++i__) { as[i__] = aa[i__]; /* L10: */ } ldas = lda; i__6 = lbb; for (i__ = 1; i__ <= i__6; ++i__) { bs[i__] = bb[i__]; /* L20: */ } ldbs = ldb; bls = beta; i__6 = lcc; for (i__ = 1; i__ <= i__6; ++i__) { cs[i__] = cc[i__]; /* L30: */ } ldcs = ldc; /* Call the subroutine. */ if (*trace) { io___124.ciunit = *ntra; s_wsfe(&io___124); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof( integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, transa, (ftnlen)1); do_fio(&c__1, transb, (ftnlen)1); do_fio(&c__1, (char *)&m, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&n, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&k, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&alpha, (ftnlen) sizeof(real)); do_fio(&c__1, (char *)&lda, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&ldb, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&beta, (ftnlen) sizeof(real)); do_fio(&c__1, (char *)&ldc, (ftnlen) sizeof(integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } sgemm_(transa, transb, &m, &n, &k, &alpha, & aa[1], &lda, &bb[1], &ldb, &beta, &cc[ 1], &ldc, (ftnlen)1, (ftnlen)1); /* Check if error-exit was taken incorrectly. */ if (! infoc_1.ok) { io___125.ciunit = *nout; s_wsfe(&io___125); e_wsfe(); *fatal = TRUE_; goto L120; } /* See what data changed inside subroutines. */ isame[0] = *(unsigned char *)transa == *( unsigned char *)tranas; isame[1] = *(unsigned char *)transb == *( unsigned char *)tranbs; isame[2] = ms == m; isame[3] = ns == n; isame[4] = ks == k; isame[5] = als == alpha; isame[6] = lse_(&as[1], &aa[1], &laa); isame[7] = ldas == lda; isame[8] = lse_(&bs[1], &bb[1], &lbb); isame[9] = ldbs == ldb; isame[10] = bls == beta; if (null) { isame[11] = lse_(&cs[1], &cc[1], &lcc); } else { isame[11] = lseres_("GE", " ", &m, &n, & cs[1], &cc[1], &ldc, (ftnlen)2, ( ftnlen)1); } isame[12] = ldcs == ldc; /* If data was incorrectly changed, report */ /* and return. */ same = TRUE_; i__6 = nargs; for (i__ = 1; i__ <= i__6; ++i__) { same = same && isame[i__ - 1]; if (! isame[i__ - 1]) { io___128.ciunit = *nout; s_wsfe(&io___128); do_fio(&c__1, (char *)&i__, (ftnlen) sizeof(integer)); e_wsfe(); } /* L40: */ } if (! same) { *fatal = TRUE_; goto L120; } if (! null) { /* Check the result. */ smmch_(transa, transb, &m, &n, &k, &alpha, &a[a_offset], nmax, &b[b_offset], nmax, &beta, &c__[c_offset], nmax, &ct[1], &g[1], &cc[1], &ldc, eps, &err, fatal, nout, &c_true, (ftnlen)1, (ftnlen)1); errmax = max(errmax,err); /* If got really bad answer, report and */ /* return. */ if (*fatal) { goto L120; } } /* L50: */ } /* L60: */ } L70: ; } L80: ; } /* L90: */ } L100: ; } /* L110: */ } /* Report result. */ if (errmax < *thresh) { io___130.ciunit = *nout; s_wsfe(&io___130); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); e_wsfe(); } else { io___131.ciunit = *nout; s_wsfe(&io___131); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&errmax, (ftnlen)sizeof(real)); e_wsfe(); } goto L130; L120: io___132.ciunit = *nout; s_wsfe(&io___132); do_fio(&c__1, sname, (ftnlen)6); e_wsfe(); io___133.ciunit = *nout; s_wsfe(&io___133); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, transa, (ftnlen)1); do_fio(&c__1, transb, (ftnlen)1); do_fio(&c__1, (char *)&m, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&k, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&alpha, (ftnlen)sizeof(real)); do_fio(&c__1, (char *)&lda, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&ldb, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&beta, (ftnlen)sizeof(real)); do_fio(&c__1, (char *)&ldc, (ftnlen)sizeof(integer)); e_wsfe(); L130: return 0; /* End of SCHK1. */ } /* schk1_ */ /* Subroutine */ int schk2_(char *sname, real *eps, real *thresh, integer * nout, integer *ntra, logical *trace, logical *rewi, logical *fatal, integer *nidim, integer *idim, integer *nalf, real *alf, integer * nbet, real *bet, integer *nmax, real *a, real *aa, real *as, real *b, real *bb, real *bs, real *c__, real *cc, real *cs, real *ct, real *g, ftnlen sname_len) { /* Initialized data */ static char ichs[2] = "LR"; static char ichu[2] = "UL"; /* Format strings */ static char fmt_9995[] = "(1x,i6,\002: \002,a6,\002(\002,2(\002'\002,a1" ",\002',\002),2(i3,\002,\002),f4.1,\002, A,\002,i3,\002, B,\002,i" "3,\002,\002,f4.1,\002, C,\002,i3,\002) \002,\002 .\002)"; static char fmt_9994[] = "(\002 ******* FATAL ERROR - ERROR-EXIT TAKEN O" "N VALID CALL *\002,\002******\002)"; static char fmt_9998[] = "(\002 ******* FATAL ERROR - PARAMETER NUMBER" " \002,i2,\002 WAS CH\002,\002ANGED INCORRECTLY *******\002)"; static char fmt_9999[] = "(\002 \002,a6,\002 PASSED THE COMPUTATIONAL TE" "STS (\002,i6,\002 CALL\002,\002S)\002)"; static char fmt_9997[] = "(\002 \002,a6,\002 COMPLETED THE COMPUTATIONAL" " TESTS (\002,i6,\002 C\002,\002ALLS)\002,/\002 ******* BUT WITH " "MAXIMUM TEST RATIO\002,f8.2,\002 - SUSPECT *******\002)"; static char fmt_9996[] = "(\002 ******* \002,a6,\002 FAILED ON CALL NUMB" "ER:\002)"; /* System generated locals */ integer a_dim1, a_offset, b_dim1, b_offset, c_dim1, c_offset, i__1, i__2, i__3, i__4, i__5; alist al__1; /* Builtin functions */ integer s_wsfe(cilist *), do_fio(integer *, char *, ftnlen), e_wsfe(void), f_rew(alist *); /* Local variables */ integer i__, m, n, ia, ib, na, nc, im, in, ms, ns, laa, lbb, lda, lcc, ldb, ldc, ics; real als, bls; integer icu; extern logical lse_(real *, real *, integer *); real err, beta; integer ldas, ldbs, ldcs; logical same; char side[1]; logical left, null; char uplo[1]; real alpha; logical isame[13]; extern /* Subroutine */ int smake_(char *, char *, char *, integer *, integer *, real *, integer *, real *, integer *, logical *, real * , ftnlen, ftnlen, ftnlen); char sides[1]; extern /* Subroutine */ int smmch_(char *, char *, integer *, integer *, integer *, real *, real *, integer *, real *, integer *, real *, real *, integer *, real *, real *, real *, integer *, real *, real *, logical *, integer *, logical *, ftnlen, ftnlen); integer nargs; logical reset; char uplos[1]; extern /* Subroutine */ int ssymm_(char *, char *, integer *, integer *, real *, real *, integer *, real *, integer *, real *, real *, integer *, ftnlen, ftnlen); real errmax; extern logical lseres_(char *, char *, integer *, integer *, real *, real *, integer *, ftnlen, ftnlen); /* Fortran I/O blocks */ static cilist io___171 = { 0, 0, 0, fmt_9995, 0 }; static cilist io___172 = { 0, 0, 0, fmt_9994, 0 }; static cilist io___175 = { 0, 0, 0, fmt_9998, 0 }; static cilist io___177 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___178 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___179 = { 0, 0, 0, fmt_9996, 0 }; static cilist io___180 = { 0, 0, 0, fmt_9995, 0 }; /* Tests SSYMM. */ /* Auxiliary routine for test program for Level 3 Blas. */ /* -- Written on 8-February-1989. */ /* Jack Dongarra, Argonne National Laboratory. */ /* Iain Duff, AERE Harwell. */ /* Jeremy Du Croz, Numerical Algorithms Group Ltd. */ /* Sven Hammarling, Numerical Algorithms Group Ltd. */ /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Scalars .. */ /* .. Local Arrays .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. Scalars in Common .. */ /* .. Common blocks .. */ /* .. Data statements .. */ /* Parameter adjustments */ --idim; --alf; --bet; --g; --ct; --cs; --cc; c_dim1 = *nmax; c_offset = 1 + c_dim1; c__ -= c_offset; --bs; --bb; b_dim1 = *nmax; b_offset = 1 + b_dim1; b -= b_offset; --as; --aa; a_dim1 = *nmax; a_offset = 1 + a_dim1; a -= a_offset; /* Function Body */ /* .. Executable Statements .. */ nargs = 12; nc = 0; reset = TRUE_; errmax = 0.f; i__1 = *nidim; for (im = 1; im <= i__1; ++im) { m = idim[im]; i__2 = *nidim; for (in = 1; in <= i__2; ++in) { n = idim[in]; /* Set LDC to 1 more than minimum value if room. */ ldc = m; if (ldc < *nmax) { ++ldc; } /* Skip tests if not enough room. */ if (ldc > *nmax) { goto L90; } lcc = ldc * n; null = n <= 0 || m <= 0; /* Set LDB to 1 more than minimum value if room. */ ldb = m; if (ldb < *nmax) { ++ldb; } /* Skip tests if not enough room. */ if (ldb > *nmax) { goto L90; } lbb = ldb * n; /* Generate the matrix B. */ smake_("GE", " ", " ", &m, &n, &b[b_offset], nmax, &bb[1], &ldb, & reset, &c_b84, (ftnlen)2, (ftnlen)1, (ftnlen)1); for (ics = 1; ics <= 2; ++ics) { *(unsigned char *)side = *(unsigned char *)&ichs[ics - 1]; left = *(unsigned char *)side == 'L'; if (left) { na = m; } else { na = n; } /* Set LDA to 1 more than minimum value if room. */ lda = na; if (lda < *nmax) { ++lda; } /* Skip tests if not enough room. */ if (lda > *nmax) { goto L80; } laa = lda * na; for (icu = 1; icu <= 2; ++icu) { *(unsigned char *)uplo = *(unsigned char *)&ichu[icu - 1]; /* Generate the symmetric matrix A. */ smake_("SY", uplo, " ", &na, &na, &a[a_offset], nmax, &aa[ 1], &lda, &reset, &c_b84, (ftnlen)2, (ftnlen)1, ( ftnlen)1); i__3 = *nalf; for (ia = 1; ia <= i__3; ++ia) { alpha = alf[ia]; i__4 = *nbet; for (ib = 1; ib <= i__4; ++ib) { beta = bet[ib]; /* Generate the matrix C. */ smake_("GE", " ", " ", &m, &n, &c__[c_offset], nmax, &cc[1], &ldc, &reset, &c_b84, ( ftnlen)2, (ftnlen)1, (ftnlen)1); ++nc; /* Save every datum before calling the */ /* subroutine. */ *(unsigned char *)sides = *(unsigned char *)side; *(unsigned char *)uplos = *(unsigned char *)uplo; ms = m; ns = n; als = alpha; i__5 = laa; for (i__ = 1; i__ <= i__5; ++i__) { as[i__] = aa[i__]; /* L10: */ } ldas = lda; i__5 = lbb; for (i__ = 1; i__ <= i__5; ++i__) { bs[i__] = bb[i__]; /* L20: */ } ldbs = ldb; bls = beta; i__5 = lcc; for (i__ = 1; i__ <= i__5; ++i__) { cs[i__] = cc[i__]; /* L30: */ } ldcs = ldc; /* Call the subroutine. */ if (*trace) { io___171.ciunit = *ntra; s_wsfe(&io___171); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof( integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, side, (ftnlen)1); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, (char *)&m, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&n, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&alpha, (ftnlen)sizeof( real)); do_fio(&c__1, (char *)&lda, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&ldb, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&beta, (ftnlen)sizeof( real)); do_fio(&c__1, (char *)&ldc, (ftnlen)sizeof( integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } ssymm_(side, uplo, &m, &n, &alpha, &aa[1], &lda, & bb[1], &ldb, &beta, &cc[1], &ldc, (ftnlen) 1, (ftnlen)1); /* Check if error-exit was taken incorrectly. */ if (! infoc_1.ok) { io___172.ciunit = *nout; s_wsfe(&io___172); e_wsfe(); *fatal = TRUE_; goto L110; } /* See what data changed inside subroutines. */ isame[0] = *(unsigned char *)sides == *(unsigned char *)side; isame[1] = *(unsigned char *)uplos == *(unsigned char *)uplo; isame[2] = ms == m; isame[3] = ns == n; isame[4] = als == alpha; isame[5] = lse_(&as[1], &aa[1], &laa); isame[6] = ldas == lda; isame[7] = lse_(&bs[1], &bb[1], &lbb); isame[8] = ldbs == ldb; isame[9] = bls == beta; if (null) { isame[10] = lse_(&cs[1], &cc[1], &lcc); } else { isame[10] = lseres_("GE", " ", &m, &n, &cs[1], &cc[1], &ldc, (ftnlen)2, (ftnlen)1); } isame[11] = ldcs == ldc; /* If data was incorrectly changed, report and */ /* return. */ same = TRUE_; i__5 = nargs; for (i__ = 1; i__ <= i__5; ++i__) { same = same && isame[i__ - 1]; if (! isame[i__ - 1]) { io___175.ciunit = *nout; s_wsfe(&io___175); do_fio(&c__1, (char *)&i__, (ftnlen) sizeof(integer)); e_wsfe(); } /* L40: */ } if (! same) { *fatal = TRUE_; goto L110; } if (! null) { /* Check the result. */ if (left) { smmch_("N", "N", &m, &n, &m, &alpha, &a[ a_offset], nmax, &b[b_offset], nmax, &beta, &c__[c_offset], nmax, &ct[1], &g[1], &cc[1], &ldc, eps, &err, fatal, nout, &c_true, ( ftnlen)1, (ftnlen)1); } else { smmch_("N", "N", &m, &n, &n, &alpha, &b[ b_offset], nmax, &a[a_offset], nmax, &beta, &c__[c_offset], nmax, &ct[1], &g[1], &cc[1], &ldc, eps, &err, fatal, nout, &c_true, ( ftnlen)1, (ftnlen)1); } errmax = max(errmax,err); /* If got really bad answer, report and */ /* return. */ if (*fatal) { goto L110; } } /* L50: */ } /* L60: */ } /* L70: */ } L80: ; } L90: ; } /* L100: */ } /* Report result. */ if (errmax < *thresh) { io___177.ciunit = *nout; s_wsfe(&io___177); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); e_wsfe(); } else { io___178.ciunit = *nout; s_wsfe(&io___178); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&errmax, (ftnlen)sizeof(real)); e_wsfe(); } goto L120; L110: io___179.ciunit = *nout; s_wsfe(&io___179); do_fio(&c__1, sname, (ftnlen)6); e_wsfe(); io___180.ciunit = *nout; s_wsfe(&io___180); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, side, (ftnlen)1); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, (char *)&m, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&alpha, (ftnlen)sizeof(real)); do_fio(&c__1, (char *)&lda, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&ldb, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&beta, (ftnlen)sizeof(real)); do_fio(&c__1, (char *)&ldc, (ftnlen)sizeof(integer)); e_wsfe(); L120: return 0; /* End of SCHK2. */ } /* schk2_ */ /* Subroutine */ int schk3_(char *sname, real *eps, real *thresh, integer * nout, integer *ntra, logical *trace, logical *rewi, logical *fatal, integer *nidim, integer *idim, integer *nalf, real *alf, integer * nmax, real *a, real *aa, real *as, real *b, real *bb, real *bs, real * ct, real *g, real *c__, ftnlen sname_len) { /* Initialized data */ static char ichu[2] = "UL"; static char icht[3] = "NTC"; static char ichd[2] = "UN"; static char ichs[2] = "LR"; /* Format strings */ static char fmt_9995[] = "(1x,i6,\002: \002,a6,\002(\002,4(\002'\002,a1" ",\002',\002),2(i3,\002,\002),f4.1,\002, A,\002,i3,\002, B,\002,i" "3,\002) .\002)"; static char fmt_9994[] = "(\002 ******* FATAL ERROR - ERROR-EXIT TAKEN O" "N VALID CALL *\002,\002******\002)"; static char fmt_9998[] = "(\002 ******* FATAL ERROR - PARAMETER NUMBER" " \002,i2,\002 WAS CH\002,\002ANGED INCORRECTLY *******\002)"; static char fmt_9999[] = "(\002 \002,a6,\002 PASSED THE COMPUTATIONAL TE" "STS (\002,i6,\002 CALL\002,\002S)\002)"; static char fmt_9997[] = "(\002 \002,a6,\002 COMPLETED THE COMPUTATIONAL" " TESTS (\002,i6,\002 C\002,\002ALLS)\002,/\002 ******* BUT WITH " "MAXIMUM TEST RATIO\002,f8.2,\002 - SUSPECT *******\002)"; static char fmt_9996[] = "(\002 ******* \002,a6,\002 FAILED ON CALL NUMB" "ER:\002)"; /* System generated locals */ integer a_dim1, a_offset, b_dim1, b_offset, c_dim1, c_offset, i__1, i__2, i__3, i__4, i__5; alist al__1; /* Builtin functions */ integer s_cmp(const char *, const char *, ftnlen, ftnlen), s_wsfe(cilist *), do_fio( integer *, char *, ftnlen), e_wsfe(void), f_rew(alist *); /* Local variables */ integer i__, j, m, n, ia, na, nc, im, in, ms, ns, laa, icd, lbb, lda, ldb, ics; real als; integer ict, icu; extern logical lse_(real *, real *, integer *); real err; char diag[1]; integer ldas, ldbs; logical same; char side[1]; logical left, null; char uplo[1]; real alpha; char diags[1]; logical isame[13]; extern /* Subroutine */ int smake_(char *, char *, char *, integer *, integer *, real *, integer *, real *, integer *, logical *, real * , ftnlen, ftnlen, ftnlen); char sides[1]; extern /* Subroutine */ int smmch_(char *, char *, integer *, integer *, integer *, real *, real *, integer *, real *, integer *, real *, real *, integer *, real *, real *, real *, integer *, real *, real *, logical *, integer *, logical *, ftnlen, ftnlen); integer nargs; logical reset; char uplos[1]; extern /* Subroutine */ int strmm_(char *, char *, char *, char *, integer *, integer *, real *, real *, integer *, real *, integer * , ftnlen, ftnlen, ftnlen, ftnlen), strsm_(char *, char *, char *, char *, integer *, integer *, real *, real *, integer *, real *, integer *, ftnlen, ftnlen, ftnlen, ftnlen); char tranas[1], transa[1]; real errmax; extern logical lseres_(char *, char *, integer *, integer *, real *, real *, integer *, ftnlen, ftnlen); /* Fortran I/O blocks */ static cilist io___221 = { 0, 0, 0, fmt_9995, 0 }; static cilist io___222 = { 0, 0, 0, fmt_9995, 0 }; static cilist io___223 = { 0, 0, 0, fmt_9994, 0 }; static cilist io___226 = { 0, 0, 0, fmt_9998, 0 }; static cilist io___228 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___229 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___230 = { 0, 0, 0, fmt_9996, 0 }; static cilist io___231 = { 0, 0, 0, fmt_9995, 0 }; /* Tests STRMM and STRSM. */ /* Auxiliary routine for test program for Level 3 Blas. */ /* -- Written on 8-February-1989. */ /* Jack Dongarra, Argonne National Laboratory. */ /* Iain Duff, AERE Harwell. */ /* Jeremy Du Croz, Numerical Algorithms Group Ltd. */ /* Sven Hammarling, Numerical Algorithms Group Ltd. */ /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Scalars .. */ /* .. Local Arrays .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. Scalars in Common .. */ /* .. Common blocks .. */ /* .. Data statements .. */ /* Parameter adjustments */ --idim; --alf; c_dim1 = *nmax; c_offset = 1 + c_dim1; c__ -= c_offset; --g; --ct; --bs; --bb; b_dim1 = *nmax; b_offset = 1 + b_dim1; b -= b_offset; --as; --aa; a_dim1 = *nmax; a_offset = 1 + a_dim1; a -= a_offset; /* Function Body */ /* .. Executable Statements .. */ nargs = 11; nc = 0; reset = TRUE_; errmax = 0.f; /* Set up zero matrix for SMMCH. */ i__1 = *nmax; for (j = 1; j <= i__1; ++j) { i__2 = *nmax; for (i__ = 1; i__ <= i__2; ++i__) { c__[i__ + j * c_dim1] = 0.f; /* L10: */ } /* L20: */ } i__1 = *nidim; for (im = 1; im <= i__1; ++im) { m = idim[im]; i__2 = *nidim; for (in = 1; in <= i__2; ++in) { n = idim[in]; /* Set LDB to 1 more than minimum value if room. */ ldb = m; if (ldb < *nmax) { ++ldb; } /* Skip tests if not enough room. */ if (ldb > *nmax) { goto L130; } lbb = ldb * n; null = m <= 0 || n <= 0; for (ics = 1; ics <= 2; ++ics) { *(unsigned char *)side = *(unsigned char *)&ichs[ics - 1]; left = *(unsigned char *)side == 'L'; if (left) { na = m; } else { na = n; } /* Set LDA to 1 more than minimum value if room. */ lda = na; if (lda < *nmax) { ++lda; } /* Skip tests if not enough room. */ if (lda > *nmax) { goto L130; } laa = lda * na; for (icu = 1; icu <= 2; ++icu) { *(unsigned char *)uplo = *(unsigned char *)&ichu[icu - 1]; for (ict = 1; ict <= 3; ++ict) { *(unsigned char *)transa = *(unsigned char *)&icht[ ict - 1]; for (icd = 1; icd <= 2; ++icd) { *(unsigned char *)diag = *(unsigned char *)&ichd[ icd - 1]; i__3 = *nalf; for (ia = 1; ia <= i__3; ++ia) { alpha = alf[ia]; /* Generate the matrix A. */ smake_("TR", uplo, diag, &na, &na, &a[ a_offset], nmax, &aa[1], &lda, &reset, &c_b84, (ftnlen)2, (ftnlen)1, ( ftnlen)1); /* Generate the matrix B. */ smake_("GE", " ", " ", &m, &n, &b[b_offset], nmax, &bb[1], &ldb, &reset, &c_b84, ( ftnlen)2, (ftnlen)1, (ftnlen)1); ++nc; /* Save every datum before calling the */ /* subroutine. */ *(unsigned char *)sides = *(unsigned char *) side; *(unsigned char *)uplos = *(unsigned char *) uplo; *(unsigned char *)tranas = *(unsigned char *) transa; *(unsigned char *)diags = *(unsigned char *) diag; ms = m; ns = n; als = alpha; i__4 = laa; for (i__ = 1; i__ <= i__4; ++i__) { as[i__] = aa[i__]; /* L30: */ } ldas = lda; i__4 = lbb; for (i__ = 1; i__ <= i__4; ++i__) { bs[i__] = bb[i__]; /* L40: */ } ldbs = ldb; /* Call the subroutine. */ if (s_cmp(sname + 3, "MM", (ftnlen)2, (ftnlen) 2) == 0) { if (*trace) { io___221.ciunit = *ntra; s_wsfe(&io___221); do_fio(&c__1, (char *)&nc, (ftnlen) sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, side, (ftnlen)1); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, transa, (ftnlen)1); do_fio(&c__1, diag, (ftnlen)1); do_fio(&c__1, (char *)&m, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&n, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&alpha, (ftnlen) sizeof(real)); do_fio(&c__1, (char *)&lda, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&ldb, (ftnlen) sizeof(integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } strmm_(side, uplo, transa, diag, &m, &n, & alpha, &aa[1], &lda, &bb[1], &ldb, (ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); } else if (s_cmp(sname + 3, "SM", (ftnlen)2, ( ftnlen)2) == 0) { if (*trace) { io___222.ciunit = *ntra; s_wsfe(&io___222); do_fio(&c__1, (char *)&nc, (ftnlen) sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, side, (ftnlen)1); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, transa, (ftnlen)1); do_fio(&c__1, diag, (ftnlen)1); do_fio(&c__1, (char *)&m, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&n, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&alpha, (ftnlen) sizeof(real)); do_fio(&c__1, (char *)&lda, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&ldb, (ftnlen) sizeof(integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } strsm_(side, uplo, transa, diag, &m, &n, & alpha, &aa[1], &lda, &bb[1], &ldb, (ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); } /* Check if error-exit was taken incorrectly. */ if (! infoc_1.ok) { io___223.ciunit = *nout; s_wsfe(&io___223); e_wsfe(); *fatal = TRUE_; goto L150; } /* See what data changed inside subroutines. */ isame[0] = *(unsigned char *)sides == *( unsigned char *)side; isame[1] = *(unsigned char *)uplos == *( unsigned char *)uplo; isame[2] = *(unsigned char *)tranas == *( unsigned char *)transa; isame[3] = *(unsigned char *)diags == *( unsigned char *)diag; isame[4] = ms == m; isame[5] = ns == n; isame[6] = als == alpha; isame[7] = lse_(&as[1], &aa[1], &laa); isame[8] = ldas == lda; if (null) { isame[9] = lse_(&bs[1], &bb[1], &lbb); } else { isame[9] = lseres_("GE", " ", &m, &n, &bs[ 1], &bb[1], &ldb, (ftnlen)2, ( ftnlen)1); } isame[10] = ldbs == ldb; /* If data was incorrectly changed, report and */ /* return. */ same = TRUE_; i__4 = nargs; for (i__ = 1; i__ <= i__4; ++i__) { same = same && isame[i__ - 1]; if (! isame[i__ - 1]) { io___226.ciunit = *nout; s_wsfe(&io___226); do_fio(&c__1, (char *)&i__, (ftnlen) sizeof(integer)); e_wsfe(); } /* L50: */ } if (! same) { *fatal = TRUE_; goto L150; } if (! null) { if (s_cmp(sname + 3, "MM", (ftnlen)2, ( ftnlen)2) == 0) { /* Check the result. */ if (left) { smmch_(transa, "N", &m, &n, &m, & alpha, &a[a_offset], nmax, &b[b_offset], nmax, & c_b84, &c__[c_offset], nmax, &ct[1], &g[1], &bb[ 1], &ldb, eps, &err, fatal, nout, &c_true, ( ftnlen)1, (ftnlen)1); } else { smmch_("N", transa, &m, &n, &n, & alpha, &b[b_offset], nmax, &a[a_offset], nmax, & c_b84, &c__[c_offset], nmax, &ct[1], &g[1], &bb[ 1], &ldb, eps, &err, fatal, nout, &c_true, ( ftnlen)1, (ftnlen)1); } } else if (s_cmp(sname + 3, "SM", (ftnlen) 2, (ftnlen)2) == 0) { /* Compute approximation to original */ /* matrix. */ i__4 = n; for (j = 1; j <= i__4; ++j) { i__5 = m; for (i__ = 1; i__ <= i__5; ++i__) { c__[i__ + j * c_dim1] = bb[i__ + (j - 1) * ldb]; bb[i__ + (j - 1) * ldb] = alpha * b[i__ + j * b_dim1]; /* L60: */ } /* L70: */ } if (left) { smmch_(transa, "N", &m, &n, &m, & c_b94, &a[a_offset], nmax, &c__[c_offset], nmax, & c_b84, &b[b_offset], nmax, &ct[1], &g[1], &bb[1], & ldb, eps, &err, fatal, nout, &c_false, (ftnlen)1, (ftnlen)1); } else { smmch_("N", transa, &m, &n, &n, & c_b94, &c__[c_offset], nmax, &a[a_offset], nmax, &c_b84, &b[b_offset], nmax, &ct[1], &g[1], &bb[ 1], &ldb, eps, &err, fatal, nout, &c_false, ( ftnlen)1, (ftnlen)1); } } errmax = max(errmax,err); /* If got really bad answer, report and */ /* return. */ if (*fatal) { goto L150; } } /* L80: */ } /* L90: */ } /* L100: */ } /* L110: */ } /* L120: */ } L130: ; } /* L140: */ } /* Report result. */ if (errmax < *thresh) { io___228.ciunit = *nout; s_wsfe(&io___228); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); e_wsfe(); } else { io___229.ciunit = *nout; s_wsfe(&io___229); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&errmax, (ftnlen)sizeof(real)); e_wsfe(); } goto L160; L150: io___230.ciunit = *nout; s_wsfe(&io___230); do_fio(&c__1, sname, (ftnlen)6); e_wsfe(); io___231.ciunit = *nout; s_wsfe(&io___231); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, side, (ftnlen)1); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, transa, (ftnlen)1); do_fio(&c__1, diag, (ftnlen)1); do_fio(&c__1, (char *)&m, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&alpha, (ftnlen)sizeof(real)); do_fio(&c__1, (char *)&lda, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&ldb, (ftnlen)sizeof(integer)); e_wsfe(); L160: return 0; /* End of SCHK3. */ } /* schk3_ */ /* Subroutine */ int schk4_(char *sname, real *eps, real *thresh, integer * nout, integer *ntra, logical *trace, logical *rewi, logical *fatal, integer *nidim, integer *idim, integer *nalf, real *alf, integer * nbet, real *bet, integer *nmax, real *a, real *aa, real *as, real *b, real *bb, real *bs, real *c__, real *cc, real *cs, real *ct, real *g, ftnlen sname_len) { /* Initialized data */ static char icht[3] = "NTC"; static char ichu[2] = "UL"; /* Format strings */ static char fmt_9994[] = "(1x,i6,\002: \002,a6,\002(\002,2(\002'\002,a1" ",\002',\002),2(i3,\002,\002),f4.1,\002, A,\002,i3,\002,\002,f4.1," "\002, C,\002,i3,\002) .\002)"; static char fmt_9993[] = "(\002 ******* FATAL ERROR - ERROR-EXIT TAKEN O" "N VALID CALL *\002,\002******\002)"; static char fmt_9998[] = "(\002 ******* FATAL ERROR - PARAMETER NUMBER" " \002,i2,\002 WAS CH\002,\002ANGED INCORRECTLY *******\002)"; static char fmt_9999[] = "(\002 \002,a6,\002 PASSED THE COMPUTATIONAL TE" "STS (\002,i6,\002 CALL\002,\002S)\002)"; static char fmt_9997[] = "(\002 \002,a6,\002 COMPLETED THE COMPUTATIONAL" " TESTS (\002,i6,\002 C\002,\002ALLS)\002,/\002 ******* BUT WITH " "MAXIMUM TEST RATIO\002,f8.2,\002 - SUSPECT *******\002)"; static char fmt_9995[] = "(\002 THESE ARE THE RESULTS FOR COLUMN" " \002,i3)"; static char fmt_9996[] = "(\002 ******* \002,a6,\002 FAILED ON CALL NUMB" "ER:\002)"; /* System generated locals */ integer a_dim1, a_offset, b_dim1, b_offset, c_dim1, c_offset, i__1, i__2, i__3, i__4, i__5; alist al__1; /* Builtin functions */ integer s_wsfe(cilist *), do_fio(integer *, char *, ftnlen), e_wsfe(void), f_rew(alist *); /* Local variables */ integer i__, j, k, n, ia, ib, jc, ma, na, nc, ik, in, jj, lj, ks, ns, laa, lda, lcc, ldc; real als; integer ict, icu; extern logical lse_(real *, real *, integer *); real err, beta; integer ldas, ldcs; logical same; real bets; logical tran, null; char uplo[1]; real alpha; logical isame[13]; extern /* Subroutine */ int smake_(char *, char *, char *, integer *, integer *, real *, integer *, real *, integer *, logical *, real * , ftnlen, ftnlen, ftnlen), smmch_(char *, char *, integer *, integer *, integer *, real *, real *, integer *, real *, integer * , real *, real *, integer *, real *, real *, real *, integer *, real *, real *, logical *, integer *, logical *, ftnlen, ftnlen); integer nargs; logical reset; char trans[1]; logical upper; char uplos[1]; extern /* Subroutine */ int ssyrk_(char *, char *, integer *, integer *, real *, real *, integer *, real *, real *, integer *, ftnlen, ftnlen); real errmax; extern logical lseres_(char *, char *, integer *, integer *, real *, real *, integer *, ftnlen, ftnlen); char transs[1]; /* Fortran I/O blocks */ static cilist io___268 = { 0, 0, 0, fmt_9994, 0 }; static cilist io___269 = { 0, 0, 0, fmt_9993, 0 }; static cilist io___272 = { 0, 0, 0, fmt_9998, 0 }; static cilist io___278 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___279 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___280 = { 0, 0, 0, fmt_9995, 0 }; static cilist io___281 = { 0, 0, 0, fmt_9996, 0 }; static cilist io___282 = { 0, 0, 0, fmt_9994, 0 }; /* Tests SSYRK. */ /* Auxiliary routine for test program for Level 3 Blas. */ /* -- Written on 8-February-1989. */ /* Jack Dongarra, Argonne National Laboratory. */ /* Iain Duff, AERE Harwell. */ /* Jeremy Du Croz, Numerical Algorithms Group Ltd. */ /* Sven Hammarling, Numerical Algorithms Group Ltd. */ /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Scalars .. */ /* .. Local Arrays .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. Scalars in Common .. */ /* .. Common blocks .. */ /* .. Data statements .. */ /* Parameter adjustments */ --idim; --alf; --bet; --g; --ct; --cs; --cc; c_dim1 = *nmax; c_offset = 1 + c_dim1; c__ -= c_offset; --bs; --bb; b_dim1 = *nmax; b_offset = 1 + b_dim1; b -= b_offset; --as; --aa; a_dim1 = *nmax; a_offset = 1 + a_dim1; a -= a_offset; /* Function Body */ /* .. Executable Statements .. */ nargs = 10; nc = 0; reset = TRUE_; errmax = 0.f; i__1 = *nidim; for (in = 1; in <= i__1; ++in) { n = idim[in]; /* Set LDC to 1 more than minimum value if room. */ ldc = n; if (ldc < *nmax) { ++ldc; } /* Skip tests if not enough room. */ if (ldc > *nmax) { goto L100; } lcc = ldc * n; null = n <= 0; i__2 = *nidim; for (ik = 1; ik <= i__2; ++ik) { k = idim[ik]; for (ict = 1; ict <= 3; ++ict) { *(unsigned char *)trans = *(unsigned char *)&icht[ict - 1]; tran = *(unsigned char *)trans == 'T' || *(unsigned char *) trans == 'C'; if (tran) { ma = k; na = n; } else { ma = n; na = k; } /* Set LDA to 1 more than minimum value if room. */ lda = ma; if (lda < *nmax) { ++lda; } /* Skip tests if not enough room. */ if (lda > *nmax) { goto L80; } laa = lda * na; /* Generate the matrix A. */ smake_("GE", " ", " ", &ma, &na, &a[a_offset], nmax, &aa[1], & lda, &reset, &c_b84, (ftnlen)2, (ftnlen)1, (ftnlen)1); for (icu = 1; icu <= 2; ++icu) { *(unsigned char *)uplo = *(unsigned char *)&ichu[icu - 1]; upper = *(unsigned char *)uplo == 'U'; i__3 = *nalf; for (ia = 1; ia <= i__3; ++ia) { alpha = alf[ia]; i__4 = *nbet; for (ib = 1; ib <= i__4; ++ib) { beta = bet[ib]; /* Generate the matrix C. */ smake_("SY", uplo, " ", &n, &n, &c__[c_offset], nmax, &cc[1], &ldc, &reset, &c_b84, ( ftnlen)2, (ftnlen)1, (ftnlen)1); ++nc; /* Save every datum before calling the subroutine. */ *(unsigned char *)uplos = *(unsigned char *)uplo; *(unsigned char *)transs = *(unsigned char *) trans; ns = n; ks = k; als = alpha; i__5 = laa; for (i__ = 1; i__ <= i__5; ++i__) { as[i__] = aa[i__]; /* L10: */ } ldas = lda; bets = beta; i__5 = lcc; for (i__ = 1; i__ <= i__5; ++i__) { cs[i__] = cc[i__]; /* L20: */ } ldcs = ldc; /* Call the subroutine. */ if (*trace) { io___268.ciunit = *ntra; s_wsfe(&io___268); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof( integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&k, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&alpha, (ftnlen)sizeof( real)); do_fio(&c__1, (char *)&lda, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&beta, (ftnlen)sizeof( real)); do_fio(&c__1, (char *)&ldc, (ftnlen)sizeof( integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } ssyrk_(uplo, trans, &n, &k, &alpha, &aa[1], &lda, &beta, &cc[1], &ldc, (ftnlen)1, (ftnlen)1) ; /* Check if error-exit was taken incorrectly. */ if (! infoc_1.ok) { io___269.ciunit = *nout; s_wsfe(&io___269); e_wsfe(); *fatal = TRUE_; goto L120; } /* See what data changed inside subroutines. */ isame[0] = *(unsigned char *)uplos == *(unsigned char *)uplo; isame[1] = *(unsigned char *)transs == *(unsigned char *)trans; isame[2] = ns == n; isame[3] = ks == k; isame[4] = als == alpha; isame[5] = lse_(&as[1], &aa[1], &laa); isame[6] = ldas == lda; isame[7] = bets == beta; if (null) { isame[8] = lse_(&cs[1], &cc[1], &lcc); } else { isame[8] = lseres_("SY", uplo, &n, &n, &cs[1], &cc[1], &ldc, (ftnlen)2, (ftnlen)1); } isame[9] = ldcs == ldc; /* If data was incorrectly changed, report and */ /* return. */ same = TRUE_; i__5 = nargs; for (i__ = 1; i__ <= i__5; ++i__) { same = same && isame[i__ - 1]; if (! isame[i__ - 1]) { io___272.ciunit = *nout; s_wsfe(&io___272); do_fio(&c__1, (char *)&i__, (ftnlen) sizeof(integer)); e_wsfe(); } /* L30: */ } if (! same) { *fatal = TRUE_; goto L120; } if (! null) { /* Check the result column by column. */ jc = 1; i__5 = n; for (j = 1; j <= i__5; ++j) { if (upper) { jj = 1; lj = j; } else { jj = j; lj = n - j + 1; } if (tran) { smmch_("T", "N", &lj, &c__1, &k, & alpha, &a[jj * a_dim1 + 1], nmax, &a[j * a_dim1 + 1], nmax, &beta, &c__[jj + j * c_dim1], nmax, &ct[1], &g[1], &cc[jc], &ldc, eps, &err, fatal, nout, &c_true, (ftnlen) 1, (ftnlen)1); } else { smmch_("N", "T", &lj, &c__1, &k, & alpha, &a[jj + a_dim1], nmax, &a[j + a_dim1], nmax, &beta, & c__[jj + j * c_dim1], nmax, & ct[1], &g[1], &cc[jc], &ldc, eps, &err, fatal, nout, & c_true, (ftnlen)1, (ftnlen)1); } if (upper) { jc += ldc; } else { jc = jc + ldc + 1; } errmax = max(errmax,err); /* If got really bad answer, report and */ /* return. */ if (*fatal) { goto L110; } /* L40: */ } } /* L50: */ } /* L60: */ } /* L70: */ } L80: ; } /* L90: */ } L100: ; } /* Report result. */ if (errmax < *thresh) { io___278.ciunit = *nout; s_wsfe(&io___278); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); e_wsfe(); } else { io___279.ciunit = *nout; s_wsfe(&io___279); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&errmax, (ftnlen)sizeof(real)); e_wsfe(); } goto L130; L110: if (n > 1) { io___280.ciunit = *nout; s_wsfe(&io___280); do_fio(&c__1, (char *)&j, (ftnlen)sizeof(integer)); e_wsfe(); } L120: io___281.ciunit = *nout; s_wsfe(&io___281); do_fio(&c__1, sname, (ftnlen)6); e_wsfe(); io___282.ciunit = *nout; s_wsfe(&io___282); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&k, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&alpha, (ftnlen)sizeof(real)); do_fio(&c__1, (char *)&lda, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&beta, (ftnlen)sizeof(real)); do_fio(&c__1, (char *)&ldc, (ftnlen)sizeof(integer)); e_wsfe(); L130: return 0; /* End of SCHK4. */ } /* schk4_ */ /* Subroutine */ int schk5_(char *sname, real *eps, real *thresh, integer * nout, integer *ntra, logical *trace, logical *rewi, logical *fatal, integer *nidim, integer *idim, integer *nalf, real *alf, integer * nbet, real *bet, integer *nmax, real *ab, real *aa, real *as, real * bb, real *bs, real *c__, real *cc, real *cs, real *ct, real *g, real * w, ftnlen sname_len) { /* Initialized data */ static char icht[3] = "NTC"; static char ichu[2] = "UL"; /* Format strings */ static char fmt_9994[] = "(1x,i6,\002: \002,a6,\002(\002,2(\002'\002,a1" ",\002',\002),2(i3,\002,\002),f4.1,\002, A,\002,i3,\002, B,\002,i" "3,\002,\002,f4.1,\002, C,\002,i3,\002) \002,\002 .\002)"; static char fmt_9993[] = "(\002 ******* FATAL ERROR - ERROR-EXIT TAKEN O" "N VALID CALL *\002,\002******\002)"; static char fmt_9998[] = "(\002 ******* FATAL ERROR - PARAMETER NUMBER" " \002,i2,\002 WAS CH\002,\002ANGED INCORRECTLY *******\002)"; static char fmt_9999[] = "(\002 \002,a6,\002 PASSED THE COMPUTATIONAL TE" "STS (\002,i6,\002 CALL\002,\002S)\002)"; static char fmt_9997[] = "(\002 \002,a6,\002 COMPLETED THE COMPUTATIONAL" " TESTS (\002,i6,\002 C\002,\002ALLS)\002,/\002 ******* BUT WITH " "MAXIMUM TEST RATIO\002,f8.2,\002 - SUSPECT *******\002)"; static char fmt_9995[] = "(\002 THESE ARE THE RESULTS FOR COLUMN" " \002,i3)"; static char fmt_9996[] = "(\002 ******* \002,a6,\002 FAILED ON CALL NUMB" "ER:\002)"; /* System generated locals */ integer c_dim1, c_offset, i__1, i__2, i__3, i__4, i__5, i__6, i__7, i__8; alist al__1; /* Builtin functions */ integer s_wsfe(cilist *), do_fio(integer *, char *, ftnlen), e_wsfe(void), f_rew(alist *); /* Local variables */ integer i__, j, k, n, ia, ib, jc, ma, na, nc, ik, in, jj, lj, ks, ns, laa, lbb, lda, lcc, ldb, ldc; real als; integer ict, icu; extern logical lse_(real *, real *, integer *); real err; integer jjab; real beta; integer ldas, ldbs, ldcs; logical same; real bets; logical tran, null; char uplo[1]; real alpha; logical isame[13]; extern /* Subroutine */ int smake_(char *, char *, char *, integer *, integer *, real *, integer *, real *, integer *, logical *, real * , ftnlen, ftnlen, ftnlen), smmch_(char *, char *, integer *, integer *, integer *, real *, real *, integer *, real *, integer * , real *, real *, integer *, real *, real *, real *, integer *, real *, real *, logical *, integer *, logical *, ftnlen, ftnlen); integer nargs; logical reset; char trans[1]; logical upper; char uplos[1]; extern /* Subroutine */ int ssyr2k_(char *, char *, integer *, integer *, real *, real *, integer *, real *, integer *, real *, real *, integer *, ftnlen, ftnlen); real errmax; extern logical lseres_(char *, char *, integer *, integer *, real *, real *, integer *, ftnlen, ftnlen); char transs[1]; /* Fortran I/O blocks */ static cilist io___322 = { 0, 0, 0, fmt_9994, 0 }; static cilist io___323 = { 0, 0, 0, fmt_9993, 0 }; static cilist io___326 = { 0, 0, 0, fmt_9998, 0 }; static cilist io___333 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___334 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___335 = { 0, 0, 0, fmt_9995, 0 }; static cilist io___336 = { 0, 0, 0, fmt_9996, 0 }; static cilist io___337 = { 0, 0, 0, fmt_9994, 0 }; /* Tests SSYR2K. */ /* Auxiliary routine for test program for Level 3 Blas. */ /* -- Written on 8-February-1989. */ /* Jack Dongarra, Argonne National Laboratory. */ /* Iain Duff, AERE Harwell. */ /* Jeremy Du Croz, Numerical Algorithms Group Ltd. */ /* Sven Hammarling, Numerical Algorithms Group Ltd. */ /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Scalars .. */ /* .. Local Arrays .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. Scalars in Common .. */ /* .. Common blocks .. */ /* .. Data statements .. */ /* Parameter adjustments */ --idim; --alf; --bet; --w; --g; --ct; --cs; --cc; c_dim1 = *nmax; c_offset = 1 + c_dim1; c__ -= c_offset; --bs; --bb; --as; --aa; --ab; /* Function Body */ /* .. Executable Statements .. */ nargs = 12; nc = 0; reset = TRUE_; errmax = 0.f; i__1 = *nidim; for (in = 1; in <= i__1; ++in) { n = idim[in]; /* Set LDC to 1 more than minimum value if room. */ ldc = n; if (ldc < *nmax) { ++ldc; } /* Skip tests if not enough room. */ if (ldc > *nmax) { goto L130; } lcc = ldc * n; null = n <= 0; i__2 = *nidim; for (ik = 1; ik <= i__2; ++ik) { k = idim[ik]; for (ict = 1; ict <= 3; ++ict) { *(unsigned char *)trans = *(unsigned char *)&icht[ict - 1]; tran = *(unsigned char *)trans == 'T' || *(unsigned char *) trans == 'C'; if (tran) { ma = k; na = n; } else { ma = n; na = k; } /* Set LDA to 1 more than minimum value if room. */ lda = ma; if (lda < *nmax) { ++lda; } /* Skip tests if not enough room. */ if (lda > *nmax) { goto L110; } laa = lda * na; /* Generate the matrix A. */ if (tran) { i__3 = *nmax << 1; smake_("GE", " ", " ", &ma, &na, &ab[1], &i__3, &aa[1], & lda, &reset, &c_b84, (ftnlen)2, (ftnlen)1, ( ftnlen)1); } else { smake_("GE", " ", " ", &ma, &na, &ab[1], nmax, &aa[1], & lda, &reset, &c_b84, (ftnlen)2, (ftnlen)1, ( ftnlen)1); } /* Generate the matrix B. */ ldb = lda; lbb = laa; if (tran) { i__3 = *nmax << 1; smake_("GE", " ", " ", &ma, &na, &ab[k + 1], &i__3, &bb[1] , &ldb, &reset, &c_b84, (ftnlen)2, (ftnlen)1, ( ftnlen)1); } else { smake_("GE", " ", " ", &ma, &na, &ab[k * *nmax + 1], nmax, &bb[1], &ldb, &reset, &c_b84, (ftnlen)2, (ftnlen) 1, (ftnlen)1); } for (icu = 1; icu <= 2; ++icu) { *(unsigned char *)uplo = *(unsigned char *)&ichu[icu - 1]; upper = *(unsigned char *)uplo == 'U'; i__3 = *nalf; for (ia = 1; ia <= i__3; ++ia) { alpha = alf[ia]; i__4 = *nbet; for (ib = 1; ib <= i__4; ++ib) { beta = bet[ib]; /* Generate the matrix C. */ smake_("SY", uplo, " ", &n, &n, &c__[c_offset], nmax, &cc[1], &ldc, &reset, &c_b84, ( ftnlen)2, (ftnlen)1, (ftnlen)1); ++nc; /* Save every datum before calling the subroutine. */ *(unsigned char *)uplos = *(unsigned char *)uplo; *(unsigned char *)transs = *(unsigned char *) trans; ns = n; ks = k; als = alpha; i__5 = laa; for (i__ = 1; i__ <= i__5; ++i__) { as[i__] = aa[i__]; /* L10: */ } ldas = lda; i__5 = lbb; for (i__ = 1; i__ <= i__5; ++i__) { bs[i__] = bb[i__]; /* L20: */ } ldbs = ldb; bets = beta; i__5 = lcc; for (i__ = 1; i__ <= i__5; ++i__) { cs[i__] = cc[i__]; /* L30: */ } ldcs = ldc; /* Call the subroutine. */ if (*trace) { io___322.ciunit = *ntra; s_wsfe(&io___322); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof( integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&k, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&alpha, (ftnlen)sizeof( real)); do_fio(&c__1, (char *)&lda, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&ldb, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&beta, (ftnlen)sizeof( real)); do_fio(&c__1, (char *)&ldc, (ftnlen)sizeof( integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } ssyr2k_(uplo, trans, &n, &k, &alpha, &aa[1], &lda, &bb[1], &ldb, &beta, &cc[1], &ldc, ( ftnlen)1, (ftnlen)1); /* Check if error-exit was taken incorrectly. */ if (! infoc_1.ok) { io___323.ciunit = *nout; s_wsfe(&io___323); e_wsfe(); *fatal = TRUE_; goto L150; } /* See what data changed inside subroutines. */ isame[0] = *(unsigned char *)uplos == *(unsigned char *)uplo; isame[1] = *(unsigned char *)transs == *(unsigned char *)trans; isame[2] = ns == n; isame[3] = ks == k; isame[4] = als == alpha; isame[5] = lse_(&as[1], &aa[1], &laa); isame[6] = ldas == lda; isame[7] = lse_(&bs[1], &bb[1], &lbb); isame[8] = ldbs == ldb; isame[9] = bets == beta; if (null) { isame[10] = lse_(&cs[1], &cc[1], &lcc); } else { isame[10] = lseres_("SY", uplo, &n, &n, &cs[1] , &cc[1], &ldc, (ftnlen)2, (ftnlen)1); } isame[11] = ldcs == ldc; /* If data was incorrectly changed, report and */ /* return. */ same = TRUE_; i__5 = nargs; for (i__ = 1; i__ <= i__5; ++i__) { same = same && isame[i__ - 1]; if (! isame[i__ - 1]) { io___326.ciunit = *nout; s_wsfe(&io___326); do_fio(&c__1, (char *)&i__, (ftnlen) sizeof(integer)); e_wsfe(); } /* L40: */ } if (! same) { *fatal = TRUE_; goto L150; } if (! null) { /* Check the result column by column. */ jjab = 1; jc = 1; i__5 = n; for (j = 1; j <= i__5; ++j) { if (upper) { jj = 1; lj = j; } else { jj = j; lj = n - j + 1; } if (tran) { i__6 = k; for (i__ = 1; i__ <= i__6; ++i__) { w[i__] = ab[(j - 1 << 1) * *nmax + k + i__]; w[k + i__] = ab[(j - 1 << 1) * * nmax + i__]; /* L50: */ } i__6 = k << 1; i__7 = *nmax << 1; i__8 = *nmax << 1; smmch_("T", "N", &lj, &c__1, &i__6, & alpha, &ab[jjab], &i__7, &w[1] , &i__8, &beta, &c__[jj + j * c_dim1], nmax, &ct[1], &g[1], &cc[jc], &ldc, eps, &err, fatal, nout, &c_true, (ftnlen) 1, (ftnlen)1); } else { i__6 = k; for (i__ = 1; i__ <= i__6; ++i__) { w[i__] = ab[(k + i__ - 1) * *nmax + j]; w[k + i__] = ab[(i__ - 1) * *nmax + j]; /* L60: */ } i__6 = k << 1; i__7 = *nmax << 1; smmch_("N", "N", &lj, &c__1, &i__6, & alpha, &ab[jj], nmax, &w[1], & i__7, &beta, &c__[jj + j * c_dim1], nmax, &ct[1], &g[1], &cc[jc], &ldc, eps, &err, fatal, nout, &c_true, (ftnlen) 1, (ftnlen)1); } if (upper) { jc += ldc; } else { jc = jc + ldc + 1; if (tran) { jjab += *nmax << 1; } } errmax = max(errmax,err); /* If got really bad answer, report and */ /* return. */ if (*fatal) { goto L140; } /* L70: */ } } /* L80: */ } /* L90: */ } /* L100: */ } L110: ; } /* L120: */ } L130: ; } /* Report result. */ if (errmax < *thresh) { io___333.ciunit = *nout; s_wsfe(&io___333); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); e_wsfe(); } else { io___334.ciunit = *nout; s_wsfe(&io___334); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&errmax, (ftnlen)sizeof(real)); e_wsfe(); } goto L160; L140: if (n > 1) { io___335.ciunit = *nout; s_wsfe(&io___335); do_fio(&c__1, (char *)&j, (ftnlen)sizeof(integer)); e_wsfe(); } L150: io___336.ciunit = *nout; s_wsfe(&io___336); do_fio(&c__1, sname, (ftnlen)6); e_wsfe(); io___337.ciunit = *nout; s_wsfe(&io___337); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&k, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&alpha, (ftnlen)sizeof(real)); do_fio(&c__1, (char *)&lda, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&ldb, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&beta, (ftnlen)sizeof(real)); do_fio(&c__1, (char *)&ldc, (ftnlen)sizeof(integer)); e_wsfe(); L160: return 0; /* End of SCHK5. */ } /* schk5_ */ /* Subroutine */ int schke_(integer *isnum, char *srnamt, integer *nout, ftnlen srnamt_len) { /* Format strings */ static char fmt_9999[] = "(\002 \002,a6,\002 PASSED THE TESTS OF ERROR-E" "XITS\002)"; static char fmt_9998[] = "(\002 ******* \002,a6,\002 FAILED THE TESTS OF" " ERROR-EXITS *****\002,\002**\002)"; /* Builtin functions */ integer s_wsfe(cilist *), do_fio(integer *, char *, ftnlen), e_wsfe(void); /* Local variables */ real a[2] /* was [2][1] */, b[2] /* was [2][1] */, c__[2] /* was [2][1] */, beta, alpha; extern /* Subroutine */ int sgemm_(char *, char *, integer *, integer *, integer *, real *, real *, integer *, real *, integer *, real *, real *, integer *, ftnlen, ftnlen), strmm_(char *, char *, char *, char *, integer *, integer *, real *, real *, integer *, real *, integer *, ftnlen, ftnlen, ftnlen, ftnlen), ssymm_(char *, char *, integer *, integer *, real *, real *, integer *, real *, integer *, real *, real *, integer *, ftnlen, ftnlen), strsm_(char *, char *, char *, char *, integer *, integer *, real *, real *, integer *, real *, integer *, ftnlen, ftnlen, ftnlen, ftnlen), ssyrk_(char *, char *, integer *, integer *, real *, real *, integer *, real *, real *, integer *, ftnlen, ftnlen), ssyr2k_( char *, char *, integer *, integer *, real *, real *, integer *, real *, integer *, real *, real *, integer *, ftnlen, ftnlen), chkxer_(char *, integer *, integer *, logical *, logical *, ftnlen); /* Fortran I/O blocks */ static cilist io___343 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___344 = { 0, 0, 0, fmt_9998, 0 }; /* Tests the error exits from the Level 3 Blas. */ /* Requires a special version of the error-handling routine XERBLA. */ /* A, B and C should not need to be defined. */ /* Auxiliary routine for test program for Level 3 Blas. */ /* -- Written on 8-February-1989. */ /* Jack Dongarra, Argonne National Laboratory. */ /* Iain Duff, AERE Harwell. */ /* Jeremy Du Croz, Numerical Algorithms Group Ltd. */ /* Sven Hammarling, Numerical Algorithms Group Ltd. */ /* 3-19-92: Initialize ALPHA and BETA (eca) */ /* 3-19-92: Fix argument 12 in calls to SSYMM with INFOT = 9 (eca) */ /* .. Scalar Arguments .. */ /* .. Scalars in Common .. */ /* .. Parameters .. */ /* .. Local Scalars .. */ /* .. Local Arrays .. */ /* .. External Subroutines .. */ /* .. Common blocks .. */ /* .. Executable Statements .. */ /* OK is set to .FALSE. by the special version of XERBLA or by CHKXER */ /* if anything is wrong. */ infoc_1.ok = TRUE_; /* LERR is set to .TRUE. by the special version of XERBLA each time */ /* it is called, and is then tested and re-set by CHKXER. */ infoc_1.lerr = FALSE_; /* Initialize ALPHA and BETA. */ alpha = 1.f; beta = 2.f; switch (*isnum) { case 1: goto L10; case 2: goto L20; case 3: goto L30; case 4: goto L40; case 5: goto L50; case 6: goto L60; } L10: infoc_1.infot = 1; sgemm_("/", "N", &c__0, &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 1; sgemm_("/", "T", &c__0, &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; sgemm_("N", "/", &c__0, &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; sgemm_("T", "/", &c__0, &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; sgemm_("N", "N", &c_n1, &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; sgemm_("N", "T", &c_n1, &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; sgemm_("T", "N", &c_n1, &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; sgemm_("T", "T", &c_n1, &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; sgemm_("N", "N", &c__0, &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; sgemm_("N", "T", &c__0, &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; sgemm_("T", "N", &c__0, &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; sgemm_("T", "T", &c__0, &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; sgemm_("N", "N", &c__0, &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; sgemm_("N", "T", &c__0, &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; sgemm_("T", "N", &c__0, &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; sgemm_("T", "T", &c__0, &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 8; sgemm_("N", "N", &c__2, &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__2, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 8; sgemm_("N", "T", &c__2, &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__2, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 8; sgemm_("T", "N", &c__0, &c__0, &c__2, &alpha, a, &c__1, b, &c__2, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 8; sgemm_("T", "T", &c__0, &c__0, &c__2, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 10; sgemm_("N", "N", &c__0, &c__0, &c__2, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 10; sgemm_("T", "N", &c__0, &c__0, &c__2, &alpha, a, &c__2, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 10; sgemm_("N", "T", &c__0, &c__2, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 10; sgemm_("T", "T", &c__0, &c__2, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 13; sgemm_("N", "N", &c__2, &c__0, &c__0, &alpha, a, &c__2, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 13; sgemm_("N", "T", &c__2, &c__0, &c__0, &alpha, a, &c__2, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 13; sgemm_("T", "N", &c__2, &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 13; sgemm_("T", "T", &c__2, &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L70; L20: infoc_1.infot = 1; ssymm_("/", "U", &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; ssymm_("L", "/", &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; ssymm_("L", "U", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; ssymm_("R", "U", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; ssymm_("L", "L", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; ssymm_("R", "L", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; ssymm_("L", "U", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; ssymm_("R", "U", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; ssymm_("L", "L", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; ssymm_("R", "L", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; ssymm_("L", "U", &c__2, &c__0, &alpha, a, &c__1, b, &c__2, &beta, c__, & c__2, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; ssymm_("R", "U", &c__0, &c__2, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; ssymm_("L", "L", &c__2, &c__0, &alpha, a, &c__1, b, &c__2, &beta, c__, & c__2, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; ssymm_("R", "L", &c__0, &c__2, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; ssymm_("L", "U", &c__2, &c__0, &alpha, a, &c__2, b, &c__1, &beta, c__, & c__2, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; ssymm_("R", "U", &c__2, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__2, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; ssymm_("L", "L", &c__2, &c__0, &alpha, a, &c__2, b, &c__1, &beta, c__, & c__2, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; ssymm_("R", "L", &c__2, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__2, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 12; ssymm_("L", "U", &c__2, &c__0, &alpha, a, &c__2, b, &c__2, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 12; ssymm_("R", "U", &c__2, &c__0, &alpha, a, &c__1, b, &c__2, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 12; ssymm_("L", "L", &c__2, &c__0, &alpha, a, &c__2, b, &c__2, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 12; ssymm_("R", "L", &c__2, &c__0, &alpha, a, &c__1, b, &c__2, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L70; L30: infoc_1.infot = 1; strmm_("/", "U", "N", "N", &c__0, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; strmm_("L", "/", "N", "N", &c__0, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; strmm_("L", "U", "/", "N", &c__0, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; strmm_("L", "U", "N", "/", &c__0, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; strmm_("L", "U", "N", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; strmm_("L", "U", "T", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; strmm_("R", "U", "N", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; strmm_("R", "U", "T", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; strmm_("L", "L", "N", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; strmm_("L", "L", "T", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; strmm_("R", "L", "N", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; strmm_("R", "L", "T", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; strmm_("L", "U", "N", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; strmm_("L", "U", "T", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; strmm_("R", "U", "N", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; strmm_("R", "U", "T", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; strmm_("L", "L", "N", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; strmm_("L", "L", "T", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; strmm_("R", "L", "N", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; strmm_("R", "L", "T", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; strmm_("L", "U", "N", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__2, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; strmm_("L", "U", "T", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__2, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; strmm_("R", "U", "N", "N", &c__0, &c__2, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; strmm_("R", "U", "T", "N", &c__0, &c__2, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; strmm_("L", "L", "N", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__2, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; strmm_("L", "L", "T", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__2, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; strmm_("R", "L", "N", "N", &c__0, &c__2, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; strmm_("R", "L", "T", "N", &c__0, &c__2, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; strmm_("L", "U", "N", "N", &c__2, &c__0, &alpha, a, &c__2, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; strmm_("L", "U", "T", "N", &c__2, &c__0, &alpha, a, &c__2, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; strmm_("R", "U", "N", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; strmm_("R", "U", "T", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; strmm_("L", "L", "N", "N", &c__2, &c__0, &alpha, a, &c__2, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; strmm_("L", "L", "T", "N", &c__2, &c__0, &alpha, a, &c__2, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; strmm_("R", "L", "N", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; strmm_("R", "L", "T", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L70; L40: infoc_1.infot = 1; strsm_("/", "U", "N", "N", &c__0, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; strsm_("L", "/", "N", "N", &c__0, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; strsm_("L", "U", "/", "N", &c__0, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; strsm_("L", "U", "N", "/", &c__0, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; strsm_("L", "U", "N", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; strsm_("L", "U", "T", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; strsm_("R", "U", "N", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; strsm_("R", "U", "T", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; strsm_("L", "L", "N", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; strsm_("L", "L", "T", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; strsm_("R", "L", "N", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; strsm_("R", "L", "T", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; strsm_("L", "U", "N", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; strsm_("L", "U", "T", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; strsm_("R", "U", "N", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; strsm_("R", "U", "T", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; strsm_("L", "L", "N", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; strsm_("L", "L", "T", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; strsm_("R", "L", "N", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; strsm_("R", "L", "T", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; strsm_("L", "U", "N", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__2, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; strsm_("L", "U", "T", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__2, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; strsm_("R", "U", "N", "N", &c__0, &c__2, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; strsm_("R", "U", "T", "N", &c__0, &c__2, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; strsm_("L", "L", "N", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__2, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; strsm_("L", "L", "T", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__2, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; strsm_("R", "L", "N", "N", &c__0, &c__2, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; strsm_("R", "L", "T", "N", &c__0, &c__2, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; strsm_("L", "U", "N", "N", &c__2, &c__0, &alpha, a, &c__2, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; strsm_("L", "U", "T", "N", &c__2, &c__0, &alpha, a, &c__2, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; strsm_("R", "U", "N", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; strsm_("R", "U", "T", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; strsm_("L", "L", "N", "N", &c__2, &c__0, &alpha, a, &c__2, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; strsm_("L", "L", "T", "N", &c__2, &c__0, &alpha, a, &c__2, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; strsm_("R", "L", "N", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; strsm_("R", "L", "T", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L70; L50: infoc_1.infot = 1; ssyrk_("/", "N", &c__0, &c__0, &alpha, a, &c__1, &beta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; ssyrk_("U", "/", &c__0, &c__0, &alpha, a, &c__1, &beta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; ssyrk_("U", "N", &c_n1, &c__0, &alpha, a, &c__1, &beta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; ssyrk_("U", "T", &c_n1, &c__0, &alpha, a, &c__1, &beta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; ssyrk_("L", "N", &c_n1, &c__0, &alpha, a, &c__1, &beta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; ssyrk_("L", "T", &c_n1, &c__0, &alpha, a, &c__1, &beta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; ssyrk_("U", "N", &c__0, &c_n1, &alpha, a, &c__1, &beta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; ssyrk_("U", "T", &c__0, &c_n1, &alpha, a, &c__1, &beta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; ssyrk_("L", "N", &c__0, &c_n1, &alpha, a, &c__1, &beta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; ssyrk_("L", "T", &c__0, &c_n1, &alpha, a, &c__1, &beta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; ssyrk_("U", "N", &c__2, &c__0, &alpha, a, &c__1, &beta, c__, &c__2, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; ssyrk_("U", "T", &c__0, &c__2, &alpha, a, &c__1, &beta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; ssyrk_("L", "N", &c__2, &c__0, &alpha, a, &c__1, &beta, c__, &c__2, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; ssyrk_("L", "T", &c__0, &c__2, &alpha, a, &c__1, &beta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 10; ssyrk_("U", "N", &c__2, &c__0, &alpha, a, &c__2, &beta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 10; ssyrk_("U", "T", &c__2, &c__0, &alpha, a, &c__1, &beta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 10; ssyrk_("L", "N", &c__2, &c__0, &alpha, a, &c__2, &beta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 10; ssyrk_("L", "T", &c__2, &c__0, &alpha, a, &c__1, &beta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L70; L60: infoc_1.infot = 1; ssyr2k_("/", "N", &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; ssyr2k_("U", "/", &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; ssyr2k_("U", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; ssyr2k_("U", "T", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; ssyr2k_("L", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; ssyr2k_("L", "T", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; ssyr2k_("U", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; ssyr2k_("U", "T", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; ssyr2k_("L", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; ssyr2k_("L", "T", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; ssyr2k_("U", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__2, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; ssyr2k_("U", "T", &c__0, &c__2, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; ssyr2k_("L", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__2, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; ssyr2k_("L", "T", &c__0, &c__2, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; ssyr2k_("U", "N", &c__2, &c__0, &alpha, a, &c__2, b, &c__1, &beta, c__, & c__2, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; ssyr2k_("U", "T", &c__0, &c__2, &alpha, a, &c__2, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; ssyr2k_("L", "N", &c__2, &c__0, &alpha, a, &c__2, b, &c__1, &beta, c__, & c__2, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; ssyr2k_("L", "T", &c__0, &c__2, &alpha, a, &c__2, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 12; ssyr2k_("U", "N", &c__2, &c__0, &alpha, a, &c__2, b, &c__2, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 12; ssyr2k_("U", "T", &c__2, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 12; ssyr2k_("L", "N", &c__2, &c__0, &alpha, a, &c__2, b, &c__2, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 12; ssyr2k_("L", "T", &c__2, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); L70: if (infoc_1.ok) { io___343.ciunit = *nout; s_wsfe(&io___343); do_fio(&c__1, srnamt, (ftnlen)6); e_wsfe(); } else { io___344.ciunit = *nout; s_wsfe(&io___344); do_fio(&c__1, srnamt, (ftnlen)6); e_wsfe(); } return 0; /* End of SCHKE. */ } /* schke_ */ /* Subroutine */ int smake_(char *type__, char *uplo, char *diag, integer *m, integer *n, real *a, integer *nmax, real *aa, integer *lda, logical * reset, real *transl, ftnlen type_len, ftnlen uplo_len, ftnlen diag_len) { /* System generated locals */ integer a_dim1, a_offset, i__1, i__2; /* Builtin functions */ integer s_cmp(const char *, const char *, ftnlen, ftnlen); /* Local variables */ integer i__, j; logical gen, tri, sym; integer ibeg, iend; extern real sbeg_(logical *); logical unit, lower, upper; /* Generates values for an M by N matrix A. */ /* Stores the values in the array AA in the data structure required */ /* by the routine, with unwanted elements set to rogue value. */ /* TYPE is 'GE', 'SY' or 'TR'. */ /* Auxiliary routine for test program for Level 3 Blas. */ /* -- Written on 8-February-1989. */ /* Jack Dongarra, Argonne National Laboratory. */ /* Iain Duff, AERE Harwell. */ /* Jeremy Du Croz, Numerical Algorithms Group Ltd. */ /* Sven Hammarling, Numerical Algorithms Group Ltd. */ /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Scalars .. */ /* .. External Functions .. */ /* .. Executable Statements .. */ /* Parameter adjustments */ a_dim1 = *nmax; a_offset = 1 + a_dim1; a -= a_offset; --aa; /* Function Body */ gen = s_cmp(type__, "GE", (ftnlen)2, (ftnlen)2) == 0; sym = s_cmp(type__, "SY", (ftnlen)2, (ftnlen)2) == 0; tri = s_cmp(type__, "TR", (ftnlen)2, (ftnlen)2) == 0; upper = (sym || tri) && *(unsigned char *)uplo == 'U'; lower = (sym || tri) && *(unsigned char *)uplo == 'L'; unit = tri && *(unsigned char *)diag == 'U'; /* Generate data in array A. */ i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = *m; for (i__ = 1; i__ <= i__2; ++i__) { if (gen || upper && i__ <= j || lower && i__ >= j) { a[i__ + j * a_dim1] = sbeg_(reset) + *transl; if (i__ != j) { /* Set some elements to zero */ if (*n > 3 && j == *n / 2) { a[i__ + j * a_dim1] = 0.f; } if (sym) { a[j + i__ * a_dim1] = a[i__ + j * a_dim1]; } else if (tri) { a[j + i__ * a_dim1] = 0.f; } } } /* L10: */ } if (tri) { a[j + j * a_dim1] += 1.f; } if (unit) { a[j + j * a_dim1] = 1.f; } /* L20: */ } /* Store elements in array AS in data structure required by routine. */ if (s_cmp(type__, "GE", (ftnlen)2, (ftnlen)2) == 0) { i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = *m; for (i__ = 1; i__ <= i__2; ++i__) { aa[i__ + (j - 1) * *lda] = a[i__ + j * a_dim1]; /* L30: */ } i__2 = *lda; for (i__ = *m + 1; i__ <= i__2; ++i__) { aa[i__ + (j - 1) * *lda] = -1e10f; /* L40: */ } /* L50: */ } } else if (s_cmp(type__, "SY", (ftnlen)2, (ftnlen)2) == 0 || s_cmp(type__, "TR", (ftnlen)2, (ftnlen)2) == 0) { i__1 = *n; for (j = 1; j <= i__1; ++j) { if (upper) { ibeg = 1; if (unit) { iend = j - 1; } else { iend = j; } } else { if (unit) { ibeg = j + 1; } else { ibeg = j; } iend = *n; } i__2 = ibeg - 1; for (i__ = 1; i__ <= i__2; ++i__) { aa[i__ + (j - 1) * *lda] = -1e10f; /* L60: */ } i__2 = iend; for (i__ = ibeg; i__ <= i__2; ++i__) { aa[i__ + (j - 1) * *lda] = a[i__ + j * a_dim1]; /* L70: */ } i__2 = *lda; for (i__ = iend + 1; i__ <= i__2; ++i__) { aa[i__ + (j - 1) * *lda] = -1e10f; /* L80: */ } /* L90: */ } } return 0; /* End of SMAKE. */ } /* smake_ */ /* Subroutine */ int smmch_(char *transa, char *transb, integer *m, integer * n, integer *kk, real *alpha, real *a, integer *lda, real *b, integer * ldb, real *beta, real *c__, integer *ldc, real *ct, real *g, real *cc, integer *ldcc, real *eps, real *err, logical *fatal, integer *nout, logical *mv, ftnlen transa_len, ftnlen transb_len) { /* Format strings */ static char fmt_9999[] = "(\002 ******* FATAL ERROR - COMPUTED RESULT IS" " LESS THAN HAL\002,\002F ACCURATE *******\002,/\002 EX" "PECTED RESULT COMPU\002,\002TED RESULT\002)"; static char fmt_9998[] = "(1x,i7,2g18.6)"; static char fmt_9997[] = "(\002 THESE ARE THE RESULTS FOR COLUMN" " \002,i3)"; /* System generated locals */ integer a_dim1, a_offset, b_dim1, b_offset, c_dim1, c_offset, cc_dim1, cc_offset, i__1, i__2, i__3; real r__1, r__2; /* Builtin functions */ double sqrt(doublereal); integer s_wsfe(cilist *), e_wsfe(void), do_fio(integer *, char *, ftnlen); /* Local variables */ integer i__, j, k; real erri; logical trana, tranb; /* Fortran I/O blocks */ static cilist io___361 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___362 = { 0, 0, 0, fmt_9998, 0 }; static cilist io___363 = { 0, 0, 0, fmt_9998, 0 }; static cilist io___364 = { 0, 0, 0, fmt_9997, 0 }; /* Checks the results of the computational tests. */ /* Auxiliary routine for test program for Level 3 Blas. */ /* -- Written on 8-February-1989. */ /* Jack Dongarra, Argonne National Laboratory. */ /* Iain Duff, AERE Harwell. */ /* Jeremy Du Croz, Numerical Algorithms Group Ltd. */ /* Sven Hammarling, Numerical Algorithms Group Ltd. */ /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Scalars .. */ /* .. Intrinsic Functions .. */ /* .. Executable Statements .. */ /* Parameter adjustments */ a_dim1 = *lda; a_offset = 1 + a_dim1; a -= a_offset; b_dim1 = *ldb; b_offset = 1 + b_dim1; b -= b_offset; c_dim1 = *ldc; c_offset = 1 + c_dim1; c__ -= c_offset; --ct; --g; cc_dim1 = *ldcc; cc_offset = 1 + cc_dim1; cc -= cc_offset; /* Function Body */ trana = *(unsigned char *)transa == 'T' || *(unsigned char *)transa == 'C'; tranb = *(unsigned char *)transb == 'T' || *(unsigned char *)transb == 'C'; /* Compute expected result, one column at a time, in CT using data */ /* in A, B and C. */ /* Compute gauges in G. */ i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = *m; for (i__ = 1; i__ <= i__2; ++i__) { ct[i__] = 0.f; g[i__] = 0.f; /* L10: */ } if (! trana && ! tranb) { i__2 = *kk; for (k = 1; k <= i__2; ++k) { i__3 = *m; for (i__ = 1; i__ <= i__3; ++i__) { ct[i__] += a[i__ + k * a_dim1] * b[k + j * b_dim1]; g[i__] += (r__1 = a[i__ + k * a_dim1], abs(r__1)) * (r__2 = b[k + j * b_dim1], abs(r__2)); /* L20: */ } /* L30: */ } } else if (trana && ! tranb) { i__2 = *kk; for (k = 1; k <= i__2; ++k) { i__3 = *m; for (i__ = 1; i__ <= i__3; ++i__) { ct[i__] += a[k + i__ * a_dim1] * b[k + j * b_dim1]; g[i__] += (r__1 = a[k + i__ * a_dim1], abs(r__1)) * (r__2 = b[k + j * b_dim1], abs(r__2)); /* L40: */ } /* L50: */ } } else if (! trana && tranb) { i__2 = *kk; for (k = 1; k <= i__2; ++k) { i__3 = *m; for (i__ = 1; i__ <= i__3; ++i__) { ct[i__] += a[i__ + k * a_dim1] * b[j + k * b_dim1]; g[i__] += (r__1 = a[i__ + k * a_dim1], abs(r__1)) * (r__2 = b[j + k * b_dim1], abs(r__2)); /* L60: */ } /* L70: */ } } else if (trana && tranb) { i__2 = *kk; for (k = 1; k <= i__2; ++k) { i__3 = *m; for (i__ = 1; i__ <= i__3; ++i__) { ct[i__] += a[k + i__ * a_dim1] * b[j + k * b_dim1]; g[i__] += (r__1 = a[k + i__ * a_dim1], abs(r__1)) * (r__2 = b[j + k * b_dim1], abs(r__2)); /* L80: */ } /* L90: */ } } i__2 = *m; for (i__ = 1; i__ <= i__2; ++i__) { ct[i__] = *alpha * ct[i__] + *beta * c__[i__ + j * c_dim1]; g[i__] = abs(*alpha) * g[i__] + abs(*beta) * (r__1 = c__[i__ + j * c_dim1], abs(r__1)); /* L100: */ } /* Compute the error ratio for this result. */ *err = 0.f; i__2 = *m; for (i__ = 1; i__ <= i__2; ++i__) { erri = (r__1 = ct[i__] - cc[i__ + j * cc_dim1], abs(r__1)) / *eps; if (g[i__] != 0.f) { erri /= g[i__]; } *err = max(*err,erri); if (*err * sqrt(*eps) >= 1.f) { goto L130; } /* L110: */ } /* L120: */ } /* If the loop completes, all results are at least half accurate. */ goto L150; /* Report fatal error. */ L130: *fatal = TRUE_; io___361.ciunit = *nout; s_wsfe(&io___361); e_wsfe(); i__1 = *m; for (i__ = 1; i__ <= i__1; ++i__) { if (*mv) { io___362.ciunit = *nout; s_wsfe(&io___362); do_fio(&c__1, (char *)&i__, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&ct[i__], (ftnlen)sizeof(real)); do_fio(&c__1, (char *)&cc[i__ + j * cc_dim1], (ftnlen)sizeof(real) ); e_wsfe(); } else { io___363.ciunit = *nout; s_wsfe(&io___363); do_fio(&c__1, (char *)&i__, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&cc[i__ + j * cc_dim1], (ftnlen)sizeof(real) ); do_fio(&c__1, (char *)&ct[i__], (ftnlen)sizeof(real)); e_wsfe(); } /* L140: */ } if (*n > 1) { io___364.ciunit = *nout; s_wsfe(&io___364); do_fio(&c__1, (char *)&j, (ftnlen)sizeof(integer)); e_wsfe(); } L150: return 0; /* End of SMMCH. */ } /* smmch_ */ logical lse_(real *ri, real *rj, integer *lr) { /* System generated locals */ integer i__1; logical ret_val; /* Local variables */ integer i__; /* Tests if two arrays are identical. */ /* Auxiliary routine for test program for Level 3 Blas. */ /* -- Written on 8-February-1989. */ /* Jack Dongarra, Argonne National Laboratory. */ /* Iain Duff, AERE Harwell. */ /* Jeremy Du Croz, Numerical Algorithms Group Ltd. */ /* Sven Hammarling, Numerical Algorithms Group Ltd. */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Scalars .. */ /* .. Executable Statements .. */ /* Parameter adjustments */ --rj; --ri; /* Function Body */ i__1 = *lr; for (i__ = 1; i__ <= i__1; ++i__) { if (ri[i__] != rj[i__]) { goto L20; } /* L10: */ } ret_val = TRUE_; goto L30; L20: ret_val = FALSE_; L30: return ret_val; /* End of LSE. */ } /* lse_ */ logical lseres_(char *type__, char *uplo, integer *m, integer *n, real *aa, real *as, integer *lda, ftnlen type_len, ftnlen uplo_len) { /* System generated locals */ integer aa_dim1, aa_offset, as_dim1, as_offset, i__1, i__2; logical ret_val; /* Builtin functions */ integer s_cmp(const char *, const char *, ftnlen, ftnlen); /* Local variables */ integer i__, j, ibeg, iend; logical upper; /* Tests if selected elements in two arrays are equal. */ /* TYPE is 'GE' or 'SY'. */ /* Auxiliary routine for test program for Level 3 Blas. */ /* -- Written on 8-February-1989. */ /* Jack Dongarra, Argonne National Laboratory. */ /* Iain Duff, AERE Harwell. */ /* Jeremy Du Croz, Numerical Algorithms Group Ltd. */ /* Sven Hammarling, Numerical Algorithms Group Ltd. */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Scalars .. */ /* .. Executable Statements .. */ /* Parameter adjustments */ as_dim1 = *lda; as_offset = 1 + as_dim1; as -= as_offset; aa_dim1 = *lda; aa_offset = 1 + aa_dim1; aa -= aa_offset; /* Function Body */ upper = *(unsigned char *)uplo == 'U'; if (s_cmp(type__, "GE", (ftnlen)2, (ftnlen)2) == 0) { i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = *lda; for (i__ = *m + 1; i__ <= i__2; ++i__) { if (aa[i__ + j * aa_dim1] != as[i__ + j * as_dim1]) { goto L70; } /* L10: */ } /* L20: */ } } else if (s_cmp(type__, "SY", (ftnlen)2, (ftnlen)2) == 0) { i__1 = *n; for (j = 1; j <= i__1; ++j) { if (upper) { ibeg = 1; iend = j; } else { ibeg = j; iend = *n; } i__2 = ibeg - 1; for (i__ = 1; i__ <= i__2; ++i__) { if (aa[i__ + j * aa_dim1] != as[i__ + j * as_dim1]) { goto L70; } /* L30: */ } i__2 = *lda; for (i__ = iend + 1; i__ <= i__2; ++i__) { if (aa[i__ + j * aa_dim1] != as[i__ + j * as_dim1]) { goto L70; } /* L40: */ } /* L50: */ } } ret_val = TRUE_; goto L80; L70: ret_val = FALSE_; L80: return ret_val; /* End of LSERES. */ } /* lseres_ */ real sbeg_(logical *reset) { /* System generated locals */ real ret_val; /* Local variables */ static integer i__, ic, mi; /* Generates random numbers uniformly distributed between -0.5 and 0.5. */ /* Auxiliary routine for test program for Level 3 Blas. */ /* -- Written on 8-February-1989. */ /* Jack Dongarra, Argonne National Laboratory. */ /* Iain Duff, AERE Harwell. */ /* Jeremy Du Croz, Numerical Algorithms Group Ltd. */ /* Sven Hammarling, Numerical Algorithms Group Ltd. */ /* .. Scalar Arguments .. */ /* .. Local Scalars .. */ /* .. Save statement .. */ /* .. Executable Statements .. */ if (*reset) { /* Initialize local variables. */ mi = 891; i__ = 7; ic = 0; *reset = FALSE_; } /* The sequence of values of I is bounded between 1 and 999. */ /* If initial I = 1,2,3,6,7 or 9, the period will be 50. */ /* If initial I = 4 or 8, the period will be 25. */ /* If initial I = 5, the period will be 10. */ /* IC is used to break up the period by skipping 1 value of I in 6. */ ++ic; L10: i__ *= mi; i__ -= i__ / 1000 * 1000; if (ic >= 5) { ic = 0; goto L10; } ret_val = (i__ - 500) / 1001.f; return ret_val; /* End of SBEG. */ } /* sbeg_ */ real sdiff_(real *x, real *y) { /* System generated locals */ real ret_val; /* Auxiliary routine for test program for Level 3 Blas. */ /* -- Written on 8-February-1989. */ /* Jack Dongarra, Argonne National Laboratory. */ /* Iain Duff, AERE Harwell. */ /* Jeremy Du Croz, Numerical Algorithms Group Ltd. */ /* Sven Hammarling, Numerical Algorithms Group Ltd. */ /* .. Scalar Arguments .. */ /* .. Executable Statements .. */ ret_val = *x - *y; return ret_val; /* End of SDIFF. */ } /* sdiff_ */ /* Subroutine */ int chkxer_(char *srnamt, integer *infot, integer *nout, logical *lerr, logical *ok, ftnlen srnamt_len) { /* Format strings */ static char fmt_9999[] = "(\002 ***** ILLEGAL VALUE OF PARAMETER NUMBER" " \002,i2,\002 NOT D\002,\002ETECTED BY \002,a6,\002 *****\002)"; /* Builtin functions */ integer s_wsfe(cilist *), do_fio(integer *, char *, ftnlen), e_wsfe(void); /* Fortran I/O blocks */ static cilist io___374 = { 0, 0, 0, fmt_9999, 0 }; /* Tests whether XERBLA has detected an error when it should. */ /* Auxiliary routine for test program for Level 3 Blas. */ /* -- Written on 8-February-1989. */ /* Jack Dongarra, Argonne National Laboratory. */ /* Iain Duff, AERE Harwell. */ /* Jeremy Du Croz, Numerical Algorithms Group Ltd. */ /* Sven Hammarling, Numerical Algorithms Group Ltd. */ /* .. Scalar Arguments .. */ /* .. Executable Statements .. */ if (! (*lerr)) { io___374.ciunit = *nout; s_wsfe(&io___374); do_fio(&c__1, (char *)&(*infot), (ftnlen)sizeof(integer)); do_fio(&c__1, srnamt, (ftnlen)6); e_wsfe(); *ok = FALSE_; } *lerr = FALSE_; return 0; /* End of CHKXER. */ } /* chkxer_ */ /* Subroutine */ int xerbla_(char *srname, integer *info, ftnlen srname_len) { /* Format strings */ static char fmt_9999[] = "(\002 ******* XERBLA WAS CALLED WITH INFO =" " \002,i6,\002 INSTEAD\002,\002 OF \002,i2,\002 *******\002)"; static char fmt_9997[] = "(\002 ******* XERBLA WAS CALLED WITH INFO =" " \002,i6,\002 *******\002)"; static char fmt_9998[] = "(\002 ******* XERBLA WAS CALLED WITH SRNAME =" " \002,a6,\002 INSTE\002,\002AD OF \002,a6,\002 *******\002)"; /* Builtin functions */ integer s_wsfe(cilist *), do_fio(integer *, char *, ftnlen), e_wsfe(void), s_cmp(const char *, const char *, ftnlen, ftnlen); /* Fortran I/O blocks */ static cilist io___375 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___376 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___377 = { 0, 0, 0, fmt_9998, 0 }; /* This is a special version of XERBLA to be used only as part of */ /* the test program for testing error exits from the Level 3 BLAS */ /* routines. */ /* XERBLA is an error handler for the Level 3 BLAS routines. */ /* It is called by the Level 3 BLAS routines if an input parameter is */ /* invalid. */ /* Auxiliary routine for test program for Level 3 Blas. */ /* -- Written on 8-February-1989. */ /* Jack Dongarra, Argonne National Laboratory. */ /* Iain Duff, AERE Harwell. */ /* Jeremy Du Croz, Numerical Algorithms Group Ltd. */ /* Sven Hammarling, Numerical Algorithms Group Ltd. */ /* .. Scalar Arguments .. */ /* .. Scalars in Common .. */ /* .. Common blocks .. */ /* .. Executable Statements .. */ infoc_2.lerr = TRUE_; if (*info != infoc_2.infot) { if (infoc_2.infot != 0) { io___375.ciunit = infoc_2.nout; s_wsfe(&io___375); do_fio(&c__1, (char *)&(*info), (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&infoc_2.infot, (ftnlen)sizeof(integer)); e_wsfe(); } else { io___376.ciunit = infoc_2.nout; s_wsfe(&io___376); do_fio(&c__1, (char *)&(*info), (ftnlen)sizeof(integer)); e_wsfe(); } infoc_2.ok = FALSE_; } if (s_cmp(srname, srnamc_1.srnamt, (ftnlen)6, (ftnlen)6) != 0) { io___377.ciunit = infoc_2.nout; s_wsfe(&io___377); do_fio(&c__1, srname, (ftnlen)6); do_fio(&c__1, srnamc_1.srnamt, (ftnlen)6); e_wsfe(); infoc_2.ok = FALSE_; } return 0; /* End of XERBLA */ } /* xerbla_ */ /* Main program alias */ int sblat3_ () { main (); return 0; } blis-0.9.0/blastest/src/zblat1.c000066400000000000000000000671541422157504600164450ustar00rootroot00000000000000/* zblat1.f -- translated by f2c (version 20100827). You must link the resulting object file with libf2c: on Microsoft Windows system, link with libf2c.lib; on Linux or Unix systems, link with .../path/to/libf2c.a -lm or, if you install libf2c.a in a standard place, with -lf2c -lm -- in that order, at the end of the command line, as in cc *.o -lf2c -lm Source for libf2c is in /netlib/f2c/libf2c.zip, e.g., http://www.netlib.org/f2c/libf2c.zip */ #include "f2c.h" /* Common Block Declarations */ struct { integer icase, n, incx, incy, mode; logical pass; } combla_; #define combla_1 combla_ /* Table of constant values */ static integer c__1 = 1; static integer c__9 = 9; static integer c__5 = 5; static doublereal c_b43 = 1.; static doublereal c_b52 = 0.; /* > \brief \b ZBLAT1 */ /* =========== DOCUMENTATION =========== */ /* Online html documentation available at */ /* http://www.netlib.org/lapack/explore-html/ */ /* Definition: */ /* =========== */ /* PROGRAM ZBLAT1 */ /* > \par Purpose: */ /* ============= */ /* > */ /* > \verbatim */ /* > */ /* > Test program for the COMPLEX*16 Level 1 BLAS. */ /* > */ /* > Based upon the original BLAS test routine together with: */ /* > F06GAF Example Program Text */ /* > \endverbatim */ /* Authors: */ /* ======== */ /* > \author Univ. of Tennessee */ /* > \author Univ. of California Berkeley */ /* > \author Univ. of Colorado Denver */ /* > \author NAG Ltd. */ /* > \date April 2012 */ /* > \ingroup complex16_blas_testing */ /* ===================================================================== */ /* Main program */ int main(void) { /* Initialized data */ static doublereal sfac = 9.765625e-4; /* Format strings */ static char fmt_99999[] = "(\002 Complex BLAS Test Program Results\002,/" "1x)"; static char fmt_99998[] = "(\002 ----" "- PASS -----\002)"; /* Builtin functions */ integer s_wsfe(cilist *), e_wsfe(void); /* Subroutine */ int s_stop(char *, ftnlen); /* Local variables */ integer ic; extern /* Subroutine */ int check1_(doublereal *), check2_(doublereal *), header_(void); /* Fortran I/O blocks */ static cilist io___2 = { 0, 6, 0, fmt_99999, 0 }; static cilist io___4 = { 0, 6, 0, fmt_99998, 0 }; /* -- Reference BLAS test routine (version 3.4.1) -- */ /* -- Reference BLAS is a software package provided by Univ. of Tennessee, -- */ /* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- */ /* April 2012 */ /* ===================================================================== */ /* .. Parameters .. */ /* .. Scalars in Common .. */ /* .. Local Scalars .. */ /* .. External Subroutines .. */ /* .. Common blocks .. */ /* .. Data statements .. */ /* .. Executable Statements .. */ s_wsfe(&io___2); e_wsfe(); for (ic = 1; ic <= 10; ++ic) { combla_1.icase = ic; header_(); /* Initialize PASS, INCX, INCY, and MODE for a new case. */ /* The value 9999 for INCX, INCY or MODE will appear in the */ /* detailed output, if any, for cases that do not involve */ /* these parameters. */ combla_1.pass = TRUE_; combla_1.incx = 9999; combla_1.incy = 9999; combla_1.mode = 9999; if (combla_1.icase <= 5) { check2_(&sfac); } else if (combla_1.icase >= 6) { check1_(&sfac); } /* -- Print */ if (combla_1.pass) { s_wsfe(&io___4); e_wsfe(); } /* L20: */ } s_stop("", (ftnlen)0); return 0; } /* main */ /* Subroutine */ int header_(void) { /* Initialized data */ static char l[6*10] = "ZDOTC " "ZDOTU " "ZAXPY " "ZCOPY " "ZSWAP " "DZNR" "M2" "DZASUM" "ZSCAL " "ZDSCAL" "IZAMAX"; /* Format strings */ static char fmt_99999[] = "(/\002 Test of subprogram number\002,i3,12x,a" "6)"; /* Builtin functions */ integer s_wsfe(cilist *), do_fio(integer *, char *, ftnlen), e_wsfe(void); /* Fortran I/O blocks */ static cilist io___6 = { 0, 6, 0, fmt_99999, 0 }; /* .. Parameters .. */ /* .. Scalars in Common .. */ /* .. Local Arrays .. */ /* .. Common blocks .. */ /* .. Data statements .. */ /* .. Executable Statements .. */ s_wsfe(&io___6); do_fio(&c__1, (char *)&combla_1.icase, (ftnlen)sizeof(integer)); do_fio(&c__1, l + (0 + (0 + (combla_1.icase - 1) * 6)), (ftnlen)6); e_wsfe(); return 0; } /* header_ */ /* Subroutine */ int check1_(doublereal *sfac) { /* Initialized data */ static doublereal strue2[5] = { 0.,.5,.6,.7,.8 }; static doublereal strue4[5] = { 0.,.7,1.,1.3,1.6 }; static doublecomplex ctrue5[80] /* was [8][5][2] */ = { {.1,.1},{1., 2.},{1.,2.},{1.,2.},{1.,2.},{1.,2.},{1.,2.},{1.,2.},{-.16,-.37},{ 3.,4.},{3.,4.},{3.,4.},{3.,4.},{3.,4.},{3.,4.},{3.,4.},{-.17,-.19} ,{.13,-.39},{5.,6.},{5.,6.},{5.,6.},{5.,6.},{5.,6.},{5.,6.},{.11, -.03},{-.17,.46},{-.17,-.19},{7.,8.},{7.,8.},{7.,8.},{7.,8.},{7., 8.},{.19,-.17},{.2,-.35},{.35,.2},{.14,.08},{2.,3.},{2.,3.},{2., 3.},{2.,3.},{.1,.1},{4.,5.},{4.,5.},{4.,5.},{4.,5.},{4.,5.},{4., 5.},{4.,5.},{-.16,-.37},{6.,7.},{6.,7.},{6.,7.},{6.,7.},{6.,7.},{ 6.,7.},{6.,7.},{-.17,-.19},{8.,9.},{.13,-.39},{2.,5.},{2.,5.},{2., 5.},{2.,5.},{2.,5.},{.11,-.03},{3.,6.},{-.17,.46},{4.,7.},{-.17, -.19},{7.,2.},{7.,2.},{7.,2.},{.19,-.17},{5.,8.},{.2,-.35},{6.,9.} ,{.35,.2},{8.,3.},{.14,.08},{9.,4.} }; static doublecomplex ctrue6[80] /* was [8][5][2] */ = { {.1,.1},{1., 2.},{1.,2.},{1.,2.},{1.,2.},{1.,2.},{1.,2.},{1.,2.},{.09,-.12},{ 3.,4.},{3.,4.},{3.,4.},{3.,4.},{3.,4.},{3.,4.},{3.,4.},{.03,-.09}, {.15,-.03},{5.,6.},{5.,6.},{5.,6.},{5.,6.},{5.,6.},{5.,6.},{.03, .03},{-.18,.03},{.03,-.09},{7.,8.},{7.,8.},{7.,8.},{7.,8.},{7.,8.} ,{.09,.03},{.15,0.},{0.,.15},{0.,.06},{2.,3.},{2.,3.},{2.,3.},{2., 3.},{.1,.1},{4.,5.},{4.,5.},{4.,5.},{4.,5.},{4.,5.},{4.,5.},{4., 5.},{.09,-.12},{6.,7.},{6.,7.},{6.,7.},{6.,7.},{6.,7.},{6.,7.},{ 6.,7.},{.03,-.09},{8.,9.},{.15,-.03},{2.,5.},{2.,5.},{2.,5.},{2., 5.},{2.,5.},{.03,.03},{3.,6.},{-.18,.03},{4.,7.},{.03,-.09},{7., 2.},{7.,2.},{7.,2.},{.09,.03},{5.,8.},{.15,0.},{6.,9.},{0.,.15},{ 8.,3.},{0.,.06},{9.,4.} }; static integer itrue3[5] = { 0,1,2,2,2 }; static doublereal sa = .3; static doublecomplex ca = {.4,-.7}; static doublecomplex cv[80] /* was [8][5][2] */ = { {.1,.1},{1.,2.},{1., 2.},{1.,2.},{1.,2.},{1.,2.},{1.,2.},{1.,2.},{.3,-.4},{3.,4.},{3., 4.},{3.,4.},{3.,4.},{3.,4.},{3.,4.},{3.,4.},{.1,-.3},{.5,-.1},{5., 6.},{5.,6.},{5.,6.},{5.,6.},{5.,6.},{5.,6.},{.1,.1},{-.6,.1},{.1, -.3},{7.,8.},{7.,8.},{7.,8.},{7.,8.},{7.,8.},{.3,.1},{.5,0.},{0., .5},{0.,.2},{2.,3.},{2.,3.},{2.,3.},{2.,3.},{.1,.1},{4.,5.},{4., 5.},{4.,5.},{4.,5.},{4.,5.},{4.,5.},{4.,5.},{.3,-.4},{6.,7.},{6., 7.},{6.,7.},{6.,7.},{6.,7.},{6.,7.},{6.,7.},{.1,-.3},{8.,9.},{.5, -.1},{2.,5.},{2.,5.},{2.,5.},{2.,5.},{2.,5.},{.1,.1},{3.,6.},{-.6, .1},{4.,7.},{.1,-.3},{7.,2.},{7.,2.},{7.,2.},{.3,.1},{5.,8.},{.5, 0.},{6.,9.},{0.,.5},{8.,3.},{0.,.2},{9.,4.} }; /* System generated locals */ integer i__1, i__2, i__3; doublereal d__1; doublecomplex z__1; /* Builtin functions */ integer s_wsle(cilist *), do_lio(integer *, integer *, char *, ftnlen), e_wsle(void); /* Subroutine */ int s_stop(char *, ftnlen); /* Local variables */ integer i__; doublecomplex cx[8]; integer np1, len; extern /* Subroutine */ int zscal_(integer *, doublecomplex *, doublecomplex *, integer *), ctest_(integer *, doublecomplex *, doublecomplex *, doublecomplex *, doublereal *); doublecomplex mwpcs[5], mwpct[5]; extern /* Subroutine */ int itest1_(integer *, integer *); extern doublereal dznrm2_(integer *, doublecomplex *, integer *); extern /* Subroutine */ int stest1_(doublereal *, doublereal *, doublereal *, doublereal *), zdscal_(integer *, doublereal *, doublecomplex *, integer *); extern integer izamax_(integer *, doublecomplex *, integer *); extern doublereal dzasum_(integer *, doublecomplex *, integer *); /* Fortran I/O blocks */ static cilist io___19 = { 0, 6, 0, 0, 0 }; /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Scalars in Common .. */ /* .. Local Scalars .. */ /* .. Local Arrays .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. Common blocks .. */ /* .. Data statements .. */ /* .. Executable Statements .. */ for (combla_1.incx = 1; combla_1.incx <= 2; ++combla_1.incx) { for (np1 = 1; np1 <= 5; ++np1) { combla_1.n = np1 - 1; len = max(combla_1.n,1) << 1; /* .. Set vector arguments .. */ i__1 = len; for (i__ = 1; i__ <= i__1; ++i__) { i__2 = i__ - 1; i__3 = i__ + (np1 + combla_1.incx * 5 << 3) - 49; cx[i__2].r = cv[i__3].r, cx[i__2].i = cv[i__3].i; /* L20: */ } if (combla_1.icase == 6) { /* .. DZNRM2 .. */ d__1 = dznrm2_(&combla_1.n, cx, &combla_1.incx); stest1_(&d__1, &strue2[np1 - 1], &strue2[np1 - 1], sfac); } else if (combla_1.icase == 7) { /* .. DZASUM .. */ d__1 = dzasum_(&combla_1.n, cx, &combla_1.incx); stest1_(&d__1, &strue4[np1 - 1], &strue4[np1 - 1], sfac); } else if (combla_1.icase == 8) { /* .. ZSCAL .. */ zscal_(&combla_1.n, &ca, cx, &combla_1.incx); ctest_(&len, cx, &ctrue5[(np1 + combla_1.incx * 5 << 3) - 48], &ctrue5[(np1 + combla_1.incx * 5 << 3) - 48], sfac); } else if (combla_1.icase == 9) { /* .. ZDSCAL .. */ zdscal_(&combla_1.n, &sa, cx, &combla_1.incx); ctest_(&len, cx, &ctrue6[(np1 + combla_1.incx * 5 << 3) - 48], &ctrue6[(np1 + combla_1.incx * 5 << 3) - 48], sfac); } else if (combla_1.icase == 10) { /* .. IZAMAX .. */ i__1 = izamax_(&combla_1.n, cx, &combla_1.incx); itest1_(&i__1, &itrue3[np1 - 1]); } else { s_wsle(&io___19); do_lio(&c__9, &c__1, " Shouldn't be here in CHECK1", (ftnlen) 28); e_wsle(); s_stop("", (ftnlen)0); } /* L40: */ } /* L60: */ } combla_1.incx = 1; if (combla_1.icase == 8) { /* ZSCAL */ /* Add a test for alpha equal to zero. */ ca.r = 0., ca.i = 0.; for (i__ = 1; i__ <= 5; ++i__) { i__1 = i__ - 1; mwpct[i__1].r = 0., mwpct[i__1].i = 0.; i__1 = i__ - 1; mwpcs[i__1].r = 1., mwpcs[i__1].i = 1.; /* L80: */ } zscal_(&c__5, &ca, cx, &combla_1.incx); ctest_(&c__5, cx, mwpct, mwpcs, sfac); } else if (combla_1.icase == 9) { /* ZDSCAL */ /* Add a test for alpha equal to zero. */ sa = 0.; for (i__ = 1; i__ <= 5; ++i__) { i__1 = i__ - 1; mwpct[i__1].r = 0., mwpct[i__1].i = 0.; i__1 = i__ - 1; mwpcs[i__1].r = 1., mwpcs[i__1].i = 1.; /* L100: */ } zdscal_(&c__5, &sa, cx, &combla_1.incx); ctest_(&c__5, cx, mwpct, mwpcs, sfac); /* Add a test for alpha equal to one. */ sa = 1.; for (i__ = 1; i__ <= 5; ++i__) { i__1 = i__ - 1; i__2 = i__ - 1; mwpct[i__1].r = cx[i__2].r, mwpct[i__1].i = cx[i__2].i; i__1 = i__ - 1; i__2 = i__ - 1; mwpcs[i__1].r = cx[i__2].r, mwpcs[i__1].i = cx[i__2].i; /* L120: */ } zdscal_(&c__5, &sa, cx, &combla_1.incx); ctest_(&c__5, cx, mwpct, mwpcs, sfac); /* Add a test for alpha equal to minus one. */ sa = -1.; for (i__ = 1; i__ <= 5; ++i__) { i__1 = i__ - 1; i__2 = i__ - 1; z__1.r = -cx[i__2].r, z__1.i = -cx[i__2].i; mwpct[i__1].r = z__1.r, mwpct[i__1].i = z__1.i; i__1 = i__ - 1; i__2 = i__ - 1; z__1.r = -cx[i__2].r, z__1.i = -cx[i__2].i; mwpcs[i__1].r = z__1.r, mwpcs[i__1].i = z__1.i; /* L140: */ } zdscal_(&c__5, &sa, cx, &combla_1.incx); ctest_(&c__5, cx, mwpct, mwpcs, sfac); } return 0; } /* check1_ */ /* Subroutine */ int check2_(doublereal *sfac) { /* Initialized data */ static doublecomplex ca = {.4,-.7}; static integer incxs[4] = { 1,2,-2,-1 }; static integer incys[4] = { 1,-2,1,-2 }; static integer lens[8] /* was [4][2] */ = { 1,1,2,4,1,1,3,7 }; static integer ns[4] = { 0,1,2,4 }; static doublecomplex cx1[7] = { {.7,-.8},{-.4,-.7},{-.1,-.9},{.2,-.8},{ -.9,-.4},{.1,.4},{-.6,.6} }; static doublecomplex cy1[7] = { {.6,-.6},{-.9,.5},{.7,-.6},{.1,-.5},{-.1, -.2},{-.5,-.3},{.8,-.7} }; static doublecomplex ct8[112] /* was [7][4][4] */ = { {.6,-.6},{0., 0.},{0.,0.},{0.,0.},{0.,0.},{0.,0.},{0.,0.},{.32,-1.41},{0.,0.},{ 0.,0.},{0.,0.},{0.,0.},{0.,0.},{0.,0.},{.32,-1.41},{-1.55,.5},{0., 0.},{0.,0.},{0.,0.},{0.,0.},{0.,0.},{.32,-1.41},{-1.55,.5},{.03, -.89},{-.38,-.96},{0.,0.},{0.,0.},{0.,0.},{.6,-.6},{0.,0.},{0.,0.} ,{0.,0.},{0.,0.},{0.,0.},{0.,0.},{.32,-1.41},{0.,0.},{0.,0.},{0., 0.},{0.,0.},{0.,0.},{0.,0.},{-.07,-.89},{-.9,.5},{.42,-1.41},{0., 0.},{0.,0.},{0.,0.},{0.,0.},{.78,.06},{-.9,.5},{.06,-.13},{.1,-.5} ,{-.77,-.49},{-.5,-.3},{.52,-1.51},{.6,-.6},{0.,0.},{0.,0.},{0., 0.},{0.,0.},{0.,0.},{0.,0.},{.32,-1.41},{0.,0.},{0.,0.},{0.,0.},{ 0.,0.},{0.,0.},{0.,0.},{-.07,-.89},{-1.18,-.31},{0.,0.},{0.,0.},{ 0.,0.},{0.,0.},{0.,0.},{.78,.06},{-1.54,.97},{.03,-.89},{-.18, -1.31},{0.,0.},{0.,0.},{0.,0.},{.6,-.6},{0.,0.},{0.,0.},{0.,0.},{ 0.,0.},{0.,0.},{0.,0.},{.32,-1.41},{0.,0.},{0.,0.},{0.,0.},{0.,0.} ,{0.,0.},{0.,0.},{.32,-1.41},{-.9,.5},{.05,-.6},{0.,0.},{0.,0.},{ 0.,0.},{0.,0.},{.32,-1.41},{-.9,.5},{.05,-.6},{.1,-.5},{-.77,-.49} ,{-.5,-.3},{.32,-1.16} }; static doublecomplex ct7[16] /* was [4][4] */ = { {0.,0.},{-.06, -.9},{.65,-.47},{-.34,-1.22},{0.,0.},{-.06,-.9},{-.59,-1.46},{ -1.04,-.04},{0.,0.},{-.06,-.9},{-.83,.59},{.07,-.37},{0.,0.},{ -.06,-.9},{-.76,-1.15},{-1.33,-1.82} }; static doublecomplex ct6[16] /* was [4][4] */ = { {0.,0.},{.9,.06}, {.91,-.77},{1.8,-.1},{0.,0.},{.9,.06},{1.45,.74},{.2,.9},{0.,0.},{ .9,.06},{-.55,.23},{.83,-.39},{0.,0.},{.9,.06},{1.04,.79},{1.95, 1.22} }; static doublecomplex ct10x[112] /* was [7][4][4] */ = { {.7,-.8},{0., 0.},{0.,0.},{0.,0.},{0.,0.},{0.,0.},{0.,0.},{.6,-.6},{0.,0.},{0., 0.},{0.,0.},{0.,0.},{0.,0.},{0.,0.},{.6,-.6},{-.9,.5},{0.,0.},{0., 0.},{0.,0.},{0.,0.},{0.,0.},{.6,-.6},{-.9,.5},{.7,-.6},{.1,-.5},{ 0.,0.},{0.,0.},{0.,0.},{.7,-.8},{0.,0.},{0.,0.},{0.,0.},{0.,0.},{ 0.,0.},{0.,0.},{.6,-.6},{0.,0.},{0.,0.},{0.,0.},{0.,0.},{0.,0.},{ 0.,0.},{.7,-.6},{-.4,-.7},{.6,-.6},{0.,0.},{0.,0.},{0.,0.},{0.,0.} ,{.8,-.7},{-.4,-.7},{-.1,-.2},{.2,-.8},{.7,-.6},{.1,.4},{.6,-.6},{ .7,-.8},{0.,0.},{0.,0.},{0.,0.},{0.,0.},{0.,0.},{0.,0.},{.6,-.6},{ 0.,0.},{0.,0.},{0.,0.},{0.,0.},{0.,0.},{0.,0.},{-.9,.5},{-.4,-.7}, {.6,-.6},{0.,0.},{0.,0.},{0.,0.},{0.,0.},{.1,-.5},{-.4,-.7},{.7, -.6},{.2,-.8},{-.9,.5},{.1,.4},{.6,-.6},{.7,-.8},{0.,0.},{0.,0.},{ 0.,0.},{0.,0.},{0.,0.},{0.,0.},{.6,-.6},{0.,0.},{0.,0.},{0.,0.},{ 0.,0.},{0.,0.},{0.,0.},{.6,-.6},{.7,-.6},{0.,0.},{0.,0.},{0.,0.},{ 0.,0.},{0.,0.},{.6,-.6},{.7,-.6},{-.1,-.2},{.8,-.7},{0.,0.},{0., 0.},{0.,0.} }; static doublecomplex ct10y[112] /* was [7][4][4] */ = { {.6,-.6},{0., 0.},{0.,0.},{0.,0.},{0.,0.},{0.,0.},{0.,0.},{.7,-.8},{0.,0.},{0., 0.},{0.,0.},{0.,0.},{0.,0.},{0.,0.},{.7,-.8},{-.4,-.7},{0.,0.},{ 0.,0.},{0.,0.},{0.,0.},{0.,0.},{.7,-.8},{-.4,-.7},{-.1,-.9},{.2, -.8},{0.,0.},{0.,0.},{0.,0.},{.6,-.6},{0.,0.},{0.,0.},{0.,0.},{0., 0.},{0.,0.},{0.,0.},{.7,-.8},{0.,0.},{0.,0.},{0.,0.},{0.,0.},{0., 0.},{0.,0.},{-.1,-.9},{-.9,.5},{.7,-.8},{0.,0.},{0.,0.},{0.,0.},{ 0.,0.},{-.6,.6},{-.9,.5},{-.9,-.4},{.1,-.5},{-.1,-.9},{-.5,-.3},{ .7,-.8},{.6,-.6},{0.,0.},{0.,0.},{0.,0.},{0.,0.},{0.,0.},{0.,0.},{ .7,-.8},{0.,0.},{0.,0.},{0.,0.},{0.,0.},{0.,0.},{0.,0.},{-.1,-.9}, {.7,-.8},{0.,0.},{0.,0.},{0.,0.},{0.,0.},{0.,0.},{-.6,.6},{-.9, -.4},{-.1,-.9},{.7,-.8},{0.,0.},{0.,0.},{0.,0.},{.6,-.6},{0.,0.},{ 0.,0.},{0.,0.},{0.,0.},{0.,0.},{0.,0.},{.7,-.8},{0.,0.},{0.,0.},{ 0.,0.},{0.,0.},{0.,0.},{0.,0.},{.7,-.8},{-.9,.5},{-.4,-.7},{0.,0.} ,{0.,0.},{0.,0.},{0.,0.},{.7,-.8},{-.9,.5},{-.4,-.7},{.1,-.5},{ -.1,-.9},{-.5,-.3},{.2,-.8} }; static doublecomplex csize1[4] = { {0.,0.},{.9,.9},{1.63,1.73},{2.9,2.78} }; static doublecomplex csize3[14] = { {0.,0.},{0.,0.},{0.,0.},{0.,0.},{0., 0.},{0.,0.},{0.,0.},{1.17,1.17},{1.17,1.17},{1.17,1.17},{1.17, 1.17},{1.17,1.17},{1.17,1.17},{1.17,1.17} }; static doublecomplex csize2[14] /* was [7][2] */ = { {0.,0.},{0.,0.},{ 0.,0.},{0.,0.},{0.,0.},{0.,0.},{0.,0.},{1.54,1.54},{1.54,1.54},{ 1.54,1.54},{1.54,1.54},{1.54,1.54},{1.54,1.54},{1.54,1.54} }; /* System generated locals */ integer i__1, i__2; doublecomplex z__1; /* Builtin functions */ integer s_wsle(cilist *), do_lio(integer *, integer *, char *, ftnlen), e_wsle(void); /* Subroutine */ int s_stop(char *, ftnlen); /* Local variables */ integer i__, ki, kn; doublecomplex cx[7], cy[7]; integer mx, my; doublecomplex cdot[1]; integer lenx, leny; extern /* Subroutine */ int ctest_(integer *, doublecomplex *, doublecomplex *, doublecomplex *, doublereal *); extern /* Double Complex */ doublecomplex zdotc_(integer *, doublecomplex *, integer *, doublecomplex *, integer *); integer ksize; extern /* Subroutine */ int zcopy_(integer *, doublecomplex *, integer *, doublecomplex *, integer *); extern /* Double Complex */ doublecomplex zdotu_(integer *, doublecomplex *, integer *, doublecomplex *, integer *); extern /* Subroutine */ int zswap_(integer *, doublecomplex *, integer *, doublecomplex *, integer *), zaxpy_(integer *, doublecomplex *, doublecomplex *, integer *, doublecomplex *, integer *); /* Fortran I/O blocks */ static cilist io___48 = { 0, 6, 0, 0, 0 }; /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Scalars in Common .. */ /* .. Local Scalars .. */ /* .. Local Arrays .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. Common blocks .. */ /* .. Data statements .. */ /* .. Executable Statements .. */ for (ki = 1; ki <= 4; ++ki) { combla_1.incx = incxs[ki - 1]; combla_1.incy = incys[ki - 1]; mx = abs(combla_1.incx); my = abs(combla_1.incy); for (kn = 1; kn <= 4; ++kn) { combla_1.n = ns[kn - 1]; ksize = min(2,kn); lenx = lens[kn + (mx << 2) - 5]; leny = lens[kn + (my << 2) - 5]; /* .. initialize all argument arrays .. */ for (i__ = 1; i__ <= 7; ++i__) { i__1 = i__ - 1; i__2 = i__ - 1; cx[i__1].r = cx1[i__2].r, cx[i__1].i = cx1[i__2].i; i__1 = i__ - 1; i__2 = i__ - 1; cy[i__1].r = cy1[i__2].r, cy[i__1].i = cy1[i__2].i; /* L20: */ } if (combla_1.icase == 1) { /* .. ZDOTC .. */ z__1 = zdotc_(&combla_1.n, cx, &combla_1.incx, cy, & combla_1.incy); cdot[0].r = z__1.r, cdot[0].i = z__1.i; ctest_(&c__1, cdot, &ct6[kn + (ki << 2) - 5], &csize1[kn - 1], sfac); } else if (combla_1.icase == 2) { /* .. ZDOTU .. */ z__1 = zdotu_(&combla_1.n, cx, &combla_1.incx, cy, & combla_1.incy); cdot[0].r = z__1.r, cdot[0].i = z__1.i; ctest_(&c__1, cdot, &ct7[kn + (ki << 2) - 5], &csize1[kn - 1], sfac); } else if (combla_1.icase == 3) { /* .. ZAXPY .. */ zaxpy_(&combla_1.n, &ca, cx, &combla_1.incx, cy, & combla_1.incy); ctest_(&leny, cy, &ct8[(kn + (ki << 2)) * 7 - 35], &csize2[ ksize * 7 - 7], sfac); } else if (combla_1.icase == 4) { /* .. ZCOPY .. */ zcopy_(&combla_1.n, cx, &combla_1.incx, cy, &combla_1.incy); ctest_(&leny, cy, &ct10y[(kn + (ki << 2)) * 7 - 35], csize3, & c_b43); } else if (combla_1.icase == 5) { /* .. ZSWAP .. */ zswap_(&combla_1.n, cx, &combla_1.incx, cy, &combla_1.incy); ctest_(&lenx, cx, &ct10x[(kn + (ki << 2)) * 7 - 35], csize3, & c_b43); ctest_(&leny, cy, &ct10y[(kn + (ki << 2)) * 7 - 35], csize3, & c_b43); } else { s_wsle(&io___48); do_lio(&c__9, &c__1, " Shouldn't be here in CHECK2", (ftnlen) 28); e_wsle(); s_stop("", (ftnlen)0); } /* L40: */ } /* L60: */ } return 0; } /* check2_ */ /* Subroutine */ int stest_(integer *len, doublereal *scomp, doublereal * strue, doublereal *ssize, doublereal *sfac) { /* Format strings */ static char fmt_99999[] = "(\002 F" "AIL\002)"; static char fmt_99998[] = "(/\002 CASE N INCX INCY MODE I " " \002,\002 COMP(I) TRU" "E(I) DIFFERENCE\002,\002 SIZE(I)\002,/1x)"; static char fmt_99997[] = "(1x,i4,i3,3i5,i3,2d36.8,2d12.4)"; /* System generated locals */ integer i__1; doublereal d__1, d__2; /* Builtin functions */ integer s_wsfe(cilist *), e_wsfe(void), do_fio(integer *, char *, ftnlen); /* Local variables */ integer i__; doublereal sd; extern double d_epsilon_(doublereal *); /* Fortran I/O blocks */ static cilist io___51 = { 0, 6, 0, fmt_99999, 0 }; static cilist io___52 = { 0, 6, 0, fmt_99998, 0 }; static cilist io___53 = { 0, 6, 0, fmt_99997, 0 }; /* ********************************* STEST ************************** */ /* THIS SUBR COMPARES ARRAYS SCOMP() AND STRUE() OF LENGTH LEN TO */ /* SEE IF THE TERM BY TERM DIFFERENCES, MULTIPLIED BY SFAC, ARE */ /* NEGLIGIBLE. */ /* C. L. LAWSON, JPL, 1974 DEC 10 */ /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Scalars in Common .. */ /* .. Local Scalars .. */ /* .. External Functions .. */ /* .. Intrinsic Functions .. */ /* .. Common blocks .. */ /* .. Executable Statements .. */ /* Parameter adjustments */ --ssize; --strue; --scomp; /* Function Body */ i__1 = *len; for (i__ = 1; i__ <= i__1; ++i__) { sd = scomp[i__] - strue[i__]; if ((d__2 = *sfac * sd, abs(d__2)) <= (d__1 = ssize[i__], abs(d__1)) * d_epsilon_(&c_b52)) { goto L40; } /* HERE SCOMP(I) IS NOT CLOSE TO STRUE(I). */ if (! combla_1.pass) { goto L20; } /* PRINT FAIL MESSAGE AND HEADER. */ combla_1.pass = FALSE_; s_wsfe(&io___51); e_wsfe(); s_wsfe(&io___52); e_wsfe(); L20: s_wsfe(&io___53); do_fio(&c__1, (char *)&combla_1.icase, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&combla_1.n, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&combla_1.incx, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&combla_1.incy, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&combla_1.mode, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&i__, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&scomp[i__], (ftnlen)sizeof(doublereal)); do_fio(&c__1, (char *)&strue[i__], (ftnlen)sizeof(doublereal)); do_fio(&c__1, (char *)&sd, (ftnlen)sizeof(doublereal)); do_fio(&c__1, (char *)&ssize[i__], (ftnlen)sizeof(doublereal)); e_wsfe(); L40: ; } return 0; } /* stest_ */ /* Subroutine */ int stest1_(doublereal *scomp1, doublereal *strue1, doublereal *ssize, doublereal *sfac) { doublereal scomp[1], strue[1]; extern /* Subroutine */ int stest_(integer *, doublereal *, doublereal *, doublereal *, doublereal *); /* ************************* STEST1 ***************************** */ /* THIS IS AN INTERFACE SUBROUTINE TO ACCOMODATE THE FORTRAN */ /* REQUIREMENT THAT WHEN A DUMMY ARGUMENT IS AN ARRAY, THE */ /* ACTUAL ARGUMENT MUST ALSO BE AN ARRAY OR AN ARRAY ELEMENT. */ /* C.L. LAWSON, JPL, 1978 DEC 6 */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Arrays .. */ /* .. External Subroutines .. */ /* .. Executable Statements .. */ /* Parameter adjustments */ --ssize; /* Function Body */ scomp[0] = *scomp1; strue[0] = *strue1; stest_(&c__1, scomp, strue, &ssize[1], sfac); return 0; } /* stest1_ */ doublereal sdiff_(doublereal *sa, doublereal *sb) { /* System generated locals */ doublereal ret_val; /* ********************************* SDIFF ************************** */ /* COMPUTES DIFFERENCE OF TWO NUMBERS. C. L. LAWSON, JPL 1974 FEB 15 */ /* .. Scalar Arguments .. */ /* .. Executable Statements .. */ ret_val = *sa - *sb; return ret_val; } /* sdiff_ */ /* Subroutine */ int ctest_(integer *len, doublecomplex *ccomp, doublecomplex *ctrue, doublecomplex *csize, doublereal *sfac) { /* System generated locals */ integer i__1, i__2; /* Builtin functions */ double d_imag(const doublecomplex *); /* Local variables */ integer i__; doublereal scomp[20], ssize[20], strue[20]; extern /* Subroutine */ int stest_(integer *, doublereal *, doublereal *, doublereal *, doublereal *); /* **************************** CTEST ***************************** */ /* C.L. LAWSON, JPL, 1978 DEC 6 */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Scalars .. */ /* .. Local Arrays .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. Executable Statements .. */ /* Parameter adjustments */ --csize; --ctrue; --ccomp; /* Function Body */ i__1 = *len; for (i__ = 1; i__ <= i__1; ++i__) { i__2 = i__; scomp[(i__ << 1) - 2] = ccomp[i__2].r; scomp[(i__ << 1) - 1] = d_imag(&ccomp[i__]); i__2 = i__; strue[(i__ << 1) - 2] = ctrue[i__2].r; strue[(i__ << 1) - 1] = d_imag(&ctrue[i__]); i__2 = i__; ssize[(i__ << 1) - 2] = csize[i__2].r; ssize[(i__ << 1) - 1] = d_imag(&csize[i__]); /* L20: */ } i__1 = *len << 1; stest_(&i__1, scomp, strue, ssize, sfac); return 0; } /* ctest_ */ /* Subroutine */ int itest1_(integer *icomp, integer *itrue) { /* Format strings */ static char fmt_99999[] = "(\002 F" "AIL\002)"; static char fmt_99998[] = "(/\002 CASE N INCX INCY MODE " " \002,\002 COMP TRU" "E DIFFERENCE\002,/1x)"; static char fmt_99997[] = "(1x,i4,i3,3i5,2i36,i12)"; /* Builtin functions */ integer s_wsfe(cilist *), e_wsfe(void), do_fio(integer *, char *, ftnlen); /* Local variables */ integer id; /* Fortran I/O blocks */ static cilist io___60 = { 0, 6, 0, fmt_99999, 0 }; static cilist io___61 = { 0, 6, 0, fmt_99998, 0 }; static cilist io___63 = { 0, 6, 0, fmt_99997, 0 }; /* ********************************* ITEST1 ************************* */ /* THIS SUBROUTINE COMPARES THE VARIABLES ICOMP AND ITRUE FOR */ /* EQUALITY. */ /* C. L. LAWSON, JPL, 1974 DEC 10 */ /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Scalars in Common .. */ /* .. Local Scalars .. */ /* .. Common blocks .. */ /* .. Executable Statements .. */ if (*icomp == *itrue) { goto L40; } /* HERE ICOMP IS NOT EQUAL TO ITRUE. */ if (! combla_1.pass) { goto L20; } /* PRINT FAIL MESSAGE AND HEADER. */ combla_1.pass = FALSE_; s_wsfe(&io___60); e_wsfe(); s_wsfe(&io___61); e_wsfe(); L20: id = *icomp - *itrue; s_wsfe(&io___63); do_fio(&c__1, (char *)&combla_1.icase, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&combla_1.n, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&combla_1.incx, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&combla_1.incy, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&combla_1.mode, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&(*icomp), (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&(*itrue), (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&id, (ftnlen)sizeof(integer)); e_wsfe(); L40: return 0; } /* itest1_ */ /* Main program alias */ int zblat1_ () { main (); return 0; } blis-0.9.0/blastest/src/zblat2.c000066400000000000000000005055711422157504600164460ustar00rootroot00000000000000/* zblat2.f -- translated by f2c (version 20100827). You must link the resulting object file with libf2c: on Microsoft Windows system, link with libf2c.lib; on Linux or Unix systems, link with .../path/to/libf2c.a -lm or, if you install libf2c.a in a standard place, with -lf2c -lm -- in that order, at the end of the command line, as in cc *.o -lf2c -lm Source for libf2c is in /netlib/f2c/libf2c.zip, e.g., http://www.netlib.org/f2c/libf2c.zip */ #include "f2c.h" /* Common Block Declarations */ union { struct { integer infot, noutc; logical ok, lerr; } _1; struct { integer infot, nout; logical ok, lerr; } _2; } infoc_; #define infoc_1 (infoc_._1) #define infoc_2 (infoc_._2) struct { char srnamt[6]; } srnamc_; #define srnamc_1 srnamc_ /* Table of constant values */ static doublecomplex c_b1 = {0.,0.}; static doublecomplex c_b2 = {1.,0.}; static integer c__9 = 9; static integer c__1 = 1; static integer c__3 = 3; static integer c__8 = 8; static integer c__5 = 5; static integer c__65 = 65; static integer c__7 = 7; static integer c__2 = 2; static doublereal c_b122 = 0.; static logical c_true = TRUE_; static integer c_n1 = -1; static integer c__0 = 0; static logical c_false = FALSE_; /* > \brief \b ZBLAT2 */ /* =========== DOCUMENTATION =========== */ /* Online html documentation available at */ /* http://www.netlib.org/lapack/explore-html/ */ /* Definition: */ /* =========== */ /* PROGRAM ZBLAT2 */ /* > \par Purpose: */ /* ============= */ /* > */ /* > \verbatim */ /* > */ /* > Test program for the COMPLEX*16 Level 2 Blas. */ /* > */ /* > The program must be driven by a short data file. The first 18 records */ /* > of the file are read using list-directed input, the last 17 records */ /* > are read using the format ( A6, L2 ). An annotated example of a data */ /* > file can be obtained by deleting the first 3 characters from the */ /* > following 35 lines: */ /* > 'zblat2.out' NAME OF SUMMARY OUTPUT FILE */ /* > 6 UNIT NUMBER OF SUMMARY FILE */ /* > 'CBLA2T.SNAP' NAME OF SNAPSHOT OUTPUT FILE */ /* > -1 UNIT NUMBER OF SNAPSHOT FILE (NOT USED IF .LT. 0) */ /* > F LOGICAL FLAG, T TO REWIND SNAPSHOT FILE AFTER EACH RECORD. */ /* > F LOGICAL FLAG, T TO STOP ON FAILURES. */ /* > T LOGICAL FLAG, T TO TEST ERROR EXITS. */ /* > 16.0 THRESHOLD VALUE OF TEST RATIO */ /* > 6 NUMBER OF VALUES OF N */ /* > 0 1 2 3 5 9 VALUES OF N */ /* > 4 NUMBER OF VALUES OF K */ /* > 0 1 2 4 VALUES OF K */ /* > 4 NUMBER OF VALUES OF INCX AND INCY */ /* > 1 2 -1 -2 VALUES OF INCX AND INCY */ /* > 3 NUMBER OF VALUES OF ALPHA */ /* > (0.0,0.0) (1.0,0.0) (0.7,-0.9) VALUES OF ALPHA */ /* > 3 NUMBER OF VALUES OF BETA */ /* > (0.0,0.0) (1.0,0.0) (1.3,-1.1) VALUES OF BETA */ /* > ZGEMV T PUT F FOR NO TEST. SAME COLUMNS. */ /* > ZGBMV T PUT F FOR NO TEST. SAME COLUMNS. */ /* > ZHEMV T PUT F FOR NO TEST. SAME COLUMNS. */ /* > ZHBMV T PUT F FOR NO TEST. SAME COLUMNS. */ /* > ZHPMV T PUT F FOR NO TEST. SAME COLUMNS. */ /* > ZTRMV T PUT F FOR NO TEST. SAME COLUMNS. */ /* > ZTBMV T PUT F FOR NO TEST. SAME COLUMNS. */ /* > ZTPMV T PUT F FOR NO TEST. SAME COLUMNS. */ /* > ZTRSV T PUT F FOR NO TEST. SAME COLUMNS. */ /* > ZTBSV T PUT F FOR NO TEST. SAME COLUMNS. */ /* > ZTPSV T PUT F FOR NO TEST. SAME COLUMNS. */ /* > ZGERC T PUT F FOR NO TEST. SAME COLUMNS. */ /* > ZGERU T PUT F FOR NO TEST. SAME COLUMNS. */ /* > ZHER T PUT F FOR NO TEST. SAME COLUMNS. */ /* > ZHPR T PUT F FOR NO TEST. SAME COLUMNS. */ /* > ZHER2 T PUT F FOR NO TEST. SAME COLUMNS. */ /* > ZHPR2 T PUT F FOR NO TEST. SAME COLUMNS. */ /* > */ /* > Further Details */ /* > =============== */ /* > */ /* > See: */ /* > */ /* > Dongarra J. J., Du Croz J. J., Hammarling S. and Hanson R. J.. */ /* > An extended set of Fortran Basic Linear Algebra Subprograms. */ /* > */ /* > Technical Memoranda Nos. 41 (revision 3) and 81, Mathematics */ /* > and Computer Science Division, Argonne National Laboratory, */ /* > 9700 South Cass Avenue, Argonne, Illinois 60439, US. */ /* > */ /* > Or */ /* > */ /* > NAG Technical Reports TR3/87 and TR4/87, Numerical Algorithms */ /* > Group Ltd., NAG Central Office, 256 Banbury Road, Oxford */ /* > OX2 7DE, UK, and Numerical Algorithms Group Inc., 1101 31st */ /* > Street, Suite 100, Downers Grove, Illinois 60515-1263, USA. */ /* > */ /* > */ /* > -- Written on 10-August-1987. */ /* > Richard Hanson, Sandia National Labs. */ /* > Jeremy Du Croz, NAG Central Office. */ /* > */ /* > 10-9-00: Change STATUS='NEW' to 'UNKNOWN' so that the testers */ /* > can be run multiple times without deleting generated */ /* > output files (susan) */ /* > \endverbatim */ /* Authors: */ /* ======== */ /* > \author Univ. of Tennessee */ /* > \author Univ. of California Berkeley */ /* > \author Univ. of Colorado Denver */ /* > \author NAG Ltd. */ /* > \date April 2012 */ /* > \ingroup complex16_blas_testing */ /* ===================================================================== */ /* Main program */ int main(void) { /* Initialized data */ static char snames[6*17] = "ZGEMV " "ZGBMV " "ZHEMV " "ZHBMV " "ZHPMV " "ZTRMV " "ZTBMV " "ZTPMV " "ZTRSV " "ZTBSV " "ZTPSV " "ZGERC " "ZGERU " "ZHER " "ZHPR " "ZHER2 " "ZHPR2 "; /* Format strings */ static char fmt_9997[] = "(\002 NUMBER OF VALUES OF \002,a,\002 IS LESS " "THAN 1 OR GREATER \002,\002THAN \002,i2)"; static char fmt_9996[] = "(\002 VALUE OF N IS LESS THAN 0 OR GREATER THA" "N \002,i2)"; static char fmt_9995[] = "(\002 VALUE OF K IS LESS THAN 0\002)"; static char fmt_9994[] = "(\002 ABSOLUTE VALUE OF INCX OR INCY IS 0 OR G" "REATER THAN \002,i2)"; static char fmt_9993[] = "(\002 TESTS OF THE COMPLEX*16 LEVEL 2 BL" "AS\002,//\002 THE F\002,\002OLLOWING PARAMETER VALUES WILL BE US" "ED:\002)"; static char fmt_9992[] = "(\002 FOR N \002,9i6)"; static char fmt_9991[] = "(\002 FOR K \002,7i6)"; static char fmt_9990[] = "(\002 FOR INCX AND INCY \002,7i6)"; static char fmt_9989[] = "(\002 FOR ALPHA \002,7(\002(\002,f4" ".1,\002,\002,f4.1,\002) \002,:))"; static char fmt_9988[] = "(\002 FOR BETA \002,7(\002(\002,f4" ".1,\002,\002,f4.1,\002) \002,:))"; static char fmt_9980[] = "(\002 ERROR-EXITS WILL NOT BE TESTED\002)"; static char fmt_9999[] = "(\002 ROUTINES PASS COMPUTATIONAL TESTS IF TES" "T RATIO IS LES\002,\002S THAN\002,f8.2)"; static char fmt_9984[] = "(a6,l2)"; static char fmt_9986[] = "(\002 SUBPROGRAM NAME \002,a6,\002 NOT RECOGNI" "ZED\002,/\002 ******* T\002,\002ESTS ABANDONED *******\002)"; static char fmt_9998[] = "(\002 RELATIVE MACHINE PRECISION IS TAKEN TO" " BE\002,1p,d9.1)"; static char fmt_9985[] = "(\002 ERROR IN ZMVCH - IN-LINE DOT PRODUCTS A" "RE BEING EVALU\002,\002ATED WRONGLY.\002,/\002 ZMVCH WAS CALLED " "WITH TRANS = \002,a1,\002 AND RETURNED SAME = \002,l1,\002 AND E" "RR = \002,f12.3,\002.\002,/\002 THIS MAY BE DUE TO FAULTS IN THE" " ARITHMETIC OR THE COMPILER.\002,/\002 ******* TESTS ABANDONED *" "******\002)"; static char fmt_9983[] = "(1x,a6,\002 WAS NOT TESTED\002)"; static char fmt_9982[] = "(/\002 END OF TESTS\002)"; static char fmt_9981[] = "(/\002 ******* FATAL ERROR - TESTS ABANDONED *" "******\002)"; static char fmt_9987[] = "(\002 AMEND DATA FILE OR INCREASE ARRAY SIZES " "IN PROGRAM\002,/\002 ******* TESTS ABANDONED *******\002)"; /* System generated locals */ integer i__1, i__2, i__3, i__4, i__5; olist o__1; cllist cl__1; /* Builtin functions */ integer s_rsle(cilist *), do_lio(integer *, integer *, char *, ftnlen), e_rsle(void), f_open(olist *), s_wsfe(cilist *), do_fio(integer *, char *, ftnlen), e_wsfe(void), s_wsle(cilist *), e_wsle(void), s_rsfe(cilist *), e_rsfe(void), s_cmp(const char *, const char *, ftnlen, ftnlen); /* Subroutine */ int s_stop(char *, ftnlen); integer f_clos(cllist *); /* Subroutine */ int s_copy(char *, const char *, ftnlen, ftnlen); /* Local variables */ doublecomplex a[4225] /* was [65][65] */; doublereal g[65]; integer i__, j, n; doublecomplex x[65], y[65], z__[130], aa[4225]; integer kb[7]; doublecomplex as[4225], xs[130], ys[130], yt[65], xx[130], yy[130], alf[7] ; integer inc[7], nkb; doublecomplex bet[7]; doublereal eps, err; extern logical lze_(doublecomplex *, doublecomplex *, integer *); integer nalf, idim[9]; logical same; integer ninc, nbet, ntra; logical rewi; integer nout; extern /* Subroutine */ int zchk1_(char *, doublereal *, doublereal *, integer *, integer *, logical *, logical *, logical *, integer *, integer *, integer *, integer *, integer *, doublecomplex *, integer *, doublecomplex *, integer *, integer *, integer *, integer *, doublecomplex *, doublecomplex *, doublecomplex *, doublecomplex *, doublecomplex *, doublecomplex *, doublecomplex * , doublecomplex *, doublecomplex *, doublecomplex *, doublereal *, ftnlen), zchk2_(char *, doublereal *, doublereal *, integer *, integer *, logical *, logical *, logical *, integer *, integer *, integer *, integer *, integer *, doublecomplex *, integer *, doublecomplex *, integer *, integer *, integer *, integer *, doublecomplex *, doublecomplex *, doublecomplex *, doublecomplex * , doublecomplex *, doublecomplex *, doublecomplex *, doublecomplex *, doublecomplex *, doublecomplex *, doublereal *, ftnlen), zchk3_(char *, doublereal *, doublereal *, integer *, integer *, logical *, logical *, logical *, integer *, integer *, integer *, integer *, integer *, integer *, integer *, integer *, doublecomplex *, doublecomplex *, doublecomplex *, doublecomplex * , doublecomplex *, doublecomplex *, doublecomplex *, doublereal *, doublecomplex *, ftnlen), zchk4_(char *, doublereal *, doublereal *, integer *, integer *, logical *, logical *, logical *, integer *, integer *, integer *, doublecomplex *, integer *, integer *, integer *, integer *, doublecomplex *, doublecomplex *, doublecomplex *, doublecomplex *, doublecomplex *, doublecomplex *, doublecomplex *, doublecomplex *, doublecomplex *, doublecomplex *, doublereal *, doublecomplex *, ftnlen), zchk5_( char *, doublereal *, doublereal *, integer *, integer *, logical *, logical *, logical *, integer *, integer *, integer *, doublecomplex *, integer *, integer *, integer *, integer *, doublecomplex *, doublecomplex *, doublecomplex *, doublecomplex * , doublecomplex *, doublecomplex *, doublecomplex *, doublecomplex *, doublecomplex *, doublecomplex *, doublereal *, doublecomplex *, ftnlen), zchk6_(char *, doublereal *, doublereal *, integer *, integer *, logical *, logical *, logical *, integer *, integer *, integer *, doublecomplex *, integer *, integer *, integer *, integer *, doublecomplex *, doublecomplex *, doublecomplex *, doublecomplex *, doublecomplex *, doublecomplex * , doublecomplex *, doublecomplex *, doublecomplex *, doublecomplex *, doublereal *, doublecomplex *, ftnlen); logical fatal, trace; integer nidim; extern /* Subroutine */ int zchke_(integer *, char *, integer *, ftnlen); char snaps[32], trans[1]; extern /* Subroutine */ int zmvch_(char *, integer *, integer *, doublecomplex *, doublecomplex *, integer *, doublecomplex *, integer *, doublecomplex *, doublecomplex *, integer *, doublecomplex *, doublereal *, doublecomplex *, doublereal *, doublereal *, logical *, integer *, logical *, ftnlen); integer isnum; logical ltest[17], sfatal; char snamet[6]; doublereal thresh; logical ltestt, tsterr; char summry[32]; extern double d_epsilon_(doublereal *); /* Fortran I/O blocks */ static cilist io___2 = { 0, 5, 0, 0, 0 }; static cilist io___4 = { 0, 5, 0, 0, 0 }; static cilist io___6 = { 0, 5, 0, 0, 0 }; static cilist io___8 = { 0, 5, 0, 0, 0 }; static cilist io___11 = { 0, 5, 0, 0, 0 }; static cilist io___13 = { 0, 5, 0, 0, 0 }; static cilist io___15 = { 0, 5, 0, 0, 0 }; static cilist io___17 = { 0, 5, 0, 0, 0 }; static cilist io___19 = { 0, 5, 0, 0, 0 }; static cilist io___21 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___22 = { 0, 5, 0, 0, 0 }; static cilist io___25 = { 0, 0, 0, fmt_9996, 0 }; static cilist io___26 = { 0, 5, 0, 0, 0 }; static cilist io___28 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___29 = { 0, 5, 0, 0, 0 }; static cilist io___31 = { 0, 0, 0, fmt_9995, 0 }; static cilist io___32 = { 0, 5, 0, 0, 0 }; static cilist io___34 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___35 = { 0, 5, 0, 0, 0 }; static cilist io___37 = { 0, 0, 0, fmt_9994, 0 }; static cilist io___38 = { 0, 5, 0, 0, 0 }; static cilist io___40 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___41 = { 0, 5, 0, 0, 0 }; static cilist io___43 = { 0, 5, 0, 0, 0 }; static cilist io___45 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___46 = { 0, 5, 0, 0, 0 }; static cilist io___48 = { 0, 0, 0, fmt_9993, 0 }; static cilist io___49 = { 0, 0, 0, fmt_9992, 0 }; static cilist io___50 = { 0, 0, 0, fmt_9991, 0 }; static cilist io___51 = { 0, 0, 0, fmt_9990, 0 }; static cilist io___52 = { 0, 0, 0, fmt_9989, 0 }; static cilist io___53 = { 0, 0, 0, fmt_9988, 0 }; static cilist io___54 = { 0, 0, 0, 0, 0 }; static cilist io___55 = { 0, 0, 0, fmt_9980, 0 }; static cilist io___56 = { 0, 0, 0, 0, 0 }; static cilist io___57 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___58 = { 0, 0, 0, 0, 0 }; static cilist io___60 = { 0, 5, 1, fmt_9984, 0 }; static cilist io___63 = { 0, 0, 0, fmt_9986, 0 }; static cilist io___65 = { 0, 0, 0, fmt_9998, 0 }; static cilist io___78 = { 0, 0, 0, fmt_9985, 0 }; static cilist io___79 = { 0, 0, 0, fmt_9985, 0 }; static cilist io___81 = { 0, 0, 0, 0, 0 }; static cilist io___82 = { 0, 0, 0, fmt_9983, 0 }; static cilist io___83 = { 0, 0, 0, 0, 0 }; static cilist io___90 = { 0, 0, 0, fmt_9982, 0 }; static cilist io___91 = { 0, 0, 0, fmt_9981, 0 }; static cilist io___92 = { 0, 0, 0, fmt_9987, 0 }; /* -- Reference BLAS test routine (version 3.4.1) -- */ /* -- Reference BLAS is a software package provided by Univ. of Tennessee, -- */ /* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- */ /* April 2012 */ /* ===================================================================== */ /* .. Parameters .. */ /* .. Local Scalars .. */ /* .. Local Arrays .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. Scalars in Common .. */ /* .. Common blocks .. */ /* .. Data statements .. */ /* .. Executable Statements .. */ /* Read name and unit number for summary output file and open file. */ s_rsle(&io___2); do_lio(&c__9, &c__1, summry, (ftnlen)32); e_rsle(); s_rsle(&io___4); do_lio(&c__3, &c__1, (char *)&nout, (ftnlen)sizeof(integer)); e_rsle(); o__1.oerr = 0; o__1.ounit = nout; o__1.ofnmlen = 32; o__1.ofnm = summry; o__1.orl = 0; o__1.osta = "UNKNOWN"; o__1.oacc = 0; o__1.ofm = 0; o__1.oblnk = 0; f_open(&o__1); infoc_1.noutc = nout; /* Read name and unit number for snapshot output file and open file. */ s_rsle(&io___6); do_lio(&c__9, &c__1, snaps, (ftnlen)32); e_rsle(); s_rsle(&io___8); do_lio(&c__3, &c__1, (char *)&ntra, (ftnlen)sizeof(integer)); e_rsle(); trace = ntra >= 0; if (trace) { o__1.oerr = 0; o__1.ounit = ntra; o__1.ofnmlen = 32; o__1.ofnm = snaps; o__1.orl = 0; o__1.osta = "UNKNOWN"; o__1.oacc = 0; o__1.ofm = 0; o__1.oblnk = 0; f_open(&o__1); } /* Read the flag that directs rewinding of the snapshot file. */ s_rsle(&io___11); do_lio(&c__8, &c__1, (char *)&rewi, (ftnlen)sizeof(logical)); e_rsle(); rewi = rewi && trace; /* Read the flag that directs stopping on any failure. */ s_rsle(&io___13); do_lio(&c__8, &c__1, (char *)&sfatal, (ftnlen)sizeof(logical)); e_rsle(); /* Read the flag that indicates whether error exits are to be tested. */ s_rsle(&io___15); do_lio(&c__8, &c__1, (char *)&tsterr, (ftnlen)sizeof(logical)); e_rsle(); /* Read the threshold value of the test ratio */ s_rsle(&io___17); do_lio(&c__5, &c__1, (char *)&thresh, (ftnlen)sizeof(doublereal)); e_rsle(); /* Read and check the parameter values for the tests. */ /* Values of N */ s_rsle(&io___19); do_lio(&c__3, &c__1, (char *)&nidim, (ftnlen)sizeof(integer)); e_rsle(); if (nidim < 1 || nidim > 9) { io___21.ciunit = nout; s_wsfe(&io___21); do_fio(&c__1, "N", (ftnlen)1); do_fio(&c__1, (char *)&c__9, (ftnlen)sizeof(integer)); e_wsfe(); goto L230; } s_rsle(&io___22); i__1 = nidim; for (i__ = 1; i__ <= i__1; ++i__) { do_lio(&c__3, &c__1, (char *)&idim[i__ - 1], (ftnlen)sizeof(integer)); } e_rsle(); i__1 = nidim; for (i__ = 1; i__ <= i__1; ++i__) { if (idim[i__ - 1] < 0 || idim[i__ - 1] > 65) { io___25.ciunit = nout; s_wsfe(&io___25); do_fio(&c__1, (char *)&c__65, (ftnlen)sizeof(integer)); e_wsfe(); goto L230; } /* L10: */ } /* Values of K */ s_rsle(&io___26); do_lio(&c__3, &c__1, (char *)&nkb, (ftnlen)sizeof(integer)); e_rsle(); if (nkb < 1 || nkb > 7) { io___28.ciunit = nout; s_wsfe(&io___28); do_fio(&c__1, "K", (ftnlen)1); do_fio(&c__1, (char *)&c__7, (ftnlen)sizeof(integer)); e_wsfe(); goto L230; } s_rsle(&io___29); i__1 = nkb; for (i__ = 1; i__ <= i__1; ++i__) { do_lio(&c__3, &c__1, (char *)&kb[i__ - 1], (ftnlen)sizeof(integer)); } e_rsle(); i__1 = nkb; for (i__ = 1; i__ <= i__1; ++i__) { if (kb[i__ - 1] < 0) { io___31.ciunit = nout; s_wsfe(&io___31); e_wsfe(); goto L230; } /* L20: */ } /* Values of INCX and INCY */ s_rsle(&io___32); do_lio(&c__3, &c__1, (char *)&ninc, (ftnlen)sizeof(integer)); e_rsle(); if (ninc < 1 || ninc > 7) { io___34.ciunit = nout; s_wsfe(&io___34); do_fio(&c__1, "INCX AND INCY", (ftnlen)13); do_fio(&c__1, (char *)&c__7, (ftnlen)sizeof(integer)); e_wsfe(); goto L230; } s_rsle(&io___35); i__1 = ninc; for (i__ = 1; i__ <= i__1; ++i__) { do_lio(&c__3, &c__1, (char *)&inc[i__ - 1], (ftnlen)sizeof(integer)); } e_rsle(); i__1 = ninc; for (i__ = 1; i__ <= i__1; ++i__) { if (inc[i__ - 1] == 0 || (i__2 = inc[i__ - 1], abs(i__2)) > 2) { io___37.ciunit = nout; s_wsfe(&io___37); do_fio(&c__1, (char *)&c__2, (ftnlen)sizeof(integer)); e_wsfe(); goto L230; } /* L30: */ } /* Values of ALPHA */ s_rsle(&io___38); do_lio(&c__3, &c__1, (char *)&nalf, (ftnlen)sizeof(integer)); e_rsle(); if (nalf < 1 || nalf > 7) { io___40.ciunit = nout; s_wsfe(&io___40); do_fio(&c__1, "ALPHA", (ftnlen)5); do_fio(&c__1, (char *)&c__7, (ftnlen)sizeof(integer)); e_wsfe(); goto L230; } s_rsle(&io___41); i__1 = nalf; for (i__ = 1; i__ <= i__1; ++i__) { do_lio(&c__7, &c__1, (char *)&alf[i__ - 1], (ftnlen)sizeof( doublecomplex)); } e_rsle(); /* Values of BETA */ s_rsle(&io___43); do_lio(&c__3, &c__1, (char *)&nbet, (ftnlen)sizeof(integer)); e_rsle(); if (nbet < 1 || nbet > 7) { io___45.ciunit = nout; s_wsfe(&io___45); do_fio(&c__1, "BETA", (ftnlen)4); do_fio(&c__1, (char *)&c__7, (ftnlen)sizeof(integer)); e_wsfe(); goto L230; } s_rsle(&io___46); i__1 = nbet; for (i__ = 1; i__ <= i__1; ++i__) { do_lio(&c__7, &c__1, (char *)&bet[i__ - 1], (ftnlen)sizeof( doublecomplex)); } e_rsle(); /* Report values of parameters. */ io___48.ciunit = nout; s_wsfe(&io___48); e_wsfe(); io___49.ciunit = nout; s_wsfe(&io___49); i__1 = nidim; for (i__ = 1; i__ <= i__1; ++i__) { do_fio(&c__1, (char *)&idim[i__ - 1], (ftnlen)sizeof(integer)); } e_wsfe(); io___50.ciunit = nout; s_wsfe(&io___50); i__1 = nkb; for (i__ = 1; i__ <= i__1; ++i__) { do_fio(&c__1, (char *)&kb[i__ - 1], (ftnlen)sizeof(integer)); } e_wsfe(); io___51.ciunit = nout; s_wsfe(&io___51); i__1 = ninc; for (i__ = 1; i__ <= i__1; ++i__) { do_fio(&c__1, (char *)&inc[i__ - 1], (ftnlen)sizeof(integer)); } e_wsfe(); io___52.ciunit = nout; s_wsfe(&io___52); i__1 = nalf; for (i__ = 1; i__ <= i__1; ++i__) { do_fio(&c__2, (char *)&alf[i__ - 1], (ftnlen)sizeof(doublereal)); } e_wsfe(); io___53.ciunit = nout; s_wsfe(&io___53); i__1 = nbet; for (i__ = 1; i__ <= i__1; ++i__) { do_fio(&c__2, (char *)&bet[i__ - 1], (ftnlen)sizeof(doublereal)); } e_wsfe(); if (! tsterr) { io___54.ciunit = nout; s_wsle(&io___54); e_wsle(); io___55.ciunit = nout; s_wsfe(&io___55); e_wsfe(); } io___56.ciunit = nout; s_wsle(&io___56); e_wsle(); io___57.ciunit = nout; s_wsfe(&io___57); do_fio(&c__1, (char *)&thresh, (ftnlen)sizeof(doublereal)); e_wsfe(); io___58.ciunit = nout; s_wsle(&io___58); e_wsle(); /* Read names of subroutines and flags which indicate */ /* whether they are to be tested. */ for (i__ = 1; i__ <= 17; ++i__) { ltest[i__ - 1] = FALSE_; /* L40: */ } L50: i__1 = s_rsfe(&io___60); if (i__1 != 0) { goto L80; } i__1 = do_fio(&c__1, snamet, (ftnlen)6); if (i__1 != 0) { goto L80; } i__1 = do_fio(&c__1, (char *)<estt, (ftnlen)sizeof(logical)); if (i__1 != 0) { goto L80; } i__1 = e_rsfe(); if (i__1 != 0) { goto L80; } for (i__ = 1; i__ <= 17; ++i__) { if (s_cmp(snamet, snames + (i__ - 1) * 6, (ftnlen)6, (ftnlen)6) == 0) { goto L70; } /* L60: */ } io___63.ciunit = nout; s_wsfe(&io___63); do_fio(&c__1, snamet, (ftnlen)6); e_wsfe(); s_stop("", (ftnlen)0); L70: ltest[i__ - 1] = ltestt; goto L50; L80: cl__1.cerr = 0; cl__1.cunit = 5; cl__1.csta = 0; f_clos(&cl__1); /* Compute EPS (the machine precision). */ eps = d_epsilon_(&c_b122); io___65.ciunit = nout; s_wsfe(&io___65); do_fio(&c__1, (char *)&eps, (ftnlen)sizeof(doublereal)); e_wsfe(); /* Check the reliability of ZMVCH using exact data. */ n = 32; i__1 = n; for (j = 1; j <= i__1; ++j) { i__2 = n; for (i__ = 1; i__ <= i__2; ++i__) { i__3 = i__ + j * 65 - 66; /* Computing MAX */ i__5 = i__ - j + 1; i__4 = max(i__5,0); a[i__3].r = (doublereal) i__4, a[i__3].i = 0.; /* L110: */ } i__2 = j - 1; x[i__2].r = (doublereal) j, x[i__2].i = 0.; i__2 = j - 1; y[i__2].r = 0., y[i__2].i = 0.; /* L120: */ } i__1 = n; for (j = 1; j <= i__1; ++j) { i__2 = j - 1; i__3 = j * ((j + 1) * j) / 2 - (j + 1) * j * (j - 1) / 3; yy[i__2].r = (doublereal) i__3, yy[i__2].i = 0.; /* L130: */ } /* YY holds the exact result. On exit from ZMVCH YT holds */ /* the result computed by ZMVCH. */ *(unsigned char *)trans = 'N'; zmvch_(trans, &n, &n, &c_b2, a, &c__65, x, &c__1, &c_b1, y, &c__1, yt, g, yy, &eps, &err, &fatal, &nout, &c_true, (ftnlen)1); same = lze_(yy, yt, &n); if (! same || err != 0.) { io___78.ciunit = nout; s_wsfe(&io___78); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, (char *)&same, (ftnlen)sizeof(logical)); do_fio(&c__1, (char *)&err, (ftnlen)sizeof(doublereal)); e_wsfe(); s_stop("", (ftnlen)0); } *(unsigned char *)trans = 'T'; zmvch_(trans, &n, &n, &c_b2, a, &c__65, x, &c_n1, &c_b1, y, &c_n1, yt, g, yy, &eps, &err, &fatal, &nout, &c_true, (ftnlen)1); same = lze_(yy, yt, &n); if (! same || err != 0.) { io___79.ciunit = nout; s_wsfe(&io___79); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, (char *)&same, (ftnlen)sizeof(logical)); do_fio(&c__1, (char *)&err, (ftnlen)sizeof(doublereal)); e_wsfe(); s_stop("", (ftnlen)0); } /* Test each subroutine in turn. */ for (isnum = 1; isnum <= 17; ++isnum) { io___81.ciunit = nout; s_wsle(&io___81); e_wsle(); if (! ltest[isnum - 1]) { /* Subprogram is not to be tested. */ io___82.ciunit = nout; s_wsfe(&io___82); do_fio(&c__1, snames + (isnum - 1) * 6, (ftnlen)6); e_wsfe(); } else { s_copy(srnamc_1.srnamt, snames + (isnum - 1) * 6, (ftnlen)6, ( ftnlen)6); /* Test error exits. */ if (tsterr) { zchke_(&isnum, snames + (isnum - 1) * 6, &nout, (ftnlen)6); io___83.ciunit = nout; s_wsle(&io___83); e_wsle(); } /* Test computations. */ infoc_1.infot = 0; infoc_1.ok = TRUE_; fatal = FALSE_; switch (isnum) { case 1: goto L140; case 2: goto L140; case 3: goto L150; case 4: goto L150; case 5: goto L150; case 6: goto L160; case 7: goto L160; case 8: goto L160; case 9: goto L160; case 10: goto L160; case 11: goto L160; case 12: goto L170; case 13: goto L170; case 14: goto L180; case 15: goto L180; case 16: goto L190; case 17: goto L190; } /* Test ZGEMV, 01, and ZGBMV, 02. */ L140: zchk1_(snames + (isnum - 1) * 6, &eps, &thresh, &nout, &ntra, & trace, &rewi, &fatal, &nidim, idim, &nkb, kb, &nalf, alf, &nbet, bet, &ninc, inc, &c__65, &c__2, a, aa, as, x, xx, xs, y, yy, ys, yt, g, (ftnlen)6); goto L200; /* Test ZHEMV, 03, ZHBMV, 04, and ZHPMV, 05. */ L150: zchk2_(snames + (isnum - 1) * 6, &eps, &thresh, &nout, &ntra, & trace, &rewi, &fatal, &nidim, idim, &nkb, kb, &nalf, alf, &nbet, bet, &ninc, inc, &c__65, &c__2, a, aa, as, x, xx, xs, y, yy, ys, yt, g, (ftnlen)6); goto L200; /* Test ZTRMV, 06, ZTBMV, 07, ZTPMV, 08, */ /* ZTRSV, 09, ZTBSV, 10, and ZTPSV, 11. */ L160: zchk3_(snames + (isnum - 1) * 6, &eps, &thresh, &nout, &ntra, & trace, &rewi, &fatal, &nidim, idim, &nkb, kb, &ninc, inc, &c__65, &c__2, a, aa, as, y, yy, ys, yt, g, z__, (ftnlen) 6); goto L200; /* Test ZGERC, 12, ZGERU, 13. */ L170: zchk4_(snames + (isnum - 1) * 6, &eps, &thresh, &nout, &ntra, & trace, &rewi, &fatal, &nidim, idim, &nalf, alf, &ninc, inc, &c__65, &c__2, a, aa, as, x, xx, xs, y, yy, ys, yt, g, z__, (ftnlen)6); goto L200; /* Test ZHER, 14, and ZHPR, 15. */ L180: zchk5_(snames + (isnum - 1) * 6, &eps, &thresh, &nout, &ntra, & trace, &rewi, &fatal, &nidim, idim, &nalf, alf, &ninc, inc, &c__65, &c__2, a, aa, as, x, xx, xs, y, yy, ys, yt, g, z__, (ftnlen)6); goto L200; /* Test ZHER2, 16, and ZHPR2, 17. */ L190: zchk6_(snames + (isnum - 1) * 6, &eps, &thresh, &nout, &ntra, & trace, &rewi, &fatal, &nidim, idim, &nalf, alf, &ninc, inc, &c__65, &c__2, a, aa, as, x, xx, xs, y, yy, ys, yt, g, z__, (ftnlen)6); L200: if (fatal && sfatal) { goto L220; } } /* L210: */ } io___90.ciunit = nout; s_wsfe(&io___90); e_wsfe(); goto L240; L220: io___91.ciunit = nout; s_wsfe(&io___91); e_wsfe(); goto L240; L230: io___92.ciunit = nout; s_wsfe(&io___92); e_wsfe(); L240: if (trace) { cl__1.cerr = 0; cl__1.cunit = ntra; cl__1.csta = 0; f_clos(&cl__1); } cl__1.cerr = 0; cl__1.cunit = nout; cl__1.csta = 0; f_clos(&cl__1); s_stop("", (ftnlen)0); /* End of ZBLAT2. */ return 0; } /* main */ /* Subroutine */ int zchk1_(char *sname, doublereal *eps, doublereal *thresh, integer *nout, integer *ntra, logical *trace, logical *rewi, logical * fatal, integer *nidim, integer *idim, integer *nkb, integer *kb, integer *nalf, doublecomplex *alf, integer *nbet, doublecomplex *bet, integer *ninc, integer *inc, integer *nmax, integer *incmax, doublecomplex *a, doublecomplex *aa, doublecomplex *as, doublecomplex *x, doublecomplex *xx, doublecomplex *xs, doublecomplex *y, doublecomplex *yy, doublecomplex *ys, doublecomplex *yt, doublereal * g, ftnlen sname_len) { /* Initialized data */ static char ich[3] = "NTC"; /* Format strings */ static char fmt_9994[] = "(1x,i6,\002: \002,a6,\002('\002,a1,\002',\002," "2(i3,\002,\002),\002(\002,f4.1,\002,\002,f4.1,\002), A,\002,i3" ",\002, X,\002,i2,\002,(\002,f4.1,\002,\002,f4.1,\002), Y,\002,i2," "\002) .\002)"; static char fmt_9995[] = "(1x,i6,\002: \002,a6,\002('\002,a1,\002',\002," "4(i3,\002,\002),\002(\002,f4.1,\002,\002,f4.1,\002), A,\002,i3" ",\002, X,\002,i2,\002,(\002,f4.1,\002,\002,f4.1,\002), Y,\002,i2," "\002) .\002)"; static char fmt_9993[] = "(\002 ******* FATAL ERROR - ERROR-EXIT TAKEN O" "N VALID CALL *\002,\002******\002)"; static char fmt_9998[] = "(\002 ******* FATAL ERROR - PARAMETER NUMBER" " \002,i2,\002 WAS CH\002,\002ANGED INCORRECTLY *******\002)"; static char fmt_9999[] = "(\002 \002,a6,\002 PASSED THE COMPUTATIONAL TE" "STS (\002,i6,\002 CALL\002,\002S)\002)"; static char fmt_9997[] = "(\002 \002,a6,\002 COMPLETED THE COMPUTATIONAL" " TESTS (\002,i6,\002 C\002,\002ALLS)\002,/\002 ******* BUT WITH " "MAXIMUM TEST RATIO\002,f8.2,\002 - SUSPECT *******\002)"; static char fmt_9996[] = "(\002 ******* \002,a6,\002 FAILED ON CALL NUMB" "ER:\002)"; /* System generated locals */ integer a_dim1, a_offset, i__1, i__2, i__3, i__4, i__5, i__6, i__7, i__8, i__9; alist al__1; /* Builtin functions */ integer s_wsfe(cilist *), do_fio(integer *, char *, ftnlen), e_wsfe(void), f_rew(alist *); /* Local variables */ integer i__, m, n, ia, ib, ic, nc, nd, im, in, kl, ml, nk, nl, ku, ix, iy, ms, lx, ly, ns, laa, lda; doublecomplex als, bls; doublereal err; integer iku, kls; extern logical lze_(doublecomplex *, doublecomplex *, integer *); integer kus; doublecomplex beta; integer ldas; logical same; integer incx, incy; logical full, tran, null; doublecomplex alpha; logical isame[13]; extern /* Subroutine */ int zmake_(char *, char *, char *, integer *, integer *, doublecomplex *, integer *, doublecomplex *, integer *, integer *, integer *, logical *, doublecomplex *, ftnlen, ftnlen, ftnlen); integer nargs; logical reset; integer incxs, incys; extern /* Subroutine */ int zgbmv_(char *, integer *, integer *, integer * , integer *, doublecomplex *, doublecomplex *, integer *, doublecomplex *, integer *, doublecomplex *, doublecomplex *, integer *, ftnlen); char trans[1]; extern /* Subroutine */ int zgemv_(char *, integer *, integer *, doublecomplex *, doublecomplex *, integer *, doublecomplex *, integer *, doublecomplex *, doublecomplex *, integer *, ftnlen), zmvch_(char *, integer *, integer *, doublecomplex *, doublecomplex *, integer *, doublecomplex *, integer *, doublecomplex *, doublecomplex *, integer *, doublecomplex *, doublereal *, doublecomplex *, doublereal *, doublereal *, logical *, integer *, logical *, ftnlen); logical banded; doublereal errmax; doublecomplex transl; extern logical lzeres_(char *, char *, integer *, integer *, doublecomplex *, doublecomplex *, integer *, ftnlen, ftnlen); char transs[1]; /* Fortran I/O blocks */ static cilist io___139 = { 0, 0, 0, fmt_9994, 0 }; static cilist io___140 = { 0, 0, 0, fmt_9995, 0 }; static cilist io___141 = { 0, 0, 0, fmt_9993, 0 }; static cilist io___144 = { 0, 0, 0, fmt_9998, 0 }; static cilist io___146 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___147 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___148 = { 0, 0, 0, fmt_9996, 0 }; static cilist io___149 = { 0, 0, 0, fmt_9994, 0 }; static cilist io___150 = { 0, 0, 0, fmt_9995, 0 }; /* Tests ZGEMV and ZGBMV. */ /* Auxiliary routine for test program for Level 2 Blas. */ /* -- Written on 10-August-1987. */ /* Richard Hanson, Sandia National Labs. */ /* Jeremy Du Croz, NAG Central Office. */ /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Scalars .. */ /* .. Local Arrays .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. Scalars in Common .. */ /* .. Common blocks .. */ /* .. Data statements .. */ /* Parameter adjustments */ --idim; --kb; --alf; --bet; --inc; --g; --yt; --y; --x; --as; --aa; a_dim1 = *nmax; a_offset = 1 + a_dim1; a -= a_offset; --ys; --yy; --xs; --xx; /* Function Body */ /* .. Executable Statements .. */ full = *(unsigned char *)&sname[2] == 'E'; banded = *(unsigned char *)&sname[2] == 'B'; /* Define the number of arguments. */ if (full) { nargs = 11; } else if (banded) { nargs = 13; } nc = 0; reset = TRUE_; errmax = 0.; i__1 = *nidim; for (in = 1; in <= i__1; ++in) { n = idim[in]; nd = n / 2 + 1; for (im = 1; im <= 2; ++im) { if (im == 1) { /* Computing MAX */ i__2 = n - nd; m = max(i__2,0); } if (im == 2) { /* Computing MIN */ i__2 = n + nd; m = min(i__2,*nmax); } if (banded) { nk = *nkb; } else { nk = 1; } i__2 = nk; for (iku = 1; iku <= i__2; ++iku) { if (banded) { ku = kb[iku]; /* Computing MAX */ i__3 = ku - 1; kl = max(i__3,0); } else { ku = n - 1; kl = m - 1; } /* Set LDA to 1 more than minimum value if room. */ if (banded) { lda = kl + ku + 1; } else { lda = m; } if (lda < *nmax) { ++lda; } /* Skip tests if not enough room. */ if (lda > *nmax) { goto L100; } laa = lda * n; null = n <= 0 || m <= 0; /* Generate the matrix A. */ transl.r = 0., transl.i = 0.; zmake_(sname + 1, " ", " ", &m, &n, &a[a_offset], nmax, &aa[1] , &lda, &kl, &ku, &reset, &transl, (ftnlen)2, (ftnlen) 1, (ftnlen)1); for (ic = 1; ic <= 3; ++ic) { *(unsigned char *)trans = *(unsigned char *)&ich[ic - 1]; tran = *(unsigned char *)trans == 'T' || *(unsigned char * )trans == 'C'; if (tran) { ml = n; nl = m; } else { ml = m; nl = n; } i__3 = *ninc; for (ix = 1; ix <= i__3; ++ix) { incx = inc[ix]; lx = abs(incx) * nl; /* Generate the vector X. */ transl.r = .5, transl.i = 0.; i__4 = abs(incx); i__5 = nl - 1; zmake_("GE", " ", " ", &c__1, &nl, &x[1], &c__1, &xx[ 1], &i__4, &c__0, &i__5, &reset, &transl, ( ftnlen)2, (ftnlen)1, (ftnlen)1); if (nl > 1) { i__4 = nl / 2; x[i__4].r = 0., x[i__4].i = 0.; i__4 = abs(incx) * (nl / 2 - 1) + 1; xx[i__4].r = 0., xx[i__4].i = 0.; } i__4 = *ninc; for (iy = 1; iy <= i__4; ++iy) { incy = inc[iy]; ly = abs(incy) * ml; i__5 = *nalf; for (ia = 1; ia <= i__5; ++ia) { i__6 = ia; alpha.r = alf[i__6].r, alpha.i = alf[i__6].i; i__6 = *nbet; for (ib = 1; ib <= i__6; ++ib) { i__7 = ib; beta.r = bet[i__7].r, beta.i = bet[i__7] .i; /* Generate the vector Y. */ transl.r = 0., transl.i = 0.; i__7 = abs(incy); i__8 = ml - 1; zmake_("GE", " ", " ", &c__1, &ml, &y[1], &c__1, &yy[1], &i__7, &c__0, & i__8, &reset, &transl, (ftnlen)2, (ftnlen)1, (ftnlen)1); ++nc; /* Save every datum before calling the */ /* subroutine. */ *(unsigned char *)transs = *(unsigned char *)trans; ms = m; ns = n; kls = kl; kus = ku; als.r = alpha.r, als.i = alpha.i; i__7 = laa; for (i__ = 1; i__ <= i__7; ++i__) { i__8 = i__; i__9 = i__; as[i__8].r = aa[i__9].r, as[i__8].i = aa[i__9].i; /* L10: */ } ldas = lda; i__7 = lx; for (i__ = 1; i__ <= i__7; ++i__) { i__8 = i__; i__9 = i__; xs[i__8].r = xx[i__9].r, xs[i__8].i = xx[i__9].i; /* L20: */ } incxs = incx; bls.r = beta.r, bls.i = beta.i; i__7 = ly; for (i__ = 1; i__ <= i__7; ++i__) { i__8 = i__; i__9 = i__; ys[i__8].r = yy[i__9].r, ys[i__8].i = yy[i__9].i; /* L30: */ } incys = incy; /* Call the subroutine. */ if (full) { if (*trace) { io___139.ciunit = *ntra; s_wsfe(&io___139); do_fio(&c__1, (char *)&nc, ( ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, (char *)&m, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&n, (ftnlen) sizeof(integer)); do_fio(&c__2, (char *)&alpha, ( ftnlen)sizeof(doublereal)) ; do_fio(&c__1, (char *)&lda, ( ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&incx, ( ftnlen)sizeof(integer)); do_fio(&c__2, (char *)&beta, ( ftnlen)sizeof(doublereal)) ; do_fio(&c__1, (char *)&incy, ( ftnlen)sizeof(integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } zgemv_(trans, &m, &n, &alpha, &aa[1], &lda, &xx[1], &incx, &beta, & yy[1], &incy, (ftnlen)1); } else if (banded) { if (*trace) { io___140.ciunit = *ntra; s_wsfe(&io___140); do_fio(&c__1, (char *)&nc, ( ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, (char *)&m, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&n, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&kl, ( ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&ku, ( ftnlen)sizeof(integer)); do_fio(&c__2, (char *)&alpha, ( ftnlen)sizeof(doublereal)) ; do_fio(&c__1, (char *)&lda, ( ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&incx, ( ftnlen)sizeof(integer)); do_fio(&c__2, (char *)&beta, ( ftnlen)sizeof(doublereal)) ; do_fio(&c__1, (char *)&incy, ( ftnlen)sizeof(integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } zgbmv_(trans, &m, &n, &kl, &ku, & alpha, &aa[1], &lda, &xx[1], & incx, &beta, &yy[1], &incy, ( ftnlen)1); } /* Check if error-exit was taken incorrectly. */ if (! infoc_1.ok) { io___141.ciunit = *nout; s_wsfe(&io___141); e_wsfe(); *fatal = TRUE_; goto L130; } /* See what data changed inside subroutines. */ isame[0] = *(unsigned char *)trans == *( unsigned char *)transs; isame[1] = ms == m; isame[2] = ns == n; if (full) { isame[3] = als.r == alpha.r && als.i == alpha.i; isame[4] = lze_(&as[1], &aa[1], &laa); isame[5] = ldas == lda; isame[6] = lze_(&xs[1], &xx[1], &lx); isame[7] = incxs == incx; isame[8] = bls.r == beta.r && bls.i == beta.i; if (null) { isame[9] = lze_(&ys[1], &yy[1], & ly); } else { i__7 = abs(incy); isame[9] = lzeres_("GE", " ", & c__1, &ml, &ys[1], &yy[1], &i__7, (ftnlen)2, ( ftnlen)1); } isame[10] = incys == incy; } else if (banded) { isame[3] = kls == kl; isame[4] = kus == ku; isame[5] = als.r == alpha.r && als.i == alpha.i; isame[6] = lze_(&as[1], &aa[1], &laa); isame[7] = ldas == lda; isame[8] = lze_(&xs[1], &xx[1], &lx); isame[9] = incxs == incx; isame[10] = bls.r == beta.r && bls.i == beta.i; if (null) { isame[11] = lze_(&ys[1], &yy[1], & ly); } else { i__7 = abs(incy); isame[11] = lzeres_("GE", " ", & c__1, &ml, &ys[1], &yy[1], &i__7, (ftnlen)2, ( ftnlen)1); } isame[12] = incys == incy; } /* If data was incorrectly changed, report */ /* and return. */ same = TRUE_; i__7 = nargs; for (i__ = 1; i__ <= i__7; ++i__) { same = same && isame[i__ - 1]; if (! isame[i__ - 1]) { io___144.ciunit = *nout; s_wsfe(&io___144); do_fio(&c__1, (char *)&i__, ( ftnlen)sizeof(integer)); e_wsfe(); } /* L40: */ } if (! same) { *fatal = TRUE_; goto L130; } if (! null) { /* Check the result. */ zmvch_(trans, &m, &n, &alpha, &a[ a_offset], nmax, &x[1], &incx, &beta, &y[1], &incy, &yt[1], &g[1], &yy[1], eps, &err, fatal, nout, &c_true, (ftnlen) 1); errmax = max(errmax,err); /* If got really bad answer, report and */ /* return. */ if (*fatal) { goto L130; } } else { /* Avoid repeating tests with M.le.0 or */ /* N.le.0. */ goto L110; } /* L50: */ } /* L60: */ } /* L70: */ } /* L80: */ } /* L90: */ } L100: ; } L110: ; } /* L120: */ } /* Report result. */ if (errmax < *thresh) { io___146.ciunit = *nout; s_wsfe(&io___146); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); e_wsfe(); } else { io___147.ciunit = *nout; s_wsfe(&io___147); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&errmax, (ftnlen)sizeof(doublereal)); e_wsfe(); } goto L140; L130: io___148.ciunit = *nout; s_wsfe(&io___148); do_fio(&c__1, sname, (ftnlen)6); e_wsfe(); if (full) { io___149.ciunit = *nout; s_wsfe(&io___149); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, (char *)&m, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)); do_fio(&c__2, (char *)&alpha, (ftnlen)sizeof(doublereal)); do_fio(&c__1, (char *)&lda, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&incx, (ftnlen)sizeof(integer)); do_fio(&c__2, (char *)&beta, (ftnlen)sizeof(doublereal)); do_fio(&c__1, (char *)&incy, (ftnlen)sizeof(integer)); e_wsfe(); } else if (banded) { io___150.ciunit = *nout; s_wsfe(&io___150); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, (char *)&m, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&kl, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&ku, (ftnlen)sizeof(integer)); do_fio(&c__2, (char *)&alpha, (ftnlen)sizeof(doublereal)); do_fio(&c__1, (char *)&lda, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&incx, (ftnlen)sizeof(integer)); do_fio(&c__2, (char *)&beta, (ftnlen)sizeof(doublereal)); do_fio(&c__1, (char *)&incy, (ftnlen)sizeof(integer)); e_wsfe(); } L140: return 0; /* End of ZCHK1. */ } /* zchk1_ */ /* Subroutine */ int zchk2_(char *sname, doublereal *eps, doublereal *thresh, integer *nout, integer *ntra, logical *trace, logical *rewi, logical * fatal, integer *nidim, integer *idim, integer *nkb, integer *kb, integer *nalf, doublecomplex *alf, integer *nbet, doublecomplex *bet, integer *ninc, integer *inc, integer *nmax, integer *incmax, doublecomplex *a, doublecomplex *aa, doublecomplex *as, doublecomplex *x, doublecomplex *xx, doublecomplex *xs, doublecomplex *y, doublecomplex *yy, doublecomplex *ys, doublecomplex *yt, doublereal * g, ftnlen sname_len) { /* Initialized data */ static char ich[2] = "UL"; /* Format strings */ static char fmt_9993[] = "(1x,i6,\002: \002,a6,\002('\002,a1,\002',\002," "i3,\002,(\002,f4.1,\002,\002,f4.1,\002), A,\002,i3,\002, X,\002," "i2,\002,(\002,f4.1,\002,\002,f4.1,\002), \002,\002Y,\002,i2,\002" ") .\002)"; static char fmt_9994[] = "(1x,i6,\002: \002,a6,\002('\002,a1,\002',\002," "2(i3,\002,\002),\002(\002,f4.1,\002,\002,f4.1,\002), A,\002,i3" ",\002, X,\002,i2,\002,(\002,f4.1,\002,\002,f4.1,\002), Y,\002,i2," "\002) .\002)"; static char fmt_9995[] = "(1x,i6,\002: \002,a6,\002('\002,a1,\002',\002," "i3,\002,(\002,f4.1,\002,\002,f4.1,\002), AP, X,\002,i2,\002,(" "\002,f4.1,\002,\002,f4.1,\002), Y,\002,i2,\002) " ".\002)"; static char fmt_9992[] = "(\002 ******* FATAL ERROR - ERROR-EXIT TAKEN O" "N VALID CALL *\002,\002******\002)"; static char fmt_9998[] = "(\002 ******* FATAL ERROR - PARAMETER NUMBER" " \002,i2,\002 WAS CH\002,\002ANGED INCORRECTLY *******\002)"; static char fmt_9999[] = "(\002 \002,a6,\002 PASSED THE COMPUTATIONAL TE" "STS (\002,i6,\002 CALL\002,\002S)\002)"; static char fmt_9997[] = "(\002 \002,a6,\002 COMPLETED THE COMPUTATIONAL" " TESTS (\002,i6,\002 C\002,\002ALLS)\002,/\002 ******* BUT WITH " "MAXIMUM TEST RATIO\002,f8.2,\002 - SUSPECT *******\002)"; static char fmt_9996[] = "(\002 ******* \002,a6,\002 FAILED ON CALL NUMB" "ER:\002)"; /* System generated locals */ integer a_dim1, a_offset, i__1, i__2, i__3, i__4, i__5, i__6, i__7, i__8, i__9; alist al__1; /* Builtin functions */ integer s_wsfe(cilist *), do_fio(integer *, char *, ftnlen), e_wsfe(void), f_rew(alist *); /* Local variables */ integer i__, k, n, ia, ib, ic, nc, ik, in, nk, ks, ix, iy, ns, lx, ly, laa, lda; doublecomplex als, bls; doublereal err; extern logical lze_(doublecomplex *, doublecomplex *, integer *); doublecomplex beta; integer ldas; logical same; integer incx, incy; logical full, null; char uplo[1]; doublecomplex alpha; logical isame[13]; extern /* Subroutine */ int zmake_(char *, char *, char *, integer *, integer *, doublecomplex *, integer *, doublecomplex *, integer *, integer *, integer *, logical *, doublecomplex *, ftnlen, ftnlen, ftnlen); integer nargs; logical reset; integer incxs, incys; extern /* Subroutine */ int zhbmv_(char *, integer *, integer *, doublecomplex *, doublecomplex *, integer *, doublecomplex *, integer *, doublecomplex *, doublecomplex *, integer *, ftnlen), zmvch_(char *, integer *, integer *, doublecomplex *, doublecomplex *, integer *, doublecomplex *, integer *, doublecomplex *, doublecomplex *, integer *, doublecomplex *, doublereal *, doublecomplex *, doublereal *, doublereal *, logical *, integer *, logical *, ftnlen), zhemv_(char *, integer * , doublecomplex *, doublecomplex *, integer *, doublecomplex *, integer *, doublecomplex *, doublecomplex *, integer *, ftnlen); char uplos[1]; extern /* Subroutine */ int zhpmv_(char *, integer *, doublecomplex *, doublecomplex *, doublecomplex *, integer *, doublecomplex *, doublecomplex *, integer *, ftnlen); logical banded, packed; doublereal errmax; doublecomplex transl; extern logical lzeres_(char *, char *, integer *, integer *, doublecomplex *, doublecomplex *, integer *, ftnlen, ftnlen); /* Fortran I/O blocks */ static cilist io___189 = { 0, 0, 0, fmt_9993, 0 }; static cilist io___190 = { 0, 0, 0, fmt_9994, 0 }; static cilist io___191 = { 0, 0, 0, fmt_9995, 0 }; static cilist io___192 = { 0, 0, 0, fmt_9992, 0 }; static cilist io___195 = { 0, 0, 0, fmt_9998, 0 }; static cilist io___197 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___198 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___199 = { 0, 0, 0, fmt_9996, 0 }; static cilist io___200 = { 0, 0, 0, fmt_9993, 0 }; static cilist io___201 = { 0, 0, 0, fmt_9994, 0 }; static cilist io___202 = { 0, 0, 0, fmt_9995, 0 }; /* Tests ZHEMV, ZHBMV and ZHPMV. */ /* Auxiliary routine for test program for Level 2 Blas. */ /* -- Written on 10-August-1987. */ /* Richard Hanson, Sandia National Labs. */ /* Jeremy Du Croz, NAG Central Office. */ /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Scalars .. */ /* .. Local Arrays .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. Scalars in Common .. */ /* .. Common blocks .. */ /* .. Data statements .. */ /* Parameter adjustments */ --idim; --kb; --alf; --bet; --inc; --g; --yt; --y; --x; --as; --aa; a_dim1 = *nmax; a_offset = 1 + a_dim1; a -= a_offset; --ys; --yy; --xs; --xx; /* Function Body */ /* .. Executable Statements .. */ full = *(unsigned char *)&sname[2] == 'E'; banded = *(unsigned char *)&sname[2] == 'B'; packed = *(unsigned char *)&sname[2] == 'P'; /* Define the number of arguments. */ if (full) { nargs = 10; } else if (banded) { nargs = 11; } else if (packed) { nargs = 9; } nc = 0; reset = TRUE_; errmax = 0.; i__1 = *nidim; for (in = 1; in <= i__1; ++in) { n = idim[in]; if (banded) { nk = *nkb; } else { nk = 1; } i__2 = nk; for (ik = 1; ik <= i__2; ++ik) { if (banded) { k = kb[ik]; } else { k = n - 1; } /* Set LDA to 1 more than minimum value if room. */ if (banded) { lda = k + 1; } else { lda = n; } if (lda < *nmax) { ++lda; } /* Skip tests if not enough room. */ if (lda > *nmax) { goto L100; } if (packed) { laa = n * (n + 1) / 2; } else { laa = lda * n; } null = n <= 0; for (ic = 1; ic <= 2; ++ic) { *(unsigned char *)uplo = *(unsigned char *)&ich[ic - 1]; /* Generate the matrix A. */ transl.r = 0., transl.i = 0.; zmake_(sname + 1, uplo, " ", &n, &n, &a[a_offset], nmax, &aa[ 1], &lda, &k, &k, &reset, &transl, (ftnlen)2, (ftnlen) 1, (ftnlen)1); i__3 = *ninc; for (ix = 1; ix <= i__3; ++ix) { incx = inc[ix]; lx = abs(incx) * n; /* Generate the vector X. */ transl.r = .5, transl.i = 0.; i__4 = abs(incx); i__5 = n - 1; zmake_("GE", " ", " ", &c__1, &n, &x[1], &c__1, &xx[1], & i__4, &c__0, &i__5, &reset, &transl, (ftnlen)2, ( ftnlen)1, (ftnlen)1); if (n > 1) { i__4 = n / 2; x[i__4].r = 0., x[i__4].i = 0.; i__4 = abs(incx) * (n / 2 - 1) + 1; xx[i__4].r = 0., xx[i__4].i = 0.; } i__4 = *ninc; for (iy = 1; iy <= i__4; ++iy) { incy = inc[iy]; ly = abs(incy) * n; i__5 = *nalf; for (ia = 1; ia <= i__5; ++ia) { i__6 = ia; alpha.r = alf[i__6].r, alpha.i = alf[i__6].i; i__6 = *nbet; for (ib = 1; ib <= i__6; ++ib) { i__7 = ib; beta.r = bet[i__7].r, beta.i = bet[i__7].i; /* Generate the vector Y. */ transl.r = 0., transl.i = 0.; i__7 = abs(incy); i__8 = n - 1; zmake_("GE", " ", " ", &c__1, &n, &y[1], & c__1, &yy[1], &i__7, &c__0, &i__8, & reset, &transl, (ftnlen)2, (ftnlen)1, (ftnlen)1); ++nc; /* Save every datum before calling the */ /* subroutine. */ *(unsigned char *)uplos = *(unsigned char *) uplo; ns = n; ks = k; als.r = alpha.r, als.i = alpha.i; i__7 = laa; for (i__ = 1; i__ <= i__7; ++i__) { i__8 = i__; i__9 = i__; as[i__8].r = aa[i__9].r, as[i__8].i = aa[ i__9].i; /* L10: */ } ldas = lda; i__7 = lx; for (i__ = 1; i__ <= i__7; ++i__) { i__8 = i__; i__9 = i__; xs[i__8].r = xx[i__9].r, xs[i__8].i = xx[ i__9].i; /* L20: */ } incxs = incx; bls.r = beta.r, bls.i = beta.i; i__7 = ly; for (i__ = 1; i__ <= i__7; ++i__) { i__8 = i__; i__9 = i__; ys[i__8].r = yy[i__9].r, ys[i__8].i = yy[ i__9].i; /* L30: */ } incys = incy; /* Call the subroutine. */ if (full) { if (*trace) { io___189.ciunit = *ntra; s_wsfe(&io___189); do_fio(&c__1, (char *)&nc, (ftnlen) sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen) sizeof(integer)); do_fio(&c__2, (char *)&alpha, (ftnlen) sizeof(doublereal)); do_fio(&c__1, (char *)&lda, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&incx, (ftnlen) sizeof(integer)); do_fio(&c__2, (char *)&beta, (ftnlen) sizeof(doublereal)); do_fio(&c__1, (char *)&incy, (ftnlen) sizeof(integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } zhemv_(uplo, &n, &alpha, &aa[1], &lda, & xx[1], &incx, &beta, &yy[1], & incy, (ftnlen)1); } else if (banded) { if (*trace) { io___190.ciunit = *ntra; s_wsfe(&io___190); do_fio(&c__1, (char *)&nc, (ftnlen) sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&k, (ftnlen) sizeof(integer)); do_fio(&c__2, (char *)&alpha, (ftnlen) sizeof(doublereal)); do_fio(&c__1, (char *)&lda, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&incx, (ftnlen) sizeof(integer)); do_fio(&c__2, (char *)&beta, (ftnlen) sizeof(doublereal)); do_fio(&c__1, (char *)&incy, (ftnlen) sizeof(integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } zhbmv_(uplo, &n, &k, &alpha, &aa[1], &lda, &xx[1], &incx, &beta, &yy[1], & incy, (ftnlen)1); } else if (packed) { if (*trace) { io___191.ciunit = *ntra; s_wsfe(&io___191); do_fio(&c__1, (char *)&nc, (ftnlen) sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen) sizeof(integer)); do_fio(&c__2, (char *)&alpha, (ftnlen) sizeof(doublereal)); do_fio(&c__1, (char *)&incx, (ftnlen) sizeof(integer)); do_fio(&c__2, (char *)&beta, (ftnlen) sizeof(doublereal)); do_fio(&c__1, (char *)&incy, (ftnlen) sizeof(integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } zhpmv_(uplo, &n, &alpha, &aa[1], &xx[1], & incx, &beta, &yy[1], &incy, ( ftnlen)1); } /* Check if error-exit was taken incorrectly. */ if (! infoc_1.ok) { io___192.ciunit = *nout; s_wsfe(&io___192); e_wsfe(); *fatal = TRUE_; goto L120; } /* See what data changed inside subroutines. */ isame[0] = *(unsigned char *)uplo == *( unsigned char *)uplos; isame[1] = ns == n; if (full) { isame[2] = als.r == alpha.r && als.i == alpha.i; isame[3] = lze_(&as[1], &aa[1], &laa); isame[4] = ldas == lda; isame[5] = lze_(&xs[1], &xx[1], &lx); isame[6] = incxs == incx; isame[7] = bls.r == beta.r && bls.i == beta.i; if (null) { isame[8] = lze_(&ys[1], &yy[1], &ly); } else { i__7 = abs(incy); isame[8] = lzeres_("GE", " ", &c__1, & n, &ys[1], &yy[1], &i__7, ( ftnlen)2, (ftnlen)1); } isame[9] = incys == incy; } else if (banded) { isame[2] = ks == k; isame[3] = als.r == alpha.r && als.i == alpha.i; isame[4] = lze_(&as[1], &aa[1], &laa); isame[5] = ldas == lda; isame[6] = lze_(&xs[1], &xx[1], &lx); isame[7] = incxs == incx; isame[8] = bls.r == beta.r && bls.i == beta.i; if (null) { isame[9] = lze_(&ys[1], &yy[1], &ly); } else { i__7 = abs(incy); isame[9] = lzeres_("GE", " ", &c__1, & n, &ys[1], &yy[1], &i__7, ( ftnlen)2, (ftnlen)1); } isame[10] = incys == incy; } else if (packed) { isame[2] = als.r == alpha.r && als.i == alpha.i; isame[3] = lze_(&as[1], &aa[1], &laa); isame[4] = lze_(&xs[1], &xx[1], &lx); isame[5] = incxs == incx; isame[6] = bls.r == beta.r && bls.i == beta.i; if (null) { isame[7] = lze_(&ys[1], &yy[1], &ly); } else { i__7 = abs(incy); isame[7] = lzeres_("GE", " ", &c__1, & n, &ys[1], &yy[1], &i__7, ( ftnlen)2, (ftnlen)1); } isame[8] = incys == incy; } /* If data was incorrectly changed, report and */ /* return. */ same = TRUE_; i__7 = nargs; for (i__ = 1; i__ <= i__7; ++i__) { same = same && isame[i__ - 1]; if (! isame[i__ - 1]) { io___195.ciunit = *nout; s_wsfe(&io___195); do_fio(&c__1, (char *)&i__, (ftnlen) sizeof(integer)); e_wsfe(); } /* L40: */ } if (! same) { *fatal = TRUE_; goto L120; } if (! null) { /* Check the result. */ zmvch_("N", &n, &n, &alpha, &a[a_offset], nmax, &x[1], &incx, &beta, &y[1], &incy, &yt[1], &g[1], &yy[1], eps, &err, fatal, nout, &c_true, ( ftnlen)1); errmax = max(errmax,err); /* If got really bad answer, report and */ /* return. */ if (*fatal) { goto L120; } } else { /* Avoid repeating tests with N.le.0 */ goto L110; } /* L50: */ } /* L60: */ } /* L70: */ } /* L80: */ } /* L90: */ } L100: ; } L110: ; } /* Report result. */ if (errmax < *thresh) { io___197.ciunit = *nout; s_wsfe(&io___197); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); e_wsfe(); } else { io___198.ciunit = *nout; s_wsfe(&io___198); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&errmax, (ftnlen)sizeof(doublereal)); e_wsfe(); } goto L130; L120: io___199.ciunit = *nout; s_wsfe(&io___199); do_fio(&c__1, sname, (ftnlen)6); e_wsfe(); if (full) { io___200.ciunit = *nout; s_wsfe(&io___200); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)); do_fio(&c__2, (char *)&alpha, (ftnlen)sizeof(doublereal)); do_fio(&c__1, (char *)&lda, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&incx, (ftnlen)sizeof(integer)); do_fio(&c__2, (char *)&beta, (ftnlen)sizeof(doublereal)); do_fio(&c__1, (char *)&incy, (ftnlen)sizeof(integer)); e_wsfe(); } else if (banded) { io___201.ciunit = *nout; s_wsfe(&io___201); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&k, (ftnlen)sizeof(integer)); do_fio(&c__2, (char *)&alpha, (ftnlen)sizeof(doublereal)); do_fio(&c__1, (char *)&lda, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&incx, (ftnlen)sizeof(integer)); do_fio(&c__2, (char *)&beta, (ftnlen)sizeof(doublereal)); do_fio(&c__1, (char *)&incy, (ftnlen)sizeof(integer)); e_wsfe(); } else if (packed) { io___202.ciunit = *nout; s_wsfe(&io___202); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)); do_fio(&c__2, (char *)&alpha, (ftnlen)sizeof(doublereal)); do_fio(&c__1, (char *)&incx, (ftnlen)sizeof(integer)); do_fio(&c__2, (char *)&beta, (ftnlen)sizeof(doublereal)); do_fio(&c__1, (char *)&incy, (ftnlen)sizeof(integer)); e_wsfe(); } L130: return 0; /* End of ZCHK2. */ } /* zchk2_ */ /* Subroutine */ int zchk3_(char *sname, doublereal *eps, doublereal *thresh, integer *nout, integer *ntra, logical *trace, logical *rewi, logical * fatal, integer *nidim, integer *idim, integer *nkb, integer *kb, integer *ninc, integer *inc, integer *nmax, integer *incmax, doublecomplex *a, doublecomplex *aa, doublecomplex *as, doublecomplex *x, doublecomplex *xx, doublecomplex *xs, doublecomplex *xt, doublereal *g, doublecomplex *z__, ftnlen sname_len) { /* Initialized data */ static char ichu[2] = "UL"; static char icht[3] = "NTC"; static char ichd[2] = "UN"; /* Format strings */ static char fmt_9993[] = "(1x,i6,\002: \002,a6,\002(\002,3(\002'\002,a1" ",\002',\002),i3,\002, A,\002,i3,\002, X,\002,i2,\002) " " .\002)"; static char fmt_9994[] = "(1x,i6,\002: \002,a6,\002(\002,3(\002'\002,a1" ",\002',\002),2(i3,\002,\002),\002 A,\002,i3,\002, X,\002,i2,\002" ") .\002)"; static char fmt_9995[] = "(1x,i6,\002: \002,a6,\002(\002,3(\002'\002,a1" ",\002',\002),i3,\002, AP, \002,\002X,\002,i2,\002) " " .\002)"; static char fmt_9992[] = "(\002 ******* FATAL ERROR - ERROR-EXIT TAKEN O" "N VALID CALL *\002,\002******\002)"; static char fmt_9998[] = "(\002 ******* FATAL ERROR - PARAMETER NUMBER" " \002,i2,\002 WAS CH\002,\002ANGED INCORRECTLY *******\002)"; static char fmt_9999[] = "(\002 \002,a6,\002 PASSED THE COMPUTATIONAL TE" "STS (\002,i6,\002 CALL\002,\002S)\002)"; static char fmt_9997[] = "(\002 \002,a6,\002 COMPLETED THE COMPUTATIONAL" " TESTS (\002,i6,\002 C\002,\002ALLS)\002,/\002 ******* BUT WITH " "MAXIMUM TEST RATIO\002,f8.2,\002 - SUSPECT *******\002)"; static char fmt_9996[] = "(\002 ******* \002,a6,\002 FAILED ON CALL NUMB" "ER:\002)"; /* System generated locals */ integer a_dim1, a_offset, i__1, i__2, i__3, i__4, i__5, i__6; alist al__1; /* Builtin functions */ integer s_cmp(const char *, const char *, ftnlen, ftnlen), s_wsfe(cilist *), do_fio( integer *, char *, ftnlen), e_wsfe(void), f_rew(alist *); /* Local variables */ integer i__, k, n, nc, ik, in, nk, ks, ix, ns, lx, laa, icd, lda, ict, icu; doublereal err; extern logical lze_(doublecomplex *, doublecomplex *, integer *); char diag[1]; integer ldas; logical same; integer incx; logical full, null; char uplo[1], diags[1]; logical isame[13]; extern /* Subroutine */ int zmake_(char *, char *, char *, integer *, integer *, doublecomplex *, integer *, doublecomplex *, integer *, integer *, integer *, logical *, doublecomplex *, ftnlen, ftnlen, ftnlen); integer nargs; logical reset; integer incxs; char trans[1]; extern /* Subroutine */ int zmvch_(char *, integer *, integer *, doublecomplex *, doublecomplex *, integer *, doublecomplex *, integer *, doublecomplex *, doublecomplex *, integer *, doublecomplex *, doublereal *, doublecomplex *, doublereal *, doublereal *, logical *, integer *, logical *, ftnlen); char uplos[1]; extern /* Subroutine */ int ztbmv_(char *, char *, char *, integer *, integer *, doublecomplex *, integer *, doublecomplex *, integer *, ftnlen, ftnlen, ftnlen), ztbsv_(char *, char *, char *, integer * , integer *, doublecomplex *, integer *, doublecomplex *, integer *, ftnlen, ftnlen, ftnlen), ztpmv_(char *, char *, char *, integer *, doublecomplex *, doublecomplex *, integer *, ftnlen, ftnlen, ftnlen), ztrmv_(char *, char *, char *, integer *, doublecomplex *, integer *, doublecomplex *, integer *, ftnlen, ftnlen, ftnlen), ztpsv_(char *, char *, char *, integer *, doublecomplex *, doublecomplex *, integer *, ftnlen, ftnlen, ftnlen), ztrsv_(char *, char *, char *, integer *, doublecomplex * , integer *, doublecomplex *, integer *, ftnlen, ftnlen, ftnlen); logical banded, packed; doublereal errmax; doublecomplex transl; extern logical lzeres_(char *, char *, integer *, integer *, doublecomplex *, doublecomplex *, integer *, ftnlen, ftnlen); char transs[1]; /* Fortran I/O blocks */ static cilist io___239 = { 0, 0, 0, fmt_9993, 0 }; static cilist io___240 = { 0, 0, 0, fmt_9994, 0 }; static cilist io___241 = { 0, 0, 0, fmt_9995, 0 }; static cilist io___242 = { 0, 0, 0, fmt_9993, 0 }; static cilist io___243 = { 0, 0, 0, fmt_9994, 0 }; static cilist io___244 = { 0, 0, 0, fmt_9995, 0 }; static cilist io___245 = { 0, 0, 0, fmt_9992, 0 }; static cilist io___248 = { 0, 0, 0, fmt_9998, 0 }; static cilist io___250 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___251 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___252 = { 0, 0, 0, fmt_9996, 0 }; static cilist io___253 = { 0, 0, 0, fmt_9993, 0 }; static cilist io___254 = { 0, 0, 0, fmt_9994, 0 }; static cilist io___255 = { 0, 0, 0, fmt_9995, 0 }; /* Tests ZTRMV, ZTBMV, ZTPMV, ZTRSV, ZTBSV and ZTPSV. */ /* Auxiliary routine for test program for Level 2 Blas. */ /* -- Written on 10-August-1987. */ /* Richard Hanson, Sandia National Labs. */ /* Jeremy Du Croz, NAG Central Office. */ /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Scalars .. */ /* .. Local Arrays .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. Scalars in Common .. */ /* .. Common blocks .. */ /* .. Data statements .. */ /* Parameter adjustments */ --idim; --kb; --inc; --z__; --g; --xt; --x; --as; --aa; a_dim1 = *nmax; a_offset = 1 + a_dim1; a -= a_offset; --xs; --xx; /* Function Body */ /* .. Executable Statements .. */ full = *(unsigned char *)&sname[2] == 'R'; banded = *(unsigned char *)&sname[2] == 'B'; packed = *(unsigned char *)&sname[2] == 'P'; /* Define the number of arguments. */ if (full) { nargs = 8; } else if (banded) { nargs = 9; } else if (packed) { nargs = 7; } nc = 0; reset = TRUE_; errmax = 0.; /* Set up zero vector for ZMVCH. */ i__1 = *nmax; for (i__ = 1; i__ <= i__1; ++i__) { i__2 = i__; z__[i__2].r = 0., z__[i__2].i = 0.; /* L10: */ } i__1 = *nidim; for (in = 1; in <= i__1; ++in) { n = idim[in]; if (banded) { nk = *nkb; } else { nk = 1; } i__2 = nk; for (ik = 1; ik <= i__2; ++ik) { if (banded) { k = kb[ik]; } else { k = n - 1; } /* Set LDA to 1 more than minimum value if room. */ if (banded) { lda = k + 1; } else { lda = n; } if (lda < *nmax) { ++lda; } /* Skip tests if not enough room. */ if (lda > *nmax) { goto L100; } if (packed) { laa = n * (n + 1) / 2; } else { laa = lda * n; } null = n <= 0; for (icu = 1; icu <= 2; ++icu) { *(unsigned char *)uplo = *(unsigned char *)&ichu[icu - 1]; for (ict = 1; ict <= 3; ++ict) { *(unsigned char *)trans = *(unsigned char *)&icht[ict - 1] ; for (icd = 1; icd <= 2; ++icd) { *(unsigned char *)diag = *(unsigned char *)&ichd[icd - 1]; /* Generate the matrix A. */ transl.r = 0., transl.i = 0.; zmake_(sname + 1, uplo, diag, &n, &n, &a[a_offset], nmax, &aa[1], &lda, &k, &k, &reset, &transl, ( ftnlen)2, (ftnlen)1, (ftnlen)1); i__3 = *ninc; for (ix = 1; ix <= i__3; ++ix) { incx = inc[ix]; lx = abs(incx) * n; /* Generate the vector X. */ transl.r = .5, transl.i = 0.; i__4 = abs(incx); i__5 = n - 1; zmake_("GE", " ", " ", &c__1, &n, &x[1], &c__1, & xx[1], &i__4, &c__0, &i__5, &reset, & transl, (ftnlen)2, (ftnlen)1, (ftnlen)1); if (n > 1) { i__4 = n / 2; x[i__4].r = 0., x[i__4].i = 0.; i__4 = abs(incx) * (n / 2 - 1) + 1; xx[i__4].r = 0., xx[i__4].i = 0.; } ++nc; /* Save every datum before calling the subroutine. */ *(unsigned char *)uplos = *(unsigned char *)uplo; *(unsigned char *)transs = *(unsigned char *) trans; *(unsigned char *)diags = *(unsigned char *)diag; ns = n; ks = k; i__4 = laa; for (i__ = 1; i__ <= i__4; ++i__) { i__5 = i__; i__6 = i__; as[i__5].r = aa[i__6].r, as[i__5].i = aa[i__6] .i; /* L20: */ } ldas = lda; i__4 = lx; for (i__ = 1; i__ <= i__4; ++i__) { i__5 = i__; i__6 = i__; xs[i__5].r = xx[i__6].r, xs[i__5].i = xx[i__6] .i; /* L30: */ } incxs = incx; /* Call the subroutine. */ if (s_cmp(sname + 3, "MV", (ftnlen)2, (ftnlen)2) == 0) { if (full) { if (*trace) { io___239.ciunit = *ntra; s_wsfe(&io___239); do_fio(&c__1, (char *)&nc, (ftnlen) sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, diag, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&lda, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&incx, (ftnlen) sizeof(integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } ztrmv_(uplo, trans, diag, &n, &aa[1], & lda, &xx[1], &incx, (ftnlen)1, ( ftnlen)1, (ftnlen)1); } else if (banded) { if (*trace) { io___240.ciunit = *ntra; s_wsfe(&io___240); do_fio(&c__1, (char *)&nc, (ftnlen) sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, diag, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&k, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&lda, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&incx, (ftnlen) sizeof(integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } ztbmv_(uplo, trans, diag, &n, &k, &aa[1], &lda, &xx[1], &incx, (ftnlen)1, ( ftnlen)1, (ftnlen)1); } else if (packed) { if (*trace) { io___241.ciunit = *ntra; s_wsfe(&io___241); do_fio(&c__1, (char *)&nc, (ftnlen) sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, diag, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&incx, (ftnlen) sizeof(integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } ztpmv_(uplo, trans, diag, &n, &aa[1], &xx[ 1], &incx, (ftnlen)1, (ftnlen)1, ( ftnlen)1); } } else if (s_cmp(sname + 3, "SV", (ftnlen)2, ( ftnlen)2) == 0) { if (full) { if (*trace) { io___242.ciunit = *ntra; s_wsfe(&io___242); do_fio(&c__1, (char *)&nc, (ftnlen) sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, diag, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&lda, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&incx, (ftnlen) sizeof(integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } ztrsv_(uplo, trans, diag, &n, &aa[1], & lda, &xx[1], &incx, (ftnlen)1, ( ftnlen)1, (ftnlen)1); } else if (banded) { if (*trace) { io___243.ciunit = *ntra; s_wsfe(&io___243); do_fio(&c__1, (char *)&nc, (ftnlen) sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, diag, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&k, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&lda, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&incx, (ftnlen) sizeof(integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } ztbsv_(uplo, trans, diag, &n, &k, &aa[1], &lda, &xx[1], &incx, (ftnlen)1, ( ftnlen)1, (ftnlen)1); } else if (packed) { if (*trace) { io___244.ciunit = *ntra; s_wsfe(&io___244); do_fio(&c__1, (char *)&nc, (ftnlen) sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, diag, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&incx, (ftnlen) sizeof(integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } ztpsv_(uplo, trans, diag, &n, &aa[1], &xx[ 1], &incx, (ftnlen)1, (ftnlen)1, ( ftnlen)1); } } /* Check if error-exit was taken incorrectly. */ if (! infoc_1.ok) { io___245.ciunit = *nout; s_wsfe(&io___245); e_wsfe(); *fatal = TRUE_; goto L120; } /* See what data changed inside subroutines. */ isame[0] = *(unsigned char *)uplo == *(unsigned char *)uplos; isame[1] = *(unsigned char *)trans == *(unsigned char *)transs; isame[2] = *(unsigned char *)diag == *(unsigned char *)diags; isame[3] = ns == n; if (full) { isame[4] = lze_(&as[1], &aa[1], &laa); isame[5] = ldas == lda; if (null) { isame[6] = lze_(&xs[1], &xx[1], &lx); } else { i__4 = abs(incx); isame[6] = lzeres_("GE", " ", &c__1, &n, & xs[1], &xx[1], &i__4, (ftnlen)2, ( ftnlen)1); } isame[7] = incxs == incx; } else if (banded) { isame[4] = ks == k; isame[5] = lze_(&as[1], &aa[1], &laa); isame[6] = ldas == lda; if (null) { isame[7] = lze_(&xs[1], &xx[1], &lx); } else { i__4 = abs(incx); isame[7] = lzeres_("GE", " ", &c__1, &n, & xs[1], &xx[1], &i__4, (ftnlen)2, ( ftnlen)1); } isame[8] = incxs == incx; } else if (packed) { isame[4] = lze_(&as[1], &aa[1], &laa); if (null) { isame[5] = lze_(&xs[1], &xx[1], &lx); } else { i__4 = abs(incx); isame[5] = lzeres_("GE", " ", &c__1, &n, & xs[1], &xx[1], &i__4, (ftnlen)2, ( ftnlen)1); } isame[6] = incxs == incx; } /* If data was incorrectly changed, report and */ /* return. */ same = TRUE_; i__4 = nargs; for (i__ = 1; i__ <= i__4; ++i__) { same = same && isame[i__ - 1]; if (! isame[i__ - 1]) { io___248.ciunit = *nout; s_wsfe(&io___248); do_fio(&c__1, (char *)&i__, (ftnlen) sizeof(integer)); e_wsfe(); } /* L40: */ } if (! same) { *fatal = TRUE_; goto L120; } if (! null) { if (s_cmp(sname + 3, "MV", (ftnlen)2, (ftnlen) 2) == 0) { /* Check the result. */ zmvch_(trans, &n, &n, &c_b2, &a[a_offset], nmax, &x[1], &incx, &c_b1, &z__[ 1], &incx, &xt[1], &g[1], &xx[1], eps, &err, fatal, nout, &c_true, ( ftnlen)1); } else if (s_cmp(sname + 3, "SV", (ftnlen)2, ( ftnlen)2) == 0) { /* Compute approximation to original vector. */ i__4 = n; for (i__ = 1; i__ <= i__4; ++i__) { i__5 = i__; i__6 = (i__ - 1) * abs(incx) + 1; z__[i__5].r = xx[i__6].r, z__[i__5].i = xx[i__6].i; i__5 = (i__ - 1) * abs(incx) + 1; i__6 = i__; xx[i__5].r = x[i__6].r, xx[i__5].i = x[i__6].i; /* L50: */ } zmvch_(trans, &n, &n, &c_b2, &a[a_offset], nmax, &z__[1], &incx, &c_b1, &x[ 1], &incx, &xt[1], &g[1], &xx[1], eps, &err, fatal, nout, &c_false, (ftnlen)1); } errmax = max(errmax,err); /* If got really bad answer, report and return. */ if (*fatal) { goto L120; } } else { /* Avoid repeating tests with N.le.0. */ goto L110; } /* L60: */ } /* L70: */ } /* L80: */ } /* L90: */ } L100: ; } L110: ; } /* Report result. */ if (errmax < *thresh) { io___250.ciunit = *nout; s_wsfe(&io___250); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); e_wsfe(); } else { io___251.ciunit = *nout; s_wsfe(&io___251); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&errmax, (ftnlen)sizeof(doublereal)); e_wsfe(); } goto L130; L120: io___252.ciunit = *nout; s_wsfe(&io___252); do_fio(&c__1, sname, (ftnlen)6); e_wsfe(); if (full) { io___253.ciunit = *nout; s_wsfe(&io___253); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, diag, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&lda, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&incx, (ftnlen)sizeof(integer)); e_wsfe(); } else if (banded) { io___254.ciunit = *nout; s_wsfe(&io___254); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, diag, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&k, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&lda, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&incx, (ftnlen)sizeof(integer)); e_wsfe(); } else if (packed) { io___255.ciunit = *nout; s_wsfe(&io___255); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, diag, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&incx, (ftnlen)sizeof(integer)); e_wsfe(); } L130: return 0; /* End of ZCHK3. */ } /* zchk3_ */ /* Subroutine */ int zchk4_(char *sname, doublereal *eps, doublereal *thresh, integer *nout, integer *ntra, logical *trace, logical *rewi, logical * fatal, integer *nidim, integer *idim, integer *nalf, doublecomplex * alf, integer *ninc, integer *inc, integer *nmax, integer *incmax, doublecomplex *a, doublecomplex *aa, doublecomplex *as, doublecomplex *x, doublecomplex *xx, doublecomplex *xs, doublecomplex *y, doublecomplex *yy, doublecomplex *ys, doublecomplex *yt, doublereal * g, doublecomplex *z__, ftnlen sname_len) { /* Format strings */ static char fmt_9994[] = "(1x,i6,\002: \002,a6,\002(\002,2(i3,\002," "\002),\002(\002,f4.1,\002,\002,f4.1,\002), X,\002,i2,\002, Y," "\002,i2,\002, A,\002,i3,\002) \002,\002 " ".\002)"; static char fmt_9993[] = "(\002 ******* FATAL ERROR - ERROR-EXIT TAKEN O" "N VALID CALL *\002,\002******\002)"; static char fmt_9998[] = "(\002 ******* FATAL ERROR - PARAMETER NUMBER" " \002,i2,\002 WAS CH\002,\002ANGED INCORRECTLY *******\002)"; static char fmt_9999[] = "(\002 \002,a6,\002 PASSED THE COMPUTATIONAL TE" "STS (\002,i6,\002 CALL\002,\002S)\002)"; static char fmt_9997[] = "(\002 \002,a6,\002 COMPLETED THE COMPUTATIONAL" " TESTS (\002,i6,\002 C\002,\002ALLS)\002,/\002 ******* BUT WITH " "MAXIMUM TEST RATIO\002,f8.2,\002 - SUSPECT *******\002)"; static char fmt_9995[] = "(\002 THESE ARE THE RESULTS FOR COLUMN" " \002,i3)"; static char fmt_9996[] = "(\002 ******* \002,a6,\002 FAILED ON CALL NUMB" "ER:\002)"; /* System generated locals */ integer a_dim1, a_offset, i__1, i__2, i__3, i__4, i__5, i__6, i__7; doublecomplex z__1; alist al__1; /* Builtin functions */ integer s_wsfe(cilist *), do_fio(integer *, char *, ftnlen), e_wsfe(void), f_rew(alist *); void d_cnjg(doublecomplex *, const doublecomplex *); /* Local variables */ integer i__, j, m, n; doublecomplex w[1]; integer ia, nc, nd, im, in, ms, ix, iy, ns, lx, ly, laa, lda; doublecomplex als; doublereal err; extern logical lze_(doublecomplex *, doublecomplex *, integer *); integer ldas; logical same, conj; integer incx, incy; logical null; doublecomplex alpha; logical isame[13]; extern /* Subroutine */ int zmake_(char *, char *, char *, integer *, integer *, doublecomplex *, integer *, doublecomplex *, integer *, integer *, integer *, logical *, doublecomplex *, ftnlen, ftnlen, ftnlen); integer nargs; extern /* Subroutine */ int zgerc_(integer *, integer *, doublecomplex *, doublecomplex *, integer *, doublecomplex *, integer *, doublecomplex *, integer *); logical reset; integer incxs, incys; extern /* Subroutine */ int zmvch_(char *, integer *, integer *, doublecomplex *, doublecomplex *, integer *, doublecomplex *, integer *, doublecomplex *, doublecomplex *, integer *, doublecomplex *, doublereal *, doublecomplex *, doublereal *, doublereal *, logical *, integer *, logical *, ftnlen), zgeru_( integer *, integer *, doublecomplex *, doublecomplex *, integer *, doublecomplex *, integer *, doublecomplex *, integer *); doublereal errmax; doublecomplex transl; extern logical lzeres_(char *, char *, integer *, integer *, doublecomplex *, doublecomplex *, integer *, ftnlen, ftnlen); /* Fortran I/O blocks */ static cilist io___285 = { 0, 0, 0, fmt_9994, 0 }; static cilist io___286 = { 0, 0, 0, fmt_9993, 0 }; static cilist io___289 = { 0, 0, 0, fmt_9998, 0 }; static cilist io___293 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___294 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___295 = { 0, 0, 0, fmt_9995, 0 }; static cilist io___296 = { 0, 0, 0, fmt_9996, 0 }; static cilist io___297 = { 0, 0, 0, fmt_9994, 0 }; /* Tests ZGERC and ZGERU. */ /* Auxiliary routine for test program for Level 2 Blas. */ /* -- Written on 10-August-1987. */ /* Richard Hanson, Sandia National Labs. */ /* Jeremy Du Croz, NAG Central Office. */ /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Scalars .. */ /* .. Local Arrays .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. Scalars in Common .. */ /* .. Common blocks .. */ /* .. Executable Statements .. */ /* Parameter adjustments */ --idim; --alf; --inc; --z__; --g; --yt; --y; --x; --as; --aa; a_dim1 = *nmax; a_offset = 1 + a_dim1; a -= a_offset; --ys; --yy; --xs; --xx; /* Function Body */ conj = *(unsigned char *)&sname[4] == 'C'; /* Define the number of arguments. */ nargs = 9; nc = 0; reset = TRUE_; errmax = 0.; i__1 = *nidim; for (in = 1; in <= i__1; ++in) { n = idim[in]; nd = n / 2 + 1; for (im = 1; im <= 2; ++im) { if (im == 1) { /* Computing MAX */ i__2 = n - nd; m = max(i__2,0); } if (im == 2) { /* Computing MIN */ i__2 = n + nd; m = min(i__2,*nmax); } /* Set LDA to 1 more than minimum value if room. */ lda = m; if (lda < *nmax) { ++lda; } /* Skip tests if not enough room. */ if (lda > *nmax) { goto L110; } laa = lda * n; null = n <= 0 || m <= 0; i__2 = *ninc; for (ix = 1; ix <= i__2; ++ix) { incx = inc[ix]; lx = abs(incx) * m; /* Generate the vector X. */ transl.r = .5, transl.i = 0.; i__3 = abs(incx); i__4 = m - 1; zmake_("GE", " ", " ", &c__1, &m, &x[1], &c__1, &xx[1], &i__3, &c__0, &i__4, &reset, &transl, (ftnlen)2, (ftnlen)1, (ftnlen)1); if (m > 1) { i__3 = m / 2; x[i__3].r = 0., x[i__3].i = 0.; i__3 = abs(incx) * (m / 2 - 1) + 1; xx[i__3].r = 0., xx[i__3].i = 0.; } i__3 = *ninc; for (iy = 1; iy <= i__3; ++iy) { incy = inc[iy]; ly = abs(incy) * n; /* Generate the vector Y. */ transl.r = 0., transl.i = 0.; i__4 = abs(incy); i__5 = n - 1; zmake_("GE", " ", " ", &c__1, &n, &y[1], &c__1, &yy[1], & i__4, &c__0, &i__5, &reset, &transl, (ftnlen)2, ( ftnlen)1, (ftnlen)1); if (n > 1) { i__4 = n / 2; y[i__4].r = 0., y[i__4].i = 0.; i__4 = abs(incy) * (n / 2 - 1) + 1; yy[i__4].r = 0., yy[i__4].i = 0.; } i__4 = *nalf; for (ia = 1; ia <= i__4; ++ia) { i__5 = ia; alpha.r = alf[i__5].r, alpha.i = alf[i__5].i; /* Generate the matrix A. */ transl.r = 0., transl.i = 0.; i__5 = m - 1; i__6 = n - 1; zmake_(sname + 1, " ", " ", &m, &n, &a[a_offset], nmax, &aa[1], &lda, &i__5, &i__6, &reset, & transl, (ftnlen)2, (ftnlen)1, (ftnlen)1); ++nc; /* Save every datum before calling the subroutine. */ ms = m; ns = n; als.r = alpha.r, als.i = alpha.i; i__5 = laa; for (i__ = 1; i__ <= i__5; ++i__) { i__6 = i__; i__7 = i__; as[i__6].r = aa[i__7].r, as[i__6].i = aa[i__7].i; /* L10: */ } ldas = lda; i__5 = lx; for (i__ = 1; i__ <= i__5; ++i__) { i__6 = i__; i__7 = i__; xs[i__6].r = xx[i__7].r, xs[i__6].i = xx[i__7].i; /* L20: */ } incxs = incx; i__5 = ly; for (i__ = 1; i__ <= i__5; ++i__) { i__6 = i__; i__7 = i__; ys[i__6].r = yy[i__7].r, ys[i__6].i = yy[i__7].i; /* L30: */ } incys = incy; /* Call the subroutine. */ if (*trace) { io___285.ciunit = *ntra; s_wsfe(&io___285); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer) ); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&m, (ftnlen)sizeof(integer)) ; do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)) ; do_fio(&c__2, (char *)&alpha, (ftnlen)sizeof( doublereal)); do_fio(&c__1, (char *)&incx, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&incy, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&lda, (ftnlen)sizeof( integer)); e_wsfe(); } if (conj) { if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } zgerc_(&m, &n, &alpha, &xx[1], &incx, &yy[1], & incy, &aa[1], &lda); } else { if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } zgeru_(&m, &n, &alpha, &xx[1], &incx, &yy[1], & incy, &aa[1], &lda); } /* Check if error-exit was taken incorrectly. */ if (! infoc_1.ok) { io___286.ciunit = *nout; s_wsfe(&io___286); e_wsfe(); *fatal = TRUE_; goto L140; } /* See what data changed inside subroutine. */ isame[0] = ms == m; isame[1] = ns == n; isame[2] = als.r == alpha.r && als.i == alpha.i; isame[3] = lze_(&xs[1], &xx[1], &lx); isame[4] = incxs == incx; isame[5] = lze_(&ys[1], &yy[1], &ly); isame[6] = incys == incy; if (null) { isame[7] = lze_(&as[1], &aa[1], &laa); } else { isame[7] = lzeres_("GE", " ", &m, &n, &as[1], &aa[ 1], &lda, (ftnlen)2, (ftnlen)1); } isame[8] = ldas == lda; /* If data was incorrectly changed, report and return. */ same = TRUE_; i__5 = nargs; for (i__ = 1; i__ <= i__5; ++i__) { same = same && isame[i__ - 1]; if (! isame[i__ - 1]) { io___289.ciunit = *nout; s_wsfe(&io___289); do_fio(&c__1, (char *)&i__, (ftnlen)sizeof( integer)); e_wsfe(); } /* L40: */ } if (! same) { *fatal = TRUE_; goto L140; } if (! null) { /* Check the result column by column. */ if (incx > 0) { i__5 = m; for (i__ = 1; i__ <= i__5; ++i__) { i__6 = i__; i__7 = i__; z__[i__6].r = x[i__7].r, z__[i__6].i = x[ i__7].i; /* L50: */ } } else { i__5 = m; for (i__ = 1; i__ <= i__5; ++i__) { i__6 = i__; i__7 = m - i__ + 1; z__[i__6].r = x[i__7].r, z__[i__6].i = x[ i__7].i; /* L60: */ } } i__5 = n; for (j = 1; j <= i__5; ++j) { if (incy > 0) { i__6 = j; w[0].r = y[i__6].r, w[0].i = y[i__6].i; } else { i__6 = n - j + 1; w[0].r = y[i__6].r, w[0].i = y[i__6].i; } if (conj) { d_cnjg(&z__1, w); w[0].r = z__1.r, w[0].i = z__1.i; } zmvch_("N", &m, &c__1, &alpha, &z__[1], nmax, w, &c__1, &c_b2, &a[j * a_dim1 + 1], & c__1, &yt[1], &g[1], &aa[(j - 1) * lda + 1], eps, &err, fatal, nout, & c_true, (ftnlen)1); errmax = max(errmax,err); /* If got really bad answer, report and return. */ if (*fatal) { goto L130; } /* L70: */ } } else { /* Avoid repeating tests with M.le.0 or N.le.0. */ goto L110; } /* L80: */ } /* L90: */ } /* L100: */ } L110: ; } /* L120: */ } /* Report result. */ if (errmax < *thresh) { io___293.ciunit = *nout; s_wsfe(&io___293); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); e_wsfe(); } else { io___294.ciunit = *nout; s_wsfe(&io___294); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&errmax, (ftnlen)sizeof(doublereal)); e_wsfe(); } goto L150; L130: io___295.ciunit = *nout; s_wsfe(&io___295); do_fio(&c__1, (char *)&j, (ftnlen)sizeof(integer)); e_wsfe(); L140: io___296.ciunit = *nout; s_wsfe(&io___296); do_fio(&c__1, sname, (ftnlen)6); e_wsfe(); io___297.ciunit = *nout; s_wsfe(&io___297); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&m, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)); do_fio(&c__2, (char *)&alpha, (ftnlen)sizeof(doublereal)); do_fio(&c__1, (char *)&incx, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&incy, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&lda, (ftnlen)sizeof(integer)); e_wsfe(); L150: return 0; /* End of ZCHK4. */ } /* zchk4_ */ /* Subroutine */ int zchk5_(char *sname, doublereal *eps, doublereal *thresh, integer *nout, integer *ntra, logical *trace, logical *rewi, logical * fatal, integer *nidim, integer *idim, integer *nalf, doublecomplex * alf, integer *ninc, integer *inc, integer *nmax, integer *incmax, doublecomplex *a, doublecomplex *aa, doublecomplex *as, doublecomplex *x, doublecomplex *xx, doublecomplex *xs, doublecomplex *y, doublecomplex *yy, doublecomplex *ys, doublecomplex *yt, doublereal * g, doublecomplex *z__, ftnlen sname_len) { /* Initialized data */ static char ich[2] = "UL"; /* Format strings */ static char fmt_9993[] = "(1x,i6,\002: \002,a6,\002('\002,a1,\002',\002," "i3,\002,\002,f4.1,\002, X,\002,i2,\002, A,\002,i3,\002) " " .\002)"; static char fmt_9994[] = "(1x,i6,\002: \002,a6,\002('\002,a1,\002',\002," "i3,\002,\002,f4.1,\002, X,\002,i2,\002, AP) " " .\002)"; static char fmt_9992[] = "(\002 ******* FATAL ERROR - ERROR-EXIT TAKEN O" "N VALID CALL *\002,\002******\002)"; static char fmt_9998[] = "(\002 ******* FATAL ERROR - PARAMETER NUMBER" " \002,i2,\002 WAS CH\002,\002ANGED INCORRECTLY *******\002)"; static char fmt_9999[] = "(\002 \002,a6,\002 PASSED THE COMPUTATIONAL TE" "STS (\002,i6,\002 CALL\002,\002S)\002)"; static char fmt_9997[] = "(\002 \002,a6,\002 COMPLETED THE COMPUTATIONAL" " TESTS (\002,i6,\002 C\002,\002ALLS)\002,/\002 ******* BUT WITH " "MAXIMUM TEST RATIO\002,f8.2,\002 - SUSPECT *******\002)"; static char fmt_9995[] = "(\002 THESE ARE THE RESULTS FOR COLUMN" " \002,i3)"; static char fmt_9996[] = "(\002 ******* \002,a6,\002 FAILED ON CALL NUMB" "ER:\002)"; /* System generated locals */ integer a_dim1, a_offset, i__1, i__2, i__3, i__4, i__5, i__6; doublecomplex z__1; alist al__1; /* Builtin functions */ integer s_wsfe(cilist *), do_fio(integer *, char *, ftnlen), e_wsfe(void), f_rew(alist *); void d_cnjg(doublecomplex *, const doublecomplex *); /* Local variables */ integer i__, j, n; doublecomplex w[1]; integer ia, ja, ic, nc, jj, lj, in, ix, ns, lx, laa, lda; doublereal err; extern logical lze_(doublecomplex *, doublecomplex *, integer *); integer ldas; logical same; doublereal rals; integer incx; logical full; extern /* Subroutine */ int zher_(char *, integer *, doublereal *, doublecomplex *, integer *, doublecomplex *, integer *, ftnlen); logical null; char uplo[1]; extern /* Subroutine */ int zhpr_(char *, integer *, doublereal *, doublecomplex *, integer *, doublecomplex *, ftnlen); doublecomplex alpha; logical isame[13]; extern /* Subroutine */ int zmake_(char *, char *, char *, integer *, integer *, doublecomplex *, integer *, doublecomplex *, integer *, integer *, integer *, logical *, doublecomplex *, ftnlen, ftnlen, ftnlen); integer nargs; logical reset; integer incxs; extern /* Subroutine */ int zmvch_(char *, integer *, integer *, doublecomplex *, doublecomplex *, integer *, doublecomplex *, integer *, doublecomplex *, doublecomplex *, integer *, doublecomplex *, doublereal *, doublecomplex *, doublereal *, doublereal *, logical *, integer *, logical *, ftnlen); logical upper; char uplos[1]; logical packed; doublereal ralpha, errmax; doublecomplex transl; extern logical lzeres_(char *, char *, integer *, integer *, doublecomplex *, doublecomplex *, integer *, ftnlen, ftnlen); /* Fortran I/O blocks */ static cilist io___326 = { 0, 0, 0, fmt_9993, 0 }; static cilist io___327 = { 0, 0, 0, fmt_9994, 0 }; static cilist io___328 = { 0, 0, 0, fmt_9992, 0 }; static cilist io___331 = { 0, 0, 0, fmt_9998, 0 }; static cilist io___338 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___339 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___340 = { 0, 0, 0, fmt_9995, 0 }; static cilist io___341 = { 0, 0, 0, fmt_9996, 0 }; static cilist io___342 = { 0, 0, 0, fmt_9993, 0 }; static cilist io___343 = { 0, 0, 0, fmt_9994, 0 }; /* Tests ZHER and ZHPR. */ /* Auxiliary routine for test program for Level 2 Blas. */ /* -- Written on 10-August-1987. */ /* Richard Hanson, Sandia National Labs. */ /* Jeremy Du Croz, NAG Central Office. */ /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Scalars .. */ /* .. Local Arrays .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. Scalars in Common .. */ /* .. Common blocks .. */ /* .. Data statements .. */ /* Parameter adjustments */ --idim; --alf; --inc; --z__; --g; --yt; --y; --x; --as; --aa; a_dim1 = *nmax; a_offset = 1 + a_dim1; a -= a_offset; --ys; --yy; --xs; --xx; /* Function Body */ /* .. Executable Statements .. */ full = *(unsigned char *)&sname[2] == 'E'; packed = *(unsigned char *)&sname[2] == 'P'; /* Define the number of arguments. */ if (full) { nargs = 7; } else if (packed) { nargs = 6; } nc = 0; reset = TRUE_; errmax = 0.; i__1 = *nidim; for (in = 1; in <= i__1; ++in) { n = idim[in]; /* Set LDA to 1 more than minimum value if room. */ lda = n; if (lda < *nmax) { ++lda; } /* Skip tests if not enough room. */ if (lda > *nmax) { goto L100; } if (packed) { laa = n * (n + 1) / 2; } else { laa = lda * n; } for (ic = 1; ic <= 2; ++ic) { *(unsigned char *)uplo = *(unsigned char *)&ich[ic - 1]; upper = *(unsigned char *)uplo == 'U'; i__2 = *ninc; for (ix = 1; ix <= i__2; ++ix) { incx = inc[ix]; lx = abs(incx) * n; /* Generate the vector X. */ transl.r = .5, transl.i = 0.; i__3 = abs(incx); i__4 = n - 1; zmake_("GE", " ", " ", &c__1, &n, &x[1], &c__1, &xx[1], &i__3, &c__0, &i__4, &reset, &transl, (ftnlen)2, (ftnlen)1, (ftnlen)1); if (n > 1) { i__3 = n / 2; x[i__3].r = 0., x[i__3].i = 0.; i__3 = abs(incx) * (n / 2 - 1) + 1; xx[i__3].r = 0., xx[i__3].i = 0.; } i__3 = *nalf; for (ia = 1; ia <= i__3; ++ia) { i__4 = ia; ralpha = alf[i__4].r; z__1.r = ralpha, z__1.i = 0.; alpha.r = z__1.r, alpha.i = z__1.i; null = n <= 0 || ralpha == 0.; /* Generate the matrix A. */ transl.r = 0., transl.i = 0.; i__4 = n - 1; i__5 = n - 1; zmake_(sname + 1, uplo, " ", &n, &n, &a[a_offset], nmax, & aa[1], &lda, &i__4, &i__5, &reset, &transl, ( ftnlen)2, (ftnlen)1, (ftnlen)1); ++nc; /* Save every datum before calling the subroutine. */ *(unsigned char *)uplos = *(unsigned char *)uplo; ns = n; rals = ralpha; i__4 = laa; for (i__ = 1; i__ <= i__4; ++i__) { i__5 = i__; i__6 = i__; as[i__5].r = aa[i__6].r, as[i__5].i = aa[i__6].i; /* L10: */ } ldas = lda; i__4 = lx; for (i__ = 1; i__ <= i__4; ++i__) { i__5 = i__; i__6 = i__; xs[i__5].r = xx[i__6].r, xs[i__5].i = xx[i__6].i; /* L20: */ } incxs = incx; /* Call the subroutine. */ if (full) { if (*trace) { io___326.ciunit = *ntra; s_wsfe(&io___326); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer) ); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)) ; do_fio(&c__1, (char *)&ralpha, (ftnlen)sizeof( doublereal)); do_fio(&c__1, (char *)&incx, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&lda, (ftnlen)sizeof( integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } zher_(uplo, &n, &ralpha, &xx[1], &incx, &aa[1], &lda, (ftnlen)1); } else if (packed) { if (*trace) { io___327.ciunit = *ntra; s_wsfe(&io___327); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer) ); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)) ; do_fio(&c__1, (char *)&ralpha, (ftnlen)sizeof( doublereal)); do_fio(&c__1, (char *)&incx, (ftnlen)sizeof( integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } zhpr_(uplo, &n, &ralpha, &xx[1], &incx, &aa[1], ( ftnlen)1); } /* Check if error-exit was taken incorrectly. */ if (! infoc_1.ok) { io___328.ciunit = *nout; s_wsfe(&io___328); e_wsfe(); *fatal = TRUE_; goto L120; } /* See what data changed inside subroutines. */ isame[0] = *(unsigned char *)uplo == *(unsigned char *) uplos; isame[1] = ns == n; isame[2] = rals == ralpha; isame[3] = lze_(&xs[1], &xx[1], &lx); isame[4] = incxs == incx; if (null) { isame[5] = lze_(&as[1], &aa[1], &laa); } else { isame[5] = lzeres_(sname + 1, uplo, &n, &n, &as[1], & aa[1], &lda, (ftnlen)2, (ftnlen)1); } if (! packed) { isame[6] = ldas == lda; } /* If data was incorrectly changed, report and return. */ same = TRUE_; i__4 = nargs; for (i__ = 1; i__ <= i__4; ++i__) { same = same && isame[i__ - 1]; if (! isame[i__ - 1]) { io___331.ciunit = *nout; s_wsfe(&io___331); do_fio(&c__1, (char *)&i__, (ftnlen)sizeof( integer)); e_wsfe(); } /* L30: */ } if (! same) { *fatal = TRUE_; goto L120; } if (! null) { /* Check the result column by column. */ if (incx > 0) { i__4 = n; for (i__ = 1; i__ <= i__4; ++i__) { i__5 = i__; i__6 = i__; z__[i__5].r = x[i__6].r, z__[i__5].i = x[i__6] .i; /* L40: */ } } else { i__4 = n; for (i__ = 1; i__ <= i__4; ++i__) { i__5 = i__; i__6 = n - i__ + 1; z__[i__5].r = x[i__6].r, z__[i__5].i = x[i__6] .i; /* L50: */ } } ja = 1; i__4 = n; for (j = 1; j <= i__4; ++j) { d_cnjg(&z__1, &z__[j]); w[0].r = z__1.r, w[0].i = z__1.i; if (upper) { jj = 1; lj = j; } else { jj = j; lj = n - j + 1; } zmvch_("N", &lj, &c__1, &alpha, &z__[jj], &lj, w, &c__1, &c_b2, &a[jj + j * a_dim1], &c__1, &yt[1], &g[1], &aa[ja], eps, &err, fatal, nout, &c_true, (ftnlen)1); if (full) { if (upper) { ja += lda; } else { ja = ja + lda + 1; } } else { ja += lj; } errmax = max(errmax,err); /* If got really bad answer, report and return. */ if (*fatal) { goto L110; } /* L60: */ } } else { /* Avoid repeating tests if N.le.0. */ if (n <= 0) { goto L100; } } /* L70: */ } /* L80: */ } /* L90: */ } L100: ; } /* Report result. */ if (errmax < *thresh) { io___338.ciunit = *nout; s_wsfe(&io___338); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); e_wsfe(); } else { io___339.ciunit = *nout; s_wsfe(&io___339); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&errmax, (ftnlen)sizeof(doublereal)); e_wsfe(); } goto L130; L110: io___340.ciunit = *nout; s_wsfe(&io___340); do_fio(&c__1, (char *)&j, (ftnlen)sizeof(integer)); e_wsfe(); L120: io___341.ciunit = *nout; s_wsfe(&io___341); do_fio(&c__1, sname, (ftnlen)6); e_wsfe(); if (full) { io___342.ciunit = *nout; s_wsfe(&io___342); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&ralpha, (ftnlen)sizeof(doublereal)); do_fio(&c__1, (char *)&incx, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&lda, (ftnlen)sizeof(integer)); e_wsfe(); } else if (packed) { io___343.ciunit = *nout; s_wsfe(&io___343); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&ralpha, (ftnlen)sizeof(doublereal)); do_fio(&c__1, (char *)&incx, (ftnlen)sizeof(integer)); e_wsfe(); } L130: return 0; /* End of ZCHK5. */ } /* zchk5_ */ /* Subroutine */ int zchk6_(char *sname, doublereal *eps, doublereal *thresh, integer *nout, integer *ntra, logical *trace, logical *rewi, logical * fatal, integer *nidim, integer *idim, integer *nalf, doublecomplex * alf, integer *ninc, integer *inc, integer *nmax, integer *incmax, doublecomplex *a, doublecomplex *aa, doublecomplex *as, doublecomplex *x, doublecomplex *xx, doublecomplex *xs, doublecomplex *y, doublecomplex *yy, doublecomplex *ys, doublecomplex *yt, doublereal * g, doublecomplex *z__, ftnlen sname_len) { /* Initialized data */ static char ich[2] = "UL"; /* Format strings */ static char fmt_9993[] = "(1x,i6,\002: \002,a6,\002('\002,a1,\002',\002," "i3,\002,(\002,f4.1,\002,\002,f4.1,\002), X,\002,i2,\002, Y,\002," "i2,\002, A,\002,i3,\002) \002,\002 .\002)"; static char fmt_9994[] = "(1x,i6,\002: \002,a6,\002('\002,a1,\002',\002," "i3,\002,(\002,f4.1,\002,\002,f4.1,\002), X,\002,i2,\002, Y,\002," "i2,\002, AP) \002,\002 .\002)"; static char fmt_9992[] = "(\002 ******* FATAL ERROR - ERROR-EXIT TAKEN O" "N VALID CALL *\002,\002******\002)"; static char fmt_9998[] = "(\002 ******* FATAL ERROR - PARAMETER NUMBER" " \002,i2,\002 WAS CH\002,\002ANGED INCORRECTLY *******\002)"; static char fmt_9999[] = "(\002 \002,a6,\002 PASSED THE COMPUTATIONAL TE" "STS (\002,i6,\002 CALL\002,\002S)\002)"; static char fmt_9997[] = "(\002 \002,a6,\002 COMPLETED THE COMPUTATIONAL" " TESTS (\002,i6,\002 C\002,\002ALLS)\002,/\002 ******* BUT WITH " "MAXIMUM TEST RATIO\002,f8.2,\002 - SUSPECT *******\002)"; static char fmt_9995[] = "(\002 THESE ARE THE RESULTS FOR COLUMN" " \002,i3)"; static char fmt_9996[] = "(\002 ******* \002,a6,\002 FAILED ON CALL NUMB" "ER:\002)"; /* System generated locals */ integer a_dim1, a_offset, z_dim1, z_offset, i__1, i__2, i__3, i__4, i__5, i__6, i__7; doublecomplex z__1, z__2, z__3; alist al__1; /* Builtin functions */ integer s_wsfe(cilist *), do_fio(integer *, char *, ftnlen), e_wsfe(void), f_rew(alist *); void d_cnjg(doublecomplex *, const doublecomplex *); /* Local variables */ integer i__, j, n; doublecomplex w[2]; integer ia, ja, ic, nc, jj, lj, in, ix, iy, ns, lx, ly, laa, lda; doublecomplex als; doublereal err; extern logical lze_(doublecomplex *, doublecomplex *, integer *); integer ldas; logical same; integer incx, incy; logical full, null; char uplo[1]; extern /* Subroutine */ int zher2_(char *, integer *, doublecomplex *, doublecomplex *, integer *, doublecomplex *, integer *, doublecomplex *, integer *, ftnlen), zhpr2_(char *, integer *, doublecomplex *, doublecomplex *, integer *, doublecomplex *, integer *, doublecomplex *, ftnlen); doublecomplex alpha; logical isame[13]; extern /* Subroutine */ int zmake_(char *, char *, char *, integer *, integer *, doublecomplex *, integer *, doublecomplex *, integer *, integer *, integer *, logical *, doublecomplex *, ftnlen, ftnlen, ftnlen); integer nargs; logical reset; integer incxs, incys; extern /* Subroutine */ int zmvch_(char *, integer *, integer *, doublecomplex *, doublecomplex *, integer *, doublecomplex *, integer *, doublecomplex *, doublecomplex *, integer *, doublecomplex *, doublereal *, doublecomplex *, doublereal *, doublereal *, logical *, integer *, logical *, ftnlen); logical upper; char uplos[1]; logical packed; doublereal errmax; doublecomplex transl; extern logical lzeres_(char *, char *, integer *, integer *, doublecomplex *, doublecomplex *, integer *, ftnlen, ftnlen); /* Fortran I/O blocks */ static cilist io___375 = { 0, 0, 0, fmt_9993, 0 }; static cilist io___376 = { 0, 0, 0, fmt_9994, 0 }; static cilist io___377 = { 0, 0, 0, fmt_9992, 0 }; static cilist io___380 = { 0, 0, 0, fmt_9998, 0 }; static cilist io___387 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___388 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___389 = { 0, 0, 0, fmt_9995, 0 }; static cilist io___390 = { 0, 0, 0, fmt_9996, 0 }; static cilist io___391 = { 0, 0, 0, fmt_9993, 0 }; static cilist io___392 = { 0, 0, 0, fmt_9994, 0 }; /* Tests ZHER2 and ZHPR2. */ /* Auxiliary routine for test program for Level 2 Blas. */ /* -- Written on 10-August-1987. */ /* Richard Hanson, Sandia National Labs. */ /* Jeremy Du Croz, NAG Central Office. */ /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Scalars .. */ /* .. Local Arrays .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. Scalars in Common .. */ /* .. Common blocks .. */ /* .. Data statements .. */ /* Parameter adjustments */ --idim; --alf; --inc; z_dim1 = *nmax; z_offset = 1 + z_dim1; z__ -= z_offset; --g; --yt; --y; --x; --as; --aa; a_dim1 = *nmax; a_offset = 1 + a_dim1; a -= a_offset; --ys; --yy; --xs; --xx; /* Function Body */ /* .. Executable Statements .. */ full = *(unsigned char *)&sname[2] == 'E'; packed = *(unsigned char *)&sname[2] == 'P'; /* Define the number of arguments. */ if (full) { nargs = 9; } else if (packed) { nargs = 8; } nc = 0; reset = TRUE_; errmax = 0.; i__1 = *nidim; for (in = 1; in <= i__1; ++in) { n = idim[in]; /* Set LDA to 1 more than minimum value if room. */ lda = n; if (lda < *nmax) { ++lda; } /* Skip tests if not enough room. */ if (lda > *nmax) { goto L140; } if (packed) { laa = n * (n + 1) / 2; } else { laa = lda * n; } for (ic = 1; ic <= 2; ++ic) { *(unsigned char *)uplo = *(unsigned char *)&ich[ic - 1]; upper = *(unsigned char *)uplo == 'U'; i__2 = *ninc; for (ix = 1; ix <= i__2; ++ix) { incx = inc[ix]; lx = abs(incx) * n; /* Generate the vector X. */ transl.r = .5, transl.i = 0.; i__3 = abs(incx); i__4 = n - 1; zmake_("GE", " ", " ", &c__1, &n, &x[1], &c__1, &xx[1], &i__3, &c__0, &i__4, &reset, &transl, (ftnlen)2, (ftnlen)1, (ftnlen)1); if (n > 1) { i__3 = n / 2; x[i__3].r = 0., x[i__3].i = 0.; i__3 = abs(incx) * (n / 2 - 1) + 1; xx[i__3].r = 0., xx[i__3].i = 0.; } i__3 = *ninc; for (iy = 1; iy <= i__3; ++iy) { incy = inc[iy]; ly = abs(incy) * n; /* Generate the vector Y. */ transl.r = 0., transl.i = 0.; i__4 = abs(incy); i__5 = n - 1; zmake_("GE", " ", " ", &c__1, &n, &y[1], &c__1, &yy[1], & i__4, &c__0, &i__5, &reset, &transl, (ftnlen)2, ( ftnlen)1, (ftnlen)1); if (n > 1) { i__4 = n / 2; y[i__4].r = 0., y[i__4].i = 0.; i__4 = abs(incy) * (n / 2 - 1) + 1; yy[i__4].r = 0., yy[i__4].i = 0.; } i__4 = *nalf; for (ia = 1; ia <= i__4; ++ia) { i__5 = ia; alpha.r = alf[i__5].r, alpha.i = alf[i__5].i; null = n <= 0 || alpha.r == 0. && alpha.i == 0.; /* Generate the matrix A. */ transl.r = 0., transl.i = 0.; i__5 = n - 1; i__6 = n - 1; zmake_(sname + 1, uplo, " ", &n, &n, &a[a_offset], nmax, &aa[1], &lda, &i__5, &i__6, &reset, & transl, (ftnlen)2, (ftnlen)1, (ftnlen)1); ++nc; /* Save every datum before calling the subroutine. */ *(unsigned char *)uplos = *(unsigned char *)uplo; ns = n; als.r = alpha.r, als.i = alpha.i; i__5 = laa; for (i__ = 1; i__ <= i__5; ++i__) { i__6 = i__; i__7 = i__; as[i__6].r = aa[i__7].r, as[i__6].i = aa[i__7].i; /* L10: */ } ldas = lda; i__5 = lx; for (i__ = 1; i__ <= i__5; ++i__) { i__6 = i__; i__7 = i__; xs[i__6].r = xx[i__7].r, xs[i__6].i = xx[i__7].i; /* L20: */ } incxs = incx; i__5 = ly; for (i__ = 1; i__ <= i__5; ++i__) { i__6 = i__; i__7 = i__; ys[i__6].r = yy[i__7].r, ys[i__6].i = yy[i__7].i; /* L30: */ } incys = incy; /* Call the subroutine. */ if (full) { if (*trace) { io___375.ciunit = *ntra; s_wsfe(&io___375); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof( integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof( integer)); do_fio(&c__2, (char *)&alpha, (ftnlen)sizeof( doublereal)); do_fio(&c__1, (char *)&incx, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&incy, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&lda, (ftnlen)sizeof( integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } zher2_(uplo, &n, &alpha, &xx[1], &incx, &yy[1], & incy, &aa[1], &lda, (ftnlen)1); } else if (packed) { if (*trace) { io___376.ciunit = *ntra; s_wsfe(&io___376); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof( integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof( integer)); do_fio(&c__2, (char *)&alpha, (ftnlen)sizeof( doublereal)); do_fio(&c__1, (char *)&incx, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&incy, (ftnlen)sizeof( integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } zhpr2_(uplo, &n, &alpha, &xx[1], &incx, &yy[1], & incy, &aa[1], (ftnlen)1); } /* Check if error-exit was taken incorrectly. */ if (! infoc_1.ok) { io___377.ciunit = *nout; s_wsfe(&io___377); e_wsfe(); *fatal = TRUE_; goto L160; } /* See what data changed inside subroutines. */ isame[0] = *(unsigned char *)uplo == *(unsigned char * )uplos; isame[1] = ns == n; isame[2] = als.r == alpha.r && als.i == alpha.i; isame[3] = lze_(&xs[1], &xx[1], &lx); isame[4] = incxs == incx; isame[5] = lze_(&ys[1], &yy[1], &ly); isame[6] = incys == incy; if (null) { isame[7] = lze_(&as[1], &aa[1], &laa); } else { isame[7] = lzeres_(sname + 1, uplo, &n, &n, &as[1] , &aa[1], &lda, (ftnlen)2, (ftnlen)1); } if (! packed) { isame[8] = ldas == lda; } /* If data was incorrectly changed, report and return. */ same = TRUE_; i__5 = nargs; for (i__ = 1; i__ <= i__5; ++i__) { same = same && isame[i__ - 1]; if (! isame[i__ - 1]) { io___380.ciunit = *nout; s_wsfe(&io___380); do_fio(&c__1, (char *)&i__, (ftnlen)sizeof( integer)); e_wsfe(); } /* L40: */ } if (! same) { *fatal = TRUE_; goto L160; } if (! null) { /* Check the result column by column. */ if (incx > 0) { i__5 = n; for (i__ = 1; i__ <= i__5; ++i__) { i__6 = i__ + z_dim1; i__7 = i__; z__[i__6].r = x[i__7].r, z__[i__6].i = x[ i__7].i; /* L50: */ } } else { i__5 = n; for (i__ = 1; i__ <= i__5; ++i__) { i__6 = i__ + z_dim1; i__7 = n - i__ + 1; z__[i__6].r = x[i__7].r, z__[i__6].i = x[ i__7].i; /* L60: */ } } if (incy > 0) { i__5 = n; for (i__ = 1; i__ <= i__5; ++i__) { i__6 = i__ + (z_dim1 << 1); i__7 = i__; z__[i__6].r = y[i__7].r, z__[i__6].i = y[ i__7].i; /* L70: */ } } else { i__5 = n; for (i__ = 1; i__ <= i__5; ++i__) { i__6 = i__ + (z_dim1 << 1); i__7 = n - i__ + 1; z__[i__6].r = y[i__7].r, z__[i__6].i = y[ i__7].i; /* L80: */ } } ja = 1; i__5 = n; for (j = 1; j <= i__5; ++j) { d_cnjg(&z__2, &z__[j + (z_dim1 << 1)]); z__1.r = alpha.r * z__2.r - alpha.i * z__2.i, z__1.i = alpha.r * z__2.i + alpha.i * z__2.r; w[0].r = z__1.r, w[0].i = z__1.i; d_cnjg(&z__2, &alpha); d_cnjg(&z__3, &z__[j + z_dim1]); z__1.r = z__2.r * z__3.r - z__2.i * z__3.i, z__1.i = z__2.r * z__3.i + z__2.i * z__3.r; w[1].r = z__1.r, w[1].i = z__1.i; if (upper) { jj = 1; lj = j; } else { jj = j; lj = n - j + 1; } zmvch_("N", &lj, &c__2, &c_b2, &z__[jj + z_dim1], nmax, w, &c__1, &c_b2, &a[jj + j * a_dim1], &c__1, &yt[1], &g[1], & aa[ja], eps, &err, fatal, nout, & c_true, (ftnlen)1); if (full) { if (upper) { ja += lda; } else { ja = ja + lda + 1; } } else { ja += lj; } errmax = max(errmax,err); /* If got really bad answer, report and return. */ if (*fatal) { goto L150; } /* L90: */ } } else { /* Avoid repeating tests with N.le.0. */ if (n <= 0) { goto L140; } } /* L100: */ } /* L110: */ } /* L120: */ } /* L130: */ } L140: ; } /* Report result. */ if (errmax < *thresh) { io___387.ciunit = *nout; s_wsfe(&io___387); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); e_wsfe(); } else { io___388.ciunit = *nout; s_wsfe(&io___388); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&errmax, (ftnlen)sizeof(doublereal)); e_wsfe(); } goto L170; L150: io___389.ciunit = *nout; s_wsfe(&io___389); do_fio(&c__1, (char *)&j, (ftnlen)sizeof(integer)); e_wsfe(); L160: io___390.ciunit = *nout; s_wsfe(&io___390); do_fio(&c__1, sname, (ftnlen)6); e_wsfe(); if (full) { io___391.ciunit = *nout; s_wsfe(&io___391); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)); do_fio(&c__2, (char *)&alpha, (ftnlen)sizeof(doublereal)); do_fio(&c__1, (char *)&incx, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&incy, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&lda, (ftnlen)sizeof(integer)); e_wsfe(); } else if (packed) { io___392.ciunit = *nout; s_wsfe(&io___392); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)); do_fio(&c__2, (char *)&alpha, (ftnlen)sizeof(doublereal)); do_fio(&c__1, (char *)&incx, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&incy, (ftnlen)sizeof(integer)); e_wsfe(); } L170: return 0; /* End of ZCHK6. */ } /* zchk6_ */ /* Subroutine */ int zchke_(integer *isnum, char *srnamt, integer *nout, ftnlen srnamt_len) { /* Format strings */ static char fmt_9999[] = "(\002 \002,a6,\002 PASSED THE TESTS OF ERROR-E" "XITS\002)"; static char fmt_9998[] = "(\002 ******* \002,a6,\002 FAILED THE TESTS OF" " ERROR-EXITS *****\002,\002**\002)"; /* Builtin functions */ integer s_wsfe(cilist *), do_fio(integer *, char *, ftnlen), e_wsfe(void); /* Local variables */ doublecomplex a[1] /* was [1][1] */, x[1], y[1], beta; extern /* Subroutine */ int zher_(char *, integer *, doublereal *, doublecomplex *, integer *, doublecomplex *, integer *, ftnlen), zhpr_(char *, integer *, doublereal *, doublecomplex *, integer *, doublecomplex *, ftnlen), zher2_(char *, integer *, doublecomplex *, doublecomplex *, integer *, doublecomplex *, integer *, doublecomplex *, integer *, ftnlen), zhpr2_(char *, integer *, doublecomplex *, doublecomplex *, integer *, doublecomplex *, integer *, doublecomplex *, ftnlen); doublecomplex alpha; extern /* Subroutine */ int zgerc_(integer *, integer *, doublecomplex *, doublecomplex *, integer *, doublecomplex *, integer *, doublecomplex *, integer *), zgbmv_(char *, integer *, integer *, integer *, integer *, doublecomplex *, doublecomplex *, integer *, doublecomplex *, integer *, doublecomplex *, doublecomplex *, integer *, ftnlen), zhbmv_(char *, integer *, integer *, doublecomplex *, doublecomplex *, integer *, doublecomplex *, integer *, doublecomplex *, doublecomplex *, integer *, ftnlen), zgemv_(char *, integer *, integer *, doublecomplex *, doublecomplex *, integer *, doublecomplex *, integer *, doublecomplex *, doublecomplex *, integer *, ftnlen), zhemv_(char *, integer *, doublecomplex *, doublecomplex *, integer *, doublecomplex *, integer *, doublecomplex *, doublecomplex *, integer *, ftnlen), zgeru_(integer *, integer *, doublecomplex *, doublecomplex *, integer *, doublecomplex *, integer *, doublecomplex *, integer *), ztbmv_(char *, char *, char *, integer *, integer *, doublecomplex *, integer *, doublecomplex *, integer *, ftnlen, ftnlen, ftnlen), zhpmv_(char *, integer *, doublecomplex *, doublecomplex *, doublecomplex *, integer *, doublecomplex *, doublecomplex *, integer *, ftnlen), ztbsv_(char *, char *, char *, integer *, integer *, doublecomplex *, integer *, doublecomplex *, integer *, ftnlen, ftnlen, ftnlen), ztpmv_( char *, char *, char *, integer *, doublecomplex *, doublecomplex *, integer *, ftnlen, ftnlen, ftnlen), ztrmv_(char *, char *, char *, integer *, doublecomplex *, integer *, doublecomplex *, integer *, ftnlen, ftnlen, ftnlen), ztpsv_(char *, char *, char *, integer *, doublecomplex *, doublecomplex *, integer *, ftnlen, ftnlen, ftnlen), ztrsv_(char *, char *, char *, integer *, doublecomplex *, integer *, doublecomplex *, integer *, ftnlen, ftnlen, ftnlen); doublereal ralpha; extern /* Subroutine */ int chkxer_(char *, integer *, integer *, logical *, logical *, ftnlen); /* Fortran I/O blocks */ static cilist io___399 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___400 = { 0, 0, 0, fmt_9998, 0 }; /* Tests the error exits from the Level 2 Blas. */ /* Requires a special version of the error-handling routine XERBLA. */ /* ALPHA, RALPHA, BETA, A, X and Y should not need to be defined. */ /* Auxiliary routine for test program for Level 2 Blas. */ /* -- Written on 10-August-1987. */ /* Richard Hanson, Sandia National Labs. */ /* Jeremy Du Croz, NAG Central Office. */ /* .. Scalar Arguments .. */ /* .. Scalars in Common .. */ /* .. Local Scalars .. */ /* .. Local Arrays .. */ /* .. External Subroutines .. */ /* .. Common blocks .. */ /* .. Executable Statements .. */ /* OK is set to .FALSE. by the special version of XERBLA or by CHKXER */ /* if anything is wrong. */ infoc_1.ok = TRUE_; /* LERR is set to .TRUE. by the special version of XERBLA each time */ /* it is called, and is then tested and re-set by CHKXER. */ infoc_1.lerr = FALSE_; switch (*isnum) { case 1: goto L10; case 2: goto L20; case 3: goto L30; case 4: goto L40; case 5: goto L50; case 6: goto L60; case 7: goto L70; case 8: goto L80; case 9: goto L90; case 10: goto L100; case 11: goto L110; case 12: goto L120; case 13: goto L130; case 14: goto L140; case 15: goto L150; case 16: goto L160; case 17: goto L170; } L10: infoc_1.infot = 1; zgemv_("/", &c__0, &c__0, &alpha, a, &c__1, x, &c__1, &beta, y, &c__1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; zgemv_("N", &c_n1, &c__0, &alpha, a, &c__1, x, &c__1, &beta, y, &c__1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; zgemv_("N", &c__0, &c_n1, &alpha, a, &c__1, x, &c__1, &beta, y, &c__1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; zgemv_("N", &c__2, &c__0, &alpha, a, &c__1, x, &c__1, &beta, y, &c__1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 8; zgemv_("N", &c__0, &c__0, &alpha, a, &c__1, x, &c__0, &beta, y, &c__1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; zgemv_("N", &c__0, &c__0, &alpha, a, &c__1, x, &c__1, &beta, y, &c__0, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L180; L20: infoc_1.infot = 1; zgbmv_("/", &c__0, &c__0, &c__0, &c__0, &alpha, a, &c__1, x, &c__1, &beta, y, &c__1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; zgbmv_("N", &c_n1, &c__0, &c__0, &c__0, &alpha, a, &c__1, x, &c__1, &beta, y, &c__1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; zgbmv_("N", &c__0, &c_n1, &c__0, &c__0, &alpha, a, &c__1, x, &c__1, &beta, y, &c__1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; zgbmv_("N", &c__0, &c__0, &c_n1, &c__0, &alpha, a, &c__1, x, &c__1, &beta, y, &c__1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; zgbmv_("N", &c__2, &c__0, &c__0, &c_n1, &alpha, a, &c__1, x, &c__1, &beta, y, &c__1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 8; zgbmv_("N", &c__0, &c__0, &c__1, &c__0, &alpha, a, &c__1, x, &c__1, &beta, y, &c__1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 10; zgbmv_("N", &c__0, &c__0, &c__0, &c__0, &alpha, a, &c__1, x, &c__0, &beta, y, &c__1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 13; zgbmv_("N", &c__0, &c__0, &c__0, &c__0, &alpha, a, &c__1, x, &c__1, &beta, y, &c__0, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L180; L30: infoc_1.infot = 1; zhemv_("/", &c__0, &alpha, a, &c__1, x, &c__1, &beta, y, &c__1, (ftnlen)1) ; chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; zhemv_("U", &c_n1, &alpha, a, &c__1, x, &c__1, &beta, y, &c__1, (ftnlen)1) ; chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; zhemv_("U", &c__2, &alpha, a, &c__1, x, &c__1, &beta, y, &c__1, (ftnlen)1) ; chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; zhemv_("U", &c__0, &alpha, a, &c__1, x, &c__0, &beta, y, &c__1, (ftnlen)1) ; chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 10; zhemv_("U", &c__0, &alpha, a, &c__1, x, &c__1, &beta, y, &c__0, (ftnlen)1) ; chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L180; L40: infoc_1.infot = 1; zhbmv_("/", &c__0, &c__0, &alpha, a, &c__1, x, &c__1, &beta, y, &c__1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; zhbmv_("U", &c_n1, &c__0, &alpha, a, &c__1, x, &c__1, &beta, y, &c__1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; zhbmv_("U", &c__0, &c_n1, &alpha, a, &c__1, x, &c__1, &beta, y, &c__1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; zhbmv_("U", &c__0, &c__1, &alpha, a, &c__1, x, &c__1, &beta, y, &c__1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 8; zhbmv_("U", &c__0, &c__0, &alpha, a, &c__1, x, &c__0, &beta, y, &c__1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; zhbmv_("U", &c__0, &c__0, &alpha, a, &c__1, x, &c__1, &beta, y, &c__0, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L180; L50: infoc_1.infot = 1; zhpmv_("/", &c__0, &alpha, a, x, &c__1, &beta, y, &c__1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; zhpmv_("U", &c_n1, &alpha, a, x, &c__1, &beta, y, &c__1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; zhpmv_("U", &c__0, &alpha, a, x, &c__0, &beta, y, &c__1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; zhpmv_("U", &c__0, &alpha, a, x, &c__1, &beta, y, &c__0, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L180; L60: infoc_1.infot = 1; ztrmv_("/", "N", "N", &c__0, a, &c__1, x, &c__1, (ftnlen)1, (ftnlen)1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; ztrmv_("U", "/", "N", &c__0, a, &c__1, x, &c__1, (ftnlen)1, (ftnlen)1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; ztrmv_("U", "N", "/", &c__0, a, &c__1, x, &c__1, (ftnlen)1, (ftnlen)1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; ztrmv_("U", "N", "N", &c_n1, a, &c__1, x, &c__1, (ftnlen)1, (ftnlen)1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; ztrmv_("U", "N", "N", &c__2, a, &c__1, x, &c__1, (ftnlen)1, (ftnlen)1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 8; ztrmv_("U", "N", "N", &c__0, a, &c__1, x, &c__0, (ftnlen)1, (ftnlen)1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L180; L70: infoc_1.infot = 1; ztbmv_("/", "N", "N", &c__0, &c__0, a, &c__1, x, &c__1, (ftnlen)1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; ztbmv_("U", "/", "N", &c__0, &c__0, a, &c__1, x, &c__1, (ftnlen)1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; ztbmv_("U", "N", "/", &c__0, &c__0, a, &c__1, x, &c__1, (ftnlen)1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; ztbmv_("U", "N", "N", &c_n1, &c__0, a, &c__1, x, &c__1, (ftnlen)1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; ztbmv_("U", "N", "N", &c__0, &c_n1, a, &c__1, x, &c__1, (ftnlen)1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; ztbmv_("U", "N", "N", &c__0, &c__1, a, &c__1, x, &c__1, (ftnlen)1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; ztbmv_("U", "N", "N", &c__0, &c__0, a, &c__1, x, &c__0, (ftnlen)1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L180; L80: infoc_1.infot = 1; ztpmv_("/", "N", "N", &c__0, a, x, &c__1, (ftnlen)1, (ftnlen)1, (ftnlen)1) ; chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; ztpmv_("U", "/", "N", &c__0, a, x, &c__1, (ftnlen)1, (ftnlen)1, (ftnlen)1) ; chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; ztpmv_("U", "N", "/", &c__0, a, x, &c__1, (ftnlen)1, (ftnlen)1, (ftnlen)1) ; chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; ztpmv_("U", "N", "N", &c_n1, a, x, &c__1, (ftnlen)1, (ftnlen)1, (ftnlen)1) ; chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; ztpmv_("U", "N", "N", &c__0, a, x, &c__0, (ftnlen)1, (ftnlen)1, (ftnlen)1) ; chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L180; L90: infoc_1.infot = 1; ztrsv_("/", "N", "N", &c__0, a, &c__1, x, &c__1, (ftnlen)1, (ftnlen)1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; ztrsv_("U", "/", "N", &c__0, a, &c__1, x, &c__1, (ftnlen)1, (ftnlen)1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; ztrsv_("U", "N", "/", &c__0, a, &c__1, x, &c__1, (ftnlen)1, (ftnlen)1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; ztrsv_("U", "N", "N", &c_n1, a, &c__1, x, &c__1, (ftnlen)1, (ftnlen)1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; ztrsv_("U", "N", "N", &c__2, a, &c__1, x, &c__1, (ftnlen)1, (ftnlen)1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 8; ztrsv_("U", "N", "N", &c__0, a, &c__1, x, &c__0, (ftnlen)1, (ftnlen)1, ( ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L180; L100: infoc_1.infot = 1; ztbsv_("/", "N", "N", &c__0, &c__0, a, &c__1, x, &c__1, (ftnlen)1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; ztbsv_("U", "/", "N", &c__0, &c__0, a, &c__1, x, &c__1, (ftnlen)1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; ztbsv_("U", "N", "/", &c__0, &c__0, a, &c__1, x, &c__1, (ftnlen)1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; ztbsv_("U", "N", "N", &c_n1, &c__0, a, &c__1, x, &c__1, (ftnlen)1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; ztbsv_("U", "N", "N", &c__0, &c_n1, a, &c__1, x, &c__1, (ftnlen)1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; ztbsv_("U", "N", "N", &c__0, &c__1, a, &c__1, x, &c__1, (ftnlen)1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; ztbsv_("U", "N", "N", &c__0, &c__0, a, &c__1, x, &c__0, (ftnlen)1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L180; L110: infoc_1.infot = 1; ztpsv_("/", "N", "N", &c__0, a, x, &c__1, (ftnlen)1, (ftnlen)1, (ftnlen)1) ; chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; ztpsv_("U", "/", "N", &c__0, a, x, &c__1, (ftnlen)1, (ftnlen)1, (ftnlen)1) ; chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; ztpsv_("U", "N", "/", &c__0, a, x, &c__1, (ftnlen)1, (ftnlen)1, (ftnlen)1) ; chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; ztpsv_("U", "N", "N", &c_n1, a, x, &c__1, (ftnlen)1, (ftnlen)1, (ftnlen)1) ; chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; ztpsv_("U", "N", "N", &c__0, a, x, &c__0, (ftnlen)1, (ftnlen)1, (ftnlen)1) ; chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L180; L120: infoc_1.infot = 1; zgerc_(&c_n1, &c__0, &alpha, x, &c__1, y, &c__1, a, &c__1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; zgerc_(&c__0, &c_n1, &alpha, x, &c__1, y, &c__1, a, &c__1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; zgerc_(&c__0, &c__0, &alpha, x, &c__0, y, &c__1, a, &c__1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; zgerc_(&c__0, &c__0, &alpha, x, &c__1, y, &c__0, a, &c__1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; zgerc_(&c__2, &c__0, &alpha, x, &c__1, y, &c__1, a, &c__1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L180; L130: infoc_1.infot = 1; zgeru_(&c_n1, &c__0, &alpha, x, &c__1, y, &c__1, a, &c__1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; zgeru_(&c__0, &c_n1, &alpha, x, &c__1, y, &c__1, a, &c__1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; zgeru_(&c__0, &c__0, &alpha, x, &c__0, y, &c__1, a, &c__1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; zgeru_(&c__0, &c__0, &alpha, x, &c__1, y, &c__0, a, &c__1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; zgeru_(&c__2, &c__0, &alpha, x, &c__1, y, &c__1, a, &c__1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L180; L140: infoc_1.infot = 1; zher_("/", &c__0, &ralpha, x, &c__1, a, &c__1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; zher_("U", &c_n1, &ralpha, x, &c__1, a, &c__1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; zher_("U", &c__0, &ralpha, x, &c__0, a, &c__1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; zher_("U", &c__2, &ralpha, x, &c__1, a, &c__1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L180; L150: infoc_1.infot = 1; zhpr_("/", &c__0, &ralpha, x, &c__1, a, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; zhpr_("U", &c_n1, &ralpha, x, &c__1, a, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; zhpr_("U", &c__0, &ralpha, x, &c__0, a, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L180; L160: infoc_1.infot = 1; zher2_("/", &c__0, &alpha, x, &c__1, y, &c__1, a, &c__1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; zher2_("U", &c_n1, &alpha, x, &c__1, y, &c__1, a, &c__1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; zher2_("U", &c__0, &alpha, x, &c__0, y, &c__1, a, &c__1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; zher2_("U", &c__0, &alpha, x, &c__1, y, &c__0, a, &c__1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; zher2_("U", &c__2, &alpha, x, &c__1, y, &c__1, a, &c__1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L180; L170: infoc_1.infot = 1; zhpr2_("/", &c__0, &alpha, x, &c__1, y, &c__1, a, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; zhpr2_("U", &c_n1, &alpha, x, &c__1, y, &c__1, a, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; zhpr2_("U", &c__0, &alpha, x, &c__0, y, &c__1, a, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; zhpr2_("U", &c__0, &alpha, x, &c__1, y, &c__0, a, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); L180: if (infoc_1.ok) { io___399.ciunit = *nout; s_wsfe(&io___399); do_fio(&c__1, srnamt, (ftnlen)6); e_wsfe(); } else { io___400.ciunit = *nout; s_wsfe(&io___400); do_fio(&c__1, srnamt, (ftnlen)6); e_wsfe(); } return 0; /* End of ZCHKE. */ } /* zchke_ */ /* Subroutine */ int zmake_(char *type__, char *uplo, char *diag, integer *m, integer *n, doublecomplex *a, integer *nmax, doublecomplex *aa, integer *lda, integer *kl, integer *ku, logical *reset, doublecomplex *transl, ftnlen type_len, ftnlen uplo_len, ftnlen diag_len) { /* System generated locals */ integer a_dim1, a_offset, i__1, i__2, i__3, i__4; doublereal d__1; doublecomplex z__1, z__2; /* Builtin functions */ void d_cnjg(doublecomplex *, const doublecomplex *); integer s_cmp(const char *, const char *, ftnlen, ftnlen); /* Local variables */ integer i__, j, i1, i2, i3, jj, kk; logical gen, tri, sym; integer ibeg, iend, ioff; extern /* Double Complex */ void zbeg_(doublecomplex *, logical *); logical unit, lower, upper; /* Generates values for an M by N matrix A within the bandwidth */ /* defined by KL and KU. */ /* Stores the values in the array AA in the data structure required */ /* by the routine, with unwanted elements set to rogue value. */ /* TYPE is 'GE', 'GB', 'HE', 'HB', 'HP', 'TR', 'TB' OR 'TP'. */ /* Auxiliary routine for test program for Level 2 Blas. */ /* -- Written on 10-August-1987. */ /* Richard Hanson, Sandia National Labs. */ /* Jeremy Du Croz, NAG Central Office. */ /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Scalars .. */ /* .. External Functions .. */ /* .. Intrinsic Functions .. */ /* .. Executable Statements .. */ /* Parameter adjustments */ a_dim1 = *nmax; a_offset = 1 + a_dim1; a -= a_offset; --aa; /* Function Body */ gen = *(unsigned char *)type__ == 'G'; sym = *(unsigned char *)type__ == 'H'; tri = *(unsigned char *)type__ == 'T'; upper = (sym || tri) && *(unsigned char *)uplo == 'U'; lower = (sym || tri) && *(unsigned char *)uplo == 'L'; unit = tri && *(unsigned char *)diag == 'U'; /* Generate data in array A. */ i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = *m; for (i__ = 1; i__ <= i__2; ++i__) { if (gen || upper && i__ <= j || lower && i__ >= j) { if (i__ <= j && j - i__ <= *ku || i__ >= j && i__ - j <= *kl) { i__3 = i__ + j * a_dim1; zbeg_(&z__2, reset); z__1.r = z__2.r + transl->r, z__1.i = z__2.i + transl->i; a[i__3].r = z__1.r, a[i__3].i = z__1.i; } else { i__3 = i__ + j * a_dim1; a[i__3].r = 0., a[i__3].i = 0.; } if (i__ != j) { if (sym) { i__3 = j + i__ * a_dim1; d_cnjg(&z__1, &a[i__ + j * a_dim1]); a[i__3].r = z__1.r, a[i__3].i = z__1.i; } else if (tri) { i__3 = j + i__ * a_dim1; a[i__3].r = 0., a[i__3].i = 0.; } } } /* L10: */ } if (sym) { i__2 = j + j * a_dim1; i__3 = j + j * a_dim1; d__1 = a[i__3].r; z__1.r = d__1, z__1.i = 0.; a[i__2].r = z__1.r, a[i__2].i = z__1.i; } if (tri) { i__2 = j + j * a_dim1; i__3 = j + j * a_dim1; z__1.r = a[i__3].r + 1., z__1.i = a[i__3].i + 0.; a[i__2].r = z__1.r, a[i__2].i = z__1.i; } if (unit) { i__2 = j + j * a_dim1; a[i__2].r = 1., a[i__2].i = 0.; } /* L20: */ } /* Store elements in array AS in data structure required by routine. */ if (s_cmp(type__, "GE", (ftnlen)2, (ftnlen)2) == 0) { i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = *m; for (i__ = 1; i__ <= i__2; ++i__) { i__3 = i__ + (j - 1) * *lda; i__4 = i__ + j * a_dim1; aa[i__3].r = a[i__4].r, aa[i__3].i = a[i__4].i; /* L30: */ } i__2 = *lda; for (i__ = *m + 1; i__ <= i__2; ++i__) { i__3 = i__ + (j - 1) * *lda; aa[i__3].r = -1e10, aa[i__3].i = 1e10; /* L40: */ } /* L50: */ } } else if (s_cmp(type__, "GB", (ftnlen)2, (ftnlen)2) == 0) { i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = *ku + 1 - j; for (i1 = 1; i1 <= i__2; ++i1) { i__3 = i1 + (j - 1) * *lda; aa[i__3].r = -1e10, aa[i__3].i = 1e10; /* L60: */ } /* Computing MIN */ i__3 = *kl + *ku + 1, i__4 = *ku + 1 + *m - j; i__2 = min(i__3,i__4); for (i2 = i1; i2 <= i__2; ++i2) { i__3 = i2 + (j - 1) * *lda; i__4 = i2 + j - *ku - 1 + j * a_dim1; aa[i__3].r = a[i__4].r, aa[i__3].i = a[i__4].i; /* L70: */ } i__2 = *lda; for (i3 = i2; i3 <= i__2; ++i3) { i__3 = i3 + (j - 1) * *lda; aa[i__3].r = -1e10, aa[i__3].i = 1e10; /* L80: */ } /* L90: */ } } else if (s_cmp(type__, "HE", (ftnlen)2, (ftnlen)2) == 0 || s_cmp(type__, "TR", (ftnlen)2, (ftnlen)2) == 0) { i__1 = *n; for (j = 1; j <= i__1; ++j) { if (upper) { ibeg = 1; if (unit) { iend = j - 1; } else { iend = j; } } else { if (unit) { ibeg = j + 1; } else { ibeg = j; } iend = *n; } i__2 = ibeg - 1; for (i__ = 1; i__ <= i__2; ++i__) { i__3 = i__ + (j - 1) * *lda; aa[i__3].r = -1e10, aa[i__3].i = 1e10; /* L100: */ } i__2 = iend; for (i__ = ibeg; i__ <= i__2; ++i__) { i__3 = i__ + (j - 1) * *lda; i__4 = i__ + j * a_dim1; aa[i__3].r = a[i__4].r, aa[i__3].i = a[i__4].i; /* L110: */ } i__2 = *lda; for (i__ = iend + 1; i__ <= i__2; ++i__) { i__3 = i__ + (j - 1) * *lda; aa[i__3].r = -1e10, aa[i__3].i = 1e10; /* L120: */ } if (sym) { jj = j + (j - 1) * *lda; i__2 = jj; i__3 = jj; d__1 = aa[i__3].r; z__1.r = d__1, z__1.i = -1e10; aa[i__2].r = z__1.r, aa[i__2].i = z__1.i; } /* L130: */ } } else if (s_cmp(type__, "HB", (ftnlen)2, (ftnlen)2) == 0 || s_cmp(type__, "TB", (ftnlen)2, (ftnlen)2) == 0) { i__1 = *n; for (j = 1; j <= i__1; ++j) { if (upper) { kk = *kl + 1; /* Computing MAX */ i__2 = 1, i__3 = *kl + 2 - j; ibeg = max(i__2,i__3); if (unit) { iend = *kl; } else { iend = *kl + 1; } } else { kk = 1; if (unit) { ibeg = 2; } else { ibeg = 1; } /* Computing MIN */ i__2 = *kl + 1, i__3 = *m + 1 - j; iend = min(i__2,i__3); } i__2 = ibeg - 1; for (i__ = 1; i__ <= i__2; ++i__) { i__3 = i__ + (j - 1) * *lda; aa[i__3].r = -1e10, aa[i__3].i = 1e10; /* L140: */ } i__2 = iend; for (i__ = ibeg; i__ <= i__2; ++i__) { i__3 = i__ + (j - 1) * *lda; i__4 = i__ + j - kk + j * a_dim1; aa[i__3].r = a[i__4].r, aa[i__3].i = a[i__4].i; /* L150: */ } i__2 = *lda; for (i__ = iend + 1; i__ <= i__2; ++i__) { i__3 = i__ + (j - 1) * *lda; aa[i__3].r = -1e10, aa[i__3].i = 1e10; /* L160: */ } if (sym) { jj = kk + (j - 1) * *lda; i__2 = jj; i__3 = jj; d__1 = aa[i__3].r; z__1.r = d__1, z__1.i = -1e10; aa[i__2].r = z__1.r, aa[i__2].i = z__1.i; } /* L170: */ } } else if (s_cmp(type__, "HP", (ftnlen)2, (ftnlen)2) == 0 || s_cmp(type__, "TP", (ftnlen)2, (ftnlen)2) == 0) { ioff = 0; i__1 = *n; for (j = 1; j <= i__1; ++j) { if (upper) { ibeg = 1; iend = j; } else { ibeg = j; iend = *n; } i__2 = iend; for (i__ = ibeg; i__ <= i__2; ++i__) { ++ioff; i__3 = ioff; i__4 = i__ + j * a_dim1; aa[i__3].r = a[i__4].r, aa[i__3].i = a[i__4].i; if (i__ == j) { if (unit) { i__3 = ioff; aa[i__3].r = -1e10, aa[i__3].i = 1e10; } if (sym) { i__3 = ioff; i__4 = ioff; d__1 = aa[i__4].r; z__1.r = d__1, z__1.i = -1e10; aa[i__3].r = z__1.r, aa[i__3].i = z__1.i; } } /* L180: */ } /* L190: */ } } return 0; /* End of ZMAKE. */ } /* zmake_ */ /* Subroutine */ int zmvch_(char *trans, integer *m, integer *n, doublecomplex *alpha, doublecomplex *a, integer *nmax, doublecomplex * x, integer *incx, doublecomplex *beta, doublecomplex *y, integer * incy, doublecomplex *yt, doublereal *g, doublecomplex *yy, doublereal *eps, doublereal *err, logical *fatal, integer *nout, logical *mv, ftnlen trans_len) { /* Format strings */ static char fmt_9999[] = "(\002 ******* FATAL ERROR - COMPUTED RESULT IS" " LESS THAN HAL\002,\002F ACCURATE *******\002,/\002 " " EXPECTED RE\002,\002SULT COMPUTED R" "ESULT\002)"; static char fmt_9998[] = "(1x,i7,2(\002 (\002,g15.6,\002,\002,g15.6," "\002)\002))"; /* System generated locals */ integer a_dim1, a_offset, i__1, i__2, i__3, i__4, i__5, i__6; doublereal d__1, d__2, d__3, d__4, d__5, d__6; doublecomplex z__1, z__2, z__3; /* Builtin functions */ double d_imag(const doublecomplex *); void d_cnjg(doublecomplex *, const doublecomplex *); double z_abs(const doublecomplex *), sqrt(doublereal); integer s_wsfe(cilist *), e_wsfe(void), do_fio(integer *, char *, ftnlen); /* Local variables */ integer i__, j, ml, nl, iy, jx, kx, ky; doublereal erri; logical tran, ctran; integer incxl, incyl; /* Fortran I/O blocks */ static cilist io___430 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___431 = { 0, 0, 0, fmt_9998, 0 }; static cilist io___432 = { 0, 0, 0, fmt_9998, 0 }; /* Checks the results of the computational tests. */ /* Auxiliary routine for test program for Level 2 Blas. */ /* -- Written on 10-August-1987. */ /* Richard Hanson, Sandia National Labs. */ /* Jeremy Du Croz, NAG Central Office. */ /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Scalars .. */ /* .. Intrinsic Functions .. */ /* .. Statement Functions .. */ /* .. Statement Function definitions .. */ /* .. Executable Statements .. */ /* Parameter adjustments */ a_dim1 = *nmax; a_offset = 1 + a_dim1; a -= a_offset; --x; --y; --yt; --g; --yy; /* Function Body */ tran = *(unsigned char *)trans == 'T'; ctran = *(unsigned char *)trans == 'C'; if (tran || ctran) { ml = *n; nl = *m; } else { ml = *m; nl = *n; } if (*incx < 0) { kx = nl; incxl = -1; } else { kx = 1; incxl = 1; } if (*incy < 0) { ky = ml; incyl = -1; } else { ky = 1; incyl = 1; } /* Compute expected result in YT using data in A, X and Y. */ /* Compute gauges in G. */ iy = ky; i__1 = ml; for (i__ = 1; i__ <= i__1; ++i__) { i__2 = iy; yt[i__2].r = 0., yt[i__2].i = 0.; g[iy] = 0.; jx = kx; if (tran) { i__2 = nl; for (j = 1; j <= i__2; ++j) { i__3 = iy; i__4 = iy; i__5 = j + i__ * a_dim1; i__6 = jx; z__2.r = a[i__5].r * x[i__6].r - a[i__5].i * x[i__6].i, z__2.i = a[i__5].r * x[i__6].i + a[i__5].i * x[i__6] .r; z__1.r = yt[i__4].r + z__2.r, z__1.i = yt[i__4].i + z__2.i; yt[i__3].r = z__1.r, yt[i__3].i = z__1.i; i__3 = j + i__ * a_dim1; i__4 = jx; g[iy] += ((d__1 = a[i__3].r, abs(d__1)) + (d__2 = d_imag(&a[j + i__ * a_dim1]), abs(d__2))) * ((d__3 = x[i__4].r, abs(d__3)) + (d__4 = d_imag(&x[jx]), abs(d__4))); jx += incxl; /* L10: */ } } else if (ctran) { i__2 = nl; for (j = 1; j <= i__2; ++j) { i__3 = iy; i__4 = iy; d_cnjg(&z__3, &a[j + i__ * a_dim1]); i__5 = jx; z__2.r = z__3.r * x[i__5].r - z__3.i * x[i__5].i, z__2.i = z__3.r * x[i__5].i + z__3.i * x[i__5].r; z__1.r = yt[i__4].r + z__2.r, z__1.i = yt[i__4].i + z__2.i; yt[i__3].r = z__1.r, yt[i__3].i = z__1.i; i__3 = j + i__ * a_dim1; i__4 = jx; g[iy] += ((d__1 = a[i__3].r, abs(d__1)) + (d__2 = d_imag(&a[j + i__ * a_dim1]), abs(d__2))) * ((d__3 = x[i__4].r, abs(d__3)) + (d__4 = d_imag(&x[jx]), abs(d__4))); jx += incxl; /* L20: */ } } else { i__2 = nl; for (j = 1; j <= i__2; ++j) { i__3 = iy; i__4 = iy; i__5 = i__ + j * a_dim1; i__6 = jx; z__2.r = a[i__5].r * x[i__6].r - a[i__5].i * x[i__6].i, z__2.i = a[i__5].r * x[i__6].i + a[i__5].i * x[i__6] .r; z__1.r = yt[i__4].r + z__2.r, z__1.i = yt[i__4].i + z__2.i; yt[i__3].r = z__1.r, yt[i__3].i = z__1.i; i__3 = i__ + j * a_dim1; i__4 = jx; g[iy] += ((d__1 = a[i__3].r, abs(d__1)) + (d__2 = d_imag(&a[ i__ + j * a_dim1]), abs(d__2))) * ((d__3 = x[i__4].r, abs(d__3)) + (d__4 = d_imag(&x[jx]), abs(d__4))); jx += incxl; /* L30: */ } } i__2 = iy; i__3 = iy; z__2.r = alpha->r * yt[i__3].r - alpha->i * yt[i__3].i, z__2.i = alpha->r * yt[i__3].i + alpha->i * yt[i__3].r; i__4 = iy; z__3.r = beta->r * y[i__4].r - beta->i * y[i__4].i, z__3.i = beta->r * y[i__4].i + beta->i * y[i__4].r; z__1.r = z__2.r + z__3.r, z__1.i = z__2.i + z__3.i; yt[i__2].r = z__1.r, yt[i__2].i = z__1.i; i__2 = iy; g[iy] = ((d__1 = alpha->r, abs(d__1)) + (d__2 = d_imag(alpha), abs( d__2))) * g[iy] + ((d__3 = beta->r, abs(d__3)) + (d__4 = d_imag(beta), abs(d__4))) * ((d__5 = y[i__2].r, abs(d__5)) + ( d__6 = d_imag(&y[iy]), abs(d__6))); iy += incyl; /* L40: */ } /* Compute the error ratio for this result. */ *err = 0.; i__1 = ml; for (i__ = 1; i__ <= i__1; ++i__) { i__2 = i__; i__3 = (i__ - 1) * abs(*incy) + 1; z__1.r = yt[i__2].r - yy[i__3].r, z__1.i = yt[i__2].i - yy[i__3].i; erri = z_abs(&z__1) / *eps; if (g[i__] != 0.) { erri /= g[i__]; } *err = max(*err,erri); if (*err * sqrt(*eps) >= 1.) { goto L60; } /* L50: */ } /* If the loop completes, all results are at least half accurate. */ goto L80; /* Report fatal error. */ L60: *fatal = TRUE_; io___430.ciunit = *nout; s_wsfe(&io___430); e_wsfe(); i__1 = ml; for (i__ = 1; i__ <= i__1; ++i__) { if (*mv) { io___431.ciunit = *nout; s_wsfe(&io___431); do_fio(&c__1, (char *)&i__, (ftnlen)sizeof(integer)); do_fio(&c__2, (char *)&yt[i__], (ftnlen)sizeof(doublereal)); do_fio(&c__2, (char *)&yy[(i__ - 1) * abs(*incy) + 1], (ftnlen) sizeof(doublereal)); e_wsfe(); } else { io___432.ciunit = *nout; s_wsfe(&io___432); do_fio(&c__1, (char *)&i__, (ftnlen)sizeof(integer)); do_fio(&c__2, (char *)&yy[(i__ - 1) * abs(*incy) + 1], (ftnlen) sizeof(doublereal)); do_fio(&c__2, (char *)&yt[i__], (ftnlen)sizeof(doublereal)); e_wsfe(); } /* L70: */ } L80: return 0; /* End of ZMVCH. */ } /* zmvch_ */ logical lze_(doublecomplex *ri, doublecomplex *rj, integer *lr) { /* System generated locals */ integer i__1, i__2, i__3; logical ret_val; /* Local variables */ integer i__; /* Tests if two arrays are identical. */ /* Auxiliary routine for test program for Level 2 Blas. */ /* -- Written on 10-August-1987. */ /* Richard Hanson, Sandia National Labs. */ /* Jeremy Du Croz, NAG Central Office. */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Scalars .. */ /* .. Executable Statements .. */ /* Parameter adjustments */ --rj; --ri; /* Function Body */ i__1 = *lr; for (i__ = 1; i__ <= i__1; ++i__) { i__2 = i__; i__3 = i__; if (ri[i__2].r != rj[i__3].r || ri[i__2].i != rj[i__3].i) { goto L20; } /* L10: */ } ret_val = TRUE_; goto L30; L20: ret_val = FALSE_; L30: return ret_val; /* End of LZE. */ } /* lze_ */ logical lzeres_(char *type__, char *uplo, integer *m, integer *n, doublecomplex *aa, doublecomplex *as, integer *lda, ftnlen type_len, ftnlen uplo_len) { /* System generated locals */ integer aa_dim1, aa_offset, as_dim1, as_offset, i__1, i__2, i__3, i__4; logical ret_val; /* Builtin functions */ integer s_cmp(const char *, const char *, ftnlen, ftnlen); /* Local variables */ integer i__, j, ibeg, iend; logical upper; /* Tests if selected elements in two arrays are equal. */ /* TYPE is 'GE', 'HE' or 'HP'. */ /* Auxiliary routine for test program for Level 2 Blas. */ /* -- Written on 10-August-1987. */ /* Richard Hanson, Sandia National Labs. */ /* Jeremy Du Croz, NAG Central Office. */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Scalars .. */ /* .. Executable Statements .. */ /* Parameter adjustments */ as_dim1 = *lda; as_offset = 1 + as_dim1; as -= as_offset; aa_dim1 = *lda; aa_offset = 1 + aa_dim1; aa -= aa_offset; /* Function Body */ upper = *(unsigned char *)uplo == 'U'; if (s_cmp(type__, "GE", (ftnlen)2, (ftnlen)2) == 0) { i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = *lda; for (i__ = *m + 1; i__ <= i__2; ++i__) { i__3 = i__ + j * aa_dim1; i__4 = i__ + j * as_dim1; if (aa[i__3].r != as[i__4].r || aa[i__3].i != as[i__4].i) { goto L70; } /* L10: */ } /* L20: */ } } else if (s_cmp(type__, "HE", (ftnlen)2, (ftnlen)2) == 0) { i__1 = *n; for (j = 1; j <= i__1; ++j) { if (upper) { ibeg = 1; iend = j; } else { ibeg = j; iend = *n; } i__2 = ibeg - 1; for (i__ = 1; i__ <= i__2; ++i__) { i__3 = i__ + j * aa_dim1; i__4 = i__ + j * as_dim1; if (aa[i__3].r != as[i__4].r || aa[i__3].i != as[i__4].i) { goto L70; } /* L30: */ } i__2 = *lda; for (i__ = iend + 1; i__ <= i__2; ++i__) { i__3 = i__ + j * aa_dim1; i__4 = i__ + j * as_dim1; if (aa[i__3].r != as[i__4].r || aa[i__3].i != as[i__4].i) { goto L70; } /* L40: */ } /* L50: */ } } ret_val = TRUE_; goto L80; L70: ret_val = FALSE_; L80: return ret_val; /* End of LZERES. */ } /* lzeres_ */ /* Double Complex */ void zbeg_(doublecomplex * ret_val, logical *reset) { /* System generated locals */ doublereal d__1, d__2; doublecomplex z__1; /* Local variables */ static integer i__, j, ic, mi, mj; /* Generates complex numbers as pairs of random numbers uniformly */ /* distributed between -0.5 and 0.5. */ /* Auxiliary routine for test program for Level 2 Blas. */ /* -- Written on 10-August-1987. */ /* Richard Hanson, Sandia National Labs. */ /* Jeremy Du Croz, NAG Central Office. */ /* .. Scalar Arguments .. */ /* .. Local Scalars .. */ /* .. Save statement .. */ /* .. Intrinsic Functions .. */ /* .. Executable Statements .. */ if (*reset) { /* Initialize local variables. */ mi = 891; mj = 457; i__ = 7; j = 7; ic = 0; *reset = FALSE_; } /* The sequence of values of I or J is bounded between 1 and 999. */ /* If initial I or J = 1,2,3,6,7 or 9, the period will be 50. */ /* If initial I or J = 4 or 8, the period will be 25. */ /* If initial I or J = 5, the period will be 10. */ /* IC is used to break up the period by skipping 1 value of I or J */ /* in 6. */ ++ic; L10: i__ *= mi; j *= mj; i__ -= i__ / 1000 * 1000; j -= j / 1000 * 1000; if (ic >= 5) { ic = 0; goto L10; } d__1 = (i__ - 500) / 1001.; d__2 = (j - 500) / 1001.; z__1.r = d__1, z__1.i = d__2; ret_val->r = z__1.r, ret_val->i = z__1.i; return ; /* End of ZBEG. */ } /* zbeg_ */ doublereal ddiff_(doublereal *x, doublereal *y) { /* System generated locals */ doublereal ret_val; /* Auxiliary routine for test program for Level 2 Blas. */ /* -- Written on 10-August-1987. */ /* Richard Hanson, Sandia National Labs. */ /* .. Scalar Arguments .. */ /* .. Executable Statements .. */ ret_val = *x - *y; return ret_val; /* End of DDIFF. */ } /* ddiff_ */ /* Subroutine */ int chkxer_(char *srnamt, integer *infot, integer *nout, logical *lerr, logical *ok, ftnlen srnamt_len) { /* Format strings */ static char fmt_9999[] = "(\002 ***** ILLEGAL VALUE OF PARAMETER NUMBER" " \002,i2,\002 NOT D\002,\002ETECTED BY \002,a6,\002 *****\002)"; /* Builtin functions */ integer s_wsfe(cilist *), do_fio(integer *, char *, ftnlen), e_wsfe(void); /* Fortran I/O blocks */ static cilist io___444 = { 0, 0, 0, fmt_9999, 0 }; /* Tests whether XERBLA has detected an error when it should. */ /* Auxiliary routine for test program for Level 2 Blas. */ /* -- Written on 10-August-1987. */ /* Richard Hanson, Sandia National Labs. */ /* Jeremy Du Croz, NAG Central Office. */ /* .. Scalar Arguments .. */ /* .. Executable Statements .. */ if (! (*lerr)) { io___444.ciunit = *nout; s_wsfe(&io___444); do_fio(&c__1, (char *)&(*infot), (ftnlen)sizeof(integer)); do_fio(&c__1, srnamt, (ftnlen)6); e_wsfe(); *ok = FALSE_; } *lerr = FALSE_; return 0; /* End of CHKXER. */ } /* chkxer_ */ /* Subroutine */ int xerbla_(char *srname, integer *info, ftnlen srname_len) { /* Format strings */ static char fmt_9999[] = "(\002 ******* XERBLA WAS CALLED WITH INFO =" " \002,i6,\002 INSTEAD\002,\002 OF \002,i2,\002 *******\002)"; static char fmt_9997[] = "(\002 ******* XERBLA WAS CALLED WITH INFO =" " \002,i6,\002 *******\002)"; static char fmt_9998[] = "(\002 ******* XERBLA WAS CALLED WITH SRNAME =" " \002,a6,\002 INSTE\002,\002AD OF \002,a6,\002 *******\002)"; /* Builtin functions */ integer s_wsfe(cilist *), do_fio(integer *, char *, ftnlen), e_wsfe(void), s_cmp(const char *, const char *, ftnlen, ftnlen); /* Fortran I/O blocks */ static cilist io___445 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___446 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___447 = { 0, 0, 0, fmt_9998, 0 }; /* This is a special version of XERBLA to be used only as part of */ /* the test program for testing error exits from the Level 2 BLAS */ /* routines. */ /* XERBLA is an error handler for the Level 2 BLAS routines. */ /* It is called by the Level 2 BLAS routines if an input parameter is */ /* invalid. */ /* Auxiliary routine for test program for Level 2 Blas. */ /* -- Written on 10-August-1987. */ /* Richard Hanson, Sandia National Labs. */ /* Jeremy Du Croz, NAG Central Office. */ /* .. Scalar Arguments .. */ /* .. Scalars in Common .. */ /* .. Common blocks .. */ /* .. Executable Statements .. */ infoc_2.lerr = TRUE_; if (*info != infoc_2.infot) { if (infoc_2.infot != 0) { io___445.ciunit = infoc_2.nout; s_wsfe(&io___445); do_fio(&c__1, (char *)&(*info), (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&infoc_2.infot, (ftnlen)sizeof(integer)); e_wsfe(); } else { io___446.ciunit = infoc_2.nout; s_wsfe(&io___446); do_fio(&c__1, (char *)&(*info), (ftnlen)sizeof(integer)); e_wsfe(); } infoc_2.ok = FALSE_; } if (s_cmp(srname, srnamc_1.srnamt, (ftnlen)6, (ftnlen)6) != 0) { io___447.ciunit = infoc_2.nout; s_wsfe(&io___447); do_fio(&c__1, srname, (ftnlen)6); do_fio(&c__1, srnamc_1.srnamt, (ftnlen)6); e_wsfe(); infoc_2.ok = FALSE_; } return 0; /* End of XERBLA */ } /* xerbla_ */ /* Main program alias */ int zblat2_ () { main (); return 0; } blis-0.9.0/blastest/src/zblat3.c000066400000000000000000006015111422157504600164360ustar00rootroot00000000000000/* zblat3.f -- translated by f2c (version 20100827). You must link the resulting object file with libf2c: on Microsoft Windows system, link with libf2c.lib; on Linux or Unix systems, link with .../path/to/libf2c.a -lm or, if you install libf2c.a in a standard place, with -lf2c -lm -- in that order, at the end of the command line, as in cc *.o -lf2c -lm Source for libf2c is in /netlib/f2c/libf2c.zip, e.g., http://www.netlib.org/f2c/libf2c.zip */ #include "f2c.h" /* Common Block Declarations */ union { struct { integer infot, noutc; logical ok, lerr; } _1; struct { integer infot, nout; logical ok, lerr; } _2; } infoc_; #define infoc_1 (infoc_._1) #define infoc_2 (infoc_._2) struct { char srnamt[6]; } srnamc_; #define srnamc_1 srnamc_ /* Table of constant values */ static doublecomplex c_b1 = {0.,0.}; static doublecomplex c_b2 = {1.,0.}; static integer c__9 = 9; static integer c__1 = 1; static integer c__3 = 3; static integer c__8 = 8; static integer c__5 = 5; static integer c__65 = 65; static integer c__7 = 7; static integer c__2 = 2; static doublereal c_b88 = 0.; static logical c_true = TRUE_; static logical c_false = FALSE_; static integer c__0 = 0; static integer c_n1 = -1; /* > \brief \b ZBLAT3 */ /* =========== DOCUMENTATION =========== */ /* Online html documentation available at */ /* http://www.netlib.org/lapack/explore-html/ */ /* Definition: */ /* =========== */ /* PROGRAM ZBLAT3 */ /* > \par Purpose: */ /* ============= */ /* > */ /* > \verbatim */ /* > */ /* > Test program for the COMPLEX*16 Level 3 Blas. */ /* > */ /* > The program must be driven by a short data file. The first 14 records */ /* > of the file are read using list-directed input, the last 9 records */ /* > are read using the format ( A6, L2 ). An annotated example of a data */ /* > file can be obtained by deleting the first 3 characters from the */ /* > following 23 lines: */ /* > 'zblat3.out' NAME OF SUMMARY OUTPUT FILE */ /* > 6 UNIT NUMBER OF SUMMARY FILE */ /* > 'ZBLAT3.SNAP' NAME OF SNAPSHOT OUTPUT FILE */ /* > -1 UNIT NUMBER OF SNAPSHOT FILE (NOT USED IF .LT. 0) */ /* > F LOGICAL FLAG, T TO REWIND SNAPSHOT FILE AFTER EACH RECORD. */ /* > F LOGICAL FLAG, T TO STOP ON FAILURES. */ /* > T LOGICAL FLAG, T TO TEST ERROR EXITS. */ /* > 16.0 THRESHOLD VALUE OF TEST RATIO */ /* > 6 NUMBER OF VALUES OF N */ /* > 0 1 2 3 5 9 VALUES OF N */ /* > 3 NUMBER OF VALUES OF ALPHA */ /* > (0.0,0.0) (1.0,0.0) (0.7,-0.9) VALUES OF ALPHA */ /* > 3 NUMBER OF VALUES OF BETA */ /* > (0.0,0.0) (1.0,0.0) (1.3,-1.1) VALUES OF BETA */ /* > ZGEMM T PUT F FOR NO TEST. SAME COLUMNS. */ /* > ZHEMM T PUT F FOR NO TEST. SAME COLUMNS. */ /* > ZSYMM T PUT F FOR NO TEST. SAME COLUMNS. */ /* > ZTRMM T PUT F FOR NO TEST. SAME COLUMNS. */ /* > ZTRSM T PUT F FOR NO TEST. SAME COLUMNS. */ /* > ZHERK T PUT F FOR NO TEST. SAME COLUMNS. */ /* > ZSYRK T PUT F FOR NO TEST. SAME COLUMNS. */ /* > ZHER2K T PUT F FOR NO TEST. SAME COLUMNS. */ /* > ZSYR2K T PUT F FOR NO TEST. SAME COLUMNS. */ /* > */ /* > */ /* > Further Details */ /* > =============== */ /* > */ /* > See: */ /* > */ /* > Dongarra J. J., Du Croz J. J., Duff I. S. and Hammarling S. */ /* > A Set of Level 3 Basic Linear Algebra Subprograms. */ /* > */ /* > Technical Memorandum No.88 (Revision 1), Mathematics and */ /* > Computer Science Division, Argonne National Laboratory, 9700 */ /* > South Cass Avenue, Argonne, Illinois 60439, US. */ /* > */ /* > -- Written on 8-February-1989. */ /* > Jack Dongarra, Argonne National Laboratory. */ /* > Iain Duff, AERE Harwell. */ /* > Jeremy Du Croz, Numerical Algorithms Group Ltd. */ /* > Sven Hammarling, Numerical Algorithms Group Ltd. */ /* > */ /* > 10-9-00: Change STATUS='NEW' to 'UNKNOWN' so that the testers */ /* > can be run multiple times without deleting generated */ /* > output files (susan) */ /* > \endverbatim */ /* Authors: */ /* ======== */ /* > \author Univ. of Tennessee */ /* > \author Univ. of California Berkeley */ /* > \author Univ. of Colorado Denver */ /* > \author NAG Ltd. */ /* > \date April 2012 */ /* > \ingroup complex16_blas_testing */ /* ===================================================================== */ /* Main program */ int main(void) { /* Initialized data */ static char snames[6*9] = "ZGEMM " "ZHEMM " "ZSYMM " "ZTRMM " "ZTRSM " "ZHERK " "ZSYRK " "ZHER2K" "ZSYR2K"; /* Format strings */ static char fmt_9997[] = "(\002 NUMBER OF VALUES OF \002,a,\002 IS LESS " "THAN 1 OR GREATER \002,\002THAN \002,i2)"; static char fmt_9996[] = "(\002 VALUE OF N IS LESS THAN 0 OR GREATER THA" "N \002,i2)"; static char fmt_9995[] = "(\002 TESTS OF THE COMPLEX*16 LEVEL 3 BL" "AS\002,//\002 THE F\002,\002OLLOWING PARAMETER VALUES WILL BE US" "ED:\002)"; static char fmt_9994[] = "(\002 FOR N \002,9i6)"; static char fmt_9993[] = "(\002 FOR ALPHA \002,7(\002(\002,f4" ".1,\002,\002,f4.1,\002) \002,:))"; static char fmt_9992[] = "(\002 FOR BETA \002,7(\002(\002,f4" ".1,\002,\002,f4.1,\002) \002,:))"; static char fmt_9984[] = "(\002 ERROR-EXITS WILL NOT BE TESTED\002)"; static char fmt_9999[] = "(\002 ROUTINES PASS COMPUTATIONAL TESTS IF TES" "T RATIO IS LES\002,\002S THAN\002,f8.2)"; static char fmt_9988[] = "(a6,l2)"; static char fmt_9990[] = "(\002 SUBPROGRAM NAME \002,a6,\002 NOT RECOGNI" "ZED\002,/\002 ******* T\002,\002ESTS ABANDONED *******\002)"; static char fmt_9998[] = "(\002 RELATIVE MACHINE PRECISION IS TAKEN TO" " BE\002,1p,d9.1)"; static char fmt_9989[] = "(\002 ERROR IN ZMMCH - IN-LINE DOT PRODUCTS A" "RE BEING EVALU\002,\002ATED WRONGLY.\002,/\002 ZMMCH WAS CALLED " "WITH TRANSA = \002,a1,\002 AND TRANSB = \002,a1,/\002 AND RETURN" "ED SAME = \002,l1,\002 AND \002,\002ERR = \002,f12.3,\002.\002," "/\002 THIS MAY BE DUE TO FAULTS IN THE \002,\002ARITHMETIC OR TH" "E COMPILER.\002,/\002 ******* TESTS ABANDONED \002,\002******" "*\002)"; static char fmt_9987[] = "(1x,a6,\002 WAS NOT TESTED\002)"; static char fmt_9986[] = "(/\002 END OF TESTS\002)"; static char fmt_9985[] = "(/\002 ******* FATAL ERROR - TESTS ABANDONED *" "******\002)"; static char fmt_9991[] = "(\002 AMEND DATA FILE OR INCREASE ARRAY SIZES " "IN PROGRAM\002,/\002 ******* TESTS ABANDONED *******\002)"; /* System generated locals */ integer i__1, i__2, i__3, i__4, i__5; olist o__1; cllist cl__1; /* Builtin functions */ integer s_rsle(cilist *), do_lio(integer *, integer *, char *, ftnlen), e_rsle(void), f_open(olist *), s_wsfe(cilist *), do_fio(integer *, char *, ftnlen), e_wsfe(void), s_wsle(cilist *), e_wsle(void), s_rsfe(cilist *), e_rsfe(void), s_cmp(const char *, const char *, ftnlen, ftnlen); /* Subroutine */ int s_stop(char *, ftnlen); integer f_clos(cllist *); /* Subroutine */ int s_copy(char *, const char *, ftnlen, ftnlen); /* Local variables */ doublecomplex c__[4225] /* was [65][65] */; doublereal g[65]; integer i__, j, n; doublecomplex w[130], aa[4225], ab[8450] /* was [65][130] */, bb[4225], cc[4225], as[4225], bs[4225], cs[4225], ct[65], alf[7], bet[7]; doublereal eps, err; extern logical lze_(doublecomplex *, doublecomplex *, integer *); integer nalf, idim[9]; logical same; integer nbet, ntra; logical rewi; integer nout; extern /* Subroutine */ int zchk1_(char *, doublereal *, doublereal *, integer *, integer *, logical *, logical *, logical *, integer *, integer *, integer *, doublecomplex *, integer *, doublecomplex *, integer *, doublecomplex *, doublecomplex *, doublecomplex *, doublecomplex *, doublecomplex *, doublecomplex *, doublecomplex * , doublecomplex *, doublecomplex *, doublecomplex *, doublereal *, ftnlen), zchk2_(char *, doublereal *, doublereal *, integer *, integer *, logical *, logical *, logical *, integer *, integer *, integer *, doublecomplex *, integer *, doublecomplex *, integer *, doublecomplex *, doublecomplex *, doublecomplex *, doublecomplex *, doublecomplex *, doublecomplex *, doublecomplex *, doublecomplex *, doublecomplex *, doublecomplex *, doublereal *, ftnlen), zchk3_(char *, doublereal *, doublereal *, integer *, integer *, logical *, logical *, logical *, integer *, integer *, integer *, doublecomplex *, integer *, doublecomplex *, doublecomplex *, doublecomplex *, doublecomplex *, doublecomplex * , doublecomplex *, doublecomplex *, doublereal *, doublecomplex *, ftnlen), zchk4_(char *, doublereal *, doublereal *, integer *, integer *, logical *, logical *, logical *, integer *, integer *, integer *, doublecomplex *, integer *, doublecomplex *, integer *, doublecomplex *, doublecomplex *, doublecomplex *, doublecomplex *, doublecomplex *, doublecomplex *, doublecomplex *, doublecomplex *, doublecomplex *, doublecomplex *, doublereal *, ftnlen), zchk5_(char *, doublereal *, doublereal *, integer *, integer *, logical *, logical *, logical *, integer *, integer *, integer *, doublecomplex *, integer *, doublecomplex *, integer *, doublecomplex *, doublecomplex *, doublecomplex *, doublecomplex *, doublecomplex *, doublecomplex *, doublecomplex *, doublecomplex *, doublecomplex *, doublereal *, doublecomplex *, ftnlen); logical fatal, trace; integer nidim; extern /* Subroutine */ int zchke_(integer *, char *, integer *, ftnlen), zmmch_(char *, char *, integer *, integer *, integer *, doublecomplex *, doublecomplex *, integer *, doublecomplex *, integer *, doublecomplex *, doublecomplex *, integer *, doublecomplex *, doublereal *, doublecomplex *, integer *, doublereal *, doublereal *, logical *, integer *, logical *, ftnlen, ftnlen); char snaps[32]; integer isnum; logical ltest[9], sfatal; char snamet[6], transa[1], transb[1]; doublereal thresh; logical ltestt, tsterr; char summry[32]; extern double d_epsilon_(doublereal *); /* Fortran I/O blocks */ static cilist io___2 = { 0, 5, 0, 0, 0 }; static cilist io___4 = { 0, 5, 0, 0, 0 }; static cilist io___6 = { 0, 5, 0, 0, 0 }; static cilist io___8 = { 0, 5, 0, 0, 0 }; static cilist io___11 = { 0, 5, 0, 0, 0 }; static cilist io___13 = { 0, 5, 0, 0, 0 }; static cilist io___15 = { 0, 5, 0, 0, 0 }; static cilist io___17 = { 0, 5, 0, 0, 0 }; static cilist io___19 = { 0, 5, 0, 0, 0 }; static cilist io___21 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___22 = { 0, 5, 0, 0, 0 }; static cilist io___25 = { 0, 0, 0, fmt_9996, 0 }; static cilist io___26 = { 0, 5, 0, 0, 0 }; static cilist io___28 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___29 = { 0, 5, 0, 0, 0 }; static cilist io___31 = { 0, 5, 0, 0, 0 }; static cilist io___33 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___34 = { 0, 5, 0, 0, 0 }; static cilist io___36 = { 0, 0, 0, fmt_9995, 0 }; static cilist io___37 = { 0, 0, 0, fmt_9994, 0 }; static cilist io___38 = { 0, 0, 0, fmt_9993, 0 }; static cilist io___39 = { 0, 0, 0, fmt_9992, 0 }; static cilist io___40 = { 0, 0, 0, 0, 0 }; static cilist io___41 = { 0, 0, 0, fmt_9984, 0 }; static cilist io___42 = { 0, 0, 0, 0, 0 }; static cilist io___43 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___44 = { 0, 0, 0, 0, 0 }; static cilist io___46 = { 0, 5, 1, fmt_9988, 0 }; static cilist io___49 = { 0, 0, 0, fmt_9990, 0 }; static cilist io___51 = { 0, 0, 0, fmt_9998, 0 }; static cilist io___64 = { 0, 0, 0, fmt_9989, 0 }; static cilist io___65 = { 0, 0, 0, fmt_9989, 0 }; static cilist io___66 = { 0, 0, 0, fmt_9989, 0 }; static cilist io___67 = { 0, 0, 0, fmt_9989, 0 }; static cilist io___69 = { 0, 0, 0, 0, 0 }; static cilist io___70 = { 0, 0, 0, fmt_9987, 0 }; static cilist io___71 = { 0, 0, 0, 0, 0 }; static cilist io___78 = { 0, 0, 0, fmt_9986, 0 }; static cilist io___79 = { 0, 0, 0, fmt_9985, 0 }; static cilist io___80 = { 0, 0, 0, fmt_9991, 0 }; /* -- Reference BLAS test routine (version 3.4.1) -- */ /* -- Reference BLAS is a software package provided by Univ. of Tennessee, -- */ /* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- */ /* April 2012 */ /* ===================================================================== */ /* .. Parameters .. */ /* .. Local Scalars .. */ /* .. Local Arrays .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. Scalars in Common .. */ /* .. Common blocks .. */ /* .. Data statements .. */ /* .. Executable Statements .. */ /* Read name and unit number for summary output file and open file. */ s_rsle(&io___2); do_lio(&c__9, &c__1, summry, (ftnlen)32); e_rsle(); s_rsle(&io___4); do_lio(&c__3, &c__1, (char *)&nout, (ftnlen)sizeof(integer)); e_rsle(); o__1.oerr = 0; o__1.ounit = nout; o__1.ofnmlen = 32; o__1.ofnm = summry; o__1.orl = 0; o__1.osta = "UNKNOWN"; o__1.oacc = 0; o__1.ofm = 0; o__1.oblnk = 0; f_open(&o__1); infoc_1.noutc = nout; /* Read name and unit number for snapshot output file and open file. */ s_rsle(&io___6); do_lio(&c__9, &c__1, snaps, (ftnlen)32); e_rsle(); s_rsle(&io___8); do_lio(&c__3, &c__1, (char *)&ntra, (ftnlen)sizeof(integer)); e_rsle(); trace = ntra >= 0; if (trace) { o__1.oerr = 0; o__1.ounit = ntra; o__1.ofnmlen = 32; o__1.ofnm = snaps; o__1.orl = 0; o__1.osta = "UNKNOWN"; o__1.oacc = 0; o__1.ofm = 0; o__1.oblnk = 0; f_open(&o__1); } /* Read the flag that directs rewinding of the snapshot file. */ s_rsle(&io___11); do_lio(&c__8, &c__1, (char *)&rewi, (ftnlen)sizeof(logical)); e_rsle(); rewi = rewi && trace; /* Read the flag that directs stopping on any failure. */ s_rsle(&io___13); do_lio(&c__8, &c__1, (char *)&sfatal, (ftnlen)sizeof(logical)); e_rsle(); /* Read the flag that indicates whether error exits are to be tested. */ s_rsle(&io___15); do_lio(&c__8, &c__1, (char *)&tsterr, (ftnlen)sizeof(logical)); e_rsle(); /* Read the threshold value of the test ratio */ s_rsle(&io___17); do_lio(&c__5, &c__1, (char *)&thresh, (ftnlen)sizeof(doublereal)); e_rsle(); /* Read and check the parameter values for the tests. */ /* Values of N */ s_rsle(&io___19); do_lio(&c__3, &c__1, (char *)&nidim, (ftnlen)sizeof(integer)); e_rsle(); if (nidim < 1 || nidim > 9) { io___21.ciunit = nout; s_wsfe(&io___21); do_fio(&c__1, "N", (ftnlen)1); do_fio(&c__1, (char *)&c__9, (ftnlen)sizeof(integer)); e_wsfe(); goto L220; } s_rsle(&io___22); i__1 = nidim; for (i__ = 1; i__ <= i__1; ++i__) { do_lio(&c__3, &c__1, (char *)&idim[i__ - 1], (ftnlen)sizeof(integer)); } e_rsle(); i__1 = nidim; for (i__ = 1; i__ <= i__1; ++i__) { if (idim[i__ - 1] < 0 || idim[i__ - 1] > 65) { io___25.ciunit = nout; s_wsfe(&io___25); do_fio(&c__1, (char *)&c__65, (ftnlen)sizeof(integer)); e_wsfe(); goto L220; } /* L10: */ } /* Values of ALPHA */ s_rsle(&io___26); do_lio(&c__3, &c__1, (char *)&nalf, (ftnlen)sizeof(integer)); e_rsle(); if (nalf < 1 || nalf > 7) { io___28.ciunit = nout; s_wsfe(&io___28); do_fio(&c__1, "ALPHA", (ftnlen)5); do_fio(&c__1, (char *)&c__7, (ftnlen)sizeof(integer)); e_wsfe(); goto L220; } s_rsle(&io___29); i__1 = nalf; for (i__ = 1; i__ <= i__1; ++i__) { do_lio(&c__7, &c__1, (char *)&alf[i__ - 1], (ftnlen)sizeof( doublecomplex)); } e_rsle(); /* Values of BETA */ s_rsle(&io___31); do_lio(&c__3, &c__1, (char *)&nbet, (ftnlen)sizeof(integer)); e_rsle(); if (nbet < 1 || nbet > 7) { io___33.ciunit = nout; s_wsfe(&io___33); do_fio(&c__1, "BETA", (ftnlen)4); do_fio(&c__1, (char *)&c__7, (ftnlen)sizeof(integer)); e_wsfe(); goto L220; } s_rsle(&io___34); i__1 = nbet; for (i__ = 1; i__ <= i__1; ++i__) { do_lio(&c__7, &c__1, (char *)&bet[i__ - 1], (ftnlen)sizeof( doublecomplex)); } e_rsle(); /* Report values of parameters. */ io___36.ciunit = nout; s_wsfe(&io___36); e_wsfe(); io___37.ciunit = nout; s_wsfe(&io___37); i__1 = nidim; for (i__ = 1; i__ <= i__1; ++i__) { do_fio(&c__1, (char *)&idim[i__ - 1], (ftnlen)sizeof(integer)); } e_wsfe(); io___38.ciunit = nout; s_wsfe(&io___38); i__1 = nalf; for (i__ = 1; i__ <= i__1; ++i__) { do_fio(&c__2, (char *)&alf[i__ - 1], (ftnlen)sizeof(doublereal)); } e_wsfe(); io___39.ciunit = nout; s_wsfe(&io___39); i__1 = nbet; for (i__ = 1; i__ <= i__1; ++i__) { do_fio(&c__2, (char *)&bet[i__ - 1], (ftnlen)sizeof(doublereal)); } e_wsfe(); if (! tsterr) { io___40.ciunit = nout; s_wsle(&io___40); e_wsle(); io___41.ciunit = nout; s_wsfe(&io___41); e_wsfe(); } io___42.ciunit = nout; s_wsle(&io___42); e_wsle(); io___43.ciunit = nout; s_wsfe(&io___43); do_fio(&c__1, (char *)&thresh, (ftnlen)sizeof(doublereal)); e_wsfe(); io___44.ciunit = nout; s_wsle(&io___44); e_wsle(); /* Read names of subroutines and flags which indicate */ /* whether they are to be tested. */ for (i__ = 1; i__ <= 9; ++i__) { ltest[i__ - 1] = FALSE_; /* L20: */ } L30: i__1 = s_rsfe(&io___46); if (i__1 != 0) { goto L60; } i__1 = do_fio(&c__1, snamet, (ftnlen)6); if (i__1 != 0) { goto L60; } i__1 = do_fio(&c__1, (char *)<estt, (ftnlen)sizeof(logical)); if (i__1 != 0) { goto L60; } i__1 = e_rsfe(); if (i__1 != 0) { goto L60; } for (i__ = 1; i__ <= 9; ++i__) { if (s_cmp(snamet, snames + (i__ - 1) * 6, (ftnlen)6, (ftnlen)6) == 0) { goto L50; } /* L40: */ } io___49.ciunit = nout; s_wsfe(&io___49); do_fio(&c__1, snamet, (ftnlen)6); e_wsfe(); s_stop("", (ftnlen)0); L50: ltest[i__ - 1] = ltestt; goto L30; L60: cl__1.cerr = 0; cl__1.cunit = 5; cl__1.csta = 0; f_clos(&cl__1); /* Compute EPS (the machine precision). */ eps = d_epsilon_(&c_b88); io___51.ciunit = nout; s_wsfe(&io___51); do_fio(&c__1, (char *)&eps, (ftnlen)sizeof(doublereal)); e_wsfe(); /* Check the reliability of ZMMCH using exact data. */ n = 32; i__1 = n; for (j = 1; j <= i__1; ++j) { i__2 = n; for (i__ = 1; i__ <= i__2; ++i__) { i__3 = i__ + j * 65 - 66; /* Computing MAX */ i__5 = i__ - j + 1; i__4 = max(i__5,0); ab[i__3].r = (doublereal) i__4, ab[i__3].i = 0.; /* L90: */ } i__2 = j + 4224; ab[i__2].r = (doublereal) j, ab[i__2].i = 0.; i__2 = (j + 65) * 65 - 65; ab[i__2].r = (doublereal) j, ab[i__2].i = 0.; i__2 = j - 1; c__[i__2].r = 0., c__[i__2].i = 0.; /* L100: */ } i__1 = n; for (j = 1; j <= i__1; ++j) { i__2 = j - 1; i__3 = j * ((j + 1) * j) / 2 - (j + 1) * j * (j - 1) / 3; cc[i__2].r = (doublereal) i__3, cc[i__2].i = 0.; /* L110: */ } /* CC holds the exact result. On exit from ZMMCH CT holds */ /* the result computed by ZMMCH. */ *(unsigned char *)transa = 'N'; *(unsigned char *)transb = 'N'; zmmch_(transa, transb, &n, &c__1, &n, &c_b2, ab, &c__65, &ab[4225], & c__65, &c_b1, c__, &c__65, ct, g, cc, &c__65, &eps, &err, &fatal, &nout, &c_true, (ftnlen)1, (ftnlen)1); same = lze_(cc, ct, &n); if (! same || err != 0.) { io___64.ciunit = nout; s_wsfe(&io___64); do_fio(&c__1, transa, (ftnlen)1); do_fio(&c__1, transb, (ftnlen)1); do_fio(&c__1, (char *)&same, (ftnlen)sizeof(logical)); do_fio(&c__1, (char *)&err, (ftnlen)sizeof(doublereal)); e_wsfe(); s_stop("", (ftnlen)0); } *(unsigned char *)transb = 'C'; zmmch_(transa, transb, &n, &c__1, &n, &c_b2, ab, &c__65, &ab[4225], & c__65, &c_b1, c__, &c__65, ct, g, cc, &c__65, &eps, &err, &fatal, &nout, &c_true, (ftnlen)1, (ftnlen)1); same = lze_(cc, ct, &n); if (! same || err != 0.) { io___65.ciunit = nout; s_wsfe(&io___65); do_fio(&c__1, transa, (ftnlen)1); do_fio(&c__1, transb, (ftnlen)1); do_fio(&c__1, (char *)&same, (ftnlen)sizeof(logical)); do_fio(&c__1, (char *)&err, (ftnlen)sizeof(doublereal)); e_wsfe(); s_stop("", (ftnlen)0); } i__1 = n; for (j = 1; j <= i__1; ++j) { i__2 = j + 4224; i__3 = n - j + 1; ab[i__2].r = (doublereal) i__3, ab[i__2].i = 0.; i__2 = (j + 65) * 65 - 65; i__3 = n - j + 1; ab[i__2].r = (doublereal) i__3, ab[i__2].i = 0.; /* L120: */ } i__1 = n; for (j = 1; j <= i__1; ++j) { i__2 = n - j; i__3 = j * ((j + 1) * j) / 2 - (j + 1) * j * (j - 1) / 3; cc[i__2].r = (doublereal) i__3, cc[i__2].i = 0.; /* L130: */ } *(unsigned char *)transa = 'C'; *(unsigned char *)transb = 'N'; zmmch_(transa, transb, &n, &c__1, &n, &c_b2, ab, &c__65, &ab[4225], & c__65, &c_b1, c__, &c__65, ct, g, cc, &c__65, &eps, &err, &fatal, &nout, &c_true, (ftnlen)1, (ftnlen)1); same = lze_(cc, ct, &n); if (! same || err != 0.) { io___66.ciunit = nout; s_wsfe(&io___66); do_fio(&c__1, transa, (ftnlen)1); do_fio(&c__1, transb, (ftnlen)1); do_fio(&c__1, (char *)&same, (ftnlen)sizeof(logical)); do_fio(&c__1, (char *)&err, (ftnlen)sizeof(doublereal)); e_wsfe(); s_stop("", (ftnlen)0); } *(unsigned char *)transb = 'C'; zmmch_(transa, transb, &n, &c__1, &n, &c_b2, ab, &c__65, &ab[4225], & c__65, &c_b1, c__, &c__65, ct, g, cc, &c__65, &eps, &err, &fatal, &nout, &c_true, (ftnlen)1, (ftnlen)1); same = lze_(cc, ct, &n); if (! same || err != 0.) { io___67.ciunit = nout; s_wsfe(&io___67); do_fio(&c__1, transa, (ftnlen)1); do_fio(&c__1, transb, (ftnlen)1); do_fio(&c__1, (char *)&same, (ftnlen)sizeof(logical)); do_fio(&c__1, (char *)&err, (ftnlen)sizeof(doublereal)); e_wsfe(); s_stop("", (ftnlen)0); } /* Test each subroutine in turn. */ for (isnum = 1; isnum <= 9; ++isnum) { io___69.ciunit = nout; s_wsle(&io___69); e_wsle(); if (! ltest[isnum - 1]) { /* Subprogram is not to be tested. */ io___70.ciunit = nout; s_wsfe(&io___70); do_fio(&c__1, snames + (isnum - 1) * 6, (ftnlen)6); e_wsfe(); } else { s_copy(srnamc_1.srnamt, snames + (isnum - 1) * 6, (ftnlen)6, ( ftnlen)6); /* Test error exits. */ if (tsterr) { zchke_(&isnum, snames + (isnum - 1) * 6, &nout, (ftnlen)6); io___71.ciunit = nout; s_wsle(&io___71); e_wsle(); } /* Test computations. */ infoc_1.infot = 0; infoc_1.ok = TRUE_; fatal = FALSE_; switch (isnum) { case 1: goto L140; case 2: goto L150; case 3: goto L150; case 4: goto L160; case 5: goto L160; case 6: goto L170; case 7: goto L170; case 8: goto L180; case 9: goto L180; } /* Test ZGEMM, 01. */ L140: zchk1_(snames + (isnum - 1) * 6, &eps, &thresh, &nout, &ntra, & trace, &rewi, &fatal, &nidim, idim, &nalf, alf, &nbet, bet, &c__65, ab, aa, as, &ab[4225], bb, bs, c__, cc, cs, ct, g, (ftnlen)6); goto L190; /* Test ZHEMM, 02, ZSYMM, 03. */ L150: zchk2_(snames + (isnum - 1) * 6, &eps, &thresh, &nout, &ntra, & trace, &rewi, &fatal, &nidim, idim, &nalf, alf, &nbet, bet, &c__65, ab, aa, as, &ab[4225], bb, bs, c__, cc, cs, ct, g, (ftnlen)6); goto L190; /* Test ZTRMM, 04, ZTRSM, 05. */ L160: zchk3_(snames + (isnum - 1) * 6, &eps, &thresh, &nout, &ntra, & trace, &rewi, &fatal, &nidim, idim, &nalf, alf, &c__65, ab, aa, as, &ab[4225], bb, bs, ct, g, c__, (ftnlen)6); goto L190; /* Test ZHERK, 06, ZSYRK, 07. */ L170: zchk4_(snames + (isnum - 1) * 6, &eps, &thresh, &nout, &ntra, & trace, &rewi, &fatal, &nidim, idim, &nalf, alf, &nbet, bet, &c__65, ab, aa, as, &ab[4225], bb, bs, c__, cc, cs, ct, g, (ftnlen)6); goto L190; /* Test ZHER2K, 08, ZSYR2K, 09. */ L180: zchk5_(snames + (isnum - 1) * 6, &eps, &thresh, &nout, &ntra, & trace, &rewi, &fatal, &nidim, idim, &nalf, alf, &nbet, bet, &c__65, ab, aa, as, bb, bs, c__, cc, cs, ct, g, w, ( ftnlen)6); goto L190; L190: if (fatal && sfatal) { goto L210; } } /* L200: */ } io___78.ciunit = nout; s_wsfe(&io___78); e_wsfe(); goto L230; L210: io___79.ciunit = nout; s_wsfe(&io___79); e_wsfe(); goto L230; L220: io___80.ciunit = nout; s_wsfe(&io___80); e_wsfe(); L230: if (trace) { cl__1.cerr = 0; cl__1.cunit = ntra; cl__1.csta = 0; f_clos(&cl__1); } cl__1.cerr = 0; cl__1.cunit = nout; cl__1.csta = 0; f_clos(&cl__1); s_stop("", (ftnlen)0); /* End of ZBLAT3. */ return 0; } /* main */ /* Subroutine */ int zchk1_(char *sname, doublereal *eps, doublereal *thresh, integer *nout, integer *ntra, logical *trace, logical *rewi, logical * fatal, integer *nidim, integer *idim, integer *nalf, doublecomplex * alf, integer *nbet, doublecomplex *bet, integer *nmax, doublecomplex * a, doublecomplex *aa, doublecomplex *as, doublecomplex *b, doublecomplex *bb, doublecomplex *bs, doublecomplex *c__, doublecomplex *cc, doublecomplex *cs, doublecomplex *ct, doublereal * g, ftnlen sname_len) { /* Initialized data */ static char ich[3] = "NTC"; /* Format strings */ static char fmt_9995[] = "(1x,i6,\002: \002,a6,\002('\002,a1,\002','\002" ",a1,\002',\002,3(i3,\002,\002),\002(\002,f4.1,\002,\002,f4.1," "\002), A,\002,i3,\002, B,\002,i3,\002,(\002,f4.1,\002,\002,f4.1" ",\002), C,\002,i3,\002).\002)"; static char fmt_9994[] = "(\002 ******* FATAL ERROR - ERROR-EXIT TAKEN O" "N VALID CALL *\002,\002******\002)"; static char fmt_9998[] = "(\002 ******* FATAL ERROR - PARAMETER NUMBER" " \002,i2,\002 WAS CH\002,\002ANGED INCORRECTLY *******\002)"; static char fmt_9999[] = "(\002 \002,a6,\002 PASSED THE COMPUTATIONAL TE" "STS (\002,i6,\002 CALL\002,\002S)\002)"; static char fmt_9997[] = "(\002 \002,a6,\002 COMPLETED THE COMPUTATIONAL" " TESTS (\002,i6,\002 C\002,\002ALLS)\002,/\002 ******* BUT WITH " "MAXIMUM TEST RATIO\002,f8.2,\002 - SUSPECT *******\002)"; static char fmt_9996[] = "(\002 ******* \002,a6,\002 FAILED ON CALL NUMB" "ER:\002)"; /* System generated locals */ integer a_dim1, a_offset, b_dim1, b_offset, c_dim1, c_offset, i__1, i__2, i__3, i__4, i__5, i__6, i__7, i__8; alist al__1; /* Builtin functions */ integer s_wsfe(cilist *), do_fio(integer *, char *, ftnlen), e_wsfe(void), f_rew(alist *); /* Local variables */ integer i__, k, m, n, ia, ib, ma, mb, na, nb, nc, ik, im, in, ks, ms, ns, ica, icb, laa, lbb, lda, lcc, ldb, ldc; doublecomplex als, bls; doublereal err; extern logical lze_(doublecomplex *, doublecomplex *, integer *); doublecomplex beta; integer ldas, ldbs, ldcs; logical same, null; doublecomplex alpha; logical isame[13], trana, tranb; extern /* Subroutine */ int zmake_(char *, char *, char *, integer *, integer *, doublecomplex *, integer *, doublecomplex *, integer *, logical *, doublecomplex *, ftnlen, ftnlen, ftnlen); integer nargs; extern /* Subroutine */ int zmmch_(char *, char *, integer *, integer *, integer *, doublecomplex *, doublecomplex *, integer *, doublecomplex *, integer *, doublecomplex *, doublecomplex *, integer *, doublecomplex *, doublereal *, doublecomplex *, integer *, doublereal *, doublereal *, logical *, integer *, logical *, ftnlen, ftnlen), zgemm_(char *, char *, integer *, integer *, integer *, doublecomplex *, doublecomplex *, integer *, doublecomplex *, integer *, doublecomplex *, doublecomplex *, integer *, ftnlen, ftnlen); logical reset; char tranas[1], tranbs[1], transa[1], transb[1]; doublereal errmax; extern logical lzeres_(char *, char *, integer *, integer *, doublecomplex *, doublecomplex *, integer *, ftnlen, ftnlen); /* Fortran I/O blocks */ static cilist io___124 = { 0, 0, 0, fmt_9995, 0 }; static cilist io___125 = { 0, 0, 0, fmt_9994, 0 }; static cilist io___128 = { 0, 0, 0, fmt_9998, 0 }; static cilist io___130 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___131 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___132 = { 0, 0, 0, fmt_9996, 0 }; static cilist io___133 = { 0, 0, 0, fmt_9995, 0 }; /* Tests ZGEMM. */ /* Auxiliary routine for test program for Level 3 Blas. */ /* -- Written on 8-February-1989. */ /* Jack Dongarra, Argonne National Laboratory. */ /* Iain Duff, AERE Harwell. */ /* Jeremy Du Croz, Numerical Algorithms Group Ltd. */ /* Sven Hammarling, Numerical Algorithms Group Ltd. */ /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Scalars .. */ /* .. Local Arrays .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. Scalars in Common .. */ /* .. Common blocks .. */ /* .. Data statements .. */ /* Parameter adjustments */ --idim; --alf; --bet; --g; --ct; --cs; --cc; c_dim1 = *nmax; c_offset = 1 + c_dim1; c__ -= c_offset; --bs; --bb; b_dim1 = *nmax; b_offset = 1 + b_dim1; b -= b_offset; --as; --aa; a_dim1 = *nmax; a_offset = 1 + a_dim1; a -= a_offset; /* Function Body */ /* .. Executable Statements .. */ nargs = 13; nc = 0; reset = TRUE_; errmax = 0.; i__1 = *nidim; for (im = 1; im <= i__1; ++im) { m = idim[im]; i__2 = *nidim; for (in = 1; in <= i__2; ++in) { n = idim[in]; /* Set LDC to 1 more than minimum value if room. */ ldc = m; if (ldc < *nmax) { ++ldc; } /* Skip tests if not enough room. */ if (ldc > *nmax) { goto L100; } lcc = ldc * n; null = n <= 0 || m <= 0; i__3 = *nidim; for (ik = 1; ik <= i__3; ++ik) { k = idim[ik]; for (ica = 1; ica <= 3; ++ica) { *(unsigned char *)transa = *(unsigned char *)&ich[ica - 1] ; trana = *(unsigned char *)transa == 'T' || *(unsigned char *)transa == 'C'; if (trana) { ma = k; na = m; } else { ma = m; na = k; } /* Set LDA to 1 more than minimum value if room. */ lda = ma; if (lda < *nmax) { ++lda; } /* Skip tests if not enough room. */ if (lda > *nmax) { goto L80; } laa = lda * na; /* Generate the matrix A. */ zmake_("GE", " ", " ", &ma, &na, &a[a_offset], nmax, &aa[ 1], &lda, &reset, &c_b1, (ftnlen)2, (ftnlen)1, ( ftnlen)1); for (icb = 1; icb <= 3; ++icb) { *(unsigned char *)transb = *(unsigned char *)&ich[icb - 1]; tranb = *(unsigned char *)transb == 'T' || *(unsigned char *)transb == 'C'; if (tranb) { mb = n; nb = k; } else { mb = k; nb = n; } /* Set LDB to 1 more than minimum value if room. */ ldb = mb; if (ldb < *nmax) { ++ldb; } /* Skip tests if not enough room. */ if (ldb > *nmax) { goto L70; } lbb = ldb * nb; /* Generate the matrix B. */ zmake_("GE", " ", " ", &mb, &nb, &b[b_offset], nmax, & bb[1], &ldb, &reset, &c_b1, (ftnlen)2, ( ftnlen)1, (ftnlen)1); i__4 = *nalf; for (ia = 1; ia <= i__4; ++ia) { i__5 = ia; alpha.r = alf[i__5].r, alpha.i = alf[i__5].i; i__5 = *nbet; for (ib = 1; ib <= i__5; ++ib) { i__6 = ib; beta.r = bet[i__6].r, beta.i = bet[i__6].i; /* Generate the matrix C. */ zmake_("GE", " ", " ", &m, &n, &c__[c_offset], nmax, &cc[1], &ldc, &reset, &c_b1, ( ftnlen)2, (ftnlen)1, (ftnlen)1); ++nc; /* Save every datum before calling the */ /* subroutine. */ *(unsigned char *)tranas = *(unsigned char *) transa; *(unsigned char *)tranbs = *(unsigned char *) transb; ms = m; ns = n; ks = k; als.r = alpha.r, als.i = alpha.i; i__6 = laa; for (i__ = 1; i__ <= i__6; ++i__) { i__7 = i__; i__8 = i__; as[i__7].r = aa[i__8].r, as[i__7].i = aa[ i__8].i; /* L10: */ } ldas = lda; i__6 = lbb; for (i__ = 1; i__ <= i__6; ++i__) { i__7 = i__; i__8 = i__; bs[i__7].r = bb[i__8].r, bs[i__7].i = bb[ i__8].i; /* L20: */ } ldbs = ldb; bls.r = beta.r, bls.i = beta.i; i__6 = lcc; for (i__ = 1; i__ <= i__6; ++i__) { i__7 = i__; i__8 = i__; cs[i__7].r = cc[i__8].r, cs[i__7].i = cc[ i__8].i; /* L30: */ } ldcs = ldc; /* Call the subroutine. */ if (*trace) { io___124.ciunit = *ntra; s_wsfe(&io___124); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof( integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, transa, (ftnlen)1); do_fio(&c__1, transb, (ftnlen)1); do_fio(&c__1, (char *)&m, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&n, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&k, (ftnlen)sizeof( integer)); do_fio(&c__2, (char *)&alpha, (ftnlen) sizeof(doublereal)); do_fio(&c__1, (char *)&lda, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&ldb, (ftnlen) sizeof(integer)); do_fio(&c__2, (char *)&beta, (ftnlen) sizeof(doublereal)); do_fio(&c__1, (char *)&ldc, (ftnlen) sizeof(integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } zgemm_(transa, transb, &m, &n, &k, &alpha, & aa[1], &lda, &bb[1], &ldb, &beta, &cc[ 1], &ldc, (ftnlen)1, (ftnlen)1); /* Check if error-exit was taken incorrectly. */ if (! infoc_1.ok) { io___125.ciunit = *nout; s_wsfe(&io___125); e_wsfe(); *fatal = TRUE_; goto L120; } /* See what data changed inside subroutines. */ isame[0] = *(unsigned char *)transa == *( unsigned char *)tranas; isame[1] = *(unsigned char *)transb == *( unsigned char *)tranbs; isame[2] = ms == m; isame[3] = ns == n; isame[4] = ks == k; isame[5] = als.r == alpha.r && als.i == alpha.i; isame[6] = lze_(&as[1], &aa[1], &laa); isame[7] = ldas == lda; isame[8] = lze_(&bs[1], &bb[1], &lbb); isame[9] = ldbs == ldb; isame[10] = bls.r == beta.r && bls.i == beta.i; if (null) { isame[11] = lze_(&cs[1], &cc[1], &lcc); } else { isame[11] = lzeres_("GE", " ", &m, &n, & cs[1], &cc[1], &ldc, (ftnlen)2, ( ftnlen)1); } isame[12] = ldcs == ldc; /* If data was incorrectly changed, report */ /* and return. */ same = TRUE_; i__6 = nargs; for (i__ = 1; i__ <= i__6; ++i__) { same = same && isame[i__ - 1]; if (! isame[i__ - 1]) { io___128.ciunit = *nout; s_wsfe(&io___128); do_fio(&c__1, (char *)&i__, (ftnlen) sizeof(integer)); e_wsfe(); } /* L40: */ } if (! same) { *fatal = TRUE_; goto L120; } if (! null) { /* Check the result. */ zmmch_(transa, transb, &m, &n, &k, &alpha, &a[a_offset], nmax, &b[b_offset], nmax, &beta, &c__[c_offset], nmax, &ct[1], &g[1], &cc[1], &ldc, eps, &err, fatal, nout, &c_true, (ftnlen)1, (ftnlen)1); errmax = max(errmax,err); /* If got really bad answer, report and */ /* return. */ if (*fatal) { goto L120; } } /* L50: */ } /* L60: */ } L70: ; } L80: ; } /* L90: */ } L100: ; } /* L110: */ } /* Report result. */ if (errmax < *thresh) { io___130.ciunit = *nout; s_wsfe(&io___130); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); e_wsfe(); } else { io___131.ciunit = *nout; s_wsfe(&io___131); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&errmax, (ftnlen)sizeof(doublereal)); e_wsfe(); } goto L130; L120: io___132.ciunit = *nout; s_wsfe(&io___132); do_fio(&c__1, sname, (ftnlen)6); e_wsfe(); io___133.ciunit = *nout; s_wsfe(&io___133); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, transa, (ftnlen)1); do_fio(&c__1, transb, (ftnlen)1); do_fio(&c__1, (char *)&m, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&k, (ftnlen)sizeof(integer)); do_fio(&c__2, (char *)&alpha, (ftnlen)sizeof(doublereal)); do_fio(&c__1, (char *)&lda, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&ldb, (ftnlen)sizeof(integer)); do_fio(&c__2, (char *)&beta, (ftnlen)sizeof(doublereal)); do_fio(&c__1, (char *)&ldc, (ftnlen)sizeof(integer)); e_wsfe(); L130: return 0; /* End of ZCHK1. */ } /* zchk1_ */ /* Subroutine */ int zchk2_(char *sname, doublereal *eps, doublereal *thresh, integer *nout, integer *ntra, logical *trace, logical *rewi, logical * fatal, integer *nidim, integer *idim, integer *nalf, doublecomplex * alf, integer *nbet, doublecomplex *bet, integer *nmax, doublecomplex * a, doublecomplex *aa, doublecomplex *as, doublecomplex *b, doublecomplex *bb, doublecomplex *bs, doublecomplex *c__, doublecomplex *cc, doublecomplex *cs, doublecomplex *ct, doublereal * g, ftnlen sname_len) { /* Initialized data */ static char ichs[2] = "LR"; static char ichu[2] = "UL"; /* Format strings */ static char fmt_9995[] = "(1x,i6,\002: \002,a6,\002(\002,2(\002'\002,a1" ",\002',\002),2(i3,\002,\002),\002(\002,f4.1,\002,\002,f4.1,\002)" ", A,\002,i3,\002, B,\002,i3,\002,(\002,f4.1,\002,\002,f4.1,\002)" ", C,\002,i3,\002) .\002)"; static char fmt_9994[] = "(\002 ******* FATAL ERROR - ERROR-EXIT TAKEN O" "N VALID CALL *\002,\002******\002)"; static char fmt_9998[] = "(\002 ******* FATAL ERROR - PARAMETER NUMBER" " \002,i2,\002 WAS CH\002,\002ANGED INCORRECTLY *******\002)"; static char fmt_9999[] = "(\002 \002,a6,\002 PASSED THE COMPUTATIONAL TE" "STS (\002,i6,\002 CALL\002,\002S)\002)"; static char fmt_9997[] = "(\002 \002,a6,\002 COMPLETED THE COMPUTATIONAL" " TESTS (\002,i6,\002 C\002,\002ALLS)\002,/\002 ******* BUT WITH " "MAXIMUM TEST RATIO\002,f8.2,\002 - SUSPECT *******\002)"; static char fmt_9996[] = "(\002 ******* \002,a6,\002 FAILED ON CALL NUMB" "ER:\002)"; /* System generated locals */ integer a_dim1, a_offset, b_dim1, b_offset, c_dim1, c_offset, i__1, i__2, i__3, i__4, i__5, i__6, i__7; alist al__1; /* Builtin functions */ integer s_cmp(const char *, const char *, ftnlen, ftnlen), s_wsfe(cilist *), do_fio( integer *, char *, ftnlen), e_wsfe(void), f_rew(alist *); /* Local variables */ integer i__, m, n, ia, ib, na, nc, im, in, ms, ns, laa, lbb, lda, lcc, ldb, ldc, ics; doublecomplex als, bls; integer icu; doublereal err; extern logical lze_(doublecomplex *, doublecomplex *, integer *); doublecomplex beta; integer ldas, ldbs, ldcs; logical same; char side[1]; logical conj, left, null; char uplo[1]; doublecomplex alpha; logical isame[13]; char sides[1]; extern /* Subroutine */ int zmake_(char *, char *, char *, integer *, integer *, doublecomplex *, integer *, doublecomplex *, integer *, logical *, doublecomplex *, ftnlen, ftnlen, ftnlen); integer nargs; extern /* Subroutine */ int zmmch_(char *, char *, integer *, integer *, integer *, doublecomplex *, doublecomplex *, integer *, doublecomplex *, integer *, doublecomplex *, doublecomplex *, integer *, doublecomplex *, doublereal *, doublecomplex *, integer *, doublereal *, doublereal *, logical *, integer *, logical *, ftnlen, ftnlen), zhemm_(char *, char *, integer *, integer *, doublecomplex *, doublecomplex *, integer *, doublecomplex *, integer *, doublecomplex *, doublecomplex *, integer *, ftnlen, ftnlen); logical reset; char uplos[1]; extern /* Subroutine */ int zsymm_(char *, char *, integer *, integer *, doublecomplex *, doublecomplex *, integer *, doublecomplex *, integer *, doublecomplex *, doublecomplex *, integer *, ftnlen, ftnlen); doublereal errmax; extern logical lzeres_(char *, char *, integer *, integer *, doublecomplex *, doublecomplex *, integer *, ftnlen, ftnlen); /* Fortran I/O blocks */ static cilist io___172 = { 0, 0, 0, fmt_9995, 0 }; static cilist io___173 = { 0, 0, 0, fmt_9994, 0 }; static cilist io___176 = { 0, 0, 0, fmt_9998, 0 }; static cilist io___178 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___179 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___180 = { 0, 0, 0, fmt_9996, 0 }; static cilist io___181 = { 0, 0, 0, fmt_9995, 0 }; /* Tests ZHEMM and ZSYMM. */ /* Auxiliary routine for test program for Level 3 Blas. */ /* -- Written on 8-February-1989. */ /* Jack Dongarra, Argonne National Laboratory. */ /* Iain Duff, AERE Harwell. */ /* Jeremy Du Croz, Numerical Algorithms Group Ltd. */ /* Sven Hammarling, Numerical Algorithms Group Ltd. */ /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Scalars .. */ /* .. Local Arrays .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. Scalars in Common .. */ /* .. Common blocks .. */ /* .. Data statements .. */ /* Parameter adjustments */ --idim; --alf; --bet; --g; --ct; --cs; --cc; c_dim1 = *nmax; c_offset = 1 + c_dim1; c__ -= c_offset; --bs; --bb; b_dim1 = *nmax; b_offset = 1 + b_dim1; b -= b_offset; --as; --aa; a_dim1 = *nmax; a_offset = 1 + a_dim1; a -= a_offset; /* Function Body */ /* .. Executable Statements .. */ conj = s_cmp(sname + 1, "HE", (ftnlen)2, (ftnlen)2) == 0; nargs = 12; nc = 0; reset = TRUE_; errmax = 0.; i__1 = *nidim; for (im = 1; im <= i__1; ++im) { m = idim[im]; i__2 = *nidim; for (in = 1; in <= i__2; ++in) { n = idim[in]; /* Set LDC to 1 more than minimum value if room. */ ldc = m; if (ldc < *nmax) { ++ldc; } /* Skip tests if not enough room. */ if (ldc > *nmax) { goto L90; } lcc = ldc * n; null = n <= 0 || m <= 0; /* Set LDB to 1 more than minimum value if room. */ ldb = m; if (ldb < *nmax) { ++ldb; } /* Skip tests if not enough room. */ if (ldb > *nmax) { goto L90; } lbb = ldb * n; /* Generate the matrix B. */ zmake_("GE", " ", " ", &m, &n, &b[b_offset], nmax, &bb[1], &ldb, & reset, &c_b1, (ftnlen)2, (ftnlen)1, (ftnlen)1); for (ics = 1; ics <= 2; ++ics) { *(unsigned char *)side = *(unsigned char *)&ichs[ics - 1]; left = *(unsigned char *)side == 'L'; if (left) { na = m; } else { na = n; } /* Set LDA to 1 more than minimum value if room. */ lda = na; if (lda < *nmax) { ++lda; } /* Skip tests if not enough room. */ if (lda > *nmax) { goto L80; } laa = lda * na; for (icu = 1; icu <= 2; ++icu) { *(unsigned char *)uplo = *(unsigned char *)&ichu[icu - 1]; /* Generate the hermitian or symmetric matrix A. */ zmake_(sname + 1, uplo, " ", &na, &na, &a[a_offset], nmax, &aa[1], &lda, &reset, &c_b1, (ftnlen)2, (ftnlen) 1, (ftnlen)1); i__3 = *nalf; for (ia = 1; ia <= i__3; ++ia) { i__4 = ia; alpha.r = alf[i__4].r, alpha.i = alf[i__4].i; i__4 = *nbet; for (ib = 1; ib <= i__4; ++ib) { i__5 = ib; beta.r = bet[i__5].r, beta.i = bet[i__5].i; /* Generate the matrix C. */ zmake_("GE", " ", " ", &m, &n, &c__[c_offset], nmax, &cc[1], &ldc, &reset, &c_b1, ( ftnlen)2, (ftnlen)1, (ftnlen)1); ++nc; /* Save every datum before calling the */ /* subroutine. */ *(unsigned char *)sides = *(unsigned char *)side; *(unsigned char *)uplos = *(unsigned char *)uplo; ms = m; ns = n; als.r = alpha.r, als.i = alpha.i; i__5 = laa; for (i__ = 1; i__ <= i__5; ++i__) { i__6 = i__; i__7 = i__; as[i__6].r = aa[i__7].r, as[i__6].i = aa[i__7] .i; /* L10: */ } ldas = lda; i__5 = lbb; for (i__ = 1; i__ <= i__5; ++i__) { i__6 = i__; i__7 = i__; bs[i__6].r = bb[i__7].r, bs[i__6].i = bb[i__7] .i; /* L20: */ } ldbs = ldb; bls.r = beta.r, bls.i = beta.i; i__5 = lcc; for (i__ = 1; i__ <= i__5; ++i__) { i__6 = i__; i__7 = i__; cs[i__6].r = cc[i__7].r, cs[i__6].i = cc[i__7] .i; /* L30: */ } ldcs = ldc; /* Call the subroutine. */ if (*trace) { io___172.ciunit = *ntra; s_wsfe(&io___172); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof( integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, side, (ftnlen)1); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, (char *)&m, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&n, (ftnlen)sizeof( integer)); do_fio(&c__2, (char *)&alpha, (ftnlen)sizeof( doublereal)); do_fio(&c__1, (char *)&lda, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&ldb, (ftnlen)sizeof( integer)); do_fio(&c__2, (char *)&beta, (ftnlen)sizeof( doublereal)); do_fio(&c__1, (char *)&ldc, (ftnlen)sizeof( integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } if (conj) { zhemm_(side, uplo, &m, &n, &alpha, &aa[1], & lda, &bb[1], &ldb, &beta, &cc[1], & ldc, (ftnlen)1, (ftnlen)1); } else { zsymm_(side, uplo, &m, &n, &alpha, &aa[1], & lda, &bb[1], &ldb, &beta, &cc[1], & ldc, (ftnlen)1, (ftnlen)1); } /* Check if error-exit was taken incorrectly. */ if (! infoc_1.ok) { io___173.ciunit = *nout; s_wsfe(&io___173); e_wsfe(); *fatal = TRUE_; goto L110; } /* See what data changed inside subroutines. */ isame[0] = *(unsigned char *)sides == *(unsigned char *)side; isame[1] = *(unsigned char *)uplos == *(unsigned char *)uplo; isame[2] = ms == m; isame[3] = ns == n; isame[4] = als.r == alpha.r && als.i == alpha.i; isame[5] = lze_(&as[1], &aa[1], &laa); isame[6] = ldas == lda; isame[7] = lze_(&bs[1], &bb[1], &lbb); isame[8] = ldbs == ldb; isame[9] = bls.r == beta.r && bls.i == beta.i; if (null) { isame[10] = lze_(&cs[1], &cc[1], &lcc); } else { isame[10] = lzeres_("GE", " ", &m, &n, &cs[1], &cc[1], &ldc, (ftnlen)2, (ftnlen)1); } isame[11] = ldcs == ldc; /* If data was incorrectly changed, report and */ /* return. */ same = TRUE_; i__5 = nargs; for (i__ = 1; i__ <= i__5; ++i__) { same = same && isame[i__ - 1]; if (! isame[i__ - 1]) { io___176.ciunit = *nout; s_wsfe(&io___176); do_fio(&c__1, (char *)&i__, (ftnlen) sizeof(integer)); e_wsfe(); } /* L40: */ } if (! same) { *fatal = TRUE_; goto L110; } if (! null) { /* Check the result. */ if (left) { zmmch_("N", "N", &m, &n, &m, &alpha, &a[ a_offset], nmax, &b[b_offset], nmax, &beta, &c__[c_offset], nmax, &ct[1], &g[1], &cc[1], &ldc, eps, &err, fatal, nout, &c_true, ( ftnlen)1, (ftnlen)1); } else { zmmch_("N", "N", &m, &n, &n, &alpha, &b[ b_offset], nmax, &a[a_offset], nmax, &beta, &c__[c_offset], nmax, &ct[1], &g[1], &cc[1], &ldc, eps, &err, fatal, nout, &c_true, ( ftnlen)1, (ftnlen)1); } errmax = max(errmax,err); /* If got really bad answer, report and */ /* return. */ if (*fatal) { goto L110; } } /* L50: */ } /* L60: */ } /* L70: */ } L80: ; } L90: ; } /* L100: */ } /* Report result. */ if (errmax < *thresh) { io___178.ciunit = *nout; s_wsfe(&io___178); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); e_wsfe(); } else { io___179.ciunit = *nout; s_wsfe(&io___179); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&errmax, (ftnlen)sizeof(doublereal)); e_wsfe(); } goto L120; L110: io___180.ciunit = *nout; s_wsfe(&io___180); do_fio(&c__1, sname, (ftnlen)6); e_wsfe(); io___181.ciunit = *nout; s_wsfe(&io___181); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, side, (ftnlen)1); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, (char *)&m, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)); do_fio(&c__2, (char *)&alpha, (ftnlen)sizeof(doublereal)); do_fio(&c__1, (char *)&lda, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&ldb, (ftnlen)sizeof(integer)); do_fio(&c__2, (char *)&beta, (ftnlen)sizeof(doublereal)); do_fio(&c__1, (char *)&ldc, (ftnlen)sizeof(integer)); e_wsfe(); L120: return 0; /* End of ZCHK2. */ } /* zchk2_ */ /* Subroutine */ int zchk3_(char *sname, doublereal *eps, doublereal *thresh, integer *nout, integer *ntra, logical *trace, logical *rewi, logical * fatal, integer *nidim, integer *idim, integer *nalf, doublecomplex * alf, integer *nmax, doublecomplex *a, doublecomplex *aa, doublecomplex *as, doublecomplex *b, doublecomplex *bb, doublecomplex *bs, doublecomplex *ct, doublereal *g, doublecomplex *c__, ftnlen sname_len) { /* Initialized data */ static char ichu[2] = "UL"; static char icht[3] = "NTC"; static char ichd[2] = "UN"; static char ichs[2] = "LR"; /* Format strings */ static char fmt_9995[] = "(1x,i6,\002: \002,a6,\002(\002,4(\002'\002,a1" ",\002',\002),2(i3,\002,\002),\002(\002,f4.1,\002,\002,f4.1,\002)" ", A,\002,i3,\002, B,\002,i3,\002) \002,\002 .\002)"; static char fmt_9994[] = "(\002 ******* FATAL ERROR - ERROR-EXIT TAKEN O" "N VALID CALL *\002,\002******\002)"; static char fmt_9998[] = "(\002 ******* FATAL ERROR - PARAMETER NUMBER" " \002,i2,\002 WAS CH\002,\002ANGED INCORRECTLY *******\002)"; static char fmt_9999[] = "(\002 \002,a6,\002 PASSED THE COMPUTATIONAL TE" "STS (\002,i6,\002 CALL\002,\002S)\002)"; static char fmt_9997[] = "(\002 \002,a6,\002 COMPLETED THE COMPUTATIONAL" " TESTS (\002,i6,\002 C\002,\002ALLS)\002,/\002 ******* BUT WITH " "MAXIMUM TEST RATIO\002,f8.2,\002 - SUSPECT *******\002)"; static char fmt_9996[] = "(\002 ******* \002,a6,\002 FAILED ON CALL NUMB" "ER:\002)"; /* System generated locals */ integer a_dim1, a_offset, b_dim1, b_offset, c_dim1, c_offset, i__1, i__2, i__3, i__4, i__5, i__6, i__7; doublecomplex z__1; alist al__1; /* Builtin functions */ integer s_cmp(const char *, const char *, ftnlen, ftnlen), s_wsfe(cilist *), do_fio( integer *, char *, ftnlen), e_wsfe(void), f_rew(alist *); /* Local variables */ integer i__, j, m, n, ia, na, nc, im, in, ms, ns, laa, icd, lbb, lda, ldb, ics; doublecomplex als; integer ict, icu; doublereal err; extern logical lze_(doublecomplex *, doublecomplex *, integer *); char diag[1]; integer ldas, ldbs; logical same; char side[1]; logical left, null; char uplo[1]; doublecomplex alpha; char diags[1]; logical isame[13]; char sides[1]; extern /* Subroutine */ int zmake_(char *, char *, char *, integer *, integer *, doublecomplex *, integer *, doublecomplex *, integer *, logical *, doublecomplex *, ftnlen, ftnlen, ftnlen); integer nargs; extern /* Subroutine */ int zmmch_(char *, char *, integer *, integer *, integer *, doublecomplex *, doublecomplex *, integer *, doublecomplex *, integer *, doublecomplex *, doublecomplex *, integer *, doublecomplex *, doublereal *, doublecomplex *, integer *, doublereal *, doublereal *, logical *, integer *, logical *, ftnlen, ftnlen); logical reset; char uplos[1]; extern /* Subroutine */ int ztrmm_(char *, char *, char *, char *, integer *, integer *, doublecomplex *, doublecomplex *, integer *, doublecomplex *, integer *, ftnlen, ftnlen, ftnlen, ftnlen), ztrsm_(char *, char *, char *, char *, integer *, integer *, doublecomplex *, doublecomplex *, integer *, doublecomplex *, integer *, ftnlen, ftnlen, ftnlen, ftnlen); char tranas[1], transa[1]; doublereal errmax; extern logical lzeres_(char *, char *, integer *, integer *, doublecomplex *, doublecomplex *, integer *, ftnlen, ftnlen); /* Fortran I/O blocks */ static cilist io___222 = { 0, 0, 0, fmt_9995, 0 }; static cilist io___223 = { 0, 0, 0, fmt_9995, 0 }; static cilist io___224 = { 0, 0, 0, fmt_9994, 0 }; static cilist io___227 = { 0, 0, 0, fmt_9998, 0 }; static cilist io___229 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___230 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___231 = { 0, 0, 0, fmt_9996, 0 }; static cilist io___232 = { 0, 0, 0, fmt_9995, 0 }; /* Tests ZTRMM and ZTRSM. */ /* Auxiliary routine for test program for Level 3 Blas. */ /* -- Written on 8-February-1989. */ /* Jack Dongarra, Argonne National Laboratory. */ /* Iain Duff, AERE Harwell. */ /* Jeremy Du Croz, Numerical Algorithms Group Ltd. */ /* Sven Hammarling, Numerical Algorithms Group Ltd. */ /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Scalars .. */ /* .. Local Arrays .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. Scalars in Common .. */ /* .. Common blocks .. */ /* .. Data statements .. */ /* Parameter adjustments */ --idim; --alf; c_dim1 = *nmax; c_offset = 1 + c_dim1; c__ -= c_offset; --g; --ct; --bs; --bb; b_dim1 = *nmax; b_offset = 1 + b_dim1; b -= b_offset; --as; --aa; a_dim1 = *nmax; a_offset = 1 + a_dim1; a -= a_offset; /* Function Body */ /* .. Executable Statements .. */ nargs = 11; nc = 0; reset = TRUE_; errmax = 0.; /* Set up zero matrix for ZMMCH. */ i__1 = *nmax; for (j = 1; j <= i__1; ++j) { i__2 = *nmax; for (i__ = 1; i__ <= i__2; ++i__) { i__3 = i__ + j * c_dim1; c__[i__3].r = 0., c__[i__3].i = 0.; /* L10: */ } /* L20: */ } i__1 = *nidim; for (im = 1; im <= i__1; ++im) { m = idim[im]; i__2 = *nidim; for (in = 1; in <= i__2; ++in) { n = idim[in]; /* Set LDB to 1 more than minimum value if room. */ ldb = m; if (ldb < *nmax) { ++ldb; } /* Skip tests if not enough room. */ if (ldb > *nmax) { goto L130; } lbb = ldb * n; null = m <= 0 || n <= 0; for (ics = 1; ics <= 2; ++ics) { *(unsigned char *)side = *(unsigned char *)&ichs[ics - 1]; left = *(unsigned char *)side == 'L'; if (left) { na = m; } else { na = n; } /* Set LDA to 1 more than minimum value if room. */ lda = na; if (lda < *nmax) { ++lda; } /* Skip tests if not enough room. */ if (lda > *nmax) { goto L130; } laa = lda * na; for (icu = 1; icu <= 2; ++icu) { *(unsigned char *)uplo = *(unsigned char *)&ichu[icu - 1]; for (ict = 1; ict <= 3; ++ict) { *(unsigned char *)transa = *(unsigned char *)&icht[ ict - 1]; for (icd = 1; icd <= 2; ++icd) { *(unsigned char *)diag = *(unsigned char *)&ichd[ icd - 1]; i__3 = *nalf; for (ia = 1; ia <= i__3; ++ia) { i__4 = ia; alpha.r = alf[i__4].r, alpha.i = alf[i__4].i; /* Generate the matrix A. */ zmake_("TR", uplo, diag, &na, &na, &a[ a_offset], nmax, &aa[1], &lda, &reset, &c_b1, (ftnlen)2, (ftnlen)1, (ftnlen) 1); /* Generate the matrix B. */ zmake_("GE", " ", " ", &m, &n, &b[b_offset], nmax, &bb[1], &ldb, &reset, &c_b1, ( ftnlen)2, (ftnlen)1, (ftnlen)1); ++nc; /* Save every datum before calling the */ /* subroutine. */ *(unsigned char *)sides = *(unsigned char *) side; *(unsigned char *)uplos = *(unsigned char *) uplo; *(unsigned char *)tranas = *(unsigned char *) transa; *(unsigned char *)diags = *(unsigned char *) diag; ms = m; ns = n; als.r = alpha.r, als.i = alpha.i; i__4 = laa; for (i__ = 1; i__ <= i__4; ++i__) { i__5 = i__; i__6 = i__; as[i__5].r = aa[i__6].r, as[i__5].i = aa[ i__6].i; /* L30: */ } ldas = lda; i__4 = lbb; for (i__ = 1; i__ <= i__4; ++i__) { i__5 = i__; i__6 = i__; bs[i__5].r = bb[i__6].r, bs[i__5].i = bb[ i__6].i; /* L40: */ } ldbs = ldb; /* Call the subroutine. */ if (s_cmp(sname + 3, "MM", (ftnlen)2, (ftnlen) 2) == 0) { if (*trace) { io___222.ciunit = *ntra; s_wsfe(&io___222); do_fio(&c__1, (char *)&nc, (ftnlen) sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, side, (ftnlen)1); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, transa, (ftnlen)1); do_fio(&c__1, diag, (ftnlen)1); do_fio(&c__1, (char *)&m, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&n, (ftnlen) sizeof(integer)); do_fio(&c__2, (char *)&alpha, (ftnlen) sizeof(doublereal)); do_fio(&c__1, (char *)&lda, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&ldb, (ftnlen) sizeof(integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } ztrmm_(side, uplo, transa, diag, &m, &n, & alpha, &aa[1], &lda, &bb[1], &ldb, (ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); } else if (s_cmp(sname + 3, "SM", (ftnlen)2, ( ftnlen)2) == 0) { if (*trace) { io___223.ciunit = *ntra; s_wsfe(&io___223); do_fio(&c__1, (char *)&nc, (ftnlen) sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, side, (ftnlen)1); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, transa, (ftnlen)1); do_fio(&c__1, diag, (ftnlen)1); do_fio(&c__1, (char *)&m, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&n, (ftnlen) sizeof(integer)); do_fio(&c__2, (char *)&alpha, (ftnlen) sizeof(doublereal)); do_fio(&c__1, (char *)&lda, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&ldb, (ftnlen) sizeof(integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } ztrsm_(side, uplo, transa, diag, &m, &n, & alpha, &aa[1], &lda, &bb[1], &ldb, (ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); } /* Check if error-exit was taken incorrectly. */ if (! infoc_1.ok) { io___224.ciunit = *nout; s_wsfe(&io___224); e_wsfe(); *fatal = TRUE_; goto L150; } /* See what data changed inside subroutines. */ isame[0] = *(unsigned char *)sides == *( unsigned char *)side; isame[1] = *(unsigned char *)uplos == *( unsigned char *)uplo; isame[2] = *(unsigned char *)tranas == *( unsigned char *)transa; isame[3] = *(unsigned char *)diags == *( unsigned char *)diag; isame[4] = ms == m; isame[5] = ns == n; isame[6] = als.r == alpha.r && als.i == alpha.i; isame[7] = lze_(&as[1], &aa[1], &laa); isame[8] = ldas == lda; if (null) { isame[9] = lze_(&bs[1], &bb[1], &lbb); } else { isame[9] = lzeres_("GE", " ", &m, &n, &bs[ 1], &bb[1], &ldb, (ftnlen)2, ( ftnlen)1); } isame[10] = ldbs == ldb; /* If data was incorrectly changed, report and */ /* return. */ same = TRUE_; i__4 = nargs; for (i__ = 1; i__ <= i__4; ++i__) { same = same && isame[i__ - 1]; if (! isame[i__ - 1]) { io___227.ciunit = *nout; s_wsfe(&io___227); do_fio(&c__1, (char *)&i__, (ftnlen) sizeof(integer)); e_wsfe(); } /* L50: */ } if (! same) { *fatal = TRUE_; goto L150; } if (! null) { if (s_cmp(sname + 3, "MM", (ftnlen)2, ( ftnlen)2) == 0) { /* Check the result. */ if (left) { zmmch_(transa, "N", &m, &n, &m, & alpha, &a[a_offset], nmax, &b[b_offset], nmax, & c_b1, &c__[c_offset], nmax, &ct[1], &g[1], &bb[ 1], &ldb, eps, &err, fatal, nout, &c_true, ( ftnlen)1, (ftnlen)1); } else { zmmch_("N", transa, &m, &n, &n, & alpha, &b[b_offset], nmax, &a[a_offset], nmax, & c_b1, &c__[c_offset], nmax, &ct[1], &g[1], &bb[ 1], &ldb, eps, &err, fatal, nout, &c_true, ( ftnlen)1, (ftnlen)1); } } else if (s_cmp(sname + 3, "SM", (ftnlen) 2, (ftnlen)2) == 0) { /* Compute approximation to original */ /* matrix. */ i__4 = n; for (j = 1; j <= i__4; ++j) { i__5 = m; for (i__ = 1; i__ <= i__5; ++i__) { i__6 = i__ + j * c_dim1; i__7 = i__ + (j - 1) * ldb; c__[i__6].r = bb[i__7].r, c__[i__6].i = bb[i__7].i; i__6 = i__ + (j - 1) * ldb; i__7 = i__ + j * b_dim1; z__1.r = alpha.r * b[i__7].r - alpha.i * b[i__7].i, z__1.i = alpha.r * b[i__7].i + alpha.i * b[ i__7].r; bb[i__6].r = z__1.r, bb[i__6].i = z__1.i; /* L60: */ } /* L70: */ } if (left) { zmmch_(transa, "N", &m, &n, &m, & c_b2, &a[a_offset], nmax, &c__[c_offset], nmax, & c_b1, &b[b_offset], nmax, &ct[1], &g[1], &bb[1], & ldb, eps, &err, fatal, nout, &c_false, (ftnlen)1, (ftnlen)1); } else { zmmch_("N", transa, &m, &n, &n, & c_b2, &c__[c_offset], nmax, &a[a_offset], nmax, &c_b1, &b[b_offset], nmax, &ct[1], &g[1], &bb[1], & ldb, eps, &err, fatal, nout, &c_false, (ftnlen)1, (ftnlen)1); } } errmax = max(errmax,err); /* If got really bad answer, report and */ /* return. */ if (*fatal) { goto L150; } } /* L80: */ } /* L90: */ } /* L100: */ } /* L110: */ } /* L120: */ } L130: ; } /* L140: */ } /* Report result. */ if (errmax < *thresh) { io___229.ciunit = *nout; s_wsfe(&io___229); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); e_wsfe(); } else { io___230.ciunit = *nout; s_wsfe(&io___230); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&errmax, (ftnlen)sizeof(doublereal)); e_wsfe(); } goto L160; L150: io___231.ciunit = *nout; s_wsfe(&io___231); do_fio(&c__1, sname, (ftnlen)6); e_wsfe(); io___232.ciunit = *nout; s_wsfe(&io___232); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, side, (ftnlen)1); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, transa, (ftnlen)1); do_fio(&c__1, diag, (ftnlen)1); do_fio(&c__1, (char *)&m, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)); do_fio(&c__2, (char *)&alpha, (ftnlen)sizeof(doublereal)); do_fio(&c__1, (char *)&lda, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&ldb, (ftnlen)sizeof(integer)); e_wsfe(); L160: return 0; /* End of ZCHK3. */ } /* zchk3_ */ /* Subroutine */ int zchk4_(char *sname, doublereal *eps, doublereal *thresh, integer *nout, integer *ntra, logical *trace, logical *rewi, logical * fatal, integer *nidim, integer *idim, integer *nalf, doublecomplex * alf, integer *nbet, doublecomplex *bet, integer *nmax, doublecomplex * a, doublecomplex *aa, doublecomplex *as, doublecomplex *b, doublecomplex *bb, doublecomplex *bs, doublecomplex *c__, doublecomplex *cc, doublecomplex *cs, doublecomplex *ct, doublereal * g, ftnlen sname_len) { /* Initialized data */ static char icht[2] = "NC"; static char ichu[2] = "UL"; /* Format strings */ static char fmt_9994[] = "(1x,i6,\002: \002,a6,\002(\002,2(\002'\002,a1" ",\002',\002),2(i3,\002,\002),f4.1,\002, A,\002,i3,\002,\002,f4.1," "\002, C,\002,i3,\002) \002,\002 .\002)"; static char fmt_9993[] = "(1x,i6,\002: \002,a6,\002(\002,2(\002'\002,a1" ",\002',\002),2(i3,\002,\002),\002(\002,f4.1,\002,\002,f4.1,\002)" " , A,\002,i3,\002,(\002,f4.1,\002,\002,f4.1,\002), C,\002,i3," "\002) .\002)"; static char fmt_9992[] = "(\002 ******* FATAL ERROR - ERROR-EXIT TAKEN O" "N VALID CALL *\002,\002******\002)"; static char fmt_9998[] = "(\002 ******* FATAL ERROR - PARAMETER NUMBER" " \002,i2,\002 WAS CH\002,\002ANGED INCORRECTLY *******\002)"; static char fmt_9999[] = "(\002 \002,a6,\002 PASSED THE COMPUTATIONAL TE" "STS (\002,i6,\002 CALL\002,\002S)\002)"; static char fmt_9997[] = "(\002 \002,a6,\002 COMPLETED THE COMPUTATIONAL" " TESTS (\002,i6,\002 C\002,\002ALLS)\002,/\002 ******* BUT WITH " "MAXIMUM TEST RATIO\002,f8.2,\002 - SUSPECT *******\002)"; static char fmt_9995[] = "(\002 THESE ARE THE RESULTS FOR COLUMN" " \002,i3)"; static char fmt_9996[] = "(\002 ******* \002,a6,\002 FAILED ON CALL NUMB" "ER:\002)"; /* System generated locals */ integer a_dim1, a_offset, b_dim1, b_offset, c_dim1, c_offset, i__1, i__2, i__3, i__4, i__5, i__6, i__7; doublecomplex z__1; alist al__1; /* Builtin functions */ integer s_cmp(const char *, const char *, ftnlen, ftnlen), s_wsfe(cilist *), do_fio( integer *, char *, ftnlen), e_wsfe(void), f_rew(alist *); /* Local variables */ integer i__, j, k, n, ia, ib, jc, ma, na, nc, ik, in, jj, lj, ks, ns, laa, lda, lcc, ldc; doublecomplex als; integer ict, icu; doublereal err; extern logical lze_(doublecomplex *, doublecomplex *, integer *); doublecomplex beta; integer ldas, ldcs; logical same, conj; doublecomplex bets; doublereal rals; logical tran, null; char uplo[1]; doublecomplex alpha; doublereal rbeta; logical isame[13]; extern /* Subroutine */ int zmake_(char *, char *, char *, integer *, integer *, doublecomplex *, integer *, doublecomplex *, integer *, logical *, doublecomplex *, ftnlen, ftnlen, ftnlen); integer nargs; extern /* Subroutine */ int zmmch_(char *, char *, integer *, integer *, integer *, doublecomplex *, doublecomplex *, integer *, doublecomplex *, integer *, doublecomplex *, doublecomplex *, integer *, doublecomplex *, doublereal *, doublecomplex *, integer *, doublereal *, doublereal *, logical *, integer *, logical *, ftnlen, ftnlen); doublereal rbets; logical reset; extern /* Subroutine */ int zherk_(char *, char *, integer *, integer *, doublereal *, doublecomplex *, integer *, doublereal *, doublecomplex *, integer *, ftnlen, ftnlen); char trans[1]; logical upper; char uplos[1]; extern /* Subroutine */ int zsyrk_(char *, char *, integer *, integer *, doublecomplex *, doublecomplex *, integer *, doublecomplex *, doublecomplex *, integer *, ftnlen, ftnlen); doublereal ralpha, errmax; extern logical lzeres_(char *, char *, integer *, integer *, doublecomplex *, doublecomplex *, integer *, ftnlen, ftnlen); char transs[1], transt[1]; /* Fortran I/O blocks */ static cilist io___274 = { 0, 0, 0, fmt_9994, 0 }; static cilist io___275 = { 0, 0, 0, fmt_9993, 0 }; static cilist io___276 = { 0, 0, 0, fmt_9992, 0 }; static cilist io___279 = { 0, 0, 0, fmt_9998, 0 }; static cilist io___286 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___287 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___288 = { 0, 0, 0, fmt_9995, 0 }; static cilist io___289 = { 0, 0, 0, fmt_9996, 0 }; static cilist io___290 = { 0, 0, 0, fmt_9994, 0 }; static cilist io___291 = { 0, 0, 0, fmt_9993, 0 }; /* Tests ZHERK and ZSYRK. */ /* Auxiliary routine for test program for Level 3 Blas. */ /* -- Written on 8-February-1989. */ /* Jack Dongarra, Argonne National Laboratory. */ /* Iain Duff, AERE Harwell. */ /* Jeremy Du Croz, Numerical Algorithms Group Ltd. */ /* Sven Hammarling, Numerical Algorithms Group Ltd. */ /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Scalars .. */ /* .. Local Arrays .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. Scalars in Common .. */ /* .. Common blocks .. */ /* .. Data statements .. */ /* Parameter adjustments */ --idim; --alf; --bet; --g; --ct; --cs; --cc; c_dim1 = *nmax; c_offset = 1 + c_dim1; c__ -= c_offset; --bs; --bb; b_dim1 = *nmax; b_offset = 1 + b_dim1; b -= b_offset; --as; --aa; a_dim1 = *nmax; a_offset = 1 + a_dim1; a -= a_offset; /* Function Body */ /* .. Executable Statements .. */ conj = s_cmp(sname + 1, "HE", (ftnlen)2, (ftnlen)2) == 0; nargs = 10; nc = 0; reset = TRUE_; errmax = 0.; i__1 = *nidim; for (in = 1; in <= i__1; ++in) { n = idim[in]; /* Set LDC to 1 more than minimum value if room. */ ldc = n; if (ldc < *nmax) { ++ldc; } /* Skip tests if not enough room. */ if (ldc > *nmax) { goto L100; } lcc = ldc * n; i__2 = *nidim; for (ik = 1; ik <= i__2; ++ik) { k = idim[ik]; for (ict = 1; ict <= 2; ++ict) { *(unsigned char *)trans = *(unsigned char *)&icht[ict - 1]; tran = *(unsigned char *)trans == 'C'; if (tran && ! conj) { *(unsigned char *)trans = 'T'; } if (tran) { ma = k; na = n; } else { ma = n; na = k; } /* Set LDA to 1 more than minimum value if room. */ lda = ma; if (lda < *nmax) { ++lda; } /* Skip tests if not enough room. */ if (lda > *nmax) { goto L80; } laa = lda * na; /* Generate the matrix A. */ zmake_("GE", " ", " ", &ma, &na, &a[a_offset], nmax, &aa[1], & lda, &reset, &c_b1, (ftnlen)2, (ftnlen)1, (ftnlen)1); for (icu = 1; icu <= 2; ++icu) { *(unsigned char *)uplo = *(unsigned char *)&ichu[icu - 1]; upper = *(unsigned char *)uplo == 'U'; i__3 = *nalf; for (ia = 1; ia <= i__3; ++ia) { i__4 = ia; alpha.r = alf[i__4].r, alpha.i = alf[i__4].i; if (conj) { ralpha = alpha.r; z__1.r = ralpha, z__1.i = 0.; alpha.r = z__1.r, alpha.i = z__1.i; } i__4 = *nbet; for (ib = 1; ib <= i__4; ++ib) { i__5 = ib; beta.r = bet[i__5].r, beta.i = bet[i__5].i; if (conj) { rbeta = beta.r; z__1.r = rbeta, z__1.i = 0.; beta.r = z__1.r, beta.i = z__1.i; } null = n <= 0; if (conj) { null = null || (k <= 0 || ralpha == 0.) && rbeta == 1.; } /* Generate the matrix C. */ zmake_(sname + 1, uplo, " ", &n, &n, &c__[ c_offset], nmax, &cc[1], &ldc, &reset, & c_b1, (ftnlen)2, (ftnlen)1, (ftnlen)1); ++nc; /* Save every datum before calling the subroutine. */ *(unsigned char *)uplos = *(unsigned char *)uplo; *(unsigned char *)transs = *(unsigned char *) trans; ns = n; ks = k; if (conj) { rals = ralpha; } else { als.r = alpha.r, als.i = alpha.i; } i__5 = laa; for (i__ = 1; i__ <= i__5; ++i__) { i__6 = i__; i__7 = i__; as[i__6].r = aa[i__7].r, as[i__6].i = aa[i__7] .i; /* L10: */ } ldas = lda; if (conj) { rbets = rbeta; } else { bets.r = beta.r, bets.i = beta.i; } i__5 = lcc; for (i__ = 1; i__ <= i__5; ++i__) { i__6 = i__; i__7 = i__; cs[i__6].r = cc[i__7].r, cs[i__6].i = cc[i__7] .i; /* L20: */ } ldcs = ldc; /* Call the subroutine. */ if (conj) { if (*trace) { io___274.ciunit = *ntra; s_wsfe(&io___274); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof( integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&k, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&ralpha, (ftnlen) sizeof(doublereal)); do_fio(&c__1, (char *)&lda, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&rbeta, (ftnlen) sizeof(doublereal)); do_fio(&c__1, (char *)&ldc, (ftnlen) sizeof(integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } zherk_(uplo, trans, &n, &k, &ralpha, &aa[1], & lda, &rbeta, &cc[1], &ldc, (ftnlen)1, (ftnlen)1); } else { if (*trace) { io___275.ciunit = *ntra; s_wsfe(&io___275); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof( integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&k, (ftnlen)sizeof( integer)); do_fio(&c__2, (char *)&alpha, (ftnlen) sizeof(doublereal)); do_fio(&c__1, (char *)&lda, (ftnlen) sizeof(integer)); do_fio(&c__2, (char *)&beta, (ftnlen) sizeof(doublereal)); do_fio(&c__1, (char *)&ldc, (ftnlen) sizeof(integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } zsyrk_(uplo, trans, &n, &k, &alpha, &aa[1], & lda, &beta, &cc[1], &ldc, (ftnlen)1, ( ftnlen)1); } /* Check if error-exit was taken incorrectly. */ if (! infoc_1.ok) { io___276.ciunit = *nout; s_wsfe(&io___276); e_wsfe(); *fatal = TRUE_; goto L120; } /* See what data changed inside subroutines. */ isame[0] = *(unsigned char *)uplos == *(unsigned char *)uplo; isame[1] = *(unsigned char *)transs == *(unsigned char *)trans; isame[2] = ns == n; isame[3] = ks == k; if (conj) { isame[4] = rals == ralpha; } else { isame[4] = als.r == alpha.r && als.i == alpha.i; } isame[5] = lze_(&as[1], &aa[1], &laa); isame[6] = ldas == lda; if (conj) { isame[7] = rbets == rbeta; } else { isame[7] = bets.r == beta.r && bets.i == beta.i; } if (null) { isame[8] = lze_(&cs[1], &cc[1], &lcc); } else { isame[8] = lzeres_(sname + 1, uplo, &n, &n, & cs[1], &cc[1], &ldc, (ftnlen)2, ( ftnlen)1); } isame[9] = ldcs == ldc; /* If data was incorrectly changed, report and */ /* return. */ same = TRUE_; i__5 = nargs; for (i__ = 1; i__ <= i__5; ++i__) { same = same && isame[i__ - 1]; if (! isame[i__ - 1]) { io___279.ciunit = *nout; s_wsfe(&io___279); do_fio(&c__1, (char *)&i__, (ftnlen) sizeof(integer)); e_wsfe(); } /* L30: */ } if (! same) { *fatal = TRUE_; goto L120; } if (! null) { /* Check the result column by column. */ if (conj) { *(unsigned char *)transt = 'C'; } else { *(unsigned char *)transt = 'T'; } jc = 1; i__5 = n; for (j = 1; j <= i__5; ++j) { if (upper) { jj = 1; lj = j; } else { jj = j; lj = n - j + 1; } if (tran) { zmmch_(transt, "N", &lj, &c__1, &k, & alpha, &a[jj * a_dim1 + 1], nmax, &a[j * a_dim1 + 1], nmax, &beta, &c__[jj + j * c_dim1], nmax, &ct[1], &g[1], &cc[jc], &ldc, eps, &err, fatal, nout, &c_true, (ftnlen) 1, (ftnlen)1); } else { zmmch_("N", transt, &lj, &c__1, &k, & alpha, &a[jj + a_dim1], nmax, &a[j + a_dim1], nmax, &beta, & c__[jj + j * c_dim1], nmax, & ct[1], &g[1], &cc[jc], &ldc, eps, &err, fatal, nout, & c_true, (ftnlen)1, (ftnlen)1); } if (upper) { jc += ldc; } else { jc = jc + ldc + 1; } errmax = max(errmax,err); /* If got really bad answer, report and */ /* return. */ if (*fatal) { goto L110; } /* L40: */ } } /* L50: */ } /* L60: */ } /* L70: */ } L80: ; } /* L90: */ } L100: ; } /* Report result. */ if (errmax < *thresh) { io___286.ciunit = *nout; s_wsfe(&io___286); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); e_wsfe(); } else { io___287.ciunit = *nout; s_wsfe(&io___287); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&errmax, (ftnlen)sizeof(doublereal)); e_wsfe(); } goto L130; L110: if (n > 1) { io___288.ciunit = *nout; s_wsfe(&io___288); do_fio(&c__1, (char *)&j, (ftnlen)sizeof(integer)); e_wsfe(); } L120: io___289.ciunit = *nout; s_wsfe(&io___289); do_fio(&c__1, sname, (ftnlen)6); e_wsfe(); if (conj) { io___290.ciunit = *nout; s_wsfe(&io___290); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&k, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&ralpha, (ftnlen)sizeof(doublereal)); do_fio(&c__1, (char *)&lda, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&rbeta, (ftnlen)sizeof(doublereal)); do_fio(&c__1, (char *)&ldc, (ftnlen)sizeof(integer)); e_wsfe(); } else { io___291.ciunit = *nout; s_wsfe(&io___291); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&k, (ftnlen)sizeof(integer)); do_fio(&c__2, (char *)&alpha, (ftnlen)sizeof(doublereal)); do_fio(&c__1, (char *)&lda, (ftnlen)sizeof(integer)); do_fio(&c__2, (char *)&beta, (ftnlen)sizeof(doublereal)); do_fio(&c__1, (char *)&ldc, (ftnlen)sizeof(integer)); e_wsfe(); } L130: return 0; /* End of ZCHK4. */ } /* zchk4_ */ /* Subroutine */ int zchk5_(char *sname, doublereal *eps, doublereal *thresh, integer *nout, integer *ntra, logical *trace, logical *rewi, logical * fatal, integer *nidim, integer *idim, integer *nalf, doublecomplex * alf, integer *nbet, doublecomplex *bet, integer *nmax, doublecomplex * ab, doublecomplex *aa, doublecomplex *as, doublecomplex *bb, doublecomplex *bs, doublecomplex *c__, doublecomplex *cc, doublecomplex *cs, doublecomplex *ct, doublereal *g, doublecomplex *w, ftnlen sname_len) { /* Initialized data */ static char icht[2] = "NC"; static char ichu[2] = "UL"; /* Format strings */ static char fmt_9994[] = "(1x,i6,\002: \002,a6,\002(\002,2(\002'\002,a1" ",\002',\002),2(i3,\002,\002),\002(\002,f4.1,\002,\002,f4.1,\002)" ", A,\002,i3,\002, B,\002,i3,\002,\002,f4.1,\002, C,\002,i3,\002)" " .\002)"; static char fmt_9993[] = "(1x,i6,\002: \002,a6,\002(\002,2(\002'\002,a1" ",\002',\002),2(i3,\002,\002),\002(\002,f4.1,\002,\002,f4.1,\002)" ", A,\002,i3,\002, B,\002,i3,\002,(\002,f4.1,\002,\002,f4.1,\002)" ", C,\002,i3,\002) .\002)"; static char fmt_9992[] = "(\002 ******* FATAL ERROR - ERROR-EXIT TAKEN O" "N VALID CALL *\002,\002******\002)"; static char fmt_9998[] = "(\002 ******* FATAL ERROR - PARAMETER NUMBER" " \002,i2,\002 WAS CH\002,\002ANGED INCORRECTLY *******\002)"; static char fmt_9999[] = "(\002 \002,a6,\002 PASSED THE COMPUTATIONAL TE" "STS (\002,i6,\002 CALL\002,\002S)\002)"; static char fmt_9997[] = "(\002 \002,a6,\002 COMPLETED THE COMPUTATIONAL" " TESTS (\002,i6,\002 C\002,\002ALLS)\002,/\002 ******* BUT WITH " "MAXIMUM TEST RATIO\002,f8.2,\002 - SUSPECT *******\002)"; static char fmt_9995[] = "(\002 THESE ARE THE RESULTS FOR COLUMN" " \002,i3)"; static char fmt_9996[] = "(\002 ******* \002,a6,\002 FAILED ON CALL NUMB" "ER:\002)"; /* System generated locals */ integer c_dim1, c_offset, i__1, i__2, i__3, i__4, i__5, i__6, i__7, i__8; doublecomplex z__1, z__2; alist al__1; /* Builtin functions */ integer s_cmp(const char *, const char *, ftnlen, ftnlen), s_wsfe(cilist *), do_fio( integer *, char *, ftnlen), e_wsfe(void), f_rew(alist *); void d_cnjg(doublecomplex *, const doublecomplex *); /* Local variables */ integer i__, j, k, n, ia, ib, jc, ma, na, nc, ik, in, jj, lj, ks, ns, laa, lbb, lda, lcc, ldb, ldc; doublecomplex als; integer ict, icu; doublereal err; extern logical lze_(doublecomplex *, doublecomplex *, integer *); integer jjab; doublecomplex beta; integer ldas, ldbs, ldcs; logical same, conj; doublecomplex bets; logical tran, null; char uplo[1]; doublecomplex alpha; doublereal rbeta; logical isame[13]; extern /* Subroutine */ int zmake_(char *, char *, char *, integer *, integer *, doublecomplex *, integer *, doublecomplex *, integer *, logical *, doublecomplex *, ftnlen, ftnlen, ftnlen); integer nargs; extern /* Subroutine */ int zmmch_(char *, char *, integer *, integer *, integer *, doublecomplex *, doublecomplex *, integer *, doublecomplex *, integer *, doublecomplex *, doublecomplex *, integer *, doublecomplex *, doublereal *, doublecomplex *, integer *, doublereal *, doublereal *, logical *, integer *, logical *, ftnlen, ftnlen); doublereal rbets; logical reset; char trans[1]; logical upper; char uplos[1]; extern /* Subroutine */ int zher2k_(char *, char *, integer *, integer *, doublecomplex *, doublecomplex *, integer *, doublecomplex *, integer *, doublereal *, doublecomplex *, integer *, ftnlen, ftnlen), zsyr2k_(char *, char *, integer *, integer *, doublecomplex *, doublecomplex *, integer *, doublecomplex *, integer *, doublecomplex *, doublecomplex *, integer *, ftnlen, ftnlen); doublereal errmax; extern logical lzeres_(char *, char *, integer *, integer *, doublecomplex *, doublecomplex *, integer *, ftnlen, ftnlen); char transs[1], transt[1]; /* Fortran I/O blocks */ static cilist io___334 = { 0, 0, 0, fmt_9994, 0 }; static cilist io___335 = { 0, 0, 0, fmt_9993, 0 }; static cilist io___336 = { 0, 0, 0, fmt_9992, 0 }; static cilist io___339 = { 0, 0, 0, fmt_9998, 0 }; static cilist io___347 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___348 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___349 = { 0, 0, 0, fmt_9995, 0 }; static cilist io___350 = { 0, 0, 0, fmt_9996, 0 }; static cilist io___351 = { 0, 0, 0, fmt_9994, 0 }; static cilist io___352 = { 0, 0, 0, fmt_9993, 0 }; /* Tests ZHER2K and ZSYR2K. */ /* Auxiliary routine for test program for Level 3 Blas. */ /* -- Written on 8-February-1989. */ /* Jack Dongarra, Argonne National Laboratory. */ /* Iain Duff, AERE Harwell. */ /* Jeremy Du Croz, Numerical Algorithms Group Ltd. */ /* Sven Hammarling, Numerical Algorithms Group Ltd. */ /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Scalars .. */ /* .. Local Arrays .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. Scalars in Common .. */ /* .. Common blocks .. */ /* .. Data statements .. */ /* Parameter adjustments */ --idim; --alf; --bet; --w; --g; --ct; --cs; --cc; c_dim1 = *nmax; c_offset = 1 + c_dim1; c__ -= c_offset; --bs; --bb; --as; --aa; --ab; /* Function Body */ /* .. Executable Statements .. */ conj = s_cmp(sname + 1, "HE", (ftnlen)2, (ftnlen)2) == 0; nargs = 12; nc = 0; reset = TRUE_; errmax = 0.; i__1 = *nidim; for (in = 1; in <= i__1; ++in) { n = idim[in]; /* Set LDC to 1 more than minimum value if room. */ ldc = n; if (ldc < *nmax) { ++ldc; } /* Skip tests if not enough room. */ if (ldc > *nmax) { goto L130; } lcc = ldc * n; i__2 = *nidim; for (ik = 1; ik <= i__2; ++ik) { k = idim[ik]; for (ict = 1; ict <= 2; ++ict) { *(unsigned char *)trans = *(unsigned char *)&icht[ict - 1]; tran = *(unsigned char *)trans == 'C'; if (tran && ! conj) { *(unsigned char *)trans = 'T'; } if (tran) { ma = k; na = n; } else { ma = n; na = k; } /* Set LDA to 1 more than minimum value if room. */ lda = ma; if (lda < *nmax) { ++lda; } /* Skip tests if not enough room. */ if (lda > *nmax) { goto L110; } laa = lda * na; /* Generate the matrix A. */ if (tran) { i__3 = *nmax << 1; zmake_("GE", " ", " ", &ma, &na, &ab[1], &i__3, &aa[1], & lda, &reset, &c_b1, (ftnlen)2, (ftnlen)1, (ftnlen) 1); } else { zmake_("GE", " ", " ", &ma, &na, &ab[1], nmax, &aa[1], & lda, &reset, &c_b1, (ftnlen)2, (ftnlen)1, (ftnlen) 1); } /* Generate the matrix B. */ ldb = lda; lbb = laa; if (tran) { i__3 = *nmax << 1; zmake_("GE", " ", " ", &ma, &na, &ab[k + 1], &i__3, &bb[1] , &ldb, &reset, &c_b1, (ftnlen)2, (ftnlen)1, ( ftnlen)1); } else { zmake_("GE", " ", " ", &ma, &na, &ab[k * *nmax + 1], nmax, &bb[1], &ldb, &reset, &c_b1, (ftnlen)2, (ftnlen) 1, (ftnlen)1); } for (icu = 1; icu <= 2; ++icu) { *(unsigned char *)uplo = *(unsigned char *)&ichu[icu - 1]; upper = *(unsigned char *)uplo == 'U'; i__3 = *nalf; for (ia = 1; ia <= i__3; ++ia) { i__4 = ia; alpha.r = alf[i__4].r, alpha.i = alf[i__4].i; i__4 = *nbet; for (ib = 1; ib <= i__4; ++ib) { i__5 = ib; beta.r = bet[i__5].r, beta.i = bet[i__5].i; if (conj) { rbeta = beta.r; z__1.r = rbeta, z__1.i = 0.; beta.r = z__1.r, beta.i = z__1.i; } null = n <= 0; if (conj) { null = null || (k <= 0 || alpha.r == 0. && alpha.i == 0.) && rbeta == 1.; } /* Generate the matrix C. */ zmake_(sname + 1, uplo, " ", &n, &n, &c__[ c_offset], nmax, &cc[1], &ldc, &reset, & c_b1, (ftnlen)2, (ftnlen)1, (ftnlen)1); ++nc; /* Save every datum before calling the subroutine. */ *(unsigned char *)uplos = *(unsigned char *)uplo; *(unsigned char *)transs = *(unsigned char *) trans; ns = n; ks = k; als.r = alpha.r, als.i = alpha.i; i__5 = laa; for (i__ = 1; i__ <= i__5; ++i__) { i__6 = i__; i__7 = i__; as[i__6].r = aa[i__7].r, as[i__6].i = aa[i__7] .i; /* L10: */ } ldas = lda; i__5 = lbb; for (i__ = 1; i__ <= i__5; ++i__) { i__6 = i__; i__7 = i__; bs[i__6].r = bb[i__7].r, bs[i__6].i = bb[i__7] .i; /* L20: */ } ldbs = ldb; if (conj) { rbets = rbeta; } else { bets.r = beta.r, bets.i = beta.i; } i__5 = lcc; for (i__ = 1; i__ <= i__5; ++i__) { i__6 = i__; i__7 = i__; cs[i__6].r = cc[i__7].r, cs[i__6].i = cc[i__7] .i; /* L30: */ } ldcs = ldc; /* Call the subroutine. */ if (conj) { if (*trace) { io___334.ciunit = *ntra; s_wsfe(&io___334); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof( integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&k, (ftnlen)sizeof( integer)); do_fio(&c__2, (char *)&alpha, (ftnlen) sizeof(doublereal)); do_fio(&c__1, (char *)&lda, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&ldb, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&rbeta, (ftnlen) sizeof(doublereal)); do_fio(&c__1, (char *)&ldc, (ftnlen) sizeof(integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } zher2k_(uplo, trans, &n, &k, &alpha, &aa[1], & lda, &bb[1], &ldb, &rbeta, &cc[1], & ldc, (ftnlen)1, (ftnlen)1); } else { if (*trace) { io___335.ciunit = *ntra; s_wsfe(&io___335); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof( integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&k, (ftnlen)sizeof( integer)); do_fio(&c__2, (char *)&alpha, (ftnlen) sizeof(doublereal)); do_fio(&c__1, (char *)&lda, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&ldb, (ftnlen) sizeof(integer)); do_fio(&c__2, (char *)&beta, (ftnlen) sizeof(doublereal)); do_fio(&c__1, (char *)&ldc, (ftnlen) sizeof(integer)); e_wsfe(); } if (*rewi) { al__1.aerr = 0; al__1.aunit = *ntra; f_rew(&al__1); } zsyr2k_(uplo, trans, &n, &k, &alpha, &aa[1], & lda, &bb[1], &ldb, &beta, &cc[1], & ldc, (ftnlen)1, (ftnlen)1); } /* Check if error-exit was taken incorrectly. */ if (! infoc_1.ok) { io___336.ciunit = *nout; s_wsfe(&io___336); e_wsfe(); *fatal = TRUE_; goto L150; } /* See what data changed inside subroutines. */ isame[0] = *(unsigned char *)uplos == *(unsigned char *)uplo; isame[1] = *(unsigned char *)transs == *(unsigned char *)trans; isame[2] = ns == n; isame[3] = ks == k; isame[4] = als.r == alpha.r && als.i == alpha.i; isame[5] = lze_(&as[1], &aa[1], &laa); isame[6] = ldas == lda; isame[7] = lze_(&bs[1], &bb[1], &lbb); isame[8] = ldbs == ldb; if (conj) { isame[9] = rbets == rbeta; } else { isame[9] = bets.r == beta.r && bets.i == beta.i; } if (null) { isame[10] = lze_(&cs[1], &cc[1], &lcc); } else { isame[10] = lzeres_("HE", uplo, &n, &n, &cs[1] , &cc[1], &ldc, (ftnlen)2, (ftnlen)1); } isame[11] = ldcs == ldc; /* If data was incorrectly changed, report and */ /* return. */ same = TRUE_; i__5 = nargs; for (i__ = 1; i__ <= i__5; ++i__) { same = same && isame[i__ - 1]; if (! isame[i__ - 1]) { io___339.ciunit = *nout; s_wsfe(&io___339); do_fio(&c__1, (char *)&i__, (ftnlen) sizeof(integer)); e_wsfe(); } /* L40: */ } if (! same) { *fatal = TRUE_; goto L150; } if (! null) { /* Check the result column by column. */ if (conj) { *(unsigned char *)transt = 'C'; } else { *(unsigned char *)transt = 'T'; } jjab = 1; jc = 1; i__5 = n; for (j = 1; j <= i__5; ++j) { if (upper) { jj = 1; lj = j; } else { jj = j; lj = n - j + 1; } if (tran) { i__6 = k; for (i__ = 1; i__ <= i__6; ++i__) { i__7 = i__; i__8 = (j - 1 << 1) * *nmax + k + i__; z__1.r = alpha.r * ab[i__8].r - alpha.i * ab[i__8].i, z__1.i = alpha.r * ab[ i__8].i + alpha.i * ab[ i__8].r; w[i__7].r = z__1.r, w[i__7].i = z__1.i; if (conj) { i__7 = k + i__; d_cnjg(&z__2, &alpha); i__8 = (j - 1 << 1) * *nmax + i__; z__1.r = z__2.r * ab[i__8].r - z__2.i * ab[i__8].i, z__1.i = z__2.r * ab[i__8].i + z__2.i * ab[ i__8].r; w[i__7].r = z__1.r, w[i__7].i = z__1.i; } else { i__7 = k + i__; i__8 = (j - 1 << 1) * *nmax + i__; z__1.r = alpha.r * ab[i__8].r - alpha.i * ab[i__8] .i, z__1.i = alpha.r * ab[i__8].i + alpha.i * ab[i__8].r; w[i__7].r = z__1.r, w[i__7].i = z__1.i; } /* L50: */ } i__6 = k << 1; i__7 = *nmax << 1; i__8 = *nmax << 1; zmmch_(transt, "N", &lj, &c__1, &i__6, &c_b2, &ab[jjab], &i__7, &w[ 1], &i__8, &beta, &c__[jj + j * c_dim1], nmax, &ct[1], &g[1] , &cc[jc], &ldc, eps, &err, fatal, nout, &c_true, (ftnlen) 1, (ftnlen)1); } else { i__6 = k; for (i__ = 1; i__ <= i__6; ++i__) { if (conj) { i__7 = i__; d_cnjg(&z__2, &ab[(k + i__ - 1) * *nmax + j]); z__1.r = alpha.r * z__2.r - alpha.i * z__2.i, z__1.i = alpha.r * z__2.i + alpha.i * z__2.r; w[i__7].r = z__1.r, w[i__7].i = z__1.i; i__7 = k + i__; i__8 = (i__ - 1) * *nmax + j; z__2.r = alpha.r * ab[i__8].r - alpha.i * ab[i__8] .i, z__2.i = alpha.r * ab[i__8].i + alpha.i * ab[i__8].r; d_cnjg(&z__1, &z__2); w[i__7].r = z__1.r, w[i__7].i = z__1.i; } else { i__7 = i__; i__8 = (k + i__ - 1) * *nmax + j; z__1.r = alpha.r * ab[i__8].r - alpha.i * ab[i__8] .i, z__1.i = alpha.r * ab[i__8].i + alpha.i * ab[i__8].r; w[i__7].r = z__1.r, w[i__7].i = z__1.i; i__7 = k + i__; i__8 = (i__ - 1) * *nmax + j; z__1.r = alpha.r * ab[i__8].r - alpha.i * ab[i__8] .i, z__1.i = alpha.r * ab[i__8].i + alpha.i * ab[i__8].r; w[i__7].r = z__1.r, w[i__7].i = z__1.i; } /* L60: */ } i__6 = k << 1; i__7 = *nmax << 1; zmmch_("N", "N", &lj, &c__1, &i__6, & c_b2, &ab[jj], nmax, &w[1], & i__7, &beta, &c__[jj + j * c_dim1], nmax, &ct[1], &g[1], &cc[jc], &ldc, eps, &err, fatal, nout, &c_true, (ftnlen) 1, (ftnlen)1); } if (upper) { jc += ldc; } else { jc = jc + ldc + 1; if (tran) { jjab += *nmax << 1; } } errmax = max(errmax,err); /* If got really bad answer, report and */ /* return. */ if (*fatal) { goto L140; } /* L70: */ } } /* L80: */ } /* L90: */ } /* L100: */ } L110: ; } /* L120: */ } L130: ; } /* Report result. */ if (errmax < *thresh) { io___347.ciunit = *nout; s_wsfe(&io___347); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); e_wsfe(); } else { io___348.ciunit = *nout; s_wsfe(&io___348); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&errmax, (ftnlen)sizeof(doublereal)); e_wsfe(); } goto L160; L140: if (n > 1) { io___349.ciunit = *nout; s_wsfe(&io___349); do_fio(&c__1, (char *)&j, (ftnlen)sizeof(integer)); e_wsfe(); } L150: io___350.ciunit = *nout; s_wsfe(&io___350); do_fio(&c__1, sname, (ftnlen)6); e_wsfe(); if (conj) { io___351.ciunit = *nout; s_wsfe(&io___351); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&k, (ftnlen)sizeof(integer)); do_fio(&c__2, (char *)&alpha, (ftnlen)sizeof(doublereal)); do_fio(&c__1, (char *)&lda, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&ldb, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&rbeta, (ftnlen)sizeof(doublereal)); do_fio(&c__1, (char *)&ldc, (ftnlen)sizeof(integer)); e_wsfe(); } else { io___352.ciunit = *nout; s_wsfe(&io___352); do_fio(&c__1, (char *)&nc, (ftnlen)sizeof(integer)); do_fio(&c__1, sname, (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, trans, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&k, (ftnlen)sizeof(integer)); do_fio(&c__2, (char *)&alpha, (ftnlen)sizeof(doublereal)); do_fio(&c__1, (char *)&lda, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&ldb, (ftnlen)sizeof(integer)); do_fio(&c__2, (char *)&beta, (ftnlen)sizeof(doublereal)); do_fio(&c__1, (char *)&ldc, (ftnlen)sizeof(integer)); e_wsfe(); } L160: return 0; /* End of ZCHK5. */ } /* zchk5_ */ /* Subroutine */ int zchke_(integer *isnum, char *srnamt, integer *nout, ftnlen srnamt_len) { /* Format strings */ static char fmt_9999[] = "(\002 \002,a6,\002 PASSED THE TESTS OF ERROR-E" "XITS\002)"; static char fmt_9998[] = "(\002 ******* \002,a6,\002 FAILED THE TESTS OF" " ERROR-EXITS *****\002,\002**\002)"; /* Builtin functions */ integer s_wsfe(cilist *), do_fio(integer *, char *, ftnlen), e_wsfe(void); /* Local variables */ doublecomplex a[2] /* was [2][1] */, b[2] /* was [2][1] */, c__[2] /* was [2][1] */, beta, alpha; doublereal rbeta; extern /* Subroutine */ int zgemm_(char *, char *, integer *, integer *, integer *, doublecomplex *, doublecomplex *, integer *, doublecomplex *, integer *, doublecomplex *, doublecomplex *, integer *, ftnlen, ftnlen), zhemm_(char *, char *, integer *, integer *, doublecomplex *, doublecomplex *, integer *, doublecomplex *, integer *, doublecomplex *, doublecomplex *, integer *, ftnlen, ftnlen), zherk_(char *, char *, integer *, integer *, doublereal *, doublecomplex *, integer *, doublereal *, doublecomplex *, integer *, ftnlen, ftnlen), ztrmm_(char *, char *, char *, char *, integer *, integer *, doublecomplex *, doublecomplex *, integer *, doublecomplex *, integer *, ftnlen, ftnlen, ftnlen, ftnlen), zsymm_(char *, char *, integer *, integer *, doublecomplex *, doublecomplex *, integer *, doublecomplex *, integer *, doublecomplex *, doublecomplex *, integer *, ftnlen, ftnlen), ztrsm_(char *, char *, char *, char *, integer *, integer *, doublecomplex *, doublecomplex *, integer * , doublecomplex *, integer *, ftnlen, ftnlen, ftnlen, ftnlen), zsyrk_(char *, char *, integer *, integer *, doublecomplex *, doublecomplex *, integer *, doublecomplex *, doublecomplex *, integer *, ftnlen, ftnlen), zher2k_(char *, char *, integer *, integer *, doublecomplex *, doublecomplex *, integer *, doublecomplex *, integer *, doublereal *, doublecomplex *, integer *, ftnlen, ftnlen), zsyr2k_(char *, char *, integer *, integer *, doublecomplex *, doublecomplex *, integer *, doublecomplex *, integer *, doublecomplex *, doublecomplex *, integer *, ftnlen, ftnlen); doublereal ralpha; extern /* Subroutine */ int chkxer_(char *, integer *, integer *, logical *, logical *, ftnlen); /* Fortran I/O blocks */ static cilist io___360 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___361 = { 0, 0, 0, fmt_9998, 0 }; /* Tests the error exits from the Level 3 Blas. */ /* Requires a special version of the error-handling routine XERBLA. */ /* A, B and C should not need to be defined. */ /* Auxiliary routine for test program for Level 3 Blas. */ /* -- Written on 8-February-1989. */ /* Jack Dongarra, Argonne National Laboratory. */ /* Iain Duff, AERE Harwell. */ /* Jeremy Du Croz, Numerical Algorithms Group Ltd. */ /* Sven Hammarling, Numerical Algorithms Group Ltd. */ /* 3-19-92: Initialize ALPHA, BETA, RALPHA, and RBETA (eca) */ /* 3-19-92: Fix argument 12 in calls to ZSYMM and ZHEMM */ /* with INFOT = 9 (eca) */ /* 10-9-00: Declared INTRINSIC DCMPLX (susan) */ /* .. Scalar Arguments .. */ /* .. Scalars in Common .. */ /* .. Parameters .. */ /* .. Local Scalars .. */ /* .. Local Arrays .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. Common blocks .. */ /* .. Executable Statements .. */ /* OK is set to .FALSE. by the special version of XERBLA or by CHKXER */ /* if anything is wrong. */ infoc_1.ok = TRUE_; /* LERR is set to .TRUE. by the special version of XERBLA each time */ /* it is called, and is then tested and re-set by CHKXER. */ infoc_1.lerr = FALSE_; /* Initialize ALPHA, BETA, RALPHA, and RBETA. */ alpha.r = 1., alpha.i = -1.; beta.r = 2., beta.i = -2.; ralpha = 1.f; rbeta = 2.f; switch (*isnum) { case 1: goto L10; case 2: goto L20; case 3: goto L30; case 4: goto L40; case 5: goto L50; case 6: goto L60; case 7: goto L70; case 8: goto L80; case 9: goto L90; } L10: infoc_1.infot = 1; zgemm_("/", "N", &c__0, &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 1; zgemm_("/", "C", &c__0, &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 1; zgemm_("/", "T", &c__0, &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; zgemm_("N", "/", &c__0, &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; zgemm_("C", "/", &c__0, &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; zgemm_("T", "/", &c__0, &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; zgemm_("N", "N", &c_n1, &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; zgemm_("N", "C", &c_n1, &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; zgemm_("N", "T", &c_n1, &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; zgemm_("C", "N", &c_n1, &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; zgemm_("C", "C", &c_n1, &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; zgemm_("C", "T", &c_n1, &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; zgemm_("T", "N", &c_n1, &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; zgemm_("T", "C", &c_n1, &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; zgemm_("T", "T", &c_n1, &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; zgemm_("N", "N", &c__0, &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; zgemm_("N", "C", &c__0, &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; zgemm_("N", "T", &c__0, &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; zgemm_("C", "N", &c__0, &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; zgemm_("C", "C", &c__0, &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; zgemm_("C", "T", &c__0, &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; zgemm_("T", "N", &c__0, &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; zgemm_("T", "C", &c__0, &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; zgemm_("T", "T", &c__0, &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; zgemm_("N", "N", &c__0, &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; zgemm_("N", "C", &c__0, &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; zgemm_("N", "T", &c__0, &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; zgemm_("C", "N", &c__0, &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; zgemm_("C", "C", &c__0, &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; zgemm_("C", "T", &c__0, &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; zgemm_("T", "N", &c__0, &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; zgemm_("T", "C", &c__0, &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; zgemm_("T", "T", &c__0, &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 8; zgemm_("N", "N", &c__2, &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__2, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 8; zgemm_("N", "C", &c__2, &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__2, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 8; zgemm_("N", "T", &c__2, &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__2, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 8; zgemm_("C", "N", &c__0, &c__0, &c__2, &alpha, a, &c__1, b, &c__2, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 8; zgemm_("C", "C", &c__0, &c__0, &c__2, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 8; zgemm_("C", "T", &c__0, &c__0, &c__2, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 8; zgemm_("T", "N", &c__0, &c__0, &c__2, &alpha, a, &c__1, b, &c__2, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 8; zgemm_("T", "C", &c__0, &c__0, &c__2, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 8; zgemm_("T", "T", &c__0, &c__0, &c__2, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 10; zgemm_("N", "N", &c__0, &c__0, &c__2, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 10; zgemm_("C", "N", &c__0, &c__0, &c__2, &alpha, a, &c__2, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 10; zgemm_("T", "N", &c__0, &c__0, &c__2, &alpha, a, &c__2, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 10; zgemm_("N", "C", &c__0, &c__2, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 10; zgemm_("C", "C", &c__0, &c__2, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 10; zgemm_("T", "C", &c__0, &c__2, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 10; zgemm_("N", "T", &c__0, &c__2, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 10; zgemm_("C", "T", &c__0, &c__2, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 10; zgemm_("T", "T", &c__0, &c__2, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 13; zgemm_("N", "N", &c__2, &c__0, &c__0, &alpha, a, &c__2, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 13; zgemm_("N", "C", &c__2, &c__0, &c__0, &alpha, a, &c__2, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 13; zgemm_("N", "T", &c__2, &c__0, &c__0, &alpha, a, &c__2, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 13; zgemm_("C", "N", &c__2, &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 13; zgemm_("C", "C", &c__2, &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 13; zgemm_("C", "T", &c__2, &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 13; zgemm_("T", "N", &c__2, &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 13; zgemm_("T", "C", &c__2, &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 13; zgemm_("T", "T", &c__2, &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, &c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L100; L20: infoc_1.infot = 1; zhemm_("/", "U", &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; zhemm_("L", "/", &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; zhemm_("L", "U", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; zhemm_("R", "U", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; zhemm_("L", "L", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; zhemm_("R", "L", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; zhemm_("L", "U", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; zhemm_("R", "U", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; zhemm_("L", "L", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; zhemm_("R", "L", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; zhemm_("L", "U", &c__2, &c__0, &alpha, a, &c__1, b, &c__2, &beta, c__, & c__2, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; zhemm_("R", "U", &c__0, &c__2, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; zhemm_("L", "L", &c__2, &c__0, &alpha, a, &c__1, b, &c__2, &beta, c__, & c__2, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; zhemm_("R", "L", &c__0, &c__2, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; zhemm_("L", "U", &c__2, &c__0, &alpha, a, &c__2, b, &c__1, &beta, c__, & c__2, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; zhemm_("R", "U", &c__2, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__2, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; zhemm_("L", "L", &c__2, &c__0, &alpha, a, &c__2, b, &c__1, &beta, c__, & c__2, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; zhemm_("R", "L", &c__2, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__2, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 12; zhemm_("L", "U", &c__2, &c__0, &alpha, a, &c__2, b, &c__2, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 12; zhemm_("R", "U", &c__2, &c__0, &alpha, a, &c__1, b, &c__2, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 12; zhemm_("L", "L", &c__2, &c__0, &alpha, a, &c__2, b, &c__2, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 12; zhemm_("R", "L", &c__2, &c__0, &alpha, a, &c__1, b, &c__2, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L100; L30: infoc_1.infot = 1; zsymm_("/", "U", &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; zsymm_("L", "/", &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; zsymm_("L", "U", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; zsymm_("R", "U", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; zsymm_("L", "L", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; zsymm_("R", "L", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; zsymm_("L", "U", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; zsymm_("R", "U", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; zsymm_("L", "L", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; zsymm_("R", "L", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; zsymm_("L", "U", &c__2, &c__0, &alpha, a, &c__1, b, &c__2, &beta, c__, & c__2, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; zsymm_("R", "U", &c__0, &c__2, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; zsymm_("L", "L", &c__2, &c__0, &alpha, a, &c__1, b, &c__2, &beta, c__, & c__2, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; zsymm_("R", "L", &c__0, &c__2, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; zsymm_("L", "U", &c__2, &c__0, &alpha, a, &c__2, b, &c__1, &beta, c__, & c__2, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; zsymm_("R", "U", &c__2, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__2, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; zsymm_("L", "L", &c__2, &c__0, &alpha, a, &c__2, b, &c__1, &beta, c__, & c__2, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; zsymm_("R", "L", &c__2, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__2, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 12; zsymm_("L", "U", &c__2, &c__0, &alpha, a, &c__2, b, &c__2, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 12; zsymm_("R", "U", &c__2, &c__0, &alpha, a, &c__1, b, &c__2, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 12; zsymm_("L", "L", &c__2, &c__0, &alpha, a, &c__2, b, &c__2, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 12; zsymm_("R", "L", &c__2, &c__0, &alpha, a, &c__1, b, &c__2, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L100; L40: infoc_1.infot = 1; ztrmm_("/", "U", "N", "N", &c__0, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; ztrmm_("L", "/", "N", "N", &c__0, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; ztrmm_("L", "U", "/", "N", &c__0, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; ztrmm_("L", "U", "N", "/", &c__0, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; ztrmm_("L", "U", "N", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; ztrmm_("L", "U", "C", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; ztrmm_("L", "U", "T", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; ztrmm_("R", "U", "N", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; ztrmm_("R", "U", "C", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; ztrmm_("R", "U", "T", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; ztrmm_("L", "L", "N", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; ztrmm_("L", "L", "C", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; ztrmm_("L", "L", "T", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; ztrmm_("R", "L", "N", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; ztrmm_("R", "L", "C", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; ztrmm_("R", "L", "T", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; ztrmm_("L", "U", "N", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; ztrmm_("L", "U", "C", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; ztrmm_("L", "U", "T", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; ztrmm_("R", "U", "N", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; ztrmm_("R", "U", "C", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; ztrmm_("R", "U", "T", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; ztrmm_("L", "L", "N", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; ztrmm_("L", "L", "C", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; ztrmm_("L", "L", "T", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; ztrmm_("R", "L", "N", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; ztrmm_("R", "L", "C", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; ztrmm_("R", "L", "T", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; ztrmm_("L", "U", "N", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__2, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; ztrmm_("L", "U", "C", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__2, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; ztrmm_("L", "U", "T", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__2, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; ztrmm_("R", "U", "N", "N", &c__0, &c__2, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; ztrmm_("R", "U", "C", "N", &c__0, &c__2, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; ztrmm_("R", "U", "T", "N", &c__0, &c__2, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; ztrmm_("L", "L", "N", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__2, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; ztrmm_("L", "L", "C", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__2, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; ztrmm_("L", "L", "T", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__2, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; ztrmm_("R", "L", "N", "N", &c__0, &c__2, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; ztrmm_("R", "L", "C", "N", &c__0, &c__2, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; ztrmm_("R", "L", "T", "N", &c__0, &c__2, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; ztrmm_("L", "U", "N", "N", &c__2, &c__0, &alpha, a, &c__2, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; ztrmm_("L", "U", "C", "N", &c__2, &c__0, &alpha, a, &c__2, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; ztrmm_("L", "U", "T", "N", &c__2, &c__0, &alpha, a, &c__2, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; ztrmm_("R", "U", "N", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; ztrmm_("R", "U", "C", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; ztrmm_("R", "U", "T", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; ztrmm_("L", "L", "N", "N", &c__2, &c__0, &alpha, a, &c__2, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; ztrmm_("L", "L", "C", "N", &c__2, &c__0, &alpha, a, &c__2, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; ztrmm_("L", "L", "T", "N", &c__2, &c__0, &alpha, a, &c__2, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; ztrmm_("R", "L", "N", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; ztrmm_("R", "L", "C", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; ztrmm_("R", "L", "T", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L100; L50: infoc_1.infot = 1; ztrsm_("/", "U", "N", "N", &c__0, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; ztrsm_("L", "/", "N", "N", &c__0, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; ztrsm_("L", "U", "/", "N", &c__0, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; ztrsm_("L", "U", "N", "/", &c__0, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; ztrsm_("L", "U", "N", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; ztrsm_("L", "U", "C", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; ztrsm_("L", "U", "T", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; ztrsm_("R", "U", "N", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; ztrsm_("R", "U", "C", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; ztrsm_("R", "U", "T", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; ztrsm_("L", "L", "N", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; ztrsm_("L", "L", "C", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; ztrsm_("L", "L", "T", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; ztrsm_("R", "L", "N", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; ztrsm_("R", "L", "C", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 5; ztrsm_("R", "L", "T", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; ztrsm_("L", "U", "N", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; ztrsm_("L", "U", "C", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; ztrsm_("L", "U", "T", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; ztrsm_("R", "U", "N", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; ztrsm_("R", "U", "C", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; ztrsm_("R", "U", "T", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; ztrsm_("L", "L", "N", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; ztrsm_("L", "L", "C", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; ztrsm_("L", "L", "T", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; ztrsm_("R", "L", "N", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; ztrsm_("R", "L", "C", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 6; ztrsm_("R", "L", "T", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; ztrsm_("L", "U", "N", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__2, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; ztrsm_("L", "U", "C", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__2, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; ztrsm_("L", "U", "T", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__2, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; ztrsm_("R", "U", "N", "N", &c__0, &c__2, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; ztrsm_("R", "U", "C", "N", &c__0, &c__2, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; ztrsm_("R", "U", "T", "N", &c__0, &c__2, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; ztrsm_("L", "L", "N", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__2, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; ztrsm_("L", "L", "C", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__2, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; ztrsm_("L", "L", "T", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__2, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; ztrsm_("R", "L", "N", "N", &c__0, &c__2, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; ztrsm_("R", "L", "C", "N", &c__0, &c__2, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; ztrsm_("R", "L", "T", "N", &c__0, &c__2, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; ztrsm_("L", "U", "N", "N", &c__2, &c__0, &alpha, a, &c__2, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; ztrsm_("L", "U", "C", "N", &c__2, &c__0, &alpha, a, &c__2, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; ztrsm_("L", "U", "T", "N", &c__2, &c__0, &alpha, a, &c__2, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; ztrsm_("R", "U", "N", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; ztrsm_("R", "U", "C", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; ztrsm_("R", "U", "T", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; ztrsm_("L", "L", "N", "N", &c__2, &c__0, &alpha, a, &c__2, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; ztrsm_("L", "L", "C", "N", &c__2, &c__0, &alpha, a, &c__2, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; ztrsm_("L", "L", "T", "N", &c__2, &c__0, &alpha, a, &c__2, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; ztrsm_("R", "L", "N", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; ztrsm_("R", "L", "C", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 11; ztrsm_("R", "L", "T", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__1, ( ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L100; L60: infoc_1.infot = 1; zherk_("/", "N", &c__0, &c__0, &ralpha, a, &c__1, &rbeta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; zherk_("U", "T", &c__0, &c__0, &ralpha, a, &c__1, &rbeta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; zherk_("U", "N", &c_n1, &c__0, &ralpha, a, &c__1, &rbeta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; zherk_("U", "C", &c_n1, &c__0, &ralpha, a, &c__1, &rbeta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; zherk_("L", "N", &c_n1, &c__0, &ralpha, a, &c__1, &rbeta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; zherk_("L", "C", &c_n1, &c__0, &ralpha, a, &c__1, &rbeta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; zherk_("U", "N", &c__0, &c_n1, &ralpha, a, &c__1, &rbeta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; zherk_("U", "C", &c__0, &c_n1, &ralpha, a, &c__1, &rbeta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; zherk_("L", "N", &c__0, &c_n1, &ralpha, a, &c__1, &rbeta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; zherk_("L", "C", &c__0, &c_n1, &ralpha, a, &c__1, &rbeta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; zherk_("U", "N", &c__2, &c__0, &ralpha, a, &c__1, &rbeta, c__, &c__2, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; zherk_("U", "C", &c__0, &c__2, &ralpha, a, &c__1, &rbeta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; zherk_("L", "N", &c__2, &c__0, &ralpha, a, &c__1, &rbeta, c__, &c__2, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; zherk_("L", "C", &c__0, &c__2, &ralpha, a, &c__1, &rbeta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 10; zherk_("U", "N", &c__2, &c__0, &ralpha, a, &c__2, &rbeta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 10; zherk_("U", "C", &c__2, &c__0, &ralpha, a, &c__1, &rbeta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 10; zherk_("L", "N", &c__2, &c__0, &ralpha, a, &c__2, &rbeta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 10; zherk_("L", "C", &c__2, &c__0, &ralpha, a, &c__1, &rbeta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L100; L70: infoc_1.infot = 1; zsyrk_("/", "N", &c__0, &c__0, &alpha, a, &c__1, &beta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; zsyrk_("U", "C", &c__0, &c__0, &alpha, a, &c__1, &beta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; zsyrk_("U", "N", &c_n1, &c__0, &alpha, a, &c__1, &beta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; zsyrk_("U", "T", &c_n1, &c__0, &alpha, a, &c__1, &beta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; zsyrk_("L", "N", &c_n1, &c__0, &alpha, a, &c__1, &beta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; zsyrk_("L", "T", &c_n1, &c__0, &alpha, a, &c__1, &beta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; zsyrk_("U", "N", &c__0, &c_n1, &alpha, a, &c__1, &beta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; zsyrk_("U", "T", &c__0, &c_n1, &alpha, a, &c__1, &beta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; zsyrk_("L", "N", &c__0, &c_n1, &alpha, a, &c__1, &beta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; zsyrk_("L", "T", &c__0, &c_n1, &alpha, a, &c__1, &beta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; zsyrk_("U", "N", &c__2, &c__0, &alpha, a, &c__1, &beta, c__, &c__2, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; zsyrk_("U", "T", &c__0, &c__2, &alpha, a, &c__1, &beta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; zsyrk_("L", "N", &c__2, &c__0, &alpha, a, &c__1, &beta, c__, &c__2, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; zsyrk_("L", "T", &c__0, &c__2, &alpha, a, &c__1, &beta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 10; zsyrk_("U", "N", &c__2, &c__0, &alpha, a, &c__2, &beta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 10; zsyrk_("U", "T", &c__2, &c__0, &alpha, a, &c__1, &beta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 10; zsyrk_("L", "N", &c__2, &c__0, &alpha, a, &c__2, &beta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 10; zsyrk_("L", "T", &c__2, &c__0, &alpha, a, &c__1, &beta, c__, &c__1, ( ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L100; L80: infoc_1.infot = 1; zher2k_("/", "N", &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &rbeta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; zher2k_("U", "T", &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &rbeta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; zher2k_("U", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, &rbeta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; zher2k_("U", "C", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, &rbeta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; zher2k_("L", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, &rbeta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; zher2k_("L", "C", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, &rbeta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; zher2k_("U", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, &rbeta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; zher2k_("U", "C", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, &rbeta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; zher2k_("L", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, &rbeta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; zher2k_("L", "C", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, &rbeta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; zher2k_("U", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__1, &rbeta, c__, & c__2, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; zher2k_("U", "C", &c__0, &c__2, &alpha, a, &c__1, b, &c__1, &rbeta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; zher2k_("L", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__1, &rbeta, c__, & c__2, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; zher2k_("L", "C", &c__0, &c__2, &alpha, a, &c__1, b, &c__1, &rbeta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; zher2k_("U", "N", &c__2, &c__0, &alpha, a, &c__2, b, &c__1, &rbeta, c__, & c__2, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; zher2k_("U", "C", &c__0, &c__2, &alpha, a, &c__2, b, &c__1, &rbeta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; zher2k_("L", "N", &c__2, &c__0, &alpha, a, &c__2, b, &c__1, &rbeta, c__, & c__2, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; zher2k_("L", "C", &c__0, &c__2, &alpha, a, &c__2, b, &c__1, &rbeta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 12; zher2k_("U", "N", &c__2, &c__0, &alpha, a, &c__2, b, &c__2, &rbeta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 12; zher2k_("U", "C", &c__2, &c__0, &alpha, a, &c__1, b, &c__1, &rbeta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 12; zher2k_("L", "N", &c__2, &c__0, &alpha, a, &c__2, b, &c__2, &rbeta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 12; zher2k_("L", "C", &c__2, &c__0, &alpha, a, &c__1, b, &c__1, &rbeta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); goto L100; L90: infoc_1.infot = 1; zsyr2k_("/", "N", &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 2; zsyr2k_("U", "C", &c__0, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; zsyr2k_("U", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; zsyr2k_("U", "T", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; zsyr2k_("L", "N", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 3; zsyr2k_("L", "T", &c_n1, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; zsyr2k_("U", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; zsyr2k_("U", "T", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; zsyr2k_("L", "N", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 4; zsyr2k_("L", "T", &c__0, &c_n1, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; zsyr2k_("U", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__2, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; zsyr2k_("U", "T", &c__0, &c__2, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; zsyr2k_("L", "N", &c__2, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__2, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 7; zsyr2k_("L", "T", &c__0, &c__2, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; zsyr2k_("U", "N", &c__2, &c__0, &alpha, a, &c__2, b, &c__1, &beta, c__, & c__2, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; zsyr2k_("U", "T", &c__0, &c__2, &alpha, a, &c__2, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; zsyr2k_("L", "N", &c__2, &c__0, &alpha, a, &c__2, b, &c__1, &beta, c__, & c__2, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 9; zsyr2k_("L", "T", &c__0, &c__2, &alpha, a, &c__2, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 12; zsyr2k_("U", "N", &c__2, &c__0, &alpha, a, &c__2, b, &c__2, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 12; zsyr2k_("U", "T", &c__2, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 12; zsyr2k_("L", "N", &c__2, &c__0, &alpha, a, &c__2, b, &c__2, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); infoc_1.infot = 12; zsyr2k_("L", "T", &c__2, &c__0, &alpha, a, &c__1, b, &c__1, &beta, c__, & c__1, (ftnlen)1, (ftnlen)1); chkxer_(srnamt, &infoc_1.infot, nout, &infoc_1.lerr, &infoc_1.ok, (ftnlen) 6); L100: if (infoc_1.ok) { io___360.ciunit = *nout; s_wsfe(&io___360); do_fio(&c__1, srnamt, (ftnlen)6); e_wsfe(); } else { io___361.ciunit = *nout; s_wsfe(&io___361); do_fio(&c__1, srnamt, (ftnlen)6); e_wsfe(); } return 0; /* End of ZCHKE. */ } /* zchke_ */ /* Subroutine */ int zmake_(char *type__, char *uplo, char *diag, integer *m, integer *n, doublecomplex *a, integer *nmax, doublecomplex *aa, integer *lda, logical *reset, doublecomplex *transl, ftnlen type_len, ftnlen uplo_len, ftnlen diag_len) { /* System generated locals */ integer a_dim1, a_offset, i__1, i__2, i__3, i__4; doublereal d__1; doublecomplex z__1, z__2; /* Builtin functions */ integer s_cmp(const char *, const char *, ftnlen, ftnlen); void d_cnjg(doublecomplex *, const doublecomplex *); /* Local variables */ integer i__, j, jj; logical gen, her, tri, sym; integer ibeg, iend; extern /* Double Complex */ void zbeg_(doublecomplex *, logical *); logical unit, lower, upper; /* Generates values for an M by N matrix A. */ /* Stores the values in the array AA in the data structure required */ /* by the routine, with unwanted elements set to rogue value. */ /* TYPE is 'GE', 'HE', 'SY' or 'TR'. */ /* Auxiliary routine for test program for Level 3 Blas. */ /* -- Written on 8-February-1989. */ /* Jack Dongarra, Argonne National Laboratory. */ /* Iain Duff, AERE Harwell. */ /* Jeremy Du Croz, Numerical Algorithms Group Ltd. */ /* Sven Hammarling, Numerical Algorithms Group Ltd. */ /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Scalars .. */ /* .. External Functions .. */ /* .. Intrinsic Functions .. */ /* .. Executable Statements .. */ /* Parameter adjustments */ a_dim1 = *nmax; a_offset = 1 + a_dim1; a -= a_offset; --aa; /* Function Body */ gen = s_cmp(type__, "GE", (ftnlen)2, (ftnlen)2) == 0; her = s_cmp(type__, "HE", (ftnlen)2, (ftnlen)2) == 0; sym = s_cmp(type__, "SY", (ftnlen)2, (ftnlen)2) == 0; tri = s_cmp(type__, "TR", (ftnlen)2, (ftnlen)2) == 0; upper = (her || sym || tri) && *(unsigned char *)uplo == 'U'; lower = (her || sym || tri) && *(unsigned char *)uplo == 'L'; unit = tri && *(unsigned char *)diag == 'U'; /* Generate data in array A. */ i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = *m; for (i__ = 1; i__ <= i__2; ++i__) { if (gen || upper && i__ <= j || lower && i__ >= j) { i__3 = i__ + j * a_dim1; zbeg_(&z__2, reset); z__1.r = z__2.r + transl->r, z__1.i = z__2.i + transl->i; a[i__3].r = z__1.r, a[i__3].i = z__1.i; if (i__ != j) { /* Set some elements to zero */ if (*n > 3 && j == *n / 2) { i__3 = i__ + j * a_dim1; a[i__3].r = 0., a[i__3].i = 0.; } if (her) { i__3 = j + i__ * a_dim1; d_cnjg(&z__1, &a[i__ + j * a_dim1]); a[i__3].r = z__1.r, a[i__3].i = z__1.i; } else if (sym) { i__3 = j + i__ * a_dim1; i__4 = i__ + j * a_dim1; a[i__3].r = a[i__4].r, a[i__3].i = a[i__4].i; } else if (tri) { i__3 = j + i__ * a_dim1; a[i__3].r = 0., a[i__3].i = 0.; } } } /* L10: */ } if (her) { i__2 = j + j * a_dim1; i__3 = j + j * a_dim1; d__1 = a[i__3].r; z__1.r = d__1, z__1.i = 0.; a[i__2].r = z__1.r, a[i__2].i = z__1.i; } if (tri) { i__2 = j + j * a_dim1; i__3 = j + j * a_dim1; z__1.r = a[i__3].r + 1., z__1.i = a[i__3].i + 0.; a[i__2].r = z__1.r, a[i__2].i = z__1.i; } if (unit) { i__2 = j + j * a_dim1; a[i__2].r = 1., a[i__2].i = 0.; } /* L20: */ } /* Store elements in array AS in data structure required by routine. */ if (s_cmp(type__, "GE", (ftnlen)2, (ftnlen)2) == 0) { i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = *m; for (i__ = 1; i__ <= i__2; ++i__) { i__3 = i__ + (j - 1) * *lda; i__4 = i__ + j * a_dim1; aa[i__3].r = a[i__4].r, aa[i__3].i = a[i__4].i; /* L30: */ } i__2 = *lda; for (i__ = *m + 1; i__ <= i__2; ++i__) { i__3 = i__ + (j - 1) * *lda; aa[i__3].r = -1e10, aa[i__3].i = 1e10; /* L40: */ } /* L50: */ } } else if (s_cmp(type__, "HE", (ftnlen)2, (ftnlen)2) == 0 || s_cmp(type__, "SY", (ftnlen)2, (ftnlen)2) == 0 || s_cmp(type__, "TR", (ftnlen) 2, (ftnlen)2) == 0) { i__1 = *n; for (j = 1; j <= i__1; ++j) { if (upper) { ibeg = 1; if (unit) { iend = j - 1; } else { iend = j; } } else { if (unit) { ibeg = j + 1; } else { ibeg = j; } iend = *n; } i__2 = ibeg - 1; for (i__ = 1; i__ <= i__2; ++i__) { i__3 = i__ + (j - 1) * *lda; aa[i__3].r = -1e10, aa[i__3].i = 1e10; /* L60: */ } i__2 = iend; for (i__ = ibeg; i__ <= i__2; ++i__) { i__3 = i__ + (j - 1) * *lda; i__4 = i__ + j * a_dim1; aa[i__3].r = a[i__4].r, aa[i__3].i = a[i__4].i; /* L70: */ } i__2 = *lda; for (i__ = iend + 1; i__ <= i__2; ++i__) { i__3 = i__ + (j - 1) * *lda; aa[i__3].r = -1e10, aa[i__3].i = 1e10; /* L80: */ } if (her) { jj = j + (j - 1) * *lda; i__2 = jj; i__3 = jj; d__1 = aa[i__3].r; z__1.r = d__1, z__1.i = -1e10; aa[i__2].r = z__1.r, aa[i__2].i = z__1.i; } /* L90: */ } } return 0; /* End of ZMAKE. */ } /* zmake_ */ /* Subroutine */ int zmmch_(char *transa, char *transb, integer *m, integer * n, integer *kk, doublecomplex *alpha, doublecomplex *a, integer *lda, doublecomplex *b, integer *ldb, doublecomplex *beta, doublecomplex * c__, integer *ldc, doublecomplex *ct, doublereal *g, doublecomplex * cc, integer *ldcc, doublereal *eps, doublereal *err, logical *fatal, integer *nout, logical *mv, ftnlen transa_len, ftnlen transb_len) { /* Format strings */ static char fmt_9999[] = "(\002 ******* FATAL ERROR - COMPUTED RESULT IS" " LESS THAN HAL\002,\002F ACCURATE *******\002,/\002 " " EXPECTED RE\002,\002SULT COMPUTED R" "ESULT\002)"; static char fmt_9998[] = "(1x,i7,2(\002 (\002,g15.6,\002,\002,g15.6," "\002)\002))"; static char fmt_9997[] = "(\002 THESE ARE THE RESULTS FOR COLUMN" " \002,i3)"; /* System generated locals */ integer a_dim1, a_offset, b_dim1, b_offset, c_dim1, c_offset, cc_dim1, cc_offset, i__1, i__2, i__3, i__4, i__5, i__6, i__7; doublereal d__1, d__2, d__3, d__4, d__5, d__6; doublecomplex z__1, z__2, z__3, z__4; /* Builtin functions */ double d_imag(const doublecomplex *); void d_cnjg(doublecomplex *, const doublecomplex *); double sqrt(doublereal); integer s_wsfe(cilist *), e_wsfe(void), do_fio(integer *, char *, ftnlen); /* Local variables */ integer i__, j, k; doublereal erri; logical trana, tranb, ctrana, ctranb; /* Fortran I/O blocks */ static cilist io___382 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___383 = { 0, 0, 0, fmt_9998, 0 }; static cilist io___384 = { 0, 0, 0, fmt_9998, 0 }; static cilist io___385 = { 0, 0, 0, fmt_9997, 0 }; /* Checks the results of the computational tests. */ /* Auxiliary routine for test program for Level 3 Blas. */ /* -- Written on 8-February-1989. */ /* Jack Dongarra, Argonne National Laboratory. */ /* Iain Duff, AERE Harwell. */ /* Jeremy Du Croz, Numerical Algorithms Group Ltd. */ /* Sven Hammarling, Numerical Algorithms Group Ltd. */ /* .. Parameters .. */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Scalars .. */ /* .. Intrinsic Functions .. */ /* .. Statement Functions .. */ /* .. Statement Function definitions .. */ /* .. Executable Statements .. */ /* Parameter adjustments */ a_dim1 = *lda; a_offset = 1 + a_dim1; a -= a_offset; b_dim1 = *ldb; b_offset = 1 + b_dim1; b -= b_offset; c_dim1 = *ldc; c_offset = 1 + c_dim1; c__ -= c_offset; --ct; --g; cc_dim1 = *ldcc; cc_offset = 1 + cc_dim1; cc -= cc_offset; /* Function Body */ trana = *(unsigned char *)transa == 'T' || *(unsigned char *)transa == 'C'; tranb = *(unsigned char *)transb == 'T' || *(unsigned char *)transb == 'C'; ctrana = *(unsigned char *)transa == 'C'; ctranb = *(unsigned char *)transb == 'C'; /* Compute expected result, one column at a time, in CT using data */ /* in A, B and C. */ /* Compute gauges in G. */ i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = *m; for (i__ = 1; i__ <= i__2; ++i__) { i__3 = i__; ct[i__3].r = 0., ct[i__3].i = 0.; g[i__] = 0.; /* L10: */ } if (! trana && ! tranb) { i__2 = *kk; for (k = 1; k <= i__2; ++k) { i__3 = *m; for (i__ = 1; i__ <= i__3; ++i__) { i__4 = i__; i__5 = i__; i__6 = i__ + k * a_dim1; i__7 = k + j * b_dim1; z__2.r = a[i__6].r * b[i__7].r - a[i__6].i * b[i__7].i, z__2.i = a[i__6].r * b[i__7].i + a[i__6].i * b[ i__7].r; z__1.r = ct[i__5].r + z__2.r, z__1.i = ct[i__5].i + z__2.i; ct[i__4].r = z__1.r, ct[i__4].i = z__1.i; i__4 = i__ + k * a_dim1; i__5 = k + j * b_dim1; g[i__] += ((d__1 = a[i__4].r, abs(d__1)) + (d__2 = d_imag( &a[i__ + k * a_dim1]), abs(d__2))) * ((d__3 = b[ i__5].r, abs(d__3)) + (d__4 = d_imag(&b[k + j * b_dim1]), abs(d__4))); /* L20: */ } /* L30: */ } } else if (trana && ! tranb) { if (ctrana) { i__2 = *kk; for (k = 1; k <= i__2; ++k) { i__3 = *m; for (i__ = 1; i__ <= i__3; ++i__) { i__4 = i__; i__5 = i__; d_cnjg(&z__3, &a[k + i__ * a_dim1]); i__6 = k + j * b_dim1; z__2.r = z__3.r * b[i__6].r - z__3.i * b[i__6].i, z__2.i = z__3.r * b[i__6].i + z__3.i * b[i__6] .r; z__1.r = ct[i__5].r + z__2.r, z__1.i = ct[i__5].i + z__2.i; ct[i__4].r = z__1.r, ct[i__4].i = z__1.i; i__4 = k + i__ * a_dim1; i__5 = k + j * b_dim1; g[i__] += ((d__1 = a[i__4].r, abs(d__1)) + (d__2 = d_imag(&a[k + i__ * a_dim1]), abs(d__2))) * (( d__3 = b[i__5].r, abs(d__3)) + (d__4 = d_imag( &b[k + j * b_dim1]), abs(d__4))); /* L40: */ } /* L50: */ } } else { i__2 = *kk; for (k = 1; k <= i__2; ++k) { i__3 = *m; for (i__ = 1; i__ <= i__3; ++i__) { i__4 = i__; i__5 = i__; i__6 = k + i__ * a_dim1; i__7 = k + j * b_dim1; z__2.r = a[i__6].r * b[i__7].r - a[i__6].i * b[i__7] .i, z__2.i = a[i__6].r * b[i__7].i + a[i__6] .i * b[i__7].r; z__1.r = ct[i__5].r + z__2.r, z__1.i = ct[i__5].i + z__2.i; ct[i__4].r = z__1.r, ct[i__4].i = z__1.i; i__4 = k + i__ * a_dim1; i__5 = k + j * b_dim1; g[i__] += ((d__1 = a[i__4].r, abs(d__1)) + (d__2 = d_imag(&a[k + i__ * a_dim1]), abs(d__2))) * (( d__3 = b[i__5].r, abs(d__3)) + (d__4 = d_imag( &b[k + j * b_dim1]), abs(d__4))); /* L60: */ } /* L70: */ } } } else if (! trana && tranb) { if (ctranb) { i__2 = *kk; for (k = 1; k <= i__2; ++k) { i__3 = *m; for (i__ = 1; i__ <= i__3; ++i__) { i__4 = i__; i__5 = i__; i__6 = i__ + k * a_dim1; d_cnjg(&z__3, &b[j + k * b_dim1]); z__2.r = a[i__6].r * z__3.r - a[i__6].i * z__3.i, z__2.i = a[i__6].r * z__3.i + a[i__6].i * z__3.r; z__1.r = ct[i__5].r + z__2.r, z__1.i = ct[i__5].i + z__2.i; ct[i__4].r = z__1.r, ct[i__4].i = z__1.i; i__4 = i__ + k * a_dim1; i__5 = j + k * b_dim1; g[i__] += ((d__1 = a[i__4].r, abs(d__1)) + (d__2 = d_imag(&a[i__ + k * a_dim1]), abs(d__2))) * (( d__3 = b[i__5].r, abs(d__3)) + (d__4 = d_imag( &b[j + k * b_dim1]), abs(d__4))); /* L80: */ } /* L90: */ } } else { i__2 = *kk; for (k = 1; k <= i__2; ++k) { i__3 = *m; for (i__ = 1; i__ <= i__3; ++i__) { i__4 = i__; i__5 = i__; i__6 = i__ + k * a_dim1; i__7 = j + k * b_dim1; z__2.r = a[i__6].r * b[i__7].r - a[i__6].i * b[i__7] .i, z__2.i = a[i__6].r * b[i__7].i + a[i__6] .i * b[i__7].r; z__1.r = ct[i__5].r + z__2.r, z__1.i = ct[i__5].i + z__2.i; ct[i__4].r = z__1.r, ct[i__4].i = z__1.i; i__4 = i__ + k * a_dim1; i__5 = j + k * b_dim1; g[i__] += ((d__1 = a[i__4].r, abs(d__1)) + (d__2 = d_imag(&a[i__ + k * a_dim1]), abs(d__2))) * (( d__3 = b[i__5].r, abs(d__3)) + (d__4 = d_imag( &b[j + k * b_dim1]), abs(d__4))); /* L100: */ } /* L110: */ } } } else if (trana && tranb) { if (ctrana) { if (ctranb) { i__2 = *kk; for (k = 1; k <= i__2; ++k) { i__3 = *m; for (i__ = 1; i__ <= i__3; ++i__) { i__4 = i__; i__5 = i__; d_cnjg(&z__3, &a[k + i__ * a_dim1]); d_cnjg(&z__4, &b[j + k * b_dim1]); z__2.r = z__3.r * z__4.r - z__3.i * z__4.i, z__2.i = z__3.r * z__4.i + z__3.i * z__4.r; z__1.r = ct[i__5].r + z__2.r, z__1.i = ct[i__5].i + z__2.i; ct[i__4].r = z__1.r, ct[i__4].i = z__1.i; i__4 = k + i__ * a_dim1; i__5 = j + k * b_dim1; g[i__] += ((d__1 = a[i__4].r, abs(d__1)) + (d__2 = d_imag(&a[k + i__ * a_dim1]), abs(d__2))) * ((d__3 = b[i__5].r, abs(d__3)) + (d__4 = d_imag(&b[j + k * b_dim1]), abs(d__4))); /* L120: */ } /* L130: */ } } else { i__2 = *kk; for (k = 1; k <= i__2; ++k) { i__3 = *m; for (i__ = 1; i__ <= i__3; ++i__) { i__4 = i__; i__5 = i__; d_cnjg(&z__3, &a[k + i__ * a_dim1]); i__6 = j + k * b_dim1; z__2.r = z__3.r * b[i__6].r - z__3.i * b[i__6].i, z__2.i = z__3.r * b[i__6].i + z__3.i * b[ i__6].r; z__1.r = ct[i__5].r + z__2.r, z__1.i = ct[i__5].i + z__2.i; ct[i__4].r = z__1.r, ct[i__4].i = z__1.i; i__4 = k + i__ * a_dim1; i__5 = j + k * b_dim1; g[i__] += ((d__1 = a[i__4].r, abs(d__1)) + (d__2 = d_imag(&a[k + i__ * a_dim1]), abs(d__2))) * ((d__3 = b[i__5].r, abs(d__3)) + (d__4 = d_imag(&b[j + k * b_dim1]), abs(d__4))); /* L140: */ } /* L150: */ } } } else { if (ctranb) { i__2 = *kk; for (k = 1; k <= i__2; ++k) { i__3 = *m; for (i__ = 1; i__ <= i__3; ++i__) { i__4 = i__; i__5 = i__; i__6 = k + i__ * a_dim1; d_cnjg(&z__3, &b[j + k * b_dim1]); z__2.r = a[i__6].r * z__3.r - a[i__6].i * z__3.i, z__2.i = a[i__6].r * z__3.i + a[i__6].i * z__3.r; z__1.r = ct[i__5].r + z__2.r, z__1.i = ct[i__5].i + z__2.i; ct[i__4].r = z__1.r, ct[i__4].i = z__1.i; i__4 = k + i__ * a_dim1; i__5 = j + k * b_dim1; g[i__] += ((d__1 = a[i__4].r, abs(d__1)) + (d__2 = d_imag(&a[k + i__ * a_dim1]), abs(d__2))) * ((d__3 = b[i__5].r, abs(d__3)) + (d__4 = d_imag(&b[j + k * b_dim1]), abs(d__4))); /* L160: */ } /* L170: */ } } else { i__2 = *kk; for (k = 1; k <= i__2; ++k) { i__3 = *m; for (i__ = 1; i__ <= i__3; ++i__) { i__4 = i__; i__5 = i__; i__6 = k + i__ * a_dim1; i__7 = j + k * b_dim1; z__2.r = a[i__6].r * b[i__7].r - a[i__6].i * b[ i__7].i, z__2.i = a[i__6].r * b[i__7].i + a[i__6].i * b[i__7].r; z__1.r = ct[i__5].r + z__2.r, z__1.i = ct[i__5].i + z__2.i; ct[i__4].r = z__1.r, ct[i__4].i = z__1.i; i__4 = k + i__ * a_dim1; i__5 = j + k * b_dim1; g[i__] += ((d__1 = a[i__4].r, abs(d__1)) + (d__2 = d_imag(&a[k + i__ * a_dim1]), abs(d__2))) * ((d__3 = b[i__5].r, abs(d__3)) + (d__4 = d_imag(&b[j + k * b_dim1]), abs(d__4))); /* L180: */ } /* L190: */ } } } } i__2 = *m; for (i__ = 1; i__ <= i__2; ++i__) { i__3 = i__; i__4 = i__; z__2.r = alpha->r * ct[i__4].r - alpha->i * ct[i__4].i, z__2.i = alpha->r * ct[i__4].i + alpha->i * ct[i__4].r; i__5 = i__ + j * c_dim1; z__3.r = beta->r * c__[i__5].r - beta->i * c__[i__5].i, z__3.i = beta->r * c__[i__5].i + beta->i * c__[i__5].r; z__1.r = z__2.r + z__3.r, z__1.i = z__2.i + z__3.i; ct[i__3].r = z__1.r, ct[i__3].i = z__1.i; i__3 = i__ + j * c_dim1; g[i__] = ((d__1 = alpha->r, abs(d__1)) + (d__2 = d_imag(alpha), abs(d__2))) * g[i__] + ((d__3 = beta->r, abs(d__3)) + ( d__4 = d_imag(beta), abs(d__4))) * ((d__5 = c__[i__3].r, abs(d__5)) + (d__6 = d_imag(&c__[i__ + j * c_dim1]), abs( d__6))); /* L200: */ } /* Compute the error ratio for this result. */ *err = 0.; i__2 = *m; for (i__ = 1; i__ <= i__2; ++i__) { i__3 = i__; i__4 = i__ + j * cc_dim1; z__2.r = ct[i__3].r - cc[i__4].r, z__2.i = ct[i__3].i - cc[i__4] .i; z__1.r = z__2.r, z__1.i = z__2.i; erri = ((d__1 = z__1.r, abs(d__1)) + (d__2 = d_imag(&z__1), abs( d__2))) / *eps; if (g[i__] != 0.) { erri /= g[i__]; } *err = max(*err,erri); if (*err * sqrt(*eps) >= 1.) { goto L230; } /* L210: */ } /* L220: */ } /* If the loop completes, all results are at least half accurate. */ goto L250; /* Report fatal error. */ L230: *fatal = TRUE_; io___382.ciunit = *nout; s_wsfe(&io___382); e_wsfe(); i__1 = *m; for (i__ = 1; i__ <= i__1; ++i__) { if (*mv) { io___383.ciunit = *nout; s_wsfe(&io___383); do_fio(&c__1, (char *)&i__, (ftnlen)sizeof(integer)); do_fio(&c__2, (char *)&ct[i__], (ftnlen)sizeof(doublereal)); do_fio(&c__2, (char *)&cc[i__ + j * cc_dim1], (ftnlen)sizeof( doublereal)); e_wsfe(); } else { io___384.ciunit = *nout; s_wsfe(&io___384); do_fio(&c__1, (char *)&i__, (ftnlen)sizeof(integer)); do_fio(&c__2, (char *)&cc[i__ + j * cc_dim1], (ftnlen)sizeof( doublereal)); do_fio(&c__2, (char *)&ct[i__], (ftnlen)sizeof(doublereal)); e_wsfe(); } /* L240: */ } if (*n > 1) { io___385.ciunit = *nout; s_wsfe(&io___385); do_fio(&c__1, (char *)&j, (ftnlen)sizeof(integer)); e_wsfe(); } L250: return 0; /* End of ZMMCH. */ } /* zmmch_ */ logical lze_(doublecomplex *ri, doublecomplex *rj, integer *lr) { /* System generated locals */ integer i__1, i__2, i__3; logical ret_val; /* Local variables */ integer i__; /* Tests if two arrays are identical. */ /* Auxiliary routine for test program for Level 3 Blas. */ /* -- Written on 8-February-1989. */ /* Jack Dongarra, Argonne National Laboratory. */ /* Iain Duff, AERE Harwell. */ /* Jeremy Du Croz, Numerical Algorithms Group Ltd. */ /* Sven Hammarling, Numerical Algorithms Group Ltd. */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Scalars .. */ /* .. Executable Statements .. */ /* Parameter adjustments */ --rj; --ri; /* Function Body */ i__1 = *lr; for (i__ = 1; i__ <= i__1; ++i__) { i__2 = i__; i__3 = i__; if (ri[i__2].r != rj[i__3].r || ri[i__2].i != rj[i__3].i) { goto L20; } /* L10: */ } ret_val = TRUE_; goto L30; L20: ret_val = FALSE_; L30: return ret_val; /* End of LZE. */ } /* lze_ */ logical lzeres_(char *type__, char *uplo, integer *m, integer *n, doublecomplex *aa, doublecomplex *as, integer *lda, ftnlen type_len, ftnlen uplo_len) { /* System generated locals */ integer aa_dim1, aa_offset, as_dim1, as_offset, i__1, i__2, i__3, i__4; logical ret_val; /* Builtin functions */ integer s_cmp(const char *, const char *, ftnlen, ftnlen); /* Local variables */ integer i__, j, ibeg, iend; logical upper; /* Tests if selected elements in two arrays are equal. */ /* TYPE is 'GE' or 'HE' or 'SY'. */ /* Auxiliary routine for test program for Level 3 Blas. */ /* -- Written on 8-February-1989. */ /* Jack Dongarra, Argonne National Laboratory. */ /* Iain Duff, AERE Harwell. */ /* Jeremy Du Croz, Numerical Algorithms Group Ltd. */ /* Sven Hammarling, Numerical Algorithms Group Ltd. */ /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. Local Scalars .. */ /* .. Executable Statements .. */ /* Parameter adjustments */ as_dim1 = *lda; as_offset = 1 + as_dim1; as -= as_offset; aa_dim1 = *lda; aa_offset = 1 + aa_dim1; aa -= aa_offset; /* Function Body */ upper = *(unsigned char *)uplo == 'U'; if (s_cmp(type__, "GE", (ftnlen)2, (ftnlen)2) == 0) { i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = *lda; for (i__ = *m + 1; i__ <= i__2; ++i__) { i__3 = i__ + j * aa_dim1; i__4 = i__ + j * as_dim1; if (aa[i__3].r != as[i__4].r || aa[i__3].i != as[i__4].i) { goto L70; } /* L10: */ } /* L20: */ } } else if (s_cmp(type__, "HE", (ftnlen)2, (ftnlen)2) == 0 || s_cmp(type__, "SY", (ftnlen)2, (ftnlen)2) == 0) { i__1 = *n; for (j = 1; j <= i__1; ++j) { if (upper) { ibeg = 1; iend = j; } else { ibeg = j; iend = *n; } i__2 = ibeg - 1; for (i__ = 1; i__ <= i__2; ++i__) { i__3 = i__ + j * aa_dim1; i__4 = i__ + j * as_dim1; if (aa[i__3].r != as[i__4].r || aa[i__3].i != as[i__4].i) { goto L70; } /* L30: */ } i__2 = *lda; for (i__ = iend + 1; i__ <= i__2; ++i__) { i__3 = i__ + j * aa_dim1; i__4 = i__ + j * as_dim1; if (aa[i__3].r != as[i__4].r || aa[i__3].i != as[i__4].i) { goto L70; } /* L40: */ } /* L50: */ } } ret_val = TRUE_; goto L80; L70: ret_val = FALSE_; L80: return ret_val; /* End of LZERES. */ } /* lzeres_ */ /* Double Complex */ void zbeg_(doublecomplex * ret_val, logical *reset) { /* System generated locals */ doublereal d__1, d__2; doublecomplex z__1; /* Local variables */ static integer i__, j, ic, mi, mj; /* Generates complex numbers as pairs of random numbers uniformly */ /* distributed between -0.5 and 0.5. */ /* Auxiliary routine for test program for Level 3 Blas. */ /* -- Written on 8-February-1989. */ /* Jack Dongarra, Argonne National Laboratory. */ /* Iain Duff, AERE Harwell. */ /* Jeremy Du Croz, Numerical Algorithms Group Ltd. */ /* Sven Hammarling, Numerical Algorithms Group Ltd. */ /* .. Scalar Arguments .. */ /* .. Local Scalars .. */ /* .. Save statement .. */ /* .. Intrinsic Functions .. */ /* .. Executable Statements .. */ if (*reset) { /* Initialize local variables. */ mi = 891; mj = 457; i__ = 7; j = 7; ic = 0; *reset = FALSE_; } /* The sequence of values of I or J is bounded between 1 and 999. */ /* If initial I or J = 1,2,3,6,7 or 9, the period will be 50. */ /* If initial I or J = 4 or 8, the period will be 25. */ /* If initial I or J = 5, the period will be 10. */ /* IC is used to break up the period by skipping 1 value of I or J */ /* in 6. */ ++ic; L10: i__ *= mi; j *= mj; i__ -= i__ / 1000 * 1000; j -= j / 1000 * 1000; if (ic >= 5) { ic = 0; goto L10; } d__1 = (i__ - 500) / 1001.; d__2 = (j - 500) / 1001.; z__1.r = d__1, z__1.i = d__2; ret_val->r = z__1.r, ret_val->i = z__1.i; return ; /* End of ZBEG. */ } /* zbeg_ */ doublereal ddiff_(doublereal *x, doublereal *y) { /* System generated locals */ doublereal ret_val; /* Auxiliary routine for test program for Level 3 Blas. */ /* -- Written on 8-February-1989. */ /* Jack Dongarra, Argonne National Laboratory. */ /* Iain Duff, AERE Harwell. */ /* Jeremy Du Croz, Numerical Algorithms Group Ltd. */ /* Sven Hammarling, Numerical Algorithms Group Ltd. */ /* .. Scalar Arguments .. */ /* .. Executable Statements .. */ ret_val = *x - *y; return ret_val; /* End of DDIFF. */ } /* ddiff_ */ /* Subroutine */ int chkxer_(char *srnamt, integer *infot, integer *nout, logical *lerr, logical *ok, ftnlen srnamt_len) { /* Format strings */ static char fmt_9999[] = "(\002 ***** ILLEGAL VALUE OF PARAMETER NUMBER" " \002,i2,\002 NOT D\002,\002ETECTED BY \002,a6,\002 *****\002)"; /* Builtin functions */ integer s_wsfe(cilist *), do_fio(integer *, char *, ftnlen), e_wsfe(void); /* Fortran I/O blocks */ static cilist io___397 = { 0, 0, 0, fmt_9999, 0 }; /* Tests whether XERBLA has detected an error when it should. */ /* Auxiliary routine for test program for Level 3 Blas. */ /* -- Written on 8-February-1989. */ /* Jack Dongarra, Argonne National Laboratory. */ /* Iain Duff, AERE Harwell. */ /* Jeremy Du Croz, Numerical Algorithms Group Ltd. */ /* Sven Hammarling, Numerical Algorithms Group Ltd. */ /* .. Scalar Arguments .. */ /* .. Executable Statements .. */ if (! (*lerr)) { io___397.ciunit = *nout; s_wsfe(&io___397); do_fio(&c__1, (char *)&(*infot), (ftnlen)sizeof(integer)); do_fio(&c__1, srnamt, (ftnlen)6); e_wsfe(); *ok = FALSE_; } *lerr = FALSE_; return 0; /* End of CHKXER. */ } /* chkxer_ */ /* Subroutine */ int xerbla_(char *srname, integer *info, ftnlen srname_len) { /* Format strings */ static char fmt_9999[] = "(\002 ******* XERBLA WAS CALLED WITH INFO =" " \002,i6,\002 INSTEAD\002,\002 OF \002,i2,\002 *******\002)"; static char fmt_9997[] = "(\002 ******* XERBLA WAS CALLED WITH INFO =" " \002,i6,\002 *******\002)"; static char fmt_9998[] = "(\002 ******* XERBLA WAS CALLED WITH SRNAME =" " \002,a6,\002 INSTE\002,\002AD OF \002,a6,\002 *******\002)"; /* Builtin functions */ integer s_wsfe(cilist *), do_fio(integer *, char *, ftnlen), e_wsfe(void), s_cmp(const char *, const char *, ftnlen, ftnlen); /* Fortran I/O blocks */ static cilist io___398 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___399 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___400 = { 0, 0, 0, fmt_9998, 0 }; /* This is a special version of XERBLA to be used only as part of */ /* the test program for testing error exits from the Level 3 BLAS */ /* routines. */ /* XERBLA is an error handler for the Level 3 BLAS routines. */ /* It is called by the Level 3 BLAS routines if an input parameter is */ /* invalid. */ /* Auxiliary routine for test program for Level 3 Blas. */ /* -- Written on 8-February-1989. */ /* Jack Dongarra, Argonne National Laboratory. */ /* Iain Duff, AERE Harwell. */ /* Jeremy Du Croz, Numerical Algorithms Group Ltd. */ /* Sven Hammarling, Numerical Algorithms Group Ltd. */ /* .. Scalar Arguments .. */ /* .. Scalars in Common .. */ /* .. Common blocks .. */ /* .. Executable Statements .. */ infoc_2.lerr = TRUE_; if (*info != infoc_2.infot) { if (infoc_2.infot != 0) { io___398.ciunit = infoc_2.nout; s_wsfe(&io___398); do_fio(&c__1, (char *)&(*info), (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&infoc_2.infot, (ftnlen)sizeof(integer)); e_wsfe(); } else { io___399.ciunit = infoc_2.nout; s_wsfe(&io___399); do_fio(&c__1, (char *)&(*info), (ftnlen)sizeof(integer)); e_wsfe(); } infoc_2.ok = FALSE_; } if (s_cmp(srname, srnamc_1.srnamt, (ftnlen)6, (ftnlen)6) != 0) { io___400.ciunit = infoc_2.nout; s_wsfe(&io___400); do_fio(&c__1, srname, (ftnlen)6); do_fio(&c__1, srnamc_1.srnamt, (ftnlen)6); e_wsfe(); infoc_2.ok = FALSE_; } return 0; /* End of XERBLA */ } /* xerbla_ */ /* Main program alias */ int zblat3_ () { main (); return 0; } blis-0.9.0/blis.pc.in000066400000000000000000000004071422157504600143420ustar00rootroot00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: BLIS Description: BLAS-like Library Instantiation Software Framework Version: @PACKAGE_VERSION@ Libs: -L${libdir} -lblis Libs.private: @LDFLAGS@ Cflags: -I${includedir}/blis blis-0.9.0/build/000077500000000000000000000000001422157504600135565ustar00rootroot00000000000000blis-0.9.0/build/add-copyright.py000077500000000000000000000254141422157504600166770ustar00rootroot00000000000000#!/usr/bin/env python3 # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2018, The University of Texas at Austin # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # # Import modules import os import sys import getopt import re import subprocess import datetime def print_usage(): my_print( " " ) my_print( " %s" % script_name ) my_print( " " ) my_print( " Field G. Van Zee" ) my_print( " " ) my_print( " Update copyright lines of all created or modified source files currently" ) my_print( " staged in the git index, and also insert new copyright lines where they" ) my_print( " currently are missing. This script targets copyright lines for one" ) my_print( " organization at a time." ) my_print( " " ) my_print( " Usage:" ) my_print( " " ) my_print( " %s [options]" % script_name ) my_print( " " ) my_print( " Arguments:" ) my_print( " " ) my_print( " " ) my_print( " The following options are accepted:" ) my_print( " " ) my_print( " -o org organization name" ) my_print( " Update and add copyrights for an organization named ." ) my_print( " By default, is 'Advanced Micro Devices, Inc.'" ) my_print( " " ) my_print( " -u update only" ) my_print( " Update existing copyrights to reflect the current year," ) my_print( " but do not add any additional copyright lines. With this" ) my_print( " option, the script still only updates copyright lines for" ) my_print( " the specified (or default) organization. The default is" ) my_print( " to update but also add copyright lines where missing." ) my_print( " " ) my_print( " -d dry run" ) my_print( " Go through all of the motions, but don't actually modify" ) my_print( " any files. The default behavior is to not enable dry run." ) my_print( " " ) my_print( " -q quiet" ) my_print( " Do not output feedback while processing each file. The" ) my_print( " default behavior is to output one line of text to stdout" ) my_print( " per file updated." ) my_print( " " ) my_print( " -h help" ) my_print( " Output this information and exit." ) my_print( " " ) # ------------------------------------------------------------------------------ def my_print( s ): sys.stdout.write( "%s\n" % s ) #sys.stdout.flush() def my_echo( s ): if not quiet: sys.stdout.write( "%s: %s\n" % ( output_name, s ) ) #sys.stdout.flush() # ------------------------------------------------------------------------------ def main(): global script_name global output_name global quiet # Obtain the script name. path, script_name = os.path.split(sys.argv[0]) output_name = script_name # Default values for optional arguments. the_org = 'Advanced Micro Devices, Inc.' update_only = False dry_run = False quiet = False # Process our command line options. try: opts, args = getopt.getopt( sys.argv[1:], "do:uhq" ) except getopt.GetoptError as err: # print help information and exit: my_print( str(err) ) # will print something like "option -a not recognized" print_usage() sys.exit(2) for opt, optarg in opts: if opt == "-o": the_org = optarg elif opt == "-u": update_only = True elif opt == "-d": dry_run = True elif opt == "-q": quiet = True elif opt == "-h": print_usage() sys.exit() else: print_usage() sys.exit() # Print usage if we don't have exactly zero arguments. if len( args ) != 0: print_usage() sys.exit() # Acquire our only mandatory argument. #driverfile = args[0] # Query the current year. the_time = datetime.datetime.now() cur_year = str(the_time.year) # We run 'git status' with --porcelain to make the output easily parseable. gitstatus = 'git status --porcelain' # Run the 'git status' command and capture the output. p = subprocess.run( gitstatus, stdout=subprocess.PIPE, shell=True ) git_lines = p.stdout.decode().splitlines() git_num_lines = int( len( git_lines ) ) # Consider each line of output from 'git status' for i in range( git_num_lines ): # Parse the current line to find the performance value. git_line = git_lines[i] git_words = git_line.split() mod_char = git_line[0] # Check the first character of the git output. We want to only update # files that are new ('A'), modified ('M'), or renamed ('R'). if mod_char != 'A' and \ mod_char != 'M' and \ mod_char != 'R': continue # Identify the filename for the current line of 'git status' output. if mod_char == 'R': # For renamed files, we need to reference them by their new names, # which appear after the "->" char sequence in git_words[2]. filename = git_words[3] else: filename = git_words[1] #my_echo( "-debug---- %s" % filename ) # Start by opening the file. (We can assume it exists since it # was found by 'git status', so no need to check for existence.) # Read all lines in the file and then close it. f = open( filename, "r" ) file_lines = f.readlines() f.close() # Concatenate all lines in the file into one string. file_string = "".join( file_lines ) # Search for an existing copyright line. has_cr = re.search( 'Copyright \(C\)', file_string ) # If the file does not have any copyright notice in it already, we # assume we don't need to update it. if not has_cr: my_echo( "[nocrline] %s" % filename ) continue # Check whether the file already has a copyright for the_org. We may # need to use this information later. has_org_cr = re.search( 'Copyright \(C\) ([0-9][0-9][0-9][0-9]), %s' % the_org, file_string ) # Initialize the list of processed (potentially modified) file lines. mod_file_lines = [] # At this point we know that the file has at least one copyright, and # has_org_cr encodes whether it already has a copyright for the_org. # We process the files that we know already have copyrights for the_org # differently from the files that do not yet have them. if has_org_cr: # Iterate through the lines in the current file. for line in file_lines: result = re.search( 'Copyright \(C\) ([0-9][0-9][0-9][0-9]), %s' % the_org, line ) # If the current line matches a copyright line for the_org... if result: # Extract the year saved as the first/only group in the # regular expression. old_year = result.group(1) # Don't need to update the year if it's already up-to-date. if old_year != cur_year: # Substitute the old year for the current year. find_line = ' %s, ' % old_year repl_line = ' %s, ' % cur_year line_ny = re.sub( find_line, repl_line, line ) my_echo( "[updated ] %s" % filename ) # Add the updated line to the running list. mod_file_lines += line_ny else: my_echo( "[up2date ] %s" % filename ) # Add the unchanged line to the running list. mod_file_lines += line else: # Add the unchanged line to the running list. mod_file_lines += line # endif result # endfor else: # Don't go any further if we're only updating existing copyright # lines. if update_only: my_echo( "[nocrline] %s" % filename ) continue num_file_lines = len( file_lines ) # Iterate through the lines in the current file. for i in range( int(num_file_lines) ): line = file_lines[i] # Only look at the next line if we are not at the last line. if i < int(num_file_lines) - 1: line_next = file_lines[i+1] else: line_next = file_lines[i] # Try to match both the current line and the next line. result = re.search( 'Copyright \(C\) ([0-9][0-9][0-9][0-9]), (.*)', line ) resnext = re.search( 'Copyright \(C\) ([0-9][0-9][0-9][0-9]), (.*)', line_next ) # Parse the results. if result: if resnext: # The current line matches but so does the next. Add the # current line unchanged to the running list. mod_file_lines += line else: # The current line matches but the next does not. Thus, # this branch only executes for the *last* copyright line # in the file. # Extract the year and organization from the matched # string. old_year = result.group(1) old_org = result.group(2) # Set up search/replace strings to convert the current # line into one that serves as copyright for the_org. find_line = '%s, %s' % (old_year, old_org) repl_line = '%s, %s' % (cur_year, the_org) line_nyno = re.sub( find_line, repl_line, line ) # Add the current line and then also insert our new # copyright line for the_org into the running list. mod_file_lines += line mod_file_lines += line_nyno my_echo( "[added ] %s" % filename ) # endif resnext else: # The current line does not match. Pass it through unchanged. mod_file_lines += line # endif result # endfor # endif has_org_cr if not dry_run: # Open the file for writing. f = open( filename, "w" ) # Join the modified file lines into a single string. final_string = "".join( mod_file_lines ) # Write the lines to the file. f.write( final_string ) # Close the file. f.close() # endif not dry_run # Return from main(). return 0 if __name__ == "__main__": main() blis-0.9.0/build/bli_addon.h.in000066400000000000000000000034751422157504600162600ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2021, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_ADDON_H #define BLIS_ADDON_H #if @enable_addons@ #define BLIS_ENABLE_ADDONS #else #define BLIS_DISABLE_ADDONS #endif // Enabled addons @addon_list_includes@ #endif blis-0.9.0/build/bli_config.h.in000066400000000000000000000104121422157504600164250ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_CONFIG_H #define BLIS_CONFIG_H // Enabled configuration "family" (config_name) @config_name_define@ // Enabled sub-configurations (config_list) @config_list_defines@ // Enabled kernel sets (kernel_list) @kernel_list_defines@ #if @enable_system@ #define BLIS_ENABLE_SYSTEM #else #define BLIS_DISABLE_SYSTEM #endif #if @enable_openmp@ #define BLIS_ENABLE_OPENMP #endif #if @enable_pthreads@ #define BLIS_ENABLE_PTHREADS #endif #if @enable_jrir_slab@ #define BLIS_ENABLE_JRIR_SLAB #endif #if @enable_jrir_rr@ #define BLIS_ENABLE_JRIR_RR #endif #if @enable_pba_pools@ #define BLIS_ENABLE_PBA_POOLS #else #define BLIS_DISABLE_PBA_POOLS #endif #if @enable_sba_pools@ #define BLIS_ENABLE_SBA_POOLS #else #define BLIS_DISABLE_SBA_POOLS #endif #if @enable_mem_tracing@ #define BLIS_ENABLE_MEM_TRACING #else #define BLIS_DISABLE_MEM_TRACING #endif #if @int_type_size@ == 64 #define BLIS_INT_TYPE_SIZE 64 #elif @int_type_size@ == 32 #define BLIS_INT_TYPE_SIZE 32 #else // determine automatically #endif #if @blas_int_type_size@ == 64 #define BLIS_BLAS_INT_TYPE_SIZE 64 #elif @blas_int_type_size@ == 32 #define BLIS_BLAS_INT_TYPE_SIZE 32 #else // determine automatically #endif #ifndef BLIS_ENABLE_BLAS #ifndef BLIS_DISABLE_BLAS #if @enable_blas@ #define BLIS_ENABLE_BLAS #else #define BLIS_DISABLE_BLAS #endif #endif #endif #ifndef BLIS_ENABLE_CBLAS #ifndef BLIS_DISABLE_CBLAS #if @enable_cblas@ #define BLIS_ENABLE_CBLAS #else #define BLIS_DISABLE_CBLAS #endif #endif #endif #ifndef BLIS_ENABLE_MIXED_DT #ifndef BLIS_DISABLE_MIXED_DT #if @enable_mixed_dt@ #define BLIS_ENABLE_MIXED_DT #else #define BLIS_DISABLE_MIXED_DT #endif #endif #endif #ifndef BLIS_ENABLE_MIXED_DT_EXTRA_MEM #ifndef BLIS_DISABLE_MIXED_DT_EXTRA_MEM #if @enable_mixed_dt_extra_mem@ #define BLIS_ENABLE_MIXED_DT_EXTRA_MEM #else #define BLIS_DISABLE_MIXED_DT_EXTRA_MEM #endif #endif #endif #if @enable_sup_handling@ #define BLIS_ENABLE_SUP_HANDLING #else #define BLIS_DISABLE_SUP_HANDLING #endif #if @enable_memkind@ #define BLIS_ENABLE_MEMKIND #else #define BLIS_DISABLE_MEMKIND #endif #if @enable_trsm_preinversion@ #define BLIS_ENABLE_TRSM_PREINVERSION #else #define BLIS_DISABLE_TRSM_PREINVERSION #endif #if @enable_pragma_omp_simd@ #define BLIS_ENABLE_PRAGMA_OMP_SIMD #else #define BLIS_DISABLE_PRAGMA_OMP_SIMD #endif #if @enable_sandbox@ #define BLIS_ENABLE_SANDBOX #else #define BLIS_DISABLE_SANDBOX #endif #if @enable_shared@ #define BLIS_ENABLE_SHARED #else #define BLIS_DISABLE_SHARED #endif #if @complex_return_intel@ #define BLIS_ENABLE_COMPLEX_RETURN_INTEL #else #define BLIS_DISABLE_COMPLEX_RETURN_INTEL #endif #endif blis-0.9.0/build/bump-version.sh000077500000000000000000000144011422157504600165430ustar00rootroot00000000000000#!/bin/sh # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2014, The University of Texas at Austin # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # # # bump-version.sh # # Field G. Van Zee # print_usage() { #local script_name # Get the script name #script_name=${0##*/} # Echo usage info echo " " echo " "$script_name echo " " echo " Field G. Van Zee" echo " " echo " Performs a series of actions needed when incrementing (bumping) the" echo " BLIS version number:" echo " 1. Overwrite the version file with the version string passed" echo " into this script (new_vers)." echo " 2. Commit the updated version file." echo " 3. Create a new tag (named the same as new_vers) which refers to" echo " the commit created in (2)." echo " 4. Update the CHANGELOG file." echo " 5. Commit the updated CHANGELOG file." echo " " echo " Usage:" echo " ${script_name} [options] new_vers" echo " " echo " Arguments:" echo " " echo " new_vers The new version string." echo " " echo " Options:" echo " " echo " -d dry-run" echo " Go through all the motions, but don't actually make any" echo " changes to files or perform any git commits. Note that" echo " this will result in the commits for (2) and (5) above" echo " being equal to the initial commit in the script output." echo " -f VERSFILE version file name" echo " Update VERSFILE with new version string instead of default" echo " 'version' file." # Exit with non-zero exit status exit 1 } main() { # -- BEGIN GLOBAL VARIABLE DECLARATIONS -- # The name of the script, stripped of any preceeding path. script_name=${0##*/} # The name of the config.mk file. configmk_file='config.mk' # The name of the CHANGELOG file. changelog_file='CHANGELOG' # The name of the default version file. version_file_def='version' # The name of the specified version file. version_file='' # Strings used during version query. git_commit_str='' new_version_str='' # The script name to use instead of the $0 when outputting messages. output_name='' # The git directory. gitdir='.git' # Whether we are performing a dry run or not. dry_run_flag="" # -- END GLOBAL VARIABLE DECLARATIONS -- # Process our command line options. while getopts ":dhf:" opt; do case $opt in d ) dry_run_flag="1" ;; f ) version_file=$OPTARG ;; h ) print_usage ;; \? ) print_usage esac done shift $(($OPTIND - 1)) # If a version file name was not given, set version_file to the default # value. if [ -n "${version_file}" ]; then echo "${script_name}: version file specified: '${version_file}'." else echo "${script_name}: no version file specified; defaulting to '${version_file_def}'." version_file="${version_file_def}" fi # Check the number of arguments after command line option processing. if [ $# = "1" ]; then new_version_str=$1 echo "${script_name}: preparing to bump to version '${new_version_str}'." else print_usage fi # Check if the .git dir exists; if it does not, we do nothing. if [ -d "${gitdir}" ]; then echo "${script_name}: found '${gitdir}' directory; assuming git clone." git_commit_str=$(git describe --always) echo "${script_name}: initial commit: ${git_commit_str}." echo "${script_name}: updating version file '${version_file}'." if [ -z "$dry_run_flag" ]; then echo "${new_version_str}" > ${version_file} fi echo "${script_name}: executing: git commit -m \"Version file update (${new_version_str})\" ${version_file}." if [ -z "$dry_run_flag" ]; then git commit -m "Version file update (${new_version_str})" ${version_file} fi git_commit_str=$(git describe --always) echo "${script_name}: commit to be tagged: ${git_commit_str}." echo "${script_name}: executing: git tag ${new_version_str} ${git_commit_str}." if [ -z "$dry_run_flag" ]; then git tag ${new_version_str} ${git_commit_str} fi echo "${script_name}: updating ${changelog_file}." if [ -z "$dry_run_flag" ]; then # If 'make distclean' was run recently, we need to re-run # configure in order for 'make changelog' to work properly. if [ ! -f "${configmk_file}" ]; then ./configure auto fi make changelog fi echo "${script_name}: executing: git commit -m \"CHANGELOG update (${new_version_str})\" ${changelog_file}." if [ -z "$dry_run_flag" ]; then git commit -m "CHANGELOG update (${new_version_str})" ${changelog_file} fi git_commit_str=$(git describe --always) echo "${script_name}: latest commit: ${git_commit_str}." else echo "${script_name}: could not find '${gitdir}' directory; bailing out." fi # Exit peacefully. return 0 } # The script's main entry point, passing all parameters given. main "$@" blis-0.9.0/build/config.mk.in000066400000000000000000000205721422157504600157670ustar00rootroot00000000000000# # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2014, The University of Texas at Austin # Copyright (C) 2022, Advanced Micro Devices, Inc. # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # # Only include this block of code once ifndef CONFIG_MK_INCLUDED CONFIG_MK_INCLUDED := yes # The version string. This could be the official string or a custom # string forced at configure-time. VERSION := @version@ # The shared library .so major and minor.build version numbers. SO_MAJOR := @so_version_major@ SO_MINORB := @so_version_minorbuild@ SO_MMB := $(SO_MAJOR).$(SO_MINORB) # The name of the configuration family. CONFIG_NAME := @config_name@ # The list of sub-configurations associated with CONFIG_NAME. Each # sub-configuration in CONFIG_LIST corresponds to a configuration # sub-directory in the 'config' directory. See the 'config_registry' # file for the full list of registered configurations. CONFIG_LIST := @config_list@ # This list of kernels needed for the configurations in CONFIG_LIST. # Each item in this list corresponds to a sub-directory in the top-level # 'kernels' directory. Oftentimes, this list is identical to CONFIG_LIST, # but not always. For example, if configuration X and Y use the same # kernel set X, and configuration W uses kernel set Q, and the CONFIG_LIST # might contained "X Y Z W", then the KERNEL_LIST would contain "X Z Q". KERNEL_LIST := @kernel_list@ # This list contains some number of "kernel:config" pairs, where "config" # specifies which configuration's compilation flags (CFLAGS) should be # used to compile the source code for the kernel set named "kernel". KCONFIG_MAP := @kconfig_map@ # The operating system name, which should be either 'Linux' or 'Darwin'. OS_NAME := @os_name@ # Check for whether the operating system is Windows. IS_WIN := @is_win@ # The directory path to the top level of the source distribution. When # building in-tree, this path is ".". When building out-of-tree, this path # is path used to identify the location of configure. We also allow the # includer of config.mk to override this value by setting DIST_PATH prior # to including this file. This override option is employed, for example, # when common.mk (and therefore config.mk) is included by the Makefile # local to the 'testsuite' directory, or the 'test' directory containing # individual test drivers. ifeq ($(strip $(DIST_PATH)),) DIST_PATH := @dist_path@ endif # The C compiler. CC_VENDOR := @CC_VENDOR@ CC := @CC@ # Important C compiler ranges. GCC_OT_4_9_0 := @gcc_older_than_4_9_0@ GCC_OT_6_1_0 := @gcc_older_than_6_1_0@ GCC_OT_9_1_0 := @gcc_older_than_9_1_0@ GCC_OT_10_1_0 := @gcc_older_than_10_1_0@ CLANG_OT_9_0_0 := @clang_older_than_9_0_0@ CLANG_OT_12_0_0 := @clang_older_than_12_0_0@ AOCC_OT_2_0_0 := @aocc_older_than_2_0_0@ AOCC_OT_3_0_0 := @aocc_older_than_3_0_0@ # The C++ compiler. NOTE: A C++ is typically not needed. CXX := @CXX@ # Static library indexer. RANLIB := @RANLIB@ # Archiver. AR := @AR@ # Python Interpreter PYTHON := @PYTHON@ # Preset (required) CFLAGS and LDFLAGS. These variables capture the value # of the CFLAGS and LDFLAGS environment variables at configure-time (and/or # the value of CFLAGS/LDFLAGS if either was specified on the command line). # These flags are used in addition to the flags automatically determined # by the build system. CFLAGS_PRESET := @cflags_preset@ LDFLAGS_PRESET := @ldflags_preset@ # The level of debugging info to generate. DEBUG_TYPE := @debug_type@ # Whether operating system support was requested via --enable-system. ENABLE_SYSTEM := @enable_system@ # The requested threading model. THREADING_MODEL := @threading_model@ # Whether the compiler supports "#pragma omp simd" via the -fopenmp-simd option. PRAGMA_OMP_SIMD := @pragma_omp_simd@ # The installation prefix, exec_prefix, libdir, includedir, and shareddir # values from configure tell us where to install the libraries, header files, # and public makefile fragments. We must first assign each substituted # @anchor@ to its own variable. Why? Because the subsitutions may contain # unevaluated variable expressions. For example, '@libdir@' may be replaced # with '${exec_prefix}/lib'. By assigning the anchors to variables first, and # then assigning them to their final INSTALL_* variables, we allow prefix and # exec_prefix to be used in the definitions of exec_prefix, libdir, # includedir, and sharedir. prefix := @prefix@ exec_prefix := @exec_prefix@ libdir := @libdir@ includedir := @includedir@ sharedir := @sharedir@ # Notice that we support the use of DESTDIR so that advanced users may install # to a temporary location. INSTALL_LIBDIR := $(DESTDIR)$(libdir) INSTALL_INCDIR := $(DESTDIR)$(includedir) INSTALL_SHAREDIR := $(DESTDIR)$(sharedir) #$(info prefix = $(prefix) ) #$(info exec_prefix = $(exec_prefix) ) #$(info libdir = $(libdir) ) #$(info includedir = $(includedir) ) #$(info sharedir = $(sharedir) ) #$(error .) # Whether to output verbose command-line feedback as the Makefile is # processed. ENABLE_VERBOSE := @enable_verbose@ # Whether we are building out-of-tree. BUILDING_OOT := @configured_oot@ # Whether we need to employ an alternate method for passing object files to # ar and/or the linker to work around a small value of ARG_MAX. ARG_MAX_HACK := @enable_arg_max_hack@ # Whether to build the static and shared libraries. # NOTE: The "MK_" prefix, which helps differentiate these variables from # their corresonding cpp macros that use the BLIS_ prefix. MK_ENABLE_STATIC := @enable_static@ MK_ENABLE_SHARED := @enable_shared@ # Whether to use an install_name based on @rpath. MK_ENABLE_RPATH := @enable_rpath@ # Whether to export all symbols within the shared library, even those symbols # that are considered to be for internal use only. EXPORT_SHARED := @export_shared@ # Whether to enable either the BLAS or CBLAS compatibility layers. MK_ENABLE_BLAS := @enable_blas@ MK_ENABLE_CBLAS := @enable_cblas@ # Whether libblis will depend on libmemkind for certain memory allocations. MK_ENABLE_MEMKIND := @enable_memkind@ # The names of the addons to include when building BLIS. If empty, no addons # will be included. ADDON_LIST := @addon_list@ # The name of a sandbox defining an alternative gemm implementation. If empty, # no sandbox will be used and the conventional gemm implementation will remain # enabled. SANDBOX := @sandbox@ # The name of the pthreads library. If --disable-system was given, then this # variable is set to the empty value. LIBPTHREAD := @libpthread@ # Whether we should use AMD-customized versions of certain framework files. ENABLE_AMD_FRAME_TWEAKS := @enable_amd_frame_tweaks@ # end of ifndef CONFIG_MK_INCLUDED conditional block endif blis-0.9.0/build/detect/000077500000000000000000000000001422157504600150265ustar00rootroot00000000000000blis-0.9.0/build/detect/config/000077500000000000000000000000001422157504600162735ustar00rootroot00000000000000blis-0.9.0/build/detect/config/config_detect.c000066400000000000000000000062261422157504600212420ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // NOTE: This file will likely only ever get compiled as part of the BLIS // configure script, and therefore BLIS_CONFIGURETIME_CPUID is guaranteed to // be #defined. However, we preserve the cpp conditional for consistency with // the other three files mentioned above. #ifdef BLIS_CONFIGURETIME_CPUID // NOTE: If you need to make any changes to this cpp branch, it's probably // the case that you also need to modify bli_arch.c, bli_cpuid.c, and // bli_env.c. Don't forget to update these other files as needed! // The BLIS_ENABLE_SYSTEM macro must be defined so that the correct cpp // branch in bli_system.h is processed. (This macro is normally defined in // bli_config.h.) #define BLIS_ENABLE_SYSTEM // Use C-style static inline functions for any static inline functions that // happen to be defined by the headers below. (This macro is normally defined // in bli_config_macro_defs.h.) #define BLIS_INLINE static // Since we're not building a shared library, we can forgo the use of the // BLIS_EXPORT_BLIS annotations by #defining them to be nothing. (This macro // is normally defined in bli_config_macro_defs.h.) #define BLIS_EXPORT_BLIS #include "bli_system.h" #include "bli_type_defs.h" #include "bli_arch.h" #include "bli_cpuid.h" //#include "bli_env.h" #else #include "blis.h" #endif int main( int argc, char** argv ) { arch_t id = bli_cpuid_query_id(); char* s = bli_arch_string( id ); printf( "%s\n", s ); return 0; } blis-0.9.0/build/detect/config/old/000077500000000000000000000000001422157504600170515ustar00rootroot00000000000000blis-0.9.0/build/detect/config/old/arch_detect.c000066400000000000000000000003131422157504600214570ustar00rootroot00000000000000#if defined(__i386) || defined(_X86) ARCH_X86 #endif #if defined(__x86_64__) || defined(__amd64__) ARCH_X86_64 #endif #if defined(__arm__) ARCH_ARM #endif #if defined(__aarch64__) ARCH_AARCH64 #endif blis-0.9.0/build/detect/config/old/auto-detect.sh000077500000000000000000000060371422157504600216340ustar00rootroot00000000000000#!/bin/sh # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2015, The University of Texas at Austin # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # # # auto-detect.sh # # Zhang Xianyi # main() { if [ clang -v > /dev/null 2>&1 ]; then CC=clang else CC=gcc fi CPUID_SRC=cpuid_x86.c CPUID_BIN=blis_cpu_detect ARCH=generic # The name of the script, stripped of any preceeding path. script_name=${0##*/} # The path to the script. We need this to find the top-level directory # of the source distribution in the event that the user has chosen to # build elsewhere. dist_path=${0%/${script_name}} # The path to the directory in which we are building. We do this to # make explicit that we distinguish between the top-level directory # of the distribution and the directory in which we are building. cur_dirpath="." # # Detect architecture by predefined macros # out1=`$CC -E ${dist_path}/arch_detect.c` ARCH=`echo $out1 | grep -o "ARCH_[a-zA-Z0-9_]*" | head -n1` if [ $ARCH = "ARCH_X86_64" ]; then CPUID_SRC=cpuid_x86.c elif [ $ARCH = "ARCH_X86" ]; then CPUID_SRC=cpuid_x86.c elif [ $ARCH = "ARCH_ARM" ]; then CPUID_SRC=cpuid_arm.c elif [ $ARCH = "ARCH_AARCH64" ]; then # Only support armv8 now echo "armv8a" return 0 else echo "generic" return 0 fi # # Detect CPU cores # $CC -o ${cur_dirpath}/$CPUID_BIN ${dist_path}/$CPUID_SRC ${cur_dirpath}/$CPUID_BIN rm -rf ${cur_dirpath}/$CPUID_BIN # Exit peacefully. return 0 } # The script's main entry point, passing all parameters given. main "$@" blis-0.9.0/build/detect/config/old/cpuid_arm.c000066400000000000000000000071521422157504600211650ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2015, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include #include #define CPUNAME_REFERENCE 0 #define CPUNAME_ARMV7 1 #define CPUNAME_CORTEXA9 2 #define CPUNAME_CORTEXA15 3 static char *cpuname[] = { "reference", "armv7a", "cortex-a9", "cortex-a15", }; int get_feature(char *search) { FILE *infile; char buffer[2048], *p,*t; p = (char *) NULL; infile = fopen("/proc/cpuinfo", "r"); if (infile == NULL) { return 0; } while (fgets(buffer, sizeof(buffer), infile)) { if (!strncmp("Features", buffer, 8)) { p = strchr(buffer, ':') + 2; break; } } fclose(infile); if( p == NULL ) return 0; t = strtok(p," "); if (t != NULL) { if (!strcmp(t, search)) { return 1; } } while( t = strtok(NULL," ")){ if (!strcmp(t, search)) { return 1; } } return 0; } int cpu_detect(void) { FILE *infile; char buffer[512], *p; p = (char *) NULL ; infile = fopen("/proc/cpuinfo", "r"); if (infile == NULL) { return CPUNAME_REFERENCE; } while (fgets(buffer, sizeof(buffer), infile)) { if (!strncmp("CPU part", buffer, 8)) { p = strchr(buffer, ':') + 2; break; } } fclose(infile); if(p != NULL) { if (strstr(p, "0xc09")) { if(get_feature("neon")) return CPUNAME_CORTEXA9; else return CPUNAME_ARMV7; } if (strstr(p, "0xc0f")) { if(get_feature("neon")) return CPUNAME_CORTEXA15; else return CPUNAME_ARMV7; } } p = (char *) NULL ; infile = fopen("/proc/cpuinfo", "r"); if (infile == NULL) { return CPUNAME_REFERENCE; } while (fgets(buffer, sizeof(buffer), infile)) { if ((!strncmp("model name", buffer, 10)) || (!strncmp("Processor", buffer, 9))) { p = strchr(buffer, ':') + 2; break; } } fclose(infile); if(p != NULL) { if (strstr(p, "ARMv7")) { return CPUNAME_ARMV7; } } return CPUNAME_REFERENCE; } int main() { int cpuname_id; cpuname_id=cpu_detect(); printf("%s\n", cpuname[cpuname_id]); return 0; } blis-0.9.0/build/detect/config/old/cpuid_x86.c000066400000000000000000000155471422157504600210420ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2015, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include #include #define VENDOR_UNKNOWN 0 #define VENDOR_INTEL 1 #define VENDOR_AMD 2 #define CPUNAME_GENERIC 0 #define CPUNAME_PENRYN 1 #define CPUNAME_SANDYBRIDGE 2 #define CPUNAME_HASWELL 3 #define CPUNAME_KNC 4 #define CPUNAME_KNL 5 #define CPUNAME_BULLDOZER 6 #define CPUNAME_PILEDRIVER 7 #define CPUNAME_STEAMROLLER 8 #define CPUNAME_EXCAVATOR 9 #define CPUNAME_ZEN 10 static char *cpuname[] = { "generic", "penryn", "sandybridge", "haswell", "knc", "knl", "bulldozer", "piledriver", "steamroller", "excavator", "zen", }; #define BITMASK(a, b, c) ((((a) >> (b)) & (c))) static inline void cpuid(int op, int *eax, int *ebx, int *ecx, int *edx){ #if defined(__i386__) && defined(__PIC__) __asm__ __volatile__ ("mov %%ebx, %%edi;" "cpuid;" "xchgl %%ebx, %%edi;" : "=a" (*eax), "=D" (*ebx), "=c" (*ecx), "=d" (*edx) : "a" (op) : "cc"); #else __asm__ __volatile__ ("cpuid": "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx) : "a" (op) : "cc"); #endif } static inline int have_cpuid(void){ int eax, ebx, ecx, edx; cpuid(0, &eax, &ebx, &ecx, &edx); return eax; } int get_vendor(void){ int eax, ebx, ecx, edx; char vendor[13]; cpuid(0, &eax, &ebx, &ecx, &edx); *(int *)(&vendor[0]) = ebx; *(int *)(&vendor[4]) = edx; *(int *)(&vendor[8]) = ecx; vendor[12] = (char)0; if (!strcmp(vendor, "GenuineIntel")) return VENDOR_INTEL; if (!strcmp(vendor, "AuthenticAMD")) return VENDOR_AMD; if ((eax == 0) || ((eax & 0x500) != 0)) return VENDOR_INTEL; return VENDOR_UNKNOWN; } static inline void xgetbv(int op, int * eax, int * edx){ //Use binary code for xgetbv __asm__ __volatile__ (".byte 0x0f, 0x01, 0xd0": "=a" (*eax), "=d" (*edx) : "c" (op) : "cc"); } int support_avx(){ int eax, ebx, ecx, edx; int ret=0; cpuid(1, &eax, &ebx, &ecx, &edx); if ((ecx & (1 << 28)) != 0 && (ecx & (1 << 27)) != 0 && (ecx & (1 << 26)) != 0){ xgetbv(0, &eax, &edx); if((eax & 6) == 6){ ret=1; //OS support AVX } } return ret; } int support_avx512(){ int eax, ebx, ecx, edx; int ret=0; cpuid(1, &eax, &ebx, &ecx, &edx); if ((ecx & (1 << 28)) != 0 && (ecx & (1 << 27)) != 0 && (ecx & (1 << 26)) != 0){ xgetbv(0, &eax, &edx); if((eax & 0xE6) == 0xE6){ ret=1; //OS support AVX-512 } } return ret; } int cpu_detect() { int eax, ebx, ecx, edx; int vendor, family, extend_family, model, extend_model; if ( !have_cpuid() ) return CPUNAME_GENERIC; vendor = get_vendor(); cpuid( 1, &eax, &ebx, &ecx, &edx ); extend_family = BITMASK( eax, 20, 0xff ); extend_model = BITMASK( eax, 16, 0x0f ); family = BITMASK( eax, 8, 0x0f ); model = BITMASK( eax, 4, 0x0f ); if (vendor == VENDOR_INTEL){ model |= extend_model<<4; switch (family) { case 0x6: switch (model) { case 0x0F: //Core2 case 0x16: //Core2 case 0x17: //Penryn case 0x1D: //Penryn case 0x1A: //Nehalem case 0x1E: //Nehalem case 0x2E: //Nehalem case 0x25: //Westmere case 0x2C: //Westmere case 0x2F: //Westmere return CPUNAME_PENRYN; case 0x2A: //Sandy Bridge case 0x2D: //Sandy Bridge case 0x3A: //Ivy Bridge case 0x3E: //Ivy Bridge if(support_avx()) { return CPUNAME_SANDYBRIDGE; }else{ return CPUNAME_GENERIC; //OS doesn't support AVX } case 0x3C: //Haswell case 0x3F: //Haswell case 0x3D: //Broadwell case 0x47: //Broadwell case 0x4F: //Broadwell case 0x56: //Broadwell case 0x4E: //Skylake case 0x5E: //Skylake if(support_avx()) { return CPUNAME_HASWELL; }else{ return CPUNAME_GENERIC; //OS doesn't support AVX } case 0x57: //KNL if(support_avx512()) { return CPUNAME_KNL; }else{ return CPUNAME_GENERIC; //OS doesn't support AVX } } break; case 0xB: switch (model) { case 0x01: //KNC return CPUNAME_KNC; } } }else if (vendor == VENDOR_AMD){ switch (family) { case 0xf: switch (extend_family) { case 6: switch (model) { case 1: if(support_avx()) return CPUNAME_BULLDOZER; else return CPUNAME_GENERIC; //OS don't support AVX. case 2: if(support_avx()) return CPUNAME_PILEDRIVER; else return CPUNAME_GENERIC; //OS don't support AVX. case 0: // Steamroller. Temp use Piledriver. if(support_avx()) return CPUNAME_STEAMROLLER; else return CPUNAME_GENERIC; //OS don't support AVX. } case 8: switch (model){ case 1: if(support_avx()) return CPUNAME_ZEN; else return CPUNAME_REFERENCE; //OS don't support AVX. } } break; } } return CPUNAME_GENERIC; } int main() { int cpuname_id; cpuname_id=cpu_detect(); printf("%s\n", cpuname[cpuname_id]); return 0; } blis-0.9.0/build/detect/iset/000077500000000000000000000000001422157504600157725ustar00rootroot00000000000000blis-0.9.0/build/detect/iset/avx.s000066400000000000000000000001431422157504600167520ustar00rootroot00000000000000// // Test for AVX instruction set. // vzeroall vmovapd %ymm0, %ymm1 vmulpd %ymm0, %ymm0, %ymm1 blis-0.9.0/build/detect/iset/avx512dq.s000066400000000000000000000001561422157504600175330ustar00rootroot00000000000000// // Test for AVX-512dq instruction set. // vzeroall vpmullq %zmm0, %zmm0, %zmm1 vpmullw %zmm0, %zmm0, %zmm1 blis-0.9.0/build/detect/iset/avx512f.s000066400000000000000000000002321422157504600173470ustar00rootroot00000000000000// // Test for AVX-512f instruction set. // vzeroall vmovapd %zmm0, %zmm1 vmulpd %zmm0, %zmm0, %zmm1 vfmadd213pd 0x400(%rax,%rsi,8) {1to8}, %zmm1, %zmm2 blis-0.9.0/build/detect/iset/fma3.s000066400000000000000000000001211422157504600167760ustar00rootroot00000000000000// // Test for FMA3 instruction set. // vzeroall vfmadd213pd %ymm0, %ymm1, %ymm2 blis-0.9.0/build/detect/iset/fma4.s000066400000000000000000000001521422157504600170030ustar00rootroot00000000000000// // Test for FMA4 instruction set (AMD Bulldozer only). // vzeroall vfmaddpd %ymm0, %ymm1, %ymm2, %ymm3 blis-0.9.0/build/detect/memkind/000077500000000000000000000000001422157504600164525ustar00rootroot00000000000000blis-0.9.0/build/detect/memkind/libmemkind_detect.c000066400000000000000000000002761422157504600222660ustar00rootroot00000000000000#include #include int main( int argc, char **argv ) { void* p = hbw_malloc( 4096 ); printf( "%s: hbw_malloc() returned %p\n", __FILE__, p ); return 0; } blis-0.9.0/build/detect/omp_simd/000077500000000000000000000000001422157504600166355ustar00rootroot00000000000000blis-0.9.0/build/detect/omp_simd/omp_simd_detect.c000066400000000000000000000007311422157504600221410ustar00rootroot00000000000000#include #include #define ARRAY_LEN 4096 double x[ ARRAY_LEN ]; double y[ ARRAY_LEN ]; int main( int argc, char **argv ) { const double alpha = 2.1; for ( int i = 0; i < ARRAY_LEN; ++i ) { y[ i ] = 0.0; x[ i ] = 1.0; } #pragma omp simd for ( int i = 0; i < ARRAY_LEN; ++i ) { y[ i ] += alpha * x[ i ]; } #if 0 _Pragma( "omp simd" ) for ( int i = 0; i < ARRAY_LEN; ++i ) { x[ i ] += alpha * y[ i ]; } #endif return 0; } blis-0.9.0/build/flatten-headers.py000077500000000000000000000370661422157504600172150ustar00rootroot00000000000000#!/usr/bin/env python # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2014, The University of Texas at Austin # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # # Import modules import os import sys import getopt import re def print_usage(): my_print( " " ) my_print( " %s" % script_name ) my_print( " " ) my_print( " Field G. Van Zee" ) my_print( " " ) my_print( " Generate a monolithic header by recursively replacing all #include" ) my_print( " directives in a selected file with the contents of the header files" ) my_print( " they reference." ) my_print( " " ) my_print( " Usage:" ) my_print( " " ) my_print( " %s header header_out temp_dir dir_list" % script_name ) my_print( " " ) my_print( " Arguments:" ) my_print( " " ) my_print( " header The filepath to the top-level header, which is the file" ) my_print( " that will #include all other header files." ) my_print( " " ) my_print( " header_out The filepath of the file into which the script will output" ) my_print( " the monolithic header." ) my_print( " " ) my_print( " temp_dir A directory in which temporary files may be created." ) my_print( " NOTE: No temporary files are created in the current" ) my_print( " implementation, but this argument must still be specified." ) my_print( " " ) my_print( " dir_list The list of directory paths in which to search for the" ) my_print( " headers that are #included by 'header'. By default, these" ) my_print( " directories are scanned for .h files, but sub-directories" ) my_print( " within the various directories are not inspected. If the" ) my_print( " -r option is given, these directories are recursively" ) my_print( " scanned. In either case, the subset of directories scanned" ) my_print( " that actually contains .h files is then searched whenever" ) my_print( " a #include directive is encountered in 'header' (or any" ) my_print( " file subsequently #included). If a referenced header file" ) my_print( " is not found, the #include directive is left untouched and" ) my_print( " translated directly into 'header_out'." ) my_print( " " ) my_print( " The following options are accepted:" ) my_print( " " ) my_print( " -r recursive" ) my_print( " Scan the directories listed in 'dir_list' recursively when" ) my_print( " searching for .h header files. By default, the directories" ) my_print( " are not searched recursively." ) my_print( " " ) my_print( " -c strip C-style comments" ) my_print( " Strip comments enclosed in /* */ delimiters from the" ) my_print( " output, including multi-line comments. By default, C-style" ) my_print( " comments are not stripped." ) my_print( " " ) my_print( " -o SCRIPT output script name" ) my_print( " Use SCRIPT as a prefix when outputting messages instead" ) my_print( " the script's actual name. Useful when the current script" ) my_print( " is going to be called from within another, higher-level" ) my_print( " driver script and seeing the current script's name might" ) my_print( " unnecessarily confuse the user." ) my_print( " " ) my_print( " -v [0|1|2] verboseness level" ) my_print( " level 0: silent (no output)" ) my_print( " level 1: default (single character '.' per header)" ) my_print( " level 2: verbose (several lines per header)." ) my_print( " " ) my_print( " -h help" ) my_print( " Output this information and exit." ) my_print( " " ) # ------------------------------------------------------------------------------ def canonicalize_ws( s ): return re.sub( '\s+', ' ', s ).strip() # --- def my_print( s ): sys.stdout.write( "%s\n" % s ) # --- #def echov1( s ): # # if verbose_flag == "1": # print "%s: %s" % ( output_name, s ) def echov1_n( s ): if verbose_flag == "1": sys.stdout.write( s ) sys.stdout.flush() def echov1_n2( s ): if verbose_flag == "1": sys.stdout.write( "%s\n" % s ) sys.stdout.flush() # --- def echov2( s ): if verbose_flag == "2": sys.stdout.write( "%s: %s\n" % ( output_name, s ) ) sys.stdout.flush() def echov2_n( s ): if verbose_flag == "2": sys.stdout.write( output_name ) sys.stdout.write( ": " ) sys.stdout.write( s ) sys.stdout.flush() def echov2_n2( s ): if verbose_flag == "2": sys.stdout.write( "%s\n" % s ) sys.stdout.flush() # ------------------------------------------------------------------------------ def list_contains_header( items ): rval = False for item in items: is_h = re.search( "\.h", item ) if is_h: rval = True break return rval # ------------------------------------------------------------------------------ def get_header_path( filename, header_dirpaths ): filepath = None # Search each directory path for the filename given. for dirpath in header_dirpaths: # Construct a possible path to the sought-after file. cur_filepath = "%s/%s" % ( dirpath, filename ) # Check whether the file exists. found = os.path.exists( cur_filepath ) if found: filepath = cur_filepath break return filepath # ------------------------------------------------------------------------------ def strip_cstyle_comments( string ): return re.sub( "/\*.*?\*/", "", string, flags=re.S ) # ------------------------------------------------------------------------------ def flatten_header( inputfile, header_dirpaths, cursp ): # This string is inserted after #include directives after having # determined that they are not present in the directory tree. skipstr = "// skipped" beginstr = "// begin " endstr = "// end " ostring = "" # Open the input file to process. ifile = open( inputfile, "r" ) # Iterate over the lines in the file. while True: # Read a line in the file. line = ifile.readline() # Check for EOF. if line == '': break # Check for the #include directive and isolate the header name within # a group (parentheses). #result = re.search( '^[\s]*#include (["<])([\w\.\-/]*)([">])', line ) result = regex.search( line ) # If the line contained a #include directive, we must try to replace # it with the contents of the header referenced by the directive. if result: # Extract the header file referenced in the #include directive, # saved as the second group in the regular expression # above. header = result.group(2) echov2( "%sfound reference to '%s'." % ( cursp, header ) ) # Search for the path to the header referenced in the #include # directive. header_path = get_header_path( header, header_dirpaths ) # First, check if the header is our root header (and if so, ignore it). # Otherwise, if the header was found, we recurse. Otherwise, we output # the #include directive with a comment indicating that it as skipped if header == root_inputfile: markl = result.group(1) markr = result.group(3) echov2( "%sthis is the root header '%s'; commenting out / skipping." \ % ( cursp, header ) ) # If the header found is our root header, then we cannot # recurse into it lest we enter an infinite loop. Output the # line but make sure it's commented out entirely. ostring += "%s #include %c%s%c %c" \ % ( skipstr, markl, header, markr, '\n' ) elif header_path: echov2( "%slocated file '%s'; recursing." \ % ( cursp, header_path ) ) # Mark the beginning of the header being inserted. ostring += "%s%s%c" % ( beginstr, header, '\n' ) # Recurse on the header, accumulating the string. ostring += flatten_header( header_path, header_dirpaths, cursp + " " ) # Mark the end of the header being inserted. ostring += "%s%s%c" % ( endstr, header, '\n' ) echov2( "%sheader file '%s' fully processed." \ % ( cursp, header_path ) ) else: markl = result.group(1) markr = result.group(3) echov2( "%scould not locate file '%s'; marking as skipped." \ % ( cursp, header ) ) # If the header was not found, output the line with a # comment that the header was skipped. ostring += "#include %c%s%c %s%c" \ % ( markl, header, markr, skipstr, '\n' ) # endif else: # If the line did not contain a #include directive, simply output # the line verbatim. ostring += "%s" % line # endif # endwhile # Close the input file. ifile.close() echov1_n( "." ) return ostring # ------------------------------------------------------------------------------ def find_header_dirs( dirpath ): header_dirpaths = [] for root, dirs, files in os.walk( dirpath, topdown=True ): echov2_n( "scanning contents of %s" % root ) if list_contains_header( files ): echov2_n2( "...found headers" ) header_dirpaths.append( root ) else: echov2_n2( "" ) #endif #endfor return header_dirpaths # ------------------------------------------------------------------------------ # Global variables. script_name = None output_name = None strip_comments = None recursive_flag = None verbose_flag = None regex = None root_inputfile = None def main(): global script_name global output_name global strip_comments global recursive_flag global verbose_flag global regex global root_inputfile # Obtain the script name. path, script_name = os.path.split(sys.argv[0]) output_name = script_name strip_comments = False recursive_flag = False verbose_flag = "1" nestsp = " " # Process our command line options. try: opts, args = getopt.getopt( sys.argv[1:], "o:rchv:" ) except getopt.GetoptError as err: # print help information and exit: my_print( str(err) ) # will print something like "option -a not recognized" print_usage() sys.exit(2) for opt, optarg in opts: if opt == "-o": output_name = optarg elif opt == "-r": recursive_flag = True elif opt == "-c": strip_comments = True elif opt == "-v": verbose_flag = optarg elif opt == "-h": print_usage() sys.exit() else: print_usage() sys.exit() # Make sure that the verboseness level is valid. if ( verbose_flag != "0" and verbose_flag != "1" and verbose_flag != "2" ): my_print( "%s Invalid verboseness argument: %s" \ % output_name, verbose_flag ) sys.exit() # Print usage if we don't have exactly four arguments. if len( args ) != 4: print_usage() sys.exit() # Acquire the four required arguments: # - the input header file, # - the output header file, # - the temporary directory in which we can write intermediate files, # - the list of directories in which to search for the headers. inputfile = args[0] outputfile = args[1] temp_dir = args[2] dir_list = args[3] # Save the filename (basename) part of the input file (or root file) into a # global variable that we can access later from within flatten_header(). root_inputfile = os.path.basename( inputfile ) # Separate the directories into distinct strings. dir_list = dir_list.split() # First, confirm that the directories in dir_list are valid. dir_list_checked = [] for item in dir_list: #absitem = os.path.abspath( item ) echov2_n( "checking " + item ) if os.path.exists( item ): dir_list_checked.append( item ) echov2_n2( "...directory exists." ) else: echov2_n2( "...invalid directory; omitting." ) # endfor # Overwrite the original dir_list with the updated copy that omits # invalid directories. dir_list = dir_list_checked echov2( "check summary:" ) echov2( " accessible directories:" ) echov2( " %s" % ' '.join( dir_list ) ) # Generate a list of directories (header_dirpaths) which will be searched # whenever a #include directive is encountered. The method by which # header_dirpaths is compiled will depend on whether the recursive flag # was given. if recursive_flag: header_dirpaths = [] for d in dir_list: # For each directory in dir_list, recursively walk that directory # and return a list of directories that contain headers. d_dirpaths = find_header_dirs( d ) # Add the list resulting from the current search to the running # list of directory paths that contain headers. header_dirpaths += d_dirpaths # endfor else: # If the recursive flag was not given, we can just use dir_list # as-is, though we opt to filter out the directories that don't # contain .h files. header_dirpaths = [] for d in dir_list: echov2_n( "scanning %s" % d ) # Acquire a list of the directory's contents. sub_items = os.listdir( d ) # If there is at least one header present, add the current # directory to the list of header directories. if list_contains_header( sub_items ): header_dirpaths.append( d ) echov2_n2( "...found headers." ) else: echov2_n2( "...no headers found." ) # endif # endfor # endfor echov2( "scan summary:" ) echov2( " headers found in:" ) echov2( " %s" % ' '.join( header_dirpaths ) ) echov2( "preparing to monolithify '%s'" % inputfile ) echov2( "new header will be saved to '%s'" % outputfile ) echov1_n( "." ) # Open the output file. ofile = open( outputfile, "w" ) # Precompile the main regular expression used to isolate #include # directives and the headers they reference. This regex object will # get reused over and over again in flatten_header(). regex = re.compile( '^[\s]*#include (["<])([\w\.\-/]*)([">])' ) # Recursively substitute headers for occurrences of #include directives. final_string = flatten_header( inputfile, header_dirpaths, nestsp ) # Strip C-style comments from the final output, if requested. if strip_comments: final_string = strip_cstyle_comments( final_string ) # Write the lines to the file. ofile.write( final_string ) # Close the output file. ofile.close() echov2( "substitution complete." ) echov2( "monolithic header saved as '%s'" % outputfile ) echov1_n2( "." ) return 0 if __name__ == "__main__": main() blis-0.9.0/build/flatten-headers.sh000077500000000000000000000435711422157504600171750ustar00rootroot00000000000000#!/usr/bin/env bash # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2014, The University of Texas at Austin # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # # # -- Helper functions ---------------------------------------------------------- # print_usage() { # Echo usage info. echo " " echo " ${script_name}" echo " " echo " Field G. Van Zee" echo " " echo " Generate a monolithic header by recursively replacing all #include" echo " directives in a selected file with the contents of the header files" echo " they reference." echo " " echo " Usage:" echo " " echo " ${script_name} header header_out temp_dir dir_list" echo " " echo " Arguments:" echo " " echo " header The filepath to the top-level header, which is the file" echo " that will #include all other header files." echo " " echo " header_out The filepath of the file into which the script will output" echo " the monolithic header." echo " " echo " temp_dir A directory in which temporary files may be created." echo " " echo " dir_list The list of directory paths in which to search for the" echo " headers that are #included by 'header'. By default, these" echo " directories are scanned for .h files, but sub-directories" echo " within the various directories are not inspected. If the" echo " -r option is given, these directories are recursively" echo " scanned. In either case, the subset of directories scanned" echo " that actually contains .h files is then searched whenever" echo " a #include directive is encountered in 'header' (or any" echo " file subsequently #included). If a referenced header file" echo " is not found, the #include directive is left untouched and" echo " translated directly into 'header_out'." echo " " echo " The following options are accepted:" echo " " echo " -r recursive" echo " Scan the directories listed in 'dir_list' recursively when" echo " searching for .h header files. By default, the directories" echo " are not searched recursively." echo " " echo " -c strip C-style comments" echo " Strip comments enclosed in /* */ delimiters from the" echo " output, including multi-line comments. By default, C-style" echo " comments are not stripped." echo " " echo " -o SCRIPT output script name" echo " Use SCRIPT as a prefix when outputting messages instead" echo " the script's actual name. Useful when the current script" echo " is going to be called from within another, higher-level" echo " driver script and seeing the current script's name might" echo " unnecessarily confuse the user." echo " " echo " -v [0|1|2] verboseness level" echo " level 0: silent (no output)" echo " level 1: default (single character '.' per header)" echo " level 2: verbose (several lines per header)." echo " " echo " -h help" echo " Output this information and exit." echo " " # Exit with non-zero exit status exit 1 } canonicalize_ws() { local str="$1" # Remove leading and trailing whitespace. str=$(echo -e "${str}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//') # Remove duplicate spaces between words. str=$(echo -e "${str}" | tr -s " ") # Update the input argument. echo "${str}" } is_word_in_list() { word="$1" list="$2" rval="" for item in ${list}; do if [ "${item}" == "${word}" ]; then rval="${word}" break fi done echo "${rval}" } echovo() { if [ "${verbose_flag}" == "1" ]; then # Echo the argument string to stderr instead of stdout. echo "${output_name}: $1" 1>&2; fi } echovo_n() { if [ "${verbose_flag}" == "1" ]; then # Echo the argument string to stderr instead of stdout. echo -n "$1" 1>&2; fi } echovo_n2() { if [ "${verbose_flag}" == "1" ]; then # Echo the argument string to stderr instead of stdout. echo "$1" 1>&2; fi } # --- echovt() { if [ "${verbose_flag}" == "2" ]; then # Echo the argument string to stderr instead of stdout. echo "${output_name}: $1" 1>&2; fi } echovt_n() { if [ "${verbose_flag}" == "2" ]; then # Echo the argument string to stderr instead of stdout. echo -n "${output_name}: $1" 1>&2; fi } echovt_n2() { if [ "${verbose_flag}" == "2" ]; then # Echo the argument string to stderr instead of stdout. echo "$1" 1>&2; fi } find_header_dirs() { local cur_dirpath sub_items result cur_list item child_list # Extract the argument: the current directory, and the list of # directories found so far that contain headers. cur_dirpath="$1" echovt_n "scanning contents of ${cur_dirpath}" # Acquire a list of the directory's contents. sub_items=$(ls ${cur_dirpath}) # If there is at least one header present, add the current directory to # the list header of directories. Otherwise, the current directory does # not contribute to the list returned to the caller. result=$(echo ${sub_items} | grep "\.h") if [ -n "${result}" ]; then cur_list="${cur_dirpath}" echovt_n2 " ...found headers" else cur_list="" echovt_n2 "" fi # Iterate over the list of directory contents. for item in ${sub_items}; do # Check whether the current item is in the ignore_list. If so, we # ignore it. result=$(is_word_in_list "${item}" "${ignore_list}") if [ -n "${result}" ]; then echovt "ignoring directory '${item}'." continue fi # If the current item is a directory, recursively accumulate header # directories for that sub-directory. if [ -d "${cur_dirpath}/${item}" ]; then # Recursively find header directories within the sub-directory # ${item} and store the directory list to child_list. child_list=$(find_header_dirs "${cur_dirpath}/${item}") # Accumulate the sub-directory's header list with the running list # of header directories cur_list="${cur_list} ${child_list}" fi done # Return the list of header directories. echo "${cur_list}" } get_header_path() { local filename dirpaths filepath filename="$1" dirpaths="$2" filepath="" # Search each directory path for the filename given. for dirpath in ${dirpaths}; do if [ -f "${dirpath}/${filename}" ]; then filepath="${dirpath}/${filename}" break fi done # Return the filepath that was found. Note that if no filepath was found # in the loop above, the empty string gets returned. echo "${filepath}" } replace_pass() { local inputfile dirpaths intermfile skipstr commstr result local header headerlist header_filepath header_esc subintermfile inputfile="$1" dirpaths="$2" cursp="$3" # Set the output filename, which we will return to the caller. Starting # with the input filepath, we strip it down to just the filename and # reconstruct it with the .interm suffix in temp_dir. intermfile="${inputfile##*/}" intermfile="${temp_dir}/${intermfile}.interm" # This string is inserted after #include directives after having # determined that they are not present in the directory tree. skipstr="\/\/ skipped" # Initialize the list of headers referenced in #include directives # found in the current header file. headerlist="" result=$(grep '^[[:space:]]*#include ' ${inputfile}) # Only iterate through the file line-by-line if it contains at least # one #include directive. If it does not contain any #include directives, # then we can leave headerlist initialized to empty and proceed. if [ -n "${result}" ]; then # Iterate through each line of the header file, accumulating the names of # header files referenced in #include directives. while read -r curline do # Check whether the line begins with a #include directive, but ignore # the line if it contains the skip string. result=$(echo ${curline} | grep '^[[:space:]]*#include ') # If the #include directive was found... if [ -n "${result}" ]; then # Isolate the header filename. We must take care to include all # characters that might appear between the "" or <>. header=$(echo ${curline} | sed -e "s/#include [\"<]\([a-zA-Z0-9\_\.\/\-]*\)[\">].*/\1/g") # Add the header file to a list. headerlist=$(canonicalize_ws "${headerlist} ${header}") fi done < "${inputfile}" fi if [ -n "${headerlist}" ]; then echovt "${cursp}found references to: ${headerlist}" else echovt "${cursp}no header references found." fi # Before we go any further, we strip C-style comments from the file, # if requested. if [ -n "${strip_comments}" ]; then # Make a copy of inputfile stripped of its C-style comments and # save it to intermfile. This substitution leaves behind a single # blank line. cat ${inputfile} \ | perl -0777 -pe "s/\/\*.*?\*\///gs" \ > "${intermfile}" else # Otherwise, just copy inputfile to intermfile verbatim. cp ${inputfile} ${intermfile} fi # Iterate over each header file found in the previous loop. for header in ${headerlist}; do # Find the path to the header. header_filepath=$(get_header_path ${header} "${dirpaths}") # If the header has a slash, escape it so that sed doesn't get confused # (since we use '/' as our search-and-replace delimiter). header_esc=$(echo "${header}" | sed -e 's/\//\\\//g') # If the header file was not found, get_header_path() returns an # empty string. This probably means that the header file is a # system header and thus we skip it since we don't want to inline # the contents of system headers anyway. if [ -z "${header_filepath}" ]; then echovt "${cursp}could not locate file '${header}'; marking as skipped." # Insert a comment after the #include so we know it was ignored. # Notice that we mimic the quotes or angle brackets around the # header name, whichever pair was used in the input. cat ${intermfile} \ | sed -e "s/^[[:space:]]*#include \([\"<]\)\(${header_esc}\)\([\">]\).*/#include \1\2\3 ${skipstr}/" \ > "${intermfile}.tmp" mv "${intermfile}.tmp" ${intermfile} else echovt "${cursp}located file '${header_filepath}'; recursing." # Recursively produce an inlined/flattened intermediate file at # ${header_filepath}. subintermfile=$(replace_pass ${header_filepath} "${dirpaths}" "${cursp}${nestsp}") echovt "${cursp}inserting '${subintermfile}'." # Replace the #include directive for the current header file with the # contents of that header file, saving the result to a temporary file. # We also insert begin and end markers to allow for more readability. # NOTE: We use the 'i\...' and 'a\...' notation with '$', which causes # bash to interpret '\n' as a newline, as needed for the 'a\' and 'i\' # commands in POSIX (e.g. OS X) sed. (GNU sed allows a much more # natural usage that does not require the backslash or newline.) cat ${intermfile} \ | sed -e "/^[[:space:]]*#include \"${header_esc}\"/ {" \ -e 'i\'$'\n'"// begin ${header}"$'\n' \ -e "r ${subintermfile}" \ -e 'a\'$'\n'"// end ${header}"$'\n' \ -e "d" \ -e "}" \ > "${intermfile}.tmp" mv "${intermfile}.tmp" ${intermfile} echovt "${cursp}removing intermediate file '${subintermfile}'." # Remove the recursive call's intermediate file now that it has been # inserted into this level's intermediate. rm "${subintermfile}" fi done # works, but leaves blank line: #cat "test.h" | sed -e "/^#include \"foo.h\"/r foo.h" -e "s///" > "test.new.h" # works: #cat "test.h" | sed -e '/^#include \"foo.h\"/ {' -e 'r foo.h' -e 'd' -e '}' > "test.new.h" # works: #cat "test.h" | sed -e '/^#include \"foo.h\"/r foo.h' -e '/^#include \"foo.h\"/d' > "test.new.h" #cat zorn/header.h | sed -e '/^#include \"header1.h\"/ {' -e 'i // begin insertion' -e 'r alice/header1.h' -e 'a // end insertion' -e 'd' -e '}' echovt "${cursp}header file '${inputfile}' fully processed." echovt "${cursp}returning via '${intermfile}'." echovo_n "." # Return the intermediate filename so the caller knows the name of this # invocation's output file. echo "${intermfile}" } # # -- main function ------------------------------------------------------------- # main() { # The name of the script, stripped of any preceding path. script_name=${0##*/} # The script name to use in informational output. Defaults to ${script_name}. output_name=${script_name} # Whether or not we should strip C-style comments from the output. (Default # is to not strip C-style comments.) strip_comments="" # Whether or not we search the directories in dir_list recursively. (Default # is to not search recursively.) recursive_flag="" # The list of directories to ignore ignore_list="old other temp test testsuite windows" # The amount to nest each level of recursion in the output. nestsp=" " # Process our command line options. while getopts ":o:rchv:" opt; do case $opt in o ) output_name=$OPTARG ;; r ) recursive_flag="1" ;; c ) strip_comments="1" ;; v ) verbose_flag=$OPTARG ;; h ) print_usage ;; \? ) print_usage esac done shift $(($OPTIND - 1)) # Make sure that the verboseness level is valid. if [ "${verbose_flag}" != "0" ] && [ "${verbose_flag}" != "1" ] && [ "${verbose_flag}" != "2" ]; then echo "${output_name}: Invalid verboseness argument '${verbose_flag}'." 1>&2; exit 1 fi # Print usage if we don't have exactly two arguments. if [ $# != "4" ]; then print_usage fi # Acquire the four required arguments: # - the input header file, # - the output header file, # - the temporary directory in which we can write intermediate files, # - the list of directories in which to search for the headers inputfile="$1" outputfile="$2" temp_dir="$3" dir_list="$4" # First, confirm that the directories in dir_list are valid. dir_list2="" for item in ${dir_list}; do # Strip a trailing slash from the path, if it has one. item=${item%/} echovt_n "checking ${item} " if [ -d ${item} ]; then echovt_n2 " ...directory exists." dir_list2="${dir_list2} ${item}" else echovt_n2 " ...invalid directory; omitting." fi done dir_list2=$(canonicalize_ws "${dir_list2}") # Overwrite the original dir_list with the updated copy that omits # invalid directories. dir_list="${dir_list2}" echovt "check summary:" echovt " accessible directories:" echovt " ${dir_list}" # Generate a list of directories (dirpaths) which will be searched whenever # a #include directive is encountered. The method by which dirpaths is # compiled will depend on whether the recursive flag was given. if [ -n "${recursive_flag}" ]; then # If the recursive flag was given, we need to recursively scan each # directory in dir_list for directories with headers via the # function find_header_dirs(). dirpaths="" for item in ${dir_list}; do item_dirpaths=$(find_header_dirs ${item}) dirpaths="${dirpaths} ${item_dirpaths}" done dirpaths=$(canonicalize_ws "${dirpaths}") else # If the recursive flag was not given, we can just use dir_list # as-is, though we opt to filter out the directories that don't # contain .h files. dirpaths="" for item in ${dir_list}; do echovt_n "scanning ${item}" # Acquire a list of the directory's contents. sub_items=$(ls ${item}) # If there is at least one header present, add the current directory to # the list header of directories. result=$(echo ${sub_items} | grep "\.h") if [ -n "${result}" ]; then dirpaths="${dirpaths} ${item}" echovt_n2 " ...found headers." else echovt_n2 " ...no headers found." fi done dirpaths=$(canonicalize_ws "${dirpaths}") fi echovt "scan summary:" echovt " headers found in:" echovt " ${dirpaths}" echovt "preparing to monolithify '${inputfile}'." # Make a copy of the inputfile. #cp ${inputfile} ${outputfile} echovt "new header will be saved to '${outputfile}'." echovo_n "." # Recursively substitute headers for occurrences of #include directives. intermfile=$(replace_pass ${inputfile} "${dirpaths}" "${nestsp}") # Rename the intermediate file(path) to the output file(path). mv ${intermfile} ${outputfile} echovt "substitution complete." echovt "monolithic header saved as '${outputfile}'." echovo_n2 "." # Exit peacefully. return 0 } # The script's main entry point, passing all parameters given. main "$@" blis-0.9.0/build/gen-make-frags/000077500000000000000000000000001422157504600163425ustar00rootroot00000000000000blis-0.9.0/build/gen-make-frags/fragment.mk000066400000000000000000000066231422157504600205050ustar00rootroot00000000000000# # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2014, The University of Texas at Austin # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # # # fragment.mk # # This is an automatically-generated makefile fragment and will likely get # overwritten or deleted if the user is not careful. Modify at your own risk. # # These two mmakefile variables need to be set in order for the recursive # include process to work! CURRENT_DIR_NAME := _mkfile_fragment_cur_dir_name_ CURRENT_SUB_DIRS := _mkfile_fragment_sub_dir_names_ # Source files local to this fragment LOCAL_SRC_FILES := _mkfile_fragment_local_src_files_ # Add the fragment's local source files to the _global_variable_ variable. _mkfile_fragment_src_var_name_ += $(addprefix $(PARENT_SRC_PATH)/$(CURRENT_DIR_NAME)/, $(LOCAL_SRC_FILES)) # ----------------------------------------------------------------------------- # NOTE: The code below is generic and should remain in all fragment.mk files! # ----------------------------------------------------------------------------- # Add the current fragment to the global list of fragments so the top-level # Makefile knows which directories are participating in the build. FRAGMENT_DIR_PATHS += $(PARENT_SRC_PATH)/$(CURRENT_DIR_NAME) # Recursively descend into other subfragments' local makefiles and include them. ifneq ($(strip $(CURRENT_SUB_DIRS)),) key1 := $(key1).x key2 := $(key2).y stack_$(key1) := $(PARENT_PATH) stack_$(key2) := $(PARENT_SRC_PATH) PARENT_PATH := $(PARENT_PATH)/$(CURRENT_DIR_NAME) PARENT_SRC_PATH := $(PARENT_SRC_PATH)/$(CURRENT_DIR_NAME) FRAGMENT_SUB_DIRS := $(addprefix $(PARENT_PATH)/, $(CURRENT_SUB_DIRS)) -include $(addsuffix /$(FRAGMENT_MK), $(FRAGMENT_SUB_DIRS)) PARENT_PATH := $(stack_$(key1)) PARENT_SRC_PATH := $(stack_$(key2)) key1 := $(basename $(key1)) key2 := $(basename $(key2)) endif blis-0.9.0/build/gen-make-frags/gen-make-frag.sh000077500000000000000000000403301422157504600213020ustar00rootroot00000000000000#!/bin/sh # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2014, The University of Texas at Austin # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # # # gen-make-frag.sh # # Field G. Van Zee # print_usage() { #local script_name # Get the script name #script_name=${0##*/} # Echo usage info echo " " echo " "$script_name echo " " echo " Field G. Van Zee" echo " " echo " Automatically generates makefile fragments for a specified directory" echo " tree. " echo " " echo " Usage:" echo " ${script_name} [options] root_dir frag_dir templ.mk suff_list ign_list" echo " " echo " Arguments (mandatory):" echo " " echo " root_dir The root directory to scan when generating makefile" echo " fragments." echo " " echo " frag_dir The root directory in which makefile fragments will be" echo " generated." echo " " echo " templ.mk The template makefile fragment used to generate the actual" echo " fragments." echo " " echo " suff_list File containing a newline-separated list of file suffixes" echo " of source files to that the top-level makefile expects to" echo " access." echo " " echo " ign_list File containing a newline-separated list of directory names" echo " to ignore when descending recursively into " echo " " echo " The following options are accepted:" echo " " echo " -d dry-run" echo " Go through all the motions, but don't actually generate any" echo " makefile fragments." echo " -r recursive" echo " Also generate makefile fragments for subdirectories of" echo " root_dir." echo " -h hide" echo " Hide the makefile fragments by prepending filenames with '.'." echo " -p PREFIX prefix name" echo " Use PREFIX instead of uppercased root_dir in the makefile" echo " variable name. If the root_dir were 'stuff' and -p was not" echo " used, then source would be accumulated into a makefile" echo " variable named 'MK_STUFF', but if -p JUNK were given, then" echo " the variable name would instead be MK_JUNK." echo " -o SCRIPT output script name" echo " Use SCRIPT when outputting messages instead of the script's" echo " actual name." echo " -v [0|1|2] verboseness level" echo " level 0: silent (no output)" echo " level 1: default (one line per directory)" echo " level 2: verbose (several lines per directory)." echo " " # Exit with non-zero exit status exit 1 } # # gen_mkfile() # # Creates a single makefile fragment in a user-specified directory and adds # any local source files found to a top-level Makefile variable. # gen_mkfile() { # Local variable declarations local mkfile_frag_var_name local this_dir local this_frag_dir local mkfile_frag_tmpl_name local mkfile_name local mkfile_frag_path local cur_frag_dir local cur_frag_path local local_src_files local sub_items local item_path local item_suffix local cur_frag_sub_dirs # Extract our arguments to local variables mkfile_frag_var_name=$1 this_dir=$2 this_frag_dir=$3 # Strip the leading path from the template makefile path to get its # simple filename. Hide the output makefile fragment filename, if # requested. mkfile_frag_tmpl_name=${mkfile_frag_tmpl_path##*/} if [ -n "$hide_flag" ]; then mkfile_frag_path=$this_frag_dir/.$mkfile_frag_tmpl_name else mkfile_frag_path=$this_frag_dir/$mkfile_frag_tmpl_name fi # Determine the directory in which the fragment will reside. cur_frag_path=$this_dir cur_frag_dir=${this_dir##*/} # Initialize the local source list to empty local_src_files="" # Get a listing of the items in $this_dir sub_items=$(ls $this_dir) # Generate a list of the source files we've chosen for item in $sub_items; do # Prepend the directory to the item to get a relative path item_path=$this_dir/$item # Acquire the item's suffix, if it has one item_suffix=${item_path##*.} # If the suffix matches, then add it to our list if is_in_list $item_suffix "$src_file_suffixes" then local_src_files="$local_src_files $item" fi done # Delete the leading " " space character in the local source files list. local_src_files=${local_src_files##" "} # Initialize the fragment subdirectory list to empty cur_frag_sub_dirs="" # Capture the relative path listing of items in $this_dir. sub_items=$(ls $this_dir) # Determine the fragment's subdirectory names, if any exist for item in $sub_items; do # Prepend the directory to the item to get a relative path item_path=$this_dir/$item # If item is a directory, and it's not in the ignore list, descend into it. #if [ -d $item_path ] && ! should_ignore $item; then if [ -d $item_path ] && ! is_in_list $item "$ignore_dirs" ; then cur_frag_sub_dirs=$cur_frag_sub_dirs" "$item fi done # Delete the leading " " space character in fragment's subdirectory list. cur_frag_sub_dirs=${cur_frag_sub_dirs##" "} # Be verbose, if level 2 was requested. if [ "$verbose_flag" = "2" ]; then echo "mkf frag tmpl path: $mkfile_frag_tmpl_path" echo "mkf frag path: $mkfile_frag_path" echo "cur frag path: $cur_frag_path" echo "cur frag dir: $cur_frag_dir" echo "cur frag sub dirs: $cur_frag_sub_dirs" echo "local src files: $local_src_files" echo "src file suffixes: $src_file_suffixes" echo "mkf frag var name: $mkfile_frag_var_name" echo "--------------------------------------------------" fi # Copy the template makefile to the directory given, using the new # makefile name we just created above. if [ -z "$dry_run_flag" ]; then cat $mkfile_frag_tmpl_path | sed -e s/"$mkfile_fragment_cur_dir_name_anchor"/"$cur_frag_dir"/g \ | sed -e s/"$mkfile_fragment_sub_dir_names_anchor"/"$cur_frag_sub_dirs"/g \ | sed -e s/"$mkfile_fragment_local_src_files_anchor"/"$local_src_files"/g \ | sed -e s/"$mkfile_fragment_src_var_name_anchor"/"$mkfile_frag_var_name"/g \ > $mkfile_frag_path fi # Return peacefully. return 0 } # # gen_mkfiles # # Recursively generates makefile fragments for a directory and all # subdirectories. All of the actual work happens in gen_mkfile(). # gen_mkfiles() { # Local variable declarations local item sub_items cur_dir this_frag_dir this_dir # Extract our argument cur_dir=$1 this_frag_dir=$2 # Append a relevant suffix to the makefile variable name, if necesary # NOTE: This step is disabled because special directories are presently # ignored when generating makefile variable names. #all_add_src_var_name "$cur_dir" # Be verbose if level 2 was requested if [ "$verbose_flag" = "2" ]; then echo ">>>" $script_name ${src_var_name}_$SRC $cur_dir $this_frag_dir elif [ "$verbose_flag" = "1" ]; then echo "$script_name: creating makefile fragment in $this_frag_dir from $cur_dir" fi # Call our function to generate a makefile in the directory given. gen_mkfile "${src_var_name}_$SRC" $cur_dir $this_frag_dir # Get a listing of the directories in $directory sub_items=$(ls $cur_dir) # Descend into the contents of root_dir to generate the subdirectories' # makefile fragments. for item in $sub_items; do # If item is a directory, and it's not in the ignore list, descend into it. #if [ -d "$cur_dir/$item" ] && ! should_ignore $item; then if [ -d "$cur_dir/$item" ] && ! is_in_list $item "$ignore_dirs" ; then gen_mkfiles $cur_dir/$item $this_frag_dir/$item fi done # Remove a relevant suffix from the makefile variable name, if necesary # NOTE: This step is disabled because special directories are presently # ignored when generating makefile variable names. #all_del_src_var_name "$cur_dir" # Return peacefully return 0 } #update_src_var_name_special() #{ # local dir act i name var_suffix # # # Extract arguments. # act="$1" # dir="$2" # # # Strip / from end of directory path, if there is one, and then strip # # path from directory name. # dir=${dir%/} # dir=${dir##*/} # # # Run through our list. # # NOTE: CURRENTLY, SPECIAL DIRECTORY NAMES ARE IGNORED. In order to # # re-enable them, remove the quotes from "${special_dirs}". # for specdir in "${special_dirs}"; do # # # If the current item matches sdir, then we'll have # # to make a modification of some form. # if [ "$dir" = "$specdir" ]; then # # # Convert the directory name to uppercase. # var_suffix=$(echo "$dir" | tr '[:lower:]' '[:upper:]') # # # Either add or remove the suffix, and also update the # # source file suffix variable. # if [ "$act" == "+" ]; then # src_var_name=${src_var_name}_$var_suffix # else # src_var_name=${src_var_name%_$var_suffix} # fi # # # No need to continue iterating. # break; # fi # done #} #init_src_var_name() #{ # local dir="$1" # # # Strip off the leading / if there is one # dir=${dir%%/} # # # Convert the / directory separators into spaces to make a list of # # directories. # list=${dir//\// } # # # Inspect each item in $list # for item in $list; do # # # Try to initialize the source variable name # all_add_src_var_name $item # done #} #all_add_src_var_name() #{ # local dir="$1" # # update_src_var_name_special "+" "$dir" # #} #all_del_src_var_name() #{ # local dir="$1" # # update_src_var_name_special "-" "$dir" #} read_mkfile_config() { # Read the file describing file suffixes. src_file_suffixes=$(cat "${suffix_file}") # Read the file listing the directories to ignore. ignore_dirs=$(cat "${ignore_file}") # Change newlines into spaces. This is optional, but helps when # printing these values out (so they appear on one line). src_file_suffixes=$(echo ${src_file_suffixes} | sed "s/\n/ /g") ignore_dirs=$(echo ${ignore_dirs} | sed "s/\n/ /g") } main() { # -- BEGIN GLOBAL VARIABLE DECLARATIONS -- # Define these makefile template "anchors" used in gen_mkfile(). mkfile_fragment_cur_dir_name_anchor="_mkfile_fragment_cur_dir_name_" mkfile_fragment_sub_dir_names_anchor="_mkfile_fragment_sub_dir_names_" mkfile_fragment_local_src_files_anchor="_mkfile_fragment_local_src_files_" mkfile_fragment_src_var_name_anchor="_mkfile_fragment_src_var_name_" # The name of the script, stripped of any preceeding path. script_name=${0##*/} # The prefix for all makefile variables. src_var_name_prefix='MK' # The variable that always holds the string that will be passed to # gen_mkfile() as the source variable to insert into the fragment.mk. src_var_name='' # The suffix appended to all makefile fragment source variables. SRC='SRC' # The list of source file suffixes to add to the makefile variables. src_file_suffixes='' # The lists of directories to ignore. ignore_dirs='' # The arguments to this function. They'll get assigned meaningful # values after getopts. root_dir="" frag_dir="" mkfile_frag_tmpl_path="" suffix_file="" ignore_file="" # Flags set by getopts. dry_run_flag="" hide_flag="" recursive_flag="" output_name="" prefix_flag="" verbose_flag="" # -- END GLOBAL VARIABLE DECLARATIONS -- # Local variable declarations. local item sub_items this_dir # Process our command line options. while getopts ":dho:p:rv:" opt; do case $opt in d ) dry_run_flag="1" ;; h ) hide_flag="1" ;; r ) recursive_flag="1" ;; o ) output_name=$OPTARG ;; p ) prefix_flag=$OPTARG ;; v ) verbose_flag=$OPTARG ;; \? ) print_usage esac done shift $(($OPTIND - 1)) # Make sure that verboseness level is valid. if [ "$verbose_flag" != "0" ] && [ "$verbose_flag" != "1" ] && [ "$verbose_flag" != "2" ]; then verbose_flag="1" fi # Check the number of arguments after command line option processing. if [ $# != "5" ]; then print_usage fi # If an output script name was given, overwrite script_name with it. if [ -n "${output_name}" ]; then script_name="${output_name}" fi # Extract our arguments. root_dir=$1 frag_dir=$2 mkfile_frag_tmpl_path=$3 suffix_file=$4 ignore_file=$5 # Read the makefile config files to be used in the makefile fragment # generation. read_mkfile_config # Strip / from end of directory path, if there is one. root_dir=${root_dir%/} frag_dir=${frag_dir%/} # Initialize the name of the makefile source variable. if [ -n "$prefix_flag" ]; then # If prefix_flag is not null, then we construct src_var_name using # it instead of root_dir. So if the prefix is 'junk', we will get # makefile variables that begin with 'MK_JUNK'. root_dir_upper=$(echo "$prefix_flag" | tr '[:lower:]' '[:upper:]') src_var_name="${src_var_name_prefix}_${root_dir_upper}" else # Otherwise, we use root_dir. If the root directory is 'foo' then # makefile variables will begin with 'MK_FOO'. # We are also careful to convert forward slashes into underscore so # root directories such as foo/bar result in makefile variables # that begin with 'MK_FOO_BAR'. root_dir_upper=$(echo "$root_dir" | tr '[:lower:]' '[:upper:]') root_dir_upper=$(echo "$root_dir_upper" | tr '/' '_') src_var_name="${src_var_name_prefix}_${root_dir_upper}" fi # Be verbose if level 2 was requested. if [ "$verbose_flag" = "2" ]; then echo ">>>" $script_name ${src_var_name}_$SRC $root_dir $frag_dir elif [ "$verbose_flag" = "1" ]; then echo "$script_name: creating makefile fragment in $frag_dir from $root_dir" fi # Call our function to generate a makefile in the root directory given. gen_mkfile "${src_var_name}_$SRC" $root_dir $frag_dir # If we were asked to act recursively, then continue processing # root_dir's contents. if [ -n "$recursive_flag" ]; then # Get a listing of the directories in $directory. sub_items=$(ls $root_dir) # Descend into the contents of root_dir to generate the makefile # fragments. for item in $sub_items; do # If item is a directory, and it's not in the ignore list, descend into it. #if [ -d "$root_dir/$item" ] && ! should_ignore $item ; then if [ -d "$root_dir/$item" ] && ! is_in_list $item "$ignore_dirs" ; then gen_mkfiles $root_dir/$item $frag_dir/$item fi done fi # Exit peacefully. return 0 } is_in_list() { local cur_item the_item item_list # Extract argument. the_item="$1" item_list="$2" # Check each item in the list against the item of interest. for cur_item in ${item_list}; do # If the current item in the list matches the one of interest. if [ "${cur_item}" = "${the_item}" ]; then # Return success (ie: item was found). return 0 fi done # If we made it this far, return failure (ie: item not found). return 1 } # The script's main entry point, passing all parameters given. main "$@" blis-0.9.0/build/gen-make-frags/ignore_list000066400000000000000000000000621422157504600206010ustar00rootroot00000000000000attic broken old other temp tmp test p10_testsuiteblis-0.9.0/build/gen-make-frags/special_list000066400000000000000000000000161422157504600207350ustar00rootroot00000000000000noopt kernels blis-0.9.0/build/gen-make-frags/suffix_list000066400000000000000000000000211422157504600206150ustar00rootroot00000000000000c cc cpp cxx s S blis-0.9.0/build/irun.py000077500000000000000000000241441422157504600151150ustar00rootroot00000000000000#!/usr/bin/env python3 # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2018, The University of Texas at Austin # Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # # Import modules import os import sys import getopt import re import subprocess import time import statistics def print_usage(): my_print( " " ) my_print( " %s" % script_name ) my_print( " " ) my_print( " Field G. Van Zee" ) my_print( " " ) my_print( " Repeatedly run a test driver and accumulate statistics for the" ) my_print( " output." ) my_print( " " ) my_print( " Usage:" ) my_print( " " ) my_print( " %s [options] drivername" % script_name ) my_print( " " ) my_print( " Arguments:" ) my_print( " " ) my_print( " drivername The filename/path of the test driver to run. The" ) my_print( " test driver must output its performance data to" ) my_print( " standard output." ) my_print( " " ) my_print( " The following options are accepted:" ) my_print( " " ) my_print( " -c num performance column index" ) my_print( " Find the performance result in column index of" ) my_print( " the test driver's output. Here, a column is defined" ) my_print( " as a contiguous sequence of non-whitespace characters," ) my_print( " with the column indices beginning at 0. By default," ) my_print( " the second-to-last column index in the output is used." ) my_print( " " ) my_print( " -d delay sleep() delay" ) my_print( " Wait seconds after each execution of the" ) my_print( " test driver. The default delay is 0." ) my_print( " " ) my_print( " -n niter number of iterations" ) my_print( " Execute the test driver times. The default" ) my_print( " value is 10." ) my_print( " " ) my_print( " -q quiet; summary only" ) my_print( " Do not output statistics after every new execution of" ) my_print( " the test driver; instead, only output the final values" ) my_print( " after all iterations are complete. The default is to" ) my_print( " output updated statistics after each iteration." ) my_print( " " ) my_print( " -h help" ) my_print( " Output this information and exit." ) my_print( " " ) # ------------------------------------------------------------------------------ def my_print( s ): sys.stdout.write( "%s\n" % s ) #sys.stdout.flush() # ------------------------------------------------------------------------------ # Global variables. script_name = None output_name = None def main(): global script_name global output_name # Obtain the script name. path, script_name = os.path.split(sys.argv[0]) output_name = script_name # Default values for optional arguments. #perf_col = 9 perf_col = -1 delay = 0 niter = 10 quiet = False # Process our command line options. try: opts, args = getopt.getopt( sys.argv[1:], "c:d:n:hq" ) except getopt.GetoptError as err: # print help information and exit: my_print( str(err) ) # will print something like "option -a not recognized" print_usage() sys.exit(2) for opt, optarg in opts: if opt == "-c": perf_col = optarg elif opt == "-d": delay = optarg elif opt == "-n": niter = optarg elif opt == "-q": quiet = True elif opt == "-h": print_usage() sys.exit() else: print_usage() sys.exit() # Print usage if we don't have exactly one argument. if len( args ) != 1: print_usage() sys.exit() # Acquire our only mandatory argument: the name of the test driver. driverfile = args[0] #my_print( "test driver: %s" % driverfile ) #my_print( "column num: %s" % perf_col ) #my_print( "delay: %s" % delay ) #my_print( "num iter: %s" % niter ) # Build a list of iterations. iters = range( int(niter) ) # Run the test driver once to detect the number of lines of output. p = subprocess.run( driverfile, stdout=subprocess.PIPE ) lines0 = p.stdout.decode().splitlines() num_lines0 = int(len(lines0)) # Initialize the list of lists (one list per performance result). aperf = [] for i in range( num_lines0 ): aperf.append( [] ) for it in iters: # Run the test driver. p = subprocess.run( driverfile, stdout=subprocess.PIPE ) # Acquire the lines of output. lines = p.stdout.decode().splitlines() # Accumulate the test driver's latest results into aperf. for i in range( num_lines0 ): # Parse the current line to find the performance value. line = lines[i] words = line.split() if perf_col == -1: perf = words[ len(words)-2 ] else: perf = words[ int(perf_col) ] # As unlikely as it is, guard against Inf and NaN. if float(perf) == float('Inf') or \ float(perf) == -float('Inf') or \ float(perf) == float('NaN'): perf = 0.0 # Add the performance value to the list at the ith entry of aperf. aperf[i].append( float(perf) ) # Compute stats for the current line. avgp = statistics.mean( aperf[i] ) maxp = max( aperf[i] ) minp = min( aperf[i] ) # Only compute stdev() when we have two or more data points. if len( aperf[i] ) > 1: stdp = statistics.stdev( aperf[i] ) else: stdp = 0.0 # Construct a string to match the performance value and then # use that string to search-and-replace with four format specs # for the min, avg, max, and stdev values computed above. search = '%8s' % perf newline = re.sub( str(search), ' %7.2f %7.2f %7.2f %6.2f', line ) # Search for the column index range that would be present if this were # matlab-compatible output. The index range will typically be 1:n, # where n is the number of columns of data. found_index = False for word in words: if re.match( '1:', word ): index_str = word found_index = True break # If we find the column index range, we need to update it to reflect # the replacement of one column of data with four, for a net increase # of columns. We do so via another instance of re.sub() in which we # search for the old index string and replace it with the new one. if found_index: last_col = int(index_str[2]) + 3 new_index_str = '1:%1s' % last_col newline = re.sub( index_str, new_index_str, newline ) # If the quiet flag was not give, output the intermediate results. if not quiet: print( newline % ( float(minp), float(avgp), float(maxp), float(stdp) ) ) # Flush stdout after each set of output prior to sleeping. sys.stdout.flush() # Sleep for a bit until the next iteration. time.sleep( int(delay) ) # If the quiet flag was given, output the final results. if quiet: for i in range( num_lines0 ): # Parse the current line to find the performance value (only # needed for call to re.sub() below). line = lines0[i] words = line.split() if perf_col == -1: perf = words[ len(words)-2 ] else: perf = words[ int(perf_col) ] # Compute stats for the current line. avgp = statistics.mean( aperf[i] ) maxp = max( aperf[i] ) minp = min( aperf[i] ) # Only compute stdev() when we have two or more data points. if len( aperf[i] ) > 1: stdp = statistics.stdev( aperf[i] ) else: stdp = 0.0 # Construct a string to match the performance value and then # use that string to search-and-replace with four format specs # for the min, avg, max, and stdev values computed above. search = '%8s' % perf newline = re.sub( str(search), ' %7.2f %7.2f %7.2f %6.2f', line ) # Search for the column index range that would be present if this were # matlab-compatible output. The index range will typically be 1:n, # where n is the number of columns of data. found_index = False for word in words: if re.match( '1:', word ): index_str = word found_index = True break # If we find the column index range, we need to update it to reflect # the replacement of one column of data with four, for a net increase # of columns. We do so via another instance of re.sub() in which we # search for the old index string and replace it with the new one. if found_index: last_col = int(index_str[2]) + 3 new_index_str = '1:%1s' % last_col newline = re.sub( index_str, new_index_str, newline ) # Output the results for the current line. print( newline % ( float(minp), float(avgp), float(maxp), float(stdp) ) ) # Flush stdout afterwards. sys.stdout.flush() # Return from main(). return 0 if __name__ == "__main__": main() blis-0.9.0/build/libblis-symbols.def000066400000000000000000001300051422157504600173430ustar00rootroot00000000000000EXPORTS bli_abort bli_absqsc bli_absqsc_check bli_absqsc_qfp bli_acquire_mij bli_acquire_mpart bli_acquire_mpart_b2t bli_acquire_mpart_br2tl bli_acquire_mpart_l2r bli_acquire_mpart_l2r_check bli_acquire_mpart_mdim bli_acquire_mpart_mndim bli_acquire_mpart_ndim bli_acquire_mpart_r2l bli_acquire_mpart_t2b bli_acquire_mpart_t2b_check bli_acquire_mpart_tl2br bli_acquire_mpart_tl2br_check bli_acquire_vi bli_acquire_vpart_b2f bli_acquire_vpart_f2b bli_addd bli_addd_check bli_addd_ex bli_addd_ex_qfp bli_addm bli_addm_check bli_addm_ex bli_addm_ex_qfp bli_addsc bli_addsc_check bli_addsc_qfp bli_addv bli_addv_check bli_addv_ex bli_addv_ex_qfp bli_adjust_strides bli_align_dim_to_mult bli_align_dim_to_size bli_align_ptr_to_size bli_amaxv bli_amaxv_check bli_amaxv_ex bli_amaxv_ex_qfp bli_apool_alloc_block bli_apool_array_elem bli_apool_checkin_array bli_apool_checkout_array bli_apool_finalize bli_apool_free_block bli_apool_grow bli_apool_init bli_arch_query_id bli_arch_set_id bli_arch_set_id_once bli_arch_string bli_array_elem bli_array_finalize bli_array_init bli_array_resize bli_array_set_elem bli_asumv bli_asumv_check bli_asumv_ex bli_asumv_ex_qfp bli_axpbyv bli_axpbyv_check bli_axpbyv_ex bli_axpbyv_ex_qfp bli_axpy2v bli_axpy2v_check bli_axpy2v_ex bli_axpy2v_ex_qfp bli_axpyd bli_axpyd_check bli_axpyd_ex bli_axpyd_ex_qfp bli_axpyf bli_axpyf_check bli_axpyf_ex bli_axpyf_ex_qfp bli_axpym bli_axpym_check bli_axpym_ex bli_axpym_ex_qfp bli_axpyv bli_axpyv_check bli_axpyv_ex bli_axpyv_ex_qfp bli_blksz_create bli_blksz_create_ed bli_blksz_free bli_blksz_init bli_blksz_init_easy bli_blksz_init_ed bli_blksz_reduce_def_to bli_blksz_reduce_max_to bli_cabsqsc bli_caddd bli_caddd_ex bli_caddm bli_caddm_ex bli_caddm_unb_var1 bli_caddsc bli_caddv bli_caddv_ex bli_calloc_intl bli_camaxv bli_camaxv_ex bli_castm bli_castm_check bli_castnzm bli_castnzm_check bli_castv bli_castv_check bli_casumv bli_casumv_ex bli_casumv_unb_var1 bli_caxpbyv bli_caxpbyv_ex bli_caxpy2v bli_caxpy2v_ex bli_caxpyd bli_caxpyd_ex bli_caxpyf bli_caxpyf_ex bli_caxpym bli_caxpym_ex bli_caxpym_unb_var1 bli_caxpyv bli_caxpyv_ex bli_cccastm bli_cccastnzm bli_cccastv bli_cccopysc bli_ccgemm_ker_var2_md bli_ccopyd bli_ccopyd_ex bli_ccopym bli_ccopym_ex bli_ccopym_unb_var1 bli_ccopyv bli_ccopyv_ex bli_ccpackm_blk_var1_md bli_ccpackm_cxk_1e_md bli_ccpackm_cxk_1r_md bli_ccpackm_struc_cxk_md bli_ccxpbym_md bli_ccxpbym_md_ex bli_ccxpbym_md_unb_var1 bli_cdcastm bli_cdcastnzm bli_cdcastv bli_cdcopysc bli_cdgemm_ker_var2_md bli_cdivsc bli_cdotaxpyv bli_cdotaxpyv_ex bli_cdotv bli_cdotv_ex bli_cdotxaxpyf bli_cdotxaxpyf_ex bli_cdotxf bli_cdotxf_ex bli_cdotxv bli_cdotxv_ex bli_cdpackm_blk_var1_md bli_cdpackm_cxk_1e_md bli_cdpackm_cxk_1r_md bli_cdpackm_struc_cxk_md bli_cdxpbym_md bli_cdxpbym_md_ex bli_cdxpbym_md_unb_var1 bli_cfprintm bli_cfprintv bli_cgemm bli_cgemm1m bli_cgemm3m1 bli_cgemm3mh bli_cgemm4m1 bli_cgemm4mb bli_cgemm4mb_ker_var2 bli_cgemm4mh bli_cgemm_ex bli_cgemm_ker_var2 bli_cgemm_md_c2r_ref bli_cgemmtrsm_l_ukernel bli_cgemmtrsm_u_ukernel bli_cgemm_ukernel bli_cgemv bli_cgemv_ex bli_cgemv_unb_var1 bli_cgemv_unb_var2 bli_cgemv_unf_var1 bli_cgemv_unf_var2 bli_cger bli_cger_ex bli_cger_unb_var1 bli_cger_unb_var2 bli_cgetijm bli_cgetsc bli_check_alignment_is_mult_of_ptr_size bli_check_alignment_is_power_of_two bli_check_conformal_dims bli_check_consistent_datatypes bli_check_consistent_object_datatypes bli_check_consistent_object_precisions bli_check_consistent_precisions bli_check_datatype_real_proj_of bli_check_equal_vector_lengths bli_check_error_code_helper bli_check_floating_datatype bli_check_floating_object bli_check_general_object bli_check_hermitian_object bli_check_if_exhausted_pool bli_check_integer_datatype bli_check_integer_object bli_check_level3_dims bli_check_matrix_object bli_check_matrix_strides bli_check_nonconstant_datatype bli_check_nonconstant_object bli_check_noninteger_datatype bli_check_noninteger_object bli_check_nonunit_diag bli_check_null_pointer bli_check_object_alias_of bli_check_object_buffer bli_check_object_diag_offset_equals bli_check_object_length_equals bli_check_object_real_proj_of bli_check_object_struc bli_check_object_valid_datatype bli_check_object_width_equals bli_check_packm_schema_on_unpack bli_check_packv_schema_on_unpack bli_check_real_datatype bli_check_real_object bli_check_real_valued_object bli_check_scalar_object bli_check_square_object bli_check_sufficient_stack_buf_size bli_check_symmetric_object bli_check_triangular_object bli_check_upper_or_lower_object bli_check_valid_1x3_subpart bli_check_valid_3x1_subpart bli_check_valid_3x3_subpart bli_check_valid_arch_id bli_check_valid_cntl bli_check_valid_datatype bli_check_valid_diag bli_check_valid_error_level bli_check_valid_kc_mod_mult bli_check_valid_malloc_buf bli_check_valid_mc_mod_mult bli_check_valid_nc_mod_mult bli_check_valid_packbuf bli_check_valid_side bli_check_valid_trans bli_check_valid_uplo bli_check_vector_dim_equals bli_check_vector_object bli_chemm bli_chemm1m bli_chemm3m1 bli_chemm3mh bli_chemm4m1 bli_chemm4mh bli_chemm_ex bli_chemv bli_chemv_ex bli_chemv_unb_var1 bli_chemv_unb_var2 bli_chemv_unb_var3 bli_chemv_unb_var4 bli_chemv_unf_var1 bli_chemv_unf_var1a bli_chemv_unf_var3 bli_chemv_unf_var3a bli_cher bli_cher2 bli_cher2_ex bli_cher2k bli_cher2k1m bli_cher2k3m1 bli_cher2k3mh bli_cher2k4m1 bli_cher2k4mh bli_cher2k_ex bli_cher2_unb_var1 bli_cher2_unb_var2 bli_cher2_unb_var3 bli_cher2_unb_var4 bli_cher2_unf_var1 bli_cher2_unf_var4 bli_cher_ex bli_cherk bli_cherk1m bli_cherk3m1 bli_cherk3mh bli_cherk4m1 bli_cherk4mh bli_cherk_ex bli_cherk_l_ker_var2 bli_cherk_u_ker_var2 bli_cher_unb_var1 bli_cher_unb_var2 bli_cinvertd bli_cinvertd_ex bli_cinvertsc bli_cinvertv bli_cinvertv_ex bli_clock bli_clock_helper bli_clock_min_diff bli_cmachval bli_cmkherm bli_cmkherm_ex bli_cmkherm_unb_var1 bli_cmksymm bli_cmksymm_ex bli_cmksymm_unb_var1 bli_cmktrim bli_cmktrim_ex bli_cmktrim_unb_var1 bli_cmulsc bli_cnorm1m bli_cnorm1m_ex bli_cnorm1m_unb_var1 bli_cnorm1v bli_cnorm1v_ex bli_cnorm1v_unb_var1 bli_cnormfm bli_cnormfm_ex bli_cnormfm_unb_var1 bli_cnormfsc bli_cnormfv bli_cnormfv_ex bli_cnormfv_unb_var1 bli_cnormim bli_cnormim_ex bli_cnormim_unb_var1 bli_cnormiv bli_cnormiv_ex bli_cnormiv_unb_var1 bli_cntl_calc_num_threads_in bli_cntl_clear_node bli_cntl_copy bli_cntl_create_node bli_cntl_free bli_cntl_free_node bli_cntl_free_wo_thrinfo bli_cntl_free_w_thrinfo bli_cntl_mark_family bli_cntx_1m_stage bli_cntx_3m1_stage bli_cntx_3mh_stage bli_cntx_4m1_stage bli_cntx_4mb_stage bli_cntx_4mh_stage bli_cntx_clear bli_cntx_ind_stage bli_cntx_nat_stage bli_cntx_print bli_cntx_set_blkszs bli_cntx_set_ind_blkszs bli_cntx_set_l1f_kers bli_cntx_set_l1v_kers bli_cntx_set_l3_nat_ukrs bli_cntx_set_packm_kers bli_copyd bli_copyd_check bli_copyd_ex bli_copyd_ex_qfp bli_copym bli_copym_check bli_copym_ex bli_copym_ex_qfp bli_copysc bli_copysc_check bli_copyv bli_copyv_check bli_copyv_ex bli_copyv_ex_qfp bli_cpackm_blk_var1 bli_cpackm_cxk bli_cpackm_cxk_1er bli_cpackm_cxk_3mis bli_cpackm_cxk_4mi bli_cpackm_cxk_rih bli_cpackm_herm_cxk bli_cpackm_herm_cxk_1er bli_cpackm_herm_cxk_3mis bli_cpackm_herm_cxk_4mi bli_cpackm_herm_cxk_rih bli_cpackm_struc_cxk bli_cpackm_struc_cxk_1er bli_cpackm_struc_cxk_3mis bli_cpackm_struc_cxk_4mi bli_cpackm_struc_cxk_rih bli_cpackm_tri_cxk bli_cpackm_tri_cxk_1er bli_cpackm_tri_cxk_3mis bli_cpackm_tri_cxk_4mi bli_cpackm_tri_cxk_rih bli_cpackm_unb_var1 bli_cprintm bli_cprintm_ex bli_cprintv bli_cprintv_ex bli_cpuid_is_bulldozer bli_cpuid_is_excavator bli_cpuid_is_haswell bli_cpuid_is_knl bli_cpuid_is_penryn bli_cpuid_is_piledriver bli_cpuid_is_sandybridge bli_cpuid_is_skx bli_cpuid_is_steamroller bli_cpuid_is_zen bli_cpuid_query bli_cpuid_query_id bli_crandm bli_crandm_ex bli_crandm_unb_var1 bli_crandnm bli_crandnm_ex bli_crandnm_unb_var1 bli_crandnv bli_crandnv_ex bli_crandnv_unb_var1 bli_crandv bli_crandv_ex bli_crandv_unb_var1 bli_cscal2d bli_cscal2d_ex bli_cscal2m bli_cscal2m_ex bli_cscal2m_unb_var1 bli_cscal2v bli_cscal2v_ex bli_cscald bli_cscald_ex bli_cscalm bli_cscalm_ex bli_cscalm_unb_var1 bli_cscalv bli_cscalv_ex bli_cscastm bli_cscastnzm bli_cscastv bli_cscopysc bli_csetd bli_csetd_ex bli_csetid bli_csetid_ex bli_csetijm bli_csetm bli_csetm_ex bli_csetm_unb_var1 bli_csetsc bli_csetv bli_csetv_ex bli_csgemm_ker_var2_md bli_cshiftd bli_cshiftd_ex bli_cspackm_blk_var1_md bli_cspackm_cxk_1e_md bli_cspackm_cxk_1r_md bli_cspackm_struc_cxk_md bli_csqrtsc bli_csubd bli_csubd_ex bli_csubm bli_csubm_ex bli_csubm_unb_var1 bli_csubsc bli_csubv bli_csubv_ex bli_csumsqv bli_csumsqv_ex bli_csumsqv_unb_var1 bli_cswapv bli_cswapv_ex bli_csxpbym_md bli_csxpbym_md_ex bli_csxpbym_md_unb_var1 bli_csymm bli_csymm1m bli_csymm3m1 bli_csymm3mh bli_csymm4m1 bli_csymm4mh bli_csymm_ex bli_csymv bli_csymv_ex bli_csyr bli_csyr2 bli_csyr2_ex bli_csyr2k bli_csyr2k1m bli_csyr2k3m1 bli_csyr2k3mh bli_csyr2k4m1 bli_csyr2k4mh bli_csyr2k_ex bli_csyr_ex bli_csyrk bli_csyrk1m bli_csyrk3m1 bli_csyrk3mh bli_csyrk4m1 bli_csyrk4mh bli_csyrk_ex bli_ctrmm bli_ctrmm1m bli_ctrmm3 bli_ctrmm31m bli_ctrmm33m1 bli_ctrmm33mh bli_ctrmm34m1 bli_ctrmm34mh bli_ctrmm3_ex bli_ctrmm3m1 bli_ctrmm4m1 bli_ctrmm_ex bli_ctrmm_ll_ker_var2 bli_ctrmm_lu_ker_var2 bli_ctrmm_rl_ker_var2 bli_ctrmm_ru_ker_var2 bli_ctrmv bli_ctrmv_ex bli_ctrmv_unb_var1 bli_ctrmv_unb_var2 bli_ctrmv_unf_var1 bli_ctrmv_unf_var2 bli_ctrsm bli_ctrsm1m bli_ctrsm3m1 bli_ctrsm4m1 bli_ctrsm_ex bli_ctrsm_ll_ker_var2 bli_ctrsm_l_ukernel bli_ctrsm_lu_ker_var2 bli_ctrsm_rl_ker_var2 bli_ctrsm_ru_ker_var2 bli_ctrsm_u_ukernel bli_ctrsv bli_ctrsv_ex bli_ctrsv_unb_var1 bli_ctrsv_unb_var2 bli_ctrsv_unf_var1 bli_ctrsv_unf_var2 bli_cunpackm_blk_var1 bli_cunpackm_cxk bli_cunpackm_unb_var1 bli_cunzipsc bli_cxpbyd bli_cxpbyd_ex bli_cxpbym bli_cxpbym_ex bli_cxpbym_unb_var1 bli_cxpbyv bli_cxpbyv_ex bli_czcastm bli_czcastnzm bli_czcastv bli_czcopysc bli_czgemm_ker_var2_md bli_czipsc bli_czpackm_blk_var1_md bli_czpackm_cxk_1e_md bli_czpackm_cxk_1r_md bli_czpackm_struc_cxk_md bli_czxpbym_md bli_czxpbym_md_ex bli_czxpbym_md_unb_var1 bli_dabsqsc bli_daddd bli_daddd_ex bli_daddm bli_daddm_ex bli_daddm_unb_var1 bli_daddsc bli_daddv bli_daddv_ex bli_damaxv bli_damaxv_ex bli_dasumv bli_dasumv_ex bli_dasumv_unb_var1 bli_daxpbyv bli_daxpbyv_ex bli_daxpy2v bli_daxpy2v_ex bli_daxpyd bli_daxpyd_ex bli_daxpyf bli_daxpyf_ex bli_daxpym bli_daxpym_ex bli_daxpym_unb_var1 bli_daxpyv bli_daxpyv_ex bli_dccastm bli_dccastnzm bli_dccastv bli_dccopysc bli_dcgemm_ker_var2_md bli_dcopyd bli_dcopyd_ex bli_dcopym bli_dcopym_ex bli_dcopym_unb_var1 bli_dcopyv bli_dcopyv_ex bli_dcpackm_blk_var1_md bli_dcpackm_cxk_1e_md bli_dcpackm_cxk_1r_md bli_dcpackm_struc_cxk_md bli_dcxpbym_md bli_dcxpbym_md_ex bli_dcxpbym_md_unb_var1 bli_ddcastm bli_ddcastnzm bli_ddcastv bli_ddcopysc bli_ddgemm_ker_var2_md bli_ddivsc bli_ddotaxpyv bli_ddotaxpyv_ex bli_ddotv bli_ddotv_ex bli_ddotxaxpyf bli_ddotxaxpyf_ex bli_ddotxf bli_ddotxf_ex bli_ddotxv bli_ddotxv_ex bli_ddpackm_blk_var1_md bli_ddpackm_cxk_1e_md bli_ddpackm_cxk_1r_md bli_ddpackm_struc_cxk_md bli_ddxpbym_md bli_ddxpbym_md_ex bli_ddxpbym_md_unb_var1 bli_determine_blocksize bli_determine_blocksize_b bli_determine_blocksize_b_sub bli_determine_blocksize_f bli_determine_blocksize_f_sub bli_dfprintm bli_dfprintv bli_dgemm bli_dgemm1m bli_dgemm3m1 bli_dgemm3mh bli_dgemm4m1 bli_dgemm4mb bli_dgemm4mb_ker_var2 bli_dgemm4mh bli_dgemm_ex bli_dgemm_ker_var2 bli_dgemmtrsm_l_ukernel bli_dgemmtrsm_u_ukernel bli_dgemm_ukernel bli_dgemv bli_dgemv_ex bli_dgemv_unb_var1 bli_dgemv_unb_var2 bli_dgemv_unf_var1 bli_dgemv_unf_var2 bli_dger bli_dger_ex bli_dger_unb_var1 bli_dger_unb_var2 bli_dgetijm bli_dgetsc bli_dhemm bli_dhemm1m bli_dhemm3m1 bli_dhemm3mh bli_dhemm4m1 bli_dhemm4mh bli_dhemm_ex bli_dhemv bli_dhemv_ex bli_dhemv_unb_var1 bli_dhemv_unb_var2 bli_dhemv_unb_var3 bli_dhemv_unb_var4 bli_dhemv_unf_var1 bli_dhemv_unf_var1a bli_dhemv_unf_var3 bli_dhemv_unf_var3a bli_dher bli_dher2 bli_dher2_ex bli_dher2k bli_dher2k1m bli_dher2k3m1 bli_dher2k3mh bli_dher2k4m1 bli_dher2k4mh bli_dher2k_ex bli_dher2_unb_var1 bli_dher2_unb_var2 bli_dher2_unb_var3 bli_dher2_unb_var4 bli_dher2_unf_var1 bli_dher2_unf_var4 bli_dher_ex bli_dherk bli_dherk1m bli_dherk3m1 bli_dherk3mh bli_dherk4m1 bli_dherk4mh bli_dherk_ex bli_dherk_l_ker_var2 bli_dherk_u_ker_var2 bli_dher_unb_var1 bli_dher_unb_var2 bli_dinvertd bli_dinvertd_ex bli_dinvertsc bli_dinvertv bli_dinvertv_ex bli_divsc bli_divsc_check bli_divsc_qfp bli_dlamch bli_dmachval bli_dmkherm bli_dmkherm_ex bli_dmkherm_unb_var1 bli_dmksymm bli_dmksymm_ex bli_dmksymm_unb_var1 bli_dmktrim bli_dmktrim_ex bli_dmktrim_unb_var1 bli_dmulsc bli_dnorm1m bli_dnorm1m_ex bli_dnorm1m_unb_var1 bli_dnorm1v bli_dnorm1v_ex bli_dnorm1v_unb_var1 bli_dnormfm bli_dnormfm_ex bli_dnormfm_unb_var1 bli_dnormfsc bli_dnormfv bli_dnormfv_ex bli_dnormfv_unb_var1 bli_dnormim bli_dnormim_ex bli_dnormim_unb_var1 bli_dnormiv bli_dnormiv_ex bli_dnormiv_unb_var1 bli_dotaxpyv bli_dotaxpyv_check bli_dotaxpyv_ex bli_dotaxpyv_ex_qfp bli_dotv bli_dotv_check bli_dotv_ex bli_dotv_ex_qfp bli_dotxaxpyf bli_dotxaxpyf_check bli_dotxaxpyf_ex bli_dotxaxpyf_ex_qfp bli_dotxf bli_dotxf_check bli_dotxf_ex bli_dotxf_ex_qfp bli_dotxv bli_dotxv_check bli_dotxv_ex bli_dotxv_ex_qfp bli_dpackm_blk_var1 bli_dpackm_cxk bli_dpackm_herm_cxk bli_dpackm_struc_cxk bli_dpackm_tri_cxk bli_dpackm_unb_var1 bli_dprintm bli_dprintm_ex bli_dprintv bli_dprintv_ex bli_drandm bli_drandm_ex bli_drandm_unb_var1 bli_drandnm bli_drandnm_ex bli_drandnm_unb_var1 bli_drandnv bli_drandnv_ex bli_drandnv_unb_var1 bli_drandv bli_drandv_ex bli_drandv_unb_var1 bli_dscal2d bli_dscal2d_ex bli_dscal2m bli_dscal2m_ex bli_dscal2m_unb_var1 bli_dscal2v bli_dscal2v_ex bli_dscald bli_dscald_ex bli_dscalm bli_dscalm_ex bli_dscalm_unb_var1 bli_dscalv bli_dscalv_ex bli_dscastm bli_dscastnzm bli_dscastv bli_dscopysc bli_dsetd bli_dsetd_ex bli_dsetid bli_dsetid_ex bli_dsetijm bli_dsetm bli_dsetm_ex bli_dsetm_unb_var1 bli_dsetsc bli_dsetv bli_dsetv_ex bli_dsgemm_ker_var2_md bli_dshiftd bli_dshiftd_ex bli_dspackm_blk_var1_md bli_dspackm_cxk_1e_md bli_dspackm_cxk_1r_md bli_dspackm_struc_cxk_md bli_dsqrtsc bli_dsubd bli_dsubd_ex bli_dsubm bli_dsubm_ex bli_dsubm_unb_var1 bli_dsubsc bli_dsubv bli_dsubv_ex bli_dsumsqv bli_dsumsqv_ex bli_dsumsqv_unb_var1 bli_dswapv bli_dswapv_ex bli_dsxpbym_md bli_dsxpbym_md_ex bli_dsxpbym_md_unb_var1 bli_dsymm bli_dsymm1m bli_dsymm3m1 bli_dsymm3mh bli_dsymm4m1 bli_dsymm4mh bli_dsymm_ex bli_dsymv bli_dsymv_ex bli_dsyr bli_dsyr2 bli_dsyr2_ex bli_dsyr2k bli_dsyr2k1m bli_dsyr2k3m1 bli_dsyr2k3mh bli_dsyr2k4m1 bli_dsyr2k4mh bli_dsyr2k_ex bli_dsyr_ex bli_dsyrk bli_dsyrk1m bli_dsyrk3m1 bli_dsyrk3mh bli_dsyrk4m1 bli_dsyrk4mh bli_dsyrk_ex bli_dtrmm bli_dtrmm1m bli_dtrmm3 bli_dtrmm31m bli_dtrmm33m1 bli_dtrmm33mh bli_dtrmm34m1 bli_dtrmm34mh bli_dtrmm3_ex bli_dtrmm3m1 bli_dtrmm4m1 bli_dtrmm_ex bli_dtrmm_ll_ker_var2 bli_dtrmm_lu_ker_var2 bli_dtrmm_rl_ker_var2 bli_dtrmm_ru_ker_var2 bli_dtrmv bli_dtrmv_ex bli_dtrmv_unb_var1 bli_dtrmv_unb_var2 bli_dtrmv_unf_var1 bli_dtrmv_unf_var2 bli_dtrsm bli_dtrsm1m bli_dtrsm3m1 bli_dtrsm4m1 bli_dtrsm_ex bli_dtrsm_ll_ker_var2 bli_dtrsm_l_ukernel bli_dtrsm_lu_ker_var2 bli_dtrsm_rl_ker_var2 bli_dtrsm_ru_ker_var2 bli_dtrsm_u_ukernel bli_dtrsv bli_dtrsv_ex bli_dtrsv_unb_var1 bli_dtrsv_unb_var2 bli_dtrsv_unf_var1 bli_dtrsv_unf_var2 bli_dt_size bli_dt_size_check bli_dt_string bli_dt_string_check bli_dt_union_check bli_dunpackm_blk_var1 bli_dunpackm_cxk bli_dunpackm_unb_var1 bli_dunzipsc bli_dxpbyd bli_dxpbyd_ex bli_dxpbym bli_dxpbym_ex bli_dxpbym_unb_var1 bli_dxpbyv bli_dxpbyv_ex bli_dzcastm bli_dzcastnzm bli_dzcastv bli_dzcopysc bli_dzgemm_ker_var2_md bli_dzipsc bli_dzpackm_blk_var1_md bli_dzpackm_cxk_1e_md bli_dzpackm_cxk_1r_md bli_dzpackm_struc_cxk_md bli_dzxpbym_md bli_dzxpbym_md_ex bli_dzxpbym_md_unb_var1 bli_error_checking_is_enabled bli_error_checking_level bli_error_checking_level_set bli_error_string_for_code bli_ffree_align bli_ffree_noalign bli_finalize bli_finalize_apis bli_finalize_auto bli_finalize_once bli_find_area_trap_l bli_fmalloc_align bli_fmalloc_align_check bli_fmalloc_noalign bli_fmalloc_post_check bli_fprintm bli_fprintm_check bli_fprintm_ex bli_fprintm_qfp bli_fprintv bli_fprintv_check bli_fprintv_ex bli_fprintv_qfp bli_free_intl bli_free_user bli_func_create bli_func_free bli_func_init bli_func_init_null bli_func_is_null bli_func_is_null_dt bli_gcd bli_gemm bli_gemm1m bli_gemm3m1 bli_gemm3mh bli_gemm4m1 bli_gemm4mb bli_gemm4mb_ker_var2 bli_gemm4mh bli_gemm_basic_check bli_gemm_blk_var1 bli_gemm_blk_var2 bli_gemm_blk_var3 bli_gemmbp_cntl_create bli_gemm_check bli_gemm_cntl_create bli_gemm_cntl_create_node bli_gemm_cntl_free bli_gemm_determine_kc bli_gemm_determine_kc_b bli_gemm_determine_kc_f bli_gemm_direct bli_gemm_ex bli_gemm_front bli_gemmind bli_gemmind_get_avail bli_gemm_int bli_gemm_ker_var2 bli_gemm_ker_var2_md bli_gemm_md bli_gemm_md_ccc bli_gemm_md_ccr bli_gemm_md_crc bli_gemm_md_crr bli_gemm_md_rcc bli_gemm_md_rcr bli_gemm_md_rrc bli_gemm_md_rrr bli_gemmnat bli_gemm_packa bli_gemm_packb bli_gemm_prune_unref_mparts_k bli_gemm_prune_unref_mparts_m bli_gemm_prune_unref_mparts_n bli_gemmtrsm_l_ukernel_qfp bli_gemmtrsm_ukernel bli_gemmtrsm_u_ukernel_qfp bli_gemm_ukernel bli_gemm_ukernel_qfp bli_gemv bli_gemv_check bli_gemv_ex bli_gemv_ex_qfp bli_gemv_unb_var1 bli_gemv_unb_var1_qfp bli_gemv_unb_var2 bli_gemv_unb_var2_qfp bli_gemv_unf_var1 bli_gemv_unf_var1_qfp bli_gemv_unf_var2 bli_gemv_unf_var2_qfp bli_ger bli_ger_check bli_ger_ex bli_ger_ex_qfp bli_ger_unb_var1 bli_ger_unb_var1_qfp bli_ger_unb_var2 bli_ger_unb_var2_qfp bli_getijm bli_getopt bli_getopt_init_state bli_getsc bli_getsc_check bli_getsc_qfp bli_gks_cntx_l3_nat_ukr_is_ref bli_gks_finalize bli_gks_init bli_gks_init_index bli_gks_init_ref_cntx bli_gks_l3_ukr_impl_string bli_gks_l3_ukr_impl_type bli_gks_lookup_ind_cntx bli_gks_lookup_nat_cntx bli_gks_query_cntx bli_gks_query_cntx_noinit bli_gks_query_ind_cntx bli_gks_query_nat_cntx bli_gks_register_cntx bli_hemm bli_hemm1m bli_hemm3m1 bli_hemm3mh bli_hemm4m1 bli_hemm4mh bli_hemm_basic_check bli_hemm_check bli_hemm_ex bli_hemm_front bli_hemmind bli_hemmind_get_avail bli_hemmnat bli_hemv bli_hemv_check bli_hemv_ex bli_hemv_ex_qfp bli_hemv_unb_var1 bli_hemv_unb_var1_qfp bli_hemv_unb_var2 bli_hemv_unb_var2_qfp bli_hemv_unb_var3 bli_hemv_unb_var3_qfp bli_hemv_unb_var4 bli_hemv_unb_var4_qfp bli_hemv_unf_var1 bli_hemv_unf_var1a bli_hemv_unf_var1a_qfp bli_hemv_unf_var1_qfp bli_hemv_unf_var3 bli_hemv_unf_var3a bli_hemv_unf_var3a_qfp bli_hemv_unf_var3_qfp bli_her bli_her2 bli_her2_check bli_her2_ex bli_her2_ex_qfp bli_her2k bli_her2k1m bli_her2k3m1 bli_her2k3mh bli_her2k4m1 bli_her2k4mh bli_her2k_basic_check bli_her2k_check bli_her2k_ex bli_her2k_front bli_her2kind bli_her2kind_get_avail bli_her2knat bli_her2_unb_var1 bli_her2_unb_var1_qfp bli_her2_unb_var2 bli_her2_unb_var2_qfp bli_her2_unb_var3 bli_her2_unb_var3_qfp bli_her2_unb_var4 bli_her2_unb_var4_qfp bli_her2_unf_var1 bli_her2_unf_var1_qfp bli_her2_unf_var4 bli_her2_unf_var4_qfp bli_her_check bli_her_ex bli_her_ex_qfp bli_herk bli_herk1m bli_herk3m1 bli_herk3mh bli_herk4m1 bli_herk4mh bli_herk_basic_check bli_herk_check bli_herk_determine_kc bli_herk_determine_kc_b bli_herk_determine_kc_f bli_herk_direct bli_herk_ex bli_herk_front bli_herkind bli_herkind_get_avail bli_herk_l_ker_var2 bli_herknat bli_herk_prune_unref_mparts_k bli_herk_prune_unref_mparts_m bli_herk_prune_unref_mparts_n bli_herk_u_ker_var2 bli_herk_x_ker_var2 bli_her_unb_var1 bli_her_unb_var1_qfp bli_her_unb_var2 bli_her_unb_var2_qfp bli_ifprintm bli_ifprintv bli_igetsc bli_ind_disable bli_ind_disable_all bli_ind_disable_all_dt bli_ind_disable_dt bli_ind_enable bli_ind_enable_dt bli_ind_finalize bli_ind_get_impl_string bli_ind_init bli_ind_map_cdt_to_index bli_ind_oper_enable_only bli_ind_oper_find_avail bli_ind_oper_get_avail bli_ind_oper_get_avail_impl_string bli_ind_oper_is_impl bli_info_get_blas_int_type_size bli_info_get_enable_blas bli_info_get_enable_cblas bli_info_get_enable_memkind bli_info_get_enable_openmp bli_info_get_enable_pba_pools bli_info_get_enable_pthreads bli_info_get_enable_sandbox bli_info_get_enable_sba_pools bli_info_get_enable_stay_auto_init bli_info_get_enable_threading bli_info_get_gemm_impl_string bli_info_get_gemmtrsm_l_ukr_impl_string bli_info_get_gemmtrsm_u_ukr_impl_string bli_info_get_gemm_ukr_impl_string bli_info_get_heap_addr_align_size bli_info_get_heap_stride_align_size bli_info_get_hemm_impl_string bli_info_get_her2k_impl_string bli_info_get_herk_impl_string bli_info_get_int_type_size bli_info_get_int_type_size_str bli_info_get_max_type_size bli_info_get_num_fp_types bli_info_get_page_size bli_info_get_pool_addr_align_size bli_info_get_simd_align_size bli_info_get_simd_num_registers bli_info_get_simd_size bli_info_get_stack_buf_align_size bli_info_get_stack_buf_max_size bli_info_get_symm_impl_string bli_info_get_syr2k_impl_string bli_info_get_syrk_impl_string bli_info_get_thread_part_jrir_rr bli_info_get_thread_part_jrir_slab bli_info_get_trmm3_impl_string bli_info_get_trmm_impl_string bli_info_get_trsm_impl_string bli_info_get_trsm_l_ukr_impl_string bli_info_get_trsm_u_ukr_impl_string bli_info_get_version_str bli_init bli_init_apis bli_init_auto bli_init_once bli_invertd bli_invertd_check bli_invertd_ex bli_invertd_ex_qfp bli_invertsc bli_invertsc_check bli_invertsc_qfp bli_invertv bli_invertv_check bli_invertv_ex bli_invertv_ex_qfp bli_ipow bli_iprintm bli_iprintm_ex bli_iprintv bli_iprintv_ex bli_isetsc bli_l0_xsc_check bli_l0_xx2sc_check bli_l0_xxsc_check bli_l1d_ax_check bli_l1d_axy_check bli_l1d_x_check bli_l1d_xy_check bli_l1m_ax_check bli_l1m_axy_check bli_l1m_xy_check bli_l1v_axby_check bli_l1v_ax_check bli_l1v_axy_check bli_l1v_dot_check bli_l1v_xby_check bli_l1v_x_check bli_l1v_xi_check bli_l1v_xy_check bli_l3_basic_check bli_l3_cntl_create_if bli_l3_cntl_free bli_l3_determine_kc bli_l3_direct bli_l3_ind_oper_enable_only bli_l3_ind_oper_find_avail bli_l3_ind_oper_get_enable bli_l3_ind_oper_get_func bli_l3_ind_oper_set_enable bli_l3_ind_oper_set_enable_all bli_l3_ind_set_enable_dt bli_l3_packm bli_l3_prune_unref_mparts_k bli_l3_prune_unref_mparts_m bli_l3_prune_unref_mparts_n bli_l3_thread_decorator bli_l3_thread_entry bli_l3_thrinfo_create_root bli_l3_thrinfo_free bli_l3_thrinfo_free_paths bli_l3_thrinfo_init_single bli_l3_thrinfo_print_gemm_paths bli_l3_thrinfo_print_trsm_paths bli_lcm bli_lsame bli_machval bli_malloc_intl bli_malloc_user bli_mbool_create bli_mbool_free bli_mbool_init bli_pba_acquire_m bli_pba_compute_pool_block_sizes bli_pba_compute_pool_block_sizes_dt bli_pba_finalize bli_pba_finalize_pools bli_pba_init bli_pba_init_pools bli_pba_pool_size bli_pba_query bli_pba_release bli_memsys_finalize bli_memsys_init bli_mkherm bli_mkherm_check bli_mkherm_ex bli_mkherm_ex_qfp bli_mksymm bli_mksymm_check bli_mksymm_ex bli_mksymm_ex_qfp bli_mktrim bli_mktrim_check bli_mktrim_ex bli_mktrim_ex_qfp bli_mulsc bli_mulsc_check bli_mulsc_qfp bli_next_prime_factor bli_norm1m bli_norm1m_check bli_norm1m_ex bli_norm1m_ex_qfp bli_norm1v bli_norm1v_check bli_norm1v_ex bli_norm1v_ex_qfp bli_normfm bli_normfm_check bli_normfm_ex bli_normfm_ex_qfp bli_normfsc bli_normfsc_check bli_normfsc_qfp bli_normfv bli_normfv_check bli_normfv_ex bli_normfv_ex_qfp bli_normim bli_normim_check bli_normim_ex bli_normim_ex_qfp bli_normiv bli_normiv_check bli_normiv_ex bli_normiv_ex_qfp bli_obj_alloc_buffer bli_obj_alloc_buffer_check bli_obj_attach_buffer bli_obj_attach_buffer_check bli_obj_create bli_obj_create_1x1 bli_obj_create_1x1_with_attached_buffer bli_obj_create_check bli_obj_create_conf_to bli_obj_create_const_check bli_obj_create_scalar_check bli_obj_create_with_attached_buffer bli_obj_create_without_buffer bli_obj_create_without_buffer_check bli_obj_equals bli_obj_free bli_obj_free_check bli_obj_imag_equals bli_obj_imag_is_zero bli_obj_print bli_obj_print_check bli_obj_scalar_apply_scalar bli_obj_scalar_attach bli_obj_scalar_cast_to bli_obj_scalar_detach bli_obj_scalar_equals bli_obj_scalar_has_nonzero_imag bli_obj_scalar_init_detached bli_obj_scalar_init_detached_copy_of bli_obj_scalar_reset bli_packm_acquire_mpart_l2r bli_packm_acquire_mpart_t2b bli_packm_acquire_mpart_tl2br bli_packm_blk_var1 bli_packm_blk_var1_md bli_packm_cntl_create_node bli_packm_init bli_packm_init_check bli_packm_init_pack bli_packm_int bli_packm_int_check bli_packm_offset_to_panel_for bli_packm_thrinfo_init bli_packm_thrinfo_init_single bli_packm_unb_var1 bli_param_map_blis_to_char_conj bli_param_map_blis_to_char_diag bli_param_map_blis_to_char_dt bli_param_map_blis_to_char_side bli_param_map_blis_to_char_trans bli_param_map_blis_to_char_uplo bli_param_map_blis_to_netlib_diag bli_param_map_blis_to_netlib_machval bli_param_map_blis_to_netlib_side bli_param_map_blis_to_netlib_trans bli_param_map_blis_to_netlib_uplo bli_param_map_char_to_blis_conj bli_param_map_char_to_blis_diag bli_param_map_char_to_blis_dt bli_param_map_char_to_blis_side bli_param_map_char_to_blis_trans bli_param_map_char_to_blis_uplo bli_param_map_netlib_to_blis_diag bli_param_map_netlib_to_blis_side bli_param_map_netlib_to_blis_trans bli_param_map_netlib_to_blis_uplo bli_partition_2x2 bli_pblk_print bli_pool_alloc_block bli_pool_checkin_block bli_pool_checkout_block bli_pool_finalize bli_pool_free_block bli_pool_grow bli_pool_init bli_pool_print bli_pool_reinit bli_pool_shrink bli_prime_factorization bli_printm bli_printm_ex bli_print_msg bli_printv bli_printv_ex bli_projm bli_projm_check bli_projv bli_projv_check bli_prune_unref_mparts bli_pthread_barrier_destroy bli_pthread_barrier_init bli_pthread_barrier_wait bli_pthread_cond_broadcast bli_pthread_cond_destroy bli_pthread_cond_init bli_pthread_cond_wait bli_pthread_create bli_pthread_join bli_pthread_mutex_destroy bli_pthread_mutex_init bli_pthread_mutex_lock bli_pthread_mutex_trylock bli_pthread_mutex_unlock bli_pthread_once bli_randm bli_randm_check bli_randm_ex bli_randm_ex_qfp bli_randnm bli_randnm_check bli_randnm_ex bli_randnm_ex_qfp bli_randnv bli_randnv_check bli_randnv_ex bli_randnv_ex_qfp bli_randv bli_randv_check bli_randv_ex bli_randv_ex_qfp bli_rntm_print bli_rntm_set_ways_for_op bli_rntm_set_ways_from_rntm bli_sabsqsc bli_saddd bli_saddd_ex bli_saddm bli_saddm_ex bli_saddm_unb_var1 bli_saddsc bli_saddv bli_saddv_ex bli_samaxv bli_samaxv_ex bli_sasumv bli_sasumv_ex bli_sasumv_unb_var1 bli_saxpbyv bli_saxpbyv_ex bli_saxpy2v bli_saxpy2v_ex bli_saxpyd bli_saxpyd_ex bli_saxpyf bli_saxpyf_ex bli_saxpym bli_saxpym_ex bli_saxpym_unb_var1 bli_saxpyv bli_saxpyv_ex bli_sba_acquire bli_sba_checkin_array bli_sba_checkout_array bli_sba_finalize bli_sba_init bli_sba_query bli_sba_release bli_sba_rntm_set_pool bli_scal2d bli_scal2d_check bli_scal2d_ex bli_scal2d_ex_qfp bli_scal2m bli_scal2m_check bli_scal2m_ex bli_scal2m_ex_qfp bli_scal2v bli_scal2v_check bli_scal2v_ex bli_scal2v_ex_qfp bli_scald bli_scald_check bli_scald_ex bli_scald_ex_qfp bli_scalm bli_scalm_check bli_scalm_ex bli_scalm_ex_qfp bli_scalv bli_scalv_check bli_scalv_ex bli_scalv_ex_qfp bli_sccastm bli_sccastnzm bli_sccastv bli_sccopysc bli_scgemm_ker_var2_md bli_scopyd bli_scopyd_ex bli_scopym bli_scopym_ex bli_scopym_unb_var1 bli_scopyv bli_scopyv_ex bli_scpackm_blk_var1_md bli_scpackm_cxk_1e_md bli_scpackm_cxk_1r_md bli_scpackm_struc_cxk_md bli_scxpbym_md bli_scxpbym_md_ex bli_scxpbym_md_unb_var1 bli_sdcastm bli_sdcastnzm bli_sdcastv bli_sdcopysc bli_sdgemm_ker_var2_md bli_sdivsc bli_sdotaxpyv bli_sdotaxpyv_ex bli_sdotv bli_sdotv_ex bli_sdotxaxpyf bli_sdotxaxpyf_ex bli_sdotxf bli_sdotxf_ex bli_sdotxv bli_sdotxv_ex bli_sdpackm_blk_var1_md bli_sdpackm_cxk_1e_md bli_sdpackm_cxk_1r_md bli_sdpackm_struc_cxk_md bli_sdxpbym_md bli_sdxpbym_md_ex bli_sdxpbym_md_unb_var1 bli_setd bli_setd_check bli_setd_ex bli_setd_ex_qfp bli_setid bli_setid_check bli_setid_ex bli_setid_ex_qfp bli_setijm bli_setim bli_setiv bli_setm bli_setm_check bli_setm_ex bli_setm_ex_qfp bli_setrm bli_setrv bli_setsc bli_setsc_check bli_setsc_qfp bli_setv bli_setv_check bli_setv_ex bli_setv_ex_qfp bli_sfprintm bli_sfprintv bli_sgemm bli_sgemm1m bli_sgemm3m1 bli_sgemm3mh bli_sgemm4m1 bli_sgemm4mb bli_sgemm4mb_ker_var2 bli_sgemm4mh bli_sgemm_ex bli_sgemm_ker_var2 bli_sgemmtrsm_l_ukernel bli_sgemmtrsm_u_ukernel bli_sgemm_ukernel bli_sgemv bli_sgemv_ex bli_sgemv_unb_var1 bli_sgemv_unb_var2 bli_sgemv_unf_var1 bli_sgemv_unf_var2 bli_sger bli_sger_ex bli_sger_unb_var1 bli_sger_unb_var2 bli_sgetijm bli_sgetsc bli_shemm bli_shemm1m bli_shemm3m1 bli_shemm3mh bli_shemm4m1 bli_shemm4mh bli_shemm_ex bli_shemv bli_shemv_ex bli_shemv_unb_var1 bli_shemv_unb_var2 bli_shemv_unb_var3 bli_shemv_unb_var4 bli_shemv_unf_var1 bli_shemv_unf_var1a bli_shemv_unf_var3 bli_shemv_unf_var3a bli_sher bli_sher2 bli_sher2_ex bli_sher2k bli_sher2k1m bli_sher2k3m1 bli_sher2k3mh bli_sher2k4m1 bli_sher2k4mh bli_sher2k_ex bli_sher2_unb_var1 bli_sher2_unb_var2 bli_sher2_unb_var3 bli_sher2_unb_var4 bli_sher2_unf_var1 bli_sher2_unf_var4 bli_sher_ex bli_sherk bli_sherk1m bli_sherk3m1 bli_sherk3mh bli_sherk4m1 bli_sherk4mh bli_sherk_ex bli_sherk_l_ker_var2 bli_sherk_u_ker_var2 bli_sher_unb_var1 bli_sher_unb_var2 bli_shiftd bli_shiftd_check bli_shiftd_ex bli_shiftd_ex_qfp bli_sinvertd bli_sinvertd_ex bli_sinvertsc bli_sinvertv bli_sinvertv_ex bli_slamch bli_sleep bli_smachval bli_smkherm bli_smkherm_ex bli_smkherm_unb_var1 bli_smksymm bli_smksymm_ex bli_smksymm_unb_var1 bli_smktrim bli_smktrim_ex bli_smktrim_unb_var1 bli_smulsc bli_snorm1m bli_snorm1m_ex bli_snorm1m_unb_var1 bli_snorm1v bli_snorm1v_ex bli_snorm1v_unb_var1 bli_snormfm bli_snormfm_ex bli_snormfm_unb_var1 bli_snormfsc bli_snormfv bli_snormfv_ex bli_snormfv_unb_var1 bli_snormim bli_snormim_ex bli_snormim_unb_var1 bli_snormiv bli_snormiv_ex bli_snormiv_unb_var1 bli_spackm_blk_var1 bli_spackm_cxk bli_spackm_herm_cxk bli_spackm_struc_cxk bli_spackm_tri_cxk bli_spackm_unb_var1 bli_sprintm bli_sprintm_ex bli_sprintv bli_sprintv_ex bli_sqrtsc bli_sqrtsc_check bli_sqrtsc_qfp bli_srandm bli_srandm_ex bli_srandm_unb_var1 bli_srandnm bli_srandnm_ex bli_srandnm_unb_var1 bli_srandnv bli_srandnv_ex bli_srandnv_unb_var1 bli_srandv bli_srandv_ex bli_srandv_unb_var1 bli_sscal2d bli_sscal2d_ex bli_sscal2m bli_sscal2m_ex bli_sscal2m_unb_var1 bli_sscal2v bli_sscal2v_ex bli_sscald bli_sscald_ex bli_sscalm bli_sscalm_ex bli_sscalm_unb_var1 bli_sscalv bli_sscalv_ex bli_sscastm bli_sscastnzm bli_sscastv bli_sscopysc bli_ssetd bli_ssetd_ex bli_ssetid bli_ssetid_ex bli_ssetijm bli_ssetm bli_ssetm_ex bli_ssetm_unb_var1 bli_ssetsc bli_ssetv bli_ssetv_ex bli_ssgemm_ker_var2_md bli_sshiftd bli_sshiftd_ex bli_sspackm_blk_var1_md bli_sspackm_cxk_1e_md bli_sspackm_cxk_1r_md bli_sspackm_struc_cxk_md bli_ssqrtsc bli_ssubd bli_ssubd_ex bli_ssubm bli_ssubm_ex bli_ssubm_unb_var1 bli_ssubsc bli_ssubv bli_ssubv_ex bli_ssumsqv bli_ssumsqv_ex bli_ssumsqv_unb_var1 bli_sswapv bli_sswapv_ex bli_ssxpbym_md bli_ssxpbym_md_ex bli_ssxpbym_md_unb_var1 bli_ssymm bli_ssymm1m bli_ssymm3m1 bli_ssymm3mh bli_ssymm4m1 bli_ssymm4mh bli_ssymm_ex bli_ssymv bli_ssymv_ex bli_ssyr bli_ssyr2 bli_ssyr2_ex bli_ssyr2k bli_ssyr2k1m bli_ssyr2k3m1 bli_ssyr2k3mh bli_ssyr2k4m1 bli_ssyr2k4mh bli_ssyr2k_ex bli_ssyr_ex bli_ssyrk bli_ssyrk1m bli_ssyrk3m1 bli_ssyrk3mh bli_ssyrk4m1 bli_ssyrk4mh bli_ssyrk_ex bli_string_mkupper bli_strmm bli_strmm1m bli_strmm3 bli_strmm31m bli_strmm33m1 bli_strmm33mh bli_strmm34m1 bli_strmm34mh bli_strmm3_ex bli_strmm3m1 bli_strmm4m1 bli_strmm_ex bli_strmm_ll_ker_var2 bli_strmm_lu_ker_var2 bli_strmm_rl_ker_var2 bli_strmm_ru_ker_var2 bli_strmv bli_strmv_ex bli_strmv_unb_var1 bli_strmv_unb_var2 bli_strmv_unf_var1 bli_strmv_unf_var2 bli_strsm bli_strsm1m bli_strsm3m1 bli_strsm4m1 bli_strsm_ex bli_strsm_ll_ker_var2 bli_strsm_l_ukernel bli_strsm_lu_ker_var2 bli_strsm_rl_ker_var2 bli_strsm_ru_ker_var2 bli_strsm_u_ukernel bli_strsv bli_strsv_ex bli_strsv_unb_var1 bli_strsv_unb_var2 bli_strsv_unf_var1 bli_strsv_unf_var2 bli_subd bli_subd_check bli_subd_ex bli_subd_ex_qfp bli_subm bli_subm_check bli_subm_ex bli_subm_ex_qfp bli_subsc bli_subsc_check bli_subsc_qfp bli_subv bli_subv_check bli_subv_ex bli_subv_ex_qfp bli_sumsqv bli_sumsqv_check bli_sumsqv_ex bli_sumsqv_ex_qfp bli_sunpackm_blk_var1 bli_sunpackm_cxk bli_sunpackm_unb_var1 bli_sunzipsc bli_swapv bli_swapv_check bli_swapv_ex bli_swapv_ex_qfp bli_sxpbyd bli_sxpbyd_ex bli_sxpbym bli_sxpbym_ex bli_sxpbym_unb_var1 bli_sxpbyv bli_sxpbyv_ex bli_symm bli_symm1m bli_symm3m1 bli_symm3mh bli_symm4m1 bli_symm4mh bli_symm_check bli_symm_ex bli_symm_front bli_symmind bli_symmind_get_avail bli_symmnat bli_symv bli_symv_check bli_symv_ex bli_symv_ex_qfp bli_syr bli_syr2 bli_syr2_check bli_syr2_ex bli_syr2_ex_qfp bli_syr2k bli_syr2k1m bli_syr2k3m1 bli_syr2k3mh bli_syr2k4m1 bli_syr2k4mh bli_syr2k_check bli_syr2k_ex bli_syr2k_front bli_syr2kind bli_syr2kind_get_avail bli_syr2knat bli_syr_check bli_syr_ex bli_syr_ex_qfp bli_syrk bli_syrk1m bli_syrk3m1 bli_syrk3mh bli_syrk4m1 bli_syrk4mh bli_syrk_check bli_syrk_ex bli_syrk_front bli_syrkind bli_syrkind_get_avail bli_syrknat bli_szcastm bli_szcastnzm bli_szcastv bli_szcopysc bli_szgemm_ker_var2_md bli_szipsc bli_szpackm_blk_var1_md bli_szpackm_cxk_1e_md bli_szpackm_cxk_1r_md bli_szpackm_struc_cxk_md bli_szxpbym_md bli_szxpbym_md_ex bli_szxpbym_md_unb_var1 bli_thrcomm_barrier bli_thrcomm_barrier_atomic bli_thrcomm_bcast bli_thrcomm_cleanup bli_thrcomm_create bli_thrcomm_free bli_thrcomm_init bli_thread_finalize bli_thread_get_env bli_thread_get_ic_nt bli_thread_get_ir_nt bli_thread_get_jc_nt bli_thread_get_jr_nt bli_thread_get_num_threads bli_thread_get_pc_nt bli_thread_init bli_thread_init_rntm bli_thread_init_rntm_from_env bli_thread_range_b2t bli_thread_range_l2r bli_thread_range_mdim bli_thread_range_ndim bli_thread_range_r2l bli_thread_range_sub bli_thread_range_t2b bli_thread_range_weighted_b2t bli_thread_range_weighted_l2r bli_thread_range_weighted_r2l bli_thread_range_weighted_sub bli_thread_range_weighted_t2b bli_thread_range_width_l bli_thread_set_num_threads bli_thread_set_num_threads_ bli_thread_set_ways bli_thread_set_ways_ bli_thrinfo_create bli_thrinfo_create_for_cntl bli_thrinfo_create_for_cntl_prenode bli_thrinfo_free bli_thrinfo_grow bli_thrinfo_init bli_thrinfo_init_single bli_thrinfo_rgrow bli_thrinfo_rgrow_prenode bli_trmm bli_trmm1m bli_trmm3 bli_trmm31m bli_trmm33m1 bli_trmm33mh bli_trmm34m1 bli_trmm34mh bli_trmm3_ex bli_trmm3_front bli_trmm3ind bli_trmm3ind_get_avail bli_trmm3m1 bli_trmm3nat bli_trmm4m1 bli_trmm_check bli_trmm_determine_kc bli_trmm_determine_kc_b bli_trmm_determine_kc_f bli_trmm_direct bli_trmm_ex bli_trmm_front bli_trmmind bli_trmmind_get_avail bli_trmm_ll_ker_var2 bli_trmm_lu_ker_var2 bli_trmmnat bli_trmm_prune_unref_mparts_k bli_trmm_prune_unref_mparts_m bli_trmm_prune_unref_mparts_n bli_trmm_rl_ker_var2 bli_trmm_ru_ker_var2 bli_trmm_xx_ker_var2 bli_trmv bli_trmv_check bli_trmv_ex bli_trmv_ex_qfp bli_trmv_unb_var1 bli_trmv_unb_var1_qfp bli_trmv_unb_var2 bli_trmv_unb_var2_qfp bli_trmv_unf_var1 bli_trmv_unf_var1_qfp bli_trmv_unf_var2 bli_trmv_unf_var2_qfp bli_trsm bli_trsm1m bli_trsm3m1 bli_trsm4m1 bli_trsm_blk_var1 bli_trsm_blk_var2 bli_trsm_blk_var3 bli_trsm_check bli_trsm_cntl_create bli_trsm_cntl_create_node bli_trsm_cntl_free bli_trsm_determine_kc bli_trsm_determine_kc_b bli_trsm_determine_kc_f bli_trsm_direct bli_trsm_ex bli_trsm_front bli_trsmind bli_trsmind_get_avail bli_trsm_int bli_trsm_l_cntl_create bli_trsm_ll_ker_var2 bli_trsm_l_ukernel_qfp bli_trsm_lu_ker_var2 bli_trsmnat bli_trsm_packa bli_trsm_packb bli_trsm_prune_unref_mparts_k bli_trsm_prune_unref_mparts_m bli_trsm_prune_unref_mparts_n bli_trsm_r_cntl_create bli_trsm_rl_ker_var2 bli_trsm_ru_ker_var2 bli_trsm_ukernel bli_trsm_u_ukernel_qfp bli_trsm_xx_ker_var2 bli_trsv bli_trsv_check bli_trsv_ex bli_trsv_ex_qfp bli_trsv_unb_var1 bli_trsv_unb_var1_qfp bli_trsv_unb_var2 bli_trsv_unb_var2_qfp bli_trsv_unf_var1 bli_trsv_unf_var1_qfp bli_trsv_unf_var2 bli_trsv_unf_var2_qfp bli_unpackm_blk_var1 bli_unpackm_cntl_create_node bli_unpackm_int bli_unpackm_int_check bli_unpackm_unb_var1 bli_unzipsc bli_unzipsc_check bli_unzipsc_qfp bli_utilm_fprint_check bli_utilm_mkhst_check bli_utilm_norm_check bli_utilm_rand_check bli_utilv_norm_check bli_utilv_sumsqv_check bli_utilv_xa_check bli_xpbyd bli_xpbyd_check bli_xpbyd_ex bli_xpbyd_ex_qfp bli_xpbym bli_xpbym_check bli_xpbym_ex bli_xpbym_ex_qfp bli_xpbym_md bli_xpbym_md_ex bli_xpbym_md_ex_qfp2 bli_xpbyv bli_xpbyv_check bli_xpbyv_ex bli_xpbyv_ex_qfp bli_xxmv_check bli_xxr_check bli_zabsqsc bli_zaddd bli_zaddd_ex bli_zaddm bli_zaddm_ex bli_zaddm_unb_var1 bli_zaddsc bli_zaddv bli_zaddv_ex bli_zamaxv bli_zamaxv_ex bli_zasumv bli_zasumv_ex bli_zasumv_unb_var1 bli_zaxpbyv bli_zaxpbyv_ex bli_zaxpy2v bli_zaxpy2v_ex bli_zaxpyd bli_zaxpyd_ex bli_zaxpyf bli_zaxpyf_ex bli_zaxpym bli_zaxpym_ex bli_zaxpym_unb_var1 bli_zaxpyv bli_zaxpyv_ex bli_zccastm bli_zccastnzm bli_zccastv bli_zccopysc bli_zcgemm_ker_var2_md bli_zcopyd bli_zcopyd_ex bli_zcopym bli_zcopym_ex bli_zcopym_unb_var1 bli_zcopyv bli_zcopyv_ex bli_zcpackm_blk_var1_md bli_zcpackm_cxk_1e_md bli_zcpackm_cxk_1r_md bli_zcpackm_struc_cxk_md bli_zcxpbym_md bli_zcxpbym_md_ex bli_zcxpbym_md_unb_var1 bli_zdcastm bli_zdcastnzm bli_zdcastv bli_zdcopysc bli_zdgemm_ker_var2_md bli_zdivsc bli_zdotaxpyv bli_zdotaxpyv_ex bli_zdotv bli_zdotv_ex bli_zdotxaxpyf bli_zdotxaxpyf_ex bli_zdotxf bli_zdotxf_ex bli_zdotxv bli_zdotxv_ex bli_zdpackm_blk_var1_md bli_zdpackm_cxk_1e_md bli_zdpackm_cxk_1r_md bli_zdpackm_struc_cxk_md bli_zdxpbym_md bli_zdxpbym_md_ex bli_zdxpbym_md_unb_var1 bli_zfprintm bli_zfprintv bli_zgemm bli_zgemm1m bli_zgemm3m1 bli_zgemm3mh bli_zgemm4m1 bli_zgemm4mb bli_zgemm4mb_ker_var2 bli_zgemm4mh bli_zgemm_ex bli_zgemm_ker_var2 bli_zgemm_md_c2r_ref bli_zgemmtrsm_l_ukernel bli_zgemmtrsm_u_ukernel bli_zgemm_ukernel bli_zgemv bli_zgemv_ex bli_zgemv_unb_var1 bli_zgemv_unb_var2 bli_zgemv_unf_var1 bli_zgemv_unf_var2 bli_zger bli_zger_ex bli_zger_unb_var1 bli_zger_unb_var2 bli_zgetijm bli_zgetsc bli_zhemm bli_zhemm1m bli_zhemm3m1 bli_zhemm3mh bli_zhemm4m1 bli_zhemm4mh bli_zhemm_ex bli_zhemv bli_zhemv_ex bli_zhemv_unb_var1 bli_zhemv_unb_var2 bli_zhemv_unb_var3 bli_zhemv_unb_var4 bli_zhemv_unf_var1 bli_zhemv_unf_var1a bli_zhemv_unf_var3 bli_zhemv_unf_var3a bli_zher bli_zher2 bli_zher2_ex bli_zher2k bli_zher2k1m bli_zher2k3m1 bli_zher2k3mh bli_zher2k4m1 bli_zher2k4mh bli_zher2k_ex bli_zher2_unb_var1 bli_zher2_unb_var2 bli_zher2_unb_var3 bli_zher2_unb_var4 bli_zher2_unf_var1 bli_zher2_unf_var4 bli_zher_ex bli_zherk bli_zherk1m bli_zherk3m1 bli_zherk3mh bli_zherk4m1 bli_zherk4mh bli_zherk_ex bli_zherk_l_ker_var2 bli_zherk_u_ker_var2 bli_zher_unb_var1 bli_zher_unb_var2 bli_zinvertd bli_zinvertd_ex bli_zinvertsc bli_zinvertv bli_zinvertv_ex bli_zipsc bli_zipsc_check bli_zipsc_qfp bli_zmachval bli_zmkherm bli_zmkherm_ex bli_zmkherm_unb_var1 bli_zmksymm bli_zmksymm_ex bli_zmksymm_unb_var1 bli_zmktrim bli_zmktrim_ex bli_zmktrim_unb_var1 bli_zmulsc bli_znorm1m bli_znorm1m_ex bli_znorm1m_unb_var1 bli_znorm1v bli_znorm1v_ex bli_znorm1v_unb_var1 bli_znormfm bli_znormfm_ex bli_znormfm_unb_var1 bli_znormfsc bli_znormfv bli_znormfv_ex bli_znormfv_unb_var1 bli_znormim bli_znormim_ex bli_znormim_unb_var1 bli_znormiv bli_znormiv_ex bli_znormiv_unb_var1 bli_zpackm_blk_var1 bli_zpackm_cxk bli_zpackm_cxk_1er bli_zpackm_cxk_3mis bli_zpackm_cxk_4mi bli_zpackm_cxk_rih bli_zpackm_herm_cxk bli_zpackm_herm_cxk_1er bli_zpackm_herm_cxk_3mis bli_zpackm_herm_cxk_4mi bli_zpackm_herm_cxk_rih bli_zpackm_struc_cxk bli_zpackm_struc_cxk_1er bli_zpackm_struc_cxk_3mis bli_zpackm_struc_cxk_4mi bli_zpackm_struc_cxk_rih bli_zpackm_tri_cxk bli_zpackm_tri_cxk_1er bli_zpackm_tri_cxk_3mis bli_zpackm_tri_cxk_4mi bli_zpackm_tri_cxk_rih bli_zpackm_unb_var1 bli_zprintm bli_zprintm_ex bli_zprintv bli_zprintv_ex bli_zrandm bli_zrandm_ex bli_zrandm_unb_var1 bli_zrandnm bli_zrandnm_ex bli_zrandnm_unb_var1 bli_zrandnv bli_zrandnv_ex bli_zrandnv_unb_var1 bli_zrandv bli_zrandv_ex bli_zrandv_unb_var1 bli_zscal2d bli_zscal2d_ex bli_zscal2m bli_zscal2m_ex bli_zscal2m_unb_var1 bli_zscal2v bli_zscal2v_ex bli_zscald bli_zscald_ex bli_zscalm bli_zscalm_ex bli_zscalm_unb_var1 bli_zscalv bli_zscalv_ex bli_zscastm bli_zscastnzm bli_zscastv bli_zscopysc bli_zsetd bli_zsetd_ex bli_zsetid bli_zsetid_ex bli_zsetijm bli_zsetm bli_zsetm_ex bli_zsetm_unb_var1 bli_zsetsc bli_zsetv bli_zsetv_ex bli_zsgemm_ker_var2_md bli_zshiftd bli_zshiftd_ex bli_zspackm_blk_var1_md bli_zspackm_cxk_1e_md bli_zspackm_cxk_1r_md bli_zspackm_struc_cxk_md bli_zsqrtsc bli_zsubd bli_zsubd_ex bli_zsubm bli_zsubm_ex bli_zsubm_unb_var1 bli_zsubsc bli_zsubv bli_zsubv_ex bli_zsumsqv bli_zsumsqv_ex bli_zsumsqv_unb_var1 bli_zswapv bli_zswapv_ex bli_zsxpbym_md bli_zsxpbym_md_ex bli_zsxpbym_md_unb_var1 bli_zsymm bli_zsymm1m bli_zsymm3m1 bli_zsymm3mh bli_zsymm4m1 bli_zsymm4mh bli_zsymm_ex bli_zsymv bli_zsymv_ex bli_zsyr bli_zsyr2 bli_zsyr2_ex bli_zsyr2k bli_zsyr2k1m bli_zsyr2k3m1 bli_zsyr2k3mh bli_zsyr2k4m1 bli_zsyr2k4mh bli_zsyr2k_ex bli_zsyr_ex bli_zsyrk bli_zsyrk1m bli_zsyrk3m1 bli_zsyrk3mh bli_zsyrk4m1 bli_zsyrk4mh bli_zsyrk_ex bli_ztrmm bli_ztrmm1m bli_ztrmm3 bli_ztrmm31m bli_ztrmm33m1 bli_ztrmm33mh bli_ztrmm34m1 bli_ztrmm34mh bli_ztrmm3_ex bli_ztrmm3m1 bli_ztrmm4m1 bli_ztrmm_ex bli_ztrmm_ll_ker_var2 bli_ztrmm_lu_ker_var2 bli_ztrmm_rl_ker_var2 bli_ztrmm_ru_ker_var2 bli_ztrmv bli_ztrmv_ex bli_ztrmv_unb_var1 bli_ztrmv_unb_var2 bli_ztrmv_unf_var1 bli_ztrmv_unf_var2 bli_ztrsm bli_ztrsm1m bli_ztrsm3m1 bli_ztrsm4m1 bli_ztrsm_ex bli_ztrsm_ll_ker_var2 bli_ztrsm_l_ukernel bli_ztrsm_lu_ker_var2 bli_ztrsm_rl_ker_var2 bli_ztrsm_ru_ker_var2 bli_ztrsm_u_ukernel bli_ztrsv bli_ztrsv_ex bli_ztrsv_unb_var1 bli_ztrsv_unb_var2 bli_ztrsv_unf_var1 bli_ztrsv_unf_var2 bli_zunpackm_blk_var1 bli_zunpackm_cxk bli_zunpackm_unb_var1 bli_zunzipsc bli_zxpbyd bli_zxpbyd_ex bli_zxpbym bli_zxpbym_ex bli_zxpbym_unb_var1 bli_zxpbyv bli_zxpbyv_ex bli_zzcastm bli_zzcastnzm bli_zzcastv bli_zzcopysc bli_zzgemm_ker_var2_md bli_zzipsc bli_zzpackm_blk_var1_md bli_zzpackm_cxk_1e_md bli_zzpackm_cxk_1r_md bli_zzpackm_struc_cxk_md bli_zzxpbym_md bli_zzxpbym_md_ex bli_zzxpbym_md_unb_var1 sasum_ sasumsub_ saxpy_ scabs1_ scasum_ scasumsub_ scnrm2_ scnrm2sub_ scopy_ sdot_ sdotsub_ sdsdot_ sdsdotsub_ sgbmv_ sgemm_ sgemv_ sger_ snrm2_ snrm2sub_ srot_ srotg_ srotm_ srotmg_ ssbmv_ sscal_ sspmv_ sspr_ sspr2_ sswap_ ssymm_ ssymv_ ssyr_ ssyr2_ ssyr2k_ ssyrk_ stbmv_ stbsv_ stpmv_ stpsv_ strmm_ strmv_ strsm_ strsv_ dasum_ dasumsub_ daxpy_ dcabs1_ dcopy_ ddot_ ddotsub_ dgbmv_ dgemm_ dgemv_ dger_ dnrm2_ dnrm2sub_ drot_ drotg_ drotm_ drotmg_ dsbmv_ dscal_ dsdot_ dsdotsub_ dspmv_ dspr_ dspr2_ dswap_ dsymm_ dsymv_ dsyr_ dsyr2_ dsyr2k_ dsyrk_ dtbmv_ dtbsv_ dtpmv_ dtpsv_ dtrmm_ dtrmv_ dtrsm_ dtrsv_ dzasum_ dzasumsub_ dznrm2_ dznrm2sub_ caxpy_ ccopy_ cdotc_ cdotcsub_ cdotu_ cdotusub_ cgbmv_ cgemm_ cgemv_ cgerc_ cgeru_ chbmv_ chemm_ chemv_ cher_ cher2_ cher2k_ cherk_ chpmv_ chpr_ chpr2_ crotg_ cscal_ csrot_ csscal_ cswap_ csymm_ csyr2k_ csyrk_ ctbmv_ ctbsv_ ctpmv_ ctpsv_ ctrmm_ ctrmv_ ctrsm_ ctrsv_ zaxpy_ zcopy_ zdotc_ zdotcsub_ zdotu_ zdotusub_ zdrot_ zdscal_ zgbmv_ zgemm_ zgemv_ zgerc_ zgeru_ zhbmv_ zhemm_ zhemv_ zher_ zher2_ zher2k_ zherk_ zhpmv_ zhpr_ zhpr2_ zrotg_ zscal_ zswap_ zsymm_ zsyr2k_ zsyrk_ ztbmv_ ztbsv_ ztpmv_ ztpsv_ ztrmm_ ztrmv_ ztrsm_ ztrsv_ icamax_ icamaxsub_ idamax_ idamaxsub_ isamax_ isamaxsub_ izamax_ izamaxsub_ cblas_caxpy cblas_ccopy cblas_cdotc_sub cblas_cdotu_sub cblas_cgbmv cblas_cgemm cblas_cgemv cblas_cgerc cblas_cgeru cblas_chbmv cblas_chemm cblas_chemv cblas_cher cblas_cher2 cblas_cher2k cblas_cherk cblas_chpmv cblas_chpr cblas_chpr2 cblas_cscal cblas_csscal cblas_cswap cblas_csymm cblas_csyr2k cblas_csyrk cblas_ctbmv cblas_ctbsv cblas_ctpmv cblas_ctpsv cblas_ctrmm cblas_ctrmv cblas_ctrsm cblas_ctrsv cblas_dasum cblas_daxpy cblas_dcopy cblas_ddot cblas_dgbmv cblas_dgemm cblas_dgemv cblas_dger cblas_dnrm2 cblas_drot cblas_drotg cblas_drotm cblas_drotmg cblas_dsbmv cblas_dscal cblas_dsdot cblas_dspmv cblas_dspr cblas_dspr2 cblas_dswap cblas_dsymm cblas_dsymv cblas_dsyr cblas_dsyr2 cblas_dsyr2k cblas_dsyrk cblas_dtbmv cblas_dtbsv cblas_dtpmv cblas_dtpsv cblas_dtrmm cblas_dtrmv cblas_dtrsm cblas_dtrsv cblas_dzasum cblas_dznrm2 cblas_icamax cblas_idamax cblas_isamax cblas_izamax cblas_sasum cblas_saxpy cblas_scasum cblas_scnrm2 cblas_scopy cblas_sdot cblas_sdsdot cblas_sgbmv cblas_sgemm cblas_sgemv cblas_sger cblas_snrm2 cblas_srot cblas_srotg cblas_srotm cblas_srotmg cblas_ssbmv cblas_sscal cblas_sspmv cblas_sspr cblas_sspr2 cblas_sswap cblas_ssymm cblas_ssymv cblas_ssyr cblas_ssyr2 cblas_ssyr2k cblas_ssyrk cblas_stbmv cblas_stbsv cblas_stpmv cblas_stpsv cblas_strmm cblas_strmv cblas_strsm cblas_strsv cblas_xerbla cblas_zaxpy cblas_zcopy cblas_zdotc_sub cblas_zdotu_sub cblas_zdscal cblas_zgbmv cblas_zgemm cblas_zgemv cblas_zgerc cblas_zgeru cblas_zhbmv cblas_zhemm cblas_zhemv cblas_zher cblas_zher2 cblas_zher2k cblas_zherk cblas_zhpmv cblas_zhpr cblas_zhpr2 cblas_zscal cblas_zswap cblas_zsymm cblas_zsyr2k cblas_zsyrk cblas_ztbmv cblas_ztbsv cblas_ztpmv cblas_ztpsv cblas_ztrmm cblas_ztrmv cblas_ztrsm cblas_ztrsv blis-0.9.0/build/mirror-tree.sh000077500000000000000000000111001422157504600163550ustar00rootroot00000000000000#!/bin/sh # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2014, The University of Texas at Austin # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # print_usage() { local script_name # Get the script name script_name=${0##*/} # Echo usage info echo " " echo " "${script_name} echo " " echo " Field G. Van Zee" echo " " echo " Recursively descends through the directory given in argument 1 while" echo " creating a symmetric directory structure in the new directory specified" echo " by argument 2, ignoring regular files along the way." echo " " echo " Usage:" echo " ${script_name} [-v] existing_dir new_mirror_dir" echo " " echo " The following options are accepted:" echo " " echo " -v verbose" echo " Echo progress as directories are recursively created." echo " " # Exit with non-zero exit status exit 1 } main() { # Process our command line options. We only respond to the -v flag, # in which case we'll echo what we're doing as we go along. while getopts ":v" opt; do case $opt in v ) verbose_flag=1 ;; \? ) print_usage exit 1 esac done shift $(($OPTIND - 1)) # Check the number of arguments after command line option processing. if [ $# != "2" ]; then print_usage fi # Extract arguments. e_dir=$1 n_dir=$2 # If the root new directory does not exist, then create it. if [ ! -d $n_dir ]; then # Be verbose, if -v was one of the command line options. if [ -n "$verbose_flag" ]; then echo "Creating $n_dir" fi # Make the root new directory. Create the parent directories if # they do not exist with the -p option. mkdir -p $n_dir fi # Initialize the recursive variables. We keep a separate variable # for the existing and new directories because they have different # roots, but they will always change in parallel. cur_e_dir=$e_dir cur_n_dir=$n_dir # Begin recursion, starting with the contents of the existing # directory. mirror_tree "$(ls $e_dir)" # Exit peacefully. return 0 } mirror_tree() { # Extract arguments. dir_contents="$1" # Process each item in our argument list (ie: each item in cur_e_dir). for thing in ${dir_contents}; do # Adjust the current existing and new directory paths to # include the current instance of thing. cur_e_dir="$cur_e_dir/$thing" cur_n_dir="$cur_n_dir/$thing" # If the current existing directory exists, then create a # corresponding subdirectory in new directory. if [ -d ${cur_e_dir} ]; then # Be verbose, if -v was one of the command line options. if [ -n "$verbose_flag" ]; then echo "Creating $cur_n_dir" fi # Make the new subdirectory, but only if it doesn't # already exist. if [ ! -d $cur_n_dir ]; then mkdir $cur_n_dir fi # Continue recursively on the contents of cur_e_dir. mirror_tree "$(ls $cur_e_dir)" fi # Delete the end of the path, up to the first / character to # prepare for the next "thing" in $@. cur_e_dir=${cur_e_dir%/*} cur_n_dir=${cur_n_dir%/*} done } # The script's main entry point, passing all parameters given. main "$@" blis-0.9.0/build/old/000077500000000000000000000000001422157504600143345ustar00rootroot00000000000000blis-0.9.0/build/old/flatten-headers-pass.sh000077500000000000000000000420061422157504600207070ustar00rootroot00000000000000#!/usr/bin/env bash # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2014, The University of Texas at Austin # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # # # -- Helper functions ---------------------------------------------------------- # print_usage() { # Echo usage info. echo " " echo " ${script_name}" echo " " echo " Field G. Van Zee" echo " " echo " Generate a monolithic header by recursively replacing all #include" echo " directives in a selected file with the contents of the header files" echo " they reference." echo " " echo " Usage:" echo " " echo " ${script_name} header header_out dir_list" echo " " echo " Arguments:" echo " " echo " header The filepath to the top-level header, which is file that" echo " will #include all other header files. NOTE: It is okay if" echo " this file resides somewhere in root_dir, described below." echo " " echo " header_out The filepath of the file into which the script will output" echo " the monolithic header." echo " " echo " dir_list The list of directory paths in which to search for the" echo " headers that are #included by 'header'. By default, these" echo " directories are scanned for .h files, but sub-directories" echo " within the various directories are not inspected. If the" echo " -r option is given, these directories are recursively" echo " scanned. In either case, the subset of directories scanned" echo " that actually contains .h files is then searched whenever" echo " a #include directive is encountered in 'header' (or any" echo " file subsequently #included). If a referenced header file" echo " is not found, the #include directive is left untouched and" echo " translated directly into 'header_out'." echo " " echo " The following options are accepted:" echo " " echo " -r recursive" echo " Scan the directories listed in 'dir_list' recursively when" echo " searching for .h header files. By default, the directories" echo " are not searched recursively." echo " " echo " -c strip C-style comments" echo " Strip comments enclosed in /* */ delimiters from the" echo " output, including multi-line comments. (This only applies" echo " to #included headers; C-style comments in the top-level" echo " 'header' are never stripped.) By default, C-style comments" echo " are not stripped." echo " " echo " -o SCRIPT output script name" echo " Use SCRIPT as a prefix when outputting messages instead" echo " the script's actual name. Useful when the current script" echo " is going to be called from within another, higher-level" echo " driver script and seeing the current script's name might" echo " unnecessarily confuse the user." echo " " echo " -q quiet" echo " Suppress informational output. By default, the script is" echo " verbose." echo " " echo " -h help" echo " Output this information and exit." echo " " # Exit with non-zero exit status exit 1 } canonicalize_ws() { local str="$1" # Remove leading and trailing whitespace. str=$(echo -e "${str}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//') # Remove duplicate spaces between words. str=$(echo -e "${str}" | tr -s " ") # Update the input argument. echo "${str}" } is_word_in_list() { word="$1" list="$2" rval="" for item in ${list}; do if [ "${item}" == "${word}" ]; then rval="${word}" break fi done echo "${rval}" } echoinfo() { if [ -z "${quiet_flag}" ]; then # Echo the argument string to stderr instead of stdout. echo "${output_name}: $1" 1>&2; fi } echoninfo() { if [ -z "${quiet_flag}" ]; then # Echo the argument string to stderr instead of stdout. echo -n "${output_name}: $1" 1>&2; fi } echon2info() { if [ -z "${quiet_flag}" ]; then # Echo the argument string to stderr instead of stdout. echo "$1" 1>&2; fi } find_header_dirs() { local cur_dirpath sub_items result cur_list item child_list # Extract the argument: the current directory, and the list of # directories found so far that contain headers. cur_dirpath="$1" echoninfo "scanning contents of ${cur_dirpath}" # Acquire a list of the directory's contents. sub_items=$(ls ${cur_dirpath}) # If there is at least one header present, add the current directory to # the list header of directories. Otherwise, the current directory does # not contribute to the list returned to the caller. result=$(echo ${sub_items} | grep "\.h") if [ -n "${result}" ]; then cur_list="${cur_dirpath}" echon2info " ...found headers" else cur_list="" echon2info "" fi # Iterate over the list of directory contents. for item in ${sub_items}; do # Check whether the current item is in the ignore_list. If so, we # ignore it. result=$(is_word_in_list "${item}" "${ignore_list}") if [ -n "${result}" ]; then echoinfo "ignoring directory '${item}'." continue fi # If the current item is a directory, recursively accumulate header # directories for that sub-directory. if [ -d "${cur_dirpath}/${item}" ]; then # Recursively find header directories within the sub-directory # ${item} and store the directory list to child_list. child_list=$(find_header_dirs "${cur_dirpath}/${item}") # Accumulate the sub-directory's header list with the running list # of header directories cur_list="${cur_list} ${child_list}" fi done # Return the list of header directories. echo "${cur_list}" } get_header_path() { local filename dirpaths filepath filename="$1" dirpaths="$2" filepath="" # Search each directory path for the filename given. for dirpath in ${dirpaths}; do if [ -f "${dirpath}/${filename}" ]; then filepath="${dirpath}/${filename}" break fi done # Return the filepath that was found. Note that if no filepath was found # in the loop above, the empty string gets returned. echo "${filepath}" } replace_pass() { local filename dirpaths result header headerlist filename="$1" dirpaths="$2" # This string is inserted after #include directives after having # determined that they are not present in the directory tree and should # be ignored when assessing whether there are still #include directives # that need to be expanded. Note that it is formatted as a comment and # thus will be ignored when the monolithic header is eventually read C # preprocessor and/or compiler. skipstr="\/\/skipped" #skipstr="\/\*skipped\*\/" # The way we (optionally) remove C-style comments results in a single # blank line in its place (regardless of how many lines the comment # spanned. When a comment is removed, it is replaced by this string # so that the line can be deleted with a subsequent sed command. commstr="DeLeTeDCsTyLeCoMmEnT" headerlist="" # Iterate through each line of the header file, accumulating the names of # header files referenced in #include directives. while read -r curline do # Check whether the line begins with a #include directive, but ignore # the line if it contains the skip string. result=$(echo ${curline} | grep '^[[:space:]]*#include ' | grep -v "${skipstr}") # If the #include directive was found... if [ -n "${result}" ]; then # Isolate the header filename. We must take care to include all # characters that might appear between the "" or <>. header=$(echo ${curline} | sed -e "s/#include [\"<]\([a-zA-Z0-9\_\.\/\-]*\)[\">].*/\1/g") # Add the header file to a list. headerlist=$(canonicalize_ws "${headerlist} ${header}") fi done < "${filename}" echoinfo " found references to: ${headerlist}" # Initialize the return value to null. result="" # Iterate over each header file found in the previous loop. for header in ${headerlist}; do # Find the path to the header. header_filepath=$(get_header_path ${header} "${dirpaths}") # If the header has a slash, escape it so that sed doesn't get confused # (since we use '/' as our search-and-replace delimiter). header_esc=$(echo "${header}" | sed -e 's/\//\\\//g') # If the header file was not found, get_header_path() returns an # empty string. This probably means that the header file is a # system header and thus we skip it since we don't want to inline # the contents of system headers anyway. if [ -z "${header_filepath}" ]; then echoinfo " could not locate file '${header}'; marking to skip." # Insert a comment after the #include so we know to ignore it # later. Notice that we mimic the quotes or angle brackets # around the header name, whichever pair was used in the input. cat ${filename} \ | sed -e "s/^[[:space:]]*#include \([\"<]\)\(${header_esc}\)\([\">]\).*/#include \1\2\3 ${skipstr}/" \ > "${filename}.tmp" # Overwrite the original file with the updated copy. mv "${filename}.tmp" ${filename} else echoinfo " located file '${header_filepath}'; inserting." # Strip C-style comments from the file, if requested. if [ -n "${strip_comments}" ]; then header_filename=${header_filepath##*/} # Make a temporary copy of ${header_filepath} stripped of its # C-style comments. This leaves behind a single blank line, # which is then deleted. cat ${header_filepath} \ | perl -0777 -pe "s/\/\*.*?\*\//${commstr}/gs" \ | sed -e "/${commstr}/d" \ > "${header_filename}.tmp" header_to_insert="${header_filename}.tmp" else header_to_insert="${header_filepath}" fi # Replace the #include directive for the current header file with the # contents of that header file, saving the result to a temporary file. # We also insert begin and end markers to allow for more readability. cat ${filename} \ | sed -e "/^[[:space:]]*#include \"${header_esc}\"/ {" \ -e "i // begin ${header}" \ -e "r ${header_to_insert}" \ -e "a // end ${header}" \ -e "d" \ -e "}" \ > "${filename}.tmp" # Overwrite the original header file with the updated copy. mv "${filename}.tmp" ${filename} # If C-style comments were stripped, remove the temporary file. if [ -n "${strip_comments}" ]; then rm "${header_filename}.tmp" fi fi done # works, but leaves blank line: #cat "test.h" | sed -e "/^#include \"foo.h\"/r foo.h" -e "s///" > "test.new.h" # works: #cat "test.h" | sed -e '/^#include \"foo.h\"/ {' -e 'r foo.h' -e 'd' -e '}' > "test.new.h" # works: #cat "test.h" | sed -e '/^#include \"foo.h\"/r foo.h' -e '/^#include \"foo.h\"/d' > "test.new.h" #cat zorn/header.h | sed -e '/^#include \"header1.h\"/ {' -e 'i // begin insertion' -e 'r alice/header1.h' -e 'a // end insertion' -e 'd' -e '}' # Search the updated file for #include directives, but ignore any # hits that also contain the skip string (indicating that the header # file referenced by that #include could not be found). result=$(cat ${filename} | grep '^[[:space:]]*#include ' | grep -v "${skipstr}") # Return the result so the caller knows if we need to proceed with # another pass. echo ${result} } # # -- main function ------------------------------------------------------------- # main() { # The name of the script, stripped of any preceeding path. script_name=${0##*/} # The script name to use in informational output. Defaults to ${script_name}. output_name=${script_name} # Whether or not we should strip C-style comments from the outout. (Default # is to not strip C-style comments.) strip_comments="" # Whether or not we search the directories in dir_list recursively. (Default # is to not search recursively.) recursive_flag="" # Whether or not we should suppress informational output. (Default is to # output messages.) quiet_flag="" # The list of directories to ignore ignore_list="old other temp test testsuite windows" # Process our command line options. while getopts ":o:rcqh" opt; do case $opt in o ) output_name=$OPTARG ;; r ) recursive_flag="1" ;; c ) strip_comments="1" ;; q ) quiet_flag="1" ;; h ) print_usage ;; \? ) print_usage esac done shift $(($OPTIND - 1)) # Print usage if we don't have exactly two arguments. if [ $# != "3" ]; then print_usage fi # Acquire the two required arguments: # - the input header file, # - the output header file, # - the list of directories in which to search for the headers inputfile="$1" outputfile="$2" dir_list="$3" # First, confirm that the directories in dir_list are valid. dir_list2="" for item in ${dir_list}; do # Strip a trailing slash from the path, if it has one. item=${item%/} echoninfo "checking ${item} " if [ -d ${item} ]; then echon2info " ...directory exists." dir_list2="${dir_list2} ${item}" else echon2info " ...invalid directory; omitting." fi done dir_list2=$(canonicalize_ws "${dir_list2}") # Overwrite the original dir_list with the updated copy that omits # invalid directories. dir_list="${dir_list2}" echoinfo "check summary:" echoinfo " accessible directories:" echoinfo " ${dir_list}" # Generate a list of directories (dirpaths) which will be searched whenever # a #include directive is encountered. The method by which dirpaths is # compiled will depend on whether the recursive flag was given. if [ -n "${recursive_flag}" ]; then # If the recursive flag was given, we need to recursively scan each # directory in dir_list for directories with headers via the # function find_header_dirs(). dirpaths="" for item in ${dir_list}; do item_dirpaths=$(find_header_dirs ${item}) dirpaths="${dirpaths} ${item_dirpaths}" done dirpaths=$(canonicalize_ws "${dirpaths}") else # If the recursive flag was not given, we can just use dir_list # as-is, though we opt to filter out the directories that don't # contain .h files. dirpaths="" for item in ${dir_list}; do echoninfo "scanning ${item}" # Acquire a list of the directory's contents. sub_items=$(ls ${item}) # If there is at least one header present, add the current directory to # the list header of directories. result=$(echo ${sub_items} | grep "\.h") if [ -n "${result}" ]; then dirpaths="${dirpaths} ${item}" echon2info " ...found headers." else echon2info " ...no headers found." fi done dirpaths=$(canonicalize_ws "${dirpaths}") fi echoinfo "scan summary:" echoinfo " headers found in:" echoinfo " ${dirpaths}" echoinfo "preparing to monolithify '${inputfile}'." # Make a copy of the inputfile. cp ${inputfile} ${outputfile} echoinfo "new header will be saved to '${outputfile}'." done_flag="0" while [ ${done_flag} == "0" ]; do echoinfo "starting new pass." # Perform a replacement pass. The return string is non-null if # additional passes are necessary and null otherwise. result=$(replace_pass ${outputfile} "${dirpaths}") if [ -n "${result}" ]; then echoinfo "pass finished; result: additional pass(es) needed." else echoinfo "pass finished; result: no further passes needed." fi #exit 1 # If the return value was null, then we're done. if [ -z "${result}" ]; then done_flag="1" fi done echoinfo "substitution complete." echoinfo "monolithic header saved as '${outputfile}'." # Exit peacefully. return 0 } # The script's main entry point, passing all parameters given. main "$@" blis-0.9.0/build/recu-sed.sh000077500000000000000000000332641422157504600156340ustar00rootroot00000000000000#!/bin/bash # # recursive-sed.sh # # Field G. Van Zee # print_usage() { # Echo usage info echo " " echo " "$script_name echo " " echo " Field G. Van Zee" echo " " echo " Recusively descend a directory tree and perform sed commands, either on" echo " the filename or the file contents, or both." echo " " echo " Usage:" echo " ${script_name} [options]" echo " " echo " The following options are accepted:" echo " " echo " -d " echo " Dry run. Go through all the motions, but don't actually" echo " apply any of the sed expressions to file names or contents." echo " -N " echo " Do not proceed recursively into subdirectories; consider" echo " only the files within the current directory. Default" echo " behavior is to act recursively." echo " -h " echo " Consider hidden files and directories. Default behavior is" echo " to ignore them." echo " -n " echo " Use svn mv instead of mv when renaming the file." echo " Notice that this only applies if the filename changes." echo " -p pattern " echo " Specifies the filename pattern, as would be given to the" echo " ls utility, to limit which files are affected. Default is" echo " the to consider all files present." echo " -r dir" echo " The root directory for the recursive action to be performed." echo " Default is to use the current working directory." echo " -v [0|1|2]" echo " verboseness level" echo " level 0: silent (no output)" echo " level 1: default (one line per directory; supress ls stderr)" echo " level 2: verbose (one line per directory; show ls stderr)" echo " " echo " At least one of the following option-argument pairs is required:" echo " " echo " -f sed_expr " echo " Specifies the sed expression that will be applied to the" echo " filenames of the files touched by the script. This expression" echo " must be a search-and-replace pattern." echo " -c sed_expr " echo " Specifies the sed expression that will be applied to the" echo " contents of the files touched by the script. This expression" echo " should be a search-and-replace pattern." echo " -s sed_script" echo " Specifies an arbitrary sed script that will be applied to the" echo " file contents of the files touched by the script." echo " " echo " Note: -c and -s options are mutually exclusive." echo " " # Exit with non-zero exit status exit 1 } perform_sed() { # Variables set by getopts. local exist_dir="$1" #echo "exist_dir: $exist_dir" # The suffix used to create temporary files local temp_file_suffix="sed_temp" # Check that exist_dir actually exists and is a directory if [ ! -d "${exist_dir}" ]; then echo "${script_name}: ${exist_dir} does not seem to be a valid directory." exit 1 fi # Check that the filename sed expression, if given, begins with an 's'. if [ -n "$filename_sed_expr" ]; then # If it's a valid search-and-replace expression, this should return an 's'. filename_sed_char=${filename_sed_expr%%/*} if [ "$filename_sed_char" != "s" ]; then echo "${script_name}: sed expression given with -f must be search-and-replace." exit 1 fi fi # Check that the sed script, if given, exists. if [ -n "$contents_sed_script" ]; then if [ ! -f ${contents_sed_script} ]; then echo "${script_name}: ${contents_sed_script} is not a regular file or does not exist." exit 1 fi fi # Assume that the sed expression is a search-and-replace. Extract the patterns # to match on. (Arbitrary sed expressions should be applied through a sed script.) if [ "$filename_sed_expr" != "" ]; then filename_sed_match=${filename_sed_expr#s/} filename_sed_match=${filename_sed_match%%/*} fi # Get the list of source files in the directory given. Supress stderr if # level 0 or 1 verbosity was requested. #if [ "$verbose_level" != "2" ]; then # old_filepaths=$(ls -d -b ${exist_dir}/${filename_pattern} 2> /dev/null) #else # old_filepaths="$(ls -d -b ${exist_dir}/${filename_pattern})" #fi #echo $old_filepaths #echo "$exist_dir/$filename_pattern" #for old_filepath in $old_filepaths; do #echo "exist_dir: $exist_dir" # Find all files that match the pattern in the current directory. find "${exist_dir}" -maxdepth 1 -name "${filename_pattern}" -print | while read old_filepath do #echo "old_filepath: $old_filepath" # Skip the current directory. if [ "${old_filepath}" == "${exist_dir}" ]; then continue fi # Skip any non-regular files. if [ ! -f "$old_filepath" ]; then # And say we are doing so if verboseness was requested. if [ "$verbose_level" = "2" ]; then echo "${script_name}: Ignoring $old_filepath" fi continue fi # Strip exist_dir from filename. old_filename=${old_filepath##*/} # Strip the filename from old_filepath to leave the directory path. old_dirpath=${old_filepath%/*} # Create a new filename from the old one. If a filename sed expression was given, # it will be applied now. if [ "$filename_sed_expr" != "" ]; then new_filename=$(echo "${old_filename}" | sed "${filename_sed_expr}") else new_filename="${old_filename}" fi #echo "new_filename: $new_filename" # Create the filepath to the new file location. new_filepath="${old_dirpath}/${new_filename}" #echo "new_filepath: $new_filepath" # Grep for the filename pattern within the filename of the current file. if [ "$filename_sed_expr" != "" ]; then grep_filename=$(echo "${old_filename}" | grep "${filename_sed_match}") fi # If we are not performing a dry run, proceed. if [ -z "$dry_run_flag" ]; then # Save the old file permissions so we can re-apply them to the # new file if its contents change (ie: if it's not just a 'mv', # which inherently preserves file permissions). old_perms=$(stat -c %a "${old_filepath}") # If the old and new filepaths are different, then we start off by # renaming the file. (Otherwise, if the old and new filepaths are # identical, then we don't need to do anything to the file.) If # the user requested that we use svn mv, then do that, otherwise we # use regular mv. if [ "${old_filepath}" != "${new_filepath}" ]; then if [ -n "$use_svn_mv_flag" ]; then svn mv "${old_filepath}" "${new_filepath}" else mv -f "${old_filepath}" "${new_filepath}" fi fi #else # A dry run still needs the act upon the "new" file, so if the # filepaths are different, simply set the new filepath to the # old one. (We won't need the previous value of new_filepath # anymore.) #if [ "${old_filepath}" != "${new_filepath}" ]; then # new_filepath="${old_filepath}" #fi fi # Handle the cases that might change the contents of the file. if [ "$contents_sed_expr" != "" ] || [ "$contents_sed_script" != "" ]; then # Execute the sed command based on whether the sed action was given # as a command line expression or a script residing in a file. if [ "$contents_sed_script" != "" ]; then # Perform the action, saving the result to a temporary file. cat "${new_filepath}" | sed -f ${contents_sed_script} \ > ${new_filepath}.${temp_file_suffix} elif [ "$contents_sed_expr" != "" ]; then # Perform the action, saving the result to a temporary file. cat "${new_filepath}" | sed -e "${contents_sed_expr}" \ > ${new_filepath}.${temp_file_suffix} fi # Check the difference. file_diff=$(diff "${new_filepath}" "${new_filepath}.${temp_file_suffix}") # If we are not performing a dry run, proceed. if [ -z "$dry_run_flag" ]; then # If the file contents change. if [ -n "$file_diff" ]; then # Apply the old file permissions to the new file (before we # potentially overwrite the old file with the new one). chmod ${old_perms} "${new_filepath}.${temp_file_suffix}" # Apply the file contents changes to the new filepath (which may # or may not be the same as the old filepath). mv -f "${new_filepath}.${temp_file_suffix}" "${new_filepath}" else # Otherwise remove the new temporary file since it is identical # to the original. rm -f "${new_filepath}.${temp_file_suffix}" fi else # Simply remove the file since we are only performing a dry run. rm -f "${new_filepath}.${temp_file_suffix}" fi fi # Check for dos2unix. If it's not here, we'll just substitute cat. #type_dos2unix=$(type -path dos2unix) #if [ -n "$type_dos2unix" ]; then # dos2unix -q ${new_filepath} #fi # Create a string that indicates what we are changing. We'll use this in # the verbose progress echo to indicate how the file is or would be changed. if [ -n "$grep_filename" ] && [ -n "$file_diff" ]; then which_matches="filename/contents" file_touched="yes" elif [ -n "$grep_filename" ] && [ -z "$file_diff" ]; then which_matches="filename " file_touched="yes" elif [ -z "$grep_filename" ] && [ -n "$file_diff" ]; then which_matches=" contents" file_touched="yes" else which_matches="" file_touched="no" fi # Be verbose, if requested, about which file we're looking at. if [ "$verbose_level" != "0" ]; then # But we only need to output a line if the file was touched. if [ "$file_touched" != "no" ]; then # Construct a relative filepath by stripping the initial root # directory so that the output does not span as many columns on # the terminal. rel_old_filepath=${old_filepath#${initial_root_dir}/} # Add a "dry run" condition to the output if we're doing a dry-run # so that the user knows we didn't really change anything. if [ -z "$dry_run_flag" ]; then echo "$script_name: Changing [${which_matches}] of ${rel_old_filepath}" else echo "$script_name: Changing (dry run) [${which_matches}] of ${rel_old_filepath}" fi fi fi done # Exit peacefully. return 0 } recursive_sed() { # Local variable declarations local item sub_items curr_dir this_dir # Extract our argument curr_dir="$1" # Call our function to perform the sed operations on the files in the # directory given. perform_sed "${curr_dir}" # If we were asked to act recursively, then continue processing # curr_dir's contents. if [ "$recursive_flag" = "1" ]; then # Get a listing of items in the directory according to the hidden # files/directories flag. if [ -n "$hidden_files_dirs_flag" ]; then # Get a listing of the directories in curr_dir (including hidden # files and directories). sub_items=$(ls -a "$curr_dir") else # Get a listing of the directories in curr_dir. sub_items=$(ls "$curr_dir") fi #echo "sub_items: $sub_items" # Descend into the contents of curr_dir, calling recursive_sed on # any items that are directories. find "${curr_dir}" -maxdepth 1 -name "*" -print | while read item do #echo "conisdering item: $item" # Skip the current directory. if [ "${item}" == "${curr_dir}" ]; then continue fi # If item is a directory, descend into it. if [ -d "$item" ]; then #echo "item is dir: $item" recursive_sed "$item" fi done fi # Return peacefully return 0 } main() { # Variables set by getopts. dry_run_flag="" hidden_files_dirs_flag="" use_svn_mv_flag="" filename_pattern="" root_dir="" initial_root_dir="" verbose_level="" filename_sed_expr="" contents_sed_expr="" contents_sed_script="" recursive_flag="1" # Get the script name script_name=${0##*/} # Local variable declarations. local item sub_items this_dir # Process our command line options. while getopts ":c:df:hp:r:s:nNv:" opt; do case $opt in d ) dry_run_flag="1" ;; h ) hidden_files_dirs_flag="1" ;; n ) use_svn_mv_flag="1" ;; N ) recursive_flag="0" ;; v ) verbose_level="$OPTARG" ;; p ) filename_pattern="$OPTARG" ;; r ) root_dir="$OPTARG" ;; f ) filename_sed_expr="$OPTARG" ;; c ) contents_sed_expr="$OPTARG" ;; s ) contents_sed_script="$OPTARG" ;; \? ) print_usage esac done shift $(($OPTIND - 1)) # Make sure we've parsed all command line arguments by now. if [ $# != "0" ]; then echo "${script_name}: Unparsed command line arguments! Try running with no arguments for help." exit 1 fi # Make sure we received at least one of the required options. if [ -z "$filename_sed_expr" ] && [ -z "$contents_sed_expr" ] && [ -z "$contents_sed_script" ]; then print_usage fi # Make sure that both a file contents sed expression and sed script were # not given. if [ "$contents_sed_expr" != "" ] && [ "$contents_sed_script" != "" ] ; then echo "${script_name}: The -c and -s options may not be used at the same time." exit 1 fi # Make sure that verboseness level is valid. if [ "$verbose_level" != "0" ] && [ "$verbose_level" != "1" ] && [ "$verbose_level" != "2" ]; then verbose_level="1" fi # Prepare the filename pattern arguments to perform_sed(). if [ "$filename_pattern" = "" ] ; then filename_pattern='*' fi # Prepare the directory arguments to perform_sed(). if [ "$root_dir" != "" ] ; then # Strip / from end of directory paths, if there is one. root_dir=${root_dir%/} else root_dir=$PWD fi initial_root_dir=${root_dir} #echo "root_dir: $root_dir" # Begin recursing on the root directory. recursive_sed "$root_dir" # Exit peacefully return 0 } # The script's main entry point, passing all parameters given. main "$@" blis-0.9.0/build/regen-symbols.sh000077500000000000000000000063631422157504600167130ustar00rootroot00000000000000#!/bin/sh # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2018, The University of Texas at Austin # # 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 copyright holder(s) nor the names # 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 COPYRIGHT # HOLDER 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. # # # # This script regenerates a list of symbols for use when building # Windows-compatible DLLs. We assume that this script will be run after # running configure as: # # ./configure --enable-cblas haswell # # and compiling BLIS normally. (Notice that we also prune out all # haswell/zen-related context initialization and reference kernels.) # libblis='lib/haswell/libblis.so' symfile='build/libblis-symbols.def' echo "EXPORTS" > def.exports #nm -g ${libblis} | grep -o " D BLIS_.*" | cut -f2- "-dD" > def.blis_const nm -g ${libblis} | grep -o " T bli_.*" | cut -f2- "-dT" > def.blis nm -g ${libblis} | grep -o " T bla_.*" | cut -f2- "-dT" > def.blis_bla nm -g ${libblis} | grep -o " T cblas_.*" | cut -f2- "-dT" > def.blis_cblas nm -g ${libblis} | grep -o " T s[acdgnrst].*" | cut -f2- "-dT" > def.blas_s nm -g ${libblis} | grep -o " T d[acdgnrstz].*" | cut -f2- "-dT" > def.blas_d nm -g ${libblis} | grep -o " T c[acdghrst].*" | cut -f2- "-dT" > def.blas_c nm -g ${libblis} | grep -o " T z[acdghrst].*" | cut -f2- "-dT" > def.blas_z nm -g ${libblis} | grep -o " T i[cdsz].*" | cut -f2- "-dT" > def.blas_i cat def.exports \ def.blis \ def.blis_bla \ def.blas_s \ def.blas_d \ def.blas_c \ def.blas_z \ def.blas_i \ def.blis_cblas \ | cut -f2- "-d " \ | grep -v init_haswell \ | grep -v haswell_ref \ | grep -v zen_ref \ > ${symfile} rm -f \ def.exports \ def.blis \ def.blis_bla \ def.blas_s \ def.blas_d \ def.blas_c \ def.blas_z \ def.blas_i \ def.blis_cblas blis-0.9.0/build/templates/000077500000000000000000000000001422157504600155545ustar00rootroot00000000000000blis-0.9.0/build/templates/license.c000066400000000000000000000032741422157504600173500ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2019, The University of Texas at Austin Copyright (C) 2018, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ blis-0.9.0/build/templates/license.h000066400000000000000000000032741422157504600173550ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2019, The University of Texas at Austin Copyright (C) 2018, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ blis-0.9.0/build/templates/license.sh000066400000000000000000000033251422157504600175350ustar00rootroot00000000000000#!/usr/bin/env bash # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2019, The University of Texas at Austin # Copyright (C) 2018, Advanced Micro Devices, Inc. # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # blis-0.9.0/common.mk000066400000000000000000001236641422157504600143140ustar00rootroot00000000000000# # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2014, The University of Texas at Austin # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # # Only include this block of code once ifndef COMMON_MK_INCLUDED COMMON_MK_INCLUDED := yes # # --- CFLAGS storage functions ------------------------------------------------- # # Define a function that stores the value of a variable to a different # variable containing a specified suffix (corresponding to a configuration). define store-var-for $(strip $(1)).$(strip $(2)) := $($(strip $(1))) endef # Define a function similar to store-var-for, except that appends instead # of overwriting. define append-var-for $(strip $(1)).$(strip $(2)) += $($(strip $(1))) endef # Define a function that stores the value of all of the variables in a # make_defs.mk file to other variables with the configuration (the # argument $(1)) added as a suffix. This function is called once from # each make_defs.mk. Also, add the configuration to CONFIGS_INCL. define store-make-defs $(eval $(call store-var-for,CC, $(1))) $(eval $(call store-var-for,CC_VENDOR, $(1))) $(eval $(call store-var-for,CPPROCFLAGS,$(1))) $(eval $(call store-var-for,CLANGFLAGS, $(1))) $(eval $(call store-var-for,CXXLANGFLAGS,$(1))) $(eval $(call store-var-for,CMISCFLAGS, $(1))) $(eval $(call store-var-for,CPICFLAGS, $(1))) $(eval $(call store-var-for,CWARNFLAGS, $(1))) $(eval $(call store-var-for,CDBGFLAGS, $(1))) $(eval $(call store-var-for,COPTFLAGS, $(1))) $(eval $(call store-var-for,CKOPTFLAGS, $(1))) $(eval $(call store-var-for,CKVECFLAGS, $(1))) $(eval $(call store-var-for,CROPTFLAGS, $(1))) $(eval $(call store-var-for,CRVECFLAGS, $(1))) CONFIGS_INCL += $(1) endef # Define a function that retreives the value of a variable for a # given configuration. define load-var-for $($(strip $(1)).$(strip $(2))) endef # # --- CFLAGS query functions --------------------------------------------------- # # Define some functions that return the appropriate CFLAGS for a given # configuration. This assumes that the make_defs.mk files have already been # included, which results in those values having been stored to # configuration-qualified variables. get-noopt-cflags-for = $(strip $(CFLAGS_PRESET) \ $(call load-var-for,CDBGFLAGS,$(1)) \ $(call load-var-for,CWARNFLAGS,$(1)) \ $(call load-var-for,CPICFLAGS,$(1)) \ $(call load-var-for,CMISCFLAGS,$(1)) \ $(call load-var-for,CLANGFLAGS,$(1)) \ $(call load-var-for,CPPROCFLAGS,$(1)) \ $(CTHREADFLAGS) \ $(CINCFLAGS) $(VERS_DEF) \ ) get-noopt-cxxflags-for = $(strip $(CFLAGS_PRESET) \ $(call load-var-for,CDBGFLAGS,$(1)) \ $(call load-var-for,CWARNFLAGS,$(1)) \ $(call load-var-for,CPICFLAGS,$(1)) \ $(call load-var-for,CMISCFLAGS,$(1)) \ $(call load-var-for,CXXLANGFLAGS,$(1)) \ $(call load-var-for,CPPROCFLAGS,$(1)) \ $(CTHREADFLAGS) \ $(CINCFLAGS) $(VERS_DEF) \ ) get-refinit-cflags-for = $(strip $(call load-var-for,COPTFLAGS,$(1)) \ $(call get-noopt-cflags-for,$(1)) \ -DBLIS_CNAME=$(1) \ $(BUILD_CPPFLAGS) \ $(BUILD_SYMFLAGS) \ ) get-refkern-cflags-for = $(strip $(call load-var-for,CROPTFLAGS,$(1)) \ $(call load-var-for,CRVECFLAGS,$(1)) \ $(call get-noopt-cflags-for,$(1)) \ $(COMPSIMDFLAGS) \ -DBLIS_CNAME=$(1) \ $(BUILD_CPPFLAGS) \ $(BUILD_SYMFLAGS) \ ) get-config-cflags-for = $(strip $(call load-var-for,COPTFLAGS,$(1)) \ $(call get-noopt-cflags-for,$(1)) \ $(BUILD_CPPFLAGS) \ $(BUILD_SYMFLAGS) \ ) get-frame-cflags-for = $(strip $(call load-var-for,COPTFLAGS,$(1)) \ $(call get-noopt-cflags-for,$(1)) \ $(BUILD_CPPFLAGS) \ $(BUILD_SYMFLAGS) \ ) get-kernel-cflags-for = $(strip $(call load-var-for,CKOPTFLAGS,$(1)) \ $(call load-var-for,CKVECFLAGS,$(1)) \ $(call get-noopt-cflags-for,$(1)) \ $(BUILD_CPPFLAGS) \ $(BUILD_SYMFLAGS) \ ) # When compiling sandboxes, we use flags similar to those of general framework # source. This ensures that the same code can be linked and run across various # sub-configurations. get-addon-c99flags-for = $(strip $(call load-var-for,COPTFLAGS,$(1)) \ $(call get-noopt-cflags-for,$(1)) \ $(CADDONINCFLAGS) \ $(BUILD_CPPFLAGS) \ $(BUILD_SYMFLAGS) \ ) get-addon-cxxflags-for = $(strip $(call load-var-for,COPTFLAGS,$(1)) \ $(call get-noopt-cxxflags-for,$(1)) \ $(CADDONINCFLAGS) \ $(BUILD_CPPFLAGS) \ $(BUILD_SYMFLAGS) \ ) # When compiling sandboxes, we use flags similar to those of general framework # source. This ensures that the same code can be linked and run across various # sub-configurations. (NOTE: If we ever switch to using refkernel or kernel # flags, we should prevent enabling sandboxes for umbrella families by verifying # that config_list == config_name if --enable-sandbox is given. THIS ALSO # APPLIES TO ADDONS ABOVE.) get-sandbox-c99flags-for = $(strip $(call load-var-for,COPTFLAGS,$(1)) \ $(call get-noopt-cflags-for,$(1)) \ $(CSANDINCFLAGS) \ $(BUILD_CPPFLAGS) \ $(BUILD_SYMFLAGS) \ ) get-sandbox-cxxflags-for = $(strip $(call load-var-for,COPTFLAGS,$(1)) \ $(call get-noopt-cxxflags-for,$(1)) \ $(CSANDINCFLAGS) \ $(BUILD_CPPFLAGS) \ $(BUILD_SYMFLAGS) \ ) # Define a separate function that will return appropriate flags for use by # applications that want to use the same basic flags as those used when BLIS # was compiled. (NOTE: This is the same as the $(get-frame-cflags-for ...) # function, except that it omits two variables that contain flags exclusively # for use when BLIS is being compiled/built: BUILD_CPPFLAGS, which contains a # cpp macro that confirms that BLIS is being built; and BUILD_SYMFLAGS, which # contains symbol export flags that are only needed when a shared library is # being compiled/linked.) get-user-cflags-for = $(strip $(call load-var-for,COPTFLAGS,$(1)) \ $(call get-noopt-cflags-for,$(1)) \ ) # Define functions that return messages appropriate for each non-verbose line # of compilation output. get-noopt-text = "(CFLAGS for no optimization)" get-refinit-text-for = "('$(1)' CFLAGS for ref. kernel init)" get-refkern-text-for = "('$(1)' CFLAGS for ref. kernels)" get-config-text-for = "('$(1)' CFLAGS for config code)" get-frame-text-for = "('$(1)' CFLAGS for framework code)" get-kernel-text-for = "('$(1)' CFLAGS for kernels)" get-addon-c99text-for = "('$(1)' CFLAGS for addons)" get-addon-cxxtext-for = "('$(1)' CXXFLAGS for addons)" get-sandbox-c99text-for = "('$(1)' CFLAGS for sandboxes)" get-sandbox-cxxtext-for = "('$(1)' CXXFLAGS for sandboxes)" # # --- Miscellaneous helper functions ------------------------------------------- # # Define functions that filters a list of filepaths $(1) that contain (or # omit) an arbitrary substring $(2). files-that-contain = $(strip $(foreach f, $(1), $(if $(findstring $(2),$(f)),$(f),))) files-that-dont-contain = $(strip $(foreach f, $(1), $(if $(findstring $(2),$(f)),,$(f)))) # Define a function that removes duplicate strings *without* using the sort # function. rm-dups = $(if $1,$(firstword $1) $(call rm-dups,$(filter-out $(firstword $1),$1))) # # --- Include makefile configuration file -------------------------------------- # # Use the current directory as the default path to the root directory for # makefile fragments (and the configuration family's make_defs.mk), but # allow the includer to override this value if it needs to point to an # installation directory. ifeq ($(strip $(SHARE_PATH)),) SHARE_PATH := . endif # Define the name of the configuration file. CONFIG_MK_FILE := config.mk # Identify the base path for the root directory for makefile fragments (and # the configuration family's make_defs.mk). We define this path in terms of # SHARE_PATH, which gets a default value above (which is what happens for the # top-level Makefile). If SHARE_PATH is specified by the Makefile prior to # including common.mk, that path is used instead. This allows Makefiles for # example code and test drivers to reference an installed prefix directory # for situations when the build directory no longer exists. BASE_SHARE_PATH := $(SHARE_PATH) # Include the configuration file. -include $(BASE_SHARE_PATH)/$(CONFIG_MK_FILE) # # --- Handle 'make clean' and friends without config.mk ------------------------ # # Detect whether we actually got the configuration file. If we didn't, then # it is likely that the user has not yet generated it (via configure). ifeq ($(strip $(CONFIG_MK_INCLUDED)),yes) CONFIG_MK_PRESENT := yes IS_CONFIGURED := yes else CONFIG_MK_PRESENT := no IS_CONFIGURED := no endif # If we didn't get config.mk, then we need to set some basic variables so # that make will function without error for things like 'make clean'. ifeq ($(IS_CONFIGURED),no) # If this makefile fragment is being run and there is no config.mk present, # then it's probably safe to assume that the user is currently located in the # source distribution. DIST_PATH := . # Even though they won't be used explicitly, it appears that setting these # INSTALL_* variables to something sane (that is, not allowing them default # to the empty string) is necessary to prevent make from hanging, likely # because the statements that define UNINSTALL_LIBS and UNINSTALL_HEADERS, # when evaluated, result in running 'find' on the root directory--definitely # something we would like to avoid. INSTALL_LIBDIR := $(HOME)/blis/lib INSTALL_INCDIR := $(HOME)/blis/include INSTALL_SHAREDIR := $(HOME)/blis/share endif # # --- Primary makefile variable definitions ------------------------------------ # # Construct the architecture-version string, which will be used to name the # library upon installation. VERS_CONF := $(VERSION)-$(CONFIG_NAME) # All makefile fragments in the tree will have this name. FRAGMENT_MK := .fragment.mk # Locations of important files. BUILD_DIR := build CONFIG_DIR := config FRAME_DIR := frame REFKERN_DIR := ref_kernels KERNELS_DIR := kernels ADDON_DIR := addon SANDBOX_DIR := sandbox OBJ_DIR := obj LIB_DIR := lib INCLUDE_DIR := include BLASTEST_DIR := blastest TESTSUITE_DIR := testsuite VEND_DIR := vendor VEND_CPP_DIR := $(VEND_DIR)/cpp VEND_TESTCPP_DIR := $(VEND_DIR)/testcpp # The filename suffix for reference kernels. REFNM := ref # Source suffixes. CONFIG_SRC_SUFS := c KERNELS_SRC_SUFS := c s S FRAME_SRC_SUFS := c ADDON_C99_SUFS := c ADDON_CXX_SUFS := cc cpp cxx ADDON_SRC_SUFS := $(ADDON_C99_SUFS) $(ADDON_CXX_SUFS) SANDBOX_C99_SUFS := c SANDBOX_CXX_SUFS := cc cpp cxx SANDBOX_SRC_SUFS := $(SANDBOX_C99_SUFS) $(SANDBOX_CXX_SUFS) # Header suffixes. FRAME_HDR_SUFS := h ADDON_H99_SUFS := h ADDON_HXX_SUFS := hh hpp hxx ADDON_HDR_SUFS := $(ADDON_H99_SUFS) $(ADDON_HXX_SUFS) SANDBOX_H99_SUFS := h SANDBOX_HXX_SUFS := hh hpp hxx SANDBOX_HDR_SUFS := $(SANDBOX_H99_SUFS) $(SANDBOX_HXX_SUFS) # Combine all header suffixes and remove duplicates via sort(). ALL_HDR_SUFS := $(sort $(FRAME_HDR_SUFS) \ $(ADDON_HDR_SUFS) \ $(SANDBOX_HDR_SUFS) ) ALL_H99_SUFS := $(sort $(FRAME_HDR_SUFS) \ $(ADDON_HDR_SUFS) \ $(SANDBOX_H99_SUFS) ) # The names of scripts that check output from the BLAS test drivers and # BLIS test suite. BLASTEST_CHECK := check-blastest.sh TESTSUITE_CHECK := check-blistest.sh # The names of the testsuite input/configuration files. TESTSUITE_CONF_GEN := input.general TESTSUITE_CONF_OPS := input.operations TESTSUITE_FAST_GEN := input.general.fast TESTSUITE_FAST_OPS := input.operations.fast TESTSUITE_MIXD_GEN := input.general.mixed TESTSUITE_MIXD_OPS := input.operations.mixed TESTSUITE_SALT_GEN := input.general.salt TESTSUITE_SALT_OPS := input.operations.salt TESTSUITE_OUT_FILE := output.testsuite # CHANGELOG file. CHANGELOG := CHANGELOG # Something for OS X so that echo -n works as expected. SHELL := bash # Construct paths to the four primary directories of source code: # the config directory, general framework code, reference kernel code, # and optimized kernel code. Also process paths for addon and sandbox # directories. CONFIG_PATH := $(DIST_PATH)/$(CONFIG_DIR) FRAME_PATH := $(DIST_PATH)/$(FRAME_DIR) REFKERN_PATH := $(DIST_PATH)/$(REFKERN_DIR) KERNELS_PATH := $(DIST_PATH)/$(KERNELS_DIR) ADDON_PATH := $(DIST_PATH)/$(ADDON_DIR) SANDBOX_PATH := $(DIST_PATH)/$(SANDBOX_DIR) # Construct paths to some optional C++ template headers contributed by AMD. VEND_CPP_PATH := $(DIST_PATH)/$(VEND_CPP_DIR) VEND_TESTCPP_PATH := $(DIST_PATH)/$(VEND_TESTCPP_DIR) # Construct paths to the makefile fragments for the four primary directories # of source code: the config directory, general framework code, reference # kernel code, and optimized kernel code. CONFIG_FRAG_PATH := ./obj/$(CONFIG_NAME)/$(CONFIG_DIR) FRAME_FRAG_PATH := ./obj/$(CONFIG_NAME)/$(FRAME_DIR) REFKERN_FRAG_PATH := ./obj/$(CONFIG_NAME)/$(REFKERN_DIR) KERNELS_FRAG_PATH := ./obj/$(CONFIG_NAME)/$(KERNELS_DIR) ADDON_FRAG_PATH := ./obj/$(CONFIG_NAME)/$(ADDON_DIR) SANDBOX_FRAG_PATH := ./obj/$(CONFIG_NAME)/$(SANDBOX_DIR) # # --- Library name and local paths --------------------------------------------- # # Use lib/CONFIG_NAME as the default path to the local header files, but # allow the includer to override this value if it needs to point to an # installation directory. ifeq ($(strip $(LIB_PATH)),) LIB_PATH := $(LIB_DIR)/$(CONFIG_NAME) endif # Identify the base path for the intermediate library directory. We define # this path in terms of LIB_PATH, which gets a default value above (which is # what happens for the top-level Makefile). If LIB_PATH is specified by the # Makefile prior to including common.mk, that path is used instead. This # allows Makefiles for example code and test drivers to reference an installed # prefix directory for situations when the build directory no longer exists. BASE_LIB_PATH := $(LIB_PATH) # The base name of the BLIS library that we will build. LIBBLIS := libblis # The shared (dynamic) library file suffix is different for Linux and OS X. ifeq ($(OS_NAME),Darwin) SHLIB_EXT := dylib else ifeq ($(IS_WIN),yes) ifeq ($(CC_VENDOR),gcc) SHLIB_EXT := dll.a else SHLIB_EXT := lib endif else SHLIB_EXT := so endif # Note: These names will be modified later to include the configuration and # version strings. LIBBLIS_A := $(LIBBLIS).a LIBBLIS_SO := $(LIBBLIS).$(SHLIB_EXT) # Append the base library path to the library names. LIBBLIS_A_PATH := $(BASE_LIB_PATH)/$(LIBBLIS_A) LIBBLIS_SO_PATH := $(BASE_LIB_PATH)/$(LIBBLIS_SO) # Create a filepath to a local symlink to the soname--that is, the same as # LIBBLIS_SO_PATH except with the .so major version number. Since the shared # library lists its soname as 'libblis.so.n', where n is the .so major version # number, a symlink in BASE_LIB_PATH is needed so that ld can find the local # shared library when the testsuite is run via 'make test' or 'make check'. ifeq ($(OS_NAME),Darwin) # OS X shared library extensions. LIBBLIS_SO_MAJ_EXT := $(SO_MAJOR).$(SHLIB_EXT) LIBBLIS_SO_MMB_EXT := $(SO_MMB).$(SHLIB_EXT) else ifeq ($(IS_WIN),yes) # Windows shared library extension. LIBBLIS_SO_MAJ_EXT := $(SO_MAJOR).dll LIBBLIS_SO_MMB_EXT := else # Linux shared library extensions. LIBBLIS_SO_MAJ_EXT := $(SHLIB_EXT).$(SO_MAJOR) LIBBLIS_SO_MMB_EXT := $(SHLIB_EXT).$(SO_MMB) endif LIBBLIS_SONAME := $(LIBBLIS).$(LIBBLIS_SO_MAJ_EXT) LIBBLIS_SO_MAJ_PATH := $(BASE_LIB_PATH)/$(LIBBLIS_SONAME) # Construct the output path when building a shared library. # NOTE: This code and the code immediately above is a little curious and # perhaps could be refactored (carefully). ifeq ($(IS_WIN),yes) LIBBLIS_SO_OUTPUT_NAME := $(LIBBLIS_SO_MAJ_PATH) else LIBBLIS_SO_OUTPUT_NAME := $(LIBBLIS_SO_PATH) endif # # --- Utility program definitions ---------------------------------------------- # SH := /bin/sh MV := mv MKDIR := mkdir -p RM_F := rm -f RM_RF := rm -rf SYMLINK := ln -sf FIND := find GREP := grep EGREP := grep -E XARGS := xargs INSTALL := install -c # Script for creating a monolithic header file. #FLATTEN_H := $(DIST_PATH)/build/flatten-headers.sh FLATTEN_H := $(PYTHON) $(DIST_PATH)/build/flatten-headers.py # Default archiver flags. ARFLAGS := cr # Used to refresh CHANGELOG. GIT := git GIT_LOG := $(GIT) log --decorate # # --- Default linker definitions ----------------------------------------------- # # NOTE: This section needs to reside before the inclusion of make_defs.mk # files (just below), as most configurations' make_defs.mk don't tinker # with things like LDFLAGS, but some do (or may), in which case they can # manually override whatever they need. # Define the external libraries we may potentially need at link-time. ifeq ($(IS_WIN),yes) LIBM := else LIBM := -lm endif LIBMEMKIND := -lmemkind # Default linker flags. # NOTE: -lpthread is needed unconditionally because BLIS uses pthread_once() # to initialize itself in a thread-safe manner. The one exception to this # rule: if --disable-system is given at configure-time, LIBPTHREAD is empty. LDFLAGS := $(LDFLAGS_PRESET) $(LIBM) $(LIBPTHREAD) # Add libmemkind to the link-time flags, if it was enabled at configure-time. ifeq ($(MK_ENABLE_MEMKIND),yes) LDFLAGS += $(LIBMEMKIND) endif # Never use libm with Intel compilers. ifeq ($(CC_VENDOR),icc) LDFLAGS := $(filter-out $(LIBM),$(LDFLAGS)) endif # Never use libmemkind with Intel SDE. ifeq ($(DEBUG_TYPE),sde) LDFLAGS := $(filter-out $(LIBMEMKIND),$(LDFLAGS)) endif # Specify the shared library's 'soname' field. # NOTE: The flag for creating shared objects is different for Linux and OS X. ifeq ($(OS_NAME),Darwin) # OS X shared library link flags. SOFLAGS := -dynamiclib ifeq ($(MK_ENABLE_RPATH),yes) SOFLAGS += -Wl,-install_name,@rpath/$(LIBBLIS_SONAME) else SOFLAGS += -Wl,-install_name,$(libdir)/$(LIBBLIS_SONAME) endif else SOFLAGS := -shared ifeq ($(IS_WIN),yes) # Windows shared library link flags. ifeq ($(CC_VENDOR),clang) SOFLAGS += -Wl,-implib:$(BASE_LIB_PATH)/$(LIBBLIS).lib else SOFLAGS += -Wl,--out-implib,$(BASE_LIB_PATH)/$(LIBBLIS).dll.a endif else # Linux shared library link flags. SOFLAGS += -Wl,-soname,$(LIBBLIS_SONAME) endif endif # Decide which library to link to for things like the testsuite and BLIS test # drivers. We default to the static library, unless only the shared library was # enabled, in which case we use the shared library. LIBBLIS_L := $(LIBBLIS_A) LIBBLIS_LINK := $(LIBBLIS_A_PATH) ifeq ($(MK_ENABLE_SHARED),yes) ifeq ($(MK_ENABLE_STATIC),no) LIBBLIS_L := $(LIBBLIS_SO) LIBBLIS_LINK := $(LIBBLIS_SO_PATH) ifeq ($(IS_WIN),no) # For Linux and OS X: set rpath property of shared object. ifeq ($(OS_NAME),Darwin) # rpath for test_libblis.x LDFLAGS += -Wl,-rpath,@executable_path/$(BASE_LIB_PATH) # rpath for BLAS tests LDFLAGS += -Wl,-rpath,@executable_path/../../../$(BASE_LIB_PATH) else # rpath for test_libblis.x LDFLAGS += -Wl,-rpath,'$$ORIGIN/$(BASE_LIB_PATH)' # rpath for BLAS tests LDFLAGS += -Wl,-rpath,'$$ORIGIN/../../../$(BASE_LIB_PATH)' endif endif endif # On windows, use the shared library even if static is created. ifeq ($(IS_WIN),yes) LIBBLIS_L := $(LIBBLIS_SO) LIBBLIS_LINK := $(LIBBLIS_SO_PATH) endif endif # # --- Include makefile definitions file ---------------------------------------- # # Define the name of the file containing build and architecture-specific # makefile definitions. MAKE_DEFS_FILE := make_defs.mk # Assemble a list of all configuration family members, including the # configuration family name itself. Note that sort() will remove duplicates # for situations where CONFIG_NAME is present in CONFIG_LIST, such as would # be the case for singleton families. CONFIG_LIST_FAM := $(sort $(strip $(CONFIG_LIST) $(CONFIG_NAME))) # Construct the paths to the makefile definitions files, each of which # resides in a separate configuration sub-directory. We use CONFIG_LIST_FAM # since we might need the makefile definitions associated with the # configuration family (if it is an umbrella family). # NOTE: We use the prefix $(BASE_SHARE_PATH)/$(CONFIG_DIR)/ instead of # $(CONFIG_PATH) so that make_defs.mk can be found when it is installed, # provided the caller defined SHARE_PATH to that install directory. CONFIG_PATHS := $(addprefix $(BASE_SHARE_PATH)/$(CONFIG_DIR)/, \ $(CONFIG_LIST_FAM)) MAKE_DEFS_MK_PATHS := $(addsuffix /$(MAKE_DEFS_FILE), $(CONFIG_PATHS)) # Initialize the list of included (found) configurations to empty. CONFIGS_INCL := # Include the makefile definitions files implied by the list of configurations. -include $(MAKE_DEFS_MK_PATHS) # Detect whether we actually got all of the make definitions files. If # we didn't, then maybe a configuration is mislabeled or missing. The # check-env-make-defs target checks ALL_MAKE_DEFS_MK_PRESENT and outputs # an error message if it is set to 'no'. # NOTE: We use CONFIG_LIST_FAM as the expected list of configurations. # This combines CONFIG_NAME with CONFIG_LIST. The inclusion of CONFIG_NAME # is needed for situations where the configuration family is an umbrella # family (e.g. 'intel64'), since families have separate make_def.mk files. CONFIGS_EXPECTED := $(CONFIG_LIST_FAM) ifeq ($(sort $(strip $(CONFIGS_INCL))), \ $(sort $(strip $(CONFIGS_EXPECTED)))) ALL_MAKE_DEFS_MK_PRESENT := yes else ALL_MAKE_DEFS_MK_PRESENT := no endif # # --- Configuration-agnostic flags --------------------------------------------- # # --- Linker program --- # Use whatever compiler was chosen. LINKER := $(CC) # --- Warning flags --- CWARNFLAGS := # Disable unused function warnings and stop compiling on first error for # all compilers that accept such options: gcc, clang, and icc. ifneq ($(CC_VENDOR),ibm) CWARNFLAGS += -Wall -Wno-unused-function -Wfatal-errors endif # Disable tautological comparision warnings in clang. ifeq ($(CC_VENDOR),clang) CWARNFLAGS += -Wno-tautological-compare -Wno-pass-failed endif $(foreach c, $(CONFIG_LIST_FAM), $(eval $(call append-var-for,CWARNFLAGS,$(c)))) # --- Position-independent code flags (shared libraries only) --- # Emit position-independent code for dynamic linking. ifeq ($(IS_WIN),yes) # Note: Don't use any fPIC flags for Windows builds since all code is position- # independent. CPICFLAGS := else CPICFLAGS := -fPIC endif $(foreach c, $(CONFIG_LIST_FAM), $(eval $(call append-var-for,CPICFLAGS,$(c)))) # --- Symbol exporting flags (shared libraries only) --- # NOTE: These flags are only applied when building BLIS and not used by # applications that import BLIS compilation flags via the # $(get-user-cflags-for ...) function. # Determine default export behavior / visibility of symbols for gcc. ifeq ($(CC_VENDOR),gcc) ifeq ($(IS_WIN),yes) ifeq ($(EXPORT_SHARED),all) BUILD_SYMFLAGS := -Wl,--export-all-symbols, -Wl,--enable-auto-import else # ifeq ($(EXPORT_SHARED),public) BUILD_SYMFLAGS := -Wl,--exclude-all-symbols endif else # ifeq ($(IS_WIN),no) ifeq ($(EXPORT_SHARED),all) # Export all symbols by default. BUILD_SYMFLAGS := -fvisibility=default else # ifeq ($(EXPORT_SHARED),public) # Hide all symbols by default and export only those that have been annotated # as needing to be exported. BUILD_SYMFLAGS := -fvisibility=hidden endif endif endif # Determine default export behavior / visibility of symbols for icc. # NOTE: The Windows branches have been omitted since we currently make no # effort to support Windows builds via icc (only gcc/clang via AppVeyor). ifeq ($(CC_VENDOR),icc) ifeq ($(EXPORT_SHARED),all) # Export all symbols by default. BUILD_SYMFLAGS := -fvisibility=default else # ifeq ($(EXPORT_SHARED),public) # Hide all symbols by default and export only those that have been annotated # as needing to be exported. BUILD_SYMFLAGS := -fvisibility=hidden endif endif # Determine default export behavior / visibility of symbols for clang. ifeq ($(CC_VENDOR),clang) ifeq ($(IS_WIN),yes) ifeq ($(EXPORT_SHARED),all) # NOTE: clang on Windows does not appear to support exporting all symbols # by default, and therefore we ignore the value of EXPORT_SHARED. BUILD_SYMFLAGS := else # ifeq ($(EXPORT_SHARED),public) # NOTE: The default behavior of clang on Windows is to hide all symbols # and only export functions and other declarations that have beenannotated # as needing to be exported. BUILD_SYMFLAGS := endif else # ifeq ($(IS_WIN),no) ifeq ($(EXPORT_SHARED),all) # Export all symbols by default. BUILD_SYMFLAGS := -fvisibility=default else # ifeq ($(EXPORT_SHARED),public) # Hide all symbols by default and export only those that have been annotated # as needing to be exported. BUILD_SYMFLAGS := -fvisibility=hidden endif endif endif # --- Language flags --- # Enable C99. CLANGFLAGS := -std=c99 $(foreach c, $(CONFIG_LIST_FAM), $(eval $(call append-var-for,CLANGFLAGS,$(c)))) # Enable C++11. CXXLANGFLAGS := -std=c++11 $(foreach c, $(CONFIG_LIST_FAM), $(eval $(call append-var-for,CXXLANGFLAGS,$(c)))) # --- C Preprocessor flags --- # Enable clock_gettime() in time.h. CPPROCFLAGS := -D_POSIX_C_SOURCE=200112L $(foreach c, $(CONFIG_LIST_FAM), $(eval $(call append-var-for,CPPROCFLAGS,$(c)))) # --- Threading flags --- # NOTE: We don't have to explicitly omit -pthread when --disable-system is given # since that option forces --enable-threading=none, and thus -pthread never gets # added to begin with. ifeq ($(CC_VENDOR),gcc) ifeq ($(THREADING_MODEL),auto) THREADING_MODEL := openmp endif ifeq ($(THREADING_MODEL),openmp) CTHREADFLAGS := -fopenmp LDFLAGS += -fopenmp endif ifeq ($(THREADING_MODEL),pthreads) CTHREADFLAGS := -pthread LDFLAGS += $(LIBPTHREAD) endif endif ifeq ($(CC_VENDOR),icc) ifeq ($(THREADING_MODEL),auto) THREADING_MODEL := openmp endif ifeq ($(THREADING_MODEL),openmp) CTHREADFLAGS := -fopenmp LDFLAGS += -fopenmp endif ifeq ($(THREADING_MODEL),pthreads) CTHREADFLAGS := -pthread LDFLAGS += $(LIBPTHREAD) endif endif ifeq ($(CC_VENDOR),clang) ifeq ($(THREADING_MODEL),auto) THREADING_MODEL := pthreads endif ifeq ($(THREADING_MODEL),openmp) CTHREADFLAGS := -fopenmp LDFLAGS += -fopenmp endif ifeq ($(THREADING_MODEL),pthreads) CTHREADFLAGS := -pthread LDFLAGS += $(LIBPTHREAD) endif endif # --- #pragma omp simd flags (used for reference kernels only) --- ifeq ($(PRAGMA_OMP_SIMD),yes) ifeq ($(CC_VENDOR),gcc) COMPSIMDFLAGS := -fopenmp-simd else ifeq ($(CC_VENDOR),clang) COMPSIMDFLAGS := -fopenmp-simd else ifeq ($(CC_VENDOR),icc) COMPSIMDFLAGS := -qopenmp-simd endif endif endif else # ifeq ($(PRAGMA_OMP_SIMD),no) COMPSIMDFLAGS := endif # # --- Adjust verbosity level manually using make V=[0,1] ----------------------- # ifeq ($(V),1) ENABLE_VERBOSE := yes BLIS_ENABLE_TEST_OUTPUT := yes endif ifeq ($(V),0) ENABLE_VERBOSE := no BLIS_ENABLE_TEST_OUTPUT := no endif # # --- Append OS-specific libraries to LDFLAGS ---------------------------------- # ifeq ($(OS_NAME),Linux) LDFLAGS += -lrt endif # # --- LDFLAGS cleanup ---------------------------------------------------------- # # # --- Include makefile fragments ----------------------------------------------- # # Initialize our list of directory paths to makefile fragments with the empty # list. This variable will accumulate all of the directory paths in which # makefile fragments reside. FRAGMENT_DIR_PATHS := # Initialize our makefile variables that source code files will be accumulated # into by the makefile fragments. This initialization is very important! These # variables will end up with weird contents if we don't initialize them to # empty prior to recursively including the makefile fragments. MK_CONFIG_SRC := MK_KERNELS_SRC := MK_REFKERN_SRC := MK_FRAME_SRC := MK_ADDON_SRC := MK_SANDBOX_SRC := # -- config -- # Construct paths to each of the sub-configurations specified in the # configuration list. Note that we use CONFIG_LIST_FAM, which already # has CONFIG_NAME included (with duplicates removed). CONFIG_PATHS := $(addprefix $(CONFIG_FRAG_PATH)/, $(CONFIG_LIST_FAM)) # This variable is used by the include statements as they recursively include # one another. For the 'config' directory, we initialize it to that directory # in preparation to include the fragments in the configuration sub-directory. PARENT_SRC_PATH := $(CONFIG_PATH) PARENT_PATH := $(CONFIG_FRAG_PATH) # Recursively include the makefile fragments in each of the sub-configuration # directories. -include $(addsuffix /$(FRAGMENT_MK), $(CONFIG_PATHS)) # -- kernels -- # Construct paths to each of the kernel sets required by the sub-configurations # in the configuration list. KERNEL_PATHS := $(addprefix $(KERNELS_FRAG_PATH)/, $(KERNEL_LIST)) # This variable is used by the include statements as they recursively include # one another. For the 'kernels' directory, we initialize it to that directory # in preparation to include the fragments in the configuration sub-directory. PARENT_SRC_PATH := $(KERNELS_PATH) PARENT_PATH := $(KERNELS_FRAG_PATH) # Recursively include the makefile fragments in each of the kernels sub- # directories. -include $(addsuffix /$(FRAGMENT_MK), $(KERNEL_PATHS)) # -- ref_kernels -- # -- frame -- # This variable is used by the include statements as they recursively include # one another. For the framework and reference kernel source trees (ie: the # 'frame' and 'ref_kernels' directories), we initialize it to the top-level # directory since that is its parent. PARENT_SRC_PATH := $(DIST_PATH) PARENT_PATH := $(OBJ_DIR)/$(CONFIG_NAME) # Recursively include all the makefile fragments in the directories for the # reference kernels and portable framework. -include $(addsuffix /$(FRAGMENT_MK), $(REFKERN_FRAG_PATH)) -include $(addsuffix /$(FRAGMENT_MK), $(FRAME_FRAG_PATH)) # -- addon -- # Construct paths to each addon. # NOTE: If $(ADDON_LIST) is empty (because no addon was enabled at configure- # time) then $(ADDON_PATHS) will also be empty, which will cause no fragments # to be included. ADDON_PATHS := $(addprefix $(ADDON_FRAG_PATH)/, $(ADDON_LIST)) # This variable is used by the include statements as they recursively include # one another. For the 'addons' directory, we initialize it to that directory # in preparation to include the fragments in the configuration sub-directory. PARENT_SRC_PATH := $(ADDON_PATH) PARENT_PATH := $(ADDON_FRAG_PATH) # Recursively include the makefile fragments in each of the addons sub- # directories. -include $(addsuffix /$(FRAGMENT_MK), $(ADDON_PATHS)) # -- sandbox -- # Construct paths to each sandbox. (At present, there can be only one.) # NOTE: If $(SANDBOX) is empty (because no sandbox was enabled at configure- # time) then $(SANDBOX_PATHS) will also be empty, which will cause no # fragments to be included. SANDBOX_PATHS := $(addprefix $(SANDBOX_FRAG_PATH)/, $(SANDBOX)) # This variable is used by the include statements as they recursively include # one another. For the 'sandbox' directory, we initialize it to that directory # in preparation to include the fragments in the configuration sub-directory. PARENT_SRC_PATH := $(SANDBOX_PATH) PARENT_PATH := $(SANDBOX_FRAG_PATH) # Recursively include the makefile fragments in the sandbox sub-directory. -include $(addsuffix /$(FRAGMENT_MK), $(SANDBOX_PATHS)) # -- post-processing -- # Create a list of the makefile fragments using the variable into which each # of the above include statements accumulated their directory paths. MAKEFILE_FRAGMENTS := $(addsuffix /$(FRAGMENT_MK), $(FRAGMENT_DIR_PATHS)) # Detect whether we actually got any makefile fragments. If we didn't, then it # is likely that the user has not yet generated them (via configure). ifeq ($(strip $(MAKEFILE_FRAGMENTS)),) MAKEFILE_FRAGMENTS_PRESENT := no else MAKEFILE_FRAGMENTS_PRESENT := yes endif # # --- Important sets of header files and paths --------------------------------- # # Define a function that will expand all of the directory paths given in $(1) # to actual filepaths using the list of suffixes provided in $(2). get-filepaths = $(strip $(foreach path, $(1), \ $(foreach suf, $(2), \ $(wildcard $(path)/*.$(suf)) \ ) ) ) # Define a function that will expand all of the directory paths given in $(1) # to actual filepaths using the list of suffixes provided in $(2), taking only # the first expansion from each directory with at least one file matching # the current suffix. Finally, strip the filenames from all resulting files, # returning only the directory paths. get-dirpaths = $(dir $(foreach path, $(1), \ $(firstword \ $(foreach suf, $(2), \ $(wildcard $(path)/*.$(suf)) \ ) ) ) ) # We'll use three directory lists. The first is a list of all of the directories # in which makefile fragments were generated, plus the current directory. (The # current directory is needed so we include bli_config.h and bli_addon.h in the # processing of header files.) The second and third are subsets of the first # that begins with the addon and sandbox root paths, respectively. ALLFRAG_DIR_PATHS := . $(FRAGMENT_DIR_PATHS) ADDON_DIR_PATHS := $(filter $(ADDON_PATH)/%,$(ALLFRAG_DIR_PATHS)) SANDBOX_DIR_PATHS := $(filter $(SANDBOX_PATH)/%,$(ALLFRAG_DIR_PATHS)) ALL_H99_FILES := $(call get-filepaths,$(ALLFRAG_DIR_PATHS),$(ALL_H99_SUFS)) FRAME_H99_FILES := $(filter-out $(ADDON_PATH)/%, \ $(filter-out $(SANDBOX_PATH)/%, \ $(ALL_H99_FILES) \ ) ) ALL_H99_DIRPATHS := $(call get-dirpaths,$(ALLFRAG_DIR_PATHS),$(ALL_H99_SUFS)) ADDON_H99_FILES := $(call get-filepaths,$(ADDON_DIR_PATHS),$(ADDON_H99_SUFS)) ADDON_HXX_FILES := $(call get-filepaths,$(ADDON_DIR_PATHS),$(ADDON_HXX_SUFS)) ADDON_HDR_DIRPATHS := $(call get-dirpaths,$(ADDON_DIR_PATHS),$(ALL_HDR_SUFS)) SANDBOX_H99_FILES := $(call get-filepaths,$(SANDBOX_DIR_PATHS),$(SANDBOX_H99_SUFS)) SANDBOX_HXX_FILES := $(call get-filepaths,$(SANDBOX_DIR_PATHS),$(SANDBOX_HXX_SUFS)) SANDBOX_HDR_DIRPATHS := $(call get-dirpaths,$(SANDBOX_DIR_PATHS),$(ALL_HDR_SUFS)) # # --- blis.h header definitions ------------------------------------------------ # # Use include/CONFIG_NAME as the default path to the local header files, but # allow the includer to override this value if it needs to point to an # installation directory. ifeq ($(strip $(INC_PATH)),) INC_PATH := $(INCLUDE_DIR)/$(CONFIG_NAME) endif # Identify the base path for the intermediate include directory. We define # this path in terms of INC_PATH, which gets a default value above (which is # what happens for the top-level Makefile). If INC_PATH is specified by the # Makefile prior to including common.mk, that path is used instead. This # allows Makefiles for example code and test drivers to reference an installed # prefix directory for situations when the build directory no longer exists. BASE_INC_PATH := $(INC_PATH) # Isolate the path to blis.h by filtering the file from the list of framework # header files. BLIS_H := blis.h BLIS_H_SRC_PATH := $(filter %/$(BLIS_H), $(FRAME_H99_FILES)) # Construct the path to what will be the intermediate flattened/monolithic # blis.h file. BLIS_H_FLAT := $(BASE_INC_PATH)/$(BLIS_H) # # --- cblas.h header definitions ----------------------------------------------- # # Isolate the path to cblas.h by filtering the file from the list of framework # header files, and then strip the filename to obtain the directory in which # cblas.h resides. CBLAS_H := cblas.h CBLAS_H_SRC_PATH := $(filter %/$(CBLAS_H), $(FRAME_H99_FILES)) CBLAS_H_DIRPATH := $(dir $(CBLAS_H_SRC_PATH)) # Construct the path to what will be the intermediate flattened/monolithic # cblas.h file. CBLAS_H_FLAT := $(BASE_INC_PATH)/$(CBLAS_H) # # --- Compiler include path definitions ---------------------------------------- # # Obtain a list of header files #included inside of the bli_cntx_ref.c file. # Due to the way that bli_cntx_ref.c uses headers and macros, paths to these # files will be needed when compiling bli_cntx_ref.c with the monolithic header. ifeq ($(strip $(SHARE_PATH)),.) REF_KER_SRC := $(DIST_PATH)/$(REFKERN_DIR)/bli_cntx_ref.c REF_KER_HEADERS := $(shell $(GREP) "\#include" $(REF_KER_SRC) | sed -e "s/\#include [\"<]\([a-zA-Z0-9\_\.\/\-]*\)[\">].*/\1/g" | $(GREP) -v $(BLIS_H)) endif # Match each header found above with the path to that header, and then strip # leading, trailing, and internal whitespace. REF_KER_H_PATHS := $(call rm-dups,$(strip \ $(foreach header, $(REF_KER_HEADERS), \ $(dir $(filter %/$(header), \ $(FRAME_H99_FILES)))))) # Add -I to each header path so we can specify our include search paths to the # C compiler. Then add frame/include since it's needed when compiling source # files that #include bli_oapi_ba.h or bli_oapi_ex.h. REF_KER_I_PATHS := $(strip $(patsubst %, -I%, $(REF_KER_H_PATHS))) REF_KER_I_PATHS += -I$(DIST_PATH)/frame/include # Prefix the paths above with the base include path. # NOTE: We no longer need every header path in the source tree since we # now #include the monolithic/flattened blis.h instead. CINCFLAGS := -I$(BASE_INC_PATH) $(REF_KER_I_PATHS) # If CBLAS is enabled, we also include the path to the cblas.h directory so # that the compiler will be able to find cblas.h as the CBLAS source code is # being compiled. ifeq ($(MK_ENABLE_CBLAS),yes) CINCFLAGS += -I$(CBLAS_H_DIRPATH) endif # Obtain a list of header paths in the configured addons. Then add -I to each # header path. CADDONINCFLAGS := $(strip $(patsubst %, -I%, $(ADDON_HDR_DIRPATHS))) # Obtain a list of header paths in the configured sandbox. Then add -I to each # header path. CSANDINCFLAGS := $(strip $(patsubst %, -I%, $(SANDBOX_HDR_DIRPATHS))) # # --- BLIS configuration header definitions ------------------------------------ # # These files were created by configure, but we need to define them here so we # can remove them as part of the clean targets. BLIS_ADDON_H := ./bli_addon.h BLIS_CONFIG_H := ./bli_config.h # # --- Special preprocessor macro definitions ----------------------------------- # # Define a C preprocessor macro to communicate the current version so that it # can be embedded into the library and queried later. VERS_DEF := -DBLIS_VERSION_STRING=\"$(VERSION)\" # Define a C preprocessor flag that is *only* defined when BLIS is being # compiled. (In other words, an application that #includes blis.h will not # get this cpp macro.) BUILD_CPPFLAGS := -DBLIS_IS_BUILDING_LIBRARY # end of ifndef COMMON_MK_INCLUDED conditional block endif blis-0.9.0/config/000077500000000000000000000000001422157504600137245ustar00rootroot00000000000000blis-0.9.0/config/README.md000066400000000000000000000014671422157504600152130ustar00rootroot00000000000000 For more information on sub-configurations and configuration families in BLIS, please read the Configuration Guide, which can be viewed in markdown-rendered form [from the BLIS wiki page](https://github.com/flame/blis/wiki/). If you don't have time, or are impatient, take a look at the `config_registry` file in the top-level directory of the BLIS distribution. It contains a grammar-like mapping of configuration names, or families, to sub-configurations, which may be other families. Keep in mind that the `/` notation: ``` : / ``` means that the kernel set associated with `` should be made available to the configuration `` if `` is targeted at configure-time. (Some configurations borrow kernels from other configurations, and this is how we specify that requirement.) blis-0.9.0/config/a64fx/000077500000000000000000000000001422157504600146545ustar00rootroot00000000000000blis-0.9.0/config/a64fx/bli_a64fx_sector_cache.h000066400000000000000000000104571422157504600213140ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2019, Forschunszentrum Juelich 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // A64FX: set up cache sizes // // Reference: A64FX (TM) specification Fujitsu HPC Extension // Link: https://github.com/fujitsu/A64FX/blob/master/doc/A64FX_Specification_HPC_Extension_v1_EN.pdf // // 63:15 | 14:12 | 11 | 10:08 | 07 | 06:04 | 03 | 02:00 | // RES0 | l1_sec3_max | RES0 | l1_sec2_max | RES0 | l1_sec1_max | RES0 | l1_sec0_max | // // the bits set number of maximum sectors from 0-7 // 000 - 0 // 001 - 1 // 010 - 2 // 011 - 3 // 100 - 4 // 101 - 5 // 110 - 6 // 111 - 7 // // For L1 we want to maximize the number of sectors for B // Configuration 1: 1 sector for C (sector 3) // 1 sector for A (sector 1) // 6 sectors for B (sector 2) // 0 sectors for the rest (sector 0) // // 16b bitfield conf. 1: 0b0 001 0 110 0 001 0 000 // // Configuration 2: 1 sector for C (sector 3) // 1 sector for A (sector 1) // 5 sectors for B (sector 2) // 1 sectors for the rest (sector 0) // // 16b bitfield conf. 2: 0b0 001 0 101 0 001 0 001 // // accessing the control register: // // MRS , S3_3_C11_C8_2 // MSR S3_3_C11_C8_2, // // TODO: First tests showed no change in performance, a deeper investigation // is necessary #define A64FX_SETUP_SECTOR_CACHE_SIZES(config_bitfield)\ {\ uint64_t sector_cache_config = config_bitfield;\ __asm__ volatile(\ "msr s3_3_c11_c8_2,%[sector_cache_config]"\ :\ : [sector_cache_config] "r" (sector_cache_config)\ :\ );\ } #define A64FX_SETUP_SECTOR_CACHE_SIZES_L2(config_bitfield)\ {\ uint64_t sector_cache_config = config_bitfield;\ __asm__ volatile(\ "msr s3_3_c15_c8_2,%[sector_cache_config]"\ :\ : [sector_cache_config] "r" (sector_cache_config)\ :\ );\ } #define A64FX_SET_CACHE_SECTOR(areg, tag, sparereg)\ " mov "#sparereg", "#tag" \n\t"\ " lsl "#sparereg", "#sparereg", 56 \n\t"\ " orr "#areg", "#areg", "#sparereg" \n\t" #define A64FX_READ_SECTOR_CACHE_SIZES(output_uint64)\ __asm__ volatile(\ "mrs %["#output_uint64"],s3_3_c11_c8_2"\ : [output_uint64] "=r" (output_uint64)\ : \ :\ ); #define A64FX_SCC(sec0,sec1,sec2,sec3)\ (uint64_t)((sec0 & 0x7LU) | ((sec1 & 0x7LU) << 4) | ((sec2 & 0x7LU) << 8) | ((sec3 & 0x7LU) << 12)) #define A64FX_SCC_L2(sec02,sec13)\ (uint64_t)((sec02 & 0x1FLU) | ((sec13 & 0x1FLU) << 8)) blis-0.9.0/config/a64fx/bli_cntx_init_a64fx.c000066400000000000000000000132541422157504600206620ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "bli_a64fx_sector_cache.h" void bli_cntx_init_a64fx( cntx_t* cntx ) { blksz_t blkszs[ BLIS_NUM_BLKSZS ]; blksz_t thresh[ BLIS_NUM_THRESH ]; // Set default kernel blocksizes and functions. bli_cntx_init_a64fx_ref( cntx ); // ------------------------------------------------------------------------- // Update the context with optimized native gemm micro-kernels and // their storage preferences. bli_cntx_set_l3_nat_ukrs ( 4, BLIS_GEMM_UKR, BLIS_FLOAT, bli_sgemm_armsve_asm_2vx10_unindexed, FALSE, BLIS_GEMM_UKR, BLIS_DOUBLE, bli_dgemm_armsve_asm_2vx10_unindexed, FALSE, BLIS_GEMM_UKR, BLIS_SCOMPLEX, bli_cgemm_armsve_asm_2vx10_unindexed, FALSE, BLIS_GEMM_UKR, BLIS_DCOMPLEX, bli_zgemm_armsve_asm_2vx10_unindexed, FALSE, cntx ); // Set SVE-512 packing routine. bli_cntx_set_packm_kers ( 2, BLIS_PACKM_10XK_KER, BLIS_DOUBLE, bli_dpackm_armsve512_asm_10xk, // 12xk is not used and disabled for GCC 8-9 compatibility. // BLIS_PACKM_12XK_KER, BLIS_DOUBLE, bli_dpackm_armsve512_int_12xk, BLIS_PACKM_16XK_KER, BLIS_DOUBLE, bli_dpackm_armsve512_asm_16xk, cntx ); // Initialize level-3 blocksize objects with architecture-specific values. // s d c z bli_blksz_init_easy( &blkszs[ BLIS_MR ], 32, 16, 16, 8 ); bli_blksz_init_easy( &blkszs[ BLIS_NR ], 10, 10, 10, 10 ); bli_blksz_init_easy( &blkszs[ BLIS_MC ], 256, 128, 192, 96 ); bli_blksz_init_easy( &blkszs[ BLIS_KC ], 2048, 2048, 1536, 1536 ); bli_blksz_init_easy( &blkszs[ BLIS_NC ], 23040, 26880, 11520, 11760 ); // Update the context with the current architecture's register and cache // blocksizes (and multiples) for native execution. bli_cntx_set_blkszs ( BLIS_NAT, 5, BLIS_NC, &blkszs[ BLIS_NC ], BLIS_NR, BLIS_KC, &blkszs[ BLIS_KC ], BLIS_KR, BLIS_MC, &blkszs[ BLIS_MC ], BLIS_MR, BLIS_NR, &blkszs[ BLIS_NR ], BLIS_NR, BLIS_MR, &blkszs[ BLIS_MR ], BLIS_MR, cntx ); #if 0 // Initialize sup thresholds with architecture-appropriate values. // s d c z bli_blksz_init_easy( &thresh[ BLIS_MT ], -1, 65, -1, -1 ); bli_blksz_init_easy( &thresh[ BLIS_NT ], -1, 65, -1, -1 ); bli_blksz_init_easy( &thresh[ BLIS_KT ], -1, 65, -1, -1 ); // Initialize the context with the sup thresholds. bli_cntx_set_l3_sup_thresh ( 3, BLIS_MT, &thresh[ BLIS_MT ], BLIS_NT, &thresh[ BLIS_NT ], BLIS_KT, &thresh[ BLIS_KT ], cntx ); // Update the context with optimized small/unpacked gemm kernels. bli_cntx_set_l3_sup_kers ( 4, BLIS_RRR, BLIS_DOUBLE, bli_dgemmsup_rv_armsve_10x2v_unindexed, TRUE, BLIS_RCR, BLIS_DOUBLE, bli_dgemmsup_rv_armsve_10x2v_unindexed, TRUE, BLIS_CCR, BLIS_DOUBLE, bli_dgemmsup_rv_armsve_10x2v_unindexed, TRUE, BLIS_CCC, BLIS_DOUBLE, bli_dgemmsup_rv_armsve_10x2v_unindexed, TRUE, cntx ); // Initialize level-3 sup blocksize objects with architecture-specific // values. // s d c z bli_blksz_init_easy( &blkszs[ BLIS_MR ], -1, 10, -1, -1 ); bli_blksz_init_easy( &blkszs[ BLIS_NR ], -1, 16, -1, -1 ); bli_blksz_init_easy( &blkszs[ BLIS_MC ], -1, 120, -1, -1 ); bli_blksz_init_easy( &blkszs[ BLIS_KC ], -1, 256, -1, -1 ); bli_blksz_init_easy( &blkszs[ BLIS_NC ], -1, 4080, -1, -1 ); // Update the context with the current architecture's register and cache // blocksizes for small/unpacked level-3 problems. bli_cntx_set_l3_sup_blkszs ( 5, BLIS_NC, &blkszs[ BLIS_NC ], BLIS_KC, &blkszs[ BLIS_KC ], BLIS_MC, &blkszs[ BLIS_MC ], BLIS_NR, &blkszs[ BLIS_NR ], BLIS_MR, &blkszs[ BLIS_MR ], cntx ); #endif // Set A64FX cache sector sizes for each PE/CMG // SC Fugaku might disable users' setting cache sizes. #if !defined(CACHE_SECTOR_SIZE_READONLY) #pragma omp parallel { A64FX_SETUP_SECTOR_CACHE_SIZES(A64FX_SCC(0,1,3,0)) A64FX_SETUP_SECTOR_CACHE_SIZES_L2(A64FX_SCC_L2(9,28)) } #endif } blis-0.9.0/config/a64fx/bli_family_a64fx.h000066400000000000000000000042031422157504600201430ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ //#ifndef BLIS_FAMILY_H //#define BLIS_FAMILY_H // -- MEMORY ALLOCATION -------------------------------------------------------- #define BLIS_SIMD_ALIGN_SIZE 256 #define BLIS_SIMD_MAX_NUM_REGISTERS 32 // SVE-specific configs. #define N_L1_SVE_DEFAULT 64 #define W_L1_SVE_DEFAULT 4 #define C_L1_SVE_DEFAULT 256 #define N_L2_SVE_DEFAULT 2048 #define W_L2_SVE_DEFAULT 16 #define C_L2_SVE_DEFAULT 256 #define N_L3_SVE_DEFAULT 8192 #define W_L3_SVE_DEFAULT 16 #define C_L3_SVE_DEFAULT 256 //#endif blis-0.9.0/config/a64fx/make_defs.mk000066400000000000000000000055521422157504600171320ustar00rootroot00000000000000# # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2014, The University of Texas at Austin # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # # Declare the name of the current configuration and add it to the # running list of configurations included by common.mk. THIS_CONFIG := a64fx #CONFIGS_INCL += $(THIS_CONFIG) # # --- Determine the C compiler and related flags --- # # NOTE: The build system will append these variables with various # general-purpose/configuration-agnostic flags in common.mk. You # may specify additional flags here as needed. CPPROCFLAGS := -D_GNU_SOURCE -D_A64FX CMISCFLAGS := CPICFLAGS := CWARNFLAGS := ifneq ($(DEBUG_TYPE),off) CDBGFLAGS := -g endif ifeq ($(DEBUG_TYPE),noopt) COPTFLAGS := -O0 else COPTFLAGS := -O3 -ftree-vectorize -march=armv8-a+sve endif # Flags specific to optimized kernels. CKOPTFLAGS := $(COPTFLAGS) CKVECFLAGS := # Flags specific to reference kernels. CROPTFLAGS := $(CKOPTFLAGS) ifeq ($(CC_VENDOR),gcc) CRVECFLAGS := $(CKVECFLAGS) -funsafe-math-optimizations -ffp-contract=fast else ifeq ($(CC_VENDOR),clang) CRVECFLAGS := $(CKVECFLAGS) -funsafe-math-optimizations -ffp-contract=fast else CRVECFLAGS := $(CKVECFLAGS) endif endif # Store all of the variables here to new variables containing the # configuration name. $(eval $(call store-make-defs,$(THIS_CONFIG))) blis-0.9.0/config/amd64/000077500000000000000000000000001422157504600146375ustar00rootroot00000000000000blis-0.9.0/config/amd64/bli_family_amd64.h000066400000000000000000000033321422157504600201130ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_FAMILY_AMD64_H #define BLIS_FAMILY_AMD64_H #endif blis-0.9.0/config/amd64/make_defs.mk000066400000000000000000000050271422157504600171120ustar00rootroot00000000000000# # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # # Declare the name of the current configuration and add it to the # running list of configurations included by common.mk. THIS_CONFIG := amd64 #CONFIGS_INCL += $(THIS_CONFIG) # # --- Determine the C compiler and related flags --- # # NOTE: The build system will append these variables with various # general-purpose/configuration-agnostic flags in common.mk. You # may specify additional flags here as needed. CPPROCFLAGS := CMISCFLAGS := CPICFLAGS := CWARNFLAGS := ifneq ($(DEBUG_TYPE),off) CDBGFLAGS := -g endif ifeq ($(DEBUG_TYPE),noopt) COPTFLAGS := -O0 else COPTFLAGS := -O2 endif # Setting for reference and optimized kernels are taken from individual # subconfiguration makefile fragments in this family. # Store all of the variables here to new variables containing the # configuration name. $(eval $(call store-make-defs,$(THIS_CONFIG))) blis-0.9.0/config/amd64_legacy/000077500000000000000000000000001422157504600161635ustar00rootroot00000000000000blis-0.9.0/config/amd64_legacy/bli_family_amd64_legacy.h000066400000000000000000000035131422157504600227640ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_FAMILY_AMD64_LEGACY_H #define BLIS_FAMILY_AMD64_LEGACY_H // Placeholder for bundle configuration. #endif blis-0.9.0/config/amd64_legacy/make_defs.mk000066400000000000000000000051331422157504600204340ustar00rootroot00000000000000# # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2014, The University of Texas at Austin # Copyright (C) 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # # Declare the name of the current configuration and add it to the # running list of configurations included by common.mk. THIS_CONFIG := amd64_legacy #CONFIGS_INCL += $(THIS_CONFIG) # # --- Determine the C compiler and related flags --- # # NOTE: The build system will append these variables with various # general-purpose/configuration-agnostic flags in common.mk. You # may specify additional flags here as needed. CPPROCFLAGS := CMISCFLAGS := CPICFLAGS := CWARNFLAGS := ifneq ($(DEBUG_TYPE),off) CDBGFLAGS := -g endif ifeq ($(DEBUG_TYPE),noopt) COPTFLAGS := -O0 else COPTFLAGS := -O2 endif # Setting for reference and optimized kernels are taken from individual # subconfiguration makefile fragments in this family. # Store all of the variables here to new variables containing the # configuration name. $(eval $(call store-make-defs,$(THIS_CONFIG))) blis-0.9.0/config/arm32/000077500000000000000000000000001422157504600146505ustar00rootroot00000000000000blis-0.9.0/config/arm32/bli_family_arm32.h000066400000000000000000000034721422157504600201420ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ //#ifndef BLIS_FAMILY_H //#define BLIS_FAMILY_H // -- MEMORY ALLOCATION -------------------------------------------------------- #define BLIS_SIMD_ALIGN_SIZE 16 //#endif blis-0.9.0/config/arm32/make_defs.mk000066400000000000000000000056661422157504600171340ustar00rootroot00000000000000# # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2014, The University of Texas at Austin # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # # Declare the name of the current configuration and add it to the # running list of configurations included by common.mk. THIS_CONFIG := arm32 #CONFIGS_INCL += $(THIS_CONFIG) # # --- Determine the C compiler and related flags --- # # NOTE: The build system will append these variables with various # general-purpose/configuration-agnostic flags in common.mk. You # may specify additional flags here as needed. CPPROCFLAGS := CMISCFLAGS := -mfloat-abi=hard -mfpu=neon CPICFLAGS := CWARNFLAGS := ifneq ($(DEBUG_TYPE),off) CDBGFLAGS := -g endif ifeq ($(DEBUG_TYPE),noopt) COPTFLAGS := -O0 else COPTFLAGS := -O2 endif # Flags specific to optimized kernels. CKOPTFLAGS := $(COPTFLAGS) -O3 ifeq ($(CC_VENDOR),gcc) CKVECFLAGS := -march=armv7-a else $(error gcc is required for this configuration.) endif # Flags specific to reference kernels. CROPTFLAGS := $(CKOPTFLAGS) ifeq ($(CC_VENDOR),gcc) CRVECFLAGS := $(CKVECFLAGS) -funsafe-math-optimizations -ffp-contract=fast else ifeq ($(CC_VENDOR),clang) CRVECFLAGS := $(CKVECFLAGS) -funsafe-math-optimizations -ffp-contract=fast else CRVECFLAGS := $(CKVECFLAGS) endif endif # Store all of the variables here to new variables containing the # configuration name. $(eval $(call store-make-defs,$(THIS_CONFIG))) blis-0.9.0/config/arm64/000077500000000000000000000000001422157504600146555ustar00rootroot00000000000000blis-0.9.0/config/arm64/bli_family_arm64.h000066400000000000000000000041741422157504600201540ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ //#ifndef BLIS_FAMILY_H //#define BLIS_FAMILY_H // -- MEMORY ALLOCATION -------------------------------------------------------- #define BLIS_SIMD_ALIGN_SIZE 16 #define BLIS_SIMD_MAX_NUM_REGISTERS 32 // SVE-specific configs. #define N_L1_SVE_DEFAULT 64 #define W_L1_SVE_DEFAULT 4 #define C_L1_SVE_DEFAULT 256 #define N_L2_SVE_DEFAULT 2048 #define W_L2_SVE_DEFAULT 16 #define C_L2_SVE_DEFAULT 256 #define N_L3_SVE_DEFAULT 8192 #define W_L3_SVE_DEFAULT 16 #define C_L3_SVE_DEFAULT 256 //#endif blis-0.9.0/config/arm64/make_defs.mk000066400000000000000000000057671422157504600171430ustar00rootroot00000000000000# # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2014, The University of Texas at Austin # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # # Declare the name of the current configuration and add it to the # running list of configurations included by common.mk. THIS_CONFIG := arm64 #CONFIGS_INCL += $(THIS_CONFIG) # # --- Determine the C compiler and related flags --- # # NOTE: The build system will append these variables with various # general-purpose/configuration-agnostic flags in common.mk. You # may specify additional flags here as needed. CPPROCFLAGS := -D_GNU_SOURCE CMISCFLAGS := CPICFLAGS := CWARNFLAGS := ifneq ($(DEBUG_TYPE),off) CDBGFLAGS := -g endif ifeq ($(DEBUG_TYPE),noopt) COPTFLAGS := -O0 else COPTFLAGS := -O2 endif # Flags specific to optimized kernels. CKOPTFLAGS := $(COPTFLAGS) -O3 ifeq ($(CC_VENDOR),gcc) CKVECFLAGS := -march=armv8-a else ifeq ($(CC_VENDOR),clang) CKVECFLAGS := -march=armv8-a else $(error gcc or clang is required for this configuration.) endif endif # Flags specific to reference kernels. CROPTFLAGS := $(CKOPTFLAGS) ifeq ($(CC_VENDOR),gcc) CRVECFLAGS := $(CKVECFLAGS) -funsafe-math-optimizations -ffp-contract=fast else ifeq ($(CC_VENDOR),clang) CRVECFLAGS := $(CKVECFLAGS) -funsafe-math-optimizations -ffp-contract=fast else CRVECFLAGS := $(CKVECFLAGS) endif endif # Store all of the variables here to new variables containing the # configuration name. $(eval $(call store-make-defs,$(THIS_CONFIG))) blis-0.9.0/config/armsve/000077500000000000000000000000001422157504600152215ustar00rootroot00000000000000blis-0.9.0/config/armsve/bli_cntx_init_armsve.c000066400000000000000000000140361422157504600215730ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include #ifndef HWCAP_SVE #define HWCAP_SVE (1 << 22) #endif void bli_cntx_init_armsve( cntx_t* cntx ) { if (!(getauxval( AT_HWCAP ) & HWCAP_SVE)) return; blksz_t blkszs[ BLIS_NUM_BLKSZS ]; #if 0 blksz_t thresh[ BLIS_NUM_THRESH ]; #endif // Set default kernel blocksizes and functions. bli_cntx_init_armsve_ref( cntx ); // ------------------------------------------------------------------------- // Block size. dim_t m_r_s, n_r_s, k_c_s, m_c_s, n_c_s; dim_t m_r_d, n_r_d, k_c_d, m_c_d, n_c_d; dim_t m_r_c, n_r_c, k_c_c, m_c_c, n_c_c; dim_t m_r_z, n_r_z, k_c_z, m_c_z, n_c_z; bli_s_blksz_armsve(&m_r_s, &n_r_s, &k_c_s, &m_c_s, &n_c_s); bli_d_blksz_armsve(&m_r_d, &n_r_d, &k_c_d, &m_c_d, &n_c_d); bli_c_blksz_armsve(&m_r_c, &n_r_c, &k_c_c, &m_c_c, &n_c_c); bli_z_blksz_armsve(&m_r_z, &n_r_z, &k_c_z, &m_c_z, &n_c_z); // Update the context with optimized native gemm micro-kernels and // their storage preferences. bli_cntx_set_l3_nat_ukrs ( 4, // These are vector-length agnostic kernels. Yet knowing mr is required at runtime. BLIS_GEMM_UKR, BLIS_FLOAT, bli_sgemm_armsve_asm_2vx10_unindexed, FALSE, BLIS_GEMM_UKR, BLIS_DOUBLE, bli_dgemm_armsve_asm_2vx10_unindexed, FALSE, BLIS_GEMM_UKR, BLIS_SCOMPLEX, bli_cgemm_armsve_asm_2vx10_unindexed, FALSE, BLIS_GEMM_UKR, BLIS_DCOMPLEX, bli_zgemm_armsve_asm_2vx10_unindexed, FALSE, cntx ); // Set VL-specific packing routines if applicable. if (m_r_d==16) bli_cntx_set_packm_kers ( 2, BLIS_PACKM_10XK_KER, BLIS_DOUBLE, bli_dpackm_armsve512_asm_10xk, BLIS_PACKM_16XK_KER, BLIS_DOUBLE, bli_dpackm_armsve512_asm_16xk, cntx ); else if (m_r_d==8) bli_cntx_set_packm_kers ( 1, BLIS_PACKM_8XK_KER, BLIS_DOUBLE, bli_dpackm_armsve256_int_8xk, cntx ); // Initialize level-3 blocksize objects with architecture-specific values. // s d c z bli_blksz_init_easy( &blkszs[ BLIS_MR ], m_r_s, m_r_d, m_r_c, m_r_z ); bli_blksz_init_easy( &blkszs[ BLIS_NR ], n_r_s, n_r_d, n_r_c, n_r_z ); bli_blksz_init_easy( &blkszs[ BLIS_MC ], m_c_s, m_c_d, m_c_c, m_c_z ); bli_blksz_init_easy( &blkszs[ BLIS_KC ], k_c_s, k_c_d, k_c_c, k_c_z ); bli_blksz_init_easy( &blkszs[ BLIS_NC ], n_c_s, n_c_d, n_c_c, n_c_z ); // Update the context with the current architecture's register and cache // blocksizes (and multiples) for native execution. bli_cntx_set_blkszs ( BLIS_NAT, 5, BLIS_NC, &blkszs[ BLIS_NC ], BLIS_NR, BLIS_KC, &blkszs[ BLIS_KC ], BLIS_KR, BLIS_MC, &blkszs[ BLIS_MC ], BLIS_MR, BLIS_NR, &blkszs[ BLIS_NR ], BLIS_NR, BLIS_MR, &blkszs[ BLIS_MR ], BLIS_MR, cntx ); #if 0 // Initialize sup thresholds with architecture-appropriate values. // s d c z bli_blksz_init_easy( &thresh[ BLIS_MT ], -1, 101, -1, -1 ); bli_blksz_init_easy( &thresh[ BLIS_NT ], -1, 101, -1, -1 ); bli_blksz_init_easy( &thresh[ BLIS_KT ], -1, 101, -1, -1 ); // Initialize the context with the sup thresholds. bli_cntx_set_l3_sup_thresh ( 3, BLIS_MT, &thresh[ BLIS_MT ], BLIS_NT, &thresh[ BLIS_NT ], BLIS_KT, &thresh[ BLIS_KT ], cntx ); // Update the context with optimized small/unpacked gemm kernels. bli_cntx_set_l3_sup_kers ( 4, BLIS_RRR, BLIS_DOUBLE, bli_dgemmsup_rv_armsve_10x2v_unindexed, TRUE, BLIS_RCR, BLIS_DOUBLE, bli_dgemmsup_rv_armsve_10x2v_unindexed, TRUE, BLIS_CCR, BLIS_DOUBLE, bli_dgemmsup_rv_armsve_10x2v_unindexed, TRUE, BLIS_CCC, BLIS_DOUBLE, bli_dgemmsup_rv_armsve_10x2v_unindexed, TRUE, cntx ); // Initialize level-3 sup blocksize objects with architecture-specific // values. // s d c z bli_blksz_init_easy( &blkszs[ BLIS_MR ], -1, n_r_d, -1, -1 ); bli_blksz_init_easy( &blkszs[ BLIS_NR ], -1, m_r_d, -1, -1 ); bli_blksz_init_easy( &blkszs[ BLIS_MC ], -1, 120, -1, -1 ); bli_blksz_init_easy( &blkszs[ BLIS_KC ], -1, 256, -1, -1 ); bli_blksz_init_easy( &blkszs[ BLIS_NC ], -1, 2048, -1, -1 ); // Update the context with the current architecture's register and cache // blocksizes for small/unpacked level-3 problems. bli_cntx_set_l3_sup_blkszs ( 5, BLIS_NC, &blkszs[ BLIS_NC ], BLIS_KC, &blkszs[ BLIS_KC ], BLIS_MC, &blkszs[ BLIS_MC ], BLIS_NR, &blkszs[ BLIS_NR ], BLIS_MR, &blkszs[ BLIS_MR ], cntx ); #endif } blis-0.9.0/config/armsve/bli_family_armsve.h000066400000000000000000000042031422157504600210550ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ //#ifndef BLIS_FAMILY_H //#define BLIS_FAMILY_H // -- MEMORY ALLOCATION -------------------------------------------------------- #define BLIS_SIMD_ALIGN_SIZE 256 #define BLIS_SIMD_MAX_NUM_REGISTERS 32 // SVE-specific configs. #define N_L1_SVE_DEFAULT 64 #define W_L1_SVE_DEFAULT 4 #define C_L1_SVE_DEFAULT 256 #define N_L2_SVE_DEFAULT 2048 #define W_L2_SVE_DEFAULT 16 #define C_L2_SVE_DEFAULT 256 #define N_L3_SVE_DEFAULT 8192 #define W_L3_SVE_DEFAULT 16 #define C_L3_SVE_DEFAULT 256 //#endif blis-0.9.0/config/armsve/make_defs.mk000066400000000000000000000055421422157504600174760ustar00rootroot00000000000000# # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2014, The University of Texas at Austin # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # # Declare the name of the current configuration and add it to the # running list of configurations included by common.mk. THIS_CONFIG := armsve #CONFIGS_INCL += $(THIS_CONFIG) # # --- Determine the C compiler and related flags --- # # NOTE: The build system will append these variables with various # general-purpose/configuration-agnostic flags in common.mk. You # may specify additional flags here as needed. CPPROCFLAGS := -D_GNU_SOURCE CMISCFLAGS := CPICFLAGS := CWARNFLAGS := ifneq ($(DEBUG_TYPE),off) CDBGFLAGS := -g endif ifeq ($(DEBUG_TYPE),noopt) COPTFLAGS := -O0 else COPTFLAGS := -O3 -ftree-vectorize -march=armv8-a+sve endif # Flags specific to optimized kernels. CKOPTFLAGS := $(COPTFLAGS) CKVECFLAGS := # Flags specific to reference kernels. CROPTFLAGS := $(CKOPTFLAGS) ifeq ($(CC_VENDOR),gcc) CRVECFLAGS := $(CKVECFLAGS) -funsafe-math-optimizations -ffp-contract=fast else ifeq ($(CC_VENDOR),clang) CRVECFLAGS := $(CKVECFLAGS) -funsafe-math-optimizations -ffp-contract=fast else CRVECFLAGS := $(CKVECFLAGS) endif endif # Store all of the variables here to new variables containing the # configuration name. $(eval $(call store-make-defs,$(THIS_CONFIG))) blis-0.9.0/config/bgq/000077500000000000000000000000001422157504600144755ustar00rootroot00000000000000blis-0.9.0/config/bgq/bli_cntx_init_bgq.c000066400000000000000000000060311422157504600203170ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_cntx_init_bgq( cntx_t* cntx ) { blksz_t blkszs[ BLIS_NUM_BLKSZS ]; // Set default kernel blocksizes and functions. bli_cntx_init_bgq_ref( cntx ); // ------------------------------------------------------------------------- // Update the context with optimized native gemm micro-kernels and // their storage preferences. bli_cntx_set_l3_nat_ukrs ( 2, BLIS_GEMM_UKR, BLIS_DOUBLE, bli_dgemm_bgq_int_8x8, FALSE, BLIS_GEMM_UKR, BLIS_DCOMPLEX, bli_zgemm_bgq_int_4x4, FALSE, cntx ); // Initialize level-3 blocksize objects with architecture-specific values. // s d c z bli_blksz_init_easy( &blkszs[ BLIS_MR ], 0, 8, 0, 4 ); bli_blksz_init_easy( &blkszs[ BLIS_NR ], 0, 8, 0, 4 ); bli_blksz_init_easy( &blkszs[ BLIS_MC ], 0, 1024, 0, 768 ); bli_blksz_init_easy( &blkszs[ BLIS_KC ], 0, 2048, 0, 1536 ); bli_blksz_init_easy( &blkszs[ BLIS_NC ], 0, 10240, 0, 10240 ); // Update the context with the current architecture's register and cache // blocksizes (and multiples) for native execution. bli_cntx_set_blkszs ( BLIS_NAT, 5, BLIS_NC, &blkszs[ BLIS_NC ], BLIS_NR, BLIS_KC, &blkszs[ BLIS_KC ], BLIS_KR, BLIS_MC, &blkszs[ BLIS_MC ], BLIS_MR, BLIS_NR, &blkszs[ BLIS_NR ], BLIS_NR, BLIS_MR, &blkszs[ BLIS_MR ], BLIS_MR, cntx ); } blis-0.9.0/config/bgq/bli_family_bgq.h000066400000000000000000000062131422157504600176100ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ //#ifndef BLIS_FAMILY_H //#define BLIS_FAMILY_H #undef restrict #if 0 // -- LEVEL-3 MICRO-KERNEL CONSTANTS ------------------------------------------- #define BLIS_DEFAULT_MR_S 8 #define BLIS_DEFAULT_NR_S 4 #define BLIS_DEFAULT_MC_S 1024 #define BLIS_DEFAULT_KC_S 2048 #define BLIS_DEFAULT_NC_S 8192 // 1 MPI RANK CASE: #define BLIS_DGEMM_UKERNEL bli_dgemm_int_8x8 #define BLIS_DEFAULT_MR_D 8 #define BLIS_DEFAULT_NR_D 8 #define BLIS_DEFAULT_MC_D 1024 #define BLIS_DEFAULT_KC_D 2048 #define BLIS_DEFAULT_NC_D 10240 #define BLIS_DEFAULT_MR_C 8 #define BLIS_DEFAULT_NR_C 4 #define BLIS_DEFAULT_MC_C 1024 #define BLIS_DEFAULT_KC_C 2048 #define BLIS_DEFAULT_NC_C 8192 #define BLIS_ZGEMM_UKERNEL bli_zgemm_int_8x8 #define BLIS_DEFAULT_MR_Z 4 #define BLIS_DEFAULT_NR_Z 4 #define BLIS_DEFAULT_MC_Z 768 #define BLIS_DEFAULT_KC_Z 1536 #define BLIS_DEFAULT_NC_Z 10240 // -- LEVEL-1F KERNEL CONSTANTS ------------------------------------------------ #define BLIS_DEFAULT_AF_D 8 #define BLIS_DAXPYF_KERNEL bli_daxpyf_opt_var1 // -- LEVEL-1V KERNEL DEFINITIONS ---------------------------------------------- #define BLIS_DAXPYV_KERNEL bli_daxpyv_opt_var1 #define BLIS_DDOTV_KERNEL bli_ddotv_opt_var1 #endif //#endif blis-0.9.0/config/bgq/make_defs.mk000066400000000000000000000071361422157504600167530ustar00rootroot00000000000000# # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2014, The University of Texas at Austin # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # # Declare the name of the current configuration and add it to the # running list of configurations included by common.mk. THIS_CONFIG := bgq #CONFIGS_INCL += $(THIS_CONFIG) # # --- Determine the C compiler and related flags --- # #ifeq ($(CC),) #CC := /bgsys/drivers/ppcfloor/comm/gcc.legacy/bin/mpixlc_r #CC_VENDOR := ibm #endif # NOTE: The build system will append these variables with various # general-purpose/configuration-agnostic flags in common.mk. You # may specify additional flags here as needed. CPPROCFLAGS := -I/bgsys/drivers/ppcfloor -I/bgsys/drivers/ppcfloor/spi/include/kernel/cnk ifeq ($(CC_VENDOR),ibm) CMISCFLAGS := -qthreaded -qsmp=omp -qasm=gcc -qkeyword=asm # -qreport -qsource -qlistopt -qlist else ifeq ($(CC_VENDOR),clang) CMISCFLAGS := -fopenmp else $(error xlc or bgclang is required for this configuration.) endif CPICFLAGS := CWARNFLAGS := -w ifneq ($(DEBUG_TYPE),off) CDBGFLAGS := -g endif ifeq ($(DEBUG_TYPE),noopt) COPTFLAGS := -O0 else COPTFLAGS := -O2 endif # Flags specific to optimized kernels. CKOPTFLAGS := $(COPTFLAGS) -O3 ifeq ($(CC_VENDOR),ibm) CKVECFLAGS := -qarch=qp -qtune=qp -qsimd=auto -qhot=level=1 -qprefetch -qunroll=yes -qnoipa endif # Flags specific to reference kernels. CROPTFLAGS := $(CKOPTFLAGS) ifeq ($(CC_VENDOR),gcc) CRVECFLAGS := $(CKVECFLAGS) -funsafe-math-optimizations -ffp-contract=fast else ifeq ($(CC_VENDOR),clang) CRVECFLAGS := $(CKVECFLAGS) -funsafe-math-optimizations -ffp-contract=fast else CRVECFLAGS := $(CKVECFLAGS) endif endif # Override the default value for LDFLAGS. ifeq ($(CC_VENDOR),ibm) LDFLAGS := -L/bgsys/drivers/ppcfloor/spi/lib -lSPI -lSPI_cnk -qthreaded -qsmp=omp else ifeq ($(CC_VENDOR),clang) LDFLAGS := -L/bgsys/drivers/ppcfloor/spi/lib -lSPI -lSPI_cnk -fopenmp endif # Store all of the variables here to new variables containing the # configuration name. $(eval $(call store-make-defs,$(THIS_CONFIG))) blis-0.9.0/config/bulldozer/000077500000000000000000000000001422157504600157265ustar00rootroot00000000000000blis-0.9.0/config/bulldozer/bli_cntx_init_bulldozer.c000066400000000000000000000063171422157504600230100ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_cntx_init_bulldozer( cntx_t* cntx ) { blksz_t blkszs[ BLIS_NUM_BLKSZS ]; // Set default kernel blocksizes and functions. bli_cntx_init_bulldozer_ref( cntx ); // ------------------------------------------------------------------------- // Update the context with optimized native gemm micro-kernels and // their storage preferences. bli_cntx_set_l3_nat_ukrs ( 4, BLIS_GEMM_UKR, BLIS_FLOAT, bli_sgemm_bulldozer_asm_8x8_fma4, FALSE, BLIS_GEMM_UKR, BLIS_DOUBLE, bli_dgemm_bulldozer_asm_4x6_fma4, FALSE, BLIS_GEMM_UKR, BLIS_SCOMPLEX, bli_cgemm_bulldozer_asm_8x4_fma4, FALSE, BLIS_GEMM_UKR, BLIS_DCOMPLEX, bli_zgemm_bulldozer_asm_4x4_fma4, FALSE, cntx ); // Initialize level-3 blocksize objects with architecture-specific values. // s d c z bli_blksz_init_easy( &blkszs[ BLIS_MR ], 8, 4, 8, 4 ); bli_blksz_init_easy( &blkszs[ BLIS_NR ], 8, 6, 4, 4 ); bli_blksz_init_easy( &blkszs[ BLIS_MC ], 128, 1080, 96, 64 ); bli_blksz_init_easy( &blkszs[ BLIS_KC ], 384, 120, 256, 192 ); bli_blksz_init_easy( &blkszs[ BLIS_NC ], 4096, 8400, 4096, 4096 ); // Update the context with the current architecture's register and cache // blocksizes (and multiples) for native execution. bli_cntx_set_blkszs ( BLIS_NAT, 5, BLIS_NC, &blkszs[ BLIS_NC ], BLIS_NR, BLIS_KC, &blkszs[ BLIS_KC ], BLIS_KR, BLIS_MC, &blkszs[ BLIS_MC ], BLIS_MR, BLIS_NR, &blkszs[ BLIS_NR ], BLIS_NR, BLIS_MR, &blkszs[ BLIS_MR ], BLIS_MR, cntx ); } blis-0.9.0/config/bulldozer/bli_family_bulldozer.h000066400000000000000000000054231422157504600222740ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ //#ifndef BLIS_FAMILY_H //#define BLIS_FAMILY_H #if 0 // -- LEVEL-3 MICRO-KERNEL CONSTANTS ------------------------------------------- #define BLIS_SGEMM_UKERNEL bli_sgemm_asm_8x8_fma4 #define BLIS_DEFAULT_MC_S 128 #define BLIS_DEFAULT_KC_S 384 #define BLIS_DEFAULT_NC_S 4096 #define BLIS_DEFAULT_MR_S 8 #define BLIS_DEFAULT_NR_S 8 #define BLIS_DGEMM_UKERNEL bli_dgemm_asm_4x6_fma4 #define BLIS_DEFAULT_MC_D 1080 #define BLIS_DEFAULT_KC_D 120 #define BLIS_DEFAULT_NC_D 8400 #define BLIS_DEFAULT_MR_D 4 #define BLIS_DEFAULT_NR_D 6 #define BLIS_CGEMM_UKERNEL bli_cgemm_asm_8x4_fma4 #define BLIS_DEFAULT_MC_C 96 #define BLIS_DEFAULT_KC_C 256 #define BLIS_DEFAULT_NC_C 4096 #define BLIS_DEFAULT_MR_C 8 #define BLIS_DEFAULT_NR_C 4 #define BLIS_ZGEMM_UKERNEL bli_zgemm_asm_4x4_fma4 #define BLIS_DEFAULT_MC_Z 64 #define BLIS_DEFAULT_KC_Z 192 #define BLIS_DEFAULT_NC_Z 4096 #define BLIS_DEFAULT_MR_Z 4 #define BLIS_DEFAULT_NR_Z 4 #endif //#endif blis-0.9.0/config/bulldozer/make_defs.mk000066400000000000000000000061261422157504600202020ustar00rootroot00000000000000# # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2014, The University of Texas at Austin # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # # Declare the name of the current configuration and add it to the # running list of configurations included by common.mk. THIS_CONFIG := bulldozer #CONFIGS_INCL += $(THIS_CONFIG) # # --- Determine the C compiler and related flags --- # # NOTE: The build system will append these variables with various # general-purpose/configuration-agnostic flags in common.mk. You # may specify additional flags here as needed. CPPROCFLAGS := CMISCFLAGS := CPICFLAGS := CWARNFLAGS := ifneq ($(DEBUG_TYPE),off) CDBGFLAGS := -g endif ifeq ($(DEBUG_TYPE),noopt) COPTFLAGS := -O0 else COPTFLAGS := -O2 endif # Flags specific to optimized kernels. CKOPTFLAGS := $(COPTFLAGS) -O3 ifeq ($(CC_VENDOR),gcc) CKVECFLAGS := -mfpmath=sse -mavx -mfma4 -march=bdver1 -mno-tbm -mno-xop -mno-lwp else ifeq ($(CC_VENDOR),clang) CKVECFLAGS := -mfpmath=sse -mavx -mfma4 -march=bdver1 -mno-tbm -mno-xop -mno-lwp else $(error gcc or clang are required for this configuration.) endif endif # Flags specific to reference kernels. CROPTFLAGS := $(CKOPTFLAGS) ifeq ($(CC_VENDOR),gcc) CRVECFLAGS := $(CKVECFLAGS) -funsafe-math-optimizations -ffp-contract=fast else ifeq ($(CC_VENDOR),clang) CRVECFLAGS := $(CKVECFLAGS) -funsafe-math-optimizations -ffp-contract=fast else CRVECFLAGS := $(CKVECFLAGS) endif endif # Store all of the variables here to new variables containing the # configuration name. $(eval $(call store-make-defs,$(THIS_CONFIG))) blis-0.9.0/config/cortexa15/000077500000000000000000000000001422157504600155375ustar00rootroot00000000000000blis-0.9.0/config/cortexa15/bli_cntx_init_cortexa15.c000066400000000000000000000066461422157504600224370ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_cntx_init_cortexa15( cntx_t* cntx ) { blksz_t blkszs[ BLIS_NUM_BLKSZS ]; // Set default kernel blocksizes and functions. bli_cntx_init_cortexa15_ref( cntx ); // ------------------------------------------------------------------------- // Update the context with optimized native gemm micro-kernels and // their storage preferences. bli_cntx_set_l3_nat_ukrs ( 2, BLIS_GEMM_UKR, BLIS_FLOAT, bli_sgemm_armv7a_int_4x4, FALSE, BLIS_GEMM_UKR, BLIS_DOUBLE, bli_dgemm_armv7a_int_4x4, FALSE, cntx ); // Initialize level-3 blocksize objects with architecture-specific values. // s d c z #if 1 bli_blksz_init_easy( &blkszs[ BLIS_MR ], 4, 4, -1, -1 ); bli_blksz_init_easy( &blkszs[ BLIS_NR ], 4, 4, -1, -1 ); bli_blksz_init_easy( &blkszs[ BLIS_MC ], 336, 176, -1, -1 ); bli_blksz_init_easy( &blkszs[ BLIS_KC ], 528, 368, -1, -1 ); bli_blksz_init_easy( &blkszs[ BLIS_NC ], 4096, 4096, -1, -1 ); #else bli_blksz_init_easy( &blkszs[ BLIS_MR ], -1, 4, -1, -1 ); bli_blksz_init_easy( &blkszs[ BLIS_NR ], -1, 4, -1, -1 ); bli_blksz_init_easy( &blkszs[ BLIS_MC ], -1, 176, -1, -1 ); bli_blksz_init_easy( &blkszs[ BLIS_KC ], -1, 368, -1, -1 ); bli_blksz_init_easy( &blkszs[ BLIS_NC ], -1, 4096, -1, -1 ); #endif // Update the context with the current architecture's register and cache // blocksizes (and multiples) for native execution. bli_cntx_set_blkszs ( BLIS_NAT, 5, BLIS_NC, &blkszs[ BLIS_NC ], BLIS_NR, BLIS_KC, &blkszs[ BLIS_KC ], BLIS_KR, BLIS_MC, &blkszs[ BLIS_MC ], BLIS_MR, BLIS_NR, &blkszs[ BLIS_NR ], BLIS_NR, BLIS_MR, &blkszs[ BLIS_MR ], BLIS_MR, cntx ); } blis-0.9.0/config/cortexa15/bli_family_cortexa15.h000066400000000000000000000055721422157504600217230ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ //#ifndef BLIS_FAMILY_H //#define BLIS_FAMILY_H // -- MEMORY ALLOCATION -------------------------------------------------------- #define BLIS_SIMD_ALIGN_SIZE 16 #if 0 // -- LEVEL-3 MICRO-KERNEL CONSTANTS ------------------------------------------- #define BLIS_SGEMM_UKERNEL bli_sgemm_armv7a_int_4x4 #define BLIS_DEFAULT_MR_S 4 #define BLIS_DEFAULT_NR_S 4 #define BLIS_DEFAULT_MC_S 336 #define BLIS_DEFAULT_KC_S 528 #define BLIS_DEFAULT_NC_S 4096 #define BLIS_DGEMM_UKERNEL bli_dgemm_armv7a_int_4x4 #define BLIS_DEFAULT_MR_D 4 #define BLIS_DEFAULT_NR_D 4 #define BLIS_DEFAULT_MC_D 176 #define BLIS_DEFAULT_KC_D 368 #define BLIS_DEFAULT_NC_D 4096 #define BLIS_DEFAULT_MR_C 8 #define BLIS_DEFAULT_NR_C 4 #define BLIS_DEFAULT_MC_C 64 #define BLIS_DEFAULT_KC_C 128 #define BLIS_DEFAULT_NC_C 4096 #define BLIS_DEFAULT_MR_Z 8 #define BLIS_DEFAULT_NR_Z 4 #define BLIS_DEFAULT_MC_Z 64 #define BLIS_DEFAULT_KC_Z 128 #define BLIS_DEFAULT_NC_Z 4096 #endif //#endif blis-0.9.0/config/cortexa15/make_defs.mk000066400000000000000000000056741422157504600200220ustar00rootroot00000000000000# # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2014, The University of Texas at Austin # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # # Declare the name of the current configuration and add it to the # running list of configurations included by common.mk. THIS_CONFIG := cortexa15 #CONFIGS_INCL += $(THIS_CONFIG) # # --- Determine the C compiler and related flags --- # # NOTE: The build system will append these variables with various # general-purpose/configuration-agnostic flags in common.mk. You # may specify additional flags here as needed. CPPROCFLAGS := CMISCFLAGS := -mfloat-abi=hard -mfpu=neon CPICFLAGS := CWARNFLAGS := ifneq ($(DEBUG_TYPE),off) CDBGFLAGS := -g endif ifeq ($(DEBUG_TYPE),noopt) COPTFLAGS := -O0 else COPTFLAGS := -O2 endif # Flags specific to optimized kernels. CKOPTFLAGS := $(COPTFLAGS) -O3 ifeq ($(CC_VENDOR),gcc) CKVECFLAGS := -mcpu=cortex-a15 else $(error gcc is required for this configuration.) endif # Flags specific to reference kernels. CROPTFLAGS := $(CKOPTFLAGS) ifeq ($(CC_VENDOR),gcc) CRVECFLAGS := $(CKVECFLAGS) -funsafe-math-optimizations -ffp-contract=fast else ifeq ($(CC_VENDOR),clang) CRVECFLAGS := $(CKVECFLAGS) -funsafe-math-optimizations -ffp-contract=fast else CRVECFLAGS := $(CKVECFLAGS) endif endif # Store all of the variables here to new variables containing the # configuration name. $(eval $(call store-make-defs,$(THIS_CONFIG))) blis-0.9.0/config/cortexa53/000077500000000000000000000000001422157504600155415ustar00rootroot00000000000000blis-0.9.0/config/cortexa53/bli_cntx_init_cortexa53.c000066400000000000000000000060551422157504600224350ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_cntx_init_cortexa53( cntx_t* cntx ) { blksz_t blkszs[ BLIS_NUM_BLKSZS ]; // Set default kernel blocksizes and functions. bli_cntx_init_cortexa53_ref( cntx ); // ------------------------------------------------------------------------- // Update the context with optimized native gemm micro-kernels and // their storage preferences. bli_cntx_set_l3_nat_ukrs ( 2, BLIS_GEMM_UKR, BLIS_FLOAT, bli_sgemm_armv8a_asm_8x12, FALSE, BLIS_GEMM_UKR, BLIS_DOUBLE, bli_dgemm_armv8a_asm_6x8, FALSE, cntx ); // Initialize level-3 blocksize objects with architecture-specific values. // s d c z bli_blksz_init_easy( &blkszs[ BLIS_MR ], 8, 6, -1, -1 ); bli_blksz_init_easy( &blkszs[ BLIS_NR ], 12, 8, -1, -1 ); bli_blksz_init_easy( &blkszs[ BLIS_MC ], 120, 120, -1, -1 ); bli_blksz_init_easy( &blkszs[ BLIS_KC ], 640, 240, -1, -1 ); bli_blksz_init_easy( &blkszs[ BLIS_NC ], 3072, 3072, -1, -1 ); // Update the context with the current architecture's register and cache // blocksizes (and multiples) for native execution. bli_cntx_set_blkszs ( BLIS_NAT, 5, BLIS_NC, &blkszs[ BLIS_NC ], BLIS_NR, BLIS_KC, &blkszs[ BLIS_KC ], BLIS_KR, BLIS_MC, &blkszs[ BLIS_MC ], BLIS_MR, BLIS_NR, &blkszs[ BLIS_NR ], BLIS_NR, BLIS_MR, &blkszs[ BLIS_MR ], BLIS_MR, cntx ); } blis-0.9.0/config/cortexa53/bli_family_cortexa53.h000066400000000000000000000034101422157504600217140ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // -- MEMORY ALLOCATION -------------------------------------------------------- #define BLIS_SIMD_ALIGN_SIZE 16 blis-0.9.0/config/cortexa53/make_defs.mk000066400000000000000000000060451422157504600200150ustar00rootroot00000000000000# # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2014, The University of Texas at Austin # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # # Declare the name of the current configuration and add it to the # running list of configurations included by common.mk. THIS_CONFIG := cortexa53 #CONFIGS_INCL += $(THIS_CONFIG) # # --- Determine the C compiler and related flags --- # # NOTE: The build system will append these variables with various # general-purpose/configuration-agnostic flags in common.mk. You # may specify additional flags here as needed. CPPROCFLAGS := -D_GNU_SOURCE CMISCFLAGS := CPICFLAGS := CWARNFLAGS := ifneq ($(DEBUG_TYPE),off) CDBGFLAGS := -g endif ifeq ($(DEBUG_TYPE),noopt) COPTFLAGS := -O0 else COPTFLAGS := -O2 -mcpu=cortex-a53 endif # Flags specific to optimized kernels. CKOPTFLAGS := $(COPTFLAGS) -O3 -ftree-vectorize ifeq ($(CC_VENDOR),gcc) CKVECFLAGS := -mcpu=cortex-a53 else ifeq ($(CC_VENDOR),clang) CKVECFLAGS := -mcpu=cortex-a53 else $(error gcc or clang is required for this configuration.) endif endif # Flags specific to reference kernels. CROPTFLAGS := $(CKOPTFLAGS) -O3 ifeq ($(CC_VENDOR),gcc) CRVECFLAGS := $(CKVECFLAGS) -funsafe-math-optimizations -ffp-contract=fast else ifeq ($(CC_VENDOR),clang) CRVECFLAGS := $(CKVECFLAGS) -funsafe-math-optimizations -ffp-contract=fast else CRVECFLAGS := $(CKVECFLAGS) endif endif # Store all of the variables here to new variables containing the # configuration name. $(eval $(call store-make-defs,$(THIS_CONFIG))) blis-0.9.0/config/cortexa57/000077500000000000000000000000001422157504600155455ustar00rootroot00000000000000blis-0.9.0/config/cortexa57/bli_cntx_init_cortexa57.c000066400000000000000000000060551422157504600224450ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_cntx_init_cortexa57( cntx_t* cntx ) { blksz_t blkszs[ BLIS_NUM_BLKSZS ]; // Set default kernel blocksizes and functions. bli_cntx_init_cortexa57_ref( cntx ); // ------------------------------------------------------------------------- // Update the context with optimized native gemm micro-kernels and // their storage preferences. bli_cntx_set_l3_nat_ukrs ( 2, BLIS_GEMM_UKR, BLIS_FLOAT, bli_sgemm_armv8a_asm_8x12, FALSE, BLIS_GEMM_UKR, BLIS_DOUBLE, bli_dgemm_armv8a_asm_6x8, FALSE, cntx ); // Initialize level-3 blocksize objects with architecture-specific values. // s d c z bli_blksz_init_easy( &blkszs[ BLIS_MR ], 8, 6, -1, -1 ); bli_blksz_init_easy( &blkszs[ BLIS_NR ], 12, 8, -1, -1 ); bli_blksz_init_easy( &blkszs[ BLIS_MC ], 120, 120, -1, -1 ); bli_blksz_init_easy( &blkszs[ BLIS_KC ], 640, 240, -1, -1 ); bli_blksz_init_easy( &blkszs[ BLIS_NC ], 3072, 3072, -1, -1 ); // Update the context with the current architecture's register and cache // blocksizes (and multiples) for native execution. bli_cntx_set_blkszs ( BLIS_NAT, 5, BLIS_NC, &blkszs[ BLIS_NC ], BLIS_NR, BLIS_KC, &blkszs[ BLIS_KC ], BLIS_KR, BLIS_MC, &blkszs[ BLIS_MC ], BLIS_MR, BLIS_NR, &blkszs[ BLIS_NR ], BLIS_NR, BLIS_MR, &blkszs[ BLIS_MR ], BLIS_MR, cntx ); } blis-0.9.0/config/cortexa57/bli_family_cortexa57.h000066400000000000000000000060241422157504600217300ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ //#ifndef BLIS_FAMILY_H //#define BLIS_FAMILY_H // -- MEMORY ALLOCATION -------------------------------------------------------- #define BLIS_SIMD_ALIGN_SIZE 16 #if 0 // -- LEVEL-3 MICRO-KERNEL CONSTANTS ------------------------------------------- #define BLIS_SGEMM_UKERNEL bli_sgemm_opt_8x12 #define BLIS_DEFAULT_MR_S 8 #define BLIS_DEFAULT_NR_S 12 #define BLIS_DEFAULT_MC_S 120 //1536 //336 //416 // 1280 //160 // 160 // 160 //2048 //336 #define BLIS_DEFAULT_KC_S 640 //1536 //336 //704 //1280 //672 //528 // 856 //2048 //528 #define BLIS_DEFAULT_NC_S 3072 #define BLIS_DGEMM_UKERNEL bli_dgemm_opt_6x8 #define BLIS_DEFAULT_MR_D 6 #define BLIS_DEFAULT_NR_D 8 #define BLIS_DEFAULT_MC_D 120 //1536 //160 //80 //176 #define BLIS_DEFAULT_KC_D 240 //1536 //304 //336 //368 #define BLIS_DEFAULT_NC_D 3072 #define BLIS_DEFAULT_MR_C 8 #define BLIS_DEFAULT_NR_C 4 #define BLIS_DEFAULT_MC_C 64 #define BLIS_DEFAULT_KC_C 128 #define BLIS_DEFAULT_NC_C 4096 #define BLIS_DEFAULT_MR_Z 8 #define BLIS_DEFAULT_NR_Z 4 #define BLIS_DEFAULT_MC_Z 64 #define BLIS_DEFAULT_KC_Z 128 #define BLIS_DEFAULT_NC_Z 4096 #endif //#endif blis-0.9.0/config/cortexa57/make_defs.mk000066400000000000000000000060411422157504600200150ustar00rootroot00000000000000# # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2014, The University of Texas at Austin # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # # Declare the name of the current configuration and add it to the # running list of configurations included by common.mk. THIS_CONFIG := cortexa57 #CONFIGS_INCL += $(THIS_CONFIG) # # --- Determine the C compiler and related flags --- # # NOTE: The build system will append these variables with various # general-purpose/configuration-agnostic flags in common.mk. You # may specify additional flags here as needed. CPPROCFLAGS := -D_GNU_SOURCE CMISCFLAGS := CPICFLAGS := CWARNFLAGS := ifneq ($(DEBUG_TYPE),off) CDBGFLAGS := -g endif ifeq ($(DEBUG_TYPE),noopt) COPTFLAGS := -O0 else COPTFLAGS := -O2 -mcpu=cortex-a57 endif # Flags specific to optimized kernels. CKOPTFLAGS := $(COPTFLAGS) -O3 -ftree-vectorize ifeq ($(CC_VENDOR),gcc) CKVECFLAGS := -mcpu=cortex-a57 else ifeq ($(CC_VENDOR),clang) CKVECFLAGS := -mcpu=cortex-a57 else $(error gcc or clang is required for this configuration.) endif endif # Flags specific to reference kernels. CROPTFLAGS := $(CKOPTFLAGS) ifeq ($(CC_VENDOR),gcc) CRVECFLAGS := $(CKVECFLAGS) -funsafe-math-optimizations -ffp-contract=fast else ifeq ($(CC_VENDOR),clang) CRVECFLAGS := $(CKVECFLAGS) -funsafe-math-optimizations -ffp-contract=fast else CRVECFLAGS := $(CKVECFLAGS) endif endif # Store all of the variables here to new variables containing the # configuration name. $(eval $(call store-make-defs,$(THIS_CONFIG))) blis-0.9.0/config/cortexa9/000077500000000000000000000000001422157504600154625ustar00rootroot00000000000000blis-0.9.0/config/cortexa9/bli_cntx_init_cortexa9.c000066400000000000000000000060511422157504600222730ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_cntx_init_cortexa9( cntx_t* cntx ) { blksz_t blkszs[ BLIS_NUM_BLKSZS ]; // Set default kernel blocksizes and functions. bli_cntx_init_cortexa9_ref( cntx ); // ------------------------------------------------------------------------- // Update the context with optimized native gemm micro-kernels and // their storage preferences. bli_cntx_set_l3_nat_ukrs ( 2, BLIS_GEMM_UKR, BLIS_FLOAT, bli_sgemm_armv7a_int_4x4, FALSE, BLIS_GEMM_UKR, BLIS_DOUBLE, bli_dgemm_armv7a_int_4x4, FALSE, cntx ); // Initialize level-3 blocksize objects with architecture-specific values. // s d c z bli_blksz_init_easy( &blkszs[ BLIS_MR ], 4, 4, 0, 0 ); bli_blksz_init_easy( &blkszs[ BLIS_NR ], 4, 4, 0, 0 ); bli_blksz_init_easy( &blkszs[ BLIS_MC ], 432, 176, 0, 0 ); bli_blksz_init_easy( &blkszs[ BLIS_KC ], 352, 368, 0, 0 ); bli_blksz_init_easy( &blkszs[ BLIS_NC ], 4096, 4096, 0, 0 ); // Update the context with the current architecture's register and cache // blocksizes (and multiples) for native execution. bli_cntx_set_blkszs ( BLIS_NAT, 5, BLIS_NC, &blkszs[ BLIS_NC ], BLIS_NR, BLIS_KC, &blkszs[ BLIS_KC ], BLIS_KR, BLIS_MC, &blkszs[ BLIS_MC ], BLIS_MR, BLIS_NR, &blkszs[ BLIS_NR ], BLIS_NR, BLIS_MR, &blkszs[ BLIS_MR ], BLIS_MR, cntx ); } blis-0.9.0/config/cortexa9/bli_family_cortexa9.h000066400000000000000000000055661422157504600215740ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ //#ifndef BLIS_FAMILY_H //#define BLIS_FAMILY_H // -- MEMORY ALLOCATION -------------------------------------------------------- #define BLIS_SIMD_ALIGN_SIZE 16 #if 0 // -- LEVEL-3 MICRO-KERNEL CONSTANTS ------------------------------------------- #define BLIS_SGEMM_UKERNEL bli_sgemm_armv7a_int_4x4 #define BLIS_DEFAULT_MR_S 4 #define BLIS_DEFAULT_NR_S 4 #define BLIS_DEFAULT_MC_S 432 #define BLIS_DEFAULT_KC_S 352 #define BLIS_DEFAULT_NC_S 4096 #define BLIS_DGEMM_UKERNEL bli_dgemm_armv7a_int_4x4 #define BLIS_DEFAULT_MR_D 4 #define BLIS_DEFAULT_NR_D 4 #define BLIS_DEFAULT_MC_D 176 #define BLIS_DEFAULT_KC_D 368 #define BLIS_DEFAULT_NC_D 4096 #define BLIS_DEFAULT_MR_C 8 #define BLIS_DEFAULT_NR_C 4 #define BLIS_DEFAULT_MC_C 64 #define BLIS_DEFAULT_KC_C 128 #define BLIS_DEFAULT_NC_C 4096 #define BLIS_DEFAULT_MR_Z 8 #define BLIS_DEFAULT_NR_Z 4 #define BLIS_DEFAULT_MC_Z 64 #define BLIS_DEFAULT_KC_Z 128 #define BLIS_DEFAULT_NC_Z 4096 #endif //#endif blis-0.9.0/config/cortexa9/make_defs.mk000066400000000000000000000056721422157504600177430ustar00rootroot00000000000000# # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2014, The University of Texas at Austin # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # # Declare the name of the current configuration and add it to the # running list of configurations included by common.mk. THIS_CONFIG := cortexa9 #CONFIGS_INCL += $(THIS_CONFIG) # # --- Determine the C compiler and related flags --- # # NOTE: The build system will append these variables with various # general-purpose/configuration-agnostic flags in common.mk. You # may specify additional flags here as needed. CPPROCFLAGS := CMISCFLAGS := -mfloat-abi=hard -mfpu=neon CPICFLAGS := CWARNFLAGS := ifneq ($(DEBUG_TYPE),off) CDBGFLAGS := -g endif ifeq ($(DEBUG_TYPE),noopt) COPTFLAGS := -O0 else COPTFLAGS := -O2 endif # Flags specific to optimized kernels. CKOPTFLAGS := $(COPTFLAGS) -O3 ifeq ($(CC_VENDOR),gcc) CKVECFLAGS := -mcpu=cortex-a9 else $(error gcc is required for this configuration.) endif # Flags specific to reference kernels. CROPTFLAGS := $(CKOPTFLAGS) ifeq ($(CC_VENDOR),gcc) CRVECFLAGS := $(CKVECFLAGS) -funsafe-math-optimizations -ffp-contract=fast else ifeq ($(CC_VENDOR),clang) CRVECFLAGS := $(CKVECFLAGS) -funsafe-math-optimizations -ffp-contract=fast else CRVECFLAGS := $(CKVECFLAGS) endif endif # Store all of the variables here to new variables containing the # configuration name. $(eval $(call store-make-defs,$(THIS_CONFIG))) blis-0.9.0/config/excavator/000077500000000000000000000000001422157504600157205ustar00rootroot00000000000000blis-0.9.0/config/excavator/bli_cntx_init_excavator.c000066400000000000000000000063031422157504600227670ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_cntx_init_excavator( cntx_t* cntx ) { blksz_t blkszs[ BLIS_NUM_BLKSZS ]; // Set default kernel blocksizes and functions. bli_cntx_init_excavator_ref( cntx ); // ------------------------------------------------------------------------- // Update the context with optimized native gemm micro-kernels and // their storage preferences. bli_cntx_set_l3_nat_ukrs ( 4, BLIS_GEMM_UKR, BLIS_FLOAT, bli_sgemm_piledriver_asm_16x3, FALSE, BLIS_GEMM_UKR, BLIS_DOUBLE, bli_dgemm_piledriver_asm_8x3, FALSE, BLIS_GEMM_UKR, BLIS_SCOMPLEX, bli_cgemm_piledriver_asm_4x2, FALSE, BLIS_GEMM_UKR, BLIS_DCOMPLEX, bli_zgemm_piledriver_asm_2x2, FALSE, cntx ); // Initialize level-3 blocksize objects with architecture-specific values. // s d c z bli_blksz_init_easy( &blkszs[ BLIS_MR ], 16, 8, 4, 2 ); bli_blksz_init_easy( &blkszs[ BLIS_NR ], 3, 3, 2, 2 ); bli_blksz_init_easy( &blkszs[ BLIS_MC ], 528, 264, 264, 100 ); bli_blksz_init_easy( &blkszs[ BLIS_KC ], 256, 256, 256, 320 ); bli_blksz_init_easy( &blkszs[ BLIS_NC ], 8400, 8400, 8400, 8400 ); // Update the context with the current architecture's register and cache // blocksizes (and multiples) for native execution. bli_cntx_set_blkszs ( BLIS_NAT, 5, BLIS_NC, &blkszs[ BLIS_NC ], BLIS_NR, BLIS_KC, &blkszs[ BLIS_KC ], BLIS_KR, BLIS_MC, &blkszs[ BLIS_MC ], BLIS_MR, BLIS_NR, &blkszs[ BLIS_NR ], BLIS_NR, BLIS_MR, &blkszs[ BLIS_MR ], BLIS_MR, cntx ); } blis-0.9.0/config/excavator/bli_family_excavator.h000066400000000000000000000057351422157504600222660ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ //#ifndef BLIS_FAMILY_H //#define BLIS_FAMILY_H // -- MEMORY ALLOCATION -------------------------------------------------------- #define BLIS_SIMD_ALIGN_SIZE 16 #if 0 // -- LEVEL-3 MICRO-KERNEL CONSTANTS ------------------------------------------- #define BLIS_SGEMM_UKERNEL bli_sgemm_asm_16x3 #define BLIS_DEFAULT_MR_S 16 #define BLIS_DEFAULT_NR_S 3 #define BLIS_DEFAULT_MC_S 528 #define BLIS_DEFAULT_KC_S 256 #define BLIS_DEFAULT_NC_S 8400 #define BLIS_DGEMM_UKERNEL bli_dgemm_asm_8x3 #define BLIS_DEFAULT_MR_D 8 #define BLIS_DEFAULT_NR_D 3 #define BLIS_DEFAULT_MC_D 264 #define BLIS_DEFAULT_KC_D 256 #define BLIS_DEFAULT_NC_D 8400 #define BLIS_CGEMM_UKERNEL bli_cgemm_asm_4x2 #define BLIS_DEFAULT_MR_C 4 #define BLIS_DEFAULT_NR_C 2 #define BLIS_DEFAULT_MC_C 264 #define BLIS_DEFAULT_KC_C 256 #define BLIS_DEFAULT_NC_C 8400 #define BLIS_ZGEMM_UKERNEL bli_zgemm_asm_2x2 #define BLIS_DEFAULT_MR_Z 2 #define BLIS_DEFAULT_NR_Z 2 #define BLIS_DEFAULT_MC_Z 100 #define BLIS_DEFAULT_KC_Z 320 #define BLIS_DEFAULT_NC_Z 8400 #endif //#endif blis-0.9.0/config/excavator/make_defs.mk000066400000000000000000000061501422157504600201710ustar00rootroot00000000000000# # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2014, The University of Texas at Austin # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # # Declare the name of the current configuration and add it to the # running list of configurations included by common.mk. THIS_CONFIG := excavator #CONFIGS_INCL += $(THIS_CONFIG) # # --- Determine the C compiler and related flags --- # # NOTE: The build system will append these variables with various # general-purpose/configuration-agnostic flags in common.mk. You # may specify additional flags here as needed. CPPROCFLAGS := CMISCFLAGS := CPICFLAGS := CWARNFLAGS := ifneq ($(DEBUG_TYPE),off) CDBGFLAGS := -g endif ifeq ($(DEBUG_TYPE),noopt) COPTFLAGS := -O0 else COPTFLAGS := -O2 endif # Flags specific to optimized kernels. CKOPTFLAGS := $(COPTFLAGS) -O3 ifeq ($(CC_VENDOR),gcc) CKVECFLAGS := -mfpmath=sse -mavx -mfma -march=bdver4 -mno-fma4 -mno-tbm -mno-xop -mno-lwp else ifeq ($(CC_VENDOR),clang) CKVECFLAGS := -mfpmath=sse -mavx -mfma -march=bdver4 -mno-fma4 -mno-tbm -mno-xop -mno-lwp else $(error gcc or clang are required for this configuration.) endif endif # Flags specific to reference kernels. CROPTFLAGS := $(CKOPTFLAGS) ifeq ($(CC_VENDOR),gcc) CRVECFLAGS := $(CKVECFLAGS) -funsafe-math-optimizations -ffp-contract=fast else ifeq ($(CC_VENDOR),clang) CRVECFLAGS := $(CKVECFLAGS) -funsafe-math-optimizations -ffp-contract=fast else CRVECFLAGS := $(CKVECFLAGS) endif endif # Store all of the variables here to new variables containing the # configuration name. $(eval $(call store-make-defs,$(THIS_CONFIG))) blis-0.9.0/config/firestorm/000077500000000000000000000000001422157504600157365ustar00rootroot00000000000000blis-0.9.0/config/firestorm/bli_cntx_init_firestorm.c000066400000000000000000000127621422157504600230310ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_cntx_init_firestorm( cntx_t* cntx ) { blksz_t blkszs[ BLIS_NUM_BLKSZS ]; blksz_t thresh[ BLIS_NUM_THRESH ]; // Set default kernel blocksizes and functions. bli_cntx_init_firestorm_ref( cntx ); // ------------------------------------------------------------------------- // Update the context with optimized native gemm micro-kernels and // their storage preferences. bli_cntx_set_l3_nat_ukrs ( 2, BLIS_GEMM_UKR, BLIS_FLOAT, bli_sgemm_armv8a_asm_8x12, FALSE, BLIS_GEMM_UKR, BLIS_DOUBLE, bli_dgemm_armv8a_asm_6x8, FALSE, cntx ); // Update the context with optimized packm kernels. bli_cntx_set_packm_kers ( 4, BLIS_PACKM_8XK_KER, BLIS_FLOAT, bli_spackm_armv8a_int_8xk, BLIS_PACKM_12XK_KER, BLIS_FLOAT, bli_spackm_armv8a_int_12xk, BLIS_PACKM_6XK_KER, BLIS_DOUBLE, bli_dpackm_armv8a_int_6xk, BLIS_PACKM_8XK_KER, BLIS_DOUBLE, bli_dpackm_armv8a_int_8xk, cntx ); // Initialize level-3 blocksize objects with architecture-specific values. // s d c z bli_blksz_init_easy( &blkszs[ BLIS_MR ], 8, 6, -1, -1 ); bli_blksz_init_easy( &blkszs[ BLIS_NR ], 12, 8, -1, -1 ); bli_blksz_init_easy( &blkszs[ BLIS_MC ], 120, 252, -1, -1 ); bli_blksz_init_easy( &blkszs[ BLIS_KC ], 640, 3072, -1, -1 ); bli_blksz_init_easy( &blkszs[ BLIS_NC ], 3072, 8192, -1, -1 ); // Update the context with the current architecture's register and cache // blocksizes (and multiples) for native execution. bli_cntx_set_blkszs ( BLIS_NAT, 5, BLIS_NC, &blkszs[ BLIS_NC ], BLIS_NR, BLIS_KC, &blkszs[ BLIS_KC ], BLIS_KR, BLIS_MC, &blkszs[ BLIS_MC ], BLIS_MR, BLIS_NR, &blkszs[ BLIS_NR ], BLIS_NR, BLIS_MR, &blkszs[ BLIS_MR ], BLIS_MR, cntx ); // ------------------------------------------------------------------------- // Initialize sup thresholds with architecture-appropriate values. // s d c z bli_blksz_init_easy( &thresh[ BLIS_MT ], -1, 99, -1, -1 ); bli_blksz_init_easy( &thresh[ BLIS_NT ], -1, 99, -1, -1 ); bli_blksz_init_easy( &thresh[ BLIS_KT ], -1, 99, -1, -1 ); // Initialize the context with the sup thresholds. bli_cntx_set_l3_sup_thresh ( 3, BLIS_MT, &thresh[ BLIS_MT ], BLIS_NT, &thresh[ BLIS_NT ], BLIS_KT, &thresh[ BLIS_KT ], cntx ); // Update the context with optimized small/unpacked gemm kernels. bli_cntx_set_l3_sup_kers ( 8, BLIS_RRR, BLIS_DOUBLE, bli_dgemmsup_rv_armv8a_asm_6x8m, TRUE, BLIS_RRC, BLIS_DOUBLE, bli_dgemmsup_rd_armv8a_asm_6x8m, TRUE, BLIS_RCR, BLIS_DOUBLE, bli_dgemmsup_rv_armv8a_asm_6x8m, TRUE, BLIS_RCC, BLIS_DOUBLE, bli_dgemmsup_rv_armv8a_asm_6x8n, TRUE, BLIS_CRR, BLIS_DOUBLE, bli_dgemmsup_rv_armv8a_asm_6x8m, TRUE, BLIS_CRC, BLIS_DOUBLE, bli_dgemmsup_rd_armv8a_asm_6x8n, TRUE, BLIS_CCR, BLIS_DOUBLE, bli_dgemmsup_rv_armv8a_asm_6x8n, TRUE, BLIS_CCC, BLIS_DOUBLE, bli_dgemmsup_rv_armv8a_asm_6x8n, TRUE, cntx ); // Initialize level-3 sup blocksize objects with architecture-specific // values. // s d c z bli_blksz_init_easy( &blkszs[ BLIS_MR ], -1, 6, -1, -1 ); bli_blksz_init_easy( &blkszs[ BLIS_NR ], -1, 8, -1, -1 ); bli_blksz_init_easy( &blkszs[ BLIS_MC ], -1, 240, -1, -1 ); bli_blksz_init_easy( &blkszs[ BLIS_KC ], -1, 1024, -1, -1 ); bli_blksz_init_easy( &blkszs[ BLIS_NC ], -1, 3072, -1, -1 ); // Update the context with the current architecture's register and cache // blocksizes for small/unpacked level-3 problems. bli_cntx_set_l3_sup_blkszs ( 5, BLIS_NC, &blkszs[ BLIS_NC ], BLIS_KC, &blkszs[ BLIS_KC ], BLIS_MC, &blkszs[ BLIS_MC ], BLIS_NR, &blkszs[ BLIS_NR ], BLIS_MR, &blkszs[ BLIS_MR ], cntx ); } blis-0.9.0/config/firestorm/bli_family_firestorm.h000066400000000000000000000060241422157504600223120ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ //#ifndef BLIS_FAMILY_H //#define BLIS_FAMILY_H // -- MEMORY ALLOCATION -------------------------------------------------------- #define BLIS_SIMD_ALIGN_SIZE 16 #if 0 // -- LEVEL-3 MICRO-KERNEL CONSTANTS ------------------------------------------- #define BLIS_SGEMM_UKERNEL bli_sgemm_opt_8x12 #define BLIS_DEFAULT_MR_S 8 #define BLIS_DEFAULT_NR_S 12 #define BLIS_DEFAULT_MC_S 120 //1536 //336 //416 // 1280 //160 // 160 // 160 //2048 //336 #define BLIS_DEFAULT_KC_S 640 //1536 //336 //704 //1280 //672 //528 // 856 //2048 //528 #define BLIS_DEFAULT_NC_S 3072 #define BLIS_DGEMM_UKERNEL bli_dgemm_opt_6x8 #define BLIS_DEFAULT_MR_D 6 #define BLIS_DEFAULT_NR_D 8 #define BLIS_DEFAULT_MC_D 120 //1536 //160 //80 //176 #define BLIS_DEFAULT_KC_D 240 //1536 //304 //336 //368 #define BLIS_DEFAULT_NC_D 3072 #define BLIS_DEFAULT_MR_C 8 #define BLIS_DEFAULT_NR_C 4 #define BLIS_DEFAULT_MC_C 64 #define BLIS_DEFAULT_KC_C 128 #define BLIS_DEFAULT_NC_C 4096 #define BLIS_DEFAULT_MR_Z 8 #define BLIS_DEFAULT_NR_Z 4 #define BLIS_DEFAULT_MC_Z 64 #define BLIS_DEFAULT_KC_Z 128 #define BLIS_DEFAULT_NC_Z 4096 #endif //#endif blis-0.9.0/config/firestorm/make_defs.mk000066400000000000000000000055701422157504600202140ustar00rootroot00000000000000# # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2014, The University of Texas at Austin # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # # Declare the name of the current configuration and add it to the # running list of configurations included by common.mk. THIS_CONFIG := firestorm #CONFIGS_INCL += $(THIS_CONFIG) # # --- Determine the C compiler and related flags --- # # NOTE: The build system will append these variables with various # general-purpose/configuration-agnostic flags in common.mk. You # may specify additional flags here as needed. CPPROCFLAGS := -D_GNU_SOURCE CMISCFLAGS := CPICFLAGS := CWARNFLAGS := ifneq ($(DEBUG_TYPE),off) CDBGFLAGS := -g endif ifeq ($(DEBUG_TYPE),noopt) COPTFLAGS := -O0 else COPTFLAGS := -O2 -march=armv8-a endif # Flags specific to optimized kernels. CKOPTFLAGS := $(COPTFLAGS) -O3 -ftree-vectorize CKVECFLAGS := -march=armv8-a # Flags specific to reference kernels. CROPTFLAGS := $(CKOPTFLAGS) ifeq ($(CC_VENDOR),gcc) CRVECFLAGS := $(CKVECFLAGS) -funsafe-math-optimizations -ffp-contract=fast else ifeq ($(CC_VENDOR),clang) CRVECFLAGS := $(CKVECFLAGS) -funsafe-math-optimizations -ffp-contract=fast else CRVECFLAGS := $(CKVECFLAGS) endif endif # Store all of the variables here to new variables containing the # configuration name. $(eval $(call store-make-defs,$(THIS_CONFIG))) blis-0.9.0/config/generic/000077500000000000000000000000001422157504600153405ustar00rootroot00000000000000blis-0.9.0/config/generic/bli_cntx_init_generic.c000066400000000000000000000034421422157504600220300ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_cntx_init_generic( cntx_t* cntx ) { // Set default kernel blocksizes and functions. bli_cntx_init_generic_ref( cntx ); } blis-0.9.0/config/generic/bli_family_generic.h000066400000000000000000000033071422157504600213170ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ //#ifndef BLIS_FAMILY_H //#define BLIS_FAMILY_H //#endif blis-0.9.0/config/generic/make_defs.mk000066400000000000000000000060101422157504600176040ustar00rootroot00000000000000# # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2014, The University of Texas at Austin # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # # Declare the name of the current configuration and add it to the # running list of configurations included by common.mk. THIS_CONFIG := generic #CONFIGS_INCL += $(THIS_CONFIG) # # --- Determine the C compiler and related flags --- # # NOTE: The build system will append these variables with various # general-purpose/configuration-agnostic flags in common.mk. You # may specify additional flags here as needed. CPPROCFLAGS := CMISCFLAGS := CPICFLAGS := CWARNFLAGS := ifneq ($(DEBUG_TYPE),off) CDBGFLAGS := -g endif ifeq ($(DEBUG_TYPE),noopt) COPTFLAGS := -O0 else COPTFLAGS := -O2 endif # Flags specific to optimized kernels. CKOPTFLAGS := $(COPTFLAGS) -O3 ifeq ($(CC_VENDOR),gcc) CKVECFLAGS := else ifeq ($(CC_VENDOR),icc) CKVECFLAGS := else ifeq ($(CC_VENDOR),clang) CKVECFLAGS := else $(error gcc, icc, or clang is required for this configuration.) endif endif endif # Flags specific to reference kernels. CROPTFLAGS := $(CKOPTFLAGS) ifeq ($(CC_VENDOR),gcc) CRVECFLAGS := $(CKVECFLAGS) -funsafe-math-optimizations -ffp-contract=fast else ifeq ($(CC_VENDOR),clang) CRVECFLAGS := $(CKVECFLAGS) -funsafe-math-optimizations -ffp-contract=fast else CRVECFLAGS := $(CKVECFLAGS) endif endif # Store all of the variables here to new variables containing the # configuration name. $(eval $(call store-make-defs,$(THIS_CONFIG))) blis-0.9.0/config/haswell/000077500000000000000000000000001422157504600153635ustar00rootroot00000000000000blis-0.9.0/config/haswell/bli_cntx_init_haswell.c000066400000000000000000000232141422157504600220750ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" //GEMMSUP_KER_PROT( double, d, gemmsup_r_haswell_ref ) void bli_cntx_init_haswell( cntx_t* cntx ) { blksz_t blkszs[ BLIS_NUM_BLKSZS ]; blksz_t thresh[ BLIS_NUM_THRESH ]; // Set default kernel blocksizes and functions. bli_cntx_init_haswell_ref( cntx ); // ------------------------------------------------------------------------- // Update the context with optimized native gemm micro-kernels and // their storage preferences. bli_cntx_set_l3_nat_ukrs ( 8, // gemm #if 1 BLIS_GEMM_UKR, BLIS_FLOAT, bli_sgemm_haswell_asm_6x16, TRUE, BLIS_GEMM_UKR, BLIS_DOUBLE, bli_dgemm_haswell_asm_6x8, TRUE, BLIS_GEMM_UKR, BLIS_SCOMPLEX, bli_cgemm_haswell_asm_3x8, TRUE, BLIS_GEMM_UKR, BLIS_DCOMPLEX, bli_zgemm_haswell_asm_3x4, TRUE, #else BLIS_GEMM_UKR, BLIS_FLOAT, bli_sgemm_haswell_asm_16x6, FALSE, BLIS_GEMM_UKR, BLIS_DOUBLE, bli_dgemm_haswell_asm_8x6, FALSE, BLIS_GEMM_UKR, BLIS_SCOMPLEX, bli_cgemm_haswell_asm_8x3, FALSE, BLIS_GEMM_UKR, BLIS_DCOMPLEX, bli_zgemm_haswell_asm_4x3, FALSE, #endif // gemmtrsm_l BLIS_GEMMTRSM_L_UKR, BLIS_FLOAT, bli_sgemmtrsm_l_haswell_asm_6x16, TRUE, BLIS_GEMMTRSM_L_UKR, BLIS_DOUBLE, bli_dgemmtrsm_l_haswell_asm_6x8, TRUE, // gemmtrsm_u BLIS_GEMMTRSM_U_UKR, BLIS_FLOAT, bli_sgemmtrsm_u_haswell_asm_6x16, TRUE, BLIS_GEMMTRSM_U_UKR, BLIS_DOUBLE, bli_dgemmtrsm_u_haswell_asm_6x8, TRUE, cntx ); #if 1 // Update the context with optimized packm kernels. bli_cntx_set_packm_kers ( 8, BLIS_PACKM_6XK_KER, BLIS_FLOAT, bli_spackm_haswell_asm_6xk, BLIS_PACKM_16XK_KER, BLIS_FLOAT, bli_spackm_haswell_asm_16xk, BLIS_PACKM_6XK_KER, BLIS_DOUBLE, bli_dpackm_haswell_asm_6xk, BLIS_PACKM_8XK_KER, BLIS_DOUBLE, bli_dpackm_haswell_asm_8xk, BLIS_PACKM_3XK_KER, BLIS_SCOMPLEX, bli_cpackm_haswell_asm_3xk, BLIS_PACKM_8XK_KER, BLIS_SCOMPLEX, bli_cpackm_haswell_asm_8xk, BLIS_PACKM_3XK_KER, BLIS_DCOMPLEX, bli_zpackm_haswell_asm_3xk, BLIS_PACKM_4XK_KER, BLIS_DCOMPLEX, bli_zpackm_haswell_asm_4xk, cntx ); #endif // Update the context with optimized level-1f kernels. bli_cntx_set_l1f_kers ( 4, // axpyf BLIS_AXPYF_KER, BLIS_FLOAT, bli_saxpyf_zen_int_8, BLIS_AXPYF_KER, BLIS_DOUBLE, bli_daxpyf_zen_int_8, // dotxf BLIS_DOTXF_KER, BLIS_FLOAT, bli_sdotxf_zen_int_8, BLIS_DOTXF_KER, BLIS_DOUBLE, bli_ddotxf_zen_int_8, cntx ); // Update the context with optimized level-1v kernels. bli_cntx_set_l1v_kers ( 10, // amaxv BLIS_AMAXV_KER, BLIS_FLOAT, bli_samaxv_zen_int, BLIS_AMAXV_KER, BLIS_DOUBLE, bli_damaxv_zen_int, // axpyv #if 0 BLIS_AXPYV_KER, BLIS_FLOAT, bli_saxpyv_zen_int, BLIS_AXPYV_KER, BLIS_DOUBLE, bli_daxpyv_zen_int, #else BLIS_AXPYV_KER, BLIS_FLOAT, bli_saxpyv_zen_int10, BLIS_AXPYV_KER, BLIS_DOUBLE, bli_daxpyv_zen_int10, #endif // dotv BLIS_DOTV_KER, BLIS_FLOAT, bli_sdotv_zen_int, BLIS_DOTV_KER, BLIS_DOUBLE, bli_ddotv_zen_int, // dotxv BLIS_DOTXV_KER, BLIS_FLOAT, bli_sdotxv_zen_int, BLIS_DOTXV_KER, BLIS_DOUBLE, bli_ddotxv_zen_int, // scalv #if 0 BLIS_SCALV_KER, BLIS_FLOAT, bli_sscalv_zen_int, BLIS_SCALV_KER, BLIS_DOUBLE, bli_dscalv_zen_int, #else BLIS_SCALV_KER, BLIS_FLOAT, bli_sscalv_zen_int10, BLIS_SCALV_KER, BLIS_DOUBLE, bli_dscalv_zen_int10, #endif cntx ); // Initialize level-3 blocksize objects with architecture-specific values. // s d c z #if 1 bli_blksz_init_easy( &blkszs[ BLIS_MR ], 6, 6, 3, 3 ); bli_blksz_init_easy( &blkszs[ BLIS_NR ], 16, 8, 8, 4 ); //bli_blksz_init_easy( &blkszs[ BLIS_MC ], 1008, 1008, 1008, 1008 ); //bli_blksz_init_easy( &blkszs[ BLIS_MC ], 168, 72, 72, 36 ); bli_blksz_init_easy( &blkszs[ BLIS_MC ], 168, 72, 75, 192 ); bli_blksz_init_easy( &blkszs[ BLIS_KC ], 256, 256, 256, 256 ); #else bli_blksz_init_easy( &blkszs[ BLIS_MR ], 16, 8, 8, 4 ); bli_blksz_init_easy( &blkszs[ BLIS_NR ], 6, 6, 3, 3 ); //bli_blksz_init_easy( &blkszs[ BLIS_MC ], 1024, 1024, 1024, 1024 ); //bli_blksz_init_easy( &blkszs[ BLIS_MC ], 112, 64, 56, 32 ); bli_blksz_init_easy( &blkszs[ BLIS_MC ], 112, 72, 56, 44 ); bli_blksz_init_easy( &blkszs[ BLIS_KC ], 256, 256, 256, 256 ); #endif bli_blksz_init_easy( &blkszs[ BLIS_NC ], 4080, 4080, 4080, 4080 ); bli_blksz_init_easy( &blkszs[ BLIS_AF ], 8, 8, 8, 8 ); bli_blksz_init_easy( &blkszs[ BLIS_DF ], 8, 8, 8, 8 ); // Update the context with the current architecture's register and cache // blocksizes (and multiples) for native execution. bli_cntx_set_blkszs ( BLIS_NAT, 7, // level-3 BLIS_NC, &blkszs[ BLIS_NC ], BLIS_NR, BLIS_KC, &blkszs[ BLIS_KC ], BLIS_KR, BLIS_MC, &blkszs[ BLIS_MC ], BLIS_MR, BLIS_NR, &blkszs[ BLIS_NR ], BLIS_NR, BLIS_MR, &blkszs[ BLIS_MR ], BLIS_MR, // level-1f BLIS_AF, &blkszs[ BLIS_AF ], BLIS_AF, BLIS_DF, &blkszs[ BLIS_DF ], BLIS_DF, cntx ); // ------------------------------------------------------------------------- // Initialize sup thresholds with architecture-appropriate values. // s d c z bli_blksz_init_easy( &thresh[ BLIS_MT ], 201, 201, -1, -1 ); bli_blksz_init_easy( &thresh[ BLIS_NT ], 201, 201, -1, -1 ); bli_blksz_init_easy( &thresh[ BLIS_KT ], 201, 201, -1, -1 ); // Initialize the context with the sup thresholds. bli_cntx_set_l3_sup_thresh ( 3, BLIS_MT, &thresh[ BLIS_MT ], BLIS_NT, &thresh[ BLIS_NT ], BLIS_KT, &thresh[ BLIS_KT ], cntx ); #if 0 // Initialize the context with the sup handlers. bli_cntx_set_l3_sup_handlers ( 1, BLIS_GEMM, bli_gemmsup_ref, cntx ); #endif // Update the context with optimized small/unpacked gemm kernels. bli_cntx_set_l3_sup_kers ( 16, //BLIS_RCR, BLIS_DOUBLE, bli_dgemmsup_r_haswell_ref, BLIS_RRR, BLIS_DOUBLE, bli_dgemmsup_rv_haswell_asm_6x8m, TRUE, BLIS_RRC, BLIS_DOUBLE, bli_dgemmsup_rd_haswell_asm_6x8m, TRUE, BLIS_RCR, BLIS_DOUBLE, bli_dgemmsup_rv_haswell_asm_6x8m, TRUE, BLIS_RCC, BLIS_DOUBLE, bli_dgemmsup_rv_haswell_asm_6x8n, TRUE, BLIS_CRR, BLIS_DOUBLE, bli_dgemmsup_rv_haswell_asm_6x8m, TRUE, BLIS_CRC, BLIS_DOUBLE, bli_dgemmsup_rd_haswell_asm_6x8n, TRUE, BLIS_CCR, BLIS_DOUBLE, bli_dgemmsup_rv_haswell_asm_6x8n, TRUE, BLIS_CCC, BLIS_DOUBLE, bli_dgemmsup_rv_haswell_asm_6x8n, TRUE, BLIS_RRR, BLIS_FLOAT, bli_sgemmsup_rv_haswell_asm_6x16m, TRUE, BLIS_RRC, BLIS_FLOAT, bli_sgemmsup_rd_haswell_asm_6x16m, TRUE, BLIS_RCR, BLIS_FLOAT, bli_sgemmsup_rv_haswell_asm_6x16m, TRUE, BLIS_RCC, BLIS_FLOAT, bli_sgemmsup_rv_haswell_asm_6x16n, TRUE, BLIS_CRR, BLIS_FLOAT, bli_sgemmsup_rv_haswell_asm_6x16m, TRUE, BLIS_CRC, BLIS_FLOAT, bli_sgemmsup_rd_haswell_asm_6x16n, TRUE, BLIS_CCR, BLIS_FLOAT, bli_sgemmsup_rv_haswell_asm_6x16n, TRUE, BLIS_CCC, BLIS_FLOAT, bli_sgemmsup_rv_haswell_asm_6x16n, TRUE, cntx ); // Initialize level-3 sup blocksize objects with architecture-specific // values. // s d c z bli_blksz_init ( &blkszs[ BLIS_MR ], 6, 6, -1, -1, 9, 9, -1, -1 ); bli_blksz_init_easy( &blkszs[ BLIS_NR ], 16, 8, -1, -1 ); bli_blksz_init_easy( &blkszs[ BLIS_MC ], 168, 72, -1, -1 ); bli_blksz_init_easy( &blkszs[ BLIS_KC ], 256, 256, -1, -1 ); bli_blksz_init_easy( &blkszs[ BLIS_NC ], 4080, 4080, -1, -1 ); // Update the context with the current architecture's register and cache // blocksizes for small/unpacked level-3 problems. bli_cntx_set_l3_sup_blkszs ( 5, BLIS_NC, &blkszs[ BLIS_NC ], BLIS_KC, &blkszs[ BLIS_KC ], BLIS_MC, &blkszs[ BLIS_MC ], BLIS_NR, &blkszs[ BLIS_NR ], BLIS_MR, &blkszs[ BLIS_MR ], cntx ); } blis-0.9.0/config/haswell/bli_family_haswell.h000066400000000000000000000114211422157504600213610ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ //#ifndef BLIS_FAMILY_H //#define BLIS_FAMILY_H #if 0 // -- LEVEL-3 MICRO-KERNEL CONSTANTS AND DEFINITIONS --------------------------- // -- sgemm micro-kernel -- #if 0 #define BLIS_SGEMM_UKERNEL bli_sgemm_asm_4x24 #define BLIS_DEFAULT_MC_S 256 #define BLIS_DEFAULT_KC_S 256 #define BLIS_DEFAULT_NC_S 4080 #define BLIS_DEFAULT_MR_S 4 #define BLIS_DEFAULT_NR_S 24 #define BLIS_SGEMM_UKERNEL_PREFERS_CONTIG_ROWS #endif #if 1 #define BLIS_SGEMM_UKERNEL bli_sgemm_asm_6x16 #define BLIS_DEFAULT_MC_S 144 #define BLIS_DEFAULT_KC_S 256 #define BLIS_DEFAULT_NC_S 4080 #define BLIS_DEFAULT_MR_S 6 #define BLIS_DEFAULT_NR_S 16 #define BLIS_SGEMM_UKERNEL_PREFERS_CONTIG_ROWS #endif #if 0 #define BLIS_SGEMM_UKERNEL bli_sgemm_asm_16x6 #define BLIS_DEFAULT_MC_S 144 #define BLIS_DEFAULT_KC_S 256 #define BLIS_DEFAULT_NC_S 4080 #define BLIS_DEFAULT_MR_S 16 #define BLIS_DEFAULT_NR_S 6 #endif // -- dgemm micro-kernel -- #if 0 #define BLIS_DGEMM_UKERNEL bli_dgemm_asm_4x12 #define BLIS_DEFAULT_MC_D 152 #define BLIS_DEFAULT_KC_D 160 #define BLIS_DEFAULT_NC_D 4080 #define BLIS_DEFAULT_MR_D 4 #define BLIS_DEFAULT_NR_D 12 #define BLIS_DGEMM_UKERNEL_PREFERS_CONTIG_ROWS #endif #if 1 #define BLIS_DGEMM_UKERNEL bli_dgemm_asm_6x8 #define BLIS_DEFAULT_MC_D 72 #define BLIS_DEFAULT_KC_D 256 #define BLIS_DEFAULT_NC_D 4080 #define BLIS_DEFAULT_MR_D 6 #define BLIS_DEFAULT_NR_D 8 #define BLIS_DGEMM_UKERNEL_PREFERS_CONTIG_ROWS #endif #if 0 #define BLIS_DGEMM_UKERNEL bli_dgemm_asm_8x6 #define BLIS_DEFAULT_MC_D 72 #define BLIS_DEFAULT_KC_D 256 #define BLIS_DEFAULT_NC_D 4080 #define BLIS_DEFAULT_MR_D 8 #define BLIS_DEFAULT_NR_D 6 #endif // -- cgemm micro-kernel -- #if 1 #define BLIS_CGEMM_UKERNEL bli_cgemm_asm_3x8 #define BLIS_DEFAULT_MC_C 144 #define BLIS_DEFAULT_KC_C 256 #define BLIS_DEFAULT_NC_C 4080 #define BLIS_DEFAULT_MR_C 3 #define BLIS_DEFAULT_NR_C 8 #define BLIS_CGEMM_UKERNEL_PREFERS_CONTIG_ROWS #endif #if 0 #define BLIS_CGEMM_UKERNEL bli_cgemm_asm_8x3 #define BLIS_DEFAULT_MC_C 144 #define BLIS_DEFAULT_KC_C 256 #define BLIS_DEFAULT_NC_C 4080 #define BLIS_DEFAULT_MR_C 8 #define BLIS_DEFAULT_NR_C 3 #endif // -- zgemm micro-kernel -- #if 1 #define BLIS_ZGEMM_UKERNEL bli_zgemm_asm_3x4 #define BLIS_DEFAULT_MC_Z 72 #define BLIS_DEFAULT_KC_Z 256 #define BLIS_DEFAULT_NC_Z 4080 #define BLIS_DEFAULT_MR_Z 3 #define BLIS_DEFAULT_NR_Z 4 #define BLIS_ZGEMM_UKERNEL_PREFERS_CONTIG_ROWS #endif #if 0 #define BLIS_ZGEMM_UKERNEL bli_zgemm_asm_4x3 #define BLIS_DEFAULT_MC_Z 72 #define BLIS_DEFAULT_KC_Z 256 #define BLIS_DEFAULT_NC_Z 4080 #define BLIS_DEFAULT_MR_Z 4 #define BLIS_DEFAULT_NR_Z 3 #endif #endif //#endif blis-0.9.0/config/haswell/make_defs.mk000066400000000000000000000066321422157504600176410ustar00rootroot00000000000000# # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2014, The University of Texas at Austin # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # # Declare the name of the current configuration and add it to the # running list of configurations included by common.mk. THIS_CONFIG := haswell #CONFIGS_INCL += $(THIS_CONFIG) # # --- Determine the C compiler and related flags --- # # NOTE: The build system will append these variables with various # general-purpose/configuration-agnostic flags in common.mk. You # may specify additional flags here as needed. CPPROCFLAGS := CMISCFLAGS := CPICFLAGS := CWARNFLAGS := ifneq ($(DEBUG_TYPE),off) CDBGFLAGS := -g endif ifeq ($(DEBUG_TYPE),noopt) COPTFLAGS := -O0 else COPTFLAGS := -O2 endif # Flags specific to optimized kernels. # NOTE: The -fomit-frame-pointer option is needed for some kernels because # they make explicit use of the rbp register. CKOPTFLAGS := $(COPTFLAGS) -O3 -fomit-frame-pointer ifeq ($(CC_VENDOR),gcc) CKVECFLAGS := -mavx2 -mfma -mfpmath=sse -march=haswell ifeq ($(GCC_OT_4_9_0),yes) # If gcc is older than 4.9.0, we must use a different label for -march. CKVECFLAGS := -mavx2 -mfma -mfpmath=sse -march=core-avx2 endif else ifeq ($(CC_VENDOR),icc) CKVECFLAGS := -xCORE-AVX2 else ifeq ($(CC_VENDOR),clang) CKVECFLAGS := -mavx2 -mfma -mfpmath=sse -march=haswell else $(error gcc, icc, or clang is required for this configuration.) endif endif endif # Flags specific to reference kernels. CROPTFLAGS := $(CKOPTFLAGS) ifeq ($(CC_VENDOR),gcc) CRVECFLAGS := $(CKVECFLAGS) -funsafe-math-optimizations -ffp-contract=fast else ifeq ($(CC_VENDOR),clang) CRVECFLAGS := $(CKVECFLAGS) -funsafe-math-optimizations -ffp-contract=fast else CRVECFLAGS := $(CKVECFLAGS) endif endif # Store all of the variables here to new variables containing the # configuration name. $(eval $(call store-make-defs,$(THIS_CONFIG))) blis-0.9.0/config/intel64/000077500000000000000000000000001422157504600152115ustar00rootroot00000000000000blis-0.9.0/config/intel64/bli_family_intel64.h000066400000000000000000000033061422157504600210400ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ //#ifndef BLIS_FAMILY_H //#define BLIS_FAMILY_H //#endif blis-0.9.0/config/intel64/make_defs.mk000066400000000000000000000061241422157504600174630ustar00rootroot00000000000000# # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2014, The University of Texas at Austin # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # # Declare the name of the current configuration and add it to the # running list of configurations included by common.mk. THIS_CONFIG := intel64 #CONFIGS_INCL += $(THIS_CONFIG) # # --- Determine the C compiler and related flags --- # # NOTE: The build system will append these variables with various # general-purpose/configuration-agnostic flags in common.mk. You # may specify additional flags here as needed. CPPROCFLAGS := CMISCFLAGS := CPICFLAGS := CWARNFLAGS := ifneq ($(DEBUG_TYPE),off) CDBGFLAGS := -g endif ifeq ($(DEBUG_TYPE),noopt) COPTFLAGS := -O0 else COPTFLAGS := -O2 endif # Flags specific to optimized kernels. CKOPTFLAGS := $(COPTFLAGS) -O3 ifeq ($(CC_VENDOR),gcc) CKVECFLAGS := -mssse3 -mfpmath=sse -march=core2 else ifeq ($(CC_VENDOR),icc) CKVECFLAGS := -xSSSE3 else ifeq ($(CC_VENDOR),clang) CKVECFLAGS := -mssse3 -mfpmath=sse -march=core2 else $(error gcc, icc, or clang is required for this configuration.) endif endif endif # Flags specific to reference kernels. CROPTFLAGS := $(CKOPTFLAGS) ifeq ($(CC_VENDOR),gcc) CRVECFLAGS := $(CKVECFLAGS) -funsafe-math-optimizations -ffp-contract=fast else ifeq ($(CC_VENDOR),clang) CRVECFLAGS := $(CKVECFLAGS) -funsafe-math-optimizations -ffp-contract=fast else CRVECFLAGS := $(CKVECFLAGS) endif endif # Store all of the variables here to new variables containing the # configuration name. $(eval $(call store-make-defs,$(THIS_CONFIG))) blis-0.9.0/config/knc/000077500000000000000000000000001422157504600144775ustar00rootroot00000000000000blis-0.9.0/config/knc/bli_cntx_init_knc.c000066400000000000000000000061501422157504600203250ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_cntx_init_knc( cntx_t* cntx ) { blksz_t blkszs[ BLIS_NUM_BLKSZS ]; // Set default kernel blocksizes and functions. bli_cntx_init_knc_ref( cntx ); // ------------------------------------------------------------------------- // Update the context with optimized native gemm micro-kernels and // their storage preferences. bli_cntx_set_l3_nat_ukrs ( 1, BLIS_GEMM_UKR, BLIS_DOUBLE, bli_dgemm_knc_asm_30x8, TRUE, cntx ); // Initialize level-3 blocksize objects with architecture-specific values. // s d c z bli_blksz_init_easy( &blkszs[ BLIS_MR ], 0, 30, 0, 0 ); bli_blksz_init_easy( &blkszs[ BLIS_NR ], 0, 8, 0, 0 ); bli_blksz_init_easy( &blkszs[ BLIS_MC ], 0, 120, 0, 0, 0, 160, 0, 0 ); bli_blksz_init ( &blkszs[ BLIS_KC ], 0, 240, 0, 0, 0, 300, 0, 0 ); bli_blksz_init_easy( &blkszs[ BLIS_NC ], 0, 14400, 0, 0 ); // Update the context with the current architecture's register and cache // blocksizes (and multiples) for native execution. bli_cntx_set_blkszs ( BLIS_NAT, 5, BLIS_NC, &blkszs[ BLIS_NC ], BLIS_NR, BLIS_KC, &blkszs[ BLIS_KC ], BLIS_KR, BLIS_MC, &blkszs[ BLIS_MC ], BLIS_MR, BLIS_NR, &blkszs[ BLIS_NR ], BLIS_NR, BLIS_MR, &blkszs[ BLIS_MR ], BLIS_MR, cntx ); } blis-0.9.0/config/knc/bli_family_knc.h000066400000000000000000000067241422157504600176230ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ //#ifndef BLIS_FAMILY_H //#define BLIS_FAMILY_H // -- THREADING PARAMTERS ------------------------------------------------------ #define BLIS_TREE_BARRIER #define BLIS_TREE_BARRIER_ARITY 4 // -- MEMORY ALLOCATION -------------------------------------------------------- #define BLIS_SIMD_ALIGN_SIZE 64 #define BLIS_SIMD_MAX_SIZE 64 #define BLIS_SIMD_MAX_NUM_REGISTERS 32 #if 0 // -- LEVEL-3 MICRO-KERNEL CONSTANTS ------------------------------------------- #define BLIS_SGEMM_UKERNEL bli_sgemm_asm_30x16 #define BLIS_DEFAULT_MR_S 30 #define BLIS_DEFAULT_NR_S 16 #define BLIS_DEFAULT_MC_S 240 #define BLIS_DEFAULT_KC_S 240 #define BLIS_DEFAULT_NC_S 14400 #define BLIS_DGEMM_UKERNEL_PREFERS_CONTIG_ROWS #define BLIS_DGEMM_UKERNEL bli_dgemm_asm_30x8 #define BLIS_DEFAULT_MR_D 30 #define BLIS_DEFAULT_NR_D 8 #define BLIS_DEFAULT_MC_D 120 #define BLIS_DEFAULT_KC_D 240 #define BLIS_DEFAULT_NC_D 14400 #define BLIS_MAXIMUM_MC_S (BLIS_DEFAULT_MC_S + BLIS_DEFAULT_MC_S/4) #define BLIS_MAXIMUM_KC_S (BLIS_DEFAULT_KC_S + BLIS_DEFAULT_KC_S/4) #define BLIS_MAXIMUM_NC_S (BLIS_DEFAULT_NC_S + 0) #define BLIS_MAXIMUM_MC_D (BLIS_DEFAULT_MC_D + BLIS_DEFAULT_MC_D/4) #define BLIS_MAXIMUM_KC_D (BLIS_DEFAULT_KC_D + BLIS_DEFAULT_KC_D/4) #define BLIS_MAXIMUM_NC_D (BLIS_DEFAULT_NC_D + 0) #define BLIS_PACKDIM_MR_S (BLIS_DEFAULT_MR_S + 2) //#define BLIS_PACKDIM_NR_S (BLIS_DEFAULT_NR_S + ...) #define BLIS_PACKDIM_MR_D (BLIS_DEFAULT_MR_D + 2) //#define BLIS_PACKDIM_NR_D (BLIS_DEFAULT_NR_D + ...) #endif //#endif blis-0.9.0/config/knc/make_defs.mk000066400000000000000000000061011422157504600167440ustar00rootroot00000000000000# # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2014, The University of Texas at Austin # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # # Declare the name of the current configuration and add it to the # running list of configurations included by common.mk. THIS_CONFIG := knc #CONFIGS_INCL += $(THIS_CONFIG) # # --- Determine the C compiler and related flags --- # # NOTE: The build system will append these variables with various # general-purpose/configuration-agnostic flags in common.mk. You # may specify additional flags here as needed. CPPROCFLAGS := CMISCFLAGS := -mmic -fasm-blocks CPICFLAGS := CWARNFLAGS := ifneq ($(DEBUG_TYPE),off) CDBGFLAGS := -g endif ifeq ($(DEBUG_TYPE),noopt) COPTFLAGS := -O0 else COPTFLAGS := -O2 endif # Flags specific to optimized kernels. CKOPTFLAGS := $(COPTFLAGS) -O3 ifeq ($(CC_VENDOR),icc) CKVECFLAGS := else $(error icc is required for this configuration.) endif # Flags specific to reference kernels. CROPTFLAGS := $(CKOPTFLAGS) ifeq ($(CC_VENDOR),gcc) CRVECFLAGS := $(CKVECFLAGS) -funsafe-math-optimizations -ffp-contract=fast else ifeq ($(CC_VENDOR),clang) CRVECFLAGS := $(CKVECFLAGS) -funsafe-math-optimizations -ffp-contract=fast else CRVECFLAGS := $(CKVECFLAGS) endif endif # Override the default value for LDFLAGS. LDFLAGS := -mmic # Never use libm with Intel compilers. ifneq ($(CC_VENDOR),icc) LDFLAGS += $(LIBM) endif # Store all of the variables here to new variables containing the # configuration name. $(eval $(call store-make-defs,$(THIS_CONFIG))) blis-0.9.0/config/knl/000077500000000000000000000000001422157504600145105ustar00rootroot00000000000000blis-0.9.0/config/knl/bli_cntx_init_knl.c000066400000000000000000000116701422157504600203520ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_cntx_init_knl( cntx_t* cntx ) { blksz_t blkszs[ BLIS_NUM_BLKSZS ]; // Set default kernel blocksizes and functions. bli_cntx_init_knl_ref( cntx ); // ------------------------------------------------------------------------- // Update the context with optimized native gemm micro-kernels and // their storage preferences. bli_cntx_set_l3_nat_ukrs ( 2, BLIS_GEMM_UKR, BLIS_FLOAT, bli_sgemm_knl_asm_24x16, FALSE, BLIS_GEMM_UKR, BLIS_DOUBLE, bli_dgemm_knl_asm_24x8, FALSE, cntx ); // Update the context with optimized packm kernels. bli_cntx_set_packm_kers ( 2, BLIS_PACKM_8XK_KER, BLIS_DOUBLE, bli_dpackm_knl_asm_8xk, BLIS_PACKM_24XK_KER, BLIS_DOUBLE, bli_dpackm_knl_asm_24xk, cntx ); // Update the context with optimized level-1f kernels. bli_cntx_set_l1f_kers ( 4, // axpyf BLIS_AXPYF_KER, BLIS_FLOAT, bli_saxpyf_zen_int_8, BLIS_AXPYF_KER, BLIS_DOUBLE, bli_daxpyf_zen_int_8, // dotxf BLIS_DOTXF_KER, BLIS_FLOAT, bli_sdotxf_zen_int_8, BLIS_DOTXF_KER, BLIS_DOUBLE, bli_ddotxf_zen_int_8, cntx ); // Update the context with optimized level-1v kernels. bli_cntx_set_l1v_kers ( 10, #if 1 // amaxv BLIS_AMAXV_KER, BLIS_FLOAT, bli_samaxv_zen_int, BLIS_AMAXV_KER, BLIS_DOUBLE, bli_damaxv_zen_int, #endif // axpyv #if 0 BLIS_AXPYV_KER, BLIS_FLOAT, bli_saxpyv_zen_int, BLIS_AXPYV_KER, BLIS_DOUBLE, bli_daxpyv_zen_int, #else BLIS_AXPYV_KER, BLIS_FLOAT, bli_saxpyv_zen_int10, BLIS_AXPYV_KER, BLIS_DOUBLE, bli_daxpyv_zen_int10, #endif // dotv BLIS_DOTV_KER, BLIS_FLOAT, bli_sdotv_zen_int, BLIS_DOTV_KER, BLIS_DOUBLE, bli_ddotv_zen_int, // dotxv BLIS_DOTXV_KER, BLIS_FLOAT, bli_sdotxv_zen_int, BLIS_DOTXV_KER, BLIS_DOUBLE, bli_ddotxv_zen_int, // scalv #if 0 BLIS_SCALV_KER, BLIS_FLOAT, bli_sscalv_zen_int, BLIS_SCALV_KER, BLIS_DOUBLE, bli_dscalv_zen_int, #else BLIS_SCALV_KER, BLIS_FLOAT, bli_sscalv_zen_int10, BLIS_SCALV_KER, BLIS_DOUBLE, bli_dscalv_zen_int10, #endif cntx ); // Initialize level-3 blocksize objects with architecture-specific values. // s d c z bli_blksz_init_easy( &blkszs[ BLIS_MR ], 24, 24, -1, -1 ); bli_blksz_init_easy( &blkszs[ BLIS_NR ], 16, 8, -1, -1 ); bli_blksz_init ( &blkszs[ BLIS_MC ], 240, 120, -1, -1, 288, 144, -1, -1 ); bli_blksz_init ( &blkszs[ BLIS_KC ], 336, 336, -1, -1, 408, 408, -1, -1 ); bli_blksz_init_easy( &blkszs[ BLIS_NC ], 14400, 14400, -1, -1 ); bli_blksz_init_easy( &blkszs[ BLIS_AF ], 8, 8, -1, -1 ); bli_blksz_init_easy( &blkszs[ BLIS_DF ], 8, 8, -1, -1 ); // Update the context with the current architecture's register and cache // blocksizes (and multiples) for native execution. bli_cntx_set_blkszs ( BLIS_NAT, 7, // level-3 BLIS_NC, &blkszs[ BLIS_NC ], BLIS_NR, BLIS_KC, &blkszs[ BLIS_KC ], BLIS_KR, BLIS_MC, &blkszs[ BLIS_MC ], BLIS_MR, BLIS_NR, &blkszs[ BLIS_NR ], BLIS_NR, BLIS_MR, &blkszs[ BLIS_MR ], BLIS_MR, // level-1f BLIS_AF, &blkszs[ BLIS_AF ], BLIS_AF, BLIS_DF, &blkszs[ BLIS_DF ], BLIS_DF, cntx ); } blis-0.9.0/config/knl/bli_family_knl.h000066400000000000000000000116171422157504600176420ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ //#ifndef BLIS_FAMILY_H //#define BLIS_FAMILY_H // -- THREADING PARAMETERS ----------------------------------------------------- #define BLIS_THREAD_RATIO_M 4 #define BLIS_THREAD_RATIO_N 1 #define BLIS_THREAD_MAX_IR 1 #define BLIS_THREAD_MAX_JR 1 // -- MEMORY ALLOCATION -------------------------------------------------------- //#define BLIS_TREE_BARRIER //#define BLIS_TREE_BARRIER_ARITY 4 #define BLIS_SIMD_ALIGN_SIZE 64 #define BLIS_SIMD_MAX_SIZE 64 #define BLIS_SIMD_MAX_NUM_REGISTERS 32 /* #ifdef BLIS_NO_HBWMALLOC #include #define BLIS_MALLOC_POOL malloc #define BLIS_FREE_POOL free #else #include #define BLIS_MALLOC_POOL hbw_malloc #define BLIS_FREE_POOL hbw_free #endif */ //#define BLIS_MALLOC_INTL hbw_malloc //#define BLIS_FREE_INTL hbw_free #if 0 // -- LEVEL-3 MICRO-KERNEL CONSTANTS ------------------------------------------- #define BLIS_SGEMM_UKERNEL_PREFERS_CONTIG_ROWS #define BLIS_SGEMM_UKERNEL bli_sgemm_opt_30x16_knc #define BLIS_DEFAULT_MC_S 240 #define BLIS_DEFAULT_KC_S 240 #define BLIS_DEFAULT_NC_S 14400 #define BLIS_DEFAULT_MR_S 30 #define BLIS_DEFAULT_NR_S 16 #define BLIS_PACKDIM_MR_S 32 #define BLIS_PACKDIM_NR_S 16 #if 0 #define BLIS_DGEMM_UKERNEL_PREFERS_CONTIG_ROWS #define BLIS_DGEMM_UKERNEL bli_dgemm_opt_30x8_knc #define BLIS_DEFAULT_MC_D 120 #define BLIS_DEFAULT_KC_D 240 #define BLIS_DEFAULT_NC_D 14400 #define BLIS_DEFAULT_MR_D 30 #define BLIS_DEFAULT_NR_D 8 #define BLIS_PACKDIM_MR_D 32 #define BLIS_PACKDIM_NR_D 8 #elif 0 #define BLIS_DGEMM_UKERNEL_PREFERS_CONTIG_ROWS #define BLIS_DGEMM_UKERNEL bli_dgemm_opt_30x8 #define BLIS_DEFAULT_MC_D 120 #define BLIS_DEFAULT_KC_D 240 #define BLIS_DEFAULT_NC_D 14400 #define BLIS_DEFAULT_MR_D 30 #define BLIS_DEFAULT_NR_D 8 #define BLIS_PACKDIM_MR_D 32 #define BLIS_PACKDIM_NR_D 8 #define BLIS_DPACKM_8XK_KERNEL bli_dpackm_8xk_opt #define BLIS_DPACKM_30XK_KERNEL bli_dpackm_30xk_opt #else #define BLIS_DGEMM_UKERNEL_PREFERS_CONTIG_ROWS #define BLIS_DGEMM_UKERNEL bli_dgemm_opt_24x8 #define BLIS_DEFAULT_MR_D 24 #define BLIS_DEFAULT_NR_D 8 #define BLIS_PACKDIM_MR_D 24 #define BLIS_PACKDIM_NR_D 8 #define BLIS_DEFAULT_MC_D 120 #define BLIS_DEFAULT_KC_D 336 #define BLIS_DEFAULT_NC_D 14400 #define BLIS_DPACKM_8XK_KERNEL bli_dpackm_8xk_opt #define BLIS_DPACKM_24XK_KERNEL bli_dpackm_24xk_opt #endif #define BLIS_MAXIMUM_MC_S (BLIS_DEFAULT_MC_S + BLIS_DEFAULT_MC_S/4) #define BLIS_MAXIMUM_KC_S (BLIS_DEFAULT_KC_S + BLIS_DEFAULT_KC_S/4) #define BLIS_MAXIMUM_NC_S (BLIS_DEFAULT_NC_S + 0) #define BLIS_MAXIMUM_MC_D (BLIS_DEFAULT_MC_D + BLIS_DEFAULT_MC_D/4) #define BLIS_MAXIMUM_KC_D (BLIS_DEFAULT_KC_D + BLIS_DEFAULT_KC_D/4) #define BLIS_MAXIMUM_NC_D (BLIS_DEFAULT_NC_D + 0) #endif //#endif blis-0.9.0/config/knl/make_defs.mk000066400000000000000000000077761422157504600170000ustar00rootroot00000000000000# # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2014, The University of Texas at Austin # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # # Declare the name of the current configuration and add it to the # running list of configurations included by common.mk. THIS_CONFIG := knl #CONFIGS_INCL += $(THIS_CONFIG) # # --- Determine the C compiler and related flags --- # # NOTE: The build system will append these variables with various # general-purpose/configuration-agnostic flags in common.mk. You # may specify additional flags here as needed. CPPROCFLAGS := CMISCFLAGS := CPICFLAGS := CWARNFLAGS := ifneq ($(DEBUG_TYPE),off) CDBGFLAGS := -g endif ifeq ($(DEBUG_TYPE),noopt) COPTFLAGS := -O0 else COPTFLAGS := -O2 endif ifeq ($(DEBUG_TYPE),sde) # Unconditionally disable use of libmemkind in Intel SDE. # Note: The BLIS_DISABLE_MEMKIND macro definition will override # (undefine) the BLIS_ENABLE_MEMKIND macro definition. CPPROCFLAGS += -DBLIS_DISABLE_MEMKIND # This value is normally set by configure and communicated to make via # config.mk, however, the make_defs.mk files (this file) get included # after config.mk, so this definition will override that earlier # definition. MK_ENABLE_MEMKIND := no endif # Flags specific to optimized kernels. CKOPTFLAGS := $(COPTFLAGS) -O3 ifeq ($(CC_VENDOR),gcc) CKVECFLAGS := -mavx512f -mavx512pf -mfpmath=sse -march=knl else ifeq ($(CC_VENDOR),icc) CKVECFLAGS := -xMIC-AVX512 else ifeq ($(CC_VENDOR),clang) CKVECFLAGS := -mavx512f -mavx512pf -mfpmath=sse -march=knl else $(error gcc, icc, or clang is required for this configuration.) endif endif endif # The assembler on OS X won't recognize AVX512 without help. ifneq ($(CC_VENDOR),icc) ifeq ($(OS_NAME),Darwin) CKVECFLAGS += -Wa,-march=knl endif endif # Flags specific to reference kernels. # Note: We use AVX2 for reference kernels instead of AVX-512. CROPTFLAGS := $(CKOPTFLAGS) ifeq ($(CC_VENDOR),gcc) CRVECFLAGS := -march=knl -mno-avx512f -mno-avx512pf -mno-avx512er -mno-avx512cd -funsafe-math-optimizations -ffp-contract=fast else ifeq ($(CC_VENDOR),icc) CRVECFLAGS := -xMIC-AVX512 else ifeq ($(CC_VENDOR),clang) CRVECFLAGS := -march=knl -mno-avx512f -mno-avx512pf -mno-avx512er -mno-avx512cd -funsafe-math-optimizations -ffp-contract=fast else $(error gcc, icc, or clang is required for this configuration.) endif endif endif # Store all of the variables here to new variables containing the # configuration name. $(eval $(call store-make-defs,$(THIS_CONFIG))) blis-0.9.0/config/old/000077500000000000000000000000001422157504600145025ustar00rootroot00000000000000blis-0.9.0/config/old/armv7a/000077500000000000000000000000001422157504600156775ustar00rootroot00000000000000blis-0.9.0/config/old/armv7a/bli_cntx_init_armv7a.c000066400000000000000000000062431422157504600221520ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_cntx_init_armv7a( cntx_t* cntx ) { blksz_t blkszs[ BLIS_NUM_BLKSZS ]; // Set default kernel blocksizes and functions. bli_cntx_init_armv7a_ref( cntx ); // ------------------------------------------------------------------------- // Update the context with optimized native gemm micro-kernels and // their storage preferences. bli_cntx_set_l3_nat_ukrs ( BLIS_GEMM_UKR, BLIS_FLOAT, bli_sgemm_armv7a_asm_4x4, FALSE, BLIS_GEMM_UKR, BLIS_DOUBLE, bli_dgemm_armv7a_asm_4x4, FALSE, BLIS_GEMM_UKR, BLIS_SCOMPLEX, bli_cgemm_armv7a_asm_2x2, FALSE, BLIS_GEMM_UKR, BLIS_DCOMPLEX, bli_zgemm_armv7a_asm_2x2, FALSE, cntx ); // Initialize level-3 blocksize objects with architecture-specific values. // s d c z bli_blksz_init_easy( &blkszs[ BLIS_MR ], 4, 4, 2, 2 ); bli_blksz_init_easy( &blkszs[ BLIS_NR ], 4, 4, 2, 2 ); bli_blksz_init_easy( &blkszs[ BLIS_MC ], 432, 192, 64, 64 ); bli_blksz_init_easy( &blkszs[ BLIS_KC ], 352, 256, 128, 128 ); bli_blksz_init_easy( &blkszs[ BLIS_NC ], 4096, 4096, 4096, 4096 ); // Update the context with the current architecture's register and cache // blocksizes (and multiples) for native execution. bli_cntx_set_blkszs ( BLIS_NAT, 5, BLIS_NC, &blkszs[ BLIS_NC ], BLIS_NR, BLIS_KC, &blkszs[ BLIS_KC ], BLIS_KR, BLIS_MC, &blkszs[ BLIS_MC ], BLIS_MR, BLIS_NR, &blkszs[ BLIS_NR ], BLIS_NR, BLIS_MR, &blkszs[ BLIS_MR ], BLIS_MR, cntx ); } blis-0.9.0/config/old/armv7a/bli_family_armv7a.h000066400000000000000000000057701422157504600214450ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_FAMILY_H #define BLIS_FAMILY_H // -- ARCHITECTURE-SPECIFIC PROTOTYPES ----------------------------------------- // Define the current architecture's name. #define archname armv7a // Include the context initialization function API template. #include "bli_cntx_init_arch.h" #if 0 #define BLIS_SGEMM_UKERNEL bli_sgemm_opt_4x4 #define BLIS_DEFAULT_MR_S 4 #define BLIS_DEFAULT_NR_S 4 #define BLIS_DEFAULT_MC_S 432 #define BLIS_DEFAULT_KC_S 352 #define BLIS_DEFAULT_NC_S 4096 #define BLIS_DGEMM_UKERNEL bli_dgemm_opt_4x4 #define BLIS_DEFAULT_MR_D 4 #define BLIS_DEFAULT_NR_D 4 #define BLIS_DEFAULT_MC_D 192 #define BLIS_DEFAULT_KC_D 256 #define BLIS_DEFAULT_NC_D 4096 #define BLIS_CGEMM_UKERNEL bli_cgemm_opt_4x4 #define BLIS_DEFAULT_MR_C 2 #define BLIS_DEFAULT_NR_C 2 #define BLIS_DEFAULT_MC_C 64 #define BLIS_DEFAULT_KC_C 128 #define BLIS_DEFAULT_NC_C 4096 #define BLIS_ZGEMM_UKERNEL bli_zgemm_opt_4x4 #define BLIS_DEFAULT_MR_Z 2 #define BLIS_DEFAULT_NR_Z 2 #define BLIS_DEFAULT_MC_Z 64 #define BLIS_DEFAULT_KC_Z 128 #define BLIS_DEFAULT_NC_Z 4096 #endif #endif blis-0.9.0/config/old/armv7a/make_defs.mk000066400000000000000000000052131422157504600201470ustar00rootroot00000000000000# # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2014, The University of Texas at Austin # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # # Declare the name of the current configuration and add it to the # running list of configurations included by common.mk. THIS_CONFIG := armv7a #CONFIGS_INCL += $(THIS_CONFIG) # # --- Determine the C compiler and related flags --- # ifeq ($(CC),) CC := gcc CC_VENDOR := gcc endif # Enable IEEE Standard 1003.1-2004 (POSIX.1d). # NOTE: This is needed to enable posix_memalign(). CPPROCFLAGS := -D_POSIX_C_SOURCE=200112L CMISCFLAGS := -std=c99 -mfloat-abi=hard CPICFLAGS := -fPIC CWARNFLAGS := -Wall -Wno-unused-function -Wfatal-errors ifneq ($(DEBUG_TYPE),off) CDBGFLAGS := -g endif ifeq ($(DEBUG_TYPE),noopt) COPTFLAGS := -O0 else COPTFLAGS := -O3 endif CKOPTFLAGS := $(COPTFLAGS) ifeq ($(CC_VENDOR),gcc) CKVECFLAGS := -mfpu=vfpv3 -marm -march=armv7-a else $(error gcc is required for this configuration.) endif # Store all of the variables here to new variables containing the # configuration name. $(eval $(call store-make-defs,$(THIS_CONFIG))) blis-0.9.0/config/old/emscripten/000077500000000000000000000000001422157504600166535ustar00rootroot00000000000000blis-0.9.0/config/old/emscripten/bli_kernel.h000066400000000000000000000146161422157504600211420ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_KERNEL_H #define BLIS_KERNEL_H /* Use the same parameters as non-SIMD PNaCl */ // -- LEVEL-3 MICRO-KERNEL CONSTANTS ------------------------------------------- #define BLIS_SIMD_ALIGN_SIZE 16 // -- Cache blocksizes -- // // Constraints: // // (1) MC must be a multiple of: // (a) MR (for zero-padding purposes) // (b) NR (for zero-padding purposes when MR and NR are "swapped") // (2) NC must be a multiple of // (a) NR (for zero-padding purposes) // (b) MR (for zero-padding purposes when MR and NR are "swapped") // #define BLIS_DEFAULT_MC_S 252 #define BLIS_DEFAULT_KC_S 264 #define BLIS_DEFAULT_NC_S 8196 #define BLIS_DEFAULT_MC_D 1080 #define BLIS_DEFAULT_KC_D 120 #define BLIS_DEFAULT_NC_D 8400 #define BLIS_DEFAULT_MC_C 120 #define BLIS_DEFAULT_KC_C 264 #define BLIS_DEFAULT_NC_C 4092 #define BLIS_DEFAULT_MC_Z 60 #define BLIS_DEFAULT_KC_Z 264 #define BLIS_DEFAULT_NC_Z 2040 // -- Register blocksizes -- #define BLIS_DEFAULT_MR_S 4 #define BLIS_DEFAULT_NR_S 3 #define BLIS_DEFAULT_MR_D 4 #define BLIS_DEFAULT_NR_D 3 #define BLIS_DEFAULT_MR_C 2 #define BLIS_DEFAULT_NR_C 3 #define BLIS_DEFAULT_MR_Z 2 #define BLIS_DEFAULT_NR_Z 3 // NOTE: If the micro-kernel, which is typically unrolled to a factor // of f, handles leftover edge cases (ie: when k % f > 0) then these // register blocksizes in the k dimension can be defined to 1. //#define BLIS_DEFAULT_KR_S 1 //#define BLIS_DEFAULT_KR_D 1 //#define BLIS_DEFAULT_KR_C 1 //#define BLIS_DEFAULT_KR_Z 1 // -- Maximum cache blocksizes (for optimizing edge cases) -- // NOTE: These cache blocksize "extensions" have the same constraints as // the corresponding default blocksizes above. When these values are // larger than the default blocksizes, blocksizes used at edge cases are // enlarged if such an extension would encompass the remaining portion of // the matrix dimension. //#define BLIS_MAXIMUM_MC_S (BLIS_DEFAULT_MC_S + BLIS_DEFAULT_MC_S/4) //#define BLIS_MAXIMUM_KC_S (BLIS_DEFAULT_KC_S + BLIS_DEFAULT_KC_S/4) //#define BLIS_MAXIMUM_NC_S (BLIS_DEFAULT_NC_S + BLIS_DEFAULT_NC_S/4) //#define BLIS_MAXIMUM_MC_D (BLIS_DEFAULT_MC_D + BLIS_DEFAULT_MC_D/4) //#define BLIS_MAXIMUM_KC_D (BLIS_DEFAULT_KC_D + BLIS_DEFAULT_KC_D/4) //#define BLIS_MAXIMUM_NC_D (BLIS_DEFAULT_NC_D + BLIS_DEFAULT_NC_D/4) //#define BLIS_MAXIMUM_MC_C (BLIS_DEFAULT_MC_C + BLIS_DEFAULT_MC_C/4) //#define BLIS_MAXIMUM_KC_C (BLIS_DEFAULT_KC_C + BLIS_DEFAULT_KC_C/4) //#define BLIS_MAXIMUM_NC_C (BLIS_DEFAULT_NC_C + BLIS_DEFAULT_NC_C/4) //#define BLIS_MAXIMUM_MC_Z (BLIS_DEFAULT_MC_Z + BLIS_DEFAULT_MC_Z/4) //#define BLIS_MAXIMUM_KC_Z (BLIS_DEFAULT_KC_Z + BLIS_DEFAULT_KC_Z/4) //#define BLIS_MAXIMUM_NC_Z (BLIS_DEFAULT_NC_Z + BLIS_DEFAULT_NC_Z/4) // -- Packing register blocksize (for packed micro-panels) -- // NOTE: These register blocksize "extensions" determine whether the // leading dimensions used within the packed micro-panels are equal to // or greater than their corresponding register blocksizes above. //#define BLIS_PACKDIM_MR_S (BLIS_DEFAULT_MR_S + ...) //#define BLIS_PACKDIM_NR_S (BLIS_DEFAULT_NR_S + ...) //#define BLIS_PACKDIM_MR_D (BLIS_DEFAULT_MR_D + ...) //#define BLIS_PACKDIM_NR_D (BLIS_DEFAULT_NR_D + ...) //#define BLIS_PACKDIM_MR_C (BLIS_DEFAULT_MR_C + ...) //#define BLIS_PACKDIM_NR_C (BLIS_DEFAULT_NR_C + ...) //#define BLIS_PACKDIM_MR_Z (BLIS_DEFAULT_MR_Z + ...) //#define BLIS_PACKDIM_NR_Z (BLIS_DEFAULT_NR_Z + ...) // -- LEVEL-2 KERNEL CONSTANTS ------------------------------------------------- // -- LEVEL-1F KERNEL CONSTANTS ------------------------------------------------ // -- LEVEL-3 KERNEL DEFINITIONS ----------------------------------------------- // -- gemm -- // -- trsm-related -- // -- LEVEL-1M KERNEL DEFINITIONS ---------------------------------------------- // -- packm -- // -- unpackm -- // -- LEVEL-1F KERNEL DEFINITIONS ---------------------------------------------- // -- axpy2v -- // -- dotaxpyv -- // -- axpyf -- // -- dotxf -- // -- dotxaxpyf -- // -- LEVEL-1V KERNEL DEFINITIONS ---------------------------------------------- // -- addv -- // -- axpyv -- // -- copyv -- // -- dotv -- // -- dotxv -- // -- invertv -- // -- scal2v -- // -- scalv -- // -- setv -- // -- subv -- // -- swapv -- #endif blis-0.9.0/config/old/emscripten/make_defs.mk000066400000000000000000000053051422157504600211250ustar00rootroot00000000000000# # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2014, The University of Texas at Austin # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # # Only include this block of code once. ifndef MAKE_DEFS_MK_INCLUDED MAKE_DEFS_MK_INCLUDED := yes # # --- Development tools definitions -------------------------------------------- # # --- Determine the C compiler and related flags --- CC := emcc CC_VENDOR := emcc # Enable IEEE Standard 1003.1-2004 (POSIX.1d). # NOTE: This is needed to enable posix_memalign(). CPPROCFLAGS := -D_POSIX_C_SOURCE=200112L CMISCFLAGS := -std=c99 CPICFLAGS := -fPIC CDBGFLAGS := #-g4 CWARNFLAGS := -Wall -Wno-unused-function -Wfatal-errors COPTFLAGS := -O2 CKOPTFLAGS := -O3 CKVECFLAGS := # --- Determine the archiver and related flags --- AR := emar RANLIB := emranlib ARFLAGS := cr # --- Determine the linker and related flags --- LINKER := $(CC) SOFLAGS := -shared LDFLAGS := -O3 -s TOTAL_MEMORY=67108864 -s FORCE_ALIGNED_MEMORY=1 -s PRECISE_F32=2 -s GC_SUPPORT=0 # --- Determine JS interpreter --- JSINT := node # end of ifndef MAKE_DEFS_MK_INCLUDED conditional block endif blis-0.9.0/config/old/haswellbb/000077500000000000000000000000001422157504600164455ustar00rootroot00000000000000blis-0.9.0/config/old/haswellbb/bli_cntx_init_haswell.c000066400000000000000000000257011422157504600231620ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // Instantiate prototypes for packm kernels. PACKM_KER_PROT( float, s, packm_6xk_bb4_haswell_ref ) PACKM_KER_PROT( double, d, packm_6xk_bb2_haswell_ref ) // Instantiate prototypes for level-3 kernels. GEMM_UKR_PROT( float, s, gemmbb_haswell_ref ) GEMMTRSM_UKR_PROT( float, s, gemmtrsmbb_l_haswell_ref ) GEMMTRSM_UKR_PROT( float, s, gemmtrsmbb_u_haswell_ref ) TRSM_UKR_PROT( float, s, trsmbb_l_haswell_ref ) TRSM_UKR_PROT( float, s, trsmbb_u_haswell_ref ) GEMM_UKR_PROT( double, d, gemmbb_haswell_ref ) GEMMTRSM_UKR_PROT( double, d, gemmtrsmbb_l_haswell_ref ) GEMMTRSM_UKR_PROT( double, d, gemmtrsmbb_u_haswell_ref ) TRSM_UKR_PROT( double, d, trsmbb_l_haswell_ref ) TRSM_UKR_PROT( double, d, trsmbb_u_haswell_ref ) GEMM_UKR_PROT( scomplex, c, gemmbb_haswell_ref ) GEMMTRSM_UKR_PROT( scomplex, c, gemmtrsmbb_l_haswell_ref ) GEMMTRSM_UKR_PROT( scomplex, c, gemmtrsmbb_u_haswell_ref ) TRSM_UKR_PROT( scomplex, c, trsmbb_l_haswell_ref ) TRSM_UKR_PROT( scomplex, c, trsmbb_u_haswell_ref ) GEMM_UKR_PROT( dcomplex, z, gemmbb_haswell_ref ) GEMMTRSM_UKR_PROT( dcomplex, z, gemmtrsmbb_l_haswell_ref ) GEMMTRSM_UKR_PROT( dcomplex, z, gemmtrsmbb_u_haswell_ref ) TRSM_UKR_PROT( dcomplex, z, trsmbb_l_haswell_ref ) TRSM_UKR_PROT( dcomplex, z, trsmbb_u_haswell_ref ) void bli_cntx_init_haswell( cntx_t* cntx ) { blksz_t blkszs[ BLIS_NUM_BLKSZS ]; blksz_t thresh[ BLIS_NUM_THRESH ]; // Set default kernel blocksizes and functions. bli_cntx_init_haswell_ref( cntx ); // ------------------------------------------------------------------------- // Update the context with optimized native gemm micro-kernels and // their storage preferences. bli_cntx_set_l3_nat_ukrs ( #if 0 8, // gemm BLIS_GEMM_UKR, BLIS_FLOAT, bli_sgemm_haswell_asm_6x16, TRUE, BLIS_GEMM_UKR, BLIS_DOUBLE, bli_dgemm_haswell_asm_6x8, TRUE, BLIS_GEMM_UKR, BLIS_SCOMPLEX, bli_cgemm_haswell_asm_3x8, TRUE, BLIS_GEMM_UKR, BLIS_DCOMPLEX, bli_zgemm_haswell_asm_3x4, TRUE, // gemmtrsm_l BLIS_GEMMTRSM_L_UKR, BLIS_FLOAT, bli_sgemmtrsm_l_haswell_asm_6x16, TRUE, BLIS_GEMMTRSM_L_UKR, BLIS_DOUBLE, bli_dgemmtrsm_l_haswell_asm_6x8, TRUE, // gemmtrsm_u BLIS_GEMMTRSM_U_UKR, BLIS_FLOAT, bli_sgemmtrsm_u_haswell_asm_6x16, TRUE, BLIS_GEMMTRSM_U_UKR, BLIS_DOUBLE, bli_dgemmtrsm_u_haswell_asm_6x8, TRUE, #else 12, BLIS_GEMM_UKR, BLIS_FLOAT, bli_sgemmbb_haswell_ref, FALSE, BLIS_TRSM_L_UKR, BLIS_FLOAT, bli_strsmbb_l_haswell_ref, FALSE, BLIS_TRSM_U_UKR, BLIS_FLOAT, bli_strsmbb_u_haswell_ref, FALSE, BLIS_GEMM_UKR, BLIS_DOUBLE, bli_dgemmbb_haswell_ref, FALSE, BLIS_TRSM_L_UKR, BLIS_DOUBLE, bli_dtrsmbb_l_haswell_ref, FALSE, BLIS_TRSM_U_UKR, BLIS_DOUBLE, bli_dtrsmbb_u_haswell_ref, FALSE, BLIS_GEMM_UKR, BLIS_SCOMPLEX, bli_cgemmbb_haswell_ref, FALSE, BLIS_TRSM_L_UKR, BLIS_SCOMPLEX, bli_ctrsmbb_l_haswell_ref, FALSE, BLIS_TRSM_U_UKR, BLIS_SCOMPLEX, bli_ctrsmbb_u_haswell_ref, FALSE, BLIS_GEMM_UKR, BLIS_DCOMPLEX, bli_zgemmbb_haswell_ref, FALSE, BLIS_TRSM_L_UKR, BLIS_DCOMPLEX, bli_ztrsmbb_l_haswell_ref, FALSE, BLIS_TRSM_U_UKR, BLIS_DCOMPLEX, bli_ztrsmbb_u_haswell_ref, FALSE, #endif cntx ); // Update the context with customized virtual [gemm]trsm micro-kernels. bli_cntx_set_l3_vir_ukrs ( 8, BLIS_GEMMTRSM_L_UKR, BLIS_FLOAT, bli_sgemmtrsmbb_l_haswell_ref, BLIS_GEMMTRSM_U_UKR, BLIS_FLOAT, bli_sgemmtrsmbb_u_haswell_ref, BLIS_GEMMTRSM_L_UKR, BLIS_DOUBLE, bli_dgemmtrsmbb_l_haswell_ref, BLIS_GEMMTRSM_U_UKR, BLIS_DOUBLE, bli_dgemmtrsmbb_u_haswell_ref, BLIS_GEMMTRSM_L_UKR, BLIS_SCOMPLEX, bli_cgemmtrsmbb_l_haswell_ref, BLIS_GEMMTRSM_U_UKR, BLIS_SCOMPLEX, bli_cgemmtrsmbb_u_haswell_ref, BLIS_GEMMTRSM_L_UKR, BLIS_DCOMPLEX, bli_zgemmtrsmbb_l_haswell_ref, BLIS_GEMMTRSM_U_UKR, BLIS_DCOMPLEX, bli_zgemmtrsmbb_u_haswell_ref, cntx ); // Update the context with optimized packm kernels. bli_cntx_set_packm_kers ( 2, BLIS_PACKM_6XK_KER, BLIS_FLOAT, bli_spackm_6xk_bb4_haswell_ref, BLIS_PACKM_6XK_KER, BLIS_DOUBLE, bli_dpackm_6xk_bb2_haswell_ref, cntx ); // Update the context with optimized level-1f kernels. bli_cntx_set_l1f_kers ( 4, // axpyf BLIS_AXPYF_KER, BLIS_FLOAT, bli_saxpyf_zen_int_8, BLIS_AXPYF_KER, BLIS_DOUBLE, bli_daxpyf_zen_int_8, // dotxf BLIS_DOTXF_KER, BLIS_FLOAT, bli_sdotxf_zen_int_8, BLIS_DOTXF_KER, BLIS_DOUBLE, bli_ddotxf_zen_int_8, cntx ); // Update the context with optimized level-1v kernels. bli_cntx_set_l1v_kers ( 10, #if 1 // amaxv BLIS_AMAXV_KER, BLIS_FLOAT, bli_samaxv_zen_int, BLIS_AMAXV_KER, BLIS_DOUBLE, bli_damaxv_zen_int, #endif // axpyv #if 0 BLIS_AXPYV_KER, BLIS_FLOAT, bli_saxpyv_zen_int, BLIS_AXPYV_KER, BLIS_DOUBLE, bli_daxpyv_zen_int, #else BLIS_AXPYV_KER, BLIS_FLOAT, bli_saxpyv_zen_int10, BLIS_AXPYV_KER, BLIS_DOUBLE, bli_daxpyv_zen_int10, #endif // dotv BLIS_DOTV_KER, BLIS_FLOAT, bli_sdotv_zen_int, BLIS_DOTV_KER, BLIS_DOUBLE, bli_ddotv_zen_int, // dotxv BLIS_DOTXV_KER, BLIS_FLOAT, bli_sdotxv_zen_int, BLIS_DOTXV_KER, BLIS_DOUBLE, bli_ddotxv_zen_int, // scalv #if 0 BLIS_SCALV_KER, BLIS_FLOAT, bli_sscalv_zen_int, BLIS_SCALV_KER, BLIS_DOUBLE, bli_dscalv_zen_int, #else BLIS_SCALV_KER, BLIS_FLOAT, bli_sscalv_zen_int10, BLIS_SCALV_KER, BLIS_DOUBLE, bli_dscalv_zen_int10, #endif cntx ); // Initialize level-3 blocksize objects with architecture-specific values. // s d c z #if 0 bli_blksz_init_easy( &blkszs[ BLIS_MR ], 6, 6, 3, 3 ); bli_blksz_init_easy( &blkszs[ BLIS_NR ], 16, 8, 8, 4 ); bli_blksz_init_easy( &blkszs[ BLIS_MC ], 168, 72, 75, 192 ); bli_blksz_init_easy( &blkszs[ BLIS_KC ], 256, 256, 256, 256 ); bli_blksz_init_easy( &blkszs[ BLIS_NC ], 4080, 4080, 4080, 4080 ); #else bli_blksz_init_easy( &blkszs[ BLIS_MR ], 24, 12, 12, 6 ); bli_blksz_init ( &blkszs[ BLIS_NR ], 6, 6, 6, 6, 24, 12, 6, 6 ); bli_blksz_init_easy( &blkszs[ BLIS_MC ], 144, 72, 72, 36 ); bli_blksz_init_easy( &blkszs[ BLIS_KC ], 256, 256, 256, 256 ); bli_blksz_init_easy( &blkszs[ BLIS_NC ], 8160, 4080, 4080, 2076 ); #endif bli_blksz_init_easy( &blkszs[ BLIS_AF ], 8, 8, 8, 8 ); bli_blksz_init_easy( &blkszs[ BLIS_DF ], 8, 8, 8, 8 ); // Update the context with the current architecture's register and cache // blocksizes (and multiples) for native execution. bli_cntx_set_blkszs ( BLIS_NAT, 7, // level-3 BLIS_NC, &blkszs[ BLIS_NC ], BLIS_NR, BLIS_KC, &blkszs[ BLIS_KC ], BLIS_KR, BLIS_MC, &blkszs[ BLIS_MC ], BLIS_MR, BLIS_NR, &blkszs[ BLIS_NR ], BLIS_NR, BLIS_MR, &blkszs[ BLIS_MR ], BLIS_MR, // level-1f BLIS_AF, &blkszs[ BLIS_AF ], BLIS_AF, BLIS_DF, &blkszs[ BLIS_DF ], BLIS_DF, cntx ); // ------------------------------------------------------------------------- // Initialize sup thresholds with architecture-appropriate values. // s d c z bli_blksz_init_easy( &thresh[ BLIS_MT ], -1, 1, -1, -1 ); bli_blksz_init_easy( &thresh[ BLIS_NT ], -1, 1, -1, -1 ); bli_blksz_init_easy( &thresh[ BLIS_KT ], -1, 1, -1, -1 ); // Initialize the context with the sup thresholds. bli_cntx_set_l3_sup_thresh ( 3, BLIS_MT, &thresh[ BLIS_MT ], BLIS_NT, &thresh[ BLIS_NT ], BLIS_KT, &thresh[ BLIS_KT ], cntx ); // Update the context with optimized small/unpacked gemm kernels. bli_cntx_set_l3_sup_kers ( 8, //BLIS_RCR, BLIS_DOUBLE, bli_dgemmsup_r_haswell_ref, BLIS_RRR, BLIS_DOUBLE, bli_dgemmsup_rv_haswell_asm_6x8m, TRUE, BLIS_RRC, BLIS_DOUBLE, bli_dgemmsup_rd_haswell_asm_6x8m, TRUE, BLIS_RCR, BLIS_DOUBLE, bli_dgemmsup_rv_haswell_asm_6x8m, TRUE, BLIS_RCC, BLIS_DOUBLE, bli_dgemmsup_rv_haswell_asm_6x8n, TRUE, BLIS_CRR, BLIS_DOUBLE, bli_dgemmsup_rv_haswell_asm_6x8m, TRUE, BLIS_CRC, BLIS_DOUBLE, bli_dgemmsup_rd_haswell_asm_6x8n, TRUE, BLIS_CCR, BLIS_DOUBLE, bli_dgemmsup_rv_haswell_asm_6x8n, TRUE, BLIS_CCC, BLIS_DOUBLE, bli_dgemmsup_rv_haswell_asm_6x8n, TRUE, cntx ); // Initialize level-3 sup blocksize objects with architecture-specific // values. // s d c z bli_blksz_init ( &blkszs[ BLIS_MR ], -1, 6, -1, -1, -1, 9, -1, -1 ); bli_blksz_init_easy( &blkszs[ BLIS_NR ], -1, 8, -1, -1 ); bli_blksz_init_easy( &blkszs[ BLIS_MC ], -1, 72, -1, -1 ); bli_blksz_init_easy( &blkszs[ BLIS_KC ], -1, 256, -1, -1 ); bli_blksz_init_easy( &blkszs[ BLIS_NC ], -1, 4080, -1, -1 ); // Update the context with the current architecture's register and cache // blocksizes for small/unpacked level-3 problems. bli_cntx_set_l3_sup_blkszs ( 5, BLIS_NC, &blkszs[ BLIS_NC ], BLIS_KC, &blkszs[ BLIS_KC ], BLIS_MC, &blkszs[ BLIS_MC ], BLIS_NR, &blkszs[ BLIS_NR ], BLIS_MR, &blkszs[ BLIS_MR ], cntx ); } blis-0.9.0/config/old/haswellbb/bli_family_haswell.h000066400000000000000000000122601422157504600224450ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ //#ifndef BLIS_FAMILY_H //#define BLIS_FAMILY_H #define BLIS_POOL_ADDR_ALIGN_SIZE_A 4096 #define BLIS_POOL_ADDR_ALIGN_SIZE_B 4096 #define BLIS_POOL_ADDR_OFFSET_SIZE_A 32 #define BLIS_POOL_ADDR_OFFSET_SIZE_B 64 // Disable right-side hemm, symm, and trmm[3] to accommodate the broadcasting of // elements within the packed matrix B. #define BLIS_DISABLE_HEMM_RIGHT #define BLIS_DISABLE_SYMM_RIGHT #define BLIS_DISABLE_TRMM_RIGHT #define BLIS_DISABLE_TRMM3_RIGHT #if 0 // -- LEVEL-3 MICRO-KERNEL CONSTANTS AND DEFINITIONS --------------------------- // -- sgemm micro-kernel -- #if 0 #define BLIS_SGEMM_UKERNEL bli_sgemm_asm_4x24 #define BLIS_DEFAULT_MC_S 256 #define BLIS_DEFAULT_KC_S 256 #define BLIS_DEFAULT_NC_S 4080 #define BLIS_DEFAULT_MR_S 4 #define BLIS_DEFAULT_NR_S 24 #define BLIS_SGEMM_UKERNEL_PREFERS_CONTIG_ROWS #endif #if 1 #define BLIS_SGEMM_UKERNEL bli_sgemm_asm_6x16 #define BLIS_DEFAULT_MC_S 144 #define BLIS_DEFAULT_KC_S 256 #define BLIS_DEFAULT_NC_S 4080 #define BLIS_DEFAULT_MR_S 6 #define BLIS_DEFAULT_NR_S 16 #define BLIS_SGEMM_UKERNEL_PREFERS_CONTIG_ROWS #endif #if 0 #define BLIS_SGEMM_UKERNEL bli_sgemm_asm_16x6 #define BLIS_DEFAULT_MC_S 144 #define BLIS_DEFAULT_KC_S 256 #define BLIS_DEFAULT_NC_S 4080 #define BLIS_DEFAULT_MR_S 16 #define BLIS_DEFAULT_NR_S 6 #endif // -- dgemm micro-kernel -- #if 0 #define BLIS_DGEMM_UKERNEL bli_dgemm_asm_4x12 #define BLIS_DEFAULT_MC_D 152 #define BLIS_DEFAULT_KC_D 160 #define BLIS_DEFAULT_NC_D 4080 #define BLIS_DEFAULT_MR_D 4 #define BLIS_DEFAULT_NR_D 12 #define BLIS_DGEMM_UKERNEL_PREFERS_CONTIG_ROWS #endif #if 1 #define BLIS_DGEMM_UKERNEL bli_dgemm_asm_6x8 #define BLIS_DEFAULT_MC_D 72 #define BLIS_DEFAULT_KC_D 256 #define BLIS_DEFAULT_NC_D 4080 #define BLIS_DEFAULT_MR_D 6 #define BLIS_DEFAULT_NR_D 8 #define BLIS_DGEMM_UKERNEL_PREFERS_CONTIG_ROWS #endif #if 0 #define BLIS_DGEMM_UKERNEL bli_dgemm_asm_8x6 #define BLIS_DEFAULT_MC_D 72 #define BLIS_DEFAULT_KC_D 256 #define BLIS_DEFAULT_NC_D 4080 #define BLIS_DEFAULT_MR_D 8 #define BLIS_DEFAULT_NR_D 6 #endif // -- cgemm micro-kernel -- #if 1 #define BLIS_CGEMM_UKERNEL bli_cgemm_asm_3x8 #define BLIS_DEFAULT_MC_C 144 #define BLIS_DEFAULT_KC_C 256 #define BLIS_DEFAULT_NC_C 4080 #define BLIS_DEFAULT_MR_C 3 #define BLIS_DEFAULT_NR_C 8 #define BLIS_CGEMM_UKERNEL_PREFERS_CONTIG_ROWS #endif #if 0 #define BLIS_CGEMM_UKERNEL bli_cgemm_asm_8x3 #define BLIS_DEFAULT_MC_C 144 #define BLIS_DEFAULT_KC_C 256 #define BLIS_DEFAULT_NC_C 4080 #define BLIS_DEFAULT_MR_C 8 #define BLIS_DEFAULT_NR_C 3 #endif // -- zgemm micro-kernel -- #if 1 #define BLIS_ZGEMM_UKERNEL bli_zgemm_asm_3x4 #define BLIS_DEFAULT_MC_Z 72 #define BLIS_DEFAULT_KC_Z 256 #define BLIS_DEFAULT_NC_Z 4080 #define BLIS_DEFAULT_MR_Z 3 #define BLIS_DEFAULT_NR_Z 4 #define BLIS_ZGEMM_UKERNEL_PREFERS_CONTIG_ROWS #endif #if 0 #define BLIS_ZGEMM_UKERNEL bli_zgemm_asm_4x3 #define BLIS_DEFAULT_MC_Z 72 #define BLIS_DEFAULT_KC_Z 256 #define BLIS_DEFAULT_NC_Z 4080 #define BLIS_DEFAULT_MR_Z 4 #define BLIS_DEFAULT_NR_Z 3 #endif #endif //#endif blis-0.9.0/config/old/haswellbb/make_defs.mk000066400000000000000000000064101422157504600207150ustar00rootroot00000000000000# # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2014, The University of Texas at Austin # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # # Declare the name of the current configuration and add it to the # running list of configurations included by common.mk. THIS_CONFIG := haswell #CONFIGS_INCL += $(THIS_CONFIG) # # --- Determine the C compiler and related flags --- # # NOTE: The build system will append these variables with various # general-purpose/configuration-agnostic flags in common.mk. You # may specify additional flags here as needed. CPPROCFLAGS := CMISCFLAGS := CPICFLAGS := CWARNFLAGS := ifneq ($(DEBUG_TYPE),off) CDBGFLAGS := -g endif ifeq ($(DEBUG_TYPE),noopt) COPTFLAGS := -O0 else COPTFLAGS := -O3 endif # Flags specific to optimized kernels. CKOPTFLAGS := $(COPTFLAGS) ifeq ($(CC_VENDOR),gcc) CKVECFLAGS := -mavx2 -mfma -mfpmath=sse -march=haswell ifeq ($(GCC_OT_4_9_0),yes) # If gcc is older than 4.9.0, we must use a different label for -march. CKVECFLAGS := -mavx2 -mfma -mfpmath=sse -march=core-avx2 endif else ifeq ($(CC_VENDOR),icc) CKVECFLAGS := -xCORE-AVX2 else ifeq ($(CC_VENDOR),clang) CKVECFLAGS := -mavx2 -mfma -mfpmath=sse -march=haswell else $(error gcc, icc, or clang is required for this configuration.) endif endif endif # Flags specific to reference kernels. CROPTFLAGS := $(CKOPTFLAGS) ifeq ($(CC_VENDOR),gcc) CRVECFLAGS := $(CKVECFLAGS) -funsafe-math-optimizations -ffp-contract=fast else ifeq ($(CC_VENDOR),clang) CRVECFLAGS := $(CKVECFLAGS) -funsafe-math-optimizations -ffp-contract=fast else CRVECFLAGS := $(CKVECFLAGS) endif endif # Store all of the variables here to new variables containing the # configuration name. $(eval $(call store-make-defs,$(THIS_CONFIG))) blis-0.9.0/config/old/loongson3a/000077500000000000000000000000001422157504600165645ustar00rootroot00000000000000blis-0.9.0/config/old/loongson3a/bli_kernel.h000066400000000000000000000146231422157504600210510ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_KERNEL_H #define BLIS_KERNEL_H // -- LEVEL-3 MICRO-KERNEL CONSTANTS ------------------------------------------- #define BLIS_SIMD_ALIGN_SIZE 16 // -- Cache blocksizes -- // // Constraints: // // (1) MC must be a multiple of: // (a) MR (for zero-padding purposes) // (b) NR (for zero-padding purposes when MR and NR are "swapped") // (2) NC must be a multiple of // (a) NR (for zero-padding purposes) // (b) MR (for zero-padding purposes when MR and NR are "swapped") // #define BLIS_DEFAULT_MC_S 256 #define BLIS_DEFAULT_KC_S 256 #define BLIS_DEFAULT_NC_S 8192 #define BLIS_DEFAULT_MC_D 32 #define BLIS_DEFAULT_KC_D 128 #define BLIS_DEFAULT_NC_D 1024 #define BLIS_DEFAULT_MC_C 128 #define BLIS_DEFAULT_KC_C 256 #define BLIS_DEFAULT_NC_C 4096 #define BLIS_DEFAULT_MC_Z 64 #define BLIS_DEFAULT_KC_Z 256 #define BLIS_DEFAULT_NC_Z 2048 // -- Register blocksizes -- #define BLIS_DEFAULT_MR_S 8 #define BLIS_DEFAULT_NR_S 4 #define BLIS_DEFAULT_MR_D 4 #define BLIS_DEFAULT_NR_D 4 #define BLIS_DEFAULT_MR_C 8 #define BLIS_DEFAULT_NR_C 4 #define BLIS_DEFAULT_MR_Z 8 #define BLIS_DEFAULT_NR_Z 4 // NOTE: If the micro-kernel, which is typically unrolled to a factor // of f, handles leftover edge cases (ie: when k % f > 0) then these // register blocksizes in the k dimension can be defined to 1. //#define BLIS_DEFAULT_KR_S 1 //#define BLIS_DEFAULT_KR_D 1 //#define BLIS_DEFAULT_KR_C 1 //#define BLIS_DEFAULT_KR_Z 1 // -- Maximum cache blocksizes (for optimizing edge cases) -- // NOTE: These cache blocksize "extensions" have the same constraints as // the corresponding default blocksizes above. When these values are // larger than the default blocksizes, blocksizes used at edge cases are // enlarged if such an extension would encompass the remaining portion of // the matrix dimension. //#define BLIS_MAXIMUM_MC_S (BLIS_DEFAULT_MC_S + BLIS_DEFAULT_MC_S/4) //#define BLIS_MAXIMUM_KC_S (BLIS_DEFAULT_KC_S + BLIS_DEFAULT_KC_S/4) //#define BLIS_MAXIMUM_NC_S (BLIS_DEFAULT_NC_S + BLIS_DEFAULT_NC_S/4) //#define BLIS_MAXIMUM_MC_D (BLIS_DEFAULT_MC_D + BLIS_DEFAULT_MC_D/4) //#define BLIS_MAXIMUM_KC_D (BLIS_DEFAULT_KC_D + BLIS_DEFAULT_KC_D/4) //#define BLIS_MAXIMUM_NC_D (BLIS_DEFAULT_NC_D + BLIS_DEFAULT_NC_D/4) //#define BLIS_MAXIMUM_MC_C (BLIS_DEFAULT_MC_C + BLIS_DEFAULT_MC_C/4) //#define BLIS_MAXIMUM_KC_C (BLIS_DEFAULT_KC_C + BLIS_DEFAULT_KC_C/4) //#define BLIS_MAXIMUM_NC_C (BLIS_DEFAULT_NC_C + BLIS_DEFAULT_NC_C/4) //#define BLIS_MAXIMUM_MC_Z (BLIS_DEFAULT_MC_Z + BLIS_DEFAULT_MC_Z/4) //#define BLIS_MAXIMUM_KC_Z (BLIS_DEFAULT_KC_Z + BLIS_DEFAULT_KC_Z/4) //#define BLIS_MAXIMUM_NC_Z (BLIS_DEFAULT_NC_Z + BLIS_DEFAULT_NC_Z/4) // -- Packing register blocksize (for packed micro-panels) -- // NOTE: These register blocksize "extensions" determine whether the // leading dimensions used within the packed micro-panels are equal to // or greater than their corresponding register blocksizes above. //#define BLIS_PACKDIM_MR_S (BLIS_DEFAULT_MR_S + ...) //#define BLIS_PACKDIM_NR_S (BLIS_DEFAULT_NR_S + ...) //#define BLIS_PACKDIM_MR_D (BLIS_DEFAULT_MR_D + ...) //#define BLIS_PACKDIM_NR_D (BLIS_DEFAULT_NR_D + ...) //#define BLIS_PACKDIM_MR_C (BLIS_DEFAULT_MR_C + ...) //#define BLIS_PACKDIM_NR_C (BLIS_DEFAULT_NR_C + ...) //#define BLIS_PACKDIM_MR_Z (BLIS_DEFAULT_MR_Z + ...) //#define BLIS_PACKDIM_NR_Z (BLIS_DEFAULT_NR_Z + ...) // -- LEVEL-2 KERNEL CONSTANTS ------------------------------------------------- // -- LEVEL-1F KERNEL CONSTANTS ------------------------------------------------ // -- LEVEL-3 KERNEL DEFINITIONS ----------------------------------------------- // -- gemm -- #define BLIS_DGEMM_UKERNEL bli_dgemm_opt_4x4 // -- trsm-related -- // -- LEVEL-1M KERNEL DEFINITIONS ---------------------------------------------- // -- packm -- // -- unpackm -- // -- LEVEL-1F KERNEL DEFINITIONS ---------------------------------------------- // -- axpy2v -- // -- dotaxpyv -- // -- axpyf -- // -- dotxf -- // -- dotxaxpyf -- // -- LEVEL-1V KERNEL DEFINITIONS ---------------------------------------------- // -- addv -- // -- axpyv -- // -- copyv -- // -- dotv -- // -- dotxv -- // -- invertv -- // -- scal2v -- // -- scalv -- // -- setv -- // -- subv -- // -- swapv -- #endif blis-0.9.0/config/old/loongson3a/make_defs.mk000066400000000000000000000052121422157504600210330ustar00rootroot00000000000000# # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2014, The University of Texas at Austin # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # # Declare the name of the current configuration and add it to the # running list of configurations included by common.mk. THIS_CONFIG := loongson3a #CONFIGS_INCL += $(THIS_CONFIG) # # --- Determine the C compiler and related flags --- # ifeq ($(CC),) CC := gcc CC_VENDOR := gcc endif # Enable IEEE Standard 1003.1-2004 (POSIX.1d). # NOTE: This is needed to enable posix_memalign(). CPPROCFLAGS := -D_POSIX_C_SOURCE=200112L -mabi=64 CMISCFLAGS := -std=c99 CPICFLAGS := -fPIC CWARNFLAGS := -Wall -Wno-unused-function -Wfatal-errors ifneq ($(DEBUG_TYPE),off) CDBGFLAGS := -g endif ifeq ($(DEBUG_TYPE),noopt) COPTFLAGS := -O0 else COPTFLAGS := -O3 -mtune=loongson3a endif CKOPTFLAGS := $(COPTFLAGS) ifeq ($(CC_VENDOR),gcc) CKVECFLAGS := -march=loongson3a else $(error gcc is required for this configuration.) endif # Store all of the variables here to new variables containing the # configuration name. $(eval $(call store-make-defs,$(THIS_CONFIG))) blis-0.9.0/config/old/newarch/000077500000000000000000000000001422157504600161315ustar00rootroot00000000000000blis-0.9.0/config/old/newarch/bli_kernel.h000066400000000000000000000033001422157504600204040ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_KERNEL_H #define BLIS_KERNEL_H #endif blis-0.9.0/config/old/newarch/make_defs.mk000066400000000000000000000053421422157504600204040ustar00rootroot00000000000000#!/bin/bash # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2014, The University of Texas at Austin # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # # Declare the name of the current configuration and add it to the # running list of configurations included by common.mk. THIS_CONFIG := newarch #CONFIGS_INCL += $(THIS_CONFIG) # # --- Determine the C compiler and related flags --- # ifeq ($(CC),) CC := gcc CC_VENDOR := gcc endif # Enable IEEE Standard 1003.1-2004 (POSIX.1d). # NOTE: This is needed to enable posix_memalign(). CPPROCFLAGS := -D_POSIX_C_SOURCE=200112L CMISCFLAGS := -std=c99 CPICFLAGS := -fPIC CWARNFLAGS := -Wall -Wno-unused-function -Wfatal-errors ifneq ($(DEBUG_TYPE),off) CDBGFLAGS := -g endif ifeq ($(DEBUG_TYPE),noopt) COPTFLAGS := -O0 else COPTFLAGS := -O2 endif CKOPTFLAGS := $(COPTFLAGS) ifeq ($(CC_VENDOR),gcc) CKVECFLAGS := else ifeq ($(CC_VENDOR),icc) CKVECFLAGS := else ifeq ($(CC_VENDOR),clang) CKVECFLAGS := else $(error gcc, icc, or clang is required for this configuration.) endif endif endif # Store all of the variables here to new variables containing the # configuration name. $(eval $(call store-make-defs,$(THIS_CONFIG))) blis-0.9.0/config/old/pnacl/000077500000000000000000000000001422157504600155775ustar00rootroot00000000000000blis-0.9.0/config/old/pnacl/bli_kernel.h000066400000000000000000000172151422157504600200640ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_KERNEL_H #define BLIS_KERNEL_H /* * SIMD-enabled (SP only) PNaCl shipped in Chrome 36 and it is not backward-compatible. * Therefore, if compilation targets an older Chrome release, we use scalar kernels. * The target Chrome version is indicated by PPAPI_MACRO defined in the header below. */ #include // -- LEVEL-3 MICRO-KERNEL CONSTANTS ------------------------------------------- #define BLIS_SIMD_ALIGN_SIZE 16 // -- Cache blocksizes -- // // Constraints: // // (1) MC must be a multiple of: // (a) MR (for zero-padding purposes) // (b) NR (for zero-padding purposes when MR and NR are "swapped") // (2) NC must be a multiple of // (a) NR (for zero-padding purposes) // (b) MR (for zero-padding purposes when MR and NR are "swapped") // #if PPAPI_RELEASE >= 36 #define BLIS_DEFAULT_MC_S 256 #define BLIS_DEFAULT_KC_S 256 #define BLIS_DEFAULT_NC_S 8192 #else #define BLIS_DEFAULT_MC_S 252 #define BLIS_DEFAULT_KC_S 264 #define BLIS_DEFAULT_NC_S 8196 #endif #define BLIS_DEFAULT_MC_D 1080 #define BLIS_DEFAULT_KC_D 120 #define BLIS_DEFAULT_NC_D 8400 #if PPAPI_RELEASE >= 36 #define BLIS_DEFAULT_MC_C 128 #define BLIS_DEFAULT_KC_C 256 #define BLIS_DEFAULT_NC_C 4096 #else #define BLIS_DEFAULT_MC_C 120 #define BLIS_DEFAULT_KC_C 264 #define BLIS_DEFAULT_NC_C 4092 #endif #define BLIS_DEFAULT_MC_Z 60 #define BLIS_DEFAULT_KC_Z 264 #define BLIS_DEFAULT_NC_Z 2040 // -- Register blocksizes -- #if PPAPI_RELEASE >= 36 #define BLIS_DEFAULT_MR_S 8 #define BLIS_DEFAULT_NR_S 4 #else #define BLIS_DEFAULT_MR_S 4 #define BLIS_DEFAULT_NR_S 3 #endif #define BLIS_DEFAULT_MR_D 4 #define BLIS_DEFAULT_NR_D 3 #if PPAPI_RELEASE >= 36 #define BLIS_DEFAULT_MR_C 4 #define BLIS_DEFAULT_NR_C 4 #else #define BLIS_DEFAULT_MR_C 2 #define BLIS_DEFAULT_NR_C 3 #endif #define BLIS_DEFAULT_MR_Z 2 #define BLIS_DEFAULT_NR_Z 3 // NOTE: If the micro-kernel, which is typically unrolled to a factor // of f, handles leftover edge cases (ie: when k % f > 0) then these // register blocksizes in the k dimension can be defined to 1. //#define BLIS_DEFAULT_KR_S 1 //#define BLIS_DEFAULT_KR_D 1 //#define BLIS_DEFAULT_KR_C 1 //#define BLIS_DEFAULT_KR_Z 1 // -- Maximum cache blocksizes (for optimizing edge cases) -- // NOTE: These cache blocksize "extensions" have the same constraints as // the corresponding default blocksizes above. When these values are // larger than the default blocksizes, blocksizes used at edge cases are // enlarged if such an extension would encompass the remaining portion of // the matrix dimension. //#define BLIS_MAXIMUM_MC_S (BLIS_DEFAULT_MC_S + BLIS_DEFAULT_MC_S/4) //#define BLIS_MAXIMUM_KC_S (BLIS_DEFAULT_KC_S + BLIS_DEFAULT_KC_S/4) //#define BLIS_MAXIMUM_NC_S (BLIS_DEFAULT_NC_S + BLIS_DEFAULT_NC_S/4) //#define BLIS_MAXIMUM_MC_D (BLIS_DEFAULT_MC_D + BLIS_DEFAULT_MC_D/4) //#define BLIS_MAXIMUM_KC_D (BLIS_DEFAULT_KC_D + BLIS_DEFAULT_KC_D/4) //#define BLIS_MAXIMUM_NC_D (BLIS_DEFAULT_NC_D + BLIS_DEFAULT_NC_D/4) //#define BLIS_MAXIMUM_MC_C (BLIS_DEFAULT_MC_C + BLIS_DEFAULT_MC_C/4) //#define BLIS_MAXIMUM_KC_C (BLIS_DEFAULT_KC_C + BLIS_DEFAULT_KC_C/4) //#define BLIS_MAXIMUM_NC_C (BLIS_DEFAULT_NC_C + BLIS_DEFAULT_NC_C/4) //#define BLIS_MAXIMUM_MC_Z (BLIS_DEFAULT_MC_Z + BLIS_DEFAULT_MC_Z/4) //#define BLIS_MAXIMUM_KC_Z (BLIS_DEFAULT_KC_Z + BLIS_DEFAULT_KC_Z/4) //#define BLIS_MAXIMUM_NC_Z (BLIS_DEFAULT_NC_Z + BLIS_DEFAULT_NC_Z/4) // -- Packing register blocksize (for packed micro-panels) -- // NOTE: These register blocksize "extensions" determine whether the // leading dimensions used within the packed micro-panels are equal to // or greater than their corresponding register blocksizes above. //#define BLIS_PACKDIM_MR_S (BLIS_DEFAULT_MR_S + ...) //#define BLIS_PACKDIM_NR_S (BLIS_DEFAULT_NR_S + ...) //#define BLIS_PACKDIM_MR_D (BLIS_DEFAULT_MR_D + ...) //#define BLIS_PACKDIM_NR_D (BLIS_DEFAULT_NR_D + ...) //#define BLIS_PACKDIM_MR_C (BLIS_DEFAULT_MR_C + ...) //#define BLIS_PACKDIM_NR_C (BLIS_DEFAULT_NR_C + ...) //#define BLIS_PACKDIM_MR_Z (BLIS_DEFAULT_MR_Z + ...) //#define BLIS_PACKDIM_NR_Z (BLIS_DEFAULT_NR_Z + ...) // -- LEVEL-2 KERNEL CONSTANTS ------------------------------------------------- // -- LEVEL-1F KERNEL CONSTANTS ------------------------------------------------ // -- LEVEL-3 KERNEL DEFINITIONS ----------------------------------------------- // -- gemm -- #if PPAPI_RELEASE >= 36 #define BLIS_SGEMM_UKERNEL bli_sgemm_opt #define BLIS_CGEMM_UKERNEL bli_cgemm_opt #endif // -- trsm-related -- // -- LEVEL-1M KERNEL DEFINITIONS ---------------------------------------------- // -- packm -- // -- unpackm -- // -- LEVEL-1F KERNEL DEFINITIONS ---------------------------------------------- // -- axpy2v -- // -- dotaxpyv -- // -- axpyf -- // -- dotxf -- // -- dotxaxpyf -- // -- LEVEL-1V KERNEL DEFINITIONS ---------------------------------------------- // -- addv -- // -- axpyv -- #if PPAPI_RELEASE >= 36 #define BLIS_SAXPYV_KERNEL bli_saxpyv_opt #define BLIS_CAXPYV_KERNEL bli_caxpyv_opt #endif // -- copyv -- // -- dotv -- #define BLIS_SDOTV_KERNEL bli_sdotv_opt #define BLIS_DDOTV_KERNEL bli_ddotv_opt #define BLIS_CDOTV_KERNEL bli_cdotv_opt #define BLIS_ZDOTV_KERNEL bli_zdotv_opt // -- dotxv -- // -- invertv -- // -- scal2v -- // -- scalv -- // -- setv -- // -- subv -- // -- swapv -- #endif blis-0.9.0/config/old/pnacl/make_defs.mk000066400000000000000000000056411422157504600200540ustar00rootroot00000000000000# # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2014, The University of Texas at Austin # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # # Only include this block of code once. ifndef MAKE_DEFS_MK_INCLUDED MAKE_DEFS_MK_INCLUDED := yes # # --- Development tools definitions -------------------------------------------- # # --- Determine the C compiler and related flags --- CC := pnacl-clang CC_VENDOR := pnacl-clang # Enable IEEE Standard 1003.1-2004 (POSIX.1d). # NOTE: This is needed to enable posix_memalign(). CPPROCFLAGS := -D_POSIX_C_SOURCE=200112L CMISCFLAGS := -std=gnu11 -I$(NACL_SDK_ROOT)/include CPICFLAGS := CDBGFLAGS := -g CWARNFLAGS := -Wall -Wno-unused-function -Wfatal-errors COPTFLAGS := -O3 CKOPTFLAGS := $(COPTFLAGS) -ffast-math CKVECFLAGS := # --- Determine the archiver and related flags --- AR := pnacl-ar ARFLAGS := rcs # --- Determine the linker and related flags --- LINKER := $(CC) SOFLAGS := ifneq ($(CC_VENDOR),icc) LDFLAGS := -lm endif # --- Determine the finalizer and related flags --- FINALIZER := pnacl-finalize FINFLAGS := # --- Determine the translator and related flags --- TRANSLATOR := pnacl-translate TRNSFLAGS := -O3 TRNSAMD64FLAGS := -arch x86-64 TRNSX86FLAGS := -arch i686 TRNSARMFLAGS := -arch armv7 # end of ifndef MAKE_DEFS_MK_INCLUDED conditional block endif blis-0.9.0/config/penryn/000077500000000000000000000000001422157504600152375ustar00rootroot00000000000000blis-0.9.0/config/penryn/bli_cntx_init_penryn.c000066400000000000000000000065111422157504600216260ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_cntx_init_penryn( cntx_t* cntx ) { blksz_t blkszs[ BLIS_NUM_BLKSZS ]; // Set default kernel blocksizes and functions. bli_cntx_init_penryn_ref( cntx ); // ------------------------------------------------------------------------- // Update the context with optimized native gemm micro-kernels and // their storage preferences. bli_cntx_set_l3_nat_ukrs ( 4, BLIS_GEMM_UKR, BLIS_FLOAT, bli_sgemm_penryn_asm_8x4, FALSE, BLIS_GEMM_UKR, BLIS_DOUBLE, bli_dgemm_penryn_asm_4x4, FALSE, //BLIS_GEMM_UKR, BLIS_SCOMPLEX, bli_cgemm_penryn_asm_8x4, FALSE, //BLIS_GEMM_UKR, BLIS_DCOMPLEX, bli_zgemm_penryn_asm_4x4, FALSE, BLIS_GEMMTRSM_L_UKR, BLIS_DOUBLE, bli_dgemmtrsm_l_penryn_asm_4x4, FALSE, BLIS_GEMMTRSM_U_UKR, BLIS_DOUBLE, bli_dgemmtrsm_u_penryn_asm_4x4, FALSE, cntx ); // Initialize level-3 blocksize objects with architecture-specific values. // s d c z bli_blksz_init_easy( &blkszs[ BLIS_MR ], 8, 4, 0, 0 ); bli_blksz_init_easy( &blkszs[ BLIS_NR ], 4, 4, 0, 0 ); bli_blksz_init_easy( &blkszs[ BLIS_MC ], 768, 384, 0, 0 ); bli_blksz_init_easy( &blkszs[ BLIS_KC ], 384, 384, 0, 0 ); bli_blksz_init_easy( &blkszs[ BLIS_NC ], 4096, 4096, 0, 0 ); // Update the context with the current architecture's register and cache // blocksizes (and multiples) for native execution. bli_cntx_set_blkszs ( BLIS_NAT, 5, BLIS_NC, &blkszs[ BLIS_NC ], BLIS_NR, BLIS_KC, &blkszs[ BLIS_KC ], BLIS_KR, BLIS_MC, &blkszs[ BLIS_MC ], BLIS_MR, BLIS_NR, &blkszs[ BLIS_NR ], BLIS_NR, BLIS_MR, &blkszs[ BLIS_MR ], BLIS_MR, cntx ); } blis-0.9.0/config/penryn/bli_family_penryn.h000066400000000000000000000061321422157504600211140ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ //#ifndef BLIS_FAMILY_H //#define BLIS_FAMILY_H // -- MEMORY ALLOCATION -------------------------------------------------------- #define BLIS_SIMD_ALIGN_SIZE 16 #if 0 // -- LEVEL-3 MICRO-KERNEL CONSTANTS ------------------------------------------- #define BLIS_SGEMM_UKERNEL bli_sgemm_asm_8x4 #define BLIS_DEFAULT_MR_S 8 #define BLIS_DEFAULT_NR_S 4 #define BLIS_DEFAULT_MC_S 768 #define BLIS_DEFAULT_KC_S 384 #define BLIS_DEFAULT_NC_S 4096 #define BLIS_DGEMM_UKERNEL bli_dgemm_asm_4x4 #define BLIS_DEFAULT_MR_D 4 #define BLIS_DEFAULT_NR_D 4 #define BLIS_DEFAULT_MC_D 384 #define BLIS_DEFAULT_KC_D 384 #define BLIS_DEFAULT_NC_D 4096 #define BLIS_DGEMMTRSM_L_UKERNEL bli_dgemmtrsm_l_asm_4x4 #define BLIS_DGEMMTRSM_U_UKERNEL bli_dgemmtrsm_u_asm_4x4 // -- LEVEL-1F KERNEL DEFINITIONS ---------------------------------------------- #define BLIS_DAXPY2V_KERNEL bli_daxpy2v_int_var1 #define BLIS_DDOTAXPYV_KERNEL bli_ddotaxpyv_int_var1 #define BLIS_DAXPYF_KERNEL bli_daxpyf_int_var1 #define BLIS_DDOTXF_KERNEL bli_ddotxf_int_var1 #define BLIS_DDOTXAXPYF_KERNEL bli_ddotxaxpyf_int_var1 // -- LEVEL-1V KERNEL DEFINITIONS ---------------------------------------------- #define BLIS_DAXPYV_KERNEL bli_daxpyv_opt_var1 #define BLIS_DDOTV_KERNEL bli_ddotv_opt_var1 #endif //#endif blis-0.9.0/config/penryn/make_defs.mk000066400000000000000000000061231422157504600175100ustar00rootroot00000000000000# # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2014, The University of Texas at Austin # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # # Declare the name of the current configuration and add it to the # running list of configurations included by common.mk. THIS_CONFIG := penryn #CONFIGS_INCL += $(THIS_CONFIG) # # --- Determine the C compiler and related flags --- # # NOTE: The build system will append these variables with various # general-purpose/configuration-agnostic flags in common.mk. You # may specify additional flags here as needed. CPPROCFLAGS := CMISCFLAGS := CPICFLAGS := CWARNFLAGS := ifneq ($(DEBUG_TYPE),off) CDBGFLAGS := -g endif ifeq ($(DEBUG_TYPE),noopt) COPTFLAGS := -O0 else COPTFLAGS := -O2 endif # Flags specific to optimized kernels. CKOPTFLAGS := $(COPTFLAGS) -O3 ifeq ($(CC_VENDOR),gcc) CKVECFLAGS := -mssse3 -mfpmath=sse -march=core2 else ifeq ($(CC_VENDOR),icc) CKVECFLAGS := -xSSSE3 else ifeq ($(CC_VENDOR),clang) CKVECFLAGS := -mssse3 -mfpmath=sse -march=core2 else $(error gcc, icc, or clang is required for this configuration.) endif endif endif # Flags specific to reference kernels. CROPTFLAGS := $(CKOPTFLAGS) ifeq ($(CC_VENDOR),gcc) CRVECFLAGS := $(CKVECFLAGS) -funsafe-math-optimizations -ffp-contract=fast else ifeq ($(CC_VENDOR),clang) CRVECFLAGS := $(CKVECFLAGS) -funsafe-math-optimizations -ffp-contract=fast else CRVECFLAGS := $(CKVECFLAGS) endif endif # Store all of the variables here to new variables containing the # configuration name. $(eval $(call store-make-defs,$(THIS_CONFIG))) blis-0.9.0/config/piledriver/000077500000000000000000000000001422157504600160715ustar00rootroot00000000000000blis-0.9.0/config/piledriver/bli_cntx_init_piledriver.c000066400000000000000000000063051422157504600233130ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_cntx_init_piledriver( cntx_t* cntx ) { blksz_t blkszs[ BLIS_NUM_BLKSZS ]; // Set default kernel blocksizes and functions. bli_cntx_init_piledriver_ref( cntx ); // ------------------------------------------------------------------------- // Update the context with optimized native gemm micro-kernels and // their storage preferences. bli_cntx_set_l3_nat_ukrs ( 4, BLIS_GEMM_UKR, BLIS_FLOAT, bli_sgemm_piledriver_asm_16x3, FALSE, BLIS_GEMM_UKR, BLIS_DOUBLE, bli_dgemm_piledriver_asm_8x3, FALSE, BLIS_GEMM_UKR, BLIS_SCOMPLEX, bli_cgemm_piledriver_asm_4x2, FALSE, BLIS_GEMM_UKR, BLIS_DCOMPLEX, bli_zgemm_piledriver_asm_2x2, FALSE, cntx ); // Initialize level-3 blocksize objects with architecture-specific values. // s d c z bli_blksz_init_easy( &blkszs[ BLIS_MR ], 16, 8, 4, 2 ); bli_blksz_init_easy( &blkszs[ BLIS_NR ], 3, 3, 2, 2 ); bli_blksz_init_easy( &blkszs[ BLIS_MC ], 2016, 1008, 512, 400 ); bli_blksz_init_easy( &blkszs[ BLIS_KC ], 128, 128, 256, 160 ); bli_blksz_init_easy( &blkszs[ BLIS_NC ], 8400, 8400, 8400, 8400 ); // Update the context with the current architecture's register and cache // blocksizes (and multiples) for native execution. bli_cntx_set_blkszs ( BLIS_NAT, 5, BLIS_NC, &blkszs[ BLIS_NC ], BLIS_NR, BLIS_KC, &blkszs[ BLIS_KC ], BLIS_KR, BLIS_MC, &blkszs[ BLIS_MC ], BLIS_MR, BLIS_NR, &blkszs[ BLIS_NR ], BLIS_NR, BLIS_MR, &blkszs[ BLIS_MR ], BLIS_MR, cntx ); } blis-0.9.0/config/piledriver/bli_family_piledriver.h000066400000000000000000000057171422157504600226100ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ //#ifndef BLIS_FAMILY_H //#define BLIS_FAMILY_H // -- MEMORY ALLOCATION -------------------------------------------------------- #define BLIS_SIMD_ALIGN_SIZE 16 #if 0 // -- LEVEL-3 MICRO-KERNEL CONSTANTS ------------------------------------------- #define BLIS_SGEMM_UKERNEL bli_sgemm_asm_16x3 #define BLIS_DEFAULT_MC_S 2016 #define BLIS_DEFAULT_KC_S 128 #define BLIS_DEFAULT_NC_S 8400 #define BLIS_DEFAULT_MR_S 16 #define BLIS_DEFAULT_NR_S 3 #define BLIS_DGEMM_UKERNEL bli_dgemm_asm_8x3 #define BLIS_DEFAULT_MC_D 1008 #define BLIS_DEFAULT_KC_D 128 #define BLIS_DEFAULT_NC_D 8400 #define BLIS_DEFAULT_MR_D 8 #define BLIS_DEFAULT_NR_D 3 #define BLIS_CGEMM_UKERNEL bli_cgemm_asm_4x2 #define BLIS_DEFAULT_MC_C 512 #define BLIS_DEFAULT_KC_C 256 #define BLIS_DEFAULT_NC_C 8400 #define BLIS_DEFAULT_MR_C 4 #define BLIS_DEFAULT_NR_C 2 #define BLIS_ZGEMM_UKERNEL bli_zgemm_asm_2x2 #define BLIS_DEFAULT_MC_Z 400 #define BLIS_DEFAULT_KC_Z 160 #define BLIS_DEFAULT_NC_Z 8400 #define BLIS_DEFAULT_MR_Z 2 #define BLIS_DEFAULT_NR_Z 2 #endif //#endif blis-0.9.0/config/piledriver/make_defs.mk000066400000000000000000000061511422157504600203430ustar00rootroot00000000000000# # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2014, The University of Texas at Austin # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # # Declare the name of the current configuration and add it to the # running list of configurations included by common.mk. THIS_CONFIG := piledriver #CONFIGS_INCL += $(THIS_CONFIG) # # --- Determine the C compiler and related flags --- # # NOTE: The build system will append these variables with various # general-purpose/configuration-agnostic flags in common.mk. You # may specify additional flags here as needed. CPPROCFLAGS := CMISCFLAGS := CPICFLAGS := CWARNFLAGS := ifneq ($(DEBUG_TYPE),off) CDBGFLAGS := -g endif ifeq ($(DEBUG_TYPE),noopt) COPTFLAGS := -O0 else COPTFLAGS := -O2 endif # Flags specific to optimized kernels. CKOPTFLAGS := $(COPTFLAGS) -O3 ifeq ($(CC_VENDOR),gcc) CKVECFLAGS := -mfpmath=sse -mavx -mfma -march=bdver2 -mno-fma4 -mno-tbm -mno-xop -mno-lwp else ifeq ($(CC_VENDOR),clang) CKVECFLAGS := -mfpmath=sse -mavx -mfma -march=bdver2 -mno-fma4 -mno-tbm -mno-xop -mno-lwp else $(error gcc or clang are required for this configuration.) endif endif # Flags specific to reference kernels. CROPTFLAGS := $(CKOPTFLAGS) ifeq ($(CC_VENDOR),gcc) CRVECFLAGS := $(CKVECFLAGS) -funsafe-math-optimizations -ffp-contract=fast else ifeq ($(CC_VENDOR),clang) CRVECFLAGS := $(CKVECFLAGS) -funsafe-math-optimizations -ffp-contract=fast else CRVECFLAGS := $(CKVECFLAGS) endif endif # Store all of the variables here to new variables containing the # configuration name. $(eval $(call store-make-defs,$(THIS_CONFIG))) blis-0.9.0/config/power10/000077500000000000000000000000001422157504600152215ustar00rootroot00000000000000blis-0.9.0/config/power10/bli_cntx_init_power10.c000066400000000000000000000137301422157504600215730ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2019, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // Instantiate prototypes for packm kernels. PACKM_KER_PROT( float, s, packm_6xk_bb4_power10_ref ) PACKM_KER_PROT( double, d, packm_6xk_bb2_power10_ref ) // Instantiate prototypes for level-3 kernels. GEMM_UKR_PROT( float, s, gemmbb_power10_ref ) GEMMTRSM_UKR_PROT( float, s, gemmtrsmbb_l_power10_ref ) GEMMTRSM_UKR_PROT( float, s, gemmtrsmbb_u_power10_ref ) TRSM_UKR_PROT( float, s, trsmbb_l_power10_ref ) TRSM_UKR_PROT( float, s, trsmbb_u_power10_ref ) GEMM_UKR_PROT( double, d, gemmbb_power10_ref ) GEMMTRSM_UKR_PROT( double, d, gemmtrsmbb_l_power10_ref ) GEMMTRSM_UKR_PROT( double, d, gemmtrsmbb_u_power10_ref ) TRSM_UKR_PROT( double, d, trsmbb_l_power10_ref ) TRSM_UKR_PROT( double, d, trsmbb_u_power10_ref ) GEMM_UKR_PROT( scomplex, c, gemmbb_power10_ref ) GEMMTRSM_UKR_PROT( scomplex, c, gemmtrsmbb_l_power10_ref ) GEMMTRSM_UKR_PROT( scomplex, c, gemmtrsmbb_u_power10_ref ) TRSM_UKR_PROT( scomplex, c, trsmbb_l_power10_ref ) TRSM_UKR_PROT( scomplex, c, trsmbb_u_power10_ref ) GEMM_UKR_PROT( dcomplex, z, gemmbb_power10_ref ) GEMMTRSM_UKR_PROT( dcomplex, z, gemmtrsmbb_l_power10_ref ) GEMMTRSM_UKR_PROT( dcomplex, z, gemmtrsmbb_u_power10_ref ) TRSM_UKR_PROT( dcomplex, z, trsmbb_l_power10_ref ) TRSM_UKR_PROT( dcomplex, z, trsmbb_u_power10_ref ) void bli_cntx_init_power10( cntx_t* cntx ) { blksz_t blkszs[ BLIS_NUM_BLKSZS ]; // Set default kernel blocksizes and functions. bli_cntx_init_power10_ref( cntx ); // ------------------------------------------------------------------------- // Update the context with optimized native gemm micro-kernels and // their storage preferences. bli_cntx_set_l3_nat_ukrs ( 12, BLIS_GEMM_UKR, BLIS_FLOAT, bli_sgemm_power10_mma_8x16, TRUE, BLIS_TRSM_L_UKR, BLIS_FLOAT, bli_strsmbb_l_power10_ref, FALSE, BLIS_TRSM_U_UKR, BLIS_FLOAT, bli_strsmbb_u_power10_ref, FALSE, BLIS_GEMM_UKR, BLIS_DOUBLE, bli_dgemm_power10_mma_8x8, TRUE, BLIS_TRSM_L_UKR, BLIS_DOUBLE, bli_dtrsmbb_l_power10_ref, FALSE, BLIS_TRSM_U_UKR, BLIS_DOUBLE, bli_dtrsmbb_u_power10_ref, FALSE, BLIS_GEMM_UKR, BLIS_SCOMPLEX, bli_cgemmbb_power10_ref, FALSE, BLIS_TRSM_L_UKR, BLIS_SCOMPLEX, bli_ctrsmbb_l_power10_ref, FALSE, BLIS_TRSM_U_UKR, BLIS_SCOMPLEX, bli_ctrsmbb_u_power10_ref, FALSE, BLIS_GEMM_UKR, BLIS_DCOMPLEX, bli_zgemmbb_power10_ref, FALSE, BLIS_TRSM_L_UKR, BLIS_DCOMPLEX, bli_ztrsmbb_l_power10_ref, FALSE, BLIS_TRSM_U_UKR, BLIS_DCOMPLEX, bli_ztrsmbb_u_power10_ref, FALSE, cntx ); // Update the context with customized virtual [gemm]trsm micro-kernels. bli_cntx_set_l3_vir_ukrs ( 8, BLIS_GEMMTRSM_L_UKR, BLIS_FLOAT, bli_sgemmtrsmbb_l_power10_ref, BLIS_GEMMTRSM_U_UKR, BLIS_FLOAT, bli_sgemmtrsmbb_u_power10_ref, BLIS_GEMMTRSM_L_UKR, BLIS_DOUBLE, bli_dgemmtrsmbb_l_power10_ref, BLIS_GEMMTRSM_U_UKR, BLIS_DOUBLE, bli_dgemmtrsmbb_u_power10_ref, BLIS_GEMMTRSM_L_UKR, BLIS_SCOMPLEX, bli_cgemmtrsmbb_l_power10_ref, BLIS_GEMMTRSM_U_UKR, BLIS_SCOMPLEX, bli_cgemmtrsmbb_u_power10_ref, BLIS_GEMMTRSM_L_UKR, BLIS_DCOMPLEX, bli_zgemmtrsmbb_l_power10_ref, BLIS_GEMMTRSM_U_UKR, BLIS_DCOMPLEX, bli_zgemmtrsmbb_u_power10_ref, cntx ); // Update the context with optimized packm kernels. bli_cntx_set_packm_kers ( 2, BLIS_PACKM_6XK_KER, BLIS_FLOAT, bli_spackm_6xk_bb4_power10_ref, BLIS_PACKM_6XK_KER, BLIS_DOUBLE, bli_dpackm_6xk_bb2_power10_ref, cntx ); // s d c z bli_blksz_init_easy( &blkszs[ BLIS_MR ], 8, 8, -1, -1 ); bli_blksz_init_easy( &blkszs[ BLIS_NR ], 16, 8, -1, -1 ); bli_blksz_init_easy( &blkszs[ BLIS_MC ], 832, 320, -1, -1 ); bli_blksz_init_easy( &blkszs[ BLIS_KC ], 1026, 960, -1, -1 ); bli_blksz_init_easy( &blkszs[ BLIS_NC ], 4096, 4096, -1, -1 ); // Update the context with the current architecture's register and cache // blocksizes (and multiples) for native execution. bli_cntx_set_blkszs ( BLIS_NAT, 5, // level-3 BLIS_NC, &blkszs[ BLIS_NC ], BLIS_NR, BLIS_KC, &blkszs[ BLIS_KC ], BLIS_KR, BLIS_MC, &blkszs[ BLIS_MC ], BLIS_MR, BLIS_NR, &blkszs[ BLIS_NR ], BLIS_NR, BLIS_MR, &blkszs[ BLIS_MR ], BLIS_MR, cntx ); } blis-0.9.0/config/power10/bli_family_power10.h000066400000000000000000000034561422157504600210660ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2019, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #define BLIS_POOL_ADDR_ALIGN_SIZE_A 4096 #define BLIS_POOL_ADDR_ALIGN_SIZE_B 4096 #define BLIS_POOL_ADDR_OFFSET_SIZE_A 192 #define BLIS_POOL_ADDR_OFFSET_SIZE_B 152 blis-0.9.0/config/power10/make_defs.mk000066400000000000000000000054701422157504600174760ustar00rootroot00000000000000 # # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2019, The University of Texas at Austin # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # # Declare the name of the current configuration and add it to the # running list of configurations included by common.mk. THIS_CONFIG := power10 #CONFIGS_INCL += $(THIS_CONFIG) # # --- Determine the C compiler and related flags --- # # NOTE: The build system will append these variables with various # general-purpose/configuration-agnostic flags in common.mk. You # may specify additional flags here as needed. CPPROCFLAGS := CMISCFLAGS := CPICFLAGS := CWARNFLAGS := ifneq ($(DEBUG_TYPE),off) CDBGFLAGS := -g endif ifeq ($(DEBUG_TYPE),noopt) COPTFLAGS := -O0 else COPTFLAGS := -O2 endif # Flags specific to optimized kernels. CKOPTFLAGS := $(COPTFLAGS) -O3 ifeq ($(CC_VENDOR),gcc) CKVECFLAGS := -mcpu=power10 -mtune=power10 else ifeq ($(CC_VENDOR),clang) CKVECFLAGS := -mcpu=power10 -mtune=power10 else $(info $(CC_VENDOR)) $(error gcc, clang is required for this configuration.) endif endif # Flags specific to reference kernels. CROPTFLAGS := $(CKOPTFLAGS) CRVECFLAGS := $(CKVECFLAGS) # Store all of the variables here to new variables containing the # configuration name. $(eval $(call store-make-defs,$(THIS_CONFIG))) blis-0.9.0/config/power7/000077500000000000000000000000001422157504600151475ustar00rootroot00000000000000blis-0.9.0/config/power7/bli_cntx_init_power7.c000066400000000000000000000057441422157504600214550ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_cntx_init_power7( cntx_t* cntx ) { blksz_t blkszs[ BLIS_NUM_BLKSZS ]; // Set default kernel blocksizes and functions. bli_cntx_init_power7_ref( cntx ); // ------------------------------------------------------------------------- // Update the context with optimized native gemm micro-kernels and // their storage preferences. bli_cntx_set_l3_nat_ukrs ( 1, BLIS_GEMM_UKR, BLIS_DOUBLE, bli_dgemm_power7_int_8x4, FALSE, cntx ); // Initialize level-3 blocksize objects with architecture-specific values. // s d c z bli_blksz_init_easy( &blkszs[ BLIS_MR ], 0, 8, 0, 0 ); bli_blksz_init_easy( &blkszs[ BLIS_NR ], 0, 4, 0, 0 ); bli_blksz_init_easy( &blkszs[ BLIS_MC ], 0, 64, 0, 0 ); bli_blksz_init_easy( &blkszs[ BLIS_KC ], 0, 256, 0, 0 ); bli_blksz_init_easy( &blkszs[ BLIS_NC ], 0, 4096, 0, 0 ); // Update the context with the current architecture's register and cache // blocksizes (and multiples) for native execution. bli_cntx_set_blkszs ( BLIS_NAT, 5, BLIS_NC, &blkszs[ BLIS_NC ], BLIS_NR, BLIS_KC, &blkszs[ BLIS_KC ], BLIS_KR, BLIS_MC, &blkszs[ BLIS_MC ], BLIS_MR, BLIS_NR, &blkszs[ BLIS_NR ], BLIS_NR, BLIS_MR, &blkszs[ BLIS_MR ], BLIS_MR, cntx ); } blis-0.9.0/config/power7/bli_family_power7.h000066400000000000000000000040621422157504600207340ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ //#ifndef BLIS_FAMILY_H //#define BLIS_FAMILY_H #if 0 // -- LEVEL-3 MICRO-KERNEL CONSTANTS ------------------------------------------- #define BLIS_DGEMM_UKERNEL bli_dgemm_opt_8x4 #define BLIS_DEFAULT_MR_D 8 #define BLIS_DEFAULT_NR_D 4 #define BLIS_DEFAULT_MC_D 64 #define BLIS_DEFAULT_KC_D 256 #define BLIS_DEFAULT_NC_D 4096 #endif //#endif blis-0.9.0/config/power7/make_defs.mk000066400000000000000000000056551422157504600174310ustar00rootroot00000000000000# # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2014, The University of Texas at Austin # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # # Declare the name of the current configuration and add it to the # running list of configurations included by common.mk. THIS_CONFIG := power7 #CONFIGS_INCL += $(THIS_CONFIG) # # --- Determine the C compiler and related flags --- # # NOTE: The build system will append these variables with various # general-purpose/configuration-agnostic flags in common.mk. You # may specify additional flags here as needed. CPPROCFLAGS := CMISCFLAGS := -mcpu=power7 CPICFLAGS := CWARNFLAGS := ifneq ($(DEBUG_TYPE),off) CDBGFLAGS := -g endif ifeq ($(DEBUG_TYPE),noopt) COPTFLAGS := -O0 else COPTFLAGS := -O2 -mtune=power7 endif # Flags specific to optimized kernels. CKOPTFLAGS := $(COPTFLAGS) -O3 ifeq ($(CC_VENDOR),gcc) CKVECFLAGS := -mvsx else $(error gcc is required for this configuration.) endif # Flags specific to reference kernels. CROPTFLAGS := $(CKOPTFLAGS) ifeq ($(CC_VENDOR),gcc) CRVECFLAGS := $(CKVECFLAGS) -funsafe-math-optimizations -ffp-contract=fast else ifeq ($(CC_VENDOR),clang) CRVECFLAGS := $(CKVECFLAGS) -funsafe-math-optimizations -ffp-contract=fast else CRVECFLAGS := $(CKVECFLAGS) endif endif # Store all of the variables here to new variables containing the # configuration name. $(eval $(call store-make-defs,$(THIS_CONFIG))) blis-0.9.0/config/power9/000077500000000000000000000000001422157504600151515ustar00rootroot00000000000000blis-0.9.0/config/power9/bli_cntx_init_power9.c000066400000000000000000000136501422157504600214540ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2019, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // Instantiate prototypes for packm kernels. PACKM_KER_PROT( float, s, packm_6xk_bb4_power9_ref ) PACKM_KER_PROT( double, d, packm_6xk_bb2_power9_ref ) // Instantiate prototypes for level-3 kernels. GEMM_UKR_PROT( float, s, gemmbb_power9_ref ) GEMMTRSM_UKR_PROT( float, s, gemmtrsmbb_l_power9_ref ) GEMMTRSM_UKR_PROT( float, s, gemmtrsmbb_u_power9_ref ) TRSM_UKR_PROT( float, s, trsmbb_l_power9_ref ) TRSM_UKR_PROT( float, s, trsmbb_u_power9_ref ) GEMM_UKR_PROT( double, d, gemmbb_power9_ref ) GEMMTRSM_UKR_PROT( double, d, gemmtrsmbb_l_power9_ref ) GEMMTRSM_UKR_PROT( double, d, gemmtrsmbb_u_power9_ref ) TRSM_UKR_PROT( double, d, trsmbb_l_power9_ref ) TRSM_UKR_PROT( double, d, trsmbb_u_power9_ref ) GEMM_UKR_PROT( scomplex, c, gemmbb_power9_ref ) GEMMTRSM_UKR_PROT( scomplex, c, gemmtrsmbb_l_power9_ref ) GEMMTRSM_UKR_PROT( scomplex, c, gemmtrsmbb_u_power9_ref ) TRSM_UKR_PROT( scomplex, c, trsmbb_l_power9_ref ) TRSM_UKR_PROT( scomplex, c, trsmbb_u_power9_ref ) GEMM_UKR_PROT( dcomplex, z, gemmbb_power9_ref ) GEMMTRSM_UKR_PROT( dcomplex, z, gemmtrsmbb_l_power9_ref ) GEMMTRSM_UKR_PROT( dcomplex, z, gemmtrsmbb_u_power9_ref ) TRSM_UKR_PROT( dcomplex, z, trsmbb_l_power9_ref ) TRSM_UKR_PROT( dcomplex, z, trsmbb_u_power9_ref ) void bli_cntx_init_power9( cntx_t* cntx ) { blksz_t blkszs[ BLIS_NUM_BLKSZS ]; // Set default kernel blocksizes and functions. bli_cntx_init_power9_ref( cntx ); // ------------------------------------------------------------------------- // Update the context with optimized native gemm micro-kernels and // their storage preferences. bli_cntx_set_l3_nat_ukrs ( 12, BLIS_GEMM_UKR, BLIS_FLOAT, bli_sgemmbb_power9_ref, FALSE, BLIS_TRSM_L_UKR, BLIS_FLOAT, bli_strsmbb_l_power9_ref, FALSE, BLIS_TRSM_U_UKR, BLIS_FLOAT, bli_strsmbb_u_power9_ref, FALSE, BLIS_GEMM_UKR, BLIS_DOUBLE, bli_dgemm_power9_asm_12x6, FALSE, BLIS_TRSM_L_UKR, BLIS_DOUBLE, bli_dtrsmbb_l_power9_ref, FALSE, BLIS_TRSM_U_UKR, BLIS_DOUBLE, bli_dtrsmbb_u_power9_ref, FALSE, BLIS_GEMM_UKR, BLIS_SCOMPLEX, bli_cgemmbb_power9_ref, FALSE, BLIS_TRSM_L_UKR, BLIS_SCOMPLEX, bli_ctrsmbb_l_power9_ref, FALSE, BLIS_TRSM_U_UKR, BLIS_SCOMPLEX, bli_ctrsmbb_u_power9_ref, FALSE, BLIS_GEMM_UKR, BLIS_DCOMPLEX, bli_zgemmbb_power9_ref, FALSE, BLIS_TRSM_L_UKR, BLIS_DCOMPLEX, bli_ztrsmbb_l_power9_ref, FALSE, BLIS_TRSM_U_UKR, BLIS_DCOMPLEX, bli_ztrsmbb_u_power9_ref, FALSE, cntx ); // Update the context with customized virtual [gemm]trsm micro-kernels. bli_cntx_set_l3_vir_ukrs ( 8, BLIS_GEMMTRSM_L_UKR, BLIS_FLOAT, bli_sgemmtrsmbb_l_power9_ref, BLIS_GEMMTRSM_U_UKR, BLIS_FLOAT, bli_sgemmtrsmbb_u_power9_ref, BLIS_GEMMTRSM_L_UKR, BLIS_DOUBLE, bli_dgemmtrsmbb_l_power9_ref, BLIS_GEMMTRSM_U_UKR, BLIS_DOUBLE, bli_dgemmtrsmbb_u_power9_ref, BLIS_GEMMTRSM_L_UKR, BLIS_SCOMPLEX, bli_cgemmtrsmbb_l_power9_ref, BLIS_GEMMTRSM_U_UKR, BLIS_SCOMPLEX, bli_cgemmtrsmbb_u_power9_ref, BLIS_GEMMTRSM_L_UKR, BLIS_DCOMPLEX, bli_zgemmtrsmbb_l_power9_ref, BLIS_GEMMTRSM_U_UKR, BLIS_DCOMPLEX, bli_zgemmtrsmbb_u_power9_ref, cntx ); // Update the context with optimized packm kernels. bli_cntx_set_packm_kers ( 2, BLIS_PACKM_6XK_KER, BLIS_FLOAT, bli_spackm_6xk_bb4_power9_ref, BLIS_PACKM_6XK_KER, BLIS_DOUBLE, bli_dpackm_6xk_bb2_power9_ref, cntx ); bli_blksz_init_easy( &blkszs[ BLIS_MR ], -1, 12, -1, -1 ); bli_blksz_init ( &blkszs[ BLIS_NR ], -1, 6, -1, -1, -1, 12, -1, -1 ); bli_blksz_init_easy( &blkszs[ BLIS_MC ], -1, 576, -1, -1 ); bli_blksz_init_easy( &blkszs[ BLIS_KC ], -1, 1408, -1, -1 ); bli_blksz_init_easy( &blkszs[ BLIS_NC ], -1, 8190, -1, -1 ); // Update the context with the current architecture's register and cache // blocksizes (and multiples) for native execution. bli_cntx_set_blkszs ( BLIS_NAT, 5, // level-3 BLIS_NC, &blkszs[ BLIS_NC ], BLIS_NR, BLIS_KC, &blkszs[ BLIS_KC ], BLIS_KR, BLIS_MC, &blkszs[ BLIS_MC ], BLIS_MR, BLIS_NR, &blkszs[ BLIS_NR ], BLIS_NR, BLIS_MR, &blkszs[ BLIS_MR ], BLIS_MR, cntx ); } blis-0.9.0/config/power9/bli_family_power9.h000066400000000000000000000040511422157504600207360ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2019, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #define BLIS_POOL_ADDR_ALIGN_SIZE_A 4096 #define BLIS_POOL_ADDR_ALIGN_SIZE_B 4096 #define BLIS_POOL_ADDR_OFFSET_SIZE_A 192 #define BLIS_POOL_ADDR_OFFSET_SIZE_B 152 // Disable right-side hemm, symm, and trmm[3] to accommodate the broadcasting of // elements within the packed matrix B. #define BLIS_DISABLE_HEMM_RIGHT #define BLIS_DISABLE_SYMM_RIGHT #define BLIS_DISABLE_TRMM_RIGHT #define BLIS_DISABLE_TRMM3_RIGHT blis-0.9.0/config/power9/make_defs.mk000066400000000000000000000054741422157504600174320ustar00rootroot00000000000000 # # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2019, The University of Texas at Austin # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # # Declare the name of the current configuration and add it to the # running list of configurations included by common.mk. THIS_CONFIG := power9 #CONFIGS_INCL += $(THIS_CONFIG) # # --- Determine the C compiler and related flags --- # # NOTE: The build system will append these variables with various # general-purpose/configuration-agnostic flags in common.mk. You # may specify additional flags here as needed. CPPROCFLAGS := CMISCFLAGS := CPICFLAGS := CWARNFLAGS := ifneq ($(DEBUG_TYPE),off) CDBGFLAGS := -g endif ifeq ($(DEBUG_TYPE),noopt) COPTFLAGS := -O0 else COPTFLAGS := -O2 endif # Flags specific to optimized kernels. CKOPTFLAGS := $(COPTFLAGS) -O3 ifeq ($(CC_VENDOR),gcc) CKVECFLAGS := -mcpu=power9 -mtune=power9 -DXLC=0 else ifeq ($(CC_VENDOR),IBM) CKVECFLAGS := -qarch=pwr9 -qtune=pwr9 -DXLC=1 else $(info $(CC_VENDOR)) $(error gcc/xlc is required for this configuration.) endif endif # Flags specific to reference kernels. CROPTFLAGS := $(CKOPTFLAGS) CRVECFLAGS := $(CKVECFLAGS) # Store all of the variables here to new variables containing the # configuration name. $(eval $(call store-make-defs,$(THIS_CONFIG))) blis-0.9.0/config/sandybridge/000077500000000000000000000000001422157504600162175ustar00rootroot00000000000000blis-0.9.0/config/sandybridge/bli_cntx_init_sandybridge.c000066400000000000000000000063071422157504600235710ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_cntx_init_sandybridge( cntx_t* cntx ) { blksz_t blkszs[ BLIS_NUM_BLKSZS ]; // Set default kernel blocksizes and functions. bli_cntx_init_sandybridge_ref( cntx ); // ------------------------------------------------------------------------- // Update the context with optimized native gemm micro-kernels and // their storage preferences. bli_cntx_set_l3_nat_ukrs ( 4, BLIS_GEMM_UKR, BLIS_FLOAT, bli_sgemm_sandybridge_asm_8x8, FALSE, BLIS_GEMM_UKR, BLIS_DOUBLE, bli_dgemm_sandybridge_asm_8x4, FALSE, BLIS_GEMM_UKR, BLIS_SCOMPLEX, bli_cgemm_sandybridge_asm_8x4, FALSE, BLIS_GEMM_UKR, BLIS_DCOMPLEX, bli_zgemm_sandybridge_asm_4x4, FALSE, cntx ); // Initialize level-3 blocksize objects with architecture-specific values. // s d c z bli_blksz_init_easy( &blkszs[ BLIS_MR ], 8, 8, 8, 4 ); bli_blksz_init_easy( &blkszs[ BLIS_NR ], 8, 4, 4, 4 ); bli_blksz_init_easy( &blkszs[ BLIS_MC ], 128, 96, 96, 64 ); bli_blksz_init_easy( &blkszs[ BLIS_KC ], 384, 256, 256, 192 ); bli_blksz_init_easy( &blkszs[ BLIS_NC ], 4096, 4096, 4096, 4096 ); // Update the context with the current architecture's register and cache // blocksizes (and multiples) for native execution. bli_cntx_set_blkszs ( BLIS_NAT, 5, BLIS_NC, &blkszs[ BLIS_NC ], BLIS_NR, BLIS_KC, &blkszs[ BLIS_KC ], BLIS_KR, BLIS_MC, &blkszs[ BLIS_MC ], BLIS_MR, BLIS_NR, &blkszs[ BLIS_NR ], BLIS_NR, BLIS_MR, &blkszs[ BLIS_MR ], BLIS_MR, cntx ); } blis-0.9.0/config/sandybridge/bli_family_sandybridge.h000066400000000000000000000053741422157504600230630ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ //#ifndef BLIS_FAMILY_H //#define BLIS_FAMILY_H #if 0 // -- LEVEL-3 MICRO-KERNEL CONSTANTS AND DEFINITIONS --------------------------- #define BLIS_SGEMM_UKERNEL bli_sgemm_asm_8x8 #define BLIS_DEFAULT_MC_S 128 #define BLIS_DEFAULT_KC_S 384 #define BLIS_DEFAULT_NC_S 4096 #define BLIS_DEFAULT_MR_S 8 #define BLIS_DEFAULT_NR_S 8 #define BLIS_DGEMM_UKERNEL bli_dgemm_asm_8x4 #define BLIS_DEFAULT_MC_D 96 #define BLIS_DEFAULT_KC_D 256 #define BLIS_DEFAULT_NC_D 4096 #define BLIS_DEFAULT_MR_D 8 #define BLIS_DEFAULT_NR_D 4 #define BLIS_CGEMM_UKERNEL bli_cgemm_asm_8x4 #define BLIS_DEFAULT_MC_C 96 #define BLIS_DEFAULT_KC_C 256 #define BLIS_DEFAULT_NC_C 4096 #define BLIS_DEFAULT_MR_C 8 #define BLIS_DEFAULT_NR_C 4 #define BLIS_ZGEMM_UKERNEL bli_zgemm_asm_4x4 #define BLIS_DEFAULT_MC_Z 64 #define BLIS_DEFAULT_KC_Z 192 #define BLIS_DEFAULT_NC_Z 4096 #define BLIS_DEFAULT_MR_Z 4 #define BLIS_DEFAULT_NR_Z 4 #endif //#endif blis-0.9.0/config/sandybridge/make_defs.mk000066400000000000000000000063761422157504600205020ustar00rootroot00000000000000# # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2014, The University of Texas at Austin # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # # Declare the name of the current configuration and add it to the # running list of configurations included by common.mk. THIS_CONFIG := sandybridge #CONFIGS_INCL += $(THIS_CONFIG) # # --- Determine the C compiler and related flags --- # # NOTE: The build system will append these variables with various # general-purpose/configuration-agnostic flags in common.mk. You # may specify additional flags here as needed. CPPROCFLAGS := CMISCFLAGS := CPICFLAGS := CWARNFLAGS := ifneq ($(DEBUG_TYPE),off) CDBGFLAGS := -g endif ifeq ($(DEBUG_TYPE),noopt) COPTFLAGS := -O0 else COPTFLAGS := -O2 endif # Flags specific to optimized kernels. CKOPTFLAGS := $(COPTFLAGS) -O3 ifeq ($(CC_VENDOR),gcc) CKVECFLAGS := -mavx -mfpmath=sse -march=sandybridge ifeq ($(GCC_OT_4_9_0),yes) # If gcc is older than 4.9.0, we must use a different label for -march. CKVECFLAGS := -mavx -mfpmath=sse -march=corei7-avx endif else ifeq ($(CC_VENDOR),icc) CKVECFLAGS := -xAVX else ifeq ($(CC_VENDOR),clang) CKVECFLAGS := -mavx -mfpmath=sse -march=sandybridge else $(error gcc, icc, or clang is required for this configuration.) endif endif endif # Flags specific to reference kernels. CROPTFLAGS := $(CKOPTFLAGS) ifeq ($(CC_VENDOR),gcc) CRVECFLAGS := $(CKVECFLAGS) -funsafe-math-optimizations -ffp-contract=fast else ifeq ($(CC_VENDOR),clang) CRVECFLAGS := $(CKVECFLAGS) -funsafe-math-optimizations -ffp-contract=fast else CRVECFLAGS := $(CKVECFLAGS) endif endif # Store all of the variables here to new variables containing the # configuration name. $(eval $(call store-make-defs,$(THIS_CONFIG))) blis-0.9.0/config/skx/000077500000000000000000000000001422157504600145315ustar00rootroot00000000000000blis-0.9.0/config/skx/bli_cntx_init_skx.c000066400000000000000000000112501422157504600204060ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_cntx_init_skx( cntx_t* cntx ) { blksz_t blkszs[ BLIS_NUM_BLKSZS ]; // Set default kernel blocksizes and functions. bli_cntx_init_skx_ref( cntx ); // ------------------------------------------------------------------------- // Update the context with optimized native gemm micro-kernels and // their storage preferences. bli_cntx_set_l3_nat_ukrs ( 2, // gemm BLIS_GEMM_UKR, BLIS_FLOAT , bli_sgemm_skx_asm_32x12_l2, FALSE, BLIS_GEMM_UKR, BLIS_DOUBLE, bli_dgemm_skx_asm_16x14, FALSE, cntx ); // Update the context with optimized level-1f kernels. bli_cntx_set_l1f_kers ( 4, // axpyf BLIS_AXPYF_KER, BLIS_FLOAT, bli_saxpyf_zen_int_8, BLIS_AXPYF_KER, BLIS_DOUBLE, bli_daxpyf_zen_int_8, // dotxf BLIS_DOTXF_KER, BLIS_FLOAT, bli_sdotxf_zen_int_8, BLIS_DOTXF_KER, BLIS_DOUBLE, bli_ddotxf_zen_int_8, cntx ); // Update the context with optimized level-1v kernels. bli_cntx_set_l1v_kers ( 10, #if 1 // amaxv BLIS_AMAXV_KER, BLIS_FLOAT, bli_samaxv_zen_int, BLIS_AMAXV_KER, BLIS_DOUBLE, bli_damaxv_zen_int, #endif // axpyv #if 0 BLIS_AXPYV_KER, BLIS_FLOAT, bli_saxpyv_zen_int, BLIS_AXPYV_KER, BLIS_DOUBLE, bli_daxpyv_zen_int, #else BLIS_AXPYV_KER, BLIS_FLOAT, bli_saxpyv_zen_int10, BLIS_AXPYV_KER, BLIS_DOUBLE, bli_daxpyv_zen_int10, #endif // dotv BLIS_DOTV_KER, BLIS_FLOAT, bli_sdotv_zen_int, BLIS_DOTV_KER, BLIS_DOUBLE, bli_ddotv_zen_int, // dotxv BLIS_DOTXV_KER, BLIS_FLOAT, bli_sdotxv_zen_int, BLIS_DOTXV_KER, BLIS_DOUBLE, bli_ddotxv_zen_int, // scalv #if 0 BLIS_SCALV_KER, BLIS_FLOAT, bli_sscalv_zen_int, BLIS_SCALV_KER, BLIS_DOUBLE, bli_dscalv_zen_int, #else BLIS_SCALV_KER, BLIS_FLOAT, bli_sscalv_zen_int10, BLIS_SCALV_KER, BLIS_DOUBLE, bli_dscalv_zen_int10, #endif cntx ); // Initialize level-3 blocksize objects with architecture-specific values. // s d c z bli_blksz_init_easy( &blkszs[ BLIS_MR ], 32, 16, -1, -1 ); bli_blksz_init_easy( &blkszs[ BLIS_NR ], 12, 14, -1, -1 ); bli_blksz_init_easy( &blkszs[ BLIS_MC ], 480, 240, -1, -1 ); bli_blksz_init ( &blkszs[ BLIS_KC ], 384, 256, -1, -1, 480, 320, -1, -1 ); bli_blksz_init_easy( &blkszs[ BLIS_NC ], 3072, 3752, -1, -1 ); bli_blksz_init_easy( &blkszs[ BLIS_AF ], 8, 8, -1, -1 ); bli_blksz_init_easy( &blkszs[ BLIS_DF ], 8, 8, -1, -1 ); // Update the context with the current architecture's register and cache // blocksizes (and multiples) for native execution. bli_cntx_set_blkszs ( BLIS_NAT, 7, // level-3 BLIS_NC, &blkszs[ BLIS_NC ], BLIS_NR, BLIS_KC, &blkszs[ BLIS_KC ], BLIS_KR, BLIS_MC, &blkszs[ BLIS_MC ], BLIS_MR, BLIS_NR, &blkszs[ BLIS_NR ], BLIS_NR, BLIS_MR, &blkszs[ BLIS_MR ], BLIS_MR, // level-1f BLIS_AF, &blkszs[ BLIS_AF ], BLIS_AF, BLIS_DF, &blkszs[ BLIS_DF ], BLIS_DF, cntx ); } blis-0.9.0/config/skx/bli_family_skx.h000066400000000000000000000113171422157504600177010ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ //#ifndef BLIS_FAMILY_H //#define BLIS_FAMILY_H // -- THREADING PARAMETERS ----------------------------------------------------- #define BLIS_THREAD_RATIO_M 3 #define BLIS_THREAD_RATIO_N 2 #define BLIS_THREAD_MAX_IR 1 #define BLIS_THREAD_MAX_JR 4 // -- MEMORY ALLOCATION -------------------------------------------------------- #define BLIS_SIMD_ALIGN_SIZE 64 #define BLIS_SIMD_MAX_SIZE 64 #define BLIS_SIMD_MAX_NUM_REGISTERS 32 //#include //#define BLIS_MALLOC_POOL malloc //#define BLIS_FREE_POOL free #if 0 // -- LEVEL-3 MICRO-KERNEL CONSTANTS ------------------------------------------- // -- Cache and register blocksizes -- // // Constraints: // // (1) MC must be a multiple of: // (a) MR (for zero-padding purposes) // (b) NR (for zero-padding purposes when MR and NR are "swapped") // (2) NC must be a multiple of // (a) NR (for zero-padding purposes) // (b) MR (for zero-padding purposes when MR and NR are "swapped") // #define BLIS_DGEMM_UKERNEL bli_dgemm_opt_16x12_l2 #define BLIS_DEFAULT_MC_D 144 #define BLIS_DEFAULT_KC_D 336 #define BLIS_DEFAULT_NC_D 5760 #define BLIS_DEFAULT_MR_D 16 #define BLIS_DEFAULT_NR_D 12 #define BLIS_PACKDIM_MR_D 16 #define BLIS_PACKDIM_NR_D 12 // NOTE: If the micro-kernel, which is typically unrolled to a factor // of f, handles leftover edge cases (ie: when k % f > 0) then these // register blocksizes in the k dimension can be defined to 1. //#define BLIS_DEFAULT_KR_S 1 //#define BLIS_DEFAULT_KR_D 1 //#define BLIS_DEFAULT_KR_C 1 //#define BLIS_DEFAULT_KR_Z 1 // -- Maximum cache blocksizes (for optimizing edge cases) -- // NOTE: These cache blocksize "extensions" have the same constraints as // the corresponding default blocksizes above. When these values are // larger than the default blocksizes, blocksizes used at edge cases are // enlarged if such an extension would encompass the remaining portion of // the matrix dimension. #define BLIS_MAXIMUM_MC_S (BLIS_DEFAULT_MC_S + BLIS_DEFAULT_MC_S/4) #define BLIS_MAXIMUM_KC_S (BLIS_DEFAULT_KC_S + BLIS_DEFAULT_KC_S/4) #define BLIS_MAXIMUM_NC_S (BLIS_DEFAULT_NC_S + 0) #define BLIS_MAXIMUM_MC_D (BLIS_DEFAULT_MC_D + BLIS_DEFAULT_MC_D/4) #define BLIS_MAXIMUM_KC_D (BLIS_DEFAULT_KC_D + BLIS_DEFAULT_KC_D/4) #define BLIS_MAXIMUM_NC_D (BLIS_DEFAULT_NC_D + 0) //#define BLIS_MAXIMUM_MC_C (BLIS_DEFAULT_MC_C + BLIS_DEFAULT_MC_C/4) //#define BLIS_MAXIMUM_KC_C (BLIS_DEFAULT_KC_C + BLIS_DEFAULT_KC_C/4) //#define BLIS_MAXIMUM_NC_C (BLIS_DEFAULT_NC_C + BLIS_DEFAULT_NC_C/4) //#define BLIS_MAXIMUM_MC_Z (BLIS_DEFAULT_MC_Z + BLIS_DEFAULT_MC_Z/4) //#define BLIS_MAXIMUM_KC_Z (BLIS_DEFAULT_KC_Z + BLIS_DEFAULT_KC_Z/4) //#define BLIS_MAXIMUM_NC_Z (BLIS_DEFAULT_NC_Z + BLIS_DEFAULT_NC_Z/4) #endif //#endif blis-0.9.0/config/skx/make_defs.mk000066400000000000000000000112761422157504600170070ustar00rootroot00000000000000# # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2014, The University of Texas at Austin # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # # Declare the name of the current configuration and add it to the # running list of configurations included by common.mk. THIS_CONFIG := skx #CONFIGS_INCL += $(THIS_CONFIG) # # --- Determine the C compiler and related flags --- # # NOTE: The build system will append these variables with various # general-purpose/configuration-agnostic flags in common.mk. You # may specify additional flags here as needed. CPPROCFLAGS := CMISCFLAGS := CPICFLAGS := CWARNFLAGS := ifneq ($(DEBUG_TYPE),off) CDBGFLAGS := -g endif ifeq ($(DEBUG_TYPE),noopt) COPTFLAGS := -O0 else COPTFLAGS := -O2 endif # Flags specific to optimized kernels. # NOTE: The -fomit-frame-pointer option is needed for some kernels because # they make explicit use of the rbp register. CKOPTFLAGS := $(COPTFLAGS) -O3 -fomit-frame-pointer ifeq ($(CC_VENDOR),gcc) CKVECFLAGS := -mavx512f -mavx512dq -mavx512bw -mavx512vl -mfpmath=sse -march=skylake-avx512 else ifeq ($(CC_VENDOR),icc) CKVECFLAGS := -xCORE-AVX512 else ifeq ($(CC_VENDOR),clang) # NOTE: We have to use -march=haswell on Windows because apparently AVX512 # uses an alternate calling convention where xmm registers are not callee-saved # on the stack. When this is mixed with framework code compiled for general # x86_64 mode then chaos ensues (e.g. #514). ifeq ($(IS_WIN),yes) CKVECFLAGS := -mavx512f -mavx512dq -mavx512bw -mavx512vl -mfpmath=sse -march=haswell else CKVECFLAGS := -mavx512f -mavx512dq -mavx512bw -mavx512vl -mfpmath=sse -march=skylake-avx512 endif else $(error gcc, icc, or clang is required for this configuration.) endif endif endif # The assembler on OS X won't recognize AVX512 without help ifneq ($(CC_VENDOR),icc) ifeq ($(OS_NAME),Darwin) CKVECFLAGS += -Wa,-march=skylake-avx512 endif endif # Flags specific to reference kernels. # Note: We use AVX2 for reference kernels because, as Jeff Hammond says, # reference kernel code "is not going to achieve high enough SIMD utilization # to overcome the AVX-512 frequency drop". (Issue #187) CROPTFLAGS := $(CKOPTFLAGS) ifeq ($(CC_VENDOR),gcc) CRVECFLAGS := -march=skylake-avx512 -mno-avx512f -mno-avx512vl -mno-avx512bw -mno-avx512dq -mno-avx512cd -funsafe-math-optimizations -ffp-contract=fast else ifeq ($(CC_VENDOR),icc) CRVECFLAGS := -xCORE-AVX2 else ifeq ($(CC_VENDOR),clang) # NOTE: We have to use -march=haswell on Windows because apparently AVX512 # uses an alternate calling convention where xmm registers are not callee-saved # on the stack. When this is mixed with framework code compiled for general # x86_64 mode then chaos ensues (e.g. #514). ifeq ($(IS_WIN),yes) CRVECFLAGS := -march=haswell -funsafe-math-optimizations -ffp-contract=fast else CRVECFLAGS := -march=skylake-avx512 -mno-avx512f -mno-avx512vl -mno-avx512bw -mno-avx512dq -mno-avx512cd -funsafe-math-optimizations -ffp-contract=fast endif else $(error gcc, icc, or clang is required for this configuration.) endif endif endif # Store all of the variables here to new variables containing the # configuration name. $(eval $(call store-make-defs,$(THIS_CONFIG))) blis-0.9.0/config/steamroller/000077500000000000000000000000001422157504600162555ustar00rootroot00000000000000blis-0.9.0/config/steamroller/bli_cntx_init_steamroller.c000066400000000000000000000063071422157504600236650ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_cntx_init_steamroller( cntx_t* cntx ) { blksz_t blkszs[ BLIS_NUM_BLKSZS ]; // Set default kernel blocksizes and functions. bli_cntx_init_steamroller_ref( cntx ); // ------------------------------------------------------------------------- // Update the context with optimized native gemm micro-kernels and // their storage preferences. bli_cntx_set_l3_nat_ukrs ( 4, BLIS_GEMM_UKR, BLIS_FLOAT, bli_sgemm_piledriver_asm_16x3, FALSE, BLIS_GEMM_UKR, BLIS_DOUBLE, bli_dgemm_piledriver_asm_8x3, FALSE, BLIS_GEMM_UKR, BLIS_SCOMPLEX, bli_cgemm_piledriver_asm_4x2, FALSE, BLIS_GEMM_UKR, BLIS_DCOMPLEX, bli_zgemm_piledriver_asm_2x2, FALSE, cntx ); // Initialize level-3 blocksize objects with architecture-specific values. // s d c z bli_blksz_init_easy( &blkszs[ BLIS_MR ], 16, 8, 4, 2 ); bli_blksz_init_easy( &blkszs[ BLIS_NR ], 3, 3, 2, 2 ); bli_blksz_init_easy( &blkszs[ BLIS_MC ], 2016, 1008, 512, 400 ); bli_blksz_init_easy( &blkszs[ BLIS_KC ], 128, 128, 256, 160 ); bli_blksz_init_easy( &blkszs[ BLIS_NC ], 8400, 8400, 8400, 8400 ); // Update the context with the current architecture's register and cache // blocksizes (and multiples) for native execution. bli_cntx_set_blkszs ( BLIS_NAT, 5, BLIS_NC, &blkszs[ BLIS_NC ], BLIS_NR, BLIS_KC, &blkszs[ BLIS_KC ], BLIS_KR, BLIS_MC, &blkszs[ BLIS_MC ], BLIS_MR, BLIS_NR, &blkszs[ BLIS_NR ], BLIS_NR, BLIS_MR, &blkszs[ BLIS_MR ], BLIS_MR, cntx ); } blis-0.9.0/config/steamroller/bli_family_steamroller.h000066400000000000000000000035051422157504600231510ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ //#ifndef BLIS_FAMILY_H //#define BLIS_FAMILY_H // -- MEMORY ALLOCATION -------------------------------------------------------- #define BLIS_SIMD_ALIGN_SIZE 16 //#endif blis-0.9.0/config/steamroller/make_defs.mk000066400000000000000000000061521422157504600205300ustar00rootroot00000000000000# # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2014, The University of Texas at Austin # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # # Declare the name of the current configuration and add it to the # running list of configurations included by common.mk. THIS_CONFIG := steamroller #CONFIGS_INCL += $(THIS_CONFIG) # # --- Determine the C compiler and related flags --- # # NOTE: The build system will append these variables with various # general-purpose/configuration-agnostic flags in common.mk. You # may specify additional flags here as needed. CPPROCFLAGS := CMISCFLAGS := CPICFLAGS := CWARNFLAGS := ifneq ($(DEBUG_TYPE),off) CDBGFLAGS := -g endif ifeq ($(DEBUG_TYPE),noopt) COPTFLAGS := -O0 else COPTFLAGS := -O2 endif # Flags specific to optimized kernels. CKOPTFLAGS := $(COPTFLAGS) -O3 ifeq ($(CC_VENDOR),gcc) CKVECFLAGS := -mfpmath=sse -mavx -mfma -march=bdver3 -mno-fma4 -mno-tbm -mno-xop -mno-lwp else ifeq ($(CC_VENDOR),clang) CKVECFLAGS := -mfpmath=sse -mavx -mfma -march=bdver3 -mno-fma4 -mno-tbm -mno-xop -mno-lwp else $(error gcc or clang are required for this configuration.) endif endif # Flags specific to reference kernels. CROPTFLAGS := $(CKOPTFLAGS) ifeq ($(CC_VENDOR),gcc) CRVECFLAGS := $(CKVECFLAGS) -funsafe-math-optimizations -ffp-contract=fast else ifeq ($(CC_VENDOR),clang) CRVECFLAGS := $(CKVECFLAGS) -funsafe-math-optimizations -ffp-contract=fast else CRVECFLAGS := $(CKVECFLAGS) endif endif # Store all of the variables here to new variables containing the # configuration name. $(eval $(call store-make-defs,$(THIS_CONFIG))) blis-0.9.0/config/template/000077500000000000000000000000001422157504600155375ustar00rootroot00000000000000blis-0.9.0/config/template/bli_cntx_init_template.c000066400000000000000000000076571422157504600224420ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_cntx_init_template( cntx_t* cntx ) { blksz_t blkszs[ BLIS_NUM_BLKSZS ]; // Set default kernel blocksizes and functions. bli_cntx_init_template_ref( cntx ); // ------------------------------------------------------------------------- // Update the context with optimized native gemm micro-kernels and // their storage preferences. bli_cntx_set_l3_nat_ukrs ( 5, BLIS_GEMM_UKR, BLIS_DCOMPLEX, bli_zgemm_template_noopt, FALSE, BLIS_GEMMTRSM_L_UKR, BLIS_DCOMPLEX, bli_zgemmtrsm_l_template_noopt, FALSE, BLIS_GEMMTRSM_U_UKR, BLIS_DCOMPLEX, bli_zgemmtrsm_u_template_noopt, FALSE, BLIS_TRSM_L_UKR, BLIS_DCOMPLEX, bli_ztrsm_l_template_noopt, FALSE, BLIS_TRSM_U_UKR, BLIS_DCOMPLEX, bli_ztrsm_u_template_noopt, FALSE, cntx ); // Update the context with optimized level-1f kernels. bli_cntx_set_l1f_kers ( BLIS_AXPY2V_KER, BLIS_DCOMPLEX, bli_zaxpy2v_template_noopt, BLIS_DOTAXPYV_KER, BLIS_DCOMPLEX, bli_zdotaxpyv_template_noopt, BLIS_AXPYF_KER, BLIS_DCOMPLEX, bli_zaxpyf_template_noopt, BLIS_DOTXF_KER, BLIS_DCOMPLEX, bli_zdotxf_template_noopt, BLIS_DOTXAXPYF_KER, BLIS_DCOMPLEX, bli_zdotxaxpyf_template_noopt, cntx ); // Update the context with optimized level-1v kernels. bli_cntx_set_l1v_kers ( BLIS_AXPYV_KER, BLIS_DCOMPLEX, bli_zaxpyv_template_noopt, BLIS_DOTV_KER, BLIS_DCOMPLEX, bli_zdotv_template_noopt, cntx ); // Initialize level-3 blocksize objects with architecture-specific values. // s d c z bli_blksz_init_easy( &blkszs[ BLIS_MR ], 0, 0, 0, 4 ); bli_blksz_init_easy( &blkszs[ BLIS_NR ], 0, 0, 0, 4 ); bli_blksz_init_easy( &blkszs[ BLIS_MC ], 0, 0, 0, 128 ); bli_blksz_init_easy( &blkszs[ BLIS_KC ], 0, 0, 0, 256 ); bli_blksz_init_easy( &blkszs[ BLIS_NC ], 0, 0, 0, 4096 ); // Update the context with the current architecture's register and cache // blocksizes (and multiples) for native execution. bli_cntx_set_blkszs ( BLIS_NAT, 5, BLIS_NC, &blkszs[ BLIS_NC ], BLIS_NR, BLIS_KC, &blkszs[ BLIS_KC ], BLIS_KR, BLIS_MC, &blkszs[ BLIS_MC ], BLIS_MR, BLIS_NR, &blkszs[ BLIS_NR ], BLIS_NR, BLIS_MR, &blkszs[ BLIS_MR ], BLIS_MR, cntx ); } blis-0.9.0/config/template/bli_family_template.h000066400000000000000000000033071422157504600217150ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ //#ifndef BLIS_FAMILY_H //#define BLIS_FAMILY_H //#endif blis-0.9.0/config/template/kernels/000077500000000000000000000000001422157504600172025ustar00rootroot00000000000000blis-0.9.0/config/template/kernels/1/000077500000000000000000000000001422157504600173425ustar00rootroot00000000000000blis-0.9.0/config/template/kernels/1/bli_axpyv_template_noopt_var1.c000066400000000000000000000154101422157504600255470ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_zaxpyv_template_noopt ( conj_t conjx, dim_t n, dcomplex* restrict alpha, dcomplex* restrict x, inc_t incx, dcomplex* restrict y, inc_t incy, cntx_t* restrict cntx ) { /* Template axpyv kernel implementation This function contains a template implementation for a double-precision complex kernel, coded in C, which can serve as the starting point for one to write an optimized kernel on an arbitrary architecture. (We show a template implementation for only double-precision complex because the templates for the other three floating-point types would be similar, with the real instantiations being noticeably simpler due to the disappearance of conjugation in the real domain.) This kernel performs a vector scale and accumulate (axpy) operation: y := y + alpha * conjx( x ) where x and y are vectors of length n and alpha is a scalar. Parameters: - conjx: Compute with conjugated values of x? - n: The number of elements in vectors x and y. - alpha: The address of a scalar. - x: The address of vector x. - incx: The vector increment of x. incx should be unit unless the implementation makes special accomodation for non-unit values. - y: The address of vector y. - incy: The vector increment of y. incy should be unit unless the implementation makes special accomodation for non-unit values. This template code calls the reference implementation if any of the following conditions are true: - Either of the strides incx or incy is non-unit. - Vectors x and y are unaligned with different offsets. If the vectors are aligned, or unaligned by the same offset, then optimized code can be used for the bulk of the computation. This template shows how the front-edge case can be handled so that the remaining computation is aligned. (This template guarantees alignment to be BLIS_SIMD_ALIGN_SIZE.) Additional things to consider: - Because conjugation disappears in the real domain, real instances of this kernel can safely ignore the values of any conjugation parameters, thereby simplifying the implementation. For more info, please refer to the BLIS website and/or contact the blis-devel mailing list. -FGVZ */ const dim_t n_elem_per_reg = 1; const dim_t n_iter_unroll = 1; const dim_t n_elem_per_iter = n_elem_per_reg * n_iter_unroll; const siz_t type_size = sizeof( *x ); dcomplex* xp; dcomplex* yp; bool use_ref = FALSE; dim_t n_pre = 0; dim_t n_iter; dim_t n_left; dim_t off_x, off_y; dim_t i; if ( bli_zero_dim1( n ) ) return; if ( bli_zeq0( *alpha ) ) return; // If there is anything that would interfere with our use of aligned // vector loads/stores, call the reference implementation. if ( bli_has_nonunit_inc2( incx, incy ) ) { use_ref = TRUE; } else if ( bli_is_unaligned_to( x, BLIS_SIMD_ALIGN_SIZE ) || bli_is_unaligned_to( y, BLIS_SIMD_ALIGN_SIZE ) ) { use_ref = TRUE; // If a, the second column of a, and y are unaligned by the same // offset, then we can still use an implementation that depends on // alignment for most of the operation. off_x = bli_offset_from_alignment( x, BLIS_SIMD_ALIGN_SIZE ); off_y = bli_offset_from_alignment( y, BLIS_SIMD_ALIGN_SIZE ); if ( off_x == off_y ) { use_ref = FALSE; n_pre = off_x / type_size; } } // Call the reference implementation if needed. if ( use_ref == TRUE ) { zaxpyv_ft f = bli_zaxpyv_template_ref; f ( conjx, n, alpha, x, incx, y, incy, cntx ); return; } // Compute the number of unrolled and leftover (edge) iterations. n_iter = ( n - n_pre ) / n_elem_per_iter; n_left = ( n - n_pre ) % n_elem_per_iter; // Initialize pointers into x and y. xp = x; yp = y; // Iterate over elements of x and y to compute: // y += alpha * conjx( x ); if ( bli_is_noconj( conjx ) ) { // Compute front edge cases if x and y were unaligned. for ( i = 0; i < n_pre; ++i ) { bli_zaxpys( *alpha, *xp, *yp ); xp += 1; yp += 1; } // The bulk of the operation is executed here. The addresses xp and // yp are guaranteed to be aligned to BLIS_SIMD_ALIGN_SIZE. for ( i = 0; i < n_iter; ++i ) { bli_zaxpys( *alpha, *xp, *yp ); xp += n_elem_per_iter; yp += n_elem_per_iter; } // Compute tail edge cases, if applicable. for ( i = 0; i < n_left; ++i ) { bli_zaxpys( *alpha, *xp, *yp ); xp += 1; yp += 1; } } else // if ( bli_is_conj( conjx ) ) { // Compute front edge cases if x and y were unaligned. for ( i = 0; i < n_pre; ++i ) { bli_zaxpyjs( *alpha, *xp, *yp ); xp += 1; yp += 1; } // The bulk of the operation is executed here. The addresses xp and // yp are guaranteed to be aligned to BLIS_SIMD_ALIGN_SIZE. for ( i = 0; i < n_iter; ++i ) { bli_zaxpyjs( *alpha, *xp, *yp ); xp += n_elem_per_iter; yp += n_elem_per_iter; } // Compute tail edge cases, if applicable. for ( i = 0; i < n_left; ++i ) { bli_zaxpyjs( *alpha, *xp, *yp ); xp += 1; yp += 1; } } } blis-0.9.0/config/template/kernels/1/bli_dotv_template_noopt_var1.c000066400000000000000000000172501422157504600253600ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_zdotv_template_noopt ( conj_t conjx, conj_t conjy, dim_t n, dcomplex* restrict x, inc_t incx, dcomplex* restrict y, inc_t incy, dcomplex* restrict rho, cntx_t* restrict cntx ) { /* Template dotv kernel implementation This function contains a template implementation for a double-precision complex kernel, coded in C, which can serve as the starting point for one to write an optimized kernel on an arbitrary architecture. (We show a template implementation for only double-precision complex because the templates for the other three floating-point types would be similar, with the real instantiations being noticeably simpler due to the disappearance of conjugation in the real domain.) This kernel performs an inner (dot) product operation: rho := conjx( x^T ) * conjy( y ) where x and y are vectors of length n and rho is a scalar. Parameters: - conjx: Compute with conjugated values of x? - conjy: Compute with conjugated values of y? - n: The number of elements in vectors x and y. - x: The address of vector x. - incx: The vector increment of x. incx should be unit unless the implementation makes special accomodation for non-unit values. - y: The address of vector y. - incy: The vector increment of y. incy should be unit unless the implementation makes special accomodation for non-unit values. - rho: The address of the output scalar. This template code calls the reference implementation if any of the following conditions are true: - Either of the strides incx or incy is non-unit. - Vectors x and y are unaligned with different offsets. If the vectors are aligned, or unaligned by the same offset, then optimized code can be used for the bulk of the computation. This template shows how the front-edge case can be handled so that the remaining computation is aligned. (This template guarantees alignment to be BLIS_SIMD_ALIGN_SIZE.) Additional things to consider: - While four combinations of possible values of conjx and conjy exist, we implement only conjugation on x explicitly; we induce the other two cases by toggling the effective conjugation on x and then conjugating the dot product result. - Because conjugation disappears in the real domain, real instances of this kernel can safely ignore the values of any conjugation parameters, thereby simplifying the implementation. For more info, please refer to the BLIS website and/or contact the blis-devel mailing list. -FGVZ */ const dim_t n_elem_per_reg = 1; const dim_t n_iter_unroll = 1; const dim_t n_elem_per_iter = n_elem_per_reg * n_iter_unroll; const siz_t type_size = sizeof( *x ); dcomplex* xp; dcomplex* yp; dcomplex dotxy; bool use_ref = FALSE; dim_t n_pre = 0; dim_t n_iter; dim_t n_left; dim_t off_x, off_y; dim_t i; conj_t conjx_use; // If the vector lengths are zero, set rho to zero and return. if ( bli_zero_dim1( n ) ) { bli_zset0s( *rho ); return; } // If there is anything that would interfere with our use of aligned // vector loads/stores, call the reference implementation. if ( bli_has_nonunit_inc2( incx, incy ) ) { use_ref = TRUE; } else if ( bli_is_unaligned_to( x, BLIS_SIMD_ALIGN_SIZE ) || bli_is_unaligned_to( y, BLIS_SIMD_ALIGN_SIZE ) ) { use_ref = TRUE; // If a, the second column of a, and y are unaligned by the same // offset, then we can still use an implementation that depends on // alignment for most of the operation. off_x = bli_offset_from_alignment( x, BLIS_SIMD_ALIGN_SIZE ); off_y = bli_offset_from_alignment( y, BLIS_SIMD_ALIGN_SIZE ); if ( off_x == off_y ) { use_ref = FALSE; n_pre = off_x / type_size; } } // Call the reference implementation if needed. if ( use_ref == TRUE ) { zdotv_ft f = bli_zdotv_template_ref; f ( conjx, conjy, n, x, incx, y, incy, rho, cntx ); return; } // Compute the number of unrolled and leftover (edge) iterations. n_iter = ( n - n_pre ) / n_elem_per_iter; n_left = ( n - n_pre ) % n_elem_per_iter; // Initialize pointers into x and y. xp = x; yp = y; // Initialize accumulator to zero. bli_zset0s( dotxy ); conjx_use = conjx; // If y must be conjugated, we compute the result indirectly by first // toggling the effective conjugation of x and then conjugating the // resulting dot product. if ( bli_is_conj( conjy ) ) bli_toggle_conj( &conjx_use ); // Iterate over elements of x and y to compute: // rho = conjx( x^T ) * conjy( y ); if ( bli_is_noconj( conjx_use ) ) { // Compute front edge cases if x and y were unaligned. for ( i = 0; i < n_pre; ++i ) { bli_zdots( *xp, *yp, dotxy ); xp += 1; yp += 1; } // The bulk of the operation is executed here. The addresses xp and // yp are guaranteed to be aligned to BLIS_SIMD_ALIGN_SIZE. for ( i = 0; i < n_iter; ++i ) { bli_zdots( *xp, *yp, dotxy ); xp += n_elem_per_iter; yp += n_elem_per_iter; } // Compute tail edge cases, if applicable. for ( i = 0; i < n_left; ++i ) { bli_zdots( *xp, *yp, dotxy ); xp += 1; yp += 1; } } else // if ( bli_is_conj( conjx_use ) ) { // Compute front edge cases if x and y were unaligned. for ( i = 0; i < n_pre; ++i ) { bli_zdotjs( *xp, *yp, dotxy ); xp += 1; yp += 1; } // The bulk of the operation is executed here. The addresses xp and // yp are guaranteed to be aligned to BLIS_SIMD_ALIGN_SIZE. for ( i = 0; i < n_iter; ++i ) { bli_zdotjs( *xp, *yp, dotxy ); xp += n_elem_per_iter; yp += n_elem_per_iter; } // Compute tail edge cases, if applicable. for ( i = 0; i < n_left; ++i ) { bli_zdotjs( *xp, *yp, dotxy ); xp += 1; yp += 1; } } // If conjugation on y was requested, we induce it by conjugating // the contents of dotxy. if ( bli_is_conj( conjy ) ) bli_zconjs( dotxy ); bli_zcopys( dotxy, *rho ); } blis-0.9.0/config/template/kernels/1f/000077500000000000000000000000001422157504600175105ustar00rootroot00000000000000blis-0.9.0/config/template/kernels/1f/bli_axpy2v_template_noopt_var1.c000066400000000000000000000240661422157504600260060ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_zaxpy2v_template_noopt ( conj_t conjx, conj_t conjy, dim_t n, dcomplex* restrict alpha1, dcomplex* restrict alpha2, dcomplex* restrict x, inc_t incx, dcomplex* restrict y, inc_t incy, dcomplex* restrict z, inc_t incz, cntx_t* restrict cntx ) { /* Template axpy2v kernel implementation This function contains a template implementation for a double-precision complex kernel, coded in C, which can serve as the starting point for one to write an optimized kernel on an arbitrary architecture. (We show a template implementation for only double-precision complex because the templates for the other three floating-point types would be similar, with the real instantiations being noticeably simpler due to the disappearance of conjugation in the real domain.) This kernel fuses two axpyv operations: z := z + alpha1 * conjx( x ) z := z + alpha2 * conjy( y ) where x, y, and z are vectors of length n and alpha1 and alpha2 are scalars. Parameters: - conjx: Compute with conjugated values of x? - conjy: Compute with conjugated values of y? - n: The number of elements in vectors x, y, and z. - alpha1: The address of the scalar to be applied to x. - alpha2: The address of the scalar to be applied to y. - x: The address of vector x. - incx: The vector increment of x. incx should be unit unless the implementation makes special accomodation for non-unit values. - y: The address of vector y. - incy: The vector increment of y. incy should be unit unless the implementation makes special accomodation for non-unit values. - z: The address of vector z. - incz: The vector increment of z. incz should be unit unless the implementation makes special accomodation for non-unit values. This template code calls the reference implementation if any of the following conditions are true: - Any of the strides incx, incy, or incz is non-unit. - Vectors x, y, and z are unaligned with different offsets. If the vectors are aligned, or unaligned by the same offset, then optimized code can be used for the bulk of the computation. This template shows how the front-edge case can be handled so that the remaining computation is aligned. (This template guarantees alignment in the main loops to be BLIS_SIMD_ALIGN_SIZE.) Here are a few additional things to consider: - Because conjugation disappears in the real domain, real instances of this kernel can safely ignore the values of any conjugation parameters, thereby simplifying the implementation. For more info, please refer to the BLIS website and/or contact the blis-devel mailing list. -FGVZ */ const dim_t n_elem_per_reg = 1; const dim_t n_iter_unroll = 1; const dim_t n_elem_per_iter = n_elem_per_reg * n_iter_unroll; const siz_t type_size = sizeof( *x ); dcomplex* xp; dcomplex* yp; dcomplex* zp; bool use_ref = FALSE; dim_t n_pre = 0; dim_t n_iter; dim_t n_left; dim_t off_x, off_y, off_z; dim_t i; // Return early if possible. if ( bli_zero_dim1( n ) ) return; // If there is anything that would interfere with our use of aligned // vector loads/stores, call the reference implementation. if ( bli_has_nonunit_inc3( incx, incy, incz ) ) { use_ref = TRUE; } else if ( bli_is_unaligned_to( x, BLIS_SIMD_ALIGN_SIZE ) || bli_is_unaligned_to( y, BLIS_SIMD_ALIGN_SIZE ) || bli_is_unaligned_to( z, BLIS_SIMD_ALIGN_SIZE ) ) { use_ref = TRUE; // If a, the second column of a, and y are unaligned by the same // offset, then we can still use an implementation that depends on // alignment for most of the operation. off_x = bli_offset_from_alignment( x, BLIS_SIMD_ALIGN_SIZE ); off_y = bli_offset_from_alignment( y, BLIS_SIMD_ALIGN_SIZE ); off_z = bli_offset_from_alignment( z, BLIS_SIMD_ALIGN_SIZE ); if ( off_x == off_y && off_x == off_z ) { use_ref = FALSE; n_pre = off_x / type_size; } } // Call the reference implementation if needed. if ( use_ref == TRUE ) { zaxpy2v_ft f = bli_zaxpy2v_template_ref; f ( conjx, conjy, n, alpha1, alpha2, x, incx, y, incy, z, incz, cntx ); return; } // Compute the number of unrolled and leftover (edge) iterations. n_iter = ( n - n_pre ) / n_elem_per_iter; n_left = ( n - n_pre ) % n_elem_per_iter; // Initialize pointers into x, y, and z. xp = x; yp = y; zp = z; // Iterate over rows of x, y, and z to compute: // z += alpha1 * conjx( x ) + alpha2 * conjy( y ); if ( bli_is_noconj( conjx ) && bli_is_noconj( conjy ) ) { // Compute front edge cases if x, y, and z were unaligned. for ( i = 0; i < n_pre; ++i ) { bli_zaxpys( *alpha1, *xp, *zp ); bli_zaxpys( *alpha2, *yp, *zp ); xp += 1; yp += 1; zp += 1; } // The bulk of the operation is executed here. For best performance, // alpha1 and alpha2 should be loaded once prior to the n_iter // loop and the elements of z should be loaded and stored only once // each. The addresses xp, yp, and zp are guaranteed to be aligned // to BLIS_SIMD_ALIGN_SIZE. for ( i = 0; i < n_iter; ++i ) { bli_zaxpys( *alpha1, *xp, *zp ); bli_zaxpys( *alpha2, *yp, *zp ); xp += n_elem_per_iter; yp += n_elem_per_iter; zp += n_elem_per_iter; } // Compute tail edge cases, if applicable. for ( i = 0; i < n_left; ++i ) { bli_zaxpys( *alpha1, *xp, *zp ); bli_zaxpys( *alpha2, *yp, *zp ); xp += 1; yp += 1; zp += 1; } } else if ( bli_is_noconj( conjx ) && bli_is_conj( conjy ) ) { // Compute front edge cases if x, y, and z were unaligned. for ( i = 0; i < n_pre; ++i ) { bli_zaxpys( *alpha1, *xp, *zp ); bli_zaxpyjs( *alpha2, *yp, *zp ); xp += 1; yp += 1; zp += 1; } // The bulk of the operation is executed here. For best performance, // alpha1 and alpha2 should be loaded once prior to the n_iter // loop and the elements of z should be loaded and stored only once // each. The addresses xp, yp, and zp are guaranteed to be aligned // to BLIS_SIMD_ALIGN_SIZE. for ( i = 0; i < n_iter; ++i ) { bli_zaxpys( *alpha1, *xp, *zp ); bli_zaxpyjs( *alpha2, *yp, *zp ); xp += n_elem_per_iter; yp += n_elem_per_iter; zp += n_elem_per_iter; } // Compute tail edge cases, if applicable. for ( i = 0; i < n_left; ++i ) { bli_zaxpys( *alpha1, *xp, *zp ); bli_zaxpyjs( *alpha2, *yp, *zp ); xp += 1; yp += 1; zp += 1; } } else if ( bli_is_conj( conjx ) && bli_is_noconj( conjy ) ) { // Compute front edge cases if x, y, and z were unaligned. for ( i = 0; i < n_pre; ++i ) { bli_zaxpyjs( *alpha1, *xp, *zp ); bli_zaxpys( *alpha2, *yp, *zp ); xp += 1; yp += 1; zp += 1; } // The bulk of the operation is executed here. For best performance, // alpha1 and alpha2 should be loaded once prior to the n_iter // loop and the elements of z should be loaded and stored only once // each. The addresses xp, yp, and zp are guaranteed to be aligned // to BLIS_SIMD_ALIGN_SIZE. for ( i = 0; i < n_iter; ++i ) { bli_zaxpyjs( *alpha1, *xp, *zp ); bli_zaxpys( *alpha2, *yp, *zp ); xp += n_elem_per_iter; yp += n_elem_per_iter; zp += n_elem_per_iter; } // Compute tail edge cases, if applicable. for ( i = 0; i < n_left; ++i ) { bli_zaxpyjs( *alpha1, *xp, *zp ); bli_zaxpys( *alpha2, *yp, *zp ); xp += 1; yp += 1; zp += 1; } } else // if ( bli_is_conj( conjx ) && bli_is_conj( conjy ) ) { // Compute front edge cases if x, y, and z were unaligned. for ( i = 0; i < n_pre; ++i ) { bli_zaxpyjs( *alpha1, *xp, *zp ); bli_zaxpyjs( *alpha2, *yp, *zp ); xp += 1; yp += 1; zp += 1; } // The bulk of the operation is executed here. For best performance, // alpha1 and alpha2 should be loaded once prior to the n_iter // loop and the elements of z should be loaded and stored only once // each. The addresses xp, yp, and zp are guaranteed to be aligned // to BLIS_SIMD_ALIGN_SIZE. for ( i = 0; i < n_iter; ++i ) { bli_zaxpyjs( *alpha1, *xp, *zp ); bli_zaxpyjs( *alpha2, *yp, *zp ); xp += n_elem_per_iter; yp += n_elem_per_iter; zp += n_elem_per_iter; } // Compute tail edge cases, if applicable. for ( i = 0; i < n_left; ++i ) { bli_zaxpyjs( *alpha1, *xp, *zp ); bli_zaxpyjs( *alpha2, *yp, *zp ); xp += 1; yp += 1; zp += 1; } } } blis-0.9.0/config/template/kernels/1f/bli_axpyf_template_noopt_var1.c000066400000000000000000000223431422157504600257000ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_zaxpyf_template_noopt ( conj_t conja, conj_t conjx, dim_t m, dim_t b_n, dcomplex* restrict alpha, dcomplex* restrict a, inc_t inca, inc_t lda, dcomplex* restrict x, inc_t incx, dcomplex* restrict y, inc_t incy, cntx_t* restrict cntx ) { /* Template axpyf kernel implementation This function contains a template implementation for a double-precision complex kernel, coded in C, which can serve as the starting point for one to write an optimized kernel on an arbitrary architecture. (We show a template implementation for only double-precision complex because the templates for the other three floating-point types would be similar, with the real instantiations being noticeably simpler due to the disappearance of conjugation in the real domain.) This kernel performs the following gemv-like operation: y := y + alpha * conja( A ) * conjx( x ) where A is an m x b_n matrix, x is a vector of length b_n, y is a vector of length m, and alpha is a scalar. The operation is performed as a series of fused axpyv operations, and therefore A should be column-stored. Parameters: - conja: Compute with conjugated values of A? - conjx: Compute with conjugated values of x? - m: The number of rows in matrix A. - b_n: The number of columns in matrix A. Must be equal to or less than the fusing factor. - alpha: The address of a scalar. - a: The address of matrix A. - inca: The row stride of A. inca should be unit unless the implementation makes special accomodation for non-unit values. - lda: The column stride of A. - x: The address of vector x. - incx: The vector increment of x. - y: The address of vector y. - incy: The vector increment of y. incy should be unit unless the implementation makes special accomodation for non-unit values. This template code calls the reference implementation if any of the following conditions are true: - Either of the strides inca or incy is non-unit. - The address of A, the second column of A, and y are unaligned with different offsets. If the first/second columns of A and address of y are aligned, or unaligned by the same offset, then optimized code can be used for the bulk of the computation. This template shows how the front-edge case can be handled so that the remaining computation is aligned. (This template guarantees alignment in the main loops to be BLIS_SIMD_ALIGN_SIZE.) Additional things to consider: - When optimizing, you should fully unroll the loops over b_n. This is the dimension across which we are fusing axpyv operations. - This template code chooses to call the reference implementation whenever b_n is less than the fusing factor, so as to avoid having to handle edge cases. One may choose to optimize this edge case, if desired. - Because conjugation disappears in the real domain, real instances of this kernel can safely ignore the values of any conjugation parameters, thereby simplifying the implementation. For more info, please refer to the BLIS website and/or contact the blis-devel mailing list. -FGVZ */ const dim_t n_elem_per_reg = 1; const dim_t n_iter_unroll = 1; const dim_t n_elem_per_iter = n_elem_per_reg * n_iter_unroll; const siz_t type_size = sizeof( *a ); dcomplex* ap[ bli_zaxpyf_fusefac ]; dcomplex* xp[ bli_zaxpyf_fusefac ]; dcomplex* yp; dcomplex alpha_x[ bli_zaxpyf_fusefac ]; bool use_ref = FALSE; dim_t m_pre = 0; dim_t m_iter; dim_t m_left; dim_t off_a, off_a2, off_y; dim_t i, j; // Return early if possible. if ( bli_zero_dim2( m, b_n ) ) return; // If there is anything that would interfere with our use of aligned // vector loads/stores, call the reference implementation. if ( b_n < bli_zaxpyf_fusefac ) { use_ref = TRUE; } else if ( bli_has_nonunit_inc3( inca, incx, incy ) ) { use_ref = TRUE; } else if ( bli_is_unaligned_to( a, BLIS_SIMD_ALIGN_SIZE ) || bli_is_unaligned_to( a+lda, BLIS_SIMD_ALIGN_SIZE ) || bli_is_unaligned_to( y, BLIS_SIMD_ALIGN_SIZE ) ) { use_ref = TRUE; // If a, the second column of a, and y are unaligned by the same // offset, then we can still use an implementation that depends on // alignment for most of the operation. off_a = bli_offset_from_alignment( a, BLIS_SIMD_ALIGN_SIZE ); off_a2 = bli_offset_from_alignment( a+lda, BLIS_SIMD_ALIGN_SIZE ); off_y = bli_offset_from_alignment( y, BLIS_SIMD_ALIGN_SIZE ); if ( off_a == off_y && off_a == off_a2 ) { use_ref = FALSE; m_pre = off_a / type_size; } } // Call the reference implementation if needed. if ( use_ref == TRUE ) { zaxpyf_ft f = bli_zaxpyf_template_ref; f ( conja, conjx, m, b_n, alpha, a, inca, lda, x, incx, y, incy, cntx ); return; } // Compute the number of unrolled and leftover (edge) iterations. m_iter = ( m - m_pre ) / n_elem_per_iter; m_left = ( m - m_pre ) % n_elem_per_iter; // Initialize pointers into the columns of A and elements of x. for ( j = 0; j < b_n; ++j ) { ap[ j ] = a + (j )*lda; xp[ j ] = x + (j )*incx; } yp = y; // Load elements of x or conj(x) into alpha_x and scale by alpha. if ( bli_is_noconj( conjx ) ) { for ( j = 0; j < b_n; ++j ) { bli_zcopys( *xp[ j ], alpha_x[ j ] ); bli_zscals( *alpha, alpha_x[ j ] ); } } else // if ( bli_is_conj( conjx ) ) { for ( j = 0; j < b_n; ++j ) { bli_zcopyjs( *xp[ j ], alpha_x[ j ] ); bli_zscals( *alpha, alpha_x[ j ] ); } } // Iterate over rows of A and y to compute: // y += conja( A )*conjx( x ); if ( bli_is_noconj( conja ) ) { // Compute front edge cases if a and y were unaligned. for ( i = 0; i < m_pre; ++i ) { for ( j = 0; j < b_n; ++j ) { bli_zaxpys( alpha_x[ j ], *ap[ j ], *yp ); ap[ j ] += 1; } yp += 1; } // The bulk of the operation is executed here. For best performance, // the elements of alpha_x should be loaded once prior to the m_iter // loop, and the b_n loop should be fully unrolled. The addresses in // ap[] and yp are guaranteed to be aligned to // BLIS_SIMD_ALIGN_SIZE. for ( i = 0; i < m_iter; ++i ) { for ( j = 0; j < b_n; ++j ) { bli_zaxpys( alpha_x[ j ], *ap[ j ], *yp ); ap[ j ] += n_elem_per_iter; } yp += n_elem_per_iter; } // Compute tail edge cases, if applicable. for ( i = 0; i < m_left; ++i ) { for ( j = 0; j < b_n; ++j ) { bli_zaxpys( alpha_x[ j ], *ap[ j ], *yp ); ap[ j ] += 1; } yp += 1; } } else // if ( bli_is_conj( conja ) ) { // Compute front edge cases if a and y were unaligned. for ( i = 0; i < m_pre; ++i ) { for ( j = 0; j < b_n; ++j ) { bli_zaxpyjs( alpha_x[ j ], *ap[ j ], *yp ); ap[ j ] += 1; } yp += 1; } // The bulk of the operation is executed here. For best performance, // the elements of alpha_x should be loaded once prior to the m_iter // loop, and the b_n loop should be fully unrolled. The addresses in // ap[] and yp are guaranteed to be aligned to // BLIS_SIMD_ALIGN_SIZE. for ( i = 0; i < m_iter; ++i ) { for ( j = 0; j < b_n; ++j ) { bli_zaxpyjs( alpha_x[ j ], *ap[ j ], *yp ); ap[ j ] += n_elem_per_iter; } yp += n_elem_per_iter; } // Compute tail edge cases. for ( i = 0; i < m_left; ++i ) { for ( j = 0; j < b_n; ++j ) { bli_zaxpyjs( alpha_x[ j ], *ap[ j ], *yp ); ap[ j ] += 1; } yp += 1; } } } blis-0.9.0/config/template/kernels/1f/bli_dotaxpyv_template_noopt_var1.c000066400000000000000000000260401422157504600264250ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_zdotaxpyv_template_noopt ( conj_t conjxt, conj_t conjx, conj_t conjy, dim_t n, dcomplex* restrict alpha, dcomplex* restrict x, inc_t incx, dcomplex* restrict y, inc_t incy, dcomplex* restrict rho, dcomplex* restrict z, inc_t incz, cntx_t* restrict cntx ) { /* Template dotaxpyv kernel implementation This function contains a template implementation for a double-precision complex kernel, coded in C, which can serve as the starting point for one to write an optimized kernel on an arbitrary architecture. (We show a template implementation for only double-precision complex because the templates for the other three floating-point types would be similar, with the real instantiations being noticeably simpler due to the disappearance of conjugation in the real domain.) This kernel fuses a dotv and axpyv operation: rho := conjxt( x^T ) * conjy( y ) z := z + alpha * conjx( x ) where x, y, and z are vectors of length n and alpha1 and alpha2 are scalars. Parameters: - conjxt: Compute with conjugated values of x^T? - conjx: Compute with conjugated values of x? - conjy: Compute with conjugated values of y? - n: The number of elements in vectors x, y, and z. - alpha: The address of the scalar to be applied to x. - x: The address of vector x. - incx: The vector increment of x. incx should be unit unless the implementation makes special accomodation for non-unit values. - y: The address of vector y. - incy: The vector increment of y. incy should be unit unless the implementation makes special accomodation for non-unit values. - rho: The address of the output scalar of the dotv subproblem. - z: The address of vector z. - incz: The vector increment of z. incz should be unit unless the implementation makes special accomodation for non-unit values. This template code calls the reference implementation if any of the following conditions are true: - Any of the strides incx, incy, or incz is non-unit. - Vectors x, y, and z are unaligned with different offsets. If the vectors are aligned, or unaligned by the same offset, then optimized code can be used for the bulk of the computation. This template shows how the front-edge case can be handled so that the remaining computation is aligned. (This template guarantees alignment in the main loops to be BLIS_SIMD_ALIGN_SIZE.) Here are a few additional things to consider: - While four combinations of possible values of conjx and conjy exist, we implement only conjugation on x explicitly; we induce the other two cases by toggling the effective conjugation on x and then conjugating the dot product result. - Because conjugation disappears in the real domain, real instances of this kernel can safely ignore the values of any conjugation parameters, thereby simplifying the implementation. For more info, please refer to the BLIS website and/or contact the blis-devel mailing list. -FGVZ */ const dim_t n_elem_per_reg = 1; const dim_t n_iter_unroll = 1; const dim_t n_elem_per_iter = n_elem_per_reg * n_iter_unroll; const siz_t type_size = sizeof( *x ); dcomplex* xp; dcomplex* yp; dcomplex* zp; dcomplex dotxy; bool use_ref = FALSE; dim_t n_pre = 0; dim_t n_iter; dim_t n_left; dim_t off_x, off_y, off_z; dim_t i; conj_t conjxt_use; // If the vector lengths are zero, set rho to zero and return. if ( bli_zero_dim1( n ) ) { bli_zset0s( *rho ); return; } // If there is anything that would interfere with our use of aligned // vector loads/stores, call the reference implementation. if ( bli_has_nonunit_inc3( incx, incy, incz ) ) { use_ref = TRUE; } else if ( bli_is_unaligned_to( x, BLIS_SIMD_ALIGN_SIZE ) || bli_is_unaligned_to( y, BLIS_SIMD_ALIGN_SIZE ) || bli_is_unaligned_to( z, BLIS_SIMD_ALIGN_SIZE ) ) { use_ref = TRUE; // If x, y, and z are unaligned by the same offset, then we can // still use an implementation that depends on alignment for most // of the operation. off_x = bli_offset_from_alignment( x, BLIS_SIMD_ALIGN_SIZE ); off_y = bli_offset_from_alignment( y, BLIS_SIMD_ALIGN_SIZE ); off_z = bli_offset_from_alignment( z, BLIS_SIMD_ALIGN_SIZE ); if ( off_x == off_y && off_x == off_z ) { use_ref = FALSE; n_pre = off_x / type_size; } } // Call the reference implementation if needed. if ( use_ref == TRUE ) { zdotaxpyv_ft f = bli_zdotaxpyv_template_ref; f ( conjxt, conjx, conjy, n, alpha, x, incx, y, incy, rho, z, incz, cntx ); return; } // Compute the number of unrolled and leftover (edge) iterations. n_iter = ( n - n_pre ) / n_elem_per_iter; n_left = ( n - n_pre ) % n_elem_per_iter; // Initialize pointers into x, y, and z. xp = x; yp = y; zp = z; // Initialize accumulator to zero. bli_zset0s( dotxy ); conjxt_use = conjxt; // If y must be conjugated, we compute the result indirectly by first // toggling the effective conjugation of xt and then conjugating the // resulting dot product. if ( bli_is_conj( conjy ) ) bli_toggle_conj( &conjxt_use ); // Iterate over elements of x, y, and z to compute: // r = conjxt( x^T ) * conjy( y ); // z += alpha * conjx( x ); if ( bli_is_noconj( conjx ) && bli_is_noconj( conjxt_use ) ) { // Compute front edge cases if x, y, and z were unaligned. for ( i = 0; i < n_pre; ++i ) { bli_zdots( *xp, *yp, dotxy ); bli_zaxpys( *alpha, *xp, *zp ); xp += 1; yp += 1; zp += 1; } // The bulk of the operation is executed here. For best performance, // alpha should be loaded once prior to the n_iter loop, dotxy // should be and kept in registers, and each element of x should be // loaded only once each. The addresses xp, yp, and zp are // guaranteed to be aligned to BLIS_SIMD_ALIGN_SIZE. for ( i = 0; i < n_iter; ++i ) { bli_zdots( *xp, *yp, dotxy ); bli_zaxpys( *alpha, *xp, *zp ); xp += n_elem_per_iter; yp += n_elem_per_iter; zp += n_elem_per_iter; } // Compute tail edge cases, if applicable. for ( i = 0; i < n_left; ++i ) { bli_zdots( *xp, *yp, dotxy ); bli_zaxpys( *alpha, *xp, *zp ); xp += 1; yp += 1; zp += 1; } } else if ( bli_is_noconj( conjx ) && bli_is_conj( conjxt_use ) ) { // Compute front edge cases if x, y, and z were unaligned. for ( i = 0; i < n_pre; ++i ) { bli_zdotjs( *xp, *yp, dotxy ); bli_zaxpys( *alpha, *xp, *zp ); xp += 1; yp += 1; zp += 1; } // The bulk of the operation is executed here. For best performance, // alpha should be loaded once prior to the n_iter loop, dotxy // should be and kept in registers, and each element of x should be // loaded only once each. The addresses xp, yp, and zp are // guaranteed to be aligned to BLIS_SIMD_ALIGN_SIZE. for ( i = 0; i < n_iter; ++i ) { bli_zdotjs( *xp, *yp, dotxy ); bli_zaxpys( *alpha, *xp, *zp ); xp += n_elem_per_iter; yp += n_elem_per_iter; zp += n_elem_per_iter; } // Compute tail edge cases, if applicable. for ( i = 0; i < n_left; ++i ) { bli_zdotjs( *xp, *yp, dotxy ); bli_zaxpys( *alpha, *xp, *zp ); xp += 1; yp += 1; zp += 1; } } else if ( bli_is_conj( conjx ) && bli_is_noconj( conjxt_use ) ) { // Compute front edge cases if x, y, and z were unaligned. for ( i = 0; i < n_pre; ++i ) { bli_zdots( *xp, *yp, dotxy ); bli_zaxpyjs( *alpha, *xp, *zp ); xp += 1; yp += 1; zp += 1; } // The bulk of the operation is executed here. For best performance, // alpha should be loaded once prior to the n_iter loop, dotxy // should be and kept in registers, and each element of x should be // loaded only once each. The addresses xp, yp, and zp are // guaranteed to be aligned to BLIS_SIMD_ALIGN_SIZE. for ( i = 0; i < n_iter; ++i ) { bli_zdots( *xp, *yp, dotxy ); bli_zaxpyjs( *alpha, *xp, *zp ); xp += n_elem_per_iter; yp += n_elem_per_iter; zp += n_elem_per_iter; } // Compute tail edge cases, if applicable. for ( i = 0; i < n_left; ++i ) { bli_zdots( *xp, *yp, dotxy ); bli_zaxpyjs( *alpha, *xp, *zp ); xp += 1; yp += 1; zp += 1; } } else // if ( bli_is_conj( conjx ) && bli_is_conj( conjxt_use ) ) { // Compute front edge cases if x, y, and z were unaligned. for ( i = 0; i < n_pre; ++i ) { bli_zdotjs( *xp, *yp, dotxy ); bli_zaxpyjs( *alpha, *xp, *zp ); xp += 1; yp += 1; zp += 1; } // The bulk of the operation is executed here. For best performance, // alpha should be loaded once prior to the n_iter loop, dotxy // should be and kept in registers, and each element of x should be // loaded only once each. The addresses xp, yp, and zp are // guaranteed to be aligned to BLIS_SIMD_ALIGN_SIZE. for ( i = 0; i < n_iter; ++i ) { bli_zdotjs( *xp, *yp, dotxy ); bli_zaxpyjs( *alpha, *xp, *zp ); xp += n_elem_per_iter; yp += n_elem_per_iter; zp += n_elem_per_iter; } // Compute tail edge cases, if applicable. for ( i = 0; i < n_left; ++i ) { bli_zdotjs( *xp, *yp, dotxy ); bli_zaxpyjs( *alpha, *xp, *zp ); xp += 1; yp += 1; zp += 1; } } // If conjugation on y was requested, we induce it by conjugating // the contents of rho. if ( bli_is_conj( conjy ) ) bli_zconjs( dotxy ); bli_zcopys( dotxy, *rho ); } blis-0.9.0/config/template/kernels/1f/bli_dotxaxpyf_template_noopt_var1.c000066400000000000000000000340001422157504600265700ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_zdotxaxpyf_template_noopt ( conj_t conjat, conj_t conja, conj_t conjw, conj_t conjx, dim_t m, dim_t b_n, dcomplex* restrict alpha, dcomplex* restrict a, inc_t inca, inc_t lda, dcomplex* restrict w, inc_t incw, dcomplex* restrict x, inc_t incx, dcomplex* restrict beta, dcomplex* restrict y, inc_t incy, dcomplex* restrict z, inc_t incz, cntx_t* restrict cntx ) { /* Template dotxaxpyf kernel implementation This function contains a template implementation for a double-precision complex kernel, coded in C, which can serve as the starting point for one to write an optimized kernel on an arbitrary architecture. (We show a template implementation for only double-precision complex because the templates for the other three floating-point types would be similar, with the real instantiations being noticeably simpler due to the disappearance of conjugation in the real domain.) This kernel performs the following two gemv-like operations: y := beta * y + alpha * conjat( A^T ) * conjw( w ) z := z + alpha * conja( A ) * conjx( x ) where A is an m x b_n matrix, x and y are vector of length b_n, w and z are vectors of length m, and alpha and beta are scalars. The operation fuses a dotxf and an axpyf operation, and therefore A should be column- stored. Parameters: - conjat: Compute with conjugated values of A^T? - conja: Compute with conjugated values of A? - conjw: Compute with conjugated values of w? - conjx: Compute with conjugated values of x? - m: The number of rows in matrix A. - b_n: The number of columns in matrix A. Must be equal to or less than the fusing factor. - alpha: The address of the scalar to be applied to A^T*w and A*x. - a: The address of matrix A. - inca: The row stride of A. inca should be unit unless the implementation makes special accomodation for non-unit values. - lda: The column stride of A. - w: The address of vector w. - incw: The vector increment of w. incw should be unit unless the implementation makes special accomodation for non-unit values. - x: The address of vector x. - incx: The vector increment of x. - beta: The address of the scalar to be applied to y. - y: The address of vector y. - incy: The vector increment of y. - z: The address of vector z. - incz: The vector increment of z. incz should be unit unless the implementation makes special accomodation for non-unit values. This template code calls the reference implementation if any of the following conditions are true: - Any of the strides inca, incw, or incz is non-unit. - The address of A, the second column of A, w, and z are unaligned with different offsets. If the first/second rows of A and addresses of w and z are aligned, or unaligned by the same offset, then optimized code can be used for the bulk of the computation. This template shows how the front-edge case can be handled so that the remaining computation is aligned. (This template guarantees alignment in the main loops to be BLIS_SIMD_ALIGN_SIZE.) Additional things to consider: - When optimizing, you should fully unroll the loops over b_n. This is the dimension across which we are fusing dotxv operations. - This template code chooses to call the reference implementation whenever b_n is less than the fusing factor, so as to avoid having to handle edge cases. One may choose to optimize this edge case, if desired. - Because conjugation disappears in the real domain, real instances of this kernel can safely ignore the values of any conjugation parameters, thereby simplifying the implementation. For more info, please refer to the BLIS website and/or contact the blis-devel mailing list. -FGVZ */ const dim_t n_elem_per_reg = 1; const dim_t n_iter_unroll = 1; const dim_t n_elem_per_iter = n_elem_per_reg * n_iter_unroll; const siz_t type_size = sizeof( *a ); dcomplex* ap[ bli_zdotxaxpyf_fusefac ]; dcomplex* xp[ bli_zdotxaxpyf_fusefac ]; dcomplex* yp[ bli_zdotxaxpyf_fusefac ]; dcomplex* wp; dcomplex* zp; dcomplex At_w[ bli_zdotxaxpyf_fusefac ]; dcomplex alpha_x[ bli_zdotxaxpyf_fusefac ]; bool use_ref = FALSE; dim_t m_pre = 0; dim_t m_iter; dim_t m_left; dim_t off_a, off_a2, off_w, off_z; dim_t i, j; conj_t conjat_use; // Return early if possible. if ( bli_zero_dim2( m, b_n ) ) return; // If there is anything that would interfere with our use of aligned // vector loads/stores, call the reference implementation. if ( b_n < bli_zdotxaxpyf_fusefac ) { use_ref = TRUE; } else if ( bli_has_nonunit_inc3( inca, incw, incz ) ) { use_ref = TRUE; } else if ( bli_is_unaligned_to( a, BLIS_SIMD_ALIGN_SIZE ) || bli_is_unaligned_to( a+lda, BLIS_SIMD_ALIGN_SIZE ) || bli_is_unaligned_to( w, BLIS_SIMD_ALIGN_SIZE ) || bli_is_unaligned_to( z, BLIS_SIMD_ALIGN_SIZE ) ) { use_ref = TRUE; // If a, the second column of a, w, and z are unaligned by the same // offset, then we can still use an implementation that depends on // alignment for most of the operation. off_a = bli_offset_from_alignment( a, BLIS_SIMD_ALIGN_SIZE ); off_a2 = bli_offset_from_alignment( a+lda, BLIS_SIMD_ALIGN_SIZE ); off_w = bli_offset_from_alignment( w, BLIS_SIMD_ALIGN_SIZE ); off_z = bli_offset_from_alignment( z, BLIS_SIMD_ALIGN_SIZE ); if ( off_a == off_a2 && off_a == off_w && off_a == off_z ) { use_ref = FALSE; m_pre = off_a / type_size; } } // Call the reference implementation if needed. if ( use_ref == TRUE ) { zdotxaxpyf_ft f = bli_zdotxaxpyf_template_ref; f ( conjat, conja, conjw, conjx, m, b_n, alpha, a, inca, lda, w, incw, x, incx, beta, y, incy, z, incz, cntx ); return; } // Compute the number of unrolled and leftover (edge) iterations. m_iter = ( m - m_pre ) / n_elem_per_iter; m_left = ( m - m_pre ) % n_elem_per_iter; // Initialize pointers into the columns of A and elements of x. for ( j = 0; j < b_n; ++j ) { ap[ j ] = a + (j )*lda; xp[ j ] = x + (j )*incx; yp[ j ] = y + (j )*incy; } wp = w; zp = z; // Load elements of x or conj(x) into alpha_x and scale by alpha. if ( bli_is_noconj( conjx ) ) { for ( j = 0; j < b_n; ++j ) { bli_zcopys( *xp[ j ], alpha_x[ j ] ); bli_zscals( *alpha, alpha_x[ j ] ); } } else // if ( bli_is_conj( conjx ) ) { for ( j = 0; j < b_n; ++j ) { bli_zcopyjs( *xp[ j ], alpha_x[ j ] ); bli_zscals( *alpha, alpha_x[ j ] ); } } // Initialize our accumulators to zero. for ( j = 0; j < b_n; ++j ) { bli_zset0s( At_w[ j ] ); } conjat_use = conjat; // If w must be conjugated, we compute the result indirectly by first // toggling the effective conjugation of At and then conjugating the // resulting dot products. if ( bli_is_conj( conjw ) ) bli_toggle_conj( &conjat_use ); // Iterate over the columns of A and elements of w and z to compute: // y = beta * y + alpha * conjat( A^T ) * conjw( w ); // z = z + alpha * conja( A ) * conjx( x ); // where A is m x b_n. if ( bli_is_noconj( conja ) && bli_is_noconj( conjat_use ) ) { // Compute front edge cases if A, w, and z were unaligned. for ( i = 0; i < m_pre; ++i ) { for ( j = 0; j < b_n; ++j ) { bli_zdots( *ap[ j ], *wp, At_w[ j ] ); bli_zdots( *ap[ j ], alpha_x[ j ], *zp ); ap[ j ] += 1; } wp += 1; zp += 1; } // The bulk of the operation is executed here. For best performance, // the elements of alpha_x should be loaded once prior to the m_iter // loop, At_w should be kept in registers, and the b_n loop should // be fully unrolled. The addresses in ap[], wp, and zp are // guaranteed to be aligned to BLIS_SIMD_ALIGN_SIZE. for ( i = 0; i < m_iter; ++i ) { for ( j = 0; j < b_n; ++j ) { bli_zdots( *ap[ j ], *wp, At_w[ j ] ); bli_zdots( *ap[ j ], alpha_x[ j ], *zp ); ap[ j ] += n_elem_per_iter; } wp += n_elem_per_iter; zp += n_elem_per_iter; } // Compute tail edge cases, if applicable. for ( i = 0; i < m_left; ++i ) { for ( j = 0; j < b_n; ++j ) { bli_zdots( *ap[ j ], *wp, At_w[ j ] ); bli_zdots( *ap[ j ], alpha_x[ j ], *zp ); ap[ j ] += 1; } wp += 1; zp += 1; } } else if ( bli_is_noconj( conja ) && bli_is_conj( conjat_use ) ) { // Compute front edge cases if A, w, and z were unaligned. for ( i = 0; i < m_pre; ++i ) { for ( j = 0; j < b_n; ++j ) { bli_zdotjs( *ap[ j ], *wp, At_w[ j ] ); bli_zdots( *ap[ j ], alpha_x[ j ], *zp ); ap[ j ] += 1; } wp += 1; zp += 1; } // The bulk of the operation is executed here. For best performance, // the elements of alpha_x should be loaded once prior to the m_iter // loop, At_w should be kept in registers, and the b_n loop should // be fully unrolled. The addresses in ap[], wp, and zp are // guaranteed to be aligned to BLIS_SIMD_ALIGN_SIZE. for ( i = 0; i < m_iter; ++i ) { for ( j = 0; j < b_n; ++j ) { bli_zdotjs( *ap[ j ], *wp, At_w[ j ] ); bli_zdots( *ap[ j ], alpha_x[ j ], *zp ); ap[ j ] += n_elem_per_iter; } wp += n_elem_per_iter; zp += n_elem_per_iter; } // Compute tail edge cases, if applicable. for ( i = 0; i < m_left; ++i ) { for ( j = 0; j < b_n; ++j ) { bli_zdotjs( *ap[ j ], *wp, At_w[ j ] ); bli_zdots( *ap[ j ], alpha_x[ j ], *zp ); ap[ j ] += 1; } wp += 1; zp += 1; } } else if ( bli_is_conj( conja ) && bli_is_noconj( conjat_use ) ) { // Compute front edge cases if A, w, and z were unaligned. for ( i = 0; i < m_pre; ++i ) { for ( j = 0; j < b_n; ++j ) { bli_zdots( *ap[ j ], *wp, At_w[ j ] ); bli_zdotjs( *ap[ j ], alpha_x[ j ], *zp ); ap[ j ] += 1; } wp += 1; zp += 1; } // The bulk of the operation is executed here. For best performance, // the elements of alpha_x should be loaded once prior to the m_iter // loop, At_w should be kept in registers, and the b_n loop should // be fully unrolled. The addresses in ap[], wp, and zp are // guaranteed to be aligned to BLIS_SIMD_ALIGN_SIZE. for ( i = 0; i < m_iter; ++i ) { for ( j = 0; j < b_n; ++j ) { bli_zdots( *ap[ j ], *wp, At_w[ j ] ); bli_zdotjs( *ap[ j ], alpha_x[ j ], *zp ); ap[ j ] += n_elem_per_iter; } wp += n_elem_per_iter; zp += n_elem_per_iter; } // Compute tail edge cases, if applicable. for ( i = 0; i < m_left; ++i ) { for ( j = 0; j < b_n; ++j ) { bli_zdots( *ap[ j ], *wp, At_w[ j ] ); bli_zdotjs( *ap[ j ], alpha_x[ j ], *zp ); ap[ j ] += 1; } wp += 1; zp += 1; } } else if ( bli_is_conj( conja ) && bli_is_conj( conjat_use ) ) { // Compute front edge cases if A, w, and z were unaligned. for ( i = 0; i < m_pre; ++i ) { for ( j = 0; j < b_n; ++j ) { bli_zdotjs( *ap[ j ], *wp, At_w[ j ] ); bli_zdotjs( *ap[ j ], alpha_x[ j ], *zp ); ap[ j ] += 1; } wp += 1; zp += 1; } // The bulk of the operation is executed here. For best performance, // the elements of alpha_x should be loaded once prior to the m_iter // loop, At_w should be kept in registers, and the b_n loop should // be fully unrolled. The addresses in ap[], wp, and zp are // guaranteed to be aligned to BLIS_SIMD_ALIGN_SIZE. for ( i = 0; i < m_iter; ++i ) { for ( j = 0; j < b_n; ++j ) { bli_zdotjs( *ap[ j ], *wp, At_w[ j ] ); bli_zdotjs( *ap[ j ], alpha_x[ j ], *zp ); ap[ j ] += n_elem_per_iter; } wp += n_elem_per_iter; zp += n_elem_per_iter; } // Compute tail edge cases, if applicable. for ( i = 0; i < m_left; ++i ) { for ( j = 0; j < b_n; ++j ) { bli_zdotjs( *ap[ j ], *wp, At_w[ j ] ); bli_zdotjs( *ap[ j ], alpha_x[ j ], *zp ); ap[ j ] += 1; } wp += 1; zp += 1; } } // If conjugation on w was requested, we induce it by conjugating // the contents of At_w. if ( bli_is_conj( conjw ) ) { for ( j = 0; j < b_n; ++j ) { bli_zconjs( At_w[ j ] ); } } // Scale the At_w product by alpha and accumulate into y after // scaling by beta. for ( j = 0; j < b_n; ++j ) { bli_zscals( *beta, *yp[ j ] ); bli_zaxpys( *alpha, At_w[ j ], *yp[ j ] ); } } blis-0.9.0/config/template/kernels/1f/bli_dotxf_template_noopt_var1.c000066400000000000000000000236251422157504600257010ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_zdotxf_template_noopt ( conj_t conjat, conj_t conjx, dim_t m, dim_t b_n, dcomplex* restrict alpha, dcomplex* restrict a, inc_t inca, inc_t lda, dcomplex* restrict x, inc_t incx, dcomplex* restrict beta, dcomplex* restrict y, inc_t incy, cntx_t* restrict cntx ) { /* Template dotxf kernel implementation This function contains a template implementation for a double-precision complex kernel, coded in C, which can serve as the starting point for one to write an optimized kernel on an arbitrary architecture. (We show a template implementation for only double-precision complex because the templates for the other three floating-point types would be similar, with the real instantiations being noticeably simpler due to the disappearance of conjugation in the real domain.) This kernel performs the following gemv-like operation: y := beta * y + alpha * conjat( A^T ) * conjx( x ) where A is an m x b_n matrix, x is a vector of length m, y is a vector of length b_n, and alpha and beta are scalars. The operation is performed as a series of fused dotxv operations, and therefore A should be column- stored. Parameters: - conjat: Compute with conjugated values of A^T? - conjx: Compute with conjugated values of x? - m: The number of rows in matrix A. - b_n: The number of columns in matrix A. Must be equal to or less than the fusing factor. - alpha: The address of the scalar to be applied to A*x. - a: The address of matrix A. - inca: The row stride of A. inca should be unit unless the implementation makes special accomodation for non-unit values. - lda: The column stride of A. - x: The address of vector x. - incx: The vector increment of x. incx should be unit unless the implementation makes special accomodation for non-unit values. - beta: The address of the scalar to be applied to y. - y: The address of vector y. - incy: The vector increment of y. This template code calls the reference implementation if any of the following conditions are true: - Either of the strides inca or incx is non-unit. - The address of A, the second column of A, and x are unaligned with different offsets. If the first/second columns of A and address of x are aligned, or unaligned by the same offset, then optimized code can be used for the bulk of the computation. This template shows how the front-edge case can be handled so that the remaining computation is aligned. (This template guarantees alignment in the main loops to be BLIS_SIMD_ALIGN_SIZE.) Additional things to consider: - When optimizing, you should fully unroll the loops over b_n. This is the dimension across which we are fusing dotxv operations. - This template code chooses to call the reference implementation whenever b_n is less than the fusing factor, so as to avoid having to handle edge cases. One may choose to optimize this edge case, if desired. - Because conjugation disappears in the real domain, real instances of this kernel can safely ignore the values of any conjugation parameters, thereby simplifying the implementation. For more info, please refer to the BLIS website and/or contact the blis-devel mailing list. -FGVZ */ const dim_t n_elem_per_reg = 1; const dim_t n_iter_unroll = 1; const dim_t n_elem_per_iter = n_elem_per_reg * n_iter_unroll; const siz_t type_size = sizeof( *x ); dcomplex* ap[ bli_zdotxf_fusefac ]; dcomplex* xp; dcomplex* yp[ bli_zdotxf_fusefac ]; dcomplex Atx[ bli_zdotxf_fusefac ]; bool use_ref = FALSE; dim_t m_pre = 0; dim_t m_iter; dim_t m_left; dim_t off_a, off_a2, off_x; dim_t i, j; conj_t conjat_use; // Return early if possible. if ( bli_zero_dim1( b_n ) ) return; // If the vector lengths are zero, scale r by beta and return. if ( bli_zero_dim1( m ) ) { bli_zscalv_ex ( BLIS_NO_CONJUGATE, b_n, beta, y, incy, cntx ); return; } // If there is anything that would interfere with our use of aligned // vector loads/stores, call the reference implementation. if ( b_n < bli_zdotxf_fusefac ) { use_ref = TRUE; } else if ( bli_has_nonunit_inc2( inca, incx ) ) { use_ref = TRUE; } else if ( bli_is_unaligned_to( a, BLIS_SIMD_ALIGN_SIZE ) || bli_is_unaligned_to( a+lda, BLIS_SIMD_ALIGN_SIZE ) || bli_is_unaligned_to( x, BLIS_SIMD_ALIGN_SIZE ) ) { use_ref = TRUE; // If a, the second column of a, and x are unaligned by the same // offset, then we can still use an implementation that depends on // alignment for most of the operation. off_a = bli_offset_from_alignment( a, BLIS_SIMD_ALIGN_SIZE ); off_a2 = bli_offset_from_alignment( a+lda, BLIS_SIMD_ALIGN_SIZE ); off_x = bli_offset_from_alignment( x, BLIS_SIMD_ALIGN_SIZE ); if ( off_a == off_a2 && off_a == off_x ) { use_ref = FALSE; m_pre = off_x / type_size; } } // Call the reference implementation if needed. if ( use_ref == TRUE ) { zdotxf_ft f = bli_zdotxf_template_ref; f ( conjat, conjx, m, b_n, alpha, a, inca, lda, x, incx, beta, y, incy, cntx ); return; } // Compute the number of unrolled and leftover (edge) iterations. m_iter = ( m - m_pre ) / n_elem_per_iter; m_left = ( m - m_pre ) % n_elem_per_iter; // Initialize pointers into the rows of A and elements of y. for ( i = 0; i < b_n; ++i ) { ap[ i ] = a + (i )*lda; yp[ i ] = y + (i )*incy; } xp = x; // Initialize our accumulators to zero. for ( i = 0; i < b_n; ++i ) { bli_zset0s( Atx[ i ] ); } conjat_use = conjat; // If x must be conjugated, we compute the result indirectly by first // toggling the effective conjugation of A and then conjugating the // resulting product A^T*x. if ( bli_is_conj( conjx ) ) bli_toggle_conj( &conjat_use ); // Iterate over columns of A and rows of x to compute: // Atx = conjat_use( A^T ) * x; if ( bli_is_noconj( conjat_use ) ) { // Compute front edge cases if A and y were unaligned. for ( j = 0; j < m_pre; ++j ) { for ( i = 0; i < b_n; ++i ) { bli_zzzdots( *ap[ i ], *xp, Atx[ i ] ); ap[ i ] += 1; } xp += 1; } // The bulk of the operation is executed here. For best performance, // the elements of Atx should be kept in registers, and the b_n loop // should be fully unrolled. The addresses in ap[] and xp are // guaranteed to be aligned to BLIS_SIMD_ALIGN_SIZE. for ( j = 0; j < m_iter; ++j ) { for ( i = 0; i < b_n; ++i ) { bli_zzzdots( *ap[ i ], *xp, Atx[ i ] ); ap[ i ] += n_elem_per_iter; } xp += n_elem_per_iter; } // Compute tail edge cases, if applicable. for ( j = 0; j < m_left; ++j ) { for ( i = 0; i < b_n; ++i ) { bli_zzzdots( *ap[ i ], *xp, Atx[ i ] ); ap[ i ] += 1; } xp += 1; } } else // if ( bli_is_conj( conjat_use ) ) { // Compute front edge cases if A and y were unaligned. for ( j = 0; j < m_pre; ++j ) { for ( i = 0; i < b_n; ++i ) { bli_zzzdotjs( *ap[ i ], *xp, Atx[ i ] ); ap[ i ] += 1; } xp += 1; } // The bulk of the operation is executed here. For best performance, // the elements of Atx should be kept in registers, and the b_n loop // should be fully unrolled. The addresses in ap[] and xp are // guaranteed to be aligned to BLIS_SIMD_ALIGN_SIZE. for ( j = 0; j < m_iter; ++j ) { for ( i = 0; i < b_n; ++i ) { bli_zzzdotjs( *ap[ i ], *xp, Atx[ i ] ); ap[ i ] += n_elem_per_iter; } xp += n_elem_per_iter; } // Compute tail edge cases, if applicable. for ( j = 0; j < m_left; ++j ) { for ( i = 0; i < b_n; ++i ) { bli_zzzdotjs( *ap[ i ], *xp, Atx[ i ] ); ap[ i ] += 1; } xp += 1; } } // If conjugation on y was requested, we induce it by conjugating // the contents of Atx. if ( bli_is_conj( conjx ) ) { for ( i = 0; i < b_n; ++i ) { bli_zconjs( Atx[ i ] ); } } // Scale the Atx product by alpha and accumulate into y after // scaling by beta. for ( i = 0; i < b_n; ++i ) { bli_zzscals( *beta, *yp[ i ] ); bli_zzzaxpys( *alpha, Atx[ i ], *yp[ i ] ); } } blis-0.9.0/config/template/kernels/3/000077500000000000000000000000001422157504600173445ustar00rootroot00000000000000blis-0.9.0/config/template/kernels/3/bli_gemm_template_noopt_mxn.c000066400000000000000000000110661422157504600252630ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_zgemm_template_noopt ( dim_t m, dim_t n, dim_t k, dcomplex* restrict alpha, dcomplex* restrict a1, dcomplex* restrict b1, dcomplex* restrict beta, dcomplex* restrict c11, inc_t rs_c, inc_t cs_c, auxinfo_t* restrict data, cntx_t* restrict cntx ) { /* Template gemm micro-kernel implementation This function contains a template implementation for a double-precision complex micro-kernel, coded in C, which can serve as the starting point for one to write an optimized micro-kernel on an arbitrary architecture. (We show a template implementation for only double-precision complex because the templates for the other three floating-point types would be nearly identical.) This micro-kernel performs a matrix-matrix multiplication of the form: C11 := beta * C11 + alpha * A1 * B1 where A1 is MR x k, B1 is k x NR, C11 is MR x NR, and alpha and beta are scalars. For more info, please refer to the BLIS website's wiki on kernels: https://github.com/flame/blis/wiki/KernelsHowTo and/or contact the blis-devel mailing list. -FGVZ */ const num_t dt = BLIS_DCOMPLEX; const dim_t mr = bli_cntx_get_blksz_def_dt( dt, BLIS_MR, cntx ); const dim_t nr = bli_cntx_get_blksz_def_dt( dt, BLIS_NR, cntx ); const inc_t packmr = bli_cntx_get_blksz_max_dt( dt, BLIS_MR, cntx ); const inc_t packnr = bli_cntx_get_blksz_max_dt( dt, BLIS_NR, cntx ); const inc_t cs_a = packmr; const inc_t rs_b = packnr; const inc_t rs_ab = 1; const inc_t cs_ab = mr; dim_t l, j, i; dcomplex ab[ mr * nr ]; dcomplex* abij; dcomplex ai, bj; /* Initialize the accumulator elements in ab to zero. */ for ( i = 0; i < mr * nr; ++i ) { bli_zset0s( *(ab + i) ); } /* Perform a series of k rank-1 updates into ab. */ for ( l = 0; l < k; ++l ) { abij = ab; /* In an optimized implementation, these two loops over MR and NR are typically fully unrolled. */ for ( j = 0; j < nr; ++j ) { bj = *(b1 + j); for ( i = 0; i < mr; ++i ) { ai = *(a1 + i); bli_zdots( ai, bj, *abij ); abij += rs_ab; } } a1 += cs_a; b1 += rs_b; } /* Scale each element of ab by alpha. */ for ( i = 0; i < mr * nr; ++i ) { bli_zscals( *alpha, *(ab + i) ); } /* If beta is zero, overwrite c11 with the scaled result in ab. Otherwise, scale c11 by beta and then add the scaled result in ab. */ if ( bli_zeq0( *beta ) ) { /* c11 := ab */ bli_zcopys_mxn( m, n, ab, rs_ab, cs_ab, c11, rs_c, cs_c ); } else { /* c11 := beta * c11 + ab */ bli_zxpbys_mxn( m, n, ab, rs_ab, cs_ab, beta, c11, rs_c, cs_c ); } } blis-0.9.0/config/template/kernels/3/bli_gemmtrsm_l_template_noopt_mxn.c000066400000000000000000000065761422157504600265160ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_zgemmtrsm_l_template_noopt ( dim_t k, dcomplex* restrict alpha, dcomplex* restrict a10, dcomplex* restrict a11, dcomplex* restrict b01, dcomplex* restrict b11, dcomplex* restrict c11, inc_t rs_c, inc_t cs_c, auxinfo_t* restrict data, cntx_t* restrict cntx ) { /* Template gemmtrsm_l micro-kernel implementation This function contains a template implementation for a double-precision complex micro-kernel that fuses a gemm with a trsm_l subproblem. This micro-kernel performs the following compound operation: B11 := alpha * B11 - A10 * B01 (gemm) B11 := inv(A11) * B11 (trsm) C11 := B11 where A11 is MR x MR and lower triangular, A10 is MR x k, B01 is k x NR, B11 is MR x NR, and alpha is a scalar. Here, inv() denotes matrix inverse. For more info, please refer to the BLIS website's wiki on kernels: https://github.com/flame/blis/wiki/KernelsHowTo and/or contact the blis-devel mailing list. -FGVZ */ const num_t dt = BLIS_DCOMPLEX; const inc_t mr = bli_cntx_get_blksz_def_dt( dt, BLIS_MR, cntx ); const inc_t nr = bli_cntx_get_blksz_def_dt( dt, BLIS_NR, cntx ); const inc_t packnr = bli_cntx_get_blksz_max_dt( dt, BLIS_NR, cntx ); const inc_t rs_b = packnr; const inc_t cs_b = 1; dcomplex* restrict minus_one = bli_zm1; /* b11 = alpha * b11 - a10 * b01; */ bli_zgemm_template_noopt ( mr, nr, k, minus_one, a10, b01, alpha, b11, rs_b, cs_b, data ); /* b11 = inv(a11) * b11; c11 = b11; */ bli_ztrsm_l_template_noopt ( a11, b11, c11, rs_c, cs_c, data ); } blis-0.9.0/config/template/kernels/3/bli_gemmtrsm_u_template_noopt_mxn.c000066400000000000000000000065751422157504600265260ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_zgemmtrsm_u_template_noopt ( dim_t k, dcomplex* restrict alpha, dcomplex* restrict a10, dcomplex* restrict a11, dcomplex* restrict b01, dcomplex* restrict b11, dcomplex* restrict c11, inc_t rs_c, inc_t cs_c, auxinfo_t* restrict data, cntx_t* restrict cntx ) { /* Template gemmtrsm_u micro-kernel implementation This function contains a template implementation for a double-precision complex micro-kernel that fuses a gemm with a trsm_u subproblem. This micro-kernel performs the following compound operation: B11 := alpha * B11 - A12 * B21 (gemm) B11 := inv(A11) * B11 (trsm) C11 := B11 where A11 is MR x MR and upper triangular, A12 is MR x k, B21 is k x NR, B11 is MR x NR, and alpha is a scalar. Here, inv() denotes matrix inverse. For more info, please refer to the BLIS website's wiki on kernels: https://github.com/flame/blis/wiki/KernelsHowTo and/or contact the blis-devel mailing list. -FGVZ */ const num_t dt = BLIS_DCOMPLEX; const inc_t mr = bli_cntx_get_blksz_def_dt( dt, BLIS_MR, cntx ); const inc_t nr = bli_cntx_get_blksz_def_dt( dt, BLIS_NR, cntx ); const inc_t packnr = bli_cntx_get_blksz_max_dt( dt, BLIS_NR, cntx ); const inc_t rs_b = packnr; const inc_t cs_b = 1; dcomplex* restrict minus_one = bli_zm1; /* b11 = alpha * b11 - a12 * b21; */ bli_zgemm_template_noopt ( mr, nr, k, minus_one, a10, b01, alpha, b11, rs_b, cs_b, data ); /* b11 = inv(a11) * b11; c11 = b11; */ bli_ztrsm_u_template_noopt ( a11, b11, c11, rs_c, cs_c, data ); } blis-0.9.0/config/template/kernels/3/bli_trsm_l_template_noopt_mxn.c000066400000000000000000000111321422157504600256300ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_ztrsm_l_template_noopt ( dcomplex* restrict a11, dcomplex* restrict b11, dcomplex* restrict c11, inc_t rs_c, inc_t cs_c, auxinfo_t* restrict data, cntx_t* restrict cntx ) { /* Template trsm_l micro-kernel implementation This function contains a template implementation for a double-precision complex trsm micro-kernel, coded in C, which can serve as the starting point for one to write an optimized micro-kernel on an arbitrary architecture. (We show a template implementation for only double-precision complex because the templates for the other three floating-point types would be nearly identical.) This micro-kernel performs the following operation: C11 := inv(A11) * B11 where A11 is MR x MR and lower triangular, B11 is MR x NR, and C11 is MR x NR. For more info, please refer to the BLIS website's wiki on kernels: https://github.com/flame/blis/wiki/KernelsHowTo and/or contact the blis-devel mailing list. -FGVZ */ const dim_t mr = bli_cntx_get_blksz_def_dt( dt, BLIS_MR, cntx ); const dim_t nr = bli_cntx_get_blksz_def_dt( dt, BLIS_NR, cntx ); const inc_t packmr = bli_cntx_get_blksz_max_dt( dt, BLIS_MR, cntx ); const inc_t packnr = bli_cntx_get_blksz_max_dt( dt, BLIS_NR, cntx ); const dim_t m = mr; const dim_t n = nr; const inc_t rs_a = 1; const inc_t cs_a = packmr; const inc_t rs_b = packnr; const inc_t cs_b = 1; dim_t iter, i, j, l; dim_t n_behind; dcomplex* restrict alpha11; dcomplex* restrict a10t; dcomplex* restrict alpha10; dcomplex* restrict X0; dcomplex* restrict x1; dcomplex* restrict x01; dcomplex* restrict chi01; dcomplex* restrict chi11; dcomplex* restrict gamma11; dcomplex rho11; for ( iter = 0; iter < m; ++iter ) { i = iter; n_behind = i; alpha11 = a11 + (i )*rs_a + (i )*cs_a; a10t = a11 + (i )*rs_a + (0 )*cs_a; X0 = b11 + (0 )*rs_b + (0 )*cs_b; x1 = b11 + (i )*rs_b + (0 )*cs_b; /* x1 = x1 - a10t * X0; */ /* x1 = x1 / alpha11; */ for ( j = 0; j < n; ++j ) { x01 = X0 + (0 )*rs_b + (j )*cs_b; chi11 = x1 + (0 )*rs_b + (j )*cs_b; gamma11 = c11 + (i )*rs_c + (j )*cs_c; /* chi11 = chi11 - a10t * x01; */ bli_zset0s( rho11 ); for ( l = 0; l < n_behind; ++l ) { alpha10 = a10t + (l )*cs_a; chi01 = x01 + (l )*rs_b; bli_zaxpys( *alpha10, *chi01, rho11 ); } bli_zsubs( rho11, *chi11 ); /* chi11 = chi11 / alpha11; */ /* NOTE: The INVERSE of alpha11 (1.0/alpha11) is stored instead of alpha11, so we can multiply rather than divide. We store the inverse of alpha11 intentionally to avoid expensive division instructions within the micro-kernel. */ bli_zscals( *alpha11, *chi11 ); /* Output final result to matrix C. */ bli_zcopys( *chi11, *gamma11 ); } } } blis-0.9.0/config/template/kernels/3/bli_trsm_u_template_noopt_mxn.c000066400000000000000000000111451422157504600256450ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_ztrsm_u_template_noopt ( dcomplex* restrict a11, dcomplex* restrict b11, dcomplex* restrict c11, inc_t rs_c, inc_t cs_c, auxinfo_t* restrict data, cntx_t* restrict cntx ) { /* Template trsm_u micro-kernel implementation This function contains a template implementation for a double-precision complex trsm micro-kernel, coded in C, which can serve as the starting point for one to write an optimized micro-kernel on an arbitrary architecture. (We show a template implementation for only double-precision complex because the templates for the other three floating-point types would be nearly identical.) This micro-kernel performs the following operation: C11 := inv(A11) * B11 where A11 is MR x MR and upper triangular, B11 is MR x NR, and C11 is MR x NR. For more info, please refer to the BLIS website's wiki on kernels: https://github.com/flame/blis/wiki/KernelsHowTo and/or contact the blis-devel mailing list. -FGVZ */ const dim_t mr = bli_cntx_get_blksz_def_dt( dt, BLIS_MR, cntx ); const dim_t nr = bli_cntx_get_blksz_def_dt( dt, BLIS_NR, cntx ); const inc_t packmr = bli_cntx_get_blksz_max_dt( dt, BLIS_MR, cntx ); const inc_t packnr = bli_cntx_get_blksz_max_dt( dt, BLIS_NR, cntx ); const dim_t m = mr; const dim_t n = nr; const inc_t rs_a = 1; const inc_t cs_a = packmr; const inc_t rs_b = packnr; const inc_t cs_b = 1; dim_t iter, i, j, l; dim_t n_behind; dcomplex* restrict alpha11; dcomplex* restrict a12t; dcomplex* restrict alpha12; dcomplex* restrict X2; dcomplex* restrict x1; dcomplex* restrict x21; dcomplex* restrict chi21; dcomplex* restrict chi11; dcomplex* restrict gamma11; dcomplex rho11; for ( iter = 0; iter < m; ++iter ) { i = m - iter - 1; n_behind = iter; alpha11 = a11 + (i )*rs_a + (i )*cs_a; a12t = a11 + (i )*rs_a + (i+1)*cs_a; x1 = b11 + (i )*rs_b + (0 )*cs_b; X2 = b11 + (i+1)*rs_b + (0 )*cs_b; /* x1 = x1 - a12t * X2; */ /* x1 = x1 / alpha11; */ for ( j = 0; j < n; ++j ) { chi11 = x1 + (0 )*rs_b + (j )*cs_b; x21 = X2 + (0 )*rs_b + (j )*cs_b; gamma11 = c11 + (i )*rs_c + (j )*cs_c; /* chi11 = chi11 - a12t * x21; */ bli_zset0s( rho11 ); for ( l = 0; l < n_behind; ++l ) { alpha12 = a12t + (l )*cs_a; chi21 = x21 + (l )*rs_b; bli_zaxpys( *alpha12, *chi21, rho11 ); } bli_zsubs( rho11, *chi11 ); /* chi11 = chi11 / alpha11; */ /* NOTE: The INVERSE of alpha11 (1.0/alpha11) is stored instead of alpha11, so we can multiply rather than divide. We store the inverse of alpha11 intentionally to avoid expensive division instructions within the micro-kernel. */ bli_zscals( *alpha11, *chi11 ); /* Output final result to matrix C. */ bli_zcopys( *chi11, *gamma11 ); } } } blis-0.9.0/config/template/make_defs.mk000066400000000000000000000051241422157504600200100ustar00rootroot00000000000000# # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2014, The University of Texas at Austin # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # # Declare the name of the current configuration and add it to the # running list of configurations included by common.mk. THIS_CONFIG := template #CONFIGS_INCL += $(THIS_CONFIG) # # --- Determine the C compiler and related flags --- # # NOTE: The build system will append these variables with various # general-purpose/configuration-agnostic flags in common.mk. You # may specify additional flags here as needed. CPPROCFLAGS := CMISCFLAGS := CPICFLAGS := CWARNFLAGS := ifneq ($(DEBUG_TYPE),off) CDBGFLAGS := -g endif ifeq ($(DEBUG_TYPE),noopt) COPTFLAGS := -O0 else COPTFLAGS := -O2 endif # Flags specific to optimized kernels. CKOPTFLAGS := $(COPTFLAGS) -O3 CKVECFLAGS := # Flags specific to reference kernels. CROPTFLAGS := $(CKOPTFLAGS) CRVECFLAGS := $(CKVECFLAGS) # Store all of the variables here to new variables containing the # configuration name. $(eval $(call store-make-defs,$(THIS_CONFIG))) blis-0.9.0/config/thunderx2/000077500000000000000000000000001422157504600156475ustar00rootroot00000000000000blis-0.9.0/config/thunderx2/bli_cntx_init_thunderx2.c000066400000000000000000000060551422157504600226510ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_cntx_init_thunderx2( cntx_t* cntx ) { blksz_t blkszs[ BLIS_NUM_BLKSZS ]; // Set default kernel blocksizes and functions. bli_cntx_init_thunderx2_ref( cntx ); // ------------------------------------------------------------------------- // Update the context with optimized native gemm micro-kernels and // their storage preferences. bli_cntx_set_l3_nat_ukrs ( 2, BLIS_GEMM_UKR, BLIS_FLOAT, bli_sgemm_armv8a_asm_8x12, FALSE, BLIS_GEMM_UKR, BLIS_DOUBLE, bli_dgemm_armv8a_asm_6x8, FALSE, cntx ); // Initialize level-3 blocksize objects with architecture-specific values. // s d c z bli_blksz_init_easy( &blkszs[ BLIS_MR ], 8, 6, -1, -1 ); bli_blksz_init_easy( &blkszs[ BLIS_NR ], 12, 8, -1, -1 ); bli_blksz_init_easy( &blkszs[ BLIS_MC ], 120, 120, -1, -1 ); bli_blksz_init_easy( &blkszs[ BLIS_KC ], 640, 240, -1, -1 ); bli_blksz_init_easy( &blkszs[ BLIS_NC ], 3072, 3072, -1, -1 ); // Update the context with the current architecture's register and cache // blocksizes (and multiples) for native execution. bli_cntx_set_blkszs ( BLIS_NAT, 5, BLIS_NC, &blkszs[ BLIS_NC ], BLIS_NR, BLIS_KC, &blkszs[ BLIS_KC ], BLIS_KR, BLIS_MC, &blkszs[ BLIS_MC ], BLIS_MR, BLIS_NR, &blkszs[ BLIS_NR ], BLIS_NR, BLIS_MR, &blkszs[ BLIS_MR ], BLIS_MR, cntx ); } blis-0.9.0/config/thunderx2/bli_family_thunderx2.h000066400000000000000000000034701422157504600221360ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ //#ifndef BLIS_FAMILY_H //#define BLIS_FAMILY_H // -- MEMORY ALLOCATION -------------------------------------------------------- #define BLIS_SIMD_ALIGN_SIZE 16 blis-0.9.0/config/thunderx2/make_defs.mk000066400000000000000000000060431422157504600201210ustar00rootroot00000000000000# # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2014, The University of Texas at Austin # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # # Declare the name of the current configuration and add it to the # running list of configurations included by common.mk. THIS_CONFIG := thunderx2 #CONFIGS_INCL += $(THIS_CONFIG) # # --- Determine the C compiler and related flags --- # # NOTE: The build system will append these variables with various # general-purpose/configuration-agnostic flags in common.mk. You # may specify additional flags here as needed. CPPROCFLAGS := -D_GNU_SOURCE CMISCFLAGS := CPICFLAGS := CWARNFLAGS := ifneq ($(DEBUG_TYPE),off) CDBGFLAGS := -g endif ifeq ($(DEBUG_TYPE),noopt) COPTFLAGS := -O0 else COPTFLAGS := -O2 -mcpu=thunderx2t99 endif # Flags specific to optimized kernels. CKOPTFLAGS := $(COPTFLAGS) -O3 -ftree-vectorize ifeq ($(CC_VENDOR),gcc) CKVECFLAGS := -mcpu=thunderx2t99 else ifeq ($(CC_VENDOR),clang) CKVECFLAGS := -mcpu=thunderx2t99 else $(error gcc or clang is required for this configuration.) endif endif # Flags specific to reference kernels. CROPTFLAGS := $(CKOPTFLAGS) ifeq ($(CC_VENDOR),gcc) CRVECFLAGS := $(CKVECFLAGS) -funsafe-math-optimizations -ffp-contract=fast else ifeq ($(CC_VENDOR),clang) CRVECFLAGS := $(CKVECFLAGS) -funsafe-math-optimizations -ffp-contract=fast else CRVECFLAGS := $(CKVECFLAGS) endif endif # Store all of the variables here to new variables containing the # configuration name. $(eval $(call store-make-defs,$(THIS_CONFIG))) blis-0.9.0/config/x86_64/000077500000000000000000000000001422157504600146625ustar00rootroot00000000000000blis-0.9.0/config/x86_64/bli_family_x86_64.h000066400000000000000000000033061422157504600201620ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ //#ifndef BLIS_FAMILY_H //#define BLIS_FAMILY_H //#endif blis-0.9.0/config/x86_64/make_defs.mk000066400000000000000000000061221422157504600171320ustar00rootroot00000000000000# # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2014, The University of Texas at Austin # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # # Declare the name of the current configuration and add it to the # running list of configurations included by common.mk. THIS_CONFIG := x86_64 #CONFIGS_INCL += $(THIS_CONFIG) # # --- Determine the C compiler and related flags --- # # NOTE: The build system will append these variables with various # general-purpose/configuration-agnostic flags in common.mk. You # may specify additional flags here as needed. CPPROCFLAGS := CMISCFLAGS := CPICFLAGS := CWARNFLAGS := ifneq ($(DEBUG_TYPE),off) CDBGFLAGS := -g endif ifeq ($(DEBUG_TYPE),noopt) COPTFLAGS := -O0 else COPTFLAGS := -O2 endif # Flags specific to optimized kernels. CKOPTFLAGS := $(COPTFLAGS) -O3 ifeq ($(CC_VENDOR),gcc) CKVECFLAGS := -mssse3 -mfpmath=sse -march=core2 else ifeq ($(CC_VENDOR),icc) CKVECFLAGS := -xSSE3 else ifeq ($(CC_VENDOR),clang) CKVECFLAGS := -mssse3 -mfpmath=sse -march=core2 else $(error gcc, icc, or clang is required for this configuration.) endif endif endif # Flags specific to reference kernels. CROPTFLAGS := $(CKOPTFLAGS) ifeq ($(CC_VENDOR),gcc) CRVECFLAGS := $(CKVECFLAGS) -funsafe-math-optimizations -ffp-contract=fast else ifeq ($(CC_VENDOR),clang) CRVECFLAGS := $(CKVECFLAGS) -funsafe-math-optimizations -ffp-contract=fast else CRVECFLAGS := $(CKVECFLAGS) endif endif # Store all of the variables here to new variables containing the # configuration name. $(eval $(call store-make-defs,$(THIS_CONFIG))) blis-0.9.0/config/zen/000077500000000000000000000000001422157504600145205ustar00rootroot00000000000000blis-0.9.0/config/zen/amd_config.mk000066400000000000000000000057101422157504600171420ustar00rootroot00000000000000# # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2019, Advanced Micro Devices, Inc. # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # # All the common flags for AMD architectures will be added here # NOTE: The build system will append these variables with various # general-purpose/configuration-agnostic flags in common.mk. You # may specify additional flags here as needed. CPPROCFLAGS := CMISCFLAGS := CPICFLAGS := CWARNFLAGS := ifneq ($(DEBUG_TYPE),off) CDBGFLAGS := -g endif ifeq ($(DEBUG_TYPE),noopt) COPTFLAGS := -O0 else COPTFLAGS := -O2 -fomit-frame-pointer endif # Flags specific to optimized kernels. # NOTE: The -fomit-frame-pointer option is needed for some kernels because # they make explicit use of the rbp register. CKOPTFLAGS := $(COPTFLAGS) -O3 ifeq ($(CC_VENDOR),gcc) CKVECFLAGS := -mavx2 -mfpmath=sse -mfma else ifeq ($(CC_VENDOR),clang) CKVECFLAGS := -mavx2 -mfpmath=sse -mfma ifeq ($(strip $(shell clang -v |& head -1 | grep -c 'AOCC.LLVM')),1) CKVECFLAGS += -mllvm -disable-licm-vrp endif else $(error gcc or clang are required for this configuration.) endif endif # Flags specific to reference kernels. CROPTFLAGS := $(CKOPTFLAGS) ifeq ($(CC_VENDOR),gcc) CRVECFLAGS := $(CKVECFLAGS) -funsafe-math-optimizations -ffp-contract=fast else ifeq ($(CC_VENDOR),clang) CRVECFLAGS := $(CKVECFLAGS) -funsafe-math-optimizations -ffp-contract=fast else CRVECFLAGS := $(CKVECFLAGS) endif endif blis-0.9.0/config/zen/bli_cntx_init_zen.c000066400000000000000000000276271422157504600204030ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2020-2022, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" //GEMMSUP_KER_PROT( double, d, gemmsup_r_haswell_ref ) void bli_cntx_init_zen( cntx_t* cntx ) { blksz_t blkszs[ BLIS_NUM_BLKSZS ]; blksz_t thresh[ BLIS_NUM_THRESH ]; // Set default kernel blocksizes and functions. bli_cntx_init_zen_ref( cntx ); // ------------------------------------------------------------------------- // Update the context with optimized native gemm micro-kernels and // their storage preferences. bli_cntx_set_l3_nat_ukrs ( 8, // gemm BLIS_GEMM_UKR, BLIS_FLOAT, bli_sgemm_haswell_asm_6x16, TRUE, BLIS_GEMM_UKR, BLIS_DOUBLE, bli_dgemm_haswell_asm_6x8, TRUE, BLIS_GEMM_UKR, BLIS_SCOMPLEX, bli_cgemm_haswell_asm_3x8, TRUE, BLIS_GEMM_UKR, BLIS_DCOMPLEX, bli_zgemm_haswell_asm_3x4, TRUE, // gemmtrsm_l BLIS_GEMMTRSM_L_UKR, BLIS_FLOAT, bli_sgemmtrsm_l_haswell_asm_6x16, TRUE, BLIS_GEMMTRSM_L_UKR, BLIS_DOUBLE, bli_dgemmtrsm_l_haswell_asm_6x8, TRUE, // gemmtrsm_u BLIS_GEMMTRSM_U_UKR, BLIS_FLOAT, bli_sgemmtrsm_u_haswell_asm_6x16, TRUE, BLIS_GEMMTRSM_U_UKR, BLIS_DOUBLE, bli_dgemmtrsm_u_haswell_asm_6x8, TRUE, cntx ); #if 1 // Update the context with optimized packm kernels. bli_cntx_set_packm_kers ( 8, BLIS_PACKM_6XK_KER, BLIS_FLOAT, bli_spackm_haswell_asm_6xk, BLIS_PACKM_16XK_KER, BLIS_FLOAT, bli_spackm_haswell_asm_16xk, BLIS_PACKM_6XK_KER, BLIS_DOUBLE, bli_dpackm_haswell_asm_6xk, BLIS_PACKM_8XK_KER, BLIS_DOUBLE, bli_dpackm_haswell_asm_8xk, BLIS_PACKM_3XK_KER, BLIS_SCOMPLEX, bli_cpackm_haswell_asm_3xk, BLIS_PACKM_8XK_KER, BLIS_SCOMPLEX, bli_cpackm_haswell_asm_8xk, BLIS_PACKM_3XK_KER, BLIS_DCOMPLEX, bli_zpackm_haswell_asm_3xk, BLIS_PACKM_4XK_KER, BLIS_DCOMPLEX, bli_zpackm_haswell_asm_4xk, cntx ); #endif // Update the context with optimized level-1f kernels. bli_cntx_set_l1f_kers ( 4, // axpyf BLIS_AXPYF_KER, BLIS_FLOAT, bli_saxpyf_zen_int_8, BLIS_AXPYF_KER, BLIS_DOUBLE, bli_daxpyf_zen_int_8, // dotxf BLIS_DOTXF_KER, BLIS_FLOAT, bli_sdotxf_zen_int_8, BLIS_DOTXF_KER, BLIS_DOUBLE, bli_ddotxf_zen_int_8, cntx ); // Update the context with optimized level-1v kernels. bli_cntx_set_l1v_kers ( 16, // amaxv BLIS_AMAXV_KER, BLIS_FLOAT, bli_samaxv_zen_int, BLIS_AMAXV_KER, BLIS_DOUBLE, bli_damaxv_zen_int, // axpyv #if 0 BLIS_AXPYV_KER, BLIS_FLOAT, bli_saxpyv_zen_int, BLIS_AXPYV_KER, BLIS_DOUBLE, bli_daxpyv_zen_int, #else BLIS_AXPYV_KER, BLIS_FLOAT, bli_saxpyv_zen_int10, BLIS_AXPYV_KER, BLIS_DOUBLE, bli_daxpyv_zen_int10, #endif #if 1 // copyv BLIS_COPYV_KER, BLIS_FLOAT, bli_scopyv_zen_int, BLIS_COPYV_KER, BLIS_DOUBLE, bli_dcopyv_zen_int, #endif // dotv BLIS_DOTV_KER, BLIS_FLOAT, bli_sdotv_zen_int, BLIS_DOTV_KER, BLIS_DOUBLE, bli_ddotv_zen_int, // dotxv BLIS_DOTXV_KER, BLIS_FLOAT, bli_sdotxv_zen_int, BLIS_DOTXV_KER, BLIS_DOUBLE, bli_ddotxv_zen_int, // scalv #if 0 BLIS_SCALV_KER, BLIS_FLOAT, bli_sscalv_zen_int, BLIS_SCALV_KER, BLIS_DOUBLE, bli_dscalv_zen_int, #else BLIS_SCALV_KER, BLIS_FLOAT, bli_sscalv_zen_int10, BLIS_SCALV_KER, BLIS_DOUBLE, bli_dscalv_zen_int10, #endif #if 1 // setv BLIS_SETV_KER, BLIS_FLOAT, bli_ssetv_zen_int, BLIS_SETV_KER, BLIS_DOUBLE, bli_dsetv_zen_int, // swapv BLIS_SWAPV_KER, BLIS_FLOAT, bli_sswapv_zen_int8, BLIS_SWAPV_KER, BLIS_DOUBLE, bli_dswapv_zen_int8, #endif cntx ); // Initialize level-3 blocksize objects with architecture-specific values. // s d c z bli_blksz_init_easy( &blkszs[ BLIS_MR ], 6, 6, 3, 3 ); bli_blksz_init_easy( &blkszs[ BLIS_NR ], 16, 8, 8, 4 ); /* Multi Instance performance improvement of DGEMM when binded to a CCX In Multi instance each thread runs a sequential DGEMM. a) If BLIS is run in a multi-instance mode with CPU freq 2.6/2.2 Ghz DDR4 clock frequency 2400Mhz mc = 240, kc = 512, and nc = 2040 has better performance on EPYC server, over the default block sizes. b) If BLIS is run in Single Instance mode mc = 510, kc = 1024 and nc = 4080 */ #ifdef BLIS_ENABLE_ZEN_BLOCK_SIZES // Zen optmized level 3 cache block sizes #if BLIS_ENABLE_SINGLE_INSTANCE_BLOCK_SIZES bli_blksz_init_easy( &blkszs[ BLIS_MC ], 1020, 510, 510, 255 ); bli_blksz_init_easy( &blkszs[ BLIS_KC ], 1024, 1024, 1024, 1024 ); bli_blksz_init_easy( &blkszs[ BLIS_NC ], 8160, 4080, 4080, 3056 ); #else bli_blksz_init_easy( &blkszs[ BLIS_MC ], 144, 240, 144, 72 ); bli_blksz_init_easy( &blkszs[ BLIS_KC ], 256, 512, 256, 256 ); bli_blksz_init_easy( &blkszs[ BLIS_NC ], 4080, 2040, 2040, 1528 ); #endif #else bli_blksz_init_easy( &blkszs[ BLIS_MC ], 144, 72, 144, 72 ); bli_blksz_init_easy( &blkszs[ BLIS_KC ], 256, 256, 256, 256 ); bli_blksz_init_easy( &blkszs[ BLIS_NC ], 8160, 4080, 4080, 3056 ); #endif bli_blksz_init_easy( &blkszs[ BLIS_AF ], 8, 8, -1, -1 ); bli_blksz_init_easy( &blkszs[ BLIS_DF ], 8, 8, -1, -1 ); // Update the context with the current architecture's register and cache // blocksizes (and multiples) for native execution. bli_cntx_set_blkszs ( BLIS_NAT, 7, // level-3 BLIS_NC, &blkszs[ BLIS_NC ], BLIS_NR, BLIS_KC, &blkszs[ BLIS_KC ], BLIS_KR, BLIS_MC, &blkszs[ BLIS_MC ], BLIS_MR, BLIS_NR, &blkszs[ BLIS_NR ], BLIS_NR, BLIS_MR, &blkszs[ BLIS_MR ], BLIS_MR, // level-1f BLIS_AF, &blkszs[ BLIS_AF ], BLIS_AF, BLIS_DF, &blkszs[ BLIS_DF ], BLIS_DF, cntx ); // ------------------------------------------------------------------------- // Initialize sup thresholds with architecture-appropriate values. // s d c z bli_blksz_init_easy( &thresh[ BLIS_MT ], 512, 256, -1, -1 ); bli_blksz_init_easy( &thresh[ BLIS_NT ], 512, 256, -1, -1 ); bli_blksz_init_easy( &thresh[ BLIS_KT ], 440, 220, -1, -1 ); // Initialize the context with the sup thresholds. bli_cntx_set_l3_sup_thresh ( 3, BLIS_MT, &thresh[ BLIS_MT ], BLIS_NT, &thresh[ BLIS_NT ], BLIS_KT, &thresh[ BLIS_KT ], cntx ); // Initialize the context with the sup handlers. bli_cntx_set_l3_sup_handlers ( 1, BLIS_GEMM, bli_gemmsup_ref, //BLIS_GEMMT, bli_gemmtsup_ref, cntx ); // Update the context with optimized small/unpacked gemm kernels. bli_cntx_set_l3_sup_kers ( 16, //BLIS_RCR, BLIS_DOUBLE, bli_dgemmsup_r_haswell_ref, BLIS_RRR, BLIS_DOUBLE, bli_dgemmsup_rv_haswell_asm_6x8m, TRUE, BLIS_RRC, BLIS_DOUBLE, bli_dgemmsup_rd_haswell_asm_6x8m, TRUE, BLIS_RCR, BLIS_DOUBLE, bli_dgemmsup_rv_haswell_asm_6x8m, TRUE, BLIS_RCC, BLIS_DOUBLE, bli_dgemmsup_rv_haswell_asm_6x8n, TRUE, BLIS_CRR, BLIS_DOUBLE, bli_dgemmsup_rv_haswell_asm_6x8m, TRUE, BLIS_CRC, BLIS_DOUBLE, bli_dgemmsup_rd_haswell_asm_6x8n, TRUE, BLIS_CCR, BLIS_DOUBLE, bli_dgemmsup_rv_haswell_asm_6x8n, TRUE, BLIS_CCC, BLIS_DOUBLE, bli_dgemmsup_rv_haswell_asm_6x8n, TRUE, BLIS_RRR, BLIS_FLOAT, bli_sgemmsup_rv_haswell_asm_6x16m, TRUE, BLIS_RRC, BLIS_FLOAT, bli_sgemmsup_rd_haswell_asm_6x16m, TRUE, BLIS_RCR, BLIS_FLOAT, bli_sgemmsup_rv_haswell_asm_6x16m, TRUE, BLIS_RCC, BLIS_FLOAT, bli_sgemmsup_rv_haswell_asm_6x16n, TRUE, BLIS_CRR, BLIS_FLOAT, bli_sgemmsup_rv_haswell_asm_6x16m, TRUE, BLIS_CRC, BLIS_FLOAT, bli_sgemmsup_rd_haswell_asm_6x16n, TRUE, BLIS_CCR, BLIS_FLOAT, bli_sgemmsup_rv_haswell_asm_6x16n, TRUE, BLIS_CCC, BLIS_FLOAT, bli_sgemmsup_rv_haswell_asm_6x16n, TRUE, #if 0 BLIS_RRR, BLIS_FLOAT, bli_sgemmsup_rv_zen_asm_6x16m, TRUE, BLIS_RRC, BLIS_FLOAT, bli_sgemmsup_rd_zen_asm_6x16m, TRUE, BLIS_RCR, BLIS_FLOAT, bli_sgemmsup_rv_zen_asm_6x16m, TRUE, BLIS_RCC, BLIS_FLOAT, bli_sgemmsup_rv_zen_asm_6x16n, TRUE, BLIS_CRR, BLIS_FLOAT, bli_sgemmsup_rv_zen_asm_6x16m, TRUE, BLIS_CRC, BLIS_FLOAT, bli_sgemmsup_rd_zen_asm_6x16n, TRUE, BLIS_CCR, BLIS_FLOAT, bli_sgemmsup_rv_zen_asm_6x16n, TRUE, BLIS_CCC, BLIS_FLOAT, bli_sgemmsup_rv_zen_asm_6x16n, TRUE, #endif #if 0 // NOTE: This set of kernels is likely broken and therefore disabled. BLIS_RRR, BLIS_SCOMPLEX, bli_cgemmsup_rv_zen_asm_3x8m, TRUE, BLIS_RCR, BLIS_SCOMPLEX, bli_cgemmsup_rv_zen_asm_3x8m, TRUE, BLIS_CRR, BLIS_SCOMPLEX, bli_cgemmsup_rv_zen_asm_3x8m, TRUE, BLIS_RCC, BLIS_SCOMPLEX, bli_cgemmsup_rv_zen_asm_3x8n, TRUE, BLIS_CCR, BLIS_SCOMPLEX, bli_cgemmsup_rv_zen_asm_3x8n, TRUE, BLIS_CCC, BLIS_SCOMPLEX, bli_cgemmsup_rv_zen_asm_3x8n, TRUE, BLIS_RRR, BLIS_DCOMPLEX, bli_zgemmsup_rv_zen_asm_3x4m, TRUE, BLIS_RCR, BLIS_DCOMPLEX, bli_zgemmsup_rv_zen_asm_3x4m, TRUE, BLIS_CRR, BLIS_DCOMPLEX, bli_zgemmsup_rv_zen_asm_3x4m, TRUE, BLIS_RCC, BLIS_DCOMPLEX, bli_zgemmsup_rv_zen_asm_3x4n, TRUE, BLIS_CCR, BLIS_DCOMPLEX, bli_zgemmsup_rv_zen_asm_3x4n, TRUE, BLIS_CCC, BLIS_DCOMPLEX, bli_zgemmsup_rv_zen_asm_3x4n, TRUE, #endif cntx ); // Initialize level-3 sup blocksize objects with architecture-specific // values. // s d c z bli_blksz_init ( &blkszs[ BLIS_MR ], 6, 6, -1, -1, 9, 9, -1, -1 ); bli_blksz_init_easy( &blkszs[ BLIS_NR ], 16, 8, -1, -1 ); bli_blksz_init_easy( &blkszs[ BLIS_MC ], 144, 72, -1, -1 ); bli_blksz_init_easy( &blkszs[ BLIS_KC ], 256, 256, -1, -1 ); bli_blksz_init_easy( &blkszs[ BLIS_NC ], 8160, 4080, -1, -1 ); #if 0 bli_blksz_init ( &blkszs[ BLIS_MR ], 6, 6, 3, 3, 9, 9, 3, 3 ); bli_blksz_init_easy( &blkszs[ BLIS_NR ], 16, 8, 8, 4 ); bli_blksz_init_easy( &blkszs[ BLIS_MC ], 144, 72, 72, 36 ); bli_blksz_init_easy( &blkszs[ BLIS_KC ], 512, 256, 128, 64 ); bli_blksz_init_easy( &blkszs[ BLIS_NC ], 8160, 4080, 2040, 1020 ); #endif // Update the context with the current architecture's register and cache // blocksizes for small/unpacked level-3 problems. bli_cntx_set_l3_sup_blkszs ( 5, BLIS_NC, &blkszs[ BLIS_NC ], BLIS_KC, &blkszs[ BLIS_KC ], BLIS_MC, &blkszs[ BLIS_MC ], BLIS_NR, &blkszs[ BLIS_NR ], BLIS_MR, &blkszs[ BLIS_MR ], cntx ); } blis-0.9.0/config/zen/bli_family_zen.h000066400000000000000000000064001422157504600176540ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // By default, it is effective to parallelize the outer loops. // Setting these macros to 1 will force JR and IR inner loops // to be not paralleized. #define BLIS_THREAD_MAX_IR 1 #define BLIS_THREAD_MAX_JR 1 #define BLIS_ENABLE_ZEN_BLOCK_SIZES // Vanilla BLIS disables AMD's small matrix handling by default. #if 0 #define BLIS_ENABLE_SMALL_MATRIX #define BLIS_ENABLE_SMALL_MATRIX_TRSM // This will select the threshold below which small matrix code will be called. #define BLIS_SMALL_MATRIX_THRES 700 #define BLIS_SMALL_M_RECT_MATRIX_THRES 160 #define BLIS_SMALL_K_RECT_MATRIX_THRES 128 #define BLIS_SMALL_MATRIX_THRES_TRSM 32768 //128(128+128) => m*(m+n) #define BLIS_SMALL_MATRIX_A_THRES_TRSM 128 #define BLIS_SMALL_MATRIX_A_THRES_M_GEMMT 96 #define BLIS_SMALL_MATRIX_A_THRES_N_GEMMT 128 //This macro will enable BLIS DGEMM to choose block sizes for a single instance mode #define BLIS_ENABLE_SINGLE_INSTANCE_BLOCK_SIZES 0 #define D_BLIS_SMALL_MATRIX_THRES_TRSM_NAPLES 250 #define D_BLIS_SMALL_MATRIX_THRES_TRSM_ALXB_NAPLES 90 #define D_BLIS_SMALL_MATRIX_THRES_TRSM_DIM_RATIO 22 #endif #if 0 // Allow the sup implementation to combine some small edge case iterations in // the 2nd loop of the panel-block algorithm (MR) and/or the 2nd loop of the // block-panel algorithm (NR) with the last full iteration that precedes it. // NOTE: These cpp macros need to be explicitly set to an integer since they // are used at compile-time to create unconditional branches or dead code // regions. #define BLIS_ENABLE_SUP_MR_EXT 1 #define BLIS_ENABLE_SUP_NR_EXT 0 #endif blis-0.9.0/config/zen/make_defs.mk000066400000000000000000000065411422157504600167750ustar00rootroot00000000000000# # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # # Declare the name of the current configuration and add it to the # running list of configurations included by common.mk. THIS_CONFIG := zen #CONFIGS_INCL += $(THIS_CONFIG) # # --- Determine the C compiler and related flags --- # # NOTE: The build system will append these variables with various # general-purpose/configuration-agnostic flags in common.mk. You # may specify additional flags here as needed. CPPROCFLAGS := CMISCFLAGS := CPICFLAGS := CWARNFLAGS := ifneq ($(DEBUG_TYPE),off) CDBGFLAGS := -g endif ifeq ($(DEBUG_TYPE),noopt) COPTFLAGS := -O0 else COPTFLAGS := -O2 -fomit-frame-pointer endif # Flags specific to optimized and reference kernels. # NOTE: The -fomit-frame-pointer option is needed for some kernels because # they make explicit use of the rbp register. CKOPTFLAGS := $(COPTFLAGS) -O3 CROPTFLAGS := $(CKOPTFLAGS) CKVECFLAGS := -mavx2 -mfma -mfpmath=sse CRVECFLAGS := $(CKVECFLAGS) -funsafe-math-optimizations -ffp-contract=fast ifeq ($(CC_VENDOR),gcc) ifeq ($(GCC_OT_6_1_0),yes) # gcc versions older than 6.1. CVECFLAGS_VER := -march=bdver4 -mno-fma4 -mno-tbm -mno-xop -mno-lwp else CVECFLAGS_VER := -march=znver1 -mno-avx256-split-unaligned-store endif else ifeq ($(CC_VENDOR),clang) CVECFLAGS_VER := -march=znver1 else ifeq ($(CC_VENDOR),aocc) CVECFLAGS_VER := -march=znver1 -mllvm -disable-licm-vrp else $(error gcc, clang, or aocc is required for this configuration.) endif endif endif CKVECFLAGS += $(CVECFLAGS_VER) CRVECFLAGS += $(CVECFLAGS_VER) # Store all of the variables here to new variables containing the # configuration name. $(eval $(call store-make-defs,$(THIS_CONFIG))) blis-0.9.0/config/zen/make_defs.mk.old000066400000000000000000000066211422157504600175510ustar00rootroot00000000000000# # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2014, The University of Texas at Austin # Copyright (C) 2019, Advanced Micro Devices, Inc. # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # # FLAGS that are specific to the 'zen' architecture are added here. # FLAGS that are common for all the AMD architectures are present in # amd_config.mk. # Declare the name of the current configuration and add it to the # running list of configurations included by common.mk. THIS_CONFIG := zen #CONFIGS_INCL += $(THIS_CONFIG) # # --- Determine the C compiler and related flags --- # # Include the file containing common flags for all AMD architectures. AMD_CONFIG_FILE := amd_config.mk AMD_CONFIG_PATH := $(BASE_SHARE_PATH)/config/zen -include $(AMD_CONFIG_PATH)/$(AMD_CONFIG_FILE) ifeq ($(CC_VENDOR),gcc) # If gcc is older than 6.1.0, we must use -march=bdver4 and then remove the # Bulldozer instruction sets that were omitted from Zen. # Additionally, if gcc is 4.9 (clang 3.5?) or newer, we may want to add # Zen-specific instructions back into the mix: # -mclzero -madx -mrdseed -mmwaitx -msha -mxsavec -mxsaves -mclflushopt -mpopcnt ifeq ($(GCC_OT_6_1_0),yes) CRVECFLAGS += -march=bdver4 -mno-fma4 -mno-tbm -mno-xop -mno-lwp CKVECFLAGS += -march=bdver4 -mno-fma4 -mno-tbm -mno-xop -mno-lwp else # If gcc is at least 6.1.0, then we can specify the microarchitecture using # the preferred option. CRVECFLAGS += -march=znver1 CKVECFLAGS += -march=znver1 endif else ifeq ($(CC_VENDOR),clang) # I couldn't find which versions of clang added support for -march=znver1, # so we don't even bother attempting the differentiation that appears in the # gcc branch above. CRVECFLAGS += -march=znver1 CKVECFLAGS += -march=znver1 else $(error gcc or clang are required for this configuration.) endif endif # Store all of the variables here to new variables containing the # configuration name. $(eval $(call store-make-defs,$(THIS_CONFIG))) blis-0.9.0/config/zen/old/000077500000000000000000000000001422157504600152765ustar00rootroot00000000000000blis-0.9.0/config/zen/old/bli_kernel.h000066400000000000000000000165661422157504600175730ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2017 - 2019, Advanced Micro Devices, Inc. Copyright (C) 2018, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_KERNEL_H #define BLIS_KERNEL_H // -- LEVEL-3 MICRO-KERNEL CONSTANTS AND DEFINITIONS --------------------------- // // Constraints: // // (1) MC must be a multiple of: // (a) MR (for zero-padding purposes) // (b) NR (for zero-padding purposes when MR and NR are "swapped") // (2) NC must be a multiple of // (a) NR (for zero-padding purposes) // (b) MR (for zero-padding purposes when MR and NR are "swapped") // // threading related // By default it is effective to paralleize the // outerloops. Setting these macros to 1 will force // JR and NR inner loops to be not paralleized. #define BLIS_DEFAULT_MR_THREAD_MAX 1 #define BLIS_DEFAULT_NR_THREAD_MAX 1 // sgemm micro-kernel #if 0 #define BLIS_SGEMM_UKERNEL bli_sgemm_asm_24x4 #define BLIS_DEFAULT_MC_S 264 #define BLIS_DEFAULT_KC_S 128 #define BLIS_DEFAULT_NC_S 4080 #define BLIS_DEFAULT_MR_S 24 #define BLIS_DEFAULT_NR_S 4 #endif #if 0 #define BLIS_SGEMM_UKERNEL bli_sgemm_asm_16x6 #define BLIS_DEFAULT_MC_S 144 #define BLIS_DEFAULT_KC_S 256 #define BLIS_DEFAULT_NC_S 4080 #define BLIS_DEFAULT_MR_S 16 #define BLIS_DEFAULT_NR_S 6 #endif #if 1 #define BLIS_SGEMM_UKERNEL bli_sgemm_asm_6x16 #define BLIS_DEFAULT_MC_S 144 #define BLIS_DEFAULT_KC_S 256 #define BLIS_DEFAULT_NC_S 4080 #define BLIS_DEFAULT_MR_S 6 #define BLIS_DEFAULT_NR_S 16 #define BLIS_SGEMM_UKERNEL_PREFERS_CONTIG_ROWS #endif // dgemm micro-kernel #if 0 #define BLIS_DGEMM_UKERNEL bli_dgemm_asm_12x4 #define BLIS_DEFAULT_MC_D 96 #define BLIS_DEFAULT_KC_D 192 #define BLIS_DEFAULT_NC_D 4080 #define BLIS_DEFAULT_MR_D 12 #define BLIS_DEFAULT_NR_D 4 #endif #if 0 #define BLIS_DGEMM_UKERNEL bli_dgemm_asm_8x6 #define BLIS_DEFAULT_MC_D 72 #define BLIS_DEFAULT_KC_D 256 #define BLIS_DEFAULT_NC_D 4080 #define BLIS_DEFAULT_MR_D 8 #define BLIS_DEFAULT_NR_D 6 #endif #if 1 #define BLIS_DGEMM_UKERNEL bli_dgemm_asm_6x8 #define BLIS_DEFAULT_MC_D 510 // 72 /* Improves performance for large Matrices */ #define BLIS_DEFAULT_KC_D 1024 // 256 #define BLIS_DEFAULT_NC_D 4080 #define BLIS_DEFAULT_MR_D 6 #define BLIS_DEFAULT_NR_D 8 #define BLIS_DGEMM_UKERNEL_PREFERS_CONTIG_ROWS #endif // cgemm micro-kernel #if 1 #define BLIS_CGEMM_UKERNEL bli_cgemm_asm_3x8 #define BLIS_DEFAULT_MC_C 144 #define BLIS_DEFAULT_KC_C 256 #define BLIS_DEFAULT_NC_C 4080 #define BLIS_DEFAULT_MR_C 3 #define BLIS_DEFAULT_NR_C 8 #define BLIS_CGEMM_UKERNEL_PREFERS_CONTIG_ROWS #endif // zgemm micro-kernel #if 1 #define BLIS_ZGEMM_UKERNEL bli_zgemm_asm_3x4 #define BLIS_DEFAULT_MC_Z 72 #define BLIS_DEFAULT_KC_Z 256 #define BLIS_DEFAULT_NC_Z 4080 #define BLIS_DEFAULT_MR_Z 3 #define BLIS_DEFAULT_NR_Z 4 #define BLIS_ZGEMM_UKERNEL_PREFERS_CONTIG_ROWS #endif // zgemm micro-kernel #if 1 #define BLIS_ZGEMM_UKERNEL bli_zgemm_asm_3x4 #define BLIS_DEFAULT_MC_Z 72 #define BLIS_DEFAULT_KC_Z 256 #define BLIS_DEFAULT_NC_Z 4080 #define BLIS_DEFAULT_MR_Z 3 #define BLIS_DEFAULT_NR_Z 4 #define BLIS_ZGEMM_UKERNEL_PREFERS_CONTIG_ROWS #endif // -- trsm-related -- #define BLIS_STRSM_L_UKERNEL bli_strsm_l_int_6x16 #define BLIS_DTRSM_L_UKERNEL bli_dtrsm_l_int_6x8 // --gemmtrsm-related -- #define BLIS_SGEMMTRSM_L_UKERNEL bli_sgemmtrsm_l_6x16 #define BLIS_DGEMMTRSM_L_UKERNEL bli_dgemmtrsm_l_6x8 #define BLIS_SMALL_MATRIX_ENABLE //This will select the threshold below which small matrix code will be called. #define BLIS_SMALL_MATRIX_THRES 700 #define BLIS_SMALL_M_RECT_MATRIX_THRES 160 #define BLIS_SMALL_K_RECT_MATRIX_THRES 128 gint_t bli_gemm_small_matrix ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, cntl_t* cntl ); // -- LEVEL-2 KERNEL CONSTANTS ------------------------------------------------- // -- LEVEL-1F KERNEL CONSTANTS ------------------------------------------------ // -- LEVEL-1M KERNEL DEFINITIONS ---------------------------------------------- // -- packm -- // -- unpackm -- #define BLIS_DEFAULT_1F_S 8 #define BLIS_DEFAULT_1F_D 4 // -- LEVEL-1F KERNEL DEFINITIONS ---------------------------------------------- // -- axpy2v -- // -- dotaxpyv -- // -- axpyf -- #define BLIS_SAXPYF_KERNEL bli_saxpyf_int_var1 #define BLIS_DAXPYF_KERNEL bli_daxpyf_int_var1 // -- dotxf -- #define BLIS_SDOTXF_KERNEL bli_sdotxf_int_var1 #define BLIS_DDOTXF_KERNEL bli_ddotxf_int_var1 // -- dotxaxpyf -- // -- LEVEL-1M KERNEL DEFINITIONS ---------------------------------------------- // -- packm -- // -- unpackm -- // -- LEVEL-1V KERNEL DEFINITIONS ---------------------------------------------- // -- amax -- #define BLIS_SAMAXV_KERNEL bli_samaxv_opt_var1 #define BLIS_DAMAXV_KERNEL bli_damaxv_opt_var1 // -- addv -- // -- axpyv -- #define BLIS_DAXPYV_KERNEL bli_daxpyv_opt_var10 #define BLIS_SAXPYV_KERNEL bli_saxpyv_opt_var10 // -- copyv -- // -- dotv -- #define BLIS_DDOTV_KERNEL bli_ddotv_opt_var1 #define BLIS_SDOTV_KERNEL bli_sdotv_opt_var1 // -- dotxv -- #define BLIS_SDOTXV_KERNEL bli_sdotxv_unb_var1 #define BLIS_DDOTXV_KERNEL bli_ddotxv_unb_var1 // -- invertv -- // -- scal2v -- // -- scalv -- #define BLIS_SSCALV_KERNEL bli_sscalv_opt_var2 #define BLIS_DSCALV_KERNEL bli_dscalv_opt_var2 // -- setv -- // -- subv -- // -- swapv -- #endif blis-0.9.0/config/zen2/000077500000000000000000000000001422157504600146025ustar00rootroot00000000000000blis-0.9.0/config/zen2/bli_cntx_init_zen2.c000066400000000000000000000251231422157504600205340ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2020-2022, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_cntx_init_zen2( cntx_t* cntx ) { blksz_t blkszs[ BLIS_NUM_BLKSZS ]; blksz_t thresh[ BLIS_NUM_THRESH ]; // Set default kernel blocksizes and functions. bli_cntx_init_zen2_ref( cntx ); // ------------------------------------------------------------------------- // Update the context with optimized native gemm micro-kernels and // their storage preferences. bli_cntx_set_l3_nat_ukrs ( 8, // gemm BLIS_GEMM_UKR, BLIS_FLOAT, bli_sgemm_haswell_asm_6x16, TRUE, BLIS_GEMM_UKR, BLIS_DOUBLE, bli_dgemm_haswell_asm_6x8, TRUE, BLIS_GEMM_UKR, BLIS_SCOMPLEX, bli_cgemm_haswell_asm_3x8, TRUE, BLIS_GEMM_UKR, BLIS_DCOMPLEX, bli_zgemm_haswell_asm_3x4, TRUE, // gemmtrsm_l BLIS_GEMMTRSM_L_UKR, BLIS_FLOAT, bli_sgemmtrsm_l_haswell_asm_6x16, TRUE, BLIS_GEMMTRSM_L_UKR, BLIS_DOUBLE, bli_dgemmtrsm_l_haswell_asm_6x8, TRUE, // gemmtrsm_u BLIS_GEMMTRSM_U_UKR, BLIS_FLOAT, bli_sgemmtrsm_u_haswell_asm_6x16, TRUE, BLIS_GEMMTRSM_U_UKR, BLIS_DOUBLE, bli_dgemmtrsm_u_haswell_asm_6x8, TRUE, cntx ); #if 1 // Update the context with optimized packm kernels. bli_cntx_set_packm_kers ( 8, BLIS_PACKM_6XK_KER, BLIS_FLOAT, bli_spackm_haswell_asm_6xk, BLIS_PACKM_16XK_KER, BLIS_FLOAT, bli_spackm_haswell_asm_16xk, BLIS_PACKM_6XK_KER, BLIS_DOUBLE, bli_dpackm_haswell_asm_6xk, BLIS_PACKM_8XK_KER, BLIS_DOUBLE, bli_dpackm_haswell_asm_8xk, BLIS_PACKM_3XK_KER, BLIS_SCOMPLEX, bli_cpackm_haswell_asm_3xk, BLIS_PACKM_8XK_KER, BLIS_SCOMPLEX, bli_cpackm_haswell_asm_8xk, BLIS_PACKM_3XK_KER, BLIS_DCOMPLEX, bli_zpackm_haswell_asm_3xk, BLIS_PACKM_4XK_KER, BLIS_DCOMPLEX, bli_zpackm_haswell_asm_4xk, cntx ); #endif // Update the context with optimized level-1f kernels. bli_cntx_set_l1f_kers ( 4, // axpyf BLIS_AXPYF_KER, BLIS_FLOAT, bli_saxpyf_zen_int_5, BLIS_AXPYF_KER, BLIS_DOUBLE, bli_daxpyf_zen_int_5, // dotxf BLIS_DOTXF_KER, BLIS_FLOAT, bli_sdotxf_zen_int_8, BLIS_DOTXF_KER, BLIS_DOUBLE, bli_ddotxf_zen_int_8, cntx ); // Update the context with optimized level-1v kernels. bli_cntx_set_l1v_kers ( 16, // amaxv BLIS_AMAXV_KER, BLIS_FLOAT, bli_samaxv_zen_int, BLIS_AMAXV_KER, BLIS_DOUBLE, bli_damaxv_zen_int, // axpyv BLIS_AXPYV_KER, BLIS_FLOAT, bli_saxpyv_zen_int10, BLIS_AXPYV_KER, BLIS_DOUBLE, bli_daxpyv_zen_int10, // dotv BLIS_DOTV_KER, BLIS_FLOAT, bli_sdotv_zen_int10, BLIS_DOTV_KER, BLIS_DOUBLE, bli_ddotv_zen_int10, // dotxv BLIS_DOTXV_KER, BLIS_FLOAT, bli_sdotxv_zen_int, BLIS_DOTXV_KER, BLIS_DOUBLE, bli_ddotxv_zen_int, // scalv BLIS_SCALV_KER, BLIS_FLOAT, bli_sscalv_zen_int10, BLIS_SCALV_KER, BLIS_DOUBLE, bli_dscalv_zen_int10, //swap BLIS_SWAPV_KER, BLIS_FLOAT, bli_sswapv_zen_int8, BLIS_SWAPV_KER, BLIS_DOUBLE, bli_dswapv_zen_int8, //copy BLIS_COPYV_KER, BLIS_FLOAT, bli_scopyv_zen_int, BLIS_COPYV_KER, BLIS_DOUBLE, bli_dcopyv_zen_int, //set BLIS_SETV_KER, BLIS_FLOAT, bli_ssetv_zen_int, BLIS_SETV_KER, BLIS_DOUBLE, bli_dsetv_zen_int, cntx ); // Initialize level-3 blocksize objects with architecture-specific values. // s d c z bli_blksz_init_easy( &blkszs[ BLIS_MR ], 6, 6, 3, 3 ); bli_blksz_init_easy( &blkszs[ BLIS_NR ], 16, 8, 8, 4 ); #if AOCL_BLIS_MULTIINSTANCE bli_blksz_init_easy( &blkszs[ BLIS_MC ], 144, 240, 144, 72 ); bli_blksz_init_easy( &blkszs[ BLIS_KC ], 256, 512, 256, 256 ); bli_blksz_init_easy( &blkszs[ BLIS_NC ], 4080, 2040, 4080, 4080 ); #else bli_blksz_init_easy( &blkszs[ BLIS_MC ], 144, 72, 72, 36 ); bli_blksz_init_easy( &blkszs[ BLIS_KC ], 256, 256, 256, 256 ); bli_blksz_init_easy( &blkszs[ BLIS_NC ], 4080, 4080, 4080, 4080 ); #endif bli_blksz_init_easy( &blkszs[ BLIS_AF ], 5, 5, -1, -1 ); bli_blksz_init_easy( &blkszs[ BLIS_DF ], 8, 8, -1, -1 ); // Update the context with the current architecture's register and cache // blocksizes (and multiples) for native execution. bli_cntx_set_blkszs ( BLIS_NAT, 7, // level-3 BLIS_NC, &blkszs[ BLIS_NC ], BLIS_NR, BLIS_KC, &blkszs[ BLIS_KC ], BLIS_KR, BLIS_MC, &blkszs[ BLIS_MC ], BLIS_MR, BLIS_NR, &blkszs[ BLIS_NR ], BLIS_NR, BLIS_MR, &blkszs[ BLIS_MR ], BLIS_MR, // level-1f BLIS_AF, &blkszs[ BLIS_AF ], BLIS_AF, BLIS_DF, &blkszs[ BLIS_DF ], BLIS_DF, cntx ); // ------------------------------------------------------------------------- // Initialize sup thresholds with architecture-appropriate values. // s d c z #if 1 bli_blksz_init_easy( &thresh[ BLIS_MT ], 500, 249, -1, -1 ); bli_blksz_init_easy( &thresh[ BLIS_NT ], 500, 249, -1, -1 ); bli_blksz_init_easy( &thresh[ BLIS_KT ], 500, 249, -1, -1 ); #else bli_blksz_init_easy( &thresh[ BLIS_MT ], 100000, 100000, -1, -1 ); bli_blksz_init_easy( &thresh[ BLIS_NT ], 100000, 100000, -1, -1 ); bli_blksz_init_easy( &thresh[ BLIS_KT ], 100000, 100000, -1, -1 ); #endif // Initialize the context with the sup thresholds. bli_cntx_set_l3_sup_thresh ( 3, BLIS_MT, &thresh[ BLIS_MT ], BLIS_NT, &thresh[ BLIS_NT ], BLIS_KT, &thresh[ BLIS_KT ], cntx ); #if 0 // Initialize the context with the sup handlers. bli_cntx_set_l3_sup_handlers ( 1, BLIS_GEMM, bli_gemmsup_ref, cntx ); #endif // Update the context with optimized small/unpacked gemm kernels. bli_cntx_set_l3_sup_kers ( 16, //BLIS_RCR, BLIS_DOUBLE, bli_dgemmsup_r_haswell_ref, BLIS_RRR, BLIS_DOUBLE, bli_dgemmsup_rv_haswell_asm_6x8m, TRUE, BLIS_RRC, BLIS_DOUBLE, bli_dgemmsup_rd_haswell_asm_6x8m, TRUE, BLIS_RCR, BLIS_DOUBLE, bli_dgemmsup_rv_haswell_asm_6x8m, TRUE, BLIS_RCC, BLIS_DOUBLE, bli_dgemmsup_rv_haswell_asm_6x8n, TRUE, BLIS_CRR, BLIS_DOUBLE, bli_dgemmsup_rv_haswell_asm_6x8m, TRUE, BLIS_CRC, BLIS_DOUBLE, bli_dgemmsup_rd_haswell_asm_6x8n, TRUE, BLIS_CCR, BLIS_DOUBLE, bli_dgemmsup_rv_haswell_asm_6x8n, TRUE, BLIS_CCC, BLIS_DOUBLE, bli_dgemmsup_rv_haswell_asm_6x8n, TRUE, BLIS_RRR, BLIS_FLOAT, bli_sgemmsup_rv_haswell_asm_6x16m, TRUE, BLIS_RRC, BLIS_FLOAT, bli_sgemmsup_rd_haswell_asm_6x16m, TRUE, BLIS_RCR, BLIS_FLOAT, bli_sgemmsup_rv_haswell_asm_6x16m, TRUE, BLIS_RCC, BLIS_FLOAT, bli_sgemmsup_rv_haswell_asm_6x16n, TRUE, BLIS_CRR, BLIS_FLOAT, bli_sgemmsup_rv_haswell_asm_6x16m, TRUE, BLIS_CRC, BLIS_FLOAT, bli_sgemmsup_rd_haswell_asm_6x16n, TRUE, BLIS_CCR, BLIS_FLOAT, bli_sgemmsup_rv_haswell_asm_6x16n, TRUE, BLIS_CCC, BLIS_FLOAT, bli_sgemmsup_rv_haswell_asm_6x16n, TRUE, #if 0 BLIS_RRR, BLIS_FLOAT, bli_sgemmsup_rv_zen_asm_6x16m, TRUE, BLIS_RRC, BLIS_FLOAT, bli_sgemmsup_rd_zen_asm_6x16m, TRUE, BLIS_RCR, BLIS_FLOAT, bli_sgemmsup_rv_zen_asm_6x16m, TRUE, BLIS_RCC, BLIS_FLOAT, bli_sgemmsup_rv_zen_asm_6x16n, TRUE, BLIS_CRR, BLIS_FLOAT, bli_sgemmsup_rv_zen_asm_6x16m, TRUE, BLIS_CRC, BLIS_FLOAT, bli_sgemmsup_rd_zen_asm_6x16n, TRUE, BLIS_CCR, BLIS_FLOAT, bli_sgemmsup_rv_zen_asm_6x16n, TRUE, BLIS_CCC, BLIS_FLOAT, bli_sgemmsup_rv_zen_asm_6x16n, TRUE, #endif #if 0 // NOTE: This set of kernels is likely broken and therefore disabled. BLIS_RRR, BLIS_SCOMPLEX, bli_cgemmsup_rv_zen_asm_3x8m, TRUE, BLIS_RCR, BLIS_SCOMPLEX, bli_cgemmsup_rv_zen_asm_3x8m, TRUE, BLIS_RCC, BLIS_SCOMPLEX, bli_cgemmsup_rv_zen_asm_3x8n, TRUE, BLIS_CRR, BLIS_SCOMPLEX, bli_cgemmsup_rv_zen_asm_3x8m, TRUE, BLIS_CCR, BLIS_SCOMPLEX, bli_cgemmsup_rv_zen_asm_3x8n, TRUE, BLIS_CCC, BLIS_SCOMPLEX, bli_cgemmsup_rv_zen_asm_3x8n, TRUE, BLIS_RRR, BLIS_DCOMPLEX, bli_zgemmsup_rv_zen_asm_3x4m, TRUE, BLIS_RCR, BLIS_DCOMPLEX, bli_zgemmsup_rv_zen_asm_3x4m, TRUE, BLIS_CRR, BLIS_DCOMPLEX, bli_zgemmsup_rv_zen_asm_3x4m, TRUE, BLIS_RCC, BLIS_DCOMPLEX, bli_zgemmsup_rv_zen_asm_3x4n, TRUE, BLIS_CCR, BLIS_DCOMPLEX, bli_zgemmsup_rv_zen_asm_3x4n, TRUE, BLIS_CCC, BLIS_DCOMPLEX, bli_zgemmsup_rv_zen_asm_3x4n, TRUE, #endif cntx ); // Initialize level-3 sup blocksize objects with architecture-specific // values. // s d c z bli_blksz_init ( &blkszs[ BLIS_MR ], 6, 6, -1, -1, 9, 9, -1, -1 ); bli_blksz_init_easy( &blkszs[ BLIS_NR ], 16, 8, -1, -1 ); bli_blksz_init_easy( &blkszs[ BLIS_MC ], 168, 72, -1, -1 ); bli_blksz_init_easy( &blkszs[ BLIS_KC ], 256, 256, -1, -1 ); bli_blksz_init_easy( &blkszs[ BLIS_NC ], 4080, 4080, -1, -1 ); // Update the context with the current architecture's register and cache // blocksizes for small/unpacked level-3 problems. bli_cntx_set_l3_sup_blkszs ( 5, BLIS_NC, &blkszs[ BLIS_NC ], BLIS_KC, &blkszs[ BLIS_KC ], BLIS_MC, &blkszs[ BLIS_MC ], BLIS_NR, &blkszs[ BLIS_NR ], BLIS_MR, &blkszs[ BLIS_MR ], cntx ); } blis-0.9.0/config/zen2/bli_family_zen2.h000066400000000000000000000073631422157504600200310ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2019, Advanced Micro Devices, Inc 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // By default, it is effective to parallelize the outer loops. // Setting these macros to 1 will force JR and IR inner loops // to be not paralleized. #define BLIS_THREAD_MAX_IR 1 #define BLIS_THREAD_MAX_JR 1 // Vanilla BLIS disables AMD's small matrix handling by default. #if 0 #define BLIS_ENABLE_SMALL_MATRIX #define BLIS_ENABLE_SMALL_MATRIX_TRSM // This will select the threshold below which small matrix code will be called. #define BLIS_SMALL_MATRIX_THRES 700 #define BLIS_SMALL_M_RECT_MATRIX_THRES 160 #define BLIS_SMALL_K_RECT_MATRIX_THRES 128 #define BLIS_SMALL_MATRIX_THRES_TRSM 32768 //128(128+128) => m*(m+n) #define BLIS_SMALL_MATRIX_A_THRES_TRSM 128 #define BLIS_SMALL_MATRIX_A_THRES_M_GEMMT 96 #define BLIS_SMALL_MATRIX_A_THRES_N_GEMMT 128 #define BLIS_ENABLE_SMALL_MATRIX_ROME #define BLIS_SMALL_MATRIX_THRES_ROME 400 #define D_BLIS_SMALL_MATRIX_THRES_TRSM_ALXB_ROME 80 #define D_BLIS_SMALL_MATRIX_THRES_TRSM_ALXB_ROME_ROW_PANEL_M 40 #define D_BLIS_SMALL_MATRIX_THRES_TRSM_ALXB_ROME_COLUMN_PANEL_M 1000 #define D_BLIS_SMALL_MATRIX_THRES_TRSM_ALXB_ROME_COLUMN_PANEL_N 10 #define D_BLIS_SMALL_MATRIX_THRES_TRSM_XAUB_ROME 150 #define D_BLIS_SMALL_MATRIX_THRES_TRSM_XAUB_ROME_ROW_PANEL_M 5 #define D_BLIS_SMALL_MATRIX_THRES_TRSM_XAUB_ROME_COLUMN_PANEL_N 130 #define D_BLIS_SMALL_MATRIX_THRES_TRSM_XALTB_ROME 120 #define D_BLIS_SMALL_MATRIX_THRES_TRSM_XALTB_ROME_ROW_PANEL_M 10 #define D_BLIS_SMALL_MATRIX_THRES_TRSM_XALTB_ROME_ROW_PANEL_N 1200 #define D_BLIS_SMALL_MATRIX_THRES_TRSM_XALTB_ROME_SQUARE_M 30 #define D_BLIS_SMALL_MATRIX_THRES_TRSM_XALTB_ROME_SQUARE_N 280 #define D_BLIS_SMALL_MATRIX_THRES_TRSM_XALTB_ROME_COLUMN_PANEL_N 100 #define D_BLIS_SMALL_MATRIX_THRES_TRSM_XALB_ROME 110 #define D_BLIS_SMALL_MATRIX_THRES_TRSM_XALB_ROME_COL_PANEL_N 30 #define D_BLIS_SMALL_MATRIX_THRES_TRSM_XAUTB_ROME 120 #define D_BLIS_SMALL_MATRIX_THRES_TRSM_XAUTB_ROME_COL_PANEL_N 50 // When running HPL with pure MPI without DGEMM threading (Single-threaded // BLIS), defining this macro as 1 yields better performance. #define AOCL_BLIS_MULTIINSTANCE 0 #endif blis-0.9.0/config/zen2/make_defs.mk000066400000000000000000000075561422157504600170660ustar00rootroot00000000000000# # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # # Declare the name of the current configuration and add it to the # running list of configurations included by common.mk. THIS_CONFIG := zen2 #CONFIGS_INCL += $(THIS_CONFIG) # # --- Determine the C compiler and related flags --- # # NOTE: The build system will append these variables with various # general-purpose/configuration-agnostic flags in common.mk. You # may specify additional flags here as needed. CPPROCFLAGS := CMISCFLAGS := CPICFLAGS := CWARNFLAGS := ifneq ($(DEBUG_TYPE),off) CDBGFLAGS := -g endif ifeq ($(DEBUG_TYPE),noopt) COPTFLAGS := -O0 else COPTFLAGS := -O2 -fomit-frame-pointer endif # Flags specific to optimized and reference kernels. # NOTE: The -fomit-frame-pointer option is needed for some kernels because # they make explicit use of the rbp register. CKOPTFLAGS := $(COPTFLAGS) -O3 CROPTFLAGS := $(CKOPTFLAGS) CKVECFLAGS := -mavx2 -mfma -mfpmath=sse CRVECFLAGS := $(CKVECFLAGS) -funsafe-math-optimizations -ffp-contract=fast ifeq ($(CC_VENDOR),gcc) ifeq ($(GCC_OT_6_1_0),yes) # gcc versions older than 6.1. CVECFLAGS_VER := -march=bdver4 -mno-fma4 -mno-tbm -mno-xop -mno-lwp else ifeq ($(GCC_OT_9_1_0),yes) # gcc versions 6.1 or newer, but older than 9.1. CVECFLAGS_VER := -march=znver1 -mno-avx256-split-unaligned-store else # gcc versions 9.1 or newer. CVECFLAGS_VER := -march=znver2 endif endif else ifeq ($(CC_VENDOR),clang) ifeq ($(CLANG_OT_9_0_0),yes) # clang versions older than 9.0. CVECFLAGS_VER := -march=znver1 else # clang versions 9.0 or newer. CVECFLAGS_VER := -march=znver2 endif else ifeq ($(CC_VENDOR),aocc) ifeq ($(AOCC_OT_2_0_0),yes) # aocc versions older than 2.0. CVECFLAGS_VER := -march=znver1 -mllvm -disable-licm-vrp else # aocc versions 2.0 or newer. CVECFLAGS_VER := -march=znver2 endif else $(error gcc, clang, or aocc is required for this configuration.) endif endif endif CKVECFLAGS += $(CVECFLAGS_VER) CRVECFLAGS += $(CVECFLAGS_VER) # Store all of the variables here to new variables containing the # configuration name. $(eval $(call store-make-defs,$(THIS_CONFIG))) blis-0.9.0/config/zen2/make_defs.mk.old000066400000000000000000000073751422157504600176420ustar00rootroot00000000000000# # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2014, The University of Texas at Austin # Copyright (C) 2019, Advanced Micro Devices, Inc. # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # # FLAGS that are specific to the 'zen2' architecture are added here. # FLAGS that are common for all the AMD architectures are present in # config/zen/amd_config.mk. # Declare the name of the current configuration and add it to the # running list of configurations included by common.mk. THIS_CONFIG := zen2 #CONFIGS_INCL += $(THIS_CONFIG) # # --- Determine the C compiler and related flags --- # # Include file containing common flags for all AMD architectures. AMD_CONFIG_FILE := amd_config.mk AMD_CONFIG_PATH := $(BASE_SHARE_PATH)/config/zen -include $(AMD_CONFIG_PATH)/$(AMD_CONFIG_FILE) ifeq ($(CC_VENDOR),gcc) ifeq ($(GCC_OT_9_1_0),yes) ifeq ($(GCC_OT_6_1_0),yes) # If gcc is older than 6.1.0, we must use -march=bdver4 and then remove the # Bulldozer instruction sets that were omitted from Zen. CRVECFLAGS += -march=bdver4 -mno-fma4 -mno-tbm -mno-xop -mno-lwp CKVECFLAGS += -march=bdver4 -mno-fma4 -mno-tbm -mno-xop -mno-lwp else # If gcc is older than 9.1.0 but at least 6.1.0, then we can use -march=znver1 # as the fallback option. CRVECFLAGS += -march=znver1 -mno-avx256-split-unaligned-store CKVECFLAGS += -march=znver1 -mno-avx256-split-unaligned-store endif else # If gcc is at least 9.1.0, then we can specify the microarchitecture using # the preferred option. CRVECFLAGS += -march=znver2 CKVECFLAGS += -march=znver2 endif else ifeq ($(CC_VENDOR),clang) ifeq ($(strip $(shell $(CC) -v |&head -1 |grep -c 'AOCC.LLVM.2\|AOCC_2')),1) CKVECFLAGS += -march=znver2 else #if compiling with clang VENDOR_STRING := $(strip $(shell ${CC_VENDOR} --version | egrep -o '[0-9]+\.[0-9]+\.?[0-9]*')) CC_MAJOR := $(shell (echo ${VENDOR_STRING} | cut -d. -f1)) #clang 9.0 or later: ifeq ($(shell test $(CC_MAJOR) -ge 9; echo $$?),0) CKVECFLAGS += -march=znver2 else CKVECFLAGS += -march=znver1 endif # ge 9 endif # AOCC 2 endif # Clang endif # gcc # Store all of the variables here to new variables containing the # configuration name. $(eval $(call store-make-defs,$(THIS_CONFIG))) blis-0.9.0/config/zen3/000077500000000000000000000000001422157504600146035ustar00rootroot00000000000000blis-0.9.0/config/zen3/bli_cntx_init_zen3.c000066400000000000000000000261571422157504600205460ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2020-2022, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_cntx_init_zen3( cntx_t* cntx ) { blksz_t blkszs[ BLIS_NUM_BLKSZS ]; blksz_t thresh[ BLIS_NUM_THRESH ]; // Set default kernel blocksizes and functions. bli_cntx_init_zen3_ref( cntx ); // ------------------------------------------------------------------------- // Update the context with optimized native gemm micro-kernels and // their storage preferences. bli_cntx_set_l3_nat_ukrs ( 8, // gemm BLIS_GEMM_UKR, BLIS_FLOAT, bli_sgemm_haswell_asm_6x16, TRUE, BLIS_GEMM_UKR, BLIS_DOUBLE, bli_dgemm_haswell_asm_6x8, TRUE, BLIS_GEMM_UKR, BLIS_SCOMPLEX, bli_cgemm_haswell_asm_3x8, TRUE, BLIS_GEMM_UKR, BLIS_DCOMPLEX, bli_zgemm_haswell_asm_3x4, TRUE, // gemmtrsm_l BLIS_GEMMTRSM_L_UKR, BLIS_FLOAT, bli_sgemmtrsm_l_haswell_asm_6x16, TRUE, BLIS_GEMMTRSM_L_UKR, BLIS_DOUBLE, bli_dgemmtrsm_l_haswell_asm_6x8, TRUE, // gemmtrsm_u BLIS_GEMMTRSM_U_UKR, BLIS_FLOAT, bli_sgemmtrsm_u_haswell_asm_6x16, TRUE, BLIS_GEMMTRSM_U_UKR, BLIS_DOUBLE, bli_dgemmtrsm_u_haswell_asm_6x8, TRUE, cntx ); #if 0 // AMD: This will be enabled in other PRs. // packm kernels bli_cntx_set_packm_kers ( 2, BLIS_PACKM_8XK_KER, BLIS_DOUBLE, bli_dpackm_8xk_gen_zen, BLIS_PACKM_6XK_KER, BLIS_DOUBLE, bli_dpackm_6xk_gen_zen, cntx ); #else // Update the context with optimized packm kernels. bli_cntx_set_packm_kers ( 8, BLIS_PACKM_6XK_KER, BLIS_FLOAT, bli_spackm_haswell_asm_6xk, BLIS_PACKM_16XK_KER, BLIS_FLOAT, bli_spackm_haswell_asm_16xk, BLIS_PACKM_6XK_KER, BLIS_DOUBLE, bli_dpackm_haswell_asm_6xk, BLIS_PACKM_8XK_KER, BLIS_DOUBLE, bli_dpackm_haswell_asm_8xk, BLIS_PACKM_3XK_KER, BLIS_SCOMPLEX, bli_cpackm_haswell_asm_3xk, BLIS_PACKM_8XK_KER, BLIS_SCOMPLEX, bli_cpackm_haswell_asm_8xk, BLIS_PACKM_3XK_KER, BLIS_DCOMPLEX, bli_zpackm_haswell_asm_3xk, BLIS_PACKM_4XK_KER, BLIS_DCOMPLEX, bli_zpackm_haswell_asm_4xk, cntx ); #endif // Update the context with optimized level-1f kernels. bli_cntx_set_l1f_kers ( 4, // axpyf BLIS_AXPYF_KER, BLIS_FLOAT, bli_saxpyf_zen_int_5, BLIS_AXPYF_KER, BLIS_DOUBLE, bli_daxpyf_zen_int_5, // dotxf BLIS_DOTXF_KER, BLIS_FLOAT, bli_sdotxf_zen_int_8, BLIS_DOTXF_KER, BLIS_DOUBLE, bli_ddotxf_zen_int_8, cntx ); // Update the context with optimized level-1v kernels. bli_cntx_set_l1v_kers ( 16, // amaxv BLIS_AMAXV_KER, BLIS_FLOAT, bli_samaxv_zen_int, BLIS_AMAXV_KER, BLIS_DOUBLE, bli_damaxv_zen_int, // axpyv BLIS_AXPYV_KER, BLIS_FLOAT, bli_saxpyv_zen_int10, BLIS_AXPYV_KER, BLIS_DOUBLE, bli_daxpyv_zen_int10, // dotv BLIS_DOTV_KER, BLIS_FLOAT, bli_sdotv_zen_int10, BLIS_DOTV_KER, BLIS_DOUBLE, bli_ddotv_zen_int10, // dotxv BLIS_DOTXV_KER, BLIS_FLOAT, bli_sdotxv_zen_int, BLIS_DOTXV_KER, BLIS_DOUBLE, bli_ddotxv_zen_int, // scalv BLIS_SCALV_KER, BLIS_FLOAT, bli_sscalv_zen_int10, BLIS_SCALV_KER, BLIS_DOUBLE, bli_dscalv_zen_int10, //swap BLIS_SWAPV_KER, BLIS_FLOAT, bli_sswapv_zen_int8, BLIS_SWAPV_KER, BLIS_DOUBLE, bli_dswapv_zen_int8, //copy BLIS_COPYV_KER, BLIS_FLOAT, bli_scopyv_zen_int, BLIS_COPYV_KER, BLIS_DOUBLE, bli_dcopyv_zen_int, //set BLIS_SETV_KER, BLIS_FLOAT, bli_ssetv_zen_int, BLIS_SETV_KER, BLIS_DOUBLE, bli_dsetv_zen_int, cntx ); // Initialize level-3 blocksize objects with architecture-specific values. // // These are reference block sizes and may be overridden based on // number of threads used at runtime. // s d c z bli_blksz_init_easy( &blkszs[ BLIS_MR ], 6, 6, 3, 3 ); bli_blksz_init_easy( &blkszs[ BLIS_NR ], 16, 8, 8, 4 ); bli_blksz_init_easy( &blkszs[ BLIS_MC ], 144, 72, 72, 36 ); bli_blksz_init_easy( &blkszs[ BLIS_KC ], 256, 256, 256, 256 ); bli_blksz_init_easy( &blkszs[ BLIS_NC ], 4080, 4080, 4080, 4080 ); bli_blksz_init_easy( &blkszs[ BLIS_AF ], 5, 5, -1, -1 ); bli_blksz_init_easy( &blkszs[ BLIS_DF ], 8, 8, -1, -1 ); // Update the context with the current architecture's register and cache // blocksizes (and multiples) for native execution. bli_cntx_set_blkszs ( BLIS_NAT, 7, // level-3 BLIS_NC, &blkszs[ BLIS_NC ], BLIS_NR, BLIS_KC, &blkszs[ BLIS_KC ], BLIS_KR, BLIS_MC, &blkszs[ BLIS_MC ], BLIS_MR, BLIS_NR, &blkszs[ BLIS_NR ], BLIS_NR, BLIS_MR, &blkszs[ BLIS_MR ], BLIS_MR, // level-1f BLIS_AF, &blkszs[ BLIS_AF ], BLIS_AF, BLIS_DF, &blkszs[ BLIS_DF ], BLIS_DF, cntx ); // ------------------------------------------------------------------------- // Initialize sup thresholds with architecture-appropriate values. // s d c z bli_blksz_init_easy( &thresh[ BLIS_MT ], 512, 256, -1, -1 ); bli_blksz_init_easy( &thresh[ BLIS_NT ], 200, 256, -1, -1 ); bli_blksz_init_easy( &thresh[ BLIS_KT ], 240, 220, -1, -1 ); // Initialize the context with the sup thresholds. bli_cntx_set_l3_sup_thresh ( 3, BLIS_MT, &thresh[ BLIS_MT ], BLIS_NT, &thresh[ BLIS_NT ], BLIS_KT, &thresh[ BLIS_KT ], cntx ); #if 0 // Initialize the context with the sup handlers. bli_cntx_set_l3_sup_handlers ( 2, BLIS_GEMM, bli_gemmsup_ref, BLIS_GEMMT, bli_gemmtsup_ref, cntx ); #endif #if 0 // AMD: This should be enabled in the PR which has added these kernels // Update the context with optimized small/unpacked gemm kernels. bli_cntx_set_l3_sup_kers ( 28, //BLIS_RCR, BLIS_DOUBLE, bli_dgemmsup_r_haswell_ref, BLIS_RRR, BLIS_DOUBLE, bli_dgemmsup_rv_haswell_asm_6x8m, TRUE, BLIS_RRC, BLIS_DOUBLE, bli_dgemmsup_rd_haswell_asm_6x8m, TRUE, BLIS_RCR, BLIS_DOUBLE, bli_dgemmsup_rv_haswell_asm_6x8m, TRUE, BLIS_RCC, BLIS_DOUBLE, bli_dgemmsup_rv_haswell_asm_6x8n, TRUE, BLIS_CRR, BLIS_DOUBLE, bli_dgemmsup_rv_haswell_asm_6x8m, TRUE, BLIS_CRC, BLIS_DOUBLE, bli_dgemmsup_rd_haswell_asm_6x8n, TRUE, BLIS_CCR, BLIS_DOUBLE, bli_dgemmsup_rv_haswell_asm_6x8n, TRUE, BLIS_CCC, BLIS_DOUBLE, bli_dgemmsup_rv_haswell_asm_6x8n, TRUE, BLIS_RRR, BLIS_FLOAT, bli_sgemmsup_rv_zen_asm_6x16m, TRUE, BLIS_RRC, BLIS_FLOAT, bli_sgemmsup_rd_zen_asm_6x16m, TRUE, BLIS_RCR, BLIS_FLOAT, bli_sgemmsup_rv_zen_asm_6x16m, TRUE, BLIS_RCC, BLIS_FLOAT, bli_sgemmsup_rv_zen_asm_6x16n, TRUE, BLIS_CRR, BLIS_FLOAT, bli_sgemmsup_rv_zen_asm_6x16m, TRUE, BLIS_CRC, BLIS_FLOAT, bli_sgemmsup_rd_zen_asm_6x16n, TRUE, BLIS_CCR, BLIS_FLOAT, bli_sgemmsup_rv_zen_asm_6x16n, TRUE, BLIS_CCC, BLIS_FLOAT, bli_sgemmsup_rv_zen_asm_6x16n, TRUE, BLIS_RRR, BLIS_SCOMPLEX, bli_cgemmsup_rv_zen_asm_3x8m, TRUE, BLIS_RCR, BLIS_SCOMPLEX, bli_cgemmsup_rv_zen_asm_3x8m, TRUE, BLIS_CRR, BLIS_SCOMPLEX, bli_cgemmsup_rv_zen_asm_3x8m, TRUE, BLIS_RCC, BLIS_SCOMPLEX, bli_cgemmsup_rv_zen_asm_3x8n, TRUE, BLIS_CCR, BLIS_SCOMPLEX, bli_cgemmsup_rv_zen_asm_3x8n, TRUE, BLIS_CCC, BLIS_SCOMPLEX, bli_cgemmsup_rv_zen_asm_3x8n, TRUE, BLIS_RRR, BLIS_DCOMPLEX, bli_zgemmsup_rv_zen_asm_3x4m, TRUE, BLIS_RCR, BLIS_DCOMPLEX, bli_zgemmsup_rv_zen_asm_3x4m, TRUE, BLIS_CRR, BLIS_DCOMPLEX, bli_zgemmsup_rv_zen_asm_3x4m, TRUE, BLIS_RCC, BLIS_DCOMPLEX, bli_zgemmsup_rv_zen_asm_3x4n, TRUE, BLIS_CCR, BLIS_DCOMPLEX, bli_zgemmsup_rv_zen_asm_3x4n, TRUE, BLIS_CCC, BLIS_DCOMPLEX, bli_zgemmsup_rv_zen_asm_3x4n, TRUE, cntx ); #else // Update the context with optimized small/unpacked gemm kernels. bli_cntx_set_l3_sup_kers ( 16, //BLIS_RCR, BLIS_DOUBLE, bli_dgemmsup_r_haswell_ref, BLIS_RRR, BLIS_DOUBLE, bli_dgemmsup_rv_haswell_asm_6x8m, TRUE, BLIS_RRC, BLIS_DOUBLE, bli_dgemmsup_rd_haswell_asm_6x8m, TRUE, BLIS_RCR, BLIS_DOUBLE, bli_dgemmsup_rv_haswell_asm_6x8m, TRUE, BLIS_RCC, BLIS_DOUBLE, bli_dgemmsup_rv_haswell_asm_6x8n, TRUE, BLIS_CRR, BLIS_DOUBLE, bli_dgemmsup_rv_haswell_asm_6x8m, TRUE, BLIS_CRC, BLIS_DOUBLE, bli_dgemmsup_rd_haswell_asm_6x8n, TRUE, BLIS_CCR, BLIS_DOUBLE, bli_dgemmsup_rv_haswell_asm_6x8n, TRUE, BLIS_CCC, BLIS_DOUBLE, bli_dgemmsup_rv_haswell_asm_6x8n, TRUE, BLIS_RRR, BLIS_FLOAT, bli_sgemmsup_rv_haswell_asm_6x16m, TRUE, BLIS_RRC, BLIS_FLOAT, bli_sgemmsup_rd_haswell_asm_6x16m, TRUE, BLIS_RCR, BLIS_FLOAT, bli_sgemmsup_rv_haswell_asm_6x16m, TRUE, BLIS_RCC, BLIS_FLOAT, bli_sgemmsup_rv_haswell_asm_6x16n, TRUE, BLIS_CRR, BLIS_FLOAT, bli_sgemmsup_rv_haswell_asm_6x16m, TRUE, BLIS_CRC, BLIS_FLOAT, bli_sgemmsup_rd_haswell_asm_6x16n, TRUE, BLIS_CCR, BLIS_FLOAT, bli_sgemmsup_rv_haswell_asm_6x16n, TRUE, BLIS_CCC, BLIS_FLOAT, bli_sgemmsup_rv_haswell_asm_6x16n, TRUE, cntx ); #endif // Initialize level-3 sup blocksize objects with architecture-specific // values. // s d c z bli_blksz_init ( &blkszs[ BLIS_MR ], 6, 6, 3, 3, 9, 9, 3, 3 ); bli_blksz_init_easy( &blkszs[ BLIS_NR ], 16, 8, 8, 4 ); bli_blksz_init_easy( &blkszs[ BLIS_MC ], 144, 72, 72, 36 ); bli_blksz_init_easy( &blkszs[ BLIS_KC ], 512, 256, 128, 64 ); bli_blksz_init_easy( &blkszs[ BLIS_NC ], 8160, 4080, 2040, 1020 ); // Update the context with the current architecture's register and cache // blocksizes for small/unpacked level-3 problems. bli_cntx_set_l3_sup_blkszs ( 5, BLIS_NC, &blkszs[ BLIS_NC ], BLIS_KC, &blkszs[ BLIS_KC ], BLIS_MC, &blkszs[ BLIS_MC ], BLIS_NR, &blkszs[ BLIS_NR ], BLIS_MR, &blkszs[ BLIS_MR ], cntx ); } blis-0.9.0/config/zen3/bli_family_zen3.h000066400000000000000000000074601422157504600200310ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLI_FAMILY_ZEN3_ #define BLI_FAMILY_ZEN3_ // By default, it is effective to parallelize the outer loops. // Setting these macros to 1 will force JR and IR inner loops // to be not paralleized. // #define BLIS_THREAD_MAX_IR 1 #define BLIS_THREAD_MAX_JR 1 // To enable framework optimizations for zen3 platform // All zen3 specific code should be included in this macro #define BLIS_CONFIG_ZEN3 // To enable framework optimizations for zen3 platform // All zen3 specific code should be included in this macro #define BLIS_CONFIG_ZEN3 #define BLIS_ENABLE_SMALL_MATRIX #define BLIS_ENABLE_SMALL_MATRIX_TRSM // This will select the threshold below which small matrix code will be called. #define BLIS_SMALL_MATRIX_THRES 700 #define BLIS_SMALL_M_RECT_MATRIX_THRES 160 #define BLIS_SMALL_K_RECT_MATRIX_THRES 128 #define BLIS_SMALL_MATRIX_THRES_TRSM 32768 //128(128+128) => m*(m+n) #define BLIS_SMALL_MATRIX_A_THRES_TRSM 128 #define BLIS_SMALL_MATRIX_A_THRES_M_GEMMT 96 #define BLIS_SMALL_MATRIX_A_THRES_N_GEMMT 128 #define BLIS_ENABLE_SMALL_MATRIX_ROME #define BLIS_SMALL_MATRIX_THRES_ROME 400 #define D_BLIS_SMALL_MATRIX_THRES_TRSM_ALXB_ROME 80 #define D_BLIS_SMALL_MATRIX_THRES_TRSM_ALXB_ROME_ROW_PANEL_M 40 #define D_BLIS_SMALL_MATRIX_THRES_TRSM_ALXB_ROME_COLUMN_PANEL_M 1000 #define D_BLIS_SMALL_MATRIX_THRES_TRSM_ALXB_ROME_COLUMN_PANEL_N 10 #define D_BLIS_SMALL_MATRIX_THRES_TRSM_XAUB_ROME 150 #define D_BLIS_SMALL_MATRIX_THRES_TRSM_XAUB_ROME_ROW_PANEL_M 5 #define D_BLIS_SMALL_MATRIX_THRES_TRSM_XAUB_ROME_COLUMN_PANEL_N 130 #define D_BLIS_SMALL_MATRIX_THRES_TRSM_XALTB_ROME 120 #define D_BLIS_SMALL_MATRIX_THRES_TRSM_XALTB_ROME_ROW_PANEL_M 10 #define D_BLIS_SMALL_MATRIX_THRES_TRSM_XALTB_ROME_ROW_PANEL_N 1200 #define D_BLIS_SMALL_MATRIX_THRES_TRSM_XALTB_ROME_SQUARE_M 30 #define D_BLIS_SMALL_MATRIX_THRES_TRSM_XALTB_ROME_SQUARE_N 280 #define D_BLIS_SMALL_MATRIX_THRES_TRSM_XALTB_ROME_COLUMN_PANEL_N 100 #define D_BLIS_SMALL_MATRIX_THRES_TRSM_XALB_ROME 110 #define D_BLIS_SMALL_MATRIX_THRES_TRSM_XALB_ROME_COL_PANEL_N 30 #define D_BLIS_SMALL_MATRIX_THRES_TRSM_XAUTB_ROME 120 #define D_BLIS_SMALL_MATRIX_THRES_TRSM_XAUTB_ROME_COL_PANEL_N 50 #endif blis-0.9.0/config/zen3/make_defs.mk000066400000000000000000000101001422157504600170420ustar00rootroot00000000000000# # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # # Declare the name of the current configuration and add it to the # running list of configurations included by common.mk. THIS_CONFIG := zen3 #CONFIGS_INCL += $(THIS_CONFIG) # # --- Determine the C compiler and related flags --- # # NOTE: The build system will append these variables with various # general-purpose/configuration-agnostic flags in common.mk. You # may specify additional flags here as needed. CPPROCFLAGS := CMISCFLAGS := CPICFLAGS := CWARNFLAGS := ifneq ($(DEBUG_TYPE),off) CDBGFLAGS := -g endif ifeq ($(DEBUG_TYPE),noopt) COPTFLAGS := -O0 else COPTFLAGS := -O3 endif # Flags specific to optimized and reference kernels. # NOTE: The -fomit-frame-pointer option is needed for some kernels because # they make explicit use of the rbp register. CKOPTFLAGS := $(COPTFLAGS) -fomit-frame-pointer CROPTFLAGS := $(CKOPTFLAGS) CKVECFLAGS := -mavx2 -mfma -mfpmath=sse CRVECFLAGS := $(CKVECFLAGS) -funsafe-math-optimizations -ffp-contract=fast ifeq ($(CC_VENDOR),gcc) ifeq ($(GCC_OT_9_1_0),yes) # gcc versions older than 9.1. CVECFLAGS_VER := -march=znver1 -mno-avx256-split-unaligned-store else ifeq ($(GCC_OT_10_1_0),yes) # gcc versions 9.1 or newer, but older than 10.1. CVECFLAGS_VER := -march=znver2 else # gcc versions 10.1 or newer. CVECFLAGS_VER := -march=znver3 endif endif else ifeq ($(CC_VENDOR),clang) ifeq ($(CLANG_OT_9_0_0),yes) # clang versions older than 9.0. CVECFLAGS_VER := -march=znver1 else ifeq ($(CLANG_OT_12_0_0),yes) # clang versions 9.0 or newer, but older than 12.0. CVECFLAGS_VER := -march=znver2 else # clang versions 12.0 or newer. CVECFLAGS_VER := -march=znver3 endif endif else ifeq ($(CC_VENDOR),aocc) ifeq ($(AOCC_OT_2_0_0),yes) # aocc versions older than 2.0. CVECFLAGS_VER := -march=znver1 else ifeq ($(AOCC_OT_3_0_0),yes) # aocc versions 2.0 or newer, but older than 3.0. CVECFLAGS_VER := -march=znver2 else # aocc versions 3.0 or newer. CVECFLAGS_VER := -march=znver3 endif endif else $(error gcc, clang, or aocc is required for this configuration.) endif endif endif CKVECFLAGS += $(CVECFLAGS_VER) CRVECFLAGS += $(CVECFLAGS_VER) # Store all of the variables here to new variables containing the # configuration name. $(eval $(call store-make-defs,$(THIS_CONFIG))) blis-0.9.0/config/zen3/make_defs.mk.old000066400000000000000000000116271422157504600176360ustar00rootroot00000000000000# # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # # FLAGS that are specific to the 'zen3' architecture are added here. # FLAGS that are common for all the AMD architectures are present in # config/zen/amd_config.mk. # Declare the name of the current configuration and add it to the # running list of configurations included by common.mk. THIS_CONFIG := zen3 #CONFIGS_INCL += $(THIS_CONFIG) # # --- Determine the C compiler and related flags --- # # NOTE: The build system will append these variables with various # general-purpose/configuration-agnostic flags in common.mk. You # may specify additional flags here as needed. CPPROCFLAGS := CMISCFLAGS := CPICFLAGS := CWARNFLAGS := ifneq ($(DEBUG_TYPE),off) CDBGFLAGS := -g endif ifeq ($(DEBUG_TYPE),noopt) COPTFLAGS := -O0 else #frame pointers are needed to execution tracing ifeq ($(ETRACE_ENABLE),1) COPTFLAGS := -O3 else COPTFLAGS := -O3 -fomit-frame-pointer endif endif # # --- Enable ETRACE across the library if enabled ETRACE_ENABLE=[0,1] ----------------------- # ifeq ($(ETRACE_ENABLE),1) CDBGFLAGS += -pg -finstrument-functions -DAOCL_DTL_AUTO_TRACE_ENABLE LDFLAGS += -ldl endif # Flags specific to optimized kernels. CKOPTFLAGS := $(COPTFLAGS) ifeq ($(CC_VENDOR),gcc) GCC_VERSION := $(strip $(shell $(CC) -dumpversion | cut -d. -f1)) #gcc or clang version must be atleast 4.0 # gcc 9.0 or later: ifeq ($(shell test $(GCC_VERSION) -ge 9; echo $$?),0) CKVECFLAGS += -march=znver2 else # If gcc is older than 9.1.0 but at least 6.1.0, then we can use -march=znver1 # as the fallback option. CRVECFLAGS += -march=znver1 -mno-avx256-split-unaligned-store CKVECFLAGS += -march=znver1 -mno-avx256-split-unaligned-store endif else ifeq ($(CC_VENDOR),clang) # AOCC clang has various formats for the version line # AOCC.LLVM.2.0.0.B191.2019_07_19 clang version 8.0.0 (CLANG: Jenkins AOCC_2_0_0-Build#191) (based on LLVM AOCC.LLVM.2.0.0.B191.2019_07_19) # AOCC.LLVM.2.1.0.B1030.2019_11_12 clang version 9.0.0 (CLANG: Build#1030) (based on LLVM AOCC.LLVM.2.1.0.B1030.2019_11_12) # AMD clang version 10.0.0 (CLANG: AOCC_2.2.0-Build#93 2020_06_25) (based on LLVM Mirror.Version.10.0.0) # AMD clang version 11.0.0 (CLANG: AOCC_2.3.0-Build#85 2020_11_10) (based on LLVM Mirror.Version.11.0.0) # AMD clang version 12.0.0 (CLANG: AOCC_3.0.0-Build#2 2020_11_05) (based on LLVM Mirror.Version.12.0.0) # For our prupose we just want to know if it version 2x or 3x # for version 3x we will enable znver3 ifeq ($(strip $(shell $(CC) -v |&head -1 |grep -c 'AOCC_3')),1) CKVECFLAGS += -march=znver3 else # for version 2x we will enable znver2 ifeq ($(strip $(shell $(CC) -v |&head -1 |grep -c 'AOCC.LLVM.2\|AOCC_2')),1) CKVECFLAGS += -march=znver2 else #if compiling with clang VENDOR_STRING := $(strip $(shell ${CC_VENDOR} --version | egrep -o '[0-9]+\.[0-9]+\.?[0-9]*')) CC_MAJOR := $(shell (echo ${VENDOR_STRING} | cut -d. -f1)) #clang 9.0 or later: ifeq ($(shell test $(CC_MAJOR) -ge 9; echo $$?),0) CKVECFLAGS += -march=znver2 else CKVECFLAGS += -march=znver1 endif # ge 9 endif # aocc 2 endif # aocc 3 endif # clang endif # gcc # Flags specific to reference kernels. CROPTFLAGS := $(CKOPTFLAGS) CRVECFLAGS := $(CKVECFLAGS) # Store all of the variables here to new variables containing the # configuration name. $(eval $(call store-make-defs,$(THIS_CONFIG))) blis-0.9.0/config_registry000066400000000000000000000025071422157504600156030ustar00rootroot00000000000000# # config_registry # # Please refer to the BLIS wiki on configurations for information on the # syntax and semantics of this file [1]. # # [1] https://github.com/flame/blis/blob/master/docs/ConfigurationHowTo.md # # Processor families. x86_64: intel64 amd64 amd64_legacy intel64: skx knl haswell sandybridge penryn generic amd64_legacy: excavator steamroller piledriver bulldozer generic amd64: zen3 zen2 zen generic arm64: armsve firestorm thunderx2 cortexa57 cortexa53 generic arm32: cortexa15 cortexa9 generic # Intel architectures. skx: skx/skx/haswell/zen knl: knl/knl/haswell/zen haswell: haswell/haswell/zen sandybridge: sandybridge penryn: penryn # AMD architectures. zen3: zen3/zen3/zen2/zen/haswell zen2: zen2/zen2/zen/haswell zen: zen/zen/haswell excavator: excavator/piledriver steamroller: steamroller/piledriver piledriver: piledriver bulldozer: bulldozer # ARM architectures. armsve: armsve/armsve a64fx: a64fx/armsve firestorm: firestorm/armv8a thunderx2: thunderx2/armv8a cortexa57: cortexa57/armv8a cortexa53: cortexa53/armv8a cortexa15: cortexa15/armv7a cortexa9: cortexa9/armv7a # IBM architectures. power10: power10 power9: power9 bgq: bgq # Generic architectures. generic: generic blis-0.9.0/configure000077500000000000000000004317601422157504600144010ustar00rootroot00000000000000#!/usr/bin/env bash # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2014, The University of Texas at Austin # Copyright (C) 2020-2022, Advanced Micro Devices, Inc. # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # # # -- Helper functions ---------------------------------------------------------- # print_usage() { # Use the version string in the 'version' file since we don't have # the patched version string yet. if [ -z "${version}" ]; then version=$(cat "${version_filepath}") fi # Echo usage info. echo " " echo " ${script_name} (BLIS ${version})" #echo " " #echo " BLIS ${version}" echo " " echo " Configure BLIS's build system for compilation using a specified" echo " configuration directory." echo " " echo " Usage:" echo " " echo " ${script_name} [options] [env. vars.] confname" echo " " echo " Arguments:" echo " " echo " confname The name of the sub-directory inside of the 'config'" echo " directory containing the desired BLIS configuration." echo " Note that confname MUST be specified; if it is not," echo " configure will complain. To build a completely generic" echo " implementation, use the 'generic' configuration" echo " " echo " Options:" echo " " echo " -p PREFIX, --prefix=PREFIX" echo " " echo " The common installation prefix for all files. If given," echo " this option effectively implies:" echo " --libdir=EXECPREFIX/lib" echo " --includedir=PREFIX/include" echo " --sharedir=PREFIX/share" echo " where EXECPREFIX defaults to PREFIX. If this option is" echo " not given, PREFIX defaults to '${prefix_def}'. If PREFIX" echo " refers to a directory that does not exist, it will be" echo " created." echo " " echo " --exec-prefix=EXECPREFIX" echo " " echo " The installation prefix for libraries. Specifically, if" echo " given, this option effectively implies:" echo " --libdir=EXECPREFIX/lib" echo " If not given, EXECPREFIX defaults to PREFIX, which may be" echo " modified by the --prefix option. If EXECPREFIX refers to" echo " a directory that does not exist, it will be created." echo " " echo " --libdir=LIBDIR" echo " " echo " The path to which make will install libraries. If not" echo " given, LIBDIR defaults to PREFIX/lib. If LIBDIR refers to" echo " a directory that does not exist, it will be created." echo " " echo " --includedir=INCDIR" echo " " echo " The path to which make will install development header" echo " files. If not given, INCDIR defaults to PREFIX/include." echo " If INCDIR refers to a directory that does not exist, it" echo " will be created." echo " " echo " --sharedir=SHAREDIR" echo " " echo " The path to which make will makefile fragments containing" echo " make variables determined by configure (e.g. CC, CFLAGS," echo " and LDFLAGS). These files allow certain BLIS makefiles," echo " such as those in the examples or testsuite directories, to" echo " operate on an installed copy of BLIS rather than a local" echo " (and possibly uninstalled) copy. If not given, SHAREDIR" echo " defaults to PREFIX/share. If SHAREDIR refers to a" echo " directory that does not exist, it will be created." echo " " echo " --enable-verbose-make, --disable-verbose-make" echo " " echo " Enable (disabled by default) verbose compilation output" echo " during make." echo " " echo " --enable-arg-max-hack --disable-arg-max-hack" echo " " echo " Enable (disabled by default) build system logic that" echo " will allow archiving/linking the static/shared library" echo " even if the command plus command line arguments exceeds" echo " the operating system limit (ARG_MAX)." echo " " echo " -d DEBUG, --enable-debug[=DEBUG]" echo " " echo " Enable debugging symbols in the library. If argument" echo " DEBUG is given as 'opt', then optimization flags are" echo " kept in the framework, otherwise optimization is" echo " turned off." echo " " echo " --disable-static, --enable-static" echo " " echo " Disable (enabled by default) building BLIS as a static" echo " library. If the static library build is disabled, the" echo " shared library build must remain enabled." echo " " echo " --disable-shared, --enable-shared" echo " " echo " Disable (enabled by default) building BLIS as a shared" echo " library. If the shared library build is disabled, the" echo " static library build must remain enabled." echo " " echo " --enable-rpath, --disable-rpath" echo " " echo " Enable (disabled by default) setting an install_name for" echo " dynamic libraries on macOS which starts with @rpath rather" echo " than the absolute install path." echo " " echo " -e SYMBOLS, --export-shared[=SYMBOLS]" echo " " echo " Specify the subset of library symbols that are exported" echo " within a shared library. Valid values for SYMBOLS are:" echo " 'public' (the default) and 'all'. By default, only" echo " functions and variables that belong to public APIs are" echo " exported in shared libraries. However, the user may" echo " instead export all symbols in BLIS, even those that were" echo " intended for internal use only. Note that the public APIs" echo " encompass all functions that almost any user would ever" echo " want to call, including the BLAS/CBLAS compatibility APIs" echo " as well as the basic and expert interfaces to the typed" echo " and object APIs that are unique to BLIS. Also note that" echo " changing this option to 'all' will have no effect in some" echo " environments, such as when compiling with clang on" echo " Windows." echo " " echo " -t MODEL, --enable-threading[=MODEL], --disable-threading" echo " " echo " Enable threading in the library, using threading model" echo " MODEL={openmp,pthreads,no}. If MODEL=no or " echo " --disable-threading is specified, threading will be" echo " disabled. The default is 'no'." echo " " echo " --enable-system, --disable-system" echo " " echo " Enable conventional operating system support, such as" echo " pthreads for thread-safety. The default state is enabled." echo " However, in rare circumstances you may wish to configure" echo " BLIS for use with a minimal or nonexistent operating" echo " system (e.g. hardware simulators). In these situations," echo " --disable-system may be used to jettison all compile-time" echo " and link-time dependencies outside of the standard C" echo " library. When disabled, this option also forces the use" echo " of --disable-threading." echo " " echo " --disable-pba-pools, --enable-pba-pools" echo " --disable-sba-pools, --enable-sba-pools" echo " " echo " Disable (enabled by default) use of internal memory pools" echo " within the packing block allocator (pba) and/or the small" echo " block allocator (sba). The former is used to allocate" echo " memory used to pack submatrices while the latter is used" echo " to allocate control/thread tree nodes and thread" echo " communicators. Both allocations take place in the context" echo " of level-3 operations. When the pba is disabled, the" echo " malloc()-like function specified by BLIS_MALLOC_POOL is" echo " called on-demand whenever a packing block is needed, and" echo " when the sba is disabled, the malloc()-like function" echo " specified by BLIS_MALLOC_INTL is called whenever a small" echo " block is needed, with the two allocators calling free()-" echo " like functions BLIS_FREE_POOL and BLIS_FREE_INTL," echo " respectively when blocks are released. When enabled," echo " either or both pools are populated via the same functions" echo " mentioned previously, and henceforth blocks are checked" echo " out and in. The library quickly reaches a state in which" echo " it no longer needs to call malloc() or free(), even" echo " across many separate level-3 operation invocations." echo " " echo " --enable-mem-tracing, --disable-mem-tracing" echo " " echo " Enable (disable by default) output to stdout that traces" echo " the allocation and freeing of memory, including the names" echo " of the functions that triggered the allocation/freeing." echo " Enabling this option WILL NEGATIVELY IMPACT PERFORMANCE." echo " Please use only for informational/debugging purposes." echo " " echo " -i SIZE, --int-size=SIZE" echo " " echo " Set the size (in bits) of internal BLIS integers and" echo " integer types used in native BLIS interfaces. The" echo " default inteter type size is architecture dependent." echo " (Hint: You can always find this value printed at the" echo " beginning of the testsuite output.)" echo " " echo " -b SIZE, --blas-int-size=SIZE" echo " " echo " Set the size (in bits) of integer types in external" echo " BLAS and CBLAS interfaces, if enabled. The default" echo " integer type size used in BLAS/CBLAS is 32 bits." echo " " echo " --disable-blas, --enable-blas" echo " " echo " Disable (enabled by default) building the BLAS" echo " compatibility layer." echo " " echo " --enable-cblas, --disable-cblas" echo " " echo " Enable (disabled by default) building the CBLAS" echo " compatibility layer. This automatically enables the" echo " BLAS compatibility layer as well." echo " " echo " --disable-mixed-dt, --enable-mixed-dt" echo " " echo " Disable (enabled by default) support for mixing the" echo " storage domain and/or storage precision of matrix" echo " operands for the gemm operation, as well as support" echo " for computing in a precision different from one or" echo " both of matrices A and B." echo " " echo " --disable-mixed-dt-extra-mem, --enable-mixed-dt-extra-mem" echo " " echo " Disable (enabled by default) support for additional" echo " mixed datatype optimizations that require temporarily" echo " allocating extra memory--specifically, a single m x n" echo " matrix (per application thread) whose storage datatype" echo " is equal to the computation datatype. This option may" echo " only be enabled when mixed domain/precision support is" echo " enabled." echo " " echo " --disable-sup-handling, --enable-sup-handling" echo " " echo " Disable (enabled by default) handling of small/skinny" echo " matrix problems via separate code branches. When disabled," echo " these small/skinny level-3 operations will be performed by" echo " the conventional implementation, which is optimized for" echo " medium and large problems. Note that what qualifies as" echo " \"small\" depends on thresholds that may vary by sub-" echo " configuration." echo " " echo " --enable-amd-frame-tweaks, --disable-amd-frame-tweaks" echo " " echo " Enable building with certain framework files that have" echo " been customized by AMD for Zen-based microarchitectures." echo " The default counterparts of these files must be portable," echo " and so these customized files may provide some (typically" echo " modest) performance improvement for some select operations" echo " and/or APIs, though there may a few (tiny dimension) cases" echo " where the improvement is more pronounced. Note that the" echo " target configuration must be Zen-based (or 'amd64') for" echo " this option to have any effect. (Also note that this" echo " option is NOT to be confused with enabling AMD *kernels*," echo " which are determined by the BLIS subconfiguration used at" echo " runtime.) By default, these customized files are disabled." echo " " echo " -a NAME --enable-addon=NAME" echo " " echo " Enable the code provided by an addon. An addon consists" echo " of a separate directory of code that provides additional" echo " APIs, implementations, and/or operations that would" echo " otherwise not be present within a build of BLIS. This" echo " option may be used multiple times to specify the inclusion" echo " of multiple addons. By default, no addons are enabled." echo " " echo " -s NAME --enable-sandbox=NAME" echo " " echo " Enable a separate sandbox implementation of gemm. This" echo " option disables BLIS's conventional gemm implementation" echo " (which shares common infrastructure with other level-3" echo " operations) and instead compiles and uses the code in" echo " the NAME directory, which is expected to be a sub-" echo " directory of 'sandbox'. By default, no sandboxes are" echo " enabled." echo " " echo " --with-memkind, --without-memkind" echo " " echo " Forcibly enable or disable the use of libmemkind's" echo " hbw_malloc() and hbw_free() as substitutes for malloc()" echo " and free(), respectively, when allocating memory for" echo " BLIS's memory pools, which are used to manage buffers" echo " into which matrices are packed. The default behavior" echo " for this option is environment-dependent; if configure" echo " detects the presence of libmemkind, libmemkind is used" echo " by default, and otherwise it is not used by default." echo " " echo " -r METHOD, --thread-part-jrir=METHOD" echo " " echo " Request a method of assigning micropanels to threads in" echo " the JR and IR loops. Valid values for METHOD are 'slab'" echo " and 'rr'. Using 'slab' assigns (as much as possible)" echo " contiguous regions of micropanels to each thread while" echo " using 'rr' assigns micropanels to threads in a round-" echo " robin fashion. The chosen method also applies during" echo " the packing of A and B. The default method is 'slab'." echo " NOTE: Specifying this option constitutes a request," echo " which may be ignored in select situations if the" echo " implementation has a good reason to do so." echo " " echo " --disable-trsm-preinversion, --enable-trsm-preinversion" echo " " echo " Disable (enabled by default) pre-inversion of triangular" echo " matrix diagonals when performing trsm. When pre-inversion" echo " is enabled, diagonal elements are inverted outside of the" echo " microkernel (e.g. during packing) so that the microkernel" echo " can use multiply instructions. When disabled, division" echo " instructions are used within the microkernel. Executing" echo " these division instructions within the microkernel will" echo " incur a performance penalty, but numerical robustness will" echo " improve for certain cases involving denormal numbers that" echo " would otherwise result in overflow in the pre-inverted" echo " values." echo " " echo " --force-version=STRING" echo " " echo " Force configure to use an arbitrary version string" echo " STRING. This option may be useful when repackaging" echo " custom versions of BLIS by outside organizations." echo " " echo " -c, --show-config-lists" echo " " echo " Print the config and kernel lists, and kernel-to-config" echo " map after they are read from file. This can be useful" echo " when debugging certain configuration issues, and/or as" echo " a sanity check to make sure these lists are constituted" echo " as expected." echo " " echo " --complex-return=gnu|intel" echo " " echo " Specify the way in which complex numbers are returned" echo " from Fortran functions, either \"gnu\" (return in" echo " registers) or \"intel\" (return via hidden argument)." echo " If not specified and the environment variable FC is set," echo " attempt to determine the return type from the compiler." echo " Otherwise, the default is \"gnu\"." echo " " echo " -q, --quiet Suppress informational output. By default, configure" echo " is verbose. (NOTE: -q is not yet implemented)" echo " " echo " -h, --help Output this information and quit." echo " " echo " Environment Variables:" echo " " echo " CC Specifies the C compiler to use." echo " CXX Specifies the C++ compiler to use (sandbox only)." echo " FC Specifies the Fortran compiler to use (only to determine --complex-return)." echo " AR Specifies the static library archiver to use." echo " RANLIB Specifies the ranlib (library indexer) executable to use." echo " PYTHON Specifies the python interpreter to use." echo " CFLAGS Specifies additional compiler flags to use (prepended)." echo " LDFLAGS Specifies additional linker flags to use (prepended)." echo " LIBPTHREAD Pthreads library to use." echo " " echo " Environment variables are traditionally set prior to running configure:" echo " " echo " CC=gcc ./configure [options] haswell" echo " " echo " However, they may also be specified as command line options, e.g.:" echo " " echo " ./configure [options] CC=gcc haswell" echo " " echo " Note that not all compilers are compatible with a given" echo " configuration." echo " " # Exit with non-zero exit status exit 1 } query_array() { local arr key var_name arr="$1" key="$2" var_name="${arr}_${key}" echo "${!var_name}" } assign_key_value() { local arr key val arr="$1" key="$2" val="$3" printf -v "${arr}_${key}" %s "${val}" } # # FGVZ: This commented-out function is being kept as an example how how # to effectively "pass by reference" in bash. That is, pass the name of # a variable, instead of its conents, and then let the function use the # variable by prepending a $, at which time it can evaluate the string # as if it were a literal variable occurance. # #filteradd_to_list() #{ # local dlist ditem list_c item_c is_blacklisted # # # Add $1 to the list identified by $2, but only if $1 is not # # found in a blacklist. # # # Note: $2 can actually be a list of items. # ditem=\$"$1" # dlist=\$"$2" # # # Acquire the contents of $dlist and $ditem and store them in list_c # # and item_c, respectively. # list_c=$(eval "expr \"$dlist\" ") # item_c=$(eval "expr \"$ditem\" ") # # # Iterate over $item_c in case it is actually multiple items. # for cur_item in $item_c; do # # is_blacklisted=$(is_in_list "${cur_item}" "${config_blist}") # if [ ${is_blacklisted} == "false" ]; then # # # If cur_item is not blacklisted, add it to list_c. # list_c="${list_c} ${cur_item}" # fi # done # # # Update the argument. # eval "$2=\"${list_c}\"" #} pass_config_kernel_registries() { local filename passnum local all_blist local curline list item config kernels local cname clist klist # Read function arguments: # first argument: the file containing the configuration registry. # second argument: the pass number: 0 or 1. Pass 0 builds the # indirect config blacklist (indirect_blist) ONLY. Pass 1 actually # begins populating the config and kernel registries, and assumes # the indirect_blist has already been created. filename="$1" passnum="$2" # Initialize a list of indirect blacklisted configurations for the # current iteration. These are configurations that are invalidated by # the removal of blacklisted configurations. For example, if haswell # is registered as needing the 'haswell' and 'zen' kernel sets: # # haswell: haswell/haswell/zen # # and 'zen' was blacklisted because of the compiler version, then the # 'haswell' configuration must be omitted from the registry, as it no # longer has all of the kernel sets it was expecting. if [ "${passnum}" == "0" ]; then indirect_blist="" fi # For convenience, merge the original and indirect blacklists. # NOTE: During pass 0, all_blist is equal to config_blist, since # indirect_blist is still empty. all_blist="${config_blist} ${indirect_blist}" # Disable support for indirect blacklisting by returning early during # pass 0. See issue #214 for details [1]. Basically, I realized that # indirect blacklisting is not needed in the use case that I envisioned # in the real-life example above. If a subconfiguration such as haswell # is defined to require the zen kernel set, it implies that the zen # kernels can be compiled with haswell compiler flags. That is, just # because the zen subconfig (and its compiler flags) is blacklisted # does not mean that the haswell subconfig cannot compile the zen # kernels with haswell-specific flags. # # [1] https://github.com/flame/blis/issues/214 # if [ "${passnum}" == "0" ]; then return fi while read -r line do curline="${line}" # Remove everything after comment character '#'. curline=${curline%%#*} # We've stripped out leading whitespace and trailing comments. If # the line is now empty, then we can skip it altogether. if [ "x${curline}" = "x" ]; then continue; fi # Read the config name and config list for the current line. cname=${curline%%:*} list=${curline##*:} # If we encounter a slash, it means the name of the configuration # and the kernel set needed by that configuration are different. if [[ "${list}" == *[/]* ]]; then #echo "Slash found." klist="" clist="" for item in "${list}"; do # The sub-configuration name is always the first sub-word in # the slash-separated compound word. config=${item%%/*} # Delete the sub-configuration name from the front of the # string, leaving the slash-separated kernel names (or just # the kernel name, if there is only one). kernels=${list#*/} # Replace the slashes with spaces to transform the string # into a space-separated list of kernel names. kernels=$(echo -e ${kernels} | sed -e "s/\// /g") clist="${clist} ${config}" klist="${klist} ${kernels}" done else #echo "Slash not found." clist=${list} klist=${list} fi # Strip out whitespace from the config name and config/kernel list # on each line. cname=$(canonicalize_ws "${cname}") clist=$(canonicalize_ws "${clist}") klist=$(canonicalize_ws "${klist}") # Next, we prepare to: # - pass 0: inspect klist for blacklisted configurations, which may # reveal configurations as needing to be indirectly blacklisted. # - pass 1: compare cname to the blacklists and commit clist/klist # to their respective registries, as appropriate. # Handle singleton and umbrella configuration entries separately. if [ $(is_singleton_family "${cname}" "${clist}") == "true" ]; then # Singleton configurations/families. # Note: for singleton families, clist contains one item, which # always equals cname, but klist could contain more than one # item. # Only consider updating the indirect blacklist (pass 0) or # committing clist and klist to the registries (pass 1) if the # configuration name (cname) is not blacklisted. if [ $(is_in_list "${cname}" "${all_blist}") == "false" ]; then if [ "${passnum}" == "0" ]; then # Even if the cname isn't blacklisted, one of the requisite # kernels might be, so we need to check klist for blacklisted # items. If we find one, we must assume that the entire entry # must be thrown out. (Ideally, we would simply fall back to # reference code for the blacklisted kernels, but that is not # at all straightforward under the current configuration # system architecture.) Thus, we add cname to the indirect # blacklist. for item in ${klist}; do if [ $(is_in_list "${item}" "${config_blist}") == "true" ]; then indirect_blist="${indirect_blist} ${cname}" break fi done fi if [ "${passnum}" == "1" ]; then # Store the clist to the cname key of the config registry. #config_registry[${cname}]=${clist} #printf -v "config_registry_${cname}" %s "${clist}" assign_key_value "config_registry" "${cname}" "${clist}" fi fi if [ "${passnum}" == "1" ]; then # Store the klist to the cname key of the kernel registry. #kernel_registry[${cname}]=${klist} #printf -v "kernel_registry_${cname}" %s "${klist}" assign_key_value "kernel_registry" "${cname}" "${klist}" fi else # Umbrella configurations/families. # First we check cname, which should generally not be blacklisted # for umbrella families, but we check anyway just to be safe. if [ $(is_in_list "${cname}" "${all_blist}") == "false" ]; then if [ "${passnum}" == "1" ]; then # Check each item in the clist and klist. (At this point, # clist == klist.) If any sub-config is blacklisted, we # omit it from clist and klist. for item in ${clist}; do if [ $(is_in_list "${item}" "${all_blist}") == "true" ]; then clist=$(remove_from_list "${item}" "${clist}") klist=$(remove_from_list "${item}" "${klist}") fi done # Store the config and kernel lists to entries that # corresponds to the config name. #config_registry[${cname}]=${clist} #kernel_registry[${cname}]=${klist} #printf -v "config_registry_${cname}" %s "${clist}" #printf -v "kernel_registry_${cname}" %s "${klist}" assign_key_value "config_registry" "${cname}" "${clist}" assign_key_value "kernel_registry" "${cname}" "${klist}" fi fi fi done < "${filename}" if [ "${passnum}" == "0" ]; then # Assign the final indirect blacklist (with whitespace removed). indirect_blist="$(canonicalize_ws ${indirect_blist})" fi } read_registry_file() { local filename local clist klist local iterate_again config local cr_var mem mems_mem newclist local kr_var ker kers_ker newklist filename="$1" # Execute an initial pass through the config_registry file so that # we can accumulate a list of indirectly blacklisted configurations, # if any. pass_config_kernel_registries "${filename}" "0" # Now that the indirect_blist has been created, make a second pass # through the 'config_registry' file, this time creating the actual # config and kernel registry data structures. pass_config_kernel_registries "${filename}" "1" # Now we must go back through the config_registry and subsitute any # configuration families with their constituents' members. Each time # one of these substitutions occurs, we set a flag that causes us to # make one more pass. (Subsituting a singleton definition does not # prompt additional iterations.) This process stops when a full pass # does not result in any subsitution. iterate_again="1" while [ "${iterate_again}" == "1" ]; do iterate_again="0" #for config in "${!config_registry[@]}"; do for cr_var in ${!config_registry_*}; do config=${cr_var##config_registry_} clist=$(query_array "config_registry" ${config}) # The entries that define singleton families should never need # any substitution. if [ $(is_singleton_family "${config}" "${clist}") == "true" ]; then continue fi #for mem in ${config_registry[$config]}; do #for mem in ${!cr_var}; do for mem in ${clist}; do #mems_mem="${config_registry[${mem}]}" mems_mem=$(query_array "config_registry" ${mem}) # If mems_mem is empty string, then mem was not found as a key # in the config list associative array. In that case, we continue # and will echo an error later in the script. if [ "${mems_mem}" == "" ]; then #echo " config for ${mem} is empty string! no entry in config list." continue; fi if [ "${mem}" != "${mems_mem}" ]; then #clist="${config_registry[$config]}" clisttmp=$(query_array "config_registry" ${config}) # Replace the current config with its constituent config set, # canonicalize whitespace, and then remove duplicate config # set names, if they exist. Finally, update the config registry # with the new config list. # NOTE: WE must use substitute_words() rather than a simple sed # expression because we need to avoid matching partial strings. # For example, if clist above contains "foo bar barsk" and we use # sed to substitute "bee boo" as the members of "bar", the # result would (incorrectly) be "foo bee boo bee boosk", # which would then get reduced, via rm_duplicate_words(), to # "foo bee boo boosk". #newclist=$(echo -e "${clist}" | sed -e "s/${mem}/${mems_mem}/g") newclist=$(substitute_words "${mem}" "${mems_mem}" "${clisttmp}") newclist=$(canonicalize_ws "${newclist}") newclist=$(rm_duplicate_words "${newclist}") #config_registry[${config}]=${newclist} #printf -v "config_registry_${config}" %s "${newclist}" assign_key_value "config_registry" "${config}" "${newclist}" # Since we performed a substitution and changed the config # list, mark the iteration flag to continue another round, # but only if the config (mem) value is NOT present # in the list of sub-configs. If it is present, then further # substitution may not necessarily be needed this round. if [ $(is_in_list "${mem}" "${mems_mem}") == "false" ]; then iterate_again="1" fi fi done done done # Similar to what we just did for the config_registry, we now iterate # through the kernel_registry and substitute any configuration families # in the kernel list (right side of ':') with the members of that # family's kernel set. This process continues iteratively, as before, # until all families have been replaced with singleton configurations' # kernel sets. iterate_again="1" while [ "${iterate_again}" == "1" ]; do iterate_again="0" #for config in "${!kernel_registry[@]}"; do for kr_var in ${!kernel_registry_*}; do config=${kr_var##kernel_registry_} klist=$(query_array "kernel_registry" ${config}) # The entries that define singleton families should never need # any substitution. In the kernel registry, we know it's a # singleton entry when the cname occurs somewhere in the klist. # (This is slightly different than the same test in the config # registry, where we test that clist is one word and that # clist == cname.) if [ $(is_in_list "${config}" "${klist}") == "true" ]; then #echo "debug: '${config}' not found in '${klist}'; skipping." continue fi #for ker in ${kernel_registry[$config]}; do #for ker in ${!kr_var}; do for ker in ${klist}; do #kers_ker="${kernel_registry[${ker}]}" kers_ker=$(query_array "kernel_registry" ${ker}) # If kers_ker is empty string, then ker was not found as a key # in the kernel registry. While not common, this can happen # when ker identifies a kernel set that does not correspond to # any configuration. (Example: armv7a and armv8a kernel sets are # used by cortexa* configurations, but do not corresond to their # own configurations.) if [ "${kers_ker}" == "" ]; then #echo "debug: ${ker} not found in kernel registry." continue fi # If the current config/kernel (ker) differs from its singleton kernel # entry (kers_ker), then that singleton entry was specified to use # a different configuration's kernel set. Thus, we need to replace the # occurrence in the current config/kernel name with that of the kernel # set it needs. if [ "${ker}" != "${kers_ker}" ]; then #klisttmp="${kernel_registry[$config]}" klisttmp=$(query_array "kernel_registry" ${config}) # Replace the current config with its requisite kernels, # canonicalize whitespace, and then remove duplicate kernel # set names, if they exist. Finally, update the kernel registry # with the new kernel list. # NOTE: WE must use substitute_words() rather than a simple sed # expression because we need to avoid matching partial strings. # For example, if klist above contains "foo bar barsk" and we use # sed to substitute "bee boo" as the members of "bar", the # result would (incorrectly) be "foo bee boo bee boosk", # which would then get reduced, via rm_duplicate_words(), to # "foo bee boo boosk". #newklist=$(echo -e "${klisttmp}" | sed -e "s/${ker}/${kers_ker}/g") newklist=$(substitute_words "${ker}" "${kers_ker}" "${klisttmp}") newklist=$(canonicalize_ws "${newklist}") newklist=$(rm_duplicate_words "${newklist}") #kernel_registry[${config}]=${newklist} #printf -v "kernel_registry_${config}" %s "${newklist}" assign_key_value "kernel_registry" "${config}" "${newklist}" # Since we performed a substitution and changed the kernel # list, mark the iteration flag to continue another round, # unless we just substituted using a singleton family # definition, in which case we don't necessarily need to # iterate further this round. if [ $(is_in_list "${ker}" "${kers_ker}") == "false" ]; then iterate_again="1" fi fi done done done } substitute_words() { local word new_words list newlist word="$1" new_words="$2" list="$3" for str in ${list}; do if [ "${str}" == "${word}" ]; then newlist="${newlist} ${new_words}" else newlist="${newlist} ${str}" fi done echo "${newlist}" } build_kconfig_registry() { local familyname clist config kernels kernel cur_configs newvalue familyname="$1" #clist="${config_registry[${familyname}]}" clist=$(query_array "config_registry" ${familyname}) for config in ${clist}; do # Look up the kernels for the current sub-configuration. #kernels="${kernel_registry[${config}]}" kernels=$(query_array "kernel_registry" ${config}) for kernel in ${kernels}; do # Add the sub-configuration to the list associated with the # kernel. # Query the current sub-configs for the current ${kernel}. #cur_configs="${kconfig_registry[${kernel}]}" cur_configs=$(query_array "kconfig_registry" ${kernel}) # Add the current sub-configuration to the list of sub-configs # we just queried. newvalue=$(canonicalize_ws "${cur_configs} ${config}") # Update the array. #kconfig_registry[${kernel}]="${newvalue}" #printf -v "kconfig_registry_${kernel}" %s "${newvalue}" assign_key_value "kconfig_registry" "${kernel}" "${newvalue}" done done } is_in_list() { local word list rval item word="$1" list="$2" rval="false" for item in ${list}; do if [ "${item}" == "${word}" ]; then rval="true" break fi done echo "${rval}" } is_singleton() { local list rval count_str item list="$1" rval="false" count_str="" for item in ${list}; do count_str="${count_str}x" done if [ "${count_str}" == "x" ]; then rval="true" fi echo "${rval}" } is_singleton_family() { local familyname memberlist rval familyname="$1" memberlist="$2" rval="false" if [ $(is_singleton "${memberlist}") ]; then if [ "${memberlist}" == "${familyname}" ]; then rval="true" fi fi echo "${rval}" } remove_from_list() { local strike_list list flist item strike_words="$1" list="$2" flist="" for item in ${list}; do # Filter out any list item that matches any of the strike words. if [ $(is_in_list "${item}" "${strike_words}") == "false" ]; then flist="${flist} ${item}" fi done flist=$(canonicalize_ws "${flist}") # Return the filtered list. echo "${flist}" } canonicalize_ws() { local str str="$1" # Remove leading and trailing whitespace. str=$(echo -e "${str}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//') # Remove duplicate spaces between words. str=$(echo -e "${str}" | tr -s " ") # Update the input argument. echo "${str}" } rm_duplicate_words_simple() { local str revstr revres res str="$1" # Remote duplicates, keeping the first occurrence. res=$(echo "${str}" | awk '{for (i=1;i<=NF;i++) if (!a[$i]++) printf("%s%s",$i,FS)}{printf("\n")}') echo "${res}" } rm_duplicate_words() { local str revstr revres res str="$1" # We reverse the initial string, THEN remove duplicates, then reverse # the de-duplicated result so that only the last instance is kept after # removing duplicates (rather than keeping only the first). This is # totally unnecessary but works well for the kinds of duplicates that # show up in certain use cases of the config and kernel registries. # For example, these gymnastics allow us to keep only the last instance # of the 'generic' configuration in a configuration family that # includes it twice or more. revstr=$(echo "${str}" | awk '{ for (i=NF; i>1; i--) printf("%s ",$i); print $1; }') revres=$(echo "${revstr}" | awk '{for (i=1;i<=NF;i++) if (!a[$i]++) printf("%s%s",$i,FS)}{printf("\n")}') res=$(echo "${revres}" | awk '{ for (i=NF; i>1; i--) printf("%s ",$i); print $1; }') echo "${res}" } get_cc_search_list() { local list # For Linux, Darwin (OS X), and generic OSes, prioritize gcc. list="gcc clang cc" # For OpenBSD and FreeBSD, prioritize cc and clang over gcc. if [ "${os_name}" = "OpenBSD" ]; then list="cc clang gcc" elif [ "${os_name}" = "FreeBSD" ]; then list="cc clang gcc" fi echo "${list}" } get_cxx_search_list() { local list # For Linux, Darwin (OS X), and generic OSes, prioritize g++. list="g++ clang++ c++" # For OpenBSD and FreeBSD, prioritize cc and clang over gcc. if [ "${os_name}" = "OpenBSD" ]; then list="c++ clang++ g++" elif [ "${os_name}" = "FreeBSD" ]; then list="c++ clang++ g++" fi echo "${list}" } get_fc_search_list() { local list list="gfortran ifort" echo "${list}" } get_ar_search_list() { local list list="ar" echo "${list}" } get_ranlib_search_list() { local list list="ranlib" echo "${list}" } auto_detect() { local cc cflags config_defines detected_config rval cmd # Use the same compiler that was found earlier. cc="${found_cc}" # For debugging: reveal what compiler was chosen for auto-detection. #touch "${cc}.txt" # Tweak the flags we use based on the compiler. This is mostly just # an opportunity to turn off annoying warnings that some compilers # may throw off. if [ "${cc}" == "clang" ]; then cflags="-Wno-tautological-compare" else cflags= fi # Accumulate a list of source files we'll need to compile along with # the top-level (root) directory in which they are located. c_src_pairs="" c_src_pairs="${c_src_pairs} frame:bli_arch.c" c_src_pairs="${c_src_pairs} frame:bli_cpuid.c" c_src_pairs="${c_src_pairs} frame:bli_env.c" c_src_pairs="${c_src_pairs} build:config_detect.c" # Accumulate a list of full filepaths to the source files listed above. c_src_filepaths="" for pair in ${c_src_pairs}; do filename=${pair#*:} rootdir=${pair%:*} filepath=$(find ${dist_path}/${rootdir} -name "${filename}") c_src_filepaths="${c_src_filepaths} ${filepath}" done # Accumulate a list of header files we'll need to locate along with # the top-level (root) directory in which they are located. c_hdr_pairs="" c_hdr_pairs="${c_hdr_pairs} frame:bli_system.h" c_hdr_pairs="${c_hdr_pairs} frame:bli_type_defs.h" c_hdr_pairs="${c_hdr_pairs} frame:bli_arch.h" c_hdr_pairs="${c_hdr_pairs} frame:bli_cpuid.h" c_hdr_pairs="${c_hdr_pairs} frame:bli_env.h" # NOTE: These headers are needed by bli_type_defs.h. c_hdr_pairs="${c_hdr_pairs} frame:bli_malloc.h" c_hdr_pairs="${c_hdr_pairs} frame:bli_pthread.h" # Accumulate a list of full paths to the header files listed above. # While we are at it, we include the "-I" compiler option to indicate # adding the path to the list of directories to search when encountering # #include directives. c_hdr_paths="" for pair in ${c_hdr_pairs}; do filename=${pair#*:} rootdir=${pair%:*} filepath=$(find ${dist_path}/${rootdir} -name "${filename}") path=${filepath%/*} c_hdr_paths="${c_hdr_paths} -I${path}" done # Define the executable name. autodetect_x="auto-detect.x" # Create #defines for all of the BLIS_CONFIG_ macros in bli_cpuid.c. bli_cpuid_c_filepath=$(find ${dist_path}/frame -name "bli_cpuid.c") config_defines=$(grep BLIS_CONFIG_ ${bli_cpuid_c_filepath} \ | sed -e 's/#ifdef /-D/g') # Set the linker flags. We typically need pthreads (or BLIS's homerolled # equiavlent) because it is needed for parts of bli_arch.c unrelated to # bli_arch_string(), which is called by the main() function in ${main_c}. if [[ "$is_win" == "no" || "$cc_vendor" != "clang" ]]; then ldflags="${LIBPTHREAD--lpthread}" fi # However, if --disable-system was given, we override the choice made above # and do not use any pthread link flags. if [[ "$enable_system" == "no" ]]; then ldflags= fi # Compile the auto-detect program using source code inside the # framework. # NOTE: -D_GNU_SOURCE is needed to enable POSIX extensions to # pthreads (i.e., barriers). cmd="${cc} ${config_defines} \ -DBLIS_CONFIGURETIME_CPUID \ ${c_hdr_paths} \ -std=c99 -D_GNU_SOURCE \ ${cflags} \ ${c_src_filepaths} \ ${ldflags} \ -o ${autodetect_x}" if [ "${debug_auto_detect}" == "no" ]; then # Execute the compilation command. eval ${cmd} else # Debugging stuff. Instead of executing ${cmd}, join the lines together # with tr and trim excess whitespace via awk. cmd=$(echo "${cmd}" | tr '\n' ' ' | awk '{$1=$1;print}') echo "${cmd}" return fi # Run the auto-detect program. detected_config=$(./${autodetect_x}) # Remove the executable file. rm -f ./${autodetect_x} # Return the detected sub-configuration name. echo "${detected_config}" } has_libmemkind() { local main_c main_c_filepath LDFLAGS_mk binname rval # Path to libmemkind detection source file. main_c="libmemkind_detect.c" main_c_filepath=$(find ${dist_path}/build -name "${main_c}") # Add libmemkind to LDFLAGS. LDFLAGS_mk="${LDFLAGS} -lmemkind" # Binary executable filename. binname="libmemkind-detect.x" # Attempt to compile a simple main() program that contains a call # to hbw_malloc() and that links to libmemkind. ${found_cc} -o ${binname} ${main_c_filepath} ${LDFLAGS_mk} 2> /dev/null # Depending on the return code from the compile step above, we set # enable_memkind accordingly. if [ "$?" == 0 ]; then rval='yes' else rval='no' fi # Remove the executable generated above. rm -f ./${binname} echo "${rval}" } has_pragma_omp_simd() { local main_c main_c_filepath binname rval # Path to omp-simd detection source file. main_c="omp_simd_detect.c" main_c_filepath=$(find ${dist_path}/build -name "${main_c}") # Binary executable filename. binname="omp_simd-detect.x" # Attempt to compile a simple main() program that contains a # #pragma omp simd. ${found_cc} -std=c99 -O3 -march=native -fopenmp-simd \ -o ${binname} ${main_c_filepath} 2> /dev/null # Depending on the return code from the compile step above, we set # enable_memkind accordingly. if [ "$?" == 0 ]; then rval='yes' else rval='no' fi # Remove the executable generated above. rm -f ./${binname} echo "${rval}" } echoerr() { printf "${script_name}: error: %s\n" "$*" #>&2; } echowarn() { printf "${script_name}: warning: %s\n" "$*" #>&2; } blacklistcc_add() { # Check whether we've already blacklisted the given sub-config so # we don't output redundant messages. if [ $(is_in_list "$1" "${config_blist}") == "false" ]; then echowarn "${cc_vendor} ${cc_version} does not support '$1'; adding to blacklist." config_blist="${config_blist} $1" fi } blacklistbu_add() { # Check whether we've already blacklisted the given sub-config so # we don't output redundant messages. if [ $(is_in_list "$1" "${config_blist}") == "false" ]; then echowarn "assembler ('as' ${bu_version}) does not support '$1'; adding to blacklist." config_blist="${config_blist} $1" fi } blacklist_init() { config_blist="" } blacklist_cleanup() { # Remove duplicates and whitespace from the blacklist. config_blist=$(rm_duplicate_words "${config_blist}") config_blist=$(canonicalize_ws "${config_blist}") } echoerr_unsupportedcc() { echoerr "${script_name}: *** Unsupported compiler version: ${cc_vendor} ${cc_version}." exit 1 } echoerr_unsupportedpython() { echoerr "${script_name}: *** Unsupported python version: ${python_version}." exit 1 } get_binutils_version() { binutil=${AS:-as} # Query the full binutils version string output. This includes the # version string along with (potentially) a bunch of other textual # clutter. if [ "$(uname -s)" == "Darwin" ]; then # The default OS X assembler uses a trifecta of brain-dead # conventions: responding only to '-v', hanging indefinitely if # not given an argument, and outputing the result to stderr. # (And if you still weren't convinced, it creates an 'a.out' # by default. So yeah.) bu_string=$(${binutil} -v /dev/null -o /dev/null 2>&1) else bu_string=$(${binutil} --version 2>/dev/null) fi # Query the binutils version number. # The last part ({ read first rest ; echo $first ; }) is a workaround # to OS X's egrep only returning the first match. bu_version=$(echo "${bu_string}" | egrep -o '[0-9]+\.[0-9]+\.?[0-9]*' | { read first rest ; echo ${first} ; }) # Parse the version number into its major, minor, and revision # components. bu_major=$(echo "${bu_version}" | cut -d. -f1) bu_minor=$(echo "${bu_version}" | cut -d. -f2) bu_revision=$(echo "${bu_version}" | cut -d. -f3) echo "${script_name}: found assembler ('as') version ${bu_version} (maj: ${bu_major}, min: ${bu_minor}, rev: ${bu_revision})." } get_python_search_list() { local list # For Linux, Darwin (OS X), and generic OSes, prioritize 'python'. list="python python3 python2" echo "${list}" } get_python_version() { local python vendor_string python="${found_python}" # Query the python version. This includes the version number along # with other text, such as "Python ". # NOTE: Python seems to echo its version info to stderr, not # stdout, and thus we redirect stderr to stdout and capture that. vendor_string="$(${python} --version 2>&1)" # Drop any preceding text and save only the first numbers and what # comes after. python_version=$(echo "${vendor_string}" | sed -e "s/[a-zA-Z_ ]* \([0-9]*\..*\)/\1/g") # Parse the version number into its major, minor, and revision # components. python_major=$(echo "${python_version}" | cut -d. -f1) python_minor=$(echo "${python_version}" | cut -d. -f2) python_revision=$(echo "${python_version}" | cut -d. -f3) echo "${script_name}: found python version ${python_version} (maj: ${python_major}, min: ${python_minor}, rev: ${python_revision})." } check_python() { local python python="${found_python}" # # Python requirements # # python1: no versions supported # python2: 2.7+ # python3: 3.4+ # # NOTE: It's actually unclear whether python 3.0 through 3.3.x would work. # Python 3.5 is the oldest python3 that I have available to test with, and # I only know that 3.4 will work thanks to feedback from Dave Love. So it's # quite possible that some of those "unsupported" python3 versions are # sufficient. -FGVZ # # Python 1.x is unsupported. if [ ${python_major} -eq 1 ]; then echoerr_unsupportedpython fi # Python 2.6.x or older is unsupported. if [ ${python_major} -eq 2 ]; then if [ ${python_minor} -lt 7 ]; then echoerr_unsupportedpython fi fi # Python 3.3.x or older is unsupported. if [ ${python_major} -eq 3 ]; then if [ ${python_minor} -lt 4 ]; then echoerr_unsupportedpython fi fi echo "${script_name}: python ${python_version} appears to be supported." } get_compiler_version() { local cc vendor_string cc="${found_cc}" # Query the full vendor version string output. This includes the # version number along with (potentially) a bunch of other textual # clutter. # NOTE: This maybe should use merged stdout/stderr rather than only # stdout. But it works for now. vendor_string="$(${cc} --version 2>/dev/null)" # Query the compiler "vendor" (ie: the compiler's simple name) and # isolate the version number. # The last part ({ read first rest ; echo $first ; }) is a workaround # to OS X's egrep only returning the first match. cc_vendor=$(echo "${vendor_string}" | egrep -o 'icc|gcc|clang|emcc|pnacl|IBM|oneAPI|crosstool-NG|GCC' | { read first rest ; echo $first ; }) # AOCC version strings contain both "clang" and "AOCC" substrings, and # so we have perform a follow-up check to make sure cc_vendor gets set # correctly. aocc_grep=$(echo "${vendor_string}" | grep 'AOCC') if [ -n "${aocc_grep}" ]; then cc_vendor="aocc" fi # Detect armclang, which doesn't have a nice, unambiguous, one-word tag armclang_grep=$(echo "${vendor_string}" | grep 'Arm C/C++/Fortran Compiler') if [ -n "${armclang_grep}" ]; then cc_vendor="armclang" fi # Begin parsing cc_vendor for the version string. if [ "${cc_vendor}" = "GCC" ]; then # Conda gcc sometimes has GCC (all caps) in the version string cc_vendor="gcc" fi if [ "${cc_vendor}" = "crosstool-NG" ]; then # Treat compilers built by crosstool-NG (for eg: conda) as gcc. cc_vendor="gcc" fi if [ "${cc_vendor}" = "icc" -o \ "${cc_vendor}" = "gcc" ]; then cc_version=$(${cc} -dumpversion) elif [ "${cc_vendor}" = "armclang" ]; then # Treat armclang as regular clang. cc_vendor="clang" cc_version=$(echo "${vendor_string}" \ | egrep -o 'based on LLVM [0-9]+\.[0-9]+\.?[0-9]*' \ | egrep -o '[0-9]+\.[0-9]+\.?[0-9]*') elif [ "${cc_vendor}" = "clang" ]; then cc_version=$(echo "${vendor_string}" \ | egrep -o '(clang|LLVM) version [0-9]+\.[0-9]+\.?[0-9]*' \ | egrep -o '[0-9]+\.[0-9]+\.?[0-9]*') elif [ "${cc_vendor}" = "aocc" ]; then aocc_ver21=$(echo "${vendor_string}" | grep 'AOCC.LLVM.2') # Versions 2.0 and 2.1 had different version string formats from # 2.2 and later, so we have to handle them separately. # Examples: # AOCC.LLVM.2.0.0.B191.2019_07_19 clang version 8.0.0 (CLANG: Jenkins AOCC_2_0_0-Build#191) (based on LLVM AOCC.LLVM.2.0.0.B191.2019_07_19) # AOCC.LLVM.2.1.0.B1030.2019_11_12 clang version 9.0.0 (CLANG: Build#1030) (based on LLVM AOCC.LLVM.2.1.0.B1030.2019_11_12) # AMD clang version 10.0.0 (CLANG: AOCC_2.2.0-Build#93 2020_06_25) (based on LLVM Mirror.Version.10.0.0) # AMD clang version 11.0.0 (CLANG: AOCC_2.3.0-Build#85 2020_11_10) (based on LLVM Mirror.Version.11.0.0) # AMD clang version 12.0.0 (CLANG: AOCC_3.0.0-Build#2 2020_11_05) (based on LLVM Mirror.Version.12.0.0) if [ -n "${aocc_ver21}" ]; then # Grep for the AOCC.LLVM.x.y.z substring first, and then isolate the # version number. Also, the string may contain multiple instances of # the version number, so only use the first occurrence. cc_version=$(echo "${vendor_string}" \ | egrep -o 'AOCC.LLVM.[0-9]+\.[0-9]+\.?[0-9]*' \ | egrep -o '[0-9]+\.[0-9]+\.?[0-9]*' \ | { read first rest ; echo $first ; }) else # Grep for the AOCC_x.y.z substring first, and then isolate the # version number. As of this writing, these version strings don't # include multiple instances of the version, but we nonetheless # take only the first occurrence as a future-oriented safety # measure. cc_version=$(echo "${vendor_string}" \ | egrep -o 'AOCC_[0-9]+\.[0-9]+\.?[0-9]*' \ | egrep -o '[0-9]+\.[0-9]+\.?[0-9]*' \ | { read first rest ; echo $first ; }) fi elif [ "${cc_vendor}" = "oneAPI" ]; then # Treat Intel oneAPI's clang as clang, not icc. cc_vendor="clang" cc_version=$(echo "${vendor_string}" \ | egrep -o '[0-9]+\.[0-9]+\.[0-9]+\.?[0-9]*' \ | { read first rest ; echo ${first} ; }) else cc_version=$(echo "${vendor_string}" \ | egrep -o '[0-9]+\.[0-9]+\.?[0-9]*' \ | { read first rest ; echo ${first} ; }) fi # Parse the version number into its major, minor, and revision # components. cc_major=$(echo "${cc_version}" | cut -d. -f1) cc_minor=$(echo "${cc_version}" | cut -d. -f2) cc_revision=$(echo "${cc_version}" | cut -d. -f3) # gcc 7 introduced new behavior to -dumpversion whereby only the major # version component is output. However, as part of this change, gcc 7 # also introduced a new option, -dumpfullversion, which is guaranteed to # always output the major, minor, and revision numbers. Thus, if we're # using gcc and its version is 7 or later, we re-query and re-parse the # version string. if [ "${cc_vendor}" = "gcc" -a ${cc_major} -ge 7 ]; then # Re-query the version number using -dumpfullversion. cc_version=$(${cc} -dumpfullversion) # And parse the result. cc_major=$(echo "${cc_version}" | cut -d. -f1) cc_minor=$(echo "${cc_version}" | cut -d. -f2) cc_revision=$(echo "${cc_version}" | cut -d. -f3) fi echo "${script_name}: found ${cc_vendor} version ${cc_version} (maj: ${cc_major}, min: ${cc_minor}, rev: ${cc_revision})." } check_compiler() { local cc cc="${found_cc}" # # Compiler requirements # # General: # # icc 15+, gcc 4.7+, clang 3.3+ # # Specific: # # skx: icc 15.0.1+, gcc 6.0+, clang 3.9+ # knl: icc 14.0.1+, gcc 5.0+, clang 3.9+ # haswell: any # sandybridge: any # penryn: any # # zen: gcc 6.0+[1], clang 4.0+ # zen2: gcc 6.0+[1], clang 4.0+ # zen3: gcc 6.0+[1], clang 4.0+ # excavator: gcc 4.9+, clang 3.5+ # steamroller: any # piledriver: any # bulldozer: any # # cortexa57: any # cortexa15: any # cortexa9: any # # armsve: clang11+, gcc10+ # # generic: any # # Note: These compiler requirements were originally modeled after similar # requirements encoded into TBLIS's configure.ac [2]. # # [1] While gcc 6.0 or newer is needed for zen support (-march=znver1), # we relax this compiler version constraint a bit by targeting bdver4 # and then disabling the instruction sets that were removed in the # transition from bdver4 to znver1. (See config/zen/make_defs.mk for # the specific compiler flags used.) # [2] https://github.com/devinamatthews/tblis/ # echo "${script_name}: checking for blacklisted configurations due to ${cc} ${cc_version}." # Fixme: check on a64fx, neoverse, and others # gcc if [ "x${cc_vendor}" = "xgcc" ]; then if [ ${cc_major} -lt 4 ]; then echoerr_unsupportedcc fi if [ ${cc_major} -eq 4 ]; then blacklistcc_add "knl" if [ ${cc_minor} -lt 7 ]; then echoerr_unsupportedcc fi if [ ${cc_minor} -lt 9 ]; then blacklistcc_add "excavator" blacklistcc_add "zen" fi fi if [ ${cc_major} -lt 5 ]; then blacklistcc_add "knl" fi if [ ${cc_major} -lt 6 ]; then # Normally, zen would be blacklisted for gcc prior to 6.0. # However, we have a workaround in place in the zen # configuration's make_defs.mk file that starts with bdver4 # and disables the instructions that were removed in znver1. # Thus, this "blacklistcc_add" statement has been moved above. #blacklistcc_add "zen" blacklistcc_add "skx" # gcc 5.x may support POWER9 but it is unverified. blacklistcc_add "power9" fi if [ ${cc_major} -lt 10 ]; then blacklistcc_add "armsve" fi fi # icc if [ "x${cc_vendor}" = "xicc" ]; then if [ ${cc_major} -lt 15 ]; then echoerr_unsupportedcc fi if [ ${cc_major} -eq 15 ]; then if [ ${cc_revision} -lt 1 ]; then blacklistcc_add "skx" fi fi if [ ${cc_major} -eq 18 ]; then echo "${script_name}: ${cc} ${cc_version} is known to cause erroneous results. See https://github.com/flame/blis/issues/371 for details." blacklistcc_add "knl" blacklistcc_add "skx" fi if [ ${cc_major} -ge 19 ]; then echo "${script_name}: ${cc} ${cc_version} is known to cause erroneous results. See https://github.com/flame/blis/issues/371 for details." echoerr_unsupportedcc fi fi # clang if [ "x${cc_vendor}" = "xclang" ]; then if [ "$(echo ${vendor_string} | grep -o Apple)" = "Apple" ]; then if [ ${cc_major} -lt 5 ]; then echoerr_unsupportedcc fi # See https://en.wikipedia.org/wiki/Xcode#Toolchain_versions if [ ${cc_major} -eq 5 ]; then # Apple clang 5.0 is clang 3.4svn blacklistcc_add "excavator" blacklistcc_add "zen" fi if [ ${cc_major} -lt 7 ]; then blacklistcc_add "knl" blacklistcc_add "skx" fi else if [ ${cc_major} -lt 3 ]; then echoerr_unsupportedcc fi if [ ${cc_major} -eq 3 ]; then if [ ${cc_minor} -lt 3 ]; then echoerr_unsupportedcc fi if [ ${cc_minor} -lt 5 ]; then blacklistcc_add "excavator" blacklistcc_add "zen" fi if [ ${cc_minor} -lt 9 ]; then blacklistcc_add "knl" blacklistcc_add "skx" fi fi if [ ${cc_major} -lt 4 ]; then # See comment above regarding zen support. #blacklistcc_add "zen" : # explicit no-op since bash can't handle empty loop bodies. fi if [ ${cc_major} -lt 11 ]; then blacklistcc_add "armsve" fi fi fi } check_compiler_version_ranges() { local cc cc="${found_cc}" # # We check for various compiler version ranges that may cause us # issues in properly supporting those compiler versions within the # BLIS build system. # # range: gcc < 4.9.0 (ie: 4.8.5 or older) # variable: gcc_older_than_4_9_0 # comments: # These older versions of gcc may support microarchitectures such as # sandybridge, but the '-march=' flag uses a different label syntax. # In newer versions, '-march=sandybridge' is the preferred syntax [1]. # However, in older versions, the syntax for the same compiler option # is '-march=corei7-avx' [2]. # # [1] https://gcc.gnu.org/onlinedocs/gcc-4.9.0/gcc/i386-and-x86-64-Options.html#i386-and-x86-64-Options # [2] https://gcc.gnu.org/onlinedocs/gcc-4.8.5/gcc/i386-and-x86-64-Options.html#i386-and-x86-64-Options # # range: gcc < 6.1 (ie: 5.5 or older) # variable: gcc_older_than_6_1_0 # comments: # These older versions of gcc do not explicitly support the Zen (Zen1) # microarchitecture; the newest microarchitectural value understood by # these versions is '-march=bdver4' [3]. However, basic support for these # older versions can be attained in a roundabout way by starting with the # instruction sets enabled by '-march=bdver4' and then disabling the # instruction sets that were removed in the transition from Excavator to # Zen, namely: FMA4, TBM, XOP, and LWP. Newer versions of gcc support Zen # via the '-march=znver1' option [4]. # # [3] https://gcc.gnu.org/onlinedocs/gcc-5.5.0/gcc/x86-Options.html#x86-Options # [4] https://gcc.gnu.org/onlinedocs/gcc-6.1.0/gcc/x86-Options.html#x86-Options # # range: gcc < 9.1 (ie: 8.3 or older) # variable: gcc_older_than_9_1_0 # comments: # These older versions of gcc do not explicitly support the Zen2 # microarchitecture; the newest microarchitectural value understood by # these versions is either '-march=znver1' (if !gcc_older_than_6_1_0) [5] # or '-march=bdver4' (if gcc_older_than_6_1_0) [3]. If gcc is 6.1 or # newer, '-march=znver1' may be used (since the instruction sets it # enables are a subset of those enabled by '-march=znver2'); otherwise, # '-march=bdver4' must be used in conjuction with disabling the # instruction sets that were removed in the transition from Excavator to # Zen, as described in the section above for gcc_older_than_6_1_0. # Newer versions of gcc support Zen2 via the '-march=znver2' option [6]. # # [5] https://gcc.gnu.org/onlinedocs/gcc-8.3.0/gcc/x86-Options.html#x86-Options # [6] https://gcc.gnu.org/onlinedocs/gcc-9.4.0/gcc/x86-Options.html#x86-Options # # range: gcc < 10.1 (ie: 9.4 or older) # variable: gcc_older_than_10_1_0 # comments: # These older versions of gcc do not explicitly support the Zen3 # microarchitecture; the newest microarchitectural value understood by # these versions is '-march=znver2' (if !gcc_older_than_9_1_0) [7]. # Newer versions of gcc support Zen3 via the '-march=znver3' option [8]. # # [7] https://gcc.gnu.org/onlinedocs/gcc-9.4.0/gcc/x86-Options.html#x86-Options # [8] https://gcc.gnu.org/onlinedocs/gcc-10.3.0/gcc/x86-Options.html#x86-Options # gcc_older_than_4_9_0='no' gcc_older_than_6_1_0='no' gcc_older_than_9_1_0='no' gcc_older_than_10_1_0='no' clang_older_than_9_0_0='no' clang_older_than_12_0_0='no' aocc_older_than_2_0_0='no' aocc_older_than_3_0_0='no' echo "${script_name}: checking ${cc} ${cc_version} against known consequential version ranges." # gcc if [ "x${cc_vendor}" = "xgcc" ]; then # Check for gcc < 4.9.0 (ie: 4.8.5 or older). if [ ${cc_major} -eq 4 ]; then if [ ${cc_minor} -lt 9 ]; then echo "${script_name}: note: found ${cc} version older than 4.9.0." gcc_older_than_4_9_0='yes' fi fi # Check for gcc < 6.1.0 (ie: 5.5 or older). if [ ${cc_major} -lt 6 ]; then echo "${script_name}: note: found ${cc} version older than 6.1." gcc_older_than_6_1_0='yes' fi # Check for gcc < 9.1.0 (ie: 8.3 or older). if [ ${cc_major} -lt 9 ]; then echo "${script_name}: note: found ${cc} version older than 9.1." gcc_older_than_9_1_0='yes' fi # Check for gcc < 10.1.0 (ie: 9.4 or older). if [ ${cc_major} -lt 10 ]; then echo "${script_name}: note: found ${cc} version older than 10.1." gcc_older_than_10_1_0='yes' fi fi # icc if [ "x${cc_vendor}" = "xicc" ]; then : fi # clang if [ "x${cc_vendor}" = "xclang" ]; then # Check for clang < 9.0.0. if [ ${cc_major} -lt 9 ]; then echo "${script_name}: note: found ${cc} version older than 9.0." clang_older_than_9_0_0='yes' fi # Check for clang < 12.0.0. if [ ${cc_major} -lt 12 ]; then echo "${script_name}: note: found ${cc} version older than 12.0." clang_older_than_12_0_0='yes' fi fi # aocc if [ "x${cc_vendor}" = "xaocc" ]; then # Check for aocc < 2.0.0. if [ ${cc_major} -lt 2 ]; then echo "${script_name}: note: found ${cc} version older than 2.0." aocc_older_than_2_0_0='yes' fi # Check for aocc < 3.0.0. if [ ${cc_major} -lt 3 ]; then echo "${script_name}: note: found ${cc} version older than 3.0." aocc_older_than_3_0_0='yes' fi fi } check_assembler() { local cc asm_dir cflags asm_fp cc="${found_cc}" # The directory where the assembly files will be. asm_dir="${dist_path}/build" # Most of the time, we won't need any additional compiler flags. cflags="" echo "${script_name}: checking for blacklisted configurations due to as ${bu_version}." # # Check support for FMA4 (amd: bulldozer). # asm_fp=$(find ${asm_dir} -name "fma4.s") knows_fma4=$(try_assemble "${cc}" "${cflags}" "${asm_fp}") if [ "x${knows_fma4}" == "xno" ]; then blacklistbu_add "bulldozer" fi # # Check support for AVX (intel: sandybridge+, amd: piledriver+). # asm_fp=$(find ${asm_dir} -name "avx.s") knows_avx=$(try_assemble "${cc}" "${cflags}" "${asm_fp}") if [ "x${knows_avx}" == "xno" ]; then blacklistbu_add "sandybridge" fi # # Check support for FMA3 (intel: haswell+, amd: piledriver+). # asm_fp=$(find ${asm_dir} -name "fma3.s") knows_fma3=$(try_assemble "${cc}" "${cflags}" "${asm_fp}") if [ "x${knows_fma3}" == "xno" ]; then blacklistbu_add "haswell" blacklistbu_add "piledriver" blacklistbu_add "steamroller" blacklistbu_add "excavator" blacklistbu_add "skx" fi # # Check support for AVX-512f (knl, skx). # # The assembler on OS X won't recognize AVX-512 without help. if [ "${cc_vendor}" == "clang" ]; then cflags="-march=knl" fi asm_fp=$(find ${asm_dir} -name "avx512f.s") knows_avx512f=$(try_assemble "${cc}" "${cflags}" "${asm_fp}") if [ "x${knows_avx512f}" == "xno" ]; then blacklistbu_add "knl" blacklistbu_add "skx" fi # # Check support for AVX-512dq (skx). # # The assembler on OS X won't recognize AVX-512 without help. if [ "${cc_vendor}" == "clang" ]; then cflags="-march=skylake-avx512" fi asm_fp=$(find ${asm_dir} -name "avx512dq.s") knows_avx512dq=$(try_assemble "${cc}" "${cflags}" "${asm_fp}") if [ "x${knows_avx512dq}" == "xno" ]; then blacklistbu_add "skx" fi } try_assemble() { local cc cflags asm_src asm_base asm_bin rval cc="$1" cflags="$2" asm_src="$3" # Construct the filename to the .o file corresponding to asm_src. # (Strip the filepath, then the file extension, and then add ".o".) asm_base=${asm_src##*/} asm_base=${asm_base%.*} asm_bin="${asm_base}.o" # Try to assemble the file. ${cc} ${cflags} -c ${asm_src} -o ${asm_bin} > /dev/null 2>&1 if [ "$?" == 0 ]; then rval='yes' else rval='no' fi # Remove the object file. rm -f "${asm_bin}" # Return the result. echo "${rval}" } set_default_version() { local gitdir version_file gd_stderr git_describe_str git_error new_version_str gitdir='.git' # The path to the version file. version_file=$1 echo "${script_name}: determining default version string." # Check if the .git dir exists; if it does not, we do nothing. if [ -d "${dist_path}/${gitdir}" ]; then echo "${script_name}: found '${gitdir}' directory; assuming git clone." echo "${script_name}: executing: git describe --tags." gd_stderr="git_describe_stderr.txt" # Query git for the version string, which is simply the current tag, # followed by a number signifying how many commits have transpired # since the tag, followed by a 'g' and a shortened hash tab. Capture # stderr to a file. git_describe_str=$(git -C ${dist_path} describe --tags 2> ${gd_stderr}) # Pull in whatever error message was generated, if any, and delete # the file. git_error=$(cat ${gd_stderr}) # Remove the stderr file. rm -f ${gd_stderr} # If git returned an error, don't do anything. if [ -n "${git_error}" ]; then echo "${script_name}: git returned an error: '${git_error}'." echo "${script_name}: using string from unmodified version file." # Use what's in the version file as-is. version=$(cat "${version_file}") else echo "${script_name}: got back ${git_describe_str}." # Strip off the commit hash label. new_version_str=$(echo ${git_describe_str} | cut -d- -f-2) echo "${script_name}: truncating to ${new_version_str}." # Write the new version string to the version file. #echo "${new_version_str}" > ${version_file} # Set the version variable. version="${new_version_str}" fi else echo "${script_name}: could not find '${gitdir}' directory; using unmodified version file." # Use what's in the version file as-is. version=$(cat "${version_file}") fi } select_tool_w_env() { local search_list env_var env_str tool_str found_var local _the_tool # Example calling sequence: # # select_tool_w_env "${cc_search_list}" "${CC}" "CC" "C compiler" "yes" found_cc # search_list="$1" # the tool's default search list. env_var="$2" # the value of the environment variable for this tool. env_str="$3" # a string naming the source of env_var. tool_str="$4" # a human-readable string identifying the tool. is_required="$5" # is it fatal if env_var doesn't exist/work? (yes or no) found_var="$6" # the variable into which to save the selected tool. # If the environment variable contains something, verify that it exists. If # it is unset or empty, we proceed with the default search list. if [ -n "${env_var}" ]; then echo "${script_name}: user specified a ${tool_str} via ${env_str} (${env_var})." # See if the binary specified by env_var exists. _the_tool=$(select_tool "${env_var}" "${env_str}") # Copy the result into the variable specified by found_var. eval "${found_var}=\"${_the_tool}\"" # If the tool specified by env_var doesn't exist, throw a tantrum. if [ -z "${_the_tool}" ]; then echo "${script_name}: *** Could not find the ${tool_str} specified via ${env_str} ('${env_var}')." # Whether the tantrum is fatal depends on the is_required argument. if [ "${is_required}" == "yes" ]; then echo "${script_name}: *** A working ${tool_str} is required. Please set ${env_str}" echo "${script_name}: *** to a ${tool_str} that exists (or unset ${env_str})." exit 1 else echo "${script_name}: *** Note that a ${tool_str} will not be available." # Set the found_var variable to *something* so that the output # makefile fragment contains a record that the tool wasn't found. eval "${found_var}=\"${env_str}\"-not-found" fi else # The user-specified tool was found. echo "${script_name}: ${_the_tool} exists and appears to work." echo "${script_name}: using '${_the_tool}' as ${tool_str}." fi else echo "${script_name}: ${tool_str} search list is: ${search_list}." # Search for a working tool from the search list. _the_tool=$(select_tool "${search_list}" "${env_str}") # Copy the result into the variable specified by found_var. eval "${found_var}=\"${_the_tool}\"" # If we didn't find a working tool from the search list, throw a tantrum. if [ -z "${_the_tool}" ]; then echo "${script_name}: *** Could not find a ${tool_str} from the search list." # Whether the tantrum is fatal depends on the is_required argument. if [ "${is_required}" == "yes" ]; then echo "${script_name}: *** A working ${tool_str} is required. Cannot continue." exit 1 else echo "${script_name}: *** Note that a ${tool_str} will not be available." # Set the found_var variable to *something* so that the output # makefile fragment contains a record that the tool wasn't found. eval "${found_var}=\"${env_str}-not-found\"" fi else # A tool from the search list was found. echo "${script_name}: found '${_the_tool}'." echo "${script_name}: using '${_the_tool}' as ${tool_str}." fi fi } select_tool() { local search_list env_str local the_tool tool the_flags rval # This is the list of tools to search for, and the order in which # to search for them. search_list="$1" # This is the name of the environment variable associated with the tool. For # example, if search_list is a list of C compilers, env_str will be "CC". env_str="$2" # Initialize our selected tool to empty. the_tool="" # Try each tool in the list and select the first one we find that works. for tool in ${search_list}; do # Map each tool (via its canonical environment variable form) to the set # of options we should use to check that it is working and available. the_flags=$(get_tool_checkflags "${env_str}") # Check that the tool works with at least one of the flags in the_flags # the_flags (or, if the_flags is empty, check that the tool exists). rval=$(check_tool "${tool}" "${the_flags}") # If check_tool() returns 0, we're done. if [ "${rval}" == "0" ]; then the_tool=${tool} break fi done # Return the selected tool. echo "${the_tool}" } get_tool_checkflags() { local env_str local allflags flaglist # The tool for which we will determine the flag/option to pass in # when testing that the tool works. Notice that it's not actually # the tool but rather its equivalent environment variable. env_str="${1}" # The default list of flags to use in most circumstances. allflags="--version -V -h" if [ "${os_name}" = "Linux" ]; then # If we are on Linux, it is very likely that all the tools will respond # to at least one of the usual flags. flaglist="${allflags}" else # If we are on Darwin/OSX/BSD or something else, we sometimes skip flag # checks. (Note that when the list of flags to check is empty, we end # up testing for the existence of the tool instead.) if [ "${env_str}" = "AR" -o \ "${env_str}" = "RANLIB" ]; then # AR, RANLIB may not respond to the normal flags on Darwin/OSX/BSD, # so all we can really do is check for their existence. flaglist="" else # Even on Darwin/OSX/BSD, we expect that CC, CXX, FC, PYTHON will # respond to the typical flag checklist. flaglist="${allflags}" fi fi echo "${flaglist}" } check_tool() { local tool the_flags local rval opt toolpath # This is the name, or filepath, of the tool to check for. tool="$1" # Some command line options to try to determine that the tool works. the_flags="$2" # Start with the assuming that the tool doesn't work/exist. rval=1 if [ -n "${the_flags}" ]; then # If the list of flags to check non-empty, we will iterate through the # list in search of a flag that works. Failure to find one that works # means the tool doesn't work (or, if the user specified the tool via # its environment variable, failure might mean that the tool doesn't # even exist). # Try each flag in the list of flags. for opt in ${the_flags}; do # See if the tool responds to the current flag. ${tool} ${opt} > /dev/null 2>&1 # If the tool responded to the flag with a nominal error code of # 0, we found one that works and set rval accoringly. if [ "$?" == 0 ]; then rval=0 break fi done else # If the list of flags to check is empty, we interpret this as a # request to instead check for the existence of the tool. # Use 'which' to determine if the tool exists. toolpath="$(which ${tool} 2> /dev/null)" # If the tool doesn't exist, we set rval accordingly. if [ -n "${toolpath}" ]; then rval=0 fi fi # Return the error code. echo "${rval}" } # # -- main function ------------------------------------------------------------- # main() { #declare -A config_registry #declare -A kernel_registry #declare -A kconfig_registry # -- Basic names and paths -- # The name of the script, stripped of any preceeding path. script_name=${0##*/} # The path to the script. We need this to find the top-level directory # of the source distribution in the event that the user has chosen to # build elsewhere. dist_path=${0%/${script_name}} # The path to the directory in which we are building. We do this to # make explicit that we distinguish between the top-level directory # of the distribution and the directory in which we are building. cur_dirpath="." # The file in which the version string is kept. version_file="version" version_filepath="${dist_path}/${version_file}" # The name of and path to the directory named "build" in the top-level # directory of the source distribution. build_dir='build' build_dirpath="${dist_path}/${build_dir}" # The name/path to the registry (master list) of supported configurations. registry_file="config_registry" registry_filepath=${dist_path}/${registry_file} # The names/paths for the template config.mk.in and its instantiated # counterpart. config_mk_in='config.mk.in' config_mk_out='config.mk' config_mk_in_path="${build_dirpath}/${config_mk_in}" config_mk_out_path="${cur_dirpath}/${config_mk_out}" # The names/paths for the template bli_config.h.in and its instantiated # counterpart. bli_config_h_in='bli_config.h.in' bli_config_h_out='bli_config.h' bli_config_h_in_path="${build_dirpath}/${bli_config_h_in}" bli_config_h_out_path="${cur_dirpath}/${bli_config_h_out}" # The names/paths for the template bli_addon.h.in and its instantiated # counterpart. bli_addon_h_in='bli_addon.h.in' bli_addon_h_out='bli_addon.h' bli_addon_h_in_path="${build_dirpath}/${bli_addon_h_in}" bli_addon_h_out_path="${cur_dirpath}/${bli_addon_h_out}" # Path to 'mirror-tree.sh' script. mirror_tree_sh="${build_dirpath}/mirror-tree.sh" # Path to 'gen-make-frags.sh' script and directory. gen_make_frags_dirpath="${build_dirpath}/gen-make-frags" gen_make_frags_sh="${gen_make_frags_dirpath}/gen-make-frag.sh" # The name of the (top-level) configuration directory. config_dir='config' config_dirpath="${dist_path}/${config_dir}" # The name of the (top-level) kernels directory. kernels_dir='kernels' kernels_dirpath="${dist_path}/${kernels_dir}" # The name of the (top-level) reference kernels directory. refkern_dir='ref_kernels' refkern_dirpath="${dist_path}/${refkern_dir}" # The root directory of the BLIS framework. frame_dir='frame' frame_dirpath="${dist_path}/${frame_dir}" # The names of the addons. addon_dir='addon' addon_dirpath="${dist_path}/${addon_dir}" # The name of the sandbox directory. sandbox_dir='sandbox' sandbox_dirpath="${dist_path}/${sandbox_dir}" # The name of the directory in which object files will be kept. obj_dir='obj' obj_dirpath="${cur_dirpath}/${obj_dir}" # The name of the directory in which libraries will be kept. lib_dir='lib' lib_dirpath="${cur_dirpath}/${lib_dir}" # The name of the directory in which headers will be kept. include_dir='include' include_dirpath="${cur_dirpath}/${include_dir}" # The name of the directory in which the BLAS test suite is kept. blastest_dir='blastest' # The name of the directory in which the BLIS test suite is kept. testsuite_dir='testsuite' # -- Version-related -- # The shared library (.so) version file. so_version_file='so_version' so_version_filepath="${dist_path}/${so_version_file}" # The major and minor/build .so version numbers. so_version_major='' so_version_minorbuild='' # -- configure options -- # Define the default prefix so that the print_usage() function can # output it in the --help text. prefix_def='/usr/local' # The installation prefix, assigned its default value, and a flag to # track whether or not it was given by the user. prefix=${prefix_def} prefix_flag='' # The installation exec_prefix, assigned its default value, and a flag to # track whether or not it was given by the user. exec_prefix='${prefix}' exec_prefix_flag='' # The installation libdir, assigned its default value, and a flag to # track whether or not it was given by the user. libdir='${exec_prefix}/lib' libdir_flag='' # The installation includedir, assigned its default value, and a flag to # track whether or not it was given by the user. includedir='${prefix}/include' includedir_flag='' # The installation sharedir, assigned its default value, and a flag to # track whether or not it was given by the user. sharedir='${prefix}/share' sharedir_flag='' # The preset value of CFLAGS and LDFLAGS (ie: compiler and linker flags # to use in addition to those determined by the build system). cflags_preset='' ldflags_preset='' # The user-given debug type and a flag indicating it was given. debug_type='' debug_flag='' # The system flag. enable_system='yes' # The threading flag. threading_model='off' # The method of assigning micropanels to threads in the JR and JR loops. thread_part_jrir='slab' # Option variables. quiet_flag='' show_config_list='' # Additional flags. enable_verbose='no' enable_arg_max_hack='no' enable_static='yes' enable_shared='yes' enable_rpath='no' export_shared='public' enable_pba_pools='yes' enable_sba_pools='yes' enable_mem_tracing='no' int_type_size=0 blas_int_type_size=32 enable_blas='yes' enable_cblas='no' enable_mixed_dt='yes' enable_mixed_dt_extra_mem='yes' enable_sup_handling='yes' enable_amd_frame_tweaks='no' enable_memkind='' # The default memkind value is determined later on. enable_trsm_preinversion='yes' force_version='no' complex_return='default' # The addon flag and names. addon_flag='' addon_list='' # The sandbox flag and name. sandbox_flag='' sandbox='' # -- Configuration registry -- # The name of the chosen configuration (the configuration "family"). config_name='' # The list of sub-configurations associated with config_name. config_list='' # The list of kernel sets that will be needed by the sub-configurations # in config_list.. kernel_list='' # The list of kernel:sub-configuration pairs for all kernels contained # in kernel_list. kconfig_map='' # -- Out-of-tree -- # Whether we are building out-of-tree. configured_oot="no" # Dummy file. Used to check whether the cwd is the same as the top-level # source distribution directory. dummy_file='_blis_dir_detect.tmp' # -- Debugging -- # A global flag to help debug the compilation command for the executable # that configure builds on-the-fly to perform hardware auto-detection. debug_auto_detect="no" # -- Command line option/argument parsing ---------------------------------- found=true while $found = true; do # Process our command line options. unset OPTIND while getopts ":hp:d:e:a:s:t:r:qci:b:-:" opt; do case $opt in -) case "$OPTARG" in help) print_usage ;; quiet) quiet_flag=1 ;; prefix=*) prefix_flag=1 prefix=${OPTARG#*=} ;; exec-prefix=*) exec_prefix_flag=1 exec_prefix=${OPTARG#*=} ;; libdir=*) libdir_flag=1 libdir=${OPTARG#*=} ;; includedir=*) includedir_flag=1 includedir=${OPTARG#*=} ;; sharedir=*) sharedir_flag=1 sharedir=${OPTARG#*=} ;; enable-debug) debug_flag=1 debug_type=noopt ;; enable-debug=*) debug_flag=1 debug_type=${OPTARG#*=} ;; disable-debug) debug_flag=0 ;; enable-verbose-make) enable_verbose='yes' ;; disable-verbose-make) enable_verbose='no' ;; enable-arg-max-hack) enable_arg_max_hack='yes' ;; disable-arg-max-hack) enable_arg_max_hack='no' ;; enable-static) enable_static='yes' ;; disable-static) enable_static='no' ;; enable-shared) enable_shared='yes' ;; disable-shared) enable_shared='no' ;; enable-rpath) enable_rpath='yes' ;; disable-rpath) enable_rpath='no' ;; export-shared=*) export_shared=${OPTARG#*=} ;; enable-system) enable_system='yes' ;; disable-system) enable_system='no' ;; enable-threading=*) threading_model=${OPTARG#*=} ;; disable-threading) threading_model='off' ;; thread-part-jrir=*) thread_part_jrir=${OPTARG#*=} ;; enable-pba-pools) enable_pba_pools='yes' ;; disable-pba-pools) enable_pba_pools='no' ;; enable-sba-pools) enable_sba_pools='yes' ;; disable-sba-pools) enable_sba_pools='no' ;; enable-mem-tracing) enable_mem_tracing='yes' ;; disable-mem-tracing) enable_mem_tracing='no' ;; enable-addon=*) addon_flag=1 addon_name=${OPTARG#*=} # Append the addon name to the list. addon_list="${addon_list} ${addon_name}" ;; disable-addon) addon_flag='' ;; enable-sandbox=*) sandbox_flag=1 sandbox=${OPTARG#*=} ;; disable-sandbox) sandbox_flag='' ;; int-size=*) int_type_size=${OPTARG#*=} ;; blas-int-size=*) blas_int_type_size=${OPTARG#*=} ;; enable-blas) enable_blas='yes' ;; disable-blas) enable_blas='no' ;; enable-cblas) enable_cblas='yes' ;; disable-cblas) enable_cblas='no' ;; enable-mixed-dt) enable_mixed_dt='yes' ;; disable-mixed-dt) enable_mixed_dt='no' ;; enable-mixed-dt-extra-mem) enable_mixed_dt_extra_mem='yes' ;; disable-mixed-dt-extra-mem) enable_mixed_dt_extra_mem='no' ;; enable-sup-handling) enable_sup_handling='yes' ;; disable-sup-handling) enable_sup_handling='no' ;; enable-amd-frame-tweaks) enable_amd_frame_tweaks='yes' ;; disable-amd-frame-tweaks) enable_amd_frame_tweaks='no' ;; with-memkind) enable_memkind='yes' ;; without-memkind) enable_memkind='no' ;; enable-trsm-preinversion) enable_trsm_preinversion='yes' ;; disable-trsm-preinversion) enable_trsm_preinversion='no' ;; force-version=*) force_version=${OPTARG#*=} ;; show-config-list) show_config_list=1 ;; complex-return=*) complex_return=${OPTARG#*=} ;; *) print_usage ;; esac;; h) print_usage ;; p) prefix_flag=1 prefix=$OPTARG ;; d) debug_flag=1 debug_type=$OPTARG ;; e) export_shared=$OPTARG ;; a) addon_flag=1 addon_name=$OPTARG # Append the addon name to the list. addon_list="${addon_list} ${addon_name}" ;; s) sandbox_flag=1 sandbox=$OPTARG ;; q) quiet_flag=1 ;; t) threading_model=$OPTARG ;; r) thread_part_jrir=$OPTARG ;; i) int_type_size=$OPTARG ;; b) blas_int_type_size=$OPTARG ;; c) show_config_list=1 ;; \?) print_usage ;; esac done shift $(($OPTIND - 1)) # Parse environment variables found=false while [ $# -gt 0 ]; do case $1 in *=*) var=`expr "$1" : '\([^=]*\)='` value=`expr "$1" : '[^=]*=\(.*\)'` eval $var=\$value export $var shift found=true ;; *) break ;; esac done done # -- Check the operating system -------------------------------------------- os_name=$(uname -s) os_vers=$(uname -r) echo "${script_name}: detected ${os_name} kernel version ${os_vers}." # Define a single variable off of which we can branch to tell if we are # building for Windows. is_win=no if [[ $os_name == MSYS* ]] || \ [[ $os_name == MINGW* ]] || \ [[ $os_name == CYGWIN* ]] ; then is_win=yes fi # -- Find a python interpreter --------------------------------------------- # Acquire the default python search order. python_search_list=$(get_python_search_list) # Select a python interpreter from the default list, or from PYTHON if it # refers to a valid binary. select_tool_w_env "${python_search_list}" "${PYTHON}" "PYTHON" \ "python interpreter" "yes" found_python # -- Check the python version ---------------------------------------------- # Check the python interpreter's version. get_python_version check_python # -- Find a C compiler ----------------------------------------------------- # Acquire the default compiler search order. This will vary based on os_name. cc_search_list=$(get_cc_search_list) # Select a C compiler from the default list, or from CC if it refers to a # valid binary. select_tool_w_env "${cc_search_list}" "${CC}" "CC" \ "C compiler" "yes" found_cc # Also check the compiler to see if we are (cross-)compiling for Windows if ${found_cc} -dM -E - < /dev/null 2> /dev/null | grep -q _WIN32; then is_win=yes fi # -- Check the compiler version -------------------------------------------- # Initialize the blacklist to empty. blacklist_init # Check the compiler's version. Certain versions of certain compilers # will preclude building certain sub-configurations, which are added # to a blacklist. We also make note of certain version ranges that # will be useful to know about later. get_compiler_version check_compiler check_compiler_version_ranges # Now check the assembler's ability to assemble code. Older versions # of binutils may not be aware of certain instruction sets. Those # sub-configurations employing kernels that use such instruction sets # will also be blacklisted. get_binutils_version check_assembler # Remove duplicates and whitespace from the blacklist. blacklist_cleanup if [ -n "${config_blist}" ]; then echo "${script_name}: configuration blacklist:" echo "${script_name}: ${config_blist}" fi # -- Find a C++ compiler --------------------------------------------------- # Acquire the default C++ compiler search order. This will vary based on # os_name. cxx_search_list=$(get_cxx_search_list) # Select a C compiler from the default list, or from CC if it refers to a # valid binary. select_tool_w_env "${cxx_search_list}" "${CXX}" "CXX" \ "C++ compiler" "no" found_cxx # -- Find a Fortran compiler ----------------------------------------------- # Acquire the default Fortran compiler search order. fc_search_list=$(get_fc_search_list) # Select a Fortran compiler from the default list, or from FC if it refers # to a valid binary. # NOTE: A Fortran compiler is not necessary for building BLIS. The only # reason we might want to query it is to detect the style of returning # complex values from functions. The 'gnu' style returns complex values # from functions normally, via the C language return statement, while the # 'intel' style returns them in a "hidden" parameter (inserted by the # compiler) that precedes all other function parameters. select_tool_w_env "${fc_search_list}" "${FC}" "FC" \ "Fortran compiler" "no" found_fc # -- Find a static library archiver ---------------------------------------- # Acquire the default archiver search order. ar_search_list=$(get_ar_search_list) # Select an archiver from the default list, or from AR if it refers # to a valid binary. select_tool_w_env "${ar_search_list}" "${AR}" "AR" \ "library archiver" "yes" found_ar # -- Find an archive indexer ----------------------------------------------- # Acquire the default archive indexer search order. ranlib_search_list=$(get_ranlib_search_list) # Select an archive indexer from the default list, or from RANLIB if it # refers to a valid binary. select_tool_w_env "${ranlib_search_list}" "${RANLIB}" "RANLIB" \ "archive indexer" "yes" found_ranlib # -- Read the configuration registry --------------------------------------- # Make sure the config registry file exists and can be opened. if [ ! -f "${registry_filepath}" ]; then echo "${script_name}: could not open '${registry_file}' file; cannot continue." echo "${script_name}: BLIS distribution appears to be incomplete." echo "${script_name}: *** Please verify source distribution." exit 1 fi # Read the registered configuration names and lists into associative # arrays. echo -n "${script_name}: reading configuration registry..." read_registry_file ${registry_filepath} echo "done." # Report if additional configurations needed to be blacklisted. # NOTE: This branch should never execute so long as indirect blacklisting # is disabled. See comment regarding issue #214 in the definition of # pass_config_kernel_registries(). if [ -n "${indirect_blist}" ]; then echo "${script_name}: needed to indirectly blacklist additional configurations:" echo "${script_name}: ${indirect_blist}" fi # -- Acquire the BLIS version ---------------------------------------------- # Set the 'version' variable to the default value (the 'git describe' # augmented instance of whatever is in the 'version' file if this is a git # clone, or whatever is in the 'version' file unmodified if it is a bare # source release). set_default_version "${version_filepath}" # Initial message. echo "${script_name}: starting configuration of BLIS ${version}." # Check if the user requested a custom version string. if [ "x${force_version}" = "xno" ]; then echo "${script_name}: configuring with official version string." else echo "${script_name}: configuring with custom version string '${force_version}'." version="${force_version}" fi # -- Acquire the shared library (.so) versions ----------------------------- # The first line of the 'so_version' file contains the .so major version. so_version_major=$(cat ${so_version_filepath} | sed -n "1p") # The second line contains the minor and build .so version numbers # (separated by a '.'). so_version_minorbuild=$(cat ${so_version_filepath} | sed -n "2p") echo "${script_name}: found shared library .so version '${so_version_major}.${so_version_minorbuild}'." echo "${script_name}: .so major version: ${so_version_major}" echo "${script_name}: .so minor.build version: ${so_version_minorbuild}" # -- Various pre-configuration checks -------------------------------------- # Set config_name based on the number of arguments leftover (after command # line option processing). if [ $# = "0" ]; then #configs_avail="auto "$(ls ${config_dirpath}) echo "${script_name}: " echo "${script_name}: *** No configuration given! ***" echo "${script_name}: " echo "${script_name}: Default configuration behavior is not implemented (for your" echo "${script_name}: own safety). Please re-run '${script_name}' and specify one" echo "${script_name}: of the existing configurations in the source distribution's" echo "${script_name} '${registry_file}' file:" echo "${script_name}: " #for k in "${!config_registry[@]}"; do for cr_var in ${!config_registry_*}; do #v=${config_registry[$k]} k=${cr_var##config_registry_}; v=${!cr_var} echo "${script_name}: $k (${v})" done echo "${script_name}: " exit 1 elif [ $# != "1" ]; then # more than one configuration argument given. print_usage fi if [ $1 = "auto" ]; then echo "${script_name}: automatic configuration requested." # Call the auto_detect() function and save the returned string in # config_name. config_name=$(auto_detect) # Debugging stuff. When confirming the behavior of auto_detect(), # it is useful to output ${config_name}, which in theory could be # set temoprarily to something other than the config_name, such as # the compilation command. if [ "${debug_auto_detect}" = "yes" ]; then echo "auto-detect program compilation command: ${config_name}" exit 1 fi echo "${script_name}: hardware detection driver returned '${config_name}'." # If the auto-detect code returned the "generic" string, it means we # were unable to automatically detect the user's hardware type. While # this is going to be a rare event, it will likely lead the user to # experience much lower performance than expected, and thus we will # warn them about it at the end of the configure output (to increase # the chances that they see it). if [ "${config_name}" = "generic" ]; then warn_user_generic=1 else warn_user_generic=0 fi else # Use the command line argument as the configuration name. config_name=$1 echo "${script_name}: manual configuration requested; configuring with '${config_name}'." fi # Use the selected config name to look up the list of configurations # and kernels associated with that name. #config_list=${config_registry[${config_name}]} #kernel_list=${kernel_registry[${config_name}]} config_list=$(query_array "config_registry" ${config_name}) kernel_list=$(query_array "kernel_registry" ${config_name}) # Use the config_registry and kernel_registry to build a kconfig_registry # for the selected config_name. build_kconfig_registry "${config_name}" # Print the configuration list and kernel list, if requested. if [ "${show_config_list}" == "1" ]; then echo "${script_name}: configuration list:" #for k in "${!config_registry[@]}"; do for cr_var in ${!config_registry_*}; do #v=${config_registry[$k]} k=${cr_var##config_registry_}; v=${!cr_var} echo "${script_name}: $k: ${v}" done echo "${script_name}: kernel list:" #for k in "${!kernel_registry[@]}"; do for kr_var in ${!kernel_registry_*}; do #v=${kernel_registry[$k]} k=${kr_var##kernel_registry_}; v=${!kr_var} echo "${script_name}: $k: ${v}" done echo "${script_name}: kernel-to-config map for '${config_name}':" #for k in "${!kconfig_registry[@]}"; do for kc_var in ${!kconfig_registry_*}; do #v=${kconfig_registry[$k]} k=${kc_var##kconfig_registry_}; v=${!kc_var} echo "${script_name}: $k: ${v}" done fi # For each kernel in the kernel list, reduce the list of associated # sub-configurations (in the kconfig_registry) to a singleton using # the following rules: # 1. If the list is a singleton, use that name. # 2. If the list contains a sub-configuration name that matches the # kernel name, use that name. # 3. Otherwise, use the first name in the list. # We use the chosen singleton to ceate a "kernel:subconfig" pair, which # we accumulate into a list. This list is the kernel-to-config map, or # kconfig_map. # We use a sorted version of kernel_list so that it ends up matching the # display order of the kconfig_registry above. kernel_list_sort=$(echo ${kernel_list} | xargs -n1 | sort -u) kconfig_map="" for kernel in ${kernel_list_sort}; do #configs="${kconfig_registry[$kernel]}" configs=$(query_array "kconfig_registry" ${kernel}) has_one_kernel=$(is_singleton "${configs}") contains_kernel=$(is_in_list "${kernel}" "${configs}") # Check if the list is a singleton. if [ "${has_one_kernel}" == "true" ]; then reducedclist="${configs}" # Check if the list contains a sub-config name that matches the kernel. elif [ "${contains_kernel}" == "true" ]; then reducedclist="${kernel}" # Otherwise, use the last name. else last_config=${configs##* } reducedclist="${last_config}" fi # Create a new "kernel:subconfig" pair and add it to the kconfig_map # list, removing whitespace. new_pair="${kernel}:${reducedclist}" kconfig_map=$(canonicalize_ws "${kconfig_map} ${new_pair}") done if [ "${show_config_list}" == "1" ]; then echo "${script_name}: kernel-to-config map for '${config_name}' (chosen pairs):" for k in ${kconfig_map}; do echo "${script_name}: $k" done fi echo "${script_name}: checking configuration against contents of '${registry_file}'." # First, ensure that the config name is registered (ie: it is present # in the config_registry file). if [ -z "${config_list}" ]; then # NOTE: This branch should never execute when using auto-detection, # but we have it here just in case. if [ $1 = "auto" ]; then echo "${script_name}: 'auto-detected configuration '${config_name}' is NOT registered!" echo "${script_name}: " echo "${script_name}: *** Cannot continue with unregistered configuration '${config_name}'. ***" echo "${script_name}: " exit 1; else # At this point, we know: (a) config_list is empty; and (b) the user # requested manual configuration. If the config_name given by the # user is present in the configuration blacklist (config_blist), # then we can deduce why the config_list is empty: because the only # subconfig implied by config_name is blacklisted. Thus, we cannot # proceed. if [ $(is_in_list "${config_name}" "${config_blist}") == "true" ]; then echo "${script_name}: 'user-specified configuration '${config_name}' is blacklisted!" echo "${script_name}: " echo "${script_name}: *** Cannot continue with blacklisted configuration '${config_name}'. ***" echo "${script_name}: *** Try updating your compiler and/or assembler (binutils) versions. ***" echo "${script_name}: " exit 1; else # If config_name is NOT present in config_blist, then we know # that config_list is empty simply because config_name is # unregistered. echo "${script_name}: 'user-specified configuration '${config_name}' is NOT registered!" echo "${script_name}: " echo "${script_name}: *** Cannot continue with unregistered configuration '${config_name}'. ***" echo "${script_name}: " exit 1; fi fi else # This branch executes when the configuration is found to be present # (i.e. registered) in the config_registry file. echo "${script_name}: configuration '${config_name}' is registered." echo "${script_name}: '${config_name}' is defined as having the following sub-configurations:" echo "${script_name}: ${config_list}" echo "${script_name}: which collectively require the following kernels:" echo "${script_name}: ${kernel_list}" fi echo "${script_name}: checking sub-configurations:" # Now, verify that the constituent configurations associated with the # config name are all valid. for conf in ${config_list}; do # First confirm that the current configuration is registered. #this_clist=${config_registry[${conf}]} this_clist=$(query_array "config_registry" ${conf}) # If the config_list associated with conf is empty, then it was # never entered into the config_registry to begin with. Thus, # conf must be unregistered. if [ -z "${this_clist}" ]; then echo "${script_name}: '${conf}' is NOT registered!" echo "${script_name}: " echo "${script_name}: *** Cannot continue with unregistered configuration '${conf}'. ***" echo "${script_name}: " exit 1; else echo -n "${script_name}: '${conf}' is registered." fi # Then confirm that the current sub-configuration directory exists. if [ ! -d "${config_dirpath}/${conf}" ]; then echo "..but does NOT exist!" echo "${script_name}: " echo "${script_name}: *** Cannot continue with nonexistent configuration '${conf}'. ***" echo "${script_name}: " exit 1; else echo "..and exists." fi done echo "${script_name}: checking sub-configurations' requisite kernels:" # Also, let's verify that the requisite kernel sets associated with # the config name all correspond to directories that exist. for kernel in ${kernel_list}; do echo -n "${script_name}: '${kernel}' kernels..." # Confirm that the current kernel sub-directory exists. if [ ! -d "${kernels_dirpath}/${kernel}" ]; then echo "do NOT exist!" echo "${script_name}: " echo "${script_name}: *** Cannot continue with nonexistent kernel '${kernel}'. ***" echo "${script_name}: " exit 1; else echo "exist." fi done # In order to determine the default behavior of the --with[out]-memkind # option, we try to detect whether libmemkind is available. If it is, # the default implied option will be --with-memkind; otherwise, will be # --without-memkind. has_memkind=$(has_libmemkind) # Try to determine whether the chosen compiler supports #pragma omp simd. pragma_omp_simd=$(has_pragma_omp_simd) # -- Prepare variables for subsitution into template files ----------------- # Parse the status of the prefix option and echo feedback. if [ -n "${prefix_flag}" ]; then echo "${script_name}: detected --prefix='${prefix}'." else echo "${script_name}: no install prefix option given; defaulting to '${prefix}'." fi # Parse the status of the exec_prefix option and echo feedback. if [ -n "${exec_prefix_flag}" ]; then echo "${script_name}: detected --exec-prefix='${exec_prefix}'." else echo "${script_name}: no install exec_prefix option given; defaulting to PREFIX." fi # Parse the status of the libdir option and echo feedback. if [ -n "${libdir_flag}" ]; then echo "${script_name}: detected --libdir='${libdir}'." else echo "${script_name}: no install libdir option given; defaulting to EXECPREFIX/lib." fi # Parse the status of the includedir option and echo feedback. if [ -n "${includedir_flag}" ]; then echo "${script_name}: detected --includedir='${includedir}'." else echo "${script_name}: no install includedir option given; defaulting to PREFIX/include." fi # Parse the status of the sharedir option and echo feedback. if [ -n "${sharedir_flag}" ]; then echo "${script_name}: detected --sharedir='${sharedir}'." else echo "${script_name}: no install sharedir option given; defaulting to PREFIX/share." fi # Echo the installation directories that we settled on. echo "${script_name}: final installation directories:" echo "${script_name}: prefix: "${prefix} echo "${script_name}: exec_prefix: "${exec_prefix} echo "${script_name}: libdir: "${libdir} echo "${script_name}: includedir: "${includedir} echo "${script_name}: sharedir: "${sharedir} echo "${script_name}: NOTE: the variables above can be overridden when running make." # Check if CFLAGS is non-empty. if [ -n "${CFLAGS}" ]; then cflags_preset="${CFLAGS}" echo "${script_name}: detected preset CFLAGS; prepending:" echo "${script_name}: ${cflags_preset}" else cflags_preset='' echo "${script_name}: no preset CFLAGS detected." fi # Check if LDFLAGS is non-empty. if [ -n "${LDFLAGS}" ]; then ldflags_preset="${LDFLAGS}" echo "${script_name}: detected preset LDFLAGS; prepending:" echo "${script_name}: ${ldflags_preset}" else ldflags_preset='' echo "${script_name}: no preset LDFLAGS detected." fi # Check if the debug flag was specified. if [ -n "${debug_flag}" ]; then if [ "x${debug_type}" = "xopt" ]; then echo "${script_name}: enabling debug symbols with optimizations." elif [ "x${debug_type}" = "xsde" ]; then debug_type='sde' echo "${script_name}: enabling SDE processor emulation." else debug_type='noopt' echo "${script_name}: enabling debug symbols; optimizations disabled." fi else debug_type='off' echo "${script_name}: debug symbols disabled." fi # Check if the verbose make flag was specified. if [ "x${enable_verbose}" = "xyes" ]; then echo "${script_name}: enabling verbose make output. (disable with 'make V=0'.)" else echo "${script_name}: disabling verbose make output. (enable with 'make V=1'.)" fi # Check if the ARG_MAX hack was requested. if [ "x${enable_arg_max_hack}" = "xyes" ]; then echo "${script_name}: enabling ARG_MAX hack." else echo "${script_name}: disabling ARG_MAX hack." fi enable_shared_01=1 # Check if the static lib flag was specified. if [ "x${enable_static}" = "xyes" -a "x${enable_shared}" = "xyes" ]; then echo "${script_name}: building BLIS as both static and shared libraries." elif [ "x${enable_static}" = "xyes" -a "x${enable_shared}" = "xno" ]; then echo "${script_name}: building BLIS as a static library (shared library disabled)." enable_shared_01=0 elif [ "x${enable_static}" = "xno" -a "x${enable_shared}" = "xyes" ]; then echo "${script_name}: building BLIS as a shared library (static library disabled)." else echo "${script_name}: Both static and shared libraries were disabled." echo "${script_name}: *** Please enable one (or both) to continue." exit 1 fi # Check if the "export shared" flag was specified. if [ "x${export_shared}" = "xall" ]; then if [ "x${enable_shared}" = "xyes" ]; then echo "${script_name}: exporting all symbols within shared library." else echo "${script_name}: ignoring request to export all symbols within shared library." fi elif [ "x${export_shared}" = "xpublic" ]; then if [ "x${enable_shared}" = "xyes" ]; then echo "${script_name}: exporting only public symbols within shared library." fi else echo "${script_name}: *** Invalid argument '${export_shared}' to --export-shared option given." echo "${script_name}: *** Please use 'public' or 'all'." exit 1 fi # Check if we are building with or without operating system support. if [ "x${enable_system}" = "xyes" ]; then echo "${script_name}: enabling operating system support." enable_system_01=1 else echo "${script_name}: disabling operating system support." echo "${script_name}: WARNING: all threading will be disabled!" enable_system_01=0 # Force threading to be disabled. threading_model='off' fi # Check the threading model flag and standardize its value, if needed. # NOTE: 'omp' is deprecated but still supported; 'openmp' is preferred. enable_openmp='no' enable_openmp_01=0 enable_pthreads='no' enable_pthreads_01=0 if [ "x${threading_model}" = "xauto" ]; then echo "${script_name}: determining the threading model automatically." elif [ "x${threading_model}" = "xopenmp" ] || [ "x${threading_model}" = "xomp" ]; then echo "${script_name}: using OpenMP for threading." enable_openmp='yes' enable_openmp_01=1 threading_model="openmp" # Standardize the value. elif [ "x${threading_model}" = "xpthreads" ] || [ "x${threading_model}" = "xpthread" ] || [ "x${threading_model}" = "xposix" ]; then echo "${script_name}: using POSIX threads for threading." enable_pthreads='yes' enable_pthreads_01=1 threading_model="pthreads" # Standardize the value. elif [ "x${threading_model}" = "xoff" ] || [ "x${threading_model}" = "xno" ] || [ "x${threading_model}" = "xnone" ]; then echo "${script_name}: threading is disabled." threading_model="off" else echo "${script_name}: *** Unsupported threading model: ${threading_model}." exit 1 fi # Check the method of assigning micropanels to threads in the JR and IR # loops. enable_jrir_slab_01=0 enable_jrir_rr_01=0 if [ "x${thread_part_jrir}" = "xslab" ]; then echo "${script_name}: requesting slab threading in jr and ir loops." enable_jrir_slab_01=1 elif [ "x${thread_part_jrir}" = "xrr" ]; then echo "${script_name}: requesting round-robin threading in jr and ir loops." enable_jrir_rr_01=1 else echo "${script_name}: *** Unsupported method of thread partitioning in jr and ir loops: ${threading_model}." exit 1 fi # Convert 'yes' and 'no' flags to booleans. if [ "x${enable_pba_pools}" = "xyes" ]; then echo "${script_name}: internal memory pools for packing blocks are enabled." enable_pba_pools_01=1 else echo "${script_name}: internal memory pools for packing blocks are disabled." enable_pba_pools_01=0 fi if [ "x${enable_sba_pools}" = "xyes" ]; then echo "${script_name}: internal memory pools for small blocks are enabled." enable_sba_pools_01=1 else echo "${script_name}: internal memory pools for small blocks are disabled." enable_sba_pools_01=0 fi if [ "x${enable_mem_tracing}" = "xyes" ]; then echo "${script_name}: memory tracing output is enabled." enable_mem_tracing_01=1 else echo "${script_name}: memory tracing output is disabled." enable_mem_tracing_01=0 fi if [ "x${has_memkind}" = "xyes" ]; then if [ "x${enable_memkind}" = "x" ]; then # If no explicit option was given for libmemkind one way or the other, # we use the value returned previously by has_libmemkind(), in this # case "yes", to determine the default. echo "${script_name}: libmemkind found; default is to enable use." enable_memkind="yes" enable_memkind_01=1 else if [ "x${enable_memkind}" = "xyes" ]; then echo "${script_name}: received explicit request to enable libmemkind." enable_memkind="yes" enable_memkind_01=1 else echo "${script_name}: received explicit request to disable libmemkind." enable_memkind="no" enable_memkind_01=0 fi fi else echo "${script_name}: libmemkind not found; disabling." if [ "x${enable_memkind}" = "xyes" ]; then echo "${script_name}: cannot honor explicit request to enable libmemkind." fi enable_memkind="no" enable_memkind_01=0 fi if [ "x${pragma_omp_simd}" = "xyes" ]; then echo "${script_name}: compiler appears to support #pragma omp simd." enable_pragma_omp_simd_01=1 else echo "${script_name}: compiler appears to not support #pragma omp simd." enable_pragma_omp_simd_01=0 fi if [ "x${enable_blas}" = "xyes" ]; then echo "${script_name}: the BLAS compatibility layer is enabled." enable_blas_01=1 else echo "${script_name}: the BLAS compatibility layer is disabled." enable_blas_01=0 fi if [ "x${enable_cblas}" = "xyes" ]; then echo "${script_name}: the CBLAS compatibility layer is enabled." enable_cblas_01=1 # Force BLAS layer when CBLAS is enabled enable_blas='yes' else echo "${script_name}: the CBLAS compatibility layer is disabled." enable_cblas_01=0 fi if [ "x${enable_mixed_dt}" = "xyes" ]; then echo "${script_name}: mixed datatype support is enabled." if [ "x${enable_mixed_dt_extra_mem}" = "xyes" ]; then echo "${script_name}: mixed datatype optimizations requiring extra memory are enabled." enable_mixed_dt_extra_mem_01=1 else echo "${script_name}: mixed datatype optimizations requiring extra memory are disabled." enable_mixed_dt_extra_mem_01=0 fi enable_mixed_dt_01=1 else echo "${script_name}: mixed datatype support is disabled." enable_mixed_dt_extra_mem_01=0 enable_mixed_dt_01=0 fi if [ "x${enable_sup_handling}" = "xyes" ]; then echo "${script_name}: small matrix handling is enabled." enable_sup_handling_01=1 else echo "${script_name}: small matrix handling is disabled." enable_sup_handling_01=0 fi if [ "x${enable_trsm_preinversion}" = "xyes" ]; then echo "${script_name}: trsm diagonal element pre-inversion is enabled." enable_trsm_preinversion_01=1 else echo "${script_name}: trsm diagonal element pre-inversion is disabled." enable_trsm_preinversion_01=0 fi # Report integer sizes. if [ "x${int_type_size}" = "x32" ]; then echo "${script_name}: the BLIS API integer size is 32-bit." elif [ "x${int_type_size}" = "x64" ]; then echo "${script_name}: the BLIS API integer size is 64-bit." else echo "${script_name}: the BLIS API integer size is automatically determined." fi if [ "x${blas_int_type_size}" = "x32" ]; then echo "${script_name}: the BLAS/CBLAS API integer size is 32-bit." elif [ "x${blas_int_type_size}" = "x64" ]; then echo "${script_name}: the BLAS/CBLAS API integer size is 64-bit." else echo "${script_name}: the BLAS/CBLAS API integer size is automatically determined." fi # Disallow the simultaneous use of 64-bit integers in the BLAS and # 32-bit integers in BLIS. if [ "x${blas_int_type_size}" = "x64" -a "x${int_type_size}" = "x32" ]; then echo "${script_name}: *** To avoid the possibility of truncation, we do not allow use of 64-bit integers in the BLAS API with 32-bit integers in BLIS. Please use a different configuration of integers." exit 1 fi # Check whether we should use AMD-customized versions of certain framework # files. if [ "x${enable_amd_frame_tweaks}" = "xyes" ]; then echo "${script_name}: AMD-specific framework files will be considered." echo "${script_name}: checking eligibility of target configuration." # Make sure we are targeting either one of the zen subconfigs or the # amd64 umbrella family. uconf=$(echo ${config_name} | grep -c 'zen\|amd64') if [[ $uconf == 0 ]]; then echo "${script_name}: target configuration '${config_name}' is not eligible." echo "${script_name}: disabling AMD-specific framework files." enable_amd_frame_tweaks='no' else echo "${script_name}: target configuration '${config_name}' is eligible." echo "${script_name}: enabling AMD-specific framework files." fi else echo "${script_name}: AMD-specific framework files will not be considered." fi # Check if addons were given. if [ -n "${addon_flag}" ]; then # Remove duplicates in the addon list, if they exist. addon_list=$(rm_duplicate_words_simple "${addon_list}") echo "${script_name}: configuring with addons:" for addon in ${addon_list}; do echo "${script_name}: ${addon_dir}/${addon}" addon_fullpath="${addon_dirpath}/${addon}" if [ ! -d "${addon_fullpath}" ]; then echo "${script_name}: requested addon sub-directory does not exist! Cannot continue." echo "${script_name}: *** Please verify addon existence and name." exit 1 fi done enable_addons_01=1 else echo "${script_name}: configuring with no addons." enable_addons_01=0 fi # Check if a sandbox was given. if [ -n "${sandbox_flag}" ]; then #sandbox_relpath="${sandbox_dir}/${sandbox}" echo "${script_name}: configuring for alternate gemm implementation:" echo "${script_name}: ${sandbox_dir}/${sandbox}" sandbox_fullpath="${sandbox_dirpath}/${sandbox}" if [ ! -d "${sandbox_fullpath}" ]; then echo "${script_name}: requested sandbox sub-directory does not exist! Cannot continue." echo "${script_name}: *** Please verify sandbox existence and name." exit 1 fi enable_sandbox_01=1 else echo "${script_name}: configuring for conventional gemm implementation." enable_sandbox_01=0 fi # Check the method used for returning complex numbers. if [ "x${complex_return}" = "xdefault" ]; then # If we prevoiusly found a Fortran compiler, let's query it to see what # kind of complex return type it uses (gnu or intel). The 'gnu' style # returns complex values from functions normally, via the C language # return statement, while the 'intel' style returns them in a "hidden" # parameter (inserted by the compiler) that precedes all other function # parameters. if [ -n "${found_fc}" ]; then # Query the full vendor version string output. This includes the # version number along with (potentially) a bunch of other textual # clutter. # NOTE: This maybe should use merged stdout/stderr rather than only # stdout. But it works for now. vendor_string="$(${FC} --version 2>/dev/null)" # Query the compiler "vendor" (ie: the compiler's simple name). # The last part ({ read first rest ; echo $first ; }) is a workaround # to OS X's egrep only returning the first match. fc_vendor=$(echo "${vendor_string}" | egrep -o 'ifort|GNU' | { read first rest ; echo $first ; }) if [ "x${fc_vendor}" = "xifort" ]; then complex_return='intel' elif [ "x${fc_vendor}" = "xGNU" ]; then complex_return='gnu' else echo "${script_name}: unable to determine Fortran compiler vendor!" complex_return='gnu' fi else complex_return='gnu' fi fi if [ "x${complex_return}" = "xgnu" ]; then complex_return_intel01='0' elif [ "x${complex_return}" = "xintel" ]; then complex_return_intel01='1' else echo "${script_name}: unknown complex return type \"${complex_return}\"! Cannot continue." echo "${script_name}: *** Acceptable values are \"gnu\" and \"intel\"." exit 1 fi echo "${script_name}: configuring complex return type as \"${complex_return}\"." # Variables that may contain forward slashes, such as paths, need extra # escaping when used in sed commands. We insert those extra escape # characters here so that the sed commands below do the right thing. os_name_esc=$(echo "${os_name}" | sed 's/\//\\\//g') prefix_esc=$(echo "${prefix}" | sed 's/\//\\\//g') exec_prefix_esc=$(echo "${exec_prefix}" | sed 's/\//\\\//g') libdir_esc=$(echo "${libdir}" | sed 's/\//\\\//g') includedir_esc=$(echo "${includedir}" | sed 's/\//\\\//g') sharedir_esc=$(echo "${sharedir}" | sed 's/\//\\\//g') dist_path_esc=$(echo "${dist_path}" | sed 's/\//\\\//g') cc_esc=$(echo "${found_cc}" | sed 's/\//\\\//g') cxx_esc=$(echo "${found_cxx}" | sed 's/\//\\\//g') ar_esc=$(echo "${found_ar}" | sed 's/\//\\\//g') ranlib_esc=$(echo "${found_ranlib}" | sed 's/\//\\\//g') python_esc=$(echo "${found_python}" | sed 's/\//\\\//g') libpthread_esc=$(echo "${LIBPTHREAD--lpthread}" | sed 's/\//\\\//g') cflags_preset_esc=$(echo "${cflags_preset}" | sed 's/\//\\\//g') ldflags_preset_esc=$(echo "${ldflags_preset}" | sed 's/\//\\\//g') # For Windows builds, clear the libpthread_esc variable so that # no pthreads library is substituted into config.mk. (Windows builds # employ an implementation of pthreads that is internal to BLIS.) if [[ "$is_win" == "yes" && "$cc_vendor" == "clang" ]]; then libpthread_esc= fi # We also clear the libpthread_esc variable for systemless builds # (--disable-system). if [[ "$enable_system" == "no" ]]; then libpthread_esc= fi # Typically, there are no slashes in the version variable. However, # downstream maintainers (such as those for Debian) may create custom # tags in their local clones such as "upstream/0.4.1", which obviously # contain slashes. This line, and subsequent use of the escaped variable # for the version string, accommodates those use cases. version_esc=$(echo "${version}" | sed 's/\//\\\//g') # Create a #define for the configuration family (config_name). uconf=$(echo ${config_name} | tr '[:lower:]' '[:upper:]') config_name_define="#define BLIS_FAMILY_${uconf}\n" # Create a list of #defines, one for each configuration in config_list. config_list_defines="" for conf in ${config_list}; do # Convert the current config name to uppercase. uconf=$(echo ${conf} | tr '[:lower:]' '[:upper:]') # Create a #define and add it to the running list. config_define="BLIS_CONFIG_${uconf}" config_list_defines="${config_list_defines}#define ${config_define}\n" done # Create a list of #defines, one for each kernel set in kernel_list. kernel_list_defines="" for kern in ${kernel_list}; do # Convert the current config name to uppercase. uconf=$(echo ${kern} | tr '[:lower:]' '[:upper:]') # Create a #define and add it to the running list. kernel_define="BLIS_KERNELS_${uconf}" kernel_list_defines="${kernel_list_defines}#define ${kernel_define}\n" done # Create a list of #includes, one for each addon in addon_list. addon_list_includes="" for addon in ${addon_list}; do # Create a #define and add it to the running list. addon_header="\"${addon}.h\"" addon_list_includes="${addon_list_includes}#include ${addon_header}\n" done # -- Determine whether we are performing an out-of-tree build -------------- if [ "${dist_path}" != "./" ]; then # At this point, we know the user did not run "./configure". But we # have not yet ruled out "/configure" or some # equivalent # that uses relative paths. To further rule out these possibilities, # we create a dummy file in the current build directory. touch "./${dummy_file}" # If the dummy file we just created in the current directory does not # appear in the source distribution path, then we are in a different # directory and thus we must create a symbolic link. if [ ! -f "${dist_path}/${dummy_file}" ]; then configured_oot="yes" #echo "${script_name}: detected out-of-tree build directory." else configured_oot="no" #echo "${script_name}: detected in-tree build directory." fi # Remove the dummy file. rm -f "./${dummy_file}" fi # -- Instantiate config.mk file from template ------------------------------ # Begin substituting information into the config_mk_in file, outputting # to config_mk_out. echo "${script_name}: creating ${config_mk_out_path} from ${config_mk_in_path}" cat "${config_mk_in_path}" \ | sed -e "s/@version@/${version_esc}/g" \ | sed -e "s/@so_version_major@/${so_version_major}/g" \ | sed -e "s/@so_version_minorbuild@/${so_version_minorbuild}/g" \ | sed -e "s/@config_name@/${config_name}/g" \ | sed -e "s/@config_list@/${config_list}/g" \ | sed -e "s/@kernel_list@/${kernel_list}/g" \ | sed -e "s/@kconfig_map@/${kconfig_map}/g" \ | sed -e "s/@os_name@/${os_name_esc}/g" \ | sed -e "s/@is_win@/${is_win}/g" \ | sed -e "s/@dist_path@/${dist_path_esc}/g" \ | sed -e "s/@CC_VENDOR@/${cc_vendor}/g" \ | sed -e "s/@gcc_older_than_4_9_0@/${gcc_older_than_4_9_0}/g" \ | sed -e "s/@gcc_older_than_6_1_0@/${gcc_older_than_6_1_0}/g" \ | sed -e "s/@gcc_older_than_9_1_0@/${gcc_older_than_9_1_0}/g" \ | sed -e "s/@gcc_older_than_10_1_0@/${gcc_older_than_10_1_0}/g" \ | sed -e "s/@clang_older_than_9_0_0@/${clang_older_than_9_0_0}/g" \ | sed -e "s/@clang_older_than_12_0_0@/${clang_older_than_12_0_0}/g" \ | sed -e "s/@aocc_older_than_2_0_0@/${aocc_older_than_2_0_0}/g" \ | sed -e "s/@aocc_older_than_3_0_0@/${aocc_older_than_3_0_0}/g" \ | sed -e "s/@CC@/${cc_esc}/g" \ | sed -e "s/@CXX@/${cxx_esc}/g" \ | sed -e "s/@AR@/${ar_esc}/g" \ | sed -e "s/@RANLIB@/${ranlib_esc}/g" \ | sed -e "s/@PYTHON@/${python_esc}/g" \ | sed -e "s/@libpthread@/${libpthread_esc}/g" \ | sed -e "s/@cflags_preset@/${cflags_preset_esc}/g" \ | sed -e "s/@ldflags_preset@/${ldflags_preset_esc}/g" \ | sed -e "s/@debug_type@/${debug_type}/g" \ | sed -e "s/@enable_system@/${enable_system}/g" \ | sed -e "s/@threading_model@/${threading_model}/g" \ | sed -e "s/@prefix@/${prefix_esc}/g" \ | sed -e "s/@exec_prefix@/${exec_prefix_esc}/g" \ | sed -e "s/@libdir@/${libdir_esc}/g" \ | sed -e "s/@includedir@/${includedir_esc}/g" \ | sed -e "s/@sharedir@/${sharedir_esc}/g" \ | sed -e "s/@enable_verbose@/${enable_verbose}/g" \ | sed -e "s/@configured_oot@/${configured_oot}/g" \ | sed -e "s/@enable_arg_max_hack@/${enable_arg_max_hack}/g" \ | sed -e "s/@enable_static@/${enable_static}/g" \ | sed -e "s/@enable_shared@/${enable_shared}/g" \ | sed -e "s/@enable_rpath@/${enable_rpath}/g" \ | sed -e "s/@export_shared@/${export_shared}/g" \ | sed -e "s/@enable_blas@/${enable_blas}/g" \ | sed -e "s/@enable_cblas@/${enable_cblas}/g" \ | sed -e "s/@enable_amd_frame_tweaks@/${enable_amd_frame_tweaks}/g" \ | sed -e "s/@enable_memkind@/${enable_memkind}/g" \ | sed -e "s/@pragma_omp_simd@/${pragma_omp_simd}/g" \ | sed -e "s/@addon_list@/${addon_list}/g" \ | sed -e "s/@sandbox@/${sandbox}/g" \ > "${config_mk_out_path}" # -- Instantiate bli_config.h file from template --------------------------- # Begin substituting information into the bli_config_h_in file, outputting # to bli_config_h_out. NOTE: We use perl instead of sed because the version # of sed used on OS X is old and does not handle the '\n' character # intuitively, which was used when constructing ${config_name_define}, # ${config_list_defines}, and ${kernel_list_defines}. echo "${script_name}: creating ${bli_config_h_out_path} from ${bli_config_h_in_path}" cat "${bli_config_h_in_path}" \ | perl -pe "s/\@config_name_define\@/${config_name_define}/g" \ | perl -pe "s/\@config_list_defines\@/${config_list_defines}/g" \ | perl -pe "s/\@kernel_list_defines\@/${kernel_list_defines}/g" \ | sed -e "s/@enable_system@/${enable_system_01}/g" \ | sed -e "s/@enable_openmp@/${enable_openmp_01}/g" \ | sed -e "s/@enable_pthreads@/${enable_pthreads_01}/g" \ | sed -e "s/@enable_jrir_slab@/${enable_jrir_slab_01}/g" \ | sed -e "s/@enable_jrir_rr@/${enable_jrir_rr_01}/g" \ | sed -e "s/@enable_pba_pools@/${enable_pba_pools_01}/g" \ | sed -e "s/@enable_sba_pools@/${enable_sba_pools_01}/g" \ | sed -e "s/@enable_mem_tracing@/${enable_mem_tracing_01}/g" \ | sed -e "s/@int_type_size@/${int_type_size}/g" \ | sed -e "s/@blas_int_type_size@/${blas_int_type_size}/g" \ | sed -e "s/@enable_blas@/${enable_blas_01}/g" \ | sed -e "s/@enable_cblas@/${enable_cblas_01}/g" \ | sed -e "s/@enable_mixed_dt@/${enable_mixed_dt_01}/g" \ | sed -e "s/@enable_mixed_dt_extra_mem@/${enable_mixed_dt_extra_mem_01}/g" \ | sed -e "s/@enable_sup_handling@/${enable_sup_handling_01}/g" \ | sed -e "s/@enable_memkind@/${enable_memkind_01}/g" \ | sed -e "s/@enable_trsm_preinversion@/${enable_trsm_preinversion_01}/g" \ | sed -e "s/@enable_pragma_omp_simd@/${enable_pragma_omp_simd_01}/g" \ | sed -e "s/@enable_sandbox@/${enable_sandbox_01}/g" \ | sed -e "s/@enable_shared@/${enable_shared_01}/g" \ | sed -e "s/@complex_return_intel@/${complex_return_intel01}/g" \ > "${bli_config_h_out_path}" # -- Instantiate bli_addon.h file from template ---------------------------- # Begin substituting information into the bli_addon_h_in file, outputting # to bli_addon_h_out. NOTE: We use perl instead of sed because the version # of sed used on OS X is old and does not handle the '\n' character # intuitively, which was used when constructing ${addon_list_includes}. echo "${script_name}: creating ${bli_addon_h_out_path} from ${bli_addon_h_in_path}" cat "${bli_addon_h_in_path}" \ | perl -pe "s/\@addon_list_includes\@/${addon_list_includes}/g" \ | sed -e "s/@enable_addons@/${enable_addons_01}/g" \ > "${bli_addon_h_out_path}" # -- Create top-level object directories ----------------------------------- # Create obj sub-directories (if they do not already exist). base_obj_dirpath="${obj_dirpath}/${config_name}" echo "${script_name}: creating ${base_obj_dirpath}" mkdir -p ${base_obj_dirpath} obj_config_dirpath="${base_obj_dirpath}/${config_dir}" mkdir -p ${obj_config_dirpath} for conf in ${config_list}; do echo "${script_name}: creating ${obj_config_dirpath}/${conf}" mkdir -p ${obj_config_dirpath}/${conf} done obj_kernels_dirpath="${base_obj_dirpath}/${kernels_dir}" mkdir -p ${obj_kernels_dirpath} for kern in ${kernel_list}; do echo "${script_name}: creating ${obj_kernels_dirpath}/${kern}" mkdir -p ${obj_kernels_dirpath}/${kern} done obj_refkern_dirpath="${base_obj_dirpath}/${refkern_dir}" mkdir -p ${obj_refkern_dirpath} for conf in ${config_list}; do echo "${script_name}: creating ${obj_refkern_dirpath}/${conf}" mkdir -p ${obj_refkern_dirpath}/${conf} done obj_frame_dirpath="${base_obj_dirpath}/${frame_dir}" echo "${script_name}: creating ${obj_frame_dirpath}" mkdir -p ${obj_frame_dirpath} if [ -n "${addon_flag}" ]; then obj_addon_dirpath="${base_obj_dirpath}/${addon_dir}" for addon in ${addon_list}; do echo "${script_name}: creating ${obj_addon_dirpath}/${addon}" mkdir -p ${obj_addon_dirpath}/${addon} done fi if [ -n "${sandbox_flag}" ]; then obj_sandbox_dirpath="${base_obj_dirpath}/${sandbox_dir}" echo "${script_name}: creating ${obj_sandbox_dirpath}/${sandbox}" mkdir -p ${obj_sandbox_dirpath}/${sandbox} fi obj_blastest_dirpath="${base_obj_dirpath}/${blastest_dir}" echo "${script_name}: creating ${obj_blastest_dirpath}" mkdir -p ${obj_blastest_dirpath} obj_testsuite_dirpath="${base_obj_dirpath}/${testsuite_dir}" echo "${script_name}: creating ${obj_testsuite_dirpath}" mkdir -p ${obj_testsuite_dirpath} # Create lib directory (if it does not already exist). base_lib_dirpath="${lib_dirpath}/${config_name}" echo "${script_name}: creating ${base_lib_dirpath}" mkdir -p ${base_lib_dirpath} # Create include directory (if it does not already exist). base_include_dirpath="${include_dirpath}/${config_name}" echo "${script_name}: creating ${base_include_dirpath}" mkdir -p ${base_include_dirpath} # -- Mirror source directory hierarchies to object directories ------------- # Combine the config_list with the config_name and then remove duplicates. config_list_plus_name=$(rm_duplicate_words "${config_list} ${config_name}") # Mirror each of the sub-configuration directories to the object directory. for conf in ${config_list_plus_name}; do echo "${script_name}: mirroring ${config_dirpath}/${conf} to ${obj_config_dirpath}/${conf}" ${mirror_tree_sh} "${config_dirpath}/${conf}" "${obj_config_dirpath}/${conf}" done # Mirror optimized kernels source tree to its object sub-directory. # We perform the mirroring on each configuration/kernel sub-directory # within 'kernels'. for kern in ${kernel_list}; do # Only mirror the optimized kernels source directory if it exists. # There are occasions where one of the sub-configurations in the # config_list does not correspond to a kernels sub-directory, such # as when architecture B is so close to architecture A that B can # use A's kernel source code unmodified (though perhaps with # different blocksizes). #if [ -d "${kernels_dirpath}/${conf}" ]; then echo "${script_name}: mirroring ${kernels_dirpath}/${kern} to ${obj_kernels_dirpath}/${kern}" ${mirror_tree_sh} "${kernels_dirpath}/${kern}" "${obj_kernels_dirpath}/${kern}" #else # echo "${script_name}: mirroring ${kernels_dirpath}/${conf} skipped... directory does not exist" #fi done # Mirror reference kernel source tree to its object sub-directory. echo "${script_name}: mirroring ${refkern_dirpath} to ${obj_refkern_dirpath}" ${mirror_tree_sh} ${refkern_dirpath} ${obj_refkern_dirpath} # Mirror reference kernels source tree to its object sub-directory. for conf in ${config_list}; do echo "${script_name}: mirroring ${refkern_dirpath} to ${obj_refkern_dirpath}/${conf}" ${mirror_tree_sh} "${refkern_dirpath}" "${obj_refkern_dirpath}/${conf}" done # Mirror framework source tree to its object sub-directory. echo "${script_name}: mirroring ${frame_dirpath} to ${obj_frame_dirpath}" ${mirror_tree_sh} ${frame_dirpath} ${obj_frame_dirpath} # Mirror the chosen addon source tree to its object sub-directory. if [ -n "${addon_flag}" ]; then for addon in ${addon_list}; do echo "${script_name}: mirroring ${addon_dirpath}/${addon} to ${obj_addon_dirpath}/${addon}" ${mirror_tree_sh} "${addon_dirpath}/${addon}" "${obj_addon_dirpath}/${addon}" done fi # Mirror the chosen sandbox source tree to its object sub-directory. if [ -n "${sandbox_flag}" ]; then echo "${script_name}: mirroring ${sandbox_dirpath}/${sandbox} to ${obj_sandbox_dirpath}/${sandbox}" ${mirror_tree_sh} "${sandbox_dirpath}/${sandbox}" "${obj_sandbox_dirpath}/${sandbox}" fi # -- Generate makefile fragements ------------------------------------------ clist_contains_cname=$(is_in_list "${config_name}" "${config_list}") # If the config_list does not already contain the config_name (i.e., # if config_name is an umbrella family), generate makefiles in that # directory. (In the next step, we will loop over the actual sub- # configurations and create fragments there as well.) if [ "${clist_contains_cname}" == "false" ]; then echo "${script_name}: creating makefile fragments in ${obj_config_dirpath}/${config_name}" ${gen_make_frags_sh} \ -h -r -v0 \ -o ${script_name} \ -p 'CONFIG' \ ${config_dirpath}/${config_name} \ ${obj_config_dirpath}/${config_name} \ ${gen_make_frags_dirpath}/fragment.mk \ ${gen_make_frags_dirpath}/suffix_list \ ${gen_make_frags_dirpath}/ignore_list fi # Generate makefile fragments for each of the sub-configurations present # in the configuration list. for conf in ${config_list}; do echo "${script_name}: creating makefile fragments in ${obj_config_dirpath}/${conf}" ${gen_make_frags_sh} \ -h -r -v0 \ -o ${script_name} \ -p 'CONFIG' \ ${config_dirpath}/${conf} \ ${obj_config_dirpath}/${conf} \ ${gen_make_frags_dirpath}/fragment.mk \ ${gen_make_frags_dirpath}/suffix_list \ ${gen_make_frags_dirpath}/ignore_list done # Generate makefile fragments for each of the kernel sets required by # the configuration list (in the kernel list). for kern in ${kernel_list}; do echo "${script_name}: creating makefile fragments in ${obj_kernels_dirpath}/${kern}" ${gen_make_frags_sh} \ -h -r -v0 \ -o ${script_name} \ -p 'KERNELS' \ ${kernels_dirpath}/${kern} \ ${obj_kernels_dirpath}/${kern} \ ${gen_make_frags_dirpath}/fragment.mk \ ${gen_make_frags_dirpath}/suffix_list \ ${gen_make_frags_dirpath}/ignore_list done # Generate makefile fragments in the reference kernels directory. echo "${script_name}: creating makefile fragments in ${obj_refkern_dirpath}" ${gen_make_frags_sh} \ -h -r -v0 \ -o ${script_name} \ -p 'REFKERN' \ ${refkern_dirpath} \ ${obj_refkern_dirpath} \ ${gen_make_frags_dirpath}/fragment.mk \ ${gen_make_frags_dirpath}/suffix_list \ ${gen_make_frags_dirpath}/ignore_list # Generate makefile fragments in the framework directory. echo "${script_name}: creating makefile fragments in ${obj_frame_dirpath}" ${gen_make_frags_sh} \ -h -r -v0 \ -o ${script_name} \ -p 'FRAME' \ ${frame_dirpath} \ ${obj_frame_dirpath} \ ${gen_make_frags_dirpath}/fragment.mk \ ${gen_make_frags_dirpath}/suffix_list \ ${gen_make_frags_dirpath}/ignore_list # Generate makefile fragments in the addon sub-directory. if [ -n "${addon_flag}" ]; then for addon in ${addon_list}; do echo "${script_name}: creating makefile fragments in ${obj_addon_dirpath}/${addon}" ${gen_make_frags_sh} \ -h -r -v0 \ -o ${script_name} \ -p 'ADDON' \ ${addon_dirpath}/${addon} \ ${obj_addon_dirpath}/${addon} \ ${gen_make_frags_dirpath}/fragment.mk \ ${gen_make_frags_dirpath}/suffix_list \ ${gen_make_frags_dirpath}/ignore_list done fi # Generate makefile fragments in the sandbox sub-directory. if [ -n "${sandbox_flag}" ]; then echo "${script_name}: creating makefile fragments in ${obj_sandbox_dirpath}/${sandbox}" ${gen_make_frags_sh} \ -h -r -v0 \ -o ${script_name} \ -p 'SANDBOX' \ ${sandbox_dirpath}/${sandbox} \ ${obj_sandbox_dirpath}/${sandbox} \ ${gen_make_frags_dirpath}/fragment.mk \ ${gen_make_frags_dirpath}/suffix_list \ ${gen_make_frags_dirpath}/ignore_list fi # -- Handle out-of-tree builds --------------------------------------------- # Under some circumstances, we need to create some symbolic links to # properly handle out-of-tree builds. if [ "${configured_oot}" = "yes" ]; then # If 'Makefile' symlink does not already exist in the current # directory, create a symbolic link to it. If one does exist, we # use -f to force creation of a new link. if [ ! -e "./Makefile" ]; then echo "${script_name}: creating symbolic link to Makefile." ln -s "${dist_path}/Makefile" elif [ -h "./Makefile" ]; then echo "${script_name}: symbolic link to Makefile already exists; forcing creation of new link." ln -sf "${dist_path}/Makefile" else echo "${script_name}: Non-symbolic link file or directory 'Makefile' blocks creation of symlink." echo "${script_name}: *** Please remove this entity and re-run configure." exit 1 fi # If 'blis.pc.in' symlink does not already exist in the current # directory, create a symbolic link to it. If one does exist, we # use -f to force creation of a new link. if [ ! -e "./blis.pc.in" ]; then echo "${script_name}: creating symbolic link to blis.pc.in." ln -s "${dist_path}/blis.pc.in" elif [ -h "./blis.pc.in" ]; then echo "${script_name}: symbolic link to blis.pc.in already exists; forcing creation of new link." ln -sf "${dist_path}/blis.pc.in" else echo "${script_name}: Non-symbolic link file or directory 'blis.pc.in' blocks creation of symlink." echo "${script_name}: *** Please remove this entity and re-run configure." exit 1 fi # If 'common.mk' symlink does not already exist in the current # directory, create a symbolic link to it. If one does exist, we # use -f to force creation of a new link. if [ ! -e "./common.mk" ]; then echo "${script_name}: creating symbolic link to common.mk." ln -s "${dist_path}/common.mk" elif [ -h "./common.mk" ]; then echo "${script_name}: symbolic link to common.mk already exists; forcing creation of new link." ln -sf "${dist_path}/common.mk" else echo "${script_name}: Non-symbolic link file or directory 'common.mk' blocks creation of symlink." echo "${script_name}: *** Please remove this entity and re-run configure." exit 1 fi # If 'config' symlink does not already exist in the current # directory, create a symbolic link to it. If one does exist, we # use -f to force creation of a new link. if [ ! -e "./config" ]; then echo "${script_name}: creating symbolic link to 'config' directory." ln -s "${dist_path}/config" elif [ -h "./config" ]; then echo "${script_name}: symbolic link to 'config' directory already exists; forcing creation of new link." ln -sf "${dist_path}/config" else echo "${script_name}: Non-symbolic link file or directory 'config' blocks creation of symlink." echo "${script_name}: *** Please remove this entity and re-run configure." exit 1 fi echo "${script_name}: configured to build outside of source distribution." else echo "${script_name}: configured to build within top-level directory of source distribution." fi if [ "${warn_user_generic}" = "1" ]; then echo "${script_name}: " echo "${script_name}: *** Unable to automatically detect hardware type! ***" echo "${script_name}: " echo "${script_name}: NOTE: configure was unable to identify a subconfiguration" echo "${script_name}: optimized for your hardware. As a result, the 'generic'" echo "${script_name}: subconfiguration (with low-performance reference kernels)" echo "${script_name}: will be used. For support, please open an issue on GitHub" echo "${script_name}: at https://github.com/flame/blis/issues." echo "${script_name}: " fi # Exit peacefully. return 0 } # The script's main entry point, passing all parameters given. main "$@" blis-0.9.0/docs/000077500000000000000000000000001422157504600134075ustar00rootroot00000000000000blis-0.9.0/docs/Addons.md000066400000000000000000000254151422157504600151500ustar00rootroot00000000000000## Contents * **[Introduction](Addons.md#introduction)** * **[Enabling addons](Addons.md#enabling-addons)** * **[Addon rules](Addons.md#addon-rules)** * **[Caveats](Addons.md#caveats)** * **[Known issues](Addons.md#known-issues)** * **[Conclusion](Addons.md#conclusion)** ## Introduction This file briefly describes the requirements for enabling or creating a custom BLIS *addon*. Simply put, an addon in BLIS provides additional APIs, operations, and/or implementations that may be useful to certain users. An addon can be thought of as a standalone extension of BLIS that does not depend on any other addon, although addons may utilize existing functionality or kernels within the core framework. By definition, an addon should *never* provide APIs that conflict with the interfaces that belong to either the [typed API](BLISTypedAPI.md) or the [object API](BLISObjectAPI.md). Thus, you'll never have to worry about a properly constructed (and properly functioning) addon interfering with or otherwise changing core BLIS functionality. How does an addon differ from a [sandbox](Sandboxes.md)? Great question! Sometimes you want to include additional BLIS-like functionality that does not relate directly to `gemm` or any other BLIS operation. (By contrast, a sandbox requires you to implement `gemm` whether you want to or not.) Furthermore, you may wish to enable multiple addons simultaneously. (By contrast, only one sandbox may be enabled at a time.) Thus, the addon feature provides additional flexibility to some users in a way that sandboxes cannot, while still providing many of the conveniences of sandboxes. ## Enabling an addon To enable an existing addon at configure-time, you simply specify it as an option to `configure`. Either of the following usages are accepted: ``` $ ./configure --enable-addon=foobar auto $ ./configure -a foobar auto ``` Here, we tell `configure` that we want to use the `foobar` addon, which corresponds to a subdirectory of the `addon` directory named `foobar`. (Reminder: the `auto` argument is the configuration target and unrelated to addons.) You may also enable multiple addons within the same build of BLIS: ``` $ ./configure -a foobar -a thing1 -a thing2 auto ``` Note that the default behavior of `configure` is that no addons are enabled. As `configure` runs, you should get output that includes lines similar to: ``` configure: configuring with addons: configure: addon/foobar configure: addon/thing1 configure: addon/thing2 ``` And when you build BLIS, the addon source code will be among the last files to be compiled: ``` Compiling obj/haswell/addon/foobar/foobar.o ('haswell' CFLAGS for addons) Compiling obj/haswell/addon/thing1/thing1.o ('haswell' CFLAGS for addons) Compiling obj/haswell/addon/thing1/thing1_api.o ('haswell' CFLAGS for addons) Compiling obj/haswell/addon/thing2/thing2_api.o ('haswell' CFLAGS for addons) ... ``` That's it! After the BLIS library is built, it will contain your chosen addons. You can always confirm this by using `nm` to confirm the presence of your API symbols: ``` $ nm lib/haswell/libblis.a | grep foobar foobar.o: 0000000000000000 T foobar ``` ## Addon rules Please follow these guidelines for the best developer experience when creating addons. 1. As with sandboxes, you don't need to worry about creating makefiles. The BLIS build system will take care of this for you. :) By configuring BLIS with an addon enabled, `make` will scan your addon subdirectory and compile all of its source code using similar compilation rules as were used for the rest of the framework. In addition, the compilation command line will automatically contain one `-I` option for every subdirectory in your addon, so it doesn't matter where in your addon directory hierarchy you place your header files -- they will be found! 2. We recommend that you write your addon in C99. While you *may* use C++11 to implement your addon, you should provide a C99 wrapper API to your implementation so that others can interface with it. There is no guarantee that the end-user will be using a C++11 compiler, and therefore you should limit the definitions in your addon header to those that are C99 compliant. If you write your addon in C++11, you must use one of the BLIS-approved file extensions for your source files (`.cc`, `.cpp`, `.cxx`) and your local header files (`.hh`, `.hpp`, `.hxx`). Note that `blis.h` already contains all of its definitions inside of an `extern "C"` block, so you should be able to `#include "blis.h"` from your C++11 source code without any issues. 3. All of your code related to the addon should reside within the named addon directory, or some subdirectory therein. If your addon requires new kernels, you should add kernel source code to an appropriate microarchitecture-specific subdirectory within the top-level `kernels` directory so that they are compiled with the correct microarchitecture-specific optimization flags. 4. If your addon is named `foobar`, the BLIS build system will expect to find a header called `foobar.h` somewhere in the `addon/foobar` directory (or one of its subdirectories). This `foobar.h` header will automatically be inlined into the monolithic `blis.h` header that is produced by the BLIS build system. `foobar.h` may `#include` other local headers, each of which will also (recursively) get inlined into `blis.h`. However, you may choose to omit some local addon headers from `foobar.h.` You might do this, for example, because those headers define things that are not needed in order for the end user to call your addon code. 5. Your addon APIs will always be available within static library builds of BLIS, but if you want your addon APIs to be exported as public APIs within *shared* library builds of BLIS, you'll need to annotate the prototypes accordingly. (BLIS makes its shared library symbols private by default; this allows us to export only those functions that we consider to be part of the public APIs.) This annotation can be done by prefixing function prototypes with the `BLIS_EXPORT_ADDON` macro as follows: ```c BLIS_EXPORT_ADDON void foobar_calc( void* a, void* b ); ``` 6. Do not define any symbols in your addon that conflict with any symbols within the core framework. For example, don't define a function called `bli_copym()` in your addon since that function is already defined within BLIS. 7. Do not define any symbols in your addon that conflict with any symbols within the C99 standard libraries/headers. For example, don't define a function called `printf()` since that function is already defined within the C99 standard library. 8. *Try* to not define any symbols in your addon that conflict with symbols in any other addon, unless your addon is meant to serve as an alternative to the conflicting addon, in which case conflicting symbol names is okay (since you will presumably never build with both addons enabled). 9. When choosing names for your addon files, avoid source filenames that already exist within BLIS. For example, don't name one of your files `bli_obj.c` since that file would compile into `bli_obj.o`, which will have already been placed into the library by the build system. 10. Similarly, avoid header filenames that already exist within BLIS or C99. For example, don't name one of your header files `bli_obj.h` since that file already exists in BLIS. Also, don't name one of your header files `math.h` since that name would conflict with the `math.h` defined by C99. (This also means you shouldn't name your addon `math` since normally that name would require that you provide a `math.h` header inside the addon directory.) If you follow these rules, you will be much more likely to have a pleasant experience integrating your BLIS addon into the larger framework. ## Caveats Notice that the BLIS addons are limited in what they can accomplish. Generally speaking, addons cannot change existing implementations within BLIS. Instead, addons aim to provide a way to quickly augment BLIS with additional bundles of code that extend BLIS's set of functionality in some interesting way. If you want to define new BLAS-like functions, but don't know where to start, creating a new addon is an appropriate place to start experimenting. If you want to change or refactor existing BLIS code, an addon is probably not suited for your needs. Another important limitation is the fact that the build system currently uses "framework `CFLAGS`" when compiling the addon source files. These are the same `CFLAGS` used when compiling general framework source code, ``` # Example framework CFLAGS used by 'haswell' sub-configuration -O2 -Wall -Wno-unused-function -Wfatal-errors -fPIC -std=c99 -D_POSIX_C_SOURCE=200112L -Iinclude/haswell -I./frame/3/ -I./frame/1m/ -I./frame/1f/ -I./frame/1/ -I./frame/include -DBLIS_VERSION_STRING=\"0.8.1-195\" -fvisibility=hidden ``` which are likely more general-purpose than the `CFLAGS` used for, say, optimized kernels or even reference kernels: ``` # Example optimized kernel CFLAGS used by 'haswell' sub-configuration -O3 -fomit-frame-pointer -mavx2 -mfma -mfpmath=sse -march=haswell -Wall -Wno-unused-function -Wfatal-errors -fPIC -std=c99 -D_POSIX_C_SOURCE=200112L -Iinclude/haswell -I./frame/3/ -I./frame/1m/ -I./frame/1f/ -I./frame/1/ -I./frame/include -DBLIS_VERSION_STRING=\"0.8.1-195\" -fvisibility=hidden ``` (To see precisely which flags are being employed for any given file, enable verbosity at compile-time via `make V=1`.) Compiling addons with these more versatile `CFLAGS` compiler options means that we only need to compile one instance of each addon source file, even when targeting multiple configurations (for example, via `./configure x86_64`). However, it also means that addons are not ideal for microkernels, as they sometimes need additional compiler flags in order to yield the highest performance. If you have a new microkernel you would like to use within an addon, you can always develop it within that addon. However, once it is stable and ready for use by others, it's best to move the kernel(s) to the appropriate microarchitecture-specific subdirectory of the `kernels` directory the kernel(s). This will allow the kernel to be compiled with the appropriate microarchitecture-specific compiler flags. Please see the [Configuration Guide](ConfigurationHowTo) for more details, and when in doubt, please don't be shy about seeking guidance from BLIS developers by opening a [new issue](https://github.com/flame/blis/issues) or sending a message to the [blis-devel](http://groups.google.com/d/forum/blis-devel) mailing list. Notwithstanding these limitations, hopefully you still find BLIS addons useful! ## Known issues * None yet. ## Conclusion If you encounter any problems, please open a new [issue on GitHub](https://github.com/flame/blis/issues). If you are unsure about how something works, you can still open an issue. Or, you can send a message to [blis-devel](https://groups.google.com/d/forum/blis-devel) mailing list. blis-0.9.0/docs/BLISObjectAPI.md000066400000000000000000002447401422157504600161560ustar00rootroot00000000000000# Contents * **[Contents](BLISObjectAPI.md#contents)** * **[Operation index](BLISObjectAPI.md#operation-index)** * **[Introduction](BLISObjectAPI.md#introduction)** * [BLIS types](BLISObjectAPI.md#blis-types) * [Integer-based types](BLISObjectAPI.md#integer-based-types) * [Floating-point types](BLISObjectAPI.md#floating-point-types) * [Enumerated parameter types](BLISObjectAPI.md#enumerated-parameter-types) * [Global scalar constants](BLISObjectAPI.md#global-scalar-constants) * [Basic vs expert interfaces](BLISObjectAPI.md#basic-vs-expert-interfaces) * [Context type](BLISObjectAPI.md#context-type) * [Runtime type](BLISObjectAPI.md#runtime-type) * [BLIS header file](BLISObjectAPI.md#blis-header-file) * [Initialization and cleanup](BLISObjectAPI.md#initialization-and-cleanup) * **[Object management](BLISObjectAPI.md#object-management)** * [Object creation function reference](BLISObjectAPI.md#object-creation-function-reference) * [Object accessor function reference](BLISObjectAPI.md#object-accessor-function-reference) * [Object mutator function reference](BLISObjectAPI.md#object-mutator-function-reference) * [Other object function reference](BLISObjectAPI.md#other-object-function-reference) * **[Computational function reference](BLISObjectAPI.md#computational-function-reference)** * [Level-1v operations](BLISObjectAPI.md#level-1v-operations) * [Level-1d operations](BLISObjectAPI.md#level-1d-operations) * [Level-1m operations](BLISObjectAPI.md#level-1m-operations) * [Level-1f operations](BLISObjectAPI.md#level-1f-operations) * [Level-2 operations](BLISObjectAPI.md#level-2-operations) * [Level-3 operations](BLISObjectAPI.md#level-3-operations) * [Utility operations](BLISObjectAPI.md#utility-operations) * **[Query function reference](BLISObjectAPI.md#query-function-reference)** * [General library information](BLISObjectAPI.md#general-library-information) * [Specific configuration](BLISObjectAPI.md#specific-configuration) * [General configuration](BLISObjectAPI.md#general-configuration) * [Kernel information](BLISObjectAPI.md#kernel-information) * [Clock functions](BLISObjectAPI.md#clock-functions) * **[Example code](BLISObjectAPI.md#example-code)** # Operation index This index provides a quick way to jump directly to the description for each operation discussed later in the [Computational function reference](BLISObjectAPI.md#computational-function-reference) section: * **[Level-1v](BLISObjectAPI.md#level-1v-operations)**: Operations on vectors: * [addv](BLISObjectAPI.md#addv), [amaxv](BLISObjectAPI.md#amaxv), [axpyv](BLISObjectAPI.md#axpyv), [axpbyv](BLISObjectAPI.md#axpbyv), [copyv](BLISObjectAPI.md#copyv), [dotv](BLISObjectAPI.md#dotv), [dotxv](BLISObjectAPI.md#dotxv), [invertv](BLISObjectAPI.md#invertv), [scal2v](BLISObjectAPI.md#scal2v), [scalv](BLISObjectAPI.md#scalv), [setv](BLISObjectAPI.md#setv), [setrv](BLISObjectAPI.md#setrv), [setiv](BLISObjectAPI.md#setiv), [subv](BLISObjectAPI.md#subv), [swapv](BLISObjectAPI.md#swapv), [xpbyv](BLISObjectAPI.md#xpbyv) * **[Level-1d](BLISObjectAPI.md#level-1d-operations)**: Element-wise operations on matrix diagonals: * [addd](BLISObjectAPI.md#addd), [axpyd](BLISObjectAPI.md#axpyd), [copyd](BLISObjectAPI.md#copyd), [invertd](BLISObjectAPI.md#invertd), [scald](BLISObjectAPI.md#scald), [scal2d](BLISObjectAPI.md#scal2d), [setd](BLISObjectAPI.md#setd), [setid](BLISObjectAPI.md#setid), [shiftd](BLISObjectAPI.md#shiftd), [subd](BLISObjectAPI.md#subd), [xpbyd](BLISObjectAPI.md#xpbyd) * **[Level-1m](BLISObjectAPI.md#level-1m-operations)**: Element-wise operations on matrices: * [addm](BLISObjectAPI.md#addm), [axpym](BLISObjectAPI.md#axpym), [copym](BLISObjectAPI.md#copym), [scalm](BLISObjectAPI.md#scalm), [scal2m](BLISObjectAPI.md#scal2m), [setm](BLISObjectAPI.md#setm), [setrm](BLISObjectAPI.md#setrm), [setim](BLISObjectAPI.md#setim), [subm](BLISObjectAPI.md#subm) * **[Level-1f](BLISObjectAPI.md#level-1f-operations)**: Fused operations on multiple vectors: * [axpy2v](BLISObjectAPI.md#axpy2v), [dotaxpyv](BLISObjectAPI.md#dotaxpyv), [axpyf](BLISObjectAPI.md#axpyf), [dotxf](BLISObjectAPI.md#dotxf), [dotxaxpyf](BLISObjectAPI.md#dotxaxpyf) * **[Level-2](BLISObjectAPI.md#level-2-operations)**: Operations with one matrix and (at least) one vector operand: * [gemv](BLISObjectAPI.md#gemv), [ger](BLISObjectAPI.md#ger), [hemv](BLISObjectAPI.md#hemv), [her](BLISObjectAPI.md#her), [her2](BLISObjectAPI.md#her2), [symv](BLISObjectAPI.md#symv), [syr](BLISObjectAPI.md#syr), [syr2](BLISObjectAPI.md#syr2), [trmv](BLISObjectAPI.md#trmv), [trsv](BLISObjectAPI.md#trsv) * **[Level-3](BLISObjectAPI.md#level-3-operations)**: Operations with matrices that are multiplication-like: * [gemm](BLISObjectAPI.md#gemm), [hemm](BLISObjectAPI.md#hemm), [herk](BLISObjectAPI.md#herk), [her2k](BLISObjectAPI.md#her2k), [symm](BLISObjectAPI.md#symm), [syrk](BLISObjectAPI.md#syrk), [syr2k](BLISObjectAPI.md#syr2k), [trmm](BLISObjectAPI.md#trmm), [trmm3](BLISObjectAPI.md#trmm3), [trsm](BLISObjectAPI.md#trsm) * **[Utility](BLISObjectAPI.md#Utility-operations)**: Miscellaneous operations on matrices and vectors: * [asumv](BLISObjectAPI.md#asumv), [norm1v](BLISObjectAPI.md#norm1v), [normfv](BLISObjectAPI.md#normfv), [normiv](BLISObjectAPI.md#normiv), [norm1m](BLISObjectAPI.md#norm1m), [normfm](BLISObjectAPI.md#normfm), [normim](BLISObjectAPI.md#normim), [mkherm](BLISObjectAPI.md#mkherm), [mksymm](BLISObjectAPI.md#mksymm), [mktrim](BLISObjectAPI.md#mktrim), [fprintv](BLISObjectAPI.md#fprintv), [fprintm](BLISObjectAPI.md#fprintm),[printv](BLISObjectAPI.md#printv), [printm](BLISObjectAPI.md#printm), [randv](BLISObjectAPI.md#randv), [randm](BLISObjectAPI.md#randm), [sumsqv](BLISObjectAPI.md#sumsqv), [getsc](BLISObjectAPI.md#getsc), [getijv](BLISObjectAPI.md#getijv), [getijm](BLISObjectAPI.md#getijm), [setsc](BLISObjectAPI.md#setsc), [setijv](BLISObjectAPI.md#setijv), [setijm](BLISObjectAPI.md#setijm), [eqsc](BLISObjectAPI.md#eqsc), [eqv](BLISObjectAPI.md#eqv), [eqm](BLISObjectAPI.md#eqm) # Introduction This document summarizes one of the primary native APIs in BLIS--the object API. Here, we also discuss BLIS-specific type definitions, header files, and prototypes to auxiliary functions. There are many functions that BLIS implements that are not listed here, either because they are lower-level functions, or they are considered for use primarily by developers and experts. The object API was given its name (a) because it abstracts the floating-point types of its operands (along with many other properties) within a `typedef struct {...}` data structure, and (b) to contrast it with the other native API in BLIS, the typed API, which is [documented here](BLISTypedAPI.md). (The third API supported by BLIS is the BLAS compatibility layer, which mimics conventional Fortran-77 BLAS.) In general, this document should be treated more as a reference than a place to learn how to use BLIS in your application. Thus, we highly encourage all readers to first study the [example code](BLISObjectAPI.md#example-code) provided within the BLIS source distribution. ## BLIS types The following tables list various types used throughout the BLIS object API. ### Integer-based types | BLIS integer type | Type definition | Used to represent... | |:------------------|:-------------------------|:---------------------------------------------------------------------| | `gint_t` | `int32_t` or `int64_t` | general-purpose signed integer; used to define signed integer types. | | `guint_t` | `uint32_t` or `uint64_t` | general-purpose signed integer; used to define signed integer types. | | `dim_t` | `gint_t` | matrix and vector dimensions. | | `inc_t` | `gint_t` | matrix row/column strides and vector increments. | | `doff_t` | `gint_t` | matrix diagonal offset: if _k_ < 0, diagonal begins at element (-_k_,0); otherwise diagonal begins at element (0,_k_). | | `siz_t` | `guint_t` | a byte size or byte offset. | ### Floating-point types | BLIS fp type | Type definition | Used to represent... | |:------------------|:---------------------------------------|:-------------------------------------| | `float` | _N/A_ | single-precision real numbers | | `double` | _N/A_ | double-precision real numbers | | `scomplex` | `struct { float real; float imag; }` | single-precision complex numbers | | `dcomplex` | `struct { double real; double imag; }` | double-precision complex numbers | ### Enumerated parameter types | `num_t` | Semantic meaning: Matrix/vector operand... | |:----------------|:--------------------------------------------------------| | `BLIS_FLOAT` | contains single-precision real elements. | | `BLIS_DOUBLE` | contains double-precision real elements. | | `BLIS_SCOMPLEX` | contains single-precision complex elements. | | `BLIS_DCOMPLEX` | contains double-precision complex elements. | | `BLIS_INT` | contains integer elements of type `gint_t`. | | `BLIS_CONSTANT` | contains polymorphic representation of a constant value | | `dom_t` | Semantic meaning: Matrix/vector operand... | |:----------------|:--------------------------------------------| | `BLIS_REAL` | contains real domain elements. | | `BLIS_COMPLEX` | contains complex domain elements. | | `prec_t` | Semantic meaning: Matrix/vector operand... | |:-------------------|:--------------------------------------------| | `BLIS_SINGLE_PREC` | contains single-precision elements. | | `BLIS_DOUBLE_PREC` | contains double-precision elements. | | `trans_t` | Semantic meaning: Matrix operand ... | |:-------------------------|:--------------------------------------------------| | `BLIS_NO_TRANSPOSE` | will be used as given. | | `BLIS_TRANSPOSE` | will be implicitly transposed. | | `BLIS_CONJ_NO_TRANSPOSE` | will be implicitly conjugated. | | `BLIS_CONJ_TRANSPOSE` | will be implicitly transposed _and_ conjugated. | | `conj_t` | Semantic meaning: Matrix/vector operand... | |:---------------------|:---------------------------------------------------------| | `BLIS_NO_CONJUGATE` | will be used as given. | | `BLIS_CONJUGATE` | will be implicitly conjugated. | | `side_t` | Semantic meaning: Matrix operand... | |:-------------|:---------------------------------------------------| | `BLIS_LEFT` | appears on the left. | | `BLIS_RIGHT` | appears on the right. | | `struc_t` | Semantic meaning: Matrix operand... | |:------------------|:------------------------------------------------------------------| | `BLIS_GENERAL` | has no structure. | | `BLIS_HERMITIAN` | has Hermitian structure. | | `BLIS_SYMMETRIC` | has symmetric structure. | | `BLIS_TRIANGULAR` | has triangular structure. | | `uplo_t` | Semantic meaning: Matrix operand... | |:-------------|:------------------------------------------------------------------| | `BLIS_LOWER` | is stored in (and will be accessed only from) the lower triangle. | | `BLIS_UPPER` | is stored in (and will be accessed only from) the upper triangle. | | `BLIS_DENSE` | is stored as a full matrix (ie: in both triangles). | | `diag_t` | Semantic meaning: Matrix operand ... | |:--------------------|:---------------------------------------------------------------------------| | `BLIS_NONUNIT_DIAG` | has a non-unit diagonal that should be explicitly read from. | | `BLIS_UNIT_DIAG` | has a unit diagonal that should be implicitly assumed (and not read from). | ## Global scalar constants BLIS defines a handful of scalar objects that conveniently represent various constant values for all defined numerical type values (`num_t`). The following table lists the constants defined by BLIS. | BLIS constant `obj_t` name | Numerical values | |:---------------------------|:-----------------| | `BLIS_MINUS_TWO` | `-2.0` | | `BLIS_MINUS_ONE` | `-1.0` | | `BLIS_ZERO` | ` 0.0` | | `BLIS_ONE` | ` 1.0` | | `BLIS_TWO` | ` 2.0` | These objects are polymorphic; each one contains a `float`, `double`, `scomplex`, `dcomplex`, and `gint_t` representation of the constant value in question. They can be used in place of any `obj_t*` operand in any object API function provided that the following criteria are met: * The object parameter requires unit dimensions (1x1). (In other words, the function expects a scalar for the operand in question.) * The object parameter is input-only. (In other words, the function is not trying to update the scalar.) The correct representation is chosen by context, usually by inspecting the datatype of one of the other operands involved in an operation. For example, if we create and initialize objects `x` and `y` of `num_t` type `BLIS_DOUBLE`, the following call to `bli_axpyv()` ```c bli_axpyv( &BLIS_TWO, &x, &y ); ``` will use the `BLIS_DOUBLE` representation of `BLIS_TWO`. ## Basic vs expert interfaces The functions listed in this document belong to the "basic" interface subset of the BLIS object API. There is a companion "expert" interface that mirrors the basic interface, except that it also contains two additional parameters that are only of interest to experts and library developers. The expert interfaces use the same name as the basic function names, except for an additional "_ex" suffix. For example, the basic interface for `gemm` is ```c void bli_gemm ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, ); ``` while the expert interface is: ```c void bli_gemm_ex ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, rntm_t* rntm ); ``` The expert interface contains two additional parameters: a `cntx_t*` and `rntm_t*`. Note that calling a function from the expert interface with the `cntx_t*` and `rntm_t*` arguments each set to `NULL` is equivalent to calling the corresponding basic interface. Specifically, a `NULL` value passed in for the `cntx_t*` results in a valid context being queried from BLIS, and a `NULL` value passed in for the `rntm_t*` results in the current global settings for multithreading to be used. ## Context type In general, it is permissible to pass in `NULL` for a `cntx_t*` parameter when calling an expert interface such as `bli_gemm_ex()`. However, there are cases where `NULL` values are not accepted and may result in a segmentation fault. Specifically, the `cntx_t*` argument appears in the interfaces to the `gemm`, `trsm`, and `gemmtrsm` [level-3 microkernels](KernelsHowTo.md#level-3) along with all [level-1v](KernelsHowTo.md#level-1v) and [level-1f](KernelsHowTo.md#level-1f) kernels. There, as a general rule, a valid pointer must be passed in. Whenever a valid context is needed, the developer may query a default context from the global kernel structure (if a context is not already available in the current scope): ```c cntx_t* bli_gks_query_cntx( void ); ``` When BLIS is configured to target a configuration family (e.g. `intel64`, `x86_64`), `bli_gks_query_cntx()` will use `cpuid` or an equivalent heuristic to select and and return the appropriate context. When BLIS is configured to target a singleton sub-configuration (e.g. `haswell`, `skx`), `bli_gks_query_cntx()` will unconditionally return a pointer to the context appropriate for the targeted configuration. ## Runtime type When calling one of the expert interfaces, a `rntm_t` (runtime) object can be used to convey a thread-local request for parallelism to the underlying implementation. Runtime objects are thread-safe by nature when they are declared statically as a stack variable (or allocated via `malloc()`), initialized, and then passed into the expert interface of interest. Notice that runtime objects have no analogue in most BLAS libraries, where you are forced to specify parallelism at a global level (usually via environment variables). For more information on using `rntm_t` objects, please read the [Multithreading](Multithreading.md) documentation, paying close attention to the section on [local setting of parallelism](Multithreading.md#locally-at-runtime). ## BLIS header file All BLIS definitions and prototypes may be included in your C source file by including a single header file: ```c #include "blis.h" ``` ## Initialization and Cleanup As of [9804adf](https://github.com/flame/blis/commit/9804adfd405056ec332bb8e13d68c7b52bd3a6c1), BLIS no longer requires explicit initialization and finalization at runtime. In other words, users do not need to call `bli_init()` before the application can make use of the library (and `bli_finalize()` after the application is finished with the library). Instead, all computational operations (and some non-computational functions) in BLIS will initialize the library on behalf of the user if it has not already been initialized. This change was made to simplify the user experience. Application developers should keep in mind, however, that this new self-initialization regime implies the following: unless the library is *explicitly* finalized via `bli_finalize()`, it will, once initialized, remain initialized for the life of the application. This is likely not a problem in the vast majority of cases. However, a memory-constrained application that performs all of its DLA up-front, for example, may wish to explicitly finalize the library after BLIS is no longer needed in order to free up memory for other purposes. Similarly, an expert user may call `bli_init()` manually in order to control when the overhead of library initialization is incurred, even though the library would have self-initialized. The interfaces to `bli_init()` and `bli_finalize()` are quite simple; they require no arguments and return no values: ```c void bli_init( void ); void bli_finalize( void ); ``` # Object management ## Introduction Before using the object API, you must first create some objects to encapsulate your vector or matrix data. We provide examples code for creating matrix objects in the [examples/oapi](https://github.com/flame/blis/tree/master/examples/oapi) directory of the BLIS source distribution. However, we will provide API documentation for the most common functions for creating and freeing objects in the next section. Generally speaking, an object is created when an `obj_t` structure is initialized with valid properties describing the object as well as a valid data buffer (to hold the elements of the vector or matrix). The valid data buffer can be allocated automatically on your behalf at the same time that the other object fields are initialized, or "attached" in a second step after the object is initialized with preliminary values. The former is useful when using the object API at the setup stage of an application (and if `malloc()` is an acceptable method of allocating memory). Similarly, the latter is useful when interfacing BLIS into the middle of an application after the allocation has already taken place, or when some function other than `malloc()` is desired for allocating the buffer. Only objects that were created with automatic allocation must be freed via BLIS object API. Objects that were initialized with attached buffers can be freed in whatever manner is appropriate, based on how the application originally allocated the memory in question. ## Object creation function reference ```c void bli_obj_create ( num_t dt, dim_t m, dim_t n, inc_t rs, inc_t cs, obj_t* obj ); ``` Initialize an _m x n_ object `obj` and allocate sufficient storage to hold _mn_ elements whose storage type is specified by `dt` and with row and column strides `rs` and `cs`, respectively. This function allocates enough space to enforce alignment of leading dimensions, where the alignment factor is specific to the configuration being used, though the alignment factor is almost always equal to the size of the hardware's SIMD registers. The address `obj` must reference valid memory--typically an `obj_t` declared statically or allocated dynamically via `malloc()`. After an object created via `bli_obj_create()` is no longer needed, it should be deallocated via `bli_obj_free()`. --- ```c void bli_obj_free ( obj_t* obj ); ``` Deallocate (release) an object `obj` that was previously created, typically via `bli_obj_create()`. --- ```c void bli_obj_create_without_buffer ( num_t dt, dim_t m, dim_t n, obj_t* obj ); ``` Partially initialize an _m x n_ object `obj` that will eventually contain elements whose storage type is specified by `dt`. This function does not result in any memory allocation. Before `obj` can be used, the object must be fully initialized by attaching a buffer via `bli_obj_attach_buffer()`. This function is useful when the user wishes to encapsulate existing buffers into one or more `obj_t` objects. An object (partially) initialized via this function should generally not be passed to `bli_obj_free()` even after a buffer is attached to it via `bli_obj_attach_buffer()`, unless the user wishes to pass that buffer into `free()`. --- ```c void bli_obj_attach_buffer ( void* p, inc_t rs, inc_t cs, inc_t is, obj_t* obj ); ``` Given a partially initialized object (i.e., one that has already been passed to `bli_obj_create_without_buffer()`), attach the buffer pointed to by `p` to the object referenced by `obj` and initialize `obj` as containing elements with row and column strides `rs` and `cs`, respectively. The function also initializes the imaginary stride as `is`, which is experimental and not consistently used by all parts of BLIS. --- ```c void bli_obj_create_with_attached_buffer ( num_t dt, dim_t m, dim_t n, void* p, inc_t rs, inc_t cs, obj_t* obj ); ``` Initialize an _m x n_ object `obj` as containing _mn_ elements whose storage type is specified by `dt` and with row and column strides `rs` and `cs`, respectively. The function does not allocate any memory and instead attaches the buffer pointed to by `p`. Note that calling this function is effectively equivalent to calling ```c bli_obj_create_without_buffer( dt, m, n, obj ); bli_obj_attach_buffer( p, rs, cs, 1, obj ); ``` Objects initialized via this function should generally not be passed to `bli_obj_free()`, unless the user wishes to pass `p` into `free()`. --- ```c void bli_obj_alloc_buffer ( inc_t rs, inc_t cs, inc_t is, obj_t* obj ); ``` Given a partially initialized _m x n_ object, allocate and attach a buffer large enough to contain _mn_ elements with the row and column strides `rs` and `cs`, respectively. This function allocates enough space to enforce alignment of leading dimensions, where the alignment factor is specific to the configuration being used, though the alignment factor is almost always equal to the size of the hardware's SIMD registers. Note that calling `bli_obj_create()` is effectively equivalent to calling ```c bli_obj_create_without_buffer( dt, m, n, obj ); bli_obj_alloc_buffer( rs, cs, 1, obj ); ``` Very few users will likely have a need to call this function. We provide documentation for it mostly so that others can manually access the alignment features of `bli_obj_create()` without also needing to initialize an `obj_t`. --- ```c void bli_obj_create_1x1 ( num_t dt, obj_t* obj ); ``` Initialize a _1 x 1_ object `obj` and allocate sufficient storage to hold one element whose storage type is specified by `dt`. The address `obj` must reference valid memory--typically an `obj_t` declared statically or allocated dynamically via `malloc()`. This function is useful any time the user wishes to create a scalar object with an allocated buffer. Note that calling `bli_obj_create_1x1()` is effectively equivalent to calling ```c bli_obj_create_without_buffer( dt, 1, 1, obj ); bli_obj_alloc_buffer( 1, 1, 1, obj ); ``` After an object created via `bli_obj_create_1x1()` is no longer needed, it should be deallocated via `bli_obj_free()`. --- ```c void bli_obj_create_1x1_with_attached_buffer ( num_t dt, void* p, obj_t* obj ); ``` Initialize a _1 x 1_ object `obj` as containing one element whose storage type is specified by `dt`. The function does not allocate any memory and instead attaches the buffer pointed to by `p`. Note that calling this function is effectively equivalent to calling ```c bli_obj_create_without_buffer( dt, 1, 1, obj ); bli_obj_attach_buffer( p, 1, 1, 1, obj ); ``` Objects initialized via this function should generally not be passed to `bli_obj_free()`, unless the user wishes to pass `p` into `free()`. --- ```c void bli_obj_create_conf_to ( obj_t* s, obj_t* d ); ``` Initialize an object `d` with dimensions conformal to those of an existing object `s`. Object `d` is initialized with the same row and column strides as those of `s`. However, the structure, uplo, conjugation, and transposition properties of `s` are **not** inherited by `d`. On entry, object `s` must be fully initialized and the address `d` must reference valid memory--typically an `obj_t` declared statically or allocated dynamically via `malloc()`. Note that calling this function is effectively equivalent to calling ```c num_t dt = bli_obj_dt( s ); dim_t m = bli_obj_length( s ); dim_t n = bli_obj_width( s ); inc_t rs = bli_obj_row_stride( s ); inc_t cs = bli_obj_col_stride( s ); bli_obj_create( dt, m, n, rs, cs, d ); ``` After an object created via `bli_obj_create_conf_to()` is no longer needed, it should be deallocated via `bli_obj_free()`. --- ```c void bli_obj_scalar_init_detached ( num_t dt, obj_t* obj ); ``` Initialize a _1 x 1_ object `obj` using internal storage sufficient to hold one element whose storage type is specified by `dt`. (Internal storage is present within every `obj_t` and is capable of holding on element of any supported type.) This function is similar to `bli_obj_create_1x1()`, except that the object does not trigger any dynamic memory allocation. Objects initialized via this function should **never** be passed to `bli_obj_free()`. ## Object accessor function reference Notes for interpreting function descriptions: * Object accessor functions allow the caller to query certain properties of objects. * These functions are only guaranteed to return meaningful values when called upon objects that have been fully initialized/created. * Many specialized functions are omitted from this section for brevity. For a full list of accessor functions, please see [frame/include/bli_obj_macro_defs.h](https://github.com/flame/blis/tree/master/frame/include/bli_obj_macro_defs.h), though most users will most likely not need methods beyond those documented below. --- ```c num_t bli_obj_dt( obj_t* obj ); ``` Return the storage datatype property of `obj`. --- ```c dom_t bli_obj_dom( obj_t* obj ); ``` Return the domain component of the storage datatype property of `obj`. --- ```c prec_t bli_obj_prec( obj_t* obj ); ``` Return the precision component of the storage datatype property of `obj`. --- ```c trans_t bli_obj_conjtrans_status( obj_t* obj ); ``` Return the `trans_t` property of `obj`, which may indicate transposition, conjugation, both, or neither. Thus, possible return values are `BLIS_NO_TRANSPOSE`, `BLIS_CONJ_NO_TRANSPOSE`, `BLIS_TRANSPOSE`, or `BLIS_CONJ_TRANSPOSE`. --- ```c trans_t bli_obj_onlytrans_status( obj_t* obj ); ``` Return the transposition component of the `trans_t` property of `obj`, which may indicate transposition or no transposition. Thus, possible return values are `BLIS_NO_TRANSPOSE` or `BLIS_TRANSPOSE`. --- ```c conj_t bli_obj_conj_status( obj_t* obj ); ``` Return the conjugation component of the `trans_t` property of `obj`, which may indicate conjugation or no conjugation. Thus, possible return values are `BLIS_NO_CONJUGATE` or `BLIS_CONJUGATE`. --- ```c struc_t bli_obj_struc( obj_t* obj ); ``` Return the structure property of `obj`. --- ```c uplo_t bli_obj_uplo( obj_t* obj ); ``` Return the uplo (i.e., storage) property of `obj`. --- ```c diag_t bli_obj_diag( obj_t* obj ); ``` Return the diagonal property of `obj`. --- ```c doff_t bli_obj_diag_offset( obj_t* obj ); ``` Return the diagonal offset of `obj`. Note that the diagonal offset will be negative, `-i`, if the diagonal begins at element `(-i,0)` and positive `j` if the diagonal begins at element `(0,j)`. --- ```c dim_t bli_obj_length( obj_t* obj ); ``` Return the number of rows (or _m_ dimension) of `obj`. This value is the _m_ dimension **before** taking into account the transposition property as indicated by `bli_obj_onlytrans_status()` or `bli_obj_conjtrans_status()`. --- ```c dim_t bli_obj_width( obj_t* obj ); ``` Return the number of columns (or _n_ dimension) of `obj`. This value is the _n_ dimension **before** taking into account the transposition property as indicated by `bli_obj_onlytrans_status()` or `bli_obj_conjtrans_status()`. --- ```c dim_t bli_obj_length_after_trans( obj_t* obj ); ``` Return the number of rows (or _m_ dimension) of `obj` after taking into account the transposition property as indicated by `bli_obj_onlytrans_status()` or `bli_obj_conjtrans_status()`. --- ```c dim_t bli_obj_width_after_trans( obj_t* obj ); ``` Return the number of columns (or _n_ dimension) of `obj` after taking into account the transposition property as indicated by `bli_obj_onlytrans_status()` or `bli_obj_conjtrans_status()`. --- ```c inc_t bli_obj_row_stride( obj_t* obj ); ``` Return the row stride property of `obj`. When storing by columns, the row stride is 1. When storing by rows, the row stride is also sometimes called the _leading dimension_. --- ```c inc_t bli_obj_col_stride( obj_t* obj ); ``` Return the column stride property of `obj`. When storing by rows, the column stride is 1. When storing by columns, the column stride is also sometimes called the _leading dimension_. --- ```c dim_t bli_obj_vector_dim( obj_t* obj ); ``` Return the number of elements in a vector object `obj`. This function assumes that at least one dimension of `obj` is unit, and that it therefore represents a vector. --- ```c inc_t bli_obj_vector_inc( obj_t* obj ); ``` Return the storage increment of a vector object `obj`. This function assumes that at least one dimension of `obj` is unit, and that it therefore represents a vector. --- ```c void* bli_obj_buffer( obj_t* obj ); ``` Return the address to the data buffer associated with object `obj`. **Note**: The address returned by this buffer will not take into account any subpartitioning. However, this will not be a problem for most casual users. --- ```c siz_t bli_obj_elem_size( obj_t* obj ); ``` Return the size, in bytes, of the storage datatype as indicated by `bli_obj_dt()`. ## Object mutator function reference Notes for interpreting function descriptions: * Object mutator functions allow the caller to modify certain properties of objects. * The user should be extra careful about modifying properties after objects are created. For typical use of these functions, please study the example code provided in [examples/oapi](https://github.com/flame/blis/tree/master/examples/oapi). * The list of mutators below is much shorter than the list of accessor functions provided in the previous section. Most mutator functions should *not* be called by users (unless you know what you are doing). For a full list of mutator functions, please see [frame/include/bli_obj_macro_defs.h](https://github.com/flame/blis/tree/master/frame/include/bli_obj_macro_defs.h), though most users will most likely not need methods beyond those documented below. --- ```c void bli_obj_set_conjtrans( trans_t trans, obj_t* obj ); ``` Set both conjugation and transposition properties of `obj` using the corresponding components of `trans`. --- ```c void bli_obj_set_onlytrans( trans_t trans, obj_t* obj ); ``` Set the transposition property of `obj` using the transposition component of `trans`. Leaves the conjugation property of `obj` unchanged. --- ```c void bli_obj_set_conj( conj_t conj, obj_t* obj ); ``` Set the conjugation property of `obj` using `conj`. Leaves the transposition property of `obj` unchanged. --- ```c void bli_obj_apply_trans( trans_t trans, obj_t* obj ); ``` Apply `trans` to the transposition property of `obj`. For example, applying `BLIS_TRANSPOSE` will toggle the transposition property of `obj` but leave the conjugation property unchanged; applying `BLIS_CONJ_TRANSPOSE` will toggle both the conjugation and transposition properties of `obj`. --- ```c void bli_obj_apply_conj( conj_t conj, obj_t* obj ); ``` Apply `conj` to the conjugation property of `obj`. Specifically, applying `BLIS_CONJUGATE` will toggle the conjugation property of `obj`; applying `BLIS_NO_CONJUGATE` will have no effect. Leaves the transposition property of `obj` unchanged. --- ```c void bli_obj_set_struc( struc_t struc, obj_t* obj ); ``` Set the structure property of `obj` to `struc`. --- ```c void bli_obj_set_uplo( uplo_t uplo, obj_t* obj ); ``` Set the uplo (i.e., storage) property of `obj` to `uplo`. --- ```c void bli_obj_set_diag( diag_t diag, obj_t* obj ); ``` Set the diagonal property of `obj` to `diag`. --- ```c void bli_obj_set_diag_offset( doff_t doff, obj_t* obj ); ``` Set the diagonal offset property of `obj` to `doff`. Note that `doff_t` may be typecast from any signed integer. --- ## Other object function reference --- ```c void bli_obj_induce_trans( obj_t* obj ); ``` Modify the properties of `obj` to induce a logical transposition. This function operates without regard to whether the transposition property is already set. Therefore, depending on the circumstance, the caller may or may not wish to clear the transposition property after calling this function. --- ```c void bli_obj_alias_to( obj_t* a, obj_t* b ); ``` Initialize `b` to be a shallow copy, or alias, of `a`. For most people's purposes, this is equivalent to ``` b = a; ``` However, there is at least one field (one that only developers should be concerned with) that is not copied. --- ```c void bli_obj_real_part( obj_t* c, obj_t* r ); ``` Initialize `r` to be a modified shallow copy of `c` that refers only to the real part of `c`. --- ```c void bli_obj_imag_part( obj_t* c, obj_t* i ); ``` Initialize `i` to be a modified shallow copy of `c` that refers only to the imaginary part of `c`. # Computational function reference Notes for interpreting function descriptions: * `conj?(X)` and `trans?(X)` should be interpreted as predicates that capture the operand `X` with that object's `conj_t` or `trans_t` property applied. For example: * `conj?(x)` refers to a vector `x` that is either conjugated or used as given. * `trans?(A)` refers to a matrix `A` that is either transposed, conjugated _and_ transposed, conjugated only, or used as given. * Any operand marked with `conj()` is unconditionally conjugated. * Any operand marked with `^T` is unconditionally transposed. Similarly, any operand that is marked with `^H` is unconditionally conjugate-transposed. * All occurrences of `alpha`, `beta`, and `rho` parameters are scalars. * In general, unless otherwise noted, all object parameters must be stored using the same `num_t` datatype. In a few cases, one of the object parameters must be stored in the real projection of one of the other objects' types. (The real projection of a `num_t` datatype is the equivalent datatype in the real domain. So `BLIS_DOUBLE` is the real projection of `BLIS_DCOMPLEX`. `BLIS_DOUBLE` is also the real projection of itself.) * Many object API entries list the object properties that are honored/observed by the operation. For example, for `bli_gemv()`, the observed object properties are `trans?(A)` and `conj?(x)`. The former means that matrix `A` may be (optionally) marked for conjugation and/or tranaposition while the latter means that vector `x` may be (optionally) marked for conjugation. A function may also list `diagoff(A)` as an observe property, which means that it will accept general diagonal offsets. Similarly, `diag(A)` refers to recognizing the unit/non-unit structure of the diagonal and and `uplo(A)` refers to reading/updating only the stored triangle/trapezoid/region of `A`. --- ## Level-1v operations Level-1v operations perform various level-1 BLAS-like operations on vectors (hence the _v_). **Note**: Most level-1v operations have a corresponding level-1v kernel through which it is primarily implemented. --- #### addv ```c void bli_addv ( obj_t* x, obj_t* y, ); ``` Perform ``` y := y + conj?(x) ``` where `x` and `y` are vectors of length _n_. Observed object properties: `conj?(x)`. --- #### amaxv ```c void bli_amaxv ( obj_t* x, obj_t* index ); ``` Given a vector of length _n_, return the zero-based index of the element of vector `x` that contains the largest absolute value (or, in the complex domain, the largest complex modulus). The object `index` must be created of type `BLIS_INT`. If `NaN` is encountered, it is treated as if it were a valid value that was smaller than any other value in the vector. If more than one element contains the same maximum value, the index of the latter element is returned via `index`. Observed object properties: none. **Note:** This function attempts to mimic the algorithm for finding the element with the maximum absolute value in the netlib BLAS routines `i?amax()`. --- #### axpyv ```c void bli_axpyv ( obj_t* alpha, obj_t* x, obj_t* y ); ``` Perform ``` y := y + conj?(alpha) * conj?(x) ``` where `x` and `y` are vectors of length _n_, and `alpha` is a scalar. Observed object properties: `conj?(alpha)`, `conj?(x)`. --- #### axpbyv ``` void bli_axpbyv ( obj_t* alpha, obj_t* x, obj_t* beta, obj_t* y ) ``` Perform ``` y := conj?(beta) * y + conj?(alpha) * conj?(x) ``` where `x` and `y` are vectors of length _n_, and `alpha` and `beta` are scalars. Observed object properties: `conj?(alpha)`, `conj?(x)`. --- #### copyv ```c void bli_copyv ( obj_t* x, obj_t* y ); ``` Perform ``` y := conj?(x) ``` where `x` and `y` are vectors of length _n_. Observed object properties: `conj?(x)`. --- #### dotv ```c void bli_dotv ( obj_t* x, obj_t* y, obj_t* rho ); ``` Perform ``` rho := conj?(x)^T * conj?(y) ``` where `x` and `y` are vectors of length _n_, and `rho` is a scalar. Observed object properties: `conj?(x)`, `conj?(y)`. --- #### dotxv ```c void bli_dotxv ( obj_t* alpha, obj_t* x, obj_t* y, obj_t* beta, obj_t* rho ); ``` Perform ``` rho := conj?(beta) * rho + conj?(alpha) * conj?(x)^T * conj?(y) ``` where `x` and `y` are vectors of length _n_, and `alpha`, `beta`, and `rho` are scalars. Observed object properties: `conj?(alpha)`, `conj?(beta)`, `conj?(x)`, `conj?(y)`. --- #### invertv ```c void bli_invertv ( obj_t* x ); ``` Invert all elements of an _n_-length vector `x`. --- #### scalv ```c void bli_scalv ( obj_t* alpha, obj_t* x ); ``` Perform ``` x := conj?(alpha) * x ``` where `x` is a vector of length _n_, and `alpha` is a scalar. Observed object properties: `conj?(alpha)`. --- #### scal2v ```c void bli_scal2v ( obj_t* alpha, obj_t* x, obj_t* y ); ``` Perform ``` y := conj?(alpha) * conj?(x) ``` where `x` and `y` are vectors of length _n_, and `alpha` is a scalar. Observed object properties: `conj?(alpha)`, `conj?(x)`. --- #### setv ```c void bli_setv ( obj_t* alpha, obj_t* x ); ``` Perform ``` x := conj?(alpha) ``` That is, set all elements of an _n_-length vector `x` to scalar `conj?(alpha)`. Observed object properties: `conj?(alpha)`. --- #### setrv ```c void bli_setrv ( obj_t* alpha, obj_t* x ); ``` Perform ``` real(x) := real(alpha) ``` That is, given an _n_-length vector `x`, set all elements' real components to the real component of scalar `alpha`. (If `alpha` is complex, the imaginary component is ignored.) If `x` is real, this operation is equivalent to performing `setv` on `x` with the real component of scalar `alpha`. **Note**: This operation is provided for convenience as an object wrapper to `setv`, and thus it has no analogue in the [BLIS typed API](BLISTypedAPI). --- #### setiv ```c void bli_setiv ( obj_t* alpha, obj_t* x ); ``` Perform ``` imag(x) := real(alpha) ``` That is, given an _n_-length vector `x`, set all elements' imaginary components to the real component of scalar `alpha`. (If `alpha` is complex, the imaginary component is ignored.) If `x` is real, this operation is equivalent to a no-op. **Note**: This operation is provided for convenience as an object wrapper to `setv`, and thus it has no analogue in the [BLIS typed API](BLISTypedAPI). --- #### subv ```c void bli_subv ( obj_t* x, obj_t* y ); ``` Perform ``` y := y - conj?(x) ``` where `x` and `y` are vectors of length _n_. Observed object properties: `conj?(x)`. --- #### swapv ```c void bli_swapv ( obj_t* x, obj_t* y ); ``` Swap corresponding elements of two _n_-length vectors `x` and `y`. --- #### xpbyv ``` void bli_xpbyv ( obj_t* x, obj_t* beta, obj_t* y ) ``` Perform ``` y := conj?(beta) * y + conj?(x) ``` where `x` and `y` are vectors of length _n_, and `beta` is a scalar. Observed object properties: `conj?(beta)`, `conj?(x)`. --- ## Level-1d operations Level-1d operations perform various level-1 BLAS-like operations on matrix diagonals (hence the _d_). These operations are similar to their level-1m counterparts, except they only read and update matrix diagonals and therefore ignore the `uplo` property of their applicable input operands. Please see the descriptions for the corresponding level-1m operation for a description of the arguments. --- #### addd ```c void bli_addd ( obj_t* a, obj_t* b ); ``` Observed object properties: `diagoff(A)`, `diag(A)`, `trans?(A)`. --- #### axpyd ```c void bli_axpyd ( obj_t* alpha, obj_t* a, obj_t* b ); ``` Observed object properties: `conj?(alpha)`, `diagoff(A)`, `diag(A)`, `trans?(A)`. --- #### copyd ```c void bli_copyd ( obj_t* a, obj_t* b ); ``` Observed object properties: `diagoff(A)`, `diag(A)`, `trans?(A)`. --- #### invertd ```c void bli_invertd ( obj_t* a ); ``` Observed object properties: `diagoff(A)`. --- #### scald ```c void bli_scald ( obj_t* alpha, obj_t* a ); ``` Observed object properties: `conj?(alpha)`, `diagoff(A)`. --- #### scal2d ```c void bli_scal2d ( obj_t* alpha, obj_t* a, obj_t* b ); ``` Observed object properties: `conj?(alpha)`, `diagoff(A)`, `diag(A)`, `trans?(A)`. --- #### setd ```c void bli_setd ( obj_t* alpha, obj_t* a ); ``` Observed object properties: `conj?(alpha)`, `diagoff(A)`. --- #### setid ```c void bli_setid ( obj_t* alpha, obj_t* a ); ``` Set the imaginary components of every element along the diagonal of `a` to a scalar `alpha`. Note that the datatype of `alpha` must be the real projection of the datatype of `a`. Observed object properties: `diagoff(A)`. --- #### shiftd ```c void bli_shiftd ( obj_t* alpha, obj_t* a ); ``` Add a constant value `alpha` to every element along the diagonal of `a`. Observed object properties: `diagoff(A)`. --- #### subd ```c void bli_subd ( obj_t* a, obj_t* b ); ``` Observed object properties: `diagoff(A)`, `diag(A)`, `trans?(A)`. --- #### xpbyd ```c void bli_xpbyd ( obj_t* a, obj_t* beta, obj_t* b ); ``` Observed object properties: `conj?(beta)`, `diagoff(A)`, `diag(A)`, `trans?(A)`. --- ## Level-1m operations Level-1m operations perform various level-1 BLAS-like operations on matrices (hence the _m_). --- #### addm ```c void bli_addm ( obj_t* a, obj_t* b ); ``` Perform ``` B := B + trans?(A) ``` where `B` is an _m x n_ matrix, `A` is stored as a dense matrix, or lower- or upper-triangular/trapezoidal matrix with arbitrary diagonal offset and unit or non-unit diagonal. If `uplo(A)` indicates lower or upper storage, only that part of matrix `A` will be referenced and used to update `B`. Observed object properties: `diagoff(A)`, `diag(A)`, `uplo(A)`, `trans?(A)`. --- #### axpym ```c void bli_axpym ( obj_t* alpha, obj_t* a, obj_t* b ); ``` Perform ``` B := B + conj?(alpha) * trans?(A) ``` where `B` is an _m x n_ matrix, `A` is stored as a dense matrix, or lower- or upper-triangular/trapezoidal matrix with arbitrary diagonal offset and unit or non-unit diagonal. If `uplo(A)` indicates lower or upper storage, only that part of matrix `A` will be referenced and used to update `B`. Observed object properties: `conj?(alpha)`, `diagoff(A)`, `diag(A)`, `uplo(A)`, `trans?(A)`. --- #### copym ```c void bli_copym ( obj_t* a, obj_t* b ); ``` Perform ``` B := trans?(A) ``` where `B` is an _m x n_ matrix, `A` is stored as a dense matrix, or lower- or upper-triangular/trapezoidal matrix with arbitrary diagonal offset and unit or non-unit diagonal. If `uplo(A)` indicates lower or upper storage, only that part of matrix `A` will be referenced and used to update `B`. Observed object properties: `diagoff(A)`, `diag(A)`, `uplo(A)`, `trans?(A)`. --- #### scalm ```c void bli_scalm ( obj_t* alpha, obj_t* a ); ``` Perform ``` A := conj?(alpha) * A ``` where `A` is an _m x n_ matrix stored as a dense matrix, or lower- or upper-triangular/trapezoidal matrix with arbitrary diagonal offset. If `uplo(A)` indicates lower or upper storage, only that part of matrix `A` will be updated. Observed object properties: `conj?(alpha)`, `diagoff(A)`, `uplo(A)`. --- #### scal2m ```c void bli_scal2m ( obj_t* a, obj_t* b ); ``` Perform ``` B := conj?(alpha) * trans?(A) ``` where `B` is an _m x n_ matrix, `A` is stored as a dense matrix, or lower- or upper-triangular/trapezoidal matrix with arbitrary diagonal offset and unit or non-unit diagonal. If `uplo(A)` indicates lower or upper storage, only that part of matrix `A` will be referenced and used to update `B`. Observed object properties: `conj?(alpha)`, `diagoff(A)`, `diag(A)`, `uplo(A)`, `trans?(A)`. --- #### setm ```c void bli_setm ( obj_t* alpha, obj_t* a ); ``` Perform ``` A := conj?(alpha) ``` That is, set all elements of `A` to scalar `conj?(alpha)`, where `A` is an _m x n_ matrix stored as a dense matrix, or lower- or upper-triangular/trapezoidal matrix with arbitrary diagonal offset. If `uplo(A)` indicates lower or upper storage, only that part of matrix `A` will be updated. Observed object properties: `conj?(alpha)`, `diagoff(A)`, `diag(A)`, `uplo(A)`. --- #### setrm ```c void bli_setrm ( obj_t* alpha, obj_t* a ); ``` Perform ``` real(A) := real(alpha) ``` That is, given an _m x n_ matrix `A`, set all elements' real components to the real component of scalar `alpha`. (If `alpha` is complex, the imaginary component is ignored.) If `A` is real, this operation is equivalent to performing `setm` on `A` with the real component of scalar `alpha`. **Note**: This operation is provided for convenience as an object wrapper to `setm`, and thus it has no analogue in the [BLIS typed API](BLISTypedAPI). Observed object properties: `diagoff(A)`, `diag(A)`, `uplo(A)`. --- #### setim ```c void bli_setim ( obj_t* alpha, obj_t* a ); ``` Perform ``` imag(A) := real(alpha) ``` That is, given an _m x n_ matrix `A`, set all elements' imaginary components to the real component of scalar `alpha`. (If `alpha` is complex, the imaginary component is ignored.) If `A` is real, this operation is equivalent to a no-op. **Note**: This operation is provided for convenience as an object wrapper to `setm`, and thus it has no analogue in the [BLIS typed API](BLISTypedAPI). Observed object properties: `diagoff(A)`, `diag(A)`, `uplo(A)`. --- #### subm ```c void bli_subm ( obj_t* a, obj_t* b ); ``` Perform ``` B := B - trans?(A) ``` where `B` is an _m x n_ matrix, `A` is stored as a dense matrix, or lower- or upper-triangular/trapezoidal matrix with arbitrary diagonal offset and unit or non-unit diagonal. If `uplo(A)` indicates lower or upper storage, only that part of matrix `A` will be referenced and used to update `B`. Observed object properties: `diagoff(A)`, `diag(A)`, `uplo(A)`, `trans?(A)`. --- ## Level-1f operations Level-1f operations implement various fused combinations of level-1 operations (hence the _f_). **Note**: Each level-1f operation has a corresponding level-1f kernel through which it is primarily implemented. Level-1f kernels are employed when optimizing level-2 operations. --- #### axpy2v ```c void bli_axpy2v ( obj_t* alphax, obj_t* alphay, obj_t* x, obj_t* y, obj_t* z ); ``` Perform ``` y := y + conj?(alphax) * conj?(x) + conj?(alphay) * conj?(y) ``` where `x`, `y`, and `z` are vectors of length _m_. The kernel, if optimized, is implemented as a fused pair of calls to [axpyv](BLISObjectAPI.md#axpyv). Observed object properties: `conj?(alphax)`, `conj?(x)`, `conj?(alphay)`, `conj?(y)`. --- #### dotaxpyv ```c void bli_dotaxpyv ( obj_t* alpha, obj_t* x, obj_t* y, obj_t* rho, obj_t* z ); ``` Perform ``` rho := conj?(x)^T * conj?(y) y := y + conj?(alpha) * conj?(x) ``` where `x`, `y`, and `z` are vectors of length _m_ and `alpha` and `rho` are scalars. The kernel, if optimized, is implemented as a fusion of calls to [dotv](BLISObjectAPI.md#dotv) and [axpyv](BLISObjectAPI.md#axpyv). Observed object properties: `conj?(x)`, `conj?(y)`, `conj?(alpha)`. --- #### axpyf ```c void bli_axpyf ( obj_t* alpha, obj_t* a, obj_t* x, obj_t* y ); ``` Perform ``` y := y + alpha * conja(A) * conjx(x) ``` where `A` is an _m x b_ matrix, and `x` and `y` are vectors. The kernel, if optimized, is implemented as a fused series of calls to [axpyv](BLISObjectAPI.md#axpyv) where _b_ is less than or equal to an implementation-dependent fusing factor specific to `axpyf`. Observed object properties: `conj?(alpha)`, `conj?(A)`, `conj?(x)`. --- #### dotxf ```c void bli_dotxf ( obj_t* alpha, obj_t* a, obj_t* x, obj_t* beta, obj_t* y ); ``` Perform ``` y := conj?(beta) * y + conj?(alpha) * conj?(A)^T * conj?(x) ``` where `A` is an _m x b_ matrix, and `x` and `y` are vectors. The kernel, if optimized, is implemented as a fused series of calls to [dotxv](BLISObjectAPI.md#dotxv) where _b_ is less than or equal to an implementation-dependent fusing factor specific to `dotxf`. Observed object properties: `conj?(alpha)`, `conj?(beta)`, `conj?(A)`, `conj?(x)`. --- #### dotxaxpyf ```c void bli_dotxaxpyf ( obj_t* alpha, obj_t* a, obj_t* w, obj_t* x, obj_t* beta, obj_t* y, obj_t* z ); ``` Perform ``` y := conj?(beta) * y + conj?(alpha) * conj?(A)^T * conj?(w) z := z + conj?(alpha) * conj?(A) * conj?(x) ``` where `A` is an _m x b_ matrix, `w` and `z` are vectors of length _m_, `x` and `y` are vectors of length `b`, and `alpha` and `beta` are scalars. The kernel, if optimized, is implemented as a fusion of calls to [dotxf](BLISObjectAPI.md#dotxf) and [axpyf](BLISObjectAPI.md#axpyf). Observed object properties: `conj?(alpha)`, `conj?(beta)`, `conj?(A)`, `conj?(w)`, `conj?(x)`. ## Level-2 operations Level-2 operations perform various level-2 BLAS-like operations. --- #### gemv ```c void bli_gemv ( obj_t* alpha, obj_t* a, obj_t* x, obj_t* beta, obj_t* y ); ``` Perform ``` y := conj?(beta) * y + conj?(alpha) * trans?(A) * conj?(x) ``` where `trans?(A)` is an _m x n_ matrix, and `x` and `y` are vectors. Observed object properties: `conj?(alpha)`, `conj?(beta)`, `trans?(A)`, `conj?(x)`. --- #### ger ```c void bli_ger ( obj_t* alpha, obj_t* x, obj_t* y, obj_t* a ); ``` Perform ``` A := A + conj?(alpha) * conj?(x) * conj?(y)^T ``` where `A` is an _m x n_ matrix, and `x` and `y` are vectors of length _m_ and _n_, respectively. Observed object properties: `conj?(alpha)`, `conj?(x)`, `conj?(y)`. --- #### hemv ```c void bli_hemv ( obj_t* alpha, obj_t* a, obj_t* x, obj_t* beta, obj_t* y ); ``` Perform ``` y := conj?(beta) * y + conj?(alpha) * conj?(A) * conj?(x) ``` where `A` is an _m x m_ Hermitian matrix stored in the lower or upper triangle as specified by `uplo(A)`, and `x` and `y` are vectors of length _m_. Observed object properties: `conj?(alpha)`, `conj?(beta)`, `conj?(A)`, `uplo(A)`, `conj?(x)`. --- #### her ```c void bli_her ( obj_t* alpha, obj_t* x, obj_t* a ); ``` Perform ``` A := A + conj?(alpha) * conj?(x) * conj?(x)^H ``` where `A` is an _m x m_ Hermitian matrix stored in the lower or upper triangle as specified by `uplo(A)`, and `x` is a vector of length _m_. Observed object properties: `conj?(alpha)`, `uplo(A)`, `conj?(x)`. **Note:** The floating-point (`num_t`) type of `alpha` is always the real projection of the floating-point types of `x` and `A`. --- #### her2 ```c void bli_her2 ( obj_t* alpha, obj_t* x, obj_t* y, obj_t* a ); ``` Perform ``` A := A + alpha * conj?(x) * conj?(y)^H + conj(alpha) * conj?(y) * conj?(x)^H ``` where `A` is an _m x m_ Hermitian matrix stored in the lower or upper triangle as specified by `uplo(A)`, and `x` and `y` are vectors of length _m_. Observed object properties: `uplo(A)`, `conj?(x)`, `conj?(y)`. --- #### symv ```c void bli_symv ( obj_t* alpha, obj_t* a, obj_t* x, obj_t* beta, obj_t* y ); ``` Perform ``` y := conj?(beta) * y + conj?(alpha) * conj?(A) * conj?(x) ``` where `A` is an _m x m_ symmetric matrix stored in the lower or upper triangle as specified by `uplo(A)`, and `x` and `y` are vectors of length _m_. Observed object properties: `conj?(alpha)`, `conj?(beta)`, `conj?(A)`, `uplo(A)`, `conj?(x)`. --- #### syr ```c void bli_syr ( obj_t* alpha, obj_t* x, obj_t* a ); ``` Perform ``` A := A + conj?(alpha) * conj?(x) * conj?(x)^T ``` where `A` is an _m x m_ symmetric matrix stored in the lower or upper triangle as specified by `uploa`, and `x` is a vector of length _m_. Observed object properties: `conj?(alpha)`, `conj?(x)`. --- #### syr2 ```c void bli_syr2 ( obj_t* alpha, obj_t* x, obj_t* y, obj_t* a ); ``` Perform ``` A := A + alpha * conj?(x) * conj?(y)^T + conj(alpha) * conj?(y) * conj?(x)^T ``` where `A` is an _m x m_ symmetric matrix stored in the lower or upper triangle as specified by `uplo(A)`, and `x` and `y` are vectors of length _m_. Observed object properties: `uplo(A)`, `conj?(x)`, `conj?(y)`. --- #### trmv ```c void bli_trmv ( obj_t* alpha, obj_t* a, obj_t* x ); ``` Perform ``` x := conj?(alpha) * transa(A) * x ``` where `A` is an _m x m_ triangular matrix stored in the lower or upper triangle as specified by `uplo(A)` with unit/non-unit nature specified by `diag(A)`, and `x` is a vector of length _m_. Observed object properties: `conj?(alpha)`, `uplo(A)`, `trans?(A)`, `diag(A)`. --- #### trsv ```c void bli_trsv ( obj_t* alpha, obj_t* a, obj_t* y ); ``` Solve the linear system ``` transa(A) * x = alpha * y ``` where `A` is an _m x m_ triangular matrix stored in the lower or upper triangle as specified by `uplo(A)` with unit/non-unit nature specified by `diag(A)`, and `x` and `y` are vectors of length _m_. The right-hand side vector operand `y` is overwritten with the solution vector `x`. Observed object properties: `conj?(alpha)`, `uplo(A)`, `trans?(A)`, `diag(A)`. --- ## Level-3 operations Level-3 operations perform various level-3 BLAS-like operations. **Note**: Each All level-3 operations are implemented through a handful of level-3 microkernels. Please see the [Kernels Guide](KernelsHowTo.md) for more details. --- #### gemm ```c void bli_gemm ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c ); ``` Perform ``` C := beta * C + alpha * trans?(A) * trans?(B) ``` where `C` is an _m x n_ matrix, `trans?(A)` is an _m x k_ matrix, and `trans?(B)` is a _k x n_ matrix. Observed object properties: `trans?(A)`, `trans?(B)`. --- #### gemmt ```c void bli_gemmt ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c ); ``` Perform ``` C := beta * C + alpha * trans?(A) * trans?(B) ``` where `C` is an _m x m_ matrix, `trans?(A)` is an _m x k_ matrix, and `trans?(B)` is a _k x m_ matrix. This operation is similar to `bli_gemm()` except that it only updates the lower or upper triangle of `C` as specified by `uplo(C)`. Observed object properties: `trans?(A)`, `trans?(B)`, `uplo(C)`. --- #### hemm ```c void bli_hemm ( side_t sidea, obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c ); ``` Perform ``` C := beta * C + alpha * conj?(A) * trans?(B) ``` if `sidea` is `BLIS_LEFT`, or ``` C := beta * C + alpha * trans?(B) * conj?(A) ``` if `sidea` is `BLIS_RIGHT`, where `C` and `B` are _m x n_ matrices and `A` is a Hermitian matrix stored in the lower or upper triangle as specified by `uplo(A)`. When `sidea` is `BLIS_LEFT`, `A` is _m x m_, and when `sidea` is `BLIS_RIGHT`, `A` is _n x n_. Observed object properties: `uplo(A)`, `conj?(A)`, `trans?(B)`. --- #### herk ```c void bli_herk ( obj_t* alpha, obj_t* a, obj_t* beta, obj_t* c ); ``` Perform ``` C := beta * C + alpha * trans?(A) * trans?(A)^H ``` where `C` is an _m x m_ Hermitian matrix stored in the lower or upper triangle as specified by `uplo(C)` and `trans?(A)` is an _m x k_ matrix. Observed object properties: `trans?(A)`, `uplo(C)`. **Note:** The floating-point (`num_t`) types of `alpha` and `beta` are always the real projection of the floating-point types of `A` and `C`. --- #### her2k ```c void bli_her2k ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c ); ``` Perform ``` C := beta * C + alpha * trans?(A) * trans?(B)^H + conj(alpha) * trans?(B) * trans?(A)^H ``` where `C` is an _m x m_ Hermitian matrix stored in the lower or upper triangle as specified by `uplo(C)` and `trans?(A)` and `trans?(B)` are _m x k_ matrices. Observed object properties: `trans?(A)`, `trans?(B)`, `uplo(C)`. **Note:** The floating-point (`num_t`) type of `beta` is always the real projection of the floating-point types of `A` and `C`. --- #### symm ```c void bli_symm ( side_t sidea, obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c ); ``` Perform ``` C := beta * C + alpha * conj?(A) * trans?(B) ``` if `sidea` is `BLIS_LEFT`, or ``` C := beta * C + alpha * trans?(B) * conj?(A) ``` if `sidea` is `BLIS_RIGHT`, where `C` and `B` are _m x n_ matrices and `A` is a symmetric matrix stored in the lower or upper triangle as specified by `uplo(A)`. When `sidea` is `BLIS_LEFT`, `A` is _m x m_, and when `sidea` is `BLIS_RIGHT`, `A` is _n x n_. Observed object properties: `uplo(A)`, `conj?(A)`, `trans?(B)`. --- #### syrk ```c void bli_syrk ( obj_t* alpha, obj_t* a, obj_t* beta, obj_t* c ); ``` Perform ``` C := beta * C + alpha * trans?(A) * trans?(A)^T ``` where `C` is an _m x m_ symmetric matrix stored in the lower or upper triangle as specified by `uplo(A)` and `trans?(A)` is an _m x k_ matrix. Observed object properties: `trans?(A)`, `uplo(C)`. --- #### syr2k ```c void bli_syr2k ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c ); ``` Perform ``` C := beta * C + alpha * trans?(A) * trans?(B)^T + alpha * trans?(B) * trans?(A)^T ``` where `C` is an _m x m_ symmetric matrix stored in the lower or upper triangle as specified by `uplo(A)` and `trans?(A)` and `trans?(B)` are _m x k_ matrices. Observed object properties: `trans?(A)`, `trans?(B)`, `uplo(C)`. --- #### trmm ```c void bli_trmm ( side_t sidea, obj_t* alpha, obj_t* a, obj_t* b ); ``` Perform ``` B := alpha * transa(A) * B ``` if `sidea` is `BLIS_LEFT`, or ``` B := alpha * B * transa(A) ``` if `sidea` is `BLIS_RIGHT`, where `B` is an _m x n_ matrix and `A` is a triangular matrix stored in the lower or upper triangle as specified by `uplo(A)` with unit/non-unit nature specified by `diag(A)`. When `sidea` is `BLIS_LEFT`, `A` is _m x m_, and when `sidea` is `BLIS_RIGHT`, `A` is _n x n_. Observed object properties: `uplo(A)`, `trans?(A)`, `diag(A)`. --- #### trmm3 ```c void bli_trmm3 ( side_t sidea, obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c ); ``` Perform ``` C := beta * C + alpha * trans?(A) * trans?(B) ``` if `sidea` is `BLIS_LEFT`, or ``` C := beta * C + alpha * trans?(B) * trans?(A) ``` if `sidea` is `BLIS_RIGHT`, where `C` and `trans?(B)` are _m x n_ matrices and `A` is a triangular matrix stored in the lower or upper triangle as specified by `uplo(A)` with unit/non-unit nature specified by `diag(A)`. When `sidea` is `BLIS_LEFT`, `A` is _m x m_, and when `sidea` is `BLIS_RIGHT`, `A` is _n x n_. Observed object properties: `uplo(A)`, `trans?(A)`, `diag(A)`, `trans?(B)`. --- #### trsm ```c void bli_trsm ( side_t sidea, obj_t* alpha, obj_t* a, obj_t* b ); ``` Solve the linear system with multiple right-hand sides ``` transa(A) * X = alpha * B ``` if `sidea` is `BLIS_LEFT`, or ``` X * transa(A) = alpha * B ``` if `sidea` is `BLIS_RIGHT`, where `X` and `B` are an _m x n_ matrices and `A` is a triangular matrix stored in the lower or upper triangle as specified by `uplo(A)` with unit/non-unit nature specified by `diag(A)`. When `sidea` is `BLIS_LEFT`, `A` is _m x m_, and when `sidea` is `BLIS_RIGHT`, `A` is _n x n_. The right-hand side matrix operand `B` is overwritten with the solution matrix `X`. Observed object properties: `uplo(A)`, `trans?(A)`, `diag(A)`. --- ## Utility operations --- #### asumv ```c void bli_asumv ( obj_t* x, obj_t* asum ); ``` Compute the sum of the absolute values of the fundamental elements of vector `x`. The resulting sum is stored to `asum`. Observed object properties: none. **Note:** The floating-point type of `asum` is always the real projection of the floating-point type of `x`. **Note:** This function attempts to mimic the algorithm for computing the absolute vector sum in the netlib BLAS routines `*asum()`. --- #### norm1m #### normfm #### normim ```c void bli_norm[1fi]m ( obj_t* a, obj_t* norm ); ``` Compute the one-norm (`bli_norm1m()`), Frobenius norm (`bli_normfm()`), or infinity norm (`bli_normim()`) of the elements in an _m x n_ matrix `A`. If `uplo(A)` is `BLIS_LOWER` or `BLIS_UPPER` then `A` is assumed to be lower or upper triangular, respectively, with the main diagonal located at offset `diagoff(A)`. The resulting norm is stored to `norm`. Observed object properties: `diagoff(A)`, `diag(A)`, `uplo(A)`. **Note:** The floating-point (`num_t`) type of `norm` is always the real projection of the floating-point type of `x`. --- #### norm1v #### normfv #### normiv ```c void bli_norm[1fi]v ( obj_t* x, obj_t* norm ); ``` Compute the one-norm (`bli_norm1v()`), Frobenius norm (`bli_normfv()`), or infinity norm (`bli_normiv()`) of the elements in a vector `x` of length _n_. The resulting norm is stored to `norm`. Observed object properties: `diagoff(A)`, `diag(A)`, `uplo(A)`. **Note:** The floating-point (`num_t`) type of `norm` is always the real projection of the floating-point type of `x`. --- #### mkherm ```c void bli_mkherm ( obj_t* a ); ``` Make an _m x m_ matrix `A` explicitly Hermitian by copying the conjugate of the triangle specified by `uplo(A)` to the opposite triangle. Imaginary components of diagonal elements are explicitly set to zero. It is assumed that the diagonal offset of `A` is zero. Observed object properties: `uplo(A)`. --- #### mksymm ```c void bli_mksymm ( obj_t* a ); ``` Make an _m x m_ matrix `A` explicitly symmetric by copying the triangle specified by `uplo(A)` to the opposite triangle. It is assumed that the diagonal offset of `A` is zero. Observed object properties: `uplo(A)`. --- #### mktrim ```c void bli_mktrim ( obj_t* a ); ``` Make an _m x m_ matrix `A` explicitly triangular by preserving the triangle specified by `uplo(A)` and zeroing the elements in the opposite triangle. It is assumed that the diagonal offset of `A` is zero. Observed object properties: `uplo(A)`. --- #### fprintv ```c void bli_fprintv ( FILE* file, char* s1, obj_t* x, char* format, char* s2 ); ``` Print a vector `x` of length _m_ to file stream `file`, where `file` is a file pointer returned by the standard C library function `fopen()`. The caller may also pass in a global file pointer such as `stdout` or `stderr`. The strings `s1` and `s2` are printed immediately before and after the output (respectively), and the format specifier `format` is used to format the individual elements. For valid format specifiers, please see documentation for the standard C library function `printf()`. **Note:** For complex datatypes, the format specifier is applied to both the real and imaginary components **individually**. Therefore, you should use format specifiers such as `"%5.2f"`, but **not** `"%5.2f + %5.2f"`. --- #### fprintm ```c void bli_fprintm ( FILE* file, char* s1, obj_t* a, char* format, char* s2 ); ``` Print an _m x n_ matrix `A` to file stream `file`, where `file` is a file pointer returned by the standard C library function `fopen()`. The caller may also pass in a global file pointer such as `stdout` or `stderr`. The strings `s1` and `s2` are printed immediately before and after the output (respectively), and the format specifier `format` is used to format the individual elements. For valid format specifiers, please see documentation for the standard C library function `printf()`. **Note:** For complex datatypes, the format specifier is applied to both the real and imaginary components **individually**. Therefore, you should use format specifiers such as `"%5.2f"`, but **not** `"%5.2f + %5.2f"`. --- #### printv ```c void bli_printv ( char* s1, obj_t* x, char* format, char* s2 ); ``` Print a vector `x` of length _m_ to standard output. This function call is equivalent to calling `bli_fprintv()` with `stdout` as the file pointer. --- #### printm ```c void bli_printm ( char* s1, obj_t* a, char* format, char* s2 ); ``` Print an _m x n_ matrix `a` to standard output. This function call is equivalent to calling `bli_fprintm()` with `stdout` as the file pointer. --- #### randv ```c void bli_randv ( obj_t* x ); ``` Set the elements of a vector `x` of length _n_ to random values on the interval `[-1,1)`. **Note:** For complex datatypes, the real and imaginary components of each element are randomized individually and independently of one another. --- #### randm ```c void bli_randm ( obj_t* a ); ``` Set the elements of an _m x n_ matrix `A` to random values on the interval `[-1,1)`. Off-diagonal elements (in the triangle specified by `uplo(A)`) are scaled by `1.0/max(m,n)`. Observed object properties: `diagoff(A)`, `uplo(A)`. **Note:** For complex datatypes, the real and imaginary components of each off-diagonal element are randomized individually and independently of one another. **Note:** If `uplo(A)` is `BLIS_LOWER` or `BLIS_UPPER` and you plan to use this matrix to test `trsv` or `trsm`, additional scaling of the diagonal is recommended to ensure that the matrix is invertible. In this case, try using the [addd](BLISObjectAPI.md#addd) operation to increase the magnitude to the diagonal elements. --- #### sumsqv ```c void bli_sumsqv ( obj_t* x, obj_t* scale, obj_t* sumsq ); ``` Compute the sum of the squares of the elements in a vector `x` of length _n_. The result is computed in scaled form, and in such a way that it may be used repeatedly to accumulate the sum of the squares of several vectors. The function computes scale\_new and sumsq\_new such that ``` scale_new^2 * sumsq_new = x[0]^2 + x[1]^2 + ... x[m-1]^2 + scale_old^2 * sumsq_old ``` where, on entry, `scale` and `sumsq` contain `scale_old` and `sumsq_old`, respectively, and on exit, `scale` and `sumsq` contain `scale_new` and `sumsq_new`, respectively. **Note:** This function attempts to mimic the algorithm for computing the Frobenius norm in the netlib LAPACK routine `?lassq()`. **Note:** The floating-point (`num_t`) types of `scale` and `sumsq` are always the real projection of the floating-point type of `x`. --- #### getsc ```c void bli_getsc ( obj_t* chi, double* zeta_r, double* zeta_i ) ``` Copy the real and imaginary values from the scalar object `chi` to `zeta_r` and `zeta_i`. If `chi` is stored as a real type, then `zeta_i` is set to zero. (If `chi` is stored in single precision, the corresponding elements are typecast/promoted during the copy.) --- #### getijv ```c err_t bli_getijv ( dim_t i, obj_t* b, double* ar, double* ai ) ``` Copy the real and imaginary values at the `i`th element of vector object `x` to `ar` and `ai`. If elements of `x` are stored as real types, then only `ar` is overwritten and `ai` is left unchanged. (If `x` contains elements stored in single precision, the corresponding elements are typecast/promoted during the copy.) If either the element offset `i` is beyond the vector dimension of `x` or less than zero, the function returns `BLIS_FAILURE` without taking any action. Similarly, if `x` is a global scalar constant such as `BLIS_ONE`, the function returns `BLIS_FAILURE`. --- #### getijm ```c err_t bli_getijm ( dim_t i, dim_t j, obj_t* b, double* ar, double* ai ) ``` Copy the real and imaginary values at the (`i`,`j`) element of object `b` to `ar` and `ai`. If elements of `b` are stored as real types, then only `ar` is overwritten and `ai` is left unchanged. (If `b` contains elements stored in single precision, the corresponding elements are typecast/promoted during the copy.) If either the row offset `i` is beyond the _m_ dimension of `b` or less than zero, or column offset `j` is beyond the _n_ dimension of `b` or less than zero, the function returns `BLIS_FAILURE` without taking any action. Similarly, if `b` is a global scalar constant such as `BLIS_ONE`, the function returns `BLIS_FAILURE`. --- #### setsc ```c void bli_setsc ( double* zeta_r, double* zeta_i, obj_t* chi ); ``` Copy real and imaginary values `zeta_r` and `zeta_i` to the scalar object `chi`. If `chi` is stored as a real type, then `zeta_i` is ignored. (If `chi` is stored in single precision, the contents are typecast/demoted during the copy.) --- #### setijv ```c err_t bli_setijv ( double ar, double ai, dim_t i, obj_t* x ); ``` Copy real and imaginary values `ar` and `ai` to the `i`th element of vector object `x`. If elements of `x` are stored as real types, then only `ar` is copied and `ai` is ignored. (If `x` contains elements stored in single precision, the corresponding elements are typecast/demoted during the copy.) If the element offset `i` is beyond the vector dimension of `x` or less than zero, the function returns `BLIS_FAILURE` without taking any action. Similarly, if `x` is a global scalar constant such as `BLIS_ONE`, the function returns `BLIS_FAILURE`. --- #### setijm ```c err_t bli_setijm ( double ar, double ai, dim_t i, dim_t j, obj_t* b ); ``` Copy real and imaginary values `ar` and `ai` to the (`i`,`j`) element of object `b`. If elements of `b` are stored as real types, then only `ar` is copied and `ai` is ignored. (If `b` contains elements stored in single precision, the corresponding elements are typecast/demoted during the copy.) If either the row offset `i` is beyond the _m_ dimension of `b` or less than zero, or column offset `j` is beyond the _n_ dimension of `b` or less than zero, the function returns `BLIS_FAILURE` without taking any action. Similarly, if `b` is a global scalar constant such as `BLIS_ONE`, the function returns `BLIS_FAILURE`. --- #### eqsc ```c void bli_eqsc ( obj_t chi, obj_t psi, bool* is_eq ); ``` Perform an element-wise comparison between scalars `chi` and `psi` and store the boolean result in the `bool` pointed to by `is_eq`. If exactly one of `conj(chi)` or `conj(psi)` (but not both) indicate a conjugation, then one of the scalars will be implicitly conjugated for purposes of the comparision. Observed object properties: `conj?(chi)`, `conj?(psi)`. --- #### eqv ```c void bli_eqv ( obj_t x, obj_t y, bool* is_eq ); ``` Perform an element-wise comparison between vectors `x` and `y` and store the boolean result in the `bool` pointed to by `is_eq`. If exactly one of `conj(x)` or `conj(y)` (but not both) indicate a conjugation, then one of the vectors will be implicitly conjugated for purposes of the comparision. Observed object properties: `conj?(x)`, `conj?(y)`. --- #### eqm ```c void bli_eqm ( obj_t a, obj_t b, bool* is_eq ); ``` Perform an element-wise comparison between matrices `A` and `B` and store the boolean result in the `bool` pointed to by `is_eq`. Here, `A` is stored as a dense matrix, or lower- or upper-triangular/trapezoidal matrix with arbitrary diagonal offset and unit or non-unit diagonal. If `diag(A)` indicates a unit diagonal, the diagonals of both matrices will be ignored for purposes of the comparision. If `uplo(A)` indicates lower or upper storage, only that part of both matrices `A` and `B` will be referenced. If exactly one of `trans(A)` or `trans(B)` (but not both) indicate a transposition, then one of the matrices will be transposed for purposes of the comparison. Similarly, if exactly one of `trans(A)` or `trans(B)` (but not both) indicate a conjugation, then one of the matrices will be implicitly conjugated for purposes of the comparision. Observed object properties: `diagoff(A)`, `diag(A)`, `uplo(A)`, `trans?(A)`, `trans?(B)`. # Query function reference BLIS allows applications to query information about how BLIS was configured. The `bli_info_` API provides several categories of query routines. Most values are returned as a `gint_t`, which is a signed integer. The size of this integer can be queried through a special routine that returns the size in a character string: ```c char* bli_info_get_int_type_size_str( void ); ``` **Note:** All of the `bli_info_` functions are **always** thread-safe, no matter how BLIS was configured. ## General library information The following routine returns the address the full BLIS version string: ```c char* bli_info_get_version_str( void ); ``` ## Specific configuration The following routine returns a unique ID of type `arch_t` that identifies the current current active configuration: ```c arch_t bli_arch_query_id( void ); ``` This is most useful when BLIS is configured with multiple configurations. (When linking to multi-configuration builds of BLIS, you don't know for sure which configuration will be used until runtime since the configuration-specific parameters are not loaded until after calling a hueristic to detect the hardware--usually based the `CPUID` instruction.) Once the configuration's ID is known, it can be used to query a string that contains the name of the configuration: ```c char* bli_arch_string( arch_t id ); ``` ## General configuration The following routines return various general-purpose constants that affect the entire framework. All of these settings default to sane values, which can then be overridden by the configuration in [bli\_config.h](ConfigurationHowTo#bli_configh). If they are absent from a particular configuration's `bli_config.h` header file, then the default value is used, as specified in [frame/include/bli_config_macro_defs.h](https://github.com/flame/blis/blob/master/frame/include/bli_config_macro_defs.h). ```c gint_t bli_info_get_int_type_size( void ); gint_t bli_info_get_num_fp_types( void ); gint_t bli_info_get_max_type_size( void ); gint_t bli_info_get_page_size( void ); gint_t bli_info_get_simd_num_registers( void ); gint_t bli_info_get_simd_size( void ); gint_t bli_info_get_simd_align_size( void ); gint_t bli_info_get_stack_buf_max_size( void ); gint_t bli_info_get_stack_buf_align_size( void ); gint_t bli_info_get_heap_addr_align_size( void ); gint_t bli_info_get_heap_stride_align_size( void ); gint_t bli_info_get_pool_addr_align_size( void ); gint_t bli_info_get_enable_stay_auto_init( void ); gint_t bli_info_get_enable_blas( void ); gint_t bli_info_get_blas_int_type_size( void ); ``` ## Kernel information ### Micro-kernel implementation type query The following routines allow the caller to obtain a string that identifies the implementation type of each microkernel that is currently active (ie: part of the current active configuration, as identified bi `bli_arch_query_id()`). ```c char* bli_info_get_gemm_ukr_impl_string( ind_t method, num_t dt ) char* bli_info_get_gemmtrsm_l_ukr_impl_string( ind_t method, num_t dt ) char* bli_info_get_gemmtrsm_u_ukr_impl_string( ind_t method, num_t dt ) char* bli_info_get_trsm_l_ukr_impl_string( ind_t method, num_t dt ) char* bli_info_get_trsm_u_ukr_impl_string( ind_t method, num_t dt ) ``` Possible implementation (ie: the `ind_t method` argument) types are: * `BLIS_1M`: Implementation based on the 1m method. (This is the default induced method when real domain kernels are present but complex kernels are missing.) * `BLIS_NAT`: Implementation based on "native" execution (ie: NOT an induced method). Possible microkernel types (ie: the return values for `bli_info_get_*_ukr_impl_string()`) are: * `BLIS_REFERENCE_UKERNEL` (`"refrnce"`): This value is returned when the queried microkernel is provided by the reference implementation. * `BLIS_VIRTUAL_UKERNEL` (`"virtual"`): This value is returned when the queried microkernel is driven by a the "virtual" microkernel provided by an induced method. This happens for any `method` value that is not `BLIS_NAT` (ie: native), but only applies to the complex domain. * `BLIS_OPTIMIZED_UKERNEL` (`"optimzd"`): This value is returned when the queried microkernel is provided by an implementation that is neither reference nor virtual, and thus we assume the kernel author would deem it to be "optimized". Such a microkernel may not be optimal in the literal sense of the word, but nonetheless is _intended_ to be optimized, at least relative to the reference microkernels. * `BLIS_NOTAPPLIC_UKERNEL` (`"notappl"`): This value is returned usually when performing a `gemmtrsm` or `trsm` microkernel type query for any `method` value that is not `BLIS_NAT` (ie: native). That is, induced methods cannot be (purely) used on `trsm`-based microkernels because these microkernels perform more a triangular inversion, which is not matrix multiplication. ## Clock functions --- #### clock ```c double bli_clock ( void ); ``` Return the amount of time that has elapsed since some fixed time in the past. The return values of `bli_clock()` typically feature nanosecond precision, though this is not guaranteed. **Note:** On Linux, `bli_clock()` is implemented in terms of `clock_gettime()` using the `clockid_t` value of `CLOCK_MONOTONIC`. On OS X, `bli_clock` is implemented in terms of `mach_absolute_time()`. And on Windows, `bli_clock` is implemented in terms of `QueryPerformanceFrequency()`. Please see [frame/base/bli_clock.c](https://github.com/flame/blis/blob/master/frame/base/bli_clock.c) for more details. **Note:** This function is returns meaningless values when BLIS is configured with `--disable-system`. --- #### clock_min_diff ```c double bli_clock_min_diff ( double time_prev_min, double time_start ); ``` This function computes an intermediate value, `time_diff`, equal to `bli_clock() - time_start`, and then tentatively prepares to return the minimum value of `time_diff` and `time_min`. If that minimum value is extremely small (close to zero), the function returns `time_min` instead. This function is meant to be used in conjuction with `bli_clock()` for performance timing within applications--specifically in loops where only the fastest timing is of interest. For example: ```c double t_save = DBL_MAX; for( i = 0; i < 3; ++i ) { double t = bli_clock(); bli_gemm( ... ); t_save = bli_clock_min_diff( t_save, t ); } double gflops = ( 2.0 * m * k * n ) / ( t_save * 1.0e9 ); ``` This code calls `bli_gemm()` three times and computes the performance, in GFLOPS, of the fastest of the three executions. --- # Example code BLIS provides lots of example code in the [examples/oapi](https://github.com/flame/blis/tree/master/examples/oapi) directory of the BLIS source distribution. The example code in this directory is set up like a tutorial, and so we recommend starting from the beginning. Topics include creating and managing objects, printing vectors and matrices, setting and querying object properties, and calling a representative subset of the computational level-1v, -1m, -2, -3, and utility operations documented above. Please read the `README` contained within the `examples/oapi` directory for further details. blis-0.9.0/docs/BLISTypedAPI.md000066400000000000000000002075061422157504600160340ustar00rootroot00000000000000# Contents * **[Contents](BLISTypedAPI.md#contents)** * **[Operation index](BLISTypedAPI.md#operation-index)** * **[Introduction](BLISTypedAPI.md#introduction)** * [BLIS types](BLISTypedAPI.md#blis-types) * [Integer-based types](BLISTypedAPI.md#integer-based-types) * [Floating-point types](BLISTypedAPI.md#floating-point-types) * [Enumerated parameter types](BLISTypedAPI.md#enumerated-parameter-types) * [Basic vs expert interfaces](BLISTypedAPI.md#basic-vs-expert-interfaces) * [Context type](BLISTypedAPI.md#context-type) * [Runtime type](BLISTypedAPI.md#runtime-type) * [BLIS header file](BLISTypedAPI.md#blis-header-file) * [Initialization and cleanup](BLISTypedAPI.md#initialization-and-cleanup) * **[Computational function reference](BLISTypedAPI.md#computational-function-reference)** * [Level-1v operations](BLISTypedAPI.md#level-1v-operations) * [Level-1d operations](BLISTypedAPI.md#level-1d-operations) * [Level-1m operations](BLISTypedAPI.md#level-1m-operations) * [Level-1f operations](BLISTypedAPI.md#level-1f-operations) * [Level-2 operations](BLISTypedAPI.md#level-2-operations) * [Level-3 operations](BLISTypedAPI.md#level-3-operations) * [Utility operations](BLISTypedAPI.md#utility-operations) * [Level-3 microkernels](BLISTypedAPI.md#level-3-microkernels) * **[Query function reference](BLISTypedAPI.md#query-function-reference)** * [General library information](BLISTypedAPI.md#general-library-information) * [Specific configuration](BLISTypedAPI.md#specific-configuration) * [General configuration](BLISTypedAPI.md#general-configuration) * [Kernel information](BLISTypedAPI.md#kernel-information) * [Clock functions](BLISTypedAPI.md#clock-functions) * **[Example code](BLISTypedAPI.md#example-code)** # Operation index This index provides a quick way to jump directly to the description for each operation discussed later in the [Computational function reference](BLISTypedAPI.md#computational-function-reference) section: * **[Level-1v](BLISTypedAPI.md#level-1v-operations)**: Operations on vectors: * [addv](BLISTypedAPI.md#addv), [amaxv](BLISTypedAPI.md#amaxv), [axpyv](BLISTypedAPI.md#axpyv), [axpbyv](BLISTypedAPI.md#axpbyv), [copyv](BLISTypedAPI.md#copyv), [dotv](BLISTypedAPI.md#dotv), [dotxv](BLISTypedAPI.md#dotxv), [invertv](BLISTypedAPI.md#invertv), [scal2v](BLISTypedAPI.md#scal2v), [scalv](BLISTypedAPI.md#scalv), [setv](BLISTypedAPI.md#setv), [subv](BLISTypedAPI.md#subv), [swapv](BLISTypedAPI.md#swapv), [xpbyv](BLISTypedAPI.md#xpbyv) * **[Level-1d](BLISTypedAPI.md#level-1d-operations)**: Element-wise operations on matrix diagonals: * [addd](BLISTypedAPI.md#addd), [axpyd](BLISTypedAPI.md#axpyd), [copyd](BLISTypedAPI.md#copyd), [invertd](BLISTypedAPI.md#invertd), [scald](BLISTypedAPI.md#scald), [scal2d](BLISTypedAPI.md#scal2d), [setd](BLISTypedAPI.md#setd), [setid](BLISTypedAPI.md#setid), [shiftd](BLISTypedAPI.md#shiftd), [subd](BLISTypedAPI.md#subd), [xpbyd](BLISTypedAPI.md#xpbyd) * **[Level-1m](BLISTypedAPI.md#level-1m-operations)**: Element-wise operations on matrices: * [addm](BLISTypedAPI.md#addm), [axpym](BLISTypedAPI.md#axpym), [copym](BLISTypedAPI.md#copym), [scalm](BLISTypedAPI.md#scalm), [scal2m](BLISTypedAPI.md#scal2m), [setm](BLISTypedAPI.md#setm), [subm](BLISTypedAPI.md#subm) * **[Level-1f](BLISTypedAPI.md#level-1f-operations)**: Fused operations on multiple vectors: * [axpy2v](BLISTypedAPI.md#axpy2v), [dotaxpyv](BLISTypedAPI.md#dotaxpyv), [axpyf](BLISTypedAPI.md#axpyf), [dotxf](BLISTypedAPI.md#dotxf), [dotxaxpyf](BLISTypedAPI.md#dotxaxpyf) * **[Level-2](BLISTypedAPI.md#level-2-operations)**: Operations with one matrix and (at least) one vector operand: * [gemv](BLISTypedAPI.md#gemv), [ger](BLISTypedAPI.md#ger), [hemv](BLISTypedAPI.md#hemv), [her](BLISTypedAPI.md#her), [her2](BLISTypedAPI.md#her2), [symv](BLISTypedAPI.md#symv), [syr](BLISTypedAPI.md#syr), [syr2](BLISTypedAPI.md#syr2), [trmv](BLISTypedAPI.md#trmv), [trsv](BLISTypedAPI.md#trsv) * **[Level-3](BLISTypedAPI.md#level-3-operations)**: Operations with matrices that are multiplication-like: * [gemm](BLISTypedAPI.md#gemm), [hemm](BLISTypedAPI.md#hemm), [herk](BLISTypedAPI.md#herk), [her2k](BLISTypedAPI.md#her2k), [symm](BLISTypedAPI.md#symm), [syrk](BLISTypedAPI.md#syrk), [syr2k](BLISTypedAPI.md#syr2k), [trmm](BLISTypedAPI.md#trmm), [trmm3](BLISTypedAPI.md#trmm3), [trsm](BLISTypedAPI.md#trsm) * **[Utility](BLISTypedAPI.md#Utility-operations)**: Miscellaneous operations on matrices and vectors: * [asumv](BLISTypedAPI.md#asumv), [norm1v](BLISTypedAPI.md#norm1v), [normfv](BLISTypedAPI.md#normfv), [normiv](BLISTypedAPI.md#normiv), [norm1m](BLISTypedAPI.md#norm1m), [normfm](BLISTypedAPI.md#normfm), [normim](BLISTypedAPI.md#normim), [mkherm](BLISTypedAPI.md#mkherm), [mksymm](BLISTypedAPI.md#mksymm), [mktrim](BLISTypedAPI.md#mktrim), [fprintv](BLISTypedAPI.md#fprintv), [fprintm](BLISTypedAPI.md#fprintm),[printv](BLISTypedAPI.md#printv), [printm](BLISTypedAPI.md#printm), [randv](BLISTypedAPI.md#randv), [randm](BLISTypedAPI.md#randm), [sumsqv](BLISTypedAPI.md#sumsqv), [getsc](BLISTypedAPI.md#getsc), [getijv](BLISTypedAPI.md#getijv), [getijm](BLISTypedAPI.md#getijm), [setsc](BLISTypedAPI.md#setsc), [setijv](BLISTypedAPI.md#setijv), [setijm](BLISTypedAPI.md#setijm), [eqsc](BLISTypedAPI.md#eqsc), [eqv](BLISTypedAPI.md#eqv), [eqm](BLISTypedAPI.md#eqm) # Introduction This document summarizes one of the primary native APIs in BLIS--the "typed" API. Here, we also discuss BLIS-specific type definitions, header files, and prototypes to auxiliary functions. This document also includes APIs to key kernels which are used to accelerate and optimize various level-2 and level-3 operations, though the [Kernels Guide](KernelsHowTo.md) goes into more detail, especially for level-3 microkernels. There are many functions that BLIS implements that are not listed here, either because they are lower-level functions, or they are considered for use primarily by developers and experts. For curious readers, the typed API was given its name (a) because it exposes the floating-point types in the names of its functions, and (b) to contrast it with the other native API in BLIS, the object API, which is [documented here](BLISObjectAPI.md). (The third API supported by BLIS is the BLAS compatibility layer, which mimics conventional Fortran-77 BLAS.) In general, this document should be treated more as a reference than a place to learn how to use BLIS in your application. Thus, we highly encourage all readers to first study the [example code](BLISTypedAPI.md#example-code) provided within the BLIS source distribution. ## BLIS types The following tables list various types used throughout the BLIS typed API. ### Integer-based types | BLIS integer type | Type definition | Used to represent... | |:------------------|:-----------------------|:---------------------------------------------------------------------| | `gint_t` | `int32_t` or `int64_t` | general-purpose signed integer; used to define signed integer types. | | `dim_t` | `gint_t` | matrix and vector dimensions. | | `inc_t` | `gint_t` | matrix row/column strides and vector increments. | | `doff_t` | `gint_t` | matrix diagonal offset: if _k_ < 0, diagonal begins at element (-_k_,0); otherwise diagonal begins at element (0,_k_). | ### Floating-point types | BLIS type | BLIS char | Type definition | Used to represent... | |:-----------|:----------|:---------------------------------------|:-------------------------------------| | `float` | `s` | _N/A_ | single-precision real numbers | | `double` | `d` | _N/A_ | double-precision real numbers | | `scomplex` | `c` | `struct { float real; float imag; }` | single-precision complex numbers | | `dcomplex` | `z` | `struct { double real; double imag; }` | double-precision complex numbers | ### Enumerated parameter types | `trans_t` | Semantic meaning: Corresponding matrix operand... | |:-------------------------|:--------------------------------------------------| | `BLIS_NO_TRANSPOSE` | will be used as given. | | `BLIS_TRANSPOSE` | will be implicitly transposed. | | `BLIS_CONJ_NO_TRANSPOSE` | will be implicitly conjugated. | | `BLIS_CONJ_TRANSPOSE` | will be implicitly transposed _and_ conjugated. | | `conj_t` | Semantic meaning: Corresponding matrix/vector operand... | |:---------------------|:---------------------------------------------------------| | `BLIS_NO_CONJUGATE` | will be used as given. | | `BLIS_CONJUGATE` | will be implicitly conjugated. | | `side_t` | Semantic meaning: Corresponding matrix operand... | |:-------------|:---------------------------------------------------| | `BLIS_LEFT` | appears on the left. | | `BLIS_RIGHT` | appears on the right. | | `uplo_t` | Semantic meaning: Corresponding matrix operand... | |:-------------|:--------------------------------------------------| | `BLIS_LOWER` | is stored in (and will be accessed only from) the lower triangle. | | `BLIS_UPPER` | is stored in (and will be accessed only from) the upper triangle. | | `BLIS_DENSE` | is stored as a full matrix (ie: in both triangles). | | `diag_t` | Semantic meaning: Corresponding matrix operand... | |:--------------------|:--------------------------------------------------| | `BLIS_NONUNIT_DIAG` | has a non-unit diagonal that should be explicitly read from. | | `BLIS_UNIT_DIAG` | has a unit diagonal that should be implicitly assumed (and not read from). | ### Basic vs expert interfaces The functions listed in this document belong to the "basic" interface subset of the BLIS typed API. There is a companion "expert" interface that mirrors the basic interface, except that it also contains at least one additional parameter that is only of interest to experts and library developers. The expert interfaces use the same name as the basic function names, except for an additional "_ex" suffix. For example, the basic interface for `gemm` is ```c void bli_?gemm ( trans_t transa, trans_t transb, dim_t m, dim_t n, dim_t k, ctype* alpha, ctype* a, inc_t rsa, inc_t csa, ctype* b, inc_t rsb, inc_t csb, ctype* beta, ctype* c, inc_t rsc, inc_t csc ); ``` while the expert interface is: ```c void bli_?gemm_ex ( trans_t transa, trans_t transb, dim_t m, dim_t n, dim_t k, ctype* alpha, ctype* a, inc_t rsa, inc_t csa, ctype* b, inc_t rsb, inc_t csb, ctype* beta, ctype* c, inc_t rsc, inc_t csc, cntx_t* cntx, rntm_t* rntm ); ``` The expert interface contains two additional parameters: a `cntx_t*` and `rntm_t*`. Note that calling a function from the expert interface with the `cntx_t*` and `rntm_t*` arguments each set to `NULL` is equivalent to calling the corresponding basic interface. Specifically, a `NULL` value passed in for the `cntx_t*` results in a valid context being queried from BLIS, and a `NULL` value passed in for the `rntm_t*` results in the current global settings for multithreading to be used. ## Context type In general, it is permissible to pass in `NULL` for a `cntx_t*` parameter when calling an expert interface such as `bli_dgemm_ex()`. However, there are cases where `NULL` values are not accepted and may result in a segmentation fault. Specifically, the `cntx_t*` argument appears in the interfaces to the `gemm`, `trsm`, and `gemmtrsm` [level-3 microkernels](KernelsHowTo.md#level-3) along with all [level-1v](KernelsHowTo.md#level-1v) and [level-1f](KernelsHowTo.md#level-1f) kernels. There, as a general rule, a valid pointer must be passed in. Whenever a valid context is needed, the developer may query a default context from the global kernel structure (if a context is not already available in the current scope): ```c cntx_t* bli_gks_query_cntx( void ); ``` When BLIS is configured to target a configuration family (e.g. `intel64`, `x86_64`), `bli_gks_query_cntx()` will use `cpuid` or an equivalent heuristic to select and and return the appropriate context. When BLIS is configured to target a singleton sub-configuration (e.g. `haswell`, `skx`), `bli_gks_query_cntx()` will unconditionally return a pointer to the context appropriate for the targeted configuration. ## Runtime type When calling one of the expert interfaces, a `rntm_t` (runtime) object can be used to convey a thread-local request for parallelism to the underlying implementation. Runtime objects are thread-safe by nature when they are declared statically as a stack variable (or allocated via `malloc()`), initialized, and then passed into the expert interface of interest. Notice that runtime objects have no analogue in most BLAS libraries, where you are forced to specify parallelism at a global level (usually via environment variables). For more information on using `rntm_t` objects, please read the [Multithreading](Multithreading.md) documentation, paying close attention to the section on [local setting of parallelism](Multithreading.md#locally-at-runtime). ## BLIS header file All BLIS definitions and prototypes may be included in your C source file by including a single header file: ```c #include "blis.h" ``` ## Initialization and Cleanup As of [9804adf](https://github.com/flame/blis/commit/9804adfd405056ec332bb8e13d68c7b52bd3a6c1), BLIS no longer requires explicit initialization and finalization at runtime. In other words, users do not need to call `bli_init()` before the application can make use of the library (and `bli_finalize()` after the application is finished with the library). Instead, all computational operations (and some non-computational functions) in BLIS will initialize the library on behalf of the user if it has not already been initialized. This change was made to simplify the user experience. Application developers should keep in mind, however, that this new self-initialization regime implies the following: unless the library is *explicitly* finalized via `bli_finalize()`, it will, once initialized, remain initialized for the life of the application. This is likely not a problem in the vast majority of cases. However, a memory-constrained application that performs all of its DLA up-front, for example, may wish to explicitly finalize the library after BLIS is no longer needed in order to free up memory for other purposes. Similarly, an expert user may call `bli_init()` manually in order to control when the overhead of library initialization is incurred, even though the library would have self-initialized. The interfaces to `bli_init()` and `bli_finalize()` are quite simple; they require no arguments and return no values: ```c void bli_init( void ); void bli_finalize( void ); ``` # Computational function reference Notes for interpreting the following prototypes: * Any occurrence of `?` should be replaced with `s`, `d`, `c`, or `z` to form an actual function name. * Any occurrence of `ctype` should be replaced with the actual C type corresponding to the datatype instance in question, while `rtype` should be replaced by the real projection of `ctype`. For example: * If we consider the prototype for `bli_zaxpyv()` below, `ctype` refers to `dcomplex`. * If we consider the prototype for `bli_znormfv()` below, `ctype` refers to `dcomplex` while `rtype` refers to `double`. * Any occurrence of `itype` should be replaced with the general-purpose signed integer type, `gint_t`. * All vector arguments have associated increments that proceed them, typically listed as `incX` for a given vector `x`. The semantic meaning of a vector increment is "the distance, in units of elements, between any two adjacent elements in the vector." * All matrix arguments have associated row and column strides arguments that proceed them, typically listed as `rsX` and `csX` for a given matrix `X`. Row strides are always listed first, and column strides are always listed second. The semantic meaning of a row stride is "the distance, in units of elements, to the next row (within a column)," and the meaning of a column stride is "the distance, in units of elements, to the next column (within a row)." Thus, unit row stride implies column-major storage and unit column stride implies row-major storage. Notes for interpreting function descriptions: * `conjX()` and `transX()` should be interpreted as predicates that capture the operand X with any value of `conj_t` or `trans_t` applied. For example: * `conjx(x)` refers to a vector `x` that is either conjugated or used as given. * `transa(A)` refers to a matrix `A` that is either transposed, conjugated _and_ transposed, conjugated only, or used as given. * Any operand marked with `conj()` is unconditionally conjugated. * Any operand marked with `^T` is unconditionally transposed. Similarly, any operand that is marked with `^H` is unconditionally conjugate-transposed. * All occurrences of `alpha`, `beta`, and `rho` parameters are scalars. --- ## Level-1v operations Level-1v operations perform various level-1 BLAS-like operations on vectors (hence the _v_). **Note**: Most level-1v operations have a corresponding level-1v kernel through which it is primarily implemented. --- #### addv ```c void bli_?addv ( conj_t conjx, dim_t n, ctype* x, inc_t incx, ctype* y, inc_t incy ); ``` Perform ``` y := y + conjx(x) ``` where `x` and `y` are vectors of length _n_. --- #### amaxv ```c void bli_?amaxv ( dim_t n, ctype* x, inc_t incx, dim_t* index ); ``` Given a vector of length _n_, return the zero-based index `index` of the element of vector `x` that contains the largest absolute value (or, in the complex domain, the largest complex modulus). If `NaN` is encountered, it is treated as if it were a valid value that was smaller than any other value in the vector. If more than one element contains the same maximum value, the index of the latter element is returned via `index`. **Note:** This function attempts to mimic the algorithm for finding the element with the maximum absolute value in the netlib BLAS routines `i?amax()`. --- #### axpyv ```c void bli_?axpyv ( conj_t conjx, dim_t n, ctype* alpha, ctype* x, inc_t incx, ctype* y, inc_t incy ); ``` Perform ``` y := y + alpha * conjx(x) ``` where `x` and `y` are vectors of length _n_, and `alpha` is a scalar. --- #### axpbyv ```c void bli_?axpbyv ( conj_t conjx, dim_t n, ctype* alpha, ctype* x, inc_t incx, ctype* beta, ctype* y, inc_t incy ) ``` Perform ``` y := beta * y + alpha * conjx(x) ``` where `x` and `y` are vectors of length _n_, and `alpha` and `beta` are scalars. --- #### copyv ```c void bli_?copyv ( conj_t conjx, dim_t n, ctype* x, inc_t incx, ctype* y, inc_t incy ); ``` Perform ``` y := conjx(x) ``` where `x` and `y` are vectors of length _n_. --- #### dotv ```c void bli_?dotv ( conj_t conjx, conj_t conjy, dim_t n, ctype* x, inc_t incx, ctype* y, inc_t incy, ctype* rho ); ``` Perform ``` rho := conjx(x)^T * conjy(y) ``` where `x` and `y` are vectors of length _n_, and `rho` is a scalar. --- #### dotxv ```c void bli_?dotxv ( conj_t conjx, conj_t conjy, dim_t n, ctype* alpha, ctype* x, inc_t incx, ctype* y, inc_t incy, ctype* beta, ctype* rho ); ``` Perform ``` rho := beta * rho + alpha * conjx(x)^T * conjy(y) ``` where `x` and `y` are vectors of length _n_, and `alpha`, `beta`, and `rho` are scalars. --- #### invertv ```c void bli_?invertv ( dim_t n, ctype* x, inc_t incx ); ``` Invert all elements of an _n_-length vector `x`. --- #### scalv ```c void bli_?scalv ( conj_t conjalpha, dim_t n, ctype* alpha, ctype* x, inc_t incx ); ``` Perform ``` x := conjalpha(alpha) * x ``` where `x` is a vector of length _n_, and `alpha` is a scalar. --- #### scal2v ```c void bli_?scal2v ( conj_t conjx, dim_t n, ctype* alpha, ctype* x, inc_t incx, ctype* y, inc_t incy ); ``` Perform ``` y := alpha * conjx(x) ``` where `x` and `y` are vectors of length _n_, and `alpha` is a scalar. --- #### setv ```c void bli_?setv ( conj_t conjalpha, dim_t n, ctype* alpha, ctype* x, inc_t incx ); ``` Perform ``` x := conjalpha(alpha) ``` That is, set all elements of an _n_-length vector `x` to scalar `conjalpha(alpha)`. --- #### subv ```c void bli_?subv ( conj_t conjx, dim_t n, ctype* x, inc_t incx, ctype* y, inc_t incy ); ``` Perform ``` y := y - conjx(x) ``` where `x` and `y` are vectors of length _n_. --- #### swapv ```c void bli_?swapv ( dim_t n, ctype* x, inc_t incx, ctype* y, inc_t incy ); ``` Swap corresponding elements of two _n_-length vectors `x` and `y`. --- #### xpbyv ```c void bli_?xpbyv ( conj_t conjx, dim_t n, ctype* x, inc_t incx, ctype* beta, ctype* y, inc_t incy ) ``` Perform ``` y := beta * y + conjx(x) ``` where `x` and `y` are vectors of length _n_, and `beta` is a scalar. --- ## Level-1d operations Level-1d operations perform various level-1 BLAS-like operations on matrix diagonals (hence the _d_). Most of these operations are similar to level-1m counterparts, except they only read and update matrix diagonals and therefore do not take any `uplo` arguments. Please see the descriptions for the corresponding level-1m operation for a description of the arguments. --- #### addd ```c void bli_?addd ( doff_t diagoffa, diag_t diaga, trans_t transa, dim_t m, dim_t n, ctype* a, inc_t rsa, inc_t csa, ctype* b, inc_t rsb, inc_t csb ); ``` --- #### axpyd ```c void bli_?axpyd ( doff_t diagoffa, diag_t diaga, trans_t transa, dim_t m, dim_t n, ctype* alpha, ctype* a, inc_t rsa, inc_t csa, ctype* b, inc_t rsb, inc_t csb ); ``` --- #### copyd ```c void bli_?copyd ( doff_t diagoffa, diag_t diaga, trans_t transa, dim_t m, dim_t n, ctype* a, inc_t rsa, inc_t csa, ctype* b, inc_t rsb, inc_t csb ); ``` --- #### invertd ```c void bli_?invertd ( doff_t diagoffa, dim_t m, dim_t n, ctype* a, inc_t rsa, inc_t csa ); ``` --- #### scald ```c void bli_?scald ( conj_t conjalpha, doff_t diagoffa, dim_t m, dim_t n, ctype* alpha, ctype* a, inc_t rsa, inc_t csa ); ``` --- #### scal2d ```c void bli_?scal2d ( doff_t diagoffa, diag_t diaga, trans_t transa, dim_t m, dim_t n, ctype* alpha, ctype* a, inc_t rsa, inc_t csa, ctype* b, inc_t rsb, inc_t csb ); ``` --- #### setd ```c void bli_?setd ( conj_t conjalpha, doff_t diagoffa, dim_t m, dim_t n, ctype* alpha, ctype* a, inc_t rsa, inc_t csa ); ``` --- #### setid ```c void bli_?setid ( doff_t diagoffa, dim_t m, dim_t n, ctype_r* alpha, ctype* a, inc_t rsa, inc_t csa ); ``` Set the imaginary components of every element along the diagonal of `a`, as specified by `diagoffa`, to a scalar `alpha`. Note that the datatype of `alpha` must be the real projection of the datatype of `a`. --- #### shiftd ```c void bli_?shiftd ( doff_t diagoffa, dim_t m, dim_t n, ctype* alpha, ctype* a, inc_t rsa, inc_t csa ); ``` Add a constant value `alpha` to every element along the diagonal of `a`, as specified by `diagoffa`. --- #### subd ```c void bli_?subd ( doff_t diagoffa, diag_t diaga, trans_t transa, dim_t m, dim_t n, ctype* a, inc_t rsa, inc_t csa, ctype* b, inc_t rsb, inc_t csb ); ``` --- #### xpbyd ```c void bli_?xpbyd ( doff_t diagoffa, diag_t diaga, trans_t transa, dim_t m, dim_t n, ctype* a, inc_t rsa, inc_t csa, ctype* beta, ctype* b, inc_t rsb, inc_t csb ); ``` --- ## Level-1m operations Level-1m operations perform various level-1 BLAS-like operations on matrices (hence the _m_). --- #### addm ```c void bli_?addm ( doff_t diagoffa, diag_t diaga, uplo_t uploa, trans_t transa, dim_t m, dim_t n, ctype* a, inc_t rsa, inc_t csa, ctype* b, inc_t rsb, inc_t csb ); ``` Perform ``` B := B + transa(A) ``` where `B` is an _m x n_ matrix, `A` is stored as a dense matrix, or lower- or upper-triangular/trapezoidal matrix, as specified by `uploa`, with the diagonal offset of `A` specified by `diagoffa` and unit/non-unit nature of the diagonal specified by `diaga`. If `uploa` indicates lower or upper storage, only that part of matrix `A` will be referenced and used to update `B`. --- #### axpym ```c void bli_?axpym ( doff_t diagoffa, diag_t diaga, uplo_t uploa, trans_t transa, dim_t m, dim_t n, ctype* alpha, ctype* a, inc_t rsa, inc_t csa, ctype* b, inc_t rsb, inc_t csb ); ``` Perform ``` B := B + alpha * transa(A) ``` where `B` is an _m x n_ matrix, `A` is stored as a dense matrix, or lower- or upper-triangular/trapezoidal matrix, as specified by `uploa`, with the diagonal offset of `A` specified by `diagoffa` and unit/non-unit nature of the diagonal specified by `diaga`. If `uploa` indicates lower or upper storage, only that part of matrix `A` will be referenced and used to update `B`. --- #### copym ```c void bli_?copym ( doff_t diagoffa, diag_t diaga, uplo_t uploa, trans_t transa, dim_t m, dim_t n, ctype* a, inc_t rsa, inc_t csa, ctype* b, inc_t rsb, inc_t csb ); ``` Perform ``` B := transa(A) ``` where `B` is an _m x n_ matrix, `A` is stored as a dense matrix, or lower- or upper-triangular/trapezoidal matrix, as specified by `uploa`, with the diagonal offset of `A` specified by `diagoffa` and unit/non-unit nature of the diagonal specified by `diaga`. If `uploa` indicates lower or upper storage, only that part of matrix `A` will be referenced and used to update `B`. --- #### scalm ```c void bli_?scalm ( conj_t conjalpha, doff_t diagoffa, uplo_t uploa, dim_t m, dim_t n, ctype* alpha, ctype* a, inc_t rsa, inc_t csa ); ``` Perform ``` A := conjalpha(alpha) * A ``` where `A` is an _m x n_ matrix stored as a dense matrix, or lower- or upper-triangular/trapezoidal matrix, as specified by `uploa`, with the diagonal offset of `A` specified by `diagoffa`. If `uploa` indicates lower or upper storage, only that part of matrix `A` will be updated. --- #### scal2m ```c void bli_?scal2m ( doff_t diagoffa, diag_t diaga, uplo_t uploa, trans_t transa, dim_t m, dim_t n, ctype* alpha, ctype* a, inc_t rsa, inc_t csa, ctype* b, inc_t rsb, inc_t csb ); ``` Perform ``` B := alpha * transa(A) ``` where `B` is an _m x n_ matrix, `A` is stored as a dense matrix, or lower- or upper-triangular/trapezoidal matrix, as specified by `uploa`, with the diagonal offset of `A` specified by `diagoffa` and unit/non-unit nature of the diagonal specified by `diaga`. If `uploa` indicates lower or upper storage, only that part of matrix `A` will be referenced and used to update `B`. --- #### setm ```c void bli_?setm ( conj_t conjalpha, doff_t diagoffa, diag_t diaga, uplo_t uploa, dim_t m, dim_t n, ctype* alpha, ctype* a, inc_t rsa, inc_t csa ); ``` Set all elements of an _m x n_ matrix `A` to `conjalpha(alpha)`, where `A` is stored as a dense matrix, or lower- or upper- triangular/trapezoidal matrix, as specified by `uploa`, with the diagonal offset of `A` specified by `diagoffa` and unit/non-unit nature of the diagonal specified by `diaga`. If `uploa` indicates lower or upper storage, only that part of matrix `A` will be updated. --- #### subm ```c void bli_?subm ( doff_t diagoffa, diag_t diaga, uplo_t uploa, trans_t transa, dim_t m, dim_t n, ctype* a, inc_t rsa, inc_t csa, ctype* b, inc_t rsb, inc_t csb ); ``` Perform ``` B := B - transa(A) ``` where `B` is an _m x n_ matrix, `A` is stored as a dense matrix, or lower- or upper-triangular/trapezoidal matrix, as specified by `uploa`, with the diagonal offset of `A` specified by `diagoffa` and unit/non-unit nature of the diagonal specified by `diaga`. If `uploa` indicates lower or upper storage, only that part of matrix `A` will be referenced and used to update `B`. --- ## Level-1f operations Level-1f operations implement various fused combinations of level-1 operations (hence the _f_). **Note**: Each level-1f operation has a corresponding level-1f kernel through which it is primarily implemented. Level-1f kernels are employed when optimizing level-2 operations. --- #### axpy2v ```c void bli_?axpy2v ( conj_t conjx, conj_t conjy, dim_t m, ctype* alphax, ctype* alphay, ctype* x, inc_t incx, ctype* y, inc_t incy, ctype* z, inc_t incz ); ``` Perform ``` z := y + alphax * conjx(x) + alphay * conjy(y) ``` where `x`, `y`, and `z` are vectors of length _m_. The kernel, if optimized, is implemented as a fused pair of calls to [axpyv](BLISTypedAPI.md#axpyv). --- #### dotaxpyv ```c void bli_?dotaxpyv ( conj_t conjxt, conj_t conjx, conj_t conjy, dim_t m, ctype* alpha, ctype* x, inc_t incx, ctype* y, inc_t incy, ctype* rho, ctype* z, inc_t incz ); ``` Perform ``` rho := conjxt(x^T) * conjy(y) y := y + alpha * conjx(x) ``` where `x`, `y`, and `z` are vectors of length _m_ and `alpha` and `rho` are scalars. The kernel, if optimized, is implemented as a fusion of calls to [dotv](BLISTypedAPI.md#dotv) and [axpyv](BLISTypedAPI.md#axpyv). --- #### axpyf ```c void bli_?axpyf ( conj_t conja, conj_t conjx, dim_t m, dim_t b, ctype* alpha, ctype* a, inc_t inca, inc_t lda, ctype* x, inc_t incx, ctype* y, inc_t incy ); ``` Perform ``` y := y + alpha * conja(A) * conjx(x) ``` where `A` is an _m x b_ matrix, and `y` and `x` are vectors. The kernel, if optimized, is implemented as a fused series of calls to [axpyv](BLISTypedAPI.md#axpyv) where _b_ is less than or equal to an implementation-dependent fusing factor specific to `axpyf`. --- #### dotxf ```c void bli_?dotxf ( conj_t conjat, conj_t conjx, dim_t m, dim_t b, ctype* alpha, ctype* a, inc_t inca, inc_t lda, ctype* x, inc_t incx, ctype* beta, ctype* y, inc_t incy ); ``` Perform ``` y := y + alpha * conjat(A^T) * conjx(x) ``` where `A` is an _m x b_ matrix, and `y` and `x` are vectors. The kernel, if optimized, is implemented as a fused series of calls to [dotxv](BLISTypedAPI.md#dotxv) where _b_ is less than or equal to an implementation-dependent fusing factor specific to `dotxf`. --- #### dotxaxpyf ```c void bli_?dotxaxpyf ( conj_t conjat, conj_t conja, conj_t conjw, conj_t conjx, dim_t m, dim_t b, ctype* alpha, ctype* a, inc_t inca, inc_t lda, ctype* w, inc_t incw, ctype* x, inc_t incx, ctype* beta, ctype* y, inc_t incy, ctype* z, inc_t incz ); ``` Perform ``` y := beta * y + alpha * conjat(A^T) * conjw(w) z := z + alpha * conja(A) * conjx(x) ``` where `A` is an _m x b_ matrix, `w` and `z` are vectors of length _m_, `x` and `y` are vectors of length `b`, and `alpha` and `beta` are scalars. The kernel, if optimized, is implemented as a fusion of calls to [dotxf](BLISTypedAPI.md#dotxf) and [axpyf](BLISTypedAPI.md#axpyf). ## Level-2 operations Level-2 operations perform various level-2 BLAS-like operations. --- #### gemv ```c void bli_?gemv ( trans_t transa, conj_t conjx, dim_t m, dim_t n, ctype* alpha, ctype* a, inc_t rsa, inc_t csa, ctype* x, inc_t incx, ctype* beta, ctype* y, inc_t incy ); ``` Perform ``` y := beta * y + alpha * transa(A) * conjx(x) ``` where `transa(A)` is an _m x n_ matrix, and `y` and `x` are vectors. --- #### ger ```c void bli_?ger ( conj_t conjx, conj_t conjy, dim_t m, dim_t n, ctype* alpha, ctype* x, inc_t incx, ctype* y, inc_t incy, ctype* a, inc_t rsa, inc_t csa ); ``` Perform ``` A := A + alpha * conjx(x) * conjy(y)^T ``` where `A` is an _m x n_ matrix, and `x` and `y` are vectors of length _m_ and _n_, respectively. --- #### hemv ```c void bli_?hemv ( uplo_t uploa, conj_t conja, conj_t conjx, dim_t m, ctype* alpha, ctype* a, inc_t rsa, inc_t csa, ctype* x, inc_t incx, ctype* beta, ctype* y, inc_t incy ); ``` Perform ``` y := beta * y + alpha * conja(A) * conjx(x) ``` where `A` is an _m x m_ Hermitian matrix stored in the lower or upper triangle as specified by `uploa`, and `y` and `x` are vectors of length _m_. --- #### her ```c void bli_?her ( uplo_t uploa, conj_t conjx, dim_t m, rtype* alpha, ctype* x, inc_t incx, ctype* a, inc_t rsa, inc_t csa ); ``` Perform ``` A := A + alpha * conjx(x) * conjx(x)^H ``` where `A` is an _m x m_ Hermitian matrix stored in the lower or upper triangle as specified by `uploa`, and `x` is a vector of length _m_. **Note:** The floating-point type of `alpha` is always the real projection of the floating-point types of `x` and `A`. --- #### her2 ```c void bli_?her2 ( uplo_t uploa, conj_t conjx, conj_t conjy, dim_t m, ctype* alpha, ctype* x, inc_t incx, ctype* y, inc_t incy, ctype* a, inc_t rsa, inc_t csa ); ``` Perform ``` A := A + alpha * conjx(x) * conjy(y)^H + conj(alpha) * conjy(y) * conjx(x)^H ``` where `A` is an _m x m_ Hermitian matrix stored in the lower or upper triangle as specified by `uploa`, and `x` and `y` are vectors of length _m_. --- #### symv ```c void bli_?symv ( uplo_t uploa, conj_t conja, conj_t conjx, dim_t m, ctype* alpha, ctype* a, inc_t rsa, inc_t csa, ctype* x, inc_t incx, ctype* beta, ctype* y, inc_t incy ); ``` Perform ``` y := beta * y + alpha * conja(A) * conjx(x) ``` where `A` is an _m x m_ symmetric matrix stored in the lower or upper triangle as specified by `uploa`, and `y` and `x` are vectors of length _m_. --- #### syr ```c void bli_?syr ( uplo_t uploa, conj_t conjx, dim_t m, ctype* alpha, ctype* x, inc_t incx, ctype* a, inc_t rsa, inc_t csa ); ``` Perform ``` A := A + alpha * conjx(x) * conjx(x)^T ``` where `A` is an _m x m_ symmetric matrix stored in the lower or upper triangle as specified by `uploa`, and `x` is a vector of length _m_. --- #### syr2 ```c void bli_?syr2 ( uplo_t uploa, conj_t conjx, conj_t conjy, dim_t m, ctype* alpha, ctype* x, inc_t incx, ctype* y, inc_t incy, ctype* a, inc_t rsa, inc_t csa ); ``` Perform ``` A := A + alpha * conjx(x) * conjy(y)^T + conj(alpha) * conjy(y) * conjx(x)^T ``` where `A` is an _m x m_ symmetric matrix stored in the lower or upper triangle as specified by `uploa`, and `x` and `y` are vectors of length _m_. --- #### trmv ```c void bli_?trmv ( uplo_t uploa, trans_t transa, diag_t diaga, dim_t m, ctype* alpha, ctype* a, inc_t rsa, inc_t csa, ctype* x, inc_t incx ); ``` Perform ``` x := alpha * transa(A) * x ``` where `A` is an _m x m_ triangular matrix stored in the lower or upper triangle as specified by `uploa` with unit/non-unit nature specified by `diaga`, and `x` is a vector of length _m_. --- #### trsv ```c void bli_?trsv ( uplo_t uploa, trans_t transa, diag_t diaga, dim_t m, ctype* alpha, ctype* a, inc_t rsa, inc_t csa, ctype* y, inc_t incy ); ``` Solve the linear system ``` transa(A) * x = alpha * y ``` where `A` is an _m x m_ triangular matrix stored in the lower or upper triangle as specified by `uploa` with unit/non-unit nature specified by `diaga`, and `x` and `y` are vectors of length _m_. The right-hand side vector operand `y` is overwritten with the solution vector `x`. --- ## Level-3 operations Level-3 operations perform various level-3 BLAS-like operations. **Note**: Each All level-3 operations are implemented through a handful of level-3 microkernels. Please see the [Kernels Guide](KernelsHowTo.md) for more details. --- #### gemm ```c void bli_?gemm ( trans_t transa, trans_t transb, dim_t m, dim_t n, dim_t k, ctype* alpha, ctype* a, inc_t rsa, inc_t csa, ctype* b, inc_t rsb, inc_t csb, ctype* beta, ctype* c, inc_t rsc, inc_t csc ); ``` Perform ``` C := beta * C + alpha * transa(A) * transb(B) ``` where C is an _m x n_ matrix, `transa(A)` is an _m x k_ matrix, and `transb(B)` is a _k x n_ matrix. --- #### gemmt ```c void bli_?gemmt ( uplo_t uploc, trans_t transa, trans_t transb, dim_t m, dim_t k, ctype* alpha, ctype* a, inc_t rsa, inc_t csa, ctype* b, inc_t rsb, inc_t csb, ctype* beta, ctype* c, inc_t rsc, inc_t csc ); ``` Perform ``` C := beta * C + alpha * transa(A) * transb(B) ``` where C is an _m x m_ matrix, `transa(A)` is an _m x k_ matrix, and `transb(B)` is a _k x m_ matrix. This operation is similar to `bli_?gemm()` except that it only updates the lower or upper triangle of `C` as specified by `uploc`. --- #### hemm ```c void bli_?hemm ( side_t sidea, uplo_t uploa, conj_t conja, trans_t transb, dim_t m, dim_t n, ctype* alpha, ctype* a, inc_t rsa, inc_t csa, ctype* b, inc_t rsb, inc_t csb, ctype* beta, ctype* c, inc_t rsc, inc_t csc ); ``` Perform ``` C := beta * C + alpha * conja(A) * transb(B) ``` if `sidea` is `BLIS_LEFT`, or ``` C := beta * C + alpha * transb(B) * conja(A) ``` if `sidea` is `BLIS_RIGHT`, where `C` and `B` are _m x n_ matrices and `A` is a Hermitian matrix stored in the lower or upper triangle as specified by `uploa`. When `sidea` is `BLIS_LEFT`, `A` is _m x m_, and when `sidea` is `BLIS_RIGHT`, `A` is _n x n_. --- #### herk ```c void bli_?herk ( uplo_t uploc, trans_t transa, dim_t m, dim_t k, rtype* alpha, ctype* a, inc_t rsa, inc_t csa, rtype* beta, ctype* c, inc_t rsc, inc_t csc ); ``` Perform ``` C := beta * C + alpha * transa(A) * transa(A)^H ``` where C is an _m x m_ Hermitian matrix stored in the lower or upper triangle as specified by `uploc` and `transa(A)` is an _m x k_ matrix. **Note:** The floating-point types of `alpha` and `beta` are always the real projection of the floating-point types of `A` and `C`. --- #### her2k ```c void bli_?her2k ( uplo_t uploc, trans_t transa, trans_t transb, dim_t m, dim_t k, ctype* alpha, ctype* a, inc_t rsa, inc_t csa, ctype* b, inc_t rsb, inc_t csb, rtype* beta, ctype* c, inc_t rsc, inc_t csc ); ``` Perform ``` C := beta * C + alpha * transa(A) * transb(B)^H + conj(alpha) * transb(B) * transa(A)^H ``` where C is an _m x m_ Hermitian matrix stored in the lower or upper triangle as specified by `uploc` and `transa(A)` and `transb(B)` are _m x k_ matrices. **Note:** The floating-point type of `beta` is always the real projection of the floating-point types of `A` and `C`. --- #### symm ```c void bli_?symm ( side_t sidea, uplo_t uploa, conj_t conja, trans_t transb, dim_t m, dim_t n, ctype* alpha, ctype* a, inc_t rsa, inc_t csa, ctype* b, inc_t rsb, inc_t csb, ctype* beta, ctype* c, inc_t rsc, inc_t csc ); ``` Perform ``` C := beta * C + alpha * conja(A) * transb(B) ``` if `sidea` is `BLIS_LEFT`, or ``` C := beta * C + alpha * transb(B) * conja(A) ``` if `sidea` is `BLIS_RIGHT`, where `C` and `B` are _m x n_ matrices and `A` is a symmetric matrix stored in the lower or upper triangle as specified by `uploa`. When `sidea` is `BLIS_LEFT`, `A` is _m x m_, and when `sidea` is `BLIS_RIGHT`, `A` is _n x n_. --- #### syrk ```c void bli_?syrk ( uplo_t uploc, trans_t transa, dim_t m, dim_t k, ctype* alpha, ctype* a, inc_t rsa, inc_t csa, ctype* beta, ctype* c, inc_t rsc, inc_t csc ); ``` Perform ``` C := beta * C + alpha * transa(A) * transa(A)^T ``` where C is an _m x m_ symmetric matrix stored in the lower or upper triangle as specified by `uploa` and `transa(A)` is an _m x k_ matrix. --- #### syr2k ```c void bli_?syr2k ( uplo_t uploc, trans_t transa, trans_t transb, dim_t m, dim_t k, ctype* alpha, ctype* a, inc_t rsa, inc_t csa, ctype* b, inc_t rsb, inc_t csb, ctype* beta, ctype* c, inc_t rsc, inc_t csc ); ``` Perform ``` C := beta * C + alpha * transa(A) * transb(B)^T + alpha * transb(B) * transa(A)^T ``` where C is an _m x m_ symmetric matrix stored in the lower or upper triangle as specified by `uploa` and `transa(A)` and `transb(B)` are _m x k_ matrices. --- #### trmm ```c void bli_?trmm ( side_t sidea, uplo_t uploa, trans_t transa, diag_t diaga, dim_t m, dim_t n, ctype* alpha, ctype* a, inc_t rsa, inc_t csa, ctype* b, inc_t rsb, inc_t csb ); ``` Perform ``` B := alpha * transa(A) * B ``` if `sidea` is `BLIS_LEFT`, or ``` B := alpha * B * transa(A) ``` if `sidea` is `BLIS_RIGHT`, where `B` is an _m x n_ matrix and `A` is a triangular matrix stored in the lower or upper triangle as specified by `uploa` with unit/non-unit nature specified by `diaga`. When `sidea` is `BLIS_LEFT`, `A` is _m x m_, and when `sidea` is `BLIS_RIGHT`, `A` is _n x n_. --- #### trmm3 ```c void bli_?trmm3 ( side_t sidea, uplo_t uploa, trans_t transa, diag_t diaga, trans_t transb, dim_t m, dim_t n, ctype* alpha, ctype* a, inc_t rsa, inc_t csa, ctype* b, inc_t rsb, inc_t csb, ctype* beta, ctype* c, inc_t rsc, inc_t csc ); ``` Perform ``` C := beta * C + alpha * transa(A) * transb(B) ``` if `sidea` is `BLIS_LEFT`, or ``` C := beta * C + alpha * transb(B) * transa(A) ``` if `sidea` is `BLIS_RIGHT`, where `C` and `transb(B)` are _m x n_ matrices and `A` is a triangular matrix stored in the lower or upper triangle as specified by `uploa` with unit/non-unit nature specified by `diaga`. When `sidea` is `BLIS_LEFT`, `A` is _m x m_, and when `sidea` is `BLIS_RIGHT`, `A` is _n x n_. --- #### trsm ```c void bli_?trsm ( side_t sidea, uplo_t uploa, trans_t transa, diag_t diaga, dim_t m, dim_t n, ctype* alpha, ctype* a, inc_t rsa, inc_t csa, ctype* b, inc_t rsb, inc_t csb ); ``` Solve the linear system with multiple right-hand sides ``` transa(A) * X = alpha * B ``` if `sidea` is `BLIS_LEFT`, or ``` X * transa(A) = alpha * B ``` if `sidea` is `BLIS_RIGHT`, where `X` and `B` are an _m x n_ matrices and `A` is a triangular matrix stored in the lower or upper triangle as specified by `uploa` with unit/non-unit nature specified by `diaga`. When `sidea` is `BLIS_LEFT`, `A` is _m x m_, and when `sidea` is `BLIS_RIGHT`, `A` is _n x n_. The right-hand side matrix operand `B` is overwritten with the solution matrix `X`. --- ## Utility operations --- #### asumv ```c void bli_?asumv ( dim_t n, ctype* x, inc_t incx, rtype* asum ); ``` Compute the sum of the absolute values of the fundamental elements of vector `x`. The resulting sum is stored to `asum`. **Note:** The floating-point type of `asum` is always the real projection of the floating-point type of `x`. **Note:** This function attempts to mimic the algorithm for computing the absolute vector sum in the netlib BLAS routines `*asum()`. --- #### norm1m #### normfm #### normim ```c void bli_?norm[1fi]m ( doff_t diagoffa, doff_t diaga, uplo_t uploa, dim_t m, dim_t n, ctype* a, inc_t rs_a, inc_t cs_a, rtype* norm ); ``` Compute the one-norm (`bli_?norm1m()`), Frobenius norm (`bli_?normfm()`), or infinity norm (`bli_?normim()`) of the elements in an _m x n_ matrix `A`. If `uploa` is `BLIS_LOWER` or `BLIS_UPPER` then `A` is assumed to be lower or upper triangular, respectively, with the main diagonal located at offset `diagoffa`. The resulting norm is stored to `norm`. **Note:** The floating-point type of `norm` is always the real projection of the floating-point type of `x`. --- #### norm1v #### normfv #### normiv ```c void bli_?norm[1fi]v ( dim_t n, ctype* x, inc_t incx, rtype* norm ); ``` Compute the one-norm (`bli_?norm1v()`), Frobenius norm (`bli_?normfv()`), or infinity norm (`bli_?normiv()`) of the elements in a vector `x` of length _n_. The resulting norm is stored to `norm`. **Note:** The floating-point type of `norm` is always the real projection of the floating-point type of `x`. --- #### mkherm ```c void bli_?mkherm ( uplo_t uploa, dim_t m, ctype* a, inc_t rs_a, inc_t cs_a ); ``` Make an _m x m_ matrix `A` explicitly Hermitian by copying the conjugate of the triangle specified by `uploa` to the opposite triangle. Imaginary components of diagonal elements are explicitly set to zero. It is assumed that the diagonal offset of `A` is zero. --- #### mksymm ```c void bli_?mksymm ( uplo_t uploa, dim_t m, ctype* a, inc_t rs_a, inc_t cs_a ); ``` Make an _m x m_ matrix `A` explicitly symmetric by copying the triangle specified by `uploa` to the opposite triangle. It is assumed that the diagonal offset of `A` is zero. --- #### mktrim ```c void bli_?mktrim ( uplo_t uploa, dim_t m, ctype* a, inc_t rs_a, inc_t cs_a ); ``` Make an _m x m_ matrix `A` explicitly triangular by preserving the triangle specified by `uploa` and zeroing the elements in the opposite triangle. It is assumed that the diagonal offset of `A` is zero. --- #### fprintv ```c void bli_?fprintv ( FILE* file, char* s1, dim_t m, ctype* x, inc_t incx, char* format, char* s2 ); ``` Print a vector `x` of length _m_ to file stream `file`, where `file` is a file pointer returned by the standard C library function `fopen()`. The caller may also pass in a global file pointer such as `stdout` or `stderr`. The strings `s1` and `s2` are printed immediately before and after the output (respectively), and the format specifier `format` is used to format the individual elements. For valid format specifiers, please see documentation for the standard C library function `printf()`. **Note:** For complex datatypes, the format specifier is applied to both the real and imaginary components **individually**. Therefore, you should use format specifiers such as `"%5.2f"`, but **not** `"%5.2f + %5.2f"`. --- #### fprintm ```c void bli_?fprintm ( FILE* file, char* s1, dim_t m, dim_t n, ctype* a, inc_t rs_a, inc_t cs_a, char* format, char* s2 ); ``` Print an _m x n_ matrix `A` to file stream `file`, where `file` is a file pointer returned by the standard C library function `fopen()`. The caller may also pass in a global file pointer such as `stdout` or `stderr`. The strings `s1` and `s2` are printed immediately before and after the output (respectively), and the format specifier `format` is used to format the individual elements. For valid format specifiers, please see documentation for the standard C library function `printf()`. **Note:** For complex datatypes, the format specifier is applied to both the real and imaginary components **individually**. Therefore, you should use format specifiers such as `"%5.2f"`, but **not** `"%5.2f + %5.2f"`. --- #### printv ```c void bli_?printv ( char* s1, dim_t m, ctype* x, inc_t incx, char* format, char* s2 ); ``` Print a vector `x` of length _m_ to standard output. This function call is equivalent to calling `bli_?fprintv()` with `stdout` as the file pointer. --- #### printm ```c void bli_?printm ( char* s1, dim_t m, dim_t n, ctype* a, inc_t rs_a, inc_t cs_a, char* format, char* s2 ); ``` Print an _m x n_ matrix `a` to standard output. This function call is equivalent to calling `bli_?fprintm()` with `stdout` as the file pointer. --- #### randv ```c void bli_?randv ( dim_t n, ctype* x, inc_t incx ); ``` Set the elements of a vector `x` of length _n_ to random values on the interval `[-1,1)`. **Note:** For complex datatypes, the real and imaginary components of each element are randomized individually and independently of one another. --- #### randm ```c void bli_?randm ( doff_t diagoffa, uplo_t uploa, dim_t m, dim_t n, ctype* a, inc_t rs_a, inc_t cs_a ); ``` Set the elements of an _m x n_ matrix `A` to random values on the interval `[-1,1)`. If `uploa` is `BLIS_LOWER` or `BLIS_UPPER`, then additional scaling occurs so that the resulting matrix is diagonally dominant. Specifically, the diagonal elements (identified by diagonal offset `diagoffa`) are shifted so that they lie on the interval `[1,2)` and the off-diagonal elements (in the triangle specified by `uploa`) are scaled by `1.0/max(m,n)`. **Note:** For complex datatypes, the real and imaginary components of each off-diagonal element are randomized individually and independently of one another. --- #### sumsqv ```c void bli_?sumsqv ( dim_t n, ctype* x, inc_t incx, rtype* scale, rtype* sumsq ); ``` Compute the sum of the squares of the elements in a vector `x` of length _n_. The result is computed in scaled form, and in such a way that it may be used repeatedly to accumulate the sum of the squares of several vectors. The function computes scale\_new and sumsq\_new such that ``` scale_new^2 * sumsq_new = x[0]^2 + x[1]^2 + ... x[m-1]^2 + scale_old^2 * sumsq_old ``` where, on entry, `scale` and `sumsq` contain `scale_old` and `sumsq_old`, respectively, and on exit, `scale` and `sumsq` contain `scale_new` and `sumsq_new`, respectively. **Note:** This function attempts to mimic the algorithm for computing the Frobenius norm in the netlib LAPACK routine `?lassq()`. --- #### getsc ```c void bli_getsc ( ctype* chi, double* zeta_r, double* zeta_i ) ``` Copy the real and imaginary values from the scalar object `chi` to `zeta_r` and `zeta_i`. If `chi` is stored as a real type, then `zeta_i` is set to zero. (If `chi` is stored in single precision, the corresponding elements are typecast/promoted during the copy.) --- #### getijv ```c err_t bli_?getijv ( dim_t i, ctype* x, incx, double* ar, double* ai ) ``` Copy the real and imaginary values at the `i`th element of vector `x` to `ar` and `ai`. For real domain invocations, only `ar` is overwritten and `ai` is left unchanged. (If `x` contains elements stored in single precision, the corresponding elements are typecast/promoted during the copy.) Note that the object-based analogue of [getijv](BLISObjectAPI.md#getijv) does bounds checking of the vector element offset `i` against the vector length while the typed functions specified above do not (since the vector length is not given). --- #### getijm ```c err_t bli_?getijm ( dim_t i, dim_t j, ctype* b, inc_t rs_b, inc_t cs_b, double* ar, double* ai ) ``` Copy the real and imaginary values at the (`i`,`j`) element of object `b` to `ar` and `ai`. For real domain invocations, only `ar` is overwritten and `ai` is left unchanged. (If `b` contains elements stored in single precision, the corresponding elements are typecast/promoted during the copy.) Note that the object-based analogue of [getijm](BLISObjectAPI.md#getijm) does bounds checking of the matrix element offsets (`i`,`j`) against the matrix dimensions while the typed functions specified above do not (since the matrix dimensions are not given). --- #### setsc ```c void bli_setsc ( double* zeta_r, double* zeta_i, ctype* chi ); ``` Copy real and imaginary values `zeta_r` and `zeta_i` to the scalar object `chi`. If `chi` is stored as a real type, then `zeta_i` is ignored. (If `chi` is stored in single precision, the contents are typecast/demoted during the copy.) --- #### setijv ```c err_t bli_?setijv ( double ar, double ai, dim_t i, ctype* x, incx ); ``` Copy real and imaginary values `ar` and `ai` to the `i`th element of vector object `x`. For real domain invocations, only `ar` is copied and `ai` is ignored. (If `x` contains elements stored in single precision, the corresponding elements are typecast/demoted during the copy.) Note that the object-based analogue of [setijv](BLISObjectAPI.md#setijv) does bounds checking of the vector element offset `i` against the vector length while the typed functions specified above do not (since the vector length is not given). --- #### setijm ```c err_t bli_?setijm ( double ar, double ai, dim_t i, dim_t j, ctype* b, inc_t rs_b, inc_t cs_b ); ``` Copy real and imaginary values `ar` and `ai` to the (`i`,`j`) element of object `b`. For real domain invocations, only `ar` is copied and `ai` is ignored. (If `b` contains elements stored in single precision, the corresponding elements are typecast/demoted during the copy.) Note that the object-based analogue of [setijm](BLISObjectAPI.md#setijm) does bounds checking of the matrix element offsets (`i`,`j`) against the matrix dimensions while the typed functions specified above do not (since the matrix dimensions are not given). --- #### eqsc ```c void bli_?eqsc ( conj_t conjchi, ctype* chi, ctype* psi, bool* is_eq ); ``` Perform an element-wise comparison between scalars `chi` and `psi` and store the boolean result in the `bool` pointed to by `is_eq`. If `conjchi` indicates a conjugation, `chi` will be implicitly conjugated for purposes of the comparision. --- #### eqv ```c void bli_?eqv ( conj_t conjx, dim_t n, ctype* x, inc_t incx, ctype* y, inc_t incy, bool* is_eq ); ``` Perform an element-wise comparison between length _n_ vectors `x` and `y` and store the boolean result in the `bool` pointed to by `is_eq`. If `conjx` indicates a conjugation, `x` will be implicitly conjugated for purposes of the comparision. --- #### eqm ```c void bli_?eqm ( doff_t diagoffa, diag_t diaga, uplo_t uploa, trans_t transa, dim_t m, dim_t n, ctype* a, inc_t rs_a, inc_t cs_a, ctype* b, inc_t rs_b, inc_t cs_b, bool* is_eq ) ``` Perform an element-wise comparison between matrices `A` and `B` and store the boolean result in the `bool` pointed to by `is_eq`. Here, `B` is an _m x n_ matrix, `A` is stored as a dense matrix, or lower- or upper-triangular/trapezoidal matrix with arbitrary diagonal offset and unit or non-unit diagonal. If `diaga` indicates a unit diagonal, the diagonals of both matrices will be ignored for purposes of the comparision. If `uploa` indicates lower or upper storage, only that part of matrix `A` will be referenced in the comparison. If `transa` indicates a conjugation and/or transposition, then `A` will be conjugated and/or transposed for purposes of the comparison. ## Level-3 microkernels **Note:** The `*` in level-3 microkernel function names shown below reflect that there is no exact naming convention required for the microkernels, except that they must begin with `bli_?`. We strongly recommend, however, that the microkernel function names include the name of the microkernel itself. For example, the `gemm` microkernel should be named with the prefix `bli_?gemm_` and the `trsm` microkernels should be named with the prefixes `bli_?trsm_l_` (lower triangular) and `bli_?trsm_u_` (upper triangular). --- #### gemm microkernel ```c void bli_?gemm_* ( dim_t k, ctype* restrict alpha, ctype* restrict a1, ctype* restrict b1, ctype* restrict beta, ctype* restrict c11, inc_t rsc, inc_t csc, auxinfo_t* restrict data, cntx_t* restrict cntx ); ``` Perform ``` C11 := beta * C11 + alpha * A1 * B1 ``` where `C11` is an _MR x NR_ matrix, `A1` is an _MR x k_ "micropanel" matrix stored in packed (column-stored) format, `B1` is a _k x NR_ "micropanel" matrix in packed (row-stored) format, and alpha and beta are scalars. The storage of `C11` is specified by its row and column strides, `rsc` and `csc`. Please see the [Kernel Guide](KernelsHowTo.md) for more information on the `gemm` microkernel. --- #### trsm microkernels ```c void bli_?trsm_l_* ( ctype* restrict a11, ctype* restrict b11, ctype* restrict c11, inc_t rsc, inc_t csc auxinfo_t* restrict data, cntx_t* restrict cntx ); void bli_?trsm_u_* ( ctype* restrict a11, ctype* restrict b11, ctype* restrict c11, inc_t rsc, inc_t csc auxinfo_t* restrict data, cntx_t* restrict cntx ); ``` Perform ``` B11 := inv(A11) * B11 C11 := B11 ``` where `A11` is an _MR x MR_ lower or upper triangular matrix stored in packed (column-stored) format, `B11` is an _MR x NR_ matrix stored in packed (row-stored) format, and `C11` is an _MR x NR_ matrix stored according to row and column strides `rsc` and `csc`. Please see the [Kernel Guide](KernelsHowTo.md) for more information on the `trsm` microkernel. --- #### gemmtrsm microkernels ```c void bli_?gemmtrsm_l_* ( dim_t k, ctype* restrict alpha, ctype* restrict a10, ctype* restrict a11, ctype* restrict b01, ctype* restrict b11, ctype* restrict c11, inc_t rs_c, inc_t cs_c, auxinfo_t* restrict data, cntx_t* restrict cntx ); void bli_?gemmtrsm_u_* ( dim_t k, ctype* restrict alpha, ctype* restrict a12, ctype* restrict a11, ctype* restrict b21, ctype* restrict b11, ctype* restrict c11, inc_t rs_c, inc_t cs_c, auxinfo_t* restrict data, cntx_t* restrict cntx ); ``` Perform ``` B11 := alpha * B11 - A10 * B01 B11 := inv(A11) * B11 C11 := B11 ``` if `A11` is lower triangular, or ``` B11 := alpha * B11 - A12 * B21 B11 := inv(A11) * B11 C11 := B11 ``` if `A11` is upper triangular. Please see the [Kernel Guide](KernelsHowTo.md) for more information on the `gemmtrsm` microkernel. # Query function reference BLIS allows applications to query information about how BLIS was configured. The `bli_info_` API provides several categories of query routines. Most values are returned as a `gint_t`, which is a signed integer. The size of this integer can be queried through a special routine that returns the size in a character string: ```c char* bli_info_get_int_type_size_str( void ); ``` **Note:** All of the `bli_info_` functions are **always** thread-safe, no matter how BLIS was configured. ## General library information The following routine returns the address the full BLIS version string: ```c char* bli_info_get_version_str( void ); ``` ## Specific configuration The following routine returns a unique ID of type `arch_t` that identifies the current current active configuration: ```c arch_t bli_arch_query_id( void ); ``` This is most useful when BLIS is configured with multiple configurations. (When linking to multi-configuration builds of BLIS, you don't know for sure which configuration will be used until runtime since the configuration-specific parameters are not loaded until after calling a hueristic to detect the hardware--usually based the `CPUID` instruction.) Once the configuration's ID is known, it can be used to query a string that contains the name of the configuration: ```c char* bli_arch_string( arch_t id ); ``` ## General configuration The following routines return various general-purpose constants that affect the entire framework. All of these settings default to sane values, which can then be overridden by the configuration in [bli\_config.h](ConfigurationHowTo#bli_configh). If they are absent from a particular configuration's `bli_config.h` header file, then the default value is used, as specified in [frame/include/bli_config_macro_defs.h](https://github.com/flame/blis/blob/master/frame/include/bli_config_macro_defs.h). ```c gint_t bli_info_get_int_type_size( void ); gint_t bli_info_get_num_fp_types( void ); gint_t bli_info_get_max_type_size( void ); gint_t bli_info_get_page_size( void ); gint_t bli_info_get_simd_num_registers( void ); gint_t bli_info_get_simd_size( void ); gint_t bli_info_get_simd_align_size( void ); gint_t bli_info_get_stack_buf_max_size( void ); gint_t bli_info_get_stack_buf_align_size( void ); gint_t bli_info_get_heap_addr_align_size( void ); gint_t bli_info_get_heap_stride_align_size( void ); gint_t bli_info_get_pool_addr_align_size( void ); gint_t bli_info_get_enable_stay_auto_init( void ); gint_t bli_info_get_enable_blas( void ); gint_t bli_info_get_blas_int_type_size( void ); ``` ## Kernel information ### Micro-kernel implementation type query The following routines allow the caller to obtain a string that identifies the implementation type of each microkernel that is currently active (ie: part of the current active configuration, as identified bi `bli_arch_query_id()`). ```c char* bli_info_get_gemm_ukr_impl_string( ind_t method, num_t dt ) char* bli_info_get_gemmtrsm_l_ukr_impl_string( ind_t method, num_t dt ) char* bli_info_get_gemmtrsm_u_ukr_impl_string( ind_t method, num_t dt ) char* bli_info_get_trsm_l_ukr_impl_string( ind_t method, num_t dt ) char* bli_info_get_trsm_u_ukr_impl_string( ind_t method, num_t dt ) ``` Possible implementation (ie: the `ind_t method` argument) types are: * `BLIS_1M`: Implementation based on the 1m method. (This is the default induced method when real domain kernels are present but complex kernels are missing.) * `BLIS_NAT`: Implementation based on "native" execution (ie: NOT an induced method). Possible microkernel types (ie: the return values for `bli_info_get_*_ukr_impl_string()`) are: * `BLIS_REFERENCE_UKERNEL` (`"refrnce"`): This value is returned when the queried microkernel is provided by the reference implementation. * `BLIS_VIRTUAL_UKERNEL` (`"virtual"`): This value is returned when the queried microkernel is driven by a the "virtual" microkernel provided by an induced method. This happens for any `method` value that is not `BLIS_NAT` (ie: native), but only applies to the complex domain. * `BLIS_OPTIMIZED_UKERNEL` (`"optimzd"`): This value is returned when the queried microkernel is provided by an implementation that is neither reference nor virtual, and thus we assume the kernel author would deem it to be "optimized". Such a microkernel may not be optimal in the literal sense of the word, but nonetheless is _intended_ to be optimized, at least relative to the reference microkernels. * `BLIS_NOTAPPLIC_UKERNEL` (`"notappl"`): This value is returned usually when performing a `gemmtrsm` or `trsm` microkernel type query for any `method` value that is not `BLIS_NAT` (ie: native). That is, induced methods cannot be (purely) used on `trsm`-based microkernels because these microkernels perform more a triangular inversion, which is not matrix multiplication. ### Operation implementation type query The following routines allow the caller to obtain a string that identifies the implementation (`ind_t`) that is currently active (ie: implemented and enabled) for each level-3 operation. Possible implementation types are listed in the section above covering [microkernel implemenation query](BLISTypedAPI.md#microkernel-implementation-type-query). ```c char* bli_info_get_gemm_impl_string( num_t dt ); char* bli_info_get_hemm_impl_string( num_t dt ); char* bli_info_get_herk_impl_string( num_t dt ); char* bli_info_get_her2k_impl_string( num_t dt ); char* bli_info_get_symm_impl_string( num_t dt ); char* bli_info_get_syrk_impl_string( num_t dt ); char* bli_info_get_syr2k_impl_string( num_t dt ); char* bli_info_get_trmm_impl_string( num_t dt ); char* bli_info_get_trmm3_impl_string( num_t dt ); char* bli_info_get_trsm_impl_string( num_t dt ); ``` ## Clock functions --- #### clock ```c double bli_clock ( void ); ``` Return the amount of time that has elapsed since some fixed time in the past. The return values of `bli_clock()` typically feature nanosecond precision, though this is not guaranteed. **Note:** On Linux, `bli_clock()` is implemented in terms of `clock_gettime()` using the `clockid_t` value of `CLOCK_MONOTONIC`. On OS X, `bli_clock` is implemented in terms of `mach_absolute_time()`. And on Windows, `bli_clock` is implemented in terms of `QueryPerformanceFrequency()`. Please see [frame/base/bli_clock.c](https://github.com/flame/blis/blob/master/frame/base/bli_clock.c) for more details. **Note:** This function is returns meaningless values when BLIS is configured with `--disable-system`. --- #### clock_min_diff ```c double bli_clock_min_diff ( double time_prev_min, double time_start ); ``` This function computes an intermediate value, `time_diff`, equal to `bli_clock() - time_start`, and then tentatively prepares to return the minimum value of `time_diff` and `time_min`. If that minimum value is extremely small (close to zero), the function returns `time_min` instead. This function is meant to be used in conjuction with `bli_clock()` for performance timing within applications--specifically in loops where only the fastest timing is of interest. For example: ```c double t_save = DBL_MAX; for( i = 0; i < 3; ++i ) { double t = bli_clock(); bli_gemm( ... ); t_save = bli_clock_min_diff( t_save, t ); } double gflops = ( 2.0 * m * k * n ) / ( t_save * 1.0e9 ); ``` This code calls `bli_gemm()` three times and computes the performance, in GFLOPS, of the fastest of the three executions. --- # Example code BLIS provides lots of example code in the [examples/tapi](https://github.com/flame/blis/tree/master/examples/tapi) directory of the BLIS source distribution. The example code in this directory is set up like a tutorial, and so we recommend starting from the beginning. Topics include printing vectors and matrices and calling a representative subset of the computational level-1v, -1m, -2, -3, and utility operations documented above. Please read the `README` contained within the `examples/tapi` directory for further details. blis-0.9.0/docs/BuildSystem.md000066400000000000000000000661721422157504600162110ustar00rootroot00000000000000## Contents * **[Contents](BuildSystem.md#contents)** * **[Introduction](BuildSystem.md#introduction)** * **[Obtaining BLIS](BuildSystem.md#obtaining-blis)** * **[Step 1: Chose a framework configuration](BuildSystem.md#step-1-choose-a-framework-configuration)** * **[Step 2: Running `configure`](BuildSystem.md#step-2-running-configure)** * **[Step 3: Compilation](BuildSystem.md#step-3-compilation)** * **[Step 3b: Testing (optional)](BuildSystem.md#step-3b-testing-optional)** * **[Step 4: Installation](BuildSystem.md#step-4-installation)** * **[Cleaning out build products](BuildSystem.md#cleaning-out-build-products)** * **[Compiling with BLIS](BuildSystem.md#compiling-with-blis)** * [Disabling BLAS prototypes](BuildSystem.md#disabling-blas-prototypes) * [CBLAS](BuildSystem.md#cblas) * **[Linking against BLIS](BuildSystem.md#linking-against-blis)** * **[Uninstalling](BuildSystem.md#uninstalling)** * **[make targets](BuildSystem.md#make-targets)** * **[Conclusion](BuildSystem.md#conclusion)** ## Introduction This document describes how to configure, compile, and install a BLIS library on your local system. The BLIS build system was designed for use with GNU/Linux (or some other sane UNIX). Other requirements are: * Python (2.7 or later for python2; 3.4 or later for python3) * GNU `bash` (3.2 or later) * GNU `make` (3.81 or later) * a working C99 compiler * Perl (any version) * `git` (1.8.5 or later, only required if cloning from Github) BLIS also requires a POSIX threads library at link-time (`-lpthread` or `libpthread.so`). This requirement holds even when configuring BLIS with multithreading disabled (the default) or with multithreading via OpenMP (`--enable-multithreading=openmp`). (Note: BLIS implements basic pthreads functionality automatically for Windows builds via [AppVeyor](https://ci.appveyor.com/project/shpc/blis/).) Finally, we also require various other shell utilities that are so ubiquitous that they are not worth mentioning (such as `mv`, `mkdir`, `find`, and so forth). If you are missing these utilities, then you have much bigger problems than not being able to build BLIS. ## Obtaining BLIS Before starting, you must obtain a copy of BLIS. If you are an end-user (i.e., not a developer), you can download a tarball or zip file of the latest tagged version by returning to the main [BLIS homepage](https://github.com/flame/blis) and clicking on the [releases](https://github.com/flame/blis/releases) link. **However**, we highly recommend that you instead clone a copy using the command: ``` $ git clone https://github.com/flame/blis.git ``` Cloning a repository allows users and developers alike to quickly and easily pull in new commits as they are available, including commits that occur **between** tagged releases. Once you download the BLIS distribution, the top-level directory should look something like: ``` $ ls CHANGELOG Makefile common.mk configure mpi_test testsuite CREDITS README.md config frame obj version INSTALL bli_config.h config.mk kernels ref_kernels windows LICENSE build config_registry lib test ``` ## Step 1: Choose a framework configuration The first step is to choose how to configure BLIS. Specifically, a user must decide which configuration to use, or whether to allow `configure` to automatically guess the best configuration for your hardware. (Note: This automatic configuration selection only applies to x86_64 systems.) Configurations are described in detail in the [Configuration Guide](ConfigurationHowTo.md). Generally speaking, a configuration consists of several files that reside in a sub-directory of the `config` directory. To see a list of the available configurations, you may inspect this directory, or run `configure` with no arguments. Here are the current (as of this writing) contents of the `config` directory: ``` $ ls config amd64 cortexa15 excavator intel64 old power7 template bgq cortexa57 generic knc penryn sandybridge zen bulldozer cortexa9 haswell knl piledriver steamroller ``` There is one additional configuration available that is not present in the `config` directory, and that is `auto`. By targeting the `auto` configuration (i.e., `./configure auto`), the user is requesting that `configure` select a configuration automatically based on the detected features of the processor. Another special configuration (one that, unlike `auto`, _is_ present in `config`) is the `generic` configuration. This configuration, like its name suggests, is architecture-agnostic and may be targeted in virtually any environment that supports the minimum build requirements of BLIS. The `generic` configuration uses a set of built-in, portable reference kernels (written in C99) that should work without modification on most, if not all, architectures. These reference kernels, however, should be expected to yield relatively low performance since they do not employ any architecture-specific optimizations beyond those the compiler provides automatically. (Historical note: The `generic` configuration corresponds to the `reference` configuration of previous releases of BLIS.) If you are a BLIS developer and wish to create your own configuration, either from scratch or using an existing configuration as a starting point, please read the BLIS [Configuration Guide](ConfigurationHowTo.md). ### Multithreading Multithreading in BLIS is disabled by default. For more information on enabling multithreading, please read the section of the [Multithreading](Multithreading.md) document titled ["Enabling Multithreading"](Multithreading.md#enabling-multithreading). **IMPORTANT**: Even when multithreading is enabled at configure-time, BLIS will default to single-threaded execution at runtime. For more information on the various ways of specifying multithreading at runtime, please read the section titled ["Specifying Multithreading"](Multithreading.md#specifying-multithreading). ## Step 2: Running `configure` This step should be somewhat familiar to many people who use open source software. To configure the build system, simply run: ``` $ ./configure ``` where `` is the configuration sub-directory name you chose in [Step 1](BuildSystem.md#step-1-choose-a-framework-configuration) above. If `` is not given, a helpful message is printed reminding you to explicit specify a configuration name along with a list of valid configuration families and their implied sub-configurations. For more information on sub-configurations and families, please see the BLIS [Configuration Guide](ConfigurationHowTo.md). Alternatively, `configure` can automatically select a configuration based on your hardware: ``` $ ./configure auto ``` However, as of this writing, BLIS lacks support for automatically detecting some architectures. If the `configure` script is not able to detect your architecture, the `generic` configuration will be used. Upon running configure, you will get output similar to the following. The exact output will depend on whether you cloned BLIS from a `git` repository or whether you obtained BLIS via a downloadable tarball from the [releases](https://github.com/flame/blis/releases) page. ``` $ ./configure --prefix=$HOME/blis haswell configure: using 'gcc' compiler. configure: found gcc version 5.4.0 (maj: 5, min: 4, rev: 0). configure: checking for blacklisted configurations due to gcc 5.4.0. configure: warning: gcc 5.4.0 does not support 'skx'; adding to blacklist. configure: found assembler ('as') version 2.26.1 (maj: 2, min: 26, rev: 1). configure: checking for blacklisted configurations due to as 2.26.1. configure: configuration blacklist: configure: skx configure: reading configuration registry...done. configure: determining default version string. configure: found '.git' directory; assuming git clone. configure: executing: git describe --tags. configure: got back 0.3.2-16-gb699bb1f. configure: truncating to 0.3.2-16. configure: starting configuration of BLIS 0.3.2-16. configure: configuring with official version string. configure: found shared library .so version '0.0.0'. configure: .so major version: 0 configure: .so minor.build version: 0.0 configure: manual configuration requested; configuring with 'haswell'. configure: checking configuration against contents of 'config_registry'. configure: configuration 'haswell' is registered. configure: 'haswell' is defined as having the following sub-configurations: configure: haswell configure: which collectively require the following kernels: configure: haswell zen configure: checking sub-configurations: configure: 'haswell' is registered...and exists. configure: checking sub-configurations' requisite kernels: configure: 'haswell' kernels...exist. configure: 'zen' kernels...exist. configure: no install prefix option given; defaulting to '/u/field/blis'. configure: no install libdir option given; defaulting to PREFIX/lib. configure: no install includedir option given; defaulting to PREFIX/include. configure: final installation directories: configure: libdir: /u/field/blis/lib configure: includedir: /u/field/blis/include configure: debug symbols disabled. configure: disabling verbose make output. (enable with 'make V=1'.) configure: building BLIS as a static library. configure: threading is disabled. configure: internal memory pools for packing buffers are enabled. configure: libmemkind not found; disabling. configure: the BLAS compatibility layer is enabled. configure: the CBLAS compatibility layer is disabled. configure: the internal integer size is automatically determined. configure: the BLAS/CBLAS interface integer size is 32-bit. configure: creating ./config.mk from ./build/config.mk.in configure: creating ./bli_config.h from ./build/bli_config.h.in configure: creating ./obj/haswell configure: creating ./obj/haswell/config configure: creating ./obj/haswell/config/haswell configure: creating ./obj/haswell/kernels configure: creating ./obj/haswell/kernels/haswell configure: creating ./obj/haswell/kernels/zen configure: creating ./obj/haswell/ref_kernels configure: creating ./obj/haswell/ref_kernels/haswell configure: creating ./obj/haswell/frame configure: creating ./obj/haswell/blastest configure: creating ./obj/haswell/testsuite configure: creating ./lib/haswell configure: creating ./include/haswell configure: mirroring ./config/haswell to ./obj/haswell/config/haswell configure: mirroring ./kernels/haswell to ./obj/haswell/kernels/haswell configure: mirroring ./kernels/zen to ./obj/haswell/kernels/zen configure: mirroring ./ref_kernels to ./obj/haswell/ref_kernels/haswell configure: mirroring ./frame to ./obj/haswell/frame configure: creating makefile fragments in ./config/haswell configure: creating makefile fragments in ./kernels/haswell configure: creating makefile fragments in ./kernels/zen configure: creating makefile fragments in ./ref_kernels configure: creating makefile fragments in ./frame configure: configured to build within top-level directory of source distribution. ``` The installation prefix can be specified via the `--prefix=PREFIX` option: ``` $ ./configure --prefix=/usr ``` This will cause libraries to eventually be installed (via `make install`) to `PREFIX/lib` and development headers to be installed to `PREFIX/include`. (The default value of `PREFIX` is `/usr/local`.) You can also specify the library install directory separately from the development header install directory with the `--libdir=LIBDIR` and `--includedir=INCDIR` options, respectively: ``` $ ./configure --libdir=/usr/lib --includedir=/usr/include ``` The `--libdir=LIBDIR` and `--includedir=INCDIR` options will override any path implied by `PREFIX`, whether it was specified explicitly via `--prefix` or implicitly (via the default). That is, `LIBDIR` defaults to `EXECPREFIX/lib` (where `EXECPREFIX`, set via `--exec-prefix=EXECPREFIX`, defaults to `PREFIX`) and `INCDIR` defaults to `PREFIX/include`, but `LIBDIR` and `INCDIR` will each be overriden by their respective `--libdir`/`--includedir` options. There is a third related option, `--sharedir=SHAREDIR`, where `SHAREDIR` defaults to `PREFIX/share`. This option specifies the installation directory for certain makefile fragments that contain variables determined by `configure` (e.g. `CC`, `CFLAGS`, `LDFLAGS`, etc.). These files allow certain BLIS makefiles, such as those in the `examples` or `testsuite` directories, to operate on an installed copy of BLIS rather than a local (and possibly uninstalled) copy. For a complete list of supported `configure` options and arguments, run `configure` with the `-h` option: ``` $ ./configure -h ``` The output from this invocation of `configure` should give you an up-to-date list of options and their descriptions. ## Step 3: Compilation Once `configure` is finished, you are ready to instantiate (compile) BLIS into a library by running `make`. Running `make` will result in output similar to: ``` $ make Generating monolithic blis.h......................................................... ..................................................................................... ..................................................................................... ..................................................................................... ..................................................................................... .......................................... Generated include/haswell/blis.h Compiling obj/haswell/config/haswell/bli_cntx_init_haswell.o ('haswell' CFLAGS for config code) Compiling obj/haswell/kernels/zen/1/bli_amaxv_zen_int.o ('haswell' CFLAGS for kernels) Compiling obj/haswell/kernels/zen/1/bli_axpyv_zen_int.o ('haswell' CFLAGS for kernels) Compiling obj/haswell/kernels/zen/1/bli_axpyv_zen_int10.o ('haswell' CFLAGS for kernels) Compiling obj/haswell/kernels/zen/1/bli_dotv_zen_int.o ('haswell' CFLAGS for kernels) Compiling obj/haswell/kernels/zen/1/bli_dotv_zen_int10.o ('haswell' CFLAGS for kernels) ``` If you want to see the individual command line invocations of the compiler, you can run `make` as follows: ``` $ make V=1 ``` Also, if you are compiling on a multicore system, you can get parallelism via: ``` $ make -j ``` where `` is the number of jobs `make` is allowed to run simultaneously. Generally, you should limit `` to p+1, where p is the number of processor cores on your system. ### Running into the ARG_MAX limit On some systems, you may observe an error message when the build system attempts to archive BLIS object files into the static library (or perhaps when the linker attempts to generate the shared library): ``` Archiving lib/x86_64/libblis.a bash: ar: Argument list too long Makefile:584: recipe for target 'lib/x86_64/libblis.a' failed make: *** [lib/x86_64/libblis.a] Error 126 ``` This error message results when the user attempts to execute a program with too many arguments (or more specifically, a program-argument string that occupies too many bytes)--that is, when the command exceeds the [ARG_MAX limit](https://www.in-ulm.de/~mascheck/various/argmax/). This doesn't occur very often, but if it does, don't worry--we have a workaround. Simply rerun `configure` as you did previously, except this time include an addition option: `--enable-arg-max-hack`. You will see confirmation that the option was accepted as configure runs: ``` configure: enabling ARG_MAX hack. ``` The archiver and/or linker should no longer choke when creating the libraries. ## Step 3b: Testing (optional) If you would like to run some ready-made tests that exercise BLIS in a number of ways, including through its BLAS compatibility layer, run `make check`: ``` $ make check ``` Watch the output near the end. You should see the following messages, though not necessarily in immediate succession: ``` All BLIS tests passed! All BLAS tests passed! ``` Please see the [Testsuite](Testsuite.md) document for more details on running either the BLIS testsuite or the BLAS test drivers. If you have any trouble, please report your problem to BLIS developers by opening a [new issue](https://github.com/flame/blis/issues/). ## Step 4: Installation Toward the end of compilation, you should get output similar to: ``` Compiling obj/haswell/frame/thread/bli_thread.o ('haswell' CFLAGS for framework code) Compiling obj/haswell/frame/thread/bli_thrinfo.o ('haswell' CFLAGS for framework code) Compiling obj/haswell/frame/util/bli_util_check.o ('haswell' CFLAGS for framework code) Compiling obj/haswell/frame/util/bli_util_oapi.o ('haswell' CFLAGS for framework code) Compiling obj/haswell/frame/util/bli_util_oapi_wc.o ('haswell' CFLAGS for framework code) Compiling obj/haswell/frame/util/bli_util_oapi_woc.o ('haswell' CFLAGS for framework code) Compiling obj/haswell/frame/util/bli_util_tapi.o ('haswell' CFLAGS for framework code) Compiling obj/haswell/frame/util/bli_util_unb_var1.o ('haswell' CFLAGS for framework code) Archiving lib/haswell/libblis.a Dynamically linking lib/haswell/libblis.so ``` Now you have a BLIS library (in static and shared forms) residing in the `lib//` directory. To install the libraries and the header files associated with it, simply execute: ``` $ make install ``` This installs copies of the libraries and header files, and also creates conventional symbolic links of shared libraries: ``` Installing libblis.a into /u/field/blis/lib/ Installing libblis.so.0.0.0 into /u/field/blis/lib/ Installing symlink libblis.so into /u/field/blis/lib/ Installing symlink libblis.so.0 into /u/field/blis/lib/ Installing blis.h into /u/field/blis/include/blis/ ``` This results in your `PREFIX` directory looking like: ``` # Check the contents of 'PREFIX'. $ ls -l $HOME/blis drwxr-xr-x 3 field dept 4096 May 10 17:36 include drwxr-xr-x 2 field dept 4096 May 10 17:42 lib # Check the contents of 'PREFIX/include'. $ ls -l $HOME/blis/include drwxr-xr-x 2 field dept 4096 May 10 17:42 blis $ ls -l $HOME/blis/include/blis -rw-r--r-- 1 field dept 915324 May 10 17:42 blis.h # Check the contents of 'PREFIX/lib'. $ ls -l $HOME/blis/lib -rw-r--r-- 1 field dept 2979052 May 10 17:42 libblis.a lrwxrwxrwx 1 field dept 16 May 10 17:42 libblis.so -> libblis.so.0.0.0 lrwxrwxrwx 1 field dept 16 May 10 17:42 libblis.so.0 -> libblis.so.0.0.0 -rw-r--r-- 1 field dept 2185976 May 10 17:42 libblis.so.0.0.0 ``` ## Cleaning out build products If you want to remove various build products, you can use one of the `make` targets already defined for you in the BLIS Makefile: ``` $ make clean Removing flattened header files from ./include/haswell. Removing object files from ./obj/haswell. Removing libraries from ./lib/haswell. ``` Executing the `clean` target will remove all binary object files and library builds from the `obj` and `lib` directories, as well as any flattened header files. Any other configurations' build products are left untouched. ``` $ make cleanmk Removing makefile fragments from ./config. Removing makefile fragments from ./frame. Removing makefile fragments from ./ref_kernels. Removing makefile fragments from ./kernels. ``` The `cleanmk` target results in removal of all makefile fragments from the framework source tree. (Makefile fragments are named `.fragment.mk` and are generated at configure-time.) ``` $ make distclean Removing makefile fragments from ./config. Removing makefile fragments from ./frame. Removing makefile fragments from ./ref_kernels. Removing makefile fragments from ./kernels. Removing flattened header files from ./include/haswell. Removing object files from ./obj/haswell. Removing libraries from ./lib/haswell. Removing object files from ./obj/haswell/blastest. Removing libf2c.a from ./obj/haswell/blastest. Removing binaries from ./obj/haswell/blastest. Removing driver output files 'out.*'. Removing object files from ./blastest/obj. Removing libf2c.a from ./blastest. Removing binaries from ./blastest. Removing driver output files 'out.*' from ./blastest. Removing object files from ./obj/haswell/testsuite. Removing binary test_libblis.x. Removing output.testsuite. Removing object files from testsuite/obj. Removing binary testsuite/test_libblis.x. Removing ./bli_config.h. Removing config.mk. Removing obj. Removing lib. Removing include. ``` Running the `distclean` target is like saying, "Remove anything ever created by the build system." ## Compiling with BLIS All BLIS definitions and prototypes may be included in your C source file by including a single header file, `blis.h`: ```c #include "stdio.h" #include "stdlib.h" #include "otherstuff.h" #include "blis.h" ``` If the BLAS compatibility layer was enabled at configure-time (as it is by default), then `blis.h` will also provide BLAS prototypes to your source code. ### Disabling BLAS prototypes Some applications already `#include` a header that contains BLAS prototypes. This can cause problems if those applications also try to `#include` the BLIS header file, as shown above. Suppose for a moment that `otherstuff.h` in the example above already provides BLAS prototypes. ``` $ gcc -I/path/to/blis -I/path/to/otherstuff -c main.c -o main.o In file included from main.c:41:0: /path/to/blis/blis.h:36900:111: error: conflicting declaration of C function ‘int xerbla_(const bla_character*, const bla_integer*, ftnlen)’ TEF770(xerbla)(const bla_character *srname, const bla_integer *info, ftnlen srname_len); ``` If your application is already declaring (prototyping) BLAS functions, then you may disable those prototypes from being defined included within `blis.h`. This prevents `blis.h` from re-declaring those prototypes, or, allows your other header to declare those functions for the first time, depending on the order that you `#include` the headers. ```c #include "stdio.h" #include "stdlib.h" #include "otherstuff.h" #define BLIS_DISABLE_BLAS_DEFS // disable BLAS prototypes within BLIS. #include "blis.h" ``` By `#defining` the `BLIS_DISABLE_BLAS_DEFS` macro, we signal to `blis.h` that it should skip over the BLAS prototypes, but otherwise `#include` everything else as it normally would. Note that `BLIS_DISABLE_BLAS_DEFS` must be `#defined` *prior* to the `#include "blis.h"` directive in order for it to have any effect. ### CBLAS If you build BLIS with CBLAS enabled and you wish to access CBLAS function prototypes from within your application, you will have to `#include` the `cblas.h` header separately from `blis.h`. ``` #include "blis.h" #include "cblas.h" ``` ## Linking against BLIS Once you have instantiated (configured and compiled, and perhaps installed) a BLIS library, you can link to it in your application's makefile as you would any other library. The following is an abbreviated makefile for a small hypothetical application that has just two external dependencies: BLIS and the standard C math library. We also link against libpthread since that library has been a runtime dependency of BLIS since 70640a3 (December 2017). ```make BLIS_PREFIX = $(HOME)/blis BLIS_INC = $(BLIS_PREFIX)/include/blis BLIS_LIB = $(BLIS_PREFIX)/lib/libblis.a OTHER_LIBS = -L/usr/lib -lm -lpthread CC = gcc CFLAGS = -O2 -g -I$(BLIS_INC) LINKER = $(CC) OBJS = main.o util.o other.o %.o: %.c $(CC) $(CFLAGS) -c $< -o $@ all: $(OBJS) $(LINKER) $(OBJS) $(BLIS_LIB) $(OTHER_LIBS) -o my_program.x ``` The above example assumes you will want to include BLIS definitions and function prototypes into your application via `#include blis.h`. (If you are only using the BLIS via the BLAS compatibility layer, including `blis.h` is not necessary.) Since BLIS headers are installed into a `blis` subdirectory of `PREFIX/include`, you must make sure that the compiler knows where to find the `blis.h` header file. This is typically accomplished by inserting `#include "blis.h"` into your application's source code files and compiling the code with `-I PREFIX/include/blis`. The makefile shown above a very simple example. If you need help linking your application to your BLIS library, please [open an issue](https://github.com/flame/blis/issues). ## Uninstalling If you decide that you want to uninstall BLIS, simply run `make uninstall` ``` $ make uninstall Uninstalling libraries libblis.a libblis.so.0.0.0 from /u/field/blis/lib/. Uninstalling symlinks libblis.so libblis.so.0 from /u/field/blis/lib/. Uninstalling directory 'blis' from /u/field/blis/include/. ``` This removes the libraries, symlinks, and header directory that was installed by `make install`. Before running `make uninstall`, however, make sure that BLIS is configured the with the same `LIBDIR` and `INCDIR` paths used during installation. ## `make` targets The BLIS `Makefile` implements many `make` targets. The table below lists most of the interesting ones that typical users and developers may wish to use. | `make` target | Description | |:----------------|:---------------------------------------------------| | `all` | Execute `libs` target. | | `libs` | Compile BLIS as a static and/or shared library (depending on `configure` options). | | `test` | Execute `checkblis` and `checkblas` targets. | | `check` | Execute `checkblis-fast` and `checkblas` targets. | | `checkblis` | Execute `testblis` and characterize the results to `stdout`. | | `checkblis-fast`| Execute `testblis-fast` and characterize the results to `stdout`. | | `checkblis-md` | Execute `testblis-md` and characterize the results to `stdout`. | | `checkblis-salt`| Execute `testblis-salt` and characterize the results to `stdout`. | | `checkblas` | Execute `testblas` and characterize the results to `stdout`. | | `testblis` | Run the BLIS testsuite with default parameters (runs for 2-8 minutes). | | `testblis-fast` | Run the BLIS testsuite with "fast" parameters (runs for a few seconds). | | `testblis-md` | Run the BLIS testsuite for `gemm` with full mixing of datatypes (runs for 10-30 seconds). | | `testblis-salt` | Run the BLIS testsuite while simulating application-level threading (runs for a few seconds). | | `testsuite` | Same as `testblis`. | | `testblas` | Run the BLAS test drivers with default parameters (runs for a few seconds). | | `showconfig` | Show a summary of currently selected `configure` options. | | `clean` | Execute `cleanh` and `cleanlib`. | | `cleanmk` | Remove `.fragment.mk` makefile fragments generated by `configure`. | | `cleanh` | Remove the flattened header file(s) in `include//`. | | `cleanlib` | Remove the libraries in `lib//`. | | `cleantest` | Remove build products produced by `testblis`/`testblis-fast` and `testblas`. | | `install` | Install libraries and header files to installation directories. | | `uninstall` | Uninstall libraries and header files that reside within installation directories. | | `uninstall-old` | Uninstall older libraries and header files that reside within installation directories. | For more details on `configure` options, such as enabling/disabling static or shared library generation, or specifying installation directories for libraries and/or headers, please review the output of `./configure --help`. ## Conclusion If you have feedback, please consider keeping in touch with the project maintainers, contributors, and other users by joining and posting to the [BLIS mailing lists](https://github.com/flame/blis#discussion). Thanks for using BLIS! blis-0.9.0/docs/CodingConventions.md000066400000000000000000000233001422157504600173600ustar00rootroot00000000000000## Contents * **[Contents](CodingConventions.md#contents)** * **[Introduction](CodingConventions.md#introduction)** * **[C99](CodingConventions.md#c99)** * [Placement of braces](CodingConventions.md#placement-of-braces) * [Indentation](CodingConventions.md#indentation) * [Comments](CodingConventions.md#comments) * [Blank lines](CodingConventions.md#blank-lines) * [Condensing short code to single lines](CodingConventions.md#condensing-short-code-to-single-lines) * [Whitespace in function calls](CodingConventions.md#whitespace-in-function-calls) * [Whitespace in function definitions](CodingConventions.md#whitespace-in-function-definitions) * [Whitespace in expressions](CodingConventions.md#whitespace-in-expressions) * [Trailing whitespace](CodingConventions.md#trailing-whitespace) ## Introduction This wiki describes the coding conventions used in BLIS. Please try to adhere to these conventions when submitting pull requests and/or (if you have permission) committing directly to the repository. There is some support for these conventions for Emacs editing in the `.dir-locals.el` file, which will affect editing with CC mode in the blis directory. ## C99 Most of the code in BLIS is written in C, and specifically in ISO C99. This section describes the C coding standards used within BLIS. ### Placement of braces Please either use braces to denote the indentation limits of scope, or to enclose multiple statements on a single line. But do not place the open brace on the same line as a conditional if the conditional will be more than one line. ```c { // This is fine. if ( bli_obj_is_real( x ) ) { foo = 1; } // This is also fine. (Ideal for short conditional bodies.) if ( bli_obj_is_real( x ) ) { foo = 1; return; } // This is bad. Please use one of the two forms above. if ( bli_obj_is_real( x ) ) { foo = 1; } // This is (much) worse. Please no. if ( bli_obj_is_real( x ) ) { foo = 1; } } ``` ### Indentation If at all possible, **please use tabs to denote changing levels of scope!** If you can't use tabs or doing so would be very inconvenient given your editor and setup, please set your indentation to use exactly four spaces per level of indentation. Below is what it would look like if you used tabs (with a tab width set to occupy four spaces), or four actual spaces per indentation level. ```c bool bli_obj_is_real( obj_t* x ) { bool r_val; if ( bli_obj_is_real( x ) ) r_val = TRUE; else r_val = FALSE; } ``` Ideally, tabs should be used to indicate changes in levels of scope, but then spaces should be used for multi-line statements within the same scope. In the example below, I've marked the characters that should be spaces with `.` (with tabs used for the first level of indentation): ```c bool bli_obj_is_complex( obj_t* x ) { bool r_val; if ( bli_obj_is_scomplex( x ) || .....bli_obj_is_dcomplex( x ) ) r_val = TRUE; else............................r_val = FALSE; return r_val; } ``` ### Comments Please use C++-style comments, and line-break your comments somewhere between character (column) 72 and 80. ```c { // This is a comment. This comment can span multiple lines, but it should // not extend beyond column 80. (For these purposes, you can count a tab // as anywhere from one to four spaces.) } ``` If you are inserting comments in a macro definition, in which case you must use C-style comments: ```c #define bli_some_macro( x ) \ \ /* This is a comment in a macro definition. It, too, should not spill beyond column 80. Please place the ending comment marker on the last line containing words, unless the comment marker would cause you to go beyond column 80, in which case you can place it on the next line aligned with the first comment marker. */ ``` ### Blank lines Please use blank lines to separate lines of code from the next line of code. However, if adjacent lines of code are meaningfully related, please skip the blank line. ```c { // Set the matrix datatype. bli_obj_set_dt( BLIS_DOUBLE, x ); // Set the matrix dimensions. bli_obj_set_length( 10, x ); bli_obj_set_width( 5, x ); // Set the matrix structure. bli_obj_set_struc( BLIS_GENERAL, x ); bli_obj_set_uplo( BLIS_DENSE, x ); } ``` ### Condensing short code to single lines Sometimes, to more efficiently display code on the screen, it's helpful to skip certain newlines, such as those in conditional statements. This is fine, just try to line things up in a way that is visually appealing. ```c { bool r_val; dim_t foo; // This is fine. if ( bli_obj_is_real( x ) ) r_val = TRUE; else r_val = FALSE; // This is okay. (Notice the spaces after '{' and before '}'.) // However, the next example is preferred over this style. if ( bli_obj_is_real( x ) ) { r_val = TRUE; foo = 1; } else { r_val = FALSE; foo = 0; } // Similar to above, but with some extra alignment. This is better // than above. if ( bli_obj_is_real( x ) ) { r_val = TRUE; foo = 1; } else { r_val = FALSE; foo = 0; } } ``` ### Whitespace in function calls For single-line function calls, **please avoid** a space between the last character in the function/macro name and the open parentheses. Also, please do not insert any spaces before commas that separate arguments to a function/macro invocation. But please **do** insert at least once space after each comma. (I say "at least one" because sometimes it looks nicer to align the commas with those of function calls on lines above or below the function call in question.) Also, please include one space between the opening parentheses and the first argument, and also between the last argument and closing parentheses ```c { obj_t x; // Good. bli_obj_create( BLIS_DOUBLE, 3, 4, 0, 0, &x ); bli_obj_set_length( 10, x ); // Bad. Please avoid these. bli_obj_set_dt ( BLIS_FLOAT, x ); bli_obj_set_dt( BLIS_FLOAT , x ); bli_obj_set_dt(BLIS_FLOAT, x); bli_obj_set_dt(BLIS_FLOAT,x); // Good. bli_obj_set_dt( BLIS_FLOAT, x ); } ``` For multi-line function calls, please use the following template: ```c { bli_dgemm ( BLIS_NO_TRANSPOSE, BLIS_TRANSPOSE, m, n, k, &BLIS_ONE a, rs_a, cs_a, b, rs_b, cs_b, &BLIS_ZERO, c, rs_c, cs_c ); } ``` Notice that here, the parentheses are formatted similar to braces. However, notice that the arguments do not constitute a new level of "scope." Instead, you should use exactly two additional spaces. before each line of arguments. ### Whitespace in function definitions When defining a function with few arguments, insert a single space after commas and types, and after the first parentheses and before the last parentheses: ```c // Please write "short" function signatures like this. void bli_obj_set_length( dim_t m, obj_t* a ) { // Body of function } ``` As with single-line function calls, please do not place a space between the last character of the function name and the open parentheses to the argument list! ```c // Please avoid this. void bli_obj_set_length ( dim_t m, obj_t* a ) { // Body of function } ``` When defining a function with many arguments, especially those that would not comfortably fit in a single 80-character line, you can split the type signature into multiple lines: ```c // Please write "long" function signatures like this. void bli_gemm ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx ) { // Body of function } ``` If you are going to use this style of function definition, please indent the parentheses exactly five spaces (don't use tabs here). Then, indent the arguments with an additional two spaces. Thus, parentheses should be in column 6 (counting from 1) and argument types should begin in column 8. Also notice that the number of spaces after each argument's type specifier varies so that the argument names are aligned. If you insert qualifiers such as `restrict`, please right-justify them: ```c // Please align 'restrict' keywords and variables, as appropriate. void bli_gemm ( obj_t* restrict alpha, obj_t* restrict a, obj_t* restrict b, obj_t* restrict beta, obj_t* restrict c, cntx_t* restrict cntx ) { // Body of function } ``` ### Whitespace in expressions Please insert whitespace into conditional expressions. ```c { // Good. if ( m == 10 && n > 0 ) return; // Bad. if ( m==10 && n>0 ) return; // Worse! if (m==10&&n>0) return; // Okay, now you're just messing with me. if(m==10&&n>0)return; } ``` Unlike with the parentheses that surround the argument list of a function call, there should be exactly one space after conditional keywords and the open parentheses for its associated conditional statement: `if (...)`, `else if (...)`, and `while (...)`. ```c { // Good. if ( ... ) return 0; else if ( ... ) return 1; // Good. while ( ... ) { // loop body. } // Good. do { // loop body. } while ( ... ); } ``` Sometimes, extra spaces for alignment are desired: ```c { // This is okay. if ( m == 0 ) return 0; else if ( n == 0 ) return 1; // This is sometimes preferred because it allows your eyes to more easily // see the differences between the 'if' conditional expression and the // 'else if' conditional expression. if ( m == 0 ) return 0; else if ( n == 0 ) return 1; } ``` ### Trailing whitespace Please try to avoid inserting any trailing whitespace. This also means that "blank" lines should not contain any tabs or spaces. blis-0.9.0/docs/ConfigurationHowTo.md000066400000000000000000002050071422157504600175250ustar00rootroot00000000000000## Contents * **[Contents](ConfigurationHowTo.md#contents)** * **[Introduction](ConfigurationHowTo.md#introduction)** * **[Sub-configurations](ConfigurationHowTo.md#sub-configurations)** * [`bli_cntx_init_*.c`](ConfigurationHowTo.md#bli_cntx_init_c) * [`bli_family_*.h`](ConfigurationHowTo.md#bli_family_h) * [`make_defs.mk`](ConfigurationHowTo.md#make_defsmk) * **[Configuration families](ConfigurationHowTo.md#configuration-families)** * **[Configuration registry](ConfigurationHowTo.md#configuration-registry)** * [Walkthrough](ConfigurationHowTo.md#walkthrough) * [Printing the configuration registry lists](ConfigurationHowTo.md#printing-the-configuration-registry-lists) * **[Adding a new kernel set](ConfigurationHowTo.md#adding-a-new-kernel-set)** * **[Adding a new configuration family](ConfigurationHowTo.md#adding-a-new-configuration-family)** * **[Adding a new sub-configuration](ConfigurationHowTo.md#adding-a-new-sub-configuration)** * **[Further development topics](ConfigurationHowTo.md#further-development-topics)** * [Querying the current configuration](ConfigurationHowTo.md#querying-the-current-configuration) * [Header dependencies](ConfigurationHowTo.md#header-dependencies) * [Still have questions?](ConfigurationHowTo.md#still-have-questions) ## Introduction This document describes how to manage, edit, and create BLIS framework configurations. **The target audience is primarily BLIS developers** who wish to add support for new types of hardware, and developers who write (or tinker with) BLIS kernels. The BLIS [Build System](BuildSystem.md) guide introduces the concept of a BLIS [configuration](BuildSystem.md#Step_1:_Choose_a_framework_configuration). There are actually two types of configurations: sub-configuration and configuration families. A _sub-configuration_ encapsulates all of the information needed to build BLIS for a particular microarchitecture. For example, the `haswell` configuration allows a user or developer to build a BLIS library that targets hardware based on Intel Haswell (or Broadwell or Skylake/Kabylake desktop) microprocessors. Such a sub-configuration typically includes optimized kernels as well as the corresponding cache and register blocksizes that allow those kernels to work well on the target hardware. A _configuration family_ simply specifies a collection of other registered sub-configurations. For example, the `intel64` configuration allows a user or developer to build a BLIS library that includes several Intel x86_64 configurations, and hence supports multiple microarchitectures simultaneously. The appropriate configuration information (e.g. kernels and blocksizes) will be selected via some hardware detection heuristic (e.g. the `CPUID` instruction) at runtime. (**Note:** Prior to 290dd4a, configuration families could only be defined in terms of sub-configurations. Starting with 290dd4a, configuration families may be defined in terms of other families.) Both of these configuration types are organized as directories of files and then "registered" into a configuration registry file named `config_registry`, which resides in the top-level directory. ## Sub-configurations A sub-configuration is represented by a sub-directory of the `config` directory in the top-level of the BLIS distribution: ``` $ ls config amd64 cortexa15 excavator intel64 old power7 template bgq cortexa57 generic knc penryn sandybridge zen bulldozer cortexa9 haswell knl piledriver steamroller ``` Let's inspect the `haswell` configuration as an example: ``` $ ls config/haswell bli_cntx_init_haswell.c bli_family_haswell.h make_defs.mk ``` A sub-configuration (`haswell`, in this case) usually contains just three files: * `bli_cntx_init_haswell.c`. This file contains the initialization function for a context targeting the hardware in question, in this case, Intel Haswell. A context, or `cntx_t` object, in BLIS encapsulates all of the hardware-specific information--including kernel function pointers and cache and register blocksizes--necessary to support all of the main computational operations in BLIS. The initialization function inside this file should be named the same as the filename (excluding `.c` suffix), which should begin with prefix `bli_cntx_init_` and end with the (lowercase) name of the sub-configuration. The context initialization function (in this case, `bli_cntx_init_haswell()`) is used internally by BLIS when setting up the global kernel structure--a mechanism for managing and supporting multiple microarchitectures simultaneously, so that the choice of which context to use can be deferred until the computation is ready to execute. * `bli_family_haswell.h`. This header file is `#included` when the configuration in question, in this case `haswell`, was the target to `./configure`. This is where you would specify certain global parameters and settings. For example, if you wanted to specify custom implementations of `malloc()` and `free()`, this is where you would specify them. The file is oftentimes empty. (In the case of configuration families, the definitions in this file apply to the _entire_ build, and not any specific sub-configuration, but for consistency we support them for all configuration targets, whether they be singleton sub-configurations or configuration families.) * `make_defs.mk`. This makefile fragment defines the compiler and compiler flags to use during compilation. Specifically, the values defined in this file are used whenever compiling source code specific to the sub-configuration (i.e., reference kernels and optimized kernels). If the sub-configuration is the target of `configure`, then these flags are also used to compile general framework code. Providing these three components constitutes a complete sub-configuration. A more detailed description of each file will follow. ### bli_cntx_init_*.c As mentioned above, the kernels used by a sub-configuration are specified in the `bli_cntx_init_` function. This function is flexible in that the context is typically initialized with a set of "reference" kernels. Then, the kernel developer overwrites the fields in the context that correspond to kernel operations that have optimized counterparts that should be used instead. Let's use the following hypothetical function definition to guide our walkthrough. ```c #include "blis.h" void bli_cntx_init_fooarch( cntx_t* cntx ) { blksz_t blkszs[ BLIS_NUM_BLKSZS ]; // Set default kernel blocksizes and functions. bli_cntx_init_fooarch_ref( cntx ); // ------------------------------------------------------------------------- // Update the context with optimized native gemm microkernels and // their storage preferences. bli_cntx_set_l3_nat_ukrs ( 5, BLIS_GEMM_UKR, BLIS_DOUBLE, bli_dgemm_bararch_asm, FALSE, BLIS_GEMMTRSM_L_UKR, BLIS_DOUBLE, bli_dgemmtrsm_l_bararch_asm, FALSE, BLIS_GEMMTRSM_U_UKR, BLIS_DOUBLE, bli_dgemmtrsm_u_bararch_asm, FALSE, BLIS_TRSM_L_UKR, BLIS_DOUBLE, bli_dtrsm_l_bararch_asm, FALSE, BLIS_TRSM_U_UKR, BLIS_DOUBLE, bli_dtrsm_u_bararch_asm, FALSE, cntx ); // Update the context with optimized packm kernels. bli_cntx_set_packm_kers ( 2, BLIS_PACKM_4XK_KER, BLIS_DOUBLE, bli_dpackm_bararch_asm_4xk, BLIS_PACKM_8XK_KER, BLIS_DOUBLE, bli_dpackm_bararch_asm_8xk, cntx ); // Update the context with optimized level-1f kernels. bli_cntx_set_l1f_kers ( 5, BLIS_AXPY2V_KER, BLIS_DOUBLE, bli_daxpy2v_fooarch_asm, BLIS_DOTAXPYV_KER, BLIS_DOUBLE, bli_ddotaxpyv_fooarch_asm, BLIS_AXPYF_KER, BLIS_DOUBLE, bli_daxpyf_fooarch_asm, BLIS_DOTXF_KER, BLIS_DOUBLE, bli_ddotxf_fooarch_asm, BLIS_DOTXAXPYF_KER, BLIS_DOUBLE, bli_ddotxaxpyf_fooarch_asm, cntx ); // Update the context with optimized level-1v kernels. bli_cntx_set_l1v_kers ( 2, BLIS_AXPYV_KER, BLIS_DOUBLE, bli_daxpyv_fooarch_asm, BLIS_DOTV_KER, BLIS_DOUBLE, bli_ddotv_fooarch_asm, cntx ); // Initialize level-3 blocksize objects with architecture-specific values. // s d c z bli_blksz_init_easy( &blkszs[ BLIS_MR ], 8, 8, 8, 4 ); bli_blksz_init_easy( &blkszs[ BLIS_NR ], 8, 4, 4, 4 ); bli_blksz_init_easy( &blkszs[ BLIS_MC ], 128, 128, 128, 128 ); bli_blksz_init_easy( &blkszs[ BLIS_KC ], 256, 256, 256, 256 ); bli_blksz_init_easy( &blkszs[ BLIS_NC ], 4096, 4096, 4096, 4096 ); // Update the context with the current architecture's register and cache // blocksizes (and multiples) for native execution. bli_cntx_set_blkszs ( BLIS_NAT, 5, BLIS_NC, &blkszs[ BLIS_NC ], BLIS_NR, BLIS_KC, &blkszs[ BLIS_KC ], BLIS_KR, BLIS_MC, &blkszs[ BLIS_MC ], BLIS_MR, BLIS_NR, &blkszs[ BLIS_NR ], BLIS_NR, BLIS_MR, &blkszs[ BLIS_MR ], BLIS_MR, cntx ); } ``` _**Function name/signature.**_ This function always takes one argument, a pointer to a `cntx_t` object. As with the name of the file, it should be named with the prefix `bli_cntx_init_` followed by the lowercase name of the configuration--in this case, `fooarch`. _**Blocksize object array.**_ The `blkszs` array declaration is needed later in the function and should generally be consistent (and unchanged) across all configurations. _**Reference initialization.**_ The first function call, `bli_cntx_init_fooarch_ref()`, initializes the context `cntx` with function pointers to reference implementations of all of the kernels supported by BLIS (as well as cache and register blocksizes, and other fields). This function is automatically generated by BLIS for every sub-configuration enabled at configure-time. The function prototype is generated by a preprocessor macro in `frame/include/bli_arch_config.h`. _**Level-3 microkernels.**_ The second function call is to a variable argument function, `bli_cntx_set_l3_nat_ukrs()`, which updates `cntx` with five optimized double-precision complex level-3 microkernels. The first argument encodes the number of individual kernels being registered into the context. Every subsequent line, except for the last line, is associated with the registration of a single kernel, and each of these lines is independent of one another and can occur in any order, provided that the kernel parameters of each line occur in the same order--kernel ID, followed by datatype, followed by function name, followed by storage preference boolean (i.e., whether the microkernel prefers row storage). The last argument of the function call is the address of the context being updated, `cntx`. Notice that we are registering microkernels written for another type of hardware, `bararch`, because in our hypothetical universe `bararch` is very similar to `fooarch` and so we recycle the code between the two configurations. After the function returns, the context contains pointers to optimized double-precision level-3 real microkernels. Note that the context will still contain reference microkernels for single-precision real and complex, and double-precision complex computation, as those kernels were not updated. _Note:_ Currently, BLIS only allows the kernel developer to signal a preference (row or column) for `gemm` microkernels. The preference of the `gemmtrsm` and `trsm` microkernels can (and must) be set, but are ignored by the framework during execution. _**Level-1m (packm) kernels.**_ The third function call is to another variable argument function, `bli_cntx_set_packm_kers()`. This function works very similar to `bli_cntx_set_l3_nat_ukrs()`, except that it expects a different set of kernel IDs (because now we are registering level-1m kernels) and it does not take a storage preference boolean. After this function returns, `cntx` contains function pointers to optimized double-precision real `packm` kernels. These kernels, like the level-3 kernels previously, are also borrowed from the `bararch` kernel set. Unregistered `packm` kernels will continue to point to reference code. _**Level-1f kernels.**_ The third function call is to yet another variable argument function, `bli_cntx_set_l1f_kers()`. This function has the same signature as `bli_cntx_set_packm_kers()`, except that it expects a different set of kernel IDs (because now we are registering level-1f kernels). After this function returns, `cntx` contains function pointers to optimized double-precision real level-1f kernels. These kernels are written for `fooarch` specifically. The unregistered level-1f kernels will continue to point to reference code. _**Level-1v kernels.**_ The fourth function call is to `bli_cntx_set_l1v_kers()`, which operates similarly to the `bli_cntx_set_l1f_kers()`, except here we are registering level-1v kernels. After the function returns, most kernels will continue to point to reference code, except double-precision real instances of `axpyv` and `dotv`. For a complete list of kernel IDs, please see the definitions of `l3ukr_t`, `l1mkr_t`, `l1fkr_t`, `l1vkr_t` in [frame/include/bli_type_defs.h](https://github.com/flame/blis/blob/master/frame/include/bli_type_defs.h). _**Setting blocksizes.**_ The next block of code initializes the `blkszs` array with register and cache blocksize values for each datatype. The values here are used by the level-3 operations that employ the level-3 microkernels we registered previously. We use `bli_blksz_init_easy()` when initializing only the primary value. If the auxiliary value needs to be set to a different value that the primary, `bli_blksz_init()` should be used instead, as in: ```c // s d c z bli_blksz_init_easy( &blkszs[ BLIS_MR ], 0, 8, 0, 0 ); bli_blksz_init_easy( &blkszs[ BLIS_NR ], 0, 4, 0, 0 ); bli_blksz_init ( &blkszs[ BLIS_MC ], 0, 128, 0, 0, 0, 160, 0, 0 ); bli_blksz_init ( &blkszs[ BLIS_KC ], 0, 256, 0, 0, 0, 288, 0, 0 ); bli_blksz_init_easy( &blkszs[ BLIS_NC ], 0, 4096, 0, 0 ); ``` Here, we use `bli_blksz_init()` to set different auxiliary (maximum) cache blocksizes for _MC_ and _KC_. The same function could be used to set auxiliary (packing) register blocksizes for _MR_ and _NR_, which correspond to the _PACKMR_ and _PACKNR_ parameters. Other blocksizes, particularly those corresponding to level-1f operations, may be set. For a complete list of blocksize IDs, please see the definitions of `bszid_t` in [frame/include/bli_type_defs.h](https://github.com/flame/blis/blob/master/frame/include/bli_type_defs.h). For more information on interpretations of the auxiliary blocksize value, see the digressions below. Note that we set level-3 blocksizes even for datatypes that retain reference code kernels; however, by passing in `0` for those blocksizes, we indicate to `bli_blksz_init()` and `bli_blksz_init_easy()` that the current value should be left untouched. In the example above, this leaves the blocksizes associated with the reference kernels (set by `bli_cntx_init_fooarch_ref()`) intact for the single real, single complex, and double complex datatypes. _Digression:_ Auxiliary blocksize values for register blocksizes are interpreted as the "packing" register blocksizes. _PACKMR_ and _PACKNR_ serve as "leading dimensions" of the packed micropanels that are passed into the microkernel. Oftentimes, _PACKMR = MR_ and _PACKNR = NR_, and thus the developer does not typically need to set these values manually. (See the [implementation notes for gemm](KernelsHowTo.md#Implementation_Notes_for_gemm) in the BLIS Kernel guide for more details on these topics.) _Digression:_ Auxiliary blocksize values for cache blocksizes are interpreted as the maximum cache blocksizes. The maximum cache blocksizes are a convenient and portable way of smoothing performance of the level-3 operations when computing with a matrix operand that is just slightly larger than a multiple of the preferred cache blocksize in that dimension. In these "edge cases," iterations run with highly sub-optimal blocking. We can address this problem by merging the "edge case" iteration with the second-to-last iteration, such that the cache blocksizes are slightly larger--rather than significantly smaller--than optimal. The maximum cache blocksizes allow the developer to specify the _maximum_ size of this merged iteration; if the edge case causes the merged iteration to exceed this maximum, then the edge case is _not_ merged and instead it is computed upon in separate (final) iteration. _**Committing blocksizes.**_ Finally, we commit the values in `blkszs` to the context by calling the variable argument function `bli_cntx_set_blkszs()`. This function call generally should be considered boilerplate and thus should not changed unless you are altering the matrix multiplication _algorithm_ as specified in the control tree. If this is your goal, please get in contact with BLIS developers via the [blis-devel](http://groups.google.com/group/blis-devel) mailing list for guidance, if you have not done so already. _**Availability of kernels.**_ Note that any kernel made available to the `fooarch` configuration within `config_registry` may be referenced inside `bli_cntx_init_fooarch()`. In this example, we referenced `fooarch` kernels as well as kernels native to another configuration, `bararch`. Thus, the `config_registry` would contain a line such as: ``` fooarch: fooarch/fooarch/bararch ``` Interpreting the line left-to-right: the `fooarch` configuration family contains only itself, `fooarch`, but must be able to refer to kernels from its own kernel set (`fooarch`) as well as kernels belonging to the `bararch` kernel set. The configuration registry is described more completely [in a later section](ConfigurationHowTo.md#configuration-registry). ### bli_family_*.h This file is conditionally `#included` only for the configuration family targeted at configure-time. For example, if you run `./configure haswell`, `bli_family_haswell.h` will be `#included`, and if you run `./configure intel64`, `bli_family_intel64.h` will be `#included`. The header file is `#included` by [frame/include/bli_arch_config.h](https://github.com/flame/blis/blob/master/frame/include/bli_arch_config.h). This header file is oftentimes empty. This is because the parameters specified here usually work fine with their default values, which are defined in [frame/include/bli_kernel_macro_defs.h](https://github.com/flame/blis/blob/master/frame/include/bli_kernel_macro_defs.h). However, there may be some configurations for which a kernel developer will wish to adjust some of these parameters. Furthermore, when creating a configuration family, the parameters set in the corresponding `bli_family_*.h` file must work for **all** sub-configurations in the family. A description of the parameters that may be set in `bli_family_*.h` follows. _**Memory allocation functions.**_ BLIS allows the developer to customize the functions called for memory allocation for three different categories of memory: user, pool, and internal. The functions for user allocation are called any time the creation of a BLIS matrix or vector `obj_t` requires that a matrix buffer be allocated, such as via `bli_obj_create()`. The functions for pool allocation are called only when allocating blocks to the memory pools used to manage packed matrix buffers. The function for internal allocation are called by BLIS when allocating internal data structures, such as control trees. By default, the three pairs of parameters are defined via preprocessor macros to call the implementation of `malloc()` and `free()` provided by `stdlib.h`: ```c #define BLIS_MALLOC_USER malloc #define BLIS_FREE_USER free #define BLIS_MALLOC_POOL malloc #define BLIS_FREE_POOL free #define BLIS_MALLOC_INTL malloc #define BLIS_FREE_INTL free ``` Any substitute for `malloc()` and `free()` defined by customizing these parameters must use the same function prototypes as the original functions. Namely: ```c void* malloc( size_t size ); void free( void* p ); ``` Furthermore, if a header file needs to be included, such as `my_malloc.h`, it should be `#included` within the `bli_family_*.h` file (before `#defining` any of the `BLIS_MALLOC_` and `BLIS_FREE_` macros). _**SIMD register file.**_ BLIS allows you to specify the _maximum_ number of SIMD registers available for use by your kernels, as well as the _maximum_ size (in bytes) of those registers. These values default to: ```c #define BLIS_SIMD_MAX_NUM_REGISTERS 32 #define BLIS_SIMD_MAX_SIZE 64 ``` These macros are used in computing the maximum amount of temporary storage (typically allocated statically, on the function stack) that will be needed to hold a single micro-tile of any datatype (and for any induced method): ```c #define BLIS_STACK_BUF_MAX_SIZE ( BLIS_SIMD_MAX_NUM_REGISTERS * BLIS_SIMD_MAX_SIZE * 2 ) ``` These temporary buffers are used when handling edge cases (m % _MR_ != 0 || n % _NR_ != 0) within the level-3 macrokernels, and also in the virtual microkernels of various implementations of induced methods for complex matrix multiplication. It is **very important** that these values be set correctly; otherwise, you may experience undefined behavior as stack data is overwritten at run-time. A kernel developer may set `BLIS_SIMD_MAX_NUM_REGISTERS` and `BLIS_SIMD_MAX_SIZE`, which will indirectly affect `BLIS_STACK_BUF_MAX_SIZE`, or he may set `BLIS_STACK_BUF_MAX_SIZE` directly. Notice that the default values are already set to work with modern x86_64 systems. _**Memory alignment.**_ BLIS implements memory alignment internally, rather than relying on a function such as `posix_memalign()`, and thus it can provide aligned memory even with functions that adhere to the `malloc()` and `free()` API in the standard C library. ```c #define BLIS_SIMD_ALIGN_SIZE BLIS_SIMD_MAX_SIZE #define BLIS_PAGE_SIZE 4096 #define BLIS_STACK_BUF_ALIGN_SIZE BLIS_SIMD_ALIGN_SIZE #define BLIS_HEAP_ADDR_ALIGN_SIZE BLIS_SIMD_ALIGN_SIZE #define BLIS_HEAP_STRIDE_ALIGN_SIZE BLIS_SIMD_ALIGN_SIZE #define BLIS_POOL_ADDR_ALIGN_SIZE_A BLIS_PAGE_SIZE #define BLIS_POOL_ADDR_ALIGN_SIZE_B BLIS_PAGE_SIZE #define BLIS_POOL_ADDR_ALIGN_SIZE_C BLIS_PAGE_SIZE #define BLIS_POOL_ADDR_ALIGN_SIZE_GEN BLIS_PAGE_SIZE ``` The value `BLIS_STACK_BUF_ALIGN_SIZE` defines the alignment of stack memory used as temporary internal buffers, such as for output matrices to the microkernel when computing edge cases. (See [implementation notes](KernelsHowTo#implementation-notes-for-gemm) for the `gemm` microkernel for details.) This value defaults to `BLIS_SIMD_ALIGN_SIZE`, which defaults to `BLIS_SIMD_MAX_SIZE`. The value `BLIS_HEAP_ADDR_ALIGN_SIZE` defines the alignment used when allocating memory via the `malloc()` function defined by `BLIS_MALLOC_USER`. Setting this value to `BLIS_SIMD_ALIGN_SIZE` may speed up certain level-1v and -1f kernels. The value `BLIS_HEAP_STRIDE_ALIGN_SIZE` defines the alignment used for so-called "leading dimensions" (i.e. column strides for column-stored matrices, and row strides for row-stored matrices) when creating BLIS matrices via the object-based API (e.g. `bli_obj_create()`). While setting `BLIS_HEAP_ADDR_ALIGN_SIZE` guarantees alignment for the first column (or row), creating a matrix with certain dimension values (_m_ and _n_) may cause subsequent columns (or rows) to be misaligned. Setting this value to `BLIS_SIMD_ALIGN_SIZE` is usually desirable. Additional alignment may or may not be beneficial. The value `BLIS_POOL_ADDR_ALIGN_SIZE_*` define the alignments used when allocating blocks to the memory pools used to manage internal packing buffers for matrices A, B, C, and for general use. Any block of memory returned by the memory allocator is guaranteed to be aligned to this value. Aligning these blocks to the virtual memory page size (usually 4096 bytes) is standard practice. ### make_defs.mk The `make_defs.mk` file primarily contains compiler and compiler flag definitions used by `make` when building a BLIS library. The format of the file is mostly self-explanatory. However, we will expound on the contents here, using the `make_defs.mk` file for the `haswell` configuration as an example: ```make # Declare the name of the current configuration and add it to the # running list of configurations included by common.mk. THIS_CONFIG := haswell ifeq ($(CC),) CC := gcc CC_VENDOR := gcc endif CPPROCFLAGS := -D_POSIX_C_SOURCE=200112L CMISCFLAGS := -std=c99 -m64 CPICFLAGS := -fPIC CWARNFLAGS := -Wall -Wno-unused-function -Wfatal-errors ifneq ($(DEBUG_TYPE),off) CDBGFLAGS := -g endif ifeq ($(DEBUG_TYPE),noopt) COPTFLAGS := -O0 else COPTFLAGS := -O3 endif CKOPTFLAGS := $(COPTFLAGS) ifeq ($(CC_VENDOR),gcc) CVECFLAGS := -mavx2 -mfma -mfpmath=sse -march=core-avx2 else ifeq ($(CC_VENDOR),icc) CVECFLAGS := -xCORE-AVX2 else ifeq ($(CC_VENDOR),clang) CVECFLAGS := -mavx2 -mfma -mfpmath=sse -march=core-avx2 else $(error gcc, icc, or clang is required for this configuration.) endif endif endif # Store all of the variables here to new variables containing the # configuration name. $(eval $(call store-make-defs,$(THIS_CONFIG))) ``` _**Configuration name.**_ The first statement reaffirms the name of the configuration. The `THIS_CONFIG` variable is used later to attach the configuration name as a suffix to the remaining variables so that they can co-exist with variables read from other `make_defs.mk` files during multi-configuration builds. Note that if the configuration name defined here does not match the name of the directory in which `make_defs.mk` is stored, `make` will output an error when executing the top-level `Makefile`. _**Compiler definitions.**_ Next, we set the values of `CC` and `CC_VENDOR`. The former is the name (or path) to the actual compiler executable to use during compilation. The latter is the compiler family. Currently, BLIS generally supports three compiler families: `gcc`, `clang`, and `icc`. `CC_VENDOR` is used when conditionally setting various variables based on the type of flags available--flags that might not vary across different versions or installations of the same compiler (e.g. `gcc-4.9` vs `gcc-5.0`, or `gcc` vs `/usr/local/bin/gcc`), but may vary across compiler families (e.g. `gcc` vs. `icc`). If the compiler you wish to use is in your `PATH` environment variable, `CC` and `CC_VENDOR` will usually contain the same value. _**Basic compiler flags.**_ The variables `CPPROCFLAGS` and `CWARNFLAGS` should be assigned to C preprocessor flags and compiler warning flags, respectively, while `CPICFLAGS` should be assigned flags to enable position independent code (shared library) flags. Finally, `CMISCFLAGS` may be assigned any miscellaneous flags that do not neatly fit into any other category, such as language flags and 32-/64-bit flags. These four categories of flags are usually recognized across compiler families. _**Debugging flags.**_ The `CDBGFLAGS` variable should be assigned to contain flags that insert debugging symbols into the object code emitted by the compiler. Typically, this amounts to no more than the `-g` flag, but some compilers or situations may call for different (or additional) flags. This variable is conditionally set only if `$(DEBUG_TYPE)`, which is set the by `configure` script, is not equal to `noopt`. _**Optimization flags.**_ The `COPTFLAGS` variable should be assigned any flags relating to general compiler optimization. Usually this takes the form of `-O2` or `-O3`, but more specific optimization flags may be included as well, such as `-fomit-frame-pointer`. Note that, as with `CDBGFLAGS`, `COPTFLAGS` is conditionally assigned based on the value of `$(DEBUG_TYPE)`. A separate `CKOPTFLAGS` variable tracks optimizations flags used when compiling kernels. For most configurations, `CKOPTFLAGS` is assigned as a copy of `COPTFLAGS`, but if the kernel developer needs different optimization flags to be applied when compiling kernel source code, `CKOPTFLAGS` should be set accordingly. _**Vectorization flags.**_ The second-to-last block sets the `CVECFLAGS`, which should be assigned any flags that must be given to the compiler in order to enable use of a vector instruction set needed or assumed by the kernel source code. Also, if you wish to enable automatic use of certain instruction sets (e.g. `-mfpmath=sse` for many Intel architectures), this is where you should set those flags. These flags often differ among compiler families, especially between `icc` and `gcc`/`clang`. _**Variable storage/renaming.**_ Finally, the last statement commits the variables defined in the file to "storage". That is, they are copied to variable names that contain `THIS_CONFIG` as a suffix. This allows the variables for one configuration to co-exist with variables of another configuration. ## Configuration families A configuration family is represented similarly to that of a sub-configuration: a sub-directory of the `config` directory. Additionally, there are two types of families: singleton families and umbrella families. A _singleton_ family simply refers to a sub-configuration. The `configure` script only targets configuration families. But since every sub-configuration is also a valid configuration family, every sub-configuration is a valid configuration target. An _umbrella_ family is the more interesting type of configuration family. These families are defined as collections of architecturally related sub-configurations. (**Important:** an umbrella family should always be named something different than any of its constituent sub-configurations.) BLIS provides a mechanism to define umbrella families so that users and developers can build a single instance of BLIS that supports multiple configurations, where some heuristic is used at runtime to choose among the configurations. For example, you may wish to deploy a BLIS library on a storage device that is shared among several computers, each of which is based on a different x86_64 microarchitecture. Throughout the remainder of this document, we will sometimes refer to "umbrella families" as simply "families". Similarly, we will refer to "singleton families" and "sub-configurations" interchangeably. To the extent that any ambiguity may remain, context should clarify which type of family is germane to the discussion. Let's inspect the `amd64` configuration family as an example: ``` $ ls config/amd64 bli_family_amd64.h make_defs.mk ``` A configuration family contains a subset of the files contained within a sub-configuration: A `bli_family_*.h` header file and a `make_defs.mk` makefile fragment: * `bli_family_amd64.h`. This header file is `#included` only when the configuration family in question, in this case `amd64`, was the target to `./configure`. The file serves a similar purpose as with sub-configurations--a place to define various parameters, such as those relating to memory allocation and alignment. However, in the context of configuration families, the uniqueness of this file makes a bit more sense. Importantly, the definitions in this file will be affect **all** sub-configurations within the family. Thus, it is useful to think of these as "global" parameters. For example, if custom implementations of `malloc()` and `free()` are specified in the `bli_family_amd64.h` file, these implementations will be used for every sub-configuration member of the `amd64` family. (The configuration registry, described in [the next section](ConfigurationHowTo.md#configuration-registry), specifies each configuration family's membership.) As with sub-configurations, this file may be empty, in which case reasonable defaults are selected by the framework. * `make_defs.mk`. This makefile fragment defines the compiler and compiler flags in a manner identical to that of sub-configurations. However, these configuration flags are used when compiling source code that is not specific to any one particular sub-configuration. (The build system compiles a set of reference kernels and optimized kernels for each sub-configuration, during which it uses flags read from the individual sub-configurations' `make_defs.mk` files. By contrast, the general framework code is compiled once--using the flags read from the family's `make_defs.mk` file--and executed by all sub-configurations.) For a more detailed walkthrough of these files' expected/allowed contents, please see the descriptions provided in the section on [sub-configurations](ConfigurationHowTo.md#sub-configurations): * [bli_family_*.h](ConfigurationHowTo.md#bli_family_h) * [make_defs.h](ConfigurationHowTo.md#make_defsmk) With these two files defined and present, the configuration family is properly constituted and ready to be registered within the configuration registry. ## Configuration registry The configuration registry is the official place for declaring a sub-configuration or configuration family. Unless a configuration (singleton or family) is declared within the registry, `configure` will not accept it as a valid configuration target at configure-time. Before describing the syntax and semantics of the registry, we'll first briefly describe three types of information we wish to encode into the registry: _**Configuration list.**_ First and foremost, the registry needs to enumerate the registered sub-configurations. That is, it needs to list the sub-configurations (or, singleton families) that are available to be targeted by `configure`. The registry also needs to specify configuration family membership--that is, the (umbrella) families to which those sub-configurations belong. _**Kernel list.**_ Next, the registry needs to specify the list of kernel sets that will be needed by each sub-configuration, and by proxy, each configuration family. It's easy to think of different configurations as corresponding to different microarchitectures, and that generally holds true. However, sometimes we use the same configuration for multiple microarchitectures (e.g. `haswell` is used for Intel Haswell, Broadwell, and non-server Skylake variants). It might also be tempting to think of each microarchitecture as having its own set of kernels. However, in practice, we find that some microarchitectures' kernels are identical to those of a previous microarchitectural revision, or to those of another vendor's microarchitecture. Thus, sometimes a sub-configuration will wish to use a kernel set that is "native" to a different configuration. In these cases, there is not a one-to-one mapping of sub-configuration names to kernel set names, and therefore the configuration registry must separately specify the kernel sets needed by any sub-configuration (and by proxy, any configuration family). _**Kernel-to-configuration map.**_ Lastly, and most subtly, for each kernel set in the kernel list, the registry needs to specify the sub-configuration(s) that depend on that particular kernel set. Notice that the kernel list can be obtained by mapping sub-configurations to kernel sets they require. By contrast, the kernel-to-configuration map tracks the reverse dependency and helps us answer: for any given kernel set, which sub-configurations caused the kernel set to be pulled into the build? This mapping is needed when determining which sub-configuration's compiler flags (as defined in its `make_defs.mk` file) to use when compiling that kernel set. The most obvious solution to this problem would have been to associate compiler flags with the individual kernel sets. However, given the desire to share kernel sets among sub-configurations, we needed the flexibility of applying different compiler flags to any given kernel set based on the sub-configuration that would be utilizing that kernel set. In the case that multiple sub-configurations pull in the same kernel set, a set of heuristics is used to choose between the sub-configurations so that a single set of compiler flags can be chosen for use when compiling that kernel set. ### Walkthrough The configuration registry exists as a human-readable file, `config_registry`, located at the top-level of the BLIS distribution. What follows is an example of a `config_registry` file that is based on actual contents in a BLIS commit recent as of this writing. Note that lines containing only whitespace are ignored. Furthermore, any characters that appear after (and including) a `#` are treated as comments and also ignored. ``` # # config_registry # # Processor families. x86_64: intel64 amd64 intel64: haswell sandybridge penryn generic amd64: zen excavator steamroller piledriver bulldozer generic arm64: cortexa57 generic arm32: cortexa15 cortexa9 generic # Intel architectures. haswell: haswell sandybridge: sandybridge penryn: penryn knl: knl # AMD architectures. zen: zen/haswell/sandybridge excavator: excavator/piledriver steamroller: steamroller/piledriver piledriver: piledriver bulldozer: bulldozer # ARM architectures. cortexa57: cortexa57/armv8a cortexa15: cortexa15/armv7a cortexa9: cortexa9/armv7a # Generic architectures. generic: generic ``` Generally speaking, the registry can be thought of as defining a very simple grammar. (However, as you'll soon see, there are nuances that are un-grammar-like.) The registry can contain two kinds of lines. The first type defines a singleton configuration family. For example, the line ``` haswell: haswell ``` defines a configuration family `haswell` (the left side of the `:`) as containing only itself: the sub-configuration by the same name, `haswell` (the right side of the `:`). When singleton families are defined in this way, it implicitly pulls in the kernel set by the same name as the sub-configuration (in this case, `haswell`). More specifically, the `haswell` sub-configuration depends on the kernels residing in the `kernels/haswell` sub-directory. The second type of line defines an umbrella configuration family. For example, the line ``` intel64: haswell sandybridge penryn generic ``` defines the configuration family `intel64` as containing the `haswell`, `sandybridge`, `penryn`, and `generic` sub-configurations as members (technically speaking, it is more accurate to think of the family as containing singleton families rather than their corresponding sub-configurations). Thus, if the user runs `./configure intel64`, the library will be built to support all sub-configurations defined within the `intel64` family. **Note:** `generic` is a somewhat special sub-configuration that uses only reference kernels and reference blocksizes. It is included in every umbrella family so that when those families are instantiated into BLIS libraries and linked to an application, the application will be able to run even if none of the other sub-configurations (`haswell`, `sandybridge`, `penryn`) are chosen at runtime by the hardware detection heuristic. Some sub-configurations, for various reasons, do not rely on their own set of kernels and instead use the kernel set that is native to another sub-configuration. For example, the `excavator` and `steamroller` configurations each correspond to hardware that is very similar to the hardware targeted by the `piledriver` configuration. In fact, the former two configurations rely exclusively on kernels written for the latter configuration. (Presently, there are no `excavator` or `steamroller` kernel sets in BLIS.) We denote this kernel dependency with a `/` character: ``` excavator: excavator/piledriver steamroller: steamroller/piledriver ``` Here, the first line (reading from left-to-right) defines the `excavator` singleton family as containing only itself, the `excavator` sub-configuration, and also specifies that this sub-configuration must have access to the `piledriver` kernel set. The second line defines the `steamroller` singleton family in a similar manner. **Note:** Specifying non-native kernel sets via the `/` character is only allowed when defining singleton configuration families. They may NOT appear in the definitions of umbrella families! When an umbrella family includes a singleton family that is defined to require non-native kernels, this will be accounted for during the parsing of the `config_registry` file. Sometimes, a sub-configuration may need access to more than one kernel set. If additional kernel sets are needed, they should be listed with additional `/` characters: ``` zen: zen/haswell/sandybridge ``` The line above defines the `zen` singleton family as containing only itself, the `zen` sub-configuration, and also specifies that this sub-configuration must have access to the `haswell` kernel set as well as the `sandybridge` kernel set. What if there exists a `zen` kernel set as well, which the `zen` sub-configuration must access in addition to those of `haswell` and `sanydbridge`? In this case, it would need to be annotated explicitly as: ``` zen: zen/zen/haswell/sandybridge ``` This line (which is hypothetical and does not appear in the `config_registry` example above) defines the `zen` singleton family in terms of only the `zen` sub-configuration, and provides that sub-configuration access to `zen`, `haswell`, and `sandybridge` kernel sets. (Also: the kernel sets may appear in any order.) Notice that while kernel sets usually correspond to a sub-configuration, they do not always. For example, while the `armv7a` and `armv8a` kernel sets are referenced in the example `config_registry` file, there do not exist any registered sub-configurations by those names. However, the kernel directories exist and the kernel sets appear in the definitions of a few `cortex` singleton families. One last thing to point out: take a look at the `x86_64` configuration family: ``` x86_64: intel64 amd64 ``` Unlike most of the registered families, which are defined in terms of sub-configurations, `x86_64` is defined in terms of *other* families--specifically, `intel64` and `amd64`: ``` intel64: haswell sandybridge penryn generic amd64: zen excavator steamroller piledriver bulldozer generic ``` This multi-level style of specifying sub-configurations became available starting in 290dd4a. The behavior of `configure` in this situation is as you would expect; that is, including `intel64` and `amd64` in the definition of `x86_64` is equivalent to: ``` x86_64: haswell sandybridge penryn zen excavator steamroller piledriver bulldozer generic ``` Any duplicates that may result are removed automatically. ### Printing the configuration registry lists The configuration list, kernel list, and kernel-to-configuration map are constructed internally by `configure`, but these structures can be inspected by running `configure` with the `-c` (which is the short form of `--show-config-lists`) option. This can be useful as a sanity check to make sure `configure` is properly parsing and interpreting the `config_registry` file. The first thing printed is the configuration list: ``` $ ./configure -c amd64 configure: reading configuration registry...done. ... configure: configuration list: configure: amd64: zen excavator steamroller piledriver bulldozer generic configure: arm32: cortexa15 cortexa9 generic configure: arm64: cortexa57 generic configure: bulldozer: bulldozer configure: cortexa15: cortexa15 configure: cortexa57: cortexa57 configure: cortexa9: cortexa9 configure: excavator: excavator configure: generic: generic configure: haswell: haswell configure: intel64: haswell sandybridge penryn generic configure: knl: knl configure: penryn: penryn configure: piledriver: piledriver configure: sandybridge: sandybridge configure: skx: skx configure: steamroller: steamroller configure: x86_64: haswell sandybridge penryn zen excavator steamroller piledriver bulldozer generic ``` This simply lists the sub-configurations associated with each defined configuration family (singleton or umbrella). Note that they are sorted alphabetically. Next, the kernel list (actually, all kernel lists) is printed: ``` configure: kernel list: configure: amd64: zen piledriver bulldozer generic configure: arm32: armv7a generic configure: arm64: armv8a generic configure: bulldozer: bulldozer configure: cortexa15: armv7a configure: cortexa57: armv8a configure: cortexa9: armv7a configure: excavator: piledriver configure: generic: generic configure: haswell: haswell zen configure: intel64: haswell zen sandybridge penryn generic configure: knl: knl configure: penryn: penryn configure: piledriver: piledriver configure: sandybridge: sandybridge configure: skx: skx configure: steamroller: piledriver configure: x86_64: haswell sandybridge penryn zen piledriver bulldozer generic configure: zen: zen ``` This shows the kernel sets that are pulled in by each configuration family. For singleton families, this is specified in a straightforward manner via the `/` character described [in the previous section](ConfigurationHowTo.md#Walkthrough). For umbrella families, this is determined indirectly by looking up the definitions of the singleton families that are members of the umbrella family. Next, the full kernel-to-configuration map is printed: ``` configure: kernel-to-config map for 'amd64': configure: bulldozer: bulldozer configure: generic: generic configure: piledriver: excavator steamroller piledriver configure: zen: zen ``` For each of the kernel sets required of the selected configuration family above, the kernel-to-configuration map shows the sub-configurations that required that kernel set. Notice that sometimes a single kernel set may be pulled in by more than one sub-configuration, as with the `piledriver` kernel set. Lastly, we print a version of the kernel-to-configuration map in which we've used a set of heuristics to select a single sub-configuration for each kernel set in the map: ``` configure: kernel-to-config map for 'amd64' (chosen pairs): configure: bulldozer:bulldozer configure: generic:generic configure: piledriver:piledriver configure: zen:zen ``` This variant of the kernel-to-config map is formatted as a series of "sub-configuration:kernel-set" pairs. These pairs are used during the processing of the top-level `Makefile` to determine which sub-configuration's compiler flags should be used when compiling the source code within each kernel set. ## Adding a new kernel set Adding support for a new set of kernels in BLIS is easy and can be done via the following steps. 1. _**Create and populate the kernel set directory.**_ First, we must create a directory in `kernels` that corresponds to the new kernel set. Suppose we wanted to add kernels for Intel's Knight's Landing microarchitecture. In BLIS, this corresponds to the `knl` configuration, and so we should name the directory `knl`. This is because we want the `knl` kernel set to be pulled by default into builds that include the `knl` sub-configuration. ``` $ mkdir kernels/knl $ ls kernels armv7a bgq generic knc old piledriver sandybridge armv8a bulldozer haswell knl penryn power7 ``` Next, we must write the `knl` kernels and locate them inside `kernels/knl`. (For more information on writing BLIS kernels, please see the [Kernels Guide](KernelsHowTo.md).) We recommend separating level-1v, level-1f, and level-3 kernels into separate `1`, `1f`, and `3` sub-directories, respectively. The kernel files and functions therein do not need to follow any particular naming convention, though we strongly recommend using the conventions already used by other kernel sets. Take a look at other kernel files, such as those for `haswell`, [for examples](https://github.com/flame/blis/tree/master/kernels). Finally, for the `knl` kernel set, you should insert a file named `bli_kernels_knl.h` into `kernels/knl` that prototypes all of your new kernel set's kernel functions. You are welcome to write your own prototypes, but to make the prototyping of kernels easier we recommend using the prototype-generating macros for level-1v, level-1f, level-1m, and level-3 functions defined in [frame/1/bli_l1v_ker_prot.h](https://github.com/flame/blis/blob/master/frame/1/bli_l1v_ker_prot.h), [frame/1f/bli_l1f_ker_prot.h](https://github.com/flame/blis/blob/master/frame/1f/bli_l1f_ker_prot.h), [frame/1m/bli_l1m_ker_prot.h](https://github.com/flame/blis/blob/master/frame/1m/bli_l1m_ker_prot.h), and [frame/3/bli_l3_ukr_prot.h](https://github.com/flame/blis/blob/master/frame/3/bli_l3_ukr_prot.h), respectively. The following example utilizes how a select subset of these macros can be used to generate kernel function prototypes. ```c GEMM_UKR_PROT( double, d, gemm_knl_asm_24x8 ) PACKM_KER_PROT( double, d, packm_knl_asm_24xk ) PACKM_KER_PROT( double, d, packm_knl_asm_8xk ) AXPYF_KER_PROT( dcomplex, z, axpyf_knl_asm ) DOTXF_KER_PROT( dcomplex, z, dotxf_knl_asm ) AXPYV_KER_PROT( float, s, axpyv_knl_asm ) DOTXV_KER_PROT( float, s, dotxv_knl_asm ) ``` The first line generates a function prototype for a double-precision real `gemm` microkernel named `bli_dgemm_knl_asm_24x8()`. Notice how the macro takes three arguments: the C language datatype, the single character corresponding to the datatype, and the base name of the function, which includes the operation (`gemm`), the kernel set name (`knl`), and a substring specifying its implementation (`asm_24x8`). The second and third lines generate prototypes for double-precision real `packm` kernels to go along with the `gemm` microkernel above. The fourth and fifth lines generate prototypes for double-precision complex instances of the level-1f kernels `axpyf` and `dotxf`. The last two lines generate prototypes for single-precision real instances of the level-1v kernels `axpyv` and `dotxv`. 2. _**Add support within the framework source code.**_ We also need to make a minor update to the framework to support the new kernels--specifically, to pull in the kernels' function prototypes. **`frame/include/bli_arch_config.h`**. When adding support for the `knl` kernel set to the framework, we must modify this file to `#include` the `bli_kernels_knl.h` header file: ```c #ifdef BLIS_KERNELS_KNL #include "bli_kernels_knl.h" #endif ``` The `BLIS_KERNELS_KNL` macro, which guards the `#include` directive, is automatically defined by the build system when the `knl` kernel set is required by _any_ sub-configuration. ## Adding a new configuration family Adding support for a new umbrella configuration family in BLIS is fairly straightforward and can be done via the following steps. The hypothetical examples used in these steps assume you are trying to create a new configuration family `intelavx` that supports only Intel microarchitectures that support the Intel AVX instruction set. 1. _**Create and populate the family directory.**_ First, we must create a directory in `config` that corresponds to the new family. Since we are adding a new family named `intelavx`, we would name our directory `intelavx`. ``` $ mkdir config/intelavx $ ls config amd64 cortexa15 excavator intel64 knl piledriver steamroller bgq cortexa57 generic intelavx old power7 template bulldozer cortexa9 haswell knc penryn sandybridge zen ``` We also need to create `bli_family_intelavx.h` and `make_defs.mk` files inside our new sub-directory. Since they will be very similar to those of the `intel64` family's files, we can copy those files over and then modify them accordingly: ``` $ cp config/intel64/bli_family_intel64.h config/intelavx/bli_family_intelavx.h $ cp config/intel64/make_defs.mk config/intelavx/ ``` First, we update the configuration name inside of `make_defs.mk`: ``` THIS_CONFIG := intelavx ``` and while we're editing the file, we can make any other changes to compiler flags we wish (if any). Similarly, the `bli_family_intelavx.h` header file should be updated, though in our case it does not need any changes; the original file is empty and thus the copied file can remain empty as well. Note that other configuration families may have different needs. Remember that all of the parameters set in this file, either explicitly or implicitly (via their defaults), must work for **all** sub-configurations in the family. When creating or modifying a family, it's worth reviewing the parameters' defaults, which are set in [frame/include/bli_kernel_macro_defs.h](https://github.com/flame/blis/blob/master/frame/include/bli_kernel_macro_defs.h) and convincing yourself that each parameter default (or overriding definition in `bli_family_*.h`) will work for each sub-configuration. 2. _**Add support within the framework source code.**_ Next, we need to update the BLIS framework source code so that the new configuration family is recognized and supported. Configuration families require updates to two files. * **`frame/include/bli_arch_config.h`**. This file must be updated to `#include` the `bli_family_intelavx.h` header file. Notice that the preprocessor directive should be guarded as follows: ```c #ifdef BLIS_FAMILY_INTELAVX #include "bli_family_intelavx.h" #endif ``` The `BLIS_FAMILY_INTELAVX` will automatically be defined by the build system whenever the family was targeted by `configure` is `intelavx`. (In general, if the user runs `./configure foobar`, the C preprocessor macro `BLIS_FAMILY_FOOBAR` will be defined.) * **`frame/base/bli_arch.c`**. This file must be updated so that `bli_arch_query_id()` returns the correct `arch_t` microarchitecture ID value to the caller. This function is called when the framework is trying to choose which sub-configuration to use at runtime. For x86_64 architectures, this is supported via the `CPUID` instruction, as implemented via `bli_cpuid_query_id()`. Thus, you can simply mimic what is done for the `intel64` family by inserting lines such as: ```c #ifdef BLIS_FAMILY_INTELAVX id = bli_cpuid_query_id(); #endif ``` This results in `bli_cpuid_query_id()` being called, which will return the `arch_t` ID value corresponding to the hardware detected by `CPUID`. (If your configuration family does not consist of x86_64 architectures, then you'll need some other heuristic to determine how to choose the correct sub-configuration at runtime. When in doubt, please [open an issue](https://github.com/flame/blis/issues) to begin a dialogue with developers.) 3. _**Update the configuration registry.**_ The last step is to update the `config_registry` file so that it defines the new family. Since we want the family to include only Intel sub-configurations that support AVX, we would add the following line: ``` intelavx: haswell sandybridge ``` Notice that we left out the Core2-based `penryn` sub-configuration since it targets hardware that only supports SSE vector instructions. ## Adding a new sub-configuration Adding support for a new-subconfiguration to BLIS is similar to adding support for a family, though there are a few additional steps. Throughout this section, we will use the `knl` (Knight's Landing) configuration as an example to illustrate the typical changes necessary to various files in BLIS. 1. _**Create and populate the family directory.**_ First, we must create a directory in `config` that corresponds to the new sub-configuration. ``` $ mkdir config/knl $ ls config amd64 cortexa15 excavator intel64 old power7 template bgq cortexa57 generic knc penryn sandybridge zen bulldozer cortexa9 haswell knl piledriver steamroller ``` We also need to create `bli_cntx_init_knl.c`, `bli_family_intelavx.h`, and `make_defs.mk` files inside our new sub-directory. Since they will be very similar to those of the `haswell` sub-configuration's files, we can copy those files over and then modify them accordingly: ``` $ cp config/haswell/bli_cntx_init_haswell.c config/knl/bli_cntx_init_knl.c $ cp config/haswell/bli_family_haswell.h config/knl/bli_family_knl.h $ cp config/haswell/make_defs.mk config/knl/ ``` First, we update the configuration name inside of `make_defs.mk`: ``` THIS_CONFIG := knl ``` and while we're editing the file, we can make any other changes to compiler flags we wish (if any). Similarly, the `bli_family_knl.h` header file should be updated as needed. Since the number of vector registers and the vector register size on `knl` differ from the defaults, we must explicitly set them. (The role of these parameters was explained in a [previous section](ConfigurationHowTo.md#bli_family_h).) Furthermore, provided that a macro `BLIS_NO_HBWMALLOC` is not set, we use a different implementation of `malloc()` and `free()` and `#include` that implementation's header file. ```c #define BLIS_SIMD_MAX_NUM_REGISTERS 32 #define BLIS_SIMD_MAX_SIZE 64 #ifdef BLIS_NO_HBWMALLOC #include #define BLIS_MALLOC_POOL malloc #define BLIS_FREE_POOL free #else #include #define BLIS_MALLOC_POOL hbw_malloc #define BLIS_FREE_POOL hbw_free #endif ``` Finally, we update `bli_cntx_init_knl.c` to initialize the context with the appropriate kernel function pointers and blocksize values. The functions used to perform this initialization are explained in [an earlier section](ConfigurationHowTo.md#bli_cntx_init_c). 2. _**Add support within the framework source code.**_ Next, we need to update the BLIS framework source code so that the new sub-configuration is recognized and supported. Sub-configurations require updates to four files--six if hardware detection logic is added. * **`frame/include/bli_type_defs.h`**. First, we need to define an ID to associate with the microarchitecture for which we are adding support. All microarchitecture type IDs are defined in [bli_type_defs.h](https://github.com/flame/blis/blob/master/frame/include/bli_type_defs.h) as an enumerated type that we `typedef` to `arch_t`. To support `knl`, we add a new enumerated type value `BLIS_ARCH_KNL`: ```c typedef enum { BLIS_ARCH_KNL, BLIS_ARCH_KNC, BLIS_ARCH_HASWELL, BLIS_ARCH_SANDYBRIDGE, BLIS_ARCH_PENRYN, BLIS_ARCH_ZEN, BLIS_ARCH_EXCAVATOR, BLIS_ARCH_STEAMROLLER, BLIS_ARCH_PILEDRIVER, BLIS_ARCH_BULLDOZER, BLIS_ARCH_CORTEXA57, BLIS_ARCH_CORTEXA15, BLIS_ARCH_CORTEXA9, BLIS_ARCH_POWER7, BLIS_ARCH_BGQ, BLIS_ARCH_GENERIC, BLIS_NUM_ARCHS } arch_t; ``` Notice that the total number of `arch_t` values, `BLIS_NUM_ARCHS`, is updated automatically. * **`frame/base/bli_gks.c`**. We must also update the global kernel structure, or gks, to register the new sub-configuration during library initialization. Sub-configuration registration occurs in `bli_gks_init()`. For `knl`, updating this function amounts to inserting the following lines ```c #ifdef BLIS_CONFIG_KNL bli_gks_register_cntx( BLIS_ARCH_KNL, bli_cntx_init_knl, bli_cntx_init_knl_ref, bli_cntx_init_knl_ind ); #endif ``` This function submits pointers to various context initialization functions to the global kernel structure, which are then stored and called at the appropriate time. The functions **must** be named strictly according to the format shown in the example above, with `knl` replaced with the sub-configuration name. Also, note the call to `bli_gks_register_cntx` is guarded by `BLIS_CONFIG_KNL`. This macro is automatically `#defined` by the build system if and when the `knl` sub-configuration is enabled at configure-time, either directly as a singleton family or indirectly via an umbrella family. * **`frame/include/bli_arch_config.h`**. This file must be updated in two places. First, we must modify it to generate prototypes for the `bli_cntx_init_*()` functions, including the developer-provided function `bli_cntx_init_knl()` (defined in `config/knl/bli_cntx_init_knl.c`), by inserting: ```c #ifdef BLIS_CONFIG_KNL CNTX_INIT_PROTS( knl ) #endif ``` Here, the `CNTX_INIT_PROTS` macro generates the appropriate prototypes based on the name of the sub-configuration. Next, we must `#include` the `bli_family_knl.h` header file, just as we would if we were adding support for an umbrella family: ```c #ifdef BLIS_FAMILY_KNL #include "bli_family_knl.h" #endif ``` As before with umbrella families, the `BLIS_FAMILY_KNL` macro is automatically defined by the build system for whatever family was targeted by `configure`. (That is, if the user runs `./configure foobar`, the C preprocessor macro `BLIS_FAMILY_FOOBAR` will be defined.) * **`frame/base/bli_arch.c`**. This file must be updated so that `bli_arch_query_id()` returns the correct `arch_t` architecture ID value to the caller. `bli_arch_query_id()` is called when the framework is trying to choose which sub-configuration to use at runtime. When adding support for a sub-configuration as a singleton family, this amounts to adding a block of code such as: ```c #ifdef BLIS_FAMILY_KNL id = BLIS_ARCH_KNL; #endif ``` The `BLIS_FAMILY_KNL` macro is automatically `#defined` by the build system if the `knl` sub-configuration was targeted directly (as a singleton family) at configure-time. Other ID values are returned only if their respective family macros are defined. (Recall that only one family is ever enabled at time.) If, however, the `knl` sub-configuration was enabled indirectly via an umbrella family, `bli_arch_query_id()` will return the `arch_t` ID value via the lines similar to the following: ```c #ifdef BLIS_FAMILY_INTEL64 id = bli_cpuid_query_id(); #endif #ifdef BLIS_FAMILY_AMD64 id = bli_cpuid_query_id(); #endif ``` Supporting runtime detection of `knl` microarchitectures requires adding `knl` support to `bli_cpuid_query_id()`, which is addressed in the next step (`bli_cpuid.c`). Before we finish editing the `bli_arch.c` file, we need to add a string label to the static array `config_name`: ```c static char* config_name[ BLIS_NUM_ARCHS ] = { "knl", "knc", "haswell", "sandybridge", "penryn", "zen", "excavator", "steamroller", "piledriver", "bulldozer", "cortexa57", "cortexa15", "cortexa9", "power7", "bgq", "generic" }; ``` This array is used by `bli_arch_string()` when mapping `arch_t` values to the strings associated with that architecture ID. Because the `arch_t` value is used as the index of each string, **the relative order of the strings in this array is important**. Be sure to insert the new string (in our case, `"knl"`) at the **same relative location** as the `arch_t` value inserted in `bli_type_defs.h`. This will ensure that each `arch_t` value will map to its corresponding string in the `config_name` array. * **`frame/base/bli_cpuid.c`**. To support the aforementioned runtime microarchitecture detection, the function `bli_cpuid_query_id()`, defined in [bli_cpuid.c](https://github.com/flame/blis/blob/master/frame/base/bli_cpuid.c), will need to be updated. Specifically, we need to insert logic that will detect the presence of the new hardware based on the results of the `CPUID` instruction (assuming the new microarchitecture belongs to the x86_64 architecture family). For example, when support for `knl` was added, this entailed adding the following code block to `bli_cpuid_query_id()`: ```c #ifdef BLIS_CONFIG_KNL if ( bli_cpuid_is_knl( family, model, features ) ) return BLIS_ARCH_KNL; #endif ``` Additionally, we had to define the function `bli_cpuid_is_knl()`, which checks for various processor features known to be present on `knl` systems and returns a boolean `TRUE` if all relevant feature checks are satisfied by the hardware. Note that the order in which we check for the sub-configurations is important. We must check for microarchitectural matches from most recent to most dated. This prevents an older sub-configuration from being selected on newer hardware when a newer sub-configuration would have also matched. * **`frame/base/bli_cpuid.h`**. After defining the function `bli_cpuid_is_knl()`, we must also update [bli_cpuid.h](https://github.com/flame/blis/blob/master/frame/base/bli_cpuid.h) to contain a prototype for the function. 3. _**Update the configuration registry.**_ Lastly, we update the `config_registry` file so that it defines the new sub-configuration. For example, if we want to define a sub-configuration called `knl` that used only `knl` kernels, we would add the following line: ``` knl: knl ``` If, when defining `bli_cntx_init_knl()`, we referenced kernels from a non-native kernel set--say, those of `haswell`--in addition to `knl`-specific kernels, we would need to explicitly pull in both `knl` and `haswell` kernel sets: ``` knl: knl/knl/haswell ``` ## Further Development Topics ### Querying the current configuration If you are ever unsure which configuration is "active", or the configuration parameters that were specified (or implied by default) at configure-time, simply run: ``` $ make showconfig configuration family: intel64 sub-configurations: haswell sandybridge penryn requisite kernels: haswell sandybridge penryn kernel-to-config map: haswell:haswell penryn:penryn sandybridge:sandybridge ----------------------- BLIS version string: 0.2.2-73 install prefix: /home/field/blis debugging status: off multithreading status: no enable BLAS API? yes enable CBLAS API? no build static library? yes build shared library? no ``` This will tell you the current configuration name, the [configuration registry lists](ConfigurationHowTo.md#printing-the-configuration-registry-lists), as well as other information stored by `configure` in the `config.mk` file. ### Header dependencies Due to the way the BLIS framework handles header files, **any** change to **any** header file will result in the entire library being rebuilt. This policy is in place mostly out of an abundance of caution. If two or more files use definitions in a header that is modified, and one or more of those files somehow does not get recompiled to reflect the updated definitions, you could end up sinking hours of time trying to track down a bug that didn't ever need to be an issue to begin with. Thus, to prevent developers (including the framework developer(s)) from shooting themselves in the foot with this problem, the BLIS build system recompiles **all** object files if any header file is touched. We apologize for the inconvenience this may cause. ### Still have questions? If you have further questions about BLIS configurations, please do not hesitate to contact the BLIS developer community. To do so, simply join and post to the [blis-devel](http://groups.google.com/group/blis-devel) mailing list. *** blis-0.9.0/docs/FAQ.md000066400000000000000000000712731422157504600143520ustar00rootroot00000000000000## Introduction Here we attempt to provide some frequently-asked questions about the BLIS framework project, as well as those we think a new user or developer might ask. If you do not see the answer to your question here, please join and post your question to one of the [BLIS mailing lists](https://github.com/flame/blis#discussion). ## Contents * [Why did you create BLIS?](FAQ.md#why-did-you-create-blis) * [Why should I use BLIS instead of GotoBLAS / OpenBLAS / ATLAS / MKL / ESSL / ACML / Accelerate?](FAQ.md#why-should-i-use-blis-instead-of-gotoblas--openblas--atlas--mkl--essl--acml--accelerate) * [How is BLIS related to FLAME / libflame?](FAQ.md#how-is-blis-related-to-flame--libflame) * [What is the difference between BLIS and the AMD fork of BLIS found in AOCL?](FAQ.md#what-is-the-difference-between-blis-and-the-amd-fork-of-blis-found-in-aocl) * [Who do I contact if I have a question about the AMD version of BLIS?](FAQ.md#who-do-i-contact-if-i-have-a-question-about-the-amd-version-of-blis) * [Does BLIS automatically detect my hardware?](FAQ.md#does-blis-automatically-detect-my-hardware) * [I understand that BLIS is mostly a tool for developers?](FAQ.md#i-understand-that-blis-is-mostly-a-tool-for-developers) * [How do I link against BLIS?](FAQ.md#how-do-i-link-against-blis) * [Must I use git? Can I download a tarball?](FAQ.md#must-i-use-git-can-i-download-a-tarball) * [What is a microkernel?](FAQ.md#what-is-a-microkernel) * [What is a macrokernel?](FAQ.md#what-is-a-macrokernel) * [What is a context?](FAQ.md#what-is-a-context) * [I am used to thinking in terms of column-major/row-major storage and leading dimensions. What is a "row stride" / "column stride"?](FAQ.md#im-used-to-thinking-in-terms-of-column-majorrow-major-storage-and-leading-dimensions-what-is-a-row-stride--column-stride) * [I'm somewhat new to this matrix stuff. Can you remind me, what is the difference between a matrix row and a matrix column?](FAQ.md#im-somewhat-new-to-this-matrix-stuff-can-you-remind-me-what-is-the-difference-between-a-matrix-row-and-a-matrix-column) * [Why does BLIS have vector (level-1v) and matrix (level-1m) variations of most level-1 operations?](FAQ.md#why-does-blis-have-vector-level-1v-and-matrix-level-1m-variations-of-most-level-1-operations) * [What does it mean when a matrix with general stride is column-tilted or row-tilted?](FAQ.md#what-does-it-mean-when-a-matrix-with-general-stride-is-column-tilted-or-row-tilted) * [I am not really interested in all of these newfangled features in BLIS. Can I just use BLIS as a BLAS library?](FAQ.md#im-not-really-interested-in-all-of-these-newfangled-features-in-blis-can-i-just-use-blis-as-a-blas-library) * [What about CBLAS?](FAQ.md#what-about-cblas) * [Can I call the native BLIS API from Fortran-77/90/95/2000/C++/Python?](FAQ.md#can-i-call-the-native-blis-api-from-fortran-7790952000cpython) * [Do I need to call initialization/finalization functions before being able to use BLIS from my application?](FAQ.md#do-i-need-to-call-initializationfinalization-functions-before-being-able-to-use-blis-from-my-application) * [Does BLIS support multithreading?](FAQ.md#does-blis-support-multithreading) * [Does BLIS support NUMA environments?](FAQ.md#does-blis-support-numa-environments) * [Does BLIS work with GPUs?](FAQ.md#does-blis-work-with-gpus) * [Does BLIS work on (some architecture)?](FAQ.md#does-blis-work-on-some-architecture) * [What about distributed-memory parallelism?](FAQ.md#what-about-distributed-memory-parallelism) * [Can I build BLIS on Mac OS X?](FAQ.md#can-i-build-blis-on-mac-os-x) * [Can I build BLIS on Windows?](FAQ.md#can-i-build-blis-on-windows) * [Can I build BLIS as a shared library?](FAQ.md#can-i-build-blis-as-a-shared-library) * [Can I use the mixed domain / mixed precision support in BLIS?](FAQ.md#can-i-use-the-mixed-domain--mixed-precision-support-in-blis) * [Who is involved in the project?](FAQ.md#who-is-involved-in-the-project) * [Who funded the development of BLIS?](FAQ.md#who-funded-the-development-of-blis) * [I found a bug. How do I report it?](FAQ.md#i-found-a-bug-how-do-i-report-it) * [How do I request a new feature?](FAQ.md#how-do-i-request-a-new-feature) * [I'm a developer and I'd like to study the way matrix multiplication is implemented in BLIS. Where should I start?](FAQ.md#im-a-developer-and-id-like-to-study-the-way-matrix-multiplication-is-implemented-in-blis-where-should-i-start) * [Where did you get the photo for the BLIS logo / mascot?](FAQ.md#where-did-you-get-the-photo-for-the-blis-logo--mascot) ### Why did you create BLIS? Initially, BLIS was conceived as simply "BLAS with a more flexible interface". The original BLIS was written as a wrapper layer around BLAS that allowed generalized matrix storage (i.e., separate row and column strides). We also took the opportunity to implement some complex domain features that were missing from the BLAS (mostly related to conjugating input operands). This "proto-BLIS" was deployed in [libflame](http://shpc.ices.utexas.edu/libFLAME.html) to facilitate cleaner implementations of some LAPACK-level operations. Over time, we wanted more than just a more flexible interface; we wanted an entire framework from which we could build operations in the BLAS as well as those not present within the BLAS. After this new BLIS framework was created, it turned out that the interface improvements were much less interesting (albeit still of consequence) than some of the framework's other features, and the fact that it allowed developers to rapidly instantiate new BLAS libraries by optimizing only a small amount of code. ### Why should I use BLIS instead of GotoBLAS / OpenBLAS / ATLAS / MKL / ESSL / ACML / Accelerate? BLIS has numerous advantages to existing BLAS implementations. Many of these advantages are summarized on the [BLIS homepage](https://github.com/flame/blis#key-features). But here are a few reasons one might choose BLIS over some other implementation of BLAS: * BLIS facilitates high performance while remaining very portable. BLIS isolates performance-sensitive code to a microkernel which contains only one loop and which, when optimized, accelerates virtually all level-3 operations. Thus, BLIS serves as a powerful tool for quickly instantiating BLAS on new or experimental hardware architectures, as well as a flexible "laboratory" in which to conduct research and experiments. * BLIS provides robust multithreading support, allowing symmetric multicore/many-core parallelism via either OpenMP or POSIX threads. It also computes proper load balance for structured matrix subpartitions, regardless of the location of the diagonal, or whether the subpartition is lower- or upper-stored. * BLIS supports a superset of BLAS functionality, providing operations omitted from the BLAS as well as some complex domain support that is missing in BLAS operations. BLIS is especially useful to researchers who need to develop and prototype new BLAS-like operations that do not exist in the BLAS. * BLIS is backwards compatible with BLAS. BLIS contains a BLAS compatibility layer that allows an application to treat BLIS as if it were a traditional BLAS library. * BLIS supports generalized matrix storage, which can be used to express column-major, row-major, and general stride storage. * BLIS supports mixed-datatype computation for general matrix multiplication `gemm`, and does so while holding the impact on performance to a relative minimum. * BLIS is free software, available under a [new/modified/3-clause BSD license](http://opensource.org/licenses/BSD-3-Clause). ### How is BLIS related to FLAME / `libflame`? As explained [above](FAQ.md#why-did-you-create-blis?), BLIS was initially a layer within `libflame` that allowed more convenient interfacing to the BLAS. So in some ways, BLIS is a spin-off project. Prior to developing BLIS, [its primary author](http://www.cs.utexas.edu/users/field/) worked as the primary maintainer of `libflame`. If you look closely, you can also see that the design of BLIS was influenced by some of the more useful and innovative aspects of `libflame`, such as internal object abstractions and control trees. Note that various members of the [SHPC research group](http://shpc.ices.utexas.edu/people.html) and its [collaborators](http://shpc.ices.utexas.edu/collaborators.html) routinely provide insight, feedback, and also contribute code (especially kernels) to the BLIS project. ### What is the difference between BLIS and the AMD fork of BLIS found in AOCL? BLIS, also known as "vanilla BLIS" or "upstream BLIS," is maintained by its [original developer](https://github.com/fgvanzee) (with the [support of others](http://shpc.ices.utexas.edu/collaborators.html)) in the [Science of High-Performance Computing](http://shpc.ices.utexas.edu/) (SHPC) group within the [The Oden Institute for Computational Engineering and Sciences](http://www.oden.utexas.edu/) at [The University of Texas at Austin](http://www.utexas.edu/). In 2015, [AMD](https://www.amd.com/) reorganized many of their software library efforts around existing open source projects. BLIS was chosen as the basis for their [CPU BLAS library](https://developer.amd.com/amd-aocl/blas-library/), and an AMD-maintained [fork of BLIS](https://github.com/amd/blis) was established. AMD BLIS sometimes contains certain optimizations specific to AMD hardware. Many of these optimizations are (eventually) merged back into upstream BLIS. However, for various reasons, some changes may remain unique to AMD BLIS for quite some time. Thus, if you want the latest optimizations for AMD hardware, feel free to try AMD BLIS. However, please note that neither The University of Texas at Austin nor BLIS's developers can endorse or offer direct support for any outside fork of BLIS, including AMD BLIS. ### Who do I contact if I have a question about the AMD version of BLIS? For questions or support regarding [AMD's fork of BLIS](https://github.com/amd/blis), please contact the [AMD Optimizing CPU Libraries](https://developer.amd.com/amd-aocl/) group at aoclsupport@amd.com. ### Does BLIS automatically detect my hardware? On certain architectures (most notably x86_64), yes. In order to use auto-detection, you must specify `auto` as your configuration when running `configure` (Please see the BLIS [Build System](BuildSystem.md) guide for more info.) A runtime detection option is also available. (Please see the [Configuration Guide](ConfigurationHowTo.md) for a comprehensive walkthrough.) If automatic hardware detection is requested at configure-time and the build process does not recognize your architecture, the `generic` configuration is selected. ### I understand that BLIS is mostly a tool for developers? It is certainly the case that BLIS began as a tool targeted at developers. In order to achieve high performance, BLIS requires that hand-coded kernels and microkernels be written and referenced in a valid [BLIS configuration](ConfigurationHowTo.md). These components are usually written by developers and then included within BLIS for use by others. The good news, however, is that BLIS has matured to the point where end-users can use it too! Once the aforementioned kernels are integrated into BLIS, they can be used without any developer-level knowledge, and many kernels have already been added! Usually, `./configure auto; make; make install` is sufficient for the typical users with typical hardware. ### How do I link against BLIS? Linking against BLIS is easy! Most people can link to it as if it were a generic BLAS library. Please see the [Linking against BLIS](BuildSystem.md#linking-against-blis) section of the [Build System](BuildSystem.md) guide. ### Must I use git? Can I download a tarball? We **strongly encourage** you to obtain the BLIS source code by cloning a `git` repository (via the [git clone](BuildSystem.md#obtaining-blis) command). The reason for this is that it will allow you to easily update your local copy of BLIS by executing `git pull`. Tarballs and zip files may be obtained from the [releases](https://github.com/flame/blis/releases) page. ### What is a microkernel? The microkernel (usually short for "`gemm` microkernel") is the basic unit of level-3 (matrix-matrix) computation within BLIS. It consists of one loop, where each iteration performs a very small outer product to update a very small matrix. The microkernel is typically the only piece of code that must be carefully optimized (via vector intrinsics or assembly code) to enable high performance in most of the level-3 operations such as `gemm`, `hemm`, `herk`, and `trmm`. For a more thorough explanation of the microkernel and its role in the overall level-3 computations, please read our [ACM TOMS papers](https://github.com/flame/blis#citations). For API and technical reference, please see the [gemm microkernel section](KernelsHowTo.md#gemm-microkernel) of the BLIS [Kernels Guide](KernelsHowTo.md). ### What is a macrokernel? The macrokernels are portable codes within the BLIS framework that implement relatively small subproblems within an overall level-3 operation. The overall problem (say, general matrix-matrix multiplication, or `gemm`) is partitioned down, according to cache blocksizes, such that its `A` and `B` operands are (1) a suitable size and (2) stored in a special packed format. At that time, the macrokernel is called. The macrokernel is implemented as two loops around the microkernel. The macrokernels, along with the microkernel that they call, correspond to the so-called "inner kernels" (or simply "kernels") that formed the fundamental unit of computation in Kazushige Goto's GotoBLAS (and now in the successor library, OpenBLAS). For more information on macrokernels, please read our [ACM TOMS papers](https://github.com/flame/blis#citations). ### What is a context? As of 0.2.0, BLIS contains a new infrastructure for communicating runtime information (such as kernel addresses and blocksizes) from the highest levels of code all the way down the function stack, even into the kernels themselves. This new data structure is called a *context* (defined in code as a `cntx_t` type), and together with its API it helped us clean up some hacks and other awkwardness that existed in BLIS prior to 0.2.0. Contexts also lay the groundwork for managing kernels and related kernel information at runtime. If you are a kernel developer, you can usually ignore the `cntx_t*` argument that is passed into each kernel, since the kernels already inherently "know" this information (such as register blocksizes). And if you are a user, and the function you want to call takes a `cntx_t*` argument, you can safely pass in `NULL` and BLIS will automatically build a suitable context for you at runtime. ### I'm used to thinking in terms of column-major/row-major storage and leading dimensions. What is a "row stride" / "column stride"? Traditional BLAS assumes that matrices are stored in column-major order (or, as we often say, matrices that are "column-stored"), where a leading dimension measures the distance from one element to the next element in the same row. But column-major order is really just a special case of BLIS's more generalized storage scheme. In generalized storage, we have a row stride and a column stride. The row stride measures the distance in memory between rows (within a single column) while the column stride measures the distance between columns (within a single row). Column-major storage corresponds to the situation where the row stride equals 1. Since the row stride is unit, you only have to track the column stride (i.e., the leading dimension). Similarly, in row-major order, the column stride is equal to 1 and only the row stride must be tracked. BLIS also supports situations where both the row stride and column stride are non-unit. We call this situation "general stride". ### I'm somewhat new to this matrix stuff. Can you remind me, what is the difference between a matrix row and a matrix column? Of course! (BLIS's primary author remembers what it was like to get columns and rows confused.) Matrix columns consist of elements that are vertically aligned. Matrix rows consist of elements that are horizontally aligned. (One way to remember this distinction is that real-life columns are vertical structures that hold up buildings. A row of seats in a stadium, by contrast, is horizontal to the ground.) Furthermore, it is helpful to know that the number of rows in a matrix constitutes its so-called *m* dimension, and the number of columns constitutes its *n* dimension. Matrix dimension are always stated as *m x n*: the number of rows *by* the number of columns. So, a *3 x 4* matrix contains three rows (each of length four) and four columns (each of length three). ### Why does BLIS have vector (level-1v) and matrix (level-1m) variations of most level-1 operations? At first glance, it might appear that an element-wise operation such as `copym` or `axpym` would be sufficiently general purpose to cover the cases where the operands are vectors. After all, an *m x 1* matrix can be viewed as a vector of length m and vice versa. But in BLIS, operations on vectors are treated slightly differently than operations on matrices. If an application wishes to perform an element-wise operation on two objects, and the application calls a level-1m operation, the dimensions of those objects must be conformal, or "match up" (after any transposition implied by the object properties). This includes situations where one of the dimensions is unit. However, if an application instead decides to perform an element-wise operation on two objects, and the application calls a level-1v operation, the dimension constraints are slightly relaxed. In this scenario, BLIS only checks that the vector *lengths* are equal. This allows for the vectors to have different orientations (row vs column) while still being considered conformal. So, you could perform a `copyv` operation to copy from an *m x 1* vector to a *1 x m* vector. A `copym` operation on such objects would not be allowed (unless it was executed with the source object containing an implicit transposition). ### What does it mean when a matrix with general stride is column-tilted or row-tilted? When a matrix is stored with general stride, both the row stride and column stride (let's call them `rs` and `cs`) are non-unit. When `rs` < `cs`, we call the general stride matrix "column-tilted" because it is "closer" to being column-stored (than row-stored). Similarly, when `rs` > `cs`, the matrix is "row-tilted" because it is closer to being row-stored. ### I'm not really interested in all of these newfangled features in BLIS. Can I just use BLIS as a BLAS library? Absolutely! Just link your application to BLIS the same way you would link to a BLAS library. For a simple linking example, see the [Linking to BLIS](KernelsHowTo.md#linking-to-blis) section of the BLIS [Build System](BuildSystem.md) guide. ### What about CBLAS? BLIS also contains an optional CBLAS compatibility layer, which leverages the BLAS compatibility layer to help map CBLAS function calls to the corresponding functionality in BLIS. Once BLIS is built with CBLAS support, your application can access CBLAS prototypes via either `cblas.h` or `blis.h`. At the time of this writing, CBLAS support is disabled by default, so be sure to enable it at configure-time. Please see `./configure --help` for the syntax for enabling CBLAS. ### Can I call the native BLIS API from Fortran-77/90/95/2000/C++/Python? In principle, BLIS's native (and BLAS-like) [typed API](BLISTypedAPI) can be called from Fortran. However, you must ensure that the size of the integer in BLIS is equal to the size of integer used by your Fortran program/compiler/environment. The size of BLIS integers is determined at configure-time. Please see `./configure --help` for the syntax for options related to integer sizes. You may also want to confirm that your Fortran compiler doesn't perform any name-mangling of called functions or subroutines (such as with additional underscores beyond the single trailing underscore found in the BLAS APIs), and if so, take steps to disable this additional name-mangling. For example, if your source code calls `dgemm()` but your Fortran compiler name-mangles that call to `_dgemm_()` or `dgemm__()`, your program will fail to link against BLIS since BLIS only defines `dgemm_()`. As for bindings to other languages, please contact the [blis-devel](http://groups.google.com/group/blis-devel) mailing list. ### Do I need to call initialization/finalization functions before being able to use BLIS from my application? Originally, BLIS did indeed require the application to explicitly setup (initialize) various internal data structures via `bli_init()`. Likewise, calling `bli_finalize()` was recommended to cleanup (finalize) the library. However, since commit `9804adf` (circa December 2017), BLIS has implemented self-initialization. These explicit calls to `bli_init()` and `bli_finalize()` are no longer necessary, though experts may still use them in special cases to control the allocation and freeing of resources. This topic is discussed in the BLIS [typed API reference](BLISTypedAPI.md#initialization-and-cleanup). ### Does BLIS support multithreading? Yes! BLIS supports multithreading (via OpenMP or POSIX threads) for all of its level-3 operations. For more information on enabling and controlling multithreading, please see the [Multithreading](Multithreading.md) guide. BLIS is also thread-safe so that you can call BLIS from threads within a multithreaded library or application. BLIS derives its thread-safety via unconditional use of features present in POSIX threads (pthreads). These pthreads features are employed for thread-safety regardless of whether BLIS is configured for OpenMP multithreading, pthreads multithreading, or single-threaded execution. ### Does BLIS support NUMA environments? We have integrated some early foundational support for NUMA *development*, but currently BLIS will execute sub-optimally on NUMA systems. If you are interested in adapting BLIS to a NUMA architecture, please contact us via the [blis-devel](http://groups.google.com/group/blis-devel) mailing list. ### Does BLIS work with GPUs? BLIS does not currently support graphical processing units (GPUs). However, others have applied the BLIS approach towards frameworks that provide BLAS-like functionality on GPUs. To see how NVIDIA's implementation compares to an analogous approach based on the principles that underlie BLIS, please see a paper by some of our collaborators, ["Implementing Strassen’s Algorithm with CUTLASS on NVIDIA Volta GPUs"](https://apps.cs.utexas.edu/apps/sites/default/files/tech_reports/GPUStrassen.pdf). ### Does BLIS work on _(some architecture)_? Please see the BLIS [Hardware Support](HardwareSupport.md) guide for a full list of supported architectures. If your favorite hardware is not listed and you have the expertise, please consider developing your own kernels and sharing them with the project! We will, of course, gratefully credit your contribution. ### What about distributed-memory parallelism? No. BLIS is a framework for sequential and shared-memory/multicore implementations of BLAS-like operations. If you need distributed-memory dense linear algebra implementations, we recommend the [Elemental](http://libelemental.org/) library. ### Can I build BLIS on Mac OS X? BLIS was designed for use in a GNU/Linux environment. However, we've gone to great lengths to keep BLIS compatible with other UNIX-like systems as well, such as BSD and OS X. System software requirements for UNIX-like systems are discussed in the BLIS [Build System](BuildSystem.md) guide. ### Can I build BLIS on Windows? If all you need is a Windows DLL of BLIS, you may be in luck! BLIS uses [AppVeyor](https://ci.appveyor.com/) to automatically produces dynamically-linked libraries, which are preserved on the site as "artifacts". To try it out, just visit the [BLIS AppVeyor page](https://ci.appveyor.com/project/shpc/blis/), click on the `LIB_TYPE=shared` link for the most recent build, and then click on "Artifacts". If you would like to provide us feedback, you may do so by [opening an issue](http://github.com/flame/blis/issues), or you can join the [blis-devel](http://groups.google.com/group/blis-devel) mailing list and send us a message. If you want to build on Windows, there are two options: 1. MSVC ABI compatible DLL with clang If you want BLIS to be compatible with DLLs built by MSVC, you need to use `clang.exe` to build BLIS as BLIS does not support building with Visual Studio C compiler (``cl.exe``). To build BLIS, you need a recent clang from [LLVM](https://releases.llvm.org/download.html), an [MSYS2](https://www.msys2.org/) environment (for build tools like `sed`, `bash`), a Visual Studio 2015 or later environment (for C standard library) and Windows SDK. To build `BLIS`, * Activate the Visual Studio environment from a command prompt Run `call C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Auxiliary\Build\vcvarsall.bat x64` * Start the bash shell from the same command prompt. (Run `bash.exe`) * Run `export AR=llvm-ar AS=llvm-as RANLIB=echo CC=clang CXX=clang++` * Run `./configure --prefix=/c/blis/ --disable-static --enable-shared auto` * Run `make -j install` 2. MinGW DLL This is the easiest option to compile BLIS on windows, but the DLL might not be compatible with other programs compiled with MSVC. To build `BLIS`, install [MSYS2](https://www.msys2.org) and `mingw-w64` compilers. Then start a `bash` shell from MSYS2 and follow the instructions for the Linux build. ### Can I build BLIS as a shared library? Yes. By default, most configurations output only a static library archive (e.g. `.a` file). However, you can also request a shared object (e.g. `.so` file), sometimes also called a "dynamically-linked" library. For information on enabling shared library output, simply run `./configure --help`. ### Can I use the mixed domain / mixed precision support in BLIS? Yes! As of 5fec95b (circa October 2018), BLIS supports mixed-datatype (mixed domain and/or mixed precision) computation via the `gemm` operation. Documentation on utilizing this new functionality is provided via the [MixedDatatype.md](MixedDatatypes.md) document in the source distribution. If this feature is important or useful to your work, we would love to hear from you. Please contact us via the [blis-devel](http://groups.google.com/group/blis-devel) mailing list and tell us about your application and why you need/want support for BLAS-like operations with mixed-domain/mixed-precision operands. ### Who is involved in the project? Lots of people! For a full list of those involved, see the [CREDITS](https://github.com/flame/blis/blob/master/CREDITS) file within the BLIS framework source distribution. ### Who funded the development of BLIS? BLIS was primarily funded by a variety of gifts/grants from industry and the National Science Foundation. Please see the "Funding" section of the [BLIS homepage](https://github.com/flame/blis#funding) for more details. Reminder: _Any opinions, findings and conclusions or recommendations expressed in this material are those of the author(s) and do not necessarily reflect the views of the National Science Foundation (NSF)._ ### I found a bug. How do I report it? If you think you've found a bug, we request that you [open an issue](http://github.com/flame/blis/issues). Don't be shy! Really, it's the best and most convenient way for us to track your issues/bugs/concerns. ### How do I request a new feature? Feature requests should also be submitted by [opening a new issue](http://github.com/flame/blis/issues). ### I'm a developer and I'd like to study the way matrix multiplication is implemented in BLIS. Where should I start? Great question! The first thing you should know is that the core framework of [level-3 operations](BLISTypedAPI.md#operation-index) was *not* designed to be used to teach or explain a high-performance implementation of matrix multiplication. Rather, it was designed to encode the family of level-3 operations with as little code duplication as possible. Because of this, and also for historical/evolutionary reasons, it can be a little difficult to trace the execution of, say, `gemm` from within the core framework. Thankfully, we have an alternative environment in which experts, application developers, and other curious individuals can study BLIS's matrix multiplication implementation. This so-called "sandbox" is a simplified collection of code that strips away much of the framework complexity while also maintaining local definitions for many of the interesting bits. You may find this `gemmlike` sandbox in `sandbox/gemmlike`. Sandboxes go beyond the scope of this FAQ. For an introduction, please refer to the [Sandboxes](Sandboxes.md) document, and/or contact the BLIS developers for more information. ### Where did you get the photo for the BLIS logo / mascot? The sleeping ["BLIS cat"](README.md) photo was taken by Petar Mitchev and is used with his permission. blis-0.9.0/docs/HardwareSupport.md000066400000000000000000000137371422157504600170760ustar00rootroot00000000000000## Introduction This wiki is intended to track the support for various hardware types within the BLIS framework source distribution. We apologize if this wiki falls out of date. For the latest support, we recommend peeking inside of the relevant sub-configuration (specifically, in the `bli_cntx_init_.c` file) and looking at which kernels are registered. You may also contact the [blis-devel](http://groups.google.com/group/blis-devel) mailing list. ## Level-3 microkernels The following table lists architectures for which there exist optimized level-3 microkernels, which microkernels are optimized, the name of the author or maintainer, and the current status of the microkernels. A few remarks / reminders: * Optimizing only the [gemm microkernel](KernelsHowTo.md#gemm-microkernel) will result in optimal performance for all [level-3 operations](BLISTypedAPI#level-3-operations) except `trsm` (which will typically achieve 60 - 80% of attainable peak performance). * The [trsm](BLISTypedAPI#trsm) operation needs the [gemmtrsm microkernel(s)](KernelsHowTo.md#gemmtrsm-microkernels), in addition to the aforementioned [gemm microkernel](KernelsHowTo.md#gemm-microkernel), in order reach optimal performance. * Induced complex (1m) implementations are employed in all situations where the real domain [gemm microkernel](KernelsHowTo.md#gemm-microkernel) of the corresponding precision is available, but the "native" complex domain gemm microkernel is unavailable. Note that the table below lists native kernels, so if a microarchitecture lists only `sd`, support for both `c` and `z` datatypes will be provided via the 1m method. (Note: most people cannot tell the difference between native and 1m-based performance.) Please see our [ACM TOMS article on the 1m method](https://github.com/flame/blis#citations) for more info on this topic. * Some microarchitectures use the same sub-configuration. *This is not a typo.* For example, Haswell and Broadwell systems as well as "desktop" (non-server) versions of Skylake, Kaby Lake, and Coffee Lake all use the `haswell` sub-configuration and the kernels registered therein. Microkernels can be recycled in this manner because the key detail that determines level-3 performance outcomes is actually the vector ISA, not the microarchitecture. In the previous example, all of the microarchitectures listed support AVX2 (but not AVX-512), and therefore they can reuse the same microkernels. * Remember that you (usually) don't have to choose your sub-configuration manually! Instead, you can always request configure-time hardware detection via `./configure auto`. This will defer to internal logic (based on CPUID for x86_64 systems) that will attempt to choose the appropriate sub-configuration automatically. * There is a difficulty in automatically choosing the ideal sub-configuration for use on Skylake-X systems, which may have one or two FMA units. The `skx` sub-configuration is only beneficial when used on hardware with two FMA units. Otherwise the hardware is treated as a "desktop" Skylake system, which uses the `haswell` sub-configuration. Furthermore, the number of units can't be queried directly; instead, we rely on a manually-maintained list of CPU models (via logic in `frame/base/bli_cpuid.c`), which may be incorrect for new processors, particularly Gold models. In that case, you can either fix the code (and please raise an issue!) or manually target the `skx` at configure-time (i.e., `./configure [options] skx`). If your performance seems low, you can set `export BLIS_ARCH_DEBUG=1`, which will cause BLIS to output some basic debugging info to `stderr` that will reveal whether your system was detected as having one or two VPUs (FMA units). | Vendor/Microarchitecture | BLIS sub-configuration | `gemm` | `gemmtrsm` | |:-------------------------------------|:-----------------------|:-------|:-----------| | AMD Bulldozer (AVX/FMA4) | `bulldozer` | `sdcz` | | | AMD Piledriver (AVX/FMA3) | `piledriver` | `sdcz` | | | AMD Steamroller (AVX/FMA3) | `steamroller` | `sdcz` | | | AMD Excavator (AVX/FMA3) | `excavator` | `sdcz` | | | AMD Zen (AVX/FMA3) | `zen` | `sdcz` | `sd` | | Intel Core2 (SSE3) | `penryn` | `sd` | `d` | | Intel Sandy/Ivy Bridge (AVX/FMA3) | `sandybridge` | `sdcz` | | | Intel Haswell, Broadwell (AVX/FMA3) | `haswell` | `sdcz` | `sd` | | Intel Sky/Kaby/CoffeeLake (AVX/FMA3) | `haswell` | `sdcz` | `sd` | | Intel Knights Landing (AVX-512/FMA3) | `knl` | `sd` | | | Intel SkylakeX (AVX-512/2×FMA3) | `skx` | `sd` | | | Intel SkylakeX (AVX-512/1×FMA3) | `haswell` | `sdcz` | `sd` | | ARMv7 Cortex-A9 (NEON) | `cortex-a9` | `sd` | | | ARMv7 Cortex-A15 (NEON) | `cortex-a15` | `sd` | | | ARMv8 Cortex-A53 (NEON) | `cortex-a53` | `sd` | | | ARMv8 Cortex-A57 (NEON) | `cortex-a57` | `sd` | | | ARMv8.1 ThunderX2 (NEON) | `thunderx2` | `sd` | | | ARMv8.1 A64FX (SVE) | `a64fx` | `d` | | | IBM Blue Gene/Q (QPX int) | `bgq` | `d` | | | IBM Power7 (QPX int) | `power7` | `d` | | | template (C99) | `template` | `sdcz` | `sdcz` | ## Level-1f kernels Not yet written. Please see the relevant sub-configuration (`bli_cntx_init_.c`) to determine which kernels are implemented/registered. ## Level-1v kernels Not yet written. Please see the relevant sub-configuration (`bli_cntx_init_.c`) to determine which kernels are implemented/registered. blis-0.9.0/docs/KernelsHowTo.md000066400000000000000000001752621422157504600163320ustar00rootroot00000000000000## Contents * **[Contents](KernelsHowTo.md#contents)** * **[Introduction](KernelsHowTo.md#introduction)** * **[BLIS kernels summary](KernelsHowTo.md#blis-kernels-summary)** * [Level-3](KernelsHowTo.md#level-3) * [Level-1f](KernelsHowTo.md#level-1f) * [Level-1v](KernelsHowTo.md#level-1v) * [Level-1v/-1f Dependencies for Level-2 operations](KernelsHowTo.md#level-1v-1f-dependencies-for-level-2-operations) * **[Calling kernels](KernelsHowTo.md#calling-kernels)** * **[BLIS kernels reference](KernelsHowTo.md#blis-kernels-reference)** * [Level-3 microkernels](KernelsHowTo.md#level-3-microkernels) * [Level-1f kernels](KernelsHowTo.md#level-1f-kernels) * [Level-1v kernels](KernelsHowTo.md#level-1v-kernels) ## Introduction This wiki describes the computational kernels used by the BLIS framework. One of the primary features of BLIS is that it provides a large set of dense linear algebra functionality while simultaneously minimizing the amount of kernel code that must be optimized for a given architecture. BLIS does this by isolating a handful of kernels which, when implemented, facilitate functionality and performance of several of the higher-level operations. Presently, BLIS supports several groups of operations: * **[Level-1v](BLISTypedAPI.md#level-1v-operations)**: Operations on vectors: * [addv](BLISTypedAPI.md#addv), [amaxv](BLISTypedAPI.md#amaxv), [axpyv](BLISTypedAPI.md#axpyv), [copyv](BLISTypedAPI.md#copyv), [dotv](BLISTypedAPI.md#dotv), [dotxv](BLISTypedAPI.md#dotxv), [invertv](BLISTypedAPI.md#invertv), [scal2v](BLISTypedAPI.md#scal2v), [scalv](BLISTypedAPI.md#scalv), [setv](BLISTypedAPI.md#setv), [subv](BLISTypedAPI.md#subv), [swapv](BLISTypedAPI.md#swapv) * **[Level-1d](BLISTypedAPI.md#level-1d-operations)**: Element-wise operations on matrix diagonals: * [addd](BLISTypedAPI.md#addd), [axpyd](BLISTypedAPI.md#axpyd), [copyd](BLISTypedAPI.md#copyd), [invertd](BLISTypedAPI.md#invertd), [scald](BLISTypedAPI.md#scald), [scal2d](BLISTypedAPI.md#scal2d), [setd](BLISTypedAPI.md#setd), [setid](BLISTypedAPI.md#setid), [subd](BLISTypedAPI.md#subd) * **[Level-1m](BLISTypedAPI.md#level-1m-operations)**: Element-wise operations on matrices: * [addm](BLISTypedAPI.md#addm), [axpym](BLISTypedAPI.md#axpym), [copym](BLISTypedAPI.md#copym), [scalm](BLISTypedAPI.md#scalm), [scal2m](BLISTypedAPI.md#scal2m), [setm](BLISTypedAPI.md#setm), [subm](BLISTypedAPI.md#subm) * **[Level-1f](BLISTypedAPI.md#level-1f-operations)**: Fused operations on multiple vectors: * [axpy2v](BLISTypedAPI.md#axpy2v), [dotaxpyv](BLISTypedAPI.md#dotaxpyv), [axpyf](BLISTypedAPI.md#axpyf), [dotxf](BLISTypedAPI.md#dotxf), [dotxaxpyf](BLISTypedAPI.md#dotxaxpyf) * **[Level-2](BLISTypedAPI.md#level-2-operations)**: Operations with one matrix and (at least) one vector operand: * [gemv](BLISTypedAPI.md#gemv), [ger](BLISTypedAPI.md#ger), [hemv](BLISTypedAPI.md#hemv), [her](BLISTypedAPI.md#her), [her2](BLISTypedAPI.md#her2), [symv](BLISTypedAPI.md#symv), [syr](BLISTypedAPI.md#syr), [syr2](BLISTypedAPI.md#syr2), [trmv](BLISTypedAPI.md#trmv), [trsv](BLISTypedAPI.md#trsv) * **[Level-3](BLISTypedAPI.md#level-3-operations)**: Operations with matrices that are multiplication-like: * [gemm](BLISTypedAPI.md#gemm), [hemm](BLISTypedAPI.md#hemm), [herk](BLISTypedAPI.md#herk), [her2k](BLISTypedAPI.md#her2k), [symm](BLISTypedAPI.md#symm), [syrk](BLISTypedAPI.md#syrk), [syr2k](BLISTypedAPI.md#syr2k), [trmm](BLISTypedAPI.md#trmm), [trmm3](BLISTypedAPI.md#trmm3), [trsm](BLISTypedAPI.md#trsm) * **[Utility](BLISTypedAPI.md#Utility-operations)**: Miscellaneous operations on matrices and vectors: * [asumv](BLISTypedAPI.md#asumv), [norm1v](BLISTypedAPI.md#norm1v), [normfv](BLISTypedAPI.md#normfv), [normiv](BLISTypedAPI.md#normiv), [norm1m](BLISTypedAPI.md#norm1m), [normfm](BLISTypedAPI.md#normfm), [normim](BLISTypedAPI.md#normim), [mkherm](BLISTypedAPI.md#mkherm), [mksymm](BLISTypedAPI.md#mksymm), [mktrim](BLISTypedAPI.md#mktrim), [fprintv](BLISTypedAPI.md#fprintv), [fprintm](BLISTypedAPI.md#fprintm),[printv](BLISTypedAPI.md#printv), [printm](BLISTypedAPI.md#printm), [randv](BLISTypedAPI.md#randv), [randm](BLISTypedAPI.md#randm), [sumsqv](BLISTypedAPI.md#sumsqv) Most of the interest with BLAS libraries centers around level-3 operations because they exhibit favorable ratios of floating-point operations (flops) to memory operations (memops), which allows high performance. Some applications also require level-2 computation; however, these operations are at an inherent disadvantage on modern architectures due to their less favorable flop-to-memop ratio. The BLIS framework allows developers to quickly and easily build high performance level-3 operations, as well as relatively well-performing level-2 operations, simply by optimizing a small set of kernels. These kernels, and their relationship to the other higher-level operations supported by BLIS, are the subject of this wiki. Some level-1v, level-1m, and level-1d operations may also be accelerated, but since they are memory-bound, optimization typically yields minor performance improvement. --- ## BLIS kernels summary This section lists and briefly describes each of the main computational kernels supported by the BLIS framework. (Other kernels are supported, but they are not of interest to most developers.) ### Level-3 BLIS supports the following three level-3 microkernels. These microkernels are used to implement optimized level-3 operations. * **gemm**: The `gemm` microkernel performs a small matrix multiplication and is used by every level-3 operation. * **trsm**: The `trsm` microkernel performs a small triangular solve with multiple right-hand sides. It is not required for optimal performance and in fact is only needed when the developer opts to not implement the fused `gemmtrsm` kernel. * **gemmtrsm**: The `gemmtrsm` microkernel implements a fused operation whereby a `gemm` and a `trsm` subproblem are fused together in a single routine. This avoids redundant memory operations that would otherwise be incurred if the operations were executed separately. The following shows the steps one would take to optimize, to varying degrees, the level-3 operations supported by BLIS: 1. By implementing and optimizing the `gemm` microkernel, **all** level-3 operations **except** `trsm` are fully optimized. In this scenario, the `trsm` operation may achieve 60-90% of attainable peak performance, depending on the architecture and problem size. 1. If one goes further and implements and optimizes the `trsm` microkernel, this kernel, when paired with an optimized `gemm` microkernel, results in a `trsm` implementation that is accelerated (but not optimized). 1. Alternatively, if one implements and optimizes the fused `gemmtrsm` microkernel, this kernel, when paired with an optimized `gemm` microkernel, enables a fully optimized `trsm` implementation. ### Level-1f BLIS supports the following five level-1f (fused) kernels. These kernels are used to implement optimized level-2 operations (as well as self-similar level-1f operations; that is, the `axpyf` kernel can be invoked indirectly via the `axpyf` operation). * **axpy2v**: Performs and fuses two [axpyv](BLISTypedAPI.md#axpyv) operations, accumulating to the same output vector. * **dotaxpyv**: Performs and fuses a [dotv](BLISTypedAPI.md#dotv) followed by an [axpyv](BLISTypedAPI.md#axpyv) operation with x. * **axpyf**: Performs and fuses some implementation-dependent number of [axpyv](BLISTypedAPI.md#axpyv) operations, accumulating to the same output vector. Can also be expressed as a [gemv](BLISTypedAPI.md#gemv) operation where matrix A is _m x nf_, where nf is the number of fused operations (fusing factor). * **dotxf**: Performs and fuses some implementation-dependent number of [dotxv](BLISTypedAPI.md#dotxv) operations, reusing the `y` vector for each [dotxv](BLISTypedAPI.md#dotxv). * **dotxaxpyf**: Performs and fuses a [dotxf](BLISTypedAPI.md#dotxf) and [axpyf](BLISTypedAPI.md#axpyf) in which the matrix operand is reused. ### Level-1v BLIS supports the following 14 level-1v kernels. These kernels are used primarily to implement their self-similar operations. However, they are occasionally used to handle special cases of level-1f kernels or in situations where level-2 operations are partially optimized. * **addv**: Performs a [vector addition](BLISTypedAPI.md#addv) operation. * **amaxv**: Performs a [search for the index of the element with the largest absolute value (or complex modulus)](BLISTypedAPI.md#amaxv). * **axpyv**: Performs a [vector scale-and-accumulate](BLISTypedAPI.md#axpyv) operation. * **axpbyv**: Performs an [extended vector scale-and-accumulate](BLISTypedAPI.md#axpbyv) operation similar to axpyv except that the output vector is scaled by a second scalar. * **copyv**: Performs a [vector copy](BLISTypedAPI.md#copyv) operation * **dotv**: Performs a [dot product](BLISTypedAPI.md#dotv) where the output scalar is overwritten. * **dotxv**: Performs an [extended dot product](BLISTypedAPI.md#dotxv) operation where the dot product is first scaled and then accumulated into a scaled output scalar. * **invertv**: Performs an [element-wise vector inversion](BLISTypedAPI.md#invertv) operation. * **scalv**: Performs an [in-place (destructive) vector scaling](BLISTypedAPI.md#scalv) operation. * **scal2v**: Performs an [out-of-place (non-destructive) vector scaling](BLISTypedAPI.md#scal2v) operation. * **setv**: Performs a [vector broadcast](BLISTypedAPI.md#setv) operation. * **subv**: Performs a [vector subtraction](BLISTypedAPI.md#subv) operation. * **swapv**: Performs a [vector swap](BLISTypedAPI.md#swapv) operation. * **xpbyv**: Performs a [alternate vector scale-and-accumulate](BLISTypedAPI.md#xpbyv) operation. ### Level-1v/-1f Dependencies for Level-2 operations The table below shows dependencies between level-2 operations and each of the level-1v and level-1f kernels. Kernels marked with a "1" for a given level-2 operation are preferred for optimization because they facilitate an optimal implementation on most architectures. Kernels marked with a "2", "3", or "4" denote those which need to be optimized for alternative implementations that would typically be second, third, or fourth choices, respectively, if the preferred kernels are not optimized. | operation / kernel | effective storage | `axpyv` | `dotxv` | `axpy2v` | `dotaxpyv` | `axpyf` | `dotxf` | `dotxaxpyf` | |:-------------------|:--------------------|:--------|:--------|:---------|:-----------|:--------|:--------|:------------| | `gemv, trmv, trsv` | row-wise | | 2 | | | | 1 | | | | column-wise | 2 | | | | 1 | | | | `hemv, symv` | row- or column-wise | 4 | 4 | | 3 | 2 | 2 | 1 | | `ger, her, syr` | row- or column-wise | 1 | | | | | | | | `her2, syr2` | row- or column-wise | 2 | | 1 | | | | | **Note:** The "effective storage" column reflects the orientation of the matrix operand **after** transposition via the corresponding `trans_t` parameter (if applicable). For example, calling `gemv` with a column-stored matrix `A` and the `transa` parameter equal to `BLIS_TRANSPOSE` would be effectively equivalent to row-wise storage. --- ## Calling kernels Note that all kernels, whether they be reference implementations or based on fully optimized assembly code, use names that are architecture- and implementation-specific. (This appears as a `` in the [kernel reference](KernelsHowTo.md#blis-kernels-reference) below.) Therefore, the easiest way to call the kernel is by querying a pointer from a valid context. The first step is to obtain a valid context. Contexts store all of the information specific to a particular sub-configuration (usually loosely specific to a microarchitecture or group of closely-related microarchitectures). If a context is not already available in your current scope, a default context for the hardware for which BLIS was configured (or, in the case of multi-configuration builds, the hardware on which BLIS is currently running) may be queried via: ```c cntx_t* bli_gks_query_cntx( void ); ``` Once this `cntx_t*` pointer is obtained, you may call one of three functions to query any of the computation kernels described in this document: ```c void* bli_cntx_get_l3_nat_ukr_dt ( num_t dt, l3ukr_t ker_id, cntx_t* cntx ); void* bli_cntx_get_l1f_ker_dt ( num_t dt, l1fkr_t ker_id, cntx_t* cntx ); void* bli_cntx_get_l1v_ker_dt ( num_t dt, l1vkr_t ker_id, cntx_t* cntx ); ``` The `dt` and `ker_id` parameters specify the floating-point datatype and the kernel operation you wish to query, respectively. Valid values for `dt` are `BLIS_FLOAT`, `BLIS_DOUBLE`, `BLIS_SCOMPLEX`, and `BLIS_DCOMPLEX` for single- and double-precision real, and single- and double-precision complex, respectively. Valid values for `ker_id` are given in the tables below. Also, note that the return values of `bli_cntx_get_l1v_ker_dt` `bli_cntx_get_l1f_ker_dt()`, and `bli_cntx_get_l3_nat_ukr_dt()`, will be `void*` and must be typecast to typed function pointers before being called. As a convenience, BLIS defines function pointer types appropriate for usage in these situations. The function pointer type for each operation is given in the third columns of each table, with the `?` taking the place of one of the supported datatype characters. | kernel operation | l3ukr_t | function pointer type | |:-----------------|:----------------------|:----------------------| | gemm | `BLIS_GEMM` | `?gemm_ukr_ft` | | trsm_l | `BLIS_TRSM_L_UKR` | `?trsm_ukr_ft` | | trsm_u | `BLIS_TRSM_U_UKR` | `?trsm_ukr_ft` | | gemmtrsm_l | `BLIS_GEMMTRSM_L_UKR` | `?gemmtrsm_ukr_ft` | | gemmtrsm_u | `BLIS_GEMMTRSM_U_UKR` | `?gemmtrsm_ukr_ft` | | kernel operation | l1fkr_t | function pointer type | |:-----------------|:----------------------|:----------------------| | axpy2v | `BLIS_AXPY2V_KER` | `?axpy2v_ft` | | dotaxpyv | `BLIS_DOTAXPYV_KER` | `?dotaxpyv_ft` | | axpyf | `BLIS_AXPYF_KER` | `?axpyf_ft` | | dotxf | `BLIS_DOTXF_KER` | `?dotxf_ft` | | dotxaxpyf | `BLIS_DOTXAXPYF_KER` | `?dotxaxpyf_ft` | | kernel operation | l1vkr_t | function pointer type | |:-----------------|:----------------------|:----------------------| | addv | `BLIS_ADDV_KER` | `?addv_ft` | | amaxv | `BLIS_AMAXV_KER` | `?amaxv_ft` | | axpyv | `BLIS_AXPYV_KER` | `?axpyv_ft` | | axpbyv | `BLIS_AXPBYV_KER` | `?axpbyv_ft` | | dotaxpyv | `BLIS_DOTAXPYV_KER` | `?dotaxpyv_ft` | | copyv | `BLIS_COPYV_KER` | `?copyv_ft` | | dotxv | `BLIS_DOTXV_KER` | `?dotxv_ft` | | invertv | `BLIS_INVERTV_KER` | `?invertv_ft` | | scalv | `BLIS_SCALV_KER` | `?scalv_ft` | | scal2v | `BLIS_SCAL2V_KER` | `?scal2v_ft` | | setv | `BLIS_SETV_KER` | `?setv_ft` | | subv | `BLIS_SUBV_KER` | `?subv_ft` | | swapv | `BLIS_SWAPV_KER` | `?swapv_ft` | | xpybv | `BLIS_XPBYV_KER` | `?xpbyv_ft` | The specific information behind a queried function pointer is not typically available. However, it is guaranteed that the function pointer will always be valid (usually either an optimized assembly implementation or a reference implementation). --- ## BLIS kernels reference This section seeks to provide developers with a complete reference for each of the following BLIS kernels, including function prototypes, parameter descriptions, implementation notes, and diagrams: * [Level-3 microkernels](KernelsHowTo.md#level-3-microkernels) * [gemm](KernelsHowTo.md#gemm-microkernel) * [trsm](KernelsHowTo.md#trsm-microkernels) * [gemmtrsm](KernelsHowTo.md#gemmtrsm-microkernels) * [Level-1f kernels](KernelsHowTo.md#level-1f-kernels) * [axpy2v](KernelsHowTo.md#axpy2v-kernel) * [dotaxpyv](KernelsHowTo.md#dotaxpyv-kernel) * [axpyf](KernelsHowTo.md#axpyf-kernel) * [dotxf](KernelsHowTo.md#dotxf-kernel) * [dotxaxpyf](KernelsHowTo.md#dotxaxpyf-kernel) * [Level-1v kernels](KernelsHowTo.md#level-1v-kernels) * [addv](KernelsHowTo.md#addv-kernel) * [amaxv](KernelsHowTo.md#amaxv-kernel) * [axpyv](KernelsHowTo.md#axpyv-kernel) * [axpbyv](KernelsHowTo.md#axpbyv-kernel) * [copyv](KernelsHowTo.md#copyv-kernel) * [dotv](KernelsHowTo.md#dotv-kernel) * [dotxv](KernelsHowTo.md#dotxv-kernel) * [invertv](KernelsHowTo.md#invertv-kernel) * [scalv](KernelsHowTo.md#scalv-kernel) * [scal2v](KernelsHowTo.md#scal2v-kernel) * [setv](KernelsHowTo.md#setv-kernel) * [subv](KernelsHowTo.md#subv-kernel) * [swapv](KernelsHowTo.md#swapv-kernel) * [xpbyv](KernelsHowTo.md#xpbyv-kernel) The function prototypes in this section follow the same guidelines as those listed in the [BLIS typed API reference](BLISTypedAPI.md#Notes_for_using_this_reference). Namely: * Any occurrence of `?` should be replaced with `s`, `d`, `c`, or `z` to form an actual function name. * Any occurrence of `ctype` should be replaced with the actual C99 language type corresponding to the datatype instance in question. * Some matrix arguments have associated row and column strides arguments that proceed them, typically listed as `rsX` and `csX` for a given matrix `X`. Row strides are always listed first, and column strides are always listed second. The semantic meaning of a row stride is "the distance, in units of elements, from any given element to the corresponding element (within the same column) of the next row," and the meaning of a column stride is "the distance, in units of elements, from any given element to the corresponding element (within the same row) of the next column." Thus, unit row stride implies column-major storage and unit column stride implies row-major storage. * All occurrences of `alpha` and `beta` parameters are scalars. ### Level-3 microkernels This section describes in detail the various level-3 microkernels supported by BLIS: * [gemm](KernelsHowTo.md#gemm-microkernel) * [trsm](KernelsHowTo.md#trsm-microkernels) * [gemmtrsm](KernelsHowTo.md#gemmtrsm-microkernels) #### gemm microkernel ```c void bli_?gemm_ ( dim_t m, dim_t n, dim_t k, ctype* restrict alpha, ctype* restrict a1, ctype* restrict b1, ctype* restrict beta, ctype* restrict c11, inc_t rsc, inc_t csc, auxinfo_t* restrict data, cntx_t* restrict cntx ); ``` where `` is implementation-dependent. (Recall that the precise `` associated with the microkernel along with the rest of the function name doesn't matter if you are querying the function address from the context. See section on [calling kernels](KernelsHowTo.md#calling-kernels) for details.) The following (more portable) wrapper is also defined: ```c void bli_?gemm_ukernel ( dim_t m, dim_t n, dim_t k, ctype* restrict alpha, ctype* restrict a1, ctype* restrict b1, ctype* restrict beta, ctype* restrict c11, inc_t rsc, inc_t csc, auxinfo_t* restrict data, cntx_t* restrict cntx ); ``` This function simply queries a microkernel function pointer from the context specified by `cntx`. Note that in the case of either method of calling the microkernel, `cntx` must be a valid pointer. (Passing in `NULL` will *not* result in a default context being used.) The `gemm` microkernel, sometimes simply referred to as "the BLIS microkernel" or "the microkernel", performs the following operation: ``` C11 := beta * C11 + alpha * A1 * B1 ``` where `A1` is an _m x k_ "micropanel" matrix stored in packed (column-wise) format, `B1` is a _k x n_ "micropanel" matrix stored in packed (row-wise) format, `C11` is an _m x n_ "microtile" matrix stored according to its row and column strides `rsc` and `csc`, and `alpha` and beta are scalars. Here, _m <= MR_ and _n <= NR_, where _MR_ and _NR_ are the register blocksizes associated with the microkernel. They are chosen by the developer when the microkernel is written and then encoded into a BLIS configuration, which will reference the microkernel when the BLIS framework is instantiated into a library. For more information on setting register blocksizes and related constants, please see the [BLIS developer configuration guide](ConfigurationHowTo.md). **Note:** For many years, BLIS defined its microkernel to operate on microtiles whose dimensions were *exactly* _MR x NR_. However, as of commit 54fa28b, we have augmented the `gemm` microkernel API to pass in _m_ and _n_ dimensions as well as _k_. This change was made as part of our decision to move edge-case handling into the microkernel, whereas previously it was handled outside of the microkernel, within the portable parts of BLIS framework. And while this does mean additional complexity for microkernel authors, adding generic edge-case handling can be done in a relatively painless manner by employing some pre-defined preprocessor macros (which are defined in `bli_edge_case_macro_defs.h`). For examples of how to use these macros, please see the beginning and end of existing microkernel functions residing within the `kernels` directory. Parameters: * `m`: The number of rows of `C11` and `A1`. * `n`: The number of columns of `C11` and `B1`. * `k`: The number of columns of `A1` and rows of `B1`. * `alpha`: The address of a scalar to the `A1 * B1` product. * `a1`: The address of a micropanel of matrix `A` of dimension _m x k_ (where _m <= MR_), stored by columns with leading dimension _PACKMR_, where typically _PACKMR_ = _MR_. (See [Implementation Notes for gemm](KernelsHowTo.md#implementation-notes-for-gemm) for a discussion of _PACKMR_.) * `b1`: The address of a micropanel of matrix `B` of dimension _k x n_ (where _n <= NR_), stored by rows with leading dimension _PACKNR_, where typically _PACKNR_ = _NR_. (See [Implementation Notes for gemm](KernelsHowTo.md#implementation-notes-for-gemm) for a discussion of _PACKNR_.) * `beta`: The address of a scalar to the input value of matrix `C11`. * `c11`: The address of a matrix `C11` of dimension _MR x NR_, stored according to `rsc` and `csc`. * `rsc`: The row stride of matrix `C11` (ie: the distance to the next row, in units of matrix elements). * `csc`: The column stride of matrix `C11` (ie: the distance to the next column, in units of matrix elements). * `data`: The address of an `auxinfo_t` object that contains auxiliary information that may be useful when optimizing the `gemm` microkernel implementation. (See [Using the auxinfo\_t object](KernelsHowTo.md#Using_the_auxinfo_t_object) for a discussion of the kinds of values available via `auxinfo_t`.) * `cntx`: The address of the runtime context. The context can be queried for implementation-specific values such as cache and register blocksizes. However, most microkernels intrinsically "know" these values already, and thus the `cntx` argument usually can be safely ignored. #### Diagram for gemm The diagram below shows the packed micropanel operands and how elements of each would be stored when _MR_ = _NR_ = 4. The hex digits indicate the layout and order (but NOT the numeric contents) of the elements in memory. Note that the storage of `C11` is not shown since it is determined by the row and column strides of `C11`. ``` c11: a1: b1: _______ ______________________ _______ | | |0 4 8 C | |0 1 2 3| MR | | |1 5 9 D . . . | |4 5 6 7| | | += |2 6 A E | |8 9 A B| |_______| |3_7_B_F_______________| |C D E F| | . | NR k | . | k | . | | | | | |_______| NR ``` #### Implementation Notes for gemm * **Register blocksizes.** The register blocksizes `MR` and `NR`, corresponding to the maximum number of *logical* rows in `a1` and columns in `b1`, respectively, are defined in the context and may be queried via `bli_cntx_get_blksz_def_dt()`. However, you shouldn't need to query these values since the implementation inherently "knows" them already. * **Leading dimensions of `a1` and `b1`: _PACKMR_ and _PACKNR_.** The packed micropanels `a1` and `b1` are simply stored in column-major and row-major order, respectively. Usually, the width of either micropanel (ie: the number of *logical* rows of `a1` and the number of columns of `b1`) is equal to that micropanel's so-called "leading dimension", or number of *physical* rows. Sometimes, it may be beneficial to specify a leading dimension that is larger than the panel width. This may be desirable because it allows each column of `a1` or row of `b1` to maintain a certain alignment in memory that would not otherwise be maintained by _MR_ and/or _NR_, which would othewise serve as the maximum value for each micropanel, respectively. If you want your microkernel to support _MR < PACKMR_ or _NR < PACKNR_, you should index through columns of `a1` and rows of `b1` using the values _PACKMR_ and _PACKNR_, respectively (which are stored in the context as the blocksize "maximums" associated with the `bszid_t` values `BLIS_MR` and `BLIS_NR`). These values are defined in the context and may be queried via `bli_cntx_get_blksz_max_dt()`. However, you shouldn't need to query these values since the microkernel implementation inherently must "know" them already. * **Storage preference of `c11`.** Usually, an optimized `gemm` microkernel will have a "preferred" storage format for `C11`--typically either contiguous row-storage (i.e. `cs_c` = 1) or contiguous column-storage (i.e. `rs_c` = 1). This preference comes from how the microkernel is most efficiently able to load/store elements of `C11` from/to memory. Most microkernels use vector instructions to access contiguous columns (or column segments) of `C11`. However, the developer may decide that accessing contiguous rows (or row segments) is more desirable. If this is the case, this preference should be indicated via the `bool` argument when registering microkernels via `bli_cntx_set_l3_nat_ukrs()`--`TRUE` indicating a row preference and `FALSE` indicating a column preference. Properly setting this property allows the framework to perform a runtime optimization that will ensure the microkernel preference is honored, if at all possible. * **Edge cases in _MR_, _NR_ dimensions.** Sometimes the microkernel will be called with micropanels `a1` and `b1` that correspond to edge cases, where only partial results are needed. This edge-case handling was once performed by the framework automatically. However, as of commit 54fa28b, edge-case handling is the responsiblity of the microkernel. This means that the kernel author will need to handle all possible values of _m_ and _n_ that are equal to **or** less than _MR_ and _NR_, respectively. Fortunately, this can be implemented outside of the assembly region of the microkernel with preprocessor macros. Please reference the existing microkernels in the `kernels` directory for examples of how this is done. (The macros that are now employed by most of BLIS's microkernels are defined in `bli_edge_case_macro_defs.h`.) * **Alignment of `a1` and `b1`.** By default, the alignment of addresses `a1` and `b1` are aligned to the page size (4096 bytes). These alignment factors are set by `BLIS_POOL_ADDR_ALIGN_SIZE_A` and `BLIS_POOL_ADDR_ALIGN_SIZE_B`, respectively. Note that these alignment factors control only the alignment of the *first* micropanel within a given packed blockof matrix `A` or packed row-panel of matrix `B`. Subsequent micropanels will only be aligned to `sizeof(type)`, or, if `BLIS_POOL_ADDR_ALIGN_SIZE_A` is a multiple of `PACKMR` and/or `BLIS_POOL_ADDR_ALIGN_SIZE_B` is a multiple of `PACKNR`, then subsequent micropanels `a1` and/or `b1` will be aligned to `PACKMR * sizeof(type)` and/or `PACKNR * sizeof(type)`, respectively. * **Unrolling loops.** As a general rule of thumb, the loop over _k_ is sometimes moderately unrolled; for example, in our experience, an unrolling factor of _u_ = 4 is fairly common. If unrolling is applied in the _k_ dimension, edge cases must be handled to support values of _k_ that are not multiples of _u_. It is nearly universally true that the microkernel should not contain loops in the _m_ or _n_ directions; in other words, iteration over these dimensions should always be fully unrolled (within the loop over _k_). * **Zero `beta`.** If `beta` = 0.0 (or 0.0 + 0.0i for complex datatypes), then the microkernel should NOT use it explicitly, as `C11` may contain uninitialized memory (including elements containing `NaN` or `Inf`). This case should be detected and handled separately by overwriting `C11` with the `alpha * A1 * B1` product. #### Using the auxinfo\_t object Each microkernel ([gemm](KernelsHowTo.md#gemm-microkernel), [trsm](KernelsHowTo.md#trsm_microkernels), and [gemmtrsm](KernelsHowTo.md#gemmtrsm-microkernels)) takes as its last argument a pointer of type `auxinfo_t`. This BLIS-defined type is defined as a `struct` whose fields contain auxiliary values that may be useful to some microkernel authors, particularly when implementing certain optimization techniques. BLIS provides kernel authors access to the fields of the `auxinfo_t` object via the following static inline functions. Each function takes a single argument, the `auxinfo_t` pointer, and returns one of the values stored within the object. * `bli_auxinfo_next_a()`. Returns the address (`void*`) of the micropanel of `A` that will be used the next time the microkernel will be called. * `bli_auxinfo_next_b()`. Returns the address (`void*`) of the micropanel of `B` that will be used the next time the microkernel will be called. * `bli_auxinfo_ps_a()`. Returns the panel stride (`inc_t`) of the current micropanel of `A`. * `bli_auxinfo_ps_b()`. Returns the panel stride (`inc_t`) of the current micropanel of `B`. The addresses of the next micropanels of `A` and `B` may be used by the microkernel to perform prefetching, if prefetching is supported by the architecture. Similarly, it may be useful to know the precise distance in memory to the next micropanel. (Note that occasionally the next micropanel to be used is **not** the same as the next micropanel in memory.) Any and all of these values may be safely ignored; they are completely optional. However, BLIS guarantees that all values accessed via the macros listed above will **always** be initialized and meaningful, for every invocation of each microkernel (`gemm`, `trsm`, and `gemmtrsm`). #### Example code for gemm An example implementation of the `gemm` microkernel may be found in the `template` configuration directory in: * [config/template/kernels/3/bli\_gemm_opt\_mxn.c](https://github.com/flame/blis/tree/master/config/template/kernels/3/bli_gemm_opt_mxn.c) Note that this implementation is coded in C99 and lacks several kinds of optimization that are typical of real-world optimized microkernels, such as vector instructions (or intrinsics) and loop unrolling in the _m_ or _n_ dimensions. It is meant to serve only as a starting point for a microkernel developer. --- #### trsm microkernels ```c void bli_?trsm_l_ ( ctype* restrict a11, ctype* restrict b11, ctype* restrict c11, inc_t rsc, inc_t csc, auxinfo_t* restrict data, cntx_t* restrict cntx ); void bli_?trsm_u_ ( ctype* restrict a11, ctype* restrict b11, ctype* restrict c11, inc_t rsc, inc_t csc, auxinfo_t* restrict data, cntx_t* restrict cntx ); ``` where `` is implementation-dependent. (Recall that the precise `` associated with the microkernel along with the rest of the function name doesn't matter if you are querying the function address from the context. See section on [calling kernels](KernelsHowTo.md#calling-kernels) for details.) The following (more portable) wrappers are also defined: ```c void bli_?trsm_l_ukernel ( ctype* restrict a11, ctype* restrict b11, ctype* restrict c11, inc_t rsc, inc_t csc, auxinfo_t* restrict data, cntx_t* restrict cntx ); void bli_?trsm_u_ukernel ( ctype* restrict a11, ctype* restrict b11, ctype* restrict c11, inc_t rsc, inc_t csc, auxinfo_t* restrict data, cntx_t* restrict cntx ); ``` The `trsm_l` and `trsm_u` microkernels perform the following operation: ``` C11 := inv(A11) * B11 ``` where `A11` is _MR x MR_ and lower (`trsm_l`) or upper (`trsm_u`) triangular, `B11` is _MR x NR_, and `C11` is _MR x NR_. _MR_ and _NR_ are the register blocksizes associated with the microkernel. They are chosen by the developer when the microkernel is written and then encoded into a BLIS configuration, which will reference the microkernel when the BLIS framework is instantiated into a library. For more information on setting register blocksizes and related constants, please see the [BLIS developer configuration guide](ConfigurationHowTo.md). **Note:** Although the `gemm` microkernel must handle edge-cases, and therefore must take _m_ and _n_ parameters, the `trsm` microkernels are simpler in that they still assume _m = MR_ and _n = NR_, and therefore do not need these _m_ and _n_ parameters passed in. Parameters: * `a11`: The address of `A11`, which is the _MR x MR_ lower (`trsm_l`) or upper (`trsm_u`) triangular submatrix within the packed micropanel of matrix `A`. `A11` is stored by columns with leading dimension _PACKMR_, where typically _PACKMR_ = _MR_. (See [Implementation Notes for gemm](KernelsHowTo.md#implementation-notes-for-gemm) for a discussion of _PACKMR_.) Note that `A11` contains elements in both triangles, though elements in the unstored triangle are not guaranteed to be zero and thus should not be referenced. * `b11`: The address of `B11`, which is an _MR x NR_ submatrix of the packed micropanel of `B`. `B11` is stored by rows with leading dimension _PACKNR_, where typically _PACKNR_ = _NR_. (See [Implementation Notes for gemm](KernelsHowTo.md#implementation-notes-for-gemm) for a discussion of _PACKNR_.) * `c11`: The address of `C11`, which is an _MR x NR_ submatrix of matrix `C`, stored according to `rsc` and `csc`. `C11` is the submatrix within `C` that corresponds to the elements which were packed into `B11`. Thus, `C` is the original input matrix `B` to the overall `trsm` operation. * `rsc`: The row stride of matrix `C11` (ie: the distance to the next row, in units of matrix elements). * `csc`: The column stride of matrix `C11` (ie: the distance to the next column, in units of matrix elements). * `data`: The address of an `auxinfo_t` object that contains auxiliary information that may be useful when optimizing the `trsm` microkernel implementation. (See [Using the auxinfo\_t object](KernelsHowTo.md#Using_the_auxinfo_t_object) for a discussion of the kinds of values available via `auxinfo_t`, and also [Implementation Notes for trsm](KernelsHowTo.md#implementation-notes-for-trsm) for caveats.) * `cntx`: The address of the runtime context. The context can be queried for implementation-specific values such as cache and register blocksizes. However, most microkernels intrinsically "know" these values already, and thus the `cntx` argument usually can be safely ignored. #### Diagrams for trsm Please see the diagram for [gemmtrsm\_l](KernelsHowTo.md#diagram-for-gemmtrsm-l) and [gemmtrsm\_u](KernelsHowTo.md#diagram-for-gemmtrsm-u) to see depictions of the `trsm_l` and `trsm_u` microkernel operations and where they fit in with their preceding `gemm` subproblems. #### Implementation Notes for trsm * **Register blocksizes.** See [Implementation Notes for gemm](KernelsHowTo.md#implementation-notes-for-gemm). * **Leading dimensions of `a11` and `b11`: _PACKMR_ and _PACKNR_.** See [Implementation Notes for gemm](KernelsHowTo.md#implementation-notes-for-gemm). * **Edge cases in _MR_, _NR_ dimensions.** See [Implementation Notes for gemm](KernelsHowTo.md#implementation-notes-for-gemm). * **Alignment of `a11` and `b11`.** The addresses `a11` and `b11` are aligned according to `PACKMR * sizeof(type)` and `PACKNR * sizeof(type)`, respectively. * **Unrolling loops.** Most optimized implementations should unroll all three loops within the `trsm` microkernel. * **Prefetching next micropanels of `A` and `B`.** We advise against using the `bli_auxinfo_next_a()` and `bli_auxinfo_next_b()` macros from within the `trsm_l` and `trsm_u` microkernels, since the values returned usually only make sense in the context of the overall `gemmtrsm` subproblem. * **Diagonal elements of `A11`.** At the time this microkernel is called, the diagonal entries of triangular matrix `A11` contain the **_inverse_** of the original elements. This inversion is done during packing so that we can avoid expensive division instructions within the microkernel itself. If the `diag` parameter to the higher level `trsm` operation was equal to `BLIS_UNIT_DIAG`, the diagonal elements will be explicitly unit. * **Zero elements of `A11`.** Since `A11` is lower triangular (for `trsm_l`), the strictly upper triangle implicitly contains zeros. Similarly, the strictly lower triangle of `A11` implicitly contains zeros when `A11` is upper triangular (for `trsm_u`). However, the packing function may or may not actually write zeros to this region. Thus, the implementation should not reference these elements. * **Output.** This microkernel must write its result to two places: the submatrix `B11` of the current packed micropanel of `B` _and_ the submatrix `C11` of the output matrix `C`. #### Example code for trsm Example implementations of the `trsm` microkernels may be found in the `template` configuration directory in: * [config/template/kernels/3/bli\_trsm\_l\_opt\_mxn.c](https://github.com/flame/blis/tree/master/config/template/kernels/3/bli_trsm_l_opt_mxn.c) * [config/template/kernels/3/bli\_trsm\_u\_opt\_mxn.c](https://github.com/flame/blis/tree/master/config/template/kernels/3/bli_trsm_u_opt_mxn.c) Note that these implementations are coded in C99 and lack several kinds of optimization that are typical of real-world optimized microkernels, such as vector instructions (or intrinsics) and loop unrolling in _MR_ or _NR_. They are meant to serve only as a starting point for a microkernel developer. --- #### gemmtrsm microkernels ```c void bli_?gemmtrsm_l_ ( dim_t m, dim_t n, dim_t k, ctype* restrict alpha, ctype* restrict a10, ctype* restrict a11, ctype* restrict b01, ctype* restrict b11, ctype* restrict c11, inc_t rsc, inc_t csc, auxinfo_t* restrict data, cntx_t* restrict cntx ); void bli_?gemmtrsm_u_ ( dim_t m, dim_t n, dim_t k, ctype* restrict alpha, ctype* restrict a12, ctype* restrict a11, ctype* restrict b21, ctype* restrict b11, ctype* restrict c11, inc_t rsc, inc_t csc, auxinfo_t* restrict data, cntx_t* restrict cntx ); ``` where `` is implementation-dependent. (Recall that the precise `` associated with the microkernel along with the rest of the function name doesn't matter if you are querying the function address from the context. See section on [calling kernels](KernelsHowTo.md#calling-kernels) for details.) The following (more portable) wrappers are also defined: ```c void bli_?gemmtrsm_l_ukernel ( dim_t m, dim_t n, dim_t k, ctype* restrict alpha, ctype* restrict a10, ctype* restrict a11, ctype* restrict b01, ctype* restrict b11, ctype* restrict c11, inc_t rsc, inc_t csc, auxinfo_t* restrict data, cntx_t* restrict cntx ); void bli_?gemmtrsm_u_ukernel ( dim_t m, dim_t n, dim_t k, ctype* restrict alpha, ctype* restrict a12, ctype* restrict a11, ctype* restrict b21, ctype* restrict b11, ctype* restrict c11, inc_t rsc, inc_t csc, auxinfo_t* restrict data, cntx_t* restrict cntx ); ``` The `gemmtrsm_l` microkernel performs the following compound operation: ``` B11 := alpha * B11 - A10 * B01 B11 := inv(A11) * B11 C11 := B11 ``` where `A11` is _MR x MR_ and lower triangular, `A10` is _MR x k_, and `B01` is _k x NR_. The `gemmtrsm_u` microkernel performs: ``` B11 := alpha * B11 - A12 * B21 B11 := inv(A11) * B11 C11 := B11 ``` where `A11` is _MR x MR_ and upper triangular, `A12` is _MR x k_, and `B21` is _k x NR_. In both cases, `B11` is _MR x NR_ and `alpha` is a scalar. However, `C11` is _m x n_, and therefore the `C11 := B11` statements amount to a copy of only the top-leftmost _m x n_ elements of `B11`. (Recall that A11 and B11 are packed and therefore guaranteed to reside within fully-sized micropanels, whereas `C11` exists in the caller-provided output matrix and may represent a bottom-right edge case.) Here, `inv()` denotes matrix inverse. _MR_ and _NR_ are the register blocksizes associated with the microkernel. They are chosen by the developer when the microkernel is written and then encoded into a BLIS configuration, which will reference the microkernel when the BLIS framework is instantiated into a library. For more information on setting register blocksizes and related constants, please see the [BLIS developer configuration guide](ConfigurationHowTo.md). Parameters: * `m`: The number of rows of `C11`. * `n`: The number of columns of `C11`. * `k`: The number of columns of `A10` and rows of `B01` (`trsm_l`); the number of columns of `A12` and rows of `B21` (`trsm_u`). * `alpha`: The address of a scalar to be applied to `B11`. * `a10`, `a12`: The address of `A10` or `A12`, which is the _MR x k_ submatrix of the packed micropanel of `A` that is situated to the left (`trsm_l`) or right (`trsm_u`) of the _MR x MR_ triangular submatrix `A11`. `A10` and `A12` are stored by columns with leading dimension _PACKMR_, where typically _PACKMR_ = _MR_. (See [Implementation Notes for gemm](KernelsHowTo.md#implementation-notes-for-gemm) for a discussion of _PACKMR_.) * `a11`: The address of `A11`, which is the _MR x MR_ lower (`trsm_l`) or upper (`trsm_u`) triangular submatrix within the packed micropanel of matrix `A` that is situated to the right of `A10` (`trsm_l`) or the left of `A12` (`trsm_u`). `A11` is stored by columns with leading dimension _PACKMR_, where typically _PACKMR_ = _MR_. (See [Implementation Notes for gemm](KernelsHowTo.md#implementation-notes-for-gemm) for a discussion of _PACKMR_.) Note that `A11` contains elements in both triangles, though elements in the unstored triangle are not guaranteed to be zero and thus should not be referenced. * `b01`, `b21`: The address of `B01` and `B21`, which is the _k x NR_ submatrix of the packed micropanel of `B` that is situated above (`trsm_l`) or below (`trsm_u`) the _MR x NR_ block `B11`. `B01` and `B21` are stored by rows with leading dimension _PACKNR_, where typically _PACKNR_ = _NR_. (See [Implementation Notes for gemm](KernelsHowTo.md#implementation-notes-for-gemm) for a discussion of _PACKNR_.) * `b11`: The address of `B11`, which is the _MR x NR_ submatrix of the packed micropanel of `B`, situated below `B01` (`trsm_l`) or above `B21` (`trsm_u`). `B11` is stored by rows with leading dimension _PACKNR_, where typically _PACKNR_ = _NR_. (See [Implementation Notes for gemm](KernelsHowTo.md#implementation-notes-for-gemm) for a discussion of _PACKNR_.) * `c11`: The address of `C11`, which is an _m x n_ submatrix of matrix `C`, stored according to `rsc` and `csc`, where _m <= MR_ and _n <= NR_. `C11` is the submatrix within `C` that corresponds to the elements which were packed into `B11`. Thus, `C` is the original input matrix `B` to the overall `trsm` operation. * `rsc`: The row stride of matrix `C11` (ie: the distance to the next row, in units of matrix elements). * `csc`: The column stride of matrix `C11` (ie: the distance to the next column, in units of matrix elements). * `data`: The address of an `auxinfo_t` object that contains auxiliary information that may be useful when optimizing the `gemmtrsm` microkernel implementation. (See [Using the auxinfo\_t object](KernelsHowTo.md#Using_the_auxinfo_t_object) for a discussion of the kinds of values available via `auxinfo_t`, and also [Implementation Notes for gemmtrsm](KernelsHowTo.md#implementation-notes-for-gemmtrsm) for caveats.) * `cntx`: The address of the runtime context. The context can be queried for implementation-specific values such as cache and register blocksizes. However, most microkernels intrinsically "know" these values already, and thus the `cntx` argument usually can be safely ignored. #### Diagram for gemmtrsm\_l The diagram below shows the packed micropanel operands for `trsm_l` and how elements of each would be stored when _MR_ = _NR_ = 4. (The hex digits indicate the layout and order (but NOT the numeric contents) in memory. Here, matrix `A11` (referenced by `a11`) is **lower triangular**. Matrix `A11` **does contain** elements corresponding to the strictly upper triangle, however, they are not guaranteed to contain zeros and thus these elements should not be referenced. ``` NR _______ b01:|0 1 2 3| |4 5 6 7| |8 9 A B| |C D E F| k | . | | . | a10: a11: | . | ___________________ _______ |_______| |0 4 8 C |`. | b11:| | MR |1 5 9 D . . . | `. | | | |2 6 A E | `. | MR | | |3_7_B_F____________|______`.| |_______| k MR ``` #### Diagram for gemmtrsm\_u The diagram below shows the packed micropanel operands for `trsm_u` and how elements of each would be stored when _MR_ = _NR_ = 4. (The hex digits indicate the layout and order (but NOT the numeric contents) in memory. Here, matrix `A11` (referenced by `a11`) is **upper triangular**. Matrix `A11` **does contain** elements corresponding to the strictly lower triangle, however, they are not guaranteed to contain zeros and thus these elements should not be referenced. ``` a11: a12: NR ________ ___________________ _______ |`. |0 4 8 | b11:|0 1 2 3| MR | `. |1 5 9 . . . | |4 5 6 7| | `. |2 6 A | MR |8 9 A B| |______`.|3_7_B______________| |___.___| b21:| . | MR k | . | | | | | NOTE: Storage digits are shown k | | starting with a12 to avoid | | obscuring triangular structure | | of a11. |_______| ``` #### Implementation Notes for gemmtrsm * **Register blocksizes.** See [Implementation Notes for gemm](KernelsHowTo.md#implementation-notes-for-gemm). * **Leading dimensions of `a1` and `b1`: _PACKMR_ and _PACKNR_.** See [Implementation Notes for gemm](KernelsHowTo.md#implementation-notes-for-gemm). * **Edge cases in _MR_, _NR_ dimensions.** See [Implementation Notes for gemm](KernelsHowTo.md#implementation-notes-for-gemm). * **Alignment of `a1` and `b1`.** See [Implementation Notes for gemm](KernelsHowTo.md#implementation-notes-for-gemm). * **Unrolling loops.** Most optimized implementations should unroll all three loops within the `trsm` subproblem of `gemmtrsm`. See [Implementation Notes for gemm](KernelsHowTo.md#implementation-notes-for-gemm) for remarks on unrolling the `gemm` subproblem. * **Prefetching next micropanels of `A` and `B`.** When invoked from within a `gemmtrsm_l` microkernel, the addresses accessible via `bli_auxinfo_next_a()` and `bli_auxinfo_next_b()` refer to the next invocation's `a10` and `b01`, respectively, while in `gemmtrsm_u`, the `_next_a()` and `_next_b()` macros return the addresses of the next invocation's `a11` and `b11` (since those submatrices precede `a12` and `b21`). * **Zero `alpha`.** The microkernel can safely assume that `alpha` is non-zero; "alpha equals zero" handling is performed at a much higher level, which means that, in such a scenario, the microkernel will never get called. * **Diagonal elements of `A11`.** See [Implementation Notes for trsm](KernelsHowTo.md#implementation-notes-for-trsm). * **Zero elements of `A11`.** See [Implementation Notes for trsm](KernelsHowTo.md#implementation-notes-for-trsm). * **Output.** See [Implementation Notes for trsm](KernelsHowTo.md#implementation-notes-for-trsm). * **Optimization.** Let's assume that the [gemm microkernel](KernelsHowTo.md#gemm-microkernel) has already been optimized. You have two options with regard to optimizing the fused `gemmtrsm` microkernels: 1. Optimize only the [trsm microkernels](KernelsHowTo.md#trsm-microkernels). This will result in the `gemm` and `trsm_l` microkernels being called in sequence. (Likewise for `gemm` and `trsm_u`.) 1. Fuse the implementation of the `gemm` microkernel with that of the `trsm` microkernels by inlining both into the `gemmtrsm_l` and `gemmtrsm_u` microkernel definitions. This option is more labor-intensive, but also more likely to yield higher performance because it avoids redundant memory operations on the packed _MR x NR_ submatrix `B11`. #### Example code for gemmtrsm Example implementations of the `gemmtrsm` microkernels may be found in the `template` configuration directory in: * [config/template/kernels/3/bli\_gemmtrsm\_l\_opt\_mxn.c](https://github.com/flame/blis/tree/master/config/template/kernels/3/bli_gemmtrsm_l_opt_mxn.c) * [config/template/kernels/3/bli\_gemmtrsm\_u\_opt\_mxn.c](https://github.com/flame/blis/tree/master/config/template/kernels/3/bli_gemmtrsm_u_opt_mxn.c) Note that these implementations are coded in C99 and lack several kinds of optimization that are typical of real-world optimized microkernels, such as vector instructions (or intrinsics) and loop unrolling in _MR_ or _NR_. They are meant to serve only as a starting point for a microkernel developer. ### Level-1f kernels --- #### axpy2v kernel ```c void bli_?axpy2v_ ( conj_t conjx, conj_t conjy, dim_t n, ctype* restrict alphax, ctype* restrict alphay, ctype* restrict x, inc_t incx, ctype* restrict y, inc_t incy, ctype* restrict z, inc_t incz, cntx_t* restrict cntx ) ``` This kernel performs the following operation: ``` z := z + alphax * conjx(x) + alphay * conjy(y) ``` where `x`, `y`, and `z` are vectors of length _n_ stored with strides `incx`, `incy`, and `incz`, respectively. This kernel is typically implemented as the fusion of two `axpyv` operations on different input vectors `x` and `y` and with different scalars `alphax` and `alpay` to update the same output vector `z`. --- #### dotaxpyv kernel ```c void bli_?dotaxpyv_ ( conj_t conjxt, conj_t conjx, conj_t conjy, dim_t n, ctype* restrict alpha, ctype* restrict x, inc_t incx, ctype* restrict y, inc_t incy, ctype* restrict rho, ctype* restrict z, inc_t incz, cntx_t* restrict cntx ) ``` This kernel performs the following operation: ``` rho := conjxt(x)^T * conjy(y) z := z + alpha * conjx(x) ``` where `x`, `y`, and `z` are vectors of length _n_ stored with strides `incx`, `incy`, and `incz`, respectively, and `rho` is a scalar. This kernel is typically implemented as a `dotv` operation fused with an `axpyv` operation. --- #### axpyf kernel ```c void bli_?axpyf_ ( conj_t conja, conj_t conjx, dim_t m, dim_t b, ctype* restrict alpha, ctype* restrict a, inc_t inca, inc_t lda, ctype* restrict x, inc_t incx, ctype* restrict y, inc_t incy, cntx_t* restrict cntx ) ``` This kernel performs the following operation: ``` y := y + alpha * conja(a) * conjy(x) ``` where `a` is an _m x b_ matrix, `x` is a vector of length _b_, and `y` is a vector of length _m_. Vectors `x` and `y` are stored with strides `incx` and `incy`, respectively. Matrix `a` is stored with row stride `inca` and column stride `lda`, though `inca` is most often (in practice) unit. This kernel is typically implemented as a fused series of _b_ `axpyv` operations updating the same vector `y` (with the elements of `x` serving as the scalars and the columns of `a` serving as the vectors to be scaled). --- #### dotxf kernel ```c void bli_?dotxf_ ( conj_t conjat, conj_t conjx, dim_t m, dim_t b, ctype* restrict alpha, ctype* restrict a, inc_t inca, inc_t lda, ctype* restrict x, inc_t incx, ctype* restrict beta, ctype* restrict y, inc_t incy, cntx_t* restrict cntx ) ``` This kernel performs the following operation: ``` y := beta * y + alpha * conjat(a)^T conjx(x) ``` where `a` is an _m x b_ matrix, where `w` is a vector of length _m_, `y` is a vector of length _b_, and `alpha` is a scalar. Vectors `x` and `y` are stored with strides `incx` and `incy`, respectively. Matrix `a` is stored with row stride `inca` and column stride `lda`, though `inca` is most often (in practice) unit. This kernel is typically implemented as a series of _b_ `dotxv` operations with the same right-hand operand vector `x` (contracted with the rows of `a^T` and accumulating to the corresponding elements of vector `y`). --- #### dotxaxpyf kernel ```c void bli_?dotxaxpyf_ ( conj_t conjat, conj_t conja, conj_t conjw, conj_t conjx, dim_t m, dim_t b, ctype* restrict alpha, ctype* restrict a, inc_t inca, inc_t lda, ctype* restrict w, inc_t incw, ctype* restrict x, inc_t incx, ctype* restrict beta, ctype* restrict y, inc_t incy, ctype* restrict z, inc_t incz, cntx_t* restrict cntx ) ``` This kernel performs the following operation: ``` y := beta * y + alpha * conjat(a)^T conjw(w) z := z + alpha * conja(a) conjx(x) ``` where `a` is an _m x b_ matrix, `w` and `z` are vectors of length _m_, `x` and `y` are vectors of length _b_, and `alpha` and `beta` are scalars. Vectors `w`, `z`, `x` and `y` are stored with strides `incw`, `incz`, `incx`, and `incy`, respectively. Matrix `a` is stored with row stride `inca` and column stride `lda`, though `inca` is most often (in practice) unit. This kernel is typically implemented as a series of _b_ `dotxv` operations with the same right-hand operand vector `w` fused with a series of _b_ `axpyv` operations updating the same vector `z`. --- ### Level-1v kernels --- #### addv kernel ```c void bli_?addv_ ( conj_t conjx, dim_t n, ctype* restrict x, inc_t incx, ctype* restrict y, inc_t incy, cntx_t* restrict cntx ) ``` This kernel performs the following operation: ``` y := y + conjx(x) ``` where `x` and `y` are vectors of length _n_ stored with strides `incx` and `incy`, respectively. --- #### amaxv kernel ```c void bli_?amaxv_ ( dim_t n, ctype* restrict x, inc_t incx, dim_t* restrict index, cntx_t* restrict cntx ) ``` Given a vector of length _n_, this kernel returns the zero-based index `index` of the element of vector `x` that contains the largest absolute value (or, in the complex domain, the largest complex modulus). If `NaN` is encountered, it is treated as if it were a valid value that was smaller than any other value in the vector. If more than one element contains the same maximum value, the index of the latter element is returned via `index`. --- #### axpyv kernel ```c void bli_?axpyv_ ( conj_t conjx, dim_t n, ctype* restrict alpha, ctype* restrict x, inc_t incx, ctype* restrict y, inc_t incy, cntx_t* restrict cntx ) ``` This kernel performs the following operation: ``` y := y + alpha * conjx(x) ``` where `x` and `y` are vectors of length _n_ stored with strides `incx` and `incy`, respectively, and `alpha` is a scalar. --- #### axpbyv kernel ```c void bli_?axpbyv_ ( conj_t conjx, dim_t n, ctype* restrict alpha, ctype* restrict x, inc_t incx, ctype* restrict beta, ctype* restrict y, inc_t incy, cntx_t* restrict cntx ) ``` This kernel performs the following operation: ``` y := beta * y + alpha * conjx(x) ``` where `x` and `y` are vectors of length _n_ stored with strides `incx` and `incy`, respectively, and `alpha` and `beta` are scalars. --- #### copyv kernel ```c void bli_?copyv_ ( conj_t conjx, dim_t n, ctype* restrict x, inc_t incx, ctype* restrict y, inc_t incy, cntx_t* restrict cntx ) ``` This kernel performs the following operation: ``` y := conjx(x) ``` where `x` and `y` are vectors of length _n_ stored with strides `incx` and `incy`, respectively. --- #### dotv kernel ```c void bli_?dotv_ ( conj_t conjx, conj_t conjy, dim_t n, ctype* restrict x, inc_t incx, ctype* restrict y, inc_t incy, ctype* restrict rho, cntx_t* restrict cntx ) ``` This kernel performs the following operation: ``` rho := conjxt(x)^T * conjy(y) ``` where `x` and `y` are vectors of length _n_ stored with strides `incx` and `incy`, respectively, and `rho` is a scalar. --- #### dotxv kernel ```c void bli_?dotxv_ ( conj_t conjx, conj_t conjy, dim_t n, ctype* restrict alpha, ctype* restrict x, inc_t incx, ctype* restrict y, inc_t incy, ctype* restrict beta, ctype* restrict rho, cntx_t* restrict cntx ) ``` This kernel performs the following operation: ``` rho := beta * rho + alpha * conjxt(x)^T * conjy(y) ``` where `x` and `y` are vectors of length _n_ stored with strides `incx` and `incy`, respectively, and `alpha`, `beta`, and `rho` are scalars. --- #### invertv kernel ```c void bli_?invertv_ ( dim_t n, ctype* restrict x, inc_t incx, cntx_t* restrict cntx ) ``` This kernel inverts all elements of an _n_-length vector `x`. --- #### scalv kernel ```c void bli_?scalv_ ( conj_t conjalpha, dim_t n, ctype* restrict alpha, ctype* restrict x, inc_t incx, cntx_t* restrict cntx ) ``` This kernel performs the following operation: ``` x := conjalpha(alpha) * x ``` where `x` is a vector of length _n_ stored with stride `incx` and `alpha` is a scalar. --- #### scal2v kernel ```c void bli_?scal2v_ ( conj_t conjx, dim_t n, ctype* restrict alpha, ctype* restrict x, inc_t incx, ctype* restrict y, inc_t incy, cntx_t* restrict cntx ) ``` This kernel performs the following operation: ``` y := alpha * conjx(x) ``` where `x` and `y` are vectors of length _n_ stored with strides `incx` and `incy`, respectively, and `alpha` is a scalar. --- #### setv kernel ```c void bli_?setv_ ( conj_t conjalpha, dim_t n, ctype* restrict alpha, ctype* restrict x, inc_t incx, cntx_t* restrict cntx ) ``` This kernel performs the following operation: ``` x := conjalpha(alpha) ``` where `x` is a vector of length _n_ stored with stride `incx` and `alpha` is a scalar. Note that here, the `:=` operator represents a broadcast of `conjalpha(alpha)` to every element in `x`. --- #### subv kernel ```c void bli_?subv_ ( conj_t conjx, dim_t n, ctype* restrict x, inc_t incx, ctype* restrict y, inc_t incy, cntx_t* restrict cntx ) ``` This kernel performs the following operation: ``` y := y - conjx(x) ``` where `x` and `y` are vectors of length _n_. --- #### swapv kernel ```c void bli_?swapv_ ( dim_t n, ctype* restrict x, inc_t incx, ctype* restrict y, inc_t incy, cntx_t* restrict cntx ) ``` This kernel swaps corresponding elements of two _n_-length vectors `x` and `y` stored with strides `incx` and `incy`, respectively. --- #### xpbyv kernel ```c void bli_?xpbyv_ ( conj_t conjx, dim_t n, ctype* restrict x, inc_t incx, ctype* restrict beta, ctype* restrict y, inc_t incy, cntx_t* restrict cntx ) ``` This kernel performs the following operation: ``` y := beta * y + conjx(x) ``` where `x` and `y` are vectors of length _n_ stored with strides `incx` and `incy`, respectively, and `beta` is a scalar. blis-0.9.0/docs/MixedDatatypes.md000066400000000000000000000267211422157504600166660ustar00rootroot00000000000000## Contents * **[Contents](MixedDatatypes.md#contents)** * **[Introduction](MixedDatatypes.md#introduction)** * **[Categories of mixed datatypes](MixedDatatypes.md#categories-of-mixed-datatypes)** * **[Computation precision](MixedDatatypes.md#computation-precision)** * **[Computation domain](MixedDatatypes.md#computation-domain)** * **[Performing gemm with mixed datatypes](MixedDatatypes.md#performing-gemm-with-mixed-datatypes)** * **[Running the testsuite for gemm with mixed datatypes](MixedDatatypes.md#running-the-testsuite-for-gemm-with-mixed-datatypes)** * **[Known issues](MixedDatatypes.md#known-issues)** * **[Conclusion](MixedDatatypes.md#conclusion)** ## Introduction This document serves as a guide to users interested in taking advantage of BLIS's support for performing the `gemm` operation on operands of differing datatypes (domain and/or precision). For further details on the implementation present in BLIS, please see the latest draft of our paper "Supporting Mixed-domain Mixed-precision Matrix Multiplication within the BLIS Framework" available in the [Citations section](https://github.com/flame/blis/#citations) of the main [BLIS webpage](https://github.com/flame/blis). ## Categories of mixed datatypes Before going any further, we find it useful to categorize mixed datatype support into four categories: 1. **Fully identical datatypes.** This is what people generally think of when they think about the `gemm` operation: all operands are stored in the same datatype (precision and domain), and the matrix product computation is performed in the arithmetic represented by that datatype. (This category doesn't actually involve mixing datatypes, but it's still worthwhile to define.) Example: matrix C updated by the product of matrix A and matrix B (all matrices double-precision real). 2. **Mixed domain with identical precisions.** This category includes all combinations of datatypes where the domain (real or complex) of each operand may vary while the precisions (single or double precision) are held constant across all operands. Example: complex matrix C updated by the product of real matrix A and complex matrix B (all matrices single-precision). 3. **Mixed precision within a single domain.** Here, all operands are stored in the same domain (real or complex), however, the precision of each operand may vary. Example: double-precision real matrix C updated by the product of single-precision real matrix A and single-precision real matrix B. 4. **Mixed precision and mixed domain.** This category allows both domains and precision of each matrix operand to vary. Example: double-precision complex matrix C updated by the product of single-precision complex matrix A and single-precision real matrix B. BLIS's implementation of mixed-datatype `gemm` supports all combinations within all four categories. ### Computation precision Because categories 3 and 4 involve mixing precisions, they come with an added parameter: the *computation precision*. This parameter specifies the precision in which the matrix multiplication (product) takes place. This precision can be different than the storage precision of matrices A or B, and/or the storage precision of matrix C. When the computation precision differs from the storage precision of matrix A, it implies that a typecast must occur when BLIS packs matrix A to contiguous storage. Similarly, B may also need to be typecast during packing. When the computation precision differs from the storage precision of C, it means the result of the matrix product A*B must be typecast just before it is accumulated back into matrix C. ### Computation domain In addition to the computation precision, we also track a computation domain. (Together, they form the computation datatype.) However, for now we do not allow the user to explicitly specify the computation domain. Instead, the computation domain is implied by the domains of A, B, and C. The following table enumerates the six cases where there is at least one operand of each domain, along with the corresponding same-domain cases from category 1 for reference. We also list the total number of floating-point operations performed in each case. In the table, an 'R' denotes a real domain matrix operand while a 'C' denotes a matrix in the complex domain. The R's and C's appear in the following format of C += A * B, where A, B, and C are the matrix operands of `gemm`. | Case # | Mixed domain case | Implied computation domain | flops performed | |--------|:-----------------:|:--------------------------:|:---------------:| | 1 | R += R * R | real | 2mnk | | 2 | R += R * C | real | 2mnk | | 3 | R += C * R | real | 2mnk | | 4 | R += C * C | complex | 4mnk | | 5 | C += R * R | real | 2mnk | | 6 | C += R * C | complex | 4mnk | | 7 | C += C * R | complex | 4mnk | | 8 | C += C * C | complex | 8mnk | The computation domain is implied in cases 1 and 8 in the same way that it would be if mixed datatype support were absent entirely. These cases execute 2mnk and 8mnk flops, respectively, as any traditional implementation would. In cases 2 and 3, we assume the computation domain is real because only B or A, respectively, is complex. Thus, in these cases, the imaginary components of the complex matrix are ignored, allowing us to perform only 2mnk flops. In case 5, we take the computation domain to be real because A and B are both real, and thus it makes no sense to compute in the complex domain. This means that we need only update the real components of C, leaving the imaginary components untouched. This also results in 2mnk flops being performed. In case 4, we have complex A and B, allowing us to compute a complex product. However, we can only save the real part of that complex product since the output matrix C is real. Since we cannot update the imaginary component of C (since it is not stored), we avoid computing that half of the update entirely, reducing the flops performed to 4mnk. (Alternatively, one may wish to request real domain computation, in which case the imaginary components of A and B were ignored *prior* to computing the matrix product. This approach would result in only 2mnk flops being performed.) In case 6, we wish for both the real and imaginary parts of B to participate in the multiplication by A, with the result updating the corresponding real and imaginary parts of C. Granted, the imaginary part of A is zero, and this is taken advantage of in the computation to optimize performance, as indicated by the 4mnk flop count. But fundamentally this computation executes in the complex domain because both the real and imaginary parts of C are updated. A similar story can be told about case 7. ## Performing gemm with mixed datatypes In BLIS, performing a mixed-datatype `gemm` operation is easy. However, it will require that the user call `gemm` through BLIS's object API. For a basic series of examples for using the object-based API, please see the example codes in the `examples/oapi` directory of the BLIS source distribution. The first step is to ensure that BLIS is configured with mixed datatype support. Please consult with your current distribution's `configure` script for the current semantics: ``` $ ./configure --help ``` As of this writing, mixed datatype support is enabled by default, and thus no additional options are needed. With mixed datatype support enabled in BLIS, using the functionality is simply a matter of creating and initializing matrices of different precisions and/or domains. ```c dim_t m = 5, n = 4, k = 2; obj_t a, b, c; obj_t* alpha; obj_t* beta; bli_obj_create( BLIS_DOUBLE, m, k, 0, 0, &a ); bli_obj_create( BLIS_FLOAT, k, n, 0, 0, &b ); bli_obj_create( BLIS_SCOMPLEX, m, n, 0, 0, &c ); alpha = &BLIS_ONE; beta = &BLIS_ONE; bli_randm( &a ); bli_randm( &b ); bli_randm( &c ); ``` Then, you specify the computation precision by setting the computation precision property of matrix C. ```c bli_obj_set_comp_prec( BLIS_DOUBLE_PREC, &c ); ``` If you do not explicitly specify the computation precision, it will default to the *storage* precision of C. With the objects created and the computation precision specified, call `bli_gemm()` just as you would if the datatypes were identical: ```c bli_gemm( alpha, &a, &b, beta, &c ); ``` For more examples of using BLIS's object-based API, including methods of initializing an matrix object with arbitrary values, please review the example code found in the `examples/oapi` directory of the BLIS source distribution. ## Running the testsuite for gemm with mixed datatypes The BLIS testsuite has been retrofitted to test all combinations of datatypes for each matrix operand. For more information on enabling mixed-datatype tests for the `gemm` operation, please see the explanations of the relevant options in the [Testsuite](Testsuite.md) documentation. ## Known issues There may be odd behavior in the current implementation of mixed-datatype `gemm` that does not conform to the reader's expectations. Below is a list of issues that BLIS developers are aware of. If any of these issues poses a problem for your application, please contact us by [opening an issue](https://github.com/flame/blis/issues). * **alpha with non-zero imaginary components.** Currently, there are many cases of mixed-datatype `gemm` that do not yet support computing with `alpha` scalars that have non-zero imaginary components--in other words, values of `alpha` that are not in the real domain. (By contrast, non-real values for `beta` are fully supported.) In order to support these use cases, additional code complexity and logic would be required. Thus, we have chosen, for now, to not implement them. If mixed-datatype `gemm` is invoked with a non-real valued `alpha` scalar, a runtime error message will be printed and the linked program will abort. * **Manually specifying the computation domain.** As mentioned in the section discussing the [computation domain](MixedDatatype.md#computation-domain), the computation domain of any case of mixed domain `gemm` is implied by the operands and thus fixed; the user may not specify a different computation domain, even if the mixed-domain case would reasonably allow for computing in either domain. * **Sandboxes should be used with caution.** When building a `gemm` sandbox in BLIS, please consider either (a) disabling mixed datatype support, or (b) consciously **never** running the testsuite with mixed domain or precision computation enabled. Even the reference `ref99` sandbox implementation in BLIS does not support mixing datatypes. If you do choose to enable a sandbox while also keeping mixed datatype support enabled in BLIS, make sure that the mixing of datatypes is disabled in the testsuite's `input.general` file (unless, of course, you decide to implement all mixed datatype cases within your sandbox). This issue is also discussed in the documentation for [Sandboxes](Sandboxes.md#known-issues). ## Conclusion For more information and documentation on BLIS, please visit the [BLIS github page](https://github.com/flame/blis/). If you found a bug or wish to request a feature, please [open an issue](https://github.com/flame/blis/issues). For general discussion or questions, please join and post a message to the [blis-devel mailing list](http://groups.google.com/group/blis-devel). Thanks for your interest in BLIS! blis-0.9.0/docs/Multithreading.md000066400000000000000000000707661422157504600167310ustar00rootroot00000000000000# Contents * **[Contents](Multithreading.md#contents)** * **[Introduction](Multithreading.md#introduction)** * **[Enabling multithreading](Multithreading.md#enabling-multithreading)** * [Choosing OpenMP vs pthreads](Multithreading.md#choosing-openmp-vs-pthreads) * [Specifying thread-to-core affinity](Multithreading.md#specifying-thread-to-core-affinity) * **[Specifying multithreading](Multithreading.md#specifying-multithreading)** * [Globally via environment variables](Multithreading.md#globally-via-environment-variables) * [The automatic way](Multithreading.md#environment-variables-the-automatic-way) * [The manual way](Multithreading.md#environment-variables-the-manual-way) * [Globally at runtime](Multithreading.md#globally-at-runtime) * [The automatic way](Multithreading.md#globally-at-runtime-the-automatic-way) * [The manual way](Multithreading.md#globally-at-runtime-the-manual-way) * [Locally at runtime](Multithreading.md#locally-at-runtime) * [Initializing a rntm_t](Multithreading.md#initializing-a-rntm-t) * [The automatic way](Multithreading.md#locally-at-runtime-the-automatic-way) * [The manual way](Multithreading.md#locally-at-runtime-the-manual-way) * [Using the expert interface](Multithreading.md#locally-at-runtime-using-the-expert-interface) * **[Known issues](Multithreading.md#known-issues)** * **[Conclusion](Multithreading.md#conclusion)** # Introduction Our paper [Anatomy of High-Performance Many-Threaded Matrix Multiplication](https://github.com/flame/blis#citations), presented at IPDPS'14, identified five loops around the microkernel as opportunities for parallelization within level-3 operations such as `gemm`. Within BLIS, we have enabled parallelism for four of those loops, with the fifth planned for future work. This software architecture extends naturally to all level-3 operations except for `trsm`, where its application is necessarily limited to three of the five loops due to inter-iteration dependencies. **IMPORTANT**: Multithreading in BLIS is disabled by default. Furthermore, even when multithreading is enabled, BLIS will default to single-threaded execution at runtime. In order to both *allow* and *invoke* parallelism from within BLIS operations, you must both *enable* multithreading at configure-time and *specify* multithreading at runtime. To summarize: In order to observe multithreaded parallelism within a BLIS operation, you must do *both* of the following: 1. Enable multithreading at configure-time. This is discussed in the [next section](docs/Multithreading.md#enabling-multithreading). 2. Specify multithreading at runtime. This is also discussed [later on](docs/Multithreading.md#specifying-multithreading). # Enabling multithreading BLIS disables multithreading by default. In order to allow multithreaded parallelism from BLIS, you must first enable multithreading explicitly at configure-time. As of this writing, BLIS optionally supports multithreading via either OpenMP or POSIX threads. To enable multithreading via OpenMP, you must provide the `--enable-threading` option to the `configure` script: ``` $ ./configure --enable-threading=openmp auto ``` In this example, we target the `auto` configuration, which is like asking `configure` to choose the most appropriate configuration based on some detection heuristic (e.g. `cpuid` on x86_64). Similarly, to enable multithreading via POSIX threads (pthreads), specify the threading model as `pthreads` instead of `openmp`: ``` $ ./configure --enable-threading=pthreads auto ``` You can also use the shorthand option for `--enable-threading`, which is `-t`: ``` $ ./configure -t pthreads auto ``` For more complete and up-to-date information on the `--enable-threading` option, simply run `configure` with the `--help` (or `-h`) option: ``` $ ./configure --help ``` ## Choosing OpenMP vs pthreads While we provide the ability to implement multithreading in BLIS in terms of either OpenMP or pthreads, we typically encourage users to opt for OpenMP: ``` $ ./configure -t openmp auto ``` The reason mostly comes down to the fact that most OpenMP implementations (most notably GNU) allow the user to conveniently bind threads to cores via an environment variable(s) set prior to running the application. This is important because when the operating system causes a thread to migrate from one core to another, the thread will typically leave behind the data it was using in the L1 and L2 caches. That data may not be present in the caches of the destination core. Once the thread resumes execution from the new core, it will experience a period of frequent cache misses as the data it was previously using is transmitted once again through the cache hierarchy. If migration happens frequently enough, it can pose a significant (and unnecessary) drag on performance. Note that binding threads to cores is possible in pthreads, but it requires a runtime call to the operating system, such as `sched_setaffinity()`, to convey the thread binding information, and BLIS does not yet implement this behavior for pthreads. ## Specifying thread-to-core affinity The solution to thread migration is setting *processor affinity*. In this context, affinity refers to the tendency for a thread to remain bound to a particular compute core. There are at least two ways to set affinity in OpenMP. The first way offers more control, but requires you to understand a bit about the processor topology and how core IDs are mapped to physical cores, while the second way is simpler but less powerful. Let's start with an example. Suppose I have a two-socket system with a total of eight cores, four cores per socket. By setting `GOMP_CPU_AFFINITY` as follows ``` $ export GOMP_CPU_AFFINITY="0 1 2 3 4 5 6 7" ``` I am communicating to OpenMP that the first thread to be created should be spawned on core 0, from which it should not migrate. The second thread to be created should be spawned on core 1, from which it should not migrate, and so forth. If socket 0 has cores 0-3 and socket 1 has 4-7, this would result in the first four threads on socket 0 and the second four threads on socket 1. (And if more than eight threads are spawned, the mapping wraps back around, staring from the beginning.) So with `GOMP_CPU_AFFINITY`, you are doing more than just preventing threads from migrating once they are spawned--you are specifying the cores on which they will be spawned in the first place. Another example: Suppose the hardware numbers the cores alternatingly between sockets, such that socket 0 gets even-numbered cores and socket 1 gets odd-numbered cores. In such a scenario, you might want to use `GOMP_CPU_AFFINITY` as follows ``` $ export GOMP_CPU_AFFINITY="0 2 4 6 1 3 5 7" ``` Because the first four entries are `0 2 4 6`, threads 0-3 would be spawned on the first socket, since that is where cores 0, 2, 4, and 6 are located. Similarly, the subsequent `1 3 5 7` would cause threads 4-7 to be spawned on the second socket, since that is where cores 1, 3, 5, and 7 reside. Of course, setting `GOMP_CPU_AFFINITY` in this way implies that BLIS benefits from this kind of grouping of threads--which, generally, it does. As a general rule, you should try to fill up a socket with one thread per core before moving to the next socket. A second method of specifying affinity is via `OMP_PROC_BIND`, which is much simpler to set: ``` $ export OMP_PROC_BIND=close ``` This binds the threads close to the master thread, in contiguous "place" partitions. (There are other valid values aside from `close`.) Places are specified by another variable, `OMP_PLACES`: ``` $ export OMP_PLACES=cores ``` The `cores` value is most appropriate for BLIS since we usually want to ignore hardware threads (symmetric multithreading, or "hyperthreading" on Intel systems) and instead map threads to physical cores. Setting these two variables is often enough. However, it obviously does not offer the level of control that `GOMP_CPU_AFFINITY` does. Sometimes, it takes some experimentation to determine whether a particular mapping is performing as expected. If multithreaded performance on eight cores is only twice what it is observed of single-threaded performance, the affinity mapping may be to blame. But if performance is six or seven times higher than sequential execution, then the mapping you chose is probably working fine. Unfortunately, the topic of thread-to-core affinity is well beyond the scope of this document. (A web search will uncover many [great resources](http://www.nersc.gov/users/software/programming-models/openmp/process-and-thread-affinity/) discussing the use of [GOMP_CPU_AFFINITY](https://gcc.gnu.org/onlinedocs/libgomp/GOMP_005fCPU_005fAFFINITY.html) and [OMP_PROC_BIND](https://gcc.gnu.org/onlinedocs/libgomp/OMP_005fPROC_005fBIND.html#OMP_005fPROC_005fBIND).) It's up to the user to determine an appropriate affinity mapping, and then choose your preferred method of expressing that mapping to the OpenMP implementation. # Specifying multithreading There are three broad methods of specifying multithreading in BLIS: * [Globally via environment variables](Multithreading.md#globally-via-environment-variables) * [Globally at runtime](Multithreading.md#globally-at-runtime) * [Locally at runtime](Multithreading.md#locally-at-runtime) (that is, on a per-call, thread-safe basis) Within these three broad methods there are two specific ways of expressing a request for parallelism. First, the user may express a single number--the total number of threads, or ways of parallelism, to use within a single operation such as `gemm`. We call this the "automatic" way. Alternatively, the user may express the number of ways of parallelism to obtain within *each loop* of the level-3 operation. We call this the "manual" way. The latter way is actually what BLIS eventually needs before it can perform its multithreading; the former is viable only because we have a heuristic of determining a reasonable instance of the latter when given the former. This pattern--automatic or manual--holds regardless of which of the three methods is used. Regardless of which method is employed, and which specific way within each method, after setting the number of threads, the application may call the desired level-3 operation (via either the [typed API](docs/BLISTypedAPI.md) or the [object API](docs/BLISObjectAPI.md)) and the operation will execute in a multithreaded manner. (When calling BLIS via the BLAS API, only the first two (global) methods are available.) **Note**: Please be aware of what happens if you try to specify both the automatic and manual ways, as it could otherwise confuse new users. Here are the important points: * Regardless of which broad method is used, **if multithreading is specified via both the automatic and manual ways, the values set via the manual way will always take precedence.** * Specifying parallelism for even *one* loop counts as specifying the manual way (in which case the ways of parallelism for the remaining loops will be assumed to be 1). And in the case of the environment variable method, setting the ways of parallelism for a loop to 1 counts as specifying parallelism! If you want to switch from using the manual way to automatic way, you must not only set (`export`) the `BLIS_NUM_THREADS` variable, but you must also `unset` all of the `BLIS_*_NT` variables. * If you have specified multithreading via *both* the automatic and manual ways, BLIS will **not** complain if the values are inconsistent with one another. (For example, you may request 12 total threads be used while also specifying 2 and 4 ways of parallelism within the JC and IC loops, respectively, for a total of 8 ways.) Furthermore, you will be able to query these inconsistent values via the runtime API both before and after multithreading executes. * If multithreading is disabled, you **may still** specify multithreading values via either the manual or automatic ways. However, BLIS will silently ignore **all** of these values. A BLIS library that is built with multithreading disabled at configure-time will always run sequentially (from the perspective of a single application thread). Furthermore: * For small numbers of threads, the number requested will be honored faithfully. However, if you request a larger number of threads that happens to also be prime, BLIS will reduce the number by one in order to allow more more efficient thread factorizations. This behavior can be overridden by configuring BLIS with the `BLIS_ENABLE_AUTO_PRIME_NUM_THREADS` macro defined in the `bli_family_*.h` file of the relevant subconfiguration. Similarly, the threshold beyond which BLIS will reduce primes by one can be set via `BLIS_NT_MAX_PRIME`. (This latter value is ignored if the former macro is defined.) ## Globally via environment variables The most common method of specifying multithreading in BLIS is globally via environment variables. With this method, the user sets one or more environment variables in the shell before launching the BLIS-linked executable. Regardless of whether you end up using the automatic or manual way of expressing a request for multithreading, note that the environment variables are read (via `getenv()`) by BLIS **only once**, when the library is initialized. Subsequent to library initialization, the global settings for parallelization may only be changed via the [global runtime API](Multithreading.md#globally-at-runtime). If this constraint is not a problem, then environment variables may work fine for you. Otherwise, please consider [local settings](Multithreading.md#locally-at-runtime). (Local settings may used at any time, regardless of whether global settings were explicitly specified, and local settings always override global settings.) **Note**: Regardless of which way ([automatic](Multithreading.md#environment-variables-the-automatic-way) or [manual](Multithreading.md#environment-variables-the-manual-way)) environment variables are used to specify multithreading, that specification will affect operation of BLIS through **both** the BLAS compatibility layer as well as the native ([typed](docs/BLISTypedAPI.md) and [object](docs/BLISObjectAPI.md)) APIs that are unique to BLIS. ### Environment variables: the automatic way The automatic way of specifying parallelism entails simply setting the total number of threads you wish BLIS to employ in its parallelization. This total number of threads is captured by the `BLIS_NUM_THREADS` environment variable. You can set this variable prior to executing your BLIS-linked executable: ``` $ export GOMP_CPU_AFFINITY="..." # optional step when using GNU libgomp. $ export BLIS_NUM_THREADS=16 $ ./my_blis_program ``` This causes BLIS to automatically determine a reasonable threading strategy based on what is known about the operation and problem size. If `BLIS_NUM_THREADS` is not set, BLIS will attempt to query the value of `OMP_NUM_THREADS`. If neither variable is set, the default number of threads is 1. **Note**: We *highly* discourage use of the `OMP_NUM_THREADS` environment variable and may remove support for it in the future. If you wish to set parallelism globally via environment variables, please use `BLIS_NUM_THREADS`. ### Environment variables: the manual way The manual way of specifying parallelism involves communicating which loops within the matrix multiplication algorithm to parallelize and the degree of parallelism to be obtained from each of those loops. The below chart describes the five loops used in BLIS's matrix multiplication operations. | Loop around microkernel | Environment variable | Direction | Notes | |:-------------------------|:---------------------|:----------|:---------------| | 5th loop | `BLIS_JC_NT` | `n` | | | 4th loop | _N/A_ | `k` | Not enabled | | 3rd loop | `BLIS_IC_NT` | `m` | | | 2nd loop | `BLIS_JR_NT` | `n` | Typically <= 4 | | 1st loop | `BLIS_IR_NT` | `m` | Typically 1 | **Note**: Parallelization of the 4th loop is not currently enabled because each iteration of the loop updates the same part of the output matrix C. Thus, to safely parallelize it requires either a reduction or mutex locks when updating C. Parallelization in BLIS is hierarchical. So if we parallelize multiple loops, the total number of threads will be the product of the amount of parallelism for each loop. Thus the total number of threads used is the product of all the values: `BLIS_JC_NT * BLIS_IC_NT * BLIS_JR_NT * BLIS_IR_NT`. Note that if you set at least one of these loop-specific variables, any others that are unset will default to 1. In general, the way to choose how to set these environment variables is as follows: The amount of parallelism from the M and N dimensions should be roughly the same. Thus `BLIS_IR_NT * BLIS_IC_NT` should be roughly equal to `BLIS_JR_NT * BLIS_JC_NT`. Next, which combinations of loops to parallelize depends on which caches are shared. Here are some of the more common scenarios: * When compute resources have private L3 caches (example: multi-socket systems), try parallelizing the `JC` loop. This means threads (or thread groups) will pack and compute with different row panels from matrix B. * For compute resources that have private L2 caches but that share an L3 cache (example: cores on a socket), try parallelizing the `IC` loop. In this situation, threads will share the same packed row panel from matrix B, but pack and compute with different blocks of matrix A. * If compute resources share an L2 cache but have private L1 caches (example: pairs of cores), try parallelizing the `JR` loop. Here, threads share the same packed block of matrix A but read different packed micropanels of B into their private L1 caches. In some situations, *lightly* parallelizing the `IR` loop may also be effective. ![The primary algorithm for level-3 operations in BLIS](http://www.cs.utexas.edu/users/field/mm_algorithm_color.png) ## Globally at runtime If you still wish to set the parallelization scheme globally, but you want to do so at runtime, BLIS provides a thread-safe API for specifying multithreading. Think of these functions as a way to modify the same internal data structure into which the environment variables are read. (Recall that the environment variables are only read once, when BLIS is initialized). **Note**: Regardless of which way ([automatic](Multithreading.md#globally-at-runtime-the-automatic-way) or [manual](Multithreading.md#globally-at-runtime-the-manual-way)) the global runtime API is used to specify multithreading, that specification will affect operation of BLIS through **both** the BLAS compatibility layer as well as the native ([typed](docs/BLISTypedAPI.md) and [object](docs/BLISObjectAPI.md)) APIs that are unique to BLIS. ### Globally at runtime: the automatic way If you simply want to specify an overall number of threads and let BLIS choose a thread factorization automatically, use the following function: ```c void bli_thread_set_num_threads( dim_t n_threads ); ``` This function takes one integer--the total number of threads for BLIS to utilize in any one operation. So, for example, if we call ```c bli_thread_set_num_threads( 4 ); ``` we are requesting that the global number of threads be set to 4. You may also query the global number of threads at any time via ```c dim_t bli_thread_get_num_threads( void ); ``` Which may be called in the usual way: ```c dim_t nt = bli_thread_get_num_threads(); ``` ### Globally at runtime: the manual way If you want to specify the number of ways of parallelism to obtain for each loop, use the following function: ```c void bli_thread_set_ways( dim_t jc, dim_t pc, dim_t ic, dim_t jr, dim_t ir ); ``` This function takes one integer for each loop in the level-3 operations. (**Note**: even though the function takes a `pc` argument, it will be ignored until parallelism is supported in the `KC` loop.) So, for example, if we call ```c bli_thread_set_ways( 2, 1, 4, 1, 1 ); ``` we are requesting two ways of parallelism in the `JC` loop and 4 ways of parallelism in the `IC` loop. Unlike environment variables, which only allow the user to set the parallelization strategy prior to running the executable, `bli_thread_set_ways()` may be called any time during the normal course of the BLIS-linked application's execution. ## Locally at runtime In addition to the global methods based on environment variables and runtime function calls, BLIS also offers a local, *per-call* method of requesting parallelism at runtime. This method has the benefit of being thread-safe and flexible; your application can spawn two threads at the application level, with each thread requesting different degrees of parallelism from their respective calls to level-3 BLIS operations. As with environment variables and the global runtime API, there are two ways to specify parallelism: the automatic way and the manual way. Both ways involve allocating a BLIS-specific object, initializing the object and encoding the desired parallelization, and then passing a pointer to the object into one of the expert interfaces of either the [typed](docs/BLISTypedAPI.md) or [object](docs/BLISObjectAPI) APIs. We provide examples of utilizing this threading object below. **Note**: Neither way ([automatic](Multithreading.md#locally-at-runtime-the-automatic-way) nor [manual](Multithreading.md#locally-at-runtime-the-manual-way)) of specifying multithreading via the local runtime API can be used via the BLAS interfaces. The local runtime API may *only* be used via the native ([typed](docs/BLISTypedAPI.md) and [object](docs/BLISObjectAPI.md)) APIs, which are unique to BLIS. (Furthermore, the expert interfaces of each API must be used. This is demonstrated later on in this section.) ### Initializing a rntm_t Before specifying the parallelism (automatically or manually), you must first allocate a special BLIS object called a `rntm_t` (runtime). The object is quite small (about 64 bytes), and so we recommend allocating it statically on the function stack: ```c rntm_t rntm; ``` We **strongly recommend** initializing the `rntm_t`. This can be done in either of two ways. If you want to initialize it as part of the declaration, you may do so via the default `BLIS_RNTM_INITIALIZER` macro: ```c rntm_t rntm = BLIS_RNTM_INITIALIZER; ``` Alternatively, you can perform the same initialization by passing the address of the `rntm_t` to an initialization function: ```c bli_rntm_init( &rntm ); ``` As of this writing, BLIS treats a default-initialized `rntm_t` as a request for single-threaded execution. **Note**: If you choose to **not** initialize the `rntm_t` object, you **must** set its parallelism via either the automatic way or the manual way, described below. Passing a completely uninitialized `rntm_t` to a level-3 operation **will almost surely result in undefined behavior!** ### Locally at runtime: the automatic way Once your `rntm_t` is initialized, you may request automatic parallelization by encoding only the total number of threads into the `rntm_t` via the following function: ```c void bli_rntm_set_num_threads( dim_t n_threads, rntm_t* rntm ); ``` As with `bli_thread_set_num_threads()` [discussed previously](Multithreading.md#globally-at-runtime-the-automatic-way), this function takes a single integer. It also takes the address of the `rntm_t` to modify. So, for example, if (after declaring and initializing a `rntm_t` as discussed above) we call ```c bli_rntm_set_num_threads( 6, &rntm ); ``` the `rntm_t` object will be encoded to use a total of 6 threads. ### Locally at runtime: the manual way Once your `rntm_t` is initialized, you may manually encode the ways of parallelism for each loop into the `rntm_t` by using the following function: ```c void bli_rntm_set_ways( dim_t jc, dim_t pc, dim_t ic, dim_t jr, dim_t ir, rntm_t* rntm ); ``` As with `bli_thread_set_ways()` [discussed previously](Multithreading.md#globally-at-runtime-the-manual-way), this function takes one integer for each loop in the level-3 operations. It also takes the address of the `rntm_t` to modify. (**Note**: even though the function takes a `pc` argument, it will be ignored until parallelism is supported in the `KC` loop.) So, for example, if we call ```c bli_rntm_set_ways( 1, 1, 2, 3, 1, &rntm ); ``` we are requesting two ways of parallelism in the `IC` loop and three ways of parallelism in the `JR` loop. ### Locally at runtime: using the expert interfaces Regardless of whether you specified parallelism into your `rntm_t` object via the automatic or manual method, eventually you must use the data structure when calling a BLIS operation. Let's assume you wish to call `gemm`. To so do, simply use the expert interface, which takes two additional arguments: a `cntx_t` (context) and a `rntm_t`. For the context, you may simply pass in `NULL` and BLIS will select a default context (which is exactly what happens when you call the basic/non-expert interfaces). Here is an example of such a call: ```c bli_gemm_ex( &alpha, &a, &b, &beta, &c, NULL, &rntm ); ``` This will cause `gemm` to execute and parallelize in the manner encoded by `rntm`. To summarize, using a `rntm_t` involves three steps: ```c // Declare and initialize a rntm_t object. rntm_t rntm = BLIS_RNTM_INITIALIZER; // Call ONE (not both) of the following to encode your parallelization into // the rntm_t. (These are examples only--use numbers that make sense for your // application!) bli_rntm_set_num_threads( 6, &rntm ); bli_rntm_set_ways( 1, 1, 2, 3, 1, &rntm ); // Finally, call BLIS via an expert interface and pass in your rntm_t. bli_gemm_ex( &alpha, &a, &b, &beta, &c, NULL, &rntm ); ``` Note that `rntm_t` objects may be reused over and over again once they are initialized; there is no need to reinitialize them and re-encode their threading values! Also, you may pass in `NULL` for the `rntm_t*` parameter of an expert interface. This causes the current global settings to be used. # Known issues * **Internal transposition and manual parallelism.** BLIS supports both row- and column-stored matrices (and tensor-like general storage). However, typically the `gemm` microkernel prefers to read and write microtiles of matrix C by rows, or by columns. If the storage of the user-provided matrix C does not match that of the microkernel preference, BLIS logically transpose the entire operation so that by the time the microkernel sees matrix C, it will appear to be stored according to its storage preference. If the caller is employing the automatic style of parallelism, whereby only the total number of threads is specified, this transposition happens *before* the the total number of threads is factored into the various loop-specific ways of parallelism and everything works as expected. However, if the caller employs the manual style of parallelism, the transposition must (by definition) happen *after* the thread factorization is done since, in this situation, the caller has taken responsibility for providing that factorization explicitly. This situation could lead to unexpectedly low multithreaded performance. Suppose the user calls `gemm` on a problem with a large m dimension and small k and n dimensions, and explicitly requests parallelism only in the IC loop, but also suppose that the storage of C does not match that of the microkernel's preference. After BLIS transposes the operation internally, the *effective* m dimension will no longer be large; instead, it will be small (because the original m and n dimension will have been swapped). The multithreaded implementation will then proceed to parallelize this small m dimension. There are currently no good *and* easy solutions to this problem. Eventually, though, we plan to add support for two microkernels per datatype per configuration--one for use with matrices C that are row-stored, and one for those that are column-stored. This will obviate the logic within BLIS that sometimes induces the operation transposition, and the problem will go away. * **Thread affinity when BLIS and MKL are used together.** Some users have reported that when running a program that links both BLIS (configured with OpenMP) and MKL, **and** when OpenMP thread affinity has been specified (e.g. via `OMP_PROC_BIND` and `OMP_PLACES`), that very poor performance is observed. This may be due to incorrect thread masking in this case, causing all threads to run on one physical core. The exact circumstances leading to this behavior have not been identified, but unsetting the OpenMP thread affinity variables appears to be a solution. # Conclusion Please send us feedback if you have any concerns or questions, or [open an issue](http://github.com/flame/blis/issues) if you observe any reproducible behavior that you think is erroneous. (You are welcome to use the issue feature to start any non-trivial dialogue; we don't restrict them only to bug reports!) Thanks for your interest in BLIS. blis-0.9.0/docs/Performance.md000066400000000000000000001114001422157504600161670ustar00rootroot00000000000000# Contents * **[Contents](Performance.md#contents)** * **[Introduction](Performance.md#introduction)** * **[General information](Performance.md#general-information)** * **[Interpretation](Performance.md#interpretation)** * **[Reproduction](Performance.md#reproduction)** * **[Level-3 performance](Performance.md#level-3-performance)** * **[ThunderX2](Performance.md#thunderx2)** * **[Experiment details](Performance.md#thunderx2-experiment-details)** * **[Results](Performance.md#thunderx2-results)** * **[SkylakeX](Performance.md#skylakex)** * **[Experiment details](Performance.md#skylakex-experiment-details)** * **[Results](Performance.md#skylakex-results)** * **[Haswell](Performance.md#haswell)** * **[Experiment details](Performance.md#haswell-experiment-details)** * **[Results](Performance.md#haswell-results)** * **[Zen](Performance.md#zen)** * **[Experiment details](Performance.md#zen-experiment-details)** * **[Results](Performance.md#zen-results)** * **[Zen2](Performance.md#zen2)** * **[Experiment details](Performance.md#zen2-experiment-details)** * **[Results](Performance.md#zen2-results)** * **[A64fx](Performance.md#a64fx)** * **[Experiment details](Performance.md#a64fx-experiment-details)** * **[Results](Performance.md#a64fx-results)** * **[Neoverse N1](Performance.md#neoverse-n1)** * **[Experiment details](Performance.md#neoverse-n1-experiment-details)** * **[Results](Performance.md#neoverse-n1-results)** * **[Feedback](Performance.md#feedback)** # Introduction This document showcases performance results for a representative sample of level-3 operations on large matrices with BLIS and BLAS for several hardware architectures. # General information Generally speaking, for level-3 operations on large matrices, we publish three "panels" for each type of hardware, each of which reports one of: single-threaded performance, multithreaded performance on a single socket, or multithreaded performance on two sockets. Each panel will consist of a 4x5 grid of graphs, with each row representing a different datatype (single real, double real, single complex, and double complex) and each column representing a different operation (`gemm`, `hemm`/`symm`, `herk`/`syrk`, `trmm`, and `trsm`). Each of the 20 graphs within a panel will contain an x-axis that reports problem size, with all matrix dimensions equal to the problem size (e.g. _m_ = _n_ = _k_), resulting in square matrices. The y-axis will report in units GFLOPS (billions of floating-point operations per second) in the case of single-threaded performance, or GFLOPS/core in the case of single- or dual-socket multithreaded performance, where GFLOPS/core is simply the total GFLOPS observed divided by the number of threads utilized. This normalization is done intentionally in order to facilitate a visual assessment of the drop in efficiency of multithreaded performance relative to their single-threaded baselines. It's also worth pointing out that the top of each graph (e.g. the maximum y-axis value depicted) _always_ corresponds to the theoretical peak performance under the conditions associated with that graph. Theoretical peak performance, in units of GFLOPS/core, is calculated as the product of: 1. the maximum sustainable clock rate in GHz; and 2. the maximum number of floating-point operations (flops) that can be executed per cycle (per core). Note that the maximum sustainable clock rate may change depending on the conditions. For example, on some systems the maximum clock rate is higher when only one core is active (e.g. single-threaded performance) versus when all cores are active (e.g. multithreaded performance). The maximum number of flops executable per cycle (per core) is generally computed as the product of: 1. the maximum number of fused multiply-add (FMA) vector instructions that can be issued per cycle (per core); 2. the maximum number of elements that can be stored within a single vector register (for the datatype in question); and 3. 2.0, since an FMA instruction fuses two operations (a multiply and an add). The problem size range, represented on the x-axis, is usually sampled with 50 equally-spaced problem size. For example, for single-threaded execution, we might choose to execute with problem sizes of 48 to 2400 in increments of 48, or 56 to 2800 in increments of 56. These values are almost never chosen for any particular (read: sneaky) reason; rather, we start with a "good" maximum problem size, such as 2400 or 2800, and then divide it by 50 to obtain the appropriate starting point and increment. Finally, each point along each curve represents the best of three trials. # Interpretation In general, the the curves associated with higher-performing implementations will appear higher in the graphs than lower-performing implementations. Ideally, an implementation will climb in performance (as a function of problem size) as quickly as possible and asymptotically approach some high fraction of peak performance. Occasionally, we may publish graphs with incomplete curves--for example, only the first 25 data points in a typical 50-point series--usually because the implementation being tested was slow enough that it was not practical to allow it to finish. Where along the x-axis you focus your attention will depend on the segment of the problem size range that you care about most. Some people's applications depend heavily on smaller problems, where "small" can mean anything from 10 to 1000 or even higher. Some people consider 1000 to be quite large, while others insist that 5000 is merely "medium." What each of us considers to be small, medium, or large (naturally) depends heavily on the kinds of dense linear algebra problems we tend to encounter. No one is "right" or "wrong" about their characterization of matrix smallness or bigness since each person's relative frame of reference can vary greatly. That said, the [Science of High-Performance Computing](http://shpc.ices.utexas.edu/) group at [The University of Texas at Austin](https://www.utexas.edu/) tends to target matrices that it classifies as "medium-to-large", and so most of the graphs presented in this document will reflect that targeting in their x-axis range. When corresponding with us, via email or when opening an [issue](https://github.com/flame/blis/issues) on github, we kindly ask that you specify as closely as possible (though a range is fine) your problem size of interest so that we can better assist you. # Reproduction In general, we do not offer any step-by-step guide for how to reproduce the performance graphs shown below. That said, if you are keenly interested in running your own performance benchmarks, either in an attempt to reproduce the results shown here or to measure performance of different hardware, of different implementations (or versions), and/or for different problem sizes, you should begin by studying the source code, `Makefile`, and scripts in the [test/3](https://github.com/flame/blis/tree/master/test/3) directory of the BLIS source distribution. Then, you'll need to take time to build and/or install some (or all) of the implementations shown (e.g. [OpenBLAS](https://github.com/xianyi/OpenBLAS), [MKL](https://software.intel.com/en-us/mkl/), and [Eigen](http://eigen.tuxfamily.org), including BLIS. Be sure to consult the detailed notes provided below; they should be *very* helpful in successfully building the libraries. The `runme.sh` script in `test/3` will help you run some (or all) of the test drivers produced by the `Makefile`, and the Matlab/Octave function `plot_panel_4x5()` defined in the `matlab` directory will help you turn the output of those test drivers into a PDF file of graphs. The `runthese.m` file will contain example invocations of the function. # Level-3 performance ## ThunderX2 ### ThunderX2 experiment details * Location: Unknown * Processor model: Marvell ThunderX2 CN9975 * Core topology: two sockets, 28 cores per socket, 56 cores total * SMT status: disabled at boot-time * Max clock rate: 2.2GHz (single-core and multicore) * Max vector register length: 128 bits (NEON) * Max FMA vector IPC: 2 * Peak performance: * single-core: 17.6 GFLOPS (double-precision), 35.2 GFLOPS (single-precision) * multicore: 17.6 GFLOPS/core (double-precision), 35.2 GFLOPS/core (single-precision) * Operating system: Ubuntu 16.04 (Linux kernel 4.15.0) * Page size: unknown * Compiler: gcc 7.3.0 * Results gathered: 14 February 2019 * Implementations tested: * BLIS 075143df (0.5.1-39) * configured with `./configure -t openmp thunderx2` (single- and multithreaded) * sub-configuration exercised: `thunderx2` * Single-threaded (1 core) execution requested via no change in environment variables * Multithreaded (28 core) execution requested via `export BLIS_JC_NT=4 BLIS_IC_NT=7` * Multithreaded (56 core) execution requested via `export BLIS_JC_NT=8 BLIS_IC_NT=7` * OpenBLAS 52d3f7a * configured `Makefile.rule` with `BINARY=64 NO_CBLAS=1 NO_LAPACK=1 NO_LAPACKE=1 USE_THREAD=0` (single-threaded) * configured `Makefile.rule` with `BINARY=64 NO_CBLAS=1 NO_LAPACK=1 NO_LAPACKE=1 USE_THREAD=1 NUM_THREADS=56` (multithreaded, 56 cores) * Single-threaded (1 core) execution requested via `export OPENBLAS_NUM_THREADS=1` * Multithreaded (28 core) execution requested via `export OPENBLAS_NUM_THREADS=28` * Multithreaded (56 core) execution requested via `export OPENBLAS_NUM_THREADS=56` * ARMPL 18.4 * Single-threaded (1 core) execution requested via `export OMP_NUM_THREADS=1` * Multithreaded (28 core) execution requested via `export OMP_NUM_THREADS=28` * Multithreaded (56 core) execution requested via `export OMP_NUM_THREADS=56` * Affinity: * Thread affinity for BLIS was specified manually via `GOMP_CPU_AFFINITY="0 1 2 3 ... 55"`. However, multithreaded OpenBLAS appears to revert to single-threaded execution if `GOMP_CPU_AFFINITY` is set. Therefore, when measuring OpenBLAS performance, the `GOMP_CPU_AFFINITY` environment variable was unset. * Frequency throttling (via `cpupower`): * No changes made. * Comments: * ARMPL performance is remarkably uneven across datatypes and operations, though it would appear their "base" consists of OpenBLAS, which they then optimize for select, targeted routines. Unfortunately, we were unable to test the absolute latest versions of OpenBLAS and ARMPL on this hardware before we lost access. We will rerun these experiments once we gain access to a similar system. ### ThunderX2 results #### pdf * [ThunderX2 single-threaded](graphs/large/l3_perf_tx2_nt1.pdf) * [ThunderX2 multithreaded (28 cores)](graphs/large/l3_perf_tx2_jc4ic7_nt28.pdf) * [ThunderX2 multithreaded (56 cores)](graphs/large/l3_perf_tx2_jc8ic7_nt56.pdf) #### png (inline) * **ThunderX2 single-threaded** ![single-threaded](graphs/large/l3_perf_tx2_nt1.png) * **ThunderX2 multithreaded (28 cores)** ![multithreaded (28 cores)](graphs/large/l3_perf_tx2_jc4ic7_nt28.png) * **ThunderX2 multithreaded (56 cores)** ![multithreaded (56 cores)](graphs/large/l3_perf_tx2_jc8ic7_nt56.png) --- ## SkylakeX ### SkylakeX experiment details * Location: Oracle cloud * Processor model: Intel Xeon Platinum 8167M (SkylakeX/AVX-512) * Core topology: two sockets, 26 cores per socket, 52 cores total * SMT status: enabled, but not utilized * Max clock rate: 2.0GHz (single-core and multicore) * Max vector register length: 512 bits (AVX-512) * Max FMA vector IPC: 2 * Peak performance: * single-core: 64 GFLOPS (double-precision), 128 GFLOPS (single-precision) * multicore: 64 GFLOPS/core (double-precision), 128 GFLOPS/core (single-precision) * Operating system: Ubuntu 18.04 (Linux kernel 4.15.0) * Page size: 4096 bytes * Compiler: gcc 7.3.0 * Results gathered: 6 March 2019, 27 March 2019 * Implementations tested: * BLIS 9f1dbe5 (0.5.1-54) * configured with `./configure -t openmp auto` (single- and multithreaded) * sub-configuration exercised: `skx` * Single-threaded (1 core) execution requested via no change in environment variables * Multithreaded (26 core) execution requested via `export BLIS_JC_NT=2 BLIS_IC_NT=13` * Multithreaded (52 core) execution requested via `export BLIS_JC_NT=4 BLIS_IC_NT=13` * OpenBLAS 0.3.5 * configured `Makefile.rule` with `BINARY=64 NO_CBLAS=1 NO_LAPACK=1 NO_LAPACKE=1 USE_THREAD=0` (single-threaded) * configured `Makefile.rule` with `BINARY=64 NO_CBLAS=1 NO_LAPACK=1 NO_LAPACKE=1 USE_THREAD=1 NUM_THREADS=52` (multithreaded, 52 cores) * Single-threaded (1 core) execution requested via `export OPENBLAS_NUM_THREADS=1` * Multithreaded (26 core) execution requested via `export OPENBLAS_NUM_THREADS=26` * Multithreaded (52 core) execution requested via `export OPENBLAS_NUM_THREADS=52` * Eigen 3.3.90 * Obtained via the [Eigen git mirror](https://github.com/eigenteam/eigen-git-mirror) (March 27, 2019) * Prior to compilation, modified top-level `CMakeLists.txt` to ensure that `-march=native` was added to `CXX_FLAGS` variable (h/t Sameer Agarwal): ``` # These lines added after line 67. check_cxx_compiler_flag("-march=native" COMPILER_SUPPORTS_MARCH_NATIVE) if(COMPILER_SUPPORTS_MARCH_NATIVE) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native") endif() ``` * configured and built BLAS library via `mkdir build; cd build; cmake ..; make blas` * installed headers via `cmake . -DCMAKE_INSTALL_PREFIX=$HOME/flame/eigen; make install` * The `gemm` implementation was pulled in at compile-time via Eigen headers; other operations were linked to Eigen's BLAS library. * Single-threaded (1 core) execution requested via `export OMP_NUM_THREADS=1` * Multithreaded (26 core) execution requested via `export OMP_NUM_THREADS=26` * Multithreaded (52 core) execution requested via `export OMP_NUM_THREADS=52` * **NOTE**: This version of Eigen does not provide multithreaded implementations of `symm`/`hemm`, `syrk`/`herk`, `trmm`, or `trsm`, and therefore those curves are omitted from the multithreaded graphs. * MKL 2019 update 1 * Single-threaded (1 core) execution requested via `export MKL_NUM_THREADS=1` * Multithreaded (26 core) execution requested via `export MKL_NUM_THREADS=26` * Multithreaded (52 core) execution requested via `export MKL_NUM_THREADS=52` * Affinity: * Thread affinity for BLIS was specified manually via `GOMP_CPU_AFFINITY="0 1 2 3 ... 51"`. However, multithreaded OpenBLAS appears to revert to single-threaded execution if `GOMP_CPU_AFFINITY` is set. Therefore, when measuring OpenBLAS performance, the `GOMP_CPU_AFFINITY` environment variable was unset. * Frequency throttling (via `cpupower`): * Driver: acpi-cpufreq * Governor: performance * Hardware limits: 1.0GHz - 2.0GHz * Adjusted minimum: 2.0GHz * Comments: * MKL yields superb performance for most operations, though BLIS is not far behind except for `trsm`. (We understand the `trsm` underperformance and hope to address it in the future.) OpenBLAS lags far behind MKL and BLIS due to lack of full support for AVX-512, and possibly other reasons related to software architecture and register/cache blocksizes. ### SkylakeX results #### pdf * [SkylakeX single-threaded](graphs/large/l3_perf_skx_nt1.pdf) * [SkylakeX multithreaded (26 cores)](graphs/large/l3_perf_skx_jc2ic13_nt26.pdf) * [SkylakeX multithreaded (52 cores)](graphs/large/l3_perf_skx_jc4ic13_nt52.pdf) #### png (inline) * **SkylakeX single-threaded** ![single-threaded](graphs/large/l3_perf_skx_nt1.png) * **SkylakeX multithreaded (26 cores)** ![multithreaded (26 cores)](graphs/large/l3_perf_skx_jc2ic13_nt26.png) * **SkylakeX multithreaded (52 cores)** ![multithreaded (52 cores)](graphs/large/l3_perf_skx_jc4ic13_nt52.png) --- ## Haswell ### Haswell experiment details * Location: TACC (Lonestar5) * Processor model: Intel Xeon E5-2690 v3 (Haswell) * Core topology: two sockets, 12 cores per socket, 24 cores total * SMT status: enabled, but not utilized * Max clock rate: 3.5GHz (single-core), 3.1GHz (multicore) * Max vector register length: 256 bits (AVX2) * Max FMA vector IPC: 2 * Peak performance: * single-core: 56 GFLOPS (double-precision), 112 GFLOPS (single-precision) * multicore: 49.6 GFLOPS/core (double-precision), 99.2 GFLOPS/core (single-precision) * Operating system: Cray Linux Environment 6 (Linux kernel 4.4.103) * Page size: 4096 bytes * Compiler: gcc 6.3.0 * Results gathered: 25-26 February 2019, 27 March 2019 * Implementations tested: * BLIS 075143df (0.5.1-39) * configured with `./configure -t openmp auto` (single- and multithreaded) * sub-configuration exercised: `haswell` * Single-threaded (1 core) execution requested via no change in environment variables * Multithreaded (12 core) execution requested via `export BLIS_JC_NT=2 BLIS_IC_NT=3 BLIS_JR_NT=2` * Multithreaded (24 core) execution requested via `export BLIS_JC_NT=4 BLIS_IC_NT=3 BLIS_JR_NT=2` * OpenBLAS 0.3.5 * configured `Makefile.rule` with `BINARY=64 NO_CBLAS=1 NO_LAPACK=1 NO_LAPACKE=1 USE_THREAD=0` (single-threaded) * configured `Makefile.rule` with `BINARY=64 NO_CBLAS=1 NO_LAPACK=1 NO_LAPACKE=1 USE_THREAD=1 NUM_THREADS=24` (multithreaded, 24 cores) * Single-threaded (1 core) execution requested via `export OPENBLAS_NUM_THREADS=1` * Multithreaded (12 core) execution requested via `export OPENBLAS_NUM_THREADS=12` * Multithreaded (24 core) execution requested via `export OPENBLAS_NUM_THREADS=24` * Eigen 3.3.90 * Obtained via the [Eigen git mirror](https://github.com/eigenteam/eigen-git-mirror) (March 27, 2019) * Prior to compilation, modified top-level `CMakeLists.txt` to ensure that `-march=native` was added to `CXX_FLAGS` variable (h/t Sameer Agarwal): ``` # These lines added after line 67. check_cxx_compiler_flag("-march=native" COMPILER_SUPPORTS_MARCH_NATIVE) if(COMPILER_SUPPORTS_MARCH_NATIVE) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native") endif() ``` * configured and built BLAS library via `mkdir build; cd build; cmake ..; make blas` * installed headers via `cmake . -DCMAKE_INSTALL_PREFIX=$HOME/flame/eigen; make install` * The `gemm` implementation was pulled in at compile-time via Eigen headers; other operations were linked to Eigen's BLAS library. * Single-threaded (1 core) execution requested via `export OMP_NUM_THREADS=1` * Multithreaded (12 core) execution requested via `export OMP_NUM_THREADS=12` * Multithreaded (24 core) execution requested via `export OMP_NUM_THREADS=24` * **NOTE**: This version of Eigen does not provide multithreaded implementations of `symm`/`hemm`, `syrk`/`herk`, `trmm`, or `trsm`, and therefore those curves are omitted from the multithreaded graphs. * MKL 2018 update 2 * Single-threaded (1 core) execution requested via `export MKL_NUM_THREADS=1` * Multithreaded (12 core) execution requested via `export MKL_NUM_THREADS=12` * Multithreaded (24 core) execution requested via `export MKL_NUM_THREADS=24` * Affinity: * Thread affinity for BLIS was specified manually via `GOMP_CPU_AFFINITY="0 1 2 3 ... 23"`. However, multithreaded OpenBLAS appears to revert to single-threaded execution if `GOMP_CPU_AFFINITY` is set. Therefore, when measuring OpenBLAS performance, the `GOMP_CPU_AFFINITY` environment variable was unset. * Frequency throttling (via `cpupower`): * No changes made. * Comments: * We were pleasantly surprised by how competitive BLIS performs relative to MKL on this multicore Haswell system, which is a _very_ common microarchitecture, and _very_ similar to the more recent Broadwells, Skylakes (desktop), Kaby Lakes, and Coffee Lakes that succeeded it. ### Haswell results #### pdf * [Haswell single-threaded](graphs/large/l3_perf_has_nt1.pdf) * [Haswell multithreaded (12 cores)](graphs/large/l3_perf_has_jc2ic3jr2_nt12.pdf) * [Haswell multithreaded (24 cores)](graphs/large/l3_perf_has_jc4ic3jr2_nt24.pdf) #### png (inline) * **Haswell single-threaded** ![single-threaded](graphs/large/l3_perf_has_nt1.png) * **Haswell multithreaded (12 cores)** ![multithreaded (12 cores)](graphs/large/l3_perf_has_jc2ic3jr2_nt12.png) * **Haswell multithreaded (24 cores)** ![multithreaded (24 cores)](graphs/large/l3_perf_has_jc4ic3jr2_nt24.png) --- ## Zen ### Zen experiment details * Location: Oracle cloud * Processor model: AMD Epyc 7551 (Zen1 "Naples") * Core topology: two sockets, 4 dies per socket, 2 core complexes (CCX) per die, 4 cores per CCX, 64 cores total * SMT status: enabled, but not utilized * Max clock rate: 3.0GHz (single-core), 2.55GHz (multicore) * Max vector register length: 256 bits (AVX2) * Max FMA vector IPC: 1 * Alternatively, FMA vector IPC is 2 when vectors are limited to 128 bits each. * Peak performance: * single-core: 24 GFLOPS (double-precision), 48 GFLOPS (single-precision) * multicore: 20.4 GFLOPS/core (double-precision), 40.8 GFLOPS/core (single-precision) * Operating system: Ubuntu 18.04 (Linux kernel 4.15.0) * Page size: 4096 bytes * Compiler: gcc 7.3.0 * Results gathered: 6 March 2019, 19 March 2019, 27 March 2019 * Implementations tested: * BLIS 9f1dbe5 (0.5.1-54) * configured with `./configure -t openmp auto` (single- and multithreaded) * sub-configuration exercised: `zen` * Single-threaded (1 core) execution requested via no change in environment variables * Multithreaded (32 core) execution requested via `export BLIS_JC_NT=1 BLIS_IC_NT=8 BLIS_JR_NT=4` * Multithreaded (64 core) execution requested via `export BLIS_JC_NT=2 BLIS_IC_NT=8 BLIS_JR_NT=4` * OpenBLAS 0.3.5 * configured `Makefile.rule` with `BINARY=64 NO_CBLAS=1 NO_LAPACK=1 NO_LAPACKE=1 USE_THREAD=0` (single-threaded) * configured `Makefile.rule` with `BINARY=64 NO_CBLAS=1 NO_LAPACK=1 NO_LAPACKE=1 USE_THREAD=1 NUM_THREADS=64` (multithreaded, 64 cores) * Single-threaded (1 core) execution requested via `export OPENBLAS_NUM_THREADS=1` * Multithreaded (32 core) execution requested via `export OPENBLAS_NUM_THREADS=32` * Multithreaded (64 core) execution requested via `export OPENBLAS_NUM_THREADS=64` * Eigen 3.3.90 * Obtained via the [Eigen git mirror](https://github.com/eigenteam/eigen-git-mirror) (March 27, 2019) * Prior to compilation, modified top-level `CMakeLists.txt` to ensure that `-march=native` was added to `CXX_FLAGS` variable (h/t Sameer Agarwal): ``` # These lines added after line 67. check_cxx_compiler_flag("-march=native" COMPILER_SUPPORTS_MARCH_NATIVE) if(COMPILER_SUPPORTS_MARCH_NATIVE) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native") endif() ``` * configured and built BLAS library via `mkdir build; cd build; cmake ..; make blas` * installed headers via `cmake . -DCMAKE_INSTALL_PREFIX=$HOME/flame/eigen; make install` * The `gemm` implementation was pulled in at compile-time via Eigen headers; other operations were linked to Eigen's BLAS library. * Single-threaded (1 core) execution requested via `export OMP_NUM_THREADS=1` * Multithreaded (32 core) execution requested via `export OMP_NUM_THREADS=32` * Multithreaded (64 core) execution requested via `export OMP_NUM_THREADS=64` * **NOTE**: This version of Eigen does not provide multithreaded implementations of `symm`/`hemm`, `syrk`/`herk`, `trmm`, or `trsm`, and therefore those curves are omitted from the multithreaded graphs. * MKL 2019 update 1 * Single-threaded (1 core) execution requested via `export MKL_NUM_THREADS=1` * Multithreaded (32 core) execution requested via `export MKL_NUM_THREADS=32` * Multithreaded (64 core) execution requested via `export MKL_NUM_THREADS=64` * Affinity: * Thread affinity for BLIS was specified manually via `GOMP_CPU_AFFINITY="0 1 2 3 ... 63"`. However, multithreaded OpenBLAS appears to revert to single-threaded execution if `GOMP_CPU_AFFINITY` is set. Therefore, when measuring OpenBLAS performance, the `GOMP_CPU_AFFINITY` environment variable was unset. * Frequency throttling (via `cpupower`): * Driver: acpi-cpufreq * Governor: performance * Hardware limits: 1.2GHz - 2.0GHz * Adjusted minimum: 2.0GHz * Comments: * MKL performance is dismal, despite being linked in the same manner as on the Xeon Platinum. It's not clear what is causing the slowdown. It could be that MKL's runtime kernel/blocksize selection logic is falling back to some older, more basic implementation because CPUID is not returning Intel as the hardware vendor. Alternatively, it's possible that MKL is trying to use kernels for the closest Intel architectures--say, Haswell/Broadwell--but its implementations use Haswell-specific optimizations that, due to microarchitectural differences, degrade performance on Zen. ### Zen results #### pdf * [Zen single-threaded](graphs/large/l3_perf_zen_nt1.pdf) * [Zen multithreaded (32 cores)](graphs/large/l3_perf_zen_jc1ic8jr4_nt32.pdf) * [Zen multithreaded (64 cores)](graphs/large/l3_perf_zen_jc2ic8jr4_nt64.pdf) #### png (inline) * **Zen single-threaded** ![single-threaded](graphs/large/l3_perf_zen_nt1.png) * **Zen multithreaded (32 cores)** ![multithreaded (32 cores)](graphs/large/l3_perf_zen_jc1ic8jr4_nt32.png) * **Zen multithreaded (64 cores)** ![multithreaded (64 cores)](graphs/large/l3_perf_zen_jc2ic8jr4_nt64.png) --- ## Zen2 ### Zen2 experiment details * Location: Oracle cloud * Processor model: AMD Epyc 7742 (Zen2 "Rome") * Core topology: two sockets, 8 Core Complex Dies (CCDs) per socket, 2 Core Complexes (CCX) per CCD, 4 cores per CCX, 128 cores total * SMT status: enabled, but not utilized * Max clock rate: 2.25GHz (base, documented); 3.4GHz boost (single-core, documented); 2.6GHz boost (multicore, estimated) * Max vector register length: 256 bits (AVX2) * Max FMA vector IPC: 2 * Alternatively, FMA vector IPC is 4 when vectors are limited to 128 bits each. * Peak performance: * single-core: 54.4 GFLOPS (double-precision), 108.8 GFLOPS (single-precision) * multicore (estimated): 41.6 GFLOPS/core (double-precision), 83.2 GFLOPS/core (single-precision) * Operating system: Ubuntu 18.04 (Linux kernel 4.15.0) * Page size: 4096 bytes * Compiler: gcc 9.3.0 * Results gathered: 24 September 2020, 29 September 2020 * Implementations tested: * BLIS 4fd8d9f (0.7.0-55) * configured with `./configure -t openmp auto` (single- and multithreaded) * sub-configuration exercised: `zen2` * Single-threaded (1 core) execution requested via no change in environment variables * Multithreaded (64 core) execution requested via `export BLIS_JC_NT=4 BLIS_IC_NT=4 BLIS_JR_NT=4` * Multithreaded (128 core) execution requested via `export BLIS_JC_NT=8 BLIS_IC_NT=4 BLIS_JR_NT=4` * OpenBLAS 0.3.10 * configured `Makefile.rule` with `BINARY=64 NO_CBLAS=1 NO_LAPACK=1 NO_LAPACKE=1 USE_THREAD=0` (single-threaded) * configured `Makefile.rule` with `BINARY=64 NO_CBLAS=1 NO_LAPACK=1 NO_LAPACKE=1 USE_THREAD=1 NUM_THREADS=64` (multithreaded, 64 cores) * configured `Makefile.rule` with `BINARY=64 NO_CBLAS=1 NO_LAPACK=1 NO_LAPACKE=1 USE_THREAD=1 NUM_THREADS=128` (multithreaded, 128 cores) * Single-threaded (1 core) execution requested via `export OPENBLAS_NUM_THREADS=1` * Multithreaded (64 core) execution requested via `export OPENBLAS_NUM_THREADS=64` * Multithreaded (128 core) execution requested via `export OPENBLAS_NUM_THREADS=128` * Eigen 3.3.90 * Obtained via the [Eigen GitLab homepage](https://gitlab.com/libeigen/eigen) (24 September 2020) * Prior to compilation, modified top-level `CMakeLists.txt` to ensure that `-march=native` was added to `CXX_FLAGS` variable (h/t Sameer Agarwal): ``` # These lines added after line 60. check_cxx_compiler_flag("-march=native" COMPILER_SUPPORTS_MARCH_NATIVE) if(COMPILER_SUPPORTS_MARCH_NATIVE) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native") endif() ``` * configured and built BLAS library via `mkdir build; cd build; cmake ..; make blas` * installed headers via `cmake . -DCMAKE_INSTALL_PREFIX=$HOME/flame/eigen; make install` * The `gemm` implementation was pulled in at compile-time via Eigen headers; other operations were linked to Eigen's BLAS library. * Single-threaded (1 core) execution requested via `export OMP_NUM_THREADS=1` * Multithreaded (64 core) execution requested via `export OMP_NUM_THREADS=64` * Multithreaded (128 core) execution requested via `export OMP_NUM_THREADS=128` * **NOTE**: This version of Eigen does not provide multithreaded implementations of `symm`/`hemm`, `syrk`/`herk`, `trmm`, or `trsm`, and therefore those curves are omitted from the multithreaded graphs. * MKL 2020 update 3 * Single-threaded (1 core) execution requested via `export MKL_NUM_THREADS=1` * Multithreaded (64 core) execution requested via `export MKL_NUM_THREADS=64` * Multithreaded (128 core) execution requested via `export MKL_NUM_THREADS=128` * Affinity: * Thread affinity for BLIS was specified manually via `GOMP_CPU_AFFINITY="0-127"`. However, multithreaded OpenBLAS appears to revert to single-threaded execution if `GOMP_CPU_AFFINITY` is set. Therefore, when measuring OpenBLAS performance, the `GOMP_CPU_AFFINITY` environment variable was unset. * All executables were run through `numactl --interleave=all`. * Frequency throttling (via `cpupower`): * Driver: acpi-cpufreq * Governor: performance * Hardware limits (steps): 1.5GHz, 2.0GHz, 2.25GHz * Adjusted minimum: 2.25GHz * Comments: * MKL performance is once again underwhelming. This is likely because Intel has decided that it does not want to give users of MKL a reason to purchase AMD hardware. ### Zen2 results #### pdf * [Zen2 single-threaded](graphs/large/l3_perf_zen2_nt1.pdf) * [Zen2 multithreaded (64 cores)](graphs/large/l3_perf_zen2_jc4ic4jr4_nt64.pdf) * [Zen2 multithreaded (128 cores)](graphs/large/l3_perf_zen2_jc8ic4jr4_nt128.pdf) #### png (inline) * **Zen2 single-threaded** ![single-threaded](graphs/large/l3_perf_zen2_nt1.png) * **Zen2 multithreaded (64 cores)** ![multithreaded (64 cores)](graphs/large/l3_perf_zen2_jc4ic4jr4_nt64.png) * **Zen2 multithreaded (128 cores)** ![multithreaded (128 cores)](graphs/large/l3_perf_zen2_jc8ic4jr4_nt128.png) --- ## A64fx ### A64fx experiment details * Location: RIKEN Center of Computational Science in Kobe, Japan * These test results were gathered on the Fugaku supercomputer under project "é‡å­ç‰©è³ªã®å‰µç™ºã¨æ©Ÿèƒ½ã®ãŸã‚ã®åŸºç¤Žç§‘å­¦ ―「富岳ã€ã¨æœ€å…ˆç«¯å®Ÿé¨“ã®å¯†é€£æºã«ã‚ˆã‚‹é©æ–°çš„強相関電å­ç§‘å­¦" (hp200132) (Basic Science for Emergence and Functionality in Quantum Matter: Innovative Strongly-Correlated Electron Science by Integration of "Fugaku" and Frontier Experiments) * Processor model: Fujitsu A64fx * Core topology: one socket, 4 NUMA groups per socket, 13 cores per group (one reserved for the OS), 48 cores total * SMT status: Unknown * Max clock rate: 2.2GHz (single- and multicore, observed) * Max vector register length: 512 bits (SVE) * Max FMA vector IPC: 2 * Peak performance: * single-core: 70.4 GFLOPS (double-precision), 140.8 GFLOPS (single-precision) * multicore: 70.4 GFLOPS/core (double-precision), 140.8 GFLOPS/core (single-precision) * Operating system: RHEL 8.3 * Page size: 256 bytes * Compiler: gcc 10.1.0 * Results gathered: 2 April 2021; BLIS and SSL2 updated on 21 Sept 2021 * Implementations tested: * BLIS b05279d (post-0.8.1) * configured with: * `../configure -t none CFLAGS="-DCACHE_SECTOR_SIZE_READONLY" a64fx` (single-threaded) * `../configure -t openmp CFLAGS="-DCACHE_SECTOR_SIZE_READONLY" a64fx` (multithreaded) * sub-configuration exercised: `a64fx` * Single-threaded (1 core) execution requested via no change in environment variables * Multithreaded (12 core) execution requested via `export BLIS_JC_NT=1 BLIS_IC_NT=1 BLIS_JR_NT=12` * Multithreaded (48 core) execution requested via `export BLIS_JC_NT=1 BLIS_IC_NT=4 BLIS_JR_NT=12` * Eigen 3.3.9 * Obtained via the [Eigen GitLab homepage](https://gitlab.com/libeigen/eigen) * configured and built BLAS library via `mkdir build; cd build; cmake ..; make blas` * installed headers via `cmake . -DCMAKE_INSTALL_PREFIX=$HOME/flame/eigen; make install` * The `gemm` implementation was pulled in at compile-time via Eigen headers; other operations were linked to Eigen's BLAS library. * Single-threaded (1 core) execution requested via `export OMP_NUM_THREADS=1` * Multithreaded (12 core) execution requested via `export OMP_NUM_THREADS=12` * Multithreaded (48 core) execution requested via `export OMP_NUM_THREADS=48` * **NOTE**: This version of Eigen does not provide multithreaded implementations of `symm`/`hemm`, `syrk`/`herk`, `trmm`, or `trsm`, and therefore those curves are omitted from the multithreaded graphs. * ARMPL (20.1.0 for A64fx) * Single-threaded (1 core) execution requested via `export OMP_NUM_THREADS=1` * Multithreaded (12 core) execution requested via `export OMP_NUM_THREADS=12` * Multithreaded (48 core) execution requested via `export OMP_NUM_THREADS=48` * **NOTE**: While this version of ARMPL does provide multithreaded implementations of `symm`/`hemm`, `syrk`/`herk`, `trmm`, or `trsm` (with the exception `dtrsm`), but these implementations yield very low performance, and their long run times led us to skip collecting these data altogether. * Fujitsu SSL2 (Fujitsu toolchain 1.2.33) * Single-threaded (1 core) execution requested via `export OMP_NUM_THREADS=1 NPARALLEL=1` * Multithreaded (12 core) execution requested via `export OMP_NUM_THREADS=12 NPARALLEL=12` * Multithreaded (48 core) execution requested via `export OMP_NUM_THREADS=48 NPARALLEL=48` * Affinity: * Thread affinity for BLIS was specified manually via `GOMP_CPU_AFFINITY="12-23 24-35 36-47 48-59"`. * All executables were run through `numactl --interleave=all` (multithreaded only). * Frequency throttling: No change made. No frequency lowering observed. * Comments: * Special thanks to Stepan Nassyr and RuQing G. Xu for their work in developing and optimizing A64fx support. Also, thanks to RuQing G. Xu for collecting the data that appear in these graphs. ### A64fx results #### pdf * [A64fx single-threaded](graphs/large/l3_perf_a64fx_nt1.pdf) * [A64fx multithreaded (12 cores)](graphs/large/l3_perf_a64fx_jc1ic1jr12_nt12.pdf) * [A64fx multithreaded (48 cores)](graphs/large/l3_perf_a64fx_jc1ic4jr12_nt48.pdf) #### png (inline) * **A64fx single-threaded** ![single-threaded](graphs/large/l3_perf_a64fx_nt1.png) * **A64fx multithreaded (12 cores)** ![multithreaded (12 cores)](graphs/large/l3_perf_a64fx_jc1ic1jr12_nt12.png) * **A64fx multithreaded (48 cores)** ![multithreaded (48 cores)](graphs/large/l3_perf_a64fx_jc1ic4jr12_nt48.png) --- ## Neoverse N1 ### Neoverse N1 experiment details * Location: AWS cloud * Processor model: Graviton2 Neoverse N1 * Core topology: one socket, 64 cores per socket, 64 cores total * SMT status: none * Max clock rate: 2.5GHz (single-core and multicore) * Max vector register length: 128 bits (NEON) * Max FMA vector IPC: 2 * Peak performance: * single-core: 20.0 GFLOPS (double-precision), 40.0 GFLOPS (single-precision) * multicore: 20.0 GFLOPS/core (double-precision), 40.0 GFLOPS/core (single-precision) * Operating system: unknown * Page size: unknown * Compiler: gcc 10.3.0 * Results gathered: 15 July 2021 * Implementations tested: * BLIS fab5c86d (0.8.1-67) * configured with `./configure -t openmp thunderx2` (single- and multithreaded) * sub-configuration exercised: `thunderx2` * Single-threaded (1 core) execution requested via no change in environment variables * Multithreaded (64 core) execution requested via `export BLIS_NUM_THREADS=64` * OpenBLAS 0.3.17 * configured `Makefile.rule` with `BINARY=64 NO_CBLAS=1 NO_LAPACK=1 NO_LAPACKE=1 USE_THREAD=0` (single-threaded) * configured `Makefile.rule` with `BINARY=64 NO_CBLAS=1 NO_LAPACK=1 NO_LAPACKE=1 USE_THREAD=1 NUM_THREADS=64` (multithreaded, 64 cores) * Single-threaded (1 core) execution requested via `export OPENBLAS_NUM_THREADS=1` * Multithreaded (64 core) execution requested via `export OPENBLAS_NUM_THREADS=64` * Affinity: * Thread affinity for BLIS was specified manually via `GOMP_CPU_AFFINITY="0-63"`. However, multithreaded OpenBLAS appears to revert to single-threaded execution if `GOMP_CPU_AFFINITY` is set. Therefore, when measuring OpenBLAS performance, the `GOMP_CPU_AFFINITY` environment variable was unset. * Frequency throttling (via `cpupower`): * No changes made. * Comments: * N/A ### Neoverse N1 results #### pdf * [Neoverse N1 single-threaded](graphs/large/l3_perf_nn1_nt1.pdf) * [Neoverse N1 multithreaded (64 cores)](graphs/large/l3_perf_nn1_jc2ic8jr4_nt64.pdf) #### png (inline) * **Neoverse N1 single-threaded** ![single-threaded](graphs/large/l3_perf_nn1_nt1.png) * **Neoverse N1 multithreaded (64 cores)** ![multithreaded (64 cores)](graphs/large/l3_perf_nn1_jc2ic8jr4_nt64.png) --- # Feedback Please let us know what you think of these performance results! Similarly, if you have any questions or concerns, or are interested in reproducing these performance experiments on your own hardware, we invite you to [open an issue](https://github.com/flame/blis/issues) and start a conversation with BLIS developers. Thanks for your interest in BLIS! blis-0.9.0/docs/PerformanceSmall.md000066400000000000000000000647371422157504600172040ustar00rootroot00000000000000# Contents * **[Contents](PerformanceSmall.md#contents)** * **[Introduction](PerformanceSmall.md#introduction)** * **[General information](PerformanceSmall.md#general-information)** * **[Interpretation](PerformanceSmall.md#interpretation)** * **[Reproduction](PerformanceSmall.md#reproduction)** * **[Level-3 performance](PerformanceSmall.md#level-3-performance)** * **[Kaby Lake](PerformanceSmall.md#kaby-lake)** * **[Experiment details](PerformanceSmall.md#kaby-lake-experiment-details)** * **[Results](PerformanceSmall.md#kaby-lake-results)** * **[Haswell](PerformanceSmall.md#haswell)** * **[Experiment details](PerformanceSmall.md#haswell-experiment-details)** * **[Results](PerformanceSmall.md#haswell-results)** * **[Zen](PerformanceSmall.md#zen)** * **[Experiment details](PerformanceSmall.md#zen-experiment-details)** * **[Results](PerformanceSmall.md#zen-results)** * **[Zen2](PerformanceSmall.md#zen2)** * **[Experiment details](PerformanceSmall.md#zen2-experiment-details)** * **[Results](PerformanceSmall.md#zen2-results)** * **[Feedback](PerformanceSmall.md#feedback)** # Introduction This document showcases performance results for the level-3 `gemm` operation on small matrices with BLIS and BLAS for select hardware architectures. # General information Generally speaking, for level-3 operations on small matrices, we publish two "panels" for each type of hardware, one that reflects performance on row-stored matrices and another for column-stored matrices. Each panel will consist of a 4x7 grid of graphs, with each row representing a different transposition case (`nn`, `nt`, `tn`, `tt`) complex) and each column representing a different shape scenario, usually with one or two matrix dimensions bound to a fixed size for all problem sizes tested. Each of the 28 graphs within a panel will contain an x-axis that reports problem size, with one, two, or all three matrix dimensions equal to the problem size (e.g. _m_ = 6; _n_ = _k_, also encoded as `m6npkp`). The y-axis will report in units GFLOPS (or billions of floating-point operations per second) per core. It's also worth pointing out that the top of some graphs (e.g. the maximum y-axis value depicted) correspond to the theoretical peak performance under the conditions associated with that graph, while in other graphs the y-axis has been adjusted to better show the difference between the various curves. (We *strongly* prefer to always use peak performance as the top of the graph; however, this is one of the few exceptions where we feel some scaling is warranted.) Theoretical peak performance on a single core, in units of GFLOPS, is calculated as the product of: 1. the maximum sustainable clock rate in GHz; and 2. the maximum number of floating-point operations (flops) that can be executed per cycle. Note that the maximum sustainable clock rate may change depending on the conditions. For example, on some systems the maximum clock rate is higher when only one core is active (e.g. single-threaded performance) versus when all cores are active (e.g. multithreaded performance). The maximum number of flops executable per cycle (per core) is generally computed as the product of: 1. the maximum number of fused multiply-add (FMA) vector instructions that can be issued per cycle (per core); 2. the maximum number of elements that can be stored within a single vector register (for the datatype in question); and 3. 2.0, since an FMA instruction fuses two operations (a multiply and an add). Typically, organizations and individuals publish performance with square matrices, which can miss the problem sizes of interest to many applications. Here, in addition to square matrices (shown in the seventh column), we also show six other scenarios where one or two `gemm` dimensions (of _m,_ _n_, and _k_) is small. In these six columns, the constant small matrix dimensions were chosen to be _very_ small--in the neighborhood of 8--intentionally to showcase what happens when at least one of the matrices is abnormally "skinny." The problem size range, represented on the x-axis, is sampled in increments that vary. These increments (and the overall range) are generally large for the cases where two dimensions are small (and constant), medium for cases where one dimension is small (and constant), and small for cases where all dimensions (e.g. _m_, _n_, and _k_) are variable and bound to the problem size (i.e., square matrices). The legend in each graph contains two entries for BLIS, corresponding to the two black lines, one solid and one dotted. The dotted line, **"BLIS conv"**, represents the conventional implementation that targets large matrices. This was the only implementation available in BLIS prior to the addition to the small/skinny matrix support. The solid line, **"BLIS sup"**, makes use of the new small/skinny matrix implementation. Sometimes, the performance of **"BLIS sup"** drops below that of **"BLIS conv"** for somewhat larger problems. However, in practice, we use a threshold to determine when to switch from the former to the latter, and therefore the goal is for the performance of **"BLIS conv"** to serve as an approximate floor below which BLIS performance never drops. Finally, each point along each curve represents the best of three trials. # Interpretation In general, the the curves associated with higher-performing implementations will appear higher in the graphs than lower-performing implementations. Ideally, an implementation will climb in performance (as a function of problem size) as quickly as possible and asymptotically approach some high fraction of peak performance. When corresponding with us, via email or when opening an [issue](https://github.com/flame/blis/issues) on github, we kindly ask that you specify as closely as possible (though a range is fine) your problem size of interest so that we can better assist you. # Reproduction In general, we do not offer any step-by-step guide for how to reproduce the performance graphs shown below. That said, if you are keenly interested in running your own performance benchmarks, either in an attempt to reproduce the results shown here or to measure performance of different hardware, of different implementations (or versions), and/or for different problem sizes, you should begin by studying the source code, `Makefile`, and scripts in the [test/sup](https://github.com/flame/blis/tree/master/test/sup) directory of the BLIS source distribution. Then, you'll need to take time to build and/or install some (or all) of the implementations shown (e.g. [OpenBLAS](https://github.com/xianyi/OpenBLAS), [MKL](https://software.intel.com/en-us/mkl/), [Eigen](http://eigen.tuxfamily.org), [BLASFEO](https://github.com/giaf/blasfeo), and [libxsmm](https://github.com/hfp/libxsmm)), including BLIS. Be sure to consult the detailed notes provided below; they should be *very* helpful in successfully building the libraries. The `runme.sh` script in `test/sup` (or `test/supmt`) will help you run some (or all) of the test drivers produced by the `Makefile`, and the Matlab/Octave function `plot_panel_trxsh()` defined in the `octave` directory will help you turn the output of those test drivers into a PDF file of graphs. The `runthese.m` file will contain example invocations of the function. # Level-3 performance ## Kaby Lake ### Kaby Lake experiment details * Location: undisclosed * Processor model: Intel Core i5-7500 (Kaby Lake) * Core topology: one socket, 4 cores total * SMT status: unavailable * Max clock rate: 3.8GHz (single-core) * Max vector register length: 256 bits (AVX2) * Max FMA vector IPC: 2 * Peak performance: * single-core: 57.6 GFLOPS (double-precision), 115.2 GFLOPS (single-precision) * multicore: 57.6 GFLOPS/core (double-precision), 115.2 GFLOPS/core (single-precision) * Operating system: Gentoo Linux (Linux kernel 5.2.4) * Page size: 4096 bytes * Compiler: gcc 8.3.0 * Results gathered: 3 March 2020 * Implementations tested: * BLIS 90db88e (0.6.1-8) * configured with `./configure --enable-cblas auto` (single-threaded) * configured with `./configure --enable-cblas -t openmp auto` (multithreaded) * sub-configuration exercised: `haswell` * Multithreaded (4 cores) execution requested via `export BLIS_NUM_THREADS=4` * OpenBLAS 0.3.8 * configured `Makefile.rule` with `BINARY=64 NO_LAPACK=1 NO_LAPACKE=1 USE_THREAD=0 USE_LOCKING=1` (single-threaded) * configured `Makefile.rule` with `BINARY=64 NO_LAPACK=1 NO_LAPACKE=1 USE_THREAD=1 NUM_THREADS=4` (multithreaded) * Multithreaded (4 cores) execution requested via `export OPENBLAS_NUM_THREADS=4` * BLASFEO f9b78c6 * configured `Makefile.rule` with: `BLAS_API=1 FORTRAN_BLAS_API=1 CBLAS_API=1`. * Eigen 3.3.90 * Obtained via the [Eigen git mirror](https://github.com/eigenteam/eigen-git-mirror) (36b9596) * Prior to compilation, modified top-level `CMakeLists.txt` to ensure that `-march=native` was added to `CXX_FLAGS` variable (h/t Sameer Agarwal): ``` # These lines added after line 67. check_cxx_compiler_flag("-march=native" COMPILER_SUPPORTS_MARCH_NATIVE) if(COMPILER_SUPPORTS_MARCH_NATIVE) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native") endif() ``` * configured and built BLAS library via `mkdir build; cd build; CC=gcc cmake ..; make blas` * installed headers via `cmake . -DCMAKE_INSTALL_PREFIX=$HOME/flame/eigen; make install` * The `gemm` implementation was pulled in at compile-time via Eigen headers; other operations were linked to Eigen's BLAS library. * Single-threaded (1 core) execution requested via `export OMP_NUM_THREADS=1` * Multithreaded (4 cores) execution requested via `export OMP_NUM_THREADS=4` * MKL 2020 initial release * Single-threaded (1 core) execution requested via `export MKL_NUM_THREADS=1` * Multithreaded (4 cores) execution requested via `export MKL_NUM_THREADS=4` * libxsmm a40a833 (post-1.14) * compiled with `make AVX=2`; linked with [netlib BLAS](http://www.netlib.org/blas/) 3.6.0 as the fallback library to better show where libxsmm stops handling the computation internally. * Affinity: * Thread affinity for BLIS was specified manually via `GOMP_CPU_AFFINITY="0-3"`. However, multithreaded OpenBLAS appears to revert to single-threaded execution if `GOMP_CPU_AFFINITY` is set. Therefore, when measuring OpenBLAS performance, the `GOMP_CPU_AFFINITY` environment variable was unset. * Frequency throttling (via `cpupower`): * Driver: intel_pstate * Governor: performance * Hardware limits: 800MHz - 3.8GHz * Adjusted minimum: 3.8GHz * Comments: * libxsmm is highly competitive for very small problems, but quickly gives up once the "large" dimension exceeds about 180-240 (or 64 in the case where all operands are square). Also, libxsmm's `gemm` cannot handle a transposition on matrix A and similarly dispatches the fallback implementation for those cases. libxsmm also does not export CBLAS interfaces, and therefore only appears on the graphs for column-stored matrices. ### Kaby Lake results #### pdf * [Kaby Lake single-threaded row-stored](graphs/sup/dgemm_rrr_kbl_nt1.pdf) * [Kaby Lake single-threaded column-stored](graphs/sup/dgemm_ccc_kbl_nt1.pdf) * [Kaby Lake multithreaded (4 cores) row-stored](graphs/sup/dgemm_rrr_kbl_nt4.pdf) * [Kaby Lake multithreaded (4 cores) column-stored](graphs/sup/dgemm_ccc_kbl_nt4.pdf) #### png (inline) * **Kaby Lake single-threaded row-stored** ![single-threaded row-stored](graphs/sup/dgemm_rrr_kbl_nt1.png) * **Kaby Lake single-threaded column-stored** ![single-threaded column-stored](graphs/sup/dgemm_ccc_kbl_nt1.png) * **Kaby Lake multithreaded (4 cores) row-stored** ![multithreaded row-stored](graphs/sup/dgemm_rrr_kbl_nt4.png) * **Kaby Lake multithreaded (4 cores) column-stored** ![multithreaded column-stored](graphs/sup/dgemm_ccc_kbl_nt4.png) --- ## Haswell ### Haswell experiment details * Location: TACC (Lonestar5) * Processor model: Intel Xeon E5-2690 v3 (Haswell) * Core topology: two sockets, 12 cores per socket, 24 cores total * SMT status: enabled, but not utilized * Max clock rate: 3.5GHz (single-core), 3.1GHz (multicore) * Max vector register length: 256 bits (AVX2) * Max FMA vector IPC: 2 * Peak performance: * single-core: 56 GFLOPS (double-precision), 112 GFLOPS (single-precision) * multicore: 49.6 GFLOPS/core (double-precision), 99.2 GFLOPS/core (single-precision) * Operating system: Cray Linux Environment 6 (Linux kernel 4.4.103) * Page size: 4096 bytes * Compiler: gcc 7.3.0 * Results gathered: 3 March 2020 * Implementations tested: * BLIS 90db88e (0.6.1-8) * configured with `./configure --enable-cblas auto` (single-threaded) * configured with `./configure --enable-cblas -t openmp auto` (multithreaded) * sub-configuration exercised: `haswell` * Multithreaded (12 cores) execution requested via `export BLIS_NUM_THREADS=12` * OpenBLAS 0.3.8 * configured `Makefile.rule` with `BINARY=64 NO_LAPACK=1 NO_LAPACKE=1 USE_THREAD=0 USE_LOCKING=1` (single-threaded) * configured `Makefile.rule` with `BINARY=64 NO_LAPACK=1 NO_LAPACKE=1 USE_THREAD=1 NUM_THREADS=12` (multithreaded) * Multithreaded (12 cores) execution requested via `export OPENBLAS_NUM_THREADS=12` * BLASFEO f9b78c6 * configured `Makefile.rule` with: `BLAS_API=1 FORTRAN_BLAS_API=1 CBLAS_API=1`. * Eigen 3.3.90 * Obtained via the [Eigen git mirror](https://github.com/eigenteam/eigen-git-mirror) (36b9596) * Prior to compilation, modified top-level `CMakeLists.txt` to ensure that `-march=native` was added to `CXX_FLAGS` variable (h/t Sameer Agarwal): ``` # These lines added after line 67. check_cxx_compiler_flag("-march=native" COMPILER_SUPPORTS_MARCH_NATIVE) if(COMPILER_SUPPORTS_MARCH_NATIVE) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native") endif() ``` * configured and built BLAS library via `mkdir build; cd build; CC=gcc cmake ..; make blas` * installed headers via `cmake . -DCMAKE_INSTALL_PREFIX=$HOME/flame/eigen; make install` * The `gemm` implementation was pulled in at compile-time via Eigen headers; other operations were linked to Eigen's BLAS library. * Single-threaded (1 core) execution requested via `export OMP_NUM_THREADS=1` * Multithreaded (12 cores) execution requested via `export OMP_NUM_THREADS=12` * MKL 2020 initial release * Single-threaded (1 core) execution requested via `export MKL_NUM_THREADS=1` * Multithreaded (12 cores) execution requested via `export MKL_NUM_THREADS=12` * libxsmm a40a833 (post-1.14) * compiled with `make AVX=2`; linked with [netlib BLAS](http://www.netlib.org/blas/) 3.6.0 as the fallback library to better show where libxsmm stops handling the computation internally. * Affinity: * Thread affinity for BLIS was specified manually via `GOMP_CPU_AFFINITY="0-11"`. However, multithreaded OpenBLAS appears to revert to single-threaded execution if `GOMP_CPU_AFFINITY` is set. Therefore, when measuring OpenBLAS performance, the `GOMP_CPU_AFFINITY` environment variable was unset. * Frequency throttling (via `cpupower`): * No changes made. * Comments: * libxsmm is highly competitive for very small problems, but quickly gives up once the "large" dimension exceeds about 180-240 (or 64 in the case where all operands are square). Also, libxsmm's `gemm` cannot handle a transposition on matrix A and similarly dispatches the fallback implementation for those cases. libxsmm also does not export CBLAS interfaces, and therefore only appears on the graphs for column-stored matrices. ### Haswell results #### pdf * [Haswell single-threaded row-stored](graphs/sup/dgemm_rrr_has_nt1.pdf) * [Haswell single-threaded column-stored](graphs/sup/dgemm_ccc_has_nt1.pdf) * [Haswell multithreaded (12 cores) row-stored](graphs/sup/dgemm_rrr_has_nt12.pdf) * [Haswell multithreaded (12 cores) column-stored](graphs/sup/dgemm_ccc_has_nt12.pdf) #### png (inline) * **Haswell single-threaded row-stored** ![single-threaded row-stored](graphs/sup/dgemm_rrr_has_nt1.png) * **Haswell single-threaded column-stored** ![single-threaded column-stored](graphs/sup/dgemm_ccc_has_nt1.png) * **Haswell multithreaded (12 cores) row-stored** ![multithreaded row-stored](graphs/sup/dgemm_rrr_has_nt12.png) * **Haswell multithreaded (12 cores) column-stored** ![multithreaded column-stored](graphs/sup/dgemm_ccc_has_nt12.png) --- ## Zen ### Zen experiment details * Location: Oracle cloud * Processor model: AMD Epyc 7551 (Zen1) * Core topology: two sockets, 4 dies per socket, 2 core complexes (CCX) per die, 4 cores per CCX, 64 cores total * SMT status: enabled, but not utilized * Max clock rate: 3.0GHz (single-core), 2.55GHz (multicore) * Max vector register length: 256 bits (AVX2) * Max FMA vector IPC: 1 * Alternatively, FMA vector IPC is 2 when vectors are limited to 128 bits each. * Peak performance: * single-core: 24 GFLOPS (double-precision), 48 GFLOPS (single-precision) * multicore: 20.4 GFLOPS/core (double-precision), 40.8 GFLOPS/core (single-precision) * Operating system: Ubuntu 18.04 (Linux kernel 4.15.0) * Page size: 4096 bytes * Compiler: gcc 7.4.0 * Results gathered: 3 March 2020 * Implementations tested: * BLIS 90db88e (0.6.1-8) * configured with `./configure --enable-cblas auto` (single-threaded) * configured with `./configure --enable-cblas -t openmp auto` (multithreaded) * sub-configuration exercised: `zen` * Multithreaded (32 cores) execution requested via `export BLIS_NUM_THREADS=32` * OpenBLAS 0.3.8 * configured `Makefile.rule` with `BINARY=64 NO_LAPACK=1 NO_LAPACKE=1 USE_THREAD=0 USE_LOCKING=1` (single-threaded) * configured `Makefile.rule` with `BINARY=64 NO_LAPACK=1 NO_LAPACKE=1 USE_THREAD=1 NUM_THREADS=32` (multithreaded) * Multithreaded (32 cores) execution requested via `export OPENBLAS_NUM_THREADS=32` * BLASFEO f9b78c6 * configured `Makefile.rule` with: `BLAS_API=1 FORTRAN_BLAS_API=1 CBLAS_API=1`. * built BLAS library via `make CC=gcc` * Eigen 3.3.90 * Obtained via the [Eigen git mirror](https://github.com/eigenteam/eigen-git-mirror) (36b9596) * Prior to compilation, modified top-level `CMakeLists.txt` to ensure that `-march=native` was added to `CXX_FLAGS` variable (h/t Sameer Agarwal): ``` # These lines added after line 67. check_cxx_compiler_flag("-march=native" COMPILER_SUPPORTS_MARCH_NATIVE) if(COMPILER_SUPPORTS_MARCH_NATIVE) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native") endif() ``` * configured and built BLAS library via `mkdir build; cd build; CC=gcc cmake ..; make blas` * installed headers via `cmake . -DCMAKE_INSTALL_PREFIX=$HOME/flame/eigen; make install` * The `gemm` implementation was pulled in at compile-time via Eigen headers; other operations were linked to Eigen's BLAS library. * Single-threaded (1 core) execution requested via `export OMP_NUM_THREADS=1` * Multithreaded (32 cores) execution requested via `export OMP_NUM_THREADS=32` * MKL 2020 initial release * Single-threaded (1 core) execution requested via `export MKL_NUM_THREADS=1` * Multithreaded (32 cores) execution requested via `export MKL_NUM_THREADS=32` * libxsmm a40a833 (post-1.14) * compiled with `make AVX=2`; linked with [netlib BLAS](http://www.netlib.org/blas/) 3.6.0 as the fallback library to better show where libxsmm stops handling the computation internally. * Affinity: * Thread affinity for BLIS was specified manually via `GOMP_CPU_AFFINITY="0-31"`. However, multithreaded OpenBLAS appears to revert to single-threaded execution if `GOMP_CPU_AFFINITY` is set. Therefore, when measuring OpenBLAS performance, the `GOMP_CPU_AFFINITY` environment variable was unset. * Frequency throttling (via `cpupower`): * Driver: acpi-cpufreq * Governor: performance * Hardware limits: 1.2GHz - 2.0GHz * Adjusted minimum: 2.0GHz * Comments: * libxsmm is highly competitive for very small problems, but quickly gives up once the "large" dimension exceeds about 180-240 (or 64 in the case where all operands are square). Also, libxsmm's `gemm` cannot handle a transposition on matrix A and similarly dispatches the fallback implementation for those cases. libxsmm also does not export CBLAS interfaces, and therefore only appears on the graphs for column-stored matrices. ### Zen results #### pdf * [Zen single-threaded row-stored](graphs/sup/dgemm_rrr_zen_nt1.pdf) * [Zen single-threaded column-stored](graphs/sup/dgemm_ccc_zen_nt1.pdf) * [Zen multithreaded (32 cores) row-stored](graphs/sup/dgemm_rrr_zen_nt32.pdf) * [Zen multithreaded (32 cores) column-stored](graphs/sup/dgemm_ccc_zen_nt32.pdf) #### png (inline) * **Zen single-threaded row-stored** ![single-threaded row-stored](graphs/sup/dgemm_rrr_zen_nt1.png) * **Zen single-threaded column-stored** ![single-threaded column-stored](graphs/sup/dgemm_ccc_zen_nt1.png) * **Zen multithreaded (32 cores) row-stored** ![multithreaded row-stored](graphs/sup/dgemm_rrr_zen_nt32.png) * **Zen multithreaded (32 cores) column-stored** ![multithreaded column-stored](graphs/sup/dgemm_ccc_zen_nt32.png) --- ## Zen2 ### Zen2 experiment details * Location: Oracle cloud * Processor model: AMD Epyc 7742 (Zen2 "Rome") * Core topology: two sockets, 8 Core Complex Dies (CCDs) per socket, 2 Core Complexes (CCX) per CCD, 4 cores per CCX, 128 cores total * SMT status: enabled, but not utilized * Max clock rate: 2.25GHz (base, documented); 3.4GHz boost (single-core, documented); 2.6GHz boost (multicore, estimated) * Max vector register length: 256 bits (AVX2) * Max FMA vector IPC: 2 * Alternatively, FMA vector IPC is 4 when vectors are limited to 128 bits each. * Peak performance: * single-core: 54.4 GFLOPS (double-precision), 108.8 GFLOPS (single-precision) * multicore (estimated): 41.6 GFLOPS/core (double-precision), 83.2 GFLOPS/core (single-precision) * Operating system: Ubuntu 18.04 (Linux kernel 4.15.0) * Page size: 4096 bytes * Compiler: gcc 9.3.0 * Results gathered: 8 October 2020 * Implementations tested: * BLIS a0849d3 (0.7.0-67) * configured with `./configure --enable-cblas auto` (single-threaded) * configured with `./configure --enable-cblas -t openmp auto` (multithreaded) * sub-configuration exercised: `zen2` * Multithreaded (32 cores) execution requested via `export BLIS_NUM_THREADS=32` * OpenBLAS 0.3.10 * configured `Makefile.rule` with `BINARY=64 NO_LAPACK=1 NO_LAPACKE=1 USE_THREAD=0 USE_LOCKING=1` (single-threaded) * configured `Makefile.rule` with `BINARY=64 NO_LAPACK=1 NO_LAPACKE=1 USE_THREAD=1 NUM_THREADS=32` (multithreaded) * Multithreaded (32 cores) execution requested via `export OPENBLAS_NUM_THREADS=32` * BLASFEO 5b26d40 * configured `Makefile.rule` with: `BLAS_API=1 FORTRAN_BLAS_API=1 CBLAS_API=1`. * built BLAS library via `make CC=gcc` * Eigen 3.3.90 * Obtained via the [Eigen GitLab homepage](https://gitlab.com/libeigen/eigen) (24 September 2020) * Prior to compilation, modified top-level `CMakeLists.txt` to ensure that `-march=native` was added to `CXX_FLAGS` variable (h/t Sameer Agarwal): ``` # These lines added after line 60. check_cxx_compiler_flag("-march=native" COMPILER_SUPPORTS_MARCH_NATIVE) if(COMPILER_SUPPORTS_MARCH_NATIVE) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native") endif() ``` * configured and built BLAS library via `mkdir build; cd build; CC=gcc cmake ..; make blas` * installed headers via `cmake . -DCMAKE_INSTALL_PREFIX=$HOME/flame/eigen; make install` * The `gemm` implementation was pulled in at compile-time via Eigen headers; other operations were linked to Eigen's BLAS library. * Single-threaded (1 core) execution requested via `export OMP_NUM_THREADS=1` * Multithreaded (32 cores) execution requested via `export OMP_NUM_THREADS=32` * MKL 2020 update 3 * Single-threaded (1 core) execution requested via `export MKL_NUM_THREADS=1` * Multithreaded (32 cores) execution requested via `export MKL_NUM_THREADS=32` * libxsmm f0ab9cb (post-1.16.1) * compiled with `make AVX=2`; linked with [netlib BLAS](http://www.netlib.org/blas/) 3.6.0 as the fallback library to better show where libxsmm stops handling the computation internally. * Affinity: * Thread affinity for BLIS was specified manually via `GOMP_CPU_AFFINITY="0-31"`. However, multithreaded OpenBLAS appears to revert to single-threaded execution if `GOMP_CPU_AFFINITY` is set. Therefore, when measuring OpenBLAS performance, the `GOMP_CPU_AFFINITY` environment variable was unset. * All executables were run through `numactl --interleave=all`. * Frequency throttling (via `cpupower`): * Driver: acpi-cpufreq * Governor: performance * Hardware limits (steps): 1.5GHz, 2.0GHz, 2.25GHz * Adjusted minimum: 2.25GHz * Comments: * None. ### Zen2 results #### pdf * [Zen2 sgemm single-threaded row-stored](graphs/sup/sgemm_rrr_zen2_nt1.pdf) * [Zen2 sgemm single-threaded column-stored](graphs/sup/sgemm_ccc_zen2_nt1.pdf) * [Zen2 dgemm single-threaded row-stored](graphs/sup/dgemm_rrr_zen2_nt1.pdf) * [Zen2 dgemm single-threaded column-stored](graphs/sup/dgemm_ccc_zen2_nt1.pdf) * [Zen2 sgemm multithreaded (32 cores) row-stored](graphs/sup/sgemm_rrr_zen2_nt32.pdf) * [Zen2 sgemm multithreaded (32 cores) column-stored](graphs/sup/sgemm_ccc_zen2_nt32.pdf) * [Zen2 dgemm multithreaded (32 cores) row-stored](graphs/sup/dgemm_rrr_zen2_nt32.pdf) * [Zen2 dgemm multithreaded (32 cores) column-stored](graphs/sup/dgemm_ccc_zen2_nt32.pdf) #### png (inline) * **Zen2 sgemm single-threaded row-stored** ![sgemm single-threaded row-stored](graphs/sup/sgemm_rrr_zen2_nt1.png) * **Zen2 sgemm single-threaded column-stored** ![sgemm single-threaded column-stored](graphs/sup/sgemm_ccc_zen2_nt1.png) * **Zen2 dgemm single-threaded row-stored** ![dgemm single-threaded row-stored](graphs/sup/dgemm_rrr_zen2_nt1.png) * **Zen2 dgemm single-threaded column-stored** ![dgemm single-threaded column-stored](graphs/sup/dgemm_ccc_zen2_nt1.png) * **Zen2 sgemm multithreaded (32 cores) row-stored** ![sgemm multithreaded row-stored](graphs/sup/sgemm_rrr_zen2_nt32.png) * **Zen2 sgemm multithreaded (32 cores) column-stored** ![sgemm multithreaded column-stored](graphs/sup/sgemm_ccc_zen2_nt32.png) * **Zen2 dgemm multithreaded (32 cores) row-stored** ![dgemm multithreaded row-stored](graphs/sup/dgemm_rrr_zen2_nt32.png) * **Zen2 dgemm multithreaded (32 cores) column-stored** ![dgemm multithreaded column-stored](graphs/sup/dgemm_ccc_zen2_nt32.png) --- # Feedback Please let us know what you think of these performance results! Similarly, if you have any questions or concerns, or are interested in reproducing these performance experiments on your own hardware, we invite you to [open an issue](https://github.com/flame/blis/issues) and start a conversation with BLIS developers. Thanks for your interest in BLIS! blis-0.9.0/docs/ReleaseNotes.md000066400000000000000000002241551422157504600163330ustar00rootroot00000000000000# Release Notes *Note: For some releases, credit for individuals' contributions are shown in parentheses.* ## Contents * [Changes in 0.9.0](ReleaseNotes.md#changes-in-090) * [Changes in 0.8.1](ReleaseNotes.md#changes-in-081) * [Changes in 0.8.0](ReleaseNotes.md#changes-in-080) * [Changes in 0.7.0](ReleaseNotes.md#changes-in-070) * [Changes in 0.6.1](ReleaseNotes.md#changes-in-061) * [Changes in 0.6.0](ReleaseNotes.md#changes-in-060) * [Changes in 0.5.2](ReleaseNotes.md#changes-in-052) * [Changes in 0.5.1](ReleaseNotes.md#changes-in-051) * [Changes in 0.5.0](ReleaseNotes.md#changes-in-050) * [Changes in 0.4.1](ReleaseNotes.md#changes-in-041) * [Changes in 0.4.0](ReleaseNotes.md#changes-in-040) * [Changes in 0.3.2](ReleaseNotes.md#changes-in-032) * [Changes in 0.3.1](ReleaseNotes.md#changes-in-031) * [Changes in 0.3.0](ReleaseNotes.md#changes-in-030) * [Changes in 0.2.2](ReleaseNotes.md#changes-in-022) * [Changes in 0.2.1](ReleaseNotes.md#changes-in-021) * [Changes in 0.2.0](ReleaseNotes.md#changes-in-020) * [Changes in 0.1.8](ReleaseNotes.md#changes-in-018) * [Changes in 0.1.7](ReleaseNotes.md#changes-in-017) * [Changes in 0.1.6](ReleaseNotes.md#changes-in-016) * [Changes in 0.1.5](ReleaseNotes.md#changes-in-015) * [Changes in 0.1.4](ReleaseNotes.md#changes-in-014) * [Changes in 0.1.3](ReleaseNotes.md#changes-in-013) * [Changes in 0.1.2](ReleaseNotes.md#changes-in-012) * [Changes in 0.1.1](ReleaseNotes.md#changes-in-011) * [Changes in 0.1.0](ReleaseNotes.md#changes-in-010) * [Changes in 0.0.9](ReleaseNotes.md#changes-in-009) * [Changes in 0.0.8](ReleaseNotes.md#changes-in-008) * [Changes in 0.0.7](ReleaseNotes.md#changes-in-007) * [Changes in 0.0.6](ReleaseNotes.md#changes-in-006) * [Changes in 0.0.5](ReleaseNotes.md#changes-in-005) * [Changes in 0.0.4](ReleaseNotes.md#changes-in-004) * [Changes in 0.0.3](ReleaseNotes.md#changes-in-003) * [Changes in 0.0.2](ReleaseNotes.md#changes-in-002) * [Changes in 0.0.1](ReleaseNotes.md#changes-in-001) ## Changes in 0.9.0 April 1, 2022 Improvements present in 0.9.0: Framework: - Added various fields to `obj_t` that relate to storing function pointers to custom `packm` kernels, microkernels, etc as well as accessor functions to set and query those fields. (Devin Matthews) - Enabled user-customized `packm` microkernels and variants via the aforementioned new `obj_t` fields. (Devin Matthews) - Moved edge-case handling out of the macrokernel and into the `gemm` and `gemmtrsm` microkernels. This also required updating of APIs and definitions of all existing microkernels in `kernels` directory. Edge-case handling functionality is now facilitated via new preprocessor macros found in `bli_edge_case_macro_defs.h`. (Devin Matthews) - Avoid `gemmsup` thread barriers when not packing A or B. This boosts performance for many small multithreaded problems. (Field Van Zee, AMD) - Allow the 1m method to operate normally when single and double real-domain microkernels mix row and column I/O preference. (Field Van Zee, Devin Matthews, RuQing Xu) - Removed support for execution of complex-domain level-3 operations via the 3m and 4m methods. - Refactored `herk`, `her2k`, `syrk`, `syr2k` in terms of `gemmt`. (Devin Matthews) - Defined `setijv` and `getijv` to set/get vector elements. - Defined `eqsc`, `eqv`, and `eqm` operations to test equality between two scalars, vectors, or matrices. - Added new bounds checking to `setijm` and `getijm` to prevent use of negative indices. - Renamed `membrk` files/variables/functions to `pba`. - Store error-checking level as a thread-local variable. (Devin Matthews) - Add `err_t*` "return" parameter to `bli_malloc_*()` and friends. - Switched internal mutexes of the `sba` and `pba` to static initialization. - Changed return value method of `bli_pack_get_pack_a()`, `bli_pack_get_pack_b()`. - Fixed a bug that allows `bli_init()` to be called more than once (without segfaulting). (@lschork2, Minh Quan Ho, Devin Matthews) - Removed a sanity check in `bli_pool_finalize()` that prevented BLIS from being re-initialized. (AMD) - Fixed insufficient `pool_t`-growing logic in `bli_pool.c`, and always allocate at least one element in `.block_ptrs` array. (Minh Quan Ho) - Cleanups related to the error message array in `bli_error.c`. (Minh Quan Ho) - Moved language-related definitions from `bli_macro_defs.h` to a new header, `bli_lang_defs.h`. - Renamed `BLIS_SIMD_NUM_REGISTERS` to `BLIS_SIMD_MAX_NUM_REGISTERS` and `BLIS_SIMD_SIZE` to `BLIS_SIMD_MAX_SIZE` for improved clarity. (Devin Matthews) - Many minor bugfixes. - Many cleanups, including removal of old and commented-out code. Compatibility: - Expanded BLAS layer to include support for `?axpby_()` and `?gemm_batch_()`. (Meghana Vankadari, AMD) - Added `gemm3m` APIs to BLAS and CBLAS layers. (Bhaskar Nallani, AMD) - Handle `?gemm_()` invocations where m or n is unit by calling `?gemv_()`. (Dipal M Zambare, AMD) - Removed option to finalize BLIS after every BLAS call. - Updated default definitions of `bli_slamch()` and `bli_dlamch()` to use constants from standard C library rather than values computed at runtime. (Devin Matthews) Kernels: - Added 512-bit SVE-based `a64fx` subconfiguration that uses empirically-tuned blocksizes (Stepan Nassyr, RuQing Xu) - Added a vector-length agnostic `armsve` subconfig that computes blocksizes via an analytical model. (Stepan Nassyr) - Added vector-length agnostic d/s/sh `gemm` kernels for Arm SVE. (Stepan Nassyr) - Added `gemmsup` kernels to the `armv8a` kernel set for use in new Apple Firestorm subconfiguration. (RuQing Xu) - Added 512-bit SVE `dpackm` kernels (16xk and 10xk) with in-register transpose. (RuQing Xu) - Extended 256-bit SVE `dpackm` kernels by Linaro Ltd. to 512-bit for size 12xk. (RuQing Xu) - Reorganized register usage in `bli_gemm_armv8a_asm_d6x8.c` to accommodate clang. (RuQing Xu) - Added `saxpyf`/`daxpyf`/`caxpyf` kernels to `zen` kernel set. (Dipal M Zambare, AMD) - Added `vzeroupper` instruction to `haswell` microkernels. (Devin Matthews) - Added explicit `beta == 0` handling in s/d `armsve` and `armv7a` `gemm` microkernels. (Devin Matthews) - Added a unique tag to branch labels to accommodate clang. (Devin Matthews, Jeff Hammond) - Fixed a copy-paste bug in the loading of `kappa_i` in the two assembly `cpackm` kernels in `haswell` kernel set. (Devin Matthews) - Fixed a bug in Mx1 `gemmsup` `haswell` kernels whereby the `vhaddpd` instruction is used with uninitialized registers. (Devin Matthews) - Fixed a bug in the `power10` microkernel I/O. (Nicholai Tukanov) - Many other Arm kernel updates and fixes. (RuQing Xu) Extras: - Added support for addons, which are similar to sandboxes but do not require the user to implement any particular operation. - Added a new `gemmlike` sandbox to allow rapid prototyping of `gemm`-like operations. - Various updates and improvements to the `power10` sandbox, including a new testsuite. (Nicholai Tukanov) Build system: - Added explicit support for AMD's Zen3 microarchitecture. (Dipal M Zambare, AMD, Field Van Zee) - Added runtime microarchitecture detection for Arm. (Dave Love, RuQing Xu, Devin Matthews) - Added a new `configure` option `--[en|dis]able-amd-frame-tweaks` that allows BLIS to compile certain framework files (each with the `_amd` suffix) that have been customized by AMD for improved performance (provided that the targeted configuration is eligible). By default, the more portable counterparts to these files are compiled. (Field Van Zee, AMD) - Added an explicit compiler predicate (`is_win`) for Windows in `configure`. (Devin Matthews) - Use `-march=haswell` instead of `-march=skylake-avx512` on Windows. (Devin Matthews, @h-vetinari) - Fixed `configure` breakage on MacOSX by accepting either `clang` or `LLVM` in vendor string. (Devin Matthews) - Blacklist clang10/gcc9 and older for `armsve` subconfig. - Added a `configure` option to control whether or not to use `@rpath`. (Devin Matthews) - Added armclang detection to `configure`. (Devin Matthews) - Use `@path`-based install name on MacOSX and use relocatable `RPATH` entries for testsuite binaries. (Devin Matthews) - For environment variables `CC`, `CXX`, `FC`, `PYTHON`, `AR`, and `RANLIB`, `configure` will now print an error message and abort if a user specifies a specific tool and that tool is not found. (Field Van Zee, Devin Matthews) - Added symlink to `blis.pc.in` for out-of-tree builds. (Andrew Wildman) - Register optimized real-domain `copyv`, `setv`, and `swapv` kernels in `zen` subconfig. (Dipal M Zambare, AMD) - Added Apple Firestorm (A14/M1) subconfiguration, `firestorm`. (RuQing Xu) - Added `armsve` subconfig to `arm64` configuration family. (RuQing Xu) - Allow using clang with the `thunderx2` subconfiguration. (Devin Matthews) - Fixed a subtle substitution bug in `configure`. (Chengguo Sun) - Updated top-level Makefile to reflect a dependency on the "flat" `blis.h` file for the BLIS and BLAS testsuite objects. (Devin Matthews) - Mark `xerbla_()` as a "weak" symbol on MacOSX. (Devin Matthews) - Fixed a long-standing bug in `common.mk` whereby the header path to `cblas.h` was omitted from the compiler flags when compiling CBLAS files within BLIS. - Added a custom-made recursive `sed` script to `build` directory. - Minor cleanups and fixes to `configure`, `common.mk`, and others. Testing: - Fixed a race condition in the testsuite when the SALT option (simulate application-level threading) is enabled. (Devin Matthews) - Test 1m method execution during `make check`. (Devin Matthews) - Test `make install` in Travis CI. (Devin Matthews) - Test C++ in Travis CI to make sure `blis.h` is C++-compatible. (Devin Matthews) - Disabled SDE testing of pre-Zen microarchitectures via Travis CI. - Added Travis CI support for testing Arm SVE. (RuQing Xu) - Updated SDE usage so that it is downloaded from a separate repository (ci-utils) in our GitHub organization. (Field Van Zee, Devin Matthews) - Updated octave scripts in `test/3` to be robust against missing datasets as well as to fixed a few minor issues. - Added `test_axpbyv.c` and `test_gemm_batch.c` test driver files to `test` directory. (Meghana Vankadari, AMD) - Support all four datatypes in `her`, `her2`, `herk`, and `her2k` drivers in `test` directory. (Madan mohan Manokar, AMD) Documentation: - Added documentation for: `setijv`, `getijv`, `eqsc`, `eqv`, `eqm`. - Added `docs/Addons.md`. - Added dedicated "Performance" and "Example Code" sections to `README.md`. - Updated `README.md`. - Updated `docs/Sandboxes.md`. - Updated `docs/Multithreading.md`. (Devin Matthews) - Updated `docs/KernelHowTo.md`. - Updated `docs/Performance.md` to report Fujitsu A64fx (512-bit SVE) results. (RuQing Xu) - Updated `docs/Performance.md` to report Graviton2 Neoverse N1 results. (Nicholai Tukanov) - Updated `docs/FAQ.md` with new questions. - Fixed typos in `docs/FAQ.md`. (Gaëtan Cassiers) - Various other minor fixes. ## Changes in 0.8.1 March 22, 2021 Improvements present in 0.8.1: Framework: - Implemented an automatic reduction in the number of threads when the user requests parallelism via a single number (ie: the automatic way) and (a) that number of threads is prime, and (b) that number exceeds a minimum threshold defined by the macro `BLIS_NT_MAX_PRIME`, which defaults to 11. If prime numbers are really desired, this feature may be suppressed by defining the macro `BLIS_ENABLE_AUTO_PRIME_NUM_THREADS` in the appropriate configuration family's `bli_family_*.h`. (Jeff Diamond) - Changed default value of `BLIS_THREAD_RATIO_M` from 2 to 1, which leads to slightly different automatic thread factorizations. - Enable the 1m method only if the real domain microkernel is not a reference kernel. BLIS now forgoes use of 1m if both the real and complex domain kernels are reference implementations. - Relocated the general stride handling for `gemmsup`. This fixed an issue whereby `gemm` would fail to trigger to conventional code path for cases that use general stride even after `gemmsup` rejected the problem. (RuQing Xu) - Disabled AMD's small matrix handling entry points for `syrk` and `trsm` due to lack of testing on our side. - Fixed an incorrect function signature (and prototype) of `bli_?gemmt()`. (RuQing Xu) - Redefined `BLIS_NUM_ARCHS` to be part of the `arch_t` enum, which means it will be updated automatically when defining future subconfigs. - Minor code consolidation in all level-3 `_front()` functions. - Reorganized Windows cpp branch of `bli_pthreads.c`. - Implemented `bli_pthread_self()` and `_equals()`, but left them commented out (via cpp guards) due to issues with getting the Windows versions working. Thankfully, these functions aren't yet needed by BLIS. Kernels: - Added low-precision POWER10 `gemm` kernels via a `power10` sandbox. This sandbox also provides an API for implementations that use these kernels. See the `sandbox/power10/POWER10.md` document for more info. (Nicholai Tukanov) - Added assembly `packm` kernels for the `haswell` kernel set and registered to `haswell`, `zen`, and `zen2` subconfigs accordingly. The `s`, `c`, and `z` kernels were modeled on the `d` kernel, which was contributed by AMD. - Reduced KC in the `skx` subconfig from 384 to 256. (Tze Meng Low) - Fixed bugs in two `haswell` dgemmsup kernels, which involved extraneous assembly instructions left over from when the kernels were first written. (Kiran Varaganti, Bhaskar Nallani) - Minor updates to all of the `gemmtrsm` kernels to allow division by diagonal elements rather that scaling by pre-inverted elements. This change was applied to `haswell` and `penryn` kernel sets as well as reference kernels, 1m kernels, and the pre-broadcast B (bb) format kernels used by the `power9` subconfig. (Bhaskar Nallani) - Fixed incorrect return type on `bli_diag_offset_with_trans()`. (Devin Matthews) Build system: - Output a pkgconfig file so that CMake users that use BLIS can find and incorporate BLIS build products. (Ajay Panyala) - Fixed an issue in the the configure script's kernel-to-config map that caused `skx` kernel flags to be used when compiling kernels from the `zen` kernel set. This issue wasn't really fixed, but rather tweaked in such a way that it happens to now work. A more proper fix would require a serious rethinking of the configuration system. (Devin Matthews) - Fixed the shared library build rule in top-level Makefile. The previous rule was incorrectly only linking prerequisites that were newer than the target (`$?`) rather than correctly linking all prerequisites (`$^`). (Devin Matthews) - Fixed `cc_vendor` for crosstool-ng toolchains. (Isuru Fernando) - Allow disabling of `trsm` diagonal pre-inversion at compile time via `--disable-trsm-preinversion`. Testing: - Fixed obscure testsuite bug for the `gemmt` test module that relates to its dependency on `gemv`. - Allow the `amaxv` testsuite module to run with a dimension of 0. (Meghana Vankadari) Documentation: - Documented auto-reduction for prime numbers of threads in `docs/Multithreading.md`. - Fixed a missing `trans_t` argument in the API documentation for `her2k`/`syr2k` in `docs/BLISTypedAPI.md`. (RuQing Xu) - Removed an extra call to `free()` in the level-1v typed API example code. (Ilknur Mustafazade) ## Changes in 0.8.0 November 19, 2020 Improvements present in 0.8.0: Framework: - Implemented support for the level-3 operation `gemmt`, which performs a `gemm` on only the lower or only the upper triangle of a square matrix C. For now, only the conventional/large code path (and not the sup code path) is provided. This support also includes `gemmt` APIs in the BLAS and CBLAS compatibility layers. (AMD) - Added a C++ template header, `blis.hh`, containing a BLAS-inspired wrapper to a set of polymorphic CBLAS-like function wrappers defined in another header, `cblas.hh`. These headers are installed only when running the `install` target with `INSTALL_HH` set to `yes`. (AMD) - Disallow `randv`, `randm`, `randnv`, and `randnm` from producing vectors and matrices with 1-norms of zero. - Changed the behavior of user-initialized `rntm_t` objects so that packing of A and B is disabled by default. (Kiran Varaganti) - Transitioned to using `bool` keyword instead of the previous integer-based `bool_t` typedef. (RuQing Xu) - Updated all inline function definitions to use the cpp macro `BLIS_INLINE` instead of the `static` keyword. (Giorgos Margaritis, Devin Matthews) - Relocated `#include "cpuid.h"` directive from `bli_cpuid.h` to `bli_cpuid.c` so that applications can `#include` both `blis.h` and `cpuid.h`. (Bhaskar Nallani, Devin Matthews) - Defined `xerbla_array_()` to complement the netlib routine `xerbla_array()`. (Isuru Fernando) - Replaced the previously broken `ref99` sandbox with a simpler, functioning alternative. (Francisco Igual) - Fixed a harmless bug whereby `herk` was calling `trmm`-related code for determining the blocksize of KC in the 4th loop. Kernels: - Implemented a full set of `sgemmsup` assembly millikernels and microkernels for `haswell` kernel set. - Implemented POWER10 `sgemm` and `dgemm` microkernels. (Nicholai Tukanov) - Added two kernels (`dgemm` and `dpackm`) that employ ARM SVE vector extensions. (Guodong Xu) - Implemented explicit beta = 0 handling in the `sgemm` microkernel in `bli_gemm_armv7a_int_d4x4.c`. This omission was causing testsuite failures in the new `gemmt` testsuite module for `cortexa15` builds given that the `gemmt` correctness check relies on `gemm` with beta = 0. - Updated `void*` function arguments in reference `packm` kernels to use the native pointer type, and fixed a related dormant type bug in `bli_kernels_knl.h`. - Fixed missing `restrict` qualifier in `sgemm` microkernel prototype for `knl` kernel set header. - Added some missing n = 6 edge cases to `dgemmsup` kernels. - Fixed an erroneously disabled edge case optimization in `gemmsup` variant code. - Various bugfixes and cleanups to `dgemmsup` kernels. Build system: - Implemented runtime subconfiguration selection override via `BLIS_ARCH_TYPE`. (decandia50) - Output the python found during `configure` into the `PYTHON` variable set in `build/config.mk`. (AMD) - Added configure support for Intel oneAPI via the `CC` environment variable. (Ajay Panyala, Devin Matthews) - Use `-O2` for all framework code, potentially avoiding intermitten issues with `f2c`'ed packed and banded code. (Devin Matthews) - Tweaked `zen2` subconfiguration's cache blocksizes and registered full suite of `sgemm` and `dgemm` millikernels. - Use the `-fomit-frame-pointer` compiler optimization option in the `haswell` and `skx` subconfigurations. (Jeff Diamond, Devin Matthews) - Tweaked Makefiles in `test`, `test/3`, and `test/sup` so that running any of the usual targets without having first built BLIS results in a helpful error message. - Add support for `--complex-return=[gnu|intel]` to `configure`, which allows the user to toggle between the GNU and Intel return value conventions for functions such as `cdotc`, `cdotu`, `zdotc`, and `zdotu`. - Updates to `cortexa9`, `cortexa53` compilation flags. (Dave Love) Testing: - Added a `gemmt` module to the testsuite and a standalone test driver to the `test` directory, both of which exercise the new `gemmt` functionality. (AMD) - Support creating matrices with small or large leading dimensions in `test/sup` test drivers. - Support executing `test/sup` drivers with unpacked or packed matrices. - Added optional `numactl` usage to `test/3/runme.sh`. - Updated and/or consolidated octave scripts in `test/3` and `test/sup`. - Increased `dotxaxpyf` testsuite thresholds to avoid false `MARGINAL` results during normal execution. (nagsingh) Documentation: - Added Epyc 7742 Zen2 ("Rome") performance results (single- and multithreaded) to `Performance.md` and `PerformanceSmall.md`. (Jeff Diamond) - Documented `gemmt` APIs in `BLISObjectAPI.md` and `BLISTypedAPI.md`. (AMD) - Documented commonly-used object mutator functions in `BLISObjectAPI.md`. (Jeff Diamond) - Relocated the operation indices of `BLISObjectAPI.md` and `BLISTypedAPI.md` to appear immediately after their respective tables of contents. (Jeff Diamond) - Added missing perl prerequisite to `BuildSystem.md`. (pkubaj, Dilyn Corner) - Fixed missing `conjy` parameter in `BLISTypedAPI.md` documentation for `her2` and `syr2`. (Robert van de Geijn) - Fixed incorrect link to `shiftd` in `BLISTypedAPI.md`. (Jeff Diamond) - Mention example code at the top of `BLISObjectAPI.md` and `BLISTypedAPI.md`. - Minor updates to `README.md`, `FAQ.md`, `Multithreading.md`, and `Sandboxes.md` documents. ## Changes in 0.7.0 April 7, 2020 Improvements present in 0.7.0: Framework: - Implemented support for multithreading within the sup (skinny/small/unpacked) framework, which previously was single-threaded only. Note that this feature works harmoniously with the selective packing introduced into the sup framework in 0.6.1. (AMD) - Renamed `bli_thread_obarrier()` and `bli_thread_obroadcast()` functions to drop the 'o', which was left over from when `thrcomm_t` objects tracked both "inner" and "outer" communicators. - Fixed an obscure `int`-to-`packbuf_t` type conversion error that only affects certain C++ compilers (including g++) when compiling application code that includes the BLIS header file `blis.h`. (Ajay Panyala) - Added a missing early `return` statement in `bli_thread_partition_2x2()`, which provides a slight optimization. (Kiran Varaganti) Kernels: - Fixed the semantics of the `bli_amaxv()` kernels ('s' and 'd') within the `zen` kernel set. Previously, the kernels (incorrectly) returned the index of the last element whose absolute value was largest (in the event there were multiple of equal value); now, it (correclty) returns the index of the first of such elements. The kernels also now return the index of the first NaN, if one is encountered. (Mat Cross, Devin Matthews) Build system: - Warn the user at configure-time when hardware auto-detection returns the `generic` subconfiguration since this is probably not what they were expecting. (Devin Matthews) - Removed unnecessary sorting (and duplicate removal) on `LDFLAGS` in `common.mk`. (Isuru Fernando) - Specify the full path to the location of the dynamic library on OSX so that other dynamic libraries that depend on BLIS know where to find the library. (Satish Balay, Jed Brown) Testing: - Updated and reorganized test drivers in `test/sup` so that they work for either single-threaded or multithreaded purposes. (AMD) - Updated/optimized octave scripts in `test/sup` for use with octave 5.2.0. - Minor updates/tweaks to `test/1m4m`. Documentation: - Updated existing single-threaded sup performance graphs with new data and added multithreaded sup graphs to `docs/PerformanceSmall.md`. - Added mention of Gentoo support under the external packages section of the `README.md`. - Tweaks to `docs/Multithreading.md` that clarify that setting any `BLIS_*_NT` variable to 1 will be considered manual specification for the purposes of determining whether to auto-factorize via `BLIS_NUM_THREADS`. (AMD) ## Changes in 0.6.1 January 14, 2020 Improvements present in 0.6.1: Framework: - Added support for pre-broadcast when packing B. This causes elements of B to be repeated (broadcast) in the packed copy of B so that subsequent vector loads will result in the element already being pre-broadcast into the vector register. - Added support for selective packing to `gemmsup` (controlled via environment variables and/or the `rntm_t` object). (AMD) - Fixed a bug in `sdsdot_sub()` that redundantly added the "alpha" scalar and a separate bug in the order of typecasting intermediate products in `sdsdot_()`. (Simon Lukas Märtens, Devin Matthews) - Fixed an obscure bug in `bli_acquire_mpart_mdim()`/`bli_acquire_mpart_ndim()`. (Minh Quan Ho) - Fixed a subtle and complicated bug that only manifested via the BLAS test drivers in the `generic` subconfiguration, and possibly any other subconfiguration that did not register complex-domain `gemm` ukernels, or registered ONLY real-domain ukernels as row-preferential. (Dave Love) - Always use `sumsqv` to compute `normfv` instead of the "dot product trick" that was previously employed for performance reasons. (Roman Yurchak, Devin Matthews, and Isuru Fernando) - Fixed bug in `thrinfo_t` debugging/printing code. Kernels: - Implemented and registered an optimized `dgemm` microkernel for the `power9` kernel set. (Nicholai Tukanov) - Pacify a `restrict` warning in the `gemmtrsm4m1` reference ukernel. (Dave Love, Devin Matthews) Build system: - Fixed parsing in `vpu_count()` on some SkylakeX workstations. (Dave Love) - Reimplemented `bli_cpuid_query()` for ARM to use `stdio`-based functions instead of `popen()`. (Dave Love) - Use `-march=znver1` for clang on `zen2` subconfig. - Updated `-march` flags for `sandybridge`, `haswell` subconfigurations to use newer syntax (e.g. `haswell` instead of `core-avx2` and `sandybridge` instead of `corei7-avx`. - Correctly use `-qopenmp-simd` for reference kernels when compiling with icc. (Victor Eikjhout) - Added `-march` support for select gcc version ranges where flag syntax changes or new flags are added. The ranges we identify are: versions older than 4.9.0; versions older than 6.1.0 (but newer than 4.9.0); versions older than 9.1.0 (but newer than 6.1.0). - Use `-funsafe-math-optimizations` and `-ffp-contract=fast` for all reference kernels when using gcc or clang. - Updated MC cache blocksizes used by `haswell` subconfig. - Updated NC cache blocksizes used by `zen` subconfig. - Fixed a typo in the context registration of the `cortexa53` subconfiguration in `bli_gks.c`. (Francisco Igual) - Output a more informative error when the user manually targets a subconfiguration that configure places in the configuration blacklist. (Tze Meng Low) - Set execute bits of shared library at install-time. (Adam J. Stewart) - Added missing thread-related symbols for export to shared libraries. (Kyungmin Lee) - Removed (finally) the `attic/windows` directory since we offer Windows DLL support via AppVeyor's build artifacts, and thus that directory was only likely confusing people. Testing: - Fixed latent testsuite microkernel module bug for `power9` subconfig. (Jeff Hammond) - Added `test/1m4m` driver directory for test drivers related to the 1m paper. - Added libxsmm support to `test/sup drivers`. (Robert van de Geijn) - Updated `.travis.yml` and `do_sde.sh` to automatically accept SDE license and download SDE directly from Intel. (Devin Matthews, Jeff Hammond) - Updated standalone test drivers to iterate backwards through the specified problem space. This often helps avoid the situation whereby the CPU doesn't immediately throttle up to its maximum clock frequency, which can produce strange discontinuities (sharply rising "cliffs") in performance graphs. - Pacify an unused variable warning in `blastest/f2c/lread.c`. (Jeff Hammond) - Various other minor fixes/tweaks to test drivers. Documentation: - Added libxsmm results to `docs/PerformanceSmall.md`. - Added BLASFEO results to `docs/PerformanceSmall.md`. - Added the page size and location of the performance drivers to `docs/Performance.md` and `docs/PerformanceSmall.md`. (Dave Love) - Added notes to `docs/Multithreading.md` regarding the nuances of setting multithreading parameters the manual way vs. the automatic way. (Jérémie du Boisberranger) - Added a section on reproduction to `docs/Performance.md` and `docs/PerformanceSmall.md`. (Dave Love) - Documented Eigen `-march=native` hack in `docs/Performance.md` and `docs/PerformanceSmall.md`. (Sameer Agarwal) - Inserted multithreading links and disclaimers to `BuildSystem.md`. (Jeff Diamond) - Fixed typo in description for `bli_?axpy2v()` in `docs/BLISTypedAPI.md`. (Shmuel Levine) - Added "How to Download BLIS" section to `README.md`. (Jeff Diamond) - Various other minor documentation fixes. ## Changes in 0.6.0 June 3, 2019 Improvements present in 0.6.0: Framework: - Implemented small/skinny/unpacked (sup) framework for accelerated level-3 performance when at least one matrix dimension is small (or very small). For now, only `dgemm` is optimized, and this new implementation currently only targets Intel Haswell through Coffee Lake, and AMD Zen-based Ryzen/Epyc. (The existing kernels should extend without significant modification to Zen2-based Ryzen/Epyc once they are available.) Also, multithreaded parallelism is not yet implemented, though application-level threading should be fine. (AMD) - Changed function pointer usages of `void*` to new, typedef'ed type `void_fp`. - Allow compile-time disabling of BLAS prototypes in BLIS, in case the application already has access to prototypes. - In `bli_system.h`, define `_POSIX_C_SOURCE` to `200809L` if the macro is not already defined. This ensures that things such as pthreads are properly defined by an application that has `#include "blis.h"` but omits the definition of `_POSIX_C_SOURCE` from the command-line compiler options. (Christos Psarras) Kernels: - None. Build system: - Updated the way configure and the top-level Makefile handle installation prefixes (`prefix`, `exec_prefix`, `libdir`, `includedir`, `sharedir`) to better conform with GNU conventions. - Improved clang version detection. (Isuru Fernando) - Use pthreads on MinGW and Cygwin. (Isuru Fernando) Testing: - Added Eigen support to test drivers in `test/3`. - Fix inadvertently hidden `xerbla_()` in blastest drivers when building only shared libraries. (Isuru Fernando, M. Zhou) Documentation: - Added `docs/PerformanceSmall.md` to showcase new BLIS small/skinny `dgemm` performance on Kaby Lake and Epyc. - Added Eigen results (3.3.90) to performance graphs showcased in `docs/Performance.md`. - Added BLIS thread factorization info to `docs/Performance.md`. ## Changes in 0.5.2 March 19, 2019 Improvements present in 0.5.2: Framework: - Added support for IC loop parallelism to the `trsm` operation. - Implemented a pool-based small block allocator and a corresponding `configure` option (enabled by default), which minimizes the number of calls to `malloc()` and `free()` for the purposes of allocating small blocks (on the order of 100 bytes). These small blocks are used by internal data structures, and the repeated allocation and freeing of these structures could, perhaps, cause memory fragmentation issues in certain application circumstances. This was never reproduced and observed, however, and remains entirely theoretical. Still, the sba should be no slower, and perhaps a little faster, than repeatedly calling `malloc()` and `free()` for these internal data structures. Also, the sba was designed to be thread-safe. (AMD) - Refined and extended the output enabled by `--enable-mem-tracing`, which allows a developer to follow memory allocation and release performed by BLIS. - Initialize error messages at compile-time rather than at runtime. (Minh Quan Ho) - Fixed a potential situation whereby the multithreading parameters in a `rntm_t` object that is passed into an expert interface is ignored. - Prevent a redefinition of `ftnlen` in the `f2c_types.h` in blastest. (Jeff Diamond) Kernels: - Adjusted the cache blocksizes in the `zen` sub-configuration for `float`, `scomplex`, and `dcomplex` datatypes. The previous values, taken directly from the `haswell` subconfig, were merely meant to be reasonable placeholders until more suitable values were determined, as had already taken place for the `double` datatype. (AMD) - Rewrote reference kernels in terms of simplified indexing annotated by the `#pragma omp simd` directive, which a compiler can use to vectorize certain constant-bounded loops. The `#pragma` is disabled via a preprocessor macro layer if the compiler is found by `configure` to not support `-fopenmp-simd`. (Devin Matthews, Jeff Hammond) Build system: - Added symbol-export annotation macros to all of the function prototypes and global variable declarations for public symbols, and created a new `configure` option, `--export-shared=[public|all]`, that controls which symbols--only those that are meant to be public, or all symbols--are exported to the shared library. (Isuru Fernando) - Standardized to using `-O3` in various subconfigs, and also `-funsafe-math-optimizations` for reference kernels. (Dave Love, Jeff Hammond) - Disabled TBM, XOP, LWP instructions in all AMD subconfigs. (Devin Matthews) - Fixed issues that prevented using BLIS on GNU Hurd. (M. Zhou) - Relaxed python3 requirements to allow python 3.4 or later. Previously, python 3.5 or later was required if python3 was being used. (Dave Love) - Added `thunderx2` sub-configuration. (Devangi Parikh) - Added `power9` sub-configuration. For now, this subconfig only uses reference kernels. (Nicholai Tukanov) - Fixed an issue with `configure` failing on OSes--including certain flavors of BSD--that contain a slash '/' character in the output of `uname -s`. (Isuru Fernando, M. Zhou) Testing: - Renamed `test/3m4m` directory to `test/3`. - Lots of updates and improvements to Makefiles, shell scripts, and matlab scripts in `test/3`. Documentation: - Added a new `docs/Performance.md` document that showcases single-threaded, single-socket, and dual-socket performance results of `single`, `double`, `scomplex`, and `dcomplex` level-3 operations in BLIS, OpenBLAS, and MKL/ARMPL for Haswell, SkylakeX, ThunderX2, and Epyc hardware architectures. (Note: Other implementations such as Eigen and ATLAS may be added to these graphs in the future.) - Updated `README.md` to include new language on external packages. (Dave Love) - Updated `docs/Multithreading.md` to be more explicit about the fact that multithreading is disabled by default at configure-time, and the fact that BLIS will run executed single-threaded at runtime by default if no multithreaded specification is given. (M. Zhou) ## Changes in 0.5.1 December 18, 2018 Improvements present in 0.5.1: Framework: - Added mixed-precision support to the 1m method implementation. - Track internal scalar datatypes in the `obj_t` info bitfield. This allows slightly better handling of scalars during mixed-datatype `gemm` computation. - Fixed a bug that allowed execution of 1m with mixed-precision `gemm`, despite such usage not yet being officially supported. (Devangi Parikh) - Added missing internal calls to `bli_init_once()` in `bli_thread_set_num_threads()` and `bli_thread_set_ways()`. (Ali Emre Gülcü) Kernels: - Redefined `packm` kernels to handle edge cases and zero-filling, and updated their APIs accordingly. This was needed in order to fully support the use of non-default/non-reference packm kernels. (Devin Matthews) Build system: - Disallow explicit requests to use 64-bit integers in the BLAS API while simultaneously using 32-bit integers in the BLIS API. (Jeff Hammond, Devin Matthews) - Fixed an msys2/Windows build failure. (Isuru Fernando, Costas Yamin) - Fixed a MinGW build failure. (Isuru Fernando) - Disabled `arm32`, `arm64` configuration families since we don't yet have logic to choose the correct context at runtime. Testing: - Make sure the testsuite fails for `NaN`, `Inf` in input operands. (Devin Matthews) - Added `hemm` driver to `test/3m4m`. - Minor updates to `test/mixeddt` drivers, matlab scripts. - Added additional matlab plotting scripts to `test/3m4m`. Documentation: - Updated `docs/Multithreading.md` to include discussion of setting affinity via OpenMP. - Updated `docs/Testsuite.md` to include discussion of mixed-datatype settings. - Updated `docs/MixedDatatypes.md` to include a brief section on running the testsuite to exercise mixed-datatype functionality, and other minor updates. - Fixed broken links in `docs/KernelsHowTo.md`. (Richard Goldschmidt) - Spelling fixes in FAQ. (Rhys Ulerich) - Updated 3-clause license comment blocks to refer generically to copyright holders rather than just the original copyright holder, UT-Austin. ## Changes in 0.5.0 October 25, 2018 Improvements present in 0.5.0: Framework: - Implemented support for matrix operands of mixed datatypes (domains and precisions) within the `gemm` operation. - Added configure-time option to use slab or round-robin partitioning within JR and IR loops of most level-3 operations' macrokernels. - Allow parallelism in the JC loop for `trsm_l`, which previously was unnecessarily disabled. (Field Van Zee, Devangi Parikh) - Added Fortran-77/90-compatible APIs for some thread-related functions. (Kay Dewhurst) - Defined a new level-1d operation `shiftd`, which adds a scalar value to every element along an arbitrary diagonal of a matrix. - Patched an issue (#267) that may arise when linking against OpenMP-configured BLIS from which parallelism is requested at runtime and a level-3 operation (e.g. `gemm`) is called from within an OpenMP parallel region of an application where OpenMP nested parallelism is disabled. (Devin Matthews) Kernels: - Imported SkylakeX `dgemm` microkernel from `skx-redux` branch, which contains optimizations (mostly better prefetching on C) over the previous implementation. (Devin Matthews) - Renamed/relocated level-3 `zen` microkernels to the `haswell` kernel set. Please see a recent message to blis-devel for more information on this rename [1]. - BG/Q kernel fixes. (Ye Luo) Build system: - Added support for building Windows DLLs via AppVeyor [2], complete with a built-in implementation of pthreads for Windows, as well as an implementation of the `pthread_barrier_*()` APIs for use on OS X. (Isuru Fernando, Devin Matthews, Mathieu Poumeyrol, Matthew Honnibal) - Defined a `cortexa53` sub-configuration, which is similar to `cortexa57` except that it uses slightly different compiler flags. (Mathieu Poumeyrol) - Added python version checking to `configure` script. - Added a script to automate the regeneration of the symbols list file (now located in `build/libblis-symbols.def`). - Various tweaks in preparation for BLIS's inclusion within Debian. (M. Zhou) - Various fixes and cleanups. Testing: - Added tests for `cortexa15` and `cortexa57` in Travis CI. (Mathieu Poumeyrol) - Added tests for mixed-datatype `gemm` and the simulation of application-level threading (salt) in Travis CI. - Add statistics-collecting `irun.py` script. - Include various threading parameters in the initial comment block of testsuite output. - Various fixes and cleanups. Documentation: - Added `MixedDatatypes.md` documentation for mixed-datatype `gemm`. - Added example code demonstrating use of mixed-datatype `gemm` (object API only). - Added description of `shiftd` to `BLISTypedAPI.md` and `BLISObjectAPI.md`. - Added "Known issues" sections to `Multithreading.md` and `Sandboxes.md`. - Updated `FAQ.md`. - Various other documentation updates. [1] https://groups.google.com/forum/?fromgroups#!topic/blis-devel/pytWRjIzxVY [2] https://ci.appveyor.com/project/shpc/blis/ ## Changes in 0.4.1 August 30, 2018 Improvements present in 0.4.1: Framework: - Improved thread safety by homogenizing all critical sections to unconditionally use pthread mutexes. (AMD) - Fixed `bli_finalize()`, which had become uncallable due to sharing `pthread_once_t` objects between the initialization and finalization steps. This manifested as a rather large memory leak (many megabytes) if/when the application manually finalized BLIS in the middle of its execution. (Devangi Parikh, Field Van Zee) - Fixed a minor memory leak in the global kernel structure. (Devangi Parikh, Field Van Zee) - Replaced extensive use of function "chooser" macros in object API functions with use of a new set of functions using the suffix `_qfp()` ("query function pointer"). These functions can be used to query function pointers for most families of typed functions. - Fixed an obscure integer size bug due to improper use of integer literal constants with `va_arg()`. This oddly manifested as LP64 systems using the general stride output case of microkernels even when the output matrix storage matched that of the microkernel output preference. (Devangi Parikh, Field Van Zee) Kernels: - Fixed compilation of `armv7a` kernels. (Mathieu Poumeyrol) Build system: - Generate makefile fragments within the `obj` directory rather than in `config`, `kernels`, `ref_kernels`, and `frame`. This allows a user to perform an out-of-tree build even if the BLIS source distribution is read-only. (Devin Matthews) - Allow a dependent sub-project such as example code or the testsuite to compile and link against an installation of BLIS rather than implicitly searching for a local (uninstalled) copy. (Victor Eijkhout, Field Van Zee) - Fixed a link error that manifested after building only a shared library (e.g. `--disable-static`) and then trying to build a dependent sub-project such as example code or the testsuite. (Sajid Ali) - Changed `test` make target of top-level `Makefile` to behave more like `check` by printing a color-coded characterization of the test results. - Fixed the `-p` option to `configure`, which had likely been broken since May 7, 2018. The `--prefix` option was unaffected. (Dave Love) - Running `configure` no longer requires a C++ compiler given that a C++ compiler was only ever envisioned for *optional* use in the sandbox. (Devangi Parikh, Field Van Zee) Testing: - Added the ability to "simulate" multiple application-level threads in the testsuite by executing the individual experiments with multiple threads. This should make it easier to test for thread-safety in the future. (AMD) - Removed borderline useless wall clock time from test drivers' output. Documentation: - Updated typed and object API documents to include language on `rntm_t` parameters in the expert interfaces. - Updates to `README.md`, including language on sandboxes. - Added table of make targets to `BuildSystem.md`. - Added missing language to `ConfigurationHowTo.md` on updating the architecture string array in `bli_arch.c`. (Devangi Parikh, Field Van Zee) ## Changes in 0.4.0 July 27, 2018 Framework: - Added support for "sandboxes" for employing alternative `gemm` implementations. A ready-to-use reference C99 sandbox provides developers with a starting point for experimentation. - Separated expert, non-expert typed APIs (levels 1v, 1d, 1f, 1m, 2, and 3, and utility functions). - Defined new `rntm_t` structure and API to provide a uniform way of storing user-level threading information (equivalent of `BLIS_NUM_THREADS` and `BLIS_*_NT` environment variables), and also conveying that information to expert APIs. (Matthew Honnibal, Nathaniel Smith) - Renamed various `obj_t` accessor macros, converted to static functions, and inserted explicit typecasting to facilitate #including blis.h from a C++ application. (Jacob Gorm Hansen) - Cache and reuse `arch_t` architecture query result at runtime. (Devin Matthews) - Implemented object-based functions `bli_projm()`/`_projv()`, which project objects from one domain to another (within the same precision), and `bli_castm()`/`_castv()`, which typecast objects from one datatype to another. - Implemented object-based functions `bli_setrm()`/`_setrv()`, `bli_setim()`/`_setiv()`, which allow the caller to broadcast a scalar to all real elements or all imaginary elements within an object. - Enforce consistent datatypes in most object APIs. - For native execution, initialize a context's virtual microkernel slots to the function pointers of native microkernels. This simplifies query routines and paves the way for more generalized use of virtual microkernels beyond those for induced methods. - Various bugfixes. (Devangi Parikh) Kernels: - Re-expressed x86_64 microkernels in terms of assembly language macros, which support lower- and upper-case, AT&T and Intel syntax. (Devin Matthews) - Various bugfixes. (Robin Christ, Francisco Igual, Devangi Parikh, qnerd) Build system: - Added support for `--libdir`, `--includedir` configure options. (Nico Schlömer) - Adopted Linux-like shared library versioning and enabled building shared libraries by default. - Improved shared library handling on OS X. (Alex Arslan) - Added configure support for preset `CFLAGS`, `LDFLAGS`. (Dave Love) - Improvements to version file handling. - Implemented configure option hack for circumventing small/limited values of `ARG_MAX`. - Reorganized `cc`, `cc_vendor` detection responsibilities from `Makefile` to `configure`. (Alex Arslan) - Cross-compilation fixes. - Preliminary Windows ABI suport using `clang`, appveyor. (Isuru Fernando) - Better support for typical development environment on OpenBSD, FreeBSD. (Alex Arslan) - Bumped shared library `soname` version number to 1.0.0. - Various build system fixes and cleanups. (Mathieu Poumeyrol, Nico Schlömer, Tony Skjellum) Testing: - Rewrote Travis CI testing config file and supporting logic to use Intel's SDE emulator. This allows multiple x86_64 microarchitectures to be tested regardless of what hardware Travis happens to be using at the time. (Devin Matthews) - Added `docs/studies` hardware-specific test driver directory to track individual performance studies. (Devangi Parikh) - Streamlined `testsuite/input.operations` file format. Documentation: - Relocated all wiki documents to a `docs` directory and adjusted all links, and `README.md`, accordingly. - Added a `CONTRIBUTING.md` file to top-level directory. - Added `docs/CodingConventions.md`. - Added `docs/Sandboxes.md`. - Added `docs/BLISObjectAPI.md`. - Renamed and updated `docs/BLISTypedAPI.md`. - Updated `docs/KernelsHowTo.md`. - Updated `docs/BuildSystem.md`. (Stefanos Mavros) - Updated `docs/Multithreading.md`. - Updated indentation in `docs/ConfigurationHowTo.md` for easier reading. - Added example code for the BLIS typed API in `examples/tapi`. - Expanded existing example code for the object API in `examples/oapi`. - Added links to RHEL/Fedora and Debian packages to `README.md`. - Various cleanups. (Tony Skjellum, Dave Love, Nico Schlömer) ## Changes in 0.3.2 April 28, 2018 - Added `setijm`, `getijm` operations for updating and querying individual matrix elements via the object API. - Added `examples/oapi` directory containing a code-based tutorial on using the object-based API in BLIS. - Track separate reference kernel `CFLAGS` for each sub-configuration. - Added support for blacklisting sub-configurations based on the assembler/binutils. - Added 64-bit support to BLAS test drivers. - Various bugfixes. ## Changes in 0.3.1 April 4, 2018 - Enable use of new zen kernels in haswell sub-configuration. - Added row-storage optimizations to zen `dotxf` kernels (now also used by haswell). - Integrated an `f2c`ed version of the BLAS test drivers from netlib LAPACK into BLIS build system (e.g. `make testblas`, `make checkblas`). See the [Testsuite](Testsuite.md) document for more info. Also scheduled these BLAS drivers to execute regularly via Travis CI. - Added a new `make check` target that executes a fast version of the BLIS testsuite as well as the BLAS test drivers (primarily targeting package maintainers). - Allow individual operation overriding in the BLIS testsuite. (This makes it easy to quickly test one or two operations of interest.) - Added build system support for libmemkind. If present, `hbw_malloc()` is used as the default value for `BLIS_MALLOC_POOL` instead of `malloc()`. It can be disabled via `--disable-memkind`. - Tweaks and fixes to BLAS compatibility layer, courtesy of the new BLAS test drivers. - Output the active sub-configuration in testsuite output header. - Allow arbitrary nesting of "umbrella" configuration families in `config_registry`, allowing us to define x86_64 in terms of amd64 and intel64. - Added skx and knl to intel64 (and by proxy, x86_64) configuration families. - Implemented basic support for ARM hardware detection (via `/proc/cpuinfo`). - Various bugfixes. ## Changes in 0.3.0 February 23, 2018 This version contains significant improvements from 0.2.2. Major changes include: - Real and complex domain (s,d,c,z) assembly-based gemm microkernels for AMD's Zen microarchitecture. (AMD, Field Van Zee) - Real domain (s,d) assembly-based `gemmtrsm_l` and `gemmtrsm_u` microkernels for Zen. (AMD, Field Van Zee) - Real domain (s,d) intrinsics-based `amaxv`, `axpyv`, `dotv`, `dotxv`, `scalv`, `axpyf`, and `dotxf` kernels for Zen. (AMD, Field Van Zee) - Generalized the configuration system to allow multi-configuration builds targeting configuration "families". A single sub-configuration is chosen at runtime via some heuristic, such as querying CPUID (e.g. runtime hardware detection). This change was extensive and required a reorganization of the build system, configuration semantics, reference kernels, a new naming scheme for native kernels, and a rewrite of the global kernel structure (gks). Please see the rewritten [Configuration Guide](ConfigurationHowTo.md) for details. - Implemented runtime hardware detection for x86_64 hardware. - Reimplemented configure-time hardware detection in terms of new runtime hardware detection code, which queries for CPU features rather than individual models. - Implemented library self-initialization by rewriting `bli_init()` in terms of `pthread_once()` and inserting invocations to `bli_init()` in key places throughout BLIS. The expectation is that through normal use of any BLIS API (BLAS, typed BLIS, or object-based BLIS), the user no longer needs to explicitly initialize the library, and that `bli_finalize()` should never be called by the user unless he is absolutely sure he no longer needs BLIS functionality. Related to this: global scalar constants (`BLIS_ONE`, `BLIS_ZERO`, etc.) are now statically initialized and thus ready to use immediately. Collectively, these changes provide improved thread safety at the application level. - Compile with and install a single monolithic (flattened) `blis.h` header to (1) speed up compilation and (2) reduce the number of build product files. - Added a sub-API for setting multithreading environment variables at runtime. For a few examples, please see the [Multithreading](Multithreading.md) guide. - Reimplemented OpenMP/pthread barriers in terms of GNU atomic built-ins. - Other small changes and fixes. ## Changes in 0.2.2 May 2, 2017 - Implemented the 1m method for inducing complex matrix multiplication. (Please see ACM TOMS publication ["Implementing high-performance complex matrix multiplication via the 1m method"](https://github.com/flame/blis#citations) for more details.) - Switched to simpler `trsm_r` implementation. - Relaxed constraints that `MC % NR = 0` and `NC % MR = 0`, as this was only needed for the more sophisticated `trsm_r` implementation. - Automatic loop thread assignment. (Devin Matthews) - Updates to `.travis.yml` configuration file. (Devin Matthews) - Updates to non-default haswell microkernels. - Match storage format of the temporary micro-tiles in macrokernels to that of the microkernel storage preference for edge cases. - Added support for Intel's Knight's Landing. (Devin Matthews) - Added more flexible options to specify multithreading via the configure script. (Devin Matthews) - OS X compatibility fixes. (Devin Matthews) - Other small changes and fixes. Also, thanks to Elmar Peise, Krzysztof Drewniak, and Francisco Igual for their contributions in reporting/fixing certain bugs that were addressed in this version. ## Changes in 0.2.1 October 5, 2016 - Implemented distributed `thrinfo_t` structure management. (Ricardo Magana) - Redesigned BLIS's level-3 algorithmic control tree structure. (suggested by Tyler Smith) - Consolidated `gemm`, `herk`, and `trmm` blocked variants into one set of three bidirectional variants. - Integrated a new "memory broker" (`membrk_t`) abstraction in place of the previous memory allocator, which allows one set of pools per broker (or, in other words, per memory space). (Ricardo Magana) - Reorganized multithreading APIs, including more consistent namespace prefixes: `bli_thrinfo_*()`, `bli_thrcomm_*()`, etc. - Added `randnm`, `randnv` operations, which produce random powers of two in a narrow range, and integrated a corresponding option into the testsuite. (suggested by AMD) - Reclassified `amaxv` as a level-1v operation and kernel. - Added complex `gemm` microkernels for haswell, which have register allocations consistent with the existing 6x16 `sgemm` and 6x8 `dgemm` microkernels. - Adjusted existing microkernels to work properly when BLIS is configured to use 32-bit integers. (Devin Matthews) - Relaxed alignment constraints in sandybridge and haswell microkernels. (Devin Matthews) - Define CBLAS API with `f77_int` instead of `int`, which means the BLAS compatibility integer size is inherited by the CBLAS compatibility layer. (Devin Matthews) - Added an alignment switch to the testsuite to globally enable/disable starting address and leading dimension alignment. (suggested by Devin Matthews) - Various enhancements to configure script. (Devin Matthews) - Avoid compiling BLAS/CBLAS compatibility layer when it is disabled via configure. (suggested by Devin Matthews) - Disabled compilation of object-based blocked partitioning code for level-2 operations, as it was already functionally disabled. - Fixes and tweaks to POSIX thread support. (Tyler Smith, Jeff Hammond) - Other small changes and fixes. ## Changes in 0.2.0 April 11, 2016 Most of BLIS 0.2.0's changes are contained within a single commit, 537a1f4 (aka "the big commit"). An executive summary of the most consequential of these changes follows: - BLIS has been retrofitted with a new data structure, known as a "context," affecting virtually every internal API for every computational operation, as well as many supporting, non-computational functions that must access information within the context. - In addition to appearing within these internal APIs, the context--specifically, a pointer to a `cntx_t`--is now present within all user-level datatype-aware APIs, e.g. `bli_zgemm()`, appearing as the last argument. - User-level object APIs, e.g. `bli_gemm()`, were unaffected and continue to be "context-free." However, these APIs were duplicated so that corresponding "context-aware" APIs now also exist, differentiated with an `_ex` suffix (for "expert"). - Contexts are initialized very soon after a computational function is called (if one was not passed in by the caller) and are passed all the way down the function stack, even into the kernels, and thus allow the code at any level to query information about the runtime instantiation of the current operation being executed, such as kernel addresses, microkernel storage preferences, and cache/register blocksizes. - Contexts are thread-friendly. For example, consider the situation where a developer wishes two or more threads to execute simultaneously with somewhat different runtime parameters. Contexts also inherently promote thread-safety, such as in the event that the original source of the information stored in the context changes at run-time (see next two bullets). - BLIS now consolidates virtually all kernel/hardware information in a new "global kernel structure" (gks) API. This new API will allow the caller to initialize a context in a thread-safe manner according to the currently active kernel configuration. For now, the currently active configuration cannot be changed once the library is built. However, in the future, this API will be expanded to allow run-time management of kernels and related parameters. - The most obvious application of this new infrastructure is the run-time detection of hardware (and the implied selection of appropriate kernels). With contexts, kernels may even be "hot swapped" within the gks, and once execution begins on a level-3 operation, the memory allocator will be reinitialized on-the-fly, if necessary, to accommodate the new kernels' blocksizes. If a different application thread is executing with another (previously loaded) kernel, it will finish in a deterministic fashion because its kernel info was loaded into its context before computation began, and also because the blocks it checked out from the memory pools will be unaffected by the newer threads' reinitialization of the allocator. This version contains other changes that were committed prior to 537a1f4: - Inline assembly FMA4 microkernels for AMD bulldozer. (Etienne Sauvage) - A more feature-rich configure script and build system. Certain long-style options are now accepted, including convenient command-line switches for things like enabling debugging symbols. Important definitions were also consolidated into a new makefile fragment, `common.mk`, which can be included by the BLIS build system as well as quasi-independent build systems, such as the BLIS test suite. (Devin Matthews) - Updated and improved armv8 microkernels. (Francisco Igual) - Define `bli_clock()` in terms of `clock_gettime()` intead of `gettimeofday()`, which has been languishing on my to-do list for years, literally. (Devin Matthews) - Minor but extensive modifications to parts of the BLAS compatibility layer to avoid potential namespace conflicts with external user code when `blis.h` is included. (Devin Matthews) - Fixed a missing BLIS integer type definition (`BLIS_BLAS2BLIS_INT_TYPE_SIZE`) when CBLAS was enabled. Thanks to Tony Kelman reporting this bug. - Merged `packm_blk_var2()` into `packm_blk_var1()`. The former's functionality is used by induced methods for complex level-3 operations. (Field Van Zee) - Subtle changes to treatment of row and column strides in `bli_obj.c` that pertain to somewhat unusual use cases, in an effort to support certain situations that arise in the context of tensor computations. (Devin Matthews) - Fixed an unimplemented `beta == 0` case in the penryn (formerly "dunnington") `sgemm` microkernel. (Field Van Zee) - Enhancements to the internal memory allocator in anticipation of the context retrofit. (Field Van Zee) - Implemented so-called "quadratic" matrix partitioning for thread-level parallelism, whereby threads compute thread index ranges to produce partitions of roughly equal area (and thus computation), subject to the (register) blocksize multiple, even when given a structured rectangular subpartition with an arbitrary diagonal offset. Thanks to Devangi Parikh for reporting bugs related to this feature. (Field Van Zee) - Enabled use of Travis CI for automatic testing of github commits and pull requests. (Xianyi Zhang) - New `README.md`, written in github markdown. (Field Van Zee) - Many other minor bug fixes. Special thanks go to Lee Killough for suggesting the use of a "context" data structure in discussions that transpired years ago, during the early planning stages of BLIS, and also for suggesting such a perfectly appropriate name. ## Changes in 0.1.8 July 29, 2015 This release contains only two commits, but they are non-trivial: we now have configuration support for AMD Excavator (Carrizo) and microkernels for Intel Haswell/Broadwell. ## Changes in 0.1.7 June 19, 2015 - Replaced the static memory allocator used to manage internal packing buffers with one that dynamically allocates memory, on-demand, and then recycles the allocated blocks in a software cache, or "pool". This significantly simplifies the memory-related configuration parameter set, and it completely eliminates the need to specify a maximum number of threads. - Implemented default values for all macro constants previously found in `bli_config.h`. The default values are now set in `frame/include/bli_config_macro_defs.h`. Any value #defined in `bli_config.h` will override these defaults. - Initial support for configure-time detection of hardware. By specifying the `auto` configuration at configure-time, the configure script chooses a configuration for you. If an optimized configuration does not exist, the reference implementation serves as a fallback. - Completely reorganized implementations for complex induced methods and added support for new algorithms. - Added optimized microkernels for AMD Piledriver family of hardware. - Several bugfixes to multithreaded execution. - Various other minor tweaks, code reorganizations, and bugfixes. ## Changes in 0.1.6 October 23, 2014 - New complex domain AVX microkernels are now available and used by default by the sandybridge configuration. - Added new high-level 4m and 3m implementations presently known as "4mh" and "3mh". - Cleaned up 4m/3m front-end layering and added routines to enable, disable, and query which implementation will be called for a given level-3 operation. The test suite now prints this information in its pre-test summary. 4m (not 4mh) is still the default when complex microkernels are not present. - Consolidated control tree code and usage so that all level-3 multiplication operations use the same gemm_t structure, leaving only `trsm` to have a custom tree structure and associated code. - Re-implemented micropanel alignment, which was removed in commit c2b2ab6 earlier this year. - Relaxed the long-standing constraint that `KC` be a multiple of `MR and `NR` by allowing the developer to specify target values and then adjusting them up to the next multiple of `MR` or `NR`, as needed by the affected operations (`hemm`, `symm`, `trmm`, trsm`). - Added a new "row preference" flag that the developer can use to signal to the framework that a microkernel prefers to output micro-tiles of C that are row-stored (rather than column-stored). Column storage preference is still the default. - Changed semantics of blocksize extensions to instead be "maximum" blocksizes (and thus emphasizing the "extended" values rather than the difference). - Various other minor tweaks, code reorganizations, and bugfixes. Thanks go to those whose contributions, feedback, and bug reports led to these improvements--in particular, Tony Kelman, Kevin Locke, Devin Matthews, Tyler Smith, and perhaps others whose feedback I've lost track of. ## Changes in 0.1.5 August 4, 2014 - Added a CBLAS compatibility layer, which can be enabled at configure-time via `BLIS_ENABLE_CBLAS` in `bli_config.h`. Enabling the CBLAS layer implicitly forces the BLAS compatibility layer to also be enabled. Once enabled, the application may access CBLAS prototypes via `blis.h` or `cblas.h`. - Fixed a packing bug for cases when `MR` or `NR` (or both) are 1. - Redefined bit field macros in `bli_type_defs.h` with bitshift operator to ease future rearranging, expanding, or adding of info bits. ## Changes in 0.1.4 July 27, 2014 - Added shared library support to build system. - Preliminary parallelization of `trsm` (Tyler Smith). - Added generic `_void()` microkernel wrappers so that users (or developers) can call the microkernel without knowing the implementation/developer-specific function names, which are specified at configure-time. - Added `bli_info_*()` API for querying general information about BLIS, including blocksizes. - Reimplemented initialization/finalization for thread safety. - Fixed a possible `Inf`/`NaN` issue in several level-3 operations when beta is zero. - Minor fixes to BLAS compatibility layer. - Added initial support for Emscripten (Marat Dukhan). ## Changes in 0.1.3 June 23, 2014 This is a relatively minor release. The changes can be summarized as: - Added experimental support for PNaCL (Marat Dukhan). - Fixed aligned memory allocation on Windows (Tony Kelman). - Fixed missing version string in build products when downloading tarballs/zip files (Field Van Zee). Thanks to Victor Eijkhout for pointing out this bug. ## Changes in 0.1.2 June 2, 2014 Tyler has been hard at work developing and refining extensions to BLIS that provide multithreading support (currently via OpenMP, though POSIX threads may be supported in the future). These extensions enable multithreading within all level-3 operations except for `trsm`. We are pleased to announce that these code changes are now part of BLIS. ## Changes in 0.1.1 February 25, 2014 I. I am excited to announce that BLIS now provides high-performance complex domain support to ALL level-3 operations when ONLY the same-precision real domain equivalent gemm microkernel is present and optimized. In other words, BLIS's productivity lever just got twice as strong: optimize the `dgemm` microkernel, and you will get double-precision complex versions of all level-3 operations, for free. Same for `sgemm` microkernel and single-precision complex. II. We also now offer complex domain support based on the 3m method, but this support is ONLY accessible via separate interfaces. This separation is a safety feature, since the 3m method's numerical properties are inherently less robust. Furthermore, we think the 3m method, as implemented, is somewhat performance-limited on systems with L1 caches that have less than 8-way associativity. We plan on writing a paper on (I) and (II), so if you are curious how exactly we accomplish this, please be patient and wait for the paper. :) III. The second, user-oriented change facilitates a much more developer-friendly configuration system. This "change" actually represents a family of smaller changes. What follows is a list of those changes taken from the git log: - We now have standard names for reference kernels (levels-1v, -1f and 3) in the form of macro constants. Examples: `BLIS_SAXPYV_KERNEL_REF` `BLIS_DDOTXF_KERNEL_REF` `BLIS_ZGEMM_UKERNEL_REF` - Developers no longer have to name all datatype instances of a kernel with a common base name; [sdcz] datatype flavors of each kernel or microkernel (level-1v, -1f, or 3) may now be named independently. This means you can now, if you wish, encode the datatype-specific register blocksizes in the name of the microkernel functions. - Any datatype instances of any kernel (1v, 1f, or 3) that is left undefined in `bli_kernel.h` will default to the corresponding reference implementation. For example, if `BLIS_DGEMM_UKERNEL` is left undefined, it will be defined to be `BLIS_DGEMM_UKERNEL_REF`. - Developers no longer need to name level-1v/-1f kernels with multiple datatype chars to match the number of types the kernel WOULD take in a mixed type environment, as in `bli_dddaxpyv_opt()`. Now, one char is sufficient, as in `bli_daxpyv_opt()`. - There is no longer a need to define an obj_t wrapper to go along with your level-1v/-1f kernels. The framework now provides a `_kernel()` function, as in `bli_axpyv_kernel()`, which serves as the `obj_t` wrapper for whatever kernels are specified (or defaulted to) via `bli_kernel.h`. - Developers no longer need to prototype their kernels, and thus no longer need to include any prototyping headers from within `bli_kernel.h`. The framework now generates kernel prototypes, with the proper type signature, based on the kernel names defined (or defaulted to) via `bli_kernel.h`. - If the complex datatype x (of [cz]) implementation of the gemm microkernel is left undefined by `bli_kernel.h`, but its same-precision real domain equivalent IS defined, BLIS will enable the automatic complex domain feature described above in (1a) for the datatype x implementations of all level-3 operations, using only the corresponding real domain gemm microkernel. If the complex gemm microkernel for x IS defined, then all complex level-3 operations will be defined in terms of that microkernel. The net effect of (III) is that your `bli_kernel.h` files can be MUCH simpler and less cluttered. (Extreme example: the reference configuration's `bli_kernel.h` is now completely empty!) I have updated all configurations and kernels that are currently part of BLIS by stripping out unnecessary/outdated definitions and migrating existing definitions to their new names. (If you ever need to reference the complete list of options and macros, please refer to the `bli_kernel.h` inside the template configuration.) Please set aside some time to test and, if necessary, tweak the configurations which you originally developed and submitted. I may have broken some of them. If so, please accept my apologies and contact me for assistance. I will work with you to get them functional again. The changes mentioned in (I), (II), and (III), along with all other changes since 0.1.0, are included BLIS 0.1.1 (fde5f1fd). I know these changes may be a little disruptive to some, but I think that most developers will find the new complex functionality very useful, and the new configuration system much easier to use. ## Changes in 0.1.0 November 9, 2013 - Added `sgemm` microkernel for dunnington. - Added `dgemm` microkernels and configurations for sandybridge, bgq, mic, power7, piledriver, loonson3a, which were used to gather performance data in our second ACM TOMS paper. Many thanks to Francisco Igual, Tyler Smith, Mike Kistler, and Xianyi Zhang for developing, testing, and contributing these kernels. - Migrated to signed integer for `dim_t`, `inc_t` (to facilitate calling BLIS from Fortran). - Added "template" configuration and kernel set for developers to use as a starting point when developing new kernels from scratch. - Improvements to test suite, including section overrides and standalone level-1f/level-3 kernel modules. - Improvements to Windows build system (though it may still not yet be functional out-of-the-box). Thanks to Martin Schatz for his help here. - Removed support for element "duplication" in level-3 macrokernels. - Several bug fixes to BLAS compatibility layer. Thanks to Vladimir Sukharev for his numerous bug reports wrt the LAPACK test suite. - Various other minor bugfixes. ## Changes in 0.0.9 July 18, 2013 - A few algorithmic optimizations and bug fixes to `trmm` and `trsm`. - Parameter checking in the compatibility layer that mimics netlib BLAS. - Default use of `stdint.h` types (`int64_t`, `uint64_t` by default). - Optional (and very much untested) C99 built-in complex type/arithmetic support. Note that `bli_config.h` has changed since 0.0.8. Added configuration macros are: ``` #define BLIS_ENABLE_C99_COMPLEX #define BLIS_ENABLE_BLAS2BLIS_INT64 #define PASTEF770(name) // ... ``` The first macro enables C99 built-in complex types. The second causes a Fortran integer to be defined as an int64_t (rather than `int32_t`). The third is a macro to name-mangle a full routine name for Fortran (ie: add an underscore) and should be obtained from `config/reference/bli_config.h`. ## Changes in 0.0.8 June 12, 2013 This version includes several kernel optimizations and bug fixes. While neither `bli_config.h` nor `bli_kernel.h` has changed formats since 0.0.7, `make_defs.mk` **has** changed, so please update your copy of this file when you git-pull. Specifically, we now define a new `CFLAGS_KERNELS` variable that allows one to use different compiler flags when compiling kernels. It works like this: At compile time, make will use `CFLAGS_KERNELS` to compile any source code that resides in any directory that begins with the name `kernels`. My recommendation is to simply apply this naming convention to the symbolic link to your kernels directory that resides in your configuration directory. Thanks to Tyler for suggesting this change. ## Changes in 0.0.7 April 30, 2013 This version incorporates many small fixes and feature enhancements made during our SC13 collaboration. ## Changes in 0.0.6 April 13, 2013 Several changes regarding memory alignment were made since 0.0.5, including modifications to `bli_config.h`. Also, this update fixes a few bugs. ## Changes in 0.0.5 March 24, 2013 The most obvious change in this version is the migration to the `bli` function (and source code filename) prefix, from the old `bl2` prefix, as well as a rename of the main BLIS header (`blis2.h` -> `blis.h`). The test suite seems to indicate that the change was successful. A few other much more minor changes were made, one pertaining to a renamed constant in the `_config.h` file. ## Changes in 0.0.4 March 15, 2013 The changes included in 0.0.4 mostly relate to the contiguous (static) memory allocator. The previous implementation was intended as a temporary solution that would work for benchmarking purposes, until enough other priorities had been tended to that I could go back and do it right. I began with the assumption that the benefit of packing matrices into contiguous memory is non-negligible and worth the effort. Furthermore, we assume that: - the only portable way to acquire contiguous memory is to reserve a region of static memory and manage it ourselves; - the cache blocksizes used for one level-3 operation will be the same as those used for another level-3 operation, since all of them boil down to some form of matrix-matrix multiplication; - only three types of contiguous memory will ever be needed (for level-3 operations): a block of matrix A, a panel of matrix B, or a panel of matrix C--and the last case is not commonly used; - when a block or panel is to be acquired from the allocator, the caller knows which of the three types of memory is needed. Given these assumptions, I was able to come up with an implementation that is simple, easy to understand, and thread-safe (provided you add OpenMP directives to protect the critical sections, which are clearly marked with comments). It can also both allocate and release in O(1) time. And of course, page-alignment is taken care of behind the scenes. So while it is not a generalized solution by any means, I think it will work very well for our purposes. Also, note that based on the level of the overall matrix multiplication algorithm at which you parallelize, the minimum number of blocks/panels of each type of contiguous memory will vary. For example, if you want all of your threads to work on different iterations of a single rank-k update (via block-panel multiply), the threads share the packed panel of B, but each one needs memory to hold its own packed block of A. Thus, the memory allocator needs to be initialized so that it contains enough memory for at least one panel of B and at least t blocks of A, where t is the number of threads. All of this can be adjusted at configure-time in `bl2_config.h`. ## Changes in 0.0.3 February 22, 2013 The biggest change in this version is that the BLAS-to-BLIS compatibility layer is now available. Virtually every BLAS interface is included, even those corresponding to functionality that BLIS does not implement (such as banded and packed level-2 operations). If the application code attempts to call one of these unimplemented routines, the code aborts with a generic not-yet-implemented error message. The compatibility layer is enabled via a configuration option in `bl2_config.h`. For now, it is enabled by default (provided you have an up-to-date copy of `bl2_config.h`). ## Changes in 0.0.2 February 11, 2013 Most notably, this version contains the new test suite I've been working on for the last month. What is the test suite? It is a highly configurable test driver that allows one to test an arbitrary set of BLIS operations, with an arbitrary set of parameter combinations, and matrix/vector storage formats, as well as whichever datatypes you are interested in. (For now, only homogeneous datatyping is supported, which is what most people want.) You can also specify an arbitrary problem size range with arbitrary increments, and arbitrary ratios between dimensions (or anchor a dimension to a single value), and you can output directly to files which store the output in matlab syntax, which makes it easy to generate performance graphs. BLIS developers: note that 0.0.2 makes small changes to the configuration files. This new version also contains many bug fixes. (Most of these fixes address bugs which were found using the test suite.) ## Changes in 0.0.1 December 10, 2012 - Added auto-detection of string version (via `git`). - Wrote basic INSTALL, CHANGELOG, AUTHORS, and CREDITS files. - Updates to standalone `test` directory `Makefile`. - Added initial build system - Various code reorganizations. blis-0.9.0/docs/Sandboxes.md000066400000000000000000000254431422157504600156670ustar00rootroot00000000000000## Contents * **[Introduction](Sandboxes.md#introduction)** * **[Enabling a sandbox](Sandboxes.md#enabling-a-sandbox)** * **[Sandbox rules](Sandboxes.md#sandbox-rules)** * **[Caveats](Sandboxes.md#caveats)** * **[Known issues](Sandboxes.md#known-issues)** * **[Conclusion](Sandboxes.md#conclusion)** ## Introduction This file briefly describes the requirements for building a custom BLIS *sandbox*. Simply put, a sandbox in BLIS provides an alternative implementation to the `gemm` operation. To get a little more specific, a sandbox provides an alternative implementation to the function `bli_gemm_ex()`, which is the [expert interface](BLISObjectAPI.md##basic-vs-expert-interfaces) for calling the [object-based API](BLISObjectAPI.md#gemm) for the `gemm` operation. Why sandboxes? Sometimes you want to experiment with tweaks or changes to the `gemm` operation, but you want to do so in a simple environment rather than the highly macroized and refactored (and somewhat obfuscated) code of the core framework. By building a BLIS sandbox, you can experiment (within limits) and still benefit from BLIS's existing build system, testsuite, and toolbox of utility functions. ## Enabling a sandbox To enable a sandbox at configure-time, you simply specify it as an option to `configure`. Either of the following usages are accepted: ``` $ ./configure --enable-sandbox=gemmlike auto $ ./configure -s gemmlike auto ``` Here, we tell `configure` that we want to use the `gemmlike` sandbox, which corresponds to a sub-directory of `sandbox` named `gemmlike`. (Reminder: the `auto` argument is the configuration target and thus unrelated to sandboxes.) NOTE: Using your own sandbox implementation means that BLIS will call your sandbox for *all* problem sizes and shapes, for *all* datatypes supported by BLIS. If you intend to only implement a subset of this functionality within your sandbox, you should be sure to redirect execution back into the core framework for the parts that you don't wish to reimplement yourself. As `configure` runs, you should get output that includes lines similar to: ``` configure: configuring for alternate gemm implementation: configure: sandbox/gemmlike ``` And when you build BLIS, the last files to be compiled will be the source code in the specified sandbox: ``` Compiling obj/haswell/sandbox/gemmlike/bls_gemm.o ('haswell' CFLAGS for sandboxes) Compiling obj/haswell/sandbox/gemmlike/bls_gemm_bp_var1.o ('haswell' CFLAGS for sandboxes) ... ``` That's it! After the BLIS library is built, it will contain your chosen sandbox's implementation of `bli_gemm_ex()` instead of the default BLIS implementation. ## Sandbox rules Like any civilized sandbox, there are rules for playing here. Please follow these guidelines for the best sandbox developer experience. 1. Don't bother worrying about makefiles. We've already taken care of the boring/annoying/headache-inducing build system stuff for you. :) By configuring BLIS with a sandbox enabled, `make` will scan your sandbox directory and compile all of its source code using similar compilation rules as were used for the rest of the framework. In addition, the compilation command line will automatically contain one `-I` option for every subdirectory in your sandbox, so it doesn't matter where in your sandbox you place your header files. They will be found! 2. Your sandbox must be written in C99 or C++11. If you write your sandbox in C++11, you must use one of the BLIS-approved file extensions for your source files (`.cc`, `.cpp`, `.cxx`) and your header files (`.hh`, `.hpp`, `.hxx`). Note that `blis.h` already contains all of its definitions inside of an `extern "C"` block, so you should be able to `#include "blis.h"` from your C++11 source code without any issues. 3. All of your code to replace BLIS's default implementation of `bli_gemm_ex()` should reside in the named sandbox directory, or some directory therein. (Obviously.) For example, the "gemmlike" sandbox is located in `sandbox/gemmlike`. All of the code associated with this sandbox will be contained within `sandbox/gemmlike`. Note that you absolutely *may* include additional code and interfaces within the sandbox, if you wish -- code and interfaces that are not directly or indirectly needed for satisfying the the "contract" set forth by the sandbox (i.e., including a local definition of`bli_gemm_ex()`). 4. The *only* header file that is required of your sandbox is `bli_sandbox.h`. It must be named `bli_sandbox.h` because `blis.h` will `#include` this file when the sandbox is enabled at configure-time. That said, you will probably want to keep the file empty. Why require a file that is supposed to be empty? Well, it doesn't *have* to be empty. Anything placed in this file will be folded into the flattened (monolithic) `blis.h` at compile-time. Therefore, you should only place things (e.g. prototypes or type definitions) in `bli_sandbox.h` if those things would be needed at compile-time by: (a) the BLIS framework itself, or (b) an *application* that calls your sandbox-enabled BLIS library. Usually, neither of these situations will require any of your local definitions since those local definitions are only needed to define your sandbox implementation of `bli_gemm_ex()`, and this function is already prototyped by BLIS. *But if you are adding additional APIs and/or operations to the sandbox that are unrelated to `bli_gemm_ex()`, then you'll want to `#include` those function prototypes from within `bli_sandbox.h`* 5. Your definition of `bli_gemm_ex()` should be the **only function you define** in your sandbox that begins with `bli_`. If you define other functions that begin with `bli_`, you risk a namespace collision with existing framework functions. To guarantee safety, please prefix your locally-defined sandbox functions with another prefix. Here, in the `gemmlike` sandbox, we use the prefix `bls_`. (The `s` is for sandbox.) Also, please avoid the prefix `bla_` since that prefix is also used in BLIS for BLAS compatibility functions. If you follow these rules, you will be much more likely to have a pleasant experience integrating your BLIS sandbox into the larger framework. ## Caveats Notice that the BLIS sandbox is not all-powerful. You are more-or-less stuck working with the existing BLIS infrastructure. For example, with a BLIS sandbox you **can** do the following kinds of things: - use a different `gemm` algorithmic partitioning path than the default Goto-like algorithm; - experiment with different implementations of `packm` (not just `packm` kernels, which can already be customized within each sub-configuration); - try inlining your functions manually; - pivot away from using `obj_t` objects at higher algorithmic level (such as immediately after calling `bli_gemm_ex()`) to try to avoid some overhead; - create experimental implementations of new BLAS-like operations (provided that you also provide an implementation of `bli_gemm_ex()`). You **cannot**, however, use a sandbox to do the following kinds of things: - define new datatypes (half-precision, quad-precision, short integer, etc.) and expect the rest of BLIS to "know" how to handle them; - use a sandbox to replace the default implementation of a different level-3 operation, such as Hermitian rank-k update; - change the existing BLIS APIs (typed or object); - remove support for one or more BLIS datatypes (to cut down on library size, for example). Another important limitation is the fact that the build system currently uses "framework `CFLAGS`" when compiling the sandbox source files. These are the same `CFLAGS` used when compiling general framework source code, ``` # Example framework CFLAGS used by 'haswell' sub-configuration -O3 -Wall -Wno-unused-function -Wfatal-errors -fPIC -std=c99 -D_POSIX_C_SOURCE=200112L -I./include/haswell -I./frame/3/ -I./frame/1m/ -I./frame/1f/ -I./frame/1/ -I./frame/include -DBLIS_VERSION_STRING=\"0.3.2-51\" ``` which are likely more general-purpose than the `CFLAGS` used for, say, optimized kernels or even reference kernels. ``` # Example optimized kernel CFLAGS used by 'haswell' sub-configuration -O3 -mavx2 -mfma -mfpmath=sse -march=core-avx2 -Wall -Wno-unused-function -Wfatal-errors -fPIC -std=c99 -D_POSIX_C_SOURCE=200112L -I./include/haswell -I./frame/3/ -I./frame/1m/ -I./frame/1f/ -I./frame/1/ -I./frame/include -DBLIS_VERSION_STRING=\"0.3.2-51\" ``` (To see precisely which flags are being employed for any given file, enable verbosity at compile-time via `make V=1`.) Compiling sandboxes with these more versatile `CFLAGS` compiler options means that we only need to compile one instance of each sandbox source file, even when targeting multiple configurations (for example, via `./configure x86_64`). However, it also means that sandboxes are not ideal for microkernels, as they sometimes need additional compiler flags not included in the set used for framework `CFLAGS` in order to yield the highest performance. If you have a new microkernel you would like to use within a sandbox, you can always develop it within a sandbox. However, once it is stable and ready for use by others, it's best to formally register the kernel(s) along with a new configuration, which will allow you to specify kernel-specific compiler flags to be used when compiling your microkernel. Please see the [Configuration Guide](ConfigurationHowTo) for more details, and when in doubt, please don't be shy about seeking guidance from BLIS developers by opening a [new issue](https://github.com/flame/blis/issues) or sending a message to the [blis-devel](http://groups.google.com/d/forum/blis-devel) mailing list. Notwithstanding these limitations, hopefully you still find BLIS sandboxes useful! ## Known issues * **Mixed datatype support.** Unless you *really* know what you are doing, you should probably disable mixed datatype support when using a sandbox. (Mixed datatype support can be disabled by configuring with `--disable-mixed-dt`.) The BLIS testsuite is smart enough to verify that you've configured BLIS with mixed datatype support before allowing you to test with mixed domains/precisions enabled in `input.general`. However, if those options *are* enabled and BLIS was built with mixed datatype support, then BLIS assumes that the implementation of `gemm` will support mixing of datatypes. BLIS *must* assume this, because there's no way for it to confirm at runtime that an implementation was written to support mixing datatypes. Note that even the `gemmlike` sandbox included with BLIS does not support mixed-datatype computation. ## Conclusion If you encounter any problems, or are really bummed-out that `gemm` is the only operation for which you can provide a sandbox implementation, please open a new [issue on GitHub](https://github.com/flame/blis/issues). If you are unsure about how something works, you can still open an issue. Or, you can send a message to [blis-devel](https://groups.google.com/d/forum/blis-devel) mailing list. Happy sandboxing! blis-0.9.0/docs/Testsuite.md000066400000000000000000000735041422157504600157330ustar00rootroot00000000000000# Contents * **[Contents](Testsuite.md#contents)** * **[BLIS testsuite](Testsuite.md#blis-testsuite)** * **[Introduction](Testsuite.md#introduction)** * **[Compiling](Testsuite.md#compiling)** * **[Setting test parameters](Testsuite.md#setting-test-parameters)** * [`input.general`](Testsuite.md#inputgeneral) * [`input.operations`](Testsuite.md#inputoperations) * **[Running tests](Testsuite.md#running-tests)** * **[Interpreting the results](Testsuite.md#interpreting-the-results)** * **[BLAS test drivers](Testsuite.md#blas-test-drivers)** # BLIS testsuite ## Introduction This wiki explains how to use the test suite included with the BLIS framework. The test suite exists in the `testsuite` directory within the top-level source distribution: ``` $ ls CHANGELOG Makefile common.mk examples sandbox version CONTRIBUTING.md README.md config frame so_version windows CREDITS RELEASING config_registry kernels test INSTALL blastest configure mpi_test testsuite LICENSE build docs ref_kernels travis ``` There, you will find a `Makefile`, a script, several input files, and two directories: ``` $ cd testsuite $ ls Makefile input.general.mixed input.operations.mixed check-blistest.sh input.general.salt input.operations.salt input.general input.operations obj input.general.fast input.operations.fast src ``` As you would expect, the test suite's source code lives in `src` and the object files, upon being built, are placed in `obj`. The two `input.*` files control how the test suite runs, while the `Makefile` controls how the test suite executable is compiled and linked. However, only two input files are used at any given time: one `input.general` and one `input.operations`. (We have several pairs so that Travis CI can run multiple variations of tests automatically when new commits are made to github.) You can focus your attention on the general-purpose input files `input.general` and `input.operations`. ## Compiling Before running the test suite, you must first configure and compile BLIS. (Installing BLIS is not necessary to run the test suite, though it is supported.) For directions on how to build and install a BLIS library, please see the [Build System](BuildSystem.md) guide. Once BLIS is installed, you are ready to compile the test suite. When you are ready to compile, simply run `make` from within the `testsuite` directory. Running `make` will result in output similar to: : ``` $ make Compiling src/test_addm.c Compiling src/test_addv.c Compiling src/test_amaxv.c Compiling src/test_axpbyv.c Compiling src/test_axpy2v.c Compiling src/test_axpyf.c Compiling src/test_axpym.c Compiling src/test_axpyv.c Compiling src/test_copym.c Compiling src/test_copyv.c ``` As with compiling a BLIS library, if you are working in a multicore environment, you may use the `-j` option to compile source code in parallel with `` parallel jobs: ``` $ make -j4 ``` After `make` is complete, an executable named `test_libblis.x` is created: ``` $ ls Makefile input.general.mixed input.operations.mixed test_libblis.x check-blistest.sh input.general.salt input.operations.salt input.general input.operations obj input.general.fast input.operations.fast src ``` ### Compiling/linking aginst an installed copy of BLIS By default, the `Makefile` in the `testsuite` directory is programmed to look in `../include//` for `blis.h` and `../lib//` for the BLIS library. However, some users may wish to run the testsuite after installing BLIS and deleting the entire source tree. In this situation, it is necessary to point `make` to the location of your BLIS installation (i.e., the installation prefix). If you would like to compile with an installed header and link against an installed library, you have two options: 1. First, you may set the envrionment variable `BLIS_INSTALL_PATH` to the install prefix used when BLIS was installed, and then run `make`. In this example, we assume that BLIS was installed after running the `configure` script with the `--prefix=/usr/local` option. ``` $ export BLIS_INSTALL_PATH=/usr/local $ make ``` 2. Alternatively, you may set the `make` variable `BLIS_INSTALL_PATH` on the command line as you execute `make`: ``` $ make BLIS_INSTALL_PATH=/usr/local ``` Both options result in the same outcome: `make` looks for the BLIS installation in `BLIS_INSTALL_PATH` when building the test suite. ## Setting test parameters The BLIS test suite reads two input files, `input.general` and `input.operations`, to determine which tests to run and how those tests are run. Each file is contains comments and thus you may find them intuitive to use without formal instructions. However, for completeness and as a reference-of-last-resort, we describe each file and its contents in detail. ### `input.general` The `input.general` input file, as its name suggests, contains parameters that control the general behavior of the test suite. These parameters (more or less) apply to all operations that get tested. Below is a representative example of the default contents of `input.general`. ``` # ---------------------------------------------------------------------- # # input.general # BLIS test suite # # This file contains input values that control how BLIS operations are # tested. Comments explain the purpose of each parameter as well as # accepted values. # 1 # Number of repeats per experiment (best result is reported) c # Matrix storage scheme(s) to test: # 'c' = col-major storage; 'g' = general stride storage; # 'r' = row-major storage c # Vector storage scheme(s) to test: # 'c' = colvec / unit stride; 'j' = colvec / non-unit stride; # 'r' = rowvec / unit stride; 'i' = rowvec / non-unit stride 0 # Test all combinations of storage schemes? 1 # Perform all tests with alignment? # '0' = do NOT align buffers/ldims; '1' = align buffers/ldims 0 # Randomize vectors and matrices using: # '0' = real values on [-1,1]; # '1' = powers of 2 in narrow precision range 32 # General stride spacing (for cases when testing general stride) sdcz # Datatype(s) to test: # 's' = single real; 'c' = single complex; # 'd' = double real; 'z' = double complex 0 # Test gemm with mixed-domain operands? 0 # Test gemm with mixed-precision operands? 100 # Problem size: first to test 300 # Problem size: maximum to test 100 # Problem size: increment between experiments # Complex level-3 implementations to test 1 # 1m ('1' = enable; '0' = disable) 1 # native ('1' = enable; '0' = disable) 1 # Simulate application-level threading: # '1' = disable / use one testsuite thread; # 'n' = enable and use n testsuite threads 1 # Error-checking level: # '0' = disable error checking; '1' = full error checking i # Reaction to test failure: # 'i' = ignore; 's' = sleep() and continue; 'a' = abort 0 # Output results in matlab/octave format? ('1' = yes; '0' = no) 0 # Output results to stdout AND files? ('1' = yes; '0' = no) ``` The remainder of this section explains each parameter switch in detail. _**Number of repeats.**_ This is the number of times an operation is run for each result that is reported. The result with the best performance is reported. _**Matrix storage scheme.**_ This string encodes all of the matrix storage schemes that are tested (for operations that contain matrix operands). There are three valid values: `'c'` for column storage, `'r'` for row storage, and `'g'` for general stride storage. You may choose one storage scheme, or combine more than one. The order of the characters determines the order in which the corresponding storage schemes are tested. _**Vector storage scheme.**_ Similar to the matrix storage scheme string, this string determines which vector storage schemes are tested (for operations that contain vector operands). There are four valid values: `'c'` for column vectors with unit stride, `'r'` for row vectors with unit stride, `'j'` for column vectors with non-unit stride, and `'i'` for row vectors with non-unit stride. You may choose any one storage scheme, or combine more than one. The ordering behaves similarly to that of the matrix storage scheme string. Using `cj` will test both unit and non-unit vector strides, and since row and column vectors are logically equivalent, this should provide complete test coverage for operations with vector operands. _**Test all combinations of storage schemes?**_ Enabling this option causes all combinations of storage schemes to be tested. For example, if the option is disabled, a matrix storage scheme string of `cr` would cause the `gemm` test module to test execution where all matrix operands are column-stored, and then where all matrix operands are row-stored. Enabling this option with the same matrix storage string (`cr`) would cause the test suite to test `gemm` under all eight scenarios where the three `gemm` matrix operands are either column-stored or row-stored. _**Perform all tests with alignment?**_ Disabling this option causes the leading dimension (row or column stride) of test matrices to **not** be aligned according to `BLIS_HEAP_STRIDE_ALIGN_SIZE`, which defaults to `BLIS_SIMD_ALIGN_SIZE`, which defaults to `BLIS_SIMD_MAX_SIZE`, which defaults to 64 (bytes). (If any of these values is set to a non-default value, it would be in `bli_family_.h` where `` is the configuration family.) Sometimes it's useful to disable leading dimension alignment in order to test certain aspects of BLIS that need to handle computing with unaligned user data, such as level-1v and level-1f kernels. _**Randomize vectors and matrices.**_ The default randomization method uses real values on the interval [-1,1]. However, we offer an alternate randomization using powers of two in a narrow precision range, which is more likely to result in test residuals exactly equal to zero. This method is somewhat niche/experimental and most people should use random values on the [-1,1] interval. _**General stride spacing.**_ This value determines the simulated "inner" stride when testing general stride storage. For simplicity, the test suite always generates and tests general stride storage that is ["column-tilted"](FAQ.md#What_does_it_mean_when_a_matrix_with_general_stride_is_column-ti). If general stride storage is not being tested, then this value is ignored. _**Datatype(s) to test.**_ This string determines which floating-point datatypes are tested. There are four valid values: `'s'` for single-precision real, `'d'` for double-precision real, `'c'` for single-precision complex, and `'z'` for double-precision complex. You may choose one datatype, or combine more than one. The order of the datatype characters determines the order in which they are tested. _**Test gemm with mixed-domain operands?**_ This boolean determines whether `gemm` tests are performed that exercise the mixed-domain functionality within BLIS. (In other words, with precision held constant, all combinations of real and complex matrix operands will be tested.) If this option is set to 1 and the mixed-precision option is set to 0, then domain combinations will be varied for the precisions represented by the "Datatype(s) to test" option. If this option and the mixed-precision option are both set to 1, then _all_ datatype combinations will be tested, regardless of the datatypes indicated by the "Datatype(s) to test" option. _**Test gemm with mixed-precision operands?**_ This boolean determines whether `gemm` tests are performed that exercise the mixed-precision functionality within BLIS. (In other words, with domain held constant, all combinations of supported precisions will be tested.) If this option is set to 1 and the mixed-domain option is set to 0, then precision combinations will be varied for the domains represented by the "Datatype(s) to test" option. If this option and the mixed-domain option are both set to 1, then _all_ datatype combinations will be tested, regardless of the datatypes indicated by the "Datatype(s) to test" option. _**Problem size.**_ These values determine the first problem size to test, the maximum problem size to test, and the increment between problem sizes. Note that the maximum problem size only bounds the range of problem sizes; it is not guaranteed to be tested. Example: If the initial problem size is 128, the maximum is 1000, and the increment is 64, then the last problem size to be tested will be 960. _**Complex level-3 implementations to test.**_ This section lists which complex domain implementations of level-3 operations are tested. If you don't know what these are, you can ignore them. The `native` switch corresponds to native execution of complex domain level-3 operations, which we test by default. We also test the `1m` method, since it is the induced method of choice when optimized complex microkernels are not available. Note that all of these induced method tests (including `native`) are automatically disabled if the `c` and `z` datatypes are disabled. _**Simulate application-level threading.**_ This setting specifies the number of threads the testsuite will spawn, and is meant to allow the user to exercise BLIS as a multithreaded application might if it were to make multiple concurrent calls to BLIS operations. (Note that the threading controlled by this option is orthogonal to, and has no effect on, whatever multithreading may be employed _within_ BLIS, as specified by the environment variables described in the [Multithreading](Multithreading.md) documentation.) When this option is set to 1, the testsuite is run with only one thread. When set to n > 1 threads, the spawned threads will parallelize (in round-robin fashion) the total set of tests specified by the testsuite input files, executing them in roughly the same order as that of a sequential execution. _**Error-checking level.**_ BLIS supports various "levels" of error checking prior to executing most operations. For now, only two error-checking levels are implemented: fully disabled (`'0'`) and fully enabled (`'1'`). Disabling error-checking may improve performance on some systems for small problem sizes, but generally speaking the cost is negligible. _**Reaction to test failure.**_ If the test suite executes a test that results in a numerical result that is considered a "failure", this character determines how the test suite should proceed. There are three valid values: `'i'` will cause the test suite to ignore the failure and immediately continue with all remaining tests, `'s'` will cause the test suite to sleep for some short period of time before continuing, and `'a'` will cause the test suite to abort all remaining tests. The user must specify only **one** option via its character encoding. _**Output results in Matlab/Octave format?**_ When this option is disabled, the test suite outputs results in a simple human-readable format of one experiment per line. When this option is enabled, the test suite similarly outputs results for one experiment per line, but in a format that may be read into Matlab or Octave. This is useful if the user intends to use the results of the test suite to plot performance data using one of these tools. _**Output results to `stdout` AND files?**_ When this option is disabled, the test suite outputs only to standard output. When enabled, the test suite also writes its output to files, one for each operation tested. As with the Matlab/Octave option above, this option may be useful to some users who wish to gather and retain performance data for later use. ### `input.operations` The `input.operations` input file determines **which** operations are tested, which parameter combinations are tested, and the relative sizes of the operation's dimensions. The file itself contains comments that explain various sections. However, we reproduce this information here for your convenience. _**Enabling/disabling entire sections.**_ The values in the "Section overrides" section allow you to disable all operations in a given "level". Enabling a level here by itself does not enable every operation in that level; it simply means that the individual switches for each operation (in that level) determine whether or not the tests are executed. Use 1 to enable a section, or 0 to disable. _**Enabling/disabling individual operation tests.**_ Given that an operation's section override switch is set to 1 (enabled), whether or not that operation will get tested is determined by its local switch. For example, if the level-1v section override is set to 1, and there is a 1 on the line marked `addv`, then the `addv` operation will be tested. NOTE: You may ignore the lines marked "test sequential front-end." These lines are for future use, to distinguish tests of the sequential implementation from tests of the multithreaded implementation. For now, BLIS does not contain separate APIs for multithreaded execution, even though multithreading is supported. So, these should be left set to 1. _**Enabling only select operations**_ If you would like to enable just a few (or even just one) operation without adjusting any section overrides (or individual operation switches), change the desired operation switch(es) to 2. This will cause any operation that is not set to 2 to be disabled, regardless of section override values. For example, setting the `axpyv` and `gemv` operation switches to 2 will cause the test suite to test ONLY `axpyv` and `gemv`, even if all other sections and operations are set to 1. NOTE: As long as there is at least on operation switch set to 2, no other operations will be tested. When you are done testing your select operations, you should revert the operation switch(es) back to 1. _**Changing the problem size/shapes tested.**_ The problem sizes tested by an operation are determined by the dimension specifiers on the line marked `dimensions: `. If, for example, `` contains two dimension labels (e.g. `m n`), then the line should begin with two dimension specifiers. Dimension specifiers of `-1` cause the corresponding dimension to be bound to the problem size, which is determined by values set in `input.general`. Positive values cause the corresponding dimension to be fixed to that value and held constant. Examples of dimension specifiers (where the dimensions are _m_ and _n_): * `-1 -1 ` ...Dimensions m and n grow with problem size (resulting in square matrices). * `-1 150 ` ...Dimension m grows with problem size and n is fixed at 150. * `-1 -2 ` ...Dimension m grows with problem size and n grows proportional to half the problem size. _**Changing parameter combinations tested.**_ The parameter combinations tested by an operation are determined by the parameter specifier characters on the line marked `parameters: `. If, for example, `` contains two parameter labels (e.g. `transa conjx`), then the line should contain two parameter specifier characters. The `'?'` specifier character serves as a wildcard--it causes all possible values of that parameter to be tested. A character such as `'n'` or `'t'` causes only that value to be tested. Examples of parameter specifiers (where the parameters are `transa` and `conjx`): * `??` ...All combinations of the `transa` and `conjx` parameters are tested: `nn, nc, tn, tc, cn, cc, hn, hc`. * `?n` ...`conjx` is fixed to "no conjugate" but `transa` is allowed to vary: `nn, tn, cn, hn`. * `hc` ...Only the case where `transa` is "Hermitian-transpose" and `conjx` is "conjugate" is tested. Here is a full list of the parameter types used by the various BLIS operations along with their possible character encodings: * `side`: `l` = left, `r` = right * `uplo`: `l` = lower-stored, `u` = upper-stored * `trans`: `n` = no transpose, `t` = transpose, `c` = conjugate, `h` = Hermitian-transpose (conjugate-transpose) * `conj`: `n` = no conjugate, `c` = conjugate * `diag`: `n` = non-unit diagonal, `u` = unit diagonal ## Running tests Running the test suite is easy. Once `input.general` and `input.operations` have been tailored to your liking, simply run the test suit executable: ``` $ ./test_libblis.x ``` For sanity-checking purposes, the test suite begins by echoing the parameters it found in `input.general` to standard output. This is useful when troubleshooting the test suite if/when it exhibits strange behavior (such as seemingly skipped tests). ## Interpreting the results The output to the test suite is more-or-less intuitive. Here is an snippet of output for the `gemm` test module when problem sizes of 100 to 300 in increments of 100 are tested. ``` % --- gemm --- % % test gemm seq front-end? 1 % gemm m n k -1 -1 -2 % gemm operand params ?? % % blis_
__ m n k gflops resid result blis_sgemm_nn_ccc 100 100 50 1.447 1.14e-07 PASS blis_sgemm_nn_ccc 200 200 100 1.537 1.18e-07 PASS blis_sgemm_nn_ccc 300 300 150 1.532 1.38e-07 PASS blis_sgemm_nc_ccc 100 100 50 1.449 7.79e-08 PASS blis_sgemm_nc_ccc 200 200 100 1.540 1.23e-07 PASS blis_sgemm_nc_ccc 300 300 150 1.537 1.54e-07 PASS blis_sgemm_nt_ccc 100 100 50 1.479 7.40e-08 PASS blis_sgemm_nt_ccc 200 200 100 1.549 1.33e-07 PASS blis_sgemm_nt_ccc 300 300 150 1.534 1.44e-07 PASS blis_sgemm_nh_ccc 100 100 50 1.477 9.23e-08 PASS blis_sgemm_nh_ccc 200 200 100 1.547 1.13e-07 PASS blis_sgemm_nh_ccc 300 300 150 1.535 1.51e-07 PASS blis_sgemm_cn_ccc 100 100 50 1.477 9.62e-08 PASS blis_sgemm_cn_ccc 200 200 100 1.548 1.36e-07 PASS blis_sgemm_cn_ccc 300 300 150 1.539 1.51e-07 PASS blis_sgemm_cc_ccc 100 100 50 1.481 8.66e-08 PASS blis_sgemm_cc_ccc 200 200 100 1.549 1.41e-07 PASS blis_sgemm_cc_ccc 300 300 150 1.539 1.63e-07 PASS blis_sgemm_ct_ccc 100 100 50 1.484 7.09e-08 PASS blis_sgemm_ct_ccc 200 200 100 1.549 1.08e-07 PASS blis_sgemm_ct_ccc 300 300 150 1.539 1.33e-07 PASS blis_sgemm_ch_ccc 100 100 50 1.471 8.06e-08 PASS blis_sgemm_ch_ccc 200 200 100 1.546 1.24e-07 PASS blis_sgemm_ch_ccc 300 300 150 1.539 1.66e-07 PASS ``` Before each operation is tested, the test suite echos information it obtained from the `input.operations` file, such as the dimension specifier string (in this case, `"-1 -1 -2"`) and parameter specifier string (`"??"`). Each line of output contains several sections. We will cover them now, from left to right. _**Test identifier.**_ The left-most labels are strings which identify the specific test being performed. This string generally a concatenation of substrings, joined by underscores, which identify the operation being run, the parameter combination tested, and the storage scheme of each operand. When outputting to Matlab/Octave formatting is abled, these identifiers service as the names of the arrays in which the data are stored. _**Dimensions.**_ The values near the middle of the output show the size of each dimension. Different operations have different dimension sets. For example, `gemv` only has two dimensions, _m_ and _n_, while `gemm` has an additional _k_ dimension. In the snippet above, you can see that the dimension specifier string, `"-1 -1 -2"`, explains the relative sizes of the dimensions for each test: _m_ and _n_ are bound to the problem size, while _k_ is always equal to half the problem size. _**Performance.**_ The next value output is raw performance, reported in GFLOPS (billions of floating-point operations per second). _**Residual.**_ The next value, which we loosely refer to as a "residual", reports the result of the numerical correctness test for the operation. The actual method of computing the residual (and hence its exact meaning) depends on the operation being tested. However, these residuals are always computed such that the result should be no more than 2-3 orders of magnitude away from machine precision for the datatype being tested. Thus, "good" results are typically in the neighborhood of `5e-06` for single precision and `1e-16` for double precision (preferrably less). _**Test result.**_ The BLIS test suite compares the residual to internally-defined accuracy thresholds to categorize the test as either `PASS`, `MARGINAL`, or `FAIL`. The vast majority of tests should result in a `PASS` result, with perhaps a handful resulting in `MARGINAL`. Usually, a `MARGINAL` result is no cause for concern, especially when similar tests result in `PASS`. Note that the various sections of output, which line up nicely as columns, are labeled on a line beginning with `%` immediately before the results: ``` % blis_
__ m n k gflops resid result blis_sgemm_nn_ccc 100 100 50 1.447 1.14e-07 PASS ``` These labels are useful as concise reminders of the meaning of each column. They are especially useful in differentiating the various dimensions from each other for operations that contain two or three dimensions. If you simply want to run the BLIS testsuite and know if there were any failures, you can do so via the `make check` and `make check-fast`. The former uses the `input.general` and `input.operations` files, while the latter uses the `input.general.fast` and `input.operations.fast`. (We generally recommend using the "fast" target since it usually finishes in much less time while still being relatively comprehensive.) A one-line characterization of the test results is output after the tests finish: ``` $ make check-fast Running test_libblis.x (fast) with output redirected to 'output.testsuite' check-blistest.sh: All BLIS tests passed! ``` # BLAS test drivers In addition to the monolithic testsuite located in the `testsuite` directory, which exercises BLIS functionality in general (and via one of its native/preferred APIs), we also provide a C port of the netlib BLAS test drivers included in netlib LAPACK. These BLAS drivers are located in `blastest`, along with other files needed in order to build the drivers, such as a subset of `libf2c`. After configuring and compiling BLIS, the BLAS test drivers may be run from within `blastest`: ``` $ ./configure haswell # Lots of configure output... $ make -j4 # Lots of compilation output... $ cd blastest $ ls Makefile f2c input obj src ``` Simply run `make`: ``` $ make Compiling obj/abs.o Compiling obj/acos.o Compiling obj/asin.o Compiling obj/atan.o ... Compiling obj/wsfe.o Compiling obj/wsle.o Archiving libf2c.a Compiling obj/cblat1.o Linking cblat1.x against 'libf2c.a ../lib/haswell/libblis.a -lm -lpthread -lrt' Compiling obj/cblat2.o Linking cblat2.x against 'libf2c.a ../lib/haswell/libblis.a -lm -lpthread -lrt' Compiling obj/cblat3.o Linking cblat3.x against 'libf2c.a ../lib/haswell/libblis.a -lm -lpthread -lrt' ... ``` And then `make run`: ``` Running cblat1.x > 'out.cblat1' Running cblat2.x < 'input/cblat2.in' (output to 'out.cblat2') Running cblat3.x < 'input/cblat3.in' (output to 'out.cblat3') Running dblat1.x > 'out.dblat1' Running dblat2.x < 'input/dblat2.in' (output to 'out.dblat2') Running dblat3.x < 'input/dblat3.in' (output to 'out.dblat3') Running sblat1.x > 'out.sblat1' Running sblat2.x < 'input/sblat2.in' (output to 'out.sblat2') Running sblat3.x < 'input/sblat3.in' (output to 'out.sblat3') Running zblat1.x > 'out.zblat1' Running zblat2.x < 'input/zblat2.in' (output to 'out.zblat2') Running zblat3.x < 'input/zblat3.in' (output to 'out.zblat3') ``` The results can quickly be checked via a script in the top-level `build` directory: ``` $ ../build/check-blastest.sh All BLAS tests passed! ``` This is the message we expect when everything works as expected. You can also combine the `make`, `make run`, and script execution into one command: `make check`. Alternatively, you can execute all of the steps described above (`make ; make run; ../build/check-blastest.sh`, or `make check`) from the top-level directory. After running `configure` and `make`, simply run `make checkblas`: ``` $ ./configure haswell # Lots of configure output... $ make -j4 # Lots of compilation output... $ make check ``` This will build all of the necessary BLAS test driver object files, link them, and run the drivers. Output will go to the current directory (either the top-level directory of the source distribution, or the out-of-tree build directory from which you ran `configure`), with each output file (prefixed with `out.`) named according to the BLAS driver that generated its contents: ``` $ ls CHANGELOG blastest docs out.cblat1 out.sblat3 testsuite CONTRIBUTING.md bli_config.h examples out.cblat2 out.zblat1 travis CREDITS build frame out.cblat3 out.zblat2 version INSTALL common.mk include out.dblat1 out.zblat3 windows LICENSE config kernels out.dblat2 ref_kernels Makefile config.mk lib out.dblat3 sandbox README.md config_registry mpi_test out.sblat1 so_version RELEASING configure obj out.sblat2 test ``` If any of the tests fail, you'll instead see the message: ``` $ make check At least one BLAS test failed. Please see out.* files for details. ``` As the message suggests, you should inspect the `out.*` files for more details about what went wrong. blis-0.9.0/docs/graphs/000077500000000000000000000000001422157504600146735ustar00rootroot00000000000000blis-0.9.0/docs/graphs/large/000077500000000000000000000000001422157504600157655ustar00rootroot00000000000000blis-0.9.0/docs/graphs/large/l3_perf_a64fx_jc1ic1jr12_nt12.pdf000066400000000000000000000375571422157504600235400ustar00rootroot00000000000000%PDF-1.4 %¡³Å× 2 0 obj <>stream xœÍ}M¯,ÉqÝ_¹Kjñ®*¿3^X€$X `YÀ A+’‹eˆ” X¿ÞçDEvß™y|—²áMu÷ÍʪÊS'>NüË[¨ù=§ð6b{ óÿÞC~û2BûݯßþçÛ?¿…·ïßþåízoy´Rß®ù¿/ó¨løËß®/Bîñ-ĘåÿáíÌÿ½ôç_ó‡­¾Å^ÞâUÞ¾Ä+òO¯yÞk^ËxûË·øöWs¿™ÇUþ¯½ýûWü/óÖ´xLó·ëd×Û?½ýb]âý¶!cêïqÄ“Cr–þª¯·sü‘ÿì;<ü¹æØF_ƒÇ2æ?ã­öööÝoßþô/æ°õ]ÖÆwÿðöw? ãºþäKý}Äñ³ÔçÑß÷Woþݶ®^[D—®×o¼=íi}¿¿¶ÀcHï±¶s†ÞKʇ|ºy_^îñŠ_ò隇üéE~å÷Pû[»Ê{šÇO ýgן|÷›·/¡¼µðÞRzûîWo?+}®õ)þâÎZzÏqž$Œ÷÷$;Oò—ñóÿþ7¿øÓ_þŸßýZÇøþ£¹Öú^J~ë-¾Ç?˜ëï¿ÿõo+,Î7úûõM/ó>ošÜà÷:ß!vsóû5æEË›eÞàþæQs*ó(DùôË|eyÅ„úžæaoï½ÏÃx½g9ìï×:ÌïE£ü8öyž9ð5'%c¥øÞÖñ|$AŽë{—ã(—0sЃK¾ÌEg5Ç2Xk^aÞÜK¦YÒš˜Wù~¾ief!ÏK”¹Ô°¦dy7Ô²æò|d2~:¹\ßç úŸÞæ£l8®ò}k:¹Rä¼ó¶Ì¨_ùy¯:½9,_K§W¢NdÞª½j;û—o®·úö÷óàWÓ¬úÍü⯿ ~sø8—èüæ}®7üæ¥Ýð›ˆmá†ß¼”Toø…+ë}þÆþÊ{oó‘v‡¿ùþ^×»ð'ïM¿Pt©s™^Íá/´÷ìñw ñ7íhóûèñçïšÃßœÌZ‰Ä_œ8I7þäd‡¿yÉ¡8üÍé¬5Dü "šÃß„LÝð Öñ7ѺÇß|‡ òŠªfºè€¿¹ôèñ. œW‡ <«î(¿(€óŠ7pÞÅ81šàüEk€s>)åëî˜`HÃ#Ó…+#ç·è8Çз8Ÿ^8ïxß(¿è€sŒõV*v€ý-Mä%`ð›°7—ü|??`/5€b¯'ÝÜ€=Y):ߊK®ú숾ùy 7úärÖ üæ#^ß~Ó¶~åÒç¸à7÷‹µ”¿ £1üäÕü Ö3á7/_·»`¯íî·¿ »^üÄ‚I~s¥ ¿ùwëÝøÍ••£ƒß Q·ôiý¤¨D&ÁþÉ2žìô°€JÕãÅI§ Te¼<ÏnAWYƒ4d¼œ•‹Ì÷Ô%ãå®v^W¬7½:1¥»ú±\k D©Â$*QÉÆâúÓ(Z³ZfË,jÇàö½ëïÕöç:RÞ0oSÀp—Z?a= 9¿ºÉæÒHkÀçÀ$ðò8n·Ø´”>E¸Å¦‘Ô¢ÎáÊ0“ÖC™¿Èt­­§RiàæKKm°ûçýRÒÔÔ”¶Ì$màíQŸL%o/Uxµ”È_úlæ¢W¯a%K"S¯]ŸNƒ£EhÉþ¡' ƒµ‘‚> û“^À.‡.ÈЇ>¢ù2”‘ô™ÿm4}HòA^K:èSjÑ{×~ˆÜ›ƒHœDkzOH,úx‰Ó¦‹M~åa‰< HÌ]¹8Ó"ÕbïçªZO0œ‡­Ü(œVo,7¿—]ñÁ‰´ÚoV,qP¾m7þ*Üð€Ÿàv£Oe¾ÁWáSöæs¹¡' ¡ÞÈnà5P™…;q(4»ù¥. NHqt ›Ç±;ÌÍŘHJäÎ ]mq ñN~ßÞæïAÜn ïP¢MØnq`kttkó{½@m+)Òdüî€6¯/‡³¹ôt>€Y«ðÍe$ kˆgcÝ<Ú ±ù3½_@Ø|^ºl°y¼^ÚÄWOŠÈ3d¥Îkùt²Â“!2Ø)²"q½Ãd¥_á4Yá,‘Îñ²RçºÍá§’ Ž’•§eô½è…çF{^⯘Ùk´£dEF›ð$Gø„ vŠ›Lca…i‰¹]DY—G‡ÔYã&œã+ܤ¹¿†™äCÌäi½Ä%¦eP÷¼Â_1ª×hG©‰Œx–š<ßÀ׈„Žw–œ¬1_g'= ˆÇÙɵR=;ù×߉¥Œ¹µ’¤ôh# õužD¸¼ÕFš›ÒiÖ^]¬€T;r"ÕFšÜÚya#uäÖÁFêȾ„4 å†Ô‘^ iTä” ŠreýšQ”«Z&ɲ…%Jn;i™õÎPZŒã¶”V¶á¸M¥•0o[iEqâm,­¬>çÉ[e}Ož"7ØGQ$Á:;ž’’æ _šL5ëFYoFOTä¦ma”i¯©N¢2í ýzר°Z_(­Lu¥œ³ PR½VU4ÕQˆ{ŠR-&ÒU®à”oLÍçºh@•༨`PM–ë‹´¤B,Tâhp Ê¨¢` ,G€JìúqƒªD OfÍ[ * ÖUAm@5×Ev•É5!›-®ÿVLj‚ª¶­(¹Á˜¨*M*Iõò% hÕ4uT²Â<¨‹«ªU]NPÍg}%r¬A¨·Àލ¤˃Š~‚ªG‚LAÕYÂPõ^Põ´W@Î;Ò¬«“TóÇÑ—?vVmT½15KA5Óp+@5XP –ºÕàë Aß¿ÕüûqŽtÌë,íútq9ÇŽ0ÇJµŸ‹º+ÛäΨÃ’³Ü.ûˆ<ÌøÕú0¹-<üñ$bžníK1çF{Zå/*º” õͧ¨Á0Ï·]Œ§è‹q¾ªz‡|z¯ Ä<ÝÂׇ|º‰¯ùt¿YÆ&Ë^ño2$Æ´<„ÚDÐ÷Q~þ¨þ ¬äTÍÏÊŽxIÖ&Ì}®Šs±$kó«“²6EŒ g]XÕ¼Qƒ±$lÁj0ÎþråÆƒ9lÔÕÊyHÃJÈÃbØlÆJñÂ6RìHÅJÌÉŦES¼°F.;ˈI±²¿@†‚•ýâYí·í(Jž‘Éæ·Ê~|o•ý(ÒEeÿ&xaÂd ÛãÜÂ6ÝWöÏÓ)—2aV ›°M&ûBe½Xƒ`‹8‡7aÂâu ÛP±‚•ýbæUgOÊ/"Ù*v‹rÉÔl•ý•z¦lSÕ0e›¢iƒ·²MeeEê Uö7z³U€ Á4e« ²Íß+ûk$C˘f†KÝ”m¬•ý…NsS¶IZ—b•ý|ÈŸ£lS&ºž[Âs‡²MÛ(›\fº(~xGÙäîÄ€ý²¸ÅD®Í2Wnr”­;?Ȳ½ô—ÅùA:%¤y½o”­7‹×®)5Ëk[6~ÒÀP7@9ºùíJ„ææ4äæQtZ¼ €ŒeN*…nƒ™W@Û€& Á6›G¬ p>Bm\Œ')Ò$´ÁT_à¬u„S3Ų1# ¼Ó¶‘ª ˆÉøÅ!l@"…“qõ´-:Q€ÁŠ kÎ]NÚ†”F£mp&mCÜh[d¬Èh[ðŠYo¤m/3Ú†dæãj5eyež•¢àP< 8éÑ¡JÒˆuÞ&ÿ: I‰½šßÓ †Å=Mž°W«É„ÒÚÓˆj{Ú°Tmª¡­¡íið©Ùž–õ}n{ܶ§ }+ڞƒ¶d/¸uëmO &¦X[׸°k Ùíiœ{Ú|Õ)m¬­bS«uæ÷´ùAßÄ¢æŒ6Å C_ý&ÖÖ¸‡aO³È=­#öj{ZãÜÓ¨if{Zßñ¶~ÑüžfWÛÓXëjj5tµØžfšY·Ž±ïi– Í=í¢z÷4‡šZ •{L­& wÂÔjÅi¢ÝÏæ‘ò‹¶ïiðb¿®VSDl)௷Ç™†@õ²ào´t‡ånÔ74p† Põ²18–°¨Að…/€.~10‘àö,|G×=¶( J]ÁtÜëË~{=¢ÛGɆ¥¸Y‡¸àßExßC–d‡•“ñèÁ¼‰îq@7ÜQˆ :NÉ«ÕðÇÀKdv⤼ý‡;K¤ÄÝöã,ˆV‡æû,@ç|pX ƒ‡ÀÏdØaç”6Ko߸¶€,Ãsj5êFüdµš?âkºŽÄ×åj>ðú½*spHÎòÙí÷ê$lį¬ùIGâqÍšs¾?Q497ÚóBUaæ#_âk#~äL|x_Ó˜yò&¾8ÜGÞÄ׆üЛøÚzÿ lpë|¦3ñû7)›œ»•¤;Îä»_ÕÙGßõ$î‘«y©åV„Èå«%;’ ’‰© ™™è÷ëV5Á‰´hB í$è¿Rh'£l:;âq¬âékðôi2”·™!^ ÐÈ ñO 3Ä ²C˜!^ iÁ ñ3ÄÅ äÊéL´Ótvw4 ÁÁ[g'ÃÕ×1¿d5uKVGIÒ­³£Ž?ÓÙ{²ªLX]pLŸWž·JV±ÄiÞQgg¯d­Ì7‹uªÔÙ¡ŸÀë쨂:;Åtv˜Bn:;È;¶ñÊš[&ˆ×Î .îD_d'·_=£L/Þ&ˆ‹ÌÐVÉZ-•:;L²qf¿›ÎN¢*-Ä%E÷³R4ˆDYx†b¢ƒb•iT%á,ÓHôÞhI%î«È£" H¤¢uv’‡svÑU‘3ç(¬H7 'XR¼AØð J’Cº!Ø€ V‘'åÛ d8¤>?…_¿ ‚¥èëÌSð‰õnì5‹z=éúò:´¸¼I²Uwb°¯¥¯eíi :)bñÕã#2¢“‡8)³§ËOî½$;ø‚Œ¹/·pÑ&ß{° …k£îPe×Ù™¿¿|-ë`88›PéÅÁ¬c¹e‰7™lž¾cTbN!6(œ „kÏÇ"¾ 2Îéì|:ÍâIŽ0#ìÍ¢„ÍAND›ƒCr–çh'ùÍ¢ÔΗf=-¦—ÕvÎö¼Ð_ÕÆ9K³dij4k¡ñ(Ízz"¯‹í¦Y2äaš%C¾N³( ô¹lˆukZ"~>=FWî;;AÎÕœÀaÞu…sSÆÎ[âa8×Cp¥¸%ë‚þÀ ð9G³ :8}).ž€¿Ò6/GÁÕ}ÕÄëc½‚Ìk@¯Bô È›‹NY—oÞî ‰r&;sLu–^ÄBÜNT¢— \€\qÑÞÅp# qõ„o’‹ëËÞ $ qÙ„…¸æ¬I˜ÊC­°Ñ &”Úë[p&óõ0+…¸ ØdõÚ]VH ˆILÒ;2dkó«×îÆ(ã´dЧÓ,žä3’ÁŽÑ,ªñäDÔã9:¤ÎòÍâ$_¢Yªôu$ë¤pÐ9Z´4eÎ ÷¼Î_•ù9˲dij,kñ(Ëz~$dƒó¬5æa¢µÆ|iQÞè“™–ôWœ»¬gZgåŽÓ Ö‡ÛÂKÈ;$Ó¢ºZx=XWº•*‹}™Lklr¬óÆq[xbÜ$gâ­¦ÃQ­yŽ<Õ‚*©«ja|R­J@ª•Šåù)ÕBºšQ­¡ÎdëÁ„µN¨YØ H“Dý-x<÷"õÐhov$æhv´‹$@»Ð1Ó‚[H™?(ôéµÈvG•^Ôp9W e¡“ÅÃÐ:9$fy®™“|©™ H_U|Vé ÷qœƒÃ=/ö—‹Î–%¯!Ï&+&–&??–H‡‹“ט‡«“ט¯—'S«é³ùWËy§_'µ›Š$qŧ6ÅUÓî 5ü¥H±$6ÃXÊDÐãAíGÊj-Rj¦k$‚½Šƒš@lV\ÔeŒú‚ì)))0–PRЛ % Ó¦h®c1‹RQÂön¨©˜Ê@Z# ¤5"PÒP¯ŠJŽôI‘šéÙ¨ªƒkÞ‘EsW-^0öP¨ÎmV-²êU‹ ±j±PYÆK§XKuQ%6&µ­Š¯Zc¾u&ö4.wkwý…Ts"b!Õ\zekû}±Ò—…T2R]ì~Á‘`±˜¬Ü:yÕùZmTRTéZ!U`Z" ©»¦³*À@·B*én§&JFä´µýŽHˆ³B*ÑS¾"GŠƒ em²—ñˆ2ÔVeYb@YeÑ™É$]𬰂xÐ-è4|t‹(è„àºòæ%è„Ê7 LÔŠ]cnÂZ²_]oý-è”\£4²(7Ê zÂPЩª± :i¦ ¢¬X× “”eÊ eéÙU\ …¬7ÊÄ—äQV)[”IY^r(«Ì„£ ŸPÆf= d&´ Œ•²AA'&»RЉ•Ä@Xƒ26£/¾jc¯½ŸŒ³y•´~1mPÁU5œ´5:C(èÄHÞ-è¤eUV£¸êi¯Â²^{@Ug2@UXU«@÷µ‰óï]iâ¹+¾LyÞÈ𦀜+Ò}¤hJÕÜkÏ‚ø5Д!14eèfMé£@S‰P¾¨\º™E‹MK€&‰]·g!g—{ÜF@S+ÛžÅ^‹Ü³—š:º™M±eîY²èº¨\pC]*÷,*š 4qG#šÄc°íYŽ@«´GÛ&E“x,|#ëúš›ÅrÇb29ëì)³Ì:{í²ÎšVgOhÖÙ#aÚ6«+>ܬ"ñ…Íjùºm³º"ÓyPkÝ?"ʲ|¹U]e‡”8rtåVu¡(Û¶ªk°œ[Õ…5b[•l¾â^ÎÒÎE…§ Òç÷Ÿ­”&ç8âM˜cÕ’ÏŒE ²mrg”ÒÉYn—}D)íÇFüj¥´XÖ.õÇSJ{ºµ/)¥íi•¿¨CÖ„mÓe–¥«Þ1Uæ§›÷ºdØÓòñš¿Y…,ŠúÇiþWK2_OªcÒ9:ΓÌÕë>ƒêX™ ÎvùPuì—'UÇúÚyŸ4¤Õ}2;Lì˜äXÍ…€ 5Z¦6¼î˜¨ ;bc™¡Ôh–±i´ÀÆ2茜¼  ›¬ƒRy‘hi²L×Ìù¶È$æ¸bLÔhÙtÛd+8n£,Th4S£¥^jQ˜îrïL£¥ ˆéŽzÛfKQÅi×®Óo-i“„a“²éŽIËÙg¢BŒ-åy‰–±¹Ä9Ƴæ8¼ÉŽUVbѳÐHKL¢…qYz„8m-šF&Ñuâ´ÕØtýVh¡Ú1mµF=ìe«5f€Ò±ÐÐRÅ ÊG´ÖdÁ[kÍRd©ÐRX«H…–žš°Ö™B $[ÌZ[o·Op,(“¤@>!0 È~…a­l—ø”ÃèWÀ¢_áÚÔ×cÐ{B¿B€\ Ä[Ðãê-葹ä[ mFýXþp‰zߨàCüV_÷L("A".”‘†Š ¤È)ã5¦J—ˆ\Xr‰ÖÆöRŠ 79tªcvØéÑgO5—ÄäØJQø´é¹$VCÐ%GTtat’.è J˜qn&êÂH'U]à)5Y&¯S×%í“Óy×]¤V¥]Vð%Çæ[ˆ‰rý“S…5Ê»ð{ê» n/ ‰¼TxáÉ(ñÂcà*¢ÔD^0¾©¼¤ó¾Å“tïOž…ºíhÒµÌ÷2XÅ^v,pnK‹~K‹ØlKËêJ±-­ëéLv ŠpkKËØ²lK»Ø¦–;ZmnGËÈv7Õ1¼±Luì²T&ê çg°L·£uç_5åÞÑ ¤¶œêXlnG+}ëq «-:ÉZ¼ »üu¿TÒ¤‚[Za4Â)ifïuX2˜LŒ¸ô­¢/\dg6Góž<ù“±mi¯¾[uì¢;‚JšìÈlªcìkJšþI5rJšãžfþFîi÷T£Oß”4Ó.Ónªq·’&÷fS£2©SÒŒ^ª}%/Ýeðû¼I\+?ŸÐÜpƒ`ãÒëCW5 –"`dú"Ä€˜ú€¼ðŸ…ÂZÉakknpTéD˜ã§éNuŒßQÀð5‹Æ‰ŒK8¨œŠ· q”9ç´£@ÄÃÊÉx;,ðèøò¦à-KánŽaæN&ŠþppR›îìÞÉ€‡D ÜäÄ MuìÆþÁ!ñ?$:˜ƒwqJ›oއSJ¸OÄ„~kˆP#ãœê˜ºä>YuìÁ'÷šÎуSîÛ£ž×´W½ÉY>»Ð^äøÕªc?é”;®:vÎ&rOçF{^è¯*z}ä—{qÄsß>âÓý{]}ëCÇÜ‹C~ä˜ûƒê èuÒ/'…åi–¯^iëË_þ¯33Èui‹·xVcÙá¼DrÚU;,.ß[6Ž­¿³øÀ†+xXš\°}ØP¸º<ëUbà«ËËPË”%»+ CXñ ‘}Ä15©¾ªo†“._ñÀTmV<ˆ:“/..'"$ÓQÎA ¯¦—k^¨˜`ÅCE7VÓlxÁXïEjxÁ ¦†Ù¨whÐ=F½âÚ·†×ZG·†WsÚ=«›^(‚øs®¸¼Gë¶Fá('ë0Ð-À3e}ÁÝ`ò `'–µ¯2*¯è0ÚŽ¹Amjx½ÂhþþbrNG8ßò ÆöV%à.¦ÀpW¦’87?¾ÕóbU¾æA>È›šƒüÂ=€ˆÝ€Ìâ!Þ.Ê~[ÙCƒ¨¿•= ø+ˆ·@Ÿ®•=°HÇʘÿB¼™Î#ñ6ÿdùvωz}:‹áIŽì‹¡\ÖAÊA½¬ƒCr–çX 'ù‹¡¨×—Å<-¦—E½Îö¼Ð_Ì:ËbÖˆGYÌÓý{]Üê0‹YC¾Ìb¨—u˜ÆˆýñHcNÊc‰ãöO²<µtj9e–ë©åĤ|XNmlê§…,Ú†:,'Ùלúé@K_XN£ï%Ûú¼À\eæ‘­.;ežµ}vG`<ª$0L¹# h]KQŒ@ÃN`"ZQ“ÀDäU’ÀÈEnêXè‘AÇ.Bœ˜H¬êX S“À¤þP° &vl39ØÔ±h©c¹°ƒ‚WØL†|«ÙS™bÈ´§äƒæí©io‚=òo÷Š=®B«ØSy°öÔbXTÇŠ»8ª|ö‚í«Í©c…­`»d–P‹½uM E"·1«ÑM«ªêÕ±\˜ä,1Îï¯'6}ºÆ_ª“yCaÀ$ˆÚg 0¢P8ßU‹È…)ß@a„LP˜5 &„A€Á„¦\€`¢V–"0Uý[p.hmÿ§øßk½á'å Ž¿dðh€/K¹YÊ$ôXþäeøxÙÀ]†aÁNtüLBîà]n ­(æ$Ôá!—Ù­ˆË¿¢8Öµ; 2㞀›”flâXëØ23‹µw âLñ+Šc%ŠaA‹šÂÀ™HoâXù4ÇâºÈ„ë‡1ÏÄ 5˜°ÒHPL«y|”¢˜8V:tu›O§+<Ɇ!ƒ£+”:È-¨;utHå9ºÂI¾DWTëëÈÊIq¬sôb)îy¿*ÍLÒéÎbû=:‰ëÀLÊ’ 0•©¢¦¹©Lµ²ˆ¹ëc.’7–e™æ@s²¢+Óº9ÊRØh*S²½{mÑe>oQzÇ}çô›i‘)/x³:§lQ‘{ÚœÀ–SeS˜ƒe*SHù¾;§$°S™Ê¸뜒™ÇuwN)[Ô¥2 ÞT¦`ÍÜ*S îoëœÂ¶0$-Ò´ÒT+Íz#-Òzy‹ºTTóÞ*SNwS™¨Î·¨Ë¥fà'ªLu©ÎÏQ(`Aðå¦ðtV·ª²lÙ°Ø`‘!- ¾½ŠH”ÖÃí¢¬W'é+«1ùØç…¼fâðB›Ts òÚ„µQ‡o®ƒ° kÏïkt®ƒæq³u¢TO?DšÌuÂFƺE`ä8{Nì@J[qhÙàÄa`Gaâ0°p˜8¼Øä‡8¼˜I†‡~*!°¡7q";¬‡RÕ¿9æÙªWŸ2'‹áPd(¢ÇaDî«á0òAλÙ7iíp(g©‡ó,}‹~F¦ˆÃÈ7q;sɆùw HŠüºo°²D£Ça„ìÁAªO¯ó´³8Nò¢â͹ZOè;,Ì„ÀÓÉ!1ËsµžœäKµžT¡úªZϳ*TIŽÈþîy±¿¬ït¶äS‡$Û_˜›¥Û‹N¢0j‰™µ²Û%¶¾U^²ë‹%ÝJˆ2í^l$¸ ñ^ì=u #õ>²‰“ïc ÈÒïYåg ø‘Q´8“/ÓÕ`HÕT‰øb1mšNRƨ6’ñçqKǧȘ%ä‹q¿•^&FR~B€ê3¨ á&bÉãIÖi>—uÁæt$æå”hÄïïê/Yï¼U¬à CÀ›¹ºB±N/x›÷-:¼fÙckqdl&.îêt‚p¬f¹ÐÀc+À\| Þˆ[‰D®ÓDOú Å¢þˆ u`]‹È˜õuáÊ›¼Ó`÷PЍ ¼Ê(HCÁ Ò ¢Æâf ÒXqzR}Û­,ìºv}'ùÀr6uz”€1 5Vš†ø×­¡VA…L–¦ÓPìµpy™'¹˜xãíBnŸáÍ4o‰·«Ð—@ 5¾8L˜f Blj¬»3ašþ€·«²ö¹ZÛðE™rÚzT˜f>µðéÊ4ë$G(Æl¤qf,оì³;£MsrLÎs»ð#â4?6âW‹Óä?D˜æ‹x:r]â`IM·Žß¾ý—·žÿ'Ò¼ cóü^²98Ü3*^Tž™o“µ0®š‚cŽÚ*ë>?וlžîá‰!îâëC>ÝÇoÖÛ‘"ã| Tu¯'ù¹ Öù™H¿Æ—Õwâ2^?Rßù“ê;aù_Ÿ´ $#(˜í9ÙP·í9(ÚHñª_³€:"»ßÄw.kR©JQâM©¢¤¦TÀÞ(áíÎåb1uÞ9ß 9mR rNª`lRp"›TATã‹v¨´îóâ;’‘ã$F—}µBX*Èý“ãèøßÊ sÒˆ +Nª@mI'U 2&UÀ¾ &UP`È‘JRMñ P$Ù8RJŒLªàº›8˜¢Â¦ë[ؔԤ XÏD›´Œ©‚ mR[ÞJ° o“*”qBX-lò;Å^ª]T`“Ré–* H¯I@Næ–* K›ÔfE›Tf·ÉïT„t?G~'¬8Fy„`@Ÿ ¸[ •(ëëé_h;ѹžì›üNhÉjú­Š}Caýwê{èƒCèáéyC7àPî@ß»±‰gÆ•:,-Êï :È!`CÄAš„€A†LÑu£-^XÔ—0±6Л„ê;´‚úÎ…’5ªï\pÆ‚ÂlPkê;ˆv›úΟòàôâ&p5vƒx!¹£$ñ5È/v®\è²¼éÎÉõÍ¿ÂÉZü=‘Å{C`qrÄ@c°ìRyï.¯ÿ/©ò«| œ®9ƒgçeƒ|ôäŠ%i,•u†ü§‹i䗹冑 ¦ßѢꄔô:r‚ôË×EuߥVîw´ˆ(>aÑ𔸊x2–äu‡,"€Ðïá°5µ0àJð¯rGcðŠÂ#¾²ñ °”-6¼¦—P‚ʧ7¥ü°£%*\sG³Üsîhó¾éNÀMRyýŽ&ܶíjzr‰ÁQîh"ñ—üŽ–êƒW3Qº;ZB °.U‹8¹ÝCŽ7[1—XÒJÐÉuì^Mf¦v RH·W“Þ(ójVf•Ó«ÉMмš•u{ôj6õÔÝ^ͪ ¯‹ï¹ímüsë"M(i]áe™ãªŸÂ®Ê*Ÿry˜áHAÅGÓÞ Þd¼]–üOjï\Zúiï¨áHí°iï\›öNØ´wÖ‘iï¯d¥Ó¢öNhHº¸L{'xé»Ñ´wö] Fiï„ÍÄžbÚ;a ào©½ƒ䆇Ô7ÈÐâ£öÎnÔÞ ^&›ßšöË6)ÓÞ¹n£A€îoÒ­½³«-²SòµMÉ´wpHí¸ibã%dÚ;qÄÉɢƯã'‹ï<º_Syð;¾®¾ó‘ðUe›“cržÏ^ÂWgùc#~µþÎú«VÅïxåøGñ;>/½—µz÷0^ÕÖùÈõøêˆÏ¾ÇÑûóñ5ugçã‹ã}ä||uÈœ¯ ù¡óñJn‡¦Ð'ú¿SAJs]G¯ÿ8+1V2ýS®{Á«ùµ½n]\…7mC ½IMb(˜gPËA3d»‘ï.D®4p•œ®cJ eµ¿MbMTLc2à̳ÍÐøaž-»3ÏVÜ^pRГæKå|+HmùîðLšÆ¨ Ï–Î;ËwG¹žå»WõµX¾{Û:»Êù×ýažmeýì*Ñ­¸{–e[iÔX¶;s,Û½'Y¶;µ=-Û=«îlwhRÞÙî [Oe*‰¸l÷°g»G=X¶;µl÷‹2¦Ìv¿Ð¹Ì²Ý3¹ÓÝSY½˜–íÎË·lw6³ÝÁ€4³ÝٛŲÝ)Käz*_{¶{PQqKvçfKåüîöªòd¼$1$ç9Ù=âjÐR¹À©‹–Ê—‰œ®dwø¾EA’+”/·‹Pž¹'ô‡òã€a‹›ÐEÕ†œcJ Ávðc °£¿%†úV"ßñ²¡ÄPÛzšËËÇ•èŽËtO}'*J ¡Ý6%†ØðË$†¢ÃÝüVÓ-–ÄPÆJ¥ÄPÞKt0kC™”ª»ª×`ù:*_ÈHÞ$e,8¸­7½CÛ°d,4TLACå§¥© A·ÍwTŽi×Å·6SÊÂí¶XH»P`Oå‚¿0q!¨?ùžÊÙê®$—­¬Dj ²š´ÒܲÙç_è5m¡¤Ž°sÚBŸÏÒì,Gˆ•ŒvŒ¥Q·ç$£¢rÏÉ19Ïs,³|‰¥Q_èÿ[–ö¼ô^Ö":8ÜÀxU;è,KÓO²´…Þ£,íù™¼®Ft˜¥éGYš ù:K£fÒ§Ò4É‘|æi'5” !<›†Ãó´Â6¨ƒdHJe3 çžÎ¦°Ë>)ºµSC©Z²þ²NÈØÀЮÀÞËÖ0¸eÇÐ.DvÈÐæû0ÇÐd†É14ªhºJH6´ÔJ;œÏD”‚F¯¬² a¬Q*ޡű)¹Xþ·‰(¡Âš -%ˆ*QD©Ò:LÊW79Ê%¢4Ô#3æQê(Œ4¥†HŸ‰(1@m"JŒh›ˆÒÅ(s3­wÌD”ÌO¥Àn—QŠln™¬j½&Ú]6îU^Ö5Ý᮳Íp(÷:<âpchl¬(dô¾’ QYs•@|ž’b)Tªû«:ý$Ñ0H(¡m¶´ƒá YO£Œ»„’ˆ39I„(3à›õyú’Yo J(]Höúzb …y bYž(à¦w :®€]b=²¢NŒ'“^N}çg e„\²V/…¼X— %”âݪ â»Ã;Dæx¹R]Õšw‡Là€)Ö2c¾”PêHÄÒæ?ꓸ%”P£8“„7ï)ä^”P‚ö”I(E†”!¡Ä˜%”2ÎO %fQB©€¯RB©"ÇŠJÎ[B©{Éׂfíç$”>Ÿ•ÙYŽ)í+£<ÑIE¢³cê<ϱ2Îò%V¦2J?ÍÉò'{^x¯K.ï\¼*‘t–”éˆ'IÙïQRöÁC9 ¹t˜–aÌ£¼lù:1£6Ô'³²¤¢<1;«µˆÙ³Ï>¡ìU-­ à‹‚‡›bQÌ€2±(Í:„Mx5KR9ćL-ªCh“jQP•'7KH_%7›}ôL’Õ|‡ŽtwTûwÞËñåÕ¢rÔß;µ¨ê;tdt5µ¨¾5 X¬Éq3F÷,z†Fœ^-*9nVn[ªE…ºæZÚÜjQaS©£Ì[‹Ê»ZÔ…ªH?«[ü¬"펟E¶Ý¼ãg}S©ù o4®îy»Z†Ÿ=¨EAÁ莟¡#ä?«0M-ª°E@°&*ÅM-ïø¦,~Ëþ 5Õºh›y–Ý`\©|Ï`T}2e ˆ\ÑKÂ\M#[Rišý Œ¼žjQµ…—„Ȥ—$£ý&ä¢!ë䢚¢”øoN’®N s’@ÆÍœ$P3'I|PšNZKnN’¼‡±#BT&…v&…ôh“‹Â#4ÅL. J×¢TxÕ[ñ’ÅMkÚŠ•\TÝ€hí,DÉÑön’AyfkÝÑvâ¶Þ—[¯’ná&r8Ĥ ‡2VÄa°î›—y°ÔãCšxqêƒj›]½©E*P-ŠS7µ¨ëAµ¬ßp(ÝkjQΈC–T‹úüâëû4Ž~½(ws®JLG‹¥¡ÅttLÌó\6gùR6£~²;åÿœìßëêR'Çû/‹A­ÃÆ'+±ÃGk±?x0ô¥WccÌ£åØkÌ×뱩ƒõéÁ¶iì”î¤.VðÏ´>œy©ƒ½ÞÕ.‰U¯ZîR.*â« U`lU¡Ê¨AÅK¿ð­–¼tè[¢æE |UÙ…0Ç*{¹˜‰Âöcé˼7l·¨j.hÐÍò11êÛ]ÑÞ%0'ðE0sÆÉ·tŸ6àߪʢºÅ;˜%“±.|éU²V”m«)KJˆX“XbIŒ´Ñ -Ö”±‘e1ùz¨’΃biLf¢ÖÒÉš÷­l:Y‘­X#ªe[t.ŒÃ¡D&#ÉÌŠd2ƒ{,“ÉLHd¡Œ<žM'+£-…˲EƺP©Èé – ÕH_eóOtA²l¦PuŒ…3¥°#JgJyhçβö»F:³i: h r?Q'kyTF~‚zL~èŽH¬ÆX vd}Ê€ûØS'‹²YÐÉB3á‡üSêd}ÚrÔɪàsÂàÚWØ»PcM쉦[wØc1#±£#öæqòóâ¢Ç^@šq™¼¼BÁ<9É›rDÐM, M¦Q—ê9/ÖšFbî·FCFÌêáô.V/è]ñVèM¶¬ËѳØcѳp·bñ­˜Å¨Ÿ)fA!ͨgŠYï[1«'Cž<„­Mü¼quS'¸* kŠYtÁyÆôL1«P}È ìcŠY¼2"/ Ïí­˜…â½ÿÀ<–¬X—/¢ù´ÿÙÏÿÛ/°Y‚ô 3ûjÂçÁóÞIÆöM…®Gƒág(ŒÌéi†ño¿ùÇýý¿½ýâ?¶­}ÓÈÌe¯ë!üÈÔüK„P§éÿ׿ýë¿ù9æ­g|P‘ø–ÉÊ‹·ol“µúÁTÿü¿ÿõ?»©¾^œ¯³•f®^¥u›íÿÊðº endstream endobj 5 0 obj <> endobj 9 0 obj <> endobj 11 0 obj <>stream xœeAkÂ@…ÿÊÜTJÝ5š(Ф©¥XC#íAãÇ?xþgP endstream endobj 12 0 obj <>/Length 72/Root 9 0 R /Info 1 0 R /ID[<871C71A48AF28B763D0F15B60A37D300>]>>stream xœcbÿÿ™˜€7##Ó ÍÆÀ¦ßi`bd`°î„ÐG›¡â¨ÞÆ‹á/HþÈ60ÃF(‡iNll    yÌfÒÄ pHYsœœ&Í:4@IDATxìݘU×ÀñCgéM@ªT¥Y( (Õ‚Xì ‚ ¼*‚~ر`CEDTlXA±‚¢/‚EDéUŠ"½—|÷LÞŒI6É&»™M&ùßç3õÎß`î&srnÉAñxYÊ•+çô)©@ ÉÔÇä¤ïH¦ÏBÉÔ–lü“à@ åÜÚ÷åF»éÃRþŸ?ˆ@ÎÌíoš‰‚ ,\¸ÐÓ¡C Šñ˜ÿk&äiÒ¤‰çž{îñräˆgøðáóãûsܸqãìË;v¬½^?®Y³ÆÞjF?G^~ùåçêÕ«—çСC¡vg €@”9ícFe¿7wÜqïí5²·=òÈ#v‹²Ûw$Óg¡dj‹ Ë  €@Tnêûü/(§íöÕEæ“à´¨l¾É~1|¥ý¿!œÐ@Ÿž={zL£€ÙæÿØËM›6õ¬^½:ªæL˜0ÁS´hÑõøê×@œÉ“'{L6¥€ýÞyçˆçøå—_2õøê ~-Uª”˜©Â>ú(àüÚ¦U«VyêÕ«°>¸n]ÖëÔ¢M­ZµÊr TÚ³gOØæ$S[Â6’  €€KœèçâU§É(è1Yðì~C|#õþä&ãž}œöE&¡çرcö.ÉÒ—$K;lf@,xõeþœñªÓÉþQŒü?Ó}ýõד-7äç¸ìi_®?Šñ?OãÆ=Û¶móçb@ xõ1wÝuWÀû³ÿ{µÿ|Ÿ>}ìÖe·ïH¦ÏBÉÔ–@ˆnìûô‚âÕn}˜O‚WÒ^ rÎÇb2ñS@ þ÷Þ{¯¼úê«bRÚ•kÚøSO=UêÖ­›i°Ÿ~úIN;í4™;w®½ðŒ¦H4™|äꫯóËÎàÍË&c’tíÚU&Mš°>Òœ9s¤uëÖ²hÑ¢L»…ªmÇŽb~M*ýû÷Ï´¸š‚±]»vb²E„ÛÅ^o¾„ ÈÅ_,3gδׇ›™5k–têÔIôÚ£)ÉÔ–hÚË> €@2 8ÑÏūΪU«J›6ml®}ûöÉ_|a/GšùðÃ6_{íµ¢Cx†+ÉÒ—$K;Â9±Hxõeþ^ñª37ûG“ÙH:wîÕç8ÿk 7o‚¤cÇŽb2áÚ»œ~úéòÍ7ßH™2eìuÌ €Ä&¯>&¶³†Þ;»}G2}J¦¶„Vf- €€[û>§ÛMÆÿ -¯E†£´ZÀ /¿ü2 ³B³fÍ<&˜'àT:D˜f:çœs~¤û†+:¤˜ùŸÝž (àéÑ£‡Ç|Éj¥ž_¶l™çí·ß¶RÌûö -\†#<ä Ny¬Yˆ&NœèY¿~½Õ$Mo¯iøÍÃW» ¾ó<÷Üs!›%­Y&|ǘÀ)Ï”)S<[·nõhÛÇïѬI¾íúš?~{Ù|‘ìyê©§<³g϶²™ -ÏÀ3 W§m U’©-¡ÚÇ:@À-Nôsñ®S³'ø÷':üJ4E3ú÷Ç–,}I²´#‡@ ÍâÝ—)g¼ëtª ÎRqþùçô§UªTñ\xá…Ílñí·ßÚÿR¢Rm×®]Ífëß?·hÑ"Ë!µí“0ƒ R ž}ÌÆ=?ÿü³5ég/ÿ÷ìÏ?ÿÜÞ¦Ùö|%»}G2}J¦¶ø\yE/àÖ¾/žíöéЇù$xE íR-íÿ ”þ9%K–ôüý÷ßÛyÕUW|×¢à¢_²–/_ÞÞOw¾úê«àÝìeý"¹páÂöþ¾úᎠ°¯g2BØõÏ 2$`ÿÊ•+{Ì/‘‚wóÿÑ¢í(X° µ>ÓÎf…~9jº–-[z¶lÙêÏÓO?Жp•“©-!/„• €€Kœèçâ]§Òú÷ƒ:i¤~MéuÈO_©¯¡‚€“¥/I–v¸äŸ,ÍDrE Þ}™6:Þu:Õ??4öõ§Õ«W·~0îdp¤ímÞ¼y@ÿ¬Ãmëçc  €@ÎâÝÇøZsóÍ7¼o¯]»Ö·)à5»}G2}J¦¶ಀ RÀ­}Ÿí¦ ùO„•¤£Cª™/±($Àüùóí65iÒDÊ–-k/‡šéׯ_Àê… ,ë“O>)&½~äÈ‘rî¹çÚËÁ3:ÔÙ°aÂW‡\6XåÙgŸµ·5nÜXÌ¿’‘‘a¯ žy衇Äd²W›_2‰ €²—#ÍÜzë­VzýPûè°ršß¿˜%yå•WÄ\ù¯¶ço¹å1™ìåÅ‹ÛóYÍ$S[²j+Û@dp¢Ÿ‹w&àW.ºè"›L‡"5¿²—CÍ„N-Ô~Áë’¥/I–vû°Œ¤‹@¼û2u‹w¹Ù?šŒ¹ÖÙ&Q¶þ ˜`#ë3¯ÿ°ã:<·öçÅ‹ÏV„ ð¯@¼û˜kÎþ\vûŽdú,”LmÉþàH@ 5ÜÚ÷åV»éÃRóß=W…@Vÿ>aÏjO¶#€@®;vL–/_nŸkÉ’%bÂ!%Ož<öºàó M1b„:tÈÚtÊ)§ì²sçN1Y|ìuuêÔ (ʪh “*™Ì@w½çž{ìsk;5ØÈ ÅñݨǙaÞìc_{í5騱cÄã4øê¾ûω'ž(þ_*›aã䤓N {ŒZNN8áY±b…µÏ_ýv_ÿ ÉÔÿv1$³€ýœuª¡ùõøé|—.]Âò~ðÁö6í¯¸â {9ÜL²ô%ÉÒŽpN¬GR]À‰¾Ì‰:õ>äFÿ¨çѵ”.]Zgc.Û·o·‚ü¿X×ÜLž<9âcb> €i*àT“SÎìôÉôY(™Ú’Ó{Áñ €@ª ¸µïË­vÓ‡¥Ú¿x®è8ŠÞŠ=È3˜4jÔÈú%§žpóæÍÒ§O3fLÄ žÛo¿=lû~ÿýwÑÌ ¾Ò©S§ˆuùö3îÉþó:t¨oUÈWÿÌDµjÕÍÊM9î¸ã¤M›6òõ×_[»ë—¿f¸Ñó†+fh4)UªT¸ÍÖú2eÊlWϬJ‰%ì]þùç{>ÒL2µ%R;Ù†$“€ýœuª™ÁjŸâë>ûì39pà€˜¡Ö2‘š4ÿ2oÞ<{½>Ô¬P¡‚½n&Yú’diG8'Ö#€©.àD_æDzr£ÔÏ”‘2òFú÷°mÛ6ëØ Ø»i›'Mš²·wb@ j§ú˜¨bÇìöÉôY(™Ú‚˜U €@Z ¸µïË­vÓ‡¥õÿ\|š äMóëçòHJMóî_Æ'ÕªU“»ï¾[bîËWÇÊ•+}³ÖkÛ¶m–#-Ô¯_?ÒfÑl@šªÞWt8µXŠ0fhZ³fMÄÃÕ!«¢‹ü‹AÅR4â;š’Lm‰¦½ìƒ$‹@¼û9½.'êÔ!9/¿ür›m÷îÝa‡ÿôÏ„¤\sÍ5öq‘f’¥/I–vD²b êNôeNÔ™ýã©§žš­Û­ŸOÛ·ooÿ€G+Ñö¾þúëeK”ƒ@ðNô1áÏ–õ–ìöÉôY(™Ú’µ8{ €é'àÖ¾/7ÚM–~ÿ?pÅø8òIðŠ@ ÜÿýÒ¬Y³€ýùçŸòÄOÈÉ'Ÿ,åË——®]»ZY4£BV%8àH‡T‹¶T¯^=â®Ë–- ØþÛo¿I÷îÝ£žf̘pü† –ƒ²jOðþº\©R¥P«s¼.™Ú’ã‹¡@ âÝÏiÓ¨SëÕacüKp`‘o›ÿpjE‹•K/½Ô·)âk²ô%ÉÒŽˆXlDR\À‰¾Ì‰:õ68Ý?Æò™ÕÿŸEçÎå—_~ñ_e á=dÈ€u, €ä\À©>&»-Ënß‘LŸ…’©-Ù½‡¤²€[û¾Üh7}X*ÿËçÚˆ,Àj‘}ØŠ@BJ–,i 3Ö­[7{¸1ÿ†è¯6'NœhMº^³]qÅÖðgåÊ•óßÕš8*]ºt¦}­È**9TÀ‘e·ìß¿?â¡Ù Ò”‘N”dj‹×G €€Sñîç´NÔ©õj:à5jÈêÕ«uQ>ùäëÁ¥fKð•uëÖÉ?üà[}Ø©AGÑ”déK’¥ј± ªNôeNÔ©þN÷ùógïëª7†üç1vìX¹êª«¬!½CîÀJ@˜œêcbnÈÿÈnß‘LŸ…’©-Ù½‡¤²€[û¾Üh7}X*ÿËçÚˆ,àÌSøÈçd+D! |õÕW2sæL¹îºë$T ‘¯š%K–ÈСC­a×^{í5ßjû5øK×R¥JÙÛ²šÉêú>dg9pà@ÄêòåËq{nnL¦¶äæus.@ ñìç|íq¢ÎøÚê5Yú’diG(#Ö!€é$àD_æDN÷9½çÚ<Ø®ÆãñHïÞ½%«Ï›öÌ €D%àDÕ‰ã¸S2}J¦¶Ä‘˜ª@”pkßçt»éÃRêŸ9ƒ@LÙûÉXL§`gȉÀYg%:;vÌÊžðí·ßÊôéÓeÖ¬Yœ H—õKTrí /´OœeaûöíR¡B{{¤™-[¶DÚ,UªT Ø~ÓM7Ée—]°.–…FŲ;û"€¸\ ý\0A¼ë¼æškdذaöi4ÀÈ¿ŸõNMûàsÎ9ÇÞ—@²#ï¾LÛï:“µ0`€<ýôÓVFÂ÷ß_–/_nÝ}}àäñÇÏÎ-á@ñîc"œŠM €$…€[û>·¶;)n:@d8 ÉÂJ’O@‡kÑ¢…õ+ͯ¿þZ4hhêÔ©Ò·o_)^¼¸Ýà£GÊÍ7ßl/ëLpF£X²­_¿> ®à…ºuë¬Ò!fÎ=÷ÜlO+V ¨@ôÈI?N(^užtÒIÒ´iSû4“'O–Ç[ËÚOú§vå•WJVÙ튘A@ xõeþ§‰WÉØ?>ôÐC2räHÑ L… ’Ñ£Gû_ºŒ1B,X°Ž@ø Ä«‰_‹¨ @gÜÚ÷¹µÝÎÞMjGìp”5ŽA ôËÓóÎ;O^|ñEùå—_¤zõêv«Ö®]+ýõ—½ì¿MWfDdhf4¨)R 8Z¶lY¤ÝÙ† €@T±ôsQUhvÊIþäiЯfÔ2qâDÑaZ|Å?ß:^@ˆ—@Nú²pmÈIþý^2ô=zô¸LÍ:xõÕWÛëŽ9"½zõ}¥ €8/“>ÆùÖq@â/à־ϭíŽÿ¤FˆU€€£XÅØ‡}ôQ©_¿¾5qÆQí„Nþýûì»hÑ"{9¸žO?ýÔÞiF‡qÓ,‘Šͦc¿úÊO?ý”i¨7ß¶P¯š†ßw½mÚ´ xhjÖ!€¸[À‰~Ή:ƒ•5s‘ÿXä¾aÔ|¯º½zõ¤Y³fÁ‡²Œ €@–NôeNÔ|!nèux5ÿ¬¿šáè©§ž ¾–@bÈ>&†æ°+ €Ž ¸µïsk»¿¡œâ&@ÀQÜ(©øèb¿ÿþ»5ýøã²fÍš¨*öúÑ*W®lײeK+«ƒoÅÛo¿-Ñ «6vìXYµj•ï°°¯:„š¯lÛ¶M^~ùeßbÄWn„ öõ6lØÐJ}ñ 6"€¸ZÀ‰~Ή:ƒ‘5ÀV³$øŠäjFÁ9sæøVIpV{3 €d!àD_æDÁ—á†þQÛøØc4ýÁ²ó°€Ä$}LL bg@pkßçÖv;|;©â(@ÀQ1© xgF=ztTÕN›6ÍÞ¯X±brâ‰'ÚË¥K—Í$ä+‡–[o½U8à[•éUƒî¾ûîLëC­Ð_‡fddØ›ž|òIÙºu«½jfß¾}rçwlòOǰ@”p¢Ÿs¢ÎPàþýÔßÿ-·Ür‹™OÇ=÷ßêxÖ!€ NÀ‰¾Ì‰:Cµß¿ÿKÖþ±OŸ>âŸùW? ÷îÝÛîÇC]ë@ 8ÙÇèg+ÿ’ÕwŒþû2 €€Sníûœl·SÖÔ‹îüëÝ]m§µ¤¤@ƒ äÔSOµ¯mĈ2xð`Ñ ¡PE‡={ä‘GäÝwßµ7wìØQ‚?œß{ï½R¢D {ŸO>ùDZ·n-¿þúkÀ—¬;vì°ÒË·k×NvîÜiïi¦zõêrÏ=÷Ø»lذAš6m*óçÏ·×ùÏèúÆËÂ… íÕ={ö”-ZØËÌ €¤¦€ýœu†Ò¿ôÒK¥hÑ¢ö¦Ï>ûÌž?ûì³¥J•*ö23 €Ä"àD_æD¡®É ý£~>3fLÀð¨3fÌ—^z)Ô%±@ 'ûÍÄà_žx≀ï.ý·1 €@n ¸µïs²Ý¹eÏy@ ¹ò'wóhé' _„êPfÍ›7 &ÒIÇXÕ¡[4H3Õ¨QCþùçùã?D‡GóvM?”¿ð ™àjÕª%o¾ù¦tëÖM:dmŸ7ož4jÔHJ•*%õë×Më:xð }üÍ7ß²>{‡ÿÍh¶¢·ÞzËNK¿~ýzѡܚ4ibPÕ®][V®\)‹-Ížä@¥ðŒ5*¸J–@RPÀ‰~Ή:CÑk°Qçέ¾7x»ÎR@È®€}™u†º>·ôúÞþýûËÈ‘#í˸뮻䢋."hØaˆNÀÉ>¦^½zøðÃ¥xñâRµjUéÒ¥‹õÃË€X@@ ÜÚ÷9Ùî\`ç àŽ\p“hbú hŠÃ!C†ÈC=dÿ‚ç·ß~"•"EŠÈ믿.Çw\ÈÝ:uêdeÒ‡¢lä+šÕhöìÙ¾Eë5_¾|2lØ0iÕªU@ÀQÁ‚öó-*THæÎ+7Ýt“|ðÁÖj lš3gŽ5ùö ~Õ/}'Nœ(Úv  €@z8ÑÏ9Qg¨»¡ÃÆh°¯)S¦Œhv  €9p¢/s¢ÎP×è–þQ?cëçUÍÊ«e×®]Ò¯_?ùôÓOC]ë@"8ÕÇøA}ïÕÚ„½{÷ÊÒ¥KE‡î¤ € (·ö}Nµ;Q÷ó"€@r 0¤ZrÝZƒ€-ðÀÈÌ™3åä“O¶×…›É“'\sÍ5VÆ£óÎ;/ÜnÖú† Z@:T›aæ?4ŒîP¸paë¡©¦—¿ûî»eß¾}õ… fÒJ—.-ï¿ÿ¾Œ?ÞúåQÀA º¯fEÒ ¥š5kme@ Õœè眨3ø>œ{î¹R¡B…€ÕÝ»w ¼¥ € S'ú2'ê ¾N·ôÅŠ“çž{. ù:DªÿåY@ˆ(àDS @Ñ÷æºuëF<7@H„€[û>'ÚΉÉ'''MòxFëÔïB—-[&:¯ß[ê3ý¿·L/e®@ ™ÜÚ÷9Ñîdº/´r]  G¹nÎ p—ÀÃ?,÷ß¿ÝhM]\¶lY{™@ÒIÀÜKíÚµ­/¾õºuèQÍ HA@ èÓùîsí € € € ¦Uò§é…sÙ¤•€F,O™2žfýEPÓ¦MíåH3³fͲ7ëV‚lf@ÒP૯¾²ƒôòo¾ùæ4Tà’@  ô` @@@HŽÒá.si//_>éß¿¿ý€´D‰²nÝ:)Y²dDÍ?kC—.]"îÏF@R]àù矷/ñøãúF›ƒ@4 Lã›Ï¥#€ € € €@Ú äMÛ+çÂH3:ØW¼k×.=z´½jfÅŠÒ±cGÙ¿¿½¹k×®ö<3 €¤›À¼yóä‹/¾°/{À€R @{™@ÒQ€þ1ï:׌ € € €ˆäÉ ‚ÇãyÓmNêàXÈo¾ùFÎ9çûdùóç—~ýúÉwÞ)UªT±Ö[†né•9rDFeME‹•J•*YN:”éÂ5j$Ï>ûl¦õ¬@@ •fÍš%cÇŽ y‰÷ß?ÁF!eX‰ êô©~‡¹>@@@@ :†T‹Î‰½H AƒɰaÃ$###àzöîÝ+Ë—/—PÁF×_½Ì™3G4(‰‚ €"·Ýv›Üzë­P € €€Ÿý£³ € € € €@á( n2—ˆ€¿ÀàÁƒ¥oß¾Ö°0o¿ý¶¬ZµJt(5ÿR¹reéÒ¥‹\}õÕÒ¼ysÿMÌ#€ 6 6”ZµjÉîÝ»¥FÒ AéÔ©“\rÉ%icÀ…"€ ,@ÿ,Â2 € € € žyrrÙçMsüµ9©ƒc@ ±æÿcÙ²e‹lÚ´IJ—.-+V”Â… '¶Qœ@@@@@@@’U  Ž’õÖÐ.rI Ož7ß|SFŽ)Çw\ò5Ž9*°k×.ë’%K:z*O>ý¹H‘"Ö”|­ËÝmܸQôCBÅŠs÷ÄœÍQÏ?ÿ\,*TpôsE{idÖ?üðƒôéÓ‡¿Y²¦JÉ=þúë/)^¼¸.\8%¯‹ / ïçû÷ï—²eˆß)M¶8p@òçÏ/ß|óMš\qê_¦þÒ¿K—.¢)é'°mÛ6ÉÈÈ໩ô»õ¢ïçšñƒç"”ÇˬY³Òð_Bj_òwÜ!ßÿ½õýTj_iæ«ûöÛoåÈ‘#™7ݦ@ròÉ'Gõ7ðìÙ³E¿ò•ÓO?=®îÓ§O·¾kòÕߢE ë³™o9øU?»ýóÏ?²aÃ9zôhðæˆË ´2U«VMòäÉÑ#ýˆça£3›6m²ú6ýÌ’ÎEû5íççÍ›—Î ©|íUÒû_x*ßÚ\[ùòå¥zõêòÈ#ä u£À{ï½g}qyýõ×»±ù´9Æ “¶mÛÊYg•ƒZRãÐnݺ‰þ!OI-} £ý›ÔRÒO`àÀrÓM7ÉI'”~ŸæWŒ÷w‚ÁÙjjÕªö¾~üñÇ× m>óÌ3eÈ!ÖPqˆ¢Ï#ôºõ{ .ÒÑžþyÑëõ®yóærÏ=÷øVñêý·R§Në³» šëXµ_Óï¯(©+@ÀQêÞ[® @@@@@@H ͤA†Ñ”©S§ÊW\!IƒŽn¹åkØøhêHÔ>ú¸o¼1àôãÆ ™åJS4K’N_|±•ͶG²nÝ:ûxÍp¤ë*W®l¯cH¼ÉÐÚ€É!Ю];9ÿüó“£1´"WºwïnEÔçêI9 K}ûö•ªU«æÒÙ8M2 4mÚT.½ôÒdjmAâ" Ãè/%)é'аaC¹òÊ+Óï¹bHy«®ºJô=Ž’~ú7Íõ×_Ÿ~Î#€@–:t°2ù(íØ±C&Mš”屉ÞA³mÛ¶ÍnFŸ>}BÙ;øÍ´iÓÆBN‡[ó•ýû÷Ëĉ}‹¼º@@ƒë4³T à(Õï0ׇ@  4ˆëX¶1œš], ãó0>Á7Ó#€€c\p”+Wαú©8yô‹ë-Z$oi MsÎ9G*Uª”Í£9ÌÍÕ«W}AARM@ßÛô=Ž’~ú7þmCAB Ô«WOZ¶l°I‡Kö²`Á‚€&jðI,EU‚ùâ‹/b©‚},ЩS')V¬X‚[Áép^€€#ç9 € € € € € € €@Œ­[·8bÆ ËɸàpTºti©U«VÌÍìܹsÀ1k×® XfHüÉÐÚ€ € € € € € € €€¿@Þ¼ù3ªU«æ¿9)ç—-[f·kïÞ½¢C¢eddØë¢™©[·®œ|òɲk×.k÷Â… Gsû €¹*ø«§æd € € € € € € €„˜5kVÀ†“N:)`9üÛxèÐ!™9sf¶š¹hÑ"Y½zµ5ùgMÊVe„8 @À‘¨T‰ € € € € € € }uëÖÉìÙ³í J”(!:t°—“u¦yóæMëÑ£‡,^¼8`  €@*p” w‘k@@@@@@@RDà?þ³Î:KvîÜi_Ñý÷ß/*T°—“uæÌ3Ï hÚ–-[¤E‹rà 7Èÿû_9|øpÀv@· äwkÃi7 € € € € € € h^xAÖ¬Y² .”ÈŽ;BnwóʺuëJïÞ½£¾„ï¾ûN *rÿ£GʶmÛDƒs¾ýö[ùúë¯eÿþýö¾ýû÷—Ûn»Í^Næ™®]»Êµ×^+o½õ–Ý̽{÷Êøñã­©hÑ¢ÒªU+iß¾½´iÓFN;í4)P €½/3 €€[8rË¢ € € € € € € t&Lú+T¿ÿþûP«]½îÜsÏ)àè‚ .ˆùzK–,iî\tÑE1›¨òäÉ#¯¾úª@õå—_fj†M™2ÅštcFF†4kÖLZ¶li µk×.l`V¦ÊX$P€€£âsj@@@@@@p·À¤I“¬,F¡®B³Ülß¾]n½õÖP›]½Neœ.:¤ÚèÑ£E4+[Šf,Ò/¾ø¢Œ9RÖ¯_¶éšÉiÆŒÖôøãK±bŤC‡rË-·HÛ¶mÃÇ@ Ñ%úp~@@@@@@p­@… ¶½lÙ²Ö¶êÕ«‡Ý‡ ‘4KN:¬ÚSO=åšáÇ .,´‡tˆ8Íj4uêTY¶lYÄ Þ³gLœ8Ñš:vì(o¼ñ†”+W.â1lD!@ÀQ"Ô9' € € € € € € Fš­¨H‘"a¯øÀV6¨ 6ÈôéÓ­aÉV¬XaïÿÜsÏI‰%äᇶ׹aF³épr¾!åÖ­[':ÄÞœ9s¬¡ø-Z$G y)huÙe—É´iÓ\hòBX‰))7%¯Š‹B@@@@@@HüùóK¤I‡«Zµª´hÑBî¹ç™?¾tîÜ9 ýO<ñ„h€Ž›KµjÕäꫯ–Q£FYרCî}ôÑGÒ»wo9þøã3]š·Ö¯_¿LëY$Z .GmúË/¿X©ìtÒW^yÅrõêÕöõ験@@@@@@@²ÐlF“&M’®]»Ú»>|X{ì1{9fŠ/nV;VÖ¬Y#/¿ü²hP’Ñçï?ÿü³ÿ*æ@„ ädHµ‚Ï<óL X‘—úæ\N<ñD©Q£†µz̘1Vê»N:ÉÅ_,åË—Þe@@@@@@@,Tò+gu–ß³ €@â¢82Ù®ó5×í?vìØE;vÜê[í«ÉŠ$C‡•š5íØ%ùõ×_eåÊ•ÑVÁ~ €€+æÏéß_ÓiŠŒ)bâ0írô¨È¶m"“'‹ $rùå"­[‹Ô­+R¢„H±b"µk‹\swŸƒíC™‰QÀ í,æï{9ñD‘'ž3&Æ Ø@@@@@xñÅEƒl¶oßnŸëDóåþ7Þh/'ÛL‡¤I“&v³öîÝ+-Z´0?47¿4¡Ü{ï½2uêTûˆüùóK·nÝìef@dÈM#êÔ©SÏìw²ß¾ï™¡ÿšåž~뢞ÍÈÈaÆ™ &ÅÇÿÊW_}%ýúõó-òФœ@Ó¦"ï½'¢™ŒŠ ¼¼|ùD~øAdÏ‘… EþüSdóf‘M›þ}ݸQäwD&Lð!í @ ¬ÉÝK[Më}÷‰lÙ"f‘—_óK3ܳãYD3™š‘A) € € € € € à°ÀHóklMN®˜¤²víZùí·ß¬éï¿ÿØUƒnF%úMyæ™g$»Ã]{íµCÑœO÷ÑQô¼íÛ·—Ãú hS4èèróKóAæç×_½ù±yÝ×°Íü2}ÆŒæÇÒO˜gFæ¡‘_Ѥòú‹v  DQ½›7Æ“‚Ú<7h9æÅSO=ÕêPéeS6lØs€é! oˆÒ¸±ó×ûÙg"&`^n¸A¤k×øŸ/«àsÍd)#¦ʼÿ¾7pÉ/Q\üš ôTéç ßÔ¬YæÆtì(¢XçžëÍU¯^æ}|k48I³Ž>÷œˆ~6©XÑ›ÙHc\‹÷íÅ+ € € € € €8)pŸþâ8›¥@æGÝï™çæÁ@”E÷Ïnij~E(–z4+Ó+¯¼"=zô8ìÉ'Ÿ4èJ355lØÐü@½¨üñDztéRù믿ö÷-˜Q‡dÈ!¾E^@¤ˆjH53|Zuÿ›¤å3éÞͱ‘öY¡éDþW222|³¼"€@š ˜¡yÍØ¶ÿ^|£F"ß/Ò¼yàzÝà ok"Ù½A%Ÿ|"rÅ"Ãh2OL¥K‹œw^ÖA&:ÜÖ‚"C‡Š\u•·¾Çó.›¬™fL`ï0kÿ¶.òœïhâ63L¯‰:¼o¼¶š¿9¥A1Ñî"&³hTE4ÀÊüÍ.ú–\¦ŒÈ7zm£ª N;Mœè½×¤ix´àÓU®¼Æk C§éµíØ!R¶læ}Xƒ € € € € €Î lÛ¶ÍÙÕ®Yƒœ,[¶l‰¹z êÙ³§yŽu…<µ|ùrÑIŸ“ëT¨P!©V­š­¡ºõª‘4PÉ<Ÿù\€ä¶@TÁÍjký#'=OÓÐíÝ»WÖ­[g_ïqÇgÏ3ƒé# Ù4[‘fçÑ·3¤m@ 6̷ѷˤIæÈ¼ýßÿ‰¼ù¦oKæWÍV©-5kfÞæ[3`€H±b"7Ýä]£Áâƒ{‡æÒ$ó· |ó7ë‘î©h ‹fé)WN¤wïH{Æw›þí©m½ì²ÌAN:Œ˜fÒl@¾Éd•36°ˆùÁ€ttÛmÞ¡Çâ۲ȵ™Ì¡r×]Þó>ð@ä}c٪ْ6ŠEŒ}@@@@@@À ¢æómÛ¶µ&'ê§N@ Q™èÊÙ&uÛNIYRi^ï¨R¥Êë9iðaàWš4Ñ& ¤‹€…õ Þa¼4‡h L¬¥uk‘Ñ ù={DL,£=éòœ9"?.2r¤7KQ¸ú5#P¿~™·žy¦ÈÂ…Þ€#–«F 1é+3ïç¿æ½÷Dt˜7ÍT¤ˆÿ–Ü™/X0óy4¨èÓOE>ú(p[‰"÷ß/2p 7è(pkî,=ÿ¼ÈÊ•"O<á :˳r@@@@@@@ì Dpd*?l²M6F=ôDæµ²Íä#óh?öò믿ZcnúyÎ9çø/2),°¿ˆf.Ò #Í:4l˜w¸²J•²ÑšÉ&T6›‹.éÐA¤Y³ì×­ÃŒ}ü±ˆ"XÎ>;r=:,œ8i¤[n‰¼onn=ÿ|o@Ö’%"¿üât¸9ÂL¯/R9xPLJÏð{Ìš%2eŠÈÅ‹œ~zøýBmÑ@1 à:áÍ®DA@@@@@@H~¼Ñ6ñðáØ #óØÙ[LÐÑ¥¦´_¿~½oU–¯fh6ùüóÏM‘~rHÇÐù_¹à‚ ¤jÕª¾E^@ ‡ý%¢6fèפ,£G{ƒyÄÛFº,'ÁFY]¤fAÊÈȼ×ûï‹h0M´Eã"³2׼ʼnÜ·¯ˆô$SÑ ¡ÓN¹î:‘#Dî»/r°‘†iÑ7†¿Š±cEÚµóq†·þ_Ùµ+ü1þ[tèºk®>ýT¤{÷Ÿ1Cdöl‘>}¼uÿ»Å½sš­è»ïD>ø@D‡eÓ¢Ù‹®¼RäË/EÚ´™8Ñ;œfCzòI‘wßyé%^.¸hLªf5¢ € € € € € € €¸W ¦€#½Ì+Vô­[·î3{™Š™)l‰lT±bE:t¨´Ö±Ž( 7Ë/9ýt‘NðVY¢„ÈÔ©ÞŒ3‰8Ú¾Ý;”W:Þa½âvÑ1VÔ¸±È–-"EŠd?Ã’fñÑÀšòåE:tð6@³åË'rç16(‰w×xП~©[×ÛȵkEÌ(˜²d‰H¯^"T À¿ ¦={z'Í$\N>ÙŒ¥uèÐneÊïÁ2 € € € € € € €@² d'ÏıeË–=zèС:&XhEžûLLƱèŽwj/Í~³s§Èˆä9Ü1¾­2£9JŒo_ Ðaá4˜ëúëEþùGdÁï°c:4X­Z»º~Ál¤RÌ„™>ì Ó,UþÁFÁ|÷î©ZUäûï½CÙíÛ|Ë € € € € € € €nÈö#ÿ5kÖl~ùå—ç.Y²¤öøñãeÕªU²zõjÙ³gO¦ë.^¼¸É¶r‚ÉQWz÷î-5jÔÈ´+@ v­[E4ÓŽ¿Ô®þøND† ™;W¤eËðû9¹EƒK4NÆÞḜ†=HG£ÑGA@ Å^yå¹ï¾ûÌßæH  € € € € €qÈMùòå«—'Ožsý¦FÑÇ> ?>9åo°Ñm·‰Ìž]°‘¯:¬šÍr”›…Òç¦6çʉ€]uÕUf˜B3N!@ ¥æÍ›'ÕªU3Úµ¤gÏžòúë¯[Ã@‡ºHÍ´nÝ:ùꫯ䥗^’… †Ú-æuÓ¦M“©S§æz–¡?üPúôé#*T›‚ € € € € €@<¢Êpd¾t_f‚ìó™eò£ØÌ à¬Àöí"7ß,¢C§wœ7`èâ‹c?çÙg‹-ê=þŽ;Âož¯‰ž³A‘üQ½C„¯K·Üpƒˆ&1?¬—‚#ïËÖÄ lÞ¼Y^~ùe9í´Ó¤mÛ¶R¬X±Ä7*ZpìØ1éÑ£‡|`"ûJ”(aþÍ’é(Ø9 +“&M’îÝ»[>UªT‘×^{Íšôä„Ô¦M3äkM“r¹,]ºTþøãÙ»wo@Û´_Ô@¥k®¹FJ—.°-«…&EeÿþýEÛ¡¥¡ƒõÎ;ï´‚\óÇã­ Р)msÅŠͼÊüùó#ìÍ&@@@@@¢ˆ*ÃÑáǾ™6ÁGåO8ᄊџ†=@ ;_~©¥¼ÁF;‹üú«Hv‚ôÜ… ‹œwžÈ¬Y"ÿüº5û÷{÷9õT‘wß ½O,kÍ3.yóM‘¿þ"Ø(·Díûûï¿KóæÍåþûï7ÿÎ.–2eÊXayäÑÌ”£åÀÖÙ/¾øBF%”~ýúÉ”)SäÈ‘#Ùnþvé¦u•*UJ®¿þzùí·ß²]W,êuÝ`"ã&L˜ ]ºt}m2ûÅRû"€$©À“O>)]»vµ‚I¿ûî;Y¶l™üùçŸ&ûéÛ·¯ Æ.jþVyÓ ÆÑu™?ZZ¶l)·Þz«Œ=Úd†üDnºé&Yµj•µîøã—+¯¼R¾þúk»_ wé¼úÜsÏI½zõ¬`£nݺÉÿýßÿÉÚµk­ WͶôì³Ïf n W_¬ëçÌ™cõk<¬GtDA@@@@@ ^Qå/YcJ:u^7F×ùNl~{™ožWˆ¿€y&]$R¼¸˜a?Ä<˜Êù94Xé£D>ÿ\Ì/ý3×w÷Ýb~Õï]?nœÈµ×fÞ'–5Úî’%Ežz*–£Ø7ú¶³‰jÓŒD¤ÃÉèÃÉéÓ§ËŒ3ä¾û)"š©A·—1cÆH¹råD¨^}õÕræ™gŠv¼àý}ˤ¤Ç>ðÀ²mÛ6©\¹²5ÔÍo¼!\p•¢uëÖ¾Ýãúª×¡ÃÌè¹:™qß5‘všÅ‚‚ àní[þóŸÿXYû5j$Ÿ}ö™•ÍH¯Ê4¤CZ4ÈHƒj×®m Y+ýþ£A¸#GŽ”‰'Ê«¯¾*ï¿ÿ¾¼÷Þ{R¾|yiÕª•=bƾõ¬j&! TÒ×5jXûwìØÑªuðàÁòâ‹/ZÁF ‡zHn¼ñFk¿âæ¿à©jÕª¢ýo,eñâÅrá…Zý°70©+W¯^Kì‹ € € € € €@D¨Ž´†ƒ,T¨Ð9æáqe]6¯OšŒÓš5k¦‹ˆ³@ݺbF‰è³)óœ).E˜òš¼fæÇú™޾ýVL ‰˜‡f"•*‰y0&fh‘:9@Ñ<““õëÅ<À‹Kó©Ä! ²ÑŒBæ=^¾4iµÎÖñ÷LÑì&Ãh† >úæ›o¬¡Æ4H‡žÑÌ úª“î§_5;„>DÕIêÃ\}«:Mf<óï/0±žžï3ÆŸfWÒÌBo½õ–¬ôÓO?Éðá팟›¹3Î8à <Ò‡¾ ˆ›„>Œ~ÅŒ÷§u8µxÖ·FR €@L;wî´²M›6MÎ?ÿ|«Òá2Õã̘µ:E*&ûZkÒlG:,›ò|üñÇV ’«BšIëÒþPû¼»M4·fÔã}E3ùÝsÏ=VV¿×MtöS&2[û¼pEƒ˜N<ñDiܸ±5i`¬N%5ª;DY¹r¥ÉjyžìÛ·Ï™{ûл± @@@@@ Dp´nݺíæár[ó…÷4sÆê&à(ã¶Ûnk§_ë눿€I¼×¢ÏÒÞ~[LðF`µæ¹œRJ̯ú½Ù”ôðp¤C=¸o,K&~…`£XÀ°¯>àÔ‡¡šUHœjÿ¢8š]H§aÆùoÊ4¯tÒ¬ :<™2éP6:iч­:¬Lýúõ­I3'é0l:œÍƒ>(ƒ ²Èj0«­X±BFŒ!ãÇ—Ë.ó&Ö+lÆÔǾIðêÃ[*F'Í\á›×W} «ç&2}˜•YéÜsϵ› ,˜éšX à­[·ÊÌ™3­Ÿ%K–XÃ}jÖ>_Ö¡x]‰Ú>üðÃÖ´k×.+0WÏ«“f Ô¡G58÷¥—^²nÃWû3͂ԻwoY¸p¡ìرCvïÞ0iý˜ô“?ÿü³”«¹Z4ƒ öq¾¾M—}ëÿ1cçjÆBíG}AÄÖFþƒ € € € € €@¢8Òsš_Ë®0+Zš/Çǘ/µ/6Cß»ÁD)´oßÞšêš”,ú ×÷…w,íÌêWűÔž¸Q@G¨Ú¾]̰Uζþ£‡œäàA1ÄDºt3œ‡˜L4b²×ˆ òó0M$ïæGôòÌ3"wÝ%æÁ^@õ,$¡ÀÑ£G¥ÿþ2zôh+ÈHƒ4ÃP<Š-=f"Õ}ôQë©>DÕ¿¿ýö›õêÿ°´‡+P÷Ó€§PE‡·ÑlI¤n5’>|ÕIÊêÃY+šÍB³,E*f(P+ðH‡¥Ñ´z\»vídòäÉ¢}) €Î è–šmGƒq4£žoÒ`O×Ïš/–²Þ¤QÔàUß´téRëpÍ,ôôÓO[„b©/;ûjðk‡¬I?tè,«¶Ñ~&Òöjö¢¬Šöy ,°& @ÒLFÇŽ³ó uª¯:Ô›Õ^zé¥YUÉv@@@@@²-E·î:uê¬4_šÛOdÍ—ÙÇ̲56ηf,&rRô—»ÒYàñÇE^xAäë¯ÅdÉ] ó\Êd·ù÷œú#ùž=Åd«ópPä’KþÝjîï¿Et¸¶~ðÇvýõ¡öb]"4ÛþøTþøãfȼåVæƒI“&YÙ‚âÝ>}ÐÚ¤Ikò¯[ƒ…4pH³é1Ñ}x:dȰ»êV½ÆM›6ÉæÍ›í×-[¶XÁIšéA‡–ñ=ýôÓ­ÌIþÃÜ„=@²- ï½`ªýM¤¢Á;¾,x:§N5L$´¾¯¯6éuÒáÌôUƒmô=ßWN0ÑÒzÍȧY}t9E¨ôœ(Úoj ¬N@@@@@-uÀ‘ih%3ÙGÑþb7ÑÈùÈM“ÄEÌèLÒª•w:ë,1ÙcDÌ×#3ú† ¦ó€Ê›](âι´Qƒ†t85^-RÑÌLúz 6Ò%‚"ie½mÑ¢E¢Ãœi¶ͺÀ½ýöÛåqéæŽÅ·ÝéW} |Fð¸~9<©^SÙ²e­©aÆ9¬Ã@â%°aÃéÔ©“ðz¥I³¨YwšÔоI3éüÆíLxsçÎxz BÕ~ìâ‹/¶‡ýŒ5;Rİ@@@@r]@G¶X±b…õƒy}Õêðô»Àš5kZ¯&IŠõ|,ËíóÅ£ÍÔ@² Äp”lm§=$€I°"åʉ|ðÈ{ïy›Wº´È Ab‚;Ä ºÉæÇú¦ÃùðC‘ŒŒÐûÄs­Ž<5}ºˆé“%\€J&ÄpëÖ¬ÛcF¹’õV‘aÃâÙÊô«K‡šÑ‡±{öì‰ÛÅköýãK³!œvÚiÖtÊ)§HÉ’%ãv*B@ ”À&¹sçÎ¢Ùæ6c´Þwß}¡vË´Î ÛliÀìÚµk­!›ý¿T(Z´h¦cX € € € |ãÆ“¡C‡Æµao¼ñ†•á:®•†©lÊ”)Ò«W/{ëèѣͨ Âï£?ôîÞ½»} 3Y h†ó{ï½×•BG´ˆTj×®mž»’ë®»Î0‘Ø—]vYÔÕkÆ:M§ÿgï\àf(ß7~w ‘¢äBT¢¤$DQŠôS!”¨_ J‘ü$!§œ¢œ‰„Tˆ*Br(!T Iôï_Ïš5»ïìîìûîìáÝëþ|ÆÌÎ<óÌ3ß}ížë¹n @êÀë]»vÅô ¬ˆW ŸÆÞþÇg8tpd¡`¸#÷óhcÛ›€óQÛ¶m¥GòôÓOË£>j²¸Ù7^ÇÛ­Žö¿›£p‚𠜚0a‚L™2E¾üòË€#@ŒC‚²e˳ƒhÞÏTÄ$€kÁѦM›Š×¥ÜoêºÁëù™Ò…À·ßŠ\y¥È+¯ˆ<øà‰³†[Ä<˜ž^dð`ß©Çn¼Qdà@‘òåO”ÇR¼ÄF8Võê"W_-²i“¨Xk2p5‚àJ¯erÆ™«#Ý÷ú矌Ђ£‹/¾XàrTºtiƒ7t"J÷¿ž? ¤ˆ`ŸÓ<±/¼ð‚+VL0z{         Hgxgw&+V¨sAÑ¢E­i9ïСƒŒ5ÊñÜsæÌ)… 2nDN‚ŸÔùW­Z%cÆŒ‘SO,{ˆ÷ñO,F+1È«}ûö9ÖaÞºuëÌ4CSì4kÖL† bÜwàJÈ$Èÿó2Y1w#t !‘Š›E3T…Œ9Dž|R•y*̓ÓÑ믋T¬(òÐC¾dgžrWÏ6ÀAO³œDj¤£.:'v™=ÛçÞÔ¤‰Hýú'ÖsÉ=(û‘B "#¤<{Kí°àpÄ   T#€ØiÓ¦ ´+W®TaóÕ2[o .œj§Âö’ xD¤ÄÊJ¤j? „!Û·o÷Ÿ:¤§s¼ýöÛÄFÕÕ1¬Ë.»LŠ)bœ‹ùcË–-²qãFyÿý÷hÙ?¬€ˆ .>]ºt±V9Îã}<ÇFÄhå@u¶€Ø*š˜ð—A6 FxHöÀÂûÅûï¿?`>À¹è¢‹.2þ~5j$÷Þ{o€x«W¯^f](Ǩx/ÃIÄpœ±JÎgÕ©SGû««I•*UäÏ?ÿ”o5MÏĉåÃ?ô…+Ôƒš²gÉ’%®ÓÐùwæ „ @ÁQ0\M‘À%è›oDô·9ª¨TIdùrQ©hꬨvMHau,Ô “èÍ’/5 x Þ¹SdäHQç‚„4+e Ñ`UiMš4Iàñâ‹/JçÎSö|Øp  Ô €vXì(P@J”(‘aªU«–œ…í"T1’fîܹ!ò?£VŽÑæCnY ¤8Xš6mö,ð¾ Y,î Àmè·ß~óïЦMG±‘¿€m¡fÍš&DHV‡6YDãƒCÄûxMˆÙªŽ;Š=Å\©R¥dÙ²eÒó]sÍ5†éرc¥uëÖæ.²oªÃD[ ˆ ŽbA‘u¤-Òœ~æN_ûõR& 2V±«Ìœ)R¾¼Èðá"×]'ª>N™SˆyCÿV맯¾úJ $þä“Oä×_•+¯¼Ò(‡¡.Y²¤ÿ˜°Å|çwdРAF5Œ °…ìÚµ«ÜœìWþ³à @ªøôÓOÕ™°½±!Æõ ®D_~ù¥ÿ!çU¯^=y÷Ýw]â7ª¸®]»¶S_óª¢î›nº‰£b\Ñc!        Ho«V­ ìØ°ÑáÃÙgŸm\~:uêäߊw›¡Gñ>ž¿Q1^ؼy³é—´ª=ï¼óLŠ´PÎN(תU+Y¿~½¼üòËÖnÒ­[7 Žü4¸UYýûï¿òÝwß™N Øpíß¿ßØtVÛ“âÅ‹K±bÅÌV^°‚ãÃ[o½e:wsª]øá©«+ xL`÷îÝÒ¸qcsއî *˜#bÌŽ;Ìõ©oß¾2þ|óàé&7´xøHí¯ƒ™A$@$@$@$@$@$@$@$@$à) nß¾}»é—‡£Oyu€»ÍÉ'Ÿìéq½¨Ü.ʯ©UJg"%Lƒ Ä.8 ËPïã…jGV×O˜0! ŠgŸ}V.¸à‚€uNrn¸ºI Õ¬`¤pî¹ç:ç:ˆŠ@¦@ª”;GÓ&T@:…½{÷FÔiÅSO=%×^{­õÑ̃Ë<ôÐCþìC† ‘qãÆ™r ÙÎᨎhÔ¨‘h¿»}³ù믿6ÂôÉ#û†=rçÎ-—\r‰9ç=zøë³—Á²×œ‚éó¦M›üE:$Páe4”jxßùǘÝråÊr÷x/dC²¸ VÀ(7nlñw3+Ö¬Yc\ì­Ïœ“@f dJpT¦L™&ª–«®g¸=0FQÃå?hèÐÇmI[Ê!·õ° $š\þš7:T4'k¢[ÿãëõKÝyâ\¯ˆNÙ»îºËˆÚ¶m+ 64î pp@XstÌ–-[Öï|donn0ÝsÏ=f5 BÂ:ë¦Ñ^žË$@$@$à%Î;›ëÚÃ?¬÷.zó" "äîÆ ä¯½öšyðØc…*Âõ$@$@$@$@$@$@$@$@$pi±‹(ܘd a gßÒÙ}Þyçÿ¦fÍšù—­…à2õêÕ³6‡qûqütaíÚµþNY1‰ýU,!‡SÀ±õcZ´h‘LŸ>ݱÿÝkNNm ·ýlj! ¢Z¶l™+¡XpvNð6ûçxÏ~ìX.Ã±Þ ¼Ã…áÛ@Fûßâ–-[(8r åˆÚcMÅFTl4Mku-6²·úáÇöõ×_·oâ2 ¤Í"¢iµDòåK‰æ²‘.@LôÀÈìÙ³¥E‹ÆV°nݺFŽß*L·Ür‹™ ¶Ò¬Eªú´ÓN“K/½”b£H ¸H€H æðr¡ÿþR½zõ€üÜ¡ôøã ^¬Œ1"TÁ‚¡ª¸FÚd·£gBVÆ $@$@$@$@$@$@$@$@$@! Àñ.Lv±D&+VtèþÅ_ÈW\!Ÿ~úiÈ:“eCÕªUšrï½÷°6ÆàC¼ƒ&;Vai6*Ç2¡Vnݺ5`H ˆ¨GêÒqµv´¿àt`t<`d4ìßÐaôi- 7¤lü8öíÛWF¼‰ŸI i ìÞ-2eЍ]¢èE;i›É†EI cÇŽF!Žß/!Ý Š¢< ‹“ @\|«ÊèV­Z™.9Ý‹7¢%JAQ°5³UvêÔ©‚[pL:õÔL¥ZUqN$@$@$@$@$@$@$@$@ÙžÀ#<"_}õ•™š6mp¾óæÍóoëÚµkÀ¶ ˜Á„ÖÊÊ•+Ë'Ÿ|"p*Z¥©X6nÜh\È‘ëÆo´ŠÉþýûÇLöÀ I{üòË/FgвeKAê8 |ŒeÄûx±l»½.ü]XOÓ¦ÁÆ] e]°„k ˆhz rª Èíˆ?Å:°ºwÕÎŒpþ@Ê PqàÀyï½÷dΜ9ÆÍ®Ä|ùå—ÍÈëråÊ…ÚëI ihÑ,Yòè£IÓ$6$‹ |ÄïrîââÌÔ,åî$@$@ %€ûn¤…[Ñ»ï¾+EŠqÕžSN9ʼn‡~Šª«1ª(8(yòä‘Ö­[oâg       Hkóç‹`кS|òÉErðàA?þÄÖóι馟±„ S6øÖiò©T)p{¸c–ô}JÔ1œÚb­ƒ fƒu’ÖJ—s˜_àÝT*Åyú%`Bœ{î¹MG†ŒóÏ??`õaâĉ‚숳Î:Kæë—Î9çX›Í\3Ée—]fR©Ý}÷Ý2yòd³~åÊ•òÁÈ 7ÜP>™>4nÜØ˜L˜0Á߬C‡s€qãÆ™ïýv8‡š5kç&7ƒ*ý•-ÄûxA‡ÙÇÌŠ„:uêdjVCàn”©|,œg‘€kÁ‘ ŠžÑcéåÍú#·ZG9ÿ é…ZëBÍóæÍ+wÜq‡™ ´D'.(üXöêÕËÿ#ª®'D€á°a¢£ÿE4HtkxüX€ÃZ—.]äòË/7‚ÈÓO?=Õ²  ˆ;¸!ŸUúú¤¾°þúá‡Lú5·õ° ăÄÃsçŠàwWûÙ4Õ–ÈèÑ"jÀHaÇŽ3©Ó|ðA)S¦Œ,\¸Ð(ÄSø”Øt  –/_nF’e·—°PF:PÜ_ãN}°M~4vŒ-…Tlƒ–>úHjÕªå§ ÌSÁ’Ùßh. @œôï/²oŸóÁàBýÇÈ]wÝå/P €ѿЮÈþãûxÁþÕþ…pÇð²-$ê¶&p1)hóæÍþ=ׯ_o <ðn.T`à!"bP"í“=àX4SUxÇ7 üñÇMFJ°¥K—š ™KÎ8ã #>ëСCÀ;Ìè†x/\[â± G}úô‘nݺùݲpÜ{î¹Gn¿ýöx4ÇH®G¥5”Ç6&ý¿ûî»¶ÏQ-¢ºÞ*ÃmÓ¦?äc,Uª”ÿ3H ‘6 .~zm–o¿É™S´ND³ŒÈ%—$²e]]çš\Ùýõ—Qu3&,ãZU´hQ)[¶¬\|ñÅfŽe×­µk×Ê’%KÌ„‘<¸N#gvÉ-[¶4–ÂnÚ© ÜvÛmæÚ‰‘TÈçýꫯÊ?ÿücþ#íÏí$@$@$@$@$@$@$@™#`9“dnoîE©A zõêfÀ\fZ‹wéHf ŽpΣ5ý œ²àNÓ¼ys¹ì²Ë² ¸a°#&Dzü±|òÉ'šªp…Ñàý¤SÌŸ?_ûuï÷ß߸9• ^ïãß«Ïû÷ï—=zÈСCÙ^ìqçwC†Ü¹sÛWs™²LÀ•àHFvÁÑ!UîÌê‘óæÍkRY–pHÁ d P¥ŠHÛ¶¢)¶Dx@DÿTÓ*`¯‡‹Ñ_|‘–‹N_¬I¡„ÆÍ:w‘¾7¸á€³Ú7ÞhNûr @ö"€«þð›>HåëVpTEo öîÝkD=;vÌ”#ÞgŸ}f„:x8¶ùÅ­ £jmݺu2gΫˆ™cT¤÷÷ãÆ¦Š+š 5kÖ”:uêöu`TÑÛo¿mF»à¾‚-¼Ä¨]»v¬ÅúH€H€H€H€H€H€H€”ÄF÷Þ{¯ ƒ²3K4H[tÂ1Â@¬eË–8Ô`päÿþ÷?3a0ýu×]gú»àðS¢D‰°õ¥ÚÆóÏ?_î¾ûn3¡íÅ‹ûûýÅĤ‰™fe&â}¼Ì´1Ü>x‡)÷Ýw_¶qmŠë—ƒ‘ @Š˜2eŠlÛ¶Mš4i"pÂÈ FE<+ì³cÇ9ýôÓ͵qذa~áQáÂ…#îQ8Hq6yòd#(zøá‡¥k×®‚—N×3<nÙ²E6nÜ(6lðOp8BvŒ0ìÌ3ÏŒxì¬ÀË ¸‘¾þúëÆŠBÞÇ{,«Õr       ð>ôá|Ì  ³ÔëñNóà€º•R ÛÊ•+'p°i×®«ÔbÁõ%ûg™4hÐÀLh"…Z¯^½Œ’Õv šÄùã½fV#ÞÇËJ{‘E ‚Õ5kÖTmÄ}P §| xEÀ•àH;EöZ Ðå¢çw^UQî±ÖevŽŽ+à> H,áǤpÁ r¤B)p1ƒÈB… ŠT<Ãv8Aè„Î\ˆžòçÏoTÛè$¶wØeÂJfûtèÐ!«˜À ðæ›oö[/B•Ì  HOëôë×OÝ óÙwÞyGàpä&>ÿüsS ×F<õìÙS  øŒ5ˆY-ñÞ "„ëF¡,Ò¥Õ¯_ß8,Eza÷"¤/Ä}p9‚E3Îç‰E        ØÀûõ_|Ѽ‹/S¦LìÀI€2øóÏ?3¬K¶½÷Þ{&µœ{0à~Ïçîùõë×K÷îÝ¥oß¾æ=hË–-cr:ÉÈ)gΜš¡æAÚ¹«¯¾Ú8Ô['»råʘެú0÷ñìÇŽ´ŒÔixO}äÈ‘€¢Èô×ÿË/¿<`=?€|¶E‘kð%Ë“'OÕÈ»„/qôèQ3rÛ*uöÙg[‹œ“ $€:EÑ9Z¬X1™1c†±nÅI¤8|ø°ÜvÛmÒ¾}{)Z´¨Àºqâĉâæ&dçÎÆ1©mÐ!Œ9œ pÃAÒÐà&êÑG•Ê•+Ë?ü ¸iBR‹ðð†¦M›št5 ,07èP~ðÁ…b£Hß·“ @ö&€Ôšk×®5!ˆfàšçVp„‡SZo¿ýv³ßìÙ³¶Ï”âÅ‹›tfÂB8´h áEF@°‹¼áH“Il”ŒßFDé ¸›škª©Û’ñ¼Ù&      ô%€çþÞ½{ ÞyÇ+mîüˆšzÁÊ6bVð Ïì۷ϳºc]q5dܸqòË/¿ÈŠ+Ìï%pfü~µnÝÚˆ“‚·e泜 †jÞ¼¹™²âª^ºtiyöÙgNë‹/¾øŒñ>^†x°Žô 6”:ˆðïÄáŠE±‘àY¥#WGš®h9:P¬ÐÑÛ7èò\ësfæèüèÈŠR¥JY‹œ“@B´i#*j½'äð ?(Ò¦üüóϦµV­Z&uË„ Œ³:UCF^À­¬ÄþHkáÏgœa.vè°D',ì­ ŽF(‹ ¬+Uªdn `‡w„ M'/:z$@$@$p¸õ `§‹‡Näø.R¤HØ*áp„ôev±¶˜ "š5k–¹—… ©=1Ç„¨S§ŽyY˜Ê/ !¢êÒ¥‹yQ1ƒH€H€H€H€H€H€²3tä#% :qñ®|ĈrÓM7y~Êx¿¾zõjéÖ­[À;ÏÌ@šػןÜ'eHà]cµjÕÌ¡ \m–,YbÞSÂùÿüó1 øÏþ“åsó‚ÓÂ… ÍûY4ý‡/½ô’Й™Æ§Oƒc\pÄûxÁÇ÷â3DTo¿ý¶¿j¼Ë…ÃUÇŽÍûpÿ.@¸}ÿý÷Ÿhz‡_Up.Ú¤)ª³ÈªÌ¶ï·ß~3ðöý!p`@¢¬Ò¿æQ£DÓ ¤§à£(à0÷(ŸÏ<óŒÔ­[×Xî 4Èñ«ãnàth&âÿ÷Ô©Sb¥7ß|ÓLN;ãâWµjUÓ™ W$ Ä’Fû,[¶Lî¿ÿ~ãÔƒº­ÐUzá'8‚€èË/¿4ÂW'ÑЭ·Þ*˜²{`„ & dwx±Q«V­dÚ´if0Q‹-ä•W^‘ xrúëÖ­3}ð~â|f dÄ6nÂÉ ÇÍ~ÉTÎëøˆ©S§N‚¾ömÛ¶™&bôû9E"9,XÐ/8Bÿä·ß~+*TpjfÄuÁïx‘%8â}¼àãÇúóàÁƒeæÌ™þjñ#ó ú\$'»<èÿi¹ÁVY¬Óë£F*i­s;?¨ŠŽ¶mÛÊŽ;ü»à?ÿøqp!ÔÁDçÎ 8xrÒ¤I²uëV“Þ̺ãÎCúÿÜÜ”85ó‰'ž¤bÃÅÍrA;çœs¤]»vÆÖqóæÍòꫯš: ´]¾|¹lÚ´I`Ág£¥K—šlNus d…Ò‚B,„QV\qÅf1RZ5<äâžé<$@$@$@$@$@$@$@Ù›ÓtEHQ4fÌY¿~½Ô¯_ß ª-[¶¬Œ?>æÐÙ‡ z‚£š$@Ñ@¶ {lܸÑþÑqïþà€ž¬Ñ§O)W®œ™ªT©âª™%K–”Gy$ ¬Ýí'™8]{íµí=ztÀçh> ÒÁ$l‹÷ñìí‰õ2Î×þ¾ÙbæÍ›GE¬A³¾¨¸r8Bšþ¬¿Þðܯ‹%ñYG§ôïß¿þˆ›5kfn¾ðG*vîÜiœN¦OŸn:pìåæ*L $ŠG5kŠ*hÕ‚Äé_Ð)‹´1Á)SJ¥qãÆ&ÍÚ /¼ÐÈ÷Þ{ÏØõ!eTÓN¡NhtFpÃu$@$@žÀ‹Á¹sçšÔžö”h)›ÞH‚#¤SC0­§§_+'      ¤ €Nz Z8p iOñâÅM:uôgaÛ}÷ÝgDAÈ„·(‹ÉZ†Þ?@œT¢D ôŸEfåÇo^Dbdpè½­¬Y³FðPÎ       ð–žóÑ™úᇗ¡gŸ}V^}õU#jÓ¦<÷Üsæýu:uÌóü¸qãäàÁƒ‚4fè\¾ûѣGcм¼õÖ[F@ä¦Õ}ûö5N(*Áy(\@x„É)à"R«V­€M7lÙ²E00jÇŽ²‚àœ«T©°? dŽúœ[µjåßâ?8ú”*UJ*T¨ ©À4cß¾}¦LÞ¼yÍo ‡ñ 8¯ÛcÆŒ‚¶ #Ää€ÀÈ‘#¥jÕªF¸ˆßI˜Ìž=Û ²ÄoÎ â*ˆ'Nœ(H»f„M0ŽdâS’1cÆQ©½/½ô’`Ê™3§qh‚˜ BMKÔù믿ڋû—ñ.׋Pïã·cêÔ©Á«\¾êª«Œàhýúõû,^¼X0e6àDÁQféq?;¨GØYoŽë¬Î+êAÜÀýõ×_öz—‘ŽéÁ”{î¹ÇüP8ŠãJtF! ltRIf¦)àðûï¿›ÚXÕiµÃ˺­c¤Ó\¯Ãêê#:‚AÔ*5ÎüĹâ#>ð@*ðwܱcGéСƒyhƒëÃV³}Šד@âðÚ–8ö<²÷ðp}ÿý÷ ^.âAÈ ,ðVÁ Q^D:Ž_}õ•8 Ž0"ÿ®¾új§Ý¹ŽH xmKt’H€HÀS¼¶yŠ—•“ ¤ r…œ-0èí½{÷6‰ "B– ˆ0!ðÌôgÍš5¤NGÌ;×¼ãÆþxžçw2¤G3mÿ sÎ#@Øë@V¸”§i‹õq’­>^ã’íIö´lÙRþüóOóÛ€t‹VüðÂÉèƒøNeñŽúõëGuˆ­€³R{öì±V™9ÒªA@ëœÜdRÃ#Ît2H6NÐ À… ×ËÍÉ‚€w¼k×®5“µÎiŽëú8áR)£R¼çÔÞ¬¬³\ý²R÷%/dJpd5D­ºŽtëÖÍüà!Ïä¶mÛÌ´}ûv…$lËJ–,i~,0/T¨P[8«®xÏß{ï=sáÁqñ£=a„L7aÙ²e¦ã êù_~ùÅÔ~Ì¡˜DþD«s+ÚƒxYw´mÉnåÕqUÞxCäæ›ÓSp´|ùrc;Õ7:mÃÊôêÕK`×Åô-·Ü"¸1b $^Û’ëû`kbKb£xÀÜsáÁû)§œbÈñ@ ¡æxð‚…p¨€îÓ 8rŠÏ?ÿܬΕîT–ëH€¼'Àk›÷Œy  øàµ-¾¼y4 ä&€çw¸!-ú›o¾ÐYŒAEè„Æ@Xˆ>þøc?ú\‚ï L‚¸§]»vR­Z5“n=\– tPc7DJØŸ‘u¼Æe!kÈ<8¢CèשS§ â«V¤nD*.¤ë‚[P¼b'$!°Ü´iSÄãOn2¿kpdxß Ç78·!ÓP¨H6N5kÖ4™XÆéSKþùçPMX§{˜œÜ§é×Î>ûì€má>ÄûxáÚí6{:µh÷eyð’ÀIY©\•oêþ-²RG¢ö…7?ˆÌ Ž`…‰ RRE ä¡ìׯŸ±Æ‹TÛ½¬;Òñ—,Yb¬ú`Á—]BauT›TQ>ÑŠìy¦°‰1b„¹¹‚…+&¨¼1G>[üA9 s¤ÀMÒÓÀÆûºÙ'RÜNÉHäuÖYÉØ¼°mâµ-4ˆQ#ÜÉE¢oäÇßoݺug‰gÝáz”Ù€í0Âq ŒtA› °d§¼/?“@2À ­yóæÉðáÓ¹™ÚÆk[$þxÑ!&RO0H€H  àýÕ¨Q£²4ˆ0Üxm M91ÈÍÍ»Öеp @ª@ç2Ü600¿éÈ‹Xºt©ÜqÇæ¹)× f*S¦Œé€·Ü/p>”CJ£d Ž‚À Uß_ñú/ ý4诱œºB—ä–X€1î'ð "¤Ž‚›æÑÆÛo¿- 6ôï6yòd¹ë®»üŸ3³w%¤\„èË0ì@û ˜r ”y÷ÝwMÚHì‡ F 0¸à‚ LZ,-áMÄ’S4Ç UnOȲƒLXŠ ÙVà„„4y˜ãºáÞïf%â}¼¬´5•÷Åw'Á>ø •OƒmM Ø©¡·eß-ÈщY 䈄jÒn{®>ü'jܸ±y âdcgß×˺íÇIçe¤RCJ5½Ç˶b#&`+ Q‘=p†Å n\0BÄ­p衇2ùTÿûßÿºÞÇ~\.“ xK€×6où²vo 0ÀXÞÂBˆêÕ«›`¼ô³Â.6ÂÈD8eEl„zñð »öƒ FLÚG¸6Rld§ÂeH ^ÛÃG% ðޝmÞ±eÍ$@©EïZ·n-¥J•’ùóçÇLl ×]wàÙþÖ[o5©Ùž w 8ÄGëׯ7ïÈ‘R¼ÆÅ†#k‰ ˆR0Ù…B±©96µÀU ïÝöÏ¡<~ÓbÉÆ)Ož3tùòåsd2sæLs‡=äϵòê:öxå‘#GvqÈý˜Ù@H1eᜮ¹æÓQeåþýû (]8`…œÀ]ºt1£¯B©.½¬;³ç›Ýö[´HTø%ê šî.µÎîÛo¿•"EŠH¨ÿk8tÚ¹]¡ú3fŒqŒ€ÀþVCýý…£&n,ÃÕÁm$@ÞàµÍ®¬Õ[]»v•^xÁØ;Và^„kVíÚµÍä'‡M:Ü;° b#ÜSfUl„³Bª[ر#›ÝŠ÷o=ûa @b ðÚ–Xþ<: @ì ðÚ{¦¬‘H µìܹÓ8ÁÍÎÂxǽpáB)\¸pÌOÂ"¸dàXèÂ;¨5ÿý÷¿É={ö”’%KÆüØéX!¯qéø­óœI€H€HÀG 3‚£“Tqù”îÞUè~Kع… Øá"ÿ.& ®½öZéÖ­›±ˆ µO¬×cû"UšLš4I"幌tìiÓ¦/`LJŽ0t^ÙXwÞy§ÀÆ'-[¶ÌŒ¨G~N§ð²n§ã¥Û:Í$¦9=EÝ D† K­³‡£CUHA0·,ŒÁÿ%{À ©`ð †´Pø{ºä’KìE¸L$ðÚ–¾Ì4:8Áb{˜^ˆ«T©b쀑g¢t¤îìÕ«—Œ?ÞˆŽ` ‹àXŠ€Úºgƒ­²]pôÅ_á.Òí2H€C€×¶ÄpçQI€H€¼#Àk›wlY3 @ì `À+úzŠ+rÐ+Ä%ëÖ­3ƒx0ûäÎ[ ,h&dx°–Ñ7„l–ðÇj1\=&NœèÚÝÃÚ/š9ßÞ|óÍvÁ€Ý={öH¤LväŠ xË€„+²!?þø#à¬b12 B~  '•àH­Õò«`hœº£Ü–ÙóÆÍ(äèàyùå—+Pfë ·n‘¦ã‡~0Ó¶mÛäèÑ£ávqµ ÎH#GŽ (Û§OÇUÀý€ó—^zɤ¶²¶Aâ$8ò²nëØé>ïÑC´ãRdà@Ñܦ©C£1 $BWX¾Z¾‹/¾Ø8?Ü{ï½ÆE Ž ?ýô“Y7xðàù^SçÌÙR ;^Ûì4¸œŠp/!6 o¼ñFAtX×Z<Ü£G–gžyƤVÈÇújI‹4jÖ10·ò™¯ZµÊ¾ÚX®cÄO  øàµ->œy  øàµ-~¬y$ ØÀ38žÙ1PçuôoXÖ[£cÇŽùž7o^ã.«DéÒ¥åþûï7ƒ‹jÖ¬iRù+ˆóÜÿ)6Êt^ã2Ç{¥6µkל€®là H1ÑŽNVg•õü.Å9îݻפ%Cº 'ñMV›ß`aPVëÄþ³gÏ–Ý»wû«BgÙm·…×_a=:®7‹Ó?þ¨‚—@Å‹—uûœÆ :ØBEh"0-Pc…” ¸cYcï¼ó޶¿²lذÁtȾñÆÒ±cGÓ1‹‘'x„‹W³fÍRæüØP ÷xm ¼nº'Ç’É@à°Ú ¡ïÝwß•FÑQ¨Ap67nœçÏŸ?S©@Ãó9çœc^nBoÜ«zê©~A’}—I€¼!Àk¯mÞüe±V H^ÛxmKÜ_L™'0}út¹ï¾ûŒ¸¨eË–&cÞKc‚ðâÅ‹Må(„A+V4ôè@u³í÷ß7}'è??æ#]wÝuR´hÑÌ7Ž{& ^ãxKš?F2jÔ(ùúë¯M¶¸´Y÷†phc œ pò‰ÅðK]tr€ˆÔ’òH›6mŒõ%Ra„ ˆ£zõêE †îÛ·¯@|”*ññÇ4µvíÚŸC}>wt¶‡—u+Ý>cP†f 3¡÷ r²ë¿üÄ’‚%)à`= q‘•â¥lÙ²Ò¿óÀǬ믿ÞüÿúòË/)6JìWÆ£{E@¯2hh‚w¯Žà«WE}wÿö›è°,o“dµ{yýñ²î$ÃÈæD ñ,îZµjeR~†Ù«Áý%Fz„¯_¿ÞŒÂ´ê‡£àe—]fÒ—Zë8'HM^^¼¬;5i³Õ$@$@ñ àåõÇ˺ãÁ†Ç È9sæHóæÍ»þ| =4M܇,X`R§íß¿_8 ˜oݺUfÍš%Ý»w—Ûo¿Ý/6B Î:ë,Ó¾ úŽÐ7D±QÖ¾ŸtØÛËë—u§Ãw“®çˆC‡•E‹dÏÁïÒÒõ¯‚çM$Š€[‡#È3ºÛ+Q±Ð¬yóæÓ›Å&öõNËùòå3.Fp2Z±b…tîÜÙ(PöСC2|øpyöÙgvÍôº“UQÒ¯_?Çý¡¬‡X#3Ž(+ÐûO7œšnmÛ¶ ØÕ˺”†4»˜ŽÄéÔIUs²¹ä…ÑH‘5ÒöÁ"8ÐYÛ¤I3oãgÈVæÎyì1Ñäñ"·ÞŠ7±?=(õúôˆ^#þOX’1xm ¼n&ãwÄ69€sRêâæ˜1cœ Åy-GHé¶fÍ#èݹs§ìÚµKbô7†A$7¼¶ñÚ·?6ˆH€âD€×6^Ûâô§ÆÃ@L¼÷Þ{æÝ2Ü…áb„ÔgNqÆg8­æº4#Àk¯qiö'pºwÞy§Œ;6`? ˆ¸©=œ&¡’²6`=z·ŠÔ+&º¸æškä­·Þ2®-PÄ#&OžlÄ7 ˆ®²0¥!‚ÒÔ)¶lÙ’)Áöû ÎÇ£B… ‚”n£åÕJNñý÷ßìæeÝJÃûö‰<÷œˆfgÑ‘©à©§žŒ.AÞì.]º¤NÃÙRpK®EnKÔ ON;MTçØmž1CäÛoe¢^‹î‚°) ƒ×¶$üRØ$WàÒ‡xâ‰'\•G!Ž«V­2‚#+õm°H<má1H ðÚ–Îß>ÏH€²'^Û²ç÷ʳ"ìH`É’%Ɖ(Ožùä3(úp9€i $‚€—×!/ëN+3~Ð?‡Œ=x§Ù­[7Šâ‡žG"HA®Žô¼ÔæD¨àH-&²uëÖÕôVi£Èý[£F¬UêñÞvw# ©â¢ ä0¶ê;óÌ3Í*/ë¶ÓÍ2œ§ÐžÙ³g›â§žzªüç?ÿq³kÒ–©];i›–¡aKU\Ѿ}{c_;sæLÁCƒ²õë}"œÜNÔÉ+l¼ø¢È)§ˆtì¶Xf7Bü¹AÓ^½nlnÔHö©Ëé^^¼¬;Úïßóï¿ÿî¿¶aÿúõë럖þm1<%€4²{öìÑÿÂÞüÎlãÏ;ï<)T¨_p‡#Œê,W®\f«ä~$tÖ®]+pRE¬^½ZöÁú3 ÂËë—uGûÕüù矂ÉznÃþ7ß|³šBª+$ƒH€²) Xܸq£9;,ã?ÂËë—uGûÝ9rÄ<Û¯mµõ¥S9EK’åI 4C‡ɬY³¤C‡¦Ðüùó¥R¥J¡wàÏ Æ:}/‰@?ÙÁƒ=?f2ÀËë—uGËïÆ~øáÿó²§${Ÿh´çÈò$@$`øñÇýïÝùå(k;çÙ‹€[ÁQ)Ûiýî»ï¶Ú>gj/AÏW§ Ü@!¶mÛfæÉüOðKŒhG–¸È:GÜì”*åCëeÝÖñÜÎÑ)‹ÎŒl@@ð’ê‚#·çž åz÷î­Y¦N’yóæ¹NÙ— ífÒÀøñ¾gÈY+1·1eН¤Z‘Êܹ" ЍÕ1´sT,¹ë.‘2e‹du%⋌-«¸r´ C!„=vìXV«M™ý½¼þxYw´€ñ=c²®mØ¿^½zE 2å‘Níä“O–æÍ›gboowãÒ‡~h:5¾øâ ó’•"4o™³öø@‡,þÆ?ÿü³§Ä·‰9š—×/뎖ÄFýõWÀµíú믧à(Z,O$RÐ)kÝÓ£ãîÀ)ÕþÌ6ÖËë—uG{¾ÿý·y·¾cì_µjU Ž¢Éò$DëðÿjÒ¤IFìÑÜàýsµjÕ‚Jóc¼  oÌúÝÃo2îóÓ)¼¼yYw´ßúÜìßuéÒ¥)8Š"Ë“ ¤ ]»vù¯m¸ïÀû+Fö%àVpä·zPw£S‹+–sÇŽ‡³Š¢ +vïÞm-&í<øæ$ر(RÃËÛÕÕ^Ö©]ÁÛ!+£ûC‡ ÞÄÏÀ çâÅ‹¥‘º¬\|ñÅÕ'”Àaý ;V¤m[º¸ }ñ¦j‘\¹\÷´RÁyè×_ET$g¢E Ñ7ƒ"– (TÔ†TŠ}«!j%"òÎ;¡G}ûújQG<¯â<ð¼ürÑDÌò¿þýeÞ¥—júÅÉ¿(^^¼¬;ÚS‡›MÑ¢Eym‹\ËãeÊ\Þpà †«‹ùîa4çÛš{¯L§sĬ0Á7n,˜ø¿ˆ…t/¯?^ÖíwS @9ûì³ym‹Ë“ ¤4 ˆ³Å-Y²DF•Òçã¶ñ^^¼¬ÛíùYåòæÍkžÇùNÒ"Â9 øUßÃÁÁâKLÖ2ä×Á€pñ-X° ™° •åË—ËôéÓMFôÇ\sÍ5r÷ÝwKÓ¦M÷“ŒÄÀ;L¤}ïÑ£‡YN—¼¼yYw´ßÏ…^hžßž}öÙhwey H9UªTL5²‘6mÚ¤Ü9°Áî ¸êåV‘ÑO–8Hç'åÊ•«¬b•ûÃd,‰ =ì­À q²GðÍI´Gxh¶‡ÝÓ˺íÇL§å D4‹„tîùJ"U ÜUî¿ÿþD6ƒÇŽ!CDž~Ú—*ìÁ#QíåÍn©‚ ͉‚œŽ‘÷±J¨{úŠ<ü°µ&ësM‘¤>ö¾ÿ`¹sûêƒøH_øªŒèðCçc í›6ùÚR¢„Èš5¢ùËêMˆ¾ HÅŠÎeb±V;êTé'òÏ?±¨-åêðòúãeÝ):M95ÝZ©)íDSjéS¸¨òËÛ³Ó<éòüó"­[û„5½zE>,?ø@)ɆÑ—ã´ÓD•l"Õ«ûþC|ü±èXÄÝ€uÔ~Ù8.Y…o»M¤}{Ñdð¢ù[¬µóiÓ|lÕ¾9lüô“Èoˆú<‹¤Àõ!ì¹$ùF/¯?^ÖäXÙ<%«ÔO>ùĸåÁo^F©R¥ŒítèЪ 4%¾ÿþ{k“ã|½ ºjª¢ë¯¿^Ó\iž+[t סl+—èŬޜÀÆÔ±…«Û~ÌtYÖAòðÃ>íC*œ3ìmßyç¹ñÆ™G;ÔöÖ[>qN(çœàý 8yôQ‘™3E4ÿyÄøê+‘I“DêչᆈÅcR)¼^zIäÏ?Ež{Î]•°IFZ²þAZ2ìë& ÌQ eý!Ù¼9p­[}éÚ×:Âï8Õ¨!rÕUË ­š:…Ȳe·Á™ a¥Só}Êø/öí5Í/¯Ãº2n·Ö@Ó(ÕÃ~óo-„[pÐùêõF† yäÑdö>¡Ó‚¾4mVœkn;†hÅ´á®?^^7ímæròÐ{FÍN9Áؽ߯ßÔLb°GL§–I€Ü’€—×/ëNB”l @’ðòúãeÝI‚Í ¤&pXß[6ÕÁyÈŽ0yòdãl”Ô fãH Ƽ¼yYwŒ1°:  HY®=9·lÙò»¦Q»CXÞS±QnëŒ7nܨýå/™ ö„ i_ø?þP3’Ÿå'Mª7Ó5kÖ´ªKêyðÍ Î+šØes0Á{~e/뎦,›p8zô¨Üÿý‰i@²N7;Šþ°øDnÚ QÄ(=&rþù‘÷xúiŸëÜâ8Õ®-2nœ¯­ÙD ¸p¼ø¢ÈSO‰tè 2v¬o8 •)#rñÅk@nA”»î:_jµ¥K}ç»gHݺÈ}äK]V¡BÆ}GŒð9EAɇTnø>‚ݬ½ 8Ò´€&­?V@†tjšc^"¹ˆ *zÑéÔ)²R÷î"sçúìÌ Æš?ß'Æ*\Xßi‹>'(œûŒ"Ó§‹æw.fµ,íç^^¼¬;í¿¸$°LE‡?¨£Y'ýœìiB¯ÑÔ/¿ü²fo¼6É©²y$@n xyýñ²n·çÇr$@$nà¾YÎlÚ´É̱ŒiݺuR­Zµ´ÀáåõÇ˺ÓâËáI’@ tÐw{ø=ëÛ·¯T¯^=‹µqwH=^^‡¼¬;õH³Å$@$@$à ׂ#^]Œ–_xá… tÔú n\Z0¹FIÏž=ÝOx9ˆ©ìñQ\^ŽØJ+VÔŒM'ù÷ö²nÿA¸´—7¿p c8@ /¤âêß_TÕèP h••Š+~wÎAp½Y¼X)Î.½4¨²8|„ËR‘AT…¶¸ ¤Tûà‘×_µÆ©UË'®9çÑ·°¢=ük+¬¿oiÆ pƒƒÊ&â$6Z´H䡇|®FêÂeÊiL°È)P¶Ïž˜¾mÅ ‘;D:wvÚ+pÝêÕ¾:/RÀeéÖ[EæÌcÔ-·œ8/+Ï=D\Í›‹lÝ꩸€q‚€—×/ë>q\JFo¾ù¦iV²§SC#q?ºCŸŠ-šŒ(Ù& LðòúãeÝ™8UîB$@ÙžÀÎ;åÊ+¯”`gÕsôÙ·H‘"òÿ÷ÙžNÐËë—u§Å—Ó$,€3ðX$WO$>s HC^^‡¼¬; ¿*ž2 8pè‘v,ç_©#ˆíÛ·¯ŒŠŽzçÈ‘ã˜C *ZÒl9¯©AÇ‹I?êÝ~Z]tQÀ>FV:tÈ^$ä2ÄIÿ Òñ¨ G[xY·í0Ù~ñàA‘·ßu JS]¡B äéF§lΜ9S§áñj©º¤ùSdA,ã&Ù¶Í'6Rǵ°—“x ‡ÒŽy:JI›¡k¾â ŸXháB|Ü‹pEBª°¹ûn‘ýûE ÎrYu .CHe ±\ Î ¢"§¸é&ˆ›"M_òê[^Ÿh âžP1Ä=_}¢„Š,ÕÚ':±Öy ND+WúDÎ%×"Åœ‹¶oÍMèCYb#{É’%Eàˆ„sbø xyýñ²nÿ p!é@d=]ÿO¢c¨|ùòI×>§QläD…ëH u xyýñ²îÔ%Ζ“ €7¦÷¾ûî3b£'ô¹¢öÏ>ûLöîÝ+{Ô­w˜œð(ÂËë—u§ÃwÃs$Ì@戇ô}žGá~oœœÙ:¹ ¤"/¯C^ÖŠ¬Ùf  ð‚@Ô‚#4Bê¨ðè¹9sæÌnÒ¤‰k‘D¡B…T7ÐGûƒßQ3ŽZ^œ§u"%HýúõýÇÀ(ªåË—û?‡[øè£6_oO5¤[¼¬;àÀÙüt Š>¤¥Î‰Ž=Ú4–éÔB|gÏ<ãK¯¥énôÇ&D!Ûj¸¬é.-Ò¾½mCˆEü±¬]ëK敻ň\~¹O¢ò "¹rù\ŽþþÛ—,TYk½¦± ¥ÊG‘%KDš5ó¹ýXÛæ¹s‹¨£–h~x³OëÖ"Ï?ïTòÄ:8K!5\¦¶,Rê?Ëý.GVäÉãKˆ”on"š—Ægœ!Ò¸±O|å¦n– àåõÇ˺N‚’ŠÀlý¿ÿûï¿köBM_È  ðòúãeÝ @ÅC’ @R¬î¼ï¿ÿ¾´iÓÆ¤Àm¡Ï¥W_}µä‡›qš…—×/ëN³¯‰§K® Ö÷rèWÁ|²Ð Nûäº"$l@ÀËë—ugô<  ˆ “³RK©R¥÷îÝ[Ö¬Y#K—.Õ~ï FPô ºmÜvÛmfR=Ô„cœök/1ÓwÜ‘R®FÁ|n·:Òo9rdp‘ Ÿ÷«ëFú[QR]6”õÑ?÷²nÿA²ùÂøñ>͆þ™¥D8p@¦M›&U«VMˆ°H+¨ÿ×eóæ€Õa?èE=iÌ#Å—_ú\|2 i³Ü„þæÈˆüï‘JÝÀÝGÓÙI§Nákÿé§ðÛCm:Ut¦DGùò…*%R¼¸È£ú\àÀ7!|"ċÇûŠ*ÍMÔªåK‘!öpSR{g“Šmî\Ÿè(Ü>×^+g)»à(\ynK8/¯?^Öppl€#ŒÏÜàö(p×Ñ—t1gŸyï=Ÿ£ÛÊáTÔ±£È/úS)EÚcùÒƒ!M˜›Ø°A"ÀêÕEܨÎ Ù±Ã'¤sO¨è×Ï'L‚’¦Vtp*Bê2 lŠ( ÷!pš´gH—æ&t´gÔq×]Ñí’#Gäï˪éÖ®MEòã>1•µó¤$àåõÇ˺“f7Jï#å›o¾‘…šòæ›oHC›ÆXxê$@ "àåõÇ˺„‹‡% ¸øçŸ4óö×R¤H3…:èßú,ݼysAg>Äìyà˜Ë/¯?^ÖͯŽR‘ÀO:ðïÿ7mÚd&,cBJG¼çÇ„g`{œ§ïñZüŠ+®ðO%J”0ƒµß~ûmÁ´zõj³Ëé§Ÿ.mÛ¶Õ׆ú.A$Àk\šÿ ¼§}L-[¶  €{Á~è—ÉDhv1F´G¬³u õ¹šY¢páÂrà 7È-·Üb–ÝÔU¾|y…=rjÖŽuëÖeé~)8Ñ–à@&82«tïÞÝiSØupÜ»øâ‹ÍÿI\Ï Ø—pQ»vmÙ€¾¹ã,G•*U²>rN$ŒàHÏóFÐÑèÃU|´BS…ÍÒæYª¸wa¯‘”‚NVÎ!˜8½zõ¼4ÁH~Œè·b×®]Ò¡CÓùf­+£é„Â¥ñ²n« ÙumLsþûßÔ9C\ôÏÐtPwE+þp{ŠÔ U׸Á±¨BÑ?äÈGX¶LdÁÑ·€"—^š±¼þŸOì¡nhÒµ«è‹ÏñǾ-x.H,Ò®sýÁåñÿ/qÜH£¿ÿ^DÝÙdÖ,_êµH7ŸiñÚŽv¹ ”…KQß¾"nR„u–\‡à&Ç¥ÓNs{¤ä+78ü§Ô›KW©í’ï Ò®E^^¼¬;í¾¨$9á/Õ/¶lÙâŸ~T!î‡áîu’äØ  4 àåõÇ˺Óà«á)’ ¤ tƯ\¹Ò¸¢Ãù|ùòå§ç3uÀÏ }_qß}÷9’èÖ­›é”G'I•*UˤëJ/¯?^Ö®ßÏ;õÌÒw…øm‚s‘=rè@¼ .¸@J—.-¹sç6DCÖò¡C‡Ìïž“çÂüxäÊ•Kþúë/óé}7ø_}qÝ A©S§ŽÙ×*Ç9 €˜ªìwKÏ¿ô“¡?ÕcµäíÛÂïo´t•Áõ¹­c¨‰' 77nlî]!šp¼ƒ058 €ÊJ ²¤8O8w=˜a8íܶàÏØY¬¸êª«dèС&­±µ.x¾{÷î€c rƒËó3 @ö# *ÐNÈk¨Z±Æi§ö²Ú¯þ÷ßgA€¤JjíÁ¤‹C 9\$ÊGµ ½eܸqªÕ¨ xøâ‹/dûöíf»õÄH={ö {ô²n«©0‡ -„Àú ç:ÞxCÔeKôÍõ. -w¬Ï?ÿ\ànÑ‘'T~¸ ªY3rõ¸B¹ZµDÿ¸#—æÑ?fÑ?êÀ²pU‚ "»«Ï‘#"-Zà?ŒˆÞ¨‰>”‡ <ˆ?ý´ÏH­…#þX –Â=Rø\}uø] Òÿ¯&FòG¸=ªU•r‹Ì˜!‚4onÕÙz£¬?"­[‡«=ps©¤š lý‰OênbSH«Ö¾ý‰õ\JZ^^¼¬;ifã†}¦i"1‚T,‰¯¹‚9FóàAœA$@‰&àåõÇ˺ÍÇ' @gË:xéÃ?4ï¸.Wçä[5Õ9œ,qÿçúÑt¸ÃñrÑ¢Eòé§Ÿú¿õ=£!¥<:o0Šn#Õ¥¸`Á‚þêð¾í¥—^2e»bÐ#€€—×/ë8 ~ $%W5ˆйŒŒ:0Û?•,Y2` q¨S@'+RB®ZµÊLX¾TjBdT£F ›yJ¨]¹žÒž€—×!/ëNû/.‹ Ð#Np@Lóî»ï‡àmñüŒûÛéÚÏA)¦«#õ=94nêÔ©YaÿDúºqÿãg‘ñ„A$@ŒàH0?ÔmwéÍt€@?WĤ¤ž*>úNËÌ‚é»ï¾ûT—ÿu¨/mVA8ôûï¿á‘uÒxcW¿Zë1Lj‡!C†Ô ‘Â˺#;¶+VQ·Y£{±  Û´O>µµyâ wæapÜH1R}éˆ$“ƒ/Ryl‡S„X:ÒRæÍ‹¼Ø#Ò-ª gÚ,ïÕJSß2‹aÉ›7í¤â {yýñ²îTdªmÖÔ»Fx°óô·#Î1J“A$@ÉJÀËë—u'+O¶‹H û€›îï 0¤ïþü'[´hQ™4i’ a”yM¬ñ:ïàîÎKdô Ò§k`ý5×\#×]w)ûFˆŽ;w6Žà¨sÅŠFt„Îx´N™x‡†Tjvq³#ÿ1¼¼þxY7¿>HvLü½º¢ÃQã ´ÌDà7MLpJb DGÀËë—uGw–,m'0yòd9‚ÁêûA¤ôÊjœ¯}Tõë×X ÄE@ÁÅ.-'wìˆþ`´ÜG 4Sîsáòm@¸úÍ7ßD»[†ò—\r‰@šaÃñ8wœã¯j(£,[mp EZ·jœÏ  Fp¤ù‡[iŽášýfí@j¨?õužÏ^V?—ÑÏuÞQÕý?i™Ùj1Z?Ò™±´³×ŠËÈÿÚk¯É°aÃ4ûÑXmj¨ÀKŒŽ¸ì²ËB XïeÝJÒ(wÓM¾LLÈFUªT䆎ï+£ï¥’*0ªêgÜàÕš,[E¸@xv†»¢Iß<Ü¿„@ptá…ÎåõæJ{•}5èÍ…J™}Î=v#«~¤cC]7ÞèS€Á)Ý©^o­’çIé IéK»æÆGóȪ͆èÛPŸ+Ôj‘£‰ôÿnT¡ß•Zvˆ~¡¢Iw#§yƒ»"w#ßÙç_ˆ¿ £Ø(e¾S/¯?^Ö2€S¼¡ûöí“zõêÉž={Ìhtä0g @²ðòúãeÝÉΕí#È^B¨½>ÿôÓOæÄ2è0p¶Dú¤W@š Œ@_¼x±¼ÿþû:öçQã‚N:Ø‘.¨nݺÆÉ#gΜf}ð?ùu \Ž 2‚‹HÆ Í~èlÚ¦ƒFŒ¡¯'ôýÑ€—×/ëv<®$$!ð÷ß›  Gy$IZÅf@úðò:äeÝé÷MÅîŒ!ö´™@ð{Œ {O ÞÏ—/ »Ú*îz§9¤‹&ðþónL×N+2 NœÑ×!ÔÈÃdÇA1¤Öœ­™ î¹çž{eÜŒtjVØë´Ö¹W×¾9· Я9^;]qŸ÷?2ýà>õêÕL ê:Ë‘@8)ĹæÐûZº­‘ Œ -¢œö#ç5/ nR…ȵšB £Ò-þTq¬ý" /gðY\R¼xq£ø„¨$³áeݡڴD]Y`i—?ñÜGÀŒÆ0Ы¨NKúõ ß ¤v-£r8`^¹2|ÙxnÅE¹‰Š}p#ÐÿKæï/Q£Fe±'¡¶¿ª„ó9ùDr8äND ’Ño¡*rb(ª°C"eŸà¦iS‘'Ÿéß? hÀˆsàT„"XOA AQ8Ù?ÿ¨×Ú]>÷¤×_õj¨2äˆZTÔeÚÂÚ=ä¾ÑlPõºT®ìsn²Ýg¨B¿{)V y†|.S pE2ÀÈòåËC¦ Hæ¶Ç²m^^¼¬;Ø™wïÞÝÑ¢7Ô>\‚ôq¯‡¯¾úª‘~b+—H€R^ÔÁ¹bøðá©Ð\OÚèåõÇ˺CÁÀ`àD  Ì@§I‡ôÑý-5æ=[3¦÷4®E.ð›‡Î—9ê ‘îëh~ûÂ… ‡ÛÍqÚ€ß2\£؈zÝÞ_Ò4é&LpS<[–ñòúãeÝ¡¾ 8da`×HgÏ 8À=r»víô=t?3p8އæ¡H €ÀW_}%=zôàû+¥âåuÈ˺¾PÛª‘&Œi©N@Y§»íF ´`À£=Åú*[G9¨";ï¼Ó Ü[X÷šþ•.pŸÛXû¹ð>Å çÑl9wZë1‡ ¼e6€´œp ²Ü?ÿóŸÿÔcß/Ü2ú7lØ`Š 5çÇì/ŽTÇó‘Ä! ŠzüñÇý[p¿ûæhßCSí ´;PM™2%€-êÃwˆïÒŠO4% Ò°1HÀ"÷Ü6Ú¿Œ”ÝŒlI Ø©!N먺A¶‰©]™2eªªX¢¡.7Ôyû>Ô?:˜ð Ñ^4`T¨œîöý³Ã2l¢qÑÁëð²îX·5õAŸ·Y\'eËŠ [ÖóÏûÌtBÕ ]0¸Ñ÷bIá†b£-ZHM'vÁH®\¹N´êªV‘' er Âä˜{øaŸ‚+\5ª®–Dr>aQpYXVâeãSOùRd!¥kÂ9¡Ô‰›ÜØa´£:…a8YÎLøì6l7NnwÉT9¤D¬UKÔKÞ—b-”u&Df»wûDY™:w"Äðòúãe݉'—ýZ€ë-[¶4b£'T@ŠN) ¤"/¯?^ÖŠ¬Ùf ø€(/o7iJo}g&kNÜ7êH.xÐÉR°`Á€F½®ƒ|žÔDèÔÁ`)ˆÊ *P&Ôüæ!¥D,R\@¤„NœÑ: Ñcð"ˆáš€—×/ëv}‚,Hq ç ¤QÃo ÜÞ$@ÉAÀËë—u'½Ôh…ÝÝ-Fj]tì‚#¤U‹Vp«³GŸ7R‰ÙG¸wþAS³”Ef˜€ bJA¬}!Xr0¹°ÄFØõÙGnëÉl9¤O†s©ýû€°È.æÊlÝÜH {P/™ˆñ¯¾¼øD_\<­Ó…jŸVA­ÓºkçÓêà=¡r„¥r'uJAš¨ûT9—KÁ\žŸI ˜D°Ðá +–*Q5°ˆ¦p [·úLy…+Y2»Àb°Y³f*šš%Í›77ÖƒåÊ• ©£¨=¤±f “Ž/ä‰GÚ`Ù,‰(RÀÕHo⌔æÏÈ+‹~úR¢AM Ç"µ)A”±‘:9iouØâ)³¶[p04(t“Á,U‘Ï  T'еkWÕYNÒŸòFÆ68Õχí'   T$€MpíÄÈä¶mÛJ¥J•ôµÂêö\Þ¤${úé§Í¶5kÖ¨án1㦌÷Ž#%ÞÓ¡C£J1P°U«VÆ¥e0 Ü­ØÈ+vu½pá Â(¯ŽÇzI€HÀ"𚺺ïÜ¹Ó …A$@$à=ô£Ù]*qÿZK{Cäbÿ-†Àf+:+VÌàfôã?Fl ÎÏ.ÌÁ@ÜwGötj?Ýzë­Ñ쓲ÁNEß|óMLêe%$@Ù‹@(‡£g¹eË–µºÓóëׯŸ©Öh !2‚Õ£•³;ÿ£©‘`›†éyµ¨©P¡‚ßb¹dÉ’(  8Ê™Säâ‹}†;Ï<#šW4´VîFÐ~è;³¤ÜD ¯+ìÈ!:BžS(™3ÄÔ©¾†ÃGGFt ÊPA„p Ò´~¢yYÃàiÎY}£'êaº(òÛ=ø høBúG¡KŸØ‚/iؼLsvâhñYªWÏ—¿)æ´^ ȲǶmê ·Hýàо±µoá2 ¤Œ4ïÓ§±ÁÅKÇkZÊL$@$@$@ÉEb"¼KX±b…éÐÈ©/F¬ à‡—ûpá°â<}毧ϧHapá… Ò6`^À68i;Þ}÷]3*bžO?ýÔ쎔ï)þ’¾Hwr‹ç$@$`'€´J/¾ø¢Usˆ9$@$@ñ!°`Á‚³ d Á{džœ[¦è3·GÈ2sæLM Ò&ä~Ö»»±H5gñ°ÊÄcœB $$@$L f‚#{ÅÈ!%˜`û¼|ùr#>‚zsÿþýö¢²k×.“vŠ‚£,üpœÜ‹0èÎGÐä$kçà[n‘—ß{OJר!ÏLšþ¡Š‘L¨’@p¤¶½zÇás$:ûìÐßý“OúòË.,j`©M£\ss]7Üà;®¦{3ñÜs¢^ŒÎe¹Ö™”q>*òôÓ"ú} Ä[ýPL‘ž=Eý?}ëø/ ¤ŒºOŰ…õzƒ{7¤ç` ¸'€wèdˆ”®ì7ÞîÝ»K¥J•dÊ”)áß%¸?¸xZqï½÷Z‹fMƒ ÷ÊV £H"Gƒ0èÜ·Þz«äÏŸß¶Æy&ˆ*ê¤ÒV¤vÑ@ZµhG`!Ú¾}ûLñúçÀ&£‹ýxÌZd§Áe ‹€'‚#«rÌ‘kþ8`Â,T¨‹-2Î?ÿü³½(—IÀ‘@ûö"K–ˆŒ-Ò¥‹c‘خԗ|ª’µÝõ(Xwÿþýeˆ M9é$éª7B'#\¸@:5Ô ±‘ª¡³‘º#‰¦®‘ûïwÞó­·|b#¤4Û²ÅWnGÁ±j•¨}˜O £í ÿûŸèÝ™Hîܾ²! rCHP¡÷î-¢ß¿_pT·®Èüù"—_r7n  DÀÁ«U«&Oª€µ`Á‚ŽÍ«.m­[·–âÅ‹±Ñ¸î0H€H€H€H€"ø];æÎ+oéóû‚ Œx¨sçÎòÄO˜4iÁ@Ø G 8k`¿†ÛÓŸ!­õK´³©<Ã¥&ûòË/åûï¿÷×ýö:ý=Z8|ø°@fOë–O³¥4nÜØ£#²Z T&Ÿ_æã„ðc\µjU3=§®*±ðž 5?žA,šÓÔgÌc×Ê4l(šzOdÄŸ¡ŒjÖzè<ô™0¶Õ±¾ Ի߸•NMÓº… =©ê?Ñ7š"眶(7† pÖY¢RtßââÅ>\n¾9Ä\M$@‰#€ôË–-3^Ú¶mÛÖ< ± kGèu¥æ2-Uª”¡ó‹A$@$@$@$šÀž={döìÙFd´XŸ 1Rï¾®½öZùé§Ÿ4wWyíµ×LGÅÝššû¤ã/;š Q£FFd„ôµp–d @:°É m \ßð|º}ûvãl ±tüÂ)bàÀq뼎õ9°> $$ ïÕäöÛö©ö :tÈ+ ¸pÍ1û…9†c½ö•^C|ÜÆÍÞñÕW_ù‹×ÕAÜN#o¼ñF9[3‚ìÝ»×”…¢~ ¨Œ6 2…ˆ'RTwªüQÇüo1b'»èûâšqM¨Ì"A•ÿûï¿þ5H«f Ž`Ì1cÆ i§…aO§–[MઔÕÀsJ¸”l3A…kïÒ¥KÍuÏ:öèÑ£‡(PÀ¾ŠË$@$`¨ª"qq™Š20a¤=ƒÙ =AY÷Œöªà°=¾¯ÓQ."}ûzÀLDúVP¤W/Ñ×°€½/^â¦çuÊŽ „²Ò•סéÔ¬À ÇPb#œ4Ij]¨w!>g¤¡C}L-Õª%R¶¬U“¯L¸tj'JŠ>½Û?q93\äºëD-Ü2³7÷! ¸@~pt~3F`ŒÜáÃuDÕý:* ÂÙYê²÷¨¦ŠDú4Œ¶/Šk ƒH€H€H€H $¤âÁ}Ô_ý%9rä0GwÜq‡ö1Ý®éàÏ5)Õp¿ÕS_h´Ðw({08HÞ¢iÙ‘vmáÂ…R®\¹Çà Hè|…“Ęp³)ÉÀ÷:}ï¸ó05‹qäÈA'¾j²0”ÕwªÍ›7Ïb­ÜH€lÂü¦¬V!%D•µ1 <+æY©6`_aw7Â1ï¹çž€C[p{ëQ£FY«iÕ2#8Z®M®ºê*=Ñ. M2Þ§þ÷¿ÿvWSþÊ+¯” Õ]jóæÍæ3Òª¹á¹!N¨p‹²;FE{"—kVpm޶>–'È^ԎÛ€ò;urÁˆzŒöZ¡6‚ÝÅ P` ¤FAŽ¡.ãêº ª|™ îAÔP(ö¼mpjÙ2lݸ1„ª¶‚°K‡„ð@4y²È®]Îûkž^)_^äŠ+œ·¯…=#rú"½›*ºM .„K#©àÉÌ­ýô†K H²[DYÛ8=¼ì€ºœ¼cÏ–5’ ÄŒ:³à(‰µx0Æ(¢9sæH… ô’1ÔXÈã….:»`ëK±QÌг"   lH`÷îÝF0„û'¤¡Å‹{¬›¯éµ‘" b#:Iyäónì±ÇÓV«¤zõêšûr3rBð믿>â)‘ @t0¿¡ƒe¤ËÁod/ŠßNdLX·n]t•ÚJïØ±Ã8Îá7éa0ˆ‚&+ý¥­(I€H€<$pôèQ™8q¢ÿgj_Äú¡bT{à}f8—{ÙX.á⧬ê°âcÍd²sçNëcÀüóÏ?¤µÂ¾Ÿµ.ÞóV­Ziò•éoð< ¤SõU_’œ‘7oÞ*'Ÿ|2¼ÿVÑôpå± ù•GŽinÜ!ƼXA¾Iü8[VÒÁeø9ý@‹¦ž‚#‹ˆ>_Šš4ˆ ‚ch„Z™›”XaœpS„<¥°UÄß::pýñÔS>û%¹èhÁ¤7D¢¶Œ®BÝ&t¤HÍš"=zîÛFX=éøzJŠú¯û¶ƒH€H€lð÷d ‘£ôx`4&‘úôécFàC$nuYå8'   8Aâ-u€Ò `×¢H©~òkê 8!uíÓ:¢÷\èD5šûÄѸD$@ÙŸR§Á5¢–â„+œ=–ƒ<ÑÑ Á&}bŽw²èŒT7˜°|@ÝásåÊ•a Q¤®û¡¸L$@$ø=†Pߊ&Mš˜ßmësðפþùçŸÍ&¼ßD:2\âèDÛ-Z¤ GlG¢h„C½{÷6{ ÝÚôéÓƒ‚ÞN ÎFp8JD¨6À N…£«ýr"ÚÂc’ $?GÁ‘Ú;×д]´ùµUtÚñÓX¡ó°‚#Øœ"¥=7e0‚¯¿þZ0¡ó e‘ŽŠAÖ Ͱ1lý¥ËFUàõ×Mζ?Õ.òcí€ÅÃù矟¡Š‡~Øë0R±uëÖÛqñ¿ä‘×^ó ‚œrŒ;­ ¬EDsÊê°Ñž_‘I“|®KÁeƒ¢#õà   P. Ñ Aƒ EêÔ©#˜$@$@$@$@¡ ÄB¡“è ‰&F÷e¿þú+EÞÑ€cY lK`±ÚØã=k™2eŒ˜ÎpÁ”gÅŠ3uëÖ5ýÁ}èÅo3R\ZÒ´!0àûuèÐÁtÚrt0a~& øN§†ß˜X„‹+4[DÿV ­Z´‚£5jȰaì*BÎ!hÚ·oŸlܸÑ›–-[æ/ ·<\O ruº^ù †X¸TÓ»À].{¤U YB$« dYÉ;·õ1Kóšjl7ÖHÁ¨h'\$@$à–@°Rá}2Dwn«7ß'¹­åžÑ”Oeà6ðCÑ]¸8dæÇÙíqX.5 ÂàÈW2Æÿª¢Xƒ§ g5ýßÀ!øo ‚ܬ—i£0!õ Ò¾¦b"tÎ0 c#ðßF­õÊ-‚ôl åŒ;9¬Ñãš´i9sŠ&)w( «úA$@$@aÀ•oîܹR¹re>(†áÄM$@$@$@$L/ü7oÞlÒѾøâ‹²fÍãp¥ÎòH¿Sºti#RÂS‘"E2 „£ÄGˆHNtvæ   ˜€è~Þ¼yõÂu.ÚX²d‰IOìdª.\;ÐÇç6,¡*ÒoŽF?ßñؾ}»"5kÖÌZÕ.GÝ»w7û|öÙg²mÛ6)Q¢„¿ŽO?ýÔœ›µÙ‚büТE‹XUÇzH€H €@€àHpF©Î¨e@ þŸ½3—±lÃø•5dßB‘%B¡H YZHiA%*RZ”Ò&íÚKZ¥EŠ¢]‹RI¢DZPÚóIö"$©ôÝ×3fÎ;cΜ9çÌ>×ýûy—ç}–ÿóÎû<÷}Ý”‘‹älTªT)—Ê#´*æ`¦¬4£ÄdÙMÀïpdN¾É±™3a¼À°a˜jòæ|PeÚ¿¯¬c|1?©ß6lˆÆGQæ½à sgÿ)ß;oÚ×^ Ü?,|¦à DI’J ŒöD@D@Ò™ÀL»¿mܸQÒ·éü!ªï" " "  !À´<³fÍçªøúâ‹/,#º/%z1Sf .Š)R$!ýQ#" "‰¨ Áu*Mð;–ª5Ês¨T¢§cR´Æïm9EKKåD@D þžyæ00²°Æ ÖUg¥ü´Íßü?þ8æÍ›çž ü×ÒQ(GUS¯¼òJÕn߿ÔfÇsŒWï" "ÒGæDq¦õ47g£íöå÷C¸‘Pž4œÒ ½K¯5§ J¯U«VÍåQæÄ ËRzÎoÏ=÷œS:Ò€ŸHv¾3¥…|’–ao§—òÏæäóýwZ6³³1jÔ¨À‡±jÕ*çxÄèæ+­@™GËká»:•´,„&ìÒ± “d" " "þtjʵøjRD@D@D mlذÁE=3­bÅŠhݺ5˜Â¯¶mÛbŸ}öqçôˆ€ˆ@þ|m¿t2zå•WœZ¯¦ªð›·œÿ˜ÞE@D U 8‡£ t·TjM¼´Eªë-Zt„}ÙÍ0©Ó¿¼ç¼Û3fÌðîºmzd2J!œ1Jì:E•#YöàýÔüÎìá3I ÌÙŸø9ç`úôé°ÿ –%­sNg>ü¶R øÿÖíá–FÐ<è€*UrÊy·(Õ4``?@5$™ˆ€ˆ€$˜ÀܹsñË/¿(Z‚¹«9ô#Àèb.b\~ùå¨S§Nú @="ÀçP*3ôïßߥø¾è¢‹lZu†{>¥ªSÄ”(Q"…z¬®ˆ€ˆ€Ä“À¸qオ?ýôÓQ¦L™¨_{î¹§ðV2aÂïnܶٶ×üЍÞcùÙu$âséÕüÆõõ.]ºøwõ." )OÀ9™ƒÅ0oOÍÙèCS4ºÝ{,·mF|yrpmÚ´ñÚe›Qö:t·¶Ì/Ã3dYI€éÔh&Œ•c:µ €ž=]c³fÍÊ\®CÌõf£–\Ü×?:(Q–)¯(œK/,Ï«TŽ’ó±ªUÈvþtj=zôÈv¿ˆ€ˆ€ˆ€äJ€*3gÎt àåʕ˵œNˆ€ˆ€äM€ ¦Ì~ðÆo€ Ê?üðF…N:¡hÑ¢yW " " Eàï¿ÿƳÏ>þ© š_;å”S‚.¡…eè :fïñZaŽêÕ«‡ƒ>8P%Ž,ËËä?xâ‰'Ê1×Cï" iA ˆ}¹Õ¶/øC=½Ýl7€3mß<*"›9 •^±bEP!¦M‹Æ?üð bÞ˜A'´“ñ¾úÊ7ĸ(mßP¡hãÆð?ý`ìø“Z¢4ch:5Ô¯sŸ†åþƒiL§Fe£¼þÖ퇃ÉJ&ŒeË·¯£" " "'t8bЖ-[Æ©U+" " " ©G`ýúõ˜:u*–/_Uç&Mšä+B££ºX…D@D@~÷öîÝü.¥cSUR}¢ƒw|ùå—xüñÇÝÚ¤¿¡Pç*ÿq½‹€ˆ@ª(bÎFæM‘c¦nô¾å«_šs$÷­Y³fU =êHzÞ¿O/N¯1‡³,; ,^ {š%õ‹ “ìÛ¨bÎüÇw¦Sc‘]ŽxpÐ àŸ€sÏ,?,N; (^œg"ÛwäÞvä+uVD@D@ L€«ÌΈ™ˆ€ˆ€ˆ€d*¿,=ú'Ÿ|‚|ÐEJï»ï¾TÅ©wÜq°9®<‡Î¨âÒ¥K£{÷îy–U] ¼ùæ›NՈߧ=MAþk“³?‰A˜2¬'0~üø gœqFÐ~´;tüaJN¯%"­Z¨ÂѦM›¼](ÐöÉ'Ÿ *=ùíŠ+®ðo¢R¥J8ꨣûÚt P̾Ôê†tôûý\w,XPÍ{r¯½öBݺ¡ÕyKäl×§jŒÇ¨,#ËNO? Œì¾{ŒÇo¹ÁÍ58ä`ðàð•›²ªšßœ¥œ~ÝuN¦°}ûö»–íÖ öÇíS+âÙ¼Ò©ùk°ÉNð%P:µÂVS" " " I!pï½÷â:{Ž÷GsÒ¾aÆ8óÌ3A¥ .€¿ýöÛèÆçù\ŒÁo³gÏv äeʔɥ”‹€ˆ€„#@§ÎáÇã–[nqJF'N,Pšœpu똈€ˆ@ú  Ñ[̲Óv·E@:¦Ô¨ D=¿M¶¬$›7oF¨Sÿ|,ÞCŽèp´Ý2«”(Q¢ÀÕS‘þÐCÅG}äêøã?u1x´x4b+RoãþûïG5 Ô1¦c•ZÐé"H*:I ÙƒÂÑöÈr0[^©kÓ¦MÎN[Õ«W's¶lÙâJ®bª*YÖØsÏýÏ?adÀóÏ%K†o€êGöúÇÔ‹>øàw“;ÉX¤pþùÀUWÁBv`w¼ðõ騈€ˆ€¤>|3º¿]»v)ÐuAD@D@D@bGà÷ßGÿþýñÚk¯¡Q£Fnqû 4jݺu uç˜7¢›"9½ôÒKرcGPZƒØõT5‰€ˆ@æà‚+ßxã |ðÁn˜ÁÈ2ðxæ™gÜÚ›ŸŠ¢åË—÷ïæû ¦T&ý“ëf|çh¿hòÝ"P¬X± µl>;|ñÅîÙ£Õ.¡ó”ßá(pÐ6¼éÖ¼ÇÓi›Š‡µV­ZÉᨠðt$‘€yQ H’Ⱦ,£r8ªZµê+W®¬èí{‹-¼»yn׬Y3Pæ—_~ lkCÂX²$ìá°¯½`y¦4ÛgŸ°E¼)ÁNOè°éÔü-í,‚?ì?¢wH9KìþÇ”jÌm^”9Ke" " " "!Lits6êÓ§æÍ›‡ë¯¿G}tÀÙˆC­U«–sDb`ÑgŸ}–ëè9ΨåHNI¹^¬" "¥,Ù-´ÒÙˆ‹¼³fÍ‚œ²ôAÃb•NÍßètäµD¤U«V­š·IÜwß}AûÙaZµ":ðƒG;wîì9¢MHü6Ûîíª)mõîç¶m^¨‡™Rз!'}òc^™¸råÊåçR•Í6æ „&M€hò»Î <ø ж-pá…Q‘š>}º+ÑáÈr§âÒKp)×¢jE…D@D@D þ”N-þŒÕ‚ˆ€ˆ€ˆ@â <úè£8ì°Ã@õ¢GyŒ˜MqàíÕW\¦Y£ÊQ8[¾|9>þøcç¤]ªT©pEtLD@D „Œ¨(÷ã?Úôëƒàb2SäÈD@D@DÀK`þüùøê«¯‡èLÓµk×À~A7B€fΜéž Z_4×ñÄkÏ[V•Ñ£G{å{›)ÇÚ‡¬5öèÑÃ)*å»2] " I&À”jÿóöÁ<*ëØþ|ï±pÛvå¢Ê1: Õ«W/ç@[¿ýö[ T:lV–mf̘ž´[7JF½=Ì⯿òvöa™³Ï†%9žxæ"¡ÒœSt8âß0åúd" " "Î(%ÌÅ·ˆN´é<@õ]D@D@D «0Xí¼óÎóÏ>ëæ˜-š€·¦M›:å"þ6Z¼x14hÄíÅ_„ÒeDÚ‚ iGD@â@€ß—·Þz+n¼ñF—¾ûõ×_G‡âÐ’ªÈ-[¶t¿µc=:åðžÉN9åð+›8q"øÊËÖ¯_ŸW‘ óï¿ÿ~Ð~^;ûX6—¼Æî¯cÈ!à+æu,KD{jCD õ±j‹½Ý²/«¨<Ìáèhïu¼y0r,Z[±b¶mÛ(.‡£Š¬Ú¸ûn wï(ü‚&M‚å…N<12Ÿ[n¾û>hÔ(rÙg9yÉ”j;v”÷pTÄTHD@D U 0E-#õ™¤dÉ’©ÚMõKD@D@D@"ø÷ßÁÀ ‚óEt6:Ñæü)Õ"^ì99tèPؼ—eG·ôè!Ætj¦Þ“H몵+" Eàûï¿G§Npà 7àÀté,ål”Q±#" " " " &@ù— …#sjžWmõëׯfŽI-½åÚµkçÝÍsûÃ? *CÏLYö ¢"3¥E"¢ÒÔ©Àá&ª’+Õ3ùBüü3ðÅÀ]wÁB“NÖ>øàüý÷ßR‚ˆ˜Ê‰€ˆ€¤,—_~Ù-ªtÒI)ÛGuLD@D@D@ cŸÏ ¦8ꨣ0vìXÔ®]L§Æ´±tÊnóLýÔ?¿þúkàR¦š7oø›©D‰ãÚÈ!À`á믿Í›7çò/ºè"Ìž=Û}/ç”Ò–ˆ€ˆ€ˆ€ˆ€ˆ@6(¶qãÆÅ•*U 00‡£¾–íö%K–,  Ù°2½ì”«*?G”|ãD‘×8$Ë.æãÆrGGþæ›ÀÖ­ÀÉ'ïZìóÏÓNÚ¶þü&³<ùdùÙ‚«aÔ$M©g‚¹hOD@D ½Ì™3Æ CÅŠqì±Ç¦WçÕ[¬$`sRNÉèí·ßÆ[o½ª5Ò˜mðàÁ.ÝYÆ ņ*G½zõ¨Q£póÍ7»º¨nD;õÔSÝ»þ&ðî»ï:P¦¤lÑ¢{ì1çÀ\J{" " " " " ÙN Øºuë6ÛÂÔóæ@d‰­œ+Z´¨%ºCãwøåükJD¬ì¥9G€½öÚ ùQ(šùä“°ÎFݺus)@r»^Ç3—€=Ç⤓ò&ÚºxóMXØ#P³f\`Ðá¨I“&V}|êK§U©ˆ€ˆ@Öøæ›oœ³¬9Œãµ×^Cçγž‰ˆ€ˆ€ˆ€¤ 6`À€î7ŠÍ7aäÈ‘nn(ÎF~*TV²@;üõ×_èÙ³'Š-ê?¥wÈj7Ýt^xá˜ï…[n¹%«Yhð" " " " " ù#p8âe+W®Üú¿ÿýo9u·ÝŸ#Tõ÷Ž;.³¨°/"”‰xŠiØî¹çžˆet2s üï°R`Ñ¢c4‡5lÙ9Z„Ëó:õÃ?ðoJ§–)H%æ î”6mÚ„W^yG}t*uO}Èr¯¾ú*7nŒqãÆ¹Ô¯t”f°Z²|*Uª„sÎ9Ç}:}úôÉòOIÃçž{t8jÕªž~úiš7¥y™ˆ€ˆ€ˆ€ˆ€ˆ€DI RÍ[ÞœŽ¦Ø~͆ Ö3磶} ½×.R¤È—ÿþûïÇöš¿téÒmv|‚÷ºh¶›7oŽ¡C‡º‡˜hÊ«Lf0Ñ+g‡a|þtjyó§S“ÃQ<èªNxà"ÞÏ?ÿì·©)T @U#¦-{öÙgQ¹reLœ8}ûöM…®úpûí·ã„N0!eSR–‰€ˆ@–øøã]­Zµðú믣T©RYNDÃÈ/°GþJ-Z´Ä¶ùzÅ,?ïuêÔAÇŽQ¡B4mÚíÚµC½zõòS…Êf({žu–«Ã‘IœcŠù½µiìµW\(Ðá¨X±bèСC\êW¥" " "O=õJ”(~ýúÅ£zÕ)" " " ù&ðÆoà¼óÎsNÑtèyôÑG±çž{滞x_PºtitêÔ)Þͨ~HyË—/lj'žèÔçø^£F”ï³:(" " " " "z":¶»_2%@…#Î=šOZx{ç`󿏥S[¸p!¦M›†CÌã©\¹ráû £" " "bV­Z:Ìrb˜Ê2H&7bÈ! CtÅŠ]:ž3Î8#™]RÛ" " yX¼x1zôèµk׺4Ýx`Wè´ˆ€ˆ€ˆ€ˆ€ˆ€„'W‡£ðMêh¶ØfÉø¾üˆ˜fÝ: J•¸8-[¶ Çs ,5 î¸ãŽlÿ84~4"0aÂìØ±ýû÷O£^««" " " ©N`Þ¼y¸óÎ;Q¾|yT«VͽªW¯Øþ矰ΞÓC_LÁC‡h¦y}üñÇQ³fÍTªú'" YKàóÏ?wßõ“&MrÏ•#FŒpÁ,Y D(49¡*È/ùó¿ÿ†© E¸rÀØj*P¤H„Bù?µ~ýztíÚkÖ¬Á /¼€öíÛç¿]!" " I"@õ.ÒqV&" " " ± 0cÆ 0 Úü‘ïê¨jôä“O⬳ÎÊ÷µº@D@D 1fΜé¨öNãóäÕW_­yÑÄàW+" " " " "Ñäp”ÑojŽéÔhŽX ÆÎF[·nE÷îÝñý÷ßcÔ¨QèÕ«[‘‰€ˆ€ˆ@ZøÄn ¼‡]zé¥(VL?áÒâCS'E@D@D Å ¼úê«8í´ÓPªT)Ì™3ûï¿¿K±Ã ¦Úáû¯¿þê~{T1bï‹é]ù*Z´hŠRÝì$ðñÇã’K.Á§Ÿ~꾫ûô郫®º Íš5ËN µˆ€ˆ€ˆ€ˆ€ˆ@Ì äµZµ[:uö)Q¢DSk¹Þn»í¶Âd´¿Y²dɶÿoÌ{£ ³‚ŽèKtðÁ‰.Ó§õîÝsçÎŰaÃpÑE%®qµ$" " 1 0~üxWK¿~ýbP›ªÈvãÆÃÀQµjU¼óÎ;èråÊ¡AƒÙŽGã´&ð×_¹`Kª½4W\qêÖ­›ÖcRçE@D@D@D@D@R@X‡£}ÌŠ/>ÚŒ:X—Ëx»Íˆú}÷Ý÷/;ö†EÙÝo¿ý¼§µ-y°à4i”-›gјàƒõ믿Ž3Ï<wÜqGÌêUE" " "œ,f*Ð-Z yóæ‰hRmˆ€ˆ€ˆ€d0{ï½×->ÛôÞ}÷]Ô¯_?ƒG«¡‰€ˆ@ö3f V­Z…ûî»C† É>±ˆ€ˆ€ˆ€ˆ€ˆ@B˜ÎL°5lØð\S4úÊœºÙ™ g#I;WÒ^½zôèqüý÷ߦª’‰@4~ùX¾<ŠtjÑTe™›nº |ÈîÒ¥ ÆŽåU*&" " ©C`òäÉøí·ß u£ÔùLÔHW×^{-.¿ür4mÚÔ¥Q“³Qº~’ê·ˆ€„'°mÛ6Üyç¨Q£Î?ÿüð…tTD@D@D@D@D@b@ ÈáÈœîµ:³×ÑÔmiªŠ>òÈ#¸æšk¢)®2"¦S£µiã{÷¿ŒÔ>|8Zµj…I“&Á”»âݤê˜xê©§@•É>}úļnU(" " "=®ºê*Ü~ûíöLÞ³fÍr‹ÑÙ3zTD@²ƒÀ£>ŠÕ«WãꫯÆî»ïžƒÖ(E@D@D@D@D@’B àpdÎFÍÿûï¿‹ Ò‹·Þz Œ¼—‰@^,°ýûíÛçU26ç¹@kj\xñűÇQùÑŦaÕ"" " 1"ð‹É¾óÎ;èÖ­ªU«£ZUˆ€ˆ€ˆ@¶`ŠÖQ£F¹­Ó§OGÅŠ³ Æ+" O€™îºë.ÔªU çž{nÆWH.bžæ2ÇŒ¢ž}˜Ò§¶ÿúŽ;æšëBKµVË¢ë÷·c=¬lOoY¦­¢Š fd"Ö­¾aœL}ã7¬½Ö¨[·n"šT" " "s'N„©JšÃnÿ˜×­ E@D@D@²‡ÀìÙ³Á…èÓN; eʔɞk¤" "E˜€A+=ôJ–,™E#×PE@D@D@D@D@’AÀ9Õ¯_¿³5Þ.¤3ÿþûïnK—.Ýæ9¾Þ¶¿´×³ 4¸´H‘"÷Øön<¿eËçÜ¡¼Ð¤!Ë7íÛ[núõ4È÷åá.`:µM›6¡W¯^áN똈€ˆ€¤ñãÇ£råÊ8öØcÓ¢¿ê¤ˆ€ˆ€ˆ@jà32í¨£ŽJͪW" " …"ðçŸ:u£½÷Þ,T]ºXD@D@bE`ìØ±¸ñÆcU] žÑ£GãÄO ìscêÔ©8ûì³Çî¼óNœqÆ}mˆ€ˆ€Äž€s82µ¢f!U¹aÆÖ­[çu6 *²xñâûúöí{ñgŸ}¶ÿ„óoê]òGàµ×€[o…iº—]–¿ks)=iÒ$w¦gÏ 1®\Jë°ˆ€ˆ€¤ùóçã›o¾ÁàÁƒaJ“©×AõHD@D@D áV¯^W^y|æ-[¶¬ þЦÓ¦MCÕªU]JµhÊ«Œˆ€ˆ@zàÂëÚµkA•#=?¦×g§ÞŠ€ˆ@&øã?Àg˜XÕ[CͲõµE± ™ˆ€ˆ@| øŽöó6c)Ô5g£ÍÞcá¶Ï9çœïäpŽŒŽå›À“OÅ‹Ã\ó}i¸ L “'OFË–-•N- H T7¢õ£ LD@D@D k ,_¾/¿ü²s2š;w.þûï¿ :'7mÚ4°nã×_Å_|Þ½{ÂÎÂÑ14&ÀÕ»ï¾uêÔÁ€Òx$꺈€ˆ€ˆ€ˆ€ˆ@:pGÖáP‡£éÑ ¢cÇŽë+T¨€7ºâK–,9+ÁR­Es¹ÊdAƒ€O?fÍJ—ö ~Å €Òî”>´hËXØ{ï½çþ.•N-4U‡ˆ€ˆ@2l·t£Ï=÷ößç@›Œ>¨Mä`ðœ9sðþûïƒÏ·ìå:²Ç{à”SNq©Ãwß}wtïÞÝ9"ååp4}út礤tjÉù<Õªˆ€Ä›À¨Q£@çÒ1cÆHÝ(Þ°U¿ˆ€ˆ@¡0õgíÚµ U/¦z«LD ±Ìo¿ s P¯^bÛVk©KÀ¯pô;yóæŸ£ír5GýõÖ¯_¯/ùháeY¹?6m q6"ª7˜£š…ßÄŒˆ?šŽb†T‰€ˆ€$˜À”)SÜïªaÆ%¸e5'" " "hTé1c†s0¢“ѼyóðÏ?ÿ¸nTªT §Ÿ~ºs2êÒ¥ èhDû÷ßQ¹re—^í†npÇrûç]ù˜}ôѹÑq4%@'Õ‘#G:•÷þýû§é(Ôml!pÖYgᦛnŠËpÛµkçž«ü•7jÔÈ¿©wB°Ÿœô|û-Ъ`âË(æ—¶)dݺ<½ øÿ ¼zÚÛ-Âþd¢³š5kâ»ï¾ ¦Â‘LB l¶}üêÙ3ä eàÇìï]»†œ,Ø.'e_{í54oÞ 4(X%ºJD@D@’Làž{îAÉ’%-ÛhlÒ&y8j^D@D@D ¦¿™8q¢+A£c=¦*N:¡Y³faÓ -Z'œpž´åTœ®!¼G7F­Zµ"ôB§D@D@Ò‘Àƒ>è‚UFŒâÅ‹§ãÔgˆ *Uª¸g¨˜T¦JD@¸œ晾µþƒ‚IöÓ×\(¢,&P$ÌØ·‡9–ë!.„ÉD /eÊ ×_RræLà§Ÿ€~ý›,…Í´:©´%u£XÐT" " É @eƒ>úŒø©^½z2º 6E@D@D@Dàã?Æ3Ï<ƒÎ;ãóÏ?Ǻuë\Í!C\ Ín»ycÄ‚;Õ£Gwàå—_>áÙcØÊ•+¥näa¢MÈ¿ÿþ;¬R¿~}[²U ™ˆ€ˆ€ˆ€ˆ€ĘÀm·¯¾ ôé[·š6…)•_ã†T]Zð+¥eçÕéô!PÄ\ÛLphW{â ß1¥SÛ•Žˆ€ˆ€d-Ûo¿ÝäH‹aèСYË@l 🅠ұˆ÷ý‡~ù•ü?òÈ#Q¶lY—VíÊ+¯ ‹ÌŸNí¨£Ž {^E@D@Ò—ÀõݹaÃ<ðÀî^’¾#QÏE@D@D ù˜êzÙ²e–”¥&J—.Óm¶T0+V¬Àš5kP¾|yÔ©SǥȎe#¬›m°­jÕª¡víÚîy1–m¨®ì#0e À,îŒ ËÊŒpig&øˆPì¿•,à Èá(Ã?à”ÞÆ°YQàðÃa¹ÏbÒÕÿý×E‚î¿ÿþØo¿ýbR§*Døì³ÏÀ…A¦R«[·n"›V[" " "  &ðì³Ïâ“O>qNGùu6bW©:}ÜqÇáùçŸÇêÕ«ÝÄxè¦M›æRì0E›LD@D s,\¸Ð9«¶mÛ}ûöÍœi$" " "P@|¶b §ß.¸àtíÚÕ¿öýÛo¿Å&Ž@åÙ–ªeÛ¶m®ŽN?ýt\|ñÅ.5õ?æY1xðà@gŸ}6ZµjØ·±cÇsÌ &àÃ?×0½ÆuL*2Åv^*÷TÄ¿âŠ+—¿ôÒKnî˜NR£Gvíð·×˜j•'Æ Cûöí½§´-A¶l˜­(Ô-‚ý?€9ÇùŽJ•ò•àŸ>ÿÜ"2»‚¼¾{÷Ú6wÑ1´jígp)Õ2hxJJ°‰U»svSŽ•Íš5 k×®U:µXU=" "  'p›é“2uÊÕW_ð¶Õ ˆ€ˆ€ˆ@âüùçŸnâ·²ÍÜÝÀpÁÓªQ)éô„'Ÿ?øàvØa6yfö0¤¼vE@D@Òƒ¿÷ ä:K…¼Hé7ÓcDꥈ€ˆ€žÀÏ?ÿŒ×_=ðZºtiÄJŸ{î9´nÝ÷Þ{¯¥‰ú(àlÄ‹Ð1bÄ—¶”uÒáèÑG ¼/^±î¯¾ú t-ž : …:ñâï¿ÿ×\sPxòÉ'#Ö·ÑDæÏŸxmݺLŸ}ðÁãÒK/5ç`g#VÆçÁ·Þz :uÂ}÷ݱ~Ì^?ýÔ¨s®–/Ïá`BY8á€ÎH/¼SåÊ9Ç­¼œÌ‡ÏþK—·¿ÅrÁk/£Èá(£>ÎÔÌo¿³gvï 6Þ<ËÙL¯^ÁÇ ±7iÒ$wu¯ÖYˆîèRȯ-é1`O:é$4nÜ8_ת°ˆ€ˆ€ˆ@z¸ûî»±råJÜtÓM¨X±b;Ì1Ç ”…†s8â¤ùü£>ºÀõëBÔ#@µ~Ç_tÑEhÖ¬YêuP=&@禶îÓ§9S˜7Eû믿œÈA¸ç­Ü.›;w®%w9<¬P¸Tmt&¢cÕ”¢µ~øÁ9…s4 ­ƒã¥:Ed"ðË/Á ¸Žß°!0jL,ç\‰@›6€M] sçœãÑn5ip0nÜjìµ×ëÑ^¦riH@Giø¡¥[—-+ŒIõ;}|Ý7/csÃ…­¨Â¡ÆdH”&ä Ÿ„M›6IªDD@D@IàŽ;îp Œl‘‰€ˆ€ˆ€d.U«V¹hÙ&6wÞyçj T.êÒ¥‹›<^·n]P]LÓJ£Œ¾LD@D 3üf«BW]uöÜsOÜ|óÍ™1(BD@2Àv³q…yý»(ø :Çò¡ö·ð_ÿOèIÛÐFà:ÿõ|OVaºžJ‡{ì1<ðÀ.1õS›½÷Þ{¦Æ²‹,Ô3Ï<ƒSN9Å•¡RÏGc¿ÿþ»©Âœ:ù¥/¿ü2V¬XáœØÓb3e›×F™Ç_ѯ]³f+zä‘Gbòäɮߛ6mrNÉ·Þz«K­í¯‹k¨TÖ—e7Ëćzõ`9Lˆ óæ–#Gæ/Y’ÎB0缜cá¶LüË©€;ï >KÍË$ˆC U$ .§½ô'P,ý‡ ¤:K™êìC<=å7 ­cG÷‹æÌ™ƒ_Ì-óœsΉEuªCD@D@JàÇ4iÒÜ‚aË–-Ú¶H,aÆ)Õ(Ý_¬Xá§f˜Víµ×^s“ÌŒŒõÛ4›1¬T©ôÛÂODï" "þ®»î:üú믘8q¢‰ÇÛJŽLD@D 5t²n|¾+1ÐwÂåƘ[à2.ì?¼óÈ•ö>"è,¡’¾Ýdµ¶3¾ƒ ’`*±Â… j›-OUfýFÅ!>K…iì»ï¾N‰j±Tܶ\yzxŸöÛ€ðÐC9UZÿ±:–›Š¯SO=uëÖÅ-·Üâ?…»îºË¥M-Z´hàX¸ >O2¥ê=÷ÜãRªyËzè¡æäq¨kƒŽRLÅJcj7:$é÷ƒ—Völ?ø ìoæ´ØŸ÷.VÐ8%óesLüoÝ­L}s—ªu à ~V+Ãix…'ÀT‡úòò;Qú(F¦tj1©jD@D@’B€“”·½öÚk“Ò¾H O?ýÔEËv³™8*źwïî¢W©úëw8Ú°aƒ ÏGÏž=Q¤ˆ®cÁYuˆ€ˆ@² ,X°>ú¨KÓÒ·oßdwGí‹€ˆ€x c; ¼r¶™þŠ©¹‚Ò`†KÔÁÀý?v^.1B9­y¶’Õ†§ ¡›?ü0ø*ŒQ­‡Î61¦¶^»vmàÒûî»og£ÀIÛàóÕŠ˜’,/[²dIrÒA&3fÌDr¢Z!Ó`³4ªá2p„©³ó² .¸`g#ï5TA¢³Ó';•!¶oßþ–èC1o{ÚNMô73qL—ÍĶ0u*P»vìúÊÔkãÇ=01Y–ØÅáȼ‹7lذ_4yä‘z+W® *:ÕþJ âySkÉ2Ž€© ÚÍ èÐvó÷ G5jõë{|“Þ¹”#lРš7o^ðŠt¥ˆ€ˆ€$O=õÔSh×®¥!3n†¢&E@RˆÀÖ­ÀÌ™À”)LoÜÙ&«f¥PïÔÈ^CLœÎŒD•U¨P;wÆôéÓ«3fÌ'âC#ucÕ¦êH,Î4È9‘ŽæjŽLD@D µ\—{wf>:ëׯG³kóþ`Ö®H™»"´‘{ë!gÑFH“©²ËtgT™õUŒüþcáÞéØCG% ³pexìꫯzhtˆÊËÙÈ´xïíþkÇY«¼Ž˜Zû†nðW‘ë;×LýG,š†;× u"f¾ø‚ŽdLuÐ9'‘f~Ž8ë,à¹ç€¶m×_‡© ǾLËöÝw0%çØ×­SŸÀ.Göhù0>š®ßÿý»»ýöÛw9Í9EC)ýÊ|ù¥¥›5•Á6mBú~Ç€å•}l2Jôú¥,½LD@D@ÒÀHKŽÌJ©¥Û'§þŠ@r¼óìûÂ'|ÀZ{yØYôÞ{Žh5jìÀæÍq˜QðU¯E@¢$ðœÍòÍ;_|1 “ \sL«öŽ}A¼ùæ›8í´Ó\T,Ë1€LD@D =Ìš5Ë)ß2fhPïØ±cÝ‚áe—]†ý÷ß?=¤^Š€ˆ€ˆ@ øÎ<"¶lÙèÑñÇQ}È_i×èô{ã7ú…}§2‘ßê›àB´©­«V­j ðî»ïºË'OžìRp³ÝÜŒÏ|Õ«WÏítàx¨HƒŽh²aâU.ÍØÏ?&&:•0³ì…8ñD`Θò1,/°ûîñkÞ4AdYJ`‡£,å aÇ¡§Ÿ§@IDAT‰ÀçŸû*>øà¢äÂ+e™O•ïþmþà‹ùIýïŒâ¤õêÕ+¤!튀ˆ€ˆ@j`NïÇ”ØíÚµkjwV½Hæ>§ (‡>û̧Rä¨\°¯|ý5L|×.1¥1’L4 Çç{-Zô¾9!,Ûµ°Žˆ€˜ÀŠ+PªT)T©R%ª:˜:•A2•,œ0¯‰ê¨* )t¢Í$2ò–꿜|æd5#vëÔ©RR»" " ©H€ó›t¥’U, Zµjå^t0¢úAÍš51|øðTì¾ú$" " Q8õÔSQØ´ M§öã?õ1?©Åš4itmèçx™zÍoœëÍ`e~‡#®.]º‘ÚŒ6€¥^½zAÝàÚª,qn½ ³ͲÛ%ÌáhÑ"àØcÅ‹+¯îº+$‘¯KúWbB@G1Á¨Jr#àÿÝk¯ÜJìzÜRõ¹œ£Ìg›kÚ´iÔÞÂù©WeE@D@D ž¨É½k®¹&žÍ¨n'@'£Ù³_ô9ýò‹¯Ã V3ŸsÈ€­;aÙNß!FJ…ÚСÀu×åËçœáDƒLD v~øárÈ!Îa˜©Ë¢±Ï̃pùòåöÿó:çtÍ5ù)S­Z5—ž•©î.\è&¨/¼ðÂüT¡²" " I"°aÃôïßeË–uφüŸ7ož}öY<óÌ3^Q)ed" " "®5j„îÝ»'¥û¡G ЈÖò äX2ñòÍ7ßàŒ3Έ¶z|ÿý÷AeW®\Ñá¨bÅŠAåsÛ)R¤Hn§t<Îþ÷?à¾û`ó@‹À“OóçÃÖ²ãÛ° f⤓`éÖÇÎ=7¾í©vÑþâJÀq…ª_ ”€gägŸ>}Üô{ìô줔ä»w»víÚ:´!" " é@€¶YhCãÆÁ4(2ì"àw2zé%Ÿ“‘ßYßæÞ0p pòÉS¦E2û©¼‹™·LD Ž6Ù¬Õ„~ÿýwS#ûЩòF³øëWæíÒ¥KÜzÇßLÇsÅW¸6Ž:꨸µ¥ŠE@D@bGàüóÏǪU«ðÔSOáÌ3Ï TL¥„ù¶2Eç£bÅŠ¡wïÞsÚÈP‡£hvØJ^káŽètTPÛºukÄKw÷JaG,©“É"p饀‰UaÔ(Øz¶Ïáˆ*GãÆÅ¯G櫎³Îò¥N³l릞¿¶T³ø 8‡#‹ªoi_LEý£}ÿý÷G›|¸MƒËD <5k|mQ*Ì»Jþg.Ÿ”øóF]GE@D@D ½ Üjšª\´|â‰'œd~zF½ˆ†€eÈÀÌ™À¤IÀ+¯ü½L£“ÑÙg§œ’·“‘ï ý+" Lssúé§»èS*}òÉ'öz&Ž?þø<»C‡#ÔðºxÙIÆ8dȰ-.LwêÔ)^M©^LI§Ï *`„ .h2·âO?ý4^2ô“ÍÛÜëlÄò¼þˆ#Žp¯Ü®×qèй×k¼ÏFk|¾ŠdT³¥mÛ¶-buR.Šˆ'é'M¼Ò¥3³év˜¯;íÚÏ?Œ T®Ÿ.R³V-àõ×ËÈ+„pߎ&Ëföù·Zµjå/çUþ›ÐiN€ GüÒÌã>%'o—,Y¢‡èmˆ€ˆ€d*Ÿ~ú L#ÚºukôêÕ+S‡©q‰@Âüó/õ³òî·_šÍwC»íæs,Zº¦næ“5æW@³fù®Jˆ€$À 7Ü€7Þxýúõs)o˜`Ú´iy:1}êܹsqä‘G¢xñâqë9£n>ø`0}›Ê•+·¶T±ˆ€ˆ@îÆŒãRY‚ΟoZˆyÕ02”KíGáàÁƒma¨}ôÑÜ+ÔB`Ö¯ýöÛo¨eŠ–5þˆ1oží½öÚ˳œwÞyèÙ³gбüì—äu~*SÙ„¨T øê+À¦ÆŒç§ >† Žé³RÕ¨dɘV«ÊD "Èî˜/ÕIÈ›ï¿Õªå]Î_‚ÀôÚÍOÞTÿµzt"píµ×š¤êvŒ1"º­¾Š@J`.ræA·@rg]»ú¢…š6MÉîÂÖŸ\´Q“&©Ù?õJD ÑiöìÙ.f"î ¡E@D@D Å0`Äkt"¢Bl4öÎ;ïD,êp´hÑ¢ˆåu2ýX’ðcå¼&ç0K—Îßè€Ä€ÉX›Å6ÁüÛd"4E’ֲΠ_|ᓆ‹v°r8Š–”ʉ€ˆ€¤3«®º »Y^%N0ËD ¾ÿ¸ür`Ü8àçŸ ×"®ókS¦T­Þ{o m[ØÂ 0l,­ À5øñã}Ñ=T$zàÀ‚ƒŒN;mÚݺ·Üüþ{Ði\z)̸çØÂLÙÃ׳Rì»/ìÿLE3øšDì‘5' N>9­© x Rʼn'žˆ¿,g#(¼Rù~¡¼TŽèpDg¥ý÷ß?^Ý ÔËv&L˜Ñ*PX" " 1%@U¦Înk?zélD;×ä8_}õUüñÇèØ±#Þ6/úùóçcøðáî¾ ç˜~ªLD@D@r%À´Ó^cºìhŒª„“'OŽX”JIå=r6óæÍÃÖ­[#^ã=Ù·o_41)l¾ ú_A&à¼j»Pˆÿ‡€gŸõÍ©ÚO8§V´ß~@—.°çíðsœýûïB5¯‹©ã±Ï>¾yÑ|]¨Â"CùQ8*R¯^½¦EŠ9ØÈ†Që¸ãŽ;Äö]wø%Z®\9'ýÊ ´æ&kC•š¢ÞPÞv\U¥.*ìÛo}«Im ~#‡19…¢C" " E`Ú´iæ`1Ý©$bÑ1£ài0"À|áGüúkÎå-ZÇã{z(P,Otâ|Œ­e£fÍœ:m-ÞEÓ”*<ôP¶lÎ9þôãƒy£F¾r”ñÁœ/¦ßåücO? ‹ð†¥,ò©!ùûµçž°Ts_}u°qN+9[-[|[ØñåDç5t>bÃSNÉ)Ï­M›||õtóÍñlIu‹€Ä“À¿–«±wïÞøñÇí{äQ·€ìmïû‚å¼ïïgSª-Œ­[· .tõÐáX&" "¹.¹ä·@øàƒ ²{÷îxï½÷`óé¦Ìy¼sBåýƒ*H%•÷"ˆ•vD@D@D ^˜â”÷]“Ðx¾É¤±#©Õ²Ü˜1c°dÉnF4¤Lš4É•¡Úáã?Ž‹/¾8â5<É–géÙ²Ó:uêä‚UýûzO=R…è‰'|êìþ–ÍœoäË|˰q#LùØÖ÷þÑG€ýäÃyçùæ!ƒÏÆgïüó}jïì“L’E Ï¥s2Ú·X±bæ!‚~öªáí¨ß9Ä{ŒÛ/¾ø¢;TÆÂ˜»Yò©§žŠ8 ´˜ö³€å)ÇÝwGÑáˆyMóº¹g:WD@D 302…êFLÃr³<2ãCMñQØú¶¥ïñ9ë0ÍÓš1-U ï¸Ã÷>¸ñÆèBå!* í±,Ð çFýpÞÅ2ø¸6¸æ~øá9ç4ðµ›s$x‹I÷ÝçëÏK/¶6äEÇ#ŽÅï€|uî{'[ÔFö9ýØc &N^=÷kr;³f `륊Ï8ç¼îž¯_æ`œyf¸:&"ê/^ìÒ¨}d³†T§8³†!V¹retÐAn™Q¯þ ,o1.0ó7€Òåx©h[D@2Uðf̘ai}º{CèÛ˜d'ï)]»vÅO?ý„‘#G¢Y³f¡Å´/" " "'+V•„žÜ™×êo“¢ïíLŸêW6ºÛÖDÀBÚÜìÏ?ÿÄСCƒNŸ~úéAûÚ‰?CRžKÙwdÊÆpŠê­[ûœŒ8·™WüÐõ×û‚1YO^FUtÎuÚÏÂÕL4Ó~{ú”Þ \‘.B°©ûðfá•J—.}—MŠ1D¯@!x[¶lÁK¶bÀŽ˜¿ZQáygÅÑ?ô­1Œ>£[}[™ 7I›Ë%:," " iC€Q3_X¾Q>DzÓ±¤ÍÔÑ´"ðùç>g#›·pJ?T4¢1³„LÙÙ9Q™(Z£³Ñ† À¨QÁQ<|àþòK€m1u™×)ÚºYŽ‘Atâ gùu6ò×ÁüèTMâ\ •ŽöÙÇ&ïw:hYpš Bíᇦ£ƒû]¥JN Ž…AmyMFä\¡-T!@ç Ñæ©H'ámö¥vÙe—ELƒÊ(Ö;Ì‹ósûâmÉpÇ£ÃMG!`´+" D€÷‹+®¸Â¥R¹r¹XÆ ññÇ;e<.xÊD@D@D Û¼cQp›( ]H;ðÀ-À+ÿ^×\sS!ò÷áu‹J;Ü¢æè„ÔÔ&yüª´MÂfìØ±¤w£ÍwÙ„WVÇ$½¯¶É'®‡ÓVš\N«V­\jÕpÏŠL±Êß?ÐÛe§ °,1‡FXGõ—Ó{l PÁˆîÇësàá/ˆq‘êòÑš‰(ƒéÐ8¯èSæ\ð•WúT–¸®NG"ÎÁ>ôðÀ>¥¥ÐúÙo™$›€ýù›}ÑžhÎF¶,›’l–çr;¿üø™×ƒkb” ¿dyøý÷ß#W®³iO€_’̤GI8çbɰðµËì®Â›;'be" " "i6)>¨2І¯²ì!Àù¦0 5:²xÍÖ¸]Žp:óa‘½:–­ÇÉøîLï½$â6JßxcWg£ˆE8iBö[ ¸çžÌr¤ùàس и±ol¡,æÌ{ &³ têä+Ïχû«Wû&˜BnÊ€Q2ô$ÀˆVª3ÓÙè|›ùãp^ÎF)'M!ï2 1Ä–X¾IÖHÝ(ŒvE@D ƒP½àÎ;ï´ß“qÑEeÐÈ4ÈLǼ¥¢šoAuUç1ª1ý)‡üÎF¶fîLN ‰¾+Q¢„çÊœM[;wj†thò×>ç΋GyÄÒv]ÎϱÉ&¯³×Ú©¶ÄgËL3:øPyüC|A•œë´L³N-üºë|ï î+[Öwœ~ñ0ÎÏf7ßJå PKä”=ypnѯND-.¡³<ÇùdËòn¿-az¾P‹Å>d"jŠy;dŽ=MÑèy;tÜSæ%szÛ”hþgïÿ³/Ü‘vÎþì}Æ/ßU¦ýŇ,NÌ=ÿüóX&÷À׿¢w†å`¤ £üe™I`Í߸\jÒw?ôíDp8b:5šŽ|¨ô¯ˆ€ˆ@æ £5eõ©l  èÌù\£ /¹°¹±³Ç9Wuë[„ö=0R9yçO!§ŠÓ¼¹ïá²fMÀ„B]J¯ÐŸÍ”ê­[×çŒÄ÷ûïÏIéejÍN–שLæ4qkíZFkù”zB3Q¨òå—}*?~ÎE¬?UOÚ<ÈÙãЫWþ{ÉÏ–×òÅ­Šó_‡®HïMÞŒ“º/Û—£K™ò”iá©Z­q¢¹ƒyˆÒQ‰RûÞ bªÑŽ8âˆh«S94#p¥…¢óûÿ~ûA^¬ y€ÓlÌꮈ€ˆ€¤;ýÍÃ…N@X4Ù$‹òûòË/±eË–À°v·Iµc,¯S¦2È$4À$’GE›zñÅñÔSOYðÚ`lfn¬\Œeˆ›o¾Ùæm’)ÃÌ’Û8%¦þâü…*¨;áÙt¹›eÀŸe)w¯_„þñµuñÅ>Gžø´]­Lå;v§Ÿ™ù¡¡Q#_² -¼¢Ò¥—ãÆÁþV}iÖ¸/T!p,ÚgŸ}ö´N=i¯À1O'瘃Ñåæb>t¹¿)9Îó]žg`o½õž~úi|óÍ7AÒ;ô¬³Îr_âÅ‹:§Ì À›=3«W·ñÐ}•9%ÚµËupr8ÊNˆ€ˆ€¤9W^yÅIñÞu×]ùà˜æOܺOçk Zr E¦Ô ¯³¥ãƒÞ~挜sLèÜÙ§ “WǘîžêLufó#3&øŠü8ñJö×ÖÜ0¥y9')gz7Žƒ?ÙíO8ãŒc•å0Ô),ã`i@"˜Ê›«“-ß$üÏ¡e-”ò\Ó4罺 J„tPzÛ¾Ð?0Ù4NJûGEL[½3¿Üe" " G€)atK¥„ü8«f HD@D@r!0dÈð•;ñÄ]¶hÛ¢zÑe—]æ^;,²Ï‡L§VÝ6kÚ¤[)¿üŒUèuFbý‘Žüí÷ë×=zô0'šÏ±À'x ä‰yÎM?š±uÔQ®£^ýGœÔ1c†›DfÔªLD@D óP¹€vë­·fÞà4"È" iDy™\ì+J{,‡#gp E:øÊVkØ0#Œ¤*<‘ò2e>ú(0~<,p÷Ý0…ªœ«ì#NYg£œ^æ¾eþíèÚ T­Z¹—ÓH4çpÔ AƒC­á3B_m9%;.[¶Ì=ÞZ·níÔŒ˜F„y1ýÆ<•Ç{¬“-÷Ó{†Xn~k|Qó-‚Ñህœô•‰€ˆ€ˆ@& ÃÓ«˜¢d& +kÇb„ñ À¶m½/ð zŽ&ýXAœBáÖÙÈ_ßUWõë§žê;b“ú×ɯ¿Þ_Jï" "~¨<ÄÈQK#o¼Ñ91š4VÖÔBë•Ùÿâ‹/\t,åñe" " ™G€J¯¾úªEëïgAæ½/HiT¼:uj T2jEy(lΜ9R¶®nú ¹ , fáã{,g„zƒ#©¸n¢’hÑ"÷JôyÊ)¾ùZúQÍܦ2ÎLëEÎF÷©¦ÿ€œÃ‘M¸õÊßÿüóO×X9ùë®d9yä7É·víZwx›­ÔÐéèöÛo÷Ó{¦ º-7:ñ&Í `™ˆ€ˆ€d:5iÒÄ¥TɤqeãX˜rlÀØrøÑóçN47á¯NþQFõîÓûï–-ó©V*]Xm‰€¤¦5;á„LM®¸›\nÓ¦M\@•#*]P"¿F`»´#™/S&" "qfÏžíTóäXšq­$" "¡˜Bíâ‹/Æ’%KÜË•+gz ËQ¾|ùˆ#f*´Y³fÊ0MšlW²8—¶Œ~\L|SX³$JÎá¨O`Þ¼ð ïT4bœç.9w»S€¸°Mëz( ±ræß±›ý÷²‡ìË6X.ètÁwø¥}Ûm·UðÞ{ïY>ÆB&d ªQ;)E ‡#~þK—.µº}Sªëꌈ€ˆ€–ÀƱzõjì¿ÿþ…­J×'‘•~l>¬}xî9XþuàË/o¾,S°åy:tHb'cÜôæÍÀwø.¼0Æ•«:H·ß~Ý»wGÉ’%P¼œ8oZ5îÓáˆ*¾mÛ¶å®LD@D ÃLš4ɨW¯^62 GD@D@2—@—.]ƒÛ´i“ų±xñb—6{ëÖ­³º÷Pm sƆâÄÆÙˆ•S˜˜nT_·k9 â<“ç˜/¸œv!¤"ELQæ@k¦¦§©í¦:t‹g?æ›ÌSY¯^½@½\ˆûì³ÏûÚȡ֬Y“òZ[¶£GÃÒçÙXèõ[§°÷޹짟~rc’ÃQ®ˆtBD@2–@ºÜÛ úP݈ÆT+²äà|Àk¯ï¿_°öéLtÈ!À¨Q@ÇŽÀÂ…> Êø2s‚‰WYŽw˜Rcø(›‚µšü«,Å<Þ|3 \¯LD z™~o‹žDrK¾n¡'Z8ä{ì3fD-•_Ð^SÉˆŠ½L«ö—yª~hÁ7t6¢Ó‘LD@Ò€îmÁŸàÿý‡W^yÅO6kÖ,ø¤öD@DÀ¬\ \z©/PI@R—€îo©ûÙÄ«g={ö ªúËÙEÕ£•üO»Óø<÷‰åðzðÁ]`‰?kOŸ}öÙ8øàƒýEõî!pÓM¾ù×ÓO÷ŒÁæå—û–š÷Ü3¸²«®®¼è 0ã4-‚ùhOE ˜M†Y⇳‡¥L>î·œ#ñÙêÖ­zè¡@å3gÎÄ¡‡ØOõ Jç1GwA¬~ýú¸è¢‹¢¾”“”ãÇ·¨ùÿ9g#^ÈI̪U«¢]»v8ùä“ÍÃÓ\߸ùfàÚka©ñ¢¹23ÊH”#3>Çl…îmÙûéSu¢i®3µ;•†q®^½:¸èL‡£96ÛÉX¥SËÞ¿A\âI Q÷·tœ“Œ'woÝsçÎŪU«põÕW{k[D@jÕž¦žâSç¸ì²ìšO€Èdžîoù€¥¢&pÄG`Ĉ:t¨«ƒXFÙd!_eÊ”AÍš5±lÙ2lß¾}—6°ÈÃx`—ãÙvÀym˜0°¬t³%븘-‰Ã²áìßsÏž|8ì0`ÊŸR €6D@J€GAþ€¶ÿN"zкuë f¼ž£A'Rt‡•oq«ÖÊWFãp´Â¼v®2÷ÌùN&(¸!FÑУ–‘4|uîÜÙÝ ËF»z\]Ì÷L„ÉYõMæHd}u+uZ‘ÃQ8:%"  " {[|@Ã|[f‰XèŒÏR¯VÊçzfÙC!1’…ŽAü‰Fe:ñ”N3Ìr0mšOҗ⋜ô ù9v  Vf®ðóχ9z‡-¢ƒ" )L@÷¶þp Ù5Î!sÌ1ذaƒS0âİÿEE¡)6ãH ¦pßo¿ý ÙZô—3­ÚHÓt¿ï¾ûÜEr8ŠžJŠ€DO Þ÷·tž“ŒžbáJ*ZáøéjÈœà"8•>¨ÀÁm¦b2ˆPãâ¹w1=ô|¶ìëþ–-ŸtòÇy¥ý§¤CÑm–«Ë›*m‹M&ú×+C{Ù¿'¤ÁçÎlµ?†9jÁÔ|bÅ|ªCÇ—XæfB>5{Ó6qÁ¦¥K'¶jMD ˜@s\©æ=´cÇŽeÞýxmSÇk¿þú«w7å·éÝO#Þ¼Â9…k—òðÌš*ÍÊYµußú6òP¯òßÀ¥pîÓÕ1H ÝÛâÙ GåÌ;f/&’–Šˆ®¸–š×—Ü[³óöî ûý˜¨…ËïmªÇΉÁ—\âsBbd¡­M‡ÈãëÎ xª‹&N”³Qˆ6D ÍèÞ–fX”Ýå„0S¥Ñ©woKÝM£Mæºxñb|ôÑGxã7P»vm|ðÁ u6b÷épD£ÃSÅŠSNØuNÿˆ€¤=xÞßÒ}N2QîË/¿Œºuëê{>QÀÕŽ¤/¾Ö¯îhË–À‚¾l ~jÞܧâ/Å9.œ›0§Ìèþ¦?ƒD¸ÖdÌéd}ë­·¢qãÆ(Y²ä.Í×2©²ÁƒƒÎpãÆsA.»Ê‚LRÃ`N.õ ˜ùã@¢ˆúï¿omé™Îœ“'r6Ê‚?@ 1å ˜ÿ!‚ŽŠ)²S›&¾}¯V-¨Y¬[·.¾ ƸvïŸòåË£T©RQ·P¹råˆe™tÀ€AùB9z˜éµµý-Z`ãÆ.èsÏ=‡Í›7»ú–.]êd|üq—r-b#q>P8ªm7hêÙÙÍ:’ÑᨴÝ(U(HÝÛâË¡R7*<[ &R©háBàC€?þ®“ÇèhDãÃon?).¸À—éÕ«ÄŸR£Gû^THbjXûé%Ⱥ·eÀ‡fgŸ}¶ ιñÆ1|øð0%’w¨½åáäóû6»¡P‰ØæX’×µ,"±âuË„9ÉD|èŸ~ú)–/_nŠ%W&¢9µ!"¨¤ÌÔAUªøRµ[‹ {â ŸSQ—.>Õ ïI.1µ{÷îÀYggžé[$g€ÓÀs¾ã„Ae»éþ–í‰?×kéxÄ3ˬ±ÅÍŸþÙì¹çžîÙ.ñ½J¹Ö{óÍÀ˜1¾ï¨“Nî¼hØ0y}äw*O™ð‡Jr2ä`Jµ2Þnüûï¿;¼ûñÚfNL¯11]Œ7z½úRétŠ•½øâ‹X´hQ ºâÅ‹;ÏÙƒ:(pŒí,¯Ç©§žŠ~ýúœ“˜[ý%û•zÊ)§•MôN@áèüæld¯<ŒGR7Ê’N‹€ˆ@ èÞ¸LÊaª0È G€—]æs4bz³Ðõ[:õì]^g#^Aér fB… ¾6¸/Hº·¥ÿgnwÜqxÓ£GÐá(ÕŒÁH|VŸ>}:Ž8âˆTëžú#"âyË„9ÉD|ÄJ§–ÊjCRƒS³ßp,ø;§?:^‡£©SsÎöٸr¡[G |õ•O„ŽF4ªƒÐžJHÙnº¿eû_@òÇoëå “_Ùn;ÌS`ÄXÊ9ß\¬=âºý<’Ù$ [èÜnÂVC" a 0¥šù'æ˜EßUÏÙ‹ßÖæ²ðX®ð¤‰ÑÕ?~£|n¬Œ9CÇÐUÔc·ß~{®ò¼LÏr÷Ýw{JœH¶Ž¢økâ˜$‡£djj_D › èÞŸOŸéÔhR8æÌx¸ÿ~àÞ{‘#}ªŒŠ±µc÷ÐÊcæÇíÊ1úr½^cà A»:yËd›?C-ëL,ÒÔ"aòÈ©E׈€¤ÝÛRí‰Ü¦ ûøã#bª4Fž6·\O?ýtÒ•}së,¡(Çß­[·ÜŠè¸ˆ€˜@¼îo™2'Y`°ù¸éÔ˜º³uëÖù¸JEE@Ò‰À{ïùT–©XÄTi^èKÙ¾r%еkðH¸×]0Î`G¤àR¾½J•¸~㛃øüsX*`9ù9éþæ'¡wÈ?:q.Õ~žà¢‹ò½÷ x²Tá¾9R[‚Æk¯¦uáå½å´-" ~T8²¯Ž3$û:Š¿…:å•f,þ=о¯¬#¥ÒkÔ¨ýÅy”œl '©†à·#<Ǽ7ì;•ø€K9_ÚWæ&O¦½÷Þ;lùDäŠƒÉæÝÚ’%KLYà_9åJ%D@D nto‹Z¦S£ÉáÈ'>dHþ8¿ðì÷Aþ®)hiE”œ®Ô% {[ê~6¡=ûñÇ Ÿ =öX‹¢¼Í9yËñžÚ·o_KcQ|n.“ÂÞ¡XþN*3m¸LD@bM ^÷·L™“Œ5ïÐú,XÎe^z饡§´/"¸ÄržÅõ%|jDæï.ºG²¡C#ÝõÜá‡ïz,Ûèþ–ía0ˆóª«~oíKyvñÅù¯‘ªïü~Z¼ØôÉ Q‹¥‘‰€ˆ@DT8 r82…#vŒ¿Í§»·ÇÒÕáhÓɤÌ^¬löìÙAUE+ÁšÒí-&N¢Qá¨Zµèòg2M GIüÀÔ´ˆ@Öð>ÔëÞ»?¿ÂQÓ¦McWišÖD¹qþÌùè#`î\Ÿ9ómó'¡ÍÙ»ÜÛ”(ç9–›5 èÔ)M«n‹€¤ÝÛRâcˆªwYH8޲0J>Ëxà8í´ÓLéÎ÷¬È€%âlÛ¶ T•¨S§NTõ&³œ’I_m‹@fˆ×ý-Sæ$ãýé+Z¼ «~H.Ò3mE7-y$og£äõ8³ZÖý-³>O&±Î?ß—þqéRŸ³'C–›£êPÑ¢Õèí±Û9.ÉÙ(*l*$YO ˆ9ËøBïw¢0¤Î 4(o2³¸Šä±&MšxöR{“é¿üV¯^=ÿfLÞ?ãÊÛN£#S&ŽÂB%|“ípD…#:EcþId9ECKeD@D >to‹W:Q‰¡zõ(rŒÆ§ )S«‰B¢m[Ÿün›60uFŸÔ¸ 5Ú²o›ÇxŽåÚ·ªVM™î«#" iH@÷¶ôøÐV¯^íÒ£1ˆfÚ´iøÜrKPåèùçŸç ÚjO¯^½œšÄC=d÷»AÈD@D ‹ Äëþ–)s’ñþÓ ÃQÍš5-­È¡ñnJõ‹€$ˆÀ?ÿLáÎ4D_ƌ9¹'¨jÆÐýM"=~oy­œ­êßt,#ðê«>U¢“O˜-¿Ö³'`YÂe" "5"‹-šnNFýW˜“KIÛæßÇûO?ýä&½uwìØÑ»›ÒÛ^OëºuëÆ¬¯”ã]¿~} ¾fÍš!Zå§8¥J• \KIúdŽ¢][•ÃQ2?)µ-" >º·Åç/áÛo¿ÍÚtj¶NìpãCVµŠ€ˆ@ÞtoË›Q*”¸çž{ð×_áꫯvÝiÞ¼9Þxã Ì™3ÇPÛbìØ±˜9s&.¼ðBœ{ÐeõAD@’J ÷·Lš“Œç‡óå—_:õ½ž¶KÅûxöYu‹€äM X1_ÔtêËûïŸ÷5*{º¿Åž©jÌL·Üy$ðßáÇG}'Ÿ~ù ÓÑ߇/ÇëYîÍ7ß×Qˆ–Jm·×d{õó_dLC6l8Öœ‘–øÅòýŽ;îpréþ:ù¿ýŠ ýáó¹’2EÜ?üà^Æ {ì±5jãN˜Ö¯_ß?Ü\ßùÐê5^­/^µk×víóš¿í²iÓ&”£[k‚mëVà?ò§pT¶lY©?$øsRs" "à% {›—Fl¶W®\‰7"Ó©YÐ/N?öÛ¦Rá˪ªED@¢' {[ô¬’U’©Ò{ì1÷ÌLU#¯vØaxÿý÷êѼyó0tèPïim‹€ˆ@ÖˆÇý-Sæ$ãýG¡tjñ&¬úE yÌǶÄb΄ÉëC¶·¬û[¶ÿhüy°,ä.Ýã¸qãmÚ+†¿ŠŽFL«6r$pÙeÀ¨QÁå/Î:Ë—vËóÇ)\F{" "-ç»mFí¯Ã¥rÞÚk¯½³Å² ÑVM¹gŸ}|ðAPѦ͖NQ!^iG*tÒI–Ï×ú†ØG}äŽpl½{÷Æå—_:Öäf^u#–©P¡BnEÃ/_¾|ÐqÖW‡£-[¶`óæÍà¤.­ˆÝeâÝ+J£º-? GJ§æc¦E@O`«yI~óÍ7†wìØ:’f›eú½ŸóŸþ¸·ñóå½÷¸x™ÿï*œªcÁÂ~F8rþ°Ì8(Q"µª‚X±bÖìüqNåþÎÏ&Ëô{Uøò?·ñ³e° ƒQÒÅ|ðA÷wéW7 ×ï£>|ÉD@D€V­Ze©!|¹!¨˜ÍßøÙfñ¸¿¥Êœ$(ÿµÕ4ï½ÏS»3?s Ž˜.»]»v)ÐuA2À÷ßÃþ¿ûÒšÅstTõ`À´w©&™s|fã³ëLÛ¶m‹çðS¶îL¾¿:×ÜøYûïq-Øo¿ýRöóPÇR@Ñ¢>µ"Æê¼ðP¦Lä>Þy'L,°ÌähÝ8㌜òœ6X¸<¸õV9åÑV¬ðù‚¯h ÌÞ¾ú7²L%àŽìGÌtsøxÙc,3cÀ•.]zª)óô´ô\¾_;SÛgn—wòÎc•*UÂyçç9’Ú›k×®-ýFµ¦¼ÌRÖá¹çžÃôéÓqóÍ7£sçÎa/ùý÷߃Žç×á(Ô¹ˆÿ™ ’òíÓÙãÜÛo¿Ýõ§dÉ’®ÿA‹°³Ï>öƒ}Ñjü[†êJ{D( ÷ã™_4Ê{“NЀđ¿×ýßwl†G\¼Ë&ˆ{Û¯¿þŠÐÏúyËùU"Ž3J_ýµû3ÊD…#NÌ}÷|/f¸±Ÿ Îø°;u*,Õ+РA6ýOÒXE õL3¯¿7wjcóY#‚< K3îmTÑ£ª­÷wÌO|ѦL™p>JNoÛj6ÜÛ¨°PµjÕ„ÞÛbù)2•Sîºë.›,M•žXNu‰€ÄÀi§¾hTPüñÇãÖV*V¯û[ªÌI2øÒ`SòÞ¦tj©ø?B}Ê&Xçœlù£GÇÏÙˆõSåcéR ˜Âyt‹öñæ|üñǃ/Ú‚ 0|øp·MÿdúýŸ%÷ÜsO\{íµÙôÑj¬1&_Ac›2°5ià¸ã`*¡9Gì–œbüᨺ ;v_4úLœËˆeYÆ8™ãÇZs˜h#¥cQà¸mW´É¿çíÜͦÔ3Úk^6E¤Uy¡4üGÛ/DF„3þˆ:õÔSÃJÙcÞ<²þNò? Uš(è5¦äyúé§]Ô¦_â™ÒÀ—YÂL.x†Ê‡>ÜçWá(4]#F“föÃEt6bß(M“ÑàD@D )to‹v¦T«Y³fÚ(MäFRão½‹HÞ}×¼ÏmŸ™V)F±÷Þ°hc V­Ü®ÖqHÝÛ’Ã=ÚVÝvï½÷Úý£Î<óÌh/S9Èzñº¿eÔœdþJ¨*8vìXçèÛ¡C‡8´ *E { X<2:u‚©Rò,'”ÂB0\âˆUÖ).¼qpÈ!À@®„ÉR†€îo)óQ¨#)Dàw‹Óq*Eùu4òÃïhi>Ý2ˆ ¯cóþjê6Ç›ƒµ‰Ë„´ØÐœ°c˜sˆýÔÃ'¦NÔ„òçLåÅ Cz!û_LËÅTb¹ΘŽ,Ýdý½?|Š˜nÝ7ÞˆÞ½{‡f±bÅ0`À´mÛ={öhTõ¹ï¾ûpõÕW]Ê"¿i^üõû+ U<òû»¥ròe¾0<“ÃQ€tZD@@@÷¶ØCæo *;vØa±¯q¢OÑÈ‚`?kpòÉ0µFØo›uB͈€ˆ@ èÞV@p ºì)“Ê[½zµs:Êïso‚º¨fD@D % Äëþ–1s’qúÔhºbÅ §¨%U¾8AVµYI€é|èldKIxöY_`“„esŽAŒñ¶,T([Ö¦pïæ;(KAº¿¥à‡¢.%•€% 'À„.¸¦\xÇK9%õãTã"ñ‚Ž8Zs†y»^½zìáiŠ=lV GÀŽ[,;öš:uj¸Óy;Á¾%o¾ùf[¸Ú¥ù<¯Mv /¼§Ÿ~ºË5Èþ3O^ÖÈ”~¨jD©x¿M·Á¡G”Ã÷Z~óÒéËk+Vôî&lû‹áwt@»-‘—0¾Žö±¨!È•€îm¹¢)ð‰ŸlÖlË–-H×tjÌë=nÌY¨R¸æ`Ð )øBŠ€$œ€îm Guƒÿþû/FŒaòí•%©55xÝß2eN2'O<ñ^|ñESxí…sÎ9'M¨NÈ(ëÖY Ë¡AKoB s Ft0¢bÑÒ¥°T+0't`Âà”S‚1pq|èP`ÈXšh_Á%ûYéÚ¢"óæÍ@¥J»¾úö…­á„^©ýT# û[ª}"êO2 |ü±Ïو߃3gÞÙ(™cQÛ" ÙA H¸a.Y²ä³­[·6¶s[„¾ýl‹U¯^cÆŒq“‹¡éÄbÓBük)Y²$ªU«S‚ŠÊÙÈߣ³Î: eÊäˆF­4=ÐP‡¢*\ÑóXèyÏ©°›Û¶m :^‰¿°“`w=Zñ>v´°|+yŽ˜:.tìy\¦Ó" " 1$ {[ aéÔh©êpÄI9Nþþ;Ì1jg§=oåË;ûŽ,·Ý&g#mŠ€¤ÝÛR÷Câ¢-U/6É<ï3rêöX=Ô!¯û[è¼\ºÎIÆú“úá‡ÜýªvíÚNÝ(Öõ«>È4gœÔ¨XÌ6þÏÞy€IQt]ø°ä( ’sTrV’”((& DQ1**~³b@ ˆ¢‚"$*‚$‘("H2$‡ÿžnfwf6Í.3»Ó3ç>Om§êꪷg§§«NÝûÑG­ã 9'2Õ¶Q'‹>-†L?¸ôÒÀ¼¾­›o®º èØÑ·Ç]<ûŸlž7.» X¶ÌÙ¿,¦Nu'P Ü{/Làx®¶¢“€žoÑy_T«¬'°d‰û—#ðÙg@:Y_]QD@2J EÁ 1AÌ?bmÐÑ£GëÛæË&<Ú•ÑÂ}ùéáçá‡Æt 8¯q®éšØBÑù8K†Zñ·}¹ßÆ@Ç~–]‚£­›¢þEîÆõüj“ò*GÁ\RΩ½" " ÑF žžme¿Œ½]f§Ÿ~zFOÍ’üÔCѱ¢i~Ž¾à‹šã Б%gæË|TÛ" "»ôl‹ì½eÈQ†V/dÓÝÙ‹©tDé=ßb¥O2±ÁaX¡'ùÞ½{ƒË &8&ÃP¬Š˜!pôhò¦pòÒùçÃþg€îÝŸ{.0e @û#¬ž•-˜DšFAÒÕW'e™4 ¨ZÕýû/0l°a°b°u«ë©y—dуÒÂ…ÀóÏ'«µØ# ç[ìÝÓxnÑš5@ûöCJòû²Y³x¦¡¶‹€x‰@º1Ílæ!GÌ”-[öfëìjë--5µD5IKÉŒ®Ñëׯ Øb3Ô­[7YžxÜAaÍÏ?ÿœØô`PðËýæÍ›ó†²ò'ý7†{+R¤ˆo3K—%öýzì‰X“Ôm¯=5Yçx¡¥NFGD@DÀ;âåÙ–Ñ;BGìôˆÁÑË/Œ²zñÅI­ Äë¯w;âÌy£LD@DÀ€žm~0¼:Õ¦œ/]ºC‡µg“=œd" " YF ­ç[¬ôI†æwÞéôã>øàƒhÙ’Ýá2-[ÜAðÉ“={€¹s™Œ¸í¿Å¡Š®]Ýä¿?£ëœE±Ó“O ï¶ÍWVá“B©ùˆÄöRϷؾ¿ñÒ:z|;ï<àï¿ +éy^&" ^!®àÈ׆˜‚ïOܰ}ûö·-ôZ¯=öë2Ož<ÎLŠ\rçÎÍã² Øø[åÊ•ý7Pmþ;R‚¢1œš¿@‰‚/tf¹Yl–÷þëäú2Å[i^~Éu9Õ?e" " Þ$϶LÜz8¢Û}zpÈN32Äõ}á…€é‘+_ÞâæŽËΚéÚ" "½ôl‹Ü½5j”Ó_pË-·Dî"*YD@D Ei=ßJ–,pŽ'û$ZpbÓ¦MÃ{™jÕª•…d²˜L2ˆc _öá‡À‹/ ‹fÝùàÄ%Œ:ûm—µp:ÙÐÃo¿¹uÈÚ+ëjÑJ@Ï·h½3ªW¨¶ow¿Sé­í7öáÊD@DÀKB¥Ð¨£6ûÅ~RÆÍ›7Éøì‚ .0÷Ÿæÿ3Dó?—§T«V-àÌš5k:¢#Ÿç# i‡ÿþû  È—Ò;Ž9’xè\ú(Í[´È}ëhØ0Ý«3œM‚£tQ)ƒˆ€DŒ€žmáGËçñ¯¿þjoÖû–fkpÏ=@íÚÀ—_&‰²±Jº´ˆ€d =Û²s†/²dɤúÆÂf\aá<Ëfø| " ñN ’Ï·˜è“ Ód‹¹p¹Úâ7µøÓ ¥–3gÎ0•¬bDÀ[ØuÿÒKÀøñÃm¾9zôp½'wìèzÊŽq޵<5gùÈ]SϷȱUÉÑAÀ†z1`€n’“@}6s&,ä8ðûïÀÊ•½Ä¥fÒw®–" "MNDpMíÈ’ºXx9 ><ñZæÝ LÜNke«^·n]bv°(P q›+ èܹ3^}õUgÿQó :×ü’¶gÐÎtl&ŸL~vöÙgûmeáªÏ+“GY]—Ìг-óìR;“ãàŒ3ÎH-KÄ÷ÿïÀ#ÀBÜ_|HGü’º€ˆ€D =Û¢æVTdôèÑÎöºÞ“‰€ˆ€d˜@$Ÿo1Ñ'™a¢ÉO 'ö>}ú˜¸b;>øàT¨P!y&í&@oF —æófĦÚiÜqLˆ”(ÃWÓ²€žoÙ†^Îfx4"†ÍÁ¿àˆaÔšÒº‘áÑ AYP!]BD@"@ !e†Täã?ŽÿÙh˜/…tR6gjÑ¢E@ ¦N°ÖÆ3ÏúÈÉP(ã/–‰f| faä«Èp)'NLÜNm…^Š8+Æg… Â7ÞèÛ XÖªU+ ÄØÒ¥KŽÙ€L~{ìitýõ×Ã?NmÏž=ýrdíê¯ßýƒ‡‹ÂŠ?OJ÷Â|òÉ(V¬Xºy•AD@D 2ôl ?WŸà(«<ѵ9f  œv@mÚ¸aÔ, €LD@⎀žmÑwËŸ{î9ÇûŸ¼Eß½QD@¼C ÒÏ7¯÷I†ãNþôã : @IDATÓON1—_~y8ŠS"à)ùò¹"£'Ÿ6m‚ImÛzª ª¬G èùæÑ§j‡DÀ†oÁ¹©½z¥ž]a"Sg£#" Þ m‚#oàI^Ëk®¹&`ç°aÃðè£â ý¦`/¼ð‚3+†áÑ|FPñâÅ}›É–ÁaÚ~øa¼ùæ›8|øp@Þ?ÿüÓqó»ÐÆÌŽV¯^ÝÙ1«6þû?­?÷ÿ3Ä™ùÞe)8ªQ£FzÙt\D@D Âôl /àåË—;aRk×®Þ‚S(QWK•zôpã|ïÞ ÜpðÙg€é›e" "·ôl‹ž[Ï0£Ñ o°÷Œè©¥j"" Þ éç›gû$Ãtû/^ì”T·nÝ0•¨bD ü‚窫S˜3.\{­òlÆЮÅa ÆàôŸ1r$pÛm°IÂÁG´-‘% ç[dùªôì%`~&d" "ÓrÅtë"и~ýúaÕªU ‡&Ÿ½þúëŽ"ŠgèÍ ŸMXi¾FéiçξlβN:é ‚ºvíŠY³fá“O>qΡXiøðá?~<øÂËò,X€ Ao¹råƒ>ˆÜ¹s\3Ë6~þ[•t.WÒ]¤zé¿þúËÜnA‡RÍ£" " YC@϶ðr¦‡#ÎÎâó:Òf?;ÀgnÛ¶n2ݱLD@DÀèÙ=zÞºu+F…œ9sFOÅTð H?ß<Û'¦{IÁQ… Òœ(¦K©H“€LÀ—_º‰ax*UJÊþÏ?Ào$mûÖž}¸ï>W0”ÚðÃútë|ÿ=¬ß8t6–à+AKÈ>z¾e{]9¼þþ8vLa(ÃKU¥‰€D; Ž2q‡èqˆ‚™9sæ$ž}È~ÿòË/NJÜ´ÂMt!Ÿ'Ož #É7)¢X‰Â#Ÿm´é L)Yþüù1vìX4nÜ8¥ÃY³Ï<-mƒ«4¢·…´Ì碸Q£FieÓ1," g[x@Óã!=øuéÒ%<¦SŠÝÊD@D@R! g[*`²x÷h‹õY¸paG–Å—ÖåD@D & DúùæÉ>É0Üiz–_±bÚµk†ÒT„œFp")â.ýG6Ÿ{÷GŽôVÄå?ºaÖï¾Û#Q|töÙÉëP¢,Š0t(lâ²ÄFÉ iOvÐó-;éëÚá ðÃÀ€IßË6l+¸ ­ s#)zå•Wðâ‹/:Ò+¾”©o^{í5ÜqÇ!‰X^Á‚ÁplƒvÖÓºF³fÍœk-[¶L+[ä]z)¶ž{™sô<ÑCM‚#ƒþˆ€ˆ@¶г-<·€ÙQ}ú駇§@¿RLïŒwÞñÛ¡U4 èÙ–&ž,9øÍ7߀Þ""¡GÌd" " 'L ÒÏ7OöIž0U8b#†­_¿~JS"pbžz øî;€ž2JÝßrä8ˆÍ0êüyU¬˜›géRX”`ýzàœs€Ë¬›~ófÿ3 €yó€'ž <¦-Ènz¾e÷Ðõ3K`Í W/À†j±|9,Êû=Ùòtžˆ€x€ýÄ”e–@›6mÀDo=ôf°Þ~Í3ÌYñâÅQÝbš01¤JéÒ¥‘ƒo´„„ÜxãNçì´iÓ°ÔÞ6Û[Â^›ÂP¶lYÇÅï9öö‰AÍ VÕÍnS$¶åu¤65M#3†€«W¯^šùtPD@D k èÙvb¼NÆ«á´{ï}hÞèÙ°Ÿ2 èÙ"¨d£w#¾×ÞtÓM(]EŠ€ˆ@|ˆäóÍs}’aø(P KS_e`ªˆ pNî˜1À«¯ºb ߉:øÖB_2¨û.¿¸ùfÀ¢ÚbêTؘP±bR9 ¡–ÄBkÑI@Ï·è¼/ªUrÛ·=sᆨ¼ðBà±Ç€Úµ“çÕˆe…áîÒKO$=õ°é=zôpRªÑ"¶nÒónÄ ÐÃÑi§f³1l:†LD@D êèÙ–¹[²œÓXÌÂ)8Ú²xé%WlôùçeîÎè,p½«ê½-ë> klšç§Ÿ~Š®]»¢jÕªYwa]ID@âŒ@$ßݼÔ'y¢·]‚£%¨ó3BÀæ,ã¾û`Q €œ9a޶m3RBêy+W¦L>ùxà`Ö,àŠ+Rϯ#"­ô|‹Ö;[õÚ¿øùg˜cX(ðÐÚ¶o0r$ðÿìÞ ´há®gwšÐj¯\" "~…Ÿi\—¸mP¦LÚ¶›ì÷?þPLô´1騈€ˆ€ ÐÃQn›.X³fͰÕÞ%:„åÊ…þâ¶‹« È$16]ÿèÑ£2dH&KÐi" " "u~¶ÑF†“£·z™D‚À¡CÀǯ¼LŸûœ>0jlbnø¯Ø¥ À$H™À‘#n(´Ù³aÑkRμwÓ&€žŒ,ˆ‹õÿãÇ]œKÛ" þþúë/§ÈŸÖc‹@Bl5G­Én¥çáˆÞh7Îîêêú" " "V J~eÆŽ¾ÿàË«¿Õª%±‘?­‹€ˆ€D7;wâµ×^Cƒ œ0äÑ][ÕND@D@€%K– N:N(PñpX±:à$" b€3` /¾èÅ8b£pÖ_e‰€ˆ@¬¸öZWJq¦iŽÓµš4.î¿ £{‰ÒŦ qL`¶©ù.½ôR´nÝtF"‹]òp»÷6Ë[f}Ê8p(U*íKûG‘ gv tTD@D@ÂO`“©„6n܈N:e¨pÎjüî;`Ò$`òd˜@7þ7Ý«ËD@D@DÀ‹^~ùeìÙ³GÞ¼xóTgˆC›7oÆ6›EÙ½{÷8l½š »vï½¼ú*0ož{z ð誫Òï?DT¦ˆ€ˆ@ö»Òã\‡î2Gޤc)­ýû/pÞy½Õ½û.pÉ%)åÒ>ÝgðM‹;nÜ8å-GûçjÞ¼9ö3~¡,f Hp³·6ë¶u«{Íô<Ñû=?Ô«W/ë+©+Š€ˆ€ˆ@„Ì;Þ‹ÈСÚáÃã{Ó«Þûï¸èÖÍÝÖ_ð6ÿñÇGi‹ Ú»wo¯U_õˆC‹/vZ­¾Ê8¼ùjòèÑÀ ¸£~ý€V­"t1+" "!¦ƒÀðá@Ó¦Àû﹂FÊo¼¨Z¸õÖ¤b‹žÞ £Ö¨QÒ~­‰€¸V¯^§žzÊqZÑ¢EIh×_½ãAtàÀB¾Fc¸¥jZÄ 0œ-GgœqòæÍëž ¿" " "|‚£-Z„Üš_tÅF—_îÎt¬_?äS•QD@D@¢ŽÀš5kpî¹ç‚!Õ>úè#äÉ“'êê¨ ‰€ˆ€ˆ@0 Ž‚‰h;#6l*T€ÍàO:«o_7„ZÏž žDEk" "ýèa~ð`W84ujòPjôP7s&ðì³€é'0v,3§[o‹ %"0gÎŒ9ü1ŽZ(F7ºá†œPjùóçwr³¯HÛ$8Šíû›¥­cH5jˆÒòp´ÕÜ 1äLú)”‰€ˆ€ˆ@ ˜?>ŠÙt—šô“‚ñvØ0·’Â#Î|”‰€ˆ€ˆ€W ¬_¿çœs¶oßn.æßEÇŽ½ÚÕ[D@D ÎPpÄpuêÔ‰³–«¹'B€NŽm"¿ý«¯€6m’J£‰^d" " ÑC€B¢+®p&LŸ”(‘¼nEŠsçº!Ó~þÙ ¡æ%Ï­="[Ž;Šƒ,XF+âd²*Uª8©ª¹ýb:å”SpäÈûý3Ù}o¡ø;ºK—.:v¨yt”KÇØúT„Ö ŽBã¤\iàˆéc¡S»vƒñS0¦ž™_R´Æ§žIGD@D@DÀc<ˆ… âì³Ïv~`‡R}{tÚ ,ðê«…ÂKyD@D@¢—ÀƱ'—¼õÖ[¸è¢‹¢·²ª™ˆ€ˆ€ à¨šÅ·.\¸pÐmŠ@ê8hÆ à‚ `aCRϧ#" " ÙOàÇnÝ€|ù€Ï?*WN½N'L›ìÞíæO=§Žˆ€w l³°EëÖ­ÃÚµk±hÑ"G`Äñ]óOà *z.âd3.¯½öZ ?xkÈ“°Ó(Z‡þ¸ëÞÈf´&$¤^3Ÿàˆ.Õd" " "+ø£|ÿþý5œÚ£GõêW]+Ôx$°eË'Œ=½òÊ+ŽÛìxä 6‹€ˆ€x“ßãV®\iƒ6 )T:äÎxð‰'`ácZµ÷kKD@D z,[æz˜7g,Îw6=Õ­›~ýrÙè¹9²—‰@L˜iL™âŒ(2úí·ßðßÿ´­ˆ¹÷jРcøtRÂÜ€1¯ï.™(64h“˜G&é3p⬃ٱҥÓ-‹.ØòØ›XÝPžèé–¦ " " "NÖ¼yó*tÏ=0ðä“HS¨RaÊ$" " ÙD௿þÂyç‡U«VaܸqèÛ·o6ÕD—ÌXf#‘ Q³AdqE€ƒÎÇÃË€‹/N.(" ‹*‚1c`áb+€âÅ“©{;‰…ÖD@D Z ˜¦Ø }iÑžðÀ@ÆÑZSÕKÂK€Þyç ÿú~f|@3ŽÏW¬Xgu–Í&a…kÔ¨‘bä†âöãGNDÂ{ob±4Gpd¢e_¯bFh¢‘|¹(óÌ„+ç2Q„N‰Ñÿ¸ø¥&X!0oÞ<% iÓ¦é6É´·˜0èÐ6H›nve¨$ÀwúvV{ùòå5j®¿þú¨¬§*%" " i`85šGiQòþ1z¸(W.Ð[¡­«Ú¼3œG;`,,ˆ›ïÛoatÀ'ŸGÂfü96@pä}*jˆ€Ä>îÝ>N;-öÛªŠ pbØóÏ?gŸ}ôHÍhƒvúlN=õTg C¤D ܵ‰ ZÁR}àÀ0ÉâœÀqÁÑG+k#ßçnÜꔈüùçŸØ¼y3ºPJ,"@GµkׯI òŽåÌ œy&@÷ë2ð*I“&9³äî»ï>ÜrË-^m†ê-" "ç$8Ší= LœÜy'ðè£Ií½é&àòËa!aasÀÃ=T®ìz6²9EÖ û´i“tžÖD@D@¢“=ÉS@zÅIõãw¹ÄFI<´[èÅhõêÕæ…q…“–.]ŠO?ýûöís<=aLQʘEl‘Qk²š@æÜeu-u½è&p\ptÇóU‘¿Hê‚#†S£1î£LD@D@b…g üþûïèß¿HMª_˜3'¤¬Ê$" " QK`Ö¬YNÝäÙ(jo‘*&" " ŽŠ-ŠJ•*…[Y¼Fàý÷]Ã\ô葼ö'Ÿ Üq0t(0m̰p!pãÀÍ7Õ«'?G{D@D@¢ÀC¹!Ó葎žë8áS&±Dà?þ°ß( Äi­[·Î ìk§9˜AóæÍ1dÈ {±ýèÁÇFËÈà(²|ã£ôã‚£mÿäB“4^ÂN&ÁQ||,ÔJˆ §Fãy™ˆ€ˆ€Ä o-Öˆ…gG™2eâ¥Éj§ˆ€ˆ@ X²d êÖ­ƒ-S“H€^ŒZ·Î:+mô€Ñ¹³›ÒΩ£" " ÑF`ûv`Ü8Ž=Ó§Klm÷Gõ £JQXäKùDF •æ³mˆ@vpGkÖ¬y*3•xôÑG«Úye^,³u+ʔŒi7Š!Õ8cH_‚isÒQo˜?¾¹víÚ©V|×.àé§aîLÂ…Sͦ" " "à ônDkÓ¦'ê«JŠ€ˆ€ˆ@JNÆA™w |þ¹mùr }û@Á‘w[¥š‹€ˆ€d„€9x‘‰@TX¶lžxâ |üñÇŽÐ=¸’¹rå2±\Yǃô¹çž‹ * bÅŠÎ’^¥kÖ¬©ÐhÁдuR-ên‰+Äj§ŸžfÅ7n܈­&LêÞ½{šùtPD@D@¼Dàðáà¿V­Z1’S³aÀ§LÞ]©ЧOj¹´_D@D@¼A`Ö¬YNE[3F‰LD@D@”kÖ¬q’o}åʕౠØï•A&Ž»U«V ­PåpGÿïÍcÇŽ•òµÃÖ¯±’¾m-E U §föÉ¿-ñõ-À]w¥?IIgQpÄ—wº‹“‰€ˆ€ˆ@¬˜7ožJ­YÓiøüðñÒbµCD@D Þ øÂ©µiÓ&ÞQ¨ý" " &°gϬ[·½{÷öp+â£êôüxðAw_çÎnÈò*UóhKD@D ö¼ü²ëäà₩MÝpšgž{íT‹¢‹Ã¢ýg1[™-ZäŒ(2Ú´i“SQ ‰.»ì2Ô©SÕ«WOL… Š®†¨6"…NHýñØcÕÊÏ)Çí†n@ží´ÓR:¬}" " "àI6E_LüíÑGÕ«'ž*Vô?¢uð6Y³f9 hݺµ·¢Ú‹€ˆ€Ä5Šgé±!1dYOÀð;fN­GÄU­ˆ€ˆ€Ä1‹/¾ÿxé%8QUâ…šžIÄ+¯¼‚Gyļ'nBÙ²e1vìX 0@Qš2ÉT§‰@z$8JާKÀÂZZ|K˜Ë¹”³ÒÃÝ+¦eÊ|´WD@DÀ{Ž9 jN®W}¶j0bP·.0dˆo¯–" " "¾ýö[”(QB“Ibãvª"VkÖÀ¾'’Šþí7àÜs ܉j\)üû¯›þù'ižB6é²Ë`IehMÂM`}`ÿ³Ízõê…»h•—½{ñãÑ£†ËáÿºLD@D@ü T®ìþ¦ôß§uHÀæÍ›±bÅ ,Z´Ï<ó ~ÿýw‹ÊS O=õ”…k½ùòåK¯8<êظÑ]¦$8Z¿~=þþûo…SÓ‡ED@D ¦,Y²Äé §vûí€M¢ÀóϹô++¦î¹#" ñN`Ïž=Nç]—.]ƒžne" "pœÀ…ìnœr löpëBÁ‚À”)ÀäÉIûÓZcH%Á½‡Þ?°aìû˜3'­³uLÒ'Àpj4 ŽÒgŽ6hžÜ÷dŠ ÍY¾½O‡£d•!" " "ovíÚå„J[¾|9~ýõW'íܹ3'Iýßÿý „ $î׊ˆ@äh(,rlã¦ä´Gôþ@kÔ¨QÜðPCE@D@bŸÀüùóFÒÑÏ8[sút€$Z&" " 1E`îܹ8|ø0Ú´iSíRcDÀË8pÏ>ô¬š°û×_û€Ì‰u€ÑkQñâ@¯^Àyç² h°ÐUÀ¾}îÒ&cÿ~ X1÷.}ë9s+Wµk–a_=x÷]Ø,e ZµÀcÚÌà(3Ô2~Å‚Í'ºsN=Õݾê* þŒ—§3D@D@b‹Å§}ûçŸôë[mSk"GàÊ+¯´Éîl‡Ò¥K£aƨU«–½CÔv'䌙ˆ@–à(ËPÇî…B5iÒ$v¨e" " qG`Þ¼yN›ýGe qÁq‡C ˆ³fÍrZÙºuë8hmü5ñØ1Àçu"«[OG#O?í†N(WhÖÌMM›Òû'Oê52Ç[شɸ.TȰøçæ`7çA1ì­/íÞ ôî \{-P¦ŒîÈ­S˜þÇnb÷ÈI'%]‹B†ä¥—Lzâ` CŽ¥f¿üâz ¢Ç ~ØînÝÜÐDû¤äe“Ÿ3\ÁÏ=÷–¼c‡»]´hÒ~þ¦µ(X¿`H4²›9æå Ö™°þ6l˜ÿVÊëðž2¥edl)SÞ¼ÁG´-™#ðÓO?9¡588% ?~Ïî†Nãw[Û¶Àm·:¹^ÊÂE•(" "à5üI/™¦SqÛóþû®g¥:u\áÑE%JR ˆmày]Ñ “ÏXÿ\‘ÑÖ­¾½î’ƒ(ümH!T… I‰uö·Â…aí®'§íÛnûEF¼G4–3h+²jÛ&–pvcÝ:7dÑÛo' QHÔ¾=pÖYVþb#ž}úé€E%€ÍÃúõ@¥J™U®œ”ªVuùQ´%¯à ×NS7¶lÙÒëMÉòúoÛæ~1T"…š?œô=tè,ì*LÌåŠS_~ÙýîÒ÷F–ß&]PD@úÈõÂóä“À¸qÉ…G ËõçŸÉ…×6QÏ<ã–{Ë-À¨QI×`_…2Á!ÓŠwCÔ†¦–uæ€wjV¿>ÀäoÔÌ1|C…QHEôüCOß¾þ¹1c\ïJÜKq”¿àˆü-2“ÃŽ,)GöA’‰€D- Ž¢öÖx b&8ZY¼&=âv`Öª•Tç­æ žq:3ª`M*Ak" " "}8èJkÒ¤IôUN5˜5k–Sj(nÐ#pyO¹};ÀŸ 眓º¸gútàÚkaž68ð s;œzªÛÜ–lwßíz=âÏ`ÑЃºe¼òŠ+*²>^¼þ:pýõ®· FC80¸Dm‹€ˆ@|`¨ÚYg_ jí¡C¡6ÿþ6a1èÐ!(£6E@D@DÀ½õìé†Sæ¤Ú_œ aÁNœ :·ÞêN¤ —UFÁ²hY2Øn/¡m&Ëü‘¸üÙf°|ÿý÷æ%×Üä·Š+:“qÙGÀ‰I§vZ¦F¾2ý—9sæê•*UÊ5Ýpà þ‡µ."…RÙ?s·š5kšûš´íÀ6/É>ýôSsxco2aÝé‹[æ-&8ú1ÿ5øßÿ`aÓÁÑO?ýä´¥aÆÞj“j+" " ið ŽkÊg”tHD@D –|óÍ7&nɇ¦M›ÆR³BnËo¿'¹¢´øîÜ Ü~;ðæ›€E¢·ý3}m^è©ÈúOPd6YÓùOe·Jùòþgºë µ–š=ù¤+Bzî9€¯á1Íœ X_°¹¥§X:µ3µ_D@â‡=•.]ÕªU‹ŸFµ”^(8n·f P¡0r¤;@œ”Q›" " "D€^ðønÁ0Ð>ÁQ¡BßièIÕ—rÙÈóÓO7ÝT€6£†ÀÞ½{ñõ×_[¨»ÏœåúõëfÁd_@#{nÑ¢…“š›+«²eËg ûv‚ý0É)2OHQpdÿÈæL5}ÛCÿß~öƒqfÒ$8Ê$¸ì:Rf )³ñø zpg(Ã©Ñø ’‰€ˆ€ˆ@¬ à¨`Á‚¨]»¶Ó$Nî0±2¸è¢Xi¥Ú!" " .¾óÓÃÑÙgŸéÉE^eIïð uvÏ=Àÿ¹­(ZèÚÕ}æŸ~r/CìlgX³ €nû;çûõs÷pæ/ÅAì ‡tðÌ3À5׸&ŠÚµÞ~ÛÇ5T†ˆ€x™Ÿi‹/F·nݼ܌®»/²K=æ¾Ç{Ì;á ¨˜$ÀÉÑùÀ¨QIMäs„ï8Lóç ð]'Î &Š¢µÕ«W;£iÓ¦Ùä”™0§"NíªV­ŠsÏ=×ÞM+ØÄ—òÎÒ·^¹re ÿà{$ŠZ¤ªˆ€D GÑR9Õ#Š üó3e³fù½èY'yüU Žr™Œ™±:e" " " ¯šü(¦å, gÏvã’ÇBÕð'ð¥=èØ o¡²ýÕí0ÿî;Àú^03Ö7‹>p=Ñ;ÅD;&À~¸ÔÌó;~ø!uOÍšÀ A€yžwBø³×:ÅN󿹡ÚèÝÈW·p•¯rD@DÀ«æÛ(è‘#GÌœ¹€‹cã„zï+^<Ž!¨é" " &P¤ˆû®CO®©…H3ç7`’EeË–™·©›@ïÅ4F*b(´KµcÇŽ°ˆGÑUaÕFDÀs$8òÜ-‹’ oÝêT䢛qуÉëDÁãvÒÝžLD@D@bgì´Ø(Müb’LŸî¶¬}ûXh¡Ú " " 6Ö‰STãÄè%ˆaÑr=?<òP €Ûø»ïv…<“'L›6%ô0¼@jÆ1î¬çfx6›ˆ*ð#0gÎgë¬8q¹°¿ëŨLàºëü@تÄF<´%" "8ŽH (˵ËÜR12ÑXsÝ{Ô\øöéÓ=zôÀ9çœãxð²êª:" & Á‘‡o^¶V}Ë÷ò÷<Øþ1ïG¿ÿþ;®¾úêàCÚÏ`85ZãÆÛpóÍ@Æ=ÈD@D@D –г]­Ÿn>óéF=^¬pa׫ѫ¯¦<;·R%à–[ÜDQ’LD@DÀæÎkÒöÒ\ÁŸ-ZPÖ­ƒy0H.8Šñæ«y" " "×ø.ÿæ›oâŽ;îÀVsÑÜÜNQtD¯ý2ˆGp´wïÞFæ‰ÆœgÌ,Æã³ùóç¿$cg)wLHCpDïF´†•‰€ˆ€ˆ@Œð Žü=1r¨¢‡ÆÈ V3D@D@ð½nóæÍ¸òÊ+öÇÂÆ¿ÿttÁ°¨7Þ(æ¼™Ë.òäI¿¥¹s§ŸG9D@D@²ŸC©1¤Z³fÍ+WìÏ¿-_8|5 <8ûù«" " Þ$°f °bÐ¥‹7ëoµ>d3bØ}»¹ìýÎ⃗,Y¯ÚL:‡ÈA7¸2ˆç kãÆÿd¦üråÊÈÌy:'Hp7QMÈ  X±b¨&ÿÁÁ¦¼" " %0uêT§æ;wöh R¯v«VÀòåîñ3΀¹–ÌŠØ(ð m‰€ˆ€D3Å‹cÏž=ˆ—pj§œpXÂØhþTªn" "ÝV¯.¾øå`åJXht×7žjGFkìA¿lÙ2{¯]î,¹¾jÕ* ~9sæ4Áñ`<ôÐC(Z´h<¡Q[E@²‰@ìOéÈ&°1YmDyô½½>úÛL™^½’ZüÓO?!!!õêÕKÚ©5ð0Έ]d~é[¶léáV¨ê" " ":O?ýÔÚ¶hÑ"ô“¢,§õÃâ?=±Š·Þ °éSYÄ8™ˆ€ˆ@Œ`85Z¬½Ïñ9÷ÑGÀÌ™ÀÓO;MLü#±Q" ­ˆ€ˆ€d€Ÿ-ãÆÁÂqû÷#FHl”|ÉzôèQP<=kÖ¬Äô×_%^‹ã±UªTAÇŽq†Í¨éÝ»·³LÌ ˆ0 Ž" 8f‹7ÁÑo¨‚/çæGç  zt½_³fM*T(f›¯†‰€ˆ€Äα´hܸ±ÓpR.Y‹} ÙÆ µVD@D ö lÛ¶ ôì×Ëf–DsèÓ›Ç Ø3:yš7xùe÷9ÍÙ¹þ䯹&öï¡Z(" "D`ŽÅÑä`œ—E´I­|B£„ @ ƒÁúcýsi]D@D@2F€“5ø®ôå—@ÕªÀøñî$Œ•¢Üá"0qâDL˜0ÁÂÏÁÎ;b齨aÆ楷êÖ­ë‹j×® „ë²*GD@2L@‚£ #Ó z8Ê_Ø0.¸ÏvíÚ…µk×âÒK/õíÒRD@D@ðÔSÀ!Î.ý˜!0mÚ4Ì<†h §f¯œ3xí5`÷îÔ±—)\}µ;37þÔó鈈€ˆ@l ‡£:uê H‘"žnhJB£Ûo˜FM&" " ™%ðúëÀÍ7Ä-ÀÀÀÈ‘0§™-M羋ß}÷Ýæ]jòX¼oöG·nÝmÚ´Á™gž‰Â… ŸHñ:WD@ÂN@‚£°#“ÄÆBµ’ Žn†C*le" " "+èåæMŸî¶ìÜsÝ¥þŠ€ˆ€ˆ@,`85z‚¸à‚ ¢®YV5\x!`^å-Œ7ŸÍ°ÙœÉS¥J@ûö0MQ×UHD@D ¬_¿›6m²g‡=<¡ÑC?ÿì>ó†uÃÝHhäÑ›ªj‹€ˆ@”رä1e P¶,ðÎ;°÷À(©\ U㈹çÝ·o_º‘aÚØë5æfŠž(.šb7¦D‰1DBMˆEêz‹Å»šm²àào²`®Ïz8b85šGYqt ¬"@G¥K—F¹råœKRpÄ—p›$+˜"pèÐ!̘1à ;sòÉ'gKÛÞzË ]Z¡l&§+,òUäì³a¡ÞÜY·mÛúöj)" " ) w#ZË–-SÎÅ{}B#_è4 l)4¢G£’%£¸âªšˆ€ˆ€'> ôè|õpÙeÀر@±bž¨º§*Éh À† pà 7Øsüv{Ž'3‚L÷îÝñõ×_;KŠŽòËU¯§îµ*+ñJà„GëÖ­ÃÖ­[O˜_¬ÄÐ>a*`㦰p¡6›TiŸà¨AƒI;µ&" " &pàÀ,]ºÔB¨Y 53{GÄòåîì7KU Ìš5 ìèìÔ©SŠÇý“žê×,•³k'Mr÷=úh à¨`Aàí·ókKD@D@R#ÀA>ÚYg•Z–¨ÜÏjßx#°xq’G# ¢òV©R" "àY7ÝäŠLƒgŸõl3¢¶â;->Ý]wÝ…^xyóæEÕªUñä“Oâ¹çžs„GwÜqG¢÷"zcìØ±#–,YbÏÿñôÓO;^‡£¶qª˜ˆ€øHWpT½zu·n“#GŽóÌåÛý&0Úéw>Þxã Lœ8ÑW¦ÖW®\™©ótRöظ(SŽèÈW ŽøÐ,Z´¨o—–" " "ài‹­‡—îl5jŠáÃÎ.Í—è×ÏÓÍRåE@D@D ES§NuöwîÜ9ÅãáÚÉh÷ßPP4~<ЧORÉôpôøãÀ &Ì ‡£òåË£bÅŠ™-"[Îã$Ï5käÑ([àë¢" "Lß‚÷ÞÎ;&n‰ƒgq?üðCG8ôçŸâlsÓûâ‹/¢Zµjàþ­sù‰'žÀ¸qã0xð`tèÐW\q6Ú ëˆ#@!’LD@¼D Wj•µ/¾ê&2º/!!ÁéÁÉgëÃó£oWY\ àÈÿ]}ïÞ½ pŒ.ÿd" " "+,X`M©„÷ßäx6ª[×õ¬púé±ÒBµCD@D@’|ú駨`±ÌêD0nè¿ÿ—_|öд)pÎ9I×çšMþ´ÎX7Ñ–ˆ€ˆ€„N`ÇŽö·={ö ý¤(ÉÙ¢là6©3J*¤jˆ€ˆ€Ärå€ï¿E;—3SÍ˶ÆP`DE³øt¯¼ò ®¹æšÄú\tÑEÎêäÉ“1lØ0›hó¸“òäɃ·læÍeŒm'Hé1’³fÍšÿgí0gz®Ð(’m¢¹† Fò*;ÛuËàÌ3“ §ó‚¥û™„Dk" " 1@àÝw¬‹­£º† q=.p T&" " ±F`õêÕ`ºîºë"Ö4‹Rj¬ÀÚµ®·@ºî×s5b¸U°ˆ€Ä5yóæá¨¹Ô‹æpjœËk‘U°gÌ£Aàí’Ø(‡¶D@D@ÂK€“@óæ'Z²Îô ²‘Õ~ø­Zµ2µ9Ó?!Ì9fÌ€…K L&ÜÉzÞMÛ›h  5Z @â.­ˆ€ˆ€ˆ@DÜpL8Ô¬)ÁQ(€üñG<ýôÓøè£ðßÿcáÍš5C=œph•+W¥å¸ àŽJ”(QØZ;ʿř \½zõËþû3³^¨P!<øàƒæ î¾ûnl<®VyÝü©ŸfÓ:ºuë–™buN6°ÉA6ëÕýqÂjЕàòåËCr˜ÕÖ¥E@D@D CÖ®ýÎÉߤI“ §Ì" " "à5t ÏÁY¾·‡ÃÊ•³MVEF]ºÈkC8˜ª Ð Ìž=ôJЦM›ÐO SηÞ®¹°.qŒäÍ ¨ä„–äØ(9í/?þ&O.¸92¼eÇRiGl¶Ìd5zôh|÷Û'Lá²OdTŽ/¹2dÁQ±bÅzØ{rÍ„FGm­ßš5kÆß–EÓ¦Mñì³Ï¢{÷î°ðlN™=ô¸¿lÙ²a¹† Ƀã]ðÕ‹‰[¶l™Ó9ݰaÃÄ}Z¯àlÎ`ÑóÍëwRõHÀÔ©S,á –Þu\D@D@"G€aOh w’•F‘Í·…9Çç7 ví¬¼º®%" " É ð™dNÿ,: Ìë_òãñ°‡!Ñ("*]º´3Í1é2eÊ8ë¯~ùå—ñÌ3Ï`Æ È—/ú÷ïo!OoÆgœxÔF8!ŽàÈÒ®ô/ÅGo…[lä+¿V­ZèÝ»7Þ~ûmg]Ñ1ÔÚ­·ÞêË¢e´˜>öÄ ¨åÂ… º¹¶P@IDATm È`цˆ€ˆ€Ç Pptê©§*·Ç/" "6ëÀ´iÓP§NT¬X1íÌ©µ9)އTk·ˆ€ˆ€d)O-vŸiuëÖÍ’ërn­KbìXØ5ݰ5š_›%èuT«B¦̲iÓ&\oñ½}B䔚Èɦ|'¦éá‡Æu×]‹ ”RVíH@®jÕªU°/Ò¶üBõ™mñ­GbIU(;3wìØá?eÊ 2 ‘¸œÊ 7-[€æÍJ•à(‡6D@D@Ç—ñ«¯`aÓ‚a³B}{µì#àóbÐ¥K—ˆW‚ϾŽo¾q'®°»[c•Ç® ˆ€ˆ€¤A€Þg;u‚yêzôH#cŒZ·n €¯¿þåË—w"îtäÃZ&" " ¦5*Tò¬ íˆlV¯^= \ Vd `â°£HÀe?Þ‚7Þpë»oß>,^¼Øœz=ò@kTEHF€§´¼yç8ËÆ;KýX$päȼ÷Þ{`øó d¸‰Û¶… 3fÀB²eøt " " a'Àpj… BÛ¶mÃVöܹÀСÀˆEr/»¹o» ˜0Ab£@:ÚÈýúìßü)¢®%²£ei_sÆ öœá„ ÿÆ”À ¶|ùrKl”69#ËN/ç_ÄÑ£G7øoGj½jÕªEoc/¥,ú ˜àh Jc⯠PÂ4b}ú‹²ø3-Z´ˆþú«†" " "¾ƒ<,]úrçΩÁ×t.¡Ã" " "5ØËpj7ÜpC¦êÄ0¤;»¢£L “D@D@D Œþùç|÷ÝwNh”¼yó†¥äéÓ]O¦ÑEÆÀwûÔS®§¿À½Ú¬'0|¸+€¥ÚGÍúëgå mæÌ™øâ‹/lÌ ¬ZµÊ¹<^0œZ8…ÇYÙ.]KD@¼F€‚£Gæñ(KGÕªU `ÅN™Ø}ÚˆòNEÍ¡c|‰§Ipä`ÐhÚ”aÔŽ¡D‰ÙhÔ¨òåËçñ©ú" " ":·ß~Û9x)•CéØþýÀœ9Àyçf¤‡#™ˆ€ˆ€DiÓ¦ÞûÂN­M7\Ú­·õê%o%ÊÊD@D@D » |û-pÿý°É“À›oôÂKvÌâ˜.\¸Ÿ}ö>ÿüs|ÿý÷8|ø°ÓÄJ•*¡ÿþhß¾½ó@ý¹±tçÕh'@ÁQ‘ Jþ´ææõ×_Þ½{'æ9ùä“×ÓZ)Z´(ræÌé¼2ßöíÛÓÊ®cÑBÀ<•ÂV;#%(¯ˆ€ˆ€dI“‹”>}€6m²§é]•B£Ë/¿ÜñdäË[¸pa4lØ7v½ÌW¨%x|UÐRD@D LrÙýÚ5j¬0•¨9ÛÕ¢ùrçÎý ­Þ¦k$+†áÔ¾ù曀ý Y€#z7LpÔüŸi¨i?^Þxøî»ïìE¼´ó2½•VÍD@D@D }ÑråúÖYr&LD@D@b•éٻ?zôèá4‘Îk¯¼X»8ï<`üx˜ç£Xm½Ú%" "k~±XhëÖ­3µæ²6öæ›Ö n½àÿþ  ÆŒItìžR”UD@D@²žÀîÝÀ!îsëÉ'³þú¡\ñõ×_wžÍ{Í}`ÿþýѶm[G`T³fMy/  òˆ€ˆ€ÐÃãa¾kB£a¾úÚú &BzÛbg~ïÛÎåˆ#ð§N·bÅŠ¡N:¾M-£˜À±-[±èЩ(µÎ=\ºt©<@DñýRÕD@D@B'@Á‘½ëâ—_¦;'Ip:;åðNúâ‹/Ю];0¼9_ÏÍs½Bíé§Áƒ9É[mRmE@D@â›@Fé{52ÇÖÇß Õzo0ÇAŽ=þ8pÊ)ÑU÷;wâºë®Ã;#òåË;á¼)6’‰€ˆ€Ä6iÇŽ£Lt´Õ¯y¹Ltôi•*UNõÛ–U΢¤ëvëÛ·/ræÌé¿KëÑHÀ¦úl;Xå¶À?þˆÃ‡£E‹ÑX[ÕID@D@B&@oë×çž Ìž=öȼ:È­CÈ•QD@DÀS&™ßýC‡%†S+Xøùg7Ýt“ÄFžº™ª¬ˆ€ˆ€C€‚#†g e0ó£€ÓOwC¨]q'Hl¤‘ˆ€ˆ€÷4hüú+ÌsPtÕ‘QêׯwïŽÅ‹‡ô|Ž®V¨6" " ¡pGýõ×nÝtR‰\S¤ZµjíÏÔæ¾}û0zôh 6,àü"EŠ8±;vj#: ˜Æ•[:u£àh}î›Ipä`Ðð…SkÒd'V®\‰Ö­[{¸5ªºˆ€ˆ€¤M€òçÏnݺ%f<é$×Ó_â­ˆ€ˆ€ˆ€GXß¶ÓOÙ¾}{äÉ“'ÍZ¿÷pÉ%°|ÀÇ ©fÎ÷e" " "àI… EÏ„‘ß~û ÷ÝwŸÓ¯ºmÛ6¼ð ˜Ç‡GmÛ¶ÅùçŸïˆŒäÍ(kî…®"" ÑH @pÄ ÚƒƒqÏ:T¯^ý›2ÜÖ“åa>å4wyLÜ ÙråÊ…»îº W^yeÈç(côð Ž~ÿ}®S©-ZDOåTȆS£µh±O>¹ݺYìP™ˆ€ˆ€Ä Õ«WcÁ‚r挙ËñîwÙe1ØP5ID@D n|ûí·ØµkWªáÔ–-Î8#np¨¡" " 1Lࡇ€¥Ká6ri±‘9¨Àûï¿I“&aáÂ…U:ŸèÕ«½¦C‡(P @ ÓVÓD@D@B%¢˜ÈN>f“&:ša¢£ûL­ÚÕF ¡šR>zEj×®¹ù„Zµj¥”Eû<@€‚#sje³aç8µ «àèW+r“¥]–þ³ÄH|L‡‚ÖsÚ6?¹¥-]eÉß쉎¶6ÀO—mO²´Ú2YØŒÞdÉv×)ci 7üŒZ«ï,±TÇR'Kþöm¬µä«'—l½KúÖ}‘ËÛ¾[,ùÛ,Ûàuø_W×RKþö‘m¬±ä_wÖÇW¶ÿ’,*Yº×’¿ñßZây ,G7|Íö­²DÖ¾¶pùY&¯ã[/këwXò·¯lc¶%ÖÓB!x ÿEÛÇûÎòýÛÍë'Þàk|mûøqäý¬o©‹%k+-±î¹/}ë¼ÿ¾úûÚRÎö µäoŸÛY±Ž-·ƒ×ßbÉW–?£”öñ³{%ãýþÑëÈÏUkKþ6Ñ6V[b;Y_b¸Îý¾k±-¼FKþÆ6Ì·ÄsêYjgÉß&دÁûÅò˜÷ÂéûŸay?úZò·olÃw ÞúÅó·7lƒŸ+Ö‘eùÚÁ¥¯-\úòÁ¬¦Û>þ2ïGGKþö¡mü~|ÛáŸØß6³ð:%-] Y¼øê+ o^ûh䘋#GŽ uëàÀx%£v‹€ˆ€Ä·ß~ÛiÒ•WžcÃÀ=÷ØÏ1þ“‰€ˆ€ˆ€G Ðs­k×®ÉZ`ÎOÇwÞ™ì°vˆ€ˆ€ˆ€§ÜbãHAwß™jûDF-Z´È¹H±bÅpÕUWáâ‹/Fûöí­Õ:Qe" " "àG Í®E{¸P¶Ú½jÕª5Ì3ÑͶÎaÝ*~ç§»Z®\9´lÙW_}µÅÆ®šn~eˆn•/Ì›7¼·*Tp+Lш Ø:¢‹­¶<ÉÒ–üíÛ¸ßÅ WZzÃ’¿ÝeSüw¤³N1ÃUAy>³íaÇ÷ñØùÇ×}‹·l%£×è;ùør†-<¾~µ-ƒGl×ÇLJ² ØÇ~(Y>t|O_[ Ž^³}¹F#Ëïñò|‹/måáã¼Æ…¾Ç—“mùiо´6y`1ÐLÛ7üøIר2X¨ó‰íËÈ5(. ¾Æ×¶Ÿ-¯,8úÂöñ:¡…QCƒ2ϱíÇï`Ëàv?~<”E3Ë$ÁQ(¤b2ÃÈühb¿3Ͼÿ~¦ÓÆV­ZÅd[Õ(ø&pàÀ<ÿüó¨T©.ºè,\¢ß?ñýPëE@D lݺÓ²ïù´ W[¿ÃÎXÄltïUD@D@âž#‡RDN[¹r%>üðC¼÷Þ{‰"£âæuàšk®AÏž=qÎ9ç wîÜἤʈ1¹BiϺuëèóâFæ­Y³f9óxÔÚRsÏ=·GžWü?¿ßÛœØß>^Ÿ×¡@R·8+ˆÏ¶mÛ€+®˜"EŠ nݺqËC ˆ]o¼ñ¶lÙ‚§Ÿ~9sòGLD@D@¼M`ìØ±  ö¶ÛØQhœGbŽ0z4P£Fà1m‰€ˆ€ˆ@¼°±]ÌŸ?S¦LqÒ¯¿þê  '£¾}û:"#û•È(^? j·ˆ€d‚‡¥3d«V­Úd'LdZ½zu[ê•-C½›ùï¿ýûM'{«rÆ §ÆOþ)n˜`©–¥Ò–RP„À”šQlq¢VÅ `Jͪ¥v ûË[^¦Ô,×(c…3¥f§¦v ûÓ»E/) _2p GÔ’’°ÅW…N)‰|ÇCY–´LL©BL'bü<§ô™ö•ÙÚ·rËJv.SjV5µØ_Îò2¥f•S;ýe-/SjƧƉ?Si}®N;Ñ èüx#Ï„†¥J0OG?¢mÛ¶„·€Ú+" q@€„žxâ ]ýúõ‹ƒ«‰" " ±N`ïÞ½xî¹çLLT#Åpj6nŠ©Sc‚Ú'" "ë–,MŽ<ñV²ßó¥—^ÂÇæieË–Åu×]‡nݺɓщ#V " "·è§Bæ!ûMñÇÓHÖš ŸqÓMæÔ¤Ð<çÂÝ7u.·U Œf[²MÔ¶”–0ÃËD@D@DÀŸ@v>Û|õàK7ë¡pj>"ZŠ€ˆ€œhx¶ùן.òW¯®iÛYøçº“•‰€ˆ€ˆ@ÆDÛ³müøñøÛfGÞrË-H0×µÿÏÞ}ÀMQœ¨‚tTxADT¬Xƒ"{IŒ-bKþö Ô(–¨X‚&j1¶XÁh¢DD&½I•^ï¿Ïâ®»×Þ{ß÷ænËoý¼Þ–ÙÙ™ï÷ÜÞÍÍè%Y@(@ÐbœS‡ñãE>X䦛œ=eÔŸÜyç¢h‡£ÝvÛMn¹åoe¾Àö];ïžtÒIŒhTvZÎ@øI Ì#!WxÑ£G‹ÞD[#J¹=+Uª$­ [uŽò³Î:K:wîl¼`Öûkø}k6±žÏÊ]Uî’–YC éˆFXùµÄx ¸ €@P‚Û-.G•!Ëœ\yDˆ“@Ðb›×þ¾ûI¥JÏÈœ9ûKU>ðÒ°Ž E ¨±M¿<}øá‡¥Q£FrñÅËĉ"§&ÒÏšJÞú•@R‚㜂¯Z%rÞybß¿]t‘³·lÚ¡è‚ .Q£FI§Näù矷FKÊÃpIe+©@".ÀGnàùóçË7Þ(&LH)¥Î³ºlÙ2yã7ì¿ãŽ;Nî¿ÿ~©S§¢sG¥\Ê·#±=!gü÷ ¹t»5 ÿ!Ö¡áÖŸÕ‰@\‚Û´Üú!Ã.»ì"‡¢Á@܂ۜŒ9Òš6´µy€\{­5ss¶©›“xDˆµ@ÐcÛ[o½%3gΔþýû[_¢Ö”3αú IëÖ±n6* ƒ@ÐcœVAcšÕOH¾ÿ^dÈ‘öís¨XR’7ß|ÓžN{åÊ•ÖÌ%WÛßêgŸ, €ä[€)Õò-š§ü~øáû:é:¥»ÄG}$gžy¦èy&—5ç­‘K7_*Ó›OùȺLr“7 ) Æ6ýuì˜1cäÐCµ;E Ê €jlóVúÞ{´6ï”zõ¶[?hña@T0ĶxÀ¾w;òÈkä—¿ÙuW«­œ}vj}؃ €€#†§e½í6‘#Äê0$rùåNés{ÔéáúYCþõéÓÇžrôwÞ±f.y„ÏýôS;v¬œ{î òë_7’íÛEÞ~[¤k×Ôú°@G 1NËj L$÷Ü#Ö#EÜ)}éú=á+¯¼">ø L:UtV”^xAš6mZúɤ@@ t8ªž©SõMÁôéÖB?-ÕªU“gŸ}V:wîìì²»wï.çœsŽusýk·s’N óꫯZ¿è1ó“ž7W¾)O[ÿ-:µæúýÜßþö7»ƒQË–-¥ÿþVç¤öHFÓ¬¡‘tºÑË.»LêÔ©“z2{@0(@‡#ƒ¸åÉúÿûŸï´=zø¶3mqľCÇ÷mçc£víÚÖpÅŸË-·Ü’ìÈ@ &AŽm;vìG}”Ø“ç"ÕDò%䨦u\±b…<÷œþ$¶¶<òH-k$¿|Õœ|@¢*ôضjÕ*yê©fÿ…rúé"Vß#@rzŒ»ûnk,¹ðB‘k®ù¹JÛ¶m“wß}WÎ9çÙ}÷ÝíEãÇ—³Ï>ÛÞ¯üùÏ–¶mÛþ|k €X€G/írÚ¡ÇY*Uª$G§ëÊì$ðæµ3fŒ :4æ T?ßaˆmo¿}ˆUíêÖHõó]}ò ˆÀàÁƒeêÔ©) Å(¤€~a¡Ói° O0Ķ5fÉ.»|eM‰]_vÝ5Ÿµ'¯ <óÌ3¢¯q,ñÐ÷4úÞ†Aqµj‰5³ˆÈ°aäŸÿ|Nºwï.ûí·Ÿ5µÚR¯^=¹çž{ìÏ´>þøc¹ä’K¤nݺ&˜ÈÓ €Æ7~0`8ÀYÿéO’åË—¸„ üÐá(?ŽyÉeÒ¤I¾|Ú´iãÛζQ­Z5Ùk¯½Ü$[·nÓ•@b ÛŠ©Ïµ@L„!¶=öØÒ·ïéу_¼šx' 50Ķ¡C¯¶>ëÜ_š6­5~êƒ `P 1î‰'î”CÝC~ó›ßØ? ¾è¢‹ä“O>‘éÓ§ËÍ7ßìûîÏ Y#€ P.îÐÊÅfæ$ïèFz…úõËökTííì]4¿òôvÖáÝÖ­[':Å’.:•Z“&M¼Y³Qµk×ÚÃû-\¸0¢5¤Z™6mÚ$+W®”8¶½Î…ííe¾cÇk ’m™¨Ø_F Ä¶7Ú¯oNlÓjèÜç:})Kôôßô?üË׸è·nö®^½:Öïmô½ÝzŸÝZ¾ÿþ{w=»GKJlÛ¼y³lٲŽoÓrë}›Þ¿épüúÇÛúÒZ3¼Çµíõ¹Ç÷ïámµü”\ïÛôþ-®m¯ŸWéŸ.3fÌ`Š‚ü<­|#®k–ÅúLR@¹}ûv_lkܸ1SÆä©ƒžMœ?› zÛ˜.Ÿ~.§ïmãÛôûçÇãÚÁDÿ-°äO (÷oz®Ó:ŸMV¯^]6lhWTïÛ÷Þ{o9ï¼ó¤wïÞî÷zqý7‘¿ÖFNúozÕªU±} F+§ú¾vÉ’%±|/«ßǬY³Æ†_°`ýùUqZ«B€G…PÎñÎ?<'yYoî“;é©–-[:Ùåü8vìXÑ9b/¸àûý26¹3SΙ‘0TúÆ'‘Hȇ~ªrSØŠ èMÍ7ß|Ëá‹õMŸÞð9‹þÐñsÒÒ9ÇôA‰mz3?þ|7¶ii5¶Ñá(}»Em¯þ¿å–[¤jUÞúF­mK«~h­¯óqºZoîÕ@o»2ÿHiO™œŽ%¶éÔúåŒsߦ…×{BípÄ}ípq÷Ýw‹ŽvÌ/íl¦2~ùË_Æ«â?ÕV?·p¾ˆÕئ_Ö±T\ (±M¿ŒÐ÷/ÞØV§NX~ISñV _úÙ”ŽDòøã‡¯ð”¸B×ô¾%®±M뮯}ÎÂûyG"?A‰q:b‘v–þ÷¿ÿmWL?£ª]»¶½îܯ¿õÖ[¢,ÑÐø¦S†>ùä“Ѫµ)U@_úõëË÷²zߪjYâ!À·.jçä7>eí䓜>¹çv®U½ë®»DÿX@¨¨@PbÛUW]%úÇ‚ €@E‚Ûô ™¸~)SÑ6ä|@¿@Pb[·nÝä»ï¾óŽ-@* ”÷î»ïV œŠ €@pøéc€Ú&ùOYG8Ò_üxgˆiï>Ö@(¤±­Ú\ @ ĶB(s @B Û ©Íµ@ )@Œ+¤6×Bˆ£ŽÔêÉÓº”uXhzÔ»$xä=Æ: €… ¶B™k €R€ØVHm®… Pb[!”¹ €@1ˆqÅPçš €q ÃQ€Z»qãÆ¾Ò¬]»Ö·]Ú†Îõë]4hàÝd@‚ Û NÎ@ Û “= €@Áˆm'ç‚ € ÆšË €ÄV€GjúÝvÛÍWš²v8Ú´i“ïü† ú¶Ù@@ ÐĶB‹s=@ÓÄ6ÓÂä Phb[¡Å¹ €@¡ˆq…’æ: €q ÃQ€Z¾¢o|–-[æ« Ž|l €A€ØVt.‰ `T€Øf”—Ì@Š @l+:—D(ˆ1® Ì\@ Æt8 Pã'¿ñY¼xq™J·hÑ"7}ÕªU¥nݺî6+ €C€ØV u®‰ `R€ØfR—¼@Š!@l+†:×D(„1®Ê\@ Ît8 Pë7iÒÄWš‰'ú¶³mètjÞJ:u’J•*e;…c € ¶'æ € ¶œË!€ ¶'æ €E Æ žË"€ÄF€Gjê6mÚˆ÷ÍÏôéÓeýúõ9•P;'mß¾ÝMÛ£Gw@Š%@l+–<×E0%@l3%K¾ €Å ¶Kžë"€˜ Æ™&@¸ Ðá(@πʕ+Ë©§žê–hÇŽ2fÌw;ÛÊÈ‘#}‡=öXß6 €C€ØV u®‰ `R€ØfR—¼@Š!@l+†:×D(„1®Ê\@ Ît8 XëŸ~úé¾ 2Ä·ncõêÕòꫯº‡öÞ{oiÙ²¥»Í  €Å ¶SŸk#€˜ ¶™P%O@b ÛŠ©Ïµ@L ãLê’7 €@Üèp°g@»vídß}÷uK5yòdy饗Üíä•uëÖÉ•W^)6lp}öÙî:+ €[€ØVìàú €ù ¶å[”ü@Š-@l+v p}@SÄ8S²ä‹ €€H•Š Ü~ûígXçw¬Hœ›*P»vmùðÃÝ£G–zõêIûöíE‡t–E‹Éå—_.“&MrvIëÖ­åÞ{ï•*U*Ô´n~¬ € b[>É@ HĶ µeAȇ±-Šä Db\[…2!€D@à¡J©D"‘xÁ:ÿŠäÁ¹éþïÿþOÞyçßÁ’’騱£Ô¨QC¾øâ ™7ožïxÕªUåù矗.]ºøö³ €@ˆmAhÊ€ Ob[>5É @ Ķ ´e@0!@Œ3¡Jž €1(¡ÃQ@Ÿëׯ—k¯½VF•S kÖ¬)ƒ–îݻ甞D €Z€ØVhq®‡ `Z€ØfZ˜ü@ -@l+´8×C(”1®PÒ\@ F%šw‹)ÕÌ=UªW¯.§žzª=…Ú”)SdëÖ­/ÖµkWyàäCɘ† €[€ØVìàú €ù ¶å[”ü@Š-@l+v p}@SÄ8S²ä‹ c¦T CãoذA†.“'O–Å‹‹n7mÚTš7o.Çwœ´oß> Õ Œ €¸Ä6—‚@ˆÛ"ÒT@À ¶¹¬ €DL€±¥: €Å`JµbÉs]@@@@@@@@B(PR9„…¦È € € € € € € € € P$: žË"€ € € € € € € € F:…±Õ(3 € € € € € € € €E ÃQ‘à¹, € € € € € € € €a ÃQ[2#€ € € € € € € € P$: žË"€ € € € € € € € F:…±Õ(3 € € € € € € € €E ÃQ‘à¹,^­[·ŠþmÛ¶Í»»Bë+W®”ùóçç5O§@›6m’¥K—†.o§üÅ|\¿~½Ì;W–,Y";vì0R”+VÈ´iÓäÇÌ{þ´}ÞIÉÈ „-¶iCðW±§£éG|«Xûp6T\ÀDlÓRqïVñ¶1•±-½¬É÷Lé¯È^0%@lóËÆáõØæosg+mïÔ•Gâ @|ó·rÔ_ãÂÛ´¥L¶É¼ýÏ2¶â,P5Ε§îAàƒ>«®ºÊ.Ê!‡"/¾øb¹Š5sæLyã7ä»ï¾³;›,_¾ÜΧråÊÒ¤I9ꨣäâ‹/–V­Z•+ÿÑ£GËsÏ='3f̰;i&•*U’ÆK÷îÝ嬳ΒÎ;.ïr('% 9r¤¼óÎ;òÉ'ŸÈºuëÜÜ«U«&{î¹§”””Èé§Ÿ.§všT©RÅ=žëÊš5käÉ'Ÿ” &Èœ9s|4h -[¶”ãŽ;N~ýë_KõêÕsÍÖMGÛ»¬ €@Ža‰mZ^ãrlÔ4ÉLÇ8â[tv!€@ÑòÛ´Ü»­K½0±-3‘É÷L™¯Ê0)@lÛ©õ×7b[æEQoûÌ5çÑ ¾ílß(¿Æ…=¶i ™l“yGûÕƒÚ•W RyOÔó¬Ð/XV$ÎE îÚÙHßéRÞGÿú׿äöÛo·{Á–æÙ«W/¹ûî»sîx¢£$Ýxãvg–ÒòÖN-÷߿ԩS§´¤öq“yçTÉt$†›nºIF•Ó•´cÐÕW_-¿øÅ/rJ¯‰Þ|óM¹ï¾ûì_E—vÒ^{í%·Ür‹{ì±¥%µ›l“yçT9!€€Q Ç6­¼É×!“ym¸2dn:ÆßÊÐ$E‚ä#¶iA¹w+Hs•ë"Ķôlqx_“¾æìE úÄ6sŸyåÙClKßĶô.ìE *Ä·hÇ·0Ç6ý7f2™Ì;*¯ÔÈ@ ŽŒ¸’)¹ ¬ZµÊyhË–-ö eíp¤ç 0ÀÙ(·+îLuØa‡ÉàÁƒ¥víÚYOûá‡äÜsÏ• dMç=¸÷Þ{Û£4éÈGÙ“yg»n¡Žétf}úô)“S¶GyDN>ùdg3ãã Aƒä™gžÉx<Óí Ô»wïL‡íý&ÛÇdÞY+ÅA(ˆ@Ðc›"˜|2™wA0‡‹˜ŽqÄ·$ PPŠÆ6-,÷nm²2_ŒØ–ž,ïkÒל½D_€Øfî3Ï <{ˆmé[‚Ø–Þ…½DE€øíøæØ¦ÿÆLÆ “yGåõz Ã‘1Z2F Í›7Ëo~óßÈAeípô׿þUzè!ß•:uê$'œp‚ì·ß~R«V-{ ´ñãÇÛSzyêô]<ð€w—o]Ëwæ™gÊôéÓÝý5jÔÃ?\Ž8âÑë¬^½Z4ïaÆÉÚµkÝtGy¤<ýôÓö”kîNϊɼ=—)êêïÿ{ùðÃ}eP—Ž;Êþûï/{챇̛7OÆŽkwÛ¾}»›VÛMùÜ¢E w_òÊçŸ.]t‘Ž4çêÒ¥‹Ý‘HGJÒÎdšÿ7ß|#ÿøÇ?dãÆnºš5kÊ믿žqz=“íc2o·‚¬ €@Ñôßxc›Â˜|2™wÑ5Í…MÆ8â[pv!€@QòÛ´Ü»µK½8±-•(.ïkRk΢/@l3÷™gž=ĶÔÖ ¶¥š°( ߢßÂÛôß™Éd2ï(½FPc%ÊY§T³þX@  VÇœÄo¼‘°:ó$Ú´iãû»à‚ rÎÉ60qÐA¹ç·k×.ñØc%¬Ž+ióøôÓOÝ»wwÓëµ'L˜6­î´:©øÒ¶oß>czk˜¾„5š/ý?ÿùÏ¢äñ¢<0iÒ$ŸEÛ¶mC‡ÍX‚ï¿ÿ>qÔQGùα¦V˘Þzó°¦Eó¥·F¬JìØ±#í9 .LXÌ|éÏ;ï¼´iu'mŸ‘† A ,±M‹Ïk\†FÌq·ÉG|˱H†ÈWlÓÂrïV&+÷EˆmééL¾gJEö"€€ibÛNá8¼¾ÛÒÿkŠCÛ§¯9{ˆ¶ñmgûFý5.̱M[Èdû˜Ì;Ú¯Ô.OÍ*W¨Ç'#€@©Ö?VyðÁE{ÞöìÙSºuë&7Ýt“XÁ±Ôs³%xôÑGeýúõníF¯Q¹rúÖ]»v•»ï¾ÛM¯+:µVºE‡û2dˆïÐ=÷Ü#;wöís6JJJD§?ñ.¯¼òŠwÓ]7™·{‘"¯¼öÚk¾ 8PÎ?ÿ|ß>ï†NC÷ÄOHÕªUÝÝ:2Q¦eÚ´ibu"rxàò»ßý.ãˆRM›6µGªV­š{Î×_m÷¨vwü´b²}Læ\¶@À¬@c›Š˜|2™·ÙÖ,[î&cñ­lmAjȯ€©Ø¦¥äÞ-¿m•ï܈m©¢qy_“Zsö -b[j{ÆåõØß¶O­9{ˆžñ-µMãßÂÛ´µL¶É¼SŸiìA ½@úž éÓ²Ê!`:cwÞÑéµfΜ)[·n-G.þS4OËYêÕ«'ýúõs63>Z£èH=Üã_}õ•,]ºÔÝvVÞzë-Y¶l™³)ǼôêÕËÝN·¢‘=ôP÷ÐäÉ“ÅùÈÝvVLæí\£ØÃ‡w‹°çž{ÊgœángZ±Fk$$÷ð‚ dݺuî¶wåÛo¿õnJŸ>}2v6r¶nÝÚ×>Û¶m“)S¦8‡ÝG“íc2o·¬ €@AÂÛÆäëɼ Ò¨9^ÄdŒ#¾¥¾oʱYH†y0Û´XÜ»¥¿/ÌC“å- b[jü‰Ëûš¼=‰È€ ÛâûúFl‹oÛôåˆb!Wâ[<_ãÂÛôÉoòþÊdÞyý‡Kf‘ ÃQ¤›—ÊEU@;£h¯UgÑNDÚé(—åðÃ÷%5j”o[7þ÷¿ÿùöy;)ù$mqľ=Þ7Γy;×(æã?þ(úç,G}tÆQ§œ4Σ·Ã‘î›3gŽsÈ÷øÝwßù¶[¶léÛδ‘œnåÊ•)IM¶É¼S*€éئ &_‡Læ”Æ4ãˆo?wXJ›S¨¸€éøf2þ˜Ì»â²ùÉØ&Çûöü<{Èø ÛÒ¿våAlKß>qx_”ç å@ ¬Ä·ô¯ŸAhÏ0Ç6õ3ƒLæ„¶§ áøyþžp”—R":âìþûïO[nEèH{,ÛN)É»è”\¹.{íµ—/éèѣ嬳ÎòíûüóÏÝíJ•*‰všÉeñŽp¤éõƒËßþö·¾SMæí»P‘6’GŒÒéær]’G„jܸqÚS4hàÛ¿xñbßv¦¹sçú%?ô Éö1™·¯bl €€q0Æ6E1ù:d2oã šãLÇ8â[êû¦›†d ±M‹Å½[úûÂ<4Y^² ¶¥oŸ8¼¯ÉˈL¸±-õýu^߈mĶ€¿4Q<*,@|‹_| slÓ'¼É÷&ó®ð?V2ˆŽbÓÔT´XÚaçôÓOO{ùÙ³g—«Ã‘žç]š7oîÝ̺®S|y—o¾ùÆ»)š÷Š+Ü};v”F¹ÛÙV:tè 5kÖ”7ÚÉfÍšåKn2o߅ЏQ·n]éß¿¿[‚Ã;Ì]϶¢SíMš4ÉM²ë®»Êî»ïîn{WöÝw_ï¦h§1V-Û²dÉ™8q¢›¤zõê’ÜáÈdû˜ÌÛ­+ P0°Å6…1ù:d2ï‚5j2ãˆoþ÷M94 I@ &b›Oc„wáÞÍ«Qüub›HïÛ‹ÿÌ£F€ØæÍ}[öç]®ŸMrßæ^eWå(˜ ¾ù_‡âßÂzߦÏ“íc2oÿvÉ3ºL©ݶ¥f¨S§Ž¯vëׯ÷mgÛÐŽ'ÞeÕªUÞM_§=ЦMßñlÕªUóubÑUêÐY¼jt_>óv®QìGí$tá…º­ZµÊ©HO<ñ„lÞ¼ÙMÛ«W/w=y¥{÷îâýè½÷Þ“þóŸÉÉÜíM›6ÉM7Ý$Þ牖±Fn]1Ù>&óöU‚ ­€Éئ(&_‡Læ¤5ãˆoþ÷MAj{Ê‚å0ßLÆ“y—_3ÿgÛDâxßžÿg9"/b[êkgžĶÔö‰Ëûš =) a ¾¥¾~¥ÃÛÔÏd 2™wPÚžr„C€Gáh'J‰€O ¹˼yó|dzmÌ™3ÇwxÆ ²eËwŸwt#ÝY¿~}÷X.+õêÕó%óæç]×DùÌÛwÑm,Z´Hn¿ývÑGÎR»vm¹æškœÍ”G}ã;`ÀßþÛn»M~÷»ßÉ_|!ëÖ­“D"!:ÕÚˆ#¤gÏž2nÜ87½¾9KžêNšl“y»cB-`2¶)ŒÉ×!“y‡¹QËãˆo©ÏÓ0·?eG&ã›Éøc2ï0?7ˆm¥·^¶ÏJ?› bÛÎVJŽ•ah»te$¶¥Sñï#¶ù=ØB ªÄ·-…ø”ئ¢Éžùü^ÔdÞQýwN½Ì0¥šWrEÀ¨@òŸ¯¾ú*çëM™2%%­Žr¤PtY³fïxYƒŸmè]4àµlÙÒÞe2oï5ƒº®#Ýzë­ö´sóçÏ—©S§ÊêÕ«}Å=à€dРAÒ°aCßþäN8A† bw<ÒŽEºü÷¿ÿµÿt]G›Ò_ª&/íÚµ“Áƒ§íìe²}Læ\G¶@ œ&c›Š˜|2™wXZ3_1Žøöóû¦°´=åDì&ã›Éøc2ïìbÁ9JlÛÙùüL 8­KI@ "ĶzÞÏ<+âYÈs‰m;µ‰m…|Öq-Â#@|ÛÙVa‹oAŽm*jòÞÚdÞáù—KIƒ ÀGAhÊ€@4h %%%îYŸ}ö™|úé§îv¦• &È›o¾™rXGÄq–ä•ü ']¦ÇäôÞ¶&óÎTž íß¶m›¼óÎ;òÊ+¯Ø#%w6ÚgŸ}äé§Ÿ}Ìe9úè£å¹çž“ds=7]g£=öØCž}öYiÞ¼yÚìM¶É¼ÓV† :“±M1L¾™Ì;, ™ÏG| K«SNÈEÀd|3Læ‹[ÒÛv¶BºûÍl퓜Þû™@¶ó8†á ¶íl«0¾¾Ûv¶]r¬*í__rú0¶}iuä8ˆßv> Âö䨦¢&ï­MæÍke ÃQY´H‹@€n¸á_iî¸ã™5k–oŸwCé9:ÕVòâ•(9@•õÉóÜfë̔ϼ“ëÆíÙ³gËñÇ/ZÆJ@IDAT=öX©Åß±c‡= [ïÞ½SÞ°d:yÉ’%¢éG•6 mŸ–… P@S±M«Àk\2Í¥rqÄ·Ÿ;§ad„TÀT|#¶÷ AlKïŸí3ôg°Â(@lñ~æÆ6LWfb[:b[zö"Eâ[ôâ[1c›þá¾=НÔ)Y€)Õ’EØF $'t’yä‘2zôh»Ä4ûôé#—_~¹têÔItøGVkÆŒòŸÿüG^~ùeÙ¾}»¶zõê²eË·¦ÞŽ?•*Ur÷늦-Ë’<²Ž÷ &ó.K‹•VÛãŠ+®uX¾|¹,[¶L´Ý.\èiýúõö”gÚ‹|À€vZ÷ gE;˜i›z—-ZH=ì’tJ¶yóæÙÐÞ{ï=Ù°aƒtéÒ¥ösäºë®“¾}ûzOO¹mïãa `*¶iÑMÆ “y€=/—ÈWŒ#¾ÕËK{ KÀT|3Læ¬ÖÉ\bÛN›|ÞfÖæ„M€Ø&iGz;Ûv¶±-èÏTʇ@ñˆoá‹oAŽmúL6yom2ïâý+äÊa ÃQ[2#ð“€vH¹à‚ D;‘è¢s•<ø§£é:tè`O©5|øp;þBC²³4nÜØYµ×®]ëÛ.mCËà]tJg1™·s ?êÍìÿøG_uÄ©qãÆÙS©;Ö=6lØ0éÖ­›œ|òÉî>gåùçŸ÷u6ªR¥Š\{íµrñÅ§í ¦Ç ä›NOGQÒÑ”Z·níd+&ÛÇdÞnXAH˜ˆm còuÈdÞaiÔ|Ä8âÛÎá»ÃÒæ”Ê&`"¾™Œ?&ó.›\ñRÛvÚçó3âµ&WFĶŸ?ó4ák"ObÛNUb›‰gy"â[¸â[c›þ«0yom2ïèü‹¦&…`JµB(s  4oÞ\tôšÓO?=§+h–'Ÿ|R/^ì¦÷vÒ»í¶›{LWÊz¶iÓ&ßù:ÒŽ³˜ÌÛ¹Fصòá‡.C† ‘®]»úНm•¼èÈTÏ<óŒow¿~ýì‘“ôUºEÝÿüç?Û#b9Çu^Û;ï¼ÓÙ´M¶É¼}•`B/`"¶)ŠÉ×!“y‡¹AËãˆo;[Úû¾)ÌmOÙ@ UÀD|3L檞=ĶÒÛ*Ûg¥ŸM “±íçÏ<ÃÔnÉe%¶%‹¤nÛRM؃@”ˆoáoA‰múïÄ併ɼ£üoœºå_€Gù7%G * #ÝÿývG¢ž={ʾûî+U«î¼L÷Ûo?9묳䡇9@{¼Î™3Ç-ãî»ïî®ëJE”Næ]¼_œ™ÌÛ{Í0®ë(S<òˆT®üóËò´iÓdÉ’%¾ê|üñÇöTlÎN:/yj4ç˜÷Qß`i§#ïhVŸþ¹oj=“íc2oo=YGhä;¶©ŠÉ×!“yG¡Es‰qÄ·-í}ß…¶§ àÈw|3LæíW ç±-s»eûL óYA° ÛÂÚr©å&¶¥š8{ˆmŽÄG€ø¶.vlSE“÷Ö&óŽÆ3€ZJ€)Õ %Íu0,pÜqljþé²uëVY´h‘ì¹çž)SlÍŸ?_V­Zå–æÐCu×u%9@yGCò%̰¡×uíðT·n]gÓhÞîEB¼¢£Mí½÷Þ2{öl·Ú^{챇»=kÖ,w]Wºté":¥Z.‹¶­N¡6uêT;ùŽ;äûï¿—¶mÛÚÛ´}.ФAB ä+¶i™y+dË¥^«´G|»Ã¸÷}Sª"{@ *ùŠoĶâ>#ˆméý³}&þ ö"€@ˆmQhÅS}º¬_¿Þ—&Ó†vNÚ¾}»{¸G˜ÌÛw¡"nèhDNÛhgžuëÖ•©4És‚ï³Ï>¾ó“§ZINïKœf#ù‹LïèI&ÛÇdÞiªÉ.¡€Éئ&_‡L椦4ãˆo"ÉÔö”Ê/`2¾™Œ?&ó.¿fþÏ$¶¥ÆŸ¸´}þŸMäˆ@|ˆm©¯Aj}b[jûÛ‚ô ¥,W€ø–úú”Ö klS?“1ÈdÞAi{Ê:…£(%>5kÖ¸£èèH:øÃ|Ç3mhç—>øÀ=Ü­[7{úw‡µR¹re9õÔSÝ]:í–·“’{ ÍÊÈ‘#}{=öX߶ɼ}*âFr!gú²\‹4eÊ7é.»ìbO±æî°VöÛo?ï¦h‡°²,ÞôÚû{ºÉö1™·[V@ Ô&c›Â˜|2™wÕdŒ#¾‰$¿o RÛS(¿€Éøf2þ˜Ì»üšù?“Ø–âÒöù6‘#ñ ¶¥¾v©õ‰m©íCl Ò3”² \â[êëgPZ+¬±MýLÆ “y¥í)G8èpŽv¢”øêׯï…hüøñ¢ƒJ[† &ÞqÎ;ï¼´§œ~úé¾ýC† ñm§ÛЩ¿^}õU÷Î÷ݲeKwÛY1™·sb>¶nÝÚwùýë_¾ílÚakÙ²ení T¥Jw[W’¿ýè£dùòå¾4™6–.]*3fÌpkÕ¨QÃÝÖ“íc2o_%Ø@P ˜ŽmŠbòuÈdÞAiP“1Žø–þ}SPÚžr €@ùLÇ7“ñÇdÞåÍï™Ä¶ôñ'mŸßg¹!/b[ú×Π< ˆméۇؔg(å@ ¸Ä·ô¯ŸAh±0Ç6õ3ƒLæ„¶§ á ÃQ8Ú‰R""Ю];wŸö¼þßÿþçn§[™6mš <Ø=tðÁË‘Gén{W4oïÈ7“'O–—^zɛķ®#']y啲aÃwÿÙgŸí®{WLæí½N±Öûôé#:U³¼ýöÛòá‡:›—,Y"7Þx£ïx¯^½|ۺѢE Ñ7¾Î²víZ8p èpŸÙêîü£x§ß;å”SRN1Ù>&óN©;@ ”ú:á,ùŽmš¯É×!“y;&Å~4ãˆoéß7»Í¹>äGÀd|3LæÙŠçBlKâÐööñ ¶·ý‰mĶà>;)Á ¾³ÂÛTÔäý•ɼƒùl TAðQÆÞ~ûígX§t,ãi$GŸV­Z%C‡u=š5k&gœ¡ÿ¬J_jÖ¬)Çwþç?ÿ‘ƒ:HJJJÜ}ÎÊûï¿/}ûöõnôÀHÓ¦M$)µk×öu”=z´Ô«WOÚ·oo蜰hÑ"¹üòËeÒ¤IÎ.ÑÞÆ÷Þ{oÊèûL:wîìëŒä$ÐiÝn¸áÑ‘°œ¥U«V¢Ïäòèq“íc2o§n<"€@q‚ÛTÆäëɼ‹Ûª;¯n2Æß2¿o BÛSâ.P‘ئvÜ»Uè£'£O?b[æøõ÷5FŸXdŽ@ˆm?ÿ80ŸŸy¡é‰mĶ <)Å ¾E3¾…=¶é¿“÷W&ó.Ö¿e®*‡üßd—±ìÖˆ/X§\XÆÓHŽ? Ìž=[¼£ÌrÈ!òâ‹/æìsíµ×ÚYœªW¯.Gq„h>:§©v4™0aBÊèGzžŽHTÚòÿ÷òÎ;ïø’i‡¦Ž;ÚSq}ñÅ2oÞ<ßñªU«ÊóÏ?/]ºtñíOÞ0™wòµ ½­ÓÖx≢S˜yµÑvÑÇÕªU“9sæÈ¬Y³D§£ó.:B’ŽŒ”®ó˜“î/ù‹<ùä“Φý¨yjG"ÊN;“éôlz ¡Ê»è—º/¿ü²têÔɻ۷n²}Læí« P Ç6E1ù:d2ï¢4hÒEMÇ8â[8› ŠÆ6­÷nhÊ´… ¶¥e±wFý}Mæšsè ÛÌ}æ„g±-s+Û2Ûp(ߢßÂÛôß—Éd2ï(¼6P£%t82êKæd¨è›Ÿ•+WÊE]$:ÂM®Ë¥—^jv“Kúõë×ÛŒ5*—äö/wuÚ¶îÝ»—šÞdÞ¥^¼ æÏŸoO‘¦¾Ê²´mÛVî¸ã{´ªlçéÈIýû÷—×_½ÔéÔ¼ù4jÔH  't’wwʺÉö1™wJEØzlS“¯C&ó.xcf¸ ÉG|Ë€În(ª@Ec›ž{·¢6a©'¶¥'ŠÃûšô5g/Ñ ¶™ûÌ3(Ïb[ú– ¶¥wa/Q ¾E;¾…9¶é¿1“1ÈdÞQy} ÆJ*4®µ5ÝSªk2Žƒ@>†w<ûì³íŽ>_~ù¥èô\™õæ¶Ûn“ßüæ7™’¤ìדN=õT{ µ)S¦ÈÖ­[SÒ8;ºvíjOÑ¥£+岘Ì;—ë›N£ÓÏé¼²ZO J¿@Ͷԭ[×î6pàÀ¬SÝ9yè(E=zôN8A/^ldäËô¨åÑQ‘8à€LIÜý&ÛÇdÞnXA¢ =¶)ŒÉ×!“y­Q“.l2Æß’°ÙD@T4¶i%tZ5îÝÑœi AlKËbô=Sú+² %@l3÷™g¡Ú°´ëÛÒ Åáž=}ÍÙ‹@<ˆoÑŽoaŽmú/Ðd 2™w<^=¨e˜R­xœŠ@ –,Y"ãÇ·;žè4Z‹-’&MšÈÞ{ï-ûï¿¿=ÅW•*åïc¸aÃ>|¸==—vpÑm¶«yóærÜqÇIûöíËía2ïr*'._¾\¦OŸ.Ú»^§Pûþûïí/Z´haO¦ÚFÚ騼˷ß~+ß|ó÷ܹsíéÜš5kfO±¦Ó¬é4n­[·.Wö&ÛÇdÞåª,'!€@ LÇ6­¬É×!“y¥¡LÇ8â[PZšr €@>LÇ7“ñÇdÞù4®H^Ķôzqhûô5g/ä"@lËE©xiˆméí‰mé]Ø‹? ß~¶ÚZ˜c›ZšŒA&óÚó€òB€)ÕÑ @@@@@@@@p”TG9)% € € € € € € € €A€GAhÊ€ € € € € € € € €@Hèp’†¢˜ € € € € € € € €A€GAhÊ€ € € € € € € € €@Hèp’†¢˜ € € € € € € € €A€GAhÊ€ € € € € € € € €@Hèp’†¢˜ € € € € € € € €A€GAhÊ€ € € € € € € € €@Hèp’†¢˜ € € € € € € € €A€GAhÊ€ € € € € € € € €@Hèp’†¢˜ € € € € € € € €A€GAhÊ€ € € € € € € € €@Hèp’†¢˜ € € € € € € € €A€GAhÊ€ € € € € € € € €@Hèp’†¢˜ € € € € € € € €A€GAhÊ€ € € € € € € € €@Hèp’†¢˜ € € € € € € € €A€GAhÊ€ € € € € € € € €@Hèp’†¢˜ € € € € € € € €A€GAhÊ€ € € € € € € € €@Hèp’†¢˜ € € € € € € € €A€GAhÊ€ € € € € € € € €@Hèp’†¢˜ € € € € € € € €A€GAhÊ€ € € € € € € € €@Hèp’†¢˜ € € € € € € € €A€GAhÊ€ € € € € € € € €@Hèp’†¢˜ € € € € € € € €A€GAhÊ€@V®\)•*Urÿzè¡<äJ €C€8Œv  €Á >мôÒKÒ¬Y3÷oÁ‚Áj$Jƒ à ·\ V@b"@ì‹ICSMb,P5Æu§ê € € € €!X¿~½,Z´È­ÁöíÛÝuV@@@@Ì 0‘9[rF@@@@@2ôïß_Z´háþ-\¸° g“@ð ûÂ×f”v 0ÂÏ@@@@@„ÀªU«dÞ¼ynY½Î¥`@ ¢ľˆ6,ÕB ŒpƒF¦Š € € € € € € € €äK€Gù’$@@@@@@@@b @‡£42UD@@@@@@@@ _Uó•ù €€yåË—‹þ5iÒD6l˜× nݺUæÎ+M›6•]wÝ5¯y¯]»VæÏŸ/K—.•zõêI‹-¤Q£Fy½†f¶hÑ"™5k–Ô­[WöÙg©S§NÖk,^¼Ø.W¥J•äÀ”êÕ«gMŸëÁ ”#×ò’Š€‰8·}ûv™7ožÌœ9S6nÜ(íÛ·—–-[JåÊÁîw¤X¤²å¹J9@B ˜ˆZþ°ÅÈD"!3fÌ HÇŽe·Ýv+d3p-@LÅ­/Ÿ’¬"ñ#(÷BA)G .;@l0Ç>Ó÷…Ä0þ‘ €@VëÍú Ö øïÿ›8÷ÜsµjÕJXÿ ݿڵk'~õ«_%>ÿüsûê+V¬piº|°ÔRM™2%ñ‡?ü!qøá‡'jÔ¨ážou:JÜpà ëƒ\;«3R¢oß¾îŸsÍl°Þ¤$þö·¿%Ž9æ˜D•*Uܼ:´k×.qÏ=÷$–,Y’-÷ØÇœ8øàƒÝ¿O>ùÄ>¶~ýúÄC=”Ð2;y;GqDbäÈ‘nº¢åzüñÇV#_ú]vÙ%ѵk×ĵ×^›X³fïïFPÊá-ë €@˜Lʝ¾ú*qÒI'%¬Î¤¾×{VÇZ;žÜ|ó͉͛7§å{ùå—ݘ£ñçšk®I›.ÓγÎ:ËwþÔ©SݤAŠ%A*‹ Ä  €@ÂT|TÚŠÄH“ññ›o¾ñÅÎñãÇÛÏ„mÛ¶%î¿ÿþ„õÃ7¦?óÌ3î³dÈ!î~ósæÌq¥[Ñ{ȳÏ>Ûw­K/½4±eË–tÉÙ‡ ƒ@>âÖc=æ¾67nÜØ÷ÚÞ¡C÷ØÝwßí+QyãGPî…‚R* €¥ „1öy+U‘ûB'b˜#Á#±hf}SþÅ¢£ÃQ¬Ÿ?TÞ¤€~zÉ%—øn®­­)ÛÖè< ½Ñ.k‡£—^z)¥SrþÚ ç­·ÞJX#Bø®;lذ¬UŸ4iRJ‡žä¼íúõëÛ“²fhü׿þå+ƒ–köìÙ‰ýöÛÏ·ßÉ×û¨uÕE;7yä‘¥¦×ŽJëÖ­³ÏIþ_PÊ‘\.¶@° ˜ŠsÚIVã§5‚Q©¯÷+ºté’øþûïSø¬Q‘cx¢”2ņ䓭ÑöÜóô|kD¥ÄŽ;ÜdAŠ%A*‹ Ä  cSñQIó#MÆGí`äÄ]}üðÃÖh¹iïáÊÛáHc¹þ(Æ{Î;Û÷Ó1~ÚQu@ ÜùŒ[7Þx£ïõÙûZí]¿âŠ+|å-oüʽPPÊáCe@ £@˜cŸV*÷…1Ì‘àX 4 ö\Ö qÐ! ­_\Êßÿþ÷R«o½„É­·Þ*÷Ýw_©i5æmâ#矾XoŒ²žcú gžy¦¼ñÆYÓyŽ7NŽ:ê(ùú믽»íõtSµ­^½Z¬_“ÊÕW_’>Û†ñØckĈlÉìcÖòå—_Êi§&£G.5ý˜1c¤W¯^¢õ/m J9J+'Ç@ ˜Œs·Ür‹?­>n•uÊ•N:I›6mR¦Ïüâ‹/ä ƒ’O?ýÔM¯+Í›7—£>ÚÝ·aÃ>|¸»måµ×^ó¾ð E§ïÌ´)–©,™¼ØDUÀd|T³|ÄÈBÆGkd#éÝ»wN÷p¹<'¬ÎFrÊ)§ˆ5 ®›üÐCë—ÉyŸ²Ü½+ €@„LÇ­òÒ•7~å^((å(¯?ç!€QˆBìËÇ}a¦6&†e’a?d°::0ÂQ¬;¬QyS HùEω'ž˜xî¹çß~ûmbÙ²e‰÷Þ{/ѯ_?ßè Ö?V÷¼LSªétbÞtÕªU³§fÓáuèùéÓ§'†j1ï¤Kž-ÓGVç¡DòÇ:Ñ믿ž˜?¾Í¥×Ðaø­/_}åÐk=úè£I“{JëHNù¬ÎS‰÷ßßvÑò«“Žœä×ǪU«ºÛ 6L<ðÀ‰±cÇÚ£Y_6'®»îº”iw´œÉKPÊ‘\.¶@0 ˜Šs#FŒðÅÅC9$au„õÑX $t$¾ã?Þ '4mò¢£'xc‰N¿’Ë¢£&yÏûî»ï|§)–©,>$6@ ˜ŠJ™Ïi*>&PqòÉ'ûâiIII¢gÏž Ùâ£>rŸ!¹L©öã?&t$[o|>ì°Ã²N§í^€@´ùŽ[ .LLœ8ÑþÓ{/ïk¶~êÓÑö¼KyãGPî…‚R¯)ë €éÂûòy_¨BİôÏö"3¦T‹YƒSÝh§zõê¹7Õ:Ëm·Ý曊Å[ Z̛޹O×áH?dmÒ¤‰›·vÚùàƒ¼ÙùÖõƒä5j¸é¼3u8ºþúë}iuJkD_žÞþýûûÒ7kÖ,aý É›Ä]O~ã¢e©^½ºý†ÆMäYÑ!ÒM§søá‡'–.]êIùóêC=ä+Oº/–ƒRŽŸKÍ .“qÎÛ™Ucãòå˳âœwÞy¾×}í|ë]´¬Þ8X«V­¬qMÏÕé>x©é:2)–©,^{Ö@¸ ˜Œj™Ïi*>&aìÄÓ-ZØ?Éôœ(­Ã‘–·[·n¾ø¬Smëý1  €@ùLÇ-ý‘¥ôqîܹ ZÞø”{¡ ”##0@l(ľ|Þ* 1Œ ` 0¥šuÂ@ ¬ˆdÍš5n™þð‡?ÈwÜ‘q*úë±ÇsÓg[4hX£#¹I~øa9á„ÜíäêlàÀÉ»Ón[_°Ê#<âëܹ³XüJÍš5Ý}É+wÞy§X# ¹»­_2‰ÕÊÝ.m媫®²‡ØO—N§ÇÑáñ½‹ÕAIþö·¿‰ÕéÊ»Û]ÿýï/ÖHHîöäÉ“Ýõl+A)G¶2r Š€É87a·š|°4jÔÈÝN·rå•WúvõÕW¾m«Ó’œzê©î>ŠÔú%»n%ÝtjéÒ%ï R, RY’ØF¢*`2>ªY>cd!ã£5b®==¶5Q¹šÞúRÀ¾çõNªSsk<¯S§N¹òä$@Óq«¢ÆåA¹ J9*ÚœDI ±/Ÿ÷…™Ú––I†ýDW rt«FÍŸ€5üå/q n@$7Üpƒ»iÅšRLÚ´i“é°½_;1Y#ø¸iöÝw_ÑE¥-úeìî»ï^Z2¹ùæ›eË–-v:kT&»³‘5[NçiG gyöÙgÕ¬ú%òŸþô§¬iÚ¶më;þ«_ýJÚµkçÛçݰ¦—“½÷ÞÛÝõÃ?¸ë™V‚RŽLåc? $“qnÇŽ2cÆ ·ºÖ¤bõ®w·Ó­X£ˆ5" Ü{ï½öߘ’Ìúåo_r‡"ßAkãÕW_uwi<çœsÜíL+AŠ%A*K&/ö#€Q0ÕÊDŒ,D|Ô²ëZ4h «e^V­Z%Öªòù矻çên¬iyĵÐÝÇ  €@ÙLÇ­²•&}êòÄ Ü ¥éeÙ‹ÄS ±ÏÄ}aò³–,Â6ñ ÃQ<Ú™Z†DÀšÊE¼\.»ì²Œ£ñx«¤_hêHHÙ–©S§ŠŽÌà,:2R.‚´ÓÓï~÷;紌ޑ‰Zµj%:²D.KãÆåè£v“ZSĉ¾y+m±¦F“úõëgMÖ°aCßñ:ø¶ÓmÔ­[×ݽråJw=ÓJPÊ‘©|ìG‚$`2ÎYÓhŠ÷u~É’%rÅWÈöíÛ³hü¼é¦›ì¿=z¤¤=å”SÄOÞ}÷]Ù´iSJ:Ýa óŸò¥f.vƒK‚T–´ÈìD"(`2>*—‰Yˆø¨÷”ÙFäÍöTX±b…h\÷þ‚WËüöÛog…7[žCØ)`:nUÔ¹¼ñ#(÷BA)GEÛó@( D!ö™¸/LncbX²ÛÄC€Gñhgj™3gúJZ–aãÛ·oï;7ycÖ¬Y¾]ÇsŒo;ÛÆþûïŸí°ÝIJ‡ªwN­,‹÷ b%iΜ9¥ž¾×^{•šFG,ò.Úª,‹öø.m J9J+'Ç@ ˜ŒsZ?"Å»<óÌ3¢¯ÓÚ¡(×i2½ç뺎ÂwöÙg»»×®]›qúÏäÑ.¸à÷¼l+AŠ%A*K63Ž!€Q0Õ*ß1²ñ±S§NåjfýÏqÇgOÅæd å}þùç¥FÎ.@Ê)Pˆ¸U΢٧•7~å^((å¨Hp. 5¨Ä¾|ß&·31,Y„mâ!P5Õ¤–„C ¹SP‹-r.xi<9oR-×¥´rLŸ>Ý—Õ”)S䢋.òí˶1mÚ4ßá HiœJ+“/ß6š6mšnw…ö¥ª'#€HŽEey --Îin»í6=z´o”¡E‹É}÷Ýgÿé¨zGu”=½ŠŽrëõuÚ˜§žzÊUÒŽE:R`òâNM§jéÓ§Or’´Û¹–Ã{²‰˜¦ù©,Þú²ŽDYÀt|T;1Òt|,Ë=«÷ùÑ»woY¸p¡w—=ýwÿþý}ñÜ—€ @œ ·r.Lš„åA¹ J9Òв ˆ­@TbŸ‰ûBï“‚æÕ`øÐá(>mMMC ü¦%—/Wjé:EZ¦©c’ónРsj©¥•#]‡#ítTÞeãÆ¥žZž/ZuÈÈ|/A)G¾ëE~ €€ äXTZ|ñ–¡´8§iëÕ«'~ø¡œuÖYö£÷|]×^ýuûO·µsë9çœcOºÛn»é®´‹ܲeKùþûïíã:‹ŽÈ§£%8˼yódüøñΦè—Úé(—%H±$HeÉÅŽ4 €@LÇG52#MÇǪUË÷‘Urg#ç92dÈ9ï¼ó|Sz;ÇxDÈ] q+÷Ò¤¦,oüʽPPÊ‘*Ë@ ¾Q‰}&î ½Ï b˜Wƒuâ#ÿoßãcGMÈ»€Žìã]6lèÝ̺®²ÝP'èZ¿~ý¬ùyfËWÓé—¬ù\6mÚTjvZß ,A)G,( Pš€É8ç\[oœ?øà{¤£_ÿú×’­#Ñ·ß~+ °§]{öÙg,R+Uª$ÞéÑÖ¬Y“Ò¡)y:5õ!×%H±$HeÉÕt €@Ø Õ(ß1Òt|¬h»j,¾õÖ[Ýl‰„\~ùå’Ëý¦{+ €)…Š[)6¼#(÷BA)‡an²GB%¥Ø—ïûBoCü¬#òý\,>>Ô‚ hïßo¾ùƽ¦NÓªU+w;ÛŠŽÚ°yóæŒI’GYXµj•ì¾ûîÓ{,]ºÔ»™²^RRâÛ÷ÛßþV~ùË_úö•e£C‡eINZ@˜ŒsÉÝ»wýÛ±c‡=òÐG}$#GŽ”1cÆHòHzº­_@6iÒDzö왜•½­ŽèÓFÞ´ÞéÔ4Ÿã?ÞMË  €Ù µùŒ‘A×^{­<ôÐCöˆ„¯¼òŠÌ˜1Ãn}¼ýöÛåÏþs¶&á €@BÇ­,Eá €ˆbìËç}aA‹ €@`á(°MCÁâ(<Çøüùósf(-mòˆFe•¨´¼Û´iã+§N1s '”ûo=öðåÇ €@4LƹLB:æa‡fp Ó­i‡ÛÿûßÒ·o_©S§Ž{šNIÚ¯_?w;y¥]»vÒ¥Kw÷[o½%[·nµ·5Nz§S;÷Üs³Ž:èf  €–@1â£Âç#F1>ÞyçòðËŽÀ´Ë.»ÈO<á{ž=øàƒòå—_úö± »@±âVî%$% €ùˆrìËÇ}a~µÉ Â&@‡£°µå´@rÇçW˜¹TzΜ9Y“µhÑÂw¼´NDÞÄúÅl¶%¹ÜÓ§OÏ–œc €1HŽùŒs¹’ê'žx¢<ùä“2iÒ$ñÆÇ¹s犎˜iñN“¦—tÔ$]^ýuÑiZœÅ›ÎÙÇ# €™‚µlå‘Þ¸„øø«_ýÊG­£žþùî¾mÛ¶É¥—^*úÈ‚ Pv Ä­²—œ3@(Ÿ@œb_yï Ë'ËY :E¡©Cd’{I?ÿüó9×­´´]»võåõÎ;ïø¶3mèT4:ŠC¶E§fÓy_å‹/¾H™®Æ9–îQ‡áßÿýí¿£>Ú÷¥mºôìC§€É8wÏ=÷¸±$9æeÒÚ{ï½åꫯöþúë¯}ÛÞ ¹È;¹3šó¨i÷Ûo?9äC¼§±Ž €@V“ñQ/l:F†!>êôjÞQu„£x k»p@ ½€é¸•þªìE@ xQˆ}¦ï ‹×:\Š-@‡£b·×GÀ# S¾4lØÐÝ3fÌùꫯÜíL+S§N•wß}7Óa{ÿá‡nÿbÕI4tèPÉeZµ!C†ÈìÙ³Ó2>êjβbÅ yúé§Í¬:½ÍK/½$Zý;à€ì¡ï³žÄA@P ˜Œs:§K>ûì3)mä?ÐÛaV÷5kÖÌ9”ò¨lu”gѹ:*Ò¸qãœ]’<ª‚{€@2˜ŒzIÓ12 ñQËxï½÷úZàŽ;îFçõ‘°ä$`:nåT!€ P@(Ä>Ó÷…l.… ÃQÀ„âÄ[@q9`À‚޼°víZß>ïÆæÍ›åüc©£5hÐ@t$!gÙºu«\uÕU²iÓ&gWÊ£~a{ÓM7¥ìO·CZ³fM÷РAƒdÙ²eîvº• 6È 7Üà;äŽßw€ @Ð ˜ŒsÉ£ =ñÄ9yýç?ÿqÓÕ®][Ú¶mën§[ñÆ©åË—Ëïÿ{7ëœçÞãéÎg €É&ã£^«1Òÿ‚¯¸â ñŽ‚¨÷—_~¹Ǔۅm@ô¦ã–^Uï­¼KiŸ1zÓ²Ž €@¾¢û q_˜owòCpøß¹‡£Ì”H \yå•âžqôèÑrÌ1Ç¤í¼³jÕ*Ñ‘…FŒ‘“É-·Ü"uëÖuÓ¾ýöÛrÔQGÉ7ß|ãûuõêÕöðòÇ{¬¬Y³ÆMŸm¥E‹róÍ7»I,X ]ºt‘ &¸û¼+º¿sçξœ.¹äÑžâ, €Ñ0çÚ·o/:urá|ðA¹õÖ[E;ئ[tÊлï¾[^~ùe÷ð)§œ’òÁ¶{ð§•>}úH­ZµÜÝÞ{ôè!%%%î1V@ÈUÀT|Ôë"F†!>ê—×O=õ”ozÔQ£FÉ_ÿú×\›‰t €? ˜Œ[z …Á»Üwß}¾Ï.½ÇXG@ a}…¸/,D;p ž@Õà‰!ojÕªÉÃ?,½zõý2T—‰'Ê^{í%x ýëÔ&MšØÓ·Œ;V~üñG;~I:cÆ ™9s¦½î­Zµ’^xAÎ:ë,Ù²e‹äóÏ?—:ˆöÐÞÿýE§CÓihtä$géׯŸ<þøãÎfÆG­èÅ_t‡¥Ÿ?¾èTn|°ý%pëÖ­eÖ¬Yòõ×_‹ŽžäýXßì<öØcóæ €@4LÅ9ýQ§íÖ­›?5†êÜä:í™v Õ‘‹Z¶l)+W®”ï¾ûNtjQï´kúv.±N;õîÝÛ>?¹E´ã,  €å0µ,…ˆ‘a‰Ú9YGÖ{ng¹ñÆåÔSO¥Ó°Â# ƒ€É¸¥—ßo¿ý|¥xíµ×¤N:Ò¼ys9ãŒ3ìø° €€a°Ç¾BÜn²G€ Ðá(  C±â-гgOyÿý÷å¼óγ;©†vÒN:ú—¼pÀòÒK/ù†‡ONãlkG&]H¿ÕÎF΢£i&ïR¥J8p y䑾/a«W¯îMæ®ï²Ë.òé§ŸÊoû[yõÕWíýÚ±iܸqöŸ›0iE?ô}ýõ×e×]wM:Â& €@LÅ9¸ÿþrçwº¿~2eŠè_¶EãÏóÏ?/7ΖÌ=¦ÓÆh‡%ïÒ°aCÑÑX@(¯€©ø¨å)DŒ K|Ô÷ z¿ª£òê¢?âÑ_+¿óÎ;ö6ÿCÈMÀdÜr:‚:¯ÕZ¢õë×Ë´iÓD§îdA@ a}…¸/,F»pM(®Sªן«#Q@§Js¦Ë”H{$_~ùå2~üx{„¢Lé’÷k%í¤ÓÍèfÞ©a4m5ì/Muxù›nºI6lØàË"Û² 4W^yEž{î9û—G¾“64­ŽŠ¤”öÙgŸ¤£l"€DYÀTœ»ýöÛE§#íØ±c©|•*U’ .¸ÀñèÄO,5½“@˾ûî»;›öãE]$Úñ–@Š˜ŠZ&Ó12,ñ±víÚòè£úšI§HõN³ê;È €@FSqKG‘Ð׿6mÚd¼6@(†@ØcŸéûÂb´ ×Dâ TªÈå‰Ä ÖùV$ÎEì:%ÌäÉ“Ý)Ô–,Y"M›6µ§A;÷Üs¥Y³fÙ3Èá¨^C§cÓéÔô TÍ¿fÍšî™o¾ù¦oÔ†©S§J»víÜã™VÖ®]+_~ù¥=%œN ·xñb;ï’’éܹ³=l=_ÎfÒc? Sqnûöí2|øp;¾Íž=[ôoÙ²eöüÚÉU§ÕN·tP¹ /½ôRùûßÿîž«±Z;ô² € SñQËf2FóÑúä„OÀTÜÒ˜¥÷rÓ§O·ã—~n©?.ñ~n>-JŒ °Ç>“÷…Qh_ê€9 ”Ðá(g+"_»îºKn»í6@‡.nÔ¨‘»Í  €q°:ÝKëÖ­í¾µÞ:õ¨Ž È‚ €@œˆqn}êŽ € € €1(©ÃJSeb) ½•ßÿ}·îú‹ .]º¸ÛÙVÆŒãÖ/Xélär°‚ C>øÀíl¤Õïׯ_ ¨2 €~â£ßƒ-@@@@ êt8Šz S?~¨R¥Š\}õÕî¤uëÖ•yóæI½zõ²éThÞQÎ8㌬é9ˆ €@ÔìVqÏ=÷b£ËÁ  €@Œˆ1n|ªŽ € € €±¨ËZSib*pÒI'¹5ÿñÇå‰'žp·Ó­Ìœ9SN9åÙ¸q£{øÌ3Ït×YA@ nŸþ¹ >Ü­öµ×^+ÕªUs·YA@ ŽÄÇ8¶:uF@@@¸ Tª@"‘xÁ:ÿŠäÁ¹ P8ÿþ÷¿rüñÇ»¬Zµª\yå•rà 7HII‰½óæÍòÕW_Éøñãåᇖ9sæ¸é/½ôRyæ™gÜmV@ˆºÀ?þñY½zµì±Ç2iÒ$yê©§dÅŠvµëׯ/sçÎ5@8 ãÔÚÔ@@@H+P”ji]؉@4zôè!÷ß¿ÝÁHk¸mÛ6yì±Çì¿ZµjIÓ¦Mí/N·lÙ’СCyä‘GRö³@( Œ3F† ’¶Š·ÝvÒʰ@ êÄǨ·0õC@@@J`JµÒH@¤®¿þz8p Ô¬YÓW¯õë×ËŒ3$]g£‹/¾XÆ'Ú)‰@D®¹æ¹êª« @@ñуÁ* € € € qF8ŠxS=Ò Üzë­Ò·o_{Z˜¡C‡ÊìÙ³E§Ró.Íš5“3Î8CÎ?ÿ|éÖ­›÷ë €ÄFà€V­ZÉÚµk¥eË–Ò¾}{éÕ«—œ~úé±1 ¢ €$ “EØF@@@â'P©"UN$/Xç_X‘<8Š/`ý[–¥K—ÊâÅ‹¥Aƒ²Ç{H5Š_0J€ € € € € € € €A(a„£ 5 åA •*U²;iG#@@@@@@@@ ›@ål9† € € € € € € € €xèpäÕ`@@@@@@@@² Ðá(+@@@@@@@@@À+PÕ»Á:*0iÒ$yóÍ7¥]»v€ÄL`Ñ¢E²}ûviÞ¼yÌjNug̘!»í¶›4hÐ ö&LÛn»MjÕª{‹(èsüÅ_”öíÛG©ZÔ%G)S¦H‹-¤víÚ9žA²¨,[¶LÖ¯_/-[¶ŒJ•Ê]•+WJåÊ•åŠ+®(wœ,… Ê“O>);v VÁ(MA¦M›&{î¹§Ô«W¯ ×ã"ÁÐ×sýkݺup U¤’¬Y³F6mÚ$W]uU‘JÀeó- ÏíAƒÉA”ï¬É/3gΔ† Ú!(.EÌ£€¾ž/Y²DÚ¶m›Ç\ÙպuëdÅŠrýõׇ³”:£ÀðáÃeêÔ©|÷’Q(ºfÍš%õë×—FE·’Ô,­À×_mǶ5j¤=—7n”ùóçËŸþô§¸T9võ¤ÃQìš¼ô OžüðC»iÜÜ®ŸGê¿:ï9š¯Ñá(_’ÊG;ì³Ï>òàƒF¨VT%ÁƒÛ£Üxã¹$'M„t´ƒÞ½{Ë/~ñ‹Õª|Uù÷¿ÿ-5kÖ,ßÉœX½©ÓuĶÀ6‘Ñ‚õêÕËþå;NŒ22óaÆɗ_~)÷ß ËWÈBiÇíxÉgtJb[tÚ´,5¹à‚ ä²Ë.“£>º,§‘6úZ®¯éüÛùä“Oäé§ŸŽ@«RG@G$Õ_€óüvDâõØ·o_9í´Ó¤gÏžñª8µu_Ïù·/2qâD¹ýöÛyVDP U«Vö(7·ÞzkkG•² ôë×ON:é$ÑÏ'Yâ%н{w¹å–[d¯½öŠWÅ“j«?gÄõ$”ˆmVŽX}¨ € € € € € € € €`„#ƒ¸d@ØtÙêÕ«‡­Ø”7»ï¾;SˆåÁ‘,@ ˜úG| fÛ˜.•þJ¾aƦ/Cþ €@Át*5Få,8{ .¨íÞ¨Q£@”…B €ùÐÑwÝu×|fI^!Б͘&6$E1@ Ìúú÷)µÊŒ‘š7o.U«Ò#"ÍI5²ð,Ï‚Ã!â&pá…Æ­ÊÔ÷'»îº @ ²LµÙ¦-µb:%ƒþ± €Qxøá‡£V%ê“£ÀqÇ'úÇ‚DM`àÀQ«õÉQ k×®¢, €@ ÅjQ§† –C*’ ~¦T R@@@@@@@@ &@‡£‚Qs!@@@@@@@@Â/@‡£ð·!5@@@@@@@@@ `t8*5B@@@@@@@@ üt8 R@@@@@@@@ &@‡£‚Qs!@@@@@@@@Â/@‡£ð·!5@@@@@@@@@ `t8*5B@@@@@@@@ üt8 R@@@@@@@@ &@‡£‚Qs!@@@@@@@@Â/@‡£ð·!5@@@@@@@@@ `t8*5B@@@@@@@@ üUƒ^…M›6ÉôéÓeáÂ…²bÅ Ù¼y³lÙ²EN>ùdiÙ²¥]ü7JÍš5ƒ^ʇ € € € € € € € €@èÙáH;½ñÆ2bÄ™0a‚lݺ5ºmÛ¶n‡£§žzJFŽ)½zõ’ÓN;Mš4i’’ž € € € € € € € € PqÀu85j” 0@-ZT¦ÚM›6Môï‰'ž{î¹GN:é¤2Ob@@@@@@@@(] réI —âµ×^“¾}û–¹³‘·„ëÖ­“«¯¾ZŸÛóA@IDATî¼óδ##yÓ²Ž € € € € € € € €eL‡£qãÆÉ­·Þ*Û·oO©AÆ ¥[·n²Ë.»¤Ó5kÖLÙ?tèPyðÁSö³@@@@àÿÙ;x)§7Ž?ödÉ’¥„R–²e«Ð¢6•%K’¥ E$K…”²D!"YYC Y²EQ¡B”´ŠÄýŸï¹ÿ3sçιwæÞY~Ïç3wfÞõ¼ßwî{Þ÷œßù=" " " " " " " " " Å'‚£õë×Ûµ×^vˆˆºtébS§N5ÄH?ü°U¨P!l™À—‹.ºÈ†nUªT Lòï=ô‘¢M!" " " " " " " " " " " " " " " " "i!8š0a‚-Y²$xDåÊ•³1cÆØUW]eÕªU N/ìÃ&›lb-[¶´—_~ÙÚ¶m¶ØÈ‘#þ니€ˆ@úX·Îì™g̦M3ûî;³Ó·¬*™ˆ€ˆ€ˆ€ˆ€ˆ€ˆ€ˆ€ˆ€ˆ€ˆ€ˆ€ˆ€ˆ€ä*´=÷ÜsAþ¤M=z´Õ­[78-Þ[n¹¥ 0ÀöÙgŸà*_~ù¥-X° ø]D@D × üû¯ÙÍ7›{®Ù«¯šåå•=„E÷ÞkV£†Ù©§š5lhîZnæô§¶÷Þf‹…—ñë¯Í:v4kÓÆ¬sçðy‰~ûí·D×Ðò" " " " " " " " " " " " " "Û6-ëÃG 4oÞ¼`1Z´haG}tð{¢HÅvÓM7…­ö*=ê ÈR?ýdöÉ'ñܘµkg.¥Ù#˜5mš/ìA€ÄvJ;;MœhV³¦Y÷îfΰΥÈ4»ë.³Ë/Ïí²‹¯Ðøýw³§ž2{é%³wß “Øç^0ç¤göøã‰­§¥E@D@D@D@D@D@D@D@D@D@D@D@D@D — ”¹àháÂ…aüëÔ©ö½8_ØnGMט¦wÈtsæ˜wžYÕªf'Ÿl¶vmÑG4j”ÙóÏ›}¶Ùܹf×\c¶aC¾i¯½ÌZ·Îñ½¥’/ñúëfGivÚifË–å».ÍŸoÖ»·YÏžf·ßn6i’ÙG™9-iXsŒNM”uâ ÜŒN9%›¬³ãŽfÛmgÖ©“ÙE™ýùg¼[Òr" " " " " " " " " " " " " "»Ê\pôã?†ÑO†àh³Í6³}÷Ý7¸Ý¥K—?냈€d:·ßÎtÙ¸qfÇk6a‚Ù¶Û}dˆyÆÏw7ÚsŽpf?ü`FfËfÍ̦L1kÙÒ¬kW3Òœ¥*p/jÒÄÌe½´>}Ì¥¾4ëß߬|ùøöˆ¯Dã¶ÛÌ^|Ñ, u­_ßìÓOóË2fŒB¦¿þrÊ+…ˆ€ˆ€ˆ€ˆ€ˆ€ˆ€ˆ€ˆ€ˆ€ˆ€ˆ€ˆ€ˆ€ˆ@¡6/tN)Íøûï¿ÃöT¹rå°ïÅý²Ûn»Ùì?\,Ã:C!" iFáÐúõù"›ZµÌvÞù¿’j ! ®EkÖä¿ã΃ÀhÖ,³M\ôÔSÍúö5«[÷¿õB?}û­9ñeè3§Çôn>¡S7w5ÎF¼–,1»ðB³±cÍØß³Ï†.™¼ÏˆHïvõÕf8+%+H¯Fú5ÄT‘±b…ÙÝw›|°Y‡ÿÍeù©Só–4Ûj«[ÿ›©O" " " " " " " " " " " " " " ¸næ²]èé ‰yóæ¹;G†L)ÞÇù!9v¶ŽÌÅS¼Mj-$ðÚkù‚œwpÂÑN2gŸO>Éß©ÃÁÑa‡¾ý÷Îå¬[73‚ªWÿozä'C,Gš0\}â½ V©bö ùë6l¹Õä}ÇM‰W2—¤ ò·ûÒK·¼ÓNùîFœ¿Hw$\×]gV¯žÙ¸öpÁ hŠˆ€ˆ€ˆ€ˆ€ˆ€ˆ€ˆ€ˆ€ˆ€ˆ€ˆ€ˆ€ˆ€ˆ€'Pæ‚£HG£/]~’ ŽÖ­[g‹- žâHQSp†>ˆ€äûÌ%ESV´¢pi¾ˆ€ˆ€ˆ€ˆ€ˆ€ˆ€ˆ€ˆ€ˆ€ˆ€ˆ€ˆ€ˆ€‹@™ Ž(u¯^½ áQ ^w½ÿ]\ïþâÿ:À×Þ­[7Û€ Çÿ£…³Ù“h…ˆ@Úøç³§ž2;ê(³ òÅ,mÚ˜MžlvÀÉ/.Û}ë­ðíry@óX®\øôhßÐ."ˆÂéˆ4h±w¡wÞÉOñEª¯LU«ÌÖ¯7kßÞ qXqbêT³îÝÍn»­8kÇ¿N¿~f»ìbF:<Τn0ã÷¦(9´!êÑ£GØÑ̘1ÃZ¶liƒ ²çŸÞ8{ DEÈsVK]ž£÷ßßyäkÞ¼¹õéÓÇpH Ä6.Óå—_øZ*ïˆæÏŸoŸþ¹­^½:éûüóÏ?í—_~±7&}ÛÚ ”&D;ûîkÖ±£Ù_˜ š‘Ní™gÌš6-X’'Ÿ4[¹²àt¦>«F ³Ë.3{÷Ý|¢Ð%š B!M—œvŠ={æ;ô<úhì-àn´É&æ®A±—Ë”¹‡föê«ù©ç.,^©ï¸Ã ×¥ˆË}ñ6c­í·Ïw£úé§|Ó]w™½ý¶Ùf›ÅXI³bPÝfŠ€ˆ€d ÕmxÒTd" ¤²~S›d‘øµ€ˆ€ˆ@Ѝ~KXmVD@D@’@Àuý¦GàLôã?:·gwòÿøë¯¿lüøñ¯aï=]¯¨)l¦û²é¦›Úˆ#¬J•*‘³’þ}Íš56vìX{á…ì'×Ã*;í´“U«V͹·4°®]»ºÎöÄ‘Owv"ãÆ³o¿ýÖ‹Øö&Nɰ‹³ð¨W¯žuèÐÁC   ðSESšñÛoæþÌž{.ß…fàÀ|JÅŠ…—bγ3Ï4sÿNÖ¬™Y¤Øס§Ÿ692ÿU©’Y»vf§žšŸ¬S§|ÁÉÑG›MœX²c>糫¯6»ûn³‹.Š^f9¤Ps:H«U+ú2™8õCÌ8¶â¤hã·Ò²•ÂeÙ.¼Ð ¡Q ­šÓ®*$ º-A`Z\D@D í ¨nKûS¤Š€ˆ€ƒ@*ë7µIã„h¤Pý–ŒÚˆˆ€ˆ€¤œ@âê—éÆoô¡Ñ£G»48±óÅí¾ûî6`À/òIaqý¦':õÂí·ßn«È7%V¬Xa¼>þøc{óÍ7mذaq§x#¥ÜUW]å×Ü4¢&Üœžqv0¼6lèÒÝfÛm·]ä¢ú.¸Ÿ¤û͘-_n6ož™3+• ÙYg™æ ˆî½× 7š¢AÂ÷oíÜà .}Þyf¼fÏÎMšdvÏ=ù/Uˆ].¹ÄÜÿª¹ô×Od ¬\ÆGígÚ4³O,¸öðáùé»p^ʶ(ŽØœw‰/µ@ÛIê¶V­òEjÇWj»ÎŠ©nËŠÓ¨ƒ! º-†>Š€ˆ€d TÕoj“ÌšŸˆDD@2’€ê·ŒU«Vuizö³ .¸À§/+°P &LsÖ&×_}Ø–9æ—B©¹Kt´Ur9æÏŸo³fÍrN(wyΉuëÖÙСCûг_)$H%×ÅY¨,Y²$¸D¹råìØcµãœMG:ulåÊ•öÁØ„  kI!ÓÕ.×Óý÷ߟ°X+¸#}È î_Åý¯ä‹p"xÆŒüÔW›m9§dß«W7—æ0ßm¦F’m+žµk×6㕊àXN>9Ëÿþ›/> ìgÔ(smfÙèn8ÆÀ;—(wÙs©Í¼d©êÛLö{1²X&»µ=ÕmuºTX8¨n‹’È8©ªßÔ&™q?XD@²Š€ê·¬::!–‚£û]%Ò„b¹Ëÿ„¨féÒ¥FÚ´jN1±óÎ;f—ÚûgçAʶдn­\Þž[o½Õ¹žügEùyyä‘^ õÖ'.^ýuûè£ìˆ#ŽˆZfì"¿ùæ›à<œ›r–)‡vXpê¹^þÓN;ÍÎ=÷Ü 8‰Üê(À;v춬¾ˆ@(œ_xE†ÓÈyWžš5ÍÞ}7~¢Èíö½gÏÂædÞt—ÉÐ"EYè ï¾ÛœÒœãXæS´ÿí,‚pP{öÙgmòäɶ×^{yg·-ZXåÊfGeöÄf+š d™r ÷£÷ß7—â2ÚÖ5-¨nK§³¡²ˆ€ˆ€$ƒ€ê¶dPÔ6D@D@Ò@*ë7µI¦ÛÙVyD@D w¨~Ës­#È.ÿ©c2à¸*ºmD:';kÞËBl¦çž{Î~ùå— 1:Þo¹å–0±Qp¦ûP«V-/ †è(ZpS5f̘°Y¸=EŠ T©RÅ;&¾óNã€BŠC`×]Í¥%4#ÙÓOg áëäå…Ϧo‘b#ŽmîÜ|—ŸÞ½ Š‘2éØqb›4i’uêÔÉpœkÖ¬™=Ú¶Ýv[›={¶µlÙÒêÖ­k/½ô¢oV¿~¾ÐÊ-êÓæ!ºZ´(ÿˆ ›|~š¹Lb‹eUÝ–‹g]Ç," ÙM@u[vŸ_ˆ€ä*TÕoj“ÌÕ_”Ž[D@Òƒ€ê·ô8*…ˆ€ˆ€$J ÌG¯½öšwÞyÁÎAéÿüóïx”qs—¯§ÿþÎé$vþ©¶mÛ† ’æ¢LˆÏ?ÿ¼ýúë¯Á976Ü“bb$:ÿñ…S‹,^¼8ðUï"à „dè+”ÈöÛ›Ýt“i¨pð)I,X`Fê1gŠ“3á²Ú?˜]tQæò”)SlW§<ëСƒOÙ¸ÿþûÛ!Cœ˜j®Í›7ϧ¸¼ä’Kœ(í ç’uŠsZ;Âzõšb<Ÿ.”|½z™í½·9¡¤978sB%³ví2—I.”\u[.œe£ˆ@4¤0~Üå½ï¾ûlýúõÑÑ´ % º-COœŠ-" "“@*ë7µIÆD¯™" " )$ ú-…pµiH1'+(ÛX¸p¡Íœ93Xˆ?ÉI”Æ»@„HQAþ7ÞhË–-ó‹n²#J¼K«hÔ¨QÈ·Â?wÜq6kÖ¬à/½ô’=d°ê!x$ú Æ™ÝpƒÙ+¯˜sLì-î¸c~Z5§´µkóÅ"±×ˆ>×e´ï¾3«P!úülšê²=ú”bÓV[eî‘‘ÊñÌ3Ï´òåËût–mÚ´±=öØ#ì€*»©Â£9sæØc=æûBŸ5pñ»à‚ ܽJ£L7ß|³]|ñÅ6Ì)µut7A©@åÐi/õCUÝVêȵCR ÊúMm’¥pµ ¨T¿EÅ¢‰" " "Ê<¥Z­ZµÂ@­X±"è6#M¾„ÞøTpÖ-Çe“@¹q{ú ;ÿÇÁN²óÎ;¾Æ|?è ƒlë­·.ÃèmEnX´ÈÌe¸r)®ÌÆ3ëÙÓìè£Í¶ÛÎìÐCÍ ?òS¤Mœh¶Í6ñ1q®ƒ­øiÕØ÷×_›KOßþ2y)²nØ`v×]É9Š·ÞzË»µlÙÒ.½ôR»ûiªÍŸ?ß6nܘœDÙ ©-¿úê+ïZT”Ø(tõÝwß݆îS®qÆöâ‹/ƽ\^µ•+3‰Bi¥ïgÕmé{nT2Èyyyî>eœ5mÚÔ§îìܹ³w6ª_¿¾­âœ‡‘÷À“&M2Ö)nàHжŽËwJ½DzP¶GýôÔSOÙÒ¥K}Ý…SßYgå§sÿ|“Ë-Kzc~øá¾.n´^ÙPÝV¶üµwÔHUý¦6ÉÔœ/mUD@D >ªßâ㤥D@D@D  ”¹ÃQ•*U|ú„çÈ¿óÿxÅå}¢á?ÝâßÿµO>ù$X¬½öÚ+ø™ß~û­OÏðóÏ?é!ª¹žöÎV†ÑÓ{î¹gزѾ|þùça“÷Ûo¿°ï±¾†‚òÌ›7Ï/ö÷ßÛêÕ«­°Ôm±¶¥y™E€Ÿ Z3×/ç:ÕÌ>ú(ÿ…ŸÝÏÀp@Âý(Þpæ5^´„æ[#M™¸"²qÅ»ûŒZç(—…Ì0'[¿>ÿ\÷HiÖÎÙK­wúÚ)¶p* Ò»p]ášÂõ÷Àg‡Š·ºüwtìžvÚivùå—k3{ï½·=îìžIõéÓÇ ¥Æo×\sŸÆ5J‘žT·¥çyQ©D Û N½âŠ+Ü=ÅVÖ¬Y3_ßµnÝÚvÚi§à¡RÝ~ûívÏ=÷Π꯼òJ¿ ÷Ö‘/œ‘þqvzr¹–ñÎ÷~øÁH Â4¶OšáN:9çÅz1‹¶qÊlê­nݺy¢ßæÍ›»{¢£]zЫ½‹Ÿ‚§+­?¨nKëӣ‰€ˆ€“@*ë7µIó¤h5PýVb„Ú€ˆ€ˆ€”)2qôýû÷·™3gúÑÄ|'=)Âܰ^ª# $ ì±+Èu×]g_~ùe`V÷O<Ñw`Ä…º±vØ¡ÀvbMÀq)4Ø^qGß}÷ñ}Ñ14vìØÐMës8ùäü´UÛoŸ_(ׇç:òþ+ ¦8N§’p´jµÑÞ{os0`º4½é0búöík8Ù(þ#àt5%R¹œìN&©7nl¸3 dÄÝ(ðBTøÚk¯y'¡Ð"èÙrË-m³Í6sç{sÿâ3ÿ¿¤9£“7R$Éú¯»Üy\ƒqHÆÿùQGe3f̰‰ÎR · ~/ŒP™0aBhqÓêóâÅ‹íª«®òîz|æüñÇyMM«B'±0¹R·ñÿ´ÈYÂê6>øàƒþÿ&‰8µ)(¸GFȃHö}—ëµ°{ÜŠ+Ú-·Üâë,„G~Î>ûì([Œ=©œË){ê©§z‘‚!êÇD‘îH—]v™O³öÐCâ(œY©/¸¢®- NÂÅ´¸û{ôÑGÁϲr!r¥nÃkùòåauÿ7…ýå¹×1Š€d?R²’œXµj•eÿQça*ë·ti“äœò<úÜF;qåÊ•så4ë8E@rÀË/¿ìÓ€sèk×®õ޼¹„!ê7Î'ŒgÏžíßùNÿ'iå" " zßÿÓà`²@†+Eö(–ò"øÑ©‹©~úé'ç¨ò—Y 6Švà‰ö‡ñ€CÛüù¤1ùÆ¥ØúƽôŽXø½Kptñ§áHFÇ(â"\š4iâ7†@‘WdŠ3F}|ïÒÎ >BÆû?þèpw¼èT\¶l™K÷v—OWs¦³b¢£ôÀôÛg¤ŒáÚAƒ-ÎÉ RâÐ9Ëoå‰'žðé'/!÷_ ‚c-_¾¼Äž%Ø”_•›Ä[ˆ£¦L™â]á˜Áµ7ÑÎé’–¥,×Ï•ºmÇwôN'º æÅíÀ/Ëó¥}‹@¦ØàòŽ"¢NBüÏým¨ðTþW·sùZ#_‹¸7‰|q OÆýëΪqÔ¨Q¾pĈ¾.=çœsü@„¼çŸ~XJãdR¿ñìpÿý÷Û3Ï<ãëSêªâéŸé ã^´§¡ŽRÅÙ^¦¬“+u÷pÛn»mð¹óý’BD@²™)O¹W ¾p¹åD“+‘Êú-]Ú$Zs/úÜÏýc®ütœ" ÙI€ ëƒNÓyàf*Î@.Ôop#Cm$´Ç¹2ØÕ¬þˆ€ä}÷Ý7X·¡ý`€œ"{ ¤…༤ã¡S1 ì8œwÞy¾£ÎvÔ¾TÈÅIc°Ë.»$å F>|só‡#ÿØu×]}5”z ,0„à3ÿP»í¶›Ñ‘ÛOô†#rùÈÑI‘û+ì;9<Ìüñ…-¢éYJ€ÿ;F‘Ñ)ضmc›>}©YÖÉÞzëp'RÙßw¸á80}út«_¿~ 7ßl.í Ù˜1f;ï\`¶&B gÏžþºÇ{÷îÝ Yê¿Ét¢î³Ï>þ…sCQ¨LjGyÄwö¶jÕÊz÷îíSŸq­šŠ8WÜpà ¶nÝ:¿z—°M›6îwßÖ¥È;3§„(‘uO¶Ömêè”UÝVœÿ˜Ì_!&âRmá¼Ö²eËÌ?¨ 9îí?ýôS8p yä‘ •šÎÄ®]»&´N*FˆO=JZ5„Á#GŽôî¼óNïØ”,ÏÒ¥KmܸqöÀøçž{vv7T¤=¥.Åa)ž óC—ëõ­·Þ²·ß~Û;Éê;ÄÀ¹¹R·!ºã¥º-~Õ:FªU«¯@àž˜+‘Êú-rÛ‘mŒE1Ž\¾¸m’ˆ›«n+Š¸æ‹€dÀ Sމ¶«çŸ>›¯Èc‰¬ƒ’Ù6¹íÈúª¨ÂE._ÜúýÐçF¿‹ê¸¢¨k¾ˆ@6@ Á‹àº^ܾ¼l`‘ Ç‚£Fyeo8ëŒì%Þ|óMÿ Ì+Î;#z“‘Jk„Q@EZ¢Ð”itn‘BâòË/÷ªÀ²ƒ6Ò!² È›ŸDGð  ì7ÙK€ ~nðCÒáb£€…ô^Ná:Í¥˜ªãFð›y 8" Q¤àÝÆw Ìçæ9iÅJ« Á†ÿ3Ò—%+pLãZ't’ñ9c¯Y³fùSÜ"®ˆnRÙñ/,ï¹æ!´üÄ)Òft–2š¡£Vq¯8í´Ó|]C믾j8Ö BœÊ(×xcîܹ>µ)æy!4 m°Žw;Ù²œê¶l9“:ŽÂИƒÛ¢ î1`zè¡víµ×z‘aqÄì…íKÓà `H•LJµL¹ßG´‹p1õ©PãqTBð†ø ñ÷é¡/\üpÛãù‡q [‘r•TÓžpˆ**°¢GDKª-—\ŽhФoáÂ…Em"+æ«nËŠÓ¨ƒˆ ÊúMm’°õUD@Ê€nì –Êµv ÕoeðcÓ.E@D@D ‰Ò"W ⡯€Ø(‰Ç™”ME>|6J‡À½÷Þ&6b#rhð'í¶˜àƑΊȈ¼‘¤S ‘uSb½Hõu"ÛÒ²eG`øpsÎ5æD=…—Áé/ìàƒÍ‰& _&Ñ97;{":aIù‡Øˆpú×™–_¾×¬YÓŽ>úhÿ›^³f “‚A*N—ÅÏúõ3' NΚ¸?Õ¨QË^9(:[Ì  ‰ Òב’®¤JAT“Ê Ã’Ô,¸$ððʹ¾îºëR¹K¿m®ˆªHûF§?ÿ…¿«!C†xPg—f“´o}úôñN¸àQ~¶s‡S·‘Z § œ“8¶åË—¶Ù°é—^z©ïÐ}üñÇ}úÀ\Fu[ØÏC_²ŒbZÒy!6B´ˆàƒ´¡ˆÑIeyÐAyqc¨[e–!(³ÃALsî¹çz÷„2Ù”ÂÏõ×_ïA¯¼òŠg,’3ŽC‡rˆ¹vêÔÉH³Ì DKˆ—pÄÁ‘îâÅ‹½Àˆû\¡ #Âýî»ïŠÜõ:ÏUÜ_àH¹råJ{ã7|y©S}¯QdKiÕm¥Z»(U©¬ßÔ&Yª§R;¨h¯ýì³Ï\Æ?¢ÎÏÖ‰ªß²õÌê¸D@D@r…@ZŽ2v4Áâ Ü5bi"F¸|Dn/2õ[¤ #Ö>˜÷×_…-‚û‡"³,[f®CÈ\‡’9Aˆ)Ê¢ËíÛç¿—ôïÌ™3}z):Âèô Ää;9#˜`ÊŠ‘ùO>ùdpÚŸšs¢1Ûcs‹ÁÉYõŽA\ž}öYï®ÏÁ!hÁ ê`§#©PÈÑ|ÓM7ùTc|ÆÉŒNÆÒ"p"] ©`"ã9®â,Cç*éâp­‹&râzx×]wYõêÕýõ’ŽiÜ´zárêǵÁÀçŸn}ô‘ïð¥#—ßfQ»îHˆ™))¬@]ÕmúedDDü¯#Ô@\4~üx/G°ˆpÁø¢E‹¼CÍèŽÙp܉ {M›6õ×Úx×epâP˜"¤\§qÓÁáˆÔÈÙ¤JFôJ½Žû^aA…hˆÁe¹— ]è{ï½çEÉpÂE!r»ví 8)’Ê ±î­·ÞZØ.ütÜ“zè!Ã=–û¹zõêyW£˜+eéÌÈç,Su[–žl–ˆ€äTÖoj“Ì¡’UD H±K¹r1 +í'žxbÖ>C†Fõ[ad4]D@D@2ƒ@Z޶ß~{Kå+Y§‚ü¹‘SF<ö¤ûÁí(t‚E¦4¨X±b`¶OTpô'ª@è¤È,ô#‘šÌõE¹t/æÒ½˜Kùdæ~.ÁÀ(‡lymÛæ/œQÌŒ|'ù3y¨)*&"Ä3¤U Äý÷›¹ Ö·¯¹Ž­ÀÔìy§C•t)8?•/_Þ‹]Hy+è8¤³•F;Òö°.¢@ÏÜÐ N'-Nˆlr!èä'µiaYtZó»;À©Û.¹äÿû;v¬¿>âü@Ý+¸¶Þï~€8˜°M:r ®‘¸%±M:ÊùT·é—¸¶\pÁ>U«V­üu&Ôa‡ÔŽ\‹pQ#ÕŽG=zôÈF1‰zè”SNñBLꦟ~ú)æò™\·Ósí­T©’”~üñÇÙþz̵!S6s垉z|çwö,,Xdø€0–´©ˆ%!¾%•'nF`pªV­ZLá1 ΤE7nœ»ßr7\…u1»ÌÕm9þÐá‹€ˆ@–Heý¦6É,ýÑè°D@&À í¶ÛΚ5kæCâ8”êŒÏ?ÿ¼o?f0ð AƒâêoJøÀÒxÕoi|rT4ˆƒÀæq,“òEf̘‘ò}$cÑn|±MJFbþüù¾“=ð½¤÷¤O ŽBi”Íg×/ä:—ò…8Ng3~ùÅlÔ(sÂ4³nÝÌu\勊ÐO0Ïi^œ#_ÐãÅ[„¾,æ¶cͼð }ŠD8ß°Õ«W©Ï6Ûl³ÈEüwœp+ÂÁ€4…}¨7ÜpCða0rE:üHiBç#îQ¡A'$éWxåbì¹çž^„Õ¼ys—~ï\/.‚)ébJ’!çñ¸ã޳3Î8ÃH_*\BL€› ¢º^½zå"úB9²®PÝV(*ÍÈ8ÉáŽvß}÷yW™gžy&®”R¤ýB°3n4[S±¥q øE`‰C.C‘÷˜EQN{S\åMj`܈H¿Å}×dw Ê8ù`÷Žð–ÂêF®Ãð'H½Z¹råÂ6“UÓixF¸†(!7Έ0a:¿É’Š€Åý B¢Ñ£Gûý„,@Æy£.d4¬Â <©nÓ¯BD@D ¤òÙMm’Ùð Ñ1ˆ@v`Àö×_t ¸ ñŽË,m{ûï¿TÔ%=zÚˆiàY‹vEú}¦OŸîç›&<óWû}÷Ý׋ p ޙ60?žw«âÊÌ •©S§ZrQp¤ú-ž_‹–ô% ÁQç¦FaK“-‘ÜÖ¡á;4"¿òÉ'¡³c~&UP¨@‰ômñ¤z‹¹QÍ,þ1«_ßÌeÐ0§©°c5—BË\Ç ¹ÐÂ7éž“Üȉðù¤'ã9Æ™ë8'³«®Š½ðµc£³çdè<Œýú™¹¾X›3ÇìÀÍ»òìµ×I®C­“uäÙË/oâ\ bm¡ôçáj„ÓEt¦òÈ‹ÿcÞ£ L™8q¢w8ÂÙbÓMóLÒQ=iÒ$/Èb[ëá.pê©§ú¿Hvü/^tÑEÞÝ·EAtæ3ÆwÆ"4B„”Œ¨[·®Ýxãþ¼ÐU øŽ»ÔwÞÓÑ*°|.½«nË¥³YÇÊ}ÓÒ¥K}º*ÒbSÄ2¸Ê!ÅIæ¹çžó‘±Ö ÌÃÅ!)âĉ|N×X²d‰E-^¼Ø †pÂÙ 'u¢“¢‚úV¤ö¢ãžñæ›oöÜ8vRwE ®£ZàÅ6AzK^8ï0”º°cÇŽÙ9ñÞÏÝ,!d†+)Ö¸¯ˆ6lXbœ#êLî]¨ËÜ&õΈÀäà—Eu[ðç¡" " YD •õ›Ú$³è‡¢C &€ÃN¼pb.ƈŽp¯ç…ëÏ]Ûl³M¬ÕbÎ#Ý:ºaâXË _„@ï¾û®OÉþÍ7ßXà…ãz h‹àñQQÁÀžá¿w©ÞÀà Ê\ Õo¹zæuÜ" " ÙB@‚£Î$î•*U {¸ÉDù©À.l“‘ŽFˆB%<øÔhÜ´®[·.®eÄIÿ tù`ï©(åÍõá9áC~ÞzË܈ôüiÎô&¡ÀíèŽ;Ì=8™¾\•έ«œ‰ßiLpŠåL@G%‰ˆaècdFQ°î¹Ê Ž\¢9³[¹ò)7Òdk'¤zß=S°`e8…Nj:^q` 5L7rÔE ŽÿÞqÕ( :úý÷ßKU?ª%T¸ÂfñËà Û&EX è°¥Ó·ŒXç!°|®¾ŸþùÆ+ÙÁÿ£ŽH±†ÃégpœÂÉ«mÛ¶Þm"ÙûÌôí©nËô3˜ùåçšMªI„°Œbä=ðâ>± ˆ8Ñž–÷Zµjy!# }„Ê×Ó¯s*_„Ÿ‰ºõìÙÓ_×¹~S‡ö2Ý1×¶@]ΈJi”}ËÝlPoQGÑhIc%ó#AiAi}ÂY(þhÅ‘wÄ3p@äª>&"0êÖ@Ú°Ð…`éì:?›?#"õ*¿OA°˜ÐÉÜØ*ÊŽÀ%—˜¹A>5‚!§KqÂ4s „:Å+ëÒ©±Ä4¸ðÅïá é<ªW¯îfHe‚ ˆàÇÒqT­ZÕwV1WƒxFO¸>H×ii枇Ì=C¹í›­Y³;¾s]ª¸[ØTÒ¡¢?Å Ü)è|%ÍLab#¶Èˆë Öµt^pÁA»^öèTᬥ¢¹Œ9Ò;B\ÂÉþðÀˈ®êô P)Ýw®£¸Jà.øŽ:‚s„3ÕðáÃK·0´7Õmt²²¨¨ÜçQ7â,òHzOÄ8ÄüòË/ÞŠœk8®h4È‘JŠôŸü^qñÁeçâ‹/ö£ ™þþûï÷ZX '*6+uSÜyBÝ{Ò9îBÔ㈳¸ž!ŠjÑ¢…O]†Ë%|=ôPßÀ‰À;÷š4\RßSGœqÅИ‹}hpÁý £‘A½Œ‹ûŒXiX#×Ë¥ï Bà7}¬³·Dl”ìˆÃ÷H¤ $:§#Î ÷¡©Ds‰{aǪº­02š." "ÉRU¿©M2“*»d>ž£‘ÎŒ~² îáÕºukÿ¢ýÇWž[yž]¸p¡ N[À!C|;.‚!æ'’™‚g`-ñ¼ÅsV@à/Õ ®Áþ˜cŽñYiצ}™´eÐnO›3T9ÒŽW©RÅ•™’C‡wWY½œê·¬>½:8(œ€ë(zÔ½’nôvžëÌÏs7dy®£¤È—ÍžçR äýðÃI/KäÝ oXyÜòÁ5°æqïW^y¥ßuž¢ìpÏâ¨óœàΟ#îÃ\ãv\â7íDzq-› åBÝ6þü<çN– §KÇ " Å"Àµž{·\ŠTÖoéÐ&IûÏ Ü!ðôÓOûvnžqÜ›b¸d“wðÁûçÖ ä-Z´(®m¹î~þýûǵ|< ÑOÕ½{÷<7È'ø,N[>×7'nÊsNÍy.5|Ô~¥?þ8'Û¯²½~ãwã2Nä9A\­OŸ>~T"õÚYge‡~¸¿†G;®=öØÃjd´¢Øš˜úzÈ –¢-^ìiŒ.¤ÞÄåˆ{¸hñÙgŸùTf܃Æ,Kžh¸[wïRÄ=2ÎBÔ籂Tp^x¡OŸŠS(nQŒíÛ·¯vÚiÆ9À ¾°4hŸuíµ×ùé§Ÿ|6ܨ¨geG€{Ò©áˆ=?÷O8Á* PÝV‰¦ˆ€ˆ€d>TÖoj“Ìü߇Ž@JJ€þÚcI·ƒ<©ÆŠr b7È˧=Otÿ´ÇòœÊ3ªœXÍš5ÝDpù<Ч*Ãéœ6sž_'Ñ`O[2íí7ZÌ´EÒ¿… Ó¸qã|Ûþêի͉‰¼‹Òù.•©ãuS*fq2b5ÕoqšTHˆJ ­Gä¹% F¨x&j© ™Hƒ;â 7Ü[X²X‰&#ê uAhÐñÅ éúõëC'ûÏtÐ ¢àf2”ï¨£Ž |-ðN'QhÐñCŠ ÈÔqlûœsÎñ7ôå;ŒŸø®÷Ô@oæ²”¸‡¯¢÷å~âN bvûíùË:7UÛ°Á\ÇÑë¾ýöÛ>Íöª¤:á…Ô<|ñ[ã Qv±ÜˆG –¡—´+ð°sEäV©R¥h‹{Â%öõ 9ãJýúõó üþŸzê)ÿ¿ÌÿéHHWTБ‹õ®s€òÀü/$°æúÁµs’ð"AÎA¬ ¿4ÿŸ¼èÈå\:jc­§y¥C€”C¤âÁ¾8é•J§”é±Õméq²¹ˆf¨3v~úé§æâ|jЀ86Žº’{=C㤭¢ÁQVß;wöõ5Ë” SO85s#'½Å:\Š êsÒÌ!¤ ¤Ñ*jÐùˆY—c!èž{î:»Àg7"ÔßsL™2Å7в[êdÄNj-€¬Ô'`ÑÏý÷<Àb=W”záÒh‡ªÛÒèd¨(" " I#êúMm’I;UÚd$ÚI6}útß–\·n]?ز]»vþy˜çD<‚ìøã÷ƒ]þN&Ïü (bðKQAû/ý&<³N›6ÍœÛ}Q«9Ÿö]öO9£o+fpÓk¯½æÛ{#7€8‰Ý<ë§¢íë¤CGĥؑôÿ«~ ç¡o" " "I6)Ia]'‰ój±³J²ÀºÎBÒwnDSÌÓ1BÇ?7¯;ì°ƒÏÍËhmœ+P¡6ºœÑ¿4ȧ"è C Œ°g47Ç.Ý{àÒZ> Œ2/JøAÙ]ÚƒÐÍ{tqsêRŽx·šÐ\J/´8âˆ#B''üÁ ÇFç–¢hî”8Á‰™Ó9PÑË»SgnÀ…sß17RÄœƒÙ /ä¯ÇïŸÑ .Š…øíó΋ŽJ::y`J—èÝ»·1Âf̘á…QÅ)¿5þŽ;î8{óÍ7Ñû„Kçâ;¨×!¶¢ƒ¶° óš‡Ã«®ºÊÀ)l¹¢¦ãfÁ± tŠ':Ò‰Ì5Ì¥2—š-žÕ´L¨]»¶ÿ ƒ=×"›ë6®' p×Ûÿ_psíä–ññâ¶çÒ]xáËwÞY¤è¥Œ‹ëEÞŒ†üî»ï¼ó÷dˆR¹¿ÃFQÜô¨ÿpCâ¾)šÃ$õ:ŽI.­£Kªšg.]™¿¾àNC8Ëx_Ï!ÆâþŽ{[—î,øB4LÃ( ¹¸:•V%BeF‡:zïöÇg—¶Ë-ës£ýç ýf§\gP÷ˆñ÷)4¼;÷xÏše²¹nã™ç3:h" "‹h¿Â¥¸(çñld“Êú­,Û$iïuéíÃnfãùÓ1‰@:@hÄsŸKÙk8ìâ¸ÿÆoxwaú""C#0¢/„Ï$,Ïu™çf‚Á ü?“Íg]þ¿C_.í˜&æ^v¿ýöK:öÅ@!ž¥ žáO:é$Ãq™rÍš5Ë?£3È—Á9é¸E1*WÛ¯²µ~ã÷Å ²ß~ûÍ®¹æštù¹©" "P*ÐJ0°þ_EV¨’‚#ÜDPɇ*ßïàÞÃÍ_¬Î5kÖxW:‚¸),1›´Jt’¤"^zé%ßDâ‰#<Ò§]Úm·ÝŠ\|ݺuÞí ûÏxþÝwßmõêÕ‹gñ˜ËHpO™¤EsFB.¥_Y OÀÉŠß=ŽY™â”CÚ?„pXÁºüÓ 3e85!(äá5òÿ÷ D<¸C ´ÀCjàY ]Pß1›hº¸„ ±×.y@Ud>\qö²µn“à¨ìþ7i”Ä! Ä×™عS¯ÜSÒèJ=tªË…ùHZ7³4dòЄ)0º‰:‘¡?aTѰùüóÏûn„…br|¹Ï-m$õ:†\¿üòK{÷Ýw½0¸°²jzúÈUÁg&[ë6 ŽÒÿÿN%²$@[[`0OY–#•ûÎeÁ\SU¿•e›$÷Õ¥ò¿FÛèPIßÏ~ ªDD¤ãšËÿ(}5ÌÇ™(2È\H‰ë¢%DE¡Á ZÖãÅÀÚÛ]€D]êC·Ïç9.5ÏB¼Eq¬<ã3 ‡z’tïE g?ÉZ&×GpÌÆúã’à \$ ÁQÖŸõôÝu×]^,ÀÍ +â™xGëÖãfG£•+W&ùŽ &¿'ûÎ+Œü M™¹ì {ôèaÝ»w7>Lj§Få;{xØ/,H£@:'œq’%ƒbâÛÀ ‹ß>)[è-íŽÅÄKüߨëòÿÇM3#Gâ C8rÑ M‡laî\XÛ"æáa£°àág¢h»…­£é"@® Ž`’u›GÑ~í¥3 ÷ìÖqªË´Q\¤f¤a ôjÕªEFƒëÙgŸí¯\?Húá‡ÖìˆÒ{õêe·Þzk¡îD¥¢¡±cÇúŽÉI“&ùÿÇhÇBê4F 6bäeQb#¶óéÔ" ¥G@u[é±ÎÖ=!V¡qˆTcÙ*6âÜ1B±ðñÇo]»võbzD²™’>®°ßßСCíòË/·*Uª¶ˆ¦‹@ÆPÝ–q§LH€À¼yóü½ƒàHáÊÀRÀâTˆðtÈ!þ…«bóæÍ}úò“N:Éw2'°›à¢ÊiÏ8ðÀƒÓ’ý2#6Â]œT<¿ýö›w¨à1)hæÛ$SÑ.©6IýºD t p]#ƒÿχ~¸ÑîHÝŠÒp}e€ç#<"±Q*k›%"ªç7Õo%:-ZYD@D@”ùS9!¡ÁH«’ŽItü0Úœøì³ÏJºI­/8#;î8³úõ ÌJx©óè9rdÆvÈbkŽ)sèˆqvhÓ¦çëØøñãí¡‡òN`LÄÚý¶ÛnK˜—VH¤Ãõ‡Ñõ8øåB{ì±~Dh¶+xeËÙÔqˆ€ˆ€d"%K–Ø|`‹/öB¢XîÙ æ;õÔSmýúõ6eÊ? ‰c&5*/ÚÈ!!>b>˼¨ï¹‡iÑ¢…µmÛÖ»tÅ 7G„É7Üpƒw²dÐ)x’-¶æøiC |ì/2)Õ"§ë»ˆ€d*|r› ]•`fÍš5íˆ#Žðƒ65jä§'ãµ{ì1;ù䓽^2¶©mˆ€ˆ€ˆ€ˆ€äMËúpCG(õqx)il·Ýv>}G`;ŒzRˆ@2 |ÿ½YÿþæR‡•|«k×®õ²¤È»è¢‹J¾Á2ÜB¿ë®»Î^yåÛrË-}c%Ì‹ÀC3ù—{öìi¸‘>‘‡f…ˆ€ˆ@ö>|¸Oã1`ÀÛj«­²ïuD" " " "ÿþû¯­^½ÚB¢ãÁv»víü34í8^“æ§‹Ï?ÿ¼Ð=òì=gÎï&Ü AƒËñ¼~ÔQGùù¤EGÌ3fÌïrDúÔ~ýúù”:ˆ–˜_X|ñÅvôÑG»6‘þÞÕ¸¾…EŠýöÛÏ|ðÁàà¿hë¯[·Î&Ožl¡mÑ– L»õÖ[mÆ ¾!0Mï" "­f̘aO?ý´¯–-[æÛWsҮʀHC´oÜí¯qß%]adú¼GÞ=‰e" " " " "Pe.8b”V  %+hè„GzO7ÀÎ5¢™uéRò-’f†‡È믿>k:d7nl³gÏvPÇÙèÑ£ýèÉ&MšØÄ‰½àˆ‡XK" " ÙI€{/Gûï¿¿{î¹Ùy:*H€ÀŠ+lذa^ôS£F Û}÷ݽÃ1ƒp*T¨à]6lèÓ´"Êa@ƒ’ñà ü½ù„`‘PdÜÿýöè£z'£+¯¼2rvÔï "m(‡pöÙgíÐCõŸ?üðÃàºtLßxãþY'qGŸ|ò‰½õÖ[Þͧ¤óÏ?ß·„ –6!HÂA gdöAÚåË—·íÃÏ?ÿl<ð€yä‘Ö¬Y³h‹hšˆ€d \è¨IêHÄ–+V4R^’ºu©1]vÙeq÷SO=e½zõ²K.¹Ä‹XÙ¢%D®uÒ×_m×\sU­ZÕOÓH”@™§TÛa‡‚e&å;í´SpZq?,Z´(¸*7ê H7øÐ~Ø\c ™ÓД(~ÿýw»ýöÛ½#WçÎK´­t[™ÆKy®[·®U®\9ÝŠ¨òˆ€ˆ€¤ˆÀ!C|#&Dr²KdmVD@D@D # Ú!ú“O>éÓÑæµ÷Þ{ûgdR¤1ø.ðN*ZžŸ ƒ xhœp vÚi§yÏÚXÁ>t&W«V͵Uûl/FB¸p6Ç݈ù8mD|EG9nÉ8-rÊ)ʨ " "Mþúë/ïdÄ5üºë®‹yh#GŽôŽt¤B#f¹rå¢.¨ˆk-×sêsÎ9ÇV®\iˆ•üqïnGJOžÝ‹S'EÝ©&Š€ˆ€ˆ€ˆ€ä$Ê%JÎ,tD[{ÿý÷K¼QòÉ#: £¼" ò]‹î¼³ð¥›¹1h®Q¬ðeâ™CÚnGµk×¶ÓO?=žU´Œˆ€ˆ€¤=FÄ3ýæ›o.Öû´?@PD@D@D ç ,^¼Øw ï³Ï>^DÃ`D8ˆnH…Fj„7¤ª!-ƒëÞ}÷];óÌ3KÔ±‹K8®@{H¯Cj² ØwÜ‘ô´åx ï”¤ÛÁ©iàÀQÅF¡?KÓ§O÷ÇþË/¿Ø#<âÝŽb#–Eˆ…+ò¥—^ê#t}>“æç?þ°ké¥R$°Á5#è,Í@DÄ5k^Q§¹v’ÞráÂ…þ™;Z9tRWtìØÑ‹ËP‡tíÚÕÄRÑÓ¨Q£Àl½‹€ˆ€ˆ€ˆ€ˆ@±”¹¥ £•Pï“ZŠÀþ¹fÍšÅvEùí·ß Ø€bÙ¬x¸ 0öå—æÈ¢/킘s µ ̪W¾L¼So¸á[·n·*ß´¤VIñîTˉ€ˆ€ˆ@ Ð0;vìX«_¿¾5oÞ<…{Ò¦E@D@D@D t àñÊ+¯Ø½÷ÞëÓÒüóÏ?>5Z½zõ|ú3\&HƒÆ‹Ï¤ÄA`„)ÙPçØc5R™qß…“Eª‚h8%¤u;à€ ]…vÀ‡zÈš6mêÓµM›6Í9H牤]Aƒ³Ú¶m[è64CD@RA`ðàÁF›m‹-üõžT—© \ˆØ'Öž={Ƶ+ÒhÒ‡rÛm·ÙYgåÓ¢VDèÉvvÝuWï^˜ù^¹reŸÚ3rº¾‹€ˆ€ˆ€ˆ€ˆ@¢Ê\pDƒ–ž(ù l ¯¾újÛl³Í¶M^»v­9¶dÉ’ R¶}ôÑÁïú …pm‡öÆfn0žõë¾”s—5ׯfß~kεÁÜHÅðù‰|[´h‘a{ûâ‹/úߦRŽ%BOËŠ€ˆ€¤#´Œ²>|¸/Þ­·ÞšŽÅT™D@D@D@D !´3}óÍ7^h4fÌï@A{Ñ_|±‘&, ”IhÃIX˜k”-S£I“&¾Sü®»îòŽF}ûöõ‡‚[Üqú@¸¤Ò$€+ÛV[må…¥8½!¸ìÕ«—ï«HE9pŽ[µj•=ðÀq;àQÝwß}^xJ Ë7hÐþઇp‡£Š+&ë]D@D@D@D@RF ÌSªqd矾·R%£Æ®¸â ïrôä“Oz˜À¼hï?þø£ÝrË-ÞJštj¡Ñ»woÿ:MŸE Ó½õ–ÙÔ©æ,Âÿ[bͳë¯7;é$³þýÍÙ¥›³£ýo~¼ŸýHëˆ2yòäxW×r" " "–žþy_·1º²N:Þ–ý˜cŽI˲ªP" " " "PR†ñÌŽ[PÆ ­J•*>]Úá‡îÚúÛ_ýåE0ß}÷½ð ^tTVb£ÂŽ!Ó¦#RÇ qÑçŸn+­4$¦uèÐ!ÓGåÈp3gÎ4®ñ8½öÚk¶ûî»} fþôÓO£ý¤¶œ7o^Ôù±&²ÎèÑ£½p¨}‚Í”é‚ .ðéÑ{ì1¿Þy>Ç]Oq±Èkžˆ€ˆ€ˆ€ˆ@2 ”¹Ãè{œ…  F1‚<ñ×;¥Ç—ç [ÑJ•*ù}rc7ŠÐè§Ÿ~ò7õÜÜGFãÆus Eßc@tä~faÀhölsqf¯¾jæœË­|ù°EŠüòÉ'ŸØ…^ès€Ww¹Ø…ÂïS!" " ™Jà‡~ð ±t¸U¨PÁî¾ûnßA§Ž·L=£*·ˆ€ˆ€ä.ßÿÝH¶aÃ{R‰p >UÍ¡‡êÝŒ6ß<-šÑ²æD‘~nüøñ†Xýì³Ï¶–-[ÚêÕ«}¡î)³æ4ë@D cp="è£8ØYà3°™ôjÆ 3\åuÔQöÕW_ý¼#ú;|¤¸d™Ö­[Çå~wå•WÚÆƒNÁ~# üaö³Ï>k—_~¹vØaÞ‰ ‘ÂM…ˆ€ˆ€ˆ€ˆ€”´i)©Y³¦ÝÿýNÌq©ýúë¯aÇ¿~ýz›3gŽ…͈ñ…†"F¦©"$ÍŠ›éº_yÅœÈÍœWÜ«ù†2LIÈo‘t×]wѨ¦L$ðóÏ?{áìí·ßnüñ‡=I, › ÈDÓ§O÷b#œvzöìi»í¶[&FF–)ÒV‚ËQ5ìŒ3ÎÈÈcQ¡E@2—Àßÿm'N´Úµk{±GBû-¢®I¸ :4x€¤|Ü{ï½íÄOôŽ¿¤1›0a‚µk×ÎlJÇyçgÛn»mpÀ‡5ÎNª³ØgðÎi§æELy‰¼ï¸ã޾L;w¶ºuëúÜ81X[!" " " " ¥E mG0J|ìJÇgcÆŒ)2•Z4HX^÷éÓÇŠŠ6_ÓD ”@^ž¹‘sæͶÙ&tNôÏñŠè€Åé{ð+VøÑzü¦yhUˆ€ˆ€ˆ@¦Èsæ›o¾é…FÏ=÷œ…¹ÿþûûÑç5Ê´ÃQyE@D@D@D ŒÀ;ï¼ã¿Ó©,±QšRùÂà¬)S¦øÔ¼¤¯Ûl³ÍJe¿Ú‰ˆ€ B4Ô·oßÀ¤àû!‡â¯OŠx6fà4©·‰hLFœ4jÔ(»÷Þ{½0bÊ.]ºøå.\è³4~mÙ²e~Ûd}`’Ĺçžk>ø QáתU«’lN늀ˆ€ˆ€ˆ€ˆ@ÂÒJpDéË•+g_|±uìØÑ 6ž~úé -i¬£Û~ûíýzÜXo¹å–±Õ<xàsv³fάÁn¾98¹Ø°_ǩ릛n²¥K—ZµjÕ¼Ó¿KF¾(D@D@D “ šEN*Ðo¿ýÖ×e't’¿ç:å”SÔ”I'Se(”µ+VôÈ….¤)#€Àè©§ž²I“&Ù9眓²ýhÃ" ™I€ôe¸F\îq#Gy&MvN¶Û3Ï<3ê¦q®ïÔ©SÔy‰VqºGDùè£Úˆ#ÂÒ¥á LºÎæÍ›{¤† ZÕªU«ûÁ™hVˆ€ˆ€ˆ€ˆ€ˆ@iH;ÁQÖŸKeR¬ýðÃþµhÑ"'ùÙvÝuWC¾—ËuÅ97ôtèé=¤GcÐÊž{šõëÏ…/óÏ?ÿøI*¿ÿþ{«T©’Ænw‹-¶(|EÍ4%ÀÈÌ+®¸ÂHm»Ë.»Ø•W^i]t‘í³Ï>iZbKD@D@D@'°víZ›={¶!¦V»Râü’µŽå—]vY²6§íˆ€d8ÜãIqÆÀΙ3gú£áM[ëW_}UÀ]¨$‡Kгɓ'[ƒ \;±k(.a0 šrvíÚÕ>úè#ŸšçèòåË—pËÑW'…Nû ( i+8 ÀàA1/r+D Yzô0[µÊìñÇͶۮø[]½zµ|òÉ6}útÛyçí¶Ûn³ž={ú‡ÉâoUkŠ€ˆ€ˆ@ÙXå*ÇóÏ?ßp™¬Q£†¡Ù¾}{9H–ÍéÐ^E@D@D@â$@š›/¾øÂ^ýuŸ ¶iÓ¦ÎÑØYtdoܸÑw4±¨f‹€ˆ€¤˜ÎºÃ† 3Ò—ÑæºõÖ[{ç3<Ÿþ¹õp º7Þx£Ýzë­I+ Ͼ ´)ÊÁ(ÑÒ¯qä‘G&ºš–Œ"ö‚£Œ¢©Âf 7Þ0{þy³3Î0kÑ¢øÅþý÷ßFÌ?üÐ?ð<ØHï§L$ÀèËÓN;Í.\èßÇŒ£z-O¤Ê," " 9B`É’%^`ôÚk¯ÙîAÿ—_~ 9÷5tL“'VNÀÙB!" "Pvp3Âé w£C=Ô»‘â¬B… ¾PÇ{¬=ôÐC>}ékÕª•”Â>öØc¶ÕV[Y‡’²=mDD@D@D@D@r‰@Z ŽHO…5*"Ž>øÀXØa‡¢ž—gžyÆ/KÃHX–*D 7èÑ¥…1÷ ivË-±–Œ=oÙ²eÖ¤Iûì³Ï|ú?Ò©)D@D@D S Œ9Ò§M£SîÞ{﵋/¾8SEåÈRýõ—wž:uªñš3gŽ?R\$>ø`;ûì³­qãÆöꫯÚðáÃ}›Ò1Ç“‚#Õ©S'ærš)" " è$ýíü{ï½·7ÎN8á„;ãYõ¾ûîó}ݺu³€`´À‚ Løù矽+^ëÖ­­°þ‡6§EE@D@D@D@D 礕àûë±cÇÚ¨Q£lݺuÁ“©°`ôÚ£>ê_ŒD¨_¿¾‚M!Ñ8G^ûä³¾}ÍöÚ+ÚEOãa”FL„qC† ±~ýú½’–4$@ãn—.]ì¹çž³ýöÛÏ&Nœh‡rH–TEÈE?ýô“ï„F`4mÚ4ï|‡Ê•+Ûyçç5jÔÈvÝu× žwÜÑ ŽžwÖÆ±Gþù§Íš5Ë6lX¤Rpãú " "4o¿ý¶uÖY†cn»£G:EÛÉá‡nÝ»w·»ï¾Û “:wîm±¸§‘ºíßÿõeˆ{%-(" " " " "$ÛW:¸Xê?¬ZµÊ?, :4Ll”Èžéöúë¯[›6mlæÌ™‰¬ªes„€û‰Ø5ט¹¶G»úêâôâÅ‹½Õ:b£#FHlT<ŒZKD@D Ì;׎<òH/6êÔ©“}üñÇ¥ÁyQD@D@D@ÌpîÝ»·í³Ï>Ö«W/ïZ„³õ-Ϊ§áüÑ|ðA—*ýŒ0±츿©T©’K¥îr©Ç\µiK:þøãc,¥Y" " É&°qãF×F{|®\¹Ò§J{â‰'bŠe¸é¦›l÷Ýw÷½+V¬L.Öûøñã½³QË–-‹µ¾V\'‚#F`{ýæ›o&å|ð ÁH}Fè+D ”À=÷˜}ÿý¢£Ðyñ|^¸p¡wÑZ°`qs饗Ƴš–´#ðÚk¯ùÿ?üðƒO¡FCë¶Ûn›våTD@D@D@r‹Ò®¿þz/4bÏAd“&M2Úzp8ºêª«|ú´XTH±ÖªU+C\ýí·ßºh Oƒ ]F3D@D@’K€ë9Y l8Íž=Ûq*ªP¡‚ 6Ì S¯.îˆRwH_ýµßwûöíÌ Ä ¤…àèå—_¶yóæ…•ž‡ /¼Ð{ì1Ûi§Âæ…~a$Û Aƒì¸ãŽ l¤gcÔ[IG9„mT_2š€,c7ßl.¸YÏž‰ ©fêÕ«ç-~É%ÎïS!" " ™H€ôµ-Z´0:ã^y廸â‹3ñ0Tf,"°~ýz»í¶Û¼Ðˆvž½\ô§Ÿ~Ú>üðC;õÔSF·nÝÚÓ‰år„à¨|ùòvÄGdIŠˆ€¤/Rz7iÒÄÞÿ}»âŠ+lÆŒV£F„ |æ™gzw¤ûï¿ßo+á ¸tCÒM!" " " " "P<e.8Â݈œË¡Ñ¸qc›:uª]~ùå¾Ñ‡Î°Âb‡v°Ž;zí‡zÈvÛm·à¢ëÖ­ó#öƒô!§ bN€fæ\wݨ•øQÌŸ?ßwʶmÛÖþøã{òÉ'íœsΉZRD@D@Ò„À?ÿüãS’ôèÑÃwæÑÈÛ°aÃ4)Š!" " "‹(Æ€±êÕ«{÷¢í·ßÞ~øaûâ‹/¬]»vÅFÂ=î… ŽHçóÞ{ïÙÑGm[l±E±÷£E@D@â#€ƒ]Ó¦Mí“O>qí³7ÙСCKtýe ×ïnݺϺ‰ƒ•üqÛsÏ=M.w‰Ó²" " " " "N ÌG4 ‘¦*ÕªU³áÇÇt5 ,ù~ì±ÇúÑoˆ1aÂ[¾|yà«Þs˜€{~´FÌ:uŠ£+±q¯]»¶À!2‰‹‘• È44î¶lÙÒ ½é€Cl´ß~ûeÚa¨¼" " " YB€çëîÝ»ûÎ^Râl¶Ùfþ>å›o¾ñƒ|6Ý´dMV¤Ç¡c{æÌ™QÛ…>þøcc š:š³ä¥ÃHkkÖ¬±fÍšy׺Ø5×\Sâòî¿ÿþÖ·o_ûôÓO­ÿþþýÄ8+}ÿý÷†SR¬ÁÎñlKˈ€ˆ€ˆ€ˆ€ˆ@.ؼ¬~Ñ¢EaEèÓ§O‰r&ï²Ë.þ…‡ âï¿ÿ¶¹sçúTXa;Ò—¬!°aƒÙe—™KqfV§Ná‡EµxS©1ò2·Q<>ø`»çž{ô*­æˆ€ˆ€¤9úH?;gΟ”zmóÍËü60Í©©x" " " © ðÆoØwÜa/½ô’á0Q·n]ëÝ»·µoß>é÷'¤U#-Û‹/¾h;w;Ò©…aÑH:µk×ZóæÍý „ALÚ>.1à˜”œ¼2 àšGª¶ªU«z·»råÊYè‹uˆNñŽLõK눀ˆ€ˆ€ˆ€ˆ@$2ïiZ¼xqX™8à€°ïÅù¶«®ºÊH×F ©W¯^q6¥u2€ÀĉæRç™{ ýò ˜‰ÀwÞi—^z©U¨PÁFŒáDJ=ýHËÄ·¤5D@D@D =С‡Ø¨_¿~6„£ (e|ð؃Ë"nF¸#4­:UÑ¢E ¿/Em¹å–>¥Zªö¯íŠ€ˆ@®`ðËÉ'Ÿl8 1@øæ›oN*’­·ÞÚ¦OŸnÓ¦M³ ø×üùóý;w±¢Ž¹zÐAÅZDóD@D@D@D@D@Š Pæ‚£%K–‹ÈHû=öØ#ø½¸°ÍÞk¯½¼ÐˆmüðÃÅÝ”ÖËwÝeV¾¼Y—.ÿÖ9°;g"³³Î2—Ül÷Ýÿ›WÔ§Ñ£GÛ®»îjŸþ¹SÔòš/" " éNÁÑ­[·t/ªÊ'" " "eh†è7 Ú}Ôsùå—{׉TêÎ;ïì ½úê«öçŸzw öɵwß}׎8⣳Z!" "|¤7kÓ¦½ýöÛ^pp Jöž*W®Õ©g%ê ÒgR^ëׯ·¿þú+¥‚×d£¶'" " " " éJ ÌG¡é<6nÜèS 1Ò­¤š{ù×_-éæ´~šp$mÖ¬ütj;î^H—9ÆÆŽ5[¸ÐìÍ7Ãçö ÷‡¯¾úÊwÈb¿«L'@ª’©S§Z­Zµ¼ ;ÓGåÈ tðÞrË-6lØ0£s‡ >ï·ß~¥z¤U£³ûõ×_÷e`ç 0Z¹r¥üñ¥ZíLD@²×Wž?_yå/ìܰaƒõèÑçÒ,ícßvÛm­fÍš¥½[íOD@D@D@D@rŠ@™ ŽvÙe—0à :äÀ ›–è—U«VÙwß}\mÇH%JpŽ>d:܈^½òßi¿|ã ³_4ûôSs ‰f;ì˜[øûDò³¹èرcá iŽˆ€ˆ€dO]EøóÏ?;×?gû§È:ˆypq@àxáàS·n]ÛtÓMKåxqŠX¶l™1à‹×7Îv±÷ ¤«>|¸5nܸTʹ“V­ZYŸ>}Œ´jˆžˆwÞyÇ¿7hÐÀ¿ëˆ€ˆ@ñ 0zâ‰' 79®ûDygGÏu¿mÛ¶vþùçãZSD@D@D@D@D ­ ”¹àˆÑö¡Åö AƒB'%üù³Ï> [§R¥Jaßõ%;üò‹ÙSO™x¢YíÚщ¶Äÿ·'F_ b*‚£Ý]þ55:F€ÑWŒ%H§Ö¢E‹Œ=\D@D@D œÀ—_~éÓÓL›6ͧ Ÿ›ÿí`—güŽ;î°† F›]âiO?ý´õïßß–.]j«W¯.°=˜Ýwß}ÖµkWK†“uÄ9¡zõêÞéqòäɆó#ŽØŽ(ÓqX#+D@D@ŠE€l¤È¼óÎ;ýúµ]í™gžiÍš5³úõëÛV[mU¬íj%Ì!Pæ‚#wñðÇxjÏ<óŒ5iҤ؂ß~ûÍvxÀQd×niΕ×.¹$9ÇöÅ_ØÜ¹s½ÍoiMNɵ(œ‚£í·ß^j…#ÒÈ{ `wß}·Ñ©[±bE#mÌ6Ûl|á01jÔ(kÔ¨‘µiÓÆ†j5jÔHÚq²}„DNJ»îº«!2â3)ÊIWÆ=H:.GC† ±\^ö£>Ú ŽêÔ©cÛm·]:OeŒ#€›]‡üõ”ëýÃ?l{ï½wƇ ," " " " "P2e.8b¤髯ç„‘={ö´k®¹Æ?´$"üX±b…uéÒ%,ZµjÕJœ¢­dˆµv*üý·ÙèÑædÍN9%9{P:µäpÔVD@D@Ò‡Àï¿ÿî;ÖZ·nm[l±EúL%H˜À£>jW^y¥wB4ƒèèðÃ/t;—¸Ñ9,ϳ.d¾_wÝua" R¡-Z´È¾ÿþ{Ÿ–{†xÚaºuëæR—¯´^xÁ=“'顼Ð#)ù Ž ÁiÕvpùÖIÿ¦t³%çª-ˆ€ä&Y³fÙ©§žjK–,±K/½Ôn¿ývÛ|ó2ïfÈÍ“¡£2&°iïßïÑÎ;ï, ^×_½…÷ÀØ‚ ‚ó¢}øê«¯ìÚk¯u©µNô5¡Ë\}õÕ¡_õ9KLšd.'¸Y÷îælГsP4Â’~¯^½zÉÙ ¶"" " eLà•W^±þùÇ”N­ŒO„v/" " % ðùçŸûÔ4çœsޝ×ÇŽk3gÎŒ)6bw8M<ùä“6}út;è ƒ|‡ð¾ûîëÓÝðÜ[¥JÛzë­m¿ýö³“N:ÉÚµkçÓ´UÔ &xáis2AlÄñàÂÄó>‚#Ò©J¥î1舀$D€:ˆë'YÆo#FŒØ(!‚ZXD@D@D@D@²‹@Z =ÀÂú®»îòîDþùgð¼yó¼í7Öß[îvÚÉ*T¨`؈/]ºÔ‰N~¶5kÖ× ý€s–®Šì#@jp×.ê,Ü“slŸ}ö™}óÍ7Ö«W¯¸Fs&g¯ÚŠˆ€ˆ€¤–néV" " " ™EçÒ§‘¦†`°Ö Aƒ¼CO"G‚¸7ŠGyÄú÷ïo†H{VµjU?à†w^ˆ“h›ásŸ>}¢îg œ’XÿNÌ3$6Ùd/Ž3fŒ=øàƒÆ÷úõëgHéUL({´Ù_vÙeÎq~´¯'ž}öY#5¥BD@D@D@D@D · ¤…àˆS€ ø¨Q£ìŠ+®0R£EZ¼â FæÝpà ñ.®å2ˆÀG™½ÿ~¾ØÈéÏ’J§–ŒÚˆˆ€ˆ@ÈËË3Ž9äÛc=Ò¨d*Šˆ€ˆ€ˆ@,´‰þ‹”itð6lØÐ† V¢Ž]Ò¤uîÜÙÎ>ûlÃUº|ùòŠpúé§{í2{íµ—µoß¾À2ˆž–/_îÓ´…:UX0 '´jÕÊ}ðÁV«V­0§í4,®Š$" iAàßÿ5Rz’€œMš4±'žx¬´H©8 Çwœ½öÚkÖ­[7+W®\`rBïØƒ3Ò‚Æ9ÔÙGàé§óÉ™%-ÑËoP!" " Ù@à#§Ðýõ×_•N-N¦ŽAD@D '¬_¿Þn¹å«^½ºOV³fM/~ã7J$6 …·™ËIMlÄ2;찃Ꮈûî»{aÒŒ3BW5Ü,xvf€W‡Âæe—FÙ6Ûlã‹*7ìL8c*£ˆ@Y NÀÅÁêºuëìŽ;î°©S§JlTÖ'Fû4"vŠœm·ÝÖÛ³"<¢kË-·Œ ×n»ífƒ¶^xÁN8ᄸÖÑB™IÀiÉ —£ƒNNùgÏžmóçÏ÷£7±UWˆ€ˆ€ˆ@6¤SkÑ¢E6ŽŽAD@D@²’Àï¿ÿnS¦L±«¯¾ÚjÔ¨áßqzüñÇíã?¶“N:©Tg#î!6ß|skݺµO=Np]êÞ½»ïdÆ:ƒmM›6õEoРA&‚Ê," ¥B€4œ´¯·lÙÒ,XàÓqòNJ5 ð-•S ˆ€ˆ€ˆ€ˆ€ˆ@ÆH›”j‘ÄvÝuW»é¦›lРA~t>–­×O?ý乪V­êsFW«VÍI,I1{¿» |I ¥SKJmHD@D ¼üòËÞ©à˜cŽI£R©(" " "ÛhÏÀ±÷ wß}×¾úê+# *³iÔ.¼ðBÛb‹-Ê nO=õ”rÊ)Ö¼ys{ï½÷¬oß¾¶téRŸV‡ö—L=zØ/¿üeêq¨Ü" " ÔG]t‘Ýÿý†#Þ\`´Ê•+§bwÚ¦ˆ€ˆ€ˆ€ˆ€ˆ@H¹àèÚk¯µƒ:Ȱ®®X±bÂÈјÅëÈ#Lx}­ E@pT¥JS‡lQ¤4_D@D S,_¾Ü>üðCïÞGC±BD@D@D ì ކ4i«W¯ö…ÁMèôÓO·zõêùWíÚµÓÆ9¢Y³fvß}÷Y×®]ý³òÂ… ½ÓÅYgUö KP‚† /…ˆ€ˆ@A´ã#6jܸ±Ýu×]vÀ\HSD@D@D@D@D@D „@ÊG3gÎô#ã `‡v˜`iÒ¤‰í¹çž!ÅÐG(XÔÓpÚ»wo9d•Í)Ð^E@D@R@àì ¼TãÆ)QJ*Y•ŠVd)ÊR*TR!k–”ú‡”,iAYK"”,‘¥¨,Be ! ‘%´üÏ{šš;wîÜ™¹göç÷ùÌåœóž÷|ÏÜyÏyßç}~/¼ð6oÞ ¥SK\)" " q £ÅF½zõBÿþýÓ¾_ä /ÄÊ•+ûtÙ²e1vìØ8\›‰€ˆ€¤;‰'bذahÒ¤ fΜ ¦¡Tˆ€ˆ€ˆ€ˆ€ˆ€ˆ@a.8 T€–¬wðqë­·ºñQ«V­Àjz°lÌÍš;}ú„]%®•N-.lÚHD@D Í 0]"éN H¯¼òŠ«]ƒ2eÓÜ—)Sõë×GÕªUÓ¤j!" "à+¦ùdú4:ï=ûì³ùJW…‰€ˆ€ˆ€ˆ€ˆ@vH¸àˆ³"fÍš…þù'ÉåË—ƒÚ³òf& >jРœfòÒ°¬g0³,KÍç/É“'»ï¿§ Èt6š3gŽs–dJZ…ˆ€ˆ€ˆ@z à¨B… ¨W¯^zT(ÊZ\}õÕQ®©ÕD@D@2ÀW_}…öíÛcÇwtÎFº‡Ì´3¨úŠ€ˆ€ˆ€ˆ€ˆ@j KôE‹9aÑ©§žŠ]wÝ5ß.¿ùæ<ôÐC8ãŒ3ÌŦ˜~Vãÿý÷_¾uõAn=6«¸ürÿŽÿwÞoª;uê$‘›XU’ˆ€ˆ@Š ðºëçŸV:µŸí^D@D@‚ 0•Ÿ=öX݃Ñk”øí·ßpòÉ'ã—_~Á¤I“2N›2pÚ±ˆ€ˆ€ˆ€ˆ€ˆÀ6 w8âžJ•*…–-[ºEDo¿ý6æÎ‹—^z kÖ¬ÙV¾à{ÞàðAqR‹-œû…H,G‘›ž{Ö9 ”/ïßñ+š,U’ˆ€ˆ@ú`:5FëÖ­Ó§Rª‰ˆ€ˆ€ä8 `Ó¦M®#ÇQèðE@D@Ò€Û¤Î;ãã?ÆÈ‘#ѶmÛ4¨•ª " " " " "i’"8 †B{Ö£>Ú=Œ>øóæÍs:Çúõë1cÆ ÷(Y²¤s?bê5ŠÊ–-¼ª^g9 ìÔû¼™ž8q"ªU«†Ã?Ü·rUˆ€ˆ€¤šÀìÙ³]º¥ Mõ™ÐþE@D@D`;¦Sc°?C!" " ©&ЧO7!¸{÷îæ(|ªLûH*¤ Ž‚n‡v@Æ Ý£ÿþX±bÅ6ñÑòå˃WÅ?ÿüƒ_|Ñ=Š/îD"p Pné<¨ô¦“'OF·nݰaÃL˜0¡µµXD@D@2‡À?þˆ÷Þ{gžy&ŠKxæÜÌ£šŠ€ˆ€ˆ@Š Pp´çž{¢nݺ)®‰v/" "ënºé&Œ3Æõ«ßsÏ=¹ŽCÇ/" " " " "P)…Ö»V­Zà£W¯^øöÛoøˆ"#œmÙ²eÛê´|}óÍ7ÝcèС.¿4ÅGLÛFÇ…„#ÀïÍ€pÇw råÊ`Ê™¦M›†[UŸ‰€ˆ€ˆ@F˜6mš»fjÓ¦MFÖ_•l$ð믿:wçÓO?=OÇ$" "A†Ž¢Q£Fà¤Ì%Òjx ƒHªª" " " " " $¶Sß÷ÙgçBóÄOàõ×_…EÍš5S²…Ƈ~ˆ;ï¼­Zµrù¦ïºë.,[¶,t5½Ï0tœ?þxX.ñ¢W|Íš5–’íD'6bJ?ŠØ$6*:W• " "Þ~ûm´k×={öÄN;í䮉ңfª…ˆ€ˆ€ˆÀk¯½†Í›7+š¾ " " )%pë­·âÚk¯uÙæÍ›‡råÊ¥´>Ú¹ˆ€ˆ€ˆ€ˆ€ˆ@æH[ÁQ0Ú=öØ]ºtÁ¸qãðÖ[o9qÑI'„Ò¥K¯æ^þùç¸ï¾ûpÚi§¹Î¼aÆå[Gds÷…õË¢T©¢Õ—ƒ°œµC {ºgñ¹J•*E+T[‹€ˆ€ˆ@˜?¾Ô6iÒ3gÎD‡°hÑ"ðÚI!" " "Xœü´råÊBwÂ{PF‹- ]W+ˆ€ˆ€ˆ@"ÐñÎïõë×3 ”/_>»Q™" " " " " 9F #GÁç¤L™28ùä“1jÔ('> ˆ‹ÂÍÈøþûï1a„àÍõ:CXÆ<¼ü2е+°ÿþñWšƒ®tÆúùçŸ1qâDÜ}÷Ýa]²â߃¶ä`1û8pIÑÑÙgŸíܧL™‚ $¿BÚ£ˆ€ˆ€äö54nÜØõOvèI/L!¯d1búõë‡zõêᥗ^’Ø(Ù'@û,&ÑIšK–,‰ãŽ;Î=6mÚ„wÞy´ƒå ÜêÕ«³ø´eÿ¡Ñݨ˜É᮹¦hÇ:fÌüûï¿ÎíáðÃ/ZaÚZD@D@Ò€À7ß|:=/^—\r ®¾újT¯^= j¦*ˆ€ˆ€ˆ@n¸ñÆqà 7¸¶˜éÜçÌ™S`:Óµk×béÒ¥8óÌ3sŽŽRD@D ­Üu×]èÛ·/>ø`×g^¡B…´ªŸ*#" " " " "Ù2ÎᨠÜt;âˆ#0pà@¼úê«xæ™gÜ œà "–žŸÿý70c0{6ЩP”  ýõ¦M›æ¾¥çùV­D@D@b'À³ZO:cÇŽ•Ø(v„ÚBD@D@â"°qãF\|ñÅNlÄ´Ý .t¢£‘#GXû'¶lÙ¢tjÒD=z4®¸â Ô­[×9U¬X1Q»R¹" " " " " 9J £Ž"³C9|p‡"= üù'Ì• xÿ}ïñÞ{Àòå°ATX§-pÝuE«÷³Ï>‹?þøÃÒ²Y^6…ˆ€ˆ€d ~øaì·ß~hݺu‘AD@D@2ƒÀŸvÛÉfÅ<ÿüó® ~úé§Á”ï;vÄäÉ“ñÉ'Ÿ víÚù†éÔLƒªd¸çž{ЧO×61Úž{]k?" " " " " 9D kŽrèœeÍ¡rœ”}®W^ Lœ˜!Úµ˜Ní­·`‚±¢êã?Ž%J K—.E+H[‹€ˆ€ˆ@š˜9s&¾ûî;ç®PŒ¹G" " "  'ðã?âØcub£ /¼Ð\yg8±wLç:1eM¸ àhŸ}öÁn±>ß Œ3½{÷ÆA¶C•*Uò}*PD@D@D@D@D@H #Ž6oÞŒ/¿ü}ôvØaÐvÿý÷G•*UtV3ˆÀ¼y€Ýÿ¢aCïQ®œ•_»v-æÌ™ƒ–-[ºï‡%«$(" €eË€ªUÊ•‹X˜6È5L¡F1m·nÝríÐu¼" " "Ÿ~ú)Zµj…•+WbÈ!.ZpE˜Ú½I“&6‰f"† † *l[L¡ÒÇŒsÏ=wÛgz!" " ‰$pï½÷¢W¯^%²ÊØF e‚#Ú‘/Y²†ì¸ãŽQ¥™?>xà×a÷÷ßo;ˆÀ‹úõë£sçÎÎÒœB$Ez(YÒs7JD-Ÿzê)lܸgŸ}v"ŠW™"=wß…M'ƒýà|¬Xûrwß ëо­)"ó8Ð9wî\´oß^"ëœÿ6€ˆ€ˆ@2,^¼ØõUüúë¯xä‘Gpþùç‡Ý-]ŽÎ8ã P|íµ×n[‡} ¥SsôGD@D Áî»ï>'6ªU«^~ùe›ç¦‰n F®âE@D@D@D@"øá‡,ÓÑ• .D‘½’.8z×ßÙ ÷æ›oâ¿ÿþsdšÅMkæ×Š?ü0n»í6gU^Ðj0ññ /¸uË—/_Ъú<Ë 0Z™2e,E›åhSˆ@ª˜ Ž: öc³cƒY±§œ4h4mšªZi¿" J`ܸq Ëc÷îÝ3ôTmÈLAÃûINd™>}:Ú¶m[`å;vìèÒ¦1…M¿~ýܤ*®Ì29 ú#" "@ìo¿ì²ËP£F ×þ(@a«hˆ6mÚd¾ w;—èõë×£Zµj××ÂÌ&P,YÕçkРAèÚµ+^{íµmb£höÏ‚·ÞzkD±Qp9 ,@Ïž=cÚGðözÙ˜n‚¶: téÒ™}0ª}f°ß:'62;k¬[|ñ0u*¬…õDG™}tª½ˆ@ p°“âk¦=ñÄ“¸gíJD@D@rÀ´iÓܤ¨âÅ‹;wÁHb#ÒaºS¦¯ùþûïA·Ý@PpĶ{¿ýö |¤gð3ôèÑx ÄF¾ÓU" " " " ±X¸p!5jºAï±Ç.{ûFÙK i‚£ë¯¿“&MŠ™ä¼yó0eÊ”·+UªTØeï¿ÿ>FŽvY2?¤ø…uácõêÕEÞõ† ðã?ºY–E.,E<ù$0l`‚Ƅݷ)D ¥˜NqúéÀn»y¯õW²€€Ú¶äŸÄ3f€ö£—\r‰¦™cšBD@DÀWjÛ|řх=ôÐCèÔ©vß}w¼úê«fL3)Ûè]vÙwÝu—;~Š>ýôS¹eô·A•Ì'àgû– }’™Fóg‹Ó—Š˜Ês¯½öÊ»’Þ‰€ˆ@Pû–…'U‡$"ñÖ®]‹nݺ¹~”+V`àÀX¶l™úE2þÌ~II©Fûñ©tõ;›ñfèŠ4bĈ|‹öÝw_\wÝu¨S§öÜsO®¬w®I\wÕªUÛÖÒ”-t:bj­TÄæfrÚi§7ä ÎxìÝ»wÌU¡cÓøñãñÙgŸ9± à`cÅŠÝ?-;C©Ì” ÙËW]•˜SpT©R%œp ‰ÙJM kœpÖY@É’°àˆ#RSXöJÁg3ÛÿjZÄ?ÿkÖ?ýä=ªWjÖL‹ª©™C@m[jÎíñyÍtÁ¤¦Ú«ˆ€d1µmY|rc<4:+0p€s6ªÎëå(£\¹r8ÿüóÁ´j¼‡ÿæ›oÜ–J§%@­&"à;?Ú·lë“ôr |ùå—Ý€Î×_íú@}ôQ(Z Oˆv-"4jß’†Z;¨ ücãGy$>ÿüs´lÙ÷ÜsKõuZ1£ $\p´eËg•Jé \zé¥hܸ1vÚi§ÐÅîý»6XO¥rp|ðÁ.¥HÙ²e·}¼ë®»‚çGuÎ8ã ¬\¹Ò-û믿ðì³Ï¦ÄéæßÿuVa±Ñ¶ÊÆðâÛo¿ÅÕW_Å‹çÛŠ\2Ñ…\|wÜq¸í¶Û@é?ÿ Kw´k;ïþהߪ&ûôéÚß+²„€5Pö%÷D2¥HDÍ¿ÿ>þØû²Ç´aW6&~ÿ}ûøOh"¸è¢íŸåʫ͛a*N V­\9b_ŽSm›/c.„×Bt|<ÝÜÒ(¨Uˆ€ˆ€øG@m›,3¹¤ÍvmØ·o_çNT¿~}¼ð ¨\¹ṙÄûÐ{m† Ý–Ë—/ï¶—à(fŒÚ@DÀEmß²±OÒ¬iQÄŸþéú‹ÙÞÐYï¾ûîs}ìiQ9UBD@L@í[‚«xˆ“¯M)6h_Ó-Î&ßï²Užˆ€ä:µm¹þ Ö­[‡6mÚ8±Ñ1ÇãÒ¨Å#6"É5j¸ÉPœøÄt¨|_•×Ü H2¢´oÙÜ'™äÓàûî^{í5Ô«WϹé{ì±øðÃ%6ò² HgjßÒùì¨n" ™H`ãÆøå—_À Ë—/wº^s>ÿüóæ©`¦ QÄï6N8lØ0ì³Ï>NÅ&Z%Ë”Hôñ<ðÀyvAG#:E/½ôRžÕ8ÓÎH‘â @æ ׫¯¾êVc2Šv¸ßd÷MAU¼AÛ1æ8 N·óÎ;;§£m¼Aƒ®StÑ¢ENPÅ”çÄÛV@IDATr :;]sÍ5àÀ$S®¥cT¨\}bjÆ|O=õ”eˆªiE‰©’J-*³…vÎF?üPLf¢º¨ã™g€½÷†ýóÃòE½YÄùå}úiXKq5·éÔ±þöØ`>ý0+l'´òJ ÿ—â¤áÙ3·Þ*ü8m¦už°tŒŽéÝwŸ|â› 7£Kiù,Ñ£Ž£Þ,å+~õ•Ç‹O·ßËwûÑöÒõ¥¼ré[µm©97ÿý÷1±ãèÜ SS íUD@²“€Ú¶ì<¯±Õ'v ÜÎìwÙop± ñiùiRT4e_qÅxî¹çÜd :D³‰Ö_ ¥}Ëæ>I_!'¹0¶WLûÉ´i¥J•²n˜Ñèe}2éÚÿ›d<Úˆ@ŽPû–#'Z‡)"pQPDwgþ¶ò \ðºó½÷Þ³¹û6y?BP ºvíZ—¡ŠzEîH¨àèûï¿ÇtùØ´yeÚ¯bÅŠ>*ð™ÛRML›Mf%Öe’%8â?Ô€»Žëùi4|JÁÁÖØÑÄllÔ¨Qà#÷Ü´iStéÒçwÞ6qs«Ož<;wγn.¼¡@mõêÕèÙ³g.nÞcœ26%8þx˜¢æÿŸwyð;º¹XabÞz–†Ð7ANð~Šúšÿÿt6â3Å ¬g´ÁtYtî±ÙÊæ/ Üx#,Ça´[¼Uûƒ eÅ*~c½Ï=×ZÙ kó /<²ôJöe÷Ü9 (kß} ®{¸%TÎ ËAóà?6¨] àóÚk=qÕÖtùŠ8áo{ Á˜'ññÇ=ÞùVŒñº&1=d¢„“L·Ø»7pÒI°W˜R°6Çrp±®b<¬L^]m[êÎÞôéÓÍØíG—æEÉ©;Ú³ˆ@öPÛ–}ç4Ö#¢(¨k×®`*ö1–fدûH¦;§û]'”N-Ö³¢õE@ŠJ ¨í›ú$‹züÝþ-›\vË-·8×<ºÞž`ý0L¡Æ ) È%jßrélëXE@ü&°aÃÌ™3Ç Œ(4úšfQS±ÿþû£L™2.]/µ|0…eËÂŒBo¾ù¦ ‰†7vøé§Ÿ\Zù:uêØÐ¦m*r’@áÊŸ"`ù†®Aq¸ fïMÇ‘(âý÷ßÏ·¿ôÑDõêÕó¬FñR2‚7~ÑzŒQ±bŘwËàPW(Ú…Š“çítè väbÒ©uÖY¹wø}û¯¿ ë1|ü˘ ˜K%ÅvRX;¬ÁI›øî;Opc®]7Ö¢Å^µiÓ<{í\y%pÎ9E?FrûóO &ŠT+sV³V(H¬SжV­X\x!¬÷84oÌŸïma¢:ð;Þ²¥'2âÿ?d±ŠûçE‚åVuò¦‹ÜÕW­[{NK‘Ò»±ŽtFb)Ö¡è¨%t`w…>”+ç‰álÈ ‚V­*t³˜V +º2ÑMŠb#~?($;ê(ZÅÅTT.¬¬¶-µgyìØ±ÎiiV" " þPÛæÇL.…÷Øt6¢›Ñ‹/¾è›Ø(ÀäF›ðÀ{øV­Z>Ò³ˆ€$œ@QÛ7õI&üE½ÑÁÿÈ#tb#¶YͳÉgEQ+Š€d µoYr"u" I'ðÑG™ß@ìeã¤íÛ·Çý÷ßïúAzÛ„üY³f9=Ã\3%àÄwÞ‰¡C‡º”htÒ¼ÒÆÍ˜U‰Y¤†pì¹€`ÿÇü›o¾Å9Ù_‘“*8 N Fº¡B HÄù k¨°‹&8à€<«ý@ç$ÄøñãmÌÚ­-vÛm73¹6æ½>kƒöT‚3WN=õÔÀÛ°ÏìȤ˜+K—.ÍçX–ÊgêÏh<“ˆà¬Ôi&0áxèùOÄþÒªL $¨F¥3Ž¥Ù³´ÈÕc)¦Ð²Žu›&å‰p˜«Z5/½”5 ¾ÅoxÂKMuðÿÕfã‹/`­pÁQoºmEº¨5oÜp¬5„ýy)ÙÌÌ9&m[që K¡àÒ’…~úž‚#ÆÖ”Þ›0ÿþÛ ÅšN-Pë(´ È‘nOÄÐeéÉ'=qó§^uP¢D`ËøŸ{ôðÜŠ(@2':»¸ß ß–°…ï¹§Wº-щiÚ,çk\ѯpÓM@ݺÞþyœ–^Ò¿z®Kt%²‹—FŽ8üåñó<Çü®°ÌQ£<• ®êòü)¶PÛ¶ EÒ_|n‚¿—ÍŽéXâ1'½ÂÚ¡ˆ€dµmr¢PM¦*¥Kðu×]‡CÌ%ô]›HÀ]¿ƒ÷ðìÓØ]î™~£Uy" µ}Ëæ>ÉØÒjÓY}ôÑ6?ª]`}b[ßû<›4i’VuUeD@D YÔ¾%‹´ö#" þ4Ó„‡~Ø—³ßƒ©x«V­ê\ˆ¾°qWfXâg¼ÞdÊ´Hqƒ½1ƒ7.\˜oÕ¯¾úÊ™¨aãj4)r—€´&.BS¢E+bBŽøe6*Uªäì¾ëG·”siSýˆÁƒ£J•*·Q?¿N—š 8ž)²¢ÞŒÇìÙ³ƒß¦Åkê?¨—HD°S„ JZâ',Ì} –ÚË–%lq¿P¤S˜8$°ŠxøÝ¢“ Kt{¡Éìñ°ß~Þ3SlQða9<­—°œž¦† ”Pø3–,ÝŸÛžB‘hDG_~ 4kæ ?èºDUQƒ©¹xÞ òœ€˜âìµ×¶—Ê”bäF× ­îdÛ†¼bçNÉ’… ŽØH[zEŒR@ŒoÂ#¦X¤›Ð;ïeËznB<¦x] ªEMÜÏ=Ý•Ì1êàù¥cÖÌ™ž›T¬êÂõë½ï Ea¼p¡Ë¥‘rßAŠŽè,Å}P`D¡‘ýÆ:áw)L+jüïÀ3Ï–Îm(Û ¦T˜•Ú¶T~ î±ïû:v‚Œ²qÍråÊ¡FNCpæ™g¢oß¾Îå›T_³fMó¸ßÿ½¯ÇbènŸ¿ßfYQèŽtÅWl[eÉ’%xâ‰'l¹uÔZ†mëEÖ(‘È#¢ò-8væ`}Aw£Í!îLK«ì˜Þ,‘Á¼„œuÂ`ê7ZŒÅ,ƒŒ¨W¯*T¨xñ™¶h´>ãEƒÿøé4=aœrŠ÷ìçß–vjΜ9n–ê{ìágÑÛË¢#ÎwÀòµyÊ) +,—eZެ‰Y Zy:ÑEçüó=Å-ëÖy_õž)B‰ÆE‰‚º&ÑyËòw‚)Û,O(N<1t¯Þ{ŠH(ü¡‹ÍSOy¢•ðkíSZúq_|fC͘k½÷…ý¥°‹ßŠ^;¬°µý]âø[ª¥1?«]`8¾•)óiŒ¾|¦g‹Ñž£He¶ÌÜô¾¦‹•ÂutªmKݶ¦`0 u•ОE@D Ëè¾-ËNhŒ‡3Ö\1é~|×]wjcÑZ]D@RJÀö-›û$SzrbØ9E±¿X_Û©’ê—ˆœVÈVjß²õÌê¸D@^yå 2Ä¥7£CQ±bÅ‹ò=3B¿~ýœ°¨V­Z.…ÍWBt#ò;.»ì2Kn2ÓM>Åú™FþZšMXðV! U«V-aªé>øà<Ÿ…{<£†Ë)ª^½z¸U üìW $¶F"mÒ)t™µ™ˆ€$ƒ€_í[6÷I&ã<uÄrÒIýúõѵk×¢§íE@D ã ¨}ËøS¨ˆ@`Íš5ΕˆîËŒWm¼q–2›O8M›Ï;ï<ókx Íš5óÏ>‹Ýwß=Âü]ÄŒL<òh~rñÅ»4jÌ´t–eÉáõ«BL ¸ &8xóM¼Aw” hܸ±éLe|ûí·`‡b Âýs–åù‡~Àõ×_¿­v\²®ñF°»Ë %Z,Q6D4Z^´eÑ]j“¥‹â€gàí¶áÖ³ßM,Z´jÅ|áÖˆÿ³µk׺`Z­(ÖÝ1ØÊ•ž0…+Ñî‡:sQÐBwnG‡šCõÒ•ï•k}‚×§è…Ѽ¹{J‹?L=ÇTWåD+š³Ü¡–G1ñb£ þoÑçÁcq{žG~‘ìeêy;Šó¨2¤ÈŽß^ø¹]ˆ¤cð7/ð[Çg s9Ô¶¥þìÓ>Ÿ3[û÷ïqVCêkªˆ€¤;æQ´q¼?â5~.F6·mºŽ‰î}¿Má÷àšk®A´ÎËÑ•¬µD@’M ¸m£Ëw®¶mäîgûÚ‡˜ª>IÞó¸~ás¨ ~²¿sÉØÝòù}¾õÖ[u˜ àÚ‡¤à¶í¯¿þʉ߽H§ Û7/¯Y‚Ïu [I$Z&"]xû KÒ¡ˆb£6–ùåã?ÆÿlzÁ‚N¼óØcå9èu–‰æ¤“Nrb#NNž;wnRÅFÊÐI‰}+?ýôºtébä;ÚðŸÿ4F \Ó«m+R}œT‡£å¼Áýè£ò¬Õ´iÓ<ï {ÃÊàuZ ^ïkÞìÒÞŒ.B ªúzR4ÅY(suG¬7÷¡nFd¹ÿþûÕëO>ùLkwøÖÔYì}é£â šÖ0C^"Ò©ñÇf s7š:˜0ÁK÷ué¥Ñ0¥©%²„%É*WöRLÑõ…®:|¼óŽ·ŒËäÌ”9:xïcù;¾·v"¬£b©G`]:1…– ÀƒÀçÑ<[:ÂŒˆÒ¥=g£×_÷¾Ø,3âxUIŠëèFç1ŠM)eJÂ4ŒÏ?ÿÜÙOªÆ›¿õë×›ñU ÎW3ü9›Û6¦å¹´mÎ9çðú—÷<ì´nݼ^ìcÆ7ˆ”v-^Ž«VyÃy¦#rÙŠ嘑(] StêÔÉÕb©=zD¼F§'}1ضÅb,Ø¿ž3‡@BG¡GÌïw©‰6"‰`^xá÷Å F‹àˆ_ÚiÓ¦oîRåùÀ‡7º¼ûî»®¤Rææq‡¹Ø”(Q4œ¡7÷±v‡®:;)Úî[·®™ðŠÇ<ÚM"®G£fé2¡¦¯A ¹1cÆ8{¹ÓN;Íײ]aÖyo¿þ°{ࡇ¢+ÿ³Ï€Î>ðFzȰR%oÛOÜ^½iû4cÌû0…j\A—º.™²4åA¡Õxî?f­çR©¥¼R ª^vs€%K¼4y ÚMÆ[¾<0~|zUáL[IqëL_Iy ˜úsW ¦r0²¹m«a¿•œ90ƒ¿»i¼Xçòí·ßžvb¨4Ʀª‰@F°ËV›­äeÛÑÈ4êã{ùe¯#€šy^jòÆ>psÏÎ Ú3çZdsÛ¶Ï>û8ê+¯¼’k§5¦ã½÷Þ{0‹÷Žé&4Žé@´²ˆ€#лwoðÁ`êvÔçbøÝ¾¥KŸ$E³eÊ”qƒ²¹r^y­Ævº)D@r“˜ù`pâ÷àÁƒÝë\ü“­íÏ%Å´Ø„Üë®».O­ŽYršÀ°aÃ0hÐ §¸Ü2¾ :4ßTË–-%1u³AQóðý÷ß; Bß¾}}cHtÓ=Y?!`º 7tÆÂ™¬ÄL”\¼58T~Øa@íÚÞçì[©S§ŽÓ{xŸlÿKOŠúÈ´k×Î=¸”Á5l;§l|•Дj¼A¤X èqÛm·h I· ñ!ƒÓ{›ëI,EÌ[œwœ3êÕ«¨‚/ÏtD¸çž{¶•uíµ×ÆTÇm†¼½¹Õá(t€œÊÇT‡5˜½›—…ªBkCå?gôRÕYœŠ&¿£[7ÀR¶ÁRÛ8§¢ÂÊçÁw¬E€µÞÄF¡ÛÒ͇ÊUº'ýø#,Ñeè…¿§hÉ;.îFÖXº´hC†Txý3ys¥UËœ³h³`aƒM`º7EXjÛÂbIê‡ìdæuó/3M«BD {˜éŒ¹¡/¾˜?›+oÜ9Á.m­3!ï13K4o;ØM0³-EM4`´Ì9jÛrþ+Úv³m¥8뢋.È ‰hß²±O2N6]ú9A—i)7nœ UVE@D aÔ¾% ­ H:.Ÿyæ™NhH³w,ÎHË:ž¨ÉŸyæ_kcÔO>ù$ü™‘¨xÃÑ{î 4kÜr‹7D}Þy°”m@°oFÉ’Þú–ÍúS5„«û›Øªa oÇQGÁÒ¬m_W¯r‡€uE'6úõë—gáË6í–)B( Šc.¾øb|óÍ7Áãä“OÎó>ÒªýBÕßtTâÀ_Áz2•Z Gü 'œ`†6})>ÔNl'¦áŠ!˜18B‚—%ëõüù0˷ĤSã2ÓÈ%¤ã˜öÜLÅ™Ѧ:ãùâÔuŽ$q´'ÚT[üÕæ#Ö \Fóæî)¥˜&Î\¾œÌÕþ?²>Ž>fiÆé”Y¨y€t¹£ës92LîFpÙžHpä1 ù«¶-HŠÞN5K’O?ý—]vY7)ªšv+iEà‡`‚s€.>™lŽX_^îQxÄ,£ÁAcÎêÚxøáà%€9*›‹ƒ—7ï’‚ßqµìý3l®†Ú¶\=óy›3ï~úé'p’P¬÷×yKÒ;H‰jß²±O2=ÎXäZôïßߥNºùæ›#¯¨¥" "åÔ¾eù Öá‰@`ª0ê^z饈GEg¢cŽ9“&Mr©Ó˜R±aÆ· ,¤ëÝŠ+œã…éE ßr¸Œ"£³Ï†Õ– 渼ý6À~VzÁPêP¶lÞ=y¤çÉÁ¤6‘Â4Qæ`ä•m HåiYæ(–è*ïe©žB!TðQ¨sºùr]ýõ.ßßQ&{û€i¨‚‚‚'ì@¼óÎ;Õ‚ ;ÿ)ý Zž­¢³ŒEÅŠM©çŸTåÇúõëƒßúš)Æ‚ÃO¡Up¹±¼d)¢ªÑϘ7ožû¡åw« %h\û³Žhé…©Ê`¶UÀèѱsê©ÉÄ.·ØjêïÚ“'æ&f²[/ž¿¥§_iæÞ˱ì,ÌÒp[˜KØÓ¹J‘:æBg¹5½”…¬Å”)L»Ý 2u5KÛ=«mKSs‹M)(]º´sîK©"~,«±Ë&ËK´K_WÙý÷÷Ä;¼QÑâ§ì`((âmΕWÂ,‡óWƒ—r4Çä͹Ýå ŠöÝ×Ó²¯Y“gQÄ7ì4(^<·]ŽÔ¶EüŠäÄBZÐÝh¿ýöC7º×*D@D $ª}ËÆ>Ét?Ýœpò–åèÑ£‡ úبBD@r˜€Ú·>ù:tÈ3fÌÀ¡‡жmÛbܸqNçp¤Îb^² â0›]ø®Yšß`ä“m •ýþ±D•*U¬´F,›ä[÷‚ ˜Î˜>hÝÚ›èHEHƒ{}¨¡#C a5k†~ºý=˦”£jU˜ `‚ŸàøõW`ݺ„ËQ‚w©×) `‰*ýæÌ™ãrôöF7æ"䣠 Xˆöaáâu›®K·$æýc^ÛPwnCw%?g1N·ÿšçž{n[u80X¾|ùmï‹ú‚yʃ#VÁÑæ\ ?ëTlL/M æ‚ÊI?cĈ.Ó©ùfcŒ>‚M/}”Þp¾ïka‹Á’þæÿõöu'QfùÖ›åÊY²Zóæ0OCÏo°reï ì·Èz‹€N²ä 3ô0zön½æM ´oó „]ÍÁr|fè%¶ÚjÛË7ÚÒ)¤]¼x±9™ôFèõ@´eh=ÈÔçS€sûí°ü¼GÌáµjyM1o†yãl“ÆMhì¼sÞu“õnÝ:ODds0Ìa%ü^m²“Íx ¿ŒÍ—]öºüé×\ëпm‘ƒo›< 2“^yhÑ"üvÙú©Ú¶l=³±Ó Ó~|ذa¾ö ÄV ­-" þHdûz’ }’þ‘÷¿¤váz]Üq%'ã*D@ÒŸ‡±˜›Áy·¼W ~>â€÷}ŠØ ¨}‹™¶H-6‘}šMn§ùMSJY ŽKŸeÖâãm¶ãÃÖñÆLM 4piÓN3+¡§,7'=ÑA”¯ýÊ’ÏÓQý¥– –ÑÍ÷0釥öú$™üÇæ{å N¦œ3g_T©b ¥"k $EpÄÀ)æ0As F—˜÷V¤œ„/¼ð‚STVX>餓 Z×眈úõëƒnJ ,(¾üòË<‹ø>x}¦kҤɶuŠzsO§§àHÁQ`&¶Ÿ‚£Í6‰çŸ6rûrÄÉÏà÷ßz9/ü¬´Ÿu ”eÓ–ƒ0ðNÏÉ&0|¸'j Þ¯©•]˜ÊY‘B€Y^\ç4eö–.Ÿ =#cT§ð’ºkµmIÅ]àΆÛoJ KÕÈ´­ íxSÌ,¦èØÑÓ’Ò½'4¸ž]"‚†ƒ÷ÞëéNi\ICÒ¾}Ë´ š2þý×[/Dïï-ôñ/†L·ï;ÖâyÌfëÄC´'æÌ¤à0Gf¼'FbZ¶@0Ã/÷k©œ)càó\xVÛ– g9ò1r üKù¼¿Ùžq"“BD@²@"Û·lì“LçsÎ*¦ÓæàU¨»T:×[u\$ðÆ»ÙÅltÊ¢vmos±b¡Kô¾0jß #¤å" ‰ @#“™fBñŒMXg¡m¶bÉ’%·=ÓÐäùçŸwÆ)t'ºÒ¬ËitRy«ÁáÖA7Ð:ßn·Y‘<ð€ùtrcÖߨ¸mU³ûyöÙgѸqãDT=ê297Ÿ?ƒž ”6,XtèàùvPlT ¥Ï=·ƒõÅúgàâçñ¨,ußûS`A¥ðuðàÁ8ÖrðpM@‰²A`°íNKŽ3˜†³DüŽ`¡%K– W¯^1í‚yùÄ!‡â~ÈïCoî ¯Y Á| G šR÷Ýç ò”+ç_MènÄà{BbŸ}RlÌ…®^í%Ç<çXOyþÍéÂD‡#Ej„»{¤àˆŸG™‡55Ï‘½^q…'8âÿÏæÍrŠpÚÕ¶E€“¤Eo[²äWÌ‚„×/¾ i“t ÚøE€B f¥é$L·Áå‡/ç%0gîГéÌè†dý®“˜¶¾¼d¦#gùÐ02QÁÔÂ>1Ûj°(žýÝ}7P¯žÇƒu¾ ±[,—>ŽÇÕªyîNcÇsç/Éþ×jÛ²ÿv„ìðûÙþÑ9x±#ï›" "Ù¾ecŸdºžrΔgßæî»ïŽ+Øw¡HºÂ~öpÜqÀÙg´½*o¾é9æZ¢ wÿʼn œÈÂI+ýüùçöçï¾óʾOÛ^RøW¼ï¥ïÛr=Ô¾åú7@Ç/É%ð‘e¹yä‘Gl’ÞD§U ›9Želæb³Oç$áp"q¦=ãuݵfk>Ò2nÐiù³¼cê\.Kf°=cÿ‡5ÁÒ2ùò-±•ÌxÉ‚èrtðÁ)Ûך5¿¶¾Zê#4Ùº`R™½$i‚£¦æçÏthßš‹Ì'Ÿ|ºÕP(s]ÍÑ5è`ûVRAOp{þã3‡b&Æž!Ž:Lmð¢,X Dû6þ@¦:8Ó¯Zå ŒxclÆ$.ªWB2ç-¬wüùÿßÿ&…ˆ@ÊpÊþÝ=l£FyG¼/µùa¸è"OxT£†?Õd¹,óé§aÂC€ŽµÁB'ö¢RÔ¾HèYr›À_¦¥Àˆ)Ð8ù—Q«V-—iéZÆù_µŸL4·ÿ˜rfS×6mÚÕ9*‘ÀØË’ðþIéz”Á|ÜÁiΨ„ v UCÖ´Q^¶¡µ.÷ÍÍ'ÅI›8¢±5Žg^…,Œ{mš8ä‹ändéýLŽ <ú(pÌ1éK‰çF%:Ô“Š¦omU³uë€/¾(º…HúG€3)8jÝÚ»úñ¯ä¬*Im[jOç¬Y³œ½jG›*W‡*…d8 bnºÉ;Zæ† Ž~ùfEì¹…*gƒÒ è”S¼‡_ÿæ€ì:‘Nè~ù~ùrO”c}ð£#Ù\“-•2@ÓV¿æBP¬ÅΛ4…ÓO÷:§9c‰Yœÿø#ÜQÁî·¦a£ÓÒ_ì~¥,üTm[žÔ(i‘Y€u5K1ÞkÓο ȉlßÔ'™¼oÉ]wÝåÚ§Xó“WCíIr‡Lï¿à¼owζúúëø'SÓ(#Ôñˆ“Eè”´b…—6{þ| M€éiBæ¢ç©K¶¿Qû–ígXÇ'©%ð›ÍŽ<ñÄñÎ;ï€ãôݺus[…B|pxƒiØLàúï1c»“ÛN&¤ÑùçÜ‘¼¾½x÷º‡¾­+Íš….ñï½e–]ŽÆÚ·‡™ƒøW¶JÊlÛûv±ð‘Ìxî¹çbÚÝçŸn¦&÷ÛçÛ/HïÞ½oó=³+ГO>Ù),¹ömoX’àhDYóyut’ʶ øŠ‚# ËÚó—,Þxùeïn!]R§tœ Ïï8s‚pÔŠ#KŠô%@w#ºgE#çMߣȮšÙï)hµQ„ ÄìþhÔ¶…ç’ŒO×™PñSP<=jÔ¨dìRûÈA¼|eÓìâËÎM lBÅ@~àá3;Jé¶sàùK4ga³ö\ŒØyx0 J‰²üÍ_“¼Ÿ0Åo˜9i‰BE ÓÆ›86ÑÀ_“JÖéáhEL·¢1c¼ZrVn$ƒX®{é¥ÀW_ýîÎ{QŽ-S¶UÛ–)gÊßz~iê»SO=ÕvŠßjÕªù»•&" )&ÈöM}’É9¹Ëí"|ŽMïÔ©“›ˆ›œ½j/" ‘PTÐ$‘x37ðÞrøpoJ… Û÷N^N±¬; #®mà a×°ÞœIºôæb¨}Ëų®cä`ÿ;ÇØ)6bvFeòQ”ÚµjpºlYoÒe k‚íÍK/Ý»ãÇ/¼àMìС({ó¶¥È)0ïžJ‰ŒCe$r*; Ø×[‘NÚ…Œü<@™}!ÁÌɼŠÝìXÝÿýoSölîsîsåJªÀAÙ5kÖ8Ëav„ÄüEç/|0*ô8-Þµˆâ{PhYZ!±(8bt‡ê-ÕßdØao´·(¿ɬoï+›Ú6?OÓæÂÅ´²Ìï\µjU?‹VY"ffµÉ;Î-hðà¼@øžÚmº ½újÞeѾ£±Ëaú´à `ˆúzÞ\Ó¨±  x†)ͨÍïÙÓѤJlÄ:rFαÇÂ약ônÕ;šÏ,¾ùÖ‰TªÍѯcÆ-n¦ÒرÀD·ë`†° Ÿ ¨móh‹ûÅìÓÚØôðŸM=øä“Oflšõ"bÐæ" "P$jÛŠ„/ªén´Å&«ñ^P!"žçsR€sÛmœ~¢|ú⋞»íêÕE)%ò¶LþþûÞ}ñï¿o_—Ìœ7N±ÃL6œƒ­™tâœs¼¹¬Þýõ“€Ú7?iª,ÈÁb£Ì6ü–[nñUlôï¿pý¯¡D˜6“êœdI÷à ÆìÙÀ„ ·?í4 sg`íÚàµbMsg¶›–ÑM!)!PÕFJê›õ;=ÈöÖÊã°ÔrN<ñÄ÷–?¡G`þÉ@tæ¯SÄ?xŠÊ»ï.zeFí8t0©'…GqÇwß–ªÇwIÝä§?(Ò—À»ïz>¹ ¦oU3HljÛüB8Ûî,Æ[OSk›z@D…øMàõ×½Ù4Ô.œ·tç@¯^µ²Í›{ÎBfÌuð&¸vm//8-t³%¬ßO=íˆN8øðCÏ&¹h%…ßšQ ÎŽU¤Ž€Ú¶Ô±Ý3SnÓw…Ù·Ñ1ð”нРô^D@D ,µma±øö!űMÝ~øá‡ãˆ#Žð­\$ÙFÀæ[:h˜püñ§Ž÷¸9ÉäÆM›â-¡ðí¨)2àDlNF š:*ðÎ{fJò3Θ §ÿ¼ËôÎjßüá¨RD “PlH£6ÈT8Cø£ìCÐhcêT€®Dt°ãäÅÐöäÌ3=1)Ž ŠsÏ>þØK³I?¦A³yÉ ÈX)q6Ç·ß~‹W^y>ú(æÍ›g6ÿ_Ù?f¯ô2ä4… jn´+`Þn¤'ZPÐá\ûUzI†·Æ–»‚Ÿ¥Cüô“W‹¢æ~ÝFÌúöíky”k¹ÁÙèZœöÀd—„YÛV§»ƒw+™Xñ|0Sjœ›õ¤àȃ&‘ÎÍã×Q‹@!²¥m+ä0£ZÌò(kwê·=*fZ)vÌÊÊ•´hN§Æ’èxCA8S«1=—]†»Ù4Ñî…©¼8ôÖ[³Ë„‘ã>ì0½ÔŒ–KðzdѤ2Q¯ž'"cÚ:ΆR¤Ž€Ú¶Ô±ì™ý î.0k1Þ3^vÙeEzˆƒ€Ú¶8 E¹ ]ì9aTîFQÓj9A€CAœøÁ9ÂàX»Y9IÆ2УL™À’¢?³‹ýùçúõ‹>Ѥ°Ú˜™†s¾ ³o¤àý§ÍGCÓ¦ÀwÏ®ºÊk;:v„¥q5ò„¢ñöͱö™góÛp}´ÑI!™H D²+½Êü$©$d¾Ä¿ÿþ;ßîw´žùãÌ}¦¿É¹÷Þ{ï|ËsáƒSÍ3ôµ×^ÃÌ™3Ýán6ïЛLê>Þ®<ëÙÃÎ;ïlÝïš:>Hok–0Ï4²%Ãt*=Mÿd9Éã¯Íf“ļæ<æ©&Ým·ÝòÆ»&:¦ÿƒWð…)(˜8“‘)G¬+ÅQÌIòÈ#ÀС‰½â¾ñàÔLšÚ/¾íµ•äliÛü8Uì`þÎzÓ6%ˆR©ùATe°ÓÔtüØwßí,Š|IÄ5™]–³;™ÊŒ®GÌ~ÒIÛË÷jÃ/¿8·µ±}p?Šä¸þúäïS{ÌO@m[~&ÉþäÚk¯Å¤I“púé§ãöÛoOöîµ?È:jÛsJ9‰tŒ©öÙ×Í6K!"à¹1Ótó~–[Qª”7IÆï¹é6$vãr‚N2¢råèöR²$0}º':âý½ÂjßügªE U86~³å,ÛÓªÕªUÃ~ûíçûZÇ(ut6â:…FÅþ ëozÈk«XŽùb8áÑyçy:ã-;x»Þ½Ò¥a”=§#úf%B ^5ìk›ÛìºaêCH¤ Žž²Ì‘œþ+ô8ÿ3•Êœ9sœóÑ…&$éÞ½;Jñ 3ǂ¡ß~ûÍ ‡N±ႌî±ü ‡zh¸Å)ùìÈ#Ï>‹×ü.Pl´Ú¦Ð?ýôÓ¨S§NÞÂèøÄiùÌ}Á)éo½å݉Dr‹ àˆåD{µŸw©yÇi¼ 08ë,/GÅG¡þ«©©öº~=ìªÆãFÿ:1"޲¡m+*×çm*ÄL¥vs])rŠ€eý;ƒƒmŠvxsH«Ý`ÓÓRÎ|Þ… ËÌvÒ2…M/+V ·VäÏ(bçîðá… ŽÌ˜t±´¬EyêyÙ¿ô÷ß½ëÞÆ³ÿXu„y ¨mËË#™ïn»í6׿p¤ÝxÒ8Ÿn2+£}‰€ˆ@PÛæÿÉ|Ʀ¯³Ow¸]ps¨Br‘»Pß~X´ÈëÆç€*'´Ð1ÂÆÃFðý1W ‹ïãͨ0k–·›6mÂî.¥25Ï’%tEZ‹eËRZ•¬Ý¹Ú·¬=µ:° &ÀéÓ¦M³ '™h¦\TG2nÜ8Ð924Ø'À±rjŠ"6¢ð“4™Ú“ï>œ÷ÝèôÕà~èipÌ1À‹/uëF·'N¥@—¢Z…¤Š@ÒRªñ†êó‘Œ$6 †ð¯]=Þwß}àŒÅ\Œ],-ÓØ±cÑÛ¤|)š4iâ:X›&ê—.ÒθŒ–øo¼ñ†Ýt\å„Gùve>ÿ65¦ÌòDG?pä-\PýÄé™än8JÓ¹ŠþzŸ~š?7J`=='ŸÀ®»zܳF“Ï_{Ì(¹Þ¶QH|± H™J-ÜMQFLU6&ÔHór%\öW ‰Ø‰ÊÎE^ÖÇÀÄ÷^³ß¶­·=gׂ6ólzfφÍÞ‰ßjž¦¢-ñrjáÂ@éùŸyÃÍ,¶»ïîÝdç_#;>¡läHÏÒ8Ú#¢.Ü.É]z´Ûh½ì ëm[ªÎâ]fËvµõþÑø9ó2§#®BD@DÀjÛüá\ Û­Ò6ŠšÒ'x½l#`IlÙ›G{È!žû '×]›pî¥5£èˆ&•;íTøÑó¾šÝú6Ë, _?Ü•/ï #„[žêÏ¢áê:fòþÕ¾eòÙSݳ‘ÝŠ:è œy晸óÎ;£>ÄùóçcW—[ºt)fÙû½÷Þëúºt邆 ‚““ŠâldIˆ@#¶cæóáDGô€Hô¼a0ó ˜‰—b- ò¦˜—ÎK H%¤L©X¾|9åtè8b¶ 4oÞíÚµ‹cëÔnr å[±bEÜ•(V¬˜å*î…nݺÙ@Òl÷ãÉcmíµ×^–ªl—~®n´2Ǹk’ü {ì1Ü}÷ÝhÑ¢…›µ¶L¯Æ»&ræH}çºvLÝj9ùòoÂuLQ–iÁiíÛ“'{ùR˜ÇD‘>† ó„`v1£l' ¶-þ3H¥öù°æjÚØøéeî–éP7ÜÙñ™]‚ÛÄ`íZïÜQ[)LûïŽ=8üðHkjYºPÛ–®g&|½Ø™È6•÷Á/Ú´¿ò5Rˆ€ˆ€ä#P”ö-—û$ó,âoZ¾¨EféBµYE„©Í3†'²Ð¥á‹/¼*3ý7'á0IìBU/Ns°–-aƒÈÀEy÷ɱ¡K]9 êœK9Z7õÔ¾¥þ¨"P ­‘¸òÊ+ÝõÑî6«‘bÀyóæáÆo,´X¦L{Û6ÇÛ8ïÁìá6¢«žé&iò÷?´¯óë¯=G¡pNñ'Ÿ T¯X"¢¤§*ëÐøê«èÓµM °ï™ýË H%¤ކjJ@“Å!&kçBƒ œ‚ñÇ´ô[ŸÙ`Ê\÷ZÕþ©‡¸TaU«V þ8g^s ó{çJŽoªRyÎÁX*\‹Gº`î‘@Xú50'ˆu@»çÐí˜N#H ÊÄ`O¶ôÇS¤Jž" 1ȵ¶7RØTÚÃRH¬È¦‡é¨M<›a“ÿ¸~8ÿgO8»‘ÙTù ø…³\$®Ã›_šú¡w¥€‰7§Ô63=›™†ä N6b¨ñÎæà%$‹(ââe%ÅX‘‚ësÆ®™“*rœ@®µm©8ÝZúlNÊ©eÓ÷^² %Ãõ¦¢bÚ§ˆ€d)µmE?±t7bŠ>}ú½0• iD€Ã=ìjœ<É5–ðœžaýüáÖŠý³>ðÜmX ýúE_†e¸wƒ²é˜N-ú£Ðš~PûæI•#ÑøÊ”4t*žl;ZF^133<ûì³æìó›Ë ©D ¹™†­yóæaW³.W,è`ΠgÛ¤à‰žlŸØ_{ôÑÞÄJºç‚nó©ŒJ•¢ß;û…9)TÃÆÑ3Óš‰!PÀ%¡;ã?ÿâÅ‹óÈ`ÛhI=pä‘GZZ†Ýèè”SNq®6¬‡Ÿ7bøÓrGÌä”jEFà,yÎ5FZ º81¿ùž±$dfʱK/(M ý¾PâùÊ+Þˆó€dbÐs–-¤F³2ñì©Î" 9NàeŠ^-˜?Z‘;˜˜‚6áO=pFf¼ÁÔk={ÂÒÍ_~éÝ<óÛ±Q NÙ0 £˜œ)×h&Y¥Š·^6ÿeŠ9ÎÂe 9vJD ÎÐ]²ÄsŠ´ž–‰€À„ ÜÄ”8lW+ÅÒ W´]kkˆ‹À·–çbªMlÕªj×®WÚHÒïCãæ›a}÷^Š™Ð1ÎÿæÏÂ/±÷Ï!#&Ò0S 7I„©Ù¢ ¦S£@Jƒ²ÑÓz" "àŽ÷^cvéLŸF±Q{³n_¶l(ʦû#ÍI6mÚ„W_}µÐ2#TpôÇž“}L–àñÆŒV®>ú(¯ØˆÛÓ=žnBt¾3 BZǪUÀï¿ç¯"›è(H!m°˜*ÿšúDOÀ.±¡)Å8‘è%K–,pÇXÞ :ÇçŸüV¯3€s[†°*¬êt8bÊ8 Ó¶IP Û(°œÒSN½=:ð‰÷Ì©ú´ÈÄtjÁG$Ä þX¯E@D@Ò›ÀS#0-A½p¶1é]uÕ.N·Þ ×ӧî}ã,(Ìf̬jiÉ}·õmÔàÍ8Sµ…ÆwxŸ˜ãqNuìÌÐûÓO°"ÏYÊúG" )"ðÄO8‡ÀjÕª9±ï" " "îî±ÎÑ7âòË/O÷ªª~"–€ÿš…—0ÀL›óDåÊ@^Úíï¾Ë³È½ M>ø>)SÆ»Ç.W8ã ša#ÎáejN©P!¾ýj+Ø Ì˜1uêÔÁ-·ÜâÒŸQT4mÚ4k?¬Ù1˜2½° àh·ÝvC#vbn ¶ü}Ÿ2ÅkØ—Çjœ¸IǽpA±Ý8lœÎ Lؾ6n pb$}5‚ƒ qè6È”¥ H5„ ޾äì 8îË𪰠è(8$8 ¦‘¯ù£‹AŠ©÷Vš²u¿#”-,‡E( Þé0µÝŒ([ ÄVg w\à=‹€ˆ€ˆ@Ò|hÂך–³ª”¦$y*wtÿýÞlK^ÊÌžíYÛ¦²>±ì›7ãtö Ž•+½›vÎàLÒ\‰‹.ònè-Î>àe&?{ýõ\! ãô 0Û~HÏ=÷\0Å:öÙgŸô¨˜j!" " ¬_¿<ð€s6jÙ²e„5µHÒ“€}…Ý ,çõ6oî¥ ®)S¥ÑwÍ`èÐà%‰m†—.eëÈôå|޼‡£;„Ò©E¢¤e" "à¯-M;ûæcݺu.»Ñ;fŸ~Ì1ÇäÛ Jö6;<¦M›ù"ë¤kÚ´)ŠoUµ2]æa‡Ë—{O> Ó D*%ï²wö<,ò~š>ïèȉ¦Û²Ì yëE믶-/½K ¤ ŽŽ:ê¨¨Ž´~ýú6kÛdê[ƒÂ%ŠQ™C ÁsxÞlÆEŸ~ PºKË@Ó»·÷ŠK`CEç£fÍŸèYD@D@’B€¶±NËÝ()¸S¶Î2ùá€b£Ë.ófzÎë¿ Q*Ð&áºë¦ˆË¥ +íúy^yYiýxè!ïr’z:XÙ„u…ˆ@ üóÏ?ö›zvÝuW›Sò èp¤L 0vìX7ÀvÕUWY¨2¡Êª£l#`ãÄ8úhoM·nïm-ëMa†ÎIOô—?þ8¼óCp…˜NѶ­÷¬¿" " ‰!ðŸYÊÝj¶ït5¢»Ñ™gžib åèÕ«—sÿ/h¯t9úØ~Ð`'\ñ¦åJû÷ßÑ¢E ·ûåN>ÙK—IáQ¿~l˜á›~ݵÉt¼™˜Ž“CãF”£gð‹@Â/C*V¬uÝ«T©²m]v4þüóÏÛÞëEzàŒ;eˆát»úèƒ@÷·_8ŠÃ†%žéLÅvøáÀĉ°;{o$ˆ‰¦ùyéÒé NµÈ:LJÑ4ÅÔŠì$ÀÌ­»ìK ôèsá  0P©Rv/;–‡ É]Ý6Ÿ"2›ˆå 4ÙÁÔÏ> ˜N^!"@LE³råJ\ýõ8€SÙ" " "86räHçÎw6­2"¦ ˜ÉæÒK;ïôîqfÎôºÖ- n»Í›tÁ”ÓéLùÍ1Þ›]qEþt3:Ÿp‚—Z§AƒÀ'zð“݇èìx°Y£0À93EÓ£W¦ex!H«FWã‚‚“Í›7Ç÷ß·ßî9±¿û.@j¶]Œ,Î?ûNŸîõMvì¸ý3½T(‘èo J*¸£]™îÂј(c/µùä“O¶­-‡£m(Òþ­T±¦TûÓîhlL«L–ZžŽDñ]ŽxÇÁ´jtÕ¢¼USÐ㥩íD@D@Š@`É’%nk ŽŠ1Í75×_g1_½:l@èÜÙ¥yµ#V—Pì\5 Ø}÷ˆ«æÔºu=.d£H,_~ù7ß|³s5âlH…ˆ€ˆ€d &Ø@Ø÷&à¸Ó ׋п™)¬zf,:$p 6t|—C8LÕÒ¾}úÚƒtdâ½+3.ŒŸ?= øPˆ€ˆ€øC€Cÿ4püÎ2ÕŒ3ƉhÂÌE7Ýt“¹ õ‹é( 8¢H©k×®a+9þ|ìf6ì 6´”jÞdσÊ Ÿ‰P³L¶Ñ¼Ä<å”°¨ô¡$@ÂGÁGDÁQ,Q’y I€÷ŒXG•(Ó´¨Ð½»{ŽûÏg:ï=`" " "ÒþÆB‚#á¿÷ž'î)[Ößr +×8÷fz±ÀìH:àÌž]Ø–™µœ_[šEÖ¨ ˜YuWmE@²ƒ;)ýõWÜ{ï½v[§¾ì8«: È~œ0{»M¹/o7 —\rIö°Ž0£üù§çΨ´Û@±'Ôùì3X:xàÛo=¡‘™TdDÐù)ß8>½jUÁ.Gq0ª¤ˆ€¤1ŠŒž{&(ÚŒe˶X¿è½xûí¾`µš5kš;úsá9?&ã‘ÀáÒ€¤víÚx饗åy¦ƒÒÛo¿mNF'𨍏[Ö¨QžUræ û]’Ý/ž3u 1Hªà(æÚiƒŒ%—àÈrS4´é+L–Y«¨igJØW›…ˆ€ˆ€¤˜Žv7‹˜½iƒ£ˆ‰Ó’Í›vp:s®n ÞàRW¼z5pÖY^³H7™Lµõ^4PDÜÏwß Lž PÛÅ]XoØ¥‹'47N‚£4>Mªšd-/¿üÒ)Ï5@IDATÍ’<Ì€.üARˆ€ˆ€ˆ@†˜bSÎ?3åÆ 7Ü€2eÊdH­UÍ\ ÀÔм¿æ e… y˜“†ùÈÔ9»ñ>‚*éÔóž[½xüñÇxä‘G°xñb¬5;¼Õ«7`éÒ1ø÷ßZVÜöøo¼ÑÝ܆¾Æ7¶@›6mÌñÈ,¢ »åÇ«¯zýµ¥KögŠÏãÁ´ê¼ŽªÁA±páBÛ÷¿.ZÐÇ9ù’“DÉìÜssòðuÐiJ@ŠŒ4=1™^­€à¨bÅèd£Ýí”·Á9Ö°ÉRˆ€ˆ€ˆ@6 ÃQ£Hj˜l8ȃÝGnË¿}Î9yG6iƒÁ\/ bøhÒèÙÓKgÆNFnÿÆÞƒz)N*ª™årŸ¼çÍkù¢œ ´,ͺÍX².„?`ƒ%E)MÛŠ€ˆ@l®¹æ×™xÇwÄÔiÛ^´¶ˆ€ˆ€øOàÖ[oµA ÒèÝ»·ÿ…«Dˆ“zí² M›çdc+ìºkÞ#³±iw?KWb…ˆ€ˆ@á~²ÁÝÑ£G;§a:3v¶†c=ö0AçO¨\y‰‰Œ^±Ôi`êÔ+Ìï˜9‘K¯VPé6õêå]gÑ" [·í[°}êÕ«¥Ñå(TpÄtjÀüþ{ÐŒÔí›çÔ+²¢Ë‘BÒ‰€]†)DÀkÖxeÆ’Rí·‡r­9öXÿ+¤E@D@D ¾úê+»ú]éÔâ`¿Ë.@«VÀë¯ÃfÔä-€bÎâxë-ØLࢋ`³l€óÎófjRð|ê©€õõ»ÏéôË/yˈçg<ú(0bÀÎÌlЏxó/±Q¶ŸiŸ¤·ìÇýé§ŸF»vípÌ1ǤWåTˆ@`žÙÇÐ à"»AáÀœBÒ…]‚<ÒKÎ{í\‰ÿýÏsnš4)WŽXÇ)"‹èÔ¹3¬:òÑÓ!¨ øâ‹/l"gOì·ß~¸ùæ'QªÔxà\¿6Ó™}kù6ÿ½¾þº3¦O¿ãÇ_…Y³Š[:5 uk€uV=6,ïÒæÍ½6iæLϹžý¿>x’õ·îŒiy3füdŸ\oËö'¢æräBŸt.ŸßL=v9eê™KózŽ¢Y QzÎ,·ãªÔ¢Ešª'" " Ñ »£~QS…F·»¬Z‹È^x¡ðC¢yÔƒ·ßL˜›]컯gO;øºuó‹ƒxcÏÍÛ¶-¼NZCD@D ~W]u•9Ò•0Ѩ©F" " "An¹å׆õíÛ7ƒj­ªæáà ²×Ý(Ü9äà÷“OzK8Ø­l$Àt’_ ¬_ï¹ÃSxÄ À‡Eì/e\xá…xøá‡[Qy³}Û}÷ÝxÞ¸q#æØøì¦Mû`·Ý^µöâ0W^×®;¸Ô]^ ùÿ6kæýΞn¦Cœ4J§ùà1a:ÒwïpбcÞí«Tø`œ|2`U°þÝ­^³ðòË]LT´Ùún½Ùžýõ—M(=ßÞo²cØ1®>]oOú+"(907;QèTn$ÁQÔ)Õ¬%*õÛoxÆ =øàƒ#­e" " "1–Ð3Ö¢}cs<Þ|8ã ï2(Ê•úôñòOœ\z)pÈ!ù…EL­FÃŒPפDÔIeŠ€ˆ€ÄF`ª©Fß°{ÃK.¹µjÕŠmc­-" " )$ðÎ;ïØÙË8묳l„Í€Pˆ@šÈÖTja®^à°µk,h-}." ™M`Å OLjz!çrÄ£¡ë'q2•æØ±œœ9Õ‰Ø?}üñÇ;£M›6áÓO?ÅóÏ?ï-[¶´mµ´i‡£S§l›Ìå¨p6íÛÃÒ¯ÁR«mÚxi,[uêD¡Àôiø4üóý÷{ýÆ¿þzœ ¥nÇûï°mÅ… bË–ÓqöÙ³ -gÛFz!"Tr8J*îÜÙÙÀrx;íå1?C©0Ýf²^]³f”i5Ho·ü_ui³“ãa÷¯xê)/g÷µ×¦¯MV­.» hÜØ«Oêj£=‹€ˆ€üg½¢ °•»aðàÁõ," " A€îF;˜%jÿþý3¢¾ªdö`Jk®ñÜ-Ê–ÍÞãŒæÈ,3BD@²šûX9é28“ëŽ;Ó¦GÁþÏ-(Sf’Kõ:wî\TªTÉñ £'eî½7JÿaGndñÍ7±»áÙ|!üðì>8çoß,‹m]Ž¢ š=ú(°råZ¼õÖù6©t1˜f1þ|ûû=þ÷?«¬BD - Ø¿°Bü'0cp9ó‚RR[P0‰ô”)Xib£k×ÞÖ°´º>L!@Ávε©„aNÐõ×uêÀò€?ÿf…­™»¯›XðE[b®Áxúi˜M0°Uï\h ·ÝæÙº²Vˆ‹Àý6¥ñ³Ï>ÃÕW_ŠQ[寵+m$" " ¾XaöÓ§OÇ)§œ¢É&¾’͎˜Ú륗’s,(fjqºMpàV!" "Ý(Ô ޶B`Ö,:¿ÿß~gBÔÇ·‰Lwdnü@»v°ÔeÈ3&oö A°{yOð¨C¬ÏÔ<=ÿ|«ókæ|Ü7Üà•@ÁQYS/5lØ0Ö"µ¾ˆ@’”HÒ~Ün¨’œFYe”±ŠÓσâó€ãlÇX£C‡±n¢õ} à±L”|ÑEÀùçcÆ„/õ­·€ï¾Ã$[ªtjáéSÌ#ð‡Ùý}i=‹g0XŽÆ† ÛgÅÐYˆžÔ ó¦7\¼ý¶gµ{ÞyÀøñáÖðç³Ã˜í®0;ßÀÞnº –èÒØu×À§zð‹Àºuë0tèP›]¹7®¸â ¿ŠU9" " "·Ùì„Í6bG§>EnàÀ-¿ì ç„Nt±,5øåïtŸ} çóÛožÃ„fY_yÞõy_ºf p ùï«ß}&z~üÑ›0Ó»wÞmõND@D uFŒð~Ûï¼æ†=˜]†mK4v Ž·~Øñ&ày£G·ûC9¡ræL tiO IJ(Zò#Ìì±ÈQ®ÜÎhÖìv,XP7Þx(ªUûo[‡ñI'dõô©¢E®¥ %P"ôƒD¾X¤Ç»aÆŵ©Gqaóg£÷ÞþúË›Va¹AqÚiù˵»¡-võŒ9z•m}"" " A`éÒ¥–_z‹Í©—õõ»’œÅÉ™•¼¡>óL¯t¦0‹C†x7¹œ“èˆVlDagþðdÇžè³¢òE@r•S¨­]»'ND©R¥rƒŽ[D@D  |g“({ì1sÌ18òÈ#3ðTe¿Ðäÿì³É“=çN¢á òèÑ@Û¶Þ²W^‰<°k—B¸ðBo¢Î‰'z÷¢Áõ»ë.o ˜c®yb& šì2 çž ëƒðöß±cðVz-" "jlF‚]+xã­ÏÀ9ÿÐ9¯I“‚KùÆ,ï.¿ürT­Z×]÷zö,aBo}öqRxÄtjé­Z…W_m…Cý K—®v)ßš7ožŽUUD@¶P_…ÄX¹Ò»‹¢%>Žèë6Ýb’ÉzÛçr8 …£÷" " ™J€éÔõë×ÏÔCˆ»Þt1¢±Ó«î¹gtżó0{6й3`V“¯¾êÍ8 Ýñí·{ŸôëºDïE@D@ü °|ùr3Ã#Ž8]»võ£H•!" " I#0|øpükJ“k®¹&iûÔŽŠN€Õ«‹^Np o¼L™âÝÓr@8mÚÿûðÚk^ŠñÀçáž›6Ž: 0-6ºwÏ¿Œœ~:ðÕWçgs –ïË”æÏ$6ÊÏMŸˆ€ˆ@ª PJW¡;&•Ž ›¤4hPp9œÛ­[7K¥özè!ô豋KµÉöáõ×'žH_±êxšWà´n}—1{ܨGƒþˆ@Úà(mOMæVì矽ë‹/ì(8Úk//‡ŠÙä;{€óÜ;ß~ë>“à(} " "¡²]pDËÝ‚âÚk ˆh%ïî XÑ]+l]p78°€•ü1íæy³N{av¯_ï餟zʳ«WšðŸ/"³˜Bm“5*£lºçÌ¢ !@÷€|Љf™êC‘˜J†©ÍxÇÉ2ñÝŒ8Á&8Z´ð?O> 0¥xpÐI‚s‘xß»pa𒼯÷ßß+cРðÂ!Ö›H¼Oåþ™–œ)À)NZ´È»ŸÍ[¢Þ‰€ˆ€$›Àœ9Àõ×çÝk… ^ºM¦¿ä¤Çx‚i5?ý&&J–,¸„{î¹/™Ò¥—^ŠV­Z¹{ôžyÆs£/xËôXÒØ,òË•+‡_|Ñ„´óÝë‘VéQmÕBrš€G9}úsðË–Áf¦z.øúkX’MX‚M o_wL!ñÑGa—]vÁþ¼«Rˆ€ˆ€ˆ@øðñÇ{˜îv¯,8šü‡Ð³' >}€3`³f¼u^x`>rÎÊdgjAñÜs@:À#‹³fy³2ùY*‚³DiÆøÉ'^gm•*ží=uÒýû§¢FÚ§ˆ€d?Yöãÿ‚5çœsŽ >Mñ© "p“)=èntã7fP­s»ª¿þ »îvÛÍs™ØqÇÈ<6oö„ÝU²Ç“" iM Â0?õ¦í™"·0i“&À~;ÿèÉu«Uóðî‹S9èWË©$K–{îi7m?ãk-[·n[ t´" " YK€Ïë-'W}z¦gi ð±b̦×{¼ò ð÷ßžØh¿ý"8;kï½×»Ñ¦¹S'˜ø8ò6ÉXjãÞÎéˆnG–!ÁYí'c¿Ú‡ˆ€äѦXåìËa61¥ må" " "A†šåÍF³C•»Q´­U-(í7ïKé>ºHXVKIã¹UqiRM`»HÏ—\Ìë¥DcjÎÕmÓ&ÒZ&" ")(je[¶¢ 1êUWæÓ#€ˆþÈ,ƒ«]wµj½l enÃËÖˆpOhÐ hàÀ6ÒfPfpPpº)D@Ò›@ÂGé}øª]"ð&É»Q²©"6À¼…·ï†Ò[¶¢“'oKfMw#ÆÁÌË¢, °„¢Z‹lÙÄtéì¼sÞT«ov¦X£©%G–%5ªh׸øbÏ¢>•îFU–³^" " þøÉlq9@[Ýîér¤L"@Áìc=æœèp¤H_¼GµÓ•‹O%Ý#8¡†“i[¶ô\yý>:Óã»ï¼I8=zø½•'" "*¥JEÞó‘G|LœXfVz2DŒ 6`æÌÙæ |¬­÷Fj‰v*n.JÇ¡fÍš6Qrì½÷Þ÷Úk/;™ùC†GíڵݱümÍÙÔ¿žá§EÕ HpT -ð…¶ÐÆ£•|l Ž$ô," "->üðCw(ÙrCt×]ÀWÀÒÄÁò|–˜N;Z±Q ”Xfó¶Ñ³ˆ€ˆ@f¸îºëð›ùÍ3MÉ’%3û`T{œ#0xð`lÚ´ t9R¤/?0US£1]6S¡§ž ð‘È EP¿þ syLäžT¶ˆ€ˆ@¢ ¬[Äšè‡.G;cÆC†„¯á ³”a6H“&MÂï¿g+†ý÷Ÿk¯½ß¶íˆÝÙ˜dyŒ7Î¥‡£k“BD ½ Hp”Þç''j'ÁQNœf¤ˆ€ä:•0ÿÜ:uêdüq/Xôí ;àúë3þpt" " )&ðþûïãá‡v32;tèâÚh÷" " "eË–á©§ž2w÷6æP`Š´%0jðôÓ@çÎ0WÅôª&ƒ%6J¯s¢Úˆ€ˆ@¬˜“é6O; ¸ýöè·nß8àÏånÀ Øéõ×_·Éžw`ÆŒزe ;ì0ÄçŸoÁo\SmGëÖ­£‡ª5E@RJ@²À”â×ÎI€‚£ *XC©)úFˆ€ˆ€d ޲é“;í´SÆûÐ)8š5+ö;ð:ß ôéÓ;ì°î¢}žBD@D@2ŒÀ Aƒ,•ôf¹¥ùycªoºóZv—¶& nÍÓœ¸ª'" ¹EàŸΟùòËèô‚éа‡Nòk×ãÇÃ]WL:Õ ™›5kf)Ôf¢½©’.\ˆ'Ÿ|Û\ñªÙ¾vÈ)±Q0/½Nî»°1ލã–[€F€o¾‰z­˜=ÒÂáˆ7iŸ}ö™¥éXêÄ'?Úù÷ßÇúõëé²eËb·ÝvCùòåqðÁ»|5jÔ@ñâųçLdÑ‘Ø}·Ë;zÙeÑGÙ’r&º#ÖZ" " ÙL€×0+W®ÄYg•‡iFM¸í¶¬8„ˆ€ˆ@Š L›6 Ì:¯gÏž8äCR\í^D@D@b#ðÁ€‚íÚµCãÆcÛ8G×Þ¸æþ›üƒgênŽ•Ýsl"Pò÷¯=Š€ˆ€d7‹.‚9ýú^Û±®^½Ú±Ù¸wŒ;ÇÜ‘ú㫯¾ÂÎf×½{w›øÙgôïs:zôˆmZ[b&`c˜<¦ræÏ‡åö.â˜7p—] /ŽùkMçJ•ò­[ÆDto‰>È)¸ÜßŽŽƒqS¦L;×Ð{.Šxš>¨»Ø—›Öµ]ºtQGeÜ’¹ ó޲ï8ÁѪU«°Î~¬($Sˆ€ˆ€ˆ@6 €š–·™(¦µ{[»ÑN>hÚ4ΆŽAD@D Œ9%K–ÄàÁƒÓ©Zª‹ˆ€ˆ€DEà†npë :4ªõsy%›_Œ .ðÆ¬˜eÄ/}L2˜Ðu‚©mh¦ë p2ê§}ˆ€ˆ€d.j0Ì´=s!hêMеh”åúüðÃÆÃw4™ÿP­Z5 8½zõ23‡=óW³&ж-,%yžõF¢'°a0{¶—û/ÒV6^*é¬Ï§œâ)¶©ÉX¼8æ˜H[zËÞ{¨SÇÛ>xíDå+¯DŸ½ö þT¯³Œ@‰T&ÌA9™J¹8ãÏ?ÿtÛ³ ÎŒä _½zõâ,M›ùE€³V~ùÅs8ЦLº1$8І–ÖÈL§ÆÈ”ëÞ(3]]RçÌñ&Øe–G™ðeSE@D ƒ°c•îFçw*V¬˜A5WUE@D@r‰À矎ÿý¥K—F©R¥Üƒ¯ßÿ}—â¤S§Ns¯—Êóff†xôQàÀ_„¹8$¯6? |÷'r2³…ˆ€ˆ€øB€IyÌÏ?´h቎˜­°øâ‹/œþ&ë„åÕÿ³w`R]> Q’ AÉ9 E@EQ1b¨ˆÁ€Y1b#†OÌ9!Š € ˆ 9‰$Arúïéfvgfgv'ÇsŸgÙ™îêêê·‡­éªSçžn¹Ø8nìùa–Ÿ`Aý"*À{÷†YtŸœxbðj(2“téâ~qû怂£,XpDaS©ñ?†\x!6ÚšÏmwÿ}zŸ1Š$úJ¾±è`ó€[¿~}ÌNM'³Ï>ÛþÏôƵ¦’£û‘"9˜s”ö~~"Ü ‘à((íHSÁQª;Ñá”À¯½¬Xá:¤2÷8-z;.Má«Ù" " )Kà)æ4±¸*+Ü”½ 5LD@D “ ðY®E‹/±P¡B(l³ŠwÝuWÀýÚ˜Kছ\çÜN€‰´.h)_>w?_™cÆüáN¤Z–:Ÿà1‘ ñïÜéºMPÛlYi" " "K–¸¦/O¥{n-ZpÕ]pÁزe ¾úê+sÌ1âbÐ!CšÑ~¸;f° 6f‰a¢  S' bÅØ^ßÕW»b£óÎøÅ¬ èÙ3·DëÖî„G… óhÙ2oIsLZýÐCøó²ËòîÓ–Œ!PÁÑ—_~‰Aƒa'¿ù ÑF®¨ýÅþË–$”r©KF›‡si¿dËòS„pj펂ÀêÕîÁ¡.X•à( Ø:TD@D % pšö·tPʵÏR„;# ö1¡^=€ø°,gÓ”»ejˆ€dº±YŶmÛ¢M›6qMºÌ#0)#,Î?ÿ|KÇu0¶nÝêüp’¯>úh4iÒ$ó.<†WÄÔ2>y$ðþûn6ŽbÅòžàÖ[O>q÷{§‰a:4.¬çØ2ã‡|Öå{¶ÃŒ©" " "5Ÿ~(Œ]³0Ýn¸!ô*ï¿ÿ~üðøþú냊X›™+‚†tæ3}³"] ü÷Pºtè­Ÿ4)×ÈÄíNJ23m¹E÷ÝŒá®,5 `ýá¿HY†)ð?@AÁtj ªåYI a‚£q–£ƒb#ª9E×®]-àQ¨U«–#4ªè§âÛnO-·‚œÈ{ã7ì¯ýõõ X¨eÿy*T¨à·WoãM€.£òŠÀÙ÷Ö™:Þ¹îæ<ÿò~U¯^p@ž}Ú " " éF`Ù”²o;’£«) ÿ÷®s*¿Šqu)W{ÚW&tèB USD@D@2’ÀÈ‘# ÈÈëÓE‰€ˆ€d?h·cqçwÚpfý̸¨^ųÏ7ß Kã¦íÎOðÃ9°Gq‡÷Û/·‘¶Þ}ð,]xóV|Ö:6'@GÅÜ:õJD@D@"%ðæ›@Ÿ>®ˆÙ¦zô½¦©S§Ú"Ï»Ôi÷±ãË'è:ÏEš6 ˜;×Í·Ê¥¼úª[Š_`fÍ(@Úµ«à#M¯¿vS¤y‘òic0¸í6˜ug®ܳ/œßíÚü‚·lP£Fð#ù¥‚¦ N¡ÁÔžL!$݉n¶§@b£–f¯õ–å|üñÇqÆg µYtù‹»¸=mÔ­[×%]m`_Û¤m¹DÓ¦MóÜ‹?ÿü}ûö ÉI)ÏÁÚÃQåUæ+øöÛn~µ 5rR–òÍš5 RB›E@D@D ½0'÷fó~gîT :}ñpê©À;ïÿí>+Hl”JwImÌ$@7ⶪ®’Y0ºBD@D@R•Ç)K˜µÇ áxýuWäÓ ûìYÐÚR>27jš#ód­»ãŽðÚÀtáöHŽÃ3ï,*-" "©lÊÒ'hVc>8ð@àÛoÃÑ‘މûYGÇì<ÅÙýùœMoRŽ•ÌT÷ÿ`ä×PæÜãæà+(hëÈz¦!c>ZŠhÓØ§OAGº6§œÔ¬ Ür 0o^î1Ÿ}0}Y:Àر@™2¹ûÂ}uÄî¥U£ÃÅúÑœ+ܶ©|JHˆàèá‡v&ß¼¯œ¶´O>ù$^·§‘æ\öfðs“’¾gÞª¯ÚÂjÕªùÔ0gÎ'µšÏF½‰;ÁÑ&{º£š‘ì‚'eiG,ÁQ@Ú," "vèÂȈä»MŠŽ’gŸ s}„=Ø&£:§ˆ€ˆ€äàªÎ=¶ÒmÀ€¹õJD@D@RÓ©1š6mš‚­KL“lí.eáâþ`‹ÖéúÀtkñpÔåÂ}ŠˆÂq9J )ED@D  Ð ž)@ý׈ÆRDŒK,¥ÖÊ•+ñôÓOkÑM:}HØV Ѝ@c椑#K/ì úö…)Í€_ ~ü[o¹ž .^&Ü=œ à—²@V]áÖå]žiÕø%ÑZ бÁ¾,º{õo†ˆ«àˆj«=9¶ $'ß®¼òʸ"=ÊþÔ­[7ç6lÀÚˆ)B€·»R…ÝnŽÊZµò=çÌ™3Q¯^=”,Y2ßrÚ)" " é@à/{r]aÖªLõš¬¸é&×9uÒ¤u¿Éj¢Î+" "%¶Ú2Ò—lÖ’NÇrÅBD@D@R˜€Gp”ÍG—]›(Þ~;5nTƒÀ…&À5nÓûïŸÿ |„¶Š€ˆ€dµkاÄ+Ë7Í7^ýu4nÜ~ø!Î;ïpîë´Ó€3ÏL·ßÎEÌ{çï8—Û³'píµÞ{ôZD@D@r Ü}7°q#0t¨ÛŸäî‰Í«ï¾ûG˜ FíDÃÌzž©Ôi@ÀÒ¿ƒ©ÓfÌŽ9ÆÑyèœs¢o<Ü;v¸_®ük[°øáàôÓ]Ñ‘ÿþT{O1‘‰é×&ÿ¶ñí;tP1’y½ÏXq­¥tÔ+:uêäõ.~/ý–ÓþL‘Ôv}w;e0ùŽè:ÅTwìˆ" " " ~b~d ÿï!™pmº—-äË–-kÎQ¬ ÷¤*/" "  ÃQÆ -…Wö­Þøæàºë€F€Ñ£Ï'Eˆ5êÃhÀÌ$6Ÿ‹/¿Ì­Žsƒf&á˜ÆY!" " yP×ñì³°yHàŒ3òìŽjëüLSèrÞ{†uJ· 4ÈÉöUå:8rfvá` ªaÝ:ओ`)“ÜT`T¥Ñ6‘" Xë)_>pZ5~ÙbÄ2š[câÿýýw75œÒ©%ž}Š1®‚£ü¬ÂªV­šË¯T©’ÏyÖ¬Yãó^oâL`ñb÷ùŽ~ zÓ¢=­" " "èpT¦LËÞ$!W³gп?ÀÁa…ˆ€ˆ€¤ï¿ÿÞt½è¢‹PºtéTjšÚ"" " yЉ}±g6mÚ4ϾLßÀuºg”,éγ™V8åâ¶Û€bÅ€;îÈm3•pÍç«TÉÝ®W" " "à!póÍ®âá‡=[¢ÿ½ÒRn]}õÕNêðwß}לöz‚¢åáÇ›¾Ä&ŠÄX¶ øôS×¾ÊÒØÙ9Xš% [·‚Û@ûÄ^€)Å\kDZcSN)ø¸PK0ÐùçäìËŠs(Gä¦]ËÙ˜¦/8¸ñFàÄÓôÔìX(«ŠÕã/8ª˜ ü}•+WöiŽ¿Ó’ÏN½‰=%KÜ:kÖ Z7GEízëÖ­ƒ–ÑH{LýÃT²ì× Ž«žÛAb©ÁѯðÒKÀæÍnŠéta¥vŠ€ˆ€d>ÇÜܶ áÊ+¯Ìü‹ÕŠ€ˆ€¤=9sæ`¯=drÈ!i-á\ÀöínJ2®Õ}ï=Øâ™pŽN\Ù5€'Ÿt ¼ÏÚ¶­÷;½\Ôx¼ý6н;бcîöH_q¾ûÁÄSO=…­[·:Ù[6%SÇXTi£²õ¸_ºvLü•§[o8³-Y†ÉGa‹†Á´gñ ÖÏ/06y¾´pñ}÷¹ú™àªIæ<OŠª;Mäó¿-ú+à]ïà€c"‚©º¼ƒy3 $`+‚œ¥%\$(8:Ü,ÖJ”(¤„6‹€ˆ€ˆ@ú˜={66mÚ”°tjW]劸ð‚¢#…ˆ€ˆ€¤ Om…áÛ6²{ŠuR7N•f©" " "”À¬Y³œ}Ù&8¢.xÊ€B=zÅ“;.»,%š¡Fˆ€ˆ€¤ npõ&Ñj!þý÷_ 6Ìq0âØoóæÍqÏ=÷à´ÓNK)ÞLÎ'Ï |è9]ŸÞÑú¿U+à°Ã€fÍ€R¥Rëbí³â´ï7` ·}F}vjµS­°OvüâÀô©ÜßñÈgg ߬cîE¯8€–^Џ˜7¦îÍß ä“Nmþüù`š;¥S‹û-Ñ D@D@D€éÔm=«âxÞÁƒgžqŸÃ̹ױ–ãéTµˆ€ˆ€„L`õêÕ¸øâ‹+ùgŸ}6äãTPD@D@’I€©PÙ$8â3%¯œ|2p×]ɤ¯s‹€ˆ€ˆ@l |ü1ðÍ7®M4k`FŒ:uêàî»ïFµjÕðÖ[oaúôéE{»~ûÍýòa¦ØMÇ5dHèµ~õÀ ;s` €víROl乺™PͱÛòlÓoÈ@qù§6[±bEBú Žü…O iDžÄL‹,w©¥¤\]9_ÁÑäÉ“:GydRÒ%‹€ˆ€d"à¨pâ÷ß0ïx‡ÀL­T!зo_PtôÜsÏ¡zõê©Ò,µCD@D@ò%@ÁQÑ¢EÑ Aƒ|ËeÊN3#Ä5×õëcÆÀÒ‚gÊ•é:D@D@²ÀnóC¸ñFWŽ†ÅŸÛK¦Ê½Ê,æË•+‡—_~¿ÿþ;Î:ë,'u¸Y½Ï‡3}÷ðúëÀµ×ºiÏèüÛ³lЧ@óªÄB‰¿þþüèÒ%”ÒÉ/Ó«Àl@/¾˜ü¶¨"GEâX7*UªäSý÷ßo;úøl‹Ç›iÓ¦ùT+Á‘ޏ½±qe'*Ã^Ô::èy˜N!‡£ ˆ´CD@D ÍüôÓO¨Zµª³Ú%^MúiàÖ[a)IΤzE@D@D |O™ÝígŸ}æ<ós V!" " éB€‚£† ¢H‘¸•§Ž÷ÞÎ9æF|ø! Ä)q[Ô ˆ–©Bׯ:(²J'L˜€Ë/¿Üq7☯ÿ\wdµféQ;v:å^|­Z®ê™¹\¹}¿ý€óÏ^{ Xµ ¨R%·l Wt7bwœû;Õÿ5ÁÎ<xçØê, ²v(D  Äuý‚ÿª Mþû￸cü†^y^‘Mv¸^—ð—t°;©ÃFTo`jÍF‚žŸŸÚÖ¨Q#hít!°uëVÌœ93®éÔ^}Õud÷:nluMºÐQ;E@D@²À¬Y³pà 7 ^½zxòÉ'³á’u" " B`Û¶mX¸paÖ¤S£©±|û-SÈeÈMÔeˆ€ˆ€ˆÀ>… 4•1s¢ˆbΜ98ãŒ3l¡çþ¶àóS‰"¢èuWÌÚâ$GpÃTj‹=sŒ+6bÑOöî¾ø‚ïòàèØcó/—J{™²€ Ò]l4oì?‡{/S‰¯Ú’â*8¢ƒM™2er.tçÎŽµzΆ8¼X´h‘“CÓ»êcø‡KwgŸ |ö]YT›û5pñÅÏGÁ­•N- mHCÌݽËìaÛ¶m—Ö3uše¨qRS{ÐËiT©ˆ€ˆ€DD`ûöí6 ÛËé ÇX^–Ò¥KGTdàÄâž={²FpdÚ`üüs¾kE“qtNH:µk×â”SNqŒ3Þ}÷]4iÒ$émʈPýE¡Ê¡‡¾œN€åªsWÙ.‘»•‚£¦M#·¯Ê­)q¯˜n>,%)£Uæ—_&ŽÎ”6â*8*V¬˜¹šùÚš1×å2æeŒS :»™¤s_T¬XÍš5ó¼Õï$ ý ïÒ©%ùFèô" " 1#À¾Ñ®]»˜Õ驈£sÏuEF|Íç…ˆ€ˆ€¤›o¾¿ÙJÅ;î¸#.}a*]«Ú"" "y˜NÑ”“Wi4øøc`öì4l¼š," " 1 ðÏ?À´iùW´ÚÒYM™2%h!.¤éÞ½»ãzøÌ3Ïä™Ûz`¦îøë/àöÛÌÝ?®Á4j´`¤Ã¿Ø‹?ÿØ.?ÝA°âÚc–¹È™œøñÇW¬ê2@\GÄ?ÐÞÁ?ÚýúõÆ ¼7Çäõk–ãqÒ¤I>uõìÙÓ„‘¦ŒT¤¦ScÈá(%n‡!" "?ÛòP~×hݺu jó­‚Ë¥J¹Ï[õëûîÓ;H6/meÛcf‡Þ¡CÜrË-ÉnŽÎ/" " aðŽIÓübO<tëXpĬ%—\عBD@D@ÒŽÀ÷ß~˜¿eýzàøãfØbÖª@Agú.]º8îôuêÔÁM7Ý„_ý5§è^¹ô5{ùÉ“'cðàÁ¸ôÒKsöeÝ K—îXí'Ü{/` Œœ¬Ÿ|Å›oÂ&üï g«9KƒßkÖ?Ê2è sg k×àe´'¾¸àšŸ~ɤâj?…¸ Ž(,9vh^Á´güƒý÷ß{mîåÈ‘#q×]wùTR¡Bôïßßg›Þ$—;ìâÅ‹[®pK® @ÁQãÆQ¶lÙ˜_Í7ºÇÁgc~BU(" " !Xo#»]t‘“F}ôèÑØo¿ýBøàƒhÑ¢…“Nõî»ïÆu×]‡×_4°x€Ž>Ù> ŒE×àÓOÇÖ­úôÓá|Áððyåà¼ó€+®ðl‰ü7ÅM6ŒÊ•ƒ×ѪÀÆI'/£=ñ%pİ4F?'T¼¢Å·ª= Ä]pÄk2dˆ¥'<Àçòùǽ›}?µ?XTF_Y¾ÆÓí\ Nàšk®AéÒ¥#­ZÇ…I W/àÙgƒÄûü£Y­µ²Néö" " "î˜Û{áÂ…qM!“ßsVºóSûE@D@Ò—†¹ˆèQhª]»vú^ˆZ." "ÕèpTßVÔ§ÛX¥™5à ;Î÷ùÛ|*.¿œãòÀ[oeõ-ÖÅ‹€ˆ€¤‹/v]ßÌÃgœ›[tMU¼/ç¶Û€ûîƒ9îzoÍ}½Ô¸QXÌùèÅæÌòÝwß᪫®2s–pçwbøðáhÓ¦ ¸&ë3æ0ÚO?''Ÿ üßÿT8ŸsðÁ®ÛÑC¹ 0Ú(Ö¬ <òH.p½Êl1øå“!s—ƒþ¿Ãxàæ¼vož­×¸öÚkÍý¬«}6_ÁªU«Bº%;vì­Û{˜´õÊ+¯„ÇúÖû`Š™Îá@EBlÚS»ýP°αN‰«`•N-!mH7t7b´mÛ6ê¦/_[IXJq…ˆ€ˆ€¤<>úÈq¯=÷ÜsS¾­j ˆ€ˆ€"°}ûv,X°M›6 ´;¥·Ý?0e ,õ о}Þ¦R üÌ3°‰T˜ƒSÞýÚ"" " ©J`Ð `É×DÅ´@ŽàÈLˆÝ æÏÏm9³k±ÔÕW_Í›7cĈÎó+EL þÔSOY ¶øâ‹/p»‰l>1§–’%KæVœi¯8ðL!QAA{DÿqîƒÞx˵‘¢`–eÈ&ëjÕ ªUû3…UübIU e3rÒíeʵé:¢"°Çã-‰æ3ö”Cס­[·ú4šŠÒûL‚ÊŸ*Uª yóæ8Øþ€•)SÆIO‡?ªP=?+W®Ì×éè£ÆÐ¡C¥Dõ¡ß7ž´šù¹0üðÃN#Úz ŽoóT»ˆ€ˆ€Ä…@¬G¶°gžéŠèFÚ§O\š«JE@D@D &¸xh¢­xìÒ¥‹\…cBT•ˆ€ˆ€$ƒÀܹs-+Än'¥J2Îé9ù¸çغë`i=:ND@D@R341(…D—]æ¶®R%×Dçúë]}‹†\$ßó,íŸ]ýƒiÁ9wÍŸŒ¾}]¡Èر‘_*9Yö"ËIp.¿Œ¤aJÚÈèHSå¹9ùeôÐC¥j×G"‡@ÂG<#…@t2êß¿¿¥|\—Óït9¢¢4ÒèÞ½»cÇÜÛŠÄð¸1Hp”8æ:“ˆ€ˆ@ò PpT¢D Ë%~XTa®q[lƒwßuÓaGU™8øüóÏAça>+D@D@D ] Ìš5Ëiú!‡’6—°mpÁ@áÂn6‹bÅÒ¦éj¨ˆ€ˆ€äKÀ2œ¡_? |yà…ò=è ·Ì»'ï–-[¶X6°ÿC¹rå0lذ¼²iË¿ÿ“&'žýUÓÕæŽ;¢¯G5¤/¦U£à¨eËô½µ<æìÑ$±Á ¹±¦ ìÕ«—=ÅîôtFzþùçñåŽäÄŸ"±<‚#*ƒÅäÉ“Q»vmǽ*Xmt"@ÁÑá–«¸hÑ¢Q5ÛÜ}1{¶ÄFQAÔÁ" "  #ðá‡:ŽÂ§žzjÂΩ‰€ˆ€ˆ@¬ üñÇN•é$8ºõV€Í¾ë.wy¬™¨>HzQp®ñÉ'£ÏÒu—u”K,/3ëD¥R6]vîh«¯h {,Ш]f¢­IÇgØ)~€rÀXþè;ÁAʳÎ: ¥J• ãhߢìC}Ù¶7ÎqPòÝ«w‰"àU¾Í<-ýlذÁ&Rg[NñIÅý 뽈€ˆ€¤ à[zÓÖ?¯u„m¯^=Âu˜ˆ€ˆ€$À®]»ðÙgŸ¡M›6¨ZµjϬS‰€ˆ€ˆ@l PpÄt*_N‡øæà±Ç€#N‡«" " ":Ë|ædìêÝ;ôc•¤ƒáðáÃѺuk\qÅŠd×6K+g+†-Ê®û¯«=ã `Θ³L¼Î zÓ@RóŽ5lØ÷Þ{/nµ¥&LÀ´iÓðÛo¿Ùçtމ-Mm <ð@´hÑÂqh×®]Ô)LœB›" °f{PåeÓ»GþñÓO?aïÞ½ö@lOÄ Èt7bðûH8±v-ÌÒ×(Î/i8uª¬ˆ€ˆ€$ŠÀ76ÛÉ%Ý´:2QÈu8 à¨^½z(Îô )›6]”, ¼ü²›R-Å›¬æ‰€ˆ€ˆ@Ø¢ÍrÊyÈË/¿»wïÆ³Ï>ÓL;a_L¼ éƒ¥ŒCãÆŸÁ YÚ!˜ú –~¦àò*!" HªàÈÓÞ’ö¤tÊ)§8?ܶgÏü÷ßø×òJòw1KFMW¤²eËF²ÄsNýŽ-‡£ò& àXÅtj 9Å–»jHŠiá8ÍŸœtÀß:ÁVÙ$¯ý:³ˆ€ˆ€DBà#®Ž´èÞ½{$‡ë˜,%`C;(]Ú÷â9FN!63ذBD@J€‹]çÍ›g‹ýÓ#=諯‹#Fõë'•N&" " iC`Ô¨Qøî»ï0`À´jÕ*mÚVCo¾xí5àÝwž=ó?ôÛoa+†Ò+Ûûûï@ÇŽîµY†#s!´r7ÿ{­½"DII©VÐõ.\ØÕ¨QMš4qVšÐÙ¨hÑ¢šÔý;vìÀŠ+—¦¥¦0¥‚6Ö±mÛ6¬Zµ ´±O¥ðŽ*Õœï‡~ÀþûïæÍ›§R³ÕdsßVÐáˆßO¸"6”°®Ð„·À¢E°6…ÂLeD@D Ô·EG•©ÑëÔ©ƒfÍšEW‘ŽNþpÚ?lø!ª ˜¨C J \9`ûvßê&MjÕ‚9‹¸FɇØü€"… Ø‚qs¯.¸¼×+W¿þ [H˜·¼™›+â@ Þý[ªŽIFŠrîÜ¹Îøê!ÑZ)DÚ€0ë×xøa=G†‰MÅE@2€€ú· ¸‰A.aýzà‚ €}k:ƒ” }ónj믿ތ|Æ}÷ÝúéV’_8_þÜs·|ß‚!³(.¸lª”`Ê®®]›sÇÆ0· ÿTiÚ!"€@J8hWT›xàÇÉS Ó¶Å+ÖX.1®ðüôÓOÁ¼ ÞATíÚµQ·n]ǽéÄOôÞòëomäo”ºqÕ ÅFŒB–o³R¥J&ð숳Î: -[¶ ¹¾x\½rÊâ?¯[-Oõt¬¢ D›6mP¤HF~äò\³6ˆ€ˆ@:PßVðÝãjØéÓ§£sçζ–}üÀnÏy'ŸÒa*$" "#êÛb’)Ð/^ŒƦBÕ’t›7ÃÜ=š[–{’å6‰ë…˜1ýôÓa‹‡€2e\—"ïß<žÇÚ"bôî zhîñfTí¸qЉƒ6Q\ä [c†Aƒ\aÊß»‹XûölžÏ?0[»çPýN™3a+Å €ŠÝ~¿å<€™”çüx‹Ë¾ú 8öØÜ¿þºûYyäàÚks·ëUdâÝ¿¥Ã˜ddä¦Sc4mÚ4Ò*zçmU!" YA@ý[æßf.>àóÃ_¹ß)Ûµ‹üš—,Y‚k®¹\ÃL9cÆŒq~G^c´ùS|ýµû°Å‡)æN-(ªV¥å°ëpÄ•­¶ (hp š«<¸º#]âøã ܇L>pÒÜ£K—ti½Ú)YIÀ†2/>øà¬§4v_ÄKp4Öò^ÞqÇ6°b#+ÂcÍK¡Ð8³|cÚ8–gz¸PbÙ²e¸ñÆmÐÏFýü‚yHW›­Ð{ï½çük¼ ðØ@IDAT£7=ô Ú`bÍŠ¨ŒÕ0…Už³SˆEFJ§–6ˆ€ˆ@ÊPßÚ-á„+Wø†’N«û{õrÅF|˜N²F8´ T)È êÛbw3•N-v,S¥¦óÎ&N„ ÐûŠ(âw[[º4†¶&ÊGpD! '‚ÅMÆåîå0Ó;ù¦+b9Ò]Øš["½^Q4õøã€­Ss2ÐáÒ;.¹ÄujÜæî ð7ç(ò¢ ‡®PÅ”)ÀÂ…®˜«E 7Ó@AÇ„³ŸófBžŒQ Æï·ÿüÌž sˆqÛÊöÚbr§Ý|Í¡/f=à5yÇqÇ4”¹î:WÀvÙeÞ{ó¾¦È‰Â´ýö8÷À¹ àl^ÖG<û·t“Œôƒà¥¢Ãä¹~Ö†zQ¢D¤W¨ãD@D = ¨KÏûn«)¤å3¿ó÷éîÑnyÎÁ>ú裸çž{¬®-8ÏnøžGi—_üïnsù…·aCàÎ;sÎÉÿø%úw€^€Ù9.K“ >,\}uàý©º•îFL÷ùç®ËÛɇ…ˆ@ÊÈHÁQ"hÓqhèСaŠ.HL¿Âcël› î>ÖË._¾<¤sL0µç™gž‰Ñ£G;ÎG!ÃB@«û'€àˆéÔGyd ϨªD@D@bM@}[èDÙŸ3Bñ¡™“m¯¾*±‘Mÿˆ€ˆ@ ¨o‹-l®-_¾¼ã´ÛšU[²Üv›»ØÕßÚ2¢ƒN4tª¡ ɲÆ;©±6mr3M_sL¼m[ S'º„DwöÑÂo§\u•ëŠtå•pBYèÝÙ}þýw×e‰cô|M÷ ‚(’òþ¡˜†ûgÌpÓAx×B±(&2ãë¼ý¶›®‹ß³b™%€‚Š]h"M!…?̾ôÚk…<ž(Z°…ÕŽðŠâ–ó+ó'XðÚøCñÖŸºnAößÌq¢{Ö­ss‘— 3剀nÝ\AC{3sÎâ³ÏÜó!¹†¿þêfi`Y~ 4ÔJ5AËÐ ‹îYÁ‚×KAÛÎõzäN¡S÷Qà•íb£xöoé8&ìsTÐv:Õ±$sM¥ Ø“ø¹§ðH!" ÙB@ý[fßi iý‡"Iزоärô­·Þ²E %Íð^Ü`ÂbÅŠ¥ÀûïwWVtìXÖpÅG8ÁùåK/n¹ÅÍIÍ<ØþÁ\Õ–bÇã¿'µßóÚøðÇÕ»Œ .pë_”% ÁQ·†©ËvÑ3z_T¯^Ý_3Á¥).½¢¥ùŸuÖYæj÷n³eƒLƒÆ`Š4® íÁef‚åܹssöµ¬‘æ+Èú¼££uD瘭ÞE6 çqBbnõ·mÄíì³Ïö.÷דϷQ2ªhkÿ–ç\t8¢£EY Ô$ ¾-¼ûòÓO?Ù"’º6ÙQ1è\­~ÓM°U6°U6A‹i‡ˆ€ˆ@œ¨o‹-X¦Sã3m7ªI!@Á‹ 18 [(Ì¡ (£fMÀŒœ”kC¿û£Ý»ac!°a®à&Áëò^HìYqÍvx×{y\(|áÐ Œ(Ê¢ Q$ÁãZµrÂ=¾uk€?¢^=·}̰@üQGÁÆŠ\^þ×å<Vèn5v¬›¾Ì<ßs!3ÅF+Wº¢³§žÊeËÅßüÉöˆgÿ–Žc’‘|8®;oÞ`yGéæ\•n¬Õ^ˆÂ1¨#«ª ‹Ðt.Û•Í zÔ¨QyÄFžýüÍTg}8Zâ?þ¸×»Ü—ì(ŸþùÜ öê~Sºú‹<(vòw[âà@Âø8á×¹ÿcKò(žR:µ„ßPD@B& ¾-dTNÁ7Ú*ô?óM§ÆÉ(¦Ú悌7ßJ• ï*-" "õmÑñ t4G\5šŠ“³Ú›ÎÛèlÃ]t»ñ Óåæºë3^öÑ-†‚¦è Û¶/¼à¦Üb:«t~âµRhÅõMþÁ yŠR~üÑÀðßOaP(ñý÷®‹ÑÔ©¹¥ixh²Ÿ«°iÞÌÅÄ=æ:ð<ú¨+†JÅq|Š™†uER\óÆá"f# #” e9‚­Ü«Î}ÅTjt]JäbhÎ'PûqÒIîçœ./lc¤B®Ü«É¬WñìßÒvL2‚[<þ|g²òC‰àèøÂô‡þþÄ÷¬ª]D@’K@ý[rùÇóìt¨¤3k… À¡‡†&~?6lꙚž#f˜™dêø÷-ÏoZŠ,û hSʪTÚ—+>ÏäÚ2ï°gŽÖ³B&æwN×Ct8â!C‚#—ƒþ& ÁQ˜7‡ƒ¬Þq¹ùcרQÃ{SÀ×ô±è¥ý:zcûVSyº/ºX΂VRŒÔÖË}æÌ™X¶l™§ŠÄüfgÆo ~ˆt7b´oßÞù­D@D@R€ú¶ðî …Ç{ì­M›6AäBˬ N@1í´BD@D ±Ô·Å–÷–Ûe‚ÙÍtîÜÙùLq¡H€ò6îí8>ð@À">mìÜËÐ}†ÎEL‰E'}(Z¶öœžƒ(`¶9r<òˆ™ ×öluS,c†ÇŽÛ ]=ÁÔTt¢X‰«Š-lÈ ­‚N=ù1·kØZ,Ÿ`ú0:ù áø”áÞrY²ÄÍ6§@†l C~6¿üÒèá*s.ˆæpš(0¢ðÊ;)x ‰¸Í#9s.t—bJ·sÏõn^{ijKÛ1Iœ0~ÏÚ§HLÁÓFÒQL!" ÙL@ý[fÞ}>»PôÎlgÔ¿T­Þu2›KcSË_g«Ê™0‡™fè:WZ¤JðáëçŸóo ¿ˆ/]ê¦>ëÓÇýÎ/æfhu\v™+,âêïàƒPKrtòÉÞ[Óç53æ K”÷a/}®B-¬! ÁQ˜·zΜ9>Gœ@•eÁ|àTàz‡]Ü÷å¾^q\~£j^å:tèàõŽ«ì>óy÷7ì,9‚é¿r”È¢u0o¿òz+" "xþý‘ú¶üïÝù N Kq \uUþui¯ˆ€ˆ@|¨o‹-×Ï?ÿÜ&C·£{÷î±­8Mkcú-÷!^ S¨öì <ø @—"ÿ #ÅÈ7Üð¾lY.ή½Öƒp Þ4]à˜±e ÀÑGû×Ðù"PÜy'0z4°v-ЩÀ4Týû».ÜG!ÏÏd—dzð£zànÚ9¦> 'ºiǘ‰€‚¯L[ÓædV 3”Gt´y3ðä“ÀøñÉ»zÎ…0ݪø;ÀðRò—bgŽgÿ–¶c’Ü£?hf‘ß3]Õ†}ÿ2cÈ•W†}¨Œ" þ-£n§s1ô[8å`Ãà7Â[I'­ƒ<Ûò3•Óíñ3rÞyç™éM¡ÔEQÚ˜·xçÎÀíâíEéªÈr4n Ø(#‹Àúme¾áÚµ‘#ªø– ݱ+íØ`.ît >¤ñÁX!"ò‚ U¥|»“ÖÀ••Ùåíu%ª,CŒZ~#&Ë9ÒçS¦LÉÙÂŽóè@#Œ9%r_x;qk"G“¿Ûƒ»–ôÁòJ¶Ó/<“² ³aäÎïÚõVD@Ò…€ú¶ðîT(}Ÿ}™"[!" "êÛbËÝ³âø´ÓN‹mÅiP‚(Ôád0'…ëׇ¹Íšåm<û~.,¥ƒEGþÁz®¿Þu(š=8öXwü”0†©Ñž{Î]ÈÉÔ]áDïÞ®Ëǰ¯¾–®hÑÂM£ÅÕÅ×\“=é©8üòÞ{®ƒ?¶ç\CÆôteSp1µÍ×ॗÜÅÖÔÓÓé)™AݪöÛ/™­HýsdzKÇ1ÉHïŽ ›‚³ -¾’‰^pP­pë­Ij„N+" )B@ý[ŠÜˆ5ƒ.¢\ˆ1w.ðøã¡›ìp‘Ë]–K¹™=l}i¢œ‹-Û¼yóì»ú –NºxŒZƒj˜ªŒ–ª§ŸІ–Šª`ù•i_ûÁÓŸñAiÔb9_Ê)Ì÷Ì1´‘bp`šœï¾ë¾×¿" "gEâ\ÆUïýŧJ•*a]ß_ýåSÞ_€´páB[ùON™ÃÌÿû@.É !µä§%K–ÄÖ­[Ò ˜Ç%A1ñãM²çt«ðªûs®}£8È:Ò²9Rˆ€ˆ€¤$õmáÝ Žø[›«G" " )I@}[ìnËn³óùÔT0­Zµ²´UþO|±;OªÕDS—q€Ü2Ê9Á±äºuSOuÓéÈ[aåàO° 08æÌ9nŽÇ:h.Ìôj¯¾êº(1=U¶ô>ó pÉ%Àg¸>æ˜z-Û#–sÙÎ2Þׯþ-]Ç$#åý‹) 4h`îofÿ§Ø² ¨‘é é`Ç¿?Þ¿9/Hsƒ¯¿êÔ‰S#T­ˆ€¤ õoir£Bl&õ/t­80t÷w Œ®2«x Œ(8zöÙgͶCˆgŒS±oFrÝ‹è`äù¡àˆaéÞÌý¡àŽœ.D\¯0a–“~Œ+N˜ÃÎ8)D@D $8 ò‹/¾hntfGgÎCé¶mÛË?ïÓù¯¢ùí·ß¼w›Èµ¡ÏûüÞµ§Öš5kšKž-K³Øi߯"ôY³Øü·Q•êåñËÅP Ô% ¾-¼{þ¶¾ÙpE¬wpÒ‘á=ñènÑ¿" " ‰& ¾-vÄ™bgùáähqו)ã¦3 t9L/E‘Ñû®CM›LIÆ4e\”M”+uT45„v,Û™mŽ=ÁÈpìÎQÇ».Uÿû_°’Ú.éA ^ý[ºŽIFr×6mÚds~óqî¹çFrxÈÇ\w+6bªLö;œ£¤ãƒçwóænúËÚµC®RE@D c ¨Ëœ[kEÎâ‡nÝÜtÒ]ÙßÿAƒáÍ7ß4³ Röö°óìY„9w“|0ä >\qŽ“Êav8 ™­tÏͶpU S¼-]êæÕN~«Ô,"ä¿ØéGÚ_$ê°“¤ 'ènäïúãínÄr„ÙQ•ãè¥W°>ÿsxíúrƒ-åä±~ø¡S†û)L¶$Z7߉óú•:6ò)±Æ¼ç90Žpʧ½ 8ók.)Ü{l…E›ÙÙзñ>ÿûï¿9}ïï©ö ¶_˜ê ~6-Z„îÝ»çùˆL˜à¦QãÂ:ê*D@D ÙfZ^':0f̘õë×'»I ;6ôm[Ì:?žç6ÂíÚµkÌ­æ=õwãˆqšÇˆ¹+lÙ•ÓÙÞWü¡CÕ«zõ€'Ÿzõ‚‰Œ=¥ô; P<ÆŒLwǹ.úµ¡ 'Ý\:^O¶·yΜ99‹íøšßñ³)âÕ¿¥Ê˜$ÇNùÌåé{xo;î8”.]:f·yúôéÎbÒ–-[ƬÎ@yҲ£] sj›ˆ@z`¶Šß©¶X¼x±¹kþ—žE«3½#šµ–ã—cŠž>ŽÙM:Ò’3C†0x0,À.öµ×òŽâüë$oµ¼¢·ía_ÒŸ°4e5hÿ— Á¼Ë|Hä›tXÍqÙeÀÇß|œ~*T²œÀ²eË,}¹ý?²XµjUN†¦,Ç’±—/ÁQní矎ÑLÌíƒÙóú…ÿ I¸‚#q êDàÉËΓ_|ñ…ÓÂbæ÷›Ÿà¨÷-µÀÿ`:5F£F¾B$ÿrz/" É$À‡xÏß;¶ƒ;»víJf“ÒâÜéÖ·ñ>ûßë“N:)lÁWÂ2µL ¾mâDØ2`šb…ˆ€¤:²yDµ´¨§8Eœ@ºõm¼ŸtÒõþÓÙl˜ö3–ñÕW_¡ZµjhN+†4 ‚LJ­œuÝï½/‡¢¢·ßvÓÝ<÷@gœd/ªõnŸ^GN€úò7ÞŽ8¸öZWxd:­œý ò³êÈxबçï'îèV£ÈŸ@(ý[ªŒIî0 >{î1¯ìûÏKÁ‘gâ#Þ‚#N¶2­£BD@ "°dÉ’œ¿{ü{¬ç¶‚ˆ¹ûÓ©c‹9çæ}¯ëÙ ‡LÑ è˜c`ßË€‹.rÝbùÌ,Ø÷ïßßRAOµqÔZ3fŒ³04Xù¤lŸ2Å=-sV§Cœx"‹°<èéÐZµ1 ¬°üÁžïô›íǯ™K@‚£8Þ[NZ3Ïèãôc÷ º"téÒÅk‹ûÒÿáÞß±(Ï~üËû¯Nò+ô-S³1UÌÓO?´L(;<‚#9…BKeD@’E jÕª>ï˜#ºdÉ’ÉjNÊŸ7]û6ÞgN–FÛ·yR—}û-Ý µZ>å?Äj d3Ï<üa|òÉ'øôÓO³èêC¿ÔtíÛ*V¬ˆ *DÝ·åGŠbÝY³f™s_fX÷Ñiþ½÷‚_ñë¯UªÀD[ÁËhOz !43 ´k˜ùúö•Ø(=ï$œqžEq“&MÂÿ”'/è­ §K•1É2–{ŒÏãÑ>·…b;<‚£Ã?<¿bÚ'"  #pì±Ç‚? þ2dˆóZÿ&Žý¯¤AƒÎó}2-(.â¢&M€Ã ~uŠßvÛmN?_ÈìÿhÌp§å¯Þÿýƒ”¬=&†r, [µJV Â;/WÐHl3•Ž+vöðÍq_F.EÆà(N·–¶Îì8™ÆÀ;8AÉíÂÿá>\‡#>”{‡“žIY Ž’ytnˆõm\ oKá- ŽÌÐóæåo»»¡šD@D@bA@}[þ§ØªN:ûÑ]"ÝbùrØJYàÆCo¹­½Qd0›ã¿¯ÑÕýœs2øBui"`Âíß2mL2¿'óé_¾|ùüŠE´ÏrÃÖº(D@D@âD@ý[œÀ†Y­N:)¨½+èûõx³š½ÈìèzÒ¡CǬ S6lá*èT¶lÊ6Q T!`’GE, 0Ù}÷݇ž={æ|òÉxóÍ7­ ÜAQÑëLeN0ǹwø;yïKÄk:1úºuë&ât:‡ˆ€ˆ@œ¨oË›Ÿàˆ‹q2 ÛLîÅꕈ€d0õm¡ÝÜüÑ)˜N‚#ËHGuWÖÞtàqÂíŠU*Ó ´m \~9LhéWªëËV‘öo™6&ìþ3M'«[ÅÁ­€Ž·92ØÙµ]D@D Rêß"%ûã^yÅMO=ztèuÓÙ¨W¯^Nº@ºS~kfJ‹xi? ŒúEª¤ˆ€d19ÅèæsÕç[o½å¤Oc.Vï Íý¶¬²GÞ›ó¼®T©’϶póÐoß¾Ýçøx¬Ôñ9½aNVºëŸu,çªï^NÊrÅPÑ¢E}w舀ˆ@ZÈÖ¾-¿›Ã¾ýu"úØüÚ¡}" " ‘Pß7 Žø<ײeËðLpi: ¾û®ûCç{S£1‹`›6î{ý+" ™L Úþ-Ç$#¹Ÿ¿þú«ãÜë~CÁ½{Ã^Â\"i™ŽD@ý[ *ÉÛFÙ>}€ZµÂëï† †5kÖà…^À%—\’¼ ЙE@D@âB î‚#æUÿûï¿ãÒø`•nÞ¼9Ø®¸lçÊæõ¸xNÂÕAçž{.®½öÚ ®Fž²ü]±bEï·&æ15O±mÛ6ŸÒ:Å;V­¾ú*ï .óè.0_Å.]ºÄ» ª_D@D ²¹oË'Ýû7nœ_íHQêÛ¿1?ýô“¹÷5GÉ’%Ã?8ÎGðñwøpàõ×aîÂîÉ8¸ààŒ3\÷û%âÜU/" )@ ý[:ŽIF‚žéÔ±qè›ë-Ÿ|hØ0’–éêßü‰$ÿ}ûöÀÑGt9ªQ#´ö¬]»ÖhE£FL¬Ô'´ƒTJD@D ­Ä]p´uëV$Z”È;0Ú|xàø§3ko=ïMæßΤd´÷«W¯ö¹ôDŽL”섟9–˜=—ø%B!" "^²½o v·Ö­[>$û÷mÿý¼öpÒI¡?l;‡¶‹€ˆ€ć€ú¶ð¹.Z´«l…ÉY´³M±øá o_Ø¢˜ó Я,­9pÜqî„oŠ5W͸ˆUÿ–Žc’‘@—àèC\ñ+Ól+D@D@¢' þ-z†ñ¨©C¿þ:¼š‡ê˜+Ü{ï½Øo¿ýÂ;8Ö¥9‡Ê‡ÈNb]³ê¬&wÁQ¦ÒýÏf™&müøñ>—Èb7ß|³©|Mæfø?Ü‡ë µbÅŠœ31ß²eËæ¼×‹`‚#ÛSC-ë‰zÕ+" 1' ¾-¤ž¾Í_pdiÇ´¢?üßÿå_‡öŠ€ˆ€$–€ú¶Èy3ãˆ#Žˆ¼’89r$pé¥@±bÀÃÁ®ãp"U)" )L Öý[:ŽIFr{(8ª^½º“&;’ãó;Fb£üèhŸˆ€„F@ý[hœÒ¥ÔòåË1bÄ´jÕÊ\h͆6QÁÕ¡ß}tíê{ÆÓOfÍlQ) öݧw" " à(Btt/òQà3`À'ÿh1Ž|F•+Wö9ʳêÆgc7L§æ-PjÑ¢˜Ò-Þ±fùv;EqgU©÷¹˜r†á?)ë]F¯E@D@R‹€ú¶üïG0ÁÑĉîqÇ“ÿñÚ+" "xêÛ"gžª‚£ãøC¡¯ u#¿¿:RD ½ ĺKÇ1ÉpïàŽ;lŽq–9Óš5m”Áj_~ \xa”épêß|p$ýÍ!@ýúÀùçGÖ”!Vç.ï¿ÿþ„ÌW:­Ü²8õT€+Dþ¦vÊm|çÎÀäÉÀôé¾ÛsK蕈€ˆ@â.8ºà‚ »¼Ú–²‡¼b J¿äSå¾(_¾<ž}öYPäMÐ ˆøžÔhí0]©R¥ ¬–â¤Ý»wç”;Ž^ò ˆ5ïL²³œ€J[—Úïš9gôŽäp”ƒD/D@D ¥ ¨o+øöä'8:ð@àÐC ®C%D@D@G@}[t¬)8¢ãE½zõ¢«(‚£ÿú øþ{ D X€#Ì­ÄŒ)ðùç¹ïõJD@²@<ú·t“ ÷¾Ïœ9;wîDË–-Ã=Ô§üo¿¹ó˜ì«Ú¶7öÙ­7" " Pÿ!¸86ap×]@ûö@¯^áquÔ¨Q8ÆVhžp qjå¾j)2bM!ÑèÑ®¨hàÀ¼¢"®½ï>7/œ·)¾­Sí" "ñâ.8êÛ·oFA\¼x1z衜k*Y²$žþyvØa9Û"}QØ,üN5åíK/½äT±gÏdý>¤Îx¢Ç^aßÉ;S©›€X³Ò9Ujb£À^Á/JU­ZÕk«^Š€ˆ€¤"õm¡Ýömt4¬Ë„åûbãF`Ú4 {wØJÏVýH6õmÑÝíÛ·cÆŒ!=‹Fw&àßrå|kùé'àœsÜm‡Øú…ˆ€ˆ€ˆWÿ–Žc’á~ ˜î ¦çóì1Çx¶è·ˆ€ˆ@*PßÝ]˜nƒ¶L=sÄGDWQGô`F¿xõUß‚<-q¹«j" " .xöoé6&îgÂ#8j¡£ÁSO¹ÎFÅŠãǽ{‡Û•F@ý[02ÉÙ~÷ÝÀüùÀ=÷6Ýv°Ï}çwlf÷ø½l&Ïþ-ÝÆ$ÃýL3kÚ*Uª„íÆ¾y³+.ºújXšQ€]dÇŽáž]åE@D@ò# þ-?:‰ÝgS’xäX R€FA‘Ä-·ÜbNð…pï½÷FrxþÇÐ÷ÝwÝÅõë]eW«Ø9ѵ+¬³ÏÿxâÒf—ÎH‚9äŽ>:ÐmB î)Õ‚œ7-7Ï™3ÇÒxχÔ_|Ñó6ìßÌ[Z³fÍ<Ç]vÙe¸á†r¶ßc2bNtžwÞyN*ÏŽ+V`À€˜5k–gêׯ /¼0ç}\_XÊ·5[K£òþ–O¹Š£yóæaïÞ½y&eãÚU." "õm¡a£µ3üÝû&N*Vš6 ­•ˆ?õmÑ3¦àˆéuÚ´i}e~5XÖp{f.N<–R6ùëWHoE@D@òHDÿ–6c’yèä¿a—©[¹¨³s˜+EþøÃÀΞíš'Œ™7 hþgÖ^‚¨+ˆPâöÛ”Ÿ³0„¿_xØo¿ðÏ=ÑKLJ .¸Íš5 ¿‚‚ޏñF·a=Y§L›z ¡8¨ÛºµïÙÌH«V={ún×;| Ä]pDáÌÚµksÁ|tPÎûtzAgïøá‡ÀŸHƒIGݺuÃ7ß|ƒ?þØ©zõîT5ÊIßV¢D L:K—.õ9u‘"EÌnþ.ŸT/>býƬ × .c ]½‚éÔþ“²^EôRD@D E¨o íF0ûoó,†¡k¯-ÚQˆ€ˆ€¤õmÑß Žš4i‚²eËF_™W öH‹K.Š˜šæª«¼vꥈ€ˆ@¾Ñ¿¥Í˜d¾¤òîüÔCÛ¶m3·³k1h8okBÁL-tz¸îºT1°¨ W\ ?ý4@¡ë¯?<üSш€îFÅ,ÿ(ç*cŸ}Lšäª¢,[LDqä‘°º‚#^¨wؼ«þB$ï2z-" "‡@ÜG´«ý믿rNìú+gcš¼X²dIÂZÊÎø_›É¤ðÈË—/EIËiö”ضNdGh‚§5hÃÊçÞ_¶Í3)ëŸv&P»µMD@D ¹Ô·…ÆßÓ·y ޾ýæ@paŒBD@D u¨o‹î^¬´…%dx •A1Œñã݉ÛZµ€±c)âaåªJD@²€@¢ú·´“ ó~ÿòË/ÎÁÑ›o<sgw3²0…§'(08xöY Z5€e;tðìÕoXPÿk¢‘ÕGsŸ[oêÔ‰…¯cçθøâ‹“†«-iVË íÒÍ7[²•’À!‘×ÌãÛ¶<»Þ6NS¦¸õÆÁé7òëHH}…Sµ‰#Í£ö±ÇËùa“d‡¿£P<ÛSªT)<÷Üs`ÇÌ×ùE»víðꫯZþðŽù‹ù¾ —ã(|ƒÖÍ;IpsäªPD@bN@}[hH ޾þÚ=6LWþÐN¨R" " Pß1:ç@º1Ž8âçw,það3Ï„=ÛŸ~*±Q,˜ªì#¨þ-Æ$ýûþ‚#Î-šáÞy˜<Ù·6N¸ŽtéLŸ.±‘/½ØPÿ{¦‘ÔH÷ÙM›€gžöß?¼6oÞŒÓN; £GF=ðÓÅ:Ö¬qFUp´9¹9˜»q#°OœÓT:ñâ9$g“^ˆ€ˆ€L îG7!p vLÞn>—^z©cøtb¶>øàƒàO¢¢páÂ0`€£ þ̬™küï¿ÿ]¢ªZ‡Z£F {ì±hÚ´i¢šäsžb+cn0Oaß´rL©Æ´y±¶ß÷9¹Þˆ€ˆ€Ä„€ú¶Ð0RpT®\9T©R%瀉Ê•õ šD/D@D E¨o‹îFÄZpd†I8ùd`ëV`Ü8Xª¶èÚ§£E@D [ $²Kõ1Ép?U¨Pµk×v¥–?6?j㬾µÕ¯|ÿ=l¼°¡Y…ˆ€ˆ@œ ¨‹3ધ÷ãÞ½O á¯"kLtÊ)§`й]f¹HGŒý¼]ƒ¼ÊFõ’c²?Ø\¤9)E´«¿ç7­š·›GÌ%öGÝhU " ©K eG©‹,ñ-ÛßµgÚS0R*,¥š5kú4‹‚£fÍšùlÓð&²}›w#½^SpäN©Ô<8ôP¯Bz)" "ÕÒ­o v³(8*S¦Œ-êŒ~U''rO=à£ã+¯( i0æÚ." ©J ú¶=–‚eÆŒûè¼ÈX^Ïy©ú‰T»D@D 62¡‹ ·jo8Î9|xxµ.Z´ÈJ'bÞ¼y¸ãŽ;,Û]áUIé¢E#9Ê÷˜öía®àè3U`,X¬_´ní¾×¿" " !à(dT*˜‡GÙ¹››‘'Ö®]‹uëÖùLÊzöé·ˆ€ˆ€¤#Mæ'L‡Á.ôÔß\èòÅžwú-" " ™A`·)j§ÚªN¦S£»E´akQ°p!0dpÁÑÖ¦ãE@D@D |\ÉT/­Zµ ÿ`!" " Y@`Âà?€J•B¿Ø_ý]»vÅêÕ«- Û3¸üòËC?8Ù%K–Úµ¾ýàªRôšC“ÞŽGÉn§Î/" iB úÄ4¹P53–,ªW÷ñ¦£aÆq8¡ªÄðômÞG‰o…Î(" " ñ'À4Þœ”¥à(A7z«wÞ‹ÚT‡ˆ€ˆ€„O`Ú´iÎA-[¶ÄòånµðkÑ" " "¹ènÔ©Sè×7ÁJGu6lØ€·ß~;:±‘ —0`ðÒK®ÃPè͈®dç΀-2Å¾ï ¶òÆ­OGÑqÕÑ" YI@‚£¬¼í±¹èç7Á5;6ׇÜú¸jˆ!ÁQ.½Hož¾M‚£ô¾j½ˆ€ˆ@Á˜N+ÁëªVÿ*D@D@D 9~ùåçÄ T­êÎ/&§5:«ˆ€ˆ€$—ÀÊ•À£FÞ†_|Ñq6¢#î¸qãгgÏÈ*£³Ðý÷mÛO? \r P¥Š›“ûÕWÿþ‹¬ÞP:æ7ƒË>Çá¨lYNn†ZƒÊ‰€ˆ€ì# Á‘> ‘°U¯ßü×Oüu¶oÏ­B“²¹,ôJD@D 3ø;1w¼Ÿy3ƒœ®BD@D ÝxGíh/aüûo„ê0ˆ ŽÊÚb¥Jõñé§ Ê”‰Ã‰T¥ˆ€ˆ€¤8Ó¡ysàúë}kMBnñž={0xð`\z饨Q£&Ožì¸…\wAtìÜz+Р0i0r$pÜq0pá…ÀâÅÞGÄþ5-8ÈËÜßvm @™éW Šý¹T£ˆ€d8 Ž2üÇíò–.Ÿ ]½óºrR¶H‘"¨[·nÜN­ŠE@D@D ‘Ø·qÕN{ž5Ë]xÃç^…ˆ€ˆ€d ŽêÕ«g“²î³^¸×gÎú¨];6Ü#U^D@D@bO`ïÞ½˜>}:Z´h÷ß/„mÛ€^½bÕ(" " ©B`çN`Ñ"€™Êüƒ†B;vï¼CW[ÿ½ÁßoÙ²gžy&~øatèÐ?ýôš4iü€`{¬_ÆSO̽ýóÏ®ò‰)Í,=úôq$iÁôÚk@³fÁj‰Ív›ÇD©Rn]s渫KÛ´‰MݪED@²Œ€ýEUˆ@Ê•ÃIg•Æ…–[Ÿ\=§:Õ©SE‹ÍÙ¦" " "Î(8ªY³&æÏ/öíá8û]w]:_‘Ú." " y ¬·Õ|žëáLìŒÀé§ÃDº°¯yë×H4… â_³Þc:5Î]/œqF¢[¡ó‰€ˆ€ˆ@büõœ±ËeË`ót€uƒ>1f ÀLfµjùlÎ÷ÍŠ+Э[7L3aPïÞ½Á”jÅÙ¡†óæW\|õ̱xùe×åÈ¿žÎ;Ïk|ßOêÖOD…ˆ€ˆ@Øäp62à°„çç¼u}3WlDKÅùóç[ŠSå8Õ§DD@D 3pE,'_5j„C­æèÞpùå™q}º ðà*Uö{G„³ÔÕs°ýÞ´ ØàÃã¿Õë´z)" " A 0£nÝ#ñõ×ÀÉ'´¸vˆ€ˆ€ˆ@ZxóM€b#f cÚ4ÿ¨nÓyáˆfت’¶mÛ:b£»îº £G_l4|¸kÏyCŠú÷~û-°ØÈ¿Á‰z?eŠ{&9%ЏÎ#"aäp”a74™—³dÉs}Ø.ÁQ2o‚Î-" "SË—/mƒ)8¢cÓ‰+D@D@D  PpĈTpÔ©“»‚¶dÉL¤£kHGÁÑ_ut"4ñKÇKW›E@D@²Àûï¥KÏ?”(€qãÆ9iÔvíÚe.¯™éP„®C|[Í \x!pÉ%nú´èšû£épT±¢›<öµ«FÈxeü-NÜÒ‚ÁIY…ˆ€ˆ€¤;æ;ÿý÷ùÎe¨oK÷»©ö‹€ˆ€DàÇ´AéhÞ¼yAEƒî—Ø((íH Žö7û½¯¾:e˧žš„Fè”" " "«V“'»©C£5 ýúõC¹rå@áÑ‘Gù¼ò pÐAn^ÓÈk‰ï‘l#­¡" " à("l:(?ÿüÓÙ¬”jèh›ˆ€ˆ@º<˜=Ûž[¨oK·»§öŠ€ˆ€„C€©ÔèpÔªU+-Z4¤Cwìpª6kRq„ à¨aÓ1uj!\tQôn ¿PD@D@B$ÀÔÖ{ö§ŸâAŠÝ{クýöÛQ§NŒ;6zƒpr¸iSÜ77hðG!" "K¢ð Pì{øáÀÿþ—{¬ÇáH“²¹LôJD@D } LŸüýwqçäp”¾÷Q-(˜¬_¿>ätj|d µví€3 ®_%D@D@D Ñ–.]еk×¢X±>Ω•N-Ñw@çH$÷ÞƒõyÀ)§DvÖÝ»w£ÿþŽØ¨eË–æ–49z±QdMÑQ" " iF@‚£4»a©ÒÜ•+Ýe“Î ŽJ•*…jÕªålÓ HG›7 òAýOÇ‚¿zõêéxj³ˆ€ˆ€„D`Ê”)N¹6mÚXþË/88ì°QH8©S§:ç\º´#ªTŽ;.áMÐ E@D@D !þý˜0Áíë˜B4ÜØ²e‹9#ŽçŸ'žx"&MšdYÐ, šBD@D@B ÁQT$/5kÜm•*åîãªX¹åòÐ+ô%0k`Ùe°mÛ§o+T¨Pú^ŒZ." " EpÄ~ÑÜõѵ+°k@Ëþûî kT¡ºÚ-" " nßÖ+W–Ã9çûí—ŒVèœ" " "Ÿ|ìÜ ôìþ¹Ö­[‡c=ü1úôéƒO¬²Ò¥K‡_‘ŽÈZE}åãÇG%o•Jl¦µ€W°“+^ÜMkâµ9¤—Tæ*bK`õj·>ϭܺu+–™¯þ‘GÛ©6H™3Ý“nØð­ìƒ“À_§H,º@T¨PuëÖ xb:Ûž>ðÙg@‹À»ïÂÊ,ª" " "Ø·/^ 5kîE¯^Z@’7Eˆ ÷ßw‚tï^õ›6m²%]ͽv n»í6ÜsÏ=áUà]zãF {%ï:ôZD@D - $\pôè£FêÎ;ïŒè8$ÁQÄèø÷ßXó«-oEUT®ì™?¾9Aì•ÃQ`bÚ*" "f<‚#`¦ Ž.L³Ö«¹" " ":]fW4cÆ têÔ)àA¿þÊgj`Ñ" o_`Ä D‰€EµQD@D@R†À´iÓЦMS|û­ÄF)sSÔ˜0/|þ9б#Ìì!ôêi"pÚi§9b£!C† š9X˜pÉr°W^ <òHèPIŒ pÁQFPËö‹3k£à膜/0L§ÆPJ5ƒþHs•(±ÓRª-‘ÃQšßK5_D@D ¿ÿþ;8ØÜ¦M›<·owÅF+VÏ?ôë—§ˆ6ˆ€ˆ€ˆ@ÊX°`Ö›=_ëÖ­S®mjˆ€ˆ€Ä’“Å\|1¬Ï ½Ö–íŒ3ÎÀ¤I“0hРèÄF<-­p©|jÐ ôF¨¤ˆ€ˆ@Æà(cne/déR¬AKç„Åôܹs÷5J`Ct*ˆ Ž*UZeéB÷JpĪUD@D E0å #Фìð᮳Š%6J‘¦fˆ€ˆ€H ¿¾­ÀƒU@D@D@Òˆ@ÅŠÀO„ÞàÝ»w£wïÞ;v,.½ôR 6,ôƒƒ•|ï= 9 †›Ó-X}Ú." "V §UkÕØÔ @ÁQ¡Ê(Q|/J—v›$‡£Ô¸5j…ˆ€ˆ@ôV­Ö¬ŠwÅ´r©jH]S¦LqçïpÄþðþûÝEª¤nûÕ2ð'ðóÏìÛ tïó/«÷" " "-öîÝk Iúáí·ßƹ瞋çž{.ÿK§s‘9âæ´Å5ñÚ·wÓªå[X;E@D@2‘@ÜŽÞ3eëž={2‘]ö^GE«¢RåÜèd9ZË–-›½\tå" " A€îFŒ;¦¡jÕª(S¦Œ»AÿŠ€ˆ€ˆ@  ÄÁŒjÕªù\Ýôéî"ÕGŠóÙ¥7" " "Ò¾ü’}Øb,]Z ¦tSÕ8HbäÈ‘8õÔSñÊ+¯ pá|<)hs{ýõ@¹r€Íÿ¡J•Àí?Ø´ÉÍŸ„¶Š€ˆ€d8¸ Ž8à€ G˜…—GÁQá*–j&÷Ú)8jÑ¢Eî½4%àýóÏD´m«T¡izÕll·Õ¨3­ãëÚµkžÒÜ´hP¡Bž]Ú " " )K€î ³g7ÇÞ½5Q»vÊ6S ¨ ¬[úóÚýf_û„å^ëܹ³ãpT´hÑàçÿê+àÆ]‘­oùzÔ¨ÀåßßÝ~úé÷k«ˆ€ˆ@ÆÈG¾šñ×® Œ„À–-À?ÿ`Í®ò9‚£Uö…cÆ hÔH“²‘ Õ1" " ©EÀ#8Ú¼ùGõm©ukÔøõ×_±sçΠ)g$6Š1pU'" "wüñ'ví:ÙŒ–£~ý¸ŸN'¤0}-=44c¡-6¯÷àƒ¢I“&øè£P¢D‰àm^²–o (]øö[Øê`Þ<€©Óüc÷nX…Àa‡õêùïÕ{,! ÁQ–Üè˜]¦¹mEIü·«DŽàˆîFŒÆÇì4ªHD@D@’Eàâ‹«®šo§_'ÁQ²n‚Î+" "S¦LqÎÓºu넜O'x˜>}ª¢) ú#Þ§Rý" " "4?þ¬XÜ„wß}7n´ñΫLGdB¢`±u+г§c:€Ñ£ €7Þ¾û(^<ïQܾfMhª§¼Gk‹ˆ€ˆ@†à(CndÂ.ÃG;P ç¶žŽݳΙ3Çy!‡£„ÝHD@D ŽØ¿vØç êÛâZU‹€ˆ€$ÀÔ©œ”EŽÃ­ŽŸôf©" " "1WL» gŸm“¤ ÈPßï^X(™ÌFŽiz¡âèÕ«Wþ4ú÷~ù28õT·l¹r@¡BS:µÀ\´UD@²Œ€GYvã¾\•ÿxýžùàw†Ž\úWD@D sxú6 Ž2çžêJD@D@òà¤líÚµQ±bEgçðáÀñÇ3·¬¶ˆ€ˆ€ˆ@: ˜¶‚å­S§N:4Wmˆ\=°`äøâÅ‹1qâDôèÑåË—^ø‰'€W_ºun¿=x9ï=|ëpæÍ½·êµˆ€ˆ@–à(ËnxÔ—Ëü­Œš5Ýßö/ލޮU«VÎ6½t&@Áû6NÂ*D@D@D  lÞ¼³gφ'ÚªUÀý÷õë»cÌ™xͺ&Ì&°{÷n̘1#§oËì«ÕÕ‰€ˆ€d;ºu &0jÔ(ìÝ»}ûö ^ø›o€ë®5rEG… /ëÙC'$Άb±ä9F¿E@D@2’@‘T¾ª… bG=£ŒöíÛGYƒÏ!`GNx Ž8)Û°aC.,ýZ'½HK6÷ŠR¥\÷¾ú6㪾--o£-" "_l€xÏž=9éÔþûhÕ 4(V,„ TDD@D@RŒÀ-·¬Â–-Çšàè°k™š#" " ‰'@¡ÑË/¿ŒjÕª™“­YÙŠ~Î: (Y`Š´²e•ʻ͓N­gϼû´ED@D «$UpôŸhþüóϘ™3¹g‡õmÛÍE¸QøèHS§NE!³ÊoE[#…ˆ€ˆ€¤9>‚/smíJ©–æ÷RÍNÀãl^X° xÏž—^zÉyÙ§OÏ&ßß­[Ùìûýw Gß}ù½›;øãØjM˜’)¿’Ú'" "ÚP˜òÀओN‡~èUâɸxñâ&®U:µ˜1¦lùr|_¨#ÆŒqEÏsæÌqª×¤lÌ(«"$ض °l®8øàµN Ô·%éFè´" "  !@‡#¦Æ.ªe~BZ¥“ˆ€ˆ€ˆ@dÞxƒÇíB¥Jß F‘U¢£D@D@D Å Œ <û,@g¿übãÆxÏ\ˆ:vìˆ .zõÕ0GتËÀûƒm5Ë Tæ“`„´]D@²Š@ÂG›7ovÜŒFZoHáQ$Q’9D ˆbÅŠaÀ€&ˆ®Ø5jTGhwÈV®vìÀšý‚avR¹zÒÕÉá(dŠ*(" "¢J”þù8æ˜Jp”¢7J͈šÀ† lEì´hѷ߬_u•ª@D@D@’F€ýظq{͹ï+sÔ·¡ È@Lóæ›@³f°g¹ü/ð Sânݺ}ûöÍ¿`${:ÊÍÇÝ¥K$Gë #@ŸÙ„Ä Aƒ0iÒ¤€çªX±"Š-pŸ÷@Lý@IDATÆqãÆ9ošý€çgüøñXI!̾Øa‚˜õö”ÙšV€ŠØàÊWSD÷]°?ŽÙ'Uó8qe¬BD@D@Ò@¹r°ïÓœËPß–îwSíF€‹s˜ÂüßûãÞ{éî\ye°ÒÚ." " ©Màý÷™N­5òu §ö­RëD@D@¢ ðÙgîbÉÁƒ ®„æ¥J•ÂÙgŸ]pápKx Ì:)Ü£T^D@D C $DpôÖ[oe*Xvv;wF‘ÿgï>à¥¨ÎÆ?—Þ«ô^ED" € DM4X"vË_ú¾ÖÄ{‹¨¼v4±DÅ®DEQQ, `CAޤåÃþÏ3¸ÃÎîìÞÝ{÷ìÎìþÆÏ¸s¦œ9ç{–}¶œ{N•Ä¢””èEïÒ¬Y3Ñ5:Ušvdºçž{D{ëFÝHó»îºë¢»x̆€ys"fˆÄãcòÒŽZ¶lÉ0ü1&l"€„[@c[“&M¤Q£FᮥG@ ‰€N§&ÒF>ø ì½·Èùç'9‘Ý €„@@¿®Re‡lßþ†épôlJL@È\@g?«d8ýôÔ×ê@'N”³Î:KêÔ©“údŽ"€ PAëSªmذAîºë®„bÞvÛmòøãË!C|;%\d‡Ë[n¹ÅL3ú/iݺµ{ÖÓO?-o¼ñ†›fÃŽ€þ(Ë”3vlÉ@ ?Ķü¸sW@Ü èG%%÷È–-•åþûõGÚÜÝ›;!€ MŸyÿ}‘V­¦™l×2ÂQ6qÉ @ 0:}è[o‰ÀAc^êbéèFºœm:‰™†@›Ö;é4h7ntë £i¤lã×·o_yä‘GLïÞÝUºõÖ[eñâÅî½ÙÈ®€Ne·víZéÖ­[v3&7@ò `d”É“×ÈŠ+èL›n‰ ;?3¥ÚÉ2t¨˜?ÊÝ}¹ €ÙxõU‘;4ל?FmÞ¼y¶oA~ €ä]@¿·Ü²Eä÷¿O]”&(ê :u’ƒæÎÙg‘o¿M}G@¨€ÀîÞ9È$Õ¥£Göj¾Ñ<á„<û²•ÐŽ/§œrŠ›]ii©gª5÷YÐaua„£¬p’  €@ô¯bO>Yä¶ÛÌ'w³tíÚ5¥áÖ €ØXºt¹,_~½ùcí2b„½û3 €¹xï=^&"‹dt£\€s@¼ètjµj‰ù}5õíß}÷]Y²d‰\`~+-¹új3øßZ1=rS_ÄQ@* `µÃ‘µI“&yŠ÷û²ºßzÎÎ\̦©/â( €°Úá諯¾òm¿ýö3£÷™áû,.ÚÙè¸ãŽsï Ó~Mœ8ÑM³Q1Ã)óç‹éÄ%ÂG³äj@àD;E"ß8…¢ÃQpÚ†’ €dO`Ý:‘üC{-•ë¯Ï^¾ä„ €@>ôXý®²E‹ÙÎí÷ßÿ|ƒ{"€ `UàÙgwe晩o£¿‡¾õÖ[r^ß¾RW‡D0 ì9ØRgÉQ@ʰÚáhùòåžôéÓÇ“¶•èܹ³'ë)S¦xÒ$Ê/ SÎèҤɮŽjÔ¨!m۶ݵ“ÿ#€ Rh‡£µk?–*Uª8󜇴*@¤:…Ziimënèžô< € êÕÅé@[£Æ;Nqép†V£Œ €™ hß¡æÍÅŒR›úÊ+®¸B¶mÝ*wê4jº<òˆHIÉ®mþ €€%«Ž–ép}1K‹-bRö6;vìèÉ<¾ã“ç ‰Œb;éG]»vu†gÌ(NF@ `ÚáH?¸Ï;E:tè U«V X ) €xÇü[R²JzõúZªU«Vñ É@< ´j%rûí" þËù׸qã<–†[#€ }I“D~üQä´ÓD*WNžÿ¸qãdÔ¨Q2¢W/iôý÷"_,²ï¾É/à €Y°Úá(¾£OË–-³TìÔÙtê¤CÄï^â;>í>ÂV¦ÑGõêm‘yóæI·nÝ2Í‚ó@”@$"2}º˜i_#2{öla:µ@5…AÈ’ÀÆ"_|‘HäcéÛ77£g©èdƒ €@RÒÒRÑ?Šdt£¤D@±€NóÞ{»ú%«ÆæÍ›å¢‹.’ÖµjÉÿ.X Ò¬™È­·&;ý €dU JVs‹ËlÆ ž= 6ô¤ËJ\xá…rÊ)§¸§¥ûW* 40=}+ËŽ;œkŽö’qsb£¼Qʵk”;wò£ly!¹@ 0sæèô2b¦]+[¶l!¶¦e( €@6.Ôï×Ë¢Eñ£l6aÉ @ ¯_~ù¥ó0ŽòÚ Ü@À’@%3lÄ A©3¿ãŽ;Ì(H?ÊÌ}ö‘Êß~+òÜs"õë§¾ˆ£ €dIÀj‡£FyйjÕ*Oº¬D3Ó W×L—õë×»ôZýñ%;Ë—‹™fFdÉ3$£Yá(;®ä‚ ?NM—zõæ9Œpä0ð?@0³aË™gÞ%ýë}Ò§Ï/Á¯ÀêHu@ŠG`ëV1ÓƒŠL™2Å©4ŽŠ§í©) €Ànåoøðár›™g´‹v6Ò¹×teA@ GV§T‹‘hÉ’%9©ÖÊ•+=÷Étd%ÏÅ$<:ÂQ“&â U¬øQÖÃC@ „ÑG•*MwJOl a#Rd@´>øàÑÏÇ{ï½wZçs €A¸å‘–-EÆŒùVªT©b:Óš9gX@(2)¦ë¶mrÝŠ";Š<öX‘ P]@| XípÔ¢E Oý&L˜àIÛJLŸ¾ëÃhþñŸ¢ûyÌ\ Úáè‡~p.æGÙÌ ¹@ XÚáH‡'^·n¢S0b[°Ú‡Ò €dG`Íš5Î(ƒ6qÏêWÙ)0¹ € Bà“ODÖ¯Èĉ¯H¿~ý¤nݺ)Îæ €áX»Väî»EæÏO^î§Ÿ~Z&Ž/ÿ1TRiÇ‘çŸ×!Ü“_À@,Xý–qàÀž"üñÇæÇ¼už}6ï¿ÿ¾'[¦ýòpT(íp¤Ã4¶2C4Ö©S§Bùq1 €ùÐG;‹Ìžý­™Þ¼~¹¦sÍw¸? €e ¼÷Þ{ÎÔãC† )ëTŽ#€ híÛE&OÙk¯5¦ÓÑZ9âˆ#]^ ‡ €@¦o¾)rÍ5"cÇú_©3½üéO’ÇjÖ”–«V‰Üv›˜¸þ'³@‹V;µmÛÖŒà×Ñ-þV3¹öƒ>è¦mlhÕaâc—Ä&Ù.§€Î®½ªuJ5ሎ\å„ä2@À˜‡¿êÑcWlct£À4 AÈ¢À‹/ŠÜxc#“c3¡ÃQaÉ @ /f5™7O¤oßgœûÓá(/ÍÀM@, ¼òŠHåÊ"Çç“«®ºJz›iÔÎÚ´IdÐ “fA@ V;i…~ó›ßxêõ¼Òï믿öìËfân3Æ`ii©›eC3”`ý‘¥Â:¬.5kn0=´^øQv—ÿG¯@Õª»:ÓÞwßzY¼x1±-¼MIÉ@R¼úªÈwßbþ ¨…tèÐ!Å™B@ {ì!2uê Ò AéÓ§O8 M)@HS ‘óÏÑx¿L˜0Až|òI©røá"×_/ò¯‰™7;þ4Ò €äDÀz:ûì³¥qãÆnev˜yD/¸à™3gŽ»/[£F’Ñ£G{²ÓûWÖnÀ,пºøb‘¶mròb„£ “’ €@4¾­X1Ó) iÐ @ ëãÇ›¹gä9ê(ó­5  € °fÍ3­Úd3¨Ã ¾û-€ö¤  €^°èÑG½û4µÝÌ+zá…JõêÕåÁ¿ýMäöÛEZ¶L<‘= €äHÀz‡£:uêÈ¥—^ê©ÎêÕ«åŒ3Î>úȳ¿¼‰MfÈÀûï¿_n¾ùfOõêÕ“ÓO?ݳDùš6yøa‘¦M?v2áGÙò[r% €@°tªP]ˆmÁjJƒ Pqó7?fµ &£û˜N­âœä€ ÷ß_ô[™N- B1@r"ðÐCÉôéÓåšk®‘N:åäžÜ@TÖ;é͇ –ðáoåÊ•rÞyçÉ7ÞhæÜ6“n—cYµj•<øàƒr衇Êc=–Ã_þòÑO,Ùˆþ(ËGÙu%7@ü DcŽò×Ü@ÀŽ€ø»qãƒR¥Ê Î(vîB® €äF`éR‘_3Êý'Î ép”wî‚ ¥&êÀ :MöÕW_ÿQ@Œ@•\(T2s‡Þwß}rÖYg™¹µ§znù¢ù„¨ë€œŽC={ö”½÷Þ[ªU«æ9oçÎòóÏ?Ë¢E‹dñâÅòùçŸË믿.[·nõœMœxâ‰rì±ÇF“À €yÈÉ”jÑ:j'¢'žxB®¼òJ©¬ãº'Yt4£5¦ïÂ… åûï¿wÓélT¥JÑiÔFŒAïÞ$¶ݽiÓ&g <¦œ©¨$×#€E ‰ÈÌ™3…Ø”¡ €ÙزEäí·?p²cÊ™l©’ €@>´ÃQ£FëM ±-Ÿ-Á½@²-°q£È˜1"íÛ{;騵_|±T¯^]xàlß–ü@¨@N;iIuº’óMÝ—_~Y?ü𬌒£yêÌW_}UÎ<óÌ pqjY³f‰þ0Û­[·Ô'r@hçæ=ŽBÒ`@ mwÞ¹óΫ͔ØgHß¾}Ó¾Ž@¢ÀêÕbþ8UL\ûRôO ÄbR&@Ê% ŸßJKE† ó^þèý÷KÕiÓ䪫®’N:y’B@ Ï9›R-¾žÝ»w—GyDæÎ+Ï<óŒ|øá‡ÎHFñç¥J·jÕJhæí>K:vì˜êTŽeI`ÆŒNN ?Êšž×¢‡–˜uñ/«n÷3ëÙf]þl:{žÎA{¥YO0kì2Ø$–š5bÖ¿<êv4m6mMër²YÿêlíþßefSïQÕ¬zß™5vÙÓ$˜Uó×EË¢«.ÑÇhþúxŽYу1Ëqf{ì/éûÍ£êÒ³ìeRË̪ùiºÆ×'zsÈqzX7b–KÌöd³Ö3ëÿšõ³Æ.˜ÄB³šy}eSì$Û™ýÅ;ڤǛµ²YõØÌ»h=VÅìˆZiwÅèvôQë§×ßs¾nj?ÀÏÌZݬ·˜õD³Æ.Lâg³nþeÝjcmLÒ]tÿf½ÇݳkãHóð¡Yµ,™õ,³Æ.MbYõUOW­¯Ö!Ùò{sসƒ§™ôWfm`ÖkÍ?réŸÌ¾fÕö0_‚9«n'{žésæz³Æ.šçç¿ìxÔ<Æ?w;˜}æC‡³Dô1ºêØm}Þܦ;cõŸjVý÷q¯YãG ?ÝìÓrGÛCõù¥;Ìß Í¾øzüÚì›bV­ûH³Æ×£µÙ§yÆæe’ž²k:º\j6n&~yd£V7ÛZîØEŸïZG}>­7«¶ÿ†_5mþâßyèó@W­Çåfe):NM—„ØVtT@ ÐÞ{OßðT—lr”áB«7õA(LO?5_˜ïV¬-ýúõMŸ@Bxåóó†ù}ㄘßÌ–-[&[®¿Þù|ûJU© €@ èÏîy]Ú·o/7Þx£S œ“'O6s“þàL©¶víZçQ§XkР»vîÜYúôé#Úáˆ%·ÑeÝ޾0÷ܬϙUÀ_ôÇý³ãv.3éùfÕŽkãŽiR;4è¢BôjÞ`¹«v д.ÑǺ»’žÿkY´ãÇ6³jâ—_™]̪÷Ðrøuzˆæ¯{™5~ÙÏìˆv¾ð{*îkŽk4oÍ#ZvÝŽ]MÒYöŒnÄü¢Àè_.жˆ]µ}´.zŸØ{i~ñK'³CË™ì9ÑÓÓß¿bó‰Ý6‡<‹_=ö3ghùôºž³w=Ÿµ£“¶stÑçGô¹¨õÍ}ësAŸw,E)mt8*Êæ§Ò €@A üç?ÚS}ƒùÂzï‚®'•C(NM—͛ߓ!CŽß•àÿ €€Àfó]ú[o‰ùcóóFÌïžsŽÜ`æÊ^o]h0dHÔ”* €š€ßOÍy«c³fÍä˜cŽqÖ¼‚§ÐŽj™ÿöžd¾°þ£9õó_Nïmõs¾¾Òº¶0kc³Æ/ÏÄïˆKK—'©?R-ϧ:˜æ±›Ê8ï…2ާsøÉ2Nú Œãé¾½Œ“þ]ÆñtëH=©ój^n+#‡7Ê8žÎá²êñ½ÉD;²ÔN'³$çĤÚ»ñ;Ê‘~¢Œkü:é•qIÂá‡öxwŒñ&Ë•º/ÅUÚ1J;n骉´]´# >t8òAa €@èÌl¡2{¶ö°~[Ž<òˆÐׇ €  ŽªUÛ,[·N“#Žx @ Fà]ó½ÿó½ü‰'î®Ò§| '#3ìQƒÑ毄Ít¢, €M€è´ xyº|ÒE–”,‘êš¡B´SÅÿ3ëfÝ?à§xäB y.nÂ=ÒÐQªteA  ípT«V-iÝZçúcA@ 0&M2zî¬, N—N†F¥¨ €@Ñ l3£4›ñ¥fͯÍZWúöí[´T@ ð¢Ó©E;mß¾]fœ|²œcªºòŠ+¤ñ>:…  €ÁÐÉnXB$°ÙŒ«¨SÏé›|,S–M‘µÍnV:å£)¸' P0ùŽm3gΔ®]»š9Ò£óú -AÈ“@¾c›VûÍ7W;µ?ä>öçéiÀm@‚Èwl›:ÕÌno¦·_·nŒ –!C†íJð@Ê)¤7nœv¨Ý=ÚfÇ‘O?-ë+U’¦ï½'¦—m9kÉe €Ø Ã‘}ãrßaÁ‚rõÕWËTýž¸%‰ÈòåËåµ×^sÖAƒÉðáÃ¥nݺqgf/ÙªU+Y±bEÞFWÊ^MÈ @ _A‹mÕªU3ó£opÖ|™p_@p -¶©æŽbþ`e³õ¹yäaá¦ô €9blÓG%%;L‡£IrÄ:ä:  €™ 1ƽüò®zètj;Í÷”‘㎓f×Ì#¤[·n™W’+@È¡c«ç;“[ýl†J<묳|;ùåóþûïˉæÝˆ^gsiܸ±4kÖÌæ-È@ @‚ÛªV­* 6,Puª… `S ¨±íË/w˜?©)­Zý$ èWÕ, €¤'ÔØ¶y³HµjÓ¤S§æÒ±cÇô*ÃY €Ä1ÆmÛ&òï‹ì¿¿Hûö¦“Ñ!‡H—åݤۥ—Æ”žM@‚)ÀGl—-fÂÖsÎ9G.\è–®FÒ¿`ÞdôêÕKÖ¬Y#“&M’Q£FÉúõëóæÎ+×^{­<þøãΔkîÅl € gb[ž€Û#€d] ȱíùç˜ú¶—ƒæoŒ²Þðdˆ°@cÛCÍ–ÎeF7º €[€ª!€ØjŒ›1CÄÌœfYñ—¿H·/¾±µkËacÇÚ¢ _@²*@‡£¬rf'³—^zIfΜéf¦#/<ùä“Ò»wowŸn 8PN>ùdùÃþàvNÒyg_6ã/žtÒIžsI € Ob[>õ¹7 €€ Ƕ±c7š*ï4Ÿ»Ø¨:y"€¨@°c›þðºS† R úT @À¦@Pc\"Ë–‰lùïGRã7wŠé$µ_yEjÖªe“ƒ¼@Èšî˜5Êìd´uëV9r¤'³;ï¼3¡³Qô„Ö­[Ë=÷ÜM:úƉ@ Û‚Ò”@ [Am3g65%û­ Ü'[U&@zl7nœT®\Y Tà-Aõ@²-ôWeéB©tÒ1R‰ÈK§ž*Ž:*Ûä‡ €€5:Y£-_Æ£G–åË—»~øá2tèP7í·¡#õíÛ×=4mÚ4Y°@‡ÐgA@ ÿĶü·%@È®@ÐcÛyç=!§œò_©R…A³Ûò䆮@Ðc[çÎeذaR¿~ýÂmj† `E Ð1nËÙrÌ1RcýzùS“&rEÜ€V@È@, Ðá(‹˜ÙÈêã?öd3xð`O:YbÀ€žCcÆŒñ¤I € /b[¾ä¹/ €€- Ç¶G¹Fž{î [Õ'_@zl>|¸Œ5ªå© €€m@Ç8óG"o­]+w„Ÿ}VêÔ©c›ƒü@Ȫ޲ÊYñÌ&OžìfRRR"‡rˆ›Nµ;‘žG‡£TZK&ðÌ3ÏÈßÿþ÷d‡Ù_À×]wŒ?¾€kHÕò)@l˧>÷VsÎ9G¾ýö[0ŠP@ÿŠQ§'fA ÛĶl‹’_¦—\r‰Lœ81ÓË8¿Þ{ï=ÑÏo,d[€Ø–mQòËTàÚk¯}c)>Ï>ûL.½ôÒâ«85Ι@cÜ3²Ñð¦Må'óÝÕG‘3n”;o¼QtjX–â8ñÄeÑ¢EÅWqj\tŒ¯ &Ÿ3gެ\¹Ò-QÏž=¥qãÆn:ÕF=¤fÍš²iÓ&ç´Ù³g§:cø ¬[·NJKK}±³°V¬X!7n,ìJR»¼ÛòÂÎMãô5nÛ¶mq{Iƒ€Æ¶5kÖCU©cˆm9ÄæVIô»ƒ-fú–âؼy³¬^½ºø*N­ Û¬ò’yšúÚ¦¯q,Å'°uëVÏï"Å'@m =Æ5hÐ@>ýôSÞÛÛ|ä9oýìýí6ÏEáö9Xºt©ìر#Çwåvä^€ŽrožôŽß|óçX×®]=éT‰ªU«JÛ¶mÝSôG5í<‚ €@>ˆmùÔçÞ €6ˆm6TÉ@ ŸĶ|êso@›aˆq•+W–ZµjÙd o@¬ 0‘5ÚÌ3ŽÝH¯ÖžÍ™,õë×÷œ®ùÕ«Wϳ/„/ùõ×_»Ó¹éÔnûî»o:—rNÈ~üñGÙ¾}»,^¼8ä5¡ø™ |÷ÝwÎÿùÏ2½4ôçë_üðÃn=´ÃæªU«$þ5Õ=Œ‚Û¾úê+ÑÑÿb§*Õ‘+U¢ïuF Ò“5®ýßÿýŸ4lØ0¤5 Øå˜?¾ߊuxþ… ŠŽð¥‹Æ;ý“¥âA‰m3gÎýk¹ØØÖ½{wÑ?Fa)|}_£Óa¿öÚk…_YjèX²d‰èZ¬±Më¾lÙ2ÇDGùbKÏӣ܉ Ä6}ß®#oÇÆ¶nݺI5Ê]7. €Nƒ­ßÇŒ;6<…¦¤YøùçŸEG¡)ÖØ¶|ùr÷ûxí‰Qè³ò´r3 JŒ›0a‚èwðÑ׸ڵkK—.]Ür²Q¸ÚéMÿ3mhá¶q²šéÀ ·Ýv[Qv(Ô÷tú½¬.ú™míڵɘØ_t8 P#ÆÿcË´ÃQ|ç"}#Õ¡C‡ŒkØ·o_ùþûï¥E‹εúcì~ûí—q>\>UkçÎÒºuëðžWH@Û¼Q£FÎZ¡ŒBx±þÛÔÌ“]æÎK§„(FƒÛ´ã¬Æ·V­Z¹µÒØF‡#—£ 7ô߸ŽY§N‚®'•KÐ/®õG«öíÛ',‚= ,p¾ÔÒªªCüç…" °RŠĶÎ;K¿~ý<ïݵ3-ެ4{à2ÕÏëÍ›7§“|àZÆ~ô‹[]õ5 í¢ŽtÑdyÍËγ (±M_Ûôs[ì(îÚ™–GÙiç çRÌßM½ml—O_ƒ´#ýž{îiûVÌ_;Òê‹è¢Ó Ò™6»Í”7xð`ç½»~¯‹~GU¬Ïùì¶pðskÓ¦3ÀDãÆƒ_XJ˜Uý÷®ÿΫW¯žÕ|ÙöQÐßÚtÑδëׯw¶ù_a Ðá(@íÿÆ'ÓÑ5âÏï¹nU>ø`Ñ•@Š %¶õîÝ[ž|òÉŠV‡ëC*püñLJ´ä‚(”ئ ûÔSO‘ˆ2!€„L (±M;R>óÌ3!Ó£¸ €AJŒ;çœsDW(¾“.ž¶.öš2H€žño|2á¨nݺžÚlذÁ“& €@®ˆm¹ç~ €¶ˆm¶…É@ ×Ķ\‹s?@\ ãr%Í}@ŠU€Gjù’’OiªU«æI—•ˆj3~Ä£²®ç8 €Ù ¶e[”ü@ò-@lËw p@l Û²-J~ €A Æ¥%( €@¡ Ðá(@-Û¤IOi2ÏpË–-žë6lèI“@@ ×Ķ\‹s?@ÛÄ6ÛÂä kb[®Å¹ €@®ˆq¹’æ> €Å*@‡£µü{ìá)M¦Ž6oÞì¹¾Q£Fž4 @r-@l˵8÷C°-@l³-Lþ €¹ ¶åZœû!€äJ€—+iîƒ P¬t8 PËWôÏòåË=µ¡Ã‘‡ƒ €@ˆmy@ç– €VˆmVyÉ@ Ķ< sK@œãrÂÌM@ŠX€Gjüø7>K–,ɨt‹/vϯR¥ŠÔ«WÏM³ €@>ˆmùPçž €6ˆm6uÉ@ Ķ|¨sO@\ãr¡Ì=@ŠY€Gjý¦M›zJóÅ_xÒ©:Zl¥^½zIIIIªK8† €€ub›ubn€ cb[ŽÁ¹ €€ub›ubn€ 'b\žà¹- €@ÑÐá(@MݵkW‰}ó3sæL)--M«„Ú9iÇŽv·Ù@@ _Ķ|És_@[Ä6[²ä‹ /b[¾ä¹/ €€mbœmaòG(v:èP©R%9æ˜cÜíܹS>ùä7jcüøñžÃ‡v˜'M@|Ûò¡Î=@l Ûlê’7 €@>ˆmùPçž €¹ ÆåB™{ €³ŽÖúÇ{¬§D#GŽô¤ýkÖ¬‘—_~Ù=Ô¾}{éСƒ›f@| Ûò©Ï½@lÛl¨’' €@>ˆmùÔçÞ €6ˆq6uÉ@ Øèp°g@·nݤK—.n©¦M›&Ï?ÿ¼›Žßذaƒ\xá…²qãF÷ÐI'än³ €@¾ˆmùnî mb[¶EÉ@ ßĶ|·÷G°%@Œ³%K¾ €ˆT®ÂÍ7ß|‚¹¾gEòàÚD:uêȸqãÜ&LúõëK÷îÝE‡Œ.‹/–óÎ;O¾ùæ›è.éܹ³Üu×]R¹r…šÖÍ @²!@lˆ"y €I€Ø¤Ö , €Ù ¶eC‘<@‚(@Œ b«P&@QR‘JD"‘™ëϨH\ë/ð§?ýIÞ|óMÏÁÖ­[KÏž=¥F2eÊ™?¾çx•*Uäé§Ÿ–ý÷ßß³Ÿ €A ¶¡( €@6ˆmÙÔ$/@ Û‚Ð ”@À†1Ά*y"€¹@k:ôPZZ*—]v™|ôÑGi•°fÍšòðÃËÀÓ:Ÿ“@ȵ±-×âÜ@À¶±Í¶0ù#€äZ€Ø–kqî‡ +b\®¤¹ €@ ´®Ð¼[L©fï©R­Z59æ˜cœ)Ô¦OŸ.Û¶mKz³~ýúɽ÷Þ+}úôIz@È·±-ß-Àý@²-@l˶(ù!€ä[€Ø–ïàþ €¶ˆq¶dÉ@ ˆ˜R- ¿qãF3fŒL›6M–,Y"šnÙ²¥´iÓF $Ý»wC5(# €®±Í¥`@ @ˆmÒT@À ¶¹l €˜1®À”ê €äK€)Õò%Ï}@@@@@@@@¡@ëJ!,4EF@@@@@@@@< Ðá(OðÜ@@@@@@@@0 Ðá(Œ­F™@@@@@@@@È“ŽòÏm@@@@@@@@£ŽÂØj”@@@@@@@@< Ðá(OðÜ@@@@@@@@0 Ðá(Œ­F™ N`Û¶m¢ëöíÛ³V·U«VÉ‚ ²šg´p›7o–eË–….ïhùóùXZZ*óæÍ“¥K—ÊÎ;­eåÊ•2cÆ Y·n]Öó§í³NJ†¬@Øb›6¯q{:ÚŽqķеW#€@ÅlÄ6-ŸÝ*Þ6¶r ¶ùËÚ|ÏäGö"€€-b›W¶^߈mÞ6¦Š¡í£uåb ¾y[¹Ð_ãÂÛ´¥l¶Í¼½Ï2RÅ,P¥˜+OÝ‚Àرcåÿ÷¢ôéÓGž}öÙrëÇ”×^{M~øá§³ÉŠ+œ|*Uª$M›6•ƒ>XÎ:ë,éÔ©S¹òŸ0a‚<õÔS2kÖ,§³‘fRRR"Mš4‘ʰaäwïÞË»\ÊâE‘HDÆ/o¾ù¦|øá‡²aÃ7÷ªU«J‹-¤uëÖrì±ÇÊoû[©\¹²{<ݵk×Êc=&S§N•¹sçz:5lØP:tè ƒ ’?üáR­Zµt³uÏ£í] 6@ M°Ä6­¯qi6ªÏi¶cñÍ] 7lÅ6­ŸÝòÖŒeޘؖœÈæ{¦äwåØ ¶íÒ-ô×7b[òE…ÞöÉkÎ [€ø¶«} ù5.ì±M[ÈfûØÌ»°_=¨]yJÊ{¡^gþAÿË<œQ‘<¸bÐÎFúH—òv8zýõ×åæ›ovzÁ–å9tèP¹ãŽ;Òîx¢£$]}õÕNg–²òÖN-Ç—ºuë–uªsÜfÞiÀòI:Ã5×\#}ôQZwÒŽA—\r‰üæ7¿Ië|=é7Þ»ï¾Ûù«è².jÛ¶­\wÝurØa‡•uªsÜfûØÌ;­ÊqXzlÓÊÛ|²™·Õ†Ë sÛ1Žø–Acp*äD ±M Êg·œ4W¹nBlóg+†÷5þ5g/…/@l³÷gPž=Ä6ÿ– ¶ù»°B ¾v| slÓc6cͼ åõzXhM‡#+®dŠ@z«W¯vFÚºu«sA¦Žôº›nºÉÙ(½;î:ëÀ”‡~XêÔ©“ò²ŸþYN9åY¸paÊób¶oßÞ¥IG>JµØÌ;Õ}suL§3;þøã3²‹–í£Ž:*šLúxÏ=÷ÈO<‘ôx²ÚAé¸ãŽKvØÙo³}læ²RDœ=¶)‚Í×!›yç¤Ó¸‰íG|K£8r*PÑØ¦…å³[N›,ã›ÛüÉŠá}ÍÙ‹@á Ûì}ç”g±Í¿%ˆmþ.ìE Pˆo…ßÂÛôߘÍd3ïBy} Öèpd–Œ(C`Ë–-röÙg{FÊ´ÃÑßÿþw1b„çN½zõ’!C†È^{í%µk×v¦@›4i’3¥Wì‰:}×½÷޻˳­å;ñÄeæÌ™îþ5jHÿþýeÀ€¢÷Y³fhÞ£F’õë×»çtÐAòøã;S®¹;c6læs›¼nþÏÿüŒ7ÎSuéÙ³§ì½÷ÞÒ¼ys™?¾|úé§N‡±;v¸çj»é_>·k×ÎÝ¿1yòd9óÌ3u¤9÷Ðþûïït$Ò‘’´3™æÿí·ßÊ3Ï<#›6mrÏ«Y³¦¼úê«I§×³Ù>6óv+ÈäM@ÿ9¶)ŒÍ×!›yç­Q}nl3Æß|ÀÙ…yÈFlÓ ðÙ-¯ÍXæÍ‰m‰DÅò¾&±æìA ðˆmö¾ó Ò³‡Ø–ØĶDö PHÄ·ÂoamúïÌf ²™w!½FPk­+”³N©fVÈ@Àt̉¼öÚkÓ™'ÒµkWÏzúé§§“60²ß~û¹×wëÖ-òÐCELÇß<&Nœ8p {¾Þ{êÔ©¾çêNÓIÅsn÷îÝ“žo†é‹˜éÔ<ç¿øâ‹yÉ;éMsxà›o¾ñXì¹çž‘çž{.i ~úé§ÈÁì¹ÆL­–ô|óæ!b¦EóœoF¬ŠìܹÓ÷šE‹EL3Ïù§žzªï¹º“¶OJÃH"–ئÅç5.I#¦¹ÛfŒ#¾¥Ùœ†9ÈVlÓÂòÙ-'MVî›Ûüél¾gò¿#{@À¶±m—p1¼¾Ûüÿ5CÛûל½¶ñmWûúk\˜c›¶Íö±™wa¿zP», ´ªT¡G\Œe ˜¬rß}÷‰ö¼=úè£å€k®¹FLp,óÚT'<øàƒRZZꞢ£Ýè=*Uòÿgݯ_?¹ãŽ;ÜóuC§Öò[t¸ÿ‘#GzÝyçÒ»woϾh¢uëÖ¢ÓŸÄ./½ôRlÒݶ™·{“6óޝi°+ÆØ¦"6_‡læm·53ËÝfŒ#¾eٰ֜۴”|vËn[e;7b[¢h±¼¯I¬9{(,b[b{Ëë±­xÛ>±æìA ðˆo‰mZ ñ-¬±M[ËfûØÌ;ñ™Æüü{&øŸË^(‡€uÆé¼£Ókýøã²mÛ¶räâ½DóÔ)±¢Kýúõåâ‹/Ž&“>šQtdðàÁîñ¯¾úJ–-[榣£G–åË—G“røá‡ËСCݴ߆vFêÛ·¯{hÚ´ibF>rÓÑ ›yGï‘ïÇ1cƸEhÑ¢…œp n:Ù†AJÌHHîá… ʆ ÜtìÆwß}›”ã?>ig£è‰;wö´ÏöíÛeúôéÑÃî£Íö±™·[6@ 'aŒm cóuÈfÞ9iÔ4ob3Æßß7¥Ù,œ†Y°Û´X|vóÿ\˜…&ËZĶĸS,ïk²ö$"#*@l+Þ×7b[ñ¶}@_Ž(Y ¾çk\Xc›>ùm~¾²™wVÿá’YA Ðᨠ›—ʪ€vFÑ^«ÑE;i§£t–þýû{Nûè£Ü·Ü:ŠÐ½÷Þë{,ÕN))vÑ)¹Ò]Ú¶më9u„ 2lØ0Ͼɓ'»é’’ÑN3é,±#éùúÅå\à¹ÔfÞžå)?b”N7—î?"T“&M|/mذ¡gÿ’%K<éd‰yóæyÅ?ô Íö±™·§b$@Àº@c›¢Ø|²™·õMó¶cñ-ñ}SšMÃi ±M‹Åg7ÿÏ…Yh²¬dAlóoŸbx_“•'™ pb[âûëbx}#¶ÛþÒDñ¨°ñ­øâ[˜c›>ám¾ÿ°™w…ÿ±’AÑÐá¨hššŠæK@;ì{ì±¾·Ÿ3gN¹:éu±K›6mb“)·uНØåÛo¿MŠæ½råJw_Ïž=¥qãÆn:ÕF=¤fÍš²iÓ&ç´Ù³g{N·™·çFyLÔ«WOn¸á·x »jC§Úûæ›oÜSjÕª%Íš5sÓ±]ºt‰MŠvÓiÕR-K—.•/¾øÂ=¥ZµjßáÈfûØÌÛ­ 3°Å6…±ù:d3ïœ5j7²ãˆoÞ÷Mi4 § €@lÄ6-žÆˆØ…Ïn±ùß&¶‰ãçöü?ó(¹ ¶yß_ó¹-õó.Ýï&ùÜæ}^¥Vå(Ø ¾y_‡Š!¾…õs›>ÿm¶Í¼müÛ%ÏÂ`JµÂm[jVÀuëÖõÔ®´´Ô“N•ÐŽ'±ËêÕ«c“žN/z k×®žã©U«VõtbѪ:Ôat‰íP£û²™wôù~ÔNBgœq†»vêÔ)­"=ú裲eË÷Ü¡C‡ºÛñ”ØÑÞ~ûmyñÅãOsÓ›7o–k®¹FbŸ'ZÆ5j¸çè†Íö±™·§$@ ´6c›¢Ø|²™wÔvŒ#¾yß7©í) ”_Àf|³læ]~Íì_Il)ÆÏíÙ&‘#Å%@lK|í Ò3€Ø–Ø>Åò¾&HÏCÊ‚@ˆo‰¯ŸAiǰÆ6õ³ƒlæ”¶§á ÃQ8Ú‰R"àˆïÄ2þ|ÏñT‰¹sçzoܸQ¶nÝêî‹ÝHw6hÐÀ=–ÎFýúõ=§Åæ»­'e3oÏMC”X¼x±Ü|óÍ¢Ž¢K:uäÒK/&õïM7ÝäÙã7ÊE]$S¦L‘ 6H$jíwÞ‘£>Z>ûì3÷|}s?Õ´Ù>6óv+Æ„ZÀflS›¯C6ós£fãˆo‰ÏÓ0·?eG]6ã›Íøc3ï0?7ˆme·^ªïʾš3@ Ķ]­+ÃÐv~e$¶ù©x÷Û¼¤(TâÛ®–-„ø”ئ¢ñžÙü]ÔfÞ…úïœzÙ`J5;®äŠ€Uø7>_}õUÚ÷›>}z¹:Ê‘vBÑeíÚµžã™?Ú0vрסCg—ͼcïÔmÁèúë¯w¦[°`|ÿý÷²fÍOq÷Ùg¹çž{¤Q£Fžýñ‰!C†ÈÈ‘#ŽGÚ±H—÷Þ{ÏYu[G›Ò¿T_ºuë&?ü°og/›íc3ïø:’Fp ØŒm*bóuÈfÞaiÍlÅ8âÛî÷Mai{ʉ©lÆ7›ñÇfÞ©Å‚s”ض«-²ù@pZ—’ €@Eˆm»ôb¿ó¬ˆg.¯%¶íÒ&¶åòYǽñmW[…-¾9¶©¨ÍÏÖ6óÏ¿\JF8 B+P2hذ¡´nÝÚ½êóÏ?—‰'ºédS§N•7Þx#á°Žˆ]âTü_pDÏKö~l[›y'+Oöoß¾]Þ|óMy饗œ‡â;uìØQüqÑÇt–C9Džzê)‰7×ký:5oÞ\ž|òIiÓ¦oö6ÛÇfÞ¾•a'„NÀflS ›¯C6óKCf3ÆßÂÒê”Ò°ßlÆ›y§ã„sˆm»ZÁïófªö‰??ö;T×q Â#@lÛÕVa|}#¶íj»øXUÖ¿¾øóÃØöeÕ‘ã B|Ûõ,Ûk\c›ŠÚülm3o^ÈD€G™hq.¸êª«<¥¹å–[döìÙž}± =¦×èT[ñKì¨Dñ*Ó¿øˆŸç6Ug¦læ_§0¦çÌ™#‡~¸<ôÐCeçÎÎ4lÇw\–d/]ºTôü>úÈ÷ÚÞ—… C[±M«Àk\ÒçVéÆ8âÛîNà>ŒìB ØŠoĶü>!ˆmþþ©¾ð¿‚½ Fb›HìwžalC¿2ÛüTDˆmþ.ìE ˆo…ßòÛôßŸÛ ñ•‚:Å 0¥Z¼iB"pä‘GÊA$&LpJ¬Aóøã—óÎ;Ozõê%:ü£N«5kÖ,ùïÿ+/¼ð‚ìØ±Ã9·Zµj²uëV·¦±JJJÜýº¡çf²Ä¬û 6óΤŒù:WÛãüóÏuX±b…,_¾\´Ý-Zä©´´Ô™òL{‘ßtÓMιîÁ˜ í`¦m»´k×N쌤S²ÍŸ?ßé„ööÛoËÆS—-[æûÌ™JíÓO?u5J8à9ꨣÜ}ѧŸ~ÚÓÙ¨råÊrÙe—ÉYgåÛALÝsÏ=žéôt%M©sçÎÑlÅfûØÌÛ­ P6b›ÂØ|²™wX51Žø¶køî°´9åDÌlÄ7›ñÇfÞ™ÉåïlbÛ.ûl~'¿ÖäÎ `C€Ø¶û;O¾6ò$¶íR%¶Ùxv‘'…#@| W| rlÓ6?[ÛÌ»pþES“\0¥Z.”¹–Ú´i#:zͱǛִËc=&K–,qÏí¤;÷Øc÷˜ndúlóæÍžëu¤èb3ïè=Âö¨=û÷ï/#GŽ”~ýúyНm¿èÈTO<ñ„g÷Å_쌜¤o¬üuÿë_ÿꌈ=®óÚÞzë­Ñ¤óh³}læí© ½€Ø¦(6_‡lææÍ$Æßvµtìû¦0·=eGDñÍfü±™w¢NxöÛÊn«Tß ”}5g €@˜ˆm»¿ó S»Å—•Ø/’˜&¶%š°B ¾…?¾%¶é¿›Ÿ­mæ]ÈÿÆ©[öèp”}SrD §:BÑðáÃŽDG}´téÒEªTÙ5x™>îµ×^2lØ01b„èÈÚãuîܹn›5kænëFE”N»Äþpf3ïØ{†q[G™zà¤R¥Ý/Ë3fÌ¥K—zªóÁ8S±EwêÔyñS£EÅ>ê,ít;šÕäÉ“r @IDAT=SëÙl›yÇÖ“m( lÇ6U±ù:d3ïBhÑtbñmWKǾo*„¶§ àÈv|³læíU gŠØ–¼ÝR}'ü*Ž €@Xˆmam¹ÄrÛM¢{ˆmQ (â[a´u¾c›*Úülm3ïÂxP‹\ 0¥Z®¤¹– $ºê²mÛ6Y¼x±´hÑ"aŠ­ ÈêÕ«ÝÒôíÛ×ÝÖø;’çÄ$ ½otÑOõêÕ‹&­æíÞ$Ä:ÚTûöíeΜ9n-´½š7oî¦gÏžínëÆþûï/:¥Z:‹¶­N¡öý÷ß;§ïܹS~úé'ÙsÏ=4mŸŽ"ç €@.²۴̼Æå²åïUVŒ#¾‰Óa<ö}S¢"{@ P²߈mù}FÛüýS}'à{@ ˆm…Њ»¦xNõÝ$ŸÛøÜVÏtj@úÄ·ô­‚zf>?·© ŸÛƒúÌ \ÙØ=”F6s%/È«€öÚm×®]Bg#-ÔÔ©S=e0`€'Ý´iSOú‹/¾ð¤S%txÙØJ½zõY'ºØÌ;z|?|ðÁ¢õÖuÈ!'Úù'záš5k¢›Îã¢E‹<é®]»zÒe%âÏŸ?¾{‰Íö±™·[6@  *ÛÆæëͼƒÔ¨6cñMœ÷±ï›‚Ôö”ì T$¾ÙŒ?6ó¶§™yÎĶĸS,mŸù³…+@ ]b[ºRvÎ#¶Ûì<³Èˆoù{„5¶©˜ÍÏW6óÎ_ksç0 Ðá(Œ­F™‹^ ‰È¦M›ÜUG4Jwùä“OÜSk×®-û›Ö í¤fΜ)¥¥¥žs’%´sÒŽ;ÜÃv·uÃfÞžå1¡£EÛF;ólذ!£ÒÄÏ Þ±cGÏõñS­ÄŸï9Ù'ÿCfìèI6ÛÇfÞ>Õd„PÀflS›¯C6óRSÚŒqÄ7‘ø÷MAj{Ê‚å°ßlÆ›y—_3ûWÛãO±´}öŸMäˆ@ñÛ_;ƒÔúĶÄö!¶éJY®ñ-ñõ3(­Öئ~6cͼƒÒö”#t8 G;QJ<k×®uGÑÑ‘t®¸â Ïñd íü2vìX÷ðàLßáî0•*U’cŽ9ÆÝ¥ÓnÅvRrølŒ?Þ³÷°Ãó¤mæí¹Qñ„¢Ó—¥[¤éÓ§»§V¯^Ý™bÍÝa6öÚk¯Ø¤h‡°L–Øóµ=ºtéâ^n³}læíV€ µ€Íئ06_‡læ¤Fµãˆo"ñÔö”Ê/`3¾ÙŒ?6ó.¿fö¯$¶%ÆŸbiûì?›Èâ ¶%¾v©õ‰m‰íCl Ò3”² \â[âëgPZ+¬±MýlÆ ›y¥í)G8èpŽv¢”x4hà…hÒ¤I¢ƒÊZF%±#âœzꩾ—{챞ý#GŽô¤ý:õ×Ë/¿ìÒù¾;tèণ6óŽÞ#Ÿ;wöÜþõ×_÷¤S%´ÃÖòåËÝS´3PåʕݴnÄÿ ûþûïËŠ+<ç$K,[¶LfÍšåÖ6ªQ£†›Ö ›íc3oO%H €@(lÇ6E±ù:d3ï 4¨ÍG|óß”¶§ P~ÛñÍfü±™wùE³{%±Í?þCÛg÷™Dn—±Íÿµ3(Ïb›ûÛ‚ò ¥W€øæÿú„ slS?›1ÈfÞAh{Ê:…£(% ݺus÷iÏë?þØMûm̘1C~øa÷Я~õ+9è ƒÜtì†æ;òÍ´iÓäùçŸ=ų­#']xá…²qãFwÿI'änÇnØÌ;ö>ùÚ>þøãE§ª‹.ÿþ÷¿eܸqÑdÒÇ¥K—ÊÕW_í9>tèPOZíÚµ}ã]Ö¯_/·ß~»èpŸ©êîÊ+¯”Øé÷~ýë_'\b³}læPv €@(ôu"ºd;¶i¾6_‡læ5É÷£ÍG|óß”ï6çþ ›ñÍfü±™wvd+ž ±Í?þCÛWüÙC·±-¸íOl#¶÷ÙIɾñ-˜mæØ¦¢6?_ÙÌ;˜ÏJDïЖðæ›o>Á\Ò3ÃË8~X½zµ<÷Üs®G«V­ä„ôŸUÙKÍš5e̘1î‰ÿýïe¿ýö“Ö­[»û¢ï¾û®üñôŒntï½÷JË–-£§$<Ö©SÇÓQf„ R¿~}éÞ½»3`ô‚Å‹Ëyç'ß|óMt—hoã»îº+atžè 6óŽÞ#_µjÕrF›š8q¢SyêwÞݯvñ#mß¾Ýy\~ùå¢?®G—¾}ûŠy•’’’è.çQÓêûÖ[o¹ûüñGùüóÏ¥wïÞžÎHÑtZ·«®ºJt$¬èÒ©S'Ñç@|yô¸Íö±™w´n<"€@~‚ÛTÆæëͼóÛª»în3Æß’¿o BÛSŠ] "±MíøìV¡¯ž¬>ýˆmÉãO¡¿¯±úÄ"sB @lÛýÇÙüÎ3MOl#¶áyHÈ—ñ­0ã[Øc›þ{°ùùÊfÞùú·Ì}C%0ÂûKv†e7#jüË\rF†—q:ü"0gΉe¦OŸ>òì³Ï¦ísÙe—9Y¢T«VM  šÎiªM¦Nš0ú‘^§#•µüéO’7ß|ÓsšvhêÙ³§3×”)SdþüùžãUªT‘§Ÿ~ZößÏþø„ͼãï•ë´N[wÄGˆNa»¨¶‹ö8®ZµªÌ;WfÏž-:]ì¢#$éÈH~Ç¢çÝÿýòØcE“Σæ©‰t*;íL¦Ó³é=t„ªØEÔ}á…¤W¯^±»=Û6ÛÇfÞžJ@¼=¶)ŠÍ×!›yç¥Aãnj;ÆßâÀI"€@ *Û´|v DSú‚ØæËâì,ô÷5ÉkÎ _€Øfï;Ï <{ˆmÉ[ؖ܆#‚ñ­pã[Øc›þû²ƒlæ]¯ ÔÁª@k:Yõ%sR TôÍϪU«äÌ3Ïá&ÝåÜsÏuF»IçüÒÒRç‹ñ>ú(Ó¿ÜÕiÛXæù6ó.óæ98aÁ‚ÎiÚá+“eÏ=÷”[n¹Å­*Õu:rÒ 7Ü ¯¾új™Ó©ÅæÓ¸qc¹é¦›äÈ#ŒÝ°m³}læPv €@΂ÛÄæëͼsÞ˜Inh3Æß’ ³ò*PÑØ¦…ç³[^›°Ì›Ûü‰Šá}ÍÙ‹@á Ûì}ç”g±Í¿%ˆmþ.ìE Pˆo…ßÂÛôߘÍd3ïBy} ÖZWh\k3ÝSªYk2.l ïxÒI'9}¾üòKÑé¹’-:êÍ7Þ(gŸ}v²SöëˆIÇsŒ3…ÚôéÓeÛ¶m çDwôë×Ï™¢KGWJg±™w:÷·}ŽN?§óÊj=u$(ý5ÕR¯^=§#Øí·ßžrª»h:JÑàÁƒeÈ!²dÉg$£è±dZiŸ}öIvŠ»ßfûØÌÛ­ 7 Ç6…±ù:d3ï¼5jÜmÆ8â[6I„@Ec›VB§Uã³[ šÓ·Ä6_«ï™üïÈ^È•±ÍÞwž¹jòîCló*†Ïìþ5g/Å!@|+ìøæØ¦ÿmÆ ›yÇ«µ¬€SªUK”ÀÒ¥KeÒ¤INÇFkñâÅÒ´iSiß¾½ì½÷ÞÎ_•+—¿áÆe̘1Îô\ÚÁEÓ:mW›6mdРAÒ½{÷r{ØÌ»Ü…Êâ…+V¬™3gŠö®×)Ô~úé'ç‡víÚ9ӟ飶‘v:*ïòÝwßÉ·ß~ëä=oÞˆüêW¿r×?üй¦´´42bĈˆ–7šoôqÀ€‘ñãÇ{òÖ2=òÈ#ÓÁÈs~õêÕ#ýúõ‹\vÙe‘µk×z®‰O©,ñe#„Q ñíõ×_÷¼®5Ê¡0]#×]w]Ätrõ×Xa:šF~ûÛßF>ÿüóŒØˆo»ßƒØŠµ5'#€*PÌññÛo¿u?ûéçÀI“&9­l:G†1†Ý¸þÄO¸Ï€‘#Gºû5ÖÏ;×=æ·¡Ÿ'O:é$ϽÎ=÷ÜÈÖ­[ýNg €@‰_=ôûšÜ¤IÏkz=ÜcwÜq‡[’òÆŒ }¿¤²¸°l €¤-–Ø[¡¯¾ú*rä‘G:ßFS‹>š œ˜{íµ×F¶lÙ{YÂ61,„«@+óRþŨÑá¨XŸ:Ô;gO>ùdDƒ¼ù—ZæªoÒéôüóÏGj×®2?íˆ3zôh§Sì½£?ä&øæ›o:õÄ^»Ý A§cR²¼tüÉZ¦9sæDöÚk¯”å×ûh=uÑŽMtP™çë§6lp®ñû_ÊâW>ö!€aÈV|‹mÖ8¥±0Y'ÝØ8TµjÕÈã?žñÍÿ}H¶cmZÁI €@ {|ÔF±±zܸq3ª ïç¹òv8ÒÏ|úÇ1±÷éÝ»wdåÊ•üÌ¢j €€]ŠÆ¯«¯¾Úóºû»}þùç»)öÿ Éw.) €„)öiµtpsÎ9'bF0J+æî¿ÿþ‘Ÿ~ú)©HâiÒBrr!Ð*{㢙wþ, =Æ9ûì³eãÆžŒ5j$M›6õìÓ„O8lØ0gºµ„ƒf‡‘hFò‘ÓN;MÌ_túâî3½—åÄO”×^{ÍÝWÖÆgŸ}&|°|ýõ× §úMÕ¶fÍ1E*—\rIÂùÉvh;ì0ùþûï“âî7_BÈ—_~)f ™0a‚»?ÙÆ'Ÿ|"f$)Ѻ§³©,é”—s@ ؈o±õúá‡䨣Ž>3v1#îÅ&mRô¢‹.’©S§&‹ÝA|‹ÕðnÛŽµÞ»‘B W€øèß¶êrÜqÇ¥õyÎ?ï^ÓÙH~ýë_‹×=зo_yï½÷D?g³ €d&`;~eRšòÆŒ }¿¤²dbϹ €@1 „5ö™‘àåŸÿü§ìܹÓm.¢ºW¯^ÒµkW1#»ûucÊ”)²ß~ûÉĉ=û“%ˆaÉdØ)L—(F8ÊE¿0îQ”>ú¨§—±Nÿò—¿ü%b~@u=L‡È‹/¾Ñ)ÕÌ?Vw=öØcÝsb7tJ±Øótd‡ßÿþ÷óåª3äüÌ™3#Ï=÷œ3´|ô¼ø)Ñ’p¤e‰òXG!zõÕW# ,pŠ¡ÃÚ¿ð ‘3Î8ÃS½×ƒ>[Tw;¾—tìhO¦ãTäÝwß,_¾<¢eê©§":jR´ìúX¥J7m¾@ŽÜ{qO?ýÔõȼaŠ\~ùå CGjý– •ů|ìC íøÿÚûW:ƒŽŒ3&b>ð:Å££=üðÑš5kº±Ac…N[šl!¾å6Ö&kö#€….@|ÜÕÂñ£U˜NÄž˜ÝºuëÈÑGÑ.Þÿ}÷i‘ΔjëÖ­‹è¨¶±Ÿ<ðÀ2§Övo €@‚@¶â×¢E‹"_|ñ…³ê”—±¯Õo¿ý¶{lþüùnÊ3â?Cò]£KÊ €@aŒ}ï¼óN¤¤¤Ä¯}úô‰˜?°ôÔÖ XÑïN?üp÷<Çz®ß¤xêW>ö!€@ΘR-gÔÜ tÈøfÍš¹A];é‚d˲eË:ûèõØE¿\5£"¹yê‡é±cÇÆžâÙÖáékÔ¨ážý Ÿ¬ÃÑŸÿügϹ:4£™É“glâ†nðœßªU«ˆé{гÿ¦EË¡ºßoÑ/'blŽ–»ÿþuò[FŒá)‹~±á·©,~åc tñÍïµYãÀ³Ï>›”ã£>òÄ8wɦÔ$¾%2ÚŒµ‰wc PøÄÇÝmÿãqôó\»víœ?Ù}¦w«¬GÚø€ð|îÓi·õs2  €@ùlÄ/-ÉÅ_ìy½ž7ožoË3ü>Cò]£/1;@âÂûb¨_¿~dÅŠq5ó&O=õTO,ÖA â— ÅÓø²‘Fœ Ðá(§ÜÜ 4nºé&O0×yÌËZttŸè—±ú¨#Å.ñ|þþ÷¿ÇöÝÖÑ€bóÔm¿G³gÏöŒÔ»woßÎCñ7ÑÑ…bó×Q(â¿7-W^yeüižtüÉú¥™‚ÍsNlbëÖ­ž‘td&¿%Heñ+û@  ؈o~¯Í\pA™fzO úðî!¾%¸;lÅZ÷l €E$@|ÜÝØ~?ëç³U«Ví>Ég+U‡£Õ«W;•ûÙÓLÓ´³±OöìBð°¿ô6ép”NÌðû Éw> Ì.@°Æ>ÑÏCƒ J¨WüýcÍèùúxß}÷ÅŸâ {Žnç+ž&Ž KV•Ì H`íÚµb:ú¸%ª^½ºèܪe-fT1#4¸§™NÝmÍÓŒâ㦻té"çž{®›N¶qá…Ši)Ùawÿµ×^+¦ÓŽ“6Ã2Šù²WÌTlîñdzé ä~òÉ'Ýíd73µ\²ÃÎþ=÷ÜÓsÜL'ݺuóì‹M˜©å¤}ûöþÙÝNµ¤²¤*'Ç@ ؈o~õ2ÓgÊ]wÝåwȳoàÀž´ßk?ñÍCäIä*ÖznJ(@âcÙúÀHÆ Ë>Ñç ÓÙHÌ”2yòd÷è!CÄLÏ#µk×v÷± ™@®âWf¥)OÌÒ÷{A*K¦öœº@XcßÎ;eÖ¬Ynó|÷Ýwbz"¸i¿ 3¬˜NFÎw¬ú=ë¾ûîëwšg1ÌÃA¢¨RTµ¥²„@@ƒ}ii©[ÒC=Têի禓mÔ¬YÓéTdæ2wNiݺµ{ªÝÇ“çСCÓêd¦]“‹.ºHL¯m7/¿ 35›»»S§Nò«_ýÊM§ÚhÒ¤‰rÈ!2nÜ8ç´Ñ£G‹™†Mô¾É35š4hÐ Ùag¿þØ»ôèÑ#6é»klþzÖ÷œøA*K|ÙH#€A°ßüêhæOëGÉ=öØÃs¹JØ“Öñ-ÄÝ‘«XëÞ @ @ˆ©?ÿégKí Tžeåʕε_~ù¥{ù¯ýkyíµ×<¬ãd@ m\ů´ dN,oÌÒ÷{A*K&öœ‹ƒ@Xc_¥J•D#‹~.Zºt©œþùò·¿ý-åï„W\qEFÍJ ˈ‹“((:TsR™B0Ó·xªñ›ßüÆ“N•Љü–ø<µSºËÞ{ïòTbÍš5î9f:5w; }£íp¤£$Í;WRݳmÛ¶ef«#Å.Ú *“E{|§³©,é”—s@| ÄÇ¢lÄ7¿útèÐÁow¾؎¦z0¶³¯¦‰oª|ÉU¬M^Ž €…!@|Lýù¯W¯^åjhãú‡6ß|ó{½Ž®ûôÓOÓÙÈa(¿@®âW&%,oÌÒ÷{A*K&öœ‹ƒ@˜cŸ™RÚíp¤mõÄOȘ1cäÌ3Ï”ÓO?ÝéTÑ6$†UT믎ÂÛv”¼@âß´tîܹÂ5ÏS§TKwi×®]ÊSgΜé9>}útçMŠggŠÄŒ3»Æ¶þqÇ'‹-ŠÝåL~à 78Éë9@@ c\ůL VÞ˜¤ï÷‚T–Lì9(0Ǿo¼Q&L˜à™jzñâÅr÷Ýw;«ÎFrðÁ;ÓQ먰å‰G幆ï‹á_u,:C+SÇP Ä¿iÑ@_Ñ%>φ ¦eY½’ý~ÕNGå]6mÚ”òÒò¼Ñ!#m,A*‹ú‘' MøX”øæW¾V­ZùíÎxñ-32[±6³Rp6 >âcêÏUª”ïk«øÎFÑgÆÈ‘#åÔSOu¦öŽîã@ s\ůLJVÞ˜¤ï÷‚T–Lì9(0Ǿúõë;3 6Ìq$¶Ít„ØW_}ÕYu¿ÎBròÉ'ËE]${ì±Gì©I·‰aIi8€@Á Øù¾àÙ¨ ötJ±Ø¥qãÆ±ÉrmÇÙÚ Aƒ´ó)ëÃúüùóÓÎ+7oÞœò´Ê•+§<žËƒA*K.ëͽ@ò؈o~å(+nù]ã·øæ§Â>@l Sþ«¨÷gœ!×_½›M$‘óÎ;OÊúÜé^À €€¯@®â—ïͳ¼3Hßï©,Yf&;@ ôa}ÚéhìØ±ÎHGøÃRv$úî»ï䦛nàÉ'ŸL«íˆai1q)P¾?+H *…@0â{ ¯]»¶Â«]»¶'Õ«WK³fÍ<û’%–-[–쳿uëÖžã\püîw¿óìË$Ñ£GLNç\@؈o6«N|³©KÞ €Q⣽Ï—]v™Œ1™Jí¥—^’Y³f9ìúxóÍ7Ë_ÿú×h3ðˆ ¡@ØâW†Õãt@ %ö 8Ptݹs§Lš4IÞÿ}?~¼|òÉ'?‰¦õ6š6m*G}t‚ ;@ ÃÏ&еkWO‰,X ûí·Ÿg_¦‰øtÔ†t;éýS-ñå­V­š 2$Õ%C(Bøx‘øf“1¾¼Ä7›Úä¯@|¼!>fç¹pë­·Ê 7ÜàdV½zuyôÑG=ŸSï»ï>gŠ€Š~ÖÎNiÉŸ@ØâWø„)1 €@Ð -öUªTI<ð@gÕQa·lÙ"~ø¡¼þúëòÜsÏÉúõë&رc‡\|ñÅt8 Ú’ò  :¨1( *ÿ¦%~˜ÆTJôúé'ç)èî»ïv¶Ûµkç¹L¿ÄîÓ§g_²ÄþóŸd‡œýñå9sfÊó9ˆ Pœññ"ñͦd|y‰o6µÉ(^øxC|ÌÎsá÷¿ÿ½'£Ã?\N;í4yþùçýÛ·o—sÏ=W>ÿüsÉÖt¬ž’@ \ lñ«À›ƒê!€ä@ ÐcŸþ¡ÆGá¬W_}µzè¡2oÞŸâ©\¬X1S&¡ íÝ»×n»í6ûûᅢI‡Œõ‡GïÞ½™žÔ=š?þøY>ú¨mܸ1þ}R/víÚe½zõJ0ëꫯNðž7 €±#ë[´u¸¾E[˜í#€p}ÌÜ]»vMð[Y¿‰»té’àáÌ="ö†dOh^¿råJØe‘Ú=Æì)ÈQ#€d7ìzí«W¯^ê#F$xŸÜ›™3gÆÏ*X° p ñïy„ $üë=t¯@à° tèÐÁN?ýôøýëÂ~á…Ú¶mÛâ§/fÍšåç… 0ÀrçÎ,âÇ}ûöµÂ… ÇO{ë­·¬qãÆ¶xñâ7W·nÝêÓÊ7iÒ$ÉýÅo äE¥J•¬OŸ>ñSTÞ­nݺöõ×_ÇO }¡éuêÔ±o¾ù&~r§N¬aÆñïy {Ѹ¾ES‰ë[4uÙ6 €@ Àõ1ˆþXØ#GŽLð{yîܹ6jÔ¨èïœ= €1&­ë—21„¶Gy$Á½ËÐy¼F@ 3²ãµïä“O¶ÚµkÇ3=þøãÖ¯_?Sb‚¤Ú|‚ƒ‰'ÆÏVÿdâ€àø™¼@/pdŽ,( ²bO?ý´5oÞÜvìØápΜ9V²dI;õÔSM©`¤`!e" m—]v™Ý~ûí¡“üëjÕªÙ¸qãLó÷ìÙã§}ùå—V³fM+Z´¨¯áªr1J§øÏ?ÿį߽{w{öÙgãß'÷BÙŠ^}õÕøtô¿þú«©”›§ôÇLõêÕmùòå¦:¯:æÐ?fôΗ† ÛѸ¾E[Œë[´…Ù> €×ÇÌý7 ß§=zô°'Ÿ|2~Ç÷Þ{¯µjÕÊÊ—/? €) DëúU£F;žAÙ5‡ÓGez6YX€€£,üáph9[@Ù~˜£Òª­ª¦ ¯¾úÊIé(Àg̘1IÍòÓZ·ní³)›‚‚¦¬FŸ}öYðÖ•!iðàÁvöÙg'øcBi#“jyóæµÏ?ÿܺuëfo¼ñ†_DMóçÏ÷CRëhšnöN™2ÅŽ>úèäa: €@ DãúM®oÑÔeÛ €×Ç@"sÆô¿[•WmûöívóÍ7ÛôéÓ3çØ  #Ѹ~ Áw´¨vîÜi?ÿü³mÞ¼9Fä8 @ì*¯}*«Ö¿Óï ÿý×Óÿðæ!¥¦~»—_~Ù'CHi9æ!€@Π¤ZÎþü9û,.pâ‰'Ú‚ ¬cÇŽ–'Oždö¸ãŽó7K?ýôSÿÄO² º§œrŠRÚDýaT @‹çË—ÏÚ¶mkJ+ß»woÛµkW‚ùʲ”\+V¬˜Mš4É^zé¥TCË*k„‚”ªV­šÜ&™Ž ƒѸ¾E“‰ë[4uÙ6 €@ Àõ1ˆþ¸`Á‚6|øð;zûí·-´l@‚™¼AHV Ò×/ÝÕwòñÇŸì>™ €ÀáȎ׾ûï¿ß>ùä«U«VªtÊätÕUWùŒG\pAªË³äl#2rú. rœ[ÿêŒlƒu@ <•9S92e8RÔñ±Çk 4Ò ,AG™¾„eJŸ¸téRS95m³lÙ²–?þøƒš:uª@ &(Û’þ˜J­©Ü¢E‹láÂ…~X¿~½ß¶RÔשSǧ«WÖ €@ΈÖõ-Zª\ߢ%Ëv@B¸>†jð@ »Dòúµÿ~[±b…-Y²ÄôZ÷-ÕIzß2»¸pœ €±+Ý®}º¦¾û_P×Y 7nô¥K• Zµj>YÁi§»g†‘(OÀQ$9Ù1(0hÐ 0`@ü™)uq‰%âßó@@@@@@@r”@ùô¥DÉQFœ,Ù_@Ë3f̈?=T·nÝø÷)½˜7o^üìêÕ«l¯Á @@@@@@@r¦G9ósç¬s˜@îܹ­G>5¢N½pá¶fÍ+R¤HŠ*‡6wîÜøeÚµkÿš € € € € € € € 3råÌÓæ¬ÈyÍ›7?éíÛ·Ûˆ#âß'õbÙ²evá…ÚîÝ»ãg_zé¥ñ¯y € € € € € € €9S€€£œù¹sÖ9P }ûö ÎzÀ€>ëÑÚµkã§ÿóÏ?¶`Á>|¸5kÖÌ6nÜ?ïÆo´zõêÅ¿ç € € € € € € €äL#2rÚÿþûï8·þÕÙë"€@æ <úè£Ö«W¯CvX @+[¶¬­^½ÚöìÙsÈüš5kÚüùóMËÑ@@@@@@@@ G ”'ÃQŽþü9ùœ&pÏ=÷ØàÁƒ-þü N}çζtéÒ$ƒ®¿þz‚hñ@@@@@@@œ-@†£œýùsö9Tà?þ°‘#GÚøñãmÅŠ¦Rj¡­\¹rÖ®];»òÊ+­Aƒ¡³x € € € € € € €9[ <G9ûg€¹Òˆ¶aÃ[¿~½+VÌJ—.mùòåC@@@@@@@HJ ü‘IMeä#Ž8Â)Ј† € € € € € € €¤&+µ˜ € € € € € € € €Œ@@@@@@@@@ UŽR%b@@@@@@@@Ž ^0F X¼x±½ýöÛv '“çuëÖÙ¬|ùò9äŒ9Í@`Ù²eV¼xq?ÓrêxáÂ…Ö»wo+P @N%ˆÉó^¾|¹Mœ8ÑN:餘yòdÿ÷[êK³D¬ po*Ö>ÑðÏGßç+V¬ ?‘ýù矶téRŽÂÿç“m–œ9s¦)ø FÙæ˜9ÐÈèg=,¢þZÎøøãýµíè£ÎY'žèlwìØaŠ= à(L ½%à(†>ÌHŠ"¬«U«fÆ ‹Ô&ÙN6xæ™g|G_úÙä‹àavíÚÕ.¹ä»è¢‹"¸Õ칩SN9ÅòçÏŸ=ž£NV@?èÊ•+ǵ-Y¡ØžÑºuk³î´ÓN‹íåì˜0a‚-Z´È†zȼœ6ALßyçœvÚ1}¾ÇsŒÏNÉﶘþ˜“=¹«®ºÊô7ü9眓ì2̈M}—ë;ÿ÷ÍæÌ™ã3½Åæ'3ϪP¡B–/_>þ}çÌßnºé&»øâ‹­eË–9T çžvð}εÍL ÷ßÎýÇÃg®ì”z®_¿~1|–œZRz¸¹yóæ¦û“´œ%ШQ#ëß¿¿Ï¼Ÿ³Î<áÙ*Ù…î_ÐbW Wìžg† € € € € € € € €‘ ÃQ¤EÙÙX pá–'Ožl|zzô„|NOë˜^;ÖC¬/ ï8®oYÿsŠÆêÚV´hÑhlšm"€‡U D‰–7oÞÃz ìüð(û eb={Eè è»Mßq´œ'pÔQG™þ¶¡!€±( ï7**Äâ'›ú9©”^îܹS_%ÈæeóÃG ’×^{m$7Ƕ²‘À!C²ÑÑr¨ €@Ú^|ñÅ´­ÀÒ1#ЦMÓ@CbM`øðá±vJœO˜M›65 4@ Özè¡X;%Î'L† š ‹ŒÅÓâœÂ˜Ù<òˆY“&ÁÚqã?ÿüÓ:tè`;v,L8ƒw €1#°Ï¥ØÛé¢Nƒá¯¿þò¯u‚ ô)çjwæM›Á³çw\f½öV @{üñÇM™_7»ô~¡Ã¦M›láÂ….›ŸKç—¨) ©gÏžÖ£G+¬¨à0Û÷Å…^h?þø£Ý~ûívÞy繿GÜ$4@@@@@" ænôêÕ«wrOâŽrûNóºÁñêÆ¾n˜_uÕUÖ§O×Iœ õ{‚3FBT¤¾· .ˆËÌÚ±Ãìøãã2ïÔ¨WúK;éiÊÄã’ øæ*§Ø–-fGqpKÊH4tèÁ÷z5yòÁ÷*5¦à# }ÿ}\à‹ÙLÐp¤Š, >:ꨳüû™3NKë;ƒ‚|jÕ2›8ÑL&mI}õ«#ôÎ;ïôÙ*¹ôG¡CåÊ•­|ùòV¨P¡CvÔ¶¾ùƬví„‹*Xé‹/NÓ;•¹Q¾e.UR±bÅ]€) €ÙZ@=´lÙÒV¬X‘êy¨ä™4èºÓ¸qckÕª•QýÑ4¶7ß|Ó:vìh*¦,G§žzjŠ[P0Òúõëý°nÝ:[µj•5Êe/ìîpõF<¤í¥Ô¾qÁ‹.ºÈ~wiŸxâ °ôöÛo§´ ó@@@@@H“@š‚†\f£ó\°Ñ˜¤ö 'ow½ó*±öÒy$jùóçO4Ålüøñ®#ü(ëÝ»÷!ó˜€9KÀ=èoÓ¦™¹~9Ÿ©G6çŸ7(à&M¥¸/Ž ÚQ6 ?Ž+Å¥mWŠ,زé«I˹¾>„ÌIûØõWÚØ±f?üWö,4ØH[sýŸ¾¤˜ú 5T¨wŒ ˜Ãk¯é;3nßI%‡K¥ß1íh õ±ÞsO\™³k¯5ûòËD ¤òÖ%òAUèè¶ÛnsÆùüo/ýþÚãþxÑø;÷ÇË®^©J^Oš4É_ƒm1F@@@@@ RG†»!ש{´ 6º¼ Úç:iÔû*ª;äÚÙgŸm7n ]Ì¿îÖ­›ëD¯àŸ°Õü u½ðgžy¦r8˜Ær†€¾ þ÷¿¸ £O>1Û¿?®,–2 Mj6eJœƒ‚>ÿ<¡ÉÈ‘fÊÚ£ò_·ÞjvÍ5 ç»$j¶}»¹Îĸ "er 4—0Çn¾Ù\¹seFÌòeÌz(á´Ðw)•ðRpûZ3m_Í%Jp4þe’ÿq‰Üw`ÂYÊf¤¡{÷¸é Øq•V|0’|2£©ÓRY”Aã*U~·Ç«ç¬Nw»?"ìCpÉ\f³Ï>3;Ý­êâ‚i òQæ;u„ðÁ¾#\¼*³zõêø!èV§°²7|¬¨±ÿš2>èz¤ëÍ…ži/¿l6x°¹ ¤¸à£`¹ÐñCîC¾ï¾û| Ò[o½eçœsG¡@¼F˜P Ê•W^é‚nr>G}´hàî»ïöÙGY BУ ?ún×>X£!x]Â¥ K*ƒ]Fwÿ…Kk×¢E Ûµk—û»bŠ]|ñÅiÚ¤®7ï¾û® ˆ~Ó4ôþûnö¿_”1©aÆîz]×/…nX¿q:wîìdµÞqÇ:;M¯tµ]¸¤àX1)ðh ‹”Ö\Óà ÊxÖYg%·Ó@@@@@È@ØG®3à&÷ôsÕ`o.ëÄ®¡C‡~zá…^LKi¬'§uS¾Y³f6`ÀdࢠþkÆ #à(À`Œ@p‰kÌ=”ïh”ÀÆõ7ºrVqeÇÔ¨l=.ÁÏ@¤ ¢Â…EQY,%•.m¦òg‰›ª†¬\7ÕõkÚÉ'ÇÕ¬i ¥J%^+¼÷ ŽR€“22%®Œ¢òlʤ€£¹sÃÛ^8K)ÃRÓ¦á,™±ef̘áK]*ÈG™ ’jÊ&tÓM7ùlDê N©)ˆìŠ+â‚”!)©`#ekxÀ¥>R¶ )8UMY”9OCr-(=£lH#]Ú+¯¼â‡šîCîÜùÄt­5hàþü×Ôá­u¶»h4•n›èêÃÕru⦹³r!,̈}Ç*ØhРAvà 7Ø/¿üb*1¦±†.ž¾×•Á§L™2?k•«Ô~?ýôÓ·­RfAvŸ`ì2¬ºëvMœòõ&© Ïub•BÓw¿Ê‰¯Ô‰ilʤ§À! ºv¼óÎ;þwŒ‚y‚óÉ;·?Æ ¸kNÛ´i“õêÕË_W”%)R×íç÷ˆÊRëú¥k¶‚‘òæÍëeŽÕk]?;tè`º^Ó@@@@@ˆ–À‘ánØe7º.XÖív7î[¹`£NÁ´pǺþÿ÷¦Ò+V¬ð«©dùòå¦Ä–€J¥)€Èõ‡Å7Ï(È%[p¥IÌe0—á ~¶¡uÚ¶Ή{çâ]‰“„Û ]N_/;wšýõ—¹R&f¹r…ÎMþµ:%•9GE“©S¦ínØ—É%k°:uâ¶§òk®ÏŸï‹/&¿¬:ç©§ž2e¸Pi™:î¤Ôé ¥]dW)¡¥ŽÓ1cÆøåúõëç3 åÍ;ØWôÙ—tnûöíó,”ÅbÞ¼#]6ˆ¢>@ë‘Gž¹Ê¥©̳Ï>ë³C¨óVÍii¡¥gÔûƒ«[7jÔ(ttûí7»WwùìEÊl¡AÇÚÚ·oï2!½|HfŠÐexdg¯¾úÊq_À§»s*c¬•¥TpQÐŒ£Ì?š¯ïÄH5}Ï?ýôÓ>UÁžúίïÒêµ¾“5^+HG¿ôûàKW·Së†6eÀ«]»v‚A×êäÊÁ)Q[÷‡Džc•²VÑ@@@@@8\!!É‚+PÃÍ­²Äë®Càc÷>ÍGÚ†:ˆ»:7¡7É•ÕBå h ]WUÅ•4‰+e¶m›¹Nǃƒ{ˆßgæqqiÓ§›]v™¹'ðÍÎ=÷à&]"WzÑÌ=¨ŸîV¨Pꫪœš†´´¾}ûúŽY­£L;Ê~ §ºtFÊÂӢſªoY›6qY‡\Ÿ¦¶QÙ0ùºÊ+.«@ZözpÙÇ{Ì—øR Ê¯(;A0è½²$è;4’m¯«×ÝÕn=z´??u<'ª,uÊ”¡²4êT7n’;”{Ž.-ÿ4k†}òIkßþ;í´Óü l}úô± &¸ÌMM]¶ª©>ÐIKg¤ìRY >Ü~øa{ýõ×íÕW_õÚ*Ù“xÐçÙ¥K—d;«3r¬‹$1b„)°óØcõ? úÑ  : JQ §¾§"Ù£R\ÊŒóÒK/ù`£¤¶¯,@îA÷>Îÿ=®,=m RV#eÒ5åE‰Û8qýÐdv¢àÐU«Vù¤¥K—ú ¬ß ºFM%Øô]®!F:å”S|æeøÑ|)Ø*ÒM™„5jä‡`Û¿º:¯ Úáʸ𙂠¸<î)Xð(—Uh¶ë,ÎkÓ]Zh9Mí¤KqõÚk¯ù0)î43µutk !€‡[à§Ÿ~òe0ºÕÕ 7oÞ!|TK˜Ê4¤ #e´)«¨¾§‡ b ÄI©=ùä“þš×£G_b-¹ÌAÚÆüá™°\ƒBÇú¾¿÷Þ{}Àç­·Þêƒ@um·ÉB¾B›ö'Kƒ²¦¥Í´¬‚«Ôt­Ô54µóö Gè? TÊ‚Fh“l@@@@@,+VÀ‘+1TI©ûƒæ: 2p¤ÎeëPùµßÿ=ØŸqgÇŽ¸Ö«—uÈŘø ý¯÷Ûoqúu‘ 6ÒžȤû€£}fõ¦àÇN:ùŽJeÝQ¦5•S¦M›6Íä\tÑE>ÃÂyç4WÌZ¶4s•!]¹H3WÕ+ÍM¨ Œ?~¼}öÙ.(ì­ørnún\¶l™”åAÖ¬Yc«W¯¶E‹ÙþýûÙŸÊ’ÁGŸp V£F ßq«@¦ ýüóϾS[%lÔÁ¬`§ £6X&µñI'dÏ=÷d*‹Åý(c…Jhê¸5¨3xÀ€iÞg*;c6 ¥TªS×}×Ï™3Ç—Ó5gýúõîúû›­sß•®Î¨2ñ(ƒ‚\ì£À×Ö­[ûïie?J)(©^°`¢­ç.½zõJj‘Ót­PÉ3] ” )¹€M•BS@”2ù(ˆHÇœTS¬²šâ0©Ó0MåÑ‚¬ƒ×^{müšº.† ýù矾¼¦~kÐ@@@@@@ :a¹Ž–\'ÉêHŽÊ G›”V…†éP¦§Ÿ6{è!s%YnB•YÞxÃìŒ3¹Ä8 š«ââJ¹$˜‘7:§ãÊ·¤}s*£R%™Ù|ðA 3pàÀø`#íÿHw >Ò ¬>*u¦’8-Z´p\ïºò0…í‹/ÌuÇ•WK|Ìê˜M©DÎÎ;}†!u4_rÉ%¾Ä˜2;­téÒ¦Ae[7C©³ZÁGT¾&Ôy­ŒMÊœÚTºG#Ô ;qâDÓþU­[·n¡‹EåµÎ«nݺ~ˆÊØ( † æƒsîºë.l¤CT¦¸ #PpÈ÷Üsm߾ݗS† ]cî¿ÿ~?”*UÊ”aO×e£S`iJM×Q é¦à¡pƒI•I¥(UòRÙïBƒTµ?]w.¿ür>*Aªk§²ס`\°`AŸáHãÌhÊö§AZ4@@@@@ȰB\ÀQ‚ôCîéâZîðæfô•µ#h*1AC´ ¸J)®óÏ\`I\I¯ÄGî!×a˜öí*#ÒsÏ™+“¾ !íÑõs¦¹1ºwïnÅŠ³jÕªùL=¡ãSO=ÕŠ/žæí¦´‚²=䢵Tê±wïÞ)-j*9£Žâ¡C‡úÎß3f¸ìAEÝp5þ 4ÈÆç;A[º4H”é!(ÚìRP)[’ƒºvíj:÷p;…µ7u$'î°= eRF$e2R š`¬ý}ôÑGÞQ™)š4iº¯@"$  r÷ÝwŸU¯^Ý_RÛ¬|УAì>ûì3x¤k²à)HYGO?ýtxtÖYgù ÎÄHýû÷÷ßû?ü°)]¸Mû×õðÆoôÇûè£&XU×*e`R0“‚ÔJ”(áea¢!€ € € € € €@Î+À•‚XZRÍeÌ8Ýe(àHY5Tþ h*­CC´ (‹‹qÌ48týôi+.öÅߘ)ÐUX «¹~U$Ö¢I.¤²2 øQ¡ã?ÞgëY¸p¡+Ïæê³ý×TRæ”SNq™…ûòckùô6ekPÇ©2©ô‹Êµ¤Öyät4xð`;ÿüó}9™ J> 4zå•W|&ˆ† ú’‘Ï<óŒiP¶£¦M›Z³fÍüû%K–˜:†•Y)ÒMMÊf¤AÙ“B›2#éXØECˆ¼€®+ ÜÙ½{·3Æ]OÓ\¯T•ÙÔ  •ØTà‘†?üÐt šÊ—áÒª|š€T­~ýúv÷Ýw‹„=Ö5ñ9q¬ÌL]ºtñ×c­¬ŒFcÇŽõÁ³Ï?ÿ|ØÛcA@@@@@ˆM°Ž\&¢Ï\ùm®£¿ˆÜø®òåË¿œ•‰mzR›†ihÛ6®”Wz‹’ÛcfÏ>k®”‹ÙÕW› LInɸé£G›ËLd6eŠÙŧ¼lrsïté”v¸ÔJ&LðšZNeaÄ£ŒAÊŠöùçŸÛܹsݱ=ë-£ÌÊtá…ú Ä%`´LrMÙÔÔ¯_?;í´Ó’[ìé *R¦£Øyçç;“GåK×ìÝ»×Î9çD¤€(5eRV ê,V¹rê åþtiÿÖ®]{È Rf—^z©/#¦ìq‘h Ú™3gŽÏÚ\ 2²]•×¼þúëý @\]»¾p5=5(sÝ®†ê믿îw¡€Ó´”R =.ö>Ü”=©gÏžþº¥€Y=5p‘Í“&MòöB×á5 € € € € €äŽ÷Þ34c®t˜™Kè“®6kÖ,ßQªL<*=´¼yóÚ 'œàM»í¿tK+W®ôG >Òð /øAŠÔIªReN>ùä`S‡ŒôÀør3Ê2”Ö¦ut¤¬LuëÖõ«+…¶™¸LY WsMƒ²MlÛ¶ÍfΜi*£À$ Þzë-h© oúnÏ즀¢)ŠŠM¢)Èfòäɦ`L•õTé0e Jo[í.ä÷Þ{¯U®\ÙTÖ,ÒM«ºîh‚V°ûõ×_ÛW_}å3*»]z›²ó]uÕU¾„›;^z·Ëz € € € € € ;á™ËØq¿ëXïà:d|‘·umž€®P¡BX"zû=™ Ž—={öᣠ€p·¿/È.)¹¾9S¢0ÿ7ñgÕ¹³ÙG™Ë&`Ö«×á;ÑË.KyߪtæýøAAO.y ¢Iy¤æêû@š*ñõÔSO%µÈ!ÓT>FÃu×]çç©sW™Óô£à¥Ù³g;»^þ»EH*3£¡N:V @_¦­S§Núnó¥ÔÒÛù­eeTRæ¢;î¸ÃgX:ä`M(R¤ˆÏ¢‘h2o@˜PÉÌvíÚÙþýûýwf«V­|F¡-Z¤¹ÔXz”OÁF*;¦lx.Sg‚AÇ¥2a#\=Q•S™KÜÜ~ûíV³fÍ4ïRKýõ—ýïÿ³‚ ¦yýô¬P¨P!ŸíOÿ"ÑT>têÔ©Þ¤lÙ²>;_F‚°"qLl@@@@@²Ž@ØG®3¥+«æB lppø?þøcYe"¹ÌE%ÔªUË?M­ ¢ ¹¬Höûï¿ûrHK–,±ñãÇû×Á|Õñ×]w…Nâ5Ù^@ÿ¸XSO£‹{×§O»çž{|`Ò°aÃ|©Ì1cÆXµjÕ\¿Š~P€¼½W‰3e¹S 6][4Ö0mÚ4ûàƒìÆo +5©cÉ Ód4xð`:t¨6Jïõ9+œ Ç€ € € € € €‘;àH»^ºtéƒÕ«W¯ä:lº‡¢ŽýW_}5x›`|ë­·ú," &†¼QDz™è)s±" d®?Õ³˜ë¤Œ+5öàƒf.™ƒëÈ4Ók×ß\ÿ« ´1ëÑÃÌ%¾ñM17óæ™uìh.ûŽÙòåfo¾iV¼¸¹²aqH®*×a 8R µk¯5Û¼ÙÌýon=f®nÞÁ9q¯\…—Ì\F3×ïêˬ¹Ä`6nœYÑ¢‰—ŽÌûîÝ»»@'éô_Óÿ§ê4Ý»·£ ºØiÆg.pê —…b›;–s­iÓ¦Ö¬Y³T3GÛ Æï¼óŽ/=£LÚFf¶’%KfæîØ cL¤¦rjI5¡÷íÛ×î¼óN_òì1—6O%Ð}ôQ¿NsW?4(iV¬X±¤6‘ì´oÝ…Y×´víÚùÒ¿É.ÆŒ‚ Z5üÆâ,‚ € € €¤I@§ô š6ÆÂ € €@&¤'àÈÖªU«~=zôç?þøcu=ý½bÅ [¹r¥ééïÄ­KÕâ”ÌeF².]ºX•*U/Â{²µ€‚€00À¬_?s™z=kçË©…ÎQY2Åë¹D ʬ….£×7ÝWžMK—]f.3Xâ%"óþ‹/¾ˆï˜}þùç} ‘Ê˨¹$D.+™Y¾|ûìÜs÷Úœ9×Ù¬Y³,Ò2Õ\ ¹‹/¾ØgŸ}v|& ÍKÜþv)”ÉBßO<ñDâÙ¼Gˆý]øÆo¸,}õí¤“NJñŒòåËgݺuó+ªÜÚ#.m ²ßiš‚~*T¨à5jä•T¢7¹¦ìF ŒOkv£ä¶Çt@@@@ ’ÊÄÿúë¯Ûk¯½fóçÏ7e\¦!€ €ÙE ÝGÁ ªóh¨êDý×6oÞl.É—ÇÐë .*Q¢D0›11) >Ô… SJîį».áœ={öØ¢E‹üÿ7eË–õe¿´„K 䇄KGö:dÕq;xðàCþ¿u‰Ž\¶ íO_縌Dçø ;\¸¹.}Ó{ï½go¿ý¶ËÈô””IY)Z´haê V€ÑîÝ»ýX¯¿üòK¨¨`#' @ ö&MšäƒÑ“Ën”Ôë:t©«EªA°.¸Ýe×[ã•4Ók—aÓÞÿ}[½zµ)@V%Ó·~øÁ¸Ôºuk«]»vâÙ¼G@@@’øçŸlݺu~øí·ßLÆ |iu­ ‡›‚ÊuåÔVµjU?.W®\’÷*´®2ýùçŸþ~º‚Œ>üðC_¢]÷Ð/¼ðBÛ¹s§£!€ €ÙB ÃG‰Ïò˜cŽ1 4ršÀ‰€2|Úýû÷Oħ+ ÈÑ *çœsŽ/ £€žH6 éÇ͵.í’JƄ۔¡¨eË–~xæ™gìûï¿·éÓ§ûaòäÉ¦Îæäš:€oS­8 €@L ¨œZþüù­cÇŽé:¿3\}R ‰›‚s/¹ä{á…|`î°aÃ/âƒguÓO×U € € € œ€‚€ô`ÓÈ‘#mÞ¼yöÇ$·hXÓóæÍk•*Uò÷ów¹ÒÛ·o÷ömÛ|@Q¬”Ç•EлW¹z`ê矶ûï¿?¬}° €  8re’.qO›ßrÀË—.]zsÈ{^"€@ÔªÎY= q™« Æ €  8rd)݉+èß\q%9[`ýzs›f.NÇŽ=62ÿûßÿLe {÷îmwÝu×!ݲe‹M:Õ&Nœè3éµR­ê镞9÷Üs­X±b‡¬—Ú=½¡ò4]»või_S[>Üù¥J•²öíÛ‡»8Ë!€ÄÀرcýÙ¤¥œZZN_¬Ê¨×ÌÕ}衇üõPÁ®j>ø OQNv£´ˆ², € € €Y_`ÿþý¦ûä Ò½t z¨UA<ª ±ö(€hïÞ½>«J•)ÛÆ*öÊ+¯ø‡™T>­téÒÖ¯_?\Aim HÒC¸4@@ § „päÒ;. "µäÞ—Ó 8_ <ð€¹'Ìš77—e(ñÜô½Wi=%¡²fIµâÅ‹›:n5èGÑo¼a&Lðƒê=»Ldvê©§Z“&MüpöÙgûWIm+tš:d•敎ÙP^#€¤W@7ÿ”‘O™ìT 4ZMA·ï½÷žwÞyþÆ 2)󟮉矾5lØ0Z»f» € € € %•[µj•)CP0üôÓO>ÈHÁFAI²Ôv¯@¤}ûö%»˜àU5¶mÛúìÿÉ.È @@$ 8rà_©"µ|TªråÊ¥“Ü"Èæ“'›Ë dvï½fõê%}2®JŒcÖ¸qä‚”juÖ¬Y>SQÉ’%“ÞqÈÔc]Z¥[o½ÕkÖ¬ñ®ü±Íž=Ûžxâ ?è •’Q™uÆ&Õ¦M›f_~ù¥Ý~ûíV¾|ù¤a €i˜1c†­w©ŸfðM={ö4ï*àiÀ€iØ ‹"€ € € €Àáرc‡Í;×ß×½êï¾ûζoß8yòä±ãŽ;ÎjÕªeÇsŒt=x­ ¢mÛ¶%´¾²}ôÑ~ÐCJz­±`ºà‚ ìÄOŒß/@@Ò.VÀ‘‹$_åþ˜{Ù]ìÂE†S')À`3¿ÿn.{™û}cï¼c¦j0;zzUª˜=ù¤Yýú‡ÎKï”1.‚IOftéÒ%Í›Pš×nݺùA+ÿøã¦à# *—¦r3½zõò¿úq4íOYôC«OŸ>ÁdÆ €1&°gÏ»ãŽ;¬iÓ¦™RêòÅ_ôY÷®¿þúL‘Ô Æ™3gš2û-^¼Ø—Õk € € €d=ݧ˜?¾0ÒC¸_|ñE|&"eù?ýôÓ}&eó×pòÉ'ûÊYïL8"@@ g „p$" ÞÓ•\:ß•Ó{7~ÔEšÏ¬—\ -DC › ¸˜lôàƒf#F˜]q…‚wÌT>íˆ#žŒbv\r¡ˆ5ebx饗Ìeó%`2ºá“N:É4tïÞÝ”9éÊ+¯´‡~Ø>úè#_f¦Zµj~¯¿þº}ÿý÷.›Ó½¦ŒI4@ؘ7ož=÷Üs~PºðáÇ[Íš5£r²›6m²éÓ§ûëY… ¢²¤6Z¦L£Rû(š”Ó@@@È|ýðöpáB?,Z´È¾ùæÛ½{·?e.nÙ²¥HJåÑkÔ¨‘ùÉ@@Ò%vÀ‘+Ùô§ R8וhšéöTÉåw:M{ì1;óÌ3ÓµsVB + 8w4î·õíkvà fmÚ˜ tôÊ+æ2Eçˆßqé”Ö­[çö5(â¥gªV­jŸ~ú©/-óÈ#Øi§fÏ>û¬Bºÿþû­páÂ>ûQtÎŒ­"€d¥#WSºpeÒµ@™ñtÝÑ“ƒ‘l¯¾úª¹r¼.c K˜É­R¥J6uêÔLÞ+»C@@@ ç(€èÛo¿õY‰”™H¯õ@íQGåeØ×k7lØàƒ´NД¥¸qãÆ¾4ºŒêÔ©c®ß)˜Í@@  „p¤sZ¾|ù2÷¤ú™ùòåéŽ.þã? Þà¢2Î;ïòG9zôhÿ£Jÿ?E£¹ˆ6dÈ_Zíšk®±k¯½Ö† f¿üò‹)è(ÒÍÑ8¶‰ ~årº7ß|Ó–,YbÊ4Â¥ò›è.p´›nº)b7÷TNMוK.¹$ýÌš € € € pXô‘²'–.]ꃌ`ä*bÄ›þÉŸ?¿íÚµËX¤õƒ±²5oÞÜ)°H@ef6äøƒä € €@TÂ8:î¸ã–»@¢|ÁQüûï¿Ü{¢a¾L“J5e¤)ð†@Vp^Ä7÷;É&L0WžÌìÿþÏìŒ3ÌFŽ4kÝ:~‘ ¿øí·ßì½÷Þ³‹.ºÈÊ•ó 3¼Íä6ФIÿÄÉ7Þè‚§¦Y‰%¬gÏžÉ-Ît@PÀ‘Jm(PÀßÜ›;w®6êåj‰Þêj„ª´¦ž>Ô… L Æšvê©§úl–gu–~úéæJ좢,}J‰®Œz‹/öÛLj¹CVd € € €6-[¶˜î,X°À_}õ•mܸ1ÙãуãM›6u÷Éψt™† € 3Â8r}º/}¦Ê]U Ó=âúõëûAŽ•é˜† € €@¸a¹?@·º&¨¡á:™ŽvO·'˜îŽY¬ à3¸, fÍš™Í˜‘ùG4sæL[µj•õë×Ï—¯Éü#` €±.RÀQ8ç® ¤sÏ=×Z^Á²?ÿü³Ï‚tâ‰'rý ‘e@@@HE`ûöíöÒK/ùßÜË—/7 ÊX¬ #5e zðÁ­gÏž¾z*›3•Sùå—íÍ7ß´­[·š‚Œ5jdW\q…µoßÞg/JmÌG@@ %°Ž–,YR&ñ†\‡Ó874)‰axŸ-\©Ýz«¹Zf>zxy´K¯¤z7Þxãá9öŠ ó 8ÒŠÊ<‰¦ëV Õ¥!€ € € €@D”}è®»î²õë×ûí(PÀªV­j­ZµòY*T¨`Ï=÷œÝ}÷ݾ$š“”ñ(©öõ×_[Ÿ>}ìÃ?ô³ëԩヌ:tè`Ú @@H „p©²RØ¿ß\¶„Ô–Êø|uïnÖ¢…¹r0··víZûøã­cÇŽæ2xœáW›6m²iÓ¦YÓ¦M“ýqá]²9@(ðÕW_iÑsàÏ)#€ € €dy_~ùÅn¹åûè£ì˜cŽ1= zñÅÛ±Ç{ȱwíÚÕz÷îmO?ý´¨è‰'ž°.]ºÄ/·téR»ï¾ûì7Þð¹^wÝu>ðè„Nˆ_† € €DR W$7ƶˆ„€{àÂ.¹$[J}W^iÖ¿Âå d×^{­Õ®]Û>ùä“„3#øNélU?;ôGa7Ϧ@°5kÖØ† ¬^½zh € € € €@ؽ{·õë×ÏéáWÝ#VðQçΓ 6Òaçϟ߆ f3gδâÅ‹›Z¶li‹-²›o¾ÙN:é$›4i’Xúî»ï|y6‚²ÈÎa € €1*@†£ý`³ëiýù§Ù÷ß›rÊá;ƒO?ýÔ *d+V¬°sÎ9Çô$È£®æšž0I®mÞ¼Ù§»-V¬˜iPÊÛÐvàÀse í›o¾‰æÍ›ç·yIfEW…¯@r„€Ê©©p”#>nN@@@ ‹ ,[¶Ì =òÈ#¶jÕ*;í´ÓlĈÖ Aƒ°ü¼óÎ3Ý~ûí¦‡Zß}÷]¿n£FLÛ=óÌ3ÃÞ "€ €  ýû₩?’UXõ…·nÝj»ví²Ò¥KûzÀåË—÷ã2eÊØ‘Gfxw9WÖÍó盹RvÖYqëþ9YÑ¢‘;ð}ûÌý3«^=émþé"ž~úé'_ÓzàÀ®äZwÿ$ÈôéÓýµN:ùt´zEÙT[O”|ûí·î¸Ýÿ׎:ê(x¤'MòæÍëƒôÿEÐô4JMWÇM? µ, @hp U¶‰ € € €@x¿þú«)ƒ‘J¦iÐ{µÂ… ûlEºÿœ;wîð6²T‘"Eü}ë¶mÛÚØ±c}f¤V­Z…,ÁK@@¢/î råÊ•èÛ·o-ý±¼eË–T4Ož<Öºuk»é¦›¬bÅŠ©.Ï9S E sOg˜ X3W‹Ú\Mê¸÷ÕªEÆÃý~³×_7sIŒ’Ì¢ôÙgŸùÀ¡³\ÄS5·Ó3fø4´={öô?Ú^x៺VËýóÏ?þ J•*e;v4¥§UÀ‚–ôÿD0Ö4=]¢mÁpüñǧë‡ddØ  €@NPÀQÁ‚­F9å”9O@@@"*ðùçŸÛ¨Q£ì裶³Ï>ÛßëÕƒÖI5e‚‹fÍšåÖ–Óos)C‘†¢xÒ¶M›6¦† € €ÀáHWÀQõêÕ/Ë•+׋S¦L)îAïÝ»×Üò6uêT_CX5…+W®îê,—Crå2—ù'îdO=Õ\¶,³‡6=:ã=föüóf\`vâ‰IoODj 8 Úå—_n-\$TÿþýíÙgŸµ|ùòY“&M¬Y³fvþùçûLEGqD°8c@²„€2ï)e:uÌýÝ–%މƒ@@@ Rû\ëÐlÓ‘Ú.ÛA$ ï—·ß~Û†ê^uO¯þ×TþLM} >Ò RçÌ™c 0úþûïã¿›ªV­êbUp‘î'«* @@XHsÀ‘ 6º×uZ¹ôµýû÷û £·ÞzËzõêe7ÜpCú6ÄZ1/и±¹lf¯¼b6`€¹Ò|é?å7ß4÷ï-.«Ño˜+ï—ô¶æÍ›g… rÙNI°@âÖeõò¥Ò(ƒ–€‡7 €YP`É’%¶mÛ6«W¯^<: @@ð”Aú;—[ßþòË/ñãåË—»‡ÊÜSe4@ ‚{öì±W_}ÕsO¯þôÓO¦ûÀ:u²»ï¾Ûg¾ÿä“O,Æg‚¦€¢+®¸Âš6mê3ñÀu Ã@@ V’ »Hút]¨3\dÿƒIÍ­à¢A”F´D‰>èöíÛmÆ ¶qãF[»v­)ÃQh;pà€Ë\ó°éi¤.]º„Îâ5ñ÷ÝgÖ¼¹¹'IâJ¬ÅÏHà WMÆ®¾ÚìØcÍÞyGõ±“^YÿFUzFÙ’«›}¬6BC@ 蚦FÀQ6ø°8D@@$V¯^m§ºØ ¤š:ÿ«U«f 642N*Œ@ 'N´;ï¼ÓÖ¯_ïû8z÷îm=zô°2eÊÄo^AD×\s¿iÓ&ŸýHãFÙI'¿/@@È i 8:Êq?äs0yóæÝë¢ûó\tÑEæ‚‘‚ɇŒwìØa|ðMŸ>Ý,X` 6 Úã?î<øc<ɹcõ‹þý·¹F3éA5%fxá³~ýÌ¥M›‹us%üÌÝ€2sIµ¬bÅä×_´h‘+á¶+A9µä—f €Y[€€£¬ýùpt € €@NЃ‡zÈ+Ü@!=¤¨`£xÀÒëþ£:ûµ •/=ztNdäœ@ »›Ò·ß~»=ÿüóî¡ÕcM}úþQ&ü”ZÉ’%­mÛ¶)-Â<@@bZ ì€#÷ƒ¾¯“ˆ¯3傾yýõ×WÖ¨Q#Õ¿¨õ‡yûöíý Èúc}ëÖ­Vµ d&LˆihN.ue1úßÿÌ\¦l÷cîàòÊrÔ¦¹4¶qÃÁ9©¿Rò,—h˦L‰ \JiÏ>ûÌÏV†# €Ù]@GÊ}Ìuž†wò®Ô¶»eîßšY»v©¯3Ï€ž«_¿~ê ³ €YX@OŽóÍ7Ö¸qã,|” € €@vøë¯¿ì£>²¥K—š^+»yèXå…¾ýö[ŸI:8Ge 9å”Sìã?¶›o¾ÙÆŒÌ:d¼nÝ:_Ö¨\¹rî4÷ ˆ‚€‚‹ô}¤ G>ø »÷Ü'ì lQ86‰ € €@¶+àÈÕE¯æÎ¬`ÈÙ=¶lÙ²µ!ïÓôR›õ²¶õÇdt“¬ŸTNMí¬³âÆ‰ÿëîGYß¾f×^kvà fîÞ“åÏŸx©¸÷.©ƒMœhÖ¦Ùe—%½Lâ©Ên¤vVrxÞ#€ …8ʇ† €DYà·ß~³iÓ¦ù e t?nùòå¶páB[´h‘÷Ýw>;fJ‡UËÕº¿ÖÝ”iÞ¼¹Ï’RPQJÛѼ… û€¢3Î8î¸â ›?¾tÒI~5Üîž"SùµaÆ¥¶)æ#€É èáÒIîiÔ9sæØ'Ÿ|ßÿ ÀGe¹ïën6÷èуjÉ 2@@Ô 8r鎫èq5÷4ÀÖÔ7ÞÇ<GáQÅüR 8rÙk­R¥äOõÊ+ÍÞ}7.˜hòd³k®IzÙSN1s©ØqÇ%=?©©J®¦tß4@²»€Ž”¾L™2ÙýT8~@@4üý÷ß>+P¸™ÄK–,i7¶ÓN;ÍjÔ¨áË—)(IAAôZ%ÍŽ>úè4Eê‹V­ZÕ¦L™bÍš5ó%Ö¾øâ +Q¢„uïÞÝLv7~Š/žú†XPƶ÷Þ{ÏFmï¼óŽéý‘Giª¶pƒ{ŠõœsαFù@ÌÕx‰ € €é+àÈe8Úlß½.W¶lÙcÜ®`UÆÚš5kâ7'Ožø×¼ÈY.[·)+Qûö)ŸwîÜf¯½fîé7³Ö­S^ÖývLSSÀ‘:f+¥ñ”¦-²0 €‡G@L‹Ý…µU«V‡çØ+ € €Àa¸ãŽ;LÁFwÝu—ïXߺu«ýù矦±•I«P¡‚ï|WQùòåÛ±ªãĈÖ¥KwO¨½uëÖÍht饗ú÷‡íÀØ1d9}ûöÙÔ©S}ð%UMãbÅŠù E«W¯¶_|Ñk×®µÜîFò…^h;w¶óÏ?ß—‚Ìr'Å!€ € a¹ó\z®®V{÷þíÐii}½wï^_>X§–‰œ7þüs³’/§*rÄ©….ÎkÝlSǬnhÑ@Èî*¡›±õêÕËî§Âñ#€ €¤A`¢«/?jÔ(ß¹>tèP ²•§a™¾¨‚~øá{ê©§|É#e9zöÙg3ý8Ø!d]•+WÚ•.õý纉œ¨)°Hý üñ‡»¿|À*V¬h<ð€uêÔé°T&:LÞ"€ € ³a¹?Öçé÷ ¹,Gç¹× 8úþûïMAGA«R¥Jð’qøì³¸>ë¬ôø¦MæÒp›»¡fV½zÚ·¡«úAzVz í»d @¢& rjjE˜ #€ €YN`éÒ¥ÖµkW_RwüøñÙ"Ø(@|ì±ÇüC‰3f̰áÇ[©R¥‚YŒ@ ‡ èûì–[n±;vØwÞéË?nÞ¼Ù4lr7…ƒqéÒ¥}É´æÍ›g«ï¿þñrú € €1 VÀÑòåËçwÜq›\ QIó¿ÿþ{{õêÕ¥÷üõÄÁ=÷Ü“`õsÏ=7Á{ÞäWÍÌŽ>Ú¬víôóÝw›½òŠY¾|f³g›Õ¯Ÿ¶í¨œšÚ™gž™¶Y@,(Õ­[7 ‡„ € =„·~ýz[·n]ü  Ìz JÃþýûãÇ.Ó¸Ýxã¦õ¤šJê^vÙe¶k×.{ë­·²]ÀŽrœâž$ûâ‹/ŒûƒI}ÂLC ç èû°{÷îöꫯZÙ²eíÍ7ß´¦M›æ<Î@@,.VÀ‘;Wðʆ»aÎÇår£±£Gž¯:ëiiýõ—¯É®ZÊAS½å T¥–ÓÜý3[°ÀìŒ3ÌÕàNßÙfîFœY¡Bf§Ÿžöm(àèhñT;½Oiß%k € 5¹Àp+V¬XÔöÁ†@@Ò.0}útò鉫vÇwØ·ß~k̶;º/C°QȇÊKr°€²Ñ_uÕU¶bÅ kÓ¦3ÆTn‘† € €YO ì÷äÕcGuÔî*ë4\ÐQn—ò¸Ñ;ï¼cW\q…µjÕÊôÄUrí·ß~³qãÆÙo¼a : m={ö´¼yó†NâuPÜYÁ‚Ê.”þ.ZÔÜÓ.é[_O .pOõ]Z¤#Óñ”¾]³ €é˜íRú©SFYŒråRx\Û¶m›-Y²Ä:vìLbŒ € p˜6lØ`=zô°I“&¹‡¥ ùž”±#ñPÔÝàP¶ý}§!x½xñb»÷Þ{­_¿~öüóÏÛ#Ë"€‡S@e$_yåëÛ·¯/5yÚi§™¾ÓjÔ¨q8‹}#€ € €@ai[®ë›jÕª]äž²šä‚ŽÊ…n÷îÝöÃ?ø!tzJ¯5jdO>ù$7DRBÊ!óÜC+‡¥©œšÚ™I±tXŽœ"€ä4eË–Ù¥—^êËe4oÞÜg7úàƒlòäÉþiyyè©x5Ž<ÿA@›€JuëÖÍfΜ邦L™âŽÒ{@Êö¡£k®¹Æî¿ÿ~9r¤Ý”€S@IDAT]~ùå> Ò[o½e¥J•Jï¦Y8lsçÎ5U?X¸p¡ÿSƶÎ;Ó_pØ>vŒ € €@ÚÖàs=—©è3\tœ[¼Ÿ+ƒ¶'ÌÕ,V¾|y{â‰'|ýeW¦-Á<Þ ™ 8rÁsÖ°aÃÌÜ-ûB@ M*I{úé§›Êi 4ÈÞ{ï=ÞO>ùÄ^zé%ŸöuÆ ~;2QI“Fù×uêÔI×ö£¹ítPWrI\êo³nˆàFÓ°)e7R;óÌ3Ó°‹"€YW€k[ÖýlR:²Ñ£Gûi 0r¥kã;­´ŽþžèׯŸ=ðÀ–;wî”6Ã<@ &¸¶ÅäÇÊI!å6mÚdÊHô×_%86Ýשì¤;õÔSýt‡k8pà€ëoµÚµkû#ÝÿÉ›7o‚õyƒ@R\Û’RaZ¬ (ˆSÞô`r`¤÷ªV­k§Ëù €À\ãø§€ €@ΈHÀQvd›>}z†[Ùqî½÷^ûúë¯Ù–n@)Uì›o¾é‡óÎ;ϧ‡-T¨Ð!Ë&5!šÛNj‡cšâ}\,«^ýpìÝ,8:묳ϰW@ Â\Û" š ›[°`uëÖÍUªTÉ?ÝYÝ]ƒ¡fÍš¦é4@ § pmË©Ÿ<ç@æ («¤‚z÷îí;Ãõ÷—e-¢!i®m‘e{YM`ëÖ­Ö¢E ŸY^é^wÝuYí9ˆ’׸(Á²Y@²°@FŽrÏ;·¸žÆWgÙ#¼lx¬\Û²á‡Æ!{Ÿ~úÉÞ~ûm»ñÆ­xñâɪüóÏ?Ö¦M_¢rèС%+Å bO€k\ì}¦œ €á¤'àèˆãŽ;în·ñû\åÂÁNöïß¼}ú˜J§(ívR-šÛNj‡sšû}õ&ï‡~8ÙýÜp¸ê¹%{DÌ@Ò.Àµ-ífYa =éùå—_Ú]wÝE°QVø@8ÈR\Û²ÔÇÁÁ åÈ­ÎðÏ?ÿÜúëâ‹/¶¦z쯿þºýþûïöè£l”ª dD€k[FôX÷p èáM•ø~æ™glïÞ½öØcÙÓO?m—_~ù!‡¤r“W^y¥¹‡”­gÏžvÏ=÷² @ 6¸ÆÅæçÊY!€ Ž@šŽ*V¬XÌ ½ä‚eZ‡³ñ¤–Ñ3gδ… Úã?îƒt’Z.ÒÓ”ûÃ?´×^{ÍgÈÈö'Mšä2óLÍ“'O;v¬Õ©S'Áf5jd:tðOr™>ùä{ã7’üQ¦•£¹í—Þ(ë–‚êׯoW]u•)R$Á Œ\•+WΜ"Ī׶ìûÉnß¾Ý!+Óž‚°i €q\Ûø—€á¨S[ÁE|ðÍŸ?ß?ð¥Nñ éa7elß¾½zê©Áä$ÇO=õ”(PÀ:wîœä|&"Q®mdýÃ! ïYÝïîÛ·¯mܸÑß_Õ}î!C†øûݺǮìpeË–?¼[o½ÕTéàŠ+®ð÷ýãgðbV€k\Ì~´œ €a ¤%à(—Ëâó±ÛrÊwjÂÜõ–-[|– =m–Ôan&ÙÅôtÛOé&×gœ¬âkXÿúë¯ñïƒÑÜv°Ã=Þ¹Óì•WÌ}Ñ;’‰'Ú-·Üb®ôŸéf$7 £gÍ–@ s¸¶e®w´ööóÏ?ûôúÛàúë¯ÖnØ. -¸¶e‹‰ƒDà° ¼úê«Ö¤I;æ˜c|VqãÆY… ¬ÿþ>Ë‘2Gª|ÏСC­]»vÿÏÞ™ÀËTþaü !É’½dß"’ˆvÑ*K•ö,í‹DD–”•¨P¡¤´‘¢$¡Òž"Rñ!E QIÿßsNsïÌܹ÷ÎŒ9÷ΙyÞÏgÌYÞóž÷ýžkÎ9ïû¼ÏÏqÛ «C¨ÏŸ?3gÎ̶þt7bÈ{¬+‰@¢èÞ–(’*'¯ ì´Ž[ЇŽ?þxÇ%®oß¾ŽËÿe—]–! âo1Ç^ýutÐAàØ@ãÆç^öÓáˆÑ”D@R“€îq©y]Õ*ØÑ Ž˜opð‰L,4ý7ޘѻwog&;h²K|Ðч³øiÅÊð!ÄÎ~ðKâì·àÔºuëàÕl—ù¢œfÍš¼ê,{Yv–“åÓšCÙ;ª½˜zSû›tfÜÐΗb³à¿5oΨRE@DÀÿ¼¼ÿxY¶_Éß|óÍØ³gFÑië×¶¨Þ" "¬¼¼ÿxYv²òT½D ?üøãhÓ¦ è¦ñÙgŸ9Ët3fÈúE‹ŽÙ ¡^¨Pdónºm/^}úô‰8 Nد¾ú*Î:ë,Ø$»üh¢Î)1ðòþãeÙ15R™óÀW_}åôñO˜0§Ÿ~:–-[†ûî»ÏEªÔÙgŸo¾ù×\s3¹¶fÍš ûEHJ" "+/ïC^–k;•_D@D@R‘@ä^™°–šSL3ÛT/hóŠ¿ÿþ»ë¡‡údж¨;î8L›6 m۶ŶmÛœcžþy\uÕUÎlµ¨ ‰"SœÙm‘²2îô<iW®Û.\˜‘‡"«“O>9c=§…`‡#æ£àˆmN^–|žüZ¦«‘E¹C¥J°XÞ‰¯g4vîÜÙq4¢Ø¨jÕª‰?‰J|$ {[è}3/Eܧž1c†ã¾Gg#)‰€ˆ@ºнÍÿ÷¶tÿVû½!Àð=iÿöÛoŽ#äÈ‘#cv/f †Z8p 3Ñ-ÜÅè‘GÁ?ÿüãœÇ›V¨Ôt% {›îm~ûÛg”†IãoâCÖyÛ«W¯¨š@qј1cÑ‘ä!ª•ID é è§{\Òÿ‘ª‚" " yN *Á‘ÕªfpÍÌÝèö5kÖìÞËr¹rå0`Àg–3ñ^ä„Nˆ¥˜óR Ô¡C‡ˆyV¯^—àˆÇmÙ²%£ÌF¡L™2ë9-4lØ‚»vír²­Zµ*$»—e‡œ(WÌÝf"ÂfÇEŠ$®"œõH±í}iÙ;{ölÔ«¬KܹT’ˆ€ä'ÝÛò“þ¾ŸûÏ?ÿt:nK”(á„”Ý÷U‚ˆ€øŸ€îmþ¿†jÄB€!Î>úè#'üÎÑGm’lFRPâû=Ãóp’¯§L™â8e‰iñ–[n]‘†ê8%•.]Ú9~ÇŽ ‹Gƒ pÚi§ÅT¦2‹@ntoËö' †¤äoî‹/¾ˆêÕ«;ßÍšqÞql‰ýÞJ" éA@÷¸ô¸Îj¥ˆ€ˆ€ÄB Új5‚ 5ÁÑ’àõx–Ï8ã P H&` ,&í÷Ò¥KCê‹å6…0UªTÉ8ž"+¾Ô’—eΑŸßÿþ Œ”, \}uü5™9s&lI‚qÁi^¹retìØÑ®1~8·+‰€ˆ€DGÀËû—eG׺äÊõàƒ‚ãAƒ)ägr]ÕFD Åxyÿñ²ì» jŽ„ j3,ýwÜvíÚ¡Ð)8bX>щúˆ#ŽpÄFœPÄp> ©¶/‰¿î½÷^lÝºÕ Á(kÒ¤IŽë6=”DÀ¼¼ÿxY¶ئk¿øâ §•b£N:añâňGl”®üÔnÄðò>äeÙ‰# ’D@D@DÀߢu8ªÔÌ¿W®\¹&h=®Å"fqCN@h´víÚ¸ÊÉ˃‚ÝxÞR¥JÅtú’TÛ%–G—&/Ë:eT‹+V¬À’%K2ÂÅ-ZÔ ÿÕÁÙdzí5àÛoþýamÎ&S.›ß}÷]´oßÞÉE%ýa‡†è«[·.(þâ¬D9åQ»E@² äŠ+®ÈØNA(g<‡ÿfgdH±/ï?^–ëeøþûïAwÁàP¨ ¿Y¸páX‹Š+ÿ† 0|øpçžÎ#®uˆ€DA€á‚¦Nêäܽ{·ã¸Åa¾ÏâåýÇ˲cÏ{˦M›BîmÓ§OW8“XA*¿çÞzë-ôèÑëÖ­sÞÛû[ÇÀwß}‡E‹ÞóæÍsDF¬EHÏš=2EH‰Jœ°4jÔ(<öØc¸öÚkQ«V-Œ=Úq¬¾øâ‹u•“G&Nœ Æ˜è š.ÉËû—eÇz}(ܹsgȽmòäÉ!“8c-Sù³øàƒ@(ûW¿Ysi‹ˆ@^x饗œÿ‹<ß_ý¾»¥Sòò>äeÙ±^£/¿üŸ~ú)æÌ™ãJw¸G}4Öb”_D@|A€ýaÚ³gOˆ ‹/ JÆD ZÁÑßRÍݨ9Ê^¿~½,°#Žo¾ÔÒæÍ›‹IûýÛo¿…Ô-VÁQ@\(„;´«eò²ìÀù¢ý®V­š3 :‚–D–‚¨¢-#<ŸM(„é–,xøžè×Çç¼³3²E‹i3`=!切]ÒžzꩌC9ÛºX±b멾àåýÇ˲c½. ÉA¡ê˜1c2¥û`^¥3f8çÆ sÂæÕyuô&еk׌A{Š÷9¸”ÉËû—eÇzmª¼lÙ²!Ï1é"˜Ž••òçþaH3 DØòÄO8Â#Öæ”SNɨÿß|ó –/_ºaÇÚ×’QP6 ì{9r$Ž?þxôíÛÝ»wÇÿþ÷?›Õ_ý Ù0KæÍt¸nÙ²¥SÅ… fk“¹Î‰¨›—÷/ËŽµí¼Ñ™,ø½bÅŠ±£ü9 P¯[·n(X° Þÿ}0¼¥’ˆ@þàóOÓ¦MJð™ˆBÀtJ^Þ‡¼,;ÖkÄÉò|&¾ú¿ ¼ß)‰€ˆ@ªàûwà™þ‡~p\Sµ­j•àÈDFâ ûÞÏoê¼Åû7zº RéÒ¥‹Iûþpkgnxþ`uµ—eÇ ”îSt5ªQ#$’^¬Ådä·± Sn»¡Ô*TÈØÓiœ­ËÙ7Á“1¢Ì" "n‚ïx¿K„Ð2©’r“—÷/ËŽ&¯søµŽµŒ}ÉÏA-&YÔï E+"+2eÊ8<Ž×|ÎO‡äåýÇ˲c½6Î*T(ä9&Ö2”_ö…ÀçŸîÌÊ>ðÀwPöy>œ™ÏÐi?þø£#"zòÉ'ñw¤óñoùÈ#t>‘ö'bÝ‘»té:0´ÿï\wÝu‰(Zeä1öú隥{[tÀ/}’Áð}<ø=º*W´î¼óNGtyÿý÷Kl-4å žŸxšmÛ¶¥ÝD5/ß±¼,;Ö? ޹ñZë+9åð#âÅ‹ƒ¦½{÷:ïà~l‡ê¨GVÔ¢àâl0öj[¿*x[¬Ë Ùœ*Uª¼š”Ëá'±Îº;è ƒBÚÅ=äeÙsä×÷}÷ÁfÍ}úÄ_ª i'zÕUûôgt¤ˆ€¤(/ï?^–í·ËAÁQ œ¬ßê®úŠ€ˆ€ßxyÿñ²l¿qV}Ó›À®]»pÁ8!k³#Á• &àÊ+¯Ì.Kžn¿×¬—_³xï ©Ì0ktÀT¿ðòþãeÙ~á›.õd<…FMš4qèÒ¥Ýj§ˆ@rðò>äeÙÉMUµ¼#•àÈbë½m®TÇ8R4]Q³fÍéñV“Î>¸}2N<ñÄÀbÒ~Óõ"8Ñ)!–D›ðà<»È˲ƒÏ™×Ë6q³gÃ:"aÊíøÎn[àlÈ fÔ¡C‡ø ÑQ" "  xyÿñ²ìˆIâÕªU+­Ü³’ør¨j" )NÀËû—e§øeQóRŒÀàÁƒ±Ñ<€K.¹Ä ÏßÿÝYÞ¹s§ãPœL“ËÒž!Þî³YQ½zõJ±+¢æ¤:/ï?^–ê×ÅOíû矜’¬3Å t“Rd àå}È˲“ê " " É@ *ÁÑš5kvשSçI«p Gf³·}eôèÑK®¿þú˜϶nÝêÌn §ÆNŸúõë'ëP®\¹ýÛ·oYÏm…1²ƒSÀšÛ¼,;øœy½ÌpjLÝ»»ßñü;wî\§#³ÿþig'/#" ±ðòþãeÙ±´1¿óšpÛ #Û®]»ü®ŠÎ/" iAÀËû—e§ÅÅQ#S‚ÀâÅ‹ñÐCá˜cŽq„; T¾|y_´mذa΀»BYøâr©’A¼¼ÿxYvP´˜ÏFŽ †Âìׯ7nœÏµÑéE@D “€—÷!/ËÎl–D@D@D ½ ˆ¶ù6X6Ôœf~ ä7eð=öX‹sÎ9ãÇÏÑF›Ç|óÍ78p N9å,_¾þøã¸çž{|e¿M÷¦àÄY}Ñ&†S (1V¶‰¶2÷²ìŒ“øl?>´hgggÛ¶m}V{UWD@üAÀËû—eûƒ®[K ŽütµTWT àåýÇ˲S½ÚàOÓ§O7gâ¦4hêÕ«‡Ñ£Gƒ¡ÓÂ'±oã‰'ž€2Âéh]¼%àåýÇ˲½¥¢Òs#ÀÈ·Þz«Ó·zÿý÷ç–]ûE@D _xyò²ì|¥“Š€ˆ€ÏŒ7;w¦©Ïj®êÆB fÁ ÿå—_¶›ð莙3g¾Æ?’Â… GuÎ *`øðáNˆ¬–-[FuL2eâ,¾à îܹ3ª*RœÜa׺uëã¼,;äD>Z™={6Ö®]‹îÝ»ƒŽPJ" " ‰'àåýÇ˲O»~–¡fƒŸ!¼;›JðòþãeÙºr"×öìÙƒ>}ú€îÓEŠÁƒ>ˆ2eÊছnBóæÍñùçŸgTéé§ŸÆÜ¹s÷s9dd`Ñ‚ä/ï?^–g€t¢ü}§kÝ©§ž ›8Œ1cÆ8ï¤!™´"" IBÀËû—e' >UCD@’’À_ýå8l^sÍ5Žø=;'夬¼*3¸G³T¯^}×]wÝ…¥K—bÁ‚xöÙgAÑÕW_öíÛãòË/Ç!CÀŽ©÷Þ{ÏùtêÔÉW®F¶ò»@!N;tàùðód»üî»ï†ì;å”SBÖ½,;äDy¼²m[ü'¤ ¹Pp¤$" "à /ï?^–í oJ¥@™J" " yCÀËû—eç E\t`æD¨xÇw8Iê–[nÁ×_~ýú9ý<Ýxã`¸µÞ½{£R¥JC†þ‚D xyÿñ²ìü¡•¾gݾ};Fމš5k¢k×®X³fÓ7ß¡C‡ô…¢–‹€$=/ïC^–ô`UAÈ'tÙ¤ñ £qÆxå•WpàæSmtÚ¼ àŽlìIûô4Q…xNÊÐ`t/jÖ¬((êÕ«FŒþýûã /ıÇ‹Š+†„‹ç<ÉpLø ­ÄsKÛLuóòË/gd«V­ŒuÆz`Á˲çÈËo›@ƒÒ¥s]9­_¿o¼ñÚ´iƒÃ;,æãu€ˆ€ˆ@ô¼¼ÿxYvô-Ì¿œtBܰaƒGùw tf4%àåýÇ˲Óôr©ÙyL€š4iâL»ùæ›Á R‡z¨S‹bÅŠáž{îÁâÅ‹!Ò#<â„YÛºu+}ôQ”*U*k«Ó‰€xyÿñ²ì@ýõí¾sR,Ê>TŠG9£üî»ïÆ?ü€Áƒ{wb•,"  "àå}È˲Ô|#" )CàÓO?ÅÑG?þ}ûöŬY³ä´™2W7û†ŽNµ,[ت &súªï»ï>'\·éltûí·ãàƒNS*j¶ˆ€ßxyò²l¿qV}E@DÀ+ÿþû/¹ˆ!ØiÄò /€Ï§tšSJ}!WÙœŠ¸~‚]ü‹)²Ú„5‹M|4¨F SEô-ìÙ³gHæaÆaòäÉ`|ìàÄÙ%—^z©cMØnžŠë¨xyÿñ²ì¨§L1`ô…^þîOš4Éù}©e$#àå}È˲“ £ª#" YLŸ>cÆŒÁŸþ阧PXDó~s¢ÒöíÛ¾Fm O§œrŠÉéœsÎÉ¢oàqƒ C±3]ýõŽ^¢dÉ’áÅh=Å 8‚£ï¾ûîÊC9äú<ðLu4QQ[û.Üv[¯eë}ì»…Ùhy^³?ÐJmÛ¶Íò|\ª.S8ôÛo¿9£@)’á'R:à€ð裢iÓ¦‘v‡ló²ìy¼b“!ͺ7ö“L:Õ9èÊ+¯Œý`!" "7/ï?^–wƒóàÀ€àˆƒ|J" " yOÀËû—eç=)ѯ8ûðwÞqDFóçχõï8M±¾4kÖÌ€fÇ ]”D@Rƒ€—÷/ËN úÉÓŠ;î¸Ãq±ãLr:ì+‰€xOÀÆfÁ¨ŒèP° ÷çKÇ3xyò²ìt¼Vj³ˆ€?ÐÜcÈ!ŽYJ‰%@s”À§ ÝÌb½råÊ8âˆ#œpê¥J•r¾K—.%K–€cöìs¨X±"ºwïŽ=z8ÊÏ?ÿ¼3©iãÆhÑ¢…#h:ꨣüEµL8Œjþëë˜zÅÆ.±ïò&(:Ý>ãìŒ#œµ’u^]ݯ_¿ÖÇ{,úôéãÌžÛµkW„¬©¹ÉÄYN,BZ“s9§Ô¼ys'äÚ 'œS¶Œ}^–q’$^X¸p¡3ûòÐCMâZªj" "z¼¼ÿxYv2_ ŽLÔƒ:(™«©º‰€ˆ@ÊðòþãeÙ){AÔ°„¸êª«P¾|ytéÒÅéŸàìDv²ãoÓ¦MøôÓOqûí·Kl”Pê*LòŸ€—÷/ËÎr©SºîßsÏ=8æ˜c0jÔ¨Ôi˜Z"IN`Í€C4¬T hÒ°ùø6ø ¼ür’WÞ'Õóò>äeÙ>Á«jŠ€¤j6.¸à <qœ‚ý4NYc74†M[±b–-[†?þØqHf_ÂØ±cç̾}ûâ¹çžsòß{ï½ ± £=Õ¨QõêÕC×®]w¤ñãǃ!Ô$6J£?®M5š\Ó~6+¿… Œ:ZÎŽöí}Ƈ>ñÄqÚi§[éb™õÇ`Ö¬Yøê«¯@%×9¸xØa‡¡U«VhРA®³ËàeÙÙó½÷ÞÃO<áüd—Ç«í´_£z’±§L™âÕiT®ˆ€dK€Jî?ü0mîaÙðòþãeÙÙµgñâÅÎÃõŒ3²ËâÉöƒÍêïÈ#tfxr*" Qxýõ×ÁÐÅì8H×äåýÇ˲³»^«V­rÄ%œi¦”~†Ž€›.¿ür´nÝÕªUK?jqZ`ÿÕ“O>‰gŸ}6m9xyÿñ²ìì.ØOfÒ¦M|ñÅÙeIûí¼ÿÓAŸ3Ó-Zäô?§=<"Àà÷ßlØ`³ômš~à³{·[šYÄ› …øÿšNyݽ;ÒËû—egGdܸqزe‹ó Ÿ]mD0“Ðé˜:uÂ3Ï<ƒbÅŠíSÑ çûÖ[o9ýŠüf?ðÿÈ-QÜÔ³gOЕY)% T.E³þµ?„-?}M¹Ö°@ñÓ8øxÆþ›;w®ó¡ gYP|tê©§šÍ¤ùL¦hâÒóÎ;Ïù$º‰^–躆—g“)kÑ(¢Èeúù矃?ZÑ„žË8H " "  'àåýÇ˲b üùçŸñ믿ÂBÑîC):TD@D Q¼¼ÿxYv¢Ú¯rR‡Àk¯½†:¢æÙ³gç꺜:-WKD@ xyÿñ²ìðvh=:œ©ÎA£ßÿüýçdW%Äøþ{`Ð  lY`äÈÌò-â FÎ\,Q€dÆ“6  |öðÒK@ƽ¡ßfaްPˆ¡Ûµ–•€—÷!/ËÎÚm¼#@á~‡ðã?‚!xNÒôû\ӆଳÎr>Ç纒D#8 äu¾W¯^ý•-ðsç7ß|óŠÙlu¤ÈˆÊk Á–‘÷ hK .~°Q£FŽøèôÓO׬» J©½pýõ€µš5[ôí¤àˆ©Y³fѤœ" " "„hSÊ$ÁQ^UID@D@|J€ÎÊ_|1Ê•+çÌ|gh%Ô!Ààœ¸R¦L;”E‰%2wõÕWcÉ’%N8 NòUÊ™Ýh,ŠlŽ´¹B-[æœ_{Ó‡ÀÚµÀ™gÂÂÄ ÀÂÀd¶b£ºu]Q×Ú˜l 6s¤% vaÏe®8©_?ØD|X¸C˜›Cfn–{Å€™ó¡fMࢋÜÉÚÌAÁRÿþÀ°a™ùµ$" " 9عs'¶nÝê<7¾ùÉjL Æj^$‰¼ êï2c7÷ðÃßi\y啸å—_0oÞ<¼ýöÛøä“Oœ¸}Áy—.] ~|ðAXˆ6G|Ä£} 7\¾–“€¹ ;±Œc©íÝøC¥X±PS^d$ ÁQ2^ÕID@D@üK€ý.íÛ·Ç_ýå8[T©RÅ¿QÍE@D@²`H¹†f‹²;ŸÉrì¿ÿþN¨Š’%K‚ï˜íÚµÃí·ßžåXmÈJÀ†,l¬ÂÝ®ÏZ½6Ná D Îz¬¶¤6[n–/‡EæJ• m«E+ĉ'ºG'Ÿº/§5Š’X®E»Åù绎GtH:÷\÷¨âÅeËÓ âî»3ÅFÜûòË®;¿/º¨öì)’Ó©´OD@D E¼ÿþûæœ7Ú wvÄG8š ~¿ëÓàåÛo¿u£Ѵƒã蜈ü¼Œ£R¥J +²Œ=‚©hÙkû$8 ®g\œoORüìØ±ï¾û®#>Z`qÆC NTØñ3vìXbòo ô¢L(5–)8jt/÷vñÇ’"¶â|WàÈÇOUŸ°(xè!Ø pÙe° Ÿ6DÕÈBào‹½Á0:kÌBxâĉ8þøã³äÑxúé§Á£«,6F[¶lq&ùò›ŸMñŒÅlJDX “ʽöS¦¸b£n݀ǃMp =fÚ4`Ì jU oßÐ}ZKmó篼{®¦NÍÚVF*´yõq'º}ù¥ûw×±cf1fNicbYNÌqÓM°Af W/`üøJæ°dÖJJ" " )K€Q£ àL$¢ C”':\Ò°…û/^¢³(_¾®@lèÐĿǘI„#î)ZÔu¸òªÅ¦´ñ®¬¥ç4þK·% •† Y‹/¾˜a_œµmð5åf¯w‡uØM3å3äY|Í¡vã©Ë2³Áûúë¯o.ó³Ç:ûŽ;î8Ç­¨iÓ¦à'ØýÈ×0Tù”"à‰à(˜P{¢oÕª•ó¡í­¾vmîܹشiSpV-§º1Å2¸Aw#&Ù¼9ôˆ€ˆ€Ï PpT½zuuûü:ªú"R×_Ìšüö[f‰6Q 5k6ùÈBd“'gî³Pëk=s=§¥ÿ8{›b#j÷›7wÃCpeÄ kWàŒ3<õË©ŠÚ'"°~øa<ùä“8óÌ3íÿ´ý§VH9•òòÖ[oMÛwHN^}üqw+…ôñ¦Ûn6ovCTÑù3Rb5:Y´RG˜)¶å-¾3Ù˜*V¬pÏûâ‹Àwº(l.WB’Üpš äº[%¤ÐÂvvì¸K–ìN`©*JD@D ¿ ¬_¿ÞM¶Ž?j%:tè`¢ç»ÀðiDc9hèÛoò´×™³üiåÅ|Œ18gÎG|ä7pªo΂£XŽ(Fc’à(g¶Ú+" "ühƒÊð±]+‰€ˆC›}ñ…k“ôÑ®‹ŒØ¯öŒb${Er>1#êÔ»·; Ò¾=0aÌ] °H˜9Ó¹kÑ®­3Ã,”D@’šŸ8ØLËtZ¬óÃå_ͪ¡nݺxá…÷Ĥn„*'" "ñãÇ;Çu£Š< Ó›o7Þ膜ºçžøX  I´n \rIÎåœ~zÎûµ7o PÆw :´2Ô]¨ø1ã/'üÅHû’,¸(4bÈ4ŠÒ”D@D@DÀk >räHÐÞ‰;wÚóIk >ÇÐÖ\IRˆ@ž ŽÂ¹5´˜üôf¹RJˆWp´ÿþû[ }Qøá‡°{÷nÔ©SÇÇ­PÕE@E€–ýŸ~ ‹¡žs‰´Þ?á÷žsêTXˆF I“Ð=±¾ œtÀYÀÙ¿tO² S·³…?ú(ô8­‰€$ 8)kôèÑØ±cGFÅ®¾qãÆ8Ú”Šì7)É %”#ð›©Î§ÚÃÞ ö X¯^½”k_4 úö[€ýÉ÷Þ Ü|s4GdÍcczŽèžîEt²QÊ ƄӮ(šÚ˜¡cF:í4àî»pß.¿¸ï¾ø©të2n\褌jAD@D@HàwÞ1íuøÖrj×®í„Ì=ãŒ3x%ÉCÀº¡•D ñÑòbq8bH5 ЊrDFID@D@|L€îLùø"ªê"' ¯vbó;8å&6 ξüûï@nGûsÏeî?¸ýv˜ ˜1ö¹/x)»PÁy´,"?(0êØ±£3Ë‘¡Xûôéƒ)S¦`ùòå‚ñ7¼ÿþû`HµÃ8_ID@D % =òy™'Hg%ÓÀÂ͸î¯t£zê) V-7Tõ’%Y²ç¸ùŸx¤±/áúr<‰vŠ€ˆ€ˆ€ظq#.ºè"'òÁš5k0lØ0'â“ÄFúóHež9q†ÞêÕ«-&î2ì·ß~ ¹ØyV©R¥Tæ©¶ýG V‡#þoذmÛ¶Cð= Ž| Õˆ‹ÀŠ;°—.ìu×^W1Y*QŠ8÷\ W/Ø33Ìé8åwÖ/#oÈø$ 6m¤'@GÄvíÚÙoÆR ûr ž´iýEâeMúÖª‚" " Ù˜`1qKØ_çγ˒RÛmÎ)ÌäG™Ù,®Ç2q5óHwɆ!l@æ_¸,ÓúšÀxï=€B¥ø lÞ \|1ðöÛ°ÉÅ@ÏžYËâ~æûë/7¯v‰â±Ù³iÓ`!i€Çs?6†ë„^Ëî¸àí ×gCTæ&¼UË" " "ßmfà‹Õ¹Õ,Åùø¬[·Î&!Ž÷·oߣFBµjÕâ;‰ŽÈQpd"¡âtPó T´6ýµråÊ—skÛ»ï¾kjñ'ðÍ7ß833Âóio]¬¾S§NŽ)|¿ÖSƒ@¬‚£… : oÖ¬YjP+D@D@Òš€Gi}ùÕx Øk&OøØHNpzè!€N›ûüóû¡Ó×ùÍC->Í›ýú—°oË>{†ÍPß·²Âf{98cú„ q;Íép¤$"à?ü±ãl´ÙFÛî1 €~‰ü1òÕXD@Ò–ÀâÅ‹±hÑ" vŠ+–ò>û  [ Åòt4bø³H‰ÏÔÏ?ï LøÌ›[>6á:fWfNeüò Àîiº$Y”ÓˆiçNàÀ#îÒÆÿÌ›çŠøNF¡E\á.›sŒW_ȳkW÷]-€6œdcJÿ†( «Z5ô¨t¯O¸³ìË6¢µ`põÕ¡"·Ð£µ&" "  ïúVØlÂÀ‡¢mÛ¶YxÐ_3>\ÿ‡ŽÙ$š¯Ð½RÙÒæ”$QpT£F ,ØßZÜÚ܉Šü×òìÛϲO'NÄý÷ß釙MZbþ•üÌ6Y:ó,ÿlHù{3Gœ˜þ€Ÿ]«‚£¦M›f—EÛE@D@DÀ7(8bgqåÊ•}SgUTü@À" 9ƒ¬+g·† Žh³o«Q¥Bö&Ï`DN…sÆìe—ÇŸS®ø÷qÖ÷¾ÌüŽÿÌ:RD ‘ž}öY'lN!û!zå•WpÎ9ç$²x•%" "à#ãÇwj›áÔ>ù8ã wRÀ¤I9?‹s‚Á½÷º!°N;-÷ úè£@›6ÀÉ'çž7R:“2,2Ïyå•À¡‡º¹¾ú xí5W cº0GDÃ|éžÌÐÁñÚ´h(   /¼ðpþù‘)r@'RÔ©9ON[9à'ìë,—)SÆÑ8ð;øS·n]srÜ?¸-‹@ʬ]»¶=žã*ûOÅÜL>·ÛÔÚiôµŒ2½ÿþûbàZ›¶ô¶äÍIlt€ùfò*<Ñ2väÈ‘èÛ·oø.­ûœ-oÄ 9¶ˆ?ð7gx*‰€ˆ€ˆ€Ÿ üij‡µk×:ácýÜÕ]òŠC)|ñ…ÛAmZ='´·QpD[|΀ $ð“]bGw¼‰B&3ÁM7EW‚9(ƒ!Ô† qÅMÑ¥\" éL`ùòåŽØˆƒÊ¯¿þºMÒ1Û2%´%0uêT'LÇ0ª6R8}ðû ÏéÍo¾ œpBî­VÍ(™6×y'8å~dü9(ˆ:ûlà7ÜCvÝx£+4:é$X¿uüeûùÈ[oF‚ ¥aáaܖМ‘ŽU6,ä|, n¾¸ï¾œ«¼ä@G£€«Q8¼¬‚ÊHB¿ÿþ»9 žŒ¯h[h©J•*&"îàˆ½ùn~´©e) /œªä+ÉuêÔ¹ÔjžØè/ “¶"R˨|ˆòÿ°Äÿ° @ýúõQ¾|ylß¾Ýbå.pò®_¿>#7…t:*N)¼RÊÈmCpC׬Yc6ª¿Ø ½(‰€ˆ€ˆ€Ï ¬Zµ {÷îµÙzqxƒû¼íª¾DC௿3;µÁv·#Ÿâ¢àT±"Ìõæ:358˺a ±S§œÏÀ:·k³[6ºtÉ9¿öŠ€ˆ 0”Óˆ#$6rHèHo §FÇ÷‹.º(eAØp€êŒæEr)Í®ñ×\ãº!=ù¤+òÏÇg%VôÜsnø4ÚÜØ´O|t¡Øˆ¡ê(È $^ÏæÍÝߣ’-Å»#Ùj¯úˆ€ˆ€$ŠÀßÿmˆç:b#º _wÝu(W®\¢ŠW9" ÿ°èºNÚÏE·ý·ü5ßE­mЬÄwß}weðŽÀ2iV¼EÿÛȰXœ¡Ñ²eKGlÄÍŒqx¶Màöjœ¢ð_úÃ|._£?©RÚX¸p¡ÓöfÍš¥-5\D@D u0œ“G©sMÕ’Ä […à@g!,] ?Œœ>,V:Ìõ4øˆ¼]æ'Š 2àÀ#Ÿ›¯>§œìÜ ›4\}ä|Ú*" á>´QWºûÒÅÂú_Âwk]D@D ÍL˜0Ái1Âü¾þÚ$Àçàhó]|1ìžÌ™P¸k*`#={º!ÕÎ+ÌPØñ$?žÇéØz›MÝæ{ƒ_‹èX4r$ðóÏÙ·¢V-×eJfÙ3Òä$0hÐ <óÌ3hß¾=Fœ•T­D E8‚#ëìêܽo³,l ÷De`p:ÒüF[äòQ¯^½}œÑñ§ +¥2ÑôêÏlej¡Í¤K°êÖ­ºCk" " "àCùð¢©Ê1X¼8ôP W¯¬‡Q8TªpÚi® '8Ç?ý|ðп¿Š,x2,_r‰Û.†O¯¼’âí·aî­á9´." Ù„SKå°9Ù·^{D@D@‚ ì1»žI“&¡fÍšN„€à}ɸ œxbô¥ìJ¬PÁ­TÒ˜©hQàñÇ]wRwKÞÿËÐÊÖ­íªòþìñŸqÚ4àòËÝÐÕŒÿâ‹@«Vn?¾@à°Ã€Ûo¿|)" " ùM`¶ R_}õÕ0ýƒ‰ig¢X±bù]%_Rž@™4$3™ä]³ù^“¹%û¥ ” ß.$ ßXçôà´aÆàU-û˜g®3U¬è~çô/e7K¤fÍšå”MûD@D@DÀ7xo«S§Žo꫊Š@´Ø¡~©MKøþ{˜±;Ã9üØ;î¦Ln¾™a›Ã÷ús³²{ôªUsg2K+àÏë¨Z‹@~˜5k¶Ú¨íÅŒ-£$" "Öþ4å~¿~ý,„ï¸âŠ+’–Å{ïȯ¾ tí Ðå”b:Òåˆb•ì{â €QãEôšk\qϸq¡gLDÙ¡%F¿fsg1}:ðä“Ñ“ß9íqÄq©*_`¨èÚµÝIœ<ÌP×wÝ冖æû…eJ" " "à7‹-BçÎQ²dI¼ùæ›(Ï›ž’ˆ€ç ™à¨zØY–‡­g»jÿqCþ§V®\Õ«‡ùpZƧ7¯jÙǶo‡¹œ’[Z¸p¡“¥)}y•D@D@DÀç(¢ýÉ”·gF²~ñyÛT}`Ç3mö):êÙ3õyp…íä` Mr šçÛÔ'£Š€ìÝ»7*§Þçž{ÎÉו#¶J" " iMà¾ûîƒE ¿+F3[3ŸhÐÝôé§Ýð[jprqJù“O€"E{B¿ -Q©eK7„ëBQ Ž’!ÑÈO‰¢1†¿¦[TØÐ lX¸îF«WÃÆxüÔ2ÕUD@D Ð%ò.{ à7'övîÜiÏ E­ï-MN§? µ5ß Ðá¨Fp-ÌáhEðzNË+V¬(¼¿E‹Á«9.W°ÞzÎä¤ü1°¨oŸ í*ciGcîðùçŸ;­•ÑÏ/ºª/" "à »“Ž ú'‰üðCäÙ·S§´k0Ov‰3`é^DwŸð™ÅÙã÷íÿ º¡ (>’ØÈïWTõÄØn3l^zé%s¸¥K—ÃÊ3Txvé·ß~slÜ[Úhé¡´…PH[«V­Â=÷܃  W¯^IÍÎ=f€Ë. ­æI'¹ï_~ ôéºÏË5‹Œ‚-[>—+ÅG€‚¢¯¿ê×ÏþxºFQŒÄÉÄJ" " "Œ±¸¦=ö˜9 NÇ‹ãJ‘Q¥J•,”뉸袋ðÚk¯á¸ãŽKƪ«N"² YËBôê6C/*ÁQ¹r劯_¿¾t0™Æ¯æº|ˆæŒ&*•R‡@Á‚ѵ…G|°K3º#”KD@D@’—€GÉ{mÒ±fÿæìU{Çë¯fÄaa€B|ø/Ùã¸ãÞÃý|~cÈ„ðÄÈÇ6®n“Ü0 ž#5×O=ÕÕMŽù®!5éªU"à/›7oÆŒ3œÍyóæáplò–# b¸´±cÇZx‹/!M5e'ó+œZ8Ú$" iFàúë¯wî ¼oì¿ÿþIÝú2e~"%NDXa#;fî¥Xǘ7s["—Víä“a®P‰,5qe™Ù±#†âDŽdJáï2åÊ%SíTt$À ;ß|ó >úè#ç󥩘xà´nÝ:*3Í~¡Ò6X‡eÁh££*9µ2}û-P·nÎ"⯾>ø ŸÌQG¥VûÕš¼%Àáó¢ÉLÖi¶+s-û%‹xœý(„hÝ›0xq ißBþK%J”,ê;MüóÏ?ÿ{±£:M“&«™" " )NÀÜÊá(Å/t’7/úÀÆ1œp`œjèÑ#«p†~øb9gP»vÖ†qà KÀÆÚñÊ+‘ód=*µ¶Hl”Z×S­hìÚµ ~ø¡‰6ç:¾·2|‡O9å`íˆ:˜CÜAhÔ¨úöíë„S­Q£F–âŸ}öYÇÒ½S§NYöiƒˆ€ˆ@úxùå—1{öl\~ùå¾ï åûC«§»ïžx0].?6&Ž7Þþø([¸í6€áªU˹‚‘:¡ùBÌP¹ì¬¾õÖÐÌ9—¦½" "à?kÖ¬ÁóÏ?ïŒ(6¢+SYû1íܹ³…žl‡¶mÛZ‡õØ¥‰'¢U«VÎò»ï¾k!H2çe­[·Î:ßsŽ×$« hZ4#Àpœ ¡F—÷#F$eëm Чðû°Ãb«"gÇî jÕŠíØTÉMÁÕ &OŠ÷¶u ÿüóÏÀG„žgÙ2˜ëƒ+ÐJr#­ÐŠkMD@D % l±˜¨'›M!CË-ZM›6uBž1ìÙ±Çë„+ë­·œÐhÒ^=‡Dw#&¾Ÿû!­\ œ{®ûlÀ®öÓ>þ8ÌÑ)±ý¬—^ s}î¿ßu°çÒoÆî½×]æÅ>_úÀœ¾+Lzî9×õžÎ÷Öý!C¼×AË©E ÍÒ[Ü!f®EQ)l0íô`G}´3À¼-§ev¼íÞ½;#‹G(|¿ðôÓö'‘cb85&Þ\”D@D@D ,_¾UªTÁés*.Z’·ÁÜ…í…&Òš7wßW™šý~ÈÜÂqîcŽqgÎð¥q_fÌXÄð¹î$›fpÏ=™çÐ’ˆ€¤Ú¹Ÿd?vì-V¬Z¶l‰S-®"?GydŽ}Ì{ƒM=z´ó¹ùæ›3ðL1ûÚÅ_tÑEÛ´ " "~l3È4 '!k" üõ—+ta¨¬Ê•ã+™ïVEppªT©ØË ÀÆÆñÔS07ÀØO…#ªzÁ×UÖÌ W×^ªWO|ëÞ}×u% -ßýèXœÌHË —¼MË" " yOÀ"…™3.,·ûaÿfÒ)ýmtû¥Øèá‡6§ŸkP˜¶…A‰ûçÏŸo(ß0—õ.A{².RpTÄ:;O;í´¬;óhËÒ¥®À˜“7/¾6ùį¿\r `ºsGôîë6Ý…(B¢ˆ¤}M0ñÙƒksÑq‘΋D‡‹ Y‡à¾^2/Zä>¾ô`‘áѵ+0hPzºÝïë5IÇãmHß7Ü„DG¯GZ®Y³fyë4 ‘“œp ‘²f»íý÷ßÙW-·i×!¹µ’¬ÂÜì+¶ÜêøùçŸ;Yäp”)íð† ¥àèˆðé…~¨¼ê˜´F8K媫›ì“%ñå–¶¼´Áýøcà÷ßÝo³/b#žˆ"|q~á P¡,§ÖH ßÿ½ÓYI÷ :щ™!on5k·Æ»…Î…¹¥{¬§Žî†·›-݉áÔÊ”)ƒ³Î:+°Iß" " iF`‰Y‘R”ÊüÝ»wOxë):iÒæÑíÍ ©ÁA%‹sâ€'A°éœ(º¢³Ý8¸×¬@qо&º¼óŽ;@ÉpuÝ 4³sÎÊZz`°1ëmð‚ÀŽ0Q;i/¸| yé:cfºàýšŽ3=œ#õ—)0¢ë/'æÜd±ÄÂÅF$p®©ohŒ2•*—ÒMWa†9/® Éá¸D#û`ª¬fM˜¹JèÞlÈ }{WD!0…Eì§íÓÇ yzíµno葱¯Q$ÄmŒîÎI£á‰ý¹6‡*KŠô¬Àç8H}ú)¬Ä1Õ¯°®ÿ@g)GD @ Ð¶mÛVÒÎ5¬3í" 6|õêÕ™½dÿ}[žóìC±RFŠEpÄ~Ó§OÏ8– tPò?Z¹2U¨à~çô/Ž*V¬hƒY6š¥$" " >'°Òø &X¬VNÀy€1IJI'>þøã1kÖ,sxß•mä†]ûˬó;œûhÙ‡;i’”‚ã@¢)'ošY“hÚ4€îôÁ‰"´Ç Þâ.³˜eG›x.†?c¢x#îª>¾žªºˆ€ˆ@ô¾æFKEÏ,rrv ;V¯vC¤ñ;ðaçC!ð•#Æô$¾ä)‰€ˆ€$žÀÖ­[qºÙÄÙd+Œ?>n±Q fì ½å–[œŽTv¬Z_‹³ëbö6*‰€ˆ€¤%Þ_>6ÅH/³¡aˆÎD':ßØØœ3»žsyÍ îdQD•H€æ†Ÿ|´iã>S{|A`ô%‡ópÀ¡±ùþÈT©’"Å ²œ0mM›ÂÜ!Ü}úWD@D ÿ Ð)†¯~¹…Çb_'6oîÞè"ibaþ·(15xÝâ‰õ5uûÉ9¹Çt9̰jŒŒD·áŽ)OÈšX&SÛ¶m³î܇-ì“å}7’¨†×É4ãŽx8ø9‹Ž×_Ÿõ¤ñþÏH@cƸ}½YsEÞB¡2„èb_­Zä<Á[)ncß2ó{á2i]vM¶)»Äpqá»N| ò»É®mOf¦E…ü?·Ùö&$:€ëöÝÞìÀçÛ,Œ‹m¶þznc*[¶ìA63o–í¯ånqÿå?÷‡&‰2dHðá¸úê«a¢§mZñ'hŽV¬Xá(Q%4óçuV­E@D@² ‹“Bªee“î[ø²Èwå7ß %ÁßÕ«»³šÐÁb£ÐÜZHZ±s–%ïÝuëÖ-!E6Ìf2¾A“æ ëu3÷h<.!e«øÝb÷ïßßqv:t¨'•§ØÈŒœ°Z×]çÉ)Tè>¨W˜?æ€è:q‚É9çä\ ç8HIEFÑ 8æ\¢öŠ€ˆ€xIà°ÃîÌ"ºˆtN†âzñEØ»¨ëŠD1K*öÒl¢«Å[et¥™£«­ŸrI «F6êEíÝ»×yצ€;‘“(ÖáäOº QÅHmæ‘â|ØoËî~†%£a%Åb¹%Þ·¿ü0Ÿ–˜Ãï•-ë ›è’Hg,†QÍ.á ØèŠÕUÙåJÌöpç$ºux¢ëîÄ¿ßU«BÏC7~Š´Èó„\át£FQ)¥ 8WØfôýP§NûóÄ @kMTt²-¯4áÑ-±õÚ¶Þܾí¿Xfb¼ÅK黚KÚ¼y³Å0žìØŒÓÝ&èŽtùå—VõísÑ Žäáó ­ê‹€ˆ€d!À{ãM×c¯¢’üG€³dìÙÑæ¶];7®6ck›c° ý…JD@D / üi*Ð:XØ™Ï0pà@Ç•(Qç/j#‰O?ý´#2¢ÃQ ŒN¢ÊW9" " þ!ÀÐ![¶lqúÂ)Bõ"Ñ ‡³íù¾OŠ5tG<çH÷c8ð8ož+:¢sÑÛo»ËÙqá §EŸQðXnó”ÚœÜt“z“¦=ÁÎ9>jvĪR Àg|ïfˆ´êœiE:Ì”[ǘÍ;]Œ6Úƒàô©©³~þùg×$F]Cgž=\«H7›—ºGÎ<Ó½^±t÷Ç*6b;é„Èû?DÏ?ŸUl4j”+~b”!‹ ê×<˜RÞ,SPµ{·[GŠ£ÂÓ!gÌpŸ{Þ{9ªY(ØáYµžB2$e6Ãï> mÖÉE í³å"¶|Œ}ØþM±PŽ>°àÑóMÆo.IX´h‚…Fì},¨qøG`Ÿ¾ýG 8âZNI‚£œèhŸˆ€ˆ€ ðÞF'ƒb±[öcCUç˜ð=˜3¯¼²G£˜à)³ˆ€$˜Àž={,LÉùN?ÅõæNG¢D'v’0À,õïjrV¢Ï¯òD@D@òŸÄFŽi3ÓÇ%—\âI…èlÄ÷ 1ìV¬éóÏa¡EÝÁ­l"—ÄZ¤ògC ¶Mãž;ö|4nš‰T8Ȩ‰(¡\´&" ÉJÀÌ{°|9,$wü5¼ñF`éR÷|ÛmÝjüœ¶YÌ-NèaÙ—^z k×®u&âœ@{›ÒyçjæÌ™“%l’˜(fJDb84ºMQ´=qbò8MµjðžXWÃë„}ãs_Ë–nÈ6 •ó:lv5ÿû_ög-_Þíg_8…I|š<ù7¬YcJ%¥”%!8Ú°aÃæ6Ôì€xÐF×DÓâöíÛ/ëÝ»wýš{4c-¾Ì©Ù¤6æz&åJ)C 8ªP!ç&qP–1;ëÖ­›sFí ¨úö¤Íg%&pë­°ÐÁ€MpV'r0-‹€ˆ@>àlÈ×^{Íü=z´g5`èë+‰Ê:Þ³J¨`|#0|øp›%¿wÝu—ÓÿéEE(6â |› I sÁÐÜÂ~Øx,ê›õ͆®4°)Þ¯¾Z8ÝÌt t.PÈ{ÿþë:ÛP¸‘›Óƒ÷\v@ÑÑÑG»æñÖxÌ÷~ÍþB 8Ú¶·¤Ìãø ÀPž#Sô±¯‰v(¢ÞiÁ>ãÐɈ®CŸ|ò‰=w,‡EJrNG×_>ÿ\FP1¦N:9‚£iÓ¦EU°çfÍšÅXjäìö¨æ<+]{mäýɶÕt\N˜7ö1û)1œ,ÿ¶ëÕû={®õSÕU× dŽxÜúõëmn®µ0j³Ltô„-g7?âo‹—xÛˆ#šXž#ìsb6ƱVJ-Ñé.<¦cx+)8ªeK‹)¾Kë" " "à;QttD$QßµFN$v,?ôP"KTY" " ñ¸ãŽ;læâDGÌoë󈧘¨)Q¢DÔy•QD@D u¬[·cÇŽµPMmÖ¼M›÷(MêNh°±¹t챿ÿÞí£ ÙùßÊ£ï¾ tï0‡RÞ°h{8ã à‹/lpÅFW8Nëñ£IÞ7Rgxá kW˜.0eJ΢#ÓÑ`ñbÀ^-Íå~ßÇqÔW^qû é8oâýƒ!«ŽËt:0>üpßG=óÌ3æô¢6§ºU·xd\pZ´hcí!¤±YùíOë¾8ËjÒ¤‰3IˆýìrÖ¬YƒeË–¡[·n1¿ÇïÝ X´sÇi§J•ÌJz¨‰!|"6b­ã Ó–ÙZ-‰€÷BGÓ}÷Ýw¯Ûò!uêÔ©aªD}eßU (°ôŸþùÄ>_Øp3ÂÂäÀ1Ñ~yä‘èÛ·¯óÒí1Ê猙›»ão®ZµÊfp(^£®¬j*" "¾ô05 ºDID@D@D ©Œ7ΙeÉpg´x/T(bWHRÕY•ð'!C†àÏ?ÿÄ=÷ÜãYžâuë½§¸ˆfÁ‰á+è^ôüó® Cð>.3lC¹ÐÙÈÃ*†ŸVëa8—NfŠˆAƒÂvjUD@D ϘVÓ§»áµ,*Ž|êE‹ºâ04&G‰Ht!²HÜq¥„…-žz 6ÞêÁf| ûR¬‰aÐ&Ožì|8±–‰k/¼ðBtÐAæ®s`ȧ´Yím'*Ÿ+¥ ÊÒåˆ!Êßyç ýê*±â §FV—.EGÖ`ŽLA'Ò¢ˆ@B äØËf?*«ílü˜Î2öTµjU‹#ØÒÜnJ9pŒ×Xc_eŸ±WCGä!:å&8¢½­ø4(›‡F§ð”û˜äpä)æ¤.œ/±ìÔçLÕ^½€ö퓺ºªœˆ€¤ W-~Éõ×_sr¶ÁÙ×NÒ´i¼*" "§V¬XI“&á”SNÁ©§žêÙ¹ „9õ=z=æÎäßûÜs÷›æÍÊ– Ï¡õ¼"P¼8ðþû0÷ÿ¼:£Î#" "‰Ýåx´ál{oŒ”0'”…¢v›7çÈùòb«išÑ¯ðÈ#À?ÿ+·Ýæ êÔɾf$â„>Ûd®?Ù@.¿Ÿ•+W:¡ÑaËzYÇæ%—\‚£Ž:*û=ÚsžÅŠ¥àhªY9 Žª-»g+º:=ù$pùå¡ÏFÕª;ºnOõêyTa+"àÈQp´¯ŒzØ ?JéC€‚£Frno`PV‚£œ9i¯ˆ€ˆ€Ðᨠõúš;¤*­šÆE€³bÎ: ¸øbØËwfœüÃQÜO}½G™l´$" ùEàCó’çŒÌ²6¢:{öl”+W.¿ª¢óŠ€ˆ€¤Úàß?žº#:9€)•,é:pP48q‚Äe—¹!9æÏÏꌜWËyC@b£¼á¬³ˆ€ˆ@nx_1"û\t=¢¹=Cªå6þ™})¹ï¡pæŠ+Üûu$ÝòW_]ðû¸ã\¡Q›60ßìËf™ÜϰgñDJ%íá¡‹Y]z饎È'?Ù·Þ°aCpâCÔþñÇ2î=´nÝ:âä¡9s€›o¾ýع¸õÖÌÒé)›&gfÒ’ˆ@B„½z$¤L’¦œêÚÜŽ$8JÓ?5[D@R˜ïmtN(¢Ã¾ÊnÓèbÄ—Ùï¾ mjÿþîÌ"> 1nº’ˆ€ˆ@þøÖzÛµkgƒ²ûcÖ¬Yr[ÎßË¡³‹€ˆ@ÊXd±V¦™ª§C‡hÞ¼y¾¶7\l4s&L€ëöÙÒÙˆ.J" " "Ž6ov'nÝ]놋b¤fÍ\OtGÅ—kµÅzã Ø{,ðÖ[™e˜ñFŽtë`dá]ò8Ù1'±î…ÞpÄF­ZµÂ˜1cðÊ+¯€“sVY,¶¦ÒÙ¶m›åymL½”Ÿb£@‹VíçŸÆ‚ ŒÃ[æ0õ—ónØÏo†‘³G.œq`Ñà0lXöUÁÇiYDÀ9è½9¡JM]%J¼Yóæ—Sâ ,oZ˜U¿øÓ&|Aë˜ÝS¿7PõÏ @÷"¾ÀrÖ0æEJ… GÚªm" " yIà‡~À™gž‰;vX‡íhÒ¤I^ž^çHC·ß~;ö³¸,wÑþ ‰'Ktî ”.í†Q«U+‰*§ªˆ€ˆ€ˆ@ؽ8çàã¶móÏÏþäwß sÔÆsE= ¥–“¸'û’¢ßCã| ƒO; ?ÞÓðhÓá–[`Îúnø·¦M£+“ý˜6‹+¯ÜƒR¥JYè¸ç,›Å`KòİjC† Á£~a}îÕ­¶£lò祘1øå`Ë`ýzàï¿éÜä Â*WNòF©z"â åÒ¾ýªV­Z­pá ,_ {iZ·gÏž¯W¯^mÚAü“˱Úfë4‡z Žh‹gWiFHÍHEtP m¾B…&÷Õe¼u›°ƒòåã¯ç”)ÀŠÀ An‡}ü%éHDØm½Ç3ÍÂaòäÉNø4ë»p–Oco­’ˆ€ˆ€xH€¡>8ÿ‹¹|ÄGxx&€áÐxŠhÞk.tV9`:w.P¯ž§USá" " "´h”Àpeõë—³Øhûv€£€»ùý÷‡ž7M;ê(à£BÝO8`Ÿ$}Š‹¾7Ü`RQKL´s4î¼ó‘lÅFµ,¦r£¯A|9ÙÇ^·n]´IDœB,š#³hé(SvÍ Ÿvâ‰ñCG‰€$–@DÁQ5Kf;þ˜ ŒN¶ÓÙ+IfúϙƂE`æòåË ÖÓ›J&-åJ€À&Xù瞛k^e?„ õºcÙ,’µŽ‹»vÄ?þè¾Òn׌/À—ÒhõϦ)ËÕÝ(YÛ¯z‰€ˆ@ªø×zi³þì³Ïâå—_Æoç»`Á‚8ýôÓqÝu×áì³ÏNÕ¦«]" " yD€÷šmt’áG~úé'TªT ‡rHȇîF á9tèPOkÅIìRå 'LsKK'ðâ‹î{Pnùµ_D@D@RoÖ¬V®tCoñ{ÉàÝw‹Ö…áÃsnåA¹BÝ®]]áOïÞ9çOô^:…'†F5}öÙg6{†…z=½{ÏÌ8œâ>G ?›6¹}¤·ÞêöŸÒ\"¿]Žî¾›à'ãæ›/Ľ÷öA‘"ù]+_D ;YGæ<ÓÓ2?hŸâÙdB$þ·>ÏD#ÿôìÙW]u8à€ì²k»d D -ˆ€ˆ€¤eË–9-‘ÃQr^P¾D_|±Ysš`¨KØÀ4ðÀîgÈ`ðàèêÍ™DÿûŸ›ß\ˆ•D@D@ò™ÀÆѪU+ØD(§& ›Fg‰ ­'¶B… ù\;^D@DÀÏöZ ’-~ ŬýÈ™ ¹¤k¯½Õ«WÏ%×¾í~ûm˜¸ÖESRß¾?J" " "¶nuC¥™ÎÆé n3Å* £f†¸5xOäå*U€>ˆ¼Ï[éøËñûý÷ÿO=5 û¨÷¨Q®øŠÃútMlÞxóM×AÉŒ…œðm—^ -8"ï¿;™2ìnƵÃbtíú¸ÄFy tFˆ‰@ˆàÈÄFÙѽ¢-Á‡;v,Ö®]‹‘#GF{˜ò¥(Âñ¥—–ÙÅ2 ¸@hP6EÿÔ,HC¼·1LhíÚµÓ°õÉÝä#\›d†|¥ð¨E €Êœ½cÌù"ºúÜ(4êõ“rte+—ˆ€ˆ@ìþ¶)«;wvÄF·Ür ºuë†úõëÇ^Ž ™…P_Sè¼h–@›8Ýßßóú÷ïδ?ܬ…(xݰaCÈgçΪäΠ’¼Ydˆ€ZU”D@D@D@Âpb!{Î:Ëuö«U ¨YàwåÊ@a¤ðêC=dýŸK0hÐ çù%¸©¶ËÑIÉ ‚ÄǞѣqã`&#ÀwÀ\ƒºÄsL¨HkÕ*€"è+¯ŒÞ9>øü‘–-Ì0ÒÄÞ¦Ž²æZvávíÚ…¦M›F:DÛD@’ˆ@†àÈÄFGšEìæ^sõfÍš…–-[ZüH ©”¶8¨7~<@qéÒ‘1Hp™‹¶Š€ˆ€ø—ŽWšag•’ƒ­“¯¾˜8Ñí`˜i®ÁU«ºuã£nãÆî'¼¶ë׌>ƒç¹çܸíC†%K†¥u¼&ÐÛ<íé<Áïh[§$" "  0gÎŒ²iÿuïÞÝyä‘!%רQüäGºà€%HœÅäÖæ~ý€òåsË™ÚûW¯^!Ö‰Éþj†} O4O+º¡æ &L€™Œ¸.ït†ÿýwW8懀k®ºõ…BÅH<±|3ôëW¸“D.„9»G¿þúëàd£xt ±œ_yE@ö@ "µÿ´ÿiÝ­&@úÌ>ÍɨµÍÔ(kÿ±)JºÈ>Ó‚Žs£:{Ùðã´ž:,Œ¹9Ÿ~º+6jÓ6 )6Ê©–?ÿ œpо=löLfÎ`w£›oÎÜ®%ü!ðœ©@yägÒÓ}÷Ý—?•ÐYE@D@R’À§Ÿ~ê´ë¥—^°aÃ.6JÉF«Q" " "„~ù*ÛuöãØc4éC$6"§kL Dg Çg(²"Ñ ËÈsàÀ7+WÓL @£‰ð9¶t<2ÃaØã’㈔qp ,‹Nó kžènD‹ 2ÅFÌCÁÔŒù¦$"ôœ©ø5kÖ¤^ІXBÒ;&0jcƒh»ƒ¶n±å¥ö™bVf½ (ð -;–H´ŽiÓǯætr¥´$ÀxŸŒï™S¢àH.9Ò>?à}Í„ØzùI¢‹öùçî *_Žií,(:Q dтѮ`“›«ågŸu_²!AîFIt¡U´$°téRôìÙÓìð+;án Fû#Ÿ–´ÔhX PpT¬X1½ßÅ NùE@D@D Á}ؼÙ-ôüó¹s³ _|Ê”(nÊ”)Ö§9ÇÂ]‰“O>9î6ñUûÜs#NQÒäÉ { o9O`«u›[X7à®»`â§È“B{ôzõ貤$"àOŽàÈœ…UéÖ­[;üòË/Áb£,+W®yÑEݸpáÂj¶-°¨ï4$@Û»œRÀ¢3¥¯J" " "*4/âo¿;v‡šYº}ù¥J-skîK µ6f ̉æÄèŠöìÍlvgÙÜtSîe(‡ˆ€ˆ€w¶mÛfžçbý8O³é‘å镯$" "  "À‰$ÖÏ£>Zá²ÄTň€ˆ€ˆ@<ÌPÕ¬ œu–»Ìpi‘¢iÇr-žº$ã1tÛÿý÷±aÃlܸ1äóƒÅ;ã»òZy˜(êß?çð:^z©ë”Ô¬ðÚk@¥JY©U+ë6mð€à¨^pµ÷îÝ;ÎÄFÛƒ·EZ¶XÖßJp‰Œ¶E"ðí·ßÂþ¶v&mð%€àHö®y{ù>úȵô}óM kW7|Zp 6 ^‹myÔ¨Ìü ­væ™îì›%2·kID@D o pØ&g:1~øášìRs joâªIÙMa4]¦(Û¹VGw¹S'?_Õ]D Z‡£àŸâ¿~þùçÑpÈ!‡€¡²‰!³”Ò€™[aút m[ nÝÈíç ²ˆö¬¥€œ‘i«ˆ€ˆ€¯üþûïX·nÌñÑWõöKe†Ù^ìÞZëøQHm³gÏÆùçŸïLjš6mšó>™Ú-VëD@D@ò‹Àg6zY±bET©R%¿ªñ¼6öˆÍ›k®‰¸[E@D@D -0¤è½÷·Þêºè¼ððððÐÛ@ãÆþAð÷ßãÿû8^Jç|~/Y²Ä hEåÊ•­?ôB £z’‰¬ZûbLµQ#€×„‚0 Ä,úŽ:*Ð"}‹€¤:€à(¸¯ä¶L‰’Ð}€7z»æ(8ªg^‡é¨$" " >'ÀB¦#èå«”PDK‹cž{Îÿ³” G…‰€ˆ@š˜3g:v숃,¾å¼yó’n8M.ƒš)" iA`·ÍpXjqYÚ´i“°öZ¬\é‚îK÷¹ém$‡€„]$" "¤Ö¯wÇ.¹‚½{»!FÏ>;s³f™ËɼôÌ3ÏàþûïwÄFR¡B…P»vm'|8FüT¯^=°ÛWßfÀ„_uÝ4QÔW—N•}&Ip´Ï…ª€ô#ÀXœL6(bÚizk×®uT¹3h£ˆ€ˆ€øŒg¡05 ·½RB Üx£§ý‘G$6J(X&" >!@Ñ9çœcnv:b#‰{}ráTMð)E‹ƒÍ›7OX ̤_ìÎö7³¾¸#©¼ò P§аa\Eè ð Þ7׬V¬€¹ÛF®ö„ ‘·'óV†K»îºëPØ”Tgu–3y•ýÉ|Ï¥I·§J²ùBJ" iH@‚£4¼è^49 8ªP!réßXOÆÕ ld>Ú*" "à?‡#ÝÛ{í8ƒwþ| Gàè£[¶JH~ï¾û.ÚÛÔÈ¢E‹âí·ßF#z³+‰€ˆ€ˆ€‡>ýôS§ôD Ž.t+\ª@w¢k¯……E‰­ lØôïÛqÊ-" " ~#`‘MñÞ{Àå—g/6ò[›õ0`vìØ™3g¢mÛ¶Íú”! ÁQÊ\ÊümHn‚# ÊæïõÑÙE@D@O€GÅ‹GÕªU_xš–¸k@{dvÊß}wšBP³E@D ,X°Àé€å OŠŽ:ê¨4¦¡¦‹€ˆ€ä Ž (€¦M›&ì”ýT® Ô­ ̘üþ{ì‚£©SÝêœw^ª¥‚D@D@D ) ,YpЧORV/îJÑEqÒ¤I8í´Ó$6Š›¢Hv’½‚ªŸ?lÚ³ýJ—Ž\_ Ž"sÑVÿ཭~ýúØo¿ýüÛˆ$«ù}÷ÁB°C‡åÊ%YåTO |ðÁ8ûì³Q¨P!¼õÖ[ær'›;O«p ~øá(Q¢Dƶ}]3øá Z5€!ÕæÎlÌ1¦ÄpjÕ«MšÄt˜2‹€ˆ€ˆ€ïÐéÜ"Y_«ïªžc…{õêåô?ôÐC9æÓNð3 Žü|õ’¨î›7åËg_!º@пFÙgÒð ­[·b“©mk[)6ß}|ûmÖc(4ºÿ~S7Ü@ÖÚ"" "ŠöìÙƒ{ï½×™ñIïìÙ³qÌ1ǤbSÕ&$$°Ù:5׬YƒD†S 4307å¶ÛÜ-œ`mbH6¾#1›’ˆ€ˆ€¤’%S«•Ó¦M]|{˜šJ}È©umÕP…òÐZœ~ý8øàì¦ g ÑžXID@D@üN€BZ¦ ø½)ž×ß& ÃÆ’ôï¿@—.°Î|ÀÞ¹CÒ-· ©6jÌÝ"d—VD@D@R”ÀóÍçoÿþýÍÁ¡:Þyç´hÑ"E[«f‰€ˆ€$#º1y)vmØhÓ`ˆ´•+££x_’à(:^Ê%" " ÉDàÏ?ÿ´ðp}PÒTTwÞyg2UMu„ú#áHÓ³ÀmÛ`7ÎÈmß¾};Ö­[§AÙÈx´UD@DÀ‡¡B5;%ç‹·t)в%pÙen>Î𥠨X1 sgà›oÜíóæ pÞy@«V9—©½" " þ'ÀÎ×¢iÓ¦Xj7‹Ûo¿‹/V5ÿ_Zµ@D@|Gà³Ï>sêì…ÃQ0 ºíÝ <ð@ðÖì—ßx¨\Ù¬‘}.íÿ0óxL™âßúçTó‡~ßÿ=î¸ã”+W.§¬Ú'" ¾'eþø¿ÿþ»:uþʹ}cÇŽ­±~ýúL´?'ÞuÇŽCÊÑŠ¿üöPªTä:eå™¶Š€ˆ€ø€Žr¿f;v¸¢"vªß|sfþ“N-؈ËÎŽô¶mÌ̧%Ô$ðñÇ£[·n^ó[4iÒ&L@ãÆS³±j•ˆ€ˆ@Ò ÃQ1›Ñ6D J5kW^™Y ߃hâ7i0t(P¡Bæ¾HKv»tÜaÙ"åÑ6ð+ŠN9øßÿ€#¤‹¼_[’µÞ ×:|øpÔªU 7ÜpCÖ Ú"" )F ‹àh¿ýö+bm|:švR¡žø#O’à(jÉqÌîÝ€MPÍÖáH‚£ä¸Nª…ˆ€ˆ@âðÞVÊ”¶‡zhâ M±’®ºÊí4àãb³f¡;äXüòÌmuë3gf®kID@D 5 Lœ8Ñ~ÿ{ páÂÿgï<À¤¨²6ü‘³ ˆ "A² ( b@1gE0£(FÌ袻®ñG]®ŠYAEAL¨+fÑ5bQPP’Éñ¿§Êšéîé™é8Óá=ÏSÓnÝðÖÌÜ®{ÏýŽn¹å 2Ä…Ñ,2,‘›§U€ qÜÂ[™ÂQ·nÝT©R¥”Ôoýz_ÅèÐCÃŽ,ó¡C¥Þ½}Õ×Ò†Ðk×–sÈMI•È€ Qg£~î½7·œ ´©ù®X±Â9?á½ûf|*@ ©–¨ù–¥©™R ‡#Ÿ?!@ w˜ÂÊ}Å?ÏGñ%‘m0ý’KŠOÇ@Èï¿ÿ¾Î;ï<µhÑB_ýµ›tгQþ<~Z @ # LŸ>]ËÝÀf*é}ódNG.jh;æ©Céþûå&"‹\æ @ ç D: œ[MþÆ}0ßý|SoÅ äŽòà!§»‰Á rI!ÕLš¸eË–é® ùC€ÒN`Ñ¢Eúý÷ßq8*†ô”)¾“‘›OÖÈ‘Å$â4 ä™3gêøãW5œ¢Ý«jgÒv @ œ X85³T:}þ¹ß¨H•W;káÑ®¼RÎÉIzè!??!@ùB ×V®\©‹/¾Ø{œÃ‡Ï—ÇJ;!‡#~ ’&Ц´aƒtíµÑ³2…£nùŽ ×=g!@YDÀÔÌP8*|h›6I³gK'J'œ mÜ(=û¬\عÂ4ìA€@~0刣>ZË–-ÓØ±cµÓN;å'Z @G G“'ûÍŒ¦pdWN9E.4·dóöÞiöe 7L% ƒ ä \v6Z³fî¼óNí¸ãŽš4i’Î9çuéÒ%Wí€ P*Ê–bõêÕݪW¯w ê‰'Žp+Ý´–ï*»ß$Û"Í—çÏŸ¯<0òÇ€ ¬$ðã?zõnc·ynî}Z:Isæ„–Ûàùî»ç9š@Úä}JÎò¬³¤ãŽ+šÆcÝ|¥®¿^ª÷Òà¢ùq€ æÎ•Þ~[êÛ77œ6:‰ÂQ£F馛nr‹0çxÎË÷:O*S6ªjžÅ <#E“&ÏÐÜ´ ìLZñ’9 ”s8ªìdýZ˜‡Mž™ €G:}ðAžA ¹€ ‡zH÷Üsë7ziĈ1ÝC"@€@YøòË/µaÃí±Ç)+ò«¯äÔý¤â©…´õÖ¡Gþþ­·Jû›íZÑÔœ dÑ£¥-[¤\Pï?~¼†ªéÓ§k›m¶ÑwÜ¡ .¸À-Êt«21@yJ bž¶›f§€É ¾þº´reÑLg̘álÛ¶mÑ‹œ d! ©fÎFæt”/¶y³tþùÒþûKÏ=—/­¦€ (wß}×ÉäVëÖ­õ /¨J•*‰fÅ}€ ´°pjf©t8²pjf»íæ&òg£D¨q d2§žòCfs„mûÞгgO§bØGóçÏ×7Þ¨ŸþYW\qÎF™üËGÝ 2!€ÃQ™`ÎíBž~ZN~Xš7¯h;ˆ–cƒ d9-n9޽LÚj>Ù5×H>(|°ßççSÛi+ ÄN`Ñ¢EÎAõ|vØaªU«–^}õUÕ¯_?ö H @(#6qX±bE甄wPD]'O–*Tºu‹¸À! @ O ,[&m»­tòÉr‹7³ÂÌ™3Õ¯_?õèÑCŸ|ò‰÷¾k箽öZÕ®];ûD!¤@þ{O²LŠÀòåþíõêÍ&U ŠRà  ä yλvÍš5yçpäD*<%ûEž+O“v@€@ª¬^½Ú“’¿ýöÛ]±Ò[ùiáÔÚ·oŸª"È€ RæpÔ¡CÕ©S'eùšÂQ›6Rݺ)Ë’Œ @YMÀæ 'NôCªeSC6¹©×¸˜Ã‡÷B°öîÝ[·ºØ§íڵ˦fPW@eB ‡£Š;î¸cG·òc· *twµÛþ¨£ŽÚÃV‚˜ÕuoR[mµ•·z±S§NêÒ¥‹{Áj£J•*y×ù‘»4ëd‹¾L› ĬY³Ô«W¯Üm<-ƒ ¼"`Ž´fö'Ÿ¬iSé¾ûò©Å´€b!`ƒ°#GŽÔ?ÿùO-X°À|½í¶Ûtì±ÇÆr;i @åB`ñâÅúå—_4pàÀ”•o ?ýä+8¤,S2‚ äSÌ[±b…ú÷ï¯7ÞxÃSB¼Ë­ÀÜgŸ}²¥úÔ€@™(ÕáÈ9µ©\¹²½} pÛv¡5 &ÝBÏÙþ¸qã¼S&¡~„‹µeÿ˜wÞyçÈdç뮓l‹´¹sçjíÚµy7)Éc@È*Ô,ßBªåΤ%€ *>í ƒÒÔ©SÕ¨Q#Ýÿý4h“É/u˜!UU @€@BLÝÈl=öHèþh7™Ã‘×D»Ê9@€²ÀìÙ³åÄ6¼÷\{¿µ÷\Þq³áÉQG@ < ;Ø´iÓú5kּͩԜå*˜ïéªU«ôÜsÏy›9ÙªÇÎ;—g{)» 0)[†°) €Ê„@àlë G."Ž - w^™`¥@ÈB¶ÊÓœ®¼òJï]¿víÚYØ ª @ùH G-ZHÿùO>Ҥ̀ è6n”sÖ‰~-Ï~òÉ'žZï’%Kdᇠ’‰Õ¤N€2Ž@Åh5jÕªÕaÎÙhº»v¶ Ÿ–³Qd¾S¦LQ¿~ýtÓM7É‘°Ü'/“²¹ÿ$i! Ì™ÖÂŶ°Ñä5§¬¡C¥Ö¯ÏÑFÒ,@HŠ€)Ù>öØcjÛ¶­,„ÎFIáäf@(c_|ñ…jÔ¨¡N:•qÉ@ÈË—KMšHwÞ™í}öÙgµÿþû{ó×/¾ø"ÎFÙñب% !Š89g£Þn"íeW¿mJ«cµjÕÖwìØQ»ì²‹6lXZr9µ$=Z§Ÿ~º–[oƒå4ŽrúñÒ8@yIÀú6s6ªR¥JN¶æLéä“¥zõ¤—^’ªVÍÉfÒ(@H’Àرcõûï¿ë /TŠÖ(%Y#n‡ ÄNà‡~ðœfm1 @€@ê Œ'ýö›Ô AêóNUŽëÝJËY³fé†nÐI'äêÚ@“&MòTŽRUù@Èabv.<Èñn°p¬kxØùÏ9§¡×7mÚô£ûüqúôéB¢Gd@IDATw¸k§××­[§ùóçkÞ¼yúæ›odƒ&=i&»~Úi§iÔ¨Qª_¿~äe޳Œ€­RûöÒ '„WÜŽ,¶iË–-Ã/p@ÈBæ8m/¡={öÌÂÚ—^e ìÓGÎ)\zýuiÇK¿‡€ ŸFŒ¡ZµjiÀ€ù €VC€@Ö0•¾9sæ¸q̬̈m‡ d'¤š5¥ãÏŒºMž<Ù›³¶ïÁ¶páBO(Ãj¸ë®»êÕW_ÕöÛoŸ¦€²ˆ@c‘[­ßØÕûq·œ iÇÿÜ$ÛÎäÓsEvâ‘›œÚÑÛöÝw_{0a‚ž|òI}÷Ýwaé³’Î<óL=ÿüó9«Öà=ps¯ºþz‚2ò==P0§# € íÌ©zõêÕjݺu¶7%jý”\\Ýz«tÈ!Q“p€  O?ýT6X{Þyç©nݺ d“Þ¼y³[<éVO¦ÈÞ{OºÃ-Ëu Úm·eJ6€ ,&`Êé_}%Õ©Sþ0gããŽ;NsçÎUÅŠÕ¸qc5oÞÜ[TÚ¬Y3o¬÷ÔSOõÕ”m© ì#Pà RµjÕ¹êoÚçd4Ç_æœ/jüæòTïÞ½½í³Ï>ÓСC=¤ '“¯}üñÇ=ǤàŸÙEàÏ?å^ÒåšÃë¨@ì·ß~á8‚ d) T¨S„ÌÒ_íÛo—Lê¸o_éo+>W @¦ndfáÔ0@€@¶°ñh³T:}ð¯{ãÙFƒúB€ÒC zuiÏ=Ó“w¼¹Ú;¬9ÝêVY^~ùåˆ`Ä ô€J!à9¹•úöoÿ´ˆ´¿ºø•½fÏžýsÄù„wß}wOÍhðàÁúâ‹/ ò¸ÿþûuä‘GªiÓ¦çØÉvŬ^=ÿ3øiaõÖ¬Y£\œ” ÚÈ' ä j– GO?-Íœ)9ßp×_Kÿ÷R§Nrán½&ò€ •Ào¿ýæTÇÉ–t²Žƒ dÀá¨C‡)«ùçŸûïV;§,K2‚ @ V¬X¡[n¹ÅS4ºôÒKq6JS²€ IÀs8ªP¡Â6lܸñ°T9yׯ__<ð€Ž:ê(-^¼Ø;mRvæt4lذ ŸYD`Ù2¿²‘ G¹4)›EƒªB€@ ä’ÂÑèÑÒoÂÚzkɤŽkÕ*<Ç @ ’À£>ªuëÖÉa€ l$ðý÷ßË…§t‘¤©Äöéã;e#ê @ˆ—Àgûí¥J•â½³lÓÿë_ÿÒï¿ÿ®;ï¼SÕªU+ÛÂ) €@ž¨èÚéÞ±*ÑÞûfÍš5%â\Jë:Ï”ÿ³eô!öî»ïÊ98…œa7[ G‘G¹4)›-Ï‚zB€@z ˜3m%÷ݲeËô”âÜ_~YrƒaöðÃÒ÷MÏD'?ùDúé'Sn K @ ŒÀ¦M›ôàƒºAåí½°éa9€ d S8jÞ¼¹jÖ¬™²÷ì)uVʲ##@€@FøÇ?äúRÉiL¸6Òí·KŸ}&¹WFýûßÒ#H›7—-Z¤»ï¾[;vÔi§Eù)ÿúQ@¹B ² ²«kL“­wªC7…§|wß}÷ÕŽ;î(çÔäå½ÌÉä|î´g÷Ì”€ž)oqê24E¨åÎ˧Aƒª\Ù¨J]æ ä8E†TCá(˜Ü@ O dZßVÜc0gZ˜®R¥JqI2î¼½ì÷ï/í²‹ïXTp‡$Û0@HléÛâiý+¯¼¢9në7Þ˜ï¢ñÔ´€ <\èÛ¶lÙ"³´±i € `r¡+Ë'¹zµtß}R³f¾ÓÑ;ïH&ø5¨SGN\Â_Ô8hPYÖ*zYöîºjÕ*/ÂNÅŠ¦¿A€@:TvêF=C3v/^ï»AÄ?BÏ¥cÿˆ#Žp’ë•þ²ÿþ÷¿Yåp4iÒ$zÄÅIÀZµj—ý| Q£Fy/Äæ‘kfÒ¿ 6Ô>ûì£N8A]»vM &ÉßR\H5›”5‡¨lSHž9@È^ôm%?»™3gzýnÉ©2çêŸJÇçK;A €@^ oKÝc1b„çt;(FŽS×,r‚ •ʪËä1ÉDÜìÙ³µÚÍ”¶oß>‘Û¹€ÒL€þ-Í€Sý¸qr¢rN<ÒHkÖH,½ÿ¾4q¢Ü<¦týõ)((É,l÷'µ´×^{é˜cŽI27n‡ ’˜ÃQãÐîøÍÐãtíï¾ûîaYÏ‹Œõv5ó>v=è„Àm7ÎêuïÞ=&‡£¹sçêo.øï$ÂlEÎâÅ‹õâ‹/zÛ ‹EZÇ\ˆËÐJR82ˆLPa*C@ « зÿøæÏŸï L·iÓ¦øDvžÜ|³T½º¯p”aÕ£:€Ê„}[j0ÿý÷²Pè't’7BHMä@qHwÿ– c’qû+±…S3K…щöë'Ývï[áå€@Òèß’F˜ö ,\šE%=忨5$7=émi/<Ž®½öZmذA·Þzkw‘€!PÑ9®lzãæÍ›g‡§kßÔyBí·ß~ =Ìø}[“N3gœqFTg£hå¾÷Þ{êÛ·¯ÊšcàpT·na­ÌÊÂåeÓ¤laíÙƒ ¿èÛŠö¦ÜgæBÑŸ(¯¸¯:ñÄ ¬U‚ PFèÛRúþûï÷2ºð S“!¹@€@RÒÙ¿e˘d"SépdïZo½º:‘:q  +d‘©{—]æ/p Ì´º~ýõ×;v¬Ž<òHõìä'ÓªJ} äÊ®aG.Ž¥³+ÍÍÛvÛ°bµdÉ’4—˜ÚìC¿øÔu=k sãÑ4hPbÊuëÖiàÀ U}ªîä Lúoï½÷Ö.»ì¢e.–Ù§Ÿ~ª1cÆèO‹™âì—_~ÑÕW_íÉZȵ²°h!Õ¬ÞkœŽ"Geñ(€@êзÏ2[ŽŠoW äú¶äŸ³½o>ñÄÞ{¨½b€ PþÒÕ¿eÓ˜d"O!UG·ß.ï«;œw^"5á@ˆF€þ-•Ì:çt2ÞlžÔæH‡YÜ7 €ÒNÀBªÕ -eÓ¦M›CÓµ¿qãÆ°¬W¬XvœÉ¦àcÒ >Üs Ž“ý炠Θ1£ ›*UªhäÈ‘êÚµkÁ9ÛÙgŸ}Ô¿ 0 À9Éb«?÷ÜsNÒ·_XÚt Gõê–À¤l! ö d ú¶’ŸÔ€ÜY¦;Ó~ód~ÍM›–Ü®BÈôm©yÊO=õ”·ÈeðàÁ©É\ @ )éìß²iL2ˆæpTÏ b6jÔ(‘Û½{&M’®¹FêØQzè¡„³áF@ˆ @ÿ„ÄLœ8Qo¼ñ†N=õTuîÜ9¡<¸ €â#`!ÕœÂQâo\q”½téÒ°Ôö²—-¶hÑ"ÙŠŸÀZ¶lì&ý¹~ýz=üðÃaù˜n¤³Q ©›Q¼Ý–Õ„˜ ”•­]+ç),mµUa‰Ù2)[Xcö @€¾­äßs¦­T©’RÙç—\büW-êÛ!‡ÈIKîë@ ï з¥æWÀÞ/ëÔ©£“O>95’  $E ]ý[¶I&ñûï¿W‡¹Õ»gáB¹ÅŸ’¢× /HµÂ–ñ&œ-7B€€#@ÿƯA²þøã]uÕUªZµªn¼ñÆd³ã~@ˆ‘@E§p´ 4­s@jzœ®ýH‡£ÒÂŒ¥«‰ä*ëh¡Î¶Ûn»D²‰zÏË/¿¬Å‹\;è ƒtÌ1ÇGÛ1g¤Ýwß½àÒ”)S˜ .¤agÔ(ié²çûËP8 Hð @ {з•ü¬Ì™¶Y³fÞ kÉ)Ëçê÷mΜ̟ûž{äêY>õ T@™D€¾-5Oã»ï¾óV†ÆF<5%“  D#®þ-ÛÆ$£±)éܲe˼1×öíÛ—”¬Øk›6I'ž(™ÓÑcIíÚ›” € ú· •á-æhD<)Ãbc*jþüù2dˆ7vûùçŸËÔy3yÑhL" ,"` GaGNáÈMW¥ß¾øâ‹°B²Õá¨E‹^,аÆ$qðᇆÝ}à†w°÷Þ{‡]š0aBØq:œàC˜Ù¤leçD‡†…@M ô¥ž¾­è£š9s¦Z·n]ôBœqãæ:ì0é知G‘Ž>:*E dú¶äÂ’%Kd[2jÉׂ @ ”@ºú·l“ åRÚ¾©™%êptÝuÒûïK_,õëWZi\‡ x пÅK¬ìÒOŸ.õí+]rIÙ•KI*uàÀÚqÇuçwzŸ£GÖ¿þõ¯Xn'  ¤ˆ€)}š—s@:ÀM¨…È ½šºýIð:ÄvÚi§£ÌÞ3gNA­#K¥™÷m`îÙh¿ýö Kü U8²„eépY1S8jÞ¼¹çtyc@ÈLômÅ?—N>hÕªUjÓ¦Mñ‰Ê銅65!Äo¿•{™–Î8£œ*B±€2}[ò%˜œÅá(y–ä@ UÒÕ¿å˜dIŒmRÒ,‡£Í›¥løúŽ;J*…k€ (ú·DÉ¥ÿ¾GõË8óÌô—K öžÚ§O×/螺#GªGzíµ×ôÍ7ßè”SNQ¥H•„X2%  $L âŒ3ÞqNFnm¼oÎÉ¥šÛ§ãóg·ÿ«¯¾ ˺W¯^aÇ™|êiJŸY³fé÷ß/hzçΫòÓÎ;ï¬P‰{Sb(s¿K²²3qR¶³LS82Iÿþý¥>®¸BºòÊâÛÀ@ùH€¾-ù§>mÚ4/“lZ ”|«É€@fHGÿ– c’¥=µdŽ&OöÃWwœT¥Ji%q€!@ÿ–µ²¹§^=É‚¬Ä¨¶JÙüãðáÃÕµkWY(Øc=Vü±S |_GqDÚÊ%c@(™@ewy½Û^vÛ€ ©s:º´mÛ¶:g¤YÁ¹T~ÞrË-Úd³dÙ6Ûl£N:‡ÿùÅgãÆ²qÓ® mŽ›j×®íby·“ã¨.]º¨U«V¥¶ë[“'1»7V«âÞv›5kæ•o÷lذA+V¬ÐV[¥W¬jìX¹¶I»íæ×Ôb¥®Y³‡£Xé dú¶â„)÷™ešÃÑ AÒ+¯H§Ÿ.Ý~{ñõç  |%@ß–ü“Gá(y†ä@ ÕÒÑ¿eã˜d¼\ÍáÈÆOQ«óM¿´C‰·TÒC€@¬èßb%Uöéþþwɶò4SÀ:ÃI»ÿ÷¿ÿõæŸzê)í±ÇåY%ʆ ¿˜Ã‘œƒÑh÷êpTÃOhÚ´é^óæÍ[jiReÏ<óŒçmšßqnyˆ…Ë •v4E"“î3'£Hû裼SÖ¶O<Ñ©\¡:uêD&+8U7²“õÌm8«[·nXjË/‡#[Õd/á't’—_µjÕ4jÔ¨°¼íÀùY¹4þæ«g™ªá׎Ÿ€Š˜;w®®ºêª‚ æDjá³"ÿ§$ÈÑ\ïÛì9[ƒ¾ÍãO<¡ªU«–úD‡£LRïê´(b°ŽY®÷m‹-Ò’%KÂú¶\¼—xß#Kú0…£Zµjy‹[JJÇ5@eEà¹çžÓ‹/¾è·|ùrýùçŸeUtÆ”“Žþ-SÆ$í™®^½:¬o»óÎ;Õ¤I“¤ùÛX§-"©\¹²–û=’>ûLjÚ´ô¬ß~[nŒUÚsÏÒÓ’€@¼,ÔèÑ6E'­\¹R .Œ7‹œHŸËý›= {·úòË/5uêTïy™`Áõ×_ïíó£dO>ù¤.ºè"Odá‚ .p /oWÍš5K¾‰«€@¹˜4i’ Iìb;3¡’È÷r­…§œ€çpdaÕÜ$Ú Î1æøÚ¹Øo8ežã]ˆ¬¹!çÞµXš·ÞzkØýõë××¹çžv.“/^ìýau4µ¦ÒÌöÇŒ£wÞyG7Þx£8à€¨·ØKu¨Å;Pé\d¼‰„|ÛvÛmµÝvÛé /ôªS±bÅÐjìÕ õsÊÄIÙ‚ ³@ 뇂ÿwvùœsΑ9Zæ“åCßf!Jm }Ö6Ћ™3­õ…‰¬„%ÿxÓ¼û®tÛmÒ^{In¾Å ˜Ç›é!|!гgÏ¥ÕO?ý´HXë\æ}›9G›²nhß–êAWS8jß¾}V-ÊåßkÚÈ[ÉncVf¦Êó¶y‚ä‘¥«Ë”1É5jx‹BBû¶­·Þ:é'lJð¶Àò˜cŽñòúðCiÁiüxyÎG¥`ʲe”w¯ÒHqH„À.»ìR°ðÑæWž~úéD²Éê{r½³‡³ýöÛ{‘_‚Å‘óyYýÓTy[`cóÇælnüÌñüäÓD›l!Z6–|§ÿõ×_õïÿ;µ[F(˜¢Ú¼yó•*Uêåj× ¤†»¹sß8§£óÓÑ8w>¡%±ïº™±ûî»Ïóà ÉÛÛ½ä’K¼AÒÈó™zêeZGS1²h»îº«·¢Ô¾N™2E¶ê4°ß~ûM_|±žþyoÐ68|F¾ÜÇ«®™>QoA´¶¼öÙgŸ jQ?Ý»ºzôkwáeŽ Y°d[µúÿÎKbuDÉŽ–^Ë|èÛl6òY—NÆOa}º…-E )Ö<M·näò¸U<’© ºñx €@±ÌQ2p–\¶l™‚ÅÅÞCò¡o«^½ºl ý“ÊGhª!NñXûï¿*³%/@I°ïå¶™mÚ´IºxR™fÑÍéêß2eLÒÞ¹ì}<Õ}›Wšš±M|˜Íží?tS92µ£ÒÌDèmÁ@ Ì‘Â63¿ ”üÒQV¦æ™ëý›q·97SìKu—ÎgjÓ›¥³„èy[ŸýÐCéúë¯/Põ1b„RᄽDÎB©&`â&¶™Ùxd¾-òO5ÏLϯÀáÈ9-v3ƒ\…ͱ¨à¼ÛßÚ9u×ntJ=#œcÍ Ni~i [¿~½:Í:[ÍlUIÿþý£]ÊØs¡qdƒJš†yÙš£N¨Y§hR÷Þ{¯'l×lEÍå—_î}i´ÁáP‹|¹Wá(2\›Éo¦Ó7–>þ8¼û§a‰(+…çÄ ”ú¶’I[ßÖæ‚qà 7èŠ+®(âldm2Ç›jìØ±ªR¥JA3s—†^pìD²ˆWIÁœ™B-Rñ(ôZºömÅPs7šoê éâI¾€Ê‚}[ñ”.\(sàuß{ŠOT†WÌWÙ©9ße €J @ßVœ/M³Ø1Îp8ŠÉ ”tõo¹0&YþP‡£@Ýè²ËäŠâlT7®A(+ôoeE:¶rÜ4ŸSº•–/— ˆíždS}ýõ×:ðÀ½ð§¦´{ÓM7ÉÍYãl”,Xî‡ PÂެ<ç óºSæÙß©-.®|÷ÚÔmÇ¿ñÆ,TÚ°aÃtçwzñ3?ýôS{ÜýÅÝ®c=V÷ÜsOV:¥X¼Á>ø@&Lk¿N<ñÄbÛ\h×®§jÛç;ï¼zèí7lØ0ìœIØÇcë,ÎJˆ•µ¼ =ss¦Ê”IÙìB€@ èÛŠ‡„jݺuñ‰¸@G€¾-ùG(í´ÓNÉgF€ éêß²}L²4¸Ã‘ÑG±(ÆÎwÿ£GKK—–V×!@ ôoÉÐKí½ælä4%´ØÍ#}tjóÌmîܹ:óÌ3Õ­[7Mœ8QgŸ}¶LØÀ.jÔ¨™œc@È@Eެ޳fÍú|Íš5¦›~¿s"Ù”ªz7rÁ>M é_ÿú—"É¥ªŒtçc1-æ`«V­<%ŸX˳³V­ZÉÍC7Ò¡h›m¶)¸n;‘×Ã.F9X»vmØÙúõ뇧û`¾{ w¿7bR6ݤÉ€@j зÏÓ^pÍp¦-žW d"ú¶äŸŠ9™êîŽ;î˜|fä@)!®þ-ÛÇ$KƒkGMš4ÑV[m¥9süÔ±8/všÜâÓÒJà: $C€þ-z©»÷§Ÿ|e#s6zæ©oßÔå™Ó¢E‹ä¢èxc®£FòÔLåè‘GQãÆ#“s @L ªÃ‘Õ×9Ä,urunÞ¼ywø¨swÛz·Eµ xÞ¨C† ñ¬½òÊ+êׯ_ÞËßE:âD:E¾Ü[hºxì×ÀóÇÝT¹reoÕN<÷Ç›öý÷¥[n‘þøÃ¿ˆx ’€@öȵ¾-ò‰˜ÃQÅŠËUÝÁ)ë?ÿ‘Ü" €Ê€@®÷m± 4õÜŸþY:˜ð1@¹@ ¤þ-ÛÆ$ãy6^ºÂ­âu8rëBeG7ÊaK§œ=G‹¬mêuêD¿ÎY@(ùÚ¿¥’ü¬Y~5›’4g#7›r³ˆ.7ÜpƒZ¶l©Ûn»Í‹”òòË/ëÓO?ÕÁœòòȀʎ@åX‹r/g«]Ú±mv[Åß~ûíB«ÿÊ•+=©õzõêyN.UléV„ÀêÕ†°ÐZ´hQxàö,T[¨}‡” ‡:(í²Ë.2ïîtÚòå~îuëúŸ™ ‘Îö’7 %k}[d Í™v‡vI;—‡ÙêÛûï—öÙG.žyyÔ€2!ä\ïÛby¢¦áÔŽµÓN;Å’œ4€ Jêß²mL2ÜNÍ,p¢½ï>éÊ+åÞñü\Ö»%µ¯¾*¹¡UU¯îŸ ~ÞuW°Ç' d*|íßRõ<æÏ/t6=Zêß?U9‡çs‚“L²(8¦¢ûÐC¹rú§}3¼A€@ºÄìp¥›Ýê— QÎçì©?þXS5ò°ÃSÆ cnoè½vS«V­ÂÖ^ðå#§,%§,¥Zµj…¥‹v`ÎI›6m*¸t -ÏI³GÎÏÌ3›”5e%óPÆ @ ;з•üœ¬ïÞ}÷ÝKN”ƫ͛Kï¼cNÉr/ái,ˆ¬!äú¶äæ÷ßïeLÎ&Ÿ#9@€@²ÒÙ¿eÛ˜d<,ƒ>-P8rÂü²-°ãŽ“>üPzï=éˆ#‚³|B€@Y ++ÒÑË1çÚ¹s¥Q£¤OŒž&Ù³Ö›³Ñq®Ó7nœ*Uª”l–Ü@D ‡£¤šqë­·Ê”‘»ù曃݌ýtáåZO§î¤sÎ9'¦ú.Z´H³L—ð/kÒ¤‰jÖ¬zŸ²å¨£ŽÒã?îÛŠÒÿýï:äCÂÒE;˜8qbØéý÷ß?ì8Ë–É}1j×ös·IÙænfÔœŽ0@ÈômÅ?'ë»Mî7Rš¹ø;Òs¥W¯ôäK®€r•}[òOvÚ´i^&(%Ï’ ¤Š@:û·l“Œ‡i p8EÞkáÔöÞ[Úm·È+C€@Y + ÊÑË0•¿'Ÿ”Úµ“ ˆž&gMÑÈìòË/ÇÙ(@É€@†¨X^õ?~¼ž{­¼êO¹{î¹gXò×^{-츤ƒ{ï½W6 Bçtì±Ç†eóðÇG;Xæ<Œe`ª­,T†Lá(§¶eËÙÃòž” ð @± o+žS Lغuëâq€2Ž}[òÄV ÚªSS¼À @ 3¤»˦1Éxžˆ9Õv«%›6mõ6S“5Q[e£âá$ ´ K;âb XºTêÙS:ÿüb“$}Á„žxâ uêÔÉ9ø:_ €rŽ@¹9e#I æÂÈTÝ^XÇŒSp\ÜŽ©½ð —í%wðàÁÇ¡;¶Ú&ÔigÊ”)zæ™gB“„í›JÔùîÛ@hœÚ~ýú…¥I×A¨Ãѯ¿þêÕIÙtÑ&_@é!@ßV<×Àá(´_.>uꮼñ†ôũ˜ äú¶äŸ¸9Ù"–jÕª%Ÿ9@€@J¤»˦1Éx€Úøm;“np¶d‰ôõ×rc˜%ç0v¬Ôµ«ôå—%§ã* $O€þ-y†‰æÐ¸±ôâ‹Ò%—$šCé÷uª‰&œwÞy¥'& d%Žâ|l »ãúë¯×°aô޴£˜Iž}öÙ²ðh™ƒPýúõƒÃ"Ÿ‘aÚnºé&=õÔSÚ¸qcXZsò9ýôÓÝËoáÛ¯9üع²0 ©(ýøã^‘e=)[í¤ @¹N€¾-úú¶²t¦ýäéøã¥Në÷£×‹³€ P:ú¶Ò—ÂÞ;­$œZq„8@ ü¤»Ë–1ÉXŸ€-Ôœ7ož‚pj&V¿ë®Ò;ƒ-ùê+©Q£’Óq€RC€þ-531—|PµjÕÒi§–‰Õ£N€ •SG^eqÖYgiÆŒ²p™ ©™³ÉV¯^]Ó§O—­ Yn2@!¶óÎ;—êtÌ1ÇhÒ¤IzõÕW½;ÍYéæ›oÖ¨Q£Ô¹sg/ÿÉ“'kΜ9!9K•+WÖ 7Ü *Uª„O×5m‡üÜËK"]m#_@ùD€¾-úÓ¶¾­bÅŠÚqÇ£'HñY÷µAGåKù?û¬õë).€ì äú¶Ä¶…ʶ5:tH<î„ ´Hwÿ–-c’±ÂµñY³Àá(JmÞ¼hNÜÏ÷Jû›ôÖ[rc¼ÒöÛMÇ@H=ú·Ô3Í„¿rÞ»Ÿ}ö™ ¤­¶Ú*ªD @ ˜ÊJª)-q¼~øaÁÝ6lдiÓ¼­àdÄŽ}iºôÒKUµjÕˆ+EÍqÈœ•Ìñ(0[‘c[4«Q£†î»ï>uïÞ=Úå´œ ©V*ii™BÈSômEü‚ Ô AÏÑ·èÕÔž™?_:ôPiÅ é•W¤ÝvKmþä@  з%öÔí½Ö …£Äøq tHwÿ– c’±2¶Å fÃѺuRÍšR³fEspâòºå9Uzɽ ê¤“Š¦á  ¤ý[úØFæ¼i“ôûïÒ¶ÛF^Iíñ<àeH8µÔr%7@™F b¦U(êcC=ö˜~øaOѨ´:7rú»#GŽÔUW]“³‘ågƒŽí¢‹.òöK*c=öðB®í³Ï>%%Ké5‹uî|¬ Bª™ „),µhÑ"¥å ” ú¶¢œ/^¬† ½â3¢ô°Ã¤¹s¥Ç÷÷S\ÙAÈKôm‰=öïMâÁ G‰ñã.@é&îþ-ÓÇ$ãá8}šתUÒÖ[Íå¸ãüsÿ»ÿi B0@(;ôoeÇúõ×¥¦M¥qãÒWæ ·ªr̘1nQånêÚµkú "g@(w(%ñöÛo?ÙöÅ_È~~ùå/ÌY}·¦uëÖÞÖªU+5nÜX*Tˆ»$ ã2xð`YüÚ &hÊ”)n…Í­vÞ>Mš4qáÌvРŽ;Æw²7‘âêÕós2ÙýfnyPY…sK¶þÜ@Ñ äsßIä·ß~“…BM§¹¨©êÓGš:UºývéÔSÓYyCÈOômñ=÷@á(PƒˆïnRC€@YHgÿ–Éc’ñð5'ÚJ•*yc´¥Ýg¢ñ¦|daתW—öÝ·´;¸@é @ÿ–ªáy>òˆdc’{í~>•G£GÖÊ•+…ºQ*©’ Ì$€ÃQ žK·nÝd[º¬¦ÓúíÛ·¯·¥«ŒxóµÕ@r5X´hÑ"™s@¹A û¶Ð'·Ù½uÿñÇiW8>\š8QºðBiÈа@©&ï}[¬ ”?ŽÊÿPÄCÀÂ’ &õëç+¶X8²P³1 áÝ}·d!ÒþŠ0\pëÆÒe—I'Ÿì+Mœ(]pô÷¿K÷ßï«í½·ô—PšwߦMRÿþÒ=÷HO?]UR;+WJVöÕW[ÛÛiÓ¦JIåÇ͹KÀŽ*¸8}j_àpÔ¼yî¶™–A€Š#à„‡Ô¥‹ôüóÅ¥HþüæÍ›õ‹Û°aC§†éä01@È 8åÅcN}#íKÉi§™³G©§KŽ€ PÞÒ­pdí«ÄÜHy?fʇ ¦pd¡²4hq…C@ ¼|ü±tà¾CQä‘©fÞq‡ô þwË… k¹ftØaÒ‘GJ¦2«™j‘…Ú~{éÍ7 ï²ü^].<†ï8¿çž…×lû3ÏøcD¦t´`í©§¤×^“Î~B€@ö0gÚm¶ÙÆs:JEk,Ä„mãp” žä@©'`êFfŠó^H}‘ä¼"ðË/þ8Š…E;é$ÿ»aq, ÙñÇË…‚ò„ºu+.eéç‡ óކõW¼›ó’ÕáŠ+ü°iÏ=WèlTzn¤€@vøî»ï¼ŠvêÔÉû´Ð2ü!5‹{ô;;ÚK-!@FÀ”&ÍzH2Ñ€tÛs·OŸ>. ï›:ÝIZ>þøãªT©Rº‹%@È0žÃ‘s6rCr~®ñ™y®Ú†å7s82g#¾Hä÷ï­‡ K¬oK¥rŸ{ßöVýã¹D‰¶@€@.Àá(—ž&m) æ¼pë­~ˆ1 'VšúÏÏ?ûŽ>Ý»K{ï]| _zI²ü,ü™9uî\|ÚX¯üíoÒV[I^(í¼³´|¹œò‹ôÆ~ˆ©Xó!²…ÀT“ír(™º‘™…Ä @¹J m[ÎF+7ïÑG­‰'êÜsÏÕ< 7ל«hi ”@€j%ÀáRlR=)[©¤‚ ¤€)uI¡Þ¾…±˜2EÚzëôÕ™œ!@ɘ6mšw;!Õ’¡È½ùB`Ééàƒ¥¯¿ö[F¤~R6'Ñ@ÈZ¦n´eË5lØ0kÛ@Å!@ñ°ã:Ä{é!‘ÌÁèƒ$s0²íóÏ¥ üªš³ÑæÍrß÷ «^»vlGóçK ͘᧿ì2?>}$UB¯¼"#½ù¦4y²tÒIR…å··b…d[‹Ò[oI;îX\JÎC¥XïäÂ~üñG/ÌK6p8Bá( Â' @ ~Ï>û¬Îvr™ëÖ­Ó¿ÿýoçhï<í1@È{žÃÑO?ý”Þó\µ!Žòì×Èæî¹GêÛWN6ÑŸ”ÝvÛmóŒÍ… \%`Ê}f8åê¦]€ IÀ”ý-ZäÉâG^ãÙHàï—î¾Û¯y=·¼î°Ã¤ýö“zõ’vÙÅW8Ú¸Qn²D²Pf¶i³fuü1g¥ ¤ûï—,DY¨™ÓÒÉ'û›‹2á94Åâldyœq†J­²7Jš+û€@¼¦OŸîþ¦7ªcÇŽ·þþ»ÿ·‹ÂQv @1°~õÊ+¯t߯ïöqǧ½÷Þ;æûI@¹M€¡ŒÜ~¾ii­º³•€6hLÊâp”Ôdšn.l’·´5ø4o:Û7«YSªRÅßÏÔŸV×µký?H«{°Ùh°´ÉÒ†n6¢n#m[mUrë–.õ—ïZzÛ,Èü­ ;W±báf£ðvl£ùÛlSr?ÿ,½ý¶Ÿ‡åcf²ç6:oÏÁ>ƒýh#ð¶ ¸Nï¶b؈ÿ/¿øËšmi³mÖ+/hÏ_ûÍmÖËk¦pd–оí…|EÀ6mò)‡ 'ðÍ7ßx5ìT\¼§ ¯?ÕË^ øj@Á×ÿúõÍéÛ…°}{¥HÄþõ/ɾíµ—ÿ],Z>öja›…S‹4S2ÚuW©gOß¹(pRhÜX²?—jÕ"ï?vÑ ã¶h¯:qg €€ wèâ: u8zøa9%¨D€ \#`ÃÚ¦ðí{m²m]ྰ÷s±‚?üðCçÀ¿ŸLå¨Q£FÉfËý€ Cp8Ê¡‡YVMY¶Ì/ÉÐp8J1u[Zi$f¥9‚ø©bÿ8UÎ!öió…•÷Wlûb35瓯¾ò—Z=Í1#ø´}sF uL öƒ û÷÷G{ƒãhŸ_~)Ý|s¡sK‡}ù‡:΄î[š{<2ZÎ…ç&L(=¥6‡#û–l¶dÕ[®»NÚÿÂü¢í½÷ž4t¨d0V¯€û_N-ž“KhÝ#÷ÍKᨣ¢å\xîå—å&Ç»g÷sLÉwMœ˜þ2ìwêÜsK®GIW_}µtVæÐt %åRp­OiR)ÙÉUÃQ² G«Vù«Õmîöãs•í‚ \ 0Ùb?9ëÖ­[.4‡6d(wÞñ€lMA`S§Jgž…š“Pà€d¿šÿü§ïDž*ú‘½Ê]pAôk±œµWãc•žzÊw:š9ÓwN²{Ks6Š%Ò@é#ÍáÈJ‹Uq,}5#g@€@z¸èØêÒEºýv)ù›Š’&Mšä9™î!CtË-·8‡}¦•SÁ–< äz†\zšeÔ 1ËK‡#›=6¡[Û¶RË–>”â~ºØñ. ­´fï cŸÁf;Á¾9¥f€-_ÛÎ;O:äàJôOs 9õÔB¢À‘È>Có~·4fŒtâ‰Å]õÏö™tøá%§)éêÎ;—îpdÊ"¯¼âæš^}°ì4rߎƒÍÒØˆ°Ç¢JÔ¤‰ï|bém;òÓÚ`KìyÛÊ•¾óÐܹþ¹’Úi׌¹û"®­·öëdŠ?¡›•”ÚŽ`?–0…-ZøÞ –O (äz.È3ôÓ˜µo_Z+üçu×]>#»ÇòÍ;(ÏÊ·6ÛêÜfo:¥Ù>ûø GKü]Øsþ>lß³"­]»È3EÍãÃÙì÷#ج=· l÷ùÖÿýŸbsM*Z grƒ@ªœiŸ^²gœ‘\h ä./¾øÂ}-ª ®]»æn#iY¹1Â%0@züñª˜ŠÐk¯ù_ÿíë¾­q±WÂ%K ?íµjôhiìXéì³ý‰[ j.ªƒúô‰íu0ô¾âö4ž|R:í4ÉTžíÕƒ²ƒ€9Ùdh»XÆ ²£IÔ€ P">ò‡ÍK›¦*1“ˆ‹£Ýðºi—êzÞ rŸÌÂ爼9„ Ü"à ™´mÛö©-[¶hà¹ý?ýôÓ¼Üj*­IÀáÈBª¥J"UuK(Ñ´‘Ë?þð7S¤±}û´Æ†~šRM¤Ýy§tùå‘gÃM¹ÈINzË©Ì1&e£˜Á± öÍiã—_$ 5eê-½{‡çíÈTxLç=p¦ý œB"?Íy$H׺u´\ÃÏuì(=ø ¿¤ÓêjK;ƒOÛRì3tßœ9ÌL¾4;ôP_¨´tÉ\·0_6"N;è iöìt– 7#$™Þ2ì÷"•Ë"¢ÕÖœ«ŒW:Íœ«þþ÷˜J˜fVX^HUß6j”ÿ/ÒÄÝ0@€@&0…#7.àÄ<š'RØëª½ªš:‘9W›hjI¿:öJ;x°Üï˜tíµá™›¸èG„Ÿ‹vd“(û›ôþûá*%¶ÖÁ-¶–}…¿æÉ­H©|pJ³#3@  LuÿœÚ¸˜ŠU«V-ƒÒ(€ Pþþ¬õ §¢6·Þz«ûn}vØa½þúëÚi§R‘-y@€@Žp^žíãV3¶ðwm®£ó\À €ùߘ™Ï?,öö·EÅK™‚æ¼cNB¿ÿ^øiû¶2P)±blß2zô(¹P»÷ ÃÓ˜#Ž…3¯*k¨ûbå}Çv.ØöÜ3üÞhGæ¨óçŸÑ®”~.ÇUZÊÝv“l6f’ }•κ‘7 H…‘MÂÙ„˜9Y×A€2•Àr·Èb¦‹uòÉ'gj©Wpó Þ:'" Ù`"¤™Ú‰íZ3µ4‹xmŽF—\"Ùš›Dl¯½¤>ðUìu=0[cÎF={JW^œåÈWkZò¬Y³œâ™“<ûËl-˜ýÿØiû탳|B€r‡Àøk†“¦ÛìV\ì"uŒpò¤]\ä‚ &¨‰E‹À @%ŽJHRü%¯³}ظÑ%VÏ+W®„*%4)k¡’¾úÊwè1Gœ’Ì”†N?ÝU4]uÛâqܱ%¥9™*Ð{ïù¡¯,ü•m¶<3På)©~eqÍ”‚0@(3¦pTÉÍdÕKÂSè‰'üè‚gœQfÕ¦ @€@B,œšS9V·nݺŸ›r‹€­ï™>½¨ã9Yˆ1›¬ßw_É^å-j±Eð~øa_ל,ZòùçK}ûÊùlLh÷ÆSéaÃð|,Äš­Gºâ _Y2ü*G€@¾øá‡\$öMîTáxã¤IþÐâøñ8åÛïí… /ìû¶ ü'ckÜŠ‚SN9E/½ô’<ð@½øâ‹nM¾[”A€J!”'믾ÚîwS‡ùËÎv#=84r÷3p82s8ªâBr•8);c†ôñÇÒ§ŸJŸ}&}û­?*yÎ9ÒC• ÊÂu½ý¶d£Š¶Yx'[ºÕ¯ï[H13ÓT·ÍÌyJ3 fËœ0@€€#`}[C×çT´·õ̺ `BŽ0 ä@(SæpdÖ½{÷2-—Â2‹€9Y¤pS±¯@¶öÇ¢o6hd›Dš½ÚÛ«þý÷KÏ>+7Qá‹ïÞw_dÊÔ[cŒœœúÂÉÈ8ßÙ?3gÌ#ò/ ¢ÝÛzC € ¢–:þ£>ÚÐøÈs:9r¤7ïW4%g @E $åpT4;ÎäÐj6)[b85Ó4¿ãŽB,K‡.í¾»tÐA…ç‹Û3-SD @eDÀŽÌá(Q³PjRmèPÂ.Ñ|¸€ P&Ožì9Ùîºë®eQed(¦M¥¹s¥½÷ö×ã¬[îpÍÑ(´)öŠo›…7só1½î‡ÞÏ> T˜:uª—M¨Â‘½ÚÙÿ§-RQy@€r‹Àüùó=E£éNæôo.bˆ‹lã‚TÈ­FÒ@H+ŽÒŠ773Ž,ÒL Q¤¥&ïpÑErÁ^ýËK/õßîYNT' @ ³˜ÃQ2“®£Fùí!œZf=Wj@Ñ ˜ÂQ»víT»víè 8›Ì¡hʹ°²É5׈-¼@ <˜Â‘©ï·iÓ¦ øsÏ•là @¹H`ôh©U+iÏ=ãæì!£@IDAToÝ:·Ê OŸ>šá¢”Ü{ï½|B(/æpÔ¶m[U®ÌÛòz” @eG`ÃÉÂ_w]be^pÁúüóÏ]ˆâ¿ãl”Bî‚ G€·/~ â&à ië­åV ­ÕŸþ>)»i“4`€ôôÓÒGH/¼ U¯wÜ@(æH»Å;%RÍœV­’P7*§G™€ /S72ëÞ½{¼·’¾¬_/Íš%ýô“Ìq£9‡^ [ÝüöÛ~H×*U¤&MüBF¨eKɦ™SÑH—]&Ýt“dQÐ1@¹@`õêÕ.´õÏêß¿.4‡6@€J%ðõ×Òš5Ò^{•š´H‚ÜKÁã?®Ã?\7ÜpC‘뜀 ÄJ‡£XI‘®€€ Ù6gÎbï\ „¹SŸ|²/íл·ôì³æ•Tp;€ L'`¡BÍ ú¶8+láÔÌÏöÄ㼑ä€ r 0yòd¯TŽÊ~E>óŒtæ™þ¦¦épä'ëÉ'‹ÏØœ”6”,ðÃ.˜ 1@ WL›6Í[<Ò±cÇ\ií€ ”Hà£üËñ:}än¼ä’KÔºuk=ã^2*V$N‰ ¹@%Àá¨D<\,‰@ؤ¬‹õªN^}ÕŸe}ê)ÉeIp € aLáÈ,Q…£‹.’Ž:Jª[7ÃFu @Q˜Â‘ .ïºë®Q®rª< ˜xpdˆ³=ö®¾Znb@Š6Ÿ~çÒm·IåÜÖÍ+ýò‹œâGáçìÙÒ¡‡JwßÍ÷•ò|¾” ¤ž€…S3 u8š>]ºývßYsï½S_&9B€Ê“€9™¯-FˆÕ¸Õ}ûöuZUõÒK/©^½z±ÞJ:@€@T8EÅÂÉXGÞ¤¬Š5g# §æd½o9±dB@€@ú¶DŽŽ?>ƒCU @¥0…£öíÛ«V­Z¥¤ärYøá?<ëÀ’½jÖ¡ƒ4lXpTôÓŒl Ì ;u Žø„ Û¢9M*=ö˜tÀG¹ýüi |$`G¶a«­bkýz£ÙœÌéhܸqî]—…ØÈ‘ €J"€N^It¸V"@›”uò‹zôQiäHœJ¤ÆE@ÈdAß–¨ÂQ&·ºA€B ,]ºÔ)ßü¬îÝ»‡žf¿ ˜ª‘)q˜à”…Gsó ÄHÀŽª»øÖ­Zµ*¸cηyó‚Sì@€r‚€©™Î›'ÅNͨY8µ«®ºÊ,qK0@€@ „¬}KAnd‘FŒlee˜ D×®’m @ ‹ }GYü©: ÄDÀ©™uëÖ-¦ô$ŠÀŠRíÚáëq,´Û÷ÌD¥"7 þä9Õ)-O<¡â«©!ä©NÎÈTû*…Ä£´0’f8ùø @¹CÀÔÌbu8éÄ|ðA|ðÁN5µÙT?[~B€b&€ÃQ̨Hhœâ¢–N9EÚn»Å”DÃÎ@€ i…£xû¶7Þðã¥ö<Óž(õ âG(G(þó¦P4v¬Ü@¾ôá‡Ò¬YRË–…ùlÙ"Ùw3{·Ž´ŠNƒzÈ馛äT:"¯r @ÅøóÏ?5×I=ôìÙ3,‰9Y¨Éí¶ ;Í @ ë ÄëptÝuשI“&î}el˜snÖƒ € Pîp8*÷G]X¶Ì¯oݺ… G¨@d×3¤¶€ P<s8ªìF¤ëÅá9´d‰tì±ÒAI¯½V|Þ\ dÉ“'{Í»ì²K&U+«ëbCn_óçKýúÉñ oŽ)­]+U¨ mÜ(­Z¾m½5*áÄ8‚ iÓ¦i‹óêìØ±cØ R­iÓ¢ÿÃq@ÈBæp´í¶RëÖ¥WÞ›˜cî·º¡~ýú¥ß@ @€@p8ŠIå^Þ¥#”lLúÅ; øZÞ@€@.°jæH[Áfc´Ñ£}•‚ÓN‹ñ’A€2€€ :wp±²kÖ¬™µÉÎ*8A Õ©SXwûúðì³¾ªQqãøÁW Sܰ…<¶a€ ï¾ûÎË S§Na™ÂQÄ©°ë@€²‘ÀêÕÒ×_ûsu±Ôÿ¥—^ò’õéÓ'–ä¤ ÄEÀ­¿Ã ;F¤ÿüG4H2ÔbgGJ@È|‰ôm¦fЮÄ;{æ?_j@>ßÿ]¿üò‹ºuë’¬[ç‡7|ætjv®8g£ÐtìC€@êL:ÕË,TáÈTä\w§fÍRW9A€2ÀçŸûŠ©{í[mƯFnr¯G±Ý@*@€@p8ŠIà ˜ Ķ¦ÙˆA€r„@"}ÛÅK?ü U«–#h ä<S72ëÞ½{η5Õ üñGiÏ=¥#ü0=" ƒ ò%` G¦Ø×²eË‚ŠLŸîïÆj¦à&v @Y@`éR©I)‡£Ý Œõ“Ç{¬*ÚªI € bQCªUªT©wÛ¶m–VÖºu몄¦ù“¾©–àlR~¡$³cßT ºté’•¥–€ RlذAË—/G½¯N\† ì'0yòd¯(Å÷,ÇŒ‘Î=W2Ռ믗®½VnÐ>¾ùäõë×OU«VÍ›vÓP@([ˆ—-ï¬/íÓO¥‡–æÍûCǺÖtŸ2EN¯8ëÛE @ñ:¹ÐçêÑCÚ¼v€ ì!°dÉÍ™3GÝ»wÏžJ§¡¦6}ÆÒsÏ…gnjF†¦n]iÑ"éÿ³÷_é–[¤×_ÇÙ(œG€ÊŸ@qGMšH̰eù?!j@åEàå—_Ö–-[\ø5ƒ ƒ ¤‰ Gi›«Ù._î·líÚE:Àí®rK>kµj•«Í¥]€ G"CªÝ{¯tóÍãÜ£º`Ö”&N”[!$UÄ};~Kh* ì'`êFfݺuËþÆ$Ø‚Ûn“†õo®UK:á„ÂŒÌÑèí· Ùƒ Ì&0uêT¯‚:u «èèÑa‡@€r‚À!R½zÒ?þQzsÆï)~øá¥'& @ AžÃÑêÕ«»U¯^½R¼yLœ8q„“`š‹7Ògݳ-¿~¯öno¾¤vã³ @ ë D*í°ƒÔ²¥¯ìgê~êü’K¤#”FŽ”[!$ ˜õͦ€ g¾øâ ¯Åù¢pdýu¤(¯·Ûüôe—I]»æÙ/Í… cf¸˜—"t{à @9L`ÃéÁ¥Ýw/ÝáhÅŠzï½÷ÜxæÚj«­r˜ Mƒ ò&à9Í›7oi"Ù~ûí×%r÷d/S8ªREjðõG^#6î»oö6†šC€BD*™²‘mNôž{ü+ï¾+™°Ÿ{gW³fÒA…dÀ. @ ˜ÂQåʕեK—,¨mâU´þ{ìXiÜ8é­·¤P¥ÂÎ¥§žJ „ D%0~üxï|ïÞ½£^ç$ @ •p8J%Í<ÈkÅ §p´ržÜX®fZÀX € #LáhÛm·Õ{ïù“–:äHÃh @à/_ýµ*Uªä&a³{Ö îêÐCýP“&Iç'MŸ.  U¨Àㆠ|!8µiÓ¦ Éî•NÆIGQpŠ@€@ÖX´H.ŒhéÍØìVb¼òÊ+nF'µnݺôH@H’@å$ï׬Y³´Èzº$mÏ=÷L2nO7•+ý/4[-™©o\a5,`,@Èë×¯× çUk G&þPÙ}CêÙ3F @!¦:?›”­^½zÈÙìÛ­YS²÷S‹0t¨…ˆË¾6Pc@Hž€95p ì¶Ö´©tõÕÁŸ€ Ü pÊ)’©øÍŸ/U,AJâã?öæl ” §€ ñJu8r°[¹VìW¡B…ƒ6mÚôOç`´<´UO>ù¤ÆŒz*¡ýé¶ËhNͬ޺Åz×}š @ÈNÍÌú¶áÃ¥o”j×Î…–Ñ@€€O`íÚµš9s¦sÒq^:Y`[¶HS¦Ho¿-U­*]tQx¥?ø äöðÔA€@.0‡£¶mÛæbÓh @ €€['©>’öÞ»ôw —^zÉ»/[Þû É d-bŽZµjÕÚ9][±bÅ“]ë¼tnÿæÈ–n±Q@,/¬['µ¬¿\M–þ*mFÝ @ÈNÍÌŽÌZ¶ô>ø@È?üðƒ“àßäIëgC£^|QêÛׯ©Eó<8<\ZI«z³¡}Ô€’#` µ¶päb§%’»!@ ã |ú©´f´ÿþ¥Wuüøñjæ^ ºvíZzbR@€R@ šð^%·2äÎJ•*}ïŒNweë””‚òU­Z5N-$ÓŸG«VÒ¬}Nוî’[LŠÂQú‘S ”P…£2*’b @eJÀ©™uìØ±LË¥0©]›7‡§´Áô!C¤·Þ’L¹B…ðëA€@~ÔòCŽ"û’ü&Dë!@ WLœè·¤W¯’[ô“5UÛÞ½{—œ«€ s8r«úk·iÓæe—ÿånKÈѨF¥V¯ªÓCì–'>ýôÓšñÄNâÛ Y²ã«@Èûò’%U¦š€  øGxið?JLÏE@€@6øóÏ?5gÎ7[¾áÔl üÊ+ý0i+]œn·WÏ<#Õ­›M4©+ ds8Úa‡T³fÍ‚ê˜ÂQË–RéÆ @9@`âD¿½zߘ[n¹E¿þú«n¾ùf÷nÅËUñ¤¸@é PÑ2Ýzë­ûºÚAÎÑh³ÛøÓO?=œKÅçî»ï®#F¨bE¯X/Ëo¼ÑëS‘?y” ›”µgØ Aƒ²)R @i&`δ*è L—=ÍÕ {@€@Z|÷Ýwrïùåæp´i“ôøãRÛ¶ÒwH=zH_-vZZšK¦€ ~üñGׯ¸Žå/³3Ó§;àÁ' äÿþ×MÞºÙÛîÝ£·göìÙºóÎ;‚lguÖYÑq€ Fžç“Ÿ æs‘£ÝKÛ¨t”kî¡áÕLêoìØ±é(Š<ÓDÀ&e*V˜ãXšŠ"[@€@™X¸p…›ˆÝC={J•+—I‘@(3Nͬ<Ž^rzÉ;ï,7ø-­Y#Ý}·ôÁ¾E™  @È) ,©÷…:M›æäù>¿…ìÄ @¹@Àb-¤š…Ÿ.n¼òª«®r!×Öjøðá>;¸Ó@ˆ@Eçzç`Ô+ô6w|Oèqª÷/¹äÕ«W¯ Û—_~Y›7›¨– ÌáhÛÿgï>à¤(ÒÆ?Ë‚dIJ,A@ÄÄðêxÆSÏôQO}Ï3éDÑÃŒ¾g8ñÐ3ü‡§‚(zfÁ¬˜1$'I ‹äý×ÓK7ݳ3³3»S3Ý3¿þ|šéê®®®þÖ0ÏÌlMU³fQ¨*uD@ %… ÷4ùj Ó©¥ÄE&@ˆ äªÃÑ#ˆsŒÈÂ…"×^+2w®ˆù:À|1@ª‹ *NM‡#NM—}ö){ä_@¢. t¿DÓ©½ûî»2aÂ9úè£ÍwšC¢~»Ô@ ¢ÕÌèFû›µÈWÿ÷çÌ™3Ý—Îø¦v6Òè.Ë–-3½tMäd‰„Ž"ÑLT@ Õ«{9¹ùlžY@"# ŽêšqøÛ´i“Õ:Ÿx¢ÈÕW‹Ì™#rýõâL]šÕ p1@¼ˆ×áèË/Ën•Žò²É¹)@  Þ{¯ì¶.û:eöE]$5kÖ4ÓV›y«Y@È‘€v8jsí©1i+É:ÊýôÓOiáزe‹¬]»Vš6mÎ R+@ÒØd~*´yó@ó}½ô*ëw”f dG@ ÜÚá¨[·nü­Qæë¼jU°ÌZµDn¼Q̹Áý¤@¨ŠÀ?üàœ;‘é[+{íU•’9@ðè7t¿}÷-_§GÌp²Ó§O7#ÈþYÌL6å3°@, T3×ié¿–™Úl?mk{¯˜O:jKøV®\)Úsš)ÕÂßVÔ@ 59s~2÷•=÷œkþ›Ú9äB@ *únùòåÒ½{wkU^ºTdøð²¡þ7o¶v F@ÀÐŽjÔ¨!mÛ¶õDt„£=„Ïtž €QÐï)5¶ÅNI½~ýzùë_ÿêüîšk®‰úmR@ˆ h‡£ÀGæYépÛãV¿e ¿€Û1ŒGáo+jˆ šÀÿ»Ñd,–®]Í_KY@È3ÝH[ŽÖ¬)û|òdqF 4² € `U@;éwËÅ;þ«_MÿZa:5«ìŽ [n¹E–šà7fÌ©_¿~HjE5@ U º¹ñØhd>ž¥¾œwÞyrâ‰'z'4nÜØÛN¶Ñ°aCçCá¶mÛœl?ý¤£ °„]€Gao!ê‡ ®ÀÔ©úvH¤_¿uéžJ~@B/`»ÃQ£F"^(²Ï>"#F„žƒ "€D\@¿KþñÇåðÃ÷îDG7ÒEc  €ù, KýûßÿîL™}ÖYgåó­ro €п°ÅöôišNÝ›7o.º¦»¬[·NÜÎFzî&~™.aNòÓá('ì\@À¢Àôé LéKÍ—Ó5-^…¢@È@¦;™¶ËMWsíµ¹¹7®Š PxÚÙh³™¿³S§NÞÍët3÷ß/2t¨·‹ @"-pÇ"C†ˆôî¼›o¾YJJJäoû›T«¦“ذ € [j¥¥¥¹ÌLºu6ª´jÕªÀeéÏ"YB/@‡£Ð7DHC`ûv1ó/1g<íÌ{žÆ©dE@ ÚáHG"Þ}÷Ý«\ßW^)›>íÛo«\ € P)NM‡£–-EÎ=W¤C‡JÉI €„J`öl‘Ë.yà`µ/^,ãÆ“}÷ÝWFŽÑßýü³˜sv>®Y#òúëb¾Ø9ñD‘±cEt$ @r!àv8òp”‹zpM@l èç­C)›Rͽ†N)úÐCÉÀåðØžHn&@È@õÙ³gÏ騱ãwfd£®z}óX«F×›Í?ÛªN§öÖ[oŠ0`@ M"œúGÙš5kJƒ ÂYAj… €@š:zß.»ì"õêÕKóL²#€ nNM—ŠF8š2EäÈ#ãß‹ùø'={–u4:øàøyØ‹ €@¶´Ã‘~vs§ Õ±EEb>Óe«\@»Ç#¢«=z´lÙ²…Ñü(l#€„B@§T“ÒÒÒûkc:o:!õ÷ïËäö­·Þ*%%%^‘5’=zxi6Â+ Žš5kÞ R3@Ò ¶¥ Fv@ȤÚá¨~}‘ý÷yá‘?ùî;‘¥KE6lÙ´Iä“ODèl™f§¢ €@^ h‡#ÿèF&ˆÔ­+òßÿæõmss €,ðý÷ßËO|¸ì·ß~Áƒ¤@€ÓáHëa†£}Ð|`{Ö_'ñ¨ZµjSÌôj÷›ŽGüÇRÝ^½zµÜ}÷Ýò›ßüFÆWî´k®¹Æ {kƽe ½€vÓ©ð˜R-ôME@RÐØ¶~ýzb[Š^dCˆŽÀöíÛåÛo¿•îÝ»G§ÒÔ@$:š.þ)Õ¾üRdòä$'q@ˆÌŸ/Ò¤‰Èý÷ï¬ð¨Q£œÄßþö·;ÙB@ DΔj;ê³Ýt8Ò¡†š™ŽF¹u4ÛEfû\ÓñèÓñè5³ý’É÷±yüÜÍã>êš:JÀâÅ‹eÉ’%òñÇËóÏ?/›7ov³=öX1bD`‰ð èèFºÐá(¼mDÍ@Ò¨Q£†¼ñƲÛn»¥w"¹@¹€™]6lذÃÑìÙ"Ï<#rñÅ"µj…üf¨ €F ^‡£âb‘=÷„@è ¼òŠÈÚµeŽôn>üðCyñÅå„N0£ù™áüX@¡€¿Ã‘Ìž={SÛ¶m‡›?¾=múæ¯ïŽŽG‡š}‡j$Óéh[ïÞ½·êèêÕ«'ëÖ­“eË–™9³Í¤Ù),Gy¤¸=sSÈN–4nÜXž{î93D1c‡ 9¨ €@Ìô±2dÈ ”D €„K@§SÓ%ÑGù‹ÈĉbF#9à'+ÿ € jxŽB]a*‡ €@ÚáÈ|U)Æ•¤3Ä›žµ×_}¥@ì :é¥çÍ›gúÏÊ:t¸ÜŒj4Æl—Ë£ùL§£bókI]5™ò¢Ø»òÊ+åÔSOMù2†C@§¾9rd8*C-@@@ $ëpôöÛeŽ?žÎF 9€ :ípÔ¼ys©_¿~èêF…@¨ŠÀ–-bFaÙ‘ DÞÿ}gTöÓO?]:wî\•¢9@«Õ”^jF;ºÕL‘ÖߟhF3Úž _Ê»uT¤C=Tž}öY:¥¬FF@@@ÒÐGú9|ï½÷.wr¯^"—]&rë­å±@Ð h‡£N:9õ3•ü#´U¥b €¤%ðÞ{bf’9üð²Ón¼ñF1ƒBÈUW]•V9dF@ ÛqG/r+a:}f¶Gš)´:š‘‰þl¶ÿǬíÜã©<¶lÙR(Ú —©¸R# € € €UÐGíÚµ“:uê”+¨aC‘Ûo/·› €„V`ÕªU¢«v8š5KäÑGEJKE.¸ ´U¦b €¤, Ó©é¢޾øâ ™2eŠo†¤u;Ú–å_@Â'´Ã‘[ݹsçšqò¿š6Á­¥ñhY{ :ôØš5kv\»v­˜Ñ¤¡ùÖÒ]Í”lÒ¯_?ÑG, € € € -f<þ~øAŽ8âˆì\« € `Y@G7ÒEÿðúØceûÃÊù@¨ h‡£fÍDúô9á„›œÛ¹úê«£~[Ô@ Rêpäw0î›ôSºÎš5«µyìè?Î6 € € €äN@ÿ(«Žºwïž»Jpe@2(àv8êØ±“\z©˜¹Š œÁ P €9XºTäË/EN=UdæÌäÙgŸ•£Ž:JöÙgŸÕˆË"€ º@µÔ³’@@@Â. Ó©éâïp´h‘Èa‡•}‘öúS?@bÜGë×÷’9å‘j|³ËD@ ‚þéÔn¹ågFF7Š`CRe@ @Òá¨@BsÛ7n”ŸþY7n,Õ«G´ù~1œ?™u‹Yw5ëžfõ/›Äl³nݱn‹ÙÖôö«™«]ê™5v¾ö;—̪ǻšõd³ú—ÿgï›Õ-Çÿ¨çhÚ¿46‰»ý;ÌöËf5óÅ;˾æß¿ìØvî2¯›5¶,÷¸>êµtÑG3\¦WžîÓå³>`Vý¥¿YcGÐü?³ï5³ê5´ w5›²Ýëè5žÖƒ¾å?fûžéæ±l´În1›z¯©.ÍMÆ 1™Ÿ5i½F‘YõcÌê_ôšSÌêÞG23-cw³N4«©è>ôšúœð_Ãuñ—ãnë54¿ѱÝÔ¼¦Y™5ÖÊmÍæØ³º‰®³‡Éó¢YýË“&qÇŽ¿ñmïØ%×™ØsÜcz÷Zîv ³/¶ý7ûnßqÒó¨õö/7˜„{ØòüùÜíx÷ῆþâðïnæ×™ÇÉ;¶S¹FE÷ñS–þŸó/Ú>:÷µ–ï¾nÄ>j~÷úzÿê–l äElË6×Cµ@®c[¼G:ÿ«¯Š3*D¨ñ¨ €@(rÛ´ÃQ5ÓÃèí·[;>:   €™ÈuŒÓGÚ‰¶k×…rúéO˜üˉ[£ @¬ T·~.PeiÓ¦É#<"f ;Y¾|¹S^QQ‘4mÚT(Çwœ™×ÕLìš«å[saíôò½YWƬ Mú;³ú—GLâÏ;v 7“vl»÷›‡ÝD ú=Cl‡#í´¤Ltù­YOv¶vþó¶ÙLç{šü±Žfš}ÿ6«.¿š5¶Ã‘º¼aVí “hqécÙ÷%Áœ MR;-i‡ˆxÿ[0û§šÕ¼uVóà]Ï_¶nëÚJ3Ä,kLZÛN—¶Î¿Á–™¤{õÐ%Þ}j´¹fuïí»æ·Ä;^Ñ}èñEfõ_#^9îõ긾ÇMf{…Y7›µƒo¿»©NÚÚ!©†ï1Ñuêš<±‹–½vÇΒ؃&­Ï5÷¸ÿ°{ ÿ£nkcítµqÇÎxÇ1Çô>ýeiv7­Ûþ%Þ}l3Ükhç«ØEïC¯£‹–ë–í>:|ÿÄ«§ÿ>ôz±‹¾\êÿS-³Ø¬Úö±f—wíxeèq+¡mVîšB@òY L±mÆŒÎT:wîìOŸ.òøã"‡.rè¡ùÜ Ü €@&ÂÛ´ÃQ›6ä¹çŠ¥wo‘nÝ2y§”… Pha‰qÛÌwÒ¯™¿¯õí+ò¯ÝêLÍèF…ölä~@h ÄëÂí;Ê£Ú/\¸P®¸â ™®ßÇ,¥¥¥²bÅ ó!û9g2dˆÜvÛmR¯^½˜œ’«L™Ú æÕ«vâpýƒ~#³61k{³¶5kìbÞ8É•fÕ:úP좇´#’>;ÝU; ¸Ûn‡}ÔŽµÌ»œjv˜éœãñ:Ch硱fÕrµ ™n¹f··hžØåB³ãO;vÆ;þOsLת,j¡k¢å~s@ת,g›“uM´èÈ4ºVe©èÿg ×µ*KE׸îkU–ÓÍɺ&Z2Ñæ§›ÂuM´ÜfèZ•åæd]-úCת,§™“uM´dã>tÄ#]YB%ÚØ*%*ƒ %0Æ6á¨cÇŽR³¦ö„/ÕH1;¶ªïñ¢Ô0Ô@ ÒaŒmÆ “9súÈĉæ+dßiTú®9@ Âã>ùDdù±ôÀëå¾ûþ%ûí·ŸrÈ!…ÐÜ# €@žh– üôÓOfèÄÓeÑ¢E)ÕîÍ7ß”c=Öüjõqg䣔NªL¦qæ¤ÿ5«Ž,¢‹vú³YõW²ýÌÚØ¬Úa'Ùr 9¨k¢e_s@ת,ÚéI×DKÝDÒØ¯Œâu4J£²"€…$ÚØVHÀ½"€dT ¬±íP3ŒQ“&ú+3 ì$‘wÞ9çFƒÈhãS §amcM¯ÙáæŠÅæÇƒ'”§øÜ €€U0ƸþýE>ûLdüø»E§vct#«O G° @‡# ¨U-rÓ¦Mræ™g:ÕªUK<ð@0`€ôêÕKÖ®]+}ô‘<õÔS²nÝ:ç’óæÍ“«®ºJxàÑ)׬,::ѱfÕ󆙵µYY@¨@ Ô±­‚ºs@xaŽm÷Þ{¯Så-fjÛË/3®È 7Ä» ö!€ °S ̱Íü6S^y¥ljÐæÍwÖ™-@RkŒÓ?åµm»FžxâéÞ½»é\«Ó° € :…°­&L˜ :/¹»Ô¨QC~øaéÓ§»Ëy8p œp rÚi§y“tÞÙgžyFŽ?þø@ÞŒ%t£g¬4 B(PǶin@ ³Qˆmã̵úÑòÆEøãlfÛŸÒ@|sl{úiíHËtjùøÌãž@ûaŽqwß}·3°€Žndm0ûÄ\@ @*šüª@YrwÛ›7o6C'ŽTছn*×ÙÈÍЪU+¹ýöÛݤó¨oœX@‹±-,-A=@2%…ØfÅuF5jmF¥½øâLÝ9å €ä«@ØcÛ¿Í ë×1"_[€ûB°%æ·~ýzÑGíÛ··7€-XÊE@ÀÐá(dOƒI“&ÉŠ+¼ZrÈ!¡¨#í·ß~Þ9_ýµ,\¸ÐK³ €@.ˆm¹ÔçÚ €6¢ÛÆŒYµJÄü~Ej×¶¡@™ €ù$öØöÒK"“'Óòé9ǽ €ÙsŒÓÎP'Ÿ|²\{íµR\\œ-®ƒ €@Æèp”1ÊÌôî»ï :th (1`À€À¡)S¦Ò$@È•±-Wò\@À–@ØcÛܹ"÷Ü#Ò·¯˜/¯m)P. €@> „=¶5h 2hP>‰s/ €ÙsŒÛm·ÝœŽþÀœ¡Ùz:p@ Ðá(àU-î“O>ñŠÐ¹Z>ø`/lÃ?‘æ£ÃQ2-Ž%xüñÇËMé—(/ûóK`Ô¨QòÎ;ïä×Mq7¡ ¶…¦) ¶"gŸ}¶Ì˜1£`ï¿o|²ùü-·ÜRÈÜ»%°Ç¶+®1?”•;ï1+YòPàb3OÞÇœ‡wÆ-U$ðæ›oÊ5×\SQ6Ž#¶@Øc[Ú7Ä ‘Ð×¶·Þz+rõ¦ÂUøè£ä’K.©zA”€@b\vgEàú믗7Þx#+×â"á8餓dÉ’%᪵AÀ‚@u eRd%暟¡®Ò1ïw,={ö”ƻɤ=zô0Ãä×–_ýÕÉ7gΜ¤ù9ˆ@<µk×JIII¼CìËsåË—ÓöyÞÆ¹º=b[®ä¹®_@_ãtˆj–ÂX¿~½¬^½ºðnœ;¶*…ØvÙe"{ï-rÐAV)(<‡:»ûù?‡ÕàÒ9Ðv÷w”ƒ*pÉ<ˆBlËCvn)F`åÊ•²aƘ½$ A`ãÆ¢ïmX°!@Œ³¡J™éèëwKG,ò.\¸P¶nÝš?7Ä @€ŽÀäb÷W_}¸l§Néd‰5jÈž{îéeÙ²e‹üòË/^š @r!@lË…:×D°)…ØÖ¿¿ˆù%  €) D!¶¥t#dB@ F€B@ 0ÂQ†A«R\ì/Ô6l˜Vq t2sߢåÕ¯_ß·'µÍéÓ§‹¾ ©œJžˆ ´nÝZ¶mÛ&úÈRX»í¶›4iÒ¤ ÿ¯€Õx¦S‚«QõǰĶ®]»ŠÆ·-Zx7¥±GG^oèÿñ6mÚþ¯çõ ssž€¾Ö?ZUæ=±WH„7ô5O¿¼×EèL›™Æ KlÓçµvžmÕª•wcû쳎<üÞÐÿÏ{ì±ÿ¯ó»™ãÞ~Q«k‡âÏ÷ÚáHW]ô³\Íš5óý–³ra‰mM›6ub›÷îÝ»Óá(+Ï‚Ü_¤qãÆ¢ßOéÊRXúÔ¹sgg-¬;/»[ý̦ïëtÙ´iÓï”±dì߰ĸAƒ9ñÌýÞY¿«êÒ¥KÆî“‚Â+ wÑ¿÷jœc),í4¯ñ­;Ïk}o¯‹þHD<`É_:…¨mcßø¤ûØü±=·S½Uý‘ÿ—D©žG>@bÂÛúõë'?þxlõH#€ ¶@Xb›~iõä“O¦]N@@ V ,±M;K?ýôÓ±Õ# €@¥ÂãÎ>ûlÑ• Gàøã/œ›åN Z€yDBÔü±o|Òá¨^½z»aèÍ @Ûr€Î%@¬ Û¬òR8 €@ˆm9@ç’ €Y Æe…™‹ €°ŽBÔøEEEÚ¤;,tì¼õ±# ' €@ˆmY@æ €Y ¶e•›‹!€dA€Ø–d. b\Nع( €@ Ðá(DíÎeèV)Ýù u~_ÿâÎëßÇ6 €Ù ¶eS›k!€dC€Ø– e® Mb[6µ¹ €@6ˆqÙÔæZ €…(@‡£µz“&MµI·ÃÑÆçï¶Ûn4 @²-@l˶8×C°-@l³-Lù €Ù ¶e[œë!€dK€—-i®ƒ P¨t8 QËWõÏŠ+wC‡£ @Ûr€Î%@¬ Û¬òR8 €@ˆm9@ç’ €Y Æe…™‹ €°ŽBÔø±o|–.]šVí–,Yâå¯^½ºÔ¯_ßK³ €@.ˆm¹Pçš €6ˆm6u)@ Ķ\¨sM@l㲡Ì5@ Y€G!jýfÍšjóÙgŸÒÉ:š¿ƒR¯^½¤¨¨(Ù)C@Àº±Í:1@Ȳ±-Ëà\@Àº±Í:1@È‘1.Gð\@ `èp¢¦îÔ©“øßüÌœ9SJJJRª¡vNÚ¶m›—wèСÞ6 €äJ€Ø–+y®‹ `K€ØfK–r@r%@lË•<×E°-@Œ³-Lù €….@‡£=ªU«&Gu”W£íÛ·Ë{ï½ç¥“m¼ýöÛäI € b[.Ô¹& €€Mb›M]ÊFÈ…±-ê\@ ĸl(s @B ÃQÈZĈ?>Ž—X»v­<óÌ3Þ¡¶mÛJ»ví¼4 €äR€Ø–K}® `C€ØfC•2@r)@lË¥>×F°)@Œ³©KÙ €….@‡£=ºté";vôjõõ×_Ë“O>é¥c7Ö¯_/çwžlذÁ;tüñÇ{Ûl € kb[®[€ë#€dZ€Ø–iQÊCȵ±-×-Àõ@l ãlÉR. €"ÅUA=zô1æüžU)ƒsË Ô­[W^{í5ïÀ´iÓ¤AƒÒ­[7ÑáÝeÉ’%röÙgËW_}åî’:ÈÍ7ß,ÅÅUjZ¯<6@È„±-Š” &b[˜Zƒº €dB€Ø– EÊ@£1.Œ­B@ò@à΢ªÜDiiécæüSªRçÆ¸ì²ËdòäɃ­Zµ’ž={J­ZµäÓO?• ŽW¯^]}ôQéÛ·o`? @ @l C+P@L Û2©IY €a ¶…¡¨ €€ bœ UÊD(pVt8 é3 ¤¤D.ºè"™:ujJ5¬]»¶Ü{ï½2pàÀ”ò“ @l Û²-Îõ@l Ûl S> €@¶ˆmÙçz €Ù ÆeKšë €@«*ͻŔjöž*5kÖ”£Ž:Ê™BmÆŒ²eË–„ëß¿¿Œ;Vúõë—0@ȵ±-×-Àõ@2-@lË´(å!€äZ€Ø–ëàú €¶ˆq¶d)@ €˜R- ¿aÙ2eŠ|ýõײtéRÑt‹-¤uëÖ2dÈéÖ­[nƒ:"€ à Û< 6@òD€Ø–' Ém €xÄ6‚ @< ÆåYƒr; €¹`Jµ\És]@@@@@@@@"(ЪZ+M•@@@@@@@@@ Gt8Ê<—E@@@@@@@@ Št8Šb«Qg@@@@@@@@r$@‡£ÁsY@@@@@@@@¢(@‡£(¶uF@@@@@@@@ Gt8Ê<—E@@@@@@@@ Št8Šb«Qç¼زe‹èºuëÖŒÝÛêÕ«eáÂ…-Ó­ÜÆeùòå‘+Û­.KJJdþüù²lÙ2Ù¾}»•ª¬ZµJ¾ÿþ{ùå—_2^>mŸqR D o¢Û´!x«ÚÓÑvŒ#¾U­}8ª.`#¶i­øìVõ¶±U±-¾¬Í÷Lñ¯È^°%@l ÊÂë±-ØænªÚÞ½W(â[°•óý5.ʱM[ÊfûØ,;ø,#UÈÕ ùæ¹w ðꫯʟþô'§*ýúõ“ǼRÕš={¶<÷ÜsòÃ?8MV®\é”S­Z5iÖ¬™ 4HN?ýtiß¾}¥ÊŸ6mš<òÈ#2kÖ,§³‘RTT$M›³®nì@IDAT6•ÊqÇ'}úô ]Ù•ªPO*--•·ß~[&Ož,ï¼óެ_¿Þ+½F²Ç{H«V­dĈòÛßþVŠ‹‹½ã©nüüóÏ2nÜ8™>}ºÌ›7/ÐѨQ£FÒ®];2dˆœvÚiR³fÍT‹õòÑö ¢@Tb›Þ¯q)6jœl¶cñ-:»@ g™Šmz|vËY3Vxab[b"›ï™_•# `S€ØV¦›ï¯oĶÄÿ‹ò½íß9GÈoâ[Yûæók\Ôc›¶Íö±Yv~¿zpw•(ªì‰zžùý˜y8¥*ep.…. ô .•ípôüóÏËèÑ£^°y>\n¼ñÆ”;žè(IW\q…Ó™¥¢²µSËm·Ý&õêÕ«(«sÜfÙ)UÀr&‰áÊ+¯”©S§¦t%ítá…ÊÿüÏÿ¤”_3Mœ8Qn½õVçWÑ´çž{ÊÕW_-ƒ®(«sÜfûØ,;¥›#X{lÓ›·ù:d³l« —Fá¶cñ-Æ +dE ±M+Êg·¬4W¥.Bl‹ÏVïkâß9{Èb›½ï<Ãòì!¶Åo b[|ö"/Ä·üŽoQŽmúÌf ²Yv¾¼>pVZÑáÈŠ+…"šÀš5kœ‘‡6oÞìœn‡#=ïºë®sF6JíŠe¹8à¹÷Þ{¥nݺIOûé§ŸäÄO”E‹%Íç?ضm[g”&ù(Ùb³ìd×ÍÖ1ÎläÈ‘iÙ¹u»ë®»äðÃw“ o¿ývyðÁOt@;(}ôщ;ûm¶Í²“Þ@ +amŠ`óuÈfÙYiÀ.b;ÆßRh² €@VªÛ´²|vËj“¥}1b[|²Bx_ÿÎÙ‹@þ Ûì}ç–g±-~KÛâ»°| ¾åw|‹rlÓÿc6cͲóåõû°&@‡#k´Œ@›6m’3Î8#0rPºŽþùÏÊwÞ¸R¯^½dذaÒµkW©S§Ž3ÚG}äLéåϨÓw;Ö¿+°­õ;öØceæÌ™ÞþZµjÉ( ½ÎÚµkEË~ê©§dݺu^¾ƒ:HxàgÊ5o§oÃfÙ¾Ëätóÿ÷åµ×^ ÔA]zöì){ï½·ì¾ûî²`Áyÿý÷cÛ¶móòj»é/ŸÛ´iãí‹Ýøä“OäÔSOÕ‘æ¼C}ûöu:éHIÚ™LËÿæ›oäÿý¿ÿ'¿þú«—¯víÚòì³Ï&œ^ÏfûØ,Û»A6@ gú<̱Mal¾Ù,;gçÂ6cñ-8»@ §™ˆmz|vËi3Vxqb[y¢By_SþÎÙƒ@þ Ûì}ç¦g±­|kÛÊ›°| ¾å|‹jlÓÿg6cͲóé5‚{±&ЪJ%ë”jfeA4LÇœÒçž{®Ôtæ)íÔ©S`=ùä“S.É XÚ»woïü.]º”ÞsÏ=¥¦ãJÜ2>üðÃÒzùõÚÓ§O›WwšN*¼ÝºuK˜ß ÓWj¦S äÿ÷¿ÿ“²^4‹¾úê«€EçÎKŸx≄5øñÇK 8ÇL­–0¿yóPj¦E ä7#V•nß¾=î9‹/.5ÌùO:餸yu'mŸ† @ *±M«Ïk\‚FLq·ÍG|K±ȆYÈTlÓÊòÙ-+MVé‹ÛâÓÙ|ÏÿŠìEÛĶ2áBx}#¶ÅÿßTmÿÎÙ‹@~ ßÊÚ7ß_ã¢Û´…l¶Í²óûÕƒ»Ë@ËjUêqÄÉ P¡€ùÏ*wÜq‡hÏÛ#p覛n’>}úö¹‰V­Z‰Nâ_&L˜àOzÛ6Ëö.’ãÿüç?Œ3F~ÿûßöù: Ý}÷Ý'Õ«W÷vëÈD‰–ï¿ÿ^L'"ïð>ûì#çŸ~Â¥Z´hጄU£F ïœ/¿üÒéQííØ±a³}l–{¤@À®@c›ŠØ|²Y¶ÝÖL¯t›1Žø–^[2+`+¶i-ùì–Ù¶ÊtiĶò¢…ò¾¦ü³ü ¶•oÏBy}#¶nÛ—¿sö Ä·òmZñ-ª±M[ËfûØ,»ü3=Ĉß3!~^ö"€@%̨3Nç^köìÙ²eË–J”ÜKÇÛÐÎHûí·Ÿwè믿3ò‘—v7l–í^#×S¦Lñª°Ç{È1Çã¥m˜¤ÄŒ„ä^´h‘¬_¿ÞKû7¾ýö[RFŽ™°³‘›±C‡öÙºu«Ì˜1Ã=ì=Úl›e{7ÀdE бMal¾Ù,;+šâElÆ8â[ù÷M)6 Ù@ 6b›V‹Ïnñ?f É2V±­|ü)”÷5{Q! ¶îë±­pÛ>¤/GT Œ ß ó5.ª±MŸü6?_Ù,;£ÿq),¯èp”×ÍËÍå«€vFÑ^«î¢ˆ´ÓQ*ËÈ6uêÔ@Zï¾ûn`Ÿ¿“Rà@LbÀ€=þ7î›e»×Èåã/¿ü"ººËÁœpÔ)7ûèïp¤ûæÍ›ç <þðÃt»víéD‰Ø|«W¯.—ÕfûØ,»Ü°"'`;¶)ˆÍ×!›e‡¥1mÇ8âÛÎËaisêU°ßlÆ›eW]63%ÛD ñs{fž=”‚@á Ûâ¿v†åAl‹ß>…ð¾&,ÏAê@Tˆoñ_?ÃОQŽmêg3Ù,; mO¢!°sþžhÔ—Z"9âì¶Ûn‹[oEhìØ±q%Û©#%ù’+ÕeÏ=÷ d6mšwÜq}Ÿ|ò‰—.**í4“ÊâáHóë—çž{nàT›e.”£DìˆQ:Ý\ªKìˆPM›6{j£Fû—.]H'JÌŸ??p(ö¹ m¶Í²7F¬ D1¶)ŠÍ×!›e[oÐ/`;ÆßÊ¿oJ±iȆ°Û´Z|v‹ÿ¹0M–‘"ˆmñÛ§Þ×dä D!„\€ØVþýu!¼¾Ûˆm!i¢zTY€øVxñ-ʱMŸð6ߨ,»ÊÿY) `èpT0MÍæJ@;ìŒ1"îåçÎ[©Gzžiݺµ?™t[§øò/ß|ó?)ZöªU«¼}={ö”Æ{éd=zôÚµk˯¿þêd›3gN »Í²Êa¢~ýú2jÔ(¯p€·lC§Úûꫯ¼,»îº«4oÞÜKû7:vìèOŠvÓiÕ’-Ë–-“Ï>ûÌËR³fM‰ípd³}l–íÝ 5¨Å6…±ù:d³ì¬5j ²ãˆoÁ÷M)4 Y@ ƒ6b›VOc„á³›_#÷ÛÄ6‘BüÜžûg5@ ;Ķàûk>·%Þ¥úÝ$ŸÛ‚Ï«äªEÄ·àëP!Ä·¨~nÓç¿Íö±Y¶ÿ»”™¿L©–¿mËå±@½zõwWRRH'KhÇÿ²fÍ2ÐéEtêÔ)pÿèFº³aÆޱT64hÈæ/Ï¿­™2Yvà¢J,Y²DF-ÚáÈ]êÖ­+þóŸÝd¹G}ã{Ýu×ö_{íµrþùç˧Ÿ~*ëׯ—ÒÒRÑ©Ö^~ùe9òÈ#åƒ>ðò뛳ةîô Íö±Y¶wcl €@¤lÆ6…±ù:d³ì(7jº1ŽøVþyåö§î P&`3¾ÙŒ?6ËŽòsƒØVqë%ûN â³ÉQ ¶•µRl¬ŒBÛÅ«#±-žJp±-èA | ¾•µl>Ä·°Ä6õÌäßEm–¯ÿϹ/;L©fÇ•R°*ûÆç‹/¾Hùz3fÌ(—WG9ÒN(ºüüóÏãé?ÚпhÀk×®³ËfÙþk†u[G0úë_ÿêL;·páBùî»ïdíÚµêvïÞ]n¿ývÙm·ÝûcÆ “ñãÇ;´c‘.o¼ñ†³ê¶Ž6¥¿T]ºté"÷Þ{oÜÎ^6ÛÇfÙ±÷H¢)`3¶©ˆÍ×!›eG¥53ãˆo;ß7E¥í©'$°ßlÆ›e' ÏQb[Y[dò;ð´.5AªÛÊôüßyVÅ3›çÛÊ´‰mÙ|Öq-¢#@|+k«¨Å·0Ç6µùÙÚfÙÑùŸKMà ÀGahê€@š5’V­Zyg}üñÇòá‡zéDÓ§O—‰'–;¬#â¸Kl€Šý‡›/Ñcl~[›e'ªO˜öoݺU&Ož,&LpFŠíl´×^{É< ú˜ÊrðÁË#<"±æzn¼ÎF»ï¾»<üðÃÒºuë¸ÅÛl›eǽv"€@älÆ6Űù:d³ì¨4d&cñ-*­N=@ ›ñÍfü±Yv*naÈCl+k…xŸ7“µOl~ÿwÉÎãDG€ØVÖVQ|}#¶•µ]l¬ªè_lþ(¶}E÷Èq!¾•= ¢öæØ¦¢6?[Û,›×Ò ÃQ:ZäE D—_~y 6×_½Ì™3'°ÏŸÐczŽNµ»øG%Š Péþâ#vžÛd™2Yvì=E1=wî\9äCäž{î©°úÛ·ow¦a;úè£Ë½aItò²eËDóO:5nÚ>. ;@ ‹¶b›Þ¯qYlÈ8—J5ÆßvvÃÈ.ˆ¨€­øFlËí‚Øß?ÙwñÏ`/DQ€Ø&âÿÎ3Šm¯ÎĶx*"Ķø.ìE ˆoùßrÛôÿŸÛóñ•‚{Š`JµXÒDDà°Ã“ƒ:H¦M›æÔXƒæÈ‘#åì³Ï–^½z‰ÿ¨ÓjÍš5K^ýuyúé§eÛ¶mNÞš5kÊæÍ›½;õwü)**òöë†æMg‰YÇÿ ›e§SÇ\åÕö8çœsDV®\)+V¬m·Å‹{U*))q¦<Ó^ä×]w“×;èÛÐfÚ¦þ¥M›62tèPg„$’mÁ‚N'´—^zI6lØàd]¾|¹ó¹øâ‹åü£ÿôr×¢í<$@ ¶b›VÝf ²YvØ3r‰LÅ8â[ƒŒ´… €@¸lÅ7›ñÇfÙájĵ!¶•ÙdòsabmŽ €@ÔˆmwÄñ°·#±­¬…ˆma¦R?r'@|‹^| slÓg²ÍÏÖ6ËÎÝÿB®E:E±Õ¨3;´CÊÉ'Ÿ,Ú‰D«ôÞ{ïÝq4þC=œ)µ¦L™âdÐ_hh@v—¦M›º›ÎãºuëéŠZÿ¢ÃPº‹Í²Ýk„ùQ?Ì^zé¥*êˆS|ð3•Úûï¿ï{ê©§dÿý÷—Ã?ÜÛçn<úè£ÎFÅÅÅrÑEÉé§Ÿ·ƒ˜»ýöÛÓéé(J:šR‡ÜbÅfûØ,Û»6@ /lÄ6…±ù:d³ì¨4j&bñ­løî¨´9õDôlÄ7›ñÇfÙéÉå.7±­Ì>“ß ä®5¹2Ø ¶íüÎÓ†¯2‰meªÄ6Ï.ÊD ˆoÑŠoaŽmú¿Âægk›eçÏÿhî$L©– e®€%Ö­[‹Ž^3bĈ”® XÆ'K—.õòû;éÎ&MšxÇt#Ý`7n œ¯#í¸‹Í²ÝkDíQ{ xà2~üxéß¿ úÚV±‹ŽLõàƒv_pÁÎÈIúÆ*Þ¢î·Ür‹3"–{\çµ½á†ܤóh³}l–¸  y±MQl¾Ù,;Ê šNŒ#¾•µ´ÿ}S”Ûžº#€@yñÍfü±Yvyèì!¶UÜVɾ¨ølr €@”ˆm;¿óŒR»ÅÖ•Ø+R>Ml+oÂòY€øýø–ئÿOl~¶¶Yv>ÿçÞ2/@‡£Ì›R"YЊn»í6§#Ñ‘G);v”êÕË/ÓÇ®]»ÊqÇ'wÞy§èÈÚãuÞ¼y^›7oîmëFU”Næ_ü8³Y¶ÿšQÜÖQ¦îºë.©VmçËò÷ß/Ë–- ÜÎ[o½åLÅæîÔ©ób§Fsùõ –v:òfõÉ'Ÿ¦Ö³Ù>6Ëöß'Û ™ŽmªbóuÈfÙùТ©Ä8â[YKûß7åCÛs Èt|³l–T‰fŠØ–¸Ý’}'ø,Ž €@TˆmQm¹òõ&¶•7q÷Û\ (â[~´u®c›*Úülm³ìüxpÙ`JµlIs, 2DtÕeË–-²dÉÙc=ÊM±µpáBY³fW›ýöÛÏÛÖØå )1AB¯ë.Úá©~ýúnÒjÙÞE"¼¡£MµmÛVæÎëÝ…¶×î»ïî¥çÌ™ãmëFß¾}E§TKeѶÕ)Ô¾ûî;'ûöíÛåÇ”Î;;iÚ>Eò €@62۴μÆe³åÊ_«¢G|§Ã¸ÿ}SyEö €@¾d*¾ÛrûŒ ¶Å÷Oö@ü3Ø‹ù @lˇV,›â9Ùw“|nãs[~<Ó¹ R ¾¥nÖœ¹üܦ&|në3ƒzeR`çP™,•²@ §Úk·M›6å:i¥¦OŸ¨Û€éfÍšÒŸ}öY ,¡ÃËú;(õêÕKtdw±Y¶{\?4Hô¾u6lXÚÕq;ÿ¸'®]»ÖÝt/^HwêÔ)®(›Á‚Þ)6ÛÇfÙÞ °y-P•ئ06_‡l–¦Fµãˆoâ¼wð¿o SÛS°'P•øf3þØ,Ûžfú%ÛÊÇŸBiûôŸ-œ© ÛR•²“ØFl³óÌ¢T ¾åî9ÕØ¦b6?_Ù,;w­Í•£(@‡£(¶u.xÒÒRùõ×_½UG4Juyï½÷¼¬uêÔ‘}öÙÇKë†vHñ©™3gJIII O¢„vNÚ¶m›wxèС޶nØ,;p¡&t4"·m´3ÏúõëÓªMìœà{íµWàüØ©Vbó2ÇIÄþ!Ó?z’Íö±YvœÛdDPÀflS›¯C6ËSSÚŒqÄ7‘Ø÷Maj{ê‚•°ßlÆ›eW^3ógÛÊÇŸBiûÌ?›( ¶•í SëÛÊ·±-LÏPê‚@xˆoå_?ÃÒZQmêg3Ù,;,mO=¢!@‡£h´µD ðóÏ?{£èèH:—\rIàx¢„v~yõÕW½Ãûï¿¿3}‡·ÃlT«VMŽ:ê(o—N»åï¤äˆ³ñöÛoö<8¶YvàB9LÄvr§/KµJ3fÌð²î²Ë.Îk޳ѵkWR´CX:‹?¿¶GÇŽ½Óm¶Í²½`"-`3¶)ŒÍ×!›e‡©QmÆ8â›Hìû¦0µ=uAÊ ØŒo6ãͲ+¯™ù3‰måãO¡´}æŸM”ˆ@áÛÊ¿v†©õ‰måۇئg(uA ¼Ä·ò¯Ÿai­¨Æ6õ³ƒl––¶§Ñ ÃQ4Ú‰Z"hذa`¢>úH´cPEËSO=%þqN:餸§Œ1"°üøñt¼„NýõÌ3Ïx‡t¾ïvíÚyiwÃfÙî5rùØ¡C‡ÀåŸþù@:YB;l­X±ÂË¢Š‹‹½´nÄþAöÍ7ß”•+Wò$J,_¾\fÍšåÖ6ªU«–—Ö ›íc³ìÀM@H ØŽmŠbóuÈfÙaiP›1Žøÿ}SXÚžz €@ålÇ7›ñÇfÙ•Íì™Ä¶øñ§Ú>³Ï$JC °ˆmñ_;Ãò, ¶Åob[Xž¡Ôð ßâ¿~†¡Å¢ÛÔÏf ²YvÚž:DC€GÑh'j‰@9.]ºxû´çõ»ï¾ë¥ãm|ÿý÷rï½÷z‡öÝw_9è ƒ¼´CËö|óõ×_Ë“O>éÏØÖ‘“Î;ï<Ù°aƒ·ÿøã÷¶ý6Ëö_'WÛ#GŽªÎ]^xáyíµ×ÜdÂÇeË–ÉW\8>|øð@ZmÚ´}ãë.ëÖ­“1cƈ÷™lÑ©î.½ôRñO¿wÄG”;ÅfûØ,»Ü°") ¯î’騦åÚ|²Y¶k’ëG›1Žøÿ}S®Ûœë#€@flÆ7›ñÇfÙ™‘­z)Ķøñ§Ú¾êÏJ@ °ˆmámb±-¼ÏNj†@øˆoál£(Ç6µùùÊfÙá|6P«0 ‡ÎH³†£G>ÆœÒ3ÍÓÈŽ;Ö¬Y#O<ñ„çѲeK9æýoUñR»vm™2eŠ—ñõ×_—Þ½{K«V­¼}îÆ+¯¼"üã£;VZ´háf)÷X·nÝ@G™iÓ¦Iƒ ¤[·n΀î K–,‘³Ï>[¾úê+w—hoã›o¾¹Üè]t‘Ó™Å=¡fÍš2`ÀÑrtNSíh2}úôr£éy:"QEËe—]&“'OdÓM={öt¦âúôÓOeÁ‚ãÕ«W—G}TúöíØ›°Yvìµ²Öië=ôPÑ)Ìü‹Úh»hã5jȼyódΜ9¢ÓÑù!IGFŠ×yÌÍ÷÷¿ÿ]Æç&G-S;éTvÚ™L§gÓkèUþEÿ¨ûôÓOK¯^½ü»Û6ÛÇfÙ› 9{lS›¯C6ËÎIƒÆ\ÔvŒ#¾Å€“DPT5¶éMðÙ-M·͏,ÎÎ|_“øÎ9‚@þ Ûì}ç†g±-q+ÛÛp| ¾åo|‹zlÓÿ_6cͲóáµ{°*ЊGV})äU}ó³zõj9õÔSEG¸Iu9묳œÑnRÉ_RRâ|1>uêÔT²;¿ÜÕiÛXa~›eWxñ,dX¸p¡3EšvøJgéܹ³\ýõÎhUÉÎÓ‘“F%Ï>ûl…Ó©ùËiܸ±\wÝurØa‡ùw—Û¶Ù>6Ë.w#ì@¬ „=¶)ˆÍ×!›eg½1\ÐfŒ#¾%@g7äT ª±M+Ïg·œ6a…'¶Å'*„÷5ñ俱ÍÞwžayöÛâ·±-¾ {Èâ[~Ç·(Ç6ý?f3Ù,;_^¸k­ª4®µ™î‡)Õ¬µ ‚@&†w<þøãŽ>Ÿþ¹èô\‰õæÚk¯•3Î8#Q–rûuĤ£Ž:Ê™BmÆŒ²eË–ryÜýû÷w¦èÒÑ•RYl–ÊõmçÑéçt^Y½O Jÿ€šl©_¿¾Ól̘1I§ºsËÐQІ*Æ “¥K—:#¹Ç=j}tT¤îÝ»'Êâí·Ù>6Ëön€ È™@Øc›ÂØ|²YvÎ5æÂ6cñ-›$„B ª±MoB§Uã³[(š3n%ˆmqY¬¾gŠEö"€@¶ˆmö¾óÌVVtb[|¡BøÌÿÎÙ‹@aßò;¾E9¶éÿ@›1ÈfÙ…ñêÁ]VA€)Õª€Ç©„J`Ù²eòÑG9Ot­%K–H³fͤmÛ¶²÷Þ{;S|W¾á† dÊ”)Îô\ÚÁEÓ:mWëÖ­eÈ!Ò­[·J{Ø,»Ò•Êà‰+W®”™3gŠö®×)Ô~üñGçmÚ´q¦?ÓGm#ítTÙåÛo¿•o¾ùÆ){þüùÎtn-[¶t¦XÓiÖt·:Tªx›íc³ìJÝ,'!€@¨lÇ6½Y›¯C6ËKCÙŽqÄ·°´4õ@L ØŽo6ãͲ3i\•²ˆmñõ ¡íãß9{@ b[*J¹ËCl‹oOl‹ïÂ^Ø)@|Ûi¶­(Ç6µ´ƒl–¶çõ …Sª…¢¨ € € € € € € € €ÑhU-õ¤– € € € € € € € € :…¡¨ € € € € € € € € ÃQDŠj"€ € € € € € € € :…¡¨ € € € € € € € € ÃQDŠj"€ € € € € € € € :…¡¨ € € € € € € € € ÃQDŠj"€ € € € € € € € :…¡¨ € € € € € € € € ÃQDŠj"€ € € € € € € € :…¡¨ € € € € € € € € ÃQDŠj"€ € € € € € € € :…¡¨ € € € € € € € € ÃQDŠj"€ € € € € € € € :…¡¨ € € € € € € € € ÃQDŠj"€ € € € € € € € :…¡¨ € € € € € € € € ÃQDŠj"€ € € € € € € € :…¡¨ € € € € € € € € ÃQDŠj"€ € € € € € € € :…¡¨ € € € € € € € € ÃQDŠj"€ € € € € € € € :…¡¨ € € € € € € € € ÃQDŠj"€ € € € € € € € :…¡¨ € € € € € € € € ÃQDŠj"€ € € € € € € € :…¡¨ € € € € € € € € ÃQDŠj"€ € € € € € € € :…¡¨ € € € € € € € € ÃQDŠj"€ €”˜8q¢yëÓO?]>{@(0B‹O>ù¤´lÙÒ[-ZT`-Îí"€ € € €Ù¨žýKrE@@@@2#PRR"K–,ñ Û¶m›·Í € € € €€F8²ãJ© € € € € € †À¨Q£¤M›6Þºxñâ4Î&+ €Ñ öE¯Í¨1ì`„£l!€ € € € € €@ŽÖ¬Y# ,ð®Î¨u €y*@ìËÓ†å¶(F8*†æ6@@@@@@@@È„Ž2¡H € € € € € € € €ˆŽ ¤¡¹M@@@@@@@@2!P=…PD[`Ë–-2þ|iÑ¢…ìºë®½™uëÖÉÂ… eùòåÒ AiÓ¦4nÜ8£×X²d‰Ì™3Gêׯ/{íµ—Ô«W/iùK—.uêTTT$ûì³Ô¬Y3iþt†©.éÔ›¼ €@¾ lݺU,Xିþú«ì¾ûîÒ¾}{'fT垉o¹‹µUi7ÎE(ˆj|,--•Y³fÉ¢E‹¤gÏžÒ¤Iš@¸U‰aú~/Lu‰ ÍN@Фû¶mÛæ|_:{ölÑïL»uë&íÚµ“jÕ27V 1,4O *‚€U:Yå¥p*'пÑ`_Ù¥iÓ¦òòË/'=ýÛo¿•ýë_òá‡ÊgŸ}&7ntòk§£SN9E.¼ðBiÙ²¥èÑúÓŸ¼²Î:ë,éÛ·¯—Ž·±}ûvyä‘Gä±Ç“iÓ¦•»—.]ºÈþð9óÌ3¥yóæñŠðö½ýöÛrÙe—yé;ï¼S $6lþóŸ2vìXÑ7-þeÀ€rã7ÊÁìíÖ:Ýÿý2~üxùòË/½ý»ì²‹ôêÕK8à¹þúë“þ:Luñn€ @ BÙˆo.ÇŠ+ä®»îrbŪU«ÜÝΣv4=ì°ÃdÔ¨QÒ¯_¿À±d âÛN[±vçØB G€ø¸³­g̘!§vš·ã¾ûî“ýöÛÏùL©ŸÇŒ#¿üò‹süÁý|Z™E?OžqÆÎWÜóõsá¸qã¤Fî.@’d2~Ý{ï½Îw‰z9ýÁˆ9ꨣ¼ sÌ1rõÕW;‡+3Âôý^˜êâ7g@ ¾@TcŸÿnôïcW\q…¼õÖ[²yófÿ!g@‚®]»Ê¡‡*£Göâo ÓŽ1,ž û@ mÓSò1³² €@†Š‹‹KÍÈJ¯{ì±GÒ=ùä“¥uêÔIZ¾éˆS:iÒ¤RÓ³9ï©§žJZöW_}UjF œ“è^6lXj:=%-ïù矔¥uš;wn©yÓØïzŸº,[¶¬ô ƒª0¿ùãiéúõëÖ'LuIXI €!°ßb_›5N}òÉ'¥ ãÅÿ>óÅÒx %1â[ü÷%™Žµ)5™@< >îlÐ>ú(¿_{íµR3ª`ÜÏs¦Ã‘w¢ùaIà¼yóæyÇb7ô3ßo~ó›@þ>}ú”šʱYI#€$Èdü2ø ¼.û?·ù·Ï9ç¯F•±Ÿ!ù®Ñ#e@ ¨Æ>½-3ÓI© ÔŒ`”RÌ5”þøã EÂOV’ –™ͼógAp è¨I]t‘üþ÷¿—’’’¤•Ý´i“{ì±òÜsÏ%Íç?øÁ8£ùGrÇ›ªmíÚµÎ/Ru4¥TÍhðàÁòÝwßUxŠùB>ÿüsùío댴TÑ ï½÷ž >\ôÞSYÂT—TêK@ ~øá9üðÃE§Ïô/æ ÒÙÖ)EÏ?ÿ|™>}z¹cþÄ7¿FpÛv¬ ^ €@e¢uÄÝ£>:¥Ïs©Ø˜ÎFrÄGˆþ×]t¥7ÞxCvÛm7w €¨lÌÓ÷{aªKŸT(8tbŸŽøÐC‰Žàî.:EµŽôÚ©S§r£}úé§Ò»wog–7²GbX2Ž!ßL©–ßíËÝETàoû›˜.‡)ÕÞürSÌè ¼Ã† ¤Ý„NA¦Ó˸‹ÒI'9CÖ·oßÞ>ÑŒ !æ—=2aÂÑ?ÄêÔg©,?ÿü³Œ1B´‘»èЋ:ä½~ÛªU+™?¾óæäÅ_”ÇÜÍ&÷ÜstìØ10u›w0fãÒK/u¦SÓÝÚqJëg~ê\÷ý÷ßw:T¹uÐ/“õÚú¦KýYßTxà²×^{É¢E‹ä‰'žüãÞБo¾ù¦Lœ8QN8áçœdÿ„©.ÉêÉ1@ ,¶â›ÿþn¸áïƒóСCE_«õƒ³N7ªU§N*ùË_œ¹ÉõÿŽØ/’õK3ª…?K`{óæÍ¥Õ«W÷êbFf wñÞ@åª.nxDòM ÝøïµùÜsÏ­%6†¾óÎ;åÎ!¾•#ñvØŠµÞØ@J|Œ÷Çcý|¶zõê€Gl"Y‡£5kÖ”š_ðzŸ÷ô3«™¦;agãØ²I#€T^ Ýø¥WªJ‡£TbF¼Ï¹ú~/Lu©|+s& €€_ Œ±Oã£û÷»!C†ø«w[¬éæ×Ç;\>bX9v P¨-«™ ˆ À5×\ãLýåV½víÚNÚbØÝ¯:ŒÅÇÛ¥Ó—uÖY^:ÑÆyç'Í›7OtØÛÕUWyS’‰ù²WŠ‹‹½ã‰6ô<ÓÈ;üðÃ{Û‰67n,zïÉ–Î;ë´k]ºt ìó'tj¹¶mÛz»~úé'o;ÙF˜ê’¬žC¢$N|‹w_:}æÍ7ßïP`ßÀéx¯ýÄ·Q ‘­X¸( @ € 5>j“ë95ªTë›ÎFrÈ!‡ˆNî.:¹NÏS§Nw €–ª¿Ò­VebF˜¾ß S]Òµ'? €@™@ØbŸé%³fÍòšçÛo¿Ó+ÂKÇÛ0£ÁŠédä|Ǫ߳ê´Ö-İЄ8Ž@þ Ðá(Û–;Ëc3ÊÜtÓM;|衇¤oß¾}nÂŒî#%%%nR†žR‡ 3íšœþùÞy‰6ÌÔlÞ¡öíÛ˾ûî륓m4mÚT>ø`/ˤI“ÄLÃæ¥ãm˜©Ñ¤aÆñyûôÍþ¥GþdÜíúõë{ûͯg½ídaªK²zr ˆŠ@ºñ-Þ}éä©üQ²I“&ÓÍP´&ˆoåH¼ÙеÞÙ@ X ã£~¶ÔB•YV­Z%C‡•éÓ§{§qÄò /ˆþ`‡@À®@&âW:5¬lÌÓ÷{aªK:öäE(cì«V­šøÿF¶lÙ29çœsdÛ¶mI›í’K.‘+¯¼ÒYõsUE 1¬"!Ž#¿t8Êß¶åÎòT@™yæ™gîN{LŸxâ‰}þ„™ÆŸ”ßüæ7t²ÄÞ{ïì°èˆk×®õò˜éÔ¼íT6üotÌÔf2oÞ¼¤§í¹çžIëA±È¿h'¨tíñʦº¤R_ò €a¨L|‹w?íÚµ‹·»Ü>GS=èiâ›*$^²k×€# €@az|ìÕ«W¥Z㸙*@>ÿüsï|]÷ÑG•ZµjyûØ@°#©ø•Ní*3Âôý^˜ê’Ž=y@ÄU5Ý¿ÝUÕ-ÕØg¦”\êÁ9Ú¡è믿«l‚VY9ÎC úÕ£ Ü…#°dÉ9úè£eãÆÞM9Rn¸á/o#¶Ã‘N©–êÒ¦M›¤YgΜ8>cÆ 9õÔSû’%¾ÿþûÀáE‹I²NNÕ'PØŽD‹-âí®ò¾0Õ¥Ê7C €@*ßâUÙ?Ef¼ã©î#¾¥*U–ÏV¬M¯äFòK€ø(’ÎgWëëçæÅ‹ûw9Ó€5Jî¿ÿþÀ~ €™ÈdüJ§f•aú~/LuIÇž¼ €@¡ „=ö]{íµ2mÚ´ÀTÓZç[o½ÕYu6’Aƒ9ÓQ먰•‰G•9‡ï ý÷Ÿ/t8Ê—–ä>ò^@;é—¦ú&À]tÞÔÇ{LŠŠŠÜ]qc;¥2ÕŒ[PE½’ãýAV;Uvùõ×_“žZ™7 :d¤%Lu±q”‰dC *ñ-^ýZ¶lowÚûˆoé‘ÙŠµéÕ‚Ü €@þËÚ²zõÊ}mÛÙÈ}fŒ?^N:é¤ÀÔÞî1@ª.éø•N*3Âôý^˜ê’Ž=y@BˆBìkР¼öÚkrÜqÇ9±í¥#Ä>ûì³ÎªÇtP€N8AÎ?ÿ|iÒ¤Ilö¸ibX\v"Pvþ _tÜ$ÙСu8bwiÖ¬™Lš4IêÔ©ãîJøûekÆ æ=Pчõ ÄžR¥´¾9K¶';œÕcaªKVoœ‹!€¨J|‹WŠâV¼sâí#¾ÅSa €@¶ˆ™‘>å”Sä¯ý«WXii©œ}öÙQƒ½ƒl €TY Óñ«ÊJ¡€0}¿¦º¤@G@#•اŽ^}õUg¤£ÓN;-iG¢o¿ýV®»î:gÚµ‡~8¥v&†¥ÄD&òR r?ËK n ð ÜtÓMòÔSOy¬Y³¦<÷Üs)kÛ)iÍš5Ò¼ys¯¼dË—/OvXZµj8~î¹çÊï~÷»À¾t=zôH';y@",PÕøfóÖ‰o6u)@ ™ñ1™NêÇ.ºè"¹óÎ;©Ô&L˜ ³fÍrNÖÇÑ£GË-·Ü’zaäD¨P Ìñ«ÂÊ“@JD1ö 8Ptݾ}»|ôÑGòæ›oÊÛo¿-ï½÷žÄÎ@¢iýÁ†€pä‘GVBˆS@ èpT­Ì=FZ`âĉrÍ5×îáþûï—ö%KÄŽh¤£6¤ÚáháÂ…ÉŠ–N:Žkg¨aÆö‘@@ V ñ-¶ÌL¦‰o™Ô¤,@Tˆ©J%Ïwà 7ȨQ£œL»ì²‹Üwß}Ï©wÜq‡3E@ïÞ½“ÄQ@”¿Rº 2!€ †@Ôc_µjÕä€pVvÓ¦MòÎ;ïÈóÏ?/O<ñ„¬[·ÎÑØ¶m›\pÁt8Jã¹AV M€)Õ ­Å¹ßH |õÕWrê©§Šûî.—\r‰œqÆn2¥Ç6mÚòUԉȟù¿ÿý¯?Yn;ö²3gÎ,—‡ €ø2ßüefz›ø–iQÊC¨H€øX‘PêÇÿð‡?2rÈ!òûßÿÞÛ·uëV9묳DY@ª&…øUµ;äl@‚ùûô‡‡z¨Œ7NôþüWœ?¾üôÓOAR €À:ñT@ ¤¼GŒ!ëׯ÷jxøá‡Ëm·Ýæ¥SÝèß¿ ëäÉ“éD RqÒ¤I‰;ûu¤$ûÕ]>ýôÓrÃ.ºÇâ=ž|òɲ÷Þ{;ëÁè\/?û@¢-ÉøfS‚øfS—²@bˆ±"™OëôjþÑ?ÿüs;vlæ/D‰ €@ D%~P“p« €–¢ûtÚ7÷op±+LDÕ¶m[¹ð ‡¿üòË@š à ÐáÈ•à lÞ¼Y~÷»ßɼyó¼ZuéÒEž~úi)..öö¥ºqàŠöNvQ§U«h?~¼Ì;·¢l¡éW­Z%<ð@…çh†×^{Mž|òIùî»ïœµ{÷îRTT”Ò¹dBˆž@¦ã›mÿ¡Ä7ÛÚ”®ñ1;m¯‰o¾ùæÀÅ®¿þza”Þ @ e¨Å¯”oŒŒ €$ˆbìÛ}÷ݽ¿Á}üñÇ¿;&¸Mg· ÝѲeËdÙ9†,@‡£n|n=¼çŸ¾L›6Í«`£FDG%Š ð^† 6ô|IÈ]¶lÙ"úÓŸdãÆî®rúÆãÊ+¯,·?ÞýUhíÚµ½C·ß~»¬X±ÂKÇÛØ°aƒ\~ùåC§œrJ M@ ¿2ßlëßl S> €€ ³÷<8çœsÄÿ«^ýL|öÙg3Ònöš€+!€@ ØŠ_ÕªÿdQÑwŒyDÊ­ €„\ б¯_¿~Õûî»/N”xýõ×½CuëÖ•Î;{i6@¿@u‚mȽÀ]wÝ%ÿú׿Ñ/@u¤¡TFrOìÓ§4iÒÄMÊÕW_-ÿùÏä—_~qö½ð 2hÐ y衇¤[·nÞÈBk×®•|P®»î:ÑNA©,:—ëUW]%×^{­“}Ñ¢EÒ·o_yþùçeß}÷-WÄôéÓP?üðƒwìÌ3Ï”8ÀK³ _¶â›M%â›M]ÊFPâcvŸúGìûï¿ßù¼ºmÛ6çâS§N•þóŸòÇ?þ1»•áj €@„lÆ/‰Á¿Üzë­2aÂï»Kÿ1¶@È–@TcŸþý¯W¯^òÅ_8TwÜq‡Ô¨QCFí<Æúmß¾ÝVg\q—#Ž8Bb;»ÇxDèpÄs h]n»í6Ñ5eÊ”)¢oÜ¥}ûöòØcÉqÇ':ì£.Ÿ|ò‰ôèÑC6lèÌáªÓÅè4n›6mrO“ .¸@þñxéD:ZÑã?î G¿páBѩܴѾ™éСƒÌ™3GtžW=IGYr}ÃsÏ=÷¸I@òPÀV|³ME|³-Lù €@a ³ßþúùô /”ÿû¿ÿó.~ÅWÈQG%­Zµòö± XÀfüêÚµkàÂúÊzõêIëÖ­å˜cŽ‘o¼1pœ €ÙˆjìÓŽBãÇ—ý÷ß_´3‘®7Ýt“Lš4IìŒ\Ô®];Y½zµè O<ñD`Ú5íœÊß³Ñ\Â)@‡£p¶ µ*` ö¶–áÇ‹Ž.¤£ ig#wÑQÞÿ}7é<˘1cä ƒ ¼™¨Y³f Ÿ›Øe—]äÃ?”sÏ=Wžyæg·vlúàƒœÕÍû¨_ö>û쳲뮻Æ" G6ã›M&â›M]ÊF >ææ9pà 78Ÿ[ut^]t$àóÎ;Ï™Ê<75⪠€@´lÆ/·¨û­2%%%òý÷ßËÊ•+£Em@òF ʱO§U5j”èç ÒÒR§Mf̘!º&[ôïv>ú¨4mÚ4Y6Ž!€@ 'D.p nBèÞ½»ÓH‡MÔ)ÌêÔ©¸íZµjÉÈ‘#E‡•¿òÊ+ËM«–ìE£Fœ!Žyäç—G‚cšWGÐNJ{íµWÌQ’ €„G€øž¶ & €áˆr|¬[·®Ü}÷ÝÌ_|QüÓ’@Èš€Nó¢¯É:uÊÚ5¹ €¹ÈFìÓš¦M›&={ö¬ðV‹ŠŠää“OvF<:ôÐC+ÌO(l¢ªÜ¾éù˜9ÿ”ª”Á¹ [í•=kÖ,ÑéÔš7o.-Z´Úµk{•š8q¢ÓÉÝñÝwßI—.]ÜdÂÇuëÖÉçŸ.Ÿ}ö™³.]ºÔ)[‡¨ïÓ§3\½ŽÁ‚ €@”ˆoQj-êŠ -âc¶¤¹ P8Û¶m“¹sçÊÌ™3E·õ{Ký#©MÌqÎ@IDATÿ{ËÂÑàN@ A ±O¯1eÊçï‚gu]±b…3u©о}{g°‚Þ½{9÷ˆUhE‡£ÿÏÞ™À[5½oümР”B¥¢ É!úEÉJ’±d¨…’yˆDÉ™ûѶS÷ó¿ÿþÛªT©’zWÂG‡J•*Ù|PÂ{Öî’E`Þ¼yÖ±cG«^½z²v¡í¦0ÕM¥ðÅIò¡q?çÝMífÿüó§ýé§Ÿ&™º6_Ò.¸àÿÌ¢¶—’&_úûSùVú× ´Ž`ÕªU¾l+W®\iBJì—ºYÞcgÍš•Ç£ƒ(~ju)~¦i¿Å† Z³fͼè(íOF'P(=ö˜ýõ×_Ö»wïB­§…ÓŸÀ•W^iGy¤µmÛ6ýO¦ˆg*­™E ^½z¶ãŽ;¢ZEö8÷Üs­_¿~¶ûî»gßÉgù¿üòË6gΣœËö@hôÎ;ïd;†Œ:ÿí¶ÛζÝv[7n\F—N&>”k]»vµ<0¾´TƘ:uª1 6,cÎ)Ñùè£lüøñ‰®®õR"ZbŸþù<:R² \uÕUvøá‡Ûa‡–ì]iû)F€ûùÓO?­öw]¾úê+1bDŠ]!NqhÚ´©ÔöéÓ§86§m¤ÁƒÛ!‡bíÚµK££Ö¡Î;û{:mÙ?ýô“ 4(›dü¹Kp”ñ—¸ð'¸œdû °ðäÒ œ?Ê–-kºöé- {ljÖ¬©kïÀ•)SÆÿ–¡–Om”m º¿¥öuJÖÑálDü®²§îv·Þzkïn¤ko¾œ—“aêþV92îmô’Óï;zé¿ÿÏÛl³®ú_ÊBŸïm¼¿éß¼è’g|Eæ NŠwrý¾3çšæLT7UZ™µ,"zœõ¿o¶téR“;sfý¾ƒ³á7Ž‹—~ç‘ìù¤|ÃqZ×>{®yp¦ÔÙÔ©S'ë¯ýºuë|ýUÀEŸ™G læ’ÎHD@D@D@D@D@D@D@D@D@D@D@D@D@D@D@D@D Yäp”,²Ú®¤!:„òD§ááë‹@ W¯^Y¯².>­*"âú÷ïo¤ŒUdV­ZÙn»í–}'®3Èx¤bhÒ¤IÆŸ§N0/æÍ›[íÚµóÎÐHsçœsŽÕ­[7ÍÏB‡ŸfÍš™ÒL%BN눀¤Ê7=¿§Ã•*þc$ 6.~ ÈteúÖù‰@!¨Âº°2lÑýöÛ/ÃÎH§#" › ´nÝzóewÜÑ" "i:è L;%OœhŒWƒ|œ°´˜ˆ@ZhÑ¢EZ¯¶øÔªUË" "‰è0 ÈNmÚ´ÉÎ×Yg¥T˺K®Ä Hp”8;­)" " " " " " " " " " " " " " " " YG@‚£¬»ä:aHœ€G‰³Óš" " " " " " " " " " " " " " " " "u$8ʺK®Ä Hp”8;­)" " " " " " " " " " " " " " " " YG@‚£¬»ä:aHœ€G‰³Óš" " " " " " " " " " " " " " " " "u$8ʺK®Ä Hp”8;­)" " " " " " " " " " " " " " " " YG@‚£¬»ä:aHœ@ùÄW-™5ׯ_oß~û­ýòË/¶bÅ Û°aƒmܸю:ê(kÔ¨‘?ˆuëÖYåÊ•K怴Èb))8BP4aÂ{íµ×læÌ™ö÷ßç¹DM›6 Žî¿ÿ~›6mšüñvÜqÇY­Zµò,¯ " " " " " " " " " " " " " " " " " E'r‚£wß}׆ b‹/.ÔÙÍ;×FeÇ·öíÛj}-," " " " " " " " " " " " " " " " "›@ÙØ‹”ÜÏ=÷œõîÝ»Ðb£ð#\³fõíÛ×®¿þú¨ÎHáËj\D@D@D@D@D@D@D@D@D@D@D@D@D@D@D@D@D pRFp4}út»êª«lÓ¦MyΠfÍšÖ²eK«X±bžyL¨\¹ržéO>ù¤Ý~ûíy¦k‚ˆ€ˆ€ˆ€ˆ€ˆ€ˆ€ˆ€ˆ€ˆ€ˆ€ˆ€ˆ€ˆ€ˆ€ˆ€ˆ€ˆ@âRBp´nÝ:»úê«s"¢³Î:Ë&Ožlˆ‘}ôQ«^½z®e‚/½zõ²;î¸ÃêׯLòŸ?ü°‘¢M!" " " " " " " " " " " " " " " " "P<RBp4nÜ8[´hQèŒ*UªdcÆŒ±Z£FBÓó)S¦ŒsÌ1öÚk¯Ù‰'ž˜k±#Fäú®/" " " " " " " " " " " " " " " " " ‰H ÁÑ‹/¾:Ò¦=Ú8à€Ð´xG*T¨`C† ±Æ‡Vùꫯì‡~}׈ˆ€ˆ€ˆ€ˆ€ˆ€ˆ€ˆ€ˆ€ˆ€ˆ€ˆ€ˆ€ˆ€ˆ€ˆ€ˆ€ˆ@âJ]p„hÞ¼y¡38ú裭eË–¡ï…!Û°aÃr­öÆoäú®/" " ©G`Ö,³ÎÍN:É즛bßÌ™æD¦fÍ››µje¶tiìu‚%®»Îlë­Íúõ ¦èSD@D@’K`öìÙöÊ+¯ØüùóíßÿMîδuH2òIÞ~ÌÍÿøã¹–ÙgŸ}r}Oä ÛÀíhãÆ~õðtm‰lO눀ˆ@² ¬[g¶lYΰzµÙöÛ›5h`V¥Jâ{f;¿þjÖ¤‰Y¹r‰o‡5ÿþÛì´ÓÌœiœíº«Y³f9ã U«Æ¿ý Ì;Ìì ͺuÛ¼Þï¿›½ð‚™Ë’i?ýdvÅ›ç1öÇfÓ§›½ü²¹[³_~É™£µkÍ}ÔlÀ€ÜëDû¶r¥Ù7æsy—X¿~—¼5ED@D í ~¹|ùòvàZµjÕJô|p]=øàƒmÍš5~¿U\áµÛn»Ù{ìa»ï¾»í¹çžÞáukÔ°IŠuûüs3D.íÛç`ÂfÛí·›Õ¬™3áOq>d“üí·‘Ñíyv³Í6f;îh¶÷Þf?œ{ö'Ÿ˜}ô‘Ù[˜k¨Ìqù _â„̦M3—fÒ¬³3Ï4sY+ŠáÃÍž}Ö¬nݱ ðhÑÂìõ×s˜…O6þÀf~˜ãf>¿m[³?ÿüËç“N4Úоû®¡O‘É=¸ür³ÌY£iÓœs:þx³ýö3Ûa‡øG´årýÙ,ÎH‘±nÝ‘“ô]D@D üóÏ?vñÅÛ¨Q£üY”-[Ö‹}tÐA~hJÁ’¤Xé”®;v´ Nq{óÍ7Û’%Kü{ "¤O(Ìÿ‹2NqÛÌ)zƒãâ“ãbzQ‘Ó­·Þê‡ãŽ;®(›Òº" " " " " " " " " " ""Pê‚£¿±Í‹º´fCÔ®];$8ú}…ˆ@VàÖòüóf?n®QÑ\#[îÓ≜yLu™½ãN°Ä¦Mf×_o†C`GÒ}F´óê«f‹™w^ζ‚¿þ™3½V-sI3>¶ÛÎl«­Ì5Fš-X`¶paÎç×_knþDàsÍ59ßO9%¯x¦{÷!Ò¸qfçŸoF±K.ÉgÑb­³ zÑ)¡vÚi''rÚÛ*Uªd_~ivà f{íeöé§æÒÀ˜}ÿ½Ù7ßä ¤6CtÊ×1cÆøÝׯ_ßhçž{®+ç+ÛQ¶uíÚÕH#}ß}÷¹²/wá÷»S>ÓIb–Ë+Ê1qlcÇŽõQÓ©Ÿ;uêdƒ *ôõAhõ€Sù^ë èeÎFq§Î|÷*¶Õ†D@D@D@D@D@D@D@D@D@D@²Ž@ùÒ>ãíh]‹yóæùƇ°I ~OkøQ5BD Ä Lqú «W¯äv¡™kOõ¢Ú q*ŠŒ«®2ëÛ7gâ—ðÀùæ»ïÌÞ~ÛlêÔœÁµý¹Æ?³‹.Š-ª ¶õÅfÇ›“-Rp4lXŽˆ'X6‘Ïž=Í=4'ÝNH‘qöÙ9SpSrmªÞµÉµ¥zÁOŸ>æÜ̶ÝvóZ4†žxâ‰6{öl?q gDª—¥KŸ°M›vuéʾµ²ewöÔˆ¸‚À)ˆ”g±‚ãà7qç9B¯ðå¯p9ÔâÔSííÔ×NeõS51<÷Üs®‘|¼_œÔi4P“§eË–~èÚu?'8ªh<[p¾Ï`œß›¨‘#GkCs°}}Š€ˆÀý÷ßo÷Þ{¯seÛϹ«µòn6Eu¯‰‡,¢—“O>Ù•i®PË'Z·nmï¾ûn>s‹6áËi./'÷óNMû6ì áiÅèx>lïò‹"|M4x¯8ÞYá!v:ß)oïvªXV¸8­â£qN{‘+äq BÜs¶+DIÑ\Ô`[¯;…ð9眓GlĶÁž¡…³ ñ¬ =â ¸3UáUî&‘Ö„ ìÊ+¯ôçGÄU°žÚ졇ÌHeU±~}Žh…6È`pÆN,’“ö w#Ò !´qí{MŒ+s nC¸1?ÿlNØböÁ9ßãùË1!ºâ8"—hóÀ›o¾é†H YPC´3cpŽ Ñ¶’{Ú–[šõëgvá…9®N®-Õ<‘Ú —$ҵъêU«|c& ¼Ÿ:;#†Å‹Û¹ ¶µîÝŸró¸ôlý}Clx#0mر !¸n°@àÕ«Wîc|ÐåJ#Ý ð:EQ¤»Äºu댆ã™ÎNé#—GnÆŒÎÁêy—æíY¿¡ªU«Z£Fs¬jÕzî{¹Ü/àifîºë.¿ïÕÎÒŠ´žˆ" "Pœ~v…Èe—]æÄ››Œg]îsD Wp’Ò‹ÔYÜóq Ái‡çã dqÇСC½Ø÷D-" Æo¹å{å•Wœ{Ý÷¾ü)Ž}†oƒýSž €æ  ¹sçúTb¤cxë­·lÒ¤Iá«„ÆÉëÔ»Ýmß¡NeK:´x‚mâlÄ}1é…‚QÏ)¢;wî쇜•D°¸à‚ ¼q"¸‰Äøñã½€‰kŒØ,Þ@ „«PlÈ!^4„ð1B&~+ÄÆ½KÒNéÌ€pŒÏ­œ!ì/½ôRÛÒ= LœˆƒŸBD@D@D@D@D@D@D@D@D@D@Ї@© Žš7oúÆNé!§JÀacë"(^%‡QXГ\!"?×nå„'¹ÅC­xçš#r\ƒ‚eq B°óØcfŸnöÌ3æÒ¨s£â~@cÂ\nh|ŒÏ>Ë›>,X†´g¸¹Œ)®±6˜ÿ' ”4 ã€@ã.i|ºfÎag÷ß­Óen±§žÊIÅïôr0~øa¿xµjÕlß}÷õnÜÇHuockä>i/=ë,³ž=ÍH)ÇukÓÆìÔSwׯ§U¯^ݸÂ=†{M0ê+òÙ±¢%‡¸7º\”‰Þû«\ïò„òÌ}Ë=)èäì6¸|—޳ *Îà˜‡ý_çr{r»9‹<†3Î8Ãï ±-¢,ÒZîCŒãvÇû!Roâ–DÚÏhñ¯SúŽ5Ê mûùwŒ×^{ÍÚµkmÑ\Ó(gæò q"XÊdØí”ӻOïÉg ôɵˆ/_º|¤ˆ•¸Žd‹â–t˜{¸a@Œða<(¯úé'ïž*÷(Vƒö®F‡¦¯" " " " " " " " " " "P,òñ؈oÛ®Bÿq·d÷ø–Ωø4:Á4 DëLªeË–ùŨh§â=2è5ŽK=}ƒ@@M´Ì×gnï¼óŽoxòÉ'sÏзŒ#°h‘™ë|ï]€œ¶Å‡3yñŽ7®]Љ7bŸ2B"4}.»•Ýq‡9§†¼ë 4!{‰3Qp=ýÍ Uò.Láÿüý÷ß¾Ú.»ä[rîzg\uæÏÏI™†cN0àb„%<ÍWh#qŽæQn:uœ ÃÁ€ „Ù(7œïRä¸ôĹٸ{Ì)³h|mãT@"ŸÏ`œw‚ÀeT*ˆs6lè?Gˆ´×^{EmHÖüœ4iuìXÆ9\üŸ5n|¡kȼÆ}6Ž\,×wØŒu¹åhˆ¥q˜FMH¤§Ù6s=m¯½öZÕ_eàÅ¿ÿþûmÅŠ>»@žžNID@ò%€«þyçç]Üó]H3Ò™@ýœÖÕR>…‹œ =»ƒž¹„Îr6ô‚ŽW(DÃ=˜orùzÂÅF¼¤Æ»RÆ Ý‹@‰@ôóÒKæD}æ'rR~m·Ùé§çìá"×ߥ®ÊI#VБšÌ8GsÎ0Ñ—tåˆOGæÌcœ{€¹Æ7s. 9)ØÂ×Àݱâ#?þ½û¿îéD)‹Èå çr³…ÕÐÈ>Äã4¾Ÿhã¸;V…FB(9æ˜\‹qj×n’KSböôÓŸ9ç„}sÍ/êœp â\Hˆwhüýî»ï|e/œŒÓØúñÇû4áûÅ=ÆF€ƒ!h\f;—‚ÆXO¯¼ò2'6ªl5k>éÄF÷:±Ñ–¡Í! B¡‰nîÙ8@P©Ë=‘NAÜkiØ­S§¥[n?;é¤Jþ; Ÿ£G—ñB-\°HƒGÀš49¤q£ H´!šmqîˆWOw?ä+®¸Âýv÷ Áˆ¡±ý9s®vKžâR ¶ÿý¯…OUCz¡ðÔplK!" ÅE±*÷LîW¢÷/Ò GK)Ì3-B%ÒNâ´w÷ÝwGÛDÔi<ãô믿ºrëé|ÅF¬Œ Á+îu8.qÄQ·Ldî·o¨0c?ÑâòË/÷åç^”{<âŽq*Â#Ò•á~„ ©é(oÂ"Ä%Ó*Uªøò„2§%DO”Õ|ãƒq…"ãÇuœ3gŽ/«qÎCT[ܳÃz§ºVVÜtµ=x ¤„àˆFjlÿq§w ü»téâô ¦á$Ïi@¡64<04¢$ƒ†¡… zW=h)ΠaÆùmœKàÆQœÛ×¶J—À{ï™MÐðgNtb.uHñæ`®ãŸk4ç €@ÃÜÿ—9G0³rï‘Óg©ËZ¶Ì=/ò™Æ®¼2rjÞïÎ|Ç9ö8 ósÒy9]Œw;"# † eÊüãöHÏ…ˆeÕªZÖÝù§U¬ÈöÿÏ5ÖÞä6_|ñ…ïѾœhH9C •DÅG}ûöõŽB×\sM±û¢!±G–^pôøãÅ-8B@…[ÍùÎÜë=Ñ(ˆXžF`D< ¸·…‚î{hÅé!®  ¯lƒûFø=”y8XÜtÓp8Ð]€°påÝ}ל¨ÈìöÛÃf„Âa Ô¤Ša˜7ožsúÐÝÿh¯ãœÒØî × ½;·¯­J•-Üõ|ѹ6íå1:uêä¢q´;òÈ#öžø(©k}ôQ×~ûÝô 5ð×®ÝÔ¥ØëäÜ–»ÆêOå^THÄ*Û L‹§$„éA¸—’š«$‚{1¢Dô8Ñ6#qE@϶x¶%ÅW<aÑSÈo#Á)*c ŽþPðœÛÝÖ¸«p|áeBOÄH¸;á‚W\qðÁÃÈ‘#½#S}ºMž<Ùw8*™³JŸ½¨|KŸk¥#È>åSå”Ïw*ÒàìïùÙ"ãZÙx¬Ç'˜„o+Ö8é{èyNšz@óðDÍš5}/kÄØÝ'ò0úžS¡<âzOãl‚µ0€`;gKó¿ÿýÏ öÝ·xÝV‚ã×gÉpåØ&Çy±?¡gžÉqJäŒ8=žkø3—^Êœ;PŽ€ÉýK¹ÿ sŽ4æÁÌjÕŠ¾u\‹Ü¿£sˆ>?Ñ©ÎÁ9Ϙµmk. WŽØ‰m‘ÉjÛmW»cþÎÛPw\µü±]½ÙqÇ‘6Å´]òF£1)ùœ={¶‘&„—2œmpG*Lðÿ… ¢,kó‹Ö­ëøYŸ¾Ö§½)èþâ´‡®‘øUëÖí'riêE‘¢÷3ΡU«V­¢-u÷†ÈÿH¼¤2Fª\¹rÞåñQøÐÒ©ÉHùüöHMç2§Ù '„ω>ν±C÷ßÿ»–míRà½ãŽíAwmvr÷¯m‹]_×ð#„âƽ眊3pÛš?ÿ@÷»˜á̘±;¦2Ö¿ÿvNlTœ{ËÜm©lËÜk›g†»Û©§žêÞèE0lpÂ9(Á3eJ#綃[¢¨„gLÊ(Ê \…pï)(¦9+Áë]!Šë]¸ ¿ uš4iâÅ»/¾ø¢©æ—V’çRÒ—àFÊñôèÑÃ?SæðÑòåË}8ÊÊXîùÅl3Û-ÌqÒ€gŽðçÞgxf'E¬"õ¨lK½k¢#(:d–oª“,úõÑD@Ò‹jpÖ¥gÉ’%~`œÎïˆ^:Ìâ¨K½là¸K½/ébÂ;’æwæ8Ÿ{î9ŸZ†úl:qmJÔÐù^A»FòÚÝT¾é&" " ÅG Hµÿî!ÈIÌyO ¢ÑŸžÁ8~$uêÔ±!C†äé…œèö Zt·Ýv›o˜)h9æíí¬\nwv!ñ¦xûùçŸóÈÀ¸ò–Óãú–[nñ»±Ž#Ö|‘¸¸F)’KQû©º†:3R‘rÌ츞ûæ^,̽Ü$¶ÿK.1×À˜{ÝCÍùtì˜#ðÉ=·ä¿-X`®ÁÒ\Zs¿í7¦9ݙޱ,‘Æ_Ò ÑxL£ò•Îr‰†V„6±Ç$œ𑲌ÆÃüÂeƱûî{Ïúöí`W_}‰Oí’ß²S§þŸkÐ.ë ú:ä/¤á™Ô,án =ö˜?nÜ+M•vã)54HíÚå¤ÝËïübMwíúvüñæósR³q)¦N]àœ˜¾ð"(„P¸ánÏuе¿ðùάÊ9m˜sz2—Ú&gmœ.Í ñ¾¼Ôã²—_c{AëfʼL,ÛøÍñl€pCQò¨8kÓ¦w‰áÿžJ¹’ †¸_êòz"Êœ4i’¯(¤’tš¤#õUq:ÆP&qÉå1=žbƒòç=~ˤ(ëׯ_Ô-’2¡Ñš5kü3äÎ;ïu¹hq7BH„3Q¯^½¢-â…OS§NõiÅHÛɵEx4xð`çbWÑ•“÷¢¥ &øgÉnݺEÝŽ&–<ž3øís²12±lûÁõ2 S " ÈFÔ_=ଜó묘 L’U¾•V$¢}êGfΜ™ —Oç(""p¯Å1v)²iAçñÚµkû:L\o©?æ]{åÊ•~ S,㼯ӶE.À—¸ÊùhiÅ¿ÿþ{ÿ¾Í»7ë7öõÔI0šÇâl¯¿Ê´òkM] ¿µXÈXV!" ™D€òQ.uÊŠŒ$P?¥Gâß~ûÍ7¤ÐP(»ƒy})~pKJD°Pж£Í£÷ÕW_m– D;v,79¯† F]/˜zâ/"÷UœÁ6©dáÁ·(!ÁQQèÅ¿î¬YæÜlÌÖ®5ç(`vë­f³>™³p8rš³˜iÕ\?—Âà WÒ.‹—«œÉq©!!íœÅÙ1qÔi§™kàȦäì5ñ¿Üzè!Ÿ¦+Ñ--p*¦“j‹”b‡:…Õ¸qãü a~ÛãeÞ'üŸ‘úlÿ@’ß n:/4Þ®uŽ 8î;ÑâÌ3?t®»ÿãÇœjÇë4ïÈ„+.Lü¿’}ÒáSAb§hûHÆ4®-©ôH©üžŠ²‡Ø‹èöÜÓÜEQ¶ÿº?fR8yaâ: 9Ç sÂ.s×$öv²]p”©e›G±ûÉ\ǶØÛ¹ÀuŒŠÐ ›L‘­NYBïþü‚‡[z— 6,Gc.,¤[¢×:B }hLÂZ’øé§Ÿ¼³ ½»JÛ%Åþ¸ 9.>}d®QЬyóÍPhŸdš3UðiÃ6Ï1×€i®‘Μ8Í\Ê©ð9yÇFÇœqƒs2;∜ù®Ó5tæ]6ž)ô"»ùæ›} ^ˆhtœ=»ŒlT¨³gØàQîßÎ;áijÝü–áwÎÿÈ^Ná‚DQ¢Aƒ†jÿþýíî»ïv¼›{w…hÚq´àþÂÃ~ýôSÿÿIjÎõŽ;îðinX–ÙTq8Å¡»Š<å|¿»l:Þm(ß’0ƒ “®-ÞÜ»»§'ðQÄŸWÎF2ü¯Ê¶ ¿À¥xz8§!œ!pnC<ïU —$ßÈ‘#}C\&G5î¹^x¡"ç>MHOC‚å¹ïSA-pÓ;À©…qAÜÃs)ÂTRe"H1bD´ÕžFåç[o½åSŸQE,I†;QaÅFl‹JXDT±g‘-<8_xDë‡À a•³¬›­.:á¼4žT¶¥ÆuÐQˆ€ˆ€/d•oª“,Þ뤭‰€ïãtê™bѸ¿Êá(nT1ÄuÈu`ðáÚè¼ÓKÌ•ÜdÄa†ÔP ™RpI +Êϯ UóÌC„Ãï’žAT¯~šKø¸k¸üÈ5 ×qép9‡Ÿ÷$—ÅÁªU –Lì³gÏž¾a“°#<2±DY 1ÐÙgŸíy4Ð’+|àE}öèÑÃï?Ê&òÄÿrýúõ½Ž‘ÁK套6v×ãX×;¦œsÍØ¼ Åœ3î÷l^@cÅJ‡/§Có×ÀiËœ3öæ³Õá(ÓË69Åþí'k D×ôØÃQ)Íp}£×BO=õTT«ñâ8*¦Ws…N@TÆ ztS">â“ÊK„ä X¨ŸˆÈyä'À}ÆWhâb‰«b&Äå¤Ð¼ñÆcí.¡ù ½!¢RÓÁá=Ÿo£=‹f'<RùIZ_R¥ œŸpäœéG Ž2½l“ÃQúýêˆE@Š—@¶:%³|+í:I9ïÿˆ¶&éJ€w^F Ô¥®é$ƒKïö ´›Ÿ•+WöB¢À͈O:æP7€û1Û †uëÖya„F8wàŒÏ=÷xW£“N:ÉwT¢>!Vðî}íµÙép”Éå×]G±~ýš/"©äp”©W6t^©ép:¼ˆD ¥/¾øb.±é,hɯg÷Ýw÷¢ M‚àA9šàˆ‡ª1cÆ‹ùOzÿG1ÑZá.+ä·¥1HQ²6D ~œQ•s 2;ì°ÜîF±ŽÌ½79‡¬XK™{Y2ç¨eN|—wß±×λv¥¼ÔàÌp¬SKñ;}óÍ÷lÖ¬_œ ÏNnhâ^ä.p½Gnrû¼Ç¥ÈúÀ7¾Ò‹˜'èQÂg0ŽÛ²4RFiĨÌBhTœb#öCŽp"CܳjÕ*Ÿ›†nÆ7¹Üaü_ñ _˜@ öý÷Û¸4u½lüøŽÍ,ß`lƒ—WþgË—ÿÐ5r—qŸÁœœOÄŠ_~ù¥]|ñÅþ¥7&Eò¸Ÿ°ãaHç~ŠŠ¨l+Žf‰6àÜq•#ŒãFwà 7x‘4åÃ5×\ãïÉ“p»¤â°¨Ë"Q„?ñˆØû¦Übˆ¸úà\‡SÝØ±c}jPÖáù,¿´»±¶Ï|¬Ýרx–/Ì2ôìlܸ±ß>×(p…B O™žÌó*ÌqjYˆ‡€Ê¶x(it#¬òMu’éöKÐñŠ@æ˜7ož‘ÞŒÎt"x%­7éÊÉ,A]nºdvØa‡ì–[nÉœ‹Tg¢ò­ k" " "MáIØCŒM’·–žíAЀBºT D £GWƒ 5Æ„fDŒœx≾AŠ4©&¢ÅK/½dË–- ÍBœ€{RAÁƒ6éÿvø=”=Ë—ÿî¶»T4e£nGŠd5GÝaOtæ#^h¤tjÿT¶Ì'ær‡¸‚Šç…ãŽ;®D+è¸ßñ¼.ަÒA(bSÊ…È]T Ö¨QÃ;Z"p _7Þë“éÛx*jÊ΂öIIRª1ð F¹Ã³ŽGé°‡¿—7\¾V*u9/*þN8á_ž§ãy阳€Ê¶ì»æ:cÈÉ,ßT'™ ¿ £”ÞÏÉ^£pðIûÅG}äÓ¥1-:ÀàZȈ¶‘­·Þ:˜¥Ï & ò-ƒ/®NMD@D ã ”ºàèG—ㆼAv#•ƒ”,áéËxè¥'|¬¨U«–]ïrjñPMä'"‰LÏtøá‡ÇÚ´ŸßªU«àˆ ¯¾úªõêÕ+®uµPÑ àžâ\XÐË|º±¢l‘ß ÿä+¾ì²Ë¼ðèÜsÏõ½9вÝXë>üðþ÷ûGl}úTuB;sÎ<9¿Ç‡ªngž¹ÈçÉ&ÅáâÅ‹½5- Ê‘6µãÆóÃ%—\âÓ‡ÑØPÁ!éÅH©SÒ‘hC0éäˆ ø†{–Láð„X'³&M³~(WäßBΞô7Q+Wšk 7kÝÚœ[G¢[ÉŽõT¶eþu&Ýn5΋>»uë·ëO¢„xîÁaÏB‘AOEœâ¦M›æSæ’B!|ÀŽr¢aÆÎ1ÐY"ƒr_¾÷Þ{½…z!VMxQĵáiÈÞP)¯ˆàñ1)ãánDÚU„É H*ÛÒåJé8E@D@ C ™å›ê$ s%´¬dêx—,YâÛFhÁQžOê†i× ïÃÝïIg†à(ZàlŒC=ŽÈ´o0Ô©S'Ú¢š–áT¾eøÖ鉀ˆ€d4RÑ€?ýôSø×”Ÿ9sf®c:õÔSs}/èK—.] šíç}òÉ'¡eèa~衇†¾4‚cAxHpN#¹ã?ü`æÒJÛ]lôõ×_{±îFGq„=ðÀ>=ËC=äpO ®ôîà³R¸¥R‚§Ê !Îb4# ŠŒråÌ5T›áØ´Ûnf=zä,ÁK!αܴH9ƒwÎ…Ï &x‡!1Ó)0sÙ~|\xá…Þ‚YR¤q.¼D_zéµN`h¶Ë.étf™w¬[m•ãH\¯Ì;Ãâ;#•mÅÇ2U·ôî»ïúCCd4qâDïÂaa+=·$—g‚TcT4éÔ¢íè1Çm–OAyðÁ»òç$ûôÓO­^½zQ—‹œH¹FÊYR~r~ŠÂhРµmÛÖèåŽú¹çž3R#Vˆ@ºPÙ–.WJÇ)" "PÉ,ßT'Y˜+¡eE 3 ÐégÒ¤I6þü\è´ŽÞ¶Q¢B… ¶ýöÛûzêŠq”ç3蔊+0n÷ tÜ>I§N'T–Wˆ€Ê7ýD@D@D } ”ºàˆ^öáñûï¿{ x\ƒÂ×+©ñðM ÛÛ¾ ãÄíiÅŠ¡EöÚk¯EãùPÙ–™Ì™ŽàaÏ£.()%¹oqÏïÛ·¯w`¼è¢‹¬wïÞQ]ˆŠBtj[9õ©¸ ž…8fDÛ¤§å<â)ç(Oéyy×]wå¢ðp–šêr:vìh¤–»QájÒ% ²­tùkï" " É!¬òMu’ɹ^Úª¤:œlIkFÇÐ^xÁ9¶onS@4DçT„AÍš5óŸ‹êׯï:1Î2tœVˆ@Q¨|+ =­+" " ¥K ÔG<”ÒãI¯¿þºuïÞ=øš2Ÿ4¶|öÙg¡ãÙqÇCãŒ|÷Ýw¾!Œ.,F5jd;í´“5mÚ4¦ ëÓƒ ÜpnD„TN6ß~û­ÑKáJQz,vêÔÉ®¾új:t¨‘b”²² à^|óÍ7ûÊÐóÎ;¯ E5¯pÇÉ´x¤FP«t! ²-]®”ŽSD@D 0’Y¾©N²0WBËŠ@ÉX¹r¥!ÂÀí7øÄ̘1 ÀüáÓŸÑ”VÔ'Ó–Aà`O}}èüS“^§ (*ßJ²v!" " I$Pê‚#ÎmРA>]òeËü©ÞrË-Þ­¥0‚›$2 m:K¤Á¢×÷W_}ÌÊóIZŠ«®ºª@áQ¸» eVa‚Äð`{ÕªU Ÿ×8b)D(ï½÷ž_¾œ³³!‰":·ß6gÿjÎ*úüx§ò‚·|ùr8p`h.Ÿ{´É“Í6l¨d4þ.ƒ—KQc.u×ÑvÎ9G½QºvíjÏ<óŒ]qž¡Õ/ÇRÎà,vçw¸ŠÂ8ÿüó}c=÷£Ž:Ê ÏÚ8þæ×Íõò)ܶ´téÀí%\LÊK.) ²%²¥lû믿¼³OP¶q}[µjee±-Ëð@ôÃùrÈ!¹ÎÑä.h¯^½¼ðûî»ïönB8 Á†T‘T4"RJ$aPAéÔâÝ.i?iÁËõË/¿<ßU~øa_‰JùV¡S¾;È’¤ÙC€FzWÒï)Ò“=”/^ì~îܹ¾SDzžIáŽ:[Ê6ÒG2„—mx žé ÷sÑÒ" iF`Á‚.­ýBÔsæÌñiÍÓì>Üd–o©R'IçÞÇÃ˶ýöÛ/i) ¾ZQ’D`Ö¬Y¾c#®C8Aý<®Åtâý§¡x‚wþ·]åõ¢E‹¢Þ/éøJ'!Ò˜·hÑ"žMj™$øå—_B×ûûï¿e±H®Rr“ÙP¾ž67®uPÆÑž‡¸O!" ™H€t¬tH&¨›Ü°aC&ž¦Îé?‰µ 3> Vx¸ ~t4âÓ“=•„.8…‚£gŸ}Ö»lÚ´)|Vžqìßÿ}ߨGÚ’hÁGxVp).¢²—¥Â=ÙyÈ»ï¾ûüªˆPRé:ö| »<•ß|óÕ©S'¦%¬«ÛrnCf§Vؽä]ž=œªzôè‘kæ 7˜´˜s¤Ø<Ùý»¸1æÒ­åLöö§B¢w ‚=œµpˆÜðI7CjÃTt‹uü©0g¨cŽ9Æ&NœèÝ8&gvæ®AŽóU*£Ž¡`î‚ûK"8ʦ‡Ÿl)Û(¯u¶4Ê’†Œˆù‰î—Z¾øâ Cx4nÜ8;ù䓽=ú ® Š,›‚uóûD˳ÏJ1‹”s˜He‹°–T²í۷ϵYœœèõ‰ÓܶÛnkhÄ‹ŒÈíG:E.ù=rùÈÞI‘Ëç÷½qãÆ>­Wð›ßr™8Ýienºé&wzuè7«[·® òRsíh¤&H§F¸Ÿi‘â§Ÿ~²·ÞzË÷&á7‘"w÷\êz¦˜sÀkó’8UšÆXz¯ „Áf· 6l˜¿ÉÓ˜œ .±(Ì<÷ïíÌ¥Êq ;v¬Og¸Ï>ûøÍŒEZÃÂlQË–&*Zžzê©Ð!ì±Ç¾×XhB†D–=™Z¶qI=~­3üÒ†NÁQE§R=à€BÓòá>F˜lô~@IDATI„&Ø´1ÂÎ8ã Ã5ˆz?ƈ¬)Ûpí+®òe«­¶òvïûï¿¿Á¼óÎ;þy‹óc˜>}ºwrâø8~z*ŠFñ;ÏâŠô%€X0 "Žž4iRúžL!Ž<[ʶڵk{e6–m…ø9hQ #Ð¥Kc x¤óV¶D2Ë·ÈmGÖ1Æb¹|¢u’lq‘ʶXÄ5?SÐ!€û™ø¿¡³Ç=÷Üã}#ÏñØcuûÛøN§ñŽ‚Ôk¯¾úªï´¹=}Otfe pa¿öÚkýx¶ü‰,ƒŠ³n2rÛ‘åU,Æ‘Ë'Z¾±ŸÝvÛÍ· òÿ®L'À3MЉ•ûúyç—é§œÕç—‚£Ã?Ü÷^ ®¢"zÆS¢ƒ¡(1oÞ¼¢¬Z7Ri0*cH GƒfX“fí²Ë.ó¶¥ÁôáÇ{Á "«ðˆ|ø)¬Ã qá^?7ß4»äR•}ï„F“\é!N°sºsÝZhÜ ?üðCÿ»¼ãŽ;¼ "©S›ºT3¸FÄ¿ŸhKÒ¸ËoþœsΉ6;×4g:áDnæ‰rMö_×Ñ„èˆ 8zµã^-æÏŸï“[¶li'œpB´E4-ˆ‰œÁ†õî#8B$.;òÈ|VÔdHA*ÛRð¢ã!QyIY€Øaj¼CÏ5X¯¼òJ_^ÊŒJM*Fb¥*+ÎtjáÇLïËñãÇû–O4JPöáât衇æëæ,¯OÌ& ²-³¯¯ÎND@²•@2Ë7ÕIfë¯Jç]š¨k&:¼Òù·[·nù.–ÌGDêt:ãäüO?óÌ3þ=L…¤2•o©|utl" " "›@ÙØ‹$‰eË–Yøˆ’¿çÂí!òå;X›Þûôú1¯¼S¢à@Ú53‚À:ŒF¼Èˆto*¬~¸›ÛŽT_GîOß7ÀÉ­W/sn ÿ:§šƒÃ—R©ªõë÷‚OÏò믿úKØ›žè¬…žþy'äÙÓ^}u­³½ÜhZ¯ÍŽcŒÆ`œ#pÞ82¥ éÔjÔ0;úèèÇŠs„ >×3=#H›"¸/¿üÒ}ôQŸÂôq¤žQŽ€ëLî¯ùéG ·²–# ²-Å.H1å7ù¥S‹µ;ÄÏ<ãPJO,Ķ<Ó)š¢­OJBž}°|ÏOôm½x§µk×Îp–C,‹#!džÝ8Nƒö‚£Ègªx·­åD@2ƒ€Ê¶Ì¸Ž: Ü’Y¾E>?«N27{}D ÐαdÉØúXÞYO;í4ßùÿûŸï¬LÛ¦ ûïÙ³§}ä‘G‚IQ?I»ö×_ÉM *ML5*ßRíŠèxD@D@D pRBpT¸C.½¥gDî0¤~+(jÖ¬™G`DÏ…ÈíE¦~ûóÏ? Úlžy4ð…G T)Џàbé \Š–Ynù…Ö¹s—¾ÏìÓO7¯¾Å[x;[Ä<¤mÙk¯3Ü5¬â2gEkÖª•YÅŠcý ݺ5·sÏ5Û~ûèëÓßµkKûüssÎVßÙðácmÔ¨Q.ÅVoëÛ·¯[/Ÿ£l—†²eËÆ® b6eJ΢¥S‹Üt=Œ—Ü믿Þççþ˜H_ˆã/§|6jÔ(r5}“ÀÎ;“SÛœ“”¹ÔB›Wr&æniîšnž¦1He*ÛRùêýØ•+W΋rŠº5¶Ó¯_?Ÿ²“t±Ï=÷œsú{Õ7nì\{ùrŒ† zR²l×®]‹ºK­/"  PÙ–6­$" "â’Y¾©N2Å/¾¯TP×>mÚ4›4i’æÓ[õ¿ ÓK­ZµBuý3gδßÿ=XÄg ½y³fÍŒôà ¼?3<Ñ@¸Ä;ùË/¿ìßÏ#·CGÙÙ³gûtm±Ò¡G®«ï"PT¾•uíSD@D@Š@JŽ>Àº% "ÚƒÏ.ØœÄ8Ì‚#V¡WDq ŽHK…Óˆ>ŽiÕÙg›sF0{ðAsŽ?S}j¼vÚ)ú aS]Šms:2ç2Ú5º¶öi]è‘‚ûCw§¢'Køõ [54Jº3œ H¥FJµ‚¢sçÁQÆ9⨂– æ]wÝuvüñÇ[ýúõ­6yÀÅF€}çŠìþÍõ,Ú¼ÙNÌæÌ1sYø"T¶¥ÅeJè qzï½÷¼Èt«¢äþŒØ{½zõŒÞ” .´1cƸòóAï4„5<=4!‘ö¬N:k꫈€” •m%ÃY{(YÉ,ߊ*8RdÉþ´·äX»v­=ùä“^`DÚnÒ’ˆ„úôéãEDüÞ©Óå“áÛo¿õ‹éÜIý0ììz+ÆÓQ¹°gCJ6Ü~IÑÖ¥K—<«óžNœwÞyyæi‚¤"•o©xUtL" " "?”Ÿ¥»$NLáA/†hCáË„7hÐ ü«Káµ¹W3"_îÉï\˜X¼xqhñòåË;—•ÜÇš©‘aÃ̾þÚì†ÌÙÌ.µo¾ùÆÎ8ãŒÐü‚F*U2;ì0–(k¸ ‘:ñЭ·Þê_zè!;î¸ã¬ÿþFNîhÁ‹á?ÿücçœsN´Ù¹¦!8rÒÜK«ùto¹fðw-EñÀáˆpu ¹G|wú.…¤ ȲBe[Ú\º˜J™¶|ùò¸Ëµ˜ŒX¡ì0Wq|/¼ð‚Ýwß}6nÜ8¿T2Ó©E†¾Š€ˆ@*Ûò Ñ ÌòMu’ðÑ)™À¼yó|'š¯]e1uëÔç’Jœ—¢T :•uÔQöÚk¯¹¿æêì³jÕ*ŸÒíàƒ¶=öØ#UYÇ!PùV Í”' ¤?…¸D‘®7X¥&puÃ#òûgäkŠ3°x (í³Ï>IéAçá¤ÅbÎYÖ¹™Kug6`€ÙÔ©Sýq·mÛ6¡ã§Ç nB¸I`]Û±cG›8q¢‘£»E‹¾×Ɇ rmWÒϰ^¬ ãÞ7š{ñµ¤æ—ÀÜì»ï6stèþ‚y›çhLR—€Ê¶Ô½6E=2Ò©‡rHQ7UàúXÉŸ|òÉööÛo;ï×6zôh;å”S \G3E@D ™T¶%“®¶-" "PZ’Y¾©N²´®ªö›*HŽ3nE7º X:ïðŽ‹ƒ}*‰^¤UÛ´i“OiLãóñÇ·uëÖù´çáÓ5.©L@å[*_›ˆ€ˆ€Ä& ÁQlF¡%jÔ¨aÛo¿}è;/«W¯}5éh„­jxž-üŸl\ã ÄI¼dqøá‡£ú #@Ú4Ðx`Ž;0¦¹N+!ÁÑa9¶E~-gáS®¹Ü…Š–-[Ú„ ¼cÒùçŸoôáEÔfƒ ²ŸþÙhæã¨Dc­"½ÿ¾á‚#\¯þüÓlĈô:mvPÙ–¹×Ÿr1l~.{É8s*b±m§7¨BD@J‹€Ê¶Ò"¯ýŠ€ˆ€$“@2Ë7ÕI&óÊiÛ©LçyDE¤&ÛrË-mÊ”)vÅWøÔi©|ܸêo³Í6öÈ#ä:L:m½õÖQS­åZP_D …¨|K¡‹¡CHpTHh8…Çllr⌯¾ú*×’¼Ì‡GÙ²eíØc MÂAéƒ>}/hdÚ´i¹f'êÒ“k#iüå?ÌõðÈ{¿üböùçæìfÍœû¬i¶ï¾9ËÑk5ý;ìZqÍ3—Íž~:4ɸÌ1>•Vî©y¿qGe‹-²»îºËxx¦—L£F¬[·n~…³Ï>;’òÜ¥tióþ\Ý„s­JùÃ׊@.*ÛráȘ/8îa¡^³fÍŒ9'ˆˆ€ÄK@e[¼¤´œˆ€ˆ@:HVù¦:ÉtúèX‹‹éÈè´{ûí·ûŽ:Ÿ»Jãd;×±W¨PÁºvíjsæÌ±O?ýÔoöÃ?4Úzôèa•+W.®]i;"P"T¾•fíDD@D@’B ¥G¤ ûÎÙ‡<íÔwÞy§ 2Äú÷ïï_Æoú¨ÿ Ú8W…¤•oévÅt¼" "¿ÿþÛxà¬{o‹Næ,•’ù.V®\éó 7ΉCœ:$FŽêøã·Þ½{;qˆS‡$1Z·nmuëÖõbvƒÃÑÎJ‡ÊübýúõvË-·äš}å•Wæú|A|Bª5„VÛê©§Bn8ÁrÁçgÁCÊ®¿þú+˜ä_¢B_²lÄeޱ‡6#µÕc™5o€©S§ú£9C¹:-'xË/á†äê³Ü1'%[|[ß¼©m:tèàDNÕªUÛçŠñ¸ãŽ3P¸o Tä¾2eÊß.œ ÷˜æ®÷)Žh¸þÒN@Ú4êÔ¹0zt:žN˜0ÁfÍš•¶b£àœq9âÜH¯FÛD¯ÀÎ?X@Ÿ"&T¾¥É…ÒaŠ€ˆ@xþ:í´Ó¼ÞƒwFžÛxïSd.8åѸž»9Ý£Ï-üTl?±E.jðp‚Eê™gžYÔMå»>ÇØ” U©RŧÇâÅK篿þÚ¾ÿþû\/>5jÔð½,bY´^~ùå¾×F°m>ëׯo{íµ—sï©äs3Ó+,<Ê—/ï-T©Ð)J¼óÎ;þÜž|òÉ¢l&­ÖÝa‡|%y®#ÃuŒq•]96N„©| Ô®mæ4öÁù.¢i@`=öp×ðƒ¬«¸æÒdrÙöùçŸûÔ¬/¿ürü ‹~ˆy¢AF!"  a–FaRHdSdrÙFJèsÎ9ǧɦkªs(8fs¡Þ —mÆ×®]ë]·qÞ¦AŸ!è(Eƒ=ó¼+1ÎlÑ¢E¹r:WQ™Ü¨Q#×A§ÿ|"$¢îŠ}ÓñkòäÉöúë¯û}‡oˆ4G^x¡o@¯\¹rø¬\ãÔ_aÏóx¶E2Ë·Ò¬“DdvôÑGç긙m×Vç››ÀüùóíØcõõìÝ»w÷‚FžiƒzqŽGy¤ñÞ¿å–[úžô´ |Ìô A6 hw ƒ2mŠô%€(ŽïÙRy¥2µ|ã<ï¿ÿ~[±b…]uÕU‘§­ï" "ThÞÿ}Ã…–,Sˆ•ƒÏ?þøÃ»AÒ–À€;dðɳbn\yß+(x9r¤ <ػ֒jĈ^üMdž ÛPAÛм´$P¿|ªö—_~é{;E;Ä <8o³Í6¾¢ƒ^ ¼€.[¶ÌWnÐË)<°I½é¦›üøÜsÏ ŸUlãô°jÖ¬™ÿ§ùóÏ?ýv©˜ÁÉ(ÜÍ(|‡ûï¿¿oÌ­*!F\wÝu¶jÕ*ŸG:X”ŠœÈÊœ`0üUll/>Ý=Ò;¹÷Ë„‚Š5¸’Ó;Zà’ä:ä™3Ý2ôHN‹ <Ü¿«»'™«Ë3KD m¨lK›KUàRÁHƒÑÙgŸ]àrš)" Ù@@e[6\e£ˆ@$D篾úª¯W¢:&>©P¦—)Ôñ öÔËÍsVÒÔ{T@ÓQÇê¡uwTPÇ Ò±.è áî#]ºt±–-[ÆÚDÖÏOfù¦:ɬÿy¥ €÷Þ{Ï»¤Ñ(†'µ fÏžíõˆêI¡V±bE?¡Që",²Hl”îWTǯòM¿(^¿üò‹!ü Ï–¾‡@`„¶"Z ë`Ù *øwÀ@|Ä»áo¿ýæµè5h—๭aƾSHøû^°}f&”mܸÑ ätfÜ‚xH¦WK´|îÁrˆ}Þxã ï4cÆŒ\ÛàE„¼ÅävNFplûì³Ñó'?‘û¥"†žYØB3Opþ£Göùêzè¡P¥N´uIÏÖ¿ÛsÏ=£ÍÎèiÔuQ?µë®æ,µ;Õ Úa‡–‘VM‚£|1eõ §[óá:‚*D ­ ¨lKëËç>H§vÈ!‡¤ÿÉè D@D ¨l+ˆÚ„ˆ@Z@4lØ07n\žÊâ2®7BRá>tÄG8‡ÞBC“&M¼3âKáN"Ô=QÇÆpÐAYµjÕŠIpŶÁ,ÙP²Ê7ÕIfÉ(ÅOó‘GñéÁáôrÌ1Çä:bêÁH­HÖËÄà;+çZ(K¾ôë×ÏæÌ™c}úôÉ’3Öif:•o™~…u~" %Eàã?öft6AÐIÇŽš5kzWÄà3ò½Žg*„G ¬‡ƒ$b%>|ðÁ<‡R­Zµ¼£]»v> UANµy6  iO %Gkp™ bW§Á­‡T±ÛTò23à’„£½µþ)†ê+Zbm'ÑùuëÖµ§žzÊP’Ž‹JR¦‘Z-È+M¥Naq/ gu–ï™FÏ rÝÿõ×_Æ~áƒH³l ÷îé®·¹ôy‰À ևzh¾¡Í^GC†ä»˜fd1 k‘sœWˆ@ÚPÙ–Þ—P‚£ô¾~:zäPÙ–®Úªˆ@ò ÐÑŽŠÝ -¡È@hÔÑ3•ôB8à8D2õgñt‚ ñ#÷¡ï©I Yå›ê$SózgÃQqCDtË-·øÞñ¯¼òŠïM_йÓ`–ÍAéç"IT¾eÒÕÔ¹ˆ€”´ d@à¹~üøñÖ¹s縃÷MÒ`3ðÊž!'#Þ?y¿Dd„#n¬TkqíX ¥5R! ÂÁ'Tp°-lìµ×^^üÓ³gOoÝÅú¨îxà¦÷V2ƒ<ô íÛ·/öÝ{šA¼7ƒb?€Ý ûé¸Üæz¯˜~zâ‰ÃÑÞ{ïíUùmGp2®=ð€ÙW˜KÙ—ß’šžm&O6ûðCœÌrÎ\GÙö ÈìóUÙ–ž×Á¢ä†ÎºT!" "›€Ê¶Ü<ôMD 5 ¬[·ÎHóôÓOûÏõë×û¥3[³fÍ|ÏQܼqzÞõŒb9é©“âzIá@¤È.É*ßT'™]¿£Ò<[î{¸³Ñ ‘åÁl/¾ø¢oÄ*ÍãÒ¾E@J—€Ê·Ò寽‹€¤tW_}µ >Üw@y饗lß}÷-¶AdÄ p¥.8–Çž PÛ%"6 ÖÇûèóÎ;/˜dJ’-8 íL#%FÀÕ½9g,séøÌ*WNl·8R¡Æ<=ÅiÕ¹Ÿ¬BB\šx3Æœ½™þšG!4(+V¬°¯¿þÚºuëV {×.E@D@D@D@%€¨hÊ”)¾ÁJá5kքܘ:ê(ï¬Ísis>ùä“\»Ahtíµ×z‹ü\3ôED@Rœiï»ï>{øá‡måÊ•>õã%—\b7Þx£‘NM!" " " ™DAYŸ‚4e¼ßa¨ÒµkWŸ.¶(çºvíZëÞ½»m“ñvQ4E9­›]J]p„íVxüñá_G©‡åÿ´Ä¬Y³ÚŽVJmwÝeΦÍì‚ ?NÄh©éb‚÷ÞkUªÄZRó³‰@ 0zçs©Íœ!™BD@JÀ{ï½çŸ!¨BD@D@D@D ¥,]ºÔ^p½V,X`K–,ñÃâÅ‹ý'Âñ Z¶lé+œ»tébÛo¿}09ôù‡Ë-øˆ:µ=öØÃößÿÐ<ˆ€ˆ@:˜8q¢ÝsÏ=öæ›oúwX\Û®¿þzëÑ£‡O™ç cx|ùå—>Û"£/¾øÂH›©Ëp·ElÍóÂ# Vâ ¶E[÷d—Ž…ç«ŸþÙN;í4;v¬UªT)žMh(2”Uv65µk×.òI‘7[i‚Dx¥M‘7® ¤Ù³Íõü3çà`.•]â‡4uêTŸ‡²uëÖ17Bʬ­·Ž¹˜È2N$ì*CÌžxÂl—]²ìäuº" ¥J€+z@àÖ|Φ€t!ÁQ©^í\D@D@D@Bè ‡sÑèÑ£ 碿ÿþ;4ú+Eˆ†êº,ûì³|òÉ1Sãní*'H7Ä t"0sæLÃÁˆÎ24°uîÜÙu&½ÀÚ´i“N§¡c˜ÈðtÝu×ÙwÜaÿüókcÞÚZ´háSœažÂ€žaúôé>Mö³Ï>k×\sèTÒ®];«Y³¦U¯^=×À;æ´iÓìõ×_·?ü0ôŽÙ¸qc¿/žµ"P’J]p„Ò.*ZŠ+vq-ÿÍÔÛΈ9ÇÔ¯_âÇöÿ÷ö޳¥áæ^œ¿½ÄHk¦#´j»îjöØcJ§–Ž×OÇ,éF`Æ ¾wÂm·Ýf?ýôS®ÃßvÛmýK ®}»rcRˆ€ˆ€ˆ€ˆ€”Ò·“"è—›ý‡~ðNÜG8ëäsÏ=×öÞ{o/4ªZµj©Ÿv," %I7·«®ºÊ}ôQŸ.òüóÏ÷iÑ\ÜJò¸´/Ì'€@‡g‘Õ«WûÔÕ¤¯fÀˆ4d8!ê©V­š‚ñ5jxt"„Þxã ëÝ»·ÍŸ?ß;ÒÞ{ï½ù:ÓbŠÁ0Â5~i¶qÆL¥yU\JÒk3†ñ’BJƒ@© ŽPóAeÌï¿ÿîÕzÁ´D?.\Zu òn)2†Ào¿™=ù¤Y«VænΉŸ¶uä'Zâ{ÑšÙ@àÛosÎRGÙpµuŽ"P:Ö­[ç{Åßzë­þåGÈóÎ;Ïvß}wß#žÏâp‰,³Ó^E@D@D@D ýÐCõå—_6êŸpÖ¦>+|À6ãÆþíŠ+®ðÏn5J¿Õ‹€ˆ@ð.{ûí·ÛM7ÝäôŽ<òHßóžwX…ˆ€ˆ€ˆ€$›æ¤(?~|¡wUÖ¥¾A½ãŽ;Ú;ìà‡`7!†HC‹ß\#6COº†l:˜Üu×]vÑEyÁu¬Àý1áK‡ãU«Våè”LîV®¡¼B… ±6«ù"t¥.8Ún»írä¬Y³¬mÛ¶¹¦ö öÔsçÎ ­†Ý˜"sÜ¿ÙúõfEq7‚éÔˆ¢þÞüFô'« ü—½ÑvÞ9«1èäE@’@€÷ÝwŸáhD 5RmÜyçÖ«W/#­BD@D@D@D ä L˜0Á dóæÍ˳s*œ©‡¢sÓÙgŸm'œp‚©#\Lš "áe>þøã6dÈ#Ã.¼Ž>úè ?sžˆ€ˆ€ˆ@* Ó.b#Ò“‘’ïmÁ8iÜ÷„b”B„?3fÌ0ÄK‘Î!Õ©SÇ»9Òå¸ãŽ3\*%+V´¦M›&²ªÖ'Pê‚#ò†ÇG}TdÈìÙ³Cù Ù¶z…Nïq×9ÐF2kÐÀìÄ‹v.o½õ–qÃFª¢Gr8* E­+"Iàé§Ÿö½–/_î_LFŽiçœsŽ/»"—Õwäxï½÷làÀ6}út_A}Ýu×ùŠkF XîK\”üë =ˆ€$@j„Î.‰B£Ç{Ìn¸áûñÇm›m¶±»ï¾ÛH¡F¯}…ˆ€ˆ€ˆ€”Ë.»Ì|ðA/x~ñÅ‹ô®†ÙÉ¢E‹¼i³yÖa`üã?6R·áˆôì³ÏZçÎKê4µ(u¥þ”ß¼ys_!Cj+‚<ÎÍš5³Ž;&ëþýûçZ·M›6¹¾ëKúpm¯öë¯æœÌÊ•+üy|þùçþFÏÍþûï¿÷â69Dž£ÖÈM`èPsöøfõëçž®o" "N‡¢xÒžÑS⪫®ò–ó¼ `ŸÚ³gOÙ£†ÃÔ¸ˆ€ˆ€ˆ€#*ˆ9æßym·ÝvóikI÷Ã@Õüùó´h¯¼òН¤îÓ§ <Ø"]»‹ñ´)(qß~û­wgûå—_|zÕE;;koÒˆ "Š á¡÷LD˜Ã† óhªU«¹¸¾‹€ˆ€ˆ€ˆ@R ðrÇwXëÖ­í¹çž+’؈¥c 'ù™œà’„ŽF8')D ›”ºàˆü‡=zô°#Fxî¨ÿ®¼òJ'&)çíÆ s1Ö¬YãSŒ 0 ‚Êò*2ƒ€s ³[n1çðÿù|öÙgÞ.…JD¢^½zvñÅ•„ (*wó®[EÝŽÖÈ\¯¿þºuÔQÖ¡Co#OÃU´ 7éi§f'NôÏ/¤ë@t¤Hê 訶dÉ/.zã7ü³X°7ê­ê«N9åïÚѤI“`¶>E@D #"²mÛ¶öÛo¿ù/Ô¯3zUîáAçÍú®× j|ÖªUË7äÑȆ w£‹.ºÈ;Á…¯§q( d ¸æškŒ,KÔ³—„ñûȯο$ÎYûÒ$Pê‚#NžœöˆAè=AгÿòË/÷6g]»vµc=ÖªT©âçEûÃz䄯µÑQx\rÉ%J=$ÍÇ;¹s°Šï$¾ùæ»ôÒKmòäÉ~^€ûõëg]ºt±ƒ:ÈÊ”)߆´”ˆ€ˆ€‘À_|á·ðÚk¯Ù›o¾éÒ×^{­m»í¶¡-çò3žp Fù…£Ñý÷߯g˜ˆ€ˆ€ˆ€ˆ@lô*:uªñ̵‹Ëy}á…úmù­.6zâ‰'ìÔSO5ÒáˆNz!Ž5ÊpŒX¹r¥|ðÁv×]wÙþûï_ðŠš+" " I&€àˆÊW\pe8p wt$­,´ô¶ 7þG‘ä£ÑæE@D@D@D = PAMãø'Ÿ|bŸ~ú©½ÿþû6kÖ,2[l±…µnÝÚ?kyä‘Þ ûöÛo÷®DýU2Ú¨”&òù™ú#" YBà믿öb#:oŽ?Þ:vìXè3ÇÍG9…ˆ€ˆ€ˆ€äG€N ·Ýv›ÍŸ?ß6nܘg1ÌFè„O<úè£6f̘|­]»¶!†Vˆ€” ”qºäRDqøÈ#ø›–­… n ¤Ñ:æ˜c »ª–OAîRºBÆœm¯™K¹™o`ß‹U:À(Wa…®T €à¨Aƒ¡C!½çñÇoˆn¸ákÚ´©½ôÒK¶ÓN;…–шˆ€ˆ€ˆ€d;Fo¼ñ†¯+B`DúÜ4‚ búŒ3Îðu@íÛ·Ïe—«$õçœsŽwÎ~þùç}G·zõêYÛ¶mmÉ’%¤Q ¶§OÈtîÅÙè?þðbHï­â&@w¯^½¼ÛïlÔ7iÒ$ô‰iÄÌ™3ãÞ-ï…t6!å+†%«V­ þù§µiÓÆo?î jA"H)ÁgCo³Þ½{ÛÉ'Ÿì&# ¡õë×Ç}ü³ é;" " " " æÝzè!Ÿç(»ü<л·hÑÂÒᨠØgŸ}lÆŒ¾·,GT>³*¢I·¦ŽJÑÓ<L%0}útC`DÝsÏ=gÇw\¦žªÎKD@D@D  àLÛ­[7ÛvÛmçFå9šýöÛÏ>úè#£³IåÊ•óilO<ñDß³öÝwßõb£®]»f:rŸˆ€ä!p÷Ýwû{"Îtô%å·BD@D@D@Š›Žÿ¨ù•W^‰*6bŸt&™2eŠÏ`³Ûn»xK—.µ_~ùÅŽ>úè—ÓL’%²‚£•Iˆ‰8à€`²>³„ÀD?Q,Ô©¤’м #RSˆ€ˆ€ˆ@ªàåŠÈOpägꈀˆ€ˆ€d ,îßzë-£‚™!v´¨Zµª·Å_¹r¥ïÕŠÕ>¶û4„#*ŽÀ¶ŸcÁÝh«­¶*ŽMj" "6¨K%Åä3Ï<ã;nR—Š;€BD@D@D@Š›ïu:t°ß~ûÍ&L˜P`û>‚#ç¢X‚#“ˆ`ÿED@J@Ê ŽJ å,Z´ÈW:Κ5ËzöìicÆŒñ“)w : pæÏŸï9D³Œ È$¸Í™3Ç[â¿úê«öæ›oz§GΑÊcÞá÷Ýw_£zùòå¾:ø\½zµ~øá¾A¼AƒIÃ"±QÒÐjÃ" )Jà믿¶N:yç€Î;)+u/LÑ‹¥Ã4'°qãFÃ]vîܹ>C i\ Š@<„à¨G-êEI,¬Sàš)"PbRRp´iÓ&ãE¥âŒ3ìæ›o¶­·Þ:*”‘,{È!‡x…$6ÜŠô%àÖíÿÙ;x™Ê?Œ?–¬%{’$eiSZJ)IZõ¥PHi±”JRRÚQ´H* mJŠ”RB%Ù%’¬Qþ¿çsïÌÜ;÷ÎÌíÌ<¿ÏgÌÌ9ï9ç=ßsÍ{Îû>ïóÛ¸¨P!÷sàß'Ίù=zôÀÍ7ߜ ‚ óy2¿`™bÅŠÉ¥1?PZ/ &R‚#þ=ÿüó9r$¶nÝš…‚¤PÁ|cÇŽu^Å‹GÓ¦Mq÷Ýw;)ØBm£å©KàçŸa¶¾@¥Jcß}‡aÇŽ/þ”,YÒ±ÿm×®]ꞈj&" " { Hp¤?t#ÀÔ<œ}úæ›of;‰9Œ³M4hà|5y,k#}ˆÞ½{cèС¨Zµ*^{í5œrÊ)q;–v," " "º8ÎNÇ!¦8ó9ÌúÞé>[±bET«V-àÅû‡Â… ;å9ïÿÚhÎ\ÇôלhÂ?Óí–bg:=üðÃa9á„ðé§Ÿ‚޹ÜW¨àD—c=Ö…*£å" ‰'úm‚ëò×_¡oß¾øè£¢>2gj|øá‡øú믲ÆG½/m˜ÖV8±~ýlT¯^t¬òÑî÷¦›n’]^r.Ž*" "¦T+]º´óàÅæÚDD@D@D@RŠÀÒ¥Kçáï¿ÿ]tÚ·o“N:IF)u•TL'à5iÒ'NDåÊ•3‰Î_D@D@2–À¥—^Š×_=¢ó§ ˆñßÿE´]Æ ñÒK/9‚¤p7䤕÷ßßÉhT¯^½\7[±b~ÿýw'Ml®´PD iRBpÄ«:€Vܱ*+;uê„:_±Ø§ö‘>Ǽʕ Ë>/1µÒQD@D@D zt8:ôÐC£ß¶!0}út§ŸeÓ¦M2d8 ­H-wÜq‡ãlD±Ñ»ï¾ëL€I­ª6" " " ‰"0yòdGltÚi§9F*UªdYf*9“cùNWZº­\¹2Ç‹ã÷p@Ž‘˜‘†ŽDþ/:)Q0ÄL5‘G ¦L %8ò¥\ó•dÿ*+"_)!8š6mZ±ÑþûïK.¹§žz*Ê—/’Âe—]æäväÃÓ¬Y³²Êñ‡î@‹-òÜ>k}H t8*Tè/Ôªå*gS¢Rª„ˆ€ˆ€DI€÷#Ë—/Ç™gžå´™ˆ€ˆ€ˆ€¤áÇãÖ[o‡§L™‚³Ï>;5*¦Zˆ€ˆ€dèß¿?î¿ÿ~4jÔS§N•Ø(‹Œ>ˆ€ˆ€ˆ@æغu+ºuë޹3ÕY•*Ur…pðÁƒ¯dsÑP$·ð Ž|es+£e" É!tÁÕ‘?þxÀÙS$4hР°„BT^Ò¾›¯Ù³g;iÙ˜G’ÁÒ'Ÿ|ýúõ Ø¿¾¤&ºò}ýõSÅÎÁa‡ÕLÍJªV" " "Õ«Wƒ)_kÔ¨ÁV**" " " ‰%Àþ”×^{Í™ÐU½zuKqU«æTäúë¯Ç˜1cP·n]Lš4 µk×Nlu4| < pÒ\rr.¢ Ì%pÏ=÷8“aGŽRl” tøÜÉô¯>QQnuâ::'qĹ­Ö2$HºàhÁ‚Xºti¦6lŠ/žµ,Ü7vrR·nÝ´÷f¼òÊ+¸îºëk¸p÷£rÉ!ðãÀ¶m…ìàs•z&9—@Gˆ1¦Sc(¥šƒAÿˆ€ˆ€ˆ€¤E‹áöÛoÇ[o½•kÍ *ä¸clÙ²çž{®3+¶L™2¹–ÕBäx衇œI·õë×Ç{ï½ç8$¯6:²ˆ€ˆ€ˆ@² ÌŸ?>ú(6l茓'»>ùŸ©Ò˜Â{×®]ØgŸ}rŸ7oxŸS´hÒ¥ 9ê¦"é’ž·ŠiFüã–[n‰JläÛóMú;ñ‡‰hŠÔ'ÀtjnÌEÍšr8òÑлˆ€ˆ€w øGr8òî5TÍE@D@D  ¬Y³Æét>ú裱QÛ¶mÁéo¾ùÆq01bz÷îí¤º?öØcÁ™±“'O†ÄFéø× sð:Gy}úôA½zõðÁ \¹r^?%Õ_D@D@D ˜]ˆfœ@òôÓO£pá¤Ëò= Ž˜)€F%Áñ믿bÆ `…ˆ@êHº pÅŠThÏ]ÐhÙ²%n»í6ð•ÁÁ¾&Mšt·Ú>ÎÌ ooÌ1'ˆî¾/zÏàȳ—N´$°yóf 2œÞ¶mN=õTç{ƒ ²Î÷¸ãŽËú¬" " ©KàóÏ?w&Þ~üñÇ8òÈ#ñá‡:©1S·Æª™ˆ€ˆ€ˆ@"<ùä“øê«¯Ð«W/p‰Â'&bê´ã?> Ê¾Tk¾2+õED é’.i\¹reÚ tÐAYߣýÀtlÕ«WÏÚü·ß~Ëú¬©K€G%Jüm\.‡£Ô½Lª™ˆ€ˆ@8û‚¡”j@SQ˜øâ‹/pÍ5×8}.÷ÝwŸóÌýÎ;ï`ÆŒðÅüÀÚ¡ˆ€ˆ@Ì |÷ÝwhÓ¦ 7nŒ™3g¢S§NÎï9ÿ" " " ™M€n¶ÌtÈ!‡ ÿþžáùÄEþŸ³7EޝŒÿ:}H>¤;ùçZܽ{·“›±H‘"&C›8_üþûï¾zOQ–ùß~ ³g_„={Š£jÕª)ZSUKD@D@Â'@‡#¦‘¥}øÌTRD@D@D 6Ö¯_±cÇâùçŸÇÂ… žtÒIèÚµ+®¼òJOØêdž„ö"" éAà§Ÿ~rR\¾úê«Î µo߃ BíÚµÓãu" " " &н{wüõ×_7nJ—.]àý%jx 363øøÞéìC±‘Ïñ‡££M•ÛÜM:ÿìØ±Ãymß¾Ýyçqzöìé¸Ýz G ¦Pó Œø™á[ç|Ñ?" )E é·ÙœeG«ï1cÆ8`vïÞ®]»¢_¿~6‹¡]Döh7nD§NÒ©z衎ÝlJQWer([8äE¶ü/Õ̱^ D@D@DÀkø`ÈàÈÁ D@D@D@âD€)Ó.½ôRg@ºAƒŽ…~uÿÜ8W»ˆJ2uÚÂ… ´˜Ã† ‹¨Ÿ<~5‹lÏk׺"" ‰Ì˜óæÁMÝ}0mZß¾Ùû+T8ùd÷•½4úOõë}úÀ&'C†wÜý¾´¥ˆ€ˆ€„@Û¶mÍuÏl÷öF‘"E'"ºQL¼fÍüý÷ß¾ÕYï*TpœkO¶²Q£Fàó·I×ð‰Š|"#ž§ï³o]ºž»ÎK¼L é‚#£Àˆ?´To2¨Ôd^jÎÚhÓ¦ N;í4vØaκÜþáƒme¹ª9ýãöÛo÷ÿªÏ)L€ª]Eb ð:µk^¿‚ª¿ˆ€ˆ€¤>™fA±;¨Ù·òðãX±b©_qÕPD@D $ºœ{î¹øÝrŒ=òÈ#èÑ£GȲ©¸‚"£W_…õís0»†t:ýtXJ8÷e‰â6Ä€I“€a)Fa“ã~H@D@D@|ðÁÎøu“&MPßÔ°›7ovÄE|ç‹€6lèŒrâ*ÇH}ïUªT ØWº©T©’¹VÏñ|çÌ™ƒ²æZ‘—N ݹèüD Õ ¤„àˆjÌ#F8îDþ‚¡Å‹㡇r^ü‘©\¹2Ê—/ý÷ßßù^kO/¡TŸOç¤SO=5կ귗ÀÒ¥KOr8ÒŸ„ˆ€ˆ@:ÃQ:\Eƒˆ€ˆ€¤&yfñ /`äÈ‘NšúñãÇ;} ©Y[ÕJD@D \S§Nu~Ïÿûï?DZ. wÓ¤—£Èhôh`útÀ2}ZÊફ€fÍ\Qݺ@!s1ŠGØx-.¹¸é& uëì#Xr§NtNêØÑuY2S …ˆ€ˆ€$„ÛóÞ½{£D‰ŽqÆÁœãzù t2šª´–»á†µgneò[V«V-<ýôÓ¸ÿþû=™×:¿óKÇõƒ‡,YòG–ƒU:ž§ÎID@D ³0¥Z9óŒ§3£BD@D@D@¢!À±Ã‡w&iÕ5kN¬Ú²e ºwïŽ/¿üÒ™í)±Q4dµˆ€¤ûî»ÿüóèZç5±iZ¢0Ú[omÛÂú÷ ÆØ²É¡_?˜ø*ïýXæ9PœDA‘eÍ5ú÷è°Ä÷E‹r-¢…H€ÎXœ ½aCΓÿâ ÷ï*ç-ð0UÚwÞédïéÛ·ox©T–¸h®åeå‹!Á‘þ0D µ Mµêí»ï¾N^êË/¿=ö˜åXžänýúÀ/¿ÀÚÊÐe(~bº7›ïŒ«¯fÍ‚µ¥¡ËkMz`‚ ˆ-Yâž§ C¡[·Às>ÿ|€b¶òåcu_GìÙ˜†f¸ðN‘Ý™gîCßD@2›ÀP³Õ[½zµ“݇ð0#ƒb#7 ŽÂc§R",)'8ò¨\¹2î½÷^ 2û›ßíÎnùòåY/þ@—·;=âñÅ\)£žwÞwïvoÒO8á_ëD]åäáôNíUSÈÀ¿ÿþk3,W¢>{>" " " "!º]pÁ˜>}º#2m£¤Å‹p/*." "àt7Úµk—ãdç•:?õpÖYîDÒxÔ¹J Kؤd`ÊàÜsC%/±‘o«F€ž=]$º'Ýz«oÞ3EDO<KS W‚9I0ƒI›‚¥ó¥Bâ 7ðñÇe‚¿x`ä‚#:x1 …p ô"°fÍ 2Gq®½öÚô:¹8Ÿ ÇÿkšK…OpT±bEG çÃj÷"  wÁíâŽ9æœqÆàB¤AÅD|Ąˊ´"PÔþ./^Š þs‘´:AŒˆ€ˆ@FX±bv›ª–Âh…ˆ€ˆ€ˆ€DB`ƒåõ8çœs0gÎÜtÓMŽû³œœ#!¨²" "à->w£fÍš9.v^¨ýW_ÁÚ(Wp4mZüj|ÛmÀ3ϸ.G>ÁÑâÅnª+nˆ8ln3Þ~¸ë.à¼ó€Úµ#Þ…6H-Z|åt¿ò×ÐÕè×_9†p<£T) téÀ÷rårÛSèefjæˆé˜ðÙgB—Õï¸Ëš­f…FÑQQþp(""@—#:ý+V Í›7h[H<¸‡Îž=wß}7š4iâX5ÊRg­Hü™êˆ)Mà·ßìŽÝ‚nU ð:v3Ô®9ôˆ€ˆ€ˆ@˜èÈþŠØ—òøã+}Z˜ìTLD@¼JÀçnÔ¿OœÝ_n¸(R6,¾U®Z¸æ€§wß~ü6ð\tÀ´X‘FÉ’€ O8i±¬É +(6yã àÊ+ów¹ k‡*^½€ƒrÅg–u6¡asâm¢4LîºÑ‘è¸ã\Áë©Øˆ•çü4¦ö£ÃÝ–Ì([!"&,X`iÁ‘޼~%UHÅ6mþ,ËMÃIZYþ˜nݺ%îà:’ˆ€ˆ@RxÑ݈î/}úÀÚ+Xª˜øc£Ë`z÷~ÿøóO`üx€i±¢ ŠE>û,g­¼öEG$ºôÏœé:ÝPl¥H=€áÃ]G¡{î^yxúiÀLÁ<õê_~ PФ¿)O_JU^ô¢BÒbèСËõ%|þ"#ÿÏáïA%E@I î‚£† ZŽå)عsgÀy-Z´|1Õ«WÏgÒp¦QSdŸàHN™uÝu¶" "®$8J×+«óè lß¾wÜqV¯^íXÃÓÞÿ5fÌlÚ´ cÇŽÅW\ý´¥ˆ€ˆ€g¤‚»…L/F7¡pã’KÂ-YðrÕª:O> k7×_Ú´)Ø~-SKŽ Î÷°ÃÜc•)“½šC/¾Œ<ú¨›’í‚ ²×ëS| Ür‹+6jÞxë-`äH€©ñø–­(lñÙ¶mÀí·»®YÇŸzS@tì±@‰9÷O±ofb‰K/u×W©’³œ–ˆ€x—À{g÷ßÿûßÿP¿~}ïžH’kΔjÔ ÐÌD‚£$_ ^ wÁÑý÷ßïØ€úé§øàƒðñÇãï¿ÿ¨ÚòåËñüóÏ;¯J•*á KÀL÷#Š•öÙgŸ€²ú’>xƒÍ |@ýÕ’ ¶é1‡rHúœ ÎDD@D c °]cÔ G¶BD@D@D ã üiÀçÙhî,æÎ¥J•¤I“ЪU«%´XD@D ¤‚»S•]=pã@‹@‡À…¥K§iö!|°ëJdf€1-[\1 Ó¬=ôëbDq“/(Pbê,¦¾¢àE‚#™ø¾›<â:½óŽûwIÁPûönZ?RÂäÉn™p´Ú'Â\$ÝThñ½öš;ÖÁ¿¦ ›i™–0¯Ø¼Yc$yñÑ:H%İ=ÿᇜ׳fÉWÒòwRP¬ˆžÀþûïZµj9z‚ƒØ+D@Rš@ÜG<{þ¸Òœ¯]»vYÎ寅çôéÓ±~ýú@üþꫯ:¯ýöÛ§vš#>jÚ´©³Ÿ€Âúâis简ÃèpTͦ«H`æéKªÊ‹€ˆ€ì%ÀÍ *€÷2 Ì&°ÒF/Ï>ûl§º·åƒyàœ¾‘þùþ/Þ7”6?Lf#ÖÙ‹€ˆ€' øÜ °úÏŸÜy'0p püñ€%Ào¸>S§ÂúìâÅÓOw]è|D‡¡dǸÎ4ñªÇ¾û?ÿì¦n£6xÝ:Wàä<:ÑPŒ5aðÓO°PÿµúÙ°“ÂÏ_G'*þ­¾ô@¤.]`™&Mò®ÅèÑîß÷å—ç].Úµ­[+º¢µk¯Šú¾q>ÓÂq,$/‡°‹šàou´UÐv" q"ðŸ)9Žù£©ùZhy6)2âç­[·f•®<ƒ6‘ªD2YP¢ü@`>/+D@RŸ€ß-Ob*KAÉ)æÉWÿþý1ßžrè|ÄŽüƒNH“M¢ÎWq{Ò¡èˆÎG!Qݨð6 Ž'û[øÕ¬Fuè_ð8 Žänäñ‹¨ê‹@ŒØd7{ξÿÖQ⦪`¿,ü; cq¸ÿÌ`œ¡mz†€xó͚ؾ½RÀ2}ˆ?v@·lÙ 6 ={ötÊ>¾" " ™I€ÏŒ/¼ðN=õTK ÕÑG¦§3}˜ *fº`ér˜Ù!˜¢¾s<žY Ìà›6¹<ø·ÄtftÿÉ+vï†M’€¹EçU*pÅCáŒI›¾œ rõÕÛÇúS¾ÑEÌ?¶msjÕ«»i ý×鳈@jØhêÛö#Æ×† Àqì5j˜óßé8âˆ#²^Gy$Ê–-›Z•WmD@D I’*8 >ç:uꀯ®6•`ÅŠŽøˆ"£¯¿þÚnínpoükSwÙqÇ×@{Ú©gOIt>bÊ6þð+RŸ/'GÖ&cíÚ_ ׬Y3õ+®Š€ˆ€ˆ@>xÃ{Ý“äJ«E Cp¶¸ÍÀÑGœñºzuöË´‰Îwsá6WWgM?ñDäp¾øÂýKÓP{LÊÍš­¶Ùìës,×øxçwо}{›¡^üÌþ …ˆ€ˆ€@²ÜJ”pEuä|´më¾è¢ÉûKŠGÎ9'¿-Óý 7¸.HouîœÞçËkìÆÃtr“&çž x<ö÷_|1ll6¹Ø}®á2:1Ë·£à-·˜7ÏåIAS¥Å28A‘fm)®Ì‹£³øœÓS\+¬‹€88yôá‡Æ3Ï<ã¤H;Ìr7R|¥Ùú•öÏé(^" " 9¤”àÈ¿v|0:uêä¼þøã³qî¾°žt:øÇwß}¾ØnÓy)>â‹6vŠÔ$`“;Öœàɼ§ ŽRóZ©V" " ‘`ç1C‚#ƒþŒ!@Qg|3[’¿®`Èüðñ†¢#¦¦ ?8ÌÉÛ:¸‚—fç t¦`J |h¦u6}D [óHË™ÁWy³Š˜:u*N<ñÄDWCÇHa·Ýv›Ó¿Hw#â(TæÐ9 (š4‰|»tÝ⪫€¾}am}z Žè0äs$bú=>§x`öÕ|ã ÷ü™&Ï?LÁç :­RØöÈ#nú=>Ÿ°ÿŸ"#:gYæ!Œë¦ðómÃ÷Y³`éºÀž¾ëDÄ¿×h‚éY_ÿçª3(ôè>”› (šã„» Ój?ô['îRˆ€¤ÿþûÏIyýóÏ?ƒ¯Ù³gã•W^Á?ööX›ÅÕ×~äÛYþENQˆ€ˆ€äO eGþU¯h^›—\r‰óÚ²e‹åÚáˆfΜ‰mô£ô _ñ¤%RfþL î¸ã¿ú˜l± zN Þä?÷œëp¤”jɾ2:¾ˆ€ˆ@,üú«ÚµXpÔ>D Ñ8k»¨=щ(ÁÎcï¾ëŠüGáœg¹2¥_ÁñôÓnº{ô1!cðZ÷{·nñ?رž{i-ˆ5:N²)ûq²ãøãÇøñãIQ±>žö'" "à]ï¿ÿ>^{í5\tÑEhÞ¼¹wO$ƒkN÷§~À—_ ¦ ›óí…èÂó×_î9Ñ•híÚ@ÁQ÷î°y˜¨:§ÃÓ›™öÚùSa3Kla÷®RÿþÀ]w¹"8–cJ´.]\‘ŸÇ¢ ŠŠZ¶tÝ”(b¢€‰1z´ûÞ±£ûž¨7ovS]ÓÙÖæÊ;b¬D[Ç$0mÚ4<õÔSŽÀè—_~1'êš5kæΑ•_}pxBpä"ûî»/Z·ní¼Ø ̲;Ç>ø}ô‘Ùºnò/jé VãKÎ+ÁQ–¤0À}Pyî9XŽS9%ý‚¨" " 1% ‡£˜âÔÎD o¿uEA‘L4ã¬R Š˜vŒ.Bì ¿óÎÀ]ÛDs|ú©Û)=fŒ;ˆX"ô·;€tÓÜtSèrѬáý2;¨[´pëç?»˜û³ñ*{æqSÄúØÑÔWÛˆ@&X·nc¹OÛý•+WšËX1\z饸Éþ36‘D&ý)è\E@D ,;즑mû·‡Ö6*”š˜™‚#–ð¼àhÍׇ8·›iÒ(¢8¨zõœüé`töÙî+çÚl‘Oð:º1½]‘î¹°lEŽK+ËQDǨ‚'hP5l˜›¾Œ38ùyâD×]©ví‚!üímÞ¼sŽrÙ|z\w]øÛª¤ˆ@l ì±¼Š7X>L¦Mc¦•ÖÁÂl9¾WSDÆÛBNöMUªÛsÓÞD Ô×Y—…Ó.…S^eD RžùŸ`ñâÅÍötçÅ…s쎕â£?üД÷&½W¤8û»AXº<·zL©VªT)pÀ)W_UHD@D@"% ÁQ¤ÄT>S˜Ñ̵*ÀÒ ¹ïü\¦Lx6n„M$ž}6@tíš½;qçÍsE9>!ÒâÅ€M wÒÐBŸiÉ\o9‚3l9C™‚¦H33³ÓÝæ?€udÚ€X†½:äƒì´ö+ÜŽkÞFå¿FŸE@âMà³Ï>³”çÛÿû`JøAöŸôÚk¯Õsm¼Ákÿ" "àa÷ß¿ã¬ð°YT«V-ag²{·ë®rå•ÀA%ì°i} ºðüôl°Ú»§ùÛoî¤ >Gp ’n«ýú¹B#Ÿ3P¬ÏÎn™œI]vY¬÷îîÏMË–fVâ'hPHE—¥D†é aÖ¸qnÚí¼Rd'²^:–d"O>ù¿ÙÞí–reðàÁqCÀ>/Ë̆ùóÝŽìûòÝßÎ8øê+9Sû˜è=q8±’©M=èØ¸ûîü½~=°ÿþ±ïçÌÿÈ*áEžùg.ÍF9¯»l´`Á‚6Àð¾#>ò/§ÏÉ%póÍr™îÁ—‡™©gâ­NîYëè" " ™D€íZåÊ•1m&·ÎU|ØYýçŸ@•*¾%8¢œÀ¥n³Zµ\‡32Å)§¸Ë‚ËQÄY·Ì¤é:Äml"›¥8Ê]lx¤ÀoLÅvä‘À#.Oô7±Ín6IÏ9ÏsÎItmt<È\Ls‰X•+W3gδÙù—Il”¹:s›ÀvƒüåRyÒòp-»9ÀSPPO—ÎPñÜs® ÿÿ UBË3‰À[o¹NFtue_=Ÿw%6J4gºPÍšpà¿ý}t÷˜¦/žøcëˆ" .mfq6Ñ'XÚ•ºuëÆ ]lHÚ1Õý/¿¾1Pß)îd¿'Çå&øð•Ó»„€%ƒÂر®Û»ÿ~Ø=ñÌé –Þû¹];€“é(O÷wm°¯ÑæUÃŒ9"/Ø=Ýä{¨Ø H…i¸¾·_åBf“SÉF%(X9ðÀcwí)æ~øÁMÁ&_¬^½ÚyØfÞT…ˆ€ˆ€x;׬Ycn*f§¢4&@qPð¬T>ÔÚ-ºã>D›èà h‡¯PñÍ7À;ï.Ñöžý@gŸ]š>¡l÷ù LA_tW2@Ì‚éènD;Z´ÈÞ5]†â•n û(9?1]Ï•ƒC†ä\¯%" ±'°Ç¦¤ö²¾aÆáˆ#Žp&7rÈ!±?ö(" "v^zé%LŸ>]ºtÁÉ'ŸÓó3í«“ºÅß]”÷å>㽕+ÝA':‰ªë<¦èÃÚÙ½÷º® 6µÊ³n–=ä¦fN†'ÏÊÅxåa‡|Kyãkw" ž!ðÆoXšú¿ñ¿8¨nÿúËpÇÉql‡)<ÊkB'ÂÑi&?mÏÀUESŠû(O=ÕÚrh¢eËœÕ3Iʖ͹œ÷œ¼É~Ovs°ï'ùݺ@е+L‹‘s;-¤ ޶nÝj3/¾ÅüáØŸ“ׯðÞÚÎ0/ºgLz·páBlß¾ÝwYï´¤¥•ùÅ&Y§I‘Z˜²{w7磯fŽ1$8òÑ»ˆ€ˆ€— 08…Ñ5¨~Pˆ@š˜7Ïßð”3`|qÞyÀï¿û¾EþΙÙ|1u÷íí|,ÅF< vÂOš› çÚðÏ™Ã{W÷üZµêÔqgE~ÆÑoAG¨NpSÌɆ;zŽÚRÂ%°Ó¼ïi¿ÿš©!›ZnÆIö£@‡#…ˆ€ˆ€äG`“å¿¥ ?'Ì>ðÀùxýgŸLOìTÐñèÙgÝ”»PâwqÖº">zötÓ”p¢üã‹/ÜkÁÛ¦CN…àsVðä‘T¨W<êÀÉ!þFâq íSD µ ¼øâ‹(V¬˜9i›•vƒ®itŸ¦ð‚îiÔ0ѱˆ®Ûl{+VÌûüM’Ø(oF™¶–©öx/gž*¨V­`gÿê«îß%ï7è2I˜´"GP¼Ná4]ï»xôÑEr,7Θyùå9ViAš(šèó›;w.ž~úi³êü»vír_ßFò5Êfï±\Óö¿/DPÀÄ×»–eË—/¢¤'‹SløÇ¯ôc³PJ5*ú," "àUL§ÆP»æ`Ð?)B€=sãªVj×v%80ÁÏ|¨$«Ã§Ÿº'<#&ZPn˜èf”JAVœ©ÆTœÌ´äðÞ{Éé,¢57ë ˆ?¶íœ ËôiíLe9ÖüÉ‹+/FüÁë" "&î¸ã¬[·/¼ðB\ĪƯ_Ÿ ‹]­¼O<ýt7E±u©;ÏaÌõÍÞ‰>ED€.R}ä¦Òé×ð–aÚšZuîìŠÂÎ:+¢]Ǥ0's”*ì»oLv§ˆ€ˆ€g¬ZµÊq¼ÀA±/f[Êti öQ|Ä´¥üWˆ@¤Ø_Û©ìofÌâ “o»Íí«t_—à~Pü<éþ|å/ºÈMøÔSÀ-·Õ«ûÖä|§èÎÌ<øùg€&$ŠÌ!P8Q§ú¯ýµßc¾ÿW\q…ÓQç…s|>˜=øàƒyŠü÷ó©õþ3/v$Çðß^ŸG@G‰c­#‰€ˆ€ÄŸ€OpT£FøLG0Ø-4h#Ï|Û´zæ Û‘#ÎÂeZ Žh™ûä“aìlo m8Ë%ÆÙ ¯@’J2½S[Vgs:Ø ÀŽû“T!VD ®-Zdv÷Í5¢–Ó‡ÑÓ~8Ç/±Q\©kç" "^¾úê+gâí©–ß‚Nyñ¦,fú _ðÞ”³Ð™®Ø’Àt³¸úêìk¾rz: Ì˜á ¿üÅF<'|p’]Sé@·ØDhL«ÂÃ<æq'²J:–ˆ€$ŒÀ8³[¡}¤éÔè•A—˜ùó«zà @·n0·$ØX·ÛÖDldÙÞðÈ#ÇÐ·Ì @A8Ó•QlD§,ö±r™eo·LNîßV$$,{/–,zô€ Ü#Ù2ÿ²ƒfúŒþýC—ýá7ÃÝðéÈnrÇ)ôZ“n&8ºóÎ;ñ*ï¾#Œ,ÉîĉCnU’#$¹Ä7öTõˆ~©s!“ØEÌ]úÝw¡éÉ "4#­ð ޼s­¼XSv[VâÁR›0Ù³-[WsÁ7»™3o-m=V¯>ùĵ{îÓÇ}e®îpƒ‚#¦>ËIJäuÙeÀ›o ¸ò²Ã÷/GåDÀæ[¯2SµuÔQŽE³fÍœY±Ã† ³Y¬…¼qª¥ˆ€ˆ@Ò üm7Þ×X³"¦Ô2u jnswaÍÖ®u8{^?œŒAÑW¨d uëo¿í¦¶cJæ¥KãWÿ=Û»ó,HÑQÛ¶îß‚ÿz}t'@wÁŠ–ç,¿ ;Á8ÙŒ©¡Ø÷ã–!Õq§¶ßâðÃý×Fö™Ž4 ÷îí¦ÁŠlk•ö2mÛ\qx™2®(yÌ·Ÿ–©Õè¢5apüñîç9sò?Óݻݿ% 8Á4ÖÁÔ¤Ñá(·àùP$E¡e &ëpê×]ÅJŠÌ P4§ùÖ[oá J5s‰}Ì',”Ø„®HìÔ ŽêæÙÕÏüI´)•mÚàhoβ+9’²7^±_}:í›ÄÑ jþâtr‹<UªTÙ[»èÞvìØáì¯B… –ú"!—/ºŠÚV¼tÌÍYõå¦ cJ5^ÃÒôTˆ€ˆ€x‚@&·mù] ¶kŒ¬Q£F~Eµ^²¬YsÌp…?öç“#h×ÌŽ K;ºìСÈ? rg.sÓ¦±Œ/øÙÿ;—Û-©ó²1t'6ohËŽïš5Ýe¡þ5Ã'egzej<ÿ<°aƒ;»‡.GŠô  ¶-=®cA΂éÙÙÏ0eÊg7­ÍŽß5jTÝj[H*X¶o^ê“L*t;8YµiÓÆê ×þ#8]=ÁÁ'ÓÎ:"˜üîñ\µŒ<\ãÆnŠfºµléN©T)4ŠÓNsûÔÏ;Ï-_¢D財Öp²Šý:)´})NB•Õrðµo^»b‰¯ïSjüøã¸ùæ›-]•å« 3ØGG§@ºÏ˜FÜ‚bUŠ3èC·$¦Ce]8A7sNääÁ$Üb„SE•ɃÝÒ'O8±lÙì‚t$|çÀº&ðÀ®ðhÆ €B$þ„ ö³ï˜ýñJ¥|¬þýƒ—d·ÿbX¸vÏ ë?q—StD¡SÍ.ì Ÿ³·Ð§t$wÅÊ›Šý “;í®¿þzûOrŠ+´Öý:wî\ø”ü}ôÑf+6ÊþÓ쟵Í~æIzî¹ç¢±Ý¹_j^v>wm&«›d‰¬™Æ-ñ‹ý¿ÈüJùÉèÚµ«Ùíu‹¸*L7Æ$Ž?ýô““ó›;à`f%{*iÒ¤ ÚµkgjÁã#Þo<7àÛí·ÃDa®B37±ÏëJpÏúiß" " ÑÈä¶-bKÌ»”ââÑô†s•I;¼5|üq÷´ØÿA þÈ~ÙífÍr×óA´Zµœ¦NumsY–ÎC‘gÙòÞîGù…iühÚ4¿’點÷µL‹ HjÛÒçZF{&³Í"®¥þ±Ï×K‹8…ˆ€x˜@,Ú7/öI&û’q-û§gØQ÷îÝч™qˆíÛ/¿4pÓüævˆ³ÎÊm©–%‹Àù结G®»6–9».L·Fa‘/8wyýz7M';,[0EI¤ÁýéV*/©O@í[ê_£T¨á‹TaXDšÒ”¢ö³Ñµ.RT§L<þN_{-,•7L»o¡ä¶cóäpÚöZöÖ¸‰Lr;¶–¹éQM¾€ /tûqócB§yöõRdæ ŠÂC»"è¢e·‘Î8{^B4º Qhd%NùPûŒçršŽØ|-Ç­ËwþÿùðC×i‘¢£cŽÉ]â+¯wàè£>² Áð >lÑy(¿à¶ÁÑÛüåüÅFþëË™_Øpûu>Ÿwï{ƒ.GÉýóÏ?f]Ö3Klä«O$ï+V¬Àm6mz^.É)äúý÷ßç(ºGn¹2† bù íI"‚?0Tbžxbè|‘b­5oßæÍ›§@UüdzÛ–Ÿ fy”®sÊ¢"­ 0µíb#1hä¬%ŠTFDsÆ­oiw¿n]ö‹NB<g½P;Ï|Þ,ËY!ÁÁÙL™ÑÄÎmÿîàýûç *º0™æ]!iA@m[Z\ÆÄWÖCë³Ø§sò)œV¨(hûæå>Éd^:ö×vîÜÙ™ÛÁ,Ay䑸U‡é”9süá‡C§¸ˆÛÁµã¨ ÐihÕ*7õ !ð9ð䓟Ç8Ïúûï¦BãóW4b£¨+¨ E Å ¨}Kñ ”"ÕÛe* Ž 3M6M/" ö¿%*,ûª3ù¢ ¦rcV¦Y£Ø$T¿ãe—ÁƇݴoì;ôóçHTµÓæ8ÌÎC×wŠzØ×I‡Á܂⮗_v_6ߨ ^'¾˜j,·kÅ6ž.õLuË”dLÉIÐ-èãóÞ‚ýÌ&óo'Yòš°¯<صŸ¢£éÓÝtquêü“÷‰h­ç ä2dÛs v7â;‰éüKô Î0ÌÏμ®IBOeÒä½AW Ü;¾õñz:t(/^õî×Û4†Ž;†]wгÚZ2fn—*q晡ÅF¬#ÓÎðA\G©rÅTÈ›€Ú¶¼ù¼gj’ÿìIÂ7h™wi­õ*Î6åLafìåÌT>ØçœiÂJì à VŠ‹üã‚ Ü΄§Ÿ, ±c¡LƒOÚßÓqˆ©»˜7ž÷U¹‰ü÷•ˆÏìðæ ¬Šq4CâO@m[ü§ò¾þúkÇÙˆnSm«ÄF©|µT7H¤}K‡>ÉHXŲì­6’ô /˜˜ÿ<Ç¡Ÿõñ ¦×`h"€ËÁKÿÜ}7l 1xûíÜkè¡tæÈ¹În["±Ô¾eì¥èÄ™&›C#u7Šè 1,Ìô—L£Åþ?:ÕP|DS‡Çsöš5‘‚$Šór¿ Ø@_r%ðÇn¿,ÛeóÿÈ tP»6п?°y³ÛÏKªUÝöœîTÏ> ·Ïƒò¹×Ô’7Å<Ì÷ÄIÿÇ­Q$WŠª>ºÝpCN!T¨[^þ=["(Eˆ«àhµù„ÍŸ?? ci“øÑ…§p£%Ü–³iüƒiÓ‰fÍšó¯CÀŠ8}ùä“Oœ‡Ëhw¿sçNtêÔ +W®ÌÚS³ÐÅè®»îÂĉñ¼ýšu±)þŽFL%w»I )âItðG–3/" Ž5•H<l*+" I!‰m[¤ §M›æ¤<=ûì³#ÝTå=B`ùrØ`´k {øá°´Án 3Úèæ6žæÍÝ{¥¢Eó*¸Ž¢¦TÊÎÇ[óß~‚nµ+­o"à!jÛ÷#Æ;å[îGõîÒ/¾p¡üÏ€ŽFôá:²ú¢ÐݨcGàý÷aãön<ÂwÆÄéHE'#:ÒLË¢éM7ÁÆô~€Mt ÞstßýJ=÷À¾j¦áËÍa)º#ä½SúŽôí›w9­Í< yDg9ÿÒý¢%•®V­šß’Й’$8‚…DÁë}߃,/%*þ09dßþOãCéŸ'›U|k5F›/ÚñÇpMl Ë%—\b)6þ—%Nbnõ & }ûöeãý…¶´v£èˆ¹(É¥œ¾o|½ÂÙVeD@D@G SÛ¶HÓÙˆGÇwœÍ,90’MUÖCØ)Ì3²tìr}Ôͥݸ1Àuœ ¬«çÃ?g¬–)˜«ÛC§UUË4䄯ä³èƒ‡ ¨móðÅ‹AÕ.\hihZ˜›ÜVGlÄÉ= Hmß¼Ø'™ ×í)ËÅqçwšø§¾Ýû¿m“JDU-Îç gÛ³Û4øÙ·SŒr`¬aCöû–ê=Ý 0µ‡9l.2zõÊûl¯½˜3àä Ó"àujß¼~ã_ -)„¸øâ æ0>ÅyÞ«j4jÎOœ;l˜›òʺvm"Jüëš×Ø®ÓQ݆}Ag# IèšNÐ)=YiµÂ©_2ÊøRÏ1õǯ}.ƒ¾ºðÞ‹îE¡‚N„L –Û­EaLèD]ûŠm.“ γ÷T®œ›B5{IÁ>õï<ø @Ñ9ÅM&pRëÝxcÁöÉÖ¼á9Ó}kÆ w‚m$Û«lú(ÏSówèáq"–§A£P)ÜÔ[‡ÑkÎ/Ö¬Yã÷-~é,D±ÑƃT¢Y„Á´Áiè›ïZ°ØÈ·[ry(HvÉÎDó\2µF¸b#ÖÏçpîuMô9éx" " Ì¿›¹m[$×®õâ1õ€Ò©EB-±eͼ>ÁL´GæÃ”Y99·ù@Ú³'ðÕW@:n>nΊ¡ÞÞ6 ÅÌ"E¢=jâ¶ãLª‹/}<¦Sc$»óÅ­…þè ¨m‹ž]:lÉÔçgœqþ²™t>‹y2" " Ú¾yµO2Ù—n†¶ÜdSØkÛhÕ»ï¾k l¦A¢U+×U”³èC lÙ⺯†*£åéG xq ukàË/U«BŸ²ø÷ÃAk‰BsÒïPûæk•ÌšRˆÉTO=zÌÇ®]»£þÒÇÁæšdõ Úc #È|é%WdD1ÓiU¯î¦ÎJæ9ø›ºæ°¯.”Ù¿ü-·æùŠŽ2=ìòã­·€óÏ:ÈíÇ¥`—®‚mÛFF‡iÓrùï…õÝ¿ÿÒØ¶Œ½N\x!lÂuHäqÝÖ›©'fÍâ‘&.öÔ´ÇDˆ«à(8%Z$Â’`‡£F…ÍäS½0}›/Våuî+ƒ÷1cÆ€C >\ÞqÇïuÒ¤I¦Hü=k;κlÞyÅHtòÅ‚ r¤£ó­‹×;Sª1c$A‡#Ú |ðÁ‘l¦²" "  $Ém[$˜™N!ÁQ$ÔWöÞ{݇ÌË//؃7o/ƒÇ¥ëÕs;*n¾v0o7;8¼–ÞÞf´ÇÍ-8°Á™,ì„Qˆ€— ¨móòÕ+XÝÙ^Ó͈3¤Ç›/}¸iÛ vTm-" ‰!PÐöÍ«}’‰¡ú(ým¤§ˆÍ.˜:u**W®º`˜k:wv™¾9Tpf;ÃÌïF€D((zóÍÐ'Îç¶µke{ÍHk¼E@í›·®W2jKgq:Ñ4mú¯9“÷5—Ÿýp¡©2èMqÕU®Ë©§ºN5e˺ÂºÒ è¦+c?׸qù K’qná“ç°h‘{¾l' –åäÉH¶ w߉.Çs°Û2GdDQû8-‹º¥ºuù7r䑉®UìŽGW#Þ2¹EUÉ ¬èöO…øÄUpìp®àˆ¶æ‹øËèLQIÐ*Ïky‡çøÑòk<üðÃYGáÃf4)U>ó=1îÝg^†§œrJ@1>ä&2¨ ŽtGÕ­äC¹BD@D õdzÛÉáfY{b=ùä“#ÙLe@€é(âŒ&:2Fb-ÌÎæáÎ/8ÓeøpØ pÄÀ¶mÉ}ð˯¾¡ÖsÆíƒnG³ŠÏžz]V!}' ¶-Å/PœªÇ”åµ2Û:½úê«¸à‚ ât4íVD@O í›Wû$O;ûˆ_X^³O>ùÄÜ®°AMÕŒAPàÏI< Õ¥Íûuºèñ3À=¶‹sÎJ–tÓª…ªºm9!ÁQ(BZî%jß¼tµ_Wº3²ž={0ªT™déFkZ µ¹hß¾½ýV–tG/¼˜É-˜jò¨£ÜTethyýu·ŸÐ†£õ'ž˜øúÇòˆ=z¸nHtöéÐ7ñO¿~îäÂŽcY›äì‹.OL™FQ݆(¤b_m»v]Ó!xmÙ?ë'H‡ÓÒ9¤¸ ŽöÙgŸDáæ¯¦»ÑA£;¡RŠÀïËúÊî‚ZÙúöê}»M¿Å~ÉhÓÇ8ß|Ú¢)9‡É•÷F!ËÕq*e·a„¿Ã‹'RpÄ´!XÛÿ0*º·ÈnÛˆ‚£HÒì…¿w•((LoÛ"áG—¶ßLÉ"m$äS–ºf>lOŸîÎd ÷¨4­âCÜㇻ…;ƒ”³IiËtþN’X’¹¿yÞ¡fJsPòù*DÀ³Ô¶yöÒE]qŠ‹z™·þÑæõMqð•6•)Õ.Î+dÔGÓ†" "±jß¼Ø'™âÙG½ßF³Ø{Ûm·e/Œòk(2b—8S¨°¿uôèÜwÆ4tZtògî{ÓR/`Ú ‰8©†éTr Žè>4?9·¢Z&)M@í[J_ž¤VnòäÉæ\s¦3ù³yóæxà~غµƒõ̓¡C‡â¡‡ ¨5Át†áoç˜1°ì4°gBà˜c\g@ayöY eK·_’ìßPP•WÜx£›ëÅ>È«dj¯£ÀèÑGacꮬoßôåÈÃ#µÿ3µvqÕ¨Q#€ëj&I #üpYœ‚¡H…)þùgÖ‘áÔ8Æ}&‡¥x†QÍFaîfÂÏ(‚ûØÀ\{£ž=9V3OÙ1Ö2R±ë‹_~ùÅ÷1îïL§ÆˆDpô–üQvÚi§¹ë_”"ém[$ã½÷Þs„ÒJ§ µÄ–å-g·„Ô­3-;ð3iLšYnÙyíwK.2•OPÛæ‰Ë“JrÓsÏ=‡Úµk;NÄtLžmÓÇŽköêÅäÚ‰ˆ€¤ X´o^í“Læ5øá‡L ô¶“²¥nݺ® (4bœw̩֖åLqÂ.hº„š$àîAÿ¦3‹.èä;iRγd?=,ƒ,Š˹^KDÀKÔ¾yéj%¦®¿þú«µ‘ç9¦³L}ËÌ/ƒÆçŸŽ7âwÞÁ­·ÞŠråÊ%¦B)vöçQtJ3S¬Y"{&FÊvp7S¨€àÄB:'RäÌôc^ ºXQDvì±nÛH'z…ˆ@b ÄUpÄtYþ±jÕ*ÿ¯!?³¡ð,1!g‹„+V¬ÀŽ;²ŠÇSpÄAÆ &8Ç*lÓ¾‡ b3l Añó|ø;Gà ºIùó¦ÛÒfŸ(ÜDYŽéÔ‘̪yÜìŠÙSÏ5×\ãn¬E@D@R†€Ú¶È.xŸr¶üÊ#W€ÒÔU[6|ý5`F“9‚¶Èyå纼¬…ùðݨl†”›÷;Ç´@DÀsÔ¶yî’E]á3fàDóÿÖ<óùŒ>ÚzN¿üòKû]·v…ˆ€¤Xµo^í“Læå|ðÁí™cúr }ƒ©^~ü–îÓM•V´(põÕ° ®®S«ÿî}é%8ò§’YŸ)H£˜hâÄœçýᇮ;–º'r²ÑoPûæ­ëïÚîܹ÷Þ{¯¥D;Ê1•é´i¿áý÷?Àí·ßî<ëeã©p´níºüŒé¶ ;õë»÷tsšItì¼4ô÷Ÿ~r…=~Ãð¡ '` Óá5k抭"1ÆH@ÕtÈqýv8Z´hQ¾`éðóý÷ß”káÔ§ôÅó‹àzø­*ÐÇ56Ruçwfíãºë®ÅQц¿»÷Q6’©øV~ÿ _Rî/štr<¯ß~û tN…b&6Ú¡Â'8 :|¨âà æU¥}åÊ•C–Ó HuëÖáé§ŸÎ:Ô¿6MŒ¢ÕàßÔ¬iþ!]Û¶ßÿ¼Ö¾¶—‘m[pú×H//Ø RßžÚªp ª"®(zì1^»l¡Ó|z¨›‡¹Ø×®ug嘃²ÍjÊYî£iSàï¿ayÝÝýàRåË»‚¦àå™úŽOL-צ pä‘™JÁ›çý®MmûꫯœÊ/[¶ L™‰‘®m]}7mÚж1Õw´`¼þ·A—ßÞ½{ãMËIS¼xq'½M?³‹Øo¿ý¼~jª¿ˆ€Š gΜé,áÄÆµ¼ùËЈeû–*}’tCç ¢ÿsÛ–ë£bÅŠ)u•ÙoúÊ+¯àŒ3ÎÀI'TàºÑ­¦}{€)Ž}Á9šœÁô(-Zø–º.üawyöôÉóØozNÚpöËû÷ÉÓÙ‚qÎ9î»þõº³|°7—ÑzË•ü›ì³ˆ]-Ó±}#>“/\¸0«;Øl¦¯¦ºT‘'þßèÚµ+–,Yb}RGâ‰'ž°L3Ím,ÖÐÐÝF‘“õWto·aXøÒÑó¢];Àü*¬O<ç6ù-aŸ*EL}úÛ¶ÁD`“ì¶!gEŠà„f;b°ï*Q&))†!cªc?9ñ Ç…6³×_½ Ù¨Pˆ`§8g‡øG$‚#nËFÿ®‡ÿºh?s€±W¯^YÿA˜ÒŒ^Aâ/ŸrgïN"‹‹xcšëPuåà+݇<ð@§H~Ê`Ÿ‘’ÿÃM¨}s9ÝååìDÿˆ€ˆ@ ð7Ï÷{çÛgÃgb¤sÛÆ¶Œ/ÿk‰{b¨¿¦å>EÇŠøX¹øßÿ€>?Üq™é˜—MÁR¸;ÁY-vË™kÐ4“‚#vÞ¿ü²ûàkÁ ^hÕ0ÃPgv1Ð’Ÿ"/ZKpä­? >ø~÷2õá>ÝÛ¶"EŠd]cþufâ= Ÿ£ „#F೨kg=¨tˆæYØ[ÿÃU[ÈLUúÚ¶ífu¹|ùòŒëö-Uú$ÙŽñ9Íwyqóë—LÆÀP›Ý°{÷î<'hFR/Þc¸EÍš®¨„ã4¦?@¥Jîzº½Ö¨!'Ö@Z™÷iÕø Ì´9LöGuê¸#¾ezO}þmßSñw/QÓµ}#?NŠ(]ºtV—jbÚD]ãpóͤ«Ño¼ápcv™=z8“G[¶89Žý„м pþeC·n01#pôÑy—çZ›·ë¤í4Óà¬`#êã¨ä?û]ír(D $’–ãÏwOOÍû¯éK ®‚#Þ(µjÕ S§NuÒ5‚¨¹u„RÝ6f̘ÚÕ,d >E…“,y±¿ 0ðzõê…¹uøÅžzê)Ì;×Ù€ÿiø YÐÁà‡ûHÝ5‚ËG«„çhANøtRáŽxÇç8A5lØ0œÝ«Œˆ€Ä•@y³2ñÿ½>|¸#ºŒëAStçéܶñ:W¨P!àZÇâ20ãMŒÎ<÷aýùvïå>ÐÒ½Ènñ‚³shéËTiœíký8!ã¶Û`ÎfÀÝw»³ˆMw¨ð#@û}›Xn³ïÜ…>óP µÞ"иqcðÅxçw0eÊo@ j›Îm{øò¿‰2Oíâ™gž±•ýñ/Ó¨=òÈ#ÖX# H[ü¿ÎƒîÙ+¨’ÎÀˆuû–*}’¥J•ržÇS¹m£ûÈóÏ?ï8Ñá(žÁ®Y¦È¢{ƒÍ{ubútÎçQµo/8ÿ|÷ÙØÆá³GfœâLéÞÝ g :úàdv¾_[îx¾25Òµ}ãõä˜ÝS¹K…¿»l¦!'¼ÿþûNuÚ¶më<çq¬˜aFó¶Î~º³Hÿ„A€þ{=&ò-MqÒk¯¹zt`ä„Í›nrï?xo2lÌY9ßÝÄ­oÿéÖtî¹q;„vµjÕ_ŒŸþ9ëÿt v­]¤ ¸[8ÐÒœÊ]_°±¸êª«rXÓ2— mð̤ÖL6fÌš5 ýû÷(MG¥råÊ,+è*k}.=Ü×wÜ‘(*Ôñƒî#u8 ¶Š'ÓD„Opd¨ó ÊX/¹å‹JD@D ¡Ô¶E‡›‚#Þg4jÔ(ºh«° P¾x1ðä“9ÅFÜ ECœÌ>¿[Ï\÷ϬµÑÉÇ—Q‘™­œ±“éqæ™°ôº®€‹,è(EMÝqÇe:¿×¨móÚ‹¬¾÷ÝwŸã0Èþ†l$–é%6ŠŒ¡J‹€x“@<Ú7¯öI&ã >ú裠»Vß¾}ã~ø .p˜VÍ?ø<£Èlt¼¢³/3Lrrcï|(p‰B¼H@훯ZlêLg«‰'f‰y9Ž|ÅW8æ&L°j®Øˆ)H)À5Øã "NìVÇ'uî Pàj—Âq=·yl°9?Iñ”mž‘S/öë*D@Rƒ@ÜGU«VÅ5L:íL?ÒÂ’OS™zçw¢C‡ÎÌÛùóçû•‚£ö¥8)¿øÝüÝ~øa§³‘|¾`#Ô±cGßט¼S,ÃTjtkbð<ÚSâƒNíBµs$±‹Sûý"ØñÈoUL?†›RéîènE‡‰K/½4¦uÐÎD@D@¢' ¶-:vL¥F·Ã³Î:K– Ñ!Œx«*U"Þ$ä7ß Ømª“oüï¿.]`iyÝ¡!7Êv{ëgS3hQMÃR9ߺ<ô¯7¨móÆuж–O›Z”} õë×·´š?8“š‚Ÿ§£Ý·¶T&¯ö-ø7Ô+}’‰¾VÛƒÃÈ‘#Q·n]\@5P "¯ù¢ìæÜZ®î튎Áµ‹t!ðÜs°ÉÛL;èžÓÜ0 ö©§¦Ëê<2‰€Ú·LºÚÙçÊñ\ºZ±]åx1ŸíhVð“Y˜3SŠÏùË·ÅèÑÀ÷ß·ÞªÔ¢>&ñx§Žè~>y²;A“ÜC9 Yfs»Ž€ G¦5ƒoŒ9œ)²¥ãÒa‡¹©ÝÂÙFeD@âO`ïíh|Dç¢÷Ì玖Y¾ 8fÁ‚ÎË·,øb!ŠSr‹Ï>û T¹rŸ´˜ Ûpº+Eú€œÛ±ü—ÝsÏ=X¹r¥³¨’M%4hÿê}æþüƒ±‘ÄNþúûE¬üvðѲæYUXã°8Ç—ì©gÉ’%æ(p›=üØÓBD@D %¨m‹î2¼ûî»à ¥S‹Ž_^[ñõ )ì†u4äU2úuœ e·u&XhÁÌtm´ –YpÚi®¸ˆ‚£nˆž±¶dPÛ–Lúñ=ö믿Žo¼ÑÜ×ÛâDM´‰ïYiï" "xµo^í“ ZìJ=iv«›,ŸÙ0Ë%R¸pþóx{ô€ žÖtY{•³–  Ü~»ûl’³¬ÍËm©–‰P³f 3±±×ù#p¾‰@êPû–ú×(–5\³fcN@±Ñ† P¾|yÜu×]Ö/× Á÷$¾ãnÝ +p€ëZî[®÷ø`¦r3¶ôånÿl^G± x¸ûn`ãFfʽ$]ëgÏ–-s]Õé¬ÎÓ£*ä:'ZU^@IDAT™$ ßX·¨]róË—” ˆ@b $DpTÒFth‡÷Àà•W^ ë »Ø4ó[)S ìX¤•^¨he*˜³cìúÖ[oázÆí žÂXEÅŠv©àhÇŽÛDzn;úR£,¥\ÐÂ\¾Ò݈ãLs§H jÛ¢¿L§Æ™À±¾ßˆ¾F©½%õÚtb:€ƒÊ»®#F“&¹éò.Y°µ:C‡ºb£êÕÁƒ ¶¿tÙšƒ!'÷»3©ål”.W6sÎCm[ú^ëéÓ§;ÖúUÌòŽZ*W®œ¾'«3 ñlß¼Ú'„(®_9ÑóËáq°)„®¼òÊ|Åy¤Ã‡»BÝOó™‡óG™Â8¿`·ï€îÄŒ ò+­õ™H tiM ÉÄëžç¬ö-®bxçðí·ß:m)ljÿ1[œZµjaàÀ ùD©R¥òÜÉ!ÀÚµ€™Ý&=¥WžM£•ÇÞÉЉ‘âjŠŽš7‡e4r·£ hÌw’ü£\9àC€zõ󱿘s1l Ù¿TÎÏìSf:Q…ˆ@jHˆàˆ§LG›þýû›¥ç©ŽRu=§päEÍ”)Ë®¾úê\Ö†·ˆiØnçÔǶh{ãØcuòu³“3T,]º4`¿û—/S¦ 6l˜U¦ ÷L-ç‰ù3Ôçe&[¥X«uëÖ&Nªª˜–‹€ˆ€$˜€Ú¶è€ÓÙˆîLår§Ö(ò%ÀY1¦Çyç¹’¡úhÃË\ÜìtgÎðx­ç)n5 0CNuXøÁ¦»Ô_óæÐ𣞠 ¶Í—)âJ25;Ó×”¶Ñ4¶Áz®Œ¡6ð8x¶oéÜ'«Ë>ÆFÌÖÚHç£ö²Ï>ûä»[3÷wR¡ñ^zß}s/NÇxîʺKó >OÙÜW”-«ûó|a©€ˆ€§¨}óÔ劺²}úôÁC=älÏqâ[n¹Å/ Ç1põjwÂàQG;G]m't‘§ËžyNà„²òãnjX&÷á$TfËa*4 öÛ/»èÍDÒRéuêd/×'ï°a–ÄÆi–£éÐV˜OÚök³páB¬¶Ö‚9:)â9úè£Q¼xñ¨*ÅíÙhxâ‰QmŸßFþBTâ2—h$1uêTðå æ¥¼/‚îi+I£/(Ü¢ )U‚–Ü”YªÔ_õt% ¶-º+ËAOZþÞ |S¹ܶÍÍË.¾¾ø‹.rgär¶ 'óA´P¡œ›+æZöRGÍšñŽ–-¾(8º÷^wðƒæœM­¯PÛæ•+~=-Zd“­œgJNda¿BD@2@<Û·tÅß Ùßÿý¨P¡‚MT°™ aMñ÷Ž«æZzófÀŒûœôι¥[ Þˆ³ÿLq¢Ï=0ÕP÷îþKõY¼C@í›w®U´5ݽ{·9ž?k©°j;YpŽ?þøˆvuçûÙ®†r Œh‡*sœ8Ê ¤þqÆ®{z³fy_·Þ½ÝTlQJü©Ï" I"P4IÇuìgiA{ÖYgEU…CLÙܼÙÊÚ´Ž£LÖÚÄž¶j'.ŽjÏÉÛ(Øþ믿»2¼)ó(g^wLó’ˆ CëöüóÏ›2µZpôJ!" "1¼Ú¶åw|âsÎ9'¿¢·ž3o;t–,uÈ»3X|˜kÝÆŒñòËõÙçœù—"yN>Ù|Ñ”Ôú…" ~Òµmó;Å”ú¸Òrr²ß௿þ²t›“Ìž}¯?{JÕR•oPÛ–÷õc*µß,/ßóKù’מöì,pÓ‡L™K'pbF8aóVwÖ8ͳ § *“¢è(±|9pùåzŽNÑK¤j%‘€Ú·$Â÷;ô矎M›6¡gÏžˆTldÞxáàÌ3uÃúAõÀGNB5’|#”dð†ùE—×wÄHšà¨ §ÈÙ$áÎ()è±|ÛW­ZÕf lõ}Í÷ª]ÿ4gûÚ¯¦¿ëP¥ ‘4ª{yäÛf‰Ôñx´ŒÏ/(Nú÷ß³ŠAéh‚‚‡úõWÀúsW_}Õq¸Û, %‚ʵ"Z(" "ƒ€Ú¶HÂZ0mÚ4”³dÓþ©QÃÚ0 ±€?ì¦) >eÓ ƒYg™àˆ#ÜüÜÁeô=ù(&ç $ûSGӦɯj ‘PÛ ­Ô/ËtétH~饗¬ƒYBßÔ¿bª¡ˆ@¼ij}ójŸd¼XûïwݺuŽ»ÝtÓMþ«"þ|ãî é'ŸL§V¸0pþùá톩©"«¯†9‡óç»ò¹•Ñ2HejßRùêĦn¾‰›t­4>þØm/‡tK•O'¿üâ¦kãßÁ5פәé\D =xVp” ü´n$~þùgœ{î¹Y›tìØݺuËúü¹J[[ÒîQ£F9«˜‚lÖ¬Ya¹@͘1#`wL]—¨ p^š¨ÇÜr•ï ž¿BD@D µ¨m‹üz¬7Ë—¹sç¢}ûöfã[$ò¤ÉÛ·ï½çvû›*K¡êЉr;Õ%€·Þ‚‰µ\A *ëÕ&OvS­å¶–%‡ÀˆÀªU@ƒÉ9¾Ž*ÑPÛ-¹ÔÛîÏ?ÿtÒ73ä圶¯ &ÏöÍ«}’‰øsèׯþþûoGøº/_t”îÔ xñE MØ>a®}ÀD¹3m&{ Ü|3À—B¼J@í›W¯\øõæÄMš-œp áo´·d@»vÀAE¼©6ð(zkw¹ s=ªW÷èI©Ú"æl…"•œ4­å™gžÉ·z´"œ0aBV¹5jàÐCÍúïü‘/S&÷£|eyUæÍ›g©U:¸;å^ZKE@D@Ò‘€Û¶¼®Ûµ=æ…ÏÔ®™¦‡F¯^°Žà aâè@ !Ó¹(¯`§úÛo»)Y™BàŠ+Ü4ltÓQ¤Ãs]Ž(Sˆ€H·¶-ðìRçÛ‹6*ËÝ]ºtIJ©&" "¦Ô¶å¼°ßZ—Ñ£GƒNòçEh1Ä1Õ>}÷yÒIÀ¸q€™&™«}øéÔ÷¢o" " ‘Pû ­Ø—]½z5Øžž}öÙQg@‘Ø(ö×%÷HGüúõáÃkÇ”´Y"´h¸NßD@Rƒ€G©q²jQ·n]ÔªU+ëûKìýòË/g}þ°eËÜpà ضm[Ö*:.$2æÌq r;¦Ïyé Ž$*D@D@2’€Û¶¼.Ô²e˜ՇQ‘a±kpé¥nº4Þ®ðÐn]¢ŠcŽ^y–v ‰$ûï•)'*”ÚHD Ò­mK°É 8åË—ÇÅ_Vyˆž€Ú¶œìzöìé,6lXΕy,Ù¸øúk€ïÁÁIO> Üz+̽/x­¾‹€ˆ€Äš€Ú·Xl¾tjJ·L,]­°f ðÄ'¼úâ³ÏŠ‘®¼ÒM¯ç[®wÔ!4ÁV¬X-'g-~ðÁøõ×_ñ/½Ò2<‚go4ÈÔ›c±{÷î2T_uÕUökO°{ãðÃw–ù¾'â½R¥Ðv†KÙ X0ϹBD@D s x­mËëJñ~…‘H7Á¼ê“¨uL¡Fëš*^r ðå—®m{ÅŠÑ×À2ÉÚŒaw?Ï=ý~´¥ˆ€$ƒ@:µmÉà—ß1?³^Å… :Ï·%dµ–.­˜PÛ–ñ-ËÍ~ëÎ;[ èzÙ+Âø´d‰[ÈoNiÀV×] ªtjPôED@âH@í[áæ³k¦S+bù±Î:ë¬|Jf¯^¾øñÇìïú”Šƒ¹»â¢Ï?Ï>g¦£eØp¸BD E Mt½V®\‰`ŽÙâlçÈUP0öé§Ÿn–³}PrÆ Œ66š7sæLK5b¹F,þ3)ç½÷Þ‹1cÆ8¸ìl;w.–³Õõ‹¢E‹:l šOÜo—þHÁQiË­R‰ª$…ˆ€ˆ@ÆH§¶‚£Â… [Îèês=7o(úôSàÚk§žŠÝŒ>,ê1cþ”t¢"VÒ©mKÅ ãK/<8ŠuUD@D ]¨ms¯ä?ÿüƒÞ½{c¿ýösúd#½¾?ýän¡ù—‘’Syˆµoñášß^w™Uú‡~ˆF9εù•÷­·¤.¶Àö4ƒº_}§ŸÑïݺ¹îúGéb° ëÎä×ãŽ:*£ÑèäE ¥ $Tp4~üx<ðÀé¿‚é°zï½÷²f\gS>J–,\,í¿S”õ×_9Â#ßÉR¬ÅWnAF?þ8N<ñÄÜV'mekÖ¬™´ãëÀ" " ©C ]Ú6¦T;È’‡ã´‹ ˆ?þZ¶tSôê<ôPœ´NQD@Â$.m[˜§›°bþù§u*N@Ó¦MqÄG$ì¸:ˆ€ˆœÉŒéÐ'YkÉ>ÖŸþÙéÇ®\¹rÄ»ò ŽB9E¼Cm " "P`zv+0ˆw0kÖ,l¶YŒ‘¤S›8˜:èÐAb£ˆ§Áô®ð÷¯˜4 6V®Éªipiu iN p¢ÎïþûïÇÝwß§ØÈ¿.œIò¤%´¾ãŽ;ügÌgº=ýôÓèfrN~Î+6lè¤\kÒ¤I^Åâ²nëV૯€õësîžÎL¿ýö›G9Ñh‰ˆ€d$¯´mù]ŠikÔ¨‘_±´X¿jЬ™+6² ¯¥ÅUÕIˆ€Ä’@º´m±d‹}1íú›Ê(w£XÐÔ>D@D 2™Þ¶ýa3.ÙÃSh÷èÑ#2x{K3¥Z¡BÀá‡Gµ¹6ˆLoßâ€4ß]N¥rÈ¢U«Vù–õ0sAÔ¯<ü°o‰Þ3™Ó©Yr\~y&Sй‹@êHˆÃÑ¢E‹ÀÃh‚ RóæÍqþùçG³yR·9Üž*/^u˜®¥k×®èÔ©“)z§bÁ‚X³f#ÚªZµ*>ø`'ýÜQIô‘³*áä“ÝÆÿ–[OuÅŠ c•Ž¹è›ˆ€x™@&´my]Ÿ-[¶€Ðì|N÷°fÜ™v#FÀîIÒýŒu~" ™J ÓÛ¶T¼îÏ>û¬c¹ß¶mÛT¬žê$" ž PöÍ }’ñº÷Üs6mÚ¦ö,^¼xT‡¡Ã‘uÛ¢D‰¨6×F" " yPû–œ[ÅqÍ*Uªà¸ãŽ »fgð¥uë`‘(X t=Ô#ÁÑÀA·ÿ8æ˜cpÆg8 Mݺu±Î~9~²§±÷ßßyù—¥Õ!S…1}I&F©R¥ÀŽÖTìl¥•cÿýÝwÿ—.]ê|•àÈŸŠ>‹€ˆ€@*·my]!º12Aptíµ0§B`ôhàÿË‹ŠÖ‰€ˆ€€WÛ¶T»z´Ýÿá‡W‰©MµË£úˆ€dLkÛØ—IÇyºÈ·k×.ê«MÁQƒQo® E@D@âL ÓÚ·8ãÌu÷4$àsÝÕW_m®fû§lÜÜpðï¿J§6¤ˆ»àèóÏ?ǼyóN)À8cÑ–H¹rå@áÑyçg[£ñàƒbÏž=Îv[-o×Ûo¿ë¯¿>`?ú’|–~Õ‰2erÖE‚£œL´DD@DÀÛ–-[æœ@&Žžøè#7gº·¯šj/" "à%t”`\Kå«BD@D@Hàõ×_·­ѯ_¿¨ºv-ð÷ß@­ZQïBŠ€ˆ€ˆ€ç D“NÍó'­ˆÒ¥aÚ zu˜n f»ÕŽD@âD pœö›µÛà”buêÔÁÈ‘#ÄFY…÷~ âõì³ÏXüóÏ?|×—Ô —ÃQ&¹@¤ÆÕP-D@D@âMÀ×¶Õ¨Q#Þ‡Júþi,Ù¡CÒ«¡ ˆ€ˆ€d?ÿü&Lpœ%Ž<òÈ :sªˆ€ˆ@*à„×}÷ݧŸ~zÔÕ¡»£vm÷]ÿŠ€ˆ€ˆ@& à¨hÑ¢8óÌ3³NŸ¢Ü;³¾f}5 xâ X¦œ¬Eúá˜Õ–Îû|E™á6à êôE ±â.8ò¹ÜøNëÒK/uÜ|ßC½StäùÓHÏy Žxíi•˜ ƒ²©sETxð Ž2Áá(žµoÈÀرc±}ûvtéÒ%·ÕZ&" " q#ðÇ`öìÙhÙ²%Š+õq–,q7•ÃQÔµ¡ˆ€ˆ€Ç üóÏ?æšþ7nŒý÷ßß²Ùçœx À¬Ù̘R³¦›~”Ë{ö† = züÄU}ÈPqO©,8bN{ì±([¶,6mÚäç~þ3ykáÂq×H…S=•ÙK ¿”jÚDÉ’%ÅKD@D@Ò‚Gûì³¢ý‡Â #pÏ=@… @ÇŽÀ!‡ä¬¼ñbǦ°É¹NKD@D@D ˜NéÖÛµk—ˆÃé" " "E`Ê”)Nßs›6m²–EóAGÑPÓ6" " éD`æÌ™Ø²e Zµj圌Þ}hÞ¨Z0¯óZ·øáX_+ÀÌÚL£¥ð¸ ŽÖ¬Y@¥R¥JßóúB±ŠOp´Ó|ö6lØ€H¶ÏkßZù91…žBD@D@Ò…À²eË,wtu)RÄ3§ÄYDW\L›æVyà@àÑGnݲOáãÎ݇þË/×~6}HºJü`½ÍÝ»w·Y¯6íU!" "  $Àtj|Îó ŽF{è ÜI‡í´ˆ€ˆ€x›À´½ç˜}ÅE}ú¸}Ž“&¹îFÁgǾKK–¢ð(¸ÛíaK±7èP:‰jUJ]ý‚GŠÔ"JpDõòúõëͱfjUXµ Ã‘×R…àŠ˜­Öҧ㢋€¦M³!ðöªkW T)w}·jÙ;Ñ'(¿ÿþÛݦ†µP:µ€Ô¦" " QàD×÷Þ{'Ÿ|2*V¬˜ë>èòn]ùŸ·FvÝò-¬" " "†¦Z$ÝáëÕ«‡þýÝÉL¥–[Hl”-Ñ? Ž"‰âÅ‹GR\e“@€Û4yœô¥Ò“à( E‡ˆ öt¼Ù¾C=4U•#:<0r¤›'¹ÑýƒÙj­o¿ýy¤ÿ}ØضmæÏŸ¹sç:¯9sæ`É’%N›&MšX[¤Æ(öÔµG¼|l–¯œ<™W:µ.]:30]µŒøò¢©u" " ™L€“5-Z„k¯½ÖÁÀ~ÉZµ`i³3™ŠÎ]D@Ò›@BGé23ÏŽG¹©’ySÁðÒ lf^Aµˆ€ˆ@¸¼Ö¶±)¾òJ \9`âļ;Å«UøRˆ€ˆ€ˆ@< Lž<mÛ¶Å®]»²sØa‡Yçs;œtÒI¸ä’K²–냈€ˆ€$ŠÛ'F^‚#k¦0~<0s&pÖY‰ª™Ž#" " Þ"àŸN5/_–6Û[ç ÚŠ€ˆ€DF@‚£Èx©tP‚#9ÒWÏX¶l™s^Ónßî¦Nc;M—£5<_' " "àqÿþû/úô郒%KšûÞ@œxâ‰8á„LkÊX…ˆ€ˆ€$‘À;ï¼cî µP§Nµ8óLwÕûïKp’Vˆ€ˆ€d<¦Sc¶›-Zd< L!`I4"=¦TÛÿœÛKp”“‰–ˆ€ˆ€x›€ÏᨆÔ;7ÜKW'OzË–Þæ®Ú‹€ˆ€¤qãÆañâÅèÙ³'úöíët@Kl”×Vg!" ^&ðÍ7ß`ÅŠyºñüêÕªT(8 /¾œ|2ðý÷¡Jh¹ˆ€ˆ€¤/¦ÏfšÒFZ`¿ýöKßÕ™‰€ˆ€à(‡¾DJ`ôhà‰'rnEÁQ Kh~àæ\©%" " "àA>ÁQª;=õð @ëÖÀwz´ª," "v˜BmÀ€f§_·ÜrKÚŸNHD@DÀ»ÂI§fš$üù'@—£ €µks?_Núøâ  téÜ×k©ˆ€ˆ€¤3^½z¢£ žvÒúeÒNçÓÖ¹‰€ˆ@Æà(ãÿ  qc I“œû àˆ²… ʹRKD@D@DÀƒ(8b˜8 ¥kO÷AË€±caípJWU•È£FÛÑÞ½{£L™2rÖ:M/xûí·Aì)§œ²ºg´j•J-”ËÑO?Å‹‡rWZ!" " iI`Ò¤IxòÉ'qÔQ±páÁ¨V –Z--OU'%" "D@‚£ úZp{öìÁ²eËÁQÁ÷¦=ˆ€ˆ€ˆ@j`ÛÆtj©.¦íÓøî; lÙÔà¦Zˆ€ˆ€d6;wâÞ{ïEåʕѭ[·Ì†¡³H)«VýŸ½û€“ª:û8þ§ƒ´–Þ–ŽˆtQAEQ»Qì%¢±¡Ñ¨Ñh|Õ ÖDÅnb!vQcAE¬AQéHoÒû¾ç¹ãÌÎ̶ÙÝ)wf~çóöÖsÏùÞÕ»sïsŸó³¦NꂉŽR•*UŠlÛ‚ÒªUR¿~ GöRGqG.™Ÿž^ªÌ÷"-Yˆ ™v==ÿüó•››«½÷¾JI÷Ü“™}¥W €…ª^Ä*&°téRmݺUíÛ·¯XEì €€,àèàƒöQ‹¤%K¤¯¿–Ž<2²YnTS  €¾xÌõ¹xñbýýïwCÌ0ÆŒ/N @ð,»‘•ãŽ;ÎûYÔ? Ê=@ Y²Û=¤ñã%÷¾e¡Œ²}úHö¡ € -»wïÖYgå†Q[-¦ôØckkÑ"yAGÙb@?@lHjÀÑ7`çþóŸ˜Íí¦dx;vl¹Ò¯ÿæ7¿ ¯†é8 ìÚ%mÙ—<|ÈNÍ Gq‚¦@” ,[¶Ì]ó¶ø&{߯ÒwÊ=¼ ¤'v±Pd4Jùo @ˆؼy³FŽ©–-[êâ‹/Ž^Í< €)°€£êÕ«ëˆ#Ž(¶(­\)Ù}P+6¼šem°¬²={–ñ/ €Ù*`ß÷>øà]vÙe.ØèX¡uëlÕ ß €@v $=àèºë®+·ôwÜQ®} 8*[©;YF…¾}%;-×__°9GL!€d†À¼y󼎴k×ÎÚ¹Szä î•`#_œ PH`Ô¨QZ¾|¹}ôQÕ$ý^! €¤N`Ó¦Mš0a‚ Ó ®ÁׂG6¬G©;@ õŸ~ú©n¾ùíµ×>.—1ÔRFh Ê©9,GÍõ뽨_?²7Ez0‡ þ6œš¿åäH“&†S;ê(¯iüƒ €€¯Ö»/ŒvÓ9//O矾¯ÚFc@ç"†¶nÝZâpjE)p€T«–dGáeíÚ@&øðeL#€ ©¿üò‹† »ÑeüÈe]ŸÀ &™z¢é ƒG1 ±IÑîï ¯Dù- DÑ­g) €± ¯möÐÔ/e¯½¤Êü%ç—ÓA;@¢þîÆý\½zµnºé&U«V-j-³ €¤VÀ†S³þ%ÖÖX¾ƒ ¼üa™gƒåÆ¥Úµ%77@Œ8í´Û´dÉ îÞd]uUŒï/D(^ ©Cªß Ö¤£À1ÇÆ0·/ÓáÅ25nÜXuêðGF¸ Ó €é+ 8òK†£ô•¤å €Ù °Ö¥y°€£Î;ëœsÎɆ.ÓG@4ؽ{·Þ~ûmõèÑCmÛ¶-¶å–UÖº¦ .Z´(Øìé§¥Ü\©jØõ”öØCjÖ¬`;¦@È4.Úö²ËÓØ±×¹`£zzã*.x7ÓzI@Ê"öµ¨,»Å¾í믿.ûGÉ<»Ü¾\G 8jß¾}ôbæ@H[ 8ªW¯ž6l˜²>Œ%Ùp¦×^+—)"eÍàÀ €”*pÛm·ÉRì?ú裪b_) €øHà³Ï>ÓÊ•+uÑE•ت7ß”î»O:ýôÈÍš7œ·¹~:v,¼œ% €dŠÀ”)Sô»ßýN_}—ëR}½ôÒlÄMÊL9¿ô(¯@ÂŽrrrÊÛ6öKCû|éÒ¥4hP¶ž&#€ P´Àüùó•ÊìF‹I×_/Ùí«¯&à¨è³ÄR@T ,\¸P—^z©—5¢W¯^:õÔSSÝ$Ž €@!·ÞzË[vÜqÇZ¾À=Wu/žH:…/-<½m›ä.:é¤ÂëX‚ €@º lÞ¼Ù*ûþûïW¥J]\w†¸k^¾N>¹nºwö#€ÄA rê  B–"??Ÿ G!&@Ò]À25ÚÔ¼¼¼”uåòË¥M›¤‡–jÖLY380 €E ìÚµËB­[·n^°ÑYg¥qãÆ¹ûÜr(Œ… €);v¬š6mª~ýúÛKØ?mšÔ·¯ÜÃÕb7óV¸dï.ÃéI%×ÂZ@ü'0~üxuïÞÝeü»Oûì³{©ä#×ÈJºür¾ëùïlÑ"@ 5 Ïp”šnqÔdÌšÚ¥¹É#ÚpjVR-àÁ¿ €é/°xñbíØ±#eŽÞ~[n\jÙRú仞õü €øLàÆoÔ¶mÛt×]w©R¥J>kÍA@ x»7]¥J|ðÁÅoäÖØpjVbyùÃ%Mò^éÜ9°ÿ"€ Ž–ð—º¯¥»)ùôÓO§ch3 €@Š’6¤Ú»ï¾«+¯¼R»,'mŲtÐAÞp\yyy^&ðÍì†æÏ?ÿìÆÅ^¬¯¿þZ6vèªU«Â7ñ¦¿ýö[}öÙzÆ=±khmS"`Y6lˆÌpdéY!ÃQBÈ©@ Û·o÷þþØo¿ý’rôNÞ_ºï>©I“¤’ƒ € ³À7ß|ã½è3dÈR³CÄ\)"€ Ý»wëƒ>Pÿþý]Æöú%±,Gî6¶þ󉀣IY‰ àc»ÿyÚi§¹ì~›õöÛo«Q£F>n-MCð›@RŽ,óÍõ×__d°‘¥a¿îºëÔ³gÏmjÔ¨á²X0‹&]tÑEn˜‘w¼ô~3gÎŒØwöìÙ.;Àp½öÚkªV­ZÄ:fâ#`ÁFî{zÄjÅÇ–Z@ü#`ÃÆØéde8ÊÉ‘þõ/ÿôŸ– € .`ßÝ-»°e7¢ € NS\‘eÝ/m85ë“Q[öÎI›6¥÷Ðb—ìÅ  €é*ð§?ýIÓ¦MÓM7ݤAƒEtcÑ"©E ¹ ‹™A@ $”!Õî¹çmÚ´)tP›hÞ¼¹F¥_|±Ô`£ˆ©^½ºû2w‚^ýu÷`î_^š¿ðí¾ÿþ{=õÔSá‹˜Ž£@pÔºð!Õ8Š#0U!€øB`Þ¼y^;pä^¢ € 'NÔ˜1ctæ™gzCŸ§E£i$ €¿ Œ?Þ› ÙÔâÊ-·HŸ~ZÜZ–#€ 9=ö˜î¿ÿ~xà^ÀQtÏN}ºÞ|óÍí&nŒ ²4ìñ(– ײõíÛ7¢ºGyÄ‚-b!3qX¿>PMxâ`ÀQ¢ÊÆ¥áT‚ €@æÏŸïmˆk›ï(ýùÏeh›"€ Ëjdo½Zæá[o½5-à €TLà½÷ÞSíÚµµÿþûkĈ@ö¢K.‘vì¨X½ì €@: ìÚµK—_~¹.qÃ:è…^pYŒ"Ó}ö™dÃŒZÒ£Ê šœŽŠ´@À~‰° Dá¥jÕªúÇ?þ¡Ö­[‡/®ðtÆ õè£Ê‚™‚eëÖ­² #Jü‚ŽÂŽ, DŽ ¦Aƒñ? 5"€ `†£¼¼¼¸Ýý‰¢ãŽ“¾úJª[7®US €qxõÕWõå—_º´#ïkbÜK… €D lv©e?u)‹l˜˜jÕªé㸤:H™E@ ÃÖ­[§#<Ò…æCÑ_|¡V­ZêµË'!7ØŒ.»¬Ð* € HhÀ‘½ùÁ„fgu–ºté±,^3õ]ôËí·ßQÝû￯;wF,c¦âÁ€£è!ÕÚ·o_ñÊ©@ŸXÀQ¥J•Ô¶mÛ¸¶hÃÉ}·×UWI×_ת© @¸ ìp©n¸áÙ÷mûIA@ Ý&Mš¤mÛ¶)8œšœíž¯êšk¤«¯N·ÞÐ^@Ê/ðÃ?hß}÷•eþ»øâ‹5nÜ8YB‡¢Še\¶LÚk¯¢Ö² @€@BŽfÍš¥+V„¬í {#2‘å ƒRxЋEêÚ›˜”ø ì·Ÿôá‡rQÐzí&ôâÅ‹#ìã{DjC@ ùpÔ¼ysÕ¬Y3®oÜXšûìã½¶(!“GuTD½'NŒ˜g¦âöG†‹írau-X°@6ækx°WÅB  €¤V`þüùj×®]BQ§Ž\ö¤„TM¥ €ÄEÀ^,¹óÎ;Õ¢E ]qÅq©“J@H¶€=`mÖ¬™ºwï^T’v—Iÿú—ÜË«Én!ÇC@ ±ÿr8FÍ2¹3Æ “Æ8i‰§v@ {p´jÕªÉ<0b>Q3ýû÷¨Ú2ïP+`ÑV8J¬3µ#€$O`óæÍZ¾|¹òòòârШ8ì¸ÔI% €$RàÅ_ô2ÙZ°Q­Zµy(êF@ !+W®Ô7ß|£C=Ô«?pÔ¡CáÃ}ðäbm½—, ¯e  €é+pË-·(77WŸþyhˆÑ¢zó¿ÿIŸ~ZÔ–!€ P´@BŽV¯^qT{+2¥±SVì‹%%±%Ö—Ú@’/`Ù¬Ä#ÃÑ»ïJ.Ñ£{Ì«’@H {ÝØŸõêÕÓE]”í¥‘ €D ¼ÿþûÊÏÏ— §f%pTT†#Ëæþý÷ÒÕWG×Â< €é+°nÝ:o5»vêÔ©ØŽXϖ† “,ë@X’pdѳÉ(Mš4‰8Lt¦¥ˆ•Ì”Kà—_¤õë v7ož7‡²µ2… €@êâymsÏkU­štôÑ©ëGF@ ,cÇŽÕŒ3tá…&ehô²´m@ˆU`üøñÞ¦ÑŽŠ 8²d~]ºÄZ3Û!€ S§Nõ‚oûöí[lƒwï­]+=ù¤T£F±›²@„mÙ²%â`66h2ÊÎ;#³><2&b 3å¸ür¹›Î’mÆ+–á¨J•*jÛ¶my«d?@|%¯ Gß}'Ù=î“N’Z·öUi  €Å Ü}÷Ý.X¶šl85  €é*`G]»vU«V­¼.X†£† ÷5ÓµO´@²XÀ‘•~ýú»Û=÷H6´è¥—JGUìf¬@@ @BŽ5jqÀè!Ö"VÆqfÍš5µåääDÌ3SqËpTµª´Çº,ਵ{Šj7¤) €d‚@0ÃQ^^^…ºóÐCÝÿû UÃÎ €$MÀnHOœ8Q§Ÿ~zèmÒÎ@ˆ“À?þ¨ è°Ã Õ¸i“Ô¡Ch– @2^`Ê”)ª\¹²zõêUd_§M“n¼QêÖM²À#  €ep!#‰+ÑC›-Y²$q «9:à(:ð)lS&Ë)`I£,ÃQ°,_¾Ü 8 Îó@t° G–½ÏjË[ìz9z´Ô§4`@yka?@’+pϯw™ÿøÇ?&÷À @8 ‡S;üðÃCµ~ù¥´kWh– @2^ÀŽ,Û_:u õÕF19ã ɨyáɆ¥ € P„f8jܸqD[&Ož1Ÿ¨™`zÀ`ý%â÷sÜ8iΜ‚úÖº]q.ð` @ ýV®\éRí7týÊŸýôÓÒÆÙÒÿ÷ €Ù"`þ^{í5 :T{ï½w¶t›~"€d €Ù÷¹ƒ>8¢wî½  €Y!`Ïîì;^qé=ð€4{¶tÇRÏžYAB'@â,Ѐ£N:E4÷ÓO?uÝÜS·—>ú(âÝ, %®öì5˜áh³ ¶Gq%¦2@ ØP°¹¶åçK?,åæJ§–âÎpx@bøûßÿî2?ìÒ5×\ãl† €€ÿìZ6aÂí³Ï>ªW¯žÿH‹@H‚€e7²Ò·oßBGÛ±Czè!¹a´¥+®(´š €Ä$Ѐ£ý÷ß_uëÖ 5d‡»z=þøã¡ùDLX¤îôéÓ#ªŽ~‹%b%3°²V*òP¶Â @â,PÑ€£wß•~üQºà©fÍ87Žê@H€€ OþÏþÓ»=xðà*@HŽÀO?ý¤uëÖiРAÉ9 GA@À‡ÁaŠÊpôòËÒ’%ÌìHðîÃ^Ó$@d $4à¨zõê:ôÐC#úóì³ÏjÑ¢EËâ93räHïmÌ`¹.­@÷î݃³üL€ÀªU«¼ZÍš‚ €@¦ØC׊\ÛF’,Uÿ%—dŠý@Èt‡]j>Ë^Kv£L?ÓôÈ|~øÁëd×®]Cµ—BF–¶o-b@Œ° GUÜ Ê^½zêçßþ&Õ©#]xa¡U,@@ f„Y+Ž?þøˆÆl۶ͽé÷†IÄŠ8̼ð úðÃ#j:ñÄU©R¥ˆeÌTL`çNi̘@Ö«‰ Gódo@ÿ ¬_¿ÞÝ„Þ^îì}îeZïZiµní¿þÑ"@¢¶nÝêÒé?¤¼¼< 6,z5ó €¤•@0à¨sçΡv?ö˜tþùCB ™@@ ƒ,ÃÑž{î©=öØ#¢—| 7ZŒ4|¸”“±Š@Ê$ð€£hÈ!²aÏ~÷»ßiéÒ¥Ë+2óôÓOë–[n‰¨¢aƺ袋"–1SqAí¨£¤ ÔEÀQÅM©@À_½¶¹ÊϤ$öWÏh  €E X6â+V誫®òÞ€-z+–"€ EÍ™#µmKÀQzœAZ‰ PQ»¿9þ|5œZÓ¦Òé§KW\QÑ£°? €@¶ TMÀ_þò}ñÅYf̘¡ãŽ;N¶î(½RÞ,Dï¿ÿ¾÷æ¬Y³ uå w¥¬cù)qøå—@uõê~Vô¡l\Ge €ÄA ¢×¶NâU:øà84†*@H°ÀîÝ»uß}÷É^Ú9ï¼ó|4ªG@ ñ?þø£4h‘µvß}å2<$þØ@?Xv#+E¹¤GrƒÆP@¨°@Â3Y 5j¤Ûn»­Ð[’6\‰½=9tèP7~öh-_¾<¦Ù'ï½÷žNpOóFŒ¡¢‚,˜éÔSO©>6*›€;m^©_?ð³¢eËvt¶F@ ñ«V­ò’››[®ƒ T °\° €Iøê«¯df-qíÚµ“xd… €@b,ÃQøpjv”'Ÿ”x 1Ç£V@ü&0eʯI}ûöõ[Óh €@ $%Ñy~øázôÑG]z¾+´eË–BKéwûí·{Ÿ¦._Ïž=Õ¼ysÕ­[Wõ\mÛ¶iáÂ…¡Ï²eËÜ0%nœ’bÊ ÷”oäÈ‘åΚTLµ,þU ¸ Gå}( , €~ ˜Öog„ö €$RÀ‚¬ôéÓ'‘‡¡n@’"°iÓ&-Y²DƒNÊñ8 €~°€£ªU«zÏ\ýØ>Ú„ I 82. ²LF]t‘Ö¬YS¤ e97n\‘ëbYxüñÇë¯ý«we{¶)»@t†£`KSLA@ 8Ê„³H@buêÔ)Ö]Ø@ß ØuÍ^VÎpäÛÓ0@ `CªuëÖMµjÕ Õþþû’}íkÓ&´ˆ @*$”!ÕÂ[Ø£G3Fgœq†*WŽßá-3ÒO<¡»ï¾[5kÖ ?$Óqf8 RÍÒî‡ÿÑçCR €I(oÀÑ«¯J+V$µ© @ üôÓO^:t¨p]T€ €@ªl85+¥úLp|@T ¬\¹Ò5¦_¿~¡&lß.}¶tðÁr¹¡ÅL € P!øEü”¡999ºùæ›õæ›oêä“O–«”·téÒE·Þz«Þ}÷]/ƒRyëa¿Ø‚Gn´;¯ØCÙFÅ^["€ às`ö¾² j_Ú‡— ªöyçh €Q– ¢I“&ª|«$j=³ €¤“@Q™ûÜ;ª:ï‘6m’=4ñíã €ÄSÀ2uìØ1žUR €)f8 *ôÿ“¾ýVzê©”5‹#€ 4)S¦xÇêÛ·oè˜6²š{¼ª .-b@ ¤4à(ØzŠëè£ö>¶l÷îÝÚ¸q£~q©tìgõêÕeY‘ê¹”:ÕªU îÆÏ 3_~µ‡²¤ÞOÑÉà° € °k›ey(ËßîOuí* ’&Q) € ذaƒt…Ž<òÈ„ÔO¥ €$[ÀŽZ´h¡:uê„=w®Ô¾}h– @2ZÀ<Ø}Íž={†úéœq£Î„f™@@ .¾8ŠîIåÊ•½à" 0¢øO pd§g×®]ZïR1¤šÿÎ-B(¿@y²÷sŒd  €é$v† GétÖh+ €@IpžÛ6iÉiàÀ’öb €™#`Žºwï®5jdN§è  €€/|päK©µ}ûv­ZµÊûXF¦–-[ªJ•*1ìû&[·nõ2?Y€OÕª©9}6¤šïjG+W®R~~>G±ŸB¶DÒJ [®mÑ'Å®çÍ›7^Ì< €@dëµ­¸SgéY!à¨8!–#€é!èë›îIÆr&ìå‘5kÖ(|8µùó-£>Žbñc@Ào\ßÊ~F,ƒíâÅ‹5tèвïÌ €”Q 5+eldY7¿óÎ;½¡Ø‚ûÝvÛmÁɸÿ\¹r¥Þzë-ýÏ >sæÌˆú-]a^^žK×ÛÞ.îˆ#ŽˆXë̤I“ôÌ3ÏÈÞ<]¾|¹·[%ñÓ¸qcpÀ.âÉêÓ§O¬ÕUx;ËpT»¶äQɾÄ[!ÃQ…Y©ð@6^Û¢ñíúfoQ@2C€k[ñç1˜á(üÁlñ[³@ÀO‰¾¾ùížd,ö–ÝÈJçÎC›ÛpjVR-àÀ¿ €€ß¸¾Uì Yv#+ýúõ“A[/¿,w^à™^Åjfo@ ddÀÑo¼¡µk׆z›¨€£1cÆè¦›nò† ,lbÇŽ^ÝÀ}÷Ýw½ #ÛÞ²ÅR-Z¤?ýéO²±V£‹e²(å×_Ýû ”ÍÍÍW•Ôƒ ®mèe½¶}ÿ½äâ~Ýlu0… z®m±{!¦£½UBAH D^ßÒéždq'ËŽ*W®ì†OkÚÄÝ¢UµjRëÖ¡EL €øL€ë[üNˆe8êÞ½‡~ÿûjîY¡ôØcò~ÆïÔ„ €@G1OÙÐe;íVô¶@IDATwî mߪU+½ð jÚ´ih™MôéÓG'Ÿ|²^{í5ýßÿýŸl4+]üæ›oê„Nðæ£ÿyå•W|ÇÖUs߈Ÿ~úi¯¾ðm8àzê©úío N²±Õ_}õUrÊ)á›&lš G £¥b@ ©\Û ¸Ëzm7.°ï!u0… z®m¥Ÿƒ7jùòå:âˆ#Jߘ-@|!Èë[:Ý“,îdØ=Õ¼¼ož\Æ£ˆEÌ €øH€ë[üN†e7’šiÚ´“Ô¶­tóÍñ«›š@(J€€£¢TJXöÖ[oE¬½øâ‹]:ÞÒóñþá ‹,a¼fÍšàlè§e>Z±bEhþ°ÃÓqÇš/jÂ2)õïß?´jÆŒZ´hQh>ž¿ü"÷–tÕUZËúP6žm¡.@ødûµ-Z±,×¶;¤? Œ…^§NtMÌ#€¤J€k[lòöPÖ G±y± jD^ßü~O2ûŸþY›6mŠ8²Û¬öâd‡±ÔÀ6 €©àú?uaEº_[¶TרQRíÚñ«›š@(J€€£¢TJXöý÷ßG¬ãø)lÔ!ê›mt]VñÇQÿ¡‡1_ÜÌÀ#V½óÎ;óñš±€#+õê~ÚCÙªU«ºù_ó/ €@ D_²íÚ}ªV­Zå-ÊÍÍ^Uhþ“O7¯cüs Ðþ,@HŒ×¶Ø\ƒŽ:uêÛl…ø@À‚þíöÜÒ¥/öù YIiB"¯o~¿' ° §f%üº¶y³tøáR¿~±ÔÀ6 €©àú?õ1cv¹ÊNu‰ vëØcãW/5!€ PœGÅɳܯ? – ¨qãÆÁÙR¶µü…aeñâÅasÉ/¿ü2´¬R¥Jnx–A¡ù’&Â3Ùv‰ 8Ú°ArÍRýúÖXÀQ,dKj;ë@R+í×¶hý²d8²áÔ¬Ø l  €€¸¶Åv.Èp›[!€€þò©V-iÏ=¥—^j埆%©%‰¼¾ùýžd,ÄÁ€£ð!Õ,S»}o;ÿüXj`@Tp}‹ú¶mÒ”)ç©råÍzè!ÿÆG•Z@J¨ZÚ¬ÿçiÓ¦‘+K™³´¾á%:iîܹ >ä´ízôè¡F…ïRìôÞ{ïín¸Ôri·xÛÌ™3§Øm+²¢{wiçNi—I»bY bmc`þEð›@¶_Û¢ÏGðZܰaÃèU…æß{O²Íúö-´Š €)àÚ¾e8²HrrrbÛ­@ tí*¼ÜYr÷£V뫯RÜ $>Q×·t¸' uQG±ìÇ6 €©àúÿ—^ZížÝåiŸ}ÞTëÖî&  €I ਌Èÿüç?•ŸŸïíµÇ{ļ÷Ö­[]ºçÈáØö´×±ÂÊ7ß|6g7OÜÝ“KµjÕÔ¦MÍž=ÛÛc‡Ë/½~ýú„ uVÙFÛÇŠ=”îG` ÿ"€¤‹×¶È3e×6 â-í:¿fdâVp]Œ¬‰9@T pm‹MÞ2uìØ1¶Ù H¢ÀöíÒÅK—\"÷ЬàÀ§&ÙÇʇ®Íº€£D]ßÒåždàÌÿ¯Õ¨QûGZüV¬Að›×·øœ‘gž±ZéÔS«Ä§BjA@ Žb@ ߤ¼Á5÷Üs¶Y>Ã_‹e7ªW¯^pÖų̂\XÖ·LëÇ9ûµ«/úÁºKúiAK_ýµ<ð@o³š5kê=KáPDY»v-ŽŠpa¤€e„;÷ÜsC ¶€Í7º¡#;2´&s'²áÚ6oÞ<Ù¹^ÛìlŽ?Þ»}f-{_,Ã…¾ÿ¾´{7éEû1þxðÁõꫯz ² j×®íŸÆ%¸%Ùpm[²d‰ìMàðkÛ›o¾é2¡ÏøíïÛÿpÆMðo#Õ#óçK×_/÷bœýÿFrq eÖ,©N¹ÀˆÅÞŒ{N'œ Mœ(÷÷zdÀ‘=|æ™g¼í¶»¨¤J•*® ƒ—$êúæ—{’kÜ[›6mЏ¶=ÿüó1Yæ¾:¸%F&ƒÿ3 kdœÀ+¯¼¢Q£Fyý²û’áÏ‘2®³Åt(Ó¯oÖíéÓ§ëóÏ?ר±c=áäá‡.F¤|‹.œæþ6Z« /T¾ Ø ˆ“€ý¿îöÛo÷jÛå†M²$)”Ì à( çÖþ£zî¹ç"Žtíµ×FÌÛÌ/¿ü±¬¬GÑÁEv³ ]»vuÆ2“ç7ïÒ¥‹î½÷^oó⾤¯[·Î ¯¶“€£XPÙ|+кuk=:Ô¾cŽ9¦ÔÌ6¡³x"Ý®m-[¶t©„[ëÑG µêÕ«‡¦Ã'ìúËp¡ãÆö2$|o¦@ÿœuÖY:öØc½MtOm?þøcÿ4·-I·k[ãÆ½Ùð¿cÊ0mÙ¬áȇ¿Œ4 4p·ƒôÙgÏŒÒm·Éý½]ÐðªîŽãË/–Ù0h¶½-³b‰Ãû[É‚Ž,(éškE¶néRéÈ#å^„“~ÿ{éþûmiA9ñÄ5xð`oÁ—_~©×^{­`%SE Är}óË=I»ŽY¶Ùðk[óæÍ‹ìWôB»GiCÃ}ôÑ«.¼PrÏtuÙe‹™A|#0tèP—Í/Îo–»8>ôÐC¾i›Ÿ’N×7s´ *»Î]bé]±ýãY,9À¢Eç»{GªnÝ7ãY5u!€e8à€BÓ/\¸P7Þxc™ë`‡ôøõ«~ú48ZºÛ¥=xì±ÇôÀD4ûx7Øüa‡±Ìf¢¿Ü—åf±í½}ôÛI¶M,ÅRÛ;E+ÙÍ —$Bƒ\€t°þX²@Är\¶AR!`A'áÿ¿³7d‹ ´LEûüvÌt½¶ÙyŽ>×ÅÙÚõÍ‚oK+pd£ŸõVviû²H†€eº f»™9sf‘YÝ’Ñ¿#]¯m6¬vU÷ô>üXŽ:uêT–ÝØ²X`Ñ"éÝwåÞÌ·l¡v«Ã†9 8jÕJ.S\ðHÁ6Á)÷•K#GJ—_.wãY.cQ °Èþ¶>âiþüÀúë® îQð³Aƒ²»q]ÜK{dïTY®o~¹'Y¥Jïûxy®móÝ/Žeél¿H¿K6ÿH'ŸLÀQЄŸ à?{‘<ø2¹Øßù”âÒñúf½±gnö ¯<׸â5 Ö¼ñÆÞupذa ™BR$PÇ¥³µËpd÷¯(™+ÀÙMйýþûïõÿ÷ša¯y…ËdË‹*Ñ_îËšá¨nݺÕZŠüxKÔd7…,öš5«¼êcÉïvP €@ò2õÚ.iüÚõ¸´k›½•mYÝE@4Ȇk[q§Ç†±B†£â„XŽ&àž{êÎ;¥ÿýOr±«^q1!êß?‰èàƒ¥½÷–rrëÂÿ-*Ø(¸ÞÞó,FnôOÝr‹ÜÛø,GîÏq/É2 QÊ/PÖë[:Ü“,Mã‡_Çí 8²à5ûîæFY£ €d€@6^ßb=m–õтՂYŽcÝí@¨¨GŒÚ߯ ´ñvm|q{h^Ž:ê(ÝqÇ^jàðåÁéèqçËú––½Å^¢3…¯+ïtðí5ˆ­\íUSÚCÙò‹ý@ü!é×¶peËn”ïîH—–½ÏÞÊv£ïQ@ÒT ›®mÅ¢`†#ŽŠb9¼ÿ¾tî¹ÒâÅR‹Òðá’õE‡.—e¨â>–Àáê«¥3Îþô'iêTéÞ{L¯=;k(ïõ-îI–vFƒGá™û\ÒÝ~»tà¥íÍz@? dóõ-–óbÃã]úIY¥¬‰ b©Ÿm@(I€€£’tʰ΂‹^yåoø4K{^lƒ?¹;''œpBøâBÓ7ŽX¶aƈùÒf¶Yžà°L1¶¨Â“.žÊ+ö…=8¤Gf¥@À—Ùrm ÇçÚ®Á4 yÙxm+î,Z†#û.—ˆïÅ“å >wÝ%]½\|éé§G‰j}óæÒèщª=;ê­èõ-îI–v&ƒGáŽìwëÏ.mOÖ#€øU€ë[lgfäÈ/´}ûg.ëä’Øv`+@â(ð€££>ZK—.c“K¯j“ ŸÄbi¯½öZÍž=;â¨övÐinû«®º*4oÄQ3ÑÙÊp´5j\ tŠw± GÕ«Ûx³ÅÛ–ú@? dÓµ-Ü=–€#{ÃÛb„kÔß“i@¿ dëµ­¸óbŽÈnTœËÈ U«¤o¾ ]f?o¾YÊË‹ì› 7eÙ;£ËH6j×.z-ó~ˆÇõ-îI–fn´uëÖU³fÍJÛ”õ €i Àõ-ö“ôÚköLôp}4´Å®Æ– €ñHxÀÑ–-[”ì xáÄRÏsÏ=çÆ²¿SÑÙí¿ÿþºîºëÔµk×Xªñ¶©è—û+VD+QG6œš•Xʶä_@tȶk[ø¹)éÚvä‘ÒäÉ’% üðÃÀ˜ð}™Fð¯@6_ÛŠ:+öÝ^ :ôÐC‹ZÍ2HSK|ýÞ{Ò«¯Ê «!-‰zÉÝoçåtÎÅjÐ éØc¥ãÊlà@éƒ ¶eÊŸñº¾¥Ã=ÉÒ΀e8 ÏnTÚö¬Gð¯×·ØÏ%.˜;·³K°Ú‹7Š}G¶D@ N 8ŠS;}WÍÆ½aÒl\ÔðÒνöu½Ë9=ÈîØ”±D¹/kf¨%aw’ªV­SV¥26Q6¤š §fe•½*çJt»½…üƒ vÙzm ?Q%]Ûj×–öÙGêÖMnšð½˜Fð«×¶¢ÏŒe7²B†£¢}XŠ@: XѻÞzKÞ}kÏžÒСRiûÛ’Û=žÇ—>ý42à( ²±­ñ¾¾EßÛóã=ɒγ½ðºhÑ" 0 ¤ÍX‡ às®oe?Ao¿ý¶òóÿªK.¹Ïí|TÙ+`@*(@ÀQ9-{Qx°‘ø\vÙe:ÿüó]$±s¬¥I“&{M›6-b¾¤N-üf@¯^½\JìJ%íR®u6¤Zƒ]- „£ApA¹jd'@¿dëµ-Ü¿¤ G¯½¾%Ó €é Àµ­è³dÃÎXéÔ©SѰÒBàÜs¥×_dà´÷ï/|²4lXd&£â:sàÒwßIö¿„¨¤ÙÅíÂrŸÄûú–÷$K¢·@Ú|7>`t†#Ëèe¼F*ioÖ!€øE€ë[ÙÏÄkî†e•*?ê†Ü[’@R ð€£³Ï>Û =âÆÉ 2zôh—¢Úå¨þµXÀÍc=& ò©H±/Åö?84š¥¶T÷µ-¥B)Å‚“víÚÚ*Q©ñ-ÃQ0ý¶=”ÍÉÉqÌT — @ôÈæk[ø Õ¯ßHÝ»Kgž)—¹0| ¦@ÒE€k[ñgŠ GÅÛ°d X²j»Å4ožô—¿D}ÍË.-Õ¬)Y&£èÁÅ‹¥½ö*2jÓ&rÿXç¬ÞèºcÝ—í’/ˆë[:Ü“,IÚî¡ZÉÉé­§Ÿ–&N è’¹—%KÚ“u €~àúVö3aÏÇŒã†R;H7.{ì €@p4|øð84Ó?UÌŸ?_wß}w¨AµjÕÒO<áRT÷-+ïDåÊ•uÌ1Çè©§žòªØ½{·&Ož¬!C†”Zå|±Í!‡1¯ËpRÍÊ6bL™xÑR 2l¿¶…ÃŽ~ù¥±fÎ,’"|¦@ü/Àµ­äsDÀQÉ>¬E ‘nä'Mš$ íÛoG«VMúã¥:u ŽþïK^˜?é$):ãæØ±’K¸MÉ"D]ßÒáždq§ÙÝžÔÈ‘–±o¾®ºªmh3 ûÒK ò…6`@À7\ßÊw*ÞyçÙ°¢Ã,½%@ TNÑqÓö°o¼ñ†vìØjÿwÜ—`£`…Ç|pÒûiÁL¥•uëÖéÕW_ m–çRµk×.4¯‰Í›¥;¥úõ5p/YêAR+Í×¶hùUîr&uáºÞ*»IMAH?®m%Ÿ3R­aÆާä-Y‹åXºTzáÉÝ6ÒH‡È"d÷TŽ8Bºï>É%Î9Gzþyɲ…Ùq{ö dÛ´ ‰ÓO/Ü‚ ›dú’D^ßü|O²¤ózûíÒÔ©ö"èV ¾M/¿,-_.ï’‡’»Ö•´7ë@ü Àõ­|gá™g>r™üqÇžX¾ Ø @8pTFÄ·ß~;´Gûöíuä‘G†æã1ѵkW—ƺS¨ª3f¸TîU1eãÆºä’K´Ù¢~-§œrJp2®?m85+Á€£5.·wnnn`!ÿ"àWü|¿¶,Ð.—ÉÌýÈ“o¹¾- ¸¥UY¶,áçïÖÓº Èæk[ô) ÓΚXcCTP@ÒO€k[ÉçÌ2uìØ±äX‹1 ذhÑÅ|ï Ï{à Ò?þ!}þ¹ä’d먣¤{ùF²ýž}V:ã ©I“è¤þýK4aŽ($òúæç{’%ù9slØ´îåA.k| ÙmÑ¢þ{*©Ö!€¤V€ë[Ùý-³Ñ{ïµV~þ-]Ú¬ì° €q ñr ¿ÿþ{-²€€_KÓ¦MõÏþ38[æŸ6TZ›6m íw¡Ë—}Í5ׄ–ßzë­Úµk—{›ít/ëBpÅwgê²Ë.s± .8á×b7ϱ×ãPl85+pdNöaHµ€I¹ÿµ ˧nãÔÙÇr¨Ç»Øk].c‡ìºlX¡Ÿ6ýY»6°lÛ6©E ©W/éÑGKo‘Ý%µ~¸1ƒ½ „‹˜¶h5ûX§7löÜ3p‡µ´£üå/’µ«R¥@€ŽéD‚Ç·å6m?·n•lˆÁ J;‚4p ´reà<Ô®-ÕuNìÓðŸ6]Ô§ys¹§6¥ÃÆR¶vY?,e˜õ©¸bÛ4h¸SfwË,ÀñºëŠÛº`¹ýÿÃÚh6ì¡5™ƒ+ü§eksÿoñÖÛ66½Ï>E¿:[P{`êÊ+¥*U{­Ö é¾ÝÖ…ÿ´i«;X¿ý´»ævG½´bwâ­nûïÂ~?Áã†ÿ´uáóýúI¿ùMÉG0ÿîÝçÂÚÿëç,{Í8‹J¶_Û¢Ou0àÈ.­ö+áâ€) €i&Àµ­äfßãì»d¢†á.ùè¬E s쫎Ý~ùøc7Ó|iÁ¹{<ý³¯=6Z^^àÈô6L•O ×7¿Þ“,IláBûZÿ³ºt)x³¤íY‡ à/®oå;cÝØº;vª=öØ¢~ý\T;@ ¸'´‰-8cÓËÈ‘#Õ¬YzFÛÚ[ áåÓO?•}Ê[,CRQGÇwœ>úè#ý÷¿ÿõªÞíÐßvÛmzæ™g¼áÛjÖ¬©)S¦¸á^Ü7ê°bCÀÜrË-îÙ|‚VÜql”¶o¿ Ä?ØY+y ÿX‹ø¬Xª°§Õ%w^õðÃ[¸sëY¾g ı`K¯a?;w.H²À;FëÖû7eÃôÙ«”% l±•œœÀÇ¢Êìni0p¤¤}m žó²ò”¶]p½†X€•³mÛàÒ’Úð‚–“>ºX]{ìøX}¬ö3¸|ï½£÷*zÞÚdÁ@Û·Σ½&gAQaÃ(½£[jÁ1ÿû_±«C+ g™­ÉØ+®ö±¶§m¹ý7fç8øùî»@þýPEÅLXåæõÜEWsî¹¥YÐÐý÷Gïû¼£´€# ~rÿô‚²¬O6_–rÞy¥™Qõê+ë“Çý¬R^»²´ÏGÛfûµ-úTØõ­K—.ÞÿÒìáý§IAH/®m%Ÿ¯ ŽJvb-&`_íÖŒ{žã½ÏžäÚ¾FòIàkœ ™ý•ÅÞ5!+¿Gñþÿ;Xg"îKúõžd°ÏEýœ?·û*?ÏÝ6s÷Í( €i'Àõ­|§ì¹çƹqÃönñ^š,_-ì… €@Åp4uêTýüóÏ¡–†ýZ˜& ,#IŇ~qÙ`,ð(X/^,ûUj¹@…‡\Ží~–Õ#AŞˇ–ùê+ áJÚYæÏ> d²±àŽ’Ê«¯J£F¼Žh1öº¢ Øy°ßëðŸ cÁ*Áb"v‡±¤røáÀ˜`Ö«Û¦m_»«ùŸÿìmd–AǶ±c[¢b~ vrSÇKC‡RS…§í§YàNt‰5ðÂŽa…Á€Ë œ¶ŸÈcǰŸö±ee-pc.vW7Hd?í3^e̘¢k²$s·ßûþ±óeó±/h¯¸&²X°’ý~Øù°e­²À7 f«Q#ð NÛï”w[üiç®´bÛÛïžÝQÿع±b?çÃ눶,þ_ÛμƒÅ~- (|~\›Ž^nÁl¥ë¿cUžu~F-ËäÙl¿¶EŸ[.´aÃ&^œæGD¯e@ ¸¶•|–~üñGoƒð¡¼KÞƒµdŸ€ ¯ûÔSÒèÑ$¸&L:®aÛÙ×, ÉHÖõÍ÷$‹óµw‡Ž>z¹žþUq]+N‰å €€¿¸¾•ýüls/¤¿óŽ»W®J:ñD÷Œ„‚ €@ Ü“i–§Ÿ~Ú ¸ ¶nĈ.® ŽÁŠËð3:£Pv-ó¦µ]@Æã?®GyÄÝäzʵ©Ø:öÝw_o¶½cÍâRlM±¯Hy†# >pCܹS̲gÙÐVá nùòKiòdéë¯ï¿/ \r‡-XÂ\&M*y;ˋ޲¥tÐA’fÏ» i?cù}µìCö)ªXËìÙ´R–ZÊ>6o}0 ¶á»¬Þ‹.*ªöØ–ƒFJÛúê«KÛ¢âë-`É>©(v.í<§Küàï"­ìw>™Å~-@È>”¸ pm+à\ç®#;]ðZµj{z‰Îºu+XÇ €@úpm+ù\ß &ÃQÉN¬Í>{äå—¥þ3ðž’ XÂûº{æ™R«V…M6*lÂ’Ä $ëúæ÷{’áÂö~Ó‘GNpG¸ÿ^_ _Å4 €@šp}+û‰7nœ¶n=Øí˜¯#Žøõ%à²Wà €ÄEÀ·GÏ=÷œK á2hüZ~÷»ß¥<àè®»î’}’U*»oÍ—]v™ÎsC½óÎ;š1c†Qj©K¢³Ù%·iáFÓjíbf»¬C{%«I¡ãŽrcÍêÚ³ˆ —MB6tUðÓ§Ý-(bðEÓ§K}û,°ìCv÷oÙ²@`Ž 9],È‚{ŒmhªK.‘ìcÁ^óç†[´(0 ˜[Øñì§e‹ID±  "Kb Y"ºA ào®mç'xmÛ¹³‹·0—ׂÆ0… Pn®m%ÓŽÈQ²k³KÀÛ-ûiï,{®tþùÒd—½õ·@2¯o~¾'}–~øáoCªEË0¤‡×·²Ÿ§·Þú¯Ûévuë¶Ý½_£ì° €qðmÀQû˜öUíá†6l˜÷ñKgVYöWÊ5¤Ú–-’ Wæ²X髯$ËL^.¸ ô€£=¤k¯•\v'í¿ ëOxÄdw íㆦSÏž±g ¯Ç¦ín£=uæÉs´ ó €@¹üxm mÞœçõ‹ÿí—ûô²# •~¼¶u"lHµ ¸!Dµšed¥€Ùíƒ{î $ Že„欄¢ÓY'×¶¹sçzç¥}ûöYw~è0 €@ùÒáúVRÏÆ_ëV7.vðŒ’öe €ñ à(Þ¢YR_ð¡l™Ž\†&=ù¤ô¯‚ŒjÕ’öÛOêÐ!ð±6Ý©SéŠUݯnIÙ¦ìæ¹}xZ\º%[ €xÁ`Úµk[ÈFñëÚ@2OÀ21œZæWz)`ãÅ4ôÄÒ˜1¬Fücd=Ì!€€ÿl(ËÀnCÁQ@Èt5îeûùó»yÝ:4Ó{Kÿ@ÒA€€£t8K>lcÌG;wJnx<=þ¸ôÙgžØaý«töÙRNŽ{G“@²Q xm[±"WíÚI.Á @Œ°á¹—,Y¢AƒeT¿èLö XBãY³¤™3#?î×\ýûKcÇÊeô*ÞÇÅ)èê«¥6m¤(~;Ö €€?®¹Fúâ‹Û´çžWù³´ @8 LšdÏÙ.Pýú›4`Á¶qæ¥:@rpT4v‘‚eKLÿl™tòÉÒÇžÚ.]xa «ˆ €øL xm:tÚ·¯ç³ÖÑ@*.0gÎåçç“á¨â”ÔbG•^|Qšè¨U+鯥}ö‘êñç_$S¤‰À§ŸækëÖ.ÊËk&-¦™ €TLàÿØè*h¥áשjUŽ*¦ÉÞ €ñ à(ŠYX‡=”µqnkÙ°hE•~>XZºTºòJé/áî]QN,Cð@0àèØÊpj¾9+4@ ž?þø£W]§X†±Žç© 8 ¼ñ†4mštâ‰R¿~ÑÔmDõ¼‘*W.Ü[víµ…—³ÒC`îÜ]®¡ Õ¶mÛôh0­D@ ‚'öu5lpAóM*X»#€ Žâã˜uµ¬ZµÊ½ØŽÛX4=zH÷ß/rJ±›±@¿صÍJnn®_šD;@ˆ«ÀO?ýäÕ×±cǸÖKeÄ[`åJÉ2ÙÈìUªH£FEá‰'¤ÆK×2Y@Q—.EEÖȤ£À•W~ï‚otGG¤cói3 €eذa‡¶m{[:äªaÃ3Ë´/#€ (Ž%›áõZˆFßËjÕ¤±c‹_Ï@|&`×¶J•*©Aƒ>kÍA@ >d8Š#µ$^àÛo¥ßþ6pœ®] /Öd&7ÜPxß;¤íÛ%~‚é-ТÅ×®c]ÀÑ…éÝZ €@ ³fMÓÎйçºTž@|"PDBiŸ´ŒføZ Ô€#_·žÆ!€ PXÀ®m999î-z÷=@ ° Gv­+ñå‘ ì7]òŸ€ý¼÷žté¥RëÖ’Ê^ú÷—^yEZ°@úî»ð5Ÿ¶¡Ö,!óܹ¯‹@ µ ì®´iÓ&µ áè €$A`òäÉÞQ˜„£q@b ÃQlNl&°k×.­_¿ž›Ôa&L"€¤¿€mÝ:Fg%=÷\ú÷‡ € -`G §­Â|"¶m“lX´5k ¾úJzçé—_GîÜYZºT²ŸÁbÙ‡N>98¿ŸS¦HwÜ!õìtŠ_ÍÔ„©µ5íY*É1@ˆ“€U­ZUý-:Ÿ‚ €€O8òɉH§fØÙüü|ŽÒé¤ÑV@RV®\ëŽú¸ ÚR7e@ÒN`›‹ùùçŸÅÛ°iwêÒ®Á+VH­ZI–Ũ¨âF°uI¤ã—N8AÚsÏ¢¶J̲/¾Ž9FºývÉF‚§ €@ú lÙ"ÍŸ¿@{챇rssÓ·#´@R,8ñbÉŽzºÈùÚŒ \Š«@’)@ÀQ2µ3äXpd…/órBé €€'°zuP[Mݺ‚ €@æ Ì™3Ç{q„ G™wnSÑ#{è1s¦4uª4h´ß~­hÒDúío¥:u¤† ,‰m“Š2b„d ¤¿ÀWHãÆ½å²£˜þ¡ €” pï½Òßþf´×©§îS–¬B@ ù%ß<í¸jÕ*¯5Jû¾Ð@L`óæÍÚ¶í 2RÇ_  €'`GV:tèq}£C°ìŽ–ùgÖ,¹ 4É2U®\ðiÞ<(ü(×]'Xrå•‘G¶ôÉ'÷fˆ¿ÀÂ…VçNµoï") €d¨€ Cl[·jµÖe9úÔe¬ýC†ö”n!€¤«GézæRØî`†#/àÈ^i|þy颋$ÆKOáYáÐ €\Û¶h¯½VªK—ŠÔľ €øSà§Ÿ~òF†#žŸd¶ê»ï¤I“¤Ï>“>ÿ\²y 4*® X8à謳¤}÷•ºwü,n_–#€‰˜3g§«z»éÒ¦Q@ÈPåË¥=l8à7¼aÕ";CO4ÝBÒX€€£4>y©jzDÀÑ¿þ%Ýu—tÌ1¥ê„p\@ ³÷1\h…)©@À§d8òé‰IA³î¼³ ;Q^žÜ°  ¡^½¤êեݻ#?õënäá‡Kö¡ €©X¼Ø¥cÓBµiÓ&UMภ€$\ sgéã-Ðÿ>/ȶeË– ?&@@ ,I8?~¼7n\j7mÚ±ÍÛo¿­5jD,‹uæ7¿ùM¬›²] G¯¼"µn-í¿ {²  €þˆ¸¶ù³‰´ @ X†£Zµj©¹EÉ yó¤É“%ËF^FŒ† 5i¾†i@ =V­’¶n­âK†£ô8c´@ "ëÖ­sÃÏÒé§Ÿ^‘jØ@„$=àè¾ûî+WGn¾ùæríg;pTnº"w >”m±x±dw0¯¾ZªdoQ@HO•+׸†ï©œœÜôì­F@ ËpÔ¡C÷Õïn¥P¥ýê-[¤ÁƒC¦UqÏã;LjÖ¬ [6Hg… ƒ­_è²= Îð@Œøä“OÜÈùb8µŒ<½t H{Êiß:tа3ï¿8¶å_§ € Æß}·Óµ~–Þ|³_÷‚¦#€ P´À®]»´`ÁuìØ±è XšV–ú­·¤‹.’z÷–þûßÈæ»DVZºT:óLÉ%‹vY¦#×3‡¤»€»¤ýZÈp”à' €@f ¸¯p²•É–¶Ô•x?ù@? $=ÑŸ:O[Ê'`Žªº×$kØÎöí¥}ö)_Eì… €€O~ø¡š×’î݉ÅöÉ)¡ €q°`£;vxŽâX-U%QÀˆ§wÞ‘þ÷?éÃ¥mÛoÓFÚ¸±pCæÏ/¼Œ% €@¦3U©ò³Z´h‘)Ý¢ €„>úH:ê(éÉ'%ËpT·n]í½÷Þ¡õL € àŽür&Ò¨p4´^=iÑ"éºëÒ¨å4@¢æÏ¯í­èÛ·fѰ@4øÉ¢U\!ÃQzD{ >z´ôüóÒ÷ßÚ^Óý©rðÁÒÑG@¸Qò( €@Ö 35k¶MUlìH  €&0k–´u«”›»S_|ñ…7œ×¼ ;ÉtÈ„½þúëÚ½{w†pÑ °€#—¹=PN;-8ÅO@ÒV`Ù²†®í»Õ¿¿ ¨¥ € asæÌñzÔè”´8³ÿþ·ôðÃÒHùùR³fÒÅŒ=TÚc´èD&Èp´Ë%^¯‘°cP1 €©˜93pôüüoµyóf/à(•íáØ €'ð€£œœœâŽÍò4X³j•Ž´œí]ºH={¦i/h6 €«W7S¥J Ô A»‚…L!€ !d8J¯9i’ › |²ôÛßJG!—Á#½ú@k@D Ì»ËU¿Dyy­yêF@ epÔ 4{ö^˜²¶p`@J¨\ÒJÖ!P”@w—á¨ÑŽÒ©§µše €¤•ÀÎÒ¦M-U³f ûCZ5žÆ"€ ƒ€e8ªV­šÚ´iÃÖl’ ËÎñè£Ò>ÚŸÿ,-[&½ür «ÁF…X‚Ù-°`Kÿ¦…jÛ¶mvCÐ{@Œ°€£½ö’&Ožì ºï¾ûfl_é €@z p”Þç/é­_·nN‘GÀQÒý9  €@ü~úɆ+©¦zõÇ¿rjD@À–á(//Ï»Qíƒæd},˜Èž‘!=û¬ôóÏ‘$MšH$‹Ž4a>|–›½€£p¦@2F`ùrɽ÷ 8êÑ£‡êÖ­›1ý£# €™%@ÀQfÏ„÷fµûKç$w”e¹¹R·n ?@@ ÑÁ1ÑssÝ·y  €&ŸŸ¯¹sçªC‡Ö³ôíN³fÒÿýŸôÚk -[¦o_h9 N>u‡ý™ûRÏ1@.¼WÙ¬Ùj-]ºT §–pr€ PªØ—]³P`Ç»ïÊ…iRŸ>r÷H) €¤½ÀŒ»\ª¨eËuiß:€ €@´À’%K´eËuìØ1zóIX¹Rš8Q:å”ȃÝzkä¸b±7 €>˜>}»kÉnµk·Í'-¢ €ÄO`Μ9^ed8ŠŸi¬5=óŒÔµ«tæ™rY¦bÝ‹í@JµiÓ¦´MY €@Ú Ž–,yÏk;ŽÒîÒ`@ «|áÈÒ¾/·ÁJ+Xößÿ ÖÀîžÀŽj2y²¦»™ê{í  €!0kV%×ùjÖ¬^Fô‡N € .ðÓO?y³d8 W‰ßô.—(qÕ*É2…^]š0AjÞ\zñE©}ûø“š@lp#…ÊŽš4i¢Zµje3}GÈP 8jÔHš>}¬ZµjÅ¢zžé )) 8Ú¸q£¾øâ }òÉ'ºâŠ+T·nÝ×Ñ£G»sîÎ\ËìÙ³+X»{•+ë³ÎÒ“O<¡ì¯  €i.°s§ 5š_Ýõb¦û"ϵ-ÍO'ÍG(B€ GE Tp‘)=÷œôÃ’=üŽ.•\<ó…Jwß-Õ¯½–y@ò œwžô駯«wïË[û!€ àk 8ÚsÏúì³™6l˜¯ÛJã@HIÀ‘½…òðÃëm7<×.»Sçʈ# ü¢îÚÚŠI¨REÓÜÛCcÜÿÆCÙ¤±s @Ä ¸K›{8QW]u£ 8º6q¢f@R$`Ž*¹è—ö¤Ø‰Û°¿þýoiÝ:¹RãÆûºšn×NjÛ6n‡¤"@_æÍÛ­Ý»«¹!±] 9  €&°t©´v­}¯Xá®w»Õ¯_¿ ë!ÝAÈ4¤YpÑ=÷Ü#Ë\ 4J$h5Ô§OŸD"ëê^½zµ×g²@dÝ©§Ã €@F Xö:u溾}­ÜÜÜŒì#BÈnËpdiøíû1¥ì}$ýü³túé‘û¾ñ†Ô²¥T5©wU"ÛÀ sçÚË« ^&O>}F²@ N¹g¨ÒÔ©“¼ÞöíÛ7 zM@ÒY i·Æ6mÚ¤+¯¼R~øa¹½l\î-[¶”¸õêÕ]Úò µÿþû«G²yJü,àÈÞŽmذaü*¥&@R(@0m ñ94 €@Â,à¨wïÞ ?N¦`úté”S$— J–¹È¦-³Q°½((ÁO@ ¹÷Þ;U§žz¾Ë"wQrÌÑ@H‚@ݺÒÙgKãÆ½í¤ I@ç €HZÀQIÁF–Q Zµj¥väÝwßõ¶™;w®‚ŸñãÇkÙ²e¡}·oßîÒ ®%Í`H$¾öP6''ÇÝh »ÓßCP €I à(©Ü @ ‰v[çÆýêСCš‡²!Ñvî”®¹F:ï¼È`£Ìè!½@ÒS`ëÖ\Ãg¹€#Æ­LÏ3H«@b˜:uª÷=ΞÇQ@ð³@RŽ^yå•"3tÐAî-ÁStÈ!‡¸4ä…›b™t¢KÓ¦MeË`dÅ™l˜¶—^z)´éóÏ?ïÕ÷ç?ÿ9´Œ‰ø¬ZµJ §KjAð‡Gþ8´@ þ?YzW:vìÿÊÓ¼ÆÝ»Ý€ª_K&>gž)qFA§ì¾þ¼yóL!€øC`Á‚^C8òÇù  €ñ°cfÏž­“N:)þ•S# €q(åçlܸQ#GŽ,Të­·ÞêZQÆuÜ€¦·Ür‹Ž>úh]ýõZ¼x±WóÏ>«nݺé„N(cl^’€=”mÙ²eI›°@´°`Z‚µ®å,¦ € A6œš2Nêš5ÒË/Kï½'÷R”dóVl$öýö Ló/ €€¿.\è5€#Ÿ'Z‡ P> ¤o¾ùJ»Ý}ûö-_%ì… €@pdàmÞ¼9Ô%ËZtÇwèÄO -‹ÇDÿþýõðÃë7¿ùw!¶:ÿú׿ʖ·hÑ"‡ '`G=zôÀ@Œ°kÙû2ætÒ@020>ÿ\zôÑ@°ÑÖ­áÑúõ“|”jÕ ƒc@À—–ÜhÖ¬]ª]»ž4hàË6Ò(@Ê+`ùZ·–?ܽá Gå•d?@d TNôÁÞ|ó͈CwÜqq6  k×®:í´Ó‚³²´ƒáC­…V0Q.-[¶È><”-;!€øT€€#Ÿžš… PalÎpänè‰'¤Þ½Ù‹\dYÑsÏ2}ö™ÜËPÒa‡lTá_4*@’$p÷ÝÒ'Ÿ<岯÷JÒ9  €É˜93p¬õëgy}úôIÞÁ9 €åHhÀÑÒ¥Kõ¹½JVÎ9眰¹øO^qÅÊÉÉ UlO–zRq{ k…€£Š[R €€8òϹ % €ñ° GMš4ÉÊaCG’.ºHš;W1Bš1Cš4I:óL©^½ø:S €@r,Ñ´Í Z'9ä( €$Qà»ï[±b¢òòòÔ°aÃ$C!€ P>„}õÕW­êí^-ìÞ½{IJxÏX°Ñ 'œªvÙ²eúÌ^]¤TX Zµjúýï¯AƒU¸.*@@ÀùùùZ³frssýÐÚ€ €@\,ÃQ‡âZ§_*³÷ŠÆŒ‘þô'éC$*-¼ .=þ¸ôóÏrïËÝ‹_Ë4 €@: Ì™³Ã5{‘{Û6›O›@(QÀåSÐìÙ[µ`Á+ §V¢+@ü$P5‘Y±bEDõûì³OÄ|¢f:vìQõ”)S4`À€ˆeÌ”] iÓ¦zðÁ˾#{ € àS 6¸±Ñ[«U«V>m!ÍB@ |7nÔòåË5dÈòUàó½Ö¯—N9ErÝTýú’KæTä¾¾ê }Þ š‡ P&E‹*¹í¨m[ŽÊÇÆ €i!PÉ]æV¯žîFmÙBÀQZœ1‰ ` 8²››á¥yóæá³ ›nß¾}DÝÑO+™A@¬¨çÆT™?~ÖöŸŽ#€d®€e7²’©Žl$õW^‘ –ºu“*'4sæþžÐ3@ ]~ùEÚ´Éne/T›6mÒ¥Ù´@2 L:ÕÛ¾oß¾eÚ@H•@BŽ¢}Z´h‘”~FßP|JJ#8 € € €)øÉRþ¸8EÍ)×awí’\Âb½ð‚4w®ôßÿFVsä‘‘óÌ!€d®À‚Á¾Y†£ÌÌÞì!?@²W`Ú´i^çûô铽ô@ ­pd)ÜÃKƒ ÂgK¾ä’KtÚi§…¶kÔ¨Qhº¤‰÷ªc•*U´ËîNº²råÊ’6g € € €%ŽŽì+üôéÒĉÒH“&InôS¯ô[7£NAˆQ`áÂà† R-HÁO@Œ°µ³gK_|1ÛËä—›››1}£# €™-Ѐ£† Fè­Y³&b¾´™¦M›Ê>e-ÜÉ`°‘í»mÛ¶²VÁö € € €¤­@:e8úê+éÎ;¥±c%2ÇJõêÒ~ûI, q‰,ôó €@– 3U©²XÍ›7ÏRº ©¯¿.]{­\2…ª:î8†SËÔóL¿@LHhÀQtF¢¥K—&ÅpõêÕÇ)kf¥ˆ™A@@@ Í,ÃQ½zõäç7c-Ð试Þx#€»ÿþÒàÁ £¤ZµÒ æ"€$L ˜á¨E‹ª\¹rÂŽCÅ €¤B`æÌÀQwíúF}ûþ1Mà˜ €”K ¡GÑo›LrùÐÏ8ãŒr5´,;Í ^™Ý):ð©,u±- € € €é&`Ž:vìèÛf¯['YPÑÖ­Ò 'H7ß,õìéÛæÒ0@ 2å«}ûj)n ‡G@ þöX³~ýM.ãë:õéÓ'þ F@$Ѐ£8 ¢Ùü±Ö¯_ï½e±"Î3&Lˆ¨±k×®óÌ € € € ©Û·o×âÅ‹µï¾ûú¶‹99Ò#H½{häÛ“DÃ@ Ì›·Ëµf¥òòNÍG§…¦ €ÄA ?_úî; 8šï 1Ý·/CªÅ•*@’$Ðü³mÚ´qo´uÅnz>øàƒ¡ùDLØpj'NŒ¨zàÀóÌ € € € ©sçÎÕîÝ»}‘áhÖ,éúë¥3Ï,¬}î¹Va  €@Qóæív‹¨mÛ¶E­f €i+0¾´i“´cÇWÿßÞÀKM€Ë”UT@PQYª VkE­hÝZ}û¡Vû¶Ö¥J­ Z«-.u¡Ú¢­ZܵµÕþkm´¨ˆoEAe—EöõþóÌ%!™ÉÌ%'“å—Ï'LÎIr–ï™›gæÞC";w–:Ķ/4@ }F')çñÇïQ}ì±Çä½÷Þó䙸õ¯mf+2o[Ú¶m+½{÷¶“¼"€ € € hY³feú×½{÷ªösÚ4‘^½D~õ+‘I“ê‰^ÕQ9 €@l®¾úM«í?fÂQlG†#€äÐÇ©é²lÙDáîFõü‹ ãŽÎ?ÿ|i×®#²eË¹à‚ DÿÇeÐËøñãåÏþ³§X­¿I“&ž< € € €$Uà“O>Ét­GUí¢þߟQ£D^{MDç@í´SU›Cå €1¨©±f±ÊÛL8ŠñÒt@{ÂÑ–-Såàƒö?ˆ\@"*`|ÂQ‹-äâ‹/ötùòårÎ9çÈ„ <ùå&Ö­['wÜq‡Œ=ÚSD«V­¬Û¶ûÜ·Ýs @@@’#öŽfÌÑÇ£ÝpC®áÍ7‹q„H£F¹ûÈA@ X¹sçfå‘jÅŠq €@\ì G"Ó¹ÃQ\v"€8Æ'iM#FŒc=Ö©T7¾üòK9r¤\{íµòÙgŸyö›X¶l™Üu×]òõ¯]î½÷ޜӮ¾újÑ O, € € €¤E@ïpÔ¬Y3éÔ©“Ñ.¿óŽÈ·¾UÿØ´‡ëñéF«£p@ èïY³W»té’bºŽ Dp´ÓNË­®}Å„£$0}B.PFÿ7n,·Ýv›õ?Ï“)S¦xª|â‰'D×Aƒe&õéÓGöß©­­õ·uëVY²d‰|ñÅ2þ|yûí·å¹çž“7z޳§vš >ÜNòŠ € € €@*ôG{íµWæ³Aw¸®9 Nj@IDATNäoë;¾È«¯Öß¹èÄE®ºJdàÀ k£<@êtÂQÇŽe‡v€@ÄXú½clMÍ Ù}÷Ýe×]wMLßè €@:B™p¤”:èw¿û\rÉ%òúë¯çè¾ñÆ¢«.:AI‡¦w'jÙ²¥¬ZµJ.\(›7oÎ9Ï/ã„Nk®¹Æoy € € €$Z Îš´Ï>ûÚÇõëEþô'‘ßüFäÃEš6ùÎwD®¸¢þGVFa €d è„#§–…B@ öŸ~*²nþ]ôm9òȃcß:€ >Ð&)­N"ºÿþûå¾ûî“;î¸C¶lÙâ+®w3Z±bEfõ= OfMMŒ5JÎ=÷Ü,r×]"óæ‰Ü|3“r¥ÈA0)ЧOþk˜²@ª"pÜqú=ëA«î'ˆsU*E¨T Ô;¹Û«W/ùío+sæÌ±nËþ'yíµ×äóÏ?wÒàv§NdðàÁrÞyçÉ^{íÕàñ€ € € €ÛôÆÃgœ!ò׿Š\v™ÈˆÛ÷é–ÞÍH'YO.·nóïÝG @@@ 2éÓß´ XÄ£Ê9@ JU›pd÷·[·nríµ×f’‹-’É“'ËG}”yœÚÊ•+3¯úˆµ6mÚ8k=¤ÿþ¢ŽX@@@@ <÷Þyå±þ#È­·æ–¡w8bA@@0#ðî»ïJÇŽ­GVóÌj3”Š `R êŽÜÓ€:lذÌêÎg@@@‚8ø`‘·ÞÙo¿à˦D@@@ü›6m’©S§Ê!CòÄ@",© GvŠLÓÖ¯_/zç§víÚIMMJ†o«Å¿ÙZ­[ýg^ë|†£•O^¡¬uÖÎåÖºÉZµ¼ìUëÌ^ö¶2¹27XÛZ†C­µf·a¥•÷¥µj»µ<»÷vv_z[Çe×±ÊÊk¶mÍò¯¬|­c½µj_ -vý}³ÒòçYkkmn­{X«{Ñò—X«Ýìö»Óöyìm¯«­×ùÖªýØÉZÛY«{Ñ6,³V퇮­UÛ"ûUûrHæˆíÿ¬°6g[«öCëèa­îe©•Xd­Ú{µýÝåÛÛz®õÇÏ¢ã½ÀZµý;[kSkÍ·èøkŸtÕúü­«Öõ¶ûÑÂÚ_û¡ÇØ}ÐWýùÐqð[ô±ý²vèù³¬U­ÚXkwku/ZÞZkÕ÷¸Ž‡ûÕ¯/…ê°N—–Öšý,uQO»öϸ¶vy¿:ô}9ÓZµïjuµºý9×ò´l퇦í÷˜¾j¾Ž½êÏWö{×Êb1/ÊØfž•@ª(·ØÖ»w±¨@ q‹m±@¥‘ €‘¨fŒ›>}ºlذǩEâ@#@ÊÈž¾PNœcX`âĉòàƒÊÇ,úØ9]5j$íÛ·—Áƒˈ#ä`ýo©ÕXt"ÉûÖ:ÍZu"†ý}}µ·µ¶Ýï´)Vz”µê$½CäÃÖê^n³W[«=QÀžâ>&{['Gèd{ù·µ1ÂZw°Ö¬õÿY«{¹ÝJh¥,:AA˳­ã›ÛûZ¯3ìÛ^k½þ<+¯¡¤NìÐÉKöâ®c+óC{Ƕ×;­×k³òJêÄ$÷xL°Òö´¿õ:}Û¶ýr¯µq(ò՝޶«O>È*ç7Vúº¬¼†’úþÐI(ö2ÑÚ8i[BÇ\ß“îEûQªUv¯[eØuøõcŒµ_ß¿:™F'³4´èX똻—W¬ÄÛ2t2ÒÛîÖ¶–ÿ«¬¼BÉrêÐ÷­ö¥ØE.ôçý¼l%ÎÜ–1Ðz}Ó½ÓÚ¾ÅZKé‡_jU¨ŽJ¬C¯!z-a E Ò±-*AHš@œb›õûlÙÁýÝ&iƒA@ˆSl ¤Ã‚ ¨Ä¸wÜQ.ºè"9æ˜cRcOG@’%àžv¬ž% 7óæÍ“+¯¼R¦LÑ:Þ¥®®N/^,Ï>ûlf=úè£e̘1Ò²eKïA§Þ³ |ÒZíIFs¬í:k-´Üoít7Kïüò޵êd‘5Öš½t³2ô³•¾;õ,úêÞvßÆÚ•Yt¿{ÙÑJh­: Bïv“½è]L.¶V½C}wm½]L]¬ãd­:±¤ƒµf/‡ZWZ«¶Í.7»Žìz´¿î¥“•¸ÐZµ~ufå_a­Í¬µÐÝvìzôUÛà^ö¶:ÙG'×´wïØ¶}¸õzµjÛô\wÜÛvÖ!9uìeåé$í‡_ju¹µj?tuOºÒ÷—ý³_µ.w}V2s›­WíÇ.š‘µa¥G[«öÃ^µý~åkž_û[ù:iéKkõ«£­•¿µêì» é²ßŸVVfÉoÍÔ÷­NöÑ~ìf­ÙËQV†–g÷A_5­}ñ[òÕ¡~ô½ÛÑç¤~VÞ÷¬Uÿ¥«Ž‰ýêWž_ÿôNZZ‡.~ýÐñÐÅn¿¾º×ÌN×?~uè)3gÎtZÖ´iSyàäàƒõù@Û—ÁÖýïÏ8ã ùîw¿ëLNÒçÎ>õÔSrúé§o?0È-}d”®, €” éØVB?8@[ N±Mïhtâ‰"³f‰ŒW—#»¼"€ ` Ä)¶Ùmæ@bˆqÅ(q  €¥ 4.ýÎ0)°qãFëÀÖo€]ËM7Ý”3ÙÈÞݹsg¹å–[ìdæU?8± € b[TF‚v €%§Ø¶u«ÈYg‰u‡\‘ŸÿÜzp¥ ‘r@"%§Ø)8ƒ yb\䇈"€ÄX€ G¼?ÿùϲxñb§UÇsŒœtÒINÚoCï|4Àu?üiӦɼyóü%@Јm¡“S! €€a8ŶK.©„ÚÙg‹üâ†a(@ ¶qŠm±E¦á €U ÆU…J@R"À„£ˆ ô믿îiÑ!C<é|‰Aƒyv½øâ‹ž4 @ª%@l«–<õ"€˜ˆKlûÍoDîºKäë_ùãE52%B¹ €qˆKl‹»3íG_€¾95"€¤G€ GëÉ“';-jdý6øÈ#tÒ…6Üw8Òã˜pTH‹}ù¦OŸ.ï½÷^¾Ýä'X`âĉÜ-Áã[í®Ûª=Ô¯Ÿ‹–.] D >þøc™4iR {N—M Ä!¶=óŒÈå—‹ì¿¿ÈsωÔÖšV¡ü0þùÏÊüùóì’º""ðÙgŸÉk¯½‘ÖÐŒ$ Ä!¶%É›¾ä èµM¯q,éÐÏ4úÙ†SÄ8S²”[ŒÀo¼A|+*Çüå/‘Õ«W'°gt ¯޼UMÍž=[¾üòK§ }úô‘víÚ9éB½{÷–æÍ›;‡Ìš5ËÙfbþýïËßÿþ÷bç¸ <üðâcdA hb[Т”WŽÀï~÷;&U–—€sÞyçk¢…5Ó‚âÛtžÝ9çˆtì(òÒK"mÚ@Q‘xàD'U²¤Oàý÷ß—Ç<}§ÇFâÛŒPx$Æ/zcIŸ€~¦yðÁÓ×qzŠ1.f*) ðØcñý ø$yט1cdÙ²eIî"}C #À„£½¦NêiMÏž==éB‰¦M›Ê{ìá²iÓ&ùꫯœ4 €TC€ØV uêD0)‡Øöê«"55"ý«XßMjP6 €@âÛ’àL@ ƅoN €é°~É÷Ý´MmJüo¨­[·ötEËkÕª•'¯˜ÄŠ+2wZú«þvÚZôÑn{î¹g1§rLÌ–,Y"ëÖ­“>ø æ=¡ù¥ èm?ÿüóTŽýÆ3}·Í¶nÝ*šÇŒ@Tb›NÂÕÕŽmÚ;mãX’/°aÃùôÓOe‡vH~gé¡G`Á‚¢ŸmÓúÙF¯Á+W®Ì˜¼û|ùr‰ò¢ÛÖ®]+ººc[×®]¥I“&2|¸ÈÀ5Ò¬Ùfëý_^?9+Ú:ösçÎMíõ-Ú£c¶uú½mÕªU©{ev<›1c†ç̪'¿ô¨Ä6ý.¾yófOlëÒ¥‹è´dI¾€^ÛÒú»©änáêgýl“Öïmú;Ï™3‡Çï~»”¼×¶µO¬ÖßÝôo/úØHûû[³fÍd÷Ýw·›Åk‚4¾}ñÅ©½Æ%xhìš~®Õ»ø¥ñ±jú¾×ëž. .Ìüí¹A0ˆ­Ž"4töì&•úÁ'{r‘~*g¢ÞºV?Ø^yå•™¦èc;uêd7‹× èãëê긽c‚Ç8_×–.]šyÜÐ3Ï<“ïÄæëá-ZäôoË–-™‰)íÛ·wòØ(_ *±í£>Ê|°µc›öHcŽÊÛ8©?ãwÝuŽâ4hµU¿Ðë®.¹ä’€JŒW1:ÙÊþ¥†~ÆkÑ¢E¼:ÑÖF%¶éw6m‹;¶í¶Ûn™ G¥£Y è/îî¿ÿ~yä‘G,•¢â  Õÿ(”ÖØfÿG+mL(æ]•ئŒX¿~½'¶u´žÊ„£`Æ9ê¥èï²uâɳÏ>õ¦Ò¾€ôç^ÿ0™Öئ}·¯ÃÛô?°'`ÛÚ%Vëïnï½÷žLŸ>]&éó¯­E?Ãðûg{T’ýªñMÿ#äóÏ?ŸìŽÒ»ýîvÓM7Yw Nßt í»ûqrßX’+¾wx„Ç2ûƒOö‹jzöñÙ3·:ßÞÿóŸÿ\teA@ R¨Ä¶ïÿû¢+  €• D%¶x≢+  €• D%¶õïß_ô?‹° € ”@TbÜÓO?T—(@H 4ŽTkRÞ˜ì>¥Î´nÙ²¥GÐþßÌžL €„(@l ›ª@B ¶…ÂL% €! ÛBĦ*@Pˆq¡rS €@ ˜p¡AÏ~¬KmmmI­Óǹ—ì;¹÷± €@Ķ0”©@ Lb[˜ÚÔ… †±- eê@¨†1®êÔ‰ &&Eh´³Ÿ×ªÏî-eÙ°aƒçð¶mÛzÒ$@[€Ø¶8õ!€˜ ¶™¦|@°ˆma‹S €@Xĸ°¤©@ ­L8ŠÐÈï²Ë.žÖ”:áhýúõžówÞygOš €a Û§>@ÓÄ6Ó” ¶±-lqêCK€–4õ €¤U€ GùJ?ø,^¼ØÓ&y8H €TA€ØVtªD0*@l3ÊKá €U ¶U*@B Æ…ÂL% €)`ÂQ„?ûƒÏ‚ JjÝüùóãkjj¤U«VNš @ª!@l«†:u"€˜ ¶™Ô¥l@jÛª¡N €aãÂP¦@4 0á(B£ß¡COkÞ}÷]OºPB§æž Ô·o_iÔ¨Q¡S؇ €€qb›qb*@Y€Ø28Õ!€ ¶'¦@* ãªOµ €©`ÂQ„†ºgÏžâþð3sæLY³fMQ-ÔÉI[¶lqŽ2dˆ³Í €Õ ¶UKžz@L ÛLÉR. €@µˆmÕ’§^@ÓÄ8Ó” v&Eèиqc6l˜Ó¢­[·Êo¼á¤ m¼ú꫞ÝGu”'M@jÛª¡N €&ˆm&u)@ Ķj¨S' €@ĸ0”©@ ÍL8ŠØè>ÜÓ¢qãÆyÒ~‰+VÈSO=åìêÖ­›ì¹çžNš @ª)@l«¦>u#€˜ ¶™P¥L@j Ûª©OÝ €&ˆq&u)@ íL8ŠØ;`ß}÷•½÷ÞÛiÕ´iÓä±ÇsÒÙ«W¯– /¼PÖ®]ëì:ýôÓm6@¨¶±­Ú#@ý €A Û‚¥<@j Ûª=Ô `J€gJ–r@iR ÂèÑ£OµÎïSIœ›+ТE yùå—'N”Ö­[K¯^½Doÿh/óçÏ—‘#GÊÔ©Sí,éÑ£‡Ü|óÍÒ¤IECë”Ç €AÛ‚P¤ @( Û¢4´@ b[Š” Eb\G…6!€$@àöF•t¢®®îaëüs*)ƒsý.¿üryá…<;;wî,}úô‘fÍšÉ;ï¼#sçÎõ쯩©‘‡zHúõëçÉ' €@ˆmQÚ€ ¤±-HMÊBˆ‚±- £@@LãL¨R& €@Ê:3á(¢ï€5kÖÈO~ò™0aBQ-lÞ¼¹Œ;V\Ôñ„ €@ØͰũ@À´±Í´0å#€„-@l [œú@ ƅ%M= €)è\Ñs·x¤š¹·Jmm­ 6,óµéӧ˦M›òV6pà@¹õÖ[¥ÿþya €Õ ¶U{¨@ hb[Т”‡ Pmb[µG€ú@L ãLÉR. €@Šx¤ZíÚµòâ‹/Ê´iÓdÁ‚¢éÝwß]ºté"G}´ôêÕ+Ý  €8Ä6‡‚ @„Û2t@À ¶9l €$L€—°¥; €Õà‘jÕ’§^@@@@@@@@b(йq M“@@@@@@@@@ JL8ª<Õ"€ € € € € € € € G&ÅqÔh3 € € € € € € € €U`ÂQ•à©@@@@@@@@8 0á(Ž£F›@@@@@@@@¨’ŽªOµ € € € € € € € €ÄQ€ Gq5ÚŒ € € € € € € € €@•˜pT%xªEÀ-°iÓ&ÑuóæÍî슶—-[&óæÍ ´L»Aëׯ—E‹Å®l»ýÕ|]³f|öÙg²páBÙºu«‘¦|ùå—òá‡ÊW_}xùŒ}ई@bâÛt ¸ÆUöv4ãˆo•g#€@å&b›¶Šïn•©ˆmþ²&?3ù×H.˜ ¶yeÓp}#¶yÇÜN¥aìí¾òŠ@ˆoÞQNú5.αMGÊäø˜,Ûû.#•fš4wž¾#üãò£ý(Ó”þýûË#ùäyöÙgå£>ÊL6Yºti¦œÆK‡äˆ#ŽóÎ;Oºwï^Vù'N”|P>þøãÌd#-¤Q£FÒ¾}{øàÈ•]Vƒ<©®®N^}õUyá…äµ×^“Õ«W;¥7mÚTvÛm7éܹ³ >\N<ñDiÒ¤‰³¿Ø•+Wʽ÷Þ+S¦L‘9sæx&µmÛVöÜsO9úè£å»ßý®ÔÖÖ[¬scïP°E Ä%¶iw¸Æ9¨>‡™ŽqÄ7t²@ jAÅ6íßݪ6Œ VLlËOdò3SþZÙƒ&ˆmõºI¿¾Ûòÿ%}ìó÷œ=$[€øV?¾I¾ÆÅ=¶é™“e'ûêAïÊhTî‰zžõý°õrN%ep.iÐÉFúH—r'=÷Üs2zôèÌ,Ø†×ø÷œ\’/@l3÷;Ϩ¼{ˆmþ#Alów!¤ß’ßâÛôgÌd 2YvR®ôÈ@g&q¥PŠX¾|yæÎC7nÌœPê„#=ïºë®ËÜÙ¨¸ë:ôÐCeìØ±Ò¢E‹‚§-Y²D¾ýíoËçŸ^ð8÷ÎnݺeîÒ¤w>*´˜,»P½aíÓÇ™rÊ)%ÙÙm»óÎ;å¸ã޳“y_o¹å¹ÿþûóîÏ·C'(|òÉùvgòMŽÉ² vŠ Š@Ôc›"˜¼™,;”,¢Ó1ŽøVÄ p„*PilÓÆòÝ-Ô!+¹2b›?Y>×ø÷œ\’/@l3÷;Ϩ¼{ˆmþ#Alów!¤ß’ßâÛôgÌd 2YvR®ôØŽŒÑR0 lذAÎ?ÿ|σJpôûßÿ^n¿ývOM}ûö•¡C‡Ê~ûí';í´Sæho½õVæ‘^îõñ]·Þz«;˳­í;í´ÓdæÌ™N~³fÍä°Ã“Aƒ‰Ö³bŠѲÇ/«V­rŽ;üðÃå¾ûî˲ÿþûË®»î*sçΕÿüç?™ c[¶lqŽÕqÓÿùܵkW'/{còäÉrî¹çêæœ]ýúõËL$Ò;%éd2-ÿý÷ß—?ýéO²nÝ:ç¸æÍ›Ë3Ï<“÷ñz&ÇÇdÙNÙ@ª èÏx”c›Â˜¼™,»jƒêS±ÉG|ó' ª*DlÓðÝ­ªÃØ`åĶ\¢´|®Éí99$_€ØfîwžQz÷ÛrGƒØ–kBI ¾%?¾Å5¶éÏ™Éd²ì$]#è‹1Ε¬T³V(AÀš˜S÷ì³ÏÖY“yêzöìéYÏ>ûì¢K²nXwÐA9çï»ï¾uwß}w5qÅ·Œ7ß|³nðàÁÎñZ÷”)S|ÕLk’ŠçØ^½zå=ÞºM_õ85ÏñO<ñDUÊÎ[iˆ;¦Nê±ØgŸ}ê}ôѼ-øôÓOëŽ8âÏ9Ö£Õòo}x¨³‹æ9ÞºcUÝÖ­[}Ïùâ‹/ê¬ fžãÏ<óLßc5“±ÏKÃÈ#—ئÍç—g‹Ì6ãˆoE‡!€@(AÅ6m,ßÝB²²+!¶ùÓ™üÌä_#¹ `Z€ØV/œ†ë±Íÿ§) cïßsrH¶ñ­~|“~‹slÓ29>&ËNöÕƒÞ$ЩqE3Ž8°~Xå¶Ûny{ 'È×¾ö55j”XÁ±Ás p×]wÉš5kœCôn7ZGãÆþ?Ö”_þò—Îñº¡Öò[ôvÿãÆóìºé¦›äàƒöäÙ‰Î;‹>þĽ<ùä“m²l§’*o<ýôÓžÜxãrÖYgyòÜ } Ý=÷Ü#555N¶Þ™(ßòᇊ5‰ÈÙ}àÊE]”÷ŽR»ï¾{æNXM›6uÎyï½÷23ªŒm&ÇÇdÙÙý fâÛTÄäuÈdÙfG³´ÒMÆ8â[icÁÑ ¬€©Ø¦­ä»[°ctiĶ\Ñ´|®Éí99$K€Ø–;ži¹¾ÛÒ;ö¹='ä ßrÇ4 ñ-®±MGËäø˜,;÷Fþþ3ü%ʰî:“™¼£×úä“OdÓ¦Me”â=EËÔGbÙKëÖ­å‡?ü¡ÌûjÝEG† âìÿïÿ+‹-rÒöÆŸÿügY¼x±”cŽ9FN:é$'í·¡“‘ àìš6mšXw>rÒö†É²í:ªýúâ‹/:MØm·ÝäÔSOuÒù6¬;H‰u'$g÷çŸ.«W¯vÒî>øÀ”SN9%ïd#ûÀ=zxÆgóæÍ2}út{·ójr|L–ít€ E ޱMaL^‡L–Ê Y‰ÉG|ËýÜTä°p `"¶i³øîæÿ½0€! ¬b[nüIËçšÀÞD„@Dˆmé½¾ÛÒ;ö½Ñ, ¾¥óר¦o~“߯L–è.…%Z€ G‰^:—TŒ¢³VíE'餣b–Ã;ÌsØ„ n®Ø%ûŽPíÛ·÷=µmÛ¶žü xÒùŸ}ö™gWö{Awš“e{:FŒ Ä1¶)ŠÉëɲh‘˜ŽqÄ·ÜÏME ‡!€@&b›6‹ïnþß ²@Š ¶ùO>×ò¢".@lËý|†ë±ØñKÍC bâ[úâ[œc›¾áM~þ0YvÅ?¬&¥f¨éhµtÂÎðáÃ}«Ÿ={vYŽô<÷Ò¥Kw²à¶>â˽¼ÿþûî¤hÙ_~ù¥“×§Oi×®“.´Ñ»woiÞ¼¹¬[·.sجY³<‡›,ÛSQ­Zµ’k®¹ÆiÁ¡‡êlÚÐGíM:Õ9dÇw”Ž;:i÷ÆÞ{ïíNŠNÓǪZ.\(ï¾û®sHmm­dO829>&Ëv:Å„&·Ø¦0&¯C&ËmP‹¨ÈtŒ#¾y?71$‚ ˜ˆmÚ<î…ïnnêoÛDÒø½½úïjí¥—^’N8A&Mšä¯βu§;MŽÉ²Ž±±0ÛÆäuÈdÙqÔRcñ-÷}çñ§í P/`2¾™Œ?&ËŽó{ƒØÖðèú@ÃgsÄA€ØV?JÙ±2cç×Fb›ŸŠ7Øæõ …@Rˆoõ#›„ø•ئ¢ÙžAþ]ÔdÙIý9§_fx¤šWJEÀ¨@öŸÿþ÷¿E×7}úôœcõ.G: E—•+Wzö—üôÖ†îEÞž{î™É2Y¶»Î¨nëŒ~þóŸg;7oÞ<™1c†¬X±ÂÓÜ8@n¹åÙyç=ùÙ‰¡C‡Ê¸qã2tb‘.¯¼òJfÕm½Û”þOÕìeß}÷•±cÇúNö29>&ËÎî#iˆ§€Éئ"&¯C&ËŽËhãˆoÛ?7Åeìi'0ßLÆ“e‹Î^b[ýXù;èŒ.-AJˆmõzîßyVâæ¹Ä¶zmb[˜ï:êB >Ä·ú±Š[|‹rlSQ“ß­M–ŸŸ\Zîp…Q  ”(жm[éܹ³sÖÛo¿-o¾ù¦“η1eÊyþùçsvëqì%;@eÿû¸|¯ÙÇ»gØš,;_{¢”¿yófyá…äÉ'ŸÌÜq({²Ñ^{í%÷ÝwŸèk1Ë‘G)>ø d›ë¹~“vÝuWyà¤K—.¾Å›“eûv†Lˆ€Éئ&¯C&ËŽË@ãˆoquډŘŒo&ãɲ‹q‹Â1ĶúQðû¾Yh|²wÿN ÐyìCøÛêÇ*Ž×7b[ýØeǪ†~ú²ãØ7ÔGö#€€ñ­þ]·k\”c›Ššünm²l® ”"À„£R´8 \qÅžÖ\ýõ2kÖ,Ož;¡ûô}ÔVöâ¾+Qv€*õ|d?ç¶Ðd¦ ËÎîSÓ³gÏ–cŽ9Fî¾ûuëÖÌcØN>ùäœ,ùN^¸p¡èñ&Lð=„±÷e!B0Û´ \ãBHŸªŠqÄ·í“À}ÉB˜ ˜ŠoĶê¾!ˆmþþ…~'๠Gb›ˆûwžqC¿6ÛüTDˆmþ.ä"Dâ[òâ[5c›þŒð½=‰W ú”-À#Õ²EH#o|ãrøá‡Ëĉ3-Ö yÊ)§ÈÈ‘#¥oß¾¢·ÔÇj}üñÇòÏþSüqÙ²eKæØÚÚZÙ¸q£ÓS÷ÄŸF9ùº¡Ç–²dßYÇý?@L–]J«u¬ŽÇ÷¿ÿ}Q‡¥K—ÊâÅ‹EÇí‹/¾pš´fÍšÌ#Ïtùu×]—9ÖÙéÚÐ f:¦î¥k×®2dÈÌ’ô‘lsçÎÍLBûÛßþ&k׮ͺhÑ¢Ì{ä’K.‘üàîÓsêbì=<$@ S±M›n2™,;ö@ª*ÆßZ2‚Ñ0ßLÆ“eGktò·†ØVoä÷ÂüÚìA¸ ÛÄ÷ŽãQGb[ýÛ¢þN¥}TO€ø¿ø娦ïd“ß­M–]½ŸBjŽ£Žâ8j´m:!åì³ÏD¢‹>«tìØ±Ûöú¿ôîÝ;óH­_|1s€þ ÈöÒ¾}{{3óºjÕ*Oº¡„¶Á½èm(íÅdÙvQ~Õ/³—]v™§‰zÇ©I“&e¥öŸÿüÇÙ7~üxùÚ×¾&Çwœ“go<ôÐCžÉFMš4‘Ÿüä'rÞyçùNÓ}·Ür‹çqzz%½›R=ìbÅäø˜,Ûé ±MaL^‡L–—A "Æßêoß—1§ Pš€‰øf2þ˜,»4¹êMl«·òwÕMjFĶí¿ó4ák¢Lb[½*±ÍÄ»‹2HŽñ-^ñ-ʱM*L~·6Yvr~¢éI&Ëv÷“mH†@бMUL^‡L–„-&ÆßêGÚý¹) cO@À+t|3L–íU‰gŠØ–Ü ýN ÿYìA¸ Ûâ:r¹í&¶åšØ9Ä6[‚WÒ#@|KÆXW;¶©¢ÉïÖ&ËNÆ;€^„%À#ÕÂ’¦ }ôÑ¢«.›6m’ùóçËn»í–óˆ­yóæÉòåËÖ 0ÀÙÖìå¾’çÀ< ­×^tÂS«V­ì¤Ñ²Jb¼¡w›êÖ­›Ìž=Û酎׮»îê¤gÍšålëF¿~ýD©VÌ¢c«P›1cFæð­[·Ê§Ÿ~*ûì³O&ÍØ£È1 ¦@P±MÛÌ5.̑˭«¡G|“Ì„q÷ç¦\Er@ )AÅ7b[ußÄ6ÿB¿ð?ƒ\H‚±- £XÿˆçB¿›ä{ßÛ’ñN§/@|+Þ*ªGVó{›šð½=ªï Ú¤Àö[iY*e!€@UtÖn×®]s&i£¦L™âiÛ Aƒ<é:xÒï¾û®'](¡·—uOPêÛ·¯èuìÅdÙvÕ~=âˆ#Dû­ëСCKnŽ=ùÇ>qÅŠöfæõ‹/¾ð¤{öìéI7”È>~îܹÎ)&ÇÇdÙNØ@D TÛÆäuÈdÙQT“1Žø&™ÏîÏMQ{Ú‚æ*‰o&ãɲÍi–^2±-7þ¤eìK·p+@l+VÊÌqÄ6b›™w¥"€ñ­zï¸Æ63ùýÊdÙÕmjŽ£Žâ8j´9õuuu²nÝ:gÕ;»¼ñÆΡ;í´“xàNZ7tBŠ;HÍœ9SÖ¬Yã9&_B''mÙ²ÅÙ=dÈg[7L–í©¨Š ½‘=6:™gõêÕ%µ&û™à{íµ—çüìG­dï9Ø'‘ý‡L÷Ý“LŽÉ²}ºIÄPÀdlS“×!“eGi(MÆ8â›Höç¦(=mAòLÆ7“ñÇdÙåk&±-7þ¤eìƒ7Q"é ¶å^;£4úĶÜñ!¶EéJ[ˆ®ñ-÷ú•ÑŠklS?“1ÈdÙQ{Ú&Åcœh%•+W:wÑÑ;é\z饞ýù:ùåÿø‡³ûk_ûZæñN†µÑ¸qc6l˜“¥ÝrORrvøl¼ú꫞ܣŽ:Ê“6Y¶§¢*&²'Ù/+¶IÓ§OwÝa‡2Xs2¬ýöÛÏVÊâ>^Çcï½÷vN79>&Ëv:ÀÄZÀdlS“×!“eGiPMÆ8â›Höç¦(=mAòLÆ7“ñÇdÙåk&±-7þ¤eìƒ7Q"é ¶å^;£4úĶÜñ!¶EéJ[ˆ®ñ-÷ú•ÑŠklS?“1ÈdÙQ{Ú&Åcœh%6mÚxîBôÖ[o‰N jh?~¼¸ïˆsæ™gúž2|øpOþ¸qãúë©§žrvéó¾÷ÜsO'mo˜,Û®£š¯=zôðTÿÜsÏyÒ…:akñâÅÎ!:¨I“&NZ7²ÿ û¯ýK–.]ê9&_bÑ¢EòñÇ;»uŒš5kæ¤uÃäø˜,ÛÓ  KÓ±MQL^‡L–•5ãˆoþŸ›¢2ö´Ê0ßLÆ“e—/ì™Ä6ÿø“†±öDi¤K€ØæíŒÊ»€Øæ?>͍¼CiÑ ¾ù_?£0bqŽmêg2™,; cOâ!À„£xŒ­D G`ß}÷uòtæõ믿î¤ý6>üðC;v¬³ëC‘Ã?ÜI»7´l÷o¦M›&=ö˜û϶Þ9é /”µk×:ù§Ÿ~º³íÞ0Y¶»žjmŸrÊ)¢ª³—¿üå/òòË/Ûɼ¯ .”+¯¼Ò³ÿ¤“Nò¤5ѵkWѾö²jÕ*¹ñÆEo÷YhÑGÝ]vÙeâ~üÞ7¿ùÍœSLŽÉ²s:BÄR@¯ötlÓrM^‡L–m›TûÕdŒ#¾ùnªö˜S?#`2¾™Œ?&ËF¶òRˆmþñ' c_ù»‡H·±-ºãOl#¶E÷ÝIˈ¾ñ-šcçØ¦¢&¿_™,;šïZEï­3JláèÑ£OµNéSâiŽÛ–/_.>ú¨ãÑ©S'9õTý±jxiÞ¼¹¼øâ‹Îÿüç?å ƒ’Î;;yöÆßÿþwùÁ~๻ѭ·Þ*»ï¾»}HÎk‹-<e&Nœ(­[·–^½zenhŸ0þ|9r¤L:ÕÎm|óÍ7çÜÇ>ÀdÙvÕzÝqÇ3w›zóÍ73MÐ;O½ôÒK¢ùj—}Ǣ͛7gÞ—\r‰è×íeÀ€b]c¥Q£FvVæUÓêû׿þÕÉÿä“Oäí·ß–ƒ>Ø3É>@ëvÅWˆÞ Ë^ºwï.úÈnî79>&˶ûÆ+TW ʱMeL^‡L–]ÝQ­¯ÝdŒ#¾åÿÜ…±§ ¤] ’ئv|w«èWOFß~Ķüñ'éŸkŒ¾±(Û¶ÿçÀ ç…¡'¶Û¢ð>¤ TK€ø–Ìø÷ئ?&¿_™,»Z?ËÔ+Û½É.±íÖ5¶N9§ÄÓ8¶ Ìž=[Üw™éß¿¿<òÈ#Eûüä'?ÉLf±O¨­­•Aƒ‰–£Ï4Õ‰&S¦Lɹû‘ž§w$jh¹üòËå…^ð¦šúôé“y×;ï¼#sçÎõ쯩©‘‡zHúõëçÉÏN˜,;»®°Óúغc=VôfîEmt\tÆqÓ¦MeΜ92kÖ,ÑÇѹ½C’ÞÉoò˜}ÜwÜ!÷Þ{¯Ì¼j™:‘He§“ÉôñlZ‡Þ¡Ê½èuüqéÛ·¯;Û³mr|L–íé ¨Š@Ôc›¢˜¼™,»*šU©éG|Ë'‰‘¨4¶i'øî‰¡ôm±Í—%“™ôÏ5ù{Î’/@l3÷;Ï(¼{ˆmùGؖ߆=$A€ø–Üø÷ئ?_&cɲ“pm F:3áȨ/…#PX Ò?Ë–-“sÏ=Wô7Å.ßûÞ÷2w»)æø5kÖd~1>a„bÏüÏ]}lÛàÁƒ<ÞdÙ VÂóæÍË<"M'|•²ì³Ï>rýõ×gîVUè<½sÒ5×\#Ï<óLƒSs—Ó®];¹îºëäßø†;;gÛäø˜,;§#d €@èQm bò:d²ìÐ3O…&cñ-:Ù PUJc›6žïnUÂ+'¶ù¥ásÏÉE ùÄ6s¿óŒÊ»‡Øæ?Ä6rHŠñ-Ùñ-αMÆLÆ “e'åú@?Œ t®è¾ÖÖã~x¤š±±¡à4q{ÇÓO?=3ÑçÿþïÿDÏ•oÑ»Þ\{íµrþùçç;$'_ï˜4lذÌ#Ô¦OŸ.›6mÊ9ÆÎ8p`æ]zw¥b“eS¿écôñsú\Yí§Þ Jÿ€ZhiÕªUf"Ø7ÞXðQwvz—¢!C†ÈСCeÁ‚™;Ùûò½j{ô®Hp@¾Cœ|“ãc²l§l €@Õ¢ÛÆäuÈdÙUÔ¬ŠMÆ8â[6Iˆ„@¥±M;¡Uã»[$†Ó·Ä6_£Ÿ™ük$ ¶™ûgXcØP=Ä6¡4|g÷ï9¹¤C€ø–ìøçئ?&cɲÓqõ —ðHµ ð8H ,\¸PÞzë­ÌÄ}ŒÖüùó¥C‡Ò­[7Ùÿý3øjÒ¤ü9†k×®•_|1óx.à¢i}lW—.]ä裖^½z•ía²ì²à‰K—.•™3gŠÎ®×G¨}úé§™?8tíÚ5óø3}Õ1ÒIGå.|ð¼ÿþû™²?ûì³ÌãÜ:uê”yÄš>fMãÖ£G²Š79>&Ë.«³œ„‘0Û´³&¯C&ËŽÊ@™ŽqÄ·¨Œ4í@ LÇ7“ñÇdÙAWR±Í_/ cïßsr@ b[1JÕ;†ØæoOlów!¶ ß¶[Dm+αM-MÆ “eGí}@{"!À#Õ"1 4@@@@@@@@xtnvÒJ@@@@@@@@ˆ‚Ž¢0 ´@@@@@@@@˜0á(&E3@@@@@@@@ˆ‚Ž¢0 ´@@@@@@@@˜0á(&E3@@@@@@@@ˆ‚Ž¢0 ´@@@@@@@@˜0á(&E3@@@@@@@@ˆ‚Ž¢0 ´@@@@@@@@˜0á(&E3@@@@@@@@ˆ‚Ž¢0 ´@@@@@@@@˜0á(&E3@@@@@@@@ˆ‚Ž¢0 ´@@@@@@@@˜0á(&E3@@@@@@@@ˆ‚Ž¢0 ´@@@@@@@@˜0á(&E3@@@@@@@@ˆ‚Ž¢0 ´@@@@@@@@˜0á(&E3@@@@@@@@ˆ‚Ž¢0 ´@@@@@@@@˜0á(&E3@@@@@@@@ˆ‚Ž¢0 ´@@@@@@@@˜0á(&E3@@@@@@@@ˆ‚Ž¢0 ´@@@@@@@@˜0á(&E3@@@@@@@@ˆ‚@MA@J˜?¾œyæ™Î‰‡rˆÜ~ûíNš @â(@|‹ã¨Ñf@BĶB:ìCˆ£±-Ž£F›@ ¾5$Ä~r˜p”kB  -[¶ÈÂ… ¶.[¶ÌÙf@¸ ßâ:2;IDATr´@ Ÿ±-Ÿ ù €q ¶Åuäh7 €@!â[!ö!à/À#Õü]ÈE@@@@@@@@&ù … € € € € € € € €þL8òw!@@@@@@@@|˜päƒB € € € € € € € €ø 0áÈß…\@@@@@@@@ð`‘ Y € € € € € € € € à/PãŸM.+°dÉùàƒdΜ9²eËéÒ¥‹tïÞ]öÚk¯¼ElݺUÞ}÷ÝÌ9zþN;í$íÛ·—~ýúe^óž˜â6lÉ“'ËüùóeéÒ¥Ò²eKÙe—]ä ƒ’]wÝ5Å2t0#@|3ãš]*ñ-[„4 `N€ØfÎÖ]2±Í­Á6 `V€ØfÖ×.ØfKðŠ„#@| Ç™øŽ3µ t&%}„é_Ek×®•8e´hÑBÞ|óÍLzÞ¼yò»ßýNžþyÙ¼y³sŒ½qÄGÈ¥—^*ûí·Ÿ•9î¾ûî“Ç{L/^ìäÛ7–Áƒ˵×^›™¸dç'ý5Û¹OŸ>#í·N.úÍo~#/½ô’¬Y³Æ—B'jýìg?“8Àw?™^G}Tn¾ùfOæ‘G™q®­­õä“@d d_w‰ofÆ9Û™øfÆÙ.•øfKðŠ@:²¯¹Ä63ïƒlgb›g»Tb›-Á+éȾæÛ̼²‰mfœíR‰m¶¯¤W ûºK|3ó^Èv&¾™q¶K%¾Ù¼¦Q€Gª¥qÔésI›6m{µ'M˜0A†.O?ý´ïd#­@9óÌ3eÖ¬Y™ú-Z$gœq†ÜqǾ“ô ½ó‘žwòÉ'g91%ÿØÆúj;ÿãÿã?>ãœo²‘ò¼óÎ;òío[þò—¿¤D«ün>üðÃrà 78ïiõÖÉq:©‹ÉFå»r&qð»îß‚I?gâ[ðÎÄ·àM)8 ø]s‰mÁ¤Ÿ3±-xgb[𦔈@ü®¹Ä¶àGÒϙؼ3±-xSJD ®~×]â[ð£éçL| Þ™ø¼)%ÆK€ Gñ/ZI“&ÉE]”÷n;î&®[·N~üã‹ÞþqäÈ‘òþûï»wçÝ^½zµ\~ù墯i]ôŽF_|±¬\¹²(ýàtõÕW;¼Š:)e=ðÀrã7zzýo|Cî¼óN&yTH Nâ[8ãN| Þ™ø¼)%"b[8#Il ޙؼ)%"b[8#Il ޙؼ)%"$â[8£I| Þ™ø¼)%ÆO€GªÅoÌhqÖ¯_/?üá3w‡ÑftÐA2lØ0éÝ»·4jÔ(3¡è‘GñLzùä“Oä¸ãŽóLúú׿.ºöìÙ3sW£3fȃ>(_|ñ…Ó;Ý~î¹çäÜsÏuòÒ²ñé§ŸÊe—]–±Ñ>wîÜYÎ>ûlÙ{ï½e÷Ýw½[Ô”)S2³ûüóÏ}Þì=÷Ü#·Ýv›“ÇF½Àþð3fŒ‡CïuË-·HM ¡ÀC ßÂtâ[ðÎÄ·àM)¤ÛÂIb[ðÎĶàM)¤ÛÂIb[ðÎĶàM)$ ßÂMâ[ðÎÄ·àM)1ž*iv]]ÝÃÖùçTRç"e}Æ©N*Ê^š6mš™óÝï~W7öÞ(lùòå¢ù}ôQöiÒ¦M›Ìf†š³O'Ëœzê©¢”ìeÀ€¢·âKú’ÏYû}þùçËOúSiÒ¤IƒNÊÒG©-^¼ØÙg?ïWÇ(é˼yóä˜cŽqºy衇f&®9Û6~ÿûßËí·ßîÉÖGÞ|ó;®žI €@"ò]w‰oÁw>g­…ø–ßšø–߆= _ ß5—ؖ߬œ=ùœµ,b[~Qb[~ö €@~|×\b[~³röäsÖ²ˆmùE‰mùm؃…ò]w‰o…ÝJÝ›ÏYË!¾å×$¾å·ay:s[‹<2d#PHà‚ .Èd¿cÚ¶m+ßûÞ÷äŠ+®ÈÙ}ÕUW‰ßd#=p‡v+¯¼2óè5ûD½‹5±/s÷$;¯Ü×gŸ}Ö¹3S¹eä;¯_¿~Ò½{÷|»ËÎÿÎw¾#£FÊ{~§N2iÎ9gû¼G} ÝÔ©SåCÉ{^±;âh–Ý·{ï½Wî¸ãOö·¾õ­ÌÄ·ìÉržƒH €@*ˆoÞa'¾y=ŠI™2Ë®›ø–-Bò Û¼2¦®Ó|wó:—“"¶•£Æ9¤S€Øæwb›×£˜”)³ìº‰mÙ"¤@ ñÍ«cêZÍw7¯s9)â[9jœ“d&%yté›:d&*Üo²‹~8лÊZöÙgÏî-[¶ÈŠ+D'1Uºüò—¿ô<Ö­ÒòÜçßpà O8jݺµüèG?rWã»Ý¿Ñ1qßåhÉ’%¾Ç–š7³ìþÝ}÷Ý2vìXOögœ!×_} “Ø<“@Ø ßr‡ø–kÒPŽ ³ì:‰oÙ"¤@ Ÿ±-WÆÄušïn¹Î¥æÛJãxÒ+@lË{b[®IC9&̲ë$¶e‹FBÄ·\×j¾»å:—šC|+UŒãÓ à}TzL¨P@gÿî¸ãŽKñ› 4dÈ‚çèÎŽ;æ<¢mÙ²e ž—ÄFŽ)­Zµ*ªkÙµt’VÚ½«Qöd£³Ï>›ÉFicÐ ß à¸‹øV&ñ­2?ÎF mĶpFœØV™3±­2?ÎF mĶpFœØV™3±­2?ÎF Ä·pFøV™3ñ­2?ÎN®w8JîØÒ3Cݺuk°ävÚ)ç˜=öØ#'Ï/£Q£FžìuëÖyÒiI~øáEwuçwö»råJO:m‰Ûn»MÆçéöyç'?ûÙϺXg=ø¶]ø¶Ý‚-ü˜pä§BvÛm·{óïjÓ¦Mþ!ì9þøãC¨%¸*š7o\ae–7³É“'ˤI“|{{ÓM7‰Î^o×®ï~2@â[8ïâ[éÎÄ·ÒÍ8êˆmἈm¥;ÛJ7ã ¨ ¶…óN ¶•îLl+ÝŒ3@`»ñm»…É-â[éºÄ·ÒÍ8#}Ó×ezŒ@ù7–¶mÛ–_g% Î55̇, ËuP¡;;écæôŽM, €€ŸñÍO%ø<â[y¦Ä·òÜ8 ´ ÛÂyÛÊs&¶•çÆY¤]€ØÎ;€ØVž3±­<7ÎBâ[8ïâ[yÎÄ·òÜ8+]L8J×xÓÛ ôv,æp®ÜøÒK/• .¸ÀSÐK/½$¯¼òŠ'  \wÃyà\¹3ñ­rCJ@ -\sÃiœ+w&¶UnH ¤E€kn8#såÎÄ¶Ê )4 pÝ g´q®Ü™øV¹!%$S€ GÉWz…)ÐYê7Þxcf²ÑE]$;wöHŒ=ZV­ZåÉ# €@ÔˆoQ!Ú‡ Pª±­T1ŽGˆº±-ê#Dû@Ê ¾•£Æ9i`ÂQšF›¾"€@¢jkkå®»î’#FdúÙ¬Y3¹îºë<}^¼x±Œ3Æ“G@( ߢ<:´ @ b[9jœƒ eb[”G‡¶!€”+@|+WŽóÒ$P“¦ÎÒWÒ,pÎ9çÈÚµk\xá…2tèP#eW³Ð¸™rÈ!9ãpÄGÈqÇ'ÿûßÊ'Ÿ|R† &tòØ@â*·kuœãfF|‹Â»†6 €@˜q»N‡i“¯®¸™Ûò$ù T¸]§£0q3#¶Eá]C@ l¸]«Ãöñ«/nfÄ7¿Q$¯޼¤H¬ÀŒ3dõêÕFú·lÙ2#åV»Ð¤˜]uÕU2qâDY³fCzõÕWË /¼ z$@ ÎI¹V‡9I1#¾…ù®¡.S )×iÌJ ¶•nÆ b[éã”3b[écÏ ¤\«ÃOŠñ-Ìw uE]€GªE}„h P¡@ÇŽå’K.ñ”2wî\¹ûî»=y$@ˆ“ñ-N£E[@Š ¶£Ä1 €q ¶Åi´h+ €@±Ä·b¥8. L8JÃ(ÓGH½ÀYg%½zõò8üñ”éÓ§{òH € 'â[œF‹¶"€#@l+F‰c@â$@l‹ÓhÑV@bˆoÅJq\Òx¤ZÒG˜þ!°M`Ò¤IÆ,š4ib¬ìjœ$3£ë¯¿^FŒ!uuuÖ­[·ŠÞöñ™gž‘šÂA5ßkÔå $éZ]¾Big&ÉŒøVÚØs4ÄC I×é°Ä“dFl ë]C= ¦@’®Óa¹%ÉŒØÖ»†z@ l$]«Ã²K’ñ-¬w õD]€¿0G}„h ÔÖÖTRzŠIšYïÞ½Eg\?úè£Î ~øá‡ò‡?üA.¸à' @ NI»V‡aŸ43â[ïê@0’vÃ.ifĶ0Þ5Ôa $í:†]Ò̈ma¼k¨ÂHÚµ: ¿¤™ßÂx×PGÔx¤ZÔGˆö!€ \zé¥Ò¾}{O‰cÇŽ•Ù³g{òH € 'â[œF‹¶"€#@l+F‰c@â$@l‹ÓhÑV@bˆoÅJq\R˜p”Ô‘¥_ €€@‹-2QsïÚ¸q£\}õÕΣÖÜûØF@ Ä·8ŒmD(E€ØVŠÇ"€ÄA€Ø‡Q¢ €¥ ßJãø¤ 0á(i#J@Ž?þx>stream xœ½}]¯,Çqä_™Gùáw}W?ìð„5d¬×$°‚Ÿ$™kÙÔB¢ cýë7³2¢:kæèòòv’ ˆ™3SSÓ]1•‘•ù§G¨ù-§ð8c{ùç-äǧ3ôÇŸÿøß?>Âã»ÇŸÇ[Ëg+õqÈ¿ŸäQYÞøÛïÇBîñbÌúæ~ü/ù÷ÖÛ¿ä­>b/x”ǧxD¾õÏ=仜_=âãïdÇUÿiÿü¢‘ÿ$oÓâg`šß;ÿöøf|ÅŸä|Kú^ù_ýò×ÿó¾ùëßþß?ÿÞÆøî½¹Öúä2ôßbŠïÌõ‡ï~ÿý÷:À@¡ü¢¿_õcÞå¢ÉNoþ÷C~QÎǧöV‚\ÞþäA”o¯‚LHfµëÃú–äaéoý”‡ñxËúN™gÒ‡ù­ÈÃÞð×þVåá)‹£ÉÃßš>ìúyXõUŸBhò%åqò@<ôµ¹Œ)yÏ¡Ÿ›Ï1«úÛ¡ŸTÒ˜VAšþð•6æ¥Ïú;Pؘ®¢S?¬–1³äÃt¼zŽ©ùœ ãÉmlãñ)«N7›\‘û¢óé2}˜d)éÃjÓ“ÇMç~6=¹.ãgèÌ6½*Wo<î6=™VÐÇáˆ6?yA=ÇÕ&(÷íÈúD8l†U¾Ù¸!ÛõÎŽ[ºÍQÖNªãV¥1Ió/ˆÍf)/ˆã‰lšr5ÆvRÁ<å²!ÒimÇÛ9¦‘&Ú웆Ü0QY'ã‰l¢‚—³'ŠMT®iµWœ6ÑVtÕé"Êöú2>BF:ðú4®…€ pÄqµd}iÊúøYʼno߬g›¦¼"Ù+ºMSñ9¾ê1ÍŠWœÓT¤Œµ|ÌiŽoö B8ÅÈ?þêñ›p<êãŸäÁï$¦úƒüáï¿{A>¦=ƒO 3V†¡/#@ŸÜ/ôÕ±X/ôÅ6Ñ'—`¬ ¯c‰}úª1|r…ZtØ;ä¥áÂÞYìvzgX'+|̉À“‹9®;€'¯îÕáî›ß/ÜÉŸÇ­'ìŽÓ=`'àw„°“_ö±t;AS)va|è;ù&1xØÉ¶¼ ;Ù#l©va`ÇÁN¦”³‡¾¥8ØÉ;{ñ°“wôêa'6~&ì„oŒŸÜ ;¹ßµyØEYñÙÃNvÚÐ=ìN”°“=ØÉÖÔû„ 0~'ìx›'ìäÛGvsÂîÀOö„¾¥zØÉ°Iv:Íâa'Ó«mÂN¿ûÃbvý‘o Èû*ÄÉ*zEœLñLâdÝ6‡¸‚_Cœ,´Ö.Äé?¹€ÜXñœ޶.Ðy>ä uòÃ6®gP'—'¸ OVðØ@¸ßÉ¢?VÜïd1މv)Ùö1÷»jpŸû†ý.u›ÉÜï‚ý x9ÛÏÃÜïäqY÷»±}x²äÆì <™¦í žp û9&ðJ'Î<Ù¡måxB Æ–|íwoö»`áÆµß!h¸ö;b„À“Ô°îw²ø‚ž‚!yàÉ=—b¯â»ûý®µe¿«Œ`¿;lLàéÎÞ=ðjãXç4$®ý®ãs¿kܹßEìªs¿K¶®ý®Ú¼¯ý®Ùõ¼ö»¼¯DZ‘mlEnÏÀÙ_CYÅ ضİá_‡m@W³hư…°`*,Y³{mˆ:,ž‹[¦h¿ÆÀR³]H’÷ùýËFŠbHÃP3è‚ä²Ãm™@O²oì4ûúDV0p±\ù ¯3Ü'b°ê€|+ E>,;¬4À‘HÊãp¯%@Fšm²Dˆ~ß iÝ•²…Ý„F³ë>€íÊÑŠŒHÈ£DD˜8$L`(˜ Ð€W!Ú”aDÁÀXåolÓ9F¸÷Ÿrý¿0æK¥!/W?./ÇqÙ´úÕœ[[3s_?–<)¿lç{i´ú•CÙøZ{7Ù÷µCr–/‰´»süÌ€?š´ÈÕ’ŸÏÌéoRΛ2s/ËèV2­°÷öºÄßn®ñ÷’s÷F|/;÷õ#¾\¿O÷‡{/;woÈw³s~È_è²YÉ×Ü™œûnì€U6´&(„ñ×~ø[òfÉR7š9keIɳ²µ#‰ydÎ báš9³·ê/Ø™³AÖ›í`è4§§”H§çA¹êȆÿéÄ‹5DîÊ*dJe„<¶yë'ƒJ¤hd`‡<¨ë Á|iy}Ó.#'&Áþa)ù¦– “­\⌙Ž,Qé¡Ãɾ?vî6ÈßÔi—/»ÿ)Z$4Bšm‹•`¨èxŒˆúA’QD­Z_š…D½#yf¤=飄¥0K½zç,6r¦÷A »ÂôRµWXKmî–³ _b#Kj%Äèµh¯h'¤ž-ufé8 ‘Î1è‰4€\¾qW”(Œ1„<cܹÛ}‘',ÆQ6”-h·ï"«cÜ ,AÙ»7 ñ@Gívwä.X°%»=šJÑukv™vƒôSÆíåbAÆ&N»EàŽïr&»G2 ±Îf7IˆòaÌ8Ø]jȘ~žÆ]m‚PþWË3ag¸`¦ F°À0a[ #R€¡¼—„Coºàèt0Î<Ö-`(09 3Ê=Y!`P¢ãA AyñQ. ½7€„pPŽHø“}ðô'1ôU$1¾‚@Ø“e5– W­yrù°¼Š ÅÀÝ`'ìu-à:t3 ÌUf§9yl©9 NÛmàøÄ[C&†p“%{x´ÉŠ l TXcv”PÓL@vHk8 ÐdízÚ&˜ÉcðC™¼Þ2YC®–kãÆ_Ó,xqk$N˜&w£Ã—<œlO©©¨ÉÑq KjrœÌႚÈ[ìp€ÔD¨mbævP“ÀH‡Ô$t„V¤&ùuR¹{vöMjy¶BjÉHM"ŽV'5±ù8jqž0©I,yHMd•Øi+©I<ÁÌHMä ;\!5‘'6é'’š$žR’š¤ˆÔDkCº§&ºˆ¯ï^jâ`z|ÞyNàup*Ã]ˆ¼ZvãqTÜÉ_=îäž‚Üw¡®ùjïez ¢™è¨39€”¸“¿F Üé‹Ã] öãÜé‹]R@þzæ w²ú¢Ã¬½1+À.2ÖVÔÅ„s€.&;¿!æb"1ÈE–ŽqŠèA¾ˆ7yyT¢×>òÈhÓ×g¶g¬E&µˆÜ‘Y’ éë‹Ã™òÙâ`6ç”EpG‚LWOÿ#Ó#€˜&¢CX䡦›ÃW!¼ôýÉ¡+âhx19ÃùñÄ„²…Lè`»ˆÉy¦ÝÄD6¥ö¶—˜p–Ûˆ çx‡˜t%7¼/ &u1yYF·¨„Äeãp¯küNL=FÛÊLtĽÌäõÞã6Þ^n2ƼONº„8Q6»Ý§(ç 9ù÷?o9E9u·()Énü%å+J a%èID^ô¹^„I²§²yГÓöV„IÅh“dƒ´S “F6ä “´ ²]a’ìv£‚ƒa’êÕÅIŒÂ(±‡(Zè(Êã]¬¤g6Ùeq5šUirÎ@i¨%-F¥t$ÙNOåréKb£EîРÊ]S¥8GAÅB“!%è³Òe<(u×b eãý({/$62ŠFc§—ˆÈ/jðuï“9 ð]CAb•ï*µª+}ŸµïZÕg\Vý^ÀYþ^‘åfý{MÆ*G|åA*à+OzP_„£^éì~¬¾"¯Ï"øÊc TÁWjFX€‹¡¾!e!¼VÐäbMIXV†S²R2ƒSEº;BøD) h°xÔcµElRJH¤bµ¿Rzl©„ŠG@ŠÌ’µ0V •‘@¤ò )”㩌€*HuRg €T=(²Â-) HTRòâ#\*2HU¦T©±ª)¹kVûHÉÜ×RµãˆA!Õ q›J>R³¸âÁ.!%ß5z…±¬æE`,¡òj RçÕ€Tê”sR=“pDN®yHÉÆaø¦%5À”ÂEfÕ)Û¦äîàpÄ0¥úz©µ‡pÈu(íøpÓýŒ-ü@ÆJµï‹~*Ëäö¸¾l’³\¾öÛ—ÏøÅ¾/YS ï_fýòrioY¿ìíe•ßtj)Zvñ0k‘|ÜÅ]ˆÂ7»üpïðånÜ7~y¹„÷‡|¹ˆ÷‡|¹Œ_mO“ϰ8ǼÄ4ÂèuКÎãžÊ¯OÕ¿hW£»¤<§RµÞnØÕÈ\¢7t÷÷ìj~·Ó®¦TáŒÇ‹_ƒ ~1D·€Q•éNÀ/¼±,0°nùÖ©ßï–øú}ô~Ĥaч¥ÓJÊé›!̈tèY£yjOÅôxÀŽú÷î=kÈ\¨á—cÓá@{\¥RÃ_ðyÔðSOÏ”–M Ÿ'FVß–éYÓfõâc¯EVM ŠÝèYÓÁf¦gMyR$kÞ×G’ÃfÑðgžPîr›€O=(¼1q|Ç¢†¿ž+IÓ·œž¥…).˜ž5 ¥†_WZqQå †êr¨á¯0ý˜þóÙ³†µÔð×´Æ–ÃZ§¸àr˜ï4]Ž \]x©óˆ«gÍadžãY£õGÌÏLЉÀA£-Ú~=Y+•üÇ €²Fç%üyä€?•ù¤ ~²$ ¯âˆNÁWq€C©ÿ‡'Ï1NgYCÃO^<è pWQ.Ø5# ®¡L ÓûßcCe¡A®Áˆk&³ÞΗ)û/8¯5´5Êe¶÷b­‘ÈPúÏ*H mÊÂ4]…ùÂY£$0ãט¤­Ò ¤­=‘6jiÐèWck´}!iáñ¥¤ÏçAZ›µ£ƒdEo!KÏNÒÆ$ I[C!åEÚºO„td£ˆ«ÆCh&B:¥7•“;«'mðÀÚnH£p:Ïð§yò:Ön¢« í–ªK(žu±€R›—ÑÕ’›Ãò{t`;–Ýì,†Å±™(û››Ùw6lf1Ú‚äf1Mnfš!ö›Y‚#Ì4¤9W6‰¼•F˜Õ¢ØÌÒ÷ÛÌ´Ê1ºÍ,Á“‚›Y‚ Ž›™ž/{¶ÌbenfZ9ÒýfÆsܹ™e–p3˘âfV0)nf…¥—ÜÌ2k|¹™eøÍͬ4ZC3((‹[®O†4<»ž›™zÝy°éÇ&Ÿ"c´¹™É$NŸ$ÑÀéÕ+‹”¬û=àf¦šÄâ7³Òžœ  ¯çÜ̪¸™Q.073•P^Œ.x_…4Bz6¤‰¶ œÛ7¹iÑ’N¿äDZ€z£°c–6Œdž!ÄÀì7Ä ·?Ö1¥Ùãww솩`yoÔ±Ú;Ù…áeKÄXF¨Ç&ˆ¬l{“­Ö Ã"U ç€¾Ú°ƒ(È©x4pÃŒ1@Ãða.ŒYDÚÏ\ü¨,3+¯PÁaÇÜŽðZÀ„>O rz€Ï[Š2Àã@åÁÁR¡Çžä-Ò*4¡ ‹cµGãA P~¦âé?8`þ~Ï …„­@¨ÈŸ¶ó°qÚgGcö£yJÞ3ÖxÊÞ÷£y'Áw×ëeãœåk†ïî$?7â;ÒühÎp»);4ŸZ–ìíu¡ßµy/mxoÄ÷ò†7ÑøNâðž‰ÌKâðæpï%ï ùnâðÞï&RÑ7œs>2oøÝã”Ð$kžð-IĨûÝ^#Íé•W H¯@­‚”ðÆÆVÙ©<5 öª(?•mÔ¬sP~zИõ§1{djJ!P,—ÉR-—à^C¹\F …à,Ñd!¸^FW†ªAlô…àú¸>®Bð‚óÎ馃Ç馃×;7€CB\]}!x/ Á+ľÓM§®’U­E!¸=²ŠÍé¦Ã¬ßtÓ!Uwn:–úšn:ñI²:«œY.á–iܦ›Ž3¤›Î¨m`x¥ušé0V›f:']¦i¦s¡ ¼ÒL™Uàþä—™ÎÁ•…*ðzˆUà2€ËL'0ôcx@Á«Àk}ªo­¨Y^X™Á*ðÄbšé ’áÍtŠ.”ž‘3“ëÑp`"9î}¢1¤!Q"ð^.$ªv7_HŒ}Vc ­øa) à0ÊœZñl (,àŠ¡ÜÀî Á¹œ¨G­ÍtpÛÀZÜò¬%Ñ ~ êG OÓŠ®¼!C ìéšÐkP^y²2z¼€× ò}þ-† …ü„/¾P3›æ@'Ÿ‹Ç†9µtÊr=Ò<'1ýVhAÝlfKx£½à¦e8^³Ú˜ Ú4æÁFù=±¦5^³Ú`bN¤éø¾œ5âL°“½fµU:OÊúÔ¤Èz\ëÀÕ½ÜûUuZŸa¤“¿7oVÕÃê|{ßLçÃY?d 1ÒÁ¶±,úÔl¤DtªÙ9$f¹eq’·Xýt~^–õ²˜n[êìíu¡ß5ÀÙ˲tĽ,k q+Ëz¹#÷u6³,r3ËÒ!ï³,úþ|,ÍÒœé+ÏÚéT´hóxùá¬RÛÎNŒîšs,Í ]ˆîTzÖ®èNæ+ºÓž/ñŠî:tmˆî$BJ.ºÊf” R[”‹O©-Ž¼È°ŽlgóNjÛ«cXr-ã"µEy>–ðæì–öNð~¥1/Î$DÅêV„Ÿ VD½Á”Ú +uÔq†%!—¥ɰҬšÃJõM¡íÁ“' moÓlgÔ†•è22…¶ÌI“aiÀ<Å’è½.+Ô#bežébi޽zŠ•ÑFfR¬y¬6…¶”ìM¡-*™'ÅšcL¡-H± Š.¡m¤KY‹)]È힪ÖÔ6áRy þ¹^B"¸KÔx+ì…@<6e)@—g³Ü^•æ —ãŠ¸ìz4ÓGoWšÑÅ‚pÓ3Yï¬ËÉžËÄZfµ –˜»Òä:Eï ¤_Ö»¥~(ö}-¯”Q­C鵋cý×±i„eVÝ`ó ø²UuÁ+ã¬pŸ+Ї3,~ÈR¤ƒmcX4ÜÙH‡h¹³qHÎrÃâ$o1,}ÃÚé ´ Û˜}ý®ô»N>{)–ޏ—b 8n¥X¯·dƒ3Ðf’5ÆÜ̲Ƙ÷iŒ>˜fi­ýÍÚëh4hVz‡f¹$zœÑ»Ñ,š^ 1DYBϳ ‚dKÏÙ–æóØhžgQáK²Uëê·r•˜Ïó¬ŽO²¥eq`U–Ó“-Ë›®Œ¶²««m]gsY¯ó,¬Ût5Òƒåx¼x‹A=²u² ÍÈV!7%Ùʉ²ö«#[©ÏRuX·óBb†p”ÇY(Rcoˆ0•"#د8Ýš½!ªë 1e#8Î:¡ ¬‰÷ÍYèðÃ㬩 g¡Z˜ÇY(|úL€Ùâ\³Ž¥+KC½.³`žàÉÏ”•Ëñ@ë\»Cô@…±¡®ÓÄ”Zè‚GÌÉãÓ›Ÿi¥[g½<ÐBå(ñÖ§ÈØàv&Ð' í„½î<Ðb‰°&¿³F@íì³R½¬ Tg=¯=XÎÊ~ņ²3­“·ÀØ éú„ØATbg£'Zð­ÞèlôáRãù)Ž$ÝôgÙ'7†iÐNm0lƒv‰Yî“s’·äÆ07ú2µñV£”+¿w«îùí“Ûp[EÇcȽ²cƒäVáñëmÙ`o´Yz<ÆÜ¬=cÞÓ†é£i—Ê\ÂíÚiËT´bJH• ö`$cÁÞ(bA„#VðWÚÏ÷«ë°†~Ñé‚#Â=2 ¸ £RÇ!'£*Ð?ªÚC ]œŠJV`",à ®©·†p«,ñׂõHBÝJ|’~tô%†ò£×Å›éD³+5’éð™‚öƒ‘Ä'\3¡þÐ^N•(ÿ³º!@NúP€œ¬ ‚䤲ޒ©#¯=‰‡@ Þcȯñ‚)ùœ²tð¨›Z (e¢ñv/MÔîmQÿŽæ#¸ƒ&„ ã¦`Jf–Þq6oˆ'µÀLÉ$Fµ"õRÚSÀ+µFXxÏ.+ÔKÍîÔKEªF¨—Šì€F¡ˆ\¤²è¥dy–µ÷&ñïD™û/ú{˜nÒ®):ñ¯v/©ÊBZÔŠ=àˆ²°8 EPu L éU*óÏ (KeôÊ2~h×TiU.éeޤ@YáQò´kŠÞ®é°å ”ÄàÝzô€ŸvMp¦]SŸ}öðe½Ì§];­\vM¦¨¦Ð*ál‰vM¬¤]J+Æ*…Lt@c{ l¦0­^m_5óØ8Q-CbCWe{ €kÌÒ­­vMªÅ¾Ðf?p8 xL46ԡ슧Zc 욤LhÖ û§ô*3QQ§š»8DQ7¾Sù;±¤tþEû ‚ÞQ{Öh`ŠýálËÊ3=-«9éo‚g·,lDܲ"΂ LjpLåoÆ &˜à¨0•cz.$äiSAŠBEf Ltƒ˜ê¹Ø VHȦ–Q[k­¡úy‰o¤>ÍÄüŘ„ÜR¦ŽŒ#ÁÔ½)¤o¬fG©jæf`BN!ý¨c)LK`3­LòaÕË{;óMSŸa L'›,L'=Ø&mlå½ÏN6½˜ÎºÚ<ÞÜ=˜NxÍLýJ & ›÷>;éE 0•B Èæ L'=¦³Ð2zÔ¨ló>ëò÷ö>ÓÏØ’@±jÉ{Æ¢«Ø2¹=Þg‡ä,—¯½Åûìs#~±÷YT¡ÌÏé}örioyŸííe•ßtkšìÜf³¬†¸ÑdùåâÝ7{ùƆ|þÎ_í+5åüyjÿÅËÇ‹˜l¾Y0ϰØ8ÿd1=kœ5z|ÏGì·;}ĺ;†g7ˆÑZæ ¾ËÐw嘧´F3±õ’ÊØÊé¼B>G'±Œ"Æéç,j¡“ÍÀ†ùJ†ìŒæ+§IÓI §4_Ñß…aºã[³™0¥ª³4 êi¾RQGßý¿7_i CÍ|¥ÅÙ#sL¯!­Aó•I!ÍWhñJó•F/-š¯4öÌ£ùŠŠ¥’‹Êô-yqÓƒðÅI¬ã‚Ò|¥ÍöŠÈ%4wJ;¦Ù5:Ó'Ú’Kèpñ˜¹„éË\BÇÛÌ%¨´(ºMŸ¨K.¡ÓÑeäæë™KèlpÄdBgO&Ô͹@M_qúHMÇX'ô‰²$:…|L&txxÍdB‡öÇ8‰u¥åÅIŒ9ŽNïò⼟S^’ )A^þšOþ—”–™º”³L&œ0>¥9¿tÉ}ƒ=<œ‡_BO‡sNb 0ìôÄØ¡.uC<íÔ¡«æ2úÑätA– q<{àX% ¼%tÜXK´©M¡·íK´ÿ¡¡úlR‹RR6Òäqt–}úÐãŒ5º„™~œÏØ¥NŽt²Ä­g c I,B,Q¤ „%þ.ÓÂ¥Sæ{Ò‡}TQ!L¡áû¸tðæ°•X} h¥ ÜY‰6´rA£ âJY·Ïѱö™¨b¦j»•XÏÊs_œÔKòù„6ý¨•œ2LìiÅ~!¹§ÑírîiXXsOKöSÅ=-ãêpO‹è†l]*îi ­~¹§eäm¹§åØGì)ývϹè)ÿöõƒÑ¡ëdÙ]‹®Cr–¯Ù²»“ü܈_ì#ö£ù·í>bûRfjà´o´×…~×£ë½ÜÍßÉÁ}ýˆ/×゚ֻ9¸›C¾—ƒûIªXtíLÁ©V< Ãhr6þøÛÿ³'9' ‘ëK1 œ€³KEgRÐ>ëg9Í(š¤è  ƤR•tåRúâ´ªZc?¢ êô&ž^ú§”V-Ì®g,–/¾=sEA/… j` ééµOã§ä]¹ØÅˆB‰³[¡¡Á@›B†Vk ‘ÐòšñF.’2tvZšñFÊZ£ý7d 'ƒ”1LK Ê:½‡)cÐè˜qÒ¸'t‹f\SW‹+—~»¥9³æ¦–æÌ,oÊä-«f¼GDé”1tÖøPÆÀTÔ”1tVgSÆÀ¶JSÆÐ-Á!c1¬&‚2†s¦)cè‘81ÈæyÎkÇÒœ¹C=3e òDÿ¨i£Àçø F {¦q{Ã1í‹õÖÇͰxµ¶\ÑJï)‡@L0—¦h²iêò"Ï0f¿t £ÈŸ:ý©c¨ µ…³å*H§ùKê’­! ¯Âj˜¶\m¦§‡ŽŠ@¯âëSÇžm¹ìP|ØråU=¤¬Õ‹Æõ±×5Ö¶PÅ@JC„Ó–«°5l¹(J§Šëž*¶¾ -@[§(œ*†J›.ƒÚÌ$Ó–‹¢oÚr—ø°åbj*Ú”QÅ@UU ™5lP1 Ý²S1œ^Å0_OCas×¼¬]Ù²¶\NZø![x†¶´Ððj#àãÕÎ!1Ë}¤…“¼EZhËõó’–—ÅtÛ–kßh¯ ý®åÕ^Ò2FÜJZ^®ß}{ªÍ¤e y›´Ðñj3k‰ù•µì4¸êeß=ÅI§^—ÙJex¼Ptáu³ÝaRM³Óü­¢“{ªÞÀÉ=µIi¼Â¤3²žÒŠê ßéoUæÉ‡ù[Áwú[Åy¨hþV¨zþVÑNº§¿U‚Ÿý­ºÅ{Óß ž:Óß*ÍNV‹¯¨éoUVѵ6Êõ¢ky|žŽ«$¶è¥¿•/L+þyú[¡nýò·¢ìô·Š¨t%WQûÅß*‡«q³H$Ë/+ÖO«ÂhŠþVtUþVl6ý­Ø«vú[ÑFÊù[>„šMÞ.«D®Rhî:ý­2úhL+oM+¶c"W)¤Hä*ú„w8U®¢M€üèñ–¿U×8íEr éf¤ €i¨âiå ;aC 4Ì@,À„;…!_Ø ‚ #DÌàT–ĉ?ñ÷”*€²èÓ©yð¡2°Áq½ˆZ O»Ó;c9-àvzk]u)yèQ' ?… ttþ˜cŸvBNþØ=ONW=OQ9“Ç[‚ý-áákL´i-»ƒéµOä1ÀšÞo%—XI ¤%6'ÐR‚ùÍ­2Ôß4·š-œú‹õì@–ÊšÐSøî 6[@ÒÜŠÝÉ0-ñæVZràÕÖ‰@×4Ǹ½/s+Gí0·úpžÂÙB-t°m<…¶QI}£6ÉYîã)œä-žBs«/ã);Í­ö1‹á(´o¸×•~×8j/Q#n%*¯pƒÅÓfªbcÞæ*´Ú}¢æÂUöºD)Wiá5©‹ž‰èµ™°·®'…É9ëzÒfÕ‘Z¬Æ +80˜ÁR\ìxõ ކKEŒ—pºÃ€iEÒ' v” ™äuÁ‚êF¿PÝè½%oÁQ)KI‹O<Ÿþx¥†Å©FOMObs”¥"¹?›žd+wõMO>YõW}:`‘‰>µ=aYâl{ÒŸH ís®–puµ¤¥1."iiOÔ¨ YXµŸ$-zU=iiTξ'h‡=I‹¦©«'-­"/MÒÒ +kAZÚ‘´4„ÌWß“Æ ô‰bçJ’y¢ø¦ ú„…q$-­ó‰6OÁ×P=£ eÊë°¨½ËŸ±c²q÷YÒ Ò‚`¯ä)j%¡Á–‘ˆ2œ>maÛ…C¹e§c-ù|ž®¤…µdøƒŒï:]¡`œ®‹%oC1%]¢`op®dçÒ¦g |,)¤KNz¯¦'ylTCàÇÒmHëšî: N »s–Ã&ªâDò²‰ZŒ°Ï tr'dˆ¸¯bäá—ÇC?NÞÐ}’àdÕ!}¢¨ Ú挈¶ƒ‰¢í`Á%ÑÃô@þ†]щ¶˜Öö'*&IžÀè[ ÓD[hgm¡?¡M.QXR±±^hÓNXK—¡P|—¡-¦Q®ÑœŸâÈÇM‡š}:MØ1íUÂiç˜å>&'yK§ Ó¨/“in5ÚHeò{·êžiÔ>­æn¯Zӆܪ×|½†œ“6+6mÌÛ’Mº1í>yÑ ¬lf§ùÒHû†ê#¨¡=±V HO¨)‚” Þ’ž°_ùeeᥔÚœh7|#xôb¢ÙBƒe~ÍÂIN5(Nz^Ü—äòŒX%òZKáä&çR$¯JvV'ÄžÔš°—¤ÖäÀ^Ü£ïT¯49ofÁ|H“»L‡#¯4 …v0Pš¨‹© ¼P9˜ÿ¤Ò$²…Jmq²(MØ+Â|˜"û­QgËSãúÈ@‰:“ˆ^ ³’>ј‰:“4c 3ITlRg’p5«êý,¨3™â²Ñ$vV¤Î$6NIf}ÿl\Ïr|êLòì߈ûL©$u&9¬¦1ã¨iÑ™äiÙÌÆõÍwíÞK[&èd…ö :ø¦ttU–g–‡Ü ½ ©Ÿ,è99-Ïjs +ö “;–œ“Ú4W€®@Ë ÐÉ4“÷ ‹rYI´¢Ë5º—[’ʺ–M* Ð5ä.˳âä)ŒgXž‹SÇÝà:ZÑò¬Ú7¥åYX{ÞÓXuZžuB –g<™Ô®Çt<ë³Wãct§]ÏÇO³7R¦•´9j¤4™Š2´ƒÇ!ÚAôhòû”¼)Ó8rîhk†gø1¼ ÏØ’‡@;Eí ¸@;p*=˜@!ÐäŠYÎe:ž¥'dzПD-t›§LPŸÂ6•²…aÈ`g:÷ŒE¿–uv{levŽÉy._|‹¯ÌçFüb_™üSÅÜЦ=7´ÜV{ªQ[ý†–‘›šZ¡nZ9x~ M>5/ZeøÜдçðb RÐélnhZ²âÌA,´X¬àr²•Ï4âæ†V¦jzÁ̲ lh¨ç†¦O,Y–õâÜÐèªt¥3‰SnhÌÀùtf÷ÈÓWäà74:‚Ý·Í º>çu°ÍaÑ“ù¡„ë˜nزèÝ®Ãr@€ä;ms¬-×ÀV´äïðͱæÇôÍI—oN´pÒ,•fhB×òi›CÅx™.>†"xèLÛœà”¦TõxÀ¶9ݵÓ6ÇúÐÀç ˆ9Voøw{ºæd•À¾â',Å0à'ë2Íñ^‰Ç’ìg4=s‚ï·O0zæ 9msÂbŽˆ3ƒi›3“ûl0]sÐO@XÝ£X>a à÷èïÍõŸ†išc/¶µ¬ŽÕ‡½vŸg²‹lšóœ^¼çüñ”_¼ïšó^.ð®#ÍÎ19Ï×làÝY~nÄ/öÍùl~ñY~*ס÷{ÉÎ/¾®½Û&;‡{wMqÞK1Þñ5Çx¾ï$ïÙâ¼&oŽ÷^’ñîï$ï ùn’ñ'ժà èsŒßi„ðÔßø¿öz…Ñòw9v¿bçìV.{ÙTZ½ìQWs r’DXÒ(ÇEk«1ìR½®e³#ÂCõºDÙ¹’hèѹß1 ?2íìJg‡V²>œâÕÓèXz¬Ž,3'Ñ×W§ú­{ÇßY½^ÙËY'üò³z½Â7rV¯£übV¯C0;«×;­ErŠ‹àvöôµë,aÖ®7‘ÏÇýUQ»^I=XI«ßÁ{•Œl[DPx¢ þð*À1í¥v6äWc8Ó\=ŽiN:k×§}"k×ðCVÓV”þ_=ŽO¨ggc¦ifíú±ú–\oq=ŽÓRM;_1k×|[×ã¸û¬Úãx¢1ëç'4F¶x£ŽÄW¯§À,ϸõ9±åÓ2͵OX™,_? ²E“ã¾¨Þ ëÕÑI / µ«U½@Xa• j§êvA=}X¾ý.Ø Na“cøý°|}f€¾6Æòuä{ô€ô:ä©Kº3êøÝ¸ëœv½¶Y»N‘)k×)‡ 9¥ä¬]?ðz ®³}K×’‹,]?€–®Ó”¥ëqÛ™˜ 4¬±¢Íµ862ÆÇiídï-¶8fs*ÀìdUÍØiæ@¬Í¢9,ا9Ðtï…9âÑ¢äiTÞ®Íw‡7ÐÇ“³ù)[ø”޶œÑwg'‘¢óÎÖ11Ï}䌳¼EÎèô5ä,ý,äìuíÝ6Ú8Ü;ȸkþ³—œÙˆ;ÉÙ€ïVrözOîÛ m&g6äVr¦CÞ'g4=úPv6êÀ_èÙN$˯/mUàé…ŬĄ ÒÉ>#.¡Õ"†2n„­-¾­½Xá‰Ä,mpJ¤6χMKõÞôA‚+iY8ì³HËôPÛÓ²€#:Ò²á+iYD!=iYDsŽéƒ„zéƒÄ#?вga¾•›ÇUÛHoÌéƒÔÁỦ‡½¤e™~÷Ó‰J¦R@È5}Êj ©¯8ÏÖL{ÕéƒD/%çƒdöKÓ ìøòAâ¹3i™6ù\}ø Ҳ¢Ò2=Kž–ñ\Ñû åÕ‰9~烄–—Jñ郄»—k.$Ê£§Ž/$T‘ R§²á…°ù‚2•ªfŸÌ“?¸'ûË’©èÓdÄ);ð×ì«~pú,<Ÿà362±‡þ„ž]4"ŽU^šÅ†;;%ì²Ý#¢ 'èÊS*zÚ$Ãäˆ.Ɇ®Û›É<:V¸±ÜœHãÓ) Æ‰Haec12ß $²'MÉ<Î"¹3¹9v^ ”EZ›dˆ±Èg€X¤¥+-| `S¼ |Ír Àk–W]³VàŠ'Ë3 [×ãB:OÀiŠ^`Uû´@Šlf°Jèi²ÏéãéØü”- JGÛFÇh/´“:Ñ`h瘜ç>:ÆYÞ¢c´Aúq:VŸéØðûx:öºöî{&mïhÜõ8ÚËÇlÄ|làw+{ç¦l0MÚÌÈ0æVJ6ƼÏÉhîôÁœ,¯'ÏÉöš=Õ©®»ˆPâeM›ó,ØNòe±˜étÂÄ™Ìy„ð<0 ¨¶æYD{˜%”(óÀ,ÇÕ3•Y5oF¨ÙBÎi‰zÇy`†b8Ƈ:Ýi÷TÑé’vOˆëæÙaê<0C׈y`VÖnE‹óÀ Báy`†Fw`VëÌ8VB¨hî'Žwæ‘YCøì§qÐÝ ÜLx0º`Òî)LÅô´{ >d†P 7kÌkÚ=¡a›·{²A§ÝSÆÄœÝS_¸™¾¥yn¦Íù­’Z hZ¹úóÑîéôFÿ£àzdÆr]g÷dÅùÓ0Ý“ŸÍ#³Ê’_™5cב2h÷ÆéóK‚½dáÝx4c VLÂ'¶ô{Â9 OÌЃP,iVÏÃ'x8ˆzêuÁ°Aî ²ù0@¨Í;Ý¡µ.Ð~A°Ãщ<Ê‚À†ÔØ›e €¿NÑŠÁÐGS%€ï„™+°wž³Á߸§ªI@ï„‹-‘'󪞧éO™ .ˆ¼i ä'~ ‰^J}}Œ#]7ÍköÉ©a«´Uú c¥­cbžûäÔœå-95ìŸ~\M]ŸÕÔåç©v|gñÝ÷ŠÚ9Þ;à¸mí´WT!wʪ Ã[…Õïܘ nQ›¥Õs«¶zŒy_\MW«¦q}˜\­4n§ËUÒ¤—ëÔ¥Sä¼|¥‚g˜NL~¯šS> ˆp  Gª‘¨X´PÉÙ\ÑÊg(“ø)Y±•õÑB‘c†2ŒŠf;Û*k+iý;˜ú0ÒØ©k˜7õa¥#ˆ¥>L^Ñ}LakIêà /õaêëe2úD¾|C÷Ò¶ }š zAº¬}q6ú\Óu}ÈJG˜Ì±ÒQ¿·²¬z¡OöÕdîp͆–• ¾†â`šÌÁ ØÓ‚Îo  òɉ3O¸rwÚ¾Ïù]ÁˆPÇz¿é1 Äæ1w,²Ì?ÄÜgjbî8WÌ)Ô¼éÕ@Ö‚¹£=aî8ŸT™ÝD‰9ùU™FZf±YJU$Xˆ9á(+æä-Çâ|Ø·ƒ˜‹Ì¸szì¶XÌ…¼j õcÓb1;I˜ÓL•`pö=‰9¶‹™˜Ó䛸ëA¥#0¹-s6×—óšÝLÌ ¥;“PíþÚ„ÿR­'4£§oRûÇ—Ý÷o~ý?¾Á. º§œì‹©žÏúÊÏ„#&Ÿë<žC…¿8C]tN/3üåüá_þý‡ÿx|óͯãÜÏ·þÆèÌ5›ÐCøÌÔ?J2^¦ÿßÿñïÿáט·}â“Ä×L¶´§Í?i²M×ê;SýÛùî÷tS½/±·ÙžŠËöfûÿ5hkƒ endstream endobj 5 0 obj <> endobj 9 0 obj <> endobj 11 0 obj <>stream xœeAkÂ@…ÿÊÜTJÝM¢F$ ¦©¥XC#íALäèIøt•'ZÝÚ÷ô厘Yã¼.ãþ¯$½oÿ]æ^×à³.›DýöˆkÛ¼­dC7tù$§•Ä£l©Í ßµYšFÿÍEûá:fæ7|gí9™¦‹Ï8&ÉoúgF endstream endobj 12 0 obj <>/Length 73/Root 9 0 R /Info 1 0 R /ID[<37CD6D3F42D79FBFDE6B69B16F03F13A>]>>stream xœcbÿÿ™˜€7##Ó ÍÆÀ¦ßi`bd`°þ¡Š00BÅ4P½Í†¿ ù# , ¾-ÃF(‡iNll    yÌfÒÄ pHYsœœ&Í:4@IDATxìÝ ¼LåÿÀñ¯-®}ß#Y²“¥P’-II"…´ˆˆP¿-%-’(IQJüê•K‹¤µd_³${öeþÏ÷Ô3s玹÷ι3çÞÏózMs–ç<ç9ï#™óï“N’Q<ÏsxÇd4Á¡ € € € € € € € € àâéÝÓWzŠ € € € € € € € €Ñ à(Úw€ó#€ € € € € € € € à"Ž\t³è* € € € € € € € €Ñ à(Úw€ó#€ € € € € € € € à"Ž\t³è* € € € € € € € €Ñ à(Úw€ó#€ € € € € € € € à"Ž\t³è* € € € € € € € €Ñ à(Úw€ó#€ € € € € € € € à"Ž\t³è* € € € € € € € €Ñ à(Úw€ó#€ € € € € € € € à"Ž\t³è* € € € € € € € €Ñ à(Úw€ó#€ € € € € € € € à"Ž\t³è* € € € € € € € €Ñ à(Úw€ó#€ € € € € € € € à"Ž\t³è* € € € € € € € €Ñ à(Úw€ó#€ € € € € € € € à"Ž\t³è* € € € € € € € €Ñ à(Úw€ó#€ € € € € € € € à"Ž\t³è* € € € € € € € €Ñ à(Úw€ó#€ € € € € € € € à"Ž\t³è* € € € € € € € €Ñ à(Úw€ó#€ € € € € € € € à"Ž\t³è* € € € € € € € €Ñ à(Úw€ó#€ € € € € € € € à"Ž\t³è* € € € € € € € €Ñ à(Úw€ó#€ € € € € € € € à"Ž\t³è* € € € € € € € €Ñ à(Úw€ó#€ € € € € € € € à"Ž\t³è* € € € € € € € €Ñ à(Úw€ó#€ € € € € € € € à"Ž\t³è* € € € € € € € €Ñ à(Úw€ó#€ € € € € € € € à"Ž\t³è* € € € € € € € €Ñ à(Úw€ó#€ € € € € € € € à"Ž\t³è* € € € € € € € €Ñ à(Úw€ó#€ € € € € € € € à"Ž\t³è* € € € € € € € €Ñ à(Úw€ó#€ € € € € € € € à"Ž\t³è* € € € € € € € €Ñ à(Úw€ó#€ € € € € € € € à"Ž\t³è* € € € € € € € €Ñ à(Úw€ó#€ € € € € € € € à"Ž\t³è* € € € € € € € €Ñ à(Úw€ó#€ € € € € € € € à"Ž\t³è* € € € € € € € €Ñ à(Úw€ó#€ € € € € € € € à"Ž\t³è* € € € € € € € €Ñ à(Úw€ó#€ € € € € € € € à"Ž\t³è* € € € € € € € €Ñ à(Úw€ó#€ € € € € € € € à"Ž\t³è* € € € € € € € €Ñ à(Úw€ó#€ € € € € € € € à"Ž\t³è* € € € € € € € €Ñ à(Úw€ó#€ € € € € € € € à"Ž\t³è* € € € € € € € €Ñ à(Úw€ó#€ € € € € € € € à"Ž\t³è* € € € € € € € €Ñ à(Úw€ó#€ € € € € € € € à"Ž\t³è* € € € € € € € €Ñ à(Úw€ó#€ € € € € € € € à"Ž\t³è* € € € € € € € €Ñ à(Úw€ó#€ € € € € € € € à"Ž\t³è* € € € € € € € €Ñ à(Úw€ó#€ € € € € € € € à"Ž\t³è* € € € € € € € €Ñ à(Úw€ó#€ € € € € € € € à"Ž\t³è* € € € € € € € €Ñ à(Úw€ó#€ € € € € € € € à"Ž\t³è* € € € € € € € €Ñ à(Úw€ó#€ € € € € € € € à"Ž\t³è* € € € € € € € €Ñ à(Úw€ó#€ € € € € € € € à"Ž\t³è* € € € € € € € €Ñ à(Úw€ó#€ € € € € € € € à"Ž\t³è* € € € € € € € €Ñ à(Úw€ó#€ € € € € € € € à"Ž\t³è* € € € € € € € €Ñ à(Úw€ó#€ € € € € € € € à"Ž\t³è* € € € € € € € €Ñ à(Úw€ó#€ € € € € € € € à"Ž\t³è* € € € € € € € €Ñ à(Úw€ó#€ € € € € € € € à"Ž\t³è* € € € € € € € €Ñ à(Úw€ó#€ € € € € € € € à"Ž\t³è* € € € €€È´iÓ¤X±bök×®]° € € € €¤ @Æ<§B@@@@ ÙÇ—Ý»wÛíœ?Þ^f@@@@Ày29oÌ@@@@@@ „À!C¤dÉ’öë?þQ›] €¸_€±Ïý÷+@ ­ á(­ÿ àú@@@@@ˆ²À¡C‡dÇŽv/È^gS°€ JûRéå²HCd8JC7›KE@@@@@@@@ ¹%Wã@@@@@@@@HC¥¡›Í¥"€ € € € € € € € \ŒÉm€ã@Ày¯\ç/ß´i“œ ÅR_’ðG‚C@T/àÖ±/%úÍ–êÿøsDFÀüÃ}ŠyQ@À!•+Wzš5kæ1A1ó­ßËyjÖ¬é0`€çôéÓ‰êÁ¯¿þêyüñÇ=õêÕódÉ’Ån×yúõëç1_äZí™`$O·nÝì×Ò¥K/yóϤI“<7Þx£'C† vÛÞþ—/_ÞóüóÏ{öîÝ{ɶ¾ûî;ëõ:õõý÷ß[Ç?~ÜóÊ+¯x´¿Þv½ï×]wgþüù~mkŸÆç1F~õ3gÎì¹öÚk=}úôñ9rÄï˜À•XêK`ßXGÜ*àÄ8—Ü6?øà¿±§wïÞ‰âmÛ¶­ßñëÖ­³•±$Vúað€ à'ܱ̯±W’Û¦“ããÚµkýÆÎ%K–X½>wîœç¥—^ò˜—ØŸã&Nœh_Þ„ ìíúypÛ¶mö¾` ú9ò®»îò;WçÎ=gΜ Vm €a $wŒ;v¬ýwsüþn¯R¥Š½ï¹çž³{”Ô±#–> ÅR_lX@ÂpÓØç{AÉí··-Æ0¯ï `Š™ïd’^Lñç4ÐçÁô˜ F~²Íÿ­A×kÕªåÙºukX=™6mš'[¶lAÛñ¶¯83gÎô˜lJ~õþûßÿ†<ÇêÕ«ãõxÛ |Ï;·˜ªÁO>ùÄïüÚ§-[¶x*T¨à·=°m]×ëÔ¢Mõë׿d} Túûï¿ìN,õ%ÁN²p‰€ã\¤Ú4=& ž=nh€o¨ñÁ—ÜdܳӱÈd#ô\¸pÁ®+cI¬ôÆa@ÀˆÔXæË©65ÀÈ÷3Ý×_í1Ùrƒ~ŽKjÀ‘Žåú£ßóÔ¨QÃsàÀ_.–@!©1¦ÿþ~?ûþ]í»ÜµkW»wI;bé³P,õņe@ ¤€Ç>½ HõÛ‹Ãæ•àŒ@±äÏÇdþÕOAÈ 8PÞ~ûm1)í†5m|õêÕ¥\¹rñ¦[¶l™\}õÕòÓO?Ùõ4E¢Éä#íÛ·óËÎÀÝ~ë&c’´iÓF>þøc¿í¡V/^,7Üpƒ¬Zµ*^µ`Sµ>|X̯I¥W¯^ñê'´AS06lØPL¶ˆ„ªØÛÍ—²bÅ ¹í¶Ûä‡~°·'´°páBiÙ²¥èµ‡Sb©/áô—: €@, 81ÎEªÍË/¿\4h`s8qBfÍše¯‡Z˜>}ºßîŽ;ŠNá™P‰•±$Vú‘Û@´"©±Ì×+Rm¦äøh2I«V­Âúç{­ -›`#iÞ¼¹˜L¸v•k®¹F¾ýö[É›7¯½@Ä DjŒIÜYƒ×NêØKŸ…b©/Á•ÙŠ àÖ±Ïé~3†ñÿ$YÀD,‘áˆÀ5",0{öl¿Ì µk×ö˜`¿³èašM¨I“&~¿Òº RÌüÏn¿2eÊäéÔ©“Ç|Éj¥žß°aƒgêÔ©VŠyo½À)ÑÊpd‚‡<)5 ÑŒ3<;wî´º¤éí5 ¿yøj÷Á{ž×^{-h·£¤5Ë„÷8å™3gŽçÏ?ÿôhß'OžìѬIÞýúž1cF{Ý|‘ìyùå—=‹-²²™ -Ïc=oº:íc°K} Ö?¶!€npbœ‹t›š=Áw<ÑéWÂ)šqÐ÷¸õë×û+cI¬ôÇ@ Dz,SÎH·éÔø˜¥âæ›oöO‹/îiÑ¢…G3[Ì›7Ïþ“ΔjGõh6[ßñ¹nݺ—œRÛ>  €A"9ÆüñÇž_~ùÅzég/ß¿³¿üòK{ŸfÛ󖤎±ôY(–úâuå@ a·Ž}‘ì·W‡1Ì+Á;¦Tã±&à“+W.Ï_ý²‹÷Üsßq ,ú%kÁ‚íz¸óÕW_V³×õ‹ä,Y²Øõ½ô 8êÛ·¯_]Îd„°Û \2dˆ_ýbÅŠyÌ/‘«yÿÑ¢ý¸ì²Ë¬íñ*› úåD°ièêÕ«çÙ·o_°C<¯¼òŠ__z¨K} z!lD\"àÄ8é65ÖwÔ©HCkJ¯S~zÇK}+cI¬ôÃ%dé& "‘Ë´Ó‘nÓ©ñ1ð¡±w<-Y²¤õƒ‘„nÀ¥Ž´¿uêÔñŸuºmý|LAHž@¤Çoozôèá÷÷ööíÛ½»üÞ“:vÄÒg¡Xê‹.+ €AÜ:ö9Ñoư D؈@Z`J5óE˜X¾|¹ÝŸš5kJ¾|ùìõ` Ý»w÷Û¼råJ¿u]9r¤˜L@ööÑ£GKÓ¦MíõÀêløðᛃ®›¬òꫯÚûjÔ¨!æ‹_‰‹‹³·. 6LLv!{³ù%“˜({=Ô£>j¥×VG§•ÓÔø¾Å(ɤI“Ä\ùn¶—{öì)&’½¾fÍ{ùR ±Ô—Kõ•ý €@¬81ÎEºMð+·Þz«M¦S‘š_ÙëÁ‚M§¬^à¶XKb¥>¬#€iE Òc™ºEºÍ”MÆ\kŠl“(IL°‘õ™×wÚqž[Çó9r$©MB¸(é1æbËI_JêØKŸ…b©/I¿‰¤N·Ž})ÕoưÔùçž«B ‹OÙéMpTàÂ… ²qãFû¿ýö›˜pHI—.½-pÁüBSF%gΜ±vU«Vͯʑ#GÄdñ±·•-[V4 èRE™4PÉd YuÀ€ö¹µŸld¦b yŒîÔãÌ4oö±ï¼óŽ4oÞ<äq|5xðàu®ºê*ñýRÙL'åË—Oð3µœ\qŲiÓ&«Îþýû¬ë»#–úâÛ/–@Xpbœs¢M54¿þß "]nݺu‚¼}ô‘½OÇÁvíÚÙë -ÄÊX+ýHȉí €@jpb,s¢M½)1>êyôG-yòäÑÅD—C‡YÁF¾_¬ënfΜò‡1‰> €iTÀ©1&¹œI;bé³P,õ%¹÷‚ã@Ô&àÖ±/¥úÍ–ÚþÄs=$N€€£ÄyQGÌt`R¥Jë—œz¢½{÷J×®]åÍ7ß Äóøã'دuëÖ‰ffð––-[†lË[ÏL»&<òˆ :Ô»)è»of¢Ò¥K‹fe §(P@4h _ýµU]¿ü5ÓÕˆž7¡b¦F“ܹs'´ÛÚž7o^¿ýêy©’3gN»ÊÁƒíåP ±Ô—Pýd KNŒsN´©f«cŠw\øâ‹/äÔ©Sb¦Z‹GjÒüËÒ¥KííúP³P¡BözB ±2–ÄJ?rb; ڜ˜hSïCJŒú™2TFÞP8`»bÅ »šöùã?:†Û•X@[À©1&쩘Ա#–> ÅR_‚³ HÓnûRªßŒaiú.IÄ–€¦y÷-'N”%JÈ“O>)‰™îËÛÆæÍ›½‹Öû7Þè·j¥bÅŠ¡v‹fÒTõÞ¢Ó©%¦øi†¦mÛ¶…<\.U4c‘oÑ ¨Äø§ÄR_Âé/u@Xˆô8§×åD›:%ç]wÝe³;v,Áé?}3!é:t° µ+cI¬ô#”û@Ô.àÄXæD›)1>V¯^=I·[?Ÿ6jÔÈþ6¢ý}÷Ýw 6J’(!€ 81Æ$|¶KïIêØKŸ…b©/—§ öÜ:ö¥D¿ÃÒÞÿ\1¾ùj°Œ@ <õÔSR»vm¿žìÞ½[FŒ!U«V•‚ J›6m¬¬GšQáR%0àH§T ·”,Y2dÕ 6øíÿõ×_åÞ{ï ûµ`Á¿ãwíÚå·¸r©þÖ×õ¢E‹Ûœìm±Ô—d_ €)(éqN»îD›Ú®Nã[‹¼û|§SË–-›ÜqÇÞ]!ßce,‰•~„Äb' ʜ˜hSoƒÓãcb>³úþ±hÕª•¬^½Úw“5…÷!Cü¶±‚ |§Æ˜¤ö,©cG,}Š¥¾$õ>p šÜ:ö¥D¿ÃRóŸ|® K 0¥Ú¥¨@Š äʕ˚f¬mÛ¶ötc¾Ð_mΘ1ÃzévÍBÔ®];kú³üùóûVµ–ŽòäɯNB.•,àHƒŽ’ZNž<òФiÊH'J,õʼnë£M@À)HsÚO'ÚÔv5p©R¥dëÖ­º*Ÿ}ö™õàR³%xËŽ;dÉ’%ÞUчtN‰•±$VúŽu@Ô*àÄXæD›êïôø˜1cÒ¾ªúã?‚þñ˜0a‚ÜsÏ=Ö”ÞA+°@ ÑN1‰îÈ¿$u숥ÏB±Ô—¤ÞŽCR³€[Ǿ”è7cXjþ“ϵ!pigžÄ_ú¼Ô@ú€¯¾úJ~øá¹ï¾û$X ‘÷ðß~ûM†jM»öÎ;ïx7Ûï_ºæÎÛÞw©…K}Xׇ¬‘,§N Ù\† BîOɱԗ”¼nÎ…DB ’㜷?N´™.]:¿éÑŽ9/80ëQ`Öoÿ‚½ÇÊX+ýfÄ6@ - 81–9ѦÓãcr﹎Ń ²›ñx<Ò¥K¹ÔçMû@ÂpbŒ ëĬKŸ…b©/$¦)@ U ¸uìsºßŒa©ê9ƒ@¢’ö³±DŸ†@ )×_½èëÂ… Vö„yóæÉüùóeáÂ…˜ H×õKTr­E‹öé³,:tH *dïµ°oß¾P»¥xñâ~û~øa¹óÎ;ý¶%f¥J•*‰©N]@— Dbœ $ˆt›:táÇۧÑ#ßqÖw:5ƒ›4ib×e@¤Dz,Ó>DºÍXûôé#¯¼òŠ•‘ðÿûŸlܸѺúþôÓOË‹/¾˜”[Â1 €!"=Æ„8»@ˆ ·Ž}níwLÜt: á(Av ;:-Xݺu­_i~ýõ×¢ACsçΕnݺIŽ9쎞?^zôèa¯ëB`F£Äd%Ú¹s§_[+åÊ•óÛ¤SÌ4mÚ4ɯ… ûµÇ  €@ÚHÎ8—P¤Ú,_¾¼ÔªUË>ÍÌ™3åìÙ³ÖºŽ“¾Ó©Ý}÷Ýr©ì€vC, € p He¾§‰T›±8>6LF-š)sæÌòÆoø^ºŒ5JV¬Xá·@È DjŒ‰\h @gÜ:ö¹µßÎÞMZG¤ p”T9ŽC ŠúåéM7Ý$ãÇ—Õ«WKÉ’%íÞlß¾]öïßo¯ûîÓ— "²4 Ôªmذ!Tuö!€ –@bƹ°4•’Ó¦ï4iô«µÌ˜1Ctšoñ­çÝÆ; €‘HÎX–P’Ó¦ï¸ ãc§Nü.S³¶oßÞÞvîÜ9éܹ³è;@ÀyäŒ1Î÷Ž3 € y·Ž}níwäï -"€@R8JŠÇ àÀóÏ?/+V´^×^{mXg¹âŠ+¤W¯^~uW­Ze¯¶óùçŸÛûB-è4nšÅ!TÑ©ÙtîWoY¶lY¼©Þ¼û‚½k~ïõ6hÐÀï¡m°úlCp·€ãœm*kæ"߹ȽӨyßµ~… ¤víÚ‡²Ž €À%œËœh3ðBÜ0>êôj¾Y5ÃÑË/¿x)¬#€$B %ƘDt‡ª €8.àֱϭývü†rˆ¨Gå¤1’' SŠ­[·ÎzýüóϲmÛ¶°ô úÑŠ+fW¯^=+«ƒwÃÔ©S%œiÕ&L˜ [¶lñ–à»N¡æ-·ÞzË»ò]§†›6mš}½•+W¶R߇<ˆ €®pbœs¢Í@d °Õ, Þ¢¹šQpñâÅÞM˜UÁÞÁ €—pb,s¢ÍÀËpÃø¨}|á…üºþÌ3ÏÙyýHXA%cL¢:De@pëØçÖ~;|;i",@ÀQ„AiäfFxã7Âjî›o¾±ëeÏž]®ºê*{=Ož<¢™„¼åìÙ³òè£Ê©S§¼›â½k°Ó“O>o{° úëи¸8{×È‘#åÏ?ÿ´×ƒ-œ8qBúõëç·Ë7¿ßV@R€ãœm÷§þúë/éÙ³§™Oç=÷Ýìx¶!€ €c™më¿ïø«ãc×®]Å7ó¯~îÒ¥‹=Ž».¶!€$,à䣟­|Ë¥¾cô­Ë2 €N ¸uìs²ßNYÓ.¸OÀÿ_ðîë?=F U TªTIªW¯n_Ó¨Q£dРA¢ABÁŠN{öÜsÏÉ|`ïnÞ¼¹~88p ä̙ӮóÙgŸÉ 7Ü k×®õû’õðáÃVzù† Ê‘#Gìú¡J–,) °«ìÚµKjÕª%Ë—/··ù.èö5jÈÊ•+íÍ>ø Ô­[×^g@ u 81Î9Ñf0ý;î¸C²eËfïúâ‹/ìåÆKñâÅíu@HŒ€c™m»&7ŒúùøÍ7ßô›uÁ‚òÿ÷Á.‰m €—prŒÑL ¾eĈ~ß]úîc@”pëØçd¿SÊžó €@ì dŒý.ÒCÒŽ€~ªS™Õ©SG4˜H_:ǪNÝ¢A@š¹¨T©RrðàAY¿~½èôh¾Ó®é‡òqãÆÅ+]º´L™2EÚ¶m+gΜ±ö/]ºTªT©"¹sç–Š+ŠN‡¦m>}Ú>¾GAÛ³+ü» ÙŠÞÿ};-ýÎ;E§r«Y³¦@U¦LÙ¼y³¬ZµJ4{’o•þƒgìØ±M²Ž œçœh3½µjÕÊ{÷kà,@¤ 81–9Ñf°ësËø¨?ìéÕ«—Œ=Ú¾ŒþýûË­·ÞJа- ž€“cL… ü:1}útÉ‘#‡\~ùåÒºuk뇗~XA@ Ü:ö9Ùï`ç àŽ\r£èfÚЇC† ‘aÆٿàùõ×_E_¡JÖ¬YåÝwß• ­Ö²eK+ë>Õ`#oѬF‹-ò®Zï2dáÇKýúõýŽ.»ì2¿zÞ•Ì™3ËO?ý$?ü°|ôÑGÖf lZ¼x±õòÖ |×/}g̘!Úw  €@Úpbœs¢Í`wC§Ñ`_ß’7o^Ñì@’#àÄXæD›Á®Ñ-ã£~ÆÖÏ«š•WËÑ£G¥{÷îòù矻,¶!€„pjŒñ‚zÿ®Ö.?~\~ÿýwÑ©;) €DKÀ­cŸSýŽÖ}༠{L©{÷„! O?ý´üðÃRµjÕKj¤K—N:tè`e<ºé¦›BÖ¯\¹²¤Sµéf¾SÃèY²d±šjzù'Ÿ|RNœ8á×^BÁLZ)Ož<ò¿ÿýO&OžlýòÈïÀ€­«Y‘4HéÊ+¯ ØË* €@jpbœs¢ÍÀûдiS)T¨ßæ{ï½W4ð–‚ €@rœËœh3ð:Ý2>fÏž]^{í5¿î멾S”ûíd@ ¤€cL¦L™Dÿn.W®\Ès³@h¸uìs¢ßÑðçœ ›é’Ó-Ç3Åß19mp,$,pþüy™5k–lܸQ¶lÙb½þüóO+°êèTi8tõÕW'ÜHˆ=:e›¶­Ó©éÔ¢E‹J\\œ}ħŸ~ê—µaݺuR¾|y{B ÇŽ“+VÈ/¿üb½öìÙcµ]¼xq©Q£†•¶ž‡³ é±H;NŒsN´é{G:wî,o¿ý¶½iÍš5¢½@"%àÄXæD›¾×Ëøè«Á2 ¶œc´Mý.tÆ ¢Ëú½¥þ0Ó÷{Ë´¥ÌÕ"€Ä’€[Ç>'úK÷…¾ €@TŠpwNŠ€;ž}öYyê©§ìÎjêâ|ùòÙë, € –L°½”)SÆúâ[¯[§Õ¬€@Ò²ãcZ¾û\; € € €¤aâÓðÅsé¤ Xž3gŽ}­ú‹ ZµjÙë¡.\hïÖ¬Ù, €¤A¯¾úÊ6ÒËïÑ£GTà’@ð`|ô÷` @@@H+¥•;Íu¦Y 2H¯^½ì¤9sæ”;vH®\¹Bšèth¾YZ·n²>;@Hí¯¿þº}‰EŠÆF›ƒ@4,Àø˜†o>—Ž € € €iZ }š¾z.4"ЬY3ûJ=*o¼ñ†½laÓ¦MÒ¼ys9yò¤½»M›6ö2  €¤5¥K—ʬY³ìËîÓ§dÊ”É^g@´(Àø˜ï:׌ € € €ü#.9gŠ9¾crÚàXp^àÛo¿•&MšØ'ʘ1£tïÞ]úõë'Å‹·¶Ÿ>}ZV®\)K–,‘Ñ£G˶mÛìú;w–‰'Úë, € ÚÞ{ï=9|ø°.\XV¯^-o¾ù¦8pÀºìܹsËöíÛE³R@HKŒiéns­ € € € €@HâL©Ò‡¤ÆËK/½dé;wNÆŽk½²eË&E‹µœž9s&ÞW©RE^}õÕxÛÙ€ €@jX¸p¡L˜0!è%>õÔS•a# €@j`|Líw˜ëC@@@Â`Jµð­¨‰€«úöí+Ç—¸¸8¿ë8~ü¸lܸQ‚Ýÿý²xñbÑ $  €ˆôîÝ[}ôQ(@@ÀG€ñуE@@@@ á(Üh.4htëÖÍšfêÔ©²eËÑ©Ô|K±bŤuëÖÒ¾}{©S§Žï.–@H3•+W–Ò¥K˱cǤT©RR©R%iÙ²¥Ü~ûíiÆ€ E@ P€ñ1P„u@@@@ í ¤KÎ¥{<ž)æøŽÉiƒc@ zæÿaÙ·oŸìÙ³GòäÉ#… –,Y²D¯Cœ@@@@@@@b] 8ŽbýÑ?H—.d¤F@@@@@@@@ ôáT¢ € € € € € € € €  d8âÏ € € € € € € € ;vL6mÚ$7n´Þ·nÝ*¹sç–R¥JÉ•W^i½—-[VÒ§'gˆƒ·¦@ ‚E“¦@@@@@@@D*Uª$‡NEÑ¢E¥J•*R¹reë½V­Z’'Ož°Úhܸ±üþûïvÝÏ>ûLjÖ¬i¯'w¡Zµjò×_ÙÍ|óÍ7R¡B{=¡…½{÷ÊÀeòäÉâñxªfm/S¦ŒôíÛWî»ï>Éœ9sȺìD¢-.90!N1ÇwLN{S¦L‘Ñ£GKb¯sô(ч’L™2IöìÙ},ÄžÀîÝ»¥P¡B’!C†Øë\*éÑü!ú!¡pá©䊸 øòË/eРAÖÿ?ˆ¤ýµH‘"üÚ'uÜNÙ¿¿äÈ‘C²dÉ’J®(ö.ãĉ’+W.ùâ‹/b¯sô(IK–,‘®]»òo–$éÅæAúoý‚ JÆŒü6,6ïPâz¥!²fÍj½w$µÃ8uê”õÿË·ß~î!Ô‹qý¥ëÖ­E2RR‡€>\Í—/ŸõÝd긢´}”Ë.»Œï™ücpúôi9{ö¬,\¸ÐÁ³Ðt4þóŸÿÈ?þhe²‰Æù£yÎyóæÉ¹sç’Õ}ÆUµjUkL¹TC‹-’¿ÿþÛ®vÍ5×DÔ}þüùræÌ»ýºuëZßiÙ.\¸ Û·o—-[¶Èùóçö†^Õ¿s5óQ‰%$]ºd=Ò}¢4¼Wÿlê÷’ú=3Å×4³×Ò¥K9­F[ 8ßbEûÄàùõ Î’%KÊsÏ=ƒ½£K‰xýõ×­´hÑ"±‡R?î¹ç6lXDÿƒ—Õ.µmÛÖúò$ªàäÐ/8u|Ó€ZJêÐ/¾ø¢ÄÅÅ¥Ž JãW¡¿ðjÓ¦Ô¨Q#K8wù ,Ÿ~úɹÐrŠ h™ê1¶¥8½c'ìØ±£ :TòçÏïØ9h8åô;• Èõ×_Ÿr'McgZ¾|¹Ìœ93]uê¾ÜlÙ²YAdŒm©ç>?üðÃÒ¯_?ëAi깪´{%cÆŒ‘òåËËÍ7ßœv¾rÍÊ2a‡ÏBóÑÐ`ZýwaçΣqú¨ž³^½zräÈ‘dõAV¬X!?þ¸<ðÀ!ÛºýöÛ­©Ê¼•úôé#š•(R¥~ýú¢˜Þ¢ã\¹r弫ñÞõ3žþÀ9XÑ@*ýÞZ¬,(K›Ö¯_/W]u•<ûì³ü8%b2·ipô€øn%™Ž¡ß¹s§ >¡øïCÍÉÏÍiuœK¨ýO?ýT¦OŸî×Õë®»N† bM§Ïîôy„^·~o£ÁEœ¤‰ôz½E§…«S§ŽãÝÆ{dôs›ÞÓ„îadÎ’¶[Ñq-¡ÿçÓ¶Lê¹zŽRϽäJ@@@@@@@˜ÐŒ@úópÊܹs¥]»v~’4è¨gÏžÖ´ñá´­:š9硇ò;ýĉƒf¹Ò€ý¡¹¾n»í6kŠÙN:ÉŽ;ìã5ÑnÓ5P@XHK¡/ y;î¸C®½öÚÈ7L‹QéÓûçÏ(Q¢„ÏÞØ\ܰaƒÝ±ãÇ‹N‰go g¡\¹rRµjU9zô¨U=K–,áF@ Eüÿ†NÑSs2@@@@@@@‚ ,\¸ÐoGùòåýÖcqÅ·gΜ‘~ø!IÝ\µj•lݺÕzùfMJRc„8 @À‘¨4‰ € € € € € € t;vÈ¢E‹ìræÌ)Íš5³×cu¡N:~]ëÔ©“¬Y³Æo+ €@j à(5ÜE®@@@@@@H%ëׯ—믿^Ž9b_ÑSO=%… ²×cuáºë®óëÚ¾}û¤nݺòÀÈwß}'gÏžõÛÏ  àVŒní8ýF@@@@@@¢-0nÜ8Ù¶m[Ðn¬\¹RN:%‡ºßÍË•+']ºt û¾ÿþ{Éœ9sÐúçÏŸ—ˆçÌ›7O¾þúk9yò¤]·W¯^Ò»wo{=–Ú´i#;v”÷ßßîæñãÇeòäÉÖ+[¶lR¿~}iÔ¨‘4hÐ@®¾újÉ”)“]—@À-¹åNÑO@@@@@@ˆ9iÓ¦ùMý¬ƒ?þøc°Í®ÞÖ´iÓDÝrË-‰¾Þ\¹rY;·Þzk¢ÖéÒ¥“·ß~Û  š={v¼nhðÑœ9s¬—‹“ÚµkK½zõ¬¤† &˜¯16 €Q à(Šøœ@@@@@@Ü-ðñÇ[YŒ‚]…f¹9tè<úè£Áv»z›Ê8]tJµ7ÞxC4ðH³¹¥hÆ"ýs1~üx=z´ìܹ3Á®k&§ X¯_|Q²gÏ.Íš5“ž={Ê7Þ˜àqì@¢-@ÀQ´ïçG@@@@@@× *T(Á¾çË—ÏÚW²dÉë°#´€f Ò—N«öòË/»fú±,Y²Èc=féqšÕhîܹ²aÆü÷ßËŒ3¬WóæÍå½÷Þ“üùó‡<† €@48І:çD@@@@@@Ò€f+Êš5k‚W|êÔ)+Ô®]»dþüùÖ´d›6m²ë¿öÚk’3gNyöÙgímnXÐlG:œwJ¹;vˆN±·xñbk*¾U«VÉùóçƒ^ŠZÝyçòÍ7߸&Ð*è…°R¥@úTyU\ € € € € € € €@Ìd̘QB½t*±Ë/¿\êÖ­+ åË—K«V­üú?bÄÑ7—%JHûöíeìØ±Ö5ê”{Ÿ|ò‰téÒEŠ)ïÒtºµîÝ»ÇÛÎ@ Ú 8ÒhÓÕ«W[©ìtÒI“&YóQnݺվ>{’‚ € € € € € € €À¥4›ÑÇ,mÚ´±«ž={V^xá{=5,äȑà ¬š0a‚lÛ¶MÞzë-Ñ $ߢÏßùåßM,#€QHΔj—3¦ìŠ+¬ÈKýË=°\uÕURªT)kó›o¾i¥¾kÙ²¥ÜvÛmR°`ÁÀê¬#€ € € € € € € ` ¤K—ΚRlúôé¶Èš5kìåÔ¶pÙe—ÉC=$ 6”k®¹Fýÿ™Ž'úXïÅþý÷ßÒ«W/ë/Z3S¦LÞ]¼#€ € € € € € € ` äÏŸßzž|æÌk]“a=zTòæÍsBštcÏž=V¿2fÌ(#GŽLò³ðÀlF«V­Š¹ë¥C ¶•áÈDR62ÁF“ Y¼`#ý ½N:’9sæ ¢qqqñ¶O:UFo;@@@@@@@عs§xƒTCb1ØHûV°`A}³ŠfaZ·nw5ÑïEŠñ;&kÖ¬~ë¬ €Ñ;à¨hÑ¢YM°Ñ[¾6sHž{ðÁeΜ9²xñby÷Ýw%W®\¾Uìå‡~X^yå)^¼¸½MÞyçË6&³@IDATY°`ß6V@@@@@@@xÿý÷ý*V¬è·K+õë×÷ëÎĉýÖ³¢SÇù–À$ß},#€Ñ;àÈDLv3sc^éí¤Çã9ñÒK/Íëß¿¿”*UÊ»9ÁwW³E‹2{öl¹ãŽ;üê½úê«~ë¬ € € € € € € €¤meË–Å›1çž{î‰Y}î[Þ~ûmY³f聆—_ýu¿º×_½ß:+ €@´Â82ÙîóvÖ¼pá­͛7ÿÓ»-Üw“I†*W^iÇ.ÉÚµkeóæÍá6A=@@@@@@@T,0~üxÑ ›C‡ÙWyÕUWÉC=d¯ÇÚB³fͤfÍšv·Ž?.uëÖ•>úÈÞÎÂÀeîܹvÕŒ3JÛ¶míu@XÈN'Ê–-[ÁÔ«êS÷C ôYÐg[Ø‹qqq2|øpiß¾½}ÌW_}%Ý»w·×Y@@@@@@@H£GMN‘P1I/dûöíò믿Z¯¿þú˯ªÝŒ;Vô=œ2fÌIê4d;vô  ç|ZGgýÑó6jÔHΞ=k¦AGwÝu—ôíÛWî¿ÿ~)W®\Ðk8pà€,X°@FŒ!K–,ñ;¥ ,XÐo+ €@´ÂúÛØüÅX> £?¬'zµzõêÖ€ræÌëØ]»v%º @@@@@@@ˆ}Áƒ'¹“™2e’?üPš6mvZ?©¥V­ZI 8ÒóiV¦I“&I§NüN?räHÑ—]i¦¦Ê•+K¶lÙdýúõòûï¿Ëþýûýê{W̬C2dÈï*ï €@Ì„pd¦O+i¦T³;m’p”!C1™“¬èTmxïÞ½vû, € € € € € € € иqc5j”T«VÍ5÷Þ{¯”(QBúôé#+W®ôë·&äX³fõòÛ°’%Kyâ‰'ä™gžßgõÕXE¢&VÀ‘ 0òËmgþ܉*TÈ8J(b3ç¡ @@@@@@@ØÈ;·äÏŸ_Š/nMK¦Ù}4ÛKƒ dùòå2yòd4hPØ 84iG·nݬé×òæÍëÆK§Ï F 8òK?dRÖU5> ’k´iÓ&»‰¸¸8{™@@@@@@@÷ 8p E;¯Yƒœ,ûöíKtóš™èÁ”víÚÉÒ¥KeãÆÖKŸ“ë+sæÌV&¤’%KZïÕ«W T2 A}.@RZ ¬€#3¥Úvß4m§¦éh²ŽŽ?.;vì°¯·@ö2  € € € € € € €¤lÙ²É7Þh½RÃõp  €€ ¤‡ÁDW.2AFG¼uMDåL»dåo›5k–·9ë½fMa¢ € € € € € € € € €@, „pd.ଠ8šé½pTÌL6Ñ»žØ÷µk×ʰaÃükÒ¤‰ß:+ €iO`ëV‘;îùþûø×~âDümlA@@@@@@HypŽäìÙ³O› £ÓÞ.š £;Li´sçNï¦K¾›©ÙäË/¿”îݻ˙3gìú·Ür‹\~ùåö:  €iSà±ÇD>ýT$S&ÿë×`£ìÙEî»Ï{$×ÎÑéÏœ)Éfi @@@@@@Huý¢íÛ·o-[¶ì³¦þpï1¿ýö[Ñ-ZHÛ¶m¥jÕªR¹reÑ "o1J²wï^Ù¶m›lذA¦Nj-{÷ë»ÎWùŸÿüÇwË €iP@³}ñ…H›6"õêùœ<ù϶÷Þ3Öˆôíë¿?±kgÏŠ,[&²bÅ?¯•+ÿ 6:mÂjóåk—Øæ¨ € € € € € €¤)°ŽTeãÆÏ•)S¦dúôé»x•N›§³ï¿ÿ¾wÕï½gÏž~H~;ÍŠiGÆŒ#Å‹ÜÅ: €@(U꟠Ÿ¸¸øž/ŸÈܹ"×^+2pà?ï7Ü¿^8[öì1‰õDƒŒ¼¥H‘ÆEªW™6Mçs3QO@@@@@@@ aO©æ=zÓ¦MÝÌò óúÛ»-¡wßlGu .,ãÆ“’úÄ8°AÖ@’,päˆÈÈ‘"&1]TK… "W\¼ &!žLŸ.’%‹H;“„È$ÐKRÑLJë׋ôé#2gÎ?íìÞ-fÊO‘çžÓÌ{¿$©]B@@@@@@ÒŠ@¢Ž Ì3=ÚógΜ)k‚…6¥K—.QV™2e’®]»ÊìÙ³¥Q£F‰:–Ê €‘˜9S¤bE‘~ýDt9–Kùò"“&ý$t÷Ý"çÏ'¾·:]›™åSFiÖL¤P¡Ä·Á €DSàØ±c²hÑ"3&a ŒfÇ97 € € € € €@ªHJÀ‘uñÛ¶mÛûÖ[oýôñÇËí·ß.UªT‘ìÙ³…É‘#‡µÿÎ;ï”Ï?ÿ\þóŸÿHÖ¬YƒÖe# €@Ê L*rò¤ÈÛo‹´j%röìY9qB¤W/‘µkïË™3‰;Ç]wýÓ·ïÍÌgƒ4ß^eÞ¼yR¹reiß¾½¬^½Ú¯3yúq°‚¤z35´téÒEf̘áúkõŽo×]w-ZԌ׽dÉ’% ^×áÇE?³?Þã¬È@@@@@!1uƒV­hÒb¼ôÒKö¾¿þúKL0’™êf¯è´i¥J•’|ùòÙûY@ˆ-3»¥•)èàÁߤuëÁV`è“O~dL¶’ D~þYä²Ëœéó¹s"W_-Ò¼¹ÈË/‡­«ýÒáG3µlyñX“OlÚ{Ùôû2ùõ×zòßÿv—[oÍ+ 0õÍ@4! ŸM† &o¾ù¦lóÎ;ïÈG}$wÜq‡ë®ÿ¤‰îß¿¿¼þúëfúÏlÒ£GùöÛoeìØ±Ö«téÒÒ¡C¹ËDæîß¿_¾þúkùæ›odÙ²eâêú¶ÛnsÝuÓa@@@@@ØHvÀQàeåÏŸ_ôEAp‡À‰Ûåé§Ÿ–÷Þ{Ïz ™'Oyþù;ÍÃØ&DU2DdÄg®Å<÷•ß~ÑéÑSÌìœæñ?ÁJ÷Ý'²|¹È•WЬ_¿ÞÊhôË/¿È5×4J•>•wÞÉ-yón”Y³ÊË_|!f:P+ð¨iÓ¦¢/Ö¬Yce@ò¾?~<1]¡. €@ œ:uJ^{í53ž=/GŽ‘:uêÈc=&½{÷–{î¹Çš4iƒ=Þ%Í`Ô©S'3%è©_¿¾¼ûî»Ö;´¶ŽySMºÂ>øÀ ®Ò+oÉ›7¯ &n-z­éÓ§·êz÷ñŽ € € € € €@r 82¿–me¾ ~ÄçD›ÍCÚî>ë,"€D@àÃÅÝ àѩ˙9<‹‡1§Ž!ß}÷À«SHÇÅÅY/ïr¡B…¬ì{ ž4`‡ŽÏ¬euœ5j”ôéÓÇ òV­Q£†èk¤ÜõÜŸ}ö™)RÄ×u»iÑ [  € € € € €‘+à(C† Ì ›úœ4«Ï2‹ €ÉÐ,?>*2ož˜Šb¦}¹Øàÿþ?àhüx‘jÕÄ<`É’åbÝPK&Çd9ЩÈ<òçŸïÈœ9½åï¿ÿ6™€®±iÔοE§`ÑL@Û¶Õ7ýY%÷Ý—QV­Àã­qñýèÑ£V¦ }¨™.]º‹;.±df„± ^}U${v}¨ºsçNk˜J•*IŽ9.Ñ‚˜‡©¬´GÆŒÉc®áC¹âŠ‚òþûï‹>Öbfš±¦\ËœYL U9™4i’ rzFFmeCÒóT­ZUªT©"åË—·W®\ù’ç¥ €@ììٳnjisdöìÙVÑáÇMàn^ëïúGyÄ/ÀGÿ¾×zd{Ë-·ÈüùóÍxjTŸ²}ûvéÙ³§ £Ssj<Š­K—.V†¼¢E‹úÔþgqóæÍÖ´mo¿ý¶˜ÕÒ¡CyãU&(êbTTÆÖ.¿ÿh† ÍAAp¯€M3iî4ÐhåʕօhÀMm“ÖîÖ[o•=zˆN¬\{íµòé§Ÿšì}-¤Y³fòÃ?Xãžf½3fŒ•QH§×Ôñì•W^±¦!ÓÌy¯›HÙ‰'J·nÝäÉ'Ÿ´2j@иqã¬~˜ÏH¢Aš )_¾|VÆ<ÍxtâÄ kYßuú3íóçŸnuM3ëið‘í.]ºÔÊPôë¯¿Š¶¥¥dÉ’ÖXÝ¿+3Ÿµ‘ÿ € € € € € a={v¹þº×[LðQÁ+®¸¢°ww@Ä èt`}ûþ0d’ ™–b2\l§\9}ó ÓÊÜóÓOb2 …6Ú¿¿•ÕgäÈÓ&ãÂPÓÔrûíË̓د¬ì¾Á¤çÑ ¡¹sçZ™Žka¦z»Ù<Õ>­0Ó¬½,ÿ3©—ôá¬fÒŒ úðöÅ_´^Õ«W·€ÚµkgezX¸p¡x_š9Bä5ó2QUòˆlÞ¼Îd&ºBtZ}׬?ÿü³,X°Àzøªç҇ȚâÈ‘#²eË««Úw=O§N¬‡Æ˜DAHý:m˜f':eææ,hæåÔÀ Ú¹ÉÌAšÿR¸ÿòè¸õ¡™Ç´M›6ÖxøÚk¯ÉСCM6¿UR¦L+[‘ÖÑ¢AIúúòË/­:”4aÂ+àHÇ4 ’Õà] ròÍøï©â½i®Îz³2i{ÞR¬X1külh"fõ,’·.ï € € € € €DS ¬€#“Mb›Évñ®y¸{Ÿ·³3f¼Ó»Ì; €@øý¥ÙxD¾úêŸ`!“ H:w3Yxmhü§Î~æ3šßš…¨^=1S†}.wß}·É¬p­Ùÿ•ɶð—ÉâpµÉ¾ð±_ýP+šqaÖ¬Yæal“ágÓžf‹˜n^ÿ5ÛËO2ÁT}­—îÓ¢BåË×”+¯œn‚†j™iÌNÊâÅãM–£¸*üW³;h–‡ï¿ÿÞziÛ:ÍÃ?l8éC]Í AAH;K–,‘–-[šéD³Xã“›êø’”rûí·[S¥iàj«V­¬©×le(Òö‹fDÒ×Ì™3­é9u*7­¯ã’fÏ ·h&¾ÖfŽS}iY»v­õªY³¦•i)Üv¨‡ € € € € €@4 8Òž>}ú±Ì™371_èÓuó>Ò¤ýÿF§-  €„/ C›7‹<ôÈK/‰™òåⱚ‘H³ iÆ…`;/Ö ¾´w¯˜©^tz¶ófz²’;w5“ya¶©œÁdÊ/fæ–DÍ<ôå—oËÍ774cÁTsüsfг~&ÃQ.¿¾ëßúõë[¯±cÇZ™ >ûì3)R¤ˆ\wÝuæýz¹ÿþ\²n˜ëó7Î%ÜmO³'éK³FP@Ü'°oß>kú0æÏŸoöètž: gbËêÕ«­LFªÁ°:>%·hv$ÍÖ§ADÏ?ÿ¼5%Ú¥ÚÔ@%}EªxǺHµG; € € € € €¤„@úpO²cÇŽC.\¸ÑÔ߮ǘÁq½{÷n¸hÑ"]¥ €„)`Èòå"šÙÈldþ~•ñãÇ›€ «äÞ{ï5ŠêÉÖ­[ÃlñbµÂf²ËG™nžþfŽž’ÇÊñã™eÚ´tI 6ò¶¬$~ûm¦lÚ”ß ‰Éd”ËL+ãÝÿ]§áÔéeÞyçënúô-LV¢\&c‘˜)×DL$Éž=þqlAp¿Àï¿ÿ.#FŒ°Æ²¢E‹J—.]döìÙV )S¦˜©9ËYò:öÅnذÁš2íĉVpP$‚¼'¿ß lŸ|òIXÁFÞcxG@@@@@ ­ „áH¡6oÞ¼éòË/¯g²n¼iŽn;pà@öxÀLëÓÈzéÃÍd¡Y)[ (ØC¨¸B@§PÓ™¿|ÿjÌ•ëb×M¶8éÞ½» BZ.æïXi×®L˜0Atj}0«Ó·„[† f¦6j‚‹*™©Z~”O?Í-]»ŠÜzk¸-$\ïÊ+¯´vš"iÚTä¶Û®¸gÒ$‘ô&ÄÕ{ÈŒ3¬i5Sƒ×€ € € € € €€›Â8*[¶ìfH”Å{±æÂ³neHš7ožè+9eýúõÉ9œc@˜п;tó0UÌCUÿ.ä}ì±ÇäÕW_µ•æÌ™#ùóç6Ù…‚VOöÆöíã71r¤È–-"¦+Ò¹³ˆïŒ›¤džËWÄ?Ž- €©Cà‰'ž°‚n2‘¥?þ¸4lØP4ãoiܸ±,[¶L>øàk|ëß¿¿¼þúë&;ß#ÖšåË——R¥JY㢧S²i°ÑüaµÝ²eKßæXF@@@@@( „pdúWԼ쀣¤d1ŠÒ5rZ@ *šÍG³™ø!)SÆ¿ Ó¦M3-¥üeÒéÙqãÆùMåÒ¬Y3ùå—_¬ÌÇ—%K–˜iѦ™ ¢üþ ™µ“'OJ·nÝä½÷Þ“o¼Q>ûì3+«D¼Šo0³ÑÈâÅÿœ¤Aÿ€#“äÂôÉáÐ< F›¿l5@GƒQc%g̘1òÊ+¯Hýúõ­q(sæÌ Þ ýqÏ=÷ÈwÞiM'ªãœf:ò R*cN >úí·ßdãÆòæ›oJû`ѮރxG@@@@W ;vL6mÚd}¨ï[·nµ²¦ëu}7IRBþ@?1)}¾Äôº¸E 1Gn¹&ú‰Ä„@b¦CÑÌ?fÆI«\¸pA4›ÃË/¿lMA9uêÔ –(QB~øá+0éÿþïÿ¤†iP§[Û»w¯ìÙ³Ç~:tÈj[:øá‡!§¥qF¬ÎŸÿç Ù³;y&ÚFÒ®ÀÏ?ÿ,7ß|³=zÔLÙÚš–L§1‹fù裬ŒF+V”™3gJ¨`#ß~j`‘ßvéÒÅ ²ÕŒ§¿ÿþ»õÒemë¼XFšôá‡ö=”e@@@@Lœ8Q†Ñžê¯5‹vJM¢³Néðoyã7äöÛo÷®Zïu^|ñE¹÷Þ{ýê°Z@Ÿ{éŒ “'O6³hxBVÖ*öíÛWô;Ñp¿‡ lÐéóéŸOýžÓ[4Q@Íš5½«Ž¼Ÿ>}ÚʯãóæÍkf¹ÂÎ"ïÈ iÂ82¿D>lŽñû©r\\\ÖL™2ùmCˆµk׊NQÖ±cGë¡lJ÷«P!1K/žU#¥5£Ã—_~)×]w|bR(Pàb… Kú%ÍêP·n]éÞ½»¨¤ÕråÊe,U¯^Ýz¯V­šõ°7cưÿZr¶äm2]¢ €8(°|ùrÑ x„£¾Ÿ~úiyàDOûôéãșϜ9oZ4ß-X°Àú¥H‘"2ÛDžæÉ“ÇwwXËY³f•믿Þzù ç>`æãÔ¶) € € € €îøûï¿e÷îÝí¸V¤T9uê”_ÿuƉÀXçøñãUXO@@¿ÿÓ¬éÏ?ÿ¼è3´pŠf>Ò'êw£ýúõ³~ÐîÌL)u¾?ÿüÓïÏÍÙ³gù´D×ÑÀ©÷ß_>øàÑïŽ}‹>_ÔlPšEþî»ï¶²ÍûîgH „ýdzÆ ñ¾é7†SLG:Fª3´ƒDJ@³-èCXý‡öh4ùرc­@PçÐ,þúë¯R«V­PÕüöéƒ_} Z°`A¿í¾+šöQ3iÔý÷ß/š±H3;„[4R[2Ÿ8qÂzðj>Ã=”z €©@`åʕҴiSÑ/T4pU§ãlÒ¤‰ÜtÓMòØcÉÁƒeذa!¯T³ì¥OŸ>dïNý2HÇQÍ2¤•4xWDZ,Yì–­éÎô]úáuÖ¬Y¢™ù"Ytœ$Ø(’¢´… € € € -!C†ˆfgò–E‹I±bż«iò½gÏžòÖ[o½výn°ùe¿Õ ØÑ™@ô{Ñ+VXYàÃùA~JŸ/è…Eh£>ÕÀ+ï,(Íê÷ÈúLR_Ó§O·"¼þúëVö£Àº¬#°Ž’sŽERJ@¦jÚÅ#FX)§M›fýceÊ”)2þ|+#D£FâuG†Æ':Øîß¿_:uê$&L¸d:Æ?þøÃÊž¤SÜh–¡jÕzHÕ¤víÚâ¨ÖiÑtÚ}¬ÓÂ<ñÄñÎΆ… ‡S: €©L`õêÕVp‘Å~þùçV°‘^¢~!¡†n¹åyöÙg­àWǼãÖÙ¾}»õR?€jÐ’¦ïïòä'OžlÔƒ (`Wñ€‚W¨#ùrô÷yÓ¦Mw5]׬)*›6uPõžzM#©W¯žQ{>|¸Ø…JDýúõc )ëJ$@$Ì º‡¾ ŠCèG°m·9rÈÒ¥KƒbÈãÔŽð '#8ÄÂà,¢çž{N>úè#ãT[½zu{VfñÄ¡ G¢Q£F™pˆû Y^ÈóN™2Å,˜1„"pèELr $F Aƒ œL»&9Ïcrù‡~èªB¥J•\ÛÖFÕªUeÙ²eÖ®+VÌµÍ ï Zô裺Ä8Þ#<âv ;øY´hQ³àïü!`wÞÂdLó¥éò4"Œ06‰PrvƒJ<”ðñ÷Y¡B3މɤӦM“åË—»’BªS§N²bÅ ·I«®Ü S!„Œy D’Ôðàg£Ž;/]{<¸ ¼£áù[¶lY¹ÿþûBÔ nºé&3˜úóÏ?›ÛþýûË×_mòôŒ{ŠvAâálSºƒ}®an^SG£sÒ£GvÁð¤I“dðàÁæt6Šä_Ë" Ø&'Zôipæ9yò¤Ìš5Ë„ÖôÖªL™2™0kxÙÆL¨AÉhûöí&•7|Û¶m2räHÙ·oŸéÃ:tèà’ÜŬ AƒÇ%„H[¼x±q6By˜ygÝo¿ýÖä …$ô›èOzè!oUâ1        ˆyp`iÑ¢…kÉŸ?‚6åÌ™Ó|kØ–ë®».Ap'€É’ˆ$@$Ap‚Z¼v÷ïßo&L˜ ˆíêiètᵋpk»ví2 µk×6žçëׯ7H©R¥2/àù{ôèQ©V­šqFB~'Oþ-mÛöQ§¦ç%wîš2~ü&IŸ¾™zT‹¤Is…|ñE:=z ‰‰ ‰Çwß}×tô·Ür‹gu¸O$@$@†^Ç'Ý»w7FPÖà s:uL8N8¶"lš?ƒ“”‹0»¥M›6¥"8áåJ8Ù@x!EÜn(%aÖ‡ ê‡ÙA˜ T®\9£->Žx3ÌÐB:8ñöèÑÃ[#         Ÿà0d7OÅû9oÛÙ³gO ò³`ÁoIͱH—ç³"I<1QXç6„Hó¥ì„tíÛ·O~ Oi$.I©öï¿ÿÊÎ;ÍÀd¸Nœ8adº0P/Ï|ùò™5”F0ÈA# ¤€bÃÌ™3²"¥J]Î NXh$@$@$àeá´ƒð–!ôú&8•(QÂ8Ýzë­Öi¿k8Í©61+X° QO‚3R¯^½Œƒ®i×®q|‚sH€H€H€H€H€H€H€H€H züóÏ?&ŒÆå¡èƒo‡ƒ²«×DOmý×Äî”-[6)T¨ÿ ¼œÅØ]¿~ý\göîÝëÚö܈tyžå‡kÿý÷ßwËê™gž|ëMÌ0^Ïž=k’‚Õ‘#G$W®\‰]Êó$(=€ÔS.ÇÓO?] qÿò!1K“&™]¸€×_}bÉyžH€Ü óƒZœŠ¶nÝjÎA¦¡Òš5k&wÝu—* ¥q»ÆßNáÂ…ývC˜6¨•,ù½Ê;þ¢Ç¿—[o-$µkW’Ì™¯bcy Ýëʇ$@$@)ƒbºÃi z¾œíñqá<hBs"Ä'œ}ð‘Îú‘²Öê5[·n]£§&ÔF$@$@$@$@$@$@$@$@±B¡²ò#FÈÝwßmíú\;V&Ožì:|¼}—[·n OËž|òIÃÚÇÚ3MçÎåž{î1Ið ¡®`¿þú«Y[ÿÔ¯_ß­“äuÜÝ:å¶Þ´i“q¬Á˜ü… ÜÎeÈÁL^D›‡ âÊÏ-‘î8Íɳ¼ÄöwìØáJræÌã@•>}z×±@6Š-ª"¥äÔ©S&yºté|^éò|V$‰'ð·`Ùª„€¿›@ l1ÉÊö–AСfÍšÖ.×$2Žt ¾¹zKNÖXˆ:Ô˜AI±qCCÈÜlo¼ñÆÀ.f* ¸"pñâE£èe„tÁróÍ7'hã¹sçŒêú–.]*PTË;·‰A '£5jøÌMY€6o5JôðòPhÛµ+›¼ôÒsêlt«4o^åòIn‘ À^xáyê©§ÌœbÑW=øàƒæ#^a6lаœÍËf Á‘ÖúaDøÔóµ×^‹p©,ŽH€H€H€H€H€H€âŸÀŸþ©“UF‹ l! 8@*-v'Š@D2Pß~ûÍí:ŒGy3D÷ùì³Ï\§ð­ÏÓ<Ó`‚Ÿe³×Ï:Žõf HýgåÊ•³6]kŒ¥=öØcÆaéÿûŸë¸}Š5ÈËâÅ‹MdoãïNs²×)íâÅ‹G-¤…ÕªU«róÌÛî€ãyξéòìe‡sO–á»."NjEŠqû[üå—_èp(<¦óKàJ¿g½œTg£~êlô‘ž é) 3ºát„›í”)S¼”ÀC$@ñL÷(*@ºoÞ¼yòøãEÄmÛ¶­@põêÕÒµkW£š­\¹Rš6m*ˆ¿zàÀ?~¼qRò¥‘~ƒ‹L›&êížK–,錗|óæÍÝOpH€H€”ÀÛo¿mœà˜:|øpó²‡þªzõêFݳŸ>­|ùò‚Ù#ýû÷7Š}ÉélÄŽH€H€H€H€H€H€H ü0 ŒïÙW_}µ+VLùŽ~ÿý÷ðÆI€â–0!ßîl'“Ò¥K Ô}Ò¦MëÖvDë(S¦Œ|ýõ×nÇ£q§bÅŠnÕzøá‡Ý°ÜN†a'Òå…¡Ê^³°;a\5Û³g[r8 ÑH ‚R8Ò›WyUî­àüùó©¹9rHÖ¬Y|ÙáÇÍþø¡pd7Ü1 Þ™:t°Ÿâ6 @œÀÿûV­ºÈŒwÉ5×ôSŇ›¥Q£•êQ;ßx^#dË … ÈV­Z î-Nƒá¨^§Žh8§Kcþ$@$@ñB`öìÙæã!b/\¸Ð8áƒÀ–-[äƒ>Ð~o†ªç©|žZåÊ•e„ r bqÒH€H€H€H€H€H€H€â†&ÛŽ=Zë¬V¨aÒÞ½{Íw| €!œúwÞ©ßǯ„²¤Çd[K!9n °!$ `âý÷ßo(`\·–ÍŸ?ßL¼Ç>‰ì†oŒ/¿ü²ëÐí·ß.¯¿þºØg0æ¶uëVéÕ«—,Y²Ä¤=qâ„™ôøÍ7߸®Æ*Uª˜û¥U7øTªTI#Œ48U­ZUÒ¤IcNò:Òå%¹Â>2ÀߢÁÀ‚QÐû믿ÄS Žk4`ŽÒêð$}ØIe|ÕUWýݾ}û4÷Þ{¯ñ¤´Ž{®OŸ>-‹-’¹sçy4»'&_ðŸÜ[8%Ï|¸O$[TQJ–uBÓ"„ÌŒïi#Æ¡… ¯÷Þ«¥EµLà ;ùÅKe÷aÆâMBÒIûÌ3¢/‚N–¼I€H€â‰b§CJ9W®\æy×.c §"¨aÁK>>6jÔˆãé€m!     ˆP$Fˆ™»îºK'¤7#Š"P2€.&$Íœ9S'¶êÌV5¨JàûÁ²eËäË/¿”1cÆxeµ{E?ÿ\T„Á{U×®-jœÐló­åºëDj×vO¿nÈöí—Ža®šg”-e¸çti/¹ÊðVëb¶[´¸†øEÆŒLÉ®Ó ßí†o‡×_½ýk{š†â°K²dÉ"Ÿëï91_#é\I3¡ÑB0ñöí·ßšû îeÑjÍš53bˆzb0ßyç³àw®V­š¹ÃyÊMIq@ŠtyV›Â½µèׯŸÀéÈ2¨A@†Fá °Ã‘ª=­º¦bëMnã‡~¸û¦›nj’XE  ùH,x`ƒ¢:n–Ï>û¬ë&˜X^ä†*Ñk¯½&P) öwÜ!õë×7KáÂ…½Vã[˜\„1®‰'šë  “ZŸ1ß ¬‹n¼ñFi×®Yp NMP4€º}Ù¸q£Qü·®ã:¶<÷œÈW_ùªó%ÇY³.Ÿ‡³‘§ÃÑÔ©"cÇ^JÓ§OB‡#ÿe\ÎÛÚJ®2¬ò½­áŒ‡%Ã÷7Ë‘/”ëcéšï¾ûÎU]LÎ÷t6rüo£sçÎncí¸ŸD³ÃÔÜ.îØ±cƙʳ=¸/ã÷ÆK¯ŠPy‚z< §Â(ž—ùÜty>+’ 'ðÿÍÓÑõ¥—^J†š°Èx%¨ÃÑ  ·A¢ŽèÒ@ž·ŽºFˆ¤éÓ§KÛ¶m]ñj1X³{÷n)P @ Ù0 @P¿B}I¥zhª)?þ¸Œ7NžkË,}¢N—îR\Yo“DRë]éçŸE%&Eà´¤“:h$@$@$u~ÖΪnݺ&lð_|!·ÞzkÔÕ‘"      X!Å8å@è]•I…Ë0¨†` ¡Ï*T¨`TŒ±jDK—.•ž={J±bÅÌ·í .Tú­!€.^¼hj‰Áo|GÚÄÌß„¥Ä®åùè%€èWÇ{¯ß‚ tö)yà\ <"h™ã]ºˆÔ«w)‰·ymþÊpelÛH®2lUàf)ß-Û¶m›ððrj@ˆ*„û,¾U¹c†¸w¾úꫲoß>«É ÖPçY¹r¥YšáÄà|Ö­[7©Q£F‚ôÞDºùä³`RèT•ËéÍÃÎ#H—çQ|ÄvÞ§^ÏnpD{ýõ×퇸MI&Ã‘ÞØJÙKÒ‡½iöýP¶Ë–-k!9 Ã>H ¶ è3‘=rDä£DãR”—Õå¾jÕªæÅ ’‡Ø!¢^Ê"£G‹J>Š4l˜ð*8ic2Ô”~íyÕ[S•[£¨”0µÿ#{öˆèó¾¹ÞJž% ˆUøxþüyŸqÑmâ§ãøäÉ“2eÊiРA —2 €ÀÑ£GåÑG5Uv NFP¹xÿý÷%C† 2aÂ[jï›:9^®¹æã4ä=…ûQŒIMš4I'»öU5šã&T:BÍäÍ›×-!ÊÇ;¿õÞ¿G?"gVÉþìÙ³»¥ã @pªT©bV‚»êRêþ¼±BÉ0Нjšåp„j¾ýöÛ:Éa÷ÐCIÉ’%£¸öÁW êC÷ªGœôV¯^-k×®ÕP…_?„¼ôfPªkÚ´©,Y²Ä„¶ô–ÆóX¤Ëó,ß©ý'N˜Ðœo¾ù¦KÏ*ë~ -ƒ0vèßh$N9©ƒ‘ÝáèŒzþ–ÔJÀcqo-I8xöÒH€b—€öaFÙ GúÜ#?ýô¼Q2ƒ -‚‹:PƒZ®F^”Ò¥EetEªDˆÝ¯ÖwNs\•õ¥ï’ÓQ¨^^yEt‹Èºu"åË»—Ã=  Ø'G#¨ARC1<«Bbýã?Ì^Dˆ`Ìž¡‘ OJmt&)“að|¬ÊØÃ¡§bÅŠ:µ¡Lœ8Ñ„ÌAˆ o†‰@ýû÷7NIp8Bº–-[zKê:†°D:u’U«V# ¼6nÜØuÞߢh$@I'pÓM7ÉcuAóKa°p¯²+Ô8p@^|ñE³äÊ•K'Ñß!µjÕ2ß(o¸á¿ùÅÚÉëuP÷të¾~úôi£:‡ñF(ϡﰭáÛ-³B±H—Jý]g¬·ÞzK(pæµ[n óÒK/ÉÃ?l?Ìm+ÉIcü°Ò©÷·º„ÇŠ-êʈG.Ü d%€Nr…–úX •QuY©_ÿ’Ú>ëÈéÓ¯i¨³§Õa¨´‘?„ƒa°† %:¡ÅÄ<~ðAQO\÷Ú·¿¤¢‡#˜Š¦©‡³ˆ†$ ÊΜ•Z)¥n•t6 “ @ÌxE=Káä¾wï^UÆSi¼ máÂ…fÖœš5k&›7o¦³Q ™œH€H€H€H€H€H€@ap>­N:rF?ÎBÍ œ`Y6{öl3Ž÷y º{ÚG*¯_¼xqAx¡Jcê¢~<†ÓÒ]*—¿}ûvÏärîÜ9yæ™gÌ÷ê5kÖH÷îÝåÇ ØÙ(A†<@$@È’%‹ 1V»vm¯%ÑP#)'8DBýiذa œM¼^ƒ1ÎQ8£bB)œkà$d7¨×mذÁ~(äíH—rEõBD‘Bd)ü-ØšÇ~úé':%0¯M”@@Gªpô‡•“nç½îºërZûIYCÍ2H—ÑH€’Ÿ<Ëï¹çãmÿ?ê¯fêZô=MehE²d™`â­Þ|óÍæa(kÖ¬þ.õ{ʉúî©r‰"$LÚ¼¹h¼ÚKÇË”Á˪è€rÂtþŽ@II'Ãh§ë/Ï‘ Ä*ß~ûM†î’V‡Än †Ÿx)ƒ’ÑYõ®}ï½÷ŒÂQŽ9Í‚éH€H€H€H€H€H€H€”ÞÏûõë'ùóç8ÁQƒ¤pò´ôéÓ‹ò:CôÙgŸ•‘#Gš$d®W¯ž ,ÌßÿmBé;v”/¿üR'––2“añƒ’Ò-·Ü"#FŒ0믿þZ^ýu×w“ˆÿ ¤8Ö="š§£E‹¥#(ÂåÌé{x nƒ6N8S¦L [³¢‘SŽsÙ²e Â\Ú¡Â!ÒåSo„NC¤ÏI¶P¾‚óÔ“2NL]˜6åÈáHñ¸é’ih¤ŠIE†‡A»§9ãÞ&•(¯'¤ÀË×|`HÐQ#,deýÙꎨ㯢awÕƒzª˜-R¤ˆ‘6ô÷ðã/Oû9}T]Ñ—JQµ$û÷m(Á‚u^7NôåR¤U«K×ó_  ø"ЧO3cÎBï µ¢@ /f˜-‰’P5jÅÎ"PtLG$@$@$@$@$@$@†ÀÆ¥uëÖR @ã8„0åyƒð7þ”A]“†à@G%¼“CÁátãKmÛ¶5e`|i„ ²víZãTôüóÏ &Ä6mÚTî¾ûn9|ø° ¹†èÛo¿¿ htã1C¡jÕªòÎ;ï˜{ÙW:Cÿ¹çž3¢pÎô´¿þúK:tè óçÏ÷<Ò¾œÚµkgœMápú B´B… õ:ûåëׯ·ïšíH—— 8uê”4iÒDºuë&çÏŸw•P¬X1ÓOb¼÷Ö[ouç 8I ‡# ©¦Ú%—MUŽîº¼Úmàtd6i$@ÉGR×®]Í`,âÂ"¬dlyäiР:tÈkåà(­Š´R®Ü×Ò^ãœ!NìÒ¥K%Ož<^Ó{âg3f@9IôERDCÔzµPŽt2‹|ÿ½è ¯h~ÖxdC† 1 G˜ùÇ@ ´Î›7ÏÌ AllxÍîØ±ÃÌ@ùðÃõÜuR:©²|5“œ ‹NS&UZÑ´:kÅ{Î*ªdœ†‚Q8‚º¬K—KkþK$@$?ðbݽ{w¹êª«ŒT;Z†—-¼À¢¯JÌ>þøc“3‚ÔÙ>±äãÇ´vƒ^C5Ïn2d°ïšíH—— a>§Z8ÔZ–+W.3f G4„£‘@¤ äp¤•ÂÓåëVåtÐåJ]¦¼õÖ[7ZÇ]ÿùçŸòØcÉþýû]—à?BEÄL¢‘ $ ¼|½ð &„š]¾q=§Nj:.¼¨!66bÆbFIõêÕåиØåtÖKQ’Ù¼4,XБ6¨2 Àáü³Ï¼g¯ŽÝ¢ïÃF±È{ ÷£ê÷(ê?%wÜPpîç¸G$@$û&Nœ(˜ÑÒ»wo¼.ìž{î1kH²'f3gμ°VAÌP Ä)„ßÁwßaÆ™o¿PÍÀv(öË/¿˜÷è_|QÊ—/o‘âŽLI±k®¹Æ„QK—.]ÀÙ`€¹råʧgB Ø$É#|ÅO?ý”hCààrðàÁDÓ%W‚#F˜° å¶@ !*{ôèá–Ô®öMœ xg7„Ù Õ ¤`7O$œ‹työú„{íµ‹ºd̘ѨÒÏ"ܤ™_0u8Âlð—5ã=Væêp”êå—_®Ú¸qcÊIb2›¿ýö›qh€“TSìÖ³gO3ûÜ~ŒÛ$@‘#ÐE%~.\¸ ãÇ—Ô©S'(q@·lÙ¢J@]2}O=õ”‘¥…â¤qþy³ìÙ³Ç8"%¸8Œ²eñ÷N åD„Ýݽ;ñB­Pp;'ž–)H€H€b‹¤~  ùòå“§Ÿ~ÚUy8Å-ZÔH »zÙÀŒ |œhÚ´©@ª˜F$@$@$@$@$@$@ñHîwèŒL¨ü¶hÑB¿«î„§yöÙgM¸ž`ÚŒÐ8ŸÕ(­^½Ú5(˜|˜–H€‚!‡D»AQ-1ƒBL4[žøàW®Å‹Š—ëBn@˜ ìp„rU¦k£†¤¸Woˆ©ÓÑe·H=ÙÍ­[·š%Ð:ÂËðÕW_åÌñ@1 „™À‰'¤W¯^êT”Ë(YÙ«°ƒ*—‰JèŠL˜`u_Ã6ÚBZGp`÷çH‡*„„íÔI$M÷vqH€H ¶ @*áÔ0C¡?=­nݺÆáháÂ…~Žà@ïmFŒg~Ü'      X#0kÖ,iݺµ™$ŽÁKûû3&–¿óÎ;‚赆Áyoªøh3ÎuìØcGR¿~}3Xœ3gÎXÃÁú’ Ä0·–[n¹ÅDé@30 bpD±;ó`-½{÷–þùÇÜ×.^¼Ñ–ã{£Ý~‘DtÌÝ~XJ”(aBQnܸÑ5j”Že¥1Ž¡X{? 2cÆ ×)|µ;8E'´÷µ×^3ΩaÉÔNGPÚC¸°¶mÛ•zo}ϱcÇLä°[·n«½Ø€ÂizZ¤Ëó,ûh¯·poÞÒzkÕª•qÐÂwo¼X§:Feí½¾ï¾û¨D45^à@PGÈ@ÿ¿ÒðE2dÈÐ󪫮|þüù´Þ2öw á-àäà)aæïž#?t¾‡6³O J¦Ï#*[(¢ÎÒR£†¦j5¹õV÷²õYLnº 2„¢ƒ¶îç’suBÈ5(ù³9s.Õ <4  8"ðï¿ÿJ÷îÝM‹|I##¼o:í,àp„çQOƒ|/©av¦ý¥Ü3÷I€H€H€H€H€H€H Ö`pJF#FŒ„×™£JË—/Ÿ 5’'Ÿ|Ò d"<šç€&¾)ãüûï¿/éÓ§7{¬÷ñ™ñ 8LßøÚ·oï*eûöíEŸ £T©R'ˆf?~ܤ¹úê«5ÊÇ@éÛ·¯ëšHlÜ„A,›Íœ9SP—üùó œ?†nÎâ›$&TV¬XÑ8†Â¡÷mܳï¼óN£\„¶Á¹ ß1§M›æv ŽMÞ"–D'Lôœ4i’<üðÃ6""/½ô’YÒ¦MkÚ g2(Ø£ø]9â–ÞÚƒ~S_éò<ëñ!TB´Ûn»Í8A±ßnˆ^ƒ%TƒBÑh$TA;¡Àýû÷ÿ¥«º.­7ƒæŸ|ò‰œ;w.ѺdΜYE:ÏyÜ(’Û,¯Ix6zó’ ¥~àpòäIÉ‘#GØò´êádÞV\§ˆû:Aå‹0ðjuèï½'¢¢GFÙHm5^·HÏž"Ë–¹s™?_ä—_D¢m²Jj½£ –x85m²<þ¸¨÷´{»¸Gñ@€}[<üŠlC(ðá ]»v²jÕ*u–í¢Î²Þ²ÿeŠ¡èû0 óìÙ³¢NônÅ1œšî@T`ß?+A$@$FìÛ“Y‘ L`ÇŽ•„o¿ýV0x‰Ðg˜îË –±víZ²j¡xU„öÁ .ÆA j„ ?ø¦‘°ãßArÀ7A|çƒã#&$Z¶{÷nÁb7(Áù÷³Hïêøº«h(ûÀ‘æèÑ£®cØ@X5Ük‡é —Õ¦@" á[ç»ï¾k"›¸e¨;ÑÆ J{P¡zâ‰'ÄRs²ê|Aì`b(†‰¥p€:th¢“G#]ž¿z‡rnçΡ\ÆkHÀq!9YµR©®óˆí‹âLîÝ»×,¿þú«X®ÒÁI(!!LÖ¥K—6 ö¡ŠœD¢¼Ä”™¬¶³Æ·o,4ˆ6aq8жF%VÄèD¤bDÂkÒ.{ç/¿e“ªY³fFI ÊGþÌɼý•ËsñOr¦M›6(A@b‹e:N«²¸ÖÞ¥5þTòÉ^}UDÃuÓ¾_ewÝÓrH y °oK^þ,=ò * )ø%K–˜r̺´4ðW£bÅŠ¹÷… º%c857Ü!d'À¾-ÙV€H€H ÌØ·…(³#8#pñâEù裌jP¦L™‚nÔ‹nÜZ „µ J#ŒÌ˜1c$sæÌAç[«V-ý6üªSA˜5¼SÓHÀ“û8O"ÜONpJÁÒ¤I“䬆ϲS¥J%PèÁˆ!}ƒ ITšhã”1cF©Q£†Y‚jHˆ‰#]^ˆÕäe$õ’âp”jåÊ•ÙáY¸nÝ:#A—5kV¯ †Â¼5ï¸ã£€„èÉeçÏŸÌZGìÇP yÀÓÒîl„6U®\Yài ÏÊ'N.|ðœ>}ÚµgÏãýéQ_^—Næj{y]|€ ^,¡æ€Y-P7 Ä d¤Š»2b„¨“h˜™@®Jþ4ê[¥žëîõÀ{„ÆU‡o Äömqõs²1X»v­ù`§£Ç{L^{í5£pÀ¥®$P97nœ™-c½ÜãÃ.fU«VÍ•Ž$@ÉC€}[òpg©$@$@Î`ßæ[æLÑHÿçñýµE‹&tO u6l˜<ûì³õ‹ùóç Ô…³É“'ëwÛ&Í™3g$Ï–-› ‹†z$Åzôè!Xh$àû8oTxŒH€H€RPŽ®ÐAÈ¢ èСƒË’o¾ ƒAêÄÙ3 â ôt"eþù§,^¼ØÈ&ç2±:a0Ê[17§hŒ©²e˺] iRÈ¿!´‡åœ´jÕ*Áìy_øNæíV9î¤8]ºt1/—PÚBÌî@MUreÔ(Ñ™5¢ñ½Eô6ê NëJ\ÔÇÏÍ–/A4¿cG·SÜ!˜$À¾-&6V: à8‹¿<75oÞ<¤-‡#¨ÁáÈ §†þ’áÔBBÊ‹H ,Ø·…#3! ˆ"ìÛ¢èÇ`UH B T„q9sæÈŒ3dýúõ‰N’Á˜B†çÑٞخP¡‚Ì›7ÏLnöVm¨uëÖM&Mšd®Á˜KΜ9%GŽ®ûÕ«Wè8Œ·ºòXü`¿¿-[v™À©S§.ïèBKÒH€H€.ÐÀH›J«eÓ™OUg¤..g£Às§3B_ žåW_}Ì¥A¥E¬ÌQê%‡îzõêIÅŠ5Tó°TF‰¡Œ4qâD·£˜Aàéld%È—/_% Žy3'óöV¥ˆ« '£»ï¾[¦M›–` õ‹/DgÁøæ¥ÆÚµEcƒŠªHøN-gtâŽìÝ+rô¨{>ûìÒ¾Š­ÑH & °o‹ÉŸ•3/´Ó‚rfçÎCv6B•îºë.óÀ «Æpjaþ¡˜ H€}[€ ˜ŒH€H f°o‹™ŸŠ%Gà€èp6Bè±­[·Jß¾}ý–…ÉÜ<òˆàZ(!jÂQý° '¢ $¸v÷îÝ&Úœ0™e@Õ¾¡.î~R6(›7ovKÇP ÀeÁ8]©aÖ«£‘êœ$ÝþøãóàíËù&©% |ƒ j„°o#¾R / ˆylâ7„ô‹ƒ3Rùòå])Ð9í۷ϵom8™·U×)¤{1;¦R¥J‚ð†žÞ×ý%rß}"-[úg£aºUÎWäÈÿé¢ál™2—j•#»iØrU±)^Ü~”Û$;Ø·ÅÎoÅš:GàUí·¼;b~&Á2eÊ$P£\®òw˜ ‡#|ˆE` @ä°o‹k–D$@$ìÛ"Ù¥@´@Ø18þ4jÔÈL~†ÂÐo¼a‚|Õù•W^1*HO>ù¤™Ø u¤¥K—U$Œ=Œ;Öu)TÊ•+'›6m’!C†¥ìÙ³»Îsƒœ$À>ÎIºÌ;š¼õÖ[FГøGíªZêÔ©Rºë7H€H€$`‡£¢E‹¶P^ênpÙÒ§O¾£Æ%‚bŠ¿‡Ú|ÐÄ®R¥Êå‹u ÞÐp„€óQ¬ØêիݪZ³fM·}_;žm÷63Áɼ}Õ‹Çã›T0ƒ¦T©Rf6LÆŒ4X}òäìÙK!Óœ´(QâR˜²áÃm£tSo9öPDýÝLqèË»Û!î ('û'óæ—òüøã²hÑ"iÚ´©¨òf’Ô­[WþRÏ[|¼EÞ÷©.é%+3 ¨ àdÿãdÞQ•  ˆJNö?Næ•0Y)pˆÀ€d̘1FQ÷Ã?4?á|”5kVi×®NäL8““¥,:þbÖVÕ0ž°víZ)T¨tíÚUz÷î-Ï<óŒ™üŒ÷VŒ/à:¾ÃZĸŽeNöCNæËÌYwÿÞÑpo¾ù¦µ° ZÀ™4W®\þ/æY HaRØ^8& ¶§Ug¡Ù*ïy1oÞ¼ÍíǽmãòXF ¡Í>l’ž9sFÆg–½]ê1}\u›7Oô±6,å2 ËØ·±o»ü×À- ˆìÛØ·ÅÇ_2[,Œ7 ×™š*T0áÔ®ºê*“EþüùeüøñòÀ˜ˆsçÎue÷ÛG}Ô¨î"<šF˜pÃFáÂ…ÓQãÆ*H0Œ3@¡7“pL†ü‡‚ À>Ž}\.q—ês“'OŽ»v±A$@$T9)Räv-È„è'õèl©ÎFo[Ê•+Ë'Ÿ|"õë×—'N˜Ë“Î79}y[ˆ¦‡3ýôÒ^<:>-êl%ÿ\TzXôáPDè«‚…·I@ŒóçòåË](Ð/Ùã2»NÄ醓ý“yûsÀÉ÷äÉ“®¾ ×Cm‘&Á’ OżR8 _}õÕFe¨GrÛm·$ÏRðqÓ!Ç pfšb–iÛ¶mÙ-ó"¨ °yóf’*lãÆrüøñ¨¨—Ó•p²ÿq2ï`¹œ={V°Xïm¸N”VøŽ`ócz ˆ˜°øÓO?™ªbÏø)ÁœìœÌ;Øßæüùóæ}ÜÞ·Õ¬Y3ZL°ù2= „›Þi1wZÀ‘väÈ‘‰:Ý[ÅZµj ”sæ 6_¦'h €YË©öСCÆ9%êåtœìœÌ;X.p6:wîœÛsÌwÞI‡£`A2= @LÀ ¬õþ†»Ó˜m”ÌÉþÇɼƒýi0ÑïãÖoŒëNÙ3Û¶m“&MšÈŽ;}¨eÈÁTRÅ]ºt‘víÚ'${-!A†:؇m›ÎFaCÉŒ¢Œ@³fÍ lÞ¼y2þü(«¡3Õq²ÿq2ï`iäÌ™S²gÏξ-XpLO$Ó0!Κ·bÅŠDÃòÆtcm•w²ÿq2o[Ú„Ê ÞÇùÞ.&Š|›=räˆy1b„ù6‹ÉÔ½zõ2 Gx Æ(/e$¼ëÒHà.ý€5ˆ!C†˜í”ò“ý“yûû)Rļ¿AF$@ñN B… ‚¦B6Ò±cÇxorŠnß•´^ªZéÔIè õÖ/n퇺FGù@Ë|Å6¶ÎGÃÚóá$X…#OiT»4¦“yG;Ö!4’~ðÁ³Qåʕ͋(ö?ùä3 ‹^»AN|Ò¤IFš·aÆöSnÛ]CÕ’.ŠÇpjh™N0’‚E â¤Å76Ü!”FÀÉþÇɼSÚïíEß…— <ÿ=ÚHÉ[ÎFh_gõ€E7{öló‘eHÂ7„< öÙËʃk ”EÀÉþÇɼSÖ¯ÄÖ’ CÀÉþÇɼƒi#Ó’@4€jQ·nݤqãÆR¾|yÉŸ?¿Q™¿æškÌ÷Ö… šphø;jÔ(ã<l½1téÒ¥òã?†t}°å1= D;'û!'óŽv®¬ DŠ@  G—‚ìýW+õ9ꤛ%¥’›6mr»üÚk¯uÛÆ»"êç+¤•¯ºÿý·K(Ê$±+9™·¯úðxtøã?ÌËíªU«ÌÌô÷Þ{ÏHóN:Õ„~Á>ÔÆŽëjH÷î£Tzúyyþùê®cÞ6tŽ 1ź·V¶¬¨“Ö¥æ5h·ÍdÃH IœìœÌ;IæÅ'9ðV­Z‡!| Eø4o6qâDùþûï¥_¿~Æ9 ζp>ºòÊ+D½·kxŒH€< 8Ùÿ8™·g;¸O$@$@'û'ó¶êÏ5 D;D"xúé§åí·ß–ÿýï’&MÉ“'@-ù¶ÛnŒ]`»~`¼õÖ[“Ü($a¡‘ úÂåH(àÁq7þU @lÈáHcg/ÖNþOmZ&4OÚi|ÑÙ¡6ðµ[µjÕì»Q¹+W.·z'j5v³«:9™·½LnÇHêÞ{ï½òì'éÝ»·¼ôÒK®o„}ùè£Ì î¸qãŒÓÑÈ‘#UŠw•.ð,+ÿüãþîÙê?>\L¸µ´i=ÏÆÏ>ŽfÎ)]ZD#ÒH€¼p²ÿq2o/Má¡(&°zõj§¹oß¾>P}8ÒÎÔ7f’Þÿýf{îܹR¿~}î5Š›Èª‘ D'û'óŽ"„¬ @”p²ÿq2ï(ÃÈê@p.ÂÄ„8ÂäO„µÂ¤—’%Kº¾Å&¸ˆH€ÂJÀÉ~Èɼà ™‘ @ (¤Úž={Îiß²µ3Î4Ÿõúë¯ÆCy0†÷öíÛ»…S+P €Ü|óÍÁd“,isæÌéVn°GçÎãe³Çwv2ïË%r+Ú \¸pA¦OŸ.+V41-ÇŒ#/¿ür‚\Ì€ùôÓOÍ -œ‘†*-[Öæ•SÙßrÇþ[ŠÐâªú+õêùOëg«V½·ˆ²‰õ–°þ$à'û'óvŽsv‚ÀòåËM¶w «W¢D ?~¼ìß¿_Uøî4³K{öìéDµ˜' @œp²ÿq2ï8ý9Ø,  0p²ÿq2ï04Y€cÖ­[g&» ¼7Â}Ϙ1Ä:+UªT‚o±ŽU‚“ ˆ“ý“yó§#  ¸D ‡#$U•£¡ÿþû/<Œ©ÊQú7ß|³"âCjt×®]Ö)¯ëmÛ¶É€ÌÀbÛí©§ž²ïFívRN~ÿýw·¶…ÓáÈ_Þn…r'¢-Z$P²ª]»¶èÿ3xê­P4êß¿¿äË—ÏÄÿ믿döìÙÒµkWoÉÍ1¼/X°@Ê•+'C†ì—#Gš©ŠÏ=:›ÏkRÚ §mÝ*Ò§OJk9ÛK`ß8+¦ À²eËÏ=øpˆµnÝZ:tè èK«L]5¹ŒiH€HÀ`߯?  x#À¾-Þ~Q¶'9 à;lÛ¶m¥R¥J²yófÒãPÙ¥‘ Džû¸È3g‰$@$@$N…TCú ~Rè5Ue£Eêl”ÁªB>Aa ä sçÎm”²dÉ"§N’C‡ÉÁƒÅ—P‹-¤zõêVvQ½ö|ðA»‚±¸’#,VæÌ™]ûNæí*„%€Ðxy…jBÉ,Y²DÕ‡º™¸ßpÔkذ¡qÔƒŠ“Ô¡OŠ)b^rq]Ž9­oš4™¥D‰ÕòÝwéäÊ+Ó|ré:Ñ˘€H€\œìœÌÛÕnD=<~÷ÝwÒ¨Q#í£ï¤TIÓÌ*mI™º¨ÿYAˆ6Nö?NæmY ˆFPZdz%¾£ Ü|Á‚£±ša¯““ý“y‡3$$عs§ >\Þÿ}L®–:uêèÄÍÑR¬X±$äÊKI€’JÀÉ~Èɼ“Ún^O$@$@ñB `‡#4XUŒÖ¨CDcuŒx_Žr{B8r䈪¬ñ<ìsÿ¾ûî3¡ |&ˆ²p¦²Û† ì»~·NÍî „ÙúÊÐu“y» áFD @Ž¿ù{ï½'Mš4‘… š0hóçÏ7j_Pü‚Áù ÿqÂíþ*¼e‹èÌ‘mÛÒéuÿÈk¯¥ÑdªùcÆs$@ 8Ùÿ8™w–ðH¤ ÔYÓ¦MUUïzùøã-våÊ•òÏ?ÿ•ËDÛ¤K—N&L˜`;ÂM Œ€“ý“yÖ:¦" ”GßV>ÿüsãd„É\˜àKŸ>}@“µâ˜“ý“yÇ{¶!ö ìØ±Cž{î9™>}ºy7Å÷×ÁƒËwÜûc H 8Ù9™w gH€H€H ,‚r8B‰?ÿüóbõ .¬a¢ú¦M›¶ÿßÿtPqyòÉ'c.üðCmÛ´i#xš={v¢EÀáÏ€%J”H4- @88Ùÿ8™w8ÚÎÿüsùã?${öì^ó€Â#”îºë.¯çyH€œ"àdÿãdÞNñ`¾$@$-Ο?o”‰Rá#‡;räˆôìÙÓ|k|饗ü¤L9§œìœÌ;åüBli´8v옪Ãw1Añ­–F$ýœì‡œÌ;úÉÆF 1¦Ö®];·Ê>ôÐC2räH·cîht#Œhz+Ä2ð3W®\‚&øžyï½÷šm+¿5ÔÝ!@a7DÚ²e‹d̘Ñ~8¨íŸ~úÉë·UDÒˆ7ƒ ÂàÁƒ½ò{,gΜR¬X1Áÿ›2eÊöAD—íÛ·»òE”#|G¦‘ ¤–Ôê¦È õt@V.\¸× 7ÜP‚'åpñÛÒŽ;ºöÙg³®.^¼èvüÀòðÈ \Ç•­9æ:à±ádÞEq7Ìà„ÖWã›A½ê•W^ sî—²KŸžÎFŽ€e¦$@âdÿãdÞüéœ#púôiªÎFÍš53j––³J…j%ž}ðéËN æJÖWz' pp²ÿq2ïp2`^$@$MN:eÂìV¨PAàPäÏàl§(kBe“v‰€“ý“yó÷#HèÞ½»>|ØÜ?0AšF$œì‡œÌ;6èFw-áƒñTû2yòdQ‘Œ*þ×_¹åeÏ×ßöþýûMDŸ¥K—šœPÙÄ·PˆHúè£ù¢xVöeÃð×V_çÑ{0î •@<·óÍ7¾Š1Çÿýw·²BýÝü“$@QMÀ(Y5T¥"8 UUoŪ&c”*ùlÔQ³ufúì_~ùe³•.¥¯.!ä¬N3÷Z¡ãJ•*%éÒ¥“õë×˯¿þê†Jº!IÒ¤IãvܾãdÞör¸^ÿh¼³Ö­[ ” ¦N*™2e oÌH€&àdÿãdÞcIÑÙãÅ/”O>ù¤™QEK»áwÅ3ÍÌ™3 ’ýœµ½lÙ2É›7¯Q‡´ŽqM$@‘"àdÿãdÞ‘âÃrH€H ÒüqÙµk—)¶Zµj²xñbÉŸ?‚j üÑ´iÓ÷Úæ”xvããdÿãdÞnà ø!‡­[·J“&MÄóÔÏe®SŸ~ú©|ðÁÒ¸qcÜu‚$@QOÀÉ~Èɼ£l”WÊéÞ&3™fÁ‚Fa'9› cäÆ*LXÊ—/tu0™óú:ë\Ÿ\†±îŠ+¤gžy&¹ªÁrI€¢œ€q8Ò&¦Ÿ? ñªŸrÙt¿4u@ªÎG;õÌl8 íܹókÝþ÷rÊ”·Ç¡“'OÇ#«õð~ÅâÍÒ«4͘1cä¶ÛnóvÚ혓y»İ€¼÷ºuëŒÂQÕªUÖ/3" Hp²ÿq2ïH2JIea'sæÌæ…ÒÛ‡^Ì4‡rÑ’%K³Õ‘Ön˜Ý‚ÅpÈ¥‘ @rp²ÿq2ïäâÅrI€HÀ)pÀD=„¥¨[·®ôèÑCðýNGª¶î*öÌ™3&ÆÕW_-o¾ù¦ë87.p²ÿq2ïË-à x'€ÿÿ¸GèÄg¹ýöÛB”5 ZwîÜÙ„Ã7n\ —1 @p²r2ï(BsU“(Bîz3D–AH¯¤Úõ×_/õë×O48¡/Ù·oŸïƒÐ€eF]à€ƒÉ•Áœé½}; $mÛ¶™ï«¤õ—榛nò«@¶£P!ÅTl[†sƒ 2aÝ*UªdæšH€\ŒÃ‘†‚j¯²pÝ4†ä=: ÔDoõuÕ•J7t¿°®úèº~8¨iæÌž=ûZܤý)öØóˆ§mÄÛœ0a‚ 4ðBäËðbÔ§O)Y²¤¯$nÇÌÛ­ î„…®F- ”aÆ…%OÏLT1Qöî}iUOò<Ë} 'û'óO뙋„~ûí·F¹ʾ aÕ0»gÞ¼yÒ²eK·d_~ù¥Ùg857,Ü!ˆ0'û'óŽ0&G$@Ž€#:B™äÈ‘C&Mš$yòä1aÒÚ¶m+P: L™2eL  ß?ög£|ùò9Z¯XÍÜÉþÇɼc•7ë9O=õ”q6ªU«–¬X±B0¨ùðÃË /¼`î‰ÕŽŒgóþûï”>±üxžH òœì‡œÌ;ò¤â§D8¤[†È!.\0 Žá{ã‰'$kV·áj+yÀë[n¹%hGö£GšopŽ· } Ä^{í5ëϵ yÆaˆŒ2gΜ&e"œšeö<­c®«T©0„D{÷ÝwïÅ‹MhK›6mdãÆ’!C†@‹e: BÀ8¡­¯ñ¬®fý·¤QE£º}Ÿ:Á}ôZ]ìv­ïÔ¿>|¸ñЬ]»¶ùH%Ÿh78†@ž5©†›{·nݤ}ûöFÚoóæÍ&ŽçÙ³gM\OÈBßu×]&>}°e9™w°uazÿðŒ xøj(Bÿ‰C<«~mê9-:0Ä x @Ü`ß÷?qDu#ØC=ä·\ÈÔwéÒE>ùä“G§£Ã‘_„jfKüñÇ.'.é SZ[¶l1ŠAV»1±ñøñã®kP>Âóc‡¬$[çÌ™SæÎ+Íš53Ï©VÁS§N•_|1ѱÀÂ… • Ã‡›K-x{85<#¯^½ÚªŠckˆŒàù=wîÜÒ¢E —&¨‚Éý÷ßïXÙ̘H 6 ¸Ž<ªÿ·Þ8ඉ¥‹Þ+ªƒQÝn¢k(¹ìôéÓææ‡z8[`fœð±R‚Á›–p›“y‡»®)5?«Ãwª“Õ(5²f¨ä¸èÿ±”J™í&ˆ4'û'óŽ4§x-oúôéríµ×ÇimÄ‹§5+×øm-[¾|¹(P@n¼ñFë×$@$¬œìœÌ;Y¡±p H"(a`¢U«V ¾›A5êF 4»ï¾Û8#¥NZÞ~ûm(­'±ä”q¹“ý“y§Œ_‡­ ”Þ%1¡™Iÿÿ‹+&Ÿþ¹¹ôêÕKúöí+'N”:uê•y¼k¹k„¼éÔ©“QN?~| Å2 @”p²r2ï(ÇUÕ³«¡bPµƒƒÆ›-CXµäp8Bùó†Ðã-ƒCÔîÝ»¥xñâÖ!¯kˆJ4oÞÜ8Ó"”’pm¶lÙ¼¦÷v"Û·owB~‘p8² lذ¡éwí¿œÄœ µÊåšH ö\@•ÿݹsçZu@ê«K•O+¥Òiƒ5¤ÚFÏkámºdÉéׯŸ‘<…42fXœžé¹OÉE`çN‘òåE%“VÈ BÕ’Œ7ß|sÒ2óqµªÊÓO‹´kç#“ @ ”š>óÉ< x9NÌ0ûˆ,XàJúÛo¿ f¤RÝÈ…„$@$@$@$â`0 %P3fŒ×öW¯^]਎0'Hÿ´~¹é¦›¼¦åA ø$€Pj»ví’çŸ^ *äÖH8$bpçŽ9bÂÁôîÝ[î»ï>)]º´™ð|Ýu×™¨£G6gÜ2à @TÀØB`Z†Pº5jÔ8¹À!Ì28ØìÙ³ÇÚø}gd“}ûö%Z´ÏPq³gÏNô:{{85Ô}b¤­bÅŠnEnݺÕmŸ;$@$¾Ž|Òùå—_6ëI,ömÛ6kíÚµMàd´aÃQ'$×u˜Y çÌ2lØ0)Uª”Q>ÂŒ%ÎtwaâF2@ÈÑ–-EtXã¹ ŠEvƒ2Ñï¿ÿn 4`NH˜Ñµµ@YdݺuòÞ{ï™yÀŽì˜¤øÂ /سå6 ¸`<c¯½öš™ ì:Á   ¸&pìØ1™;w®«c»ùæ›]ûuëÖ•Ì™3Ë©S§Ì1(sÂqþv ìEØð<ŒúZ–JæÜxã֮ϵ%Ê1s8âÃfmÖ¬YÒ±cGŸ×Y'ìWPE¨9‹‡•&kÏjöß)å³  Ø 6‡#{s3eÊd$ï {wþüyY³fq>Âàä™ívàÀy÷Ýwépd‡ÂmÇäÏ/ªº '\¨t«—†õ4¾H ª?~ÜHúu`Wà9!Õh$@$@$ V8µ‡z(¨âî»ï>éÝ»· «V²dIÙ£±Õ;uêTLL$@$@$@$~˜Ø¡C£b Åñ™3gšÐC‰•„p 0Kbiqþ•†ãÑ7ß|cÖ{÷î5á/0@B# O«W¯6¡ÔªV­*¾B©y^Ã} ˆzªV¼V3—>¥=yRdýz¯ç5n­È-·x?g?ê§ {2¯ÛN•¡ÎAêÁîµHo§OŸ..\pzøá‡]ÛØÀócãÆeêÔ©®ãpnO‡£Ñ£G»ê€ H¶lÙÜŽyÛó= * pP·R¢¦ëp,„SÃxd$íôéÓòñÇ»ɨEn8¸C$ðGŽìt1« ÒÉXpƒ…êâÅ‹eÉ’%rèÐ!{Rn“@DXŠ»Ù³‹þMŠà/kÖà‹FÈ$2}¦U3¼*T(¨¢ðâ\®\9ùì³Ï¤R¥JæZ†S !“ @ÐV¬X!˜=]¾|y3 Ü3ƒ-[¶”(1+¼iÓ¦2yòd¯é<¯ e?»~dÁ` ø#Å´víÚ54Ü—®¼òJÉyŽH€b‡€†®•¯¾òZߦÖQüâÕ4D­ÆÐòzÊí Ÿ2ÜÒyÛqª b£²çÞJôzÌN-uêÔòàƒ&HEN»ÃÆã^yåAúH—A,ãùçŸwu£>}ú¸öýmØÃŸa qäÈ‘&9žß¡.ï/4Ùwß}'»víreoAÚótth߉á¶Ãö7™URñnA# O‘¹3ÿW*nÆ+V4 â²oÞ¼Ù„Þ€ó"MÀR‚ŠP°GÇ ªåìDÝ!& £‘ €ãЯaæJ°êFVÅ0ˆIü#F˜å5jÔ°NqM$@$@$@$F˜uÉ1cƘ\1XðeÖ77¬7lØ ;w6IãðÄO„±ÌŠH€B'€{B©A5¢¿i$@$/ºtiÔÈkk¾ÖÁ8\Ö¬YÓëy•Íñ~Üó¨Ÿ2<“&ØwªŒBŒYuùá‡Ìsªµ_§NÉ;·µëZתUKàÐMØ™¿páB]Ç•(À“ª:'žÄ Ê ûöí„ †³“Ýé×"håÊ•ËÆœÿ¡Uþ3„U³Ž ÌÅÑ®]»Z§¬íáÔ2dÈ`T•$ òÞü…dƒ3¡~ýõWY¹r¥Œ?^VÙnC† ‘œ9sÚq›H€ ˆ:y2GÈ ,øHB#§èû«Q±,]Ú½(Á𼤃|þùç¦sƃ‚S‡p é*÷ÞëT Ì—H€H€.@858‡‡Ú·YGx1½E% ½},¸\·H€H€H€H€B!€ÌrÆ  %6l¨“•¾6ˤI“‹eùòå XX ”Öq®I€H ¹L™2E÷®=z$W5X. 8Cࡇ|æ»Q8Žéì÷š}ûúLÐ ?et} ‰,în„ª´nÝÚkÒ¤Ic:ßzë-×yôõC˜¡¿f͹í¶Û\ù»‘%Kã$Û¦M›`/5éË–-klþùg³°j:Ý«„uœTƒ•]1*Øün½õV¿u6?¦'ˆ/Ž9ÁA ß|ÅWH®\¹LÜ÷k¯½6¾²5QM@•ÅUŽQdëVÑ¿G‘pà€`2^0ßÄ¡OŸ>òúë¯çp„a@˜ OË£³¬7nlÏsÜ' ä$€ï©À{'&rf 4¬OrVše“ „•À‚ ä÷ßwå‰ ýéü(Ô¨QCEòœêasÆs0`"ióFÝ/^,Å¡d‚ÙŽníã?öòØN ÊFP8JSß¹ù曥_¿~Ò¤I“ä¨Ë$ˆ!^Ž ,XUCj<¥í¨©@®ú¯=_éÚ¯ÃÑäÉ“MJ{lJO›6m,˜E˜•ˆÁI#§àÏëž{D¥þÂWœk×IÏâï¿}ˆyøáðÕ›9Å8ªUE4ž±è,V „›ÀôéÓ1Á1@•ëÙ³§äÏŸ?¨A·¤”ÇkI€H€H€H ¹¼òÊ+òÉ'ŸÈœ9sßÃ|…ƒ°ê%ð¾BcÔ¨QFÝ3¶[¶l)˜˜çË0 ƒ‰}/¿ü²|ûí·R½zuùàƒŒÃ’¯kxœH€¢‘BÇ`‚2îg+VŒÆ*²N$@$@ðT·+\¸°yÖõWl™2eäs+ˆ&DXµ`ŽªêØÊرcýcÎÁ¡éøñãòÓO?ǦU«V¹®Ù¿¿ÏÔæ„{ Ö  ô…08ß>ñÄnÙXŽHÖÁ ˜ïµÖ~RÖxxôÑGÍÑŠPO|ߥ‘ @ <ŽR)RdŒ^ü˜:%?ô´JÈàCK †u—.]LçÊÍ9Ðr˜.e¨WOK8 ,w2œš:KK&çåpâb^á °r¥ˆÆ– ‘ó  7¿þú«@ÊŽ´™2er;ì$ƒ}é¶ ¦'   ä&pìØ1ÃQ¡B…äâŋҦM9qâ„tïÞÝkÕ Y«]>@IDAT†ç"L`*]º´ÈÀ$<,7Ýt“9÷ ÆƒÏ’%‹t“ÑòåË]øñÌ3ÏÈСCE'z-ƒI€H Z ¼ûî»&„Zýúõ¥W¯^ÑZMÖ‹H€HÀAGŽ‘ùó绕ðÔSнÎV¬X!ø–‰ðœ¾W–D8‘ ŽEúØcÉÛo¿íº åBa Ïí¡¾½<Ø\ºnÝ:Ù»w¯Üpà ®¬¾þúkÓ6ë”Ãe:ö/­Zµ Wv̇H€Ü\ißÓÎ[êgÔ)Xg#ÈÈùs6JŸ>½½×ö÷*ãòꫯºö¹AÑN !)Çk®¹Æ±êÂaah+Wv¬fKÆ¿T[}À³I§ÆM›Øˆ!þù§lß¾]–.]*Æ Ì Ij8µj>«J$@$@$@I"ðâ‹/Ê©S§døðáÆq»X±bÒ£GyöÙgä‹„d‡³¯apa÷îÝæ:(~=zT…l fxçÎÛLnzóÍ7ß šõ$¤î¹çèl”€. D;üQ•绥89Ç9Ú›Çú‘ H`Ú´i&¬f€É}&Ã7Läå´Ááÿ­·Þ2“ìeáY>T³GMA;ìáÓ§}!ÍêÖ­jQ¼ŽH€"JÀåpT´hчõ¿Ò/èÍï'oçþùç3«Ëó¼K'L˜ P2Ú¸q£¬_¿Þ¤Ë—/Ÿ[RHAcЋF‘& jæ&Ôš~Ç Ø •~îÜ9Géýñ‡èH‘ÚµE¥®Æ+ýø,³f‰Üy§HÑ¢ñÑJÄ ,P@´“ˆö°$Ο?oú®%J˜™óxiÅlúZµjɤI“L… •H8€c`¡0ƒzêÔ©Ò®]» fpû¯=Ï’ @ä 4 âñ> ÅøìÙ³G®p–D$@$U<é%¥rï¿ÿ~R.êZ|;µ&„j˜¤`§Œ¾Ñ2¼?|üñÇÖ®4lØPÒ¥KçÚç D3+¤Úz3ëçe†Á2u(®Ç×èÇŽóÞG¢_~ùÅíbQb¤ -ÃÀV=mUY%[§~Ïž=æÔÙ³gM¼{Ϊ·Hq)ê ¬r¾"ºÔ8R.R§N-÷Ýw_ ÉCJ³h‘ˆúñ©÷rH—ó¢x#€?Rý0£úñÑ2½çk¼Ñ¸¢_Þã£Ml ÄHòb– Ä0è•7o^³`Û cˆÛø!YE   d'U# ¢CqÈúŽ–3gNY¶l™4hÐÀ(y#¼ZuýØ€0 ø†0K'‘4jÔÈkÝqŽßtþöЇI€b˜BåÀáá#+UªÃ-aÕI€H€’B¢›6mre ‘Á(AùóÆo4¬ÈdÛ¶m²aÃ)[¶¬+O§6ªU«&/¿ü²+{„†KŠAåÈbñÝwßÉ®]»L˜æ5kÖÈo¿ýæÊÚ®†ä:È  ˆRÆáHe›èG’›íuT¤?ÿüósöcÞ¶ñAÅÓúôéãæld?Ÿ-[6=z´Û‡¨ÑáÈN‰Ûá Ÿ 8OŸî;7L¬¢P ¯éEê T³fMÁÇD§LUÖõ£%ŽœâSùbVìĉ"¹r‰4iâ^õ×_Ù±CtJ¬ûñhß{â Ñ8N"£F‰”)íµeýH nlٲŴáµ!¡G#   š&ÏAçõë×w»>³ÆE‡RÔ< d„%þü2wî\·™Ìnq‡H€â”ƒ“Ÿ|òÉ8m%›E$@$<Û­U«V’1cFû!¿ÛH{Ï=÷ñ +á{g£ 8Ðoú¤žüê+‘Ûn¹îº¤æÄëcžÀòå"z4¤*»ïf87nœ¨ÄœÛá°î\¸ Ç&¨…Ã>ùDôë¼ÈÝw‹ô쎙 @€6oÞlRB…’F$@$@$@$¡C‡Ê}O‚Ê‘7KŸ>½Ìž=Û„GÃd¥o¾ù†ÎFÞ@ñ @ÜèÑ£‡üïÿ“7ÞxÃ¥÷fI€H€ø[ë¦ÛT ŠBÛ B¡Ç~È‘mDï±[RŽ ,(·ß~»+K8¡¿œ9s¦ëXãÆMf×n @”¸Ron×ë Þ®izZ;€‡µÞÿK¬îê(”aß¾}nÉ6-»ãŽ;Ü’ARFá"ðý÷¢碎BþsìÝÛw¤ª£ê­ùstþwìÞ½» Êì0ÎGþsMÚYˆÖØž-’–YJ¿zÅŠKÞ[Ï?›$&L¸$wÕ±cÂúwë¦wi½M›ð\(GŽ»ä¥gH×™hòøã¢±BÉÑýšýûE:t¸¤Öôî»—Úåž‚{$@€ÂQŽ9äÚk¯u°fM$@$@$@ñK`»*µb&5‰î¼óNŸ E˜ÚI“&É’%KÄsF´Ï‹x‚H€âˆÂHb’ò#<õ‰8BǦ @ܘ§!=0ÖfÂC4Xkذ¡À¹ß²Ã‡›ˆ$Ö¾SëL™2¹eT‡#df—öÃ?ÕƒºÊñt®rà D)+ÕÙ¨½nªnô¥JDï±óµ½råJóãnžŽDîg/ïÁ‹Ón°ïr›’D*A0Uí ÚàÙ7EŠÑhVâ^W¥„tÚRk Ãë¯wº”’?v ž‡Û[L´þ÷ßE§ÆŠ~Í â›°Ê8~³FÂÔðHrölÂóÁÑçR·î¥2­k»v)]Ztú®¨×u4ø5£T&UŽ+ úÕ=øð·oß^î½÷^ý¦ þ³ïõ]a0³ºB… Öa®I€H€<¼øâ‹‚¹Ì£G–\¹ÌUöHÍ]  x&¢ ¸š˜.]:iÚ´©k?Ø (AEϲ9sæÈéÿ³w&ð6”ì»Tö”}‰B‹²¤]*TŠJÚwÚµï)‰6´(©$­’R*¤”hÁß’­]%ÙEÿß3cîsîYï=çÞ{Îy~ŸÏ¹gÎÌ;ï¼ó=œ™yßç}~6, ò¶'â=Øáˆ‚#¦X.™‡±Ž=rÈ!˜µÛ9aãÆYMe:5:¦¦r ><×.û}mâz›6mRùôÕvÈHX ™ÃÑw±’øî»ï*ûˇº£Zµj6n]›6mrªøñÇýUiYòD€×i9¥W©ÎiÓ¦¡bÅŠ ]ºß¢1¦U(6üÿ~öÙÀÿÁrÖ¹¯ØöŒ½Ô«¯ºyõÌ™ LáõÌ3ÀÕWì«b¯£ J’ËÓO»N@'¾d8hðøãy}ý5`ÖŽø«T©Àã5kP04p lŠ0jTàöhŸèŒd>ç?äƒF+Ûv ±Þ{øâ àóÏ9sÜÿìÓ§ÇV‡J‰@X°`s¶r8Ê /]§*" " "3Pld.Þ(Z´¨Í[yËé ?çœsñÝo¹å§>NPRˆ€ˆ€„&°zõjPpÔÌú’.MÖÃЇÖZBHà%›(ýï¿ÿfµìD›ì¼Ç{d}Žw¡[·n([¶¬%|p3>ð$Þ·'+Š/0–½Ë²90#J»víòtHЧ<Á‘¿"º5ÿúTZ~å•WrÝ܃lò»G¹Æ§E Àµ#XÙeL‚#›¡P~íÚµù¥dê8¢fÍšY¥ùå—¬e-ˆ@^¬\ 0C_,éÔÆZ´€Ý ¸Gd:µ¯,W[Áä·ØˆF2?ìjdòrþ)±¯)ϱ‘ÍvrGÉhôر€)æaö”ÖÛë9†ÝÁ%ãH‰¯sêT`Å Xï6Lξ~æî×Ï Yçx®ƒîFŒsÏu߃ÿ^u•›Ú)ê&OÞþ3•ùgžéžÃË/»ßG¸ÒL!kÐn´woW5w.к5Àk…M ˜N!‡£h´BD@D@D@ÌTö"Gl4`À¬Zµ wß}·Ó0xð`4jÔÈLàÌìÞö "·þÁˆ€ˆ@xL¥¶eËÇ݈´ Ì&¨tjEŠ(:òG~¤U«Z5 Ù† æoB®–™V“üQ¹retéÒÅ¿JË" "øk¶ÝßRs<ÚâÿnÙT¨‡šRÀ¯akúÆ~›8:Ê(D ˜NqØaî{¤¿BÓøáçŸÝR .ÿ]æUé˜á¶Q{ÃÉ’‘ô%áöM¹õLuF' j’ÖIl=ÆÝ¨˜§úÌfY™Ô=GK|öðfó‚ ¢×}ùå°„¿ÀcE/ªÄ¶mÀ¸qT"¸©ÓB•aýcƸ)×Î?°t1Åõ׻©!C`ÓÛÂïrÛm¨±:ݱӊ¦yó`y¢Üïš©Ú&Lv +ÂL[D óxGeÞw¯3ˆL€¢"„pàbèС¨U«–ãf´|ùr|üñÇèÓ§õ,°Ç×R¸óÎ;#W¦­" "ÁèÏÔ“L•sä‘Gf0 ºˆ€ˆ pb¿×'ÉÏÓ{ì±\ÌS;ñú“ì :‡¹Œ7'ƒ'žx"OçQ£F ~øáuÐuU‚Ý$ú ""˜Rm™¿­¦¨¬mŸ¿ò¯ µlûá_OÁP½zõü«¢.ÿõ×_Yej׿a"wž‰M,‚£½÷v÷çŸîû—_~é,´oß>ï ‰£ê,ìþË1ƒIû @ë×L}uôÑz’´‹bZ2¦óÂÒ8¦DPýööÛ.Ÿ:u¢7™)âŽ9æûï:Ѳ+žà±øàæ›#ïeïNê6ëpÇ%—¸âžH{X缓~­sg7U[¤²tÇ3w10 žÍ*Ž)‚SÍÝu—ë¾tûíÀë¯ÇTEÈB–®­8ÿí(D ðáž¹Á%îN£/U§"" " "gL¿pÓM7™ëq ›ÏðrÀ cëóBg{–áëqKa½nÝ:4hÐ ÏÇT" "Žèå•W:îpo*D@D@D€i±Ì´"á (ʉVïi§¾/Úx_ÑâX'jï®h:ÇÉâˆ:6^íܽêèÞÊW~„_X–ÇÓ1D@ ¢–Bm¹¿YöcUÛÿ9ܲu¾˜Z ;xñ`‡L¬±fÍlݺ5«¸GY(´Gt8¢YJ,¶½öræÝÌž=ÛY‘ßGQïÁìXiLÉe¢œrJòN•éÔ(0¢¨)Õ¢L˜* sQ¬qï½nI:8‘m<ÁtjüØ·oô½˜­W/WD‡¡pÁTjtB2‹SŒí:0…+ËõÇçŠÏ(8ÊmÐaÿ¦Þ|øæ›ÜÕ²l™c6à×_s·¿öBH€¿K–,QúBøÝ¨I" " " É#°Ãž‹x.8ãú¬³Î²ÇÆj˜4i’Í… ?¦R¥J…©õ" "`FŒa†ÓÿÃõæt­>~ý“Ì"`9{`#¬Ùa¢¡–ÙŸB/Õ¯_¿ª “Úø·vèÐÁÿ1êòÌ™3ÊP™©¼øç7EZ,îF<–'8òŽ(8Úwß}A;Ãü jcî¾èÚ5?Z@Ç¢ „éÂN<19  hléRàŒ3\!MrŽ’¼Z­3TÍ1EX¬A±ÍÌÅ·ßžø(–}ú øà÷XAyˆÃî>r¤+æºì2€û‡ ŠÊV®x¨[7T‰ÀuYñßÃçŸk×n‹ç“—â€)Úâ ¯ÈѶÅ!ž÷0*/ùM`©ýn³Ô‰Í›7ÏïCëx" " " "P xÿC7¢½ÍÒ¸—M˜xúé§-Ãöꬶ0åB÷îÝÙÁ'Ntœ ³6jAD@D .óçÏwRQÒU÷†nˆk_H}Eׯ_àpd‚£>–­Q¤S³2½ìE±RVÄ#8¢åÛ›ø‚% ˆD€¢ Áƒ#grúâ `×. (¥jØj½”jt8Ú´i-Z„üN§¶q鸮fS¦8.2ˆUà/º1üéÔÜ5©ó·I“øÛzË-S“Qp«ÃYqÖï¹çÆ~<˵l=öSbÒÅ(Tœ~:ÀÿŒ—^jkèu´8¥Åj^\Ž(¨`=ï¼ìNú`¾µ<îÓ¿?°çž€¥‚{,UÒïùNC‹"Žg™28à€pE´^D@D@D@Ò†ï}Ž8â›ñ5jd™§ßÂ…^è8n4mÚD·nÝð³¥²3f òÛÝ8m@ëDD@Ršûæ?·I_–ù OçñÃ?àØcu&¹Œµ>¦2œP¦È(E-ý?ö1ÞwÖÅ‹+6Ä>мíæDTÉÄF½Ï|¯U«âq(â 2Î~ð¢\¹rhÑ¢…÷Qï"’€é0h«q°¾ÁAưa±›ÃøŽæÎëX®KpmbV~ø!•]ÀÉ''¦¾PµtënÔªU¨­é»®D X¹›¾Œ©Õ¶o~®,Oá×ñÇG/ë/A7"Š”Þ{xê)ÿ–ìåví¢§RË. ë¡*TTzÖcþrÑ–ï¸ÃuкõÖh%3€–-]‘Ó©§óæ;FßO%D …x9´åp”B_šš*" " )Bà›¹óî»ïšÖ~c/:uêds#þÂk¯½fs¾Äï¿ÿŽW^yÅæôÇ?f‰<|øp3†ýwÝu—Í;°‰ È0Û­¿¨oß¾6YóPÜKßI>ü}=æ˜cð«¥¥7nœu§¨?% *­´&àˆŠ,¯ý &:Úâ© Šº7lØðc³ ®å­ã{åÊ•+”(Qâ]ÛÞÀ¿ž³ÃbÏ,UÐöÅÅ_lÆæ,¡˜i©xqX'!píµ¡ Z64 4lz{ðÚ’%Ó»º¦Scä·àÈçìܼôûì9›%SpD!Œut$4˜vÌiQcýú¨EÀ´_áR‘Eß;r ŠgØY´`ð裑ËΚ|÷Ч@±R¼aõ–{¸æÀf´å9J—vÓªñÿ!ÿS|ÿ=LÉ <òH|USuxæ™nª¸O? ½¯¥—2Ÿo KשéÙg]¡“®C¡yimJà,ÿâvñl’ç´”>s5^D@D@D Ùn²´Î'X*hºZtðy¾‹ÝßoÞ¼œävÒI'9Mb_…E£GÆš5kÀ{#Фn¡C¬BD@2ŒÀßÿí8Q D7¢xÀgÆ‹ÎãŽ;Ë–-È#УGx«Py4!àŽV¬X±ÚDDt5Ê ûÜÑ^ËMx4Û„GOÙû4ë¨ùÕÖ’UÈJšbãìRýöÛo:t(.ºè"lÙ’¥mrÜ‘úõëç¯RË"’…DQßF= ÍIL«Æ”jì 4w/´nÝ:ÕÆTÇ¿ÿºY°âÐìÅTo¡,ÄÔ]“&ÁìÌ€zõB7‘Έúè£ÐÛ½vÕ*X~Çȵ.\Ðý†'‘\ƒ^xhЀÿÂ×GÐwwß¾L^·Ðlˆýœ_vYøš¨Þ£ð‰O:5w÷oÅŠÀsÏQ‰ ›6ìß’ûeÎ0öÒªÙµ7ÂþCÆ_ßí·»êÄp3õŠq ‹éçrË þ–iÈwt8b:Þ¯)D@D@D@D Qlâš=J¹ÏR—_~¹Í° Ÿ|ò Ž:ê(ìØ±“'OvÓÃ5¥Y³fÎ y¸íZ/" éJ€¢Ë:`Ú´i¸âŠ+œ~PNNa¿üÖ­[c>m:$Q`ôÕW_Y×ÒN_Ì;« ˆ€ˆ€ˆ€ˆ€ˆ@ÚpG<«7>`.G6²ž&.*e¯vE‹½ÀÞ;Ù+G"f>”ìMÅFˆøÔÜ%hSMAgš=e©wØäë®»Nƒ`~ ZŽH€&(4<á»õi‚‚¼ÓªÑáˆvëp€9•Ëk•1ïOs{7W¥˜wIÝ‚ænæS"¹1×»}Ž…JÉŽ .zöî¿?ô‘(¤aú0Š$)(Š4`_½:¬‡èÚ5´`ŠIö{çØo=ø`èã%b-mÀhF–¡âí·úõ] Ѝš7U*¶utZº`ú´DÓªQÈd× GtvþùÀá‡Ç_3…_–- ›âœs~ï¿Ðå‰e"¦8ÃßDåε-MOQ§%" " "P@fØ ¦Ó9Öîá7YÚì3ÍeôßD< Çy>S§NuDÖ_…Ì™¶sçÎqÖ â" "þæÏŸC9 mRÝC=d¦ØZwPs§ß~ñâÅ1»¾íÚµËéçÿðÃq饗â¶ÛnKx:Cˆ²G?ýôÓfsjk¢£‘÷ðmìÞ½ûÿ®a:01eʼôÒKÎŒ‰`¡w9þøã#Î< S­Vg8šã0’9¡ã±Ç²aÐ¥(7ý›ÔË­[· kÍõ%¿Ó©™Ó»Ý»gŸG¡\JDÞ··ÞrOí”SŸ"St |û-pôÑüb—MijÕw—,ú÷‡)"³k¥›9L6j”ë¼”½5ç’ͨ…uv;yÿ,­€ùøg—1Ëjœ~:@g € ²·å÷<ì„ï=àõ×ó~ôܤc wÔR¥þgذ¨V æí®dôõO> ›Þ슎B•®eCÍÑL!éL`Ñ¢E`‡0;’" " " "H¯½öšS¬¯¿þzgO,ÏtØ`_…ѹ‰?ìÁÿ={–¡«Ó¹hDJÛŒ¤Ì%÷ÐCÍM•ÚGD@ÒšÅA‡[_Ð:ëc{ùå—áïËç2…HÆ Ãgœ(%®ºê*¼òÊ+f~ªõÉú:e£ì§Í" " " " " éK KpÄS4ÁÅ˽|©‰ŽN´?G8í6€uõ!CL» ë;¦"7ÞÔ­ëf§úå·†+¯*U‚Í®Œ¯F:ýý· APÔŒZäÔch6S§вeŒ;D±±caùx`ey;:G<ÙŒ\S}1ØÇ^Ê«È{ä~ë¾û´™¢@ˆéÁ(r¢åã Ýmt ¢)–°N'×ÿ!öêåº"q?:õ˜ËˆõàD?ÿXŽ“—2{î ëᇩ=óRKòö5[oœu–ûïmÍmÐéI!N€éÔtïSˆ€ˆ€ˆ€ˆ@¢PÐÌtjMš4AÓ¦M‡Œ¶mÛÚ|0}úô°‡™h“2ZXŠíãŽ;ÎqÊæ$´#F`uˆ .Ö/…U–ûÝwßµŒÑC¥úæÔZÙR:s¿;î¸Ãñ¸LtŸ" " ^·‰füÍ,f®èw:'Ãù‚ëÇŒƒR6¬Ÿe1'ýËúÊúöí‹ÇÜÉbðâ‹/Â2"øjÒ¢ˆ€ˆ€ˆ€ˆ€ˆ@¦9"k¢£w HÍFÕ³NªZÙû~ö 1çÎ_Øë«•+WZî XŽ¡ø¢¥)+8ûMAñqËôÒÖ—‰ß~ƒ=ü‚ݔjL­F3êAì9×fâµkÃR¢ÅGëˆ#`–ÂßbÑ¢RùêpD‡&jP(”*ÔÁêš5aIÙ]Žu£|ùøšlÅŽU,j0:æX†#6ºøbà°Ã\ñ‰ul$%x.t#ºúj˜§4pðÁ®éùçÝtjñºìX:fÎèxtÎ9®‹ë?í4à’K’r iU)E¹)D@òLà¼ÐXÈá(Ï(Uˆ€ˆ€ˆ€]0~±™?çsb…E {†7nZµjesμyó°göì¦Z»É\e)¢`ˆîD3홉®Dt+ºÌ&œð~å({†â 6SþЩqãÆ^f[7¶G¬sœ‰Bœ,DñRÉHi¯³öÖ‚ˆ€d&k­Ó´’MŠcÌý÷ß?$ëÿÇ}÷Ýg†ãq£Íðdº5L6÷è mRžeGp\å˜Í@¿½~BZÌ&Rpä!Yºt©É!À×ÞºxÞk›ú£S§N΃M³fÍСCÔc>,…ÄI€­¨áØÝŸéìmÎéèÖ –¶ÏÍ|E§#3Ί;.¿Üþ¿qͪ,æÌÎŒ»‚\îàeÜ*TéÔ˜b‹¶„ëEëÖÀ×_»p_0!Þ§pÁ&El啊üÎTbtŠ'¨.³ß '­oæÎ…%šwS–±¦?ûê+`«iíw&Oa3º@œÌÚq"¢pÈ:ÍmÊVüU7l芳(:"/›‰‹§ŸŽ¿í!" y @‡£r¦ÂÕ½W jW¼tj½èêº;4hà8_Ð!ã{V¤«ãçŸv5(0bÊ3¦â©ÅôÆÿüóe¥žŠwÞyÇq2zøá‡õÕ«Ww&±É{QT±bEg»þˆ€ˆ€D'ðÅ_À& ãºë® +6òjaª4:×ÑÁ¨GNþßÿ툞3GpŠ–è„DѧBD@D@D@D@D@ü" Žüs³ÌN&¾"WÔ•0u!þ FdÙ2XÇ#Ó¢Áf@ú·Æ¶L;ø¹&f¡ëV®ì€Ù)ÊœhGÛw—¢k3ouì×nÉ-|Ë-À¶m‚#‘ ¥pæÙg'žFŽt_´­çÿñ3Î*TH|ÛÌßYnxGd3e`TŸYljy=æ·³g'æØLåF±Yò;nDñ:9ù[ÁNôO>¡š æ7íþ#õoײˆ€$™Ž˜æ„Ž H¦:{Þq(0¢ƒµ?8=ÅÒ7?Þ2r?å”9óÌ3ñ믿:ƒÖL¹F7$/*Ø3$¶ùb½ß}÷ªV­àŽä•Õ»ˆ€ˆ@|^~ùeg‡Þ½{GݑόÑ9îÜsÏÅСCm>ÞUX»v­“ói›D·Ï>ûD­GD@D@D@D@D@2@.¬;2’θ` ÐÀ†)Æ©9 f-^ tíê¦ZÛ{ïàÑ?/¶ 8³²}ûöÑ — ÊÉR:"nûýwW\.è³¹;:fÙ*žTÙ_Ð#}üóOX¯›Â,T9XŸwžëv4gÌOÙ-ÏTkL¹Æôgßjϼ­³góÚwsÏMŸóßwF6;ÖY6[þ„ÆÑG÷ßì·_Þ«­RÅMEG“BD@ò‘Àüá8 (Z>BסD@D@D Ð1ƒÐ~w#ÿi2{â:uê8ÕGÛ³Õ–-[@G$ºùÅFþ}¸ÌÁî&MšHl FŸE@D 8¹òÕW_5#ïFhMçò‚θL}IW¤ž={bÆ xæ™g:‰b¨"" " " " "¡ ‹Ô!Cñë´c!Pºt¶ž'Tyê`ò³w»ãäJpD'œ;¦ÎbXÚ@ëQV­b©».èï¿ÿ–BÝÒÜwÜ´± ?Κ›V ó¹Þ :ñe3žlú*lú*ðä“°ž×í覛`~ÍÑ뉵UY´³b*7;K RËm’þŠ€ˆ@a"@w#ÆP˜š¥¶ˆ€ˆ€ˆ€¤8/£CÅ{ì_|ÑIÇÃth,ßP0B¡Ò:Hé6a)-ãÍû ¨PÁ å¦G˜`ëƒÜ”rÇT®œ›Z´ˆ€ˆ@x‚#9%¦ªpÌ;מ›W9©v¢!ajžR¥JE+¦í" "  &°cÇPÚ²eK3O ûx‚Û©êD@D@D@D@D@Òƒ€å)Ê6[­N‰%ž°Y m«%~ÊŽâæ,bâ£m¶fÒ’%KŠ5iÒ${£–D Ål޼˖ÍvZM1P\A'#›µ‰óÎËÞ­M n]˜o¼›n,{‹³DcžsÎ>(S&hcA~´Î̙㦄+M‡¥¡íÛÛ¯Ã$7=[”¢Ú," "L©VÙ„ŸÕ«WOÎT«ˆ€ˆ€ˆ@ÆðÒ©õêÕ+ãÎ]'," ©Bà› ø§ur^wÝu©ÒdµSD@D@D@D@D … äP˜‹Ñ…%K–\`b#³( yçiÛJÙ«W=º>[¶lñ6é]J`õj Y3`ìØ„V›UÙW_}…;ÇÑGÏp²¡emˆeÁK§vÔQ¥ÙùʆÏv…Lþ+? œvšm’—7nV®Œ|o¾ýGŽ/Zä³aVˆ€ˆ€  Ž”N­`Øë¨" " "®è˜Q«V-´ç$…ˆ€ˆ@¡$Ûtj…òdÔ(BO @pdb#“BàI{•¥å;wî,6räHÜtÓM±Wˆ›€é°hL÷®1í0ÛíÀ AÿáÈ#cÚ%»ÐÔ©®¨¦K—ìu\Š’V-°p’?™ƒ““òíâ‹#hÖ,wû¡‡F.§­" " …žÀj½nذJ§Vè¿*5PD@D@R†À·ß~‹åË—;éÔlZÊ´[ L"ÀIÁ'N4gõƒa 2éÔu®" " " " " D Kpdb£–ÿý÷ß•¹iÇ»ï¾ë<Ìäf_í#‘PpÄ`¦²dÄ—_~‰¢–Bì ƒНúÿþ>ú–¨R%pß¶maOõnZµÀ-¹ûDÑPn£lY sgÀì”ñÃákùì37×[øRÚ"" ",Xà´RG)ðe©‰" " ""ènÄèÙ³gŠ´XÍÌ#0yòdüóÏ?8ãŒ32ïäuÆ" " " " " B KpdGÜf©ó·ÂH_Úës2:rÓ¦M•wìØAQR{¹=M¾ÂwÞy'~üñGß-Š@Þ PpTº4дiÞë UŽšYζòåc2õÊ®bþ|à·ß€àtj^ ¦U[µ 0AÝ™Î?`Ö²¸bæL O zu÷Xqíì+|ÑERO?í[´H‡£æÍ ‚6裈€ˆ@ª`:5†ŽRí›S{E@D@D ðxíµ×ìÑ´:;ì°ÂÛHµLD@2œÀË/¿ìL¬<Õs_Ïp:}ä(ÎCÔ¯_Ÿ9¡:nš ŒŽ_¹råVßú?lÙ”× Aƒæ 3Ô–‹p» ’0iÒ$\-u +D F_íšwþ¥Æ¸SŒÅ~ùå0íÌyçã¾b~è~èÚÕ·Ò·Èû‡^}O}Õ£Gûì´jå+nqΠ_?7—ËtêüaÿõªVå§øƒm¬_xöYÀ„(Q"°Ž•+Ÿ~N>9p½>‰€ˆ€¤$:1Õ‰G)ùõ©Ñ" " "Pè,\¸K–,Á¥—^ê dºªA" " ޳³t²~Ä5jˆˆˆ€ˆ€Ï<ó n¿ýö„·ç‰'ž°a­Àq­)S¦Œù <guV­ E@D@² 82”j‘½ÊYšÿ矞´nÝ:¿Ø( ÈòåˇõéÓçÊ9sæÔñ6Ø:oQï"gkÖ¸Æ>4 JF0£}ûö¸î:À&9¦DÅŠÅp´©SR¥€Ã]¸]; vmlš0·m‚š5ë¯]4`íŽÀÙg» 8 ;QãÆEâþ`ƒÎ¸ààÆa¹` t7bh¦ªËAE@D Å Ðáh¿ýö3Ó:¹Ö¥øW©æ‹€ˆ€ˆ@¡ @w#F¯àgÉBÑ:5BD@D€Þzë-lݺ½{÷(T6nÜhsÞmÒ{‚cË–-9jäµÐ,še(D@D@’KÀI©f‚£&þÃìÚµk”‰þñ¯ µ|þùç/ö¯—àÈOCËy%ÀtjŒÖ­Ý÷Dÿe:5G¼ç`FÀ?ÿŒá(Û·LwFN™2áw°ÎØr«cÜíßaÔ( \¹ðE³¶<þ8lê(póÍÀÃç]läU|î¹®³Ñ“Ozk²ß?ûÌ]>ôÐìuZHIÿþû//^lY2›§dûÕhÂE`•¥ ñÅQ¥JqÄ…«qjˆ€ˆ@¦S+a®æ={öÌZ§H6/QU°àhw¾¨È‡7‹Ö?*Uª„õë×;W¬X+Éb;26m‘€'8jÓ&Æâ,FÁQ9S5kÖ {íåîLÁ‘õ£F:mÞ uTŽrÖk¶Å@É’¶‰iÕ†ÅQ«-ŸÚåæ(›cÅo¿¹)ÏêÖ®¹&Çæ<­`:¶SNqR¼áûïÝk^…<Z0Õ©ã­Ñ»ˆ€ˆ@ŠXºt)¶›0VéÔRô T³E@D@D øçŸpÿý÷cذaŽcS ‹É¸œ€š!" Dà?þÀTsc?æ˜c¬sw'g¿NUD@D µì»ï¾Ž;{^[ÍI ‚'à¥TÛÏßëXúÙÿ9Ò2sB{‚£mÛ¶8ú‘DLÛb%ðõ×nÖ2Ó%<–-[†Ï?ÿmÛ¶u:M÷ÞÛ=„ýóL§ÆèÚÕ}·¿?Ûÿ¦ 3xì17˜VÍRÚ€öóÆ 8ºé&àï¿çžJ—Ϊ;äO÷Ý窣®º*°ˆ‰þLõ¸ŽŸ˜žmÂà©§€p·ïÜé– —.g-Z#" "Pˆ 0CG…øKRÓD@D@D à$²Ñ£GãÖ[oů¿þŠ–-[:¢£Î;âV«i" "Ù˜ú’n·J§–Ùÿtö" "*εŒwÞygRšÛ¡C|üñÇYu7nÜ8kY " " É!à9ñU¿ý÷ßßèûq±¦9£0u‡ìœRˆ@"Ðá¨E 7X"êóê`ÎÖ=z€¹Ûn»ÍYíMþ‰)¥Ý€h%ïËõvÚiÀ§Ÿv/cŽI»TÄþ[ÑÆØf„bÚ4 R-O–B£#tˆ¼Æ†{§…Ò¸q€Í:Åe˺%×­ƒõwÜá®÷ïÏã7lèçî»]&ÎPå±ÿûÏ_RË" " )H`³‰Qßxã §å¥à¨&‹€ˆ€ˆ@>xÌfÈÌ;ÕªUËñúé§Ÿpà 7`þüù¨^½:žyæp0 h¨ -ùÐVBD@D 6ãÇG™2epÒI'ŶƒJ‰€ˆ€ˆ@š¨\¹² ÅÙX˜BD@D ßx‚#ÿ·û?D[.UªT´"Ú.qøñGØlÊØ´7ñV~ tè1xð`téÒÅÙÝs8ŠIptÙe_»cùrWltæ™ÀK/ykw¿Ÿ>ÌÓØúm øxå•J<°:ì‡âö_÷úëK.q‹ p‹Z‡0¬“{ì‘sWÖá…Àu×o¾ œ~zvnSˆ€ˆ€¤$Îdå€à]wÝeŽ{?;éÔößÿ”<5ZD@D@D yž³I.WòÙ3B”6·Ý›Ì}wРA(_¾|„’Ú$" "PÌ›7Ÿ|ò‰3¹²B… …¡Ijƒˆ€ˆ€ˆ€ˆ€ˆ@%8Ê ÓשV4Ýa´iã¾'êïðáÃñòË/;᜹é…çpSJ5o§ÝïžÈ¨_¿  üØ´)`þ!SœyÅéT4kpÅ>{$oc„w›ij£ËÀC—^ Ë Œ ÐÉœByóÍÀ“O ŽBÖJÂLà?s§£uþÍö»ÎT¡t"1b„ß]€â¦*D@D@D@ÒšïvZšìX®ûŸ}ö.¾øbÔ©SÓ§OwöcÊ4ÿkÇŽÎ}Ä~L ®(ô~ùåœxâ‰(Q¢„Í/´ † <à3ѪU«l˜­¦%ÙY$O5fïüe,Y³fó ¶‡™Ô®]{{nÙÅò´Äç;ƒÇªZµ*øl'Aržjgh4*H*’ÿ˜ù‹º˜Žwì™3g:ßMš4Á˜1c*öG19ì ¼ø"P£Ì-)hƒ÷1’ý¼¥wsœŠxSoÎZº‹]}µëX4v,`V‘X½Ú­'Ü@3Ë0Í›‰®°t)Ш‘×J½‹€ˆ€¤3fàÚk¯uR¢T¬Xw[ªÌ¢\¹r)tjªˆ€ˆ€ˆ@n°ü…^À}÷݇­[·âõ×_GûöíÃVÅs¦/i©¹ß~ûm§c›…ëÕ«vm(ܶlÙ‚îÝ»;ƒŠ¼&´k×®p7X­| 0{ölç9É;Ô%–%äØcõ>†|_´hF/¾ø_ýµóŒÅ‚õíÛ×q‰ÝgŸ}@—ù+h°;Î;ï<tÐAÞÇï»vírÆ#y­æ%'Œøƒã•gŸ}6ú÷ï祿öo ^æÄö{ñꫯ¢nݺàóáO<á‡Î‡þ (ù¨£ŽÂ7ÞˆÃ?Ü¿IË" "0% ¥*J$f‚¹çžÄÕø“¥;í´Ó@{ø7Þx#‡¢×Çëpd÷.`J5ãu †ânñý÷ÌGg¢=÷Œ{w›¢ °ŽjÕ‚MirÓ¦Eªé¢‹\ÁÑSO¹îH‘Êj›ˆ€ˆ@¡#ð×_9ŠEMÐJ‘Óž0?¹BD@D@D ½ lÛ¶ Ï>û¬=þ=à̺ÝËfÎPpÔÑfêŒ5 ýBØîn²I.þý÷ß-³ö›hÞ¼yzCÒÙ‰€ˆ@ Ã'çÌ™ƒ[o½Õ Í€ÓÖ)Š€ˆ€ˆ@T?ÿü³3ÉÂ+xÜqÇy‹!ß™…nñ|n Ž+>øàƒxä‘G0aÂ}ôÑÎs—WŽÏa‘G ,ÀYgeIPE@Þþ|_²d‰Ó·Ëã :Ôù·û—ׯ_¯¼ô0¶âãÅ‹ãŒ3Î{ Š‘Þ}÷]¼ÿþû2dˆÓ—ì¯SË" "EQ‰êÂL€ÔSO=´~î¹ç°?ÕLAái}âu8¢»ÃDÎñ‡YâñÇ–-aw4ñïÏ=Ê—‡É«]Õ“©›Ñ«,§NäºhÕ¸1ðüó€uX+D@D@R‹À'Ÿ|âÌ\yøá‡Á—ÄF©õý©µ" " "/v$³“›ŽD—Z:íÍ›7cðàÁX¹r%˜*iUϵ”ÛW]u•3ëÖ«ŸÒìàž?>î½÷^œtÒIÞ&½‹€ˆ€¤0[n¹ÅI¯Ý»wo3L¿3…ÏDM‚!@§¡àÌ3Ï )6ò·Š?zÙØÍ bÏ?ÿGqDH!P¨TmÑ1éJŽ÷Åß}÷:wîòÁUð|éŽÄ~e…ˆ€$š€G‰&ªú º?Ìš5ËI§Æ›‚PÁ d–‘ñŽÌ=¯¼0­[‡ª5ʺ `þŒ®ð§X±(…#l¦…#…GŒË/wߣýµÙONÎ:³sTˆ€ˆ€¤Úç2º„ÍåélÖ4 @g¢ 8áQlL¡Ñ 7Üà8÷xàNŠÕN:áÑGÅ1ǃ?v[÷Òõ‚®F}úôÁ AƒÒ€†NAD@Dày›@È”š|°3±²H‘"‚"" "PXl·†l ý*¶£ø ØÎòÁ±ÃVxuØTŽˆpŒ¬ý¼ýù^PÇÈÑðµâÉ'Ÿt&ux­bê1º~ôÑGÎóÖÒ¥KñÒK/9™SX†ÆÜKüý÷ßÎdŠˆ¼ Sa¯Y³Æ8ñ™nüøñ9\ {ì1ðK0ÝÛ¯¿þêíÚµ+&Nœ¶{Æ Θè=–F†çåÓ»q"ŠBD@M@)ÕMTõå™…<%"xCÀÜ¥”½Ÿ©Ç"ӪœRÍÍ–Öñ¡Òh›l†jžÃlôÍàÍË¡‡ÆVu8+D@D@R“À´iÓ'æøVˆ€ˆ€ˆ€¤7ÍV—Vþt³¸ùæ›4áÁgL·Ã©S§:¢$>ÿ¶mÛÖ±âggr»víðÌ3Ïï¢Ï" " )H€®^x!êÔ©ã *–.]:ÏBM4&ÐÙÎmVèó»»³\øé޲²•çxÓˆÝ뮳÷ƒ¶G8FPI÷cA#dcÜ•ëÖ­sR‰E(uS^úEÿ±ì#~‡@:½õÖ[8ê(ÂÊŽ† :HL¥v¹Mög:ëX‚Ïaœ8âEÿþý-ÙÉã(S¦Œ· µk×v^§Ÿ~:êÖ­‹»ï¾;kShÓÙ¶X£:ßRxÌTl4^ðÇ!‡¾x ¥8y…Á‰¬$U¤ƒBD@D A²ŽµFÕˆ€0Ñ-žz øôS˜e|î‘,Z´]töÙgG)íâlΉ(Y2ÄñfÏڷϱÁ´Lv1‡Íͱ)ÿWÄ*4Êÿ–éˆ" "  $ð§Yñ1- F" " " éO€N•*UrG¥J• {ÂÅmÖ;±[µjåtNÓ݈ÏÂì8×€tXlÚ " )C`ùòåèÑ£‡ó›þÎ;ï jÕª)Óv5TD@2†Àqv¦ BŸ-Ó_15W‹-² 4Ë^ÌZâPÔÆÝŸÚd­Í^ˆpŒìB¾¥‚:†¯ Á‹#FŒ_y ºõäÖåoÈ!øí·ß²?lذb£¬¶ÀTgt+bJ²h±bÅŠç¤Ö–å)ðŒ4>y×]waãÆ`;?þø#>øàw¿ìÈqÉ%—äù÷  ŸgsœÓbûöí–xåkÐ!W!" ‰"Cpd*Ç5:'–Œ9²ÞÚµkŠN™2%WÊÈSN9% }È\Ìccì»oîlÚ´ÉɩʸW,ïY•*U¢VF¡SŽ˜18òHàê«MIž-%§Øœ Ñ¡L!œc/­¤˜a×%ÎHa~n…ˆ€ˆ€ˆ@z ÈxÞ¼yÎDšHb#?v†7mÚ·ß~;Œ5jø7kYD@D  ükvð½{÷v;'OžŒfÍB§à‰©É" "nn BÓFMsR·¸Ù'8 UœY»"eîŠpŒPÕ…\—Çyà‚_ÉtgLSí]Œø -(ì¡PÉKa®à¸ñLꤓl¤øÝL ˜zÍ ¦S‹'š7ož%8¢ÓÑÊ•+÷Úpu4iÒ$ܦ€õõêÕ øL!“BD@I@‚£DÒT] !°÷Þ_¹ æ0`x¥å`Ø`Î6Ú$RÝÄ‹¾÷â ­•èÔÅ¡^˜JX!" " M€³Oþ÷¿ÿ™ùž¹ï)D@D@D@ÒšÀûï¿_~ù—]vYZŸ§NND@D <­[·â¬³Îrœ^xáë²Ìƒ|øÃh‹ˆ€ˆ€ä+ÆãÄOÌ×cz q‚G¬Q 'q@IDAT»víˆE—.]°}áÂ…Îu<`e„K–, غvíÚˆ‚£=÷Ü3 |¸E‹ ·IëE@D !$8JFURP9|ê©§:MyõÕWQ)œýÕ»'œÌœ T¬ÌšåìóŽÃ°"WcH“Ñh¹ôU …åÒ}ä‘Âpjjƒˆ€ˆ€`ÆŒøÏøâ™y#l" " " …‹À¶mÛP²dID›‘Ëtj,Ãf…ˆ€ˆ@f4h8ø8dÈ4kÖ,3!è¬E@D@D ‚G±ŠvØ„ýöÛ/bKB Ž(:ÊmlÙ²%⮥K—ޏ]E@D ¿8‚#³Okc?LÅâ=èôéÓŸ(S¦Œ«ðˆwg•èׯV¬Xá¤T‹hUøÙgÀçŸÃò­=¬Z˜3ÒïcvaêÛ]±úç±h¹ï¾À„ @ˆ ¶¥tEûöÀÍ7'øTˆ€ˆ€D ÀtjŒÎ;G(¥M" " " …•­ëëÖ­‹nݺaôèÑa›ÉÉ4o¿ý¶#2Ž6‹6l%Ú " "Ò¬ßÝæA>‚:àꫯNésQãE@D@D °ø‘YO|Ö¸ÀWÆ[,^<²‡ÇêÕ«½¢ y§Óa¤sQ$:Ú&"Ÿœ_G³eû37ÝgŸ}¶åf?í#¡Øs´YÆ'”)ªDøuÆ Ãĉ¼¯]tQø‚ÜrÔQÀ—_Â’Ÿ»åhƒh¯½KÚÇ·?†ú¹›‚ÿ.ZLšT«¼EŸE@D@D ¹Øá\«V-Ô¯_?¹Rí" " " I!ð¥íþí·ßðì³Ï¢»Íd9‰¿!b‚M~açòÙgŸb«V‰€ˆ€¤; 6€+Ë•+:Þi@1Ý¿qŸˆ€ˆ@~àµÕýõ—÷Å6à÷믿úwͱÌ~[p¬²gÏžþUq-7oÞ<®ò*," E ²³ Z¥ãf$G5½?Ä'8Ú±cî»ï>Ô«WO>ùdlì<±‘¯tË–ÀÈ‘À¡‡úV-¾ø¢»¢oß  ú(" " I$ÀÁÉxó~'±9ªZD@D@D Þzë-g¯Š–Ú›Ït­Ø{ï½sÔÄÁå²eË¢W¯^9¶i…ˆ€ˆ@ú8p ²¯rú9Ùß©H `G#ºÅ*8Z³fMÄF4jÔ(`;SiE…ˆ€¤9¢i~~:½!ðï¿ÀÇ»©ÊöØ#¾FO™2ëÖ­Ã\àÌü‰oïìÒ_|1tO]À–ìyO=qDÀj}¤˜1c†S§N’zU." " ";wîÄ;ï¼cF»­l¢ËHpvìå—_žã`Ë—/ǬY³Ð£G”/_>Çv­Ho“ÌZNxÇ{,.¼ðÂô>Yˆ€ˆ€ä3à”ÕÑDDþæ½ÿþûþ9–ƒGK—.ÍQF+D@D  Hp”Žßj žÓìÙÀßGã_xá)Rgžyfü;ǹG•*0aìxqî¨â" " "Ó¦MsöîܹsjÑ®" " " E`æÌ™ææûN>ùdçÙõ”SNÁøñãñúë¯4iìØ±ÎçsÎ9'`½>ˆ€ˆ€¤?mÛ¶9"£=÷Ü£GNÿÖŠ€ˆ€ˆ@>hß¾}À)ô%víÚ…‰'F,J§¤=|Ž sçÎÅ–-["îãߨ§O4mÚÔyuìØÿý÷Ÿ³–E P°® scžy°ÿ pÄ“R­¨Y¸6³œÑmMÜqí½O·nÝÚ{9¤ù#J[ð½öÚ pZZ~ª† ¢X±bB-Q |ð[ä˜c¢ (ð·©”xC@LJýöÛ/`›>ˆ€ˆ€ˆ@º àˆ×¹ºuë¦Ë)é°ÿ>åÑ A›Ð…µ6-„ÙŒº½Ê–-û€Í°;ÏÎ4W2ÊM›6‚¾(8ºí¶Û²:×Ò‚žN"!þú ˜30GysÄŠ¯JÎþ,S¦ zöìߎaJvlV)0kV`_˜ö­kW lÙÀmú$" " É$0}út§z¥SK&eÕ-" " É#0oÞÚ}õ//Øü76•)¡¬Q#Ö*¾Å‹s· F(iÿ#âmcΚ´FD@D@â#0mÚ4' gÈ(D@D@D@RG{[aúŽEåÊ•1jÔ(›ØâÎl‘»Q } !à¥S;餓2äŒuš" " "PpºwïŠ}é&D±‘t5š”ÅÆÌqÏ=÷àðÕä aˆ°±s|ñŸȬ]˜ˆAaÓçŸî¼Bì⬢éus=°ìCáŠh} 8ùdÀd&hËÙx`Xöu'ݽ3V¯vËР뀀çŸw_æã’ïÁp'œp̼ukXÚ¿èMèÖ à‹·³Ås(P¢ï¯©K ¨¿é 6ìi?œüõ ý+ ¼jþÿþûïᦸ¬>þü o¼ñ†“ÛòÓO?…}Æ{ï½gvYO;³óØq*þ÷¿ÿ9"‘?é#¦Èxt§Sp¼ã¨L§Æ¼§G‡RQ.j®Z0÷#G)#eªD7näÅ?{Ë ë%Ê—Ï^¯%H6Ÿ~úÉ™ #w£d“Vý" " "tæå¤«O<ÑRˆ‡Î!~ŠåçÌÜ *€³t" " ™G€‚#ö¥+…Jæ}÷:c‚!p€):(:t¨sý ÎÌSºtiðYí³¨¹ñÆs¤U«R¥J؆ï¹çž`êì1f÷Âç¼HÁ²tE¢H©sU)ÒŽ@(±OòÑGaÂ4× ¨HÀ²ýaÑ"`î\à©§, •É,˜¢,¿Ãd8ì0€™þ†MlÄ6öìé¾$6Êïo¬à—¥/«S§NukγöÊZçkÞg&4ºfÙ²e=î¨Úä!_ÌwIõæ»–dpìØ±X¸p¡¯:þ#ýçž{®“'“IŠÌ$À+*6¯¸"¾ó§Í ÿ 0ÀT’!þÉÒ݈qÖYî{ŒiíÆ ®:ÿGXL ³M„u»ŸõWD@D@ò‹S¬0:wîì¼ëˆ€ˆ€ˆ@j˜ÈéŠÑ+ž}öYël|r‚N­ïW­D`ªŠSérNœšˆã¨(Çã+?âd³“af”Xƒ×Ý«Í>†¯]»vÁÆÁtjÕªUCÍš5Q¦L™¬ª6ÑÀ‘G^1^ÛéfûÍ7ßà믿v^?ÿü³Sw-Ë;ÕÚ¬cº™% Ç×£E¼çæÕGÓ†x˜xûeú;“:U¬è¦5‹‡Óýýwl&7ÜX†?K³sÐ(:ò‚Z6/ ? ½ÁtÞ–ä¾›îÍIÿ¶y³¹Ð˜EÍn3æäTµ§<,¥†Y¿=hgcÿu²Ã~€L ‚öûFöÚØ—h'Ç@¾(¡”©×¼X²d‰“ZÂ$EfÈm:5º1B¦SÛ¹ ÷¡9$.°¡GL§Æ  œBD@D@ò“€'8’ÃQ~R×±D@D@D q˜NÔ!y}‡aG·ÄF> Z "à¥Scz…ˆ€ˆ€ˆ@Á(Z´¨ec±t,ab³ªø"Á‹Óáˆ&|) Ó˜¡aÃÀv è:û˜î #nÛ6p{¸O1)S¥1O¥JáJºë)h²¬~aã Ó§Á»[0A>ü¦ép+{ç k×U¬jÒž@Qžaƒ ¨Ê¶‚ùÉrJvÊ­Ø(˜\»ví7£6L<è‹#F`íÚµ¾5ZÌ$æˆöíéÜûY[:?Œ?M›6uÔ¿9öüè#÷¸oß›¢­`J5ƸïBOžìæÊ¬SÇ]§¿" " "_¦YNÏú6Íaß}÷ͯCê8" " "  "À4ò3gÎtÄFeË–MP­ªFD@D ÝPpDgƒhâÔt;oˆ€ˆ€ä7fX0Ùý¼×\殊1>û쳬’6®Ž½½ŬµZH%fh…+¯Bé½é6dIšðÏ?nгXÎËO÷2 ÞÈ‘#QµjÕ¬z¶nÝ ŠŽ™I€ÏhÏV®\ìç?eʬ[·.´»«ñÒ©åBpä©D™RaÆ\ŽUéÔ\ú+" "(È^¾|¹Ò©årID@D@â"°aðO#\¼cS­oÅq}WFëE@D@2›À?6’EgÛ.]º |ùò™ Cg/" " I&@gÙ+MeÂ4f|yä‘–þÊli¢Ó¡}¼V»ƒiÒ©K€ÙñN: xì1 F `Ë–Àsá×kYÏ­o–ò6p[ð'&ÝyÐrHµjåºÝspçÁ¥’ÿyûv7Û%—Ä,žëi§ÁDtnú6…(D ™Þ¨Hp²¨ÇW¬X± žŠb-K‹ð{ï½7 øG&•c'œBb!Àtjöo}úôÉY|ãFàÍ7Cu_æ,qM°àˆ–q Ž\ú+" "?hÑ{óÍ7;S:µüa®£ˆ€ˆ€ˆ@<,½u(¶BË–-±råÊ»2;´Ù‘­P8±Ò² Øìúî¡6kˆ€ˆ€ˆ@‚ sÌ1Y5rI4S N=î¸ãL”’­JéÕ«WVZH-?ýÐÁˆã¿½ÿ>, zès )R,^ vpà ³äÐkw—~¤Ý’²íŽ;\?KspþÔàÁÀùçûí|úiþ¸)ÅÜ@LEÍöÍ4w¨ékñv›¡w·ïs™§²^½zYõ®_¿sè1¦ˆJ€³'µä™*ТÒx’%ÌäàkÈô2QšJë¤\„ç€è¥TcnÎ*UÜ´o¹¨N»ˆ€ˆ€Ä@ Ó¯m"s–´üÁhÑ¢…ó;v,ÓÞâØcõŠè]D@D EèÚ–"_TšÉ> ›¨…¥K—âCÁ·ß~Pÿ ¼o=—:t@åÊ•¶éƒˆ€¤"]Û’ó­Mœ8Ñ™Xy¢f;&°j(t}‹( 7÷ìÙ3à¬n»í6Çõˆnó^lÛ¶ ³gÏÆ£>Š£Ž: ¿ýö›· çwÚ¶m›õY ©C`ÞmÚ4§“.kE!_ uÞ›·ä"êׯË/¿<æ=gΜi?zc°lÙ2GlÄéðSÅ”0ì¼<õÔSѺuë˜ëK傯¾úªcYV8AÓ©1Áäé§çê4ýGkÖ¸öwT¸¥˜BD@Òœ€®mó¿a ’‡ f7õŸn Ìÿ}ñÅãÌ3Ït®ó¼æ+D@CÀn§Q­P±bbêK•Zh«üå—U±sgñTirÂÚ©k[ÂPª¢  fÜxã>|8:vìèô0%cêԩؼy³Ù´Ÿä|ÖH$üº¾©O2‘ßZκ8¡ô½÷ÞC›6m°Ï>ûä, 5" "at}˰/¼€N—iÔ´X×_½Ó^³ÜZ|•+W5kÖ'†Ò08š7oŽGy$xµ>§wßu‡Žwì^z 8ãŒø=z´›jí•W\ï‹&M€çžK®Ðˆ­äxuݺ°Ì?Àó϶۴qŽSSqëò3)øî§Ÿž|Ò"r lBTöVÎs¶a œ{.` ª"kU÷ïmŸß÷NÖr»víªö+G6ÒŸþ9Þå¯S.â “Æ"8Zc¿ 7˜ÛW_}•ã(¤¢–ƒ”|±S“È *ä([Wð°Q#àšk`ÊáØ[H·‡2æmÒ®>x–žÏI¼¹çž±Wê+éÑ݈¡ F.ýHº¶åÿwÌÚ¾}û:>ÝIJLJ[ßñL­Èÿfëˆ"’˜SùÈÍ,? ôî’§±ÑœéÄÛa3…ÍqÈ {tÀ=÷´µ{è|yÔË:naXе­0| éÙ Žª™‚‘)ã9¡Š©ph³ÏgV^Ó™NqòÉ'§'•ˆ@Höõ-û$ ô‹ :ø§–·âÏ?ÿÄ€‚¶è£ˆ€d&]ß2ó{/ˆ³¾Î,i((âóœ?UÚ&Ë Bó‡Pѯ_?ÇHƒ¢$Eá'0y20kðóÏÀ?ºýe:¦«Ó å&î¼Ó5¨xê)àÒK»îJ—ÎMMñí³ï¾®¨É<9LðTª”½¿t©Ýî¿hÖ,{½·dI¦°p!pá…°‰ˆ°‰ÎÞ·íº Íæ¡¥Ü(j•ªþÝwíÚµÊÿ9YËtçñÇï¿ÿîÿXè—©nMf/^¡ÄF¡ŽûñÇ;"œTáH5&­çø#k°³ƒâì° )¬7Îõ… ç~Ãx±¹â ÀÎÎEÂÄÊ8úèvTHº¶åÿ—¸ÐîöùP;pà@¼üòËèÖ­›ÄFùÿ5èˆB€Ž•¼ÏãL&Îb2GlK…”Ü“§ã6;2î¹èÑèÚÕ}¿ãŽÄ÷Ÿ`é†a“\1?g;1ﺙÇD©RÀµ×~ƒ²eÿXŸ tmË„o91çÈiœQK|ÿý÷Öa·Ð&§œhn¸Eqøá‡ƒ. ìç8Ã~`6U#S3Mj]þÇTˆ€ˆ@‚ $óú–î}’ þ*òTÝÛo¿íìOѪBD@DŽ«L²8èú–,²©[ïÍ7ßlÎ1k¬Ïæì¿ÿþ(ÅΓ  áÖ™D1Üsfe#±Q $~|ç×MÈæëæ*8è¾û\"¦ kßö=æ^lä5âöÛݱmóɱ‘w\ †Ì|ËR»{k`iÿ€¡Cz¼0­[¨0_,Z›åúu„*£u"WÅ­‚Á‘u–ÙœßäGÕª‡Åºuë’ÐÁÿ`¿‡ùŒÑu'Ö`ª”HÁÜ ýû÷‡ßõ©´I$=ôPS]†<ëM’Èü¡œü‡# +W®´\‹ƒð´ù£öô+1öÛÏ}åïôéÓT3asš3-ŠN8!–êB–á@”¥dÍ û" "1tmËÿ¯ÚÓB_!™J gO X1ØÌnØýnb)p†õ9Á센·£Ùˆe@Â3Ï—óÁû¦›ÓIÀYC#Gºü4)e~u/hi\¾<ìÞøãàŽ;¼-îû¨Q°î®x(RÊ7îkà¬&v”P@ŨSÇ­D±¼evÊGñ&OÞ”c}º¯Ðµ-Ý¿áÄœŽ5/ñöêg›þ­ÙK§æO—vÀ8ЬçZùZ\rÉ%‰i j ɺ¾eBŸdÊýHÁÑ~Ö9Ú²eËm‡." ……€®o…å›Èœvp¼–Â#¾˜YæW³Åæ3ážæNP½zu”äƒ}MæàŽùL™æëê«Ýâ?0•Y«V¡wg?Ìí+ H'ÆÏ×^ Ô¨Dêg ]ká[ËtjôÛ`ÿ&cëV˜q‰{ÎcƸ}«\*è‚îwBUFëD /˜R­œ¿‚;wîòNÖ2SˆøcÆ þ…z™ª^½f¿|%*&L˜`³­³§[3­ •³­[·8D‡«ösÎ9'KœÄY•¯ÚèÃiÌQˆÃ&zâÍ7aÔ±7ò3JP-xÞ9bþ|€/zÁ•,™c³Vˆ€ˆ€D& k[d>ÉÚ*ÁQ²ÈªÞÂHÀ̼ð×_îlû6o>øÀÐðv/’èèo3èaY¾j׆¹ƒÁ„þÚ²—)ÆéÜÙMákÙYA}:­™ŸœZ€»ïvgùp&IqÌ#Ȫ“ v «®~ùÅ}Ø7íã”I=!_¼ïõú©˜^88˜óýË/!C€×^s7½2|tb6gv ÐÚ\¿ñ’eorŽA‘QÆ^i½{tmóHè=k­’)mœÔs>­Â"G%u¥m™/ö5Ÿsºòr’ Ÿ_{RQ©Hæõ-ú$üu人E6ÕœŽy—ÓªR!"v–,š4É>-¦¹>Ü,®\9{½·Äçe>çŽ]›7WóVgÔ»®oõuÊ“¥‘EF|) Ž€'6bz0{´Îrð¡xˆîB^ß[8w.л7ìžÊˆgÃåYÁ‰y霬é[ox­yàìÉ–þíZü$À”j¿úhGùr7ãuæyÇ®äO8è­,¤ïT¸rƉ´HgÎЧ8â‹ûÌó-Xläm®U«– Jب„/Ø9P؃7Õœ]³»¼Må¾ÚFX.²"vâæˆo¾q…FyH§–£N­ " k[Á|Ùq&Mm*'"‚Ø)J[ÞpÁ<éf¾ f‰ É'9ÁA! ë`ÎñPb#><Ó˜â!ÞCRWOw">X7jäŠpØyëÎ 8åWøN‡È!°ôÅn§/σc=쌠Ý2Šâ‰×_‡Mp݆( Ú¸àí)g`1§;m›ý"!\ºMœàÚ<óþ8X”ê©®í±iЩðÒKÓµñóe—Ilî»Òµ-­÷˜1c†Y‹E—.]LÈW>Çó¸¿,—ÿ°gSЉŽ6¥_¨Ù®œ Ë”çß~û­“R-x}¼HÖõ-Sú$óÊ?Qû+Z¢Hª(\è@ËÉ-œt2o^vÛ˜j›nìþÙm†™µ‘Ï£Ô7p¼dÒ¤½í~ó€¬m™´ ë[&}Û:WM€NEü­¤ØÈ«qÿý®¨Èÿ`ð`X ˜(3{_öþø#@$¿Ø(»Dz.q’%Y|pÎkJzž±Îª°(jŠMÈ Å‘ä*{¿x—‚GÑÒŒÅ[2ËûmÙÁXƒ~l Δü£»ƒ3&£åñ¦©4îŽ 80yëSù}‹‰°™È«G•B¯$œNj”*Ty­  k[Ž|ù`®’fÎ7ß:¡¬J!qà¬>Hû 1ãØ;÷Eø°¬C1uªÛ P¯på•ÀûïÃÙ{îqE6–êÌ1þÞ{>Af N]´nܸó΀ª4aJ4Îb¢û}˜zlåJ7u™×™Û¶-`FŸYAqo™ŸmPµª[Œs¾øÂu?þx·ïΫ€ûØ#¼3Ï[—îïL¥Fa+“ýÐ-=Øù(ÝÏ_çW8 ÐáègÓÌáèhÿçd-{)D¼úSUpT§NË—XÄ;<¿Ó~ÝGy¤ÿcØåà”nïrªxÅ¿O>‰¿ì|Ї›¢Îsµ™¤‰ˆ»îrg0]…BD@2…€ÿ¡^×¶üùÖ.\ˆ-6M‚£üáNGaGäW¸Ž<ùq^õО—ü^þt︱-ŒÇŽ=ÖÍ©N÷! ¢hklÙ‰¡ÒGÖgzÑEnÙXÿš‘ˆÓi@Á—m\Æ©ƒ³B™IwÙ2€©ÐLoïØ,3o;£JÀLKУ‡û9Ú_vðÒ)ˆõ½ð‚ëÂÙ¼yà^k׺Ǧ°è‰'·ñáž©ÙBYã–ÌÝ'ZH˜¹©"º¶Å+C‹Ò-xñâÅ&¼ÅÜwëÚ@ýÀZ»ûñp@¾˜ý§?á„ü«µ," ùF Y×7õIæÛWºxÌž=ÛîE‰%òïÀ:’¤)`ÇÛ‚8ÍÕ«ÃøÜËgË·Þ Lÿ]´(@çZN0áqp0‰'ÃÔ¬¹=xSÆ|Öõ-c¾j¨ä ÀÉ‹œlȾG:±_Ïìwãv ŒüÁ‰ƒÜ'“â§Ÿ\ÑŸü©;3‰Îµð ÃÑB³L€Ô¥Aƒýë’±üÉ'ŸTÛ´iӀυùÃjÞ=îŽzeI`p6¥2uìØÑûñÝïpÄ‚…]pôÕC”ú?û,›9켂Éþ_´Rwê¹l¶òµi`ÙÛ" "1tmËÿ¯Ú_Kp”ÿìSýˆ»ÐчîB´ÐMvP0tã°Y–vüÁ‡úGV¬LC‡®¿Þíd¥Ò¸q®è(·Ù“ß|Óu¢ÉŸ’ÌkÃ{¸ÇdJ6 …*Tð¶À&d/ǺD—¡¾}]ëûà‡ö•+)Bî½×}ÅZ§Ê]Û Ž}*ù³m»ÇìØö7µkÙsiÑÖ~\4ö—,oáf¿OûîÚjS ß7+7Nø©œ,…áîcéMD@ÂHÖõ-Sú$ÃqÍÏõo™a×®]Ýòò³=:–V¯¼âN´á :\Ðí‚Ï–|îã¤êõ(äás^ *˜ª›imø\úÐCî3,ÇÂ…ÿ¹5\™L\¯ë[&~ë:gp 0UûõB‰Ä(e ¯R¤š*aÚ“TiªÚ™KÅ—.]úaÆ ×›¸ÅnÕØ1_¤”}ñ6¤€›rYgÔÝØ±÷Í7ß”K%ûX¿Òš³ +l¤æNÝÞ-ì.:Vç§æ6›6ðtJ`|Ï\…4ø»R£ú8n{%¼Y´§; ¾U«ð­eN‹—ìü.å“E’ãæ›ÝTI>ŒªBE@×¶üÿ:$8ÊæérD aøÎ|æLC6eJô3£KgX®[»_Ì~q<Ÿé Ä׆ ®c‘߈–£]o¤Taœ?PPsê×øJfp¶*ùñB‡ÌC«î\е-—à2d·Ë/¿Üy~9r¤Y‘—Ì:kº]zé¥xÅF¸ÎåŸ/>²)ë›lvJ¤tj¾âZ¤HÆõ-Sú$“ò…ÄY)Ór:ÔD•Э[·8÷VqÈ,tº}þy÷9”i¯ù ÌÛ6Šy(2òÞçÎî¸èÓÇ(“_”Ö¯n¿1ÂmÓr÷´áEîèú–;nÚKÒ…ÃéEàÏ?ÿ4ï‘1æŠÿ˜sï›^g§³ñ°Û2Уq¢½Îñ6˜èh@£Fž11’ÍUN|ÜÿýàÕœx@ yžßøüûï¿à áwß}缌Ê—/Æ–×8¢eË–6}dþüùçûÆ´ßÝÏîºÙÆUÚ`#FÌ^ØÂ\ƒ±m{ÔÄO°é<À•W3g†næÆøÏ¦ÕmS*Ø(­ë" " ‰' k[â™F«‘÷3…Bâ%`·™Nº23á°t @ûö‘k¸ä`ôèÈeØqË™–t&ògŒ2}Y¦“쿬óÊt©rþº¶¥Ê7•ÿí|ýõ×Wà³Ï>;‡«pëå¼Îr52­Z°àˆéÔÝ»wÏÿFëˆ" "°›@2®o™Ò'YþÑEo™åñ½ÓfÆ~ÛÂÀHmÈ<|eŠnІøüéÝem( Õ«Gv°¥ûï}÷¹Y ¼}“ùÎ!§Ÿ†¥åu'¤rˆ›v;Òœêd¶']êÖõ-]¾I‡D'°m›ÛÿX«Vô²*‘z>7KþQ£Fa„  Sôž{̧H[ÑÕèE{ó ŽÌïÖªUëеk×þÉ2‰Šq–WaÆŒÕõ°)ÔÖ†€u…ùƒßÚ‘ŽD§œr (2 ŽY³f9«xn½{÷Æ5×\cƒ86Š&üîF,™.ñÄÌ)á Ö—›WÎØüǦ¸ÏåÔ‹¢v—ߺuk_Íy[´ìhNì‡Õ@‡n²É¿ÿ‚Úï²Y¥E¬=–½Â±­w÷Ô_H:Ã-d ÝA[s I3-ÒýÚÆï™©Q¼k¿_^Ûx+ˆ ðšúLÉ¢X„ºUbç&ÓÑåèÝwÃ×Âmuí äÞzÑ~ž/>ëñÝ´òÝ‹Â×®-…™Àš5kð+Õþt.à}~&Eº_Û¶Y_þk'»p2Š"<>ë^eÞã{Y퇘ó"(ø }úé§[öïg±`ÁÐM˜A ðI“&™“[SXú ½ôQD ¿üøãøùçŸÃQ´*ýa~µ¥ Ž“Œë[aé“äJ>+ù¯mœ¤Z:TnÝ‚úòp\žÓy²Ï—×"…ˆðÆîŠŽ:ˆÂîl*û쓽i騣¾â‰Õ64Áçáx³ä2Íyçß~ Ô¬éºÓ•#/Ã[|f㳃ãLœÍÄHçë¿O>‡ð»ö®q4-hœË=¿xsÆ0Óœ|2ìÿðå—¡‡†3Jœð/¿ü‚×^{ ÏXÖ¢yóæ9gÄ”õ=Íú-<òHœ¥N!Gpd71L«öº cü†Mm6ÅœyzZz.÷n'\-1®î¹ç,—n`2]vò]tÑE1ÖPðÅ~ûí·¬´el Ýš¢;&_¶Ñ ?üwÝuºtér—¿9’ä‹xGÁâ"vä&åxƒ{§X”²Ül¢‚7óŒÚElaòd˜*Ê]ê¯ý0í°éöã·oÇë')D@D Áø»îýÞ±j Ž8x—I‘ ×¶ß­ç*ø»?~|@ •üüÎ-Zä Ž´iÓ&?«c¥(¦ð¢¨eù±{Éì“`¿”‰;¢£9s€¶m³·ù—öÝèÔ °[qhæŸLú/ðÁv»m÷Û|ÖH¥Iyýv2áÚ¶Þr8ÐÕÖ3ÚÔ…œ9¦Oà¶Ûn t0ªR¥JÈ‚L«FÁËÐú›1Ûìäø¬ìz²­HO>ù¯2gî8± “"Y×·ÂÒ'Iq4ŸÇý×¶G}Ôîak¥Å×ìw7 ž8š'¨“Ève¿Ãnê0>kzA!_çŸï­‰íÝŒ'$6ï8@lÛÞ¹+eÝA8ã 7%[ÇŽÀÛoåÊÅVS¹qî9'óÜt“;y'¶=×â}&SÎ0(¤e šL‹t¿¾ñû¤ Šb#3yp¾Þý÷ß÷ÒÆK!D€·îœ»d põÕ®Óz~Ú*'‚ÐAšÏgŸ~ú©3¶Æ{\¦°çdoNÚúÚnèxÄg7EúpG<=`½ÔÒUu²Å½ùyw´µuóLtt‰‰Ž&غÿ¼ ñ¼ôÑGxüñÇÁÁµààl*yS%ü*k›ÙyÏh­Ì7“B¡åË—;³!½Å,ËÁÎ+-}~¡”ËÁ÷ñ>x—žäoo¤e¦ã¬M>'#<Áó.GÑqä‹/0³vml²›°öÑr…$£±ªSD í Զߘ78jwpöd¹X{¼Rü=®mL;Z§N€ïº ¿6¦ScÄé{ŠŒ%@vs–ÅóÏÃî!a³œjÕrâ8ÐõÓ¬YÎmt9bÇ,]ŽÞy'çv®¡9Ç´i¡·imz8ϦÞòÅxÇþxâ£ô>k÷ì2áÚVÍ~0(˜ñßÇdÂw›—s¤» D‡XÞ‹ó#Œ†ñÙ³E‹xñÅñàƒš\xéÔN:餼4AûŠ€ä‘À6B̃êO3§ME²®o…¥O’}ªL·Ž×6ºÝ}÷Ýr7Ê ÿ¯éxªçžë>¿Úüjs®½6û,ù›|àžœËgcŒ–6–=&µ€eèÌk /`ó³"‘ÂVjã Žc‘ݾ嚟v,Õ4ìÞèÜ™isssÚ>nlü&çy²t¢Ûœ³™·F×·ÌûÎuÆ™Kà†2÷ÜSùÌ¿ùæGó1Î.t™å¤} ŒNµƒãí¦€¢#Eæ°áì0!Ñ›6Û¢»­±[®ÑÈÄFØÚµ–~m½^3w¢6œø¼MË¦Õø-6Åúl%éd9(aç\8±QGóªd:²T³õ÷ßøµÑ¡;m:ù5×\“ClDzÅÍ_³ÿþ`Ê–¾»kwaذa9³(i©Äâ Š™üQX^W/üÇäF;P£=-ŽÂ§5¼ð¶ÛÓÇÛ–î0zì)D@D@’B@×¶¤`X)GL+K×%EæàíÍ“O ÂRòÀÒü–ÙÇÉYþÖ[3ì±SÖ\µ³ÜŠhJ[ú1cÂsºõVØ=u`ºµP¦ákÐH?º¶¥ßwš×3⤟if÷Fg£–-[F­®oß¾N‡û:–-[æômœhêÏàçö¨©€ˆ€$@²®oÁ¿méÚ'™À¯"®ªènt©0˜ö”nÿ HLí$¦Ãn®Ç¿™jé¬ËÉ2tñ=ᦾtK0 '×0ßÉ¿¢–M_î¸gX–²Áô=6^ê<‡SlÄà³tp0]ŸÃÙ~KX¡Èº¾ådB €û'-ù"E Ð\†#ŽÑ3EÚh3 9ðÀ‡#fuzÅn (:’Ø(E¿à6ÛïdäTkb˜÷êÕ«×Ù\Þ±‡Íª¡ŽeëkÙúZS8;A rÎæ  'Õâ2óxcÇ#s ²ýLÅ-7nì¸=ðÀYE?üðCËókw®¾ ¾?âÍgÈçþàClaŒU?ìB-¬EÑV:y9êfO5ó»vL %ÁQaü&Õ&t! k[þ~“ìlž7ož®mùˆ·H]º¸6íì-ˆl¾K—ºm`GkåÊÀ½÷ÂÄùÙÙe™¡‡/ZÐáδôQ·ÎY á‚©Ö̵L[Ë\è´'æŒÓºu]%:()D ÓèÚ–ißxäóå³òu×]ç8JpÀ7–àžÓl ü˜1cpß}÷9»(Z,äTFD ™’u}Ë”>Éd~7‘êö»U¬X1RQm'ÀçgΕæ3«Ý9Ïš±6Šæo¾é>ëŽq„+@¢›/]…Ž;v_km¹+wÓMÀK/ÁÒV6“¯½æ>k³o€“v"ÅDÚªmÉ  ë[2¨ªN(X›7»PëE –9WQ ¬\¹?üðƒ ɯ3qØïYï\ž>}ºM”ýÕI3OƒÍ´jÕªž…šTÐB*~V¬X1§V­Zû›"ínK£v‘ ŒŠ%¢¡ÕªUsrUÓÝ(U£T©R¨ZµªóŠç˜§ðqKH¼‰wÖk-Ñ/Eþ4a•9úä‹xG[·nõíÍ©#S%ó÷ÃêßË 9¦•†?ð3Ï8ž«ãw»ç¹ïßý»Tp¤M¡^»vmO‡s ø€¿žo‘Ò'é÷äâ7%ŸòðáÃénä‚ 7…£ï•꺫“YÔ™7>ƒÃId$I²×"wnóYS„«‹¯¾ «àÈß¡ïá=z@~óQQ€¾ËÏ@q¹dxÊ#ñ=ÙßwÁûòù|óžÏ P& ©5ub¥ºÊi*K[¿h(×9Òêö½t–k&ªåË—»mºd»gÂ>F6§PÕ¸­ÔSôæâzé^ld¼·Ëö®M¢q7:RÇ÷¶O$Àg[øý8qâ„áP¤ïã=tôÉ‹¨\¹2JÜ™â^¿~}é$½£õ¢ J$@¡@ànÏ·Hè“ Ö}Pw#É(`¸ßÓÝ(Xw×uGàÆ Ó‘HÓŸé;«:ÿè6ý&ó…¢µV§!u’ÿ°cG`ÄF¶vªC“^_…EšÚ\€5=šÖ%{vÛQü|¾…Ã]dÂÀæÍ@ùò€ N%Ù‘‘ŠSÝØ¡A@³W©VC>¾úê+#%ÚxéDÖôhëׯ—göüý÷ßò{àD'bŽBQo4Y ¤¶wßòB´KöuÉ‘#ÇK2£ïQYÖ9×ä£ö4Éåã™3g6rø©­VEIÌ[ªT)§c"qƒvpþ¢aïDlPì—{ýÚ›8~üxôášî-_büy[ê˜yî“7w¡¶RÿKmÚà·Ç—y#` „$>Û¼¿-yÏ,!gôêe¦SΙ3€ü´0,ÜÕé(>!ZhÃ!©`A`ÌÇäÌè¼yPcÝ:`ÿ~@~’3H€âA€Ï¶x@ áS^“Ñ&uþ\rk$¿ã ëMu»‰- •Z´háÍi<–H€BŽ€§ç[$ôIㆨ»‘¦ò̘1#zöìŒ*ðš$àD@SÜlÛ,[LŸèféŠ‡ŠŽÔ¨Q#@'Ôø""XòÅõµ ɪk´wÐ  N_•ÊrB‰Ÿo¡t7X—H& Ï—iÓ€—_6Ÿ+ @Þ£#™Hè´]ÅC‹$çé;ï¼#®S?}#š"­_¿~2AWfè2H î*8²•/bùS9w>º9±äï›uåÊ•'.‰mvÜeM¹$K–L÷3bÐô)ö‘/_>ûU§4mÛuD+Ž¡éÔìJ¥K—6\•âxzÀ;ò˹Vfä-äá߈ˆÔ°u+6‰ €8kIZ‘xä X‹x! ˆl|¶yÿUp¤³òçÏïýÉ<Ã+2a‹›Ö½µj™§>ò$¥­WÅëŒÌ!CÌòTPäj¼à¾û¼/×gè¬!êýýA–eF >ÛÂçNë3wšôxÖ­[M›6WÞ{î9ã™Ý09@âUCžD$@q#àéù–5kV‡B±OÒ¡Z±¹©ó(N ^&ÀtsêÔæ'ö0ÍÂ…¦ÛháŒÐ„ êÂÛ±cx:ÿÈЮ]3]ˆ‡ ðàåF€Ï·€¡æ…HÀ‰€ºÇiF.­Xè0¸:æ© üƒj[Âð9íçøæ›oŒÌ@Å‹G¡B…D8ì,÷Ø/³QW¯^m|6lØ`LÄJ“& zÉìÜÞ½{#W®\>¯ Œ\ÎÿãÎ"Jf¿x°©‰{AV9r³øÀ8p ºº 4\ÀY¢×ï¶`®[P§ÆÛ…ªõßæ|¤Ve—/_†þ¸[hGÀ-»ÜµCaú€‹J—¨žŸLº•›¹Ø{g“Ìú‘©?øî‹/Œ jëÆ  ð>ÛüÃÕ]©’ª¿þú+4E ÿÔ6]EAú3Jíàm±q£¦ºµ­Ýý[3à¾ñpçg Z¶4×ïdع{<‚H àøl 8ò½ v¤iš…5¯F @'ãTªdÛžßúî?a‚):ò•kSx’ n«ø| .^âCàÜ9à©§ bóo¬¦°TïˆÇ:t0†xãS,ÏqC`«˜t|!Ó DÙõÇ8¥†0EŠŠŠ+†£bæ¡B£Ã‡ÇiŸF%yàk¿F—.]ÄŸ–ø¹â ù¤V*Dóm« ®-ÄÝ ]»vµ­zü>yò$:}Œ¤¨“™2ÕÀ.Ë_ä&ò‹ÿ³Ï>3¶ê äwß}‡zõêÙåzq£ŽžÙEÍš5íÖBgQ“»è(_Ê»VJÛžN,J–,y×cy @üðÙ?nñ=kÏž=†˜¸lÙ²ñ-‚ç ÍP+fŽcìX3­˜8ÅÊŒ˜Cã*6óHI¡ù]ÈO2qÆ0…F’1˜A$âøl ñ êÍ;ß~û-ºwïnt¼è²¼ ø€?Ÿo‘Ð'é·ã¦`MÇùçŸbüøñt7rÈ›F@²ÅB† ‡"[Iêè#?}¤ßÁt™½›ChÖɨq‘"EÄ5ÙR æóÍR·‹•%ƒ€$<‚NÒTñªŠŒš7²e#_Ðq„É“'cþüù8räˆQtQ¿"Ö„õë×—ß'ñÛo¿E´D³ihªIí Q}êt¬Aþ$ šÃà„æ $‰smŸàÔ»«Æv#øòË/ã\À¸qã 9máNÔ¬™£óϤI“l§¸ý>'RRU6Ú"_¾|–OÓ¢¬T±©ªË$œ~`»µü& Ÿà³ÍçH=¨–§yÄäq§Œ£\9ÈoH‡¡sgS ¤öðÞÆ©S€šEÊ;¼”™^±t)@±‘·$y< ‡ŸmÁáJWÕÉA}ûöãÜŒâR÷F(Uu! xð÷ó}’ñ¾5N'ꀦôÔ™ä/¼ð‚Ó~n „PW‰¶m'ŸÆŒägOtè›Ñ£O>TDƒh4\a|¾…ðÍaÕH@hªNí¢‡1Žºu£Ø(6›Øë—.]ÂÏ?ÿ{³Ëõ«2 vàÀ’’îA|ðÁÆù«¯¾Š~øÁ³¿/Vþ*$ê VRªµX¶l™ax¢îšÛ¶m34ƒÒG}„G}”b#—”¹Ñׂ&8Z¼x±!’Q¡Œ½XÆ× ôeyšMÒÈE¹wï^Ìž=;zÝÝ‚:õ¨Í™-Ò¦M‹_|Ѷêð]´hQCyhÛ¸sçNÌš5˶êô­¤žþyÉ‹)‰1ïDëÖ­m‹–ýÖ?¼ÚIÌtj–½…¬8 €EðÙØEb`~@IDATÁQÂxŸ> ´i#>‰b”¨«ö¡.Dö¡3m’%³ß긼e $Åã¶ß7må¿ÿè×X³(_Þñ®‘ „6>ÛBûþø»vê¬q:PSÙÐ.ÜßÄY> @ øûùÆ>IßÜÉ¿þú Ï=÷œÌòÏíbï›’Y šä T)`ΠE `ûv U*’!kàóÍÚ÷µ_ê¢'?iÄàh×bªáØVO}®ŽGFöÚÚµk ×å2eÊÈ$ÚrPaú­[·\BÙ°aƒ<çKaĈFöumÖìIï¾û.*T¨àòÛÆ4iÒ“œÕ”„A&4ÁQ ê«ë=óÌ3Ei¦þýúu‡í¶•‰'Ê ûÎ’Š#fLBš¿Û]ÄNÓ6|øp̘1Cr/ßt8åøñã’#ó)y±7‹;Q¨P!c›m=Ô¾Ýü uª¦Š´4(8rBà $@$às|¶ù©ÛUp¤n  p{ w¸& Ž°šüØ1àãÑhG‡ÚÅ«ûÐÿþ±ŽÞìqA~F¡Z5 gϘÃDKŽÊ•!ƒÔæŒPMÇ×l1¥p‰H ðÙ w!ðu8qâêÖ­k¤¯Q·\ºJþðŠ$@þ%àïç[8÷Iú÷Θ¥kÿï“23BÝè§L™‚¬Y³â²¼FС1o4œxÏž>ýX¸Fpë#¦‰|¾EÌ­fCCŒ€ºä}ø!е+$5—cå´OT†¸!:yÇ’&uÜÏ5ÏÔq¨›Ø?iÅYyx·oßš&­Ì¦Õ”gšv×f&ræÌtêÔ µjÕ’¾ïcxï½÷Œ,@#÷̘{C‡ÿÛ,vÃ|P]5¨ƒ¼'e¦ Ôz\ß‘$@$Nüý| ×>É@ýдÚ§ÛSf54Ô  ø€€Ë¥áΫ]å3g’ˆAaE€Ï·°ºlŒEÈ|I¹üø£YaѺˆOLåU7½y³é³•Kq!°F,óÕŒDÇñëH'óäÉ“‘7o^üûᅥÐHÓi&¤¡C‡JšÔ¶â\8§NBƒ d¢íÇÈG—¢¸`æ1!D€½oñ¸ê8tZrz¨•™-nˆ—ÜîÝ»m[ìoýÑÔ«W/$Ož<ö.§u©XI_RmqôèQèÇU¤ïTý¥vl¡êH ³1$£Ü]CGj§éç$@$@þ'Àg›ÿ«ù²Xñ”-[Öÿ ³+hz³AƒÌ—ÞqãœW¬ Yh%…Žù’¬ŽGqù 1dD$q2Ë­3>ÿܹ|n!°&>Û¬yß¼­µZ‘ëûó[o½…téÒ)Û[µjåm1<žH€,CÀßÏ·pì“ ÄÍýQFë†È †NF9rd .Ék„9uï;èß’ù2(i¾ë{+ƒ‘ŸoáxWÙ¦P%ðë¯@Ó¦€d‚5ú\eèZÒ‘;×–žÎL}ú`’ÌpÕþ‰ &.G¶s4åûàÁƒ4ðꆩ¥ÆIg·ºb~.Òí4wƒ,H ±ëô*«`èSñ-Õ?úy·ÐœÝú‡£¯øžÆEl¤åi®EMÇÖ£GcÙÓ5*V¬h¤\«Zµª§Ã‚¾OÓ“hˆˆÓcÛüAÕ,Ó&8 e7Bÿµ>~%ë‹xÇŽæl›©Su2b €·øló–˜5Ž×I*eÊ”1&«èD÷Þ{/Î|¬ÑBÖ’H€<ðçó-Üú$=“LøÞ—^zÉè3f J–,™ðYBÄÐI7š\¡kWˆûNNŽx$Aø|‹ ›!MU§:IPƒ{î<¸ÖgŠ:Ä«›ÑªU@•*Á­U¯®Y4­û_|%K–àŒÎ˜•Ðßêt©âIDI¬ãü °: Ž|pÕ©ÀŸn©S§6fiZz¦¦ØÜ'+þ ©œú¿z Ž<Àá. >Û|ZG2d@|_x–()­ Ç¢åËMÑ‘ $@$|¶%„^諃»*:š*ŠÔŽ|H„Þ bH€FÀŸÏ·°è“ôóX³f >ûì34hÐÀpª÷óåX|„ÐTâšæFÓÝ0H R ðù©w>¼ÚýÍ7ÀøñÀ#@ÆycÚ¦¾ ë×â=á÷} ºw>ùĜЩý­bÆÃð’Àm™û‘¨Ç4îÙ³g³K—.Þ½{ãø… ö²DNáA€‚£ð¸¡ßŠ}ûL{£«WïZ×ï¿ÿÞpoÊ•+×]å$@$@$`QQQøå—_ iP&9sµ‰×w3ôaÿ’+ãǸï>ó¸0_ÌÉH€H€lV¬X!i6ç¡E‹Ù ð›H€H (ÆË(¢:BMœ81^÷A©4/òdìúa X—À•+€$°‘T«fJ5ûD8b‚Mm&&9˜9ÓLŸé–þù'0l$‹dÂP¿>ä]Út[òÇõ¹Ì?þø:uÂ×_m¤NëׯŸ!2ÒLG ˆtEú¿€@µÿ×_Í+=ø Ç+ž?»wï[Á û z¬%w’ €w4ó¥K—üêˆè]‚´ #~ØQp”5+$Ç5$…¬)F¢}|ðïk@$@¡B@SŒ¿ð H—.Æéô ‰ÀÉ“'ñå—_¢^½zÈ“'OjÁËZ€ü9ôécõ–°þ$@$@ö 0Sc*d¿’Š èÛ×twÿûoÿ ŽTì4eŠéj$™È!H/ƧOŸ6&3©3Ñ#bC•iÒ$qÃ;< ‰À·ß~+)¢‡šW\¦ßRµxÙ% æ b¦€‡Š©à=÷7šÁüYÃ…K$@$`uC‡{÷ï¼-ê]k4Åfl'ø»•P¬P¤0bаáÝŽŽ¼ýÚ—0gμýöÛØµk—¤”K‚Ç\Ü¥^F¥J•¢ôïßgÏžÅÊ•+ ñ‘~gÊ” .4œ¢ä € ŽœpƒÏ üû/Žœ)¯„§¥þÑ×”jåË—GÒ¤ü§éóûÀI€H€‚B@gH[ÔM^Ý“lQ¥ ðó϶5~Û¨ƒ‘Š…4-ûo¿ý†{Dé«Bñžb•7o^Ûaß3fDÛ¶mŽYk*Pb x&@U‡g>Üë b{ÿ'Ì?Þnþ†WQeé… ˜NÍÌY @ÈPw#5jß‘ôŸÅ‹Í=@^ê"©ål+ €/ ;v D>ñ›:t¨/‹fY$@$@$à5M­ñÅ_³â‹©­ƒbÐt:;sçšB#ͮޤ‰9Hl/8ŠuWI€H€,L@Ó§½õD L™b~{ÓœâÅ‚Áƒ%€æÍÏ¿ÃA^EIêf©±{÷nL:ÕÈ&P¦L”,YÒÉmrùòåÂq°±~6Ò iBQ€eÈ!ÎØèªgT<@ÁÿøŸ€ŽŽ qOGšNM£ŠÊq$@$@$&l‚£ê±h[°}[¶˜³sä… ݽ#G)S/½t÷cy ¸#ÐCòrêàî\µÓÜ   &Ù³gãòåËébLîV¹¶dcA³fÀ7ß­ZŸ|à´JíYO  »P£õë¾}üé'௿€>0CŽ{ᆭ¯º:yS’À C`óf³œ“'Éö…iÓLkݺw/+¸uë–¸G2&!]SeïH&JÞâ¢ÖRñ‘~«(|‹tb§J• ½{÷F¿~ý%KÛáü&ð Žü•EÆ"`ŽJ=9ÙG•+WŽUWI€H€HÀº6n܈ W®\–mÄßC^΀™3Í[ÕßMp$Í–T©ÀóÏÙ²Y¶é¬8 @ ,Y²‹-ÂO<† ¹6¼< šN-mڴƳ‰6}úØ[â·þðÃÀøñ@—.¦³QþüÀôé¦{^üJ´îYö®F7oÞ4ÜŠÞxã ¤H‘ÂhTÓ¦M£wJÀ;vì0Æ™­<ñ7ºA\  0ÔB"6J#uNçm½Õ²ÌÞ¶ÌÛóy|¸qåé‘Ô÷#‡èˆbFÚüóÏ?8xð ¡Pµmã7 X€UÓ©Éû>ÿÜ|á–dz!0R;`í<µ3g€&M –µÀGÅì‘ôØXµ hÛâî³K$@$@$à —$'§Šw§KïjöìÙ½9•Ç’ €_¨»‘ƳÏ>ë—òYhèØ»Ðwe1V@’$ŽõüòKˆã,X4ok$@$@¡GàÜ9 }{àèQ`íZˆSŽ™S2q¹ ýÛ?gpü¸é@äò mìÜâ¦ÈÐ)ºvR¦ôQÁ*FEÞ:‰W]Š+†©S§Jº¹òn[ iÓj×®ív?w ø@bÿÍ’I@蛘Xüy#Ô Ð]ØÒ©U©RÅÝ!ÜN$@$@–# éÔ4ªW¯n|‡út†Ž ‡4]ÚÓO§Oï¾ ìÜé,6Ò¶èÌ} ×Y7šGÜ#GšKš†A$@$@ñ!°|ùr̘1C„­MСC‡øÁsH€H€HÀ§®K§>›4•û0}Š6¤ ;v "|6…F%KšÎöÃ+4kf¾¯_O±‘=.“ @(пï’}ËHS¦BQ|Yµ*päˆûZ?ôë>R÷gÄO›6€ºåEšØèˆÜ•.]ÚH—Ö¿ãÛ“Ø(þ”y& €/Ppä Š,Ã=I§v )ðÏå4¹§Ä=$@$@aJ@Žò厼yó†t Õðí·!uzô0;Pu]_°_}Õ|ùvÕÙ3w.Œg¼ÚÇk¨#Òüù¦ñƒšÛø_  ð†€¦Rë*Ó83dÈ€‰'zs*%  ¿X¼x1þý÷_ºùpp þï?`É`ß>ÇzäÈ/hªÉâb8NØ¡•*›7›ßöû¸L$@$ºôo»N²TQÏÂ…ÀС€º¶—+H—.ÃGô·S[±ÁÏ!ÔÎbÝô¥ØºÊž¤™pzõê…ûï¿S¦LAÍš54¶oK'µ-…šªÄbH€|L ©–56qâļ-û±Çk.¶æ¥¼=ÇG±¼;‚<¸D2Øê¾Ýêp¤Éj‹Ç   p pòäI1úÛ‹Ž;†|s’Ê/Âٳ͙êp$“H 碸TüÞ{MËáÌ’:Uãý÷Íi.“O$@$@$à@àСC5j”ˆY_•”›öÙ¯h'£¦RSËtí”d @(ÐtjÉ’%ÃSO= Õ‰¨:hJ™'€R>‰Ð2ÅTK—šétÔõwÈsÐÙ8Q"`Ý:Ûšów½z€~$@$@Ö#:µYgý[¯ÿÕÁèÉ':uL×÷+€Þ½úõ­×¶P¨ñW_}eˆŒôý>wîÜÐßRúI—.6lˆ-Zˆ«TULš4 ~ø!.]º„ *ÈÄØ·Q«V­Phë@$†àèÀÆáX§CFŒ¡=„>þ™ïtn°2y0©— Xmº¸jŠÚÿ$¶5jÔ@"}ª3H€H€H ¨»‘†Ò©éãW;XsåT|ämØÄFzžÎø,QxäoKáñ$@$@áN@;'L˜ VõŸK:Îñ.S¥i*µéÓ§£qãÆ–í†û=cûH€H€LšÞcíÚµh.9W²dÉB,~$ â¢eËL× užÐÏ©Sæ;u>û,a¿yò{˜9âœÜ¾m¾k&ôG… ~&¬|žM$@$`]úøá3=¦:Ûi¨ãG&‹¸þW…C½E©¥B"5›˜)ÝöíÛ‹3þA,Z´ÈøÌ‹üyóæE©†o¾ù¦!BŠÞÈ KˆÇ’%ÚÅJ† –-QI”¿›åÅÐÃÑöíÛqõêUæ>•{Æz ø„@( Ž¢¢Ì&&NÓÔ|ùb–²¤}ï/¼x. @8geI¹9_Ä­¹d`ï¶á±B¦‹~üñÇHŸ>½Ñäs’“¤[·nF‡¤vL2H€H€H Thj}–i*† > ál^C Œtf¢ó2RÉm0ÖÕm">¡iÏž{رòûxâ Sd$& òû#>%ò  +×OqÑ1]‹ìûEíÛðÀ¦ UÔp·o_û½\¾o¿ýÖ˜<¤ÇuëÖ¡ðgF?€žW°`AôéÓÇøœ›Á%’ËtýúõhÔ¨‘1!I²1Ý­xî'A…àM ·*¥Iã9µ¦SÓ¨R¥J¸5í! ˆ`*8R«XO)c‚çÆ È pÏ=Y&Á¨¯I$@$‰6mÚ$©PN`ðàÁèÙ³'ºté"éüïÿøqãR°úݽ{w·™m²gÏnL8ÒIG  k TÐÚ÷/,j¯ÌI’$AÅŠâ=l œ>}»wï¹tjW®Íšsçb"µ’g @ ÌÕ‡DëÖ­‘Yrq.\¸'NÄ?’7EÓ>ùä“ÐÁ\ÙøôÓOÇò?$@$@$ ´ïò?þ@Û¶mÁ™÷¾»#š²¦F Søc_jªT@Ó¦€ºðÚÄFº_'Íh*ðŒ!÷òÎm–ûe¹u(Zò»Ã¼žºi*pŠÜ3ã Gýúׯ3fžÄFáØvµIûÀ5]z¥J•P¤HŒ3åË—ÇÏ?ÿŒ_|Ñ­ØÈ_õa¹$@Á!`8.\x†Xšg³UA–Ÿ9pàÀQÛ:¿IÀŸÔᨤLYI›6­?/òI€H€H `ÔÝHÓÅèj(…T /Ï>kÎì¤Km(ÝÖ…H€—À­[·°`ÁIRÜøØZÚµkW<òÈ#h×®>ÿüs#µS©Ùèð›H€H TÌš5˨Š>¯¾!°hв%d*PªTÜË,Pò›’¢Å%mÝ 2{>_…KÕª™“oÔí—A$@$™d~ Ö­óœ‘%2Éx×j}¿_$ò¢ÜÒ4é7Ī0ä@íØ±£‘­fÍšh{‡”G“€å ØRªUM”(Q>[knÞ¼éÁHÎv¿I nöî5óœê,”Øñ矖ùÍ57ƒH€H€„€ Ž4jètÍŠÔ©U«ýf @ ¬_¿§NB=œ.YT,¶lÙ‚÷ßeË–ENõ·g @ˆÐAµyóæ‰CNQ”.]:Djeýj4lI¯j¦¶C¯Bçõˆ™Þ}ÐTi±GGeu®\1EªKÒüù1ë\" ˆLêתUd¶ÝS«E€¤ImrOGÛ·oGçÎ #Í\SWÀDÍ«c¼©Ùáì÷’@HPJµ·ß~»èhIbiû\W/: ØP'}oßÞn£Ý¢ºiTÑÜ   *8Ê‘# *r-â»_ÈÝVˆH€ž€-ÚO<á²­É“'Ç€P¯^=—û¹‘H€H€‚E`X!húOº%ìhJoûÐtf“&AÒ¯Øoû²Š•45šý+·˜, jUàÁK—â^$ ?½zQQá×6_µHEÕÆ “ôriP§N™¤*³TÝÄ•+Wзo_T¨P»ví2ÞߊÂWŽô7ÅFnÀq3 D¸IÝÀX¶lY‘ÿý7z¯ªµ£A6'O×®yóÚ¶8~Späȃk$@$@Ö'pæÌìܹmÚ´ ‰Æ,_4iUa%H€H€"€Ú««ÝººBH:÷$À&“ X™€-ZÛ¶m­ÜŒ ÕýÐ!ॗ1¹73…š¯*“*ULIçÏCÞÁ«W!)]Ìï´icös‰H€H 2èxäÈ‘ÀÛo›c“›i8#£õqoå g"uÎ+¸:yVEÖ¥$ÏiŸ>}Œ~ídÉ’®]»ݺuÃ!y¨«àhòäÉ(Y²dÜ/Æ#I€ž@‚ŽÂž˜`'N:c%O×E©à({öìÈŸ?¿ë¸•H€H€,F`Ó¦M¸-¡NM-æ›6…¸QZ "«K$@$6´sRŸîܦ¡l @ظ*êÍêàZ(º×†2pþ /è$¿ÄåËþ«qúôÀ¬YÁPÓ9éÞ{ýw-–L$@$š6]îôùS° DDC±‘«;5I,uBÐÖ­[ñꫯbß¾}†˜è•W^Áü§žz  À{gN:iÓNŠ»„f;Ú¼y3ÅF® r D89E8;6ßS§±Ó+]¬®\I™Ôê—å-ó×_E³fÍœöq X•€ÎѨ^½zP›°p!п?ä%xöÙ V…' ˆ`¶tj­[·Ž` l: € |ùå—¸páÓ©yyó¾ú èÑÃÿèûèG<âe!ñ8\],$@$@‘I@§5kÃ’†»QïÞÀƒžÈâ¢Õš"V3Iö"ÃÕhÚ´iÑý×¹sçÆûï¿Áƒc„ ;v¬!FÒb6lˆ?þØ8ÇE±ÜD$@ Ãÿø‡€<°P¦ $é§Q¾«»ªg5Gh•*UüS–J$@$@A °qãFý¯H‘"A¸ºyÉž|È–ÍœMš.]Ъ “ D0ëׯcñâÅ(W®œ1C2‚Q°é$@$@$ éÔ'N ŠfãvóŽZ¶Tø£sQeÜÛ·Fl·ò(  p$ ÙÁD8;LŸnNÀt5&Žmk›TdT¢D ClÔ¡CìØ±#Zld_Fz± ìׯŸát4cÆ ,X°_‰’XÓ®1H€HÀ:¹#Ãí #ðÛoæùê›ë&4šGnq3 €åœ;wÎxa{üñǃVwíä}ôQ Q"ÈK¤û´¦A« /L$@$1V®\‰óçÏ3ZÄÜq6”H€‡€>¿ÔᨦØ%Üwß}áÓ0?´DíU\4|8ðßðá‡@Ž~¸‹$  ;’ µj'N3gmÚØíä"4=lŸ>}0~üxdÊ” óæÍC\ú­“'O.“Ye6+ƒH€â@€‚£8@â!ñ  ‚£T©€üùÝž¬‚£)Rˆ’8!1H€H€H |óÍ7ˆŠŠr9C$Í·c6©8äbþ|ˆ£D ®Êk €kÚ™™H°t†p͇[I€H€B—ÀBÉQ}íÚ5¦S»s‹fÏš5R§Ž¹g{÷¥K›“]d<… C4:ubŽá ø‹€>‡Tl¤®zúœ âüO51AåîÚµ mÛ¶…~«€Z‹ræÌ™ 2y2 ¸"ØÕFn#ÁÑí¢`ôØÄд.±ãöíÛØ¼y³!6RуH€H€€¦SÓ¨®>¾Ž+W€æÍ!/‘ÀÈ‘@‹®/G$@$@vt&åÒ¥KQ©R%äÉ“ÇnI€H€H ô Ì–‘Kí³l©9Â"<&O†¯€^½Aè\Ózõ€5€wÞvî¤ØÈ‘×H€H€üE`÷nóùsú40wnäˆnˆ­ààÁƒQ°`A<óÌ3X´h._¾ì„YÊ—/½¢Ê1bÖ®]K±‘%n ð:ùŠ$ˉ! ö GâHùVxùe gOȃ-f·.íŸÃ³gÏ2š#®‘ XœÀ¦M›%K+V, -‘‰·†ÀhÃó¹+N¹   *¯¾ú /^d:µ Þ^œH€H >Nž<‰õë×£iÓ¦È!C|Š›s¶nž{2° ¼ù¦c³òæ…ˆ‹·qH€H€A@û>eˆ_|a:ðâšÁ¾ÆŽ;ðÔSOá×_EæÌ™1eÊã£éZbõ¤¿[~øa 8Ë—/7DI³fÍB… ‚]u^ŸH Ì Ppæ78(ÍÓtj{2T6¾]¹þðÃƾŠ+ßü XÀ±Ò¾F´)2±Å° ^µ èÚ3& —çÅH€H€HÀ%¹2ÍTÓ©µjÕÊå~n$  P% Ï°[·n1šÜ MÓݯЩ5k¨Þ1Ö‹H€H ÒÌœ üò‹™R-ÜÛ®¿IÞ+ÁaÆ!** C† 1DEÇDzeˌϺuë°bÅŠh*Lúè£.]ºèm\   àÈ_d#¹\›à(qqƒÂ8ààÈ™ · X›ÀO?ýµµ­\Ùܪ5Ý»C^,Ž uU^‡H€H€Üøï¿ÿŒ•U«V¥m»{LÜC$@$¢Ô @èš4i¢5 \µ'Þz+p×ã•H€H€H .2eŠ ±Ñž={¤Ï·#~üñG”(QÓ¦MC™2e DyÅjðÅ_4>ê.¼Jf£ê§N:tŽË?"C$à3ù % Š&`]Êmlr'8Êž=;òäÉ}H€H€HÀÊ6oÞlT¿R¥JmF¯^@Ê”ÀèÑ'‰€^š#  —Ô¾]EGO<ñ„ËýÜH$@$@¡JàСCЉ’ê *UªP­&ëE$@$@Càüy`Æ ˆ°&bšl4tÒ¤Ix饗Œ ®ýû÷Ço¼äÉ“»„ Biu¦Ã°K<ÜH$àg2GA>& ‚£4i°çh:É# dÉâXþÕ«W¡¹F™NÍ‘ ×H€H€¬M`Ë–-H’$‰X΋ç|CS—Ž èÌS „Ù³gËs)1;;Cáf°$@$@^Ðg˜FÛ¶m½:/\¾t èÛ"—±$@$@V&°w/P¡У°fu[rêÔ)ìÞ½;Î 8xð á\”3gN|÷Ýwxûí·ÝŠâ\($ ? Ã‘ŸÀFt±*8[£={é—Slß¾ÝPäRp䄆H€H€,L@ŽJ•*%šÛ4n«N$@$@ # îK–,A£F-[¶„ƳI€H€H À4Z™=©éHÂ9Μöïþü8|Øüèò®]À‘#@áÂ@çÎáL€m# °>}14&[Ö­k…;×qíÚµhß¾=.\¸`ˆŽòçÏï|P¬-C† 1ÆQ§L™Bó†Xl¸J$z(8 ½{bí;?ŽSÕZâßm†îÈ©=jK¬AÁ‘n  °(#Ò#û÷ߣE‹~oèvåZ@ãÆ~¿/@$@$@^8}ú4:uê„{î¹ãÇ÷ê\L$@$@Á&°sçNc °{÷îHš4|»Í-Ú´®_w$®©ºóæ¦ØÈ‘ ×H€H€‚Eà³Ïu9zä‘`Õ þ׊ŠÂ›o¾i¤BK:54ûËË/¿ŒÅ‹{,T¨ãbÆ Q­Z5Çr' „ð}s º‘Xu7’Ø“±ŠñíÊáHGj¯è”3F…ø  ðu7Ò¨T©’Jw,rÀ`Ý:s6j&Ä8žÌ5  ð#Îb… ÜÏ?ÿ\,eÄ’A$@$@"ðå—_µmÙ²¥…jí]U%C‹ˆƒ €W^òå‹ùdÍ $Jä]y<šH€H€üI@ŸMú±Zèdu5Z½z5zè!|ñÅ4hæÌ™u®_¿¾Û&éq·o߯[o½åöî  P"àRp”$I’æ… >q·Š^»v-™ý1Ë—/GŠ)ì7Åy9Žq® Œ?›à(I £ w‚£d‡Îze @8زe‹ÑŒÊ•+»lŽª+Q¡B@2‡_O.w»QMå=U^XŠÜbâ  ˜4i’‘JM;UÛµk„ð’$@$@$0+W®DÚ´iQµjÕ„¢g‹±Zµ.^,j×ÑŠ²Z$@$@I@SzΜ ¼öšµ›ÿý÷ßã‰'žÀÑ£GѵkWŒ3)ÅFpÔ¨QX¶lzöì u1Jž<¹SCµyéÒ¥hݺµ!Tr:€H€H  ¸‰ûÌ;q©ë¥K—Óœ’ñ ŽâK.Äγ Žþ3g³ÆýóÏ?’ü0žy晫8«C$@$@ñ' G÷Þ{¯ŠDQ+®]š6¾ýПJC‡Æ:À‹Õté€Gôâ$J$@$@~&°oß>qIxÅp5b*5?Ãfñ$@$@~!páÂ|÷Ýw’ºº±Ë@¿\4À…¾þ:ðË/À°a=/G$@$p›6™¢X1B½z )w9!DwðÁèׯŸaÎ1cÆ <ùä“Ñ5Í•+—ôéAÕk=z4úöí½Ï¶ ûÄDžÕò°f €E$¶H=YM«PÁ‘ÌÚs4Ò¤òäq¬¸¦SÓ¨X±¢ã®‘ €E ˆã#~þùg—éÔÄýÖ°«W±‘NZ7ˆ¥×öªÕÅŠAÜ#€Ø‚^¯ áÁ$@$@$àC7nÜ0¬â¯\¹íPMŸ>½KgQ$@$@$k×®ÅÍ›7Ñ AƒÀ\0WéÓÇtà– Àç%I€H€Ü˜0¨SP'¾Å‹­)6º*•WqQïÞ½qÿý÷cëÖ­b#[ãu¿NX>|8Ž?nÛl|¯Y³6lÀÓO?"EŠ8ìã „2 ŽBùîX±n'Büþpö\"-êœ÷›‚#+ÞTÖ™H€HÀíÛ·ãúõë.G:ƒtöl eKSltæ  J „ u:Þ¶m €jÕª…K³Ø  #°bÅ £Å 6 Û–g˼õ˜#a{Ù0 °”Ù±#ðüó·\@²‰ÎîVjƒÖU…CÕ«WÇ矎æÍ›b£b:kÔEh5M±¦„^}õU‡#Ôý(EŠâ/ù  °¾^XèfY¢ª 5kÊ4¥N¡‚£Ô©S£D‰Nû¸H€H€¬H@skkT®\Ù¡úS¦˜¹jê§ùÇer š4Šw8Œ+$@$@$`Y›Ä÷~äÈ‘(_¾¼¤ jÙv°â$@$@$°råJq’}ÀHJ$@$@$@þ% )>Ë–¦Oš6…1¦èF£ãߊ$°ôüÑxVG£AƒaáÂ…’&­ÇR5j$}ÄM0kÖ,|óÍ7Ʊzž–õ¼¨¯rçÎíñ|î$ P#T+ôßÿ•M™2eo+·qãÆñ©R¥zÜÛóx|dÐÔ1öq[òÊ賜$_Õ¤   ›7o–¢‰—K[{Ö¯ºuòå3Œÿ*•¹gÙ2ÛÞ}ëË·æ/Ϟݻóx4 ø‹À… СCyÆ¥2fr&Mjt/øër,—H€H€üF`çÎ8zô(^yå¿]#X¯[Ô®¬«óº$@$@$àL`Ü8ˆ» C†=xé%çc¬°E:wîlô Ï;­[·ŽsµGKÃ5…Z= G¤×Å&_…J¯½öZœËà$@$*ŒAy¡’ÞGΜ9¯yψT{÷îÅùóçQQ­$@$@$&ÔáHûÒ¥Kg´h÷nà±Ç€4i€¯¾²fMXC÷ì:uš5ƒÌ’IXY<›H€H€|E`Ú´i8räÆûï¿ßWŲ  8u7Ò·tj£F}û}tïp¬¼ 88##ÑÏ<,Yy‡æÌÊ”q8Ä+QQQ†0HÝ~ÕhñâÅÒïRP²ÅôéÓGR¾u<Ú-Ê*:Ê’%‹%°’$@$`O€)ÕìipÙ¯4šG~ÅÌÂI€H€HàØ±cøë¯¿P©R¥è«j‡îåËÀ‚KþèÍñ^xóM@ÞcÑ¿¼‹à‰$@$@$às:›SŶTË    X±b…LIƒjÕªY¸ŽUWÇ}7-\xòIÇ}\#  @ä'(]Úµoüô“5ÅFêˆX·n]#µx•*UŒ¬.ÞŠlìÕÍHKëÄŽ0S¦LèÝ»·m¿I€HÀR(8²Ôí²Fe¥ßóæ9ו‚#g&ÜB$@$`mên¤Q¹råè†èspéR V­èMN ÿýLê´Ùiþ}€8ò¢~} B§ÝÜ@$@$@A!pðàAèû]‹-Œ”jA©/J$@$@> pñâE|ûí·¨Y³&R¤HáƒC£ˆŽ^€<¯ôéC£N¬ @äÈ‘Ã|M™Ìœ ™¼b=sÄ’©dÉ’X¿~½8vdž -[¶x7$uêÔøàƒŒóU|”žìx³ä‰$@Á%`¤T nxõp#0l$ $_©cË´C:‡üªÈ•+—㮑 €E ¬ZµWj^ÜÁáHß 4ðÜ qËň›\ qc÷Çê1·nƒ»?†{H€H€H ÐfÍše\²]»v¾4¯G$@$@>% ®7nÜ»tj3BÒžú #  xÈ™رH”(ÞEøåÄÿdVèìÙ³QªT)”-[‰;ûtœ?ީ˯ Œ¾üòK# š/*ÔªU+ìÝ»W Å’A$@%àü—Ó¢ aµCƒÀõëÀ¡CÎ)d®\¹‚;w2ZhÜ&Ö‚H€H öìÚ´>ù¤?’&ýŠ)âU‰2 É“o¿íþ4yׄº%©S’8ô2H€H€H d¨àH;ZëÔ©2ubEH€H€H >4šFÆ ãszHœ#™¾9I%$î+A$@$à‰@¨‰>l¸ÖwîÜYœå+ï¸í%ßÛôéÓqòäI£)›6m2ÄH*6jÖ¬™1ÎÙ¨Q#OÍôzŸö+' 58^·‚' D2:EòÝ÷CÛÅ…"ÈÅ#8þ“$d½yó&GŽX¸F$@$`Qÿþk¦:Kœx½äß /…±|wi—Ú«èHß%e2-’%‹9áìYHp`ìXÓÝhȘ}\"  `ؾ}»1³gÏžâl+Ö¶   °0•+WHòçÏo¹Vܾ hjšW_Μ1'«Ô¨a¹f°Â$@$@aH@ŸOjPЭ[h6NÓ¢µ–4-g¥#vàÀ¸-UýM nG:ÁF@ŊÙuš*U*Lš4 ]ºt ÍÆ°V$@$d ;›Ò3!m©\¹rBNç¹Á&°jðý÷È,£§³gguª¦SÓ¨X±¢Ó>n   «¨Z˜?‡ˆlë¡iÓ7âUý;)º£Ï_Œ¼û.pîðàƒ¦ð(¶ˆ7ú. @èÌN ùÉ   +ؽ{7Ž9‚^½zY®¿ý<ÿ<ðÍ7À}÷Ë–Yî6²Â$@$–4¥g@@ÇŽ@Ê”¡ÕÌ1ÒÛ»wo¤M›VžŸË¢Ó£½õÖ[øçŸ°JÆ;õ³zõjcLS *Z`mH€H „ÜUp$Dï‘úV5g[·n ÑyûúëZU|&4~ÿý÷„ÁóƒI`éRàÿs+WVÁ‘æ>-W®\0kÉk“ €Ï;¶Ñ(«R¥J .S4»xì1àÄ  `A@_ÌÛ¶ ½¼æ n(  °4¨¨(Ì™3ÇèlUËy X™€-Zƒ ,Ó ¨2l XnÝ2tß|¸G{ð$@$@$d—.™“) Ö­ -±ÑÕ«WÅq©›‘2­hÑ¢X²d kEí"kÖ¬èСƒñ±ÛÌE  Ü Ž ,XHDF¯‹H¤œo'Ëòúâj3Ç ìÚdÈhŽ¡‚£âÅ‹Ša»¹‰H€H€,G`Ë–-†½®/Üû$U7Ò§$m¸CŠ5Ëa…I€H€–ÀÆqüøqy^É‹A$@$@' ‚#M“R½zuK´dùrS`tø0P¶,0q¢ùm‰Ê³’$@$@A@Lƒ ¡‘ aE»2qìØ1´hÑ?þø£¸Õ7ÅÌ™3E¬KµnÈÜ V„HÀÒ»¨}Qt¾Ÿ$I’="0zJö»%¹8×ëM)R¤Ó©y-ôNP_¹Šb× öľuU>·‘ @ è£î³Ï€7Ì«mÞ¼<ð€…D)”ÀÈœ’Ü´ÄO–,…ñt  ð[:µvít^ƒ¬GàÀààÁàÕûäI`Û6`ß>àìY ¾søD÷')Éåÿþ \»æ´™H€b¸|ù²¤#û5kÖ”T/!–ë%V]OŸžx2@ œ9Œ lÝJ±Q,L\% 0 4Õ6pîœã…5ûX(‰Ô8£eË–ò;| d8QläxϸF$@ !à &Ê’%KÚ 2̑ǷPråʧ'Ož]»v5„F¥J•‚®3,L@{̤G+ªxIÔ­ Q /¾Óu7Ò à(† —H€H€¬G`øp`î\ࡇÔÐï$Ë´ÒgŸ}Ög I”ÈgE±   ð9k¢`X°`8*”Eµæc@øãàçŸ?C‡]º8V²Z53…möìÀ]f@&‰!úó÷ß@‰Àƒ¥K›éÎBš4Žåkz\5€ÖïlÙ€ºu÷«“¥:”Ø"©ôÊÝ{¯9 “%‹i­³ÂmŸüù3×Kw>ùÄ,¡o_`äH[iæwýúÀO?éÒ3š5¤¶_ÖòµîúÑÿc×óüy I³Ž¥s‡Àúõëqýúu4lØ0¤¥«$û ´ûUÓpÜw_HW™•# sš*MÇ÷î…¸¿CÄ<æ3*PÍÖ1è}¢àPœÇ!æÏŸ/BÝ­èÕ«†k/ƒH€HÀ§G*6’4jîÄF'¢¢¢®ßíê«V­29tèlŸµk×Jg‹ô¶Ü }™;+S¹Ê•+gÛÄo+ÐÞ4‰ÃÙ+aý$³ã;9ÙÓà2 € è,ô/¾52G‹o6šQ©R%+6‡u&  ¯ |ùå—8/*„ö:…•A~ ð×_¦&S&Ï…«»Ç÷ß›ÉpkìgU‹‘¶!RQQìèÓÐëlÜ,è¸wçN`Ø0àÛoMÁm¯ÎЮXÑÝ™Oeì’ùv¸xÑæØŽ5 èÝÛ\kÒÄYÈó”øˆW©\ºœ:üóù­Ë*R¡½ëQùò΂£ZµÄŠ\zóT¥ªØÑ¬™)"RGå¢NJ’AÂX¾y3öÑ@ëÖÎõ|á@ۢΛ#FÊÍ>l‚'Ui& ­í£B%]Öo m žræ4×mÿUw–ÇÍ6+“ئÙÓ§QQ¦èI…QêÚ¤¼/\0?º¼gO!)?³­H~“€W4šFƒ ¼:/ЫàH]võÿɶm}u^H€H€ lÚd:î©„þî}î9@/*~ýõW´iÓ¿ÿþ;Ö¬YƒÚµk{¼ôMù¬®Fêh4pà@Çr' @üH€’FMç}5¶­ë·ØÌÝÒJYüDÔ¢ËäÛ©kBöë¡‘MzôcK•öòË/cÔ¨Q˜3gNôqjÅžTz ^{íµèm\°(Í1#±'…Ló“ì2¡‚£´2}®xìÞ#‡£¸B$@$@¡K@ZtÀÃö^ºEG·$l¿uB·æ¬ ø†€¾ÃKÚu£s×7%²”p& b™kfü~RÁ‰þ޲}4å—ŠFb‹eÞ{ÏL¤‚£=€¡C ©FÓ6ÈØB´(G]|ÔqH(õS¦ŒÙ'á.E­M äX²¹¦‚£… M£Ç7ë§u´.©Ó‘Œqà—_LMTc+O‚>þØ<ÇÕÀ‹–ë)”•š†« I?®BÆWäÿCW{Ìm¯¿î~Ÿ–©$ýþï?@2JÎG±Ï SâFn[˜¥ÇêÄpnÅ5:u2SÛ¯eØÜžÆŒqõï(oÏ‘uêdñ|÷’€*8*$ÿ£ê'”côhSøgÿ·(”ë˺‘ „/TT¯¿µÕåHÌoãÇ‘Soy¯ˆ2Ò¡j&ò#>uêÔnëñé§ŸnHêlt¯Z‹2H€H€|NÀÉYé¢Áö¥«ØH¢ëþýû'ÛoϲŠMÞxã 4nÜ ÀÑ£Gb¦M›†bÅŠ¡yóæñ)–ç„ ;G{®4jd/8Òÿò+Dݬ´sšA$@$@V# 3¯eŒ÷Ë ¨@IDAT:𢳯56oÞlÌŒyÀþ¡gîâI€H€H 쨳‘:Õ”‡á}Ìãv÷7. š7øðC@]}T„#]<¡¢lɸgˆYÔÈ•“Žý … ›Â!ûmšŠA0û÷®\ŽÔèêU ];ó7ÙÃ%KBúìK‰ÿr½zfýÕ±Ç]è?ý¸3DÑúè'¾¡sút¼D?Y³Æ·÷çÙRµ¹?ÂÜ£©ßôã.äÏ!ÒO*.Óû}ë–ù­Ë¶u=_Û¤¢°Ø¡â/u|R÷#ét É|a¸2é¿ ý¨Jfzlß;w~/.¤¢@c€—öJM‘ÝCÕ!úÿ‘º¥LS)ý7ïéïRÌ‘\"  ÿPq¾þÖg•&º ¤ØèŒ¼`<ûì³X¼x±¸”4Ì-¾ËÓ—^z ƒÆ{:sÁEü' {›Vƒ 5Æ` ø‡€!8ʘ1c+)>­í"4’¹gxöÀSmÛ|ñ]¡B¨µE‹†UË&~Õº=G޾¸Ëu8eðž¿ÌBöc¯{öì‘Χ‹b?^15ã5I€H€H ÁFŽ4MÄ}×µâݶm–Q.ŠiŒ— X€ÀQ’\“|FL§f›‡*ª³ºÜØ>öi·4ÍÕ‘#fz/û¢TT¢sÇÔ}Ç•æLt¦sÑ¢¦X(cF@S›©H?*:±-ëÀ¹+QNõê€~Ü…ºy˜¼ìî´8oç„ç8£2{÷€5<mú{:êØ±òïJl¡$à%[:µ† zy¦þySŒ©î_*¬c @(Ð êä©"ðeË€ªUW«o¾ùÆxýKì5ÛÉ̃ &È328›–ÁìÙ³1Z¬5ÅššÄŽ1b£ù·Xfê¸tÍÑË  ð Cp$iÑ:Ø—.‚£™¾ÙÊ/*½OúÇ–&ž–¸,O(MµöÊ+¯Øá·Õ¨àH¼ËE[dÌÀ³Ÿ‰¨*c ެvSY_  %pü80eЦNjÕ2™ü"94t†L¥J•‰H€H€"‚€¾¿§»…–jAð©#ÍÆÀ×_êJã.’J/Q©R¦ký`·L(–YÅîÎÞyÇü¸?"á{ü)6JxíX €•,”ü‰š~¥ÆÝ”ol”NpùäÓ=ÂÞá(€Uà¥H€H€HÀ‰€¾KÔ©hZdu TáQ bĈ†ƒ‘¾‹N‘Ú§Ÿ~:úÒ: tòäɆð¨³XsêäФú2s'Ôi¤Ì"UG¤.]ºØ6ó›H€HÀ’ÊÛÜ"0ª!¢£èâe}lôŠÔæî«¯¾käsFéK–,A¯^½dVRb?\Eú•€Nq{}/Ž=Ÿ>èxµ•+W"I’$!õïXC®‘ €{£FAMb‹Õ«W‹šV†A$@$@áNศo7ˆµŒ:§OŸ>Ü›”ö݃íÞ äÉäÏo~b lÔeè‡Ì÷î,YbªªîBåË›ÎCjý: ÙBº¼ð‚é0¤ïìõë›ûõÛGÓZi™*6Š}][9ü& p °_l¾ýö[tèÐAÒD¦ ‰&ésàÄ °iæªcƒH€H€‚M@ŸMµk›N§3fÍš¦F2Fž={â£>’1Ç1wî\)RÄéâÅe\rÀ€FÚ´wå%èµ×^‹>FÅJš\‘’ñÁÍ… $@$àIEhTI>1j#àûƒþä‹ÙÊÌ =YÍ›7ÇÔ©SM'䩵eËT‰‹_²­~‡u7’8‘«œÈûtj7$éøÚµk IÛõe-H€H€H ŽN&M2LüиqÌI*¦M›6­ØÐ?8æò\"  €PG⨨(¦SóuMo¦ïÑ:s8vdË(äÌi¦ØÑ×o¹˜6 x꩘£u~öî5SžIæ‡hÒy^xä@…E  ˆdŸ}ö™Ñügžy&d0hϼ˜4àÒ%HÊ—©+B$@$á>“€‰!éÌã–̦xV¬U§ÉKO-±›Wà í‡u*2úâ‹/0lØ0<öØc†0IÓ¯i5M»öÄO¸;•ÛI€H€|D@G9b•µ)Öº_V *äP®ÚÝQpä€Ä+wG{R•1ê[¬XLµu¶Ð… ШQ£˜\"  ‹+~:hïn¤3c6oÞ,¤Æœc‘ûÈj’ ÄŸ€Î,U›z@Â÷:÷e®Xø›)ËÔ¥HgÿÚÇO2¥kÞüðCÃa0§äŒ~á…°~ýz¨û fJ©_¿¾!6êÚµ+fΜ‰¸Šlu!/iyòäÁÉ/­)Áõ]–A$@$*½'Ö¥NÇZ÷¸úüóÏ£M›6ÑÇdΜ9zÙÓB™v—$Iãa¢Ç:uÊÓáܪ´ÇVEjüK’ß Füù矲m·‘k5T«Îz‘ €;éÒª…Vá‘}¨à¨¨x çË—Ï~3—I€H€H ìlذAÄ9?ÁYc+h,ØZ5à4عÓL™jßM[¦.E÷ßèܨ,Yì÷šË§¥§dôhà£ÌNxý) Ð1ku5ò:1·paóãé8î# ðí{^¾|9êÕ«'i*%OeCÆ=±q#0k$MŒ)N• 0òŒ `%x)  pC@ŸMÏ<\ºIiæ[Aì°aÃŒg%K–”w© îñóçÏÇÇl|²ÈËWúôéq@O}úôŠ“âi%/é„ ŒŒ+­$u¹råâS Ï! ˆÅVú¸èZs_r¶lÙ o㢌à©rÕ×®]³-òÛJ¶n5j[m¨Ù9k«:Ó©ÙHð›H€HÀªTCm¯£Þ%–GG —«ÞÖ›H€H 0Þ~ûmcVé«n,yÔ¡aß>@³¥§N˜:Åç*ê@ôÚk¦ (U*H'¶sz²Õ«™KeD€h­â­·LW#M£&ºcŒkvÄÇÑáß¡,® ‡ÀŒ3Äáî† ¨ÊˆªŸB²µ¡[7 wnˆËDØüü30g$•›yч2Ÿ!’-&z⦟ªÃbI€H€H N4ͧ¾+©_­Zq:%N 0Àp*[¶,VËKW¦L™ÄMþ¨é7Éž¢Â#ýè²n{ýõ×ãT®»ƒ6l(´›PªT)w‡p; €$½}ûöII£]´¬Ë+‘ÿãßÿu¸Hƌֹb-C‡:ÖWGÉÄ÷½N:Ž;¸F$@$@%`K§¦/¯   g?ýôÖ¬Yƒ'Ÿ|Ò¥«ßÍ›§c@]ƒ´sÚWÆê,xö¬9HkÏWÓ MœhÖæÏ™ k¿˜4 øö[@qË”1¿÷ï„Øò›£çžƒt`KNùŽçêÚ£jâ¤iî»Ïyÿ¯¿šîDZ^Ë–t<ÎÇp @høì³ÏdBIf4kÖÌ'=(^2¨Sܱcç'{^m¡Bæ3H]#T¸Ê   P" 4$“™K§×øÖSÓrkz³Ê•+cÅŠ†‹‘}YÅå!ªŸ!C†ˆÃüE¤S»yD5ÍYÊ  (¤rµ¿ì¯(⣲«ûÎþß,«bÕ>⚊Íþ.‡&u«Rûý‡~XÒ¬Iž5 „¥’é>:‡A$@$@áLàwÞNLêׯŸS35-LÇŽæì×öíÅAN'ÄaƒÎ¤}åàða@SÌĨUWˆ)S€4iœÝ‰´ømÛ1®0>º®sª4û· ƒD3…7Þ0˜tŸ«P’ ‰ÜŘ.îös; @hØ*íÚݳgOyÎȃ&qð éŠ§Â¢Æ!iÚb +_¸røçàÈét—^wu;Òí   Uúþä*­t|ê+¦xNf{L’Y!5jÔÀ²eË éÎ<…¯ÄFž®Á}$@$@þ# ‚£Õ±Š¯—/_¾ ‡>k»OWׯ_ïP^QNïpàa啯¿þ—/_6r¥Z¹¬; @dPMôŽçdöÉ@Ÿkß|ó j×®”)SF&¶šH€H "ì“ÜB$@$|Ÿ~ <ö ï`¾ 5#èÒ¥‹L™úõëKжEÆäM_^ƒe‘ „¤8xÿý÷ï‘Ù‹hõä;¥¤Â’ùxÉ_ÕÕtjê€cê†ÃšNM£‘ŽÔ2H€H€HÀbtuÄ@²ÉiY´ú*”¾~ý:˜NÍb7“Õ% ðšÀÈ‘#%6Fýû÷w:W\ñ¡Ó*ÒT2ö¢ =XœòQ³&DœëtªÃu0R>o¯^:tÞ{ÏLkæpà-ïnejg¹^[?   °¸"–C³å¡U¶lY<øàƒ¶Íñþ®Sس(R$ÞEðD  áÃÁƒï¿7ßí|UMËýÔSOa÷îÝ’²úQÌ›7)R¤ðUñ,‡H€H „ ˆÁ¸Zßžk_G½ "¤ŠöÛ|¹¬˜ê`‹Œ3¢dÉ’¶U~[ˆ€˜¡@sFª­Ú*8Ê“'‘Õ¶ß$@$@$`›6™ÎF¥KÇÔXÓ©i4h ™g$@$@$žŽ;†™3géC«T©âÐÈ€±cMA ©Ïìøî;3µL‹Î)Ñì[-Ëúú¯Ü úN9}º{±‘ý¹\&  o ÌŸ?.\ðÚÝH²°ÉÀ)0p ó)6rfÂ-$@$@¡O`Ø0ó=L4¸Æ„_ÔøÆ2d*Uª1¸I%# Ç\Š|A—e €5$Öjž;wî´«rR-ÏŸ?¿Ïçj茒%K–Ø] èÔ©’$Iâ°+Ö  ™ñÔJøÞ{ÍúêŠýû÷ÓÝÈ·µ$ pA X1à‰'SĨ਀(lEíâ n"  ð ðþûïŽ~T]do¾ ¼óP¹2°t©k·!Õ'uî ¨F÷ùçíN–ÅU«€Zµ€Ì™!ÖúÀñã€ÌCÂÏ?CÄMŽÇrH€H€|I@Ó©iZìvíÚݵXM*º[T¨T”©¸’Fœîz   & š ôí åÊkÖâ‘àØµk—xð 9­ßn§·‹j_;qâD|üñǧÞsÏ=hß¾½Ã6®X‡€ ŽäŠ-±Yg¦S³Î½cMI€H€\Ÿ+±oß>:tÝ»wwØÎ  'gΜÁ¤I“PZ,þìýDƒ„×_7ÓŒjÊ´´i]·:Q"éPg¨v\«ðÈ>¤;ÀHUªÎFÚÁÝ»7;·ý\&  ßÐ÷¸¯ÅJ¯M›6È ¹7=„dЖI±€¦ØN“èÖ òhºòy8»H€H€H ¤ ˆ&ÈpìÓÉbBd¤Á¾Ë#ñ®í¹uëFe8i:î×å…Q?É’%»ë¹<€H€H ü‚#m– ¦M–YûõÄÙè1[3e9[âĉ¿’í“ä¡ñžØöÅõ[;-Õ’ýóÏ?W'%§Ó $–nz,Žæ†P#0W’ñýþ;D±lÖLGj•XK§¯2H€H€H 0ZÜD6H€Hà®Æg¤>ïß¿ô±ï½¼ú*d¶* ©ÐÒ§ÞårAEGê\;š6Uge@÷3H€H€H P¦L™qõdzÏ>ëñ’gÏÍ›š^»eK@L‘îúÌóX w’ @ ˆÈH›¦©¬EdL"щ$ Õݼy­[·Æ¢E‹PLlâ§M›&“JdV ƒH€H b D Ž„@”¼€©ÕPVU³‘eíì&£®"<£=|)ÇIkˆÖ1TÉzêÔ);vL,Òc«$»Ö‡Îu"â"Zµj…fÍš¹ØÃM!Oàé§_~A±HÌ‘Ãügôßÿ³†Oü4:ˆA$@$@a@`…Ø9$Ož5kÖ ƒÖ° $@$@$àLàÒ¥K;v, *}O×øþ{Sl¤®DëÖ™éМόÛÛ•¸Í£H€H€H áÔ}aêÔ©È›7¯Ç‰‘‡ {÷½zêì—8q¯ÏH€H€H XˆuDÇŽæ;Ý@DA@ùò ¯Žw”‚uÜ·mÛ¶Pa¯0H€H€"›€½à¸–/_¾GÅönŽèŒêÛ£¹#<ª'ÛÔIg‡Üz衇nJ*6¤K—/^ĉ' êÖ¸DãÆ ‹½¸ËcBÀöí€tJ#iÌ?¡ 6àêÕ«hÔ¨QV˜U"  ï èsM-ø«U«F1­÷øx €E¨»‘º{¢$wÔAUª@R¢CHÀ½÷Z¤!¬& Ü!0gÎ=zLJ=×{?þ¨ ŸÌŸÅ˜1@ÏžÄG$@$@Ö&0~<з/d¬xåà­·€”)Þ&u ì&ùFgIîÑ–b8}útŒLøX €U 8Í×8|øð¹ýû÷7¥ªú¨»UÉ‹Zq´I¡/n{öì1^àâ"6Ò¦Qûàƒä!烧œUÉ[¹Þ**ÓÏàŒ3{·Ý»{öÎìþŸÃN=3ó=sçÙÙ={æé§ŸÖÏNCžf\‹ €•"©Á‘wüÚèhÔ¸qãö×_…t× ÚŸ|SS˜õÖ[O>ø`±Æ(ÖM{÷îV)Ñ_|!ÃegÙÿé¿h÷‰«ŽÄz¹ÒÞ±*·w£êðm¢kõ·Põ™õbÇä*ÍÑ‚íÜS\mà×rõ×jΛü¢Û8Aó@Ís5»Jz£ -5凉à& vòG¾›æ¦š¯Ë°L±&_¡µÕl ‚\$‹Vö`ЮšwÖ\ŠFTºR²Þ~[ô¹ã«z9òä•W^‘:HÏž=ýI¼"€ P6?ê/H¬÷á6ÚHÆ?\¶ß^ä‡Êæð8@ ð{7²†FûÛß2 <ñ„Èÿþ½ÿ˸03@Hˆ@}ýÖw5òÛÙ™3gÊ€¤_¿~²ÖZkÉïÿ{¹þúëå믿 ¸ôÒKåŠ+®m¶ÙFž×îyrM@à €À¯y=`sÒ¤Iö•°×ÿ¬ö^³žöx´£æ^ˆÔ–¬Ù‡”Ö ÖnäüÜ¥KéÛ·¯Xƒ#R™ Œ#oHï ´A³—bý8µåº‹ú˜ÙnÕ¾ýÿ Zâ–šjþ\sÍ.Ó³Zø47v°‘´Ì#4Wi¶GúáKÑÓt-q€æqš¯/zé« ´ý?OóåšÏÔ|fɵüQóè_ ·F-ÖÈ©˜ég-쯚­q_+ÍûhÖ›'©…–j/kj~Nóéš]mkG-ûÍûi¶¿OýUaQÒ -ÅK]¤Ù~”±…æ÷5¯ù^Í$2hûò>lö»¶†´ö«Øc=6ÃZLF@ Ù×^{­ÌŸ?_öÞû¿rùåõõƒf}ûçêý_²©Ø{@„<üðâ? •‹/¾Ø{¤Z¦ÝÖ§­éüLs™Ž €@üìóLm$§è»íG”5IöÞG!sçΕ?ÿùÏòÝwßÉÛúkÌÿüç?rÆgHÇŽ¥wïÞ^#£-¶ØBìG™Í¬k@ €)y58 ¯£7lÖ áQËãÇï ¯…ç3\ÚÃÑr¾ü®]•ôè¡}4j²n›4i¢Ï>ßÙÏùßgºÄæš­Ãk¬áòCíôüg4[³¹õ53Y“ƒ4[£kä2Xs±œh‘AzL‡Ñ|±æ ‚©Å°dæõ­æ'5ÿGóîš‹•&iAÖØhŠfë3íDÍ.Ò]Z¨56²‡Br±-s¬æm4Ï×\ï _õYFÖë»5BjÉbœ5 àF ˜_'»ÙCJ,^¼XfÏž-Ë—[7$u“掞®ùô’þêy;`o>Þ{ï=}sshþÝ)>§«ê› ¯G 98küã§ct`©æKý E|ý›–e.Ð|°fë!h¸æb¦ÿjaúæÑKèÿÖƒÒ•š§ySŠûŸ5P@óÝš­ÛÍ“5[£ªb¤¯´4Û~ß«¹Xr´¨jéHb½ç¼©ÙÎø©XÇbåYƒ–=4¿¤ù|Í·jÞPóYš¿Ð\hºC ØZódÍÿÐüŒæb76£e.ÔNtd=Í Ã ž«ëÚ߯öšSýÍÊ>ì{Z³5+$}¤+[3;¦!š­QãΚ-Ê=¢¹»fÛÞkšI±ˆCl³Ç©YÚÑ©iÒžåž{îñžI¾ë®»®šÈÿ €ä)‡Ø–kW¯ºê*Y°`×Äu×Õó+£ßÏ’@H+„ØöÐCé#BÇ{=3ø_ŒÚG¨‡¾êKÙ»ìj$@R’ãRvYn¾yUc#kL«å•ôi6²ÝvÛ‰õt»í¶ÛÊhý¦ßØÈ hÚ´©ì¹çžrã7zñÔzÿàƒ¼Ç­åµB¨HyÔ ;è#FÈ}÷Ýçxkld©^½zÒ¦MÙ~ûíeàÀb]–$-]*Ã'­¯ùÔ{œš=JoðàÁ^ïFÖUqÞÉhü^óîš/Òl VÓ\¬d½˜hO^/:ö=qÍÅj@¡EyiŠþŸæšíxlÜNX-j®§¹Ðô¢°Ÿæ£4[o-ökOnÔnT¥£EM´4kD5XóUšíø IÖ(Ëêz¾fk`v æÔdÇS 3+×êú<¥'uX»kT°Qhzmë늇Vnþëøúú'Ív¬®¹¦i¦®`7iîôëk_}M—~Љµi„4C×û§fëaè/¿ëKÑ“5ôë¥ù[ÍÖXîÍ©&wë´/5Û9¶¹fkÄU›ÔGW:U³ý­l’R@ ^óVš¯Õ¼›fR Ä*¶©†58j ×X½×ö’ÅÝ‘#GzT·ha' @ìq‹mÙövΜ9rË-·È¦›n*¸êÍys{?KB@ $¤Øf?δެ·†pïFC‡j‡ÔéÇkúùÚ_ì3 €*¤—®ÂüǨ|~ŶGŽžxâ‰òóÏ?Ë!C¼ž¬¶Zö/åì±j$@r ØW椘 L›6Mþô§?É1Ç#ï¼óŽ×³‘¿«Öó‚}Hl2³ž…N8áïשþ|g¯cÇÊ+wöŠïß_äÁ”Ï>ûÌ»‘oß¾}Í6k_þ[Êñšï¯ÙªY—¥soÑlå6ùuIëÕĦ3Ù{­4[£ûK²Æ!'k¶žVÕ\h­ªÙ”XÃ?YÃkˆ´¾?¡€×wtÝs3¬ÿ7¾±æaš¿É°L>“ß×…ô\ñ;÷¬¾¦kld^›jž¯¹¦É*½®Ù·dK¿Ó™s4©y¥æš¤yº°5¼šœc%ë‘èBÍŸi×YŽÕ¼Ùoêÿ5wÔl¬Ž5ÔÊÔØÈ¶a$¼As>i™.d½$í­Ù¶q±f;‡ŽÓœ-Y¯DzÓ"¯d[è×yU)Ë4ÒñÃ4Ûñ<©yMÍ©©©N°óÂæýIóÍÙÒ7:ÓÃ]“f¡ëtÚ&i¦Û¤4¿©Ù¶EªS8Æ6ë^_Ûöjã]íÜM{wûIŸ­f] ·k×N.¼ðÂ:õbã €ñˆclË¥vÑE7ÈÂ…UÞ‡Ìöc €a$Æ6ëÝh„ Õ~4ræ™úQÞÖ=ñ„þjõðQ2Œ P‰IŒqéêÉ~8©í‡¤~Žoy­—¢=öØC;ì0¯#{<š5ÐÍÕØ(Ý6™† €@:¡(Ý*L+…Àwß}'Gy¤|üñÇymî7Þð~™jë9McÆèwö»Hǵʺë.– .¸ÀëNñì³Ï®Ýf­QËZš‡jÎÕ`$Ÿ-XC’4Ûgæ·ýúª/^ƒ {-vꥶ zž·ÒlxRZ,çà ]†X#k ÑYs±ÓH-p/Í7kž”¦ð†:Íiý¢ùÔ4ósM²žzÌa7ÍË5¿¬yOÍé’mcŒæAéff˜¶H§[÷ÐlÛ8Es¶´½ÎÉÄm©ùQÍçå±ÂjºÌCš­±ÐpÍ©ÉþF¦Ll ãÖ˜iœæW5[ýçJÍtk¤c h¬áŸæë€9«¹“æ5[£Ÿ55_¡yšf«Kk dÛÍ•Ö×Ôüƒæšçh~VóÉš»kî ùÿ4[c šk{ùÙM×½\³6üðz:ºX_¿×NÖ`èÍÖhêƒðŒZÕõÚiî£ÙŽ‘äT αͧfiÇõÒðÕW^|ëׯŸqÄ«fð? €iâÛÒì®7ÉnwÛm–Þ3n«‹Þf’@’Ûlç­ö‰'z½}óM sÁ!1€ €€'Ôg;¹~n¾›~~~ÖYùUæ‡~(}úô‘Aƒ‰=™äÍ7ß”{ï½×ë< ¿X @üòùº9ÿÒX²(?þ¸Œg-V¥† zo¶°g½„ÒöÛo/|°÷…¨ß8Éž;û„ö|ÐA¹º TƒÁ7Þ]Ý[ºßn«É¹ç“N:yÏ}Í«kìðÍ#4oZÃ.\§ÙƒXÓÚ~èm U¬Gkˆr‘æLÉš4ÕÜ1ÓY¦?­ó¬!É€,ËØñ4Ñ|t–eÒÍš«oÖ|‹f¾D³5®È–fëL[Îr«l ¦™g £l_û¥™žtŽXƒ#kÄeBÌ.WÚZØ[³5D±×zšs¥{t»"µI³àdf–¬QËóš—kî¦ÙÎkÏ>éb^½Ü§¯Ûk>Ró{šWj¶Æ+¯i¡Ùü4Òì§StàT$ÏWk¤c€Ö -ÿ¾«ÙÔXC;Ãi÷ðHžÃöw4E³5&ò“•ïŸ7]uøÄ_Çwð¨Åë^ºÎÙš‡inZßþ†ŽÖ¼ë¯yíÐ¼Ú Ò•>Öü¸æ4oªyÍ~2ÏGü‘"½ÚõÂŽ¡6þEÚ…J)&Î±í­·Vu?¬aUioâH €ü&ÄØîÝhõÕÏÔ/Xõc²Kôc ûƒ„ €À¯IŒq¿ü¢]ëg×>*Ò»·>ìÀ>?Ïk÷Gÿûßÿä±Ç“;ï¼S{ökàu`0dÈ}¤èêÖb2 €… Ô/¼J(¦ÀÒ¥K½7á2/×æË©üùÖ:ÙºE '{ãä*½9n=¯èO>û‡üðÃrÙe—I£Fronº.bŠ:i¶FádEÎÑK—·^X¬QS³ ëZ;®M4Ÿ—a~¦Éß댓5¦ùHÍ‹5gJöÞÍyäûn¢.{’fk¤r±æšïМÏ>¾®ËY¥ 5§KÖËòXÏ0“R°F/ýR¦¥ýN´ž`¬ß -ð­? ÙLî M·Ak4ö´æÿ§¹žæ|’5^Yuz­ZÚž§¹³f;o¬±Î3šwÑü²æ¯4Ÿ ÙΟš¤mta;W>ÔÜWskÍÖÇŽq”æßÚú鈦|÷ÕÒ¿ýocÂÉíüu^7Ûp¸±‘-·•æ{5OÕú•W^)“&M“Î_“¿ÿ½±l¸¡>Qþþ\^@IbŒûæýX_?×·ÆFègòᆱ_!ÙwH¿&ë±é-ýåÅ_,»ì²‹¬¹æšÞëí·ß.Ûn»­Œ=Z†Jc#ŒW@gõ•LÁµxî¹çdΜ9Áº»îº«ì³Ï>ÁxºkŒ´ÕVÖÊ`UúüóÏeÚ´iþhñ^µ9õ úJ—5fèÔ—Ë–[n)‡b- òHÖˆÃ]£yµ4˯Ó:h¶/þ¦™ŸkÒp]àÍ{h¶™RWa?ä}Dó×™J3} ö˜ænšŸÒl jŠ‘¬“•i 8zj~\³YYC›|ÒŸu¡m5[C­1š­í牚­¼¶šÖ¬oNå3͵M'銟jÞ+TÀÍ:|„f³´ÆAÅNÖ`柚틿j6›ï4ÿG³Õs!_ Õõ­áÑš·Ô|‰æ÷5ÏÓ¼‰f©“:Có}š­Þ\¥Zð‘ší縉Éþn¯Õü¤æ4wÑì"ÙßÖš­~ìXHe!çØ¶r¥¶‡½Îº$^*gžy¦÷ˆPkèKB@ ›@œc[ê~[¬;ôÐErÏ=tÖäøã_½÷Þ-u1Æ@*\ I±ÍªÊz¦=õÔSå¼ón’&MÞ‘‘#·Ýw×N¬?éÚµÂ+“ÃGˆ$-Æ=£?¼¶žŒÒË^x¡þ>÷ ‘5ÖXuHßhK¤#<Òk`´óÎ;ËE]$}ô‘רèŠ+®Ð8ø¼ýöÛÒ£Gˆ# €¸¨ïª`Ê­À;ï¼YqÀ€‘ñL#Ûm·]dÖË/¿/ÆÈOß-‘k5ÑG£ÅZOÛ/ˆò~ÜL݃ɚŸaOV×éÖë‹56ú0Ã2©“çê„;4[ÙÆd nÒœ+]¬ è‡î^6©Ë.× Ö°ftÊ Û¿O~Í¿µíJY(Ãh•NŸ yxšùëé4ý0Äë9h¤¾Ôl ;j’nÔ…íx¶Ö¼Žfkf h>LóÝš§iÞOsm“íSÏ”•­ÑÌCšgi¶í;Ù¹2Y³ÙÝ®ÙlÖÒ\ŒdõùžæŸ4×|žfó«©½®BBÜqŽmõõµ0a˜Lž<ÙûUPÛ¶ÖZ“„ €@f8Ƕð^/_.ú–Ÿ´[ý¦:ùEý0z”Üv›¶´%!€ "”Øf»½`ÁÙk¯õQØÍeµÕ&É/¿l%§¦bëÇ¡ÚÁ @ˆ@Rbœ>EN?}UO} мúªè=œþöZ|=}útýñÈñÒ­[7íà~±ÞÙ‡ &ï¿ÿ¾÷4’W^yEìuN÷÷v%F@¨ Žjçæl­‘#­Õɪdo vÚi'4ëk¸‡#[ÐEƒ£ë¯)ϱDŸ³£<¹Á“2 Û€¬ûTm¦}Æ-ýŸÎœ¤y—l …æY‘ã5¿¯ÙÓü[sg͹’­g=ä<¦ùyÍ÷h>I³Mo®y3ÍGkNMíS'ä1n§6ú5’fùstšµ Û9ͼ|'Y=—kî¨ùHÍ÷j6Ç©šÔ޶#S´‘"'k oŽÚ¹\¿8;_ì˜\&kx”°d{².`I$I αͧL™â5¢íÙ³§œt’R^zé%Ynߤ“ÊBÀ> ûî»ïÊâX8ˆÊˆ{l³ZX¶Ld·ÝæÉK/µÐ¨Ÿ–þsžþ:öìʨ „åk¯½&‹/NèÞ³Û©öKó™3g¦NfØ $!¶Þ”)Seã‡É¿ÿm¿À»L:uj"Ï>+òèïÈV‹-oÅîØ›o¾é5«X€2;ðO?ýT¦Nuð9s™9q8ñHBŒÓßAÊöÛ‹ÜpƒÈŽ;êoâGëoÕw™={¶6ª=Mºté"wÜq‡ôë×O†îõbtöÙgËÖ[o- 4ˆz™ïÑ{ï½ç5ô*óìˆÃ[´h‘÷7UËA"àH ¾£r)¶“&M’yóì™N«Ò¦›n*k­•_—.½zõÒø«ÊĉƒábÜùä2Yÿ0ù‘ µä#5Ûc©ÂÉ>}KóPÍ5Ù m±i¼2EÇ­1Ðß5Û£œRÓù:ÁzØ™£ù)Íú&,ït±.¹Ró¾šÖ|«æIšwÖùĺJ&!$Ä6S¼õÖ/õ ×µ—‡Ë¥iÓµ½/e¿ü²žìkŸï‘b)p饗ʷß~Ë}c§j.ððÃË»ï¾[óY:HBŒ³†³›o.úh4½%О–êg$ÿõºá†zŸYÚ÷…¯j—G#FŒÈ»£‚:d/ûM_uÕUbç)ùö½ü!öÅ0 j+@³×ÚÊ9Xï³Ï>‹”Úµo¨ý+®¿þú2vìX¯ŒeúsVk”ТE‹H™…Œ¬\¹RVßou¹cÛ;äæ½n¹JK»_óš÷Ò¼™æ·5 Ùÿþom>QsmÒ]ÉYÚJó™ÞÐoÿòyy_-æqÍöø4ë!¨æš‹Ö×͈„T¨@Üc›UË_þò/†öïß¿Bk‰ÃF¨‰@bÛŒ‘‘#7‘Æÿ%o½ÕE»Õ· €é’ÛÎ>{¤öLkè-ÑFãä¾ûºòø´ôÕÉT@@bœþKê×_!'œð’|öÙ?¥M›7eáÂ…ÞQôîÝ[†ªÊÞ'tT "€ ŧ."½Ùn­YÃ‡Ž·lÙ2r4Ö*³6 ެû¸ŸþY>þøc¯¼úõëKÛ¶m½á£^Õh†ÌðzjøICi~[siüRc©÷b=Y¹ÆJYºíRY²õ//ë­ýøë¢µIõ7®/îi$Ë6Z&+Ö_Qër2n{[cÙOµÜOõ¸¾Z}Ú¯dgÌ(ÓŒ+¼£ý²†³fÍ¢W"úÚ#™æÎ”hÆ<¦)à(x ÜsŸVW±Íz0²ë¡Ûl_Úµk§˜©'}úôñ2×ISIV²ëa¸‡Çdí={°Ç…Úõ‚¿Ã°Jáà ,>¤üæ›o‚áÂK®ìâÛ¬—7ûÛ Ç6»o³û·ÃŸ¦ Ž^‘'ŸÜFÖ[oþ¶rÊÚûPëbÅ ½ÿ%%^À÷Ã?ð÷Wäš´Ï«,[?~¼÷¿È›¨ÈââÛì”v Ƕ6mÚho}«É.»,”Ûo@{5ê(»îÚEß×ÌÐ\‘Õ•¨ƒ¶ÏWìq@M›6MÔ~³³éøœ9½K¡SÍÕïÑ~ܸq/I©Ø:µ÷,öõRÇQ„Íû÷àÔe0CEØ÷1óçÏ÷¦LŸ>Ýûü*4›Á2 ÁQŒ*ÔÿÃów©¦_ʦ6.²7R:…ž­åœãÕž=úõ×_ËŸÿügoIû26µ1Sjëô^GZ,o!㛎—•‹ôYeoè–Iu.`7,o½õ–<ô=Ž”tûbÉþÙI¤â؇™vÃ秪ª*½Áû>ïGZúëñš^ .±Í>°ž6mZÛlo-¶YŒ#%WÀÞ«P‡É­¿ðžÛ‡ö¸뵓T<»¹÷=hñ/zŠc—Øf!´8ýû6;:»'ôß'n°A•üýïöìiRRìÞí¸ãŽ ê0)ûÍ~¦°_¥Û/êo¾ùæô 0µVÖ˲%‹möe©p¸Ä6û2ÂÞ¿„c[óæÍ½Gv”ݺUÉm·ÕÓ\ø1SBi¬Åßþö· K³U¶âJÀÞ«Ø#Õ.ý‹il÷lvíó“ÿ~Þçµ0¸Ä8ûŽÆKÿûßÿö¨AƒÒ¬Y3oØîëÚ¶]®ŸUnä}^i?Dxã7¼\ØÑ³¶+û>ÁÃeõHJ¶€}?dŸKpÀÉ>˜í½ý@ÎÞ7*C€+aŒê9õO®F>©»žº|jËíÔå3_rÉ%b™„ €@¡q‰m§œrŠX&!€ P¨@\b›}Æb…Ö&ë#€˜@\bÛÖ[o-cÇŽ¥R@(š@\bÜ‹/¾X´c¢ @â$@1ªÔ7>5íáÈ~ñN~Óái #€ PJb[)µÙ €@)ˆm¥Pf €¥ ¶•R›m!€”R€WJm¶… P‰48ŠQ­§>¤¦ÝBÛ3CÃ)µÇ£ð<†@(…±­Êl@ ”ĶRj³-@RÛJ¡Ì6@êB€Wêl@ ’hp£ÚnÓ¦Mdoì 5Iö¬ßpjÕªUx”a@J.@l+99Dp,@ls Lñ €% ¶•œœ "€”H€W"h6ƒ P±48ŠQÕ¯½öÚ‘½©iƒ£Å‹GÖoݺudœ@J-@l+µ8ÛCp-@ls-Lù €¥ ¶•Zœí!€”J€W*i¶ƒ P©48ŠQÍúÆgΜ9‘£¡ÁQ„ƒ@: ¶Õ:›Dp*@lsÊKá €u @l«t6‰ Pb\I˜Ù €@ Ðà(F•ŸúÆgÖ¬Y5Ú»™3gË7hÐ@Z´hŒ3€ €@]ÛêBm"€¸ ¶¹Ô¥l@º ¶Õ…:ÛD(…1®Êl@ ’hp£ÚoÛ¶mdoFÏ6bS 7PÚl³Í¤^½zÙVa €ÎˆmΉÙ €@‰ˆm%gs €ÎˆmΉÙ €@ ãêžÍ"€TŒ ŽbTÕ]»v•ð›ŸqãÆÉÂ… óÚCkœ´bÅŠ`Ùà € PWĶº’g» €®ˆm®d)@ ®ˆmu%Ïv@\ ã\ S> €@¥ Ðà(Fg@ýúõeï½÷öhåÊ•òî»ïãÙ†™½Ë.»DÆA@ .ˆmu¡Î6@\ Û\êR6 €@]ÛêBm"€”B€W e¶ PÉ48ŠYíï»ï¾‘=ºóÎ;#ãéF~üñGyâ‰'‚Yl°têÔ)g@º ¶Õ¥>ÛFp!@ls¡J™ €u)@l«K}¶ àR€çR—²@*]€G1;ºwï.m´Q°WŸþ¹<òÈ#ÁxêÀÏ?ÿ,'œp‚,Z´(˜uÐAà € P×Ķº®¶ Plb[±E)@ ®ˆmu]l@À•1Ε,å"€ ²Z!]tÑuýM )ƒu« 4kÖL^{íµ`ƈ#¤eË–Ò³gO±îý4sæL9öØcå³Ï>ó'I—.]dذa²ÚjUmP €C€ØV EÊ@ˆ“±-NµÁ¾ €C€ØV EÊ@ˆ£1.޵Â>!€”Àuõ 9ˆªªªuýà )ƒuÓ œuÖYò /Df¶oß^6ÝtSiܸ±|ôÑG2uêÔÈü Èý÷ß/}úô‰Lg@8ÛâP ì €@1ˆmÅÔ¤,@8ÛâP ì €€ bœ UÊD¨pö48Šé°páB9ýôÓåí·ßÎk›4i"7ß|³l¿ýöy-ÏB €”Z€ØVjq¶‡ àZ€ØæZ˜ò@J-@l+µ8ÛC(•1®TÒl@ ‚ÚôÜ-©æîTiÔ¨‘ì½÷ÞÞ#Ô¾øâ Y¶lYÆõë×O®¹æéÛ·oÆe˜ €@] ÛêºØ> €@±ˆmÅ¥<@º ¶Õu °}@WÄ8W²”‹ PÁ"€ Û @ÊD€ØV&Éa €Ķ€‚@2 Æ•Y…r8 €u%À#ÕêJží"€ € € € € € € € @öõ¸Óì2 € € € € € € € €Ô‘ ŽêžÍ"€ € € €ËôßÃ@IDAT € € € € D%±ÖØg@@@@@@@@êH€GuÏf@@@@@@@@H¢ Ž’Xkì3 € € € € € € € €u$@ƒ£:‚g³ € € € € € € € €$Q€GI¬5ö@@@@@@@@:X­í^tÑEÔõ7-¤ ÖE œ–.]*³gÏ–o¾ùF–,Y"Íš5“úõ‹×®ÏÊ·²§OŸ.Mš4‘ÕW_½h|‹/–yóæIãÆ‹ºÏ¶ƒ.Ë.@ r}ž¸6§>Kx²°)b àúš•ÔØfUÃõ°ú êú|qiî²ìêRLAºp}­rÛÌÍåõÊeÙuYç…lÛõùâÒÜeÙ…˜²._ÀõµŠØVü:«Ë]Ÿ/.ã˲ë²NØ6¤p}½²­ºŒq.¯Y.ËN_ñžêú\qííºüx×{—pë$üØ}ê\à»ï¾“çŸ^^zé%ùâ‹/"ûÓ°aCÙ`ƒ dà 7”½öÚK~ÿûßGæç3²`Á¹ûmÌœ9Sªªª‚ÕZ·n-:u’wÜQŽ9æiРfÒ#FŒûî»OÆï5”²‚ëÕ«'mÚ´‘í·ß^([l±E°½š ¸,»&û‘ϲo¿ý¶<óÌ3ù,Zm™Î;ËÉ'Ÿ\mzê×ç‰mÏ¥¹Ë²S­Gºp}ÍJjl³šIÒõ°ñÍL\Ÿ/.Í]–m6$ˆ€ëk•ËØfŠ.¯W.Ë.ö@lË-š¤úÌ}4,Ùˆm™u’v-,E|s}¾¸4wYv泈9 PW®¯Wv\.ïß\^³\–]ìú&¶åMR}æ>–¨dz…¼6|xP×?¬2X$ ¼òÊ+rÁÈO?ý”×aX£#[~Í5×ÌkùÇ\®¹æ™?~Îå{÷î-×^{­tèÐ!ç²Ó¦M“ÁƒËÇœsÙþýûËUW]%Í›7Ϲ¬-à²ì¼v  ]yå•rÏ=÷ÔbM‘>}úÈÃ?œu]×ç‰Ks—egEc&Ô™€ëkVc›UF¯‡®ã›¹¸<_\š»,Û\H /—×*;RW±ÍÊvy½rY¶í»‹DlˬšÄúÌ|4ÌA\ĶôBI½ºŽo.Ï—æ.ËN1êZÀåõÊ?6W÷o.¯Y.Ëö]ŠýJlË,šÄúÌ|4ÌA@ÚÓàˆ³Z XÏ@Æ «ñÚÖ{­Û¥K—¬ë>ñÄrÞyç¥]Æz! ÷tä/´ÆkÈÓO?íõªäOK}µÖá‡rˆ÷X¶Ôy™Æ­—¦‡zÈëù(Ó26ÝeÙÙ¶[è¼OÓ S@ —±-½P’¯….ã›ËóÅ¥¹Ë²ÓŸALEºpy½òÍÕý›Ëk–˲}¯Ä¶ôªI­ÏôGÃT<q" PQ£FÉ_þòY¾|y°º5$Ún»ídóÍ7ëmè—_~‘‰'Ê /¼ |ðA°œ l¹å–^¯8Öp(]zóÍ7Å‚ñÊ•+ƒÙÛl³ì±Ç²õÖ[Ë:ë¬#&L?üP®¿þz±g{úi×]w•[n¹Å¼.Y²D<ð@7n\0½qãÆ²í¶Ûzû¾Ùf›É?þèíï£>êu+é/¸Ã;È?ÿùOï‘kþ´ð«Ë²ÃÛq1l=O™§¥–-[J“&MòÞŒÕõ7Þ˜vy×ç‰Ks—e§Åb"Ô¹€ëkVc›UJ’¯‡®â›¹¸<_\š»,Û\H /—×*;RW±ÍÊvy½rY¶í»ËDl«®›äú¬~4LA\ĶôŸ¥&ýZè*¾¹<_\š»,;×ßó@ n\^¯ü#ruÿæòšå²lßÅÕ+±­ºl’ë³úÑ0@ }0T›{¤šf'pðÁWuíÚ5Èúرªo¿ý6£ƒ¶š®êÖ­[°¼­ûÌ3Ϥ]^N•6î‰,{ÖYgU­X±"íòcÆŒ©ÒÆH‘åGŽ™vÙx ²\Ïž=«ô±ji—Õ.ýªì¸ÂÇùØc¥]Ö&º,;ãF‹0CuUõêÕ+8ÎwÞy§¥®*Âåyb[piî²ì¢SUÀå5+©±Í€“z=tßÌÅåùâÒÜeÙæBBx ¸¼V¹Œm¦èòzå²l—g±-½nRë3ýÑ0r ÛÒ %ùZè2¾¹<_\š»,;ýÄT¨k—×+;6—÷o.¯Y.ËvYçĶôºI­ÏôGÃTõêצ¡ë PÉ“'O–O>ù$ hÛ¶­XWíÚµ ¦¥X¯BGyddò 7Ü÷Gž}öY™={¶?*{î¹§\qÅR¿~ú?Wm4$GqD°¼ ¼þúë‘qYºt©Üyç‘é—_~¹l±Å‘iþHûöíåꫯöG½W{¶mºä²ìtÛ+æ4³Ö7›A‘:u † p}ž¸4wYv!¦¬‹î\_³’ÛL;É×CWñÍ\\ž/.Í]–m.$ˆ—€Ëk•©«Øfe»¼^¹,ÛöÝe"¶U×Mr}V?¦ €@.b[ù}.iuî*¾¹<_\Æ—eçúc>Ô€Ëë•D®îß\^³\–í»¸z%¶U—Mr}V?¦ Hß‚!º c xþùçCc"ǼtèÐ!2-ÝÈé§Ÿ.öø2?Íœ9S¾ÿþ{Ô{Õ^ŒäŽ;î¦5hÐ@Î=÷\YmµÕ‚iéößÿHƒ¤¯¿þºÚbÏ=÷œÌ™3'˜n^ÛgŸ}‚ñtÖi«­¶ f}þùç¢=ãþ€Ë²ým¸z2eJP´Õ=®®ÉåybûçÒÜeÙŰ¥ (¾€ËkVRc›)'ùzè*¾™‹ËóÅ¥¹Ë²Í…„ñpy­rÛLÑåõÊeÙ®Ïb[yÝ‹»>_(r ¶•ßç’vžºŠo.Ï—ï'\–]Ž×Ž rpy½2—÷o.¯Y.Ëv}ÞÛª '¹>« Sˆ Ðà(êÁ9Róì¾ûî9×±¬1KçÎ#˦–e='MŸ>=XƵiÓ&Ï4`½, :TN;í4/Ûz©I™4`À€Èx¦‘í¶Û.2ëå—_ŽŒÛˆË²«m¬ÈÂo|6Ø`©W/ý³àkºÙÔº-æybûâÒÜeÙ5udy(€ËkVRc›É'ùzè*¾™‹ËóÅ¥¹Ë²Í…„ñpy­rÛLÑåõÊeÙ®Ïb[yÝ‹»>_(r ¶‰”Ûç’vžºŠo.Ï—ï'\–]Ž×Ž rpy½2—÷o.¯Y.Ëv}ÞÛª '¹>« Sˆ Ðà(êÁ9¾ýöÛ`™V­ZåÕ È_¡cÇŽþ ÷n\d>þøãÈüC9$2žmdàÀrâ‰'zù°Ã«¶èÈ‘#ƒiÖ¨f§v Ƴ „{8²åÒÝØ»,;Û¾cÞÔ©Sƒb6ÜpÃ`¸Ð—ç‰í›Ks—eêÊú àFÀå5+©±Í¤“|=tßÌÅåùâÒÜeÙæBBx ¸¼V¹Œm¦èòzå²l×g±­zƒ£$×§ëó…ò(Gb[ù}.iç©«øæò|q\–]Ž×Ž rpy½2—÷o.¯Y.Ëv}ÞÛª '¹>« Sˆ Ðà(êÁ9Âo~Úµk—sùð3fÌJj¤ðŸ–-[Ê6ÛlY¾¶#“&M’yóæ«oºé¦²ÖZkãÙzõê%Mš4 ™8qb0l.ËŽlÈÑH¸¥u§Nж—ç‰Ks—e —‚@ è.¯YIŒmœôë¡«øf6®Î—æ.Ë6ÄOÀյʎÔUl³²]^¯\–mûî:ÛÊë^ÜõùBù”£±M¤Ü>—´óÔU|su¾¸|?á²ìr¼&pL”‹€«ë•ïãêþÍå5ËeÙ¾‹ËWb[T7éõ=ƨ.Рú$¦ €@6»ï¾[ªªª¼Eš6mšmÑȼŋW{I=‚eV®\)£F Æ×_ý`ØÆ/o¿ý¶Ìš5K,X Ö8¦K—.Ò­[7éСCdÙÔ‘Ï>û,2©k×®‘ñl# 6Û—±cÇz‹-[¶L~úé'iÑ¢…7î²ìlûU¬y©o|–/_î}`ÇkyܸqÒ¬Y3ÏÙÜz÷î]íÑxéöÅÕybÛriî²ìtNLCx¸ºf%5¶Y­$ýzè*¾™«óÅ¥¹Ë²Í„„ñpu­rÛLÑåõÊeÙ¥8ˆmåu/^Šs†m PnÄ6‘rû\ÒÎQWñÍÕùâòý„˲ËízÀñ PN®®WfäòþÍå5ËeÙ¥8wˆm¿}‡jÞI¯ÏRœ3l#Ù48Jvý±÷u n$T“Í_}õÕ²dÉ’`ëÝÈo´cý†DþíÛ·÷¿üòK9ÿüóe̘1þ¬j¯»ì²‹ 2$cãpïF¶òšk®Y­Œl¬·¥p²òü}wYvx›®†Ã];Ú±ì¿ÿþ^#£Ôí½÷Þ{Þ${=êîÌ3Ï”æÍ›§.Œ»:Ol.Í]–à0€±puÍJjl³ JúõÐU|3Wç‹Ks—e› â'àêZå2¶™¢Ëë•˲KqÛVår/^Šs†m PnĶU5jñ¬œ®…®â›«óÅåû —e—Ûõ€ãA œ\]¯ÌÈåý›Ëk–˲KqîÛ~{¯bÞI¯ÏRœ3l#Ùêy¿ñÆáYçsžØF\š»,»` @X äsÍJjl3è$_ãßÌ3ŸóÅ¥¹Ë²íøH Pù\«\Æ6Sty½rY¶ë3€Ø¶J¸\îÅ]Ÿ/”¿ Û~³H7”í3ÏtË{ZÜâ[>ç‹Ë÷.Ë.vÝQÔ­@>×+ÛC—÷o.¯Y.Ëv]sÄ¶ê Œ’\Ÿ®ÏÊ/z8*zä(b*`Ý5Þ~ûírà 7Döpß}÷•]wÝ52-5àL˜0Á{d‰•á§¶mÛzQûþûï½g–[7Â~²á›o¾YÚµk't?Ù{M-;µÇ¢ÈÂiFR—Ïö!gê²iŠ‹LJ]>\vdA#áVÖáâ­#{|Úæ›oî5βºøüóÏeöìÙÁbß}÷œzê©òä“OJ÷î݃鵨ÉybåSŸµQf(–@M®Y©×«¤Ä6³JÝ÷Ôx•Ë3uùJŒofTÈù’jXˆy’ë3×q3 (äZUÌØfGâòzå²ìÂk!{ q¹w³½,ä|!¶e¯gæ"€@ñ ¹VÛŠW¹JŠK|+ä|!¶åªeæ#€@1jr½²í¦Þ3Æ¥–ÍõpUMÛr78*æ¹RÌ¿/ÊB ¶48ª­ë!Cà믿–óÎ;Ïk¨^´[·nÞôð4Nmim½ù©ÿþrî¹çF™¶|ùr¯ç#{´×ôéÓýEåòË/—~ýú‰=²ÍO©o|jÚÃQê£Ã~þùg¿èjoØŠYv°GáçÈú›8î¸ãä¯ý«4kÖ̟佚÷<àõ"µhÑ"oš5ò:ãŒ3äé§Ÿ–ÆG–Ïw¤¦ç‰•K}æ«Ër Plš^³’ÛÌÍåµ¶Øõ’Z^â›íSMÏ—æ.ËNõg’%PÓk•ËØfr.¯W.Ëv]ëĶUÂår/îú|¡|*]€Ø–ÿí3ÏüK©ý’qˆo5=_\¾ŸpYvík‰5@ .5½^Ù~»¼syÍrY¶ëú$¶‰„ïÛÌ;Éõéú|¡üòà‘jåQEŒì Ìe—]&üã«56ÚsÏ=å±Ç ž3ÞíÔ€ãÏÏw ¶ç‰•ïÒÜeÙùÚ°ÄO ¶×¬¤Æ6«$_ë2¾™]mÏ—æ.˶c&!€@òj{­rÛLÑåõÊeÙ®ÏbÛ*ár¹w}¾P>•*@l)ægž¥8ê2¾Õö|qù~ÂeÙ¥¨O¶nj{½²½qyÿæòšå²l7µô[©Ä¶èw¨&“äúü­fB ³ Ž2Û0 ¬X±B}ôQÙ}÷ݽžplÜO­[·–+¯¼Òk˜Ò¤IräuéÒ¥‘qÙzë­åÿþïÿªMO°²S5JÂåµiÓ&¼Š,X° 2žkdÉ’%‘EZµjŒ»,;؈£“N:IFŒ!/¿ü²Ø39äœ[²ª¬W£pzýõ×ãY‡ =O¬p—æ.ËÎ ÃLˆ¥@¡×¬p,ò0 ±Íö5É×úˆofVèùâÒÜeÙvì$HŽ@¡×*—±Í]^¯\–íú ¶­.—{q×ç å#PiĶßj¼˜ŸyþVª»¡ºˆo…ž/.ßO¸,Û]-R2¸(ôzeûåòþÍå5ËeÙ®êË/—Ø&¾o3—$×§_¯¼"M€GªeÓay XWŽƒ ’±cÇFÖ°V«ÖˆÅ¨´hÑ"2/u$]¯:§vZµ–¯©ëÙø–[néõv4zôho¶=ÇvÒ¤IÒ½{wo|íµ×ö^ýÿjzó½xñbUïÕ9ùÉeÙþ6\½®¾úêÒ¶m[/×dÖìæ›o–… z«Ù#íÌ4µæÔ2‹qžX™.Í]–êÁ8Ä[ ׬¤Æ6«™$_KßÌ«ç‹Ks—eÛñ“@ ŸV¹Œm¦èòzå²l×g±m•p¹Ü‹»>_(J ¶¹û̳çQ©ã[1Ηï'\–]Šúd PN«S§NrÎ9çÈN;íT#…Ô¬çto†2Ú±cÇȬo¾ù&O f³fÍ æå30sæÌ`± DP¹,;Øh ¬Á‘ߣ”í^ꇵþ.û<±r]š»,Û7áâ+PìkVRc›ÕP¥^óofTìóÅ¥¹Ë²Í‚„ñ(öµÊel3E—×+—eÇ÷ ïÇ"ùÜ»Ù1û|qiî²ì8×'û†Å¿VÛVU©ŸyÆý\Ë÷ÞØ÷šdÿ@À(öõÊÊuã\¾wY¶ïÇ×rŒmæ\©õÇsŒ}r#@ƒ#7®”ZgŸ}v¤±‘Ý”ž|òÉrôÑGK£Fj,Ð¥K—È:öX´š¤ªªªÈâÖ`ÉOáa›6jÔ(VÎW{œZ¸Òf›my̛˲sî\.°hÑ¢ÈÖ7Ø`ƒÈ¸?RìóÄÊuiî²lß„Wˆ¯@±¯YImVC•z=Ì7¾™Q±Ï—æ.Ë6 ÄW Ø×*—±Í]^¯\–ß3@„ØV½vrÝçW_ƒ) 'b[½ :*5¶@¾ñ­Øç‹Ks—e'  [b_¯ì@]Þ¿¹¼f¹,;¶'€îX9Æ6ó®ÔúŒó¹Æ¾W€GÅõ¤´ xàäµ×^ ޶U«Vrûí·‹5Æ©m²2ÖYg qÏܹså§Ÿ~ªÖ;Sùálk ì'{4›4¿žqãÆÉÂ… e5ÖðÉøj“V¬XÌ0`@0l.ËŽl¨È#ï¿ÿ¾„;÷‡?üAÚ´i“÷VÂëÚJ;w®¶®‹óÄ6âÒÜeÙÕ€˜€±pqÍJjl³ŠIêõ°ñÍ|\œ/.Í]–m$ˆ§€‹k•ËØfŠ.¯W.ËvyÛVé–˽¸Ës…²¨b[y|.içj)⛋óÅåû —eWÂõcD É.®WæáòþÍå5ËeÙ.Ïb›Hê}›y'µ>]ž+”]^õËëp8Ü LžÿüsVÎ×1cÆD–±æ§úõëËÞ{ïíŠõžôî»ïãÙ†™½Ë.»DÆ]–ÙP‘G&Nœ(—^ziŸy晼·0{öl™4iR°üºë®+M›6 ÆmÀåyâÒÜeÙ F@ V.¯YIŒmV9I½ºŽofãê|qiî²l3!!€@ü\]«ìH]Å6+ÛåõÊeÙ¶ï®±m•l¹Ü‹»:O(J ¶‰”ÓµÐu|su¾¸|?á²ìJ¸FpŒ$UÀÕõÊ÷puÿæòšå²lßÅÅ+±­ú{sNj}º8G(³<hpTžõÊQ9xöÙgeÙ²eÁ.¿ürÙtÓMƒñBößÿÈê×_½¤>*-²À¯#£G–?ü0˜Õ£GiÖ¬Y0nûî»odÜIåJ?þø£<ñÄÁböذN:ãþ€Ë²ýmûu›m¶‰ùÒK/EƳÜtÓM‘s õÃ[×åybå»4wY¶í; â'àòš•ÔØfµ”Äë¡ëøf..Ï—æ.Ë6ÄKÀåµÊel3E—×+—e»:ˆm"åt/îê<¡\*A€ØV>ŸKÚùê:¾¹<_\¾ŸpYv%\'8F’(àòze.ïß\^³\–íêúh0žiÀz†zê©§‚ÙÖ°ëä“OÆý—ç‰mÃ¥¹Ë²}^@ ^.¯YImVCI¼ºŽoæâò|qiî²ls!!€@¼\^«\Æ6Sty½rY¶«3€Ø&RN÷â®ÎÊE ˆmå󹤯®ã›ËóÅåû —eWÂu‚cD ‰.¯WæáòþÍå5ËeÙ®Îb[ú÷*æÄútužPnù Ô+ä´ç•uýà )ƒuH’€5J ·BµÖºÛo¿}­a÷Ýw—õ×_?²þ[o½%Çw\dÚÀeÈ!bo §™3gʉ'ž(_}õU0Ù@ýãÿÆÃÏ?ÿ¼üýï&Y7~çž{®zè¡Ò Aƒ`º•kh¾øâ‹`Z—.]¼ 6lL ¸,;¼bß}÷ÝÕkqÄrÖYgI£FªmêŽ;îðlí‘t~2ÏcŽ9Æõ^KqžØ†\š»,;‚ÅÔ¹@)®YImV9I¼ºŠoæQŠóÅ¥¹Ë²Í‡„ñ(ŵÊel3E—×+—e»:ˆmÏJ9Ý‹»:O(r ¶•ßç’v¾ºŠo¥8_\¾ŸpYv9_'86’(PŠë•¹¸¼syÍrY¶«ó…Ø–þ;TóNb}º:O(·¬ÚÓਬ꓃q-`-­Ï<óÌ¢mæ¶Ûn“þýûW+ïÚk¯•ÔGž­±Æ^ Ønݺɒ%KäË/¿” &DíÕªU+yæ™gduÖ©V¦?ÁÓ¼ð þ¨÷Ú¾}{ï±p7–>úH¦N™o‘î¿ÿ~éÓ§OdzêˆË²S·U¬ñÁƒ{ ©ÂåÙ¹m´‘l²É&b&cÇŽõ¾`?~x1éÕ«—×KTjã¤R'¶3.Í]–dêT T׬¤Æ6«œ$^]Ä7³(ÕùâÒÜeÙfDBº(ÕµÊel3E—×+—e»:ˆm™e“XŸ™†9 N€ØVžŸKZ]»ˆo¥:_\Æ—e§ûcÔ@©®Wvt.ïß\^³\–íªÖ‰m™e“XŸ™†9xíëÒÈ)0eÊ”œËckÔÔ£G¹à‚ dÁ‚^‘ .”?þØËé¶Ñ·o_ï S»víÒͦ]|ñÅb gÞ~ûí`ÚôéÓÅrºd½*Ý|óÍ9Ùº.ËN·oŘvÉ%—ÈܹsåwÞ Š[¶l™× ËueJG}´œ~úéi{B*ÕybûæÒÜeÙ™\™Ž¥(Õ5+©±Íj$‰×CñÍ,Ju¾¸4wY¶‘@ îJu­rÛLÑåõÊeÙ®Îb[fÙ$Ögæ£a¤ ¶eÿ¤™%õZè"¾•ê|qiî²ìtcLCº(ÕõÊŽÎåý›Ëk–˲]Õ:±-³lë3óÑ0Uõ@üR{þÉÍš/¹çž{zÝëm¹å–YW¶Ç¢rÊ)òÀH®ÆFVõ”d³ul8[êׯŸ<øàƒy?6ÎeÙÙö³yÖ;‘uñh=JYF¹’ß{ï½2hР´lýRž'.Í]–Ë™ù P:R^³’Û¬&’x=tßÌ¢Tç‹Ks—e› ê^ T×*;RW±ÍÊvy½rY¶í»‹DlˬšÄúÌ|4ÌAtĶt*ÑiI½ºˆo¥:_\š»,;zæ0†u)Pªë•Œ®îß\^³\–í»û•Ø–Y4‰õ™ùh˜ƒÀ*©Æ™€@f̘!cÆŒñò¸qã¼G¦Ù£Õ,wíÚUš5kV«£X´h‘¼üòËòùçŸË¬Y³ÄÆ×]w]éСƒ÷¨·ž={Öª\[ÉeÙµÞ©Ó S+X }AßšWUU=¨x‡U0 ‡Ž € € € € € € € €@% ´ç‘j•TÝ+ € € € € € € € € Ðà¨@@VG@@@@@@@@ ’hpTIµÍ±"€ € € € € € € € P  Ž du@@@@@@@@*I€G•TÛ+ € € € € € € € € Ðà¨@@VG@@@@@@@@ ’hpTIµÍ±"€ € € € € € € € P  Ž du@@@@@@@@*I€G•TÛ+ € € € € € € € € Ðà¨@@VG@@@@@@@@ ’hpTIµÍ±"€ € € € € € € € P  Ž du@@@@@@@@*I€G•TÛ+ € € € € € € € € Ðà¨@@VG@@@@@@@@ ’hpTIµÍ±"€ € € € € € € € P  Ž du@@@@@@@@*I€G•TÛ+ € € € € € € € € Ðà¨@@VG@@@@@@@@ ’hpTIµÍ±"€ € € € € € € € P  Ž du@@@@@@@@*I€G•TÛ+ € € € € € € € € Ðà¨@@VG@@@@@@@@ ’hpTIµÍ±"€ € € € € € € € P  Ž du@@@@@@@@*I€G•TÛ+ € € € € € € € € Ðà¨@@VG@@@@@@@@ ’hpTIµÍ±"€ € € € € € € € P  Ž duâ ðý÷ßK½zõ‚|Ýu×Åa·Ø@Š"@œ+ #… €”¡@¥ÇÈGyDÖ[o½ OŸ>½ k™CBÊC ÒcVyÔ"G Pb_M´X’*Ð ©;Î~#€ € € €T®ÀÂ… eæÌ™ÀŠ+‚a@@@@Ü ÐÑ[_JG@@@@@<Î?ÿ|騱cg̘‘ÇZ,‚ €@rˆ}É­;öDèሳ@@@@@ê\à‡~©S§ûAïu €e*@ì+ÓŠå°¨z8ªŠæ0@@@@@@@@(† ŽŠ¡H € € € € € € € €Tˆ Ž*¤¢9L@@@@@@@@Š!Р…P¸˜;w®XnÛ¶­´nݺ¨\¶l™L™2EÖ]w]iÚ´iQË^°`L›6MfÏž--[¶”Ž;ÊZk­UÔmXa3gΔ‰'J‹-dà 7”æÍ›gÝÆ¬Y³¼ýªW¯žôîÝ[5j”uù|gÆe?òÝ_–Câ"à*έX±B¦N*&L_~ùEzöì):u’úõãÛî>N±$Nû—s•ý@J-à"F&->VUUÉøñãeúôé²é¦›ÊÚk¯]êj`{ €y¸ˆYyl6ã"…Ä8Ý Åi_2b3¨P$ǾRÜÃ*ôƒÃF _}Ãþ f8øïÿ[uÈ!‡T­±ÆUúwäfÍšU~øáU#GŽô¶Èþ6³m@ߤTÝ}÷ÝU;ï¼sÕj«­”íC÷îÝ«.¿üòªo¿ý6[1Á¼7ß|³jË-· ò[o½åÍ[¸paÕu×]Weûì—í¿n·ÝvUÇʰÛ¯[n¹¥JE–_}õÕ«úõëWuúé§WÍŸ??²Nx$.ûÞ'†@$ ¸Œs£G®úýï_¥ J#×|‹Ú¸Ö‹)çœsNÕ’%Kªþë_ÿ bŽÅŸÓN;­Ú2Ù& 80²þW_},§X§} €@ð\ÅÈBâ£í˜«9f̘Hìüàƒ<‡åË—W]uÕUUúÃ’ žßu×]Þ<ûïÎ;ï ¦[ŒŸ8xWö!èQG¹¹Ö¿ÔjãÚ;O•Ýh×´ÁÑ#}ª¾ù曡öˆTe1Ö'Ö@)Slˆ¬¨#ÚÛ^°ž­¯½)U­\¹2X,N±$Nû1€T¸€«YŒøhUã*FZ#?îÚëk¯½V¥½å¦½‡«mƒ#‹åö£˜ðv¶Øb ï~ºÂO;¨•@1cÖàÁƒ#×çðµ:<|ÜqÇEöµ¶ñ#N÷BqÚ—.# €Õ’ûì`Šu_èÃÃ| ^¨hõâû, ½“ !P‰Ö…¡þâRî¹çžœ‡¯—/2dˆ\yå•9—µ¬líÅGþô§?‰¾1ʺŽöø x <ýôÓY— Ï|ÿý÷eÇw”O?ý4<ÙN÷¨¶üQôפrê©§V[>Ûë‚q—]ví1"ÛbÞ<ý B>ùäùÿïÿɈ#r.ÿî»ïÊ>ûì#vü¹R\ö#×~2ˆ“€Ë8gÇyî¹çz1Tù‡m]Ùl³Í¤k×®Õ¡ùÑGÉæ›o.ÿûßÿ‚å;tè ;í´S0¾hÑ"yùå—ƒñlO>ùddöa‡&öøÎL)N±$Nû’É‹é €@9 ¸Œ‘ňf_ª©=É~ûí—×=\>ç„66’=öØC´Ü`ñ­¶ÚJô—ÉEdy°@2p³ a«müˆÓ½Pœö¥º`]@ ÜÊ!öë¾0SÝÃ2É02 hcz8ªèk¼ /¼°Ú/zvß}÷ªûêË/¿¬š3gNÕK/½TuÒI'Ez_Ð?Ô`½LT³Ç‰…—kذ¡÷h6ëþѺž7n\ÕÃ?ìu1ï/—úH´L=i㡪Ô.­¢§žzªjÚ´i•múà×/_#ûaÛºñÆ3r¦¶’¶ž&üýÓÆSU¯¾úªçbûoNÖs’?ß^4hŒ·nݺêšk®©zï½÷¼^ô‹æª¿ýíoÕ¹cû™šâ²©ûÅ8 $—qî•W^‰Äƾ}ûVicØ~8Pe½ñíºë®Al°Xaˆ“õžŽ%öø•|’õ˜^oìØ±‘ÕâKâ´/$F@ p#‹­j\ÄÈÔ*þð‡?Dâiûöí«öÚk¯*ëÙâ7ÞÎ|©öÓO?UYO¶áø¼Í6Ûd}œv°@Ò ;f͘1£jÔ¨Q^¶{¯ð5Û>õçYO{áTÛø§{¡8íKØ–a@¨@Òc_±ï M‡=GC Bx¤Z…V<‡Sk´Ó²eËà¦ÚçrÁDÅÞu{´Xxyÿf<]ƒ#ûµmÛ¶AÙÖhç?ÿùO¸¸È°}ˆÜ¸qã`y¿ìL Žþþ÷¿G–µÇÙh‘2Ã#çŸ~dùõÖ[¯J…^$N}ÓbûÒ¨Q#ïÍL°PhÀ>„H÷(m·Ý¶jöìÙ¡%¼îºë"û“î‹å¸ìÇo{Í ,—qÎ$ Z->Î;7+С‡¹ö[\?Ù¾†ãàk¬‘5®Ùzö¸O?^Úkj#&[&N±$Nûb6$@ ’\ÆÈbÆG«#12õ c?žvìØÑû±H¦s#Wƒ#Û×­·Þ:ŸíQÛvLB¨€Ë˜e{d?²ô〽N™2%ãŽÖ6~Äé^(Nû’š €@… ”Cì+ö}¡İ ÿÃàðX%À#Õô¦…„@l´"™?~°?gœq†\|ñÅÅbþºé¦›‚å³ \}õÕ¢½#‹\ýõ²Ûn»ã©ö¨³K/½4urÚqý‚Un¸á†`Þ[l!úÁ¯4iÒ$˜–:0tèPÑž…‚ÉúK&ÑPÁx®SN9Åëb?Ýröhë?œ´’Ü}÷Ý¢®Â“ƒá“O>Y´'¤`üóÏ?†³ Äe?²í#ó@¸¸ŒsvŒüqp¨[n¹¥¬µÖZÁxºN8!2yôèÑÁ¸6X’½÷Þ;·G‘ê/‚ñté§–n¹ÔiqŠ%qÚ—T'Æ@rp#‹­J#µÇ\ïñØÚQ­ª^¿ðîyÃMµGs[Š-¯õ¬!Ÿî½÷^0ë«}|Þyçe]¦[·n‘ù‡~¸tïÞ=2-<¢—“ 6Ø ˜ôÝwßÙâ²™öé €@œ\Æ9;Ε+WÊøñãƒCÖÇŠ6°ÆÓ h¢½ʰaüܻwïÈbúËŸÈxjƒ¢ÈLyâ‰'‚I>øà`<Ó@œbIœö%“Ó@rp#]ÄG«ƒRÄHûQK«V­jUå?üðƒèãSeäÈ‘Áúöƒ},h¯…Á4@j&à2fÕlO2/]›ø§{¡8íKfeæ €•#P±ÏÕ}aêY@ KaÊ ÁQeÔ3G™}Œ‹„¹sÌ1{ã Ž}¡i=!eK_}õ•XÏ ~²ž‘òidžN<ñDµŒ¯áž‰:wî,Ö«D>©M›6²ÓN;‹ê#âÄÞ¼åJúh4YsÍ5³.ÖºuëÈü^½zEÆÓ´hÑ"˜üý÷ßÙâ²™öé €@œ\Æ9;N}”¦„¯õß~û­wÜq²bÅŠ¬ CÏ>ûl/0 ²ì{ì!áxòâ‹/ÊâÅ‹#Ëø#Ú͵/5ói´§X§}ñ]yE*AÀeŒt­N\ÇH»§ÌÖ#o¶óbÞ¼yb1=ü ^ÛßçŸ>k/¼ÙÊd €À*—1«ƵqºŠÓ¾£N(Hº@9Ä>W÷…©uK KaÊ ÁQeÔ3G™ &Dö²&ÝÆ÷ìÙ3²nêÈĉ#“vÞyçÈx¶‘7Þ8Ûl¯‘”uUï'{œZMRøËaë%iòäÉ9W_ýõs.c=…“5„ªI²ß¹R\ö#×~2ˆƒ€Ë8çŸ=&%œîºë.±kµ5(Ê÷Q™áõ­¾ƒ:(˜´`Á‚ŒÿLíýèÏþs°^¶8Å’8íK63æ!€å&à:F;>š¿ë¹Ùf›ÕªšíG<ýû÷÷Åæ`ûzÿý÷KãÆýI¼"€ÔRÀu̪ån«Õ6~Äé^(NûÀ2€T°@¹Ä>÷…©§1,U„q*C Ae&G‰@üRuìØ1ïÎÄS˶Gªå›ríǸqã"E}ñÅò—¿ü%2-ÛÈ×_™=}útÉÕÈ)×>E üudÝu×M7¹ iqÙ‚‚•@ ¤Æ¢š\CsÅ9ÿ.¸à1bD¤§¡™3gÊ•W^éeëYoÇwô±b=ä³öȘÛo¿Ýß„XÃ"ë)05…§fjÙÿýSI;žÏ>¤®è"¦Ù6â´/©ÇÌ8 Pήc¤‹øhõá2FÖäž5|nì·ß~2cÆŒð$ïñßçŸ~$žG`@ o×1+ïɰ`mãGœî…â´/˜™ŒT”@¹Ä>W÷…á“Ö`Ê ÁQåÔ5GsÔ7-ù~¹j‡e_<Ú#Ò2=6&µìV­Zå­‘k?Ò58²FGµM¿üòKÎUkóE«uYì—ý(öqQ àB 5åŠ/á}Èçüe[¶l)¯½öš 8Ð{õ§û¯ÖëÁSO=åe›f \>ø`ïñ¡k¯½¶¿XäÕºîÔ©“|óÍ7Þt{‹õÈg½%øiêÔ©òÁø£b_vZ££|RœbIœö%;–AÊEÀuŒtÍÞeŒlРvW¥66òÏ‘;ï¼S=ôÐÈ#½ýy¼"€ä/à:få¿'é—¬müˆÓ½Pœö%½2S@Ê(—Øçê¾0|6à#P9Åÿ¾rì8RŠ*`=û„Së֭ãY‡­±Q¶êÔ]×\sͬå…gf+×–³/Y‹™/^œ³8;Þ8¤¸ìG,Ø@ —€Ë8Þ¶Ý<ÿç?ÿñz::âˆ#$SC"[çË/¿” /¼Ð{ìÚ½÷Þ.&®W¯ž„6þüj™R§f=>ä›âKâ´/ùú± P¥ˆ‘ÅŽæî:FR·‹‡ QUU%Ç{¬äs¿¬Ä €@5RĬj-Á„8Ý Åi_J@Ï&@Ø ”Sìsq_®@bXXƒa*G v?«Ž’ XËß1cÆÛ³GÀtîÜ9Ï6`=6,Y²$ã"©½,üðÃÒ®]»ŒË‡gÌž=;mÚ´¼)r-›Ú£QMz%ÊUv×®]#ûi˜Ùm·Ýj÷»ßEÊc@ <\ƹlBöHÍm¶ÙÆëåÀ·fnÿýïËñÇ/Í›7VµÇ’žtÒIÁxx {÷îÒ§OŸ`ÒsÏ='Ë–-óÆ-N†§vÈ!‡díu0(„@~¨‹YŒøh»·9tèP¹þúë½Þ—V_}u¹õÖ[#çÙµ×^+Ÿ|òId# €ù ÔEÌÊïX@â ”sì+Ö}añÕ)’$@ƒ£$ÕûZÖ© wü_aæsГ'OκXÇŽ#ós5" /l_ÊfK©û=nܸl‹3@ BRãE1ã\MHíËÇÝwß]n»í6ùì³Ï$#§L™"Ök`º~Lš5Z²“,=õÔSbiñSx9¯ €dˆCŒ¬m|´ã ǾºŽ‘‡~x„ÚzüÓŸþL[¾|¹}ôÑb¯$@š Ä!fÕ|¯Y@Ú TRì+ä¾°ö¬‰I ÁQÒký/ÔVÒ÷ßÞÇ–kÙ~ýúEÊzá…"ã™Fì14Ö‹C¶df³ç¾úé£>ªö¨^ºWë‚ã7öòN;íùÒ6ÝòLCH¦€Ë8g"—_~yORã^&± 6Ø@N=õÔÈìO?ý42îXÏEáçûQó_m¹=zHß¾}ýUxE@ /—1Òu|´Œ{Œ´Ç«…{ýµŽ®¹æš¼ê†…@¢.cVtKŒ!€ rˆ}¥¸/ŒGm± P48ª u¶‰@{ÜKëÖ­ƒ9ï¾û®Œ=:Ï4ðÕW_É‹/¾˜i¶7}Ûm·k™ì§‡~Xòy¬ÚwÞ)“&MòWËøjPóÓ¼yóäŸÿü§?šõÕmóÈ#ˆƒåM6ÙÄëú>ëJÌDH¤€Ë8g öHN?ž|øá‡’«÷?1ÜhÖ¦­·Þzþ¬È«5°µ^üd r­G¤÷ßߟ$©½*3@@ ‹€Ëé:>ÚaÅ=FÚþ 6,R_|±Ð;o„„@ /—1+¯`!@J,P±¯÷…%®6‡1 ÁQŒ*ƒ]©lûÅå…^A°^,X™Y²d‰œyæ™9{jÕª•XOB~Z¶l™œrÊ)²xñbRµWû²öì³Ï®6=Ýûuh“&M‚YW_}µÌ™3'O7°hÑ"4hPdV¸+þÈ F@/à2ÎNjÏB·Þzk^f¯¿þz°\³fͤ[·nÁxê@8NÍ;WN>ùä Û3ÏÃóS×e@L.cd)â£W8Æ1FwÜqîÑî…=öØ Žgª¦#€D\Æ,KvoN¹>c /Ë0 €Å(‡ØWªûÂbÛS$C úî=ûÌ^"P¶'œp‚„»g1b„ì¼óÎiïüðÃb= ½òÊ+yyœ{î¹Ò¢E‹`ÙçŸ^vÜqG3fLäCÖüÑë^~—]v‘ùóçËgèØ±£œsÎ9Á"Ó§O—>}úÈÇL Øô-¶Ø"ÒƒÓQG%¬‹Ñ@IDATÖRœ„ P¾.ã\Ïž=e³Í6 ð®½öZ2dˆX#ÛtÉzÙe—É¿þõ¯`ö{ì!©n3u`ÿý÷—5ÖX#˜îapÀ€Ò¾}û` €ÔDÀUŒ,E|´ãŒ{Œ´ø~ûí·GúöÛoËwÜQ“jbY@p³|\ë…!œ®¼òÊÈg—áy #€ P ¤Ç¾RÝ–¢.ØÄO Aüv‰=B r6l(×_½ì³Ï>b_„Z5j”¬¿þúÒ»wo¯÷†¶mÛzoyï½÷ä§Ÿ~ò–±/HÇ/&LðÆÓý×¹sgyðÁeàÀ²téRo‘‘#GJ¯^½ÄZho¼ñÆbC³GÐXÏI~:餓ä–[nñG3¾ZoE=ôPÐ-ý´iÓÄå¶å–[z_wéÒE&Nœ(Ÿ~ú©XïIá/€íÍÎM7Ý”±lf €”‡€Ë8g_$Ú£@·Þzk/†Zµç“ۣϬ­õ\Ô©S'ùþûïeìØ±b ?vÍ>ÔÎבּÑ~ûíç­›Z#Öp–„ €@m\ÅÈRÄG;æ$ÄHk˜l½Û=·Ÿ,{ï½7†}^@<\Å,Ó=zôð½×'Ÿ|Rš7o.:t?þñÞG" 0‚ €€c¤Ç¾RÝ:®ŠG˜ Ðà(¦ÃnU®À^{í%¯¾úªzè¡^ “°@ÖHÇrjÚd“Mä‘G‰tŸºŒ?n ™¬w!ûRÔùÉz5²Lá´Új«É¥—^*;ì°Cä ØF… †W_}uùßÿþ'ýë_å‰'žð¦[æ÷ßßËÁ‚)ö¡ïSO=%M›6M™Ã( €@9 ¸ŒsÖ=ðùçŸ/C‡ ~ûÅ_ˆålÉbÐý÷ß/mڴɶ˜7Ïc•©uëÖ^Ïái #€ PSW1²ñÑŽ5 1ÒÞ#ØýªõÊkÉ~Äc¿V~á…¼qþCÈOÀU̲­û AýkµM[¸p¡|ýõ×bí$!€ PI}¥º/¬‹ºa› P·Ù3çÌ<ó¼ (UZ íXÄÜL)’Ï:ë,›:uªw(ж\ø| ”$Rª¥0 M £e«V­ê;Me/Ùe—Ùo¿ýVl±:ckÖ¬iÏ>û¬=úè£~äQ±Ã>hY¹"I¤´õÖ[‡}ËG@Ègé¬ç®¾újSJÒ-Z”аB… vòÉ'{Ç£C=´Ô嵀޽^½zÅ–=å”SLÂ[€ PVéª#Ó]?ªÜ¹PGn¼ñÆvçw;MJ‘šbµØ—|€ ¨ÒUgÉEB׿í¶Û.ê¾ù€ ¹^÷•Çsa&Î û„2K BYvÿï¿ÿ>áÖï^–m°. €ÒÁ|þùçÁjË—/·† ú4hݺu³FE_9Îo´¥cS:5u jûÕªU ®=f̘b® ³fͲvØ!ø}´‰Õ«WÛôéÓ}J8¥…ûî»ïü¶7nl­Zµò£•èœFù€ ƒ@:빿ÿþÛÆçë¸ùóç›^+V¬ð6üº*Õ¨„·-[¶LvÏž=íᇮ§ºZ‚^€ *éª#ÓY?ªìÔ‘©ú°@¹C u–žãfÏžmª¿Ôn©%¡í–¹C‰#… |"ëu_ºŸ óé\S@ T•ʈ PØ®»î:»êª«‚d]\»víàg& @…DÀ îm›m¶ñ&•[©Gå H@€ ud¡ÿ(? @€ @F qå+0Å…@AZùµ×^ –]#‚vß}÷àçX|ðAðku°"6 â`€ Àĉƒb#ÿœsÎ)@ € P’udI&Ì @€ @ùLÁQ>Ÿ]Êÿ¨T©’õïß?ØAºé¦›ÚâÅ‹­F1)Z¨kÃqÇsy¾„ ä;»ï¾;XÄ uc€ Pà¨# ü@ñ!@€ @(8 ®ÄJà°Ã –ü×_µ#F?Gš˜;w®qĶnݺà×;wN3@(4}ô‘7.XìóÏ?ߪT©üÌ @ P PGê™§Ü€ @€ 2 e)ü¿ÿþû„[¿{Y¶Áº€@ùxã7¬}ûöÁU®\Ùúöík—\r‰5nÜØÏÿã?lÆŒ6uêT>|¸-\¸0¸|Ïž=íÁ ~f€ ïüq[µj•Õ¯_ß>ûì3»ï¾ûlåÊ•¾Ø›m¶™-Z´ÈäH@€ ud¡qÊ @€ @€JhLJµL˜ü$pðÁÛ-·ÜâF*á_ýewÝu—m´ÑFÖ°aCßqº~ýúvÙe»ãŽ;JÌg @ Ÿ |ðÁvÿý÷G,âUW]…Ø("fB€@! Ž,„³L!@€ @€@l¤T‹Í‡o!W.¾øb»þúë­ZµjÅʵvíZ›3gŽE~úé6eÊ“(‰€ @Àì¼óγ~ýú€ 0Ô‘a@ø@€ @€ò˜Gy|r)"8p õéÓǧ…5j”ÍŸ?ß”J-45jdÇwœtÒIÖ¦M›Ð¯˜†  wÞÙš5kf«W¯¶¦M›ZóæÍ­S§NvôÑG  @ˆD€:2æA€ @€ Â"P¡,Åý÷ߟpëw/Ë6XÈ,÷lßÿ½}÷ÝwV³fM«_¿¾U­Z5³ÅÞ!@€ @€ @€ @ÈVq8ÊÖSÃqA œT¨PÁ‹Œ$4" @€ @€ @€ @€@i*–¶ßC€ @€ @€ @€ @@p Á; @€ @€ @€ @€ P*G¥"b@€ @€ @€ @€ @ @ r`‚w|öÙg6fÌÛa‡³xÏa .´êÕ«[ݺus¸z€ÀôéÓmçw¶*UªfñžbŸ|ò‰]uÕU¶ÑF¥xËl.“æÌ™cO>ù¤5oÞ<“‡Á¾SHàã?¶–-[Z¥J•R¸U6•)_ýµ5hÐÀjÔ¨‘©CÈûýþôÓOV±bEëÕ«WÞ—µP ¸lÙ2»÷Þ{­E‹…Rä¼/çŒ3l§v² 6Ø ïËZœ;w®ÕªUË¿ ¡¼™(ã/¿üb¿ÿþ»õë×/»gŸi  û•[o½Õßç§aól2>ÿüsÛf›m¬ZµjØ;»L5 øö2Ú™SMö¿í­Y³ÆV®\i_|ñ3™Ê ãÆ³Y³fÙ[l‘å)ôB|õÕW¶å–[ÚÆo\è(r¾üüñ‡©]r×]wÍù²dkÖ­[gK–,±Aƒeë!r\e$€à¨Œóqu=Ž?ÞÔpCä>™3gÚ¦›njM›6ÍýÂPÿ¿¹zõjÛpà ¡‘&¯¾úª]pÁŽÒÄ7S›U‡Î­nˆü ðÊ+¯˜+Wæv6ÎèäÉ“}G ×é;›§èÁQú—÷–—.]jºªá†È&L°U«VÑ)›§Ó¦M›f7¶† æI‰²¯ßÿ½}ûí·޲ïÔ$}D?ÿü³½ôÒK¶~ýú¤·ÁŠÙEà7Þ°=÷ÜÓ6Ùd“ì:0Ž&))1íV[m•Ôú¬T: /Õñà¨tV¹¶Ä[o½eê{c0d®¹ÈÇûî»ïúáº&¹M`íÚµ¦vI d ÒC@í‘<Œà(=|³a«ôÐdÃYȲcPƒØÖ[omÆ ˲#ãp’!pÅWøQ²Ý»wOfuÖÉ2z0¹úê«móÍ7ϲ#ËŸÃQG#ïòç|JR¿~}ßÙCÝ ’ûï 2q`îŸJ_‚“N:ÉÎ:ë,Ûo¿ýò¤DÙW SôCäÝÖ¬Y“ç¶ü9¥¦Fk9mê¾…È}}úô±£Ž:Ê:vì˜û…ÉÒ¼óÎ;öÀdéÑqXÉK@ÕªU©Û’—¥ë|ðÁ^8±í¶ÛférX‰¸ä’K¼Ù‰'ž˜Èj,›O?ýÔ·ý&° ‹æfÍšÙf›mfÌ‘#æ0c8æ˜cìÜsϵ֭[ÇZŒïr€€œwºuëÆýgÏ•ƒ32€³`Ó³à8@€ @€ @€ @€ @ G 8Ê‘ÅaB Yµkׯ¶8YxY¸žrWㆠ2£FJÙ¶ØPæ \vÙe™?Ž€@1bD‡  4°§Ÿ~:›b(XØdì©§à€ @€ @€ @€ @Hœ‚£Ä™± @€ @€ @€ @€ –‚£‚=õ€ @€ @€ @€ @‰@p”83Ö€ @€ @€ @€ @€@Á@pT°§ž‚C€ @€ @€ @€ @ qŽgÆ€ @€ @€ @€ @(XŽ öÔSp@€ @€ @€ @€ $NÁQâÌX€ @€ @€ @€ @KÁQÁžz @€ @€ @€ @€ Ä 8Jœk@€ @€ @€ @€ @ ` 8*ØSOÁ!@€ @€ @€ @€ 8G‰3c @€ @€ @€ @€ ,ÊÙ^òßÿÝfÏžmË–-³•+WÚüaëׯ·Ã?Üš6mêݺuV­Zµl/ Ç@€ @€ @€ @€ œ'•‚# Š^xá?~¼}òÉ'ö矖½ýöÛG÷ÝwŸ½ýöÛÖ©S';ꨣ¬nݺ%–g @€ @€ @€ @€ PvY'8z÷ÝwmðàÁöí·ß&Tº¯¿þÚô1b„ 2Ä;ì°„Öga@€ @€ @€ @€ @ tK_¤ü–xþùç­OŸ> ‹BpÍš5Ö¿»öÚk#:#….Ë4 @€ @€ @€ @€ ¬M™2Åhÿýw‰ÔªUËÚ´icn¸a‰ï4£Zµj%æ5ʆ Vb>3 @€ @€ @€ @€ ä d…àhݺu6hРb¥ˆ¨GöÚk¯™ÄH=ö˜Õ¨Q£Ø2½{÷¶Ûn»Í7n˜åßyäSŠ6€ @€ @€ @€ @H ¬=Ú–.],QÕªUíþûï·K/½Ôš6mœm¢B… Ö±cG?~¼{ì±Å»ãŽ;Š}æ @€ @€ @€ @€ <¬3&X¥M9r¤í¹çžÁyñNl°Á6xð`Ûzë­ƒ«|ñÅ6oÞ¼àg& @€ @€ @€ @€ ä d\p$1Ð7ß|,A‡¬M›6ÁωN(Ûõ×__lµ‰'ûÌ@€ @€ @€ @€ @ 9ÍŸ?¿Ø‘ï¶ÛnÅ>'óAÛÛQ BÓµæñ@€ @€ @€ @€ $N ã‚£eË–;êTŽ*UªdÛn»mp»Ë—/N3@€ @€ @€ @€ $O ã‚£?ÿü³ØÑ7lذØçd?Ô«W/¸ê?üœf€ @€ @€ @€ @Hž@ÆGuêÔ)vôß|óM±ÏÉ~˜;wnpÕjÕª§™€ @€ @€ @€ @€’'qÁQ¸£Ñ_|‘|iþ·æÚµkmñâÅÁí„‹š‚_0@€ @€ @€ @€ $D ã‚£–-[ÚÆo<è‡~ØV­ZüœÌĸq㊭ֺuëbŸù@€ @€ @€ @€ $G ã‚£*UªØÁ<ú+VØÀƒŸCÒµ×^[lµöíÛûÌ@€ @€ @€ @€ @ 9é°ûõëgbÒ¤IÖ£G[²dI`V©ïÿüó½úê«Ö·o_[¿~}pù:Ø[lüÌ @€ @€ @€ @€ <Êɯšº5%:çœsìöÛonôƒ>°Ž;Ú 'œ`-Z´°wÞÙ$* Ä¿ÿþkË—/·… ÚìÙ³mÔ¨Q~:ð½Þ7Úh#0`@謴OKì´xñbûí·ß¬I“&¶é¦›¦tŸ¿ÿþ»ýòË/V»vm«\9+N_JËÇÆ @ ûP·eß9ሠ@ l¨ÛÊÆµ!@ ; ¤³~£M2;Ï9G@ P¿ÂY¦Œ€ «²F±"g¢eË–ÙsÏ=dùÇØ“O>ü:qî¹ç …~§éŠ+zSãÆÃ¿JùçÕ«WÛC=d/½ô’}ûí·&1T jÕªeM›6µýöÛÏÎ<ó̤DBï½÷ž=úè£6gÎûþûïý¦+T¨`uêÔ±víÚyQV«V­»ä€ PfÔmeFÈ @ ËP·eÙ áp @ %ÒY¿Ñ&™’SÄF @ ÔoI@c@€@dàHe¿öÚkM¡‘#Gz‡ Xùä{óÍ7mذaq§xSJ¹K/½Ô¯¾m‰šV¬Xa/¼ð‚tÐAvË-·Ø&›l¾(Ÿ!@  nK C€@ nË“Ä!B€@ÂÒU¿Ñ&™ð©`@H!ê·ÂdS€ 4¨˜æí'´y¹õéÓÇ&NœhǼÉÅ'‘¨R¥ŠõêÕËÆoà¤;äÆtå•WFE:ö™3gÚÑG]"õ[¤ãüá‡ìôÓO(6Š´¼ÄL;w6­G@€’%@Ý–,9Öƒ l%@Ý–­g†ã‚ ²HWýF›dYÎ ëB€@Y P¿•• ëC€Ê—@V9Š®TaC† ±îÝ»ûTbóçÏ· Øš5k‹ßåèÓ¤IÛn»í쬳ÎòéË‚_¦qâ­·Þ²«®ºªØöÞ{o;âˆ#¬M›6Ö A›;w®M›6͆nÊs®X»v­Ýzë­vÏ=÷[7ôƒRÉõèÑÖ.]œ]µjUkÛ¶­í³Ï>¶Ûn»ÙªU«lêÔ©6zôh“µ¤báÂ…vùå—Û<°X+¸#& @ ` P·ì©§à€ò–u[ÞžZ @   ¤«~£M² V€@Æ P¿eüp€ „ d¥à(PŠvÚɧ |þñǽ¨fùò妴iM›6µÚµk¾.·÷õë×û”m¡iÝ:uêd7ß|³É¥):~½öØc/†Z¹r¥ÿjÒ¤IöñÇÛî»ïX´Ø»ì"gÏžœ'ç¦GyÄZµjœ§‰víÚY×®]í´ÓN Š“”[] ð.]º[–€ÊJàÅ_ôi/uM#òu[þSJ@ Ð P·ú/€òCÈOé¬ßh“ÌÏß ¥‚ ¨ßrá,qŒ€ ’þSÇ”ü.ëæl¾ùæ^¤sä‘Gú÷Lˆe̘1öý÷ßùtèÐÁnºé¦bb£à—n¢yóæ^:O¢£H¡›ªûï¿¿ØWr{ hܸ±wL |Ö»@3fÌð¢ÇQ£F•†F—(Õ¥ÒB\ÕÊ¼Ñ n@lžyæûûï¿3xÙµkê¶ì:  ”u[Ù²@È>éªßh“̾sÍA($Ôo…t¶)+ äŒ Ž^ýu;ãŒ3‚¯Áƒg5_uN92xŒ•+W¶+®¸Â*UªœiâØc-&Húúë¯#-fcÇŽµ+V¿kß¾½É=)VHŒ´çž{ùüóÏmÉ’%ÁÏL@…G`úôévðÁÛ¬Y³¬OŸ>¦Ô”ɆR8ÊI­B… öÝwßÙ 7Ü즲b=‰ößëÖ­›µlÙÒ&Nœ˜ǕɃ nË$}ö @é @Ý–ªl€2M õm’™>»ì€@á ~+ÜsOÉ!@ ÷ d<¥š:Á'Ož$ùûï¿§³qBøK—. šAuêÔ ~Ž6Q·n]»öÚkí‡~ð‹lºé¦}ÿý÷‹Í—` žØgŸ}lÚ´iÁEÇg½{÷~f(ºNéÚôÛo¿ÙÕW_m×\srÊ)öî»ï–*ŽŒDéì³Ïö"F¹¯Ýwß}6|øp;óÌ3m›m¶‰´xVÏ[¸p¡É•î?þðB¬Ç{Ì;ì0;âˆ#lèСÞ*« ¦ƒ£nKX6 @#@Ý–1ôì€ÒH õm’iÚ°aÃìÆo´Aƒ%´«Ñ£G›^ÇsŒuÖY¶ãŽ;Ú¾ûîk^x¡ß~BËðÂ+W®ôâ"¥ÄTêI¥ˆ“C^J;'§#•ñ¯¿þÊð‘–ÿî©ÛÊŸ9{„ò“À”)SlÀ€vÏ=÷x½ü,en”Šº-7ÎG @‰HgýF›dbç‚¥!@ u¨ßRÇ’-A€Ê›@ÆSª5oÞ¼X™úé§  P±/²äCèO5lï½÷NÙ‘ÉíIâhÑ¢…Õ®];ð1æû.»ìbÕªU .3oÞ¼à4€@vK^¯¾úªíºë®Ö¯_?Óµ¯¬¡ë“œä÷òË/{±‘¶©hºFÈéèã?Ž{7JÍ(w£úõëÛ<à×k×®xâ‰~û&Lˆ{[éZPv»—]v™w[S}Žr{êØ±£Íž=Ûî¼óN/6Òr[l±…=ñÄÞ!NNqÚF¨‹]¤måã<ê¶|<«” ˆ—€R?úè£eJ?ª})U´„¾IPœŠP´fÍšTlÊþüóÏ”l'W6BÝ–+gŠã„ D¤«~£M2‘³À²€ jÔo©&Êö @åG ãG7öÎcÆŒ –ZØÝ»w~Ζ‰þùÇäˆ-·Ü20éßçÌ™ãS}÷ÝwÞQ¤iÓ¦¾|ûí·÷ÚÅŽðá³Ï>+6w»í¶+ö9Ö‡*Uª˜Žç›o¾ñ‹©Cá×_µh©Ûbm‹ï ôøüóÏí‚ .0]zè!»òÊ+íî»ï¶§žzʧ]ìÓ§ORiÏ$$:ôÐCƒb£ÐtŒn¸¡wðÙc=üµU×±êÕ«Ç,ä¿ÿþk§vš­ZµÊ;¦m¾ùæÁåo¹å;v¬þù¦ë–®?ÑB)3—-[æKiÌ$† ¼KÕ©S§h«–:_)*»víjo½õ–?¹F‰¥Üœ”&-r,êÒ¥‹M:Õ»sÎ9¯‚ï»ï¾»½óÎ;ö /ØÅ_œ_Ôm…p–)#r—€„¤À.X° ØkÑ¢E&§TÕ›Œ&ªT§)í±ê&ÅV[met©=ðÀ­aÆqmZõ‡¹o¼±5kÖÌ×'rÔ«W¯^\ëGZèÍ7ß´£Ž:ÊvØaSŠ“ÐÁ‘–Ÿ·bÅ /~úàƒ| kÕƒª7 !¨Û á,SF@…G õm’…÷{¢Ä€@öP{¬šû:õ[öý9"@€@"2.8ÒÁ*:¥Õ(®PÿR„%"¸ñ+¦ùO@HØÄRН¾úÊ‹¾øâ‹ÀW%ÞÕa1pàÀ˜Â£Pw#m`³Í6+±X3ä¸Ú^2‚#uèh¤w@ô%±‚„ P6k×®õÂuž>ýôÓþ:§D¥,»ä’KìÜsÏõ;·ß~»ïèŒwoÊ(å™:Kål*6 lCâ9]tÑE^P£T/±â¶ÛnóB9qÄÅÕµïòË/Š¥$  •Uë>þøãá_?WªTÉ; µjÕ*8/Þ‰iÓ¦YçÎ}'´D×]w‰ÛСCíðÃ÷/ vÚi'ëÝ»·w“:ýôÓ=ƒð}¨#[å „TrD ¿¦¾Ï·÷B©ÛÔ`³xñâ`ݦóøðÃÛlo§”ò@ oè:.a®Ò„†‡\@U‡>ùä“&WP‰Nuï*ÁO<1sæL;ãŒ3lúôé¾®PªP rßxã {ä‘GüKÛ‘ØçÔSOõÛvo®å•’³nݺ>=§¨ŽÒý³žs’ ¹%}ôѾ¡YÇÕ£G¿PÚ¶ÄJ÷¯½öšÍ;7¸¸ê6¿Ü ! ¥nÓóó?þX¬n“ø:ÚoµÎ=e„òŸÀÿýßÿÙ‹/¾è úË/¿˜^…é¬ß²¥MRçSÏã6I[µÇ+/”ßå„ÒC@m«7Ýt“-\¸Ð·Ó¶nÝ:=;r[ÕõNS%ø|å•WLi-5ðSb£lëK„ÿm¸ê7uÖ¬Y¾ Bï ç«®ºÊOó€@¾P»­2Š(Ô^™Š,/ùÆ(ŸÊ“‚#uꪳ@Áß~û­ï4W§:Û¶m›5¼åêtî¹çlðàÁQÓø–—‡þ¹Ôñ­ôI‘"¼‘$цâpq‘ 䢒hÈÉD)”Ôq¢¨X1ã™÷-ËåË—›\”ž,žÐãÜy$x‘H¥råò¹JP$1ŸD1UBŽêTTú•[o½Õ§E;òÈ#ý´::£…þÇÕ©¨ŽN¹èáT® ÑB©ZfĈ¦í‡ ‰ëéAW¤rgÓ±F —Ô‘ª4mj¬S§Np1‰/å(¤‡'íGµU«V5‰ï:v•¹W¯^ÞyHç"Þ¸ÿþûýuTëHÐtÊ)§øUu,ºnéØU§¨³VuÈ{ï½g:t¦… ßOÍš5ƒ×;}§ŽÝB¡Jݦó\«V­b纼þ÷Ãs|†@>@H)Cu Ž75p8]—$’kà”S÷´¡/9õ©ž¹÷Þ{}] gÕ‰ªszöìéS‰Fú_¿~½ŸÞxã¦Ñ£ >]÷µžBÎ|ºw—øHΫªW† bgžy¦w) u9>|¸ 0À»-Mš4ɶÞzk/RR§˜ê+¥ýLô^züøñvÜqÇy7‰'ú}K¨¬ûm/ZHì+G$û6Ûlã ·Ýv[kÔ¨‘?>5`Ϙ1#Úêy5¿Pê6=ÿIdxnÓI,ÍÅ2¯N4… ’€:¼ê¨Uý[(‘Îú-[Ú$Õ¶¡û²Ðº-ÑöÑBù=PN@ µä «g>µÝ*ui·5ˆ\Ï{jW¬P¡BÒ;”K»Ú5àEïzi0ˆžI¡>2 ÕsôêÕ«³ â½ê7È ˜Ú$ºuëæÏk¡ v-ˆ1…„JP›dàž^Ú #ò—@ùô²ÇÁOé Ô.ñŽÉåD Žužë¥ÎUÈÉÜØ…v„Çq(Q øÖ¨au¸Ëò1Ù¬~)õæÍ›gJmMëJ©ÔáÛOô†#|ùðÑIáû‹öy“M6ñ£b÷ßÿh‹0YA@× ‰t|ðA/TT'œ„бÄ+ .7 )S¦ø2¨SQ׉aÒÀèAU¨þ„‡:‡$˜Qg§Ê¡c’;*䫯¾Ú»&ÖÑèDFêXÕÿù!‡âEDºöÄ ]?%Б„œÔ8«†ZmO×,‰¶ôêß¿¿Ÿ7jÔ¨¨é[$’óÄñÇï;bxà¿k9ÆHT©ëÄJ*k´ë¶DK5t×]wyX¬c×wŠÉ5IûP‡®F¶î¶ÛnÅV“TeT´o‰$îzöÙg£ ËÔQz½SÇp¤Nêb;Ê£áuO¾Ömm´‘ï” =×yt) ²‚€fu]׈ÌN8Á»ý$z=UݤºE©Š%È•h'škÑŽ;îhwÞy§I<¤Ô¤ÔÊÁO/íW%=Ü^z&Ð}‚„±ï¨.mÙ²e vèHL«—Ê¢:YušDʺ—×}¼ê0¥„V:6¹éI`y¯}«þV½>nÜ8/¾-±“(3$ –;’îÇÕªãT½¦k³ÄQj€–+<$6Ò|¹ª—ðX³fMÁ8Jݦû1½¨ÛÂí|†ò™@—RU¯@|øá‡É¼Ogý¾íð6ÆÒà†/Ÿl›¤ÄFº—¢n+8ßC©" qœÏõ<©öa=Óª­õŽ;îð.³ê«Ò3ŸÚõŒ˜H²ÚV5€EŽÛP»£yêyWÏ£j§ÕKÀ#]íÚ‚ )Âë T¶M†o;¼¾*søòÉÖoÚ´Ê|@Wu¾‡ò€´z)t]O¤þ̇òZ²Bp¤ô?RöBÓu÷›o¾iz•%”Ö ®´ÖÍf $ŠÒÍã[l˜å;(Ô¡!¼„Ðé½öÚË$² ð›ŸDGð¨c"4Ô©@@ [ è÷©ÿ ý¯‡¿”öC„Ñ* =¤©sQÂ];öØc_LÍ“H)Êi¡å×ÿ£w-Zd—^z©w0Hnê4L׈pušÊyA˜=öXTŽŽU® ê4•“®rnÐéDHJ]¦Š¹OŸ>¦Q7aª´k×®¡ÅŒ9­k”:bO>ùä #”DXá¹Á¯¿þz+Í6Xî ºöé<ÈQB¢£'žx—á™gž±6mÚÄ<9JH$7 u.‡^?ÃWÔõñ°ÃónHrf9ÖD‹ÝwßÝÞ}÷]ÿ{Pç¬Ä&DdÔm‘¹0Ù@@©’t½×(YŒ‡¾Ëj]õ‚Ä%Ñ„å]Õ[j<“ðE.Gçwž¯sâ= kTÇi£Ê0žÐ5^½t0vìXÓý¿ê_=GHôubI$¤zU÷¥…:¼â#‰ŠäD¨zZ/…îAäHîæ¤cQ]ªz\÷ñ„Ž[b&=È]içwö«©|ºOѾN:é$_†: ª\‚f¹©ê7¡´¨…Ôm…þ  ü€ò“@:ë7Ú$óó7C© Øô¬¨gÐ%K–xˆÚ65`E¡6\õãh0ÇÈ‘#½ûÑ Aƒ|›´2uÄ µ³^|ñÅ~Њڨ5ð³U«Vþ%qí”ÅéQ¿çÁ'@€@®È Á‘:»CGÙ 1üá;pœ.è¦1<ÔA!÷ ¥]S§ƒÄ å*”8Iæ¡ÞY¤‘D"ÔMIë…«¯ÙËB ä¦#AÈ‚ ¢îF.Er±‘{^I"‘žþouNAú½ï½÷Þ> Êá‡î¯!êè”ó€F‡Hˆ:Z@²+•KŽ ô`(w2¹&(¨Ä,ê OMõãüBûSç¡þïåZ°~/mu¹òÈGédtÑ5C¸ê|–@KÌêÈLæxÕY9yòdßA*W6í+ 6Ö»DO‘Ü"³ÜÄû€ð<%ÞÒùQêªÒBVéêˆ{u*«£5RHœ&‘ÑÔ©S= =ìÇ›žF¿"6ê¶Ø|ø™" §;?ÿüs±C›‰œtT¿èû—^zÉ_wåð–ÉPê/Õµ´ªPݬ¢jLUJáX¡²È™NnFŸêÞYâüdB×ýÐk¿êz œgÏžíÝ}Úµkçï)’Ù¶F¹ê5sæLïò§ç5H‡‹þµm‰Œ;uêäë¶… sbˆ´o¹öi„«„Ké¾'4$Ä—C=Ô§$U(a’fÅZB+¹.IE˜Q·ñ+€ |$Îú6É|üÅP&ä¥Ó FµwÊY½´ÁŒÉ–pùòåþùIíÌÚ—Ú†{õêUb0žëä®/¡‘öo¹åŸ•CëI„¤¶ëðPú4 Õ`õýöÛÏ?Ç©ý•ˆN€ú-:¾ äйpÙrŒ‘DQºéUê·X¡Žw‰BCÖ˜áÛ Oý–h®^uÖ„F,÷Ð嘆@yPÇŸœ$6’O.7J¥(«X9(Õ‰þ_”öLÎr ЃÝi§æE-êØS'¤:6%šQ'›B=¹!ÈYGiEäœ& \‰s$ŠQ§Ÿ–Qz‰­Hð¢:¹È­§,¶¨~£a´í3før†  Â‹úQ.B_}õ•·ñ•ÈJ£a¦M›æÅGɈ;’0KiÕAùâ‹/úk¥~QÊ291„76Ö —{Ð9çœãÓØ©!@ßñˆÛQÇ©PZOâªðPK"&§„W:§ñŠÂ·ÅçÈÂë"-EÝ™s!]¯”LõO2!'#ÕYjd•ÓŸê)Õ]_~ù¥麨ë·Ü{$ä‘8E×b9öe*äH${y Iå6(ѽì”êSY¥ùŠrp’sÄF ª9Y±Q¤}¨Î¶}ûö¾9\ÈiÒæÒœIÜIlX_ïQCt¬xùå—½(ZÏo¿ýv ±Q`Ý<ІîÅS'IÀ­zT¿996!6 ²ÏYú†ºí?>LA€@nHç³m’¹ù›à¨!O”ÂLƒG4Xä£>²¶mÛú6äÐÌáå•‹½Ò¡É^íº¥eÊÐuT¢¡í¶ÛÎjÕ³·Ú]õl«-TÏ}r“5k–oÏ8Ò*õ¶ž‡¡> ²•ØHÏÂZ±Q€Nôwê·èlø€ ²ÂáHæ‘n*²  œPÂC#ËcÝŒ–Wj"¹Ix PçÃüùó-4B¸óI¢‚£ßÿ=°;ÿžH§±ù4 H"¢ž={úÎÅÒv% Z¥ÓÞÕ)y€sÓ‰rRG`çÎý§ÜŒô *—$9 Ey¢:=8Jø$QR¦èAµ¬¡Î_ {t¼ “lHx%燀°'Ùí¤k=u~*-Zø5,Þýi}ý&TFu„TQJx¦ÎW]k%6"RO€º-õLÙbaP=%ÑÍk¯½æ¨ÓF5zê°eEGõ†®…r5’Sœí¢ÝÏÉ‚]£0>úh_§žrÊ)ÞMGóÂÓ{ÅÚg*¾“X‚(Õô˜:n9שÁXu²Ä²ré „F}^rÉ%Þ¦^‚`¹ö©¡8ŸD¥ªÓ$ºz衇L¢ÞHIx+^ªïJûÈPK]«e%:8p ç`Ë»yËp<·…á3 ät>»…?ÏÓ&™k¿Ž¹K@nî*çy FíSŽÉÉ^NB(©AˆJQ¦A.Ü£¨rÔU[¯úY4ÈDNñ€ºÏ>ûøvØÀ Õ ôÐ3»Ú—õœ¦mkc"!—Y –Ñóº‘tL:^=Ÿ)»…æ)äú«Á³D|¨ßâãÄR€ l%‚#lÎ…ˆt㣛àxCB‰€àHëèæ6•‚#¥¦ hT¡Ë0 ò$0aÂïb¤\âÄrIÐÿIèÿJiëm¿ýö>ý–Üz”o[£ÿå´+Í œ–$:Òƒ§:G•RLŸ—„Jršˆ7Þ}÷]߬^=x¦¢Uiæ²1T¶ðÆÉDŽS#}4ºHŽWê4•S•ÜœN8á߀ QFr©"ÒC€º-=\Ùjá8H.}jìÔÈF¹øÕ¯_߬|þùç}ý#Jy¦†OÕ š}©ÁTu–ÜÞ´î˜1c¼(ŠJ9©†Í>}úx«v9öÉQG#5Ë#”ÒKu¨Ò¼©84ä&ôÔSOùc‘0J΄իW÷Ç§ë½Ø©X×}Õ·ù” ó"·Ã@Ê´Ð2Jt¥n ¼P­4±Q`Ý{î¹ÇÂÏ€Kdà;Þ‹P·ñK€ |$Îú-ü™>QÁm’ùø‹£L…H@ô\ª¶T=ã¥;äH¤Á3ß~û­訽8p­“˜HmÉrÒsrHè£TÓêWQ{¤\Úõ,­ã•Û‘w%öÑs²úb4TÏšÚ†DJjû•“þùçŸq@H¼åÕ€U ÑÀZ dÕ¾Ô 8rp—Ë?À9]#UýnÔo¡T™† ¤‡@VŽÒS´Ôo5àºز:É#Ý ¾ßj«­ŠÍRJ©Ð¿ùQJDB7æH#üxßñLÐCŸ %úQ§[ÕªUÓzêÐÔ¦RŒ¨/±Ž>õ£4ê8 =Äê¡Q#nÔ±K@$G¥c=Ö—Q£sÔyLÄ& Ç«ÇÜsWš˜Ûn»Í4òH¼•NˆH𺂺-}¬Ùr~ŸÜ„Ôð©FY‰U%ŽÜsÏ=ƒ• F®5jDÕKi?cEi®FÑÖ•È\ÂZ‰{ä†'q„,²¤uж~YæË™HÂ9 Êu)<$à2dˆ¯?þxŸºô“O>ñuªF*uh>‡ê15r«.Sý‰Œt¯ û#ݯHŒoÈ)I÷J?'-¢$ê¶’L˜@¹O õm’¹ÿû H–€„2r{×3\jå8.Á̇~W{j¢ûýí·ß|šp=¿j¢ž#åö«çáðPÚíÏ>ûÌ?OéÙ[‚"¹ «½Wƒ;Bû[š4iâ·ÈyWÛ•¯ž ¢g3­ŸªvZµmßpà ֵkW“­Ê¡¶Íð•áeâsIÔo%™0€ K%p¶ÂG^Ë®3‘ÐèõÐÏßþY9ã ¥S ()}[<©ÞâÝ>ËA ,ô *·uÈJD’îÎÏÐcMÄIëIø¢—þŸ4Z&ô¥R¥DÑ·Š#¹ˆÉ¸C‡&Çuî¼óΡ‡Ãtº^É‘C×.¥Òo¦[·n~ôR2ײeËÌ¥2'ú2w.ÌV¯6kÔ(ÊÎ |6u[ÿ(~R”Kר¯¾úÊ gäУ´XáQ³fM/*‘°D¡ûµeîµtéÒb¯ï¿ÿÞ7®C÷ïgƒ(²u—=¼Õ+ç¡t}•XißZµjÓ.^û— “‘•&T©Ô$Þ$PŠ·¬¹²œÒÛ)Ý«ž•v®yóæþÐåÞ'—W«d¬öeåØ(ú¯€º-:¾ Ü%Îú6ÉÜý]päH–€LjðƒžUôœªö7=c¨½Sn½rîÑódYBiÎäÂÚ¾:hZÎ@r†oÖ¬YÔÝh`u¿~ýü3óÔ©S}»a,z¹ ë9õŠ+®°¡C‡Ú×_í i_éˆ-Z˜œî‰ä P¿%ÏŽ5!@Ù@ÁQgAF 4 {$,¨ \m“áŽFáid©ü€ ±nú×®]WgŒÄIå+& -Î;ï<ûè£ü9äBè]¯}÷Ý7x¸ÁèW#d4ÒG9ÄwÝu×à÷êHVgñ¼yó|>oÙùñØqÇ}§¸ìˆÕ9ÿÄOÄt’еeõûKtä E\箹t>æ:ßc­Q¸ßQ·î¹§äÉPã¨ìÙu¨TjŒÈU/žèG ©±SãÙN¬eTwIØ£4•e©cT²ÜŽd7ŸÊpHuãðáÃKº«î”ØFõ¤®÷…}ûöõç@.GJ †{5ìë|ÜtÓM…„¢ÜÊJÝVn¨Ù ”#tÖo´I–ã‰dWÈ0ÐöMJç ¤çF „д¾×` ÍKæùMFz&Õ³ëBB& K8àÿ®Ür¼Õ ”xBëëY<Þ“‘GDö ~ËþsÄB€b¨ëËL'G 9sæØÓO?í;2d›©NaÆù´“'O¶%K–˜RZ”WÈ}#4BošCçGšÖÈîÐÏCÈ;XFJùO(]Gh0â9”Ó™$ NN9×rÈ!Þ(“ÇRÖ}kôÌý÷ßï_ùÓ¶m[ït¤íêz%k^]—ää Ž^"qr¼}³ÒiS2¡ŒEXä~r¶å–æÄaæÒø™Kã“ÌÖ cê¶Â8Ï”²ìÖ­[ç\UÈn^÷¦ñŠÊ¾÷Ͱÿþûû”[JQ)q”R¬µoßÞÛÎ+íZÿþýM©D/ºè"?jUnH‰„Fª*Eªˆ÷Ûo¿RW•ØJ£c Ml$0mÚ´ñ~Òê¹Fä€(·ÄX)ZK…Ê1 P·ÅÄ×€ £ÒU¿Ñ&™£? Ð=+j@ˆž•ú[εz¶•ØH¡öO=ïªÏåŒ3Î(6ÈÙ/å`^xá…Îa¼‘ÉÑuñâŦA¨S¦Lñ®÷+]ÜŠäÆ+y¥"‹Wle—ÌÎ#Ôoyt2)  ¬ýüóÏÞöRùù«Þûî»Ï7пôÒK¾³_¹xuëcÝŒÈ"S7±éŽ@JŒÀ~4¢;í-¶Ø"¯:Õ$&’U®F_(¿¸:lÕy(‘ŒRÇ)8‘‰Œ:9;¢²48,ZdV¯žÙõ×C¯^æFg™=öXrÇTkQ·ÂY¦Œe% û½SO=Õ>þøcozâ‰'–u“i__×TÕQ²W}¥Æd‰€GŒaJwûí·{!ÿÍ7ßlrå“(IbÿÒBvørüÛ`ƒ ì–[n)mq¾wär$gTýn42W)f7Ùdؤ‘u[á²i@ÈtÖo´Ifì´²c”  lnݺµý\~ùå6aŸBM©ÔÂc¯½öòâ! „4ˆ%V,r qz–T6õ•Hp¤gN¥×3§`¨ •€@,Ôo±èð @ » dàhüøñ>ï=÷Üã•ïñàûóÏ?ýëÃ?Ü;‹,\¸0žÕ’ZFé•6l\WG²J³Þ£›úH±Ã;ø›óÀwÚ¾F?G‹5kÖø Y•¢K—.IÞ!1¯¼òŠvØa^8"„Í7ßñ®zxÖÿ¸ åèéA=ÇÀ6#p~Üè,³Úµ‹¾wæî÷gN¬yyæšOHÝÆ/± HìþüóÏûQ˜ÃçRÒ¬é¾Q£J•¾÷»ï¾ó ÀjÖýæI.¥ên9ïÈQTâ˜ðxã7¼(tûí··™3gúûît¦‡ ß._¥a–Hë…^ŽÎå2eû±óÜ–ígˆãƒ d¤³~£M2™3Â:È Ì­Œ«W¯ö—‡ RªÛêµ×^kzö“ù7ß|± z†lÙ²¥½úê«&Áˆ¹(˃\Dlq#Ì„€#@ýÆÏ€ »²Jp$7ŸóÏ?ßBÅ3‰ ýûï¿m̘1>—¯l?Ó²¾Úå/ëÆ AƒLi6ÂC6¥ÝºuóÂ-î2q@IDAT„ÀwÊ5,±B´è%;ޏîºëL)ÂSÇiÛiÿé§Ÿ—VdÍ# ,u:ê7§E¹g%áé!S–o½õ–í±ÇÉl&ëשçltÔù*÷ýOËM)cˆÌ¨^ý¿cpNÐ.½¹Æ³wÞùo>Sÿ nûSˆD@õÚ 7Üà¯õ>úhÎ K•þMî:uêÔ±úõëû‘§[ºÜ“ÉÖ^#^[´haC‡5¥þ}øá‡míÚµÞn—]vñ΢º?êw5@ñÐ=‘IÇçRã[‹¥ÊB€º­,ôX€²•@ºë7Ú$³õÌs\…B@Žºûì³wDME™×¯_oú¿–HÏ~~ø¡uîÜ9®M«SÏ„ÚF=ìŸþ ®§~ ¨Ö³¡®KzNÔ€S‰š$C€ú-j¬@È%ý28.—Zâ ·x÷V‰ºègŸ}æGŒ‡Þ¸V:¦Æ;·ŠÚ¶Ùf›ù×ßÿ½-kN9EŠ‹.ºÈ”ú(1lØ0ŸÚ-tÛm´‘i4”ÿ¸ü=_}õ•)åDèñÉ>ôÅ_44:v¥Z 1P'nöõðžBNi3s9ƒvß}÷ÐÕž~ÇõÈKü¥Ž'¢pè7«ÎÔ›nº)ø›•SOóæÍ­]»vÁ×V[mÊwÞé…ƒú¿}ýõ×}‡eÌøå@`öls×fsæ®m±w¨Žwuº×¨Q#ö‚yøm>×mÓ§O÷i°$ $ ]>ø`«[·®O+¡N>‡RÇI¸¯tźßVŠKÝËêšØ³gO;÷ÜsIÝ›£?>VGÀ½÷Þ›£%Hî°ó¹n›7ožyæ™^˜Ö‚ ÛÔ~õÀ”ê<žÛ¥Œ|ôé¬ß2Ù&©ûÏ:¸™s!>úè#ŸêZ@%¾Ð çhYJ+½žëtï/w"µ‡È…~ôèÑI¥60`€O«¦ëÎ…^hË—/÷¬u ÖÌgŸ}Ö‹™J;&¾€—kÀ{¡¶_åký¦³/§1¹N80¾KAÈÒJH-'D"/ 4®œ Å’J^¡b#‰wäÔ£‡L°Ž²8q¢ç(§pè6ts¢;í´S´Õ“ž¯íwÜÑß´ë®KzE ¹¼è˜äŠRZ\sÍ5öË/¿Ø»ï¾\Tâ*½"EµjÕìî»ï.³Ø(Ò¶™—JW²õÖ[û&éÙCü[Ugª:+¾þúkÛm·Ýü­Rjþûï¿ïo†uC¬ îøã÷£ad™J1#·ýoèÿR"9åA`ÊsijÌ墼7U#`n´•™ÓÄÓ­E^ºpçR·î¹§ä‘ ,X°À;öIt#!x¾‹DAbc^=á„üý€œŒtO~úé§c‰ùgÂÜ,'@Ý–å'ˆÃƒ ¤¤³~£M2©SÂJ(A`þüù^8rä‘GZ—.]J|:cÚ´i^l¤ÁÊtpë­·úþ9ÑËe(^Gu9=óÌ3~@©ÖÝÐÙ~+3ƒþ¯%bJ&$|Òó°¶£ÁàKHtÔ¿çe©"@ý–*’l€ P~’»ËLññ9ÒæÌ™ܪ\‚ÆŽë]Rb‰´Â&›lâÅJo¡›iÝôBJ~¥†JWH %¥yëh=ÜÿÛ±næûõëg?þx\b#­&Á•¸h=MÇ $Ѓˆ\hˆÜ ñŽÒ•È%@)¹2Ëé”#Y£o¼Ñ4š¦cÇŽvÎ9çØSO=å´-Zä¯z÷îíÆ”ç»U«V^0%á”ìxµ‰$¬{ï½÷•rR¥K”ÓŽ»L¥¦Ó Zu×8syáÍu‚›áe®ÁÅœ(ÓÜoÔ\çx‘ Èé4£†ûù:÷9sNpQá G€ºŸÌ ØåôxÀøÑgªwÝuׂB£{ì›o¾Ù»:©ŽWJ0¹J€º-WÏÇ @±¤«~£M2u¾ƒ@|ä&¤šj³ïÚµ«¸¹bÅŠˆ+kõ¡‡jýõ—w%êÞ½»Mž<ÙŽ;î8ïJ¤vÛeË–E\70SÎõjoV_ÊÉ'ŸìÛyåV¦A4êIVl¤ík ³DOÚ‡\o5èZ®FwÜq‡wÄ ïHê·T‘d;€ ò!ñ”jI¸ðÛo¿ù+åØ˜1c’A.[yÀ½íµ×ÒžúA7ý_|ñ…Ív¹{”2MN0zéF¿,4b3nÜ8Ó¨„ï¾ûγjذ¡)eÕAäS^¥òçBJµTÒ,¹-¹I¤¶ùæ››,r«W¯n3f̈[ŒVr‹ÉÍ‘‘\–,Ybûí·Ÿ·!/Mà§=éV½ÊË­Whj?¥œÑÿoY~ïÉ•&·ÖúñGsVÃfëÖ™Lšk|ÐÃ{n•¡¼ŽÖiÛL/×–á~WæþoŠF!iデ"}©l5œ™ž5jTänäþ £F!§T ‡’Ou)ÕÂÏ.Ÿ£˜\#6u_'!ûðáÃý½e´å™\!P¨)ÕÂÏO>Õm¤T ?»|† @!§T ?×éªßÊ»M’”jág–ϹF@b VšjõÜu×]^œ#ŽÚ‚ï¹çžbnG±‘œ‰”mÿý÷Ym°r“—ÃÜvÕæºçž{úïÕ¦¬v¥ßÒû¤I“|JlíCÎC4¢~–T†ŽEgU¶m·Ý6•›f[! =¥Z ?™/õ› CJµð³Ëg@ PR-ïÏtæSªI¬ ·TòeIWѬY3®\€P*ˆ¦M›>¦å½‘ëÅÖKùS¤tîÜÙ¿R½m¶W¾”>ð¤“Nò#B4ÒE)ò4ÊE#W&L˜P¦Ñ&‰”D"¼N:ù*ºÑÕÿ‹R¨ÄZN© õºí¶Û¼#’„G²ü•ó‘¬z‰Ø\öC/6rZKŸâëCÌä¾C”$P£†9Q¥ÙYg™Ë_$:’pÈ ÐrÎxf.õ«ÉÜΙmÅ ¥\;í4s©-Í\šy׈sq¾t¨Ûø$J@N@ziôcݺu]=mËÿôÓOöñÇÛš5kœàsKÛj«­¬N:Åö§ûÅË}š|5ª[Ó—\rI1÷Ìb+ðÈIÔm9yÚ8h@(…@ºê7Ú$KÏ×! ¥Ý\ãÕ7ß|ãÝ£•‘AÏǻцJY}öÙgûvàçž{ÎFŒa«/Ab# 6Ö€ÐÐP¬ÜäwÙe?Fb$9!iP²œ‹¡å4ˆô²Ë.óm¼ú¿MG(-›^Ê“õ[yÒf_€ äTNnµÔ­¥ðТ¬!Ç$Ýhk€bæÌ™eÝ$ëC %®¼òJ?ê䪫®²¶mÛúmªƒS¢Ÿn¸Áô}ºCéÏô »é¦›Úûï¿oJaX–P 5½ò)œ©…³1.r’óžÓ嬓Й›GNéÒÔ˜½ø¢91a*¶œŸÛpm1.½_ñ²I8äÌãü«ø7¥’U‚#—±ÁQé¸Xq˜?¾õíÛ×äž§xðÁíŠ+®ˆ{ýT.(Q‘F*Ehà¥ã ÙÂK|¤×:g9§:qwÑHÐAÎ.­^½zá«ð€ @€ P‚€Ò‹]z饾?B4Ï?ÿübƒ;5˜X‚¡s\#—GrhSвœ…÷øñãMiÓ¢…ÄJÛl³sÌ1ÞIm¹§œrŠOÙ¦~ÝvÛÍjhÄ@€ È*Á‘:~Rѹ³É&›ø›ð9²¿p±råÊ  e—(N@¢¡C‡Z›6mŠ ‹”ªeÊ”)~„ˆF²„ZçßBÙ?Íš5Ë:vìèx5r¦¬b£²QömÁ rvÅ%ë÷ß͹7•œŸèœ‡Ò5Éœ›Y¥JˆBùI§ðå—æeÌýF‹¾ ¼‡.W–i7àËzô0×S–­°.  w;Õm×¹œ†¿» e÷¦´M?þxFGµk×Î ˆtŒ+VôémO=õT/Ž•¥¼Ü5-Z|W,ÁÑiÎíꫯ¶&MšŠÇ; @€ @ *‰†ô¼©”irzúé§½(Ò r;ÒrIxé¶´hÙ²¥Íž=Û¯£>€ @ÙB ã‚£%K–YH(”ªÐ >‚£TÑd;e%ðóÏ?û‡O¥hyòÉ'­råÿþõªV­ê6[·níÓ­É~7<ÍKY÷¯õõ¿&ÛÝÕ«WûÎà@ÎïTl;_¶ñõ׿œ¦ŠRx¹Ìw>홉\?tJÄFÎ!Ù¥¡3—fÈœrdj¿übö fgœùû|ûÃEéÎÄÚe´† ÓWR‰¾@ ì&OžìÒAö¶/œ-œ¬#u˜„³^x¡IL+G=‰lË+äl)‹z‰ n¼ñF¿oÕ­ñÜ_j*Uª”ס²@€ @ÈqJÝ-ס÷Þ{ϺtéâS‹«í·´c‘R©ýæëׯ_ÚâÁï7LÅHÈàÖ˜€ @€@jü§zHÍöÞÊf›m\gÅŠ¦õZµjç%;¡Ñë )@‚÷Lèåò8-]ºÔyä—JËåÒ äÔQ{òÉ'{a’܇”0U!—/‰–-[f£FòÓ©Úv>m§OŸ¢Tj¤ìµWêKæ1ÙÂ…æœ@ÌœÎ,b8÷eŸîËe¼s©ï".’—3]šy[¾Üì©§Ò+6ÊKx  0pà@/êQ ²k®¹Æ.sÿÄšVÈ)H‚£Ç{¬\Gªc§Nj\p?žD°p¯˜-–… @€ ûþúë/ï¤A4z}þùçþý×_õÏ•J‹¦¢‘b¡kà;âˆ#ìk7zñ¢‹.²[n¹%¡¶ÜM]ß^ @€r@ÅL ÜÉeæÌ™e>$R×Í~ R!` l‹w$J@ Ï?ÿ¼iôÊéÑlmÜFOr–:={ö´×^{Ín¾ùæDwuùµk×ú4júŸP>ñO<1ê²…ü…;M.º™DG±ÄFÎÙîº+9R®íÁ4ÐÉpD ‰‘”v]£õë£.–w_ˆÍÝw›û}æ]Ñ(òŽÀ«¯¾jC† ñ)Ê>ûì3»êª«‚b#v×]wõ/YÉË^¾î'žx¢Øï<ÚT«VÍwÎî¹çžvûí·ÛŽ;îhzx'þùç›>}º_O"£ºuëzñÒĉ}çðu²Î!"pí—æ.Ž]‘»PÄ…þ7³[7³_~1?>ÖR%¿Ói¬ì’X^xaÉïÂçHvÅf¤f'“ÚÏŸ~Z$ëÛ7µÛekÈgêÜùöÛo}ãk£F¢U)B+»‹žîëÒ3œšó¾ûî³}÷Ý׺wïžîݱ}@€ r"ðÒK/Ù=÷Ücx ÈYs“M6ñîÍmÚ´±nî}¹rs€J!°xñb;äCÜ`·s|›é[o½eãÆóî½j¿mÑ¢EйW)·õì;wî\ÿþ©k@j×®(}ôѦö[9®sÌ1¥ì•¯!@€ ÿ2.8ªX±¢zê©AÒi ‘/¿ürp^¼kÖ¬±Þ½{ÛÒ¥Kƒ«(e›!”7ÁƒÛ´iÓì’K.±DDo[o½µ53räH/Vêܹ³O‰¶`Á‚bEÐÿŠ:Y5âæ¨£Žr®9µLŽa\pÿÿ‘³—Fjä:b‰È&O6×!nvøáf]ºD^&t®–‘ûP¢Æi:ÎqÙ¶Ü2tk…=ýþû™-ëÖfgœaæ4yöÔS™=ö\  úD¢:ÄLª²HôzÄGØ„ ÒÚ ¤ºP ÆŠ»•—‘€ @È Ë–-sÏÞ=¬¶³ÃÕ ®vÚÉ®¹æûæ›oìã?öíÿý·O}”¦€@Ú<ìì­wÙe{ã7|ßRƒË¥¨´P[«Ú]åztì±Çz‘‘Ú[§L™BCiðø€ @ `8¿ÌGÏž=íùçŸ75&(äÔ"¡ÄC=äó´y䑦œÊÑBë©ñá¹çž3‰ŽBCâ‹ ± EÂt9xçw즛n²=öØÃ®½öÚ„÷X¡BïJ¤‡Ùøß·rŠ8Ч±Ñ(œ·ß~Û¹ò8[y#W$=,ï·ß~¶Ï>ûØÆoœð~ q‡Í¥à1;þøøJï²ã¹kS|ˆ/åKÿ# ‡(§Y07@Õ5g‹Î½Ó+8Q`æŽ=C „¦R»ÿþûã:d¥U“€\öôªËÒ?þ¸MvÊQ¥/ÕˆT€ @ 6ßÿݪV­{¡oׯ_ï1i “:ÚË#Ô.(çJµy(Eo¸³fk7zD¯Ž;úTkåqLìÈ=zŽ•û®œŒ»=õzè¡ dÛm·õ)Å¿øâ 7pKÒx'L @€ò™@VŽ$’E²BC³fÍrÑWÙ7Þhr}iРկ_ß;¹üøã^ ¤´óæÍó"¥ðÕ¾}{?ú |>Ÿ!N?ÿü³rÊ)~”ÝSÎ6Eb dC]êLÕ¨¾¾.ïÓ Aƒü¦*UªäÝŒÎ<óL;è ƒ¼À(–(/ÙýÂzJs¦”jÙ“&™½÷^fE9é`sÙeæhŠRš¥cûñnÓ V37ЀJ!H¥öÈ#”èð‰¶jÀ}O®HÉ Ž$H×½Ÿ„´ã†Æ/.¿¥\ëÕ«—”¸7t[LC€ |'ðÓO?ùQr…ÔÀ¿»îº+®"_|ñÅvçwz7ò믿ÞÎ;ï<“[y¬øî»ïœ“ìD“cs2mjÔ «sÏ=×:uêuWá÷‡Qä @  èZ'±‘²+è:V£F2qØyçË´>+C€ @  d…àH`wÜqG{à|ÃÅŠ+б^·n·.•}i¼¡¼Ê²<-­$Þí±â%ЫW/[²d‰1ù¤I„$'£M¥Ö(Àp)Ò]ùÍœæ*'Bî9a}ä ÷w˜K‹gæŒÞœcVB«¦ta¥?»ôR]«Ín5“P+ÙpøæÜ«í¬³Ì¶Ø"Ù­° P^I¥zLl°uëÖÍFŒaÓ§O·–-[†~]êôÕW_íÓfhAj?ᄬk×®¶×^{yñ‘Déºg|ôÑGËÜp\êÁ° @ÈQk×®µ;܃å-·ÜblË Y¢£]wÝÕ4ˆ)VüßÿýŸï¤—{³K^x¡=óÌ3ÞU(RÇû¢E‹ìæ›oöí!üñ‡Ýpà ÞíRëÇr¯Ô} Ü+o•%-9œ©/ ±b((eNxá…ü3¤Á€ @€@zÄ’”ž}FÝj«V­ìõ×_7¥AKö¡Bö¨·Ýv›OǦŽ.åI@³rcèÒ¥‹qÆ)ݵ~Ïr:’cD¡Š>ýÔÌ—™¹6NŸ +YÈÎE¾Ì±x±9W¶è›qlÖ¬™¹”xÑ—)í×&ì„“™waúê+s9ê‹ÒÉ%›R.PÖgŸ-šrÚ¬ ‰Ä@ ˆ@ •šF‚Æ›J-”Òª)mà•óå5.ߢ:§.¿ürŸöãöÛo·½÷ÞÛš4ibgŸ}¶wÇlÛ¶­­ºO¦!@€ÌþüóO¿¤PJÏ®ÁK£G¶ øÔhrš6mZTTóçÏ÷NHuëÖõiÍ>ÿüsç|‘}üñÇÞqY¢ ¥[SÌž=Û·h_÷Þ{¯í¶Ûnþn±{h–Så!C":“‡ï\‚¨“N:ÉÔþñôÓO'”ú-|[|†r“€ÚT•¶LâÃdcΜ9~P³¶sŸFÍ€ @€@Úd•àH¥Tù>}úØ$—GH9–ãÍ+/†ÒjŒ?ÞçpO16 (ÔÀ&kq=ÌŽ92ÊRÌŽ—€ ÍÞy§øÒï\y¥™„<â$Ì첋™D4ÉÆK/™ëô6—ÿ=òþúËœ³‡¹Æ\³Úµ#/Ï\9 iÐé»ïškägô,㌻\úJsNtfš.KˆÙæ››x`Y¶’úu]Û¶sP1ûá‡sR¿q¶%H¥&±\†=÷ÜÓvØaSŠQuzÅê\êׯŸm¿ýöÞþ^TsçÎõ[º×“{¥:²&‘J#ª,@€@¡‘Œt&Q‘î•tï4kÖ,ï>¹¹{“ë‡î©Ž?þxïÎFîDr—\½zµw(jРU«VÍ;}øá‡¶ÓN;yq¸,%k¹\'÷Ýw_ßž§et÷ÑGù{: žt€ Å 9FË%I÷žÚ&Q£F™œÕt;äC|;¢þr rêSKÒnàf›m–è&X€ @H€@å–-×EkÕªeJ•q¥S(]†ôRã„rÁk„•F¸KÜ¡÷zõêÑáT®gˆ…P'ªFáéaViÏx˜ ¥“Ø´2*öíköâ‹æRÒ™)ýV… EÛPªugxá„]fË—ÿ7?‘=¸Ë‡•iÎEÍÌ¢%ûígV¥Š¹Q—æFr–ÜÌ×_›}ñ…Ùùç›uèPòûDæ¨Ì®Íŧ4ëØ±léÌâÙïo¿™ëÜ7ga_|é¦M‹ÄOÅç&öI\ÜÀX/Zªœe5~N7h+WžêR üåR4%V6–†@¾øàƒ¼3Qw;ýôÓ“.ž\ŽäR4nÜ8;úè£cng„ Þ±H⦉':q¢S'þ/Z·nmz)M‡Fã«#L£ç @€ PèþþûoÓ}Ô#]¯ÔÆ/ã)§œâŸ5­6×xC×-]w®¸â ÛOw @€ VYÖÝ[²¬‰¥ ½4Jž€@6•ø'Ÿ|bƒ ò#ú²ñså˜\{€miÖ©“9ž‘EENhz…†Œ3¦O7w[rúÍ7ÍÒTzs©éJ~ï :ì0s£­äˆcΞ¾øšJû6c†™Zæp—?çàfN„i®Á¤Htå—¦%\û®åj¶vm‘TiÁ”~, ‹ç€²9šÚוþîøã»:±‘Sx(p>ø '0lذ2‘PC±Fµ+­Z,ÁÑÔ©Sý(ûM6ÙÄ‹$*ÜF#Ã|@€ ‰€Ä>ºÇ’‹‡ç© í ƒòéÍŽ;î¸B£P6rQ§üwÜáS¥ÉUHñŒË_.QÐÁ솮˜®âFßèþN"€ß܈•æÍ›¾*ñ.çrmûðÃ÷Ç¥u”‚^âñÐнŸ—$„" Â# Œr6zÑ@Ôõâ½÷Þ³C=Ô #W®\é]pK£ò®³—ÐR©¹ÕVK@€ @é'õ‚£ô#`(ï¿ÿÞ†î]4ІHž€kWpiwÌöÞ;ñôaÎ@ÃÆŒ1“ ¨M›èÇàÚTýö·Þ:ú2ñ~sâ‰f/¿löüóE®LáëÅè+_´ÔϘsÏ2gaon¤W‘sÒ9çXJ]xœ™‰y¤9§.s 4¥ ²ä„$qÒQG™}v©Eð (šÄYÙ–N-pôruÚpÃ…¼C ` ȱOVö”he!·"ŒõÕWƒØJ—f²v‰Í)ÅGGY¸¹)4J b @ð–.]j£Gö)kgh”‹‹f.ÿøµ×^kr–Œ%Úö ‡ü:t¨(3ËŽä\´×^{yw¡úõëûTjJ»+šÊ7΀@.FrOúñÇ}Z6 •ôRŠ6‰Î @ 0 (•ÚØ±c½ˆñ˜cŽñ”R®»ÉùH×kd%V­Zå]‘”þQÛ“0’€ @€ÒO +G²‚Ö(-´Òhw¥Îˆ–¢Jy絬,RÕ)¦‘SÊ“€èÔ1«‘3¡äåy ù²¯‡*»œ{nâ%’ Ç9Ç{g¤)SÔà}©iëraª^½(­šÒÀ¥3´µ%?ü°™ûɹѤæ®EB'×^ë\àʶw׿ï¬ë‹ÒµiÚ Š-5ä‚ä\ðMçKnQÎ?fÒÌõêeV©RÌEùÈ0*]íìàäN”Š8õÔS½kÑù.ÏdË–-MWzi¾^º×ûõ×_ˆóeßÑ•Š}² @€ Ítï#W"¥Ò»^ÿ: Y¥”­ãFi„¾+EÚón¤‹:Ñåú¡å”2M©Ç”mß}÷õ÷T‰–WmÏ:Z¥­íåÔ$V’c‘Ò²Éi<Õ¡2ɉ€  H¥&¡ã]wݘíß·Øb {ÿý÷íˆ#Žð¢ÊœÅ¸ÜÕ8;ñpAd_×0·xñb“Sï¶Ûn[l;|€ @€ÒG «Gj0yÈ)FŒáÒù¸žìÿ…HÑBî2j¬Ðkà 7ô,W¹¼Céh‰v Ì/\]#«ñÎ¥“Ô'DÒþùÇÜÿ¾™k_°NH|3®}ÔY¿›K×c®!ÂL¢£&‰o8ÆmTä$מeËÌ”uHîLɌݿR5¹õîmnDk‘ ‘DGîÒçFyKxµYÛé§›v¥ˆs[ã 9½þºY»væ,ñÍý½¢­H§Ö¥K´%˜¤“ÀÇìGkÄgi¡û*íÖ­[i‹Æõ½RzÈÙèIgÕ¦Wx¨±Xh‡)W%@€ò€Õ=ýôÓÞõqÉ’%^Ø“h1uw‚{àTZ2uÀo°Á‰n¢ÄòuëÖõΖÈ÷Í7ߨu×]gp@‰å˜@ z»F.¥RãlËkÕªUbzŽ|ÓÙ™{ì±¾ Ví°K6lØÐ$H’PRÏ®º¾ê¹³gÏž%¶Á @€ @ }²FpôË/¿Øe—]æ ’-®ò¿Oš4É>ýôS×ñ?ÌÚ¶m›ì¦Xq¸í¶Û¼8îÊ+¯Lj4a\;)…^yÅláB3§t ÉZÙxî¾»ÈõGú¯7Þ0çzV$>Rÿún»%·ÝXk©/^B×Þk.U¼s\KŸà(p®]ŹŽ9 9Çi/ø |—è»wž¹Fsî#fÛoŸØ´ž3B±=ö0gqmööÛÑ×'‰”h»ŽÎˆo .Ó§Owÿ§{¸ô‡gÛ=÷Üs7aúºS*Å™F¡§"Ô9öÅ_ø§ÿ8…©^š¦5Š_©4@€ O”®ì72F¯²‡uѤIïÒ-‡ŽÀKÎÇ l’‹Gà]Ór8’ÀH©†Ò‘zLŽáËeüŠ+®È§S@Y ,& Á(rT;ùä“ÝB7‚0Jl¼ñÆ^¬)÷¢¯}¶D›zÍ™3Ç&OžìŸ-7nl<ð@”-0€ @H¬©³I);4’*¡Q=zôðV«]°ÒHÒ‚Ú†^¯¿þz/~Û:Fî­ŸþÙ‰[îö¤Ç|A1JGa%’ШOŸ²m]ëK¸$ç¥øzôÑ¢wwYpf®"¥!7%¥“ØHâ›Æ)Ý_èÆ\"×à:§hÚµÛ‡ ¯b x<ØÜuÒl‡ŠœŠ\ÛLRѪ•9û}³ûî+r™êÚµäf\û¸9×Ò©•Ää€:ªã$ðÖHÐhñÔSO™Ü%•-•¡Ž4½@€ ÏäØ-ÝwÚ¹tï5Àåïê–$ÏÆP»mÙxf8&ä'¥‘ìïF®éñÎ;ï,µrtÓšðÐä¥K—zw$¥š$ @€ ò%P±|wyoãÇ6–¨Q£†Ï¯²HvªåN<ñDo÷¼Ï>ûfùwš¿é¦›¼%k±/øRè7·hÑ"ßжnݺ¨Kß~ûí¶zõjŸ;¼‚”DÒÜà$ŸšË9»QIo&¸â7šKdÎÞ¬eK³ùó‹RŽ¥Zl¤ÊA颋ŠD;rðI‘H°,ÉL(µÛùç¹M˜P| ß~[䯴×^Eb#µu¿ÿ¾Y²b£ÀÖFÏÔ®sñÅæRæþ÷.á“DeΟ€Ê™€î‰d/¯Q¡£.’1âñÇwÿÏ5íÈ#Œ±_A€  𕳱Õ`£yóæÅ,°„F·Þz«5mÚÔ=]l«V­²sÏ=×=o½ïÛ†šµb£˜ãK@i ÐÇÔ`ÎûÜèµXmÿ¥ízà 7´fÍšùgØÒ–å{@€ @ õ2.8’»‘nB£}ûööÚk¯ùÑ_»ï¾{ÌTU›m¶™ÉÅèᇶGyÄêÕ«ÜT`TYp(…Àï¿ÿîœa>´6ÚÈd}iäŒ6ñ믿úÑ7Ûm·¡XÊfùºì>ýú•²`œ_Kÿ%g£}÷5›;׬Ms ½q®œÄb.£žÍšU´Ÿ$VOù*N+`·Übæ2UzATè*º«þèÑE\N8Áœ“—YíÚ¡K$7­mHL$©R´ É퀵 ¤ ¼ë,Ø–-[æÒ'žg{ï½·=ôÐC~h¤ ~þùç6sæLo¥†[€ 2÷Þ{ÏÚ¶mkýÜÃê6ÛlãÒtïæÝ´•*6¿¹É!ù’K.1¥’UúâÅ‹í.—ÃZ䤠Å; ³çž{.®Tj°‚ @€²Ÿ@ÆGêØš/û‘ÿ…F‚ÝvÛmIlP#Ðÿ9K‰1Úõ¬+ï=xHl$ÑÑ Aƒ¬cÇŽN´ò¨9²Äªj4ÔhÅ+®¸Â¥‡ªTâû²ÌPÖ¥ÿ믲l%wÖu&QöØcænÍ5Ħî¸ÕO>vl‘Ë‘œŽ$´)”ë’œ†$þÙÿâ¥V6#÷·•+ÍäÈ”J×'¥³kÑÂ\c{‘«Tñ=ó ÈÝ )ä yõÕW{—£!C†D<¹)”ê–€ @…Làå—_¶C=Ôä9bÄëÑ£‡qv¹©wÙeÓ¤Þ½{$ÖV*µ9sæøùJÿC@€@qr‹?ßÙrËÕHîñ @€ Û2Þ¯_¡qá…ZYFÔשSǧ¸ lóÏ?ÿ´¯•¯‰€@Þzë-¿ÔAdO>ù¤¡(Gˆ>ú(¸öš5kløðáþ»“O>98?UNogrÌ©\ù¿-:#°¼ éµ”ŽËµÙ¦<”âKiÚ6Lù¦sbƒÎ¨+b¤Ë´DçòÎ;‹MîR gF@" û çŸÞwŠ5oÞÜwšµq¶o‘\Žä:ùÔSOy;úðTµ:|v @€2Bà17*æ8÷0¹é¦›ÚÛo¿m}ûöõ÷OË—/w.±oúTir6ºÿþû}–„Fs½®R!4ÊÈ)c§€@ޏÒ5z~ûí·vóÍ7Ûæ›ož#GÍaB€ @Ñd\p´D!±Ã;„|Jnò°Ãsn&ÿmáÂ…Émˆµ Ž€GjPlݺµwÊ’c–~K;wvŽ0ÎÆ…F6júòË/w¢ "UÐwߥðúþû²!sZ&—ʦ¤ÓO×®fgeiûÎ$ÌYº›ýO+U¶ÈÀÚÕ«›õïovÌ1Ø9»L99*é÷*w©‰‹6¯”v‡žò]±A@ ¯¿þº¯³N:é¤àÒ—£ÃòNš4É7üânDÅ @H@®Ûgœq†5nÜØÞÿ}kÙ²e‚Ž<ð@Ÿ*MíY_~ù%B£ & Ä&0}út»ûî»}ªÊž={Æ^˜o!@€ œ ðŸ*'C‡»téÒàž%ÞhÔ¨Qðs²rHÚrË-ƒ«/Z´(8Í¢X·nM:ÕöÝwß`š´Ý\ž/ ŒäÄ¥T4r76l˜ÿ}vÚiÁMIìãÚ#ÍõÕ–)\F7ûûïâ‚#¥¿úé'³4ÛqG3gVQ,$8’;PûöæÒûŠÈ[o5“»Ò;ï˜k€7›5Ëœ#XF…B à ȱHÑ­[· ³#¹=ñÄ~™îÝ»—e€ ¥M0`€í´ÓNöÁضÛnµø*TðËáh_@£®\àtí¼ï¾ûü{ðK& @€ œ%qÁQÀ!Fÿúë/'¦SS$‰V/X±bE`’wD% ÆÄõë×ûÑŠ¡ ~úéÖ»wo“K„RÌè÷t饗Z•*U‚‹µm[49yrpVRî|´k÷ßêU«š½ñ†Ù‹/šm³M‘ é¿o‹œc† 1SÚµW^ ý†id†À[˜Í™cvà æÒ C—.™9ö B& !íXg7¶÷Þ{[“&MŠ¡ËÑüa—# j_tê¹fÍš[–€ @ “ÔIýÃ?Øüùóí³Ï>³ÉîÁ{„ &Gâçž{.eíHê×½‘îÞ{ï=—š»@ssgòd³o@ o Œ9Ò¦M›f矾Où·¥`€ @(0Õ©S§r5 •5~ùå[°`Ap35kÖ N3h”NM!{ôð¸ãŽ;l=öð›jt µýuæGÎõÈœÉÜÈð5ûìÜÚM)ÆBÛƒPÊ1÷\n …F­Zf½z™se2{é¥Ðo²{ZÜ\û°wtÊî#åè’!РAÑZýú™}óÙ~û%³ÖÊBàå—_þöÎ^ÆêÿãŸd_"K¢’=‘%dß )kI”ŠB”,e'K"Ù"E"[E´*T¶dÉ-"ñתÅY²%úŸÏ™ß\3÷ÎÜ;sïìóù¾^sgžç9ÏYÞÏÜçÌsÎ÷|¾V™ }‰-±Ê'ìNž< …SKLJÛ" " " á"ÀPæ£G¶ŽÓW\q…uŠ._¾¼u¾ÍÄlfèóÖfeCýúõí ´Ô“ªœ ¿õÖ[rñJh)-4u®ˆ€¸8pਠwY¡ÆÅ/2Ø!>ÜM)S¦Œ[æÏŸ#F¸íówcÛ¶mn§pÎ|»íÕ†¸ ÃQ®\¹À0j‰aúÞyç4nÜýúõ·¶kLüq‡ÃÛ8äÈá<êû;C©1¤Z•*ç%ßÏòäq„a[¾`¶ÄNIþ䊴 7|80k–C½é–[BQªÊ’%ÃU²Êø&ÀßT—oTNÄy²a&çí·ßn'òv™ÎŒ}›·´žÎ×>Žé¼øâ‹˜7ožy¾=ƒ«®ºÊªç̙ӊ@R %³eË4iÒéÒyþ*T¨vìØ‘ääß~sì¢ÓŒ‰ºf†ÌWØo£Ÿœ©†Y­é÷©ö„æÍµk!¬Œ_TDÛÇ;œÌâTÈÙ(¢/•*'"¥¨öø±¹ÙRµ/þü[Ae€ªU«â•W^±amï¼óN­æ÷HJ;E@D@D@‚IàøñãØk$pù¼ýòË/cÍš5¶¸&vy=p×]w!}zÏÃWmÚ´A¥J•Œêog«|4gÎÜ}÷Ý~U—á ÙF•£Ü”–‰€ˆ€ŒÀªU«¬iÓ¦MqåÛe" " " " " 1EÀ³gE›˜x5ý¿ÿþ‹nݺáÍ7ßÄ… üªÉ#›Ò¡C·pjEŠAéÒ¥ýÊG‰ãÀg&–¿{žÂ©¥D£T)€a£:ur¤4 ,SeÎplµj¥êtÐáˆfuF„}ó `Æmaü´ð×_îUjÐf‚Û¡nä~D[" "  @î³gÏ¢mÛ¶ÉfG9ûþùÇþæj×®]²iuPD@D@D@àï lõêÕèÚµ+8ñ\®\9«2L墲eË‚a`7Ù_þ&Ùºu« Y¾t(òælä,—éé¤Ä|¨Ö8dÈü÷ßÎÃɾ3|Ú«¯¾jU=…¡Möd(%púôiLœ8þùgP[ÀgMÞó¹Øx2åáe" " " " " 1GÀó±7“F‹/Õ‰h°:t¨]ýÐÜxQÐ ¤X±b^kµsçN»yPnÛÕ躩Ï"à‘éÑRãpd]‚¯sç€,Y`E=‘âNãódÔ•€êÕSLê1A‰Ÿ–,\.¹Äc² îÈ!ƒËQ÷«éß¿¿ •Fg Ì&øÕW_mÕ‰¨&Ì×µ×^k‘®¸â ÷“}Ø¢j#”¨ž1räHl7ñÎçÎkC¯y;î]ºt±á}¦Nê-™ö‹€ˆ@Ì3f †ŽéÓ§µöö~œÚFòžþÄOàË/¿4ÊíãäÉ“n¯sfÀtôèÑöŸÚ2tžˆ€ˆ€ˆ€ˆ€ˆ@䈇£9rØA'ª¹: íÞ½ãÆ³¯|ùòƒN”·æª5Jnïß¿ûöíÉ'<æÊ¶ºuëz<¦"àJ€Gyò䱫*]÷ûó™c«Uª8BªQœËKd6¯YÒQé†`¾ß^“¤x E ÀŒ˜VছRL°f,O> ¾F) f•*ÌÀ-о}ê¨V9e$" qFàÀ`¿Ö¬Y3û›)¥æ3ôCÛ&7I˜R:." " "_8à kŽá 4È.c8´Z${9 }ÿý÷ã»ï¾CÞ3œkÉ’%Í"™À®’)X°  3¾?ü°u6ª\¹2æÏŸo¼ÑãÅ6l~üñG«òAg'™ˆ€Ä†œ0aòæÍ ޽ó¾Mµ·âÅ‹§ªù¼÷Oš4ÉŽÙç2‚Ù³g·c¬Ù²e³Œ>ЫW¯Tå­“D@D@D@D@D@"Ÿ@D8S¥J•ðÒK/«â-±ñaˆ/_+ú¹RC&) ó@¹2­žT:2Jîf5%P¾|J%_<þóÏÀï¿#!,ÚÅ#þ}bX5:-ZZ‡£ûîŒÐ5r8ÑñÉkÈD@D@Â@à­·ÞÂùóçmX_Š¿ì²ËÀ—LD@D@D@|%ÀñªX¼óÎ;Ö‘è™gžA:ul˜û±cÇÚ‰gþ¡ªÓòY›JóIçïê_+eÒQ9éõ×_·cLTTªV­šUa¢ú†ëóþW_}en2+uzôèáG J*" ÑM`Ô¨QvñîìÙ³íÂ.¦ÓÑòåËm¨KZ÷Ë/¿ _¿~V½hÇŽɪÊù“¯ÒŠ€ˆ€ˆ€ˆ€ˆ€DÀ)r¬fÍšVÆõÑGµƒD©©Y ¿iÚ´iv@)˜ƒX©©›Î‰L\ÉÐzõꥹ‚æ+lÍß°jÆçÉ„sê×O[ÌX*Œ˜u8J[N¾Ÿít°êÞøðCÀ‹ÉÙÈw|J)" 'À•ü\UJ…#™ˆ€ˆ€ˆ€šÀž={0cÆ ;A}×]waðàÁ6„Yƒ 0sæLê»&OžlÕŒxŒÛ[¶l±“Ò¡§yüñDZiÓ&-Z½{÷ÃÈR•‰Æçª ÑØŽPÕɨ?" "F{÷îCHRŽ÷ïxÀ:Ž=zÔŽ‹ò¾é«1”ZÇŽm5Þûù *ˆ?åpDü|8áÀãGß}÷ÝȘ1£OW%þüà EFÚ%Ž#>ªD1A€agh7ÓãÇO££P¹r0+#'V¯³jذÁ¿Œ˜ÇªU0ûþ—8u:óm„šÌjRàôéÄGƒ³=eŠ£Í]»'å*" "à;ŸdÞÆ­j_–,Y|?Q)E@D@D@DÀGOšxÚÿšXÚT,rCñPcÞ¼yÖ§»Y‘²yóf«hDg£r|è ±1”Ú_|a‹œÊšU2Ï?ÿ¼Ýß·oß°Ô+ÄTœˆ€$`(ɳgÏÚ…ºÎ-ŒL9ïçÎG^Í›>}:>ùätéÒÅ, Lã J_ Tˆ$1!ÕÓ¹âŠ+0räHŒ1W`8_üñ‡•ç.\¸0øb,h:¹Êc'ÎOÛ"àŽø}+S¦Œ·$^÷ÿö›#|Ú_9’ÐѧB®˜ôzJИçýÃÀ-\Üz+`ÄÅd" " a&@u#Ú½÷Þ暨xX$@ç!†Qãu ÆOdmÛ¶EãÆñâ‹/ÚÅ`µk×N”"´›Y³f'Å™øßT5jÚ´)2dÈ`ž_K`èС¡­ŒJ0øî»ïlÈI:ѱÈÕ¸ŽF·ß~»½O24%{3†R£Óf¡B…0nÜ8oÉ´_D@D@D@D@D ÝáˆòÙeË–µ+òæÍë7R:Ñ™ˆ¯›nºÉïóu‚$Gà/ã)´mÛ6´jÕ*¹d^ýú«ãÐ5×\LbPZ•£‹{b÷“YÈd«ºu‹Ý6ªe" "Mèp”'O4lØ0šª­ºŠ€ˆ€ˆ€D X#*L{³\¹raÈ!Þ‡e?CU­Z÷ß?Ö­[g2gΖº¨PªÓ1¤ä³Ï>ë±xÞ#׬YcÞŠÖ­[£S§NFÑ}¢ÇPi=¤Ú[Š«ÆjÕª®t›5k~uziÄcµ2‚ ¬]».\HU856‹ G´«¯v¼ó¯ñ‘‹jÛ½fðFY,åf´kìÙ³‚5å´J!" "\;wîÄöíÛMxλìÊýà–¦ÜE@D@D@âÀ²eËL(ðUhß¾=J—.uÍ¿Ú<¸³þ A[¯^½¨«¿*," ©%ðù矅ò…öY1¹½\4ÌP”t:š1cÊ—/õë×»KÕ8ª!Q5N ]ÜÐhCD@D@D@D@â’@ÐŽœTÿûï?ûÀ2fÌ+ÛJùíÉ“'c7½d"& §F»ùæ›SU§ïœ«Â‘¿£°9âï™ÁIÿè£0ñ×/_J(V f…«/)•FD@D ˜,X`³W8µ`RVÞ" " "Ÿ8¦3pà@PhøðáQ !yx½&-ðQÛrU\D ž PîÒK/ÅÈ‘#SÄP°`A,]ºÔŽÛïÛ·uêÔÁ AƒpîÜ9ìÝ»}úô±¡ÔÆs@S&" " " " "÷‚î&@9ÖL™2%½k×.¼øâ‹hÞ¼¹] 1vìX|õÕWà –LBE€G Àu×]—ª"G® Gþf´d °|93§¿gzOo’qß}À#xOãéž¶n2fÞ˜;×S*íˆDt8âà0„e" " " "H ÛÊ1›îÝ»…_‰ß@¢¼D@D@N`¹täøçƒ>ˆR¥Jù”ÿ%F¾ý±Ç³÷ýJ•*Ù0lUªT1c÷ÙPj¯¼ò .»ì2ŸòR"Ø&t‡#Æ…Þ¼ys‚s‘§¸Î\1sæLÜsÏ=¨]»6† †Ï>ûÌ®œˆmüj]8 üùçŸ6ôLjÕXw†TËžȕ˽%}B8}Ú}â-³8FÕÕªÁ¬4J|4õÛÌ뇊]° _-wnà?NGÆË &¿ÿîëÙJ'" ".”½ßcb\¶nÝÚ¨Îýç]¸š©rE@D@D@Â@àŸþÁ!CÌso.«r†*¨HTàÂ^ªQŽãíþhnذÁž»cÇ;^ß©S'rÍß¼”^D@D@D@D@D 6 „dF*K–,öAdܸqظq#fÍše‹òåË—„ê¡C‡Œ“ÄtìØÕ«WGß¾}úËr㸑‚çF’œ´C’'°fÍ«¨•‡#*yZÜižÁa€Zg¢äk¼ù&пJ©ü?nÄÃpì°v­çÒÊ„l‡ ÉŽ£Gab²'=¿[7ࡇ3î,ˆT Ñy[&" " " $²}Úª@IDAT0mÚ4üøãÖÙèòË/dÖÊKD@D ˆÞyçpq ÕŠRN2}úôxê©§°~ýzôèÑ&Lb•µˆ€ˆ€ˆ€ˆ€ˆ@´Hê gÈ5kÖ´/>¬|ýõ×X±b…}QéÈÕNœ8E‹ÙòQý¨aÆ ƒHÎ@ÆŸr-TŸã†å„iiq8¢ÂÕ‰[Ž=fêÖM|ôâ¶ùw@³f·ù‰!ÕÊ”œuñ7ï¦MNE³g3ff“5†]3>ƒ¸ñFGè5óUzÀàªÕ·Þz EŠCÙÊD@D@D@D ­Î©Ü¥K—âõ×_·c2W]u• §–Ö|u¾ˆ€ˆ@hð9qøðá6ôÙÀÓ\(Cªñ%W!w8r-œñ o4^ |õë×»wïNp>Úµk—kRœ={+W®´¯KM¼(>àÐù¨AƒÈŸ?¿[Zmˆ€/>ù仺§X±b¾$O’æøq˜¸åžŽ*Wz÷NÞÙ(I†Þqíµ_i±‰aþç€^½`þßù™ñf*Î,Ž’‰€ˆ€D†¡ýÕHîb9š£*ˆ€ˆ€ˆ€„‘ÀæÍ›­“Ñ›FŠ—aÈ9nS׬¢yúé§Aõj™ˆ€ˆ@tøøãñí·ßÚ1÷ºõÖ[Q¸pag2½‹€WK–,Úø]K­1œíškï®MhtŒïº'²?ÿñðÀÀ!@½zëJ!±™3aB":8œºv î¸ãb:}†¢¥Ý{ï½á«„JˆZTÁ ’ÑÈ‘#±gÏÛŽ2F.··YEsŸ‘ÎMmž¨¢Š‹€ˆ@ ;v,2f̈ž={Æ@kÔH%.R+Æ­ÆÃá7ÞWîÓ±ˆ!Õ’-±}óÍ7xî¹çШQ#4iÒÏ?ÿ¼]Á‘8¶E€è°6`ÀdÍšƒ J5†S£]}µãÝ߿ǎÁ8Öù{VpÒ3lÚªUU›•}Ôq|ʘÿA uk…SKÌIÛ" "ìÓÞ~ûm”.]eË– GT¦ˆ€ˆ€ˆ@غu« Ã]íÛ·Ç_ýeÔm{ÙE_;vì°ÏÍr6Šâ‹«ª‹€Ä--[¶`Íš5hÛ¶- ,·Ôpàˆ(…#oÍÍ›7/Ú´ic_ÿý7V¯^mÕÖ®]‹S§N¹öý÷߃¯©S§Ú*†]K‹S‰[æÚˆ sæÌ±iCŒœOJõ¤Òrç†yp‡QØJ]ï½çP zÿ} E‹ÔåáËYÿþ ³R zr÷îIÏ0‹Y1k–Cµ¨qã¤Ç¹Ç,Š2ƒÎ©w®òœ«öŠ€ˆ€¤•Ã:t=zôHkV:_D@D@D ŽZeäYŽ=Ꚙ8Q¯¾úªŽÜ¨Ä÷ÆéÓ§1lØ0\qÅèÛ·oš`Üt0o^ÊYœ< dË–4ùêZ«R%é±@î1ÿ&F)Ì¡¦tË-€QÆw33þ`3¬Zz/wóo‡M›ÜNÓ†ˆ€ˆ@p†S»çž{" 6ª‚ˆ€ˆ€ˆ@$ذažyæëlܸ7Þx£Q±}… 6 `~ÃÞ½{^¿þú«]YØÝÄÛΜ9sä7L5ð™Ç>çÌ™ƒ*f °N:>Ÿ§„" " " " ñG€¡Ö6lˆöíÛ£W¯^©ÀÅO÷Þ{¯u6š2eНÈ;wB~ßÿ}Âg}ˆM1ãp”øò”-[|Éc.1™øÝæJÏãÇcæÌ™È!CH@Ôª¼ö̪"˜25€F€[o*V„‰§’jØBèpôñÇÀøñ0²Ê@ݺ¡+[%‰€ˆ€žÀüùóM?r Ú´iøÌ•£ˆ€ˆ€ˆ@Ô`ˆ´Ç{ 'Nœ°c £FBÆŒmý©‚(%Ĩ¹”ª¨ˆ€¤‰ÝOŸ>¾}û¦)," " " "ûºvíŠo¾ùÆŽ#dÏž©ëxʨ]¬[·?þ8˜§,þĬÃQü]Jµ89?þø#^~ùeT5±ÃZµj•\RŸÑiÇ(Á™‡xï§tê˜{´}1-?‡ËŒ˜ ­f팷*°mðÊ+ÀwÀ @‡«V*WD@D 5N¹¼Å‹£–ñl¥$©LD@D@D þPéðÑG ,ˆwß} 4ˆ?j±ˆ€ˆN::+V -[¶8"Àß‚o¾ù&J•*…êÕ«§Øò·ÞzËŽ!4mÚ»ví²c 9sæô{qó*懋ž*Uªd£ ¥X°Ä$¨t8bj:ìØ±Ã®ìÏgbS)R ˆÉ‹¤F¥À AƒðÏ?ÿ˜Ðf&¶YÌŒëZµ ”¾rT02*rct,š8ÆKÕ¡´´y3Œ´>ð SEUDD@DÀ‹-²Ê”*•‰€ˆ€ˆ€ÄsçÎåÜ[ñù矛E$w`ƌȓ'OüP‹E@D@,Ù³gãðáàÂ{ºtéDED@D@D@D ìß¿ c6uêTû[0kÖ¬X½z5nºé&¯­gÞnݺþ³fÍ7saó<:ÝvÛm^Ïu=Àl íNu$:;9•–]Óès|›Ã¿¼ÛŒÄ ¿Ô ouûí·§Hœÿ Ó§OÇÎ;­ lݺôÔlÖ¬j×®¿þêÈ&E%~FÃñb+¨Â$ˆ. ,@úôé¦Ú]­WmE@D@D@h6gìØ±"" "ÇΟ? &ØI£|0ŽI¨é" " " "(ÊÂßóæÍ³‚%J”@=¬ÊU‹6n܈¢E‹z„Ag£C‡Y'!:ñµbÅ ;‡N‹åË—£fÍšÏuîüï¿ÿ¬ƒž8WA•MYü¹Ã?¦M›f¿è\‘G»ñÆSt8¢‡Ñøöft`âkéÒ¥6mîܹ½%Õþ8"ÀX®ì=ztÀZ}å•0ßc‰¸€eÒŒÌâW4o”)”+Ò¢U˜ˆ€ˆ@ Ði›¿uêׯoÒ˜Nˆ2üÀÅ5jXéò(«¾ª+" "` ©ÉhÇG–,Yœ»²ˆTjß¾½`(´Ñ»wo+ºÁ¹ð *ØðºzÙ°aC%ä… ZG#†à¥ˆ‹Ó®¿þz›ç-·Ü:,Q†B/Þl̘1Ö1éa£rѦMoÉ´?N„L_•+-† f¥µÖ®] §³‘/œ‹_Üäœ\óY·nºvíêW®çësìX¹r¥½)>ôÐC(]ºtÀ–7¯#,Y´:]q°i0sfÀ(#àƒÄú¢¢*©àêÁvíÚY™ó7ÞxÃ*†¨h#" "¡Æ†Ïxì±Ç"´†ª–ˆ€ˆ€ˆ€ˆ@ PÔ…‹è0Äëô¹hÑ¢EBHÝæFmâÅ_Äÿýßÿá‰æ8sæLB±GŽÁ£> ¶¼ôÒK û*W®Œ>øÀF™jÔ¨öìÙã<äöÎù‰!C†à†nÀ¤I“ÜŽi#> „LáhðàÁxï½÷ü¦L /®Òðf\µqúôé$‡¿úê+Lœ8ýúõKr,”;¸ºäرc¶È àJJã¤Áxc`~yòäÑÀ¢çÎkSQn^&" "êÛÃ1µ¹¬Y³ÆžZ·nÝÔf¡óD@D@Pß–ˆ6#’À… pÿý÷[ésŽ“\{íµYOUJD r²Ó˜dä\Wך°?`D†Æàx±LD@â€ú·x¸Êj£ˆ€'o¿ý6òUŒ·Þz —^z©§$Ö©è—_~±b.÷ÝwxÕríÀàÜyþüù=ž{óÍ7Û¼Z­dÉ’¸ì²ËìoL:)ñ·&_trʘ1£UJ’º¦GŒq·3$Gï¿ÿ¾Wg£ 2 H‘"Á;ãO'>X¨P!<ùä“V±æ #ÕrâÄ û妤øo¿ý–|þüùVé({öì ûBùá‡~°†NïA>øuïÞÝï*P±iΜ9Ö“7Ú%—\bèԪU wß}7*V¬èw¾±~U´-ZdžUò§2Ö¨}" "hêÛMÔÿüèp”3gNS11ý§§3D@D )õmI™hOd`˜ðO>ùÄr5£LD@’#ˆþMc’Éÿ±ãÇÛ‰#Nq•¹LD@â€ú·x¸Êj£ˆ€'»wïÆöíÛÁ0fÞœœç=ûì³Ø»w/è+Ñ«W/Ô¯_óæÍ³ªGtBJΨŒôÎ;ï`Á‚8|øp‹ªIôÉ ÂìÙ³Y(¹úèXäºÃàMŸ>= ‰jÕªá‘G±Î ô‚ód\AOeW£<׬Y³ìD›sŽ9ФIÔ¨Q÷Üs~þùg{èÔ©SVú+¥g>|g¨“'žxÂMªÌßüýõWôïß_|ñE’SÉ•q©Åc*Ž;d!sà@ì_ýe²ÄDD@D íÔ·¥aZs ª#¥Ro½õÖ™Ô´æ©óE@D ž ¨o‹ç«]m§d9ÃÔ—-[\l%䤵Әdrt#çØ AƒðÇ`ÆŒà¢\™ˆ€Ä:õo±~…Õ>äP©ˆÖºuëä’Ùct ¢˜É¾}ûlسW^y¹råÂË/¿œâ¹LÀ0m|%6Š}pŽ‚ÊG2pHçü¬÷U«VǮֳgO¼úꫨ^½º•Ür=æú™ç&¶¾}ûº9¹¿üòË“Ä ¤ç^8lüøñ §ajíСCxðÁ=:yÊ“¬Zµje¥Õ=Ç}Î/eßmfŒ :Wå'" ‘M@}[ø¯Ï¦M›ÀÁ…S ÿµP D@bƒ€ú¶Ø¸Ž±ÞŠ£G¢mÛ¶ ’å™3gŽõ&«}" i$–þMc’i„¢Ó¹eêÔ©¨S§:tè¢RUŒˆ€„—€ú·ðòWé" þ x}(š2tèP»˜˜¢"©1†Qc8µzõêùt:_.\ˆ2eÊ€"-Ï?ÿ< (àÓ¹Þ1r•œ¼Ñ‰ßýAW8J¬nÄðVT6òŨPãjåË—•‘’³R¥JÙI8†¡íÙ³Ç:í°ÜP˦CUjíìÙ³öAÑ5<y3ªY³&*T¨8nÞ¼ÙJ¡Q¾ŒFe§‚^Šô\Œgû÷ß­ºY/^<à((¢U°`À³U†" "±Ô·EÆ¥qþ¾‘ÃQd\ÕBD º ¨o‹îëOµïÔ©~ùå«`qýõ×ÇSÓÕVTHKÿ¦1ÉTÃ)÷ìܹ3Ò§OoW©Çû8p.Šõoa€®"E@RMàÏ?ÿĸqã0eÊœ~¦¤ë×_:[¶l6ìWºt) +ñ\Ê÷ºæùb\ÙáœczÖ!TG¼ 0À—jzMCEÆAt½ ±bÅŠÎ]ö½V­ZhÓ¦ Ú·o§sc«SÙÇ95·ÌblãÓO?µ1%—2Ðf|½ð÷ßÀ5×:gå'" ‘I@}[ä\þ¾aøÔÄ¿ "§†ª‰ˆ€DõmÑqTK wïÞx÷Ýwí³ÇŽ…DD@’%ÖþMc’É☃'NĶmÛ0dÈÈ5b.‹*""Dêß‚WY‹€”ÀáÇA5¶É“'›¹ä¿Q®\9<õÔShÞ¼¹Y²d øâ¼?_T!¢H»ví’­‡3ªÏÝwßl:O¯¼òʸ÷ðÄEûG eÏŸ4”µwï^·³«T©‚«¯¾ÚmŸ·¯¾ú*É!:ùbE‹uKFç¥P%ÐèltäÈ[\¾|ùü.–aR«B5ÊëÄ"yÒCÒÕ88ïæ¼ñ#œšÓÎǯr¼_ µ_D Ê ¨o‹œ ÈÕÆ ©FµÃK/½4r*¦šˆ€ˆ@”Pße,Ž«;hÐ L˜0µkׯ¬Y³â˜„š."à ´öo“ô…rðÓpõ:•í½î9iU¢D <ùä“Þ’i¿ˆ€Ä õo1s)ÕˆY¼OqܾOŸ>(R¤FÂ… [Š¢Üyçv<Ÿ‘Œ8çÿÍ7ßXcªQˆ¾§OŸN–ç½Níæ›oN6Š@8ÕáÈ©ºãlXbG ç~Oï_|ñ…Ûn:ÖðŸÔ+V¬˜[²}ûö¹mkcΜ9 Âñ 98è¯}ðÁ`kÃÊøá‡Èš5k7±¾Íi¿ÿþ»ócÐÞ¿ûî;{#qÀ•&¼ÁøkŸ}ö™Û)õë×wÛö¶AµWûè£\7ãê3ÃÍ:t¼‘äp ªÊSD  ¨o‹¬«â [·nÝȪ˜j#" QD@}[]¬8®ê˜1c0lØ0~éÒ¥6œjãPÓE@| ˆþMc’>€r>óQÙ–6bÄ»2ÞÕñˆªöü± ¹qË-·¹6Ê^D@ÂO@ý[ø¯j ±N€¿;æs37n܈–-["OžPæ¬W¯^8wîœÍ¾E‹hÒ¤IªŠÚ²eKÂy¼ù:©èªpÄ âÙáÈN-X7^)%|EõAD † ¨o‹¼‹ËÁgªT®\9ò*§‰€ˆ@PßIUÄóÏ?oåÔ©p±|ùräÌ™STD@D Yêß4&™,æüôÓOm9œÈš7o8¾MÇ#Ž©sõ{Ïž=íäWÏËD@D Ö ¨‹õ+¬ö‰@x Ðw iÓ¦6„9k9'NœðZ©~ø­[·â-Z´7Ýt“"ùþûï­“Ñ3Ï<ƒªU«zU4ò–1+&—Ñ&Ožì1ç½éà¤pjñhgªÃQ† Üš˜9sf·moT7ºpá‚Ûa† óÇþþûï„ä oLãMäÇ´E0ôWž¤Æ˜ÇáÇN-W®œ½$ìHæÇeÉ’%!o|ñhüÞ,\¸¥K—Æõ×_R8 Ve*"aÔ·EÖ¡Só† ìMâßW‘USÕFD@"—€ú¶È½6ª™ƒ%ÔŸxâ û<»bÅ äÎ[hD@D Eèß4&™"æ$Xµj•u2â¸fÛ¶mñí·ßbîܹ¸òÊ+í$'ÆÆoWч¤B*DD@ÂH@ý[á«hˆqï¾û.8¯ÎðåNµ":w.\£F‚«Á‘#GžÓéøsÇw`çÎX½zµ#)V¬XšiuèÐÁ–=nܸ$NO §–f¼Ê ‚êpÄLWûã?\7½~v]QÃDt*Z´¨×ôž¸Æ¸fÜë`Ù²eËàTÔI—.ÆŽ‹ìÙ³§ª8Æ_tµ’%Kºn&û™“Œ÷è4NL?~ܹ7ïë֭ÂN ©pD¶ û±ÅÍ5SCE@"€ú¶È»&[·nÅ©S§|V>Œ¼¨F" "^êÛÂË_¥§LàÅ_Äc=Ž|òÉ'È—/_Ê')…ˆ@ÜTÿ¦1Éð•:dWÇ»®\çXó}÷Ýg'µèxôôÓOãÁ eU2õoA¬ìE N 0tZ»víæß{ï=ÐùˆágÍš…\¹rYµ!ú70ÄU%‹/n•ˆ‰iíÚµVôŸù{_PsŽŸO%™4i’Û)N„`Eõq+L"JAu8ru€aý~ÿýwŸª¹~ýz·t•*UòK‚ìW#AsæÌ™„<‚åp´oß> <8¡œ.]º€uM­¹ª1ÞØü±ÄRë‰óó5/ª?ÞzpÒ‹ÓÕ“Ó×<•.7^*!+™ˆ@Œà=Ïy¯ãûÿý#-K]3Ô·¥Ž[°Ïb85š¯¡Vƒ]å/"þù矄>ŽÏGüË}›~ÇDÿ7šÿ§?ü0zôè%J€êT²‰€x&àÚ·1ÔJ¼öm¤Èþ-ñb¸Æ$ù<Ηë3:ûºx0®’gÛ]Žœív:q"J&"{\û6.6‹—ûž·+‹ýÛÊß,®×š¿cd" ¡#Àgmª½þúëhÖ¬™uô¾óÎ;mÒ§O‡z»wïÆ+¯¼‚9rØPç}úô±aÎçÏŸM›6ÙðkÁª1¡èÜD'':F9óÞ §vË-·8wEÅ;…Qœ¿éÕ·EÅ%KS%Ó§éìNN¬p´k×®΀õÞÛ±c‡[ºZµj¹m§´A•WK\×c©ýÌ}¼Ñ8U„x“êÖ­[j³³ç¹Þ@¸Ã߇ûÄ¡ã8XÀ¸“þ=9Ö®J•*öT†ÂûòË/ýÍ&äéyMèzÝu×á†nZùT8òó+´º(c´`Œ]Ê`:ŒÕ›Ø‰Óy<–ßc¹oc¨Q^kg߯ëȾŽ1’£ÁèpÄþصþÑPoÕQD ¼8HÁ'°8@oË}ô0´ŠkßÀÕvyóæ·ËµíådÊ]wÝ…7â¶Ûn1ýˆÚÆ«â"JÓ¦MÃÒØ·eË–-•9E÷iîß"eL’c™'OžtëÛ–,Yâ·ò}4^ÝO?ýÔV;Ú&“¢‘µê,‘Fà7Þ°‘3X/ömTºˆW‹Õþ×ó‹/¾À† "¦T¬Xц͌×k­v‹@¨p^`Ĉxíµ×ì³ÃŒ3бcGÅÓñ¨S§Nhß¾½MOÇ@. ÅË:t¨U`š0a††SÛ¶m›­G“}ôÑG8p ­2û¶K.¹$šª¯ºúI ¨ßÎÄ G‹/Æ#<’¬ÌÒ¥Kí*×vøãpÄ/íÂ… ]Ow 5æv /¿ü2Þ„–%K?;­ÿì‰îýìNœ>ñê$_›[¦LT®\óæÍóõ”ˆHÇk°e¬Ë`Ù_Á |Há(X|•¯„ƒå/s×itX¤{·'Vû7àB‘bÅŠÙpM>QBT £ÑÈ‘#­cß¿ÿþ‹† ‚‹|ù­EÇOoNI©®'¶mÛÖŽ <ÿüóèÙ³g‚ƒb4†SkÑ¢ø¢q!xçÎ}  $ÑJ ¨£Y|@lܸqN˜;Ö«$$Õ‚æÌ™“ž®6±«üQ(úàƒàwœ+Ê•+ç–gZ7¨ˆ0yòä„l äWNLô!ñý¿+OSª,ž,áÔ8þkÆÍÀp<‘U[E@â€ú¶È½Êl¢ê–©Eî5RÍD@"“€ú¶È¼.ª0kÖ,Û¯=z ,ÀèÑ£ål¤/†ˆ€Ï‚Ñ¿iLÒgüAIÈ” á!u£ àU¦" QB@ý[”\(US"œ­T©RÖç N: ôòåË}r6 gó.½ôR 6ÌFW?~¼u8ŠÆpjád¨²ÃC ¨GlRß¾}ÝVãsµãRúÝÕèCY²½{÷ºîFÓ¦Mݶ“ÛàêÿÄÞßTTºüòË“;ͯc¬'C©ÑyŠÖ A´nÝÚ¯<¼%N,'–1cFoI=îgSÙŠáÔß²|ùòAk^Μ0«Äaé‚V„2Pßrä~È•Û49ù…M‰E@✀ú¶8ÿD`ó9òþûï[iv®”,P € ©Ð¦M›¬­ª$"©‚Õ¿iL2¼Wœãå´›o¾9¼Qé" "&êßÂ^ÅŠ@ `¨rú88–¾nÝ:|òÉ'¨]»vÔ´”>ŒÂ1qâDNíŽ;î@Z#,EMãUѨ%Ôj¤B‰wÆ;œ2eJ¤-[¶XGþÓóõË/¿Øš³gÏ&¤á:Üðæ’§:_®‹«êׯ7ß|\©(«Ó˜¤?W!ðiáQåpx¶ÊQD :¨‹Žë¤ZŠ@¤8räˆõ`˜åo¿ýÖVÏÛ'©U«V¤U×§ú0Ô:ëߪU+›>éùÔP%Š)Aw8"-*-[¶ÌÆèsÒ£cÐöíÛí˹/ñ;…¼ À}öÙgàêÆýc¨WG#g>TWòW%Èy®§w®F\²dIÂ!ÊžçÎ;a;­§ÜÕüu8:sæŒëé­›[ƸñÎ;ïØZéÆGUˆhêÛ"úòØ0´\‰qÓM7!K–,‘]YÕND@"„€ú¶¹qZ */÷èÑÃŽS K—. ªÑy˜/®V”‰€ˆ€¿‚Ù¿iLÒß«Øôã.Q¢¸xV&" ñF@ý[¼]qµWÒN€ t§OŸŽwß}ãà\}Ïž=­?B™2eÒ^@˜shÙ²%*V¬ˆßÿt ’‰@¤‰Ã'ÈøOOùóçûĤsçÎèÝ»·×´K—.µ± ½%hlb^ÝvÛmÞ§jÿرcÎcخӧOcÅŠ ûøñÇÝvqÛ5ýe—]†ªU«&¤IëÃ=•ž\-ÎP®ùFÚg†·›;wŠ-ioÀ‘V?ÕGD@"™€ú¶H¾:° ÇŽS8µÈ¾Lªˆ@„Pßa$NªC%ä~ýúÙ1.|zâ‰'ФIT©R9räˆ j¦ˆ@0 ³Ó˜d0¯\òySùÿ§Ÿ~B—.]’O¨£" "£Ô¿Åè…U³D HèhäüÝİiô' ƒNæÌ™ƒTbè³e¸ãåË—ƒá&N-ôüU¢ÿBâpÄjñ`üç2d:ä±¶üÇéÓ§zè!Ç}ÙÉ0lô%©_i\„¶mÛ†nݺùuþG}¾œV¶lY8•y¸/ñÃý¾}ûœI}zÿã?Ò‘#šâÁ/þ¾gn¼ùƒÞÜ»ï†ùî«W½( " !! ¾-$˜S]WkÐøûI&" "àõm¾qRªÀà÷müøñxöÙgqêÔ)4kÖ &L@ñâÅS€rÿfÿ¦1Éð}ͨnDS8µð]•,"^êßÂË_¥‹@4 } ®ºê*©dÉ’ÑT}¿êÊPÞ¢@ù•‘‹@„ÌáÈÙ><1Ú¯¿þŠï¾û;wîeJ•*ªQZ®s8[Égýþýû[%£œ9sÚw* gÈ!œÕRÙ" 1N ˜ý›Æ$Ã÷å¡ÃǶOЇ¯F*YD@BK@ý[hy«4ˆ‡ƤI“ð /€NG ,°!Ä’Ò`ä$:QÀ¤C‡‘Ð ÕADàÂæp”Ö+ððïPÚ’%Kü*îûï¿G“&MÎyðÁѽ{÷„íÄÒ¥K‡¦M›bÖ¬YöÐ… °~ýzŸœ²V'Šñ/«bfÏžm­4(eŽè,‡#3ï‹+€Œ_9m‹€ˆ@ôPß¹×nÇŽ8räˆÂ©Eî%RÍD@"”€ú¶½01R­ýû÷£M›6Ö)˜ ŸÞzë-(P FZ§fˆ€D2`öo“ Ï•ßcVOþfVOrU¿LD@â•€ú·x½òjw< à†^zé%0<Úu×]‡jÕªaÙ²e˜r8 {%S ®D‰ Ƕoߎ7Þx#a;ñz€>úè£8uêT¡֭['|Žå;þ‚Ÿ~ú-[ö0”Û• G2È" ¾ÍÿëqæÌLœ8ÑNbÞrË-þg 3D@D@‚J@}[PñFdæ”{ç„0WTr`”ýtúôQ+‘ŒU)ðPßzþt\¥º”™„ž½JˆêßâçZ«¥‘G`ß¾}èÙ³§u(â3uéÒ¥±páBlÛ¶Í*ówP¶lÙðÚk¯áŸþÁ<†0Olƒ¶ÇGø¶E@"€@ØŽþ3ñ©~5Þ!|°âd…‰UEÅóçÏG–ðV¡sçÎn LÜ믿žä&KÐvíÚáË/¿LH_¼xq»/aGŒ~0¡:ñÎ;WšÖ5^±wãê« •ÃQŒ^p5KD ê ¨oóïN:| 8p 2gÎìßÉJ-" "êÛB‚9ì…p‘Ͻ÷ÞkWc-Z›7o¶£a¯˜* " A  ¾-P“É’ãâåË—Gîܹ“I¥C" " i% þ-­u¾øG€ãÚT4â3ô /¼€²eËâÃ?ÄÖ­[qÇwà†”q±&¼LÿþýíqΉ»Ú×_ùóç£qãÆrÒv£Ï"AB¾q©‡Ž-[¶àôéÓIPdÈ\É߯_?ãDò?/’$©b{GóæÍ­DûâÅ‹mC/\¸€‘#GbΜ9(W®œxäMyïÞ½n ¸º’lÉ0ÖíƒNç´¬(Sæ/>Ü6×8Áš¸çÁiù€0ñÔªUƒ“¿rX' ¾Í÷+LÕÂ1cÆØßA‰D|ÏE)E@D@‚M@}[° ‡?Ž[´mÛßÿ=îºë.Ìž=9räÅTõmAë!Ûo¿ý´+ù=Ö.Pÿ@˜ÊJ’!°ÿ~;®Íðgô¨\¹2žzê)4iÒ$™³‡˜îã?Æ3Ï›bJ "!u8zóÍ7A¹3×ð_‰›}îÜ9,[¶Ì*uìØ]ºtA–,Y'‹ùm:;vÌ:9Kg-¾<Mž<ÙÞ¼=µ}ÿ=Ó4éE 42¡i×\£š•°°k×Ât0×CGƒªŒD@â’€ú6ß.û”)SpàÀ¼ôÒKÈ”)“o')•ˆ€ˆ@X¨o ö ÊE?ãÆÃ!Cp饗ڙݻwz¹*@D@"€ú¶Ð\…U«VÙ‚®S&" "|êß‚ÏX%Ä7ŠdT¬X‡F¥J•0lØ04kÖÌg(Ó˜;w®=—¡Õ¨lD…aú p›‚2È$²jô<:th²ÎF®ˆ«‘áD äº;n>3f%=@9¨ÉÏɽ<r­V­ZÉ%‹©c3fÌ0rÃGÍ*Ó– í¢ V0ŽÆŽ…‰§ôîP”>ˆ€ˆ€¤‚€ú¶”¡1lËXÓñ*Tt¼–‰€ˆ€D6õm‘}}RS»ßÿ 6WQ–,YŸþ¹}.OM^:GD@¢‘€ú¶Ð\5†S£Z}:uBS J8' þ-οj~P ü÷ßhß¾½u6zõÕWmh4œœ•+]º4F…={ö OŸ>6ÌZÆŒñôÓO;“è]D  „Dáh×®]xíµ×RÕü>úõêÕC‹-Ru~8O*^¼8vïÞê*¤3^.ݺuC‡@Û·oã^R!ª`Á‚¸ÆHú0ü\™2eR]F4ž¸iÓ&Pv¸GnÊT8Z¹8~¸ì²À´lçNö0ŽM0¡Û“§rh& ¾-¸WïÅ_ÄŸþ‰W^y|˜’‰€ˆ€Ÿ€ú¶à3Ž–Þÿ}têÔÉ’víÚãÇKÅåh¹^ª§ˆ@òÒÒ¿iL2y¶i=J%½5kÖØü Õ™Vš:_"—Àúõ0!y„Y,¹õŒ¶š©‹¶+¦úÆçž{«W¯Æc=†víÚ¥©É?þ8/^lEI˜· .œ¦}:òæÍ‹>øÍ›7Oþ$8  ¾-8yÛ¶m8räˆ]Hœ”«ˆ@¸ = ´iñL"˜3¸çžp×Jå; ¨s’л¤Å2Œë®»Î†&OkŽ—\r‰¹gα!Ô¨œôä“O¦5K/"dAw8Ú¸q#¾øâ ·f0WîgÊ”)aÿå—_n(±6Û¸}3Æ8zOc'Ož´ÞŒ<òHBz}ˆ/ß6˜0á?üóϵ¨R¥ è´æj]º|Êø00oP·.LyÊUùˆ€ˆ€ˆ€g“&M²ƒÎ\˜Õ2àX»v­Yuþ ~úé'Jòï ~Á*AD@D n ,]ºÔ¶ýæ›oŽ[j¸Ä:îÝÎFÂDÿÚ¶~þ&lo¬·\íˆ'gÏžÅ}÷݇óçÏçʹS.T¨V­Zeæƒÿ±‹‚≩Ú*ÑH ]°+8¤=_zé%7g£Äux衇pÛm·¹íþž'²¸"ð×_À´i@Íš@‰01:ab›Ÿ2Ìr<üðÃAgaæ}qîЯ_ЋR" " qNà¨Yú6aÂÓß•À<ç4Ô|>3gΠW¯^àdï0yòd,[¶LÎFÁG¯D@D ® pí¬Y³pÅW ^½zqÍB@øí7`äH˜ßsÈ-0y˜(½VÕȬ­Ç¨QÀæÍ0‹§:qÁô¿ÿ¦å"" á&@õ!* 6ÌF* d}*V¬ˆjÕª2Kå%"$Aw8úñÇݪ~ÑÌž=»Û>Ot:r59¹ÒˆíÏß}>f  ¨•QÆý÷ÄڣãQ}óýùÚÈWÔDµ±ÎNeÊ·ßÛ¼Õ:ð ³ކŠK/½4üR D@D@D † |þùç¸ñÆ1qâDT¯^Ýû hÔÈ¡v´sgdÔUµ´X½zµ]@Ëgêô¨”‰€Ä-ôÁnyb‡£5jøTdùòå‘+W.;ùƘυ .]Ð}¤|ªŸ‡ÀÁƒŽÞ gFUa>(´l ãdP-kË–ÍèØ±£ONki©áË/t:êÛfÐ9-9é\HžÀ‘#GÀpj¥J•2ÛfM&" " "T5i–À=Ú¨ç¦Ç¸qã¬Ê‘Æ‚‚[™Š€ˆ€x 0ÍȹÓÁµsçÎŽj—Ä7#`T'M›#l‘`[¶?ü0ºÈŸ?áŠj×Ö¬è|”5ëÅcüdüÕmݦLräðž³ñaç8æÏ®¼òb:ž³d ðå—@¹r÷듈€„‹À‰'°nÝ:¬_¿ÞÜ·Úùx.ˆåë/ãÊ÷+ͬE‹¸óÎ;ÝŒŽ;†öíÛ#[¶lxýõ×µ€6\QåŠ@„ºÃѾ}ûÜšš/_>·íä6 ‰ÞÐhŒyøðaøs~ryëXä`ø2*ýú+LåP5r­%;>ZÓ¦M]w»}¦ƒP–,ŽðknüØ0!AÍÄ/À•š÷õœ’Š€ˆ€¤ŠÀøñã“ëq£¬7MŽÕ©"¨“D@D@D eo¾ù&ú÷ï_~ù•*UÂk¯½†Ò¥K§|¢Rˆ€ˆ€ˆ@€ìß¿|ðQ9i„"EŠ(We#±A€Etæ©PF‰Ò½M{öœ;øûoàòËÝQ$ú®»`&ÍU«8wà~<[f4š42gv¼’Ë“GW_ ¡!i*ãïŽ*U’î×.ÀÙ°aƒ¹W®²¯-Æ›ó_—tˆÎ™3§¡ È5×\ƒ]»v™Ð£ìëjss»ãŽ;¬óÑÌ™3±wï^¼òÊ+Æñ³X(ª¯2ÂDÀ¸gÀtbñb•hǼ³*<–)“sKïñL èGŒKí´ 2XoGçvJï ÄwŒ¯õ?£Â‘,v <þ¸ãÁà‰'’:±Õ›¸´ÁXÕªUí»§?~èXéðôÓžŽú¶Ïôøã˜Õ®0ÒÆ¾£T" " "çÏŸÇÔ©Sí„gëÖ­S“…ÎH†ÀæÍ›ñ„yÈܸq£™ ºÏ?ÿ¼ ŸF…#™ˆ€ˆ€„’'ç8±×¥K—P«²D * p!ðsÏyŽ8ÀqúÄÎFΆÝ~;À¹…?öÍáèÐ!`ð`À¬wÇSO9sñüÎy†BãºøE‹Rž/¨SàK&" ‘DàÉ'Ÿ´áÏètD£CQãIY¿~}Ô«WÏ:]vÙeIÃr^žs³ï¿ÿ>.\h”Þ&ÛóhÞ¼¹ uÙ‰e1B€þg®C%tñ(ZÔ1gÎ&R4¤Aƒ‹íуª!DåK‘K<~ éŽü±Lr‹óWT§5N²Æ¦ss8úxj ˆ .lÌ“€3·ÆC×ËAwó|æ£g)™ˆ€ˆ@ª l۶ͪ9vëÖ-É]ª3Õ‰" " " F9÷W 03WóM<‹KÍÒ÷îÝ»› ¥§;wnÑà„U®2’êÍš5 yù*P"™ÇãßyF5ÃÍߺ–,阥Ñ/öÆŽÉQ³þ+Y3ƒ@g&#â9sŸ]O`˜5#š‰±cSÊJÎ…Ï®ù곈€’@Ïž=ñ /¹ ¸÷Þ{qË-·˜°•}‹føñ5jØ×Xs³Û±c‡u>¢òÑDÞÄdQMàäI€NC[·?ÿì˜gŸæ4#z…GqôqFÜʆ1usêÍ|ò P¶,Œ `¦8Ì÷Ê™BïñD ¤GñVmõ@©RÉÓ믇 Nz.ãRíêOZ¤.É;tp¬80‚óqIêõ#ùñ‡~r±˜½ž¬" " "àµk×ÚÔµk×öã,%HŽÀìÙ³­ŠÑéÓ§íªÍçÌRùë®».¹StLD@D@‚Jàcã Á°žÃ† ³Ž°A-L™‹@”èÓÇ¡4fLê+NÇ †dcø³”~öýôLØ  }{ïå1LL‹À7߬W»vIÓrõŒÀŠ0áÎqøctúôSÇx P!ÎTZx&ðÑGᥗ^U‹ªW¯î#qáÍss¼ùæ›MH¬Å~E!ò”ñ 7ܾd¾`ð¦ÄN8Tô˘Ñ÷<‚‘’õjÛÖ¡ÞGu¢›nrw(r–9dˆó“û;‘¦Ms„¥Ð•ñkƒ‰dotK”pO«­Ø' ?³Ø¿ÆQÓÂZµ€E3vñÛo@–,îIwlsö¾û€5k¡ÚúõsOçÜš>&DŒ3!°l™s¯ïï½{ÄY„Qñý¥ˆoo¿ý6î0R3~ø!j™IÕ^fBôÔ©SI p>õÑGµÎF ›ÆçâlÙ²%I§Á%°jP¾¼£Ïq–dĘm”§ŸNœpî ý{ÿþg£p„E[¹2u‘Œ/¶o‡ e~Ï¡H‡*Y|ÃQ|]ï¨m-éт1!ûûïŽöQ GˆZt8ºñƪ^ލmƒ*." " ‘B€áj:ÙÛÌèC©5lØ0Rª¦zˆ€ˆ€Ä1†ù¤A“&MÌ"G­rŒã¯BÔ79Î*h '$t¨ ñ¯4'<3g| «–=»{qœ¦2Ò3Ï8B¼û.Lè!‡C‘{Ê‹[TwàëþýŽ4øö©Q#`Ü8ÇjßÎP*x&0wî\-_¾|V­¨Zµj6¬YyãÑâTÑ':uîÜÙ¨ÏLí·ÞjÓfÍš5žÑ…¥ít€5?ý¬ƒë¾}«À;TÙc¿Ge!ªè}ù¥#ÕõBa3gãÇ5k„üM{‰üzÑ—}è?À(p¥=Oå]äp]×+¦jûÔSޏ¾4Š G™Í;Î@oìTVjÝ:¹*/H™:„:uꤜX)D@D@D@R$ð¼Y®ÎÅ*O˜™¾ÊD@D@D ¼bfrΟ?.]ºDBuT‡#`¾Zf¢`˜°`Úý÷;&HæÊ+aBêÀ„èî¾ÛFåçŸý/}òd‡ª‚‰ ä5ò¯¹R­¨n]‹“'}=ëb::R±]ƒS§ 8ÂÂЩ(%Ë• ð%§|N®`AOG´OD@.ào‰ö&$—é\Ô´iSp!ëĉñ‡™è¬W¯ºuë†ãÆ3´cÇŽ&Üã ÜnbM~`âÝvª@IDAT=fI,çv1[}JD€}êÖ­ŽÐ`‰ù½IÇ®1fèL†+sZÕªÀwß³f9ŽTªäP=¢ãìe—9B›1Zž‰p[½FýÊáì´p!)SàŠxüqGˆÐ#€£G—¯rŠ|r8Šük“5<}à ‡7Ò”ŒÞ¸›7oFåÊ•‘!C†”’û|ü¯¿`¼{’§Í›û|šŠ€ˆ€ˆ@@8WžÔ®]; ù)ˆg{öì1DƒQÂÄâÁ‡M™ˆ€ˆ€DM¼¤™fùµ×^‹Ûn»-j¤*ÄÏ?w8ÚB¡Àªÿ¬XT©3É ó{Ë1€!TÞ{ÏŒÎG Sæ«9Œ .œ:u O嘹uP‚“»þZ¡BÀúõŽI؇r´‹ÎU27_|Ñ:--ZÔ:+VÌV)]ºtxÜxx|óÍ7vAë”)SŒcAÌž=Ûª*.4Þ$rˆVûâ àž{ó¨Û¹ )ƒØ¤5,X÷î€YoŒ ’VßDÙµeüßÿ 8”è¬Ãpžt4¢ÓÑîÝ@ß¾À÷ß'=?µ{Èò®»!EM”=±¬€¿nìÛÙÇЬ•Y„ÃQ„_ X­oŒ…L¹¶”ì;ãêyÔ¸BúNeÊ8dOSÊ—o%K:àß%>@©•%À~®CG8³”r¦$>͇#æûû”òeZÆbfœe™ˆ€ˆ€„šŽ®¿þzäÍ›7ÔE«<ˆ)“M<ö«ÝÍB9òÆÔ¥UcD@D ê L›6Í*¶wà@¨L‚@€¡¼Z´p„g¡B°Œ*T~HlN•3Ï *50¢'5“3N*¯^íPL¢zE Œ“Å&À(xÎш~؉\Oíð|Fèöš`x5™ˆ€8 P¹·ÿþ(_¾<Ö¬YcœKw©ã¢Ö®]»â°ñÒ¡³QÆ(“hÛ·¸å¥¦‹jyÜæ°y0Ž(^ñ¿©ç¢tþY¾xúi aC }ú„C Š …+(¤áɨðGÇ!*ÊØ~*$‘‰/ÆÐ TH*\ØòÔU¡‰¡âZµrôÓt¾mÔÈ—S—†¿KÆs(Ò‘J\þ]‚ßàsçÎø…>ô[" Î¥K—1£#æ§Ñ›SY¨,dÔ„}2§ÃQ5.×ðÁLSŸoê¼ñÉD@D@D ÔöîÝkVÿý‚Gy$ÔE«<#À•?Î0:EXåTˆ?þø#ÊË’fw\1UQD@â‡û¨åfæê.»âÊ+¯ŒŸ†«¥A'@ÇN$>÷ŒCpÇÀË/;Ô‡ zñ xôQàï¿ê f(Yã$îÖ­5¤@Ï{[\Lg¬mÛ€‡vŸDN¶¢!<8o`¢&¡xñì!,UE‰€„Š#¹|oB¿4kÖ̧"¹¨fèС¨\¹²ý-qùå—ût^v Qft@¥ó)òV,~GØW'ëtÈ&Q9‰ý&C¶}ù%ŒzTʹô‘CIªGœÛvö]tò1¾åÆ1 8~¨QèÙ3åü‚‘‚JHTF¢s‘™z0NgK¡s0Œn¸x챋ûƒõ‰ÎRüªçÈ‘,ö „Üáh@~ñ¦vðPGÑýE¦ÃQaã’™œ÷®k )ñºv­ë}È"°öUíÚµ#«bªˆ@H 0®9–9PÁA•ºu®ÊMɸiåJ`ôhG8á”Òë¸Ä*†Rëd<õN:eýf"[¶l±ÚTµKD@D LŸ>ÝL²ü§…&Qxí"¹Êo¿íp4btvç„''öræ ¬ÃÕŠ6lp(:øÊ£o_ÅI sf÷38ùIÕ#WgN~,èž.˜[ 8r§E$¥ÎmîÜüH)O$Ö_uðNàODZ¡‘ÌùÝ„gŽÌx3ŽIœÛÅmzzz“¾»˜JŸD@D@D 8ö…&‡£àðU®" ‹Ý,VÃ7~œ> Píˆá’3žÇÁè%Kƒ$Šåž\™:&‘J€aj>ýôS;‘[¯^½H­¦ê%" "‡þ5?êf›Y©âÅ‹›!ÆD&"ÀÐeÌâĬ3Ü -š4¶l™ÐN{Atj×èØرÿüOrÒi©R%G¨ÿr ljN_q©?‹¨cýúËpâ„™à‰€Ä:·oßÞ:1ÿè#Íʳ.&îã/”+Íê²væL†eË–!Ož<1Â`èHj’ÐɧLç+à§Ÿý Uï;¥¦áÄJuŸ“'“žÍj ¤c(­ƒ'Ã~9w“¦vßCµ wßu¨1¼Ç–+ç¿ bûÊ`:±_æ¸aJÆö$î‡S:'XÇål,²‘™oºÈ¬–j%›MĹzõê>#aH5Zr±2¹¤jUG:ýP ÂQáÂ…“¬‘BÍ^å‰@$ l3ð9Q°h‘Ãqˆ+>ÿÜ¡Zä­Ž_ 3På—?Þ×¾qc‡l³·s´_b•À¡C‡Ì ½~¸öÚkÌúØXm¦Ú%" "¥8IxðàA™Œv/—Î*f|à¾?5[ ÕÆ‰áÞ½áWR“Ï¡ÒÇáwí‚ßOyqEjËI|9ð™Ë99»};Ì¢f U+€ÊJ‘j •g¦¿jF‹H­¢ê%"à' &à#‹¿¶››Q#׊ ˆwïš³gϺåö…¹qµ42:TîåïˆB”͉ã=ùÞ{Î>cÆ8œè¤CånóS ¯¾ ”,˜†ÒéÖ  {v‡ã •ôÊ–u8›Òÿ›ýûI†õ×2er„UkÐÀQw^10Ñï¬B“¿ùùšÞDâ3ó¤d"©äp©W&†ëuô(P¥ L§šr#NæÃ‘sîö·ß<çOùVzÍ–.íù¸öŠ€ˆ€ˆ@0 p‚t—m«S§N0‹QÞ" J€ƒÍ›;*ÇA§³üÓO;ªQŽÙ›uíêˆÅNÙiþlÛÜup³´_b“À³¼ÿĉfÐmœL4£‰2ˆ ¯¿þºu4ºï¾û"¨VªJ4àØ9PÑtêÔ¤ ¨\ài\›Ê <Æg…´¿¶|öH!êOŠÅüóÀ¼èðÃpÒNE¦OLcr«\Ù1!̬¨nD‹ÔpjŽÚ9HW¨ð7þù'—s—ÞE@¢˜ÀçfUÙÀqýõ×§”ÉÖ‘hñâÅÆùæ^Jì=Úëv?~ܶp‰ñÕØ¬(£BâÓ”¡PŒeynÖÌáÌJ±:éÔ¯ï{¿°?ð¿éâd©Ð)¨W/Çb=ÅTãx`éˆD!*¦ÖØÏ²æ‚AöÕtª ¶± tÚš5Ësä:m±¿dûþû 8|Øt̲˜%>Ø-ãMÓ›4\°ËVþ‘I€ñŸ)ïÊx—)Ž2›;x… RJšpÜépäMáˆñ@i+:ÞõWD@D@BI@áÔBI[e…šCƒ1Ž9eþ¿ÉB]OåŸ<ð€ã|Æ €+œ‚iaè3®_~ùÅ’ö·…Y¬ºo°`pÓM1 Âĉ·=}bžü-K h¥¨)Íu:*qU˜LâÀ™3gŒúK(Z´¨]mVE@D@¢‡'K.2¡ŸL|!À C†—™9Ó}B‘Š<}û¦¬ÌCÿkª.pb— n]ŸC<•OÇ&.†`ˆf¾¸(ÂyÎUW9žé<çÏ>†6¾w!7N2Ó>þØ1Á͉n>†bbØQrêÿN™²£Gï,,J}&:SD ìŽ;†{î¹Ç8Z¦7Î6o"kÖ¬¶NÌàϼyó/_>¼ð &Ìc=ãH2Ë>×9rÄ8.D5Â^ÿ@VÀøUYgX¾Ó!(5Æq0ö‡?üüÙ I•¾`Ûà:ž̲˜7Ûm²@u¨o¾™/w/ñ‘Gsî;wWiɽTß·Œ©ÿU8v¬›uœ’ð§ïì¢)eÐŽråÊMf¯d" " "&kv+(K¦Ô¦©,á!P³&0hcÀ¨DGŒÑᜫuçÏwT‰«w{ôΞ NédD ªUÝWqÕ1èÑáÈóæ@ïz.}-Ø.–5z4ÀÁ™Ä2ÄN4r`—›ê:ÄrSÕ6(%ÀpjTloÕªU”¶@Õ>3ÝpЧ7/Lˆ`õj§jàÁŠEtœñU €Ï9|>H.¬šrÇ“O: ¼ü²ÑÒ1b:&âOLø½ñFô„S‹)øjŒÄ9©F†šÎÇmLÇÎ;{¥ñ¤¹OŸ>ݪ ;ÖÜ÷ôš6Þ8Cb:Cdºòà8û±X¶a¢£Ù²\]ïm‚†Nœãå„LD@D@BIà„‰ë´mÛ6+­ÊrU–k6m > ®Ìýä˜ –à—åk ŒsÎu£fmc¬sÕ0WÓI‡ûÓj”fΘéY²8V;' \ó÷uu2W.qòÁŒ=¥hTææd_‰' LÔ)ëôå—yñï¿A¸M±®J i%ð¡‰ÝÈÅ)]ºtA6>üÉD@D@D ‚üj$׬YcÂS5GΜ9#¨fªJ$àøx£FE†[~öY€¡P¨P”£ÓRË–@¡BÞsyôQ˜çljáÃa~S9Ô_áÔ¼Ÿ]GœÞzËÁÃÏ5ÍÑÕXÕVD b|cb^õêÕ ÅŠ³ÎD)Uìá‡Ç‹ûR";Fìdž¶dØÎ@Y•*@‘"ïé®ê|Ì¿€ Jß~¨Ò¢#Ÿ½{aÂó7ßìߌŽZ«–±J@G±ze#¸]| ¢,'b’³Ô:1OªyR8¢,-c|…B™ˆ€ˆ€„œÀz£Q~þüyÔ®];äe«@hÖ ¸õVà?‚Ë‚5·Üâ{tÊ¡BϾŸ“š”NÙaþ]µÊ²`ÇG˜]®ð}â àþî ÙsƒáR²™3Ž)S’¦ôu5râ39Áß®89x0ñѤÛùò·ßî¾ÿÔ)à±Ç€¶m©ªTÍ8D¥ðÜýtm‰@Dob€d̘Ñȉ¯<™ˆ€ˆ€D¹sçÚ°( §a&ªóÌ3ÀŠ#F0 pá¨9ûüóžüê«%:qñE¬ÛÖ­ÀÏ?;ÂY§ö¹,Ö©}" #pæÌ´nÝ.\À‚ pÙe—ù”y¦L™|J ‰ŽqŒM}ú)Ì¢ÛÀÖØ µB®cw ÊÅwŸãT© ”Ñ)Ša Ìâsº`Ô(Ç ü† î%p"€ŽZ3f¸ïwÝ:}Úá¼”??ŒT¶ë‘´}nÚÔíë¯=Ë&û’»ñɰ!Þ}èÖíÚã¤/§)D,/Ì€ª÷Þ{/ ,±õTÅD@D@â—Žò™™Fü¡+/¨bÊ ÓÙ³+¯ô’(À»v„ncy|þ‰«\ ÓC^ËD@D Øž1ƒH»wïß+ó‡Æñ'ŠN¼ðиq`x «ÆPc ':rd`ËŠÔܨ†H%C†NåX%纩&%pˆM}z{î1^(ÛͬÃ³Ìø€YÞ|Ü,祌ò³ôÍ;· +pÊ—/%J˜xÄ& ±,ªìßï˜èJÉáèØ±cøÎÞ¤7pj¬woÏgÑáˆ&…#ý-µk×Úß5åÊ• mÁ*-® Q-ó»hÒÄñPúöÛÀÒ¥Àm·Ëß/¿ ”*;iž?ýähxî9€Ž>ü=Hg† £ÑQ¼^=`åJ€É®f"'™öÀŸ:Vຆ„3 ÇÌïEàÆ]ÏpÿLGóäV²Ö¬é\¦óÓUW9^®9tí P½ˆÔüýèé7$C³Q5Šƒ)ŽîD¦i±ôæiáãh3îŇ^plè¯D)çx#1F‰z™ˆ€ˆ€D/ÍÀãN3ÔÍüxÌàé‡q¤UXõ ŠY„Za¨_?ÇsÕeså [ÓC^°‡¹ ¸$ðÆËfìØ±vþú JhÇ©™q([FKŽÿqn™ãš'þ?{g?Õô¿ñE…BI *…-²ÊBöõgKDɾ'KŠÈž²EÉžÝ_EB´RD› þŸçžæû½3ßÙgî¬Ïçõšfæ.çžû¾ßæÜ{Îsžëcd¿ÙèÑå›ýªqÂ&'@Êݨ|®}¡Ÿi^G3gÎÄs&w|ÞþwüòË/I±zšž k[oþ&<Ú$Ûð×KQ¨le˜^,n|üñÇžíàÎYn•83žƒNñ¦âVL+E@ª0{P/Wáùçë®[u½–ˆ€xh«ûÉ'Ÿ S§N&º°§…ø$Æø6Méã×_»ôfÅy$p×]î¡”nDÌm^£FJÅEݘÖÅr÷¡‡–þs¡›ôÍ7»íélDí@辌¢ȠhóÍRd&BÎàáùÙä1›˜¹',}l²‚KuÆ´d±bu€¢¯e¹#G7Ýl±EÕmL#ïO“&Ó(D@‚#0gÎëX|Æfïí wƒã¬’E@D@Ò'0|øpog¥SKŸa©îùùç°Ah78šËs´yÞÞ¤š-ÓM‰)¶9&—5бD@D <œm3Öþ6ÛïûmF^¹›edyX7ìˆ.G×^ °] M° Û Ä¿P`µÛnÀ{ï-Z‡^â'¬Ó+yíZ¼x1úôéãYË>`þ¡ÉŠüT—/_îu6víÚ|Mž<Ù¿ZŸ ”Ó©191£C¬ÑomêÿÐሃEfš¥È”€ ±Ë.°œ°uàÊ+3-±êþLB«!@1íŠ+Ð1R5Q"ç§ÓHŸÀ[o­Z9ñLú¥DßsÐ `Þ<€é¾ ºô_Ó§gÏnxÈ€¢6Ñ‚böí[ouÎFqöÑoTŠ¢íÇeÛm|ô‘JÙ-XÐ}ˆÎGLç-8ã‰÷žtùÉ$(ˆzê©è÷<'æ§¿æ:erí+"ˆÀ]¦˜\i÷†—\rI¢Mµ^D@D@rNà³}”ø-lôgÇHÛΜ×F,$/¾è&8äÒðbÑ"÷ J§}Ûm]•Ȩ." "PFŒñãÇã4³÷ɶ‰BiÊÞY„’â°Ÿ®\ƒ]"[Qx¥9ÍåúWPxçsÁS‰ìoù831[ÁTlL½u­ýï¢IQ¸BGÉŽjØ”û¶¡)ïY8%μçñe£š˜*¢¼ üø#pâ‰ÎÓÜZ@g£{î%'Î.—·ßvêDæ¹Qˆ@ x—S/,vß}÷8B6 ÔªåÄFñ\xÒ9S©ñœf œý þlSÈC± ‚2‰I“`Î]n–,EGÑ‚ÛÌá~æ™–,ƒ²—_=Ú¶©,£À‰3t9SwÕ¯°Ýy¨Y8å”°ÅYûbY =ç¦Ö­îݳV¬ ˆB€)ׇ˜º‘îÆù_!" " F`¬å¶øÙn»ëưÀ®L~«ÃÉ%tšåäמ=sW— 6lη—v…Gåsák¯EwmÍ]­t$(=KÌúúâ‹/F½zõpã7–Þ &qFÌ,3kVfa:™³îÙga÷]Y(°‹8ì0€÷ݺaåUå’%SÁѸqã@[¹E”Ø'¦Lkm¿ÛÙh¨Å–‡â±Ç³1ðÁxEa à‡³Ì›6]?^Ël*û¦ J7ß9Žç2MG(8˜Ç†/–Ð1ô.%M€Ia)›¦W#mÂM< Š˜Ÿ‡¹y²™N#Òûì,XÌë‡=z¸Ü<ÌGÄôœ'/¿  ôëçF·_}Õ¥}“cRl–Z8Š®kšú¡]»vK(lü¹:î8€)œÍ:/¼]8ã¶Jýß5ÖpiÓ}4|_.7‡gs Î:+|]ªßènÄ`Žöx±ÙfÝ–Î=7sÇ!ÿq8C—‚&Š™Ì¹:,˜Ó|Ì€íÙ ^?¦q»î:Ød§·ÕŒ¢lVY"P•ÅF]tÑEUWj‰ˆ€ˆ€¦S[mµÕ$8*€kQHUØi'Xv€sê8$—Á4+?üàºÉ˜J[sŸrI_Ç(WÚ€ãO?ýd“únE:uŠú´-‹¹¹ó§v Üž}œt6çðQ.‚sái0aÆ’ !P-WõxÍ$ôÿ3ßPÚËF ºqÆãÆÑ¤IÔ­[7l3¦ ùÑ\5~°»äI6•úI¡ù•9"âK›2Í<ÙÆ +ú÷ˆS+‰¯œ]OýX¼Ô_ÛT{ŠÒ2I§FÝgºÛŸSEp ˆ³ù" q0¹;ËÏœ ̘þâ²?ÿZ¶tj¾ˆSP‚U”¼óõ×_•/Þò;§\=þ¸s7bÎ&¦>Ñ‚£ÊÜŸ¯xQ½ºS<2·âÉ'K•Öe•ï˜.t'ëm\Sy—²Ê6•Âøß8vúæ3n¸Á=ó'é˜c\M¸Œ?eLF-e¶bà ¾"ƒ N?Ý øSj·Ï);Lïm·u¢©” ÈÂü9gVO¾èØtÅ•…Úü…@ò¹S\E³V6‰ÌKÏ™E à0ÚÀQ¿~}ëÈ<.¸©dH“ÀÒ¥K1jÔ(sÝÍë×N³íV¤æÏl~˜:mó;}+O„Ž«–i'/ÁÉ'äœ òRTD@JœÀ§Ÿ~j“ëycÛ'ñ·Èã ƒ€©SfÍ`ÃÀ®»&>¡[nq™enºÉ¹Œ'Þ#ó-.» àK!"P8r"8úÅ'z÷îUl´ýöÛãòË/G›6mâRY˦.onwì|Q˜tÆgà•W^Á£6e{Ê”)aû~cSŽO¶ägÍS-]‡œ°õ%kÌY0ap@–‘‰àˆnFS‘«‚$0y2pÞy°±pe\¾+KQ(­6(< {Gš4öÞ8ð@Øp|Õ`h?ÿûwßÁzß`Š ÷š7Ï¿¶êçƒv£ØôœŽ÷Þ ´jå¶¥PuÓM† +ß7Ù¦N¦M ½ñ0{6pÄ­>"0ÏMåÂNèŽ;|$gxrf)õ”IhÆ+*æºéÓÝÏŠ_ôìߘ¶öÀî}Ø'´ŽÂº Ù˜º'f‰e‹»p¡»Ç íGcÏD?•¡m#ßéô:ø4Ô; {¶ÙeçòLu,(OOÛÍl»o»Á”™í–ç߀ÎZD@ Às–?øSãs¬¢t pŽÛW_ìÒ ½hüíOéÒ¥KᜣF…SÕDD@JÀ¿6~r¦Ùm¯ac •B°OYbÌ×믟øŒØÊ ”ž‘qb^ÚBJ™@NG´’[Î|¾àìÄ+l rçÎ}K“ÿÈŽÆ.vÏ×Ç쉖è€ ºä<üðÞ0)´LïÅA€éÔ;sÊxAîÆgP€v „¦?Ñ&aìØÔŽÄtc´è¸í¶ðQçÈRÌÊÓIfïs¿0¹-÷´Û`.Â6rN@ÌÈÿH«­o¯Äëh×ÁaŠ{h…ÁQ:1Ý^BïüÌ»YÚ¡%{L¦sã+^ìµWøZ ªX~²Çß[ßD e®²¬Ù5™©!)—® …}ƒÀ©§ÂëÀÍ7»ŸÐDû¥ºþœhˆ)·:tp–Âñ'5ü‰³[W/¨çôÇUW9Ó6ÓéÛ=.L8ï_ëôšûíð8tF²‰TžôŽ;`©·MæëŸ|Ž‹¼cãßF‘uô¯ç½×sß|›¦ˆÛsOXúfg”d}¨¿eÓÍ”t<¦BD 8t7êׯj×®íuæw$•," " é`:5N–íkÖ@úEkÏ Àûþ{à’P¬³°õÖÎñ”™ÓiÎ9p Ò'pß}÷™8ç3ôêÕË7¦¸)¢ <ûJ=èÙ³²â–.fp9çurHå&tÒ£û7õV‘}˜•[铈@9\pÄý£™ÇÙ¨ Ä6Ûl3ßÒô?îhnt3:×~Ýø þàdp u§BRïÿ÷ÿçÙå7àÈ`Aã’Pp ÿ4˜RîG ˆI€v ”eSœc©MŒrmŸ}ÜÝ܃=äFÁcV*b}ší7/¿ ÜuWe>nÆ?vþæ2ÍS“…ÒXÒþ"Ùß /Œ8`¾’å›oºd¾Ìq“ï`ŽE…äï‡;ì°CªC‘À‚Î`ÑÔ:•N®E–=[néŒâøSüþûÀüɧ((Ôÿ@-g´ Q›š3¨{X?ÿüÊ­,«°Wê%™Ù’ÁŸõ5\BG¥Ï™â*ëóð„OnëèÿR¨DMj4³7:.½ô’?QÈcƤÁ™½&Ì›žÌ¬§Šú`¨èÑ:Ô¥Qã̪ SQt¤žÀ¦°œfN•×_½¹°müuH‘Àv£þÖ[o™òv_¼~Š{kóB'Ày±|ΰ¹Íà3»Ì8Ž/¦OÓ<¶B¿‚ªŸˆ€dŸÀO6Ñ»OŸ>Ö.4ÆÕW_ýXâßÃÒ. (Ýßý‚£x‡eŸ'ÛÄ£ŽrsÚß{3Æõ ²ON!"PÞqÉ< ¾¨V­´öl‰BE×±üY´­£˜)š´’¢#Eñà Ö/Ì¥mÛ¶Y­´i˜¼|£Ôf( €GK{ `š­B Þ!qä•é·žxÂÝ-™›7ÂjŽl–Ùª3Š˜Œ¹çÎM¾Ôgžqüh¡qì±0e¥»»3 O0…½/i½À©UÜ–éË8‹éÛòEßsO ÄFùb ã–5Ši)€®Ëÿ Šœ £µ—±3˜"þü¦ñš,êTùàMA5¡LïE#;6%ÌDÉ4nɦ=£@‰B"¦ûí·ÊZÒ¦ŸZIþ”‡2ó'ŸÚSšÄQLª£™|zÚÓY³*÷÷‰ÇêׯêÛl»gwºXæp÷õ² õJ˜©ªýs×€îO â&°lÙ2s¸ÆêØàžî)D@D@D  PË´*=¨JQ”>DZ[ÏLõíëž½˜[b£’»Ü:!HHàoSìwÜqX²d hµîS(PlÄ¡£^pC_t.O6ž&®8_Ÿ!91‘s‚ا¶.þ³ÁpÎððGwÌoÑ¢…QÖ>¯gO|ÈóÇøñã-ÝÁJÿ"}ÎÆQá<‹¬Ê”)SÌ e…é;¶\•Ñw ŽY.ÖªS#Àô^Ì3Ãü-ÌÕR(AOHúH²'vXìMà¨.=´•¸ñF`ذäkKë&±<ÖàÁ°»SXŽˆx[V]Çü5ý¥µGÓ9¢Í²š4î¼`ŠÉ_tçÄi…ˆ@Þüe>µl߲ݶåí„ àÀüÉ£}=õ¡‰‚Ñêð„±Æî=Þ¿ÜÇ/Ö¡50ïèb6¡ ´¦VšÂ"êTìo`Ú3–õË/N_êÖÄÿ—)ÊØ™M›â›nªÜ–æX<_¿ƒ#×RôÔSNWÊs¤»Ó‹1æ‘GVîŸÎ'êaiÎE$¦xóÏ• Ì€Y(±á†Àˆ®É¦­³BD ¸ 05û|Soöïß¿¨:q‹›ºj/" " N,¡ß{ìá¹ì§²¯¶-,œ¤2gNÕ®¼­¶rÝ‚|¬BD@D ¼ œmJ›7-“Ãyçg“mvc‘‡É9ÔEᇖèžJöw>÷œ{qâ#'FrÌ×çR$$TM T ¢ÐP™_Ù€;;CQÝ’8òÇ8ÈØÝ¼Û67?Óé«ú›«Ç'Ÿ|bú†AVe'AàÝwÝ@ܺëÆÞ˜êŒl ʲå#EN<®2ÙÄfŸöšåË]ª,Ї˜3&Vª&så*%Ït8ºä€ÓR J°9jËGbýŸ)ÚaòY¾¸G™¿&™øòK7Í;,ŠwØ›À (Š/: Q„ï×íQù/óàÐFƒb%Ö%Vpt˜®Jt|â(©©ã“–ËÔi'P0źôtVˆ€/í7†³_²Õ¶ÔÉå¡2lN¾ý`óC#Kj,c›f—Üyg€6ÁÉ„Ý6z³}(0 ¹äð6’zNº-] \u•+‰$jÝ™¦íÕWc§£8*• –”çÅòyëʈË$ކvtq¤È¦}{`Æ '‚ÊVþôæÍ«Öžœ¨m-´Øw_€/…ˆ@q Eýí·ßnÎq­äQÜ—Rµ’%À‰¶çœsŽ Ö­Ž{î¹§dϳNŒó÷ø,Å~dv­qÒˆ?R}žóï«Ï" " …Mà@|Ñ&nï·ß~¨ÉY€q‚ϨÌà³ÿþû[¿]œÉ8e½jöl`Ò$×78sfø;‡Ð(:âR*b#9²S'`Ñ"×Wê_§Ï" åK PÁѧ¡QšU|ÛÛ]ˆ‚ŽmÚ»ÿAjS Ž‚¦ž¸|n¹e|»ÙÏ9Þ"ƒ²Ì!jŒÌÖèݸüòøÇN|Ú"*¦ãÓ8ÃR&z¹ëøýàƒavfnù[o§Ÿî¬h3E¯Ædì¦8šI! ÿ.&N„Y„81‘+5þ¿NFpÄ».»™ôF®™—†#µ‘Aäví"—ÆþÎ:›»šç>Ol*£ÄãÆ)Q´EY8ëÅ©U;†¶Šý¾÷Þ_ ‚$Óf;]hAžl*ÅY¥LFgŸaÀ뮋­‘.<…š©ÈêÑtϲòzÙ-¹Ž:y>8ógß&*WÄvÛ9Ý)ŒÎ8£b±§I¥¡õ7¤¤I­,!ú'>ôß|³ËŒiÙ„¼f3ú–•Km¬Ãbñ¾‡.Nlvƒ Ö‘éÖ" "~ýúÙíùrû-¼Ù~ÓìGM!" " F`˜=Œ|øá‡^ÚÏ­·ÞºÀj§ê¤B€ýÕìÆlÜ8z·`*ei[â"@áÐ¥—^êMvyòÉ'­¿Ñ:£ÄK/½„Ë.»ÌÐ[›ÓøSûœÊ‰—þ>AÙ±ÿŽÃqt)gjÐL±9ÌŸƒ¡þ(WA‹D@ •€ýÔ¿ÒÄ“8÷mŸîÇwÜ1l×è0¢È;€Ñm(^pP¶Žü5æ^†Á,R4Ò¡fƒÁÁò‰… Ýj.N˜Oå•%`»éÂë¯;++:5kæDG\ÎÜ2t7¢=D²w4ôd5ÊE£FnäµiSgSQ·.À-+øNg¥5×hçzOtþYîܰ԰›IOì“hŸdÖÓɉ#±W\‘ÌÖîZq6\·nnJsãœ|2@[0æ±IÕ *¹£j+Ȧ˜6GU.ŠÃP`sÖYÀã‡?Hû+š™Íá˜ævmÚ§žê=4ÇcfMÞ6Òt.RËY­Ô‡úƒšR¿0É¿.ÓÏ6YÊ;¿TÜz¨³¥Å±™}‚ͦBD@Š‘À×_‡zt/>˜£ (0tÔ¿Üf6nlyŒ¯á EÑøýwàý÷ûéÔÀ—BD@D ¼,X°ÀœË¯·á¥º˜6m8¶|Ûm·y†~“'O6g c-‘ņžRíÚµý« ê3û69DÖ¤ À¡4º¦';WP'¢Êˆ€jAÖ–?ÖþhРÿk`ŸëEäÌø…i—y'ÀÌQñâ_SM4›™÷$ J?e¡ÈÂ-Â\¼¼O»)òì ¨´Z¶,7õ¥Ðè´Óܱzö˜ë†õ1JO€D±E=÷ßïîpR©•)Æ=Oã¶m³/ bž=æ !3ÖbŸlS¯sL¥ÃS2åòN¯gžq.No½åòèHl” =m#M€bZ>¸6 5L]Ûâ©3^öêÜ{olÁ›"Šo,#O•à$dËö\’è‚H'dê<©‹e.óB¦ŒK%ØÀsQˆ€ˆ@1èmö´+-§É­œ¬ $põÕW›;ê|KIò yбÑå½Jt­eêj:@°»R!" "P¾ú÷éXÔÔÔ9k96ÇŽ‹‡~ØýüóÏæœ~þ¶™Š¯¾úª·]ºÄ8$´V‰óò{ôH·†ÚOD@Ò#`ÁE¤àˆƒm¹ˆ˜ŽÈ‘NK¾UúX@¾µœk´ÍÏF:5žS®ðO®ä ®hÑÀ™¿tÅ¡c¾8 ûÇù¹ºO!GI™0Önȼ§xÊ©SÜ#æ»Évüø#Àtpt#òçÇÉô8,",ö`¤t9â¹ÒÕ‰#ä·Ü’j Ú^D À08gÁd«m+°ÓËkuÖ^Û=@^O(Y.Ÿ5 ˆænÚÖúlPÛ5£.1;¥Æ·Ctô." ¹'0a»esºy³Ks_QD@D@âàóÝ}Öçµë®»Z÷›õ¿)ІÀ{ïtà·K—5“ó¢9yUTD@D Œ ä uÔQhß¾=èRß½{w¼`–éÛn»­Í+ƒÃ;̆¹fcÈ!^ÛVH _8E1P6ÒÙï¹Ï>ÀÌ™)TD›Š€ˆ@V ÌŠ"ÿˆ<¬ÆAøgCúã7ÊFO€ŒlÊ27é_¸ÁCšþ”\ðoûˆ#œ#ŽuÎ{¦4³%Ô¬™ÓåÓx¢\xñŽ!Œ·iN×µléþ8úôÉÞa9ºÍü=‡Ð:#Õ0+n“ÎG <ú(ÀÑt…ˆ@QøÆÒ"þnžíméԦȘÀÙgÃRTÃï¼½¤X(2ènİIH1ƒG|0·ì=hÒÄiwe3—Vˆ€ˆ@à.½ôR³¯Ž˜ZY!" " Hàæv¶¸Ç&媯»1]•8LqÊ)ÀZkC‡«:*RtxTa(;½Ì6®E·ß~{ʝ»îº>|¸÷Zºt)<ð@|ôÑG¸âŠ+2s~:ç˜Sxôüó‡LûÃ8ï&áK!" ù$è­5óYú#ÒñÈ¿.›Ÿ.\VÜúë¯ö]_rOÀÚæ„„àˆÙk-rV¹9dª®©S_Mxîio@oDçŽ;ºe;ÞyØk/XÒÚl—\åeÛuíºë€ÿþ21™bO>é¦[%ÕBD A´mT§¨w5‡c<ø ìA¿ò4Z´p‚¡‘#yó*—óõŸ¼¤¨(^Ð\ÎÒµcôhçŒo[­ŽÀHû1ÿÀzMϰØ-·Ü2¸©dH“Àc=†÷lbÞYg…í¶Û.ÍR´[>p —]¨|ökÖ,5Ð1E@D@ …ÛòçMõÓµkWì²Ë.UªE—#ºínŠ't®ã¸O†Ñ¨ì–² &dʰ0Ûýûïa“\çžN>9óòT‚ˆ€dB PÁQdj³¹L_”ƒˆE ŸrP"‚ÝØ Æ 6à묳Ž=ôeï©GŒí·wï9ý×:ЪP¯žËù²`AüÃÿòKjâ$¦Û¢ú¸ãÜ]JüÒÃ×&c÷Ä”cf%é9%]xaøþúæüù§KÉÆh—ñîŽéíäd¢¿Uض1äp´ Hot,²‰GÖ^5±\î·$þé'à“O€ý÷ªU ß>òEK6Qɬ’#×軈€ˆ@. \i#œQzõÕWçò°:–ˆ€ˆ€$E€útâ«gý|×^{mRûh£Â @Sø»î‚ *\PuR-D@D@òCà?›0~ñÅcÍ5×ÄM7ݳ[l±Þ~ûm 6,kކLpq÷ÝÎm/æ“\aš(|÷Ð¥K’;h3@ ‚#>€ùcïîsŸ}öYØQ$8 Ñ—/œAR¿~üCsP–²Ù´# ŽvØ!þ±YKY1;Ë÷Ýxä`«­\š¬h£“gF%›û‰eÚ.ÿk´²#—Mš´n “hG®©üþ×_nD÷çŸawT®î•kõ)D`Ù2ç.EAÖUWrñ]!" «Ðሃ§rjÈüO¢S'÷“K#8PçÙ¸10x°q³y¾û.pÙeþ-õYD@D P |ay°¿¶ü–§X®“È~„B­³ê%" "P^ú÷ïŸlf'å¦_<×^©ÔŠçZ©¦" " OZv‰?þgŸ}6(* 2æÌL¯7þùX±"î&1WRÀ¤B `ÎwfUŒtª¡=ú2 §‹MñžhE—EÞP“As«½÷Ž]…3fXê³EYw€Øg`þ|€K9ã¯<äSO¹)4f¿ˆGî¿6úìÒoÝx£&Õ¬™œàˆÎCǬ½¶sÔá{*AŸÅ™3ƒ^yhШUË9­±†+‰š?,-Ž8"•ÒËk[¦dë× ¯Y³€Î]âÜò¢ ³ˆC`âĉYÓÆ9\I¯bsõ¿ÿU=E6]L·Î¦,äfÄ4ª»îZu[-(L¯¾úªW±ƒøŒ¢$0|øp32oeiK”·$ÈË3eŠKM[¾V®èjÛ°aøQÙ=ºé¦áË¢}ëÓøö[÷ÌØ¼y´-´LD@D \¬0eÏ6‘ƒ 6°yãÁOïÑÃ%Æøæ؄Ԫ”Íl §æ†ë8d«Z¸–z¸í67é²jIZ"" ù%`Ã1ÁE‡¼Yý¡#ümO ƒ9ý<À p%”¾$t˜=÷Ü3ôQïy @w#F¬Æ’ëèÁØ>˹ÏÚµsn)9±e§]B„S–WÁtÿ9úhØ”]w÷ðÆÀ6Û63 0‰8‡>ýÔ¥G‹w >iwëæTTtŠ5V9öÿÒ=1ß SQÍ»ŽÒ®µìn 4 Z‹‰Íñ °×#$jÌÁMjüÊh­ˆ@!˜>}:/^œu1m!c6ê2o^æ¥y¤kRW[-ó²T‚ˆ€ˆ@î Œ3Æ„£µ°ûî»çþà:¢ˆ€ˆ€$ 0Í:7çÛŒÆ}ÍÅ<›Îì [2« p®‰NÈn°ÓNÎÔ½o_àºë`ŽRÀ?„ïI±Hë¯ï&šÐ¨Ý/¿ tìèÒfóØì å\A…ˆ€ˆ@y8p ÍÅŸ‰>¦F­S§N 0ž{àP ‡£‰B§?š´hᆠûõ&O­uiÓØŽ=û¬{U®Ñ'( Ž˜³ó_øâK-5‡>rÅæó=èVE]s Ùši§y#5k» A Žb1ÎæeáÀ^{¹÷X›2O “¤&| fú3:p5m ðÉùµ×€ž=›ï(â…¹d€Í)ÌËsøáñ¶Ž¿Ž¢¥_„%ŸwÓ„8;‹¢¨ýö¨Î¢ƒÒO!Ç£ø¥•÷Z µ>úfÑì¶[y³ÐÙ‹€„  ³-¦ ;H}ùþ{g¾ÇŸÄdbùòÔ2Š&S¦¶(.K—.Å{ï½g_{Ùü‡µŠ«òª­ˆ€ˆ@Y˜0a‚wž»ÊF5åëÍ~av¡î±l’pì݇=Ô°¿ô`ÙV½¹›ìzå|IÐÂ2á`»í>SÚDXp÷£‰ŽûfNºà*D@D@Ê—À‚ l~ýõØ|óÍqî¹ç âÏ?K.qÂØxsú9qÒ4P7Îyüü3pÍ5@›6n(bÙwØßzï½ÀÅZm^ŽxSÅl7¿þZŽg¯sÎ")6;ì0Œ5ªâ ´¬;Í<â˜'3Ûù®GŒ·ß~»âXüp„¥ƒÒÌ“0$9ÿBÛZF<3ÊÖ¨Q-[¶tçó_ºëò°x ðøã­üA [ouOµléS ŠR(bjµM6qçdög˜¶‹B¨nHføÛ0]RÄg”ìÚ€ÓD&[ m'"PXBbÚ¶‘½£…UÍ¬ÖæÚkÓ–{6¿4 LlB™ú4^¿=3¾û®ë(®^=Q‰gÅ6jäÌo­-D@D@òM`üøñ–2åo3µç0…ˆ€ˆ€  c%wq¬Ûßs*â|KÎäлV9¾»J»VŒhÎí™e5^2w¤»Q¼îØ£ŽøRˆ€ˆ€ˆ@ˆ@ïÞ½±dÉ 2Ä„ªJÕÐFi¼SLK/3ì­ˆ[nqiÒW¯bqÌL6‡yËAw¤çŸîºË¹#Ñ;@Ë1ñiEºh!Ù£`}2hÐÀݰµoŸniÚ¯Ì ®íße—]йsç0ÌL{ÖÓ\]æe#‡Æª’‡Ú4ˆk(ýô-ñÎ`bKE^ „G‰޶Ýv[ËêU-¯u­88EAt"¢­"ŸPéL ʉé Ô¤‰óõ -Oå74t6¢Ÿb²Áé@´Œà¿œ‡’¥¦íD@D o JL›# =K‡ã:‘#mí£UÙDi,xê©•kÿý·ò3?Q@´ÿþáMqø•ß8ƒeÑÈO!" "P˜N!ÁQq\/ÕRD@Ê‘Žšš¦cq 0 ÌI'9óôІœÏÉy”Ï<ZâÞ™¤àÌ3Øhûí©{"±Qx ú&" "PŽfÏžÁƒãßÈNÄ0|ðAOhÄŒ<Ý2è4ä¤H°ï“C|ìÛäð´™(Y†àæ›V­œÐÖ¿}¢Ïö£# ]ìñÿp|Ub£DäJ|}’ç–þÉ]˜9KÂ`†›m¶qãÍfÜâ=³SŸË³tP2Åܦ–ag+ü)J—@à‚#¢ëׯ_7£/ÌõPóI}Ù’*ÿÇ?¸4ƒ³!·ÔR71¡sD\pÁXGÎ#Trÿ•Ö¹4ò‰•§tîܹøÙ¼ ΂?¶œvc‹žU§Ûð‡½G€wôúuRAafZ6ú,*D@D@ ž޶±¶¤`Ä´9 Æã§ŸvVùÉLâ¶Ÿ|„œ‹¦Lq¶Á\ æ(gÓ×¥KhIìw»­ôž2è;ˆ]¸Öˆ€ˆ€BàU³2hn£‹´¶Wˆ€ˆ€ˆ@¡` –o¾ù»qr¢".¼žp¬¯¸ï¾ðM;vt“çCKÿøƒ™ `ưÉʰ¬ÀƇÖê]D@D@b ÑÄ™¦Xíacu‰DG ŸsÎ9žpø©§žŠ]h‚5 lËèEà>}€Úµ9î×÷ÛÏ ëöo™Úgö…Ò4Ÿc«Š2&@ÿðBαPؽªÝ¬:Õ7;ÓãÅ›oÇK;i8K-¦¨[×-¿â w3¯ŒDëÌÅÚËò³õÖ^ÎÜ_~‰-—-K´—Ö1œŽ6ÜpC\gb58 å‹ß~û ]t‘ÍZßßþîõD'¾Õ1?þeO/ã,©ey:Û6õÕWU¶¥˜éhSÌ)òO€¿ƒñf§„RÎlÏ©,…ôò¥èˆ-;½}wÚÉyž>°çž…V[ÕGD@D @„Ä´Ù¶̈ĩüØn;àŽ;œ)†¿0šdÜv›[ÿñÇÀ%—T»Å‹½örû˜1 hCÉàg³þÆaN/@:¡åËÝñ·ØÂ‰Ÿ˜¶Í²÷Ì4‘ÓKÉtî»Úèß"$¾2µ³Ý×~]YJºýÁ‘ _Ìœ9×_½÷ÚØF©Ú´iƒúõë{ Fm“†®°Ñ&vB†^?ýôS\W¤=ÌsîFû±šœ`|”óó‘ 1•¿E+8"¶6ÞzËY+PùÉ„¬üÁUˆ€ˆ€ˆ@ L§Æ(Ág¤r«?Wy , óÙ‰å±Ó™M©ï]ºÔ=¨'ÜYˆ€ˆ€P:5NBRˆ€ˆ€ˆ@!xï½÷¼jÉá(þÕ!&Žwq®&'Æ' "ðº\?>Ñ–Z/" " •®2U+Ýä?øàôîÝ<òV_}u<ôÐCac‡¦iÅüùó1räHÏ…¾²”Ô>Yñv à†`Ǭº/½6ØÉ׬Y.ÅZÕ­´¤$ |ö0}:P³få‹ä|qY蟋»Asœ/ZälÝšèÿ^}µS»|2pñŰ?f—}§Y3˜'ÀåöÁ„6 èÐ!z9‘KYVdÐN‹cá§Só»ìâÔáMšDnýû¤Iž›‘—e13sçšJïŸï¾‹¾–– œ ŽHŒB :Ñîn!ÿ3E ¦ÖˤÎiÆa‡†þýû—Uú’4Qåd·ËûbeyƒÀ´3ôD3&vJÏPãP°VÅD@D@òI äÞWpéB³ Åžå½ç>3ÜzkÕÂi©O#J ‰Ba—X¹¨S'´$üâ%N¨¸ûn`âD·ŽVû Ò#@ÁQM{¶ÚSî±¥wquF" "P"褰þúë£U«V%rFÙ? N€§Û,3sX׿e9H| ÜJl”˜“¶¨$ðÆoàM3 «QëÖ­ñ¬¥Ž:Â: ‡ꉎ† R!::Ù„ìŸåx1…G™Ä↓µVâR7N¼¶(!ùÜsOr'Ä›:ùƒ-¼Š»î PÌCE÷À0×—úìñÇv¾[&)K3åNñÊIfÿÈy3ÇñúË/çlj˜› ,¥Tü½iWyì±Ó°Ž§ŸžÜ˜ø¥jmÈ©àˆ\¶Ýv[ÓmŒÁ]wÝ…'Ÿ|2¦Õ]ª éŒtíµ×z¢¦T÷ÕöÁ Û#‘ÃoÖJ¦µvÅeö/‰318G3ùCœÌS0Èú™ M!" " ‰…˜6ÑI$XO‘Ñ…ºüäW^}cÚSpÄmC–÷ÜâÄDÌXÊ4ÎÑâöÛšDq–l»v@²)¢•¥e" " …I`¹Ym¿ûî»fMßÉú×t°æ)¨V" " %N€®ûŸÙÌõ}öÙ§b³ÄO9åÓã8×Ùg»Éýo‹×œráÚAD@D@|ènT½zuKÝi¹;-˜*í¹çž³ìO‡{GkØXßý–³“pž²g]-·YŸ>}|%ÄþÈ ’Ì0õå—îýÐCÃÍgr5|»†Z“uÿ0M;¢™fŒ72±fÈÆ:8Ý€vß–Úɽ~ÿ=ögŽMS½ÆÃW²™šh‚qç°ÎÕˆ³€yÓeb;ω(VýÒ]~é¥NtÔ£pÌ1ÀG9VÑÊ{ì1§Õ^D@D d |b“):ÚU'Q¯ñË/»¹œt¸gvT " " "Y¼o6Cgu–MLlRq<ÿüóæpxàÌ´qÀqãÆ™ L 6,¡`˜#Ó%yÙ©* µœ8Ù¹³‰>4»_³ K±”\5ýéÈ(üyâ ˜}ìÈuˆ'W ]VÜ+Ùí3Ýn·ÝœÛÑÇ»÷ ³ñðæŽ*<ºñs¬ àjÏ=š6µ•–—8¼ŽBL›ÛˆÕu6u¥M‹gg#gŒL¶Ñ­¯¿þÚ\·Ìv+Jlh ¹í,/S”ìdI¡é˜¤(\üm‰÷ûJ9³=mÙ‚ŽˆÒVŽ*OºQAºé¦@¯^•™[mÄQU¦ˆ€ˆ@`ÚØY–°û$zÊqð‹“4ø¬zñt8Y¡Q#ç@tÙeîy"Öi2=]Tù²þ  Ðn¿_?—û<Ö~\ÎTÏæz¬(Qì0fHpT¢X§%" %@à=Z®ZìÆÁE:Øž>,‹°Î:À 78áQ²“ô+ ÒH’ÀÕW_íMìäxrdPt4jÔ(j¶DcÇŽE½zõ0zôh¬½öÚ‘›†}çð¡e^Ã÷ß»‰•Ì"z5l¶©¾2„åÖ(Âá¬Øxé¿èjD§ :_Ѧñâ‹]:2sÊòÌ)hmÅ>}Θ Ùõڹת¿C>›õµÿK¦è‹_" ƿ֖<¼ ŽBtkšï ›¾Îã_û¿ÌF£–,Yâ½Ó®Hµk×öìòBûé½ø *8 Ù/Xê>/æQG9‘ó»$›F­øë D@D@rL€éÔG{ðÙ‹¯¹s]®ò>pïfàä9ÍZ6Û¸Ág:Ó›`Â|ç2qæBD@D ¼ Pp´Å[`Ë-·,o:{‚%0Áò@³_º}ûö[Ç|TlñbØ€.À &7Ý4hZè˜" " åB€b¢O?ý^x¡ù ˜¡@”`šnŠŒúÙ,Ç#-íTãÆ£l¾ˆš+—_KþNߊ„;›™fì§Ÿ`î&@·n±+>gŽKÆ}"Ó‘¼ëìæì[fÊ¡€†3pÍo»L­ð„à(òZ¬¾úꞸˆ£b ÚÁÿj¹Bø¢@Š s†f3þüóOOˆE§§jÕ òò¥tºñzÓµ*«A•*¥ÉqTsÈØù^²z`&" ¥E@m[ê×3P1mêÕÉÊì@fs ­\ »I®hºªr’ÉÈ‘nûk®I>=urGÐV" "µm©ñ bkºÓêþÜsÏ ¢x•)" eI èö­Ôú$ý‘üg.éLݲÃ;uªìDç™Îúví€iÓâ»Ú§S®öhÔ¾E£R>ËØ÷íÛµÌÕår*ƒâÍ-n¾ùæ8[T®š1¸ê*ØXù•ËËò“;{¦ Éœ<­ëŸzʹ ~8°ß~±;zþX°hÕ*™’S߆éÏÎ;æT<û¬Å+…ŽEtCºè"çj™ŽŒàÌûðÃÀÿþçÒˆ1Ýš Е-'X­+*E7ÙÔ :$…‚iÛ‚Š_~ù/¼ð‚ý½Œ)S¦„¦ºýÈ1—èæ›oî¹7íÇÞ4âÝwßµÔ“ÃìAn~æ´Åjf@[@Zúv3Åf`)ÉÒ¨ohf/cf<›3èÁÔz‰¬ ½LÈå¥D£…[¼à{ö†‡%nFŒp N¼}´ND@D ‚€Ú¶ i}`ÛÆv:ëbÚ´j“úNÔìš8n$+6 rË-³´l téZªwȵm¹cÌ‘”N-JÚFD@º}+Ö>ÉÄäo1uêT0]ö®»îšxãÞ‚cÖ5 Æû£iSÿ7}ìPû–]žÅ\Ú3Ï<ƒÉ“'£W¯^f4“=§™3Î~ÿÝy˜9RyÆ8W ¦›5+>ŽàLBãïü4kœsŽË.ãOAf®T8ýtÀÌ3ìfwŒ–Ï  €‡Y[[o¿þ\K“žG‚T{8å`Ÿ}œ0‰ûÕ­Ë" qT‹³®hWÑ^oÑ¢EõJpÄNRæ ýí·ß*Žåÿð·ýèQ$Ä×k¯½æ‰Ž¸=Ý’‰9fïÆFô³Ï>«²9U½óçÏ7·€‘Þkï½÷Æ-6š·îºëVÙ6_ 8Ó…‹L·rÅUkAnßYÒïc=¶êÊhKØxÑy8cYSltÖYÀС0àÀÓOg·!‹V/-" ¶-ó‹I‡#¦‡)¤69Ù³â$Ž[oM<)$Ù2¹eÌ1Ñt*{h[ȵmÙc™­’xMhy¿×^{e«H•#" eG Èö­Øû$³ñÇðgLXp²g¹ÇäŽ9øæ€™Ã[·.W:o\Pû–KÚ…}¬mV$ÝØÇz饗f­²> Œç| öÜ3kÅWA}œt’kä;uJ\÷¯¾r)Æ86KÃv ÓôÙe,Õúôq¹V™yæ¾û`.NlÄb3爼ߢPi›mbnResáQlD54³ÜÐ…(ÙH$6 •Ó¨‘sM }×»ˆ@\«Ç]«•1 ÐqˆùBc‰¢íH¤ƒ>ØÙD[ï_Fw=¢ŠüÛ…>¿ñÆ–æ¤+¸_¡- é’Kü9qâD3,úmÛ¶M®Ê|àì’â5<çŸïºIQ•Ï^)¹£j+(jÛ2¿ÔË—/÷„Æ…è<˜ÌÙQ Ìö;Ùg¯dÊÔ6" "OjÛòI?ú±·i¤ï¼óöØcÐò^!" ": Û·Rè“LhÕ=&0}†Å.»ìRue,aŸî‘G–L‹ÍI¥ š€Ú·  Wù?þ¸µC_[v«ÿ™QŽ9åd!hÎÃŒZ›lâ&\f¡Èâ*⯿€Þ½aް<ç0' `ìØÄçÀl2“&9C:ñÆà†3Îð Z´ vÜщ8øòKØÀuì²W®ºwwT€%¼A¹÷^w™þ,±Q2åk´”¤ÃQZ$R؉ηrê¿/˜ÞŒ»Ï´iÓ˜Ý÷ß_|Q)º*øÐN—#6”L·-V¬XaŽm§à‡~¨XÍÙŸ|Àå1˜¢eñâÅ^¹O<ñ–.]êm7Ó‡ÞÖP 1Ei¬²+ ÌÁX2bYì’##éAÙ?„ŽK”w ÷ܘ۞Xk-¯|ý#" "˜€Ú¶ÄŒ’Ù‚bZξIZL›L¡9Ú†še6Ÿûïï^9:¬#" PÛÚŒ ~óÍ7ÁgÞØ©H™@í[©ôI¦ 5Êt8jaƒgìó-Ç`šm›oëÅÎ;—#³ˆ@® ¨}Ë5ñÂ>ÞJ£\cŠ× 6ØÀB6ö—¥XgÀ†UA­K’Éh²tä(†v…'žè„@íÚ<´j•\Åhî°í¶U·e>:3Ïð^4°±oô…—–¬êÖáKª™DÁRæ6SAEæo ßÚ}{å'”ºêªøÎIÑöÕ2ÀHp”Z¦.ccІ bĈUò‡RHÓ­[7<ûì³æ&×Çsóá>L‘6ÚrJvéÒ%TDØûÓ–ìÛo¿­XV½zuˆ­"Ì¡¥ïÑGm®w'Uˆ“˜[9M:ꨊýóõáÔS]ûP¿~ôð’‘Ô ,ó³ýú«S»F/øç`÷Ýa*/ØTÙX[i¹ˆ€ˆ@jÛ¢@IcÑç|p³HZL›Æ1‚Ú…ý蜽ʉ. (jÛ ó*2Ec*\" " )²}+•>É”¡FìðÓO?aúôéބЈUeõUB£²ºÜ:YÈ;µoy¿Uº]ÑÔáú믷Œ[ëeµnÉèZ²zÀ\ÆÔgÌ…Ê™¥|ÍŸ_ùþöÛ0· €iÎ.¿ à'›Ñ¡ÀW*ÁmfÀá™IX&ÏP"Þþt7b½Ï8#ÞVZ'"c6WA‘ º…¹ßFmd³=†UùËdª3¦GóÇ]Ì1%þ²Q¾x lÍ fKkà’b§H·%vB˜N [lÔª½6äØÔì¨PNTÆ2â5VdúÚk±èJп" " Ô¶EÉàkJbÚ Ž“Î®Ÿ~ ¼ÿ¾ÓçÆÚ¿A I“Xkµ\D@Ї€Ú¶Â½Vñ9® ÔÙ¾•RŸdjT«nMw#'{–Sظ®BD@òB@í[^°ìAyOr­‰bêÖ­‹óÏ?¿`ëxÅ–/æÍKþ0­[Gá9f„¥;†9¾úÉ'0‡Œì‹’¯eÕ-/¾Xc —Þ­êÚÊ%ß}çÆ€iæ±é¦•ËõID ï$8Jñ¼ð a{œyæ™Øl³Í–Eûrá…‚iÑB1wî\,\¸0ôµâÎGó©8]ûì³=ôÐÐרï#íȼ˜«â‹/¾°´™sB_ ò)ç¦NSHU¥Ò!ÁQ¢©5>ÆUÊШԶEÅ’ÖB Žx_ÀâB ¦Á愦禓Í<v;¢’$ ¶-¿—uš9ÔÒéwäÈ‘5jx=^zé%<ú裞c„Ò©å÷úèè" ÅK Èö­\ú$“¹ú&Lð6Û•Pe/¿ »ì*erÊ:M" ö­€.FTeÈ!˜={6zõê…u˜- Á*Et*âØ3_‡Xjò„qÐA°Ô:.­Ùر0÷ XzXNs`ñbàw€6m“ó 8ûÕ²y†“&Å>ü}÷ÁR çœ{­È  ŽRÄþ5sø¢sçξo±?Rl´í~|YW…fЄ6ëÔ©SècÜ÷ÈàW˜Ç²€ã³Æ›`)ÐþGK¿d‚‚#Ú.4j”ÌÖÚFD@D ‘í‘Ú¶àù6]ao_ÙÃà;ìà[Z9™…Eì9ÍšÏ=çÜj9„Ï™tÚUˆ€ˆ@)PÛ–¿«ù÷ßc=öðÒ‹yä‘Ö7z8;ì0rÈ!^:pÖì v„*D@D@R&dûV.}’É@'‹z6S£yóæÉl^ôÛüü³{>¬]H²+ºèÏY' "PXÔ¾ÖõÈgmþüóO0ëË&›lbº’ìK¨½¡¦%ÂO"Ÿ§ÿØ?þÈäÀ²e.Å+¾÷ÞÀEÅß¾Ï?wÀ¼qÛm眀Ö\3þ~…°ö²Ë\-n¹%zm~ÿÝÍž¥ƒÓž{FßFKE@òF@‚£Ñ3‡w(˜ ŒŸÉFãÆÃ6ýÊÒˆø„vv«b5˥ɎÚdÂïpÄíó-8²{Œð5ZÔ´†lEƒdÔÉlT¿ü2~:µhÑ2¤¨mK SÂè0ÈAÖ¶mÛ&Ü6—LŸÎûØ@/pÓMÀG¹ôÝ#F'žèÚj3Pˆ€ˆ@IPÛ–¿ËI'£yfûÞ³gO<ñÄxüñÇ1|øpÏ݈éÈéztà毂:²ˆ€1 Û·Ré“ÌôòþnZ'N4wØòq7:ùd÷ŒøÀ@Æ™Ôþ" ":µo©3+Õ= dŽìsqÅW fÍšŸæ‚@.ƒX!šûT9Á%K€pÎDöü ª¥¾ý°,:ž P•JdûÓ)’zúi`Ö¬ª'ÅŽlº4eI„VõZ"" j™ì\Žûúo|6Þxã”üHUª/"HÓmDp[¿U±í¶Ûbà 7 }û¾Í6Ûx/S•1¾ÏsÒmAY68ôï\uUDÕm@¶Ùûïãu[ÜŒx‰‚",sCòò‹&ÚVëE@D@R& ¶-edQw`:5SRÜ{/ðï¿ÀyçUÖŠ·Çë^•KõID@J‡€Ú¶ü]ˇzÕªU³gÁþ¨_¿~þ*¢#‹€ˆ@ ª}+¥>ÉL/û‡~ˆ•+Wb·ÝvË´¨¢Øÿî»1cŠŽºv-Š*«’" %H@í[ ^ÔˆSâ˜å¢E‹Ð®]»ˆ5•_—/_n“%o2ñkCœ~úé•+2øôÝwnxñž{€Oˆ J hW¦>cJ4C~èTÄ`öœ;ïtŸKù_ºÜqp×]ágÊŽlŽ|ør}(¥xØyúsDZÔªU+é½ii Ù²e˰ý'Ožö=ÛÞêÕ«[¶±F–å¯ :,üöÛo¨M/Ü<ÄŒî M›F9¸5«ÙâþænôN2-<Ó©1:tpïúWD@D «Ô¶eççÌ‹mQH‚#ºÍ>ü0@·Y:ï*D@D \¨mËÏ•æ$›W_}ÕK™&±Q~®Ž*"PÚ‚jßJ©O2Ó¿€ &xE”ƒÃÑ”)Çö¶Ü`n…ˆ€ä‹€Ú·|‘ÏÝq™f›c¤ƒÆ©§žõÀw› vþüù¸ÿþû±ÖZkEÝ&Õ…;Yª­·^ª{æx{Ž;ÓŠþ­·€ ..½4Ç(€ÃÑÅ‚NG6¾}:u*+µöÚÀgT~×'‚" ÁQŠ—#R$”ìî·Þz+VPº*èn)ò»q³õ×_?´yRïëE´˜,/òÉ´Ølé¸ïèÑ£½Í9;õ ƒJf׊mb Ž˜gÍ: Ÿ¶œ¡«%ëAÁsŒî°CEùú " Ù"@qæ›o¾YQÜ¿fCÑf9E9´m¼ÎKÌ’6Ô¶ñú|ðÁXc5²v©ép´ÑF¡AƒY+3Ó‚.„¥g…µã™–¤ýE@Š‘S=Ò±€ÁÔ œMX.QmS¾ðåoÛößÿ¬u̦ó·Â”iÿجÃXÈ锩}D@DÀO€U¡ÉvüÌ{ürŠ Ú·Bé“dß)ŸÇým[§N°ŽMZÌU¼÷Þ{ž‹|!M$ âÜÙMMã3s²ô§0ÆAEeŠ€$C€Î/_~ù¥·éÌ™3±lÙ²dv+©mJ½}ãÅúõ×_1ÃÎBm³›”‹›Þ8s­™b*WöÃ2õ6­®¼òʰ¿aöÝrµ©¹œrÊ)aë2ý1tšiqÁìÑE.X·nÎá'˜£~©TBÓ͈–ýUÒç~õUÃJsæÌA(#ÄÏ?ÿŒP†¦Ê-ô©”Hp”ƒ«Éž=öXØ‘.ãfDDv’¤*8б³€sªÁ†ƒc™ÔbMûdEpD…®©rÿ3eòeöT{¨¥ŒK*ÌÊØSµfIÑœÔ1µ‘ˆ@ÙàC|è÷Ž'MÁíÓñ [ÛÆëy­°|ØÙqp•û{PÝS@aÄ5ª€*¤ªˆ€ä”dC¢ZvèQœ¢ˆM ØÚ6^O:éúïcöÚk¯¼ Žèü°ÙêÑÙèÀŒ ZkD@D ” ýîqànéÒ¥”V»&Ó¾JŸä_ýå=‡®1¯ÐÎ;ïœ3Áû˜R­}ûö^h)ÿ…\~9@³ýë®vܱ”ÏTç&…O`Ö¬YmõÜ–Ü5+¦ögÄ17ÿµÞÂÒd•‹àè.KÅ>XŠzÏ>ûlôéÓóæÍ3w½X}õÕ½ ~§¥ [h3'o¿ýv0£KYÄSO> ´h àfƒR§õ$)¸ºâ €9_/¹¦º™>¹sçV´mL—Èþ+Eéà(ÀkˇTZÿ±1õ­÷¡5\DD>ÜG:El^åkäö‘³“ªìcS³mi^º÷RAšfp"u°Îf_œ.céf¾?âÌ9mÚ´ñ­ŒñqÚ4J¿îÝcl Å" "ºÑøï¶Þzko6cf¥–îÞÅÚ¶ñ:oºé¦a×:›WiêÔ©žJ¿ÔgÁf“™Êž@×®]Á㥗^ÂË/¿üA‹ðÅÚ¶Õ­[ׯëÖ¶¥z))n££Öå6‚I—\…ˆ€A€âB“âÞ~ûm 2$ˆÃ”D™©´o…Ò'¹îºëzÏãþgô\^ N"áDÌ|ÓädóÍZµ‚9óI“€[nžxèØèÝ;˜ã¨Tä ì½÷Þà‹A7ˆ~ýúyŸõOtÅØ¾ñLš5kæ=¿E:ûD?ËÒYúÝwßá•W^A—.]<1ïßø™m=Ó§ 7 Ev5oÞ'œpBÆ'OíÎ'”qQÁ@å¯V ÀÆ$Ìþ 6ƒ(ØczéÌF@·§óÎÌAgUè5VýbØÉòòÅàïÀé§ŸcK-.e,“ öòÑÖù¨£Žª"6jaJUªw£EäÃ}ªG|(÷G>­7™R­I`µÕVÕˆÊEZ$Z‡ø¨–-½…Û&ãpÄtjŒÜ»þÈroÛâÙƒ¶eži…ˆ€ˆ@ÑPÛ–½KõÐCy…)Zö˜ª$H—@ªí[)õI¦ËŒû}ôÑGÞîòÔyß}À6Û;gr±÷¥>o»í€#`“a訜Mb“ÒB% ö­P¯LìzÝmN5tÃ½à‚ ¼8Ž9fÌ}ôÑxæ™g@ú¾}ûzir)¶ËÔÞ4{`‚™ÛnÌ81¿a©í-?œ3UˆV“ë¯l,ƒ¯¿Eî·h'’åedf¬Ìî –³=Ë…«8 hÚa–©r ÐÇÍ͇éUüA[ùn¸!¦sÆjê·S™¥ÌqîHÇ#ÿº ?Ïœ ì¹§ï(´¿›=&SÆÇï¿ïÙ$ÒE$aHp”‘6  ¨mKLøssðcŠÃÍy²ñƉë®-D@D  ¨mËîUgz€‘æbËÔ¢tËUˆ€ˆ€ä‡@ºí[)õIfBþÓO?õvo×®]&ŤµïW_¹Ì!ÜÙºN½nT3¡Ïj|0püñÀÅš+“U´*LD `jßPñ¼nC‡õ²ðY1ûaê×6ÚÈO¥[nëÖ­=Rh›tÞitì±Îá±Ç`éQÓ)%Kû˜È gž |öpá…N@­hs¾2û«hkÊwmÏ=x÷]'ÖRwùþ-èÌ‹†€GYºT=ýôÓž£;[ýA›û^½zy6þ呟ëÕ«¶(Õ<ô+V¬Ûzæ!~ú –VhÚtÕÁ-ïª)­œ°åg4hgY+oà[oŽ9Øl³<œ‰)" åM@m[òןGú6­hü’ß7ˆ-9äŽ;ö—s†¬BD@DÀPÛÌ_'Üüi®¶={ö æ*UD@D .LÛ·R铌 )‰•Ÿ|ò 6lˆM6Ù$‰­³· »t9@ʹ¤W\áºQŸ|Ò94¤{”•+]y5kV–P¿>ÀX…ˆ€ µoÅr¥¢×“b#Žs†Üü[­n{D}kœ®ºê*ϬËÒ‰yó`™e\.îoÅšÈ)’’ÜgÎ`ÿý(†¢¢3 ¯” u¢K–L¶—$]6›]}ut®e@'*ÅE pÁóªÏã¯}cùòå9<ï¾6‹¾ËðÍ7ß„—³ƒŽ1±ÌE–o²víÚaë¢}©K‹8_¤*8b¯?(tÊG0£bÌõºë€Å‹ýaÂ,æj<òÈ#ÝF¡íÓ¦ÇZâÞ×Y6M6|™¾‰€ˆ€N@m[òˆi <Ñ,rén938ùR²·%oh•ÏԦɘ fïÈ*ID@ ›€Ú¶à®Ó©1%x•ç¼à©’E@D@VÈFûV*}’™üQ°_õË/¿Ä!‡’I1iíkóTAW†k¯u"#ëBÅOd&8¢‹Ñ{ﯾ DÌqM«ŽÚID@rM@í[®‰g÷xì/½çž{,3V]Õšª6FôîÝÛ$%ePQ‡‚éYÀôiüÜ©“ûÌô¡¼ÿþ ˜Áž{`zñÆ+9>`çe*fàšk*—ëSò¢‰¸’ß[[Š€ä˜@à‚£?Ìê&× \2|̦…ÜtÓM6Ŧ ø‚¹¾/¿ürlµÕV¾¥ñ?fúp?Ÿ˜/ BpDõѽ÷íÛÃüñ… ‹þµ†¸M¤¼˜OÁLGC!ÒZkùÎBE@D@rM@m[jÄ¿ÿþ{Ð"¸PÒ©}û-,}+pÎ9š’Ú•ÔÖ" ¥L@m[pW÷3³ˆ§ðölël­é·Qî*YD@D`lµo¥Ò'™ÉÓd¯4[ öìÃÌa˜ÆÉsbèØÑ¹ÑÜ¡kW7‰dêT eËÔ+3l˜+sÏ=<à§^ií!" >jß|0ŠôãË/¿ì™\y啨Q£FܳHUld¾`[gÆHfx´jÜr `þ¹‰j6´N…K.vöòT>q†;>—3΃4UPˆ€ˆ@‰\pTªü–-[æ¥I{ýõ×ÃN‘©T¨Èõç# Û Î—È‡ûT¡æÎ[Qz5kð’qUªØ!‹¦Ow…yGf™ˆ¿þ®¿ÞõœÌé:UGœ=Ä|œo½ì·Ÿ·þÈ-µméñf:5FÛ¶mÓ+ Ë{Ñ¥—z_>|+D@D Ü ¨m þ/€îFŒSO=5øƒé" " l·o¥Ò'™ÉŸÇ§ÌGmÑ®]»LŠIy_ºÒ>û, „2ÉЂ®µt9êß?å"Íß-<ó À1Q…ˆ€ µoÅr¥×ó®»îBõêÕ½‰)‰·N~‹oî»øá`£¼Ä*8í4`5’/#+[RHtÿýN%ÌÔâL­Æý„€áÃúéˆ#²r("" …N@i^!ºùÅFøœ{î¹^'ëšk®™V©±uôEhÓ·(æGÚþúJÛ™g`¾Òº„Rªm¾¹U÷ä“až‰ÎËоNš4É;‡m#s–|°ó ~é% Žb^e­` ¨mKo¨½.‡#ž;•Õ±œÞõÔ^" ¥E@m[°×“ŽÆ#FŒðD·…Ô{Ö*]D@òO Ûí[©ôIfre>¡SE®G+ƒNLVš§ s żÞCíúM]«¿ª.­o+5j^;úS¡DÁ‘âp6ú&" 9  ¶-}È´Þ§õo‹-Ò/D{Š€ˆ€d€Ú¶¬#­Rà³6ƒsÉ’%r7ªBF D@D 8A´o¥Ò'™ u ޶ÜrKKA¶A&Åde_¤^zifEIl”?í-"{jßrÏ<¨#8Ð+ú‚ .¨8SžÍ™Ü|3¬µbqÜ£G‡¾ ‹®]»Ò0|mž¾QõÄÔjT <ीÉS}tXÈ1ÀG'ÓᦄbæÌ™– ÔZÆUQ³fM<`ªÕ*Ž=¡ Rx_Ýž&6§Ÿ‡~ØÛëßÿÅ„ йsç„¥¼ÅTd¾Øk¯½|ßrû±N€¯hñ…)}c²bZ5³Y“—ÓOX!" "jÛ2ÃLÁÛ¶5rîÝ[YïÿþsϵÌfcnÅ ({jÛró'Àtj5jÔ°þTëPUˆ€ˆ€N ¨ö­Tú$Ó½œ,ˉŸGuTºE$µßÈ‘.û 5Mœ¬™ÍîÛ¿þÒ4ÝOªîÚHD@‚$ ö-Hº¹-{Ñ¢E–Ql8vÜqGì´ÓN·áNÜsðãÀsÏÁ2´T¬Šúð½{ÃÆHw®Ü$g‚Ú?Ú·O\Ñʪûîë^þeú," e@ÀæK(R!0jÔ(üý÷ß»Üpà ±4[%ÿá°¹.ÅL‰bñâÅx†I¹WE“&ML<Û4ôµ`ÞgÍšÖµM›6ÑëÄ´jŒ_tïúWD@D 'Ô¶¥ùKþË/¿ Q¦ô¦¨ƒÚåŸupûíA”®2E@D ø¨m þš}÷Ýwxûí·qä‘Gz.¶ÁQG²}+å>ÉD9Ÿ}ö8ñ³=³ï¾ DÌżyÇ/Ù{ÚiÀ²eÙ9ÝvÙ˜;7;å©È5µo¹&Üñ† ‚ßÿ~w#}—Ç<ÿ<ЫWüã?ù¤Û¾uk€ÉQrß|ì¶pÆ9?´(" ÅH@‚£¯ÚKLùµ*6·`p@èkVÞ·Új+4kÖ¬¢,:1¢â{ä‡eödz–0²EгqBÇIõéÔ1GLPNëAãT¡íE@D@R' ¶-uf¡=˜Ò”ѶmÛТ¨ïÙ„Ù@G4Fä¬v0ÿïQ¯…" "PvÔ¶É_yåï r7 žµŽ " !A¶o¥Ü'âëéÔÙ]tpàÀÂ…•G=çØdLØdV`êT`u*×EûD'ÛwÞqÛF[Ïeo¼\|±/­½v¬­´\D@ ›€Ú·Â¾>ÉÖîŸþÁ½÷Þ‹  [·nUvcæ®»·Þ <ø`•Õ 8i³];`Ì`½õ*çîñ•+a¹ÃswLID@Š˜@à)ÕŠ˜M•ªýõ×–cÔ’Œ®Š7Þ´O7˜*­Q£FUv?ýôÓ-Owe¢îk¯½l¨=öXT«VyÉæÚ´•sÏ=S¦L©(ƒ¹ÆO<ñÄŠï¹þ`&ÞlšæÍË6“'Oö¾ÇL©Æ0ûíÐ_ø ƒ`~‹ÀÕW‡•¡/" " Ù% ¶-3ž!ÁQ<‡£‰Uš[Œ›9›½<ão¾é¬øilh&ŒXk­ÌÎG{‹€ˆ@)PÛ–›«8~üxKãY»ï¾{n¨£ˆ€ˆ@™ÈEûVÌ}’™üy|úé§`Z¹DI’=E@V¤õÛuêT݋ٸ“ÉÈm]ÑàüLº!E3ÁŸ1– Ðhôè< ÊV==-”¨}K WAoÌTj³gÏÆu×]ç=+þù',we•ÙoÉþKýÑ©ý™:U®}â¼N:æ%^{ àäšîÝ]EóR TD@Š‹@¥z% zS8ó믿V”~ã7b“M6©ø^Lhï>ø|¥tHŠ&8:ôÐCmöÊ;–YÌ¥£¥/èaÆyéÛjX Ía6Üþ éšk®ñrÿò\~æÃ-‚ÙGš?Ñáˆï[o½uì*1­Ú³Ïº4-'6'­,PÛ–ÈÏ?ÿÜkwãµm<âŽÁh›M‘8K'Ó »¯e±A­ZÀË/õêeZ¢öÒ  ¶-øëÈ 1L§¶“õ¯­ç¶àë" "`rѾsŸd&$t8ji9[ÖId9”äAn¾Ù Šè<”I0L›6Î)× #ìÙ³²´åË.]€E‹`}È.…wåZ}â! ö­x®U¼šþmö}ýû÷7¡mœwÞy ÿ€y.xNFö Eݺ®³C kWàý÷³œ6íË/-¶¨êˆª@¼wºÑ>ž­6–­HŽ@à‚#æÀþñÇ+jãOýU±°H>Ìš5+g5¥phÉ’%žð(tÐ~ø|E‹šf'tÏ=÷ØfF0£ ÉeœYà292èpÔܬXטA¯a%yö¼ãPˆ€ˆ€J@m[fxépÔÚН¹æš1 :å7«•q¢L¦Íõ‚Î péRg/œ—|æ1ÏX+D@D ¿Ô¶ÏŸÏù|^ím:jð‡×D@D , äª}+Ö>Étÿ(ØÃÕ ëÐìÑ£GºE„ígsR0v,pÜq@“&a«Òúr Àë¯t•· 5^0ÕÚI'ÁÌåx(»S" "P¬Ô¾ë• ¯÷Ö/íéM7Ýdìµqüñ.­hýúáÛñÛV[91íþû»þM¶›F¦«_ÚAKùÞ½]¾¶ß~K¯˜ûïwyLm| ¦W†ö2$`ÊŽÂŒ¡C‡bÀ€¯¿þú+ït ²Bœ%:xð`O œhÆ(g•Òªp·Ýv ²JI•½b…³ñ| ¦ÐŒJõ˜éÔB¥Óž~Š Žý+" PÛ–>\:8R/Kßfફ€]vÖ]× ŽÒ?*ÀÎå#޾ÿ–ØgŸLJÓ¾" "PzÔ¶M™N±÷Þ{0AD@DÀ#«ö­Xû$Óý3¡‹<£}ûöé¶Ý—]æÞ3ý—.IcÆTŠXÞõ×»Ú£.¿<Ó#hÈ/µoùåŸÎÑÙ'Ù§0r$@mÏ d––6ÚÈÒ‰žë bçÌúõvØ!úø(9hL¤›Ì ì»/0eJôm.]¶ 8üpà–[ܸ"ÅG©-ûö6Û °Ì= ä îp”|U·|ì±ÇÂÜ|zöì×= |ï`¾ÝlOŒ|å*˜~Œó)fðŠå(ûâ‹/0oތ׮Z“Ú;³¹ZæUØ­N?=µ}µµˆ€”=·•ßxã s™¯…wÞ9øƒé" " \¶oÅØ'™îŸ Ó©1²á?}:ðì³’éM§Î/¼\}5°Ýv€™I(D@D è ¨}+¾Kxì±ÀªæÓK÷Ù¸ñ/6ž{î¼³©—r›^f6‹ænä?ÛSO¦Ms¦Dçœã„GþõI}ffšCu¶´2f±”x×ÈÎYª£.„¥’I/[â#j (Y+8*Yâiœ;r»Z2S¾Š"FŒ~þXo½Šê2#¡Ã7²´k Ò&Ptm[”˵mÛ6ÊÚè‹öÛ=°qZté}›DKŸxÂmÁq…ˆ€ˆ@á(…¶-šœ½:aÂtìØ1ï“‚’©¯¶HŸ@9´mU·Ù!IM’L€’1ÿùèÕ+Á†i®ž:èÞ¨[5 &þM³ í&" eN Ú· .1Ín)6¢¶‡IJ^|ñsâ«cŸ#pæ™;U6ÙŒd–ÍÒ°Uì–ÚÎÊd+óŽ2Çh²¶}tîì,é/¼–ž¸ï>wBTS)D@D@R" ÁQJ¸´qBT››N>0‡¦PLš4Éû˜‡÷P™z|øüóÏ­©[=fÇô»ïë¯ïRª…êyðÁÀÊ•´ë-Ií×O?írsF«BD@D@rMàëÔýã?ЩS§\ZǬ`J5N\+7„8GŸ?:ØqG`Ï=ãl˜æªÅ‹Ãþü“ƒ»@ãÆi¤ÝD@D@D U³‘åþý&Mèâ~› ŽúZ6²!¨Qc JNq×áÃÓNs•yþy×H&[ÄßÃò¿¹Ôi<¬»®S l ÚND@DÀG@‚# }Ì>ñ29Ľ¯ú—‚£ ,½ÓÀ)D@D@D Ðᨹ¹ò­½öÚQO‡d˜Óœ¦¡¾k6ƒçuó¤¾õÀŽl¹%…K‰€ˆ€@`<§´Z0½·BòA€Ø9™™ýèòá+¯ÖYÇprò†ú×&ÿù×_9s€­·†—&"ù=µ¥ˆ@1˜;w.ø:$¢3s8Љ‚r7ºþz—væÞ{=r8ž› í#" "PšL£‹×_wn{Nlôn½õVÕÇ%—üIÓɈâ¢gžqiÔ`®ÑTó˜î¶›Ëù²W¢š—–MT +D@D@R& ÁQÊÈ´C,ÌÉ:þž5pøš[¢í}ñ…¹m'+}(f¿YžïïMMtl ›]šý™ §Ÿ^)6ÊÆùrl÷í·-¶ÈFi*CD@D@R'ð†å]ß,ü¶ß~ûÔwÖ"ƒ€÷£O·’‘ÌÐî§€›"#¾¾ýÖmÇlîþ[13Þ 7Tਣ*?ó ™xà¸Äï¿t Y²¤ò}Ñ"`Þ<'4bYŒ¯¿Z´pŸùï²eÀO?[nY¹LŸ²C`ùrà‡œ`㯿¾6ߨ_?¼|f¼ ˜¿vmà¿ÿÂ×雤J€éÔíÓµ ]u@þ60 /ÒM½ª¨˜o6ž‹ÿýhÐ æ&Z!" "  >gµÕ*S‡0G 6€¢#¦' $ø 0r$ðì³®S”öï¼<òH€*Ü7Nï°,£o_§žâCFÄÇéUD{‰€ˆ@ñà¨ø¯aÁœÁcVàÂoÎÂv;Î@#ŸÛÃÌ™3­oIÌ”3sªˆˆ€ˆ€$I`âĉ6Àñ_ÌÁÖ¥Kݤ˜“NJ²À$7ãCýî»'¹±6,Xf#ªü1¶¡L+ªl ''Ó½(^PèÃÉÇ:»î¾eNŒÄ¾˜%Áœ‘í$ù×1-N›lâR!Ñ•’/ ŸüñàƒÀÅÃþ—]VµþmËñ3S ôðÙg.CE¤.‘“ÑëÔqׇ±iÓ*_?þX•ØÝwçž¾|¯½œ0‰Kïº+â…oªo"@¶G4|§h‘¢  ›G‰^Rm " "Þ»Ñ\ˆ÷Át]d ßwÜṿŸxâ‰Á•6ñTôþû/,_›uíêÞ©>ÏFpV§fvfƒ¤Ê(c•ñÅÏö©Ïx{¶Ù M±» _Lž<ÙûÖ&U[C_ú(" " …D€éÔmÛ¶Z­]vqƒ-QWÚBÎØž:5uÇßXåi¹ˆ€ˆ€ä‚À;#•+W¢S§N¹8œŽQ@˜½€b ¦+ã‹sŒB“˜™€)Èøâ6¡÷ÓN«Ü†§ÂûŸ¿ÿv÷@tò‹¨9ÁØæ*yŽ5~ס ѺëºjõêņBav³f±×z(0e @a ÏÁï T«Vìýük˜Æ“Ÿ).Øj«ª‚£SOV¬p{¬±†;rò¿jÖ8 ¸26̘áÜŸüצiS`¿ýüt¦´£èˆ×‚ëü‚#ûéÀÑGWu%âuàucŠ(–I>k®é^þ¿‘Б(@bŠa35Q™ýñ)D Ÿš±¦ýѵjÕ*ƒRœÛÇ*eîžFí," "PÀn¹Åé~.¿ÜU’®F44hÖàoqÕUî¦7ÏT:ñ&^!" "Pp$8*¸KR¼š1y)ªãolÚ}¯°“˜4i’÷}Ûm· [®/" " "P¬ Žª&L.tƒ)‰¶×z(ãÇ÷ª±7s|*ŠŠ3p.Ýg(~¡K ÓU%C‡V¦NíCQ(Š NÎ<3|ék¯ý0(D¡ Ž?Bã5lè_“ÏòHP¥«\,Èüi*KQ1ENÀ, §Ï­Fkþ„5šlv2Qáܺuë°åú"" " ÅJàóÏ?·ØM±Á¤u ä;xï= ™1[¦h³çxtï`(­Êh'H’G›XΩL ’<œ6Ë€E}ððá‡À'Ÿ„ ƒºuž~:ütæyé%—Úìá‡aÏñ•ë9°ÀA†Pº2¾SXCQ Ó¡Q4ÂWè3ˆ"Ó Õ¯ôèáÄ0§œRYv1~bj·hÁ”J–u× Š¼È'ô¢Ã?ÿü30b„{Q˜•jÌž \r Àôdt†"s¿x‹eRLvÆ.­™¿| ‡ž}Ö½x=èBt<¸ÿ~`î\—½‚×B&¦˜£#_L9t)ŠÔs~x¬µZ.¹'0}útse[€öíÛçþà:¢ˆ€ˆ€ Õ/ºÈUúÎ;ï´gåèß¿¿RmÙuTuE@D AµË´Ì™ÿlƒYÏTD0¥Z3›ºF‹b…ˆ€ˆ€;?lùW_-þûîç (ùŠ˜R„ß9ø/8üºë€Y³âmU¹nôh7ƒyêMÄìÒ¥Kþ+¤ˆ€ˆ€ä€Gy¿¥Q_Ÿ¥Ø›·±0_Påüý÷ߣ§O*D@D@D <üð,üûï4¼öZ5/UÄV[Á\üœ­ð?¸Ù꯾>HyÚLy‘J:5΂çV×®‘%黈€ˆ€ä†À›o¾iBÛÿЩS§Ü°HBw:ÿ„Òƒeë4(D¡[SyQüѳgxÉÏ?ï„$ñ¾„©Ë((¡Ðˆ©"݆Â÷v®<6SsÜqÝoÁ`JºÈ à‹×’©Ç˜rìÛo+·0#OpD÷¢€}ö©\GÙ¾ûºWåÒªŸBæœ;W]÷Ê+ÀãžQôÄTo~—«ª{h‰7Ohýf‘ŽÃѽ÷\tìèÒ7 Õ^D@D@’'ÀçÂüÑÜO¯²I—ò_¶@IDAT«%¿£¶(Y•ì¥Íí‰Íg½žMw¬và/lj%ÏmÚ´ [®/" " "P¬\Ϫþ>xV¬hjnGái,j×v}ñÎÏãÑ™bíÃlÍ›»ÆXÛh¹ˆ€ˆ€Ià ÚçXìL.Ð +RÀeO™œy¦ëD¦+[¼Ø¥¡Š¬>…D–©¯¿îœ‰~ÿ݉¾ù&|Ëqã\:2.Ýi§ª‚£«¯úöu©WÓé÷ç>L§¦È/º1åÅ?¡Ôl¡5l¼õж-ÀôdÙ –,ÔÍVÏvÉ*O “Gµíá­9´Rˆ9s€‹/Z´pé SØU›Š€ˆ€ˆ@QàD l/¼ØzkWõáÇ{ºwï^Tç¢ÊŠ€ˆ€G €.Šà*«’ —ÀŒ9îO©éæÖKé‹Iôô¶àÈEE@D@Š–gû-§üÃ]wíÎ0g,YL O|ÄYáµj¹åÙú72F¶ÊU9" " ",ñ¦ŠÙܾ&Mš$»KYmÇÌ’^½zI][8Õ´bE8TkÕªáGóæ…??þXäþûÃbºì œR¥J>@¾"v‡£¡C‡ ÀÍ7ß\¤ëì"ŽŠŒ.µ õËÅÚê"ÍZÆgŸ§_,ð@Þù8@'€ÃQà»Ð¿ 0‡£,}ut¿ýöóo%© @ ?,rë­"µkÛ•?KU]s¼ Ðû¨Œ;m«³Å®Ðfц.1$‹~Ô¹s\vv @i%0nÜ8)W®œqÄi-7¿Â®¹&°CÑ·lEž{.,ö6®Eâ·%K†ì¹øÔ©áeq’é6]&$@ÈlæpTA½Uór¤µ@ g#‹l„³QfZ@"æ\kÑ`-òúÈ‘¹‰Xt#Kgæ­H{3dŸ}D^}U¤råÜJ9@CÀ¹ÃÑ›o¾);wîÌ`4$u¶¤Z«V­¤bÅŠ©_DN@€€¬_/2lX8”°…Óÿ÷¿9Ò–IüÓÃ:›ê½ö ‹‡jQ@(4mºîØÇúzë!‡ Ÿ_h_`N¹öÖíc‰tí*bA*ÌáèûïEî»/ü,[ý£ÔV‹tê$òì³¢ÎR9•°(G$@(½6mÚ$Ÿ~úiȉ¶Zµj¹@|óȉ'оd"bö$¿Èy¹.æ @ €,ÚzŸ>aÛ÷þû¹—«ÎÖ›°_|1ôòåᇞz >XdúôÜo‚¤®œ€ ÎŽjÖ¬T³¨,2âo¿…×5¯R%¬eݺu2þ| m¯±íI€ €زEäôÓÃQ†þúëOYºt©FMа $@€@) 0qâD±{»Þ½{û¢µæ”kFû›È˜1"‘ûO["MŸËwŠXdÂ#DfÏ0@äÐC}Qu*@> `Ë„nÞ¼Y’-§öÇ"}ûŠ”-+êl^^ÓU¦ € g,VÄ¹çŠØ —fû’-Vb÷„ 5ûu×]§Qdõ†¬0©°ù £›¼€ àz E‚@ñ<óŒ…RÙº5GE72ÏçöíÛçd € 0uêˆ<ú¨ÈÙg‡—S³ê·‰]ÿ,`í¡º€ ÂxçwBÙ?þø\—Ùi h}@+ƒ£æTd‘"ÎF±Å4n,r÷Ý"‹‹,_޳Q,¶!@Àì‡M½zõŠÃ±c‡H¿~"¿ÿ.òøã";Æf€ ‘zH䫯D éÞ=y#Ë©ýë_ÿJž£€ Pê àpTê‡@ñh £Ð[¦±Á¬ÌáÈR;b0 @À~þùçP=p8òEwP @Hwß}Wš6mšËÙVWZ“Ë. G²eËlù2[ÖÌE²·mSùò‰Gâ÷m)œZµâ±@0‡£½÷Þ;$±4ÑàG!Ûf/U’ @™NÀ~×»þz‘-,ºût (Q`Wã-*à믿.x ´nÝ:Ó‘Ð>@("ŽŠŽËv˜;WÚV_(½Õ'Î1éÇ íá( ›€ h‡£¶mÛºT€ 3fȼyó’.§foÂΚ%rÛm"< b_¤K‘{ït›Šöüó¬]+rÕUáõë‹.“~ÎB€ "0}úôÐ’0É–SÛ¾=ï¾û ÒÂy@€@f¸à‘M›Dúô+¼¿ÔÑ0ïÙvذaz¯§7{šÞ~ûmY«7gD7ÊŒ>§€\Èr¥½¥„À+¯ÈCo©ôwßiƒˆ6ÚŽêÕ«' 6Œc€ $‹‰ì¹§èúäáZ›ÃÑn»í&m½ @ à Xt#K‰Ë©Yt£ûïiÞ<ìT±¢È‘GŠœq†ÈÿýŸˆ-µöÜs"»ïº¼HÿÙri#FˆX¤¢OY³¦xúŠT .‚ Œ"YN-™Ã‘9mÙ"RP½ŒBc @ ÔxòI‘O>¹è"‘wß½ZW0©!:t?üP÷Ã÷é¶Œ>ÍÊÊÒeGuÝÑdé·ßDj×}`šì,Ç @ ” ÂQ)éhgÍ´WY-5iþÔÿ³õ•V{kˆèFQ$l@€@ÀØò-fÚÎ;/§âæpÄrj9<Ø‚ Ì&`š«U«¦ÎDGÆ5Ô~Œµ÷MôÝ1g#KíÛ‡Ù[²}dKk‡`‡Ïþ}¦-¶’é²e"£FálTx‚\@‰ÆŽ²k‡~xâ©Ð~Ħ%=ÉA@€@†X²Däê«E59öØOä—_~‘ ôFn„ ²zõêPT£K/½4äh4_×]ëÕ«—Ô·°³‰iòd‘ƒa-ÒD2ìC(u|áÈ·/_¾¼ØÒÅb»“Ü0æÊ•EÃEõÏÕeÖÖë/µíì)3 € @ºŠLhI˜½÷W~ÕªU¡ï$½{÷`k¨2 @ pìAó_|¡Ñ…N” *äºØ¢%F0ŠD%:öX‘þýÃË­õè‘ëÒ¤.¹DÄòžrJÎé˜wZr²@(5*ÏìšÝÏEìšE4Âɨ0¹€MÀ"ÒÚ‹–/¼ òè£C¥\¹rrÙe—…Úd/œX„ÛH”Û…pÀ–ZË•ÞzKä´ÓDjøæ/W@€@i"P¢Gæ”òÍ7ß„nøZ¦$þÈ‘#õmF}±˜iæÌ™ÅÔÀåy°G O‚m95KD8Ê“' @ÀçÌáÈR›6áO‹nÞßu |˜ÿ!@Iàý÷ß—;v„~˜-lÍi¨cGÀŸRúì3‘áÃE6lˆw8Jéb2A€R `KÄlß¾]"Ë©Ùj/¾(òÎ;"{ì‘‚²@€2„ÀÙg‹tí*²sç,ùàƒô¥Sd¯½öJÚº& ¿ý…2Ùo‚çœ#R«Vx=íý÷Oz-!@ ô(‡£ß4*Î#<Z ÔbZºÄ^iLH¶4ÉßžŸ{¨|V· Y)R·n¸®?ýôSh‡#÷µƒ ¼ ìò/’ýö çÁá(oVœ Ì#ðŽþ[¦L™è³Ö•1÷|µ¸yó‚r䜿á[¦íæ›sޱ@ð’À{ï½RgËÂØcËÁƒEÌVÕ¨áe)è‚ ƒ@Ë–"—^ú FwÏ ‘rÚ¹SÄ<–4r èR¥‚³QÊèÈ@ “ ”Mgã̹èÎ;={Ê[r/âläª5..Ë©¹¢«z5Ìþ¸-‡É“‹{Æ… ¶Gåõ‰ñ¾ûîë°pTC€Ü0‡£J•¡­”éÓ§‡ k yä®h4C€J”€E€°H|°Ô¯_?T—ÃQ‹Î=×Ûª}ô‘ȤI"¦·0NJÞÖm€ Évê£Á¡£†ßÛCÃÙï£öŽ«-%Sµj&·œ¶A€’°¥FŸ{î99à€¤[·nÉ3%;zï½"&ˆ®Á&úCo²ƒ RH mG4>ú€ä™gž)²£QåÊ• ì"[‡ÛÖ}Qãâ~÷Ýwòì³Ïx ŠH@#U-¦R§òF]/G‡9µnÝ:º&zζ @Á `Kª©)ÓuÌÃõµG5ôõ×=÷Ü3  –€ "˜¤@öúøãjÐ÷†dÑ"‘ŒJycÓ&‘Ù³“g·èFúžÜxcòó… —À·ß~+üñ‡Xt#Kÿùȯ¿ŠþÈZ\Í\@ð?õëEúö™:5§®O>ù¤.i½A ”s° ­~߸Y8ø»ï.(7ç!@ HÛ’jW\q…Lœ81)Úºº—EÄ)(Ù[––æÍ›•qãÆÉ²eË¢—nݺUþüóO}Z„'¡Q-l¤D@×j/¤Y}ÝUª„.Y»v­Ø’yÿüç?SRA&@€€ßظ-Gnë™GÒ õ@"ºQ„Ÿ€ ÉÞ}÷ÝPóz÷îmæ7߈´m+rñÅÑC)mØ ê:…xõ½”¨#¯]üöÛ"ú°\~¹H£F)©# @ Ð"Ë©wÜqÑk‰ªEÁ d0õ·U‡[Ñà á+;tP@ˆaÆÉî»ï.§vZj­··H"¿ùi°I!8DjŠÉ@™@ -Ž^}õÕ¤ÎF‡~¸˜a3G¤ÝbCäì"[¦L™\Œ4hZ&ÍZnÔ× í¦±_¿~qù,ºÑwÜwŒï l›÷»,–=¥é^‡xWúIB·u_Û·o9Ä' @ P~ù%b?²zÚŠ+BoÄâp¨n¤²€ PDæpÔ¸qã¸{:]‰FÆwJE½E <ýt[ªôñÇs®°¥l,ªQ}oåºër޳@ðš€=;®S§ŽtîÜÙkÕèƒ øš€E52¹ùf‘Ûn Wu̘1¡ —\rIê«”üßÿ‰ØSSb^K$@€@ çGë5LÀ!CbŠ oþïÿ“'žxBþö·¿IVVÑ-U«VMþûßÿÊóÏ?¯oEæ¼iëšá$¹#ðûÏke§”•¦{çD§²åÔ,ápäŽ;š!@À-ûQÔ’E¶dË©YÂá(„ÿ @ ƒ Ìš5KLb£Eš[¯^d«pŸ×\#b‘$þú+ç:}'Iô]]]Dß)"A€œXºt©ü KÀìµ×ÃúãªóÇàNÚ€R@€@Q èϯ¢AÛå–[r4<ðÀº¬uE^›bøÚ÷ßyä‘#¹êªElA€vp~§eË mÜhKn…“E-2¤”CõE.,àóàƒV›÷ˆ”-›Ó¤[o½U–,YRÀ•œ.*ù³¶….mÖn·¨ŠˆÃQ»ví¢ÇØ€ ‰€Ýˆ[ŠD8Âá(̃ÿ!@ ó $[N­¸­¶(Fö2ìàÁaM¶Ìš½a[½ºˆ9#‘ @®Œ;V#±Ÿ(S¦œ!×^ëªôB€üK`ï½sê6eÊ™}úÄój§uëÖqË«mذA^~ùe¯Ô£'À‚EáÈTM[hœü]É–T³eïLH€ °€Fú¢O(ƒÕ‡£ ö"u† ¢xçwt™³*rÈ!GÉÕWÇG%*оÈ5*D¶D^xAdæL‘+®]â&ç8[€ ¯ ¼ñÆdU9BjÕÚ)=äµvôA€üE`áBÑ y×É¢Y4hPÞ™"g,Dí™gŠ,_.2|¸èºÛ‘3|B€â8u8²°µ_ýu\guVܾ×;Tg[õ¶Ý•ÌáiçΑ]>=$0EÕ¶¦MÃJóôéÓYNÍCƨ‚ ô°GêÃ,åvùÓšÃQ­Zµ¤aÃ†é¯ %B€ÒD`Íš5¡·]>úh"úÓl®´lÙ2yå•W¤{÷î’Ò %}ûŠR‘þýE#=äÒÇ@€@„€S‡£©S§FÊ }vìØQÚ¶mwÌës6:餓¢j͈~õÕWÑ}6<"°e‹,ØP/¤,âp4gα¨RíÛ·÷¨Ô@€ÒOÀ‚#îzá'T¸9µ‰¬¯–þêP" @ ->øàÙ¾}»F«(O=%ò÷¿‹\|±·E¯_/rè¡ZÖÆ–T#A€\xúédÇŽ^úœr†œrŠ«RÐ @ðÏ?3F¤W/Ñ—&s×i¸F)2g\ ÚRºí6‘§ŸõÚM);™ @ ôÈrÙô+VÄ©?è ƒâö]í´lÙ2Nõwß}§5õ©&É;›q4•úUÖkÈýj!½¶œš¥”¼£C9ù€ à?;çÔÉ—W¯^ÃQ¶ @ C ¼ûî»Ú²æ2jÔ‘¡(Ï='R¦Œ·Õ€¡%Õ¼ÕŠ6@€@nÏ=·&tpà@]/›@Èp¶$vùò"wÜ‘»¡öló!][Ô~;=þøãsgHvÄÆ>$M–‡c€ %àÔáh¹­í“ÒµIóæÍcJIt|Š;ÉNÑèz­óë4‘f²£×ÿøã¡m"E‘°@'`Ñ,¹ŽÐpLT€N`ÇŽ2vìÇú2É'²qcY=Z¤~ý€7ŠêC€@©&ðÃM¤lÙÕrÖY-J5@™Oàõ×EWzù÷¿EŠr·÷¿º®µ-¡ýøã«mtºðMîÂ9@OÀ©eItôÙc=Ò´E‹øÉDǧ´T"à ɮXIöíPQ9²R´¥æpT¡Biݺuô€ ˆ8±¤Z{‘ºC€@A&Nœ(þy•:µ -wvôÑ]Áy@€€ |þù"Ù²e_iÑâ)Wοõ¤f€ âضMdð`[²ú¦›rk›={¶Ørj]ºt‘ÓN;-wŽ@€ŠIÀi„£õë×ÇU¯–ÅO/D0`€ôë×/zE:u¢ÛùmÔ¬YSo&Ëé:Ý;BÙþøãü²s®,´þ¸qñÚ’jûí·Ÿ†mÔ¸$@€@ Ì›^ç¼råpåq8 `'Re@(4aÃôuX,íÛo”[o­Rèë¹€ à'>¸@«ÓHN>Ùé»¶~j2u RJ@ƒÉœ9á¥ÔêÖÍ ášk®‘mê•4tèÐÜ'9@ð€€S‡£ÚµkÇUÑÖ -LjР˜6­[·.êld×nÙ²¥°*È_HŽñ·ß~“#Ž8¢W’€ à=zˆ¨ß²üðC¸NæpTWïÖë³®Œ:‰š@€€§¶oß.ï¾{°êÌ–_¬"YNŸxZu”A€’?^Ã<È&¹âŠ6IÏs€ Ö®}aDdÏ=E ÊÝ"‹d;fÌ9ýôÓCŽâr|ù¥èr%"… §ƒ@€€púšGbD¢¥K—¦úªU«âÊ)ld¥¸‹ÙI‰€E7²Ô¾}û”ò“ € à76ˆ:ÏŠì»oNÍÌáˆåÔrx°@™Gࡇ¾Õ7^–ví~Q›—yí£E€ Pº,[¶EV­ÚOêÔ™"»ïnŽG$@€@f¸ë.[àåÿ‰Dk´4;;[®ºê*©X±¢ 2$r8üi!Þ{õ9öØøãìA€Š@À©ÃQÆ ãª4iÒ¤¸}W;‘åO"úŸ"ÇùôŽGÞ±D ”  DoÂ%úcë’%KÄ"øápT2ýA©€ ÷Üc?ÆîûîãGÙô§@pI`øð_T}–tïþ—ËbÐ @(Q‹‹Ü¿Èþû‹œ}vð òý÷ßËå—_.Íš5Ëɰi“È)§ˆXx¤ÛnË9Î @ ˆœ:uëÖ-®Z“'OV¦FÌq?~|\ ­-, ÉS=$rÝu9*üñÇÐŽr˜°@Á"`Q,ÊÑ•W†ë=}úôÐGÁêGj @©˜4i«,[ÖF£@¼/=z4NýBrB€|J`íÚç´f{kT‡¦>­!Õ‚ ŸÀM7éâ¡ê;t÷ݺ”MÂ/½›ôÄuú^ݺuåúë¯/ì’KD¦NùïEŽ9&þ{€ "H0CEÐÏ%Mš4‘æÍ›GslݺU2O‡É–SûôÓOãJèÚµkÜ>;Å'ðÒK"Ï>›£ç»ï¾“=öØ#ô&ç([€ `°ôHâHÄDނՇÔ€R'°råXÍ|Š\tѲÔ/"' @ÀÇÞÿ}iÔh³rÈ~>®%Uƒ ÀÆ"&ˆ¾4"ò÷¿çÖ3tèPY´h‘Ü|óÍR£Fœ #F„Ø;î8QO¤œãlA€ŠAÀ©Ã‘Õ«—­“^RO•H4œ˜ÃžmÞ¥‹–n°ð»R­Zµ4¤ Æ$yJÀ–‰Da\ºti¨O:ê(OË@ @ $ L›6-T<G%Ù ” @. ¼úê+R¦Ìh¹øâc]ƒn@€@ZÌŸ?_fΜ™ëytZ §@€@šT©"2c†ÈÈ‘¹ \¾|¹Øï¤­ZµÒû¼‹s2|û­èúj¢Q"Dž^ôF0ç[€ bpîptî¹çjxö:Ñ*îØ±Cßž¼HæÍ›=æÕƨQ£ä­·ÞŠSgå—+W.î;Å$ðÃriÇ/äìþ )zï½÷$;;[z÷î]LÅ\@ð³k~ø¡Ø²¬~˜@È4õµØwÞyG,"pãÆ,§–iýK{ ”FcÇZä>‘ž={–ÆæÓf@(E*V]u$wƒo¼ñFY¿~½.µv·dee…3X8$ …dNFo¼!¢H€ ¯8w8ªV­š 80®¾þù§œyæ™òÙgŸÅ/ꎭGúÀÈ-·Ü§¢zõêòÏþ3î;7Nnü «\x䬲wß}7ôÅåØcy+Öº¨€  `¡ˆ|PdWP#ùꫯdÉ’%ròÉ'—@m(€ àž€ÝÇYtàÓO?Ý}a”@pL@ß‘ûïo /žvÑ%ft @ ”øôÓOåé§Ÿ–îÝ»Ë 'œný“OŠsŒÈöí"cƈtèPʨÐ\@pMÀ¹Ã‘5àÔSOU{¦-&­ZµJ.¸à¹é¦›ä·ß~‹9“úæêի塇’#Èÿ€ "p×]v¾]_Þ¹]—Sû_µŒ¦@€@i&°açÚü/䢋:•f ´€2ÀÆ"ˆþ^ŽÐÛÄÍ›7‡‚/Ì›7Ožxâ 9ºeK‘C™>]ä¼óD˜)_>ö¶!@žH›Ã‘ÕÚœˆžÔõBÍè=ðÀú/yì?‹f´fÍš¦µYYYòŸÿüGþõ¯æ2ò’ÀE¿^!Ó+$“õ…¡÷ôÕØ–ú¦U«V…ÔBv@€€X„£ŠEZ´ùßÿXNÍ?=CM @ÀkÄOŽ;îvu°] ¹ïµ~ôA€J‚ÀìÙwI“&[4j­¾(I‚ d‹Åн»HÇŽ¢K‡æ4,;;[Î=÷\ùâ‹/äÚk¯•þçŸ/Ò¾½ˆ=è´0H‰@pL ­GÖ–2ç / -¡fëˆ~òÉ'bF±8Étþío“K/½TZ·n]U\[µkeÊÖ¶²U9DÅëd¾˜§ª|¥R_eJe¯Ó\U¨Ë;‡Æò»ú9Îëvé³{Ÿ·Tìy 9 Tñ:™þKU«ì¡òí®Oý A ‘À/:Y°Eõ…E7²ó'Ÿ|rb6ö!@AÀÞ€­¨ëˆžtÒIÑ@¥›ÀÆ¢Ï(ÇK… ¤G¥­‡ RAÀ8ØJ2Íš5“·ß~[*WvñcA©@I#!@À®~‚/RÕ4h ½{÷I‘p‘s ~ü+TÆî¶Ë o|%§œrŠ”/oaJ ™–kþ¾*úã®SqÅNU“‚KÀ–S³´ß~:eÜý¦˜3íÑGÛH‚ d ôk¤~¼ì²U2aÂ9þøãCö.3ZG+ @ 4xòÉ­òÑG/ÉÜ U«V-Í(h; d[æ²ËDî»Ot…—œ†­ZµJþñ„œŒÞ{ï=©_ßÞP&A€JŽ@Ù’+š’ƒH`þ/ÆGd£.¬f‘§ÌA¬Hé½j²Êã*_ª¸J¶tS/•³TÖ8(äÕ9HžðÙ÷ºUôÍ*OÓÖmú%SZ© Œ9æå¦9Íܯò€Êo*ÿSñ2=ªÊÌÙÈx}§ò¤Š9…x¬/,RÓ³*W«¸Hö§p»Š9NMR¹WežŠÞx’lìQ9VÅÆÀ›*O«ì¯â2Ý¢ÊTéìa!ö7öUÌQZG7­MTNSY®RÜd|Ôa$äldQ§4j S¹IÅÆÛy*$$!0cFø`ݺËå믿Ö%Î ½›$+‡ @$ððÃ"cƈŒ=IvìØ¡Ëˆö d;¨4 @ –Àè-ÿMöe“ôéÓ,öÛ€ @¸òJ]$à-‘Ù³ã›qÁÈ’%KäÑGÕ•Óö?É @ àpTЋSäæÍ›Å–žÛ¾}{qÔùÚóí&^Ç_ö•”-[Vzõ2ožB¦5šÿE•¶*åTnVq•ÌÆœ€V«Üåq!ëUŸ9JXzUå[ÆËO¼J;U‘ýp®Šuy#•î*¯¨LPq•,*L'•¡*æ´áE2'&Ó»ÊD•&*.Ócªü¬„~×ýðN8Q„ÝJzÍ»*STR±¶õV©býSœdÎ9'©\§b4æ,cû^§—U¡9±¹LSUù*ç')ÄÚfNgöwsºJq¦µ³õz+£²Êh•×UvW±t‹Š9 Y{­<’ï”´m³Gº²ŒLú†.­–­ªûøŽ‚ `(iÛKkÝ:‘§ž²H~;Õéè2©]»v(ÂQl¶!@ð“m‹Ôõâ‹õý¦¿ôfN.Ñ(ì‹æ€ P(~³qãÆ‰¼öšè3J}Ù^HÞ•žxâ }‰dt(ÂÑ?ÿiË- @%O «ä«@ "0iÒ$yöÙgÕ“yvÈÙÈò—)SFêÕ«'ݺu“SO=U:u2ï÷iþRó²ùú‡ÑÒ¹sg©[×»2ÕÔüæÄb;!æy•É*ÝT¼JŸ©¢Ãw)³ï]o¨˜Óƒ—©š* RUÅt·WyHån• Tª7]© Ìy–·*·K™E 2”•»ö‹ûñ¬*8UÅÚIæŠ8\¥‹Ê%*Ÿª'“kUÌÁÄ–‹8‚è¦gÉœ³òs¡´6ôV1'*} U¤d1±³¦9OÅ&ý!GÚ©˜~cWX§*‹ddý}½Ê\•©˜ãT•di’´ˆGö7•jÚ¦?TyZÅÊ2Gœ×UòK?éÉ6*‘1˜_ÞØsvým³óUÌÙËœcS?ÝùRÅþv«Ü£R”dKælt—JVæs*6þÎL8Çn‰ð“m³G­ZÙ[CoJ¥J•¤gÏž%Æ…‚!@ ¸üdÛb)>óŒý«_O»¼)|°X†.Uªäõ3öJ¶!@ ´ð«m³~yþy œl‘“õ­¯~ýÊè=ÞÔ‘ @)ð«Ûª¿ØRjvËv¿ý´+Íš5K—ɾBÎÖ%ÔFX@]D£DNó @(1X£C_pÁ¿ÿþ{ÈS¹ÿþ2yò䨳‘]iV¬X¡7ÖoÊgœ! uöêªã´àÏês°]Ö¯ÿ¥xoÅç7ª˜ÃÍ*^¥UÑ*Æ’ò1*}mÇãdAíÒiNw«lP¹i×±â|< ?¨bmÑ ¢ŽÍt{¾Ší¹Wõœ«ò*‰é`=p¡Ê}ˆSät›^iÎFæˆ3A%™³‘µÇ^DûR¥°iž^p…Ê1*[ò¹ø@=WWå•ßòÉ—xÊœ€^T9TÅÚ‘_ª¯'­¯Ö¨˜³~çO9Ý©9«˜Îb•GUFªäõ[Ð÷zîHë£T’±½Te•ãUìoâ•á*ù¥Oõ¤±»%¿LzÎÚ¼:!9C§ò•ÊÕ*eT’%‡Æ×>ßH–a×1Óÿ¸ÊQ*‰Ó]/=fÎY‰ÎFz(”Ì¡îV•Já]þ/9~³mv¯Á¥E‹-2qâD9æ˜c¤jU0$@€@jüfÛbkmÏ RÇîZµ¶Ë'ŸœzQå Sý«‰m@(MülÛ¬-ù÷¿³¥\¹²Ûn×Ê}÷ÝWšº‡¶B€@1øÝÆ *2s¦þt¦¿5inè¶mÛB¿ž¾q£<³j•T?^dÞ¼bPàR@€€wÊz§ M^øC!?çœsäûï¿OIíxý‚Ñ·o_±ëœ%ýR³`óîR?k™±Cz÷î]ü¢öV昡ßä³â«“µª£¿Ên*G Ô¦¬âxÍÙ]ÅœN¦§|UîŒyæ*•}Ul»‚Jl*»SÄmcnŽFû«Üž‡Ž;ô¸9ј³ˆ9”&½ª™M·~1-ÏfåÕSI–ô™¤rŠEà)(ek†TlÚz@ÅœQþTÉ+Ù˜xRÅU¬œT“õ¥EÅ™šâårÏæD”j²ºWW1§µßU¨ä—Г}T^Sy:IÆzìkãßRÅz̉©Ê•*o©äÕ'z*”ºêÿíUl,˜3_lúUwîW9FÅô>¬›ÌÁè •Ž±“l—×cÖÓq®ŠÞP%MíôèÅ*ߨLIš£põEùBÅú˜”~´m*èª~KD—}9´\)Ë©¥e(P Œ!àGÛ ÷Ýw5pæ\s8zUíÜz6lXhiìØùDšÝuWègœìŽ¥Ìûú£Qƒá“ü@ð,Ô*$xõÕWÅÖc¤òåËË3Ï< 9fŸÝºu“ÓO?]Î>ûì¨s’­;ûÚk¯Éi§›Õ“í¿j5 ù6lÜ>Gú6ºÑ6­‚9,¦b#±©…ò´Ê§*ÝUŠ’ÌÂIÌ©äÂ<lß•ÇêrPyò:¼ROœ­bߪÔSI–L÷T‹Æ’jZ¦Û%ËõÓœ^ômdÙK¥ d:MTòkÏz~ŽŠqŽ$sl¹9²“ϧµÙúæq•sUË1‡I*Ç©˜ÎHº\7LRu ùæ5v¦'’lÜ|­2Nå“]ÛvÌØV¹XÅÚ^˜4T3ÛX±RUf«ŒW1ý¿ª¼ òO•HÚM7®Œì¤øi8“U¬#Éœš©d«”S¹~×¾~„RåÈF!>kiÞ“ä7Çci|zªØïJeUŠššë…ö·ÕWå»”´ÔÏ«˜þ#UŠR½,.©{æàfÎQÏ«œ£›¬<¯’õ·õW•*UHN øÕ¶Y£×¯_¯¬?–#Ž8Bj×®í”Ê!@ søÙ¶åÔ‡ÓD— £²QîÒ‡Ô$@€@~ünÛfϹæ}ï©Ò]û yì±qº¬š=d!A€ò'àw÷á‡"o¾)rê©úNîÑá¶ü©aÙ·êoqöÎøFý=°Š9UKõ—üyp€ àâüíUÐC`ëÖ­2bĈ˜#º’Ñwär6ŠdhÔ¨‘ÜsÏ=‘ÝЧ}qr‘¶«³Î]§HSù©ðË©éÛG2WÅ"Ù$K7èÁò*ÿMv2…cæôrJusŒÈ+ÍÓ—©˜CCaÒÍÜVe¬Êá*æð’_j—ßɘs?éö™*æXdm7§ ëÎù*¶dVAé7Íp†Ê•1™7è¶9éܨÒQÅœ*ÌYc³JQ’õŸ=¿±è6±é(Ý©£r¼Š9ñÄ&ûÞ[˜ï¾Öÿ±ÎF¦ËÆËa*ÆÆXý]åy•ßUîPi¢RØdN@ö'¶VÅúé•GT6ªœ«bÎ5^¤Xg#ÓgœnVyMe¥J3©*]¦òÊm*Ö÷^ÌôÆém•a*sTô!Ÿ<¤ÒSÅÆ­WéJUdõOO^éè±±¦7q¡¨Zƈç“2N>ýlÛ¬ÁïëÍúæÍ›…åÔœt?J!d$¿Û6ƒþÀ®ïî6Ü.·Þz«Ô¯_?#û‚FA€€7ünÛvè³¹³ÎÙ´)[ïßúÉ…þC:w¶7‰H€ ü øÝÆé¢'òoýý¦jU‘ûî ·e«¾A²²M9FŸYÎÑÕOªŒ³QþÝÌY@(!^ü ]BUÏÌbßzë-Y±bE´qG«+ó 'œÝO¶Ñ©S'9øàƒ£§¦M›&¿ÿnÞ¦:ê0qþï?kðž;äèÙ»\¬S-â#ÍØHeP˜óÅc*çq>¯Ãæ$2J¥—Ê"û2ÖX%¯´ž8Oå3•÷òÊ”ä¸9#˜³ÈË*Ï$9_ÔCÓõÂUÌáa´Ê\s†²È5©¤½4Ó*ß«üGe°Ê¡*výßTÌád¾Ê%*_©TR)J2'–UžM¸xOÝ?IÅvÚ&œób×úê*¡i•Š9¼˜ƒVE•â$/Vç3TlÜÍVùMåi•.*®’¡¾*5]°K¯«ß’̱ìR•i¨¿9 ‘2†€Ÿm›A~S_²¥HO:É&4 @ `~·mË—‹¼ôR¶Ú·Éºö6–›)¸KÉ@ Ôð»m»ûn}´¥Ï¶*W.uëþ"C† )õ}@H€ßmܽ÷êOúÅM7éÏh ¶ÉªAúCš.ŸÖbÍySŽZ~þ¹¾°ÏóÔz›\€ n8¥›xåMž<9.G=âöóÚéÚµkÜ©±cÇÆí{±³aÃybé²¶ÊZ)?P¿Üœ¬ZÍ $•dÎ=ú(_‡s.±ˆ6%}£)™Dßj’*ÿPùFå"•óU JæôQEÅœsvîʼV?'¨Ü£rºÊq*‰É¢Ù¹r‰' Ø7'™ÓTÌ9gIB^s>™¦2^Å~ç.Ê_äzÝ*V÷;U~U±¨3CU,Êõ‘9×ì«Rœt„^œøöy=öºÊ%*ù9zéé"¥ô*sÊ*’†¼/²:¿¤bã¦eÞÙ8Ÿ€Ÿm[vv¶|ùå—rÈ!‡È{ØdJ‚ LÀ϶Íj?|¸ÈÖ­e$;û>6lËÍÜ¥ä€ Pê øÝ¶uÑgC{íõ³lÜxe(Ú;Ëa—ú! @)ð³[¹ÒV9ÑŸoô÷›+º}+kš7—:>(³ô™å“ç''ÚZÙ$@€€ ŽÁÇÍ ~Õ¾ýöÛh#,ÚÂG˜—GÁ)6‘åvápTUã9Ž^:ZÖO^vò£µWùÔJL!5I!O²,§ È¹MºÑGÅœ]Úª<¬bŽ<©&•d¿'T1GŸcU̧¦Jw•kTÌÆô­Q)nš¡ ÎVyC¥žÊr•ØTAw¬ ÅIÕôbóS{\å••*o©\©r€ú!ÝwŒcEʽuÍæÕ«WgBShC)"àgÛf¶vΜ9òÊ+¯”¢ÉŒ¦yä‘úcÃÆÌh ­ÐÐáÿ–¯¿þ ?Û6ƒøá‡ËôÿùrÆUäðà ×Ò^Qû®ñ¸´ózû,ãmé BÀï¶­zõ)ѽtëvœ}¶=l#@¿~ýdþüùA¨*uLÀí·ß.)† ð³«[Wvxe“<¶ïP)×õ`©²h‘ÜS­š¬üè#¹ð©§xyħƒí /[m†|K–,‘¾}-: (*¯c†µ\§æÍ›'«Vå„ j×®Ô±uÌRHûï¿¿†®¬ë˜›7Ž®Ì5×Öæò>Y}BuzQu›³Îe*G«\«r©ŠE1š¨2A¥¿Ê*EI#ô¢—T~Q¹\åz•H2s62g§‘ƒ…ü´ú¾¬2N¥¥Êé*©¨ÒIÅÊð"í§J¦ªÔR©î…ÂiÖ²eË4rG¶OjC5ŠKÀ¾oÙ²¥¸j¸i!ÛÖ¤É@}øù•Ü{ï—iaB!ÞX®káñ]ß–~Ðb÷â‘g4~¨u€@~‚`Û}ôQ)[¶¬FñZ;¿öpÎ?þøãÙ¾}»*DMŠE௿þâÅŸbäâ’ wÈÍݤê”)ò…zî°Ãä¶7Þzõì v’_ Ø‹"[·nõkõ¨W!ìØ±C–.]Zˆ+È $ ÂQ"‘Üÿé§ŸâJßgŸ}âöóÛ)¯ë·6iÒ$šeÛ¶m²víÚ输³T«EÔÑ(:2D¥‘Š9î<ª²N¥ŒJQÓozá*æPT?‰’>»Î%9•Ò¡šk¦ŠŠÑµqe”Ê•*‡«xål¤ªBi/ýߥ³Ñ®bø€ àG³m~„H @ÀW‚`ÛF%_|ñË…újäP@þ%Û6bÄ™0a‚´mÛÖ¿ © øŽ@lÜuú[Þ@uªý⮻䱉q6òÝ(¢B€ "åG'Íçb£YÑ5kÚ:_©§5Ì‹&'™¾êÕ ïébá%Ôua#˹Ùr3íÛ[8¡ä©ìÁe¥GV©»¦®ÌÛsžÌÙsެª¡‘š,ZîÀä×t´ì޲²ó¬]Q\¦]OA唆óÖqÆŒ6´4´;SÛ¸yóf¹á†¤bÅŠ™ÚÄ´·ËÞ:ž9Ó<ÃÉ6mÙºÄ95ržÏÂð‹m›:uj(ú_ĶY+,’ ½!K &‹ntÍ5׈E¨"Ÿ€½qøØcÉúÉ;‹4ûÊ•+C ÍÞ•+WÎ;å¥X“_lÛ¬Y³Ä¢½ÅÚ¶6mÚˆ½ŒB &[*ôæ›o–J•*³Ô:ŽÀôéÓC÷ér$ïØÛÇ Ì’EG´û7Rñ øÅ¶YTç 6ÄÙ¶Ö­[ÇÍ‹¯¾újñŒ†´°±5dÈÙm·ÝÒV&¹#`޳gÏ–¯¾úÊ]!¥P³EJ±ùÏ’ELaùxo_lܤI“B¿ÓD¾V­ZUöÞ{ïPcWuî,Û:uY¼X ä-´9!`Ï[|ðA©UË–7!™€Í¹ÀcàÀ"þ äÆ;¬»ýƶpáÂP vÏfQI™K€_h|Ô·‰l…u8Jt.²/RÍšÙZ[…K|°üòË/Ò°aÃÐ…öclÇŽóU²­Ç6Yªÿ*ë¿ýõÉ?š6m*UªT‘úõ“…ŠòO=©IjÌ ÆÞæã‡¤Ôx¥’Ë~€ýûX°`7 ©€K1_l›9Κ}ÛsÏ=£57Û†ÃQGà6ìu‡p \Ï%¯°}ïÜ}÷ÝqöLާÈGÿýw±‡×–ìÇ»Äû…"+.åúŶµlÙR:ëƒéF,Ôl8™3-ß#4‚÷iÏöÛo?©P¡Bð*Os°¿ÍÚµk‡$×I™€ý YòÀ~`Î+2ʸ ýbÛì;¡Ý·ÅFq7gZ1ãº+P;uêÔûÎR¹rå@Õ›Ê&'`Ï™ÍI‚¥ž’ó)êQs¤5çKö²)δE%™ü:¿Ø¸=z„žyØ÷CKÕªU“V­Z%¯4G}OÀ~O°ï+Ö¤`°—ìÞÍž§¼#`> ö[›%s¦]·Î–F"e*Ž|Ô³‰_| ]#1¢çvªM=üðÃÅ„øÀÉ'Ÿì¿JQ#äCÀ/¶­“¾%ôÌ3ÏäSSNóaÐzŒúB søÅ¶ÙÛ°Ï>ûl急%‚mc@%EÀ/¶ÍÐGŽYR(×l›¨¨„ EÀ/6î¼óÎRfÀ¾eF?Ò @À¬#â GO´$~ñ)l„£Äдëׯ÷¤^( •¶­¨ä¸€üJÛæ×ž¡^€ PTض¢’ã:@ð;lœß{ˆúA€@Ð àpä£,S¦L\m F=1ÔfbÄ£8åì@€Ò@Û–È@i%€mK+n ƒ 4À¶¥2E@€@‰ÀÆ•v … RD‡#uvâÚÇ…]ÏÐÖ™ŒMµjÕŠÝe€ vض´#§@@pLÛæ0ê!@ í°miGN€ &ظ4¦@(µp8òQ××­[7®6…u8Ú¼ysÜõµk׎Ûg€ nضt§<@pMÛæš0ú!@ ݰmé&Ny€ .ظt‘¦@(­p8òQÏ÷‹ÏŠ+âZƒÃQv @ `ÛJ:EB€€SØ6§xQ@%@ÛVÐ)€ÒB—Ì@¥˜G>êüÄ/>K—.-Tí–,YÍŸ••%Õ«Wî³@( ض’ N™€ à’¶Í%]tC€@IÀ¶•uÊ„ tÀÆ¥ƒ2e@€@i&€Ã‘z¿~ýúqµ™2eJÜ~~;¶œZ¬ƒR‡¤L™2ù]Â9@€€sØ6çˆ)€ÒLÛ–fà@Î `Ûœ#¦@(!ظO±€ Pjàp䣮ÞgŸ}$öËϬY³dÆ )ÕМ“vìØÍÛ£Gè6€ ’"€m+)ò” @®`Û\‘E/ ”l[I‘§\@pMçš0ú!@ ´ÀáÈG# lÙ²Ò»wïhvîÜ)Ÿþyt?¿ &ÄîÞ½{Ü>;€ ’ €m+ ê” @. `Û\ÒE7 ”l[IP§L@Hl\:(S ”f8ù¬÷O<ñĸ1"n?ÙΚ5käµ×^‹žjÚ´©4kÖ,ºÏ @ $ `ÛJ’>eC€€ Ø6TÑ @%IÛV’ô)€\Àƹ¤‹n@(íp8òÙhݺµì½÷ÞÑZM›6M^zé¥è~âÆúõëeÀ€²qãÆè©ÓN;-ºÍ @ ¤ `ÛJº(€¼&€móš(ú @ ¤ `ÛJº(€\Àƹ"‹^@€€H¹â@¸å–[úèõ튣ƒks¨V­š|üñÇÑ“&M’5jH›6mÄÂ?FÒ’%Kä‚ .Ÿ~ú)rHZ¶l)C† ‘råŠÕµQ}l@€¼ €mó‚": @ÀO°m~ê ê@^À¶yA€ àGØ8?ö u‚ p_™â4";;ûy½þÌâèàÚ䮾újyçwâN6jÔHÚµk'•*U’ï¾ûN.\w>++Kž{î99ðÀ㎳@ðl›z:@€€—°m^ÒD ø¶Í½@ @Àlœ ªè„ RN G>6lAƒÉgŸ}–R +W®,Æ “nݺ¥”ŸL€ tÀ¶¥›8åA€€kØ6ׄÑ@é&€mK7qʃ tÀÆ¥‹4å@€@)"ШXën±¤š»¡R¡BéÝ»wh µŸþY¶mÛ–ga;w–{ï½W:è <óp€ PÒ°m%Ý”@^À¶yM}€ PÒ°m%Ý”@®`ã\‘E/ ”b,©„Î߸q£Œ;V¦M›&K—.Ûßc=¤qãÆrÔQGI›6m‚Ð ê@ˆÀ¶EQ°@BÛ–!I3 @ JÛEÁ dl\†u(Í ’"À’j%Ežr!@€ @€ @€ @€ @ʰÒT€ @€ @€ @€ @(!8•xŠ… @€ @€ @€ @€@ àpÄ^£Î€ @€ @€ @€ @(!8•xŠ… @€ @€ @€ @€@ àpÄ^£Î€ @€ @€ @€ @(!8•xŠ… @€ @€ @€ @€@ ”+N¥o¹å–>z}»âèàZd­[·ÊòåËeþüù²eË©V­š”-ë_Ÿé7Ý‹-’Ê•+KÅŠ=÷yófYµj•TªTÉÓ:[]êö @¹'®™ÓŸi,p=gÕ¶Y×0栮NjKæ.uç&Å@ $ ¸ž«\Ú6ãær¾r©»$û¼8e»/.™»Ô]¦\ xOÀõ\…mó¾ÏJR£ëñâÒþ¸Ô]’}BÙ€@r®ç++Õ¥s9g¹Ô¼7ü}ÔõXqÍÛµ~÷µ 8û²Þª'ðÇÈÛo¿-ï½÷žüüóÏqõ)_¾¼4mÚTš7o.Çwœ{ì±qçSÙY·n<õÔS¡2–,Y"ÙÙÙÑËj×®-Íš5“Ã?\ú÷ï/YY…û“ž4i’<ûì³2{ö죔).S¦ŒÔ«WOºuë&§žzªtêÔ)Z^a6\ê.L=RÉûÙgŸÉèÑ£SÉš+O‹-ä²Ë.Ëu<ñ€ëqbå¹dîRw"+ö!’'àzÎ ªm³ž Ò|˜ûfL\—Ì]ê66$@À?\ÏU.m›Qt9_¹ÔíõÀ¶L4HýYpkÈäGÛ–7 Í…é°o®Ç‹Kæ.uç=Š8”×ó•µËåý›Ë9Ë¥n¯ûÛV0Ñ õgÁ­!Gi&P¦8WLJçõú3‹£ƒk!dï¿ÿ¾ÜtÓM²víÚ”šaNG–¿fÍš)åõÕWåÞ{ï•¿þú«ÀüíÛ·—¡C‡JãÆ Ìûûï¿Ëµ×^+ßÿ}y:ê(¹ûî»e·Ýv+0¯ep©;¥ !Ó]wÝ%O?ýt®9ðÀåÅ_Ì÷Z×ãÄ%s—ºó…ÆI@ Ä¸ž³‚hÛ¬3‚8º¶oÆÅåxqÉÜ¥nãB‚üEÀå\e-ueÛL·ËùÊ¥n«»‹„mË›jû3ïÖp(ˆ¶-9¡ Î…®í›Ëñâ’¹KÝÉGG!’&àr¾Š´ÍÕý›Ë9Ë¥î¯?±my bæÝÎ@@ápÄ(€@ Xd !C†új‹d×¶lÙ2ßk_{í5¹á†’æ±(D±‘Ž"™ªV­*o¾ùf(ªRäXâ§y‡÷ë×/´,[â¹¼ö-JÓ /¼Š|”W;îRw~å÷Ü%—\"Ÿ|òI‘Ôäpäzœ¸dîRw‘`s àœ€ë9+ˆ¶Í u>tiߌ‹Ëñâ’¹KÝÆ…ø‹€Ë¹ÊZêʶ™n—ó•KÝVwW Û–œlPû3yk8 DÛ–œPçB—öÍåxqÉÜ¥îä#ˆ£€@Ip9_EÚæêþÍåœåRw„‹‹Ol[rªAíÏä­á(Bp8b @ (¦L™"ÿú׿dûöíÑËÍ‘¨k×®Ò±cG±hC›6m’¹sçÊ;ï¼#_ýu4ŸmpÀ¡¨8æ8”,}úé§bÆxçÎÑÓ]ºt‘ž={Ê!‡" 6”9sæÈ7ß|#÷ß¿ØÚž‘tôÑGË#<Ùûܲe‹ôíÛWfÍš=^©R%9ôÐCCuïСƒ¬Y³&TßQ£F…ÂJF2vØaòÄO„–\‹‹ýt©;¶ÛyÊxZªQ£†T®\9åb¬¯z衤ù]—Ì]êN ‹ƒ€@‰p=gѶY§y>teߌ‹Ëñâ’¹KÝÆ…ø‹€Ë¹ÊZêʶ™n—ó•KÝVw— Û–›nû3wk8DÛ–üYjÐçBWöÍåxqÉÜ¥î‚þÆ8” —óU¤E®îß\ÎY.uG¸¸úĶå&äþÌÝŽ@ J Qt«(¶¤š ¥ŽÀé§Ÿž½Ï>ûDE—Ë^¶lYžÔk:»U«VÑüvíèÑ£“æWƒ“­Î=qy¯¾úêì;v$Í?}úôluFŠËÿí·ß&Í;räȸ|mÚ´ÉÖeÕ’æÕ~ÙÖ®Øv¾òÊ+IóÚA—ºó,ÔƒêÔ•½ÿþûGÛ9yòd´†U¸'V‚Kæ.u{E€€§\ÎYAµm8¨ó¡Kûf\\Ž—Ì]ê6.$@À_\ÎU.m›Qt9_¹Ôír`Û’Ó j&o G!‚`Û’ ò\èÒ¾¹/.™»Ô|q(i.ç+k›Ëû7—s–KÝ.ûÛ–œnPû3yk8 (=ËÅшk Pš ,X°@~øá‡(‚úõë‹…zlРAôXâ†E:çœsâ?øàƒqû‘1cÆÈòåË#»Ò«W/¹óÎ;¥lÙä®ê4$gŸ}v4¿mŒ7.nßv¶nÝ*#FŒˆ;~ÇwH§NâŽEv5j$÷ÜsOd7ôikÛ&K.u'+ÏËcÆZ¿lFU6kÖ,º]œ ×ãÄ%s—º‹Ã”k!w\ÏYA´mF;Èó¡+ûf\\Ž—Ì]ê6.$@À_\ÎUÖRW¶Ít»œ¯\궺»LضÜtƒÜŸ¹[Ã@  ضÌ{.i}îʾ¹/.íKÝýq(.ç«H‹\Ý¿¹œ³\êŽpqõ‰mËM6Èý™»5@<ä ñy؃b¼ýöÛ1{"_|±4nÜ8îX²Aƒ‰-_IK–,‘Õ«WGvCŸÅHüñ豬¬,¹îºë¤\¹rÑcÉ6N>ùä8‡¤_ý5W¶·ÞzKV¬X=nK¯p ÑýdæŒtðÁGOM›6M4òQt?²áRw¤ WŸ¿ýö[Tµõ-WçEr9N¬~.™»Ôí[t@Þp9gÕ¶å χ®ì›qq9^\2w©Û¸ p9W¹´mFÑå|åR·ë€mˬ{q×ãýÈDضÌ{.iãÔ•}s9^\~Ÿp©;çÚL àr¾2>.ïß\ÎY.u»7ض܄ƒÜŸ¹[ÃÄÀá(ž{(@¢3Ï1ÇSà5–ÁœYZ´h—7Q—ENZ´hQ49Õ«W/ºŸ×†EYºõÖ[eàÀ!±ë“.w¨GqûyítíÚ5îÔØ±cãömÇ¥î\…y| ö‹OÓ¦M¥L™äkÁ¶ØÄ¾õrœX]\2w©»°É¤‡€Ë9+¨¶ÍÈy>teߌ‹Ëñâ’¹KÝÆ…ø‹€Ë¹Ê¥m3Š.ç+—º]l[fÝ‹»/è‡@&À¶‰dÚsI§®ì›Ëñâòû„KÝ™8/Ð&d—ó•ñqyÿærÎr©Ûõ¸Á¶å&äþÌÝŽ@ žGñ<؃@–-[ÍS«V­”‚"ìµ×^‘ÍÐg¬s‘øþûïãÎ÷ë×/n?¿SO=U.¹ä’œy晹²~ûí·ÑcæTsÄGD÷óÛˆpdù’ÝØ»Ô_ݼ8·pᨚæÍ›G·‹»árœXÝ\2w©»¸\¹pCÀåœTÛf¤ƒ<º²oÆÅåxqÉÜ¥nãB‚üEÀå\åÒ¶E—ó•KÝ®G¶-·ÃQûÓõxA?2‘¶-óžKÚ8ueß\Ž—öÇ¥îLœh2€ËùÊø¸¼s9g¹ÔízÜ`Ûrræn G O‡£xìA @±_~4hP`þØ ‹/ŽÝ•D¤Ø/>5jÔ.]ºÄå/êμyódÕªUÑËÛµk'uêÔ‰îç·±ÿþûKåÊ•£YæÎݶ —ºã r´ëiݬY3ÏJq9N\2w©Û3¸(‚<'àrÎ ¢m3ÀAŸ]Ù7cãj¼¸dîR·1!Aþ#àj®²–º²m¦Ûå|åR·ÕÝu¶eÖ½¸ëñ‚~d"l›H¦=—´qêʾ¹/.¿O¸Ô‰sm‚@¦p5_Eø¸ºs9g¹ÔáâòÛO7èýßö ›@VîCò#ðÔSOIvvv(K•*UòËwnóæÍ¹– Ùwß}£yvîÜ)S¦L‰î7iÒ$ºm³gÏ–Ï>ûL–.]*ëÖ­sŽiÙ²¥´jÕJ7n—7qç§Ÿ~Š;´Ï>ûÄíç·S¾|y±ºÌœ93”mÛ¶m²víZ©^½zhߥîüêåÕ¹Ä/>Û·oý€`í5™5k–T«V-ÄÙ¸µoß>×ÒxÉêâjœXY.™»ÔŒÇ p5gÕ¶Y¯}>teߌ«ñâ’¹KÝÆ„ø€«¹Ê¥m3Š.ç+—ºÓ1°m™u/žŽ1CÈ4Ø6‘L{.icÔ•}s5^\~Ÿp©;ÓæÚL"àj¾2F.ïß\ÎY.u§cì`Ûr~C5ÞAïÏtŒÊ6Ž‚ÝÔ¾Ä: ¦ø{î¹G¶lٽĢEœvì`Ä‘(’¡Q£F¡Í3fÈ7Þ(Ó§OœÊõÙ½{w¹þúëót<Šnd׬Y3—ŽüX´¥Ødú"uw©;¶LWÛ±¡­-'Ÿ|rÈÉ(±¼/¾ø"tÈ–£³¥î®ºê*Ùm·Ý³E÷]+À%s—º£pØ€|GÀÕœTÛfôùЕ}36®Æ‹Kæ.u à?®æ*—¶Í(ºœ¯\êNÇÀ¶…ÇG¦Ü‹§cÌP2¶-Ü£fÏ2i.teß\—ß'\êδù€ö@ “¸š¯Œ‘Ëû7—s–KÝé;ضœï*Æ;èý™Ž1CÁ&À’jÁî?j|ð¼ð qµ½æškâö-jPl2‡£×^{Múö훯³‘]óé§ŸJÏž=åᇎUÝþ믿¢Û¶QX‡£ÈM|DI¬qt©;Rž«Ï+VȦM›¢ê‡ ’ÔÙ(šA7,ºÕ¨Q£B¼Ç{ªØÛ©Œ+Ä%s—º‹ €€¯¤2gÕ¶è χ~³oÆ3•ñâ’¹KÝÖ> R™«\Ú6£èr¾r©ÛõÀ¶… gʽ¸ëñ‚~@ ‡¶-‡E²­üžy&Ëïõ1¿Ù·TÆ‹Ëï.u{ÝwèƒJ–@*ó•ÕÐåý›Ë9Ë¥n×=‡mËí`äþt=^Пˆp”ýH+|JÀÂ5>öØcòàƒÆÕðÄO”£>:îX¢Á™3gNhÉÓIõë×-£¶zõêКåF8’l{ذaÒ A9í´Ó"‡CŸ‰º#ÅeN²“˜?¿‡œ‰y“¨‹;”˜?Vw\F;±^Ö±ê-Š‘-ŸÖ±cÇs–õÅ´iÓdùòåÑlüñ‡\~ùåòúë¯KëÖ­£Ç‹²Q˜qbúéÏ¢Pæ@À+…™³ç« Ø6c•X÷D{UÏÄü¥Ñ¾£âŒ—D†Åaäþ,¨Ýœ‡ŠO 8s•—¶ÍZâr¾r©»ø½¿¿Ü»Y-‹3^°mù÷3g!ïg®Â¶y×iò‹}+ÎxÁ¶ÔËœ‡¼$P˜ùÊÊM¼òÒÆ%êf> ÷4¶­`‡#/ÇŠ—_è‚@Q àpTTr\üúë¯rà 7„Ub³¶jÕ*t<ö˜m'zZ[Ô¢H:ꨣäºë®‹[2mûöí¡ÈG¶´×¢E‹"YåŽ;îÎ;‹-ÙI‰_| á(qé°õë×GTçúÂæ¥îh!Ž6bבqá…ÊE]$ÕªU‹ }ï‘#G†¢Hmܸ1tÌœ¼®¼òJyóÍ7¥R¥JqùSÝ)ì81½ôgªtÉxM °sVPm›qs9×zÝ/‰úü`߬N…/.™»ÔÈŸ}@ X ;W¹´mFÎå|åR·ë^Ƕ… gʽ¸ëñ‚~”vضÔG@~Ϲœzõê%¯¼òJtñØj'œÈ¹k¯½V†çldç²²²¤C‡¡e×Ú¶mÉZ"Ìœ“b“Eì‰M*TˆÝ-p;6’’eŽõ¾u©»ÀŠ3C쟲eËÊÿû_1®Dg#+ÆxŸwÞyòòË/Kùòå£%Ï;Wî¿ÿþè~ªE'¦ß%s—ºSeC>@ÀŠ:gÕ¶Yy>,IûfìŠ:^\2w©ÛÚL‚‚G ¨s•KÛf]ÎW.u»ض0áL¹w=^ÐÒJÛ&âå3ÏtŒ£’´oE/.¿O¸ÔŽþ¤ @À ¢ÎWV—÷o.ç,—ºÝôRŽVl[üo¨F&Èý™Ó³lA o8å͆3(;vȨQ£ä˜cŽ E±ýHª]»¶Üu×]!ǔʕ+GÇ}nݺ5nßv9ä9÷Üss=`ºŒ¦L™"±úêÕ«{‰¬[·.n¿ -[¶Äe©U«Vtߥîh!Ž6.½ôR™4i’Œ;VlÍß~ýúX’E¨²¨F±iܸq±»ùnwœ˜r—Ì]êÎ '!_(îœk‹" ‚m³ºy>, ûfÌŠ;^\2w©ÛÚN‚‚C ¸s•KÛf]ÎW.u»ض0áL¹w=^ÐÒFÛ–Óã^>óÌÑên«$ì[qÇ‹Ëï.u»ëE4C®w¾²z¹¼s9g¹Ôíª¿"z±m"±÷mÆ%ÈýéW>!–TËç " åxÍ5×ÈÌ™3ã®0¯Usb1•êÕ«ÇKÜIUgàÀ¹<_¯³ý8 íhêÔ©¡Ó¶Ží¼yó¤uëÖ¡ýºuë†>#ÿöæ{óæÍ‘KCŸæäI.uGÊpõY±bE©_¿~H S†9 6L6lغ̖´3¦‰a˜uz1NL§Kæ.u'ò`ð7/欠Ú6ë™ Ï‡é¶oÆË‹ñâ’¹KÝÖ~  ^ÌU.m›Qt9_¹Ôíz`Û„3å^ÜõxA?Jl›»gžéGé¶o^Œ—ß'\êNGR à/æ+«Ëû7—s–KÝÞõRrMØ6‘Øû6£äþLÞË…@<"Åó`…&ð /Hß¾}s9uéÒEÆŒ#·ÜrKÎFVh²/>ûì³OÊõ9è ƒâòΙ3'º_\c¶bÅŠ¨.Ûˆ5–.uÇê£s$Û{ï½ãj4cÆŒ¸ýįƉéuÉÜ¥îD&ìCþ%àÕœTÛf=SçâØ7cåÕxqÉÜ¥nc@‚üOÀ«¹Ê¥m3Š.ç+—ºý:°my÷L~÷ùy_Å@ÀO°mní¦Ÿú:±.E±o^—ß'\êNdÈ> à_^ÍWÖB—÷o.ç,—ºýÚó™jÛŒwiìO¿Ž3ê冎ÜpEk) °~ýz¹öÚk%q9­fÍšÉàÁƒåˆ#Ž(…ÄHy'Ù—¡¼”îµ×^q§æÏŸÝO4fK—.žKecÉ’%ÑlYYYqT.uG õá†9E"JYõÖFªìõ81½.™»ÔaÂ' à_^ÏYAµmÖC¥u>LÕ¾#¯Ç‹Kæ.u  à_^ÏU.m›Qt9_¹Ôíß ¡—ER¹w³6x=^\2w©ÛÏýIÝ ïç*l[xT%>óôûXKõÞ Ûæ÷ž¤~€@„€×ó•éuiã\~w©;ÂÛŸ™hÛŒsiíO?Ž1êä†Gn¸¢µøÏþçld7¥—]v™œþùR¡B…BhÙ²eÜ5¶,ZaRvvv\vsXФØm;6eʔȩ?m9µX¥:Ä-óæRw•+Á 7nŒ+½iÓ¦qû‘¯Ç‰éuÉÜ¥î>!ÿðzÎ ªm³*­óaªöÍy=^\2w©ÛX ÿðz®riÛŒ¢ËùÊ¥nÿŽl[îÞ)è>?÷üDÛV&Ú¥Õ¶€Tí›×ãÅ%s—º£ƒ† @À·¼ž¯¬¡.ïß\ÎY.uûvhÅ2ѶïÒÚŸ~kÔÍ[8yËm¥„ÀÈ‘#åã?޶¶V­ZòØc‰9ã5™Ž† F{V®\)k×®Íå—þ؈F–Ç<#É–f3ƒ‰Â3kÖ,Ù°aƒT­Z5’%ÏOsNÚ±cGô|=¢Û¶áRw\Aï|ùå—»ìÜßÿþw©W¯^Ê¥Ä^kµhÑ"×µ.Ɖâ’¹KݹqðsVPm›uLPçÃtØ7ããb¼¸dîR·ñ Aþ$àb®riÛŒ¢ËùÊ¥n—#Û¦›)÷â.Ç º!P`Û2㹤ÕtØ7ãÅå÷ —ºKÃü@!d.æ+ãáòþÍåœåR·Ëq‚mI¼o3ÞAíO—cÝ™E lf5‡Ö@À= ÈÝwß-¨råÊ2bĈb9E”%:,M›6-rªÀÏéÓ§Çå1IeË–•Þ½{GvÅ¢'}þùçÑýü6&L˜wº{÷îqû.uÇäñÎܹså¶Ûn‹ÊèÑ£S.aùòå2oÞ¼hþ=öØCªT©Ý· —ãÄ%s—ºã±øŠ€Ë9+ˆ¶Í:'¨ó¡kûfl\—Ì]ê6&$@À\ÍUÖRW¶Ít»œ¯\궺»Jض0ÙL¹w5NÐ Ò@Û&’Is¡kûæj¼¸ü>áRwi˜#h#‚JÀÕ|ááêþÍåœåRw„‹‹Ol[îï*Æ9¨ýébŒ 33 àp”™ýJ«3fŒlÛ¶-ZÂwÜ!íÚµ‹îgãä“OŽ»üþûï—Ä¥Òâ2ìÚ™:uª|óÍ7ÑSûT«V-ºo'žxbܾ9I”Ö¬Y#¯½öZ4›-Ö¬Y³è~dÃ¥îH^véÒ%Nå{ï½·ŸßÎÃ?7vص.ljéwÉÜ¥n«; ð—sVPm›õRçC×ö͸¸/.™»Ôm\H€€¿¸œ«\Ú6£èr¾r©ÛÕÀ¶‰dÒ½¸«q‚^”ضÌy.iãÕµ}s9^\~Ÿp©»4Ì´A$àr¾2.ïß\ÎY.u»'ضäßUŒwûÓÕ8AoæÀá(óú”9&ðî»ïFKhÞ¼¹ôìÙ3º_ÜÃ;L,ZN$Y„£^x!²›ôsóæÍq—,ÓàÁƒsåmݺuÜ2k¦û¥—^Ê•/r`ýúõ2`À€¸5SO;í´Èé¸O—ºã òpÇ–@«[·nT㯿þ*£FŠîçµa‘¡Þxãèisìºì²Ë¢û‘ —ãÄÊpÉÜ¥î>!p9gÕ¶Yq>tmߌ‹Ëñâ’¹KÝÆ…ø‹€Ë¹Ê¥m3Š.ç+—º]l›H&Ý‹»'è…@i €mËœç’6^]Û7—ãÅå÷ —ºKÃz,vÃ¥îØr¼Ü~ê©§r9k}öÙrõÕWK… rõøã‡ØÚ’t‘d<û÷ïÙ }¦cœXA.™»Ô‹@ Ä ¤cÎ ªm³Î â|èʾtŒ—Ì]ê6>$@ÀÒ1W¹´mFÑå|åR·«€m#™t/îjœ ™LÛ–yÏ%m¼º²oé/.¿O¸ÔÉómƒ@ ¤c¾2..ïß\ÎY.u»/ض信ï ö§«q‚ÞŒ"Ї£ŒêO㚀yZ_uÕUž3|øp9ꨣré:t¨$.yVµjÕl«V­dË–-2cÆ ™3gNÜÒ^µjÕ’Ñ£GKÆ séŒ0gšwÞy'²úlÔ¨QhY¸J•*Éwß}' .Œ;oÎHÏ=÷œxàqÇw\êþöî^¦ú}àøc_³ïû¾ïB$-Ö*‘,¥’%J©ŸDÙ¢„%R”Ê’Š¢$[Ù’d+¤le—„,™ÿ÷ùÞÿŒ™¹3÷νsçš¹ó9¯×iÎ~¾ç=šï9Ïyïs%Õ|¿~ýl •ûñô‡Ü²eËJ•*UDM¶nÝjo°ž:uÊ}3©ZµªÍ圔\ÿN´1¡4å±= ™A«*\ŸY‘ڷ雉Ÿ‡¡èßÔ"¹þ½„Ò<”ÇV#¸úÉõYʾMCùyÊc‡ê_}›ÙH|?ý_ k@À—}[Êü]RßëPôoÉõï%”ýO(íëÿ1–!€ÀÕH®Ï+½ºP~ ågV(ªw¾Í¿l$¾Ÿþ¯†5X"WRš ‚ñ ìÞ½;Þm’b jªX±¢ 4HNŸ>myæÌY·n}£N:ö¦üùóûZíZ6tèPÑÀ™åË—»–íÛ·Otô5hV¥·Þz+Þ`#Ý7”ÇöÕ¶¤X6lØ09zô¨|ÿý÷®Ã]¼xÑtiP—¿¡K—.òä“OúÌ„”\ÿN´m¡4å±ý¹²’_ ¹>³"µoÓw$?CÑ¿©Erý{ ¥y(­F  põ’ë³*”}›*†òó*”ÇÕ¿ú6ÿ²‘ø~ú¿Ö €€/ú¶¸‚T³Hý, Eÿ–\ÿ^BiÊcûúŒe pu’ëóJ¯.”ßßBù™Êc‡ê]§oó/‰ï§ÿ«a 1©@À¼3ÿ¾g·¼í¶Ûlz½Úµkǹ³–E{üñÇå£>’ø‚ô@š)IKƒé>:×P¯^=™2eJÀeãByì¸ÚÌ:ÍN¤)5£”f4ŠoPãÉ“'Ë3Ï<ã3ØH÷OÎ'¡4å±ãsf=$Ÿ@r~fEbߦïD$~†¢S‹äú÷JóP[@àê $×g•^i¨ú6=v(?¯Bylm{(ú6ÿª‘ø~ú¿Ö €€/ú6_*žË"õ³0ý[rý{ ¥y(íù/‡9¸šÉõy弯P} ågV(ítIêWú6ÿ¢‘ø~ú¿Ö #@I5þ% û÷ï—Í›7ÛqÛ¶m¶dš–VÓ±\¹r’5kÖD]ÅÙ³geÞ¼y²iÓ&9xð è|¡B…¤hÑ¢¶Ô[åÊ•u\Ý)”ÇNt£ØQ³Hmß¾]víÚeoªæÊ•KÊ”)cÇÒ¥KK$Uª >:hEâ6 ¥y(¸«e/ˆtHìÛÔyï½÷zœ«K—.Ž .øÚœe €Ó;Öõ™œ7o^ÏôªU«ºÖ½øâ‹®–$¶Ï§ß÷©-.X&@ˆ”¾Ïý‚~þùgGóæÍíï£Î{jÎW“Àö¹ýû÷wœ?Þ}·XÓôa±HX€@4 6Ÿ#‰ŒGÑüχk¹ÀäÉ“ÚÉ›ÿKã5ø&€ éÓ§;²dÉçñ4gΜ96ˆÉýÜιþ.|ãÆ±‚zÜ÷wŸÎ‘#‡ Lòw,]î}#YÛôÇ8*V¬gûõ—Ø€#ýΧǸŸ§V­ZŽcÇŽ¥àY\ Z`û¯~ýúy|.»F»OwëÖÍu!‰í3¼¿Cò[£‹” @DRß§—¥É~øa‡É`PŸ{íµ×:þüóO¿"áÔŸúm$+@ ¹ ']n4ó×?$€–€1¿<ôÐCröìYƒæÊ•KòåËç±Lg4=aÛ¶mm¹µX+ÍM‘h2ùH‡Ä<Ñék×2½,mÚ´‘Ï?ÿܵ,¾‰U«VI£Fä—_~‰µ©¯Rm'Ožó©ôîÝ;Ööþè5Þ|óÍòÛo¿ùÛĵÜü!6l“ÅBV¬XáZîobåÊ•b2I‰^{ C8µ%ö²  ¡èßܯkëÖ­Ò¢E Ñò™îƒÉ¸ç>k§µ¤hÏž=eݺu±Ö¹/ s×ðœu_ëy6æ@”+@ÿèû½U—»îº+ ïs¾à¹ÔÉ­·Þ*&#®kEݺuåÛo¿ýžÍ€ 0P÷_ iMbûŒpú}/œÚ’{¶E¢I Rû>“ ^Þÿ}¹|ù²ëíÒÕ5jÔråʉÉïZ®k×®•š5kÊ?þè±Üß }˜?–#€@¼&,Š GÉÆy¢J`üøñQÆZþåùçŸw˜¨.°ãøä“OZRÍüÏêï¼óN×6îZRÌ};ÍìðÀ8Ì«6åü¶mÛÓ¦M³©åÛy—Dó—áHÛâòX³Íš5˱wï^Û Mk?cÆ G§N<Ú¡çzóÍ7Ý›êšöŽ’vÏöd§óçÏw>|Ø¡mÿàƒš5ÉÙv}M›6­kÞü€ìxå•W?üðƒÍzdþ`rôéÓ'VêHm£¯!œÚâ«},C"A ©û7ïÏf÷§t7nì˜7ožÃ|áµOñh–¢·ÞzË‘)S&Wß }…–-õ7п%o_ëï}`9 ÒècÞaïl&ˆØ£Ï.R¤ˆãöÛowh†‹ï¾ûÎõÏ"’jÿý·C³Úº_¬_¿~¼¥µ]'a@ –@Rõ_û÷ïw¬_¿ÞŽZòÒý³ú믿v­Û³g« ‰í3¼¿Cò[£‹” @"±ïûæ›o©R¥rõ¯uêÔq˜,=®Ö$,pèo§Mš4qm§ý±nëk§þÔWûX†É*@Iµdåæd  )ãóçÏïêÔ5ØHÿ ð7:t(V°~QwôÇU“ÉuLý2½páB÷M<¦5=}ÆŒ]Û;¿èû 8êÛ·¯Ç¶ššÑdfò8¦ûÌÀ=¶/\¸°ÃD†»ob§½ÿhÑv¨‡.÷5èî7›ínРC| ¯½öšG[ô‡ _C8µÅWûX†„»@(ú7_ŸÍÚL:Õ/ÇòåË=ú8íïü•Ô¤‹Íʾ6öÙX‚¤|úÇ+ï±÷Ícç÷¹âÅ‹ÛG®lé9_À‘_wÝußû´ì¶~Of@Hœ@(ú/mI¯^½<>¯wïÞí³‰í3|}‡ä·FŸÄ,DðˆÔ¾Ï= @öìÙGõº2ÏÙöíÛ{ôÅš´À{§þÔ»mÌ#€@² p”ìäœxìÑ™kóøÍîãü1V_5S‘ûààóÎ;︯ö9­Ù€Ü©Ó¾ŽvîÜé‘%¨V­Z>ƒ‡¼O¢Ù…ܯY(¼_´<ýôÓÞ›yÌ{ÿ¬?˜lÛ¸Ï\¸pÁ#’ffò5„S[|µe €@¸ „¢óõÙܽ{÷x)Ly>hÙ²e±ö¡‹EâZª¾Öu&@( ¼òfûºy¬ßÏŽ?~e#Sq8qÂ>•ëþÝÓ”éölìãð,Bð!ŠþKOLÀQ }†¯ïüÖèã÷‚F4@IDAT f €@,Híû´t~ºå–[b]—÷}XÓ¹½¾¾úê«Þ›Ø¤îÛèôÕêOc5Ž Ü…S›S§N‰ ôqµ&C† ¢µUãLV1\›™§®i=¦Éâãš/[¶¬téÒÅ5ïoâÑG“iÉßj×òþýû‹ Ú±ó&-£˜{Å”bs­÷7¡û™` ×êÉ“'»¦ýMäÎ[Li9«íòòåË{¬7eã¤B… ËÜgLi9)Q¢„kÑ‘#G\ÓqM„S[âj'ë@pEÿæëºLùL1b„¯UË6lè1ï볟þ̓Èc&¹úZ“2ƒ¤@úÇøßÔ7ÞxCræÌÿ†>¶0ÁFbJÈš5k\k›6m*¦áSO=• ·•>,A\lŒ@Š à(Ž¥\P$ ˜ò-Í¿í¶Û<æãšÑŒD¾ïcjS C¥J•âÜT3Bœ… xÿÑR¦L™ ¯Ðû˜ZR-СxñâqnºmÛ6õ¿þú«ý#Åca3¿ÿþ»ÇÚ}ûöÅp_{<öÿ3… òµ8èeáÔ– /† €!ðî‹’¢óÕd÷™¾ÖºŒþ-P©˜íBÕ×&¬lDžýcÜßÿòÝÕýݿ뮻dÿþýî‹lðÚ'y=V0ƒ `äê¿Ò°Äöáôû^8µ%!öl‹Dƒ@$÷}ƒ ’+Vx”š>pà€Œ9ÒŽZ¤Q£F¶µf…ML”˜}ø=1þÏá£E€€£hy§¹Îˆðþ£E;ú`ïcæÌ™3àCÆ•ì놬%v8wî\œ»&æMŠ!œÚŠë㘠€@R x÷EIÑ¿ùj_áÂ…}-Nð2ú·„‘…ª¯MX+؈<úǸ¿ÿ¥M›¸Ÿ¬¼ƒœÿ2Þ}÷]iß¾½-íí\Æ+ €@Â’«ÿJHËÛg„Óï{áÔ–„س-  ‘Ü÷eÏžÝViÛ¶­«âˆû{¦bgÍšeG]®UHÚµk'={ö”Ì/ +ˆ Ð܉ :.¤Ð’bîCîܹÝg5íýckŽ9>N|_Ö÷ìÙð±Ùðßÿs³4iÒĹ>9W†S[’óº9 Pôo¾Ú_¿åk_Ëèß|©° @ ©èãþþ¬w§Nä¹çžsÆápH×®]%¾ï®˜@ð)\ý—Ï“'ñÂpú}/œÚ’Ä̈xHïû4èháÂ…6ÓQçÎã $Ú²e‹ š)S&תѣGËáÇ]ó¾&Ξ=+Ï<óŒÇªN:yÌ3ƒ rBÑ¿…Z‡þ-ÔÂ@€þ1yÿ tëÖÍ㻲~'îÚµ«ÇÃ;ÉÛ"ΆD¦@(û¯Ô©=oWÄ÷cd Òj@HˆÔ¾¯N:ÔãÇ÷˜÷7³xñbת¬Y³Jùòå]óL €ÞžÁ{¯e’] ]»vR»vm×yµc¿õÖ[åÔ©S®eΉo¿ýÖ®s4h¤I“ƹ‰}0`€d˖͵ìË/¿”FÉæÍ›=~\=yò¤M+óÍ7û<ŸënÅ‹—þýû»–hy·k¯½VÖ­[çZæ>¡ËkÕª%?ÿü³kñÃ?,õë×wÍ3 òBÑ¿…R‰þ-”º@À)@ÿè”ý«ÞÄž0a‚Ç÷ååË—Ë;ï¼ú“s@ … „ªÿÒL îÃÈ‘#=~»t_Ç4 €É)‰}_åÊ•¥F.¦W_}Už{î9Ñľ†Ë—/Û3fÌp­Öû“ÞÁ®•L €F -  ^ZVlìØ±Ò¼ys9}ú´mܲeË$oÞ¼R½zuÑÔ`¤ÁBš‰È}hÛ¶­<ñÄî‹ìtéÒ¥eÊ”)¢ë/\¸`—­Y³FªV­*9rä°5\µ\Œ¦S<þ¼kÿ^½zɸqã\óþ&4[ÑÔ©S]éè÷îÝ+ZÊM§ô™2eÊÈÎ;Eë¼j›Ýÿ˜Ñ?xôz@R¶@(ú·P‹Ñ¿…Z˜ã#€Ð?&ï¿ý~Ú»woyýõ×]'îׯŸÜqÇR¤H×2&@âUÿU±bEÏœ9S®¹æ)Z´¨´nÝÚ#Ë»Ç†Ì € bHìû4PèÝwߕ뮻N4˜HÇ—^zIæÌ™#šx@3•,YRŽ?.[·n•iÓ¦y”]Ó@à@žÃ#€@˜ pæoÍ‹NÍö£9úEZk«ê A:k×®µ£/ ðyï½÷|­²ËZµje³i6! 6ršÕè‡~pÎÚWÍ4|øp¹á†<þ˜Ð´‘¾† 2È?þ(Ý»w—Ï>ûÌn¢M«V­²£¯}t™þØ;kÖ,Éœ9³¿MXŽ ‚BÑ¿…’‡þ-”º@À)@ÿè”Hž×^xÁ~oÕì¼:üý÷ßòè£ÊW_}•< à, €@ Eÿå u~F+Õ™3gä÷ß—£G¦9.@ R"±ïÓ²jýäp8,ý¯¿þ*:Æ5è}»?üÐ&Cˆk;Ö!€”Tãßa*P¡BY½zµÜwß}’.]:¿­,[¶¬ý±ôûï¿·OüøÝЬ¨R¥Š Ò´‰ú‡Q–,Y<6Ϙ1£Ü}÷Ý¢iåŸ}öY9{ö¬ÇzͲäoÈ™3§|úé§òÁÄÛÝV³FhR©R¥ü’å €)P ý[(™èßB©Ë±@œôN‰Ð¿fÍšUÞ|óMÍ;WÜËx¬d@À¯@R÷_ú¨~&—+WÎï9Y €ÀՈľoÈ!²bÅ ©V­Z¼tšÉ©cÇŽ6ãQ³fÍâÝž @TÁ˜HÈ)fÿNÁƒ}@ ~-s¦åÈ4ÑFçÏŸ_4ÐHGÍ”6mâ’•iúÄíÛ·‹–SÓc*TH2eÊäjÐìÙ³m’sf[Ò?¦â´܆ dýúõvsæŒlß¾Ýg°Ñƒ>H°‘‡3 € € € € € € € @†#þ eÇŽ“ &È´iÓä?þ-¥æ>.\XZ·n-:të®»Î}Ó € € € € € € € €@ŽøG€@ ˜²ˆrèÐ!9xð äÌ™S ( 3fŒb.@@@@@@@â(’6ž X)X UªT6ÈH@@@@@@@@@R²Û € € € € € € € € €*@Àÿ@@@@@@@@@ `ަbC@@@@@@@@H Þ›7o–¹sçJùòå½W1»ví’Ì™3K¾|ù"°õ4Ù[`Æ R¥JI—.÷*æ“H`ýúõòì³ÏJ–,Y’èˆ&vîÜ)3fÌJ•*…CshC¬[·NjÔ¨!iÒ¤I‚£qˆ«-°uëV)P €dÏžýj7%Åžÿøñã’*U*yøá‡Sì5FÛ…:uJÌîìfú#ÍðáÃ%OždÈО„£_Íö¦Á)Ï=÷ÜU9?'MZ»îºKžxâ ©]»vÒ˜£%»€fÞ¹ï¾ûøû3„òšý·[·n!<‡¾Ú©¯v8? € € € € € € € €DŽG‘ó^ÑR% QóÔ‘M]Xî¤YZR§æ£;,ß…É*P @I•*U²ž““…N wîÜ” /GFÈŸ??ëGÈ{H3õ»8™S‘bHÉyóæ¥ v zƒ³gÏ.™3gNAWÄ¥ €‰È—/Ÿ¤OŸ>q;³WX ¤I“†2ØaõŽÐ˜H ¤Z$¾k´ôíÛ7[³i¸ h9@‘¥K—‚ÆŽ›‚®†KA'Àßú‰s ×½FŒ®M£] €@² ̘1#ÙÎʼnB/@)¨Ðsˆ wß}72J+ãЇügΜïvl€þH“á߆5 € € € € € € € € à%@À‘³ € € € € € € € € à_€€#ÿ6¬A@@@@@@@@/޼@˜E@@@@@@@@ÿù·a  € € € € € € € €x päÂ, € € € € € € € €ø àÈ¿ k@@@@@@@@@ÀK€€#/f@@@@@@@@@À¿GþmXƒ € € € € € € € €^y0‹ € € € € € € € €þ8òoÃ@@@@@@@@ð àÈ „Y@@@@@@@@ð/ÖÿªÀ×üû￲mÛ6Ù¿¿;vLΟ?/.\-ZHÉ’%íÎ;'™2e ü l‰ € € C‡Ùïf»víÿüóOûºeËiÒ¤I‚ŽÅÆ € € € € €ø&à(ý˜1cÊnذAÖ­['/^ŒuŽòåË»Ž&L˜ K—.•V­ZIË–-%_¾|±¶g € 01¯rò¤H Ý3f{‡Ã!{÷î•­[·Ú´gΜIÜØ @ ª´ÿX²d‰üðÃrùòeÉ!ƒÇ˜>}z¹öÚk¥V­ZIêtêÔ)û=ëÛo¿•Å‹Ëo¿ýëø9räœ9súüÎkc € € € € € €@¢ŽJ—.Ý"Mš4Þ~ûíâœÃµÉï¿ÿ.:Ž?^^zé%iÞ¼¹k €Ñ!péÒ%Ù´i“8p@ôækºtéì«s:kÖ¬bú†¥6@Íf²oŸÈ/¿ˆlÜxe4 öä¿ÿÄì#Ò´©H§N"×_ïÚÝ5¡Ešåa£Ùùs_ýÕmß¾]4 ŸsÈ•+—s’W@" A93gΔ‚ Ú,?Úç;h¿òóÏ?Ë‚ dáÂ…²råJ›å5®ã¦J•JÚ·o/#GŽ”"EŠÄµ©ßušUVÏ»jÕ*Ñ £5kÖ˜~Ðt„f(Z´¨<øàƒR½zu)Q¢„5ãlöìÙeîܹòõ×_û=.+@@@@@Hˆ@‚ŽÊ”)ópêÔ©ß1'Ið¾Î†ýóÏ?Ò»wo騱£ôïßßÞlv®ã@àê hé•yóæÙLtzÓ2)†={öÈêÕ«]£fÅsð‰9‡Æ¯¶7ã:3.’jÕªIÏž=m?Q¯^V1U`b „Tª”È]w‰˜Ä &«„ˆI¦gê׿löÙboÆ®[·Y¾ø¢™)ù™ÉÜ-hŽóOš ¦ÔR¼xq¹ñÆE3ò•+WξöêÕ+Ö¹X€ ™Ú瘇$äã?–³gÏÚ‹Ðà͸zÏ=÷ØÐ3ft]œé<¤£óh¹è´iÓŠyà¾괎Äzøða»o–,Yl “>PqË-·HæÌ™í~º¯sÔ HãÆ“éÓ§ËìÙ³¥oß¾òÌ3ÏØm] p›Ð¶h¶¢õë×Û# 2ÒQKX;ÍZtçwJãÆíùµ/c@@@@@@ 94d2NÜbnоç«ašBàÖkú£º÷)S&ïE2mÚ4›ÕâÙgŸµŽ €É' 7dGm³?h–„'žxBÚ´i#O=õ”Ô©S' †è~Z–L³é Qçë¡C‡\ûkI—n¸AêÕ«g‚…JÙÒ._~YÕd]¨g¶Ie~•úõÇÊŒ3¤GöFl™2ŸÉí·×•,Yr˜rœb¶‰«T³,æÐš¹BƒšæÎýÍdoX)Ç/]vein_–\¹N›@׉æfp)©\¹²-u£ÍË›7&‹’n¯7‘@”& Ÿ‰'Nœ°o’ëÚ4`f›IC·víZ¸£ úÀAçÎCÚ ,Ò~DôÜ:h¿Ó­[79zô¨Ìš5K¦NjG ºýöÛ¥ŠéT~úé'[íøñã®öi_•-[6Ñì|ÚÏé±Ó… ¶Ù„4ȨaÆö{kG?·Þz«Í†Ô§O:t¨¼÷Þ{òòË/K‡lŸ¨íýþûïí¨OîmÑ €[£F ;Ö®]Û¾j- € € € € €É-ð]ÕB… e6?fOto )Ep©S§Niï½÷^ÑTý:èd瓾îÛvïÞݦøíµ×LIœ}®U“'O– H£F\˘@¢AÀTD1Y Ä”‹)fíx +VˆÔ­+&(Æc±ÇÌÎb²6ˆÉv òúë«âÑÁß|ó 4Zºt©Ý¾^½>òÏ?OËÞ½››µÿšq¶)OÖÇiÍî0j”¶ù¬ Ì9 ¹s¯27°—Ú2e›7o–µþÙÿhZµjU›ABoôꨩZNÆ}([VäškÄÜlSj³²Éz7A^}õU›BKp®_S~Sû‰jÈòåÇMÆ¢c6ÃވÕL'Ož½ô¼×^{­í[êׯ/zC6GŽŒbîÓš!³Ûè„LÂ=¹é&17àÅÁŠ HŠYÎ@HЬr+L²cÇQmtèÚµ«é/^7›ÿ±™DzáÂtªå*5èT3i0«{ð§Æ,Z´HÞÿ} T©R¥8Ï®ŸëZóÈ‘#6ðF¦tÔÏ~}Õ¬©š1Oû}uŽjð÷ß›Ïý¬6ÈèÑGµ9ΓiV!ÝæóÏ?·¶ZjíÓO?µCµjÕ2ýÞõvÔï(ùóçwî–d¯Íš5³A¹ï¼óŽ <Ø”í$”ƒºúQ-7ªý—2iÿ©%ÒL¦ÙX}h’5Š!€ € € € € @€ŽLY€æ&±)^3˜gGõ½yJ·™sY\¯zƒYŸnÚ´© 4ÈÜ,þµùo¼AÀ‘Kƒ ˆsoQLÌ¥:w>n2ôL2zæÚµ÷Þû¸|ôÑp(“JyDÄÜ+5A›1Û8 æÆhL ‘IÆ`ÝÆ}ؽ{·,[¶L~üñG{óR…œ£fðqÞôÕÃzSóJ•†™ŸÅìaòå+l2:œ78ûMvˆ‘6hHKµÙ÷ß1Ù4:ªŒG˜ñ})X°  ܹÉÞÐÕ›¢š}¡¬‰$Òsº&A„ÉáD¥?:ºz#\oŠë¸jÕ*{cZo/_¾Ün¦¥jrçÎmÚ—KŠ+fÏ_×Dgi€‘ž[¯)A“™ûÊ&Ĉ¹Çl²^²Û €á' Á9cÇŽÍê^¶²@R¡B¬¢}Ãĉmÿ ™F5831ƒf3Õ€U-õ¥ýˆf.Ò'Íüã4ØGƒw4KžžG_õsû¹çž3å/'ØÏjÍ¢§ß ô3Ý}Ð2bS¦L±ˆöîÝë¾*Ö´~Þk ©–Es¾j öíÛËý÷ßoZMD«AûŽ'Ÿ|ÒŽè£HÚ¹—Wó±[’-Ò¾XKxjf#ÍtôÉ'ŸØŸ`¤phŸ¦×À € € € € €@¸ ˜[­ æætgç–æ†Æ¹Ë—/ßa‚v. ôÕdE²Oòj©?þøÃî¦Y1vš4¦d[ ‡a;@ É4SΗ_~i³ôìÙÓfãqžD“çx%æq® øUo_¼xQ4 „ŽUªì’&M¶Ëo¿}"~¸ÐçŒÍÆP¤Hó¦É ¤Ûö•#òÚ¬B-[ŠÉØ ¢Éˆ._$¦,˜›ªbvšŒËìMd 4Ò›Ê"õÍø£Mã} Z"¦oß¾¶|Ú{ï67©E̩嫯ÄÜÖ4µÒ&kÝÑLCzƒXËfÖ­;À]g²>Ô1Y„º˜ì £ìMdÝCï5kŒ‘/+sérß}b ÄŠÉ$¡{Ä?h‘Žo½õ–Íf¡AFIuCØÜŸ–I“Ä\‡˜¿1ÁG¹rÝ£ØH €þ­«4wÜqG÷ŒsÍúÐCÉâÅ‹íßÓÆ 3A¤•ì´þ8í‡ÆŒcJKö·Yà^xá[ºRƒP´ÐìDÓ§Ow•úÒÀRͼӪU+[ªRÏ«?ääë¸ãÆ“|ÐÒ>*#GŽ´¥ÏÞ|óMû9¯eÐ>úè#W4 rÕlDZÖL?ûsæÌiGç´y¶rÞÛhЬŽWcÐkÒ÷DG@@@@@"I  €#“¥¢¢¹¨jnö‰¹i²ÄÌ'8àH¡Oë>Ü>Ñë<æÂ… íç<¯ €@rhVƒÙ³g›Ì6³l°Î¥KUÌi»É›on55M¦œ"&à&µÉ<$&8(°iæ½é«Çœ?¾-÷uáB%“ÙG³4ŽuͲЫ׃ÒÒDi–  ¦†Ú¼yódÈ!¦$Í+¦ -¥P¡—dΜJ6H§iÓ3æ¦îFs#÷Sjæ'SŠe½8KåèÁõ&oÛ¶Cä³Ï™À KÒ½ûeéÒå_¤ôŸiÕQoئNÉfPš:5&Ã*äÙÄ|ùòÙ¶h{âzô9}ZL•˜  +[ic*™©£HxoûÊÌ”HéŠáaÓ›Õ¬)&““–§3)@$ÐÏ]-a¦™|4óPïÞ½mp‰wyÉÄžNƒ4SŽ––ÔÆZ’Ò_¹4=gŸ>}¤qãÆöïp <Ò~J³ u¦Ñójˆãj6$ 4Òt¨R¥ŠÍTÔÄtŒåË—·ý–×nqÎj¶£ŸLŠ> f}þùçÅY²S­ôsþa󡬙÷´”fR9ÅÙ V"€ € € € € €@‚Ò²‡ù¡¿‚×v?zÍ'xVKÞh¶#Íò¡ƒ>™Í€$‡€–M™9s¦ Òr]šñ!C†Ü¦4×LùóÏ–f^3=\’¿þúËdÚdxr˜@I“úGLê?ƒÞDÖò2d¤eÑþÖTDf¨Zµ–ÉZ4Ú”šignæþdnžŽ·Ÿ}úù§™´Ô¤f‚ðn»í6Ññ믿¶¥VÖ¬©bÚXÌŒÿÉ‚ûͳ‡–¡Ñýï3©ƒôÆì7Þ( t䈘ÌbJ‘¥37ŠEž~Z³yGŠÜ}·˜i"wÝ%v;¯ª6ž;Ä3§Œô²?ûLLi1RbÚ"rölÌñ-“Õ"¦|YbŽâ9}Ы5àhÝ:Ívô¼9–i, ¤€–ÓÌC\S®\9ûù¬Ù|Ž˜éMdf å}5ãøñã6X_ËMjÙ4í/´ßdÐ~cíÚµ6ËfÓy“¹TΜ9c3ÉýóÏ?®W ÌÕì|9rä°çÓëÑ€¡`Í~ôØc™`Ô6¶ œ6uìØÑQJ,X]öG@@@@@ ô™òiÅÝK"˜¤ Ž´üÉœ$¿þú«½J½±Ï€„JàÏ?ÿ´Á@Ÿ™h½ñ«ƒ–™iÛ¶­)#Ö[>þ¸¾)ó˜Ú”t1Õ^¤zõ42uêw¶ìÌæÍ¤gÏj6CEݺuMðИ²[úU¶oßnG-3sÖDÖh&Ýæ“*çúëï57S‹›õ&Eœ‰)úðæT™©Ý•€A’tÔɯ½öš)YvIjÕjkÆZvÔlF¾ÊÉäÍ+¦›˜Œ"{5±’×`â­l 5SáGþ÷?1em—uÈý°éÒ‰|ò‰˜Ò:1ç®W/fÞTÃ1Ù£D4û‘Ifá³Üšûq®æ´©lcéÍ€$¥€3ÑCŸ˜(˜ušºÆ Zª¥S§Nöm… -læÇ#hòÎ;"]»:bRÙr.84ÂDîh‰-A3L5/uÍØÉŒÿH^ÝsÝu×Ù¬ zC¶H‘"æ&°ˆ©Žf‚“DŒ5 '±ƒ3ð(¡û› –&«†ç^š‰¨gO‘'DÞ}7æš=·Hüœ¹—./½$& TLi :ÒáÉ'ÅlÅLó_@ % hÙ1ͤ¨•+W–É“'{dÒÀ×G}Ô|þ¾+·Ür‹-¡h°Ð’%KLèÿdýúõ6ÀHK¡iŸÌ ™öšÈT-gLÆ¥`ÚÀ¾ € € € € € yy¤27#´þÏò`/W³„8J'8%xEàê hÎÏ?ÿlÊJ%,O0­Þ½{·½1«7gõ܇¶A>7iÄN"½)ÛÕDí4)|´ LçÎmQ³fÍlI3SõL´„–©„&÷ß/òÊ+1忼O§†nõ’‰¤QŸcÇr›òie¥eË?eÊ”t’={vÝLõ¹ùæ˜`£·ßŽ ¼ñØà*Ïhà“–d3 ,l`P(šcîµK‰1V†ÜfZ Åy8& ˆ€ö3úYþï¿ÿÚ¬C%ô*‰‡C‡ÉàÁƒeÒ¤I6“ÑóÏ?oNÚ>ÇýTš5ôáªå/µM 6”… š²›EÝ7ó˜Ö}Íh4oÞ=cem0I%LÀPL™/ Šo(^¼¸½AìÜÎT93ÁJyLyç’˜W­©ÇÓ2jZšM³ü„ã ÁV¡ÔáûïC}ŽøÐ š,ú¶‰þ<þ¼Ýp¦©)©Y‚ž}öÙ—3óu&íÓ4 Þ¨Q£äŸþ‘FÉ›o¾iJsV÷µ¹k™–[Ó £'žxÂùj`¬¹:G-k¦ýØ—_~i³$™¿Ç¥cÇŽòâ‹/ŠöI  € € € € € €ÀÕ(àÈd"ú¡lÙ²§Li5›ÆÃ¼>mJ}LÃõ m÷¡vmab@«%püøqiÞ¼¹¬]»ÖÞàÔ z¦V9ïz\A4Po–~ðÁ6ãÃSsìšk®±7dkšè—5j˜ŒC5eß¾*²uëq™5ë.=z´,Z´H¦M›f‚Ÿ*™2¾Onª¤Éß‹,^|Î+Ýg2$}cËÔh–‰’%KúÜÉÜÃ5¥Ö|® h¡îkî ›,W67É-l°ÑÖ­1ÁF¦b €ÀUÐÀ ÒñôéÓ¶¤™–ÇÔz ðÑÌBÚ9R:tè¨jŸöᇊf2Ò>­|ùòöxwÞygÀÇ{üñÇmYN 6Ò@"ÃÍ&‚SûDþ^ö'Är@@@ÂO@~ÒLÅ ûÍS¶‹/– .²9Û € €a!PÀ‘iéE“ÕhŽ 4z@[m^ ›h“̤É9’ðaóæÍò /xìØ¤Iyf@ ù4DÓ¦Må—_~‘!C†˜ ™›mÀÎ}÷Ýg³ú¥(®ÏŸ?ßfÚ´i“Íè0ΤÿéÖ­›¤M{åcÈ$=’>}DZµÊ/+V¬°7_õ¦°Þ`mÚt±);Ó@ H%… ‹)"ö5W®s&ëÑv“Åh¥¬\ùiÂçÒ¥Ë*SÒæfæ\º$&É3@ÈcƒÎh92÷Álôûïb²7‰iûZ¦@’C@K¦i¹2 ÞѾMƒ€túž{îq^Ëwê6ƒ ²ƒ´?zÅÔÕ,V¬˜\¼xÑþ°ç|Õù4xéäÉ“£fæ[¾|¹hŸ¦Y:}õi®Æ3¡}­üj{5¨ŽzNç´–ZÓ~™@@@Â[`çÎö÷ýÍ@Ç?þøÃüž]@*V¬(*T°£Nëï™TùZiÀ9:+‚ð°Qx¿Ç´@<®Üé÷\kÎÜxbʵ3ÁF6Û¼Þm†Z2Bo„2è“àß|ó¼üòËQÚ·Ýv[ÀÇä)R¶¬˜,b‘,-Z´N:ÉW_5”fÍš™ÏЦ&°h»)Y3ê“& Òªaí²sç«æI›ÅT¸1™šbΠUtÚµ‹ Rzë-÷³&Í´¹Gl´D~û-¦¬Ûc%Íq9  €@`h¤¥45c‘f2™8eâĉòÐCÙ2îGѲšÅ¯}ûö¢ýŒ–[kРû&Mk¹³Ø>-›¦Ú bÈ™3§èÈ€ € € €á) tÔ‡¼G} iÙ²eö7 gëµr@Û¶mE‰Ö›ÔýK–,q®òxÕlÌ•*U’®]»J¡B…ä‡~ðXÏ  € ÎíÞ½ûOSVm˜¹˜áÎ 2 …n¿ývûGSµjÕ¤J•*¢AEÎAƒ4J{×®]²mÛ6[I§Ý‡,¦&ÑÓO?í¾ˆiH&}ûöÙLF¼3fÌ[fÆyj-£_‚Æšt=ÔªU+窀^5+„fÐ0:èMßaÆ™¬D&=‘Á|„ÈŒbÎ%æ¦ë• ´¬ÛÏ?ÿl‚‘ž4Y‹&ÉÂ… íÊìÙ³›à¤²rà 7H™2eäºë® ^ÔLCG^ 62‰"D«Û|û­˜²lb>£Ä”Ô¹rü¤˜2qT’;·È믋ôîGä €œ;wN&L˜ £F²s,XÐögÝ»w—Œ3Æy ðÑÀyÝvòäÉòßÿ‰ ®—téÒy¼êߪ9rä°AúêsåÊe·ó$¬D@@@°8j~8ž9s¦y¸õ+û€’f-Η/ŸkÔy½¯¥™‰4[‘¾:G-Ùîo0èÛûc­[·–FÙ߬5³‘û þþnÒãÿfžZÕûeú»BýúõEÿv>ȤI:2 € €‘"pÀ‘^ JxÑÜØ/n"®»:/PkÐN:Õ9ëñú˜Ióá€ä±ÒÌhä¶9èSè  ¼üw‹IË£¯z³Vo¸ºšbÚ´iR£F ,¤™ŠýUŸèЬDMÚ"ý¤Y&ªV­ê~xŸÓ柃ÞìÕcèS—Lm4 4Ò/¾†üùEttšüHƒŽzõŠ)uf¾û%ù åÕô-ÙÆ€ z 4?~¼ j=d"M5˜Uƒ‡´Ÿˆ/ÐÈ»u•+W¶%Õ¼—3 € € €á-pìØ1›YH*]º´”,YÒfÙwoµ–-Ÿ={¶|üñÇöaVý}9C† v½¿×6mZ[‚]ãÖcçÉ“Çõ@’3[±>˜TªT©x3ëCR:R6=.qÖ!€ €@¤ $(àH/nÇŽ=L*È]f²¿ÍmvÿC\ÁFÝ­e,4Ú›’W@˧5oÞܦx}ÿý÷åÁôÙ½«YZ¶liKÏ,]º4Vi÷õÿùW_}U´›fŠxá…l¹ ^òV¬4$¦nµ÷ÿóuëÖõ¿ÒÏ ÒìFÎòj~6 z±K ú˜@ ¶ÀEÚ¸qcY½zµ „}ËÔÊ|ä‘G\?ÆÞƒ% € € € ΚUè[ó#î| Z6]^ÕªúªÁ<úðº/^´%Ç4 ¾Žš Èý>”fÒ²dº éosçÎ}pIƒ’š5k&:t0ñæ‡ãS§NÉ‘#GäðáîQÏ£ûëX¬X1Ñ #@@߉ùKé²I÷øR‰%Þ7e–V˜¡Œþ1è Ôii¥G}Ôdt7¶C$ÐÐwÜq‡ý²5}úti×®]œGÖmûôécÊ…½.C‡µAD¾vÐLI;w–åË—KÅŠeÊ”)R»vmMõ‘O?“•BäÇÅ|a1‰“$Y‡ÜOÌG»Ó €@ä h¹Î»ï¾ÛõíÛW†nËŸEîÑr@@@¢W@ËŒé¯ï½÷ž-]¦C\4kÖ,Šf¿×ìÄšQhåÊ•¢‹tÈ;·´iÓFš6mj’ÕhÎ2húÀ­¹we~wNeË›µoß^Úšôúºû={vÑÑTöp_Ì4 € €@€‰ 8²‡6Á™G?š?ÜÊhÔ¹Ö±ýóÏ?]칟ÿšk®‘%JˆÉŒdK]hêIH~}šãÞ{ïµ_ÀtZ¿Œ2¼üòË6èÅ_´Y‘4c‘f0rŽúdÉ×_-§O_4ÇÅ”¦é)E‹frÚ|4È;ïˆùâ(bÊdÛlC]ºˆ<ýtèƒ\`@ ¢ô‰Åûï¿_-Z$=zôQ£FEôõÐx@@@¢Q@³ }ÿý÷2iÒ$›}HKœiEŒþýûÛ Æš¡H†6mÚ$7n´¯:½aé_¿¾ÍR¤™ŠôaWgæ#_ŽzýÝZË 1 € €„F ÑGÎæTªTÉã†ÏQM ™Nþúë/ûG¢yG;÷å’O@»víjŸ™7ož\{íµŸ<}úô2cÆ Ñ’fú´‰¯Aƒ GŒ˜!=VÏf12q†&m­ˆ¾šOLj[1A‡"Ï='òàƒ"¦´5 €@”hf¢1cƘ2š¤U«V‰ºêÇ{Ìô/ŸÚ'Ç—¨c° € € €&pöìY9qâ„OžEB‚>("€ €%PÀQéÒ¥ï2Ì™p×°sûöíºæ˜@°p8òÔSOÙ¬ÕªU“ùóçKÁ‚ÝV}REGçðñÇ"æ°¦†vÌ’"EDúõs®å@ Ú4=úOûì3™6mš¬X±Bô·d­V¡U-ræÌiÇ&M½sZ3éwrÓ¥KçzÕQÏ;g3 i$ÿþûoûš%K©ZµªT©RÅ>«±2 € €¤€ŽÌÍ%7u»ìÌnÓL"€@ 9r^jÖüÙd%úJn¼ñF™3gN’¦‘5å³å¡‡DÊ—ùùg2…á?š„\5ýÑRËxΚ5KŠ/.š•¨aÆ6ͺ i¶¢Úµk‹y§HwoôG}d–*V¬(Z4k֬F@@@hÖ¢¹sçÊ”)Sì÷l×LÛµk';v´%Î4˜ˆ@@@ 82‘íÛR¥Jå:ž™Ox=&×ÞL €@\˜Zd³gÏ–›o¾Ù ÕŒkS¿ëŽ;i¶™úÚõ¤zõ&³QÑ”µñ ¦Ü¶¼ô’ˆI@!ÿûŸÈm·ùÞã¿ÿÄ|1e³å½÷6ò­ÄR@ :4‹Ñý÷ßoS°ß{ï½òÎ;ïˆ>©ƒþh9~üx©S§Ž)µÙS®¿þz»þ°ë5…û·ß~+ß}÷8 E‹µå@õ)K@@@¢YààÁƒò믿ÚqóæÍöU—Õ«WOš4ibÇ%JÄýµW@IDAT"Zµj•èC=šmXÒLC·Ür‹têÔIî¾ûnÑìE  € €$T  €£‹/®s/_a‚ò™?Z $ôdlq lذAZ´h!‡¶.\Xî¸ãiÙ²¥4nÜ8  !­±]½úJóÅñ>“ªv•)[ó 8ë[¯['æØ"·Þ»æÔòàƒ"š¹Hã —,‰™3FLf$Ïí5óí+¯ˆ˜Ø(¹öZÏuÌ!€D¯À¸qã¤wïÞ’9sf™75²‡ššØ»eÆú&Ø(f3ÍFdX17sÅÔås÷ÊîC‡Š h4dˆˆ&šèÕKäƒD-™81vRóæWög @×_]žzê)©P¡‚|ùå—¦Š;!æµ&bu‰„Õ´í ,Ò¥KK·nÝì–šåO0e@@@@ ¥ \6?ÜjqÍ<þ|1&<.YÊ)P €}0GÎѱJ•*öUŽt8vì˜Í¼xñbÑq„ vÔuº¯~_×ìÂÕ«W×E  € €$‰@@Gz&Ñ'C† MÌ·…uÞ¼Ž^³fÍb-‰Á€Á èÊ6mÚØR3ú¥òÆo´=z´lß¾]4ðHGÝNoâê—LM“ÛªU+;ê—Lý"ÙªÕD9wîc)\øoY³¦¸¤uû?\>ÿ\LÐRL@QÆbžb‰i÷Ù³b2MˆÉF!æKgÌ2s*yÿ}1_FcJ«=ü°ˆ¹—,Ù²w­ì òF%ýúõ³?vjI4_A±¾®ZÕí9B€‘/ –!€ € €¤XÍrÿÞ{ïÙNwïÞm~ËM+wÞy§Ô®][Š+æ‹)"î(|hrͬ£˜ÔôZò¼P¡Bö!V-¡Æ€ € €@R ¸…#Ä}h“¶ó„yòü&ó‡éb³eqðé‰'ž¸ùSW©AƒqïÌZð+ ed´äLŽ9ì,µjÕòØV3Dè(:žôÐC¶ô…Ö.W®œ­û«7Ž:$ôæTBÏö„£€¦É}ì±ÇDŸRYdj—•/_>ÎfjP’Ö×ÖñâÅ‹ö)ÍxôÅëMªÝ™æI—LòÍ7©M’ÿÃè÷LïïšéÓûßÞ4ÍB‰Lš$2fŒÈþýù×b  ]C† ‘¡¦.§Ë.\¸Pô‰J@@@¢]à‹/¾0q>"Ç÷K¡÷T}ôQ¹ë®»lv#¿²@@08àÈdYÙi‰2:¯ÃÔ¾læSëüwß}gGçºÄ¼nݺ51»±+ðòË/Kÿþým‘Þ¤Õ4¹ NœHgž‚ib25±A@ºïÔ©"õë'ä(o«YŽtd@ˆLÏM]M-Ù™TAAšaoĈ¢åuµÓ X@@@¢Y@³i¶"ͬYkÖ"ý¾ì=ꃧ¦¢D4Sqí € €)@ à€#s­…Ìè 8JL£àÅ% $zcVoÔÖ¨QÃÞ¤ML†¯,Yb²,(Ò¾½È½÷Š©ñ$Íã  €)L`Ê”)òÀH=äí·ßúêžyæ=z´ r­oËfË–-ècr@@@"Y@˧uìØQ¾þúkûpŽ>ø£™í@@H© 8J©\É* itµá5×\#³g϶OºÒópŒ¤¶9Åb¶Ö€£½{E do¶AˆV'NÈÿþ÷?{ùŸ|ò‰)9F2dÈhŽAƒÙ`£† ʼyól–胱# € € €a. DÎ̾úàMÖ¬YcµxË–-¶4ÚöíÛío¿ú°O0ß½c€ € €„¡@ÀG&£ÑIÓ~»S™2eÊœ.]:eax4 °èÞ½»8p@>úè#)^¼x@mûë/‘n5JäìB°Ñ ¦@| <ûì³røðaÓÜ`Êp®¹sçÊ=÷Üã{ãx–Ž2ѰaänݺÅcÅj@@@ÈЇFçÌ™#3gΔŋË… ìŤM›VjÖ¬)5²ß³õaœeË–IçÎåüùóòÖ[oI¯^½"÷Âi9 € € 8àhÛ¶m¦p“çàp8¦˜%<—2‡þ>üðCû%µmÛ¶rÿý÷ûÛ,ÖrS¹Fvì1ßg@X`ÕªU2qâD¹å–[dêÔ©R´hQ𚘀£qãÆI¿~ý¤Zµj¶Œšfêc@@@@ Ò4PèàÁƒvܸq£Ìš5K–,Y"—.]óÀµ4nÜXZ·n-ÿüó,_¾\¾ÿþ{Y³f¼úê«bÔsŸDòçÏ/ß|óh € €Ñ"@øB´¼Ó\çUصk—ôîÝ[ .,&L¸=šÝÈ”û–ÛniÙ2àÝØ@ Êô‡Ñ=zHúôéES¹,XPš6mj=zô¨äÉ“'`¡É“'Ëã?.*TE‹IΜ9Þ— @@@ ,zã7dýúõ6ÀH3Ñk6#÷AK¡µhÑBÚ´i#­ZµòøܧO`ôÛo¿Ù,€tîÜ9;v¬ýÝ×ý8L#€ € Ò8Jéï0×—/_–x@NŸ>mŸÉ•+WÀíÒ²iæû«ù"ð.lˆ €€Œ3FôÉÌÁƒK¹r嬈öEóçÏ—3fÈc=Ò'Ÿ|"<òˆ”(Q¦‘Ï—/_@û± € € €á"°oß>9r¤Lš4Iþý÷_Ѭ½… ²Y|õÖ×’%KJ“&M$[¶l~›®Y*UªdÇîÝ»ûÝŽ € €¤tŽRú;Ìõ……À¨Q£ì/O<ñ„ýšÐF™ 8  €,°gÏ2dˆ”-[Vú÷ïïÚï®»î²?ª~ôÑG}ùå—Ò©S'ûÃë·ß~ËÓš.I&@@@"A`÷îÝ2bÄÑ̽.\:uêÈ AƒäŽ;æÓF@@ÂZ è€#­O¼cÇY·nMAzòäI9{ö¬0iYŠš(‰"EŠØW}: mÚ OÖ˜4_6l°_b+W®,/¿ü²¯MX† €@’ hù³3gÎÈøñãESÁ;‡L™2Ù”ðúCëï¿ÿnK¤9×y¿®Y³Fî½÷^Ѭ|‹/¶OyzoÃ< € € €á(pâÄ éÛ·¯è7/^” Øßh›7oŽÍ¥M € €D¤@¢#€ .œ{À€Õ–,Y«Æ±/‰téÒÙzÇ=zôbÅŠùÚ„e„…À/¿ü"_|ñ…ýš:uê Úô×_IÇŽEÓìN›6M2fÌðñ¶mS'àÍÙ@+0gÎÑÌDíÛ·÷™UO˪iÀÑ”)SäÅ_ô©¦?ÆvéÒÅ”ótÈ‚ ¤|ùò>·c! € € €á&pêÔ)iÖ¬™¬]»Vn¼ñF8p 4nÜ8ÜšI{@@ˆxDES”)S¦m–,YvÍš5«ÚñãÇBÐWf{iÑ¢…ôë×OvíÚÐ~l„@r tíÚU†*sçÎMô©—.]*íÚµ³Áu¿ýö› >\ªW¯ðñÖ¯ÿ?öÎ^ÆêãOö}—B²oÙ•„”=[¡EÉžõÉVÖ"¡H’%KÉ’ÈÉRÉ–]ÈV"ûNÿçw¦¹fî¹wæÞyïwæ÷|>cfÞ÷¼ç=çû^sfÎû;¿G¤H‘!C|>„I€H€HÀ¸ÁÝ(C† òþûï{$‚ÉVˆ¿§OŸnEž !èöíÛEÅåRªT)OE¸H€H€H€H€H€H€FàæÍ›Ò¥KÑ{R¹re³ˆæµ×^“Q£FÉ—_~)7n”Û·oÇx¾ .˜{!Õ8æi)6Š @¬øíp¤_ø{ªëK¬óBݺuK¾úê+³òþõ×_——_~9V çA$`%K–RÈ >úè#ãÊåëyN½ãÆ3ijàj„³;v” øZÞüéÔIæJO=åóa,H$@$@2lØ0ùã?L*µlÙ²y$‚ñé…^PQë3ñZ¥J·r{öì‘Áƒ RöîÝÛmß @  `^õ™gž1é¼±@)À×­[e‘L¥J•äÓO?• xlR‹×©SG~úé'³€¦ÿþËq# @`ø%8*X°`9M­á1÷Æ}÷Ý'9sæ”Ì™3›UõçÏŸ—?ÿüSþúë/9zô¨É“ìÚd¬Fxçw+à(à ` €U/É“'—GyDV¬X!{5¯™þÝÇØ´1cÆH¯^½äòåË’)S&éÞ½»´k×Îëßè*ÔÌkòã"ÿûŸèÍÞèJr Ü!€ïV˜xÍ›7¯ƒîì‰ú iÕ 8BZ5WÁR¨á{œ)'Nœ(É’%‹z0· @€úÈío5¢€¾ø@OüÑGukÞdêÔ©òØcIµjÕÜöÅæ ܺ(‡A$@$@~@:5¸ÁµÈŸ@*PLðvQk=¬=z´?‡³, D!€¹¾óçÏKúôé£ìóuÚ5k¤^½z’}:â5_@|ðänä<‡Œ0.G‘ÇݼyÓ¸EÞçïûãÇEfÍ©RE¤tify  p&pòäIx)% ò'p'cÆŒæ÷Þ{O²fÍêÏá,K$@$@$@$æNœ8a¾‹â»dË–-¥\¹r‚9¿ 2H£Fd÷îÝ~Z¿~½qÝLœ8±,[¶Ì£ØÈïJy @‚:t¨™GE*ðo¾ù&Îb£ï@$@$@$@$@$ >9ݾ};º\ºJél ¸,XPöíÛgª£à(PTY?¾Õf˜Èj×®Üwß}Q-T¨T¯^]æÍ›'˜DC^q&ÌfΜ)5jÔˆâ|¥6¨‰’ܸAw#P± @$³T±zëÖ-¿Ò©9«@ ¤¹Å¸·# x"€ï›ºQ¶lÙ"¿þúkÄóßÿíVó&*Tˆ…0—7Í-ZRåô!üO?ýd„ôH‹÷˜$@ö'ðþûïKŸ>}t¡eióÂD €ý ø$8Òùgœ]Õ×9²gÏžåøñãî3 Î~<9r$¢4Ò€0H ¾ À¥{øÁë-:vìhVëM˜0Aú÷ïoŠa¢ “mƒöv˜ÏÛ/]?^¤pa‘:u|>ŒI€H€HÀ@:5¬ ¯_¿~¬ˆÀÍA$@$@$@$@žlܸQ^{í5Ù´i“\¹r%¢ÒЗ(QB7n,ÅŠ3âÅ‹K¦L™"ÊàØ^½zɤI“dÆŒ‚ùÌ¿¸–‰(¬/P¾V­Z‚”l=òÈ#®»ùšHÀ¦>þøcéÖ­›ùœ@ŠDü~e „ŸGÚÕ®ÝÕI…òú~‘ë6_ßP;W[eo“ þÖËò$à+•+Wʺuë¤mÛ¶’+W.¯‡!ÝÌý÷ß/õíÛWvíÚ%³gÏ6öÞ°ŽkèÌëp8Ò|   ð™ÀÎ;Íêò6mÚHòäÉ}>ŽI€H€H€H€H :XdõöÛo›…VI’$‘Ê•+g’R¥J™ç ˆÓ Ý[=p'Zµj•@`лwo9r¤|òÉ'RµjUã€#×DF8ïâÅ‹¥bÅŠÞªåv ˜2eŠ`‘ 2Ài>K–,6j=›J$@$@$@$@$ŸGšRm=¬¡“UõuœGÛ·o×RšCê¿È“'ó%ŸI ^ôì99Fw#4ûíÛ·7“c°ÿüóÏMû °vê\ƒH€H€ü&w#DóæÍý>– „&mÛ¶G!ÜØ¿çž{Ì©Îð:sæÌFä]Ï<(/¼ð‚üøãR²dIS×<Ý!Ñî«Y³¦IIÅ[pŒFš5¸ááéÒ¥“… q“ëv¾&°'©S§J«V­óþfË–Íža«I€H€H€H€H€¼ðIptàÀuåÒ)eEM:!Ð5þü[¼ÖÃŽÓ§OK=ÜJ=þøãnïù†¬"pó¦¨å÷1Ù¼yº:½fÜ‹b:Wë֭ͤ¬¿1ñÖ A)S¦LL‡q? XF@áææOîܹ¥R¥J–‡“ ؇æ,jÔ¨!ýõ—ÇF#­|éÒ¥¥zõêæQ¡B7§ÌÉ“'K—.]ä’æG*5¸%K–Ìc]þl„“QÓ¦MÍÃõ8§ðÏpLB9 €ý :Ô¤P„k<\æsäÈaÿN±$@$@$@$@$@Qø$8Ò£nëã} F úã?‘>Mž8qâHááO\¼xQÚµk'G8,kÖ¬R¾<²´1HÀZgÏŠ<󌨅/~äþ+.÷é„Xˆ‰±iÓ¦™É¯út ‘ €UV¯^m¾O½ñƼ1cdÖK$@$@$@6"ð÷ßËO@}]éùÓO?IóæÍeÒ¤I‚Ž      Ð&à³àt•Ô¯ùòå«£³Utä–x7¾vîÜi¾"«T©’¼ÿþû&G»¯Ç° øK@æ¡4iDFÞ+:u4®\ýQýwRíÄþY4_¹èJA÷VïÞ-‚}-[ŠÞ(vßÇw$@$@$¯¾úJÓ‚^0¹1•å~    Ð&Gæ… Ê‹/¾(o½õ–ßM‘"…T­ZÕïãx @è€k²8Ó+"Ýb† äᇖ:è\kùðÃeÖ¬Yòúë¯Ë'Ÿ|‚{:ÚGÞ~ûíÐÞ‘ ¸Häö·7êTôƒŠ‹ hѾɓ'¿îÃ!QŠ ü{ï½gV:hš¶(û¹E@çÛôG°Hž<¢+lD–/ït€fÅ_ Îá­5õ’ºuE~üQt• {© Dý?à¾ïH€H€HÀH§†Õ¢XÉÎ    ]5{«V­dĈ²zõj#:wí-nì?^jÖ¬inø»îãk ˆ “'OÊc=fÄF2.[¶ÌˆœuÁ!mýúõ2cÆ I™2¥À)íàÁƒ&#ÅFNJ|&    ð à—ÑÉÑ£G¯èë!ú\JíQŸAJØ/ÇéÒ¥3¶Î°U¥Ð(&ZÜ_|!*0ùö[‘þÙjVü=ýôÓQrŒâ\®u¨‹°<ñ„È™3"jB¡7…]÷Фפ„x0H€H€HÀ_/^Tç¼&ÝE–,Yü=œåI€H€H€H€€À¿ÿþ+óçÏ—iÓ¦ÉóÏ?¯iߟ‰¶He4tèP0`€Ü¼y3¢,Ò¡!¥îC=$™3g6ÎáHý>gΦ/Š Ä$@±%ðÛo¿I:ut¡äaéß¿¿ù òV×sÏ=' tUå8µ—/Q¢„Ô¨QÃ[Qn'    Q±9YäÈ‘ãZ¿~ýäÍ7ß”¿þúËüÁ‘#GŽÈ‰'äî»ï–ܹsK®\¹Ìs¶lÙŒ»Œóø„~Fnzo’$‰Šˆ®@xuîÜ93é¨:•[Y·ó¡ö¬órúcWôoP¤{÷·|o¼ñFD7gÎùî;‘‰#6Åù…fÔœå"û÷‹|ü±H½zq®’ €Ï8¶ùŒÊ¶·nÝjn:U®\Ù¶}`ÃI€HÀÛü¡Å²$@ÁHà›o¾1sg[¶l1Í[°`<úè£2jÔ()S¦L”&c^í…^µk×JñâÅC¸ºkjöŸ#.!0ï¶xñbI›6m”z¸!x pl ÞkÎ-ƒkQ=ȼté’L:Õ¤iŒ‰GªT©tε{LŸŸH ŒpŒ £‹Í®’ €ˆÊ‚ˆ‰ð(W®œ-À._¾\:wîlÚŠUaÓ§Ou»14eÊ“§úÏ?ÿ4õ€IÖ¬Y¥R¥JfÕš§ $_NheݾœßîeòçÁ«sàÄU_•@¥J•Šè–^:µ4HäÞ{#6Çú….@ÔüæŽômš²\Úµ‹uU<H€ü&À±Íod¶<à×_5ívÏlÙ6šH€| À±ÍH,B$`)³gÏÊ®]»¤|ùò~/¢ûVí–±èiÆ &íP·nݤuëÖ2fÌ™0a‚q)jÑ¢… Ñ=÷Ücúñ…Z5·oßÞ,fëÚµ« 6L’'Onö¹ ÎϨ¥2LE‹8ÖR¬<`8¶ %+ E‹I“&MÌ¢Ü%K–HµjÕX;«"ãÂåJ³Ÿ$@$@$p‡@@Gwª³Ï«… ƹ±üñ‡ÉQ½yóæ(uÁI®OóæÍ3ªU«Ê»ï¾ëóŠ3+ëŽÒØ0Ø€É;\¸q¹Æ8ÞíÜÁQ—."ºPQW"ŠNºž‰¯I€HÀzÛ¬g g à(®Û@$_8¶Åiž‡HÀcÇŽ™›î{öì‘ È+¯¼"e̘ÑSq³ éo!4zÿý÷eÍš5’,Y2éÔ©“ôÑUI÷þ·ÒiìØ±Ò¡CyõÕWåÓO?•/¿üRz÷î-8\E° ®EO W»—È”)^ØûfŽmÁ~…¯}øÜŸm•-[6ü °Ç$@!À1. Y ØŠ@¢8´6±NœdÂÄH;µqÁŠ/oÑÍ[o½e&Z,¡ãŸþ‘Õ«WÇ©§N2“LžÄFž*^µj•4nÜXp\LaeÝ1;÷ïÛ·O°B°V­Zfõ k‘¦gO‘œ9]·ÆîµêÉä£D'üD' cW" ØàØ[rö;‚#ܬBêZ „2Žm¡|uÙ7~‡8 íÝ»WŒŸ5ó^p(Ê‘#‡´jÕJœóAXÜ„ïgï¼óŽT©RE jذ¡üðÃÒ¦MㆠG#§ØÈÙóbÅŠÉŠ+tÑÒãPAnú×­[W¶oß­ØÈYŸíG€c›ý®Y¨·xĈòòË/ëÜhNAJ5ŠBýг$`ŽqÖ±eÍ$@$`g0hÁïfFèˆÃÑ]ºªë5Eò†Nœ¤s¢¹uë–óe”g¤ûì³ÏÌ6ÐÈS߯_?³b+Ja‹7\»vM:vì(ׯ_õ™PGË–-åèÑ£u¤H‘B*T¨ +V4)» À‚eö¬Y³äÂ… ¦Ü¡C‡Ìе‰'zµá¶²îˆÆ†Á‹'Dvïý[2dˆàï3²»0”(áxÄÉìÙ"½z‰/.êh%’4i\käñ$@$à;Žm¾³²{É›7oÊŽ;ÌÍ,»÷…í' èpl‹Ž÷‘ XMàÀ§jÌû`#|.Á‰îDX|‡RÜž[Y·[ÂàþNÖ•"ÇO¸AàCͪ@ú4‡u?Wku«ÎÂzI€H@Œí$ǶðþKÀÍ-VÓ3H€H ðw[(\EöB‡R™=öØc‚T÷ŸëJ&§Ø(rñ] ŽDçÎ3óLïjŽuˆ”b#6Š\7ßÛŸÇ6û_ÃPï\ 6ª_¿¾,_¾œb£P¿àì ǸÂdU$@$‚6mÚdíÍš53 F-‹-2©ÇC°»ìÒ|,X–<%]É¥L™òZÛ¶meÆŒÑþ¡ ×ýàÁƒMº1×ãñå9î!> tܾ}Ûƒàj´ÿ~¹qãF@N±`ÁA®AgT¯^ÝØd;ß{z†©\¹r»0õÇD¼w¾°²nç9Âái á2T¯žÈÚµËéîªT©bY×ëÔq¸)µnmÙ)X1 Ûø‡@ÁÿH€BǶP»¢ì Ø—ÀæÍ›ÍÜDDsçΕÆÛ·3ly‚àØ– øyò:tH $:×o\øu~?†#¸›H€îàw‡_‘ 8@ï±jÕ*Èzˆ 6Cè3ºhŠ $IüJ¸E¬6$à«àåú»öOÿxæóÍ7_wïÞ]|ðAQç#×Ýn¯aÉŠbÈoÔcÙ{꿸té’Œ7Îù6èŸ×­[çÖF¬`ó%"§óZ¼xq”ì¬;ÊÉBxþ¿úJ4•Ú Y¿~½IÛU.RGjªòXEîÜ¢nZ"ü}+|<ˆH X9þXYw ‹÷&@p”&MÉŸ?¼Ÿ›'$ ;°rü±²n;1f[I TÀ.¢p6º|ù²|ýõׯõ#TúÇ~„+Ç+ë+=A6|Öa>>ºùÒÐè-{A$`VŽCVÖm¾l' XAà÷ß—Hž}¤E‹¢š ÏΪƒ•€O‚#m|>×èOµ_½êºÍŸ×Y³fLõèÑÆ?ÎÝ»w›œ~þÔ]Yˆžzê)E<+ÁŽ;}útD¸á—9sæˆ÷ѽÀä&®\¹bŠ8pÀ­¸•u»(ŒÞ|÷Ýw¦·1ý€~à_d @PàØÔ—ÇòÆ!+¾‡”.]Úòsñ$@$_8¶Åiž‡ìI“˜C† 1 ÔR¥J%˜?r}\»vMnݺÑ9ˆ’ .lÄGøÎ„Å_eË–•Ô©SG”Á ,DÜԴiÓLv¬ÊìÕ«Ý>Ü(ñMl pl‹-9g% .H×®]%cÆŒÆÕÍÊs±n Ð%À1.t¯-{F$@Ñ€°höìÙFßCŠ)Lv«—_~YjÔ¨!¤2—€¯W?¯+"ý£Úêú>6¯a©åúLJüÑÁÛ¶msk"VÑù˜ôÊ•+WDqL?>⽕uGœ$Ì^ _$&z]ÞCgKöì¢+½—ñ´G5sÆÉÓ>n# »°rü±²n»ð d;án„(UªT «e]$@$r¬¬¬;ä.;Dq$ðË/¿HÇŽ5úý²gÏ9|ø°?~\N:e³áh|õêUý]¾Càœ…mµk×–‹/š÷Á•:}úôæûSÛ¶meÒ¤I2zôhÄF(ãû÷ïO±Q¯·–€•ã•u[K…µûCàÍ7ß”cǎɰaË$@$,¬‡¬¬;Xø±$@$XÜŒ>­Zµ’Áƒ˦M›Œ[‘§ºV®\iîµ7kÖLþþûo³(èĉÆé(²ÞÃÓñÜú|u8Êã‚âÆþýû¹¼ÕK䈆Ç)4ÂÄQ°‡«»Úš!C¿šŒI.×@}éÏKÃʺ]ÏéËkLä!¿¢3]TŠË–-óåÐ/Ó¯ŸîÇNœxU~üñG“N b¯˜.G?ü úa*š¦&¦Ò"Ë—‹~ ŠNdŠNVÆ\ž%H€‚—æ Âv¡¸Iù3Û¹?Ôž­¬¬Ûßë€|ÂPÞ;Ç6¿bÅ I–,™¿U%Xy Ž =OL¶%€|ésæÌ1íÇMy8®†CX9þXY·¿×‹“'OºmóçÏ—L™2ù[Ë“@ÐøçŸ¤qãÆfÂ)€¼ý]'I’DÐôx¸œ< XBªõ7šç‰'ê\ÁDS óQ˜\mذ¡ëa|m¸nS§N5-…ÃU¸„•ã•uû{}Μ9#ºþnûì³ÏÜqú['Ë‹ù<üðÃ¥B… Òºuk"!2pŒøè£L«®_¿nÕAÖDK›cå8deÝþBÁ¼¾›.ÇÍ% dEÁg3ƒH€âƒLP÷D¾ýö[³¨Çõ¼ýô;Dé=ñÄR³fM9zô¨qÆçtݺu3 }¼ý>w­º¸#nÞ¼éfÂâZޝCƒ€¯‚£ÎQÍÅ—LÿȹÁœ;bñ ûEgÀÎ:ØãܹsnMôWpä9+Á—ø iÉo¿ý!> ‚¦ÅK¬‡¬¬Û_8Hû‹{„íÛ·7‡†Ë‚ 9±< @àÀÝ ÓæÍ›'kÖ¬‰HGa8!ZåÊ•eß¾}²téRY²d‰Ì˜1C¦OŸn²Tá·9¾C¾øâ‹ÆÉ5“SL­¬X±bÄwú#GŽMŒÐ%à“àHÿ N8ÅAú|—:ÞV$[â‚=&œüÑÁ‘¿œø;™¹¼«ºÚʺýå •"\òæuˤço5ñ^~ï^<ð} éÔUªTñ©ÎÅH«æ‹à¨CQu§èÍkŸªg! &‡×Ï;ŒwvZÆ­•ã•uûÛo\çÈ×Úß:º<G˜œÀÍ  _dΜYð@`âßóÃ!¬¬¬Ûßká,Ü]\¿Çø[Ë“@0€ûâÅ‹ i 8î½÷^iРA0v™mòƒæsˆHÀ±Í7xv™“Ä üçØæÛuõ¥\S"£gÏž\¼â 0–! €ÏhççôÙ³gu¡sÌ ™–ÒÊßXVÖí/Ìçá:sŒó—Ë“ ¸À‚°h>[¶lq¾ó‘:uj#‚ÀB#¸ýB4c½zõŒkDF p­Rð[Â#8¡~ˆð¸uë– Á‘ÍßH“&à€óWŒÐ%àëÕýÅÞŒ…·ë6_#e—kà9Ø#ò—ްÂÎ5²ÇVÖíˆó$@±!`å8deݱé+! Ø€ph„ &ÅÄ©ž¢+W ª p|öÙgåé§Ÿ–ÚµkûœÕâ¥-Z˜‡§sp x"à“àHsë­PW¨cŒMG/çË—o¾§ }ÙggÞ>gùG}Ôù2hŸázápJð'n܈ÈLgsªÖñÆÊºýi£ËBp„,HåÊ]ØjãÔW—’¢E=ß±ÃÎØv 🀕ã•uûßS{¡6~TàæƒH€H zVŽ?VÖ}¯¸—BŸÀáÇåùçŸ7+¿çÎKWÇпä졬¬¬Û.²h€ \ºtɤ<þ¼Ìœ9Óç›Ln«#  X9YYwŒc øÖÀÅBð¬Y³úÍ®åmÛ¶•õë×kæûäã?6õüùçŸÆ‘®DxÒž! uÕªUMÆ¿OÆH |:tèjÁ‚'jý¯þwޤ*ä˜÷ÁlíÔ©“Ï¢{æÌiÙ²¥[:µ<šÃª¨Sññß ‚ñ)ò‡À… üjæµk×ÜÊ;- ±ÑʺÝN¢oþùGôƒV¤n]Q›àuq>L} MkÒ£ÁáˆA$@áDÀÊñÇʺÃ顯H§†(Uª”yæ?$@$@Þ X9þXY·÷q „6¬ÀÄÄ)Òý`ÎhÑ¢EšêOVj^óAƒI1ý1]¶lY)S¦Œ”,YRR§NíÆAç“dóæÍFPQ&J1_„@Y,ªV­š™xÅñ  ¨8¶EeÂ-Q àwcíÚµóÄHµ›\  vã‚ý ±}$@þøGÓò<óÌ3²råJ©Y³¦Ìž=Ûè&à:Ù¬Y32dˆ|÷Ýw2kÖ,¹ÿþû#ªß¿¿Lš4I¦Nj´©R¥2ú ˆ–'NQŽ/H Øø,8BÃÕÅh}¨ÓÑtݹ3°kÅÃ×xúé§eàÀ¾Oðr‘¿ø@HåO?~<¢x’$I$òxýVÖí×°²n×ó„ÊëìÙE\Q{ƒÕ<¬– Tè‚L™7OôïVÔ">Pµ² VŽ?VÖôâ§°ÅG@¬Ì  ˆ™€•ã•uÇÜ3– à!0jÔ(#Â*VŽÃ‰ÑÕs%¸ñÍIÒà¹fl‰½ X9þXY·½©Û£õpÃÅ*¬~_ºt©Isi–³•$@$à `å8deݼ~$@$à$púôiéÓ§Lœ8Ñd7‚¼V­ZÎÝŸ±ëÖ­&M9æ¼ð ¢f/Ër# ;8©~òäÉs–^Û¶m“5kÖÈôéÓMÞÁöíÛË“šŸª…ÚÏ 0ÀXkà ¤º²£Øí† š3nß¾m¬Ïœï£{^½zµÛîÈïï×Ot’T4ýŸÏ‡° ؆€•ã•uÛpJÁQ ²  °"`åøceÝau‘ØY[Àâ«%K–˜Ô=÷߿Ǿ`aÅFÑp# ÄŠ€•ã•uǪ³<È/&L0nï³gϦÛ,nK@IDATØÈ/r,L$,¬‡¬¬;Xø±$@ Gà_½q ‘îIã;îýoܸ1F±‘³Å0jù裤sçÎ9¡ðÙ–ŒàHU¾õÑVDÙbÓ L"á?ÅC=dE¯¾úª >\z÷îmì¿yä¹çž{Bb²é©§žrC„˜âìÙ³òå—_FË;·(ëˆ÷ÎVÖí<‡]Ÿ/\‰Œé½êº%;vì0èÞKżÇUØ´aƒÈ¢E"Mšˆ/ó±,A$@v$`åøceÝvd›6Cp”.]:ßbS! p `åøceÝápmØGûøàƒ4åø¿ÆÁÚþ½aHÀ>¬¬¬Û>„ƒ£¥7oÞô¹!×®]3 €‹-**Tðù8$ `#`å8deÝÁÆ‘í!ðŸæÞñÊß@*ñòåËKÛ¶m%yòä2kÖ,Y¹r¥ÀYAáFÀépT];>>I’$Çõ?ÂÚüùówÓUjQ1áFÇCakV @ˆ=Û·o—™3gF¼üââÅ‹òÊ+¯ÈåË—#v5zÅCXY·‡ÓÙj“:ËÉ“¢éë¼7¹11éÙ=ÊûQ÷|ø¡Húô"»w;öÁÝÙÿÔ¨‹A$@!KÀÊñÇʺCö‚Dê~ô”,Y2$„Û‘ºÆ·$@$`+Ç+ë¶ +&8wîœL:UÓ—‘G}4@µ² _X9þXY·/}cÌçÊ•Kºwïî’yóæÉ™3g¤M›6>•g! VVŽCVÖ¬<Ù. ˜ ¬[·N*Uª$¥K—6†*0´ð%ðÝ«C‡R®\9ùå—_¤[·nzOy·4kÖÌ—ÃY†B’€Spd:§NEx_ImGªï  k¶¨ø¨_Þ¼yéíârù¡VtÁƒËgŸ}&‘W ?~\^|ñEóã,¯<Í6çûÈÏVÖù\vz¿p¡#­™fêó!ªV­êµLL;2d›Ækdùr‘çŸQƒH€Bš€•ã•u‡ôEÑÎ:tHà”ˆ>   ÿX9þXY·½diˆ_Ÿ|ò‰`aU×®]ã÷Ä< €!`åøceݼ|¾X¶l™œ8q¤ÖÀsLÏädÉ’IóæÍc*Êý$@$ô¬‡¬¬;èÁ²$@n¶mÛ&õêÕ3 hþìI½ñ¼k×.#:ú®^âÖ­[2nÜ8ã`„g,ÀÁBᑚš'mÚ´^ŽâfIÐMu…R£™ ŽRºv[ß—ÂCHU|´_÷Íײó÷ïßÿs-N¯ñá³fÍYŒÆíÛ·å­·Þ’)S¦H‰%$EвiÓ&9räˆu’JÒ¤Iݶ»¾±²n×óØíõر¢B-GZ5om_µj•¨3WœRÎ<ð€£ö;EÜ‹è%¸1H€H Ô X9þXYw¨_ühA”*U*Ô»Êþ‘ @À X9þXYwÀA°BL°b6[¶l\½ ¦¬†ü%`åøceÝþö3\ËÏŸ?ßti=FŒan`ycqðàAÁâK8égΜÙ[1n' Û°r²²nÛfCI Ì üþûïòæ›ošÔgÈ–G"ÜÛÏ—/Ÿ@xôÜsÏIçÎe©¦ÜùôÓOåî»ïŽ öý÷ßK—.]b¥9r˜ÌGÏ>ûlÄ~¾ p'`Gûöík™={öN©S§~BF õ?Z=}V¯—;¡ïóë»úÜCÓ®Ð2 ôGнPF' ¹SCh½‚pVâ9ãèÑ£‚‡§H™2¥™˜{ðÁ=ívÛfeÝn'²Ñ›4iDªW÷Þ`¸IíÙ³G^~ùeï…|ØÁÑO*§Cú¶DZµQS* „+Ç+ëå‹CÁQ(_]öH >X9þXYw|°á9HÀ__ýµq_ ?–á¨Á HVŽ?VÖ0´ìsV8ç/Z´HÊ–-k\ôÇ/}úôñ*&š4iKëÖ­íÓI¶”H€b `å8deÝ1t‹»I€˜ÀÛo¿m Anܸ!O<ñ„ :Ôm/Ò£a¾S§N&…8ÌE`2R´hQéÑ£‡Ìž=[43”ôíÛWz÷î-ª§Hàñô$\BÍ„ 6.«ðhÞÞ½{›ëóÝúƒ¥¦>>Öžü[ïUáQû^½zU{ä‘G̶åš{êÊ•+ÿÕúOø0Á?¨cú`yøá‡MÊ5ä‚ô%¬¬Û—óÛ±L Ò©¡ß˜3ÕËeGéÓ‹ª]íHƒm& ذrü±²îØõÖGᇄÝ8-øìÑl¶’H€‚†€•ã•u @6„\Œ5ÊL²¶oßÞe+_’ Ä7+Ç+ëŽoNv;ßêÕ«åŸþ‘† ¡Ñ¥K—Ÿ»žŽs¸ –;wn©V­š§"ÜF$@¶$`å8deݶ„ÍF“@€k$RϾñÆR¤HÁ÷­%K–¸‰œÒ¨ó¾_}þùç‚ãêÔ©#… 2b£ ˜´kpDÂg ƒHÀÀ]îo=¾»+þüåU`ÔP÷6üÏéÈcA¨û³°FR¥JIÅFÄåË—eñâŲ}ûv“gïÕ1Jî»ï>©ZµjœnZY··Kk¸ &ÈŒ3¼ ºí­ÔŠwp˜‚] B/£¤JˆšX €+VLÖ¯_6c˜·kcåøceÝÞú³eËéß¿¿`e¾Èø>µuëV;5›m%BX1ÿÍ7ߘ|óAؼxi’•ã•u{ƒsàÀãjà\|á­·“@ @]ºtiy饗Ì$l êd$W˜¿š8q¢LŸ>=®UÙöx+Ç+ëöüÏ?ÿ47w6oÞì­HÈnïØ±£Œ;VvîÜ)… 6+êÁãðáÃ’.]:·~/\¸PhðàÁæšÛN¾!°5_~ùE3/ °Ýü•Э‡¬¬Û‹?þXNŸ>mR¼•áv Àøûï¿{ݺuòÔSO™{Þ¾Š…Ž9"-[¶4ÿg‡®xª®aaXÓþýû¥mÛ¶²jÕª0ì}Xt9gºù¯þ!ü¨åðx=oÞ¼Å%Já¥\‡âïÛo¿5ĉ ,È >ÂÄlÙ²¹ ©×©T•Ò¸qcótǬ¬;Ðmµ¢>ý Ò´uªtS¹[ÆŒÞÏ€I¦ Ll„3Qlä7÷ „>+Ç+ë¥+ƒÕ­˜\~ñÅC©[ì $+Ç+ëN0`<1 ¸pºltíÚÕe+_’ $4+Ç+ëNhnÁv~¤F[°`,XÐÐ>Í, /¿ü²!áµk|òÉ'‚¹wìg @¨°r²²îP½ì  +VÑuÍš5ͼy®\¹¢4m÷îÝR·n]9xð ¼öÚk2lØ0QmC”rÞ6 Nè$@¾ðý×õéÎí*@¤i×JõÕWó{öìirK«øÈ팰výñÇeРAR¹reyæ™gŒkΡC‡ÜÊñ DG`æL5/Rg殺Ú«{}MYç½&î!  à!'Ü$@$@$@$Pþúë/c+¹~/I¨«Àó’ „27ʱcÇÌ*|g?_xá¹ÿþûåý÷ß—+W®87w}8í?ñÄ]xq¾    %°|ùrãò¸víZyóÍ7%Ož<Æø{œß—V®\)<òˆÀ¥Ù|àPäØ(H»Îf‘@PðÅáÈk4ßá%ä<„­¬ÉðŸÊŸ~úInܸávܶmÛ‘#GЦh3p?zàÜÊñ ¸ÐÅ=’)“hª>׭úQ±bE÷|G$@$@6&€ÔGˆR¥Ü %mÜ#6H€H€HÀŽÆ'p´¦»‘¯ÛL$`º¨×4³!,Þÿ‹$I’È믿.Hµ†Ô]ºt1{¦L™"7oÞ4iUeùL$@$@$@¡Nb#¤FCZ4Ž`FïE_ýµq#B Zèà™&MYºt©T«V-Ô±°$â$8ríA–,Y¤iÓ¦æqñâEY½zµ­Ñ|XȇêÈÕ‡&­²gÏn>úôéãZ„¯I@ŽÑ”ÅÒ¼¹¨M°w È¿‰ Ã‘wFÜC$@$`/°lÅJÖ2eÊPPk¯KÇÖ’ €m \¸pA`=¿k×.·…sçÎm&wmÛ96œH€‚˜ÀüùóÍy¹råÜZ‰E¾ƒ6+óÛ·o/I“&•I“&É=÷Ü#õêÕs+Ë7$@ÁE·ÄΟýÿ\íbkH€H !Àiz±cÇ „Aþ†«ØóæÎºH›væÌ™©ér >š;w®äË—O-Z$… ö÷4,O$K¹žÊAüèÁ«àà@ç£U«VÉÙ³g]‹ÊñãÇeêÔ©BÁ‘–°yƒ {ú{Y‘¼yÝ»­¢T*X6ð÷•9sf)T¨P´å¸“H€H€ì@àĉûü´iÓÊìٳͤ²ÚÍ6’ 7,ü Eø¾qòäI·Ç¹sçÜ:€Ûp¨Æ*R8l$Žn%Û‘|C$@$à+|&ïÙ³G:tè wÝu—Ûa)R¤îÝ»K=dÚ´iæD ={ö8 1H€‚—ÀG‰ôë'šD¤B‘;E I–,xÛÌ–‘ @  üûï¿Ò«W/y÷ÝwMÕ{÷î•eË–IÆŒ}>•7±‘³‚Lš&§S§Næ±oß>#ÌÆ¼:ƒH þXþË$yòäRµjUó¸uë–üüóÏF|"&·áI@ÇÍ)¢ÆX¢.xòÜs"0*rý­Œtjúç#µjyg„œœ[¶l‘Úµk{/Ä=$@$@$`ø®ôœа„3gŽ™P¶IÓÙL   $ðÛo¿ÉâÅ‹eÉ’%ú›{\¿~=¢•¸±ÉÙ{ï½Wzè!ã®…©^]4צw7n”7n0ÝŒwDÜC$@$`#ýû÷7ii;wî,5²QËÙT   ` €¤k×®5“º9rÄ4 ´Õõ6ë<üðÃFd”-[6:)ÃEcH€šGXåÿøã{ä€L]ºt‘ÈþýûU´ð˜º¤ðfšGXÜHAB`üxÑ…d"p9‚£DGªí–Q£DjÔý>$ e3H€HÀ"Èv1õj½ÑûôÓOËŒ3ÎøÎÓ»woó½g¥ZÀ!M¬·˜7ož<ÿüó‚ß²(“ØÈ[=ÜN$`=xEîNñâÅXÃ2‹À_9ú«ó›Ò´©È£ŠÔ©s‡.¾Ô•—¢Öíw¶yz…šˆJ•*yÚÍm$@$@$`a2D'¢”#FئÝl( @Â@ФÛùì³Ïä÷ß7 *X° tíÚÕˆŒpƒ¼   à!ðÇȦM›¤yóæÑ:ÊAp4RWn^¸pAZ·n<`KH€¢¸vMdøpQçH¸‘9v#+­Þk7B#~‹‚ŒH€BŒ¾ß`¡ËNužÀïÑ÷ÔÚ-Q¢D¦—H¯–2eJùßÿþ'•+W6)¿sæÌA®HŸþ¹ùÞ³mÛ6ãÈK±Qž y¡—X³‰<ùdÐ4‰ I` *8Jà¾óô H GH£æ*6Âv¤SCÚòúõñÎ{¬_¿^Ó®%—²eËz/Ä=$@$@$äŽ?./¼ð‚¤OŸ^fÏž­+àt ƒH€H€H€¢!péÒ%™9s¦9ãäÈ‘C]„{ÊK/½dÒ¢Es8w‘ $0¯`÷®á-š³ypèÓ§qhì´‡wîä3 @Pøäâ1nFzÛ""råÙ±ÃqÏ#b#_ @ˆغu«Þï­#'Nœ0¢¡nݺEé!DHX óÊ+¯ÑE˜¯öpcÆŒ1ǦM›Öˆ’pü}÷Ý¥nHXj^%š½Ý¤ U_ ˆe‚£Û·oËÁƒõKÔŽÜ¥ùj³Jž¾S{¿¤œa æKȶ‘ @PاKø[·n-÷Üs̘1ƒb£ ¸*l øOéÔ°‚G ˆ ¤ƒØE¿„D i†N•hÚùè»sá‚ÈòåŽ2uëŠ|ò‰ÈãGŒ•{?ûLäÐ!‘nÝDR§ŽùL'OŠüü³C¤si–  à$°W!ˆÎŸ?/óæÍ3‹bümiªT©ü=„倀N?èýx‘Y³àä}úx:3OC$@$@$*ºvíjæWú÷ï/UªT •n±$@$v/^lÒŽ4lØ0ìúΞ\ræÌq¸ë¾öø¯ñ©§D^|Q4-¨›£çóŸ9#2r¤H"õêy.Ÿ[5Û­8 òê«"XLíKÀäzâD‡;UÛ¶¢™C|9ŠeH€H 89rĈNª]œw™"68®‹U­P©‡lÛ&Ò¢…Hš4QÏ‚1°dI‘Σîã–ð àÝ¥‚"5ªŒ«TPTíöíÛéÔ¶Û£¦B"¨]£˜J³çè·ÜÇ\E%UIZý¦UW½-±=wîÜű2+ýáCéÔqYŒ¹nÝ:SG¥J•Ì3ÿ!  `&°[—«Á‘/K–,ÁÜL¶H€H€H \»vMW·ïö𦋵&L˜ 5jÔ¾}û&P+yZ  ¸ÀâÝ·ÞzKR¤H!5Šku<žŒÀ¥C‘²eC\à¤ÆŽHçΉ ÎNp1Ú°AdÚ4‘éÓÝ›õôÓ"ãÆ‰téâ¾=¦wåË‹tì(ºh_ô{^L¥¹ŸH€‚ƒÀ±cÇŒØnþ“'O6.¼ÁÑ2¶Â*—‘ ß7(2i’¨³§Üꡃùó篯îFE];«¤75÷bµ¬Ú¿ÿ5×}®¯W­ZåúÖ¼îÑ£‡×•ûÕWrôèÑnÇ`âŒ>N ÁÒ©!èpd0ð  '€ˆEŠ òV²y$@$@$@ A@yD|W€@ù)]Ú'éÍ›7 nLïÙ³GÚêÒ÷ìÙ³›Õ£‰™©œ„h*ÏI$@$GÕÒd›.íµ×äÞ{ïcm<œR ®?È*`×øí7ÜÐß} ›¤¸75 „›jAÓ¢E :t¨äÌ™S¾ýö[)Uª”¬^½Ú#‰­[·šß£%a!ÌË/¿ì±\ 6BüY§Žˆ®»QÇß@Õšpõ@«&—ê\ìHš6­H¹r"¯¼"‚„>2ÄÛ B»` ¼p¡cüƒèb/g`?R~blôEþѦ\ÿàXÈ/‰Tl”ϵËên´ZÕ‰‡\·y{½fÍš(Kë" ‰¼«B'·]Çñ—Í lP_T †•*Uò¡4‹ @Âصk—iŽö:ðì$@$@$l`G z¸Í™3G'ætfN7¡«W¯®+÷‹Î»è*þËÆñ(ØÚÏö øN Q>úè#“àùçŸ÷ý@–$h¨1…@d“?¿£]Gh÷Î"pò”9¶vmG?»vuÜ…Ë‘§PƒjéSÀM NIE‹Š”.-òóCx¤Zðx>ɘQäwî“7RÆë¹y2 ð"S‡úú;uêTó¼wï^#"º¨Önø:hÐ AÚogàžl•*UÌB˜yªŒlÒ¤‰s—eÏéÒÝI› ~%ò@lÑRƒb\ƒˆU×E¸Z5RÅíډܿC¨‹ŒDË–‰¬ZåHkê,:w®£½:xŸåœÏ0dÆŸ‡NcÈöíέ|å‰ÔQÇ2üH=½ýå—_îvÝdž<‘«s-qçu>§Ïç›N0Aí8|-¤SCTÄR 9:ùbóH€H€H \½zU5j$çΓšC$W®\ Ð ž’H€H ¾¼ú꫚ä–Œ=Zt>>¾NËó„8½G, Ø_pw#ÄSO9ž#ÿ‹ÈôóÕW¢7½â£Èeð¢!ÜìŒIp¤Ù Mª°Cš´Ó§E:vt¸L<у«§sXµ-[6‘#D]Ð’É®]-¬: ë%s§NÒÏ¿ÇeéÒ¥ÒFíhækî«”)SJ³fÍdóæÍR¼xqAÊo¤XûSSÕÀñ"¤ëju³hÑ"©K¶x |¦#¶lq<Ûù_¤ƒ8Þ+ÇŽ‰`ÜÃø§»Ý”ñÓK8.^,ÇÀT©ç,XPôú»ŸNEúç!­Z¹oîÒª!èräà.ÿBpäf5¤G>›“i¾Æ,® Ê—/ïú6Ú×Ùô”«uì1üc€ 8J‘"…”)SƇÒ,B$@$@ KG·îÇ’ (ŽzWk‹Îœb2·V­ZdB$@$ÂëÜØƒ«]9äÏ`@ Í̈à!R±¨a¢À±ÇޝÈ2¨÷´=FãÆ"¸‰¡C†x,b6Bˇ:à†¡÷Ô½Æ[o‰|ÿ½Ã…AÿkšÀ¸1Z¡‚¨ Ðëa–ïhÙR4«Ã9eÁ{e–Ãæ H P;¹ úA·iÓ&ó;t‚æÊJœ8q‰ªÂDŠïöíÛËÊ•+Mzï:ªˆA™åªä¬K½x t06ØÝáN?¯¡Õ‚“Pt!°7nDW*îû& &Vz©½„^?ü ò쳎ï^ FÚ‡@|Ý>]_FxH¤ÝÌãÚUµIóIp”5kÖ4GÍèz,ò;úÙ³g(~bŒ° ðùç¢ö|Þ»ºvíZéÔ©“®,8¥lü0à=¤ŸXÉ’%‹²ŸH€H€H ØÀᨠÎ&òä le{H€H€H€,'ðÉ'ŸÈ§Ÿ~ª«ëÈ›o¾iùùx  „#pCïuëÖMÒ¤I#C‡M¸†ðÌ!Gâ¢ÿ½ãă„vL©†[Hh€thºVËk 娶m¢i ½1;P¸¬XṌƌyðAܧ€îÛå~»çƒâqëèÑ$_¾¯ãñŒ< @8€{ÄFHë=~üx0`€ÇncÑì¸qãä‹/¾+ªl…qÈ*ͳ…cã+bóæMG ¯%ìïp'!DݺŽçèþUô2v¬HëÖÑ•ŠÛ>ˆ™&MRqˆªCœ©H=Õ8mšc«Þ®÷;pŒf†—É“ý>”Ø”G×]Û®ŽGª9Ò§O_AÝp|Døë8ƒ|ÎH‡„ŒŒ° €UºˆÓkŒÑoüÈi^²dIÍ󏯭Üv•‚ž?^•þ•ܶó #¤K9|ø°)R$›Ç6‘ Ä3MMoØäÎ[WüMgZxæÏÓ‘ @|À<§f Þ½{‹ëâÛønÏzN ‡#„3U œìš¡GÓ Š4h˜V;ožzK«Ö³§ÞÓ;b#G&¬›Q`zËZH€H fp+Bµ .ȼyó¤mÛ¶1Ô¤IÁ"Z8÷û{ï?ÆÊ£)píšÃmÎ)ÎAZ5Sæ  ßõÍ7¢Âs‘Ê•cn(øž|Rb½l–ғ¦];‡¨ËÛIªVuèt¤+õVÆÛvýó1)N!ž‚˜úRmŸk7uõýý®ï½½ÖãÜþk@0”7o^oÅ=nÿçŸ"¶3ÍHŠ|ËÈIì-¶nݪ°™äܹsRU?ѬÖnêí¦tjˆŠ+šgþC$@$@ÁLËà .ÌÍdÛH€H€H€,&¡QO½ÃU»vm#2š;w®dÌèfmq X= @|8¥9 ¤+Èó—£ø>?ÏÚöýwWÇ)8‚Ãnê©y…­éÔà0ä¼¹ׯ#©Æxv8Ò{íÆ%©aCßnüƵ-<žH€šÀœ9sŒ³nÒ¤IÕùm…ŠYTÍâcÜ«ù¿²dÉâcéÀƒ;zNHŽúœ‰•ÞËŽ”bš´Ç¤ûô%iÆC¸ï©.LSØYÓã?Í $‚4žÑEýúÀèÊxÛ—<¹H›6ŽT¯-1BŸ@"½ æ–ÙW]‹|ÕtÅS¶lY¿Væý¡ ±êß9I„þóã‹T©â¹Ÿp½Ú¯~°5u),þŠ+&ýúõÓÁ¥†œ8qÂŽTì¯ö}ž[Ê­$@$@$3¬AÐá(fV,A$@$@¡Fà×_•>}ú¨ã@~ÁœÉ»ï¾«©BRÈgŸ}¯«DC+ûC$@v!ðÆo˜•Ç7Ÿÿvi7Ûi‘Ž 8B Õš]·‡àD„d™3®Õp9:~\dÇ÷:Ó¦ul›8Ñ};ß‘ €ÝÀQ?¦øX•%M›65¢!d“±ƒ‘Rƒ"½æÓO;z‡#„þ´¶edÈàH ç%ƒÇ>¥L)a¬ïš!O5r8Yqg¯¼"šÍHäÑG[øÊiçþÓÂ;º©bŽ’1u8_¾|w«0©¬k9S\­]»Öõp8#<@©‹{<Æ6MÄ 'ˆR*[-¨Ë36lØ :t09B±mÙ²eæ¦-W‚zÄÇ$@$@AF¶³:Ù…asH€H€HÀBßÿ½*THJëìèСCÍb«ÿýïòÃ?È¡C‡¤qãÆžU“ +š×jêÔ©fÑd#ÜÕa@€ à¦aÖ¬"¸™‰p Žp³Ö.ñí·"—.‰<õT`[]Z55ù¨¸)°-gm$@$3vš ÷Ô‘êlüøñ&UZä£9æU|èý|cäs;D×®Žj΄Jhv’$ÑŽÚï©èCÉ•žŽ ü6¸!Ú·w<[ùoΜ¢÷÷éä¬<ë‰Îž=ë¦yWÁÑóš­`tÍÓ2õ±RDø#8R±’ÌŸ??âX¼È•+—Û{¾ OXŠ€¸‘\}×>R $lÿ®kråÓš¬ÓŸ¿5S ÿ!  "‡#MWkD´ Ôž–H€H€H  @Pô´.Ç„CoçÎeݺu‡ç÷ß_y俜¡ã±Ù< @€ `±íµk×t9ÅFFËêþ#ÁQwpàf¦flUaómÁþ éÔ=öî+8Ü“gà¿$@$F%&L¢E‹ÊU˜¶WåHvÍ% Òxãþ;~‡"s \vׯ_o;ÃT©î\+§ÛQ‘"w¶…Û+¤JÅø×€« jáõo‡iEãÊ’ÇG%äï¿ÿ¾ n1Ÿ«€¨Ù»“$Nœx¸¾†a×íȇ¨j2ƒ–}Õu{N•©AMék,Ðo’p²qFêÔ©¥D‰η|c‘GNøqŽÁ±ÿþfàtnç3 38!mlJx¡2H€H€H€BšÜ,ª÷¹.ì’E‹IíÚµCº¿ì €wߺE£FÞ q Ä’€~ÕS§DêÖ½SAºtwRÐÜÙܯœiVœNj-¦`¦í¯¿Do¾‹lÞìp—€»ƒH€ìJ`É’%òÚk¯™,0pÏM¢Ö?³fÍ2.G!á‘#G9vì˜T­ZU¾úê+I‹\’6/¾°yâØ|h×uM³qIÒlíцjÝÕ¼CôºG-ŽgΈø“Þ-j-ÜBž —¢[·nõTÕãg=Y @UùóçWë;‘%K–´I“&]¬ûÝþ¤ëÕ«w§P ¯ ¦é¯ L¦ÈŠ\˜ì†àèž{î‘lÙ²Eé1Dm°"†M ƒH€H€‚R„îÕ%‡L§ìWŠí#  ÀÀªRü¦8p ÅFAÊZH€HÀ¶V¬Xaæ7í’ÂĶ Ã´áûö9:^0Ú<ÁçÅE&N´¦ Šº}8„Yzß=à.JÖ´šµ’ €g;wî”fÍšiÍ fqKúôéf­[·–ŸþY…•›¥mÛ¶rîÜ9iÚ´©,^¼8$ÄFžiØc+´çjxl„¯qiñèÑ¢iÚE¯uÌu}ø¡H¦L"?.¢fXntjpÂØŸqó¦èßcùûï‡ãó´ûì3½™õ”ôíÛ7Nuñ`  {8¥Ö3[·n•êÕ«3•¦½/eжéÔv9zaÍ¿N£iM˜ .ˆ´icÍyX+ XM@3Iýúõ÷ÖçÍ›'y=ØÂÁ¨aüøñrþüyùüóÏ5­¤æ•´Q¨W‰<ù¤È–-6jt MíÕË!vÕ5Éq ¸vè òý÷¢×8úª4]ü$²i“¨0íNY½ý.Õª‰¦ÛQ­Z¼ÄR}ûÞ-ªbв’8{vñâÅaª†l¤‚¢œÛô5>‘Êés9ç¶ÈÏ eΜ9òfó~J÷V­Z%û÷ï7¹#oܸ¥\=Œh)ÊnI?ý$2e >\¢voÏž=fÀ,UªTÔÜB$@$@6#°^§t8²Ù…csI€H€HÀOk×®•nݺI¡B…dÚ´i¼¹ì'?' P#€tjšM€éÔBíÂQÔäBÑeáY³Fm”Þ—6©Tlv¯9jG´iÔàp¤Yo$@$`;×5?ÖÓO?-¿ÿþ»Lš4I*W®mô~~´ûƒuçìÙ"p¦<8X[è_»þüÓá²÷ì³"‰ûw¬§Òï¼ãàóúë"H:¥^.#_>‘¯¿Aj5¤uÚðÖ[Îwñûœ& SgT,·XnÝêñÛžÍÆá?~YÕ‘é¡q¾ˆ2O>ùäŽîÝ»{-¾téR™1c†lذA<‰êÔ©#O<ñ„×ã¹#ô8?à}D Þ±Kœ>ïKç ÑÆx8öi&wHUs#DÇ÷Ýyk½oÓæ¬¶g>ÅF w ,?s„àg:zôèýÐë ¢£úúöD4g¿qûöínÇÿ5š2ÑîB6¤Xc„ $:åÇ(üú«ãω‚£ðú›`oI€H T ìÚµËtG¡z…Ù/  p'€Õ¦5’?õ‡îÔ©S™F5Üÿ Ø øn(báIŽ9È„â•@ž<ŽÓ8¯§õûdH “%‹Èo¿ù}h¬„»D¬ÑH€H@ ÍY5ŒÇÏ?ÿì3“#FÈäÉ“ÕѦž¼ûî»>ÌçÌ f$W7HGK7n„>AÔÉÉ{Ë1^Ìëpîñ^*v{¬À-ê»6i»6y: þ-*­Å‹EÆŽQO2DTká©4·‘@üHâét*:Bf¿ì Ì«â#ä·*­Ï¹%J´íÖ­[?écó¡C‡4ëž|æéøè¶•TyâëêùõàƒFWŒûB”GžÜÐ]Ž4­Ÿ(P D{Ïn‘ „8!ílÌ¢1H€H€H€BŽ@çÎå'ÍÞ«W/csrd‡H€H€ü&°gÏùã?¤K—.~ËH ®p¡‚A߯7•ô®n”â†,ƒH€B¾>|ؤÞnÓ¦lÚ´I’$ñx{>ÊôîÝ[Š+&3gν?±Ïn/àÄãì.îã¯I}ú©CH„>5þ?{goÕÔ†ñ§yNÒ„&•B¤Ei"„B‰"”Y!³(C2+Tæ±!E”!dHˆPIŸ4hÔ¬|ï³wçÞ3Þ{æ{ö9Ïûû{Î^{­µ×úï:ëìµÞõ¼§FîY‹Ào?ütPä|‘Î,Z<ó ð×_n¨1®U3"_†Ÿ}©df¥?ð0u*pÉ%n»L«ÈB¥eµ¦¨ ø¶`Áû/¾LÌ,v«W¯Ú·o*Uª iÓ¦hÓ¦I}6ˆ½"•ÈüòÞ}÷ðÝ¡ÃÑàé3|Ï”*" "‹¨p¤pj¹xçÕg\ 0dÈŒ=Çs î¸ãŽ\è²ú(" "…S‹’²$D€áTÌßÍm›8çùŽZÅö>e¬QÅ¢F WÝ"c©†‰€ˆ@’0ì6Õp»˜—åÁ >G2úÏ Aƒ"^aÓ¦MèÕ«—…Ÿ*—_~Ù"ÆTŠ˜× ' mÖ"ám[à»ï`›v€‘#fÍܨ8u뇹7T?2—0_¬fQÐÑ®«¢Ä²¥J¹ã'Ÿ¨aâS!Ö§ÛN—2˜XFH–"I¨Zxâ Ø¿#˜Ú²Û¶"iˆ.*A t8 Êó!=5ù’‰€ŽÂÅàüÓ¾ñW¬XáÈÑûòê]D@D@¼J`¥ÍðýmÁšåpäÕ;¨v‹€ˆ€ˆ@d£FÂ-·ÜâLO˜0A›f"£ÒÈ9 §FÕn•‰@*|ó й3@•ƒ+¯ ¼BqÀÈdg#¶¶gOw‘´lÙÀ¶ëHD@²Co_xá…Žþ“O>‰]wÝãÇÇm·Ýfj>§Zh±†a»Lg$*ç3¤޼n“';väOtÞaH5*>À0 ½{ÜKÓª0ÁŠ‚ó„;»aе«ël4fŒ¶Ínƒ©M…ËŸÆ6þïÀí·õët@Ê£_2È$öT&é!°v­_3\H5ªÑšsk†LD@D@Ñ:9ÑÉuöl˜“`·T*Ìو׵[*#™ÀÎ=7¶–ØÏ@›3ˆ­Œr‹€× ÈáÈëwÐCígLLZAG-ˆS&" " 'À](49yüFªù" " "àG`úôé6aÙÓ™,~÷Ýw-ŒIu¿³ú(" "ëfÍš…uëÖᨣŽÊuê lßÔ® xÙá(…xTµˆ€d1&§óÖ[oáœsÎ ˆìrä‘GšãK_ 16 Ï=÷\@[׬YcJ:}§e†a+NÙ:Eœ~ý¸æšð)_hÝ::' ð5DNå5ßx8ûl˜Bqä|‘ÎÿgÀîC`êgüóO`šïhñbà‹/€­[})zÜ PXHµbõêÕ«_ºt馆£A±bÅ~·?,Z´È|a?me"=ŸÃc4Ž4äƒû¦cÜ#àS8RHµÜ»÷걈€ˆ@v˜mÛ"O>ùdT0mõ©S§š¬zýìì¨z%" "7†S£}ôÑqס‚"P‹.øŠdœƒÿøcà°Ã€:u"åJoº Á=pÜqé½®®&" EAà“õ0`êÖ­k¡Ã,vXÝsÏ=˜4iˆ.]º ZµjN*éþñÇxúé§akóA¥¼{˜ÌGg:úXäZ¦”·|9ð @Û¶€E³KšmÜè†hÛ¶ÍUmjÓà«Q#÷S¦¸ïá’ÖU$H È/Ïm¡MœÕß{ï½'7nÜx½I¼-2G£IözÈξf1¨çÛ¹ öš`»÷-Š¡L¢#À/xZ$…#û÷†òtg•‰€ˆ€ˆ€Ç Pᨬ=ùdÓáÇo‰š/" " qX`±K޳2†Êá.Um”‰¥ Š€ˆ@V ÃQåÊ•q衇fu?Õ¹Ì&ðùçÀi§￟žv2¢<›.¸Ø)öpa:1ŒMÀªU§t " YG`»ÉÐQÕhÆ  J[•*UðÐC9áÖè˜D7nœ…ïzÙÙäÒ»wo'M Lœì² ðæ›éáŽ(|A¥!–)]:\ŽøÒèètÓM°H®#“ RY¸u˜ 2pê©Àc¹×“Øe||UÊ»Ì0ÐÌéãBK¹Ï^Ïä™óQ;:õ”SNÙ~á…šGýE(W®\~}0| GÁGÿ˜KêÂ… MšÎ´éd" " "èpÔ¤I“¬¾Í‚Û¡.ˆ€ˆ€ˆ@¡>úè#0L'ˆéXÄ—ïóäÉ“±zõj¼þúë8üðà ­KD@D@rç7¿°•-*؆ÝÜ g †¯¡™ÀFZŒ¡Ý¸ÐúÄîâë‰'º¡s¨ø@»óN`Ñ"àþûªUÝ4ýl%0lØ0Ìœ9ÓQ/jß¾}Änž~úéxþùçWÇŽü5mñtÔ¨QËäú Ž7;v ifø µd*+ù.Æðjæá¼þüøôSà“OÜ—MØЭ,,ž¯„ÞE 7<ý˜³‘ýìÃUÑvÝ&ßJû{ì`Μ9øï¿ÿмyóÀ:Ø´i“óÛè4n)”‰€ˆ€ˆ€d<+Vؤ`7¬]»6l[þ›²öÇK=,%Š€ˆ€~ø!¶Y|£´¥]ÿŠ˜@ƒ@±bés8²ŸIxã à³Ï€áÃÝÏTŸhÕ 8÷\À"¡Y3à²ËŠŒ./" )&ðÃ?`ðàÁŽ"îwÜQèÕFŽéü~èC™³7í˳zõê…–óJ†4cwŽ9&9-æú2×™¿ù&9õ%Z ׺9ýï[X¿øþ{Wõ/ѺU^¼F /¤š9hN—ÇÓ)”ð þª”‰@Î; Äª >Ø·tG5“ÃQˆ€ˆ€x”îì°íûG{ f‹€x™ÀÖ­^n½Ú.ECàÆotœž|òISøÅqþßÿþ‡e&Ó»råJ¬[·½zõ*šÆéª" " ž Àpj´£>ÚíU#½I€Óè åbÓ­|y`÷Ýa"fIøD¸gŽÖ­×^sêY@ G¢€ybFÂ_ cW" L€¢ ŒÄ9anV)S¦L¡­­[·.†êäëk±'O¤D\–˜á0Õ&`Рäuˆ®àŽ/ÁµšÏ7Ž=¦|&}ÇT5¢ 2Û)\#çpda¡ÒþØä—öºÉ”Œ:Y¼Éj¶KƒNI=íõj0¨Ûn» œ“‰@¬äp+1åÈd?Ñ»Öln»‰€ˆ@ ´m u tðÊ+®Ôt/¯K‰€' |cÛ#éhÔ¡Cœg»d˜,'~÷°íŠ5jÔÀn»í†ò\¹“‰€ˆ€ˆ@¦M›†:uê8¡µ ȦS"?(šñÇWðj©©fgí÷У‡6&\+öÞxüq˜·NNHŠHŽ”ÒD@²‰À˜1c,¼Ö§¸ôÒKѲe˨»vùå—ƒ!¼GŒu/düòK`ùr˜Jpr[Ë@9ýå¾ük¾òJ`êTàë¯ýSõYD ]JòB 6ìho;£êæ]ús0ê²xñâÍy)Àßöù;{½Ô¨Q£«Š/~Ÿ}6NÀ’0iÒ$ôëׇ2ˆšŽv·mœÌ•‰€ˆ€ˆ€× Ì›7Ïé‚޼~'Õ~H.ÆuÿΞ¤j×öÜÓ}ñç/ÃиÿÁ»k@IDATûë÷ß]EPú-2.ý€î9ß_nœ7qYT® ×ÐÁÈßX7¥ª?úÈ•t¦ßãõ×gåŸKŸE@ü \qÅöÿ°zè!ÿd}¨ pî?þ_H”¨ *£ÄHÀ§lÔ¸qÁépDç$F‹Ýe—‚óúŸ?8î8˜º#Õº€—_Î?kÑã°1¶.î, SM¢ >ëðYD&" ÙN€Ê¸×]wÍ÷ÔÆ!Cbê.ŸE»téS/dæXAK¶ÃQ‹n½Tü£¢Íðc S'àÞ{Ý4ýH/ÇáȾК]ö»U«Vu3épg£€, .| gÏž—Ïš5«¾ï„¥ù>ê]¢"`êY˜;w®³›4ªÊ$" " N€ Gæ”­­~ŸÔ<H7Ê:xÕR¥`**î"w ÛŽ®JÏé§§ùâ ^ŽG^䆂ŒG4>cPý4£sR×®î&ˆV­\åTÿr¥K»Fd7z´B¤ù³ÑgÜ&pÕUWaõêÕxê©§P‰qµd¦ÚS 8ž$Ó¨pD3¡â<‡£š5Y³€Š v„uKꯈ@*øŽlïk¾YŒÉÇÍÙh}~JøOSò'9…g£ÔPŒ/MïÓîÝóÏQbóæÍhî%òO铈€ˆ€x’Ƕzõê¡lÙ²žl¿-"? œ|²+ûÌHÔ ƒà{çä>à ì»oà+¸%×^ œ>°ÞžÔè¬ɪWwC-0?U¹é¤ôè£Íйóþ‘Š(]rŽÀÆq­ý'©Zµ*n¿ýöœë¿:," "<ï™ % :qk½,ã Ð ‡a¾¼8ýóÏC–ùTR#ÁnÔÈ=ÃýáÑ8Q]õÌ3:4ñ¹å²ËBk¦š$èx$p ¼û÷²9lvÅI'”UX¨z·x±«¤KÇ–.u‚¨¶m{r“jÍL>…uRáÈßl*^&"P„|[\ƒŽÜm…4¬}ûöW©RkÖ¬qr.Z´È¤ÿw8»ú )ªÓ9F€’«Œ/}öÙG §F“ÃQŽýƒPwE@D K ðwЛ¡ëØ‘Ñje" "O€ó w–ˆ•+ç†d‹¶†O¸ñFÀ6ÛaРï°mÛœh‹*Ÿd=aÆYÃßñÈ#ØÎKÛz)8 LŸ>Íl¬cHÉ2ž€/HƒÏ)'ã¼³[¶¿ý8·©íþ G‘òø§3ôÙÛoçÞÙÈ—WÎF>z`“-|R-·¢IëŒàn¯,2.ûS@‚k»#î¼3úÎM™ü÷p ї‰6g… ®ã-Žd" ™CÀñ-´uý›´~ýzó?ŒÎv§ÖÿNÛb¿zÿþûoß¡ÞE ÀòåîGJÛù›Žüi賈€ˆ€× ,¶mTîÛgŸ_n¯wK툑ÀªU®“2Ává˜c–ØNh›ñ‘‰€`É’%>|8ößôïß_DD@D@D nßÿ=þúë/…S‹›`ú RáˆÆpÄ÷Ýç~öÂ_¶›JDT8*Ìbq8zé%àž{\ÅÕÇ+¬fð:t¨…®üÅQÌ­S§Ž/9+ÞŸ}Öu6ªU øàØ|wôÝzë-7´Y¢›î"]‘ŽPt~ñÅH9”."nŽÃ‘]´˜ß…·®X±â¿ã?î±Çç¹³_&Áòá 6mÏÐᨂ¹¤6òÚ–’ÀnèHD@D@ §FÛ—q‘d" 9Ià×_ÝÉz†1{õÕœD N‹@Ƹúê«Ý¨ÚÔŒ"8 Lœ8Ñ)yLªVÕâl—ŠE&àS8úè#×é(rÎÌ:Ãpg´ÆÝ÷‚þZÄXìº+l!¼ \ÀìÙ@ß¾Àž{ºÏ.R0*˜—Ί€ˆ€À?üàlb9ÈâV^~ùå¾ä"ÿÇV÷©tMe¢DìñÇaJÀÀܹ‹Ê–®¶­[iCéðÃÝq(ºR±åjÙÒUP;6¶rÊ-":¾jþW°¯ƒè­L™2ÑgVΜ%@¿´Q£B»O‡#JOv ÏÐK)ED@D@RNà§Ÿ~r®!…£”£ÖD c Œ üü3LN`¼z™ˆ@f˜1c&L˜€“O>:uʬƩ5" " ž#ðüóσ:tè๶çjƒé„S¥ ж-ðÎ;UI½°ÄÁg Z4GÌG•£E‹ø)¼-[û=ä.Ú¾þ:@ ™ˆ€ˆ@áþ³xa]t¶oßn랣2j‹ý,qŸ­XŒ]x_Âå ¢÷ÔÚ>Çé(\žHitæ¥ÓÓñÇGÊ‘xúÀîøU½zâu©äð)%§6Õ"1øßÿþ‡•+W¢yóæ1”RVÈ\>…#9eî=RËD ™V¯¸{Ëßî¾øðCà’KüSõYD pB˜»O¹qêÞ{ïÍ„&© " " &0sæL é±gŸ}vF-6ziZšN…#Ší_pðÐC°ã´\6á‹Ä¢pÄ‹Mšän„wa>Ãtïüþ;0f @µ™ˆ€ˆ@tF›'ϧŸ~ŠK/½Ô¾?3ë ´_? sg÷»}ܸèúœ‹á5‹Y\$ó© k<¿n]ØS˜<ÙMO¥Ã¯Ð P©Rø6(UD ýäp”~æºâNT7¢Éáh'½‰€ˆ€xžŽªU«æ¼<ßu@²”À9縻wfàÉ'C;ùÜsÀÛoK–¸çlãš9ɦ–÷ßwÃ.0\ws0wû[IÓåni™ˆ@æ4hæÌ™ƒ¶%²g(e" " "gŸ}Ö)}`Ê1ÜÚk¯]º$R‹ÊŠ€ˆ@î`(µu&ï3vìXSØÉ‰nœ›;×Uï«QÃKŽ9àxbbL(U*º{ÅyÛ¶¹scáJ°NŽU·ß|ü1pÙe¹=hÕ*0MG" ÙO@GÙ3¢‡·Ü|÷0q¢+ÅÇFÑᨄ­Ôè¡<#n‘!" " Æï^ºt)äH› H¸çžÈàâwkQ͈/†-(W¨Y3ôE§%NâÈD@2ŸÀ'Ÿ|‚~¦-O§à×lu­t¤íþ™ßµPD@D C¼ùæ›X³f ¤n”!7$Êfüò‹›‘7™fT7zâ `¿ýØÎ;î€)4ºÊL±¶ûŸ€wßN9%°ä 'ëHD@D `/¾ø¢… ›Œ^½zá¸ãŽ+8sšÏ>þ¸«.tþùî…©PtÝuÀw×_^=/¸‰;v-{î P0’Ýt“[w¸óä=™ˆ@nÃQnÝï"ë-=]épTÌäü|F‡£&MšØ"Ž­âÈD@D@DÀã–-[f;@¶Ù.D¿mˆ/Ù@€B&}ûÂä® ïMñâ0õ÷Uxnå(J;l6ôšk®1)÷Ö8õÔS#6eñâŶÀvŠãdÄÅáê’%‹ÈJ'D@D@¢'ðœÅá-i±tÏ:ë¬è )g‘X¸Ðm‚¿ÂÑ–-îâ(C#¥1ÌÃÐpa8ØJ¯XŒ Ç «ÃúlºÂ6ÿK Ê+" ÙOà_“´æ¦”Ì ³|16—/_Ž+®¸Â6¤Õă>˜Q`¨ÒýÞ{À‘GŽT!úè#àþû]…îÂTíÌ— &ÞÁƒa¿q îb¤ór6*˜›ÎŠ@¶°)u™¤ž€ÅÎÎpß•¶Ø“Ü/¶¥äÀô%é]D@D@üøc¨Q¼-ãÆ_‹øƒíÛÇš6·&•ì%0ÄâƒõèÑà ½ý;=?#Øe;ŒÏ•#GŽ4Ð=@#Ô™¬ä­[k¯,Ú[€Ñùçå—]wÎ=øóÏ€Ó!-Tä¦=™ˆ€ÄB@G±ÐRÞ¸ p…È N3ôLÃLÔ¯»—*(" "Ëþøã§ûR8Êåê{¢~ý¸ürWˆïÁ6t(l"ÈݵŰÙªUÀÕW»Nït:’‰€dÊÙÓ¨^ôöÛoÛ"ZS 6 Ü¡J£RÏž=1wî\Ü}÷ÝŽã‘sBD@D@D Atbåxs.Wïdž"°Ç@«VÀî»»ÍÞk/˜R1ðå—™Ñ : ùGH¤U¬Ç~"{£.¼ š«LD@D ŸÀO?ýä<+RµˆY9äÌœ93?ÃÎO¯¿þºm~îÝ»;¯ EœP¥Š«Jtúé¡ ¡Ú÷SO+WºóiÜàÉl/¨¨½´‘)]D ’Á'Ì ¤TãÆ£zZzì±Çø×|õ¼óÎ;¨\¹²ï0ê÷“O>9ê¼Êè-œïå‚Ùyö+W“ÌöâSLD@D@²€€޲à&ª )%0oÀXòQ×y5nì¾Óÿœòþ÷Þ LœèîÀmÑ8óÌÐæ<òÀŸ‘¶©Ì™4Í‘Ÿb‘–œ ['_d" ÙC`Ó¦MŽì}+[1|õÕWñÁ ÿþ¸îºë@G¤Çœž4i’³ÌÐk2HgMFsW“ `ø™·ÜpÀ—ÏøÜAˆY³|)Ù÷)ìMöõT=è Pá"“¢1Cos^·W¯^èØ±£ó<Ù»wo§²5kÖàâ‹/vT¨näEëÖÍÝÇy7Ž{ ³Æž2H‡£bÅŠ•±ÊŸ‰æáâTÞyçÑ É#‡£$Y“°bLÍHGYsCÕ°|NØR8 ‹G‰"€¿þ~þ¶[,wÚš‰³“×¢R`à@7¶|`.÷È6›Ù޳pgÓ>þxúi sçðŽK¹u$"à5t&úçŸ#¶½C‡˜3g޳;õ®»îräð9|ÄG`ôèÑ^ëžÚ+" "Á¾ûî;gÌ¡£k™2œF—y™@ùòÀþû­ÂÑüù@ƒ@©R^&©¶‹€ˆ€·<ñÄøØ&*íÐCuOu£®]»¢OŸ>ŽRî=÷܃`éÒ¥ ³1•¼jÇûìãnô£ê‘LD@’I@BšÉ¤©ºÂ`85šH5ŸÂQýúõsú#" " ^' …#¯ßAµ?ÕÚ·–/w•/?ÿ6Yãî.¶hH¦Lüð0yrdg£‚Ú·e LåÄÍÁýúÁ€€G-¨”Ή€x•UŒJÚvýŒ±¸Ó¸è{ë­·‚ ÁÜ•jÊÍŽ RéÒ¥}Yô." "  à‚#íœsÎI¸.U¸¡Ò¹A"ÝÆÈÜtqØaé¾²®'" ¹K`™-Z^{íµà¦Ñ;î¸#D³fÍLñn–³å¾û­l3ÛÓ8öØc3vÜçøEÁ‡hŒªão½bÓ'MÊ#" áÈá(¥%•–hþοt8*azµuäJëÂÑ_Ï ÂQ‹ÛT¡BÏ÷ED L u`QBÌ¢O8ê\£á¼Î„ ®cоû†d:aN=¸þzÀ6 áÇo®M&"]V®\‰©ö%ÓÙ$̪W¯Ò9:M›6 óM. †ÿ®—œJØlß¾/Y¼^Ž5\„”eÂøòËØúÃEÞþgyM07æúaìX7dt÷î…fU$¸âŠ+ÀPi#FŒ@¥J•jå3æôéÓq¾yçÐùˆçG'“Z·¸Á/^Û°Á¿3_+ØÏ™ˆ€ÄE@GqaS¡XøŽ‚ŽèlÄ]©2ÈT8ÚsÏ=³¡+êƒ$DছÜ]º³g»Ž? Uea:q’åî»^ŸÎK¶YM&"…ƇMàì³ÏÎÂÞ©K" " ™L€¯™ ŽÔ2ù.EnÛ¤I®ê’%y|!›m]9j[·8þxXØàûïÝb¬ÿ‚ Üg!‹üZ¨Q‘‚Ï/\ë¾ä’B³+ƒˆ€ˆ@L™2|¦<ùä“Ñ­[·°5R%—!מþyLœ8uëÖ ›¯¨¿úÊUèKD%oà@˜J0ТL$¢¨{¤ë‹€x•€ãí±qãÆƒË–-óWɇ~8²\¹r§yµójwzøŽü7—RáèÀLOtH:qÄi¸’.!™M`óf eK`üx ]ÑswÛ ¶ æ€|ó ðøã€¢(eö¿µNâ%ð / bÅŠ'‡ã­WåD@D@D 0Ï=÷Š+†^½z–Uç3À‡ÂT*€Aƒ·ÿþ@¹r0%‹ÀôHG ƒFuU.Ðp€›óÄ«®x0=:R n:”Vš%L,Y&" "bLÎçâ‹/FåÊ•ñÈ#zµ¢Üä²u+pÊ)ÀßÃ|aŠú¡Í}ýu7í¤“BÏE›rõÕ®³¯%x 8GdU<Ø.þ-ñ”S™Ü"RmmYµjöÚk¯Ü¡ÞŠ€ˆ€d-µk×âÛÂ(…£¬½ÅêX îºËŸn‡.¼új UVÏøå—_ðùçŸ; ½åË—÷\ûÕ`ïà3ßo¼aaKÚg¬Òw馧å ¥JÁî_àõ(ÀOe‡hŽ.ºxï=€ïÁªª÷ßïnºèÙ3ðáŽøÜT¶¬ë¤î¼ÒD@D@’KàÖ[oÅo¿ýæ„RËô9\‹ö†É“ë¯ïlD2&¾F–I$Êk£F_2H„€ãp”H*+…V8¢ºMG…‘Óy¯0çm§©µk×öJ“ÕNH[{Á.»äWÇI|™ˆ€¤‚À‹/¾èT[”;MSÑ/Õ)" "ùÆ›|çf“ò<÷Üs3¿±jaXgzhø1 «6s&`¾ÍhØ0lq'qèPà©§€.]€‘#Ãç»üòÐtªPpCý¥©RAç'ó¡F¿~@­Z¡ù•"" "\ߘöƒ>hÎ9­Ð¿ÿäV¦¶9s€Ö­ÃœŒ"ÉçHd>RaíçŸ.¼(^‰€ˆ€d)eÇ}Ìæ^p÷,'*;Ì•[æ®Ú—^Š¿ÇÜIEÉfÖÁ(¹Û¶Å_—JŠ€ˆ@4fYœ“ àÌ3ÏD ®ÐÉD@D@D MÞÿ}|ñÅNHÏŠ+¦éªºL: Páˆ)¬Ú§ŸçŸï†ccˆ›XÿÐYéé§]U¤{î¨X1uªû,å^YE@D@RE€!Q?³rY,Ì8 U—Á«¯ß}çVÊ)Àé§“&Ï?ŸœK®Z´kç:Ç2œZ¥J°Í8É©[µˆ€ˆ@"¤p”=•‹€Žâ¦B" " L@ G|sr¼iëÖ¹;ªøï?`÷ݽ÷Ž>¨_?μy®3Ò®»¦}ò p À?ÿÆiWn0‹€¤†À \©3ëYÐ6ÏÔ\ZµŠ€ˆ€ä8¡G«dÉ’4hPŽ“ÈÞîS¡ìØð¡o–,¸pÌho½å>SÅJâ´Ób-¡ü" " É °cÇÜpà æ(ZÑTêL!EÆxŒºJÖ>7¨†ÇŸܨ— ûé'`ölਣÜ99:4ql’‰€ˆ@Q(CŠ7hР©IÎR¬X±–VnÏN8á0JÐÑvÙeT®\U«V5i¸ýqàÚbÆÞÚyèÐÑt8*S¦ŒÅ§V€j.ú," "à]R8òî½Ëæ–s·Ó¥—þéî€5 hÒ$|qå›5Þ{/ò„Å;ïÀÂHÀ\ܹÚIž§RE@’K`ûöí6Y;ξÚ eKNGÈD@D@D =fΜi ‡ OŸ>æ°_?=ÕUÒN X1 \È5†‘f8œ+>_¥P#í}ÖE@D <ûì³øñÇqË-· F)ë2•Å9fÏ“tPô—ä?:¹š¨/8.ÛG¸sq]º¸› O:)8‡ŽE@D hêpdNF{ÛŽó¬yæ› Ûo?3–B?~¼“ʸÖ]웯‡ýZO¥L]˜&()ƒ Ðáh/sé5ǵ n¥š&" " Ñ ÂQÙ²e±Ûn»E_H9E EþøÃu42ÅhP­è‰'€óì×|A?½öܶˆ<ðз/ðÜs¡{å7,%›éx¤5ÿPFJH ÷ÌrÙ²e¸ä’KRsÕ*" "  2ÄÙP{ýõ×GÈ¡d/<ØU0š>ÝvQÛ³O´Æ0jsæwÜtëm)åH%M›6ažÉt·hÑ¢ÀËlÙ²ƒm¨V­6ï¿ÿºóe }FU¢ýö ›­ÐDŽ/4ªdk׺ùn»  ‘ÏLˆ —]ëpä‘@íÚ¾3ï,CǤիÃ<§#(*Å#]¸víÚU7n<¦D‰ó-Ïuö p6ŠTÎ?}ƒ¹sN˜0§žzªóúμÒ?“>g5ßw­¦MËïæâÅ‹‡£ü}o ÂÑž±ÌZz»»j}xì1wr„ÎFÜʼn N’äläëν÷ºE lO=œql’˜1CÎFÁ|t,"Z/¾ø¢s…SK-gÕ." "H૯¾2GûwœÍ´Tò—y—€‰[€{§«W­ôu¦j¬E㑉€ˆ€dk®¹™tИ1c lÑÈ‘#M1h n¼ñF'BOpæÿþöØhÓ8ùd`ذàÑs Ô‚9!Õ *µp!ðå—À±ÇºŽC¾¼&Ä„o¿®¼2²³‘//Õöè”Dõq™ˆ€d°G 6<¶|ùòt4êk*4I‘¡ùþûïqº”ä®:"ÉrƒÀ¢EÀ“Oóù¯ÉlùòåÎý§Â‘LD@D@²…Žäp”-wÓ»ýàOìûï‡)mo¿ ¼ôL.:úþ0Rò /Á’Ì>è:׫çN†Ä»Û+ú–(§ˆ€äàüÁD‹ar¸mß4æüú$" " )&0tèPG¡ýy›¤˜tê«ço:‘CGûZ°j,ôŽïhÛxä‘üc}(Z«MÚç™gžqÑ¿¼þúëa´nÝ:Üyç¨[·.˜/œqÝ’!3©D‹âí‡Ë[PÚ?ÿ¸NDíÛÃT Ê |°«Ε÷ãŽsçÙ8Ÿg>QΞ æ§³" ™I ÄáÈœN2U#Û Û¿\°•)SfkÓ¦MѼysÛPøö€ÿÌ]ô[Å8çœs°–ºq²¬'`ª÷ŽÕ¬é¾3œMG.ýð>Êó®\¹Ò¤nk{¿3ê§ X4cLž PT”;¥’aƒW]åª&Q²Y>ãÉ ª:D@b!ð†I¶ÑéHêF±PS^D póì›o¾iŠ'ƒóß2oøå aÃÂûpà®êká9•CD@D (PՈχ·ß~»³.}¦É{Ï w >ÿý·“ÏÖ²ƒÎº‡Ÿî¾·jå* qÞÆa³˜øÑGÀ¶m…‡SóUÂPhS§ºjät:êÝXºÖVW%É—Oï" "à‚k& ÛÝÆZãÒý:3Áœ†ÞÞ¾}ûÏöþóüùó-ðÎöç‚wø3¬È nwî\ôêÕËñB­Zµª/YïYH`ÿýS7´s·sr8Ê›¬.‰€ˆ@ŽàošŽrüBtŸÒÏ4=RÆ›O–1ŽýÌ™®4“¨œ$txÉäÚJšV<“e" " ".T7âæÙ›nº)]—ÔuRD€ê&tF ¿À!‡“&›6åÊž_9D@D@ÒGà_›¨1b„…AÛ×]wN<ñD´k×]»vuœŽš5kæ4f™)!<ðÀŽÃ0×¢#™¿Ã÷‘2¬Z<Æpj´NÜ÷hþ¶ní:qÃà+¯¸k¨}ûFSRyD@D óä9Õ¯_¿–5ï){å¥ù5÷S{ÀøóÏ?á—ò‘^¢”8çëHÓŸ»è¢‹0eÊ<÷Üsøá‡ò›³úôéc_¤¯ T©Rçt=rãž{òû#‡£|ú$" "èhM“ÂQvÜÏtöâ·ß\ÉeóÓG¥J@ýúù/†Bów$ n'ÍM4Ô‘|N•Ü2cÁ[#ìØá¶/¸ :TàŽÔwß};wFµj…Š0§º9ª_D@D GpÞšsÖÇLŸì¾»«K>§# „sÏ-<[,u+¯ˆ€¤“@žsQéÒ¥éRÙÿâædd?­q•9½æŸíg«'™__~ù¥ãqêS`óæÍÃSO=å8&E[§òy›€ÏáÈܼݵ^D@D@vðý¶‘‘þIDC€ñ᯾˜5 ð…ž W®lY ^=‹qlëë Mï¿÷Ï?nÚ²ux'O¸òÉJc˜6™ˆ€.ön3mzÊäËD@D@D ]¸@¹Ã¼î¥n”.⩽ÎÂ…nýþÏT‘®xÊ)_2Ì#@Õ¢r&?G± Ÿµoß/¾ø¢£ˆ{Ì1Ç8£GÆá·ŒÊG‘Ì¢²Á¢§¢[·H9¢KçÜžõ±àÑåÎÅpn|ÉD@DÀË×ÎF™x‚uåþܺukûx‚¡zè¡Î΃>8àÔ£>ê„` HÔAÖ ÃQåÊ•¡PzY{‹Õ1È9R8ʹ[žP‡éÀcb¨S¸øb×™ˆÜU5n0lп?б£»³iÑ"`óæÐKšz´M¨?zN)" "-^~ùegB™›˜d" " "‹ì8Ãyv²¸(­´˜ä)¿F, G)oŒ. " "Ï-þÙ6yÆi»í¶[@Ý»wÇÈ‘#aëÙhÛ¶­³iåî»ïÈ|ðÕWÀöíá}(foBJQÙûïÃB°GUve¬$à(+V¬wPï¶Y,Ìcûí·_ƒÒ:¤“Éc=†N8Ë—/wêÚl+(t:âÎYvà  „G{íµWvuT½ÈiR8ÊéÛ_`ç?øÀ EÖ²e~6Ê4¯[X$â3ÿü¨ŒÎFß}UVeÏàøúñǃ“Ç+Vôl?Ôpoà¥Í‹ãæ›oöVÃÕÚˆ| GÑ„T‹X‰Nˆ€ˆ€)ªÙZ6®¸âаíèׯŸ)‰/ÃàÁƒ¨t<*ÈÌɱ`ßb[ÂDãÆnˆ³'ž(¨÷Ü´iî»ù)ËD@D g PáȾ£‹D`„íæ°½ÖÉ·]vÙʼn¯é_ót pÉ9Yv¸ï>€‘Ó~úÉí¥ˆ—Xl9e×}VoD@D × PáˆñÀwg°n™ÛP…OtUŠ EÎÙ(4—RD@D · Œ3Ù7>C*œZnÿ;PïE@D –.]ŠgŸ}mÚ´A»víÒyi]+…¨pT³&Ì9…QÕ" " )#ð»É ½öÚkèܹ3öÛo¿ˆ×¹õÖ[ñꫯâÉ'ŸŒ˜Çw‚Jã%M’#((­_‡S;V­òåŽüÎ9¾Ã¸ÁP&" ¹J ¸…Ska·}Òy¶ÕT‡†ä¥àÑG‰ äÕ¼fÍÌš5+ïX" "½t½à 5{6ÌÁ( å‚ì¶mÛäpùöꌈ€ä$/mánjÕª…%J„;­´$°b0y2l‘;>¨Ë"  Ñ;Ïm™z»N–ºté’©MT»D@D §äÂØ6cÆ lݺ]tQNÝÛlï,Ž5Êö^ª" ñÈ…ñ-^6™RnĈΚèUW]Uh“N9ås25/ÓBŒ G”/šñ²Ë€M›`ŽK¡ç‚S,€|jIÁçt," ¹B ¤©èÊý÷ß™ ÍêTà¤! Ÿ}`1'Z·ní;Ìøw>€Nœ81®v64ýÖK/½4ê²”‘æ™gœø£t6¢Q:°zõêÎŽ›ÓN; tPÔõ¥+ã×_{ïí†á5N&…#ƒþˆ€ˆ@ÆÐØß-¡Cmmmc‰^–”¢P'wEùìðà 4©íã¡w(JÛŠ’~ü×þÙ¤â¾úê+ôéÓÇBP†‰AÕ*)" YA ]ã›Wç$ã½Éß|óS4çYãíS®—[¿à†ãŽËuê¿xƒ€Æ7oܧt¶rÆ 3f öÝw_Gá(צP‚‰⤓Â×vê©ËéL4p LÙ>|>¥Š€ˆ€¸èpTˆOõ?NÕçC=4 j.ÖyÉ>ûì3L™2%®&·lÙ2*‡#Ê4³)dæ†åË—;2‚”ìØ±#î¹çTªT)(gÑòaŽáDzôÈ¿¾ŽòY蓈€d"m±ß†zù믿Lj×´ve9EÀ~Šá­·€áÃþ¬½÷ÞÀîkm ‰@QÐØVTä»îرc N-1Ž*-"½R=¾yyN2‘»þí·ß¢\¹rhÒ¤I"Õ¨llÊÝT,€¶[¤ã¯pûv`ð` yóøëPIôÐø–>Ö^¹C®^½wÝu—#ÄŒvû‰Zµ _[©R@¿~îø1iЭ[ø|Jp 7Ç•þ0láì7ÿãT}¦:¿­àVÙo¿¥yôîÝ;¬³Q8Lï¿ÿ>N5·ÛLáhÏçàBœüS9…»sJÌ! ±-ö{Ag#†9•ÂQìì¼ZÂ6VaÔ(XÌx kW€1ß9!.ÈLÛ2ó¾Ö*†S«Q£†³±¦°¼:/" ¹H •ã›×ç$ù÷@…£fÍš)\v",{óÍÀ‘Gº‹»½‹€x€Æ7¯Ý±Ô¶—Qf,Xà¬{R0YF=Œ3Î(¸¶ZhØ07´š-ÍbªÅòÿ(º`jp㮣lÁµé¬ˆ€d7†T«àßÅíÛ·ïð?NÕgªøÛºuëü3ú3½j)-ì³xÀqò'ú>~üxgõÕSÊÜhŸ~úiÇoÓ¦…,ësÏ=7Ï9‰±Õ'L˜€ÓO?ÝW¼HÞ¿þÚ½l‹ù—§ÃÍ*Tø'—ŸAŸD@D@ŠŒ€Æ¶øÐûœƒ¥p?/”š6 xøa`òdÀ"è¡iS˜Œ3Ыì7z 6Š@îÐØæÍ{ÏM54…SóæýS«E@RO •ã[6ÌIÆ{¨nDká?™oeYXÎ"Ú`äH˜"âã3– V uëк¸¨Ë×!@ƒ¡ç™b~ÉxôQà¹ç.)T¬p.šÊHï½ä¤¾F¥Š€do™p2« \{åúè%—\R$ »ê* jU o_ذ;7xè¡nSÞ}à‹NG2Èu © hd G¶‡ õ¶jÕª€‹Tá6qزeËÀ?>Ûk¯½|~ߺu+FPÏwÞâläËÀÎáÇûwNµñ!XvÝ5¿%t8J&«üšõID@D QÛâ#(…£ø¸ez©óÏ(ÊHye:x"À‰ñ¹sÝ8îr6Êô»¨ö‰ ±Í{ÿ ¸È0vìXÔ«WÏ!ìBz¯Kj±ˆ€$@ªÆ·l™“Œ¸ÏáˆÊò²P?ü˜È¿Ñ¡çbMyé%·‰"Y8g#û‰€NÜðÖ#F¸sÏ wm‘Φyó€¶mªÓÊD@¼G@ã›÷îY*[<þ|LŸ>§žzª9’î™ÊKX·é=à7Îvì¼óŽ›s„˜Æq’-° PÜŽ–ú÷Ó&øêú§ês°ÃQaaÆRÕŽxêõ—ud¨³Ý“Gã ¹(ßë³£Ž: ]»võ†}§òÑ¡>·ZËñý÷ß(0…-”ÂD¼|À;øàü‹ÐAëÏ?ÿ”ÃQ>}Œ" ±-¾Û!…£ø¸eJ)óóvˆ,zB€•/¼ý6P¦ pÍ5À/¿¯¿îNndÔˆ@FÐØ–Ñ·'lãfΜ‰%K–˜¼ý(ê0áa¨Dȩ߲aN2‘ÛÞ åÙ¬Y³DªÉÚ²ÜxAµ×DaÔ&N; hØ0úÚ¸¹µgOà“Oܰn|g8› /t•gêú©§`¿#€ã޶ֲ%pÁîgýÈlß2ûþ$Ú::6ÿÃX˜QÚã?îäìß¿”%¢ËÆqâï¿£ËëËÕ¥ ÌùÉu0ºõVÀöÉ`ð`à±ÇÜ4_>½‹€ˆ@® ÂQÀ‹)uNŒÙ³g\Æ«Gõmë{2'B?áÓ’Ÿuâ¶(ìêùùc›•Í™ã>Ô™TžñÇ"w«Já(‰>ˆ€ˆ@Fð¨×Øý­‘ÂQô¬2-'e‘éXtÀ®pûèm™‚[è §vÖYgŸÒ±ˆ€ˆÀN©ß²aN2‘$T8jܸ1Ê•+—H5YY–{cW®LŽÃѤIÀúõ@¬C=ýÀ¦N…m²¨4îpïÝ7Î]6ß1lÞì†Zãõd" ™O@ã[æß£DZH¥¢lÎ?zL¤ú6™wê³˳©yº¶¥t]톀êÕµkc«´U+àÓO]µ£bÅ\e#Ž;2€ G&ˆšoæÒ±Q£F•óSRóiÆŒï·ß~Ç™|À—>kNßÕw2Ž÷Y³få•¢#S»víòŽ úà¯pÄ|EépÄ'4‡#†S£ÉáÈÁ ?" "q4¶ÅwK¨pTÕ‚ykR:>~é*EÇ¡`Ûw_ओ€›nr%‘ƒÏWNù¯áà+êXD Ù4¶%›hjëÛnR&Lç¤.‘ZÖª]DÀÛR5¾eÜd¼wvݺu†kZ´hoY]ŽáÔhT8â´¸/œŒ›Ûß_„)I=zÄV®dIÀ F‚Ëuïžÿ|ÇÐjT¡hÔ¨à2:+"4¾eÆ}HE+Õ…k–‹/Æ“O>Yè%ÆÕ«W㢋.*4o¬>ÿæ`ì† µl“&@­Z±–R~È~Å,X0ÍœŒÖøºjN.eìóu¾ãT¼ÓùÄÛWûöí}3þÝßÓ:™4|°ýÛOË“¬Ñ*?Ñ3رóÆþ("“ÃQ×eE@D ÛâƒG…£¢Œ#_«s§•š¹Ûˆ»a}¿O|½§ôþ+¯C†:øRõ."M4¶yënN7zNDŸyæ™Þj¸Z+" i&Šñ-[æ$ã½sL®ÊìÍ›7·Š¬.çs8Ú7¬Ùé§ O«ÙÚ±ã¬DAÿš5c-{~ L€>Î=7ö²*!"~ßÒÏ<]W¤7˜X„ 6 Û¶m+ðÒ §VÞdÉÏ9çœóÅzrÀ/ªÉD@D@’GÀö€oØ+ï§·9]i²O˜3’íH¾Ýu×]Îà⫹ZµjØŸO,±à>ÿþû/"n¾mŸç˸¡bÅŠhbî®”â=ðÀ-&uÃB{÷ÝwßäaÙh­T©R¨[·®s}–á€ÍÝ9•‹`{>ãb[—YB_û¥pä#¡wÈLÛâ»/t8ŠV0¾+¨T¼¾ú ¶h ,\œpìwR¼5©œˆ€W hlóÖ{‰ñQÌäpä­û¦ÖŠ€¤Ÿ@*Æ·l™“Œ÷n|ûí·NQ)…'8w®›N…£ã>ùøøc€ŽC±˜ :ŽJ={ÆR*þ¼ ¡í¡=ÎñwT%E Kh|Ë’¦cÇŽE… 0pà@Ü~ûíN¸´¾}û†É pLþÜdˆÎ?ÿ|ì²Ë.aóÄ›hMÀÒ¥€El“‰€ˆ€$‘Ž`F/Ø›¿ÃƒUO©]»öá*dó$Ë8‰øÑGTwÊ)§° i™|à/íHE¢“O>Ùq2 nóÌ™3$öíŒ3ÎpÓJ•*gË;öW7bb•*UòÎEó!xðe}ñ8qWÓ¼yóò&zË”)ƒgžy&š&8yèì!L‡#z/שS'êz”QD@ÒAà÷ßǵ×^›w):‘n°­Áß©y²ôC¶m¼Ïì£ÿ"&c—.]:î;Jiß7Já(n‚©)HÉü{ïn¼Ñb~¸ì²Ô\KµŠ@¦à÷Ü;;c^¬ZµÊÙ¹ŸémNfû²}l[¶lV®\0¶=öØc1?G&“y¼uq<8q"9ä¨6ëÄ{•ð>†^|íµ×œŽ¬]»ëׯ÷~§bìA*Æ·L™“ä=å˜àÿÜvß}÷a=öˆ‘RlÙ}JüR8 Ï GIÜ #C‡#NS!"V£oq9[u°©t™ˆ€É“'ã…¸DücRÍýõ—ßÙÜù˜Íãïâ?þhêÛ_cîN/N  <8ëo0ï+×J9¶_sÍ59r$(JÑ»wo”d¼Ì £º­_¿~Ag ?ܲ3&x\qEäü‹d" ©%0cÆ pŽŠ¶É¼ü‚Ÿ7R{uÕžnη9êí½÷Þ¯šcŒE9γ&&Y÷Ž)ót·ð\¿ç¥&ðáé§ŸÆÝwßPCU{ZIE΀‹$ñ€ïüá3Œ…%y_~ùeL›6ÍñÞíØ±cØ"|¨ö·XŽ‚‹øŸ7žo5,öî»ïŽK.¹Äi…5:1äL" »‰¶AåE@D ŽC¾ï;ž¿Ðâ,ÑÑ2—,Æ6†(åËÿ^‡{¨å¾›S¶“Ý´c)¦¼) @%f EΚŒ|ø!°ï¾€m r©¥à’ªR¾×ÇVÌçT¼ž0e¦º×H)ÊÀç×+¯¼7ß|3(N2Žäü÷ðÁ£eË–1÷’ |¾M‡Ôƒxê)˜²RÌÕ¨€ˆ@ì³Ï>y¿éÿüóO<ôÐCI¨UUd*ÇáˆÛ±cÇÅ%J”howãñN;ÄÒæ˜ÓQs:oi¶g}:FŒáxð—¾ÂÜL9ÈxÅü½¬ýÛL#†@£ô.…øÃðûï¿wúlÅŠ¸üòËñÊ+¯€ÿÑ‚-øáÞ÷#38_¤ãàüñz ò~°®6mÚDºTÌét8jJÝ]™ˆ€dʹúßÑÉ2QG” ëb¡ÍÉ…± °Á÷ºP0…d`85' dé'À C‡ºNFsæÜÅD£h¦ù âÁÝݳnªþŠ@nhРø¢­Y³ÆyFɹ0¶•-[|ùÿŽñêý5j”3N÷LWŒ¯‚R»E@,Ln]çE\´ó©‹ç šTo™2'Ig#>§slÛf»~0šcŽ9&WþÅÔO[‚‰ûÚ¼nLÅB2Û^\[pÎ:+ä”D ç p^É7·Äù+Ÿ’_.Éöñ÷’knTìKç— ÿ†èpDçaß8{™yQ½ðŽ;îÀÙgŸíDFñµ“ÎFTùêß¿¿/)¦w9ç˜Ê=0ÞV´ú xýuؼHLÕ(³ˆ@PÜ„/}&rm“zªŠ<‡#s(Zn3XëéX”—nŸw5§£±vîvóBiŽ5¯š"’»ÂV@W·nÝê„N£<ÞOüVc]»vE=œÉÜ$ÿ8²¾VR ƒ*MÁŽS ËóÜsÏá‘Gq䀙Ÿ± p~4rrØß‚îcU8 ׯ9Ýf¢JŽÄ®„.Oñ‰½f85ž÷©@ÅJ„‘`‘åc°otç éôº÷Þ®â_©Š.HâþU™#ÑDÛÔÕÒ6ø§ïüÜØœ¨wõ‡…_ûÝ^¯˜:ÑÁt¦yÖ¾ÁG›nºÉ‘Àkß¾½…¯h†K/½4¢³Q»víœ8Tò’ùÿð¡ Æm·Ý††8±OÜ‘sÞyçY8±(UªT^7͹ <ð@Þ±ïC0 ßì;_Ø;™üsºíØcCkªÑâ ï–îöëz" "‹4¶Åw×¥p·d•⮥ß-è/Å$'OŽ?¶s"YWP=" ^& ±Í;wêF4/…Z÷]µTD Û¤j|ˆ9Éxï5éѨZ/ %ÀÚáÃŽCÏÅ’òÄÀ¢E°çXJ)¯ˆ@®Ðø–wúezú˜1œš¿1ò ¨rÄpk´Ï>û ܌ҫW/$#Tøu×S¦¸êztv5Ÿ'G)=‚>†óôYD@D FG,kÎ0o›2Oû’_©.{­m¯îï¼óξ •vçw:x&Lpv&.]º4oWG·nÝððÃ;9áÎgrcˆüñÇ6PMõ?d  ×ö&Mš8ªFþç¦M›æè|®Î-ú~Fe Xl‹/–ÈÎBéˆqîß>ú;Y94lèŸ Èá(‡ŽD@D Óhl‹ïŽHá(>nñ–š1Ã$ð/¯hvþ4ôYDÀŸ€Æ6™ûyÆ  l>y[¶l™¹ UËD@D C¤j|óúœd"·‡Ê 4)…§X¿>põÕ¡LÇŒößú&|¹p©E°76\3”&"4¾eàMIB“(ÆP«V-tèÐ! ¶ªU«‚÷œ*ƒ¾‚T7¢õë×/ o"Œ–:k°ß~Àûï»5µj•H*+" "Ž@ˆÃ3-Z´hÖ¦M›(*÷¨9mW0ž´š5k:JH÷Üs‚ÉÅS_Q”aŒAÆlh^5õêÕ‹º }úôA… òòs‘2Ø¡¨Zµjyçù!ø|ÀÉ0›7oHå N³Œ&A tPàUåpÈCG" "i4¶ÅwG¨pT®\9'y|5¨T´lÃLÓÔ1£-¡|" ¹N@c›7þpÇëºuë’:©ìž«•" "To^Ÿ“Œ¦[Š GUL>UÊì±Qä0í…ÙSÊ-" F@ã[öý3 C/Cª~úé`´˜`0`€£d4tèPüý÷ß?~<Ú¶mk!<›gMè˜ ŸspL?{ì‘PV{!¸@IDATu*," "†@è·üÎLæ³ÊB¬]²cÇŽæ–ô„9­ S>ª$*ü 2S§NµÅ"[-ÊA£4±…¡ èù?þpœèÃýòå¢Tév8bÜÓµk«® è–ŽqèHD@²†@.ŒmÝ,:×®]» ,:—œ °¨½¶ãèÝ; ª (€@®m IÉ)†S«X±"Î<ó̔ԯJE@D@\…o^Ÿ“Œ÷>3Œ ޤn;A†³¦1¼µLD@ŠŠ€Æ·¢"_øu#…S󕤺"ÕŒ8óy‚ ‰¨}6к5ð￾+ä¿S ‚ó‹t:’‰€ˆ€$Ÿ@D‡#ߥ,ÄÚ\s<ºÀ¤Îw·4ÎŽ´×,{Ù>†ð¶Ûn»¡S§N&·z5fíÍ7ßt¼X©Ëìpì üpÏÐt±ØŸþ™—½dÉ’¨\¹rÞqº>XØU +QᨴèÞC®Ãéº ºŽˆ€¤@.Œm‘`RáhOÅôŠ„'iéçž Xhw i«]HIƒªŠD@ $Ëc[`b8ùá‡â³Ï>+°Ä×_¯¾ú gu*ñAR&" "RoÙ0'<ÎYRiOGáém·¸æ“Öj!j¦L‰œ‡o¸èÛ¶¶%Š€ˆ@Â4¾%Œ0éСwܸq¨oƒEkzE°k®¹Æ‰†óÞ{ï¿Eºwï!gáÉöŠ[•‰€ˆ€¤™@Ô_½æÌb_Õ»óÅf_±bÅKz­Ç?¬™%”Ÿ¥“K©R¥x^D`#G;?ã`ëo Õæoœ€Öèýëï Äezwg‚ñááçÂÉ&fBûÔø äêØf¿°jÕ*)ÅÿO'¯äâÅÀ¤IÀìÙ°…gà„€»ïÎ;m‹ÐÀƒæë“ˆ€¤š@®ŽmÉâJÙüãŽ;Ωnúôé8üðÃÃV=zôh'ý¢‹. {^‰" " É%PÐø–­s’…d¸Z‹- Ëš“çß}8í4àÙga‹À¡¨r4|8L‚ CÏSeâ‰'±°åÐóJdÐø– ŠÉ­cæÌ™X²d ®»îº+®U«.¸à<òÈ#èÓ§Z¯ÀNrnÑö…¢[·”," "RQ;…iÅó8Ý&=k“¸CsáÂ…yý;öØcíÉž˜¢4ÿ²,ÒÁCý¬qãÆà¾OùÈ”¥`ÊR¨@½¿BŒÎIÛ¹íd§Qa*Sl±ö‘&™3¥j‡ˆ€ä*mñÝyªѤp¿­[×_w'Ÿ§MËßK_ìÄŒ¨J‰€ÐØ€#­’çw¶Ú=Ž»víŠO?ý ³îoÜ´ôÒK/¡eË–8è ƒüO鳈€ˆ@©ß²uN2ʼdŸÃ‘Žò|øáØÜ4P³f@rÞÏáˆaÕÂ9™`V¬®¼2¯ˆ>ˆ€ˆ@o!H<ŸPX85ÿÞ|óͦ¦÷èŸÓçºuú—/S1eHDŽjÂݶu“Œ>:t¨ïcƾ[x9ø·“ê^xaTí]¶l-Z”——áÅÊ~T:Á¶õ?õÔSN>NÖrr¶sçÎyå"} d½¿uèÐÁÿ0培îÊã wb*XÎ}Þk¯½RÞ]@D@D vÛbgÆüñ‡S°víÚñU£¥~úÉu2zî9`åJ˜*¦»S–aÓ¨°lQye" "0m #Œ»‚‡zÜÍ:`À{6<'žx¢£vÄE„š~«•t6Z¿~=¤n7jÈA©ß¼<'™È?…oMš§L™2Øwß}©&kËÎëv­iÓð]<â`—]:ÝtShžví`Æ@Û¶¡ç”"" >ß|$²ãÂ&LpÆÖ<°ÐNQÔ G‰˜-­ZxÔDjPYDØ×pÑØë¶­ƒŽïU4­ˆíªÁ±F'ói*J〹m[¾ T$‡ nAš>™ù‚.³f͇£/Cµ¥ÛÁçý÷Þ½aR¾V¸ï §FKw{ܫ믈€ˆ@a4¶F(üy)…ç)uÝ:Ø‚3°ß~Àý÷Ãâ²÷ÞëÊÛÏA'Œšœ"ÑSºˆ@¬4¶ÅJ,9ùþùgÜxãØ{ï½:Tæó,Ÿ 7 ª÷úlÔ¨Q2³Î<óL_’ÞE@D@ !êñÍ«s’…`+ð4Žšš7M)î„…9Ò }½ë®!§œ„’¶•ù˜c€/¿t•Œþþ;0÷Úr¨×>@.:$ ñ-‡×Þ·ÅBFqѳž×ï¤Ú/" Ñ(2‡£è›˜99ÍÂÈå5hÞ¼yðIæ%†ù@•¢W_}5ïLÅŠq饗æûØgŸ}œ Z_Ú÷ßïHÍûŽƒß©Õ¿øÇ©=ýôÓƒ³¥üØ"º9vðÁ—’ÃQ ‰€ˆ@¦ÐØß‘ÂQôÜLÀ™„~ç€?Q>þ Ò•’cˆLý•SD ç hlKÿ?Jà3”ÚæÍ›Å^†S£õéÓ·ÝvfÏžÓN; ÿþû/¾úê+0$xÏž=£ žþÞèŠ" "™R=¾yuN2Þ»EUö?ÿüÓBµˆ·Š¬/W¡,ôiÁÝdX5éG®cd" " o±ÐÊü¼¾5Ó3Î8#ó«Š€ˆ€$…€ŽbÄÈITû¬£BÄtÿý÷GÙ²e1þ|PiíÚµ¾lÎûP¨CP×®]1cÆ Lš4É)Cg¥¡C‡â™gžA³fÍœú¹+tÉ’%u—4[î- `ó}B½zÍq~ÿýwç½nݺ¡'•"" "4¶Å~¨pÄq·V­Z±αö³o½ã•cWwE@Š”€Æ¶ôáÿÅfx¯7¯RîL¾ë®»Â^øñÇÇÒ¥Kñä“O¢X±b8ôÐCµÀ–”E@D `©ß¼8'Y0±Èg¿ýö[礎"3Šæ Uk©`k‘U-„j4%”GD@B h| eâÅ®›®Y³guVÚšo˜ö pX?ðÀ´]Vð# ¥?Ñ~¤âÐÊ•+œ¾2Û¶mÃ?þè¼|iÁïüÑtå•W¢téÒÁ§BŽé8Dg%:ùŒ‹›¾.¾4ß;%ëGŒ–-[ú’ÒúÎÝuê„^’Gìo5BO*ED@D chl‹íVPáˆÎFŹ•SV(9ŠHD@R@@c[  UÉPj|ÎÝ´i“ãLT¾|ù î!tÇvíÚ9áÕ¤n“E@D *©ß¼6'´0™¨pD'ص:†0w.,T*,äP¢DØ,y‰|ÉD@D ß¡—eÇŒã¬22KºìÓOÊ•Óz‰€ˆ€­’Åž4Ü™9zôhGѨ°*jÖ¬‰§Ÿ~×^{mTÎF¬¯‚ɦÔ<%éù¹ ;ì°ÃœkÁÒõ•Iæ¹íÛÕ«jÕBk¥ÃQíÚµøÐ³JÈÛb»tæø& %°~=0|8`kÐ2(RÛRÿÑGÅG}„‹/¾Øq&*èŠ|®}çwððãW¯^eÕ9¤z|óÒœd˜ =E…£F¡bÅŠ…æÍŠÆ‡lܘ‹½WŸE@Š‚€Æ·¢ ž¼k.Z´ï¿ÿ>N:é$[+ ³X˜¼KåÕd:˜5 hÝÚ ï™wBD@D@ÒJ@ G àæîLßÍŸM7vñâÅN˜³ªU«:¬|h¥¬<¸c&V£jÂ¥—^ Ư2e ¾ÿþ{G†~£=éí±Ç¦(T;v´øØMc­:©ùélÄEÅÝv ­–G 3'ðm…ß§íæi»lÙ2{˜µ§YY›[°Ð±w5htïpZ" "P$4¶¥;o „½öÚ Ã¸*…qâ™›jd" " ‰Håøæ•9Éx)nذ ,À©§žoY_Ž Guë•*e}WÕA # ñ-ÃnH”Í¡Hp/¸à‚(K$žmöl˜Ú.pĉץD@D@â' ‡£øÙå•<øàƒÁWªŒ²ô|ÎÔ‡`‹.çX°Ó2eõÿ¶Xkuùt*ð\Û ºYK—.ޤpJÉg#u”³Q(¥ˆ€1mɽ ‘ÆÛûPUÞä^Yµ‰€ˆ€øHåø–és’þbùüÝwßaÇŽhÞ¼y,År&/ÕìçÍ:tÈ™.«£" H@ã[Þ”Mú÷ß(/܌ҩS§¹’ŸüÉ'nmÚ$¿nÕ(" "=…T‹ž•rF às8 V8Z²d‰S‚JL2ÈTt å²Ã‘EÀõׇÞÑ>}€wß…)]„žSŠˆ€ˆ@v˜:u*Ê–-‹c=6»:¦Þˆ€ˆ€d=†S£µhÑ"ëûO©\»y3Lµ>žÒ*#" " Ìo7Ï&OžìDg9ÿüóãŠö’WQŒ¨°^Òd5=4Æ‚Ê." "Tr8J*ÎܬÌDŒ V8b85šŽ ú#" "%~ùå§'ܵ“‹öÑGÀá‡wß Ì™H€aÔŽ>:0MG" " ÙG€j¶3fÌÀ‘G‰råÊe_Õ#¬&ðÍ7ß8ý“ÂQøÛÌpj´¦MÝwý> T¯Œ馎3%J”@îDŒÑL S¦ ÆXвÓሾÃ*Ä^V%D@D@’G@GÉc™³5ER8’ÃQÎþ“PÇE@D « øŽ6l˜Õý ×¹/¿N<(]øøcàÀÃåRšˆ€ˆ@¶øðÃMù`³Ô²ýF«" "¥fÏž=öصjÕÊÒ&Ö­~pËËá(1Ž*-" ÙJ€êF•*—]<øàj¼óÎ;8þøã±5Ö>+ 4itëæÎ7FSÇ‚ÀŠÀGD“[yD@D@RI@G©¤›#uûŽ‚CªÉá(Gþ¨›" "cQ_Þ¬å|rȨfĨ9œT0¥d(>zÝ|uUD@‚pB™¦pjA`t(" "ñ¶mÛ†̣栃Êø¶UépT¬°ß~EÕ]WD@D “ \z)ðÉ'@½zÀ€»`ûö“qÁÄÜä5k€‡¸§“ßz xê©èªáõišŸt9诈€%‹n)Ä “JªT ¬gÉ’%NBݺuOèHD@D@Ž9æ˜$׬êD@D@D õ¾ùæç"R8 Ïú߆©Q8µð|”*" "Oà—_Þ3g£æ º§Ÿ^|®°Oœg¤ºC©y¦››JGõë–\¸*óÀ£&R˜gT8b~EGÍC¢" "PdäpTdè³ÿÂt8’ºQößgõPD@r‰ÀF“øYºtiÎ8ýﮃÑ_/¼œpB.ÝmõUD@D …S GEi" " ^!ðõ×_;M-j‡#†ªfè²L³Ÿ¶nöß?ÓZ¦öˆ€ˆ€d'žxÅ‹ÏÇøñkQ¶,е+ðùçѵ’êFëÖ·Ü«#rn„ä¸tÉ%@—.n¾ \e$©Eæ¦3" "N|§³ºV6øã?P§Nlìšú$" "£-Zäô<Ž(cLe#²€ÍØN¥½é궈€ˆ@:•,YÒï$yF" " ž @‡£ÝvÛ­Èç,O9hÓXµªè°½ø"0fŒ»ëkéѤpärÐ_@=ôèüôÓ ¼ñÆ8úè£qüñ{`ÊXX5à¸ã€9sËqì{øaX86àŒ3‚Ï[õN¨µ»ïú÷wÏY`ps$Û"(z%Ù„½÷Þ{n±bÅêÆÚœfÍš•åDc<¶.¨²¬ ðÑG°õÀ/kÖ¬Áúõë‹üá=+«" " C€áÔhÙîpÄI‚ÓN6myèÝÛé¶þˆ€ˆ€ä8m¦aÿþûï£uëÖØe—]rœ†º/" "à5;LVhŽ­‚‘’ cë´: ÊCQØðáî¢ðàÁÀK/íÚ?þè¶DGEqGtMÈ|ö8ˆ‰æÍŸ·gÛзo_§Ñöˆˆ7ß„9; y¶÷ÞáûãS7züñ‚Õ|¥Ë— òå¿3]&" "Pô…#s62PTŠõµeË–RtŠçUô]W ’EàÔSK/ ¬áÔhR8 ä¢#oȇ£ƒöÛNìuJËD@D@D€fΜél,9öØcDD@D@8ap|‹Â7ß ,\¸±´¨Ú§ëŠ€ˆ€dJQ¿>ðÌ3£P£F tëÖ-¯‘;ãÆÿü0_8ó©í»¯«”.ÒD@D@¼E ¤·š«ÖfJ$òBµj-[²d‰“P·nÌÂYéHD@D@2ˆ@®8ժ̚•AàÕŒ Àpj´cŽ9&#Ú£Fˆ€ˆ€ˆ@,NVTGË—»¡cºtqU ¨_¦L,=H,/lþhÖÌ­§bE`Àફ€bÅÜ´â¶=¹aÃÄ®£Ò" " ÙKà¶Û€o¾ùÉúàšk®A©R¥:Ûµ+°x1P½z@rÞÁ¿ÿºc!U8æÈD@D@¼O@_çÞ¿‡EÚz*sÌ^{6C Gp*)C‡tjºã ¸V’ÂT•ˆ€ˆ@.`HÎAƒº D‰hn@ …ѸŸ| Êº‰ þŸ½ó€s¢ÚþøXšôÞ‘.½ Vªˆ¨(EE±W,(–'Ï‚ ËEQžÈ_EQ|Ò¬X± ˆ V,T‘Þ«(½—ÿùeÈn’Mv“M²™dÇÏ1Sîܹ÷;aofæwÏ‘‰€ˆ€¤ Ýb¤àEÍÍ.͘ üõWÆY¢xíÚµ¨Q£FÆF-‰€ˆ€ˆ@’HÁ‘h’‰€ˆ€ˆ@ÄfÍš…-[¶(ZÄät€ˆ€ˆ€[xGL©–ÛöÝwS¦]rIhÁÏ]wÁD½À{öÄ®…+V/½œx"гgìêUM" " yÀÁîÝkp ' T©Ra0}ž~xä‘°QA$"à5hÐàúõëáõzõêUO¢>¨© $0y20p °ukF#6YœÞ}[Q‚£ &ZH~É.8bØã³Îr`'ÿÕPD@D@r“Ó©ÑÎ<óÌÜ<­Î%" " 1#@ÁQÑ¢EѰaØÕnEY¥SóÖQ²¤s¯fs8qÅÀÂ…Þ=Ñ} ìß ]=:ZD@D oظ‘ïóáàÁ¹a§SËÛÄÔ{È;ÒŽvµ]¾|ùjy»}ðàA ä*ì Ø$W•/ŸQvõêÕž Ž2˜h) ?ýüþ;ì+À8›Uª8±¦«›þ±R¥ÐSÀ¨:½ÈÛoiög¯Z5 jU§Þ‚ÓwkAD@²"@ÁC{ì±Yså¾C‡€ /¾ú hÔÈ•MT£D@D@\L€‚#Î`=餓\ÜJ5MD@D@Bøí·ßТE Ï=]èR±ßÃ(³o½4k4ožuý7Þ|ü1ðÎ;À»ïÝ»;)hÂÌZ“©ò €7Þ€½˜G&" " 9%!„]hãÊù9­Flj€ˆ€¤ ¯à(G]2dHCÎ ñZÿþýQ¨P!ïª>ó¦Rc8Dß艥à…ß¾hÒ`Øé:u±Aíй\ºttçÓ”§ž ^EB^RÍš@­ZþΗÿÇüXß­wÜË÷—±…Â&¶»bE/W ‰_n¯×«ôîql¨¥¾}òbBb:ÏQ»¶ód‰O—è¾ÿ`BÕ£í" ®#°Ìbà×´¿A“P¨øðÃÀ‡W^ <÷œëЪA" " .&ðÏ?ÿà'›ЫW/ÓîGõÁŽTÓD@D@R™ŸUnÞ¼}úôÉõn~ú),-)À”iÙo5?ÿøþ{`Ø0`Ò$G€Ôºµ#<â$’p‡âõëû¿Ã‡ÇÏîÌÚ/" " Yð ŽŠ]ii:-O§LD@D@ŽˆêiáG}tÜoˆ«ðºë®“à(}µxùË–u4Þ®¯ZµÊ³È—²²\$ÀéNöðĺ‚á¡‚~Üq@±b¡²f À(BYãe2‘<Ÿz0s0£à§F §.~z—šÓ¨¥(+³¿8ã çÉ Ÿ†¬[°my?W®~üÑòÖµkWö¢£qãFàbÝô f–þ Ìœ ðÜÁìœsÂ}û­“cB£üùˆMGSP¤WK6ժ崙ìè|‚ÄigÙ™‰,ÄŠ#†Êª,Cš°|U¼¸s¶+;[²xðAçZò»áë~…SGvçÐ~HBŒp”Œ7ÔŒjôŸÿmÚ£FéŸp~õÔdH(/¿ü‡ìwe·nÝÚ\D@D@rJ€éÔh­ùÜ%—éÔøxè’KÂ?ñÉ';QŽìǯ½\z)pÿýΣ+>šÉÊøX§}{ç‘ïð^P&" " ј3ÇBö¡ N9¥LRNÆŒ¦ï:VD@D köZ&9'ÀG¾éÔXSž‹pÄiG'œ½øã?€"E‘I¸‚ >Yxì1çéBvQq(b¡8çý÷ao2.*ÏEÁ…G"ñ“ÎHEcÆ8Q…(Ä9?‹0˜õë|8Ãtgy;üä”)~òÜóüü³“³'£N8|·d^nРggE p6ìŽ;P·nݤj=5‡|0]¢ðæ›ÎŸŽ¤ê€+" "pL§F;óÌ3Þ5@D@D@rB€éÔh‰1-šwW¤mçíçˆ#Ö¾ø"Ànd'6â9h»m[àòËaQ"=«Ê‹€ˆ€ˆ@f?ü°Õ6G-3ïÔ¢‰ª4N«Š•QhCÁ =ÖFöŒäD¥y™ù¾¤¡ˆÂ& ˆ¼ÎpaÙ¯ïÀÀ‚ŽSAÀÔm¾FQ# qæ…hRñšìÜž¨‹‘¦öî͈.EáB/K§>Þ{Ï9#ÏÕ¡ƒ#|âõ¦Hnòd€‘­²2~_QŠOÀ(Ø£pŠéëd"àRŒnDK&ÁÿéSlDèÛo;ÃŒKñªY" " .&ðõ×_›Îý8ûYi¿+e" " "„á¨=OjÒ¤I®·ži­£5>.4(üZøx…)µe" " "+‹óÙýŸ–¤¢k¬ªT=" " )B -Eú¡n$ˆG óëkU®\Ùéõ}ÔI Å,]:j‹oÂ]~þyGhÄÔq7Ý”ýQLÆ4ZÑA&P(B1 …"¢îñÇÏ>™`§pa iSÇ[ÅH;1}Ø¢ENÊ5¶+ÖB†Ò €„. N€Ìs"l*SƉRä­•b%~Ÿ(ìâ”9~˜>-Zã÷ˆ"8z Q¼ÄÔqÓ¦9ΧX“&9¥Ø'†TÉNpDÜK/9Î#™ö)ŠZ´pRÓmµ™¾Î²ö÷Å“ŠË2È%É(8â8u*póÍÀä(FD@D ¥¬µû‡åË—£_¿~)Õ/uFD@D o à¨©=+£è(•Œ/¼àGf>åG™ˆ€ˆ€DJà exHãdóÆW;v”±qf†Í¥ï¢”6‹€ˆ€äU¡G¼JDý›ƒð0ÓœøG®˜ýÊ,=”!¾if¨G  ôíRæe¦9{à'¥£Qè‘õí н¶k— ÆàÛS|gz¬§Ÿ8 *–骼‘vºtñ¶BŸÉN€‘»(LËM£ ì¬³çy)@bô#Šï¸/9¸ï>'bÓð1r?gÌ}4SÒr"ÔrŽt„LLHñÿ€1>¹[¢±yÛ¨OWH6Á‘£À#­Zƹ©%" "¦OŸîieûXF,M‚~«‰" " ©C`Ó¦Mö`mJ¦å\0:'šðâ˜1©sÝÔÜ!ÀÚ={öÄ'Ÿ|‚ÓO?=èI¿ýv“m¯h‘oݯ" " y›@ZÞî¾z T¡•/ï|òÿ‡,MÔz{™â‰'flLÄÒœ9N 2 w>ý4½z9Îþ3â#o1]ÅEŒæÄtˆ^÷ Ž˜Ž.ã¿ßJ•`Ó3œ”pÙƒFOŠ9ßã)Úò¦é³Ï™zN&¼‚£:Á¢~”Mô*¿æL¥Æaæ­·,“‰€ˆ€ˆ@NxG˜BW&" " IH€Ñh­U9)®iÞljÎZlÿoï‡ÁG ¯¼KqÛºU›ˆ€ˆ@Þ ðÚk¯aÿþý–Äã&Ì›7Ïž#f~8i’eÍ0ÁQûöòõRD@D "E„K…} 0l/Í7Âg QtT“‘Ne ñŽ›‘Šå(œèCÞ¶2lUܳf9ÑV¼Û½éž(L È¨];àãR¥¼%ô)"-Fó:î8dzª+œ€ŒóÊ·ü÷Êz«TqÒÃqv>ÿ&0ÚŸú-] ,^ ,Y|ðU“8ÉWE™U;´/O à¨¢‰XK„Å+t˜å“¼&Nt´t lŠN-" "äfXôIF¯=–i{e" " "„%8b&ùÎ矇¥&8>Fyê©øÕ¯šE@D@R—Àn{†ÎÈFEl¢ï{>>dÈ <8S‡gÎt^öîmóe" " "@@‚£ Z Ÿ@0ÁөѲM©ÆH&L§Ä—ý½{Ý»‡ŸŠ)«&RdtþùÀŠÀ«¯§œ’UéÌû˜^‰B"ûÂO^§‰‚$¦’z÷]%Fw(éÿ"àNN›ìÛ*^jBþý°¿Î9º³WjU Pp” шhèPओ€‹.J 0ZD@D é l±¾yò’K.Iú¾¨" ©I`ýúÂÀ¶@jvN½Š Ž ØÄ¥æ¹a|ùrXÄÿ‰š1ë”*˜E@ÜM HØ .X¨_›ø)¼ñÞ`ÿ»téâ³Õ½‹ÔÎ2û§LD@D@¢!ðí·ßZÆÛ#6¿}4ÕèX‹Àƒ£F9i¯º ¸þzÿÃø ê§ŸÿñGçsÓ¦“Эۧþµ&(8jذ!ŽáĤ\4 Žhµk;Ÿú¿ˆ€ˆ€¸ÀÛo¿mÉò٤ŋpâ‰'zîýn¾ùfK`YŽÚܹs±eËT ØÚ"!y·êSD@D@2X>™äŒÀÅ;YËÎ>;ãø°GO> K üöð @‡ÀgŸ9"¡J•€ÿþ7£Ò¬–(òëyé%€Â¥§Ÿönݧ7-SìjTM" " I@`Ù²ežVÖ¥’G&" " y„ÀtNä0ëÀ{5™ˆ€Ä™jW­êd»æ\¯@cÚ¨nÝ€¾ø–ꑳע`AK§-¶šRm¹)Z·n¢Dü6ßy'0>ФIüΡšE@D@D §öìÙãI§vê©§¢ZµjàçÕ6‰ÿ û¡õƒµ)S¦x–ºò½›LD@D@‚P„£ P´)|iß °G3fßïLWkÙ ßx#ð÷ßÀG9éÊöî;k×ÍšmÚ#Gz¢“àÍ7a±’³?^%D@D@D L§Fs«àˆZ[NÖ½üò0:£"" " "&vßVÞÂÙ6jÔ(Ì#TLD ¯øçà½÷€‰o¾q‚WW¯øz•*#Yæ-šAìÊ+:íÐ!çÓ÷ÿŒàÉlÙ6ùÞó‰sؾùf ^~y½o1-‹€ß8ÑÑ,‚#~¿ù¸R&" " n$àM§Ö§OŸôæ=iÞÿ}ÜqÇ8묳P¢D PpTØ~x)òm:&-ˆ€ˆ€‹ìÕªDH`ÕªU6»¬ *W®úHF7ÊoÁµô/Ã4j¾O˜ü÷f^ã“,Þ¹[¨ûÕ”, 0U[™2™Ëj‹ˆ€ˆ€䀛G¯¿ÜtР,ü±ó&‡ÝÔa" " "N`çÎŒö7œ{î¹éÛ´ "· pîSD1²e§ƒS{éÎ(~göœ€Ö;»-øÐš5Àœ9Îvoy~žy&У‡ï–Œå`sÈ!e”Ö’„&Àtj´DŽB·J{D@D@D ñ¼éÔÎ?ÿüôÆp EGýúõÖï–Ëß|óN9¥ Å}”âéGhAD@D@ Žô-ˆ)F8bøÅü³yó€É“þˆ©_?X‰ð·5mêˆ,€(W.üãURD@D@ àVÁÑ®]À}÷9/}¨»åŒo™ˆ€ˆ€Ä‚À÷‘ö Ýgik,hªp>B ŒVØÂÍ› ü·Rè>z´³í®»`/ 2ö—. ,\téôí ôê”*•±ÿða`Ó&G|Ä`Õuê8«3JhIâC€‚£|ùòYT,‹®.ð`:µ?þØ„D§xÞçùb¹öÚkñꫯbĈ¨Y³&öì¹3f 5¼ ÈPêÛ4-‹€ˆ€¸”€G.½0ÉÐ,¾Ü䬳ÓNËh-G 9Õ-”  9Ü}w¨‘o瓲æÍ#?NGˆ€ˆ€ˆ@(8*V¬XÖÑû¨'ÖE¬I˜:Y¨Q#Öµ«>¼L`úôéžîwèÐ!/cPßE eðÑÓO³gþéD ²÷GžhE¾ŸëƒÖ[¦2_aÒ=÷À¢ž+WÇŸ çñwi0ãœ4¦·i¬„¶‰@|PpÄÔØ%=mûv'²W“& Äž‹Øu*0 xÓ©]xá…éG|ôн;““äà /¼`¿÷Ž·$%ÌR2Ê&£¤y~7¦Ö‚ˆ€ˆ€øàȆ##pçÀ¾}ÎÃ*¹wï^l¶ip]»v ^‘¥[Ä ŽBIO˜‚3ÒVנਧa»Ð˜JM&" " ±&0Ãr'•(QB!b Võ‰@œðÙ S˜1ýë¯ý@[–DLœèD¢hÈ&µƒh˜¡žQ3}ÑŠúôvìðJÔ«ÐCY(±Q¨òÚ.ñ&Àô ‹-Â\ïSeªÖ,'â×óÏ7ßœi·6ˆ€ˆ€ˆ@B ¦S³€F°ÀFxâ 'V@‹-0`À >ÜèM-råK.’/¡mÖÉE@D@ÜK ¨à¨@½4h°!»fïÛ·ÏoîCð.\8»Ã‚îïÝ»wÐíÚè^[¶8³á¼-\³fg±F¨0 œFW¶ll£yO®OˆC‡Ù,î•8çœsâP»ª÷Ø¿?~üñG/t´ˆ¶ÒV&"à óçÃR_œ}~ÿýÀ™gf4‹ÿT×­s" Qøc?aýìä“mÛ`BB¿Íž>Û¡øˆ‘‹xìé§;2—ÔH.sæÌÁaËç×:ù_–/wXÕ®\ÌÔZÔ',Ú%—Ï<<ð€ó[Ñ,yä|ðÁ–ád,î¹çÄÔ£Š€ˆ€ä˜@PÁQþüùMÇš½q¦ˆ¯=ôÐC¾«-Kp.WfTßìi«ø„ÊŒy]ƒ#ñ V‘"Awk£ˆ€ˆ€¸Ç¶ƒzÂð»¡mÔî~ÿ=pùåNZS7´ImH-?ÿü³'zmûöíS«c긜³ÏoܬXá<:áã¯Ï›ç,³  }ü’Þ#¦> Ü–¾Ó($ ¨\9'R«V¾GhY’ŸÀܹs=hÖ¬Y®wF‚£\G®Š€ˆ€„IàÓO?µ—»,¢eìÞ Ø*(N78ÑtE—^ 0/#Þ2R`šoŽÝ0Ï¡b" " y‹@PÁQÞB Þæ”CtûÚêÕ«=«!#q¯ÄF¾È´," "àrL§F«[·nT-åŒôÏ?˜Â¢~ýœWuß}À»ï|fÎÙF2ˆ5éÓ§{ªìСC¬«V}"'XFBêõ˜¶Ì­0D(La6u*ð÷ß™18³ûZV ÏoI¦N+T(s9mð'à5oÞÜG.¬yGµjåÂÉt ˆ€€7SŽþþ;,õhF*µÇî¼ø×¿€_„ÄFpUQÈË$8ÊËW?Æ}Kpãsª:ˆ'XŽ8[yÐ-; ¾ú øä“œµø—_€÷Þzõ’Ø(gu”ˆ€ˆ@8f˜Z‚©ÒO8á„pŠ«ŒˆÀQ‹;¢ ŠÌ-ûzôÈ@3~<п?ж­ó»¿ }móf€Q¤)(§@áØc=Úù¬T È—Ï·´–E@Â!@ÁQ©R¥P½zõpŠg[†/«Usþ­fW˜‚£Ê•¢E³+©ý" " "{Ó©½ÿ¾sno¤Ë;îp"½ôpöÙþ¿gs¯•:“ˆ€ˆ@²à(Ù®˜‹Û+Á‘‹/Žš&" "#±ñÅFL1y20s&pê©‘7gÐ çeÓcE~¬Žp¶,3m ¢Øˆ¢#™ˆ€C€‚ f‰ç‹:ÓN(àìÛ³øÏ€§ž®º 8é$ruï|ó 0eŠ#:ò-A!ƒDE¾D´,јg¹cÝhÖ, K X1`ûöìÿ½RpT»vô}P " " "KL§¶sçNO:5ÖËß³ŒÄîñ÷èë¯;‘Õ)=¨PÁIµ–?,[¢ºD@D@R‰€Gp´{÷îã‹)bCKd6mÚ´‘E‹µÀÏ2(8²ïÊ•+'" " "(8*`wßÇršyŒ/ î½66:b# ˜mÚ´È*cù/¾®¸hÒ$²cUZD@D@Â%0{öl{‘ºÝÒAµ÷•¤!@ÑÐÝwŸ}œy&pÝuÀ)§o>#Tú €-Ö¯† q¼L [7 M`Ä`åJ E `äÈàÂr–¥3­Úºu™Ïé{®Ì{µED RkÖ¬±…[*jËE»í6ç¥ìر@à߇Àêy¸apÚi{´." " ‰%à›N-¹ñFÇ}[Uµ*ðòËÀùç={:ÑúL£$<‚#» ’%>ä1é;ªU«¶/}E yŠÀO?9!¯¾¨WÏé:G5jÔÈSÔYÔ&@ÁÅFiižŸLw–7è6ÝsP‡"?XGˆ@.ØgO£˜êá†`Ѹ²>ñ¡CÀ‹/÷ßlÝê¤){í5'Q àÈ4 q¸eaÂsÏeÔKÑ8ŒrÂô¸ŒZùæ›Àĉ°”MNY¦Lã,ñ¬Œ3Ãc”Ý)«ÓhŸäyL§F‹E„£ €ï¾n¹ÅyñšÜ+œŠp”)íÈMéÔ²:÷yç99áˆiÝ(+ZÚ'" "³·gâ–ç 05Ìã;³½‚£U«VyBïçy8 " "2(8:™93rh|ñT²$pÙeN>¼ñ†ó"+\ÁÑ?üà<à®U+‡ Ña" " "3fx"û¨ÂãXÜ"ðÞ{Àw|©OÏÍ7gœ™„|_ˆ|ÿ½³ÿ·ß¦5£ð›³µÿø#³8ˆ‚‚ÓOäœs2G1a¢¶m<ظÑI›Ëôi+f´AK" ‰'àEáh÷n'2ZÙ²áOþ`:5šîÝú¿ˆ€ˆ€;|fa>}Ó©eתáÃtjgœ‘]IíÈë”u3¯rØÿ¿þrôfOcØ}º'ÂÑ?ÿüòÍ79¬]‡‰€ˆ€ˆ@â lÚ´És#^§N7†‘ÕÈ ‰®øçŸ÷ßϾZ¾4ãlübÅœÏìP È9 ŽZ¶l‰%Jä¼)9$Àß=á˜}M=‘І úõó?bÔ(àøãF0ºöZ'½ÙüùNŠ[ŠŒ(6¢5jäÌÖvÖœÿ3=e0åÚGù§Tó-ç]®T èÑCb#/}Š€›Ì™3ÇÓœ¦M›FÕ¬¡CˆµŒ4KÑQ8æ)ÂQ8´TFD@D ·¼õÖ[–28.¸à‚°NY¼¸“J¸sç°Š«ˆ€ˆ@& GyøâGÓõ-[œ£½‚#¦S£5ã¯F‚øóOç³cG§ þ/" " IF€ÑhuëÖiË™3ó·m˾Úqã€yó€Aƒ¾Ô’‰€ˆ€ˆ@¼üi÷pÛ^rÉ%ñ:…ê fÏž}`Ú¢¢E¨ Œ B·Ì¶èÞÝ_ÄèB÷Ý”/Ÿ¹:þ¾Z´¸ægD#FøŸù(g Ó׆#u¼¶‹€¸‡#15vI†›Í¡ñQ'GMš8“FX S4ò6‘éeB™G¡Èh»ˆ€ˆ@¢lµ¼ÂïÛ]¦Î®V­š§ü¼lðÄÙ§(NT»u^ä ÁQr\'×µ20ÂG'Z+o3صËy¢Çäæ2HRÑŽöïøÒ*˜Q8ćÐL’•8<ôP¦ ðïgURûD@D@D zÓ§O÷T‡Ð2ˆ†ÀºuN„!F9Ñ´j•9ZБ#ÀäÉÀ3ÏS§:gc&¿Â…•+}ü-D«RÅÿå~©RÎö`ÿ¿ûnGðæ›@ÕªNj´`å´MD u ܽtéàÕ{ïõ˜ÆQ&" " n 0vìXìÝ»×"€^›Þþ^fPŽs2ˆ†€GÑÐËÃÇ2Âòyo¸ù¤ðkãQˆoX'MrâŠça>꺈€ˆ@òÈ©àÈ"ƒQŒÞ~hÝ:8‡ìÄF<êÊ+ag…z˜¼vmÈ 0­]»v‘¬#DÀ‡ç 1%,ÙùlBµ¥opÖùÿ7Þþó'0rÁ‚Àe—wÜáÿ»‰éÕÖ®uÄGÇ—ql8K|Vqýõá”TT$Àˆ}ûíùd³fÍrܽ™3‰Ç›]»fTã­’‘ÙBu9Ò™0’þÌ4ãp-‰€ˆ€ˆ@B¼òÊ+öl±tz:5þÖæXÆÉ2ˆ–@Ô‚£esoãÆÑ¶Ã²puª ÷0‘oøòãÇÇ^;ý{rX»GÜkˆÎ$" " q"°dÉOÍ‘¤T³ÉBàÌz¾Xc h¬^=؃à¶Û¢©EÇŠ€ˆ€ˆ@xá¨Q£F¨P¡Bx¨Tž ÀHDŸ0jÅAŒàèýä2Sµm 4ož£~}à‡>7àã¢üù3öqÉ2Yú>àž{F>šÕÁ¯©QÃq¿ZlÌ™3ÇS"§‚#þÝã=ÿÆ æ²-œHµŒÄÊ*Wè2pY³f™¸h6n¾ùfK_\ÔӤŋ;H¤nh£Ú " "ܲիWÉ®;æË—ïôC‡=h£m¾]þßÿþ‡ &ønÊÑ2gŸÈ’‡#1¬¹ÇvïF9ÛðŽ­œ}ÖYG7êCD@D@’›À‚ ìEW /^<ìŽ08Äš5ÀС@¹ráöÅ΋:¦Nóµ‡öà»OË" " "K«V­²4V+-*Ìõ±¬Vu%1C‡œè?ØO¢,­€=|-«ÙÒƒƒÇã{„–E@D 6æRÕh–SÁ…’üHÑ'ø³Žòm‘"¾[µ," " î%ðòË/{wó‚µß~sBEf÷–Ó§ˆ€ˆ€„C -T!›Í_ÏDFäÏŸÿ+ã)gË–?Âi²¹ÌG‘Î;RªØ¤ûJ¨Á"T(8*d቎‹4ãÑ^2:Ñ/¿8ï;Îot™ˆ€ˆ€$]–ë˜#Ž?þx´lÙ2½É^ÁQ«Vé›´ " " 9&LpT Aƒ6/·šÛŸã“;°°½ak-m04®Ý¶g`A2"70٫ٖêÕ]Ûf5LD@D@"!°téR챯iÓ¦YÆÄLâk ø®e½|Þyßí®Xá̔ͺ´öŠ€ˆ€ë7€Ü@IDATˆ@||ýõמŠ%8Š_·ÕjºjHˆÙó*Vz(U*£•Ì*»Íb[?ò0` P-‰€¸ŸGLš––óÇÚL똓(FŒŽôÏ?@ݺ&¹ÿ›¢Š€ˆ@êxë­·°cÇôë×ϯ³¿þ +Dò Ó¯­ˆ€ˆ€ˆ€¿;¯ */]ºôDÛßݧLD‹ÌÊtYg™0TûÉ'ŸŒæÍ›{fdU^ûÜE€ÑhÞT1{øŒ$œÖ¦g»þ'" " ÉN`Þ¼yž.„­[çÌü3xï= gÏœõ˜±¾ãÍY:JD@D@b@€Ž ¢JzÞìTª*J€¢"»ULJ½{¾)ζn¾ÿöòÁi"Ó¸úÚ¿þÐÀØ—Š–E@’ÀöíÛ=)BÛû†ŽÍņÜy'ðí·À©§æâ‰u*B€éÔŽ±<Æ_|±ß^F8²W³ ÀV&" " ÑðQldiÔB‰6Xz ˜µ}þùçžË,ö¶×¿üòKlذ!ýÀýwû›îÑF•t&É´ð×_NkË—w>÷ýô,}9jžtR2uCmGœéÿ〠yžOÞ˜3H—.@:!«Ñp=•+WZ¤½¸ñÆ]ßV504FKäLeþFá'·x' ñE‚¯à¨lYÀÞÉcï^`óf D ÿz%4òç¡5ä!ÀèF´fÍšEÔè#G€^®¾°¹´Yÿ¶¾û.À44mÛú]¾ÜY7ŶÿÑZØX°`M2øW]u•¥I.™^ñêÕÎ}‚Ϥ#Ñ‚ˆ€ˆ@”ÒG–F1õüÄFGÌL€ô™myÑ¢EÙçÁÀóÙþÀM¨T©’ÇÁˆvÇwà©§žÂĉÓËŽ³) m;hРômZH–öÕ~ Á‘M›<ÆÞÂ~cMoÑ¢Ert@­lÌŸ?ùòµÂ½÷¶Ä/¿ÿqÇ¿®]þý³ÏÎØ®%HFJ§–|WÑ‹fÍ&OfÌpDFLáã5FPäí9«œ{.l²—wÿ'ËÕ¨á¿Mk" "̼‚#FÔÄ^y¸ùfG„É4“Y…š7ÜÜuWfÁÑîÝŽˆS³"¨}" " ¹Aànf×]wßé8AFá¬LD@D@bAÀ#8*_¾| «ìß )62»~ñâÅΨä»3Âåâ6=îa‹Ñݽ{w{qw/Ö¬Yã©áõ×_GãÆÑ«W¯kTñD`HàmÛŽ¶`ñR´³mõªg%²:·ˆ€ˆ€dE€Ž ~S§À '8Q¼ŸŠh”9íH6%Û˜)è»ïœv3:QË–Î ÎR¦7jd)ÏÓ§—%_ÿÔbÈ)¯à(’GŒä~Ï=@ÕªN:ÉìÎ]¿¾i6†ØèÑ6k÷eØä•€Z\$À,3ÿûßÿì¾ ‘¥øôÏñÉh¨4 Žú¿ˆ€ˆ@ô< Ê”)sUUÜ[ l¾®]²dÉï¶X|ž`oêFŽ‰Þ½{ÃÒ³yª|ä‘GìEÞ vSgwu²ä#ðûïž6¯,SåÊ•K¾ö«Å" " "@àÀøóÏåö[¥¥'’ÑgŒõ(%0mÚ4σhF*–¹ƒ3Õ?öÀ?ŒTdQü¬O S' Qm1ª™*­@¿ÝZà’K€gŸõ?5_zSh´nðÞ{þû´&" "œÀêÕ«±uëV4oÞæÛb3N푉€ˆ€ˆ@ pG ©ßÐÂñ§@‡ÔAà믿öì騱cˆÚ ›[e© ‚×ðÏ?Àg&ß}¼Œ¶Š€ˆ€„O`îܹžÂ‘F8 ÿ %½‚£ßÏØÆå_6nÌØ¦%Èm£G¶¨íGЯ_¿Ü>µÎ'" "G PpT5 ïÓÖã²Z¯^=¿zgÍšå·®÷àìËnpÚÇÜè´Þ;mg³þ/" " IK`¾‰iÓÒÒРAƒ¤íƒ." " á`„£&Mš bÅŠáW™0BQŸ>@õêÀ5׿øLë²IÇ8ùd`º=}¹ãàÍ7#¨XEE@D@‚ð>£ Gp´v-pÚi×ÖG0´Ò½A”|#}ò pÓMÀš5!Òfˆ3ƒâµ×^C­Zµpúé§Çùlª^D@D@ùí£š/ŒÃ‡¯ò]×r:uüªÞ¤¤×~<ܼšÞHŒ³íκH‘"z)ëæ ¦¶‰€ˆ€DD€Ž(6b®s™ˆ€ˆ€¤*%K–ØKÑ5èܹsªv1¡ýâ=3S<ì¡?Ц#2>8é$`ñb`Äà™g€ü|2#ˆŠ#1ˆÓ¦M³­çž{ùËi4¢’%ÚµýSª­X᜖Ûe" " " °´Ìëpýõ×{ÆÄD´AçÈ{øXË/‘ݘ­Ê uëÖõ;ÍÆœÞáùÕ¢•Ü À`F:9gâì!Έ-P @nœZç¸سg–.­‰bÅnÁÎq=•*„`t#Z'ïÍgMÿ $ðóÏÀW£Fö3!¨:KY¼õVÆî‚¾}o¿~û ¸öZçÅ4#ñ7ƤIÀ-·d”×’ˆ€ˆ@t(8bD‡%JdYѲeN:K¦µìÖ-Ë¢YîäóÑ… }ûœbŒ^G!RÙ²Y¦" " "C† ±Ôž/¢k×®8p`Ðsôè t—6Š€ˆ€ˆ@Ž ¤Ù‘v+ägù­e³r“ÅŠí˧hG­\¹rÞÅ,?K—.í©â“9³Í›7gY^;ÝCà•Wœ¶üý÷ßXk1ˆÏàºLD@D@R€À‚ ,Ïùuøùç¾8p :¤.ˆ€ˆ€ˆ@_[hF‚èØ±cˆÚüå—@ïÞŽ@è7€ûîn¼Ñ Uªäðá‹æ‹/vDŒ|á…™¹µl ð>ú©§€?Ú¶7Î\N[D@D@rFà€Ý¼-4õÏYg•mC‡|í W ŽÞ°[H´jPp¤èFÙâW8xÃnVÙÀÖÒn<Þ}÷]äì‡ã¤¦ÿ<昀Z( 0ÂQ Ò§B$uV²§l 6L÷´4j˜²·;vØÍ#6bé}Þé Ùª.!Àtj´¼Ã–‰€ˆ€ˆ@ `:5 =jÖÜ2eR Cꂈ€ˆ€„ ÀGL;SÞ›/;D¹¼ºÙžÓ£{wØÃz`Ê'ý™Í›ÂcžŸ GÁXV:̘\z©„£`ÜøÛâÊ+%6 ÆFÛD@D QtÔ¬Y³,«Y¿38å˜à6Ë¢Ùîô>åãQ>â^e9$8Ê› ˆ€ˆ€ĘÀ—6KâZ §Z³fMLž<9d¤?ŽW‡;"Ù7AÕ‰€ˆ€äqiGŽÙÈY^³õÞåx~náÔ?+£·z>4’cÑ+8jÞ¼yr4X­lÌžm1ñ±çŸ~6%µ[D@D@’—À¢E‹°nÝ:\pÁÉÛ‰8¶œÑˆɨbEà‹/`Â,àôÓþý¯¾ºtÉ89³Åÿô,,bTÆv-‰€ˆ€ä¦S£e'86ÌImt#ž‹‚#¦PÛ¾ øôàA ŽÈE&" "&Çs"Ã&¼ýöC(^¼8>ûì3T©R%äÉ;`ÔVF[•‰€ˆ€ˆ@, 0ÂÑjß M|t¦ïz¼–çÏŸïWu¸©ØüÒJB Ì™3Çs~ ŽztrX¸p6йÝRž(¼Q ±ª*—`t#Z§N<Ÿ‘þiGŸ}8çà»ï"=:qåÿ²ò=¼ü²‰"XK˜j§_?G@4s¦#6ò–ËoOPºvõ®e|2¢…ÄF<´$" ¹MÀ+8Êêåß/½pÞ$#ØEkuê[··Þê¤Sc}Šp-U/" "ÞÓprÄÏ?±¨}±k×LÀ®Æ{ï5²eþGïßìÙãlc`ÛË.(<’‰€ˆ€ˆ@, PpdóõüìŒZµjY ðøÚÔ©SýNÀ´l2÷ NŒ?f~ú úNš„v–ROb1÷_7µPD@D <L©Ö¨Q#(P ¼TJD@D@’À×_m™|–N&ò|2|à¤û׿€O>¸ž,fw0dpýõÎÌÞ#Gü[~×]ÀÝw;/£¿ýV/ŽýéhMD@ÜK€‚£Â… £~ýú!9b°s'pï½!‹D¼Ã+6]¾Ü9T‚£ˆê ð¦G}¨VÍnÈÐݺ-ÁîÝÅpÿý£¯2‚ÑI'U«Â&U#GFx ä_²dÉRK£ö‡÷8{èX¤`Á‚{×ãñÉtj|Àék§žzªïª–]Jàû¦p6в©Ëp†Mã©g/ee" " " ¶[,üÕ«W[ÚË›"&ÀGŒQ¶lÙ°{ùûïÀi§½z7:ÂÅ‹'Ÿ »Š„l×øõWà­·€ÇóJ´y30~<ÀGß|T®œðæª" " a`vNIKK z…FÏ=Ô«ôé´HT%8Š Ÿˆ€@… @¡Bý-çp‹:{¥R«gé²O?.¿XºÔÒÚX^›cuƼ,´¸œUEE@D@D 4Ï]˜ ŽÞ4¡Ñ`o1[îo3BÆ/^¼øGï¶X~>iO$wíÚ•^e™2e²Í±^X %`Z1_> Ûl©2¥Ò2HŒnD“à(.¦º " "’ÀB ó³aÃôíÛ7dß  ×ïleº±G,ØmBmß>`Ü8€Ü»uãC÷ðšC]q0m1ë¡Ð¨Jà˜c«K¥D@D@O`Û¶mž‰#Y¥ åäI¦T£H6Ál½‚£ZµÏC-HmYNµñ6S¢Í¦¸ýöÛ=¥ÞöÌ3OíÞ«w" " n$À”j–ozë3&:²Çˆé–f¢£k×®ólž&L°ëþ1ׯ¾új¥.IGïî懥U^õ+fÛg‹-<ëúŸˆ€ˆ€$;ñãwXæXŠ™öÉÞµ_D@D@B`t#ZV/f=ìö:¯¾ tî üö0jTâÅFŒ¶ÄT×^ËtN{¸ \r °h‘ó¢öË/ù27ô Ûÿúë¡÷ÇjEL‡cšððÃÀС@:Ž(êŒ3œEýûÃfüÿû_î´)V}S=" " ‘ð Žš5kô`>Ëä|ÉÆ´¢ Qâ¾û`im€ÚµƒÐ&ˆ!C€ á…^0m5œwÞy1ªYÕˆ€ˆ€ˆ@tì¶È±E‹½biÔÎ0áÑùÞm¶\ÉDN¶í£>üôÒ¥K—x÷…ûù·Å«;v¬…:ÇHJ™»ÿþûQ¼xñLÛµÁ¼ŽÊã/̳»ê›4pgCÕ*ˆÀÒ¥–C[pÚiü”‰€ˆ€ˆ@jøÆò†1R-S›ge<Lž X@büë_Y•tö]s `Z&4nìDÊþˆœ•`* ›‰¨eK§ŽÿX¼˜8Ñq{o Aû!H]S§Nõi[µj´“U«Ÿ~tWÔ9Õ¯9âŒQW¨ D@D@D éÓ4ן~ºÖ“FôQËqm#‚”Ô&È}¾#ÒaK«ÆPCMhÔÞÛ[¶Çt¸Á„G×›ðhŠ-bå~²O ¦îo&JÂæÍ›±víZ¬[·?ýô&Mš„ýû÷û<ºvÁ gÏžA÷i£; pVPÑ´(zpvÕk¨5î¼Lj•ˆ€ˆ@„˜veûözöòõ{Xþ3(ÂZT\D@D@ÜM`Á‚ظqcXQ†wX¦ÑO„Í  ¯OЭ[ýú+Pô2—Ÿ9Ó‰®Ä¹ŒLQ¢DFe§œ’±ì]b9Š‹èóæ9‚£&M¼{õ)" "ж[N³?þ;v´”f–Ó,FaîÎö¼´hN®SŠ€ˆ€ä wßíÜ/íÛw7 .Œë¯¿>Oô[H¾‚#,Y²d_­Zµz,Xp¢éŒºùvá¨ðÈ”ƒQlæÆ‘C6sä`Ù²eíÁ_ ì°§‘6lÀÁƒ} ¹Ü½{w{hOeIE€ŽÊ¥mµël3JO8!©Ú®ÆŠ€ˆ€ˆ@(Ÿ}Æ(Œ¥mvê†PE´]D@D@’žÀ´iÓ<}èÔ©S¶}yî9À2£Ûíl‹z PÜÃôföˆ "±Ñ'Ÿ7ß L±éM ymüxàÿþÏYcê´“À{ ùlÚ4ÈFmH9ï¼óöîÝ–6^çK`™ˆ€ˆ€Ä“#Î~÷Ý >—_~yÂD¶ñì£êH^~‚#vcÅŠ|ãvV½zõFÙr¦2,g¢£»wï¦s5lc˜¿{î¹Ç3(†} º†#•=¸ ­EC„*vMcÕ“ÀGýc%Kã”S…y„Љ€ˆ€ˆ@òxûí·Q¨P!tèÐ!¬ÆG­á¶Ûª6½E·Þ ‹0X6v?»ë.àÌ3(GEŠøíÒŠˆ€ˆ€xŒ7ÎéQômΠŠeË®P!pÖE@D@D ¹ôéà Î Œ$WãÕZ”'TLd½>bÑŽž4ÑÑ=`ÑŒz˜À(44©k×®6sñf4lØ0šªtl lùëjÜ€ÙÖ†Œk/ ðý÷üI´ݺéit \NuAD@D 9ö敎8#¶T©R™J2Í-#Ù†Ñ(SA6XÖu,]깈Ÿ‚¢aÀ €É“ºuý+8öX€.`Ö®]ë×z÷îi\;r6ÞÁ¢ñ«VÅvl ÖmxøçŸ@‘퉖óºmÛ¶ñ<•êˆ d)"2Ñѯ‹-ê}èÐ!*„Fš/ô ÕªUÃE]d'cĈE ÐEåùðyÛ6 <¶àwkWóæÍ]Ô:5ED@D@rF€ãÛÒ¥ýˆ–--ŒLD@D@RÀsÌ‘fv+C 1 €Ú·˜F;VöùçÀqǧŸXÖ8à¤iã ]Šx¾ï¿Ï,6ŠÕùUˆ€ˆ@ê˜0a‚ Xã²Ë.ËÔÉ÷Þá誫$6ÊGD@D@’ŽÀèÑ£Ál3¡îå’®Cj°ˆ€ˆ@Jáȯ“Ë–-[lnáÆ T³ˆGÌ›uéÒå Ç^ëÖ­ž¼Ò¥KÃëÉ£´¥àH–âþò¡œ ŽÖ”+‡ræ2Hv¿›ŠöàÁ"(Zt*WîœìÝQûE@D@D -–{üøñ8ùä“ѦM›Lûíù5žyÆ ~”©|¸ø8Àæ/~¿ú 6ÎÂî#ùó‹/^{M/‚Ãe©r" " þÆŽk)9Ëàì³Ïößak{÷uêfÚ¥ " " "˜~šûúõ;Œ‘#GÚ½TeK!šQ#E@D@Rš@X‚#_ñh­­O /^¼¸†}Ö÷ݯåÔ%°kP«øfÔØ¹[”N-u/´z&" yŒÀŒN‡ëÕ³xû2HA£Fž={pÛm·íÝ‚΋Ùwß  Z$G×P`Ó&G\ôÒKŽØè¾û€G,óºLD@D@"&0ß”«³gÏÆõ×_› ›éøK/.¹DãL&0Ú " "uöÞ{J•€*U>ÁŠ+ðÐCó’¢Cj¤ˆ€ˆ@JˆXp”Ò4Ô¹, Ô® ,8¶3¶ÚMý¶îɲ¬vŠ€ˆ€ˆ@²˜2e·5µ0N:ɦ ÉD@D@D Å´Ü¡ÿgÓc}øüóÏÚ;¦7»ÿ~X¤ˆ »£ÞX±"p÷ÝÓ¶íØ”,u•ª@D@D `t#Ú¥T…0‰ZC€Ñf×àäŒíÛW_…ÝËý×&…Ä 7Üàúv«" " y“@þ¼Ùíäíõ^‹ ¼qãFKýr0÷;qè -ZË<ƒæœª*HèØfíÿî»öÿßѺuƒôFUˆ€ˆ€ˆS¹$ð¾-àLš4 kÖ¬Aÿþý‘–zÎQ¼ÄF¾ÍáË_‰|‰hYD@’‡€[ƶ#–_f‚…Ï«Y³&Ú·oŸ<ÕR×pËG@K—/¼› 4nü‡¥¦þÊ“J­J•*®å§†‰€ˆ€äm¡Ÿ6æm.®êý Ëõ2fÌX ;؈ËgOj+T¨€víÚ¡OŸ>ö’´uüÛ¼mþ°0GSLtt]²¤T³Ð“˜cÞÖ¼Dü%ý[6ÿÅüIó&æñ°EVéæUÍŸ7aÚ«-wío;Ý?æusá´ì Äò¢y<˜-³zmöf˜?h~…y¬í€U8Ñ|¸9£žsRb<Ø­±zG™¿on);p‘¹ÌUÜ2¶¶¿{½z}†×_ Mšð“LD@D@rFÀ-c[`ëÿûßÿ¢H‘"ž´3Þ}»í7%Å?E‹z·èSD@D@2pãØÆ6­\¹÷Üsçù¨·Õ¼·ûòKàŒ3¼[ô)" " ¡ ¸qŒck Ø3ô§žFŒáéÀ€|1 wP„#w^O«V¯^mùÆ/Áu×]‡o¿ý6]lĜͳiÓ&¼÷Þ{¸øâ‹qÓM7Yhz‹MO+[w׫‡ÿ+\ Ä( ÄÖ86x§Õ͇ ]̯‰ãy¼U/´…×¼+qþ¤À%Ö¶É*ìjþˆù'æç˜s[,ÙŠ(0jeþ±9!›ÇÛ(8ã“ì³ú†šS,suŒëUålÆ«æ½Ì÷†*”ƒí+ì˜ëÌ3c¾Áü*óaæ±2 ‹§Íë˜SÈ´Èügó“Í4…ñûeqžy-óGÍ)ÐâwYænÛòÛ/¡|ù¨LûM›6u '5DD@D y¸mló%÷믿bæÌ™ž{ÆòåË{vñ…¬ÝB¢S''½™oy-‹€ˆ€ˆ ¸yl7ÎyÀsÙe—ù]¬·ßºuLg+Ü<ÆýôðÖ[@Ïž@ùò m‚äë8þøãqòÉ|ˆ.w°×l27ؼy3®ºê*üò CÍdoS§Nõ„Uäqñ´9sæXˆ&Y†âûüS­dmóÂ>"ü‚Ì8×Çü7sžãó—Íãi×XåýÌ¿‰ñI>µú|µd÷Ø:3ÚmŒáyfZ] ’Åkr“9#è¬0·¶1¶¬µºìÁ(Ưl>Íœ‚;Íceät«¹óìÉ©u‹}0ŠÎUæ˜ÇÊ~°Šî6/c~s¬*õ©‡×ý/Ÿu.Úìxn²}v7ße »Ú*m~ªù4ó?Í›˜4g£1FºË¼†ù¿Ííž0_m>Éœ}èlNZNmÈŠ Í»šó:ó»Æ:)l*f.s·ŽmóæÍCÕªUQ&7rɸâJ¨" " ±"àÖ±ÍÛ¿çž{γxë­ü‘ìØw~h?ì·S‰Þ­ú‡€›Ç¶ýû÷ãmSµ°Èë|>é5ŠiyÄ×tHÞ"ú¸yŒãåù·=?/Pxè¡=ž÷}÷†®+'" " ®& Á‘ /Ͼ}ûpÍ5×`;©wŒ!ðO;í4<ðÀx÷Ýw1zôhOHü>OˆW¬X{ï½×ýÈ{\,?ÿþûoO›š7§Ú%vœÕÁo …:ëcPŸo7ÚÊgæŒÚò«ù±æ·›ÿa c$ 1|#³¼fëǘÛlaOTûˆÚ(Ì °„"¯5³~5Î7ßïÝå'#m5kþæ7˜SØôƒùUæìo46Þf»§˜÷3ŸmÞÑü~óâæ±°÷¬’Fæ#Ìßõ©°œ-3ê ?ÿcm_¬ ±ý<ÏBó‹<[2þÇóPP“ûÂê`~¶9¯¿¯ñßË+æ·˜Sv†ù6óH,˜Pm¨UÀú¦™³_Õ̧›S€Ä}$QÄ©]ekþ”9G¯š/7ç¿ÒæçšO3¯dÎë®í´‚ñß4Ÿ/²½\ÞbNqÓóOÌùo‡Ì|í°­Pˆ(ËunÛ1pÁ‚Šn”ëßPD@’Ÿ€[Ç6/YFÄ8q":t耖-[z63,?5HMðý WÊD@D@DÀ‡€ÛǶɓ'ãŸþA`t#Fƒ°Û:0ãL¹Hž/øô]‹" " ©MÀícÜGÙ#y{&o Oðì³7`þüùxüñÇÑ®]»Ô¾0ꈀˆ@ÒHKú¤`Þ²»äE‹–ñ‚ âµ×^CëÖ A“aü¡qÑEáÊ+¯L'1ï,gú\xá…c´T²dIüüóÏ(Z´hÎk¤8¢ÔÑÃ)àCîó̯0§Ð"Ÿy´öˆUÀh-g™¿`Îo9/…FŒ±MÛ;â&ó—Ì›SèB£€jŒyAócÌ£µw¬‚{Í©ïzÔ§²Kmùwó§Ío6Ù0ßœËeÌG™Ûr?cû§šW1ä;F˧æöcß#jyÆ>}ßÝ@ûÞ6<`Îïà׿ÜDbö€ ¬ãzó;‚Èö0çwl¨ùiæü·“յݶÿ.ó)æãl6/kîµ¶ÞŸO²dù>æcÌɂ߅¢æ¾¶×Væ™o3ïâ»Ã–š_`~¥ùYæÁØóÜüsWÐ<\c}ÞwÕlù*ó3Í{™6ÏÊxmìE›'µûÚ¯¶ò_kê66VknÛÛTX†ä/^¼x¬»¬úD@D@Rœ€[Ç6/ö—^z |¨înÄÈ=dóšÙO)û-e·™2ð#àö±mìØ±Èoy±/fnУæÝèÎ;½[õ)" " þÜ<Æ:dó¿mx±b@½zc-ÒÑ8÷Üs1pà@ÿNhMD@D@\H ¿ Û”§›Ä‰£FQ1‘aT1м{«W¯Ž§8MÕÇøÃ)–––†6mÚø…,ŽèÛIÑÏì€Bm4ØFqÈæ„²­FäM±û2×¼»y(;b;ìG5¾ UÀ¶0çwe€ù±æ­Ì›¯6ç÷h¡y?ó`Âö¯ŒyV¶ÝvÎ0'w¶‘w.7g–™‡c'[¡Ñæ+Í;˜ûÇ“͇˜÷5¯o¾ßÜ×®¶• æüŽñº„2¶‘â:Šd:šóràõýÃÜ׎±•wÍyýY?HáXQ+D1׿™_kîkSm… ~G®24^Ï7ÍÏ6vM¼å zŽ~.°ÏÍÉ’ÿÎÿÿkÎrkÌ_3§ °°yvv©¨iÎï óµm¶ò?{ ·ÇÞÂÉbJÀÍc[‹SÜ«W/œ~úé1í³*HmnÛHþÀxá…P³fMÏ8ÇÐüÙí¾þÚ‚M–Níë£Þ‰€ˆ€DNÀícÛ¶mÛðñÇ£S§N¨V­š‰jmžÔ{TaÏ*þ°ç ÌZÖwrUät„ˆ€ˆ@Špû÷ê«N¤¾Ë.Û`YNú¡V­Zxýõב/_VÕSôb©[" " IG@‚#—]²>ø }ï5¾íÑ£‡w5è'ÅH'œpBú¾¹sçbõj*â`|¹OaСë¦P¤9E Ž}ÆÖ™ßgþKÀ¾HV)D¡ØäXóOÌ)„ðµpľ嗙†ébsûñçPPTCAF´vÄ*øÁ|l@Eü-y—y‰€í\-`>Ñœ‚•Ûͧ™ggä\Þü\óç³+|t?ûÇ~R ±ìè6ß¿lÅ^X`ïF[fùÊæ÷›óš¾cÎsge«lçKæ½Í(ÈïÍIæ|1ÒÕœí/dþ/óoÌ7š¿h^Ñ<\³SÍ£öIAT]sÖßÁœB™Ùæ½Ì_3_oþ¾y¸vµ|Ý|­9…K§™³ÿÕÍ)ºdþ¶9…@ü7åkŒVÎwCËØ>þ{œoκÉ×w‚y Í± +Ì_1gÙp-Í Ž1è¨ÛGºgK=Í1çµãw9Fáë[j^,H…gÙ6{èù»dw–›ÛÞÍo2¿0 ä©¶þ·Žª<4`‡V£%àú±-Úêx¶1ÂRa—À/¿Ü†_t^È~ö`Y²e" " "”€ÛǶ‘#ùe%ÞxãTð±'£ö=iÏvlÞ%æÌ±ÛyÝϽ®Ú(" "`I$\üÞéÔ˜)´F±|ù\<û쳞L#ºn" " ",(ñ¹ˆÀÏ?ÿœÞ†KìØ±cúzV ¾ŽX.n‚# Yî2gÔšÖæ4ÏΪ[Š.X>˜Qó„ù"ó[ƒðÙFAÊæB„ºG·7ò)jq´í`$˜ÃA PlÒÕœ¢„Þæ¯˜—2hþµ9ÏKaBvFÁÊ æ½Ìyì9æõÌ1of~¡ùËæeÍ)úÒ¼°y$ƾŽ3§˜«¾ycsŠ(BÙmn6lØ0PÁï‰ÎD=÷E*r öb¢Õsùpóæ±°öV‰½ñ¤áò­/ÍV(ÜúÜüsö3Z;Ë*àµå?¹æóÌÇšóZu6ç[±,­¯íÝj¾ÍœìGš_o~’y ØÅ6…c=mßßó‚ûØ•¶ü…9ëïg( ²MIe­µU’ªÅjl6\?¶eÓ~ív'FÜÍi`²” pÇwÀ÷oEJtJHi¾ßW7Þ·ýš6]`3c [J5 ìù‘݆ð>DæjLóºyófW·Q ŸÀý÷ßo) ùA&ÉAÀýcÛèÔi±m6GÌž¹M›f(ï‚wÉÁ7¯¶òÒK/µèËój÷S®ßO<ñ„ý®´–2H2nãJ” Øh8~ýõfôíÛ×¢ÔöO2ºy³¹¼Nóæñ¥’,Ù 0:4ÿíÉD@rN€¯ñe.!°lÙ2lÙ²%½5Í›7·ðÀåÒ׳ZhÖ¬™Í`-Š={œÜVK—.ͪxÎ÷±Cmö'ÕÕö9Èü]ó1æÞ|Š+æ›ï3§pÃkŽ !>o³í”¼jÞÉœ‚&Šh|…u1çûÅòæåÄ~µƒ>6ç9~¨`“­SÂóœmÞݼ¶y¤Æö 0̜砘ˆý9ϼ¡9E!'›S(c1§Šu61çµàùÌøªT©’³ËÿS´ëJƒÔÙÖ¶Ñãm¾ßßœ‹éVU&ÉB )ƶd©vúX³f Ž9â·M+ÉK`ãÆé¿c“·jy^! cÛoÔ3Ÿ¾´È—cÆiºóOНçÚµkqˆSœe)Aà/SDH—2Ot"ƶV­›ˆ/O\Ž”êä† pðàÁ”êS^î 'Aîܹ3/#Pß“€ÛÇ8þ›2d6lˆ—_æ uY2X·n¥zåKPY²àï¾w“‰€䜀;æœ]ÌœÃø¿>Ö AŸµ¬ ,ˆš5kâÏ?ÿôŸƒÎ;{êËoO¨[¶léW·ïJõ¾ÕÑç‹>¨8½"6–݈7bC¹ XWaþ¼Ó@ù–Ïn¹z×ê8aî ØuÌ.üðÜØV‚!“|¬™-sÓÇGÝgWD‹Œ,D¿/¢£’®ðìÙ³±páBüöÛoI×v583Þx <…  a•¹ˆ¶DH€‘áþøãô£(ØäŒ­À¿©é´·ŒmsçΣÿyÇ6v‚cÇ8Yr`t£AöF=Ma;’ó´ši8“Ï“6`ŸVsN€‘À6mbøNx"H(/õ{ÎÛ˜ŒGºel[¼x1Ìwlcä[NFñÚ¿ÿí]Òg2àïÒGyĽ8Ú«6fM`þüùضm¦NeÞvY¬p69#¦ÐxÌû7YôÜ2¶ñÚîÚµËolkܸ1Šñ)}UCîàwë©§žB æ ’%=>_f´˜Y³f%}_ÜÔÞ³ñÞ¶ÿ~E‘ŠñÅqË7sæLð÷á—_~éé!ÅE‘ˆ1U%F§}þùçQ¶lÙ(kÒá‰&Àßž;vìÀwޙ覤ÔùùŽmÅŠž>1Š×e©K@‚#][>ˆòµHGâ"þª]»¶o•a-·jÕ ¿ÿþ;*W®ì)Ï—±­[·ÎòØïz|—ii”Ɖö_Nlm†bæ1æ“EC€éÔŽ9æT¬X1šjt¬K*TM›6õ{‘ä’¦%m3øbÇwöÈÊ•+-"€…Å„€[ƶFã[ÕªUÓûűM‚£tI·@¡EcP$Ý¥ Ú`Š<«T©"±gP:9ßÈ¿y¤ÐøEbÚœ³ô=Ò-cïõøw°zõêéÍkÑ¢…~'¦ÓH¾N*à‹uþæ—%?råÊy^@è%Dl¯%Gtïåôï%6|Ý2¶U¨PÁ3¶1Š»×ø D‚#/äûä3ÉzõêIL›|—.h‹ù|¹X±bzΔNÎ7òž÷Ã4¦hRœ³ v¤[Ƹ:xÆ3ïsg>f5Yr –¿W|ß+$gOÔjþÝ彟§ÈbG€þ¶§q’E]²Ô% Á‘‹®màŸH_–Tn‡ÛUÎõ%îq*'"^xaüO¢3ˆ@ ¸elkÛ¶-ÆŽÞ©ªDÐßÃD__ò.·ŒmÇwÆŸw/D ö\c[ ^TuI’„€[Æ6Š¥'Nœ˜$ÔÔÌphl ‡’ʈ€Ä“€[Ƹ~ýú.T# <".º¢?|"pšvçÎ.êš"" " hlË‹W]}Ô& ±-µ¯¯z'" y‘€Æ¶¼xÕÕgÈ4Æåë¬^Š€ˆ€$Ž€G‰cŸéÌùòåóÛiXèÀ¼õü*׊ˆ€ˆ€äm¹Y§ÈUÛr·N&" " 4¶ådBD@D !4Æ%»N*" "‡Hp䢋íÍeèmR¤ù ™gÒ×¼¹`}·iYD@D@r“€Æ¶Ü¤­s‰€ˆ€äm¹AYçÈMÛr“¶Î%" "›4Æå&mKD@D /àÈEW½|ùò~­‰Tp´wï^¿ãË–-ë·®ÈmÛr›¸Î'" "oÛâMXõ‹€ˆ€ä6m¹M\çÈ-ãr‹´Î#" "W Hpä¢+íŸM›6ùõF‚#?ZHm €®SŠ€ˆ€Ä•€Æ¶¸âUå" "   ±-ÐuJ\! 1.W0ë$" " y˜€G.ºø?|Ö¯_QëÖ­[—^>-- %K–L_ׂˆ€ˆ€$‚€Æ¶DP×9E@D@âI@c[<éªnDÐØ–ê:§ˆ€ˆ@nЗ”u¼L@‚#]ýŠ+úµæ×_õ[Ïj…éÔ|J-[¶D¾|ù²:DûD@D@D î4¶Å±N " "Ë4¶å2pND@D î4¶Å±N " " ã^§È3$8rÑ¥nР|ü,Z´»ví «…':t(½l—.]Ò—µ " " ‰" ±-Qäu^xÐØ/²ªWD@D Q4¶%мÎ+" "oãâMXõ‹€ˆ€äu¹è?~œsÎ9é-:|ø0fΜ™¾žÕ´iÓüvwîÜÙo]+" " "ÛA]çˆ'mñ¤«ºE@D@A@c["¨ëœ" " ¹A@c\nPÖ9D@D@ò2 Ž\võ{öìé×¢Q£Fù­[Ùºu+Þ~ûíô]µjÕBíÚµÓ×µ " " ‰$ ±-‘ôunxÐØªªSD@D ‘4¶%’¾Î-" "OãâIWu‹€ˆ€äu¹ìаaCÔ¯_?½UsçÎÅøñãÓ×vî܉›nº »wïNßuá…¦/kAD@D@M@c[¢¯€Î/" "kÛbMTõ‰€ˆ€$š€Æ¶D__D@D ^4ÆÅ‹¬ê @4|žß<š:tlfŋǔ)SÒw̘1¥J•B“&MÀð^[·núõë‡9sæx7¡^½z2d ˆêҦקˆm± ¨:D@D@ÜD@c››®†Ú"" " ÛbAQuˆ€ˆ€¸‘€Æ87^µID@D <“/šN9rä ;þ²hêбÁ 8}ô‘ßÎêÕ«£yóæ(R¤fÍš…U«VùíOKKÃ믿Ž6mÚøm׊ˆ€ˆ€¸€Æ67\µAD@D –4¶Å’¦êpmn¸ jƒˆ€ˆ@<hŒ‹UÕ)" "Ç T—àȥ߀]»váöÛoÇôéÓÃjaÑ¢EñüóÏ£]»va•W!ÈmÛr›¸Î'" "oÛâMXõ‹€ˆ€ä6m¹M\çÈ-ãr‹´Î#" "‡T*ï–RªÅï«R¨P!œsÎ9žjóçÏÇBžìÄOÄÓO?¶mÛ†,£" " "hÛ}t~XÐØk¢ªOD@D Ñ4¶%ú èü" " ñ" 1.^dU¯ˆ€ˆ@& ”jÉpñwïÞÉ“'cîܹX¿~=¸^µjUÔ¨Q§vš4i’ ÝPE@D@D €Æ¶tZHÛRäBª" " é4¶¥£Ð‚ˆ€ˆ@ŠÐ—bTÝH¥TKyWD@D@D@D@D@D@D@D@D@D@D@D@D@D@D@D@’@õüIØh5YD@D@D@D@D@D@D@D@D@D@D@D@D@D@D@D@D A$8JxVD@D@D@D@D@D@D@D@D@D@D@D@D@D@D@D@’‘€GÉxÕÔfH Ž^§d$ ÁQ2^5µYD@D@D@D@D@D@D@D@D@D@D@D@D@D@D@D@D@‚£×iE@D@D@D@D@D@D@D@D@D@D@D@D@D@D@D@D  ˆ¦Ñƒ>ÏŽoM:VR‰Àþýû±qãF,_¾ûöíCñâÅ‘?ìt}¬Ÿu¯Y³E‹EáÂ…c†oï޽زe Š)Ó6³ñ¬;fr±¢xOâÍ\×3¿,:•¸€@¼ÿf%ëØÆK£¿‡™¿ ñþ¾Ä“y<ëÎLJ[D@I Þ«â9¶‘[<ÿ^ųîD^óhÎïïK<™Ç³îh˜êX؈÷ß*m±¿f‰¬1Þß—xŽ?ñ¬;‘×DçN Þ¯xÖxŽqñü›Ϻƒ_ wo÷w%Þ¼ã]¿»¯žZ—äžIKò¨ù"p›7oƇ~ˆO>ùóçÏ÷kOÁ‚Q«V-Ô©SÝ»wG·nÝüö‡³²cÇŒ=ÚsŽuëÖáÈ‘#釕-[µk×F‡pÝu×!--²Ò3fÌÀ˜1c°xñbPŠçË—*T@»víЧO´nÝ:ý|‘,ijîHÚNÙéÓ§cÒ¤IáÍT¦nݺ¸å–[2mÜïï ÏOæñ¬;•ÖE@O Þ³’ulã•I¦¿‡¹1¾‘I¼¿/ñdϺÉF&"àñþ[ϱãù÷*žuÇú ±-{¢Ét=³ïJˆ€dE@c[h:Éö·07Æ·x_âÉ<žu‡þiˆ@¢ÄûïûÏû·xþÍŠgݱ¾ÞÛ²'šL×3ûÞ¨D^&/šÎ›ðá ;þ²hêб"Ì>ýôS<øàƒØ¾}{XÝ èˆåK—.Vù·Þz O?ý4¶mÛ–mù-Z`ذa¨Q£F¶eW¯^»ï¾¿üòK¶eO;í4 :%J”ȶ, ijî°ƒBO>ù$^}õÕ ´iÓãÆËòØxOâÉ<žug M;E@F Þ³’qlãÅHÆ¿‡ñßÈ%žß—x2gÝä"pxþ­bOã5¶±îxþ½úöîNjjíãøCDEŠ€WQPP°D± Ø êU® ½°€+*VÄ^±ôÚÅ^À†HAPEº¸ïüÛ8™™3;åw>ŸÙI=I¾ÉæL’'ç¸Ì[ëî"Q¶•­šû³ì­a ”'@Ù_(_Ï…®Ë7—Ç‹Ks—yÇ?‚Š•-àò|åo›«ë7—ç,—yû.™þ¦l+[4÷gÙ[ìG¤( š®½öÚ Ï­Úƒ4oëÖ­ÎûÌ3ÏØÀãN£Zˆ¢k:ò'ªS§Ž=ÿüó^­Jþ°ØoE‡}ôÑ^³l±ãÊêW-M=ö˜WóQYÓh¸Ë¼-7Ýq}ûöµ7ß Ë@IDAT|3¥lÊ 8r}œ¸4w™wJØÌ„Î\Ÿ³ò±lz¾ž]–orqy¼¸4w™·\H [.ÏUÚRWe›òvy¾r™·ÖÝU¢l‹/›¯û3þÖ0Ê l‹/”ÏçB—å›ËãÅ¥¹Ë¼ãA EÊpy¾ò·ÍÕõ›Ës–˼}ß”mñUóuÆß†"à pÄ€@*&L°ã?Þþúë¯`ví¼óÎÖ±cGSmCË—/·3fØ‹/¾hŸ|òI0:¶ß~{¯VÅKo¿ý¶©0þûᅢÑ]»vµ=zX—.]l“M6±éÓ§Û§Ÿ~j·Ür‹©mO?uëÖÍî¼óN¿7ô½råJ;üðÃmêÔ©ÁðZµjÙN;íä­{‡lñâÅÞúŽ9Ò«VÒŸp×]wµ{ï½×krÍýí2ïèå¸èVÍSòTªW¯žÕ®];éÅh_ßvÛmq§w}œ¸4w™w\,"€@¥ ¸>gåcÙ¦’ÏçCWå›\\/.Í]æ-ä–€Ës•¶ÔUÙ¦¼]ž¯\æ­uw™(ÛJëæóþ,½5 Aò(ÛâßKÍ÷s¡«òÍåñâÒÜeÞåý1*GÀåùÊß"W×o.ÏY.óö]\}S¶•–ÍçýYzk‚@ Ð,èJ¥CMªE>$ŠNਣŽ*iÓ¦Mð‰4;VòÓO?•鉚.iÛ¶m0½æ5jTÜé#NI$¸'4í\P²fÍš¸ÓOœ8±$Œšþ³Ï>‹;í#<šn«­¶*‰4«wÚH•~%Ú®èí|ê©§âN«.ó.s¡ ê*iß¾}°ï¿ÿ~r]›…ËãDKpiî2dTÀå9+_Ë6çëùÐeù&—Ç‹Ks—yË…„¹%àò\å²l“¢Ëó•˼]”mñuóuÆß†"€@y”mñ…òù\è²|sy¼¸4w™wü#ˆ¡ PÙ.ÏWÚ6—×o.ÏY.óv¹Ï)ÛâëæëþŒ¿5 E hZ5•@#æA ˜fÍše_|ñE@°ÑF™ªzlܸq0,¶Cµ ýûßÿ 6lX¨ßï=z´-X°Àïµý÷ßß®»î:«Z5þ¿k$hÈN<ñÄ`zu¼ñÆ¡~õ¬ZµÊFŒ>dÈÛn»íBÃüžfÍšÙ7Þè÷zßjÛ6^r™w¼åer˜¬#?6ƒ,[´ht§Óáú8qiî2ïtL™Ü ¸>gåcÙ&í|>º*ßäâòxqiî2o¹@ ·\ž«´¥®Ê6åíò|å2o­»ËDÙVZ7Ÿ÷gé­a”'@ÙVx÷%µÏ]•o.—å˼Ëûc<TŽ€Ëó•¿E®®ß\ž³\æí»¸ú¦l+-›Ïû³ôÖ0°@ü†ð4ô!€@”À /¼Õgvúé§Û¦›n¯çÜsÏ55_æ§yóæÙ¯¿þê÷zß‘ZŒìž{î †U¯^Ý.¹ä«V­Z0,^G¯^½BI“'O.5Ù˜1cláÂ…Áp5½Ö³gÏ ?^‡‚‘vØa‡`Ô7ß|c‘š‚~¿ÃeÞþ2\}Ïž=;ÈZûGÍÕe"¹º*ßäâòxqiî2o¹@ ·\ž«\–mRty¾r™·ë#€²­°®Å]/ä@! P¶Þ}I§®Ê7—Ç‹Ëß.ó.ÄóÛ„@!¸<_ÉÇåõ›Ës–˼]7”m¥…óy–Þ†  à(ìAå ÄótïÞ½Üy4‚YZµjš66/Õœ4wîÜ`5jÔ(è/«Cµ, <ØÎ9çï£ùbS¤©°Ð ½÷Þ;Ô_VÏÎ;ï5vìØP¿z\æ]jaýÃgóÍ7·*Uâ·_ÑÅÆîÛL'Z—æ.ó®¨#Ó#€@v\ž³òµl“|>Ÿ]•orqy¼¸4w™·\H [.ÏU.Ë6)º<_¹ÌÛõ@ÙVX×â®òG (ÛÌ í¾¤ŽSWå›ËãÅåï —yâymB \ž¯äãòúÍå9ËeÞ®ʶÒÂù¼?Ko C pö r~úé§`š $äÏмys¿ÓûŽ.Ò€ñãLJÆ}ôÑ¡þD=Gq„õíÛ×ûôîݻԤŸ}öY0LA5»ï¾{П¨#º†#MïÂÞeÞ‰Ö-ãæÌ™dÓ²eË ;Ý—ljÖÍ¥¹Ë¼Óue~p#àòœ•¯e›¤óù|èª|“‹ËãÅ¥¹Ë¼åBBÜpy®rY¶IÑåùÊeޮʶÒGù¼?]/ä@! P¶Þ}I§®Ê7—Ç‹ËòÇeÞ…x^`›(—ç+ù¸¼~syÎr™·ëㆲ­´p>ïÏÒ[ÃÂ…=èC \è?7.wúè ~üñÇè^‹ @ŠþáS¯^=ëÚµkhúT{fΜi‹- fßf›mlà 7 úu´oßÞj×®L2cÆŒ [.ó-ÈQOt¤u‹-2¶—ljKs—yg —Œ@ ã.ÏYùX¶ 8ßχ®Ê7Ù¸:^\š»Ì[&$È=Wç*m©«²My»<_¹Ì[ëî:Q¶Öµ¸ëã…ü(DÊ6³B»/©ãÔUùæêxqù{ÂeÞ…xN`›(Wç+ßÇÕõ›Ës–˼}—ß”maÝ|ߟ᭡ÒÕKb$¸ÿþû­¤¤Ä›dÝu×M4ihÜŠ+J5A²å–[Óüý÷ß6a„ ³Í6 ºÕ1mÚ47nœÍŸ?ß–,Yb ŽiݺµµmÛÖ6ÝtÓд±=_ýuhP›6mBý‰zjÔ¨aZ—)S¦x“­^½Úþøã[ýõ½~—y'Z¯L‹ýáó×_y´½úL:ÕêÖ­ë9ËmÛm·-Õ4^¼uquœhY.Í]æωa ®ÎYùZ¶i¯äûùÐUù&WÇ‹Ks—yË„„¹'àê\å²l“¢Ëó•˼³qP¶Öµx6Ž–@¡ P¶™Ú}I£®Ê7WÇ‹Ëß.ó.´óÛƒ@! ¸:_ÉÈåõ›Ës–˼³qìP¶ýó UÞù¾?³q̰Œü à(¿÷k_ ÑABYü7Þh+W® fQíF~ÐŽúDþÍš5ó:'Mšdƒ ²‰'ú£J}ï¹çžv饗–x]»‘f®_¿~©< PmKÑIùùëî2ïèeºêŽ®ÚQÛÒ«W//È(vy~ø¡7HÍÑ©©»óÏ?ßÖ[o½ØÉ‚~WljàÒÜeÞ s®ÎYùZ¶iåûùÐUù&WÇ‹Ks—yË„„¹'àê\å²l“¢Ëó•˼³qP¶­=> åZ<Ç Ë@ Ð(ÛÖîQ•g…t.tU¾¹:^\þžp™w¡Ø IÀÕùJF.¯ß\ž³\æc‡²íŸß*òÎ÷ý™c†eä·Mªå÷þcíóDàÕW_µÇ{,´¶ýû÷õ«Ö è¤€£gžyÆ?üð„ÁFšçí·ß¶=zØí·ßEÐýûï¿Ýê¨hÀ‘ïg]8ºÌÛ_ž«ï… Úòå˃쯽öÚ¸ÁFÁ‘Õn5räHÏû­·ÞŠ•vw2ljâÒÜeÞi‘ä”@2ç¬|-ÛÏçÃ\+ßä™ÌñâÒÜeÞÚ>†@2ç*—e›]ž¯\æíú l[+\(×â®òG(Ûþ±ˆ×•èžg¼é3=,×Ê·dŽ—¿'\æé}G~ P¹Éœ¯´†.¯ß\ž³\æízÏQ¶•0Êçýéúx!ÿ †£ÂØlEŽ ¨ºÆáÇ۰aÃBkxðÁ[·nÝBÃb œéÓ§{M–(?m´ÑF^3j¿þú«×f¹ªö“ºï¸ãkܸ±yä‘þ`ï;6ïØ‹BÇé‰>ÑMÎØiãd;}tÞ¡ ôDGYGg¯ZŒÔ|ZÇŽ½à,í‹o¾ùÆ,XLöóÏ?[¿~ýìÙgŸµvíÚÃSé¨Èq¢üÙŸ©(3dJ "ç¬ØóU¾”m²Š]÷Øòª<쯎ܱ|“Q:ÇK¬a:æù¼?ËÛnÆ#€@ú霫2Y¶iK\ž¯\æþ^HœC®\»i-Ó9^(ÛïgÆ"€@æÒ9WQ¶en?”—S®”oé/”måíeÆ#€@&*r¾Òrc¯2YÆÅæÍùp힦l+?à(“ÇJ&ÿ¿È T8JUŽù(G`òäÉ6pà@/P%zÒ¶mÛz㇩;6ÒZµùi¯½ö²K.¹$ÔdÚ_ýåÕ|¤¦½æÎëOjC† ±wÜÑÔd›ŸbøT´†£Ø¦ÃþüóO?ëR?Ø2™w°GÑíÈú‹8õÔSí´ÓN³ºuëúƒ¼oy?òÈ#^-RË–-ó†)Èë¼óγçŸÞjÕªš>ÙžŠ'Ê—ý™¬.Ó!€@¦*zÎÊײMn.ϵ™Þ/±ùåBù¦uªèñâÒÜeÞ±þô#€@~ Tô\å²l“œËó•˼]ïuʶµÂ…r-îúx!Š]€²-ù# Ñ=ÏäsI}Ê\(ß*z¼¸ü=á2ïÔ÷s"€@®Tô|¥õvyýæòœå2o×û“²Í,úºMÞù¼?]/ä_4©Vû‘­È!ý€¹æškìÐC-l´ÿþûÛSO=´3½Ú±Ž?nÀ€v÷Ýw‡‚4®zõêÖ¡C¯Ùµ­·ÞÚŸÜk"LÁIÑI5öD§š5kF÷–Û]“’&ŽŽ¾u™w¹+–æÑ?|ªV­jW^y¥)€+6ØH‹‘÷É'ŸlO>ù¤Õ¨Q#XòŒ3ì–[n ú“íHõ8Qþ.Í]æ¬ Ó!€@î ¤zÎÊײM{ ŸÏ‡•Y¾É.ÕãÅ¥¹Ë¼µÍ$È?TÏU.Ë6)º<_¹ÌÛõ@Ù¶V¸P®Å]/ä@± P¶™eòžg6Ž£Ê,ßR=^\þžp™w6ö'Ë@7©ž¯´6.¯ß\ž³\æíf/ý“+e[øªdòyþ³géB lŽÊ¶a X³f9ÒºwïîÕ„£~?m°Ávýõ×{)µk×ö‡¾W­ZêWO—.]줓N*5;wM;}úô ?ÝÂláÂ…A^êˆ.,]æZhõ(l‹-¶­Ñ¤I“Bý±=™:N”¯Ks—yǚй+©sV¾–mÚ3Åx>L¥|“U¦Ž—æ.ó– r_ Sç*—e›]ž¯\æ«Ge[Ù{&Ñu~Ùs1rI€²Ím¹™Kû:v]R)ß2u¼¸ü=á2ïXCú@ w2u¾Òº¼~syÎr™w®îùB-Ûä]Œû3W3ÖË5¹q%×"øóÏ?mÀ€ÛœV‹-ìâ‹/¶Ýwß½B ±5 ©æx?†ÊÊ´yóæ¡Qßÿ}Ð[˜ÍŸ??—LǼyó‚ɪW¯  r™w°ÐìPÀ‘_£”V/öf­¿Ê™>N”¯Ks—yû&|#€@î dúœ•¯e›öP±ž“-ßd”éãÅ¥¹Ë¼eABÜÈô¹ÊeÙ&E—ç+—yçî`ÞË"É\»i2}¼¸4w™w.ïOÖ 2®¢l[{TÅÞóÌõc-Ùk7ʶ\ß“¬ø™>_)_—eœËßã.óö½sñ»Ë69ëþÌÅcŒur#@À‘Wr-‹.º(l¤‹Ò³Î:Ëúôéc5kÖ¬°@ëÖ­Có¨Y´Š¤’’’Ðä XòSt·†M˜0ÁUî·šS‹PêСC¨™7—y—»r•8Á²eËBKß|óÍCý~O¦åëÒÜeÞ¾ ß »™>gåkÙ¦=T¬çÃdË7eúxqiî2oY@ w2}®rY¶IÑåùÊeÞ¹{˜Q¶•Þ;å]ç—žƒ! K”mU‚ÝQ¬e›’-ß2}¼¸4w™wpÐÐ9+éó•6Ôåõ›Ës–˼söˆ¬X!–mò.Öý™ËÇë–YŽ2ëInE"ðÈ#Øë¯¿lmƒ løðá¦`œT“òØd“M‚àž_~ùÅþøãRØeå]£‘¦Q$°ŸÔ4› 4¿ž©S§ÚÒ¥K­N:þ$e~+8iÍš5Áø½÷Þ;èV‡Ë¼C ÊpÏG}dÑÍÎí·ß~Ö¨Q£¤—=¯fjÕªU©y]'ZˆKs—y—b䔀‹sV¾–mÚ1ùz>ÌFù&Ç‹Ks—y˃„¹)àâ\å²l“¢Ëó•˼]”mku åZÜå±BÞƒe[aÜ—Ô±šòÍÅñâò÷„˼‹áüÀ6"Ï.ÎWòpyýæòœå2o—Ç e›Yìu›¼óuº–mÚ9ùz>t]¾ÉÆÕñâÒÜeÞ2!!€@î ¸:WiK]•mÊÛåùÊeÞZwW‰²m­l¡\‹»:NÈb l3+¤s¡ëòÍÕñâò÷„˼‹áÁ6"¯®ÎW¾‡«ë7—ç,—yû..¾)ÛJÿV‘s¾îOÇy¦G…¹_Ù*‡£G¶Õ«WK2dˆm³Í6A:½zõ Í~Ë-·XlSi¡ þ¿çË/¿´O?ý4µå–[Zݺuƒ~u|ðÁ¡~I•—/^lÏ<óL0™š kÑ¢EÐïw¸ÌÛ_F¦¿»víÊòå—_õ'ê¹ýöÛCÇ@ìÍÍëò8Qþ.Í]æ­u'!€@î ¸tU¾É#Ç‹Ks—yˇ„¹!s•˲MŠ.ÏW.óvuP¶¶Bºwuœ/…,@ÙVx÷%u¼º*ß²q¼¸ü=á2ïB>O°mä£@6ÎWrqyýæòœå2oWÇ e[üg¨òÎÇýéê8!ß‚hFÀQAíO6Ƶ€"­Ï?ÿüŒ-æî»ï¶½öÚ«T~C‡µØ&ÏêÔ©ãEÀ¶mÛÖV®\i“&M²éÓ§‡šöjР5Ê6Ùd“RyúLóâ‹/ú½Þw³fͼfájÕªeŸþ¹Í™3'4^ÁH?ü°uêÔ)4<¶ÇeÞ±ËÊTÿ€¼@ªèüt#w‹-¶°­·ÞÚd2eÊïëï¿ÿ=™µoßÞ«%*68)[ljVÆ¥¹Ë¼Cô €@¥ d뜕¯e›vN>ž]”o²ÈÖñâÒÜeÞ2"!€@å dë\å²l“¢Ëó•˼]”meËæãþ,{kƒñ(Û ó¾¤öµ‹ò-[Ç‹ËòÇeÞñþdž•#­ó•¶Îåõ›Ës–˼]íuʶ²eóq–½5ŒAÀhöO•&ˆ €@¹³gÏ.wšLL  ¦-·ÜÒ.»ì2[²d‰—åÒ¥KmüøñÞ'Þ2:wîìý`jܸq¼ÑÁ°+¯¼Ò83nܸ`ØÜ¹sMŸxIµ*ÝqÇåi^—yÇ[·L »êª«ì—_~±÷ß?ÈnõêÕ^@—‚ºÊJ}úô±sÏ=7nMHÙ:N´n.Í]æ]–+Ã@ ûÙ:gåkÙ¦=’çCå›,²u¼¸4w™·ŒH PùÙ:W¹,Û¤èò|å2oWGe[Ù²ù¸?ËÞÆ €@<ʶÄ/AÊ,_Ï….Ê·l/.Í]æïŒa P9Ù:_ië\^¿¹åþûïïU¯·ýöÛ'œYÍ¢}öÙöÈ#XyÁFÊH5%©i0Í£îDiÇw´G}4éfã\æh=Ó§Ú‰TÅ£j”RFå%?øàƒÖ¿ÿ¸ÁFš?›Ç‰Ks—y—çÌxÈž@6ÏYùX¶iOäãùÐEù&‹l/.Í]æ-#T¾@¶ÎUÚRWe›òvy¾r™·ÖÝE¢l+[5÷gÙ[È'@ÙO%<,_Ï….Ê·l/.Í]æ>rèCÊÈÖùÊßFW×o.ÏY.óö]2ýMÙV¶h>îϲ·†1¬ I5Žò@àÇ´‰'zŸ©S§zM¦©i5}Ú´icuëÖMi+–-[fcÇŽµo¾ùÆæÏŸoêoÒ¤‰mºé¦^So[mµUJùj&—y§¼RĮZ¤¦M›f³fÍòªn°ÁÖºukïÓªU+Ûxã­J•´NI¬Ej“¸4w™wj[Ë\ ïùX¶É<_χ”oñÿcòuÆß†"€@e ¸*Û´].ÏW.óv¹O(ÛâëæëþŒ¿5 EÊ lËþÈ×òÍeùã2ïìïa–ˆ¹"ઌsyÎr™·ËýBÙ_7_÷gü­ah 4Kë©yIIÉ£¼ÞE Ȧ#€ € € € € € € € PLÍhR­˜v7ÛŠ € € € € € € € €@š¥ Èì € € € € € € € €“GÅ´·ÙV@@@@@@@@Ò à(M@fG@@@@@@@@ ˜8*¦½Í¶"€ € € € € € € € ¦Gi2; € € € € € € € €Å$@ÀQ1ím¶@@@@@@@@48JÙ@@@@@@@@(&ŽŠio³­ € € € € € € € €¤)@ÀQš€ÌŽ € € € € € € € €@1 pTL{›mE@@@@@@@@ MŽÒdv@@@@@@@@ŠI€€£bÚÛl+ € € € € € € € €i p”& ³#€ € € € € € € € PLÓÞf[@@@@@@@@HS€€£4™@@@@@@@@b ਘö6ÛŠ € € € € € € € €@š¥ Èì € € € € € € € €“GÅ´·ÙV@@@@@@@@Ò à(M@fG@@@@@@@@ ˜8*¦½Í¶"€ € € € € € € € ¦Gi2; € € € € € € € €Å$@ÀQ1ím¶@@@@@@@@48JÙ@@@@@@@@(&ŽŠio³­ € € € € € € € €¤)@ÀQš€ÌŽ € € € € € € € €@1 pTL{›mE@@@@@@@@ MŽÒdv@@@@@@@@ŠI€€£bÚÛl+ € P@£G¶*UªŸ'Ÿ|²€¶ŽMA@ 5b+Ÿxâ kÚ´ið™;wnjpÌ… € € € P!êšš‰@@@@È¥K—Ú¼yó‚µY³fMÐM € € € €€;j8rgKÎ € € € € € „À Aƒ¬yóæÁçÇLb.&A@ (ûòwß±æ °V€Ž8@@@@@@ R~ûí7›3gN°ÔZPÐ P ”}ºcÙ,ŠH€ŽŠhg³© € € € € € € € €¤+@ÀQº‚Ì € € € € € € € €@ pTD;›ME@@@@@@@@ ]êéfÀü ß«W¯¶Ù³g[“&MlÝu×ÍèÆ,Y²Ä~øá[°`Õ«WÏš7onn¸aF—1oÞ<›1c†­¿þúÖ²eK[o½õæ?þ|oªT©bÛn»­Õ¬Y3áô™KëR‘õfZ@ Pþúë/›3gŽ÷Y¾|¹m¼ñÆÖªU+¯ÌHg›)ß*¯¬Mg¿1/ €ÀZ|-KJJlÚ´i6wî\Ûf›m¬aÆìR@â ¤SfäÒý½\Z—¸Ð DÈŠ”}kÖ¬ñî—NŸ>ÝtÏt«­¶²-ZXÕª™«§„2,g Vç9'fTL`Çw4ö©¦FÙ+¯¼’pöI“&Ùý÷ßoü±M˜0ÁV¬XáM¯ £Þ½{[¿~ý¬iÓ¦¦ÑgŸ}vWŸ>}¬S§NA¼Ž¿ÿþÛzè!{ôÑGí½÷Þ+µ-íÚµ³N8ÁN>ùdkܸq¼,‚aï¼óŽ]pÁAÿÍ7ßl»í¶›-[¶Ìî¹ç»é¦›L?Z¢ÓÎ;ïl×\sí¾ûîÁ`­ÓðáÃmĈöÕW_Ã×YgëСƒuíÚÕ®¼òÊ„ si]‚  È#l”o>ÇÂ… mذa^Y±hÑ"°÷­@Ó}÷Ý× d;wKÔCùöŽ«²öŸ%Ð…åã?ûúÛo¿µO<1p×]wÙ;ìà]SêZðꫯ¶?þøÃß}÷™®OSIºž<餓¼Wüùu]x÷Ýw[5üA|#€$ÈdùuÇwx÷µ8½0<ðÀàeÁC=Ô.¹äotªeF.ÝßË¥u‰6§@ ¾@¾–}Ñ[£çc °·ß~ÛV­Z=Ê«`Ë-·´îÝ»ÛW\”¿¡‰þ¿‡2,ž Ã@ %H´ä£‘ 2(P­Zµ’È?dÊŸM6Ù$áÚ<ñÄ%uêÔI˜$§d̘1%‘ÈæÐt#GŽL˜÷×_]©5(4OYÛR¿~ý’HÐSÂüFÊKë4sæÌ’ÈžÐðxËÐv*ýôÓO%»îºk¹ÓGž–üùçŸe®O.­K™+É@ ‡\”o±çf•SŸ}öY‰ÊÂxeCô°ÈÅ’{ï½7)1Ê·ø¿K2]Ö&µ3˜(0ÊÇvè'Ÿ|*¿_ýõ’H­‚q¯ç"GÁŒ‘KBóÍš5+Û¡k¾=öØ#4ývÛmW PŽ”~@™,¿">Cçåèë¶èîSO=5X£TËŒØkHî5¤t €”#¯eŸ6+ÒÒII¤€’H FI•¹‘ŠJ¾ÿþû2Er©<-s%Ùhš¹ºÑ"¿þI »ª5éÜsϵc=Ö–.]špEW®\i‡~¸=ÿüó §‹ùÑGyµE× ä×TÛâÅ‹½7RU›R²Iµí¹çžöÝwß•;Kä&„}ñÅvÐAy5-•7Ã|`={ö4m{2)—Ö%™õe@ ¦L™bûí·Ÿ©ùÌè¹!Ýëu«IѾ}ûÚøñãK‹@ù­îv]Ö†—F €@ªùZ>ªÆÝC9$©ë¹dl"ÁFÖ£GÓÛ¸~R Jo¾ù¦m°Áþ ¾@òP Õ2#—îïåÒºäá!À*#€E'P‘²O5>ðÀ¦Üý¤&ªUÓk›6mJÕfôùçŸ[ÇŽ½VRüé}S†%Òa…/@“j…¿ÙÂ<¸êª«,r˜ÔZGÞÜ´Hí ¡i÷ÙgŸP¿ß£&ÈÔ¼ŒŸTUü1ÇãUYߪU+¯úÄH­y³Çž~úiÓƒX5}–Lúý÷ßíàƒ6ùIU/ªÊ{ÝÀmÖ¬™Íž=ÛûqòÒK/Ùc=æOf·ß~»m±Å¡¦Û‚‘1矾לš+pJëyÕ[î‡~èTùë ›ÉZ¶~t)é²~Tí´ÓNÖ²eK›;w®=þøãvçwUG¾õÖ[6zôh;ꨣ¼yýÉ¥uI´žŒCrEÀUù½}ƒ.œ÷Þ{oÓ¹ZÎjnTÁªãƳ /¼Ðk›\ó©¬Ó<*ûâ%Ê·Ê-kãí†!€…&@ùXöÕõ«‚ü¤ëÊHº^óߺ¦«HŠÔ”äéE?©iíW_}5aÓÚþ´|#€„2Y~éeDÿ^Üu×]çÝ—ô—öòË/[¤[¯WFËJ©–¹t/—Ö¥,g†#€Å,¯eŸ®ynºé¦`×uîÜÙn»í6ëÒ¥K0LHj®ô¼óγ7Þxîgm*£?ýôÓ`º²:(ÃÊ’a8”+ Š IµlUFÅrˆPÕòÛl³M¨úÃH€× Z̤%üñGÉFmL©q¨äµ×^‹,èWõôµjÕ ¦œ ¼î²šT‹<¼ M«ª—-[äÛ1hРÐôM›6-‰ÅNV[-£Ö£fÍšÞðRGL˜0!n•‘ £’ Ä›¥äæ›o­Ë‘Gwº\Z—¸+È@@ @*R¾Å;7«jàH`k™‘ £P§ò®¬&5)ßJ3º,kK/! €¾@1”±Íãø×¡Í›7/‰¼`âS”ú.¯IµÈò’ÈÍôÐuŸšÝÖu2 @À­@EÊ/­É™gž:_G^`Œ»‚©–ñ®!¹×—˜ €) äZÙ×»wï l­W¯^É/¿ü’pË"Óëš,òH©és©<-µr @l 4œ+RO‘µ%à(Û»Œå!ˆD—Dª–ú Ú‰T[×'6À'RÛQÜé¢F"žCùGÎ%ñŽf̘ái¼>‘‡âEç­îÿþ÷¿¡üÇŽ;IÜ€£H¤t©é¢ÄÞHÖMƒH­Ñ“„ºW­ZUR½zõ`]"53…Æû=ñ~@UÖºøëÄ7 Ph-ßâ›O;í´rYbËÐwß}·Ô<”o¥H‚®ÊÚ`t €„Š¥|Œ÷ðX×g¿þúkÈ#¶'QÀÑo¿ýVyƒ7¸ÞÓ5k¤™î2ƒcó¦@ uŠ–_ZR:GÉ”ñ®!+ëþ^.­Kê{™9@¢r±ìSùè?¿Ûk¯½¢W7n·^Öô§×÷СCKMGVŠ„³@Óª‘“ òL`àÀ^Ó_þj×®]Ûë÷«ö‡ë[ÍÁDjñ ©ù²>}úýeuœqÆÖ¸qã²FÃ/¾øâ I²*UªXäf¯U«V-_V‡æ‹£|ðÁ »¬Ž 7Üдí‰RÛ¶mC£ÕìZ»víBâ{Ô´Üæ›o úù矃îD¹´.‰Ö“q €@> T¤|‹·]j>óÚk¯7*4l—]v õÇ;÷S¾…ˆB=Ù*kC ¥(bb-µËÕDNƒ RÚû‘`#ëÖ­›©ép?© r5ÏS§Nß €ŽÒ-¿*ºZ©”¹t/—Ö¥¢öL °V ×ʾH”M›6-Ø=“&M²HTDЯ#R¬E‚Œ¼{¬ºÏªf­ËK”aå 1 ਰ÷/[W€‘Z†lÈ!¡-{à¬S§N¡a~O¤v[ºt©ßk={öL* (ÒìšõíÛ7˜¯¬ŽHÓlÁ¨V­ZÙöÛoô'êhÔ¨‘í¾ûîÁ$cÆŒ±H3lA¼ŽHÓhV¿~ýx£‚azØÚ·oÝ·{ýõ׆GÞž ºuäÒº$ZOÆ!€ù"PÑò-Þv© òdJ6lØ04{¤*áP¿z(ßJ‘²UÖ ¤(bb.um©¡TÒ¢E‹lï½÷¶ñãdz÷èÑÃ^xáÓ ;$@·™(¿*²†©–¹t/—Ö¥"öL‹ °V ˾ªU«Zô3²Ÿ~úÉN=õT[³fMÂÝvÞyçÙE]ä}t]U^¢ +Oˆñ¶G…½ÙºЛ™'Ÿ|rh«1}ôÑG‡†E÷Dš„‰îµ=öØ#ÔŸ¨ç_ÿúW¢Ñ¦!/^LiN-èN¦#ú‡N¤i3›5kVÂÙ6Ûl³„ã5R5E'AU$)â;™”Kë’Ìú2  Ë©”oñ¶§E‹ñ—hª‘ѹê§|“BÙ)[emÙkÀ@ 8н|ìСCJ;Zåx¤©ûâ‹/‚ùU»îÃ?lµjÕ †Ñ àF SåWEÖ.Õ2#—îïåÒºTÄži@Ì«Uµ¢ÏîÒuK¶ì‹4)ZÔ}÷Ýg*sPôÍ7߄ƥÚC–ªó!PÕ c3Ø  _`Þ¼yvÈ!‡ØŠ+‚íÕ«— <8è×p¤&Õ’MÍ›7O8éÔ©SCã¿ýö[;þøãCÃõLž<94zîܹ–(È©¼õ eöÿ=Mš4‰78ía¹´.io  €•(jùo•£›ÈŒ7>Ùa”oÉJ­ÎUY[±µ`j@ °(Í*rí½÷uÝüã?Fòš4h ><4œ@Ì d²üªÈš¥ZfäÒý½\Z—ŠØ3- Pì¹^ö]vÙeöÞ{ï…ššÖ:_ýõÞG­‘ì¶Ûn^sÔª6•ò(•y¸ŸXìÿ9l! pTH{“m)X馩~øIí¦>úè£V¥JPÜïØ€£dššñ3*/*9ÞY¥š–/_žpÖT~€¨ÊH)—ÖÅÅö‘' tÊ·xë×´iÓxƒ+<Œò­bd®ÊÚŠ­S#€…#@ù¸v_V¯žÚ-«Ø`#ÿÈ1b„sÌ1¡¦½ýq|#€¤/éò«"k”j™‘K÷÷ri]*bÏ´ €@1 äCÙW¯^={ýõ×íˆ#Žð¾c÷—jˆ}î¹ç¼Æ©R€£Ž:Êúöík 6Œø`Rû™2,)&&B `R{]¬`9Ø0rO`È!6räÈ`ÅjÖ¬iÏ?ÿ|ÒÕÆ%ýöÛoÖ¸qã ¿D ,H4Úš5kÚi§Ùa‡V‘žöíÛWdr¦EÈctË7—›NùæR—¼@ P>&ÒI~ܹçžk7ß|³×”ÚÓO?mÓ¦MófÖ÷W\a×]w]ò™1% €@¹¹\~•»òL€ €@ ùXöí²Ë.¦ÏßÿmŸ|ò‰½õÖ[öÎ;ïØ|`±-¨_/l¨„8 !fAb à¨Xö4Û™—£G¶†Ö}øðá¶óÎ;‡†%ꉭÑHµ6$pôÃ?$ÊÚÚ´i¯`¨}öÙ'4Œ@b2Q¾Åæ™É~Ê·Lj’ €@²”ÉJ%žnðàÁ6hÐ o¢uÖYÇîºë®ÐuêСC½&:vì˜8#Æ"€$%ëåWRÁD €T@ ß˾ªU«Z×®]½j…]¹r¥½ûî»6jÔ({üñÇmÉ’%žÆš5kìÌ3Ï$à¨Ç“"PŒ4©VŒ{mÎ ¯¿þÚŽ?þxSµï~:ï¼ó줓Nò{“únÞ¼yhºò‚ˆ¢'þßÿþÝ[ª;öìÔ©SKMÃ@¢2U¾Eç™énÊ·L‹’ €@y”å %?þ„NMÜ­[7;öØcƒaýõ—õéÓÇôMBHO ʯô¶¹@ bÙ§5ºwïnwß}·iû¢Ÿ+Ξ=Û~þùç0} €@”GQt"+*¼>ø`ûóÏ?ƒUÚo¿ýì†nú“íØqÇC“¾øâ‹¡þ²zT¥â˜1cÊí WMIjûÕOŸþy©jýqñ¾;î8û׿þå}vß}÷PpU¼é† ß™,ß\JP¾¹Ô%o@XÊÇX‘Ì÷«yµèÚ¿øâ »é¦›2¿ rDŠH _ʯ"Ú%l* €€c|+ûÔì›ÿ .öYaYT›o¾¹õë×/4ú«¯¾ õÓƒD p­A79 °jÕ*;ì°ÃlÖ¬YÁÚ´k×Ξ|òI«V­Z0,ÙŽvÚÉì'U‡¨fÕÊK#FŒ°™3g–7Y¨júE‹Ù½÷Þ[î<šàõ×_·'žx¾ûî;ï³õÖ[[•*U’š—‰@òO Óå›kè&B)ß\k“? P¼”ÙÙ÷ &¾öÚkC »òÊ+ZzC$ô €I ä[ù•ô†1! €eäcÙ·ñÆÏà>ýôÓÐsÇ26Ó]Ñ€4mÚ4ÑäŒC" à¨È6?÷úöíkï½÷^°b 40ÕJ[À”Ó¡ùU“ŸV¯^mgŸ}¶­X±ÂTê[?<.ºè¢RÃã Ð[¡µk×FÝxã¶pá ?^Dzeˬÿþ¡Q½{÷õÓƒ PX™.ß\ëP¾¹&@ P>fï88õÔS-ú­^]ŸrÊ)Ô´›½]À’@ €\•_U«†W”w±€HÙ@ÈDz¯sçÎ!Õ»îº+Ô_VÏo¼Œª[·®µmÛ6览¨;€~¨³öíÛ[ýúõ½6\Õ\Œšq[¹r¥?›yæ™vçwýeu¨¶¢Ç{,¨Žþ‡~05妀#ý˜iݺµÍ˜1ÃÔΫjOR-K~ÒžÛo¿Ýïå@ \•o®©(ß\ “? PÜ”Ùßÿº>íׯŸÝrË-Á `x 5kÖ,F €@Ù.˯-·Ü2´`½@¹ÞzëÙ¦›nj‡z¨]sÍ5¡ñô € |-û(4bÄëÒ¥‹)˜HŸ!C†Ø˜1clÏ=÷ôj.jÑ¢…ýú믦JüñP³k Næa6öË@Ü à(w÷ kV„*ì]¥ž={šjRmB 6ò“j5úðÃý^ï»ZµjvõÕWÛ®»îú1Q³fÍÐt~Ï:ë¬cü±vÚiöÌ3ÏxƒØôÑGyºØoÝì}î¹çlÝu×E? €@ ¸,ß\2Q¾¹Ô%o@ÊÇÊ9ì]·ªv^%Õ|ÆgxM™WαT@ ¿\–_~¨Ž–ÌÒ¥KmòäÉöË/¿äk‹ P0ù\ö©YµAƒ™®ƒJJJ¼}òí·ßš>‰’žÛ=üðÃÖ¨Q£D“1°p£È€ €@A l½õÖ^ªMTfuêÔ mo­Zµ¬W¯^¦jå/ºè¢Rͪ%úaÑ A¯Šã‡zÈ{ó(”qL¦U­ RjÙ²eÌXz@ÈÊ·ÜÙ¬  €@îäsùX·n]»í¶ÛB˜/½ô’E7I €@ÖÔÌ‹ÎÉmÚ´ÉÚ2Y €•)²O54½÷Þ{¶Í6Û”»©UªT±ãŽ;Ϋñ¨{÷îåNÏ €@•t"‘FæïNÌ‹•' ¨ìiÓ¦™šSkܸ±5iÒÄj×®¬ÐèÑ£½$Àwß}gíÚµó{Ëü^²d‰}ñÅ6aÂï3þ|/oUQ¿ÝvÛyÕÕ«Ö €ù$@ù–O{‹uEÈ–åc¶¤Y P<kÖ¬±™3gÚÔ©SMݺo©‡¤Ñ÷-‹Gƒ-E(l”}ZÆØ±c½ç‚*gõY¸p¡×t©*hÕª•WYAÇŽ‹œmDÌ4#à(3ä‚@A \uÕUvÙe—Û¦ª‹7ÜpàŸ@@@@@@@(:fÕ‹n“Ù`ŠL@˯¾új°Õz#¨S§NA¢Ž>ø ݺuk‚ :@@@@@@@(^ŽŠwß³åE"P­Z5ëׯŸW5¢6yýõ×·9sæX½zõ ¨9´qãÆÓzè¡A7 € € € € € € € P¼U‹wÓÙrŠG`ß}÷ 6ö?þ°»îº+è×1}útëÑ£‡-_¾<}øá‡Ýt € € € € € € € €@ñ pT¼ûž-/"Ã;,´µ—]v™WëÑܹsƒá+W®´O>ùÄn»í6ÛgŸ}láÂ…Á¸>}?¹Ó @IDATúXç΃~:@@@@@@@@ xª¤³é%%%FæïN̋ٸñÆ­ÿþ¥V§NkÒ¤‰Íž=ÛV­ZUj|ûöíí£>2MGB@@@@@@@¢hF GE P,^x¡]}õÕV»víÐ&/]ºÔ¦M›7Øèßÿþ7ÁF!-z@@@@@@@@€Ž8(2E‹ÙðáÃíñÇ·™3gššR‹NM›6µC=ÔŽ=öXëÒ¥Kô(º@@@@@@@@fq PÄ‘fmÁ‚6þ|kРm¼ñÆV«V­"aÓ@@@@@@@@ fÕË™€Ñ PÀUªTñ‚ŒhDB@@@@@@@’¨šÌDLƒ € € € € € € € €H€€#Ž@@@@@@@@HZ€€£¤©˜@@@@@@@@ªC€@¬À}÷Ýg·Þz«Õ­[7výy(°lÙ2«V­š­³Î:y¸ö¬r¬Àï¿ÿnë­·žU­J¼h¬M¦ú/^lo¿ý¶m²É&™Ê’|r@`Ô¨Q6pà@ïÿ'V‡UÈ€€þWëÕ«gUªTÉ@ndQÙþù§÷[¥F•½*»üU«VYƒ ìÍ7ß,Øm,¶ {ÿý÷íÔSOµõ×_¿Ø6½`·—ßú…µk—.]j*×jÖ¬YX–C[³zõj«U«–}ðÁ9´V¬J:S¦L±C9ÄûŸN>Ì›;üñ‡Õ©SÇ»7™;kÅš¤*À}æT咟ﯿþò&þüóÏ“Ÿ‰)óB oß¾Þo–ÚµkçÅú²’‰–,YbÚ—Õ«ó˜=±Tî]³f龤î3“ÜÈX÷%¿úê+7 ×JàLXé» ÷V`óÍ7·-·ÜÒ :ʽµc**pã7ZëÖ­­W¯^•ésPà€°ûï¿ß6Ø`ƒ\»ÂX¥îÝ»{7­ ckØ _ iÓ¦¶Ùf›™‚jI…!°÷Þ{Ûã?î]ÜÆ÷VœsÎ9vÜqÇÙ;ìPÜ·^Fï¾û®Ã%u¶5jd 6´‘#Gf{Ñ,Ï‘@Ïž=mĈ¦}KÊK/½Ôºuëf{î¹gþoLŽnÁÇlO?ýtŽ®«•Š€‚hõðî¹çžKevæÉAc=Ö®¹ækÑ¢E®«TQk¯½Ö¶Új+Óo’‰'Ú°aÃÜdN®•*жm[/ á¬³ÎªÔõ`á™ÐË?ýúõ³­·Þ:3’K¥ Ì›7ÏÎ>ûl~:ܳfͲK.¹ÄáȺ²8ªì=ƒË÷ßÀÓÃYRþ ¬»îºV¿~}cæÿ¾Ô¨f#Õ¼£‡K$7ª-…¤ÜØVf®*Ûôá\X™{!óËÖùPoË’ò_@µ?l¸á†ü:Ü• V¦– ‡À•µÞ¤TM¦”m•€ïh‘ú ºñÆ{G‹ Û, ¨æÕ,Çÿ¨;t]ë7>©ptÔ59ÿ7…³Oõ{¥qãÆìÓÙ¥Ügv¿#,X@)î™+e jB­ŠPÆU ƪߠú-ÊþÌ8mÖ3üû·âX}ùòåÔv騏²³§MžÊÞ,@@@@@@@@< †£<ÚY¬*©¨êbUIM* n¸ýY»’­@4†jz;ŒTªºXMÀ’@b2dˆW;m1Ò¶ÿç?ÿ±&MšÒ&±- €@…HÍ}VËÝÔ ¶jï#!€Å.пkÙ²e±3Äö«Æu5ÿJBÔ8JÝŽ9È Ú͋ݔôJvëÖ-éi™(d8 7¯è¶­k×®E·Íl0 +°Ï>ûÄ¢?:uê”ÇkϪ#€™ØsÏ=3“¹ä„À¶Ûn›ëÁJ €•-°ÓN;Uö*°ü ¨¹Ð=öØ#C¹‘ Å)@“jŹßÙj@@@@@@@@R à(%6fB@@@@@@@@ 88*ÎýÎV#€ € € € € € € € ’G)±1 € € € € € € € €Å)@ÀQqîw¶@@@@@@@@”8J‰™@@@@@@@@(NŽŠs¿³Õ € € € € € € € €¤$@ÀQJlÌ„ € € € € € € € €@q pTœû­F@@@@@@@@ %ŽRbc&@@@@@@@@ŠS€€£âÜïl5 € € € € € € € €) TOi®,δbÅ ›:uªýøã¶hÑ"[¹r¥­ZµÊöÛo?kÑ¢…·&Ë—/·Úµkgq­X € € € € € € € €Å)“G (zþùçí•W^±ñãÇÛêÕ«Kí¶mÛGÇ·wÞyÇzöìitm´ÑF¥¦g € € € € € € € €¤/sGãÆ³Ë/¿ÜæÍ›W¡­›úè#»ôÒKmÍš5¥¶`ƒ 6°.]ºØ:ë¬SjœÔ®]»ÔðÇ܆Zj8@@@@@@@@@ uœ8Z¾|¹ 80´ ":ùä“íÕW_5#=üðÃV¯^½Ð4~Ïi§f7ß|³5kÖÌä}?øàƒ¦&ÚH € € € € € € € € œ89r¤Í;7Ø¢ZµjÙˆ#lÀ€Ö¢E‹`xYUªT±8À^yåëÕ«Wh²aÆ…úéA@@@@@@@@Ôr"àhôèÑÁ¨Ù´{î¹ÇvØa‡`X²5kÖ´Ë/¿ÜZ¶lÌ2qâD›1cFÐO € € € € € € € €¤.PéG š2eJ°ûï¿¿uéÒ%è¯h‡šb»úê«C³½öÚk¡~z@@@@@@@@@ 5J8š9sfhÍ;tèêO¥Gy¨¶#?E7׿ã@@@@@@@@*.PéG?þøch­3pT­Z5Ûb‹-‚|úé§ ›@@@@@@@@H] ÒŽV¯^Zû&Mš„úSíiܸq0ëÏ?ÿtÓ € € € € € € € €© TzÀQ£FBk?eÊ”Pª=Ó§Of­]»vÐM € € € € € € € €¤.P=õY33glF'N´Î;§•ùÒ¥KmΜ9A±AMÁ:@@@@@@È’ÀŸþi .´åË—ÛŠ+¼ouûí·¶råÊ,­‹A@Ò¨ô€£Ž;ZݺuM?°”xàëÕ«—Õ¯_?å­;vlhÞí·ß>ÔO € € € € € €@ñ |úé§^O:u¼çSúö?묳NR zñý믿¶¯¾úÊÖ]w]ëÖ­›Å¾`Ñš5kìÕW_µGyÄÆŒSf`Ñ;ì=Ý € €@N TzÀQ5lï½÷ö~`IJQÝ—^z©Ýyç)Á©†¤Áƒ‡æÕ= €‰þúë/›?¾é›„ € € € €¹+°zõj/€çù矷6mÚØ)§œb 6L¸Âo¾ù¦÷üé“O>)sºÚµkÛ¦›njÍš5ó¾ýî 7ÜЦNj_~ù¥÷™1c†ýý÷ß¡|¶ÞzkëÞ½»÷Ùm·ÝLy}óÍ7öÐCÙã?n ,°*UªØ{ìa ,ÒøZµjyßêþé§Ÿlܸq¡<éA@rY ÒŽ„söÙg›j%ÒD¥7ÞxÃN>ùd»òÊ+½tÞÀrþè‡Ý+¯¼b×]w­Zµ*˜zÿý÷O:`&:@ V@5ê=Ú>þøcûñǽÏܹs½ ~•%åݘ(X6 @  tTRRRÐÛÈÆ!€ € €@þ Œ?Þž}öYï9Q‡LŸvíÚYõêÿ<ÆÒ5ržxâ oÚ_ý5Ø`½ˆ~ì±ÇZ¿~ýlÛm· †«ã£>òÞ~ûm«Y³¦õíÛ×þõ¯y-o¨¦¢èÏ¢E‹ì‡~° &Ø[o½ÊG=U«VõœŽ8âoµžZ×^{ÍûÜ|óͦ‰¬4mÚ4/-¶ØÂÎ:ë,;á„l³Í6+•¯h™Ÿ}öYÜq D@rQàŸ_j•¸vúÑuæ™gÚ­·Þ¬Å|`p€éGÛ6ÛlcŠ Ž×KE{Ïš5Ë‹*Wt¸º£“ªÀ<ÿüó£9ïÖü9sæØ²eËlóÍ7·õ×_?£ËT{¾¿ÿþ»)š>ú‡vFBf €@ ¨Ö¢ÿýïÞ›Dª²Xçh%G7Ùdï|½óÎ;[Ó¦MmÔ¨Q¶õéoe[ú†ä€•# ó¿në:AA¦]ºt±Ö­[WÎÊ8\ªªæÿî»ïì‹/¾ðÞ´7ožýòË/¦åþG7Ð>úh‡k‘_YS¶å×þbm@’pY¾qO2¹}ÀT P1É“'ÛÈ‘#íÉ'ŸôžóÄέæÍôlHA=uëÖµçž{Îôâ ’žõïßß?üpS°Ò°aÃìð>ª]HGÍ›7·+®¸Â^~ùe«V­š÷¢ûe—]æ ]V¼~½¸¨kJ}tÕªU+kß¾½×„Zìô vRRF~ð‘®ÓN=õT;ñÄm§vŠ…þ$(ß’„b2@*A 'Ž´Ýgœq†÷à™gž V®\i=öXÐÝ¡Hðè¤èqêV”¹˜Tí¥ë´dÉ»ÿþûí…^0ÝÜ~sxƒ 6°-Z˜~àþç?ÿI)Hè½÷ÞóªÜT$¼ªÜTRµ›5²]vÙÅ ÊÚn»í\o&ù#€@ èÂ|úôé^€‚lÔÎx¡%=dV-FºañÔSOy7tîT`ÑqÇgx ×®ºÊ‹è¤ZöHf”m oz¦ìTëé÷ßo³gÏö®/Œã'½Ézî¹çÚ Aƒ¼›ÕþðL|ë@7–õæ¬ÊU½  ZóüO:/"(XhñâÅ¡Êréóõ×_›¶ßO*ïêÕ«ç­ÃÆol[mµ•-_¾Ü»Fò§)ÆoʶbÜël3 Pø.Ë7îIþñÃ"P][)h'¤ë5I¦ZŠtÏNÝJz!ðœsαcŽ9Æ4hà ÿꫯ¼oM£€"%=k¹ôÒK½étã'yä‘Þt·ß~»—·‘”t}¤—/Ô¢†š^«HRÓ–[né}’OIúdûeød×/_¦£|Ë—=Åz"€»@ÎiG¨ÊKÝsÏ=Aíeí DÁFº©~ùå—{A>eÍŸ©áO?ý´ÝtÓM^­CñòTUšú豪ß:thÒM¼)j~À€Áéèüõ@cáÂ…¦ö‰õÙk¯½ì†n°õÖ[/z2º@Ào¿ýfW_}µÝqÇ¡æ'u!¯À#}6ÔΦ ò½÷ÞÛ» eà°GÍjªýt=¬Õ²+z@7=ôÐUU#ëóþûï{A3ZeÝ€8ï¼ó¼j•õf)±e[bÆ"€@n (À硇ò‚KU¨’‚|t¾ïܹ³W®©[@ªÖ^¿™}ôQï»wïÞq7æÓO?õ^|xñ޼ÜïtãXUã+ÍŸ?ß^ýuïíU¬ú/ÄË´FÞ›¹ªÁU7ÂuC¼¬¤jôõ"†ÞÞUíL~ÓÓñ¦oܸ±í±ÇÁúuìØÑ«ž?¶6Ô—^zÉ{«7^Å0Œ²­ö2ÛˆŸ€«ò{’Åw,±Åøz |ÆŒ¦š‡T;ÿ=eÊÓ85 ¦ûlú¨I2}k˜®wôÌB×.ѽòùçŸ{56iÒ$ÓK‚Jº©—´d¤kšè—u_P×M~úùçŸM-3QÚ~ûí½ëC]÷1ÂkÎL?ª ‰”?”où³¯XS@ª¤CùùhdþøwéÓÈX?o¹å/F?R“MúQ{ÒI'yµ%e£¶=8p`ÜÕSÔ|¼uW3o ÒýDIŠº÷«M4­?NyªF(Õ|”Nz÷Ýw½ãj¦Ž„…! jgï¼óN»êª«LAG:uòjùуQ51£sÿí77Ö²eKëÓ§w^Õ[F™N õÛBW@¦„TƒƒŸTÑÉ'ŸìÝ\ÐÛD±IFzÃIç,éÍKÿA³ª[V³9{î¹§rÈ!¥ÚmÍ+º_Õ4«YOÕ QŒ©PË6£)Yµ’ȶ€ª`Wõíz;O7S³™t®Õ¹òÍ7ßôj¶S9°ÑFesœ,KµôéäÃ?T»¯@US¯jìËú=,ûî»Ï{#VÕ᫬ÑÛ¯šWyê÷¯>ªYTIAA*›Ô”³ŸÈ£7\õ[âĉÞ`ýö× ì}öÙÇ»Q®2ÊoÒLßúè÷½Ê½Œ ¤&Ý@W’Ê\§´M:ë¿’^ÆÐ óúõë‡>º1¯ý¸í¶Ûzµõy—óÇ8ºûî»Ë™²ðFjÙ¦ãDçý"!€Å( kÁ{ï½·ÌÚÑ ÝÄUùV™÷$ubÿý÷ûòe¡ïO¶lèþß;ï¼ãÝKS-©ºÖQCº¨ºã½ì ë’víÚy5¹*`hæÌ™¡Ö'(¤k"]%J›nº©wOR÷%wØaï…qÕBKúG@÷JÕ\1ß¿*ÄòM{xøðá^“窡‹„“€î¹ªyQ=$¤@³œªáÈ'Ö‚!C†˜Þ8~(ò¶²~ÀªY=¬‰MªÑG6Šx?å”S¼*5c§qѯ›ºjë7:uíÚÕzôèá=äÖÃyýéíhOùMèGü7Þè=øž7º[o è!{t°‘Þ¢V¿z(¢öŠÕ¤‚jQûÆzx¥¤·Ÿ/¾øbïf‹~à“@ ¿Tk™‚‚TS‚ÚW L&’^êÜ s©jxPíFzs¨¬ó„Î]jïüÁôÈ*Hã€ðαz8ªó™n@èãw놂šŠÑQêèÛüÔtZ¶òþèí&Ë”üsœjkÓCÜQ£Fyµ:èÁ¬Ú[WK:/*OÿÆHt€‘Nu£BFúè|é×>‘ ÃbɃ²­Xö4Û™ E‹™jÇQ ¹ÎëþoA/O;í4§«0uêT/ÀHAFú¿ö\´PݼÔyTAð©&ýž}õÕW½›Ó ðÔG7‰ýný>×oaý¦/«¬©È²õàIoÂêwµ¾õ‘¯’‚nþûßÿÚ¿ÿýï¤ÞXÕp]à*ÈG¿å|£›Ýz+W5ì)©¶T婿7죤šŒd§  }ë£}y 'X÷îÝ­[·n¦š†ÊKºy¯ý¢²YÍ¿]tÑEÞGÛ¡ßJº™¯fß´Žº¾È„ayëUÈã)Û yï²m €@ñ ¸*߸'Y¼Ç[^˜º–Òõ¨4u¨ûr~jÒ¤‰wϯõ\÷Üüž·(ÀÈÿľ¨ë[Õ|ôí·ßz½°¡ë#ÝŸ‹ýè:I×\úÂË/¾ßn(ßܸ’+ €.ÒŠJqUÃQY¬7ƒT£7Œõ @íõªi„l'Õ¢‡ úÁî§ž={Úõ×_ªöÓ§Þ †òŒh¸ÞœÖìxIM<¨É#?éGú#<â½í󿔤7¹£ƒ“ôæztu£þ´É~SÃQ²RL‡@ftŽP`¢j(ÓÍ==XT­ ú?V­ É\Œkz= Õ9Ršþ·‚zÔÞ¹‚€.¹ä¯-t=N&©zcÕ† 7Fõ`9QS–ñòÓ¹K7$T¤õ‹Nz­š ¤ #=P úã?¼æqüôñÇGÏî=ØV39{Dª[ÖGF~€ShÂzе†£B/Û¨á(…fII@5îè·œ~Oé<ªÚptžR©šáÕïG›Ë«>•…«¶”* G©Zµj^ÀŒš©ÔG7˜õSòz[2¶É­DËÔÍcݨVY¥@•—T(ðH7²õQ·ÖIå‰ÿQù nƒü·j£¿,¥øü¤²BÁ÷ 2ÕïqmKE¶ÃÏÇÿÖ[½çœsŽ·Ozõêå½ð +­§ë¤à#™*øHL*Uö» 2*ÆŽ ½l£†#×ÿ¥ä¹.P¬5¹,ß*ûž¤~+SÃQ®ÿç±~ù  šÊ®¹æ¯FÝkTRí­º6õ?zÑ”{º6,ÖŽ ¹|Ó‘F G¹÷ÿÆ!€@vðL GÙ±®¤¥äf Gea4lØÐô©ì¤‡,ÑÁFº¾îºëâi]õÆ´‚‚n¾ùæ`Õßxã¸GúQ¥¶…£“j{R­"ñ’. Tc’.ùI-Ò 8òóá×zˆ8oÞùdðûWAžªýg³Í6ó…TþD0ªrÝÿ¨ Q”ü%ÜÊΫVß*3÷Ûo?S©>íÛ·÷ÊÕDùTdœ‚_õ¥‚žTÆd3é÷ö“>$7”mn\É@ r\•oÜ“¬ÜýÊÒ‹G`öìÙ^Í©zø¦”ýß$³î¥©5]?ªÆU}+X(™šOu-¦{šºß¨kC]Cé¾ ® 0*žc,_·”ò-_÷ë Pì•Þ¤šÞê}â‰'‚ý W^yeПkzPrÏ=÷«¥òª5¤¼· õÆ´‚ô0CIUŽÆKcÆŒ šSÐx½¹­Ú“%]tè-o=¸RRsz°£6‘I䢀úê-~5 XVRU¼cÇŽM«Ö‚xy+ØHöÆçöèa¯ÿT7×ta>qâD¯Æüì»ï¾ñ²I8ìý÷ß÷Þ"R­@å%; xþùç{ÿÇþôÏ=÷œ×¤Ø™gžiǼ×|¢Î= Ôyå•W¼ó¦šêQsejÆFA8º¡šß6T{ìû¹ý|SýÖùDçºÊJjf-ºæ·ÊZB].e[¡îY¶ËPcª Gçy›fúF«Ê²êw­Êý¶4«škô¦â Aƒ¼¦3‡ æ¯bÊß*ÃT†¨INUU¯&ÜXTVÒuª-T± †U͘ñÒøñã½|Ъ¤2Fe’Z¶lo–„ÃôX7Òu¾Q`>ºaîw+øFA¬ÉÜDO¸ Gf;Ø(ÅÕd¶ P¶U‹I@òFÀeùÆ=ɼ9 XÑ<P”ºU­Ëú|ùå—öÛo¿•ÚÝÔ=<½,¨®5^Xö“®/;vìhª•[ÁGúèºL]G©‰³»îºË®½öZSà’M/ÁÈÊ·|ØK¬# €ñ*=àhæÌ™öá‡k§ǹœtaÝ|™‚5jTî*+H`ðàÁ¦êL•TsG¼¤@…è”èQôtªÅ8ÒpjœvÚiÑ“Ð@)5õ¢¦Lüª[,é4ORjA1Tó‚‚>ø`¯Y¿¹ÿ[?õ@T6£üb²©pot°ÑÿûßP­cÑ™éáª.È8à¯I³3Î8#zt™Ýª©HÕ¿÷Þ{^âÑGí=PÖ ¿–ÿ[ÍèÖåݼyó¸yvØa^“cZW5«¨æw´_tcBdwÛm7;öØcíˆ#Ž0µ·î2ENÕ‘šÚ,Ò:)  Ù¤ €ò’š›ð“.TkI2I5E'Ž¢5èŽxíµ×¼êtuá/é͘sÏ=×.ºè¢2ƒãâÍ—Ì0Ué«¢j¦Kµ0D_Lûóß~ûíöý÷ß{Í ª ® .¸À•ò·‚@¤šiú¿ûøã½éûF¢kä¤õŽWû߬™ëü `-5i3`À¯é0…Ë *òÇ—õ­`¥‡~Øk~GXº9qñÅ›Î=~-f‘Š*"µUXä!sY¹¤7<òRUäa½Y¤¼HS7¹ia‘¦ÒÖ¥—3sçŠe[®ì Ö#Ó ¬ÑV›_zé%/(HeŠÊ ‰¦Û¤™nˆ©lQA7Üpƒ]xá…ån‚Êól»í¶vÒI'Ù×_]*HHùª]k5g¦¤ \%ªªI6©é1Õl¤jòÕlæå—_·œòfŒù£¦Ê䡦ÑT¶èµjTÁ*ïT{žš1»é¦›Òn^4fÑô"5ʶ¬Q³ @, ¸,߸'™ÅÉ¢ Zà÷ß·Þ½{{×\ ,ÒýÕŠ4‹&]7* I奤À%½È¨Oô·¾ýîOj9z±1Ýë\oaüA Ë”oYgq €dP Ò޶Új«Ðæüy¢­Z€rõ èè>zó@Mcd*éBAMMøi›m¶ñÞpðû}·oßÞ«>Uˆ”t±AB V@DHôÔSOY:u"µÔå½í¢ ]Èê[½9£*xï»ï>ïM=ôÌDGo½õ–Wã.–UcO¼`#­³_û‚jîRàŽª V³„©&?ØH5iûõ0µ¼¤@'©¦#5y£vÕŸ|òI«[·®×›ß¬™ØêÿNoÏ9ç/8*ÓMõh]õà·¬ÿëÑ£ÍÎ:ËL/9EžAg4=óÌÚ£HÍΦå(ÿÈ‹R‘fÞ‹™?ß"Yy£Ê"µ†X¤ùðxúr[€²-·÷O¡¬‚¡õ¶¥ª€O'éFªÎ·z ¢àK5;©|c“‚eú÷ïïÓ¼üòËÞ›¤j&S5é¼~b¤Ú¶‘#G–YÅæÛ¯P°P§Nâ΢ÿ©S§zM“éÿNÕû)6ØHq“Mª]HÍÞ(àꡇòn&hž{î9[¼x±¤¥ÚÔ¬™š?sݬY¤™÷ȃf‹ìG‹8ý³{ï½¶y³HEöÕWáqÿLUñ®ë¯·HmJyXo‘}a‘êž×æqÞy¥ózñE‹4¹³vø>û˜E*Ñ %ÅRFjˆ&å e[î”\¥·ß~Û:è ¯ Pà‘JSIEª\;î¸ã¼Zð8;pà@4h×<˜wt.ÖÍÜ~ýúyÍ‘)¸IË‹.ïtªf-´£µC‡MzU¯ü^xᯖ>÷ÕJºÖUÁD <Ò:h]õ6ªÊK•}#FŒðnfkåxëת©rüƒ>°o¿ýÖ ¶*¯ µDײeKSà”šWÓÍk­‹j]ª¦(Sy,@Ù–Ç;UG(SÀeùÆ=É2ÙQ$jZúÈ›|ºÿ¨ëNÝcÿ믿‚­×½÷Í#-5èžà³Ï>ëÕX¤À#]§©F]%]cªIj+©©mÕ&KBÿcïLàe*ß8þTB‘²DEÉZˆ5’,‘5D²–¥ì;Ù—Ù"$ûžJB$kRI¡²¯¡(²–þÿç÷Nçš;wöåÞY~Ïç3wfÎòžs¾3wÎ9ïû{~g<¿yfÄ%H€H€H œ $¹àpúôé#›7o–Ó§OV(Ia¾n²%$²¶e¹˜ìÞ½Û v!ƒÁU` bû/ÇeíÝ0ï.Ø„øp\²´çàb) f!“A'”Ü`D&ˆäÚªeYPÖkÖ¬YfÐ×ÙѨ±‚|ðÁÍ:»ÎÑÙO´¤Vu)[¶¬4oÞ\òæÍk,}!ò&à‡"|'W¨2ÅÛÿmì/r±]ˆ¶mÛ÷?‡àN±gÏžx»ý‚ðt€œ|Y ¢CaúôéfŸñ?¼S=°A†È ¬e océRQ7ÑfÛ–tZyÜØªš1©#•è ±hiÀGئV’ÓgÑÁn[»ª uHìzçü^ˆŠã/ ã5쳚f˜e´"PXDiöbRÜäÚw*…ÕΆ`gbåÜç|ÖÖ¹ (!zqV*1˜cºI4!‚,àá2„s®¼ ¸ :T† b:s'L˜`Ä:©CŠöࢇ]ˆsð[]AÕ˜è v¼>²JšÁÍâ#\›áá* hEû8Aèƒ}A(m6mÚ4³=Wëzšþæ›ošï$œŒðÛ1.Á8WßMOµjÕÌÃSûÞ̇eL!àBIUFt€;"Ê. ‘ëüXˆX9·]¹rEð°?·A°h zÅÂgÍc$ˆ=‡–#GŽ˜‡åec%By~ —>I5p?nn{L-”q/Á `ÀïFx@d—/+ПX£F “‚Ä<З‰>BÜâžmæÌ™æ>®ºHA_:úQ®‚$ö¥[4ùì $EYßA¸ì[U,¼Y7–‰…ó>'üNà³¶ÎqèßkƒH€¢‘úÞqÝ„@ßäÕ«W£ñ0yLÿ ÁN¬|ð2X_:\¨cP)œ.ÎÏŸ?ï‹ÁÊZ ôŸÜ2ûQÂŽ;:]öá«àÈQ\„ÎÜ ù(i‡‹<8â ÐaNŸƒ¯Ç«ËcðaÀ€f0®¸ÆwÕU' ~÷ÕñWDàPS¢„Í‘®4iÓ—åË[k)­÷Ì8˜¢M ÒB|„J°”Еàè…yöѪU+ùNíyð?]½zuûY_C|ˆòk 407ûÍš53"#Ëf5cÆŒf`Û†¸ƒ¦ÖeÏàöÕ¹sg¯Ê¨¹Û™ÞjõSIÁ`0ÇèoèX»ò‰¿¶fè ¯íaÍÁ4~ âÑê?êØ!š%%¢(xÇZÎzV3µt¶Þùÿ¬z ‡‰:;¡Œ›h™ ÑcöÜž~ô{à|9ý*JÑ¢¢1ý)TÇ,Qר„œ¯ú©p,±~ï°5 úÇÒÅO¬œÛpNÄÃþ³æ lèÿ¿°…vª`D3”éDG-JDâ\°TÕ”y ü¦Ãùâô‚ Êœ9sŒèë¡<Î;gD¨èô…8'¸õ CØY¤H‘BÏkËs]µm³,é!È€ˆÏx@TŽ}G@ñ+œšÐùŒò¿8'C8 ;~œcÆ'– ÝÙ~‡jš½3`¨¶Áv“†Dr(Ù‡Àùç¸XˆX9·áþíöç6\“Sp ßr# Ä.¯¾úÊ\G‚~󣙌ã±³_2\ú$1ÈÑ‘ý¹ å~]õeEóçÍc .Ü3¢~Íš5æDF+ri&Ügábއ»{2à^4lØ0“€‚{¸š¦p_‡±‚@\h­}âsl@¿ùìÙ³ÍAãú‰[±±p~Ãç ±Ñ®]»â>_Œ1PpKßt+ Ĉ¬kz\ã#œ½ÂBp¼p2[ ¸ø‡p%Ê—/o¸˜G†€£Á›&BØŽãÍ7ÔæÈl·ï¸‡ø!gΜ¦CÅ;X׸!É”)“OXÓ­gÇö3ò­å\=;.ï˜äj=Çé(¯ñðÃÇ]ä:Îçûð#ðÛo¢7Ë¢Ž;¶}Ûºu«ùÿÙ»÷aªÐRf·é€ïÝÚAã|ßÕB—ÃÄ ªMrˆô: ;Å8y-Xð‹æþ¥ Ì@,²€¬,¬„ò2ÿ ¼ Û·o7ƒÃp8‚C?Q¯^=uð!½zõ’nݺ· ü>Àa®J¿àÿÁú pUÒÍÓ1éO…–Æ͘-'$²vmü5ôgOKÿˆþvØ\€ð9i2”f³ˆÀ HM=Œó”]¥¸ø è;GS‚¼œ€>ˆPÍr,òrU—‹éWBÔE¢Y_"/¾(úûbT Ýr¹=_g@8ƒD@X+áxî‰Ös>g”Bµÿ¬cå3NÊãojp€µâšåÚ‚Q¡31Y²°¹,ö!²½$$¡6”ªE ½XˆX9·á¾‚AžÛbá[Íc$°Ô¯__ð@ ?"óX‰PžßÛvìcôÄØqyû$Ñ®ÃynóDœó½!ð›v˜ÂÕvµvtÁÙÚêÃϦ ºHŽDŸ"Fsð5ð]Eò ʪÁ îkpªu•ôâkû\>¶XÉT8j|W-[¬Pp<³oÒ±mÇó•'ÆŽËû{~Ãv´{8ÇH<í+ç“ @8@u<ø]oFÔ‹‘ \Ü#{Å ˆŠPròx¨¹ŒpTZCe¡PšVÀeÖ0@•,ƒ«DVöáxñã«ÃœWì#–l¥í;Ò_#[Ž>¸±ðÆqî1(gQK­Zp5êon¦‘Ùܺõ«²jÕýjó{“*èmB{>(¥yã Ñ‹]ÑdÑòeöKÄï÷üù÷«ÐŠü§Uøcsƒ9tè|ûí·¦Æ9êœãƒ¸Vàb®þ­6Pnäø¿xê©§îžåh|Á…‚+¸õ` Çaž¶ë8_5O2z´Í1ªbEǹ¢%$EÔ]P3D–-uL³¹Á±HµVÚY‘pPM¹ûnÛwgÁ1YûªcöÆA º3ˆ™ôgS;dDÙ­%ü{†0 ÚÎ4i¼_ÿ/ˆ¼b=xn‹õo@èŽõp7Bvç¨.ÿ ”¥Ä5TEýA¬[·®L€°Òw8À‚”ºO•—pCÂõ¢7áØÈj"4ˆfÑÙƒí@pGž‡/(äëh]3Ü ¯X±B–,Y"¨Uï.¦®qãR¨P%}½ÛÚf̘aM±.kôhZ6OÔùH´f°M°4¾ÍMÇݶ0O“u´ü¡ˆ6oJxAÔƒuïÄ:ZdŽÂUß/8X: hQòé¡‚Ÿµ¦'ÄFášÎC8¯ÀÑnD¡ ì 2R$@ÑC€ç¶èù,y$$@$@7„òüÆ>Éœù*i Àé/Hn„kýãÌ™3FÜÓ¯_?“ âlO‘Ä}ºËöwì€sÎÿÔÅç°–¬Éª7áäµ×^“M›6ʼn°r¥J¢eÎâ7£¥¡ØH+Õ¨Ó„wb#´‘’ ¹u†X.^:u’É“'5s(þQïŽ!•V픘ƒ+ž!Ú9qÂVÖlÐ ÿ¶­Òå•cªõ"6Âêø¾ºˆ–/uñoŸC½–Uþ¥ã ¸Á$OÍäÔÛskøŒUÇ`âƒÉHýVDÏ~#‘¶¶Z‹oÛ¶ÍT @™ííÛ·›„Ì‹/ ÔwjÇÏjµqG?ûĉ%‡vn¢oþ¤Ú¸C”„¾÷UjWÞªU+Ó’\$@áO€ç·ðÿŒ¸‡$@$@$àŽ€ún$}À%ÂÙ…Oîܹ½Þõ¢ZÃpVìÛ·/ž M 7÷pı Žìixÿº[·n¦ ^>­§…Ä|/zh«ìÙ «íï³ÉM› «ph·”)ÓÐÜDcÜl_¿~]FŒ!S¦dÒׯê ìT™:õ5—®ö_]¾¾®š Ëé°heÙ²Eä—_D³™D´bŽËؽ[´œÇ¨Q Óªq*èJ8ÝÝu}6ëÀIû9=Ú¶µ94iâ—~7lâ)W;Ÿ`è-mæª}WÓëÕ2DdãFÑ﹫¥nLGÙ?”¸CÉ9”A³7—ƒ‰œêôŒ( .\©RÝXÏÙ+hòಡÙW_‰+æl©Ø˜Æs[l|Ήu”(‡†LTØØ£tìm·ÝæqÓp8‚Ø–A$@Á"Às[°H²  p"Êóû$Ã铎½}A_g£FdíÚµÒ^3ÇïBEÍÄãÓO?•‡\¸!Q÷Ÿ¸mܸ±Ëõ9ƒH üðü~Ÿ ÷ˆH€H€|!G¾ìpR. &ûȘ1£Sgûeì_gÍšÕþ­rÆŒR£F óìkvMÍ ƒð_*¸Û'Î#H\<¿%.onH€H€‚M€‚#ˆ¦UÛ”{ï½7nß´®ÏùóçãÞ{záèh” #ív›"û|ˆPà~ãM@œûY+*$vm$kÃþü¾ZÜÜ®–4õë×—]»v%p¡ öáÁæwæÌ™R½zu©S§“fâØœf,Ñk¯‰™–-›H=µƒ9{ö¬Ô­û¥üôÓ:°+¢Uú’4Ê•³ }PŽ+©¥Ë£ö€ßŸŠ|ñ…hi:‘ZµDJ–÷¼wf.WhÞÜVÎËåÿÍ€à¦f÷ßïiÉÐÎG¹z”,C ²6mlŽOö[Ô$0éW/û©‰÷úÛoE³Ø¼ßžš·¹ ”Iƒ£„p(‘gkÖˆ¼ü²­äšýôçž³9;­Ze?5¶^óÜ[Ÿw°Ž×?Æ zªÂÖõ&Lýû÷kéÃ= 4Û!ð‹Ïm~aãJ$@$@aN ”ç7öI†ù‡¥»gÜ7µÖý“O>i-áØÏ ˆ=<¿ÅÞgÎ#& ˆ.^ ÃG×z4p²ˆR¼~ø!Þ¢ŽYp@6‡pPÚ´i“õÖíóúõëãÍ/%Ã'„wíÚµå9¨4Bér´oß>y饗ä¾ûî3<–è¢N» ¡Lúô7Þ£ÄZÿþ6W˜ÁƒoLOªW(‰®º;CLRÅÛo‹ŠíÄpc§¾‰ DJ”Y±Â¿=N—®S"(Ãæ*ÀdïÞ¤u7²ß7Ÿ €ÊŸ_¤{w[é9kþcÙœ î¼Óš’¸Ï©Rw{O=e+«‡òxß}gkærp¼J™Òö=±ß"Ü’nºÉV¦Í~z¬½æ¹-Ö>ñÀŽ®FÅŠ“~ýúÉúãñ®Ú§Yç´¨OÉ  0 Às[|ø¼{@IDATÜ   Õù}’Aÿ¨Ø 8sæŒI´œ¥öÚóæÍ“E‹©ù2ùøãe°vl0@Ü3eÑR¢Ó†A$³x~‹ÙžN$@$ÂZp„d¿üò‹¹!;v¬¼úê«:XÞ]Þxã Y µu6k­¤£Z‹çŸD¬…óÌ3ÏÄûر_Ž¥Òâ-ðß›ïtäÖ®VäÉ“GR§Nm½{®K»˜2eŠÝ;ç/ÿøã“bÍ…Û@6Xâ0|"€›_|–Íš5“J•*·ÔFà;º{÷nó½ÅÍ4¾G¥K—6V|ðdÈA–,uW©RÅõ;u›Ð´i6ñ„ë%gÜ~ yçÄÙžãV`06uªMH£™W¡?)êÀasõñâß+A›––.J®ŽB¹$e95Ç}»çèU# š@fJ¨a#! àò%ôa.`T¿ÄwUÿõeæìb,|NË—‹@Œ«Ás[ôòp$3fŒ†-\€Ñ®];uÚûI dž[µj¥å=o °U®N$@Á%Às[py²5  ð Êóû$Ãã3Ž–½@_8ÄD͵C}­52Žòø#áýü«-÷§Ÿ~*i¼µ8< x~K€„H€H€H b„¥àèܹsò¶Ú–<þøãq7 “&M2Â#@ Âé¯6//¼ð‚T¬XQ ~îÓ§9r$äàŸÐ‘i8ÒX‡#FÜÅUˆ¼†ÚXvÑ»wo»w7^âF˾ÔÚŸ3gÎ^Áe.9—PCè¿hРõ’Ï>€à%óðBiˆŽ¾T[|ý ˆÌŠjݳTªÊÉ—/Ÿ4lØPÅCä£>Rç¢ôæ{7ªÓ§me¯à΢›vZ­F&N ! \qà³}»íárÇC4cÆ Ñ²†";{¿¸ iBSFÌÁtÌ«FÊ—A°¶m]/7!D8 ް?pgBi1ˆ¦¶n¹|SÃ;TW*™3‹fÄy¿ŸprjÑBdÝ:›“J­uì(ââgWÍl,/ö~Ѷ$ÏmÑö‰Æ?œßzè!éÚµ«þv¹ùñŠ¿šÓw¸æA{5kÖ4Ù¨´¼wЉI€€Ïmað!pH€H€‚N ”ç7öIýãŠÙkK©R¥´¿ó´¼õÖ[ÆÁÓæ«EúìÙ³Óû{ï½§‰qëMf̂ⓠÄàù-_ @Ä;ÁÑÊ•+¥¼Žè¿£–)gÏžõ èßÿ-¸i©Zµª–Íé)‡òj=‚ÅðÀã­:tèPSV䲓Ñû'NȳÏ>+;vìˆ[ç)U•/^<î½ã‹6mÚÄ› ÷œÐ62D¾zâ¿È™3§™f½ç³w¶lÙbÊÁ4Öa·@ Ì.0‡Í¯?.ˆ–àlT¹reéÕ«—¹©Þ¹s§q6úñÇ¥}ûö¦i¸«À…ÅÁ@+ÁfáÎàXq‚6ðß!Èøñ¶äûújª!“'‹ ´›/qÿý"(a‡rl¾PYe¸\GjZ¥™Z®–HºéwÜ!òÉ'¢d6G­¤Û“[†³PëÖ"#GÞ˜f½ÂgtíšÍ™ÉšæÍ3\œ`"×£‡íËÝ:õë‹ &*6t·TtÏã¹-:?_œoÐaƒk…ëZ{²dÉ’²jÕ*ã©Ï@Ù4¸eVàôéÓýh« @âà¹-ñXsK$@$@‰G Ôç7öI&Þg­[B©´úÚÑ×¢/Ôüå—_6 +uêÔ$É¢ïõùçŸ7‰Ä™2eŠV <.  ðüæ#0.N$@$@aDÀ͹ç½ÔòS³t)õ†NÀ¹åÒ \œôÐQf8 …*°ŸŽåÎàbƒl ¸\½zÕM08A”iÓ¦U¡ÃRã¤cMsöÜ­[7Y±bE¼YY²d‘ jZýõ× à20Sm@Š)o=_ßàfdžŒ“X ¸DÁE v¿>ú¨9ldáÀñ7Ä .ô œ‘ªU«fÖùDÕðuXtíZ1NGp Š´([V´A´ã@dôè„e«"íxÙß‹EîºKÔÍ&j ¤­XY¥Ý ¦ÓŸ6-£yã¨yðAQª¨HâÆto_©NSTƒ©" o×°-÷È#ȦM›äÎHügôíP,Íç¶oÕš –íÁ*•™^M@©U”ïœ[< œã ^Æt\£ÀrÛ¶m>í1®eà< ‘óZ=a•Å?ƒH ¢ÀaBú‰°ËŒ¡ˆæsÛ~­Œ²–þ IcèkÀC%ˆRè¿z÷Ýw=:Gãá‡òü–”}’§N2ýiö‰›ÑøùEã1!åÓ,X …Õ^|¹fW¢/›A$àô» á=ú¯œ‘‰ÖóŽãO¿ÿþ»ôíÛ×Ù¡s D Tœ‚) ~Ó¬Ldðcþù§V§9÷À¼¬Y³Ê÷ß1ÇÈõ‰@–d>-Â…ñ%;v¬Ó-ܯv$¸AA ª»t$_RÜ€BrìØ±x‚4ð¯ZÅŒT« ¸Ó´†mFeIòäÉcô.ÀžCã¢* pCìꦥµpÁäMöÆ AƒÌ?ä† âöÇŠ‡³@ °ñj1¨ØÈYÛÑ>íšÚ§àfb.Kl„cΘ1cœ–Iž<¹W(ÐáR3pJBr8J¸ ”ƒØ¢ŠHÕ7 ª`‡¢m%¬T/§ŽNáã ãްç©Y–þö„_9µ`g0Ûƒ[”êúŒã”²èÿ¡­uh%ÀR“áüЦMýZ-¦Wâ¹-ò?~ˆ\!¸Æ5,ìáiÛp ñ,íá Y·n]¯¥`!vîׯÅF^Sã‚$@á@€ç¶pø¸$@$”^‚h"†@(Ïoì“ä·ÌWGU×ögLŸ8Üf̘!·ß~»¯Ípy žßø%  ð%ð×_É+¯¼"¸?sÐ,ÀíIý´Ì=÷Ü#W®\q· çE8›Ãaÿ!æèÓ§ Yû· ŠÁågÍš5æFbþýû«ƒÊhyÿý÷˜¥°†nDp6²,rV¡ 8Ø@iþØc¹Ýö«cÇŽfŸ½¡1ÿd­…õðÚ] <J®•.]ÚÝbœç‚²½¡®DÉÇ@Y5Ê>ÿüsÇYNßã»Z½zu¹õÖ[eõêÕÅFhD7oJFAp©„¥eËDÿWEräuÒÉ[Ô%Kî5Ñ_}%2o^Â#C95„S+ÛBüGÚP|_ðýAàÚCÖŒCÑfa¶ür<·…qÈ6ðÙgŸW>¯áx·=KldmYTwhmE<;–jµ–q|†xv̘1Æáȱ¬¬ã²|O$@áH€ç¶püT¸O$@ÑLÉrHì²wüö÷xQŽ©eË–¦ÎŒBu~cŸä Æ|e#€lõ%K–QðÿøôÓOK‰%´'‡Lz@m«-W–ùóçSlÄ/ @@x~ W& ؼy³k€Ø¨råÊÆ`eúôéF'Š!{öì1Iи¼té’üúë¯òÓO?ÉöíÛ† ÑK ,Ž ¬ùÅ®ŽÊ’Á­ÎFžƒfÈÐÇ.Ip4‚]BK¾™"sçÎõÔŒßóï»ï>™3gŽ×Ú??üðƒyüüóϦÊ–à‘[•©S§öy*uPÛ˜-Z víÚ%'Ož4ÿ¨Ø.ø”W[œ|ùòùÜ6W¸Ab-¸¡†¸càåù`\µjUÇÙñÞc@Ù<ÈàØÈÛÌ;½_håTÛñQ¡‚hY:Q±œ¨û—Èk¯‰<û¬(ßàšVE’¼yE6 n»¾´Ö½»ˆVh’zõD´ša\@p`¡Bq“øÂ ZÅLð°?Û¿ý&ê¦"¤ÄÕh˜Ò€×®eNŒÍ…õ6xn ëÇéÎA\„s ’ÍŸ?¿Óåî¾ûnA‰”—à ''HÜ<ÿüó&×;8_2H€H  ð܉Ÿ÷™H ’@ÌŽ¾+”8[¹r¥\¿~Ý\GÂéÄŸ@ŸúÄP& vèCb"!„ Ù²e³ÞòÙÜPNQk‘Ù°‰òÀ ô½÷Þk„[øž8 à`{à›\(ЩVG-Š €ƒË‘££„³v­i¨¸†jmŠ=ªâÜ9Q«héÁàÖáÃ6œ—{’ÅÀ¢'YÑÎNѬ®»÷ˆ4irc_ùN‚-ý9×2’¢Ùr¾¯ïÏøì\´|ç{ºíºF`áO;\'< |« AˆlàLmRg øÔX«5:=•WÅ9 ÂÉT-¹oß>—ƒ5pJ‚Ø"Ú… ªÀR–  ˆ%WÏ?þX&Nœ±ÇÀO÷¾­Zµ”tf @R8xð L›6͈ÙOœ8a:¬áL€~>\›:Ô¸kú²è+|ñÅMßTÅŠÍ5üÕ«W35œÐ (`J#ù§PçN:%øþìØ±#*Ž'ÒââÅ‹&!ÿg–ÀƒþeË–5ˆÿ2gÎl\"íØ¸¿$),·°h쿊”Ï Tû Á4Æ£à:Î ˆ ¸žÂx{Ïž=Â$ ãÞ)·ôíÃQ  Ù?`ˆb$'ã±aÃ#tB?¿³@’Aúôéãà…tPh6òèÀ.*ùÀ¡è¹çžŒ? Úî»°¬¯1ˆ6mÚx]MÈ×ö¹|’ÈbçË‘4;säÈ‘8±ö¶¬þа>ÐЙ/®耥àÈ¢Ág{ó´&ìÝš6mj?9Þk”U{M­zÐÙálY> Õjµ(Ñ™öˆM‹&ôÉÞ½¶²Pšüã4 røOoçt~¤N„;ž£Cž¢Öu"éÒùTo¿-š))Ò¹³ÿmcM53‚#TÛ³A@†Ãz dœ²´¢d¢‰°·ø¡M=z´º–øôÿ¹& $&œƒªT©bÊ£A8ëì<å¸?p] 6tÈë­·¤W¯^Ž‹á6n& 6Â5ÅF q Ät–£ïÇ4îÞxF–îwjsŒy>ø q‡K7 èBk÷ïß_råÊ% 4ðŠ:Ãá «~\ç")1eÊ”¦CîÓ#GŽ4mâºÎ  ภv{mܸQªW¯®N쵌Èÿ¿     ß@¬ƒûP±¨¬ ¸—.]jÄ;¨$!·¯{/ŒG£Ò’³À}Ó•+WâfÁpýú¸/CE„sêÿéÓ§ãž!PÂöÓ ¸Yb¬{÷îÝríÚ5éÓ§ Tˆ$àŒ@’ Žðg(ah@}'+cçÎ6Éõ£”Ê©aàªRWa ŽÐ±å8{öìYsŽÜU«VÅi›Ú‡‹:E‰Úä‰ÎwµÑ2l®çEÓ”YSäæQ®œGÖ¬™ÍªR%ÿÖÖZ§ÀÁ åz®e‰*bjÿ±)£ÁQb ÌÔ OFÞ«^…æs_¸-ð†lP+é!sŠo"¢1cÆÈ¨Q£¤mÛ¶ñ²* ž…Ø7Xîm(=$@$@$@$@1IFpSÛ¾}»&i‘]dɒʼn<'"{Whôµàµxñ⦴ZÖ¬YÍk»Õ¼„Øè…^÷ßß–h ztv[ö{÷î-ÅŠ“FÅ ¬ù|&ð2îán»uëVéÚµ«¼þúëþ5ĵH€H€H€H Æ Àä}î0GÁëŽ:Ð5|øp3=}útóâ#x äË7ñÎ;ï˜ë4hÐ>Dá¿ýö[‚J¥aœ L™2Ƥś¶±Ì¡C‡U"à´g=ã~û\ªT)o›ár1J ¬G°ÿÂ?B ²V9sæ4õÑl $àH ÐmÛ¶™Ž/ØÌ¹Šª,AMKކ ·ØuµÙ’ô€ÖÏ‚%Þã¨Åd0Œ€ØH]æ¤K»1ü2o^‘óçE;"EíÏEj×öÆ£Š–¬ó}½`¯2x8ÇjéSUøÚDPÁÞF,¶×£‡ÈÊ•¢Ë¢L‰O¢¸ Ú«¤~° cÈ.Ç n*PîÌ×úÏÈFÀMOãÆMýe8ùἆ²s¨ÇŒ"X³z›‰ƨ¸k$@$@$@$@~8yò¤¸Ct„Nqd¹æË—/îNÏîÔ–0É\èƒðÈYüóÏ?šÒ\ûQf ’q›7ÞNå„Ñ^·nÝ€\Ò4ÍI$sL‰ûI8»cÐkذa1Ç€L$@$@$@Á ñ6\à„û¦©S§je u/ø/\QRK¤<ûì³&yâs-¡‚2epˆuh–><Œ*Oè³Gy³`kñpgÐìm²½è!àl.„Ç{ôèѸÖ! VäÎ;®) ŽâPð…¸!šÁ2ÇM@]Z£F cŽN6+ºwï.kÖ¬‘víÚ™ˆ5ÏãÆ‰–a!‰ÚЉڀÛÏÝר\§Y=™Ú\Ÿ"ʪ]¾,‚²xp´R7yóéÇ•”ûÿÊ+¢Ên‘Áƒ“r/¸mop4‚Øèرc2cÆ oú¡ÞÔCÄ ê2Ó“Öý!à :—qÂ,ŠÂû{À½#  ˆè‹°\¼9êýû÷qù×_í±K„€udL”ã…&®<‰¬ À…"¢3gΘ2Mç‘…d¸îì¢YZ(3€åÐÁ½hÑ"—b#kUˆ™ šf_¢Õ6ŸI Vàÿ²œZCl4X;b(6Š•OžÇI$@$@$`€Ëj ±gÏSº b"T%ÀuîsìÅFÖ6~øa“ˆÑ¾}{­ ²N •N:ɤI“Ìû'NX‹÷É‚ ±úò‘t ±QÜù‚ü$ä‚£»îº+n×Q3Ádþ[Áš‚‰Ø{†  ¦È~Ã;jTfÏžÝ8iÔºMVÝLOd‰‡øðÃÍ3ì½ÇŽk,éÞ|óM3Íúç=7ˆž34“ÏVvËšg=«óZ€‹ZçÙÜq¬é±ð¬\ãüäÆT*˜”ÁE(Ü‚#ʪýø£H"ýúÙ¦ñ¯Tô­+6g0ÿZàZ$ýuŠØÜ7iÒÄïFI ¸¡®36nÜh{6©uΕ     ¤'€$'\›=ðÀÆ~Y°pò6®^½*óæÍ3ý"°Ýǵ$:ÂÑ'âªs÷jj;‹Ì\\s"£6€@â õÆ}4‡6ïÑGAúW B© ûñ¡ÍuIÀ;(¡¤“ï¿ÿÞ”åèß¿¿w+r)   ˆ&L0‰¸G»«¯2dpi…ìbFòÄÎ;{‘»{”?~¼,]ºÔ”TCbÇK/½$åuÐ1sæÌ’&M#,Bi4h'Þ}÷]™;w®™îë>ryH I^Ríî»ïŽwœøGDfE šˆ{÷îk"]ºtq¯ù"¶à6ÜiÓ¦5åaR¥J%ø>@h„r1è4ó¦>f¥J•%ÿPV ƒ²mÛ¶5}Ⱥ³?iÀÍè¹çDM"Ÿ~*º-ç¼?ûLdûv‘K—XŠ „à§ g"$ˆyQ‚í¡‡DU¼":>6×B³i¯ù̱cvîˆa³ŸÜ è!'"Ôk.]º´É|ôȪ¨ÎqÈŽ€[ý$@$@$@$@áA —ÖjŸ8q¢åÀ}x _×mèІU?ú%P~ ë5œ‰`áwg$÷a:Ò‘P“Þ½{ËgÚ9ùèÔ¶%«üY?ͨéÚµ«5+ g´óÓO?™ÎrXõ#Ò§Oo\£›ª²³ì_³ÿ XªW¯nYHù ì¦$@$@$@$#P©E‹ÆdãÇGƽѨQ£Œ£+uÝ„ÛC‡5÷6×Ô-ýë¸Ç*Z´¨»ÕÌCbî½`¢‚{%h쟑 û5Üó1H œ $¹à™Löú† Žvi]#ˆŽ¬È–-›õ’Ï1F' dBeêéá ÄF8a|òÉ'¦t ÚZ¶l™Ø ævï=1ØDº˜dÍêºE]U6l=ù¸^&–ætè :Ø-²j•¨B÷Æ‘kÒ£faŠ8 òâ‹á%6Â^&Ó_Ð2eDV¯ííØÜؾ" `ÀÍK«V­Ì 9¯Ùï×Ǭ.r×¢\ @x€:¼‘ô„Îo\«Á!Y°xÀyO‘7o^uâí'õdÈÁ,¡@Èè……ÿ´iÓLG7œ“6l¨I5ŸK½Q2dˆ§æ}šíáºóâÅ‹š¬õœqQ²Oâò©1.L$à9sæhÛ‹æÿ‚F¼f @¬À½îPº ÷$¸GY¿~½ Ä®‹ ðAIiÜGÙJÑbŒx…–¶ÁóeuQ@Ò\ZÑ5 ?«(ãQ¹reûMò5 D $*TȸϜ;wÎ@›9s¦äɓLj:ü¡Ub÷îÝã­ {XFìøê«¯äàÁƒ¦-ƒ²P™¢¤NB¸9Çw׊ãÇEªVQ×qY¹RDKjº ˆcŸ|Òí"15•Uk¨'S›èèÎ;Eöí³‰Ž=¹‹²‡'”UÓ±zÍ ½°pîÒž{ν"ˆ4È’Ø­êV™fíÌPWM @⸤6ë/¿ü²Þwß}¦“}æ‰ÿ9p‹$@$@$@ICÉ(!‹Rϸ¿‚°‚#DÍš5h¨oß¾ÆQã¿={ö”:uêè˜ïJsßµmÛ6S’ú–[n1÷XÐ"`= €t$5”³jÖ¬™ >!âZ[ ¶Îø‡õõ5æQêê ÿhhËlш­çùóç›Fv^0âé§Ÿ6¶åíÚµ3vV›ÃèyGþüSôeÉXóøì;×Òv¢„¢NR"cÇŠÔ¯/Z›T4cS¤IïÚIŠ¥ 8B ¬öA$@¡ ðÃ?Ȉ#Lz=B± ¶I$@$@$@$Bèà^»v­¬[·NJ–,)O=õ”)sæ¸I$8!»6wîÜÆÙè.dè8 ¸9c¹@ýßÿ½Éð…Ó ÉVï½÷^ÐÜ4Ù?®K$pGCÿ(ž«jÆ$ÜÑì]Ûƒ³¶B$@$@$@áIà€–QA2Œ*Š+fL%räÈogS§Nm´ !µnÝÚ¸½ZޝHæ¨[·®Ñ-T«VÍ”†Ž·2ß@ŒHrÁø·lÙR-Z$Ça£ñï¿ÿJ·nÝLÆ~P—ÞÊæ2 8üÁzP"¢|DGöѹsgI‘"…ý$¾Ž®áû€rz¾ÖÌt…Öã¿ýö[‚N7ôýeÊdsáH†á8µCt4x°­,Yòä" ˆ*ˆýk/±Ö*P@Ô•ÍVJ/±¶Éí Ä\áZ Ï(wÌp @dؼy³éÐ^ 7¸°á·"mÚ´¦ÓºqãÆê€ü¤Þßl2gŸþyÉœ9³–î^-3f´Ù3œN°­1cÆÈÞ½{ó¯7C†› “@¢À=dÇŽÊ4"?Nð‰~ Ü @̸zõª¹wùî»ïLù½÷Þë‘ îà ‚~ W¯^FHäî~cÊ_ýµŒ7NŽ=jÊ@ã~<¢æ1L ,F¬ zçwŒu™½`hÏž=2`À“ÑŸ={vÁÇ=÷Üc\f ü€ÐÖÑû÷ï7ƒpŽŸcÅŠué±G`Ë–-æD€“G0cçΛ4Ë0~Ù¬zõln<(“ÆŒÀ A"êì.Ë–‰¼úªè‰<°öcmˆ¤´ÂƒH€BF.Ⱦ@Çðc=²í°a    À @$þí·ßÊâÅ‹eîܹrèÐ!ÓhÞ¼yM9#”1ûâ‹/ŒiêÔ©‚D?pùž9s¦éóZ³fÀÁ(±b'$þ1H€¢‡’1Q àÝwß•¬Y³Ê¼yóX z>^ Ä óçÏË'Ÿ|"K—.5Ï–Ž¥Ñ«ƒ„Õ¨šäW®\‘N:ÉäÉ“¶`É’%R¡BÇÅœ¾‡ †&  ໚G-BpôÊ+¯h%­£d—/_6–¯°}õ6J—.­e™Æš 1o×árÑCÀ*§Ö Aƒ ¾~ê´§Y":Üh‚FðhEE-«¼öØ D2ƒJ¿~ý$gΜ2ªL @ØÀ5\‚ ú\ëmÿþûïf!B9\¸w,X0n¿‘5 …fÏžm„IèGù´U«V™rjq ó øHÀ^l„j(ÕW5 $6k×®I»víäË/¿4‚!ÇRf®ögåÊ•2~üxs…6$Q¢D ­ŠRÇ8ÂöéÓLj‚¦OŸnLM  °÷YÞµk—TªTÉTIÊ„R5  ÁŽ®pᦃfÆŒ2eʹxñ¢Ï%KéÒ¥‹T¯^Ýçu¹Bt@6!JôåÊ•K *´ƒB©¯¿ÿÉŸ?hM²!  pK M›6á5®‹n»í6·Ër& @ð üóÏ?nˆˆÎž=ïqêÔ)Ù°aƒ8pÀlàp¤„«ÈSO=%¥J•r[ºèá‡6–þC´ÆøŽ;Œ ß  „@Í”Db/ÄFËÔFÕ$@$@$@$Øpÿ„JD¸gB”+Wθ½fË–Íí®À÷Tp.*_¾¼i£V­ZÆ©ÈZ±víÚ2|øpÓQ™2e¥©ñB%œàp4tèP58èMs ŸI DÂJp„cL©õ”^|ñE£<„rÔøQðiÒ¤1ë5mÚT’'OîiqÎb7n4¥öà¬ÐþEùã‘5D´T'ƒH€H€BNn}È’GiÜŒ1H€H€H€H€—ÄFèØ†…¿«@†.:Ñ9‹Îp]DX:×aN'ð…J‡L˜0A*V¬hJPlä =.K$@$@$,?ÿü³1Ù·oŸ)m†ûæÍ›Ç‰ŽPòÕY zŒEpŸ…¾ñ|ÐÙbFO€’jÍš53eÕ`f‚þt$ïœå­í]œ6‰$@A!v‚#ë¨Ò¥K' þýû›k‡<Ž9"'Ož”Œ3šØSãÇVh7Ýt“µ:Ÿc˜€UN­aÆA£ å:ÕÖ\Tü´&Ù ¸%·>dÉ#SƒA$@$@$@$øà6 ±²r+T¨ 諲¤OŸÞ”AKü=ãI€H !îÝ»Ë[o½%eË–•åË—›¸„Kq „–ÀúõëMé³ .ÈĉaˆµE8áZå‹/¾ŒñÛÇ AƒdàÀ’/_>SéÞ{ﵟíôuΜ9«Ñ’%KL9ëüZ¦I¸Wc $°Y‡ÄDx+VÌšÌgpJàúõ릜ZžúHn¿ýöðÙ9î @ÌÀ=`q-òñÇKåÊ•ãŽý¹çžŒã¶hÑ"ÎénDˆnݺÉo¼!EŠ‘O?ýÔgÁP:uŒÈ)nc|A$hnN´-qC$ š=}ú´ÓÝ(v››   x¾ýö[ùý÷ß ~¼|C$@$@$@$`ü¡uÏ'Mš$/^ :‘É“'ËСCMâÛ‚ (6 :a6H$Lp€3n‰%Œ+[ªT©‚Ù<Û"   ¯ôéÓLj‰ "Ú¼ys<±‘ÕŽÞ}÷]9xð =zÔ” 6zâ‰'díÚµ>‹¬¶ùL$4ÂÒáêÆÝ»wËöíÛeÛ¶m2jÔ(—Õ°HòeÊ”1A)iA“4ߤ0Ù*:Á?.j?,zr “än ÄÜX!*V¬Ç˃$   _ìܹSêÖ­+û÷ï—Ù³g›ö;î¸Ã—&\.ûá‡Jûöí%W®\B——˜8ƒH L`0åG,7€`ý†Éáq7H€H€H€"„À°aÃdĈR²dISÚõî»ïv¹çp8‚NH?ü°\ºtIªT©"ó§K£KlœAaK ¬GÿûßÿdÚ´i2a„xjøÑq§N’Y³f™GŠ)ŒúqÀ€¦›«u8=: üóÏ?²xñb)P €9Aã(»t­ý)òóÏ"÷܌٠x&°fͼ¦”ÇÜóÂ\‚H€H€H€bˆú€Ð1¾¢5jQ:§WêÍûwÞ‰-[¶È³Ï>k2jaãﮓ<  qe ·ß~[nºé&Ó7èo`v‰Í Ä™3gJ¿~ý¤P¡B²jÕ*ñFݺukù÷ß套^2¥ÐæÎ+É“'1r<\ˆaSRíÏ?ÿ”víÚÉèÑ£ã‰|Á|õêUÁ]íÚµU›/ërÙÈ'7”ŸiРAPF³dÑ"Q÷,Š‚” xE×37n4"j:7z…Œ ‘ Ä¿ÿþ[:tè Íš53‚ /¿üRV¬X!½{÷…*Uª$çÎó›ÄO?ý$5kÖ4åÓ>ùäÉž=»ßmqE ð—úÆñ›æMWkv$_â÷î    Hl«W¯ˆ‡²fÍê³ó,IPZmáÂ…%öÇí‘@ „…ÃŒM›6tî#Ξ=kjD<8hâ“`ìÛ-ùóç› «œš~}T]+2p`h÷›­“ €=M›6ÉåË—YNÍ _“ Ä4 ª×«WO¶nÝ*åË——yóæÅ¹ >\n½õVAP… Þé=ÔE?}ú´ìÖ,£={ö˜g¼Þ±c‡I€ƒˆé±Ç‹iÞ ‡Xº-†‚2Û$È ä‚#¸?>­Š+Ê!CÜ ¬îºë.ãb„2Z›7o–^½zÉ©S§Ìì‹/Êĉ¥oß¾Öâ|ŽRŸ}ö™±NÇçŒÐ¯Ý‚’m øLƒaK£æ5ƒH€H€H€b•ú‹ .‚˜(UªT²dÉyæ™g\â@ßœŽ J*W®œtéÒEÖ¯_oDF'Nœ0ëÁ-¤hÑ¢’?~É›7¯á9K–,.Ûå  H ׯ_—¹sçÑ… Lß8*¤H‘Âéæáôn 1o¾ùf§Ëp" x"sòäÉ=-o>JY?õÔSf<~Á‚Rºtéxóù†H ¶$¹àh×®]ràÀ8êÙ²e“1cƸ¼™Š[ÐÉ‹ÇÜÔ­®Q£†üñÇf ܨ¡d† œ¬ÁIÑBÀ*§áY ¡‰¢çGº ’ë“ øL×/(çQ§Na§±Ïø¸ @8zô¨É|=þ¼´hÑÂmÙ3$’=÷ÜsÆ•¨`Á‚z¾@råÊåñèPŠå;w––-[šå!.B_’Ûà¢:ujíp HlH<ùõ×_È¿S]»v5F®Ê¥7Έ1ñ{Ê    O®\¹bJ¶þð±y<ãqìØ1yñÅÍØ|Ê”)=5#—/_–§Ÿ~Ú´õÖ[o™’jWâ$@QM ÉGGމh®27â-èâ ,³‘ÕÖ½{w³¬ÜöîÝKu¥ ^Ñ0NVK—.•%Jȃ>ð!½ñ†ÍÝèÕWnŠ €O>ÿüsuØû× ˆù´"&   0#ðÏ?ÿȦM›ŒÈûè̶bàÀò /¢ìÙ³[“Í3J¨5nÜØ ¼£ã{ìØ±âMÇ·ÕH§NL©u8„ ¼Z¦L™¬Y|& °%`•SkÒ¤‰dΜYÞÐÊáÇñäí·ßo¿·nÝ*Û·o7ƒƒpÿg €+pQìСƒ¼û×Và e¥3fÌhª¡ŠÌzè!k‘Ï(QýÒK/É/¿ü"ݺu“—_~9Á2œ@${’ÜonöŒUªT‰ç pèÐ!ûMðu”€­ú_ý%Íš5 øÈT»dÜŠµY¸96@$@$@>ÀMø    ˆ4þù§Ì™3Ç8 ÁiºlÙ²òÚk¯Éo¿ý&Í›77NEóæÍ3åÌÞyçÉ;·Ô¯__¾úê+#ºFù4\]ºtI°Üĉ}Y¼à|ݨQ#Š, |&kV2%ÜûsäÈa~÷úõëg„—ãÇO°ïp7B`ðA$@$@$@®\½zUêÕ«'“&M’b:ð‰ÄE‹£Œ«~óÍ7æ^lÈ!&A¤H‘"2k֬͡Œ+J½â^ åªGmîó,È $@1I ÉŽ`ÕfE²dÉL‡õÞßg8$=ðÀb >ìoS\/¼ÿþûÆ2½aÆïíÂ…"š©™–7ÅH€H€H ŽÀ¾}ûLöÇ„ Ü–Y½zµqëC'3ƒH€H€H€"ÀÉ“'eùòå²lÙ2[#œ¦Q¶xñâR­Z5ó(T¨ÜtÓMq‡ƒû÷õë×›ŽêÅ‹›No8z?~\°,J¨åÌ™3ny¾  h&çvˆŽPJÒŠV­Z™<ˆ6áö–&M3 e×j&ÜòåËg-Îg   !€rhpFlÛ¶­8ºÅÚ#€ ¨V­Zæ Š3fÌŒÃ;îÝ tFùi$mÀÜ÷uH¹í¶ÛdêÔ©Ò³gO9wîœ ±bè¬Y³:6Ã÷$@1L ÉŽìÜ`·Ž©`„}G”—Œè$€ÎHœøp’K—.]À9}ºè Tô¤pSl€H€H€â ŒÈš5k¤cÇŽqÓ_Àõv´t7r$Ã÷$@$@$@áHà‹/¾¸q@([}ˆ*Uª$S¦Lˆ`ÉŽëÂ… ÇYÇ÷£?þXÐa÷£³gÏJûöíeË–-YøL$0hxë­·w8ë€ñ~À€òûï¿›Ò’Öt8 ÿœ%L,"|&  ð'€Rf7n”'žxˆ’Q­{÷î—YÇ€Ã,ÄÉ?…#"\‹ìÇã—Ç{´»sçN“0qÜŽ0­M›6‚ò®HY±bÅFÎàq Ä8$Ý}÷Ýñ>‚Ä{ïÏü¸}¼Ã†ÃJOŽ3ƈ2!4šúè#Ó.û·nÝjDÎ{öìѱSŽ ’*U*éÚµ«SGGt2ãæÙ'    W(ŸV»vmI:µ Ãb#”H»ãŽ;Úeo;ÁÚW& 0#€¾p¸Ø—S³vñ–[n‘Aƒ 'QZ ¥Ô Pj×®)]i-Çg   ð%°mÛ6S2çp„ü ˜/X÷`ëÖ­3×Íœ9Ó$lÀŨ@&‘£téÒ²wï^yë­·Ìu„¯ÛÃ}ú¯¿ûî;“`‚v½×óu¸< @dHrÁQ©R¥Ìœ…mÉ’%ê2£63~lf‡omX¾1¢ÀŽ;d÷îݦ¦(l† ôª ¼+hK\ŸH€H€âøùçŸ6·½{÷ˆuâk×®57†ŽîŽËñ= $ v׫WOà$Žî‚ &Õ®p»$@$0€x§Z­»r,‚ ˆp'9r¤ÜvÛmÒ²e˨8v ÄôCDœ5kVS&õôéÓ>6?p=¼ï¾ûLÂÇc=fÖ‡0ÓÑï ò‘#G¤E‹rüøq#D ´üjÞ¼y x"ä‚#Xe7hÐ n?aù%æüùó-\Ü /^œ={Öü˜Ú—SË–-½`‰‹ÀÝ*ƒH€H€•À¥K—Œ•-¬ð‘òàƒš›@ÔÒ¶b×®]rêÔ)–S³€ð™H€H€H ì`P¼Q£F’Ií¿øâ yä‘GÂn¹C$@$IHùÍ7ßHýúõ]–“Ä`âàÁƒ÷•¸o„Rºté"é0¹¯$@$@$³>ûì3“¨Ñ¼ys#6ú믿˜f¸ƒ3`ÀéÔ©“<üðòiÓ&SjÕqy¸êc9ºuëfÊ\7mÚÔq1¾' HrÁŽ #ûÕW¯^5?ް‡›:uªìß¿ß-Üœõë×OÊ•+glâì†r”} Lƒå0Ü"Š)}È#" ˆ¿üò‹üïÿ“‡zHR¦Li¬ðÿøãs­c$Ê©!*V¬hMâ3 „ iÓ¦ÉóÏ?/Y²d1b#\×0H€H€#!'ÂY95û–kÕª%E‹5“:vìh?‹¯I€H€H€”úƒ1FþàÊ3Ï @´@ßö‘#GLß&ʦyŠ9rú»$Í®_ùóÏh>B @¬@•–þýûKš4iŒË‘uÜ*T<0ƹwï^kr¼g8áÃlÉ«K—.¥Ø(¾!Ga#8œR¥JÉêի套^2sþË•+—Lž<Ù¨D!HaDsçÎÉŠ+Œ²÷þûïø§OQÓ,µ3 ¸)6@$@$@  ~6Â^pT¨P!yá…Œ³¬uQ¿›åÔ ã   D&€D¯Ö­[ îµûöí+·Ür‹Œ9R¶mÛ&™3gNä½áæH€H z x[N-z ðÈH !Õái¥ Ñø„ó‚9åêU‘={DPù€A$@¡ ÷"ô wëÖMÒ§OoH츮 Ë~ýúÅ›Ž7ûöíTïAe Œƒ¢âƒH€Â@X”T³‡[8dû7nÜØØÅ-_¾\®]»f¿ˆÓ×™2eÔ³D L œ"Šš‰óçÏ—«zWЬY³€ üàD\¾¼¨È-àæØ $ ‡#ÔÐv´¾6l˜,X°@Þxã ³G Ðq @  ó ^»ví2×%èÄÆõ‰õ géõë×›-Ây}3pÓH–,캎‚H…M‘ @â@¿&ʬ.\XòæÍ›ø;À-’@˜бuuyôÑÐî ¶ƒŠM›†^ÜÚ#aë$@áHàòåË2xð`ɘ1£tîÜ9Á.+VÌŒe/Ö²+_ýµ)RÄ,sþüy©Y³¦àù“O>l0H€H „m¯~ˆ‡*C† ‘Ó§O‹YØÌâqâÄ SzíÁ4öÞÙ²e޼±Ÿ„…û螬S¥JaˆŒB1áþh8—H€H Ú ›ÉŽkd²ôìÙÓØë-ZÔq¾'   €  Œ+JØ÷èÑCÐù]¼xq¹¢Ù7pXûLþý÷_Á½ʬ½ùæ›R¹rekQ>“ @عàiùÕB5)3dÈà3ˆˆ0 ‡â|Æu+ #sË–-š}Ð4SDÔ,ˆH€H â œ:uÊt$£æ¶³€;ã¬Y³ƒz(Y    `8zô¨´hÑBÖ¬Y#HÖš1c†”)S&Á&ÐÁÝŒ á *)S¦H»víL_7GAEËÆ¢€ÀÆ"zéŸ~*ZRH´†¨C´h¿Iܬ¸›6‰–«·¹饎ÇP¶¬\i[LsÛåða‘¬Y=®ÆH€HÀ+£$5 3Ú¶mër8bœsæÌ™²nÝ:ãhW#Ü»¡¿˜A$@‘DàæPïìæÍ›eÀ€RºtiS& u+ÑáÅ  ŒrjþlŸë €/PN ‘;wn§«¥Ð½ï¿ÿ^¦M›æt>'’ €¿ .BÄFmÚ´1×ÎÄFh¥é)6ò—4×# ï 8Ð >BºIUwß}·w+r)ˆz9Oüóú뢎"K–ˆ õn@Ø¿_Dÿ$GÑq'­X¯Ž7æ»{õÍ7"¿þj[ËÑåÈ-Î#ð•Àk¯½&gÏž5%Õ’'Oîvu\`™&MšÈëúƒWªT)™8q¢Ûu8“H€‘@ÈGÖAÃÂ{ÇŽ2jÔ(©X±¢ÔªUK`+g ÄYËñ™\¸~ýºqÈ’%‹”/_ÞÕb^O?sÆëE¹ øEåÔ®Ž0%aAA$@$@$,_ýµ<ýôÓò /gà•šÆ?yòdº 0Û!   O³uëÖ2hÐ )R¤ˆ A7”  ·´ø…ºˆT©"¢æ`:(/: /’3§èÿ“h‰X‘îÝEôÒGEÖn›Š›i•SÓjF&(8ŠCÃ$@@R)Ê¡=òÈ#FDä©9¸ !1e®Ðz’KT]éI¤ä©MÎ'`ÀùU XI¢â9Ñ$&ï…½ÁØ>Ûˆ<ÉB½ËÅ‹—?þX®^½oS¨C‰Ç8-‹ÒJ•*™GÁ‚9ð߀j˜víÚU:$}ûö5Ù—9q–-ÌW_ ¤%®K$@$@® XÂjw‚#×ks xGY´³gÏ6®‰;wî4+¡Tú\îºë.ïáR$@$@A'pùòeiذ¡–…Z!U«V•E‹IªT©‚¾6HÑJàÖ[E/©PAdÎÑÿ½ÄÑRD¢‰ípiôíÈ_zI${v‘zõDú÷Ù°Á·õ¹4 8#pìØ1©V­š@d^ŽùlĈ²mÛ6ÓÉ… »;î¸#A#ɨ<@IDATG´X.J‰<ûì³òÄO¨äUÙ¨{ÿþûïËrBlØ­¿À8IWÑ4†ýê•Ú_ïð4psòÏ?¶Ç@Ûâú$@$@$àŠGÈLAÆ ƒH€H€H€‚INÒ(—ÖHkÜwß}òòË/ËáǵäH;ã0=kÖ,Š‚ œm‘ €~ÿýwIT0b£çŸÞI›V¤zõ`´Æ6H€H€HÀ9”TƒUþ-H` @ÀŨE‹òÍ7ß—貚bزeKÍ2¬+)S¦ ÒVØ €¿ E8~§{÷î­çšrÎ pJ`êT‘åËE^|Ñél3¢#8*¸‹ï¾¹÷^‘L™Ü-ucÞøñ»ºñž¯H€HÀWó®S§ŽìÚµK¯c _ÛàòÑMàâE‘?cŸ~2b ¼ö×®‰&2{ZêÆ|5Ö2!íêÕ¢eÖoÌ󿕿-Éôé"Z¸J…s"?l[ ïñèÜÙöþàA›¡G®\Þ´Êeb…@ÈŽAÞªÿEPw¢fõ—_~i„EèCY5Ǹpá‚þ~(;vÔ/sqiß¾½,[¶LþüóOÇEù>Š|¢…”sj!æ &HÉ’%@ ™™Áýðƒæ4ðíÇ:ŠóPH€H€À?j¥wàÀÉ;w"l›   ˆ×´×qÀ€R´hQùþûï¥K—.òË/¿ÈçŸ.Mš4¡Ø(¾ª¨…z3y+Y·k/ׄF¨o¾páB­¥¬Å”ƒ°\E Ö3ƒH€H€BEb#d¹<ôÐC¡ÚÛ%  ˆ!p‹†«Ñ?þ( ÔìÃéæ9†ðPI€H bŒÑÚH¼åàcÄ|dÜÑ$"€2iý%R³f`;€òh¨h°`H¯^ Ûº~]déRÑ1%‘;ïL8?˜SPf¦Ñ„{[«GŠ&às l‹H ôíÛW`–P«V-yûí·Ãa—¸aH@‹:©®A¤aCÛyÊ›]L‘Âæ" 2×ëI÷k½û®ÎsC‡ÚÎòúÙ³{ÞŽ¯mrùØ!èGîÐb@®C‡jŸ¹Ü‹zöì)=ö˜±·_ïºþ×lÙ²E¬uvËHýúõeÊ”)rèÐ!ûÅø:B lÕ‚…U† ±‘Vg“9sD Àô¡Œj„’än“ $%”SCPp””Ÿ·M$@$@‘O 9°~üñÇ›ÑPíEܾ};ÅF‘ÿÑòH€¢”ʪÀí}Ö™3gŽÒ£äa‘@p¬XakÇ×Ò/Ž[Gy­,kJ¤9sƒÐá$ýŸ;ÖqÍà½ß¼Y¤B[é7âÖ­E]¯EÞ|Säܹàm‡-‘ $=ŒI£\*ªóÌ;Wn¾9¬†Û“÷À@Á¦O?)_^$cÆ„Pp~p&mÀù bU‡zýu÷NyZdÁ¸éaÜ»JÛøîÝ ·ª)j¼Ì  Û_Àûï¿ßdîÍQuÈÆ¸è‰'ž0™!ŽŸlÄßP/²*úŸT½zu½€{Ódü9.Ç÷áO.W¿ÿþ»)¥н]¿^äØ1Q«yQ![(¶À6I€H€HÀFç4KªÙxð/ €olõz©(P@;_—"EŠÈ·ß~+ȤM–,I «};.M$@1F`ìІÎ;ÇØ‘óp“‚œjר%)B¥S§n>¾îG(Í sèÉ“EP &Uª„{R3ˆjÕlÏÖ_Œ Œ \‰ü 5¡”ªUm Îh§ysÑ ¢Iò"¯¾*rþ¼ˆ%¬òw\H | JO»ví$gΜú¿½B…Ž·…ÏÎqO‚J@‡«å×_ýoÎzZ]ž}6aªO—®]Eïóm‚!Ç%àÆ×»·ÈéÓ6—#ÇùÖûeËlûئ¨ðM$_>‘;î°æº~†8Ûß³Çõ2žæ ô›š/£OËr~t[Á‘=ö 2¨ÕXCUèM¸ß@\TU¯àn¿ývûÅÌë}ûöÉĉ¥N:R®\9ÖÈN@(¼'lþïΙ›¡–S U¶I$@$àŒŽœQá4   OP’uÚ´iÆ%±iÓ¦ÚÁxÚŽp¿œ7o^O«s> @8uꔺÌ$ÎB(Ê P@ù FjÁSF%”ÛrÖ6„6O>)òÖ[¢%…D-åzšê¨ƒC îFÖÜŒ <Í#ˆ-j-m{¾rEdØ0‘Å‹ãO÷æÝo¿‰Ô¨!êp"¢ú“äŒ[­z+(MƒÀ ó7߈4kf{Ï¿$@‘Mà/­Ù²eKI:µ¬\¹Rî¾ûîÈ> î½Kû÷‹ÜwŸ¨ÎÀå"g@œ<¹¨f!á¢ùó‹`>Š LrZQ]ÔŸEFvírôÞ{¶m`Y_bÑ"­àV=`$]:-X%—.ù²u.m"Bpd?â5ô*î-½Š…øÈÝu×]ö‹™×'Nœ™3g&˜Î áKÀ•,Y2è;©.ôæÆ7ÁȘú²A  ¨"‡#\ŸðÆ3ª>V Dà’öÂý©¾êÿûßÿ´sEG¼Þyç“)ÛªU+-½qN $‡ÖÌî´éO@ŒH€H üL˜0A®^½*t7 ¿Ï&÷ƒ…(Å¢C&¦dKb–PY·ÎV> }îÚ\| :‚›·a¹þÔ¬éíþ/§!¸I8V=Pƒ3 ìÃQÚ´"Ö\yùáQgJ›[“ý^BU¨ý¾&'gΜQ—¶NZå˜W»·Ù£ZëjäÈ‘æ¾Í«•¸PÄP ™ŠâÜ–#‡í7}ölÑk;ߢT­°kÊœ9‘0˜Q:í?D>þØyû+Y.G“&9_ûÁ’³’mÎ×°M1C$eJçîKîÖ³Ÿ‡ó vYHúô"'OÚÏáëX#,’8…ÊÒËkáC<`5¾}ûvU’¯–5kÖ¨ÅYg‘ %Â÷‚£¬Y³†¤¾92=.\ÑQ „œGQárÎÜ D Üï¢ üÚ£x³Ž>¥I“FîTŸt”ñ wDôedÔžÂQ£F›~$]1H€H€"ƒ„£HŽÍ®Ö&µ ¼`@ˆ  +ŸÞæ´ƒj~ï¾âjó~(Ò h!Û )ŠèetébsùA?¼;·!kÑœJ—¶¦$Í3ªz³¿[°/SsË-6÷"VSJšÏ[%@ üûï¿Ò¨Q#…¬•/¿üR6nÜè¶<ÚWjë6~üx)Uª”´mÛ6ÐÍsý0#Q*¤ù@b-›\ƒ´º¹Þ«‹À‘È—€(îEÎÊ©ùÒö.K¯½&òÒK¶s¯ýúý8– E·¹sm‚äºuí—¾ñºqc‘²eEû#nLóçÕ‹/ÚöË›ó¨?ísÈ  úêèˆ[ôê®D‰Ò¿µÿúBér-Xˆºr9Âöì✗ՈËe´n-÷¿@çpŠ¥ùëGàÈñ£È¯ÿý°G MFdزe‹±•wGA* ¸aIÕ Ães$@$@ À¡‘;wîó8H€H€H ¶ _¢š¦Þzë­Æ•ù½÷Þ3IRph†S3®Nëèà~­ÉñÊ+¯¸Íª-rþtgïPN fˆuÖö_‰¨±¤)¡æl¾¯ÓPZ§}{”Ç9{Ö×µo,?nœH–,"4f $-¸ ’'O'KpR¤Ào<ÎEGŽˆL*òÄ7Ž%ÇüÅÂupÊ›ËÐý{Õ²¥he ›Ëö×SÀ|b䯿-èiiÎ'À D¤à6wûöí“eË–Érõç„-ùI üÛÄ-àsD„BpuågŸ‰,Y’ÄÉÍ“ Ä”SCÐá(&>n$ ¸$°TÓ#k×®mÜŠ>ÿüsãÌìraÎ  ˆXŸiÇã?ü`Üî°¯¹±GÄ4z¹!9rˆL˜ ân0R+I÷î¢U"l%XvïöþH1è §ŸM›DPÎÍ1àÂ0bDü²cŽËXï!8R-¶T­jM Þ3ʽ!àþ¤—_ZQÁ&@²Mõý/J¿>,¢f(’)“ïë[kdÍ*òûïî'¬eùL$:OnÒ¤‰¹G[¸p¡¤TUÉûï¿/ùòåSÑd/KÔÁD»øå—_ôÿˆõîÝÛn_F:‹Eš6·_?Ûë`“jÙä¹ç‚Óίô¢ÔDL8áœì*ô+.(w±pb\µ•hA#FŒP[ÒÄEý/Þ¹s§ªÂ3Y~OÁzÆC¬_¿^ÿ‘¦Èn½ ¾ìäªùQ•Ô7ЫɺêéI;;0Ãp6Ž`!Ï1TU'ƒH€H€BMÀr8¢à(Ô¤Ù> „/dÈ>¯µE2dÈ kÖ¬1Øá»·Ü3  @ŒÕ4ö[TѱcÇ@šáº$àE‹l%Ãî½÷ÆâH¸íÔIô;(:p.Ò¶íyÖ« lƒ©plP³3XY¥ŠM@ôÀÖRîŸÓ¥Á#ÐÀ l±b"iÒÚRÂõáN6óç‹ÀíhëVïDPÖ ¬£›EÆ6g¢%nË—)pÐxì1Ñ$z®$@‰Kàºþ£7jÔHÆN×ÙPjj¤NÚ\-ZTž}öYãDkÍk«?¨WµÖJ©%Ož]äþûEòçw¿ -¦aØ9›Ä­Tª”ÿeuâÑAýø£ÍÝÉ~:_“ $W_}UÞ¾Ðß×y…ýV!0š7ožœ?^jÕª¥‚Å¿cÓëÖ­Sg[)…FP ÀG+ËAmÖecp™ƒ.×àhSÊI“D>ø@´/ßåjwÀGý.¸^&Ôsàr„}OŸÞ¶ÏØŒ| ˆp+Tý~û²–÷ËâÜŽ}ÒêñÒ¡ƒ÷ëqÉÈ'h‚#¨FñC›:t¶ý_/51G¥5}õ Õ‹øR ·k×ΧmxÑ, !Ô>½ RÌP”Sóòk£cÓ$@$@±FGhzàm·Ýk‡Îã%  ˜&€Aç–-[šD¨lÙ² ú'r9«9Ó”xð$@$]ÞÔôxô[wéÒ%ºŒG–Þ~[äÚ5‘W^I¸{öÌk¼uœ{ü¸ˆVz•jÕD^zÉ6ƒãƉh† œ¬À lùò¢eE>úÈšêÛ3ʶ¡˜AÙ²6 –&VÀ­ ³§ÐË6sü:tÒ€™ »ŠBŠ˜“€K>ÜŒ=Úér•+W–‘#Gª0ðG©_¿¾tëÖMî»ï>3FítN ˆ@›6¶ßh«LX@éÊÐâ7·à*+ˆð)Áo=xî¹GÔ Åvþƒ# ' ˆg!õF„»~½È·ßÆÛtÐß  ªû)â[ÓZAPPFN E…,p]¡ÿF2y²Èo„l3l8Ì$K¬ýé§RÁ%K–ø¼¹Õ*ƒ[ .|x¶KT `è´Ã?•+Wv”q¨šÄ´Ký¾EÞ²_ÇT:bìÍdÙ|ÓÛ@7z3J©W¥Ûd¶}ûv§¼M3-BýðÕãŽ;. :Ù³²X>Hq‡†LD@D 64¶åÍ‘¿E¶ØV† æPWE@D@-4îøà|Ó¦Msõ$6mšÅm Üx„IdÌÌr~ÿÊXÅNæÒOuœóíÊÂ… ä[í—á8û¶b·dØßÿíÄîæ9í:s¼þúëÃn %ØGŽi1‡ÿ4Hû–5+`¿˜+Ù·m+s©¤¬ß1Çv¹^Ê@‡#.ÌÒ‘*–ÆØŸ4z«ÊD@D@¢' ±-†T7¢rÈ!ù'V ¤ÐØ–ô[’ à)>O™2%K–tž÷o¶­ŒõêÕKÉþ¨Ñ" éG ã[&ÌIF{ç?úè#SŒ)†.]ºD[”ò‹@R ØþîãBoª:ù:Ò­›ïShï­[~˜ŸÜujÜ8´¼‘¤¢ÂÄ—_¿ü0Ôš,4ßBã¤Tû 0ìõxóB9Û »…øÅÀè:_ýõþBô).rúùDgL†Â¤"ßsÏy}Û²¹>-. *Ô–âm棻ÃõG¨ìãïÀTLÂ;Ì JÇ#FêÙ31M _ÇÔ6m¨ XÍÆ¹Š‰©Xµ$…@Áx×úÕW_?ü;>^µàˆT³)Z´¨ÿ¥€ÏÌl}ûö p6ò¿~€i^>Î_‚~Æ]&ɰH™“>g£HÚ°dÉ\xá…'¹—yM~—ålIJèȵjÕ*G9êûæºÆ/oò²I…Iʳzõjç߯KúŽ;€?þˆMcX½YSÜ+60TŠˆ€DI@c[hçr+ƒ™ŽBã¥T" "LÛ’I?µë~íµ×g£=z€ÏîO>ù¤œRû–ªõ"V¢ß2eN2ڛιØo,þRÛ¶mQªT©h‹S~ˆ)ªþsqt̘˜›Ö…YD\Çn¹0ßrGá(œ;áÂa8;†n£Ú„-'ÉB  ñ-HJ’À£>ꬩÞzë­Ù®é„÷ðû—N*¶·Mš y9``~cfà 3 Õ{aü©GGÑ©S]uºœêlÑÂUƳŸ†ž±3Îp›Bž5k†¦ú«ÆSáÈÜAÌŸ¡)öU±*ǃâîp¬nDE#*…b'N HÖľYò‹…}衇â$ß/CËMU éÓ§”“ˆƒaÆÙwÁ1’úè„ÉËPÛNç,zç2_ª™/œލHÄ›Œ£™—ì]¨}4ñ+Ç6ž¡¶EéD@D Õ hl íúÆ)…ÆK©D@D ™4¶%“~êÖ½cÇôïßßQè妧 *¤ngÔr´$Íø–Is’ÑÞüÏ?ÿÜœvJÝ(ZÊŸ/I“ÜMºù&ôK`‘€œEX:QB–?†âáz»¯º hÖ,ÿ<Ѥ8åà®» ôálÂŽ¦¬LÉ«ñ-SîtÞý1bªT©‚E‹åЮòwͨQ£ŒüÖ—ó-L ¢"@Á‰öí ò.†ÊFµÜq8âw1ÿÜwpøá€ArB^Rlâ†\u£DF3§J*G´¿þr•êÜ#oþ=ø`—[GåÂD¯—Ÿ{.0xðj‹1Ü›€Ôª˜ˆkH5Æ·œÁ`…ÿwz 5o’‚!ükf^î¦ñ7†M ÅZ›ö%w—øŒm £S¢ŒuSÁ)Rãäååö­µtéÒ¬"Š[K:äœp 8ꨣ°~ýzg7%œ|ÊF %wçwâ…^pB®eeöø‡#ÆF¦Q©^«!Þr7“þŠ€ˆ€ĀƶÐÑ2¤ew:è Ð3)¥ˆ€ˆ@ hlK8ò´©ðÙgŸÅâÅ‹mô”-[6mú¥Žˆ€¤hÆ·L›“ŒöŽüñÇN¡ÎYG[Ÿòg†f±€Nˆ/›fqj×C‡ÀÈ‘@éÒ‰ 7Z˼›ªP!àž{€o¿x 1í4v[Ë{ ¦–Ô¨‘˜zS±o©x×bßfF¡ã#ÀÜa^'o¿ývž•ðÙ‘hn¡t™,i ‡ë½TߣBPݺù7…NŸ|=ó 0iðÞ{°¨?°Í?nÞæÍ €Šó/+V).ÍtO`‚ÇN_¨‰ªA¶<ŸpGžpúd®øì3˜ïA8¹b—öÜs7ZQó“¥-¸:qÎßZ˜–XMþÏ Á~ýõ×l©èHŠÕ«W/ —ekÖ¬A¿~ý¢ªîÝwß+}V¤H¼òÊ+ìß)ç½U«V&ßv.»ì²,ç$ÆVϾuÏ¥Ë`ŠØ?þè„É;äØÅ@~ûÍý‚N‘.¨™" "Ö4¶…w{©pÔ Aƒ”rþ ¯‡J-" ©O@c[êßÃdõ€~°¨ZµjÙ¢Ÿ­úÉD@DÀC¢ß2mN2š[·wï^Sgo¡>šh³I4 •7WcÇ×^ pi£];àùçCw6b¡ ÀÖ r-^r!@/¾etrzóMØ&s gO˜K‘DURõh|K©ÛׯN2Ï“¿LV†" ï¼óŽ©ÜÜàˆ5äT)©Ÿ1o•:uê {÷î9%ѹص 8ë,wÝ÷Áaë×áUÊïI*ÂñõôÓ®“&•….¼Ðuª ¯´èS_y%Àè|¶ïô¥woo;±Ç_ì¾¢ï½Jœ ÌùtlÎú+ô°Ä`G ¼j %FG¥º¡¸o³''†‹³°çŽQî•^®W\yk7nt=f¥’9CåÐØÞ¿î°Ù³gŽÂæÔ" "PÛŠ;­*ãÎj†Q;Ô4Ô{ôè‘V}SgD@RŸ@´ã[¦ÍIF{Ç}áÔºtémQÊŸL•+ÿû_|*·up›pÃÆ°*æP ¤TzÈɸq–Ë ÕòþûÀÙgüá.Ôæ”^çÒ‹}o¾˜1£4æÎ½0½:eo4¾E 0²ÿk^ycÆŒA›6mpúé§ãú믷ð\Sñúë¯çØËG}ÔY«½"šÅÆKÖÉP Ü~;`~_8ã W(Ô|^OÇ%yþމ€¸âêp¬pªÃÑ–-[0gΜ€{t5%ðêÕ«g¥^±bEÖçx}øŸ=pâÑgý-ˆdµjÕ|‡!¿÷ÝwiO¡F\v '¤šÀÀ•)`?üðƒÓJ:1~d¹r@Ë–Ñ7œqm½Wž¥Ñ£T " L@c[ø7ŸáÔh 6 ?³rˆ€ˆ€Āƶ¸#Në  †T4hvȦõVçD õÄb|Ë´9ÉhïòG}d M•Ѽyóh‹Rþ$8ð@ÀüˆÁ9äx˜ýT0U X·t†€á&Û^>þxT~à&ÜnÝÂ݄ˠ ¶žŽ÷ÞªVÝŸVŸÒŸÀ!@ãÆ›Q´è†ôïlˆ=Ôø"¨ IöÚk¯aÒ®dL+³{î¹+VÄwÞ‰­[·PøÜ¾\gÏží¤-S¦LÀ5$†ÀcÆ­Zo½åý°c‰¡¢ZD = ÄÕáˆrvþªÜ8UoÛßr )æŸÆÿóæÍ›³©6O£BÏ-&¥Ãð`´nö„ЩS§ˆª¤7®Ï( xÒI'ùó|÷W8bÂTq8úñÇQ°`AÛ¹ÑÒ‘ £^áÂyv5¤‹_í&“”]H¸”HD@²ÐØ– IH'æÍ›ç¤SHµp)‘ˆ€$”€Æ¶„âN»Ê›ìÀ³Ï>‹f͚ᬳÎJ»þ©C" ©K Vã[¦ÍIFsÇ9&Pažó¿œ×”¥îK®]0qb ɇ£?~ûÍ Cç!ZùòÀøñ°@n¨4÷¬«`DG$:!™X>ý¦nã*AøÒè=s- ¼ôÒû(s:GO5¾å'C/½`^›šÇè™gžé(o_®÷ß?åfèСT ›aÔ¨‚$K<†cšÃ8.*yâïjDˆëQŸ ÿ=ú‡ÁŠC0ÿ\&§ÃP=ºø‡aëÖ­ËJ]›Oq4îrœ?¾SCM ¸{ï½÷FTË $ Ï7nì ž¾ã¼Þ<òH”(Q"+ÉßÿõÙ˨ptÄGàçŸË8ŠD|ÀŠ…ÑáÈ"ë9ƒY,ÊS" "i4¶EvÇ¥p7åDÐØ–Êé[UŒ¹›öAÆÿ–‰€ˆ€‡Äb|ËÄ9Éhn!Õh § Åää7`è2G°©÷¸(Q݈ «·ÝØG[÷¶EòÀs¹!f8•ÏYÎÓJ–¹äøÿÞk|ÛÏBŸ*1RñêÒK/E±bŲô¶x•ìËôᇆ/êÎò3 ©r¶Å¦Œ÷úpVCô!‹ÀW_—]Ô¨á:Òp@Ö%}HSqu8:è ƒ°ÑË4ûþûï’5mÚÔ~h‡þK{É’%ؾ}{VñP8h½G}S3îh¡méÒ¥³êçÃÌ™3’‡Ž…jRþ¼©¶´qãÆ€ò¼vÀûľpjlß©§º­äNÆÀ¤Ìl¸¶v­»‹DêFá’Szp hl‹ü_Ž*ÙÆô$9Då8ÐØ¨T$'¶)ßÏçíڵˠž««" ^'«ñ-Óæ$£½¯›MQ“"iß¾}´E)‚ Œ »w®š ,_üùgìA…"0`´ŸPáõé³?ôZìZ¢’D µ h|KíûÖSÝˆæ §æ«ƒ*FT3bHµ~ýú9§yL»ùæ›wýÉÀ¢EÀUWO<‘{šp®Pá¯{w dIà“O€ZµÂÉ­´" ©J Á«rïz°ÂÑœ9srOüß*ü0®¦¿µb€Ç0lòäÉ©ƒÛp1ŠƒåöDr÷Ýwg•@OZ:GEjþêF,ƒr€áX¹rå’³¼HÂɱ_‹l”0`€S™5ÖÆpj4:Y¨U|0P·®[ }¶øpvì±îq8{›ñ¯åp5¥Ì%°råJŒ1" Àž={§ÕàïÔ¬iþ!]ǶU«V÷Ú7¶ñ6rl ÿííýÓf*N-ZŠÊ/"+ŸÚŠÇÏ?ÿì·páB¬Y³&VE§T9é:¶QÕwýúõcC}Gº&¥nj‚Ëç~þF”ºQ‚Á«:ÈÀ¤I“ðí·ß:W¸±qã#e¨År|óÊœäæÍ›59ÿç¶>æQ±bEÏÜå-[¶àk“V?Ù&5æzæ¶„ÜóÆô錨Ðሠ¬œKæ¼t,là@סéöÛcQšÊÈ\'ùâ‹/œî®^½: F¦0ðïg:ŽoìŸÉ©¼ããj™'FÏž=ý»®Ï¹às/…¸V|Øa‡eKuª)œnq)ß|óMœwÞyxã7p ' eË–ÙÒêD ìáØH£2Ñ+¯À6ҺǹýýòK7ÝGÏ?Ý»ï;w¦`Ñmü¯ès¦à††±ôô6ãÿa¯‹¤dÚý‰u ƺ@ÿòüwxžr³ ,ðO’í3'Å÷Ñ[ÄÏÂq8bÞ1cÆøåF€òOÀ…(öîÝk²¨·eýaH³ë®».Š 6ä×á(ع(x²  ð<¸øÊ]:ÕªUs^UCÝŽ‘G™9]b85ZÕª­ÍÁÉ•Œõ¥³ªÝ&ö,lc85šŽ\ú+"7~çù¾ïøN£b]&Z:m… _þ÷:õÄPþ=lÚ´ œª_¿~(É•FD@âN€Ï¾ï=>[ð7~¦YºmÜÍé»Ç|ÏÔß0ñúwM'½ûG¶(g¢yóæñªJ劀„H€¾ï½ *Ä|AˆÍHz²Xo^™“ä8Æç4ß=æ;Ÿã¼dŸþ¹ãÕ¹sg/5Km ‘€ £cG7qëÖnø2:ŸPËénúÔ¬‹UF¦ðÛ<ð@Ï}ï%ò>¤ëøF† VªT©¬1ÎKδ‰¼Ç‘Ôõúë¯cÛ¶mÙÔüËzä‘GÀçc†QcnÆÉDc !F Åþú æœå:à^tÀ°£GåŽe¹åçZ.ÇÑQ£:Ùm ° . /À1V–ÙJ”(‘õ}W¹reçÿgfIïÞÇõ‰?”èU:a‡"w2äØÓO?ãD(½ÛFŽ@¼¦ý:G¡hœ}#úËsoÌ€Ì1¶çž{Ó¦MsJåšaÆEýC0øá>\uàô‘:ñ‡胥 cŒÐÀ~¿dêÖ­^½cXs­Ÿù"u8blÐXíL‰u¿Užˆ€·p’ÚÿûîñÇÏÈYÞ•tÛxŸ9iã¯cý/ñ/>¥™Éá(ÖdUžˆ@¤¨$Ê¡?ÆiQ)›/Ƕ2eÊ€¯xŽm){ã£lø¼yóðè£âÕW_u&¶9¶s.C&"|Íš5_´oÌK`É’%ÉoTZëñÍ+s’%-þ¤½<¶ñ7MGIø‡ã*)œuøá®ÂQ,Цºýãþ‹è‹"UF†àfv¾h¿üò‹óÊ®gëfºŽoì(×ܼ>Æe»!9ÁpjÜDuÎ9çäÚ¢C=TE|¤ëêZ(•3Î8#×´éz@ŒöʵÑY³èä–wO?ü¦ä SÚ¶®¿Þu@â9ªõ™x€Õ® ¼ô’+øÀ5Ü`£ª‘”‚©dæñÁö‘/×Mè´/K_q—pèÛ·¯ã¹ëCø•¹ú_zé¥Ù$)™Ë‡ÉÅ‹û’:ïá<¼}ÿý÷èß¿@þ«¯¾ÚäßòÑ È‘ÿÁ¯¿þЧžz*+á]wÝ–STVÆ Á÷á*q²ÙßÈÔ«¶{÷n̘1ÃB¦‹ †_ V$ªSŽòQ8}0a üþ{ö²Â)CiE@D  hl‹þ®ÿý÷ßN! 8°ÉD@D@’N@c[ÒoAÊ5€áÙ91ÍÉj.vpóÒ»¦ ?wî\9§ÜÝTƒE } Äc|ˤ9ÉhþePYŸÜGØJZ8d£©Ó+yÿùxùe.y¥E±iêÑo1Ÿ  ص ¶ín˜åÞj ~`ß}Lš\r ìßFÀ%ˆ€„H@ã[ˆ 2,ÃÄSdâ"“à¡øC^FuZªÒ<8GÑ‹¼ò¦Ã5Ceýþüxè¡ü{D(®§ÒÙˆvùåÀÔ©À!‡¸Î³§ eç^óÿ{Ùe®`„ÿ9}Èlqw8ª^½º©×ô  <Õ¾±ÚµkçHÛÝ}÷ÝöCügç-PüÞ¾tNÊÏV­ZÊåõîÝÛÙ}èKOu¤=zøcòN'†R£Zý8÷ÜscRvph—pCìⓟ+ù]JúÇE¦»Çö‘+ãÙ‰^…,ÿÇbNù‚—r©B§E@D@Œ€Æ¶Øü3ð9Iá(6á„g£8s r6І¨òЀē@<Ç·Lš“Œæq^˜ÎYÇ{l4ŤdÞZµªÕ®zÍg úŠ}töpgU«º¡còS8òõú ƒ€nÝ|Gî»xÀÕWÿ÷çu$"o¡qÊÄTo½õ–£ÌOQ YèN<`Ø3Î/QÝ/ظŽŠr LÕ(P ”ÔJ#"É¢pDÀÅ‹wv ždO&÷ÜsV¯^#÷Â… ;!Ëzöì™ãõPN2 ÛwÞJÒ°Ò :4+}“&Mœðm_ä¡#ëSññeâ±ú²¶вeKßeDûpÏÐrþæe‡#›~ýZãé§ÝÏ¿íü‰ÃÑ«¯f¡\®ŽE@D@öÐØ¶ŸE´ŸèpÔ Aƒh‹Q~&ÀI‹ôì„[ (ê²eîËraN=6Ú]¨à®1Û¹¸öZ€Â¥¶·õý|óGŒúô®¿Þ•Æ.YÒý ÍI$>pþíñǹÙÿÄÌü¬±-3ï{¸½ž6mšFíßÿµÝ›/d nyJ/" ñ&Ïñ-“æ$#½OT¼Ÿ1c†-à]†‚²‡7Ò¦Æ<÷¸òw­°¾Ç¼ø¸øí·€ ÷¸ñÆœ«zâ  |ùœ¯…r¶fMWM"”´J#"€Æ·ìLtÆ%ðâ‹/š¢\SÚ9_Hò @õ=:ÄúU°?ü¸é& C ti÷*ƒÏЗsW ›&XH˜Ã‘¯±'[¬+†C[²d þg¬üñþùçjº¬tâ9âˆ#P¬X1_ò°Þ™ÿöÛoG³fÍÂÊjb¡ß~û ×Q. ›0aøòÙ‘G‰÷ßßw˜ÍáhùòåY×Bù@Ž>£ãš¼jt8*P ªÝÿbÎà–S;#q8b9©øà›SÿuND@A@c[l(ï4/N@gâNרT)"cÆ­Z1,òþºÖ®{Ìutç~‡hwmÑÙÇoLòÛ]´àâëd¾ì‘³¦¤5ªŸspÍ5@Ó¦n›Œ*ÕûL §öÓO€Mé;¿›ssÚ‰”k"òíÖÒ½{εqC@n¶{·NÆÃÓì¹5]çE eh|K™[UC6oΜ9xçwB*gÑ¢E˜:u*(NQÚç-RÎÌJdâ‹àø6j”Í×{Î}=ø «À׿?0l˜{eÐ `ãF7RŒ/­ÞE@D Z w8ò5¸–é°òuj^¿è}‰sx¯mú­mÚ´±ÝåѨQ#›Èo…zõêå2uNU®\9 ±¿üòKÀq^üQæ?pÔQGÙ‚I¼²$õCªU¨ÐÝv—pvyçÔÆå¢ËÂ…9]Õ9T )ci÷îÝkj$~r$©pƒÔFÈT ºøb€¡üŽÖ¯t!|þ9@µÌ÷>8…ðç÷K/¹/*ådz5Up¼öš›ŽáÓ|GLÏf9ÔØþ'Ÿ„©¹Ï?<ðæ›¹‡¶ +û4{6Я_¡œŠÕ¹dÊØš”È2Êfb¯¸â g§,;h·)" ñ$ ±-ºYL®¢6QÙ2f¶gرÃKÍŽ S#†mt¿ýãÆ¹ê¤tð?ýôðó+‡ˆ@r h|K._íÜèñÔSOa­íúh“0 6ô]Êõ}¿€ÍÎ8ãŒ\Óè,²P¤ˆö4˜•°_~ÙUæ:6ÇBÎ}щ¸uëàÔ:È Žûì <ÓæZH ^ÐØ–‚7-AMfˆs†Âáæ'ªQiY&" ©B žã[&ÍIFr¿wX¼ÛI“&9^Ú%ÓÌçp”ŠÃ¦‰c˜1зodwNþ»vnˆ¬$åȀƷÜȤÏù)S¦8ÎFìÑ|`›¨lU>F‡£&#ÝŽrϲ 0ÜéºuîœWNsKœCâl‹@Ÿ>CŒrŽlÍš‹ÓIˆ˜@áˆsf`FŸtn¨]ÿ믿ЩS§¬ä=zôÀõ×_Ÿuüñ¿)Ëû2]Nͨ”ðý÷߇¤Ň^cè:¯ÚFÓë£'sݺu¼èÜæ‹.(]›ŸY„>çÁ‘ƒ¦†U¦åNͽ ÛÈ üú««þ`3~P1ô¬³€*U|)õ."kßbMÔ{å}ÂI³B… …äp´Þ䨿5ï˜ÓMZ®d~»º¼×Ý„µ¨F €óRö¨›«s ÀMv ‹Šãé =äšAD@D æß(ónݺ4çyn£ÈÇ8ø¾G]×ÿŒ§tæñªQ݈J<îÆfLÑü쫯öïJÏ/­®‹€ˆ€$–@&Œm>…#9%öß–jPX$fsâÏÛ)»¾yÄ•™æn¯c¦OÏ»ôß~sËd¸¶Ÿ~Ê;m²¯žyf²[~õgÂØ–nwm=Xr¼0`€œÒíæª?" 1! ±-wŒTÅ£eb85ö{Θ* ,)Àß¾ Ç’*F‡#ª>ð÷}^Æ0ÅÍ›ÿ­‰;I_|Ø·/uœ«ò꟮‰@&Ðø–ü»O‡£<\p͵L·¨& ólÔøñãMˆ`7‚ï]ž™2ô"U¯-¸NžF‡#C/¸ÃQÜÐFV0%ݦ«é6kÖ,¼É'ž\lóæÍÎ.Mî²ñÙ¹çžëûèÉ÷pŽBíÀ×_»)Û´ 5‡Ò‰€ˆ€$Š@&Œm\À,^¼8jpk‰LD jœØŸ= SO°  Pó±ÇÜðÁ×£9f¨³÷ßL'„,E ;©>XòsϹéFvÓ^ÕQºÈ„±-îá¿pèС8úè£-¤¡ýG—‰€ˆ€d# ±-’¬Ÿ›‡M“¸iLÙÌ ³M›ÜdT-ZÔUÙô…X‹ŠI“€»ï6lˆ¾t†/¦³÷÷RÕ!/ó)曢cTÜgªŠ*šO^ätM¼O@ã[rïѪU«ðË/¿8‘\|k—£9‘’‡1œšO}1d)yÉ‚¿`õjס5%; F‹€ˆ@’æp´ÏV–X¬¯ÍSäµ×^3yÒ/°ÀtJ÷P¿4Ãíª MÚbÔ¨QŽG¯?šþù—^z©3XûÎ7hÐÀ9ç;öâ»ëptºÅ =*fÍ㢓aBÕª1+R‰€ˆ€Ä@ºm ©Få¾ùÍbÆ©Št%@¥¡ŠÝ0`#Gfï%ÃÐÿæ›Ý49í°Þ¶-{¾PÏ0ÜÕ3K”p'*TpÃ¥ÙüX€=ù¤«œÔ¥KÀidtÛÒåVrîáꫯvæFXüCÊøËD@D@r& ±-;—+V`æÌ™ÎBi&>ïÑa‡F‡#•ŽQ<^SøwÝpƒÁÙgÃæÂÝ:#ùËç=Üœ^˜ TEå`ßžÞ?ìÖ£W¯ü•ò/])D@’M@ã[òîÀ§Ÿ~jjqûpÚi§¡}ûö¦ÆSÚ «–[‹vÚŽ/æ9î¸ãP¹råÜ’¥ìùaÃ`ýrç™n½5ünpü}â ÀßÈD@DÀ3Ll-±¶téRÜÿý˜:u*¶å°P¤H´mÛ·ß~;jÖ¬™ØÆy¤¶®]»:ñI?úè#–•y‡@IDAT§E{m;5åßGÚŠ wÒPAaÚ´iX¼xq@‹ ›vÙ’¡—ŽeÀ2äPÜxclZj¿SìÇJlÊR)" " ±'ÎcÇiJgª¼~ìÿµ¨Ät%`B`öX¶lÿ‹‹T ò·òå† Or 6a‚»ìñÇÝň:  “ìØ´jœp‚; ã_v¨ŸráÇaJ(ny¶¡¥Jæ¦lõ1ÇžÓQfHç±-îäË&O0yòd\wÝu*Åb¥ÈD@D@r% ±-;ªÑ2õyϧfäïpÄ)ëùó]ìÄ¢;ÃPÈ}ú¸Ï×^ ˜¯pDöÐC°õàž{ÜçŠP ¡sC-Óžàïýž=ÝcýHmß’wÿN»G¹¶Ù¹sg¼óÎ;  BõêÕ³5ì+Û¶ÉäõÒ5œç›l? –/9$[÷‡ÞÜöÈpL¦3íÏ?»ù|0{~dH¨Ã‘!C†ØN­¹öu×®]`\l*]qÅèÝ»·í.¶íÅftÚ`Ú±ß~ûmVÏé¬ÅWNFFO=õš5k–ÓeO›7ïk϶”¿ÀÃYœ¾û`xçžê†#" "&tÛ¨ØÈÝ7T”‰@&àžî²Ⱦà"@Ë–¹÷zÞ<àí·a“ICãÌ;Ù#€=§Ü\²¤û™»Ÿ/¹¸í6àÝwa;à€;îp']¨F­òÿKÓ¹I&yH×±-¯>§ÒµÕ¦UÏÍLœÈL¹™ˆ€ˆ@¾4¶"â<5J©Ê‰ìpäs<ây*ÅÚ(L%QîW¥ÓëàïýpóÈT¸æšÐsúœ.„EcÎ8Cjú¡ÓSJð>o‰¿GܤIÇݦM›f©uÖY6Oô6ÆŒcsJ6©dRbÎŒNb‰0nŽûõW˜#Ì!*þ5²[¹uíÏ?]a:ÍžwÞþ¶PÕèá‡þý]õ¿¾}ûîÛ]ŸD@D Ùò÷øˆQ 4WË{ï½7Og#ÿª¸p÷ì³Ïâ.®$d •²-Ô”{¿þúëm7u©< ´´U†\kÅ­Ü)`s攵VÂñÇÛd>ÆE¨‰Ýæù$ÕeH×±ío>™šÕ¯_ßãw@ÍØ ƒýL·ßŸ°ÉÙËä='G¨þÃÝZœY³ÆÝÁõÌ3À¸q0µNØn6˜ƒ}öüᜩUËufb4‹jèL¾pôÉ'Þ=Â)IiE 2é:¶EFÃ{¹n³ʵk×âq“D+[–Ï¡2ühlÛOˆ!`¾0Ï“£Ž:*k¡tÿÕÌøDÇ"Šéûö×0¤ÍjÍ=Ší_* qCA£F±cÃ/¿X1W)‰LáÚ‹/¶FŽ«® 7§Ò‹€x™€Æ·Äß)S¦8Ïc §æ3~¦€Â|à;•õÎq—G‡Ú`sHNò?Y)c÷sV\Ø^•¸Ø¢EÀÝw+Wæ_¿òŠª9CE­âÎXˆ@´4¾EK0qùNæïpDǯŽ;:ŽEklwZÅŠ³4}út,[¶ÌÔ«ïÈ:Ï kF×O„­·Æ§&Ûû‚GN:ÉU/Ê«–SO8îÞr‹»ÉïðÃaªúp¬õëçn²£C­LD@¼F pF.N­0`€í °m~vä‘Gâ”SNqvˆÐ[u¥¹wþi«”×óÅÆö%§Ô!'kÔ¨á;•Qïœ@åi:L’òÇž=-lh·ízíŸwÈçUoáBwQ‹‹JfÔ? uVD@Rš@:m>…#NxÈDÀ«Ö­ƒÉUœ˜à„½¿1<¸C*«PÁuèÉ)-'kzõrÃp¢„»¡e\¹é¦DÕ¦zD ;tÛ²÷Î{g¾ùægN-ã¤õñÇo“¸'9¯Æãꫯvœ‘ž~úiï5^-!écéÑNåÛ 4.rRз[·ý禆*ã‚h,á‘M}ú•*¹%×®íª£rsÃÏðzÍš9×JUª©Z…,稜Sæ}ö7\%ÖAƒ´!oRº*©M ÓÇ·DÝ=:U°I$Fiñ7†UcHµ±&a׋“HÿÙ8Jb›%*œÇ]»â7—DUoªæÙr¸…fý¯“ù¼ÑÿŠú_ Ü|³»6J•ñæÍóɨË" "D6-_ûñÇA¯Tãàò /Ø‚‡­xügØÓ ºtéb»^±0 j8´-¦!÷ÑG9†ÿ%×[Š˜?¾µüXó^m÷¿ZH½8óÌܓٳcG‘{]x ÃQ!óÖ¨ÍÙP™xŒÀ¶m°PBnˆ³õë[ƒÏæpÄpgœÌ°½èÐ!ºp×±ýÌ—‰€ˆ@\ p®€áÒŠ-ê¼sÞá»ï¾sÂÞ°bŽË{öìqæêÔ©×¶¨pô%@‡#:µžp éÛÉ«V­rÖ†Ï7Ùk*'ú[gûBç³ê;U6¯Öc=Ö?y\>ïØŒÔ¯ïŽ!ñ¨„óc›6Üè®Ñ×™áÔd" " ¿åãÐâàbŒ»ùŒ¹ú;WÛ³gOGRÏÿ¼/\‰ÿ9}N=?ü`+Z8MšlIã'Mr‹¡¡LD@D@’A€¿Q²øŸE)å’ŒŽªÎ”"ÀPÏ?ï†?`œwªqÿí·³wƒ»wË”qãÁg¿ª3" "à=oÛ—Ù´iÓœäƒC«­7¯J:ñ˜jÊÝ»w7)ú[¼×xµHD@D %lÞ¼?üðÚ´iã,ЦD£cÜH:YÐ›Ç ,˜aÕ¸™ÁÄĨ.A1©-\õ¤àBÏ96¾»NN6¼ckд² dà?€‡ŽÎÙˆõR¸øÜsmöúÀàVèXD@D tÚåFÿpj¾üåÊ•C»ví0qâDç9Žç˜TݬY³QŠ`%_¾X¾SÑ΢¦âúë]E»Q£€K/] œ—ãÀêÕ .ˆ]¹*ID@¼H îG®¢Íþ®Ó›µtéÒûOäò‰NGþ&‡#©ûù§Ÿ 8oݺHL:A‡#óaCÕª1)N…ˆ€ˆ€ˆ@Øø[§>·ÃÈDÀ(úÞ{@£F@ïÞnœ÷§ž¸Û·G€»‘ƒq깛ؔ®s5îÈ¢êäÏ?çšDD@D !vØVÔ»îº TI¾›±µÿ3qr{ôèÑR%î¢Î¾êõ." "f¾þúk ³²Ë@£”M3.ìŽh± «ÆÐm6|›#±[nN¹‰ÂüŠñú뀭SŸ}yæhpZ" " I$Àpj ÈueX5޳ŒnCó…SëæÇ3Ží§37ßù–¢¶“NG±R¢ZÞÒ¥®C“=ªÊD@D ­ $Üáèøã hÛ:Q¾|ù¬´\ÌÛ»woÖ±>¤&?þpŸ;w¶@¤a%ýmÑ"`áBØN#ÿ³ú," " ‰#@yàMæ‰Ñ€Û e"$wÜtês P¥Š»#wÅ `ÀÀ"þáÚk³‡An*¥š™77ãD̘1±›xÉ­ü–ç̧3g—_”-ë–L=ç¾bat„åøÆÍ€2Hwqw8Z¾|yÃJ•*çuP­Zµ¬ËÜÅøï¿ÿfëCjX¶¬–Åk]nªD%CåÚ à¶Û³|ó{,‡£@.:HŸ£ŽÇ<k¢ ó÷ß÷Þë*3àD‰ErÂ|0з¯ëhtÏ=îäFpúp7l†wãÚ_rI¸¹•^D@bG`ݺuNÈ´:uê8áÔbW²J@\(­]»66lx!ƒŽ¨ò@¥Ó`;ñD`Âà¸ã‚¯èXD@D@¨Žý3Ö®]›c85Ÿ-v%Ör¼]¼x1&OžŒSm7\‰%|IâöþØc®ó*éù줓` º@×®¾3‘¿sžî×_]‡&敉€ˆ@Úˆ»Ãctú¬H‘"æÑi.!Zu·ô3)ùÁHÁúÜbl×3åªÿ…Õzú¨íÙãªùgd85ÈD@D@D þ¦|Œ™Ž’A?sê¼ï> U+`à@àÝw³÷›NØÛ¶&ê8&  T _L2 àÙ³÷r"ÆÖø‡'E'ÚÏEŸD@O`РAö}´<ðŠ+–ø¨FŒ °`Áüù矹†ÉœÒoÞÜUOÍ„þª" " ±#0^©f§Q/cXµíÛ·›2÷µ¶¸‰§Æ¹³?:wv7ÖùšÇù.λ5nì;ùû°a0õ&ছ"/C9E@D •ÄÝáÈŽÂ1M †CËûiçÍcL´%¶;蟰ka^-OÎGÜdä'„V¹J," " Ñð9)¤Z´$•?/”uîßøñGà­·²§Œõæ/‹R„£Ž¦OwU“}¶³;ÿÙ[¦3" ";\üe8µfÍšáüóÏ]Á*ID@D@‚(œš;ËM ‡'Ƈ ŽÀ¦2ô!ðÉ'Ÿ B… hÑ¢Ež:ãŒ3,"JAsúØyïL/ 8Û“Oñ-nÎ@ÿ3½ë>8—W¯^œ;£âE@DÀ#êpä‘>«I"P¼8U êšWóœ°[`ŠùX´h6SX„Í7›äâþsú$" " ‰&à ©VOO‰FŸ–õ1zðuלœð7[[UŽŽ=ÖÝ!å-Ÿ¹Žoó=¸â ࡇ†Tc87îÎ’‰€ˆ@²Üu×]عs'†ÙvÑÜ•"8`x—Böã·mÛ¶qªÁûÅ.[æ†g>ì°ø¶õ‚ l¶¸®»øßšTºˆ€ˆ@"¬^½Ú6°Mw£q,Í˪™šÀñÇï$á{ÅhåºóªÌ®1LèË/»*F'ŸœOâ/P%ðÖ[#,@ÙD@D  ØR‚LC€;Riõë× »Â:uÜ\ˆ£1t­MçMD@D@D )¨pTµjÕ°BÆ&¥¡ª4®¶nÍ®Äè_!wN1$wïnܘ}ïîÝwX|0ðôÓÀ+¯øçNüç#l]¿ý âîjæB€LD@’E`êÔ©xçwÐ¥K ©}R²š¡zE@D@2€ÀnûqþÕW_¡eË–(_¾|ô8ç.2¤3f{öÌùú—_]»¿ÿžóõPή_>úhwÃC(y”FD@DÀÛ>ýôSs¸Ù—o85_/Î<óLçc"©•, Œén®óÕŸÓûÌ™îæ»œ®ñÜÓTèÕË; NcSÅæDån ¾¦cHWr8J×;ëÁ~ÍgpT³HT èpD[¸ÐyäIî»æš]ú+" "t8R8µä°OV­C‡üX;—pW.×#Î;/ðn¼&% T¯”+0.<àUªäæ;è à†€2e€·ßXG²GGá¶‚êJT<’‰€ˆ@²ôíÛב؈²k2ˆ#)S¦˜ÂçG™!ŽÕ¤DÑ,R$ç¦rCÅG¹›rN‘ÿY[“7_˜?±LD@D M0œi;vìRz™ç΀på•W†”>šD\b¨³¼šöÞ{@“&Àä\“ 8¡Cॗ€Ï?Ïž¦_?`Ô¨ìçuFD@Ò™€-wÈD 1|Gu¹"¦ù;5m LžìªpáN&" " É °É¶{R&øôÓOOFõª3Áö쮽1øá`ìØý ¨QÃu¢"PÑ¢ûÏû>x", ëd´e °ysàkÇ woàöÛÝ4¾|É|g?lc·£È¤ˆÉ¼ª[D`ܸq¦pû}OöÆañŽë"Ü" " O€áÔh¸š(Ë•À¡‡º—¨ò©}ü1lQèÔ)Ò”OD@DÀKöšÄ÷çæ…sÌ1Ç råÊ!5­Œí¾»çž{BJ›ˆDíۻζcÆ—_ž½Fn lÖ ¸ÿ~ Gì×O=5û9t' ‡£t¿Ãéw¬|ôQkÛÑ?5kÖ »UþGÌl!`±xqØÅ(ƒˆ€ˆ€ÄŒÀ_ýå”U¿~ý˜•©‚¼I`Û6€!ÅlÍÛv:¯¿ØNî|züñÀsþGçž ð•jF&¾d" ",-åõ×_²eËÚ„®ÍèÊD@D@D θPzÀ yóæq®)µ‹oØÐ ¿Ü¶mdýà†Á°Ei ZµÈÊP.oøé§Ÿðï¿ÿ¢OŸ>ÞjX­¡zy›6À_¸›K—ÌÌãÜÔSêHD@2‡@ÁÌéªzšLTøûïîælT …¨[¦;1äH£Fa¢ä" " "C §FSHµBõ`Qk×íÚ¹ÎF—\pnðdƒ›­&‰€ˆ@Z¸õÖ[±dÉ<òÈ#¨R¥JZôIð.µöãêÔ©8å”S"š¿ônÏÂkÃ¥ Ìš•{¾bÅ€;î€9fåž&¯+T峖©åEI×D@D µ|ÄX›f;wöT×/žz æ Z³vjä&„–^©D@D Ó Èá(Óÿ$¨ÿ?þH‰ÜehذdD5r§ C{,\Qve˜ð9Iá(æhãVàŠÀÝwË–…VÅ¢EÀ '¸!Ô8™þê«®¬rh¹•JD@D T˜xñÅMYîTôêÕ+š¢”WD@D@B"ð…É0LÇŽCJŸ®‰fÎúö&NŒ¼‡\Ô5Ÿá³©Žj,Õ¸‘ƒæ±5i·Qú+" ":U­ZÕs*o¼Sξý6´nuëæ†üdX5×%íçLD@D  ©¶k×.Œñ}CçÒ ÿÓK—.õ?ħ—‹RêáZwº£Ê’Jàüó7aæÌ‡Q·n݈ÚÁxÞµkËá("xÊ$" " ©¬q-” ƒ=\wðè£ÕíÛ̘|ö™ûúþ{€“áO<áNL¦Ö‘ˆ€ˆ@¼lÚ´ W^y¥óüO§#™ˆ€ˆ€$‚Àg|0£³k&Ûÿþçöþ°Ã"§pÏ=À+¯¿üøÊ0øê+ V-`çN7”CªÉD@D@RŸÀüùóñûï¿;›E pAÏC6jP¡ЩShª^hÙÒU8Z°ÀÝŒxâ‰À;ï„–_©D@D Ó$Üá¨_¿~3~à"Ê+‡£ˆ°Å4SÛ¶Xy£^=[á‹ÐèpD¹Ý‘#a;`žÒ¤l" " "T8*W®<ðÀ”¦"âA`Í bÅý%ßr pè¡®QðïFÈ£šÑÊ•núR¥€`qçÓNÛ_†>‰€ˆ€ÄŸÀm·Ý†Å‹ãù矷EI[•”‰€ˆ€ˆ@P]¯Q£F?ö„ëpd{ŒQ¤ÈþÄü/¼{ì~g#^}ýu÷¼ ïÎs—EN5EüýùôID@D u øÂ©uñX¬LŽQ\O,^Ü¢*aêXüôpüñÓÏ>;ÔœJ'" ™G@!Õ2ïž'¥Çôn¦Õ«W/âú©D@)Þ=£“ô¸Ê(" " ~èpÔ A¿3úè%Çõë¿þº¿UœÌæn&n\fˆ4«Sú¸ýv÷wÆÚµCÏËÙÈŸ’>‹€ˆ@ü |ùå—Ž£Qûöí•£ø×¨D@D@D˜5k–…^^f›l×A††¸#?Ÿ_†^³=8xì±@` a]¥ ðÈ#ç«Uî½×U°Ÿ=6,ðºŽD@D@R—ŽJ”(víÚyªtˆ¥Òùý÷‡×,_à:ÝupÎ9áåWjÈ$ U8Ê$°êk ŸÃQ¤!ÕX¸ðGkÓÆyÓH ;v€¡_å–M™§ìÞí†?{î9àðíy… …Ë=´•JD@D \ ¥Ö«W/”)S ¥.=¥ˆ†€/œšŽ:Q6?õ¡š59sÉs­™!hüUüS¶ ’’‰€ˆ€¤ 6àÛo¿uœvK–,™½:ø`ס–Jè¦E—Ô ˆ9Å ­ ö dá>ešE£pÄüä†7©QƒG2HŽk{÷î5“Б%þ9ÉÍã©ý5`Âxï=wÇmÒ¨ˆ€ˆ€„D oß¾X´hFŒaÏ~öð' ÃQq‹·ÒºuëÕèÍjÌ÷×6ׄ¶Ù³B råìGìYnÎFÞìµZ%" " O?ý»l!ÐkáÔ¢éóÞxc´%(¿ˆ€d¸;=ÚYË œêe0¹s£jÖlb»åLe D™à‚þ;¦ì®LD@D@’M€áÔh ©–œ;ñÅÀo¸Ûü­±~}`;z÷žz àÎY™ˆ€ˆ@j˜8q¢JüW]uUj4Z­H [·nÅäÉ“MQ½ãt”а>µ¢Ã ­*!Y4:™ˆ€ˆ@`8µ&‹×¹sgOQX¼Ø1ðT£ÔHCq_†)_¾|bS—B%0u*°m°nÝQ«…Z§Ò‰€ˆ€ˆ@¼ üõ×_NR8Š7éìåO˜tê䞯ZhÒÄ•ûçD7_ £&QŒìÜtFD@¼L`çθòÊ+Qºti…RóòRÛD@D M |óÍ7`ØìŽ;¦iCïéÑÂq8²(:NµŸ~Î??ÿPln ú+" "öìÙƒO>ùM›6EõêÕ=Ó¥-[Ü9ÂîÝQ£<Ó,5DD@Ò’@ÜŽÒ’š:2zÓ֮ГNªç诈€ˆ€¤8ŸÂ‘Ž#;tp%oº ¨S'ñõ«FØx饗œ0Ü?ü0j×®û T¢ˆ€ˆ€äA€¡`hø°‘bÆ Ç 0¼Y,,‡#ÖKqÂ/¿öí.¼0-Q" " ©@à»ï¾³õ¿µ~Ì[ñÇ,øètt ©@QmÔ&P0µ›¯Ö{À?ÿ¸-Ü»w©޼~³Ô> Ðá¨xñâ¨Q£FÈy”06 {LÎF±¡©RD@D ù¨(ñÀ J•*èÓ§Oò¤ˆ€ˆ€dÏ>û µjÕ2UŸãˆy„ÐòåÀÙggž»Ñá¨H ~ýÐÊô!£³gÏ=7´|J%" "NÖ¥KOuˆªFE‹j\òÔMQcD@Ò–€ŽÒöÖz£ct8*Xp¯5f5êÖ­ëF©" " "%†T«W¯žŸ<Ê¢”=Œ\wñÅnxÖ<’é’ˆ€ˆ@ xá…°téRôë×%K–Lឨé" " ©H`Ñ¢E˜;wnJª ä>+õíë’§ºÐÖ­‘ß‹ŠƒiÓ€ƒvŽB)‰NF>3¡BV<½‹€ˆ@F ÃQÍš5qôÑG{¦¿\—œ8èÔ)v €žéœ"" $à‰G€½{÷âÏ?ÿĬY³0{öl¬\¹7nĦM›dåÊ•CÙ²eM¶Ž8â4iÒÄ|F!nq—yšö²e·býú½R8òôRãD@D@B%Àß- .LÉ éPûè…t7Ü<ÿ<°kpÎ9@·n^h•Ú " "KÛ·oǃ>ˆjÕªáꫯŽeÑ*KD@D@B"@u#Zª…S3?)¼ø"pÜqî‚êúõ@ûö°ys÷|HJ´x1Ìù8ï¼  y2ê5×tVêÜ9„º$" "vè°;oÞ<l ð½ù&`Ó·¸ä5JM4&T‡#.Ö}ðÁ3f V¯^æwß}×IWªT)œ~úéötŽ<òÈò*Qâ Ðá¨xñuNÅT‚‰€ˆ€ˆ@ªX²d vî܉ ¤zWÚþ+`ŽZ0d råü«¶ˆuÎäù€À‰'æŸ^)D@D@RÀˆ#ð=4>ñÄN¨ÒÔëZ," "êèpÄM­íÚµK©®Ü?ì¹ Ê­|ynú^yàæÆÝóáü¥8½­â†l Ï<rr%H#^§fúŽÂQáVWD@DÀ³’âp´Þ¶\ 6 ï½÷^Ä`¶lÙâägt8º÷Þ{íA*‚'©ˆ[ Œù Œ/+UZaaÕ ¢6·¼ÈD@D@D Å üý÷ßNêׯŸâ=I\ó¹û¶Q#À~¾9f~ãjÕu>⻉Y‚æþ6dòúŸÑgt"°mÛ6 ±/û5jફ®J§®©/" " )B`÷îÝre"Z¶li;汓"fbxí5 m[÷åköðá@Ó¦À„ ‘9±:qó‡LD@D@ò#@‡#ŠC´å€ä›9à‹ºE‹z¤Qj†ˆ€¤9„;}ûí·¸ýöÛ±n«z ¾ Åvî¹ç⢋.Â-·Üâ p±(WeDG`Í7 Ê®]‹œIä¢Ý£ªÜ" " ž @%He¡°Ÿg޳Qß¾°¹ÀüùÀ‚À§Ÿº»rY æYäÜ,“³Q }´$ðŒÉ!¬°*O?ý4Š+––}T§D@D@¼Mà§Ÿ~† R.œÚ}÷¹!Ì|êF>Ê §Fg$‰Ìûˆè]D@D ^Ö®]‹ï¿ÿ]»võÔóri §ærÐ_H„:}ñŸùæ›±k×®|ûF¯Ø:uê H‘"X¶lY¾!×ö™œÎ믿Ž3fàå—_¶ò¶U^–Tÿ­Çbóæy8üðzIm‹*Xð9U¯^=VE¦u9¶a£GgŸ ØUÆS_ºÔuP–`T ‰€ˆ@:غu« CQ«V-ôêÕ+»ª¾‰€ˆ€x˜Ã©Ñ:tèàáV6ÍöÝâwÜ01ÇxG‘8Ù°l‹Å°ÐrÙËÓȉÀ“ÓÛ³gºté’Ó夜cHÐ7ß8ÇxüñIi‚*Œ$0‡#>ÀÑÙˆPNÖ±cG´nÝÚ »EG£Š+$Ûa#–ÚªÔo¿ý†·ß~k(¡d³gÏ6ÏÕK0räHT`NYÒø޶m›o»r8JÚPÅ" " 1%°|ùr§¼jժŴÜt,Ì"à†€%`át³÷*F”ý¼Îˆ€ˆ€¤7§žz «V­ÂsÏ=g2÷Ò¹Oï»­Þ‰€ˆ€w p¾šóÇÍ›7÷n#ƒZvÏ=.DqøÀÀ¨QÀ¤Inèë(ŠRV !Àpjmb¯S§Nžè1ºw8m¼áÑ T#D@D $ÄáhõêÕ¸óÎ;st6:æ˜cЯ_?4¡ækF‰u:­ðEǤ޽{[<ê ¯ú5üþûï9ç΋ž={âý÷ßw’.ê a|GÀ?¨[7‡-7 k‰*Ø ÂQP¥J•Øš¦%qÂz΀’ÿµk§i'Õ-°lÞ¼?ü°³ÙèòË/+¯‹€ˆ€ˆ@¬üû￘>}º)±ží,˜ÆªÜx–3u*0nœ«{ôÑù×´x1, €ûÊ-õöíÀˆ@ùòzfˑ΋€ˆ€`›O?ý-[¶DåÊ•/&é¨à“O€+®n»-IPµ" "¡l_yü“‰[¶l ¨ˆªO>ù$Þzë­|2þwÀ]gœq†…èm;0F¡FÉæØêC«É’G€¾çœó?kÀïR8JÞmPÍ" " 1&@…£J•*I‘!®íÚœ¿ýö+‰ˆ€ˆ@Fà<ÕŠï¾ûnmʈ;®NŠ€ˆ€7 |þùçØk1ž©ºŸ*fC§9Gäßb €CÉ?í?6¸Ê´,[&" " ùøæ›o°qãFO…S»ë.WÙè…`Eó뮋€ˆ€Ä’@Ü#~ýõWÛy1. Íôx¥“Щ§žp>Òƒ-Z8jFM›6 (â™gžqB°œÔA˜xZ´oõ-–ÃQ¨«"x Â‘©…N™¿Š=½RŠ€ˆ€¤/M›6YˆÍa¦€[=zôHߎªg" " ž'Àpj´XÍOÇ»Ã+W3f]vXþµ5n y$ðè£î+·'Ÿ ,\Ht07B:/" "LÀ·æÛµk×àK1=^´øå—Њ,SèÛWÎF¡ÑR*ˆ-¸;QÈß .Œ_|µjÕò?õgÆÛ~öÙgäû¶›&,ŽdÉ#°lÙ2§òš5k&¯ªYD@D@bH`ÅŠ¨^½z KTQ" " "úÚ ðÚµkqÏ=÷€s2H*qÄÙTó“ÕžüêeDïùóGÉ/¥{êcƇÜr pç¹çããm©R¹_×ðØ·oÆŽ‹  Q£F¾Ó1ÿýwW©ŠE9ÙîÝ9Õ9dˆ«ÃžI“&ôëâ‹/69WÓsƒ•³ Ôƒ(yâĉح‘'€I"–.]jò…PµjÕDV«ºD@D@D .6˜Ö<ÃÄJá(w¼öóÏ™Ï=…®ˆ€ˆ€d"W_}#FŒ@ûöíqÙe—e"õYD@DÀ#fΜ †ÊîСƒGZZ3èdѽC¶5€É“㎆ ®¸س'äìJ(" " ÙL:Õ‰,sæ™gf»«\Ò½ôRØÚnÎ |O<œqpÛm±ªQ刀ˆ€DC ®GüñV­Z•Õ¾"EŠ OŸ>YÇñøÐºuë€ð]ëׯ@YrPáˆÎF¼÷2Hu §FËt…£/¿ ~þ9ûµõdz(ðÑGٯ錈€ˆ@føí·ßpÍ5×8JÇo¾ù& ŒëTDfBV¯E@D@B&à §–jG!wÐ/á|~;ýtàå—³Î,(€LD@D@""à‹jO‡£pC©õë4oØÌ9s€oÆþýàÆG™ˆ€ˆ@r Äu–oÚ´i½kn#Uˆâm§ó ÊϾþúk¿#}L½{aŽ_ÀìÙ§Œ4q"¸¨Ô&À]°´LV8¢“Ñi§ÁÂá~x?7n8ÀIm󗉀ˆ€ˆ¨x–­nî1I…÷ß+VH*É&ûS¬X1{fñþC‹ß^Þˆ™•, Œ\r‰û~ê©@Ïž®ó‘ øÊD@D@D dc,^g “ÐkÑ¢EÈyÂI8c†»É±qcàÞ{³çlØà’ï/½‹°’=Έ€ˆ€$–@áxV·fÍš€âO<ñÄ€ãxt ë%K,> /XÛ¹Z5kÖLlåªMD@D@âD Ó޶ms% Þ{hÒ$4ÏsÂúÉ'aNæ×t$" "yfýRÓÂÿûï¿ñÌ3ÏÄmR:óȪÇ" " Ñøë¯¿P·n]Çé(šrâ—ª ŒúV¦ ðÍ7Ñ-ª¶UªÑ2$Ûðán¨µ¦M†i“‰€ˆ€ˆ@(~ÿýwÌ›7×^{­9úÄÞÓgçNwÞ‘má˜U´höVQ,·M›ìçuFD@D yâªpô/õìü,QáG*³^½zµ_+ô1þ€À޽ˤp”àªCD@D !| G‰úM“N…Q Õ‹æÎuw1VºÍÑwÎ~ÿ=УGÀiˆ€ˆ€d(!C†˜Þ‡¦¨p‰R-C1¨Û" " "@gضK²~ýújUÎM¡z•Z¶ŒÎÙÈW:׆y°áÍšú®è]D@D@ò'M8µ;€)Sò®ãþûY³\Uõ£ŽÊ;­®Š€ˆ€x‡@BŽ%^¹råÂÁJKu ÛÁj+’xK Gq!¬BE@D@’AÀ§p”‰!Õ¾úÊU.¢`å-·äLŸØ”<–‰€ˆ€ˆÀĉ-üæ=6.4ÆsÏ=' " " "à Ë–-ÃöíÛSÂáè§Ÿ\u£;îˆ-:–7uª*;¶%«4t&Àpj*Tˆ($)#°{,pÜq0Üì”~þxè!€ê{wÞ™ýºÎˆ€ˆ€x—@\޶1ÅCbϯø¬»wïÎúÌ7n 8ÖAü ”. T«ö?«h¾Žâ[5ˆ€ˆ€$ˆŽø{¦J•* ªÑÕð§TÏž®Ü>%)_,Ü0¬ù\€Òö`øÉ3”¤žLD@D@<@€a>i© p4l`ÑßP±¢À© " " M`áÂ…øõ×_ѵkWfœÎ0íµ×€>}€E‹ÜðžþÙÍ—]+`ºŠ÷/NŸE@D@L ®ËEx`@w‚C¬\ŒáÁÚµkJ+_¾|À±C€;†h5kÖLL…ªED@D@âL€ GTl,šSñ8×Ìâo¸X¼><{µd¶Ku‹€ˆ€x“C¨QiøUóRmР7©V‰€ˆ€d$Tr8â òÏÈ{¦N‹€ˆ€$Ÿ@4áÔØú&M€§ŸvÕÊ– ìÏÝwsæ‡xMG" " Þ'W‡£àÐf¾0$ñÆìpìøïúU¾K€»Zi5jÔpO诈€ˆ€¤8þ–©^½zŠ÷"¼æ [0N?¸òÊðò*µˆ€ˆ@æøá‡0iÒ$\~ùåèÖ­[æPE@D@ ùܱ#0zô`8»R¥J%¤NU"" " ñ$°aÃlÙ²%£Žn¼XµÊÝi”A~Vñüg¤²E@D ­ ,\¸cMït“Å;ôÐCÓº¯êœˆ€ˆ@j ÃQÍš5c¾`+ÜèQ¿>ðõ×±*Q刀ˆ€ˆ@îÆuëÖáâ‹/Æjî<ÌÁøŒ·wï^œyæ™9\ÍûÔ»ï¿þš{†2¨];÷4º"" "àmqu8:î¸ãP¦L™,»víˆ#²ŽãñaÁ‚6xŽ^mÚ´‰GU*3Ë—óârç>dº$" " )C`¹;¸¥ÂѾ}À_¦Œœm'íÀÀàÁÀ¹ç¦ÌmRCE@D@’HàñÇÇž={pË-·$±ªZD@D@r'0þ|sè1ÚîÝîó—íßDË–l š$" "v~þùg*Tœ÷ìÑ£GŽý=z4Š+æl,É1A.'w쮺 ¸òÊ\è´ˆ€ˆ@Zˆ«ÃQÑ¢EqÊ)§€zõÕW±dÉ’€s±ÿü¬âôAD@D ÄÝáèøãÇ©\Éò3†=ëÕ«—#Ñçw:ª¯¼ò î¿ÿþ€2*T¨€ÞÜ"K(ÿ"ÎXÿHá(¡äU™ˆ€ˆ@< øŽªU«Ïj^¶ý$Ã{ï—]Ôª•ðêU¡ˆ€ˆ@`µ'žx ;z¾f“ÓàŽª " "ž¼îpôÙgéٺ¯LD@D@âN€áÔh-Z´@éÒ¥ñÖ[oaß¾}æ t>¶nÝê\c85†\ëÚµ«sêjN˜`’©ßžCÍ¥t" " ©H îG„Ò¿{X²§%?›5k–3@?ÞÀü.…õqâĉèÞ½;† ’-ß7Þè ’Ù.èD\ üqÆêX.…£¸’Vá" " ‰$® G‰d¨ºD@D@Ò“À|€Å‹ãÚk¯C«ËD@D@DÀ‹¼ìpdÑÞ0m,d la׋ôÔ&t#àïpľsÌ1xðÁ1wî\Üpà ŽÓÑgæ ÛªU+TªT)¬î¿ÿ>`oN-,jJ," ©I !Gx  äxÁúcÚ¸q£#·ÞÑtb_{í5¬d,®lçÎøâ‹/pÆg OŸ>øã?²å¢·íyç—í¼NÄŸÀ~‡#)ÅŸ¶jH*1Lk•*UU¥ê” 0|øp”(QW_}uJ´WÈL>‡£zõêy€í©… ¢CÏ5M HSt8â ªmÛ¶- ¶… bðàÁ΋ƒ[“&M)ö2eÊ lÙ²æ»ÃÙ-É“|­X±"OU¤“N:ÉñÂ墠,ñüŽjÖ¬™ø¨Fˆ:U¬X1å•vLW^ S‰Œ()" "Q~øáL™2Åq6âf#™ˆ€ˆ€x•Ž*T¨€8ÀsMüüs·I6….¸àº+#Ñtòtåºê«¯¾ŠÆã7ÞpÚÁ(3áØÒ¥À·ßçœ[ã '§ÒŠ€ˆ€¤"„9¨dÔ»wo¬]»6G^T9úÜ÷„•cмOvëÖ  @á íZÞʰ«Ë—û:,…# ½‹€ˆ€¤>†T«–AÇ}øä ys9¥þ¿Jõ@D@’O€êFœ”¾é¦›’ßµ@D@D@ò @‡£úõëç‘"y—8Þ°!P§NòÚ šE@D@2‡ÀŒ3Àh2-Z´ÈÖéÊ•+;k¹T:jÖ¬Y€’âß~s‹®¿Þÿ,ðæ›0Ñ…S ¤¢#H_ ©æ^±ŸØ*×…^ˆ‚cW=•‘žþy :Å‹÷¯RŸL€ G î´û° Úáš`øªND@D nèpT½zõ¸•Ÿˆ‚-ú÷w'²ïº+5ªt&°`ÁŒ;:uÂ!‡’Î]UßD@D@Rœ•–-[æI‡£¹s>«zjŠCVóE@D@R†Ã©Ñrr8âùSmP3f ^xáæh·ÝÜppë­®ƒ‘/…‘LPÐB³ùÎè]D@D ÄÎã' JåË—Ç}÷݇qãÆ™¤Þ9(UªT¹“rRsàÀøì³Ï¥À«:J:*´ 5jÔHFõªSD@D@bN`ãÆØ²eKÊ;]{-,ö:,Ì-P¬XÌ1©@ #ðÄO`Ïž=¸å–[2¬çꮈ€ˆ@ª˜?¾©-ìó¤Ã‘Oì_G©ö¯JíÔ%às8¢‚Qnƈ2Mš4 ¸?ùä“3ú," "BNæÅjþ pQVÃi ýƒRSE@D Å L: 40%"“" Ã^}öœy&,ÔðÅÀwßM›º…P݈vÑEî»þŠ€ˆ€¤?¤:ùð–(Q‘`§ ;mï޽ؼy38É÷¢öÄEU¤²eË¢H‘"¾lz÷(GÝe!óJáÈ£÷G͟éÑR5¤ÚºuÀ7ºrÆÃ†…ßå`ï›'ë¦M›l|±F&" " 'àe‡#*C ”.íqˆjžˆ€ˆ@ZàÚë¼yópÁ„ÝŸ/¿„…Óv˜™ ê§œ²¿ªõ™P0eJâûc{me" " "T7b˜Ñ-Z„Uù-ÚµË=Õúž~(P ÷4º"" "^<¡p”.Hwî܉5kÖ8/*2Õ¨Q… Ši÷¶oßî(?Ñ«paoÞ¾¥K—:}fÿe" " ©M@c›{ÿ|G©¨pÔ¿?ðÉ'ÀW¸áÔRû_¤Z/" ÑÐØ=CîˆýÒ¶¶žb[YË•+}*AD@D jñßRaN2/ˆt8*^¼xžªµ óóÏnx³¼ÊÒ5ÄÐø{Ö?s°3 ×áˆã$­}{÷]E@D@D€¼é±å½2dˆŠÍWÌ Aƒ|cþ¾zõj|øá‡?~<~ÿý÷€ò©ÈT§NÔ«WÏ סC‡€ë¡Lž<#GŽÄŸæ>¼råJ'[s®d­L—ðœsÎÁ1ÇjqqO·lÙ2§Žš5kƽ.U " "{Û²3õ…T«V­Zö‹>c?QÀŸAÍ›»»‹<ÜT5MD@âJ@c[lñ~üñÇàÄÿYgÛ‚Ušˆ€ˆ@Xâ=¾¥Úœd^ðèpÄ9ZΩæfß}”)4nœ[ Hoñ¥L…# uÔQaUD‡#ê PÅH&" " >64¤Ÿ;ëÖ­ËêX¼Ž>1¹€{ï½×â‘Z@Òl×®]Ž“…>ûì3Çéˆé©~Š-Y²wÜq¦OŸž-9åW­ZÊØóÕ¶m[ :ÔŠí©8‰Æ°-R8Jâ PÕ" "%m9¤Â'¦«V­šsžµPì¸ôR bEü?{çîT•µáÞ›"½ƒˆtÔ+¢bïÎ8Ø{ïuÔ;c‚l¿Ž("‚"MA&]©Ò;ÿúrHn’›ä&¹'¹'É·žgÝœ³Ï®ïÉÍNöY{-¼ÿ¾S݃ÝT—D@D å4·¹ø}›XèÍ·ÿþîW®E@D@â"Êù-×$cAÛc –‹-ÂÑG+î¾X²6ÇÅÌæÚEs”Ûn.¼Ð åæZŪHD@2˜€æ·Ôßÿüó#…dÜwòõ×_ã´ÓNË¥Üupûíÿ´.4…<åPÛ" "8ÍmÑ™ÑÃÙ–.]:z&]a„ÓR¥€wßê×÷XçÔHÍmîƒÞ²e‹oCÍGaF­fÕ*H;TÎo™º&îfLá@IDATë&psäöíÛÑ´iÓXÙ|Î;ص à¦ÊT =E¼ô0kVª[Rý" "4¿¥þ>1B 7V&NÍœ"Á"k£OŸÔ÷Q-ˆ€ˆ€d¬ôp”ê[0uêT<öØc!Í0¼Y·nÝСC´k×[·n]õ~üñǘ8qb /´ÓËÑ[o½Õ…/_h[[üž‚X˜1Æ?üp_ts¸~ýz_½Ã† ÃÆ}õs§Î-·Ü‚!C†D­;БØóXìÜYÅ‹¯Ë(/)¡jE@D chn‹}«øC¼N:±3yìª9?ÄÂ…@ÅŠ똺#" i" ¹-5 ¹ã˜FG §–¾ªUD@ "Êù-“×$cqã-¥ ƒ#æyî9`ð`àûïN˜’:ùßÿœº p¼”º¨fðÍoé¹ônDIÔàˆF²”¾}Wý?ùI$ðÊÐe»¸ÕeŸÐ“ÏÛo¿š5kú“|¯;vÄé§ŸŽ÷Þ{ϼþ܆A£0DÚ¨Q£pÒI'ùÎÃÿ >seŸ”2÷¯¾ú*X_°tïÞgœqγ­7~ã$ÆV1b œ5mÇö<ÖŒ¶¡vír>ûikX ‰€ˆ€Š€æ¶Øøèá¨G±3yðªŒO¢«"“Î;'Ô Ž*UºtI¨˜2‹€ˆ€ä…TKð&ӋдiÓ¥jدPºy 76 d°†:cx´`yú駃OÇ;vì0Wº/Îyðàƒæ36òg ±S¸·%.• ÊÊÇÙeýR.ª{ vE@D QšÛbÛ°a6oÞlÆ´µcgÔUÏÐÜ–š[AÏ ÞÅV™3Íó_jˆ¨VH/TÎo™¾&ëNdpÄ=¢óæ95x ó´4VÕ1¯Ýx#pÔQÀœ9‘³q/ªík•ˆ€ˆ@ÎÐü–¾·=U¨P-[¶Œ»ÑM›€~zõJÊEÜÜ”QD@r…€ ޼Ó}ôQH‰Ë/¿õë×I‹trõÕWû¢ù¯14ËÚµký§Wz>ZµjUà¼D=ñÄç‘èù(ØýáŒ3°téÒHYSž¶ß~{ðçŸß‚†PÌ  ¹-ö}¢w#Š×¬r‘üØc—_Ž=]\  ¹-5wyôèÑ !î)§œ’šT«ˆ€ˆ@L©œß2}M28/^5Š˜mÖ, ysàÎ;™#¿€RÄq$.YÛ$ |ý5l#)lƒi…”ED@r”€æ·ôÜxFa™û,ä<]'|(»{÷ny8Jpµ#" .Ÿ4·…B¥‘0ÅëŽ,‚+¾ø˜??´ÿ:\$ ¹-5wáÔ(§žzjjP­" " 1 ¤r~Ëô5ÉXàhpÄ £¥K—Ž˜Í¿ËjåË;!Î ëáˆg)¶Õ6í²Ë`áHa5týÈ# ù-E*æ˜Ë½¿þú+ÄA<íU¬ôësL<¹•GD@D ×Èà(Á;¾bÅŠ@‰jÕªÙF ´§4lØ0$ç²eËBÎyâŸÊãb¶¦gÏž<,P‚=1sQýþûï¾¾ÊÃQ·LD@DÀ34·Å¾~ƒ#¯{8zä€ ×_{<º*" ¹@@s›ûwy×®]àÎã: qãÆî7 E@D@ $Êù-Ó×$cÁ£ÁQÓ¦M£f¡Á½ù÷sÒË‘?ÄZÔB\ cûÊ•ßg?ÿ œy&0r$ж-ðùç°¾T Ë" "C4¿¥çfûçúÎ;'Ô S~ò pÐA Sf! ƒ£otðŸš5k&TÚoŒã/n€´`ÁÛå’·Í¥­ýÝÿýýÙc¾¶iÓåÊ• äñÇ&$¤á`ýzàÛo7ZK•äá( ¼Õ„ˆ€¸E@s[l’þj^÷pĨ¯Ã†Á¾;ĮЀˆ@.ÐÜæþ]k®ø{UáÔÜg«E@D ^©šß2}M2?Î]ôæËàhÜ8 E‹¼ßR ¯Fƒ U«bÕûÚàÁÀºuŽ·¤*U€·ßÞxØ´ øÛßœ¶x.4¿¥ç]ðã?ú w`žÖÕŠˆ€ˆ@¶(™­KÕ¸^~ùe0Î)¥<}ìÆ)Û¶mC¸[ȃ>8¤ôôéÓCΛó×mœRªT)4hÐt‰HÙiU7lØ`;il+MšdÌà†޲ÖN„<¥ ºšhn‹ 1S<Õ©P%" " €æ6÷ß §æ>SÕ(" ‰HÕü–ék’±8ú7eF38¢úÅ‹K/ͫſ$˰j5jä¥'zTû¬ï8ø½‰Ïýúôé“Psô¿À°£H„?ëxà_‘Ý»wûœ¤$R^y3‹€ ŽÒp¿øOõæ›o†´tã7†œó„î}ƒ%Qƒ£pã".4æ¯Ø…ÖÍY0ÖÇÜW²xøvœ(õÉà( %‹€xš@ýúõ1tèÐ@?þø„<Ø æØA¦ÍmuëÖïõóÏ?¸S¥K—Ç:à]†87¬ºtMD@ÒI`m£?á„|MŽ1w¤ßùŸ¨¥³ÔV¦ÍmÜ™Z½zõï1©2˜þþûïAÜ /¼0ƒî¨º*"Ö±wïÞ¾¡Mš4 ï½÷^6ÓÕ1Å3¿yeM’óX¹råBæ¶Â†¶NÆàÈïáhÞÂø®ø Žš4i±À¸qNhêà=›Ìj]ñy8ŠX¨€D†gëÒf¨[@F]#ÀäþÍäëÖ­¿çK¢ÈÄù£á37>ÃssŽ‹N)ÿ†S£zè¡ù/FI™1˜?öžŒ’AÉ" "…@ÅŠA¥ÐÃׯ$ÙK xö­hG6{öl 0 Ÿ±=Ý~ûí;þã>QG•*U ©—!Ò)ôpT¬Ø{àÚ-}P[" " ©#‹siÒÃQawÕÒÑáᇟ}æÞý1»fÜs`NKìË»{õª&È%¹:·%z?øàßÂx‡-ªü" " E@ Ñù-Ó×$c!¦Á=†oÔd:›ÿå—üaÓø`•H ©–¨X´S ÐI"" "à.ÍoÉóô%âáhôh§½¾}“oW%E@D@²Ÿ€ÌÉ\¾Ç6lðÅÛe|qZìËqæwðÁŒêý‡^5‚%Ñ]ZŒï,‘~H_wûØ ©ö¶F"" "=rynãØ7oÞ\hGŒäfÑh0b„ã†Øw½Í™Üy'l—·5ªÈ¹<·%z—§L™‚Å‹ãºë®K´¨ò‹€ˆ€¤™@²ó[¦¯IÆÂLƒ£¦M›FÌ2aÀ=zä¿ÌÍÉD»;Ö©«gÏüu*ED@D 9šß’ã\jüøñhÖ¬™Ï78=Öñ•WíÚ]»ÆÊ¥k" " ¹N@G.½h\4|øpŸG#º½ †1¸é¦›pÒI''ç;>à€BÒ6nÜr^Р㯋ßÅtpZ*—-Ûƒ½{G½zõRÙŒêHÍméQ ãáhÁ€ Ù”/¿t^ û—6Í÷Þ Û¥ \sMakSyÈšÛ¿× §–83•t(ìü–ék’ÑxoݺÕ÷›®W¯^³|÷“ܽ{þËg•?-ž”¶maÞí>}âÉ­<" " ±h~‹E'þkôÞ>ßb£]tÑEñ²œeʽ{'TD™E@D@r@Ê ŽúõëxX—.¾ôDN¡Ço¼Ñ¼ ˜› áî âÚk¯ Äà ºœïî}ƒ%Qƒ£mÛ¶ Ò%;vëÖ1Bßry8Jtµ#" )$ ¹ÍËä”:uê8 Iü5§‡>iÝÚq×ÿë¯ÀÁ'QQP‘·ßvÜûßuPµjЊ€ˆ€D% ¹-*š¨öîÝ‹wÞyÇ·©¤K—.Qó邈€ˆ@Ñpc~Ëä5ÉXäØîÎeÑ<ýðlÍ ‘[Âßz÷ÝçVmªGD@r—€æ7÷îý˜1c|•E3Àu¯%Õ$" "‹RnpÄ$é6Jç|óÍ7ñðÃ#<œYWó1xóÍ7£E‹qw§°?îW­ZÒV: Žö9€°öÿ‡£» È<šÛòì«jÖzxì1`Ó¦¼ú“9ÚµËYÀ¦¡‘¼%CPeD@r‘€æ¶äîú·ß~‹… ú~Û†‡ÛI®F•p“€[ó[&¯IÆâÉpj”hGÿ÷0@qî¡”ˆ€ˆ€x†€æ7woÅ7ß|ã«0^ƒ#†ÕÜèî=Pm" "ÍRnp”­ð6ÙÓB†I=ztÈ7nŒ[n¹=“ÔþãÞÿ3¤'~/ ÌR²dɸ¼*Ũ.¡Kû@X™?ÌÃQË„Ê*³ˆ€ˆ€7hnËüsk²Ž&Mr<  ¼£ù[I,套€yó£#†T“ˆ€ˆ€D' ¹-:›x®¼öÚk¾lçw^<Ù•GD@D MÜžß2yM2ò‚ ŽJ—Z°Œ¹s'PªT¬VtMD@DÀ-šßÜ"Z Žh|[¯^½Ð ζl; ¸ê*àÒK#dP’ˆ€ˆ€„ÁQxOé½(ØØˆ>ÿøÇ?|1PKó×jR£FRS§N 9uÂpjÁJíÛ·G:w Åó¥%ÖXtMD@D hhnËÏÝ?·&kpDïF”Aƒœ×Âþݸ¸ûn†xƒ…l-lm*/" ÙO@s[ò÷x‹­4¿÷Þ{¶Ø|XBž{“oQ%E@D@â%àöü–Ék’±˜dp«,¯5l04ö§Ÿ”Ó¹þçŸÀþûÇ—W¹D@D@òÐü–ŸIaS~ÿýwóæ7_|q\UÝ{/ðË/°¨.qeW&@Ê ŽÎ9çläÓ±,’¡C‡âË/¿ Œ¨Zµjxá…@#ŸÂHóæÍÁøþÐhsçÎõ…£«P¡BÕÒ8i÷îÝ|GuTà8y!Õ–›‡£ºéhRmˆ€ˆ€¸H@s[d˜ôpDÞZµjEÎP@êGÁÒ:1ÎË Ë¶z5ðÊ+@ùòqR6ÈQšÛ wãßÿ} º ònT8Ž*-" nHÅü–Ék’±øÒ਼ýpª]»v¬lQ¯Uªäx¬š!ì‘G܇:yrØŠ€ˆ€H@ó[ˆ’Ê0fÌ_¹x©͚üë_À!‡W\‘Ts*$" "ƒRnptÁdÖE‹áÑG Œ©\¹rxÉb›´mÛ6–ìAq Šz¼Å[y…OMöX ÔñãÇãè£.°JºD –#ù 7rÚiÀë¯ßŠ™3gƒXÌ! ¹-ú½¢‡£ým‹j²Þ gÌ.Œ^"W–.žz ööð7‘’Ê+" ¹G@s[áï9é•)S,|eªAD@DÀ©šß2yM2X5iÒ$_–½{a›GÞ½ƒÊw9`{CññÇŽ—‡‚ªѻ=Bœyf ¸D@D@â$ ù-NPIdó?;ìÙ³g¥¯¼æØxþyÀWJD@D@D .š2â”—iäÈ‘æJ0Ï—àƒ>花‘¿…þýûû}¯4f*HÖ¯_#F²5jÔ7œ§ã€Ž¶mûØbÀÚÖ‰ˆ€ˆ@FÐÜývÑÃQ²»aYkÅŠ@›6¡õ_v6݇fˆrvÛmÀÖ­ÀãëGDJÍmI,Y²Ü {â‰'jCIRUHD@RC •ó[¦®IF#MOð|€Ý´iÓ|YèÁU_~9ߥzyàÆ‚ŒXhÜ8€†Lq<Ï iC'" " €æ·Ô½ hpÔ¬Y3{vW/f#ØcÇ—_tî3«.Š€ˆ€ˆ@…à(øä“O> d♿ýíos7ZXÜ•<0PÕ sðöÛoÎÃèâþ óm¸eË–À¥ŽÓyÀX°}iIgÔ–ˆ€ˆ@|4·EçDGuêÔ‰ž!‰+«VŸ}lØXásÏ®¾èÛ7±rÊ-" ¹H@s[áî:Ãìµ§¦ §V8Ž*-" nHåü–Ék’‘8/4W³Ü4ʇ¬áBã JÎk´¿¶§ÓÂkG»šîw>/ƒ£P.:xh~‹‡Rây–-[zû+(œÚºuÀ 75j \r pÜqÀ>GHІ ƒ…BugWŸù>ø °m[ zˆ€ˆ€@@s[€b\ÞfÎðáÃѱcGóÔg®ú$" " ž!®ù-“Ö$cÝz8¢gùJ•*ÅÊV൳Ί¼‘$¸ éQzöt^õWD@D ~šßâg•HN:/øÍÞyä‘Q‹ÑÈhêT˜w[ààƒ£fÓˆI åŽb¶ãâ›o¾âÍçbs!Pºté%Résg@M—/^ÿøÇ?pá…â³Ï>ÃŒ3@o ôEo õë×7ÏB½#Æ"OWÙŽãÀÊâªá7³”–ÏÅt²÷L[tçÁ7ÂÆÀ¦MŽÒ®^½¢ïâŸÂ>L E˜O×®fÏί ƒרŒ 4o{;wÂâMÅŠÅÎç¿Ê0“cÆ6­[f4()bæQUªq'ЦyÍmѹGòpd1~¼³ûgëVX¸Sçߨœ ‚ Ñ.2ÛôãwΓýËÔ›nr>^N¶•Ü# ¹-ù{>Ò¾ûÒÓ®¼%ÏP%E@D UÒ9¿eÊšd4Ö{ÌeÃl[ïéÁh¯-aÆ»|Ãú¹$ć±¶‹òå#·øÍ7À¢·E. TÍo®Œáó“^Œ•A8šÏ4lÜqG„ J8 xÖà(ÎþçD¶òökö4 ,Nõ¢œ}6ðÝw×â…¾4û’!^ì¢wú´k`a-V@ËôÉ.\¡øè£ðÔøÏúï§Ÿ€Ÿvô×_ÄËÕWÿ{pJþãE‹`Ûš-=è g•…OÀçÏæÍs^y¼ysþò#F¼þË/»ï¶ow”žÌxLNôìÅ]h+æ½ò˜F:+W4rzûmØöëüm§Œ\tQpJôc®qœ:ë׫V9íG/á\¡!âCíÚ‡âô‰¯\i¢!­x¿Gv”÷‡ßè)]ºßïÇúÛ­›3f®ŠYEŸ²¿<æk©RÎ}æ½VºYáŠûïU{ìk¼ìó?Àž@9m±½`eMšÄ®‡ï“… ÷¹$dd;Á•;Zx˜'7Ï‚Êñúœ9Nþ>püšï¿?P½:ÀWÿ1ï‹ÿeÑ"€Ê_X’´ðúÜFáޏkõœqsÂh†ÐÀ)§—^ p.äÛíõ×ë}49õ;£Gù¿þå| ½ü²ó‘9—RE@D@¼B æ¶‚X½öÚkö¯”Ñî³¢-¨€®‹€ˆ€d5LÛÚÚÃVûÍߪU«ûc{9ñ·¿O> œ~zÈ¥¨'48âò—¿Ú¶ÍŸËT\Z8é¤ü×”"" "àM™:¿%B“áÔ(‘Œo™ÎÇ \î_° ºA-óID@D@D  q<ñ-¨ ]ÚA,2;€=¨Y³ffâ W6üò‹£4D¸òÊÈ+ ñކæ‘ÊüVÒ" à“ê òŒsø¤štÂ…Æ óð ãÒ¥Ž÷¾2¨<Œh(ãu4mšßh†m$d@Ï;ô4yrþÜ ìk®©AC‹ì;öÑ0ˆ†4 ·‡ÑÈ£LGi‘·¼Ñ«ÙÐ8‹†T”qЧ3†x oXŽï'²¡ðÞÐНdÈW^7¯h!F@4"ËtÊô—\Ã\¨9«e ß³¼ÿl#–Ðÿ*>ÇÚ1þï7±üïM—ñ=ÃW*ƒG³mæ§7( ÇqË-±ÿ'×­†ÌC^à=[·.P­šóˉãÏIþô;hÃÐiMEÀGàwóvVÌ>sRG|›Ð¾ïwc#f:ágÚà”Á·+¯Ç+,ËoÚPò£-\®¿Þiçüóïè\D@D@Ü'@CÛÑf ‚MPÕi¨- %Àpj”–a.‡¸'N­¹¬¯ø—T¸ìÉàèóÏå„ΔâmBùD@D@DÀu48:Ð&±º\"\ŠW$í(p”," "7{Ò*ÂXjOLæ.—3Bèeå­·€tž/Z”çqÆ?€—^ú÷î¼ÓñxãOçõ¶Û`ñ÷B hLC#º²à*™–ŒÐ ãè£CûÌpPô°CmßÞyåN.½$#4 G ²hxDÙʕ¦Ð ¥0B¾Ôx„FV4Bò{ó‰§ óø™Ä›?™|T =LÑðˆž¬¨ô0Å8É40¢ru*’eS:ú_n7ˆ%Ün—L½þ:yé¢%\x¿ïðî]a–¡”üÞ”ü+páåƒÏ5n½5ÏûV°§§à|<¦]ÄÐÒ¢W/ Gç½ÇkÑ„áó轋}¾ààœsœÿµàÏ%zèb>Z†øh%8·Ñ–!]ܱ藍ð·;«ß}×±ËKäß°o_gªà¿«… ôÓÎN"" " é ð†y“ÜmFì §–ÚjCD@D •fÍšå«>ÜÊsOR4/³‘úÄ=f.‰Eþä~6:¦Ôe¥‰€ˆ€d9®i.0×E—\rI–TÃðyá.dA›‘ÅÁ4PÉ¡ñÓÒ`†!´Z·v”&Ýô”B¯8#G:J74<êÔ)¾’ iêÕsB4ÑSPçÎy.1â«%z.z(bŒzË¡W¶“Èö¬è5G¾Bï3{¼ã\KáRiB£*¯ CrQO>9½=MÄÊ!RÏø¿À•7H-[æü/ÐȈ»ƒ v"•7ÿŒGåIш,\iÄDC1%"ô&Å­…\9ŒfÌÇU@*Ÿ$"P%æa­>?cMî½×y[ÒAY4‰ö¶‹–ßopDÛÎHGÑÊ)]D@D@RAàu³ª¥g£~ýú¥¢zÕ)" " i#à÷p¼ViŽü|Î54^gÓì°ßàˆŽ"ÉðáCµq–DD@D@¼@€Þ(½¸‘7L¦MsÖ8ÝZò«^§" " 9HÀžàKD ytòÎ;;ÍYÈ~Q«Aò¥»$ ˆ¾úÊñšÉK½÷|ð0}:pß}Àûï ðé0½‡Å€Ï×}ÆÝ¡¦RèÁE"n —þ_PÓ%4’¢1Õ-9æ·jR=9N€–[XÌÃh0jÂéXÆFÉàb$F:¡ûòKà†Ç[ÿý/pãîÙù%Ó/•È=|0û«ž_uÕU¶'à Ñ%" " "Á8¯qóHå L\Öã¾§OLl`ÜûV£Íàˆšéh\"" " ^!ÍàhÑ"€ë‘§ž ˜ƒ[‰ˆ€ˆ€¸B Câ_¹2VU’t†ré¥\>9³ ŽhàлwÁ!ÁþjÄg«Ÿ4ÓHé½÷R@RUŠ€ˆ€x‰Àï¿ÿî +“JcZ1Zà¸qÀ† À)§8!Ôh€$t˜p ŽÞÄÃw¶ê©ë`Ÿ>NÝS¦ýú=–º¶T³ˆ€ˆ€D#0uêTT­ZÕ~B¥à7T´F•." " ) Àpj”–-[jÿâ gy±ÿ@RB48¢ÐË—;8ê(à“Oœtý/à¼ôÐCU­+—aút€ÚµszV¦ ðÖ[0î^è©ú " "Mdp”Mw³ÆìáÈÕ°3Ÿ}œ{nb#â7¦‹/n¸!5ÆF‰õF¹E@D@2˜ÀÒ¥K­÷G¡aC3r…Í/)’öíFì\¹6̱™MQSªVD@D@"Ø»w¯í|ý‡rHÄëJL"0kÖ,_wƒCª1œåÄ×Dÿ2¤eÎàÕWã¥[nqÒôWD@D@¼Bà£ü=iüÂŒokú¯%Ju " " ®Á‘+s·•)³Ñœm0G ÜÑ©ðøã@Ù²l ôµT) ¤½uý¯þc¶_½º{}PM" " 9K`Á‚å6ö hÑ"µ¿Â‹s"væ,h \D@D È Ì7ϲ6l@‡м/ꀈ€ˆ€–€ßÃÑÁ쫊žèQCëÕK®v¿‡£_; hÝèÖ-¹ºTJD@D@RAÀö‘øæ»R¥æ˜çÚ­èÜ9¿±Q*ÚU" " " ƒ#½ EÀ18Zf¶?Q¥J•BÕR˜‹ûBÒu"" " i °|ù”.½?^ÝB{JD@D@D ‹ L›6Í7ºŽ|+ '@Gõë×GåÊ•}#ùî;`íZàŸÿL~`-ZÀ¼ôtT®\òõ¨¤ˆ€ˆ€¤ŠÀ?:ÔЫW¯T5£zE@D@D âùR” qزXn öîo!gÆWj×. OàÅã˯\" " "P–,Yb»_ë¡|ysA$,&0uêTßèdp”Å7YC!°gÏüjnˆ‚é}ö™3øþý“‡@'ëmÛÊØ(y‚*)" "jyáÔ>Âi§–êæT¿ˆ€ˆ€Èà(€B‰X°À)±uë/ñ‡S»ùf૯€yómNùE@D@D mhpäj¨Ð´õ\ ‰€ˆ€ˆ@bhpT¾|y4÷Ç‹I¬¸r‹€ˆ€ˆ€g,\¸[·nEË–-}zàà›o€öíI:¬#0rän+¶ÚŒn7£oß¾Y7> HD@DÀ»RÍ»÷Æó=c85Ê®]³ã{(ûá‡ÀO8AÎ~Ø)¬¿" " "à1›7oƺuëâ›Û<ÖwuGD@D@%ÀjíÚµC‰%-ªü" " "à) §F öpTÒV¿{öôT7Õp•À¢EÀ¬Yü=÷1®»îWëVe" " "P´=p@AýöË'Ÿ|‚2eÊ'Å}|òÉ'ÇWã'à78~³‡²ÇÅ.ÈÌ\»ùÀ»ïüµ/ w#à,ìÜy¤{§.‰€ˆ€ˆ€{–.]Š5kÖ`À€îUªšD@D@D ˆÌœ9Ó×r°ÁQuEÍŠ€ˆ€ˆ@ÚŒµÇÚ*Ž*U¾ÅYg½˜¶vÕˆ€ˆ€@Ú­>ž ‡›$ä®»îJ¢”SDGI£‹Ypþ|ÿe5ðŸäݶ 4ظøâ  nÝüy”"" " !à=‰‰÷z¤Gꆈ€ˆ€¤†½Q:v옚T«ˆ€ˆ€¤‘€ßàèàƒNc«jJD@D@Š–ÀË/¯²TÅUWµHÚqCÑŽ@­‹€ˆ€d2â™Üyõ½h ÐDéÒ;­+b]uðÓOÀÝw}úm§Õºˆ€ˆ€@`Þ¼–£7ÞU@N]Ì&0uêTß:tèÙQïE@D@DÀ0¤ZýúõQ¹re¬²g¯ÿú°l™Ðˆ€ˆ€ˆ@vX·n¤…È‚Áƒ/Îîjt" " ž$ ƒ#OÞ–ÌèÔÇ]ô€¯³ü1ŸOV®dà¿ÿŽ=¸ýö|Y” " " ^#ðóÏ[|]:øà’^ëšú#" " ® ‡£R¥J¡uëÖ®Ö«ÊD@D@D Ýöìكٳg£eË–¾¦édýºë€1cÒݵ'" " é#0aÂ3®½_<Õ«WO_ÃjID@D@öГ4½’&P¬°fÍ,³ƒºÁaÒ¶ož~¸ÿ~'Œ½½ù&,cÒm© ˆ€ˆ€¤‹À¼yNK;VJW“jGD@D@Š„=ÑØ¨téÒEÒ¾x ì2ç£k×:ËL›69¯'VÃŽåâ­Bù²œÀ¢E‹°eË´jÕÊ7ÒÏ?w–">:ˮቀˆ€ä4'žxÂ÷Œîšk®Éi¼ˆ€ˆ@ÑH¹ÁÑ|î0‘d'%W­víÚy Ô~\=°`ЬðÆ@ÿþÙ9xJD@D + ,]ZÆ7®¶mËgåø4( 5kÖØNØe8ZObõ†ð½k ƒµzµ³o­D‰¼Ž}õ•ã<;/…GmÑ·o½Ð$å,™3gúÆî78j×(n¾ýkÖÌY$¸ˆ€ˆ@–X`ÏáFމãŽ;tP–VÃð*”U­ZÕ«cW¿\ °téR4hИ3¸â ÇO±ÅIÇ£ÂÆÂ,‘\hEUˆ€ˆ€ˆ@ú¬^í|w9ðÀôµ©–D@D@D Ýè݈ұcÇt7­öD@r„À† ÀâÅŽšóØž5ø_ÿó sç<4 ¹ã޼s:ήQ#ï¼Iàï*V*™#R¾þñÇÌŸ¿2/“Žrš€ßàÈRíÆs‡/" "žxâ9ŸÃ‡ëCT"" " ED åGE4.5›b3f¿ý¶ Ë—o@÷îfpôÉ'ÀôéÀ%—8¡Ô‚W…RÜU/" " nØ´‰žûÖ£reM»ÉUu‰€ˆ€x‹€ßà¨C‡Þê˜z#"‘è¡hâD`Â`üx`Ò$`ݺüC¡aQ­ZNx´à«*?ÿ pP½:PªTðU€›žy&4mìØ2Ĭš$"`fÍšåãà78Èfëׯ·ïAõì;ÓJ4od¥ÍƒÖØD@D@ÛѼ‰@n ÁQ=‹ øÝw}?öØÜ¿F+" ";¾ùæì-ö]ðÔÜ´F*" "àii58¢qÑc=z.ò¥’N J/ñî~ç`òdØŽ¡ 8ì0óQ,,!°téRÓfɽÔ0D@D@"Øf– ³gÏÆ‰'ž9ƒRE@\%@ïDÏ?ïx&⾺W^ ­þ…€+®MóŸÕ® ´k|°ã¹èˆ#€úõýWõ*"@{öìñÍk=zôÀ_¶Œž=ÅFD@D@²“À_üd{ ߟãÓ¨D@D@2@Ú Ž6oÞŒk®¹ÆÜ?›ÿç$¥\¹rغukÌÒ¥K—Æ¥—^Š®]»¢mÛ¶à¹Ä] ¼ý6P¢O)óÁ­xâì.dÕ&" "v;wî´+, E„8iïÔ˜>}:víÚ…SK _Õš}è˜ÛlÒͨ!¿Ú×G,Xüúkž~ú)Àg~Y¿xðAçŒNÅ ŽhL4hP¡‚­³˜QóæÀA¶·‹¯g-þªô*"À¢E‹°eËûŸi‡!Cæ•/!£’D@D@D à 0*Ì7ß4°Q”´ç >u_D@D k¤Íà(–±QõêÕQІ+Èܦb²ÀVsü:zôhßÃAÑfü²Î|MwêÔÉŸ¤W— üöP½úNœµf nú¿ÿƒY‘}ûºÜŠªô˜4i¹=H„ªU›¥·aµ&" " i$0mÚ4_kòœFèj*c |õpúé°u¦ø†`l*Ôàˆ†C F#¤*Uò×CO,òÆ’Ÿ‹RD ^ §F)^üH_¸A…S‹—œò‰€ˆ€dÎy[¶ D¹r›q f­.H‹ÁÑðáÃ#z6:¶œ 0Gy$J–Ìß•bÅŠåCTÓVh¨ô`D¡!ô½Ã8_ûä­·ÞòÕwë­·ú“ôê"Õ¬¹G­vÛ}+ѽ»‹µ«*(_|±Ù~;wš1­DD@D@²”ÀÔ©S}#“‡£,½ÁVÂèÁh­oüþ;в%P¶l^ô4Ô´)`‘š|aš¸LU¼xž–(4lè„.cÓ¦Mx衇òÕzß}÷ùŒò]H0¡¢ù—¾çž{Я_?ÜrË-X¶l™¯†×_ÝŠZ⤓NJ°FeE`Ãg!îÀ¦+aŠñ—1ÞÏBÝID@D@D Ó Ìœi!BMZ·.“éCQÿE@D@D *z8ªU«–…nª5.ˆ@6°ÈX¾Ü1$¢1µCÇx(x|íÛ¿üâ¤0„üñÇç]¥Ç¢I“òÎu$"à=œ×Š›%à´i5ÁÿÙV­¼×GõHD@D@Ü ðÁŸ×䦛p£:Õ!" " ®H¹Áà1޶_èµèA ^Ê)§ø“\y=ôÐCñì³Ïâä“O¶p({|uÞ{ï½`z:u\iC•ônD©¾õÐaãVóN%l °k—=‘Âvtîìüxφ1i " " "L`—Y`̘1½{÷NÖ±d$.ý<ü0°z5°vm~¥×¢}ËCñ™“lŸ·¢@‚œz*`¸ÍÏñV|MÇ" Þ'0yòd4iÒ sçÇEy¿¿ê¡ˆ€ˆ€$C`³9f_¼ø0”/ÿ‹E€iL*#" " )!rƒ£Q£F…tüÄOtÝØÈß@ ó_=pà@¼ýöÛ¾¤Í63ÔÚµ×^ëÏ¢×B˜?ß© ÉºÉ¾ƒJò UH¢*." "àµkó;Ë hÑb¥Wº¤~ˆ€ˆ€ˆ€«vfÛ¶mæå¥ƒ«õª2HÅ‹… yó€C:vÌk‰¡ÍlßþøÃIc(´jÕ€ýö FDuëÂçñ„¯ÔH¡Íî¾;¯N‰€duëÖÙæÈßХ˭àšå±ÇfVÿÕ[ˆ—À“Oþ޽{뚱ѯVDGñrS>ÔH©ÁÑró]=qâÄQœ{î¹!çnŸ <Ÿ}öÖ¯_﫚OW_}µÏµ®Ûmåb}~GÖNÂ&óVU±{÷\Ä 1‹€ˆ€d!%K– ¬=©ªQ£FŽNCX¸™i> ƒ­6FŠˆ½Íœé¨Ù¡fMà¶ÛB;sçÀСNÚ­·†1uìX€QÞid¤hï¡ìt&¹@`Ê”)¾až~ú<ðЩS.ŒZcÈE¯¾jÖöØŠ‹/®˜‹ÃטE@D@8ôP Q£È†Íš…T¡#Àpj”.]:ÚÚoŽ ^ÃÈsçò;umïæÍ·*" "Rj-²jÕª ;w9OÕI³°'þø”Á‘;´¹@X¹üNÔÚò'>­ß=Ü©Vµˆ€ˆ€ˆ@‘ ‡£C«C"" " YJ`üøñæE¦&7nœ¥#Ô°¼Dàœs€·Þ‚…~íU¥J@Ë–ÀqÇ9¯­ZÔHvßG P%" "‰×|K”(öíÛGº¬4È ¯¼â £Y³oQµª}É–ˆ€ˆ€ˆ€‡¤ÔàhåÊ•!C­]›¸©—&Mš„4nørQ'  ÁQãòË-Àê¶m*«Ì" " "àU¼ýõ$*W¶-CÈB›6mÂÏ?ÿìóœ…ÃÓRH`¹-ØÛÇçe¨T©Ð†èÁhÌ[X œw^è5FîÛ½àž°¦Måq­Z¡ùt&" ɘ4i’0¶Dùòå“­BåD@D@DÀÓöì^ye—õq1úõS85Oß,uND@r”@J ŽÂ }êÔ©“ÌM¹’$á†OA—t˜íÛeË€CÊÿú®*e!ò$" " " ¾øÂž¢áÔ¨ñ|6 Gc|&L˜`ƻѽ{÷|×” Áh<ôÍ7À×_;Ê”yóã!çÌ Ö®Àµ‚êÕz4*^ܸ暼c‰€ˆ€ÛVÛ‡½Ô~ø+X¸Ð6HÊyŸÛˆUŸˆ€ˆ€ðûõ•W¾{î‚^½þá© " " "J ¥GÜA,ÕªU >-ðøŠ+®ÀÀùößÿÀq¬ƒªU«úÜér1•âtó@IDAT ’ÂX»èÐfùyë, woGipMš7>ý4ÚU¥‹€ˆ@j 8G'û9ÙyImƒª]D@D@ŠˆÀ7æ~´M›6æZDÝQ³" " "B ¥Gቖ/_ÒxªNþüóϪõ¬RX'¡¾úÊwο÷Ô¯zMg" " "¡V¬¨d=Ÿ‚úšÛ2ôªÛ" " ±ìÚµ 'N´°3‡£dÉ”.Äꆮ¥™Àwß~ L›|ñеk^êÕþö7€é©Mš伿åÒ‘ˆ€x— ŽJ”¨…NöàÈ#‹{·£ê™ˆ€ˆ€‚À<‹kÌg«§Ÿ~z!jQQH”®4Ö¦Kœ 7nœí”³­r)–™3g†´nørQ'‰0ƒ£•åËc™mƒ¬U«Vbe•[D@D@ýô# peÖŽSÈ|)78ºà‚ 0lØ0Ðóe÷îݸì²Ë@Ã#z?rSØÎ(ú ¶_¢D‰ †À’%K|Åé½J"" " Ù@`ÆŒm6ŒrhÑ"å_‹²—Æ " "aæÌ™ƒU«V™¡ŠYªHRN`ñbàw:ßhÖ ¶ÙÑ–-2eòš§#èý xï=€?¯ü1ïN9hÞ°hæ¨]Ûñ`Äc‰ˆ€ˆðñÇ• ÃlÙbÈB§ŸlÜ8Ü Žö¢ÝšJD@D@DÀ£Rþd­bÅŠ 3x¦gh§ ½ù¥€*ÈOà×_íÃupÐAÚdšŸŽRD@D@²…À7ß|ãÊto*H¹ÁÇ}º™âr‘óÿû_=]rÉ%8ãŒ3pÑEY“†kñ¬µÐ^o¾ù¦-ê½…õë×ç+vûí·ƒO÷ø ŽäáÈ=¦ªID@D h ,^\Ú:0ϼ ˜{‰ˆ€ˆ€d¿ÁQ·nݲldéÎŽ°õ FÐöFŽ.¾ú ¶ÖìÜ ”/ïÑ™ÔQG‹3g:Ú¥KhùÖ­Y³€ƒM×™ˆ€ˆ@lóæ-ÃŽGZ(ʨ^ýÀØ™uUD@D@2˜ ŽZš«Ôá?F2xL꺈€ˆ@öH‹ÁQñâÅñÄOàüóÏÇ”)NŒm?Êwß}T.~Ò-`Û¶m}héÒ|ø—'{öìÁêÕ«ñûï¿ã?þ0wã?âÃ?´˜¶úAN;í4Û ¨í€Ð*IG…§Â" " #°}»í‹­óæÎúõåùÁc·GÝp Ž<ð@ Íå®'?þÿí7ÇCO°gºì‰*, <^x˜4 ¸òJØšFh·ž|øö[ ¤­ª}4,dpÒI@… yùhLDµå‰ˆ"c£ˆX”(" 1 ¼òÊ2»^={®™OE@D@D  ¬Yãü¦˜6m–.]Šk¯½6‡¡>‹€ˆ€ä´‘' ˆ^°Õºk®¹Æçí(œñxó;N¥Ð@‰áÐè¨R¥J§t#V¬X]»v…‹xÞ¯_?Üqǯ)±pø‡"/…ã¨Ò" " Þ P¦ ØW‚48’¤ÀªU«lëv4hÐ }ª%H!ÎkœßŽ<òȶ¢ªE@D@D ý6oÞláÄ~Æ 'œPèÆí'¸í°…ýÌ_«7gö¡xôQX˜óüyÜN©RÅ1€êÖ 8ì°üµŸu0hãÕ(ÿU¥ˆ€ˆ€d*O?57{˜cŽÑšp¦ÞCõ[D@D 2† }ÿ}àÀ·cêÔ7í÷Ì Tቈ€ˆ€xœ@‘ó©i>Í?þxŸ§ëØhQýâ‹/*l7n‡z!" "àRfêÔ©(S¦Œ µ© ðï¿ÿÞÂÎìB=î”íùAñâ¡Å"ùs<þ¸ãe¨Jü¯ Ë6jðÖ[Nx4†l+]ÚQÿ±Ee7O»yuÚ~$Ûõ T«–—|T¢Dð™ŽE@D@²ÀäÉœkÊÛP>D§NÇgÃ4øúk`͆ëÛì¡pj4:ð8Oyœ•'º·mÛ6ÐóÓþûï’%Ó{û*W®ŒK¹Ò+ åÜVÜž¦¶oßÞÅѨ*Šrnóóÿî»ï|‡ Cžˆüþ»"í¾û€ãŽ‹¯dÙ²À°añåõç2çÆxí5§Üºu°ß·€íAò…oÛ±#ô•»}ƒ ŽXG4c#ýzp—@QÏm~茧\¹/pÐA×¹;8Õ&" "ÓŠzŽ#|8µ9sîEãÆÑ«W¯œ¾'¼ˆ€ˆ@æH¯ÅJæpñTOÇg ±¯™Uó<0ì¥X±b8à€ÀÅãÓO?;vôTŸãê ׿k˜6+wr™¦X±ÿ3hÚ,¹* ,e;rq…iCÓ» Ì|†ÙVô!S.úŸ‘|51Knµ«—›’Ûó¦‰o†¶BÞ—t8,±2¸ÃôOS #z¦nË«ðÉ}z¨½¾gÊM}nË,«ð^Óñ¦÷˜^hš©²Á:Nf¶['˜ÞmZÌTâY;·y†°:"" "n^›ÛhpT¾|ytèÐ!n³ìûà±Ç:Þƒ,ÒyÜGq7°/ã¹ço¼áœ´ic_§íûôÙgÛÏÑkÚ»7rºRE@D@RKÀKsÛèÑ{m=t•y7Úi^øÂÜð¥ƒjÈB^šãvî4ÿ}fXÛ¤É_X°`<î½÷^ß3À,Ä®!‰€ˆ€d!yø¦.]º7Ýt¦L¡õG¨ìµ×U«Váƒ>ðiïÞ½ñ裢R¥J¡½zö™u¬Ÿé~¦¿šFYX¶+ÉËR+Ê6h£5Ýt¸©Ûb;m1Àô#S7¤JhœÕßt­)w70íjê¦,±ÊN2fJÃŒÓLùÖK…Uë“_ì;§®ý%¯‹Lo3µ‡)•­ö·÷µÀ÷òXÓÚûÎ û²Ç*xÕôNÓ?L«›þŸ)ßןšºet4Óꢡ ™ØfÓwM/0uËH‡ïÝ›Zø \mê¦ÛÃ,×ßÏœÝø?¹Ýt½)ÛŒrîHÒH «ç¶4rTS" " Þ!àŹ¡Ô~øátéÒ%!ϸ\èÞºÕ1¢P²²a@IóçÛÛðÎ;¡5ýíoöµÐ¾ž>lóLèµHg¶ßF"" "F^œÛ^yeZ·> ;Û$"$ xqŽûßÿz}­Sg”Ϩö|þP’ˆ€ˆ€ˆ@†ÐvÞ¨Õ«WÛâëù"uùk ðzÚi§å2B¸6@o=46øg z¼Åê<Ñt•éí¦4ÚH…üd•Ú—Aœc:8 ì«ó%{µÅŸÁF){=Ý”csKh$ÓÉ”ã¹Ût„)ßJôã–¬°Šn6¥A‹_øxÄô‚ ¯C¬Ž#L—šn«^¢Ü–¬ÂÏLŸ7gz”©÷††EíL/6彯”FGüùÆôxS¾Ï #4ø`j»Ê}yü¿üÑôWÓMÝx°³Üê¹Þ´¡)ïó0Ó`9ÓNz›Òh/YYiÃïmyK£§&‹{¯MeldŠ^²~n+zÄꈀˆ@š xunûé§Ÿ°yófŸGÜD´³ïŸ 8Þ†)ž÷%ûýòøãÀ'Ÿ8FGá×Ï´ï€ÿ6côxŒÂËê\D@D µ¼:·ýüódø¯æá¨Sj¨v¬%àÕ9./œÚ}èÛ·/êׯŸµ÷@È>ô!ñíÛ·ã /IJeË=+[¶,?üptëÖ íÛ·Çúõë1qâD 6 7nôå[´hn¹å 2ÄûîiÈ@ã7¼kz¶é ¦nÝíŸkJã™ûLip”*áǦ­MÝ0ΈÖOÑWKÓýL™ÒPƒÆN%L #ÏXákLË™Ž4¥¡eº)Çå†Ðp‰†3kL»›oJ¡!ÕSÞ'ާ¹iaåX«€†3O™TÙ-ûÒ¾´Wö!QáûjœiÓzA…Ù1•²Ã”†gG™Ž1­nšŒÐã½ñžÜfz“©ßyÙÓv̾üÇ”?1¥qM¼²Ä2~lJ²`]¬ç.S¾ŸÝŸ­aQ¿7ÝmÚÖ”ïa8ËÃvÂ{vŠé$Ó¦ÉNË0ÁôsÓ/Lù¿ÞÅ”iÁÒjßI…àDœ˜ÛŠ ®Ú(^žÛNÂܱÄ!™¤Ðn8ͽê*àä“Íæ¼aþúC[Ó™ˆ€ˆ€—xyn›46:ØÔ/­ý…xce3}ÙtSÞ·ø…† 4˜™fšŒ±Ñj+÷—i3S¿Ô·ƒOý'A¯ü— ³Li8”Èø†Xþ{M—™2}Ã4’ÐûŽn0íkgÖIšÆ¦~ieô˜DVuý‰A¯ÿ¶ã½¦Ï™~czœi<Âúüløž:Éô6ÓCLc Ûâ˜9öHïéU–N¦ôÊDýÔÂÿgò¾È´Ÿi$£<ÑÑÛ¦<Ž$›-‘FESLÉ”ºÑ”RÃôlSÖ¯ð}ÐÈÔ_fó#—ïéöQ´±—HÜ&Ss›ÛðTŸˆ€ˆ€' xynãïÂ%J k×®QÙMŸn¶àöùÉ'Í^Ÿû. è5mêb…ªJD@D -¼<·ÑਪÅãlª &-ï5"" ÙFÀ«sÜ¢E¶ÄmkÜ7Å~ûí‡þýûgzGD@D Ë DztœåCööðvìØ—è>H|ðÁ|ÆFþËõêÕÃc=æ?õ½ò‹SÊ„þÇ&YûB+·!¬l;Ô”F7‡]Kæô+tŸ)=µ¼¡Ð0¢0ò{…Ÿ²ëç›>^@¾h—ɘ·tW´ –þ/ÓÃL1eš¨MSÑXåGÓ`c#;MZfYÉ{LY SÑøÆhø¼ØØKˆÔ²³DpИ…#½Mk›^gИåCÓ-¦ô¨³Ä4’¬‹XÒÒÊ™ÞhzG„ëÁI×Ûɦ49Úô/ÓHBC+¾Oi Å÷l¸\f ‘Œüùþc4Ôáý –vòžéûÁ‰ûŽ;Úëù¦¼¶ÆôÓ‚Œ, ^0=Ï”GáïKÞך¦§™ò^W5%ƒ¯Lÿ4%s:E26²dŸ4³¿wî;ö¿|m4$âû²²iwÓÁ¦Ÿš¶7%ã)¦+Lß0¥a<ÂÏ {Mû›²þn¦¬Ÿíœejÿ·=6ö°‰›·M˜0í,>ZÅŠ#Þÿþ×~NØï‰…öí÷ß#fQ¢ˆ€ˆ@ŽðúÜÖ¥K 4Èû^Ýsì}£áŠ€ˆ@&ðòמ¡¼ùæD¬\y»ož+ÃÝÈ 28òØÍe¾W­ZèUŸ>}pâ‰'Î#ÐóÑ¡‡¸4cÆ ,]º4pîêÁåV[Ó¬u‡å?Ù”ÛÂÊ^bçG˜>oJŠde²¼Ð”FL4¡H¸\i GšN ¿Ç9 n6mcJ#‹hÂ6h¼p») "–­aJÖWb,m×Þ3Ýß”† óM‘•–y½) />6­bKÙÅ£LDÈD.ãLï4miÚÊônS¶q©é—¦_˜ò¾$*Û­1%›Î¦õLÿaúƒé ¦4‰W8†×Mi´t¬é,SþÃI¦ LÉt£i°ñ\ÓGL›_ˆr|«¥ßeÊ÷ä1¦™†Ë:K°<>OX4ÖIFº„zÃΛšžnz_Ø5žrœ¯šžbZÑ4^¹È2²Ì0ÓOà ñ½Îÿa~&,2iJƒ¹Þ¦¥L“•%Víí2%Ÿ‡Mÿgú§é·¦dÌÏ“X†Lv9ŸÐ¸h‚é¦o›Î1íjzþóÙÀýµï·‰›·ýòË/:th¾{±i“}ý<Ǿ¾Ù÷·ZµF^»øâ|Ù” " "ƒ¼>·=úè£øÏþ“ƒwFC(,¯Ïq¯¼Â‡A»,œÚ……ªÊ‹€ˆ€ˆ@Ú O{‹j0&ï¸â$GuTÐYôÃnÝè¦#O>ûì³¼7î°Ê™Òðè&Ó½¦ñQ~6dZ6¬ hPRÆ”† ;LÐc …ÆFu|Gùÿ\eI%MÏ3Ýšÿr¾”Õ–Âïz4l©nJƒ*46&åì %øßu–éfÓH²-Bb KëlJã ²ˆ%4¼a;öЧšn1õ Û|Ú”†"½Lw›Ë`;YnÊûϧ€aàSå„çcK;Âô>Óµ¦W˜~eÊú9Ž>¦‰…ЈeÚ™Ò(¦“饦4H[l:Àt¸)ï͇ûÎí%nh9Ÿ4ýÕ”ÆQ¼·w™ò_f?ÓóMÃÇ#+"wÛÙ-¦Mo3ýË4Xΰ“U¦CM ¾PˆcÎðÞ¾núV!ê /ZÚÈœ÷¸JØÅRvþ’)ïQðk…9=Ý Ó(nžé»¦7™ö5¥ÁPa¥©Uð‹é¦kL¿4}ÔôLÓƒìc­X¼l–_ÏÏmqB™D@D@D €×ç¶ý÷ß­ZñË®#{íë íœÝ³°M-IvªýôèìÏ¡W\'àõ¹-×ïÆ/" "</Ïq[¶lÁ;ï¼ã‹rB/µÈ4Éd:×”FN¬sˆé5¦G›Ö5mo.ÿ¶„oL/5ÇH‡†9÷šÖ1ÝaêU]ojÆR;fíÀ¢¯ù¯8¯åí¥DhRÌ3zâ}™aÊ1Kw;á{á[Ó?LŸ3ímšHý–= ŸØ뢱I?Ó{L?2]jºÊôS£T0MV[ÁÿšÒ8ŠFQü·Ûhú“©1óÝw{)´Âúõ\ä“d†í?~6 EcÈ1^žãV¯^®]»šÚKrì®döpÿ÷¿ÿaÍ>P”d:Mæ šßW$" É(ž|Q•t›À‚ ð矪mÛ¶-¸35iÓ¦ Ê•+ÈúÛo¿Ž]?¨n5Òèf€éÓ£L šWo±<4"¡!L4¹Ñ.ø uf†eZfçߘ¾l:Ç4XÛ ûð†)   ’,ó ²sz·9À”†Eךڎ_ŸG楡ËhÓ¿›V4G®¶LǘÒŠu^jJc ¦4bZ¸Äcd^†l?5­t¡Œ“÷j‹nvñÝønÕwA“<¼ÙÊ‘EͰòõìœL{˜ºñ‰Â÷ר¹.;ÒôNÓLÙŽ›r‘Uöœ)ïK'S2K…b•¶0MæÞFèÏý÷ß~’ˆ@¦Ș¹-S€ªŸ÷Üsvì¶¶ \ÒAxõÕW1oÞ¼ 칺œ‹2en³Ÿ—8í4ÛGq„í°×_o‘˜ç—]–‹w-3ÆüÈ#`Æ ™ÑYõ²@4ŽfxC‰dL™Û2¥úJàé§Ÿ¦K²ƒÀÈ‘#l¸‘£Ò(²€×縆 âóÏ?Çå—_ží·"«Æ÷ÜsÏisA–ÜÑuëÖ¿Å%" ÉpÃ< ùÖU2„ÀôéÓCΛ7orë¤T©RhРA wü§t¡²¬5EO34¡MWÓa¦÷™Ú¢6:š†KAï6#ý×”;m—„þ§iz±)Ã+ 9l‡®/\[pz"ÇôøÓÆ”õÓ[Ïg¦4¢zßti2»Ù¯7Mï0eŸ˜.4¥'I¦4žrCØN$¶¼'ÕÝh ¨² ±Tª…@VȨ¹-+ˆk" " ©& sÛˆ@Ë–ösÆ~ÏœrŠ9Üœ<ö˜EÇ­’j:ª_D@D  dÂÜ–‰\Õg¢' 9®èïz " "ÝôXßC÷7Ø»»Uµj°Ëš‚;Z%lõ˜õU®œxL"º¹eÙO>¡…Œ9f±Ðn7ŽÜsË_µ\UÔ¾¿6ŠEË`oñ½ØÑhNXˆ=U÷D.-Õ Š}^ {ËìuÂPíËW±wE”jQ ;ëìÄÖv[±{Öîh5$—~u„b¶#ØTË;fظ4 ï'C”ÌâSIÆؽ{7æÎ‹U«VeüX¼2zHY¶lY ;{öìùÿöîÜŠò<àø \äº@X^ È&‚@Cƒ—¥´V+. ©IZ‰‰F(R«ÆHƒq ´nY¥‰F¬6š6¦I1)mš ( (AACEvYnï{è gΙsïYæ3ßÌžçzf}g¾ß÷ù½gîý˜á©)¾Fí3IÉm:W¼Ü¦%Óܦ9ŽÉ]eË–žðènI¸r}…К5kø¾qSÐ>xóæÍ¹¨‹-ýW[Lµ $%·éÿ7ú“ŸÛô_ÇvèÐAzôháë¯~OFÞž{•·µ×½uï»þ¦M›¬OEü¶lÙ"ï¼ó¹-bkÍe^>{ýõ×ý<ñi2.)¹MïÏ÷ìÙÈmýúõý‡–Ln hê“øy¶›õWxÕüž¹P$še½góúáÕ«WótûhXý(ž­·¢^wÓ§½éëv½û·Î;Kß¾qüën¯ä|F)°sçNÑÿ_óß<e|bÅ'ðî»ïæ¾ò7ÔhÍõ~Ø{Ê¥ïØ±#Ú-Q 8JPux ð.©Ò/>…ƒ‹ô‹TÉBÞIB>õ‘ßš(§L™’ÛªŒ=âˆ#Bö<°jðèÁ2`ëy«ñ-YݸZvwØ-rÛí‘Í-l‰ô\dÑ2H÷?ÿó?òâ‹/f¢¼i/¤†¹å–[rHJ{Yã*ŸþÒkÆ þéô=:0¥gO}Ç"S­IÉmË—/ýbëå6-—æ6ÕZÃõ;¾¡¡An¼ñFiß>ì1õ».Î\€Þ€>òÈ#¢¿pcŠN@ÿ ཊµ¹¹YË}7ptׯHIÉmzϦגŸÛúôéãOìÑò´ÓÇßÿ“ÆzHc™ô{©¾2Ts“ûú;Lû}ÔSdÞ?$ЀšÛ:è Èbg9PRr›Þ³éðòs[ïÞ½päpãÔÿgg̘A:\‡ù—®ƒ¢—.]*ÿò/ÿ’¿šùô²^?¬¹MÿStž­±^wÓ¿Ñèÿ? ,È]Š~‡á÷Ï^­¸÷©ÿ |æÌ™|u¯êŠ®X»ë`˜¯ýëEÛXQ½€þ¹üL¥ù)½ü+Au[øÅ§ð‰Em]jáþ…#·Û:ÞÛ~óÍ7‹þ0!€ P«@RrÛå—_.úÄ €@­IÉmò'"úÄ €@­IÉmcÆŒýÇ"L €D%”÷ÔSOEU$â € (þIx‚ª£ð‹O¥#­9ä@i¼ÍXÉ €1 ÛbÄæT €±Ûbaæ$ €1 ÛbÄæT €± ãbåæd €`ÀQ‚*½ðµ.:uªèê ß…]øÄ£Š‚±3 €Û"@$ €@¢Èm‰ª.@ r[ˆ„@H¤9.‘ÕÂE!€¤H€G ªÌÂ÷µê»{+™víÚؽ[·ne@ˆ[€Ü·8çC° ·Y @ nr[Üâœ@ .r\\Òœ@ « 8JPÍ÷èÑ#p5•8Ú¹sgàøîÝ»–Y@@ nr[Üâœ@ÀZ€Üf-L|@¸Èmq‹s>@¸ÈqqIs@¬ 0à(A5_ëŸ7JÀ£  €u ·ÕS"€˜ ÛLy Ž Pr[Ð9% €@,ä¸X˜9  €@†p” Ê/üâ³~ýúŠ®nݺuþþ r衇úËÌ € Pr[=Ô9' €€¥¹ÍR—Ø €õ ·ÕCs"€Ä!@Ž‹C™s €dY€G ªý^½z®fÑ¢EåÖôujù”Ž;î8i×®]k‡° @sr›91'@ˆY€Ü38§C0 ·™s@: ãêÏi@2#À€£Uõ!C$ÿËÏŠ+dÛ¶me]¡NÚ»w¯¿ïé§ŸîÏ3ƒ €@½Èmõ’ç¼ €Vä6+Yâ"€ÔK€ÜV/y΋ `-@޳&> €@Öp” о}{™0a‚Eûöí“ßüæ7þrk3¿úÕ¯›O=õÔÀ2  €ÔC€ÜVuΉ `)@n³Ô%6 €@=ÈmõPçœ €qãâPæ €Y`ÀQÂjÿœsÎ \ÑÃ?X[øàƒäÉ'Ÿô7õïß_ à/3ƒ €@=ÈmõÔçÜ €ä6 Ub"€ÔS€ÜVO}Î `)@޳Ô%6 €@Öp”°pôÑGËàÁƒý«Z¼x±<ñÄþráÌÖ­[åÊ+¯”íÛ·û›.¸àž@ê-@n«w p~@¨ÈmQ‹@ Þä¶z×çG° ÇYÉ@‘µ Üzë­çµ?²–[,ÐØØ(?ÿùÏý /½ô’vØa2|øpÑÇ?zÓºuëä²Ë.“W_}Õ[%ƒ ’éÓ§K‡5U­@¢ ·E¡H @$ Û’T\  €@ä¶(‰ Dr\k…kBHÀ=íj)Dssóc-ÇOª%dž \ýõòÜsÏ6655ÉÈ‘#¥sçÎòÊ+¯Èš5kÛä‡?ü¡Œ=:°ž@’ @nKB-p  €Q Û¢Ô$ €@ÈmI¨®@ÀB€g¡JL@Œ 41à(¡-`Û¶mrÍ5×Èüùó˺Â.]ºÈ¬Y³dܸqeíÏN €Ä-@n‹[œó!€X Û¬…‰ ·¹-nq· —9..i΃ !¦šÞ»Å+ÕìšJ§Nd„ ¹W¨-]ºTvïÞ]òd'žx¢|ç;ß‘1cƔ܇  €Ô[€ÜVïàü €Q Û¢% €@½Èmõ®Î `%@޳’%. €@†x¥š •¿}ûvyþùçeñâŲ~ýzÑå¾}ûJ¿~ýä´ÓN“áÇ»P ®@_€ÜæS0ƒ r[J*’b €øä6Ÿ‚@” ãRV¡@ ^¼R­^òœ@@@@@@@@šÚ;xÑ\2 € € € € € € € €ÔI€Gu‚ç´ € € € € € € € €¸(À€#kkF@@@@@@@@ N 8ª<§E@@@@@@@@ÀE¹Xk\3 € € € € € € € €u`ÀQà9- € € € € € € € €. 0àÈÅZãš@@@@@@@@¨“@‡ZÎ{ë­·ž×rüÈZbp,iøè£dÆ òÖ[oÉ®]»¤±±QÚ·n\ŸÆ×Øk×®•.]ºÈAßÎ;åøƒtîÜ9ÒkÖ ´Œ@Œ¬Û‰µ9õccáT$@ÀºÏr5·iÕÐ7Pëöbin»XŠ5 POë¾Ê2·©›ee»žu^˹­Û‹¥¹eìZL9¢°î«ÈmÑ×Y=#Z·Ëüc»žu¹@ \Àº¿Ò³Zæ8Ë>Ë2vxm${­u[±ö¶ŽŸìÚã긧ÁñpùÔ]à½÷Þ“gŸ}V~úÓŸÊÒ¥K×Ó±cGéß¿¿uÔQòÇüÇò¹Ï}.°½œ…-[¶ÈìÙ³sçX·n477û‡uïÞ]  'Ÿ|²|ùË_–††Êþ—~饗ä?ø¼ñƹR¸]»vÒ³gO7nœLœ8Q>ùÉOúç«dÆ2v%×QξóçÏ—y󿕳kÑ>”«®ºªh}á ëv¢ç³4·Œ]hÅ2Ô_ÀºÏr5·i͸ÔÆ‘ßÔĺ½Xš[ÆV&HŽ€u_e™ÛTѲ¿²Œu ·µ-êR}¶]ö@ÖÈm¥u\ë ãÈoÖíÅÒÜ2véVĨ—€u¥å²¼³ì³,cG]ßä¶¶E]ªÏ¶KÃYhWKá[><Örü¤Zbp,. ¼ð rË-·È‡~XV1tБîøá‡—µÿücùÎw¾#›7onsÿc=Vî¾ûnéׯ_›û¾ýöÛ2eÊY¸pa›ûžvÚi2cÆ 9äCÚÜWw°Œ]ÖT±Ó·¿ýmùÞ÷¾WÅ‘"£G–ǼÕc­Û‰¥¹eìVÑØˆu°î³\ÌmZ.ö‡ÖùM],Û‹¥¹eluaBd XöUZR«Ü¦±-û+ËØzí¹­´ª‹õYº4lA¶ÈmáB®ö…ÖùͲ½Xš[ÆoA¬Ez XöW^Ù¬îß,û,ËØžKÔŸä¶Ò¢.ÖgéÒ°ibÀ­*ôÉ@Ó§O¯øh}z;hРV}òÉ'eÚ´i¡ûèSˆòŸtäíÔµkWyúé§sOUòÖ~êèð‹.º(÷Z¶Âm¥–õ)MsæÌÉ=ù¨Ô>ºÞ2vkç­uÛäÉ“å¿øEUaÚpdÝN,Í-cW…ÍA `.`Ýg¹˜ÛÝÕþÐ2¿©‹e{±4·Œ­.L ,˾JKj•Û4¶ee[¯Ýj"·…˺ZŸá¥a-´%@n r¹/´Ìo–íÅÒÜ2vx b-Ô[À²¿òÊfuÿfÙgYÆö\,>Ém᪮ÖgxiX‹@N€G4ªX´h‘|á _={öø‡ë@¢OúÓrüñÇ‹>mhÇŽ²jÕ*yî¹çä¿þë¿üýtfÔ¨Q¹§âèÀ¡°é—¿ü¥h2Þ·oŸ¿yìØ±röÙg˧>õ)éÓ§¬\¹R~ûÛßʽ÷Þ+únOo:ãŒ3äïÿþï½ÅÀç®]»äüóÏ—+Vøë;wî,ôG”»öãŽ;N>øàƒÜõÎ;7÷XIoÇ“N:Iyä‘Ü+×¼uùŸ–±óÏc1¯OžRO;ì0éÒ¥K٧Ѻþîw¿º¿u;±4·ŒŠÅJ¨»€uŸåbnÓJq¹?´ÊoêbÙ^,Í-c« $KÀ²¯Ò’Zå6mÙ_YÆÖk·œÈmź.×gqiXƒm Û—êz_h•ß,Û‹¥¹eì¶þc;ÔGÀ²¿òJduÿfÙgYÆö\¬>ÉmŲ.×gqiXƒ€/ÐäÏU3£¯TkùaB s^xaó!CüŸ–׎5¿ûî»%ZFM7:Ôß_7o^èþ- §¹epO`ß믿¾yïÞ½¡û/Y²¤¹e0R`ÿ—_~9tßG}4°ßðáÛ[^«ºoË#ýšµ\ùåüÑ~º¯®´Œ]ò¤lhÔÕÃKÃZhK€Ü.är_h™ß,Û‹¥¹eìðÄZ¨·€e¥e³¼³ì³,c[Ö9¹-\×Õú / kðŽh_Í@#ŽA Ë«W¯–ÿþïÿö zõê%ú¨ÇÞ½{ûë gô©B_üâ«ï¿ÿþÀ²·ðÌ3ÏȆ ¼E?~¼üÝßý´oþ¿kË !¹ä’KüýuæÅ_ ,ëÂG}$?üp`ýwÞ)Ÿüä'ë¼…¦¦&¹ë®»¼Åܧ¾Û6l²Œv¾(שuË—M?ä€üùZf¬Û‰¥¹eìZL9ì¬û,s›j»ÜZå7u±l/–æ–±Õ… ’%`ÙWiI­r›Æ¶ì¯,cëµ[Nä¶b]—본4¬A¶Èméû½¤Ö¹U~³l/–ùÇ2v[ÿ±ê#`Ù_y%²º³ì³,c{.VŸä¶bY—본4¬A (>‚!¸K 'ðì³Ïæ-‰üõ_ÿµôë×/°.lášk®}}™7­[·N6mÚä-æ>[žb$=ô¿®¡¡A¦N*:tð×…Íœ{î¹IË–-+ÚíŸþéŸdãÆþz}õÚŸþéŸúËa3:é„Nð7-^¼XZž|ä/{3–±½sX}þþ÷¿÷Ckýèëꢘ,Û‰^Ÿ¥¹eì(l‰Ñ XöY®æ6Uv¹?´ÊoêbÙ^,Í-c« $KÀ²¯²ÌmªhÙ_Yƶnä¶tÝ‹[·â#Fr[ú~/©íÔ*¿Y¶Ëï–±ÓØ/P&Ò `Ù_©åý›eŸeÛºÝÛŠ…]®ÏâÒ° Ž‚,!Ц@á`ž3Ï<³ÍctÌ2pàÀÀ¾…±ôÉIk×®õ÷ÑAA={öô—KÍèS–n¿ýv¹úê«s?z\áÔòª°ÀªÓO?=°\jáÓŸþt`ÓóÏ?XÖËØE'‹xEþŸþýûK»váô´…ue;Ñk±4·Œ]©#û#€@<–}–«¹Må]î­ò›ºX¶KsËØê„ɰì«,s›*ZöW–±­[¹-]÷âÖí…ø¤Q€Ü&’¶ßKj;µÊo–íÅòû„eì4ö ” 4XöWêcyÿfÙgYƶn7ä¶ba—본4¬A (À€£ K´)ðî»ïúûtëÖ­¬AÞŸøÄ'¼ÙÜgþà"]±páÂÀö‹.º(°ÜÚÂĉeòäɹŸI“&íúòË/ûëtPÍ)§œâ/·6“ÿ„#Ý/ìÆÞ2vk×Ŷ5kÖøaŽ:ê(¾ÖËv¢×fin»VWŽGË>ËÕܦÒ.÷‡VùM],Û‹¥¹eluaBd XöU–¹M-û+ËØÖ-€ÜV<àÈåú´n/ÄG ä¶ôý^RÛ©U~³l/–ùÇ2vûÊ„@,û+õ±¼³ì³,c[·r[±°ËõY\Ö `ÀQЃ%ÚÈÿòÓ»wï6÷ÏßáwÞÉ_”ÂHù_|;ì0;vl`ÿjÞ|óMùÃþà>räHùØÇ>æ/·63bÄéÒ¥‹¿ËªU«üy±Œ8‘ÑBþHëDvËvbin;2\!€@ä–}–‹¹M]ï­ò›ÚXµKsËØj„ɰꫴ¤V¹Mc[öW–±õÚ­'r[ºîÅ­Û ñH£¹M$m¿—Ôvj•߬ڋå÷ ËØiì(i°ê¯<«û7Ë>Ë2¶çbùIn êº^ŸÁÒ°„@±@Cñ*Ö €@k³gÏ–æææÜ.|pk»¶íܹ³è$Æ ó÷Ù·oŸ,Z´È_>òÈ#ýyyã7dþüù²~ýzÙ²e‹èà˜AƒÉСC¥_¿~} ^}õÕÀª!C†–[[èØ±£èµ,_¾<·ÛîÝ»åÃ?”C=4·l»µëŠj[áŸ={öäþ€ åÕŸ+VHcccÎYÝŽ=öØ¢Wã…]‹U;ÑsYš[Æsb$CÀªÏr5·i­¸ÞZå7µ±j/–æ–±Õ„ ’'`ÕWYæ6U´ì¯,cÇÑÈm麣ÍpÒ&@nIÛï%µZå7«öbù}Â2vÚúʃ@š¬ú+5²¼³ì³,cÇÑvÈmþ†ªÞ®×gm†s¸-À€#·ë«¯ƒ@þ ¡JN×]wÉ®]»üCôéFÞ ]é $òvhjjÊ;öÚkò7ó7²dÉoSÑç©§ž*7ß|sÉGùO7Òƒ?ü𢭭Ч-åOÏ»vËØù級ϴ£–åÜsÏÍ 2*<ßüÇäVéëèôUw×]wrÈ!…»ùËVíDO`inÛÇa'`Õg¹šÛ´‚\ï­ò›ÚXµKsËØj„ɰê«,s›*ZöW–±ãhä¶ýí#-÷âq´Î@ÚÈmûkTóYšúB«üfÕ^,¿OXÆN[@yH“€U¥F–÷o–}–eì8Ú¹íÀwõv½>ãh3œÃm^©ævýqõŽüìg?“9sæ®ö†n,ëSƒò'pôä“OÊùçŸßê`#=æ—¿ü¥œ}öÙ2sæÌüþüæÍ›ýy©tÀ‘wïÉOŽ–±½óY}nܸQvìØá‡Ÿ>}zè`#‡–}ºÕܹssÞÿöoÿ–¿©æùrÚ‰žÄÒÜ2vÍ@@D ”Óg¹šÛÚåþ0iùM=Ëi/–æ–±µ|L rú*ËܦЖý•elë@nÛ/œ–{qëöB|8 @n;`6×Úï<Ãöz]Òò[9íÅòû„eì¨ëŽx P_rú+½BËû7Ë>Ë2¶u͑ۊ¹\ŸÖí…øéà Gé¨GJ‘P}\ãƒ>(÷ßà Ï9ç9ãŒ3ë ÎÊ•+s¯,ÑÞÔ«W¯ÜkÔ6mÚ”{g¹>FØ›t~Ö¬YÒ»wo¹à‚ ¼Õ¹ÏÂØ…O, ì²P¸k¿ä,Ü7$\`Uáþù±;,ä²Î¯O1Ò×§üñ¹ÁYZ‹/– 6ø»½÷Þ{òµ¯}Mžzê)9úè£ýõÕÌTÒN4>õY2Ç €@T•ôY…ý•+¹M­ ¯½0_µåY¸ó›ÕÒ^ k1w¹>Û*7Û@ vZúª(s›–IJ¿²Œ]{-´!)÷nz•µ´r[ëõÌVˆN –¾ŠÜ]=´))ù­–öBnk«–ÙŽQ TÒ_éy ï¢Ìq…±é÷×4¹­íGQ¶•(ÿÿ"Õ 0à¨Z9ŽC  eË–É´iÓrUòw:thn}þ:/i­O-ò¦ÓN;M¦NxeÚž={rO>ÒW{­]»ÖÛUî¼óN9ñÄE_ÙæM…_|*}ÂQá«Ã¶nÝê….úÂelÿ$F3ùï‘õNqùå—ËW\!ުܧz?ú裹§Hmß¾=·Ny]{íµòôÓOKçÎû—»Pi;ѸÔg¹ºì‡Q TÚg¹šÛÔͲ¯º^ ã%!¿é5UÚ^,Í-cú³Œn TÚWYæ6•³ì¯,c[×:¹m¿pZîÅ­Û ñȺ¹­üÐÚï<ËRýžIÈo•¶Ëï–±«¯%ŽD¤TÚ_éu[Þ¿YöY–±­ë“Ü&’ߦÞ.×§u{!~:x¥Z:ê‘R$H@¿À|ë[ß’óÎ;¯h°ÑøñãåG?ú‘ÿžñüË.L8Þ¶)S¦È<l¤Ûä¸ãŽË½ví˜cŽñvϽ"L'åOúÄžü©S§Nù‹mÎç?IIwÎ}k»Í «q‡ü/>íÛ·—Ûn»MtWá`#=zÿÕ_ý•üã?þ£tìØÑ?óªU«äÞ{ïõ—Ë©¶h|KsËØåÚ°$O Ú>ËÕܦ5àrXÏü¦vÕ¶KsËØZf&pO Ú¾Ê2·©¢eeÛºÛö §å^ܺ½¬ ÛD¢ügí¨žù­Úöbù}Â2v¢8´'êIDATõÉ9@ÀF ÚþJ¯ÆòþͲϲŒmSK¢’Û‚CU—ëó@Í2‡@i•¶a  ìÝ»WæÎ+gžyfîI8ºìMÝ»w—oûÛ¹)]ºtñV>?úè£À².|êSŸ’/}éKEëóWhìÂF‹-’üx={öÌ?D¶lÙXnka×®]]ºuëæ/[ÆöOb4ó•¯|E^zé%yþùçEßù{ÑEµy&}B•>Õ(zñÅó[¯µhpKsËØ­Â°)PkŸ•Ÿ‹¼ºÛôZ]îë‘ßÔ¬Ööbin[Ë΄îÔÚWYæ6U´ì¯,c[·rÛ~á´Ü‹[·â#5rÛòwž¢ÚÍÕ#¿ÕÚ^,¿OXƶ«E"#€€•@­ý•^—åý›eŸeÛª¾¼¸ä6‘üû6uq¹>½zåÖx¥Zk:lC L}”ã 7Ü Ë—/¡£Vu‹P9ôÐCÛ žªsõÕW|-ËÕܦ5ãrw~S¯(Ú‹¥¹el-?¸!E_e™ÛTѲ¿²ŒmÝÈmû…Ór/nÝ^ˆ@–Èmv¿óŒ£Åߢh/–ß',cÇQŸœ¢ˆ¢¿Ò«±¼³ì³,cGWKá‘Èm"ù÷mªär}†×2k ð„£ KT,0gÎ9ÿüó‹;Vžyæ¹õÖ[Ûl¤' ûâ3dȲ¯g̘1}W®\é/ךÌ6nÜèÇÒ™üdi;pÒ-è@²Áƒ®èµ×^ ,.DÕN4®¥¹eìB–@ ¹QõY®æ6­™,ö‡Õä7µŠª½Xš[ÆV&H¾@T}•enSEËþÊ2vR[¹­tÍ´vŸ_ú(¶ €@’Èm¶y3Iu]x-Õä·¨Ú‹å÷ ËØ…†,#€@r¢ê¯´„–÷o–}–eì¤Ö|Zs›zg±>“Úθ.žpdãJÔ lݺU¦L™"…¯Ó0`€ÜtÓMrÊ)§T¤Pø$}òNØ—¡RA?ñ‰O6½õÖ[þra2[¿~½¿­œ™uëÖù»544PYÆöOšÀpä=QJ/¯ð—µÞ%GÝN4®¥¹elÏ„OH®@Ô}–«¹Mk(«ýa¹ùM¢n/–æ–±Õ‚ ’+u_e™ÛTѲ¿²ŒÜ ¹,Rν›–!êöbin;Éõɵ!€@ô}¹m«*ügÒÛZ¹÷n䶤×$ׇž@Ôý•ƵÌq–ßÇ-c{ÞIüLcnSç¬ÖgÛ×d#À€#W¢f@àÆo 6Ò›Ò«®ºJ.½ôRéÔ©SŃ £¯E«djnnì®–¼)^×-Z´ÈÛÔæ§¾N-€ÒqÇxÍ›eì6/®Ž;lß¾=pöþýû–½…¨Û‰Æµ4·Œí™ð‰ÉˆºÏr5·i eµ?,7¿©QÔíÅÒÜ2¶Z0!€@r¢î«,s›*ZöW–±“ÛDÈmŵÓÖ}~ñ¬A$ ÛÚùÕ‘Õܦ忷¨Û‹¥¹el¿Ñ0ƒ‰ˆº¿Ò‚ZÞ¿YöY–±ÛZ.,¹M½³ZŸInk\[´ 8ŠÖ“hxôÑGåç?ÿ¹_ÚnݺɃ>(:§ÚIcôéÓÇÜóþûïˇ~X4»Tüü'é>:Ø›ôÕlšÐ¼§ð¬X±B¶mÛ&]»võv)ù©ƒ“öîÝëo?ýôÓýy±Œ8QÄ ,ü×ÎuÖYÒ³gϲϒ¬4pàÀ¢c-Ú‰žÄÒÜ2v+@ Q}–«¹M+ÆÕþ0Žü¦>íÅÒÜ2¶z0!€@2,ú*ËܦЖý•elË@nÛ¯›–{q˶Bl² @nKÇï%µ­Æ‘ß,Ú‹å÷ ËØYè(#. XôWêayÿfÙgYƶl'ä6‘Âû6õvµ>-Û ±Ó%Ð>]Å¡4Ø ¬^½Zf̘៨K—.òðÃ×4ØÈ V8`iñâÅÞ¦6?—,YØG˜7µoß^&L˜à-Š>=é7¿ù¿ÜÚ̯~õ«ÀæSO=5°l;p¢ˆV­Z%wÜq‡ÿ3oÞ¼²Ï°aÃyóÍ7ýýûöí+|°¿¬3–íÄÒÜ2vˆH”€eŸåbnÓÊqµ?´ÎojcÕ^,Í-c« $OÀª¯Ò’Zå6mÙ_YÆÖk·šÈmûeÓr/nÕNˆ‹@Èm"iê ­ó›U{±ü>a; }eDÀU«þÊ󰺳ì³,c{.Ÿä¶âï*êìj}Z´b¦S€Gé¬WJe(ðÌ3ÏÈîÝ»ý3Üyç2räH¹–™sÏ=7pø½÷Þ+…¯J ìðÿ ¿ûÝïä·¿ý­¿iذaÒØØè/ëÌ9çœXÖARmM|ð<ùä“þnúÚ°øËÞŒelïQŽ;6ò§?ýi`¹µ…™3gÚ@á/;ôXËv¢ñ-Í-cëµ3!€@ò,û,Ws›Ö’‹ý¡u~SËöbin[]˜@ Y–}•enSEËþÊ2¶U ·‰¤é^ܪ,ÛÒó{Im¯ÖùͲ½X~Ÿ°Œ…~‚2"ࢀe¥–÷o–}–el«vBn ÿ®¢Þ.Ö§U;!núp”¾:¥DÆÿüÏÿìŸá¨£Ž’³Ï>Û_®u椓N}ZŽ7éŽæÌ™ã-†~îܹ3ðÄ%Ý馛n*Ú÷裼fMc?ñÄEûy+¶nÝ*W^yeà©\p·9ði;p¢ôh=zôð#.[¶LæÎë/—šÑ'Cýä'?ñ7ëÀ®«®ºÊ_öf,Û‰žÃÒÜ2¶çÃ'$KÀ²Ïr5·i ¹ØZç7u±l/–æ–±Õ… ’%`ÙWYæ6U´ì¯,c[µr›HšîÅ­Ú qÈ‚¹-=¿—Ôöjß,Û‹å÷ ËØYè'(#. XöWêayÿfÙgYƶj'ä¶ðï*êíb}Zµâ¦O ]-EjyòÊc-ÇOª%Ç"à’€JÉ…ª£uÇWuÎ<óL9òÈ#Çÿû¿ÿ»\~ùåu'N”›o¾YôõmùÓºuëdòäÉòúë¯û«uÔ}÷Ýç/çÏ<ûì³òo|Ã_¥ñ›:uª\|ñÅÒÐÐà¯×¸:ˆféÒ¥þºAƒåžhбcG]þŒeìüóD9?{öì¢ÁZ—\r‰\ýõÒ©S§¢S=ôÐC9[}%7©ç—¿üeo1÷G;ÑYš[Æ`±€uˆ£Ïr5·i叨Zå7õˆ£½Xš[ÆV&H†@}•enSEËþÊ2¶U ·=#iº·j'ÄE Íä¶ôý^RÛ«U~‹£½X~Ÿ°Œæ~‚²!à¢@ý•ºXÞ¿YöY–±­Ú ¹-üo¨êíb}Zµâ¦J ‰G©ªO c- #­¯»îºÈNóÀÈi§Vïî»ï–ÂWžuíÚ57vèС²k×.yíµ×dåÊ•W{uëÖMæÍ›'}úô)Šé­ÐÁ4Ï=÷œ·˜ûljjʽ®sçÎòÊ+¯Èš5kÛu0ÒøC=zt`}á‚eìÂsEµUiÖ¬Ym6Òc-c‡][ë¾ùÍoÊûï¿/¿þõ¯ýp»wïÎ èÒA]¥¦K/½T®¹æšÐ'!ÅÕNôÚ,Í-c—re=Ä/WŸåjnÓq±?´ÈojW{±4·Œ­FL P¸ú*ËܦЖý•el«@n+-ëb}–. [@ L€ÜÖú?‚T3WûB‹üW{±4·Œöÿë@ >qõWZ:Ëû7Ë>Ë2¶U­“ÛJ˺XŸ¥KÃö ´Ê(|òOùGV¾çøñãs×5jT«ëkѾúկʣ>*m 6Ò@ú¤$}5˜£ó­M'žx¢<öØce¿6Î2vk×YË6}:‘>âQŸ(¥O4jkRãïÿûrà 7„6Òããl'–æ–±Ûrf;Ä'gŸåbnÓšp±?´ÈojW{±4·Œ­FL P¸ú*-©UnÓØ–ý•el½v‹‰ÜVZÕÅú,]¶ €@˜¹-L%¸ÎÕ¾Ð"¿ÅÕ^,Í-c[K PO¸ú+¯ŒV÷o–}–elÏ%êOr[iQë³tiØ‚À~^©FK@ÀwÞyG–,Y’ûY±bEî•iúj5ý2dˆ466VUŠíÛ·ËóÏ?/‹/–õë׋.÷íÛWúõë—{ÕÛðáÃ«Š«YÆ®ú¢Ê8PŸ"õÆoÈêÕ«sTíÞ½» 4(÷3pà@ùøÇ?.íÚÕÔu–qÕíbin»ºÒr¸.àbnSsWûCò[øÿ1®ÖgxiX‹õ°ÊmZ.ËþÊ2¶eÛÂu]­ÏðÒ°ê-@n‹¿\Ío–ùÇ2vü5Ì@ )V9βϲŒmY/ä¶p]Wë3¼4¬Í°@SM5onn~¬oR†): € € € € € € € €Yhâ•jYªnÊŠ € € € € € € € €@ 8ªÃ@@@@@@@@È’޲TÛ”@@@@@@@@pT# ‡#€ € € € € € € € %e©¶)+ € € € € € € € €5 0à¨F@G@@@@@@@@ K 8ÊRmSV@@@@@@@@j`ÀQ€Ž € € € € € € € €@–p”¥Ú¦¬ € € € € € € € €Ô(À€£9@@@@@@@@, 0à(KµMY@@@@@@@@¨Q€G5r8 € € € € € € € €Y`ÀQ–j›²"€ € € € € € € € P£Žjäp@@@@@@@@²$À€£,Õ6eE@@@@@@@@ FÕÈá € € € € € € € €dI€GYªmÊŠ € € € € € € € €@ 8ªÃ@@@@@@@@È’޲TÛ”@@@@@@@@pT# ‡#€ € € € € € € € %e©¶)+ € € € € € € € €5 0à¨F@G@@@@@@@@ K 8ÊRmSV@@@@@@@@jh¨ñxG¨“Àºuëäâ‹/öÏ>jÔ(¹çž{üef@pQ€üæb­qÍ €­ ÛZÓa €€‹ä6kkFhK€üÖ–Û(`ÀQ± k@'öîÝ+ï¾û®­›6mòç™A@ÀUò›«5Çu#€” ·•’a= €€«ä6WkŽëFhM€üÖšÛà•já.¬E@@@@@@@@… ° @@@@@@@@ÂpîÂZ@@@@@@@@`ÀQ «@@@@@@@@@ \€Gá.¬E@@@@@@@@… ° @@@@@@@@ÂÂW³Êxï½÷äµ×^“Õ«WËÞ½{¥_¿~2pà@9ꨣJ†Ø·oŸ,Z´(wŒßµkWéÙ³§Œ=:÷YòÀ oصk—¼üò˲nÝ:yÿý÷åC‘=zÈñÇ/ÿøÇ3,CÑ@ò›kaTò[¡Ë €€¹ÍÎ6?2¹-_ƒy@ÀV€ÜfëëE'·y|"€ñßâq&¿ÅãÌYH»ŽÒ^Ô¯&íÛ·Ë 'œàÇhll”ÿüÏÿÌ-¿ýöÛòàƒÊ3Ï<#{öìñ÷ñfN>ùd¹öÚkeذaÞªÜ~<òˆ<ñIJqãF½7Ó¾}{7nœÜrË-¹KÞú´:92g¤åÖÁE÷Þ{¯¼ð ²mÛ¶P ¨uÓM7É1Ǻ•AÇ\¦OŸXyÊ)§äœ;uêXϤS °ß%¿ÙÔs¡3ùÍÆÙ‹J~ó$øD ›…}.¹Í¦:“Ûlœ½¨ä6O‚O²)PØç’ÛlÚA¡3¹ÍÆÙ‹Jnó$øD »…ý.ùͦ-:“ßlœ½¨ä7O‚Ï, ðJµ,Ö:e®H`÷îÝâýx‹æÏŸ/çœsŽ<õÔS¡ƒôºÏÅ_,«V­ÊoÆ rá…Ê}÷Ý:ØHwÒ'éqög–{RîÀŒüÇ3ÖOÏù_ÿõ_eüøñ9çRƒ”ç•W^‘‹.ºHž}öÙŒhU_ÌÇ{Ln¿ýv¿M«·ŽÓA] 6ªÞ•#pQ ¬ß%¿E_“aÎä·èÉoÑ›Âú\r[ô5æLn‹Þ™Ü½)pQ ¬Ï%·E_“aÎä¶èÉmÑ›WÂú]ò[ôµæL~‹Þ™ü½)Ý`À‘[õÅÕ&@`Á‚2yòä’OÛÉ¿Ä;vÈ×¾ö5ÑÇ?^vÙe²dÉ’üÍ%ç·nÝ*×_½ègV'}¢ÑÕW_-›7o.‹@¿8M›6ÍàUÖAÛéûßÿ¾ÜqÇRîsŸ“û￟ÁFȦù-žz'¿EïL~‹Þ”ˆ¤E€ÜOM’Û¢w&·EoJDÒ"@n‹§&ÉmÑ;“Û¢7%"i ¿ÅS›ä·èÉoÑ›Ñ=^©æ^qÅuعs§|å+_É=F/ãøã— &Ȉ#¤]»v¹EsæÌ zY¹r¥œuÖYÁCŸùÌgD† ’{ªÑ믿.?øÁäwÞñK§óóæÍ“/|á þº¬Ì¼õÖ[rÝu×ål´ÌMMMòùÏ^,}ûö}ZÔÂ… s¯³[»v­Ï¢ï›ý‡ø¹ûî»ýuÌì˜={¶Ì˜1#À¡Oºë®»¤¡T€a ßâ©tò[ôÎä·èM‰ˆ@ZÈmñÔ$¹-zgr[ô¦DD -ä¶xj’ܽ3¹-zS""&ò[<µI~‹Þ™ü½)ÝhWËe777?Örü¤Zbp,IÐwœê ¢Â©cÇŽ¹1—\r‰´o|PØÿþïÿŠ®_¾|yáarøá‡çž0óÙÏ~¶h›–9ï¼óD(yÓ 'œ ú(¾´O¥œµÜ_úÒ—äßø†tèСˆAeé«Ô6nÜèoóÞ÷«u”öéí·ß–3Î8Ã/æØ±cs×üÿ?óÐCÉ=÷ÜX­¯œ>}z¨k`G@ •¥ú]ò[´Õ]ÊYÏB~+mM~+mÃ(-PªÏ%·•6«fK)gEn+-Jn+mÃ(-PªÏ%·•6«fK)gEn+-Jn+mÃh] T¿K~kÝ­Ò­¥œ5ù­´&ù­´ [(!ÐÄc-JȰÖ®¸âŠ\BÛ§[·nré¥—Ê 7ÜP´yêÔ©6ØHw<è ƒdÊ”)¹W¯yêS|Zöåžžä­«öóé§ŸöŸÌTmŒRÇ=ZXjsÕëÿò/ÿRn¼ñÆ’ÇqĹ4“&÷¨¯¡{õÕWeÔ¨Q%+wƒ‹f…e{àä¾ûî ¬þó?ÿóÜÀ·ÂÁrX@L ß‚ÕN~ z”³deVxnò[¡Ë PJ€Ü”±ê§¹w :W³Dn«FcȦ¹-Xïä¶ G9KVf…ç&·аŒ­ ß‚:V}5÷nAçj–ÈoÕ¨qLšp”æÚ¥l&½zõÊ (j-xØ`ýr O•im:th`óÞ½{åƒ>ÄTëô­o}+ðZ·Zãåûí·G>àè°Ã“¯~õ«ù§ 3fŒhä?åè½÷Þ Ý·Ò•®™–oæÌ™2kÖ¬Àê /¼Pn»í¶H±³€Πߊ«üVlÒÖ ³Âs’ß EXFRä¶b‹~š{·bçJ×Û*c²+@n+®{r[±I[k,Ì ÏIn+aZ ¿ëXôÕÜ»;Wº†üV©ûgA ø.¨,”˜2"P£€Žþ=øàƒ[6@èôÓOoõÝØ»wï¢W´mÚ´©ÍãÒ¸Ãe—]&‡zhYE+¨¥ƒ´²>éS }þóŸg°QÖåG ò[+8n"¿Õ†I~«Í£Èš¹-ž'·ÕæLn«Í£Èš¹-ž'·ÕæLn«Í£È¢ù-žZ'¿ÕæL~«Í£Ó+ÀŽÒ[·”ÌH ÿþmFîÚµkÑ>GydѺ°íÚµ ¬Þ±cG`9+ 'tRÙEíÞ½{`ßÍ›7–³¶p÷ÝwËÃ?(ö¿øE¹é¦›ëX@òÈoùvóä·êmÉoÕÛq$Y ·ÅSóä¶êÉmÕÛq$Y ·ÅSóä¶êÉmÕÛq$Y ¿ÅSûä·êÉoÕÛqdúp”þ:¦„ qÄeEÔCÍÍÍþ¾ýúõóçë1óÍo~SöìÙcrêc=6ò¸å:ë‰;uê8TåtÍLf̘!³gÏxè°aÊֱÈ(·ß%¿å«U>_®³F&¿ð%¿°`Ê(·Ï%·•o¶g¹Îz,¹í€ ¹í€s P¾@¹}.¹­|Ó°=ËuÖcÉmÉm,˜CÊÊíwÉo•¹î]®³G~; G~;`Áa 8 Sa­ôéÓ§•­¥7~øá¥7ưeüøñ1œ%ºStéÒ%º`UFrÍìå—_– „–öÎ;ï½þ±},t;+@ò[ûÙϚĮgP×ÌFUT'Ÿ|²œuÖYò³Ÿý̧üñ,&LO<Ñ_Ç  ઀k}uœ]3#¿%¡Õp  §€kýtœ6¥Îåš¹­TM²Ò*àZ?„zp͌ܖ„VÃ5 €@Ü®õÕqû„Ï53ò[X-² Ž‚,!Z×_]¶nÝjR¾M›6™Ä­wд˜M:U^zé%Ù¶m›O:mÚ4yî¹çDŸ‚Ä„¸,–¾:Î:H‹ù-ÎVù@ N´ôÓ˜U.@n«ÜŒ#@À r[åõ”3r[åuÏ àŽ@Zúê8ÅÓbF~‹³Õp®¤ ðJµ¤×ׇÔ(лwoùú׿ˆ²fÍ™9sf`  €¸$@~s©¶¸V@rÈmå(± €€Kä6—j‹kE(W€üV®ûeA€GY¨eʈ™ø‹¿ø >|xÀá{ßûž,]º4°Ž@\ ¿¹T[\+ €@9ä¶r”Ø@À%r›KµÅµ"€”+@~+WŠýÒ.À+ÕÒ^ÔÿX°`™E‡Ìb×3pšÌ´Žn»í6™8q¢477çX÷íÛ'úØÇŸüä'ÒÐ@:¨g[ãÜ P½@šúêê*;2Mfä·Êêž½@À 4õÓq‰§ÉŒÜW«á< §@šúé¸ÜÒdFn‹«Õpˆ[ M}u\vi2#¿ÅÕj8OÒø sÒkˆëC "N:E);aÒf6bÄÑ×?þ¸_‰Ë–-“Ù³gËW\á¯cpI m}uöi3#¿ÅÑj8Ä)¶~:»´™‘Ûâh5œâH[?‡]ÚÌÈmq´Îq ¤­¯ŽÃ/mfä·8Z çHº¯TKz q} €@„×^{­ôìÙ3qÖ¬Yòæ›oÖ±€ €€Kä7—j‹kE(G€ÜVŽû €¸$@ns©¶¸V@rÈoåJ±_Zp”Öš¥\ €@ˆ@cccî5jù›>úè#™6mšÿªµümÌ#€ à‚ùÍ…Zâ@* ·U¢Å¾ €.Û\¨%®@ Rò[¥bìŸ6¥­F) ІÀøñãeܸq½.\(sçÎ ¬c@—Èo.Õ׊ P޹­%öApI€ÜæRmq­ €å ßÊ•b¿4 ´«¥PÍÍ͵?©–‹ € € € € € € € €Î4ñ„#gêŠ E@@@@@@@@ þ 8ªp € € € € € € € €8#À€#gªŠ E@@@@@@@@ þ 8ªp € € € € € € € €8#À€#gªŠ E@@@@@@@@ þ 8ªp € € € € € € € €8#À€#gªŠ E@@@@@@@@ þ 8ªp € € € € € € € €8#À€#gªŠ E@@@@@@@@ þ 8ªp € € € € € € € €8#À€#gªŠ E@@@@@@@@ þ 8ªp € € € € € € € €8#À€#gªŠ E@@@@@@@@ þ 8ªp € € € € € € € €8#À€#gªŠ E@@@@@@@@ þÿO}6¡$•¶IEND®B`‚blis-0.9.0/docs/graphs/large/l3_perf_a64fx_nt1.pdf000066400000000000000000000527011422157504600216110ustar00rootroot00000000000000%PDF-1.4 %¡³Å× 2 0 obj <>stream xœÍ}]¯lËQä_Ùæáì©ï‡y$@ƒŒ†ÁWšÄ†;x0„†_?U•YYÝûž{|º¶[–OíÕ]½z­]™Q™ÿüæKzOÑ¿õPßüøÏ»Oo_ºooÿòwoÿëíŸÞüÛoÿüæÞkê5—77þûeŒòñÆ¿ýí:àS o>„4ßü÷oÿsü÷¥·Ëky -¿—ß¾øV7>×ïÒßþì-¼ýù8ߌq™ÿ©oÿþM3ÿóxÓ:-~Nó·ëÃÜÛ?¾ýj}Åß{®ïLå‹O¾žç6ÞÞǤß7eHå½ÅxsJž¥ýÖîíÂ9~eÂ?þ7<ã8f_“‡Þ{ o¥Õ·~ûö_þtL[Þç³ñÃß¿ýõ/¼sî¾ôÚß]+¿sô7?üùÛŸüp¾‡RïMè“Ï1]šðéâ}y}ºÇoüú”OßùqÊŸÈ]z÷¥½U—ßã?=è¿pôÃoÞ¾øüVý{úá×o¿Èýqbþ1Ÿåk|Oa|HJLJô÷8ß;>äÏþô—ÿã/%oÿñC,ÖçüÖjx1|pš¿ûñï~ûÛ9Áàø1wßõ;ÞÆõóö÷TÍ­J﮿}W;Nü´w?F%¾—8F~œÒöqû–ùÿ_¼‹s™üÇq…ßÓ»ç¯OHïyoïãŒÆ¸½—u¼¼×ùþæÿq{Oóx¿dsDz[Ç8ù17A^'æc—eŽû:µy<Ì7ç¸ÎÍÇø>—1®rrcìçxþî®q·b޳œ\¬r²ã:¬“Ká=µ17rܸëój•“Kõ½Ïóiãù›Ãq-æÇ·"§—šîNNoþ:Ïéz’ÓËnÜÝ9nrzyœÖü®Þ9¿œæçŠœ`ïeÞ ïœa.ï^þäó|ÖÖšœcÆwô!®“ïHy«œeSÍ‹².5Þ±.ùº¼ë}>;ó'Ú勸åDÇš!2®HƤ}M:¾Ó:ÑñظõUr–÷ ­?t9ÑñhÆõ‡’äõ~}Diršã‹¹5ãÀ‚çg®k‘Ó,I%?æˆÏlë‹´„ÓÌï­¬?4œf’Â÷€ÓÌ8«^pšs5\ϳÃiFy&~… n"å¯þìí¯½{+o3¿QÕoÆ¿ø.ŽGÒåöÁñå«`ÁµŽÇ-§ Á±4—¼8¾Ùº`ëòãQ[¯þúz²7üÆïäBÔ‚ß|m3ðóë6üæc üÆoAn~óV?7žÀ´á7J¢Aßøì7úÆ©­ç”àï^Oº€_Ø/z@&òÆÏ¾+y¿iÞ8“ îÆñè-ìÆ© R»ñÁP7>>ù ºñ±‚(bÎ Tƒ¹yºÞ@®ÏgÄ ®ã—E7~F×¥'àÆ Ýà­w¹o„Ûø€Ø,Úæïp&Úz“»®`s?<Û«knhc­wÌ@¨+™-Ô:O˜H·¯H›Ÿ™-Ò~­i’‰´ö6¢ðñ?Ûw€lžCŸù²q¯ªWE'ÈÆC™Í:7žIA•€l®Óf•KN~‰²ùü§±‚UÃõØOˆ $¬çúºìØ–´ñ5‚×^ˆqr{ÄfÀ f\Æ(l´à}–ñ½MˆTœ<|@ Þ à}Ä ÞH˜àD ÞJð½À/¶@d´Áµ'@xøà[:ÆÇf6ø^@?Dß;Á7|#`Á£@ßPð(0á¸ì´ã”€¾€à¯2ð€÷’+þµ¬*n…pÿ>nÀ7Æq1W°måóØ6~ˆáÈÊwgÒs²“oûþ¹ÒÈ”~‚+ß9ež?åC ï{§äY>Ñc¯žãW&üY*"ÍPbü®o¿ÕµK|ÛÓcôE–Ë÷ý»g{~Äß_|Æ?¢Ü^›ñ#Îíûg|º~_^Ÿî#Îíµ)?äÜì”?ÿ Õj|Í›”Ûo“?êã´f´;’…yôw¿û¿W(±8ÂF¬3B˜t;ã¯_b”ÈsÄ\iåç²Ò„/~itH™içLWú8°(ÁwXYýÊ8±–$¯^L\ÜÙ=Ö}~Y ûŠw@ØÌÄ%Küç|qF"+J ¬Òò<§‹ãc£A¥aŒÄa%bcñ_qiYYðbÉV¸QÝÌ(¾Ìh ¯ðgr¨ÂŠ­ jÆŸMh¯ˆ€HX7Ì?yŠ9ßa« ¹y@`/ü‰G¾ ·ØÃ³äEùÊÀ]”g°‹’~t ä0ࢤ5€fآ䛀¸H-(ùû È¢¤Õ€Î‹Ê}µ¦£.œ ¡…'°@ÇV$t*)|$…oL8ñC&~. ¤Ã„«,Ÿ ñ¬"Î ñs Nøðstt(Àáç6ü\€&žá€‰LÍ+.¹·`Áð&±E”ä¹_âQ~‚×Ï«°‚“‘¡u³ZÍM ¾‘2Rý’7TÚ¦¶æl`J–µ o´4ý°1M~3€—I®Ä ˜q´•˜Iµø ™™kÌÔ& hÆÑEÛ5óƒò†M-rs€Nà”syš”PÝЙ̘ÁθkG àG›.McƒÏxȪÅÏÌo£PAãήJc,óCÕ#¥ˆÆS«äÖºøa~Û £qÜÛi—•@ã\ ’ª¾Pšü¢ÅÒ8ßT ˜Æƒ"óMsá)NcÍîx*…ɺªð¹¢Æü²HÍï› ¦æõêT¼žDUõòL¼Äoéj“GqZF`äñõEã;å "/«4#>!ã!'K:„‹ q„HOöS¹šE}2Ê“GœAžî¼¬8#xBý3¼ 2¸“už¡œ;yüÖÉç1¨›Û!8tòmÎ)¼ÂyŸ„r’Èá2ŒÃ6%ƒ8¼‘!ÜÞ_‘ ,AÃ7D/ Þ°7ÂÐ ïeà†÷2lãÆ ‚6î«^go ‚K¤á#k̪ὠÔð¹ Óð¹ Ò03C4ì1@ÃQ†gø\gò¹šÉ{ïð\e†H± B‹AÒøƒ “"σÒ$› •Ö~Š –> —ËÑ0%r4 ™Æ=-6«˜È6I_•÷ÝN‰¤C§Yh—mð”XäÆð);î­#€bmž†P™%9 ¢ÆÃåŽ0Šo¹Îp)GBTÒ#Q¾M†«†+jMŠ00Íäí É‘ ©)ÀîØC† è%pÉ‚¼$ÛÅ^’„°K’ÞtùH×1ಀ[–/°eaY5ŽhYêܳŒ_"*e±1 `à7¯ŒÄb‚+£DÐÊÌ*X™e^«|æœÊ,Â@e{NøE ˜È¸J8y‰ñƒ"„xâ9>ù À“i@'Ÿ9GFQ`“ñ«ÐèÑŽ .H`øbÀ/&X²ä:7.³Nõöc°ç + Öm,üÅ–E²v ¤ÉÓ”tpÚØ‡IòÀmÔH17ñÈM˜"O5—¨&ðTƧÙ-˜äÙXB~ h x˜—9,x ¥Z „«°ä„ûÁmEwp[ëiá$Ëyá‚reÃX´„n¨Ëpób gÜ›cÏ%‘;v(v‚'Å]¸µ~Ÿ2 Q>IW'ÁObm4®k°qæçBÜ1äÁ½D?@~.FIXOÅjHÜ‘„E¡Ô±÷,M瑩 h*þ„S BaO[ˆ/q[Š qgÛ;)Õ®3ÁÄyãb¦  (Â"ÑÝ@ó¯_s(Êðåt'%;)éØIY¿%º“²ŽéNJ2ë oÝI6‹;)ÉÀ& Òš(A#¯Ô” dä˜î¤¬‡@wRäËNJ¶!\d¹0wRäáÓ”tî¤d–8ÊÎ6pã{u'åà€yTwR¤2\wR$ÄÑ9ª;)ò^ÝIÉ6P‹g˜¦¡wR$TÔ”|î¤ ¾WwRdfÝIÉçNJ±¤oDùºî¤ ‹×¸­>®Ñ§s[ü+|Ôœì·5²Í4Ãù‹D”w6W¹-žå5n‹çø ·Õf}þXÑÿ€5\OÑKtÔÈpóÅ鞟ñWx™5ÛUvkÎx—Ýz¾€¯qQ2ß]~kÍù:ÁÕFœÆ¢v›àòO׿þË•B®"ÞV£ž€‰:š˜9d6ÉHêµ³jµ´ œ‡;ãØûföà¢$jLB`æEHL F~‘íþ^HG ±H¥ºã I­“#ÉPö¤e\YH®?¬™$;+Irùl&1ù jwü"¶[IrE0ƒ$¹F²Ê'HrkÌVù|ðöþ¤[é•Ò\3G&Jš,ŽlX“æJ¬ýÒB.pŒJs%V2‘æ¯È,x—¤®#&Í•¹­Nš+³‹4WfMš+LJ]Á\ÎØi–œ»w>ëÇŠ­Dñã¶v‡H!WA½ i®Ù¹i£¨9W<ö Û´´+œiÆêÃl&šš¯R-äòºíB®hs÷‹4—âp<8þ‰æòÂørkÝÒ\¹Ó”ÞL!×jøÑB.Ë1)ÎØ…\ͦÒYÅôÃ釯6ýGúLíd”{¨éG8 ¹Â‘~DCs!ÝÑôƒŒGCsᘦñH?’©“ÄðÂM4 H:d…œj' wÌk’Î$Y¢‹CM@’…Ó¢€ø3±›ë|±& ù!±ðáp' éH@$Ù H9ü€X¢Kó‘js¾€ä€Ü!ºˆ“6kŸ,áïcÙ8I€6¶c„ÍQ¢+™ÍïŽ<}<Å.U(âJòx3]ë¡ç:U…lã2Õ…ã*ÕAƒéòB£ébú¦+I&H¦+Ë÷!ÓUä6‘éBC)Ë»üz6»ójÝC|A'ÊI9 k ƒÏUìî¶<ºô4pE„OGU/¹.ÇM3p]¿ÉäºÈ]‘ëŠhþ"ו@ÄD‰„&P4e,ŒÆ(Op”Øz ;Õ²ARÆB­\—ÃêF®‹Ü¹.´Œ+וd´qb¶ª+áë8.$’ÁW¹sJWùÙ~‰ê2kMù`SS.©.[ ‰[ÝRñf­9Ëöñk¥TW1e\q­©Å®52âZ³‚B]kj·kÝÅŒÚ嬄Ãxq²â\Z ‡!G‡ˆ};Ê8ÄÄ-AÑqˆ¬à€ÃøŽò”BÉ!¢Ú‚R3ÐþÎJ4+6žd¹<¹ãuC ÈÆH­Z …¾„¤@B#1€„*" E5HYh/)KP eyö£,R$H !—l‘¤7ÀP‘4*€Œ ¨ ODT„Mšø)B>E7˽ŒúOA#UÉ ‚‡ È)¨‡p HÜè°álš'j €†GÀLÙ=¼rFÝ"†íJ ªaˆ—*i ÐRÑRK PÙÀJÕ®CóoA Q  èPpRy*q ”˜Qÿ?”ÿ ˆ`¨â?2¼ÉS)6æ*õ´È µi¼ðiccÜÕ`Àáµ;*}8s(F¢Öø˜ÛD~d¼(„åÓeünuýÔÇ’ö7]6£‡‘±Mî+€3JÏ*?©¶?û‹Çßò$*Â÷ªíõ¿äö>íVžÏú×7ÅöóÜ&v‡R‹“°½V ýZÇN'ðÌœ¼ÓM~QÛG ÁÜÉ£;„jß!H°AµýÞŨí AçeãŽgOa4jÄK×ËÈÏ‚1ÎèÇ Ïú®ÜvT8÷íÒ¡¶3UÛGœoÔö#ö.gýX¬ªxDµýdȇտWv”8Ç9ì8qÆ[’{«Ú~¾«¶&ªí윫Ú>IUÛçf7Õö©IOåï©wªíã*nµýŒ°SÕö È/Š?B¬óR Fµ}-.£Ú~FñŸêg6ÔHócá¢jûÐŒSµý¹ mãÉõo"Ê%ªVLL¹$Ó¬^ñ|K·¬ÞÒô·­³°®à9Ÿâ׈½…ÁÔ'o™1˜ð]Á]tòKVm¿ªZÒÊ-³lYSm?jû ÛÝ€_Cayr‹(Gí°×Øl!pÐe@Þø.Ù0åô…ÀAOPÜÚÔ5p‡ø0G™%\…\× ×ƒîkèܦ$S0h›ª°UÍkSq>¨ÕŽ|†Bà°Q!pÉ`H`º€e«ˆ²†¢¯èæ¤83" ;ôQœ ˆBà,lXFg+MãÝô\óVXÉãF@@«i™'ŒB)2%0ä‡kÙR r1J`@¸éº°~š'\âÓšå"Á“þ´ž*;Õ U쓡ʧä½ÁS <ÕŒšÎ@{#<ÕL™L‘ñ*OUjĺ5)¬ß…#ž¶ôXÂÕ5xj(Ë&ž@aO]S ësëÂú®måÂ(]=…qWÝÙÉÑq¯žtBÑýo ÅïR…ŠIƒ•bŸ¯è­PX,¡ÞšÑ»“)–zwF8¨w'Ú,7G‡²ÍÑ!Ü]95«Ö6­•YFœ6öÛPŽ®>rtœC9ºÊ ’o ×ÃxwÎïrÈè^ãèˆÃ2Óÿ'öá| hOSÅi#¼ˆâ•á Ržl(rÄ*ÃSŒ`;G”á±°‹GÒDQÊð”C†gUž¨ Ïz¥Êð45JôP†§™¤‰#•á±ÒUQòíh6&¸ÐϨínkOPñŬâ*<Ý&MœŠjU§wg:½;›Ð!U…£TªbÑ„ª0¤NÕ)É®G<< èð(€Ã£€ 4zT Ã!“NïÎtº &éºýgƒP•z8R£èC_Ôè<Eàà˜.6þÐ|“c\lܱظc±ñÇbã bxŒ‹/Ä DUñMm£èv,6ÞÚè°mU%ßêï©ä[8í ‚]lâi£Ã™Uò-œö¨Ø¦än:%ߨp~´ÝªäÛA`óœUò-œê¢Á2t„²J¾…S]ôˆÍâ™á½÷ì >¡ã‡\!Õæd×::\¤ÓèpuJ9Ë{ Oò%†ŽØBº§‡é5•¶©oºç'ýUK‚»Ýœñ.G·àx•£{¾%,.³tkÎË4ÝšóužŽV Ÿ]NWžxº»Ö “§sùÉ‘*¢ŸG«¬(¼6=§ƒ´Žòt§0üüµ¾ž…äéLH™Ãnª*èŸåÎ0³§žÜœE" èXNW AµjöäƒÍž‚¡êÂA?y4{J†|5¨ÙS2õ (•¡±"$¡6¶#ˆÍ£íZóBRj^T*ÍË+)4/©9uæÁY Ìp Ã1@ "ú|W8 ê}N<²Ób+ôhG~Z,ÿ­CæOÒ‡ @ñ(àÄ£Jz´áB£¥5àJWËwó( ¤„-¤-w?¹\íjkQyÐáQ‡S6z´ã’u< À0]\pôÜÖÖÒsJæ€O# ú²É38:IÈ}„j?imò:ðÚ’ª ëÚQúÂáÐòQø=õþ br8|„¨P@ãÞªÍãPk†à¦7 `3ÿj(î‚5À)ý@NiªèµÊé`e ìÔ|±öèÑŽMÏTh; ê€_¨=0³Ϻ‘6Ê×± ŽUÝQ£ó5é:öüFݳ‚[pÔ~¶¤ñ%œ5ôí,à”F2å-–:ú˜ ¦^éØXÔ( ®€Óø¼jùˆ9¶kQO§ßÉÚµ v)r¨ZݑǮ‘£'9—"—¨t€¥ÈeyÅ £†<Ÿ¬çZˆ“´³Þ\á(NýúQ,Iò|둵Çî‘îÙ¢Tì%)iÇÞWá’lEjTÙc ¤Xš´+¦¬¯TÒ®˜f‰¨2«yϲ=IM›©)Yv⃱ɣ)P±uÜtRÚ®œ´ÝAps¸MNÚî`·yt»’ž´]:i»b™mÝ®¤ÉEª+éIÛ%[vªĤí’ÝXÕ£¤íÒIÛ.Z‘¢ŸàJº¤Û?]O?Åpm/ÊÍßƃ ÂM;Ø ÜœgyO'ù’0;Mïª_ÃEênêø_œîùaÙ\á®>Þšò®Bž`òªFÞóm¹`×pY%oÍyY&oÍùºNm%>»Ìnn¸·úî¦ÍDž¥Oíà –Œ–d0¢ZÂBv°Ò¢Ž]£˜XøC¸$€G¡8Új©dŒ>GJg ý—–1v•¡^’pA¾$aûú% Ý¡0ÁȪ€‚IvÆ-±í  “ =ˆ˜dÈàCÅ$ÃqtªO:ËÈl÷R0—ŒŠùäð¨f5óGY­”‰¨|üã–ü‰è"¥ä7é¡f2» g²•¾¨f¢=7üñôQ…àS, þ$P{üQ“:þTŒ)øÓØŸÁŸÁ,¨štÏXÉoûóæÉ ¬[»‰N{(›tÚ @Ú¤·SH¿wŽ¡LçØ_Keºñ4ºB™Îáû«2Ý´óý"NA5žÚ‡?€ŠŽmpºeõ½$«© Y%&¨šÍUV?PTðPV¿IÃו;<\bPÜ üÈÇ-ÕitrQ$"oT ¥LY}/¥´”Õ/(ý¬>(Êê7´Ú£/Yý Å*”ÕÐWYý•›SVn–*«e0•Õ§ª!­(܃3kÊêoG»u0Xþ¨XY}zC[PêR¶¬¾;,):xÊê;æJžˆOÍ€jÂãPÑ¢\%dõ£Õ¯ô¿ ¬>kx(«OR‚*ZõAE T‘Q¥ƒj–`Ju©¢…æ$UÑBÉí'XTÌñüŒ¥"'$ê°Zý Á^HHÔ1s…êBISiŸ’èÚ‡®À”PÓ 0¥ÌÞ×õ@D³Be~4rÁZF'—ªú O¢ÑØ*Qí¾¡”çÌ U ŽJY:˜APæ›UMJߊ¥›Ü„Y¡Æ2‘ôþìü4ÚûE¼[”NŠÒ‘£Èc>=*Ÿw€©s…›`êpË ˜Æ á-˜´& `‹B±º(L›QSo¬F0uÚBPCu<§¢¨@ Uç•ôïX£¨¸Ê5 ­ÖºFQ9ú©“N³šüó¢+ó8iw觺v =Î?ôc•b{ ¯Š¹5tÖÕÁªb›‰Ñö‰VÅhÓ±v’_2µªpFÖ1ªÎ ìÊFOdûÄþ'­*‚QHÅH­*ÂaUì"$S«Š`ÄiáM« o0ƒWŠU…?¬*BÚ€a€G«Š`:¶-«UŠêн&Ûª"X¨ p[Uõ@â!µªp6Óa¶g´­*ä¨ZU ÀŽVΊ ò¨ZU8»ØðhÙ5ŽÛª"na8ªVÁ ó¨ZUàh;NI­*üá&G·UÅ!Eò²UEÇ?Ûªb~Æ­Niótg.š@'÷}Fˆ‹Sò,¯}Ūâk3~³UE˜ÉàÒªâéÒ¾dUqo¶§§üE#ˆ:Ëá¯Y§Î }¸hœútñ^÷lxúƦ|üÎßmæ~Ë×é­ovM]1Ÿ5÷vÒ“â´ûnÛ‡6–4}Ü>ô}øÛ›¾Í·ç'ǯ‚и1–u&š{¯Væ×»Nb„ŠÈZÕ÷ (ð}ÙL¶¾ãx7ùý<.¢!Ó÷aR&)Y;~Ö¦uzî•\ùw?5jí°f¥S+šMÔªÕ#qïCG߇ˆÊ*ú>Ä-/ñ}˜•yFxVÖ9pÍqè;äš•uÙÈcr‡]óÅJÑÏ?ˆž}’g^‚ò°äØ@߇vE“qµtÚüC±ÙÊŒ°"Ksþ#ø>¤*¾)®zZ¨¾“BI6gI”’gÎ’è &UŒ—èûhlF߇D/3ú>$²ŠÌ[[e™·$RÌ[ ᘷ¤|ʯWt›·¤ò(ÙsÓ÷¡ùÙðú„AÈ©e¥¡*$}†€’å éBËÉâèø —‚†‚JõEÎé¾È1mıôTðÖWä¦ >r"ìþN{z Ó ùM]zÉ´±vªÒkSÓ3¦Çƒ”¤‡@½ jaÀUGk'P‹bŠ\¥f¨oa¹Ò~MfpB6it¢/}Zº¶z” 3åg—72~š¸"ágþFˆ&!m<]É2Õ?íx”‰>j}ÈEÓ|2ñ:ÙŸ/RtXìu"Jú}O×:ºÜ“Ûq…ðÑ(ip$¦-J<”è ¤ˆûI—‰‰h¶&@ÛÂIReE'‡šE º. •¦•mQ¦µ•ÔÑÒOWVX/Xo˜qtq@ šG ÔI3=@ç  ñèçjUK˜v*nè»@àÀ½E‘ã@r:‘mô ;]> žñN1rf\¶È™¡€WQtO±¬•¢x0ÔÕ÷µóô°ÞHl°0j什£¦]wEmn¬;r÷çÂÓY D,y6L”Ý#šP5§pJ^CßkãÐÆù´º8ŠŽˆ˜X1;7î Êœû©‰ƒˆÂÑÄq¢Â_Y¸;öl%âö?iâÀÖm¿GjâЇjVÒÍ4q°« Þ§&Íl:lÃÄ¡&-l¤àmjâЇf]]1Í6q€-M—.¾WMÚaâЬñ1Îh›84»é©Cš84»;£qõ8)5qÀ&v{‘©C’0̳’ò…žE*PÒ2’쨠dŒM>P|§’1ݤïYø’@‹ÒK°*„ò’ôQxé°1LäXC ‰tˆz(ÝG“|$‰qµ$Ù0€†RÀ, Å AJK‡oG:’t$ÉÐÈ ¨PSÉ'ÔT XS¾QMŽäC‡‚§„r!58tÊ(&5¨6ùH§NY¢0M„?PSC§Œ/VSʹÖÓ•N2¾XMÀÓTà`ºÒÉt¥“éBµï6X<Í'˜ Œ…zœÎóÖŒHщmäèíp, §C¤ ž‰êJQ —ðz쨯ÔUôúp­$ñ‚Çy› 4ã|3“¯Ï÷Ôòð4@…–10°É@Ñ6&kÏ4öää¢ ]ó>f vFÈ.Õ²<™ ¥@9BÂ'³åø), €¦mu£.,Æ„ ™#`¨„Óö³°(¢–$aT" Góx1@* ,ARÉ'i<ÆÉbiºÈØL¾”sãhw\ UÏ€§BÓjŒƒµýœU‰6ŸŸL™MèKcÍ¡€j νÜû¨0šµ¯O!Ÿ·œû›‡>ã;Êb†ÃTÀ:HA$ó'd1ãa*Ͷ nþ–Å4p«Ø²˜a#Íò*‹™ nð¾-‹ib:D *‹™>^©²˜Ù,6Ab•ÅÜEüTóÐô ,t¤(¦¼QE1¥?BE1ói*-%vÑ£\c™y‹bZ>˜S©(f¶J~|¯Šb«+Ë©Tó`‚Y;©¢˜Åjøq¨¢˜‡áß«¢˜pa§(¦¬µ*ŠYNQÌbË_7øt¦‹r…œš“]cº(ב–¢^ÿÕ)å,ï1]<É—˜.š üa »ž¦×¤Ä&oqoºç'ýUÁþ»\ךñ*×õ|/Hë_f»dΗé.Êõߦ»FœxÒ]wÕùÛ¬”òõ1öIÑÚ÷UwÐ]Mi áWœ?¶Ë'¡åme‰GmƒÊówY³”ðê² “ð+¹oQžìŒÊó7‘-Qyþ,Ê;$¼ª´¸ ±·wÁ7S‹»‚ä&ZÜå-îÊÈ0XÜ›PnÂæSk»<|üXÛåOÍÙ h6ÐwiÔùg0rP^³Dê(BI”0VÊ«R ŒêüˆB·:?Uñµº«cß^Õù©Š¯êü᡺kêì%=MH’Uç§ )¯L|R^ä¡R^™ßž”×þ)/:k*åUÐû¡”Wš‘R^õ¡P%·Ópþ!û‡ó-ÞÄUóî0Ò)Ý[]£¼ÅYµæŸTÇÙ€ô¡:?ö^±!ÜŽ ÷f2y<’š†X½qÖ¯0 ñ{A(LMCD~iŒ$:&ƒG¢£iH8Ò`ЄiÔ4$#M¤òš†ØÔVš†1$Vš†D¿áÐD«‰H´ÐâQMD¢e½T‡‰H´õ]<ª‰Hd{ ’=ënÆ£šˆD›­ó¨&"ÑV¥ðÅšˆD[ߥG™ˆÄSÿHÓ‰yMD¢…e"-ëÅ£šˆDËãè'¨ó·µAñl(ƒÎrJŠGÂ^¨/^Ⱦd³CS‹ UQœïÆË¢¡v pi¨ ^ØhÀôtÈów4C2Ô*äJåPÅÀ•Ê=¬TÙï•ÊÅskÆAå‘+•C—Wª±7ÃÏñáø<ÆÎTzÍ+o°9>Ÿ=U(±TyÖøq©ò¨oÓ¥j ZyþÁ[Ç‹yàô|öÔCàRåqt©òì•çRåá( K•¯`=¹Ty„êRå À°Tyx4èRÅ}1]ª¼6Š'UZÈG!²oè}çR5¾\8 ‘=Í<¹TùF÷M,U÷@—*ßNjl^¹fÊUÔA—ªŠô†zËãšÆð7/1É1k…æ“äX0«Rïöž1ÑìÄà‡JW¥|cÙÛUÉn‚ZÙ䘉Ãá§ŽY¶gÌAŽÕƒ³e`èÖU©žž1f¯¯ÔUɆ}èÖU騛ä®JÕ‚ñź*iÏ#LMíÞf8÷bøâícq@:ëªÔU©)‚ß)Õ‰aÇHÃt¶‡DKZø% $Üa‡"‰Ö|-E’Fˆr)áΖK©V±«ÓDˆr)‰»‡K)”†\ 4ÚU.¥YˆÞ¹¹­.Ç>>ju9-juk$Ùˆj ³hK5†Ù„«ÃERª1 u·­1Œg+á÷ÇLâ®þÌ.Æ|„–·z* ¤Tx8!|hÒWèªUáa¦¢J^„C,…‡õTÐh¬ÂÃl1™UÜxŠ’M¨ð°UëŠZRiêÏTxx=W*<\ ’"óõýO 7£Ô¥øN…‡i§÷h w«ÕÅ£*<,• w«¦!/ÂÃÝj©ð cHáán¡O¥®´RÇ­;Ü-lpPe‡®Q/)ºr0 é=à‚ƒÀ )œ8!g ”ðÅÀ!8J|$»'z‡å"0æƒÚž½ ƒF¾È"ÕBG†lT¹3…ì»›‘š??øÈH„¥¹Gìò†­¨Ó…‡:]èC¤Nêt¡â8éHÞ©ÓUPx,HéŽÐéBË}CM5 "ùó)ºÐtd¤n¤Ã5u#]¡¤]P}vo»ç/c³*w“;C/0Ø êvªn¤×¢¡(£`µîæ Í?4Öx­³ôéT¹_FÖÝ iñKÝ€i©AX8Mž+Z/–Å„J÷ó*æ=?3±E8nþq%ò u%Ò“àJä;Åí±9ú¡9^­ÞÜçôV¿Ë«OW¢ñ‡f÷^Q»_ÕÅãcžWƒ-Þ.®:áXuâV8‚¹G¹ûE÷骳¶"tÕ‰ÔeÅr¤«]ý^œtÕÉO;™\u’AV+]u¤±‘«ŽtÑsÕ)]WÒíªSMð†cºê”cÕ©?‘È\uʹêÔsÕ©çªS5<¤«N>Wm¡f]uPIL¹ûj¼ø^•»¯V[U‡”»œö!•»¯VS•¯T¹ûjc´ˆxUåî«E‡*w_ll†£[î¾Þ³¡'9n†ÿt½ûõ!W˜§1YýÎ\”’?ÏîŽâýÍ9yžÇ¿"yÿµ¿Yò>ý>r÷3Ažße5VIFÿ íýÛ·ÿúöOã»·ëuüçÛð’<þÅéžQñ¢žýLVñÎÅ Ãê(¸6aŸfw×¾òóýxéZó=^ÃS>\Å×§|ºŽ¿7Gÿ2C‘Ïñ¨tO¢þ“•YT`8>ô÷õqÊ{|$êÿ7EýÇðüô‚Å‚õ¹ÑBÑŠ¾NUCÿyc=Õô‡³bÆÞU£ =±aãdr¤bŽ’þŽû¡’6x<ê&=%ý=j(é?w¾ó!u÷˜’þ Å)é?ÆÑP³T¼’ é +LIÿ­€òšrŽs1©Ùän4ì õ¼ñQšÕ|ñHÍB;e”W½Ÿ¥çŠ 0ÍšÍ'N~ë$£ci’³Pv[*ÌYo¥ùw$g‘rÎLδ®59§¡&¯'*ºCLÎEÁ™œEgœ–ögjrÖAï09›¯°ºÊó’Ù29‹ `59‹PÇÐäŒü³&gó$Žä,¢M“3vŠ}ޤ¿_¿O¢Ë‰R4b—Éz‘ôgƒäë øšVƉ’~4Ô;Eü)é¿’ ®oóYLÄA=xÃ1  Ƕ¤¿Q)”ô/Æ8jü*é/£J ý¤øâ àT‚ߨêr—TÒ?Ñå~RíÌÇUÒ_¸j•ô‡P¹Jú[¢ƒÄ9dɉ¬Ê‹cqÔOÁjQ9vœ”Jú'Knô“Úà‹É¯£[%ý³Š‘ë¿)韭y?•ÈÑý¾%ý³]懪¤ÿ©BŽ«¤>%ýËv(»C.xôµ|{,øá €b{?¼?‚Ý¡ØX\ž©¥ç­œ[dMP)¿éqàhúbW¤HA )²‡PŠ Ä"°© 0MÑV«ŽÙ`KyD‡ù€§¨Î·(Q‘Z¨€Ô¼^V\a&|çþÑ÷¬µ&=}`l¸Ö4ò‘f9-bß‚–-„¯~°š%òRý0.p;8èpÄ¥ÆmÜ8mÐèûLt¥qv¡qÇB㎅ÆJ•¬.3΀Åiu_Ûs`™qÇ*ãl§ªcy9Wg@â6×÷5!DÜÞp5×–a§ð"ðp\rü‰6X¿ h8ö 2øVÁwp € ž ‚ö‚>N‚Ï×…ìô ôÌ Í(ð7 ¼)\þùž~ÊÎmÎvÀ£ÀM²7çäyÞ#ðx–/xt*øYÏÿçðwÏOÞK„ÛÔ¼¿8ݸxÕ…à.'3Þäïx¯òwÏ÷ä5flÍw—¿“)¯òwsÊ×ù;º/|.7Výg旅_}7G£Æ’§Cï&Ü‚K¸1 á\‡$®òwVØäï’Ž ¦ëHVÔ±‹“j?•»´è+‚X ;áWÁÁuN½Ü)øãã)øã!«¯^ ¨ RòQˆ’wÐ{Uò.†ˆ¡È·Qò®%‹ìëo†¼óRý¢ä Í„¼‹Tª#y— B­ä]¦;É;&6JÞ1SQò®¡à†dÃxrËIÞuhz(yG5c`:¢ä]{ }Ԍњ1åP3†@ Šf ª´EßQ*ä©ïh|p´hy—¨Ó­¾£‰¯ ï(› IFèy¨ï(zÓ”Hпû,3ï…x@!déÆàÌ<$ªU¨šŒ*U82*4O‘’8°QæÊÞo2*´Y‘ŽGŒl„< $#ä•ä"䕤"„/ !))‰y\ÈC õ? ­' ht‘„ÀÄ/ôy Áƒ€`ÅøA?àÅdp”ä‡~‚/Rx¼È<°äćà8íÀ’;°hÇ"é€!9Ùå…! I8p¾CÀF‡™]oÅ@†n.äp”TÃ)á'¸1¬2¢Ö*‹Tä¸#­Ž¡Ú) 2qÂÚ!%ÂÓjYEV Êeõƒ}ˆáX§"J³ˆ– _˜1 à›f '`Æ{ºALªÚ² 3oÍ‚j4cH1ŸÃEÐnf àÜnÒ9K€N±†Ø…6œÏxÄ¢]–ÆÉ[Jžj;ʪ<¨¦S,µ_ „*{ji;ª¶¢¢Šr~¢¨9¬Š´UÃ^ÁQ{Òj0!’E¥–9,µk“Á@M%ô€ScÕ8ðÔ•Í@M7w»5šYR]»àSå7ÌüŒ2ÂÓNY,ª Fƒ¢CÚѳ斮˜‡íè¡CŒênîYUGŒt§¨ÙZŒ¸SÔÛÑfÌ Áª;EGh'#åïšYk¼Ü%ðÖH ¼Öß ƒgýKà±¢;Eݨ zcÓë© A¯;°’ÃëG‡÷êN‘ÊBT3•îõÓvTŽêNÑiÏ!wŠºÅß«;EÝòÛ:¤ÚÜi÷êN‘¼XwЧ¾WwŠºuþáPwŠ0¤Úœ³†÷Ì>ŸÐÓO¹ÂÁÍÙ®z4:¸I¾Ñêàîœrž÷=žåK„ þ¿­È{~ô^“’›úbçû¯š-Ü¥ôdÆ›”Þ‚ïUJò[&Þ%õ0çUVoÍù:­G—‰O®Ë+ËtÂÒzw]'üÒ&{’ðNˆãAë(}Öã–2h½D}Ðzñ°®› ßÛeÕ™ho|Å`='ÆïœÕ½WÍiS•'H¬ÊkÚæ'Uy^uŽX•g]'©ÕŒþ$ælÕê¢Ë&œùœ71àL& d=†º¬"%P—Õ|(âO®YÓ‰¹oTñ—iª·1á¤Ô%oåÇŒÏê‘EÍ8.Ø"ôY˜è0Ö‡º¼¾í³ÊÔÇø¬z[ 1ù±nw{=ÉàMí¡ÂqS{…fv¤ö*EŽHíѼU©½Š‡O©=šž(µGàMí±P©½Æ¢ R{L©=Z[(µ×$¼ÞÔ^·î‘©=Eb\$ÄS±DÍ&ݲô:-(4Ý2”…—*•nÂ9¯¦[í(ÌkGa^³œ:FšnYØaÄt«ï;Ž˜nuc´Š„`§[FÞ#M·ºåÏO+cŒ4ݲe¯H /Ž(ï-)†Ê{»ÓýCÊ{;k©CÊ{£ òÞÎ2媼÷QT¤CÊ{‹¬—Ê{»SÞþº”÷ÆP®SÞÛîwît¿s§ûÝ‘péòÞΖ²êP®SÞÛÝî°%NœX9<à$B{¦*1ºndfQL'’j@€dj¦Ž¼9p*0ÀÆM'  ¼Ð`ZCI9L' šø±éĸrÅÖ;'$$`3^Ý-Má@«åD–ÙÔrÊ”j9‰:ºW¡’ ×l"ÈaΈ!T¨á„£o$ '(‡ †¤®Ôp‚ÎGj8áéNÉ€Ý#5œ€1¦.SSå(xõþ´0^á‚­GZVÇ”‡tè6œÈ¬u¥á%‚Õp¢œ›oñÕ.S³AòX¦ÆõÊÖÞem@ZêožG¶•{ËNþX¦fhsN@wqN°ÐË”oåãÜ Ã‰Å£‡';VŒÕÌ'xÔŠ?,IXL¬?ìX¿ÎÖ£~¯ÙXð‘´q 8?.Iák  íÊÀˆKR3úРúº$…cIú:,ˆxôÛ8ÀtV‹÷£ó≴L¹•<6mŸ8À#ª{ˆéH ~¨Ãoã£åqtW‹÷ËŽŸ¯Ô·?Æw/JæßS냛ÃUe=ø9\çyO­gù’Z]'~^­¯ÿç¨õ}ðð½ÆNç‚›ó}Ž— %îŠöaÊ›²}‚á«Â}ܘ —¥û0çUí¾5çëâ}ôÒøä?·¬5N.𦷆ŸqC~R_™aê–× ÂÞQ¼è”÷JU£Î9Ë(D…^Ô9‡9uÎQ°@ó* ÆTamÆ–_D’T…:绲nŘkŒd‘M‚I’*ë0s®jľVHfÔ™yiY¦´¸W­ó™ŒÀÄz¤þ¨÷çAýzÔcCñÔSî‚zAÞ±õ|–¨ß!¨7UûPBñfùTN¯‚’S9=Ï‹rz-ª*§GeeÊéi±!åôbf äôb¦…äôf#š[¤‘ÓkÈ©h‘Ho9½Ng2ÈéͲA+6iÑtÈé?ªÎ»lrzã‡LØú†‡œ™ÔÏrÝX)–‹O˜CêŽP¼× µÁÑx¸phY)7Ü>  _` [Ä2v5Ž:hªb‚¶Â}/n˜q”i„—7Æ(RiGç7¾0jâ&gäô0²8J8‘f¬kXÁLö¼–4Þ@õ47P˜§«~›z­nÀŒ¡of-r ³ôÝà6}7ˆõÝh§åÓ\úÇšÅPXôÌͺ>-‚/ëZ´é>jê¡&~ûnÚÕÐwƒëˆúnPÆÏønÈ ©¾DœúnT:ŸÓwƒk‹ún4èZl(zÖôɲNâN}7­œé»Á0ˆkQ•»}7´í½©–¯? |Au°únDÖ0a-šœÏË:{vݱž‰ºîlhm‹ó`V!è(£€*ÊðöLd¡Œ«?¢< E×ÇNèºî¸n×w¬;>ØuÇ[ÉdYÖtÝñǺã+¥“¹îhTÇrݱ(‚ 1tønÐ¥D×`#9uÝ‘ýY]w0äºÓ¸3 „uÝ ÖwC‡\w‚ÛtÈu'Xß æã”ˆ|.,ÞI};óJ]wWuÝ9œÑtÈu'Xß rýºîë»áÎÑ~"7ë«^yÍÄéIø”œýñ/ÿû¯D œ”Ý73¶²d¬5}VÛxÎ=f’?y†3µçôt†úo¿ù‡ýÝ¿½ýêW¿ šî}¼Î~g0:Ï|þà´C|óñÔ¿~ÝÜ ˆœþû«¿øË_â¼?Œ ¿çdó\ßú÷žlOç§ú'ÿðãßý“9Õ ¡Ì:ÛñTdkzœíÿG8L® endstream endobj 5 0 obj <> endobj 9 0 obj <> endobj 11 0 obj <>stream xœeAkÂ@…ÿÊÜTJݘ¨ Ĥ©¥XCÚƒä°Ý º »’lJûﻉ´—†a˜÷¾7ÃÁ¸ïÁx¸„%x³8ƒ[Àz;S§ÂÒ8]yÌã,tå³9ïX8bl4Á¼1u'©ÇW!OÙ>‡7jZe4xSÊî‹—8/¶ûryš¥FvÒö±ד’­—N0iHX§ÿðà7(ŠÜ5.LdèHøtGÚÜZ‚%}Ù 3£­ÓeÜ=Âà¢hð•ßWÂÜéZ|Vu{€`ØV˜˜N[àƒh#Zêý¸¥ó'Y%>hij¥ø®t¬[õ7݇í™=˜ßð½uàdŠÎ.£Š¢wìgN endstream endobj 12 0 obj <>/Length 72/Root 9 0 R /Info 1 0 R /ID[<13346F2BC6B5F0F632CE0017102157BC>]>>stream xœcbÿÿ™˜€7##Ó ÍÆÀ¦ßi`bd`¼ ¡×00BÅ4P}І¿ ùu) ,`þ;†? y¦¼,Õ endstream endobj startxref 21605 %%EOF blis-0.9.0/docs/graphs/large/l3_perf_a64fx_nt1.png000066400000000000000000015366601422157504600216400ustar00rootroot00000000000000‰PNG  IHDR y”ÞAvsRGB®ÎéxeXIfMM*>F(‡iNll    yÌfÒÄ pHYsœœ&Í:4@IDATxìÝ ¼ÌåþÀñï±/Ù÷=)K!Y %É­\‰üIZ”kÝ(D›ŠJniE®Òv %]¥Å•BBH%Ke‹È.Ù›ÿó}Î_3sfæÌ9gæÌüf>Ïë5æ·>¿ç÷þóÌÌï;ß'MrP<Ï4³{¯TÁ® € € € € € € € € àªyÜÓVZŠ € € € € € € € €ñ à(ÞW€ã#€ € € € € € € € à"Ž\t±h* € € € € € € € €ñ à(ÞW€ã#€ € € € € € € € à"Ž\t±h* € € € € € € € €ñ à(ÞW€ã#€ € € € € € € € à"Ž\t±h* € € € € € € € €ñ à(ÞW€ã#€ € € € € € € € à"Ž\t±h* € € € € € € € €ñ à(ÞW€ã#€ € € € € € € € à"Ž\t±h* € € € € € € € €ñ à(ÞW€ã#€ € € € € € € € à"Ž\t±h* € € € € € € € €ñ à(ÞW€ã#€ € € € € € € € à"Ž\t±h* € € € € € € € €ñ à(ÞW€ã#€ € € € € € € € à"Ž\t±h* € € € € € € € €ñ à(ÞW€ã#€ € € € € € € € à"Ž\t±h* € € € € € € € €ñ à(ÞW€ã#€ € € € € € € € à"Ž\t±h* € € € € € € € €ñ à(ÞW€ã#€ € € € € € € € à"Ž\t±h* € € € € € € € €ñ à(ÞW€ã#€ € € € € € € € à"Ž\t±h* € € € € € € € €ñ à(ÞW€ã#€ € € € € € € € à"Ž\t±h* € € € € € € € €ñ à(ÞW€ã#€ € € € € € € € à"Ž\t±h* € € € € € € € €ñ à(ÞW€ã#€ € € € € € € € à"Ž\t±h* € € € € € € € €ñ à(ÞW€ã#€ € € € € € € € à"Ž\t±h* € € € € € € € €ñ à(ÞW€ã#€ € € € € € € € à"Ž\t±h* € € € € € € € €ñ à(ÞW€ã#€ € € € € € € € à"Ž\t±h* € € € € € € € €ñ à(ÞW€ã#€ € € € € € € € à"Ž\t±h* € € € € € € € €ñ à(ÞW€ã#€ € € € € € € € à"Ž\t±h* € € € € € € € €ñ à(ÞW€ã#€ € € € € € € € à"Ž\t±h* € € € € € € € €ñ à(ÞW€ã#€ € € € € € € € à"Ž\t±h* € € € € € € € €ñ à(ÞW€ã#€ € € € € € € € à"Ž\t±h* € € € € € € € €ñ à(ÞW€ã#€ € € € € € € € à"Ž\t±h* € € € € € € € €ñ à(ÞW€ã#€ € € € € € € € à"Ž\t±h* € € € € € € € €ñ à(ÞW€ã#€ € € € € € € € à"Ž\t±h* € € € € € € € €ñ à(ÞW€ã#€ € € € € € € € à"Ž\t±h* € € € € € € € €ñ à(ÞW€ã#€ € € € € € € € à"Ž\t±h* € € € € € € € €ñ à(ÞW€ã#€ € € € € € € € à"Ž\t±h* € € € € € € € €ñ à(ÞW€ã#€ € € € € € € € à"Ž\t±h* € € € € € € € €ñ à(ÞW€ã#€ € € € € € € € à"Ž\t±h* € € € € € € € €ñ à(ÞW€ã#€ € € € € € € € à"Ž\t±h* € € € € € € € €ñ à(ÞW€ã#€ € € € € € € € à"Ž\t±h* € € € € € € € €ñ à(ÞW€ã#€ € € € € € € € à"Ž\t±h* € € € € € € € €ñ à(ÞW€ã#€ € € € € € € € à"Ž\t±h* € € € € € € € €ñ à(ÞW€ã#€ € € € € € € € à"Ž\t±h* € € € € € € € €ñ à(ÞW€ã#€ € € € € € € € à"Ž\t±h* € € € € € € € €ñ à(ÞW€ã#€ € € € € € € € à"Ž\t±h* € € € € € € € €ñ à(ÞW€ã#€ € € € € € € € à"Ž\t±h* € € € € € € € €ñ à(ÞW€ã#€ € € € € € € € à"Ž\t±h* € € € € € € € €ñ à(ÞW€ã#€ € € € € € € € à"Ž\t±h* € € € € € € € €ñ à(ÞW€ã#€ € € € € € € € à"Ž\t±h* € € € €€¿À믿.UªTq[·nõ߀9@@@@¨ ä‹zTˆ € € € €@. :tH¶mÛæíäÉ“Î4 € € € €± ÃQl\©@@@@@²!0räH©Q£†óøå—_²Q » € àú>÷\+ZŠ áè/ ¦@@@@@@ Î{÷î•Í›7;­ {CÁ €@’ Ð÷%é…å´Hr2%ùæô@@@@@@@@ˆ¦GÑÔ¤.@@@@@@@@’\€€£$¿Àœ € € € € € € € €ÑÈÍʨ b/ ã•ëøå6lÇËYg%5kÖ”Ò•‰ÒŽHÛËv €@" Ä¢¯‹E±6K¤¾$‘ÚkwêGU }Y,ꌥŸÇã‘õë×ËÖ­[¥aÆR¶lÙXŽº@r H}LNúDú,”HmÉÁKƒ]@¤H¤~O³Ò÷åFÛéÃ’òeÏI!sóÇjšyP@ V®\ééСƒÇÄxÌÿ^¿‡ ò4iÒÄ3lØ0ÏÑ£G³Ôšï¾ûÎsçwzZ¶lé)T¨S¯ :ò :Ôc¾Èµõ™`$Ï­·Þê<–.]šéqÌ›ÏK/½äiÓ¦'oÞ¼NÝÞö×­[×óÈ#x~ýõ×LëÒ þûßÿÚóÔsÕÇgŸ}f÷;tèçÉ'Ÿôh›½u{ŸÏ?ÿ|Ïüùóýê×v=ûì³`ä·}Á‚=çwžgðàÁžýû÷ûíã;“(íðmÓ €@2Ä¢¯ËIo¾ù¦_¿3hР,1wëÖÍoÿ5kÖ8û'R_’Hmq€˜@prÒ—9•Lä´ÎXõ‘ß~û­_ß¹dÉÛò'Nx{ì1ùa‰ónòäÉÎYMœ8ÑY®Ÿ7nÜè¬ 6¡Ÿ!¯¾új¿cõéÓÇsìØ±`›³ @ 9éc&L˜àüm.W®œßßö 8ë~øa¿e·ÿH¤ÏB‰Ô?\f@ ä¤ßÓŠs»ïó=™œ¶Ý[}˜W‚gRR Šù&ûÅp”’¯N:74ÐçÆoô˜ F~²ÍÿÜ óM›6õüüóÏ5ñõ×_÷-Z4h=Þú5gÖ¬Y“MÉo»7Þx#ì1¾ùæ› =Þ:ŸK–,i“ÂVhV¾óÎ;~mÐvýôÓOžzõêù-¬_çõ\µhpS«V­2Ý^•~ÿýw»Oà?‰ÒŽÀv1¸U }]4ê4=&žÓgh€o¨¾!ÐÞdÛsöÓ~Èd#ôüùçŸÎf‰Ô—$R[ &@<ÑèË£Ug¬úH 0òý<÷ñÇ{L¶Ü Ÿá²p¤}¹þ(Æ÷87öìÞ½;‹y@,D£¹ûî»ýþ>ûþ­öîÛ·¯_˲Û$Òg¡Dj‹.3 €A¢ÑïiŹÝ÷é1£Õv­K }Xºÿ"¢Ur>“y§OAØ >\¦L™"æ&¥sMߨQ#©]»v†!À–-[&çœsŽ|ùå—ÎöšÑdñ‘ž={Šùegàj¿y“1Iºví*3gÎô[nfñâÅrá…ʪU«2ll¨¶}ûö‰ù5© 80Ãöáh Æ‹.ºHLƈp›Ùuæ‹Y±b…\qÅòùçŸgºýÂ… ¥S§N¢çŸYI”vdÖNÖ#€‰*‹¾.uV«VMZ·ní°ýñÇ2gÎg>ÜÄôéÓýV÷êÕKtøÎP%‘ú’DjK(/–#€© ¾,Ð)ZuæVi2IçÎ#ú x®ÁæM°‘tìØQL\gõ¹çž+Ÿ~ú©”.]ÚYÆ €@Ö¢ÕÇdýÈ÷Ènÿ‘HŸ…©-…Y‚ Hýž^¬ô}±n;}ÿ?@ b¥E†£ Uã´sGàƒ>ðˬЬY3 æñ;¸¦Ù„Úµkç÷ Ý6TÑáÄÌtç‘?~OïÞ½=æKV›z~ݺuž×^{ͦ˜÷n8$Z¨ G&xȘòX3͘1óeËÛ$Mo¯)øÍÍW§ Þã<ýôÓ¡š!JZ3Mx÷3ÁSž?üгsçN¶êÔ©Íœä]¯ÏùòåsæÍ—Éž'žx³hÑ"›õÈjyî¸ãŽ CÖi;K`´v¼ÚØ.æ@7 Ä¢¯‹fš=Á·/ÑáW")šqÐw¿µk×úí–H}I"µÅ‰@ …¢Ù—y£]g,úÈÀ —^z©_ZµjUÏe—]æÑÌóæÍóžš'’!Õ8àÑL¶¾ýs‹-Â§í€ @°Ñêc~ùåÏ×_múÙË÷oöþógfÚó-Ùí?é³P"µÅ×–i@ŒÑê÷´æÜîû¢Ùv¯ }˜W‚gRR€!ÕRò²sÒ®ð È)Q¢„g×®]aÛÞ£G¿â@XôKÖòåË;Ûi°ÌG}¸™3¯_"*TÈÙÞûA?TÀÑ!Cü¶ÕáàLF§¾À‰‘#Gúm_¥J‰ÄÜÌξiѶ(PÀ"ÛA¿ 6]Ë–-=;vì¶‹çÉ'ŸôkO°ˉҎ 'ÀB@Àe±èë¢Y§Òúöƒ:i¸~Mùu¸Oo©ÏÁ‚€©/I¤¶¸ìåKs@˜ D³/ó62ÚuÆ¢ ¼aìíOkÔ¨a,â=—ÀçÌŽ´­Í›7÷ëŸu¨mý|LAȹ@´ûmQ¿~ýüþnoÚ´)dC³Û$Òg¡DjKHhV €XXô{Zqnô}±h;}ÿ1Hi†T3_^QHXåË—;mkÒ¤‰”)SÆ™6qÛm·ù-^¹r¥ß¼Î<þøãb²9ËÇ/íÛ·wæ't¨³Ñ£G.:on°ÊSO=å¬kܸ±˜/~¥páÂβÀ‰|PLf!g±‰æåÌg61`À›b?Øv:´œ¦Ç÷-&@I^zé%1AW¾‹éþýû‹É„ä̯^½Ú™7‘(í×FÖ!€‰(‹¾.šuš€_¹üòË:ŠÔüÈ™6l8µ`Û.K¤¾$‘ÚèÄ< Ñì˼^Ñ®3·úH“1×m²yO%KÏ&ØÈ~æõv\‡æÖþ¼X±bYª‹@‚ D» ~”¬-Ínÿ‘HŸ…©-YÓgk@ ¹±ßSñHú¾Üj;}Xrÿàìðøë®ºïR¦@ îþù§¬_¿ÞiÇ÷ß/&>RÒÒÒœeæš2nÜ89vì˜]uöÙgûm²ÿ~1|œegœq†h@QfE™4PÉd »é°aÜck;5ØÈ Åv]©û™aÞœ}ÿõ¯IÇŽ3ÝO°î½÷Þ°ÛÕ©SG|¿X6CÇIݺuCîc†—“SO=U6lØ`·ùí·ßBnë]‘(íð¶‡g@À-±èëbQ§ùåøét—.]B2¿ýöÛÎ:í»wïî̇šH¤¾$‘ÚÊ‹å €@2 Ä¢/‹Ez r£Ôµ”*U*[—|ïÞ½6ØÈ÷KuýÁͬY³Âþ0&[c'@ EbÕÇä”3;ýG"}J¤¶äôZ°? L‰Úï©qf}_nµ>,™^ñœ ™ p”¹[ 3˜4hÐÀþ’Sð믿Jß¾}å…^Äsçw†lïš5kD33xK§NÂÖåÝÎ »&·ß~»Üwß}ÞEAŸ}3ÕªUK4+S$¥\¹rÒºukùøãíæú寮Fô¸áŠMJ–,n)]º´ßz5ͬ/^ÜÙdÏž=Ît¨‰DiG¨ö±HTXôu±¨Sƒ`µ?ñö ï¿ÿ¾9rDÌPkhMšYºt©³\ojV¨PÁ™5‘H}I"µ%”Ë@dˆE_‹:õĺÔÏ”á2ò†{ìÞ½Ûî»bÅ g3mïÌ™3ƒöáÎFL €dI V}L–°qvûDú,”Hm àeHiDì÷ô‚DÒ÷åVÛéÃRú¿'Ÿ‚yRðœ9e\# iÞ}ËäÉ“¥zõêrÏ=÷H¤C}ùîÿã?úÎJ›6müæÃÍœyæ™áV‹fÒTõޢée¥øi†¦7fº»ZdV4c‘oÑ@¨¬øÎ¬$J;2k'ë@Dˆv_§çí:u8Ϋ¯¾Úá;xð`Èá?}3!é×\s³_¸‰DêK©-áÌX‡$³@´û2µŠE±î#5j”­Ë¬ŸOÛ¶mëü€G+Ѷ¾üòËeK”@ð±ècÂ1üÚìö‰ôY(‘Ú^›µ €@ê $Z¿§W Ò¾/7ÚN–zÿ'8ãÔ à(µ¯?gŸà£F’fÍšùµrÛ¶m2vìXiذ¡”/_^ºvíj³iF…ÌJ`À‘©i©Q£FØM×­[ç·þ»ï¾“k¯½6âÇ‚ üöߺu«ß|°™ÌÚlŸÊ•+[œ£e‰ÒŽ;#€qˆv_§§‹:uÈßXä]ç;œZÑ¢EåÊ+¯ô® ûœH}I"µ%,+@$ˆE_‹:õIJÌÊgVß—CçÎå›o¾ñ]d‡ð9r¤ß2f@¢#«>&»­Ënÿ‘HŸ…©-Ù½ì‡$«@¢õ{êiß—m§KÖW>ç…@p†T îÂRB D‰v˜±nݺ9Ãù6Lµ9cÆ ûÐåš…¨{÷îvø³²eËúnj§ŽJ•*•a›P 2‹Hp¤AGÙ-‡Ît×ìiÊÈh—DiG´Ï‹ú@܈v_§mŽEš ¸fÍšòóÏ?[–÷Þ{ÏÞ¸Ôl Þ²yófY²d‰wVôf§ER©/I¤¶DbÇ6 €@2 Ä¢/‹EjË>2_¾ì}mõË/¿}YLœ8Qzôèa‡ôº @²%«>&[1;e·ÿH¤ÏB‰Ô–ì^öC’U Ñú=uŽ´ï˶Ӈ%ë+ŸóB ¸@ôï¼?K@ ›ÚùôÑGòùçŸËu×]'Á‰¼Uÿý÷rß}÷Ùa×þõ¯y;Ï_º–,YÒY—ÙDfoVô&k4Ë‘#G2­.oÞ¼™n“$J;rã\9  höuÞöE»Î´´4¿áÑöïߟ!80ëQ`ÆoÛ‚='R_’Hm fÅ2@ U¢Ý—©[,êŒu™“ë­}ñˆ#œ*<Ü|óÍÉçMg'&@"ˆEÑ£¸Q"}J¤¶D‘˜ª@¤ps¿ë¶Ó‡%ÍËœA "ìýT,¢ªÙ¢)pÁˆ>þüóO›=aÞ¼y2þ|Y¸p¡fÒyýU‡\»ì²ËœffYØ»w¯T¨PÁYnbÇŽáVKÕªUýÖßrË-rÕUWù-ËÊLƒ ²²9Û"€$@4úº@†hÖyÍ5×ÈèÑ£Ch€‘o?ë;œšöÁíÚµs¶e@ì D³/ó¶!Úu&b9xð`yòÉ'mF·ÞzKÖ¯_oO_Ÿï¿ÿ~3fŒ—ƒg@( D»‰bÓ¨ @¨ ¸¹ßssÛ£~!©²-@†£lÓ±#ñÐ!ÁZ´ha¥ùñÇ‹ Í;Wn½õV)V¬˜Ó¨“'OJ¿~ýœyÌh”•¬D[¶lñ«+p¦víÚ~‹tˆ™öíÛgûQ±bE¿ú˜AHœôu¡”¢Qgݺu¥iÓ¦Î!fÍš%Ç·óÚOú§öÿ÷§2v*d@0ÑèË«V‰ÖG>øàƒ2~üxÑìK ”çž{ÎïÔÇ'+V¬ð[Æ  €@t¢ÕÇD·UÔ† €@lÜÜï¹¹í±¹šÔŠY à(+Zl‹@ è—§—\r‰<ÿüóòÍ7ßH5œVnÚ´I~ûí7gÞw.Ì,ˆÈÙÑLhPS¸p´nݺp›³@ˆ²Ò×EZivëô&Mƒ~5ã –3fˆÓâ-¾Ûy—ñŒ €@4²Û—…kCNêôíûâÝGöîÝÛï45ë`Ïž=e'Nœ>}úˆ>S@rG '}Lî´£ € =7÷{nn{ô® 5!€@¤E*Åvä²À#<"gžy¦}œwÞyýÔSO•úm»jÕ*g>°žÙ³g;ëÂMè0nšÅ!\Ñ¡ÙtÜWoY¶lY†¡Þ¼ë‚=k ~ïù¶nÝÚï¦m°íY† à~Xôu±¨ÓWZ3ùŽCîFÍû¬ÛÖ«WOš5kæ»Ó €D,‹¾,užP¢÷‘:¼šoÖ_ÍpôÄOžó €YÈ>&‹Mbs@b&àæ~ÏÍmÙ¥bȱG9&¤b# CŠ­Y³Æ>¾úê+Ù¸qcDò úѪT©âìײeK›NÞ»àµ×^“H†U›8q¢üôÓOÞÝB>ëjÞ²{÷n™4i’w6ì³ ÷úë¯;ç[¿~}›ú>ìN¬Dp½@,úºXÔé ­¶š%Á[4 W3 .^¼Ø»H³*8+˜@@ Xôe±¨3ðT½Ôö=úè£~Í~à„ì¼~$Ì €YÈ>&Ëb@b$àæ~ÏÍmÑå¤Zˆ‚GQ@¤ b!˜á¹çž‹è0Ÿ|ò‰³Ý)§œ"uêÔqæK•*%šIÈ[Ž?. #GŽxexÖ`§{î¹'Ãò` ôס… vV=þøã²sçNg>ØÄü!C‡õ[囊ßo3 €I%‹¾.u¢ûöS»ví’þýû;™ùtÌsßõû2 €@f±èËbQg°óðí±ìÛ·¯øfþÕÏÂ7ß|³Ó;'–!€„ˆU£Ÿ­|Kfß1únË4 €±ˆU¿§íuß˶ÇÊ›z@ ñüßµ'~{i!)#pÖYgI£Fœó7nœŒ1B4H(XÑaÏ~øayóÍ7Õ;vÌðeøðáR¼xqg›÷Þ{O.¼ðBùöÛoý¾dÝ·oŸM/ÑEÉþýûíÃMÔ¨QC† æl²uëViÚ´©,_¾ÜYæ;¡Ë7n,+W®tßxãÒ¢E gž @äˆE_‹:¯À•W^)E‹u¿ÿþûÎôÅ_,U«Vuæ™@@ «±èËbQg°óJô>R¿Àá…ü†G]°`¼øâ‹ÁN‡e €ĪÑ, ¾eìØ±~ß]ú®c@܈U¿§íuß˶ç–?ÇAÄÈ—xM¢E  úE¨eÖ¼ysÑ`"}èøª:t‹i梚5kÊž={díÚµ¢Ã£ù»¦oLž}öÙ ˜µjÕ’iÓ¦I·nÝ䨱cvýÒ¥K¥AƒR²dI9óÌ3E‡CÓºŽ=êì߯_¿ õ9üoB³½úê«NZú-[¶ˆåÖ¤I@uúé§Ë?þ(«V­Ížä@¥ov&L˜X%ó €I*‹¾.uòk°QçÎm߸Ng) €äD }Y,ê vŽnè#õ‡=”ñãÇ;§p÷ÝwËå—_Nа# ¹@¬ú˜zõêù5búôéR¬X1©V­štéÒÅþðÒof@ÈXõ{ÚôX÷}±l{.ÐsHPŽôÂÐ,T@ÓŽ9R|ðAç<ß}÷è#\)R¤ˆ¼üòËR®\¹ ›uêÔÉfÒ›¢lä-šÕhÑ¢EÞYûœ7o^=z´´jÕÊ/à¨@~Ûyg ,(_~ù¥ÜrË-òöÛoÛÅØ´xñbûðnø¬_úΘ1C´í@ÔˆE_‹:¯ˆ£Á¾¾¥téÒ¢™( €äT }Y,ê vžnè#õ3¶~^Õ¬¼Z8 ·Ýv›Ìž=;Ø)± @ Xô1Þ@Pïßjm¡C‡ä‡~¶“‚ €@¼bÑïé¹äFß«¶ÇëZp\ˆ¿CªÅÿРÜÿýòùçŸKÆ Ãn§+ÓÒÒäšk®±.¹ä’°Ûׯ_ßéPm:„™ïÐ0ºc¡B…ìMSM/Ï=÷ÈüáW_¨`&ݨT©RòÖ[oÉÔ©Sí/üv ˜Ñm5+’)vÚik™EHXôu±¨Ó÷Z´oß^*T¨à»H®½öZÑÀ[  €ÑˆE_‹:ÏÕ }ä)§œ"O?ý´_ÓuˆTß!ÊýV2ƒ ©@´û˜üùó‹þm®]»v¦Çf@r[ Úýž¶?·ú¾X´=·ý9$Ž@ZNšâñx¦™ý{å¤öEÈNž<)sæÌ‘õë×ËO?ýd;wî´i„5PG‡JÓÀ¡sÎ9'² ¶Ò!Û´nNMo V®\Y .ìlõî»ïúemX³fÔ­[×YjâàÁƒ²bÅ ùúë¯ícûöí¶îªU«JãÆmÄ67gCé±H-Xôu±¨Ó{Uúôé#S¦LñÎÊêÕ«Ez) €DS }Y,êô=gúH_ ¦@Ôˆv£õéw¡ëÖ­Öï-õ‡™¾ß[¦–0g‹ HÑî÷ôÜr«ï‹EÛéÚÐȪåŠ3AÀý=ôŒ5Ê9M]\¦Lgž @RIÀÞËé§Ÿn¿øÖóÖ¡G5+ @T LõWç € € €)"P5_Šœ(§‰F@£•?üðCÇBÔ´iSg>ÜÄÂ… Õzƒ•`#‡ƒ @øè£œ`#=ý~ýú¥ §Œ €@FúÈŒ&,A@@@’Q€€£d¼ªœ!òæÍ+tn/^\6oÞ,%J”±GúbÍ7kC—.]ÂnÏJ@’]à™gžqN±R¥JBßèp0 âô‘)þàô@@@@ eò¤Ì™r¢ `:tèàH8p@ž{î9g>ØÄ† ¤cÇŽrøðagu×®]i&@H5¥K—Êœ9sœÓ}dòäÉÎ< €$»À+¯¼"ûö퓊+Ê7ß|#/¼ð‚ìÞ½ÛžvÉ’%eÓ¦M¢Y) €¤š}dª]qÎ@@@pª2¤šcÁ©!pñÅËc=fŒôŒOœ8!&L°¢E‹JåÊ•íÓcÇŽeiР<õÔS–³@dX¸p¡Lœ81è)Ž5Š`£ 2,DHúÈT¸Êœ# € € € \€!Õ‚»°¤2dˆŒ=Z .ìwž‡’õë×K°`£ë¯¿^/^,”DA@‘AƒÉ€ @@úÈf@@@@$ ÃQ^TN HFŒ!·Þz«æµ×^“Ÿ~úIt(5ßR¥JéÒ¥‹ôìÙSš7oi@RF ~ýúR«V-9xð Ô¬YSÎ:ë,éÔ©“üýïON@`ô‘ÁTX† € € €¤†@ZNNÓãñL3û÷ÊI싉!`þ?ËŽ;dûöíRªT)©X±¢*T(1G+@@@@@@@@ Qª’á(Q.í@ Îiii6ÈH( € € € € € € € €@(<¡V°@@@@@@@@ ÃQ ó € € € € € € €DQààÁƒ²aÃY¿~½}þù知dÉ’R³fM9í´Óìógœ!yò3$ŠìT…1 à(†¸T € € € € € €¤¢ÀYg%ûöíËÒ©W®\Y4h õë×·ÏM›6•R¥JETÇÅ_,?üðƒ³í{ï½'Mš4qæs:qöÙgË®]»œj>ùä©W¯ž3jâ×_•áÇËÔ©SÅãñ„ÚÌ.?ýôÓeÈ!rÝu×IÁ‚ÃnËJ@ Þi9i€ùƒ8Íìß+'u°oâ L›6MÆ/åÊ•K¼ÆÑ¢¸ ìØ±Ã¾¡+P @ÜÚÀKà?þÇK™2e«a9lÍ/¿ü"ú!¡bÅŠ9¬‰ÝIà?ÿùŒ1B*T¨HÍ¢-q8qâ„ìܹSôK ¾[·nµ¯‹dú5™öÛ%J”÷ßß÷T™v±À’%K¤oß¾¼gqñ5ŒEÓÿüóOÙ¾}»T©R%ÕS§‹¶mÛfß çÍ›×Ågáßô#GŽH¾|ùäÓO?õ_Áœkô—þ]ºtáý¹k¯`잌ïÏc§•:5ëÍ{ý^2þüIsÒG•ãÇËÂ… “æœ8‘tüãòÅ_ØL6©f2oÞ<ÑïàrRôÿyÆ #º±hÑ"ùý÷ßÃ{î¹QuŸ?¾;vÌ©¿E‹R¬X1g>pB?£mÚ´I~úé'9yòdàê°óz?N3U¯^]ÒÒrtK?ìqX™8œ§ßG/^}|–¦ÆdË–-eÿþý9:Y XX±b…Üyçrà 7„­ëïÿ»ªÌ»‘~÷§Y‰¢UZµj%{öìqª:t¨Ô®]Û™œÐ÷àúçPE »{÷î AYØ´víZ{_²ï“BÕÃòä˜2eŠý®GïS%KÙ²e‹Œ=:YN‡ó"@ÀQ”T_¤7VŠ)"gžyfªSpþ>úºÐHj^>()>©¿<Ô›\ÉöšÐ_ $Ó¯~SüeꜾ¦žÕ¿cÉözuN‰l è¯!õÿ;¯‹lñ%ýNuëֵåDõ—tÜ I–«™~ú O}ð7,¹®kNÏæÐ¡C¶ ^9•L¾ýõ=ÞI¦ŒŸ¿ýö[R'ß«.ëg¤¯SýE7òn— {èûs J£ àÐ ÖªU+ì~ï¶nyÖì}üÒ-W+kíÔ¿_¥K—NÉ>.ð»v À •™L3!ip’þHpñâÅ~Cš)è‰'ž°ÙŠ4“}¨øã±hß×Ò ›¾Eÿ…zïòî»ïÊôéÓ}7—óÏ?_FŽ):Ô\Û¶måÛo¿µïô{ .Òà¤gžyFô|½E‡…kÞ¼¹ 6Ì»ˆç$ÐN—,Y2äkʧ­ýZ¨ÿón<ÚœQÀÿ¯bÆõ,A@@@@@@@ GšH“DRæÎ+Ý»w÷ˤAGýû÷·ÃÆGRG¼¶Ñ:ÞtÓM~‡ŸÛ!aD O‚´ƒf €@‚ è¸jÕª%x+i^n 4jÔHzöì™›‡äX €@Tt,ì»ï¾;ªuRYrè¯íøUir\KÎTп]ú7Œ‚@ €…­j) €€î¿ÿ~ÞŸ»ñŸ̓ ’òåËÇø(TñèСƒÍtä ´oß>™9sf<›ѱ5»‘•æ-}ûöu‚t™iQ`(]׺uk;„œf»ñ–ÇËŒ3¼³<'©@ÇŽíõOÒÓã´’T€€£$½°œÑÐ7v¾on¢]?õ¹O@ÇG×ôŸ@À­úeE×®]ÝÚ|ÚC ¨ L‘ÃÃQ5 5MSÞ£G¨ÕGEÉ# ïy|oÔ$Ï™q& Ú·1G*\é¬c§Nì°3YÛ‹­@ÀmõêÕ“–-[ú5[‡Kô²bÅ ¿&jf'ߢGW_}uЀ#ÝN‡à ÜgΜ9¾U0„úCÿPCô%áérJI"@ÀQ’\HN@@@@@@H& /¼Ðït¶nÝê7Ÿˆ3¾G¥J•’Zµje¹™;wöÛgÓ¦M~óÌ €‰ /A@@@@@@@ðÈ“Ç?FõêÕ}W'äôºuëœv:tHtH´Â… ;Ë"™¨]»¶4lØP8`7/T¨P$»±  «þ¡sõÐ @@@@@@@à .ô[Q·n]¿ùDœñmã±cÇäóÏ?ÏV3W­Z%?ÿü³}øfMÊVeì„Ä@€€£ R% € € € € € € €@ö6oÞ,‹-r*(^¼¸tèÐÁ™OÔ‰æÍ›û5­wïÞ²zõj¿eÌ €É @ÀQ2\EÎ@@@@@@Hµk×Ê\ û÷ïwÎhÔ¨QR¡Bg>Q'Î?ÿ|¿¦íرCZ´h!7Üpƒü÷¿ÿ•ãÇû­gp«@>·6œv#€ € € € € € €ñxöÙgeãÆA›±råJ9räˆìÛ·/èz7/¬]»¶Ü|óÍŸÂgŸ}&  ºýÉ“'e÷îÝ¢Á9óæÍ“?þX>ìl;pà@4h3ŸÈ]»v•^½zÉ«¯¾ê4óСC2uêTû(Z´¨´jÕJÚ¶m+­[·–sÎ9GòçÏïlË àŽÜr¥h' € € € € € €$œÀ믿î7ôW°~ñÅÁ»zYûöí³pô·¿ý-Ëç[¢D ¸sùå—gyßxí––&S¦L±T|ðA†fhðч~hº²páÂÒ¬Y3iÙ²¥ @ºè¢‹Bfe¨Œ €@8Š#>‡F@@@@@@w Ìœ9Óf1 všåfïÞ½2`À€`«]½Leb]tHµçž{N4ðH³¹¥hÆ"}]<ÿüó2~üxÙ²eKȦk&§ ØÇ˜1cä”SN‘:Hÿþý¥M›6!÷c oŽâ}8> € € € € € €¸V B… !Û^¦L»®F!·aExͤVí‰'žpÍðc… ’;î¸ÃéqšÕhîܹ²nݺ°'üûï¿ËŒ3ì£cÇŽòÊ+¯HÙ²eÃîÃJ@ ÅCc"€ € € € € € €)$ ÙŠŠ)òŒ9b³AmݺUæÏŸo‡%Û°aƒ³ýÓO?-Å‹—‡zÈYæ† Ív¤ÃÉy‡”Û¼y³è{‹/¶Cñ­ZµJNž<ôT4Ðꪫ®’O>ùÄ5VAO„… ”y’ò¬8)@@@@@@@„È—/Ÿ„{èPbÕªU“-ZȰaÃdùòåÒ¹sg¿ö;V4@ÇÍ¥zõêÒ³gO™0a‚=GrïwÞ‘›o¾Y*Uª”áÔt¸µÛn»-Ãr €ñ à(ÞW€ã#€ € € € € € €ø h6£™3gJ×®]åÇ—G}Ô™O†‰bÅŠÙÀª‰'ÊÆeÒ¤I¢AI¾å¥—^’¯¿þÚwÓ €@Ü8Šû%  € € € € € € €iiivH1ßå«W¯öMªé ÈM7Ý$óæÍ“Ò¥KûÛÒ¥Kýæ™Aâ-@ÀQ¼¯ÇG@@@@@@*жm[ÑÀ#oY¿~½œ8qÂ;›PÏ7Üpƒ\sÍ5ö1xðàl·­V­Z2bÄ¿ý—-[æ7Ï  o|ñnÇG@@@@@@@ ˜@Ù²e%þürìØ1»Z‡U;pà@† @ÁöÍíesçΕíÛ·ÛÃæË—OüqÛöì´£qãÆ~»­ZµÊož@ Þd8Š÷àø € € € € € € €A¶lÙâé€8ÜXÐã°°|ùòÎQ5 Óš5kœù¬NTªTÉo—"EŠøÍ3ƒÄ[€€£x_Ž € € € € € € TàÕW_õ[~æ™gúÍ'ÒL«V­üš3yòd¿ù¬ÌèÐq¾%0ÉwÓ €@<8Ї:ÇD@@Rd#Í@IDAT@@@@+°lÙ27nœß6=zôð›O¤™Ë.»Ì¯9S¦L‘Õ«Wû-‹tæ™gžñÛô‚ .ð›gˆ·Gñ¾@@@@@@@ÀOàùçŸ ²Ù»w¯³¼N:rÓM79ó‰6Ñ¡CiÒ¤‰Ó¬C‡I‹-äí·ßv–E21|øp™;w®³i¾|ù¤[·nÎ< €@"äK„FÐ@@@@@@@ä?~¼(P ä z<Ù´i“|÷Ýwö±k×.¿m5èf„ ¢Ï‘”þóŸ’ÝaÈzõêå8Éñt›´´4Ñã¶mÛVŽ?nwÓ £«¯¾Z† "×_½Ô®];è9ìÞ½[,X cÇŽ•%K–øRÊ—/ï·Œ@ Þ‘ý5Žw+9> € € € € € € €€kî½÷Þl·=þüòïÿ[Ú·oqº}vKÓ¦M³p¤ÇÓ¬L/½ô’ôîÝÛïð?þ¸èCƒ®4SSýúõ¥hÑ¢²víZùá‡ä·ß~óÛÞ;Ó±cG9r¤w–g@ a8J˜KAC@@@@@@@|.¾øb7nœœ}öÙ¾‹zúÚk¯•êÕ«ËàÁƒeåÊ•~m=v올^½Ú>üVÌ*THîºë.yà$Ož<k™Eâ/@ÀQü¯-@@@@@@@R^ dÉ’R¶lY©Zµª–L³ûh¶!7–Ö­[ËòåËeêÔ©2bÄùõ×_#:3Î8Cn½õV;üZéÒ¥#Ú‡@xpuމ € € € € € €$±ÀîÝ»sõì4kP,ËŽ;²\½f&ºñÆ¥{÷î²téRY¿~½}lذAôQ°`A› ©Fö¹Q£F¢JiiiY>; €¹-@ÀQn‹s<@@@@@@@”(Z´¨´iÓÆ>Ræ¤9QHz{LúKÌ "€ € € € € € € € =Ž¢gIM €1øóÏ?å7ÞÆÛÈÿéӧˉ'2=ÒÉ“'嫯¾’ßÿ=ÓmÙ@@@@@@@ rŽ"·bK@( ìܹSV®\)ªhPÑÔ©S¥^½zÒ³gO;¦ñ—_~)ݺu“š5kÊ£>*»víòÛýøñã2wî\éÛ·¯TªTIÎ;ï<©S§Ž¼ùæ›~Û1ƒ € € € € € € }޲oÇž €@Ò lÚ´Iî»ï>™={¶:t(êçwìØ1;v¬ÔªUKÎ9ç)Q¢„´mÛVFŒ!ï¿ÿ¾ìÞ½[Ž=*/¼ð‚œqÆrà 7ˆ'5J´m[¶l‘Ñ£G‹Çã‘áÇKµjÕì6¯¿þº\wÝuR¾|y¹ôÒKeÒ¤IR¡B8p ­¯GÒ®];ùᇢ~NTˆ €@N–-[&cÆŒ‘uëÖE\fÿÛ³gOÄÛ³! € € € € €Ñ à(Ú¢Ô‡¸Tàµ×^“³Ï>[|ðAéÔ©“”.]Z.¾øbyâ‰'äÛo¿ÍñYýç?ÿ‘úõëË=÷Ü#+V”¡C‡Ú DK—.•GyD®¸â )[¶¬}ÜvÛmv(4]®F<ð€mO¹rålpÒÆåßÿþ·4mÚÔfAºæškä•W^±LºÏÚµkeõêÕòÔSOÙé›o¾YæÍ›' 6”aÆÉüô|vìØÑpmAwf! € hà¬÷¶nÝZš5kfû¦ºuëJ‡ä½÷Þ ( V4;à]wÝen5°vРA²oß¾`›² @@@@@˜ ä‹iíTŽ 7 ÊÑLAMš4‘Î;Kþüùƒ¶eÿþý¢>o¼ñ††ìÅ_ ¼ùðÃeþüù6PgÈ!RµjU¹ÿþû¥OŸ>Aë µpýúõ2xð`™3gŽœrÊ)6‹ÃwÜ! °»è°jдhÑ"Y¼x±:M‡M»å–[¤hÑ¢A«Í—/Ÿ\}õÕö±bÅ Ñ %½I[£F Û—)SF&NœhÛ}ûí·ÛãkF$=_ýUÔÉû8|ø° xÊP @ÈD@ƒˆt(Ð &Ø€ FÙl~ú|ê©§Ú½µŸÑÙ'Ÿ|Òf4Ò¾ðú믷A·:üç;ï¼#}ô‘íÏ´oÖ¾JƒdµßzõÕWå»ï¾³õh¦@­÷é§Ÿ¶ë4ØV·Í“‡ß“dr™X € € € € %Ž¢I5 €@¬4CPñâÅå‚ .´´´‡Ó!ÈtØ1 Ò!Ì´hžL3ýœvÚiξ ,k¯½V6oÞlƒ’&Ož, £E‡#;räˆè6|ðh¤üãÒ½{w8äTbBo¼Þ{ï½6CÒñãÇ¥W¯^v8µÊ•+ûí‘7o^›YI³+éÍÕ¬šM™•óÎ;Ï&=ÿüó¶]:tœ–Â… Û»mÚ´±7„Õ™‚ \ßÿ½ícŠ)b³÷i? Ø ×ŸfE`É’%2`ÀÛÏh_­´š©È[J–,iû: Úµk—”*UÊf5Ò}*Uªd7ëÒ¥‹lÛ¶ÍÉj ¬fÔ!EµÕ>U³jà¬ö§-Z´°Ë4éî»ï–¾}ûÚ c @:ÿüó½‡užuÈÒ5kÖˆùR@@@@@ˆ†GÑP¤@ †zÓ²ÿþòÙgŸÙ£h¦! úéÑ£‡Í^ä=ôlpÏøñãípd`3räH› Ao\Ž3Æü´oßÞfZ¶l™×€›I“&ÉM7Ýä­Êy.T¨\rÉ%ö¡Ã¡é6/½ô’ÂÅÙ(ÄÄŒ3ìPi ôÌ3ÏHË–-Cl™{‹5óC¿~ý¬Ý† ¤zõêvx7ßèyR@’G@û@Í´§;äªü´h€mÛ¶mmÒßþö7›•(«g­™ò40H³iö½;ï¼S4 UûO .Ò!Ð4Ÿ÷¹|ùòv½Ëâ§A¹šMpĈ2sæLñëС—^z©_¶B –Ò á+¯¼Òkÿ¯AÉ={ö”:uêØŒëÖ­³Ï{÷îµ§¦Ù) € € € € €DC€€£h(R  Ò›–¬óçŸÊ­·Þ*¥K—reܸqöqÆgÈÿýßÿI±bÅä±Ç³YêÕ«'?ü°½©Íºì²ËD‡DûôÓOmÖ£Y³fÙáZt]³fÍlæ"­'³¢7;‡.O=õ” €Ò›¶¡ŠfbÐ,Kz3U‡†Ñ¬ ‰TÔñÜsÏM¤&Ñ@t(PÍVW°`AѾIƒx‚•}ûöÙ@Y €=Õ i¦C‡j6½… Ê'Ÿ|bûE]÷öÛoÛþjûöí¶? VWà2 ^ÒþðÁ”ƒÚa=ÿùÏJݺuM½ø4¸(«E‡AÕàb}dV¼Ã•êj:d©¿æ-š=©aÆ¢ýü‰'Èpä…á@@@@@ Çå˜ @ Õ¦OŸn‡Ó`œZµjE…cÚ´i2tèPÑÌ Í›7—gŸ}V7nlëÖ`"ºEoœ¾õÖ[òÐCÙåš­gÊ”)Ò»wo›ÁÁ·!š¡]»vö¡u¾üòËvÍÄ ")š­A‡rÑÌ ï¾û®\uÕU!w›={¶¬ZµÊÁ–hÁF!Í @¸h¡C~µjÕÊ/ƒO`c4€Hƒzô¡AGZ´¯ÔìD×_½\~ùåÎþT¤™~tÈPÍê£YŽJ”(a÷ñö‡:£™4@öÉ'Ÿ”Ï?ÿÜÖe7Êä "Ò¡Fµß×aÍ:uê”ɱ_­AEï¿ÿ¾Í¨¤ýþé§Ÿî7ª®cØÐØ_Ž€ € € € €¤Š@dw™SEƒóD²( Yt8Í@¤7õÆç°aÃD‡) W¾øâ ;ÔÊ‘#G$ð¡ÁD‹/–råÊÙáËô¦¦Þ8ô-:\š>ô©µ¦7T5Ó‘f{ȬT¬XQî¾ûîÌ6 º^Žth6=n¸€# ‚Ò¥»îº+h=,D@`×®]6sžÕ©ý¨é°a¼£AD%K–´H¤AFšQHj×®-&L°ýÌÔ©SmÍ{ï½g³éiÆ#oÆíuH2Íüª”*UJ®»î:§?ÕãfVNžùDþûßÿÚ ¡çž{N4ÐHmK¥J•lŸ£Y5V‡hÓ¬E‘iÁ /¼Ð÷wÓ©fÖÏ›7Ï6Aƒ¤( € € € € €¤ªG©zå9o‚˜Q²l°‘®úöÛÜ 82Iä£Ò¥Ùuâp¤Ã¹ôíÛ×Ó´nÝZ† b‡t ÎLo‚êMOÍös÷ÝíÍ Q1™Äf[Ь>:´Ù=÷Üc3-hÖ-šµ¨cÇŽvX—Ë/¿ÜfnH?ÛìýkîÇÊìÙ"ï¾+öøGŠÔª%Ò¹sú£eK17e#«[“-{®˜l "wÞ)&Sz¡ŽÎ4Ñh:t™3gÊ&©T£F ç@Ÿ~ú©îV“"«J•*ÎòD›8qBäØ11_‰Ö2Úƒ$–€û©±‘”C‡Ù,~_~ù¥ Ò¾/Ÿ‰$Ög}üòË/¢CŸi  >ÜÞúÖ­¿:š>>lÞ|+Mš4 h仟wÚ;ä¨w>Òç6mÚ˜>õ]Ñ!OuX·pEû:5i©-@@@@@ à(E/<§@0­[EÎ8CäÇÓŽ‚m“ÓeÈ€bn$ŠœsÎ_µÝu—Ø,Abb}r½hæ!͆ðÚk+¤dÉ×M¦Ÿ·ä³Ï.·C¹Üe׳gO›µG³.\}õÕvèÍpP·n%4È¿¹šÁè¦HõêÃeõ껥Y³f¶nÍÀ“¢YˆÞ~;=Èhñb%ùó‹˜{¤6ØhÎ1•ÒfD63ìLdGÓk®Ù¬ºwH$òóÏbn§ ™dKAË&2éÃ?´C×<©‘jÿ+šÝ(¿i”\%j1#õ˜ S"¿ý&&ÀLL[E*WNÔÖÒ.@ >ÓakîÔ©SmŽö‘W\qEЬAš•h„ òüóÏËž={Â6XëÐaGki”l&¥pá¶Íd³¨¬Ö@c-Ÿ}öYØ€£c&Zu¡Ixþù絈Jc¨@@@@@pä‚‹DÈ-É“EþøC¤aÃØ™{‘fØ11C‹‰¹1ù×™µoÿ×tàÔ;-rß}":®ÍùüñãÇm@ÑôéÓ¥L™oM–§³L¥=äôÓ¿3|ºË 7Ü`31t79:¤‹y–lT7äÁ5SÐôé§›@£¢qF(¤„|‹&²LDœž¹H¯Ž¶vÕUéóû›˜©¿šñõ×éI_ü×2ïÔ¤ï[³¦[#RµªwMzV#ïœ^ 57£ØØŒIÞå¾ÏíÍFš½é¥—^’ûï¿_Š/.:LŽÞ¨½ñÆý²ùî—i RÓ (ͺ¥f¾íÎJ}º¿»ÍŸ/&`LL0™˜ä"“&ýx”ذ¬4‡m@„d¢i'›75M§¡¦p[Òt8ÚjðQ‹-díÚµvèÐW^yEŽšT{µk×–G}Ô9ª™4˜×û8a"Š5ËQ©R¥ò¼š7?Ú¶ùÚI„)š½éÓ3œZ$V!€ € € € €¤„@„'‰@B hÐÅ›oмø¢ˆNǪèSõë‹è0[&'ªeÆô xyüñȫ޼YdÍ‘¿ÿ==3R¤{nܸQz÷îm2)¼loÛOo^e¢w4بC‡»m°‘ó˜QÑdƳÌÒÕf(´ÏÌ®ùmF†B…Î3ÃÅ|.:¬X¸¢C¬i0ÐË/‹\½Ø,H£F¥gÒÀ. @6LL¶$3ZM¦Å$y0ÁPé@»v‰¼õ–˜ )ÿ`#­Dr|0c–(Í¥ÁN&&Èÿ¦_¡J»vék4È)\Ñ,G°7¤u»Íõf²‘òØc"$¥Y–4†^ÿFD¾ÿ>ëµïÝ+Ò¼¹È‚"·Ü"²nÈòåbn §¿ÞŸ~Zä´ÓDÖ×½¦ €I& A¡š]Hf2+:Ü™f,ºè¢‹ÌßÜïe«I¨ÙìtÍÍJ¬ª‰þ¬W¯ž Úœd‡<{ÇDª®1µfE*Z´¨ÍþSļ©(V¬˜ T*[¶l©G3i«V­dÙ²e¢CÃ…*p¬…€£PB,G@@@@H<©r¢œ'nÐÀˆ=Ľˆ¤¥Åöl4àHƒL₨þKo4CÏ¿þ•ži'ÒÊuȲŸ~JîkÊ‘‰3ßSo¨žwÞy2mÚI¹óΫ¥bÅ+eÈ!&SŽI•ó¿røða“1©“Ìž=Ûfk˜3çùâ ‘'žyã ‘O>3,Zš|ðÁ…æ†éÏ&hh‰.ìS¹ýö:&“ƒ·–àϤ×ì£ÄÔŸè²j•ˆ‰ ~Q jš1CD³<¼ïR ¼Ñ€­ÎÅÜÄõ.üÙ$š0û‰¹‰*bF¾1çz_bÍÜS¶çz+ xêi\+ÊÓ&Zç ÷‰Óe‘ “®^ï: ,Ò@³¦MÓLÒ à$rÉ%b2Oy·ŠìYjhPÑÒ¥éWz}´\vYú2½Fšñè©§D¶m{ }%ÿ"€I" Y{.½ôR›¥èÓ¡Œ2°šq(X3fŒ<òÈ#&H³¹^ó=)T¨T¨PAî¸ãY¹r¥¬2™œj£¿›HP^LM¥A;n.mÚ´±.z>¡ŠiUSíœ( € € € € €¤°€»ï ¤ð…ãÔ[@³Çh`‰¬Ì™#¢Á69-& v3„UÆšþñô •iÓDL M–Ê/¿ˆh!ߢGZtªh•qãÄÜLÏôÓºuÖk5q-6H³# (¢C‡…*/¾øž´iÓÁf(?þs´ ÉT4Ú=a†I;ÝÞ ýàƒL¢¿™€ LÆ›[LÔ¿ìÒóÏ9õÔôš5è›oD~XÒL0ʹ²gO>ôIІéðd—_.&kBúPuÈ£C iÆ¢×_OÏøT¥JdX „:ã¬-/_>ó 5Ír¤Y€¶l ]wÓ ~ýú™àŸMÒ­[7ë­ìFzTro÷n1Ã×¥ÚÝs˜2‘íÛÓ]wî ݶ`ÿçÌHo6T°½ô™¤ææºHùòÏÛ„e €€+þkÆÇ¼ÌDWæ7o"^7ÏÙgŸ-=ôÍR´NÿÐû”g͘§ÃLú=ÝFûÉSt Ï€¢C3úFóFG³i¶£d)­ÿ÷E‡ Vt(µ%K–È…^h®‚mÃ2@@@²*à1CÌ17ú÷ï/¿ÿþ{Vwg{@@ n&çr* YX48âÇÓ³Ðh°Ñ±cÕª#LiÐJNŠfÒ@›&M2Ö¢I -JÌ0 =sNŸ>"ÍšeÜ6p‰¶M‡jÓsÐ!¥´D;àè»ïDFŽ©[WLÖ„ôcdõß&-ÙÕ±cc3„×Òµkš :ÒàßòÐCšÌ › ÍðY'äÜsÙ!¸&MjfŽýµJæ~›áA³6hdÒ'ýóŸÿô­ÂoZƒ|ÔH‡/Ó 9z_U‡\‹FÑ€¤±cÓÒ³VéÐyz4*E¥Ì}d;´^µj¡[pÛm·ÙL¿þú«tïÞÝ\cs‘£T4(+°˜CȾ}"·Þšžñjþüô!×|·Ó@9Í¥ÿ'5Ð++ÅŒ6dn¶ÿ•]ØHXO?ýÔ£VÐDÉ~lÆÉÔ¬<]»v•ûî»Ïô?cåœsαÁ¸ú·üe3èó&BÿŽë¶%;Ø„=Ëè5¬‘·SÏ{¾v.AŠfó;fÞà1œZ!€ € €I, ?º™f~ ©CqëUÒ¿Ì 8÷]»vÉÔ©SÍ÷Ó D¸£ûév4c®oÑà"ý!¬k¾~ýzÉ›7¯ùNØ|)LARTà dƒîCÿ&곎Z¢ß×Õ4ÙN371õù 3LG´2­çöñRô²rÚI.@ÀQ’_`N/w®¼2}ø13êˆ Ú1£–˜a¥ÄdÓIþëñÇEzõ©W/ûíÑQJ‚i: Ôˆ¼öšˆ9¦Á*úhÐ@D®½V¤téŒÇÖ!«^}5=;’7ØH·ªSGD‡ðÒÌ;‘zíÔSƒõ¥ÁP½{‹¢DÌÍÌôÌ>‘Ôé»Íf|3½ º[Óݘ’–¶Ô¼ÉxAÚµÛf²&•5CŒ°7ûöíkŽa/皬EM°Qú83rŒÍŒóöÛçÈòå³dãÆŸÍ°l¥\¹rvX[i&ÿèù=ùd&esuà4š ê®»Òƾú*›•æp7 ª2I‹Ì›¶ð•1c“Ýpà æõö¢Ü{ï½á7Îd­î®Cžéë¸lÙЛ„T6óшbn¤‹Ìû×ëJ‡¨Ó×› hÞf9à(ôQYƒ$Ž€~©CœµiÓF4Xè3Ödà—:Ì¥ªC¢iQ“ÿ½‰ÐLG:dšfùëmþ`Þ~ûíöKÓ¯L‡SäáÓý´LÅ¢_TèssMÇ¢ÙŒŠ)âǠéi¹XS R@@@’^`ÿþýö3ôSæ ø£GÚóÕÏν̗ýך/Ýëèéÿ+š¥H³ ë÷ΚX°¢Ÿ3gÏžm·Ð`"ý¡‹fÍmÑ¢…ùñ"ó]þ9pà€èw¬šqX“ž×_QRH"É“'Û¿Eó”^yå•\û~æÃ?4÷Ù̶ÿ•çž{ÎŽ¢á×çÀmÆŒcÿFønÃtxýQ»Ž ¡Ášú÷4\Ñ‘L† "×]w¹?X0ܦ!×Åúxúýá?üõãvM‚àý~6d£r¸Bû)MÞ Òæ¦ð©æÆ¦ö=b-@ÀQ¬…©?éV¬H62÷ûÄŒDbnøùŸ²I&`>@ˆz*=‘ÿÚèÍi"=†>´Mx¤ƒ‹èPT&¡ ÂI$òU‡¦ªZ5cö%s/R>ÿÜ»UæÏæ3’ ´Z¼ø¯m5ŽÄ¢£µèðgrî¹­dJ;|½‘úî»ïša®ÊËÛo¿mß<è±Y³^5ÁC½L§ù Ü|óYµj•ÍHP³æ;fÙI3ìYz°‘GÏQ]4ç­·Ädâ©)>ú¨Ó½vê§Y¨ÌgÀ¸–#GÄ u“žÝèŸEãÒž|YèthÍU»víl·UÒt¸@Íjd>_gZ4ëÔž=é×ÔÜs—^Hߥzu‘J•Òéš7Ï´6@\% ¶5¸S†ôC£~i9kÖ,ûë º½ÑŒ©ÁB`¤ÁF…ÍU jܸq†óÔÀí;õï·0U®\Y4#R•H£3Ô˜ 4ˆëý÷ß·_ü¶ÓñE}Šé—ÀúëT  € € €@ò œ0_Vê,ï¿ÿ~ÑlEú¹Zo„/_¾Üü€÷Uó=òÃöq®ùÂ[ÌsèÐ!™4i’ÍÆ¡?ºè¢‹D?§ëgó5fhÏÍ—íšíHŸÇoª×ÀübX?—÷4éõõ3ü×úE:$ÐL^Û¶m‹êYy£ZiˆÊŽ˜›6¾í?|øp†-·Ñ¿ ”È48óIóký¾S³ ER4óÑ-憧þ:t¨ý;øcÌPõäÖñvîÜé÷º9®¿’AÑû¨Ú/½i†²Ñ>Ê·h0–fƒÒŒöÿg†¹*Z÷ø„iŒ@n)ÿ?{çîDµ}ñ­b Ø6,ˆ°¡ >  ¨(>, Ø¬X°‹ *b°€Ø±#`¡Y°‹"ðG*ŠŸÿý;aÂdî$™äfr“›½¿/7SΜsf%73sÎÚk^†€!†Àܹ" &Œ‚d#ÊC²¹þz¿*Z¨CŠÊ°Š ¬4fLBí%#^[m%‚›ŠF$èÏš%ÊpÍ¿k¯×M%ñ,­ãÿKX…y÷Í›‹2Ø—î²4BÙR§©‡Ü÷Ê*éÒ¥‹“•e’h¯²6sæÌ—–-¿U¦n?Uxj§[Ç»›ŠAƒ:¨ºÍ²iÊš ¢} k7®©u–üúaƒÇv°¨i²ýÕ¤µxK(÷D!ÞøÏ±¦–QϨÙˆ~ëܸè}‘#}…ý…ÿW¨÷ì¹t/6‚ƽÏwé[2 C ¼`à‚¬G”9»Ë.»èµüIa€ƒÌÉ»”±yž²‹/VI¿p¯Ñ£G»¹Ö!C†¸DÖÐl£!'K¦Üó<Ú3 •N9è Ì¤Xò T_öÞ[t"PTµ ÷°xÓä÷ÒD ”yá‘6ZZWuÈFÔ¢DbÔL¨8yµBÜ¡=½ÖÉôé¢Ä!©BòÊzïÜ,ÀJæ ¥TÖ]w]'?{ðÁ{Å’ï5Ь¤–_þy<øUéÚUYCa Šw°)Ã^M«O’T ÷üýwB)Yy .@^ãó®´Ø&wE™Ö¹y‘-Â=enXiCÀ0bD€ÁÉsÏ=W¶Þzk§P„ÕYðáøÛo¿uRÍ H®~— jBö$èìß¿¿SDvÙvºjȹ[$€ U¯^=7xìÇÒÿ”Q½77f†€!`†€!`†€!`e‰cΗ«¼ü´iÓBûÏ~«®ºª\vÙeÒ§OŸ*vÛž‚*F·¨å ALŠ“$‹y¶@i‚—…!P©@ ñ“òòÁ¡~ýúùVãÇ@ ™‹ŠÁ’ø›É© ÜM‚d£]wÝU f¡·žÚYð›‹êÜ,U?˜1c†ó„4ÃoµŒ•ò»Š5e¦(v{™úRÝ}7êä&d«\âÁtcžŒ7kÖ,—C­¬!#e„ÇvѨ.i']+¨am¶ß~éJD߾喢R­ÑËG-¹ï¾ Uߵݪsuêk›¾äcÉ`Ä‹›n¼èÚµ«’ˆgdÚâà… ×‰'® Ê ²‘w|Ø;×^½‘K/õϬµVK¨PÙ\kb¢R–":Ïíp /Q¸­öK«É0JüȨáAlJ®‰Ø£1èÒ]/RÇsŒ{ðã iöìÙNÅyá D0š‘x}®Ò}ddb‘f‘;øšc7ǃ7 R`I`§FáÈÁ` CÀ0 CÀ0 CÀ(°''9çŠ+®p*$ðœ|òÉŽð€}vO¼¼å4[—Ik’a³Å*š‰‹M…!`DGr^dýèâ—ÜIm~øádíZµJ.{ Œ%ycGlÛ|óͽ]öžT‹Ž?þø”½wÞy§Î+VX$9— ^|P GyÎOÞ‚LʶtŠQÅn/åÄ ¼‚2Šzþ€œµ¯NØòýDÿ·ß~s–ž¸É¼òÊ+É¢¨Bxâ‰NÝ=8Æœ,d †@Žá(GÀ¬x¼¼ûn‚¤¢ÊnÒ¨Q¼mÕdí(ÿEHvPÂM‚£ŠxEŸ}ðJ(-Q{MÛ‡\eðíÑ£‡* ýí²>`³s“àew È°í¶Û¦mÏ¿CçVeŸ}DÖXÿ5|YUq¥_?QùÚñÅ#¶A>²Gà™gD&OUÏWŽ ?ʶ†€!`dBrQ¯^½„{;ù’B@•ð”})òá‡"sæ”T× Ú,½”­ƒÌÕª´¼þzÂMïUŠqôÚ,Ï>[ئa®ÿç?ÿ‘ 7ÜPÞ|óMDzýè£dŒÊ9¡Ú9*ÙÈëY²‘WV‰»ª†$rÍ5"ª,2#™K‰Ð¢„i CÀ0 j"ð³^xŽUTH¶<C0"˲Aƒî JF<ô¡pÄõ‘xV/ÆQ¸«ÙE;\`ЂÀF˜?¾œöÈGn£ý1 CÀ0 CÀ0 CÀ((tÏ̧žzª{FÞG&™$ýñÇójç¼óÎsêCst²%”ƒ©œ»‘ò‚Ó2 C  @òGP±Ç¿/lyÍ5׬¢òCaº(v{éúQÝíŸ}ö™Î×-°#A¥ötÊN´ÇxtÐ~íb&«- !`„£iÕTætÔ¾T³D4±¼äg-¤ \:«v΂’“ d µßt‘M](c%ÕØ©vÕjå":Á–½’ñãÇ»‡5&R3ÅÍ7ß,'¨\lÛ‰'Ê;ì H!3ÀK5ˆÓ·ÝV̖˳­ŽxéGKðÉ% Û¶X°J CÀ¨!lŸ7ož¼öÚk.cäR½øl½õÖNÁèßÿþ·#°`È03¨úÍ7߸Ѷm³Û††ÕcÛòC€ûl!<Ùa#98ì!`†€!`†€!`Ge£¾*GÏs3êø$êŒCò Öf‡rˆ N5Pq@½e}G pÉ>Q·r†€!`”"¸†@ž|ñÅåÉ'Ÿ”Ï?ÿ\<ÕšRìo¦>ù @õë×—|TÛQŽ÷ÇÿýßÿùWS–‹Ý^Jã\áé~jëÒ¸qcÿ¦Ðe,çPúó¬¾ýö[oÕÞ j!`„£jÁgUËTŽ:hi­:Ï&O=µt½”–|Pdút‘µÖÊ­WØjn±…ÈÈ‘¢–báǪu©<òH‚xÑY,¼¢jn=÷\ч±ô•ðŒwä‘S¤]»ƒ¥OŸ>ŽHÄÃÞ Á¸öÚk”!¶i6Þxã`‘¢­3¿«ó¸Êè-Z“eÛЖ[Š@tnÔ(žSÀ6PUŠR<-X­†€!`… ºŒ‘-õÇ“82Kvß}w§Þ×_½)ÉÊ6l˜S,Ê”uâõ˜:ÖÈEÆÏ;ÐÞ«…ÀrË-'»îº«L™2E-Z$Ø©F8ª¬v°!`†€!`†€!`TLŠ{ʽ™Nåßž={º±å^xAºvíêÔ€IÂ!g=öÐ9‚§éȯê©NÈJ_ë {—.]tü>ÇüLÛ>CÀ(9 #î¸ãŽÉ¿#QâÖ[oMÃñ_~ùeèaŒuÔÌlïÅïK0‚ež{î¹d‘!C†$Ûy„‰?_¤¢^ßqI慠 ŒŒB.ÙWíbè¤J’æ¨ã‚ .?ÿü3]Ž´éµÅ{¡qJÛpš¨¼{•&jð¹–j8¦4Ò ,^+­´RÚ*ŠÝ^ÚŽTsß/–YféÔ©“·šñ}å•WƬýñÞ{ïùWmÙÈ:yi1 TQÑÄõáL{6ß<†ó¬rñbQ 0‘æÍä¡\ªAa•:ЉÎg…Æí·‹ÞˆÔ„º¡Xº ÄpÒI'ɲH¥‰sÏ¡Ö/Û«EÙºJÞ¹Tnºé&Aªö†npï'ªxêb¢• ?Ìk¬cj28%uª±¨a~³‚,³ÿþû'‹@dò÷/¹CÞÿýä*ŠÛÁX¬“‘¸†ðÛ—NɈßYêçÅü¿¿o‚7NÁö²­#NQ‹€(‘ "U®á'àd:¶ØíeêKuöù‰qk¯½¶SŒZcÓþïâ¬Y³Ä”õ£¢gå2!žIé(ÛgŸ~™??sEjÛìˆ7úL’V (s ñìÅ ‹Ì[nɯ~%+'õØÑ£ÖUX˜A8‚|Õ¡Cj™¸×Èú8ûì³…2¼²±t ËBA¶±—JR}úéZ:q:Co &(9êtU¨š¡6e·9›4ü@aWqÄŽlcK’š&šսG–¿þÍ`Š~Œ•4 C àú A…‡ddl¹>óÌ3‚•èYg%Èû6W–²_¶¶ÏÃú´=÷ÜÓ­ Á?sæLS7Z -†€!`†€!`†@"ÀÄü¤I“²ž9â$³BôAuƒd&ÊI̹ú꫊¬WÉ´iÓœBª (md²Óa"~ûí·WW€GRêðêò¿Ó‡G}Ô)9`Ñfa†@¹"€jJo~²$“í¶ÛÎý®®€Â/Þ|óMiÑ¢…K óm.ÉÅ–-[¦ôëè£N!`¥ì,ÀJ±Û+@—C«ðŽ¢(èû+ÁbÔ, B `„£B huä…À¡‡ŠÚŒˆüüsúÃ[µµêÀQG®’ —Ôm£`1b„(1Gd›mDP~9åQu¡‚U©"lÑ~ÖäAõ‹ƒ04uêTws‚:‘'Å[š‰Ó;î¯u®­*›IÆ ]ýË/¿¼ jÄÄ*G°¯y$ëäå—_–5×\3R?¬Pé!ðÏ?"óæ®_Ôw×]¢´âë wV“!`ÔvÈðÀZ‹ì tß5¶id$]wÝujyEº¢¶½Œ€(½Új«É}÷ÝçzmvjeôáYW CÀ0 CÀ0 C  ŒÐëfÍš¹1^ÆyýVAþ†°?ðÀåšk®&vQQx饗œÚúë¯ïì~°s­™·$¹¢Â$: ;Û0(ž%PJúI³˜±OÊ&LÐñõoé)S9Ûg†@18í´Óäí·ßv¯ ê¿Þ¾ /¼0¥;üÖ^ýõÉm;í´“#~¢TôŽZÃðˆ ¶XíÚµK–ã·˜6K=sõ¿Û­tRU;Ä þ"[½€Qìö Øõ”ªø^xßOÍ/¥@š¾+A5(ˆk†@!¨SˆJ¬C W.% $ˆõêe>úòËE:dµ3u„œÌG”ç^Žô*#GŠ*‰|qσ øHm¼}ûörä‘GºÒÇkG.½t€#]«¬¯Ëõˆ´ÛnÃäµ×DöÜ3•AM¯±Q;ãŒ3œ ÒóÏ?/ûí·Ÿ©:÷ã,xkÍ,%“¦êñãE>ûLäœsD”§fa†@ì@¨åAu­µÖŠÔÖìÙ³•…‘ó…T™h=öHσý>ê I¦çСCÝu/¹ÓÊ:z3Æ@ºçg¿×^{•õùXç CÀ0 CÀ0 CÀÈž£{÷îíÆŒ±:;T3ˆ?†(ÄÄ÷E]䯒©÷•í'IõóÏ?wãÉ·¨5€§¼qê3>Œ 0cˇ~¸Û÷f$>õÔS‘,Òhƒ±ê¾}ûʽ÷ÞëÆ®ÙÞlpb?¬¬m3 ‰À³Ï¦wõ˜4i3Y¨cúõM†òðt\)¹êH¾ÿä“Ä6º‚.[™ÚH­)±VSm„õÅÛ!æï$½ß7Úh#YuÕU#–.b.yØGú¶7ÞØ¿)¹ Ù“ßI‹ÉgõÃŽk.«ª6I–<ꨣœ˜åQò²”è;ì0éÖ­›<ðÀtÙů¿þêTñPÆãsf<–s@‰å&Dòb·—o?³—/IèÜsÏu5¯~ÔÖXc oÕÞ j! ´ C ø輜‹­¶ÊÞöŠ+Š» Cík5n¸ªqMI6yÂC@µ/¹¿Ø Ë-'ÊBN¼ŠÝ6°'Ÿ|² _;xðàdó<8n²É;J2Y$³g¯•|€„iýÝw=á(“e6Ö1‡rH²>[(_ :&‚âbˆýoN'áðÒK‡›X—SG­°!`Ôþøã7€‰Zß§Ÿ~é¼¼ŒÍo¼Q>üðC¹çž{ÜÃ-C B®eÀRŒÃüÛ#5d…Jlò m¥7¬žšcÉvÖ:f†€!`†€!`†@xýõ×ÝD0ö+;vT¥ò»ÜD7Ïà Põû;¤C‡n"ªF<{ßvÛmN?Ø&‰±Ç2¢ ûÃt°‘çê¨ÁDý O?ý´|õÕW *ÿý·Œ3Æ=Ç¡ÊdaD¯ßx#]‹{»úõLd£ á¡å[oM9û쪄£Ìm$«N.ÔTÉ„, rÆ+Ÿ`¼.—ß|Ú(•cP‰ó[É ÙÈÛç½Cå·Õ‹éÓ§—4áh™e–qvq t²2U0 ñy{c´Ì_2gI‚ $’Wd9b»½ˆÝ*J1þ߆ ’ÒJý†@¡0ÂQ¡´zrBÀ#m°A´ÃÔÕB½ŸE'ø6LêÚU­øå,ÑÔ)Ã(ü•A¬V‚uZ"ÒwŠJÈŠ^ÔüG•÷2ögü±›@m`“4l¸¬üöÛ*J.ú@³PúÉ¿ÿýoéÑ£‡zÄŠðù)¡Ü¢€ áHU«¥¾¥ÎC:!*ó):ø b±ðå±S4J+¯¼Ò‘†è ұ͛7ÏÚ+fQ¹AÆ·žÊ1žwÞyrÙe—9rò¾<Ðò Ê@&ꀵGÖz†€!`†€!`†€!`Tvxöå9šçÞÛo¿]N8á„ä©o Â$¬^pÁ‚>j¿$§®»îºnR8hY“së{.¨j¥,»¬ÈÃçO8"»ƒïŒZ ËÕW‹NÞçÒ+k†@~ ëÎC(ƒšß}÷<ùä“Y¸QþCvbd#¢±Žò W9ßó•}©Ê´ñ€{ÿý÷»lšüzfG•:|þwß}·³ (õ¾Zÿ CÀ0 CÀ0 CÀÈ&¥gÍšå&µQfre#ž£±®Á>m‹-¶­‚Ñ Aƒ\rΨQ£œÊ½gz@6¨L T>°U Ë6;µmÕä…óFébîܹ‚’‹Šte \A29ƒdj#cžÅhÃל-æ€g•öÎ;︣¿þúkéÕ«—#.‡]Jš@I®Üù3Ï<Ó‡°†# ôùçŸÏªREá£>ê^X}Þ§ò`Œÿf‹b·—­?qí'é¶gÏžÎ^ÏßD4¿ÓŸ-ù"`„£|‘³ãª…@® G4¶æš 6öŒÕjÚŒ÷­Z>‹ZVV ¶£p¤óK*Ë—´„x´óÎ"?.²h‘( ½Êae»á er!Mˆœ^˜ü ws Á•bêTMvqÄ«Äû[ÛÐçxõÍJòÎ9'·3Öñ 9öØ„âc‰²§s;ÞJ†€!dq¯Þ¼#¹ÎÃ'„#äÛ3Åk¯½¦äÚ…NÕ/Xns•HdÐÕ¢2@áÊÂ0 CÀ0 CÀ0 Ú‚¶gب`þ*EŽ¢‘?V_}u9Gþ°N[a…ü»B—4hPT5!ú„¥9cÙØ a3äÅâÅ‹RÆ6šA›Ž(啵wCÀ¨9PBCa%ŸÀö¾RË0pÄ9ß©ö+(e]×®]…ߺÚ¨a›É‹€¤Çí¤I“Ôªð §Z¼fyç%öž/©EõD‰b·¥O…(ó£Np÷ïß_n¹åáºè#Ž8Â%W®²Ê*þͶlT:Õ®!MLìÀއ Äþº›l²I¨¯nš*ls-F Âp`ƒVÂ,ðtLp¬ÂT Ö‘‘ô7YFŒQR­³B™…k•^·Ê"¸˜xJMš4©Òg˜ÂÈ~øá²ï¾ûVÙÏïž‘z}w‘C¯œ½×.TAYÔöW%“E°9Dõ(jÔ¯/²þú ÒÞ¶ÛF=Êʆ€!P=n¾ùf™2eŠôíÛWvÙeG8ÂËü«¯¾ÊxOêyƒc#ja†€!`†€!?Ÿ¨¿=÷`Çj¦Š§0«Ö‚!`•…ÊXÏ fô¯ýK>ø`Ùl³Íœò=ê÷¼6lXò `«á•#?áè•W^qÊÆ§Ÿ~zÉŸƒuШd¶ÜrË«ÆJÆ"Ó¹cƒõꫯ¦(ÔÌSû˜¸óî{¨EK;U É’ßõÚo¼±&Áå^œ×/jAóòË/;Ò‰¥Œïú5úÞ½{;b–{Ôåb·µ_QËAƺãŽ;\¢-*ÿþ€ Ùøè£öo¶eC `¨ANúЫÕÔ>¢mÓ¦M»êëðô%—îÁ#—€í·ß^}FTÒÆ¹ŽOv0Š;w–Ñ£G§x.=Ú–*G¨þåúüáˆßÉï¿)üqUÏY‡)GžzJ”I›PùAí¥‚‡+X½úÿ«2œ[9oíÉ“';¥²YNU8|NñFM(ò9ù GXc‘à¢ÿæ„Àª«ŠÔD¿3 •¯ vºUPÑû]Ññc1²Qhlƒ!`Ä„™šýúõsVhX :tp÷ OqQÏLvñ †„¼…!`†€!`†@|(uå•WÊvšý…•B³fÍä‰'žˆ¯A«Ù0 G zCºnCºÙZåüO<ñDAá1ß`0A}¤Jö“pú_˜Çvû4æi®ºê*aîf·Ýv+ ²ç¶£fBr½ ¡Kt/ÌNÍCÂÞ C 6 €âDÑ}öÙ'ôt¾U…,Å Ù4jÔÈÍ^vÙeŽxz@™o¬[·®#Ê6LæÌ™ãÈ5„üq×]wÉÛo¿íß”÷r±ÛË»£z öið2ø.øÉFXó±m†*yÙ¨:Û±Ù%)Éh7e³?³Æk|W§N—ô ù€¾ÎÈVÙÝêAÅ-R–¿ÿþ{hq¾ôLþàø}1X#¡½°5„#µyv¤£\ú¢ .ôy¨h¡dkyäQéBQ)YQÔ¢5]­†ø¼õÖ[e÷Ýwwv2ü¿]}õÕªìÔJ•fÖWuš½eæÌ™rÉ%—Èl±-T*?úHt’6ñRÎ’#­¸bÆÃlg-D@âJ_!cî¬ú©êÉGPa®zm1 C ON8ágÊC¨'‹br¹¨ÿ¥ ²cÞ{ï=Ùo¿ýœJgºr¶Ý0 ÿLÈ@IDAT CÀ0 C ùóç»ñ,þa !M0~Ȥñ…^襳øí·ßÜDÂa‡V%k9M5¶Ù0 Zƒ„!’CûôéJòŸ(${÷èÑC>ÿüsUìêlhÖÖìQÔìxàa2úÆotöb?ü°rÈ!:Æû‘;.ªåŒ¿ÍRZFåˆIÕgžyÆu ëc=&Í›7wªM¥ÔWë‹!`”&Üw–z@:zᅜҿ{üƧ ~ߙƒmf¡¢qÂ^óøã—qãÆÉšk®™rªÓ¦MKY/ÄJ±ÛË¥ÏX§¡ìÏx¶?P¾‚|Å<±ò=ü»lÙ(8AÂÑrJ4ºm¹å–›¨6hè+2àõØAÆ-Ó@‚¿÷ÈÀtÒI) tÿ~[®Ý@8ÊÂq  W/Ñ%ÑÏÐÝY7ªZ¬|ýuÖb¡ôYEÁD/Ö¡»KjãÔ©SÝÿ¬f´Ñ#“u#þW‘ZÄót[•›9㌬\BÍ’A®ÏT‘ŸQ‹]}€-©S¶Îq¶jÜ·©HV•@0K¿zòñÇUvÙCÀ0 ‚Ù;ÜG2‰÷ß¿<ÿüó.K³mÛ¶É"<¤#5Œünº‡e³SKÂe †€!`†€!`äŒÊÜo1ö@gu–ð*[´h‘›ìf`œ‰ì" ?ï¼óÜ:åÜï¡^ÁxFÔ±F¯~{7 C øB¥Ä»wïîˆFƒ r“‡üF†ÅÂ… ¥S§Nríµ×JëÖ­…_Ô X‡p3F%Ê© å^Ô㘠Æ~†íA5ˆ°úËa[·nÝåžžó,Xà6Ê¡ÿÖGCÀ¨y~øá‡šïDÄ B7|øpùæ›oÜÜÞW\á¬ÔV^yå*5 ‚è‡GȬR Ç qà„²^×®]Ý+Êeº.7iÒĉœø÷¿ùæ›þU·\ìöªt † ?ëd-Db¬Rýꆛ«UÐØ±c:÷†@1¨ãoDÉFw(Éèÿ¶(ËHº1.øÁ SíëœcõöÍÍ7‹œvšˆÊù•BpÃ\ÖZâÿ¦ÿÛîA•=äÊyˆ­W¯ž¨ŠYÖnC8"°US§DU†H¬ÛßÊE@•9…û6û•–-EŽ=6…Þ'ê¯ö‡ü¯g è÷ÔÂ0 \ ã)x²o»í6ý½Ù\Ž;î8' ÛP=@Éàd@•åV©[5"¹íرc•ýޏ†"5oa†€!`†€! NÉ»ž³ÈÏž=[ {cqÀ$ȯ¿þªŠÑ¸±?Æÿþõ¯¹Aq&?°òÙyçÛêöb]•Ãæ,p!˜÷Ò̳#F¸û?Mt÷iÞ;“ë—, CÀ(w°;âˆ#œ#㹨`‹³Ã;Èu×]ç&½sdL·}ûöÎ>RÄL~Ÿ!}öÙîÅs1¿£L8ò‹Rؤ´Wg9¾£àÍ×”Ž<;5H«†€!`DA ]x³ÄÅ„nBM&L˜àæ¹gþå ì9O>ùdÏÓ ½jF8‘(ŠÊ<Á%׺|•÷°óNKÁ(v{ÁöãX‡Dõøã'«?®¸@‘ÉÂ(&É™ÞÍ6Ûìè d£?5›hFXÇøÑ‚q ˜òÈx¢d4}út˜~Ó•Ûpà SŠâ³ #ߢrP>ŒNæ§pT”TàGtQDD B6¢3×_Ÿ=ÒÁRNy¨úòË/åÎ;ï”í¶Û.m·6Úh#Å!ëÊûƒpdQCüøcÂÇ®sçx;Àä<ß‹!C2¶OhäH<ÓSU¿Tõ^'ýõ ÎP7ºáâþýgð9ï[†îÙ.CÀ(MPðã:‡ ,§dËóÐ y{L2<p%«ñf%×a*30K0ø îk!"1¨›I¢8xœ­†€!`†€!P€àM-¶gLX{Jaçú©JJ£l„Ê$"&@®ºê*gåΘ ßÖ>¨ ]¯ã)(/ûÉFþz¹gCÙƒ‰’‰'JïÞ½ùë×±” ~2{- CÀ(wPx›4i’û­$1梋.rо¨EÀ©*/΄1v•S¦LqdMI$”Þwß}¡dPÔíÕìÀÑ£GKÿþýkÙÈû¼¹0Lº¶hÑB4©ÞÛm!P¡0¾%”p¢WJe œ’4IR&×þ^p_5]Ô$Nd½à™ããjØe¬·Þz^Uî}•UVIYg¥ØíUé@7 <Ø©zÕrÝ癉g0#y¨Ø{1ðGË(¡è܆ÇéN[õ®§™GdžìwD¢Y³f¥ìb°€›Ù6mÚ$ÿ‰ëªú 7ÆlÇæÉ ì,žxâ oÕÞ+¬"™ãS1‚¢êªÜg¬]͜Б2QlQÝ¿¢žKºÆPt€äÇûQG•®XÎÛ=∎r†®pèĺ¨*œŒ%:êZ¸zƒ5=ôPÂ7OoXT·>¸7ek\lÕÔ 6ðˆø_[uÕ䦪 Ô«7?:£/jL_u¡¶(i@GTDï¸ U£Õc5ˆYðÜKb©üþûïïŒ ÙŽÒßF|©¹§$c…ÚtY›l²‰›Ø¢Ž =„&d‚ÿýï×à™ZÓ†€!`†€!`Ô<dGsï5lØ0ÙI%ª¿Vzî¿Ó,Ô5üñ@6¢ÌHÍLäÈÜØü |4M"™PèÓ§ T”)K¢É0(y •ž žCg²=j"U¦vlŸ!`5‰Ï±$tc—ÃԓÈÝ£G¤Ró--™cÁº²Òãàƒv þªHFêw¢f¥nço”(«æ¸wÌÜz ;ÙÊÖÄ~ˆõØ óâz%˜{? 7_øÕ~J '¬—ý€B¾Á˜±?‚$ö»= ½ÌùzÉÔ½ªNÆ¡ö×+ C †X–v›6mÚ^Õšùû 0ivRÛÏ?ÿ|ÜÌ™3ÿðïó/7οê–ù¢§{à'Óü¦›nJ9•#‹ÊA€ùÿƒUßÉïœU¡[-ü"Ø5ª¿ûnQ{•„%X`W~«W_-ªO(rù墣d©ud!j¤޶ö­Ê"ŽÓÿŸ+”ýƒ,ÞK/½ääɽ£ño½å–[dï½÷vòƒÞöB¼«óšú{',Õ QŸÕ‘ø Ãð!tÀ7¶xå•+›4´%æÎM(yL¶XÑJ½k ä&äÍ, C l`òj¿ýö“Uí ™tÿƒ6YL|aµÆ$Ö­·Þ*÷ÜsOÆsÅV R²CýáeíáÈŠ-†€!`†@¥!¡›‰ï^xÁ© ¡DĤ ÷\ê€Ì–[néD¨J¼¥ò¶L€CÚfK LZªè¹jŒu@0çžâÓA:°´ë®»†*{äR·•5 C .t^ÅýfA†ùé§ŸB›áB »i ¶2þ`r˜ç[žƒQ€ Ük¯½æÔ}ýå*u›8’< ¡t‰G•Š·!P)4dâÏï¸%Pˆ)åÀf˜ûo^$Hr½ˆÁ¹y”ò¼(%œHlðÇÝ:ûþûïû7E^&AÁ<Ç£ØíÛ/ä:ª~þùg²J°#AĨIáHÉFçù;¡d£W•!w•[ºe2ŒüѼyó¬,º-TfÏ=÷L C ꢃ\¢2ÝQJ'ÊÀ7˜93aõxn‹^‰¿¤ÊëŒfÂâêÐCý{D lèà›|øaêöj¬ý¥¶Pßê`ÚÞ:ÑÚ]o0ððÆ£K&]‘Ö=ñÄ\âÃ?œ5K0Ÿ®à´¥ó³ªú :A›O vLµPyÕ¿Lø”é …`G pñÅ ÿlq„§Ð'áªP0åWZItä;Ž3±: C ¨’¦Ë†OW‡p€ÌVÆ1öÁDÿqØ…b·f¥æ/—ÎV ÂÇú MþãlÙ0 CÀ0 ÚŽ4Ü 1àÍ5×ÈСCÝ8öµ¨J¢&¹þúë˹çž+Œ¶mÛVP/òÉ'ÊdmÇÇÎÏ0 (ðê7/½ôRAiµŠ… &g²‚ d¤x@ü“ÂÉBK(Çdó'Ÿ|âlÂû+y[55½&MšT2vî†@Å"à·ÈòXø¦‹ñãÇËwÜ‘nw¬Û—]ÖMË'ÛÀ.3,‚,£B^@ZÝ|óͽÕ»56Ö$N$ð»íů¿þ*­ZµrÏÞ¶(ï¨ýñ|âÄÝ0òi±ÛóúÇ»_ľEØùÆÑ®ÕidB NãÆ7VÂQ+_¡_4Céh]ÿŸo[袅V Ê(gšòW‚ÔòUlñyPÿ‹·ÝÞ ÞõUD}V‹¨j]]˜PÂ#| s»Ì2©u"Dç4{ÅÙ_¥îÍkm¬àuÔÒ…ê=ú/ÈûPåŸÓ‡QìÓÈjáLFÇc=æ2]òjÄDBnLPqZ¼à‰píÖçd‹š@€›ÑNÕÅMmJ0èâèÙ¦jG¤_¨S¯iÓ¶â‘ñT4¶€,…ÒØWˆþSˆjÆÖ”UlÕC€lÎûï¿ß=ô’¹¾×^{¹“Z ÀvêÔI%ßÑç+ªØsäÛòÎ;שׁ‡ ÝĘ'Y¿`Ág|¨‰³Ù{äÛ®g†€!`†@!@ýe!½×Š+®è–ƒ“QÚEŠÿÈ#t*(m„YÓì«–ÕL¤c‘vµŽp߄Ҥ?±0J[VÆ0 ÚŠÀäÉ“]Ò dLˆšL¢’<Ú¯_?¹ñÆaó¤“N’sÎ9Ç=ƒ^xá…N )õs¶¨‚Ä®ÓO?ݬѫ c ÊA²áÖ[o-ØüX,¢Œ ů¬ùûï¿;Õ8¬}ÿþûoGªG=®˜r‘? àTìtžÞ¿Y¶ÒdííÔ&†¹sb *,¿üò:íØß½§Ö:¹7çÞ TAýÏ¥„çË5‘±`TS ®—<à¢Äxñf›mVEùrŒáNT• ° ª×C@jРÅR¢Øí¥4¾d…ó ³{ +ÜÖ­[7Ç¡À"E/ +_ýõÞjÎY7gØì€êè?Y í[ÕÆ+[~NHÙ*›ôzàFˆDQB‰N)ÅæÍ›—²n+µ\ÈQ \?#Ÿ0¼^QïÔÖÚñ~Z·Q²gõ©$L(§ ÷ X¹Háû¦?þšò,‘Óú“:ˆ·Ÿ2²ç*ÙhØ>Ún3½Éh¦„гÎ:K9ÿ¸ìn6Ô1§ºÓ3&¡àtÌ1¢Wõd±I“b1-Z$7å¿€-˜² ÇË¿+eud÷î¢#¢i¦ñŽDU³„ïÚôÉ 7"p—Âÿôj1è|#^“ {‚V›!`DE€-ÈF-ôÂÂ`,Rñž×´5ÕJR-ƒ± Î*x؆$ä,ÊId›bÂù٩ e«Ç0 CÀ0âD€{äÓÙô B4C“¡ÈlŽdÊv×çMÔŸxâ iÍ Jš€ÔtÑEÉqÇçÈIþ‰œ4‡ØfCÀ0*”%>ø`w®O?ý´›ðf¥k×®îY—Dš¾}û:¹ï¾ûNÚ´iã&+œ˜NÒ›DŽ©z«Ö0ÊæÊŽõ) ‡òc~Ûn»­#©|¨óõ‰ºuëºûYÈŸÅ ¬‰ý%1}Aµò‡—ÉØ%Jï-[¶t㕌Y¢”Ç}:Éš(qn«¸ç1b„ø§ö!6ÝÂÜN J '£wÝu—}ôÑ)½¼îºë„ œ'd²UW]Õ'Ÿë·8„+žQÒE±Û öwš|[jD[>òÜC–T„ UЉ*—6PH2ÂQ.ˆYÙt@8Ú$°ó“ÀzÚÕ·ß~;…&H&:?pQ"øþꫯ¢VÐ2k’›Ò ?r¾ -R›#{ÖZk­‚Õéõ%κ½6Šñ®×LU*Ñgª¼žÇWˆR¿á:‡Y8^Ë%—$ØNzq÷Œè¤"@O=%úĘP‰ñÌaù]ªáyçÉ zL]½ñXïQXS¨Ûè$­6¨Ä­eÔÁ-õ&%‡&‹ê…ÙYÆ©µŒŸp¤ 7rÄ¢úðÃ"oÕÉ]§Ô£7MšÂ#ªùМ ê͇#ÌІZÒÕŠP=U¹÷^QʾèÝV<§¥®nüw*AzCW°àx½õDG² VeJEa6jvS%†]Û*ñS/Ïs&…ŒlP½äášûÁWÔšÔ{A6Bqèæ,;(9ÂÑSz½>M•ã°S#ŒpTžß'ëuíFÀ®mµûóµ³3 Œùð|™'[ÜvÛmîþ…û'&®ÉÌF’×üá²»QˆüôÓOeûí·ÏVÛ?\“6ÔG™#8f—®HMù!`×¶üp³£ šB€ Ý‹/¾XP"y… àä8ð’N¡<ߥKYE“FÇŽëÊxýeî¡gÏž‚ý6>L£JÙ3XwŒ½劀]ãÊõ“+ï~£Éó$3žª‰Ô$é{A¢!/¼ùƒ9½bÇA:OÅ\ú—_~™leˆ4Qý­Tò¼s‚4Å+SpºWçÖYg*ÅJ 'H^8ãŒ3’jN^§y¶AY•W¦Xi¥•Ü3¦~E§°cŠÝ^Xª³m&‚†@ "á(EjH´fDí§²&Õ§fip£5°±€‘È)‘ÉO3j¹”#Œ Á6>Éù¶V ̨Ŝ|óÍ7®‰ø1‡1‰bÔž`â¬;ØV±Ö±N Q´‹­y%Èêw-A”ɹe ;1ÍÚSú¨è•MôIPBäŸ%ÑQí§Èc@‹›SV9ä„BÌÛo‹~¼¢¢j‘_7N”ž›P’Aé'0­Çªìãùzsô•fÁ¬G›ÄQG‰>áŠÒVETÊ<–P†´ŽrŠê¢'ì»–4²ë®"¼ª¨?ÊÊ–‘#Egœë…þ‹¯í!‰Ïð€Dï6 ÝBÍÔ‡­„#T¢ޝüFÒ–ªÈ‰'¦nö?þXd—] S_°¾S¸™ÖAžJ »¶UÚ'^¾çË}÷Gž(“e²²GéuŽAÆÊÚj‹È}U¡cŸ}öq×ì'Ÿ|ÒÝ"³¼Í6ÛˆMœi«Ï¨vm«~v´!`”ê3òÉ'Ÿì²—±Ö9QŸ¿ ÿƒÌf, P‰ÜtÓMõ ¬‚Áƒéÿ÷ÿy¡+Ó¦Msçɹ¢èà X”¸Öòg¢|“T‹Ñ^6e¦tXdÚŽø / C Ô€pô§¿SúÏ©ì‚ì±úê«·ÖϹ\U|,ñ9ÒbÊ1ã!RT#˜$ƒ5é—½ËTÝ8U³9ì°Ãœ’R¶É³8ëÎÔÇbíƒp´DØ*ö&Ÿð±¶±¥tÿç>}?:÷ön¿]4åDÔs%¡Äóã ©¤%íu%Ô„9Œ4.%‹úÜà/“ñðœv*QÏ‘®P¯€†JŠ7…¶…Ó›/çÛ§YG¢¶tµ.zõJ¨cᨿE±„NÆ;/ÂAƒŠ\Jœ¬vxrŸA‘ZQêNâ{:X0PÂÂO™ïÿã‹`-7Ý$ú!Ò»wØÞôÛ+…p§äÁÞ…&Ø¥oµ {ìÚVP8­²8å”Sô20E.¸à9$ìÿ=ƶƒU·oßÞeá_N˜Z![7j»¶Õ,þÖº!`äÀ`U¢e‚r3Éë®»n•Ê(æ„ß:2œ±elŒwÆ B3É’“¨hÕŒ ÂPMŒbâ$]¸1 ݉ÂQ”` ¨å+“vmË7;Ê(6Lr¢ñæ›oªH÷.2bĈ$‘hgͤeìKðgu|¥ŠŸþÙ’°I³0*»ÆUê'_šçÍý0¯š{L‡dUzxE Ê3ŽYè(5œ ø¶iÓÆ½ }®aõ»½°>Ø6C 6 €¥ZBbhÉÙ(«4¨ª’=³ÕãöðobPe.Á ˆÅÔÀËžì1²ëó ê€ié'a£Õºukµ›ÚÕ1+!¢0™F¦Ã/¿üâšš3gŽœþùΧ9ë2κó=ßBÇ$/µ!_G”à*÷)‡HÿÿÀ·+e±éuä z¥õp%g´]6AÔI)ab¯EPR >/ÎS" Šd¸ ØÅ@bß¾}•côH¢ üÜ”ìlØô;"jŸÖ_Š©\#ß›E((ù;²·×6WSÉ^•Åòí]²ˆÅU¦ ‹qÔ("ÙÈF ˆ¨J“óJóÈFÔ…›ž‹Se*$áH³0](OYV"Ç_x² ðQV´#g%ZŒï¯Çt4Y4Ý4?U|z¡L¥AWuGÊ‚×DQÍð^ ¾! •£8 G(rAâ:â' ÀPD] å"{àtÐÞÙÖ¯ŸÚg,±*Ô,`õeJÝ—icÀsÞ<÷}9Q“^ÌT¾÷Ùµ­?ëR(wªbßwÜá$ç/¿üòÐ2ÅÜȃ:Ò»X¢"e®…!`”vm+ÏÁza¹#p¶*ø^ýõîÀûô¹”ñCXîì«ÉGd!ŸªöÕXŽ0ŽpÏ=÷h^RÇdCÕ*Ù7é3D#2zÇ‚|Ä8D¶`›I‰¨„#¯\±Ææ²õ¿¶î·k[mýdí¼jwkâéi§¦¢ï¿ Ö.ØÙÔÑñÜ`0†ë)D÷Ùº!PiØ5®Ò>q;_CÀ0 C`)uTîs¦'ÏÌfU-Jè./-º¤&ûúwì äˆt$9o˰E‹y«±gQ¡¦ôâ‹/:™Ól>—ÉN¥Y€Lâ÷Ö$«Œ¢ Â“VÈ¿¡xã‘“^}õUåŒrÙkaÕÇYwX{åº Ç¤!CD'3Ž;S9¬‡2œviP/Ay(_‰pT†4£Å‹7ÞxCÅy†É^{í•´`éÔ©“û|ñöf»R¨êHÞAúξ+Õ’ï uà%ûVx}¨ê/¼£˜„ÍÌJad#_]i!‡,^,š.Yµˆæt´réö»îýgQʼn”hÖ,Ñlà ‚*ô¼ S\J2!¨@IG¤)Ôù`9ǹ@ŒÁZ²™ì$ôûá”|ø,‚õþ¾èhškÂò/X&ʺZˆÉW$T§vܱê€8@ÔŒžôXÑëªerÙ‚Ï!<'yí5Dvªp;tS"Žhh›mc0‘QkQU!|/P‰Ùn;‘ß~s›&Nœ(=zôHQ±J^úbJD<œ2ˆèĹsÕæŠ}·Þz«·Ù½ó½?Z 0ø{Uµ¦M›¦ì/ØŠ’–¡(¨þBk­%:â(Ò¿¢9ˆsæ$”etb¸J 2C rTˆàÿ’vjq$¬ì"fæÝ¾GˆŽFˆLŸž Ré ±²ó®2y ŠIª¸¡£Ά/¹Ý¿€â–~_õÆ¿5ú2ÿŒ³g',ȰŸKjèÈ<éÈTØÉa§¿µÃ#A† |î±6ã¼ÇO· (ñ?ëµ!¨ü @fã;- ;AºƒœÇgÅqMšd;ª$öÛµ­$>ëD Õ¯¿Œ° Áþƒ µ#Õn²-×Ö1JÌlî·ïLSW17£D€uI7U8³0 â#`×¶âcn-†@aÀrçàƒvIE‡~¸0¶³Ê*«¤4ÂýQ‹-Üxª×Œ%ÅŒ³qöÛ’±ŽLíá(:¹ï³k[î˜Ù†@1 cyXTòÛÌs*c¸¨Þ¢`1iÒ$êàiŠÙ'kË(ìW.Ÿ”õ³ºH€ cœØ{Ab%äT CÀ0 ¥,«vN¿(Bå@’QG}Þ¯ÓµÐÙçF­¡7ãg&Kë*>ºÝ¿)ã2ƒ/~¥!Ô^ð³/‡x z_´mÛÖ·–~‘¬~ŒÅ2(qÖhªÆVqCB‘ê\¸ ‘ G4I|þ¹HÇŽ UÔM”$'Ÿ,:"躄bÕ½÷Þ«¥mä /t~Ýþ¾ÎRµŸË.»L¶Øb §šåßÇ2„#²/Q•÷¼@*ý¹çždÓ»téâm.ì;*4ÜühvŽÎîV­[íýTî+áG‘<ôI嚪–e ßoˆH…"a§†Ò$š¸E&pŠM|QâŒË/ÕºO|FiÝ:ABÒÏ»Z¡¿“êq™ø®æ[ýS h÷]€ TƒˆlJP:#[n™(örÖ|j1ø@±(ሃÁ’ÿKÍ*sê[¹Ú †)';ÅùLž,òÍ7¢#Lé ]Áãjñzœ×Ÿ8ë®ÅIYžZïÞ½ÝuR-JGË™P{ðÁ=ö³¥¨"´Î:ë8{“zõê•%îÖiCÀG ÎëOœu‡Ÿm5 RE€ÉiîoãáYÿ!UÛ-‹O­(ŠÊ„#&OÖ_ýR…Úú¥Äyý‰³nûð RB:H÷e~‚çTže±ÚF¥×Â0j8¯CqÖ]3hY«Å@`øðá:}v‹µð ZtÔ¹EÆ- CÀ0–" Lœrþ>WIF•H´2ëúÞAšã”ˆÔMÕ¾d±öÚk×Õﱺ¿ibKâ/ìQãuU’èß¿Jq2˱ß(d`Ùqíµ×†V‰Bä|Og/ÙsÏ=½ÕŒï~…# 2…%—?â¬ÛßNM.ÃK€ßÒ°aõ{­šÚk‡¼UÅu< ø ÉèÕ+A8â»éhüx‘­·N*Ҩ◌7Î=dêÿ…\yå•n’37ÄI'äHHÈš‡ $®¬Va( ¡êÀ,Lè)S¦H¿~ý¤Y³f2xð`WO,<¡XÃÿÄž`@´2$¡ˆ!I¬ÚPºAEÈ»í–  K¥–8y‡úŸ;¼!­¶ZÞÕd=0*‰&kEY @\ÃŽ•!O± ÒÚÓO‹j.‹ê/ó£)š*•¥¢4»!·§2•¦XÆÍ®ÀzäÈÄ ¥"UñÞ-J¨~a¥–‰”±%;9_’ éÿGÚ€Ç*Wé‚2JÚ+Jðù”Yص-õºYf_­î.¤¢G•TÚ¹sg!³ßÂ0 ¨صͮmQ¿+VΨ)°KÿH훿фÆ“H,âc\Ÿ¨”óYjÍ8@)…G8‚LDÂT¦€”D2¡Ž f*fû""`×6»¶EüªX±!ðòË/Ëwäy4S|®cy$®®Épë*IІ€!v³k\nߘÚUúuK¹‡ CÀ0 ”ú!¢Š-sÕê:]¼ØÛ«d˜43•xô®ÞÕõMu}}w¤$¯„ l¢²1øÖ“5àgƒ2 ti¡2G ÖBM>„#ŽãáÅ T™Ö¢*B5©m‚ÄY·¿š^†k°îº nBuûáHŸ'Õ¢Ld½õRk{ç„sä¦*zŠ~–‚ $ ,°–d°<õÔSîû ©è?ª„¤îE]ääÑP[§6mÚ™0ÇsLF²Ù¡‡ªâ@mÝÍ7!={ötÙ‚?üpiõ*ý«Î†AƒD£L¤ÍØqöWj9èu§L¡ÙšŽH‚uD•|R!¯ê–²µ"Ð »&²×^™Kc§WÌ%%“é—Eä:~:}Áy¢ôƒª6c›l"úeñˆ°ˆÝäð®9K½uä;a÷F?yD”’Ÿ°lÕ*a+á÷;k×XCÔ ñùò@lËüßYä…€]Ûò‚ÍÊ&ÓPí;í´ÓÔyt»´µ|ýõ×Nb¸¡²‰ƒv¢i²†€!`,AÀ®möU0 RF…îs4™äÓO? í&ã<¨$Ÿþù¡ûkr£G8Šªp´5ÉXAÀ®mÑ*1"! ÉÒnà×_ÆuI #±ûËŸtÌíYUroL¦ª…!`䌀]ãr†Ì(S‘йq5ØHóµ·röÈíÛ·/Ó³±n†€!/ÉYß… ÐÏýÍéÍÊúÚYYË=õ½¾RÈF”…,”ŽtƒT!ÖS’öÞ{o¦?ÙˆãÏVµ0•ö•Zømàè›’´"wIÖ7Þ8YÞö"κ½6JáÂVh…þ0[µ -„ò< C ‚£viê–P¨YÒ!ÔÈèëСƒ{?õÔSÕ¶m†tïÞÝ©R1ШJ_Ê1 LBNU$ÿû«BÍœ9sœÏk¬xª¢$o¼!Ò­›¨¦cH|›T¹É);¡N ’¯¬§°“ÉVí†DÎ%(¯j5—^z©Sqˆ2¡ ëùdU‚xä©yuô]BU»=A´Lñ'[p~!ß¡‡©:—c‰A8BA)W\!*•ØŠr¶néÈ>ÁcƒëXm©š“Á ÅN û8ýŽËÍ7‹ôí›°÷>\ÔëN4m5¡z>J6sž}C‡ŠÊ“Um5ÏJ­ê^‘¦MEýôÂödßæa¨Ä·‚Æ¿þ%rã"—\"Ê"…Á¬á«J”™øÎ”Q@þ|…~/‰ÿé÷0HŽõöÕÆ÷8¯?qÖëgÁçL&£wmãx,aÍ6"I&Ö†êïöà†4=Šýû÷Çz7yнJÜ%‹´›’]ɵ0 ÒB€É”T‰éÓ§»ÉñÒêa<½‰óúgݹ¢Ñ—ÿÚÆóõŠq*ŠæÚI+o”¨o3i@¦rS}fkÒ¤‰S£öºù_Í’Â1ˆ V“HǸ@¹…§p”päí÷Ê—úybaGbÁ2÷ª•q^â¬;×Ïæ?þpÏãþk â«UGý9×NXùEà0kc‚÷É'ŸtIœ™:ƒƒe=[K&‡QéÝe—]tØïf9î¸ãÜáŒH¢á¹–dR C ÔÀ BAⲊ”ZcíOœ×¡8ëΔï4YwöìÙÉç7æ˜v#AÛÂ0 ZˆÀ*þ@"=¹çU OÕNIHŽ@ãË/¿Äïë$µQ«“IÃtYe:Bã/=WU^T&DÒŽB\²Õ£R”œÎÔçà F®„#\äµÁÍÎ&Ø-iÄY·×^Ôw&eÉÔ{… ¨ A8ÒßtT(…#pTEÙé\͆Ù2IQ$ cUUfÑ¢EÒ©S§ÐdÊà žK Á&l±,®‘#ÕCàkÖ¬ðMa»¦“îT¨dÜrK‚l„bNJ»~ôé#‚âQ®Ùˆ:ðÜC©( (BR"—œpB8© +¹M7ÙrËàÑK×é?6cŠ:v™6-A@›4Îw¬ÆÔÒ³4‹ÕY£-­%¾%\Smç„2R\ƒÚؾA!c÷ÝŠIwP~*£à!Þû½£ÛŽ/^\FgP½®Æyý‰³î\ÏšÏ9øY£@g„£p$ உ(úµPËDÈDL¶A^À"‰z&äÎ8ã Y_‰œƒ!mZ†@É!À„¬GªÅþrJ%Dœ×Ÿ8ëÎõ³áóäùų—’Àp”+’V¾R@ ƒçý×_=yÊ©5ùΑÖS¥ÚÇ5ùƒÿ­ýöÛOó)®Wa༆¼’õ×äÂ*«¬â’©ûˆz؈ÊRžDâuüüó½¥¥ï*SìH;0¿TÍLPðâCFAÒäŸ\U$~zHôÎ[„˜À¦K•¥T¿^tÔ)± %#Ôƒ‚ƒ¿;ì Â+[{¬è̹ȋ/&ÈI:±®¾y©5T†Poêß_T“y©ŠS¶ºóÙ}šª8K<úÄ€i¹)…Ô­›À?CÈcùª\åƒ_5,áÿ½cRAÕþªYkùçõ'κsE˜Ïy½ù?ë\먔òžºÑú{Š ñꫯºìБJpe—ŒãÞ½{ëåöGul!õ!2Z†@É!@†8/âiµŽ}æ™gJ®qt(ÎëOœu犪¬kª°]ÛrEÎÊW*LLC6êÙ³§›Üѱ/už©ŽÓŸ¹ÌKþ¿Q*†hTNjÜ™>OHDsçÎÍTÄM|Q \G$ÄyIqôùóŽ|•…3¢Rz;ã¼þÄYw®HÖÕ±žÇíÚ–+rµ£<Êò(í{Jóü¯£`Ĥ¼?P¥î®ãx$ŒQv¥•VJîFÝèwÞ,Ô°XãÅý„RÆi- RD`ï½÷^j¨KWRÄyгî\?#zp¿G¨iZ†€!PÛàžŒÁs7êÁµ:™NM=égé~^*ï‘{0XѦMg=Æ  lÝÆç^Q‰¼9ÉUሇfø¥1ã¬ÛßfM.špŸתÂ+œPÀñY¾d;o$›™€!kŠI鲊å—õ³A¢LòQ1B3ÎaGeèigu­¢¤:…4+4§èÚUäÁEg¯EPJ‚íí‰öA‰ÔŒ°EÃWõ¦GMEe0&:Zî¼3ZéJ¡Æ±ë®üc§+‘ØÎ— P7ÊFx5_r‰ÈóÏ‹ú&εAƒ8ZŒ·Î%™8êÝo;V{AˆóúgÝÁ*K"à©¡Dé©%wêÂyççn™°bë†|,4ýÚ²!`1 çõ'κc€Âª4j5_|ñ…œrÊ)‚ÅV¦˜?¾tëÖÍM^?¤Šºad#Žg‚:ø?ž©Þr؉²V¸é³TÛÈÿlŸ®°m¯1‚ßM“¬±ÂŽ OÝè‚ .p-´oßÞDɈçÙÔ³˜š}=岇ó‚`ô ë¶}÷©W¯\z_µŸ¸È6ÂQUlJxKœ×Ÿ8ë.aH˺kdþã§| $È4Á`ïǪ&È@o½rþÍJs~¶Ù0Ê8¯?qÖ]þÈÛÅCàçŸv¶ZØ.¡nUNXü£ÙIØî0áŠZ5jÏ>‹©gÂVm…¢Y~å çÄ¥žTh`U‡'«imj°¦ ÇRKØZ !çõ'κk®ZÝ,êFLÄ¥S7òŸüÊ^o½õü›lÙ0 ’A ÎëOœu— €ÖC Ä@±çMTyÿý÷åøã”^°Ý9ûì³…ç{`¥ó‚&x ÀÍ1•Q G^¹JçœÎ7ÎëOœu—ÆÖ×ì@âŒ#‚êFþ6.¿ür9æ˜cTPýgíýé§ŸÊUW]¥Â誌naµ8¯CqÖ]+À·“0 CÀ0 €@6VÆ2:è°É¦›nz¾NÛl³ÍQ[´Í´Ýå ÐvÙUQÝ›d¼ýQHÂQ¦ºýmÖä2„£ÕW•1©êÍ=Aöt•ï™x‹Ô4ßÿ½˜ºQ$¸¢REÕ6ùòK‘Ï>‹~ÙIêÏî¬Ô¢e%K½öÑlcyûí¥=b@ê7Û—nµ¥AÀ®m%òA”@7¢¨•@7­ †€!`dEÀ®mY!²†@I"€ÕùBl§³Ä©§ž*Ï=÷œ#Ý¡‰.ï¼óŽ´nÝZ®W…ܽտyž&#“&MrÊ[mµ•ÜtÓMYj­»±À%æÎz‚ýõ—@:7ÂQ(<%µÑ®m%õqTdgHN©[·®¼üòË=ÿW_}UÆç¬/›4iZ7mÿ[Ç ±ÒÜS}Ï8ãŒÐr¶Ñ0ʻƕççf½6 CÀ0<B G4”`ôŒŒ~YqÅg©‡êSúbtfŒJ•ÎÐ}¿êkÔ'Ÿ|²ªWQ%¼o|”É%¼A/ŽAòÕoCgݹô1βÇ‹>@°µs‘iÓ–V¨ê–ÝKê,÷ì¶ÛÒÍÙ–ÆŒãŠzè¡ÙŠÚþ\¸â ˜fÛl“ë‘V¾\€pDømÕæÌùí7ÑT4·Ëþ”q^⬻´P,ÿÞä¢nTþgkg`µ8¯?qÖ]Û?;?C Wè³ã¾j1½>;¾ôÒKi‹Þ Š¸·Ýv›´k×Nn½õVWåÅ &È™gž)L\o¯öÛ©Íw—.]œíÎÃ?\±va‘(¥ÚõyÅ(¯\ZàmG#çõ'κk8ë@Ax÷Ýwå´ÓN“_ýU?ýè£"Õ !ô²Ë.“~ø!myÔ–[n9GMWˆqôQ£F eGŒ!:O‘®¨m7 2D ÎëPœu—!ÔÖeCÀ0 C ªŽ”dÔKå¨ß×÷´ÅPB‘î[Q_‡©"L‡o¼Q~ÿý÷X:Wj•âiï·ý þ!ËØ©ù JÛm·]ÊÃQœu‡t§F6m¸¡èÀ_šF1EE­»nê:U.»`‘ü3Ü^²ýËDVQúßÿþ'+Qi‹-¶0)Þ}4VM…#Ъ•ÈŠ+¦² ?ü0ŠŽJòËçõ'κKÌ2î”§nÔ¿ÿ2> ëº!` â¼þÄY·}~†@¥"@ÐÅ_,M›6•ï¾ûNöQ;æ^½z©pª*§ú+ô¾}ûJ³fÍdôèÑ.‘ËÛÍdô AƒÜvƨP0†d3xð`gÁã•«´w&ÙVQëët„#o»§„Tiø”ÓùÆyý‰³îrÂØúŽ$#,)±S8p æ“ý&x ÕöƒG£(Ñ%—\â~· Æë¯¿î“ºuë&éÔ¼cVSÉ|®L- C v!çu(κk×§`gc†€!`ä@ áHÉFƒ´ª¡úŠdz¥YPË‘YvÁä߃2:Rñÿ žÑžø`YuÕUå•W^qViê¸c¯X\¢R÷àƒÊo¼á,4!“ò»ma•‹@œ×¡8ë®ÜOÌÎÜ0 CÀHE I8ÒÍCÔ&m9ÿn}`˜ª¯ U™§­*ù¬ý×_AJꪯKÃWe¼ßk{½áaÆùWC—™ØãaË Ç6Ùdo5ùgÝÉFjh«îO>ùã<: Y0A몼Î:Òñ–}傽'Ë+[ŸªY1"»íVµXº-=ö˜¬Ü¾`^oéZ²í†@#áOÅ4YÈŒLÉœzœ×Ÿ8ë.Ë #(2òY¬·ÞzR¿~}iݺµwÜqrýõ× ƒ¿‡~¸›Ð+ƒS±.†€! 8¯?qÖéä¬!P øC˜þâ‹/äÎ;ï”–-[¦œêDÜ£ ¾8bħL̤w°\ÊA¶Šd",°« †Ž‚ˆ”özœ×Ÿ8ë.mT+³wXOÞxã2sæÌ´ ìÒI'9 ³áǧ”»âŠ+¤sçÎn¼Ûï|pÏ=÷H—.]d¯8q¢´hÑ·îºë IŸ<òˆS=‚d„êF^xaJݶb•‰@œ×¡8ë®ÌOËÎÚ0 CÀHEÀŽÔ#yoݤi¼¢£=?ûì³+?ÿüóqJ&Z0{öì÷t}¤¾SuŸ³ô˜d YO=õTjíµpm‹-¶Hɺxÿý÷eäÈ‘iÏtáÂ…ê.ÔÛ îx…x ‹8ëk¯˜Ûøjl¹¥ÈsÏåÑê¸q"(DÍ›zpÇNËÉ•/·”¿^KdEêÕ -Veã[o½å$€Mݨ 4¶Á(dºÁ64;µÂaCMq^â¬;(jm•(i÷É'ŸtÖ°=zô¸u½§sö° üZ†€!P›ˆóúgݵé3°s©\4IMn»í67ýóÏ?‡ѳgOAã¼óÎŒÂbƒ 6§Ÿ~Zzè!7î’n,%ìXÛ¶O½È#-Ý#Nù¨nݺŽîßnË¥‰@œ×Ÿ8ë.M4+»W7¨25ŠE|îØZb™æH¡Gq„@LbÜ{­µÖòïMZvÊG­ZµrVk¨çÞ|óÍ.©Uµ×^{MÇu 8$º|ôÑGÎ"ó§Ÿ~rïØY†€!çu(κí“+ (œrïïsÎ9yWÎ\µ¿®¨Ë(®6oÞ\ÚµkçžQ¸¾}ýõבû%t°-Ä'˜?¯NpÖËzºç(Ú"©#ì˜lÛ8ž».¾øb§B‹ÓO¶hÛ¶mJ[̽Z†@e!P‡ÓÕ‡„m§ýÞ÷ßßQ³Ÿ¶'W5↮]»ž6mÚ´FÞÆLY^™ÚðÞ«W/gAâ ^Ôªå28êÔqº]ó” sÊ)§¸¬<¯lÓ¦M݃œ·|³î`[Å\÷įô˜{xv}u)E¨`®ÏÈ‘c̘1®ì¡‡ù+h9"0{¶(ãRDo¶-J8¯?qÖ]Ú¨–N„ÜzN¶i{ CÀ0*8¯?qÖ] ŸcíF _¿~rõÕW»“\~ùåeÏ=÷t–hØ¢1àñ›²Í¯¼òʬ`0ém‘?áhîܹ²Ã;¤TÄ6oÊ[)Yâ¼þÄYwÉZîràÀî+3~Q’ã·µ!,Ïúôé#Ó§O öØcP”VZi%yüñÇò߯Æ!½øâ‹nÒ1ô Ýy‰öúöí›’Ô›®¼m7 ÊA ÎëPœuWÎ'ß™BŽa>Õ}xVày"×€0¬/j_~ùe²(×+H¶‡v˜ÜtÓMN9>¹3dr’έWÙêÈ#¬²=êEÃÎgÁ‚i«@ #옴,ÙÁ1ï½÷^²ØŽ;î(·Ür‹ì¼óÎÉmÁ…ùóç§´¥b&Á"¶nµp´…ÿ<•±x»’~ño [V‰ë+‘pÔ¡C' ë):ÁðDJyÙm·ÝVxàzóÍ7…@FâA-Ó2κý})ö2^î r&¡Ž¢Š šr#²ùæi»=aBb—Žcf ²tF-Èüb-C6Ž…!`Ä„l@ÂG Jøoœ×Ÿ8ë.aHK¦kS¦L‘wÞyÇÉáÙ¨d>ëˆ!`8¯?qÖ]h¬ C 6˜¸†l„õªŠŒ›¼üòËòÒK/Éé§ŸîÔ4°éaìÆe—uÂÛ±õÇ*Am„S8bÜjï½=·(â¼þÄYw¹à[ ýø <üðÃî7ßì½öÚ+«ÝYƒ ä™gž‘]wÝU5j$Ï?ÿ¼³S‹‚£g·¥¬•1 Ê@ ÎëPœuWƧßYBÐA•=iÆŽë’‚ûйŽzë¨Q£&^™ˆ7éúÅõµ:„#ޝ©`®›g;„7H,±0 C OŽ'H8z)¬pp[›6m¬±Æòã?º]³fÍÈ7•0`qéWü¨½€ùêg¿zÛy_yå•eÈ!4[ÄYw¶¶ãÚ¯|,½ ¡¦µ¤ˆDd<²áüóÓ7;mZÂJ­{÷ôetêF6ì¾{úb(p 6Ì”Pçˆa×]wc(§?Êö†@µP©lF8ªŒÅ:8ÎëOœu ŸrmçöÛow]?ñÄËõ¬ß†€!`ä@œ×Ÿ8ëÎû„í@C xýõ׫4.¨^4lØPN8ág1âä#&¦×]w]7©°Új«Õ`o+§iOÁ(H8úæ›odÑ¢E¦pT†_…8¯?qÖ]†P׺.cs‰ºQ“&M¤û’±V1Ÿ}öY™:uª›LÄÊruÖq*DQÆøQ5bÌ•ä–W\±Öaf'dÅE ÎëPœu¥ÚÕ„WDÂÂSE Û—Ë6žO:è ¬‡@.‚õÅ_ œ¨÷yÁ|0 ­p°%Ë%ž{î9áŒú|®é‡^Rw®ûÊs½†Lœ.8wÎñ[l垀e/؇ʼn &àà¡b!àGÀS8J¤;-Ù£Òª_ù eZF!Æ#qQ€uÊCIm¢°'¹õÖ[i¿Lœ»ì²‹³`Ûf›m"ÁgÝ‘:S¡$Ùˆú5£Qé°‰–PjÓ&±üÁNC.¹$QÏÑ.Y|NdçpaÜ\•’.¸àùÏþ#k®¹f²œ-†@ x7Ã*ÉmQúÄyý‰³îÒG¶æzÈ=Y0­[·–¨÷!5×[kÙ0 Â#çõ'κ „ÕhÄ‹Àœ9säCqŠÎ‹ y±Ê*«¸Áyèy&gàÞoG÷x`B¼ƒ„#oÝ#$ÅÓºÕq^â¬;,¬ÎÜÀæ‡~AƒUùF±ßolTêÖ­›Õ6Æß²¯úѰeCÀ¨q^‡â¬»:ç\éÇâã þù§{± ,c›_T'¶Þzkg –KˆuÔQÎ*Ô;Ë4D n¼ñFoSÚwH»tüŸÐ¹Nì›ö Ø©yá¯ÓÛõ5B¬Ñ¢–h÷Þ{¯ôîÝ[/^ìá\˜SÅr•ç; CÀ0üx Gžî ûþTãB¡LË믿¾|üñÇÉ"ÞhrC .4nÜXf̘Qížñã~Ê)§È±Çë¤ýÞÿ}ùꫯ\ö¸l´ÑFŽñ¹UÊqÖ]í/DÊN†b¨W)Ñ'Ýä¦ä„#*•´•-‡†¢6vø¬²lráÙ´ý†@€p´á†¢ôýVjU…!`×¶0Tl‡ø–›º‘} C °k[9~jÖçJD€l]2†I@#á»´t±Œf"Ù(:ñl_n¹å\¶G0òZÁN0‘‡HqÞíÚVœ­•ª TѨiÓ¦'<3ý†W­Õ¶†€!°»Æ-Å–¢!ðÁ8Å ¯ô¡‡ꈱžÅ"Ø™¡¢ZìX{íµ—yEˆO^Üwß}2`À€¬ª~\o¹ö¢*JšáÈo§FBék¯½æu%¶wæS?þxÁ:µsçÎIªÏ>ûÌarÄGÄÖ¶Ulå‰@ÃCþÌåTL*U›“‹¯BLѸê.t_sªï­·Å»vÕ'™L‹ü•|þ¹¨V è•MÔ§Ï¿'Ò2Lè+ÔËÌÊwÞy'§ÌœH X!CÀÈŒ€N<(#Ud=2—³½%‰@œ×Ÿ8ë.I0k°SoÉ6=üðÃk°Ö´!`¥@œ×Ÿ8ë. ô¬†@8¨yä‘Næÿú믗öíÛ‡´­5Š6þdA:ãŒpT£MµóúgÝÕ>q« ‰Ê—_~¹?Τj‹*¨AD´0 C Ôˆó:gÝ¥Žk)õϯnD¿Ž>úhGÐñGlÃV­&G´Íü7Vb~ÂJ³gÏ–-¶Ø‚"iQ Æc‡ âÊ`1ͱõë×O{Lp"Ÿ|òIr3õƒpä5Ø¡CÙo¿ýœ¶· ’˜Ž<4ìÝ0<rgqxGÚ»!}–Uû9½- ŽV_]äž{D&L¨J6¢dD;µ¥•¦.Ýu×]òå—_Ê9çœcd£ThlÍ(³f‰Þy‹Þ•§=kÅ0R˜8q¢›XêÑ£‡¬´ÒJ)ûlÅ0 CÀ0 B ЧOyöÙgå¸ãŽ–-JHEØBüöÛoÉz„#ÈH†€!P¾ |pÙe—Én»í¦C¬:Æ mºé¦Ò•äO CÀ0 C †€0ûÀ${±¡º$´iÓF ¹@ó‚ öÍ5Ûm·]5£/QÈœŸŸ˜ƒ@Âc=–å¨ÔÝ~;5ÈO5‘ÜѲeË”N}ˆH„…!`ŒpÄV À§ŸŠZ¹ˆÚÎ-©ßRU’võ:Kß „£UWi×.}™4{¸x_}õÕNòÏldÒ€d› ¸Лqyûm‘3ÏŒ»%«ß0B¸ýöÛÝÖN8!d¯m2 CÀ0 C Ï?ÿ¼\uÕUÒ·o_G,êÔ©“› @I¥ &n»í¶h•Y©AÀS1òHFt‚eìÖ[o½é“5j…A`ðàÁnbËJTÂ&3o¸á§n„Jƒ©w«Å0 C z<÷ÜsI»1jêÖ­›,«S‚«:»f¯öþù'…˜äm/Ö;÷ËA5£E‹emþ¯¿þ’]wÝÕY{…ýöhÞ¶Lï~ÂѾûî+uëÖÍT<–};î¸cJ½Ÿ2áka†@#±ÕÂ#ðßÿ&êÜ`ƒ%uϘ!²pa‚p”®9,Ö^=¡Œ’‡*ÃÝwß­Nm_8u#?:]s¶Ý0 CÀ¨M|ûí·òè£ÊÞ{ï-›m¶Ym:5;CÀ0 CÀ("/½ô’pÀÒ¯_?8p ð¬Å™­üñ‡ì¿ÿþx‹ÒEÀ#Í;7ÙIGm´‘›ØIn´CÀ(+&Ož,S§N•îÝ»;u#lZ°[¹óÎ;“ç} äÐÍ7ß\ºté’Ün †€!`†@M"0|øð”æ¹–ye³?üJHþíÅZÆIŨ1e G;wîœ,:nÜ8§:šÜaaúôéâ'÷ –ô?ÄŠ¨¤ú£aÆþU[6 CÀ!`„#û"ÄŽ@ÂÑ[o%Ú 0cS:òôÓ"ÿ-Ò±cró÷ß/­[·?«7¹Ó·€ºÙ— 4Þ½{ûöØ¢!`†€!PÜ£–¥\Må¯2>o;KCÀ0 C ¾þúk—iL&íøñã•ÁO?ý$Ø@nf|¬J¯¹æšq4ouÏ6-¨pä‘ Ø”UeEDu#âÔSO•æÍ›kîæëÒ¨Q#éÙ³§eêFüv›ºhX†€!`” Tpà©§žJveûí·—fÍš%×Ij¨W¯^r}†ŠL›6-¹^Ì…ùóç ýõ¥@®µÙÂá·Uã9j̘1Ùuûýó +©(Vs^‘*(P¡ …šÿs*PV!`ÔêÔ‚s°S(qªŽÞ|3Ñc,ÕÒvjzá–L– “rÒ¤IêÐô¶¬¿þúΛ<¹Ó·À$+êF×^{mŠ×«¯ˆ-†€!`µ¤†‡ &dœ|ðÁµö<íÄ CÀ0 C >ÈžíÚµ«³95j”ì¹çžñ5f5ÇŽ€G,òG¿üò‹³Wò¶ÇÞkÀ0 ŽÀ¼yódôèÑÒ®];Ùj«­\ý7v¤#&jQ¦CÕìÁtV0Aµˆ‚wÈ*4 CÀùä“„»G먺ä Jo~,X§­·n­ºž¡ª…[âjrP ë#GŽt‰’^ïŽ>úhoѽC°aLó¾ûîKn¿ÿþûe§vJ®k•@´oß^PÌ#¨ ±Ë.»8‚Òœ9sÜ:¶j½zõrË™þø G\×IAµ°˜Á3Ï‚þðî9üÛlÙ0 #Ùw v<‘r„Âä&MÂÛÆÿôùçEE"k­åÊü?{g/SýþñO×zídß²ï[’’d%Š¥¢-Úû…P’ÊŸìRRJ I¶J¶$YBQvÙ÷ìûòž3Î83wfîÌÜÙçó¼^Çœs¾ûû\ósÎçû<æËS]9©*^ý±¡nƒK”(áP‡¦©w£\¹rá©§žrHã Äü[·nÅk¯½†7‰‡+Î1’ @à ôïßêò_ï«[µjøXcH 8{82…Gæùv†‘ „À¨Q£Œg¤={öt¨Ož¨Wºæâ5~̘1FÚèÑ£>ÑH€H H}øõW—•·4ÏÊ÷·K+YâBÔe’ÃIm8äsu¬66~øÁU‹.ÏYé¥NÚeÈOÊZG“'OÆ|Í ÓŸ~ú)hoN½½øâ‹öcO;ÖðgVM$¨-Z´ÈXÔá)4Ù*y‡ªÏvM3òYë4Ó‚õyöìY¨ÌÖ-[¶l¼7 pÖKQN 4ßÌQ‰ÝOÉ<„Œ¥1úÇÀí·»¯T^”â̇pjz£¼yóf¼ôÒK¨S§TE|¯x?RGV÷íêÝHWï 4HÚÓi$@$@$_̇ÉêFŸF$@$@$@VãÆÃ©S§ðôÓO»&/X°ýúõÃÍ7ßl<Ô·–ç~tÈ!ƒ±0KŸ—¨™‚#z8ŠÎëÉ^“Àùóç 1QqYÌ©ÏGMÃÐÌ;;w††Ç´†sqÎËc  ÐEð"øteº€þôéÓ¨_¿¾«dÛ"}×)Žg=´á˜ÑÅ‘žyŒR¾¶áEˆ1³7ëÖ­3¢˜˜Çwß}7rçÎmÚ?ÕƒŸ¾û;zô¨qNC:ëÜÖ´iS{ow4´¨Šx’3½OÒè)Û¶m3ÄNVÑ–ý¿ÿû?ÜqÇÉUc¤«Ót6GêùH=vïÞÝLNòiõn¤¿ãõ}hJíÂ… 8qâ„ÛjTÌtàÀãýêâÅ‹¡Ï—>ì¿o߾ș3§Ã9 €H"8’/Á4¥J•êè YIQl÷îÝYõ ß[Ó!ÑÃÁý÷ßï!•IÑL@G \º{”U¨VÍýêÖ¾þ2sÛó芜n¸ÁˆA®^Ô¡> }àD8ýÒ¦Mk¬êQïF:áyš¬í•r‡H€H€bŒ€ºÕ×è7ö*žxŒ ŸÃ!  ð@`êÔ©v÷ýz=lØ04jÔÈ¡ÄÁƒPjº€GÝý§K—Î!ÑK@½™B#󓂣轞ìyìÐïêŠ+JdšRn©aÒôÅ«zµMHHp™O¿¿5d H€H „$$±;[#Ž#GŽ ¾,ªO‘yh#EõZ ± «w#m²C‡Ö–íûêµ½e˖ЦiX5GK—.•W’ÞIš ¸ùÌš5«ñN²cG¯^'©¥jÕª()Þ¥Ô©‚šÞgyz‡iÝsÏ=q® Þ¢¬£’t2™•+WöØçdŠ3™H Æ $‰¨CŸ&Mðfܪæt6|øcùC-:ÊÈ»OÔ¨q­¯â†O\5kºï|¦L@ëÖöt½ž>}º¡ü6C¨éd¼eËCQ¬Ôµ¡þPчfï¼óN@&`{¸C$@$@Q@௿þ2Üú^ºt O<ñDô˜]$  H)]9«‹s’³ 6 S§NÈ›7¯!:zï½÷ «‰u†&Pቮjmß¾=öíÛ}™­Åi±C@¯ñš5k ¿)8ŠëÊ‘Ä]@ÒZž‰æÊ• ê] téÒ.¨ 13gÎŒ.]º¸LçI  ˆD/^ĤI“ì]SçÔiX5«àHYª—œ^¸kÛóê¡HÅO)1­cÀ€F¿üò öˆ§†vO ×kþý÷ß±cÇû‰HðR¨¿7ô·G¨ÂÙÙÏ ¨!àz DÔtŸtê¡ïäI‹‡£[nÄ=»øôºë&MÝýuëÖÍ¡Ìûï¿o¸TUnŸ>}@ïFxx@$@$'Ô%°¾,¬T©’áZXoÔuõ H€H€H ¶ èCo §³~ýzÕ-Z´€†à™2e Þ|óMü#Þ‡õ¥ö´iÓP¶lYôïßß8ÿ£„8ïÚµ+ôá>-¶¨àHC8èË ©P­P¡B±5Hކ¢œÀÏ?ÿ ’ª·¹† ÚÅÖa-Y²Äª—…P¿pµöƒû$@$@$à+Ù³gsœYNïGÒ§Oo&ù¬#Î tÁ„igÅ¡†# µ;Ö¸gÒ{(Í*Ò¹^ïË\™Õ»‘z ×3^6ßvÛmÆýâøñã‘IEÐH€HÀ $ŽÜäãið‹€z7RËŸßöéë¿:ñª‚9Ož_!3? @TPwÀº2FÃÙê #½þúë)r• Øi  ˆCü±ñðW‡^S<ëƒ÷ $!¡÷ÔêµHÝ÷>wÞy§‘G…&ú0{þüùèÑ£z÷îmœW³®^¥Å ©¦¶sçNcÓ—7 ™{×™#Šn t‘¦ØàÁƒñòË/ßë*0²¾lÕïh½ÿÓïn DçpjÑdáÂ…‡póÍ7cΜ9ö<VÍWz4räH{îvTÐôßÿaãÆÆý•ÎÁ¦íÞ½Ûð«‘W4Ü›¯V¡B”+WêyVMê=ûì³Õ8 ‘îÇ 2dpÈãïAíÚµñØc%[\½,j?¹0!YTÌ@$`!@Á‘wO@ÎæÂ3 WéÊÀ_yå—“¸*|¿ÿþ{T¯^Ýð‚ôôÓO{U/3‘ @´Ðp'ê¥@Ý«ø¶mÛ¶xíµ× 7®4   Ø' Þiž{î9,X~ø¡ñÀ½I“&5jT’‡È}ûö5î™5œš†&w¶úõëcíÚµ6l&OžŒÏ?ÿÜã*cçò<ŽêáHMÿ~t3HÑ3ö”bŸ€>-Uª^xáÃ{‘z{oÔ¨-Z„ìÙ³bÁo¿ý76òÅ>ŽH€H V:t³fÍrΫ¯¾êpìÍΉ* ÷å·¬z¬X±¢7Õy4ô´¾kÔyø£>²—Óvu¡‡>‹õÇÔË‘FkQ[¾|¹ñ›Üü®ç~ûí7clº¯öàƒÚvð¯†ËÖ…(4 CptæÌ™[Äm]*_åéˆÄÄÄÖ¾–cþø! ‹)E(yêߘnjc¬ÚyüñÇÝV_Ü'­X±ª>¦[?·˜˜@$@$#ôæ\ÅFM›6Å|½a¤‘ Ä]õª+zOHür}Ø­!w4$šºÚ×ûf]°£žÕûÅwß}g„J»EB›«Éé Ý^½z›»<<ýÌ—êíjÿþývoWÑ?2Ž€bƒÀŽ; ÛO@-V¬˜Ghùòåó˜ÎD  ˆê8uêÔ=z4ä·X¬ ‹ã   ð‚€z4RO>ù¤q¯¬EJ—.m¬†Õ𪃠¶mÛ ï‡:t@Μ91}útz-ò‚m¬g1G¿üò Ôc¦yëãæøH Zèw»Zݺuí]VOGÇ7BikX•uòµL™2†×#{&î @p§–’.«WÖ` ŽÌþiØê5kÖ˜‡Ø¾}»}ß×½o«\¹²áaVËjX5SpäN­Y³f¼‡ó0ó“ „@BØZfÃqC@îƒÅ °ïÃýä“O ųº-¤‘ [·nżyó /)6â_ ÄM›6áÆ‹/ŽÁƒ; >W®\†IÝîO™2ÕªUƒx³6b*TÈ!/â“À7Þ K¯¡Ô(8ŠÏ¿Ž:r ,X°ÀðNgioû÷ï=z@" àèѣƾz±£‘ @´PÁކq6­|ùò8uê”×Û¾}û.]:³86lØ€Õ«WÛƒ¹S«V-‡ê54\JLê™¶jÕ*ãY¯/]º{öì1“`Íg?É ˆPEè…‰÷n©šwìØ±È›7/TÉK#  €EçÈîÝ» @¸|ù2:vìˆóçÏãÓO?5„#ÎÃOŸ>=&Ožl¬öÕüï½÷žƒ§ çü<Ž?… 6„h:r ŽâïúsÄ‘M@=é X:ÛСC°™EŠ1æçt“ @$PçVkß¾½q?£bxo6}Oظqckøì³ÏŽƒu m[íìÙ³ÖCŸ÷…DêåHÍN-kÖ¬¸ûî»}®›H€H \(8 ùowóæ” Pã’«ø.]ºacRVK“ @ôÐZ½A/[¶,_FÿåäH€H€HÀ'ï¾û®á™¦W¯^¨Y³¦Û²êõâí·ß†®¼}æ™gÜæcB|°ŠŒT|D#ˆ êÁnïÞ½¨W¯žËéw».ÌÔ0.úb–F$@$@ÑBàâÅ‹øâ‹/ìÝÕ9­]»vöcowÔ“«Õ¾üòKè"‹`[æÌ™šH©à¨X±b¸õÖ[íuªàHÃóÍ7ös-Z´@Ú´iíÇÜ! H'@ÁQ¤_¡(ìßìÙxâ—¢–Ο8ý”b£8û3àpI€H€"œ€>0îØ±£!6Ò0ß~û-êÔ©#÷ǯ£wïÞIdéü®«[wìØöíÛcÔ¨QÆêßµk×bÍš5ÐOÝvïÞm„I«Zµj„`÷"€éÕÈüŒôþ²$tîX(.l«T©‚ìÙ³ÇÃ9F  8! ^ˆfkH”k–>}z´lÙÒ<ôùSfl£3fàäÉ“pù\±‡ÎŽTptAÐÖ<Í›7·RäDûCgû`¸V¦ÐÈü kgØ8 €A`ýúõ8xð yä!  ˜" Þ^/]ºd“z‚M‰—M}g(ï­qæÌ£NýT’.ú–éýš:×Ð÷ÝjêyV‡T¯^=EMªxÊY+²†[³ž¦ý¯¾úÊïîV«V‚#¿é± „€-šSûÅ‹o,_Úåôc>Í/±‘S•øóÏ?¡q'û÷ïoÿbvÎÃãØ ó¯áåÈ>ýA¡*$™(’³wß}êR^ÈêDN#  x'päȨ÷ÈZµj‰ØÈæ1’b£xÿ«àøI€H€BE`ÅŠ¨_¿>æÎë±I …ö¿ÿýϘ«ÇŽkäÕphË–-C¯^½ŒOõ^ñÉ'ŸàPäÏ m~ûí7»ØÈ]¹#Ãó¾ÐÅ]j槯噟H ð~þùg£Òºuë¾rÖH$@$@a$¨pjæTläì¨@êÛrçÎíÐÄ!CŽý9аj ޝèsæÌ‰zõêùSË @X 8~›IWDlÔ"UªT3d7gr=K—.Ý…òåË._s©÷šdL]Äê*?]±¡žlhqB@VêàÜ9ˆ,Õã€Õ½¢®ò¬P¡‚± Ôcf&’ @œøè£ñ2^ÀSO=åvÄâø€F$@$@$`6l@“&M /ƒõSçbs5­µ) yÖ¶m[¨w"]a«ÂMSWûï½÷ž!XJLLD—.]0}út#ÿ*ñL/Ð&)~†‚@0oÞ<#Ì_(Úc$@ÉX°`±èR˜ÐH€H€H V轎:¢0MÅ476ýþtö¤óèž={ü®Ï›‚wÜq‡C¶É“'ÃôFïàÆsžûua 1ø‘YI€"†€ƒ ™’%K¶‡F“¥wç-½"¢¡9—/_Þ,Ÿ›Å=ø{’ÖÞL?þ¼ñÅ®ÛÖŠGýÒ=|ø°™lÿü믿СC¨º5GŽöó܉^¿ÿÜt'‹1¬\i;™Œ‡#ÓûÕÛo¿DÙë¢Vž"  ˜  ±ËuEË[o½…R¥J9ŒIÝô¾óNz‰ þ4¸Ó!ÍTHT¢D —­k]ëÖ­Ão¼a¸ßWáÂA@ÿi$@‘A@ï÷-Z$Ná«!sæÌ‘Ñ)ö‚H€H€@àq@ N(m*ÊI®^¶£[ Liè–œ©—z_láÂ…¾d7Bo'7v³Bõ¨«[(Ì*, E{lƒH òØ=)R$¯tïcÙ\‰–Ê—Øí›6mzpóæÍŸlÛ¶í—íÛ·pŽx}\¦ó$ Ä"õ¤ðÍ7ßH¨³:(S¦Œ1ÄÿDêÝ¢pá$ (P vF®ž“Ä™† ±IðгKèy«éOÃAƒlBfç´Š–-m!Ý6´–Ô³R³f¶pno¾yÝûÒŽÀÈ‘6±ÑÑ£¶2‚¯¼b =çX H€H€b™ÀÂ… Å‹ß:<óÌ3Èìº6–apl$@$@a'pAnü–.]Šš5k"mÚ´aï;@$@$@$@$@$@þH-r‹ÈÈ^þÊ•+ÿÚ‚¸“+W.‡ÚYcj8¤ð ’ ¨75—‚#}˜'àüfPòw«V­Bûöíå¥j ½U5hð  pO`„ 8þ<ºuëfϤžw¶nF†‡E³l#À< Ž-6m‚ø¤OÒêöíÛs¥J•J’Æ$@$@$«Dè±cÇB…×<ð€}˜êÙGE-–kö4îx&P¥ du00y2ðÒKÀo@^*÷Þ y± 4hX´õž+³¤ªÇâŃòåN Bi[È;K6·»êµJEdÚ?çqn 1H€H àôÞó»ï¾“yá^ù^—/v „€À¶mÛ0wî\ChtìØ1üý÷ßâ%^n2,V¿~}ËwI€H€H€H€H€H ú$ˆw£ŒÖn_¾|YÖ‚ß.]ºäÐȉ'ŽyTp¤z"WÞ&í ‹¡˜‚£¢E‹ºHå)  ˆM ,-î&tîÜÙÁu~¦L¥ôŠ«¤m!é4䫼[6œ,ú#6Ò¾,^lÕªìß¼ø"P° MÈ4e  Î9§O·]·bÅÔ{£ãÔÑã­·ÚBÇ©X‰F$@$ÃÅžxr6©…§l•H€H  Ìž=ÛöH‰ó¬â#õhtTb=ÿ%SüñGÌ›7Õ5®4H€H€H€H€H€¢˜€†T;` ©&Ž$VðMo°¬–-[6ë!÷£„€ Žt‘húô¾u˜‚#ßx17 @l3fŒxÛ¹A<uEØ(–-Ó©F.Ýx#!ðý÷€Dà ‰®½;°7¤aÛvî*V´Ÿ2<õî üú+9óõóæÞ /Ë–Ù~G•, ±ç{È7³.~’ ¸&pJbcŽ?^B€W½H¸fij$@$@Á! ‚£´iÓ:Ì?Ù³g‡nåÕ…*H€H€H€H€H€b€@jyéµÏ: ¶kßYpt£¾Í¡E_~ø„‚£¨»Ôì0 @ ”Ø\ÓÅ%޾ðÔ.?ÿ Ô©c ÿ•ªYܯ½¨cMqx‘¬Y#ïh<Ý4ÄÚ矫V5kMš®6–+¼ù¦û&Μ± šT¤6s¦-4œ:ˆŒÛµëº+úË>’ Ä'O?ýT<ÐÇàÁƒãGM$@$êÍháÂ…¸ë®»IÝÙÒH€H€H€H€H€H F $ˆÀÈAp$Žd=wðm•¾¥±GQ´«:1}¡æ«©à(]ºtÈ—/Ÿ¯E™ŸH€H€¢’ÀÇŒ‹/â‰'žÀ¢E@ƒÀóÏGåP¢ºÓ¿ÿñvœ>íß0rç¶]·I“€§žr-6ò¦f‰¬`ˆ¶Ož´…k[±xùeoJ†/üùbòd@ÃÌ–% ¹r­[_}ˆ·fŠ´ôï}Ø0·Ù˜@$@% Ï:ä;g˜xª»íÛ·hݬŒH€H€<ÐPÚ*:ºçž{Ðû‹/v¨²œ?ª‡xMTpT¤H#¬L4õ›}%  èKÏqãÆ!oÞ¼"4jŽªU ÿÕ£‡?µ±LJ´h̸̟ðk)é.x8Ð^mÈ n]à¾ûRR£ïe÷ÉòƒõrG žšTHäìeiÏ@¢Êß0°¿-”îûwÓ¦ß|c;w÷Ý@«V@óæŽaädq7:t°õKÅJ={:ö±_?›L"NH؉ë›hÓ‘1#P½ºÍX¾‡ñul)>Ž.]²yNKHˆñr”$àŽÀ\ù¢ß´i^yå™seÒ¥‘ @ˆh855 ŽBœÍ „@‚<€ûI^‚3{ $y´WÌã`|ªØä?þp¨ºŽÆ¡Å ;vÈK-y«E#  8 ðÃ?`Û¶mxôÑGe´©¡Â‰wÞ„V‹ƒÁGØ5,ÚˆÀwºîØÆ@×®Àß»NÆÙT©€/¿´…(ëÔ Ðpe¾Ø?ÿW®¸.!v=Ú&*XÐ&ØÑrV“÷ñhØ(Q"·¦Øö{ èßß&’4È&4ROê©KÅHê­éŽ;€ï¿· ‹6lp¬£^=à‹/l!ätœÎ–>=Äë¥M¤tà 6oI*lÚ¼ÙÖ† ’´ŽlÙl‚,íC<Ø1¹CSÎÊL™^¾œü¨Õ{—Š´R§Ö\ÉçgˆeC‡•ÿ ©Ñ½{÷X&ÇF$@$æÌ™c<÷,]ºtöŽ]"     ÀGѸ Û Ù:šÕŠèèÙR¥J}$b$yEx(˸/[ž˜çÌ™*T|C¬1¨–,±…Ò(SÆ·f8€3gÎPpä6æ& ˆb#Dá’JT%?þ8²f>ÿ<Šå]ÏŸß ÍÝ0>ûÌæÉ§m[ lYw¹^Å@&ÍšmÚØ„6*±ÚùóÀÊ•@Íš×Ïj(³*U€,Y€&M€¦M!$~ú "t³åUQSåÊÀÍ7CBû]/¯{åËÛDC²& ‰w#MïÝòÂÞ&`qöš#N»ðä“¶íða`Ö,›G"-gšüÔ‡òtg/½èæÊô–A#1KT c[ºÔ6>çðszÝV¯nºÉòí–[\ÕùçôzÎ;3 S7ožÜ¨éÚ5Sa–^+½Þz-5´±zš²š:U/Yú÷@²V2Ü7ÿˆSž­%îcAý‚¥‘ @ˆè¤‹Mž~úéµÈfH€H€H€H€H€H |Œ×"0Ò×^VÁQ¢Ï–swìÞ½ûh »÷…,o^¤Ë¡-ö€,5—>XÎp7hh ]i¾f͵Þê2ì½{“}»¡®Ôèáè7~ Å÷c@IDATÄ4õê7KT÷Iœ¬›T A‹Xù΃*d áꎪXèùç÷ßÞxÃjÍìƒþÄRïLk×B<…¦à[)½zÙ„>'º™¦´žxÂæ½Èôd¦Y?U¤¢!w¦¹¼1­§£ýŽÂ›ÉçQ¡”†TÓMEF.ìС¤å4jÅäɶóo¾ 8 ŽÔC“Þn¨g+ ë¦õFšé¸ô+âìY›‡¢úõ2d°]w½öº©Ë´J• 7Ì#ÞÓ4\ â…Àùܺu+$$¼}Û,îÑþüóOh8Ógžy&^Ppœ$@$@B€áÔ"äB°$@$@$@$@$@!!`Ž4¬ZÉ’%§Šè§¥¥ÕÒ2d˜[¼xñ–òo—å¼ß»Ÿ|ò‰„yÇ¡|Ž9Э[7‡s<ˆ|'OÿþëŽDÝ5ôèÌœi[^ïf¹ÃÓ$@$@1I`´Ä³º"ñ®Ò%ò/¯†%0À&j —^â—_ V§p÷Ý—æ6ïEëÖ¯½”*u¥ü”Æ[oÙ¶Ý»Sl¢b•XŒ^«^Ÿ4üš³éÏPe¦¿O]93ùðÃëB¥\¹€ûïZÊ ±œ=I9×Èã·ß–U"ŽÚ·Ï& Òð}¦i¿T°¥Œ´o*à2M½^™¦Â$9âz¬f>~’@¬8zô¨ˆ/ˈÑQ…˜Qâ –‘íÚµ“pwÄ:ŽH€H ¨à(11Q~Ë׉°ž±;$@$@$@$@$@$xòÈÞfò"ì) õQGŽn¼vJ?n•skEtô¤ˆŽ¾–cyÝá»ÍŸ?Çdž ’Ö‡™2eJrž'"›€DE3Â4hX»Mš¹˜¶77ö“Iw(8JÊ„gH€H€b“Ày‰5~üx*ô x­i`Ì ÄæX£mTžìçŸÆmžo´ÿêõ¦}ûðŽ$M›§}G~ð ­/*~6 Ðß_êñÆ©Ðæ±ÇÜ¥Æöy½v… Û6W#ç'Ø¸Ñæ jêT`ìXÛ¦‚- cשP»¶«’=§!î´/*šJ—.iÝ£F%=ç|F…I 8Ÿå1 ÄiÓ¦b£öòÅ]OÔƒ*2Ò-Ÿ+UbüááˆI€H€Â@à”ÄÇ]²d‰üVk`ˆŽÂÐ6I$@$@$@$@$@!%`‰ è`©R¥—ÖUXd?/ûÙEt4YÒú‰KòâiªxDÚ“\/Õµ¹†N1bþþûo—Ù›ÉÓý‡zÈeOF6yŽ‹õë-}7öøí7à‘Glq,Iλ9á1 @¬˜,1ž>ŒŠßÂ?ÜyþL‹vK½ éÏ—Ûn‹N]ëF‘"€ SÒ§¿Þ¯Pˆa®·{{Y²ÈJŠ[m[ß¾6ñ‘ ¾ù˜0øôS`ΛG©`Žþ£‚Y;ë&ø"ðÕW_‰p/ñÌ!‹þ'§‘ @˜ üôÓOÐgâ÷ÜsO˜{ÂæI€H€H€H€H€H 4¬Â"ˆhºx3j&£)Ò|F§.”±ÑP97T¯í–Ïå⨜® Ô‡{º‚çÎömÿþýþÁ½C¤ÚòÖd ¼å‘:šáaTPïFjâ¶>9SÁ‘þÍh8= Ä2^'&–‘nqyè ”.Ë£®±5on}ûmä Ž”¤Ul]d££·úQÃÓéö×_@­Z6ïVkÖðBvù2ЯP­pß}ÑÁ„½$h" aÔ,X ÿ¿î3î-£©ïì+ @ìÐpjjMš4‰ÝArd$@$@$à#dõUŸ>}|,•|v}îÚ¢E ‡ŒsçÎÅ£>j?÷Î;ï C‡öcî ž€ƒàH«OGsŠ+VWDGß‹(·«&å¼l@Aýâöǚ˞~ò>uê$ÍûSËDY³€œ9úõ“í ŽŠ-šl>f   h&°bÅ èV©Ò\¬[wzöŒæÑÄ^ß«Wòç¦O· d1²áé(sæØ+Gä™@… 6/GúŒJ¯.\(î^Sp›²G|Á>ü0°x1а!Gžé3•ü#ð¸'»,Ê>zLöK‘ ‡Àq™Y¦Lȳõà4ÀZI€H€H hÈѽ{÷¼çgÏžMRç¹sçÚ:}út’<Êʯ*Ð"‡€:ÙT/G7¿üÕŽ#gìI@ èßÂóÏÇâ8Å£iž–-ŬøƒÍš¸ñF@nsPP–dèÏayÇdˆTdøý÷«b" €Ÿ4œZbb"š6mêg ,F$@$@%°nÝ:ìÞ½›áÔ‹•µ‘ D8·kwåé¨ô½»„X%ÞŽžáуâÙ(‹?ã)-1 Ú·oo¸;ׇ‚´è&päÄý!к5 ‘ñl¦'õmj2¦7Þ/^¤à(NL& ˆnGd^Ô—¡%JôÇ–-©Ñ£$Œlt){¯mFºtü>Ú´‰ÅQrLÞ/Û0"bp_BòÖ¨lÞ Ô¬i]º˜›þiH¶—_š5s_SH€ü'°oß>,Y²<ð2eÊäE,I$@$@$`†S»GciÓH€H€H€Ü(T¨ .ì6ÝÛ„\¹ry›•ùH€H€‚HÀ­àÈlSB¬ý%ûçÏŸÿy˜§Íï”M‚P ²lieKb7Ê2ß*Uªàæ›o–зI(‘JIòðDôX»P§ ¥J]?ˆKDcyw2ÃÒpjj ©– (&“ D5ñãÇC]øž;÷8²ey$ª‡³¯[ÆõQñˆ¾³v û³ãæÀ\H“ÐÍ“©7#Ü?óŒ¬Ìèî)'ÓH€‚E`Ê”)¸rå é 0ë% pIุ¹TÏí9räp™®‚#ÂÖªUËe:O’ ØtîÜo¾ùfPpÜyçøùçŸíu«C  @p $+82›—øšgdòµMO':tè ½öÆßL›6­¼°É†,Y²ÈƒúdžÔkiZÔøK%hb*Ø>¡K½Õô L2FÁQ2€˜L$@$õô%è(q›“={+q©ŸÕÓ¤¡—h‘G@²Þ{/0i’-DV† ‘×Gö(òŒy}bH ž¨A}¡{¯~ÓH€H€H DÔsÑúõë1|øpÓ¿µÙcÇŽaÙ²eF¨O}FN#  œ9s¢®®0¤‘ „Œ€×‚#=º"_Ü4€o(8Š·+Îñ’ øB`Ö¬Yرc‡xœY‹§Ÿö¥4󆚀zªQ/Î>ê–Ù^$Åëøßÿyw„þýy^E#ˆ»ví2^è¶‘˜ ׄ]  8! ‚¢ß~ûÍð°×¡CÌœ9ÓXdbz;úá‡$Äî%0œZœüAp˜$@$@$@$@$@v)Ù+ñgçwÞ‘(\†ëš 0ÀÜåg„PÁ‘†FÍûZGýðpT¤H‘%»G$@$@þ!qGS¥*‰Í›K£™£-ZÔ¿zX*4n½ÐFÎ~ýX¼øûo`þ|Èÿkç<&5¯¿þW¯^e8µPƒg{$@$çËBõdÛ_”èkÖ¬ÎGK—.Å'Ÿ|‚† Bé©5iÒ$ÎIqø$@$@$Ý.^¼ˆÿýùóçG†»B?yò$tÍ5kVÜtÓM8&ùÈ1¾Õºµ m+·¼Ä-,«,3gÎìKÌK$@>›àèÛo¿Åÿýgï0Gv¿#ÞƒqË-–nú(8ÒI.#cËXr—H€H VlÙ²ººµD‰ïDptzöŒ•‘q$_T\4Y‚I«w£J•(6Н«ÏÑF2 §¦aÜ7nÉÝdßH€H€bŒÀ‚ ŒµjÕJ¼`þ'ND=p÷ÝwŸsçΕߌ•P°`Á9‡C$@$@ÑE`ùòåxûí·í~òÉ'“½ܰaÆox3\½z5Î;g”WÑQûöíåùnO(PÀðf¨ó¿i>ú(ªU«fºüTÁò„ ðÙgŸaÉ’%¸¬.µ-V¦L<òÈ#èÒ¥ òäÉcIIº»páB¼ð ö„)S¦ÈB×¢P‘”.€ÕvÖ®]kO×4iÒâèW^yµjÕrHã Š@ØGë -;'€ ,íú(8Ò F$@$@±H`äÈ‘†ç…Ì™ï0æÊzõbq” Ä|ùù/M#ˆÛ·oÇŠ+Œ‡±éÒ¥‹^±$@$@ñ@@Gyóæ…¾TÓƒµk×6>‡ fœëܹ³ñÉH€H€H€ÂG`ß¾}øî»ïìHÎûà—_~‰Ç§OŸ¶—1wöîÝ‹wß}C‡5¼6jÔ£G6“ßžGþù'4«³È^ìüóÏ?xíµ×ŒvÞÿ}CxdM·îkˆ×U«VÙO={V¼rÿ¶mÛºmCÅHê‰qÞ¼y‹‡~Ø¥ØÈÚs}·©^§M›f=íqÙ²e¸ë®»\ \…jS1‘zLRoJÞÚÆQ·n]—m8סãUïH&–F$@&@ÁQ ‰Æx}"È5Ì¥à(gN£ß±c‡áõ‚#˜˜H$@$¥ÔEî¶mÛD”ks˜#G”„Ý&  $ ‚£ìÙ³îà#°{ì @ŒX$+I®^½j¼ÐsbBB^zé%ìÞ½•+WvNæ1 @¼¸ Öh\.¶TSA7‡4Íïlå„Yþ’s¢{hÃ^Î,¯ŸájÃE×#éÔ˜1c ÏEfŸ4ô˜z0œ?>ô]æ¦M›0iÒ$<øàƒFõ¤éÞØñãÇѼys¨ˆÈ´²eËbêԩصk—!pÒ6&Ožl„l3óèç‡~hlÖsîö5ÜÛŒä `ÆŒF¿OH˜š_ý 0Bª™åõÙõ[o½eò“H€F€!Õ†2>*réáèùçûï4î„Søjy€Ä$  ¨%ðï¿ÿâÂ… (Y²dÔŽ'  H$ {׬Yc¬øÔÁ4  õb¤¦h$@$@$à‘€N¿ºÎñ8·%¼iIo(û?XŽu÷YÙÌðî/Êþ»zÒbڰ亾®6®÷ ÉÞáÇPbI|8a†9õ¡ˆ=ëÉ“'ñæ›×/„zúöÛo“,nÑg¼êIC©=ýôÓ8wN\É›Šz:dÏØ¥K >‰‰‰ösê)Q7õà«ïLû÷ïoOSï‰O=õR¥š;sæ n¸áh(6çPi5jÔ€nÚ† ¥T<­¶páB¨ )K–,jf øF€‚#ßxÅ}n. ™Œ,(òçtKÆ(8J“I€H€¢šÀæÍ›þSpÕ—‘' ˆ@_ýµÑ+†S‹À‹Ã.‘ @ŒPÁQ~yîÉû¼¿Ð ‚@©¤„ëŠ4ü•†æªT©Òõ å¯ïÚ÷n“½S׎n±Ÿ½¾ã¡ë™,{ájÃÒçÝ‘#GB·”˜zëQ±?6xð`£gmÛf‹Ð²[$@$@$]ÔÍ}=ŒN3œZt];ö–H€b€†SS£à(®&Ç@$@$)ôÞ®]»v)ꎿáÔ¶nÝêÐn:uŽ=”+WÎS2:d„^33i85_¬bÅŠøñÇ"úlÇŽðÔf™2e¼ª¾X±bù’29dæ xA€‚#/ 1K`¨àH'L Ä"T©ú£P¡ŸQ¶ìÿÅâð8&  )Ÿ~ú :tÀþýûѵkW‡Õž!í# ˆ[*8*T¨œ_ÔÅ-œH€H€@ téÒ¸ï¾ûP“ïU8 Ž4¤š·vÓM7y̺iÓ&‡t ˪÷´ÞÚ?ÿüãu÷îÝGÙ³gwÈïî@#ÏÐH€H ˜(8 &]Öm'pâÄ •˜lE‹µŸã Ä K—.a×®5r³\(V†Äq @XèœÚ»wo 4™2e—_~‰6mÚ„¥/l”H€H ~ 8pvå‘G‰_9 ÄgÁ‘·¢ÅP¸pa4\ ŽTtä¯={ÖcÑôéÓ{Lg" „ŠG¡"çí¨w#5 ŽâüÃ' % óœ¾ õeULŒ¢à°H€H€HÀoê2¾mÛ¶øí·ßP½zuClD¯~ãdA  X¸p¡QšáÔR‘EI€H€H ÂìٳǡGÙ²es8öt:µçWê;wîôTÜç´sçÎy,CÏEñ0‘H „<;†°#l*¶ PpÛ×—£# x'°yófGñþ—Àñ“ øK`úôéèܹ3Ô;îK/½„ Mš4þVÇr$@$@$"NM‚£ada  ˆ(3ftèÏÿý‡FÞ¸˜3hÖ ÐÜí (8r‹† $@$@QNàÌ૯nQd§‡£(¿–ì> @x:tÈ›¦îì¿þúk4jÔ(<a«$@$@$p€ ŽŠ)‚›nº‰LH€H€H€b„€³G#õJä­àh×®])”*UÊ!=mÚ´hذ¡Ã9 @,HˆÅAqL!$ ®îñÜsÀ† ¥àÈ#&’ D1õ´?qbAG Ž¢ø:²ë$@$@á#ðÙgŸáÂ… 6lÅFá» l™H€Hà½{÷bÓ¦MônÄ¿  ˆ1ÎBâäDDÖáÏ›7Ïz˜dßYp¤¿%h$@$(8Ї«Ì19b«ýÆ=¶¢‚£téÒ!þüó1‘H€H€¢€:úSKL\ÈyΆ‚ÿ’ €O>þøcäȑ͛7÷©3“ @0,ÔU%b §f`à?$@$@$3n»í6‡±Ìœ9ÓáØÝÁ•+W0cÆ wÉÆyõ””5kV{ž•+WâìÙ³öãävÚµk‡råÊ[íÚµqõêÕäŠ0H€"‚€R­dÉ’Ýpà …}íQ¥J•Ò§Ní_T¶Ó§OûÚóG"Gª–¿³HûD$@$@~PÁQêÔ»Pº´ßU° Ä-åË—cýúõèÙ³§±H%nApà$@$@C@é©Õ©SÇøä?$@$@$@±AàŽ;î0î;ÏŸ?o hÒ¤IxóÍ7Q¸°çWäcǎŶmÛ’… !Ô¾ùæ#ßy:nÜ8ã^7¹‚?þø#¾øâ {6=ó}ªw¢ŒÀ²e¿g`ñbˆk [·(»ë3ÃÑ|ie”’™}Ýä 9 ‡üÙ|î) D&GE‹Ì1°W$@$@$à'õŒ»u+péÒL†Só“!‹‘ Ä7ñãǺtéß 8z  ˆ! ‚£âÅ‹£P¡BÓ'v„H€H€H å²gÏõ$dÚŋѣGœ;wÎ<•äó÷ßÇ+¯¼’伫ï½÷žxÁO´' <´»Ú9sæ ^zé%‡¤öíÛ;ó€"À¡CÀ’%ÀW_%íÙªUÀðáÀáÃ"i:ÏÄÿÜÅŽÈ_*8JÝšLÒîL'S0)8rGˆçI€H€¢•€N ˜#‚£JÑ: ö›H€H€ÂB@ï¿’§S·Ür *W®–>°Q  °ؽ{·,*ÙŠÇ{Ìzšû$@$@$@"0oÞ<œ8q"ŵÝ|óÍxä‘G|®çµ×^3¼™}øî»ïp×]wAC}—/_ÞîYèØ±cøè£Ð§Oã§7 i¤—W_}½{÷6²ëïŠjÕªaúôéÆ}¯s«D™¡¨7Ú“t1N5ìÇÜ!H! ‹¯G²y/2utiÒ-[jˆë½lÛhÒ"à·Û²åz÷b“€åòÇæ9ª PÁ‘ŠTt䯶oßn¤PpäO“ D-[8µËâáhŽä—5H€H€HÀkS¦L14Ó»‘×Ș‘H€H ÈÌpjÊ„F$@$@$xV[·”Z›6mü©ÃÏ>û ­[·Æ… Œn¬X±+VD¶lÙP®\9h8´;vÀ ½¦™ºwïŽ#F$ÛmõVôùçŸc“ª3ÄvíÚ å¦ mªT©‚%Jâæµk×B½'©—%ÓTðôᇚ‡ü$°¸|MFŽæÏ®^…üš5Ê–µmμñF@7Zü0GW®\–Í×a·lÙ²EÞ¼y¹œßWp±”_ý¡%ó­AÁQ,]pŽ…H€HÀ$pö,°hăß.lÞ|š!ÕL0ü$  / è ÒôéÓãá‡ö²³‘ @p ˜‚£:uê·!ÖN$@$@$6ÍD-¡Þ…tñ‹ŠLS¯F¿þú«yh|¦J•  @­ZµGiÓ¦uÈg¤K—¿ýöºuë]d£¦Â¦eË–›™ÏùSÅHS§NE† œ“xL%péäï\b6Ì|ga&z9d̬_Œˆ£.¨'#ÍûÔS`Ùy@0G[¶lâ‹·ß~»˜”£àÈx±RF=‰‹@OFÁ‘':L# ˆV @â{9s®Á(8ŠÖ É~“ „…€<‡ÀâÅ‹ ±‘®"¥‘ @$PÁQ©R¥?þHèû@$@$@$$*T0@C‡5B¬­[·§OŸ¶·¦‹cšH\¨^xÁðPôã?ÚÓt'W®\ÇÖƒìæë¯¿Æ§Ÿ~Š=zàäÉ“Öd‡}Íûøã£_¿~P±‚Mà€™3m­¨¾ÍYpôÄÿ ¶ô‚!›¿Q oÞ`÷ŒõG+Cp­g¿#€€ ŽªVõØ Ž<âa" @”ÐjW®ÌB–,Y;wnÛ þK$@$@$,õn¤öè£&›—H€H€H ô¦†OQ4   ÀxöÙg¡[(¬E‹òIb>yiê½èùçŸ76‰$‹J7áÔòäÉcˆí5YÅHzÒ“àÈ,Ô±cG< êŽ?þø«W¯6¶}ûöu%GUy¿Ú´iS¯„F¾ŽÍìC£F|bb–ãglЈ}êÈjíÛÕ«CBýYSlû3f@B wß È x$@Á‘G½ «™‚£œ9ÝvCé©QpäH€H î DÔÜæãÕØ¬±ÕÄ(8ò³“ @Œˆæ¹-Ø—fâĉƢ”.]º»)ÖO$@$@±<·éóËyóæA½äË—/€ÔX @¤ˆåù-ÒÙ‡«-[¶Ä¨Q£ìÍ÷îÝûöíO0/¡`Á‚ÆùóçÏcÍš5X¾|9† ‚ƒÚó?ú裸õÖ[íÇÜ!P?òÛøòK`Æ àôiˆ‡N A {wà¾ûBÝ#¶ïR¤X™9sfé#¦èDHê x©ë¼éÓ§ûõ÷S¼xq<ýôÓ^—]²d &L˜}©yàÀ£œx£B®\¹pçw¢uëÖ¨Zµª×õ,ãáöªn¼Ñm•[·n5ÒŠ+æ6H€H€"ƒç6߯G¾3c  %Îm¡¤í][ü±±€¦E‹Þ`.  $B5¿Eì3É$DRvb̘1F¨ì'žx"e±4 @Šp~K>ö’@ýúõñî»ï#-réÒ%|øá‡Æ–1cFäÏŸÿþû/.\¸¤ÆŠ+bèСIÎó ƒ€ ‹4ú_É’°ô×[PyÂC"ÀwmÛB´@îÜ×ópBI E‚£Pv4ÒÚZ¶lfÏžíW·ªU«æ•àh×®]xùå—%d‹Älq²«W¯ŠÚiÓ¦A·zõêdæÌ™rñ°cGHÃ6mnšY·n‘R¡B79xšH€H RpnóýJ¨à(GŽÆæ{i–  6ÎmÁ&ì}ýjû£>† гgϸY¬ä=!æ$ ï {~‹øg’Þ£J6§¾LT1¬z­Õ4  ðàü>öñÖò‹/¾hŠÞzë-XC¥W1æSg&:uÂðáá¢$ xKàòe[˜³2d2eôU¾~ê¦Nµji¤ ÇK”€ßTHT?ˆ/»5m di5 „›G~^U·Ó:¼vïÞíU3?ÿü34fèçŸnx>òªPJ3é7aÙ²kY»v-²dÉ"q#ùçI€H pnóî"ôíkû‘/ÎP†SóŽs‘ @8pn uÇ6ÕK¯zŽ=z´á¦^ÎÒƒ„##‘ €¯‚9¿EÅ3I_yÈ?uêTè˜uѧz”§‘ „ç·ð±Ç–_ýuãÞTïU'Mš$žd¶AC©Y­@FÈÕ‡~·ß~»5‰û$à‘€ äÏ ýûÛÞ%xÊø CÞp(££G‚£p´Ï6I€H€¼'À¹Í;Vº2A"Á n]›w#-EGÞ±c. 5Îm¡&~½½víÚá‹/¾0NÔ©Sǡ֬Y3¤J•êz&î‘ øE ˜ó[¬<“ô¬†ù\¼x1:tè€äˆz['ó‘ øG€ó›ÜX*pÔÓ¡ŠŒt£‘@J,] ñ  h¤„gŸÄo‰ÝT€D#X#k ÅxTáju«WÔ9°b :¡qÃǪï4‹½ýöÛIÄFfrÁ‚1xð`óÐøÔ‡‘`NMM=ÑH€H€"›ç6ï® ŽÆ‡¼8¥àÈ;bÌE$@á#À¹-<ì÷ìÙõÄ[£F ¨ÇÛ àþûï§Ø(<—ƒ­’ Ä `Ío±ôLÒÛË®ÞÔêÓ[bÌG$@Á#Àù-xlY3 @` ¨W¢?žz ¨_?iÝ*4Ú¾èÓÇQl”4'Ï@l àÈëhuë¨îôòåËçG-®‹Ì˜1´'j˜] êÉÔóQõêÕíYþüóOLö„ïPpbàlŽH€R@€s›wðÒ¦$d77¦àÈ;bÌE$@á#À¹-<ì§M›f¸¢ïÕ«*V¬žN°U ˆaÁšßb除7—ÿÌ™3˜8q¢1WÝqÇÞa  àüD¸¬šHÀ+*RŸ/¾ˆ³f¨¿‘\¹€ùó‹ë¢d‰Q£€¿þöïwL×(òôdäÈ„G±M€‚#?®¯õ‡O‘"E nöe¿üò‹CUõ]I#rØjÖ¬épvöìÙÇá8PÁQBBÊ—/ŽæÙ& €8·ùëZÖÍ„YŒ!Õ®á DÎmá¹ S§NE† ФI“ðt€­’ @ŒÖüKÏ$½ùPo|ÇÇ“O>éMvæ! 2ÎoAÌêI€’Pÿ@ž_Ø„EÅŠ=¼÷ðÇ»@… @b¢cÑ,Y€¹s; Š$aøÓyDñF€‚#?®øNý¹fÅôÛ'€¶bÅ {m*dª]»¶ýØÓŽÕÑæ‹ÁQ©R¥Œ‡ÍžúÎ4  ðàÜæû5PÁQîܹ‘Eï0h$@$@G€s[è/‰zë]²d‰!6RÑH€H ð‚5¿ÅÒ3Io¨k8µL™2¡}ûöÞdg  àüdÀ¬žHÀNàÐ!ॗ}ÅÿÆÀÂ…@‰@˜ÀßÇŽ+WBÂÄ®œa6j*d¯’;$×RÇõèý¼Ui]Tý©ȶmÛ†#GŽØk«T©’¨'E>é…©«úD‘Xž={ÖȽuëV/J/‹º%Þ²e Z·n¼FX3 @Àpnó¥,€EÖ¬¶¼*8Ra-H€H 2 pn ýu™>}:®\¹‚–-[†¾q¶H$@qB ó[,=“ôæÏ`ÕªUòi%ºvíŠÌ™3{S„yH€H€‚L€ó[³z ;»îþù×ðèÓ¸ï> M{2wH€|$@Á‘À4»óŸK—.AoT7nÜhl›6m2VÈ”.]ÚxY¹re/^<Ù–Ö­[çÇ——˜iä›°páÂFûZÉÅ‹qâĉày]Ø·Ïœòž{€Ûowè·üùçŸÆƒf;H€H ò pnKþ=js£úì³@ß¾ÇqH–BÜ{ï½Éd  °àÜzìß|ó Ò¥K‡¦M›†¾q¶H$@qB ó[T=“ Àu?~¼Q é&«  àü ¬†H YFMí 6D#H! Žühuí¨‰î¿ÿ~¨ÈÈÙ~ýõW㔆FkÓ¦ zõêåqՌջ‘Ì–-›s•³š.®åÒúü órúôiœ·?ºYç6½ÿÒÅ(á°£¢Ì](~È›4iâñ¾7}c›$@±C`Ïž=ا‹àÄô7¹þÆ7 Æü)Ï$uååË—æ¶ * }úô½Ì>®@¨R¥J@ëee$@$à½gÓ{75}ÏtîÜ9ª‰ú2±<¿éÅÑwnz­Íû7 ëY¦L™¨¿n D* ‹&N˜hsç©R]ï)2_g¬=½¿Ø¾}»QýîÝ»qáÂ…`5Åz#€G>^„ƒÚÖiÑ&[ÃÕ«Wñå—_â§Ÿ~B¿~ýP¯^=—eŽkœ‹ù*8réfB¾íß¿ßøûöÛo½ÑªÚ“º sò‚#Z< ˆ`ú½n~ßi7Up¤/ïâÉâanSoDÎ×zòäÉH›6­×—úš–Öpµj K–,éuyf$ Pøá‡0kÖ,£Y½×Ð…ñbñ0·;vÌðjký£²gÏ–Ëüí·ß¢íV­Z…¥}6J$/^Œ)S¦ƒÕwº° ž,Xó[¤<“Tq´Þ[ç¶aÆ¡`Á‚»Ìúœö‰¡Q£F€ÕÉŠH€H %–/_Ž &U¨V…üñf±>¿éõTA•ŠôÅ»ZÙ²eñÖ[oûü‡H °Nn¾ò»R{èBˆÀ/°m°6Ï4’þŽWÓß÷zïF‹]ùxm­*kkQ}x¯^n–o0 m@úŸÉ\Q¬yõegÏž=¡næ])—oî=YÛsµïœßyu’«2®Îiø·råÊaÒ¤I®’mç¼åÈ‘ÃX-侦 @ø Ü$îj¦M›fžÌ˜1£ý8vâanÓ°£EŠq¸Ö¾^[ÓÑÆv^²Äæáˆ‚#_)2? @( <úè£ÐMíûï¿·‹BÙ‡pµs[žS§N5¼+5kÖ,Õ². p жm[覶hÑ"Œ7Î!=Ö‚5¿EÊ3I}¦š!C† ÎmÊ𔼅ÒgŸ4 ˆúûÙü ½zõjôíÛ7ºÒ>Äúü¦0Ë—/¼yóâõ×_)[6F±L@èÈZ;+4lx}¤â@ ï¿¯Ñ €:u Ï*®§q/4êxÝÔT3ѵkWcŸÿÄ& Ž|¼®Ö8²fQýOÒ­[7¨ D«iHž‰'âÃ?´»xV×ÀÏ?ÿ¼qãììØùæÞWG™3g¶6oÜ<;œä)8ÒjN¦+…TlU­Z5§’ D"ÎmÞ]åÏo‹&j†T+Q¢„w…™‹H€H ¤8·…7ô^V=úÖ¯_ßçÐà¡í)[# è&¬ù-ªžI¦ðnذÁ¨‚£‚dq  Îo„ɪH †h„Iñå!‘ ®oz¼u+ä„ Ylƒ}àGÁ‘žíÞ=†@p($á\ ŽR¥JÕB¼õìO®ïâËA¨«f5ü–?vÿý÷ûS,äe¬?|ЧO´iÓÆe?R§N.]º fÍšh)!Ul¤¶U¾ ‡ ‚W_}Õ¡œsˆ_¼hEfýf¥ÎÌóù<|ØV‹j“ñĉ¨\¹r@šb%$@$@Á%À¹-y¾—/ë×µkÛòªà(¿¨âÍVò¤˜ƒH€"ƒç¶Ð^‡™3gâÂ… Æ}oh[fk$@ñH@#‘HD¬¸\©¬ù-ªžI¦ðž‚£dq ÎoA€Ê*I Š Ì ñˆÓ7·V´(ÄkШdñ“ÛlL —‚#Ò¼ãMÛê~Öj*¾ñ×¢EpÔ]$‘íÛ·7b ª HCñ$g¥K—6¼ 4ÈžUW: ŽÔ¾Õ|g¨1­–={vëa`÷MG.Gk×®5Ú¢à(°ÈY ‹ç¶äÉjœç³g!bZ[^UÒØj4  ˆ$À¹-´—EÆËÂ%´hÑ"´ ³5 ¸"°w/P¥Šm•³¬”P¡òOœY°æ·¨z&™ÂkNÁQ ²8 ç· @e•$žú øûoࡇlrçtÓ×èúY P°`]'#wæ)¼€êÁ)·|›/^Ü+±‘Ù\çμ ì–åX΂¢œNáÉœÓͺÜ}žSßrË‘#‡å(À»*8Ò —Y²$©˜‚£$Hx‚H€"šç¶ä/Ï5-­ˆŒ€#2þ÷ß(Y²dò™ƒH€H ,8·…».Dš7ožx¬ ç{ÚÐõ‚-‘ Ä ýâoýë¯m!V­rU¾|@ùòÀ“OcÆ8¦ÅËQ°æ7çïïˆ~&™Â‹­‚£¶nzõr_–)¾ð4¿EÕ3I߇n/±gÏù»;ŽråÊÙÏq‡H€H º p~‹îëÇÞÇ/¶m–-I“‰ÒN#ˆb©µïgΜ¹%}úô©|ÇÂ… G$&&¶öµ\¼æÎC/R¤ˆÃ±†j³ÚêÕ«­‡÷uE©U TE‚Ú«º;h¦‚£Ò¥“TâÄ ìØ±íÚµK’Æ$@$@±G ¦æ6—GCªé3iÑ󜟫V­ê¡“H€H€¢•@¼Ìm¸>gÏžÅìÙ³Q³fMäÕ%ˆ4 ¸' Î®W¬*WÔs‘³]¾l |ø¡m¿X1`Ð  cG Mç<Oó[T=“LÓÛ<G)€È¢$@$a8¿EØawHÀ‰€.ä]³xäÇõŠÚ¢а! ÷4 è%`ŽvïÞ}ÔŸ!(Pà¼?墵̲e˰eË{÷7nŒ\¹rÙ“Û±–ռŋw(¢¡Yôßô|´iÓ&œ>}3ftÈçê@_~^Ö§6׬~ýúænà?¯^ŽÊŸŒ Gëdæ¸*éôúx쬑H€‚A€s[òTÕ½«®Î®[×–WçÜÂ… Ãypò51 @(pn e[sçÎ5îY[ê²D @\½!~û øë/ GÇ¡Ë8Ã2gv<¯Ž¹o» Ðß×*FÒulÆA­©|^éXw<s~‹šg’)¼Ð¥ ‹“ @p~ TVI@`þ|`ð``Þ< … 4odÍz½cM›^ßç @t0GÑ=„Ðõ~«øs ¾ž¯™®æìÚµ«yèñóÀضm›=Oþÿgï<à´¨®÷ÿЋt齃 U± ˆ‚+6TlØ jl±5¶DšfŒ‰ý£1ö†i ¢¢X.MDÿç™ÙÙwY`û¾å9|sgæÎ-ß;;wÞ™3ç0˜}õêճוú£y…}üñǃí[è~üøñ8ì°ÃòåµBoS ›ŽÞŠ&l-¦z1ÂæÍà›Öí T85‰ ޶Cã &`&”<·ízXôƒè­·B;Û 6@©:ê¨]è&`&`eBÀs[éa~ÏåY×G¥ÇÜ5™@YX¶ |Fê‡Êë'°qcè‘H6‡|̵K™;7|Ù ÇI7ÜœDŸé; ¹¶Ë3,CIÎo)óL²ˆcnƒ£"ôá&`&P<¿•TieD@¯ŽŸ{¸ÿ~`òä𣂡Ck®I46*£æ¹Z0"°“Hê%Tc »ÿþû'´þ7ÞHXßÙÊßè'zÓ¦MÙYvdt¬L;—BµµiÓ&{½ØË—‡Eæáá(28êÞ½{±WëMÀLÀŠŸ€ç¶]3­R SCôéÈ“Ÿæs‡SÛ57ç00²"๭tÈËwĈØgŸ}мyóÒ©Ôµ˜€ ”*ï¿þð‡0´0rãøã×tÈÍã€{î _$äÇØH gôEèX½|8åt0Kz~K‰g’…–+¿ ŽvçóÌ‚x¬ÏU„WMÀLÀŠ™€ç·bêâL èu÷3Ï„a‘/»,ô^Ô»wè§BÞKuÏùå`Ô 0ß^{•B£\… ˜@™°ÁQÐ+Z<|ÊôéÓyAåu"/E/¾øbv®5jà2]óÎ;£C‡Ù{¦M›†ÿþ÷¿Ùë¹kèƒzøðáˆÇ©=ùä“sg+Þõ ËÛÁQãÆÑ¨Q£â­Ó¥™€ ˜€ ”Ïmêpj’½ü+©`àœÛLÀJ‘€ç¶’‡ý%c()Äøjz¿2dHÉWèLÀJÀ–-€¾¯;î80Œ0pÓMÀÊ•À°aÀÃ_}è;´×_®¿èÚµÔš–ñ•ôü–Ï$‹xÈਫOÚ"Rôá&`&P¼<¿/O—f¥A@^JÏ<3ôZú÷¿Œ¶„MVhå»ï,þúW€þ1,&`@ÀGäsÏ=7áˆßýîwøýïO7Ò¶G+óiÌù矅G‹DBõêÕ‹V·[æÓvçwâ?ÿù£˜Ñ]L/^Ì>ÃèÆ:|ù©]íÛ·¶Å²rGê£<;œZñ#w‰&`&P’<·åŸn4çÚÃQþ™9§ ˜€ ”Ïm%C]Þu/çgŠ=ùqܸqAˆqý¾µ˜€ ¤~dP$/F/¿¾0ø÷¿Á¿ùÐÛ#)Zʈ@IÏoIÿL²Ü—.]Š+V K—.E(Å‡š€ ˜€ ”Ïo%AÕeš@ñࣀ©Pxåà㾪ÆúõÀœ9À˜1á uë&d÷Š ˜@š¨˜æý+öîwÞyt7ƒR^I³äß|ê"/DòL´çž{¢jÕªøöÛo!H?ýôS”-XvëÖm—AƒÞ¾®§;òÜu×]xâ‰' Pe*Ò¤I˜?~°?ú¯bÅŠ¸ýöÛQ©R¥hSÉ,õĉ?ÒQ½zBù3gÎ <-Ùà(‹WLÀL é xnÛñÉ^xÞ<0T) +28jÒ¤ äÍÏb&`&¼<·ïØè7éc=FO'7ѳÉrôíÛ nÜâåìÒL ðVO> ôë´h‘ -râJz~Kúg’qLË»‘ÄGçì&`&P <¿•dWaϧ4@IDAT… À>ÇSFTÇĉ‰}tâº×LÀ2—@‘ ŽæÐdQ_ˆUrÇi-jy%y¼<é!ë‡~˜]Í&¬Ô×èÇköŽXB7MW^y%*W®ÛšwR†C2VÒW£‘,\¸Ò¼¤ZµjxðÁ±÷Þ{çµ»x·ÉtµaÃíÊœ2eJ°ÍGÛ¡ñ0Hz?·í`„hK F;Å 7wܱ uzÈ!‡ì ·7›€ ˜€ $ÏmÅ3_|ñô[62º•÷Ý3Î8£x w)&`eJ@_*ë[7…CˆË©§Æ×œN6%=¿%õ3É" ÆWŠH±ÁQ úP0%°møþ§2#]ìúýQ‰6¤Œ ÷üVFà]­ ì€À7ß„!Ð×Î9X·à«h‹ ˜€ lG€—‰ CtÕbŽåÊ•;dË–-·ÒÀ(ÁeÏ“üìé™gžÙy!ùØ+@©"2Ò×cÇŽÅ<„ÛYÛ5j„{î¹'ø tgùâûvÛm7(ÛC=„Çk×®ïNHï»ï¾¸öÚk!ïIe)68*Kú®ÛLÀŠFÀs[Þü¦N ·wí èõ~α×^{åÙ[MÀLÀ’Š€ç¶â…P“Áíu×]‡[n¹5jÔ(ž‚]Š ˜@±ЋJ}8w.è¼oêÔÉ»š÷ßÎ>X´( “æ[ܼ9%ãÖ’žßRñ™d~Æ)úHÔGù¡å<&`¥EàÅÑ£ÚøCÏ ~þyOì»/Be x~ËÀAw—ËœÀš5€~ðu7ä±hàÀœ&í±pÿýÀ±ÇíÛçlwÊLÀrØ¡ÁQ»víÚÓÈè–òå˟ƃ‚|Lß•»€mzš‘¡2`ÀH?ûì3(œØ<Æ\Q˜³zõêñâÛ>Pr ®e)‘7.»ì2(~í›o¾<äýþûeM›6¥kë¼øDW½M‘ÁQ•*UЩS§$h›`&`&PžÛ©}÷]J­GàÓO?v:|L"#¯™€ ˜@²ðÜVøR(µÉ“'ãÀĽ÷Þ[ø‚|¤ ˜@±øñGà¹ç—“ ,##Ý»®_ŸS•Eué~Ü|3ЪU¸OòøÝ=kÿúWh˜”s”S©B $ç·T{&™Ÿ1“ÁQZà)D¶ÅLÀJ‹€æ\ÍÓ2&Rà‹#ŽH¬YGúžŸ¯”½¼Fý@c`Nò,žß2xðÝõR! ß #F„žNÇŒ?° «­T)ÑàH[ó›pŸÿ70ÈËà¨BÇŽÿ]NÍkÿÎÊ+ð>¨¤ú‹;y:(IoÕ«WÇ!C-0àR<@G2~ª(ÿz00”&à¹-¾k®.¾àTLσ68Jé“Ú7ÈxžÛ ~ èÚ5üä1Õ³¼ç>Â’›¿{ Œˆ6n Û©{Ué‹äÖ­6m—š'&> Üv[NŸdˆ¤—›zñ©¼–Ô&P’ó[ª<“ÌÏÊàÈÞòCÊyLÀŠ“À#„Ï•Tf¿~ÛÝÅOüÿoãš7kýüó…øÝïægR¶,Ïo);tnxPdÙÿþ742¢ã@øzz64èÜ9 î&™€ ¤Ë Ôà—ÿcË*lë«1€ã:r܉È5â…^ˆý÷ßÝ»wç>á°¤4+V0¾ðBzè¡)Ý7ÞLÀLÀrˆ"ÇÈ£aýúõƒ¹óxÝLÀLÀÒ‘ÀçŸÛØ6ÇÕ}*[¶«W'ª< ÉHˆÎ²Q·nþÛAgc ìl‘÷Í㎠Ãrаaö®„#"BgÙô˜°‹Þ©×½féL`ùòåX¶lC‚0&ˆÅLÀJˆÀ—_†žãsöW\¾ËÛ£`Û¶%Ôk&ñ6o^}xðA`̘G£F`TÐÈè°Ã€ÝvËxL`&P  ŽdlÄÐ_;26ZBwêYßNí¸æwÞy'Ø9gÎD:räH,Y²$û |º²råJºˆÜ;{›©M@Þ$=ôÔËb&`&`iF` ßM¥ÿëþýû§YÏÜ00Ø1…S“ôêÕkÇ™¼ÇL O2ð¡}CžRµ*èŸà0dažY°`AøòÓOg•Î@Ž¥Ÿ}6ïãòÚšÛØ(¯<ÞféL@Þ$öp”Σ쾙@Éáï¼yÀŒ¡!ñÚµÀ/¿Ñ’A1jŠxï=@ÆÀ‘ì¹'ð—¿Dk^š€ ˜@éøíoÁÐè¡WÓ3Άòvj10â$mpÄ0j|Ì‘èÙh…Hosû£3fÌxKÚC& ÷'nàZ#šHJåÁHrÕUWá¾ûîÃÿþ'çI¡<Í'& ½uÓM7E›¼La68JáÁsÓMÀLÀvI`úôé|˜ô‹CÊì’”3˜€ ˜€ ¤y8ªAW:tH§n¹/&P*†Ö¯jÕj×—JËÑŒˆžz*ÔŽóÏÎ9ô¦™Ó4…A»óN`÷Ýù0n»§q9ùœ2Ø5íš‘s˜€ lO@ßÐÅÏóùH(00Ú>GΖ:uÀ¨@³f9Ûœ20²$pöÙ@ÍšáG;òˆZ–ísÝ&`éC 08bx^rð§x·dlD¹pæÌ™ÿŠo/LZ(o¿ývÞœ…o¼1½¥rþýï_–'?Ж”&)DžÅLÀLÀÒÀøñÀ¬YÀ ')“#ê>˜€ ˜€ ”€<õìÙ“¡œb±œ Zˆó›@†xàwü¢‹€o¿þÅ'n|4†ë®öÙ' µuÞy@Ÿ>Àᇕ*E[½4( Èà¨k×®…9Üǘ€ ¤9¥K—_=h×.§³2f z»tùèÜ9 ‰Z½z†(¾lÚ4ô"’s´S&`&Pòäíuº ùóŸ¿ÿ=¼VEµêšuóÍÑš—&`&Prƒ£ºuëÒ‘3jDÕÐЈ—(œ7kÖ¬'¢mű܇OOþÎ+Þñdžg мãŽ;øPe4Õ™%ù lØúñ80|›Õâ/ ¸yóæ¨W¯^ò÷Á-400|ÐË}Y®—<Ÿ}öYpDïÞ½óq¤³˜€ ˜€ ˜@êøî»ï°bÅ ‡SKý¡tJ˜À¦MÀÕW'´ãðhy5¡S'Ð8p÷ÝÀÛô->`@b®V­©ÅL èdpT“ŸøëÙ¥ÅLÀâ.¹xøað}øÑÊL dpÔ¥K—üev.0´$ a…FË-òÂïãñÌ3¡qîý^70d!°mÛö-9í´Ð‹¿ B4oŸÃ[LÀL ä ”o×®] ¯ŠëÄ׋;}ÅW/í¢r_}õÕlGÑ6/“”À?† “?Ñ,‘·ªeË–¡I“&Ñ&/MÀLÀL ¥ èË6:ïƒ"…ò¾_|ñìÝ(¥‡Ô70( ˜³g$~{ÅлÀµ×ÿùOF"p§M é ¬Zµ ßÓ:ÐGI?Tn  ;ùóCïE2(Ú}w _¿Ð“Q¼¢Ë/^xüHž!@²c€Äs8m&`eG`Ý:à•W€aÀ-­ÇåÄ»î7ŽouÚLÀJ—@yz7ÚZ.Ví„Ù³g‡qCb‹3)Çw\v‘K–,Áĉ³×Hbòp$Ñz–,eã-[¶8,^ÄK00”'0{6@'ŒÁ½>â矶ÁQʪ;`&`&P28ªR¥ öØc‚æ¼&VU^! .¸ ¼/|â‰Äîõé|û-ðÿT¨¸Ïk&`ÉA@Þ$68JŽñp+L $ lÞ (0à 7ݺ…¡I/¾1èѸê*@s»ÅLÀ’Àúõ€B>6hzaÓÇ òù°hQ²·Üí3ÈDikÔ4WÇyKVòÒ¾}û„J&Mš„¾}û&lóJˆ<Å Ž/^4ÔŽ’p¼Ü$00BP85‰<}öYh‡mG!ÿo&`&&OžÌ5ÝP©R¥Ìè°{iYªàƒ€§Ÿž{ s”@ôEq^/)]Þ§Ž $7%÷ø¸u&°+kÖüÞ?üìµ P¤‘hŽ~þùÐãÇøñÀ»ïæÌÛòöqÎ9À‘G‡ Ô®å¥ ˜€ $7…m–g¶?öÙ8õTà„ÿîHîqsëL “ Tdç›Å0<M–¼´mÛ6¡’tÇhI~yÉ-±ÄGÉ?|n¡ ˜€ ˜@þDGúî©§'ƒ²—žlYLÀLÀL È ±~çsÌ1Ð[wÑBÓ¦Ï<ü÷¿Àwß…ÛzöÎ88å ys“2HE68JÅQs›3‘€ŒzÞ¾ZµœÞ˸n]@ž‹$ò*رc˜Öÿ¼eÅ…†ëåËò<(££Ž½T q=rsÊLÀ’–€¾{=öØÐ“ÑM7…áÒ|-KÚárÃLÀ²Èà(ÁÃ=•ŠÁQ»víAa¹,)@`'GM›&œJ)Ð7ÑLÀLÀò& ƒ£Š¼KR…”©Y³&:tèwfo5004# ¹OÒ«W¯4ë™»c‰ÆŒž@. ÷éËa…b‘¡Q×®‰ù½f&zdpT½zu´jÕ*õï›@šX·xûíÐK‘žÝsOB(ê¶^²+¤PÕª@Æ¡ñQ´OKÍÙšÃåSs¶BYLÀL U È»êÙg2¶ÔGòld10T ƒ£Z¹º<×úNW‡Ž¡C‡fçÙ=j+{c‰:uê0¾}lÙ²%Ø»lÙ²3-ÉO ƒ#‡TKþas MÀLÀòO€·(˜7/üŠdŸ„­\¹Ò/\óÏ9MÀLÀÒ€€<é¡îÝ»§AoÜFŽ ¿~ôQðÜÎ!rÞyÀé§-ZälsÊL }èùó‚ pÐA¥O§ÜH1³gcdžFF24âŸd 22êÛ8é$àĺ4ņÕÍ5(¿ý-¼ÊcÛ³Ï&~àpÙeÀC…FF26r0™ÀuV0¤ PqÛ¶mKã_xp½T³ü®da¨«`¼–ä' qÓŒ¨Ï²DG•è·4¿Þ­¢ã¼400d$0mZ躶G0œšÚ¸×^{%cSÝ&00(28êÒ¥ úñ·ŸÅR˜ÀæÍáƒû/¾ .¸Øÿœ9ôJ §L  È»‘DsšÅL älÝ ¬ZÔ«—XÇùç=n“‘þ/½4 p´DZ^3HW2´¼é&@×J] ¥qÑG 1)£#ÿ“qÚL UÈÃQ–MyØdÎÔ?Jº_}õUB6VIÀ‘¼+28ª_?¡} ©Ö¤I»&N â00T%0ujØr9u7îó`Å!eRu4Ýn00‚g¿ytõ7lذ‚êü&t*ò©—B´ üú×@ëÖI×D7ÈL  Øà¨áºh ÷Þ®¹˜1#4ð7.K¿~@µj¡q‘ ŒÙxÍL s´k†‘Ô‡ôݰôî†yÞn‡7˜€ ˜@ŠÁÑ»¹ÚzXëÖ­ëð#mÒKNF•PxçÎÖ½’¤–/]%4NŽš7ož°Í+&`&`&ªøž5x &ƒ£¿üås:õ«ß§¤êhºÝ&`&`%0yòäàÛ”œó—90yçð!¾ Œ^=±%ÿ(ñOêëóš ˜@ò°ÁQòŒ…[’š¶m>ù$œ[Mª¹6yâPXúƒ |£íÑò쳩ÅLÀ2…ÀÚµÀ[oC†$öXF—0HWgÍš5»C‡ßгÑê$—Uëv&¯(©N+œÚèÑ£Š?à€Ö½’¤äá¨eËìÆ1–.]Š>}údosÂLÀLÀR™À7×_”/†TëNË£ *¤r—Üv00È7…S“Øà(ßÈœ±èQÃĉ:ï@Ê».! C"…iY¸0Ì_¥ 0hЮu0Ì! ƒ#…mÛ¶mætÚ=5"ÐËò‘#×^Þx|öذ!0{6ЩSNýûsæä¬;e&`™H`Ö,ð7 ?º~ê·Í¤Iáo›Läá>›€ dÀF#ÏÒÐèwQ÷™¾„FHÿ9sæÇѶâ\Þ{ï½X«;×,©[·.ºuë­z™¬¶l ƒ1Ç<ýðÃؼy3š6mš¬­v»LÀLÀL Àdl´€¶—-[†“O>¹ÀÇû00HUòpÄgèÑ£GªvÁíN1/½Þozä —˜Ó§ï¸S¦È%ðÌ3À† aˆ´+¯;, ×BÇ”0È& ƒ£N¼°”×<‹ ˜@ž6m>ýxÿýðeùG…s¬2ï¹'pî¹À1Çûî~˜•g!Þh&`D`õjàå—Ãk¦ ø9þŒæïhàÎ;ž=3ˆ»j&ñƒ£U«Vý‰F?ÃùP±Q‘ŠLhÓ¦M¿¹sç~[œ”žáS¡W_}5¡ÈsÎ9Çžˆ$éŠbÌÈjÌàHáÔ$Mòó b’vËÍ200¼ØÃC^T¼ÍLÀL Ý hþkß¾=jÕª•î]uÿÊ€À´iàù†¯ªßgàØcÌÛ»‘<'|ùehh9Ë–G…«® ³ADÒK08}ìúÝwßaèСñÍN›€ dÐ sýy|ð°fM¸±F `à@àˆ#B#£Ö­ËLÀL "°dIø›DžVu •té\zixíTØ´ØëÓ0ƒÿ70 -_¾üçzõêÝÊþ>ësýŠ+Žm×®ÝÙ³gÏ~;¶½PÉuëÖáᇦËk^‰c¢‡˜§Ÿ~zl‹“IK`ÅŠ°i±ÓGI;Zn˜ ˜€ ˜@ Øà¨ˆ}¸ ˜€ ˜@ÊÐËÙ3fओNJ¹¶»ÁÉMà—_€Ûoþô'à…BC¡¨ÅÍ›/¾­%.õ͓¤͛TªœqFhh¤Ðk0Ø覅^ý±÷Þ{ï,›÷™@Æ'#Í¥‘ȶü›o€½ö çZÉ8ž'Êë¥ ˜€ d:Ë.þõ¯ÐœŒŒ®¾8ê( qãL'ãþ›€ ˜ *þ‹aÔ£g£#0òxD—³orû#[·n½Ÿ†G³¢}ù]® ‘ÊSO=…§Ÿ~ô¤´Ýa¿ýíoQC¦ó–ä'б#°qcèç<«µ‘Á‘Cª%ÿð¹…&`&`»&ðÚkÀìÙÀS³£Ÿ´uíÚu×:‡ ˜€ ˜€ ¤Í}üí^½z¥AoÜ…d!ðÖ[À%—„FC}úmÛæ¿e ›vþù¡³åóÎËÛRþKsN0L"ð¾âCQÊŠÂbJ`æLàñÇCÃ^y3ºãŽD³ø¶§B…Äm^30Øž€<ÁÉ@óúëCp Ÿf10 dqu+¿ú«¡†44¢sêP˜Öeó"]Hã÷˜~ƒù>árr˜#ç=˜\¶l-Z„Å‹ã“O>aË—i£B#• Ô¬ <ð@n  !ЪVn¾9zã6˜€ ¤íN/í=zôHµ¦»½&oòÈh¸7. ïsÛm‰‡¾Í¸÷Ü4k~ô¸Ok66Úž‰·˜€ ˜€Â@wë–È|P¥Jâ6¯™€ ˜€ „âG˜5kÖ†Ö­[æ×üÿ£Ñ¯â² ã6yA’KÚ-üêq3C±ñÁQMüüóÏX§I›7o޶ÃôQô5wË-·ìp¿w¤ÈÑ ŽRc¼ÜJ00 cÈ¡Ÿ^n}÷Ýwöð°s\Þk&`&f"ƒ#{8J³-Åî(\‹Â³Œ Üy'èé8þxào _v–bS\• ˜@øé§Ÿh„ñ9¯?Ç#ü–6ƒa¸ëiG@së»ïo¾ È héÒ°‹z~ë­à9ŸÓe…ûQTÁýöKÜž“Ã)00§Â<ËHs2ÝmLŸtèÃÆÆF9,œ20Ü Ž´sÞ¼y¼eÅíÛ·¿Ž^îbz»<ÊÇk~ùå©Vó-+VÄ 7Ü€3Ï<3ßÇ8còÁ‘Æ´AƒÉÛH·ÌLÀLÀòIà¸ã€ºu5ô“«P°­ZµÊç‘Îf&`&`©O@/gåݯ~ýú©ß÷ Ôðû³À“Ñ__~FbWå<•ðZS\‘ ˜€ ÆŒƒ-[¶`РA&b)O`ùr`Ò$0šDhÐ;ax~‡Ý’Ž³ÏæâüL|=¶7*RÓ‚„2MyXî€ ˜€ €|dÌŸ†ƒÎË+\Šö¡&`&Öò4&b·ÑÛѽ4:zFG·Ð›Ñ`•/ }Mr衇âÒK/Eç΋R”M" ©Ö¨Q#ð ‡ÈPE¿ÙÚg10Ò& pj•6y×Wœ&NN=Uˆç”ª¥ÇÞ¯ñ‹ñ#€æÍsö9e&`&Pxò÷ôÓ@Ë–à8…/ÇGš€ ˜@&Ø‘ÁQÀ‚FGŒŒãÛ¶mÛ^l®`ZOÛ;óù_3îׯ-íϦ5=Mê-iE@ŽN-­†Ô10 …S“Øà(ÀàÿLÀLÀ2€À—tM³‰ñ°zËšÄb¹ i³Â \}N}Äo‘P«VÎ6§LÀL , Èà¨9-1:Äc¡”eƒ\· ì„,¡Ñ?ˆ{ÔhÚ44Ü•£>}BíÙ¨Ti'…y— ˜€ ˜À. èºû׿×]—xMõOá]¢s0È“ÀN Ž¢#æÌ™3“éË´Þ±cÇfôxt µ¿R¹rå 9²uëVÔáçl‘Ò;o„û@G–ô%°dÉôÔ/‹ ˜€ ˜€ ¤¥Ñ`º+&`&`ù" pj’^rOc1\ j×úö•Ç\;¹jc£í™x‹ ˜@ÙгJyì;묳ʦ®Õ @`Ø0à¹ç:š –'”s°¼l(T©ÅLÀL ø¼ö_vóm÷‚@ãÆÀyç_Ù.ÉLÀ2•@¾ Žâpf̘±ˆëÏHgΜقËñýNgå ½qãF{8Êœ!wOMÀL cØà(c†Ú50È"0yòä eG™}Jð[2üïÀÉ'cOŒ†Ïl.î½ ˜@ê5jTÐX‡SK1Ë”–þôSh¼ïoåÊÀÇ.ãûœ60(>sæ×^ ¼ôè8øç?sÏ-¾ò]’ ˜€ d2Øã£LÆà¾†€Â©IR­0ô|Œ ˜€ ˜@²C‡cŽî¸# ©VŽÁ»å†ßb&`&`™@@Ž6lh/Å™0Ø;èã{ï×\L ¬^ \|ñ2z³ ˜€ $1…S“ 80‰[é¦e~§‹>^xõUð> ?>±çÿúWâº×LÀLÀŠÀwßÏ?zûôÓ°\}X¡pjònd10(68*ŽYJdpÔT¥-&`&`&Âôô‹/€þýÃNÈÑ j«T©’½rÓMÀLÀL ¶lÙB#“© ¸Y–Œ!°iðÁá‹P½ =¨V ¸é&àôÓ3ƒ;j&fäá¨S§N6 M³qM…îh^Õ íÑ£C0X·.ly ƉØk/`Û6€ß6YLÀLÀJˆÀüù9FFŸ|V¢ÐÐgž œ}¶ ’K¨bk&`LÀG<øEíúâÅ‹ƒ"ìᨨ$}¼ ˜€ ˜@YЗü’îÝÃ¥ ŽÚ´i®ø00HsÓ¦Mã ±up8µ4hvOá\FŒŒÞ~;\W¯[µ.¿<ôp¤—¢0HEs/eÞ¼y¸ä’KR±ùnsŠXº;àmôR[Þ‹Ö® ;Q½:pÀÀÁGÈ£²ÅLÀL d ¼ñp챿§A­Z¡‘ÑI'¿ú –00’!`ƒ£’ᚥFŽlp”ÃíNš€ ˜@Zˆm¤ßó¥|rxÐA¥uŸÝ900ˆÈ„ÄŽ""é¹|òIàê« ½+ì³0xpR¶[·ôì³{e&Y¢pjƒ Ê¬Ž»·%J@^‰¾ýèÜ9±šqã€SN ·ÉCàþû‡Fz”°ï¾@¥J‰ù½f&`&P²däy Àg„FFv\_²¼]º ˜€ Dlp‘ð²ÀlpT`d>ÀLÀL I Èà¨|y`Ï=y7ÚÆ'Š­ô©¿ÅLÀLÀ2€€^ÐVæ'ŸýúõË€Þff{ 8ÿ| qcàŸÿŽ;hÔ(3Y¸×&`éK@´åùÃî Y|XL ˆ~ù8çœ0<ÚòåÀ’%@Æ9…*$ûÓO2Ú•1’ ŒrØ8e&`%M`Íàûïrj’w¹çžËYwÊLÀL tØà¨t8§e- ©¦ñü”2-Ç×20L"0e о= ¦28’Øà(“Î÷ÕLÀ2—À¦M›0ŽŸè÷íÛ—ó 'BKZÐW¾Œ4„k¯êÔIË.ºS&`N@Èà¨gÏž¨W¯^†Óp÷ C€·D FCº-úøc eKàì³­[K•ïi§%nóš ˜€ ˜@É cúàŠ»î zÒ¤Ð{kÉÖêÒMÀŠB`Ù²e uÈX‡–´%`ƒ£´Ú’ï˜<5äg*T(ùÊ\ƒ ˜€ ˜€ ”uë€Y³€ã+°ÁQ v±&`&`IIàc¾I[ÃÏC~&)‡§ÐÚ¼¨{â£pwß]èâ|  ˜€ $=/¿ü?üðÎ:묤o«˜<. ½)쨼ÿåž+JÍ!y’g¼Ü0àt+¯š5†½ÔÛàÈg… $éÓ§ãÃ?ÌÖÙ³g3²CKXÒ–@ìñSÚöÑ+!28jÒ¤I •îbMÀLÀL t|õhatïÖgƒ£ÒáîZLÀLÀ’ƒÀÈ‘#ƒ†rÈ!ÉÑ ·¢Ðè„ø0~|XÄ'Ÿ$º`h&`)@@Þ$LÖº‰eI`Õ*àå—§žÆŒ =Õ¯T«¶}«ll´=o10²$л7ðÒKÀá‡U«–eK\· d&}þùçXÎx³+W®ÌÖU¼ÁZ±b¦M›ì‹èt`ÜÃO<sçÎ6y™†lp”†ƒZZ]’ÁQ—.]J«:×c&`&`%B`êÔ°Ø=ÂedpÔR~Ó-&`&`&æÞÿ}ÔªU {ï½wš÷4ý»W©ðàƒ€B¼ôï,]~ù›þ=wMÀLÐ|V‰ÂþºZL Ÿ^{ xöYàw…ä‘1Ñ 'gž qDb8µ\‡{ÕLÀL  Lž |öpþù‰•Ë#ÅL ä ų̈Oø%Óĉ³U†FyIùòåQ»vmÈÀhذa8à€Я_¿ RÒ,†—¸ð ó:ÌÛÒ„€ ŽÒd K»²Z\¿~½=•6x×g&`&Pì¦L ‹Œ{8ªW¯jÖ¬Yìu¹@00H& ¥¦jGð-[Åxü­djd†µå»ï€ôå a®¸<8'Wƒ€Ž·Ít§LÀ2ƒÀº¬;v,öÛo?ì¶Ûn™Ñi÷r—øø:0.zþyàÍ7ÁgÙ¡ç¿Aƒ€SN êש³ËbœÁLÀL ” ȽB\Þy'P¹20dàëu)‚«K{zÇÿ-úôLHFä(·.Y²[·n XTæcÏž=qúé§£OŸ>}@ݺu©>d+W®\Ússó&`ƒ£¼¹xë.èâ#qHµ]€òn00¤' G¼FëÖaSåá¨U«VIßn7ÐLÀLÀŠJ`ܸqØ´iéÍ›%)ÜtðÌ3á‹Ð»îÚµËi–>$¼åàÑGmÛ€L48RNåðrÊL sLš4 «W¯v8µÌò„žjNœ1èØ|Ñ•³K¡EO=à÷8è pn•G#…O³˜€ ˜€ $'9s€3Î>ú4nþýo%çH¹U©F`Á‚ü»ú(Ð &`2]ˆéyP\ô!š ˆô1¶ÞÈsè¾ûîõ÷æWQUk6ŽËéÅ`8™‘ÁQÓ¦Mósš€ ˜€ ˜@ÁQ·naÃd±¿hÑ¢ÀZ? ›ê&™€ ˜€ ˜@±Pø‰ ŽŠk¾ {ùåÐãÂ#ä¼ ½ñFð¥9ð¿ÿ/¾\tpà €¼3Ü~;°jUhhô—¿½zå»*g40´&àù,­‡w‡Û¼¸ÿ~àÿæÏ­#ÁPwŸ}€ÇŽ: hÔh‡Åx‡ ˜€ ˜@’qѯ Ð/®¹&ôr$G0]X¸paöLáË/^x-Ò2Joذ!»ú´¾>üðñÿþûÚºuëÀÈH^Š,&P68* 5\ „ÁŽ|2˜€ ˜€ ¤2ñ_}µæ³°26’e¿=¥ò¨ºí&`&`ù%0räH4nÜ]»vÍï!ÎWLx¸ê*@aÐø\-Z„ï¹'ðúëÀ×_<ø`¨Ú+Œ2N:é¤bj„‹104! ƒ#…RSH5KæP4Xy”á‘~×ç~)Íôqî¹™ÃÃ=50T% ˜^¼ðм9ðê«ÀÁ§joÜn(y2R8´‰'‹´”ÁQ\*T¨€† ïñõÌGï;ö¡5vß¾}Ñ¡C‡xV§M ÈlpTd„™Y@äáÈG™9þîµ ˜€ ¤ J•€›oÎé©Ilp”ÃÄ)00ô$°lÙ2L›6 §vZzv0‰{µe ðÚkaè—·ÞÊ16Š7™žËA/ç¤ý |(üæ7@Õªñ\N›€ ˜€ ¬_¿ž×Ë ™u*éž%ílÜÌž p¨·óî÷Ê+áËi}Ú »;d&!äÉUbðPœ|2ðÏ‚!2¤óî¦ À6Æ‘½ï¾ûð»ßýëÖ­ Ž–aÑžüré裼)­w÷26Ò>‹ ”•å4¬#28rHµ4\wÉLÀ2˜€ Ž2xðÝu0È0ò¡‡U‡rH†õ¼ô»+Š’èe¨žù)\#¹îòaúñÇR‹ ˜€ ˜@Þdl$££æÁ[SŠÀܹÀ;ï3fß~.µMƺ ‹¦ÐiqOFmÚ¤T÷ÜX00,}~P¡e:€Â© f<&`;" Ðhgžy&F…Î;i…DëÓ§jÔ¨±£Ã¼ÝJ…€ ŽJsúU¢ [¹råøC¿ô,&`&`&&lp”&én˜€ ˜€ ì’€ Ž$ƒ Úe^g( €1c€O>>ýøâ àÙgcÍ)§v휴S&`&`…'0zôèà`Ïg…g˜ GN™Üs O2.’È«_ûöáüÙ©ør-g_˜Ãÿ›€ ˜€ ¤*K/¾ü¸üràÖ[ÝwOÕž¸Ý&°s[ù¥Ñ¤I“‚hK–,téÒ¥ÁRéü1svñÅã˜cŽAEÅŒÍ%¯Ð¥ãùçŸä>|8þøÇ?¢Zµj¹ryÕÊŽÀögmÙµÅ5§y8ª_¿¾]§Ð˜¹©&`&`»&`ƒ£]3r00ô ƒ£Ž;¢E‹éÑ¡2ìÅ/¿„Fï¾ H¿ù&§1 Ȩ ¨Y3g›S&`&`ÅG`êÔ©ÁóÉnݺ_¡.©ÔŒ½ývXå¯~\r  álÕ (_¾ÔšâŠLÀLÀJ‘Àc^Y€J±RWe¥D`6cÁ¾÷Þ{9rdà‘håÊ• 5+ °Bž5nÜ­[·† èßåÃE’a‘TÏj6í*Æ|øá‡ƒwò¯¾ú*œP–WL Øà(F!Û ƒ#‡SKÁs“MÀLÀvJ@GÕ«WnàwšÑ;MÀLÀL … Ì™3sŸD_ÆY G`Íàÿý?€âÃÃrš7Î; Uì·øð°påû(00üøê«¯Z½¸±¤Y³€ƒŠN9¸á gÏÔêƒ[k&`&°s6<þFâ#×léÕ+;é„ ¤ <©uÿ¹lÙ²Àã<­X±"HkÛÇ0Pä zõêQ„¢ŽËÓÑc´Â{ôÑGqÇwàî»ïÆQG…™3gòƒ¦oø|á<ùä“hÒ¤Itˆ—&Tlp”TÑ:‘Á‘.Ž00H'28j¥Ï(-&`&`&Æô•Äág ?Èýú ÿ¢‡æò`tØa€¼2ì±GáËô‘&`&`#°~ýúà…Î!C v s—mÛ€o¿&L½XÄ'+\Úƒ†óg»v¥Ö$Wd&`&PJž{¸î:€[±y3è©¥”*v5&PŒähod>ä—FÒO7]FG;’ö¼ÁÑÇ]22:˜–ÕuêÔÙQÖìíòttóÍ7ãÆoÄ[o½x41bD^í¾ûîÃo~ó›¥ì0$!`ƒ£$ˆTjÆêÕ«±víZ[R¦Ò ¹­&`&`ù"0þ|xàùÊëL&`&`&ªN­ÊLÀL hôÅ÷Ö­[ѵk×¢ä£KŒÀÕWùKXü¹ç‚°&V¥ði00ô$0y2ðóÏÀý÷‡á2Ó³—îU*PȲÏ?ÿK—. ¼ɸHÞŠ¢å×_ é6YPSj×®Ò›ñ~A ÝwßRy,ŠÒ•+W.4=§‘g#éÂ… éIy#Ú¶m[èò|  ”•é4ªGÞ$vÝ–Fƒê®˜€ ˜€ nPá›C{8òÉ`&`&Îô lÔ¨QèEöz(fÙ1=S7xùeàO C¾D¹O?=Jyi&`&PVÎBÒ¥K—²jBÆ×«üGÆŒ/Ã}$"9üðpþìÛw@‹ ˜€ ˜@æ¸é&àúëA/™Óg÷4¹ (äÙøñã³½ÉØhÓ¦My6º\¹rhÑ¢†Ê{˜~î¹çžÁÇ[yPÌ~Íb©BÀG©2RIÔÎÅúõHiÚ´iµÊM100¢P85‰ ŽŠÆÑG›€ ˜€ $7)Œ¶|ùrœwÞyÉÝÐ2nž9vë†QS­Ç/JËxP\½ ˜€ ä"ÙÃQ.0%¼úÃÀo¯¿¼û.è ?¬°n]€ŽP­ZNnTj10H_òüz÷ÝÀqÇ}úäô³fÍœ´S&PZäýrÁ‚˜={6æÌ™,•ž:u*ü2Îk–È#ÑG¾´ŠÖû€º¼‘‘êÃ,- ­B… Qv/MÀvBÀG;ã]y°‡£¼¹x« ˜€ ˜@j°ÁQjŸ[o&`&? §&4hPþÈÐ\•*!ç‡æçœtꔡ Üm0Hb qQ‰ìöíÛ'q+Ó£iŒê§ž^{ øøc0”ø.4Æ=æà°ÃÀÐv‰ÞÓ£çî… ˜€ ˜Àμú*pÅ€¾ã”¯‚ÿ÷ÿv–ÛûL ø Ìš5+ðZ4aÂHg̘„"‹×¤Pe M6lذloE;w†¼YLÀŠNÀGEg˜q%Øà(ã†Ü60Œ `ƒ£ŒfwÒLÀ2žÀÈ‘#Q¥J•à![ÆÃÈðüó?á®»‰üã‰ë^30H.òpÔ±cÇÀè(¹Z–­QhQÞ6ࡇBoF[¶µk'ÈȈNè =úê^˜€ ˜€ ŒÇàòËCwšþö7`øð‚•áÜ&_›7o†ÞM/Z´(Py,ú裣äz1Kä©èpÆsm×®] 22RºuëÖ¨\¹r”ÍK0b&`ƒ£bš ÅEG©– £í>š€ ˜@æ°ÁQ挵{j&`™J`ã„}ðÁËðjñx' „>â²Ë€÷ÞèM¿ù è:=Ca¸Û&`&bÖ¯_¹sç2ä%c^ZJ„À²eÀÑG|LJ#.¾8ôd$/€00Ì%ð׿7Üp*Æ™g÷Ý4j”¹<Üóâ% 0h£GƘ1c o–‹é:KFE •—Š+¢gÏž:t(8à€@›5kÏâ´ ˜@)°ÁQ)N§jtq—4nÜ8ºå¾˜€ ˜€ d8释 j3üDp÷MÀL è Àµk×âCIã^îºk¿üÜ}7pÿým°pî¹À½÷ÚØh×äœÃLÀ’‡À7ß|¼xêª8^–b! ÇU«æÕ°!ðÄÀþûƒžr¶;e&`&™Ö¬Î?xöÙ0äô£ýûg& ÷ºèäµhõêÕXF g…B‹ŒŒ,X®pg-[¶ B¡õç‰&c"©žÝË“Q¯^½P½zõ¢7Ä%˜€ ™€ ŽŠŒ0ó ‡£zô—+7ü00H28jÑ¢ÓÙb&`&`éHàý÷ߺ5hРtì^¾úôê«ÀWœöù5d&F/R-&`&`©E@áÔ$]ºtI­†'YkexûÒKa(œ €—_Nlà©§&®{ÍLÀL 3 LŸœx"èq& ­ùøã@™É½Î?uëÖaÔ¨Qxã70yòdüôÓOÙª¡r‹îë.¹ä|ðÁ0`èæÄb&ôlp”ôC”| ”Á‘½?$߸¸E&`&`E# ƒ£=z­m&`&`IL@áÔjð©ðÞ{ïÄ­,™¦)lÚm·tò„Úµd*”L}.ÕLÀL d DGöpT4Î|ÈP$¡g£3ζmèPÀb&`&`Ù^x!ô KÛüñÀÕWgïr¶#0oÞ<¼ù曑‘¼ÉèH¢¨9»3–ykºM¬U«—×´.ãš÷îÝtʽ¢ÅL åØà(冬ì¬jûí·_Ù7Ä-000b"°†>W®\¸c-¦"]Œ ˜€ ˜€ $-[¶à“O>aX”ýid“9V6rê$C£ñãÊ•C#£[o5JªáqcLÀLÀ HàkºX¨T©:tèPÀ#33û¬YÀĉÀ>û;æ08ì0àÁC£#¾´˜€ ˜€ ˜@y†=í4ÐP18ðÀ„Ý^É0[·nÅÔ©SñÙgŸá‡~ÀòåËtéÒ¥ô&Ì“†R™?À í¨£Ž ´cü$ø¹»&îlp”î#\Ìý“‹»ŸþMš4)æ’]œ ˜€ ˜€ ”}y!Qüg‹ ˜€ ˜€ ¤#)S¦@¿çúö훎Ý˳OcƇ]|1pÓM`øÔ<³z£ ˜€ ˜@Ї#½¸ªXÑ·ó:…¼yë-`ìØÐ»ßrÏ=Àõ×ç!oF—^š³î” ˜€ ˜€ Ä èQé3Ï€¿#Á÷‚ñ=Ng}¸¤PhcyC!•×äU«Vm×õjÕª¡~ýúÂá22Ò²fÍšÛåõ0ô#à_dé7¦%Ú#…S“8¤Z‰bvá&`&`¥L úòÂG¥ ÞÕ™€ ˜€ ” &ue’Á=²ãŽ;€³ÎZ¶,5Ô®ÈLÀL „ (4Çܹs1dÈ®)uŠç÷¡W?I,Û.ï~={§Ÿz¬ H>¹¥&`&`¥O€ö%Û…>ñÄÒo‡k,òXôí·ßò¾aôþ7®Šv3mÚ4¬^½:hŒÂLÀL µÈà¨Ýì»ï¾©Õð´V/[s@yË-(ÀYMÀLÀR‚ÀôéÓ¡d]»vM‰ö–d#Ÿ}xôQ`Ü8`Ó¦°¦N€+®Ž8"40ªZµ$[à²MÀLÀÒ…€ VýkàÉ'CFéÒ/÷#‡ÀæÍ›Eãxã E~ø!V®\™“!+¥g 4@=#éã%m‡ÊLÀHÀG> D òpdƒ£asf00$'`ƒ£$ 7ÏLÀL Èdp¤³uêÔ)rY%Y€œê~óM¢2†† êÕÛ¾v}…+OFzáúùç@ãÆÛçñ00ô! pj’.]º¤O§ Ù“W^Æ?<40Ò²M›BæÃLÀLÀ2–€ÂOÿááß}gƒ£t8–,Y‚™3gbÖ¬YÁòsþXÏ›†5kÖÝ‹<õïßíÚµ Mèݯ´Q£F[›'û`¥DÀG¥:]ª‰ ŽR-]FÔý00éË-Zˆ ˜€ ˜€ ¤yªÕ\wá…&eßgŸ ¼óðÓO‰M¬U (_¸ê*àÆÁð9aºwïœ|G ¼û. m*Ëb&`&Þ"ƒ£Lòp¤ùNp衉c{ï½ÀCuë&n÷š ˜€ ˜€ „ÀàÁ a ðç?ÍšäHçM2*=ztàµH÷IZ ‹¢öU¥ËÃý_õÀ ¼)mE/MÀŠBÀGE¡—Ç:¤Zº»l&`@@/aÓB•*U2 ·î¢ ˜€ ˜@¦w#‰\ '£\{-ðÜs`¸·Ðhh=€Hõ°{Ãà…€Gžz |@æ‹úrâ‰òrè¥kåÊÑV/MÀLÀÒ•À×_ }•ß¡C‡tíbv¿Ö¯î¿xà`Å },“ø"¸eËì¬N˜€ ˜€ ˜@¡ Ðö$øMVè|`©PXÙyóæa̘1‘‘– . ê×µ­[·ÆþûïÜ'é^©}ûöAºmÛ¶ÁýS©5Ô™€ d eÌPOG#G©V<<]Š ˜€ ˜@rÁQ«V­’£1n… ˜€ ˜€ 3d78ºõÖ0 ÚÍ7ƒ·ï¼ìO?=ÔéÓA„‰y’ÔqSb#½f&`&Plôå~§N2"ÔíªðÄÀn»·ÜÔ®]l] ˜€ ˜@†PdÒO>Î9'C¤@·W®\‰W_}ºçYºti‚.[¶ [Wœ"#y|<þøãqÐAZ/¯8ä)Ðg7ÑL u Øà(uÇ®LZ.ƒ£Úüe[­Zµ2©ß•š€ ˜€ ˜@qظq#ÓZîd-&`&`&ŽdpT¿~ý¤õѰ!ðÛßæ|çÎùËç\&`&`éI`c‹Í;—!6c3 eíÚи(êZ… aÈQ}SÑOò#,^š€ ˜€ ’Àã—]¬ÐÔ² VìV­Z…W^y…ž¦žÃÈ‘#±iÓ¦ì:j֬ɱj„víÚž‹›7oŽ~ýúF 4ÈÎç„ ˜€ ”ÿL) ê)\§Bª5mÚ4…{ছ€ ˜€ ˜@"ùóçcÛ¶möp”ˆÅk&`&`iB`=c±Lž<‡~xšôÈÝ00Èdß|ó JD_ó§‹ð¼ü2ððÃ`ˆ`ÆŒDã"¾[´˜€ ˜€ ˜@‘¬Y †¨V8ÎgŸµ±Q‘€ð`½[Õ=ÌæÍ›ïDZF錙úÚk¯á½÷Þ ŒŒ6öÐCÅI'„ qãÆvQ@ÞÎn&PºlpTº¼S¾6y8êÝ»wÊ÷Ã000ˆ€Â©IR-"⥠˜€ ˜@:˜4iäͯoß¾IÓ­#—©W_4MrCLÀLÀR„À×_´4 ŽfÎyø÷¿FGBˆžpÀ(*°³‚9!ÝL0HüIˆÓN4ï †ê¬[7žâMüâ‹/C¢×_Ÿ}öYðÁ뎺$#£Aƒáä“OÆqLJº ¡òv0$$`ƒ£$”dm’¾Œ•K¿&Mš$kÝ.00(0™00H! §&Iƒ£‰SN ÃÅ †zK!˜nª ˜€ ˜@™øê«¯‚6téÒ¥ÌÛRÐб.¦NÆŽC¦cÆ€/Žë¯Î:ËóbA™:¿ ˜€ ˜ÀŽ Ð! ‹´ë@IDAT¸í6@!:ÿòàŠ+vœß{ G@žó—/_ŽE‹a_å©h¿²Y°`AP Œ‡N£Å—~“W¡uqFEÆI•*]µjUpÀ¨W¯^áà£LÀL Œ Øà¨Œ •ª—w#‰Cª¥Ò¨¹­&`&`»"`ƒ£]ò~00T& ƒ#}-¹÷Þ{'E7ô€»\9à7üR5)Ä00# ƒ#Ík:tH‰–oÚ<ø`hd4n\è½H ¯\94À½è"à ƒR¢+n¤ ˜€ ˜@ C÷3Ï>øèÖ xúép™B]Hº¦Ê°h*-‡G…O?ý . TáÒ6lØÐ^ݧ\M—¾ƒéRª_¿~aQB¯˜€ ˜@°ÁQ fIw¥%»Îc qYàZLÀLÀL ]Øà(]FÒý00È‹€ Žzõê…jժ嵻طñÃNüç?ÀøñàïGðAlh`UôÚkÀôé@Ÿ>Ñ/MÀLÀL ÿR­S§NW€üUv9i…{ï~ü4þ  ŒèÈ5k–]»\³ ˜€ ˜@úqÑ¥—«WW^z9òk½Â÷Œ3#=:ðd¤’Êñ+šút×Û¼ys(Ì«–Íš5 –ûï¿p¯R¸}” ˜€ ¤¥Þ˜•Y‹åÚ¯U«VeV¿+600’ ƒ#¹¶­é§½%×eš€ ˜€ ”!Y³faÙ²e8ýôÓK´ Ãç¯xôQàå—C—ýmÛ+V»ïžS}£F€Ôb&`&`%°nݺ TÉ!C zh‰ç_²$ôÑ  ¡qy÷] ]»0œh|»Ó&`&`&PÜn¾øýï&M€çž;¬¸kH¯ò~ùå—À[‘ž+Z¤ò^4þ|¬Zµ*èpùòåÑ»woœ{î¹8p`àµh·ÝvK/î ˜€ ’€ Ž Î‡™€ ˜€ ˜€ ¤ý ´AmzŒ¥{a&`&H`¼Ü Qúö훸£˜Ö–.žx"44š=;ôdÄg¯¸ààØcªU‹©"c&`&`$ðÍ7ß`ëÖ­'dòÔSÀÙg[¶hÎÝÞà¨{÷dj­Ûb&`&ÎN: àw'xè¡Ä?Ò¹ÏéÛæÍ›£÷ß#GŽÄG}ÄføÅLLªò‡¬<õìÙ“áèºF1þi:ub¹œ40ˆØà("ᥠ˜€ ˜€ ˜@ÆÐÃj}±ÒÝO€3nìÝa0È §&‘K÷âN›ÁW²²c’N¾\•Ç¢ë¯ äÁÁb&`&`%A@áÔ$ ]’L¢ðhG œupôÑÉÔ2·ÅLÀL ÓÐFÏ>›i½Î»¿2$’×ßéŒé-8q"ÆŽËPsŒ5G©Q£9ä|ðÁèØ±#Z´h5»B‹ ˜€ ˜@¾ Øà(ߨœÑLÀLÀL Ýè«–ûî»-[¶L·®¹?&`&`&iŽÓ×™Å!ô"ßüX¼hÜ8þx`èP`ð` R¥â¨Áe˜€ ˜€ ˜ÀŽ |õÕWÁÎ.]ºì8S 6J«LµMý+õCõÆå{®¨üèøx_tÜbª˜©Žõ<™Õ‡H£>i]ç ò«œˆ½baY2Š€ÜÅ+thß¾} ÔïçŸ\Ó»<"&·x`î-^7# 9'~}-‰æ/a¡ºë:¬ë½–¹¯ùÜT$ùGëZ/QÙºÞGK¥5çéÒ¯vh©uµ#.š÷ÄBûòbò=·kÎQ=*3šãK͉*'šï5Åå'®¨~¯}ZÆE¬4/ªŽ¨ 呯û£qS_ÄS÷ –Œ$ CZ…<©X1÷‰T28–-nº xüqÞþñ\¿øâÐðÈž$J†·K50È?‹.{ Ðï³îÝó\*åÜ´i¾ã1óçÏßNelôý÷ºYå-. Œúõë‡Ã;,ÐîR^·ÅLÀL T”ί³RéŠ+)Szñ¡‡]Ñ ­øòPn×ëHæ0ñÿ¨:F/o¥ÆeWÞÈÚ J’h©`¨{S»PãårµH²ˆGOÌR=ðb¬[ìCÝ‹ª8¹EmÒË«©‡P›Qãr>WÔ>ý•)ïÖ•¥‡sz§e”ÖzÔŽ_1­ñˆ -àƒ:ô€ïBj×øN¦5>ê¿t7ªú¡Òè¡ ÒÚ^…:ÚŸ—g¸¢{¿5ÔÓ©í¨q¹Ž+*;R•£>ÇËêT_£æ®ãen[LUC©­¨‘¨,ZûåGýP]:Ÿt®ªžøR쎡L˳\YIUy æÔHÔ¾{¨•r©ÆWù#^ª+Ò£˜¯¸<ÍõA'S›Q#уÞó©j»°F¼”V½yÕq,·÷¥Æå®¨,™X5¡F²‚ >@ ç®Gë’¨ýZªÎÁTý­ÄEuhŸÎϨõ©‘,gâ ªÎÍÜu¨/U©b¦ò5.Òã¨ú[Œ‹Î]•òŸHmDä&®§Š£Æ ~GiKj£TuiL{Q-&˜ÅÄLêª,Õß”Öù§s/’Ï™8‹ªóUçûGԸܱ ¸›Ö>å9!HËñ0®µWóšÂ‹X“4™ÔZÊ¿žàüa&M€ë®‹—–wúÊ+iÄFë§Í¬ã§–¼fue›÷VóÉÃÆ¬›üÕ§Q'S'ðoýÓ0?¿ö bŒcÑÒ¨R;P#Ñõah%ŸËÝoe_ž 3ók"¼ùf8¿.É:žMÀþ±²t}ˆ_÷b»v˜T _àxp@ôäÿi^H‰ DÈÇü?~RñëE9Zy]xQØ&åEC˸EI“;€ºÏòºÉqS?^~9œ“ç1›®Ù“¨ñëÇR®·¢f +GöÁGe«žòá2˜¤¹^ƒãW•m߯±ÛsO`̘•ú¡:ÆS¹9[4¯rØEEY¼HÈ#÷[ŪpÌ_dõ¬OO£Þ¨ÃlºVJtÇë˜ÃõöÚ Û¦ t9]ÀYWÀIõ¨/YRs8«fõcÔ¨ÐðL}Ðõx*•³eS}³×r%Ôq«D­BÍzºû%4Jz‹«\W8#¿;ýýI¾¦î¤ÂÿfsÑ3¶žŸd­óØ–‡úQŸ²û|Ëÿ;f¥µÐzAë¨~™dÝôvë|øaxoÁÓ%µ»mVZ þé÷ÀÙ›bܳ·åN膆ý ôoÓoüêWAÚÿe t‘åŸØ Ž~þxé%àÌ3ùW;N=5¼œÊ»ŸÛLtþ®¡rZ ®-ѽ––õ¨ñ¿®‡?p©?oíkIËó\YEÕñúûËKuI’ªî>Ô3¨qù=Wt Õ5‚—ྑ‹@ô7~T4?k]ei/Uv9nãåyѼT7”† y=ª ÜÂ4ÿ„ƒ6üšË!ÔH~aþ“8ϬäE0ºÐå-b³‰ßHÕRu*Oß%À°a =z„.¥®âê(ªúñ[ê™ÔH–0^+WWgÙØòÔ ,GíÞÆr·J™ÖRë’^ßð>~tØç#ޝÙqû;Tq¾“z.5¹¾Ú»Ç·FVl¬êÒýLT‡–šß‚%Ó9±üZXÂ)§° Ë¸ÊjƒûïÛ¸Œ÷cæL 7O”uµX6!•§VP=T5{+@ºEud-»OŽåœ ャç7•©:¶Q5þgQ#‘õ@ŽÙjžÜj\˳µ]åÇu¯/X6¯×úC9†×UÉ ,p$•ÍÀ©çR#ÑýX÷FìëIÖW1«?jÛVõƒõiÙýcž[/„¹õG(V¼Kånüz!5’i_4pšÈNkÛî ~×ñ:X—iÊ 3Ã[š{¦2~'(oWjKj\þ»˜ 焬kôV–Õ£¹&{Þ‰àþ–kn?±]Lëzª·×#¸UsûîÔ¸Ü8›mX^Gƒë'w²‰Á\-·èšÊ25‡¶XÁŒ…a _sÖYt§Èüs¨j߯¨½¨q9ãk~ÂvEóšæÈà:uíTùÁ§ë)÷µZÄAú&Lë&æšk€gYà ªú¡k^j\ŽÿœÏ ³3TdC‚%;Ìg¸”ªü¬t²m93 ý½ë.à+¨[â@7j j\óFd ÛV…œåIP•ª¹n yo!ør7¶{«jœ{ÿö·ðþŠ] ÎÍ <,A.|‘,yÝ®Är+­ —¹3‰æšÍlï&ª–•Ù–jd+‘·Y-è<¬L%ÖíDûŽyçû_•UÙÆjY˪¼©ŒêQu*3ˬțµG¢:ô[]ãÀîæ)l†1Ï”¥lÏû*¬£ Ï›`ɺ‚ûXãtO :?$²–×ou•Ãêòì‘ࢇ€O¿c[j³Lñb=ÒÊÔŠêK¬fOÕñÖ[áGLµ¸G¼r‹Îçá¿çý'ÿF6ÖãØò˜Š<9*±Ùu±!ú=›‡´×¹¬¿s‹ ì‚À¯Í?C^"þô'žZ;ú»ÚEÁu[¦úÛй«¿ÑHÛ1Íò³EyÞ¤êz ß$çPã§ñ|®k¿„ÂAÙ*KsB´Ôv‰®ÒáÔÔHøg²bø ,ún¾Ÿÿ=N\q"Ö¬ã|–%Ý9]Éý+öG­ZµÐ¬K34oÜ woˆŠåxaü„?¢ª]ºVJï¦v Fò#SÕ)/Ÿ ×ÔÉ\¿'k›®µj§ò©‘j]—]†”ç^jGj$Ë™PßÄTúUm‰d·Su]×uDã§òâåGiõEõÜOסû€Ë©©æíøx|Ìõ[©ª#Rµ5j{|©>ªb¥qDèï£jì5æPã2…+§Ö¦êš-™Ìn—Ú&Zª—P›R#Q¹¨«ÁÑŽ¬å.ߥÖÌRÕ£t5ªÎ]]ósë)ÜVŸ‰Î¿TqŒæêhŸ–#©â׈Ú8¦Zç”N Û©Ú©q‹Díç4pÐØ©qÅ•·©jWÃ\ªm5¹´?×ã¢:ÄKeÇÇ:Êó!c©税±´æF¥è@éÔ¸¨¯ü; ú¡zâç­òa#>fcÕ×:€*’'¨g)‘%º¦>­äs©‰ì¨\yŸçºú!9’¿øëÚüGí(€h2>4Wþǹ®ÉÁÔ®A*üOñ±õü$uUÉ=ÞÍm_e¬1k—•ÖBÏ}±õü$ù;m»:nä¶o³'[‘hþk´’Ïesæ¸ÜÄ7’.Tå‰DuÜ­äsÙ‚ùæÊû[®ÏËÚ¦~4ËJk¡§ÿÆÖó“lÊL}seÔ˜Fç»þ~šÄösþ‡Î»‚ˆŽß'×b±$kÛž\ê¦)ý}´b­¶Æå®èú"Qý‚Tøßf.žˆ­ç'Ùš™t~Z2“€æ7ÍŸRõ£OKÝ8ïHjý‰7ø¼ Ô®ÍcºÈQtÞéú´»VrÉüÃÛx7ê.]Ê 1åúêüá³7·I%ª¼%u Xv Ž>ä꨺6w¢^OËëuïNçþ1léÃeͬ½[Y%/»âv–¹–—5ü£©ÑŽ×ÊϧzP*¹”ú%Usêt*›•-úQÒí>X[þØÎó—rëBÂ~êAp]^ljd©SG; ¨ìV€ ~ýÑ>5£Ë{ì>3Dtµ]¨”ÛôNÌk-fu¬o5-­Ì´“¸ýªÊË=•¸­å>Áà…{+;ºMZ…É© ÔƒÍ@³ÒêK¥¹ÜÆþèá»T¢ëscªÆ|7j\‚~¼Ö±…+[©Zncåzè/ÕMJ”Ö²˯DZ–´o.ës¡²U‡ÚmëCVËÙQ•½¹2•ýØ¢¾°¬òÉxS¸TZÚ„}­Ñ›yXwëÖaiGs¡ñ¨Ì¸è¾¡Í8þÕÄ~kLÔ`Éuñ*¯:¢z¸“Ú]ù¥Ï1É TÕ¡ñRóâ¢sàÀ—ÉŠçÕ&GKõ§Ë-Çöº?f9vÕ+¹éoPr:•›ƒY§š6¢:z¿ÄÌß3Á>l!+•»•ª´ÆG}ŠÆ]/LšpÜkíõã,®²ú@s×ÑŒÛû¼Å~.%*¶W/ 4›²êRZ*Ñ t1kÉ¿ÙZû±^Ž—êÐiqUu°»1Ù¢:öÍ¿áe¬ƒô’|«Æ]udÕ,™Ö9¥z:îÉ¿Ãp`—é%•%£L˜0!pßCÆY¢KçhžFO<Áçª/òRÉKHcþÝÆmÑšñ\“â5ê$êBêqÔÁÔ¸œÈ•ùÔŸ³”—áà~•uä)øõ1ž‡kyMѼ£¿ã¶W²rÿ‘Ë«³ÒZ,dÅÕäµ=ëï<¶k‡É:lô]×ñoˆ#÷ÜCþ“ÉÌ=†Ê*³Q™ äƒB#-©¼Âk@ðC2÷Rû©Sžþü›0«^Î{nxÿþ%7ñÒ±Ýýƒâð¼Y;ZPym2©lý¡K£?z¥µuƒÆ¬XJWÎ 2¢‰.E*Ÿ—«Y¼˜×Ѹ‰æ3eˆ”×Êì·¼†FéÏÙÏâ:¥iÓÐàH¿ 4¤žB Bï(ø‰ªû¥Íl¿4èG´TÛcå+ýé;Ô„Å(ž þ¦4ÕýBUvâKõcÝSܤsW&°YËà%¬ú”Å(:צ°Ž)ÿävŠŒ‚Åê¦uÿ¥¿©VÔ¸|ÿ=χç¸e·¬­j4îQ:רLçÿô'Ãü2& ³ƒ¹ªÓSC×>Ü•ý¿î«6½Ì!f#4o÷f*›íß&eZªûÍ¡Ücø;p$ó¾ §$GSÛP5öYS+S¡üø#·¿Ê´éo@™Ør,Wª±‰Ò:4¿­œ@VS‚:*öïÏ–L!ðÍ7ßðöo+/'ú,!ù øläV<ü'ÞžÎ/sêlÁ™CÖ W³u|vÅóo5ÏõŸ¹\Ë?̵lC›94:çuKs›Œúÿð‡ðã±7¸‡@—§‹©qiøóëú°3Ñ ýMÿ‹é Â̺÷•Ô \}+ܼè»$+-Îå5g¯‰ù–G™óÂ0wT‡Ú¯ƒ—¦ù3/Ú%lÚùÊÃÜCuÈàH›ÞÎ:JHze¥£Å ìÆ.ÑÚ®—ê:zs˜OuÈàèq®¾›uh.ûd¥£Å›¼ømì­åc)0÷…ùø²;08ºŠ«ïe*”çg¥£Å[,óÑZ>–f;EýÁ‘®¥cƒ-À3\ÍJG‹Ç˜a«nÎr‹NTÍš‡âr7W4Õ¡ûLJ­F}žz5Žï âš\s‹æ^σk¹&Þ¬<åÉ¿ü_ÃÌuë†KýùΧjUuô£F¢{Ê—NÖ¶_–[Áyà'Î=»QUZçmeDQ?$Í©«©Êò!•·8Ù2›©ÿäþƒÉÞËÄf¶y9ë᜴µFXOݳٵQa&9/Áý/«o¹lîþç4…ÇoŠmÈ+ÉòË‹Ymc™ Nf?¾2V’åˆ Žò‚æm¹è–T—‡@4猠.¡.¥ÞAÍúSd*üC§¾. ¿ÄtÓ;’¸c¿ØNþù%|Xq×ã—–¯¹><–?É5×`Ö³‚Pà#GŽÄä·&cò’ɼ=­GûÍn8`Àè±o´lÙ2Юó»¢íemÃ[F^ U½‘húÔ%OŸú[Õ’—¢QŸ_ *Ÿ”öÁ”ËE ßóÿç²Ò¹bªëaüX]sÿÉ«LÕQ9Kù'ŸÀj×GRµ]íÌ-ªC†œZJTÞ•¼°ÕÙÀ4Wô#~3ó?nW[ªPU––‘ÌäµlâÚŸù4§ÅåšI¼Yîß’+ÕÞìûó¹¿Uð=eÿ’¼‡ÏÕ ¯–>]~ -Û¶mû>£ÐøÀ¤$0vìX<òÈ#üèàéíÛÇks¦z\ï¥M¹äü³žšµ‹@~áÿ ¨Õ©špyL•\ã\Ht†j)ÕÍÀWÔϨ¼®Êë`pcÁE¶<ÎÔyYkqÉël‚\εèfL“XWªnžöÍZ6ãòsê§Ô©{Pï¢Æåÿ¸òUÇ  6¤ÆE?’t# UÛ5 äVÎwÁ~]çÅn7j\4_©•¨ÚÝ`0l眙ý|Zei¿ú£e¤ªS嫵¨u¨qùŽ+ªC7#»S5&‘¨Ì™Ôø¨ú¢¼ÑÍR´T=¨œW·cÁ{‚àÆI}hC­ADu¨ :/TTs’ú•_*¿Ú)Ë®¨mª£U7‘¨¼‡ÉîGTö«/Rñ–ª[¬âep5ðø¡sPû»Qã,ÿ?{÷/Eu>|ü¡ J—¢pQDQDì *Fc4ö‚ÑK,D1vÅ‚%bÿ[¢M¬`^KìˆbW4DA¤)½×}Ï3—göîîÝ{ïžÝ)¿ù|æîÔ3ç|ÏÜyvgÏžQã‰fÔõþQÝݲ¸Çr_õÿ'½Î?1ËV™±¡w1£æÃ?hÚšÿå›^ݲ¨™:¹i»¯-ͲôrŒ5Ëôê¥ÇH_o9ë3G×¹i»Ç3ïo+äSÿ?µN5¿{˜ÑoefóQÏ™ôch¹V›QÍüubÞçT8ÆWf™–C·ïiFÿy¥u®Ç×ëŒÖN»ç˜¾ê~ºÜ=·´Lz 3Þ»˜/[FeîS˜7[ ±;v¬Üx㦟W*–éy³è$ßbýÿën.6ͦ˜sÔŸ'›ì“L¬™fV,öæDÛn;óbªoç,“úáæçŸÍÿ¶I\Ù—>ê—®óÌòIæ$œ`. óÌ?ÁC ͵Ü\Ìu~ø„IûÌMé÷6¯ïošv_.1÷šQó¿§Ø4ê‡ÿÿ žûúÿ£×€fô#ÍŒþ/éÿ­þ0 €@l^3=A½þúëòÐCŦLI/ÈTþøÇ?šDïU Ð/d›™†ž{챇·^Ûõz²y[üNù[ò>Í}=3îh®÷uõºkZ2§™ùa›–Ýa^¯ð­×†û›7ÀóMŒªg>Ô5o°ê˜7vµÌ›¹ÔóÞߌ–š÷‚fÙZ³LÇõ_šù×Ëyäó¹òå7Y¿7‹LHuz¼Ó÷Øî`ÞÉ×™9 Húfw]pÔ÷‹›™7”õÍ ë™q3äšíê›}´[Š£6å¾ýÖüØeùœfÒÑQ¿,N5ë:m˜>œp‚yÚ3}ipÞtÿ/Oé~Ê“óþêÍsízKo ë¨ep§3½êz·Ý×|!-ôCVŽA{8Ò†fš_×ßuÉõªÛëñ´Á‘û¥i¶Ã¬6PæÏ/?†?ßþò¸^úê5MM¿2+íÓüJÔ©cµvÓÖWÿèOÛLmô§åø ÷¯1ד§Ÿ~:â%!û®À¼yóä7¦çª/¾øÂ]ä½j=ÿÞtË÷üóÏË zýÍ6èÿ6f›3Ï|3ÿ‹:­ ‚Î<³üK³fÇÍ8ÀŒ˜qÓ a£ß­dk§q½»4׫ƥ™qS"ú»ÜÄ»ëÍ"½ï¢ŸËþhÆ_›Ñ?tÏ\OÍçÊ:æWkÏguõÕŒõÌÿ°ŽæÒàüëÿmK“ÙËÿgõwÜQÞS‚–Aÿ÷3c3ú‡?ÿÏÜ{5_ošÃ8izÇØt¬ºæ8Î`6hn®ñ[›X¢×ýüyÖYåŸÍeƹ?³ymS¾µ÷wˆ‰ë³Í>Ú#œö4SÛ쫽ë™IçUóV×,Ó²8?F1×é­ÍõQ¡ *>¸ü¯¹ì;¡¾ƒy5¡"0¼7ÝÔŸÙÀìꌆª<}óªéëñôU¿”Õã›ÔÒÌ”O¡×8ýbë;³LïéÛ‰­ÌØÔŒþaœ)ÃBó>c•ÙgµWšQ{rðky4m“¦s óª¿äï ó¦`7´•ö &A­&fÜߌ;˜Ñ?|mÞ+ýd2¯U²Ø¤m)‹Ì«¾½1ܲ™9†óºiº›Ùvs -‡G{Õù«Y÷Í"ç”;À¼ú‡'Íöš¾yûåôZà¾.7;hlaŽÑؼêç}{™ùCÌ«;hY®53“Íhþ]ä*3lFÿð…™ÑúœkÆ9iãOf¾Õ@Gu>ÆŒ™Ñ?üÉÌÌ4£ùpäuó­Ôz~ÖŒZO:íG_Ýi='µîq.0Ó½Ìèþhf4}5ø—ËÌèºÿ#flmF}ëcþeÆó}¯:mªÌ;†ºìmFwÐóér3jZzœg̨ùq‡Yfâ~3j9tlfÆ…fÔtuT+÷U=Õê63n²3fŒÜtÓM™ï_™Í¢+ððÛ´@®»îºªÂü_Nú·¹Üëù7ÆŒz^vò%ó³™nå›×sSÏ-we&Î2£þÿožaÔ˜¥×Éz¾ñl3íÿÿYmæ_6£^¯˜ñWfÔë‹;,0_mšÑåšVÝòq底òñ?–qÆÉŒ™3ÌoKf9¯–L0·ö5áòaç.;Ëq½Ž“Þ}zËþí/›·ÖÌúj`.aΠe6®5±hӸμ®1ÿÀú^Y„⾺ÓÚà^?+æôóõ‡™tÌÁÖškëz“Ö“æzÍ´¦©Ÿ=4M}ÕÑ]¦¯úËýì“kÐÏ ÷ÜSþYÇé­Ï€­×2˜c8eÑ‚æ´aˆþØB7ó×=Ïô8Þ åÖM™œõUGwÐ ’ÂnÂÕcliŽ1Í,ÒóCÇ6fôטcÜöY¢A=áôUGMÔÅûòÒÖåÓÍhʪƒ9dóvå×~=_ô}ͨ±ÎþüWÓ³Ò»fN/þþQ7Ö“Aƒ–ŽzAw§G›4Ì14†êçqýâç^ó¢^zí¿ÚŒþcÜz›YoþÁ6š¢&@è˜r_[m“®7šãhïxúÃÞ:Z.3|ò‰‰ fûûÌ´Æžæfü?3ú‡»5÷^7õl‚Â:³ÁúæÕL;¯ÆÎéÍÑ”§Žµ‡@}Ýúe󺩎´{êæ¼zÀ$ºÄŒJñ˜ÿfúÿ̹÷¢9wµž×˜4Ýq­9ŽNë_ÜÞÝÞ;¿d, †ŽzŸæ;“7Cá”c[ójª80Üÿ¶iÈ=Æ\LטÿOíx¥ÉŒ¾º£Vóf&ÿõ͸¹Éìîo˜®Käjsëa½oÁG2ÿ¿T• Hƒ£*“Eb‡œ Ž~0EÐëÕ›FsM,ù0Ïä MZ.¦šyswÞÐlm^2£øÜÌL4c{3ö4£¾Ñb@Œ Žâyälp¤±Í|vqé4oâÜÃæƒÎ0sãhq9†öÌ£ëÜù—WÖ_“èÈb}Y£ŸaÌût'¶Õ7¯:úýФ£~˜×ψ  €€O€G>Œ˜Læjpô•éý£{÷îríµ×šŽøþ*ß|h¾››¨ Žj€ò]«Üàè S ‡LÛóYN?›™(ôËðÿÌäÉ¿Ì:SÏš¿mÌhnW:ßßvp¶(êŸùÓ§ËHÓøæóã§ñæÇ$ MÖÚÈ|Žkgîµ¶7÷T·6ŸÛ˜Ï{­Íç½Æ¦Am»Êž]zûíæÑbwš¢«ËGíUfÎ4ïôM@Žá†Äé½.Ç&Þ*ýì¬hõ}†Ž:ýå—å¼2LèSµÁ¼~vvGÝ_ÓsÓÊ5ÓM¦1£¹_køøcód—ÿþ’¾{}ÕÏÒþywZ¯Óúª?ÞÑÎæÔS ¥š¾;ºÇs©i»£öö­åÌ5˜Gê:õ¾›ž›_ÿ«N3„Jà;óØñóÎ;OÞ}×4Ôbˆ£@Y%ÿÉq,s´Ë´ÚRm ¸¥ Æu+»Û(j“¨ŽaôMTú`âTà±]é뵑‘Ž  €%(ylÛl®ùUГæ¡ç™Ÿ M*÷0_ÒÊ™gšÐæ´þb$ ƒ~!¬c¶Á|^Ëú«–lû°@ÀŠ@©cÛ'ú ;3üºõ¯eúÁ¦C¾÷E®4óÎ\.0;™q«•¦qíXsóÚ¬üï§æ±£Ë{ãÓÇÁ\sMÅ_ç›]¼a‡ÊojÃ$½Ñ©=Cêè62Ò›5ôËÛlšjš6û#€TY Ô±m„ ¦½i}éÔ±£iEk~!þÐPóÈ/óYmã…¦,f™;裄›Ï3½Ûlc~%ÿ`ùDÌ}ÔåËR2òèZ2´YÕïð56Ò]ŸyF7m`¾Ó ©# €@RJã<çõfê?f¼ÏŒ£Ê—Î2÷M³Y»‹y¢Ù_Íï0ö53­Ê×þ¦7@ ¬¬ÆŒÛc öØ®=®jðÌ2,2=®.3‚·|ì1©mz,­o¾Çlm¶=mÓØM{ãÔZuôÞóáü Ó¦[™‚k£$ýŠûCmð«?HqG×¼ºóþé|žhpÑEæ—:§”§¡ßÁêþ™F]WÝϽçœ#¢£Íá€LÁf´9´oo:u0£ÍA=UÖðÉæñIò0WD†° |dºû~üñÇeÊ”)æ‡;æ³j™@ÖÊ×LÀ8É|Ú£G°ƒü!€ à „*¶½ÿ¾éJõêòG‰üùÏå ´Á €USl›ûÊ\sz”ìwÉ~N F›{¤Í®7õð¡ÈsæÕ{>ùúkÓ3Þ†òêMÙÝw9þøò×ÊÊ­ŒNÓÛÇ  €qSl›ozï»×|QXwÛCÌã•ô[Õ˜Ñt=ÔÄôrp¾‰gû˜_`˜/ce{ó¥cýòKÇÞf,>Qæt.ÓÓ0+{²ä¦dxAˆ‰@˜bœ˜6=2ÄŒ¦¬óˆFÓžfþQ¦ÝË(Ó_ßb‘›o1Oì4ŸçªÛ¾%PeÚ;ÐìÙǹsË{Ôï uÔÞoÝÏ‹úMíýÝ ãÇ—#F˜Îsþ+Ó¦M“ï¿ÿÞé$ál³®ŸÍ”d…éÁ¦‰éIhkÓC|‡nݤAkÓüH{®u{¯ÝÜ<ŠI{±u_u:Ÿ|žuVùc?Í1¬ mL:2 €ä-@ƒ£¼©Š¿áLÓÝÕæ ÐLÏ-7³“ùóçËÌsu<äCävÓ`c Ø  €„T ”±íØcÍó_9òÈò_¬„ÔŽl!€„S Œ±mô¸¯å(ÿ2dïv¹í¦O¥Ýƒ×‰Üø^9b»v"Ç™g¬ík~«£þ€E1 € `ÂÛžéÿwéxåz“;óˆ}°LÓ“ÑUfòwæ[ÙM!L;MÐNþÌ­R¹ì2 wîÐÛ´=zÐ|‘ûë_‹h'I  €ÉcŒm­óªËÌ8HäÓÞ¥¯éhGŸ ¥1Mo]ÖhxþyÓjéæòFF fOJ{™ÕÆ6ÛmWþ9ÑL¯2ËÞþðCyÉ|ÿ¨ fkc%3Ô1ŠÚ›Þm´3„Ž&°êø­·3û`–mÆçËìάAb&@ƒ£VèO¦õð™gži9+¯êsO<ñDóØÏ§žòÚ‰@(¢@hc›vÁ[ãOîE„äP €¡klÛú°Á²Õãuä¸ÃçÊ£+Ï'óLîò_ƒj¯~›~H2‚ °Æ¶Ž¿5]=\mZýÆP]jÆCê;fÚù»&Ìé²/½d:?24èÐ¥‹È¹ç–Oë_}G?íz@ ±aq2ÀTÉéf4ÎÞ~·yÂõͰ·2mL#¤=öÈR]+VˆŒ'bz2ÏͲѦÅÚ5Òš5"»îZÞW{òkM73Ö®•©sæ8=iÏE:N5½iF6õt´³yœYß¾}åð×^½z™§š™{ª  €‰ ÁQO5&ðŸ}öÙÆF¸÷Ûo?Ùÿý¥»yÌËâÅ‹eôèÑæùâÏÈ2óLT¦OŸ. GyÄyäZ‹F–@*@lKhÅSl@ ÆaŽmþi¹üfôrÒ›·”742Ÿ/åºëÊ©ã:¡h €5sl}’Ë,ó…éÖåeÔÞŒ´Ã†EôI/:h## yú„Ь_ЖoÊ_@„ „:Æ™Ng×ï)ò§?‰ù~OÄ<…L^Ý<TŸê?þ(òÑG"\þªÈÞ¸QdØ0‘SOu·Êüz ":nô *cÇŽuz,zãþûÇ£­_¯½þ2hFeæ±hÇsŒéð×Ψ=1 € .@ƒ£t‘Ì?ûì³2yòd/'õêÕ“Ç{ÌéšÐ[h&8à9å”Säøƒ×8IŸ;ûÜsÏÉÉ'Ÿìß”i@J*@l+)?G° æØVgÃZ9é»Á"çœSÞЈgÇX8HˆŸ@˜c›£½©±‘~ {ýõ"_~)Ò¸qy¨;í4‘vŠ_P"@„9Æ-Y"rÒI"#M}úèOó¡4®»JäÉçDÞ~»¼‘épÀô™¡Ú€H­cÃÓ{Ñ| o¼ñ†¼ùæ›2oÞ"3gŠ´iS袓 €@LBÛŒû{ï•7.úôÓòG¤]q…yìÌ5•?I&¦UF±@òsŒÓNŠúôùâ ‘ .y ÿ·RgàÃ"?.æQ'å%tŸj:!Ó"(kɵ¬'N”¯¾úÊÖç¯ú†>Ú´9A[!û‡áÇûg™F@ dĶ’Ñs`@KÄ6K°$‹ P2°Ç¶£Ž¹Ì|k¾S•¿ÿÆF%;Q80 A°Ç¸¾/œ$—?Õ]D¿Ô§™|ø¡ˆéX@.¼0cc#í´@Qõë×ÏyüYÓÒ¥—^ê46êÕ«— 8P^xá™2eŠ,]ºT>ùäyøá‡å¬³Î¢±QÏ_²Œ„]€G!«¡Ï>ûÌËQ­Zµ¤wïÞÞ|® íáÈ?ÐàȯÁt!ôMéb· ÏB$H‘˜={¶Œ;6òå öˆmö9Bõô_#GެÞÎìk×_]Ö¯_ë2R¸š ÛjæÇÞöôÚ¥×0ÒÞzë-ñÿÚ=}=ó„=¶Õ«'r×]"ÛnK]%Q€÷çI¬õÊËüžyÎâ²eË*ß-/ö'çœ#2xpùc±‡ +lš©5½ÿþÆoÈÝwß-çž{®`©¶å–[š'g·‘c=ÖiD¤Cëß¿¿ó`Á‚òæ›oÊÍ7ßìôhÔ©S'ÑïÂ+ õµQŸ«Ç€À&I“&ÉÔ©Sñ@ R48 QuM›6Mô ;èsTõÍC>ƒv‰Ø°aCoS.FlÞðNŸ>½@©‘LôƒÚ£>‡¢P‹Ä6‹¸$]cmH{íµ×Ö8ˆŸÀeæçók×®_Á(QAˆma$KkÖ¬‘Ë/¿ÜRê$e}ϳdÉ’(¼[ ¶YÄ%é‚èûsq øn5›š3gŽÓTˆDŒ;òH‘k®‘•æñgÚÀH{+ÚÅê×±HWBˆ3¯]—û{ qV³fM/°bÅ gý÷ßïMgÝy „%¶é¯üµ'.lÓÏmúù!¹úžGb[rÏl%×÷<Ú DÔ?ëèý*u˜2eŠó?[™Yž¿@Xb›Þ{Ú°aC ¶µjÕJêÔ©“aØ2¶z ‹úûóØVN‰ ¦1mþüù²Å[”(…9¬Þ¯Zºt©“˜öVÃ#P ãꦖ§ŸÏõ|u?¿Õ¯__Z´hádsôèÑòÉ'ŸÈ~ûí'½zõ’Þ½{Kz‡z^ðß­Õx¼êûs´^õ|`@@ô³ŽÞ׉úÿ»Þ›p{Ø5k=ÉÇüô¦ÁQˆ*ØýÇs³TÕGé‹ôTÇŽÝäò~Õ76úŒÈÓN;ÍÙG¿ŒMoÌ”wbl}C<`À©[—ËFl*µ†Ñ/¸ôfà 'œPÔJ»»ÞÌô?ï=•JÉÂ… ó~¤eisþ£‡%¶é‡ù™3gz±Må4¶Ñà(üçÍê{½±õë˜M£¤¦­×}/õk„~¸w=¡ñîÕ sF‡%¶Mœ8Ñi4í~nÓÒégB¦ž£šŠþ¯ë@l‹j ÚË·Æ„óÎ;/ò×ý²Íý"VÏw¾œ)Ì9–ئ_Fè¹êm7¦ÁQaª9Ò©Äåýy¤+!„™×F:ú詨7JÔÏlzísÞÏ»…y KŒûàƒœÆÒo¾ù¦S0ýž¥‘y„šÚx®[·nÎ=ª#FˆŽ ñÐ÷²ßúöíùûOñ¯­â•Pãžúhµ(úý¡ÞwgH†-BTÏéo|ªÚÈ'}ûô–Ûùõ/ù‹èÈ€ €@MÂÛú÷ï/:2 € PS°Ä6mPB£’šÖ&û#€¨@XbÛ>ûì#ß~û-•‚ €@ÁÂã^{íµ‚•‰„@“}­‡¨6ÒßøTµ‡#ýÅp»˜ö/c@b ÛŠ©Í±@Š!@l+†2Ç@(¦±­˜Ú @ ˜ĸbjs,@$ Ðà(DµžþȆªv ­6òé=ù×1 €@1ˆmÅPæ €Å ¶S›c!€C€ØV eŽ P b\)Ô9& €@’hp¢ÚnÕªU 7Ë–- ÌW6£ÏúõÍ›7÷Ï2 €@шmE'ç€ €–ˆm–I@ èĶ¢“s@@" ãŠÍa@+@ƒ£U}Ë–-¹©jƒ£Õ«WöoÑ¢E`ž@Š-@l+¶8ÇC°-@l³-Lú €Å ¶[œã!€K€W,iŽƒ T…¨ækúÆgþüùÒÐà(ÀÁ  €@ ˆm%@ç €VˆmVyI@ Ķ sH@¢ãŠÂÌA@,@ƒ£U~úŸ9sæT)w³gÏö¶¯[·®4iÒÄ›g@RÛJ¡Î1@l Ûlê’6 €@)ˆm¥Pç˜ €Å ÆC™c €$Y€G!ªýÖ­[r3f̘À|®}œš¿R÷îÝ¥V­Z¹va €ÖˆmÖ‰9 €@‘ˆmEçp €ÖˆmÖ‰9 €@‰ˆq%‚ç° €‰ ÁQˆªºsçÎâó3yòdY±bE^9ÔÆI6lð¶íÓ§7Í €¥ ¶•Jžã"€Ø ¶Ù’%]@R ÛJ%Ïq@l ãl “> €@Òhp¢3 víÚrÔQGy9Ú¸q£Œ5Ê›Ï5ñþûïV|ðÁyf@(…±­ê@À¦±Í¦.i#€”B€ØV uމ P b\1”9 €@’hp²Ú?æ˜c92dH`>ÓÌâÅ‹å¹çžóVm»í¶Ò±cGož @J)@l+¥>ÇF°!@l³¡Jš €¥ ¶•RŸc#€Ø ÆÙÔ%m@¤ Ðà(dg@—.]d‡vðr5~üx6l˜7Ÿ>±|ùréׯŸ¬\¹Ò[uòÉ'{ÓL € Pjb[©k€ã#€Z€ØVhQÒC(µ±­Ô5Àñ@l ãlÉ’. €"uj‚pÓM7oößµ&i°oEFÉÈ‘#½}ô‘4mÚTºví*Úý£;Ìž=[Î=÷\7nœ»H:uê$ƒ–:ujTµ^zL € Pb[!I@ LĶ0ÕyA(„±­Ф Fb\k…ëÖ­ׯ_ŸÏæym³zõj™7o^AÓôØfú6Óö—!ŒÓk×®•Ù³g˸qãdÆŒ²aÆ‚fÓ¦mTÓ.(0‰!€@@ jñÍæuLal§ÀÙ ñ-{…$ù¼È®ÂÂ+@l ÖM’¯aQŽmZ‹6ëÎfÚÁ39(„±-¨˜äk±-x.øç’|^ø˜F JÄ·`m%ù:åøf³Þl¦<û˜‹‹@ݸ„r 7·ÞzKú÷ïïkÏ=÷”§Ÿ~ºÚEüè£äñÇ—)S¦84¡ZµjI«V­ä€“N:IzôèÊômç½Ú….ÂŽ?ýô“¼òÊ+òúë¯Ë„ G¬W¯žl»í¶²ÝvÛÉ‘G)‡~x`}>36m£šv>nlƒ5ˆJ|³ySAÛé׬–ìîM|Ëî›äó"» k¿±­¼Ž’| ‹rlÓÚ³Yw6ÓÿÕ"]b[yÝ%ùFlËþÿ›äó"» kˆ†ñ­¼ž’|‹r|³Yo6ÓŽÆÕ\ÖD VMvN¥RO™ýO¯Iì‹™´±‘¾ùÑ¡º ŽfΜ)W_}µ|ñÅ™â[zÈ!‡Èí·ß.7ö-Í=i3}›iç.U8Ö¾ñÆ2pà@Yºti^ÒFGº}³fÍ*ÝÞ¦mTÓ® @ `ao6¯cŠh;ý‚U”¥„ˆo™a“~^dVa)Ñ ¶ÙýÜö3!ª±M]mÆ›i‡ýœ ÄA€ØFl‹â}Iýß³l¦‡ëe@ Ä7â[ã›Íøc3í(\ÈcAÊhpTGA °‹-’^½z‰vç§Cui+ݾ}ûʬY³òΜö˜£=)iÏG• 6Ó·™veå ÃzíjðàÁUΊ֛îÛ©S§¬ûÚ´jÚY±X{|³ySLÛé¼Â œ ñ-3hÒÏ‹Ì*,E :Ä6»Ÿ;Ã~&D5¶©«Íøc3í°Ÿä8ÛˆmQ¼/©ÿ{6ãÍ´ãpÝ  DA€øF|‹b|³l¦…ky,˜ Ž FIBH`Íš5rÖYgz%ªjƒ#MãÄO”É“'{¹jРì·ß~²ÿþûK÷îÝeñâÅ2zôhyæ™gdÙ²eÞvx <òÈ#Î#×¼…i6Ó·™vZ1B9;fÌùýï/ëׯ÷ò§ ‰´Þvß}wÙm·ÝdÕªU2uêTyõÕW:ô64{챇 :4cýÙ´jÚ~;¦@À®€^'Âßl^ÇTÖvúvk¯æ©ß2&ý¼È¬ÂR¢#@l³û¹3ìgBTc›ºÚŒ?6Óû9Aþˆƒ±ØÅû’ú¿g3þØL;× Ê€@ˆoÄ·(Æ7›ñÇfÚQ¸&Ç‚ ”Õ(5}¤š@ ¦ÑOê?ÿùOÊ4JuîÜ90žvÚiU:“O>Ø¿k×®)óXµŒi˜îòRæqjíÿßÿû·uÚLßfÚnþÃüzÊ)§êBëfîܹY³üÜsÏ¥vÜqÇÀ>/¾øbÆímÚF5íŒP,D‚ D%¾Ù¼Ž)¨íô Zi#¾eFMúy‘Y…¥„_€ØV^GI¿†E5¶iíÙ¬;›i‡ÿê@ˆ®±­¼î’~ #¶eþNúy‘Y…¥DC€øV^OI¿ŽE5¾Ù¬7›iGãê@. (ЮvZ±3T[Àü#Ë]wÝ%]t‘y䑲Ï>ûÈ5×\#ãÆ«všº£>†mÈ!4 $=zô,sgÊÊÊäŽ;îpg×gŸ}60™¾Í´ýeëôôéÓeìØ±^öZ·ní<"­M›6Þ²ô íÉêÌ3Ï ,¾÷Þ{ó:cÓ6ªiW@bD ŠñÍæuLQm§_г˜ñ-3nÒÏ‹Ì*,E œĶŠõ’ôkXTc›Ö¤Íº³™vų% Pb[E½¤_Èm™ï‡'ý¼¨øŸÂÂ-@|«X?I¿ŽE5¾Ù¬7›iW<Y’%¡–)c(6nÜè4 9r¤|÷Ýw²nݺ‚äóå—_–ùóç{izè¡rôÑG{ó™&´1Ò^{íå­?~¼˜ž¼yÿ„Íôm¦í/CX§_yå•@Ö.¸àiß¾}`Y¦™K.¹Dô‘yî0{ölY¸p¡;ë¼Ú´jÚ f@ `QŒo6¯c k;ý‚Už¥„ˆoÅOe©*IÄ Û*V=±-šŸÝ´&mÖÍ´+ž…,AšÛ*ê%ýÕÏmZ“6ëÎfÚÏB– €@Mˆo“~‹j|³Yo6Ó®x²$ 48JB-SÆD |üñÇòöéÓ'0Ÿmfÿý÷¬>|x`Þ±™¾Í´Ýü‡ùuÒ¤IìvØaùl3ÚØhûí·¬NO˦mTÓ€1ƒ¡ˆòµÆfÞC_q&ƒé1‰øV^kI?/¢pî’Gl ؼØL[]l§oÛ¾¦éG5¶Ù®»¤Ÿ5=¯Ø8ؼØL[ím§öú%¶‰dºžôó"ìç-ùC X6¯6ÓVÛ髪{œ¨Æ7›õf3íêÖûE[€GÑ®?raÚµkËí·ßžq¼âŠ+ª]²Ï>ûÌÛ·V­ZÒ»woo>ׄ¿‡#Ý.Ó,]n3}›ikÞÃ>Ì;×ËbóæÍ¥U«VÞ|e:tl2kÖ¬À¼MÛ¨¦b &Åøfó:¦°¶Ó/XåYJˆø–¹wÒÏ K§É"`E€ØV‘5é×°¨Æ6­I›ug3íŠg!K@ &ĶŠzI¿†Û2ßOúyQñ?…%„[€øV±~’~‹j|³Yo6Ó®x²$ u“PHʈ@´1Ð1Ç“1kÓ¦M“;ï¼3ãº\ u¿ x›ìºë®²å–[zó¹&ºuë& 6”U«V9›M:µÂæ6Ó·™v…‚„tÿO›6mª”Ëü1°½¿’MÛ¨¦Àb *µøfó:¦°¶Ó/håYJŒøVÜ÷T–ª‘dH´±-XýÄ6‘(Æ6­E›ug3íàÈB€ØTäFlÓ3"ý~8çEðÿ„9¢ @| Ö×±hÆ7›õf3íàÙÇ\’èá(IµMYc/0nܸ@;wî˜Ï5S¯^=Ùf›m¼MÖ­['K—.õæuÂfú6Ó"Ä3ÿüç?åÅ_tÆ{ï½7^½ºÂãjvÚi'o›¶QMÛÃa"!åkͼG¢òL&‰oÅ}O•ó‚|"t›ñÁfÚZo¶Ó¹ÅØf»î8/¢pæ’Gì Ø¼ØL[Ul§oW¾0©ÛDÒï‡s^æÜ"¢.`óZ`3mu·~ê6ŠñÍf½ÙL; çy´#@Gv\I’ø{7Ò 4kÖ¬JùhÚ´i`{M¯I“&Þ2›éÛLÛ+@È'ü„ª’Õ;î¸CÖ¬Yãí¢½Å¡Þ8'¼*eÄ Ø¼ØL[+ÎvúQ89ˆoåçA±bsÎ òˆvãƒíØc;ý(œQŒmêj³îl¦…s‚<"€@´¯1\ÃDˆmåÿÅz.¸ŸÝ8/¸²!€€ ؼØLÛvÞ£rvD1¾ÙH/:48ŠN]‘S*HUíá¨qãÆc,_¾<0o3}›i ƒ™I“&Éõ×_/ãÇ”fÇwt–š›¶QM;݈y·@”¯56óîZ«zî’ßT†ó¢êç{ 7›×›ik=ØN?Nu¦Øf»î8/âtæRª'`ó:`3m-­íô«'νˆmù×Ke÷ÚóO‰-@ ”6c„Í´ÕÌvú¥¬—B;LñÍf½ÙL»ÐuBzÑ ÁQtꊜ"P©@­ZµÛÔ¯_?0_Ù̺u뛤ÿ Ãfú6Ó*Â3K—.•ûï¿_†*6l”ä7¿ù 4H6lX®36m£šv$ €@¨¢|­±™÷PWZ2—´ø¦4œU8Aؘ ؼØL[«Ãvúq¨ò0Æ6ÛuÇy‡3—2 P3›×›ik©m§_3ÙpìMl)ô½öpÔ,¹@ÊlÆ›ik¹l§_™]Ö‡1¾Ù¬7›iG¡¾É£Ùq%UJ"ЪU«Àq—-[˜¯lfÍš5Mš7o˜·™¾Í´…ˆàŒ6.zöÙgǧ-Z´(P‚-ZÈÕW_-Ç{l`¹ƦmTÓöû0áˆòµÆfÞÃ_s¹s˜Ôø¦*œ¹Ï Ö"›×›ikÝØN?ÊõæØf»î8/¢|æ’w #`ó:`3m-½íô #\šTˆm¿¸ú^û/)3…a°#l¦­¦¶Ós½U–·0Ç7›õf3íÊÌY_Å·n)YZ¶l(uU?­^½:°¿6fñ6Ó·™¶¿ Q›Ön¯ºê*ùöÛoY×VÈ}ûö•Ë.»Lš4iX—>cÓ6ªi§1áˆòµÆfÞÃ]k¹s—äø¦2œ¹ÏÖ"›×›ikÝØN?ªõöØf»î8/¢zæ’o '`ó:`3m°~ᔋ›±Íî½öâÖ&GCê ØŒ6ÓÖòÚN¿º¦¥Þ/ìñÍf½ÙL»ÔõÊñK'@ƒ£ÒÙsd .PÓ@1þü@ž Ýà(Wú¶ó(XDfž~úiùÛßþ&éºÛwß}åšk®‘.]ºäU›¶QM;/86BÐDùZc3ï¡© *f$éñM¹8/ªxÒ°91°y°™¶V…íô£XÝQˆm¶ëŽó"Šg.yF °6¯6ÓVÛéVº8©Û8/Šs¦qÂ/`3FØL[em§þÚ«˜Ã(Ä7›õf3íŠÚ,IŠ Ž’RÓ”3ébΜ9U*÷ìÙ³½íëÖ­[¡ç›éÛLÛ+TD&–/_î<&íí·ßä¸cÇŽ2`ÀéÝ»w`ye36m£švef¬Gp DùZc3ï᪥ÊsC|ûňóâ ¦Hª€Íë€Í´µ¾l§¥s"J±ÍvÝq^DéÌ%¯Ø°y°™¶jØNߎ¸T‰m¿ô$Ïyaç#U¢&`óZ`3mu¶~”ê2JñÍf½ÙL;Jçy-¬ Ž ëIj”T uëÖã3&0ŸkF§æo Ô½{wÑÇvù›éÛLÛ_†(LkïEþÆFÚøë¢‹.’sÎ9Gêׯ_å"Ø´jÚUFd(©@”¯56ó^ÒJ©ÆÁ‰o¿ q^übÁI°y°™¶Ö—íô£tND)¶Ù®;΋(¹ä;6¯6ÓV ÛéÛ·“*±í—ûáœvÎ1RE j6¯6ÓVgÛéG©.£ßl֛ʹ£t>× Ô.lr¤†¥èܹsà ÄäÉ“eÅŠyeI'mذÁÛ¶OŸ>Þ´;a3}›i»ùÂë“O>)#GŽô²Ú¼ys:t¨ôëׯZ4!›¶QMÛf"!åkͼG¢ò6e’ø¬-΋ s$QÀæuÀfÚZW¶ÓÊùµØf»î8/¢ræ’Oì Ø¼ØL[El§oO½°)Û‚÷Ã9/ {~‘Q°y-°™¶zÛN?*uµøf³Þl¦•ó|^€G…7%EJ&P»vm9ꨣ¼ãoܸQFåÍçšxÿý÷«>øàÀ¼ÎØLßfÚ ÒÓ§O—Ûo¿ÝË]Æ eÈ!¢½MÕd°iÕ´kâɾ P|(_klæ½ø5Q½#ߊûžªzµÄ^ Pl›ñÁfÚêd;ýb×EuŽÅØf»î8/ªs&±ñ°y°™¶Ö‚íô£PÓÄ6‘ôûáœQ8sÉ#öl^ l¦­2¶Ó·¯_ó#D1¾Ù¬7›i×¼¶H!ª48ŠjÍ‘o²sÌ15Ú`¥²añâÅòÜsÏy›m»í¶Ò±cGoÞ?a3}›iûËÖé—^zIÖ­[çeoРA²ë®»zó5™°iÕ´kâɾ P|(_klæ½ø5Qõ#ߊÿžªêµÄ P ›ñÁfÚje;ýRÔGUŽÕØf»î’~^Tåb[â*`ó:`3m­Û釽Ήm™ï‡'ý¼ûyKþ(–€ÍkÍ´ÕÇvúŪƒê'ªñÍf½ÙL»ºõÄ~Ñ ÁQ´ëÜ#PA K—.²Ã;xËÇ/Æ óæÓ'–/_î<®kåʕު“O>Ù›NŸ°™¾Í´ÓËÆù×^{ÍËÖvÛm'Gq„7_Ó ›¶QM»¦¦ìňòµÆfÞ‹[ Õ;ñ-³[ÒÏ‹Ì*,E Y6¯6ÓÖZ²~ØÏ„¨Æ6Ûu—ôó"ìç-ùC 6¯6ÓVÛéÿ&Ç ¶e¾žôó¢&çû"'›×›ikØN?ìõÕøf³Þl¦öóüÙ¨S“doºé¦ãÍþ…é~£&a_b&°hÑ":t¨WªvíÚÉñÇë¿[~C£FdäÈ‘ÞÆ}ô‘4mÚTºvíêt¡è®˜={¶œ{î¹2nÜ8w‘têÔI,uêd¿<ØLßfÚ^!C81iÒ$ùÇ?þáåLþ‚ d̘1Õ[¶léÔ¹— ™°iÕ´ý>L#€€}0Ç7›×1•µ¾ýÚ«Þˆo¥{OU½c/¨ª±ÍÞçΪÖE±¶zlS'›ïKl¦]¬:æ8$]€ØFl‹Ú}IýŸµl¦ôë åG ˜Ä7â[Ôâ›Íøc3íbþ_s¬PÜ]«&ÙH¥RO™ýO¯I싦M›èÝfÏ=÷”§Ÿ~ºâ†9–\qÅòꫯ¶(++sÑÕ AùüóÏeÆŒõuëÖ•'žxBzöìXžiÆfú6ÓÎT–0,ÓVÖ—_~yÁ²òÐCÉ!‡R!=›¶QM» @Àš@Øã›Í똢ÚNßZÅÕ aâ[ißSÕ êØò ¶ÙýÜ™g5u³8Ä6³ù¾ÄfÚE­l†@BˆmĶšžú¥¸/©y¶l¦]SoöGüˆoÄ·üΔì[•"¾ÙŒ?6ÓήȚ ”Õa¡(›o¾Y–,Y"~ø¡ç1kÖ,Ñ1ÓаaCyàòjl¤ûÛLßfڙʆe?üðCQ²aÓ6ªižƒ €@Á¢|­±™÷‚8!â[å I~lƒ¥°y°™¶ªÙN¿´5SÚ£Û¶µ™¾Í´K[+ò°y°™¶–ÏvúùÆq;Û¶6Ó·™vëš2!W›×›ik}ØN?®užO¹lÚF5í|ÜØ&Òeµj’ýT*õ”Ùÿôš¤Á¾ € € € € € € € € ²Ú‘É*E@@@@@@@@’ Ðà¨äU@@@@@@@@@ˆŽ Ž¢SWä@@@@@@@@’ Ðà¨äU@@@@@@@@@ˆŽ Ž¢SWä@@@@@@@@’ Ðà¨äU@@@@@@@@@ˆŽ Ž¢SWä@@@@@@@@’ Ðà¨äU@@@@@@@@@ˆŽ Ž¢SWä@@@@@@@@’ Ðà¨äU@@@@@@@@@ˆŽ Ž¢SWä@@@@@@@@’ Ðà¨äU@@@@@@@@@ˆŽ Ž¢SWä@@@@@@@@’ Ðà¨äU@@@@@@@@@ˆŽ Ž¢SWä@@@@@@@@’ Ðà¨äU@@@@@@@@@ˆŽ Ž¢SWä@@@@@@@@’ Ðà¨äU@@@@@@@@@ˆŽ Ž¢SWä@@@@@@@@’ Ðà¨äU@@@@@@@@@ˆŽ Ž¢SWä@@@@@@@@’ Ðà¨äU@@@@@@@@@ˆŽ Ž¢SWä@@@@@@@@’ Ðà¨äU@@@@@@@@@ˆŽ Ž¢SWä@@@@@@@@’ Ðà¨äU@@@@@@@@@ˆŽ Ž¢SWä@@@@@@@@’ Ðà¨äU@(¼ÀÂ… ¥V­ZÞx÷Ýwþ ¤ˆ €@‰ˆs%‚ç° €¡ >Š 6LÚµkç³fÍ u‘9@ ÉÄ­$×>eG’)@ìKf½Sjâ.P7î¤| € € € €ñX±b…Ìž=Û+è† ¼i&@@@@ +@G…õ$5@@@@@(€À 7Ü :tðÆü±©’ €á ö…·nÈT ‡£Š&,A@@@@@ ,Z´Hf̘áå‚Þë< &@b*@ì‹iÅR,b*@G1­XŠ… € € € € € € € €€ ÙP%M@@@@@@@@b*@ƒ£˜V,ÅB@@@@@@@@À†@]‰’&ØøùçŸEÇÖ­[K‹- zÀuëÖÉ?ü mÛ¶•Í7ß¼ i/[¶LfΜ)óæÍ“¦M›J‡dË-·,è1fÏž-S§N•&MšÈvÛm'7Ιþœ9sœ<ÕªUKvÛm7©_¿~Îí«²2Ly©J¾Ù(µ€8·aÙ1c†|÷Ýw²jÕ*éÚµ«tìØQj×wü°Ä’°ä£Ôç&ÇGJ)@|,×O¥R2eÊ™5k–ìºë®Ò²eËRV ÇFÈ"`#ne9T^‹«?ÂôY(LyÉ @„ „)öU%îã¾)1,aÿ |Ì…ê)32 €@‘ÞyçTß¾}S[l±EÊüzc£FRgœqFê³Ï>sr²`Áonw×]wUšÃ &¤.»ì²Ô~ûí—jР·¿it”ºêª«RæF®“†iŒ”ºà‚ ¼Ñ=f®˜7*©þ󟩃:(U§N/m· ]ºtI 4(5wîÜ\É8ëÞ{ï½Ô{ìá|ð³|ÅŠ©»ï¾;¥ùuÓu_÷ßÿÔûï¿H[óô÷¿ÿ=e¶ßl³ÍR{ï½wê’K.I-Y²$°OúL˜ò’ž7æ@( ØŠs_~ùeêðÃO™¥k¾Æ Ó°Ö‰) H­Y³&#Û¿ÿýo/îh úóŸÿœq»l O:é¤Àþ'Nô6 K, K><&@<$ÆÇ¯¿þ:;Gíx¬_¿>uûí·§ÌK¼˜þè£zVC† ñ–kœŸ>}º·.Ó„~Ž<ùä“Ç:çœsRk׮ʹ9Ë@ò(Dܺÿþû½ks«V­×önݺyëþú׿rTø¦ÏBaÊK–@œ¥Š}Õ‰{é©é}S7=b˜+Á+‰hgî¿T0\48JÜ9CK! 7AÏ>ûìÀ‡kóŸ[aÞôГÒÚUmp4lذ ˜ÒÓ׆8/¿ürÊô8î3Ï<““dܸqõ¤§íÎ7kÖÌi˜”+Á_|1p|ÍÓ´iÓR;í´S`¹›¦ÿUË©ƒ6l:ðÀ+Ý^*-_¾ø0=îyûéþ¦G¥ÔƽMÂKÂ’† @T’ã£60r㮾Ž92ezËÍø9®º Ž4–ëbüÇéÑ£‡óyšÓ@ ê…Œ[W_}uàúì¿Vû§Ï;ï¼@F«?ÂôY(Ly À2ƒ Q Ô±¯:qÏ-H¡î›ºéÃ\ ^Hœ@»p??Â|z`@ éÚ¡ùÅ¥üë_ÿª”Â\Âäºë®“Ûn»­ÒmuMÛôä#¿ûÝïļ1ʹéõAN<ñDùÏþ“s;ÿÊO?ýTzõê%_}õ•±3éQm‹/ókR¹øâ‹+lŸmvÁxðÁ‹é-"Û&ÞrsBÆŽ+¿ýíoå£>ò–g›5j”}ôÑ¢eÏgS^òÉ/Û €a°箽öZ'~š>^Qõ‘+Ý»w—Î;Wx„æçŸ.»ï¾»ü÷¿ÿõ¶×‰öíÛKïÞ½½e+W®”áÇ{ó¹&žþùÀêÓO?]ôžÙ†°Ä’°ä#›Ë@¸ ƒ5lz6’c=6¯ÏqÁ=3Ï™ÆFrÄGˆé ×Û`¯½öóËä‚?²Ü; €@ŒlÆ­š°U'~„é³P˜òR“z`_@ ŽaŒ}U‰{…ºoš­n‰aÙdXŽÓ¸Ž×H[àÆo¬ð‹žÃ;,õøã§¾ùæ›ÔüùóS¯¿þzê / ô¾`þY½ý²=RM)æß®^½zΣٴûGíz~òäÉ©¡C‡:]̻ۥ?-[G¦ñP*½Ëcí…è…^HÍœ9ÓaÔcècjÌ—¯|è±î»ï¾ŒÔé­¤µ— 7o¦áTjĈމæ]´×$w½¾Ö­[×›oÑ¢EêÎ;ïL}òÉ'N¯Gæ‹æÔ¥—^Zá‘;šÇLC˜ò’),C¢ `+νñƸ¸çž{¦LC؉¹1Òžø=ôP/6h¬ÐmÓí=ÁOôñ+ù Úk’¿o¿ý6°[XbIXòÀaH°@Òãcú/uýë_âiYYYêÈ#LiÏï¾û®w¦äóHµ¥K—¦´7[|Þwß}+}¤¶w&@*:nýøã©1cÆ8£~öò_³õ>¨»N{£õÕ‰aú,¦¼ø]™F¨(†ØW¸§%)ô}SM“¦ $R€Gª%²Ú)td´ÑNÓ¦M½Õú8—Åâ/Œ>^Ì¿½ûa×Dÿþýîõ3m£ÆÑ®ñýƒi $ÿüç?Å4¸ò/ö¦/ºè"1=!yóãÇ÷¦+›S^*Ë+ë@R ØŒs_|ñ…W¼=öØC¶ÜrKo>ÓD¿~ý‹¿üòËÀ¼i´$Gu”·LEj~ äÍgšÈô8µLÛ¥/ K, K>Ò}˜Gâ.@|Ì\æÇ\çÙ¦7¢ÌT²Ô|)à|æõ?:UÏ­ñ¼qãÆ•ìÍj@l6ãV¶cVeyuâG˜> …)/Uqg[@ ÎaŽ}ùĽBß7ÍV×İl2,G ^µãUJƒ@|Lo@òÿ÷^LDrÕUWyóÙ&ÌcŤsçÎÙV;˵“éÅÇÛf‡vmPTÙ _ƶiÓ¦²ÍdÀ€²víZg;Ó+“ÓØÈ<Š-¯ý´1;<öØcîdÖWýùúë¯Ïº^Wì¸ãŽõgœq†téÒ%°Ì?c-'Ûn»­·è§Ÿ~ò¦sM„)/¹òÉ:@ 6ãÜÆeÊ”)^1Í#HÅü¶À›Ï4az7Ó#  <ØwÛm· ›™_ÿ–¥7( ¬43Ï=÷œ·Hãà)§œâÍg›K, K>²9±ˆ«ñ1{ÍêZš7ož}ƒk-Z$æªòÙgŸy[énÌcyÄôZè-c@ j6ãVÕr’}ëªÆ0} S^² ³H–@Øc_eqÏÖ}Óô³€–.Â<ñ ÁQ|ë–’E\À<ÊEü ]þøÇ?fí‘Ç_TýBS{BÊ5Lœ8Q´gwО‘òi¤žþô§?¹»e}õ÷L´ýöÛ‹ö,‘ÏЪU+éÝ»··©yDœè›·\ƒy4š4kÖ,×&Ò¢E‹Àúnݺæ3Í4iÒÄ[¼páBo:×D˜ò’+Ÿ¬C `3ΙGiŠÿZ?wî\9ï¼ódÆ 9‹®ñóšk®qÆ>}úTØöˆ#ŽÄ”×^{MV¯^]a;]`ºù¯ð¥f>vÃKÂ’Œ¸,Db,@|Ì\¹ú™2W¼™÷*_º`ÁѸîÿ¯ÆôW^y%g/¼¹Òd €@¹€Í¸UãêÄ0} S^ Q¤ÄA ̱/Ÿ¸gë¾izÝÃÒE˜G ¾48ŠoÝR²ˆ |÷ÝwT¥Ûø®]»öMŸ™:uj`ÑA˜Ï5³óÎ;çZí4’Ò®êÝA§V•Áÿ±ö’4}úôœ»o³Í69×ëJí±È?h#¨ª Úâ;Ÿ!LyÉ'¿lƒ”RÀfœÓré#Rüã>*zÖEUyT¦? í…ïä“Oö-[¶,ëã?Ó{?:í´Ó¼ýrM„%–„%¹¬X‡ÄQ€ø˜¹V»wïžyE%KõG<‡rˆó(6wSçO<ñ„4hÐÀ]Ä+ €@5lÇ­jfËÛ­:ñ#LŸ…”• @ áaŽ}ùÆ=÷MÓO bXºóÄW n|‹FɈ¶@z£ :ä] ÊyzÚúHµ|‡Êò1yòä@R&Lßÿþ÷e¹f&MšX=kÖ,ÉÕÈ©²üÛ4Ó¶mÛL‹k¼,Ly©qaH°,‹ªr ­,ÎiÖ(}ôQ —¡Ù³gËm·ÝæŒÚ«^¯^½œÇ«h/ù_«öðÃ{:Ú°H{ LüSÓGµwÜqé›dœÏ7þmĵ°äÃ_N¦@$3×rU>³úS8öØcåÇô/rÿ}à 7ây`f@ò°·òÎH– «?ÂôY(LyÉBÌb@ qaŽ}ùÆ=[÷Mý'1̯Á4ñ ÁQ¼ë—ÒEX ýMK>_®ºÅÕ/õiÙ“žvóæÍÝ]+}­,™i££ê«V­Ê¹ku¾dÕ.#m aÊ‹ò‘& PHôXTY|ñ»²8§Û6mÚTFŽ)'t’óêß_§µÇƒ^xÁu^·žrÊ)ΣC[¶l©‹2ÚpÇŽåûï¿wÖëãX´G>í-Áf̘!£GvgE¿ìÔFGù a‰%aÉG>flƒÄI€ø˜¹6ëÖ­Þí«ôÆFnêC† ‘SO=5ðHow¯ €ù ØŽ[ùç$ó–Õ‰aú,¦¼df) <0Ǿ|ãž­û¦þ³æ×`x ØùÖ=Þf”¢hÏ>þ¡E‹þÙœÓÚØ(׋ô›®Íš5Ë™že®tu;ý’µÃêÕ«s&§e ˦¼„Å„| €ÙlÆ9÷˜úáù­·Þrz:úÃþ ¹}óÍ7rã7:]{ì±ÇÜ$*¼ÖªUKüG[²dI…MéSÓ^‘òÂKÂ’|ÝØˆ‹ñÑNMj,¾îºë¼ÄS©”œ{î¹RÙçMo&@2 #ne<°Å…aú,¦¼X$'i@ Rq‰}6î›ú+’æ×`x Tï'bñ6¡t„B@[ÿ~ýõ×^^ô10Ûo¿½7ŸkB{mX³fMÖMÒ{YX´h‘´iÓ&ëöþóæÍóÏV˜.++ ,;ÿüóå„N,«ÊL·nݪ²9Û"€DDÀfœK'8à€DÇ7:=½ûî»òþûï˨Q£$½'=×/ [·n-GydzRμ68ºõÖ[½uÚÀÈ¿­ÿqjšÎ¡‡êmË €¹ˆ¹tª·î’K.‘»ï¾Ûé‘ðÙgŸ•)S¦8 éëM7Ý$ûÛߪ—0{!€H1ãÜ €„A n±¯Ð÷MÃPGäŠ+@GÅõæhä-þ¬Õ™3gæ½oeÛ¦÷hT•^‰*K»sçÎ|ê#f~õ«_U{Üj«­é1ƒ ›q.›>Rsß}÷uz8ÐÇ­iƒÛ7ß|S.¸àiܸ±·›>’ô /ôæÓ'ºté"={öô¿üò˲nÝ:g^ã¤ÿqj}ûöÍÙë — €âcaOƒ[n¹Eî¹çÑ 7Ûl3yðÁ¸ë®»dìØ±eÌ €ä/PЏ•îØ@ Ä5öê¾iáÅIÂ.@ƒ£°×ùK¬@zÃ÷W˜ù€LŸ>=çf:t¬¯¬‘cýb6מïÉ“'çÚœu € H…Œsù’ê‡v˜<ôÐC2nÜ8ñÇÇ~øA´ÇÀlƒÿ1iÚpI{MÒá…^}L‹;ø·s—ñŠ €@6âc6™ê-?ãŒ3;j¯ƒ¿ûÝï¼eëׯ—sÎ9Gô•@ êaˆ[UÏ5{ € P}¤Ä¾šÜ7­¾.{"€@hpÅZ#ωHo%ýÄOä]îʶÝ{ï½i½úê«ùl3ú(íÅ!× fÓg¿ºÃçŸ^áq5îºL¯ú˜šwÞÙ{÷îøÒ6Óö,Cˆ¦€Í87hÐ /–¤Ç¼lZÛn»­\|ñÅÕ_}õU`Þ?£=ùŸEî>FÍ}ÕmwÚi'ÙsÏ=ý»1 €@NâcNž‚¬ÔÇ«ù{ýÕŽî¼ó΂¤M" €@ÒlÆ­¤YR^@hD=öã¾i4j’\"€@¡hpT(IÒA ÀúÈ—-Zx©Ž5J¾üòKo>ÛÄĉåµ×^˶ÚY¾ß~û9ÝÉ» :Tòy¬Ú!CdÚ´iînY_õjî°`Áyä‘GÜÙœ¯úx›aƉ–AÇ]vÙÅéú>çN¬Dˆ¤€Í8§ãtcÉÿþ÷?©¬ç?Ðß`V—µk×Î]UáUØj/ î  rµW¤O?ýÔ]$é½*x+˜@@ ‹ñ1 Lk Ó„?NýüóÏrÑEy1XŸ{î_Ÿi–!€ .@|L±3Þy牿Dý,|î¹çzqÜÎQIˆŸ€Í¸åjég+ÿPÙ=Fÿ¶L#€ Ph¨Ç¾bÝ7-´;é!€@x‚ïÖÛOr†@"úõë'þî?úè#9è ƒ26ÞY´h‘hÏBo¼ñF^V×^{­4iÒÄÛö•W^‘^½zÉ×_¸Éºxñb§{ùƒ>X–,YâmŸk¢C‡2`Ào“Y³fIÏž=å‹/¾ð–ù'ty==8}öÙ¢-Å@â+`+ÎuíÚUºwïîÁÝu×]rÝu׉6°Í4è#Cÿú׿ʿÿýooõG!é7¶½•›&Ž;î8Ùb‹-¼Åþûôé#eeeÞ:&@ÈW€ø˜¯Tõ·ÓÿðÃúá‡Ê?þñê'Êž €@BlÅ-—S{bð·Ýv[àÞ¥Ó €C ʱ¯X÷M‹QÂ!P7Ù  I ^½zrÏ=÷ÈÑG-úe¨cÆŒ‘m¶ÙFvÛm7Ñ–È­[·vßòÉ'ŸÈÒ¥KmôKÒ)S¦Èwß}çÌgú³ýöÛËSO=%'t’¬]»ÖÙä³Ï>“nݺ‰¶ÐÞyçE‡¦¡Ñž“Üá /”¿ÿýïîlÖWí­èé§Ÿöº¥Ÿ9s¦è£ÜöØcçKàN:ÉÔ©S嫯¾í=Éÿ%°¾á¹ÿþû³¦Í @xØŠsú%¢>tŸ}öqâ§ÆP}>¹>öLÐjÏE;v”… Ê·ß~+úhQÿc×ô†v>±N{ì±Îþé5¢ g@¨Žñ±:jUßG'k/Âú™Û®¾új9ꨣh4ì‚ðŠä!`+n¹‡Þi§ÜIçõù矗ÆKûöíåøãw~<Ø€@, D9ö뾩å* y‘ ŽBTdLGy¤Œ1BN=õT§n£ €´‘ŽŽéÃ.»ì"Æ tŸ¾;¯ ™´w!ýRT¹ƒöj¤ ˜üC:uäÖ[o•<0ð%lýúõý›yÓ›m¶™ü÷¿ÿ•óÏ?_ž{î9g¹6lúôÓOÑÛ0mBoú¾ð ²ùæ›§­a@ ޶âœ6ʽá†ä–[nñ~ý:aÂÑ1× ñç‰'žV­ZåÚÌ[§MÓKþ¡E‹¢½1 € P]âcu媶Ÿ¾OÐÏ«Ú+¯ú#ýµò«¯¾Zµ„ØH¸€­¸¥¬nCP÷Z­ËV¬X!“&M}´5 €¥ˆrì+Ö}ÓRÔ ÇDâ ðHµâ›sDª, Js;–mgm•|î¹çÊèÑ£вm—¾\(i# }ÜŒ>ÂÌÿhݶAƒΗ¦Ú½ü5×\#+W® $‘ë ÙæÍ›Ë³Ï>+?þ¸óË£ÀŽi3º­öФ”¶Ûn»´µÌ"€ÄYÀVœ»é¦›DGºë®»VÊW«V-9í´Óœ;ì°J·w7м·iÓÆu^ÿûß‹6¼e@@ &ÄÇšèå·o£Fä¾ûî l¬Hõ?f5°’@¬¶â–ö"¡×æÎ;g=6+@(…@”c_1î›–¢N8&_ VM™J¥ž2ûŸ^“4ØòÐGÂŒ?Þ{„Úܹs¥mÛ¶ÎcÐúöí+íÚµË?±,[ê1ôqlú85ýUÓoذ¡·õK/½èµaâĉҥKo}¶‰eË–ÉØ±cGÂécáæÌ™ã¤]VV&=zôp~­Ä—³ÙôXŽ$CÀVœÛ°aƒ >܉oÓ¦MçÏŸïtÁ¯\õ1£Úèv÷Ýw¯ô9çœ#ÿú׿¼}5Vkƒ^@ !@|,„"i €KÀfÜÒÏr“'OýŒ§÷-õÇ%þû–Å*#ÇA@À/åØgû¾©ß‰iˆ¥@ ŽbY¯ {ùË_dàÀÞ´ëâ-·ÜÒ›g@$ ˜øÒ©S'§“–[=ª½2 € dâc’kŸ²#€ € € €@BÊê&¤ |ÚbyĈÞýEPÏž=½ù\£FòVë¬46ò8˜@H À[o½å56Òâ_xá… T È €ˆAæ@@@@8 Ðà(޵J™¨D N:rñÅ{_6iÒDf̘!M›6͹§> ÍßkÃñÇŸs{V"€ wxÀ+âÖ[o-ÄFƒ @ \ù@@@#P;1%¥  8üðýù¥K—ʃ>èÍgšøî»ïäˆ#ŽU«Vy«O<ñDoš @’&ðÙgŸÉðáýb_rÉ%R¯^=ož @’(@|Lb­Sf@@@H¢@­š:•J=eö?½&i°/”FàwÞ‘C=Ô;xݺu¥_¿~rÕUWIYY™³|Íš5òå—_ÊèÑ£åž{î‘éÓ§{ÛŸsÎ9òè£zóL € w'Ÿ|R/^,[mµ•Œ7N~øaY°`SìfÍšÉ?ü Úk  €I >&©¶)+ € € € à ”ñH5Ï‚ ’%ЧO¹ýöÛFZòõë×Ëý÷ßïŒ[l±…´mÛÖùâtíÚµ`ºuë&÷Þ{o…å,@@ ΣF’!C†d,âÀil”Q†… €q >ƽ†) € € € Y€Gªeva)‰¸òÊ+åÖ[o•† Ê»bÅ ™2eŠdjltæ™gʧŸ~*Ú(‰@Dþüç?Kÿþý¡@@ŸñчÁ$ € € € Cz8Ša¥R$ª"pÝu×É\à<fèС2mÚ4ÑG©ù‡víÚÉñÇ/¿ûÝïdŸ}öñ¯b@Äì²Ë.²ýöÛ˲eˤcÇŽÒµkW9úè£å˜cŽIŒE@ ]€ø˜.Â< € € € Z5)f*•zÊìzMÒ`_—€ù¿–yóæÉœ9s¤yóæ²ÕV[Iƒ •Irƒ € € € € € € €¥(£‡£RÑs\B*P«V-§‘‘64b@@@@@@@@Òj§/`@@@@@@@@È&@ƒ£l2Ts”°@IDAT,G@@@@@@@@ 48ª@Â@@@@@@@@È&P7Û –'W`ܸqòÒK/I—.]’‹@É+L˜0A:tè 5ª°ŽÉX°`,^¼X¶ß~ûX|ñÅ2pà@Ùb‹-bU®¤fÊ”)òôÓOK×®]“NAù}k×®•o¾ùFºwïî[Ê$"Ÿþ¹ì¾ûîR§NØp,\¸Pj×®-çw^lÊ”ô‚üøãòÐCÉ®»îšt ÊïذaƒŒ;Vzöìé[Ê$âœú^¸~ýú±áX²d‰¬^½Zú÷ï›2%½ ú~åŽ;îpÞ‡%Ý‚òâøþlY#? ÁQ 㔌¾Qã7DoÜ0 à |ðÁΗÍ›7wñšpY³fÉܹsc÷eÆë¯¿.—^z) Žbv~÷Ýw¢u«7npô÷~(kÖ¬qñŠ€#ðÚk¯9ç…~ÀË S–-[Fƒ£¸T¨)‡¾ÓsU¯e ¸ëׯ—#Fˆ6 @X³f,^¼ØQÚ´i%Mš4‚W{ÊŸ?¿”)SF®¹æš0:j ø&pþüyùæ›odÏž=’!CIŸ>½™ì÷Y²d‘bÅŠIêÔ|<óM’KI€H€H€H€H€H€H€H€H€H€Â…[´ÃåJð8H€H … :tH-Z$¿þú«äË—OJ–,)%J”¼yóÆ;²-[¶ÈÏ?ÿl¦+VÈþýû¥bÅŠR½zu3U®\YÒ¥Ko;O3V­Z%_|ñ…L›6M¶mÛæi—y(·|ùòR¥J©Zµªy-\¸°Ë:ü@$@$@N¨§–-[fD>ö*TÈ«¸õ!ê¦Õ«WËï¿ÿnêDÔk˜©o.^¼( .”)S¦ÈW_}%ÿüóó⽇©B… qu긂 Æ[3H€H€H€H€H€H€H€H€H€H€H PpWÇ@$@)@n è|…ã:D×®]+ÿþûo¼#Éœ9³/^ÜLÿý·@`„W;ræÌ)yòä‘yóæÉ¬Y³Ìl8Atë­·JŽ9Œ#æ9§õëבÑÎ;Í69õìÙS7nlÜp|.\¼b:wîœüù矲råJ3ýôÓOö!œÐ™‹}2H€H€H£%K–ÄM›7ov‚ú¨H‘"ÆU$8 Ap ‘\ˆ¼E¶lÙŒð¢×¢E‹'>g݆÷§OŸ6uÒ—_~)ÇŽ3EaýÖ­[K¹råäìÙ³f:sæLÜûÇ‘Ó/¿ü"Ë—/Û=êÐN:ÉK/½Dw¿8*|C$@$@$@$@$@$@$@$@$@$(8 ‡«Àc  ãÇËÉ“'M‡%:#Ñq‰ ﯿþz#üÈÇ[ìÛ·O ÆùñÇMç%¶…èÿûŸË´cÇS&ÊÉž=»´mÛVêׯoDB{÷î•7ºLèEj3ˆz:tè`ªU«ç¾€T¬ƒýbÂ1@ä+ ( ½{÷–-Z˜ò®ºê*_«»,ƒËʇjìØ±R§N#zÂ11H€H€¢ƒ¶nÝjħ Â‰È®'íWÔyýõ×_qàfôÐCIÍš5åÒ¥KqÛ£Œ9sæqVF:³Ò¥KKƒ ¤R¥Jƹï–[n‘]»v™ú uê¥K—Ê‚ âÊ÷öõeß¾}¥U«VÆQÉÛzÎù¨¯qì¨Û°¯o¿ýV^}õUùî»ïŒSêM „ ŽÂá*ðH€bšÀåË—@žsçÎ8ÿ$Y²d1® p²Ð9 ¡:FíÈš5«\wÝu’*U*˜¯ö÷¡zõꑜb¸6Ô®]Û.ƼBÁQš4i\æÛ æŽ;î0“=)ÒBÄîDSH“Ø€3¦víÚIÓ¦M¥Q£Fæ|fÏž-µjÕJl±ÜŽH€H ˆàð§!8éÁ¹çÔ©SñêÔpB}… .Bö{Ô-Û·o7"!¼B0ä)P‡Á¥¶‡Àu&¸ày ìuŽ«T©RÓ¢NÄÔ¾}{S Ž©ÖPߺ×möñ¡Å6ÎÃÞĽ(¯ÿþ2|øp#ø?~¼©ó-—ë“ @° Ppl¢,H€ü pðàAãZ‘ÑüùóãR®äÎÛ¸Áq(cÆŒ¦ãÔ~E'*¶Û´iSœ;ƒÓA”%K–”®]»—"Š Fr ‰ü84¯« µZ qÓM7ºI¢ÖGÇ.RÃÝsÏ=fB8T0H€H€’Fîxªúp»ƒøÎ<‹-2)ÊP©3i6á(d§#ƒp⤣G!Üþìí v…À)7Q¯ÙÓ7Þ'2‚0)1ý£¼@Ç ÷¢äHã‰}ÁáÂ)š5k&O>ù¤ yr.\—H€H€H€H€H€H€H€H€H€H€K€‚£Ä’ãv$@QK.Hi‚NHtôar:@Ï;'çÏŸ7Þcží¬ÐÕW_·É‘#GL‡ëªU«â^wïÞm–C „´-÷Þ{¯4lØÐ8þ"‚{RÂÀ}¨bÅŠç£XêÕ«ËâÅ‹c:¥§L™ Ä?ü pŽ@'7ƒH€b‘Ä>«W¯ŽK†bH[†4c•+WŽ›àd×;wî4)4íTžëÖ­3®?à‡4 Í›7—;ï¼ÓL… ö+êá'N˜”¢¹rår©Wý.$ŠV¼ë®»l‘þô­·Þ2nQ¨çüöâwÈÔ©Så½÷Þ3×0аðTH€H€H€H€H€H€H€H€H€H€R€k/z wM$@)M©Ìúõë'HÉå¶ð©Mìt)îë8?Ã$ˆ–ÐYkÊAGmýúõ¥Fr÷Ýw R‹%6®½öZv:à!ER÷ s»eË–òé§ŸJ›6mk¸¾Ý¿¿L˜0Á6oÞl"ƒH€¢RvNž<Ùe!’… ¯˜P¯á;pëÖ­q§ú B£²eËÊÚµkeìØ±f p²={ö¾Gí€{ê5ÔouëÖ¤ë ÄÉ.¯ß"-(&†E Ož££•ÙŠ-*H‘Ö®];Ù¶m› M:^áèa:m‘¢"#ˆÌÐË  h!°hÑ"#4úñÇ@¶GÆÅ"¡Ä¶kÒ¤‰™³=· .üfÁ„@Z;ˆŽ Ãëo¿ýfc¨[µj%7ÜpƒYoΜ9æ•H€H€H€H€H€H€H€H€H€H€H (8 E–A$" ±Ý‡ B*÷i×®]FHât·Ë \,X Ø.Æ 3iÎRäD¸Ó(X°  £ÝÜ/A|tòäI“¦'{öìöb¾’ @X@}wàÀÓÐÞ½{åàÁƒrùòeãR§"Û­N}“&M2¢Ë4iÒH·nÝä¹çž“¼yó†õùñàO @‚ ©D$@$@$@$@$@$@$@$@$@$@$\(8J.ÒÜ @¢9rDàÒqÐâÅ‹åï¿ÿŽKs†NUoŽW¸1ÜtÓM¦CtÔ₤JÃ2¤Û‚ÖgD7\c;Z®\¹¢ûdyv$@ABÈ5kÖÈ’%KLýf§ãt¾=zÔŒ:$¾ê=ç ñ­k×®Ò¿“*͹ŒïI€H€H€H€H€H€H€H€H€H€H€H (8 E–A$4èL]¶l™}óÍ7²zõê¸4X%K–”Ò¥KKêÔ©Í„Uû}–,YŒ€"¢Â… ›÷éÒ¥óz\.\8?0H€H€H 9 ìÞ½[.\(¨ã¾ýö[°ÖS ŽË!ƒ\wÝu¦N»ýöÛöÆoLNbÔ›.9_‹/.ùòåóT,ç‘ Ä8¸ã÷œCàƒß7'NœŒ3ʵ×^+x^O›6m(vÇ2I€H€H€H€H€H€H€RG)Ÿ»&¸B©Ð>úè#ùä“OdÏž=fÁõ×_/­Zµ’ ˜tgè` VPl,’,‡H€H !›7o– &ÈôéÓeÓ¦MfõT©RIùòå¥K—.R¯^=#B§DFx…˜ˆA$@$@$@Á pøða™ÙGîµã‘“@Ä8sæŒL›6MÆ/K—.5  H£F¤B… ‚Y DãÇË”)SŒö§Ÿ~2‡Ÿ7o^éܹ³Ýyça-ƒH€H€H€KnB—.]ò(V†ðgΜ9æ·ÈüùóMZq8 =øàƒÆ}Ïà¿üò‹Œ1¤Œ;w®Iës#.ô›@(ë7¶Iú}¸" @”8yò¤iÏF7žÿ1@í×xµ'Ô“EŠ ø™uõ˜1cdÔ¨Q¦ õ8D» W¬ß\yð „ Ž‚p5ðƒóÃ?”Y³fɾ}ûŒK‹],^ *$wÜq‡I™‘‘Ð?ü ü±üõ×_¦3 eã-FÁöºeË–Æ ÆÞ'_I % ôÏ?ÿ4ÒÅØïÑñŠE÷@£'F?>ôÐCÒ®];¿íÛÝËág Ð`Ý®,5r  S{¿ýö›¬[·ÎŒÊ‡ˆ~ÿ9ë:üN«U«–µhѸDî™óÈI z°n‹žkÉ3!h#€gè7ß|S~ýõ×8‘Ü<ž¥‘nbŸ‚:Ð ©Ê0è ëÛ¯x§!´áy;W®\ñŠÂï•Ò¥K›é±Ç3˱~ó¸ö™>}z÷Ù‰úŒv±qãÆ™¶²þýûKµjÕŒèè–[n ¨¼Ë—/^èøõeýÆ6ÉX¿»xþ$[ ¬„S1¾ûìA³xuw÷óF%sæÌR®\9ÓWƒvo¸÷—(QÂ¬Ž²\ÿ>ûì3#À…c!‘_{í5©R¥Šqô¶XšÏú-–®6Ï•H€H ’ Pp”Ä«7uêTó?=ÅÑ£GÓêÕ«›Ë믿nl¦=­ë>.0}ûö5Ûº/CСC‡ÌzŒ¢¯S§Ž >\ð£–AÉM wïÞÆݹ_4zbTR£!MZ¾|ù̃^1åÎÛ£U»³ ¾'H¬ÛR†;÷~,X`œŠ 0úý÷ß]v`cŽ9L݆FD4Úá¨û$@áC€u[ø\  ÀpBç"\~Ð΃ßpH(^¼¸d†f˜0¿- 0Âó4ÜŒBpUH®xî¹çÌù`~;MŸ>]rÖW€:ñŽôìp˜D{X,G¨ê7¶IÆò]Ås'Ø#€ï¼wß}׈àˆ@ˆ: »=;Ož<&ëĮΠ"Xd½€pxÍš5¦®ò—bÙ²eåé§Ÿ–Ö­[›úe0ÄÔõHûì~7Öo¼»H€H€H ø(8JSäšá…<–€‘bî£ÂÐYÕ¤I#B#‘¯€[̃>h”ô¾Ö³—!5FÐCÆ( $–,Ù—-[fîUÊ@çëûï¿/7ß|³<òÈ#¦a´X±bf´"FA2H€"‹ë¶Èº^<ÚÐ8vì˜ íF "•måÊ•¥L™2‚Æ@¼ÂU mÚ´¡;–L$4¬Û‚†’‘ x —C¤<Û»w¯™à|ˆ÷˜Ÿ?~#Â+&¸`£Sât¢ýòË/&K³fÍLgã­·ÞêaÑ; îKpkÂùßsÏ=f œ!ìN\´«áýùóçeáÂ…¦ó|pŒ¸ûî»MÚ¸è%äûÌBU¿±MÒ7w.%HúÉ'ŸW"¤&ÃX<§;'¤'C»5Ú«1AÔ‹A²XwÉ’%òöÛo›F¨Ÿ±Ü÷P?%¥ŽÿA<„¬p÷CJSççÀêÕ«KݺuÃh˜ ë·0¹<   ð“G~‚r_í»ï¾“¸ÌFÃ;` ÷–-[¶ÈÊ•+å7Þ0UXöÔ½6zôh—mÐÒ©S'±~Œâèm·Ýfl9ñzÅŠ2yòä¸Ñö;vì~ýúkjž$(E‹IÇŽM¾èùóçKƒ ,÷ îë>}ú˜´ nÀH€–붰½4<° 3fŒII q¬?t¶!m.~—1H€"“ë¶È¼nø@ÐhÚ¦MŸûàB ð&Àº-¼¯.ñðû ®‘sæÌ1õÛ]wÝåWº³±cÇg£öíÛ'~çÜ’H E °nKQüÜ9 D<tPBxŒö89©UsåÊe~S``\zì éVð™H¯b ”ì÷øm‚NÍîÝ»›ßÎrcõ=:•1¨íao¯=¡ã,Ñ‘Œ‰!¦C=Tí’l“äF$0ƒ´Ç7pÛyܺmÖß~û­q „©[·nfð,€û ¤åúóÏ?ã¦M›6™úÏû¨!he¤

¿±~KùëË#  ˆ^%âÚ~õÕW&O¼½)lŸ_}õU±‘½ ¯H¹QÐÈ‘#ãfCtäIp„UèàrÆÐ¡C½6ªäÍ›×üoÛ¶mÜ&øñDÁQ¾I€l]qÿ¬^½ZàÒ…"Ï>û¬®mܸÑ<Ìy+£H`ߥK#:ò¶ç“ „?Ömáx„€Vè{öì‘Zµj»ô7ß|Óˆj}•[u4@öîÝ›iÓ|â2s¬ÛÂüñðH  MæË/¿4®9H]”^p(€«Ò¬(PÀ¤FC[ R±$Ø–á9rH=ü[9Æ× UýÆ6É¿±xú$HSgük¯½ÖcépÄ n8èÃQ°J•*&ƒÒ˜oذÁLhŸÆ{´AŸ={Ö¸¡¯¥Q£F~?¯#­ÊÆÄ_¬ßÂ÷ÚðÈH€H€HÀT¾rY|ø‘üþûïÇ-€ªþ¹çž3£­âfzxƒ|ôe:±<ÅÌ™3åСCq‹î¼óN{’¯À/çåßÿ]vïÞík.#C#5Ë—/orJ#?õÒ¥K¥P¡BÒ³gOÓ°:jÔ(Ÿ¤Æg–CpÄ ˆ\¬Û"÷ÚñÈ=ÀÈøÁƒKíÚµåØ±cÆj¶ÜeË–8ó!5­¯4ý𝲏ŒH e°nKîÜ+ D*‹àg"¸÷B´Ü²eKY¸p¡lÙ²E† b’AÀ ‘?b£HeÁão¡¬ßØ&ÞמGG‘D}hk†ëÄ>¨7áR„t˜xNG‹4føüé§Ÿ Òk¹nwM›65umÆ ¥OŸ>Æió‘fíÔ©S2{öliÑ¢…ßb£HâËÇÊú-–¯>ÏH€H Ò Ðá(À+¸fÍš¸ôeØ‚ ìÙ³'X Fj½ôÒK&/0Vö¦ê_¶l™KYuëÖuùìí,¼W®\·øë¯¿–Gy$î3ßÀÉ“'ÍhŒÁ„û÷[¾|ùä³Ï>“;î¸#œŽ b›0a‚¼üòË&§uÜÂÿÞœ;wθ!áÁ°jÕªî‹ù™H ‚°n‹ ‹ÅCMÀþýûåþûï¸@`4eÊ)V¬˜Ùî™gž1ËÞ{ï=3jÒSa~ÃÙ N:ÆÉÀÓ:œG$þX·…ÿ5â’@° ÀõéRà‚€A^Õ«W¤Rõ'ž~úiãJ]´hQãøÛ±cG¿Úzü)›ë@0 „²~c›d0¯Ë"È$pñâEÁ`£Gš—ÌcOçfÈÁ<_Ãõ/cÆŒñN¢¡Ñ£GˬY³LÚ3ˆt‘å9rDVƒ¥10åA\Ô¯_?©\¹r¼²<ÍH›6­§ÙœX¿EÁEä) Ä, ޼ôH;å Œ|ó7 ÜO(` jòÔCÝïO8ް>GþP‹þuÐÐ .ü`ßµk—Ë ãyªß~ûmAÎk÷xòÉ'Ír¸õíÛ×}±LŸ>Ý<4(Þ2Î ˆ,¬Û"ëzñh=@šOhÇo1{ì1ÓqèllݺµiÌD݇tižÜ àþ‡t>ú¨çq. @D`Ý—‰II"€ÿóiÓ¦ÉüaDF;vì0¢v¡W_}µq9Äs¯¯€³ïÈ‘#åöÛo7ŽFÎß¾¶ã2H ¡¬ßØ&™W”û$ð °jÕ*3ð©Í J(Ðoô¢܃ ²?ÿüs#øE–~»wïn\Œ°®{@ÄtþüyIŸ>½û"~ŽQ¬ßbôÂó´I€H€¢‚G^FçØÂ &X±mÛ6ÓAf—‡\Å×_½ýÑç+\fð#ú[·nõ¹>F?ä¼õ”üùç«xh”*U*nBê4gš?w"ÈÁ âwÞ1²Hè ¤¤AC,\$’#ôTEGψ<þ¸ˆ‡gÕä8 ’붨¼¬1qR{÷î•I“&¡GŒ ;v¬4oÞ<ÔeH ±ÄI:urY#,±m®\¹¤I“&.ËøH ²°n‹¬ëÅ£% Àaâĉ&EêºuëÌfÙéUJ–,)%J”0Ÿ>ø À©Bâ‡zÈã.f̘!½zõ2Û ÅF1qfUýÆ6É0ºÈ<H&xžÆs1î1hzÏ˨WÑnìœ :qâ„q„£ ¦ŸþY-Zd¶Í–-›À1°[·næ¹ÜÌôòåRläNŒÎfý£ž§M$@$\QqJ¡; (ïýõ׸äÏŸ?î=Þüõ×_²téRA*¤¯‚ £H‘"Få´U …ÝQf¯‡öþÆ5×\£¢’üæ‡>¶ý)ò{KÝæo¹\/|`¤\‡*V¬(Ï?ÿ¼é õttè,4è%Má—NhVÙ½»–Ô«'òÀž¶ð<÷F¢`_p3‚+„¸×—,Y¢‚¦¶Ó­ÙëëU³·I³f"ó狊üDžx"X%§l9Ðêsº^ËÀ_E Š6Œ‹¨6Q t-C/›Y®)ÓÕºXôžMŸçº?Å' _jùœ!þ‚(žÃº-Š/n„œ~¯ÀRéaý¹sçÊ›o¾iÒ¦áFÃ&‰ ‚M¨œ®]»š4·¯¿þºé|t޶üæ›o-pD=È ˆL¬Û"óºñ¨IÀ<ã"½ ½@ G C‡&„D*T¸¹Ç÷ßoR¤vîÜÙˆŽÜÓÎÿøãÆÕ7GŽ2oÞ<οîeò3 ¤$PÖol“LÉ+Ë}“@ò¸|ù²ÉŒ0fÌmgoœo¸áÜù¸éVªT)àƒÙ·oŸqÖ/W®œ¤K‡öh F€õ[`¼¸6 „ ޏ"¶ÈÞ¶¡Œxá…Œ·½ÌýµvíÚF¸áKx„ÆÎÈš5«óc‚ïÑàæ ”—ÁÑöíÛý©í\ƒ~~h Wœåó}ò@ã*:EÑùyéÒ%ùé§ŸLº˜=zHŸ>}\\° tëСƒÌœyPn¹6¼žW‡¢´Ò®hC¬h#«ˆö³úh2dˆéÔu Žìû¶¾â ÷þÚ_Ñ4*œµ×)PÀW Ö2=mñ‰té"Ê!þú: FGÞßõ‚ -[D6o† PâmÓ–Ò¥ãCbæ¼òŠ([K •›‰”)™ðž}ÖZOÛÁãbÁ‚+,7½æq‹Ì¯>ïëý!z¿ˆ:€ˆhv!ÃÏOã4×£øÓn½°È¿wo9Y¾¼›~o> gΜ1Q|Úq§+uÛž={L˜]·RoyJ©‡oBN`‹~ÉÞ{ï½ú=»Ù…FŒ!ÕªUóº_¬‡"Žðû¤iÓ¦¦Þ»G••þ^ËÌ™3 ê·áÇ›†Vìß4ºb¤åÃ?lÏâ+ D4O?ýTàGƒž ÐÁ +uÛ¡C‡LÊ gÝwÒ@Ÿ#cážà9†7<ó®]»ÖˆŠà¶€{Ûž>,˜àR„@Úù.ú`xß}÷%èŒPPGe`PX:uŒ8 e CßõA î‡ø]QÀŸS³%ÿ¤4 ˆúòË/ÍaÀiS¬D(ë·pi“ÄõÄó¸³nÃïöÃÁqêÔ)9pà@Ò Œ°­c¡~Ã%Ù¸q£¬Y³Æ¼â3  €·  ˆ:Ë–-´µ#éèÑ£QwŽ<¡+(8ºÂ"Áwï ޾øâ 8p`‚÷‡.tpÙ \βðÞ½‘$Іbwq à²h`TR‰Øbt¼1R†ÀÁƒÕ•èÓQ[xäÂÞ¹s§¸¡Á_ÖO=õ”±€ÇºHÿ‚®h˜iÑâ’ zÒj‡¬h#«h#«èý'úÐ*¢Z%¿)ýPÖ¸qãdÅŠRµjU#zúä“O¤páÂR«V-Ÿå › ttzëk®µê’%¢îH¢eŠ96ÕyA ŽÓ[dÊ$¢¦Ú _Ttú´èq‰:|‰6:Š—·R›-tvÚöí?ü ò_Ö—ù }P˜ X`M|eM·¦8W«bk_o¿m]'¬¡†‚ÏýûãA ëÖõ³·Æ5T£^oÏIz«Ä1;pFJ:mWÐTy¢÷Œ•žÎ./^!Ђøëî»Eê×íLKüQ£M÷B_wÝuæûnïÞtêPwYÝáöø-\Hü„Ï–±R·á:ÃÇ®ÛpÜSE†ÏU‰#Y¾|¹©·Ž?n„CsæÌ1©j[µj%¯¾úªËo˜Óúe?tèP#À…«ê&Ôƒ¹sçN,8Â!éµ×^3‚'‚ÎÙ³gkÝy;E•…#¤¶]YW®\i:ôÃñ8ƒ}L±R·áù/“þ qÖm2Ä–Sc°ï–—| ΂è`ƒ0Ò½c áìú°„A[pùEytŠÂE:@» œŽêÖ­«N¹OáéÜ­hƒA݇$FäÀý€v+\2íT>‘s‰?ÒPÖoáÒ&‰KHà¬ÛmM\_û{­&Ožl/Љ×X¨ßp!ц|›6mÌuu7ˆ‰‹Í“$ˆ7ß|s\Ýá3È1¢—G\[÷‡oüøƒÓ ,í€7À ÔÛºu«Imf/Cš3üCåÌ™SЙæîåúƒÃ}}÷ÑIîûóö {x¨ÁÈAFÊ@ãkÇŽB¢Ž»«xäMýQšZÓg•‘† ÊÔ©SUD2NSe}-£F½­¢·KfÄHU•ô‚šÄH¥¥m¬Ft„ª:¥x¡{yã K3l˜ú+Ð) ÁÑ[o½¥.9“Âh Fǯ3 {ap$Bʯ;î¸"|Á:ª½SQ‡hŽoQ¿åG‹Iûæ^ŽýÙ[ß \”`D1 L1fͲҮÙÛ%öµ|yÑ4r–s’Ö‹‚IŸÏEµV²~½èC¾%ë哾}Eó¡‹6r[Lì-aªyÚg®ëÖ{|5ÀÉ B#íÔœç¢iâ³ÑSs¾ÞŒ@löqRê©>Ò”«†lú]$šW]ÔDô;É>¢ð~Å5€ÃÕÇ[B!¤×Cº8ÔµÙ¯5Êâ©:íØ°þ'ÐQgßÁ ¬téÙ*DyÖ¯ò¢a%÷º'Zë¶Œ3šNYûZGõ‹äs@ãR `å,ýâÆˆÊ?Õ®®¯~a¢~ûꫯTÛC¿³úk]²P¿¯ž6£0aÑþ¶ª1kÔ¨‘¤ÓGÃj;ý‡ÿX¿P²´råÊæ7Ü_šAÑBÏ%vç<œ0‘20"Vê6¤¬Àĺ-îêÈ>Gˆ…10â?þøC~ÐQAÚ®kèH…¢_|g¡]%˜)Yйƒ”àá7ÅúÐ ¡1\°OFd€s&;~FãBŒD(ë7÷²ÝÛBì¾~bÛ$!6ÂÀÖm çòh$€g_ˆk!¸Å â_ýÕÔ_Îs-[¶¬$µoßÞÔ—Îeö{¸Àém¹ÈÌ€ÁÄ 40Ϻpøõ”†ÔÞ–¯)Ck;3úffº[Ù§Ìa%Û^Ýë `¶Mº—í^_%t’îë'¶~Ã~Ðç†ß¿¬ã¢Îå$@Ñ@ZL|¯Û½1EÓ9PpÀÕtWZõÈXt#å•ýÃó1ji½Õ¾©\ì€PN1î–Ýî?~Áƒ£Î€ý&#ò@˜†V¸.`Ôòر_©“Q}È´RyÁ B¤8[µª¥Œ‘JŽ?¢éU@ñ„iDõtÖpŸ†è”§#¸Þ8â}5a 90z¦žªUàæ…c‚ø?xöø÷À>š5‹¿ )0¿Q#Kà„4kÅ@Üánet,¡€Ë ;6a{89aÛ–-ÚòÊr}ö6ÂgšqìÛ}ÿçÎY‚# 2ÑLs~D\)és½ Ãâo‚}Bx¥Ú2ã:¤ýìÚÙn jàD4h%üŠ¿e`sô–Q¡£\§àÜôÒK–ÓÒµ©1–¨+}ØG‹VZ;­iD¾ýÖrÏ‚ iâå¿_ìIi#ŒëiA·j•%TòåªåºUtbÝÝ×7Ï©:a}ã7+LÅŠ3B#¸ 3Zµ1ú U£U™ §È`5Žâ÷GHãA-ê7üŽƒø‰A$ÙX·EöõãÑG>¸BÌQDFi¾g[\„³CÇM3} „Ø~„: b‚è϶Heß";wõnY> •@(ë7¶IõR±0˜ÀêÕ«µÍ®¹¶‰f6Îm%ÿ³Hßµk—é_@Ãoj¹þµ6ˆÁí¾OŸ>æÙí³˜ŠÁ<ÓâzìØ±f04úðlݽ{w¡fÀÇ H ÄX¿…0‹'  Hâò£ªx÷‡oûä0Ö¤N±–A”‘øjÀÓŒ2€8É=ÜÝb0ª'€PÅîêkç2¾Ohˆ­^½ºIQÚìÙè{KlQ„BÎhÛ6• •.}½¦„™îUldo!†¶± úvq B¸á ˆ‘ ‚`?vÀåº~ªP‚Ý=:cJc£iÀõØÙ帿꿈IïÁD/HV¼¸(чaÑŽh÷-¼Ögk“:Nû¤3DH Ò¥é`µÐ·\ˆZÿöÛEíãLh]{9ÌÂMgþ|Ë-ÉžïþZ° •ëÁ…J 7ŒÊ›³“ûöþ~s¤ÖƒÁ„MèWGªºp ܃ï¿ÿ¨ *Bº;¤Ï;rÄáÿB3 Òë!uDsª0B/÷P&Òüa Ðm·¹/ÍϬÛbóº§ÄYãw \^P›5ü>BªN[lä<ŒôBåDµ¿ƒ "#Ô© 4Xb#ì¿ÍNeº*.ášq8,̃¹çyñ= @ò`Ý–|¬¹'pÀÿÒ´Ô‡›gtôêX8B7mÚÔ¤¢Ÿ6mšq4„#4ÚI øI±‘}ŒHŽcH£†ãd@¤eýÆ6ÉH»x¼ÑD£þÑÖ q.ê([l„sDzd,ƒÀè³Ï>S×øý2eÊ# ;w®)ÁÁ϶¨‘ži'1`ϸ<Šù g¬ßÂùêðØH€H€H aÚõÌð—FØ»G5Íg„Î3_‘-[6#0Bê;`‰Šòœ¢"Ø¥:i Ø”;nŒä!a „<š‘EæIŸ=†ôÔW½%\BÛeeÚ´Mú2Òžþy}`¤#TRkJ5Q‡#K$ⲑ~€PÓСWé'ÿþõ™ÓˆŠà¨Á†3t0ŒÔªåœc½ÇƒmÑ¢E/æØ9¥ã¯é:Çß´cà¥Ùsô¡ÚÛè X}=×òúÚ­â+K@¤Y Mª6ˆl<…ø‘ž=­tiêDœ` MÒ¬Á… éΪTIp³Tþœ0…:àî¨@œ B}L(ÿÌë˜à`„tr:‰ŽÒò¼gh2áh…É(ÿ7ÚN/àôÅp%ÀºÍ•?…†CèTD Œ¾ü\¦Hsç-ÐáßMÎßNÞÖMÊ|t†ÎSõ-F}B(N§ƒ¤Ðä¶$>X·…ϵà‘ÄŒJóÍ7Mª2¸áÙ ÷ÝwŸnHV00 ¿E$‰BY¿±M2ïs48¨ XHw†4M_êè: DõHGÒJ-Ì1A|„Ôiü±tœoDH=µ¡â#w¡¯2¹ŒRšë·”¾Ü? $@ª¤m[[gÊ”)Þ ÃùÅŸð+V4£ùí0Êo,FÑÎTptùž¡#ôtP‰qçyýuËÍGÛVULæº_¤Ô‚ —øÝw]—íÙsT矕.]Š©­—̘±LÓ‹ QEjµ¿µ\hàHÌ€ âžü+÷øO¼ Ö8' Ô‡.>ч_Ì¿ÿþûÃNlþTy„$à›@(ë7¶IúfÏ¥$ hûG+ú ϤÜçá|„zîß|óqCò§¯"ýp]5Öo¡&ÌòI€H€H ´¼ø~„v§‘Zº§>¹çoTVû›µkׯ­»ÔâÈõ_$õáþСCvQæ•‚#!ù€ôWgèóÚÙZiª¹îNleÓ&K˜„tfv,^¼X…Ïhº²>šÂ¥©;VCGоI—ÎJÃU«–½vʾ"'øµZ uºˆE HÚ¹^{­ˆº kú‘qãDsŸ[å!…„_vÀåb¤@.VÚo.n ã—&¬iäՃðG³%{Ô¨!š“>ÙwÓ;dÝÓ—?¤':®[·n²yóf“¾ uÈma˜Ë°ÿþÆ"r @t`Ýבg>vîÜ©ƒVÉúõëã&ÔïvZ÷"ªôã7ŒÈˆ©IÃçºñH¢@(ë7¶IFßýÂ3 >Ç›Çîÿ/žö1„@¨/‘áíôÎ NEH9ºFGA2D¾;y*ÆïyÌtà7*®†X¿…áEá!‘ @(8 ÖµP18"GŽâéÇc—·ÜTÛ·owYîþ°[Ô@bß¾}q«#-ˆûñÆ-ŒÐ7³fYiÅ}4p‘H(Nyùr1â Ü Š”(!Ú‘êyOjè Ï>k ‰°ÆU%½òÊ+òöÛo›{è“OÎkYiëf™hÇà„T®œçò’c.2úAøn¿CE“@ Õ€"-Zˆ”/ŸÀÊ!\Œ4jp8Ò¾nã’£ƒn•upvÝ Ò«y m‡—2eDúõCº;ok…ïü;ï™,jÍl‰éÂ÷HydÁ à^W°n ÕØ.èÞ½{ËgŸ}¦uHyõÕWÍgü6 Ç@#/ƒq¬  è Àº-:®#Ï"e ìÚµK¾øâ “b#;RéƒP!µ…#C)Í¡]©R%iܸ±IMj¯ÃW ÐeýÆ6ÉÐ\3–þý÷_#¬}î¹ç.¾™3g6uáM7Ý÷ŠçÉ7Æ sQú ¸¡Ü=zÈóÏ?ïkU.#¨'Àú-ê/1OH€H Ê „gÏO˜BǨ=g -Z ‡g S×ňŸtjNR9UªD›}ªfj´adч‚x@êÖ­kF%t¤Mz<˜3H€’@(ë7¶I&ûåä#„ÀîÝ»M=øÚ#ÓAÍš5ƒˆ‘mΜ9êZÉåLÒ©e=2Ü~ûí¦ÞÄ{¤ðFÊ3÷ ÿÓ Ã X'Àú-Öïž? @¤ à(€+kRäF¶…=èXûçŸüvrw4ºùæ›]öއ<àÛ©Ñ`¹zúôiã,ã²¢‡'ááÅ4F[Üx£¨XÇA»åàHõ=òÌ3"Ù³‹Ô©#R»¶(㤑ùë/‘ DΞØ)¶ŠuªP6l˜i¸ÅuªV­šºßô3¹¹ÃQ†[Œ‘Úª}û„ÎÎuù—_ZŸ›5s+ŸÎœ™0Ár8ª^=2ϺjULŒØ Àº-6®s(Ïr“æ E•OU¥zV+G¸|ðÁÒ¼yóPî–e“ €W¬Û¼¢áp!°wï^ùá‡Ì´LGŽÀÑ"#89·mÛVZ·n­Ï¾ i_$@)O ”õÛ$SþúòÂÀĉ¥{÷îrâÄ yì±Çäµ×^sqÆE/Ihó?uê”.\X]ÑS…ßÉðˆH Œ °~ ã‹ÃC#  ?ðׯœ«À9Èþ¤˜²×ÿã?ì·æóÎÀÃÜ쀃Òräíò#–,Yâ²Vm(k¢0Ðw©Îí>ÓY9O{ð``Z ÎA¹r‰Ür‹HÏž"HÑænRµc‡•ÊL dî\gIÖû={DêÕùûo‘)S,“½òxãûí·2iÒ$9r¤ôíÛ×4Ðâ¾™?_Á†MeËú»Et­§—Y"DúÕ'ÈÃ‹Žø l;®t¬Û’Î0KX¼x±ùÝR²dI­gÇê÷~Y#¬ýK•¹ÅâÁs&ð"Àº-¼®&| þîØ±£qÙÍ›7¯½«ù¼áºÐ®];™6mš…NV<³Rl>׎GB ªúm’¼¿Hà 8ö¶Ñ†äûï¿ßŒæéˆÓÑ£G»ˆÏ2E2@IDAT°öÕW_- Ô®µÍ R .¦Øè G¾#@°~ „×%  ð"@ÁQ€×£™›m Fô»§JóTäÚµkeåÊ•q‹`CŽQƒîÑy¬¼„âøñãÆöÜ^:p÷€ƒ„¡ 5ŸR."šµL $?Þrë˜á­·¬”aî‚#hÂtàŠ<þ¸ˆ¦åŽO=%‚Ü~hmàìPUí`àNu‹ª™ *j¯¶@½{÷–áÇR«V­.TóçÏ7Ö»ñ ³ú¼¬¶¿¢#\;°Õ«->nÿ&!k_¸ rï½">èzÀšMHÿ·E%\çóS Vƒ;”‡¯Æ„7æI"Àº-Iø¢~cŒÚüóÏ?Ío^xASn6‘üùó›Ô*hx…¸iˆi[¶li]£ OH ì °n ûKÄL!Á•B¢®]»êïï Æ™ H÷}ß}÷1eZ ]î–ü!Êú-–Ú$ýaÍub“Š¢}wŠŽ4EˆÁÆwÝuWlÂàY“@2`ý–Œ°¹+  2 ŽŠüËyòä‰Û h”óçÎ3Âç:H§å)×Ù™j åÃ-Ç[À®µ[·nryœþ ˆ[Â=T#%×_/šûZD]ܽDI½z%ÎiGd*ÑFT‘DzH´aÕÚ߯"cÆXiÜ;‡8ISr› ¢$÷(_^äý÷EG„bÛåµBªP¡‚¬V¥M‡dРAòž*Nf̘a:_·lÙbÒîá!µ<6Ž €®M n3zÚ&bAp”&ˆx’éÓ­û '¾j•è½` Û2g¶XDòßC‡DB0¹bÅ Ñÿ°e$/ÖmÉË;RööÕW_©h÷Vɬ_hø}‚ßC† Ñt¢ó$kÖ¬êØSPÏÁ ¡z¤æŒ”‹Áã$˜ë¶€‘qƒ pðàA}ÆÛ+]ºt‘úPŒNxŽÅ % @deý+m’‘q¥y”ÉMí¼¯¼òŠHúŽbýøãͳîõhÀf „œë·#æH€H€H d(8 -lQ!*q:ßú÷ï/gÏžuÎ6ï÷íÛg,X!H±ãnÍ Goñ0r 9b°æÃÄK—.9抠lŒN„sŽEŠ1óìÏáúúË/–XCÍ€${vïG 1Ç›oŠ@<ä a4s™Ï@z¦k¯í ¿šö›Ê#ˆ\së2:_‘·;C† îÅDÄç2e¬Ã Äå5H[áV,DÛ¶¢9ÚE;ß­³…ˆ  éÔðu–/Ÿ¨S—uN¡þ«š“ªÐÇWc¨!¦ËgÝÓ—?ÞÉ#=(ÜúP—­_¿Þ8óõéÓǬûí79}ú´¦ÜüMàò ŽŠñN3H€b‚붘¸Ì<É Øm4à ˆL¡®ßb¡M22¯<:”V´Q£Fêvÿœ:¾—2KxàPî’e“ ¸`ýæ„I€H€H ‚¤Ž c ›C­Y³¦àÜ™îì ÍÝõõ×_€bÅŠÉùóçeÆ fäÿÅ‹ãŽýºë®“¾}ûÆ}öô¦qãÆFÀ2{öl³øš÷ ¢&Œ¬(£*téÒ©“Ê*MíµËeóÔ©SË‹/¾¨"7ËZáñ¡^=‘DÏÅ»› Üôt$cF‘gžq=î{îèGdÿ~=íx±f¨Ëaû@¼wh¶lÙ²÷máVW)äóÆÈPt¸zJç¾]¤}¶GÚ§¬Í ½fÛÑQ²sÕåÅD´k'ú?)¢Æg&=àäÉ"Õª‰”+ù§Ÿ>½¨0RdÉQ±£çÿ³`žåÏ?[¥#e°nKîá´W4²0@Ç¿Î;ËСCMÊÐp:N øK€u›¿¤¸^¬ à(V®4Ï3Ú „²~‹…6Éh¿?x~øEGÅ"5øÎ;åÁ”wß}—©ECȵI hX¿ % "  d%àAª‘¬ûØõVÛ%J˜Ž¹“'OšóÀˆ89ÝŒœ'X¹reyýõ×%gΜÎÙßC8tâÄ #<²Wسg`òéU€ô^•*Uò´8,ç%„A3´ˆš,ȳϊÜpƒë)ÀµHM¥dñb‘úõ]—áRµg‰?â/õ=§—æp5j”Y)ævÊ‘#GÜñØ·j­„y³fÍ2£_|—¹K‘R Á‘?w#DóæÖk,ü…#–-Æš0ÁJ­ îFöµƒÙ?ˆ ÕÙm·ÙsCóJÁQh¸Z*ë¶@‰EÇú—/_6"#ˆ :ºMÿáQÒý :®/Ï‚bë¶X¿¢ûü7mÚdRxW©Rů]£#s®¾új3ɯ ¸ @Øeý m’a{ay`ÉJâ"´ÃYåµÊÇ  @Ê`ý–²ü¹w  H ñ!I š„·¹Gmv :©X±¢Ï•ñЂÔ[T‘àØ…eT[ž÷ßßl‡÷¾éÙr­F¾V ûe.ˆ:7Y‡i»eÊ$òôÓñÝN“¦fCÈÔ|HJ—ö¸ØëÌjу‡ÍÒº!Ü‹4h 7Þx£é€EÚ4ˆš6mªB¨?¢Zl@ª©ÒûUÄß”j3fˆ:B‰Ô®íoT/@:550“Ö­£ç4!8B,Zd½†ò/DM¸ß  å^X¶?X·ùC)ò×ùûï¿e²Ú²!5kžPÕo±Ø&ùwÏÀ_[¶l1nÐæÛ½{wÉŸ?¿ü¬£à(6ò— ×#Ð`ýzÆÜ “@ê`‹e¡“nÒ¤I²wï^#BeóæÍ’;wnAj5LEÕn'1)· TB`§NLº¶ßUù±_sˆ9sÆtæË—OêÔ©crKG{¤§š?_äÇ­Ô\ë׋ôë'÷¸ùf‘òåEડG°²È=£¹Ûàôðá‡ЧQ¢çÎ3)íÜ'Z?Ãåè§ŸDSëˆ\u•÷³„ñÄb¸†ÁºÞ÷~KT‹¦)EGEYiÃïwD(}íµ–àhàÀÄ•áÏVúo%ëÖ‰Ü}·?ksä Àº-9('ÿ>Ö®]+3gÎÔºv¾¬\¹RBQ¶lYyòÉ'¥gÏž’!C†ä?0î‘H€’ë¶d€Ì]„œÚàš<|øp9uê”:ß GŽÔñ ¹?~\¶oß.:tùqr$@ÉG Tõ[¬µI&ßãžBA`Ĉ²páBÉ›7¯ ½“ýmòË—/×Át‹Ì´k×.spükÓ¦ð{-¿$@aE€õ[X] ø$@Á‘O<þ/„ &ŒŽv ó¯E‹f vÙ)Qžê³$mZ‘ûîsÝ»f©“Ù³E7¶D™3‹`ž·€“ Ò­}óȽ÷z[Ëÿùxðœ;w®´oßÞ£Ø%¥K—Îÿ£`Í2e,±É¶m"… {?!¿ JŠ¥tjNÅAlõÈ#ι‘ÿ>µÖH! ög¨p24礙(E³Jµj¡)Ÿ¥&žë¶Ä³ ·-Ðüˆ5õú_ý²ÎªvtÍõ ûnUùa‚HšA$@±B€u[¬\éè:Oˆ„á˜Ü_óŠc°\І fžOÑñ£ŽÚIHp„tjˆò¹Ã ˆ:¡ªß¢­M2ê.|žÐÁƒeß¾}~×W8úòË/ˉ'Ìó®/$ W#¸ÖªUË<ûZŸËH€Ržë·”¿<  HˆG âò xáÑÜØñG·Þ*:ªD䡇¬]>÷œgw#û€V ‚#¤U³G[·ŠÚàZe¢ B.òCP4tèP{1ÿ Áâ·ß| Žà„£F\r×]Öú±ö·T)‘‰£ó¬‘V BÀï¿¿òì3E:5Gþ%`@,Ó¤I£ÿϳ5õemI E!ƒH€H€H ¬ @\4uêT?~¼qTΞ=»Œ=Ú¤SC]ŽÎU¸À¹á‰'žðy.H§†¨P¡‚Ïõ¸H€H€RŠÀ¦M›Œ)À!<òÇyè—_~¸ø½  ÎO=õ”ìÞ½[ö¨»ýzôèQ©\¹²Ô­[׸¥Ô¹q¿$@$@$@$@$­"²· âmj¹‚ôeWiž'4º*Tˆ#ô#à.ݹSôÚ‰6z>Ø} ´Öñån„­õ’«‘hz‘óç-פwß9R4ÿ¶Èí·{Þ‡§¹}ô‘Šj~“çTå„ÜÝ ‹@ýú"sæˆ@ æ+ªVÁĈ>!Ô,NØgÍ Þ_ˆ!B¬T)xe²$ +ÞÕÊu\êÕ«weß‘ „C‡É´iÓäóÏ?—eË–·t¸>«£múiÎqgçk–,YLŠu8%p8Bû Ž"Åå$@$@)AÂØ»t$ãáÇÍî¿QK{8þ'XQ_1áæ‹é–[nIh3.'    >}ZÖ­['GŽ‘k®¹Æ¤ôH蜖,Y"cÇŽ• 6ÈÙ³gã­^¶lYi¥¶7÷i®.4¤1ÂÀâÅÖ1Õ©ãýØúöõ¾Ì} ÒªA˜„”OšFmæEÔ7 ±Ñ)Í…NØœ9sšF\÷}Äògdٱݣb™CHÎýÜ9+w`H ^¡%KŠäÉc Ž‚WªkIÁ% i$@Á%€NËHŒ¨6¸¥³4   `øî»ïŒÛ.^áNˆ4F-[¶”6mÚ˜öoé½o»í63fŒqrÈ—/Ÿ×ÃAGîM7Ýä"Xòº2 @2€À¶aÆráÂÁ€™Ç{L¾þúk¿G™µA©m³“ñŠqW$@$@$@$@$p…@² ŽV­Z¥i³Þ—Ÿ~úI.^¼hŽ#ìî†ZÄGÀB|øðá>s1CÀ„i¾ªO°n¶lÙ|”ÈE)A‚#hÁ4›KPBÛ_åé§­´j5jˆ4m*:b3°¢‡ &0÷%P$rš‹^ äAJ#Ø~eÌò]&ep9‚˜OÿM$W®¤”ÛK—D;QDñ—q @Ò À öòø•>}ú¤ÈH€H€H€‚Jâ¢_|Q^~ùe3«Q£FÒZGÖà5£Ï Õ«W7‚#¤Uƒ8ÉSœ9sFþüóO38ËÓrÎ#  ”"°`ÁiÞ¼¹\}õÕ2oÞ<©Y³¦¡}ÿßÿõ9¨øŸþ‘+Vè`É{™6<¥. ÷K$@$@$@$ó4‰MòÑ(íÛ·—¥K—ƉüÙ;Ò\A‚‡ â‡~0#!lA“?Ûpä!ÁœLräÎþ0€óÖòçdöÌÿI†O˸q¢×Þÿ²‘Óûõ×_—Ò¥KKçÎýßkšR]öîMFç¨[GÄG·n"'Nˆà¤Ia:δjÁ>Xh®TjœÊ|–­©4å7D¦Nõ¹’ \!ð³Ú‡}üñÇÆZ¾Y³fWð @XاêÖ­+ƒ6©ÎÖ¯_/_~ù¥ù#6ÂI@p„ð•V ³š¾B… f]þ!  ä"€,Þ)D7nlÇ,ÖFcˆ÷Üsìß¿_ÔWÀð’ŽdC:5 @ÊH6ÁRV}þùçŸåÂ… eúôé^·ó6Z$o sš66m±‹¶§5ZË9u&•ÌÍ÷¨H"›7ûW¾Šàžï×Ϥçƒè#iž ìÚ%ê™f8ˆ¾~ü1þ² ÏAÞ¼‚EªTÑL!‹gžÉŸ_dæÌÐìbÊ‘Y³DÐùG-µŠ÷€àÿ[¶¤à‘¾öšÈSO‰´m+¢é ‚øÎÐÎ Dt*vïÞÝ8%Œ5*šNçB$@$@QAŽåÊ•“ï¿ÿ^üq#*\¸pÀç†mrèˆ_‚#¤SCÀ]šA$@$@ÉAï¿ÿ~É”)“dÍšÕÔyMÕšþÉ'Ÿ4möpöƒ3ß 7Ü`'WªT)î° 8B ­š¯@]Š àÈ%.#    ÐHÁÑW_}%3fÌðx&×\s*TÈã2¸"92Þ²ü*@Z68­]»V¦ ëåÍ›×eÝÉ“'Ë©S§\æñCÊ€»¢Në5X[v»AjØ&Yòªxcôh‘âÅ1Fä›oDm±®ìïûMôf1Ë/ëïÊÏ>“»îº‹¦W(Å{7gŽH¢Â¿x‹TD(šºP¤råøË‚:î6}úˆ¤Ò¯,¸iãDHB¿KÌý±{·È€®÷O0vG£'žmMZ«cGÑ/1Ñ“Á(=deäÎ-rô¨È A!Û…ï‚Á×uî ÿÛ¾·Nx)„LÚÙ#êxÆ h!0V¿cйثW/)V¬X´œσH€H€"‚´ÔÁõêÕSÍüSòÑGÉ/¿ü"Hm'¸8#­<:cÑVqpš4i}n·Ýv›I/ò=…-8¢Ã‘':œG$@$lp5BjЉ'Ê­·Þ*+V”“'Oê<Ôœ\@Ѿ_²dI—C@½–%K–G¨Œ~…"EЏlÏ$@$@$@$@$@ÉG u¨w…4hèôrjժɣ>j8¼5¬AH´mÛ6—M‘újüøñæ¡Ã^Y]B«Vâ±cdzm3Õ¥iÜ)O‚#¸¤ü玴ÊÝå^YÜÅ©S̲v"o¾)¢"7Mü-R¢„H;·aƒÈ·ßÆ¥ãúWs×ètZÅ #FŒð},PÜ”)c¹Þø^3*—꿜 hµœqì˜hƒ¹È}÷‰:h8—„àý'Ÿˆüþ»ˆ:RÉÁƒ"-Zø·“Ç-§¢ZµD[|o£Gyøaë&U;gsá> f¢ž=­{iÔ :Bj5|?bı6À=pïâþî¢ÿ :ªÌïÀ…M—Î÷ü·Ñµ×ú½upW<Þ:vŒ zýðÖ[¢y¢Dz(éûZ¾\dî\ÑÊCTµšôòX „¿UÜøüóÏ!ö /¼GÄC   Ø ‡A¸½«.¦púI,Z´(îäSéóçu×]§™•ÿ–ªU«h“’h A*¶+VHíÚµãh ÐÊž={¼eœA$@$@Á$€:íô¨“Öv6Ô‰¶«<êI¤EÛýôUGG¥¢¾tÔ©SÑ.D¹(ïúë¯w_E¶oß®NÜ[ä‘G‰·Œ3H€H€H€H€H€’€ZE„6yëÖ­.;uê'ÚiŒÞÄFØÛºÇ3šî#<îÞBG´#àrÄHyÐ ,Y"R¡‚èõ áñÔ¨!¢ù¿U©&‚ÔXˆ ³Vcƈæ–ôOÔôã"šþAÒ¦™0Á*¹í «@5nœ¥er.Ö¾ “^ÿVxŸPüü³•!Ï«¢S8–¡B(þ'ñ¿ ñ_R[,°XÂ)éæ›­òù—"œÄÚ|ðq7hݺu„Ÿ ŸH€H€"ƒÀ!ým g¡Y³fiÖäŽj¶;Ï ”ºJ¦nºé&iÒ¤‰Ió¹„ùM­c‡ëïY¤—V UZZý ¿în±DGL§æ†I€H€‚J`ãÆF»iÓ&3 xÈ!I*©GQ~ýõ×Ëàb&¸$1H€H€H€H€H€RŽ@HG°H] ‹ÿ£ìѰ†Ñ ¶Å¨gÀŽÕŸ¸ãŽ;\VsƒË~H6¶Y•ô <à@‚)1n&ª†QÉ‚”W‡ØøâÞûPr®Ï)LóyPwÞ):4GÔ£^4 %x@z.µ­¤ÞBª*m@6.,pc‰ÂHŸ>…N ¡aÃ,1ˆ¿ÉN±Ä3Œõí+šÏ@¤S'Ï'‚Æ~½'Œ;–}²p:Â{O6>žKñ>ÎLø>ƒP&1i»°-7ÒÁ%©V-ïûÂ9â¼áö…s7¤œ=[D­¨½œ¤ ¼ÑTƒæ~¯_ßrTêÕËe˜EapŒ™Ü4¡F†b ÙBB÷å.釟©JC³IxŽþ±xAü„|Œvtè`‰ Þ‚š11a¾W 0 1%p—ÕaiTjéw`?ÿÎ;ï„Íññ@H€H€H š ÀÉîÍ+W®4¢"¸9SLä;ˆ0¸ëgUô#­½3~Eúfòp e @\ºtIN¨+<Úï1Ø¢ 8ÐÆ¢‰'ÊO<‘ä½äʕˈeè`189ÏÀlS¥JÉš5«sß“ $3Ô¡Üß®]»\ŠÇClSý‰5HmäîB"·Åq1‚Ðxøa¤,˜’Tªdi:8hí±TQëù@ãMuG饂‰t**@Š™~*Ê”)S ÅXë#=&OF]íè5¹¦Ú¶Mĉz*4ó þ€ØùÏ’*ÒÇ ÑÉøñ¢­ö ½»Øè©§¬m^yE4§È¤IVz¼ã—…”m˜ìІ “7 iç̱R¡ÙËyÅ(cc༆é(Î;šÒÐ(˳=¾E:,¤-ó:BJ“½[NR÷ÝçkMk™Sl4b„%$±·ÂõÁñéh+#¼*VL4Y¼½Ôû+î;îÆ ½¯çk =­Th8Ž@CGHK!¸ùÓh£–ÓF(äÜXCõÓµ«ÈóÏ‹¼ý¶s©õL4½ƒaî­`iÁrçÁºÈ[@äôý÷rÚ=ûlfÐ÷ÇäÉ–±4S0C6Bs?ª*w¡‚’»ìÞø‚"ç>ÜÅFö2pŹàÿ7¥;Û#G,±FÁÝpƒunîi‘ 1J]ÉlL|Np.xF]ØÞS1㽯1òóEh>¢Žf9¡ d „”R¨õ×߯pÏEëýÝÌÖÄ|u8ðj@täa0× ú{8_¾|‰)–Û ÄÓ§O Ò•Ù"£;vp﫤£IQ§ î³' ìÄ{d&(‹¶š †-8B»®Sp„ãCPpDØ,ŠH€H€H€H€I U"·ók3÷”hþ †P¸»ÃQµjÕüÚ'VBgtìØ»W;´‘Gù˜´±Ô¤y °q£8Û·oo‚çÎZ±‘M¶hQ8çh®rùè#{®çW8«ØiÙ Œe %\‚tÄmRB‘åóÏ­K¢ºqÑñ=j¹PÁÅ©ç|Òü@¨vÿ>iÈà¸óÚk>W‹[÷ž?þØHÝ=â3H+§¬ß·Øã ¨c ÒùåË!ÈãJ Ì„£ÖÈ‘ÖõN`Õx‹‘· ×Ç2’PüApõî»–k˜§²ð½™ÊQ-àØáŒT¡‚È /X©Ú^}UŒš"gàž‡8 ëk@“$´•+giœpÙqi}4× Áy 7UbXH!ç.6By!þ!~Õ3‚'rð 5éæþüÓZ/±ûçv$B^~ùeÍœøºS¡à§Ÿ~jÜhj@ŠRè‚p·$@$@1CàÂ… ú¸1Bn¾ùfo2ΤéF³”áØ‚£åpXý/‚f¦ f:5›_I€H€|@¶‚Ò¥KKóæÍuüÝû&]w÷îÝeÖ¬YrTÛþ jÅûÉ:º Î~o©+8žOá*l±ŽÙ p‚àÈ]«îÝXÎ     HY©C¹{w‡#GI± ÄŽ(‡ë"Š CüÑŒ$W¸›è@‚û®Q£F‚|Þp9*X°`ò<\„ Žj×Îû>‘þ n9Hw¶u«H:"W9Óyyß:ð%*¼Ò'‘Q£¬”ZW_xºÌd‰ šlâ"[6‘… E7iÑBdØ0ËQ)n…ÿÞ ¤æ‚›Ž±ºq_á¿ÏšÍ˜!ÚÂa9yYÍe6\{îºKä\f»|€Ø.>8^.GPΨUs²Çc‰hÊ$³ÿ¤æ¤‡(nMø.…ÝЪU¢-G Ÿö ÕP­ZW®)F¬R”ÙÔg؇6< ÒºýÐ aRÝŸ¨Âè¦ÞOõ ôHsNúV½K%Ø›ï÷¢3à–·§„ܵœÛð= „ïÔµnРA¦1½HÊ   =¤‰ƒ.ÚàÞüñÇ›tj¡ß³{È¡¿q‹è ü>°ãOØÃ ‘éÔl"|% ðFí©µÕÒ¢#ˆˆÚ¨3x Ù ¼•›”ù©tPD½“&MÒûµ)1·IcŠkhûMíO»VR€Û’ $H U‚k$aX­:ÃßN1¸a$ž3m ;uêTÜæñÀˆ0K—Š`êØÑ²Jñóðqݪ˜¡ÔÝ$g,?wá{5<èBàá…§Àˆ;-Ö¢E–{Üv :BJ°PR»éh$2D< ¬‹ :wÎeÍ2eD6nùâ +sZ<—dŒ*Ò~õïÍõc‰ZàP„Pñ—É©±‘¦ÜŒºõ•âÛãûn:þm|‰ìra›oÙ¾ÝMaeÂW€†[TëÖ"MšgG%JXé u”³¼ù¦ÿe"õî×{î±8@4ç¡$pªXQtØ™åLåV:ôH«Wë-øþa¹é[äÍK=äÌe½7$@~€€º Záâ8xðL9uŠb#¿áqE  H$}ûö™”-upêâW4Ýð† ÂJldŸ\Ž6oÞ,GþsÑ…ó/"Ðö»<¾’ Ä´£ÖѶÉíÚþ?8¥´ØÈ&´jH+>ï?GíÅ‹›A¦L§fâ+ ¤, ŽÜeÐPçOü‚ôEŽ€`(Їœcpù/ ø6Ø+ñ5$ YQ'^ùL@w#ˆwàÌãgÀѨµŠ3`?T…--[¶ôsËdZM톥iS¤©R‡ ¹ãË1)À LGÉ¡C¡9˜nÝDÒ§·RbùÚƒ¦0.Aõë‹téâ²æ-·ˆ`12Ré 'Ïÿ5ˆ‰ ªÒ #P€©Y3‘ñã­ÏÚ0 °x‹“'-1Ë#ˆæ*ð¶VòÎO¤+TÀ‰´_øgùì3‘=¬t_ÿó$°WüOÁa«råVt[¬©*M‘Ž*“Ì™Ýþ÷Wøî]¶ÌórÛìäY'eåç×—’×¹€HÀ…ê8ˆÐÑÙ­Û\5”+ wßí² ? ™:^kÔ¨¡ÚûEšéû!#æyVS?§Å Ž0 ;­šírd Ž˜R- /‰H€„ÀAmèƒØhË–-2fÌÍ\ß)LŽÌ: 8ÁéÈN«†tj Ž,>üK$@$@$@$@)M ¤‚£üùó»œßÞ½{]>{û°‚GTT׌«¼9Æ8Ö³ßîÞ½[ÍY®¸³Ppd“IþW\Êõë­ìa~ïðH1§ µª÷7zöìi>ñ`ŒFà° ¤å‚hÎM*\9<µå7y¦ ¢#(z‚pÿéÐÁr rXìÇÛZî«=”åV3q¢•þì¿•àpd‡WÁV€£Øœ9">j9%,(¢éŒû¦¸“ ìb<¿BÌ‚íqàñ\RäÍÅ÷VŸ>–³ÄgHƒìT{H¿„ëQ³fðù@p„@Z5o1uª\umf)×íVokp> €H£†tj=TŒøý÷5ÌÈŒ¸m›‡•9‹H€H€H É6ª½ëíšO©e>üðC?1^råÊ•ärCY€»àîÑ™õù ©Ö$@$@$àNŽxuëÖ•M›6éø··åá‡v_%Å?_¯ƒá`¿PÝØ/^¼(a`ráÂ…SüØx$@$@$@$@$@"!¹;áá%¡øûï¿ÕìEÝ^…ÄH÷ã÷ãp,âÛøøc+» UüŽ_£LîFx(~çẅŒÆ ËøôS‘Ÿ¶ò‘¹`¯^–ÀF­ùèH,‚Ø„{#Gz/6F>aBδþýE ”ÒÀ"D¹r"ÅŠYï½þ…;Õ{ïYû‚Ȫ_?Ü ˜ïo$—«¿Ç“ëÁù )ÔÔ*ZíK’?[RÏ÷ „¦ÞG;vˆ¬\i¥ˆ ÓQáIEÀíI ,X /¿ü²“U–{ïiª¸"TÃÇ   2uîPGÚC:`²:ÕÂÝ(¢T©R’%K±Žpåô.\‘pžÜrxBJºH ¥¶nµn÷ãÿâ kN«VîKø™HÀ ¸CÞ¯ßÃY³fUqÑT6ì­çDf̰²ORpäg“ @" @¬S[gO:¥c/¾ ¿TÝ>Î )gà4õª{íñãÇÕ\×á®ëc[." ˆïÔ«WO›ûÖé3æ0k|8Gˆþ©Átjÿ @X©à(S¦Lb?àl/_¾,õ3ýÿûŸÇ“ÇÃÎÇpAqDÞ¼y%‡¢™š²é·ß~‹+!cÆŒRÆ™ *n ß$d× H[w#m$5Î:~à±cÇÔ¦µ礖iÓ¦™Y?6 ßUžxB*-¤@Kl*­§Ÿ¶R·éH¥xñÔSøGô/]„zï]ºdÜvR>(%Jh–»ã¿Šæõ‰W4g‰D^÷Þ+‚×H _iÕ Œ€˜­~ýH<33 $;Kúý‹:îø}týõåìYKzóÍ"Íš‰¨qüõW²wH$@$@QI`Ñ¢E¦móæÍsiψ”FZ5¤˜ÿàƒÌ!Sp)WŽÇI$@ÉCu\›6mä×_•ÁƒKŸ>}’gÇIØ ÜúrçÎ-ÔþjuD¯S§NJã¦$@$@$@$@$@Á$RÁô™gž‘´ŽÔ9‹/–Ž;šç‰`ô`×®]Õ e—s¶4 ×òåËeРA.Û?úè£rÝu×¹Ìã‡0% NE¢WúÔëGÎ.ë`m¿sçN“N­´_&LOÏïÃzì1‘¥K-á•ßý·âéÓ"*º3éвe‹¿5È‘müxÑá®ñ—»Ï¹õV8íàÿ=ÛÚp-8¾ DÔuƒá…؂ל9^VˆâÙ5kŠ@ièžV ®Z«VYéÔàöÅ H,íñÛ.~UÌ—9³•™ºT„-è¥Ë‘ŃI€H€H 10ð õíˆ#LûCý­ áQ­ZµS\ŠosÛm·™cg>òåË›Wþ!  èÛ·¯ÕvîÜ9Î1(ÜÉ 5èÝwßm³jÕª&}h¸3H€H€H€H€b…@êPŸhžýôSùè£äâÅ‹q«ÃéÁŒûÌ7aNॗr7B~q8Z!ÕL§NÂüä<<¸<%&. ¢£öí½o —#ü_AH¤‚À£CÑ„î¢Ë"Uªˆüþ»¨×²ïôp å+@<‡k‹#® &ºë.QË1ýnŽsjb:µ(¿éyzÁ&Я_?;v¬ê;È+¯¼âR|úôÖǺuE]DæÎyþy—UøH€H€HÀ¸: MÚ*Âÿ®Ï5˜ÐaGΜ9eáÂ…rË-·Ø³"î±p8ªŽ·éÒ¥S—Úw<`  Ðøä“OŒÀ¶Fòî»ï†f'!*õ^u‡˜ÏÈ      ð!rÁNÎE ,-[¶Ä9„Av_ÜL·7 ]ž4±lÙ2[Ê„¬Shd¯w%ˆ–ÉK@/‡<þ¸¨ëFSú¹ïÿµ\yn¼QLÞ®6[¹r¥‘S¬X13fLkÇÐâ‰E®¹æŠí…§S‡ƒÔ³ÏŠŒ%Ò«—h>:Ok¹Î:TdãF˵ÿ“¸.¥O?ý$¢ 4F€…ô`žë ªU³^cí/ÒªÁrO¶Ÿ³f©W/Öhð|I `H?ûꫯ R¢Ì˜1ä õT¾¾Õ€AÅÛž–r €“À† Ì@• ¶ˆqn¿ýv#0B*ö[Õá5‹·ßøÎÂÂø=RÛC0µvíZ“^éÇ$@$@$ð“¶U=òÈ#R @óœimæMš41")¤ƒc „diyJ¯Cñ§OŸn:Ï&Ožì×Ù?üðÃ&…ˆ·•çkê­/lÇ +ÝsÏ=j²¡.Œd'0hôнøj+µøÇ5]UëÖ­M,îŒ3ú±U®¢£sÅé„7kÜe¼õ \˜=Dž{Î…´k—0ìb¦÷ß·D4±œ¦Pî |¿4mê™ÝÏ?‹'¶Ò×y^#ºçê÷¯²!­G¸W1 ÷E Ñ}íyvI&0NÝç`q_¶lYu.š+2dÐ4´"Úwh&÷ K&ƒH€H€HÀ; N‚wÈ!rùòeÓ΀Ôܼ­b¤UƒàˆéÔ¼ß\B$@±D`Ïž=Ò¼ysSïÁ->{öìwúpïëÖ­[Ä7˜H€H€H€H€¢@"ó6ŽVÞƒT‰7_5hð{VÝWz÷îøNþÛiØ^ýõDoÏ O@éeöl‘–-EJ—N|9¾¶DãðŽ;Ô gTD[Ýû:Ç—råÊ"»w_YuÊ‘K—|§S³×ÖM’9³È©Söœ„_ÑÛÿKm¼Žé°z îòpë¨éJ•TÝy*,BçA¦öÜFwö¬%4zùe‘Áƒ#ô„xØ$<¦ªØ£>*EŠ1ÎYá ¦L˜:UNžãà^H€H€H Z¬^½Z–WRƒÖR´hQó“I%SªT©¨áÚ!U¢bÅŠæ•H€H€b—À™3gî@” &˜Á-±KƒgN$@$@$@$@$lÉâpä<èÚµk Ò¡íV¡ÄFMÑ[ó}ûöi:âæ§´ªTÒ¦MëÜÄï÷pèÓ§iPô{#®Tp7‚‰I¨2n½õÖ[òÕW_I;uåéÒ¥KP=¢ Û¼YdÍKtôå—¢Þÿ–DAÚˆ`dË&râ„ȹs ®Êܨ@ ´Ä4n‹ÌG¤žS®˜M§f3AZµ%KD¾ýV¤aC{._Iàÿì ¸MeûÆïÌ‘!¢Œ…’H"Si DJ©„æúФ2ü©¯ú ÍH*â+3))ˆ$ ùdh”Œ™‡þϽ–}ÎÞû Î>gOkïû¹®}öÚkx‡ß:ç¼{½ïóÜd@€Ê7ÜpJ—.m¾zàÔSOuÎd6Zf$lÞæ°ÁÅYØm™Ùœ,šô7¥ÀLD@D@N·mÛf±…Q¤HçÛL+Fuå§Ÿ~ÚžOsá±ÇÀL…7^ïºæšk0nÜ8ð]&" "à-L±]§N{´‡À07—-[†:*Ga(REˆ€ˆ€ˆ€ˆ€ˆ€ˆ@ <)[QÞ(_¾<øjÑ¢E¶jf¾éK.¹Œþgt"#ø*W®œ­²tQx,YKÿKw»'á)sëÖ­øôÓOñÉ'Ÿ`áÂ…øöÛoÈÔ—˜Ú+™JCü}ïÚ0'><òˆ«ªcê^°†Y2¦±Ëê¹Y*0‰N¢Ê‘¥=ÂÆ®ìˆ×™NF'°d6:½ð‚œÚ’ùw@}Ï2'Ÿ\'žøÕ®ïĈ}P®\Å”kW¬€¥U~8eWšƒ1cÜó8 ÛO?=z¸¾¾QÁç賈€ˆ€xÀˆ#зoßL›]ÏTaÇØ ÉÀ¦d2:VÝxãÉÔeõUD@‚ƒs™b›Î²ƒL)šY²bë,Rå'{ðÛ²eKÊëO“Èå~Ω^gRôpîP&" " " " " a&3‡£œöãÖ[o_²ø!ðøãáQ7âÃð¿ÿýoÇÁˆ Xÿ0E•Õ®½öZËÊô¤±êìLæíÛÃäÂ:vøV¢»tIf"Ñë»ÏáˆiÕ‚•¶,MƒcÉîpT¥ @%.™ˆ@¦žþ SäÿîêNVÌ«¯vÿ­Ð§‘ÆÏü—Ã,˜™e£µhU hQ ØáèÐ!àúë]Q»iÓÜ!#£r´_D@D@¼B`‘¥0fv¦I{ÅM¦‹Ù½{wÀ«lÙ²6.vCîܹ½Ò-µSD@D É LãC›Y©R¥Ð¯_?G™hìØ±(T¨Pºd~þùgGퟪ~éY¾|ùЬY3GõîÊD@D@D@D@D@D Ì<ëpf*.‡/fÏ:uÎ>;¨°9s`³¼L™ \ÍÀ˜OüÒK/ŦM›,¦NkÒ¤ 7nŒjÕªepUï®] ´T÷îôÈ‚ÁKbQì:9[´™å=Jßá¨BX^¤(6HU‰€xÀNKkIÇéÉ“Ùò®èÕkZ¶¬Ž§ÁþŠ™9ñjþ;2\Œ Péœs¸×5IJL›«vüS}ûõ." " ^%ð×_9J Tñ™2e jÕªåÕ®¨Ý" " "@`úôéNŠP`Þfù°'ÛãêÕ«1uêÔeÿýû÷cøðá:t¨ãtÛ®];Ëf¹ã¨TÒrqÓa‰¯¢ŒJ‘‰€ˆ€ˆ€ˆ€ˆ€ˆ@ dìùÁJUtâ2$u#æxaŸÑÙˆNGgœ¼þºë$sìØÐÞT{èlÄèît¢‘ŸèÔ%‹âÅ:u€ùó£GÝ_~Ö¾k`ò×¶½¶¨&ÏøÒ”ÐèP»aÃT¬ø½Ã¢R+8Ã#Eë²c̰iÁ«69zõÌ™0Å@ aCXʶÔýÚ¯8jß½»˜ªëæÍ›µ9yõNªÝ" " Á„I?ª»Ÿ|òÉxçw‡¢€)B'Nœhê·—á¿ÿý/î¿ÿ~çyò¬³Î³Ï>kÁ+-ƒ‹Ógˆ ‹‰—‰@Î ¬\ Ô¬i aª•õÅî{øµ§aX¸ P° ðùçnî¿Ó{öì .Â2W¹œüÀh3> ´hXtµé[§¶Ï&†¤`y’Ô3´%"ĸH:hÐ GµoË–-xùå—-mhsKãúâæÍÏ<s`rK±uXK%ªë‹ îÙ““Út­ˆ€ˆ€ĆÀSO=…÷ßßQ ¼ñÆcÓÕ*" "  0Ó"FøÌxå•W¦”þ/“¬5k–³¿uëÖ8ÿüó‡¤íÛ·;ŽF+LâVÎF)¸´!" " " " "1S8úçŸÀ<ÓëÖ­s¢K[ú¡3Lõ¦‚¥"Ê;w P¨ÊœغöЛN Ë—eÊwßÎÁÔ]Æ ÃøñãA àÁƒ§ЖÄ+‹*³_V7­Zݺn+ÍaÎ19Åë]S»D f¶mÛæL /X°ÀIýÂèÔ(íÛ·/MÿóæÍ‹fÍšYj‘Q®\¹4ǵ#þ:ìØ{Ð jÛ‘#À÷ßM›üÈž~ýú™BRM¼ùæ›È•KÂ[„ô). 4hàªuÙ‡ý»Müê+ ~ ví¸l²%";7ÝtèlÔ«W/S"z ÀÈ‘n{(˜N{ôQWHðÞ{]aÁà²Ï>ؽ L˜|TŸE@D@D þpéH‹XîÐ)S¦8ãhüµR-ìØ»w/>üðCG ·X±bi aîÒ¥KA¥ÜòÁ%iÎÖˆ¨zvLš4ÉQ°Y¸paºÎFìö!ó^¡D:ebŸ{î¹ Ï‹"Õt<¦â‹B…Òq8Z³Ø¿8÷Ü ‹Xi¹Ø8q\¼xq̘1… Îð\¸"/Ф À´61dy‘:Qê‹Çd" "pŒÀ /¼`JCÓÑ¥KŒ5*e‘tÞ<Àü¬qÉ%áCÅ,C‡L±Æ÷ôìœs`Îݰ mØ÷¬ôÎp÷Q½Ð†fpœ—‰€ˆ€ˆ@¬pŽ C‡–Íø/¼þúë¨\¹r¬š¢zE@D@D "¨âÇÀÜ+®¸"Ãòó[€›œ2Ä£" " " " " 1"5…£!C†`ܸqYîæÁƒÁº7:9©³|¡NŒ:R¥€¿ÿ†åªšéÔh¨½lµ•L>H8pÀÉG^±bEçtýÏ`Zµ9ss¢¹*¯tjž¹}j¨DƒÀªU«pß}÷¡R¥J=ztJ•Tüøcà aζ)»s¼AÅÁN`û®3SF¾öÀñûÄÓ?cÓ&€ÊKô6ç_]úgj¯ˆ€ˆ€D–ÀÝ–žûKK]LäÌb#Û •." " ‘#ÀÚ•W^¹JT²ˆ€ˆ€ˆ€ˆ€ˆ€D€@®”™¦ÈÕ«WcüøñiögeÇìÙ³ÁÖ²ø'&ڷߺÎ@á¨cÇŽøé§ŸœØFÅÕB&@‡#ÓªQáÈ~§áÛçÑO$&@‡ÚNæýCe†·ÞzËIãÃAGÝnÝ€nðí Ï;•‹,;©ã™Y‰ô‘,X0ý3˜ •Y#ü¨SÇUAÚµ+ýsµWD@D@"I€AHtؽôÒK1xðàHV¥²E@D@D &ŽZçÌ™3Q«V-{Ž«“6¨RÈ.¨(=ñĦ~(Ç(NÖ6õ›êÕ«ã?þ°…­1Ïò‹ðåoDݺuQ¶lYÿÝÚŽwt8¢t™g¦iéúõëñÑG9éezôè‘æ¸vˆ€'Ô¬ ”.í:=ó 0q¢'š­FŠ€D‡ÀC=„+VàÉ'Ÿ4%#“2ò³“OFŽôÛ'›ÌyùåÀž=0')FئÜNˆ“ª" " IC`þüùèÛ·/ªV­ŠÉ“'#wîÜIÓwuTD@D y|õÕWزe zöì™3R:&IE`îܹøÏþ*øõïßß}Ÿ5 ¸î:Ø‚.,Õ)м¹'š­FŠ€ˆ€$ #]gƒÒI'äÌp¾@&" " ‰HÀ§ì¯´¡‰xwÕ'H|O©¶fÍšŠÕªUs$ÑýN°7ÝtZµj°{ݺuŸõ!~,^ ¼ó°w¯_›L±Êd«€ Ò©Ñáèsθä’Kü.Ò¦xÀæâ&ùÞ;5Y"D€Ñ©Ý»wGÑ¢E1aÂó»ø×­l÷„¾ÁænÑ´ÀUWÁvé]g#*=]|1ðùçÙî†.H ;vìp‘vY>ÏI“&s2HTÓ§OG™2euÿDí£ú%" " " " "¸"¾ÆÔYþvýõ×;QŠþûÒÛ¦Ó‘¿ÉáÈŸF|m¿þ:б#ð÷ß~í*YX¹xà¿©›ü1jÔ¨’èÖËTn–N&" "ÄŽ9bÏ–ÁÀ¥gŸ}-Z´Hb꺈€ˆ@¢X»v-V¯^í8Ú20S&" " " " " ^#u‡£ d‰Ñ¹¦ŒS¬X±”sé¸tôèÑ”ÏÚˆþ銻pÑ2Ũæ`E¨Z5e—oƒÓ¿üò š5kæÛ¥wH#FŒÀœ9sµÆ:¤Û':íÔ¬ Ð'ÖV¾<`MFçήÓO:ÃvJ©†ôâ‹0õ&Øw²”Ý&JPD)öíúõsß[¶‚|ÕÊ燌êNs¢vˆ€ˆ€xŽÀ=÷܃yóæá¶ÛnCŸ>}<×~5XD@D@B!@u#Ú•W^Êe:WD@D@D@D@D@â†@ÄŽ~ûí·€Î†¢hSºté”k8€¿þú+å³6â‡@åÊ@Ó¦@îÜYkÓ©Ñšò"™ˆ€ˆ€$ÿûߦTΜxÌ‹'³uT:.œÁ QÞ}ûíÀ›oÂdü3¯¸Q# o_à³Ï€7ÞH=—C“'íÛ§žêú•z<£-*%4n  ¼ý6@'æË.~ÿ=ý«fÏvµ‚¾^¦²öŠ€ˆ€xŠ•9~ò9q$ómÊD@D@D Á L›6ÍÉ  Ì¿Ñꞈ€ˆ€ˆ€ˆ€$0ˆ;ýóÏ?)øòæÍ‹B… ¥|>ÞóWû›ŽüiÄÏöСÀüùYoŽr™Rc®0ÊD@D@D AP½oÆ hݺu†ßw¨þ³q#,EŒ7;MǠ矺tIm?÷QÌiÆ  I bE7£ªeÃÉÔ*UÆž~Ú=K¶Öì(QéˆjIþÆz˜vmËà§ŸRlÞ ìÝ›úY[" " Þ#ð«åؼ뮻pÆg`Ê”)È“'÷:¡‹€ˆ€ˆ@¶nÝŠ/¾ø-íá'þü!\©SE@D@D@D@D@D ~DuG¡˜¶B¡ås?þøc0e^ñâŽÓhµTD@D@ŽCàÓO?uθøâ‹3<ÓÖQAefõ¢,èªù·½[7 dI cGWáèóÏ]Õ¢®]aè°Ecÿ³S·ÉÀßq‰Gzô€)Z=´kK«œx¢{Í)§çü÷¿®S÷þü3pÁ@ýúÀ»ïz—«ÛCýä%ð´yŸRÕøyójÕsbòþ¨ç" "LfΜié¢âŠ+®H¦n«¯" " " " "  FÀ£Ë] v’¨;«V­Âü¡tjItÏÕUH>‡£FÌ=–‰1)U€ŪVu˜NÖ°!ðàƒÀ’%À Aî¾P~òÚpS·™ÈEŠõì |õU ;Ë^‡æÍËD€ûîK9U" " "@…¦S«]»6Ú´iã¡–«©" " "}Ó§OGîܹѶmÛì¢+E@D@D@D@D@D ÆäpãlÕ3­iÓ¦ÉÖuõWD@D Á |öÙg`:ØJÌ–ä6p LÍxê)×ñ(TÆsçTIò·ôÄ2_{ÍUTzî9`Ô(ÿ³ÝíC‡\¥¤#GÒÓØxöÙg-5æ^ 0 öQ D@D@D Œ¶mÛ†u–W{÷îÝ¥îß¿ßÔ\çY°FC”(Q"à˜>ˆ€ˆ€ˆ€ˆ€ˆ€ˆ€—ÈáÈKw+ÛúË/@ïÞÀGe­qt8bôÎñÔ²VšÎø °sçN¬\¹RãÛ±Û‘/0alÌw†öíK½OW_ Œ—ú9£­–-3:¸Ÿu½÷pæ™À]w³gîÝ}tX*U `YŸ|x]¼|²µX&!¬X/-R;D@D z8~Ž9gu®æ!!@§¢s- £ªIÂ)R-?5ƒS.¼ðB´hÑ{öìÁ•W^™ ½U7D@D@D@D@D@’•€Ž’õ·©ß6¸jYY$ûçŸl±ïÔ©SE‹ S TŒˆ€ˆ€ÄžÀ矎£Gââ‹/ΰ1Tìyÿ} Y”vjÖtŽÖ¬qS¬̻ﺎ@ß|“!¦l(^˜5 8ùdàÚk’%a ×®ÓS¾ T«–­¢#~QÀ‹/õêTv²_£¸·Ã‡Ý´w­[|]}Ú&ÿþ;ðÝw€}ý“‰€ˆ@†FŒ]»v¡_¿~È•KÓ‚ÒÏ3f ~þùg\uÕU¸é¦›µwªýbÑ›‹-B¡B…ìÙÅ^d" " " " " "àay<Üv5=üù§Û.ì9ÆU¥nÝÜÕ§Îítß¾³U§­[·âæ›oد" " "àuŸ~ú©Ó…Ìü}&§ ½ÞÛ¬·ÿÞ{Ý”j­Z¹×<ù$pÒIÀÃg½Œ¬žyÆÀÔ©°ï@éÒ®ÃQûö@ùòY-!gçÙZ‚£ê4y²ë4túé€ÿ«bEÀ2*ÀÄ<§(ÿÚ&Nt¿> ÜqP¸°ÿÑðn³þGN9Å}1ƒ¿Ç5j¤—².½Úß~ÛUe:ñDWÅ*å{ ßÉo¾ Ü?@g°Ûo ò;¨Íˆøé'à­·€~ý˜1ÈŸ?bÕ©`È*;ܾg—Ä›öŘêFÁvÈr?çÍêðà‹õYD@D@D@D@D@â„€ŽâäFxµiޏÊÁ*\Å r8b:5ZÓ¦M½Ú]µ[D@D@Ò%ðÙgŸ9ê}µjÕJ÷8M–.u`’IÀ}4)ÉôéÕÒsPI=+û[ TTÊȨºóÛoÀyçetFèû™ªŽTüšCu":ðXÆ'µ›­!¤1:@]s p ©‡êÖu?6nŒ¬³k¤РФ±¶m™3ÓìN³ƒ¾åTb¢SÔ¦M@±biNqv4nìª -\äI牃ªHtÀ;í4÷U¶,Ìé õU¦L £ôkÑ^àïÙ´iÀ+¯|ª*Å{DG²•‰@<xÑäÝþúë/ <ØþO¤ó"­6‰€ˆ€ˆ@¼mú6lÀSO=•®³‹³Q@ê¸' Y½¸¿EñÝÀ4Gß~ë6Ør”Ž8‘œYº™àkôYD@D@âÀ°dÉ4kÖ,Ãt0>Õ›-â½7‘mm¢¥8”^Oè”/ðÃéÍ޾ݻó7Õ”|" T¦ó{èDÄ—­78Ö±cúŽ4T ª^=° tî±LCæÌ¸?+ŸèXÕ¿?À”r|÷S˱]tDñ½ÆsSÒÑyªIß™é¿Ï™¬\ Üw_ÆÎF¼’)âøÊÌXÿ÷ßû÷§=‹©æ*UreÈø²Ë\Ç.ÿ3x8x¸ûn÷\ÿcɰM£W_xÿ¶lqª˜JðÖ[þ®SML&ñJ€cç3Ï;ÿ|WgÀ×yÊ·?½wªÑ¡êž{Ò;šõ}¼>ãýؼøßÿ€õë_‹»ŠQ{÷úÎvßéŒõÅîkÔ(àý÷K/ <'?ѹŠNZTò"3Ó ÒŒ>¥J9»ôCâžÀk¯½fÿ;sRªå£'¨LD@D@„À4“ž\µjþõ¯9*¸ Ò-uCD@D@D@D@D@Ò%u‡#>le×(µž“ÃQv¨eíš4 GË—»y3jÔ(`¹íß¾}»Ò©PÑD ðé§Ÿ:ÝÈHÁï‘GŽ—ãÇ»Ž‰Ðg¯öG¼]T:çœÐ{Á̱tæéÑ#õZf v6J=š³-¦g³lCŽêРAnŠ2ÿTl•Îmuê>\~yFg¥îg*3öɲ F­[§óßZ´  R÷îáMÓEç/¾jÖô¯-ómrøüs÷~Påçâ‹3?ßkG©E‡1¦Eó·Y³¦<óL ys kWà’KÒWÍò¿NÛ"Oˆ4̼KZ~Í[)É%"ÀùëM¾ôžœzè'uED@D@D@D@D q XŒ³L²O€ ¨,bÚ Ç¨ptÖYn¾¿b™NÖ´iS¿½ÚïøÌòiåÏŸßQñ î ‡Å^p!è ‹->}\U˜ì:ѱã¶Û€µk£Ó¦h3-0 ÚC¹ÎCt@ 6ªýø›eo0eɬ9ù®{øa÷û߃ËóCu#:ú0•Y¼˜e2Ä[oÁþ[4z4в¥«µzuà±xÿ4>@Õ©ÛoOÛR*>1ÅÜÒ¥À˜1ün-g£´”´'Þ L˜0Á?7âÞ{ïEÁ‚ã½¹jŸˆ€ˆ€d™À‡~è¤Û¾ùæ›MyRÒ“Y§E@D@D@D@D@ê:YMê:1±Mñn¼WTc2ǾbEׇiÛâÙæÍsï'¤N?=mK#¥¦•¶&íÈà¸9tèP+VÌþçØ?™ˆ€ˆ€$ªå1 ÔâÉC?øª+" " " " " ñG Ë.ñ×µ(ú¨pdJø®QÆvî¹îû±ŸGޱô%Ÿ¢¾å1¡¤°LD@D@…ÀÊ•+±cÇ4jÔ(M—ÞxÃMùÄõÔ ¡1͹Úÿ^˜4 ¸á†è·• T³aZ>ËPë¨Úôî T¯[¸‡ýºiûrÚ2f>¦råã§-é駦ù¢Ò’Œ™˜·m˜‚ŒÊVæ÷Ž—^Ú·wû¯}`š4:‘­Yd3›t¼vMí‡ÀäÉ“M%n-úöí‹"”c“‰€ˆ€ˆ@‚Xdù‡pÙ¥KsOÇs ±Ѹ˜9Îòwüøãøã?œ«ù[ÒV…¸Ày­:Õ©S'ÄRs~úÞ½À¾}~)Õ–/w ’q`t­iÓ¦îqýð,DÛB½1Ÿ™Ç@.óNúØc°1;–6&ÔRu~$ lÞì:é´há*E²®H”MU#¦Xûè#à óA«uì˜~qtjâËËFå *E=òЩP¨Pô{sð 0q"ðüónú::±]~9lq*úmQ©4¶¥²ˆäÖüùó-mã2癘42ÈÇø¯s’‘%zéT¾1c†©i¶7RûÂ.ˆoC«‚E@D@D [,†V m5áž{îIq6ÊN›mE¬sçθÅB°¹ és6bYÿüó¶lÙ*Hu²“;î¸Ã¢Î-ì<ŠFõ†òåråŽUJ…£2eür¬¹ûépT @[³U1™ˆ€ˆ€g $ÃØêÍáø\Ó¤þ‚¬9$7hÜxc¨%êüH 8ÓÙz@¦¶b0r¤«@“é‰18È µmÛ†ßÙ(]‰j•… »Šc¿ÿ˜ÈJÔíµ×€ Üÿ L™Æt‹ï¿/g£¨ßˆ  5¶‰àGªåÎ÷Þ{okQÑ" " $Óñ-Þç$ãí.1MÎÕö§¤¦LD@D b4¾E ­ lÃQ¶Ñe~áÓO?5\IȦýi¹Êºwï¦#ËŠ}daî×^{-x]´Ì2ÄaÓ&`Ð «ñðaàûï u£C‡9ÎR lÕ5þüÑjšêˆdÛBÁ¶aÃüüóÏiÒ©± :PFª%¡ιU«º©È-ʼ¾W^©p7f~žŽz‹@@€}UÇ/¿D¯í?ý €¥DžyÆ­›iñªU‹^TSú4¶¥Ï%Ü{¿µà”yóæ¡C‡¨X±b¸‹Wy" " Ar2¾yaN2¨»1ý¸zõjLš4 -LBõ|æ!–‰€ˆ€DŒ€Æ·ˆ¡UÁ" " "mO©–í–yøÂO>ù¯¿þz¶{pàÀÜ|óÍÎ"¦¯*Ñi‡)[j×®;v`‘­”½ýöÛ)ÊF\øìg¹"^±2¦\‹ªÑ¹Š’Ö6[²d öìÙ£tjþP´-" $”cÛqîÓ Ð5j”î™ò³MK\ì¼ààãó‹FÞ¼i›D?êwÞÎ:+ÍW›´''èûª‰ý˯|øaXêÀÄ訉«`øp M€ýbÚÃhØÀîïÛ›oMšD£FÕ‘Û²B)<ç çžÙ<žUŠˆ€ˆ@†r2¾yrN2C‘?À¹Ø–-[:=ƼÚ2ˆÐø1´*XD@D@rD .ŽŽ=Šüß}÷˜óš©ÃvíÚ•âHS´hQ)RÅ‹wÒ–œk*:U-=çŸÇŽž|2výUÍ4¶òˆô§gíî°IÇ=øàƒ‘®Jå‹€ˆ@RÈéøæÙ9ÉÜu¦Ö¦³Ž$Ú¥K—´BUŠ€$¿þrUz¨þþ»t"u-Ç}Ñø–c„*@D@bF€ë%cƳµ‹h•%,˜81…(9KçæÕ˜¦‹J>×^{­óZÁõÛ¸qãàK¯BE¦þýû‡Ü¢iÓ¦YD½…Ô3FÒ+3£òÑ Õ?fTŠÚ¼y³ïcÄÞÍ/ /¼K™fUXQ£Lz* >:1Üi§°_D@D@¼A ÙÆ¶¬Þ•¿l&hõêÕêFLÑU¾¼ë ‘Õrt^lø¾6¥çp´oðÞ{À…•+Ǧ}ñRëE=z… ÇK‹¼×ûZnÊ.@Û¶îï”÷z˜-ÖØ½ûº}ûvs\|ÕI ~Ùe—E¯bÕ$" IH §ã›—æ$cy{ùåÇÙè§Ÿ~rƸnݺŲ9ª[DÀÃlZÉIùmñø8õT7Øgþübر£š‡{þ¦k| ?S•(" ‘$`‰¬0r$ШP¡0dÈ)æûÐ4’UªìˆºÃÑÂ… ѪU+ÇY(\}§ƒM‡,jøIs~¡÷Kôí‡~pÔš|5?n¡Ì¥K‡î‰îKÏâ+çÒK/õmfúÞ°aÀã³gÏø‰ŒþïÕ ­j¥›™åÃrþJÑá¨J•*8á„"Ñ•)" "AÉ8¶e'ÇkFXù§ ýüs÷ê  ¨Y-RçE‘S„Ù×SÑL[錰hB ™ÕÒRÑžì0qVǤn”]‚á¿Nc[ø™fVâèÑ£íêßxà2;MÇD@D@rH ã›—æ$sˆ+Û—ÿöÛohÖ¬8ßÉ Ú›nº)ÛeéBä%À§ŸœuLøæXV˜bðÁß™’öÇÉ '¨çß‚€è£ˆ€Ä KØäd{Xº˜3xýu`èP€n eË}ú¸ã[ÇŽÀèÑ¿ÙØ65NZ®fD‚@ wH$jð+óƒ>0•^`”ãñ¬P¡B&˜SÉ„ÌJj2.úM˜0Œ*Ù¹sçñŠëñ} ï½÷âСCN¹LùÖ–aÌÙ°%K–¤\E'&Mš¤|ÎlÃ_áˆçEÃáhëV o^ hÑô[Æ{´yt8’‰€ˆ€x‹@²ŽmY½K¾Éx‡£õë“NÎ=7«¥è¼X`Z5ËÜk‘ƒ­xóM wn€C²Ä'@E«)íþ¾2Õ¡LçþòUbè4¶…Î,'Wì·\£#FŒ°Å”Ó¡œ”¥kE@D =;wæIowÒí ×øæ¥9ÉXÜä?,T›ÎF?þø£)¾¿€[n¹%ÍP" !ÀØlžp6Ø~ÿ(V èÝxÿ}€éÔþû_ {wàä“Ý-#oú=ø%ÀùNf{¨[hÓÆÃúõ¾ø–¹ÉU|gB§·ß.»l镸>ñÛ#µ,'¢ödþ¾}sºçž{p„3ïéU›v$'#+V¬ˆSzîg%k™#ûÛo¿Åĉ±•/A¶Ò¾ÉuíÚ”Y,^¼xÐÑÈ|4hÖs•Ѭ\¹rxÔÊbu,ƒ)Z|vÎ9ç D‰¾™¾×ªU 'žx¢ó%Œ'2Ò&ÒF«2Cãýâ$³Ž2D¤" "·’ulËê a UŽÑÕ«WO¹„Ž*t^¡³Š,þ 0­ÕéëíËòCŸø¹sÝHŒR¥â¿jaÎ ˜¼E§{÷ö¸;îÈy™¾ø¿`üxàèQ߽ǚ€Æ¶èÞñöÀÅÙçŸyòDmê!ºTm" 1!À‰kFÏŽu¡ê}“6ÄS¥áß¼6'mþ\ôæÜ5Ój5 ·Ýv[´› úD@bL€±æË–'’%aëWÏÿ  à6¸S'àÆO%Ùñ h|;>#!" ‘&°n›à誫kj×ÎÍ À9t¦å;_Tïc¦,¹DeÖïÏ?ÿD?skKÏÙ¨Žy­üë_ÿ25€ÌåòçÏÊ•+;/:&ñÁŽ*>œÄüþûïîÚ W§¤í”)SLÇ$x"ht¤šgöý¬`‰ÙwÕ–víÚ…"EŠdvYŽŽϯÊçôÄû&ðdÛ²r—8Ù¼Ìf™Ú˜ë~pÊPF¨É¼A€ G´E‹RŽì«#(Û¥‹{L?Ÿ@Á‚®l='€?´õÊp:ùèeöíÖ{” hl‹.ð£æi÷Ì3Ï8A@=zôˆnåªMD a 0FϦÝ0r¤ë,\µê^û>nÞÃIláß¼6'í[NÅþåË—›ZÉ“Žz´ëW}" ±!À*50Xéw`ð©í°äˆæ:Í›Ç@ôÔc柪µo4j”º_[Y' ñ-ë¬t¦ˆ€D‚€Åáê«Ýq®×üEHn½5µªL¯ˆŠÃÑðáñgÏžF¥K—FÿþýÑ¢E‹€ýYý/_>\eît|-^¼ØqZ¢¢ŽÏq2Ær#D2â„y»~øa_•N]çŸ~ÊçP7üÕxm±W-‹å6cyÙq8âä0Ãþþûï”.dljÊçp$…£ŒÚˆCüŸ·—ÒÇŒé “Ù4¶ÿîóÍ7ŽcoÆ ²Îˆ[Lqe_'‡#_#9‰È'N Ê’‡G(j¾ú g̓Ž/•GÓ I¸N§Ó¡DÛø=Æÿ¹©ÉƒaÓAñ]Ó¦MÃÚµkçe¶I&" 9%ðÚk0åt`÷n F#¦qÐÒÎ|n©jÜÀ»œ–ïÅëÃ9¾ÅËœ$ŸÇùòÛ š‡8ƒ}bQ½êˆ1u&®mªÌY˜ GsLÔÛæúõçàË/ï3¥wlKV§Æpoñ2'ɹL­úm3gÎtïÃñ{jK,ÿò]wÝåÔO•ýxpê µ:_D 4ï½çÎ Ðç‡ã΃º*È¡<†V#›Þr2gð:>·E:kG¨í‹æù‰:¾‘!×.¿0É,_Æf™0aB4ñª.$%@÷ƒ—_††ÁÖHÜÀKÎ{Ú“bL‹æïpd®Žc-v³cÌRÅìW4ŽmúŠÞ¹&O¤›úî»ïT‘'O¼úê«as6ò^¼xq¼ð ¸üòËíÀÜÊÍÅK§£ÁLšf{ñÅñõ×_;¥Ò ùé§Ÿû– ~¸u±;øüà褬¶­F¨[·®yñ›Œ ²Œ@:ýôÓsPŠ.È`úÊU ]:f5-d©p’z$òØVµjUT«V Ó§O÷Ýêl¿ÿD×3§ÞGš5š6Ív±º0­è3JÃŽšc‰ïZ½'&/¿„)©º×óçµkg­Ÿ–ùß~ P|5DÁÒ¬UÂY|°÷=Üs±nÖ¬Y!\§&òØÆž2eÊ`Á‚qu³>úè#S[d) ïƒd" ÉE`èP€/Nj_z)L([6k Ì·3f6daêT€NF>»ì2€N½¹rµ¶]|ÑYü¼òÊ+Îv²ý÷ø/s’§œrŠ)…œP«{ËyÕk-s›œß504VíV½" 9#@Åc[RBõê@ãÆásœÍ¬UÝ»w_´eË–áñÇw¶“ñG¢Žo¼—t¦e6©å%ão¶ú,±%pÓMjiœ«ddƒîûgPTÅ}¹g¤þÌ®³K¸òÊ+·Þ³gOnÊ”@Μcg ÿöRa$Æ3¦†«X±¢ïc¶ßƒîC} ^ ÷I3f»A™\¸~=Lß•QcNâôl½TÎ’gG="½ò´OD@D r4¶e-Ç7šoì§ÿÑSOÛ¶Éá(ëãïL:Q]&>×]S»ã2м9@§£sÏõMÿ ¬tT2?‹˜;¥ßÂäÚ«±-6÷›Ïä Æyáà2¤#ÀXoÑg®E@Ÿ€¹48Á–cÇÂÔÏ¿Ïêaô D46#|jCì¥ {õêÑ^66·óÊ•+§Ô±cÇPþ6\F'¦RcÊZs[}èСCXŠ–Ë¢ë ó!ú[°â‘ÿ±œnoؼý¶›ß1£²¨pDm™ˆ€ˆ@|ÐØÚý¡ÂyK35dÇ6tßõSD q´hK Kíáª4P¹(3£Ê_Ló"‹-m±áÿÕW_ G]ºtIqÌMKT«ˆ@4PâØôXJu÷Ü,_LœèªÑ‰ŽDŒªµÌÕ§À(´ýùçÀ¸ãn†''ñHo^š“ŒÆíì±Ç0oÞ<Üf^7Þxc4ªT" "Ô4¾%õíWçE@"HÀ¾Ö:Æ€i9Et’Q‡#_Ê1ãzõêY”°… GØÚ´iPC8%æùÀù3š•,YÒ·šÀòümwf31þ'Û>pà@ÀÞ“O>9às8?üù§[šÓä>}ÜÄŽûö¥TAG¯m&õ ‡£$Ú¸% ±-´[C…#ÿtj\¡ÉáÈå Ÿ"hètÄ´.>§£+2îaýú0g =ÀgL(zG4¶EµMT7bê_*?ÿcÚH,t*âtÐOö+wîÔÏ—_pÜä4ݸqnzR*®^ Ü}wZg%~Ÿ¦´¿”ŒRoEj|óÒœd0“pf ZŽgœÇ~þùçÃ]¼ÊˆC&fæŒMqØ´¤i’Æ·¤¹Õꨈ@ X–N'eµe Æ9çD±bU•t"êp´uëÖ 5 ø©Ì…êo>!ÿ}ÙÙžj+ 3™Hþ˜ µœ Å‹÷}Ìñ;ó”û[¨Gû÷ï÷¿<¬m (Ø>øn­Ódæ’Ù¼8ñĔӨnD“ÃQ mˆ€ˆ@\ÐØÚm9h¹~ýõ×5E:•- œ~zheéìø 0jpá…€Ÿßt|4L­ˆ+-[º¹ÎMì—^ê.ž²\l•Åm±¹'ßšŸ—¯¹æšˆ¥QMÏT«ˆ@zè0t °¿ùôަî;õTÀü70r$ðÛo§kÖ„9r ¤ž§­ãˆäøæ¥9Éã“ÊþTêïÚµ«3§:eÊäÏŸ?û…éJÏ`zufNdZOYô h|‹>sÕ("èdôÚkÀÀÉÑ_õ2vLØ8rö×_^¦L™€Ï‘ú•ó§OŽ'‡6,¥æîÞg+S|ðAʾà * ø?ûŸ_¤HÔgô1Ëéýú:Ng(_}ï>¤ŽÂ‘=Œ[nß!çÝçpäŸÞ.à}ˆ ÛB» möéèÑ£) G»v+WŒy“¿Æ,ZäFçâÍ>¨ÕÑ!Ъ•«ttÕU®ÓÑEsçŸ}Å;D§Aª%CÛ2DуvÊïß¿DëQá" ±'@Õ?ŠjßrKÖ#e¹˜Û¬з/À4k?›‹}_¼Ô‚HŽo^š“Œä=›k_î¶oߎ±cÇ¢B… ‘¬Je‹€X³?x÷]÷y‹ŽªÑ0ªÙ2Æü†H ÞéÕ¡ñ-=*Ú'"H˜ÐÈ–, Tt{Åç®›oŽnª-9 دZä,Øá(øá5R5— r~ VZÊn½þ BŒÞìÝ»wHEÍž=|ù¬V­Z`´ŒÏ‚ùüÆÐ¯ŒŠ >ËcÿEèÐ);žÃ‘ÏÙJ G‘º*WD@ÂC@c[h}ã›/¥SBðaAéÔBãOg÷êå.vÕ®O­R[╎Þ{hßÞ•$îÐ8ûìxmmò¶Kc[ôïý[!â³mÛ¶mQ[ÿP£T£D™@¡BîxxäHhŸu,/´ktv*HŽo^š“L%þ­/¾øÂ)ôRJZÊD@"N€ñê'ºŽF‹»Õ,P‰¸F àŽ;"ÞpL£ºÑÓOG¾.Õ>oésÑ^o8tÈ T|óM`út74Ÿ…7öv¿ÔzH@Dލäo'Pk9 vøðá€ZvQ~Àì(µŒÉ³hüRæï ÄIÞHòfJ5ÞÎ%¬”à€ŸIáȆ6E@D ‰ xilËÊmú‰iDÍ| ~L§F“ÑËÁ‹?™æ£M/¶\mŽÖ­%K`é¦Z“%DÛÂq™nœ € Gq*CDÀ#rçöHCÕÌãÐØæ"¢ÃQùòå×q¡é`vçÎd ºwºuêÔÎ;¸ï> I“Èx\v™ReçèFÆùÅßâü©y"€ hl‹î}6ll#u£èrWm" œ®bzQ‹Ç“Å€@$Ç7/ÍIF ýW_}å¨õ5”|m¤«Ü"Àxï•+Ý—ùé9NEwÝå:ùw³KÀ—)‹± ¤µiÌ™“úÙë Gu_=<÷œÿÑœo3¦œŠþNN9/U%d—€Æ·ì’Óu" Ñ$°{·ë,túéiÕò™°è矪Uot}˜®ÓßzödÖ ysÿ½áߦ»Àرn¹r8 ?_•˜>\éïÏÞ`:ÏDÖR—ÌÏÂåpäWdÄ6¯¼òÊ€²_¦ËãqlÇŽ˜GbƒG§œb%§ãptðàAûÇú3ªT©‰ªU¦ˆ€ˆ€ÇxelË V*U°„<æa´|9L‰PéÔ²ÂM爀ˆ@¢H¤±-'÷æ÷ßwfê[ˆz¤UvsÒN]+"sœj»å W¯œ—¥â“@²mL§FkàJ­¨à"ªeеÀh×锉-˜îŒ £GLô1Áöâ‹ÀGtP õO« qc8Á^Áåf÷óo¿,—ÎNl·,9$ûø–wY½ÈxóMwüã³Ðóϧ­‹iÔ~ù&" ;ù®ˆ´³ëyâ o^à‘G|µê]"O ¢GUéÊçg_Ú_Üßÿí·'2› . (øì³ÏøÏªW¯n©Ü¾ûî;¼E Ñ Œ<ï°ð€½{÷¦œÑ¡C‡”íHlüóû pä|pkÛ°aƒ$‡£HÐW™" "à=^Û²J• G>§^Ÿµ`³JO牀ˆ@âH¤±-'wå™gžÁþýû¥n”ˆºV²A€ ¦”ãŸ1#gó’»ïL˜ƒe³]÷’}lc lA“;97£¢¸¿ƒj „——,k..»  šC¿~ýòÊ•nº °¯xÿ}w•E=z¤­ÿšk`iwbÅÒ;Þ—Æ#FïÌã§Û\±"0dˆ›¬NG²ä ìã[rÜeõR"K€nÕª¯¾ ¼÷^Úºøœ/Æ6¾ò l #>ZĔţ,¯ê¾}ûâ£AjEDä‰H©Ç ½è¢‹P¸paì¦Î˜Ù¡C‡ðÒK/á¾ûî;vFøß¸ø %úÙ%—\â÷)þ7{š®Ú<ÒÐ'Ÿ|Ò<ù “%-¦¢‚Ϙ¢®wïÞN~qß¾3Î8ݺuó}ŒÈ» *™d~Æ)Õ˜N&‡£ˆàW¡" "àIñ>¶eêÎ;±}ûö””¡'Ô® Pê[&" "|alËÉ]c*ó-lýœsÎqRƒç¤,]+"uŒI»õVXà,Ø h×.ë×f÷ÌI“€Ï>s•,jÔÈn)ºÎ ’ulã¼ëâÅ‹qÁ̽záž©")t²? äËç¦JcŠ˜Ö­]Õ„HÕ\.ëΪ-XL™ûè¬Äw¾˜æ†ŽQ4*&Ý?컫›RÍÝ«ŸÉ@ YÇ·d¸·ê£„ƒ…6¨è:s¦û¢ÃÎy祖Ìí¯¿NýŽ­?þp‘®¾:ýÒdbš$ŽJ {ý_\§?p€~îëõ×]§Z–Ä´m|ÅÊþ1˜_¬wß}×y­]»ÖiŠ|buG¢S¯}劜å³o„”UŸ:ujJ%¯Ûo=xÊGÈ…|ˆ¹¨ó!Ñg§XÞ¯š5kú>zâýŠ+®Ušf U;j3HO=õÆçLæ(PÀùcÝ´iS@èŒ4pà@“J˰?Ü8©ÅVómJ7¥šÏá¨r,ÿ£…»Ó*OD@D Gâ}lËJç˜NæS8ºùf€/™ˆ€ˆ@rH„±-'wân? w?á„rR”®€ùø9ó1Tâ‚i¤Bå=œ|2lÎ)Òµ©üXHÖ± ó ˜m(ùÚXÿ ªþ(àbåW_[·T#ò·»î¸ yýõ@ñâþGb·mÙ|mÝX½xôÑÀv0­[ziÒè|Ô±#,¨W/ð}JÉ:¾%ÏVOE s&²ã8ïðÙfÏžÔ?3%(ÓÒÁ‡Æ1oÆ@‡#ç@˜0YÇàE‹Ü5w_ñt|¢º,U`’žÑ ~× ˜Û±:l %«V­rüèÀ?{öllÞ¼ÙivÙ²e-ýê¨_¿>^{íµôº¢} B ¢GdÄü¨þGì[ì­Š5qâD“Ò,VŒL=öÉ'Ÿ”yµ¹zqò“ŽCTRðO÷³%Kæ+=;ñÄ1räHÔ­[7½ÃaÝgÿLEêX‘woq7J•J©Ãçp$oÅ$Ú0ñ<¶eåQE‘æs8ÊÊ5:GD@D ± x}lËîÝaP ÕJ—.m‹SA«SÙ-T׉@` —en:®íÚK[è¦~ñ̘:.ª‹-æ.¬FÁrªYlÜ›sJ”kñ*,N $ãØÆtj´ Äé]Q³D ü¸ŒÒª•;ÎØWº4G;‡¿Îœ”È0þ‰R‚¾î¶~0.Ý~;Ð¥‹›™ñèÌÐÀ— Â=>椺6v’q|‹mÕ,ñC€ÏTÑà˜‘1eZ×®®z¬%or”ò2:7\ûŸ{ÎÍœÀ±‹j|t ¢qÜâüµ×Íš¹c ü_… ¹çFûçóÖZ³f VZ®Ò¥æµdÉ,_¾< ]ZÕªUñàƒ‚þT¥Æºuë0vìØh7WõE‘@ÄŽø Ö¢E Ì›7/¥[\°»å–[,ÿîg‚2å@6ø‹:tèЀŠÛ_ßmLjïA+dÿ-˜~n´¹å3Æ<.Íå2£g S°ÕªU+ƒ3"¸ûÏ?݃ŽòÛFz.ÊD@D@DÀGÀ3c›¯ÁAï>…#)øÑGHb^Û²{ëæÌ™c,²üш+ìf·ºNâ3Îs×ß¹è×_]…¢Ë.sU#˜©zýÎæÓ¦OãÄ÷ /øM»M_ –óÌ3ÀM7¥=ž=ç,D3êÖ¦œœ…Ý씣k¼G Ƕ/,„œ‹!q…I&IB€¬Mš—\â¾â½Û\(îÞ¨^Ýmw°¬%…_2Ȉ@2Žo±Ð~HDÕ¡ÓgšJŠ) ”)-ê>{ÑaÇ÷*\à+ÚÆ4mƹŽF>g#¶¡JWuÉ_´ÛFÕ¢o-Êe™=˜þðÃ)/f^bÊ4Ÿ•°Á¸±§J=“ä»||t’ë=âGÄùøã;y°wPƒó˜Qª–2†<Ö¦Mç¡Îw,”÷ùóç;Ê>”ë ¶»L÷ó¤àY›à“"øù Ë9FO¿ìZ®\¹Ð»woK×r³#AFf¿™¦Û^ …+cÿ™–®™¹7Ö¨Q#»Uäüº-¦pÄÿÐ~ •©pDõ¶_&" "X’blËà–Iá(0Ú-" 'Ìc[vocr[~ ªËD@Ò°©ü÷¿S¿L››ÿJ=gûvàâ‹Y³€éÓ¬vR£1Ý §Í,öÌ"EÝó™ú…æÇ3.³¦‹¡"Ñi§ï ˜ì=ÀHÞôŒm´ØA“Åú÷˜¾Mæ=9ß<1'Æ[B‡£³Î:ËRžÆRU”ÄtÇÿ”btØ™;7~Úx¼–œy&,àüxgéx2Ðø– wY}ÐPõÞ{C‡Ü—¿ÃKbвx4¦/MÏ¢ílô§‰‹|ùå—΋ߋ¿¶Aú"øŒY–ªU«æ¨ò;óÙö Y§Ne‚ðÒ;¢âpD·§žz t:B=Ëc¶ËtÌîµÿÿùÏLî² Z¶l‰SO=Õw8Ã÷ƒ:©ÓFåxÕ¥w"™:r¶&¬ …Â]kÚi|ÅÑáÈO݈ž\mÚ´iÜ5U ˆq=¶e€‰ Glw)÷®»àd—_2€¥Ý" "„¼8¶eç6ñyo®­N1}z¹rå²S„®„'@‡Noñ;ãé§v—1c§`ô”)Àĉ®sÒäÉîyŒ›ëÙ`jF½fÅf~€¸ê* W/àÝw¯úûï@%S´Çùç¹JJ•+§ž¿mм¹+ãÿØc "L=¦­ä# cƒ;7˜jÕøe"h8uoË2Žjž­bÅ 7Y¢õSýP $Ãø*/^&Àg UàNx¹/ÑhûFË™ý‰åV]¸p¡óú‘žÉǬˆIB5lØÐQþdJ4:nµñÒ{zò¤·3û.3­èLšNGûöí ¨‚uƒlÅŽ/:{î¹NªµÂ¦aÆ_ì€2]¾×ï"æ/ÙP˜}hbZ C† ɶjRpyúH`êTàûï{î1Yp&NΛ7å>¤óþV¡æ›LD@D@ˆX™NyŸ¹ˆsÍ5 Ô9uED@D@²HàEËótôèQsj0¯™$ûÕ7ÇXð°z5Lfùé:ù£7.`ªÄÿPÊvÉ’Àw¸/¦Yã÷ËüùÝ4kÙ‘ôg/ãî&MrÛã‹Y³ ˆèÖÍMÏÆ4n4ªZXÜÆŒÿÁÔ¹aȰùX™» ÍjNØËD Ñ |Μ„f 8Ç) :žMɃk…k×¾¸Ÿvá…nÚMË(Oà³ ÓV3UšÏèldþ3² ЯbæÌ™)NFô·ðUãn¼ñFç»0Ó 3«’œ‹|tôžUQs8bƒè4~üxÜvÛmØÆ©tì?þ°H/ õʦ1Êò‰'ž@žüÐ-ë’K`Šâ®²³D±/>ãçW_ºvuûCg#Ó²Q%‰ÎH>èîÓOHtLAc$·Lâ•€MG bÅÀÖ½õн»;¥tU™ùu©>'ÔàóôYD@D@¼B€ÁÌ60|¸´ñÜs^iylÚ¹sçN jyoÙ† 8¨N0Ïc¦D»Ã"_[în¾ÊðaT&9$u¯œsÎ9s,¼êùçŸ7Ùè‰Nddûà\Ne¤'Ÿ|Òqj Gy*#c”ý.TȈ >KGÁDôYD@D üjaç\d¥ÂQÍš£Ö5wV}…À;#­[·šêÉ) ‡Nçz’cáú÷–.uÕ¸ÐÛ¬P½:l’6õjAñbÌxωw:±ýå¦Ncê¶à…j¶ÙâÓØÀivi‡$4*rÊ)Ž3mBwTó['´Àjà½÷\#û æÌÉû:”mÚTÌcO(pR¿3ý»ýJËD@D@D a˜8úö,j×vUa¦saìÈ~‹Ž¡’ŒfÏží¬gä7]еt49Üfö@Ëï½27¨;±ÅŠÃc–¾S§NŽâé÷ìÙ“­¾U³äÃ7ÜpÚµkg‘XŠ%‹8æÍݘô*ò9qAV&" " ‰B€éÔh•*Ur&òLeT&" " IG`ôèÑ(X° EÓwOº¾«ÃÉCàçŸÝdê¤8»÷^ _?ï,ÞÚ™“V“ò={º*GLÕ&HK€‹2ß|ó Zµj•ö öˆ@Œ 0àwìX7eŒ%ŒpRxrŸÏ¥@( ½‹€ˆ€$"fþ¢£Ñ´iîxÈà *ÃæÎˆ½ ½O?ÛÃë—_~‰¯¾úÊy_¶l™ãd”Ûѹ¨sçÎhß¾=Š-záºBB ‡#_û(Ãþ”%…gtäG}dQcK±bÅ ¬^½‡òð^ÂBÇj›ûâyç‡úõ냊I²è¸ï¾Œë[¿~½éÊY™ˆ€ˆ€$ Žo4o‰rGÕP pA–“X=zôp‚ˆB½^ç‹€W0à“_ýìWÝ‚å€òå½ÒòÔvΘS#óŽ“Tj˵%Ñ%°ÄòesZéÔ¢Ë]µ¥%À´—&¬Œ²eS展›åË R÷iKD@D@¼JàèQW96£ö¯[0øcóf÷Åø_¦Ý»×U4ú÷¿Ò¥3º:yö¿ÿþûNª{ªtþòË/)§ÿDsS iÙ²%:tè`AÓ&((ˆ©Ã‘¯T&jÛ¶­óâ¾£ö_çï¿ÿó ò=_¾|΄f‘"E7o^ßezCT8b¾G©MÅáÍQ“D@D@²MÀ§p$¿l#Ô…" " '@u#Z¯^½<Þ5_2'P ðÃé§‘ÏüÊø:*¥üøºjM|øâ‹/œ†5hÐ >¨V%5k€[n¶l¾ýà8ä39ùHè]D@DÀë.» &>⪽ú*L99°Gµj&>`L=bÌ‘&`wÒ} ƒüĉñôÓO;Â-¹råB-vùå—㢋.r^y‘‰@¬Ä…ÃQpçù‡Bç"¾dÞ"@‡£³Ï>Û[VkE@D@Dà8| G%JTÄîÝ@áÂǹ@‡E@D@D 0è- -¤Êp:u¨gꊸ ¼%KÂÔšSiX\œLD 02œÁ­uëÖM‚Þª‹ñFàða`Ø0à‰'`J[nŠª?ÈD@D@D  \r `"<àøwúéi{øøãS‡Ra¶\9÷½T©´ç%Óž]»vá•W^Ás–KŽéÓ Û¢Ä½–óûî»ï6N”âM¦›—d}K‡£$» Ó]þãÛjšÝRH˜[ªŽˆ€ˆ€#@…£Rö„óÞ{'9y¢Á‡$™ˆ€ˆ€$qãÆ™Œù^©%ÃÍN²>þù'@a“† ×_O²Î«»" øòË/GZ)µë—!šöí,ú÷w»K¥(‰€ˆ€ˆ@BذÁu*òêxä‘Ì»öÐC™O¦£Ë–-ÃøñãÁ¹€1³ÐСCqûí·£hѢɄB}õ„t8âS±ùì©§žòmê=‡V­î¹Ç¸h×.°0ªѪT©x@ŸD@D@DÀã¨pT©R%|ó ðÏ?ÀYgy¼Cj¾ˆ€ˆ€„@à…^°HÄèСCWéTˆo\ðå¼§2þõ¯øn«Z'"~k×®u'»víþÂU¢`ªÎ¹s÷ß>ùÄMcâZxôQ`À _¾  ôQD@D@¸óNv"FMÞ¼y3Þ|óM¼ñÆXÅÅx³š5k:êF;w¶ï ú²£[£j³@ !ަNŠíÛ·§t_G)(r¼±i0ol¢ÙŠâŠ«Ÿ{ª/ÝŒŽrŒYˆ€ˆ€Äà×_E£F‡£Ò¥SO£ª)" " "AóçÏÇš5kðÀ @¬IE‹@xp’› º MšL[T@)¦ÉåBï-·Ò$ Àtj´”9“‰@„Œ S$l ѱüùÆ–-öía™"T±Š(°©<ø `â<¨V ¨];Ê ð`uüñfÍš… &àã?¶e÷PÒò}÷éÓtНW¯ž{¥&'#„t8JÆ­>SnœfÿïÜ\2[¶ Ñ0“‘ƒA?D@D@ŒÀÆ/û+ža)Õ€æÍ¬ƒêŽˆ€ˆ€dBàUËñq‚šPº[&ñL`Ï`ÌàÙgˆëXÕª@Ïž@÷îÀ)§¶žÎFsæy43FŸD I|ñÅNOåp”$7 cG÷µv­;1.ÿ¹@Fú$ÉHàË/¿tÒW(Z2ÞýÐúÌø£»îfÌ˜Š“‚ÿÕÜX$§ Ž3¶^(¤ pöÙ©é«M˜ƒ)€ïÆÓ©hÁ‚à2S§NÅÎ;'#~ßìh¥×]wN;í4ßéz„" ‡£„º‘ï Ž˜:²ØAS7¢19µÙ¡C‡°yóf‹æÐD´D?D@D@†Žr[XâºuEP¬P©RÂtML |ýõ×ÎñzõêezžŠ@´> SÝrŒ|u2ÍWø>eü~æ™ÀàÁ×ä!Àtj´† &O§ÕÓPÁaØ0WAÛ;O? ”.R1:YD@D@ñÄ+Óé" "pŒÀÑ£GÁñ*íT²•‰€…¯}˜?ßMŸöÌ3®ã‘¾ùé]D@D ‘|ÿ½›&ÔœcÊ´ÚµöíÝW"õ7'}ùÞ`;Öž_'à‹€É•+—3Wrë­·:NFL›–yVe"¤4k˜¤7>»Ý¦Ÿ‘Í7[¶¸EÈá(»(uˆ€ˆ€lß¾;vì@Á‚®Ô¾3z Ýj¢ˆ€ˆ€ä”n­×‰r323.êÞ}7`"ZNPÕzööí¦Nu{}ÎF¬šjF?ìNˆ·jæÆ¨8¤"ðÃ?`÷îݨ_¿~Rõ[͘Ç":Í sBs• Rú´Œ‰éˆˆ€ˆ€ P)öÃÝtiL™öë¯ÀgŸ1Åljoèpôé§©Ÿ“yk‹­ƒO1É':ùÒÍŸiyºïºë.tëÖ eË–Mf<ê»ÃQ}ÈŒ€)ÅÙ¢+P²¤%‡£ÌP阈€ˆ@‚àb+íÈ‘sœw¥Ts0臈€ˆ@ðM¨Õ«W/ z«.Fƒ€­ïcÙ2àʼn¼y{ïy(VÌme8 7¸¯à6Ù¼®LD@rL`Ñ¢ENr8Ê1Ê„(€j{¶fˆµk.]€ÇªVMˆ®©" " "€€ÿþxé%בˆãYÓ;v<¶ÞëîJúŸ¿šÖÂ… Mq÷ç}ÕªU“Â… £G–jî&sÎòóÎJzb ©äp”ÊB[Ç!@érFNJµtŽòÚlaùòåSŠ‹€ˆ€ˆ€wøŽ®¿þÜw_jZïô@-ìXÂp39e_2_eÙŠðþû•ˆN8!•S¥µkç~¾â àé§µ¨›JG[" Ñ"às8ºà‚ ¢U¥ê‰#Tïw‚iµ‰ãÔ«¯Å‹gG USD@D@D LЯ¼¼þ:°mP pýõ@ëÖ@óæRñ#Úýû÷ã“zš>}:,X€ÿýï)Ä+T¨`07 eË–¸úê«-ûAÁ”cÚHK@Gi™hOš5jÕ²¦TÛ¸q£ãl¤ÜçÀÓnOX¿~½ÓîÚµKã =Ù5ZD@D@²E€GŒä£d¸L²BàÈàµ×€áÃuë€M›`ó©WÖ­ <û,œïTú^•ÊE[" Ñ%°xñb'†Ò`D—{,kcíO¸)Ó~û àgªìùLb>zð:É“#RӢըᦠ¥šßÉ'{½w9oÿÎ;1{öl¼ûî»–Ju.þþûo§Ðª&oH£Æ£I“&8ýôÓs^™JH!pâ矣' d K@G {kÃß±rå€ùó•;ÃŽèkд¿ìI­téÒÇêMD@D@ƒ€Oá¨råʉÑ!õBD@D@²@à“¶]f¹¯Î?ÿ|äÊ•+ Wè€ý®#Gº´> -Hå´Ó€»ïܧO" "M{÷îÅÊ•+qeÖdIC P!WåÊF:LñIE#™ˆ€ˆ€$ìÁ×_»éB{ö„¥K´†ÞŸƒbÊ”)xã7ðÑGŸ9ÏÁôhíÛ·ÇUW]…J•*…^°®ÈÑ£Q¦woô=õÔ¬¯³ý÷k[D@D@¼H`íZàºë€~l}‰ÉíltÔ¼ŽgÍš…Ë/¿UªT±ïCQ¬X1<óÌ3øý÷ßtj·Ür‹œmÂÿéÐ!Wf‹p]„Ÿ-2é÷O =*1nøÅ¢ÅM›Ô/ Ã“šmÛ¶Íy?Y @ú!" "ø€²qãFËo=ÖdUaεn6ÑÄèz!" " ÃQÆl’ùˆˆ: ¹cÇÂdèºuß~ƒó=)™¹¨ï" Þ!°xñb'…S†Ê‹ÀªU@÷î}¦)ÂÏñINF‰uÕ—À‹/}ú¸Îµ\œu–Èüúë¯3f ^}õUg>?wîÜN Ý^½z¡yóæ8r¼²è`îÚk®˜ßïÊ+·ßÆÑ_~‰Nݪ%f"îpÔ¶m[û‚oßð£h{öì‰bmIXuÓùäp$…£$ü]P—E@D ðAåÀØ»·­Ov™ˆ€ˆ€$:•°ÐÈŠ&{-uë€Áƒ7Þp'µ4yhÕJlD@DÀ[¨pTÃæ3O:é$o5\­Í”À¨QÀ}÷¹cÔCùógz‰Š€ˆ€ˆ€g œzªëdôòËÀ…z¶9n8ƒ…ç΋— ÄÌ™3qĤË”)ƒG}·Þz+Ê•+—ã:’¢JD2m8œ²èÒ¦ °|9pûíÀÈ‘€9ÉŸ@ÄŽöíÛ9%Ø/Rûµ=:¥SÛ·ow¶¥p”‚D" "  @€éÔÌÍyòäE: Ð!uAD@D@²@€)³—ÛäÐ%—\’…³uJ"à£>mùøOEtþJÐѨY³Dîµú&"¨˜FcÓ¦M` Yâà:U˜æsüx€J2HdíÛÃÔ{’׃söãmÐíµ×°yófG½²uëÖŽ“S©QÝH–æ°e¹æÜ‡|ÊB>õбc.Ìä”–-ï¾ ú÷ÏäDJ4w8J4`êOZ¾”jR8JËF{D@D@¼K`ýúõÖøý;öc´mkOq2H+W®ÄþýûQ¯^½$è­º˜Š¿ððøãL¡îFÍ\|qzgkŸˆ€xƒÕhõë×÷FƒÕÊã7èÛŽ"ñ'Ÿ¥J÷ " "  A Ù|j¶lÙ‚I“&Yv®·ñå—_:÷°¼9É<öØcèÑ£‡¥Q5‡YÖ ˜>ºuøªJ`çN˜zLÖ¯OïÌÏ>sîºKÎFéñIð}r8JðîIá(”U‡ˆ€ˆ@´ ¸ G@¥J•¤ümøªOD@D f˜N&‡£˜Ý‚˜VLåóN€Õ«a“¶®úõׇG]=¦Så" IO`ñâŃ $“¿ “'ÃÔª`é_?”³QBÜTuBD@D ]ô™.RÄM£–î ºs×®]xï½÷ðÖ[oaþüùNÊ4¦Å½á†Ð¥K\vÙeR3ÊνóMàÎ;]'£Þ½aÓRíõ×ÝÖHM4;wÅó×DÜá¨k׮ؽ{·çA©ÂQÆltDD@DÀ»üŽ¼Û µ\D@D@B#às8ª[·nhêì„ P¦Œ;ïøä“À}÷'ž˜ÝR'D@DT8*T¨jÔ¨!'0kl¡8í4Ø$P¶¬Ç;¤æ‹€ˆ€ˆ@V¬Àÿ³w'ðVÍëÇ¿ÍJÒ@Ñ ¤A…d¦TèFHI’›!Ã-¹‘áf W]C\QÆ¢•!„”!2çRº7J%¥yþÿž½ìÓ>çìsÎÞçìa­½?¿×k·÷^{ ¿ß{Î:{­g=\µ0í¹§ôí·R¹r̘!“í|ü”)SB÷]ö­®¶wùòåe¥ÒÎuwÆœájÉUäKjñö¶ÕLï×O.U”´ï¾Þ³•@KDÛ¸QzþyéðÃ¥ƒJÄYGÀ’ptÑEŒ„îÆ+@†£xŘ@ +V¬Ý5a €Ù"0{ölwᮎ;ÿäN@ѲNÀÊÑ,Z$wR7ë†Î€@ ƒvîÜ) ¨µ`Ú2ÙVƒ$€ûÕª›»ë‹jÚ4çg̺w—ªVõ2¹„Ä4@2Rà»ï¤Ž¥ $Ëì—‰ÁFö7š•H }ýõס}¹Ûn»¹±wT×®]uÖYg©Zµj¹“6(—J‹{û‚o¯Ÿ}VZºTêÖM5JªQ#q›ùeɶyá…‰['k ”@ÒŽ¥Ag‹%@†£b±± €€Ï~ýuJ—þ·¬üp›6>ï,ÝC@ ›6mÒ¼yóBw&`u¬"–%â´Órw”`£Ü¼Cà ÌŸ?ß]ùCG}tð“#¸ÿ~¯¤g­ZÒ A’Uû·Ü5H½õ–tàá©<#€ 9.GcÆH×_ïeŸ}á餓2g|;vìЇ~¨ÜÀ^zé%-_¾<4¸}\êÂK]9®Î;«C‡ªT©Ræ :•#±D0ãÆåߢ¥É;VêÝ;ÿg%Ò²¥W¦Íê³Ó²R€€£¬Üí‰4ŽëÉÚ@ü!ðË/{»“Ò}å²·pä]B/@’,ðÅ_hÛ¶m:òÈ#“¼%VŸn«|oçÝù]Mœ(—ž>Ý=bû €@ò>ûì³ÐÊ:ê¨äm„5'LÀn¼/ë®ZØwñ¼US¬ZÇÂ…TëH6+BH‰€Uœúí7©nÝÂ77w®WõÊ%ý U½²ïk.þ&ðmûöízï½÷BAF“'O–U°Ö¤IÝtÓM¡LF–‰²T©RkB`?W^饶ÌDñd#:î8¯ õëKöhÐÀ{®W/yi²š7÷¢Å2xVDŽ‚¸×|ÖgËpT¡Bêfúl¿Ð@’ üßÿ¹?È]kÕªdëai@‚"`åf¬Ù‰>Zf عK;ymF]ºdöX ðé§Ÿ†Èp俟…ÿýOúýw©uë]};áÉÑše7:è hŸ0 @ X9´¼lEtdDz¼Ín¹õVéÁ½OlþÁƒ¥*Uòμ÷o¼ñ†þñ(\.­Y³fêÓ§Î>ûl|ðÁÁP2{ì²N‡vü½÷J–êÊj…"ÎÞy'vAýøÛß${$ªÝq‡ôæ›Ò$j¬'’p4pà@­Zµ*‡î®»î’¥E£XÀ¾ZêµÒ¥Cƒ° GÕ«Wð€è: €¹쮋M›š…&p”Û†w €™+0{öìÐà8ÊÜ}™;5ã2YI—_žÂ3 ¹pT»vm—U ˆ´™KàË‘=ý´—Å¡Z5éûï½›ø}ÙQ:… €@1,‘U¸r94dHþ`#—ôG.Ѱî¹GúùgéØc¥G•¬BUÐÛW_}¥k¯½Ö•A}+Tí†nÐùçŸ¯æ– ‡–_`ËéðÃ%‹Æ¶ç'žž{Nºûn©W/¹ôP9×åó/œÄ)àJàiúté/Iâ†Xu’pôùçŸkÙ²e9F6lÈyÍ‹€ ¸èS—ç.'šÑ2pÐ}I·@¢ رMj¨rå6¹ôµQn;‰º@¶€e8:à€ø~ìÝSïí>0‚b¢b&¸ÀFWÃdÞ¼yîæð ¨Gà}±c‡ôÓO^`‘•D³ ¬V!ÄbÀìZZùò]G@ Zµ¼8‹Ù{ïü3 *¹@¡ŠY?.]r‰\Y±üóiŠ•K»Õ¥k=z´v¸?.¼ðBÝá²äÔ©S'HÃH}_í¡ž=½LFW_-•)ãEžÙPVýª«¤#R߯+®xÀ{p”zÿ€l1éGÅu;v¬Ö¬Y“³øåîLXy¾yäx¤í…¥p³ŒUá®#–á¨qãÆiëF@ Ñ¿Y~[ÕuikÿpÏ%Ú—õ!€øO`­Ëá¾`ÁõèÑãG €S`Μ9Ú¶m›Ž:ê¨b®ÅŠ+`7â»Sü²£E‹$»q?²|²4~¼´×^‘Sy €@pì˜×¨QîþŸrJî÷‘ïyDúì3©C/è(ò³ ½^èÿ´K_xÿý÷ËÎ/´oß^÷ÝwŸ;ì°  %}ý½å–ÜÛ¶è3ûcÊÒ_Y½½ýö“«O—{žd¿«__:óLéÅåNIM›&{‹¬?€¾ 8ï¾m,]º4‡ôÒK/%à(G#/,ãƒÕŒ¬Y3§”TË¡à €@†xŽvw—X¦# €™/`Ù‰íîCÊ©eæ¾þñGiÌÉU½wÕ™9FF…D°rjÖŽ>úèh3- .¾Kgœ!½þºWBÆ%O”ÙX{m»wÕži €d‚ÀÌ™ÒwJÓ¦y‹:vŒmTûï/Ù#¨ÍnZzÁEOš4IsçÎ £‰«cG]ºt ê° ï÷?H&È<ñ"ÅÊ•+|þ’~jÉX&O–Ú´‘®»NªWO:眒®5¾å-»’E’.Y” <¾ 8ÊÓOÞúE`åJ¯'­_¿ÞݲEÕ¬Ø6 @ X²dɪUkE†Œˆa € P¸ÀìÙ³C3yä‘…Ïȧ°%휨Ý9Û®] ‡@§@b XÀQéÒ¥ ¨-–^ñ*ë®8XÕ”Þ½¥{î‰^B¦xkf)@ü%ðæ›^ ÑÈý½!}¶Ô ¿ú˜èÞ,^¼XO>ùd(È諯¾ ­¾F®Ü%êÞ½»ûÎÙAeíLlTÕ¶­ô‡UEpÍ®wí*—*Z:é$)ZðÑêÕ’)YU§Nð–‹÷ß=÷ô"¹9F®FW§ÖþЊV§/ÞuÇ2ëÖ^€•Ûï®>ž7îX–cž¬ÈÐÿñY³ÿR?Ð<G^©zõê©ï [D@ I n­¹NIÚ«E@À_³fÍ ]%ݹ¿öK"zcçD'N”:u"Ø(ž¬‚%`GÍ›7×{쬎¼·#Gz^> º €@>;½êRwÝ%¹Ê­®:\°týõ^¿| dÀˆü¦‹®zÄe·™æÒ8Ùû½]°KŸ>}BAF'¸@šŒ 2ŠÜ-ZHù‹`ôý÷rQW^É3+{f×É-øÈjÅZ€‘¥¶çß÷ÖPµª´l™T©Räc]·®—Bëøã½LG¶m«Ç—ªvõÕR¯^Ò¨QÞ{ª¶Ëv!@ÀQ v“:™'àÈÊ©Y#Ñö]A(±ÀâÅÛCë¨_¿L‰×Å @‚€5kÖL•+WBwéc7Ü •*%Ù q M+V¬Ý…ñÅgÓ°S:VGªî1hP–å† €@¦ X’šsÏõ’ÍXÜÈ€Ò?þ!Y,H&¶U«ViôèÑé"‰t4eÊ”QçÎÕ¯_¿P&#{ŸUÍ27Yi±p»ñFiáB/ðèùç½:æö™ý!d?‡"5lè=,X)Z¤ðºby¶õ½ü²wGQªÿ¾µô]V£ý¡‡¤óÎóJ¼ ,~,=gž  à(Ãwp‡—'àˆ G f… €>X¶Ì]•sí€*ø 7t@ä üöÛo¡“‡ZjnZ 6»¤Œ ùså½÷¤7Þðζl¨¡ÑY@ ÄŸýy×÷ÑG]âu±‚üVª³É*…4j$YùN €™*ðí·ÒgH H]ä• µd6™Ö¶mÛÊf4~üxMžRÿï—_$;¯¹til}Ü}w©ys©J/k»» 5_{ñEÉ’{¸l÷ÊôóžùÏ@À XÀQ%Wïä ƒÂ# gåey Ø( ¸¬@ÀWO>éUɲÀ£L 6Z¾|¹n½õVWõ«¡Z·n­GyDµjÕÒwÞÊ‚üî»ïªG™l4gŽÜàäÒ7IÇ#YɰLÚ¹ÉøT£†tÁÞš-ËŽ’¡Èu’á(»-¶€#«ÉY½z¨d8Jã¾`Ó €IØwßGôË/Ó^{ý_Ò¶ÁŠ@ð‹À·–Þµ&Mšø¥KY×íÛ¥gŸ•fÌðJ Y0QaͲJX@Ñš5ÞM˜eóœÝ±$Ëtn™'n¾¹°5ñ ™;wîÔ¬Y³tøá‡»S™î\&­DV¢Ó‚cíÚRd«X1ò¯@ÈLÑ£¥+¤ý÷ÏŒñY–ãÿûßš8q¢¶lÙ¢ºuëjàÀêÕ«—ZfB-îÙ³¥ýö“jÖÌ¿ÃìK÷ÝwKÓ§{ŸzªÔ¾½\­89ˆüó3%·À?ÿ)uî,vXîé¼Ëj<§¤²Ú‚ÁÇ"`GV”´´—‹ G± 1 €@ÐìøVÃ"öi €d€e8*ïên5 NÚöv:^¦"Ërd¥Ò¦L‘»Ã´èîì¹§dÈfÁKcÆHG6x°´÷Þ‘ŸòÈ… º Ì5:ꨣ²cÀIåÈ‘ÒWHv¬²›ÿ‰ßJ"6«FH»€‹Y–UÙŠŒUq 3"ØÈ2Ý{ï½zýõ×CÎV2ÍNuA7VB-cÚ9çxeÒZ´ð‚‰, Èv¬»‹H—ìŽ\%«A~ðÁ3ì” Ä2BvZJ6ÅF‚#àE§¿ô4Ýpq”%ÃQºwÛGH†Ào¿ýæ’ùyÙü’±~Ö‰ €€Ÿ,ÃÑ@ˆí»Ùòˆ#¤ùóso𯕦M“,;Q‡Ò+¯äþüÕW% &*ª  õï/— _ºæš¢ææs@ 3þ÷¿ÿ…F9µâï_;æØ1å²Ë¼$vŒ"بøž,‰ ào;îM˜ WŠUêÖÍß}·wSÜ-G¸/¡'žx¢Þzë­P™4ËùžKaxš ɨ`# ,²4¿çŸï¥~øa/bÚʧ}õ•ô÷¿Kß}'O°Q¼?HÌ@Ãäò…3U«V­€˜Œ €@ð,àˆ GÁÛoô@ ~m.ºå‡~ œZütÅZbØ0éØc¥yó$ <ÊÛ,ÐÈÊÖXÖ¢³Î’,«„µG‘ºt‘n½Õ{_пv’ÜîÆµ’kwÝ%í¾{As2ÈlpÀQó¢jTf6C±Gg%;­ÂȈ^b€Ï>“š5+öêX@ß |þ¹tÞyÒÒ¥RÛ¶Þ ¾ïtüÊØüå/Ñgœ¡o¾ùÆe,¼ÂÅÚ|§çž{.€TÄâÁüØ25]|±ôÔSÒ’%’Ëz©'ž«!'-^,=ô\zç`Ž^#àS²>íÝò£ÀÖ­ÒêÕù2U©R…;aý¸¿è €@±/Þ¬ .swv”+Öò,„ €@~üñGmußõš6m¤n¶¯(µl)çÝ9m ‡&Íœ)|²—UÂe½×¤IrAaÒÕWG[b×4Ë<áÎkÇŽœJè»>ä EဣfDÉĽ×íº\çÎr&¥>}¼ëråøz·# €KÀª°ŽëÝèô «V­Òm·Ýæn`é*‰ítñ7ëÎ;ïtYp]Ülk.›³Kéœm£f¼¤T€ G)åøÆ,»‘µˆ’j–ሒ3 ÿ"€d†À'Ÿ¬u¹Ï¹«}4@2\ÀÊ©YkbÑ,´¤ X¶—¹>”¦¿°5lèYé5 ²¯áo¾)íµWaKíú¬4g{vað ²RÀŽêÕ«§=öØ#+Ç_ÜA¿ý¶tôÑ^¥‘áýL{W“å@ü*ðñÇ^pQÞþõî-9ØÈn&zàÔ¸qc—%÷µnÝÚeÖ­Ñ£GgN°‘ËÐ*‰–wçñÒ&À)¨´ÑpÃ*xu/;vÌéüï¿ÿî¾”SËá €@à¾ûnch µk»Ô4@2\`Á‚¡’á(ñ;zÎé…ò¯×2¼ÇÒöÞÛ+¯f™à?ø€¬ï±˜1 `v'¿• ¡œZì?ü!õë'Ùi_+Ï9uªt啱/Ïœ €A`Ñ"©G©Méšk¤õëƒÐë¢ûøÛo¿i˜«ßm™¯viq«V­ªçŸ^ï¿ÿ¾ZµjUô ‚4‡¥¡:þxé§Ÿ‚ÔkúŠ@F PR-£wo‚g·Rþë_¹VjŽößÿ\Óxƒ €@*TøÝuÿ 5l¸-Èàï €Ä$@†£˜˜âšióféŽ;¤»î’\ruê$í¾{\«È™Ù–;ÿüœ·¼@ˆA`‘»š¸aÃŽb°²Y¦O—.ºHZ¶L:ñDiÔ(*ÄHÇl €XëÚÛw4—üGö}­kWéÞ{‹ÿ=Í/ÃþØ¥jzì±Ç\ îIn\›]FܽÜ8ïpÁT×h·ÝvóK7Û«?¾nT»vb×ËÚ@ Ø)8zÛåeÝÛnÓ+¢­ÏVúÚk¯©‚eØ)F;óÌ3‹±‹%°cÇýán!ÃQQR|Ž $FºîžåNNO R·é+ €Å° Gv÷c͈ÒÙÅZ iÅ ¹´õr'|%«Hn7’Žü“ØìZ@ h_ýu¨Ëd8ŠmÏ•)# %=ñ„tÉ%±-Ã\ €E`Æ /°ÖâØw4—HíÛ¥÷ùûi×eŸripGŽ©¯¾ú*4CÛ¶muÙe—鬳ÎRùòåó/”î)Ÿ~*}ÿ½Ô½»\‹ßKÃhë²ú¯eSâPü~³$.òÿ÷Ýw_±Ho»í¶b-g pTlºB\½zµ,è¨zõê…ÎLJ €IÀ²÷Y«Q£FºM_@(–€e8jÒ¤I±–e!Oà‹/¼;eŸyFÚ²E.K¢WüòË9ÊÏ ÿýï¡Íp›¾e5Z¼XÚcØæg.@‚ °q£týõÒCI•+ËèH—^*•.„ÞçïãÂ… õàƒj¬+)¶Ö¥l²d Pß¾}C¥Ôò/áƒ)®Ô[h'Œc5o½4S?.w\ñ:g_¾-aIëÖÅ[ž¥@ ))8JÊ(XiZ~ÿÝJΈ GiÑg£ €É°š×Ö¨M–0ëEð‹À:—†|ùòå®|Š»ÒH‹[à7¤»ï–Þß[´];骫¤3ÎîIì¸Xð¡Gï»NgÉÎ;/÷<åöà €@°, ÎHîþ¹ä?zòI©Aƒ`ŽéwÞq¥àдiÓBI Z¶l 4êÙ³§*V¬èÏAYp‘¥û8P²síù‹tÌ1^»6mäÒ1y_¦­y<Í• 5ŽâQc^’.Ð8Τ»°Â ¸ ³ €F pD†£Àì2:Š PLËnd­iÓ¦Å\Cv.æ2Øë¢‹¤N¤O>ñNdÏ™#½÷žÔµ+ÁFÙùSÁ¨@ÀOpT»víPÉP?õ+}Y³Fê×O:üpÉ2ðÙ±Œ† €@¦ lÝ* ä%À±jVtçÝwƒlôâ‹/ê ƒR‡BÁFg¸;[ÞuƒùÂE_ä¾ú6ØÈ"›-Êë⋽òi– ø­·¤Áƒ¥¹s%»SçÑG¥æÍ¥—_ŽïGpæLï ·/Ñ@À7ùfW¯#d8 Þ>£Ç €… XªÝgŸý«›©7Ž §âS@ X°`Ah”T‹ogZx»YÓŽ~øÁ»[¶U«øÖÁÜ €Éøæ›oÜ5,w‹–#Pª”4y²tüñÒGIñ&ÈY/@ð±€=ÿ¼tè¡ÒçŸK×\ÌBž~úi}öÙZºt©Ã5²rj“ݼ}ûö>Öw]³à"ûrlAýûKîo2¹LL9ÍʹϘ!=ñ„´aƒtæ™R·nÒêÕ9³úÂ2µh!í¹g¡³ñ!¤V é%Õ^zé¥PŠ·Ô‹­¥B€ G©Pf €©X¶LZ²äP•*ÕÌ}oá‹K*íÙ €@êÈpT<ó¤zõ¤=Š·“öÛ/ϼE@ ƒ*U’¦O—êÔ‘Ê&ý xrà,°È2íçÚ¹(áºuë&gCÉXk™2^´×cyi£mâ /¹D:ýtéÊ+½ºwáÌGÑæO³”U.+´\xÏ à ¤ÿº­Zµª/šŠNlÙ²E«V­ =lÜuÜ­ŒýrM`Û´i“Ö¸¸Væ¥lš–d8JàŽeU €€O²íØfßY¬í¾ûïÞ þEÈ8l;¶¶-ਔ;Ù׸qãÂfËú϶mË}²Ú¾Šl”õ? à;dßütN²0|+§f-›3­\)Y6¾›n’;ÎïÒ"Øh—¯@ 8ß‚³¯ÒÑÓï¿÷Ê¥E^Š­_?=IÌ6§»h©ž.#ÐÞ{ï­·ß~Û?ÁFvÒܾ7hPø@-cQ¬_–kÕ’ž{N.kIli¨,»‘µÖ­½gþEß$=àÈ7#MRG~ýõW½ú꫚:uª¾þúë\[)W®œûÝÛ@ 6Ôi§¦“O>9×ç±¾ùðÃ]ºöqúî»ï´bÅŠÐbvRØ8mÚ´ ¥Õ;ì°Ãb]]Âæ#ÃQÂ(Y à+l>¶…ŽöÜs­¯ö A(™@6Û “³’jv·d%» ”–O`óféŽ;¤—_–>ýTªX1ß,L@Ò*ìã›_ÏI†žÍGv½Î Ü|³W™äˆ#äÎG¦Åg €€?8¾ùs¿ø©W;wJÇ{ÁµƒyÏ~ê_qú2Ó•!ëÚµ«*W®ì²4MW£Fгšø—Ù¾Ý[&2j+¼–9s¤aüÀ WâM'†?‰þ쮋ÇÝJ—Žm+Ófí¸ã¼gþEßpT‚]ñúë¯ëÖ[oÕüu-[]±P ²Ç›o¾ :²ùcÍú´dÉ]ýõ®Î¨+4š§ítGÓ•îv+YgO.E, @ ðÛ Þ…?ÿü³Ö®]«&Mšß| Ÿ`õWÿñ¹ KW_-Ýy§]„NøfºÂÿüG²Òo%”••!(_ýðÃ.mùŠõX»Å#ÍJ—mÛ¶+óAݺu]ÙʉªU«V®­æò¯ŸíjZ¾ð 䊈Z4kV"í•W^ Õâ̵ÀŸoìÀ>ùk“Ê•+§±cǺtî.Ÿ{DkÓ¦Î9ç—Åîœà$«­>iÒ$õèÑ#bÎä¼´ GÕªUKÎÊY+ €@J8¶yÜ‹YÍê_Üݰ5RêÏÆ@/À±­pS»‹Ò޼ó–—\âku÷Ñ@_ $óø”s’í åË—‡nÒlÞ¼yA³dÌtw¨:u’»!Uêß_1BîÔŒA,àø–…;=Æ!oÙ"=ñ„—Ñ/HǺɓ'ë²Ë.sUÉVꬳÎÒ?ÿùÏP•»öm +ìÙ¿üò‹}ôÑP…œIŠ?Ûš5ÒàÁ’K¢!WÉGíÚ]©\ræLok.1 ü'Ö€£uî6ŒÏ\é™îÅ€òeÊyê©§d|JÚÂ'RKº[Þ²ý÷¿ÿÍY•¥èµ4yƒrfp/¬Ô™•Q³ ¡p>|xÔ€£-îÈ9jÔ¨ðl¡ç;]tiÞ`£ð ìdÙ–Î=÷Üð¤P¤l*Ž,ÃG9ì¼@+À±m×®[¾Ü2-UõêÕwMä €@à8¶½ËÂ7¹d{†#»/È‚ž|Rî{½\Æâ¢í˜H—@2oA:'Y¿•S³–éGvî_þ"͛畓 B†‡‚öÓ@àøÆÏAAvÌs±:úøc©R%©wï‚æôÏtKÖÐßEÛõí5j„ž{Zɲ?Û ––0]mÏ=¥©S¥Fä.ʧ«ño×~*V”»Xÿ²,IHK½Å‹ëºë® Õ¡ìç m>ýôÓÚºuk¾Á†3åû ¬~fd³èÔzõêENŠúúª«® •E hwÜØA'o³ÌGín:tÐgœ~õÙ‚‘"kzÎsß6—,YuÞDN´þsA6‘¢¬ HÇ6ÏÝî–ùýw‹Å^ú2˜ž½ÁV@!À±­hE 8*_¾¼êׯ_ôÌ<ÇWxÁF;KwÜ‘Áeh É<¾éœdA;3Ž–.•\ÒûP°‘Kˆr2í/¦#€aŽoa ž#\±q„ldÀÎ??òS¾¶¬F-Z´uíÚU_ýµ"ƒ|ÑëV­‚ldh.”^|ÑJù‚N €@n”mwõï¾ûn—îµS¨¤˜½Of«P¡‚]Ní›o¾ÉÕåŽ;æz_ЛÝ\ýË8 ×Çy×e~ôÑG¹æ9餓r½/èMëHæñ-Hç$ ÚEÙpd‰]ØÅO@IDAT ,!ïÈ‘ÒÀI0–Ç·`í¯TôÖÅíèøã¥U«¤ñãå*½È}wMÅ–ã߯Ž;\,Ì‹.8êuëÖM›7ov}/ >*¬:Nü[Êð%6n”+áãÕ‹Í;Ô† ½Z²y§ó|!²€£õë×˲YY±âU´tiE4»CÓRÕM˜0A³gÏ•;+b‘¸>¶ZšáfåÄö¶:—1¶¼wŽ.µ[Rò´Y³fåL)劑¶‹±~fd†#[A²Ž,Íò† Èp”³·xW€c›·ïv–)©ÜŸfzŽxÛ ÿIضm›~øá5iÒ¤ð3øS+?3t¨tÜqr7DIî~% à{dß‚rN²°dG–=“/îYõ“™3¥>} “à3@ Xß‚µ¿’ÝÛaäîÝ¥*U¤>zõJö‹·~«Üc×¼­”kw×áùóçë —B×þéå×No¨©Yê·ß¤sΑz(5Ûc+ 0”Ý¿wõÕWëý÷ßÚñ½öÚËeA+: Ú›o¾ZÞNŒ†o¿ý¶"ÿ±@˼c‘¤Éh‘ÛŠ÷Ëë2/uBN·ò Ù˜~³_¨¶C9$æ |°+_YQ-Ôµï¿ÿþϵ$ç)\΂®h €ÁàØæí¿Ò. »^½%®,邘¿ÁÞóôÈ\Žm…ï[ûîiAGÙpôÀÒ-·H®:¹»YGÚ}÷½øð‹@²ŽoA:'Yؾ° |vÑ/Ó›_3wy‰ªV­ª›o¾Ùõ}@\I*’²ovî”þøC²”ˆAkuëz5ô¦N•;aA â í?ú›Õ) 8zÞ¥@‹lÔ¶m[õèÑC'œp‚K]ž¿+–á'o³ {„K¥Y Ó½.—Þ³Ï>›3«e7²õÝtÓM9ÓõbôèÑÚi¿°]«T©R̫ݴi“ò¦…lÖ¬Y®å¿üòË\ïã9ùk[ûí·Ÿ,-¾5‹¬ýÃTªXpZ8àÈî¢!€[€c›·ÿ¬:i÷î÷ëþûßpG{§Ò{@ Ë8¶þðí·ß†fhÚ´iá3fà§ORÑ£Än£Kïî Kmu≉]7kC¤ äòIð¦Ö¹£Ä]Q¾ 2$lTÒÍU®\Y·ß~»N;í´Ð/ùp™²'Ÿ|2tGK×®]Kº‰\Ëç Êõa!o,(Êêv†›e7Ê ™ÝÈæ³¨ØxÚžyΔÚúòn#–õ­^½:ôýË+ïšo™od³,RÖÈp©Âk¢€g¾ûî»9]·šË´™M-Žm¶Ÿ×¬YãJ¦xÇ6Û¿§Ÿ~º«ý»øwøXL@m6ý`¬d®À» ªµõ‘ßËÒ×+ÿn9hÇ6ÛŸ–I7òïËKÀQ6f83FúÛßä2Kï¼#í»¯é,`eÿ÷ìÂÝÚµk ž™OB±ßürNrË–-¡ïãá}l8æ˜câ 8jÑ¢EFìy»žè’(è ƒ¤×_'Ø(#v*ƒ@ Å.° ü{Ï~ó½­¨<“ƒt|³®Û5·È}}Àpôç>=ÿ|»IJú׿äJ“åÙÑi~kAb7Üpƒ¬’]+µ £[\}î¤'c0 KÏkwÉØÃ®õ~¸÷E »€5W¿-÷£fMËáe8J³[±7ðÁÞBp䂺hÁXî" ÃǶõëׇÎ_w4ô¼(¤EÞ‘b9ãŒ3läèRîõÔĉC“ìØJ­]cùÒÓÐì¢õc=æ~'æþ¥ØÅ¥„ëСC¾åýrŸ7cQ¾òLÈ;Þ»“òÌ^à[+ÍÖ¨Q£PWA3‘ᨠ¦#€@Ð,(ÕVÃí w6¯bÅŠá·<çê±Íös:uríëúhÙÃÚÂ… Õ§OŸÂàÓ@ ”Nfïþùg}úé§¹6qÁäzŸè7 ÈUŠÌžìT7KëÜ£G|ÁFM›6Õ Aƒ¢v'ï—ûx3å­šÌÔ›d8Šº ™ˆd´@¦Û®ºJ®ôЉîw‡ @ +2ýØVÐN´ GöÝ4›ÚƒÊ¥¿'Ø(›ö9cE ›â=¾éœdAûÕŽìfÌtgº/¨Å™^«ÁFÅqcÈ\l<¾eÚÞt•S]i¥Ü£rù|lôŽK‡ÛµkWYªû]ЋݜlAî/½ôRꂌÇî–ÉÆ`#»Y{ùeï™@À÷I 8úÂràE´V­Z…~9GLJøK Ò±ƒA¸Yé€ÿüç?á·I¶rdwÜqG(‹Ó¼yórmïÔSOÕsÏ=§¼¥ÏÂ3Y¹¹ÈféùâiVã<²åÍxùYI_“ᨤ‚,G ŽmVEÏ.DþþûQçG“ž"€ÅȆc[A8V~ÈnjÒ¤IA³dätûºMLqFîZ…Å=¾éœdÄps½´€£æÍ›çš¤7óçKC‡©ÇôH@6ßR§œü-͘á%¬ñ[’'«–cÕj¬,«U§™2eŠN?ýtMŸ>]³gÏVÛ¶m“Ãv ´iã}yw×ÓCÁG“'ïúŒW àK¤–T[¹re®Ay䑹Þ'ë•‹lv@8î¸ã"'%üõöíÛC5<­|Z8'¼Ksýõ×ç „ ùœ7}¼uè7[qÌ¢d8Š€æ% ¡Ùtls×]]FDiëÖ)©–¡?Ï 0l:¶´Ç-»‘µLÏp4i’\Ù%©R¥‚$˜ŽdŽ@IoA:'m¯ýöÛo²óÐ;wŽö±ï§M›&{®—ñÁUlqAÁ¾ï2DR"íÇ·” §h#V6í²ËäJ§J–ÁÏÍ~¾tw Þ~ûíZ½zµìšêµ×^«¿ÿýïÚÿýßEK1q¢4a‚\Í{©\¹Äo#ÖX¦Œ\Ä—ôä“’Ed[ |-Ô€£+Väü¾ûî›ë}²Þ4lØ0תó>åú0o,ãu×]§ äZ›ÝÔ³gO]sÍ5f5Š\`¯½öŠ|«xŽ6mÚ”ky tJV U%3¨)Y}g½ €E d۱͒ ^uÕF=ðÀ›.ûAÝ¢˜@ pÙvl+h…Ž29ÃÑÃKýû{'´}´ ¦#€™!ˆã[ÎIFÛk–ÝÈZ3ÝwŸÜye¹‹œÒ«¯lmÿ2 ²S€ã[fí÷Þ½¥¥K¥K/•ê×OÿØ>ùäõë×OsçÎ  uiÏ;ïH“@RŽò^°³¬8ñ´Z.Ý€=âmVŠ,ldËnÞ¼9ÞU9¿e/Š 6²Ÿþ.gû%—\¢òV—¥­fž³¡sæÌ‰y-VN-2@éÐC DŽyqÎhû2ïþsÌŽ à3l?¶…Žb pöÙî£; €Q²ýØ…$T ¼nݺÉImƒ)žænRuYˆS¼Q6‡¤X ÑÇ· “ŒFmG•+WV½zõ¢}ì«i/½ä%6XµÊ+¥v×]RéÒ¾ê"AÒ&Àñ-mô ßð€ÒH£G§ÿ8g7ÝØµÛ>úÈ%ªíb€žÕ9眓ð1‡Vh×£­^êwJë×KVlØ0‰4†ñ{ydü˰¤E ©_gò^°‹ ˆIæhà ÃÛHt&ž§žzJÓ§O¯>”ég„ ¡zŸÅ 6²•Y$mä|;®·R Í‚“"ƒ¬N:餖*þ,d8*¾K"€~àØ&…£ ¨õãO(}BâàØÝì»ï¾såÆšFÿЧSwìðNTÿ™Äا½¤[ €@j’q| Ò9ÉhÊpÔÌ¥¸³ ~~mkÖH\ u–×C <:4ýaýêE¿@ û8¾eÎ>¿öZiÄiÑ"ÉJˆ¦«Ù5Ó{ï½W-[¶ÔÌ™3]e³+õÍ7ß$.ØÈ­3”¢ÐUÝ‘U豤ö¸ùfÉÝä£7Þ^~™`£tý°]H™@RŽöÝwß\ùðÃs½OÖ›¯¿þ:תó>åú0Î7‹Üò«±ùg³ºž£F’e*i+íng9ýôÓsV³ÃUýØrëÆÐÞ{ï½\sp ¹Þ'úqA6Ѫ¬HÇ6©G+¡}th$òï†ôìQ¶Š À±-úÏ€Ýd“–6>úfK<Õ}åÖ¥—J]»z7‰æ]¡e‰HBbã¼›á= vdß‚tN2ïNX½zµ–/_®æÍ›çýÈ7ïgÏ–>Xzúi©sg髯¤3ÏôM÷è vŽoiß ëÀu×y }Ú¶•^{Í«&–°•DZ"»N|ì±Çê:סúõë»ê\høðá.>(5L«T‘Ž?^:ÚSnÕJîïùßÿ–æÍ“N>9Ž3+ \¤µiÓ&—Œ¥«ûÃrè%¹Í˜1#×<ðÀ\ïKòæeºuëÖœUÜéÒârÈ!9ïKú¢‹¥×‹hÌTT³/Ö“&MÊ™­AƒÚÿýsÞ'ú… Þ¶m[(³S¢×Íú@R/À±MúϤU«*†ð 8JýÏ [D-À±-ºè‚ Bø=Ãц ÒÆ»Æà²ß«wo¸vqS9ͲYàð1Çä^&g^ €$Ìã[ÎIFÛ•óçÏMösÀQ:R™2ÒOH¯¾*Õªm$LC²W€ã[ð÷½e£íÓG.£Ôºµ4uª´ûî©—]¿2dˆ;ì0Ye˜ë¯¿^_|ñ…ë“ëT¢ÛAIÓ¦Io¾)½ý¶d‰!ìa)ž¬Ö7 Ȥí·ß~®,eÃÊ-.wÞË£—ÄfåÔÞ}÷Ý\[Hää5 Éý³ÙØ:uê~›g Žjܸqκæ¹(؉'æ¼Ïûbݺu¡RnìŒìŸ­‡mMb£äLqY5 l?¶Ù…J»p¹Ûn.=‚kdðKÃ!›D,íǶ‚8­l·5?g8Ú´I²ûpN=U²×Öì\íØ±ÒàÁr'½Hí†Qk–€ØNØùc—€˜†d´@2oA8'mçZ95k~8²"v¶Z €@~ŽoùM‚4eýzéŒ3¤Ç—N9Å«$V¹rêGðé§ŸêÈ#Ô­·Þ*#þw‡éÝwßíÎùî–úΰE@ ‹Ê&{¬§º³„=ôPÎf,x¦³Ëk53“цºâ×ëíèög«V­šKYërÖ& YmÏ%K–䬩–»eôèÑ9ïã}ѱcGYPVÞÖÇ…80g²EãZ­ÑsÏ=WeËîÚe–.¸ÿþŠ,!רQ#Wü‚œe“ñÂÊ©Y3[ €@°8¶I¿ü"—¹Oîë^¸FÀQ°¦é= À±­àŸp†#¿Y2áîݽ›C/¿<úý[n‘»©IºøbÉ*ßv›ÜÉd©E ɲÖÓ@LHÅñÍïç$£í_s±Ö¬Y³h§eš÷ý2÷¦ItÛƒw €@X€ã[X"˜Ï+VH§&}þ¹÷=mäH;ÇšÚ±X˜o¼QV1Æ®¡Þæ¾(Þ|óÍîÆ² ¥vO°5ÈV¤ÿڿ袋ôÌ3ÏÈ2Y³À™¾}û†²öDf?Jİí¼òÊ+¹VeÛ/c9kÐ.\˜k-Ÿ|ò‰ìQÜfãpt† ¶z¢S¦L ­z‡K½ð¯ýKãÆ •o³hÜÙ®ø÷O?ý”kÓv ½ýöÛ“~%ÃQ.vÞ €àØ&-]Þ…KCu¼Ë—/žÀ3 €@8¶¼Ó¾ÿþûÐ Øúõëq׋5fŒ´s§TªTÁë°ÓvïËŽº›6AI Þ Ÿ €>HÕñÍÏç$£ísÙ×Õ,óCƒµk¥“O–»QÔ+-­¿LCÈ-Àñ-·GPÞ}ü±w¬ûã¯üuïÞ©í¹• ¿Ü¥Å}çwÜM+{ëÉ'ŸLNõ—_ô¾tR–-µ;˜­!€@ Üé¼ä·³Ï>[V>,²YÆ£¿ýío¡@¤âþAa™vFŒ‘µ¹~{=hÐ YÀS¢ZÞŒB‰Zo´õì¾ûî¡ ª+®¸Böº°vôÑGëé§Ÿv)å]Nù42¥™M €)àØ¶+àhãÆïT£Fɳ@d pl+XÖlêYz 7 4²À£¢ZÓ¦Þ‰m+ÁFC²A UÇ7?Ÿ“Œ¶ŸÍ%Zùhó&{š;U*Ùíª¸ÈÊ€Ò@ŠàøV´‘ßæp…lt饒•Äž:UJe°‘%j°òi‡rˆf̘ºÎl¥Ã/¸à‚Ä3Y*]ûÂy啉_7kD2H éŽÌÊÒÚÞwß}î ÓÛÕñt…<#ÚsÏ='{´nÝ:8d‰æÍ›+o9++ö믿jÙ²eZ¾|¹>ûì3Mžúè£|=úØåß³‡5ûRkåÐ,;Ñ{졵.í/¿ü¢mÛ¶å[.Ú„ÓN;ÍÝE’9·‘TªTÉÑv=¢7ÕÓÈp”jq¶‡dž€ŸŽm^µÒîïo\†#j|gÞO#BR#à§c[´‡ïöCûjïnJÕ¿ÿ-—þ^úî;¹¢õši €éðû±ÍJ…îtu8ë[¤OÁF>Ùt(DÀïÇ·Bºî›LÑ)T;Î[ÒŠ›]úÀ~ø!tͰaÃtÞyç…®%Ç ²y³T¡B̳»h&ÉêÅ=ô\íÖØ—cN@ bHTž8 "zâ‰'tíµ×ªŒ…ÀÐ,›ÑêÕ«µÔ]œ?~è9–`£²eˆʨÙÁf7êi [òÉd8*¹!k@ð€Õ¨±Óuh3%Õü³[è  €@‚ÂGé.©æë„¼`£ãŽó2Al”àÍê@,ÛÒLk´ï¾›%Ø @ |øá‡:ꨣtî¹çÊ!ÜsÏ= —O³Ä1µ9s¤~ý¤š5¥fÍ$Ë\TT³ÔM< Ñ,·ñ¢ææs@ ëbüœ8§R¥J©OŸ>š4i’:tè {_ÒfëèØ±£^|ñEþù%]Ë!`v3¯Zµjsò1 €þp7źïœ^‰ÖêÕ«û¿Ãô@b¤û¢¬uù½÷¤V­ä²K×\#½ÿ¾—¡¾Ãa@´xñâB:ŽÜý²ºà¹óÛñ£ˆ ù^(“šq®_¿^ýû÷•L7ožûîx¾ÿþ{ 80¶dTdµ»;L:üp¹ò;v·©ôÍ7Òw=èÊ•Ò?þ!¹D4@ÂÒö›²E‹zøá‡µhÑ"=õÔSîDãû¡LF…w7÷§u\íÌ6mÚ¨wïÞjذaîy—4Ëp´çž{Æ—®0i½aÅ €_Àeå•eZ8òÈ ¡•Ô°/Ÿ4@2PÀÊÎXKÇEYÛîƒzAF®b¸»YHêÖͦÒ@(¾@:ƒi/¿\zæ鬳¤¶m‹?–D@ÀïƒË]Ç•\.¾8¹½ýàƒtÑE…ʧµoß^£GŽýúïo¿I×_ï 7¸s½®êŽ.»LºôR/øèˆ#¤#¼ŒGûï} Û·ïªýìÁFïS@À ¤-à(,Õ AÝzë­¡·+V¬Ð¬Y³B)ñ¬¤Ú…jÏVbͲé„5r”ÑR/`ŽÈ‘zw¶ˆ xËkwè”)³Ll7»p”xeÖˆ àðEÙT—TÛ¼Ù;Ÿ;v¬Ô¤‰ôÊ+ÒúA„> €] |lKu0íu×I#GÊeÜ—&N´ï“A—¤ÿ €D°dA– È’YÐQ²ÚÆuã7ºx ªX±bèÙ²Å\%çÍ7å"•¤Ÿ–Ž=VúÛߤsΑ쎗p»ï>¯¾·ÛŽž}6<5÷ósÏI?þ( ’{ÙÜsñ@ B íG}Q­Zµtú駇‘Óyí/ËpÄYízƒ P<÷ýU£FIãÆ}úòL@mñY @ÀÿvQ¶råÊ)-mY-“ѧŸJ§&M˜ —-×ÿVô@ ác[µjÕRÖá;ï”î½WjÝZše›fC €¤\À¾¿Ù÷9 ®ŒÝIdGfΜªdóÝwß…ªÚŒ7Np@ì›xüq©o_/£ÑøñR¯^Ñ—u“Ô¥‹dAE–£yóüó *÷ÅYúûßóÆ@¨¥£Ne"…á¨>B¤Ào–r×5j¹ûè4 €@ VR­~ýú1Ì™˜Y,?Ü;9}ÓMÒ«¯l”YÖ‚ °€£TÛ~Xºùf©U+iêÔä]x g@ü P¯žT»vâ{²ÞÕh»êª«tüñÇkéÒ¥6l˜Þÿýø‚¬[.‘E(hîÜ‚ƒÂÝÿ÷¿¥éÓ£M›&}ù¥¼”Â`æp×xF‚*à« GAE̦~owõK×®]«TÞ9”M¾Œ@ =Lk Géñg« €É°€£víÚ%CnÁUOW‹ÒƒJÝ»§l³l@ ‹,਽e+HA³„ W\ᕵª-dìK:›@H‹À¯¿J{ïÜM¿é¦}]V¢Å‹»¬­5fÌW‚»Iñ6ºï¾^ÚÁX–nÔH²G´v÷Ý^êÂk®‰ö)Ó@  ÃQ0LŽ.`åÔvîÜÉÙè 6€ €@TÛ°¡Wu¬€YJ4ÙÎÁ^pÁ:å”Sd7€>ìÒ~øá‡Å6*Qo"þøc¹ŽH矟œtN›â% id8Ê´=šäñXÀ‘52%šÕ#€¤TÀ¾ì–*UŠã[JÕÙ €@ª,»‘µd^”uñL*_^*ËY†TíV¶ƒdµ€e7²–Ìc[øÚk¥uë¤I“¤ºuÃSyF@ ³ž^:ï<©J/è(Ñ£›8qb¨„š ŸîÊ =úè£î¸ê“«e7*írt\w]¢‡Íú@Œ ÃQÆïâÄ’3‰õdm €þ°ã[ÕªUÝ÷Jþ4òÇ¡ €‰HöEÙŸ–Ú¶•ú÷Od¯Y € $ûØÞò»ïzYºt‘ËÆžÊ3 €™%0j”tî¹RÍš^¢Ÿ#LÜø¶lÙ¢ž={ªW¯^¡>ŸyæM™2%ö`#Wu%©í«¯¤©S¥nÝäR-%uS¬ÈD®ªeâ^Mâ˜Èp”D\V 6ËpT£F´mŸ #€ LðEÙd”T[¸P:ê(éóÏ¥}÷Mæ(X7 €»ÂǶúõë„W®j›8@zà$¬œU"€ à¡C¥¾}½ãUkÖ,q²ò§]»vÕsÏ=§³Î:KóçÏż«ñvÈ!Òòå1/÷Œß~ke]¤ë¯{Q@p â@@ 2ţż €A°ãGAÙ[ô@ ^ðEÙd”± øK&H·ÝoϘ@â $óØÙ£SO•ì:dƒ‘Sy €@fÜ{¯tà ҡ‡J}$%2Žw«Gzª;¾þúëºôÒKõ¼«ÙV½zõØàþ÷?é’K¼ô‚V"ÜÞ'«Yf£eˤ#ŽHÖX/ Ñe3zt .ád8J8)+Dð€e8:è ƒ|к€ €@â–¸´¥J•R:u¾òÝv“fÌHøjY! €… ,^¼8T;Ƕ¼¦òv^Þ#€d‚€‹ÿ %õ±Bï½'í¹gâFe×;uê¤O?ýTW]u•† úNZè¶m“&O–yÄëÍ|â‰ÒرÒ~ûºh‰?´/¶4@b pT,¶ì]ˆ GÙ»ï9 ©›6mÒ† Èp”©;˜q!€Ȳ@ÔªUK*T@@Œ°c[íÚµU¶,§·3b‡2@” X6£ .;–JS§&6ØhåÊ•êØ±£æÎ«AƒiÈ!…ÍÊ¥%=þ¸W:­|y©W/éòË¥ãŽ+|Y>EH»%ÕÒ¾ ‚Õ2kÑ[@¢¦-Úˆ9@‚-`eUNí¥—äîP•vî ¶ ½G¶@"my%fΔƌáX—×…÷ €™!`¥B»t‘,®Ç‚¬Lv¢Ú2Wš¬]»v¡`£¡C‡ldeÒ.¼Ð«ãvûíR¹rÒwJK—JãÇl”¨Âz@$ p”dàL[=e3m2@+§f­F` € qÛ\Zú_~ù%!G¯¾*õì)Yêý+2ŽŠ!€D`óæÍ²ì õë×Ox·o—úõó’*¸x] €%°e‹túéÒH/¼ µl™¸áÍ›7OmÚ´Ñ‚ ôðÃëºë®‹¾òÏ>“Î[ªVMš1CÚgŸ­Ž…@(¶À’%K\¦½ ¦ÍÛ‰G•¾üR®Œ—p!ïç¼G@ È–ÕèÞ{%w©Ï•=KÜHžrCý\Ä®Ýð2nÜ8W®í‚ü+·»VþúWï e©R^š% 0:ê¨üó2@ 0fWù££–ᨚa¦!€ !dïËÉ0@¢ XÉk%)©ööÛR·nR•*Ò;ïHuSLD@ %‹/m§$Ƕ‚:Úµ«ôÍ7^‚…‚æa: €A°rj‰j–upÀ€9rdè&—I“&é裎¾zË\ôóÏrÑHÒ 7HÍšEŸ© € à(P»+ýµ G¥?Ð@Ä á(q–¬ @À–ÂZq/ʾöštÎ9RÅŠÒôé^Ö{ÿ’!€d“@"‚i òª[Wzè¡‚>e: €„-Z¤îÝ»ëóÏ?wÙ’:j„ Úk¯½Âç.]Zš;W*W.ÿgLA¬€ûíNC vËQ½zõØ`N@|.ÎpT£F Ÿ÷”î!€ ¿@ø¢l¼%ÕÞ}WjÛVêÜÙ;üÖ[Ò¡‡Æ¿}–@@ Ñác[qƒiÝÖ‡ €€Ÿ¬$ö·ß&¶‡Ó¦MÓa‡¦ÿþ÷¿ºõÖ[õº«Á]h°Qxó…%xF2F€€£ŒÙ•©ŽRãÌV@R'ÎpD@mêÌÙ €@êâ½(ûÞ{RûöÒ‰'Jÿùté¥Ò—_JG‘º>³%@ ˆ÷ØVøº¤»î*l>C@ ¸K—JgŸ-—HÚ¶­äãØ±c‡n¹å~úé*í2M:U·ß~{èuÉ×Î@‚(@Iµ îµ4õyãÆÚ´iŽÒäÏf@’#8"ÃQr|Y+ €@z¬¤Z… T³fÍ";òâ‹r)ñ¥²îLÁ%—HƒI ¹3 € R 8ªR¥ŠªV­Z¢íºÕ„‚l/–:tŽ<²D«ca@|'Ы—ä —èÉ'½ïy%é C=÷Üs]©íéî˜y¤&Mš¤úõë—d•,‹ eÀNLÕ,»‘µjÕª¥j“l@¤ XIµ²îʪ°¦!€ ivQÖÊ©•*UªÈ¡¹›TuõÕÒWHûï_äìÌ€ €@Z»¡’–S‹ 6=š`£´ìH6Š tk¯õ‚kí»^IÚ¬Y³ÜÍ)Ýeß/ûôé£#F„nlɵNK‘[±¢Ô²e®É¼AÈlJªeöþMèè¶nݪÃ?\5JèzY €é°»s(§–Î=À¶@’)8Ê»;¥åËsOu‰4lÁF¹Ux‡ à7ËÞW’€#·xNf# 6êÝÛo#¤? €$FàŒ3äJž•l]£FÒñǯ_ýUcÇŽÕÈ‘#óÍ™#rŠÔ¹³´eKÉ6ÈÒ € ÃQ vWz;k©gÏžÞN°u@,`G”SK0*«Cð…Àºuë´zõê|eÿ÷?©o_¹ÆÒܹr'‹}Ñ]: €@‘+W®Ô¦M›òÛŠ\ðÏìØgåÓ¬ŒÚOl«ó!€dŸ€oûõë§qãÆ©aÆzÑÕà>ôÐCóC|õ•Ô±£hôÔSRùòùça  €@Æ á(cw-C@X¬¤Žb‘b@  Xv#k‘Y ÜuZq„4s¦wNxûö Šþ"€d³@´c[¬k×J:Iß~+=ü°tÑE±.É| €G`Ù²’÷ÕÊ—wÜq¡`£ÓN;-”Œ j°Ñ‚^$¯»ÙE“'{)K¾yÖ€  Ž´³è* €$^ÀŽÈp”xWÖˆ ~ðEÙzõêåt¦fMé®»¤ÿüG1BªT)ç#^ € à{ð±Í2±ÇÓ¬ºK×®ÒçŸ{¥e.»,ž¥™@`<ø Ô¼¹ôñÇÅïï»ï¾ënR9B_|ñ…¬)S¦¨ZµjùWøÃÒI'Iîܪž^:ùäüó0@ ã(©–ñ»˜"€ €@AVjf‹;óLÀQABLG²@ø¢ld†#Ï€A}GÈf‚Žm…™ìØ!õê%͘!õï/Ýzkasó €Á°rÙZ†[©eËâa„»+åÚk¯u7¦TÒ«¯¾ªÓO?=úŠ–,‘N&!€ à'pˆZµêiÎé°ÃüÔ;ú‚ €@üvl³ïquêÔ‰ia7{¨ÊKÇŽÒSOI¥KÇ´3!€ (n¾þZºóNéðÃãëúÒ¥KÕ­[7Íš5+”Ñh„ ªR¥Ê®•lÛ&}ô‘\’\Ú#ÉJ©•*%=ö˜tþù»æã €@V ð++w;ƒF@@Èt»([­Z5MZ9tÒyüøL1ãCÈt;¶Õ®];tËX­¬Ì'ŸH/½$•+Ë̃ €@°¦O—\%4¼týõñõýw<âˆ#4{ölÝrË-¡2j9ÁF+WzEµjI'œ =ð€´}»tå•^RŸ>ñmŒ¹@2R€ G¹[ € € €@¶ XI5+9cåcvß]înÕlaü €A°€£&MšÄ5 W†† €@F üö›Ô»·´ÇÒÓOÇ—ÉïùçŸ×…^ â}ÁÕµ,G¹ZÕª^F£Æ¥¤.]äRÅçš…7 €pÄÏ € € €&°sçNYjüà™3¥Ë/—ì|1 @  lÚ´I+]¶…::„;â»àZèÊø@ X’¡å˽`£úõcïèÝwß­›nºIû^{í5µjÕ*ÿÂåËK‹óE2¿ S@"(©ÁK@@@2A`ÅŠÚ¼y³~ù¥§J•ò²Þg¸ €@ö Xv#k–½¯ öûïÒa‡I.Q @Œ;Ö+zÎ9ÒyçÅ6Ô­[·êÒK/Õ7Þ¨C9DŸ~úiô`£ðê¸k%,Á3 €@d8*†É € € €UÀÊ©Iõõã-Õ©“D9™ îIú (*àhûvÉ.ºÎ+­Z^Šg@2Oà‡¼›JêÖ•{,¶ñ­Y³Fgu–Þyç÷±“ž{î9WŠÍÕb£!€ P2•E@@@ð£€wQ¶¿vî,­üØCú„ €@|E}û­4{¶Ô·¯tÙeñ­›¹@Š€«ž­óÏ—Ö¯—žz*¶Šg‹-ÒqÇ 6ºÜÕÛž2e ÁFAÙáôð¹Ž|¾ƒè € € €ñ |÷Ýr·È¥jÐ`ƒ:v¬ïâÌ €€ïŠ 8jÖLš3GªSÇw]§C €$LÀJfß|³ôÅÒ '½Z+·Ý¾}{YÜaÆéꫯözë-©Q#©aâW € @ÀQ0LF@@@ ¨Ó§×v]¯ê²<üŸ{&à(¨û‘~#€ìÕ¯_×Ä<¯4È3· €d À©§Jö(ªmܸQ;wÖâÅ‹5vìXõîÝÛ[dòd©gOéàƒ½ô€E­ˆÏ@(@€’jÀ0@@@ XŠýÏ>;Æuýÿô÷¿W âè3 €ùìbéž{î©*U8¶åÃa €yvìØ¡^½ziÖ¬Yºå–[v=óŒÔ£‡T½ºôä“y–â- €ñ pŸs#€ € € àk×_—Ö­«£=öxÆ=HlìëEç@b° Gûí·_®ù/¾Xzê©\“xƒ €@F lÝß°®»î:Mv™Œþú׿jðàÁÞÂ.Ë‘Î;OÚw_郤-â[)s#€ G tž÷¼E@@@ nߦ&M¦xt@];]ú¾%K–ä 8š2E®<Œ4ÃÝ.(^!€d¤ÀÏ?K Ûð{ì1Ýwß}:þøã5fÌo¡G‘.¹D²ú£lÔ¸ql+c.@  à¨>B@@@ h×\c·¾ÞàÎW Z×é/ €QV®\©Í›7çmÚ$  W^Mº÷Þ¨‹0@Œèß_.ðV®´hÑCzã7Ôß-ÐØY†£ *HwÝ%Wo[jÚÔ 6² # €  ·zY € € €~hÔè'וûT¯Þ@¿t‰~ € P"+§f­~ýú¡ç¡C¥”† “öÙ'4‰@ÈHeˤ÷Þ“zô:w.|ˆóæÍsóõPÕªU5uêTÕ(_^êÞ]zñE©eKé­·¤š5 _ Ÿ"€ ‡Gq`1+ € € €~_”Ýo¿ýüÞUú‡ €@L‘Ç6 4ºûn©E éŠ+bZœ™@¬@:ÒüùR©R…ÁŽ•§vš¶lÙ 6jìžuä‘Ò‚RÏžÒOH»ï^øJø@88ŠŒÙ@@@ð³À˵ïG~ÞKô @ Å‹‡f·cÛUWIVRí¡‡¤²œÝއ‘y@*PTR" 6jß¾½–¹tHãÇ×ñK—J:ÉEIÇKW^БÓm@¿ ð•Ìï{ˆþ!€ € € ‡@8 D½zõâXŠY@ð¯@øØ¶pa½úªtî¹rVýÛ_z† €@ªÂÁFœ;fäH;s¦•k©‘ž^:î¸Tu…í €d¡@é,3CF@@@ cÂeÉp”±»˜!€Y'`Ƕ2e*iðà½T¹²ôïgFÈ"­[ °-jÈ‘ÁF£GÖ…³fyÁF'œ Í™C°QQ€|Ž PbŽJLÈ @@@ð€•T«T©’jÔ¨áŸNÑ@J `T+W¾]?üPJ·Ý&Õ®]‚•±( €>¸ÿ~©Ké™g îhÞ`£Þ½{KJƒIÓ§KEÕa+xÕ|‚ €@Ì”T‹™Š@@@ð¿€x¦œšÿ÷=Dˆ]`Ñ¢Z»ö 5k& ûr̉ €@Ж-“† ‘7–ºu‹Þû¨ÁF6k£FÞÂÑc* €  ÃQÂIY! € € €é°“Ï”SKŸ?[FH¼ÀÉ'¦;*衇¤rå¿~Öˆ €€_®½VZ·N1BªP!¯ 6Ê?+S@HºŽ’NÌ@@@HÀÎ;õ /„Jª¥f‹l@ä ^FíÚI'ž˜üm±@Ò%0c†ôÜsR×®Ò)§äïÅŠ+Ô¡C-^¼X£GV¨ŒZþÙ˜‚ €@Ê8J5B@@@ ¹¥J•ÒÉ'ŸœÜ°v@R,°×^RŸ>)Þ(›C@ …[·JýûK+J<ëW¯}×ûî»ïôØcl”Ÿˆ) €i à( èl@@@@@@0áÃ¥ùó¥!C¤úõs›lذA;é$ ž;W?Þz«úöí›{Þ!€ &ŽÒŸ›ÝìF¹Á=ªºG©ˆos¯Wÿ9­´{®ñ™½\ïöùv÷Øñ~mËÛgö~}´{Y¿}{ÿ¹{X³éLJ^íúç7÷òç?ßît϶îȇ}dÿ;ìaËÛóþîQÆ=Âm“{±Ô=¬/6ŽÆîÙÖº76û,Ü÷ð6Âc3[·­×žë¸‡Íná¾En7ü™=Ûça ý.3|lqïíaë.ï6–Ü#r}öùJ÷0Kk BÿîúÇö¡«ZÖ–·1ضò>lzx,öÇpÞm¬rÓl6æzîÙþpolŸ…—7ƒð¸ÂÏá}6Ûß͹ ëÏÿ¹GxuÜëÈfëÿÝ=lá‡}nó‡ámÙXlÝüùìžBÍæ3¯JÞÛ"ÿµ>™=Û²áõ‡·ç&©©{Dîs›×Ï=÷ÎÜû>y}3çœ9ó=缿gÎwfîyfL¤_Ç­g :?d¯€S`mÅF $jk°iñh?4eÕ³–I4̶ÄÛ&ÚÔÄÕV± ¸¼¶´<é BÐmñèìHlÕféôÛh^߉x¨?ªGm—(¤UFå™Auœm¢2:þ“hxÌAÚÔ£6ú£[ÅcR¨#0‰†YBc1ÐÝ꘠ýÑí•–µ¹ÆîY×Y<&ZB|Å9µEqm¥[¶¶Š_oµ‡üÊLdSùiÙ7þn‰±&²APG _ÛÀ6ÑzÔÎh?fYúT¹î&IVÿ°„Œ6ÂâZ1iR"3’,Ôå)¨Ïÿó?vïcvo-¼lfúž”BÀ)°§Ò I›ií?úh»OØT®Øÿ¶XÃýßÿ5éÑ1þ€…¶ -‚1l¿þu»VÔT¦Øÿ/¾h¾Ïœ_ #¨'ZGП@osÙµmL®¹xq1Íä×1Ù³íñÖÏœ6̹þ0ÞÑO?ýÔý?›o®±¹¤íêüy]ØÕiдaÓT^to Ú·4’”Ó6zœ¦ Ê=[ébRNøÔ Kt ,wèÖ6‹†Ï×°xóÔ¡ìXŽd?bZI,·}A?Z)Æ.@µ&Pî4[ëöR­ ̱ØõrþáœÐEE‹ ì^39y»7tkçcMÿÙýUþÁ¢RºyO‘H˜`ñ"éR¢v1û±Æî±œÝ‹åC¡:î²=åÖ¡¾®×¤2ÿ¿Ý›¸šÓêŸú ·Z¢Ü:’ýЃéíMt¤ºg™DÃÕ–8)šQBü+³N¤Üsß©9­{>µ!n²Ä‰ÑŒâI›?kÇìÜ|œú!–Ñ ›—Û›è}ðÓ–Þ¥Y©î+“¬TÇÉÍûKÝh¼ë… ¨õCyCMì™G,Ü`)»)p LôÃHôâ×’ƒÎ›¾‘=OX|÷æôÛ¾Ù6²Ç÷ƒD‰ÛyV®w¤ì“ߣ9­~¼Ù§¨ê8-‘×Vòc+}†ó¸¥÷l>h#Û&Yéü8£y©qí)¬:‚ó|C‹O‹ìSô2“rëÝGà?Öåß›è|›Þ,úá±µ ±·f¤€üßšÓººÒœ ÏZ‹Wæ´·;×N¶{÷ÚC,ÀöÙÇü«nJ¼Q~|¦}ä}ýæ‘M'Ó§»aéÌÙ’ ljq]›ˆô`ëˆ#lî²É"hû*Vèæ `óöŸæ$þ7ê û %G<âÜë¿¬íº«-F46«_&ú?›ÀÏ”Èl#¹þíÖfV‡nó°õãÊæcÔq‰ãÿfƵ%2ÛH®{½]Ï4Œo}ˇÚä}Mó1«ÚöÚÄñ§š=†'2 $e‰ì²¥õcùM…ÔyÖ›éjÛšãÁæaëÇ%ö#¨gS8 ÒyÖhÁ8êxb†-nÓ¸²ö•:ÙXø;óŸs›Jë]àóìd Æ’úq]BÑ3öPùÉ¡6mŒ’kŽE;›^‰ô¯b¼~cu@³Í9ÆêèãœáˇÕìÿÀ6ÍYî9³ÇSÖ;4¬c¥õIõ©®|°A=-~±uM뇟ló­w[AéÐä?äúì¿§_·ð4é=WDôçë±´‚lÔs¡5t-] X«O¬Ž‡,¾Ü¤›2á1›°Ù°‰C~ÜXÛfAšNvã$V+l1—êøÈml?B¬ÞU @ LK­¼ §üâè¡ò/™èúi¡‰|at»ÄÒËL>mÞnkÛ¿šDÃ,q…‰NÃL.5‰†¯XâŸÑŒ6â»ØþI‰2Òyysžfù…—Ñ"§XBç]©aW+øh¢°|@PÇ÷,þëÄþ³-]N»Yù:®·ô¯šóÔæ­û/¶tY¬l~8hq“ý0©ï6hÖ¡¾FÃ5fÌǢG¶3ý_|»IƒôëÀ,)›+¨_ÌÇ>ûïZHO¯þYº­ØvVþàÙM¥‚:þaÉ ŽX|ï„’¯[?ž(£ÛÌwn´Í¿ ½z٤͚ÆÀïš²òü´×mvó2¥gs6[›oÞq²ùó½{›}·jZ˜ucó±ýl{HBÏ]æ_1ÿWjù¾µÝnuݧÇw±æ;øêfB2&¡ì¶rê°¶¿ùs£žnª£oߦ:¬[îO&¶Û KèWòV«ãÕ2úñú»¶èÎnýè£_æ¨$-¢™aœÞ·ùë}‹hNp®9´yæÐ>2YdçÏRÌŸJ¬âVvÝW-n }笳l³®qoI÷%“Ñ&Ñð•7{lZÓ5¨©Ëÿ©m^ìzQ×tAÐuh÷'ì¹Ñµæ+ÍYjŽøãm¾ÞºÉ¯¨ g˜мý¼Í½¯Ø¹¨Òõnþš×æûüJÉ`»ÂÒ’{LN7iZ¸rßÎMs]Ë“ÿ<<ØÙ¼ÝÉÎ÷—lîÊÿŠª $ЩtA¤-š_Í)'sªMA Wþfó|ªú¡]G4í ÿcvxN;m›¿ÐÐE‰ê2Ÿ’ù‹ÍqÛ¸;MÎU¤)¨/[?·¤®QŽ5Iú1~²ô4ÚªNåé¢_ú5G).Q?u¨ýÑ­Êzµ âY|„I>°Èá&:VÇÈ^Ñp§%ÔOéOÖ!¦²{ЗhY~Þ¶Èa&ªc-±Š†[-¡k± êˆöEã^uõhû¸Éz&A˜f‘hw;š··Ùöt;Kµ]—ÚñåŸo"î’gMuO@Ó)¥ø‹=&Q\“”&¤~&šX’¢I<ú[âD]·k²K†Ï[Æ©&«˜hbLnƒ å+®­œw4 ±ÄÕÍrØÉ°µeü¬9SuH䂸viR DŽ0Y‡ú|މê/ÖÓlŸ. õCyb :äµMêÑÑ&ª?¹Ï²òÙú5Ûª â,GÙF"ÝÒñ©I²ëZÞLÄRõ%Ãf–q²‰Ž—¨Ýª+)ÊW? µUu|ßDuô1I†-,C¬bµoÔæ39ÌhPß3Ñq}£;šãºñû¡‰êD6ê‰Ö¡<õ%Y‡Æø7Läð ÙCVe†4ï×ñÙ@ú“uYVþ|Ñ6,¢óCe¥+¶²Œ3L–6‹lª¸Ú«±®6hÄ•Ö9 -!ÞbY¨Ží-ÿ'&'mƒ1*;«?²t«x4èü8ÅDãAç|2Œ¶Œ‹M´?¨'ˆ«®€•ê l£x4¨»:nÍèŽæø0Ûj¢6KGRW¡¼dv¡¼k}¼ÜDcbÉ–&CMz|`ãs†Íóí"ú#{d²h®]”[þwž³üyvþÙ øç?ÛÛ †4]@kÖ˜K†éWYŽD^ƒ6ðA\_'¥¤y£y3¯¾joKØ¤é° /¹]:Ár~Üœ›Ð¥ÜfÕMÔH“Ÿª=Íaôhç†÷nšS4?J’a¾ê¸ÂD'‹ '°¶ÁDLâÍ'òIÆ,¿Ï6ú«Ë¡Ã?[„X¨Žy·[ÁëLšÛ˜g¥‰.˜ð—¨>µÃäüOl«z-¨Z?dWÍM²I2äî´œ M‚2~1Ûœí¿Xu6C3ÆÞ‚×·é!Žš Ã“aÕ»,Gö‰ú£«Ýjkó6b*÷SËB`E–¡C¥":ýÑrT‡ …´UˆÔ¡xPÏEM{óÿ«›X?ZJM+TDzñ¶#WA?‚­”Fûcie]i„¯~Õ¹Mm’Öà 5©+=ÑXÔlÕ;PÇJ–™Dûñ¥/Ù¨v¡¦h_P΢aXa6_T¬•k|´ õ hAÞë‡ö«žÈ©q¹;l®h«+­ФCòëðh{øa¬6³:dób¡Ë=6ü[«C6÷%Q‡Í n õƒM§o™¼aòfóV÷?1‰¥Çšè¼>ÑDn,4Íý-’ÑÝâºî 2I§¾ui–õ–Øm³í<±­=(Ï/ÚØÐÊŒ6QŠ'C¿Iö°W­5Z õtâháa ùIÙ¸—ŽžóíZùye87dHÓB¾}-܃l«‰ÐÓæ¹íìxéÌÙ$²Òd…Íù+­Nm—+ny]¬]¬Ý+¬ý‡M5ÿbæsŸ³7ùý¨éÜÓ«&j› ËmÒ¦“RuØVõäLoÎê¶+MïJ›\VÚ;Õn86˜lq+o?.¸{ìÜ?Ê×uº¦àM’aÖÑÆ_“m H¾/¦w¹‰ê ¯?,ú/+ÛÓú¡ …'úá÷x‹ïo¢¹z}“d˜¹å|˜Èxõ­€Ùœe(c‹h”ýÐÈ™Ú ²ÑêÖÕqÀIvÿaõ¬´˜ö+û\sù­lkSl4”ÖïÖ4—X›=™h«?€‚úÒÝêföûêÑÖ]ƒ¯zôF–XÁgM,™f§­ÆA·›Ø5—©q‹ìø Ž%VOô§d÷5L¾±¾ÛÖp-žìñ–û²‰žßZ7cauK­ÖË®CíYñԶŸô5±>,4ª/¬G}±2ßµë½Ã~lãÛÊH†›ý­êü¢ÕeC>„ã#SëšÍ»™ŽUM>5‹M–ÚNÉ“ žÕLÙ¬Žƒí¤6ýÿ±ç&oŽSI¢þ <ü°s·Ýf`SÌþûGúko»zÚΣßxýÝc°[÷ÚI¶`ÎÆý +³A¤ÜR‹ÛÐÇ£ö[±0h¬¦ÚŽhªJ–WÞ‡&:Wí4ÍŸ¶ ƒNùç©6¼óîÇN§ü}…¶h_4Ø© ªCþ9Ðan&lú‰-² Ê[;ÍòÇjÑ<£m”“%óSð!¶•ëh^ˆµéH“ Ÿj»ôKw JK·Î±b :Vv'ÅÅ&Ö°Äž&KL›H‡ú®rQѱê‡n] ±úØòmjÎÿÆ£¾DƒÚ·–‰n•ÞmÞjîRUéTZœÕ•†O,ñ’‰ÊHTFÇA<Ö5Q¹ÙÍ[ÅÕoé×¥ˆ¶šãÊïo ó-qŸ‰ú© ~Dy©íwkG"ÈjKP‡M¹ù· «>s± N›˜ûË·GÌÕŸ èÜÙÁD~CíÿÀdº‰Ò Ѿè¼RêK4¨ŽLt¼l)Ö;AÐ8ÜÇD¶ ê™eq•—¨ÏA_´]Ï$tÜ›&*¯¾$Ã@Ëи’íU6ÙFqe&»$ÇÆ‹®gšDí`É|PÛ†˜hÜi<¨?1 âb#¦’~&I?iY„ú# é Ý!—ËÝlÕn˜J<òˆ7nœ›0aBËöM³¬˜hâ DF‡F’O€ Ÿ·›¸Çì/»zë/‹ uCà…^p?ýéOÝ}ú+ dÐÍÝÛvðÝ<>©é7ý%¤L ú‘tM»‹YÝîLô W:õ¾ãÖÂÃÛ²³»ãDÄ‚¸¶Ñt×Vçô´¡­WÁOjÅúJSùbm‘.= ‹J·ãŽM}*v¬ò¥_¯×B+=0 ŽMê Zê_×öCì¡tç–%é5êÒÔŸLjk)ýÐkó§OÿŒCPW!}…ò¶ÜÒn¬tgÕJÐëÿõW÷Ñ6«¸^÷¾Üîæ$ÑxRU)ý˜5«é‡”(cŃþDí¢xÔUJ?ô Ù$9F•ŽêöSùAØxc{¸bçLkAçÚœ9…Kh %ÇQÐßàˆRú![Èî­… ?ɾ®ÛêG´Ž¤Ž¨îbmè(«bz›ó¶yèN;¯´ë|B}˜6mšûö·¿íþù϶Ý!=ºÓäz“™ØT Ã-e§z,Üj©»Lôðq´É±&ÑpÒ/m.µ9b‰=YZ<×dÚÓ¥…Í¢?ÍÕ§ 4Ï ;ídowx¬Ðžxž~Ðyýõx^©)Í£?Þvi{šë¢AsœÎyùym•Ö›+´XJ>P¢,¨hJÿ{z©½ƒ¹@[ùø¨ólrþÐ÷»ß×ìùÆ7œ{ç Õ4çKÿª«~v½ÄU4ˆóÙgGs Çþs»^Ò“ÄHP{“mú)æ† ±MÇGs ÇýkûÏÆSÒWj.ô&ë 4•Z‡ú1Ï~=ó€{WÑ>qmôùa‡5Å[û_?êSC ¶òaŠz“õIçzëÙÙ_nM{Ó¾?ý©éœ“>éÕùÝ*_ú5¢[ÅõÙœ/|¡í:î¶§û:¯uŒô%ëÎñdJ¯³Ž½]jï¶ëе´æŒ¶‚˜©yÑ®….}ê)7žfÛ¢—™ýï½÷žÝúìïž{î¹¶Û¬ñ7eŠ- zÂ0Ø}Ê+6FÞêi÷qöëÙòMíø›œþ™ž¿þÕ>WûŦ—¡è”¾È䇟íÎǾjפ“gÙ}‘÷–Óà ö´q×Ûæ I/›S»Yº›ñî&ƒlÿçM4¿JzØAs,ßÜEþÇ&»mŒý0§J>51ù¡ÔBiÌ$yvæ–Ëzý±•7Óå¯gÚâ­ë£E&²‘ÝîçL³M›Á¦Éð»th5¨šòôßâú1Nc­­¶éý(«¶õ7Ñ1Ñ0ÝÒW(èZNõ¨O­]¶©]’µLÚ*oEòAã]Üt‹\ê1*/[Ê6¥õ-°ún§[IAǵÅ6ªHåÅZcÁ¦“ü¹j/A¶Tÿ5DÂóöɬóÏ?¿ðó«H9¢Ù#põÕWÛeî\÷ãÿ8Öx]öŽ´5ƒ¶¦(ÿØmÈæÝ}äìs§ë¹h3·¬Ó¦¶vM'fs¸Ñ¶_ÍÛÃl«ó£ŸÉY&‘âùóú1Ë æ6Í ·ÁV畹°Ø" K t”Àí™Ëñö<à¡à³©UÈñi#0¨ÔKº´5œöÔŠÀFV±„@¨ÿsÓ›E‚:ô‰>c¡¿€Ýzk{˜gOóôžúô„¤­…?…¸Œm?Öšø ú±Pâ3è¯%>ƒþBTâ3¬¿¾ý¥—‰Ï Ù$>ƒ~ô”ø ZL×Ö‚ºŽÖ¯sLâ3èÇ[‰ÏP::Àê“7ßt+þýoŸÐ6úÁäQ“ëMî4Yh¢Ê_2Ñ4»¡Éúöt{…-è™óŒýåüd{“Á¬&Ÿw啿m¿¤Xxüަ¢úqu5šDŸ›Zwݦ\µ0W‹3õ™«`Ä.¦5ž¯…Z@¡Å Zd,Ò¶Ê+´X¨” «U‡‚®´ÀHú[ Zx¡Ïç‹-Z+«}O>ÙV‰Žï¿Q¿:xçç¹SÊ)þë¨F?ô–ß¡”EImÃÁwTCÛÇx`ÛeŠ”˜o0çlÁ¡Aè~íᇛi‘ÑÓæ»îjÿ¾É &ŸÐÅæèÏ›?:í&ûë}[€¤û9Ý+mnÅÆšXVÁ ·°’«¶Õ`n†ÐrÍ%ºö˜v-´)5héÇúrƒ]µXXVL‡ú¡…,’r‚ÚÕZÛ†”£¬HY» Ê¿°O‘ýŲu}))'hÑC9AÜÊáèÖqå„À>åÓÞ²Ìí%WwÇɽé¥ZÓ>Dªî6¹l©ýñD_›*޳b}èVÝÎþxo„åoÒ,;Ø6nOfDÒšs¾I… T Ž*³ª–Ø_Tη¿’[Ë~ð좇®@€@Æ ÔÜ·i1Å6Û4½¥@o*Ðôã)€ ÐN5÷mXÿeòfsô@ú›&[Ûâ¢ýŹ_tîA{cÞ\§…3AÐB-º-%è EZTÔÖâœRt+£Oˆøm½±®Pýês© š O ¨¹oÓÛèô)]­ºèz¼-½Ñâöˬ>õ…eöyH[b?غϛ µ_ò;+!‰nó"0ˆB€@@ –>N_ͼõ kɵ&CLfé…eìß-îúÞ7»ƒÞ˜`/Z׊@ @ X±’N»ÄZ5iÒ$wà 7Ø›ä_wzµ°B'{ÀÙßþÂy—]vq‡z¨5jTì€ 4H•oÓ™¥|Ž&Í@i Ôœ@ª|Û†Ã~{Í¿Jÿˆ%öyûs×ßÿÞ¹ïLúŒÓVhß}›Þ߯wøK”Wê¶è­F@¨k©òm}mñО¶`öi[Qô‰ýðj/ŸÍ¿Üè${-ÍúíyõM]›ŽÎA€@Rå㎳ÆÚË]ÝÚËÝŠž—»N .w§­¾Àøô ¶ØhÍ6zÂn@€@m °à¨¶ü[­}æÌ™î¬³Î*øÝòœ½Â}Μ9îî»ïÎËž{îé.¾øbûÊKÏVu²€ PKø¶ZÒ§n@ðA •¾m¨õôOÏ;w-2}‹³×ä6}ÖLŸy’l»­³'×>p €ê€@*}Û¶Èè¡-›^ZtŠA>ÒľÚI€ ”C •>îëÁ^o»•c·wnÁÛîXûÔóÑ÷?h_^N×( @¨ ÈÇ­kR?•!ðþûï»o~ó›:䡇r‡rˆÓq@€@ àÛÒhÚ@!ZßvÇö¹Ð­ûÝïì³2¶úèÊ+{ççn¾¹é­F,6êˆÙ9€@]H­o3·æž2™lòm ”C µ>nõÉ.÷‹­ÜÊ9³ÝÖ¡ì>N/ @€²@€7¥ÐJK—.uÇsŒ›5kVغnݺ¹vÚÉí¼óÎö¦û‘nÞ¼yî©§žr·Þz«[°`A¾ÜôéÓÝ9çœã®½öÚü'׃‰@€jLßVcP= Tœ@ª}Û~û9wòÉÎ}ë[Îm­_h € ¶ ¤Ú·©ùÛµÝJ@€ H­[¾Ü¹ƒvËçÎuÛ—M†Ÿvš;î8}c@È¥ÐN·ß~»›:ujزUW]Õ]ýõnÔ¨Qaž"»ì²‹;üðÃÝ7¾ñpq’¾;{‡ý5ëa‡+K€ PKø¶ZÒ§n@ðA Õ¾­G¦·ùè8:!@ n ¤Ú·Õ-u:@Õ Z×¥‹»qŸ}Üx{«Q·1cÜ%—\R Ô@¨>©V1”•Qôé§ŸºqãÆÅ”;¶Åb£ À AƒZ\€è‰@H |[Z,A; @ Rðm•"‰@H |[Z,A; @ ÒÒìã/^ì~ù÷¿»9[l‘ÿ¢IçÎül[iû£€üÀsùå[¶ö{ï½×Í™3'ùG€@@ફ®rãÇ’l! ,8J‘™tq!Y?JôcFtΪŸžÑ“JÀ·U’&º*M@7öòo$ ¼ûî».—Ë%³IC O߯@H3Í]šÃHÐ5®}(DßVˆ yi"ðÎ;ï0‡¥É )i‹Ò._¾<%­¡i%€K«eh—¼ýöÛ€€@ŒÀüùóÝ‚ by$ v,8J‘…&OžkÍðáÃcéÖ«®ºªÛ`ƒ Â"Ë–-süq˜&@¨|[-¨S' ø$€oóIÝ€ P ø¶ZP§N@¨|\5(S 42.Üù´õ=ù¦>}ú”ÕÄÞ½{ÇÊK_¯^½by¥$ôzÉ—^z)üœ›>í¶å–[–r(eê˜Àìٳݯ~õ+Wc$ ß5 ýõô÷¿ÿýL³Ð+¹_{íµ°Z°ùá‡ºäœ R´ø¶_|ÑéíÑO•êM‚;³öº,ƒÖYá%K–8½­-ëóX™%5ÝùáèºtÉöíÒ¬Y³Ü|g*·Ê*«¤†o–’ß6uêÔüµXÔ·1ÂéQK@寷áÛw ë¹ü€>‰Ý­[·bE2‘¯·œo¨\ºt©Óý¡ãÒâÛôœaáÂ…±û¶M7Ý4óã¶ãBƒœyæ™™¿>Ç’•% ¹ë /t={ö¬¬â*kÓçÞ5ÿ)èÓJzNA¨´ø¸I“&¹W^yÅ=øàƒùέ±Ænã7®\GÑ”9Á›µO?ýtžQgÎzþüŸÿüÇuíÚÕ½úê«þ*©‚fýÆ6cÆŒ|MºgÓ››õK ÛOÐëÌ.É“­Ü…ÉÅEº:thÙ”¶Ûn;§ mÝu×Í«c·Új«²õp@}0`@þ-Z=zô¨¯ŽÑ›vÐ3oÞ<·ÑFµ[GÔƒwï LŸ>ÝõíÛ7H²í ´ø6-œ•8p`Ø#ù6…82¢y묳Ž9rdCöŸN' ÖY_ 3sæL§‡× úñ.y¿Pœ{Z#ß6lØ0·ýöÛ»Aƒ…ÍÕbZ…82²bÅŠüµìÖ[oÝý§ÓÅ èÓf›m–x]¼Tú÷èY-:RвÌy•±YZ|›žEê¾-úw-¦ÍúB¹ÊX©±µÔËõyc[±ò½_k­µœ®‰»wï^yåUÔ¨…´úcýa‹i+ ?->n¯½öÊÿëšk®™ï ~gÙd“M*ÛY´eŠ€é9 Ϩ3e6ïÕïmúÈà7zïzª@¿ê·6=ƒç3qyuû ŽRdÚä…O¹o×H–O®Ü.µ«»í¶›“ %ð•¯|%š$@ $iñm£Fr×_}Im¦ ®{­H‹oÓ_ÃÞpà ­5•} JàCiОÓíÖàÛZ£Ã¾´ø6ý1ÀM7Ý„A ЂsX $dÆàiñqÇsŒ“ %pðÁG“Ä!d’ßI‘Ù’>å¾á(ùêÐO>ù$E½£)€ Јðmhuú @ ¾ àÛêÛ¾ô€@#À·5¢Õé3 Æ €k ;ÓK@¨ÕŽ}‹š;uêËÓ7Ë ÉWm&ßxTŽ.ÊB€*AßV Šè€ 4À·¥É´€*AßV Šè€ 4ÀÇ¥Ñ*´ €ê‰ ŽRdÍþýûÇZSî÷ —.];¾oß¾±4 @€@µ àÛªMœú @À7|›oÂè‡ jÀ·U›8õA€@µàãªEšz @ Q °à(E–ïׯ_¬5å.8Z²dIìø5×\3–&@¨6|[µ‰S ø&€oóMý€ Pmø¶j§>@¨|\µHS 4*¥Èò½ð™3gN¬7,8Šá @5 €o«tª„ ¯ðm^ñ¢€j@ßVèT @U!€« f* &À‚£?yáóÎ;ï”ÕºÙ³g‡å»téâzõꦉ@€jAßV êÔ @> àÛ|ÒE7 Ô‚¾­Ô©€ªAW ÊÔ@L€G)²þ€b­yþùçcéÖúœZtÒÈ‘#]§NZ;„}€ ïðmÞS T™¾­ÊÀ©€¼À·yGL€ P#ø¸§Z@h,8J‘©‡î¢?S§Nu .,©…Zœ´bÅŠ°ì^{íƉ@€jEßV+òÔ @¾àÛ|‘E/ ÔŠ¾­Vä©€|ÀÇù&Œ~@ht,8JÑèܹ³3fLØ¢•+WºÇ{,L·yøá‡c»÷ØcXš @ ðmµ N€ à“¾Í']tC€@-àÛjA:!@ ðqÕ L€ ÐÈXp”2ëtÐA±7.–.”˜7ož»ãŽ;Â]C† qC‡ ÓD @µ$€o«%}ê† ðm>¨¢€jIßVKúÔ @> àã|ÒE7 4:¥llºé¦nã7[5eÊwË-·„édä“O>q'žx¢[´hQ¸ë°Ã ãD @µ&€o«µ¨€*MßVi¢èƒ ZÀ·ÕÚÔ@¾àã|‘E/ @À¹U:áüóÏ?؎ߢ#:8¶%=z¸‰'†;&Mšäz÷îíFŒáôúÇ Ìž=ÛwÜqnòäÉA–6l˜»à‚ Ü*«tÈ´¡>"€ JÀ·U‚": @ Mðmi²m JÀ·U‚": @ ðqi´ m‚ : py§Žt"—ËÝlÇÕ[˜Àgœáî¿ÿþØÎAƒ¹-¶ØÂuëÖÍ=ûì³nÆŒ±ý]ºtq7Þx£Ûf›mbù$ @i €oKƒh T’¾­’4Ñ@i €oKƒh ø €óA€ Ðà±à(¥#`áÂ…îÔSOu>úhI-ìÞ½»»òÊ+Ý.»ìRRy A€ªMßVmâÔ@¾ àÛ|F? T›¾­ÚÄ©€ªEW-ÒÔ@ D`P‡¾»Å'Õü •®]»º1cÆä?¡öòË/»eË–­lûí·w—^z©ÛvÛm‹–a @ Öðmµ¶õC€@¥ àÛ*M}€ Pkø¶Z[€ú!@À|œ/²è… &À'Õ²`üE‹¹xÀM™2ŽóÎ;NéõÖ[Ï­¿þúnÏ=÷t#FŒÈB7h# @ $€o Q :!€o«CÒ @ àÛBD @ ÎàãêÌ t€jE€OªÕŠ<õB€ @€ @€ @€ @ ƒuÎ`£i2 @€ @€ @€ @€ P#,8ªxª… @€ @€ @€ @€@ °à(‹V£Í€ @€ @€ @€ @¨Õ<ÕB€ @€ @€ @€ @ ‹Xp”E«Ñf@€ @€ @€ @€ Ôˆ Žjžj!@€ @€ @€ @€ E,8Ê¢ÕhsÃX¶l™“,_¾¼b}^²d‰{ï½÷*ª3Ú8Ÿú}êŽö!ñO?ýÔÍž=ÛMž<Ù͘1íX±¢¢ÍôÉ6«º+ e€@Œ@Öü›ÏyL`|ëÁOYÿVÜ <.ŠSaÒKß·M#ÏaYöm²¢OÛùÔ¤ JÀ·Å)6ò†o‹…hª‘ÇE”qd‰þ-n­FžÇ²ìß|Úͧîøè#U/ºÔKGèêÀƒ>è¾÷½ï廵í¶ÛºñãÇ·»‹“&Mr7Üpƒ{ýõ×󋤨S§N®ÿþn—]vq‡z¨5jT*õûn{»;]…ßÿ}wß}÷¹¿üå/îå—_ŽÕ¸êª«º!C†¸ 7ÜÐpÀnß}÷í/%á“mVu—Â2€@ÇdÅ¿ùœÇDзþŽYÉïÑø·â|y\§Â¤Ÿ¾­ÉF<‡eÙ·Éz>mçSwúgZìÀ·5Ù®‘ç0|[ñó·‘ÇEq*ì@6àßšìÔÈóX–ý›O»ùÔÙVv„@§ŽœËån¶ãꈎ… Ðb#]ü(´wÁÑÌ™3ÝYgåž{î¹Â•Dr÷ÜsOwñÅ»ž={Fr[úÔïSwë½JÇÞ¿þõ¯î¼óÎsüqI Ò¢#•ïÓ§O›å}²Íªî6¡Q¨´û7Ÿó˜ úÖ_1CyR„+ ¶ÑÇEa*äB ;ðm~ï;Ó>²êÛÄÕ§ÿñ©;íc‚öA àÛðmY|.©sϧÿñ©»æ ú,À¿áß²èß|úŸº³0'ÐÆŠÄ‚£ŠpD *Kà£>r»í¶›ÓëüÚ³àH«t8â7kÖ¬’§7æèMJzóQ[Á§~ŸºÛêWöëmT\pAÙM‘Ýtì°aÊë“mVu…Å@ âÒîß|Îc‚é[Å Va…ø·Â@}\¦B.²Cßæ÷¾3í#!«¾M\}úŸºÓ>&hê¾ ß–Åç’:÷|úŸºëaÞ Èüþ-‹þͧÿñ©; sm¬U %Š P!K—.ußúÖ·bo%*wÁ‘trÈ!nêÔ©a«ºuëævÚi'·óÎ;»‘#Gºyóæ¹§žzÊÝzë­nÁ‚a¹]wÝÕ]{íµùO®…™‰ˆOý>u'º‘ÊäóÏ?ïŽ>úh·|ùò°}ZH$»mµÕVnË-·t‹/vÓ¦Ms÷ßÞ†aA‹l½õÖn„ íç“mVuGÙ‡üÐ<‘fÿæsYßúýZ¯ãÚño…6ú¸(L…\d‡¾Íï}gÚGBV}›¸úô?>u§}LÐ>Ô|¾-‹Ï%uîùô?>u×üA ø7ü[ý›OÿãSwæÚXQƒ:¤MŸT3!@ `‹~rwß}wΠ冓#<²¬nºé¦Øñ#FŒÈÙgÕ ê°×ååìsj±òüã – 2}ê÷©;hš·‡~x̲ͻï¾[´ÉwÜqGn“M6‰sÏ=÷,ï“mVuE& PQYño>ç1õ­¿¢Fó  ÿVj£‹ÂTÈ…@ú àÛšlÔèsXV}›¬çÓv>u§v …È.|[“í}÷>‡}\¦B.²AÿÖd§FŸÇ²êß|ÚͧîlÌ´²‚vîЊ#†ÚMÀNdwÙe—¹ï~÷»î€p;ì°ƒ;ûì³ÝäɓۭSê3lãÆ‹é;v¬5jT,/H 4È]rÉ%A2¿½ýöÛcéh§~Ÿº£}Hk|úôéî…^›7`À€ü'ÒÖ^{í0/Ñ›¬¾ùÍoƲ¯¸âŠXZ Ÿl³ª»$2 ŠÈ¢ó9 ªoý1œG%ø·Âp}\¦B.ÒIßÖÒ.>‡eÕ·É’>mçSwËQH Ðø¶–ô}÷~Þèã¢å™BÒMÿÖÒ>>eÕ¿ù´›OÝ-G 9@€G`eú˜J+W®Ì/ š8q¢ûïÿë–-[V‘vÞ{ï½nΜ9¡®½÷ÞÛxàaºPD‹‘¶Ûn»p×”)Sœ½ù(LG#>õûÔíCZã÷Ýw_¬ißùÎwÜúë¯Ë+”8õÔS>™„Ù³g»?ü0Hæ·>ÙfUw  @ b²èß|Îcë[ÅŒçIþ­ú×TžL‰Z4,|[KÓãÛ²yï&Kú´OÝ-G!9€@GàÛZÒkô9,«÷m²¤OÛùÔÝr’t”þ­%ÁFŸÇ²êß|Úͧî–#œF À‚£F°2}l(ÿú׿býÝk¯½béb‰wÞ9¶ëˆ¥ƒ„Oý>uíOóöÕW_5oŸ}ö‰¥‹%´Øh£6ŠíNêòÉ6«ºcÀH@©'幯gÛSo8k`Ò'áßš¬Öèã" c—6BÀ7Ÿó€OÝââ[¿oöÕŸUßæÛv>.::®8õ@Àç<àS·ØûÖŸvûâÛœ+ô<¼ÑÇEÚÇ-íƒ@µøœ |êßú«eƒöÖ“UÿæÓn>u·×N—m,8ʶýh}† tîÜÙ]|ñÅåŒ3ÎhwÏžyæ™ðØN:¹Ýwß=L·‰¾áHå Ý`)ß§~ŸºÕö´‡wß}7lbß¾}]ÿþýÃt[‘ÁƒÇŠÌš5+–öÉ6«ºc€H@#EÿæsXßú+fu·ä4.ÐIú4Ðb ƒ:¨`ÓÞxã w饗Ü×Z¦Ž›;wnXd‹-¶pk­µV˜n-²ùæ›»îÝ»»Å‹ç‹M›6­EqŸú}ênÑ‘”fD/|Ö^{í²ZùöÛoÇÊG ùd›UÝ1X$ ŠÈšó9 ¬oý5ž'eø·ê^Sy2#j!ÐÐðmqóãۜˢo“}ÚΧîø$T‚¾-N‘9 ߦ‘|θˆŸ'¤ ø·¸•˜Ç²éß|Úͧîøè#ÕHxÃQ#Y›¾Ö=É“'Çú8|øðXºµÄª«®ê6Ø`ƒ°È²eËÜǦñ©ß§îX'Rœ¸îºëÜ=÷Ü“—+®¸¢ä–.Y²¤Åçj>÷¹Ï…Çûd›UÝ!"€@&dy®ñÙöLω«î5UVÆí„@£ðé|ê–Ý|ëÏÂØÈ¢oóm;ÆEF.m„€_>矺EÅ·~¿ä+£ßæ\òy8ã¢2c -È:ŸsOÝâî[l›EÿæÓn>uga<ÐF?xÑ®h…@MDßn¤ôéÓ§¬vôîÝ;V^úzõêæùÔïSwØ”G¢‹„Êiê%—\â–.]¢·ÕƒÝ¡I‰@ á øœ|ê–á|ëÏÂàÀ¿5ƒjùæ,Œ Úøõ¾}oýYYômâêÓv>ugaLÐF@ Ûs s˜sø¶¦³Xc!¸wc\0³A"às.ð©ÛwÛ³2:²èß|Ž Ÿº³2&hgå ð†£Ê3E#jF`þüù±ºË]pÜLJ’ŽÇ§~ŸºƒþÔãöoû›?~|¬kgžyf,í“mVuÇ‘€RO Ës϶§Þph`=û7aa\t`pp(ê„€ÏyÀ§ná÷­¿NLÜ¢µöm¾mǸhar2 Ðp|Î>uËP¾õ×ë`À·µnÙ¶žµ·~4{!´ðé#|ê?ßúÓb£J·£ÖþͧÝ|ê®´З¼á(;¶¢¥h“@ÒQ$ßXÔ–‚dù¶%ËwD¿ï¶·Õ¶¬í_¹r¥»úê«]òÓktÛ{ï½cÝñÉ6«ºc€H@©'幯gÛSo¸v4°ü›°0.Ú188uFÀç<àS·Ìà[™Ú¥Å·ù¶ã¢ÞF.ý@ù|Î>u«§¾õ—O3ÝGàÛJ³OòÙyòY{iZ(Ôš€OáS·¸ùÖ_kÛTºþ´ø7Ÿvó©»Òö@_v°à(;¶¢¥h“@ÒQ”û†£ž={Æêøä“ObiŸú}êŽu¢¯¾úªûÉO~â¦L™ëÍ&›l’ÏeZÂ'Û¬êN2" ¤›@–çŸmO·ÕÊo]£ø7‘a\”?>8õFÀç<àS·ìà[=Ù:M¾Í·íõ4ré ÚGÀç<àS·zë[ûˆ¦ó(|[éviëY{éš( Ô’€OáS·˜ùÖ_K»Tºî4ù7Ÿvó©»Ò6A_v°à(;¶¢¥h“@§NbeºvíK·•X¶lY¬Hò¯0|ê÷©;Ö© '>þøc÷›ßüÆM˜0Á­X±"Ö“ý÷ßß;ÖuïÞ=–¯„O¶YÕÝ€@ª dy®ñÙöT­ŒÆ5šÆE„¢¨S>矺eßúëÁäiôm¾mǸ¨‡‘K Ð1>矺Õkßú;F6GãÛœ«ô³ötX–V@mðé#|êV¿|ëo‹]ö§Ñ¿ù´›OÝY°7môC€G~¸¢5!пÿX½ ,ˆ¥ÛJ,]º4V¤oß¾±´Oý>uÇ:‘Á„Ý~ûíùϧ}ôÑG±¬¹æšî¬³Îr_þò—cùÑ„O¶YÕåCH?,Ï5>Ûž~˵ÞÂFõo¢Â¸h}l°@Àç<àS·lã[–íŸfßæÛvŒ‹,\ÚÊð9øÔ­ÞûÖ_µтoûŒ{¥Ÿµ¦™ f>}„OÝbê[šíÖVÛÒìß|Úͧ³¿~ °à¨~mKÏ@¿~ýb½.÷&hÉ’%±ãµ˜%|ê÷©;Ú‡¬ÅõÇ3Ï<Ó½öÚk±¦kòGáN;í4׫W¯Ø¾dÂ'Û¬êN2" ¤›@–çŸmO·ÕZo]#û7‘a\´>>Ø F àsð©[¶ñ­?«öO»oóm;ÆEVG.í†@åøœ|êßú+G¹ºšðm~ŸµWךÔ´—€OáS·úë[{™Öú¸´û7Ÿvó©»Öv¥þÚ`ÁQíØS3*N £ŽbΜ9±6UzÁQkú}·=Ö±Œ$Æï.¼ðB—üÔÝŽ;îèÎ>ûl·é¦›–ÔŸl³ª»$p‚RC Ës϶§Æ@e6¤Ñý›p1.Ê4‡@ð9øÔ-SøÖŸEsgÁ·ù¶ã"‹#—6C ²|Î>u‹‚oý•%]mø6ÆEuFµ@ ý|úŸºEÖ·þô[¯e ³àß|ÚͧÉi,8jKÓφ tï¼óNYýž={vX¾K—.-ÞœãS¿OÝa§2ùä“OòŸIûûßÿkñСCÝ9çœãvß}÷X~[ Ÿl³ª»-fì‡ÒE Ës϶§ËJm·ÿö#ÆÅg,ˆA Q øœ|ê–½|ëÏҘȒoóm;ÆE–F.m…€>矺E÷~?ÄýhÅ·}ö&yÆ…Ÿ1†Vd€Ï¹À§nqö­?K¶Ì’ói7Ÿº³4hke °à¨²<Ñš0`@¬þçŸ>–n-¡Ï©E(9Òé³]ÑàS¿OÝÑ>d!®·Eiñ×w¿û]wì±Çº®]»–ÝŸlÀŸÖ@IDAT³ª»lˆÔ”@–çŸm¯©QÚQ9þí3hŒ‹ÏXƒ@£ð9øÔ-{ùÖŸ¥1‘%ßæÛvŒ‹,\Ú ?|Î>u‹†oý~ˆûÑŠoûìy8ãÂÏC+²FÀç\àS·8ûÖŸ%[fÉ¿ù´›OÝY´µ²:WVÚ Z>|xìbêÔ©náÂ…%5I‹“V¬X–Ýk¯½Âxñ©ß§î ýYØÞtÓMnâĉaSûöíë&L˜àN<ñÄv-6’"Ÿl³ª;LÈ,Ï5>Ûž ã57ÿ·ã"΃‘€ÏyÀ§nÙÊ·þ¬Œ‡¬ù6ß¶c\deäÒNø#àsð©[D|ë÷G½²šñmñçጋʎ/´A «|Î>u‹·oýY±iÖü›O»ùÔ•ñ@;+O€G•gŠFÔŒ@çÎݘ1cÂúW®\é{ì±0ÝZäᇎíÞc=bi%|ê÷©»EGRš1}útwñŇ­ëÞ½»7nœÓÛ¦:|²ÍªîŽðäX@ ú²<×øl{õ-ѾñoÕ½¦jŸ•8 ¨6ŸþÁ§nqò­¿Ú¶hO}Yôm¾mǸhÏHâÔŸó€Oݲ‚oýY°4¾Í¹äópÆEF.m„€>矺EÆ·~ÿô;^Cý›O»ùÔÝqk¡!«Xp”UËÑn!pÐAÅöhÁJ[aÞ¼yîŽ;î‹ 2Ä :4LG#>õûÔíCZãúӟܲeËÂæ;Öm±Åaº#Ÿl³ª»#<9¨>,Ï5>Û^}K”_#þ­ú×Tå[‰# Zðé|ê+ßúkarê̪oóm»FåŒ!ÊB ^ øœ|ê–=|ëO»Íñm…Ÿ‡7ú¸Hû¸¥}¨ŸsOÝâã[µlÐÞz²êß|ÚͧîöÚ‰ã²M€GÙ¶­‡@ ›nº©ÛxãÃü)S¦¸[n¹%L'#Ÿ|òIþs]‹- wvØaa<ñ©ß§îd?Ò˜þóŸÿ6kà 7tûí·_˜îhÄ'Û¬êî(SއªK Ës϶W× í« ÿV˜[£‹ÂTÈ…@cð9øÔ-+ùÖŸö‘UßæÛv>.Ò>niªAÀç<àS·ØøÖ_ þ©ßVøyx£‹ŽŒ)Ž…@=ð9øÔ-øÖŸv;gÕ¿ù´›OÝi´ÏU:¢öüóÏ?ØŽ¯Ìë7:ÒŽ…@øè£Ü„ Â^ 8Ð|°N·ÒB=ÜĉÓ&Mr½{÷v#FŒÈ¿B1Ø1{ölwÜqǹɓ'Ynذaî‚ .p«¬R|zð©ß§î°“)Œ¼úê«îšk® [&‡?wî\÷üóÏ·Kúõë—·y¨Ð">ÙfUw”q@À?4û7Ÿó˜ÈúÖïßzí«ÿV»kªöYŒ£ r àÛüÝw–k‹j•Ϻo'Ÿ×%>uWËÆÔF'€o÷eí¹¤ÎYŸþǧîFŸoè?ªIÿ†Ëšóé|ê®æyM]© py§Ž4#—ËÝlÇÕ ´$ðÆoÄÞn³í¶ÛºñãÇ·,ØJÎgœáî¿ÿþX‰Aƒå?ÑÕ­[7÷ì³Ïº3fÄöwéÒÅÝxãn›m¶‰åJøÔïSw¡¾¤!O«¬O?ýôŠ5åw¿ûÛsÏ=[èóÉ6«º[@"ðF íþÍç<&¨¾õ{3\ãßj{MÕÓq( P"|›ßûÎÍPÕbõàÛÌçu‰OÝU56•A A àÛðmúµx.©6ûô?>uw”7ÇC¥À¿áßJ)ÅKÕ¿ùô?>u§Èž:$0¨KvŠ.AFàg?û™›?¾{ôÑGC³fÍr’B¡{÷îîÊ+¯,i±‘Ž÷©ß§îB}OCÞ[o½U•fød›UÝUO%€@Ådy®ñÙöŠ®°"ü[Û@q\´M…h,>矺e%ßúÓ8êÁ·ù¶]#Ž‹4ŽUÚZð9øÔ-f¾õ×Ò.ÅêÆ·µý‡"8.Šò!ÐÈ|Î>uËf¾õ§q\Ôƒói7ŸºÓ8h“?Å¿™TB|R­H@;tôÕŽª²k×®n̘1ùO¨½üòËnÙ²eE[²ýöÛ»K/½ÔéMJ¥Ÿú}ê.µÕ.w×]w9½š¿RA¶:th u>ÙfUw Hd@ޤݿùœÇÕ·~o†ë€bü[Ûðq\´M…È|›ßûÎ4Ž„zðmâêÓÿøÔÆ1A› Poðmø¶ŽŽéZ<—T›}úŸº;Ê›ã!Òàßðo¥”â¥jáß|úŸº‹SdOà“juhTº-Zäxà7eÊ÷Î;ï8¥×[o=·þúëç?»5bĈÇ”“áS¿OÝåô±Ëúd›UÝõhgúz&幯gÛëÙæ¥ôÍ'[ŸºÕ7ßúKáG@ ¶|Î>u‹šoýµµLmk÷ÍÖ§~Ÿºkkj‡J%àsð©[ýó­¿T†õXÎ7[Ÿú}ê®G[Ó'Ô+ŸsOݲ‡oýõjóRúå“mVu—Â2™&0¨SGšŸËån¶ãꈎ… @€ @€ @€ @€2C`PçÌ4•†B€ @€ @€ @€ @5'À‚£š›€@€ @€ @€ @€ @ ;Xp”[ÑR@€ @€ @€ @€ Ôœ Žjn@€ @€ @€ @€ ì`ÁQvlEK!@€ @€ @€ @€ Ps,8ª¹ h @€ @€ @€ @€²C€GÙ±-… @€ @€ @€ @€@Í °à¨æ& € @€ @€ @€ @ÈeÇV´€ @€ @€ @€ @5'À‚£š›€@€ @€ @€ @€ @ ;Xp”[ÑR@€ @€ @€ @€ Ôœ Žjn@€ @€ @€ @€ ì`ÁQvlEK!@€ @€ @€ @€ Ps,8ª¹ h @€ @€ @€ @€²C€GÙ±-… @€ @€ @€ @€@Í °à¨æ& € @€ @€ @€ @ÈeÇV´€ @€ @€ @€ @5'À‚£š›€@€ @€ @€ @€ @ ;Xp”[ÑR@€ @€ @€ @€ Ôœ Žjn@€ @€ @€ @€ ì`ÁQvlEK!@€ @€ @€ @€ Ps,8ª¹ h @€ @€ @€ @€²C€GÙ±-… @€ @€ @€ @€@Í °à¨æ& € @€ @€ @€ @ÈeÇV´€ @€ @€ @€ @5'À‚£š›€@€ @€ @€ @€ @ ;Xp”[ÑR@€ @€ @€ @€ Ôœ Žjn@€ @€ @€ @€ ì`ÁQvlEK!@€ @€ @€ @€ Ps,8ª¹ h @€@G üéOr:u å¶Ûnë¨Jއ dž@#úÇ[n¹Å 80”Y³feÞŽt€ @€ ¤‘@—46Š6A€ @€ @ \ .t³gÏ[±bE'@€ @€ P9¼á¨r,Ñ@€ @€ @€@ œ{î¹nðàÁ¡¼ýöÛÔÈဠtÀ÷¥Û>´(L€7æB. @€ @€ @5 ðÑG¹3f„5óƺ@¨Sø¾:5,Ý‚@à Gun`º@€ @€ @€ @€ J`ÁQ%i¢ € @€ @€ @€ @uN€Gun`º@€ @€ @€ @€ JèRIe肪G`öìÙîÙgŸuú¦ë†nè6Úh#·îºëºN:µ»Ë–-so½õ–[o½õÜꫯÞn=…\°`›9s¦{ï½÷\ïÞ½ÝàÁƒÝZk­U¨h‡òÄeÚ´i®W¯^y.={ölUß;3o—¸m¹å–®k×®­–/ugZÚQj{)@ -|ø7õmùòånÆŒyY¼x±[guò¾Sþ¢#ÿV?Û›q, ¬ðá#}ùG1öí#s¹œ{ýõ×ݬY³Ü[láúõë—UÓÒn@uMÀ‡ÿ*XG|Fšžñ¥©-åÚ€ò€…@üžX—ãûV¬X‘fúßÿþ×é¹éˆ#ÜСC]çΕ{o >¬QÎú 2 Ødu³ ¨)S¦ä<ðÀœ-,ÊÙéÚBìÇÓÜÿþïÿæì‚ ä½üò˹ÓN;-·ÓN;åºuëê´EG¹3Ï<3goóºl1Rî;ßùN(Ï<óL›uØEJîºë®Ë=:·Ê*«„ºƒ¶oºé¦¹±cÇæÞ}÷Ý6u©À?ÿùÏÜÖ[oÊ#<’?náÂ…¹Ë/¿<§6ºƒíÎ;ïœ{øá‡cúÕ®ßþö·9[`+¿Új«å¶ß~ûÜ©§žš›?~ì˜h"-툶‰8 ,¨„»çž{bsú­·ÞšGb ]s?úÑr¶È5¶_~™æ¾ô¥/åž~úé²ðáß>»ñágË2…!Ô9ŽúÈjúG™¢’>òßÿþwxï§ûÀ§žz*om[$•»øâ‹s¶h8ôí¿ÿýïÑ0nܸ0_þ~úôéá¾BÝOvØa±ºŽ=öØÜ§Ÿ~Z¨8y€ Pöú¯ßüæ7á|Ü¿ÿØ|¾ù曇û~ùË_ÆZÑ^Ÿ‘¦g|ijK . @h“@{ýžWÛ÷E;óâ‹/æöÝwßü3Òà7µ`k/%ÈûÝsÎ9'·téÒèa-âø°HÈ€@#hóFûƒ‘bÁQ# úZS×_}NÞÎØ6E oJYtË-·äÖXcVõiν÷Þ›_Ä­;ø!·”É“'·XÐ=>ïÓ§O~aR1]A~òa¹ÚõÆoä>÷¹ÏµÚÕ¥¾*hqÓ®»îÚfyý€úÉ'ŸUǶiiG¬Q$ d”@¥ü[rn–Ÿ’/,¶H7ê‡V]uÕܵ×^[Aü[áëJúÙ’ A!@ @ >²ZþQ樴Ô£¨¿ž8qbÎÞšTð~®½ Žtϧ?‰Ö3jÔ¨Üܹs`„ÑE@~tÄuÖY±99:?GãÇ|¬ñíõI?Y«gêLšÚƒK€Z%п'ÅÕö}ªS/8æ˜crö£’üî6Ûl“{óÍ7uhÁ€+ˆ…L4 •{š]ñ ÊÐ+îÍñ»o}ë[nÑ¢E± Ö\sM7`À€Xžz5ᡇšÿÜZ‹–auêì->îk_ûš³¿æ,T$̳•ËîCqwß}w˜×Vä‰'žp»í¶›{饗Z-ô©¶yóæ9û RwÊ)§´(ßZ†ú¹Ç{¸ÿüç?­Ëï³î…^pö& 7iÒ¤6Ë?öØcÎÞ&åÔÿ¶BZÚÑV;Ù@ M|ø·hÿ^{í5÷Å/~ÑéÓ™Ñ`oÜ‹&óq}Rô¤“NrÏ=÷\‹}Ñ ü[”F<îÓÏÆk"@ þ øô‘>ü£,R )._þò—KºŸ+e”Øb#·ß~û9{#nX|»í¶sÿøÇ?œîµ € PŸþ«¼–4}R»=>#MÏøÒÔ–rùS€@#H“ßïrî—ìmðîøƒ[¹reh*}¢zäÈ‘nøðáÎÞ æ+òì³Ïº­¶ÚÊ=ù䓱üb |X12äC-ز,ÞpÔ(kÓègÍ\uÕU±ÆúüËO~ò“œý€¶ÉìäþøÇ?æôI5;QC9è ƒÂ2ш>'-§7;|ýë_ÏÙƒÕüëæ§Nš›0aBþµòA¹ä'ÑŠ½áHmI¾òXo ºë®»r3gÎÌ7C¯´¿í¶ÛrGuT¬ªë׿þu´©±xr•tôO¶x*÷·¿ý-7gΜœÚà 7äô椠ýÚvéÒ%LÛäÜ¥—^š{üñÇóo=² ¦Ü~ðƒ¯ŽT;“!-íH¶‹4 ,¨´KÎÍÑ¿ÐÙk¯½r<ð@ÎnvóÁ£70\y啹îÝ»‡~A~BŸ--ðoÕó³Ål@> F!PIéÛ?Ê&¾|dòm¶8æ· ”;à€rzËÅC=R>©öñÇçôVÛèýâŽ;îØê§µÃ ˆ@€@A•ð_o¿ývîùçŸÏ‹>w§ÿò—¿„ûf̘kC{}FÒOÖêY£:“¦¶Äà’€ ‚*á÷¤¸Ú¾ï¯ýk®S§N¡ÝvÛmsö$±>êSÙz~º÷Þ{‡åä“U¶PÀ‡¢B†ŸTkSÓÑLÐëâ×^{íСk±‘.Š…÷Þ{¯Åb]¬Dƒ¬Ú[‘Bº‘~ðÁ£Ebq½š¾[·naùàF¿Ø‚£þð‡±²z-£½™)¦3š8÷Üsc嘳•ØÑ"ahÕª_ýêWcþX/.H|X’i45”¹élæüô§?9r}˵­ 7ûbµÕ›Š¢!¹Àçšk®‰î.×›€¢:/´àhÚ´i±75ªèâ¡hEz³PT¿ÞBQ(ºh9ýôÓ  ó’’õÐÀ>ÁîOF>ýôÓØ›ôv¦dHK;’í" @ +|ø·Bsó 'œÐ&{Í~Ì=òÈ#-ŽÁ¿µ@føð³¡r"€@¥}¤Oÿ(óøô‘…~<ÖýÙ‡~ØêÈhmÁÑG}”ÿ«Üèý§}¦»è‚ãV+b' „*í¿¤¸£?º–â3 ùÉZ1x`I ‚ì³kNr¶j;ÔU(bŸf ³7Úh#·õÖ[‡éÖ"ýû÷w»ï¾»›8qb¾Ø½÷Þëì3lNõ¶ìÓh®OŸ>­qz  ›o¾y4Y0ål=[°L43-툶‰8 ´ðáß õÕ¾)^Ò’ýúõ‹n¯Ž¥•À¿µ@fTÃφ• Pçªá#+éeŽjúHÝ_jP{ÂܹsóǾð ááûí·Ÿ»ûî»c°î$@%¨†ÿ*¹1ÍÛë3ÒôŒ/Mm)—?å!Ô34ú=ñ.Å÷uîÜÙé7²à¾èÝwßuǼ»úê«[ý­ð´ÓN+ˤø°²pQ™'À‚£Ì›Ô+{5}¬kûï¿,ÝZBo$*’:µˆ©Ô°Ùf›µZTo„˜7o^XÆ>§ÆK‰è"'Xp¤·$MŸ>ݵUçlЦj½±(´ªœ ßm…´´£­v²€@$}Q%ü[¡~ :´Pv‹¼è"SíŒ.öUÿ& ÅC5ülñÚÙ@ ¾TÃGVÊ?Š|µ}äÈ‘#ÛepµSl3yòäðx½a÷Æod±QH„ ö¨†ÿ*·uíõizÆ—¦¶”ËŸò€ê™@ýžx—êûì“Òá‚#÷ûßÿÞ=ðÀîè£vGyd~A’ò;ða¡Ç±ÈeÏf´¸A$/Z† Öáž'uê“j¥†Áƒ·ZtêÔ©±ý/¿ürþ%–ÙJâÕW_í5kV› ŽÚjSLasb½õÖ+”Ý¡¼´´£Cà`@U"ôE•ðo…šý#MÏøÒÔ–rùS€@=H£ßïR}ßyçç&MšûÔôìÙ³ÝE]”}‘d·ÝvËŽZo…m?jÏ1@>$}Q%ü[¡v8°PvÙyø·òùð³åµ€Ò€²K >²RþQ”«í#»tiß#¬äb£`„Œ7Î}õ«_ÍÞ;Èc @娆ÿ*·UíõizÆ—¦¶”ËŸò€ê™@ýžx—êûz÷îÿÚÈ¡‡~u$j/½!ö®»îÊ‹òõ%’Ã?ÜtÒI®_¿~Ñ¢Eãø°¢hغ$Pù_Þë‚@õ è“bѰÖZkE“íŠ'´öéÓ§d=m]¬Ì˜1£d]¥\²dI›ÅVYe•6ËT£@ZÚQ¾R Žðáß µ©-¿Uè˜Byø·BTȃ ªá#+åÕÿZøÈŽp?ꨣÜüãPE.—sÇwœ+åÞ3<ˆ ´ P ÿÕ¢ROizÆ—¦¶xÂZ@™$P~O‹Ž|ðÁü›Ž¾ño´ºè•W^q?ýéO^Jpýõ×—d3|XI˜(º!о?«›îÓ¤—@r¥ðüùó;ÜØ5ÖX#¦ã£>rk¯½v,¯Xâ½÷Þ+¶+Ÿ?hРØþN8ÁýÏÿüO,¯œÄæ›o^NqÊB€@Føðo>»ŽóIÝ€ %€ôwxê©§ºË/¿<ÿ)µÛo¿Ý½þúëyôÚžþùî /Œš‚8 ”A kþ«Œ®Q€ Ђ@=ù½]vÙÅIV®\éžzê)÷ÐC¹‡~Ø=öØc.ù¥õ pp@ .d@K€Gk{zžrǵpæÌ™n«­¶Šå•›H¾ÑH‘Zê‚#ÕßZH¶·k×®î _øBk‡°€@Ò_T¿ùĘl/þÍ'mtChlIŸƒ¬ÌxøùÏîÎ=÷ܼ²ÕV[Í]uÕU±{ÕË.»,ÿ‰€ŽÞoW¦µh =Yó_Ù#L‹!@ MêÑïuîÜÙí¸ãŽyÑ[a—.]êyäwÏ=÷¸ &¸ äM°bÅ wòÉ'³à(M’¶@ Xp”#Ð"¼hI¾¦±Ð1Ažþ›o¾™OêMA]tQ>>xðà H~«ØÛn»m,¯XâÿþïÿŠíÊç'Û;uêÔV˳€“@Ò_T¿ù$™l/þÍ'mtChlIŸƒ¬Ìxøú׿S´÷Þ{»¯}íkî–[nÉç/_¾Ü{ì±îé§Ÿv•üä\¬R€ê˜@ÖüW›‚®A€@4‚ßÓjì³Ï>y9묳ÜèÑ£Ý[o½•§«íûï¿ïú÷ï_ÚTd@ç,4’6B  $/Zî¼óÎ’0Ìš5Ëýîw¿sýë_ó¢ ƒ l¿ýöA4¿½ÿþûcéb ½NñÞ{ï-¶;Ÿ¯7%黯AxöÙg[¼r1ØWh{ä‘GºÍ6Û,/»ï¾»Ëår…Š‘@'àÿùD‚óIÝ€ %€¬Þ= >¯}ð /¼à.½ôÒ¨9ˆC€@‰²æ¿JìÅ @ dÙï;6ü.ù{aÁÎZæ!CÜ)§œÛýÒK/ÅÒ$ Æ&À‚£Æ¶?½O1í¶ÛÎm¸á†a 'Mšä¦L™¦‹En¸á†Øb/~ñ‹aÑvÚÉE éUˆú¬Z[aܸqî7Þh«XìµôsçÎu×^{m›Ç¨Àĉó]úŸÿüÇI>ÿùÏ»N:•t,… @ [|ø7ߢŸÅ¿ù¦~@KY½{@-(¾à‚ bƒíg?û™ãM†1$$ ”D ‹þ«¤ŽQ€ P€@–ýÞ:묓ÿ N¿Ãé ¯¥¾U7ú²!8p`2dAJ€Gjyúz]»vu¿üå/cí<í´ÓZ}kÐ+¯¼;fÍ5×tÑUÊ}ûöuz“P–-[æ¾÷½ï¹%K–Y-¶ºè8ûì³[äÊÐ_„vïÞ=ÜuÉ%—¸9sæ„éB‘E‹¹3Ï<3¶ë¨£ŽŠ¥I@€@ýðáß|ÓÁ¿ù&Œ~@|duÇÁñÇ»_Ö}ñqÇûžê¶ˆÚ d“€/ÿÕ¹sü§‹¶ž1f“­† ¬ðå÷ÄÁ·ïÛvÛmc¸¯ºêªXºXâïÿ{¸«Gn“M6 ÓD įÚᤊÀá‡î¶Þzë°Mrêûí·Ÿ›?~˜Dþñä÷EwÞyn•UV Šä·?úÑ\¯^½Â¼ûî»Ïí¶ÛnîßÿþwìÁê¼yóò¯”ßc= Ö*ˆDìÎ9çœ0GŸwÛf›mÜsÏ=æE#Ê5j”{ñÅÃìcŽ9Æí¸ãŽaš ÔþÍ'%ü›Oºè† (|d”†ß¸æ_}õÕ±{æG}Ô]sÍ5~+F; :$àÃé- ÑpÑEÅž]F÷‡ T“€¿§öûö}#FŒp#GŽ Q]vÙeîÇ?þ±ÓË …•+Wæ_rpÛm·…»õeraT¸“ к4d¯é42B@ŸûÍo~ãöÝw_·`Á‚|«yä׿·å–[:½ºQ Œ´XHo"ІC=Ô}ÿûßfåãm´‘»ùæ›öúé§ù¼gžyÆm¾ùæ®OŸ>ùï·ês1z•âÒ¥KÃãO>ùd÷Ûßþ6L‹èmEãÇ_E?sæL§O¹iá”.d† æ¦M›æôWµ9z!£‹õ—@õMÀ‡óM ÿæ›0ú!@@ð‘ÕºG=å”Sܯ~õ«°â³Î:Ë3Æ 4(Ì#@­ðá¿>÷¹ÏÅ*½óÎ;]Ïž=Ýúë¯ï>øàØ[ÞcI@€<ðá÷Ôdß¾O …ÆçvØa§ÅD’±cǺ{ï½×éåzsÑСC݇~è^{í57a„Øg×´ ª”ß =ãG= 2,8J™Ah’ô¶-ÌÑ´¾«ª E:Ï>ûl^’å•ÖŸë®»®Ð®|Þ˜ëÞ&¤ÅFAÐ[üñ ™ßê I¿øÅ/Ü®»î»Ðk# …ÕV[Í=ùä“î„NpwÜqG¾ˆ6=ñÄy)tŒòô ÷®»îr«¯¾z±"äC€@ðáß|âÁ¿ù¤‹n@ˆÀGFiøÿüç?Ïß»ê ½ ü±;ñÄÝý÷ßï¿rj€ PG*í¿‚ÅŸÁü,T .t¯¾úªûàƒêˆ] ,¨´ßƒjø>}VíÜsÏuºÊåryô/¿ü²“´ôÛÝ7Þ˜!BkåØ4>©Öx6ÿÿì ¼UÓûÆß””JMš%„’!c*ú—y.S2•™BBüÌSeÊ,2F„¢B!4(B%$4'iÀÿ}ÖqnçÜ¡{îpî=çÞïûùìö>{X{­ï¾}öÚÏz^Zœ†š6mj'N´SN9Å6ß|ó[ШQ£ÐQ:~üø0â'Ç}CóæÍƒH–‰úaT©R¥¸Ý+T¨`Ç{¬ÉRþšk®±?ÿü3n»\–rŠjÕªÙСCmðàÁ¹ÖCûÊ5B"¥úõëçT$ë!@ HÆý-™˜¸¿%“.eC€@,4’»\¹re»ÿþûãN2bÄ‹M·‘€ #¼©TßÇ7Îñ|l€ '¼ï©EuïëׯŸ}üñǶûî»çŠOnN]ºt ŽGíÛ·Ïuv€J2i²+‡øñ] RÇBy# 4gJG&‡#)ŽkÖ¬ii’KP¹rù3.“uâ¬Y³LéÔTf:u¬bÅŠ•>|x EWÈmI?¦r ¥‚›2eŠMž<9LóçÏeËž~¯½ö Šm¹F€ Pº $ëþ–,ªÜß’E–r!@ 3î‘™‰ð€Ò@aÝ¿þþûo›3gŽÍœ9Ó´¬~K½ í·LÔ€J6ºï‰RQÝûtž·ß~;¼Ô½VÓ¢E‹BúR4hÐ ì¹çž%ûâÑ:@  ê"8*>Ž…@)"ð¿ÿýÏn¸á†Œ˺¸zõêŸY€ @€ @€ @€ @ T¨›?+”RÁ†FB äZyÔ¨Q Óˆ –-[f|ÞÔ„ 267lرQ  @€ @€ @€ @¥‹‚£Òu½im)'P¶lY»ä’K‚-¢PlµÕV6wî\«Zµê&É(ÚG}”±ÏqÇ—±Ì @€ @€ @€ @¥‹Àf¥«¹´èСC„•+WÚÃ?œñ9»…Ù³gÛ‘Gik֬ɨ| 'd,³@€ @€ @€ @€@é"€à¨t]oZ ;þøãã(Üpà ÁõhÞ¼yë×®]k'N´ûï¿ßÚµkg‹-ÊØvÎ9çX«V­2>³@€ @€ @€ @€@é"P¦ Íý÷߇øñ] RÇBEOàî»ï¶Þ½{g9q¥J•¬N:öóÏ?Ûºuë²lßm·ÝìÓO?5íG@€ @€ @€ @€ P* ÔÅá¨T^w]Ú ôêÕËn¹å«X±bŠÕ«WÛ¬Y³²uÖYˆâhñ€ @€ @€ @€ P: àpT:¯;­†@ °dÉ{ä‘Gìù矷9sæ˜R©ÅÆöÛooÇwœvÚi¶ï¾ûÆnb€ @€ @€ @€ ÒI .‚£Òyái5²ð‰¶páB›?¾U«VÍjÕªe*TȲ+ @€ @€ @€ @(Õê–+Õͧñ€@2eÊ‘‘„F @€ @€ @€ @ȉÀf9m`= @€ @€ @€ @€ Ìe&Âg@€ @€ @€ @€ @ GŽrDÃ@€ @€ @€ @€ @ 3r™Wð_ýµ1š4i d˜1c†Õ«WÏ*W®œ±Ž…ÒM`É’%¶|ùrkРA‰1yòd»æšk¬R¥J%ª]¥½1?üðƒ½ôÒKÖ¬Y³ÒŽ‚öÇX·néþÖ¢E‹˜µ,BÀlÒ¤Iáï¢lÙ²%ÇÒ¥K­L™2Ö­[·Ó¦ÒÞùóçÛã?n»í¶[iGAûcüý÷ß6uêTÛ{ï½cÖ² ú-\¾|ùƒcÅŠöçŸZ=JL›J{CÔÇп~Ÿ—ö?„lÚ_ŸgÓLVå‘ÀôéÓ­aÆV±bÅ<™º»ÿñǶxñb»üòËS·’Ô,_Fe3gδvØ!_ÇsPÉ#ðï¿ÿ†þ§½öÚË6Û ’w…ó×¢_~ùÅÊ•+gµk×Î_)xÔš5kLíºúê«S°vT©0 8* Š%¬ uN>ÜZ·n]ÂZFs B`üøñÖ¼ysÛzë­ R Ç– ¿ýö›-X°Àôƒ¸$ÅèÑ£­gÏžŽJÒEõ¶|÷ÝwöÚk¯Ù¢E‹JXËhNAüõ×_¦û›^lˆ% ŽÀeË–…üØõ鼬ûöêÕ«¥óEÌT÷¹sçÚ°aÃL"pQ6l°±cÇÚªU«¢«˜C ÐßE›6m¬B… %†Èï¿ÿn_"8*1—4¼dõÕWù}^r.i¡µ¤$þ>/48¥¸ ?ü0ôKV©R¥ÄPÐsè¬Y³•˜+º±!ú-6mÚ4Ûe—]6®d©TàHï"V®\‰à¨Tÿ%Ä7þÛo¿ ƒDJÒ@õOH{€à(þZ—¤OŽJÒÕ,¤¶Ha­/²R‰StîÜ9<èàQ®fá´á7Þ°1cÆ”¸ï ëJÒȨ¹Úé_J:ulûí·/q¯éeŠ·MêþÆožâ½©xv9}Þ}÷ݶå–[¦bõòU'9˜Ž92_ÇrPjØvÛmm›m¶á;,5/O±ÕJÂB¹qo+¶K²'nÙ²¥Ý|óÍV³fÍ”­c^+¦Írz#J‰$Šã;¬ä\ÓÂj‰~Ÿßu×] +, %¤œ¶mÛ—òÆ—™Éy½_¿~%¦=4d#¹qU«VÍ®»îº+Y*ÕþùçŸ @»÷Þ{K” i©¾¨…ÐøÛo¿=?\xá……PZj1{öl;ï¼óR£2Ô")ðhK V … @€ @€ @€ @€@É$€à¨d^WZB' QåË—/ôr)0} Èõ¡zõêéÛj”zÊ^’Fù—ú ZˆjÕªeeÊ”)Ä) €@ÑÐw—¾Ãd& ß<úíC@HGµk׿;,/\’ë¼ÝvÛ•¨4ØIÆEñ€@ #?XU«Vµ’”*4¶m,—\¤T+¹×––A P <ñÄ…Z…¥?víÚ™&€@º¨Q£†)ÍÌ”¢…€ Ž4(`ܸqéXuêœd¤ÕL2`Ї’J€{[Rñ¦má/½ôRÚÖŠCÐ`€÷߈#УG¸Ï|€@:`hS:\%ê@€ @€ @€ @€ !€à(E.Õ€ @€ @€ @€ @€@:@p”W‰:B€ @€ @€ @€ @ E 8J‘ A5 @€ @€ @€ @€ ¥ÃU¢Ž€ @€ @€ @€ @HŽRäBP @€ @€ @€ @€ ¤Gép•¨# @€ @€ @€ @€R„‚£¹T€ @€ @€ @€ @é@ÁQ:\%ê@€ @€ @€ @€ !€à(E.Õ€ @€ @€ @€ @€@:(—•¤Ž€ @€ w³fͲ1cÆØ!Cl×]wÍ{@€ @€ @Ȇ‚£l ° €J•+WÚ¸qãlÍš5¥¯ñ´€@ ¬_¿Þ>ÿüs›8q¢m½õÖ¶óÎ;ÛN;íd;ì°ƒ•+ÇãÈ?ÿücË–-³ 6˜–ÿý÷ß0×òßÿm .´ü1cúé§ŸÂòòåËmÇw´ dLõë×\§M›DFiEÙ²e­fÍša™ @€ @€ @%@A r< ¤ ½|•“ÃìÙ³Ã|Μ9VµjÕðr[/¸£S•*U‹]½ü~÷Ýwä—ázÙ[­Zµ”i Ž$”™2eнÿþûaúøãmõêÕYš"LݺuƒøèÀ´^½zÙV[m•e¿t^¡ûÊÏ?ÿl?üðC˜~ùå[°`ÍŸ??̵üûï¿aQ¢íÔ=L÷³í·ß>ˆ‰¦NJÙß°aCëÙ³§µoßÞþúë/ûàƒ²Ûu€ @€ @€ <@p”gd@ 9æÍ›gcÇŽ5½8”\ ¢S:ul³Í6KΉS¬Ôµk×f¼ŒÕ ÙèKYÍÿøã Ò \¹>h®iÕªUAd´xñâ„ZS½zu[·n]8NH”ôÿ÷Ö®];8p`Be° ’H@N;QqŒÄ›ÃT®\Ù$r‘H“–µNÎprß‘hFStùÛo¿5 @[l±…í·ß~vØa‡Y›6m‚ðHŽ;šäÚ£ùW_}e~ø¡=úè£Ö¯_?;ï¼óRÂùHm—@H÷‰£äÆ;é>²téÒ,“ŽSÛÄOb#ݧ2Ç–[niµk×ÎDp€m·Ýv¶ùæ›[™2eÂý^÷üèò¶Ûn›!˜•ÐH÷°ØP=t>‰luítN $2ÒþÑ1bDt‘9 @€ @€ @ À!@ȉd”Â+ê°óÝwßåX^B*õÌñÇo7Þx£UªT)Ç}Óaƒ„CsçÎ .Dr$Šu%’ðJédr ½€}ñ«e½¸mÚ´©5jÔ(¼dÕ\“RËè…xôE¬æÑIÇzè¡Ad´Ï>û„2uÎAƒåtjÖCHKÍÜ{ï½öÚk¯…ïº *XÅŠ3&‰‚$’‘XEšü†¾WkÔ¨a»îº«rÈ!á;VboS!G¤gŸ}ÖúöíÜxxà»ûî»­S§N›:,ám+V¬‚¦>ú(žTŸØI,$Ú‘ø)vÊΕ)Ñ“ê>­{PçÎ3ÒI$!q­Zµ‚h+ѲrÛ¯|ùòÖ¤I“0å¶/Û!@€ @€ @…EÁQa‘¤@1$˜‘°eúôéöÛo¿Ù¢E‹Â¤ºÑe‰l¢®uëÖÍ?üpÛwß}mÉ’%Á¡@.šôtÆŒáì+¯¼b<òˆuèÐ!挅·('Õ_Â…æÑ娛…Ú '‹h[äd¡}äÈ;éxµEûÆNþù§6Å…\†ô2vÿý÷ibäüy’³F^žtŒRö(]@ 4ÓÐ]wÝeÏ?ÿ¼­_¿>RäN´fÍš w"-+ÕÖ6ÛlcÍ›7ßà 4"}'K#á¾ÿ%”Õ\“„£*KÛåʧ¹œwòú­ë¡cÎ:ë,;餓ìž{î u–P§mÛ¶vÇwX½zõ‚ Hm0(: N%:NO©¾ãÇÏHé¦ônº·%:^¢ ¥vÚi§°,AOÔQOó¨ÃžÄÀâ;)-§‰äXD@€ @€ @€J2G%ùêÒ6@ OôñÅ_´×_ÝôrQ/R£S4…Lô…¦Ü´uˆ€F)a4)%Ú´iÓ2ÒuÅVB/UõbRrnÀH“œ bC)PZ¶l»ÊäñðÃ[Ÿ>}ìˆ#ް®]»ZÿþýË͸óñA¢&µ[Ó„ ~1›è©ôRVmÖKi9i¾ýöÛ¢¨/g¥É~€@i& {Á¯¿þĬréÑýI‚MÍ•îKñÅ_Øí·ßnÇR¹ ]sÍ5IªÖõÐ}õ†n°sÏ=×®¿þz{úé§­U«Vy*>*x'…DPÇ{lp[RZ7Ýk$°Š$º; ›$tŠlótbv† @€ @€ ”2ŽJÙ§¹€@VrJ2dHx9;{öìà´}Q™uïÜ×HP¤¤{ì±G˜ä^$±&½ø”#C~B/Q/ºè";ú裭GöÜsÏÙ¨Q£lÀ€Ö¥K—<ùÍ7ßdˆŒ&OžŽ×Ë^‰™ôâZ!§£hz3͵>Ú‰†¢""9:h»¸ÅN*CÛ4ñW4@‘ïÖùóçg¤xTŠI9çè{^÷ˆØ¹\…¢Nwr»SÚIÝ·² ‰`+W®Ò£é;÷¨£Ž B#9ç¥SHôóÄOØ%—\bO>ùdÁJ,ñªæÑe …%øÍ<‰ŸÜò$0Ú}÷ݹÿ¤Óŧ®€ @€ @€ 6¥Í¥¢¢€@aX»vmpOPº½Ì•(榛n /8õÂV/y3OÑ—šrCвæšôt·Ýv³-Z„ô]…]רò$`zë­·ìå—_u•Óу>h»îºkHi›ÞFi]”ÊlΜ9aúá‡2æJu¦@êÌ3Ï íÛ·®M±çc€ F@bV¥Ãü裂ÈH÷9ìä%¶ÞzëÞ«cÇŽ!Õ—\ât‹¦8Ó|ÅŠá³ô®ºê*kÖ¬Y^N‘rûJ,4pàÀ”«‚ @€ @€ @À Á€@ÚЋT¹TªTɶØb‹,õÖË[¹?DÅ5šÿòË/ÁqG‚ ¥K‰Îå~0räÈ–FéU”z¦gÏž!…Z´à¨3OôsªÍO>ùdk×®õêÕË^xáûì³Ïr­¢/ä¡—Ðr`:æ˜cìàƒÎHÓkì@ Ð=hèСaš2eJ8FD;í´SpÞQêÌè¤urí‘Cœîs±s9Ïí¸ãŽ!mZB'f'@€ @€ @¸†ÀÑ@IDAT€ PdN$N@/Y¿þúkûþûïmÖ¬Y6sæÌŒùâÅ‹3 ’`H/aõòVs¥—Qzšhú¯èŽÚO¡r3‡„7÷Þ{¯]pÁ¡ŒÌÛÓá³Ü‰”nFÓòåËmÁ‚ÁÑHsMb&AUýúõ­Aƒáåv… Ò¡iÔ€@ZX½zµ}ùå—6~üø®rÒ¤I¡þ¯vëÖÍN<ñDkÛ¶m¾¦Uè, @€ @€ @Ȇ‚£l ° (zr‚…AÅG`ùòå!µÙðáíråÊ&‡"9ëuíÚ5×JÉ}ïÿ‚xíµ×¬cÇŽ¹îÏ€ @€ @  4øI} @HŽÒåJQO?ÿüÓ¦Njûï¿ÂgüñÇmĈ!ÍŒ^îjZ±bE˜ÿæ*‘o¿ý6”µÅ[XÛ¶m­sçÎaR šDëd·ÝfÖ¼¹Ùµ×š;N$zdâûýû¯Ù#˜½ð‚yJ³ã—(ʬL™ÄËHÆžýeöñÇf|`îþdÖ°¡yª¹ÈÜ 66:V"Dã›oÌ~ùŬC‡âow´Î®W³~ýÌž}6Ò–K.1w*1w‰î‘ø\Ïëb¨pݧó3{øa³9sÌÊ–5O‰d6yòßÚ>ìÃ?€@úøòË/í¤“N2Ý£N;í4»ýöÛ­I“&öÄOä*8ú×oɹ¨ƒ¾ @€ @€ Ê0tèÐÐ1~üxkÕªUÎB‘€ @ 9%‡+¥B ¥üþ»™gƒÉ5¾ûî;;î¸ã‚@è½÷Þ³Ã;,×c´Ã 'œà"Éqû*-Z¥J{º›ÑóžvfKÛgŸ²vÌ1u­M› A,“¨ˆçï¿Í®»ÎìÞ{Í6l0{ås§$³çž3qwÊ}ðÁ#Ö­›™7ÛÊ—7óg;»ç³:u""Çb¥èD~ðÌ™fÍüô“Ùî»›?PÆ—(áÓ”)fï¾™T—µkã÷‰~rÃ;ê(³çŸ®‰Ì/¼Ðì±ÇÌGĘ]u•ÙÝwÇoÏüIç»åó4wf:ÿ Af\y¯¢ý¼h‘Ù­·FD`ëÖ™‹ÕÌ´îŽ;"ëÔ®Ë.3ÿ;‹¯—ÄiO=YwÿýñÛÎ?ß쥗ÌjÔ0›?ßl͚ȲþÆÔ^iàš7ŸŸ ´#ðÀøwßU!Eç£>jçw^hƒîq/¸ªtÖ¬Y~/råf1vìX“;_ß¾}]ŒèjD€ @€ RMà/Ù)qìjZã‹Ñe¹*7ôQ¢JÉžHh ÓG}DFrb^½zµU¬XÑŽ<òȰœHì@€R@¹T¨u€’G@æB2+’0ãÆs>FQœsÎ9¦§råʹøä–„G£Gb£³Ï>Û.¿ür«ZµjHV¥J;ùä2A $—‰„4)äÊ£ôXQ§™ÈÚìÿÕ{Þ3ÌZ´ˆ8ÑxVœ 8Ùk¯ˆ©0D1O>ivÅf+Wš¿”Žˆs¾ÿÞšWËå[mµUI|¤IÎÉË–- Ç/ôÉh™Ê  õŠýöÛ/ô?œ|òÉ¡o£_¿~a=ÿ@€ t €à(®u„@¸þÇ4ˆ¤¤r£B*6ÅÖúõë==Uo0` ÕªU3 qiTal¨“îñÇ÷{‡ß¶d‰ç­²]ŒãêseÇìÙ®R²³ýåîý6eÊÛsÏ=ÃúÌÿÜzë­î޳™‹œ\åJGöòË‘ÔVÙ¹ÌÄìš±¨ôYr§‘cÑÏ?g¬ÎqAb¡gž‰¸ñ(õW‘ôc™G>˜ÄzõŠ#³¦XÁ‘øÈáGiË’}úDÒ³)œ\tR!ä ¤”vaeç ¥c>ÀÆ”~¬8Bn9üÉGu8' PÈVzÞĨÐH#ûì2·ûꫯ<ÝäxûüóÏ=­â½!¥™DÉÖ\¡Ï—ºÙÿ¹*Q¢$6Ìkœé*Ó¾ž“QiÓ²=é¶yqxlaÙÚ嵂ì@€ @(%$z×GF¾á#d%Rʱ¢ XR„FÀTX¡þŠ]ܾ]@€J2G%ùêÒ¶A@.®Q±‘Ür”òjРˆ GîAÑðTÒævÔQfr2ŠŠ´]/t?þøc[¿þ#ÛyçJîrt­]u•«o̰Ê!Õw”±hª5‰rt—ç˜R¦½òÊ+úz1,·‰“<·•^ÇF¬»QìúM-»IEH–S°œŽ=ñDsw ³ äv‘u/±ó1Á)'»A)ùÉ%JŽH÷Ü“ý9U §´]"'9LeW·¬µ-º5Ûn›ó¹äô”“ÛSÎG±€À¦ ¬ZµÊî¿ÿþ &ZæörJm6пL»téF êèÝzí[·¦Ó=ë#ÿò”øHŽG;v "# Ž µjÕ²Î;‡ÎL‰™êÅäfÔù”²íâ‹/ö{b…‚žŠã!@€ @iCà?þ°§žz* úÙÖ;åÈ;ß:³ }-Ûà#c?üðî|ž[¿WõŽÆØIÎAûHÈQ£F±‘\Š»¹ýyççƒ ³©¯Jc”Î,º,Gc•©Iç.¯_¿ÞV¯^mj›æÑI›ößï»U9@€ _Ù¼žÏoQÔ"àÙPܶ4>U”>û …B lü¥»!˜»%˜Û­æ~ ‰‚”jë ͭ\³ß_b#¥Ö’³‘ÄEr4RÈæ—_ÌÓ˜E>ë_¥ ó g!…ÚªUËýaí#ûàƒÂ4}úôŒœÑzH<ðÀu6uêu~Þ öÜse¬mÛåhIî67Þh~ìOöÚk¯…—¿™GcÜ.«$k•+&äNäN´¡ÞEõ¼æŽ´}L52•‚NSa†\¤$8Úi'sWެ%+ÛÒ´)mšœžRMl”µÆ¬ \¯¿þº]àvt©Ø A»ÏmíN?ýô ¡Qôìê lÖ¬Y˜Îæn,Äù¹çžkª“ÜŒnŠÞ\½|¹)Αe @€ @(”ªìé§ŸN? ,ȱÅ )íX«V­Â´[ÛGñHÀ3f̘ЗüÖ[oÙÒ¥KC9Jq&ñOv¡TéJ§~ôÑG‡içwÎn7ÖA€ ¤0G)|q¨ZÁ b>"ÂlØ03¥rà Ф"{è¡ì\” ìwÌ<Û‹]q…{ÿTνÚ¯ÿÈ~þ,\zä2äïQ­C‡œÅ&¸¡T_rÁÑä®­q‘ØH¡%K–„´z [° œ‹YÊ…Ï¿¸iܸqA`¤4hzPTÈÉáD·Rê™ƒÝ H/rõB7·è×Ï<_õi.>ºßS¯Ýî©Ú\eó_Ìš5+¸yä‘ÖBùÂbBNEb¸)˜ÝÓr±wo³ÁƒÍÄH×-¶­>hÆ]ŸÌܼ#¸ÅŠÂÒ²±ETi¥xSš@1=âˆ":)§’N@Œ]t‘ Q_tñgõ èQJ3Ý»Š3:ø zÿ‚V‡ê®°Õ(Ir|ÉÕÀê<Ýc=гzœ€ @€ P$Þ{ï=ï¿Â¦M›f5kÖ´Ç{,ô÷.^¼Ø~wK}MÑå~øÁ¾üòËÐÿ­\  Ú´iS›4iRx®Öú=÷ÜÓ.¿üòª\nEr0ZáݱÓ:-,‡¡m4b“€ @H[Åû¶'m±QñT' ­ÍwFDEQ÷‰Bäôüóæ©ZÌ$HòÁ.Ò1O ™ä€:u̺w~Ê~.s‰\Ë\}TŽÊ:4âl㮳vØaç!¥õ’ Q4$H’ Óÿþgžê,º62Ï,6:ï¼_í䓯ðr½à\BV·Ç»ÍÒ¡‡&=ðå7Z·níîGmËb9@DG™Üép%hêÓ§O¶E‹sI¥aSÊ9 Ô‰©Í#éZ_sy  ô¦àYó‚CÓÍ7ç,œ+¬>÷\„›§m' Bà7Þ®FyŒ+yä‘Ðy™ Í“À¨[·nÁÝHîJÙ¦ô¡JûÖ=·›*4€:@€ @€ @à»ï¾óÁ°½|ÀäˆR\ý¼×x‡f•*U6Yªú„uìnɯ´äšKl´×^{ѱž`'ÙÂÇ„RŸiªÛ9³E@€ ô%€à(}¯5ߥ*+_Þìâ‹Í’";Jüãï>íñÇÍGX˜‹q"û¸Ûk9¶öè‰ÈåU.E› ‰‚䞤´a#GFÜôŽR“ÒŠIØ$…Rj5jYûLµùææ/b#©·T×hüû¯œ…"iÔúöýǶÞz í²Ëá%èqn#P4u4µæÕªU F5’ˆƒQô|¹Í¯»î:ÓH‰Œô²Xy·‡¸ªêÀ –·¹_R·gçÂãÙylÀs6fJ³—îáý înÍ~xr[3xpD¼Õ©SrÏCé€@ò ,s‹·K.¹ÄïÏ…‘ŠšwéÒ%ù'Îã$8úŸ«~•FM‚#Í+º¢ôÔSOÍcIì@€ @H=ršã#lüñÇ,“ÔǬgà;î¸##5Zn­Ðžh*t9€ @¥›@¹ÒÝ|Z_R Ô«gæÙÇ‚ƒPæ6ž{®Ù!‡DDGk×FÄ=r¢É«PÕªf}d>:#kê5¥“ù&wŸÍâ‚['¹åò]v™¹Èh®½ùfç`g[¿~}.½ìB$W"qÔ¬y¨í¶Û9žBl°Ýpà vï½÷:×u9ºqõRætþÜînf¶yFOs—2UËwE”â¬o_óÜëfÉɼË]™MB<HO²Fæ™gBGåüùó­sçÎÁŠ]©=S1êù¥V{Ëó¡Žs»Ã &x:ÔÓ­ªnð @€ @ ˆ È)¨gÏž¦¥z^=Ü;äò“rL.Dû¨[ $]²dI\+Êz§eݺuíMÙ×;þäpO@€ @ ¿å—Ç¥< w¶Ø"ûjÊqHî-‰†Rg=ù¤ÙUW™»m<*‘w¨™Snm<:û%åÄ=új{úé§Ý¥©¼]ýõAÜS¡B…ìHâÚÕ«ÍZ¶4«_ÿ.[»öÉ`«;Ìm”‡[¥±¡b•+›)Í\IÛĶ-·e¥Æ;é$³•+ÍÞyÇLéøJB첋ÙYg™p@b­¹ðˆ0É3úå9š77ÓD@éG@£"~øáàh´ÚoÛúïÙgŸ âToÒ§½ã_ܧœrJ¨*éÔRýŠQ?@€ @%“À7ß|DFË—/·‰'ÚSO=erjÕªUX/’ÄA m*>ýôSwý¿8¤9«ã”×zg­³îìöþšvØaðLj¿M1d @€@â%Ί=K1›o68Ðì“O"©ÒäjTØñ¯çRS:åÊ^ê §víÚÙC=äéØ\ULQ©’Ù1Çȱg·Êý¿JMUуjlÌkÖ¿¿ùpÄ'v[iX¾ï>³/¿Œ´½}û’Õb×½%¿þqBò¬{!U þ¿Ä¦ L¨v‚R†À_žoô¶Ûn³{î¹ÇÛ¶³ÆÇMº7}é_|ºO?>Ô[ =<7©Ä;Å!’Í<¹0Õ¬YÓ.\î·tP~Šá@€ "$ @_ýupª\¿~}ž™SAH¥=kV­òA²#‚ÃÑèÑ£}Pêh{ï½÷‚éfï Þz뭃둂jÚ~ûí3*¤çZõ+ËyX‚¢Þ½{‡¬•5B”€ @€@’ 8JXŠMœ€Üa K˜ у…rr6J¼Vñ{Þyg$5ÚóÏ›§63;ûìøíý4eÊ»Ðía4zEŠJŸv’,sR Î8ÃìÅÍÓªÝe3fŒ´&MšØñ™,lü96¤¯»ñƨp1TáØc#î<Åñ®Z»ñ”njâ G+õo|õ•Y×®fß}gVŽ»ËFP,A ͼûî»A84{ölO7ÚÔ*zîÏÏ>ûÌÆŽ›¥%yæ™Áò]‚£t uªþwÝu—sÎ9éV}ê @€Òž€Òþ|å“yÎúïüar«­¶ 郔B(:)å힃ûóÏ?ý&J9ô矆¶vØaiÏ€@¥›À¯Þ¡­Ôi ½ôÒK®òràÕ$‘¥¾ÿ$>5j”½öÚköꫯhÍÝ.\£jÕª…çZ¥:—Òý÷ß •n²´€ @ (ðJ¸((sŽ,$Løþûˆ#̉'šÝzk–]òµBéŸfÎŒüýh¡…LÏ=g>JĬ^½B+Öô¨\Ùƒ òTmeìŠ+®°~ýúY•*U ï$,É–L©ã¾ür»òÊ+­S§NÁÎ7¶X¯¶mØ`îÊ»¶ô,»Ë…X¥§½jé¼yf29ä³áÃ#m×ßɘ1棱ÌÿF"ërû×ÿômß}ÍÓôå¶'Û!dPçæå—_î"Ó­’[ÜÉÝèÒK/uaäçâo¿ýf³fÍòûìÌ0Õ®];ˆuªW¯žìª%µü«<_ªîÁþ€ @É%°víÚà”)ÑÇl&Lðô䞟<Áøhÿý÷i…ô›U¸@éJ`ñâÅÁåþ§Ÿ~ )ÔN8á„,MQ µýöÛ/Lê7–3þ: éÙ]±ÓN;ÙàÁƒÝ­Þíê @€ Ȥ":§@”€Ò-)U“܈äT‚£/¾0w_ˆ8¬¦Ø(ZgÍ}ÐH¡Ås®`ÒKN½àmÓ¦=üðÃî"´[¡•_X)-x—.f÷Þ[Æîñ‡Û¬%+õÚM7e]Ïš’CÀû„M“6 á¬\0gvÞyñm”ÐÈûãBûéØ5âVÛüùæ9åÍþïÿÌÞx#~Ÿ ¢# Qå>ú¨õéÓÇ–/_nG}´=ðÀ¶Ã;ÄU¢N:¦éàƒŽ[Ÿî”2îŽ;îH÷fP@€ 2”ælòäÉÁ•Hi‚b'9yè÷§b ݵÏ>ûø`–ƒìÀ´-ZØêÕ«ÃËt½PNú*7èÖ­[×e‰Å~ø¡}óÍ7a™ ¤"üÑ4HGîm™CbK¹}ûí·6Ð;ËÏÒHÚBîoJe®I!—¸3fرnÁž.éÍh&»@€ ¤ Gir¡JZ5§N5«[×LîF˜?X™í²Ë¦[éýKvÚi‘}”ÑË߇ÁRô(‰–ÔçtíµÑ5©9WgXÏž=Cǘ^r>íÊ+¥s‰v˜¥b­•VíÞ{Íž}Ö‚àèë¯#©´þëãKÅ*S§B$ þ[¹õêevà æÂóQTæé‡Ì:vÌýDn˜bo½eöàƒf'Ÿ¼qÿ!CÌm¡Í;T6®c H.¥žÐ}húôé6Íó"FçU)‘FCJpD@€ @ /”Ž7ê¶ñÁØüw¸^ׯ_?8tì±ÇA`$±‘DG™Cû€R‰€¾×$ Òw™DBíÜæ]ËÙ…ÒC¾ì#l•MËŠÜ}Hß}švß}wïßÅÎ?ÿü Îüßÿþg—\rIvE%´.ZnB;³ @€ ™‚£BJq¹Pê-tṩÍSt™§o1É™ûq[oIÙuõÕfï¼cþPIétÜq‘tVo¾inkÖ¬YîeÇêl»Ém€¸ÂJ£ù”ºåVWI)Çvª‡?ûÃpÄJ±׵+ gªTo;õ3kÚT#OÍ^ÝìôÓ͹"©ï»/1:%a>òÊ<Ǽ¹›—™kíì™g"¢AÏÒG@I&°`Á;òÈ#ƒÈ(:¢\§T Ïænß§{ÒÕ~ƒUZ € @™ ¬[·Î–,Y\‡4Nr2’ÐH.F ¥ãU꽌oæ4iR*4€@º9rdè¿ýôÓOm3·õÖó´j¹U«VvÄG’•¾ê^ÉqHQ³fMw?/8·iÀÏÛo¿íßoÄ!û}ß¾}ãÖñ€ @éDÁQ:]­RW¹)½’;e»%vÞ%qÒÙgGÄ Ã†E\V|€IFx6˜”ŒW^yÅ…U—›¬Ãõ0ªôi-[¶LɺæT)¹Ih"7]·“NÊiOÖ—4eËšuT$ ¢»3{GI$Z6nÐÙ6]éç•ɽÌÿ+¸»—Yá¡pm¾y¶‡±(DMu{AY¬ïµ×^aD¥Òxj”e*;ì"Š‚ @H€€K}í¶Æza®äšË!SiÍr Š.¸à‚ðÒ½mÛ¶AÔžÓ¾¬‡ ê$*æÏ·Ýv[xŽ–›Üˆ4HgsïÄ’ÈrÔ¨Q6vìX›8qb`m“\ºwïÒrÈ!VVjÿ…„›JŸý~­Q£†õîÝ;º™9 @€Ò’‚£´¼lé]éÿy¸…lþÚ!§£®]#“„r;’»‘;q»ˆ'eöQÜÆIij¾øâ :t¨½÷Þ{Áf÷‘G±sÏ=7Œ‚)ìs&»¼.]Ì”Ëð„ôXy‹%»~”Ÿ\ù.ï1»è"³ÃËÛùähäÿ‚àHb#7û áÙ @ É^|ñE>|¸zê©ö /$ùl@€ ªV®\i&L°ß~û-8-]º4Ì—-[æ?ýôSp*ú÷ß3šP½zuÛsÏ=­N:¦e½L7lØÐ4h±? €Ò™À·èîÕ«WH…&` • ‘¾£qÎ9瘦¿ÿþ;Ž$@Z¸p¡Ö;*¸»I””]”/_>#­ZvÛY@€ t$€à(¯Zš×¹ ‚£Øæ+ó‹ÜS4g,^¼8Œl‘ÀèóÏ?£_þúë¯P%9GtëÖÍî¼óNÛvÛm‹³š:w­Zæí*PœÆÜ ßöÞÛlýzó¿åü7äÄÍ|€—]wY£FæN+ù/‹#!Ü ,Z´È.¾øbÓÈÉx ÷Ø€ @ ÄøóÏ?müøñö[C¿ÿþû6iÒ¤ð‚ŽÏ€J õí^zé¥aÎVné}w\]vÙe›ìË•{Ñþû漣Âv@€ @ ¯å•û˜€D+ ù ¸ŒðvžãÚlàÀˆƒNÆ_xùåH &9¢È%%ÕBw'¸âI#Yéwˆ+*”:MÓ>n½¤œÝÒ™@… f_~Y8-ÐÿãÇ+œ²(Ø4n)¶dÉ{õÕWÃýiÓ{³€ @  Èecîܹ6kÖ,›9sf˜O™2%8o(…B}G}´zè¡ÞÓ08É­HÓÖn%-Ñ@ 4xÙ;Ÿ5Pç÷ß.Eƒ BlYÿh3 @€@¾ 8Ê6*9í¶[¼°h̳4;î8óίøÒ=]¶ýø£yÞìøõ©ðI)Ò.¹äS.o-·oßÞvÞyçT¨u€ RN@)=‡ f't’üñ¥œ͇ @éO@©Î”ölªäúÊ;W4}÷Ýw! ZTXm¥:ÔGq˜çÖÈHnEr`& @ B@é%/¼ðB{óÍ7}ëv>ö%;ùä“Á@€ ä‚£<Àbׂ˜?ß|´HDX[Ú)§˜Ý|sÄå(Vp$!Ò´ifW\a>â.öˆâ]VGÞE]d?þx8|øpÛu×]‹·Rœ€ ðÌÔ}J¦JÑK@€ $…ÀªU«léÒ¥ÁURÎ’Ñe¥T?ꨣ¬‚ìbó+W®´¯¿þÚ¦OŸ&‰‹¦y‰ÖG£\¹r¡O¢C‡ž²º‘5nÜ8̵\·n]FQPÌ!Äذaƒ=ùä“võÕWÛŠ+¬K—.îº?WàF,B€ @ QŽ%Å~…B@éÔ-ZDæÑwÙ%âzäF öÐCfÞgâàƒÍE=fÞw–21ßUSrŠøôÓO½^ìÅ_´jÕª¥Lý¨ @ gÏžÁ^.G€ @#ðÏ?ÿ7¡I“&yºé/Ms9 ­^½:Ç‚ÕWеkWëÞ½»í¾ûî9î'— žk~òäÉA\$¡ÑÏ?ÿ·¿RŸíµ×^ÞŸÒ"¸ɱ¨Y³fÁq9nG>@€@¶ô=®~Ü~ýúÙìÙ³ƒ0ó…^°Ž;f»?+!@€ Ü 8Ê{"¥SSx¿X–ËÑu×™kvđ͞©Ì;æ²ìZ,+ôPªÀS¼¢ê ìÝ»·Ý~ûí¶Ùf›K}8) @ ;J£öÊ+¯qì‰'ž˜Ý.¬ƒ @H€€‹žzê©ngÊ”)qâ" €öÛo?Ûa‡LËÕ«WStYÎDrE~àÂÔªU+;÷ÜsCºž_~ùÅÆú4ÿQyäÿ ¥loÚ´©xàžŽ~7kÞ¼y˜ë< ä€ÒQê9ùÆo´3f¸‹þÖvË-·Ø¥—^j•+WÎ{@€ d@p”‚…¢ 0k–¹@Ç|d_Ö³)E¶G/¿¼Qp”u¯¼¯Y³fU¬X1á,Xrv«pÞ¼y“DF²ÜÝrË-Éé0Mv„ ¢$°hÑ"ëÑ£‡)…ÇÃ?\”§æ\€ @ Äøì³ÏlРA&·È¿þú˪V­jûí½÷ÞÖ²eË0í¼óΛl/þ’K.±‰'áÑËÞÙqÞyçÙùçŸozù ‰‹Î9çkÓ¦µnÝ:¤DSª4€#pÛm·ÙÈ‘#­V­ZV»ví¸é?þ0m—#]•*U¬oß¾vå•WÑQb¥³ @€ °)ô`lŠÛ €§Ç¶[o5«T)kÑ ˜wÚ™½þºÙ£š•/ŸuŸ¼®yä‘G좋. #Ï8ãŒ\_¹r¥~øáöÍ7ß„}Ë”)c5kÖ »².¯W¯^‘¨† @ ¸ üðæbJó©ùWn%(q¬lâkÔ¨QÜÕãü€ @ müù矦Ô:mËÍH!—!‰¹;î8ï£È_'…DDš /½ýöÛÖ°aC;à€Â$¡8@ýû÷îoríU¿ln!Q¨Eëׯ·¿ÿþ;L™Ñ@Ô^½z·z¾s3Óá3 @€ FÁQÁøqt>ø`“C.Gþüçyf'dÖµkÄ)Ç6±a¬çf»øâ‹Ãƒ¦F J8Ô¡C‡Ð Z¥ž‘Øè¦›n²3Ï<ÓêÔ©c›o¾yŽÇ°€ PÔô2¬gÏžaçï¿ÿžqzæìÔ©“yä‘!ýgÆ @€6I@ƒvw+æŸþ98`Hdtá…†tf›<0•¶§»çŒ×D@€@V£G¶«®ºÊþùçûüóσX3ë^ñkÆŒÒ]Þwß}ÁUNÏÈóçÏϘôü¬þ^=/€ @€@á@pTøL)±$2êÝÛü%ªÙ¯¿š%`J”íÙ¾ÿþûð0©½Áƒ{òN8ÁÆ,г;Hâ$=¤Êâü†nÈnÖA€Š•€FouÔQöÞ{ïÙž{îi§žzjHï±ß~ûÙN;íT¬uãä€ @ ] ÜÿýAlÔ§O»öÚkM}  yóæùÀÓ®ÁMNϽr8’;\nñº¬ò=Ž=öX+[¶lI\¤çe€ @H>Í’ ÎÄ xÆ2ów¦!|@K¾béÒ¥Ö¹sgSŽn=œ}ôÑöÖ[o§£Ž;Úœ9s²”«Q0J¿Ö®];{衇²lg @ ¸ ¬]»6t¢Jl$‡£É“'ÛÀƒè±Qq_Î@€@q˜9sfH§Þ­[7kÖ¬YpÉH¤Nr7RŸ@Ïó.·cÄF‰Pc@…G@®ó'»íý’%KBêI=ß¾ú꫹ž@)ÔÔç+qÏĹâb@€ $…‚£¤`¥Ðì¼óŽÙ›ošÛâf·u㺗_6?ÞüAsãºD—”¯[NF³fͲxÀ?üðp¨œ^zé¥ð઴j±)hÞxãÇ[’(•+‡ñW¢¼Ù€ІÀºuëÂýmÔ¨QÁ‰O÷8€ ”f .´þýûAv5¬I“&ÁÝøé§Ÿ¶¹sçÑ„ rE$w£eË–Yß¾}éÈ•;@(|W_}µ}òÉ'A(ª£J¦—J«¶©øðÃC_¯Ü@€ @ x 8*î¥ò¬·ÞjvöÙf›åòWW·®Ù˜wôå“>øàSz´ .¸ ®¥ ‘{ÑìÙ³­S§N!¿·Ü!ºtébÛn»­§qiU«V;†€ â&í9bÄ¿žùÊ”)SÜÕâü€ @ X̘1úwïn;]qŦßHZ¾ì²Ë‚#ÆüùómêÔ©!-ÏE]ÜŽsªèªU«‚h©~ýú!•ONû±€’C@)Ñä2צM»í¶ÛÂI$8Rh`è¦"6Ú¦öc @€ <¹H?’wbJ.Y{,â^”S«þý×lÚ4³-rÚ£àë `?þ¸ÉÁH£³‹óÏ?ß®¿þú0Bæ˜cŽ ©×d¿+—#¬w³#Æ:@(NºGvÚi6|øððì‰'ž0ÄFÅyE87 @ÅE@ie<òHkÞ¼¹=ùä“Ö²eK6l˜-_¾Ü¾øâ‹ÐpüñÇ[­Zµ¬aÆvå•WáÑ Aƒr¬²Ü”–w£±€@ÒÌ™3' ªÙn»íìe·¼ºÎ·jÕ*I7•Ví_ïlÖs²¾ïu_ @€ â!€à¨x¸—¸³öîmžÂÌlåJ³5k²6Ï ZÛ¶fíÚeÝVkÞ~ûíЙ¨´hC‡µ²eËæXìÍ7ßlݺu³±cÇšF>>óÌ3¶ï¾ûæ¸? @ÅAàÏAzú駇Q'{žÑÁƒ»K ?ÝŠãZpN@€ŠžÀ¢E‹Âsû=÷ÜプZ„”éï¾ûnHµ3qâDOÅ>ÞŽ;î8«T©R¶•»îºë¬^½zaÐQlZõèÎr7’«†Üô›‹€ ¢#°víÚ6\ßÅ/¼ð‚Õ©S'îär9úé§Ÿ‚ 4nÃ$47o^¸d·u€ @€@ÑÈGÒª¢©gIr/’ hæL3¥C“û­»–ÇÅV[™¹CnRâ—_~ ®ÕªU³·Þz˶ÒÉr‰G}Ô*T¨FÀœtÒI¹ìÍf@€@ÑPjÐ_|Ñ4Rÿ¹çžÛ¤˜¶èkÇ!@€@áÐ g=Ï+íù4·GÖ´páÂŒT®\9¤L»ôÒKv'ÞrË-3\®¾új{ê©§2ÊÓÂ>jJîFwß}w†«FÜ|€ Xã£R?ûì3û믿lýúõq“ÒaN™2Åúõ륙O$Á‘§J«&Ç£ÌA:µÌDø @€ â!4Á‘FåËõ믿©?dºóÎ;[íÚµ‹§¥œ5iV¯6óËmûïoæƒ ÍÉ­gOóëž´SfM5# u=¨jdb"!‹Þ‡z(‘]Ù€ Pän¼ñÆ&ôˆ#Ž¢£¨µ|‘W„B€ $Ћh¥Œ}饗lµ:<äX´ë®»†è»ï¾»iÚ{ï½M¢£¼†Ú·oœ"Ï;ï¼ w㨻‘ú©Î8㌼Ëþ€ I“&Y—.]ìûï¿ÏqO}?_ýõÙnßgŸ}‚KGwÝuW–}$8’+RëÖ­³lc @€ Pt6)8r‘På*Uª´öôµ¼JëfÏžýJnU7nœ=öØc6cÆ O­•5·Ö{ìar”Ñhý2E¡HÉ­Âl/0+"EÔ¬ivþùfƒEÜŽš4)pѹ ôh²Q¿üòË­cÇŽ¹îÏ€ T'ðÈ#˜îoÅùê«¯Úæ›ožêU¦~€ @ aK–,±!C†¡Ñ7ß|ŽÓ‹åîÝ»Û!‡b 4(Ô4²÷û¨(‰–zúÈ(¥àQŠÚ|ÐT;ï¼w£„¯;BÈ€!Ë9NB"}ßj.q§žkc§-¶ØÂÚ´i³Éï{¹Ý{ï½öå—_ZË–-3N®÷2õèу÷ TX€ @€@ñÈVpä.1mÊ–-{­W©­‹‚¶ø¯jŸø|“‚#ÙSkÄÁ¿Ê±•C|õÕW¦iÔ¨Qaßm¶Ù&‡=Y.V®ŒÔ´jU³+®0»î:3w.Oz|øá‡vË-·Ø^{íewÜqGÒÏÇ @É& QšzÖ¨Q#9rdáŸìsR> @(l¿ÿþ»§]ŸióæÍ3¥Aε¬>¡uëÖ™úƒ.¹ä’ 4Úm·Ý » å5ñÑP¤$q‘ÈuíÚ5¼ÀÖ ð3Ï<3c? @ `ô]úé§›$7kÖÌ^xáÓàãüFTp$—£XÁéÔòK”ãR•€ÿ,²µkÍ6l0[¶¬œg“Èöµ]ªVŸzA€ PÊ dþåRÖ_p=èLÎw¡QžbõéÓdž –0Î?þ8ŒBШ6Fî'Œ-%wŒ:mµ•™DG™cÙ2sW+óND³“Oμ5Ÿ5Q„[º²IÖëåË—Ï_A@Hrì;í´Ó¬F6zôhS:Z€ ¤•>"INrZ¿~}\Õ}`›Õ®]Û=ôÐ ôQº39\EÈaãùçŸ÷R×Ù¬Y³p7* èœ(U$ :ß­ï—yG°ÑÈå¨bÅŠb›VM¢ÑhHpT­ZµàŠ]ÇÉ$ðãfšcöÿtí?if/¿l6¾¹ë¢Ù7Æzî¹fÏ>]·»í³ïD@€ 4!'8r±Ñã®3:;¯u÷Ýw7)6ÒÃEvéÕ¦L™býû÷·Þ½{çõ”ìŸB¢Ge>xÑÆŽ5Oy–ÝÖü­ëÖ­[!ùÌ3ψü•ÂQ€ Ô  t";w"ì·ß~;XΧFͨ @È€œ®Ÿõ7e×\s-X° ¤†=å”Sl‡v°ºu놹ÄFGTªT)¸죠î»ï>Ûi§ìŒ3Î(ŽªpN@%†À·cyÿý÷íÉ'Ÿ´¡C‡†Á3#FŒpA†+2 !4ú„NßÛ“&M²½÷ÞÛæÎkZÖwx¹rq¯6 áŒì øk¬ 8r›ÝsÙ˜ùë ¯eþ›"ûcb×~÷ÙC™ÿ2O»%²|ðÁæÏ‘iÙ²ßmÑ¢ÅYwb  @HQ›EëÕ¸qã36!6ZçGßG÷ÿý÷ßáGì:-׫WÏ}ôQ““ÑÔ©SC®euꨣ)6^|ñEûã?bW±œf¢‚£ìÜüÏÃíÒ# *€ƒn‘|ÐÞ|óÍàpDa>@€@Pj‘#Ž8ÂþüóOÓHÍ=÷Ü3 [A•!@(­¾üòKÛo¿ý쬳Îò ÿ„Ï'Nô”ëW˜Òáh›ú‚ŠKl½.'¹õòa‡>Êé·í(æ€' ‘Ñ·y9×-YjÕªe:tb£N:Ù´iÓ Ml­‘î# 9()H§0ðO ([Cæ×UGmþžËÜ!Ñü½„Y‹fƒ™„6ÿýc&A‘gt—G³ÆÍgÒ ¹ÛÙæ)eÍ^}5kå%^rÝž¿O3oÿb[m57ëN¬ @)J`³ÿêUÆEWgSÇ÷]PÔÖ;Œ¶rËiÿÙ“5Ô±4gΜ¸ Í›7÷N¯[S¥QT©R%‹dt8è ó¾³]w8)Uš¿îòÿ±Gëݘùÿ³Í¢oãâ7ó € ¤5à;êâÎÞÔ,¶%.@ºÞEF·Ä®ËnY¶©™£W¯^V5;»ßQù•zÂÛ£% ÿ/ärÔ¥K—èGæiF`ÅŠH…cGÊa,Õ¾4AÕ«›?€Fæ‰4M“O?ýtè Ôß‘þf¢Ó÷ß„Hú›‘ˆ€ ¤#ʼþúëM©Ô¶Þzëà ´# @H5_ýup¯ž1c†iÒï—…1oö?üðÐÏÓ¬Y\·Rª5#ÔG/­5ˆ‰€ ª®¼òJ;ðÀí˜cŽ)–**›|N˜0Á>ùä“0)Y4öp ûË/¿Üä×Hö.IŽhZµþýûÛ¨Q£‚ØUï*V¬˜ä3—žâÝ´ÊSxEúòÕ¿ãŽñmÿñÇHª/½îQw|nšb‰†*Tˆ/ÃõÉž~ÏLÂ"¥#;ýôøír’{P4ü§…IHä&Z› O¨aþ_ÆŽ;ÎlذMîšëF½Ë8ôPóÁõæC¹îîÆ,LÝ{oD(uöÙfGI–{ ì@€J 8òî×Ä6ÇÅF»Øè¶Øu9-¿÷Þ{q›ôбï¾ûÆ­Ëü¡iÓ¦v°'¦ýðÃÃ&?W §<ÌDúˆ:Åj̤ú¿è¢HãùóÍÝ­k×M7ÝÄF!©´|ËÜÃTÓòåËíGºQú½{ý|Ë–-+½ @)D`ôèÑÖ·oßj¶R¥J¦tzé%Ñ@€R‰Àš5kÂo ‹:oåoàvÙeëØ±£æß5<›«‡€ ‚øôÓOí>WPÜÿýöÚk¯YgY©QHh$8õÍ*í·b3·c‘˜ôüóÏ·ý÷ß?¡vÞyç"ªÑÆÓ(­šG^x¡©žÇ{ìÆ,˜€gÇók)Æ»(ì–LCÐ][æ}‘írèÑ;uaD'+ln:„:®Kötªf=_-§ý4È~Pò™gšiP³RŽIxôöÛæéæÍ|̱rH|YÑOþß%ˆ<ÙFô]¯ùSO™iL—ê•—(çoË|ÐL¡DC¯ÂþËø—è!ì@€Jrõëׯ炣ýbZµjýúõgøçbÖe»èB¡-£ Ñþ/AeÉAî7騩S§‚£(ÅôšGG™•ÿ¹àϨ¶zµ™ëÐr ¥•éׯ_ø;s–^Ä€ ’@`¾«oå`ôÑGÙ[lRŽ\{íµM=[ÚH @(9älq¶¿mÓ1½d–3cs£WWöÅ $…€úFꕃÐÈ‘#í°ÃKʹ¢…úÀã.í†n©Ñ¶Ûn;ëÓ§Oí·ß~9f1ˆ_s nÖýç§Ÿ~²Í7ßÜ:uêT§-‘çY•ñ‹öí#ÎErRаÌ!ñÖûxà,ÓÏ?G„B®³m·¼p]r–È,@ʼƒ‚bCžsÎ1“Ó‘PW_ÕYÉÿê12ª!¶µpÆ‘ ¹I|vŽ?EÈÕH9¿Å’d€Ò@wWáJlt®TG./ëÒýŠR@€@É$ W#¹10 ˆ¤å0|Ùe——‹’ÙbZ@ 5øà ü‘{ÜóÏ?ï®.‡˜R‡;ÖZ·n”J¾í62rÝÕ@`9ØÉÝèŠ+®°Ê•+'å|ù-4šVM÷¦C=çUIvž8Ñüzç—TÎÇI,tÍ5æéÜÍ”,6ÑÄ©§šiÊ)zôÈiKd½kÖLiÔ 3Ë\’4€ùøãÍ|¬–§ö3{晈KRlm.¸ öSd¹C³[o5K›;1š=ñ„ÙQGEÒÂeÝ;~ b£x|‚ @‰ØÌ°ïœiÇï2}ÎñãäÉ“kÄnÔ˳DmUÈ?3&4òŸHO²ÝfÙìf­¿ó°3@IDAT»ÝÚÚµæV·Y·E×|ÿý÷Á ·‚'wÖÈÚµkG71‡ ¤=Ý\¹g¸ ÷1Ö‡Ø(í/) € ”HŸøÛ¼-Z„t>r“Ð h½xVJ€’K`”Û²,^¼ØN?ýtZìž!å>tä‘GÚôéÓ7yr¹Ñ)ÕX¢ñÃ?#e*P¿l¯^½<Öœ08&ÕÄFÑ6uéÒÅ$<Ò¼$†_’ ŠQz®7ߌo¡_^¿›½ñF$mYüV³W_¤“Kœ$ZZ°ÀLB …ë׬I³G5¿îæâ²ÈúÂú×/K¡Š¢õjÜ8Ò höñÉA$5iRtkÎsÕÇMºBZ6-K´¤ÑGavÇÁÕ† g¦^ȹ¶@€ $F@GqVCþ ó}b‡šHÜ(sc¨C*ѨY³fp±Y­|[¿þúk¢‡Ú~9¢ÐÃJ9©f !þr9ÿ O8\½zõB+3Z­d–=GaÏsðûï¿[ÇŽmÕªUáAZí äŸ÷¶ü³KÆ‘K–,±K/½4¤N»ï¾û’q Ê„ Pâ po+ñ—˜½œþâ‹/l̘16zôhw<øÌÊ—/o÷Üs]~ùåŠéºpÚÒA€{[é¸Îyi¥Ò©©ú´ÓN ‡)ÙðáÃCú°víÚÙÇl5Ê(R ä„4dÈ ÒþC‡Íu€Ë¸qã<Õ žk¹]àö0J™Y§NŒrSu¡¥[Õ,Z´ÈÓvŽŽHÕê&\/½‘º 4hWNC±îC*èƒÌ4¨W“ÿ)ø};¾xO`>¿NŸÔ/¯AÂçí™òìÙgÍmY÷Kå5[nq6:à³K.1;î8³¯¾Êši!»6Èéhʳ§Ÿ6ó?{'ÿ¹B&^!ýò‹ùz3¥g# ÷¸ÂcII€ t •ÿ¤ÚÿüóÏ÷?å¼äùœ+Ï›7Ï–m „ËKèaF#0 $»/ÂP‡ÚÅ_ÎØªU+‹æÈÎOôÀ7xðàЖ… †"ô€¨œ×mÚ´±Ýt¯½öÊOÑáa2Yeç«B…xT²ÖšÇܘü‰‰€ |àÞ–otI;P)H$®•Ë‘ÄÈ ä÷¶¼ñboäF@îo¸E‚FJÓ³lÙ²pHÕªUÝàxûßÿþç.Mr+†í€@po+¼zèÊ•+ÝÕæM;è ƒl‡vÈhåá‡n/¿üriù-·y‘8T"£ &¸ƒÍ¿apËQž/JÛöÜsÏÐÇÝAJ‹lâ Ï-ÕÃócUôÜWÚ_îIéé*6Ò­V–J•6NÒÈ誫4ÛÜaÐìþû#D™¯Éyç™ÿmD3:.sx&¼PÎo¿™ýü³Ùܹçóæ™sLDÔ$Mº†(ÕœD®N8êÕ3»ñÆÈ$A—ÒÉ™¾þÚ< b£„a&¸#÷¸A± @ àh]l{\(³&ösNËÞµ¿?ÔÄùjçUTóÇd¯<ÑEz¨*hüâO W_}µMÊÆËS|uñÚk¯…é°Ã³»îºËªT©’Ði“YvBÈÃN®·òvEŒòp˜}öÙöé§Ÿzþèk¬{÷îy9”}!@ ÜÛ²RŒ«d‰/As§Nì”SN)Æšpj@éK€{[ú^;jžšŽð|"êÃPš4¹Eè¥tûöíMŽÕ…åüœš-§VHÜÛRçZ¤JM† f˜Ùµk×,UÒ`ͧݢE)º•jM±¥«NôŒ©ôkÀ©ïo –Î<óÌà$ß·o_YܘáT'G;¥Mëï9õë×b£fÍše9+òGÀ“؈f3gFÄC®ëŠ 9åÔ% ¢‡6“ ¦lÙ¸Ãâ>4mj¦)»Pšvܱd‹gôçÿßì0äºNŽO™$B"’C€{\r¸R* @ • (¥ZÄbè¿Zz§“ÿ4µ\³áúq®«ß é%/I§cvÔ/â" wœ¤ì¹œuÖYæ.O •òþûï‡Ñ(zñ(ç£ME2ËÞÔyó»MV¯|ãÚ¡„ã»ï¾³—^z)¼„½í¶Û>Ž!@ {ÜÛ²çR\k•2Vöô4¨¸ªÁy!¤5îmi}ù¨| ÐÀ¨o¾ùÆð¼$z1½ÞN€@‘àÞV¤¸Óædê/ÞÂÕrÉÏ.$DÚ°aƒ½þúëžRê¸àHWY9¡bB.G“'OeÜ|óÍöÉ'Ÿ„”k*Tâ¤wÞy'8(ip,î»1àb]—ú·•²«F ³í·7O7™¢®:~ÜYÊlóÍ7¨´hQ­˜'=éÑbÇV7onî h¦ýb'½ñ±ÌA,´±4– ¾¸Ç¥ïµ£æ€ ‚(ç)Ôfkd[4¼*!å ŽÚGÑ|oO.ìëbWmrY>¹¢­uïÌž={ÚºuqÆNÑj$4Wݺu‹éámÿý÷wJ-§<Ø'N )TV­ZÊUník¯½6¤ˉU2ËN¨qùØÉ]-ö!*‘"”c\qÅWäéï&‘²Ù€@i#À½-õ®xŸ>}ÜÊüg©ø°Õ­[7õ*H ¤8îm)~¨^ZP*{õèϱQZ^B*渷¥ùLRõõ|Z+!‘Ò[æøªiS±óÎ;‡TkJíýÈ#„k*óÛo¿µsÎ9' †Ùø éw€\Ž@Hœ÷¶ÄY±'òJ@ƒ Éî 'á@ ƒ÷¶ ,dC@}¤> غté’ÍÖ¼¯’S’\v<ð@OÓužIlzÏ=÷Ø•W^™÷ÂJàë×Ç»•-kÎÆÌ“xªQó”t惊#Â#ׂ™¦ß~‹ÌçÏ7kÕJ)í²‚éÜ9ë:Ö@ 4àW®2m„ lš@9wâ™;²ÍED]<5ÚmsæÌÙ¨¨ÉT†ïs‚Om‘|{^G²ñ–llÔ«W/öc—uŽûî»Ï~üñÇ0Ée`½ž( rFzì±ÇâJQJ°Ìb£èr5¸ûî»íTåû/$*ÊNp”̲£çNÆ|ÆŒ¼•ú©ç^ó¿/»êª«2r‰ç­ö† P: poKýë®{y÷îÝÝ^}óM:¦~K¨! ¢!À½­h8s–’Iàûï¿îÊ­[·N¨êQȃ€’G€{[òØ–Ä’•NM}ó¥t)Ä8í´Ó‚ÿÒ¥Ksì·.ÄÓ¥tQÞoÏWq~ަS+¬‘;ÅÙÎ @ ( po+JÚù;×wÞiß|ó]ýõÖ´iÓüÂQ€Jîm¥èbÓÔB#ð÷ßÛí·ßúQ:tèp¹8%ŒŠ!P ÜÛ „¯T¬>b9ñŸxâ‰V¾|ùBo»úës$[è'K᥷}ï=3wVú³Ì¡Ä J—F@¹à—;#ö€ ”6ATäUW»èhM´ñ.(:ªQ£Fï7lØÐ“emŒm·Ý¶ŠØÛ·{6âÑ©S§rYš0a‚õë×/n/¥©V­ZܺTý0~üø¸ªµmÛ6îsN8à€¸Mo¿ývÜg}HfÙYNVL+6xbl9<5kÖÌZ´hQLµà´€ K ™÷Ÿd–Û†TXV§‹R©ùo(ëÝ»w*T‰:@¥ŒÀ˜§s6»Ü‡‡¬XQÊŸ©¹É¼ÿ$³ìLÍà#²øöÛoƒcEŸ>}LÏ×+ü?ûoÊõ’@DŽò2`,bÙ("ɼÿ$³ì"“–§‘»‘¢k×®iYÿT«´'<°áÃÍïñ5»è"³U«Ì>ÿܬgÏøm|‚Rƒ@2ïCÉ,;5èQ @€@ñ(§Ó{z«¹7–«Ñ Ñ긨è`_ží/;r1ÒWþÙE­µÏ+F÷Ñ\£/Î8ãŒØUÙ.ËhÈ!öôÓOǹ É鬳ÎÊö˜‚¬Ül³Íì®»îʶÕE¹«ó_|ñEÆaÎÂ>X˜rX‡#í-ÁÑùçŸw`2ËŽ;Q1~3fŒçÄþÝ.»ì²b¬§† ž¸·Åß7Sí*Nœ81¸ ž{î¹!¥ZªÕú@ 'Ê:ìYuä¿äþ¨ýe¦qÛm—ð¡ í¨òý‘Á~ø!>ÝA"OjæÙ{mÇÍš41óAÝV¶l"G¦ï>žÉÑ^|ÑlÀ3µ_ᲞÖ9²ýwÅŠò~ͶüöÎLŠbíÂG²ä$(9‚""Š˜$)¢‚× ‚9\#ÊÕ«böª×¬ˆáW0+Š˜TPĨ„+D’’Ãÿn{wf6ÍìNÏv÷œzža:TWW½½LwW:Ÿ·˜oÝÛ‚}o ÌŠ* ›6ž.Š íµ×¢fÍš¸îºëì÷ògslÈDz!ŽªV­Š:uê$ìѪˆ@: èÞ¦{[2Oü]þùç0—‰U“9>Šy( Z´æߺ›oþúË}Ư[‚6yÙýp¹F à­·l`ÃF6¾ÿ1èß?· >+‰€¤‡€îqºÇ¥ç/I¥ˆ€DƒCMž ,_T¶îÇ~ý¢ÖBµ§0ŽàˆÖ®]{—…6ëc"š=¼l¹¢-ïgß¹ñÀ¼S,TPg•Ã}ô‘Òì›o¾‰yÅ\}õÕ¾XÆR tüñÇ{§‰û6U±Go±ß–ý«‰‰ÏuÏ<ì½7pä‘Àðán_nl>‰ØÜ(¼óŽ›7vŸ–£O \lmVÅz[¿Ð¨3¥²=ºc—Øý1Ë›­³êÚ{î¹§£mk³=éE†a£õw˜R¬»ëMûòTR ú»Æ$–W½zug‹ŸeÇœ2©ÅY³fÙL’ïsÂÅU²)ÒïòW&Ÿäý(ýÝŒ|ränzÝ‚hSttG¡”D@D è0wÎ9çäÔ†‚Psý3Kîøßìœ [ðóþãgÙ©^†y¦dá`\l(Ô÷ß?m.‹,û'{*dŠ ÎöRJÀ'Ÿ¯¼˜9¦óbcÆ¡I´ü§}? ®ØNA“[:â kèô÷ذ»ÓÇùbÇïÇ]!ÎFaø:ä0,¡@‡"¡Â«QÐbãÕ¸ÿþø0±M²ÈÆ8àà¸ã`ƒä±{ÜCuÃq¦2èxÄ «V¹/­í¾{üq\ãK-™(®a=N>97ÿÛyáÄr·æ.ñŘ3m p€>øxõÕà…[Ûº&.p¯ …W1óœ0s3gftâ|ø·ÆÛr ÷Á|™ /Kì:®fCòóþãgÙ©^›4dîV¿ÅÝÛ^3+¬ÚüÏ­z/ší¡)jgÖlÛvbȺñ¹ƒGE%þ½l²C9EJûƒN`äÈ‘ŽËë¹Ñ¯øBðóþãgÙ©¢\¹r¥ÓwûÞö¬=4ÆNâLµÌ æçsÙ+ö´Ï>ûØs¸=ˆG,ñÙ›" ¾'±ûœÂù ÜÁ§‚Ä@Õ«ç¾g$âàû Eõü(‰@ ð¹ïZ×Zâó#²)ùyò³ìT¯'pÁ{ï½çʨ(?üpªÅ(¿ˆ@–àÍŽƒ^–“-KšØ÷þè£]ÔøhÑ"·D‹à6uûOž–êO<û­è.﹫_v°ÓN¹ÇrÉæaä9‰º‚Ûo¿ÝYßb‰5aÉɤ…Ȉy­š3g޽ ¹ì´0Ç#ìmßM,>ë´­[·N¶ÏT³âæS ¤–öÚk/sĹÆfï›ÚÈýçŸÆÕ"UÁ‘'.ò áÃŽ×ÙçgÙÞù’ýæŒGÚ´› Ì9„qy Jžà(™qyº]ÑééZ(‰€ˆ@@4²©sO=õTNmzš}DeZGdIòóþãgÙ©^ž†fÒ¸qc{ ¶'ê¿ïIéJt7bR8µäˆ²ïŒ‚ ]˜(È¡ã5Ét®ñCpÄ8ÒƒO ÅåÖ µùü×0ŠŒ¼^üs:ì07¬÷óކã£T¢ˆn>6ž‚*U\·Hºö”4=ö˜Í¸5*þ|t^¢+Å,|Iä7ÏÏw>¯ÃŸN9¯fôß‚þkÐ…ˆ.Aìèçy J–8¦B¡Óm·¹õáK>K²n±"¢Ä2øRËz^p+NJÜ_Ø:]œ(t¢;'ëÎv$Ò)¬œ’ìãL Ó9⨣€cŽq_ÄË;áw`†¯J‰3Š‚.¿0t‰eÄ®3ŒqwÆš³ôÉ'ŸØß¥ýafAòóþãgÙ©^š¬w§nݺqÏ1Ù"˜N•U˜òsòÏeÖ{ÇP;µjÕ2W¶‡ìwïûÍ*›§œÄgÙdŽN‰ïûJ"f½{÷Æá‡î4aÊ”)9ÂÚ0·)™ºûyÿñ³ìdÚ›‡÷1 ¤cßÑwNÇèJìI2¸|ÒI'᫯¾²wr·ï \¦ €ÜÏ Ê&‚‰“(6:ûl×]”aÙí £GçÿLK=?J"޵¸áÞxÙ6KÈe ?ïC~–êõ¡À”c„矾sh¶LJ•“ò‹€¸–-sE=tvd¿ùüùnÿiIø°?˜NFt)Z³&¾$‹ò눚øÌFG{ŠœØGÌ~|V1Í0p`òuà„)©nÌÏ&?¾ Z 1|G^{fÏž=×–ùyÕÛ–ÊwS“Á±€Âœ=lå`“ᵈ•Ë¥RXò&>œ¤Ú™›˜?V]ígÙ©¢«X±¢©+%u­< VQGËì—‘N ¡WÇÙJµbÊ/" >¨`£Ð±÷&Î/LhéCJµH?ï?~–*4^çÄkj…åÓ”'ªuéÒ¥°l¡ÛÇ™éè$6œ.3ŒõÌI] yÅd}ñŽËNQÂξàqK—íÛ»ÖŒr›Ï8¬S.Ýrø¢DagYШ¤‰³8FrE+#`˜+ë´Ž£ø’)ìaDÞüÌF¨û0SIGTÂ#±‰áØè¾Ã—¿ÄÙ"±ùb—)lºä U«\!—·ŸÎ?tb¢½-'N&Fþ³ùE&¾hòÙïÉ'Ý0lEPD>RÅO*Éô&²HåˆÜ¼ÕªÙŒ‰góŠyrsø³ÄN^gþM<÷œ{›‡¾ÌÇŠ¬úö¥¸÷Þt1®“óìÍŽk>çgCòóþãgÙ©^oÐ2ö9&Õ2”?8èê1Ä~žä¬%DÜzë­9ÿ‡ ªiKSr¶tQ‰nLÞ¤§¢òk¿•…xü0ýú믺·%y¡ÂÒ'Iq%ßÇ£po£ë ]Œø;;qÎ즣2K¸Lw£ÓO?=É+®l jÀ tPµË 3&s&gPøÏIœÄÀ}Öý¢$"`øíýNÿañµÓ9A. €ý|Çò³ìTÙrÌ×9 ÷¸TÛ®ü" © cÍÄØ±ÀôéÉ } ;'{²¯9?ƒMöGê:¯Œs%r'­²ß>Õ1‚ª6s”&†x§è^)º|½ºMêÆOTRâÃIªGÕ8“²ÇK~–íÃïdŽÆ˜ü’/Ó §æÇUP™" "P|~Þü,»ø-Nÿ‘«,ÔçŸnn==ÁnúϾ)4¡è!™¨JÌËN`‹Öâˆö*QPSœšÑU‡b#›œî8½Ä–acò$:Ñ ‰"#ºÃXD˜<‰¦dYŸ½cñ›®=6eùÀwÆî)þ2Czí·ŸûÂUЉ¥sgñæ—ÚŒ‰ŽB¦‡‹Kæ°~ýÜxvÈ3.vQáè D!…C‰ÚnºâƒE^rB±Ó?Õ4gŽë@´ÿþñ™TË JþDÖ§ë\¯„Çõ´U—.N™á'¶oÆwÿ¦¹-6ñï4¢ãN±Íô}ÙÏûŸeûF',oMK×–ù¦Nd¡L%JwèdÒ®»îjŸ€š ›Ü#‡£dh*—€Ÿ÷?Ë.QkÆAÎâ®bv¦_|ñ…… «çï 3P:Coq„"­¨ÓÑÅ•ï±é¬³ÜIÛsËã@V~^±ÇiYD úü¼ùYvô¯ŒZ("œèÊObZ´° )¥C):;û³ :gÑG+G¶(ÆpC¶¢â Oü´ :%¤’8‹%6yªunó³ìØs¦{Ù5ÉpjT2üñ鮂Ê(?ï?~–]‚&§ýзß~ÛÕ=œ­W/¾`Ȧ Ç@W æ­_ ƒq𳹤éõ×ý 6ˆêºÌ$ÊÒy'j‰Ï³|áæÿ ‹n‘öDQEc±§žêþ=óï‘0ÎRJ??ï?~–~*1 ž3Û3Zÿf? t7¢x(Y±ÛGç ¦¢ÂªyGÍš5sòëpðóþãgÙᢜ¾Ú¾ð ˜1c†"3 b#¾‹ñ¹5q^1ß+91„!œ“I»ïX$DÇyÖtXÎ;g2Ç)ˆ@´ øyò³ìh_µND ¸&O†…ÔuÝö‹êƒO<û o¸¡hgvš³+àòËÝɬ‰åpânö‹+‰@&Hp”åbZ¬I pXDY~Y< hægÙET«D»VƒW»¢å[;>'Û/쉈[qióE¤" "Pjü¼ÿøYv©ËçÄ §FÛÿîÝ»ç³78›(^aœfv2™¡·.½ÔiJ§Ζàw¢ÎÚÆCÁ0^É&†cø1>N2›í[ô‘ ›Æ­Q£ÜzXŸ=î»8î8€¢†Ÿ¢kÛD'$Ö31ѱ¦¸"›Ä²2µNA¨(¨úðCw1×y ÍPË÷4s¦êË;ÿñ%µO€nIQKÎÓIê£\w!›žÖDW#‹”䄼‹ÙqYnÂiES˜Ÿ÷?ËÎi€²‚€/·ÞÁ3ìæHg¢‰'âÜsÏM¹ít8bú­ì It8¢KsªNÍ…©]" $àçýÇϲ3ˆ(0§âïû¿ÿýoç÷öêD›ŸÀÔ2ùŠÐ–ï"Mš¸ïb±G¾û®ZÚn/ÎÄØ}-Ó–&Naˆ%ðó>ägÙºr" ÙK€ý|ìG\¸0/ö1Ò‰¾cG˜‹qÞý Rœ œœÈ¾àY³ŠîËfw§N0wdwb¯_ˆKœÄË~d:®›²’øNÀ¤"Jɨ[·n\ÖTGŒÑ›j×®³êgÙ9'ña3‹r7zžo¦–N͇  "E@D „ü¼ÿøYv ›¶Ã7™Ê»Ö˺¿Å™ âÌUºµxâ Š¸ë®x1I,ŒûïwgFpæ)Et¢X§uëØ\îò%—‡î¾¼ä÷rå±d ¬Ã8òH×=æÕWÝÎjoaß>Q¬Aûý Ëéî«Q£è<ÌAÁ4ó¥’’µ›J™Éä%cеzॗÜÐq¼6|9¥ø*1$W2e•‡ }G‘ô•/Ÿ¾tn©Áú÷ÁÝ¿eº¥[ FÇ0>/óïX)3ü¼ÿøYvfèè,A °lÙ2}ôÑNè4†P›:uªuZoa1’'8*Êሂ£fÍšã :DD ü¼ÿøYvØeº#GŽt\ç(6 »È“ïgžé†ëøøc qãxš Í™ó¼…QHÄÐÁɦ-’ õlyÊ'"^~Þ‡ü,;¼ÄUsTpò''„²Oý³Í›Ã& ]ºäöÆ–wÏ=?ì[Mð1ÁSO{î銕bY°À¨Èþoöß•ènĉÀìf¿ü¡‡W^ P†@ᣰ_ŸyXW%ð›@¹"N°CÓ¦M›Yè°=,_ ³üÕfiü0wî\›ƒ€­E¹Ý%}8ùSïcR:G…•sÊ´/rÀ®(Áéշ˜,]øë«$" "(º·•ìr0ìÉjSß5œ;9k”ŸFÂÕä×êÿüàÜ=ì©34êÕË/Wî6ºñE†¢”›nÊÝî-Ñmˆ"vR3_ÆVŠa½J;õî s_„…9°\ëèN&ñEí¯¿\–+&sDúò0”Ü‹/ºNOzñ‘Š×iút€"«Òw.–4t¨;£æª«`Î]3 }ð·‰FzOÒ(2²ÈiñÅž‚1Šç s †ÈTC÷¶È\ÊH6dŠý ö1˸_ýÕ~.µP•÷šÛYQ]3£hñ÷¬0‡£­¦NåùR ÕVðµGD 4èÞVÔS?''›µ‡iNF¹ì²ËR/ @G0ö?þáVQlÔ¬YÞÊQ€4dHÁZò¡-" "—€îqy™h‹ˆ€?fÏ訿v­Û·JÇØÄ¾îåËÝý r4w®ëÊèå)[ÖuÝç¤Â`‰¼=¹ßì,(QÄhìÛeì§7 Þ4ø`ÿoŒWIAÅ8ÛÙ—ùϺ}·gŸíŠ^yöîïŠÄÙ¿Ÿl¿w¡'ÒNH‚@¾½Z6ë­Yùòå1ÑaVF•ØrØÖªU+›S±3gÎ,Û¦M›ØÝ‘^N|ðYÂ)û)¤Å‹çä&Çê1J?ËÎ9© E9q¦æ,óãKvYþ+‰€ˆ€Š€Ÿ÷?Ë D†Sc ¢àˆ³øÒ»ìR81ÎÐ<ØaÁ‰³/ò;š"º1‚K¬eýzàˆ#rÛÑÙˆ/Z={¦_Ì‘_½’ÙFÇ¥Ã.¼?¾è#Þy`‡;C¸eZl[;¾<rˆ;K…‚.Ϊaxƒt'ŠÍþû_7”Céí³ûI÷y‚V^ºØ>е(ô»øâ µ6ÚõñóþãgÙѾ*ÙÝ: ~Þzë-›©ø¸ãŒX©R%<óÌ3N8µ’’a¿¶ s8Zh ñÓœ7o%PðóþãgÙ¡„]‚J?öØc6Ë|¡=Kÿ×BHÇu©— ÔÌj·,' Íþ9XÅwJ%ð‹€Ÿ÷!?Ëö‹‡Ê(>Ф9i’ŽAûî °/56±Îs½â `Рؽ®Ó>IÎæ£\ÆÀé§»e±<º;ÒÕ±¸é‚ €ãŽsû¤böí·£ŽrˆX·cŽI½dF&øì3Ød&àÆÝI¿|~KS¥^²Žä äµnÝšÿ½ìÏU *Æ„Hœ×}Ò‰'ž¸uýo<ï¼ó°ãŽ;”=2ÛC¥|óÍ7I·3\bJLúhsŽ÷³ìœ“ø°@ÁQa I:?0õ¦•€’ˆ€ˆ@àøyÿñ³ì €kÖA eÒ¶mÛ T)§×]Pü×Â4¿×^ Ü}·ª‹b£„²9å´+6b>š±¡óÂF¡x‚–KûœsàØØÒÕæÔS ¯!¢èNC–¥ØÙÏ—Hΰá3XÌãdZ«F>ÙžèäiÚy'`qYÜppðÁ° Å-ALJ€Ÿ÷?Ë.N[uL° pÒÑ“O>iÃhN<â»ñÖ ˜N·¡–vs(ÌáˆáÔ˜š5kæ|ëððóþãgÙá#]ü¯µ©òwÜq‡…kŒóÏ?¿ø•‘láºâV«æ†R¦Ë*«ò ¯] UÔ)E@"LÀÏûŸeGø’¨i": {FWx ¸““úõË+829ƒ3)–ý¼ù¹ðÿðƒ+(òSòÀ×òqã€1c€Ë/w]æéíÂþùâ&N¢d䊖l~“oýÅÅ­ŸŽ‹>8Á‘‰î³&ÿ3ÙfÛ,½²œ¹1þ|ÜÿýÉÚ|ÆÇ™9è…/›mÞkYldf¬PœÄY^J /ægÙÞ9ýø.ÊáhΜ9Îiƒ8ë•)" a#àçýÇϲƒÀù»ï¾³Ù pÅW¡:quàL¾`qÆDa3#øh²nÀ°‡N_Lç7Þˆ«N WK›3wi=Ûµ+Àõ‚Ò£ /ÆY-AHŒ¼£Žÿ¯­¨§nž¡ë?œÕT” n¯½`¢ÿëª3ÄðóþãgÙñ­ÐZ˜ °¯`°YR˜Lg!>ßrË-8÷ÜsÍu°ÛÁb4œâçI“&™-üZÈæ;6oÞ<§T9®€ðóþãgÙÁ—‘jÐÕhÙ²eŽÐ´biÚ¢ÒZ†á@ÅE±Hú xùe`Û6÷à:u€>pC†Rœv‰€ˆ@Zøyò³ì´4^…ˆ€”˜Ýë d¨W/€“p›6uÃÂ&nÑÍ M|ÊTb¿ã±ÇZ8)›èÊhé9¥£ŒLµ_ç‰Ó¼¹Én¼{mß¾Ýæ¡§žÆ™ï0Œ,¥Þ´¸#ʘD°G9Û¶Ù[ØçŸž³^Ø‚çôãå9‚¿1ÉϲcN“öEÎüfLÈ‚GžÅ{Ay´]D@D ôøyÿñ³ìÒ#–{æÒ §ÆG‹VZh¢ˆ†®FE9ò0C>Ñå'“/T…V>C;Ù^ò¡M.]žŠJ±òEåÕþhàÌ¢wvgÑf™ëC†¸³…Î8ÃÕ>rd4ÚµVøyÿñ³ì¨]‡lmÏ×_m3%rúHŽ1Õ/Ÿ(ø¹Á,Ïü‘3Ž˜ «&‡#þPðóþãgÙ¡†žBåWÙ´úÿX<ëVfkyöÙg§pdæ²>÷б#0q¢+ª=óe—fÎo÷+wÿÌ™n¸íشؤœ\´Îìß2½·ß~ÛìÚ{š8®«%•"“ÊK‡#¦‚ªIp”FeÀðóþãgÙ›† ÞmÊô?mV&ûÇ>3ˆ‰á58éâãÝwÊÄ:–/ÏЛn8àTÃl'–¥uH•€Ÿ÷!?ËNµÊ/"º.šqdž´~=ÌÙ×í›c¿‡è: ˜>8ë¬<ÙµAD CÁ‘͆;ÒΗ8Zö± Œ3ÁÈm6Kî#­°YyÓlýyûœdî>Œ²Ý«'C‹Ñ.<ê©Räl/M·_±çŸÞ[ÍóMKó .¸ÀépôvžrÊ)ÞbÜ·ŸeÇ(C+ëí—áÂ…q¼2tjFD@D ~Þü,;…&¦=+EÖS§NE·nÝ|DŒ­ü3Ï´Áç Tv3Qï}úéc=Û¤ZÇ­‡¡ŸnºÉÙ­Š ðÔSîLÎ~¡Fšë;ìðVIH€cFœ¡­Cà°ÃZ0Ož tê š·SãŽ;Üÿ«"Xzü¼ÿøYvé ß™7˜xy?BzÙ”ˆ|.(o#¶ï¿ÿ¾…5µi–JE9Ña©ŽýU«V-C5ÒiD@ü àçýÇϲý`¤2Ù÷ùàƒbÏ=÷D_ÆÆh:é$€ÎEšXÐ ¤j‰@–ðó>ägÙY~ÙÔ|HŠÀ‚ŸCvÚ Øw_ _?˜0ðôÓÀêÕñEL˜tî {wN8!~×n¿ÝÝÇ B¿ÿ<òðÞ{î¤À¼¹µED SÊðDæld:À¸4måÊ•ÇÛ,¸ q[cVlæÜý:uš³©ÀÙt±y¢°ùÄÿw4#'ÿgŸ×_ï†+,´íô€Ÿ÷?ËöLNÀÁÝClÄôZ‹‰Éo/Ìii5ÎÇd¦¨çÓO?5'Â3Z•dŽè´¬$"~~Þü,;üäóoÁO?ýä܇èlw‡)κ'É"¼9ï6‰u)Ì¥>1¯ÖE@D Óü¼ùYv¦9é|"›6¹!:ð¿bq“š4qEB/¾Üz+, m^ÁQ… À|S0 €E(Ï“öœs€óϾÿ¸ðÂp„NËÓmˆ°ùºŽàÈæÄç&s/z|ùòåkr·ä¿tî¹çþ4eÊ”fÞނ컽ýQùæàâ‘ò—ý8Þjñ!G¡½y¸U2˯m”je›1‰–º´ÖåŒÇ‚’ŸetÎân§ÝW_{ï 4h·”Ù´`°ë•7—¶ˆ€ˆ€€Ÿ÷?Ë.-voX@è öÔµk׌V¡{w€ŸÄÄm vß}î]rIb­‹€øA reàµ×`ƒK¹¥?ôÛÙqñŹ۴T:ü¼ÿøYvéÐ ÏY'Nœh³#O2{õe¸è¢‹œðå'žx"²ÿ|tÎtâóõ¦2¤èç=›ZÙœvhNuMe\Ãì 9é'1qbmÂXâ.­‹€„€Ÿ÷?Ë!ê"«ü‰)Ï{÷î ºþ³O¸{~/jE–’þ cÆ¸Ž¸72Ô¦ëÔ™þ³¨DH??ïC~–~*QÂOÀLÁ~1ï¶ððÃnè3¶ÌÌŠíÝÕ}NáDÚØDúß~‹Ý¿l^öü¿Mk" ¥OÀY5G$SµÃ?|EÍš5ñÇ8ÙçÎ Šo‚2›#™67…CŒÍMá‘—8Ë’ŸüÒŽ6…äaûEÝ—~qE$?Ë.âÔ)í¦Ø¨G€¡H¨DMLzÏÙ$ÁQ"­‹€ˆ@0 øyÿñ³ìLÓd¸Ô?þG˜wkB“0Ä]U”D@2K VlÄ3{¬ë8Æ¥Ò'àçýÇϲKŸ\0kðè£âr³ùã$ŸWÍÞïóX¿âŠ+ð…6µñ×_5‹õÛÓVy:öòÿí·ß¶P›ëMÔ»5çC!ÏïæáþÎ;ïX¸Å?~<êׯŸ¶s§Zêå7 Œ¡XïÒB¥ÚåHŽ€Ÿ÷?ËN®uáÈõÜsÏaÀ€`/ï]8û£”ç½Rw;nœëvkQÞœ°À¥\-^D@R"àç}ÈϲSj¤2‹@„ pˆÜ^ÑmbP¥ ÌÒ]§s‘—؇½ÇîÇÛ¦oppæâZH532ËMkÖ¬Y’»VøÒ.»ì’“a£MX±bEÎz”ªØ/åOîæì—Ï[¡#…KœägÙaá«zŠ@:0TÚ·ßÂÞ©ó–öÙ™Pld&ÄÎóÈàÁ°(yói‹ˆ@´xG;Ä4k“Y“¯Y/t±ÅÒb¼j/±#/艒³fÍ*q5éät±yÂõ·Q…q6}dúôéX²d ·›\7nŒ#<Ò”š&ÕL1ùYvŠU)0;U¨Œ½Y¯^þY(8ª]»¶óÉ?‡¶Š€ˆ€¤‹€îmé"Yt9ž{ÀîìÑÍ@2‡~üßÿ¹ñ© ‰Êššè" "Yº·e–wPÏÆwl†¬ùòË/Ñ­[7»'þè´›Rì£>B¿~ýœÉ><æ)³â¥0é­·ÞrÞׂ‰ Ë6|øpØä+ ¾7Ž:ê(çCã‘#GâÝwßuÜ›9˜|Í5×àôÓO·÷Þz`˜ô²eËÆ}*V¬[•R[¦ÃûcæÍ›‡6mrM¬¹Î$‡£R»4:±Äн-G¨V(f=ï¼óœûKÇŽûKìDÜL4æ®»†(áO;Ìl/'Ùm?ž®$g‡D@D CtËhFJ‘Ùk²Mtq+qÈ!@Œ/ Ž>jÎw)VS§È0Op{ZÓ&&Ÿ‚Ò¹–|ÓŸ³råÊ8餓œOºK÷³ì’Öµ¨X™µnݺ¤§Ññ" " ¥@ÀÏûŸeg•'8âÀ^&ÒÀŽgžuV&Ψsˆ€ˆ@4 øyÿñ³ìh^äZE± Å@ ß~½Å ¥«DA!ÜÖ†aÖèBL'"NòÒ^{í…Aƒ¡gÏžèÔ©“ãô¾Ø~`Ó/?üðCÜ}÷Ý·ù)*b>N,¢À‰ëaHt8bâsJ¬àHGa¸zª£Ÿ€Ÿ÷?Ë.~‹KïÈSO=¯¼ò ºwïŽ1cÆéxïGM§M¦L¡ˆèÑ0Ó?g™¯¦ŒêÆÉ¡J" "~Þ‡ü,;*üÕŽì&ðÙgÀ#À&ßÀž}rYpî=9Ï œçR­Zî>.5lè~â·jMD êÂÑsõ«Áö­]»Öq{bç°’ˆ€ˆ€D‰ÀÏ?ÿì >6i‘Ö—&šÑþó†‹N;Í—S¨P$:)mÓ#ûí7ÇuèœsÎ)²žtzôÑGðb&L@×®]áXñ á=|À€ÎgûöíøþûïáÅEtI*íðhE64Ÿ žšÏ)±És8RHµX*ZÔPhÄOŸ>}±ï7~§U«€ZµâÏbæ} KDk" " " i"`Á{ðüó°pâ°wd˜#0°ß~ñ‚#žŠÏ#J" "K@‚£XZNÏý¡U«Vi+S‰€ˆ€ˆ@ðǰ$™p<¸÷^€Ít9 ‰ÁB.‘ê " "rß~û-Ž9æ0ÄÙ /¼€“O>9¥]qÅà'™Ä°j:tp>ÉäjžX‡£Ø:Òáˆáà8‹[ID@D uœTyùå—›ø§–#jõ[ld§C§Ýw,\(йsn+TÈ]Ö’ˆ€ˆ€ˆ€¤J`Í€Љ˜ø½r%l’ûa?tõê0ç`ࢋ€Ývsóé_(Œ€G…ÑѾb`85& ŽŠPŠ€ˆ€”úz衾×nÅ à¿ÿÚ¶•»‘ï°uÀøüóÏW¢M›6áõ×_wš¦r®Hƒ À°r‰G5kÖ,À5WÕD@D Øn¼ñF'çO<á8ý®m¯^ÀÇ{î lÛæ÷ÙT¾ˆ€ˆ€ˆ@6°hâ¸õÖü[¼ûîî¾3ϪVÍ?¶Š€ˆ@~$8ÊŠ¶%Eà¹ç€¥K+¯Ì›}öìÙÎF Žò²ÑðX¼x1Ö™¿¬ç"àWKر»tÐA¯½ª'" Á$À›>ø öß 80#•dHío¾ú÷×{`F€ë$" " "1t,=Ú0¿ôR|ã8¸ì2À"‹;‰ßtÕïÑ8òÈø¼Zd Hp”,)åËC`Ä`úôüGr8ʃKD@D@"@ÀÄó[pD1﫯§ž #pj‚ˆ€ˆ€Aàµ×^C¿~ýl&eUŒ?:u*âíN$Àç“qãÆaëÖ­ŽhkþüùÖ‘¼Ý ›˜Wë" " …àïçùçŸïdzüñÇ-äÈß±G ?¬Ä{;vøQT üñШ°~=P­ÌhÙ2·”nÝ`.¹ëZtÐ|ùtPÌÒ2V¯jÔÈ¿ñÕ«WÏb}VÏ?ƒ¶Š€ˆ€ˆ@ dBpÄ0jüÐÔaÔ¨BR•E@D@D E ûõüµkׯ§Ÿ~*±QŠü¼ì-­'yóæÍX°`³‰\™RÍÁ D@D %Æ ÃäÉ“Íà2ìµ×^)›læáÃ{îI6·ò‰€ˆ€ˆ€ˆ€K€ÎDS¦¸¦±LjÖtŒž}øí·x±Ql>-‹€ˆ@: Hp”NšYVGé‰(8R8µ,ûƒPsE@D üÌi!–8 çG¢«ÝÚ¶^¨PÁ³¨Lë®»6lÀóÏ?víÚ«r!ªçÀè ¤çÍ›çÔ¾yóæ!j…ª*" ¥Oà÷ßïMÌ"àfƸNs¢ûÀI'Á´fžd÷À4Ÿ@ʼn€ˆ€ˆ€D–À£»ìì·p÷Ýy›yÇÀé§•+çݧ-" "àÁ³‡¤{÷î8ñÄÓZÃwßúõÖ®~¸è¢´¯ÂD@D@D@"Jà•W€óÎV¬pEG<EG´±j–ˆ@è(¤Zè.Y0*¼i°q#P£FÞúHp”—‰¶ˆ€ˆ€Dƒ<÷€t·è™g€‰ŽÓ]²Ê`xÅzM?ûì3 4mÚ´ f%CT«&6͵œ©—½° ©¶óÎ;£’¬3BtUUÒ$°É:Û ÅÊgˆ×^FŒØ¨`bÚ#"Pò8•F%tÎðàMŽ©J.á@IDATzu÷;ö_ ŽbihYD@D *–/_† õÜÒÝ.ºuèîRUžˆ€ˆ€“ÀæÍ›Í~°’ý¦›n f%CV+Šš5k:22Ñá¨yóæ!k…ª+" ¥Gàm³›9s&n¹åç÷45á¤MÓ0aäH m[àÍ7aï”é(Yeˆ€ˆ€ˆ€„‘ÀöíÀñÇcǺµgdñãŽËmÉ_¸B¤ƒ†…ç{+Z¦Ð¨~ýÜ|Z ÃQP®DÈêÁpjLù Žf3¹%¿dÂõˆ€ˆ€d˜€7x§û[†Áët" " ‘$ðÈ#8˜믿;í´S$ÛXâsÊܹs±~ýz,]º4mæ¥ÑSD@2M`ìß#gžyfZN½lÐ¥‹+6êÖ ˜¼`§ž œr 0m°Ë.°0ÙçÕGp´pá•ũLÆ 7ç8~žà(?‡#†Tã˹’ˆ€ˆ€D‰ÀÏ?ÿì4']Gÿúðè£À¾û|‘Tl!p«)nW®\‰‡z6ù)[š‘vzÏ)|ðs>†XS(šÀ—_~‰ßÿ,:s9L¿„5k€Q£€³ÎJâeˆ> Ð<‘¡Ó’MeÍ"dsͭ|" "PºÁQéVAg#‚Bª­X±œ­ÚªU«06Ku xG-Z´(0O²;8Ûõ‰'€C‘Ø(YfÊ'" "  ÷õðãS§N&¸•â6ÝWÕsbôGr8J7a•'"U^8µ^½z¥¥‰{íüò P­ZZŠS!" " " !$@—CŠF-ÁQ›ª*‹€d1 ޲øâ—¤éëÖ¹7ÈÄjt7bjݺuIŠ×±" " "8íl¶U«V-qÝÚ´î¼8春D@D@D TŒM›6áÞ{ïµNWëuUJ+ÏáhêÔ©N¹r8J+^&"aÕ¯_ßĦ«™¥‹¤Êð ³ýý÷‡ <þxøê¯‹€ˆ@²9:YRÊG _?`ëV G¸ÍðGr8Šç¢5ð`H5o¯¤­)_à E -)I/" "&“'OÆK/½„Þ½{›ËŸÙü)¥(äÚfÞýeÊ”A“&MÒ~(" Q#ð‹Y͘1Ãú9{K »l™ëZðÞ{Q#£öˆ€ˆ€ˆ€‡À¸qÀ¥—Òœxí5 B…┢cD@D Rq8*c!Dö°«NÖyµ¯5¯¡½„ufS ³º©^½:j×®víÚa/ó¥è¤,M*E’'£&NH•à(’—Z¬'°zõj,³^äîÝ»g= â¸ýöÛÌ´ùSò…@¥J•ШQ#üúë¯hРul«gÛÐ*TD R¼pj={öL¹] ›Æ)ü>ì0¹Ø¦ Pˆ€ˆ€ˆ@È üñP³fn#¾ûèÛ¨U  ðȆ͕D@D ÒŠ™È¨U¹råú…³ì³K, O\»Ë/¾ø¢³©J•*èÖ­›ý°öÅž{Më$À¿ ΦlÙ²e[§&‰€ˆ€d+†ScÒý-[ÿÔn’˜5kÞzë-ÇÝH!¸KJ³ðãéÈHÁQ³fÍ Ï¨½" " 7ß|l}ôÑ)™7øë/`øp`À€”×" " " !!ðûïî½þ‘G`N²n¥ †ö|õºðB sg72ÌæÍÀøñìKIãTM(CªÙŒ¸ÚÖ ø¤9ͲòÛ'Nl”Ì9ÿ²·-Ú¥ŸtÒIÎgÚ´iɦk®á€Hî å*6ïy¥yóæÅ.CŠ€ˆ@¶x÷Ýw±ÙlŠNÍcd&ÿJ" " " &@·"öëÞw_¼È˜aÓ(.Z¸¸ûnØû.@$†TSl!'¤š‰N0W£1 BQ*V¬¸É:²*”/_‹-²eË =„³Ÿ{î9|g,Gމ5jš_;ƒKà®»€÷Þ6lÈ­ãÒ¥KÁYAå2Ñ’ˆ€ˆ@4x‚#Ï1 ÕV½þ:ðÁî i§N©­ü" " "n=ô½;n»Q†.£÷NÞ¢E‹ Q§ðû÷ŒÊ=z„·ª¹ˆ€ˆ€ˆ€¯Î<Ó Ö¡Cþ§©S¸új÷“mèˆY§T34mÍÛÓü—L4ôÎÖ­[çØ÷œY³fýÇöîí߸q£#³Ôâ´•cy_wP­pûí)¬ì" " "rë֭ã>êLLéÕ«WÈ[ŽêwëÖÍfÙ>O<1V-E@D ”X7ƇŽ;¢aÆI×ↀ6m€ÓNKúe9‚ÄF!o–ª/" %&R­Y³f;[i#퓟Øèsí?{öìSLTòÔܹs?›7oÞÒij›ã8ƒîÐCÅ%—\‚?þw™Î{쑘&VÂ9çœãXÖæÙ© 'À‰’‰ žà¨uëÖ¯¿*(" " © Ã‘ž$•ã˜wÄ`æL˜«P¯^ªG+¿ˆ€ˆ€„›ÀSO=…•+WâŠ+®@™29]ánTÀk_©R%œiSp«V­ðšªz" "Pº&Mš„+V¤Nε·Ý<ñ`fþJ" " " !&ðæ›À.»;îØkl˜Ôål¤œ!Ò”D@D@Š&#.ªP¡:ãì´ÓN8묳BÝU^D@D zÞä(£¥ž={&Õ¸U«`ha‚Nà™g€vHê0e ×_N9¨Y8ê(÷¾Î{;çÉð{×]XiUID@HÀÙŒý¬ng$Ôoñ¦M›Ÿ?þ¼„íÅZÝo¿ýðòË/ãâ‹/ÆÔ©SsÊ µz÷îÝѨQ£œmZ' ŽÊ–-‹æÍ›‡³ªµˆ€ˆ€äC€áÔL„–-[æ³·ðMÿý/L¬<òP¥JáyµWD@D@¢FàÕW_…9$㦛n²£6eTID@D@D`ìØ±N(5†TK&]x!°p!À‰˜Íš%s„òˆ€ˆ€ˆ€‘Àk¯}ûµkâõmÛ±–ª“DƒÇV”¢MÀñ3ßa‡ÎNhææ-[¶tM—ØÈ+»¶ýr?öØcN$7žÈ† @Ñ‘Rø PpÔ´iSÐÙJID@D@¢B€‚#¦TCª™3¿c½ËÙ0F…†Ú!" " ÉøÏþã.ºè¢äRNȆͦû~=ÌÅÀl ŠH/¼Œ ôî œ}v™µ[D@D@D °l^Œ#6ªSøä‰{¡T±ÐX²d n¿ývyä‘X¹reèÛ£L€‚#{§Ú¡GB–‡mâô„miY­Q£†Å¹¶@×1éÃ?„ œb¶h1Œ(8R8µ0^9ÕYD@D 0ìˆfJUpÄÇ?ÿ„=T»±¿ ;‡ö‰€ˆ€ˆ@ÔLœ8_~ù¥J­nݺQkžÚ#" "rt7bJ6œÚ¿ÿ  ò†«ú" " "Å[{©qãÆ¸é¦›Ð¿p™É›ÐíåÑwôPp´sl³lýÝØu¿–÷Ûo¿¸¢.\·®•àX½Ú­[õê¹u”à(—…–D@D@¢E€Ä©†S»ñF`÷Ý#Žˆ µFD@D@’!pï½÷‚QW]uU2Ù•GD@D@2JàwÞqÂ:ôêÕ+©óRpÄÉ#L*»2‰€ˆ€ˆ€”2%K€—_>û æ¼_‰âyhMò#°uëVÌœ9yŸï¾û«=‘€ÄIÚ{ï½7öÙgç³ï¾ûšsØnöÜ,E_~L£¼­œuÖ‹½ð[o~&¼ƒ^Ǥe˖Ŭi1ȼߒüG­[·rÕU7H‰ÀæÍ›aÎNÌáTlÙ¸öÚTŽP^ˆN&zæ™gpà:Ÿh´J­ˆqãÆ9!Ý»w/²Y¦ŸÅ‡ÂS€:uŠÌ® " " " ¥L`åJ I˜¸¨R˜7`(5%ü ¬ZµÊœ¿¦áûï¿w>\ž1c6lØs@5бcÇœEFÔ”)S&'²—€ÅB½ØæÛ†Ìò?Õ«wZ,_¾Üÿ“ê i!ðçŸn1‰‚£òåË;±Ór"" "  ðË/¿€jþTŽPuUAD@D@J…ÀwÞiaE7â†n(•óë¤" " "P &˜#íîØyç8ãÿ|cØΓ=çœ|wk£ˆ€ˆ€ˆ@ÀÔ® \=Ю@mqåÊ« ª#¥L`ž©ð>ùä|úé§Î‡c ±©Aƒ8üðÃÑÁbz"£-Zȹ(’–ã0¤šé;s“ ªmË]óoi ¥¥1)Ö‚+f³HÀs821cNš;w®#6*WŽ6%ˆ/¾°GѸžj…ˆ€ˆ€¿-Z„áÇ£sçÎèÚµ«¿'Sé" " "P ¿þú«ãb{þùç'uôŠ@›6ÀQG%•]™D@D@D@2LÀæ» bÅø“Þ|süºÖD › ÐôåÍ7ßtDFñyØKmÛ¶ÅYg…öíÛc¯½ör>uëÖõvë[’"ÀjKcCª™ÃQý¤Ž,a¦•ô´‹I5kÖŒYÓb x‚£X‡#^φ ¹Úª›ˆ€ˆ€¤LÀµdŒ´$Í>8öØ$2+‹ˆ€ˆ€DŒ€çntÓM7E¬ejŽˆ€ˆ@T|öÙgNSæ‹[éÈ#Ÿ~J"£²ˆ€ˆ€ˆ€dœÀ¤I@ß¾ÀÿýpÈ!?½N(%`ú|ðÁΤ°×_›6mrêJ—Ï /¼‡v˜ó©_?#²ÀrRÅÒC€GKb‹²?@‹léJÕQlÿ¡§é ù…Tûã?°Ç{¤é *FD@D@‚AàçŸv*’ŒÃÑo¿·Þ p¢¬GÁ¸~ª…ˆ€ˆ@æ,^¼O>ù$öÛo?¹e»Î$" ""TG)¯ì" " " "ðÌ3À A¯Ø¥’ˆ€ óôSO=…#F€¡Òh:s¤)èû÷ïoŽG¡^½zâ$i'@‡£% GÇØYþ›ö3%8uêÔ¸-ÅáôŠçpä…TÛ¶mþúë/È¥*ЗM•(:UªT 5*òèt³Ø$%È:r7ʺK®‹€ˆ@( Lœ8Ñy¿kÚ´i(ë¯J‹€ˆ€ˆ@¶°!I\wp÷Ý@³Ð°HQ*Û©¨ýÙH`ýúõøá‡0}útL›6 ß}÷ø¬»uëV4hÐ×_=Î=÷\4oÞ<ñ¨Í$@‡£bÏg¤#mu`[»=ÝË&Lˆ+’^Já à Ž¼j«V­­Ù$8 ÇõS-E@D@’'@ÁQ‹-œ™EÅè°gœì¿Q9µ_D@D@¢E ÖÝè¸ãŽ‹VãÔÈ C;eN9å”È´I l#0`0jpàÀk¯Á[²€Ú›íÛo¿Å矎ɓ';£9s怦 ^ªZµ*ºwïŽöŸ„ßeË–õvé[|%PnöìÙ´jÕêÙ08 VÑÄ#ƒmñz¿Î³›d|´ŽZù*‰€ˆ€ˆ@¶¸ë®»°aÃüûßÿ榫½" " !"ðÅ_8ƒ2|pRµ>í4Ø`èФ²+“ˆ€ˆ€ˆ€Ïþõ/WlÔ£ðòË@ÅŠ>ŸPÅ‹@)XmîŸ~ú)øüJ‘Ñ”)Sœ~V‡B"3AŸ>}°çž{¢}ûöÎ7Œb£Z•RÕuÚ,$`‘-±É>oØç,¯ýöÇxyëÖ­‡›i®·-ßwÜq‡cçå•Y·n]´k×Î[ÕwÀ Ðá¨re7.*«ê ŽjÕªðš«z" " "<_ýœ9À‡w%ü ,Y²Æ C§NЭ[·ü3i«ˆ€ˆ€€ÀgŸ}æÔ"Á'\Ž|*®*ˆ€ˆ€ˆ€àñÇÛn:wvïÑé"jÖ¬Yƒ±cÇÚ3è¼ûî»Ø¸q£ÓÄ5jà°ÃÃAdÎ^ÚÿΠ›‘’…GT»=g_±‚£m}\£F\¸páJæIWzþùçE^ly'žx¢w±@¾Lw¶Xm‘'8’ÃQÀ/œª'" "†Sc’à(%lÊ," "eän”e\Í àˆ6œ ^TúøcØ„YਣŠÊ©ý" " " ~xÃl3.¾hÕ xë-×Áïsª|ȵk×Úßô[xñÅñÎ;ï8.FåÊ•ÃGÞ½{ƒBù=öØeÊ”ÉDut(GpôwXµWLxÔ'¦”Ý*W®<¾eË–}~þùç_c¶{ñ©§žÂwÞw|íÚµqÞyçÅmÓJ° Øï]\’à(‡VD@D@"BÀÙ³PDZ¤fˆ€ˆ€ˆ@z üöÛoxâ‰'°ï¾û¢{÷îé-\¥‰€ˆ€ˆ@ н–¡(8x“Ì€ÍÀü€ãŽKc%T”ˆ€ˆ€ˆ@Ê,¢N=°`9?ÞýN¹  °|ùr|÷Ýwøþûï—gΜ‰Í›7;aÒèbÔ·o_Ш…Ñ¡”D ,Á+»mÛ¶ -æßá¶X‡ë§N¶í{h»ÀDG/Ú¶íÞŽT¾?üðC<üðÃøñÇóvÙe—Éö+•pmXµj•Sa9…뺩¶" " …°g'C2G|ñ½òJà–[€£.¼\í¨»QT®¤Ú!" Ñ'ðõ×_;3Æ“ §FõëFŸ‹Z(" " A&°Òbðôêco¿ ´häÚªn"—6Ÿ~úiŒ7‹/ŽËЬY3'4ý±Ç‹>}ú ^½zqûµ"a!#8²Aµß[·nÍ×( ‹r¶Ûr-¶}·lß¾ýsAzÅ‘Õ@ÎùôÓOñÈ#à§Ÿ~Ê7{/»KP©§nr8 ÷õSíE@D@ò'@ÁíK›6mš†˜­6“'ÇlТˆ€ˆ€DœÀÒ¥Kw£}öÙ=zôˆxkÕ<°à`S²‚£°·Wõ(° 9¸ã IÀ^=•D æÍ›‡gŸ}ÖÍ;ש3CúvíÚ:tÀ^{íå|êWI¢@ VX½fnF½L`ô’5®JB[›ØèÛö@«V­Ú÷—æN´;gýW¯^7nÄ‚ r>´V7RB¹«´»ÃîVfîF-…’€G¡¼lª´ˆ€ˆ@hqZ«V-GtTDVsqtsì¾{Q9µ_D@D@¢A`øðáX¿~=† ©" " ‘&0qâDT¨Pûí·_¤Û©Æ‰€ˆ€ˆ@˜ Ðш‰B#/ÉqÐ#¡ï ब7ß|Ï=÷øÜIDƒ põÕW㬳ÎÂ{ìäê«n"P"q‚#–d³ùßiÑ¢Å&:zËÄ@ùzwÙöF–µÑxË,F:þøã-äÈ-I à£xâ#3®ÂèÑ@»v@ÇŽî‰$8ò¸Š(5 JÁQ2‰‚#Ó_£aÃdr+ˆ€ˆ€„›;ÎFމ]vÙ={ö wcT{Èà}ë ‹ƒMW¾J•*ÙÞiÓ€–-m6nâtÜ"TâxòI`Ø0à›o€Ûn.N):F2K`š=4Ž;Öù|õÕWŽÈhÇwD¿~ý‘ÑQGeá- ’Dœ@ÁÛkö^S5jÔ¶råÊCí…ì<¥åC} ~=tèPÐÝH)œÌìÁ~$K/Í+8’õ[8¯©j-" "? Ž&© úá@îFùsÔVèøè£Øo€ë®»N‰¢wyÕ"ˆm†ÈJ³LH6œÚ1ÇØL[›nûõבC¡‰€ˆ€ˆ@ ,^ X*ôé 5È*ªR"à ˆ}´9sÐÍhþüùζš5k¢oß¾èÕ«ºwïîD†.È&ù Ž`áÂ…4®»ÈB¬=fê»ËLxtŠ lî~êi·ÝvÃé§ŸîÌ|¤²O)¼V¯vëV’G¼®ÉÌ oËUsl#@ÁQ;Zú‘V¬~ÿèÑ£ˆŒÚ-" " !ÀpjÖ?€D¤Ej†ˆ€ˆ@” |öÙgNó’͘XD ëËŽ2µMD@D@‚Eàšk€o„½g«^ª'\=ûì³N¸´ÿýïÓOàòË/w´‡z¨&céO%« (8ò¨Xˆ5{ÍÂ@‹3xYÕªU{ÙòÁöa°kjL+Ø'OªS§:t耽÷Þ;wFûöíóäцp(SÆþì/`×]sëOÁÕ›J" " "[·nÅ_ý•TH5†ScRf—ƒþˆ6:D¼öÚk8üðÃ-܌śQ€ àˆBÙƒ:¨Èš¾ÿ¾›Å"`(‰€ˆ€ˆ€ø@À"bΠuëÜÂåU‘ËBKÁ °lÙ2§ïƒB#O¼Î°òW]uÎ8ã i‚q™T‹€(RpäÕsñâÅëlyôßn.cÿÙž_¿~}ßµk×¢B… Žè¤zõê(_¾<÷+E&NŒo˜Gñ<´&" "~LeªU«V‘ñG ©V$*eˆv¶mܸçž{nZ£&ˆ€ˆ€dµmÛœ$Ë4mpûí°"˜ÉfÖÚÔZo óƒl†­M±µ‰êJ" " " i&°mì]xùeàóÏ=÷Ló TœƒÀ6ûÜa6—“&MC¦ñ{Uq–*W®ŒÓN;ÍeŠt‹ UŒ3èˆ6¤Gù`ØV·nÝÍùlצ,#À3M›6ͲV«¹" " Q&À{“GQ¾Êj›ˆ€ˆ@qŒ1¹?žxâ‰Å9\Lj€ˆ€ˆ@F ,Z´¿üò  ”s^n~ò 0fŒ»‰sg÷ÙÇM˜p—r²kAD@D@D ÌPçœ Môèïp”†âU„$MàÏ?ÿÄäÉ“qF_~ù%Ö¬Y“s|«V­pæ™g¢K—.èÝ»7ªU«–³O " y ”Dp”·4mÉJt8Úk/FØShðGÉ„ ýá jU qãh´]­‚°núôé¸ä’KP©R¥‚²i»ˆ€ˆ€†€ãàƒΩ“EWÃüùÀ×_ÃBd¸ tY°q''õ왓U " " " i @±‘E¡Â /Ǽø¢ë(˜†¢U„I€Ñ Þzë­ÑÖ¡OW#&:uêÔÉçàÀt¾Íp¥È2•AD —@© Žî¼óN0›—n½õVoQß!"°eˬ[·Î §¢j«ª" " "P(Op”¬Ã‘¹óƒÖJ" " "eÇwš§pjQ¾Êj›ˆ€D‹ÀĉŠޏ¡bE×ш!Õ˜¶o~ú Xº8âw›þ(9 `!©€W_úôqEGtT¿ ,^¼÷Ýwžxâ‰MBc›5|òÉ';â" Œ:tè€råJM.á7•/!Pjÿƒ^ýuxƒyl©G¹Þ%>‰ @Akák®(ðô®a2%>¹  ðîoE ŽÌäK–Ç“¡Šé4" " "PJþúë/ =3Æ™ù×¾}ûRª…N+" " © ÃQƒ мyóBä’Ýww?…fÔN¤ ,[ôêåºþãÀÓOÃÄI®Œ"P,?ÿü3î¾ûnû{{7nt¢ôüóŸÿtB¤5jÔ¨Xeê ‚ ”)x—öˆ@^ ÜsÌÕÈÝÇpjL¹<ô¯ˆ€ˆ@4$+8Ú¼¸ì27îx4Z®Vˆ€ˆ€ˆ@þF5kÖ@îFùóÑVàX½zµ 4ÖÝèå—? ^]U#ˆÙ³ý÷wÅF×]<÷œÄFQ»ÆAkÏ÷ßonZ§a·Ývðaðï¾û:¡Ô¾ûî;œuÖYØ(hWLõ‰ éH£r%3Ô{OwRî·'8*Ê"CÕÓiD@D@D -’í´ðßÿ¦å”*DD@D@M€áÔªT©‚SO=5ÐõTåD@D@DÀ#ðÅ_`Û¶mˆ]y%P½:LˆäåÒ·ˆ€ˆ€ˆ@º 0RJïÞÇŸ|6q%ÝgPy"àXjñp_xá<ûì³øæ›oœÇ{,®¿þzzè¡Â$"er”NñçŸ-†«Us[å Žäp¥«¬¶ˆ€ˆ€x÷7 jõ· " " À?ü€É“'ãœsαwÁ¿_FD@D@N€áÔ˜<ÁÑâÅÀ‚ÀÀ¯¸ª'" " !&ðüó°wG R%àí·cŽ qcTõ@X¿~=Þ|óM<óÌ3xï½÷°eË'Ï@{È;ÿüóѱcÇ@Ö[•¨à(ªWÖ§vQl“ZQæï`|Þ€¬G>W±" " ¥B Y‡£R©œN*" " &0bÄçŒ §–að:ˆ€ˆ@‰PpTÝìŒÚ·oï”c‘AÑ­Ð¥K‰ŠÕÁ" " " …X¸¨_ßí¹g!µKR$@aÑý÷ß[o½ÕܳV£\¹rèÚµ+Î<óLôêÕ +VL±DeH ŽÒA1‹Ê àÈ §Æf{²eÑš*" Y@€÷·ÌÒ¯jÕªYÐZ5QD@D@ &°iÓ&gÖ`Û¶mqàœQ{D@D@D @xÿúꫯœPeË–uj¶Ûnîàg€ª©ªˆ€ˆ€ˆ@ä\s 0hÌq&rMSƒJ‘ÀÔ©SÍ¥r ¾ýö[´jÕ C‡uB¾ï´ÓN¥X+ZD€þö© HŽCª1ι—äpä‘зˆ€ˆ@”PpÄpjem(=z4*Uª„^½zE¡9jƒˆ€ˆ@ ÃQ£FPµjU§Õ6–…wÞ z¿Ë"4jªˆ€ˆ€¤…@™2°0W@:ÀW¤¥Hq3fÌpDFÏ=÷è¨\¾|yüñN¸4ŠŠøìæ}+lZÄÿÔ¼Hà(R—Ó߯0œS¢ÃQÍš5ÝúWD@D@"@€îFœUQËz¢Õ ª&ˆ€ˆ€‹Ào¿ý† &˜¸¶wÎ`m± ÒA" " "P (8êܹsΙ'Ofx5 Žr€hAD@D@Ò@à†ÒPˆŠˆ4Nî}ñÅqß}÷᫯¾rÚÚ¶m[\{íµ8óÌ3mÒo½H·_l ÁQ6\å4µqýz vm÷ãI‡# Ž<úˆ Ž˜(8Rl%ð’Å¡·oß¾ÙŠ@í)Å‹cYµïF…‘¥ßæÎÎ>ÛYÕ?" " " "  ðÑGášk®ÁÔ©S‰Lýû÷Ç€pàfàì:…ˆ@¦Hp”)Ò8O«VÀŠñ á lË–-ã7jMD@D@BLÀ탕+÷ÂæÍ0kW·1óç>MšÀ:¯¿þVMID@D@¢H`̘1NøìîÝ»G±yj“ˆ€ˆ@„ Ìœ9Ói]›6mœoº1p€û­E@D@D@ŠG€}¢ìý;biñ ÑQ‘'ðý÷ßcðàÁ?~<í ‹¹7dÈ3µ0W %Ȱ›J"P|r8*>;)" "L®àè Ö›6¹u\¸`_õ嗻믾 ì² ðæ›Álƒj%" " %!°Ðn|_|ñzöì‰Ê•+—¤(+" " 'ÀpjLžÃ‘'8ÚÿŒWE'H8èØX¾º WËD@r8‚£V­ZÍØa‡,@HjÉ~(*•+W<ÍÒ_ŒC¢jî€,$8 õUTåE@D@ x‚£&M6Ø®\W‡;îÞx¸ê* N˜,,¬hâÑZð=z4ªW¯Ž®]»†¿1jˆ€ˆ@ÖàLz:ô5²™#[·S¦û픑×Öý-¨Á" " é!ðÃÀe—Íšǧ§L•nK–,ÁÈ‘#íïa8~ùå{Î*ãô!\eçGqD¸§Ú‹€¤DÀQ ™Ø¨ŠU-¥#-óÆOªÇ)40œSÍš5£Ñ µBD@D@ŒÀüùŒ£V»îº,ŽÇ®»çŸ<ô@½uÛ¶@Ù²qY´"" " ¡'0oÞ<˜âØ W¤ºVID@D@BF€G §f}Þ˜1X»P8µ]DUWD@D 0Ö¯úö6o^xc‚©š*’atB~ÿý÷ñØcá­·ÞrÜŒ6lˆn¸çž{.š4IÙÛ$Ã-ÐéD@ü P<{"?j¢2CGÀÕªU+tuW…E@D@D  óæ•wví¶Ûy²Üx#ðôÓÀêÕÀî»çÙ­ " " "zcè‘o©/{”•D@D@D dÖÛ¨è‚ pÀ85Ÿ4ÉmÀß«!kª+" " ¥O€ÎFt8²Yð–þå(•p |ù%põÕ@—.~œAeÀÊ•+ñøã;B£ŸþÙ©ÒèèfT­Zµ TSu8 Ž~‚\= Ž‚|uT7âزظ±!jÔ˜h‡KpT†:FD@D œf̘ü\p‰neΫ¨Z‹€ˆ€Ðá¨qãÆà¬|%Ô ,] üë_@Ó¦ÀM7¥~¼Ž>%K–à¾ûîsÄFk×®µ°y;ãšk®q„F^XÚà·B5  Ž‚r%BX ŽBxÑTeB ÌËÝåLpdoÖJ" " "EènĤpjYtÑÕTˆ Ù³g〈`ËÔ$È :u€oÚ´*WÎÌ9u–Ìøå—_p÷Ýw;ŽF7nDûöíqÝu×ᤓNB¹r’ dæ*è,"=ίGëÖ­ŸµøŒõ½æÙrÿÿýï ½u}‹@~<ÁQ5òÛ­m" " ":sæ¸UÞi§•¡«»*," " %!@ÁQƒ pÈ!‡”¤+" ¾˜?X³˜3§ ¶l©èûùt‚ðX¸p!8K¿nßûû€…ËOýUSêN®¸"5QÒE€!go»í6¼ð ö|´ûï¿?† ‚îÝ»;¡hÓu•#"ÊüÝìƒ-¶õÑÞgëÖ­òœÍZMÁãwJõš6e0ƒúÃjW{ìñc€k©ª‰€ˆ€ˆ@z üôÓO6p?Ç™ÕX¦Œ×MÞs¨4H–ÀÀf[ÃB;ƒç=êì³=÷Ü«V5É›A[²–Ó˜ ä“O€êÕaÜMúGD@D@D@²ŽÀ¢E‹0hÐ ´k×Ï>û,;ì0|ôÑG˜4izôè!±QÖýE¨Á"àù£ÝqÇmvÜqÇœš]xá…¨P¡BκÒO`Æ øóÏ?QÇ< K[èCÁQÍš5ÓßH•(" "U‚vo~Gýúò Ϊ?B5VD@ÒL H÷¶dš6mÚ4'›BÐ$CKyD@<… †¶n¨[Üa/WÞ諒˜b?¬› £FÅçá6~Zý?{ç'E‘ýñ$Jœ3¢bVLQ1Ç¿zæxœzg¨”ÂѨQ£6H|°?å”SòFáè­·ÞÒðáÃ+t®ôèÑCL;íÛo¿m“/C‚/Nçø¬Œ‰Y£R›6mÔ·o_~øáêÓ§OÚùUUDŽªŠ$ù@ÈŒm²/¤ :cíµ×ÎŽN¡€ P)ŒméáûòË/ƒˆþÕ#@ 4?ÛÊÃ<"[ŽAö!œdÓcIríµ’;ÿ>±NPñ(R@Š”u„L/D«V…JJQF]$¹+IŽ?><òæ›Ótÿýù¹ruoÙ:'YÒ¹Y8êÖm}ø¡´×^RÏž%Å&€²ã[ÍõÈ÷ßK(Ýu—´óÎ5WJ®W.r%£þóŸòw¸›m¶™\Ѩÿþ•˘Ô€J!P)…£RòÍùCnnî…^¨P;·Új«´ަOŸn,iìØ±EÊYm ‘Ï;WÏ>ûlàúÙç:7Þxc°ÄY‘È ð—²n¢ Ü À؆ÂQnœÉ´€ÀŒmkX”æs…#· »þúë—c€@Ì Ø;‡@QÈ g„Üú‹[ò­;W òeÌܵon]!¨eË5 Ÿ:U:ûl©Ié ƒ$·häŠE‘l´‘tðÁÒâÅá1›¾Rä\±Èý]»J»îZ)r?R~™ß²}N²$bná¨qãÆZwÝŽš2Eš7¯¤˜„C€@6`|«¹^ùË_¤ñãCEðš«%W”Àb»ù¾÷Þ{uÓM7iÖ¬Yv/´®î¾ûn}ôÑ,›VQ¨¤ƒÒ&€ÂQÚ¨’#þðÃÉU¼7ÏžˆO8á͘1#­œ}ÍÍÃ;LÆ ,¥•¨’‘|i7–T«$D’CÈ"ù>¶ùK‘_´O±Õ™ñ-‹ÎKª@ 2ò}lK—+ùÇ$,‘ž.1âA ó\9ÇW;4£×š0!TðñUíÝgä\¹§[·äºØ´fÏ-Î:+Tî‰b¸R‘‡•Gî¿_2ƒæ…â¶GŒöÜ3´bTx Àsä‘’;$³29¾ÅaN²$ºnáÈÇ3· _¯žÔ¡CI1 ‡ l$ÀøV3½â÷š/¿,w\¨^3µ ÔŠX°`Y¥ºK·Þz«æÏŸo÷>‚ýÓN;Íî…ìf P P8ª äÄŸæÍ››©hA™ž´jÕªÔˆKm褓NJR6jذ¡vØaí¸ãŽÚ|óÍSxšmàÇ̆õÂ… ƒü¦ÚgfÿûßÍœôý×Xu³|^OŽJíJBˆ|Û¾úJºùæí­Ïþd/qìM@±'ïc[:èÏvß}÷]°Tw:ñ‰dŽÀ›oJï¼*™amÙûƒRåºë¤K/MŽrà Ò×_‡aÛm—¬pÔ¶­ôÚk¡Â’M3©Aƒd·bE¨¬ä K‘³i¨"rÀE‚¨f™ßâ0'Yjÿ²ß-3õíÛ·¤(„C€@–`|«™ÚdéÓO%¿WDâAà'[£ø¶Ûn ”‹|é´nöµ¶®ñ‰'žh÷øv“@¨F(U¶/gæ°‘¸æ¨+U•<ù䓚4iRav®…úßÿþW}ü3²ñè#í³±ãmñúÈ’¯­þÔSOéˆ#ŽHˆYõ^À\P8ªz¶ä@ &0¶ÉÆÞˆü7¦pÄ[”ˆ[@q%ÀØ–^Ï}e·«Ì”J¯^½ÒK@,ä9Ÿ=:tcÆ„/f¶ÜRr·ÕV²¹Ÿ+)’/E6t¨´h‘äÊB_œÏ¿*÷ü]hë­¥v’)O„yºu"[Ù¾Ðù´LÊ4QÙC…Ë–ù2hÅ-WÖ¯_r™©{®wï–“ì%Éñ-s’%õŒÏ¥:·p„@€@ü0¾ÕlŸmºiÍ–Oéépîh4xð`{¦XÜ÷øþ1Ç,“ž^.Ä‚ Pµluv¤¼æÌ™X÷‰ÒuïÞ=òVz»lÙ2Ýwß}IùÜ`Ÿ§¥*E:uê¬ÉíûÖ'2-(eš0ùC¨^Œm2ë€R«Vs üD,UïéGi€2B€±-=¬¾œš Géñ"VþxöY©wo©KéÌ3Ãe'̵-E(=ý´tÑEÒփzö”Î;¯(«uÖ •’ÜBÐzë=~÷ÝÒ»ïJ¶‚½ÞzKºþz©ÿP©ÉËÝl³p™‹ƒ–}½î§æâJO®¬Ô£‡ì¥CêQös@¦Æ·¸ÌI–Ô‡'N´CëÛ ¸³õ¿ÿ•‹p@ÈVŒoÙÚ3Ô+øŠ7nh¢§=hÜ~ûíö,±žžxâ ùDn”¢.7þÙÐMÔyK…£ t}¢YG_ê¬}ûöÈ¥ø$#FŒÐܹþ²3”=öØC”a«Ú•‘¶Ùf›(‰ÆŸd©ð@z"…#–œ©B¨d@  0¶IG-[NæJë…/Q8ªÁs‘¢!TƶôH¢p”'bå3R¸$Yb«]9ݧkN8AfYZš??\úÌ—å„̶Ž=6TB;61uè¿ì²pI3W^:ôТÇ vØ!L_ô(! dj|‹ËœdIçÁ7ß|c‡Î°9ÑÁr%Å#€²“ã[vö µª9n‰xøðáÁr±ÛÙZÉOÛW{íµ—^}õU}öÙgRíڼ毹¢d@ "À•("QŽm⯋YËgªHÞy礜v÷ÏãÒÔ%Ý^xá…4RUùä|òÉЂ¨Á@IDATògw÷›î{ã,kÕr˜ GèÜiÓ¦¦ªêIÙ?þ¸0oWdÚe—] ÷Kó$Z8òx(•F‹c€ J€±-$òË/¿¨iÓ¦ªW¯^*"ö!@ fÛÒë0Ÿ´ÜØ´+ø22=^ÄÊN‹‡Ë‹¹Þœ+ ™\ ¨sgiÓM(x`hè”S$3&­çžKn‹§ùôS©{wé %·t”(uê„Kð&†á‡@MÈÔø—9É’˜ôQ;´¶þüg¦»KbD8 l&ÀøVý½ãV;mU.ÙB.H–xؾbc_0m&ùý·1xðàà¹=˪Iu Xͽ'B¢¦uwŸ‰ª"ùî»ïôÓO?æÖ»woµjÕªp¿4Ϧ6ƒæ_¥.ñOòL¦Lñ¯z2'þBÖ G™cL΀ª“c[HÛÇ7– ­Î3² dŽc[Ùlݲߌ3øB²lTÄÈþåµ­(( ]y¥´Ï>k*å/I–.•Z¶”ºv•)K+WJ>uáÎÓúvÙ²0['š9sMúÈ÷õ×,g±`›½21¾ÅiN²¸žq+3f P:KtÜq¦=ˆ@€@ì0¾Uo—Ùj]f¸ TÚïÒ¥z˦´Ò ,¶¯).¹äµnÝZ÷Üs°Ä_:/ŽB5O…£ ôAêÏŠ+4vìXùZáî&ÙLVû”nƒ 6Ðú믯Í6ÛL=zøW6¥Ë¸qã’"xÚtÅ-1t±»‚p½riùòåZ°`™øN°ñnfiÄ‹–œAá( XD ù>¶}þy¸<ÆìÙmL™öôU„ ²äûØV?>a„ Z¯^½Ò‰NÔ(›s×3Ï„K™MŸž\•ÚfÐdâÄä°âöÜ’+&­½vqGQ6*ž ¡ÙF ã[œæ$‹ëÑ£çjÕª>êÕë]› ݱ¸(„A€@–`|«ÞúðCiî\éÔS«·\J+›ÀM7ݤüQwß}7ÊFeã" P8ª@'$švt‹D|p d”šÕ{ï½ùÒhGÙB¨çw^°LKj¼h?Ѻ‘‡•W™'UËÕó«ˆÂ‘Õ4ÑfêÜTŸKƒ 4dÈÀýCá("Áˆ;éö¶âB_3¡@\‰tÑ¢Eyw3Ÿëc›÷³·1Û¼»‡ªúõë=ÿÁÒwø ¬µlÞ@œ#l Ä…€_ç^z饠º?ÿü³-”²>P\RÁzæúØ6gÎÍŸ??iló¯ËóéË©¹ pTÁ“Œd•"`ßIiöìÐÒ[r%¢/¾>û,\í­·’³¿à‚ð…Èn»U\1h­µ$wH| Gåâ«3¥>oÄ£Ô2](¥Kª Þ\Sù–-ó üãeæàû=ö˜^}õU]sÍ5êׯ_±iü¡:QÊ3QìéR•‹üÇ[‘%ßÖYgµoßÞÖ<ÿsPÚþ©`Š p”„]@ ¶ZÚº ÑõÎá7ò®h™O’c›/Qê.±¯ëÖ]säËl¸,^ü™}ñŽ•‡ÿ!¸Øi§ -­~hŸ/~æoñóDòalóNܲnâØ¶V95)¢ÉnŽòä‡Q Íô¯¤m¥>³öœ\ØH#GJöM¦ÿ,g6ožL29žïuêT4½‡o»­ÿGòÀ¶v"øœ•‹[åùßÿþ—WH25¾eËœd£F‚BǶ²–¼öåßxc;Þµ%BÛäÕù@c!Ü °ùæ›~ø8yòd=òÈ#¹Ñ°r´"×Ç7GѱcG[òwe¡Rmêû¼r઒¨Ï?/µm+m³M•dG&UDàÒK/ ”¯o¾ùf%Î]WQödj#°á†ÎWÍ´/Œn¿ýöj+›‚ªŸÀš7mÕ_v,KLÔ²Nl€[1ò%жØb‹à‹R¿1?~¼ü«ÓHæÙlÚÙgŸ­§Ÿ~ZþCK•Ô‡ûT‹E©ñS÷SãWT[Ð'­=¯¾}û¦Q¸ï GÞæÔ2 #à 7NºÞ¹’e¾ÝÌçÃØæ/`Sû:ñµQMÑlµ-±ñ)í”x? ØXwÝuåÎÅïßý%_$ƶ† Ê]iÏmeõ·+ù3]'×ð@ P #F„Ö‡\‰Èt•jÈ>è6‹k¡å"_ÎÌ’vÝUfµdóÓp“M¤Ö­+Q’æ<.]ºÈ‹¿´‹¬‹ç|à ˜©ñ-[æ$Ý­?—gl{øaiùrŸâ¾Çæ[oÌ—SvB9DÀQܹøüUdÉ/‡šXfSr}|sþÜåûÊ3Æ• ®‚~øAöþR:é$Ù{¾ fB²rð÷ÅS§NÕ€RLJ;V=ôöÞ{oõïß¿\ùÙFÀ›¸sñùÈ|ûÈ?Ûú#ÓõA᨜„ב’º5ŒÓO?=øº4 ó­/ËãƒÃwÞh¤zØr³þ·¿ý-¸iôÉáDI}¸/¯…£¦M›&fg_Ú§ƒaáØÅY?ÊP‘d @"ÀØ&[UêÚu¹mW™Â‘½C @ ÖÛÒë>W8ºQz¬ˆåó¡"Ñ+¯H7Ü Õ©³†Šݳ§tÐAÅ["²te«"!€@% dj|‹Óœd*ÂÏ?Cš4SæÒk©iÙ‡ ì ÀøV½ýÀrjÕÇÛä}¥_ýÆßû²±÷Þ{¯Rßçzüݱ¿sõåd@q"P¬ÂQ:u2k=e.»téÒz‰}ÞlðUTCíàƒNÌ*ký‰7>~á¿òÊ+uÔQG[_ÿ"ç$SÞqÇu衇ƒ‰Gœ2eŠn½õVýýïOJçƒÅ¿ê)ø`•(™´>ä GåUˆJ¬~@Èù>¶-[&}ÿ½e¿$P} ‘¸e³·ÌLìgœaV_Íì+@ FŠU82Eš¦Ó†T :®|SQ‰‹Â‘¯!~ì±ÇjáÂ…‰ß®]»–Ùä 6Ø ÐL4hPaÜW_}µˆÂQ›6ÉëŒ{åSKŠžÉ¦(%¡f€@¬ äûØöÝw¾ƒÔ®ÝoA?früŒõ‰Bå!Ĉ@¾mét•[7rÁÂQ:´ò+Ž[ q£Ñ£¥>’V­’}i+¹RÑþûKûí'õî_Lh-²…@¦Æ·8ÍI¦öÅwß­ÒêÕSåó¯ Ä“ã[õõ›/Œ2fŒÔ¯ŸÔ¸qõ•›o%ýç?ÿÑù矯%K–è‚ .е×^ì¸ë®»‚ðìë›Í ìÀµÌ¾†½ð ƒUeÜ@ nlÊ)·àäköèÑÖ^)[Ù(ÊûÄO´Á{Íè=cÆŒ@i):îÛÖ­['î9žt°˜?þø#)´eË–IûU¹óË/¿`á¨*’ $ïcÛ7ß„ð[¶œxP8ªÁ“‘¢!T|ÛÒÁˆÂQ:”ò#Ž+)ûšVêÜYÚb éòË¥¯¿–;L¶T¼d±ô§P6ʳ‚Vf+Loqš“Lí›aþ° ýÌÂц©‡Ø‡ ˜`|«¾Žr«¥ní}À€ê+3ŸJš5k–öÝw_yæ™r…î7ÞxC7Þxcáê@®`ôþûïÛsWgýå/Ñ!‡¢ë®».XçÒK/ Òä/Ú äŽª©Ý4ñzë­—TÚW_}•´_Ù‡û¹nëï<ÙĸlÉ=™©Ù2þT~° •ÈUeoqš“Lí£iÓ&ZÐX8JÃ> < Ëã[¦ºÏ—SsqË¥HÕðw¦nÅhã7¶%©_”¡7nœvÞyç"…la_x|úé§:úè£5|øð /·vÎ9ç‰K 8@á¨{)Uá(UA(õáÞ5aË#3g†/J=Mݺuó{åIŸnÜE‹iùòå(¥ Œx€r˜@.Œm‘…£† §=……£>ai 4äÂØ–F3å GmÛ¶-bi7´ÄÉ«W§__Eﯕî¾;9+=ü°4y²4ÑÞÛ›eíº«Ï+$Çcˆ7ÒÆ·¸ÌI×_»96,G‡0@¹O WÇ·Lõœ?ت^êÒ%S%äW¾¿þú«®ºê*uëÖMW\qEð|ýÜsÏéÁTÓ¦MK„áÇ}ôQÝÿýU£Ûn»­Ð R‰‰8@ K ÓG‹/Þ²aÆuÊ[Ç1cÆÜݨQ£ÃË›._ã礦û”(¾T[¢¸†kºâË©%*(m¾ùæríîLˆ .X€È]ò„ /¹0¶¹…£V­Üœp¨è‹ÂQ¼ÎAj @ ª äÂØV“Õ¦¥2aÂm³Í6eEåx–xöYé²Ë¤i¦/½ûîáÊf¹_;_á{î‘Î:+ˆD²dÉvÚiÑn©Û9sæè»ï¾+ŒÓ¡C­µÖZ…ûî©]»¶M î˜ÚóýU«VéÝwßÕ^{í廥ŠY›J:¾Ûn»%íWåN¤pÄ Ùª¤J^€j†@¾mKMuºgOië­¥yóB…#,øÕ̹H©€ªŠ@¾mépôåÔ\P8J‡VvÄñ—êçŸ/½ô’T¿¾ô—¿H—_.ûJr#Ä/¿,-½ø¢lÞBÚh£d…#7°üÀÙÑjTŒ@&Ç·¸ÌI¦’»óNé£þe˘¼zˆ}@ˆ Æ·˜tÕ´{Ž‚wÂ_|ñ…|)¿{ï½WGqDðn<€ò™@í|n|yÛ¾}Êg€£}6/M¹Óž€—/_^»$… <°0Ž{î»ï¾¤ýâv\è©§ž*<äKµeÒŒp¤pÄ ÙBäx Ä–@¾m È”{%[&Û^Öý(7ð@€bK ßǶt:…£t(eWœ¹s¥W^ -¹uF³Ü(y-[´ŽY“&MÒsÏ=WuèС"_³³W¯^jذ¡¾1çné·ß~+ŒçžM7Ý´L… 8@o½õ–F¤]µj•®»î:›p¢Þ½{ùòÉ'š6mZRÞuëÖ 4këÕ«—^Õ;X8ªj¢ä@ f 0¶…ü]áÈÇr€âO€±­ä>\¹re`~=ö(9Gªœ€Yá×gŸÉ>’LßËžëe_É&Óª•´õÖÒ¡‡J‡’|Œ=@N Óã[¶ÏI¦ž³gςڷoŸzˆ}@ˆÆ·ÌvV›6R§NÒŸÿ,5nœÙ²âžû„ tå•WêÙgŸ šân¾ùf[ÎÚ "€ P,J+}gv¾ç¸zl%%uÖJf—Ñänqhþüùzçw ËY¾|¹¾úê«À¦xü¦éÜsÏUýúe¯+î&ù\YÉ"™1c†Ü'5Ò]wÝ¥­¶Úª¸ÃU†ÂQ•â$3@YA ßÇ6ïßXR-+NG*@ J0¶qòäÉZºtið±Lñ1­,ûÖæ B墱cÃí”)Òj_ù§@Š[ÍΦ lÎ ŠÁ€@ñ2=¾eóœd*‘Háˆ%ÕRɰ@ ~ß2×g¾ìò«¯J¾EŠ'àF$üè‰'žV¬9øàƒƒ}7"@€@éÊT8²%ºšY»ÔªUkûò S0J2ÙóÐCé±Ç+½”4ŽúÅ<.â Cn>ïÍ7ßÔwÜa_'Ú牥HÛ¶mõÏþS;ì°C)±’565c_Žíßÿþ·|ðA-Z´(9BÂÞ¶Ûn« .¸ °ž”œ1/ GCKÆ€jŒ@¾m‹/^¾¢pTc§ C¨rù>¶•4z~uë¼HÕpãÆ£GKÇK/¾({†óöIýõ×—Ž>ZêÓGÚrK·|,¹5#€@Edz|Ëæ9ÉT^(¥a€@| 0¾U]ß½ô’´ÓNÉÖŒP6*ž¯ßK\|ñÅ6l˜Üð~ûí§k®¹ÆžÝìá  ´”¨pÔ£Gž¦dtyíÚµÿÏr â™ÿºÔ\W'~¢—z0Ç÷wÙe¹kŸ,~ûí·š:uj°ÌYË–-eŠZ3ŽÁ:âÆ²Ü4Œ·(_¿ö…^Ðøñã5kÖ,ùKÑ:¨sçζÞj?mRܧ‘å.-ý®päukÖÌuÑ@È%ù:¶ùrj.(åÒÙL[ „òul+©ÿQ8*‰LåÂm~Úžßï†ûö•[ºýöÊä–ûiݰÄùçŸX½ßsÏ=åV¶ÜÀ@å#PœÂQõ×_ÿFËÆ†£PѨ|Y–/vƒ b¯)º¥}¢è.S²ÖZké°Ã \¦Ê(O¾®pÔ¼ysUD‰ª<å€jŽ@¾m(ÕܹFÉ€ª‹@¾m%qu…£:uêhà 7,) áeð%Ó6LŽtè¡’MoŠFmÚ$c€@& dr|˶9ÉDŽÏ?ïËÃìbA P8Jƒ€@ŽÈ×ñ­2Ý÷¿ÿ…ÊFf'A^X™œr;í[ïú´ÓNÓ믿®Ž;ÊWò0`@n7šÖAÈ $…£6mÚ4iÑ¢ÅãVÞ~-³Q£FZ²dI©ÉÝ4¢_Ì·ß~{õîÝ[¾Ä‡€+ÙyŸ SS@€@¢åB±pT(C€@ì ¸Â‘[äm˜ª1û–e¾þÅð£Jÿ»të­’+EÒ®tÊ)Ñ[@È4~} ¹B«WÏÒ:묓éâÈ€ õFŽ «xÏ=2Eš¬¯nµWЗL»å–[tå•WêûŠäŒ3ÎРAƒXÍ¥Ú{‚!\#¤päÊFfµ¦$e£Ù«V­ZV€—_~9ˆòÝwß)r¯¾úª¢5µýà²eËä–¶Új«²²ãx@á( ;…*A€@¥`á¨RøH @1!°téÒ`9ðƒ:(&5ήj^t‘tÓMR«V’¡D @  ¸ÂQƒsÕ¤IKÕ«W¯kBÑ€ ì 0j”Ô£‡´ÑFÙQŸlªÅ¸qãtÒI'iìØ±²U~4xð`í´ÓNÙTEê@ ¶ Žì{ªµ"IÙhµ‰) ½dá÷Oš4Ɇ*­HmiqËjµmÛVîÜ‚‘Ë_ÿúW›”»I?îÆ“Byä‘GT·n]]rÉ%QÛ˜ð—²]ºt‰Im©& @ l(•͈€ 'N”ÕÙ«W¯ø7¦ZpòÉÒòåÒWHk¯] H@($Z8šÆrj…Dð@€@>øâ iÚ4›ÏжÝ^sëöÛo×Å_< û;éË/¿‹¿EQ@ Âj{ÊÖ­[7µÍ-‰¹¸²‘Éi¦h´¯¹áv¬ˆ²QbüÒüMš4ÑÕW_­‡~X:u*Œ:tèP=÷Üs…ûxâAà·ß~cIµxtµ„ 4 D G,š&0¢A€@, ørj.(•Ü}¾B¼/Epâ‰Ò'Ÿ$ÇÛ`ƒp)5”’¹°@ º ,X ýú«MV¯˜¬öíÛWwñ”@È:ÑrjuU«± Í™3Gýû÷ŒbtíÚU~ø¡®¿þz”j¬G(ÈUÂÑÚk¯}˜5°IÔHS4Zeþ“&Ož<8 «Ší6Ûl£»ï¾[µkÅY^sÍ5š9sfUdOÕ@`áÂ…0/d«6E@€@µˆŽìž¨Úʤ @€@u?~|P$ GEÉ-rˆ%x 4dˆôÖ[Eã@5O`êÔ°Ë—OÆÂQÍw5€ , à G>­Ù·oT& ª0Úðz÷î­—_~Y'›©ÚO?ýT}úôÉ‚šQ@¹G Ðü±eÑŽKlš) ûöÛo‡$†U•à 7ÔQGU˜Ý¢E‹’–Z+<€'+ üꟙ p”•ÝC¥ @ ‚P8ª 8’A€@¬ØGEÁ@={öŒU½3YÙ öß?´l´õÖ¡£ï¿—þö·L–LÞ€ PQ¾œZ(? p¡` @yKÀm:Œ+í»¯T·nÞbþÇèì³ÏÖþö€·ÜÖÃ~úé§5xð`5nÜ8¿ÁÐz@$P»GMÁh×Ä2lÿŽÄýªöŸsÎ9I +#FŒÐªUnT Év(e{Q?@¨Ž*B4€ 73fÌ–ž©›ï³ÐÖq>qçÒFIÃmù#”¦M“ÆŒ‘Î=WêÖ-n½K}!äŽò§¯i) ”M`Ô(iõj)ß—SkZW[Û$wÚƒÞ.»ì¢qãÆéÐC- 1 @ Rj›u£íÌÕJÈå½)S¦˜.læÄ­ãtÐA…Ìž=[|ðAá>žì%)±äLöö5ƒ òp…£úõë«Q£FåOL @€@LLŸ>]:uŠIm3WÍÏ?—¶ÛNöå«Ôª•ô 2ËËR‡™+“œ!@ ê pTu,É €âOÀŽêÕ“öÙ'þm©H ܪÑÅ_¬m·ÝV“&MÒõ×_¯×_gߊÀ$  p…£Ô)µ·*O¹“¤špÿä“OÊ ªŸ@¤pÄ’jÕÏž!@ s||kÙ²eæ g@€@ X¹r¥æÌ™£Î;×pM2_ü²eÒ_H¦_UD®¹FÚj+é³Ï¤ /”&Lú÷/@Èb®pT«–™rÐt–TËâ~¢j€ y‹I¯½&³è#5k–ùò²­„·ß~[›m¶™ ¤>}úØÒrcuÉ%—K‰g[]© \%PÛÖ1±q¶´™ϼ¬»îºI…Ì;7iŸì$€ÂQvö µ‚ Êp GXï«CRC€@v˜9s¦\é(×-½÷ž´É&Òæ›K·ÝV´O|2ÞŽlÚ&¥¥µÖ*‡@Èn®pÔ¤ÉB«är޲»«¨ d˜@ÆÒóÏK—_žá‚²,ûßÿ] –NsK¾7Ýt“Þÿ}õêÕ+ËjJu ä>ºÖÄ$ Gfñ¨ZŽzôè‘D׿´D²Ÿ€¿uÁÂQö÷5„ ô øøÖ­[·ô€ 33fÌjœë Gß/ýø£tÁÅ/)0t¨Ô¥‹ì‹×˜u Õ… Bµj¹ÂÑ,-4£víÚ†ã ä:u¤ÝwϯV¿`kbŸy晚6mZ p4xð`¥®ª“_Dh- š%à G©Föæ—§J~Q?ꨣ “´jÕªÐ_šÇVêØHè_XºÌ›7¯´èËX8Ê’Ž € P¥\áhs7…€@€r”@¾(sŒ´ë®fÊ9É–óšNE¿x |€âJàƒ¤¸@/½TKµqíDê @('Y³féÜsÏÕ“O>iËÇ5Ó=÷Ü£ÓO?Ý–Y5Md€jŒ€+¥jú´)OmÚ¶m+wå•…ö J¤läi—.]ZÞ,ˆ_P8ªè @%°lÙ2-Y²„‰êŒR&s@¨infÞ%—,Ù®‰¥Þ½“é–¤l”‹=@ˆ3Ù³g«}ûö¼dŒs'Rw@€@V­Z¥ÿüç?ºä’KôÛo¿éCÑwÜa™”ð•Iy€ªŽ@íÕ«W'­efû«.û’súé§Ÿ’®½öÚIûìd'޲³_¨ TœÀÏ?ÿ$æ^¤â I @ÙO ×,=ÿ¼´å–áòsçf?j@UKÀŽXN­j™’ Ä‹À;ïHS¦Ä«Îå­í¸qã´Ã;èÏþ³š7o®‘#Gê™gžAÙ¨¼ ‰@ ƒÜÂQø™cA!fznóÞ“Á2ƒ¬'L˜TDºK±%%b§Ú ¸Â‘/…×´iÓj/›sˆ€-]¤+BçË*çüxqáë¬#m¸aé0V¯–ž~:LoÚï…™Öô­;çÇ£mäïlz—™^øØËŒêSXÁb<ö›ÓòåkxEéj×ÓGm‰¶žEäoØPjÒ¤˜L‚úh}üñÇÚzë­uß}÷ióÍ7§Ñ@9J îäÉ“§¬·Þz_Û—ŽymÛÐ& ¯6ï9™j³/§öÆo$e¿£+\ YO # Gß|#M›æ3àfoË n¹›9s‚‘[_qåŽâÄ ÒQ2pe¥ùó¥ß•uŠË«¤0WÔqk9eɾû–\ϲҺ‚L: G®0äÊ=‘¸²’+JEÊRõëËÞ H®Hù=Ž+|”eé&Êóë¯CË6fÉ*P†òôî|ßóu¿—‘¸Žo²I”Ké[WRqk9Q:Ï;Ñ•îq6 .U¥çïGŸ|rM;|?RŠü¾uñz¤ºnÝ‚C¥þó4ÎÕëê¬}ëý9?ùWÔѶOŸR³zºÓN óöü}ß%j‹oS•œ¢ã¾íÛ×ÿ—.^[ãyGÎËr).o—ê“Îׄ®ðvíµá›!//rž‡—•ù}?êïóõ×¢”úÏó2¤ø(Q_DyFÛ¨|Û½{ñi Í Ñr¡X8ʋ€ò–€+uò6b&nù›xíµðvÕo/»Lr£¤ 䇖† k4œ%Õò¯ÿi1 „leQõê%p@nyôÑGu†½?Z´h‘.½ôR]uÕUö*¢à}En5•Ö@ÈÁUÚÌÑ=aŠFWE­2ÿY¦„ôè·ß~ûaV•ÛAƒƒE”§¿àÛtÓM£]¶YLÀ_ʶ¬ŒušâÚæÖ‡\Á(Q\Æ—ÎòÏUÝ2J۶ᾇ¹Å—fÍd ¶ÊjMLU²?q ?WÐpÅ£HùÈ•F"çeÜï[?¾pazÖ¼d·Vã–…RÅ•¼¾nÊëîÛȹ‚G¢QjÚÔ}W[wÅ WüqFž¾ªÅïT3-eYö©Šò;¬*r)9gïÊr™¿‘¾÷ÞL–*zÝygfËð߀¿ʤ¸bÒñÇg²òÎaX8ÊáÎ¥i€ XeÏ@³fÍ2ƒŽ[ÅŠÈ3ÏH'œ>žù­žYÔOËøl¬Ie!@ \¦Nõ)ÁefL|1ŽÊEŽÈ€ KÜ†Ãøñ¹Ó"W0hF2$Xü¹çžS?wˆ@€@ÖŽL‰äSú9ÓL«#ºæ¾{÷î}¿ÿþû*}£þØciĈI`N<ñD3nb/‹‘¬'à/e×Mgy±ò´Ä܈¢ê_Üú¶ª•šë)¹PUŠÇ’ò( uéR¡"H@%@á¨d6 Ü àÊF+ìC‡¸X8òoD\¹èúëÃoO^z)\…:7zƒV@€@eì°ƒPžX¾ÃÂQeH’€ >ÿüsuÔQö}÷7Ú×V:t¨Z·n•£€ P&3;á+MÍ_h F6—$­ÍLÝ›=zôØ')´‚;KÌbÌm·Ý˜¿KÌ¢™)}sÌ1‰Aø³”€YÂÒ‚ Ì8Yè)M~üQfëPò¥–Ò±Þsæ™2‰Ò~û…ÖŒ2©lTZ½9@yI R8*s|ËK:4€r€/§æÒ9&ëÙw.6É,m³4v,ÊF¹pÒ@UEÀ ç«ÿQAvíÝ2:@€@l Üi«/l·Ýv2ãºå–[ôüóÏ£lÛÞ¤â€@¾,yã'Mš4Ø–QÛË`¸Å£Úµk¿`á÷™ ö›§L™29:–îö矶uµ‡é‘G‘/Ç•*—™u›&MÂu·S±Ÿ]\ÙÈMñ—øBöý÷¥Ûo—Üî½+õì)¹cß"€ ,%)ù¯ @  D Gq±pÔª•ôúë’xmÐ {„6A€@eÌž=;HŽ…£ÊP$- Ä•€[„õ…<â,þîØW¿9r¤ì´üqõéÓ'ÎM¢î€ò–@¡Â‘XelÜÔÐ:¦h´SDÄü¶Ö•N7Å£Óì¢ÿ?ó¶xÙö³(N´ue”yóæéG³p3sæL}ôÑG>|¸–-[EIÚvØa:ðÀ“ÂØÉ^‘ÂX…#¿»9üpéÙgÃÊï¹§tÎ92Û‡áRiÙÛ$j@ Gœ€ ë²]áÈ)}Ú aÃ5=asÎ @ X‘ÂQÛ¶m‹=N  @ W ¸ñZ3$·ø×ÅcÞzë­`åN=öØcuÏ=÷`˜"WOXÚäD…#MžYÛo¿}rM/¹$T6rå±üCÚh£äãìA€²˜€+Ù2²<ØfqQ5@¨lU8š6MúïCwÊ)’@F @e˜5k–š7o®F•—€ \"0x°Ìèƒl%’øµjåÊ•ºîºëtíµ×cø!CtüñÇǯ!Ô€’$)ù‘©S§úºgý{öìy¡Y5ºÎüEâxªR»JµûM)  ĉ€+±œZœzŒºB€@y LŸ>ÝŸáÕ¡C‡ò&Íh|[}]W]%uêÏ óŒÂ!s@(BÀ•T_~Yš1c¹XN­ @ Ç ˜¾Žx@êÜÙ^âöWc}eœcÌ$Ó›o¾)3f,¡¶þúëǫԀŠ%PÒ*Ÿ«ÍÚÑ ["m[KõœY32畟ÜÜk¯½ôÌ3Ï lT9”Ù“zÜ8餓$SD –SCÙ({ú†š@€@Ú|ÉPŽÒÆED@ˆ!·p´Î:ë¨AƒYU{3 «Ñ£ýÃ'iàÀ¬ª• ,$ðöÛÒOHsçNCá( û‡*A€@f ¼ð‚+ÝJn¶vIow3[… ån†.´Ã;ÊFgŸ}¶Þÿ}¡lT!”$‚ •ê–V+S:úÔŽ¼îºë®g–‰Î1ÿ¾æº—–&õXÇŽÕ·o_p ²|R³W?ÿ,t´|¹L‹,T:Šk[¨7 ä5·p”mòºCh< T9W8êäf„jP^}UjÖLÚf›5•hÛÖ&|– ¤Aà‡|,Y­_ýÁŽü;Y€ ?î½WªSGò7â"nm·_¿~¦(5C?ü°Ž=öظTzB€@šJU8Šòøî»ï¾5ð½¡iv4‹G;›Ût÷Ýw?¬~ýúë¹e³†dk†¶(t¶$›¶Þzk¹Â’cÜnã‘GJß/Ý¿´ýö9Ö@š@ùDÀŽ6Ùd“|j2m… <"`Ïîš5k–6ß|ókµYÍ×H®`4i’T¯^U…‚!@ Æ\á¨C‡åš8q5ŽbÜT€ÊOÀôvôâ‹Ò€²÷®åO_)fΜ(¹…£|e£šèÊ„ P ÒR8J¬Ç¤I“~´ýÇÜ}ûí·¶R¨ÖK<Ž?\t‘䟧žqFh»1šL!@ 7 ¬X±B¿ÿþ{ 0›-¤U€ ïæÌ™£eË–Õ˜…#³–¯ý÷—|î§ŸFÙ(ßÏGÚ@ ¢LVþ²uÛm›Â‘_ѬH@ˆÁƒe†¤ÓOGÕý9Ô-M™2E÷ši&_ Ü$Pn…£ÜÄ@«Ò&ðè£Ò¿þ%['OºãŽ´“€ –,Y¢]wÝU½{÷ÎÆêQ'@€@¥ ¸ {—šXRmìX©ÿ° þ5î–[†~þC€ÊKÀŒõ™­/©öK´]»våÍ‚ø€ XðEGx@êÚUÚ{ïìoÂüùóe+äè›o¾ÑÝwß­SO=5û+M !@ ÂP8ª0ºMÍÓ€fCÈ-M›6Õo¼‘[¢5€ 3fÌöª[áhÜ8i¯½Â—îlÄJÜ ‚€ÊMÀ—SsiÔhn°Eá(ÀÀ?@ÈÏ?/ýhkÏ\{­T»vv7øçŸÖ{ì¡ &èÖ[oÕYg•ݦv€ Pi(UažeðÔS¡ýâ¶mó¬á4€ @€@üD G;ûŠèÕ#_-›d–-’F’vÙ¥zÊ¥@È]‘ÂQíÚ¡å>Žr·¯i $°ÉT×ÞæžtRrx¶íÍ›7Oûì³¾øâ 4Hçž{n¶U‘ú@€@d¹.lZL–•#àêÓn· @€ ¬')U—…£… ÃeÔ~ýUrø{î™õˆ¨  Ä€@¤p´rå” ¶(Å Ó¨" Tš€/¿,  uèPéì2–Á×öÕÉvÛm§O?ýT×]w.¼ðÂŒ•EÆ€ ]°p”]ýAm @€ @UF R8êØ±c•åYZFçŸ/ù¤ø=÷Hûï_ZLŽA€Ò'0ujwÉ’‰ªS§ŽÚ´i“~bbB€bJ`âD©U+é´Ó²·¯¾úª?üp³p»H<ð€YbÊrSLÙ‹’šAˆ%ŽbÙmT€ @€ P6W8jݺµ6lXväJưyfÝwŸ´ûîÒgT23’C€¸2k£FÒ¯¿N ”j»v€ ãöÞ[²G:Õ«— ½ÿþûuÖYg©iÓ¦f‰éeí¶ÛnÙYQj@#À“YÆÐ’1 @€ @ f LŸ>]Õ±œš}̪SN‘š4‘}ÕZ³m¦t@È=®pÔ¥‹4{öl±œZîõ/-‚ ’ Ô¯/ÕªUòñš8²jÕ*]pÁfyé4uíÚUï¿ÿ>ÊF5Ñ” @ `á( :*@€ @€ªšÀêÕ«5sæLõêÕ«ª³.’_ãÆÒe—Ium–Áæ›@€@•Øl3©E ièÐÙÚ`ƒ ª4o2ƒ @ }¾tÚ1Ç£#F¨oß¾zî¹çlÙ7[÷  ¼$€ÂQ^v;† @€ \'0oÞ<-]º´Z,9K·p„@€2AàÑG¥… êž{cá(€É€ ·48`À}òÉ':öØcͺíªï&˜@È[,©–·]OÃ!@€ @ — ̘1#h^u,©–Ëi dÉéÂ’jÙÑÔ€2Gàþû¥>}¤¯¾Ê\åÍù믿ÖvÛm(]uÕUzøá‡Q6*/DâCÈAX8ÊÁN¥I€ @€ êP8úã©aCXC€2O`Ö¬YA!(ež5%@€@Í>\š0Af­¶fë•>fÌ|ðÁòåÔ† ¢ã?>:Ä€òœŽòü ù€ @€ ›¦OŸ4,SŽ^{MêÑCzçÜäG« @ »`á(»úƒÚ@€@füþ»äÏZýúIÍše¦Œòä:lØ0í½÷ÞZ½zµ^|ñE”ʸ€ò€Žò “i" @€ äÈÂQçΫ¼ñsçJ'Ÿ,-X=_ÝVy#É€²Š GYÕT€2D Ié‹/$·&[ÓrÝu×éòË/W—.]4zôhõêÕ«¦«Dù€ eP8ʲ¡:€ @€ ª )uìØ±*²KÊcæLÉÝ]wIݺ%b€ (e+™B€@ØpÚ­ÔÊ•+uúé§ëÐ[l(µoß¾f+Eé€ •P8ÊÊn¡R€ @€ Êp…£–-[j­µÖª\FŤÞ|siÜ8©¦'‹©A€ £P8ÊÑŽ¥Y€ U–,Y¢#6S¶;ÜBîСCQ6ª^ü”@ ö°pû.¤€ @€ d‘ÂQE- &=ø Ô¿¿té¥Éy³@¨nóæÍÓÊ•+Q8ªnð”@ÕF`øð°¨ƒª¶"õÚk¯é +Ð{GŒ¡}÷Ý·ú §$@È X8ʉn¤€ @€ 5*£p4q¢tÆRÇŽÒCIµj­É @ &ørj.X8ª ú” @ÕAà¹çÂe¬·Ø¢:J“F¥ýöÛOõêÕÓ«¯¾Š²Qõ`§@9G…£œëR@€ @ùN ¢ GK–H‡.-]*=þ¸Ôºu¾“¤ý€ P8ʆ^ € )Ÿ.}ÿ½ÌÚP¦JHÎ÷‰'žÐ!‡¢æÍ›k̘1Ú~ûí“#°@H“ Gi‚" @€ @ .¦OŸTµ¼Kª (}ù¥tíµRß¾qi-õ„ \'€ÂQ®÷0íƒ ßܺ‘ËÁ‡ÛLþÐÖÎþ¿ÿû¿Àjà[o½¥Þ½{g²8ò† '€ÂQŽw0̓ @€ ü#àŽZ´h¡&Mš¤Ýø‡–lîYýûK]”v2"B€2N R8jß¾}ÆË¢@€@u>\jÓFÚqÇÌ–|Çwè”SNQ·nÝôöÛokƒ 6Èlä@9O…£œïb@€ @ùFÀŽÊcÝhâDéÌ3¥Ž¥‡’jÕÊ7b´€²™@¤pÔ®]»l®&uƒ ”›ÀwßIãÆI Õ©Sîäi'¸á†tÎ9çhà 7 ”\é T– G•%Hz@€ @€@–(¯ÂÑ÷ßK H?.µne¡:€ ÷\ᨖiömÛ6ïY€r‹€[7r9è p›‰ÿW_}µ.½ôRm±ÅzóÍ7Õ¡C‡LCž€ ‡êæa›i2 @€ @ g üòË/Z¼xq¹,ù2jS§JM›æ,@1&0kÖ,µlÙRõêÕ‹q+¨: @ (W8ò•°÷ܳ豪n\uÕUÚzë­õÊ+¯KoWE¾ä@pX8â<€ @€ äéÓ§­)Ï’jže£: h  #àŽXN-Ç:•æ@€€æÌ‘Þ_ò@ÜâlUˤI“t 'huÖ‘+µhÑ¢ª‹ ?@ÈsX8Êó€æC€ @€@nðåÔ\:wîœ[ £5€ ·V®\©<½\5@IDAT.]ºämûi8 ä&¥K¥“N’ ¨úö-Z´H‡rˆ|;bÄuìØ±ê !G@È{(åý)@€ @È%‘ÂQYŽ>ø@š9S6 K­§-€ ‹¾ýö[­^½:›F› @ ¸.íý÷gÀ©§žª &èÆoÔ®»îš™BÈ€òž Gy € @€r‰@: G«VIgž)}ýµ4y²Ô©S. -€ ‹jÕª•‹Í¢M€ *'pÇwè±Ç ,]pÁUž?B€"µ#[@€ @€âO …#ÿŠöóÏ¥¿ý e£ø÷8-€ @€ x÷Ýwuþùçkƒ 6Ð!CÀ@È(Ž2Š—Ì!@€ @ÕK`úôéjÚ´©š5kVbÁnQÿ¸ã¤K/-1  @€ @ FæÌ™£#Ž8Bõë×׳Ï><ƨúT€bH€%ÕbØiT€ @€ P·pÔ©Œ5ÒìcW=ôPI9@€ @q"°bÅ y䑚9s¦üqm¼ñÆqª>u… ˜ÀÂQL;ŽjC€ @€Š#à G;w.îa€ @€ cV¯^­O @€ ˜8ÿüóƒçÀƒ:H7ß|sL[Aµ!@ ŽP8Šc¯Qg@€ @€@1jÕª¥<°˜#Ò³ÏJ/¾( $µlYl!@€ @ Fn¼ñFÝrË-ÚyçõØc©N:1ª=U… ¸`Iµ¸÷ õ‡ @€ ”Aà—_¤¥gž‘V®,#2‡!@€ @ ë 2D]t‘z÷î­‘#GªaÆY_g*@¹E G¹ÕŸ´€ @€ P„À_ÿ*Íš% *µiSä0€ @€ #£FÒ©§žªîݻ륗^RóæÍcT{ª @¹B G¹Ò“´€ @€ P ^öÝWúÓŸŠ‰@ @€ ĆÀ»ï¾«#<Ò–Ên©W^yEíÛ·MÝ©( äŽr«?i  @€ @ Ào¿I§Ÿ.ûÚUºï¾Â`<€ @€ C_~ù¥ößÕ­[W/¾ø¢zöìÃVPe@È,©–+=I; @€ @)Î;Oš1Czà©cÇ”ƒìB€ @€@lÌ;7P6Z¼xq lÔ§OŸØÔŠB€@n@á(7û•VA€ @€@ž0Ëú¢Ñ^{I'”ç0h> @€ Xºt©>ø`ýðÃ2dˆúõëãÖPu@È,©–+=I; @€ @.”N=UjÚTºÿ~°@€ @€@œ œvÚizï½÷tá…êøãsS¨; ä,åPgÒ@€ @€€¸àiÚ4é?ÿ‘ºt  @€ Ä•À AƒôÐCiÀ€úÇ?þ×fPo@ÈAX8ÊÁN¥I€ @€ ¿^]ºï>i÷Ý%û @€ ˜9r¤.¹ämºé¦zôÑGU»6¯vcÚ•T€@N`TÊÉn¥Q€ @€ ¯yDjÜXn¾92›‘º]±BrçíMôo¹¥ìS¬ÒËðüU$ÎË%qùÃ#Éÿ·ÝVjÚ4 ó¤îRUì?'½ý~'¨»Eªm®Ž¹¨ühIåy¤Ô¦M˜¾¤ÿŸ}&½ùæšü¢¼j97sµí6¼vÐûæ¯oç‚×ÇÝX´”–`AjRØW“¤Ï>—êÚÁzž—å[Ƕ~N%rü¾u‰Ê8ôP©U«0¬¤ÿÓ¦I_mõ°ŠxFÛ%Þ·‰¢¶ì¬ìº+¥•æ¼ÿ÷²ÏðJÊ= ÿøcéÕW“YyÚ ?ïçeÎëù£¶Ö5ŽG]vŒ+SrŸzM¢2">‰åqDÙí˜0Aúàƒ°Œ¨ý©ÛˆUØòäÿÇ_v;ü¼zë­°®ž:bm#n¾M){ý‰õfÆÉe²—Ó6Þ8§›GãâLÀ.í²ËT 6l%‰ /x¸]ú+%^Ž‹¡‰bCTpæþà¾ÅÇ0¿†º³ |ë×Ô†æ\ü:êæÃþ0¿Ýfùøø\pëa¾ðÚ’žxbMÚÄü£2£´‰ùGþ?ÿYêÑ#ŠQü6µ UV9ùw´±­­Ïå yO`¹Ý›rÈ!úÁæû† ¢wÜ1ï™d¿®ù¸ê®8ñy*w¥‰çácu¢Dùú6ò'–]Ÿ|ÛÒæ ËšÏógãů3î¢2¢­‡y¾>FEãTÇŽe¡Kíaâý÷Ký%•áå%^ ýžfýõ‹¦O ùü|ΰ8‰êm£r=nTŽOŒl²Iq©×„ù½Ùðáá~”Î÷Üïâù¦n#fnKªwï J‰ÿüºþØckøFåD¼£ºGm‰¶ž¡ÇÙb i«­JÌ>8ðûï’›»ŽêÕ?q囸Úç÷Ûo_z J>˜\FÔ†¨MžCJþ-ì|ï䜑œ%PÆU/gÛMà @€@ùüfÑ¿·÷Éæéb/_üÛoäûöµ cSڸ׎[ìýn2—(ç, ml!~cmi‚ˆ‰[{y¥6 ÎòÓfæìAÌÅ'«Vn-k~××ñç¤ÛÍ%ÊßJùÛ.#½¥³’"ûæÎš62Wð€ì ?õ‘޳ /ÖŸ÷Þ1—('Û„ïH{À ÒzzwQ^Ѿ'°‡Ú@SÆ<å¼ËÌ™x ¬Œ³ÌïÑ×3÷œ¹D9gŠôŒ=pÊoSÝEõÊIÜ÷„žÑZæÚñ£•q€3éen|à[óï2{È{ñô5ûI>Ïǽ, \ÁC¥¼O ÊðIžO¬¿Lï(xÑè­‹’ä2{ ~ál òú¹DÛp¯øÿÞÞ‚2>ýTz×&JkÇù?Y;ŽHÈ*ª{Tg/3*7ò7XSÆÖvN½kí²yøà%¦a+Òç—Mö|­.j‘àü|.Nüäñó¯@vÞÙÊh-cûÞ¼ÍÍ1—(—[þ/ÿ-1¤ ¿×'¡ü]v±sËúÃÏ«úæü÷ñŒ¹DyàéÿÍÕ3×´ç\üíqä™?­÷ùÖŽ,Ø_înln°¹DùÇt{°÷¨Ÿ÷QDÛ(¢ÿ¢ßþóßöÜÓºËÚ1Å‚ü’฻®9øF(]~yýwà¬.pΤtñŸt3WœB PUì2¥/Íùií—ýè²ù=<Ñùy}£¹Dñ©è× oƒ·ÍËØÆ\â튚»½.M´q=ÈߎûÖó ¶åFa~Ý®oׇ]ϱã©éÌ3í>ÂâŸçiÌífîis‘ø$lבҼƒÂ<ƒk¿åãcJ-¯”ƒJô[X-CZï–qâ‰Ò?ÿi÷í|sQOš?W\nö€±?¾ Äóœ_“ÜïÛÈÙ~­yÆË:ÖÛá/2o¹%¼_:â¹ìmî¥Àþ ÊfeœZè‰:ÛýQyQY¾k×ÌaüÓO·¾¶Îþí²@RËpVm‡ÛýÈÑ7>F¸K•9Ð. ô—ŒwÝ% ±Ý¨Œ½Ìÿrx8øï“Éíž5oÔЄc%z‹)Ãp–‘Ú/cÃÑÁÚœ¶SÆ-qÔŽâÊèYeøyUZ[¿f*ÖŽÎÙ9ï `J"àc‰¿Üðë‹\áZ”&®Ürß}6îØýœ‘sÅ}÷û5ÝüÑÖ¿øbø|XZOÚÅÕ¯»•1c±§´ô®Ü’é2üãŠÊ–Q–ÂÑ»ïJ§žZZKK?æ/ËR8ògí¿•çY$¥Èí¶+[áÈŸƒÿþ÷”„åØõgª²ŽüÄ+¯,G¦)Q÷²Á¬[·”À”][ÖIÿøGJ`9v÷ÛOe*ùGT7ÝTŽLS¢î¿Ù GþÞïI**>ö”¥pT‰2ÚZ½Zï°CEkGº"pñÅë]»žþù:Þ?Pª.ñ{w7Ý%Ž¡ë¬Sz |ŽôÞ{íöÝÆÌÈù8œê÷°Tçqüû²æ,æÍ ãyM\¡¡¸ü=¯H"µÆù‹=SùCU)2sføwå ®ŒÊ‰ê\JÒàÐ¥—J×]Wz¬Y³¤NJSÚÑtʘc÷þ®¤RQI§ ïÝv«h R:eøÇ¯d¶ W?öØŠ—qÙee+ýòKåîi¼Œ²Ž~ý5Tî­hK¼Œ²Ž~ûÍÞOœ[îZ[Šže)~•;WdºÙTê@€jŒ€?Œ~3MzÞ,ß¶ ä/Û;¬µMÿ ©=Û6Ðdpew½ÌÙM¼Ëë¯Û¨=\ý+Ü RçÇ:ojÉZÚ¤´Ýz-óYöÐZœøÛ­ì&öPÉöÍ&­]ºu3eÛZÕ]%{ž+"í­Œ¦Í’õ‹ÜòMsÑÖóÞ†ÚCùj{À¿u”M–Û +Ÿ$ïÞÝüvx}s®/b»Ed[›úš8Â-ÿÊ<ÈÏüVD¼¡t¯µsU;ãz{wg~·®ä“¤6¼‹ôª'½­à±ß­ Õ¶ yö|lÝïeEûžÞ÷Ï´7‹n¡ÈÅËpïaæ<ží‘C׳>½&Øãû æ•.Ñ6Nºù0?Oµž¥7dò9@/£›¹T9hC³|`“^?ßÖ¶Á×ùV`Ä.¨¬WÀÜßžÃý\ô LOs\AÚN¶M•Ýì|˜VPw;h]8Oèe“#î·Jú¾»+_)(Ûâú—DÖ+{£ŽæR¥E;ZÙyiçbäšÚ9Ót…{;,ÏDñÝ¿¿nýg'‘—ë¬~·°Í­0g»Eä@{°Ä^Gåm£‰¢hëìn²Ñd·Ãö ú¥^”Q¶Ö^¶sHB€y=Ÿµ ÀZ®žm—[}—Z–:/;öÊÛÖ-¶õr¼ŒÉ–æss̼w6ßi´½ù›¯Ù/Ë×Èò}ó¨5±œÕ3¶û§‚ mûΚÃï‡cm“úÛêØÔòjn€Ý53·ÔøÿR7|oþÌ” /Þ°hs\‘ €-ÓÍM-p?ØÖ§Ñ8fÞ@ž´ÿç›óëŸÞÃÍ%Ê¿íwû@ÃÄÒýuíºñz¿ÐúÞá‡K×\c–,‰mÙÓþVà÷¿Ì½âu󜕘èµs?¸èÙï7\ùäýãÃHþ…»+YPPŽ_ŸZ„‡ ÿûdôKcl·½9ûæçyú~´õ²ì7å÷?Ù[ôbÒ\áÈšð´Ë‡z˜K¿†¼÷…t5çù%:Ï7qßý&Kmüxé¥ð:Ú½{æ×¸Þæ¼ »$‘ãìúd‘¼Î÷µ¼Îv=p—è÷ƒu†_“úµ6záë|6öt溙K·žå3÷ µüƒk²×ßËò­ÕÝÓÛ‚°z6^l²…ÛèÅܺåsÞŽÍÌ%ŠÇÛÈNÆùoX6æ_må­²ˆ¾õ"</+Øì׳ø›ïæ²á†á¶‡mì ⥖á/ ZL²ëãËkÆ*¯¢qËëàuK,£Ý—õµóÉÅÍ]61çAÏ™%Š+4ìÖÜ~gvÍõü û£ ’‡%¶Ã7´ßÓ…¢I^oÎIi¼¼Dñ2öml–'ß ëx,ÕïUp©oeìjexùQ^÷ÓÌ9ßâÚ±wSiƇaš ŸDþþ }Þ&Ë£ýnw¿<ŒïV']ìUg>S’*ØFoÇ!Îê] ñJxžžW‚ó¸n 2Û6°‹ÒÞÿ ~ó½ïü%;’¿üZdVåÖ]fÌ(êÜ –ÿî]^{Mê×/ô—ôúôðËp?îÏ/Ź BÅ%·æçp¢KµJë§µÿ6Å•`þúW;‡íÚ¶¢¡Ýƒš[a7˜…[Ëß/Dµmüðg"wݦڶàwѽ{8n[UƒK¼ß›v6—(míFòä–§µa••cÁµÍŸ -ëàùП VÚå¶]nÛìÚÝo»µéïæüñ·¹ÝÌ%ʺví½ômËÃÒûµÚï¥=Ÿ6öø6r+½-ÞK|Ô·kx¸5Rž6g—'ù{쿘K”:ì㈩é XxýÝ9ßÚ&ð»Ç†u05l‡·e3üq9«Vðlx±m¥ÁÁÒ¡ûXZOo.z&ô|Ý9'ßü}ßÜå?¬)ÃÇžñö 9/¿£¹Ô2ü§ÿ–Õ©ðZg^—ˆŸ{Î1Ø7ÿ¿ Êð8n±ç#ÛÞjÎN—à™êÛ&ʺ‡JWïeç†^`ùøv¡»‚üÀeíÛO(wîˆl—üŸµÃÊ𼼞/Ñm°°Ä2ž°2¢v¸ÒÅvÜëîyx;n3—(¬²~÷þòßð2‹èÏšØ~ðÌY°¿Üö]éÜûcØü ‡ñ¦tõÍÝw~þå/#F˜^Ü-vëÙ×ôüR(àâÊ×_oó¶uÅ DçŠì¾)¹‚~ª\bO_š,X`Ïç—£ôc~r…£ÅÍ“~Mñ1ȯ%‘,·?,³=ûÝÔ²µíGV·Å±ñ¸¶yuÌù¸ìÇü·å?äú³ì7ök˜C£Fáö«p|kÐÅü–E¡¬¶ô[œcu°¼VšßŸE|ÌæÖlX)·|=Ì~ºA­§Ø¼Œ]ï\6ß<ܳ£ôvb®µ¹HVÛ}ü.OF{[ËÓëÜ÷\€‚}o‡eÒc²Ç³­L+ÔŸA]0u—¡ Ækw©ÝÜž^ 9DºxxâxVPLæó•=§[v-ò{'W¨u¹ßœ÷‰·ãs똋¤v Sú Ú[³ Æ«w0þÛÖš\S½)Yt´gêhœöT·ø?ðòûŽHÚ3îyÿ³k§ ä³~ñí2gåe˜ ž,A´¿åL{ü.(c#¿H›Ülnià³alÛ¶Àï›:6ïù'EЧæ[¯£o£ë¿y ýÛZ_t·2\"+Mÿ4¿—áiÎ0×Î\$u­QG~g{Ò"8‹`ë‘Ý™íˆÚcÛ­/zÚoÓû#²Þw­Å[bΓø3– {…âeõ}¸[e/ѵ%*kŸ¬OìàYl¼ÜüÑye?uòƒÒØN€K¾±ß•íûOq™D×·Ñœª£Qþ¾Ýó'MoòÆÞ‘: äÉ&'XOW\V¯^ý°¥>¶â92 ¼i_¨Üg_ó<òÈ#ÙX=ê@ £zõê|=ÒÜ—2øöî^Šênüÿ÷ÒéÒPšŠD°+ –‰kTŒQ»ñïOí± Q4¶çÑE4±ú`,X0;cTT¤ "Hï÷¾3ÎìÝÝ»{wÎîÌÎç¼^ÃN=sÎû ó=w†T6Ÿ˜"n2í÷bºGŒ?ö±ÈïÍÿÒ]ÍÅzOSgó¥ÅIæb¾b®¹€^f:$˜ oíÔÌÜ jaæÔ/yæKª¾là@3ß|ƒÐï•fÒùräÿ¢º5³ŸþÕ‹|½Ž7¿ó9?ðšï Î[óÀé0a¾/‘ˆŒ€¯}cˆHM~0å0÷œ/Äͧû5ìâ™Óƒws!]ÞzãAÿÏëÿýBÞÇ þ¤÷7Æ›A—µ3ÃYfð§WÍÄ?Í ç sŸMÌ}o0÷!œq­ëöfÐsÊÎfø‡Lzùå—å•W^‘|pë þ½ÀÌ™3ÍCcþKÞzë­êëò…Yeœ^0ÇfÐcÕŸÌ=;ç¸ÓŽÚAF;_è±8Ì Óôžé½fp“þµëöû›)=ÈôÀÞäL¬t¦»OfÜ|Ö774ñµ‰É[ŸF¢7’o¸ADïÏ™{Î 3=n»›ÁMzsï™°lÖoh XÏä±)W=38Ÿ&?ý!ع hÖÕ›pþ¡C‡­?4ºù¥ûÔmõõ îcïõ&²ÿœnãN»™«Ÿú ýÔδ³`uIÀv÷¡ev;·ø;ºèÕNúä}ˆ~·×õ eÌN‹Ìº¢4vóm§£c̹ýQ ôW1ý0Y>ͤ³ gÞçKf\tqÓëfäT3èw¾.f˜jÒ£®õÏÈa\Ëk‡—4F³mÊTI>÷–lùƒù¸1e^u“¾Mhõ’^7·mª§ùœâ-Ù:r³ùš2¯ºIvÉ¿^fÉg¥[ë uÉ'¥îã9³ñ Û2ØË|NNÉl¨™Öºäšô¸Ðö÷'ÿ>ôšéÿB3n.yä–”yé&õxÓ6ÐãiEÊ Ïšé·Íëg>ÿ²üz3}kÊ<ÔãFÿ1«Ç¾^ßéwÒzè÷-C_3üà þ¤ÇÔÝfÐíýùùש0ZÌ;1·Si¬™ú4݇~·ñ§afâ^ß ·=ýŸº­;¨Õrßú:ú73h=´ j5Á þt“™¸gÛ ÷ÿ¹[f÷Së¡ûÐýê>f™ÁŸ´=Î1ƒ.×z¼aú½™¸Ë?#e\ë›AÛFË ×ÁsÍ`ÒdóG"C‡Mÿjë*üS#FÈR³þ[Ÿê’%}c^YÙ§OóU§®éWý‰ e&–¹Iã ¾nòssâ×WgjÇZ}"ó)§¸k¤ÿÔŽF;h>&&êNíÄÑ …94ß:^Ï̯gĺæÀÔA;ñì²ÀÄSs2ÚÞÌ?ôPÓ9þð­²Äd±Ê wš¡³ÜôíFÓ±×”Ïí<év t;r:üÌ.jΕúù?ëÍÿWóIc·~OÒïC­Ìüï·eú¡ùÔÿcnúÖŒ´w'rüiÖ;7eÝÖfZë¡é3ìãŒmýg¾ùØÙ7ËèÃf¥ÿJY±¥™^ºm^j=j²GL^zÞñ'ÿ>Ìå‘óD_wy\÷ñ±©@·æsŽ:ú¦s}Ô¬ô۔͡îÅ‹O̸Æk7±Wbëg3óñã¶YŸ™Ï^ÛÆõã3øÿßûe}Üœ®øZÎ;ï<ówÛof\±h_'ÖÅO`á×™ÞÅ?šG–µ0ï笣7,KÌõ€hàšg½Xc†Õ)Ÿ7ši½hvÓL3r‹ô‹Ic3üÙ þô¼™¸Ã zQ¯ƒ^¸»ãî´™Ho›)s}ä¥ifì¿ÌPË zò‚üI¿@ÝnÍÛÍß÷ú·yÛLø÷ñ©™>Ù º¾Îÿ—üi´™¸Þ7C×Óäÿ¬0ÓZFs=å|ê—,½HpÓT3r¦t=ŸúEï)3o¨ÔRMš¿»tÓLýûÐþËmÛ¨Õ3øÓcfâ÷Ûfh9Ü2k¹up§õS“î[/nüû˜l¦›A“^Ìé>ýéI3q†w롟n»»ótÕÏÍ åu“^´ýbÛDóùwÁ¶ÏÇÍç5fpËì–7e5oR÷¥m쯇îc4݇.÷'·nyÝãVóÊ”Rëño³âÏÍ å3¿_È43øÓfâZ3¸©ŸþuÝñÔ}Tgõ¨ÙðªmûÐ<Üò»ûÒy©É|ÏÉ«=Ü}¤æ“m:µju´´\Ú_˜ÁŸÔê¿Í Ëݶp?ýuQk÷xHÍÃ,"Ù(yl[×Ðİ“ÌëÌ—VsôZkþRÄ|ùÜÖÜîhtÈ!í’Ã:ºŠo¶ :MB Êîù1ÊeÌ¥læ^šÓ¡/—u YG¯Ìé#cÚÞ,Ñ›™Òf™’Æ=H‘(ylÓký~¢ßƒÆ™A¯Õ455ñfØÕ m7˜Ž3_›7ó™‹õoÞ2ï{ë“!ôUcÆl½¶þ…Y/]Òn/íoþ_™ÿ\ÍÍA­?æêSÜA§›/{Ú1W;iÇštIË£Cº¤7›¯¹ Ý’ðæé>ô)H¶“û—‚¶÷Cþ €€E’Ç6íhtðÁ¦“Ķ^úä¾*D_3£OÔjÒÅü8ÒÁÄ2›þcâŽÞCÐûff5/½iÆn›êl>gzK¶Ž|_gkGŽÚfRc©{¿Í×µt™†5tܽgFÔÌü»§Lø“NΜà?ÝÌä‰fÐíM˜Lû¶_½ßdóÛ­óiŠH]ÌÔMfÐuü÷­Ü•›Ý·^{jýÝòû?u\;RÔ7ÃvfÐòøÓþfb¼V›AóIMz/qg3hÙtÐ<4¯ÔA÷¡FZÖÔt¨™¡÷ÖtµHMW›šÁÝ^óÐr»C¥o\Ëïok3é$½îYfÝ6µŽºÂfÐ}è¶î íªI÷£ûpw¿ºÌŸôú|¾\ÿ2j†ëÍàæã~šYžŸ»O—.`fjôð7—pUÒ3ç 3èñ§ƒ^_é§¹dK›´.©éx3C‡Li˜Y CjÒúh~ê«Çn¶t²Y¨C¦t£Y C!Iÿé)ÝlèPHÒöÐ!SR§ß›A;ÑÿÇ©ÿ?ªko³ ©¸%qÛª»Át(:ÙüqÆ ó´ ¿›§µÓ¸¦£’ÓÁÈíd¤øàOúd"íp4ÒÌüÖ ß›A¿ŽfpÓ*½aÖs“žK¶…SwV•Ï3Ìœ RæŽ6Óß™AaÝGg3¸Iã²>È=ê§®§ŸþÁ?¯‹ ©ç©SÍú{t½Ô§±õR3è¹FÏ9ºN¦Á]Ç\"TI_VšAÿ¶OYj.#äOfÐØ¤e3Ur’æ§Éÿéž÷ÌåH•4ÖÌѦÒu4öûS+3ñ¶†×õüƒ[~]Mϱt$%½h¦µšR÷ÑÚÌ›džºž{ÎÖ<ýƒ.KÍCç½d]Oóénjc&4ާ&7_ß:î~ê¾»¦®l¦ß6Ã*3h»§.W«¿˜AÛÞôšÁÜh¾šôS‡]t"%M4ÓZM©õÜÉÌûÌYl_·­·- |´ Lmxß|è>t»Î[gyÿêú_›A˧&nYÝi3«JJ·ÌZºîcç”-Ü}èl]î–ß?ž²I•ÿcº|ª´ŒšÚnýðþÕãêe3èµH=3èÿÿ í¢ÿ'ýIÿ/ôÏ`¼ô4OЏÀĉå±Ç“3fˆþ¥¦ sc´U«VÎ#O2£×ÏEIoš½Üg†yÛ†%9ìõwfÿSÝæ±mÛi°øó¶q÷CƒÊ|3ø¡žÝi÷$鮯Ÿz‚õ'½XÒ<ô¤¨©I¯­›ÁÍ×=ẟº¯Ô”º]G륟æÞz•¤'Yÿ‘[nÿ§L4iYS÷«$Z~]æ^ؘQ/éÿ`÷înëÖAWò»¹ë¹ÓZÎÎÛÖmáÎô}êÖž¾i-‹;¸å×i×G÷™º <î…[º}è…‚»ÜŒ:É-»›ŸZWH={in9µÌ©I¿hïj·ÌnyS×s§ÝýºÓú©ûènÝV¯ÑS“[­¿»½;žº®;Zó»ŒÓƒ;Ó>tyG3ø=òÝGuVÚFj©ûÐäîËwf¦ü“Z\÷‘’MÖÉÔ}¨…{1Ÿî¸jd–ëq¥åW#ÿ௓Z»ÇCºÿgf1)|HŶ³ÌìcLwÖ“GºHøõ'G@òˆTl{Éø·ÍXo:]d†cÍϺWE^|Ö¼2ð#Ó±}š¹¶íŽ›ù~é<©ç€ª*жlåÞ{Ý1>@ÊT R±M_‰qØa[Ÿä°ßæ~Ø~¦s¹©õ®ÁÊ ©?dhü[`†fpS'3r¥¶3Cºûú#¦…¤¾fã·²dð+³L‡BR7³ñÐ,ô2Ët($éJGgÉ Y¦C!IïÕý,KzoI‡B’ÞKÒŽ7™’Þ[Ò¡¤÷fõxË”ÜÃ3-Ïu¾æ“ÉDïWêkÒ{da%½Ç–úãbXyÇ5=&t EZ R1n›ÔæÕÍLÛ›µ{Ÿq†y"Ër³Äœ,kõ6¿5nÎ5&ö­ßÝ|×›kžÚc‚™>qU_ó§év3|ãŒmí<ØqÛ¸~èïp&;§3¢þ¦•:èñªçK÷|¥Ÿ=ÍšÌWHçØNw|k1¾NÝ Ó÷eÙFÏça| ½"Ë>Ôæ’,Ës]4 ËŠzÒ?Ëò\™¯ï“þ&—myÆ ShäLIKÉÇ3m—:_‹Ê”´=Îδ0ùÙö¡V…^7iQ²ÅaýÿÕEW*0eË#¬}윥ŒzrL–å,J¬€~¤ˆ Ì3]¿úê«Ó>FؼÎN/^,Ï=÷œ3 0@î¸ãóG¤…~Cªã³|¼ôK”~¹=Ü zòÑA/(ôä¯'ÿ§¹æ ¤}ÌÔ*3èEKº#pˆ™¯C!io³ñ¼,„± @ŸfÙÇ f™…¤½ÌÆ3²dp’Y¦C!©‡Ùø½,k–éPHÒ`þ~– Ž7Ët($ía6ÎvCç8³\‡B’îã,„Qó}A^ϲ0nLUgF›cÕY…ÑYš‚E5ˆdlÓ/yÙ.¤kVU¶BHˆ@$cÛÿz3 6ÃîkDžxÜü€ú¿[¿¯í²Ë.æÚØ\ëÓ}úš_Fuàu²*CB0‘Œm+Í ÇCÌMÉwMï0ÊmM¥÷õÇ®_˜AïÕ¹Ãf<5i‡£;Sg2 $HƸÿüG¾4¯Z»úÅ·þ]ö'+Mg¢áæ7·“ÍηØúà‹·µ’>¥§ù®OJ«=k¦õgK3˜M©¾™z"0§fébkÍrb+@2H×Ý£Œªߪ,Y²D~ûÛßÊüùósª„¾÷ðÄOtÞ[¯O>²–´ÃÆ:3Ô*`º­vJ"!€$J ²±-Q­@e@ˆllÛÞÔò‚oEî¿_䡇̫D–m}ýÙ5ט§]d:ÚÒÓ6Ì〼@rˆllûÑ(_ký1Uÿ˜ñmƒþõ~#3@¨F ª1nÅ 7H÷?eÿŸln}™Ô^Ôqë«Ëô•UúÇóÚ±¶÷¶ÏL?ÿ鯓@(ŽJ€^Ý.ׯ_/gŸ}v ³Qýúõåóxûøàyê©§dåJÓÛ٤ٳg˵×^+?ü°óʵêöS£å15bc#@ 鑎mIoê P#HǶçŸ9å‘Í“i»‰Üz«È™gš'ÑjO$ €é"ÛL8sžndÎ'ú¤ €yD5Æ­[·NÞ}ç8óË¿IóJóZó€ZùN7Ã@3˜Y$@¢,@÷‘¶Îرceúôé^ÉêÖ­+>ú¨ôé|FâAdî!ŸbîŸéuNÒ÷Î>óÌ3ròÉæQ‹$@""@l‹HCP @Ð"Û>ؼþúp‘‹/6¯˜ù…˜¿H ­Þd„ P¾‘ŽmÊn @šD5ÆÕ©SG6õm*3çÍ”®7wù¥©]ƒšÔm@(@!/Æ*M‰Ë|¯6l‘#Gj9|øð*ÜÚ·o/wÞ|ù¸^8‘@ˆŠ±-*-A9@ˆ|lkÙRdüx‘cŽ¡³QXN> €@™ D>¶•¹?ÕC°'å§ŽŽ{í8éú…él¤Ï ³‘½œ@¬ÐáÈ kÍ37nœ,^¼ØËàpóW©Ç{¬7nDŸ|´Ï>ûx‹¦N*óæÍó¦A@ ”ĶRê³o@Ä6ªä‰ PJb[)õÙ7 €€MbœM]òFHºŽ"v¼÷Þ{ ¨/i­>xà•Æë_³’@ˆ€±-@@B ¶…ÊIf € ¶E ( €€bœV2E@À ÃQÄ„?üÐ+QEE…ôïßß›Î6â‘®G‡£lZ,«‰ÀùçŸ/_|ñEM6e›2xã7dذaeZ;ª¦±-LMò S`É’%rÜqÇ…™%y•‰€vú_»vm™Ô†jØ ¶ÙP%Ï0Ö¬Y#ú¤d©ƒ–ï¿ÿ>u6ÓxÄ6‚‘ hlãú<‚ Sâ"~úéòÍ7ß”¸ì>ĸ8´RòʸeË9òÈ#E_ùGBÀx衇d̘1î$ŸÄB€Gj¦Y³fÉÒ¥K½õêÕKZ´háMgéÙ³§4hðÓË]gΜ™mu–!·À‚ dýúõyoÇå+°jÕ*Y´hQùVš…"@l …‘L, lÞ¼Y¾ýö[K¹“mœæÏŸ/•••q®e·(@l³ˆKÖ è¹KÏa$RôšG¯}H¤ ¶¥Sa^”æÍ›'úÃ, ¿Àwß}'7nôÏb*ĸ*$̈Àœ9s"TŠ~øA~üñÇ(…2 ³Žr¦²¿â”)S;éÚµk`:ÛDݺue—]vñVÑ í+VxÓŒ € P b[)ÔÙ' €€Mb›M]òF(…±­êì@ ĸb(³@$ ÔIrå£VwÿÓ´lÍš5Ë«ˆM›6 ¬¯ù5iÒ$0/—‰?þXô"ì°ÃsV¯U«–ôîÝ;—MY§Œ.\(÷ÝwŸ4oÞ¼ŒkIÕòпœÖ¿$ºâŠ+òÙ,rëê#¹ý¯ Ô›Ú‹<õœ¹‚Ǥ@Q‰mS§N}úŸÛ”Oc›Æ8Rrôÿ¿q?%·íÖüÚk¯•:uâýuIcõâÅ‹(=Ök×®m-!¹G%¶Í˜1ÃyÚ¤?¶é“oõQHÉØ´i“ó„6b[rL5×8póÍ7žŽiÝ(Ï×§/ë÷PMëÖ­ãÉ!5VTb›¶íêÕ«ßÛöØc©_¿~H5%›8 \wÝu±¿>³Ë®ç®;ï¼³F¿D©>úÍ}B¥¾ZIŸ*O O *1nÒ¤I2mÚ4yýõ×Ê5jÔHòyè@x"ä÷ÉÚW]u÷k¢Ò((‡ž'êÕ«'_ýuJSó"èol³gÏv2Ðû:M*_xßA/³vI}DZ¾ŽR;é…T§NòVÚk¯½äÓO?•wÜÑÙVŒíÓ§OÞù°Ay èp‡D?I¨À®»î*Ë—/—.]ºÄDo¼ûk}Œ)ëÂkҨĶÝwß]4¾µmÛÖ«œÆ6:y‰Ñyz½EÇêD6ÖJkÇ=gĽƒŽžóÜןêwt¦ÍÚì9/ŒJlÓïzzþjß¾½WöŸýìgt8ò4’9¢¯ÌÒæ÷Þ{ïdPëŒzÓºGÎÍëŒ+Å`v8ÒA“~—Óz‘ ˆJlkÕª•ÛüOqßsÏ=épTxÇ>‡r¹>}CD¬Ûo¿½s²Aƒ+Y~ÅÑïl;í´“³ÑúõëE˜%…'•wÈ!‡8ñ̽ï¬÷£»wï^EÉ)vÚáHÿÐ{Ô±k:«Ö{yz\¸qÁêÎ,f®}ôÚ^“þ‘ÿÊ•+-î¬K-@‡£R·€oÿ©>ùþ º~jÏmß®²Žê_ÈúÿJ6ëÊ,D@ ‹@Tb[¿~ýdÔ¨QYJÊ"@à'“O>ù§ ÆHˆJlëÖ­›Œ3&¥tL" rꩧ€@b[fø¢Ûô–§Ÿ~ÚW2FØ*À9Œ#!ÇE:æ¥ D%Æ{î¹¢ ¿À)§œâŸdˆ¥ï‰P³¥^øäû„£Æjã7L €”@€ØVtv‰ `U€Øf•—Ì@J @l+:»D(Š1®(Ìì@ Át8ŠPãWTTJ“ïc¡õ‘dþ”úÄ#ÿ2Æ@(†±­Êì@ ˜Ķbj³/@bÛŠ¡Ì>@J!@Œ+…:ûDH’Ž"ÔÚî» Ý"åû>C}¿¯?¹ï‚õÏc@b ÛŠ©Í¾@Š!@l+†2û@(¦±­˜Úì @ ˜ĸbj³/@$ Ðá(B­Þ²eË@iòíp´nݺÀö;ì°C`š @Š-@l+¶8ûC°-@l³-Lþ €Å ¶[œý!€K€W,iöƒ T:E¨å ½ðY¼xq 6t8 p0 Pb[ ÐÙ% €€Ub›U^2G(±­èì@ (ĸ¢0³@ Ðá(BŸzá³pá¼J·`Áoý:uêH“&M¼iF@(…±­êì@À¦±Í¦.y#€”B€ØV uö‰ P b\1”Ù €@’èp¡Öoݺu 4“'OLg›Ðשù;(õîÝ[***²mÂ2@¬ Û¬³@" ÛŠ Îî@¬ Û¬³@ ãJÏn@#@‡£5u×®]Åñ3}útY½zuN%ÔÎI›7oöÖ8p 7Î €¥ ¶•Jžý"€Ø ¶Ù’%_@R ÛJ%Ï~@l ãl “? €@Òèp¡# V­Z2hÐ ¯D[¶l‘I“&yÓÙFÞ~ûíÀâÃ;,0Í €¥ ¶•B}"€Ø ¶ÙÔ%o@RÛJ¡Î>@Š!@Œ+†2û@H²Ž"Öúƒ”häÈ‘étË—/—gžyÆ[Ô±cGéÔ©“7Í €¥ ¶•RŸ}#€Ø ¶ÙP%O@R ÛJ©Ï¾@l ãlê’7 €@Òèp±# {÷î²Ûn»y¥š:uªŒ3Æ›NYµj•\xá…²fÍoÑÉ'Ÿì3‚ €@©ˆm¥nö ¶±-lQòC(µ±­Ô-Àþ@l ãlÉ’/ €"µ A:tèñfû^…äÁ¶U5j$&LðLœ8Qš6m*=zô}ü£›,X çž{®L™2Å%»îº«ÜvÛmR»vAMëåÇ €aÛÂP$@( Û¢Ô”@ b[Šä Eb\[…2!€”À=…T¢²²òI³ýBò`ÛôW^y¥¼ôÒK…íÛ·—^½zIýúõå£>’¹sç–שSGüqéÛ·o`> €DA€Ø…V   €a ÛÂÔ$/@(ۢР”@À†1Ά*y"€$\ =Ž"z¬^½Z.»ì2y÷Ýws*aƒ äþûï—ƒ:(§õY @b ÛŠ-Îþ@l Ûl “? €@±ˆmÅg €Å ÆKšý €$H }AïÝâ•jö•zõêÉ AƒœW¨M›6M6nܘqgûÜu×]Ò¯_¿Œë°@R ÛJÝì@ lb[Ø¢ä‡ Pjb[©[€ý#€Ø ÆÙ’%_@ ðJµ84þš5kdüøñ2uêTY¸p¡ètÛ¶meçw–H=âP ʈ €€'@ló(A(b[™4$Õ@ðˆm# €e&@Œ+³¥: €¥à•j¥’g¿ € € € € € € € €ÄP }­š"#€ € € € € € € € €@‰èpT"xv‹ € € € € € € € €@èpÇV£Ì € € € € € € € €”H€G%‚g· € € € € € € € €ÄQ€Gql5ÊŒ € € € € € € € €@‰èpT"xv‹ € € € € € € € €@èpÇV£Ì‰ظq£è°iÓ¦Ðê¼nÝ:Y´hQ¨yú g3›yûëÅñ 6È‚ dÊ”)2wî\Ù¼ys¨Å´i×¼C&3Ä-¾Ù<)Œíüø› ¾en$™UX‚@tˆmÁ¶Iò9,αM[ÑfÛÙÌ;x2…aÛ‚ŠI>‡Û‚Ç‚*ÉÇ…ßqâ$@| ¶V’ÏcqŽo6ÛÍfÞÁ£©r¨S.¡”›Àk¯½&¿ûÝïœjõë×OFUã*Nœ8Q{ì1™1c†ÓÙH3ª¨¨V­ZÉA$'t’ôéÓ'’ùÛ.{+]„ —,Y"/¾ø¢¼òÊ+2mÚ´ÀëÖ­+;v”Î;Ë1Ç#GuT`y.6mãšw.n¬ƒ… Ä%¾Ù<© íü k%»[ß2û&ù¸È¬Â¢/@lÛÚFI>‡Å9¶iëÙl;›yGÿì@ ˆ¯±mkÛ%ùFlËüÿ7ÉÇEf– âÛÖvJòy,ÎñÍf»ÙÌ;gJYˆ@E!WVV>i¶RHl‹é´³‘^ühªi‡£yóæÉÕW_-üqúøæ0@î¸ãiܸ±onöQ›ùÛÌ;{­¢±ôÕW_•o¼QV¬X‘S´Ó‘®ß¬Y³j×·i×¼«EcM êñÍæyLmçZCYʈø–6éÇEzæ"b›ÝïQ?âÛÔÕfü±™wÔ Ê‡@9Ûˆmq¼/©ÿ÷lÆ›y—Ãyƒ: âñ-ŽñÍfü±™wÎ ”1öt8 Å‘LW`Ù²erÈ!‡ˆ>ÎOSM:i/Ý_ÿú×2þüœ §OÌÑ')铪K6ó·™wuõŠÂr}Õm·Ý–wQ´ÝtÛ]wÝ5ã¶6mãšwF, €@èQo6ÏcŠi;ÿÐ,ä ‰oéA“~\¤Wa.ñ ¶ÙýÞõ#!®±M]mÆ›yGý˜ |”ƒ±ØÇû’úÏfü±™w9œ7¨q ¾ßâßlÆ›yÇáœ@C ÃQh”d„@Hëׯ—³Î:+ðT¢|;i'žx¢LŸ>Ý+Uýúõ倸@žzê)Y¹r¥·ÞÁ,?ü°óÊ5ofʈÍümæRHNNžíH¤í¶×^{ÉÏ~ö3Y»v­Ìœ9S^zé%§ ½ÍÈÞ{ï-£GNÛ~6m㚷ߎq°+ ç‰(Ç7›ç1•µ¿ÝÖ+}ó܉öíÛËwÞéN:ŸcÇŽ Lû'læo3o¢:>{ölùä“O¼âµnÝÚyEZ›6m¼y©#ú$«ßþö·Ù÷Þ{o`Z'lÚÆ5ï*HÌ@PâßlžÇÕvþ¡4œÅLˆoéq“~\¤Wa.Ñ ¶Um—¤ŸÃâÛ´%m¶Í¼«…ÌABˆmUõ’~#¶¥¿žôã¢êÿæ mâ[ÕöIúy,®ñÍf»ÙÌ»êÈœ$Ðá( ­L#)°e˧cЄ ä믿–7†RÎqãÆÉâÅ‹½¼?üp9öØc½ét#ÚiŸ}öñM:UÌ“¼iÿˆÍümæí¯CTÇ_|ñÅ@Ñ.¸àÙyçóÒM\vÙe¢¯ÌsÓ‚ ä‡~p'O›¶qÍ;Ä„&Çøfó<¦°¶ó­ñ,eD|+þ5•¥¦$[+@l«ÚôĶx~wÓ–´Ùv6ó®z2  ¶UÕKú9,®ßÛ´%m¶Í¼«…ÌABˆoU“~‹k|³Ùn6ó®z2' t8JB+SÇD ¼÷Þ{ú800iâÀ ,?~|`Ú°™¿Í¼ÝòGùóË/¿ ïÈ# LgšÐÎF]ºt ,NÍ˦m\ó€1‘ˆó¹ÆfÙ#ßp¦€©1‰ø¶µÕ’~\ÄáØ¥ŒØ°y°™·ºØÎß¶}¡ùÇ5¶Ùn»¤…Wl@9Ø<ØÌ[ímçõö%¶‰¤»žôã"êÇ-åC X6Ï6óVÛù« jºŸ¸Æ7›íf3ïš¶ÛÅ[€Gñn?JcZµjÉwÜ‘v¸òÊ+k\³?üÐÛ¶¢¢Bú÷ïïMgñ?áH×K÷KçÛÌßfÞZö¨§ï¾ûÎ+bóæÍ¥U«VÞtu#:t¬2þüÀ´MÛ¸æbBˆc|³ySXÛù‡Öx–2"¾¥ïÄôãÂÒáF¶X ¶UeMú9,®±M[ÒfÛÙÌ»êQÈ(D€ØVU/éç0b[úûáI?.ªþOaÑ ¾UmŸ¤ŸÇâßl¶›Í¼«ÌI‚@$T’:"Eí 4xðà´E›5k–Üu×]i—e›©Û-]ºÔ[¥W¯^Ò¢E o:ÛHÏž=¥Aƒ²víZgµ™3gVYÝfþ6ó®R‘ˆÎð_ø´iÓ&¯R~ûí·õýlÚÆ5ï ª@Üâ›Íó˜ÂÚÎ?ÔÆ³”ñ­¸×T–š‘lH´±-ØüÄ6‘8Æ6mE›mg3ïàÈ„!@l *r#¶é‘z?œã"øÿ„)â @| ¶ç±xÆ7›íf3ïàÑÇT’xÂQ’Z›º–½À”)SuìÚµk`:ÛDݺue—]vñVÙ¸q£¬X±Â›Ö›ùÛÌ;P‰Oüå/‘çŸÞî½÷ÞœKºnݺ*¯«Ù}÷ݽímÚÆ5o‡ˆ…@œÏ56Ë‹Æ3…$¾÷š*.ÇåD é6ãƒÍ¼µÝlç‡c#ޱÍvÛq\ÄáÈ¥ŒØ°y°™·ªØÎß®|8¹ÛDRï‡s\„sl‘ q°y.°™·ºÛÎ?mÇøf³Ýlæ‡ã2Úà Gv\É’øŸn¤hÖ¬Y^åhÚ´i`}ͯI“&Þ<›ùÛÌÛ«@ÄGü„ò)êwÞ)ëׯ÷6ѧ•C»qLxMʉ°y>°™·6œíüãppß¶ÅŠÍq8&(#ضcíüãp|Ä1¶©«Í¶³™wŽ Êˆñ>Çp!¶mý_¬Ç‚ûÝã‚3¨€Ísͼm—=.GGã›ÍãÂfÞq9&(gø<á(|SrD d?þøc`ßùv8r¿L¹™¤›ùÛÌÛ­O9~þýï—Q£FªvÕUW¦mÚÆ5ï y8Ÿkl–=ò W@Ë9¾) ÇE›"P&6Ï6óV~Ûù—IW©F©c›í¶ã¸¨ÒäÌ@ q6Ï6óÖ†²¹ Ķì-[ݽöì[³¢"`3FØÌ[ýlç•6 »¥Žo6ÛÍfÞa·ùÅG€'ŧ­()Õ ¤ŠÔ'U—AêúÕu8J]¿üm—½º²Åmù–-[dĈ’úêµÁƒËᇨŽMÛ¸æb"/çsͲG¾ájPÀ$Ä7eḨÁÁÁ&”™€Íó€Í¼µlç_fM-Q‰m¶ÛŽã¢ÜŽ\êƒ@þ6Ï6óÖšÚÎ?ÍhoAlË­}Rï§ÞkÏ-ÖBR ØŒ6óV7Ûù—ºmÂÞTâ›Ív³™wØíA~ñ ÃQ|ÚŠ’"P­@j È÷ G7ìcÕªUi›ùÛÌ;P‰2˜øòË/åú믗©S§jÓ­[7g~`¦™°i×¼S˜Fh Äù\c³ìÑnµüK—”ø¦2ùl@¹ Ø<ØÌ[ÛÁvþåÔÖQŠm¶ÛŽã¢œŽ\ê‚@Ílžlæ­µµÍD£¹±-÷v©î^{î9±&”RÀfŒ°™·šÙο”íö¾£ßl¶›Í¼Ãnò‹ŽâÓV”j***ëÔ«W/0]ÝÄÆ«¤þ†Íümæ¨TŒ'V¬X!úÓŸdôèѲyóæ@M~ñ‹_ÈðáÃ¥Aƒù:aÓ6®yWAbDZ Îç›et£åQ¸¤Å7¥á¸ÈãaUÊTÀæyÀfÞÚ¶ó/‡&bl³ÝvåpäR °y°™·ÖÚvþ…ÉFckb›HØ÷ڣѲ”ª°#læ­õ²uvqXÅøf³Ýlæ‡ö¦ŒvèpdÇ•\(‰@«V­û]¹re`ºº‰õë×ViÞ¼y`Úfþ6óT"†Ú¹hìØ±ÎëÓ–-[¨Á;ì W_}µwÜqùþ ›¶qÍÛïÃ8D_ Îç›e~Ëe/aR㛪p\d?6XŠ@lžlæ­mc;ÿ8·”c›í¶ã¸ˆó‘KÙGÀæyÀfÞZ{Ûù‡#\š\ˆm?¹‡}¯ý§œC( ØŒ6óVSÛùG¹Ýª+[”ã›Ív³™wuæ,/_:•oÛR³ ´lÙ2Pë|¿­[·.°½vfñ'›ùÛÌÛ_‡¸ëc¯ºê*ùꫯE×^È¿þõ¯åòË/—&Mš–¥NØ´kÞ©FL#€@´â|®±Yöh·ZöÒ%9¾© ÇEöュ$AÀæyÀfÞÚ6¶ókûG=¶Ùn;Ž‹¸¹”ðlžlæ­¶óO¹¸9ÛìÞk/nk²7¨©€Ía3o­¯íükjZêí¢ßl¶›Í¼KÝ®ì¿tt8*={F tBÅâÅ‹e »ÃQ¶üm—=P±˜LŒ5Jn¿ývI}ÕÝþûï/×\stïÞ=§šØ´kÞ9Á±DF Îç›eLåY¤Ç7åâ¸Èó auÊPÀæyÀfÞÚ¶ócsÇ!¶Ùn;Ž‹8¹”plžlæ­ ¶óWº8¹Û8.Šs¤±¢/`3FØÌ[emçýÖ«ZÂ8Ä7›íf3ïªÚÌIŠŽ’ÒÒÔ3©báÂ…yÕ{Á‚ÞúuêÔ©òä›ùÛÌÛ«TLFV­Zå¼&íõ×_”¸S§Nríµ×Jÿþýó«›°i×¼«3c9DK Îç›eV+U_âÛOF?Y0†@Rlžlæ­íe;ÿ8qŠm¶ÛŽã"NG.eEÀŽ€Íó€Í¼UÃvþvÄíäJlûéIòvŽ1rE n6Ï6óVgÛùÇ©-ãßl¶›Í¼ãt}º¬^½:§"iç¤Í›7{ë8ÐwGlæo3o·üqø|â‰'d„ ^Q›7o.£G– /¼°F4#›¶qÍÛfb!çsͲǢñ¶’øl-Ž‹ S$QÀæyÀfÞÚV¶óËñ·Øf»í8.âräRNì Ø<ØÌ[ElçoO=Üœ‰mÁûáá_ä†@\lž læ­Þ¶óK›Æ-¾Ùl7›yÇåx œá Ðá(|SrD dµjÕ’Aƒyûß²e‹Lš4É›Î6òöÛovØai°™¿Í¼«T$¢3fÏž-wÜq‡Wº ÈÈ‘#EŸ6UH²i×¼ ñd[(¾@œÏ56Ë^ü–¨Ù‰oަªY+±[Àf|°™·:ÙοØmQ“ýÅ1¶Ùn;Ž‹šIlƒ@y Ø<ØÌ[[Ávþqhib›HêýpŽ‹8¹”û6Ï6óVÛùÛ×/|qŒo6ÛÍfÞ…·9ÄU€Gqm9Ê@Áƒ–h‡•êÒòåËå™gžñVëØ±£têÔÉ›öØÌßfÞþ:Duü…^7zÅ>|¸ôêÕË›.dĦm\ó.Ä“m@ øq>ר,{ñ["ÿ=ߊM•+±”BÀf|°™·ZÙοí‘Ï>ãÛl·]Ò‹|Ž!ÖE \lžlæ­ía;ÿ¨·9±-ýýð¤Q?n)Űy.°™·úØÎ¿XmPÓýÄ5¾Ùl7›y×´Ø.Þt8ŠwûQzªtïÞ]vÛm7oþÔ©Se̘1ÞtêȪU«œ×u­Y³Æ[tòÉ'{ã©#6ó·™wj=¢8ýòË/{Åêܹ³}ôÑÞt¡#6mãšw¡¦lňó¹ÆfÙ‹Û 5Ûñ-½[Ò‹ô*ÌE Y6Ï6óÖV²Ô„¸Æ6Ûm—ôã"êÇ-åC 6Ï6óVÛùÿ}ÛÒßOúqQÈ1Ŷ”“€Ísͼµ lçõvŽk|³Ùn6óŽúñ@ùìÔ.$Û¡C‡o¶çñ…„m(3eË–ÉèÑ£½Zµk×NŽ?^ÿ»å–5j$&LðVž8q¢4mÚTzôèá’¹sç–שSGüqéÛ·o`~º ›ùÛÌ;]]¢0O{Y_qÅ¡åÁ”TÉϦm\ó®‚Ä °&õøfó<¦¨¶ó·ÖpdL|+í5UMǦ £±Íî÷Λ¡¨«•ClS0›×%6ó.jc³3*@l#¶zè—⾤–Ùfü±™w¡Þl¹ ߈o¹)™×*E|³læY‘%e(оNVŠ*!€€¸ùæ›åÇ”wß}×ó˜?¾è.5hÐ@î¿ÿþœ:éö6ó·™wººGaÞœ9sŠR ›¶qÍ»(ðìBˆó¹ÆfÙC9#â[õ I<.ªWa ’%`ó<`3om%ÛùGñH(‡Øf»í’x\DñX¥L”RÀæyÀfÞjf;ÿR¶K¦}ÛªÿC‘$™Žæ#d›ç›yk›ÙÎ?ŠÇE9Ä7›íf3ï(”Éž@æw&å°O^©–« PBí¨»¬W¯ž 4Èy…Ú´iÓdãÆK²ï¾ûÊ]wÝ%ú$¥\“ÍümækýŠ½Þ³Ï>+úhþ°’¶}§NªdgÓ6®yWAbXˆz|³ySTÛù[k¸2&¾U—Äã¢zÖ@ >Ä6»ß;£x$”ClSW›ñÇfÞQ<&(å&@l#¶zL—⾤–Ùfü±™w¡Þl¹ ߈o¹)™×*E|³læY‘%e(À+ÕʰQ©UÖ¬Y#ãÇ—©S§ÊÂ… E§Û¶m+;ï¼³óÚ­=zTÙ&Ÿ6ó·™w>u,ÇumÚÆ5ïrlgê„@9 Äù\c³ìåÜæ¹Ôͦ­Í¼µn¶óÏÅu@ ´6Ï6óV5Ûù—¶eJ»wÛ¶6ó·™wi[…½#€@®6Ï6óÖúÙÎ?WÃr\϶­Íümæ]ŽmM(W›ç›yk{ØÎ¿\Û<—zÙ´kÞ¹¸±N¬ÚWRüÊÊÊ'ÍöC Ƀm@@@@@@@@@ 6íkŦ¨@@@@@@@@J.@‡£’7@@@@@@@@@ >t8ŠO[QR@@@@@@@@J.@‡£’7@@@@@@@@@ >t8ŠO[QR@@@@@@@@J.@‡£’7@@@@@@@@@ >t8ŠO[QR@@@@@@@@J.@‡£’7@@@@@@@@@ >t8ŠO[QR@@@@@@@@J.@‡£’7@@@@@@@@@ >t8ŠO[QR@@@@@@@@J.@‡£’7@@@@@@@@@ >t8ŠO[QR@@@@@@@@J.@‡£’7@@@@@@@@@ >t8ŠO[QR@@@@@@@@J.@‡£’7@@@@@@@@@ >t8ŠO[QR@@@@@@@@J.@‡£’7@@@@@@@@@ >t8ŠO[QR@@@@@@@@J.@‡£’7@@@@@@@@@ >t8ŠO[QR@@@@@@@@J.@‡£’7@@@@@@@@@ >t8ŠO[QR@@@@@@@@J.@‡£’7@@@@@@@@@ >t8ŠO[QR@@@@@@@@J.@‡£’7@@@@@@@@@ >t8ŠO[QR@@@@@@@@J.@‡£’7@@@@@@@@@ >t8ŠO[QR@@ /¼ð‚TTTxÃÓO?aMf#€ $ÆÇ1cÆH»ví¼aþüùÉipjŠ € € €Q N÷Å®@@@@°&°zõjY°`—ÿæÍ›½qF@@@@Âà GáY’ € € € € €(pà 7H‡¼áÛo¿-0G6G@ Úľh·¥Cô<á(½ s@@@@@@ Ë–-“¹sçz{æ‰u# €e*@ì+Ó†¥Z”¹O8*ó¦z € € € € € € € €„)@‡£05É @@@@@@@@2 ÃQ™70ÕC@@@@@@@@ L:afF^ o7Êœ9s¤mÛ¶²ýöÛ‡Z™•+WʼyódÑ¢EÒ´iSéСƒ´hÑ"Ô}hf ,™3gJ“&M¤sçÎÒ¸qã¬ûX¸p¡S®ŠŠ ùÙÏ~&õêÕ˺~® £RŽ\ËËz €@¹ lÚ´IæÎë k×®•wÜQºtéâÄ‹BêN|+Mœ-¤ÍØ@à'[ñQ÷`;FVVVÊŒ3dþüùÒ«W/iÙ²åOc @Ÿ@!1#J÷ø¢T/£ €È'ömÞ¼Ù¹gúõ×_‹Þ7íÑ£‡têÔIjÕ ï¹%İ$ èp$Ù `C`ß}÷ ô5M­Zµ’W_}5ëæŸþ¹üå/‘ýë_2yòdY·n³¾v:2dˆ\zé¥Ò®];ÑÑ¿ûÝï¼¼Î9çéÛ·¯7ndË–-òØcÉ“O>)'N¬R—îÝ»Ëo~ó9ûì³¥M›6é²Ì{ûí·åÊ+¯ôæÝsÏ=rÈ!‡Èš5k䡇’»îºËépä­`F<ð@¹õÖ[¥ÿþÞl-׈#däÈ‘òÙgŸyó·Ûn;éÝ»·ì¿ÿþróÍ7gü:*åð Î 3bÄ7—dñâÅrï½÷:qbéÒ¥îlçS;™uÔQrà 7H¿~ý˲Mß~Ò±gÊ1@ yÅŠ‘6⣶V˜1rÚ´iræ™gzÁ< ûì³ó½R¿ ÞrË-²bÅ gù#<"úµ&I¿OžuÖYή¸Ûë÷Â|PêÖ­ëÎâ@ ‹@Xñëþûïwî%ê®ôFüiРAÞ üñrÝu×y‹k3¢t/Jeñ`AH+VÜÓÌ‹ûüÒßÇ®¾újyë­·dÆ þEÎC vß}w9òÈ#eèС^ ¬´m‚–N…y “€éù¤H `I víÚ•æ?c‡vÚ)kÉÆŒSÙ°aìù›N8•ãÆ«4½šë=õÔSYóž2eJ¥ybP`›LuiÖ¬Y¥éô”5?]øüóÏòÓrÍš5«Ò\ôæ§ÛÖUÓwß}WyðÁW»¾ùµrÕªUÎ6©ÿD¥©åbˆ‹€ø–znÖ8õá‡Vj,Lüó̉•?üpN|Ä·ô×%aÆÙœ‚•@2;F+>js„#?øàƒ@ Ÿ0aB¥yjRÚïs¦Ã‘wD˜?, l7{öloYêˆ~ç;ôÐCë÷éÓ§ÒtRN]•i@,aÅ/ó£gàœìÿÞæ?ï¼ó¥©iÌH“¥º×¨•‰RY¸L €T+îiÆÅŽ}ºOó¶“Jó €Jó£œâ®yø@å7ß|£›¦Mİ´,ÌD )íÂ{š¹â'!€@<ô©I—]v™œvÚi²zõꬅ^¿~½œxâ‰òÜsÏe]Ï¿ðý÷ßwž<äz»<ݫږ/_îü5ª>M)Ÿ¤`<ì°Ãä‹/¾¨v3s#B>ùäùå/éZô¯qݤOPzã7d‡vpgñ‰ CšÆŒ(Ýã‹RYbxPd@ qùÄ>}Jà_ÿúWç µ.”¾¢ZŸôÚµk×*O3úè£d¯½örޔ⮟í“–M‡e”Ÿ¯T+¿6¥Fe$ð‡?üAL÷ÇœjdþjSÌÓëqÄiwB_?¦¯—q“>&þÔSOuWߥKçщæ©bþªGÆŽ+úC¬¾ú,—ôã?ÊàÁƒE;¹I»¨»×›·íÛ·—9sæ8&/¿ü²Œ5Ê]Mþô§?Én»íxu›·0ÍÈW\á¼NMiç)-£ùkTgßÿüç?NUn9ôf²î_/º4é d½¨:à€¤sçÎ2þ|=z´üùÏöùæ›oÊ /¼ §œrгM¦¢RŽLåc> 5[ñÍ_ÏaÆy_š(z®Ö/ÍúºQí¨úî»ïÊïÿ{ç½äºÆ:ÝFc_ºD|+]œM×ÌCÊUÀvŒ ;>j;+FêwXí ä&ýnižªë¼\¿Óå“Ì“’œÎFú‡&nÒWkÿýïÏøjmw=>@ª „¿ôÝûp·ß~»s_ÒÝÛ+¯¼"æ ¶Î¤þ(š-Õ4fDé_”Ê’Íše €@Š{jWìØ§ßyîºë.¯Ùúõë'÷ÝwŸì·ß~Þ<}U¶¾®ôòË/—×_Ý™¯¿µiYÿýï{ëe!†e’a>T0!x¥ZR†E=#- •ïÕ«Wàч¦só´Ô‚¯X±¢²uëÖÞºæ‰C•¯½öZêjÞ´>š¾~ýúÞúæDàŒgz¥šùñ6°®>–qÍš5^~©#7ÜpC`ývíÚUšNA©«9Ó©eÔ²Ô«WÏyäpº &Ožœö‘¦“Qå¢E‹ÒmRyÏ=÷ÊsòÉ'WY/*å¨R0f €e&O|KwnÖÇ›Ž­UL§£@ŒÓx—éušÄ·ªŒ¶âlÕ=1@ U ×i;>j¹lÅÈÔ×ã¸ßE;tèPiþÀ$•Ä›®î•jæFy¥¹™øÞ§¯ÝÖïÊ$@»¹Æ/-ÅÅ_8W›?`ÌX¸šÆŒtq²÷µbQ*KFh €ä%OÜÓŒ‹û† âÅצM›V~ÿý÷YëdVà­¯ßÉÌTYŸV…„$I 97Ô<):%ép¡®‘0=+Ícå_;í˜G¦-ojó´£´ëùgšÞÎüÍY£2]‡£™3g:€t¹æiC;ùóÿÿïÿò?~¼±7žî¢Åô”ö–§I½‘¬7 Ì“-Ò­êÌÛ°aCe:u¼ò˜§3UY7*å¨R0f €e$o|Kwn>ÿüó«I¡ï¼óN•mˆoUH¼6⬗9# €iò‰‘6ã£ÎfŒL÷ã±~?ûá‡Òº¸3³u8Z¶lY¥ù ^ïûž~o5¯éÎØáØÍ“O@Âò‰_º·BtÍ%f¤‹“¥¸×¨õRY´<$@Âò{º·bÄ>îox ¨¶’ú›îúúy÷ÝwWÙ†V…„$I ]-sr !€@Œ®¿þzçµ_n4hàL»vçë§>êÞ<ÁÇ›¥¯/;çœs¼éL#^x¡´iÓ&Óboþµ×^뽎¬¢¢BÌ^©]»¶·<Óˆng:y‹}ôQo<ÛH‹-DëŸ-uëÖ-°X_»Ö½{÷À<ÿ„¾^®cÇŽÞ¬%K–xã™F¢RŽLåc> G|â[ºúé«3o»í¶t‹ó:è Àtºó>ñ-@˜(Fœ ì @ç;¾úÙMÙ¾ºë¸ŸaÆGͳØ1R_‘Ó¼ys·:y}šÎFrøá‡‹¾>ÜMúr}EOÆ ÝY|"€X(ô;^¾ÅªÏÒ=¾(•%_{ÖG‚¾·ÕÔ¯ºØg:AÉŒ3¼ì?ÿüs1½"¼ét#æi°b:9÷Yõ^«¾ÖººD «Nˆå”—ŽÊ«=©MÂÌS†døðáZÿõ¯•¾}ûæ¹æÉ>²zõjwRŽ=öØœ:™×®ÉE]äm—iļšÍ[Ô¥KÙ{ï½½él#­Zµ’þýû{«Œ7NÌkؼéL#æÕhÒ¬Y³L‹ùzCÝŸzöìéŸL;Þ¤Io¾ùëYo<ÓHTÊ‘©|ÌGâ&o|KW?}ÿx.?H¶lÙ2°¹yŒp`Z'ˆoUH¼ň³ÞÎABcd˜ñQ›£˜1R¿_j¡š¤¥K—ÊÀåã?ö6?úè£åÅ_í°EB°+PhüÊ·t5QºÇ¥²äëÏú €@ÒŠ÷Ô;—ØW«V-ñÿFöÝwßÉyç'›7oÎÚd—_~¹\sÍ5Π߫ªKİê„XŽ@y ÐᨼړÚ$H@ÿ*óì³ÏÔXÿRè׿þu`žÂ<îÞ?)‡zh`:ÛÄ{ì‘m±è!–/_î­c^§æç2â¿È1¯5“Ù³gW»Ù.»ìRí:úÄ"ÒŽPù$íñ]]ŠJ9ª+'Ë@8Ô$¾¥«W§NÒÍ®2ÏßÉTú;æê4ñM2§bÄÙÌ{g  ,0bdXñQå‹#{÷î]£×ršWÈ'Ÿ|âm¯OØ}üñÇ¥~ýúÞ dRÄ=õÎ5ö™WJšç‘G9Ú¡hêÔ©e5 †ÕTŽíˆ§@x›R#l ÈqÇ'ëÖ­ó ~õ«_ɰaüét#©Žô•j¹¦:d]uúôéåÓ¦M“3Î8#0/ÛÄ—_~X<þ|©®“Sue d¸m¢mÛ¶éf4/*å(¨lŒD@ ¦ñ-]Ñý¯ÇL·<×yÄ·\¥¶®g#ÎæWÖFÊS ¬V|TåbÇÈ|¾¿úýîüí·ßúg9¯¿á†dĈùL €„+VüÊ·T5QºÇ¥²äëÏú €@RJ÷Ô;רwã7Êĉ¯šÖrÿñt}#É!‡⼎ZŸ [“xT“m¸§˜Ôÿ5Ô»èpT­H% Œô†©^¸Iß™úä“OJEE…;+ígj‡£\^5ãfT]ät7›µÓQMÓÚµk«Ý´& úÈȰSTÊv½È(¦@!ñ-]9Ûµk—nvÞóˆoù‘Ùˆ³ù•€µ@ò3F†U¹Ø1²NšÝÂJílä!#GŽ”SO=5ðzowŸ €… „¿ò-MMcF”îñE©,ùú³> DRÆ=õÎ5ö5mÚT&L˜ 't’ó™ÚVú„ØgŸ}Öt™>à”SN‘‹.ºHZ¶l™ºzÚibXZf"P¶áÿò^¶TT hèkÔô‘ŒnjݺµŒ7N6lèÎÊø™z£µY³f×M]PÝÅÊܹsS7)hZ/ΪKµk×®n•¢,J9ŠRYv‚X($¾¥+Ruq+Ý6éæßÒ©0@ ˜aÆÈ°â£Ö¿1²÷!C†Èÿ÷{YTVVʹçžxr°·@‚ÂŒ_&Ç ¢t/JeÉ‘Õ@D Ä)îi§£×^{ÍyÒÑ™gž™µ#ÑçŸ.7Ýt“óÚµG}4§6&†åÄÄJ”@Íþ<¬lªOEˆ—ÀðáÃå©§žò ]¯^=yî¹çr~¤aj§¤eË–I›6m¼ü²,Z´(Ûbiß¾}`ùùçŸ/'œpB`^>={öÌguÖEˆ±@¡ñÍfÕ‰o6uÉ@ :bduB¹-¿ì²Ëäž{îq^¥6vìX™1c†³¡~:Tn¿ýöÜ2b-@œ¢¿rª+!€ ‡@\ãÞA$:lÙ²E>øàyóÍ7åí·ß–I“&Iê[HtZÿ`C‚pÌ1Çä¡Ãª Pît8*÷¦~e#ð /Èõ×_¨Ïˆ#äÀ ÌË6‘úD#ý‹Ô\;Í›7/[ÖÒµk×Àrí uÄGæ1 €@ª@ñ-5Ï0§‰oaj’ €@>ÄÈ|´2¯;lØ0¹á†œ¶Ûn;yàßUï¾ûnç{íµWæLX‚ ³@ÔãWÎaE@r(‡¸W«V-ÙÿýAŸ »~ýzyçwäù矗ѣGËÊ•+‰Í›7ËÅ_L‡£Ž VA I¼R-I­M]c+0eÊ9ãŒ3Dùî¦Ë/¿\Î:ë,w2§Ï:Ö«®‘åüãþÉ*ã©?ÈNŸ>½Ê:Ì@@À/V|óçö8ñ-lQòCÈE€™‹Rnëüæ7¿ ¬xøá‡Ëi§æÍÛ´i“œsÎ9¢Ÿ$@Ââ¿ «![#€ ð“@¹Æ=ýC#úè£*\t—¥û<ýôÓe=öp†þýû:W¥[Ÿy €ñ3¾Ù” ¾ÙÔ%o@tÄÈt*áÎÓ׫ùŸüÉ'ŸÈ]wÝîNÈ H˜@\âWš…ê"€XˆcÜÓW¿¹¿Ã¥þ^˜‰©cÇŽr饗öÙgi&@ Ùt8JvûSûˆ lذAN8á™={¶WÒîÝ»ËÓO?-µk×öæå:rÀˆöLv“> Q_«V]9r¤Ìš5«ºÕ¥_ºt©<üðÃÕn£+L˜0AÆŒ#_|ñ…3ì¹çžRQQ‘Ó¶¬„ ?°ã›mÿ+B‰o¶µÉH¶1²8í¯Šo»í¶ÀÎn¾ùfáI½&@œâ¿r®+"€ F ®qoÇwô~‡û÷¿ÿøí1M5½Yþ‡ èÌvíÚyËAèpÄ1€@„.ºè"™8q¢WÂæÍ›‹>•(5¸{+T3¢Ûë“„Ü´qãFùÝï~'ëÖ­sgUùÔ‹Žk®¹¦Êüt3ô/B4hà-ºóÎ;eñâÅÞtº‘5kÖÈUW]X4dÈÀ4 €å%v|³­C|³-Lþ €®1Ò•°ÿyÞyç‰ÿ¯zõ{ñ¹çžËÓvíÓ³(Cñ«V­àOÕÝc,CVª„ QqO«j;öõë×/ úÀ¦3M¼þúëÞ¢FI·nݼiF@: €@4î½÷^ùË_þ(œÞüÔ' åò´!wÃ>}úHË–-ÝI¹îºëäoû›¬X±Â™÷â‹/Ê!‡"ýë_¥GÞ“…–/_.<òˆÜtÓM¢‚rIú×k¯½Vn¼ñFgõùóçKß¾}åù矗½÷Þ»Jü±Óꫯ¾ò–}öÙ²ÿþû{ÓŒ €”—€­øfS‰øfS—¼@\b¤+QœO½™?bÄç;ëæÍ›¾ûî»òÐCÉ\PœB°@  lÅ/} ƒ?ýñ”±cÇz÷.ýËG@ X¶âž–ßvìÓß{÷î-Ÿ~ú©Ãu÷ÝwKݺueèСÎgªá–-[œ'Ãê[WÜtôÑGWéå.ã’)@‡£d¶;µŽ€øÔtÇwˆù¤ñãÇ‹^¸©K—.òä“OÊI'$úØGM~ø¡ôìÙSš5k漿U_£¯q[¿~½»™\|ñÅòç?ÿÙ›Î4¢O+5j”÷(úy󿉾ÊM;é…Ì®»î*3gÎ}Ç«>=IŸ²ä&½ØùÓŸþäNò‰ P†¶â›m*â›maòG FÿÐ益^z©üÏÿü·ó«¯¾Z $íÛ·÷æ1‚ YÀVüÚ}÷Ý;Õ? lܸ±ì¼óÎrüñÇË­·ÞXÎ €Å°÷´ì¶cŸþÑÅÈ‘#e¿ýöíL¤ÃðáÃeܸqrØa‡9O.êÔ©“üðâ =ztàµkÚ!*—ß ‹Ñì¢#@‡£è´%A  ÞV:öØcEŸ.¤OÒÎFnÒ§ýóŸÿt'ÏÚµkË-·Ü"|pàB¢^½zõ܉í¶ÛNþõ¯ÉùçŸ/Ï<óŒ3[;6½ÿþûÎà®—ú©7zŸ}öYÙ~ûíS1 PF6ã›M&â›M]òFPbdiŽƒaÆ9ß]õ ½šôiÀ^x¡ó:óÒ”ˆ½"€ñ°¿ÜΟîùYUV¯^-_~ù¥|ÿý÷ñB¢´ €e#`+î)P1bŸ¾Ví†nýTYYé´Ë´iÓD‡lI»{üñÇ¥U«VÙVc$P ø"äPe’*°çž{:€ô‘‰ú ³† (êׯ/¿úÕ¯D)Í5×Ty­Z¶‹ŠæÍ›;8~ì±Çœ¿< dœ2¡ëêS#´“RçÎS–2‰ €@tˆoÑi J‚ -8ÇÈFÉ}÷Ý}ùå—ÅÿÚ€ÀB&@Š" ¯xÑóq×®]‹²?v‚ €@©Šûô)M'N”^½zU[劊 9ýôÓ'yä‘Õ®Ï  <ŠBªlz>>i¶RHl‹ÑÐ^Ù3fÌ}Z›6m¤mÛ¶Ò A¯p/¼ð‚ÓÉñÅ_H÷îÝÝÉŒŸ+W®”O>ùD&Ožì .tòÖÇÓ÷éÓÇé±­O !€ 'â[œZ‹²"€S€YLmö…”¿ÀæÍ›eÖ¬Y2}útÑq½o©?úï[–¿5DH’@±bŸîgüøñÎoƒkuX¼x±óúR}@@—.]œìµ×^Iâ§® Ÿ@{:åÆÚ$VàøƒÜxã^ýõÑÅ-Z´ð¦A@@@@@@@D´¯“ˆjRIp´·òßÿþwOCÿ"¨oß¾Þt¶‘I“&y‹wÝuW:yŒ € € € € € € € ,:%«½©mÂj×®-—^z©óXD¥hÒ¤‰Ì;Wš6mšUF_‡öî»ïzëüñÞ8# € € € € € € € ,Zɪ.µE£Ž:ÊCX±b…<ðÀÞtº‘¯¿þZŽ>úhY»v­·øÄOôÆA@@@@@@@d Ðá(YíMmN8! pã7:O=š?¾7ýúõòÁÈ}÷Ý'Gq„,^¼Ø[vÎ9çH¿~ý¼iF@@@@@@@@ Y…T·²²òI³ýBò`[(¾ÀwÞ)W]uU•7lØPÚ¶m+sæÌ‘ 6TYÞ³gOyÿý÷E×#!€ € € € € € € €@"Úó„£D¶;•NºÀïÿ{¹å–[¤AƒŠÕ«WËŒ3Òv6úíoKg£€ € € € € € € €$S€'%³Ý©5ŽÀÒ¥KeĈ2zôh™5k–è«Ôü©]»vrüñÇËi§&ûí·Ÿã € € € € € € € Löt8JfÃSkª˜W$Ê¢E‹dáÂ…Ò¼ysÙqÇ¥~ýúUÖc € € € € € € €$Z }DWŸÊ#€€'PQQát2ÒŽF$@@@@@@@@ “@­L ˜ € € € € € € € €¤ Ðá(U„i@@@@@@@@È(@‡£Œ4,@@@@@@@@@T:©3˜Fà‘G‘ÿýßÿ•F€'°råJiРԩÃiÃCIøÈ† dãÆÒ°aò’X¾|¹¼õÖ[²ÓN;•U½’^™çŸ^®¿þziܸqÒ)¨¿O`Ë–-¢ñ­iÓ¦¾¹Œ" ¢±@‹ŠŠŠ²áиݼysyã7ʦNI¯È{ï½'çwž4iÒ$éÔß'PYY)?þø£4kÖÌ7—QÄ9.ôZ¸V­òùÛCý>Z¿~}™4iM\&_}õ•wÜq\Ÿ—I{†Yr¼>Ó'©y­X±Â¹/Y»ví²!Ø´i“S—>ú¨lêDE¶ \tÑEÎ5‹þÆBB@Üïnåvÿ‰Ö-L`íÚµÎýHýžS.ióæÍ¢÷%?ûì³r©õH ç@ “";v”ÝwßÝét„®À9çœ#W\q…ì±Çî,>.0a™8q¢ 6¬¬$Ž<òHç¦uYUŠÊH»víd—]víTKBÀX²d‰h|{öÙgÝY|"à 0@Fít¶.íhôÎ;ï”Ku¨‡hÕª•´lÙRžzê)<ðôæä Aƒˆmž#®À/ùK9r¤sîpçÅýó_ÿú—Œ;6îÕ ü>íD«?Är}îCaÔ(Çësš¶pÓN;Mn½õVéÔ©Sá™E$‡ÿüç?rï½÷F¤4#Lnݺ9j/¹ä’0³%¯ èB~øáòôÓOK½zõb\ЦÀ<àüaÙ!CÂ̶¤yÍž=[®»îº’–۠Ñ]ßXæ^·n]'¸é³$\=.ôG Ž W„O}J‚ö².·cBŸfQNõË‘ºU@Ïa:”ÛñJû& ©ÿß9. s,×­Û¶m+Ûo¿}ÙTo‡vàVÙ´æÖŠè“Gõ<Æ9¬Ì¶Àê¬^½ÚÉã¢@È2Ü\¯yô)®mÚ´)›Úi§K½Æ'•€§úœsXù´i˜5ÑsX¹=e;LŸ$æ¥×í[·.«sÆ¢E‹xÃ@™ÌÛm·óVb\™6p ª¥Ž4é1A‡£–é&úö!í„_Nç ýèrza™zU«|ž£\#€ € € € € € € € €@.<á(%ÖA¹öÚk×íA€+Я_?çUî4Ÿ €@Üš5k&Ç[±)oî¹çþº¬ÎìÂпœ¾ûî»ÃϘc/ ×eG„ Û~d¨þa‡–a ³@xuÔQñ((¥,š@÷îÝ‹¶/v„@X¼R-,IòA@@@@@@@@ t8J@#SE@@@@@@@@ ÃQX’äƒ € € € € € € € €@èp”€F¦Š € € € € € € € €„%@‡£°$É@@@@@@@@Ðá(L@@@@@@@@K€GaI’ € € € € € € € € ¨“€:RE@@@ 1K–,‘éÓ§{ÃŒ3ä£>’C9$1T@@@@@À®Žìú’; €@„Ö­['ß|óÌš5KfΜé|®X±"Â%¦h €qؼy³Lš4I^|ñEyùå—eÑ¢EÒ¤I“ÀиqcÙ~ûíeýúõ²víZÑØ¤Ÿî¸®ß¾}{Ùy矺ݜ9s¼8æÆ3i?þøc€©víÚÒªU+'ïÀ&@@@@@¨¡ŽjÇf €á |úé§Î²ï½÷žÔ­[W5j$úcªî¸îÑý!V?ÝA×?à€¤ÿþÒ©S§ŒÓNEÿøÇ?œáã?– Heee`ývØ!0Í wÉ“'Ëã?.¯¿þºlܸ±Ju***dÀ€2l¢S @IDATØ0§SJ•Rfhš[o½ÕéÓ¢E q‡–-[:ãÚ¹Eϯß~û­3¸ãË–-“ÓN;M†.Å>×jY&L˜ 6lpöݼyóÀ§ÆuÈ'iüH!ºýÊ•+8óÒK/Éøñãå‡~p²ÕNC{ï½·³\;·Îž=Û_µj•—Ƴ Hýúõ½Ï¯¿þZþùÏzëd*£ºk§¤>}úÈn»íæ ]»vºtéâ”é•W^É´9ó@@@@@ÈK€Gyq±2$A`Ë–-ÎSôI:è“î§þ`·ÝvÛåÌ ¯/ÑwÚi'iݺµÔªU+í¶ú$‚¹sç:ƒþðx 'H:å}ŠVÓ·ÞzKôYæÍ›çØèS4­Y³ÆùÌõŸ‡~ØYu—]v‘C=Ôé|¤ô52n'#ýÑV“ÚöîÝ[>ø`éܹ³óC¬~êpôÑG;ëð gíä3zôh§£Ñ´iÓœªtìØQš6mZ¥Z«W¯–#FÈSO=%7Ýt“\rÉ%NÇÏÔ5N]}õÕòôÓO;ËõÉ;Ú‰Hãf¦¤q¯M›6Ò®];§ƒÏC=$Ï>û¬Ü~ûíröÙgçÝÉ'Ó~Rçë“…>øàÑ6ÚéG;µfKZΆ Véèê>yHc³v$ò¦ë¼•ºí`t饗ʱÇ+{íµWêbgÚ½îÐë‹L× z-¢¦4VΟ?ßùÔòhÌÓØ¥m;tèPö×i™‰ € € € € Pòþ5»$¤ìâ(°iÓ&§Ó‹vZyíµ×D¨L—ô©¯¾úªÓy(Ýrÿ¼k®¹FþøÇ?z³´ã‘v:ÒÎG:èSÜNF©¯ñ:âˆ#äoû›óÊ/K#Zwíõæ›o:ƒ>ù§^½z' ¹OÒ'.è2ô) î¸>Â}ý‹vrÇõSUOÿ ûÔ§ é·šôI —_~¹óƒìèü`ª?ÀúØu×Õ2¤ê÷î»ïÊ;ï¼#o¿ý¶<ñÄÎà'Óc/¸à9ꨣœ'yèåéR¾O¸H—ó@tÚiDÏ:è9Ñ×O·“«~êÓÛÜOÝFÏ£é=Oú+š—ž ßxã gúô¡‹/¾XÎ<óLéׯ_ºb9ó´ЕW^霋ÿöÎ^ªñã=Ú -¤•)R´ïB{ˆ”%-hñ”¥TH¢•ÚT„’¥H’¢TJÑ¢ÒJE{QZeÉÿù½§3÷ÌÜ™{gîíÌüžÏçÜ™9s–÷|ÏÜ9sÞ÷÷üˆ‚†î`B„ëÙ!CÌ÷{“&MdèСæ»û?tè8p@~ûí73¡  4"£üùóá­½ãwÞyÇì§C‡2nÜ8yõÕWÓâìٳǻïqâ5Ú…}Cô„G{BI1\ËÑJ‰Ý}÷ÝÒ°aCãÀÇ!¬ƒÉ~ŽumA®7˜k4ö!í¶‡ã)Q¢„yk‘¿Àõ×2p‚Ð*½€È®Fi®·¸Ž¥åâ—Öú|H€H€H€H€H€H€H€H€H€H€ÂM€‚£påöH€\Eî7ðD©™½{÷¡ Ä>a€ùð¸oß>?~¼T¯^Ý dÂ)Â_`´S§N2fÌ©R¥Š4jÔHvïÞmÊË`àÏá6a JŸ`ö´dÉÓ& V•Ë„#0ŠTL„]³f†Pï!àäP±bE#†Â€+&pÁ#]ý•Ž Ô60Ã*^!¶òàú6-UªTªÍ`¢ @ ç p¥¸ãŽ;Ì„ù8Wp_ºt©à Î:ÅØx‡€|ûÀ ð|uÃAÀ­àᇖ¶mÛ Ü Ä8pŠ€î W^y¥×¢hM§N* 4>úȈx¼JçJÌ@ƒ²5×_½Ìœ9Ó œú[ î 6ÁÈæátÁÀ<¸6`ÐŽ¾Ahì£nݺfª\¹²Xù.‡×`Ç {?x´Ÿƒ1ÄE˜ Z‚ëC,w!kÙ²¥™ü ç‘ @$àš³hÑ"#æ„ÀhåÊ•žkœiZµje¬(ëˆ BLû¹-rÅ#¾CíG|OC@äoÂ÷¬s‚Я!´ Vää€ýöîÝÛ\ q ‚J’Á%iÔ¨QòÀx¹9× å9„¤pPºï¾ûÌ5õ•W^LvàP¬N:æú Îã´Ÿãz“+W®TJ¸a>ƒH€H€H€H€H€H€H€H€H€H€H r(8Š[n™H ”Å &Ä5Ë—/÷ І°‰ÅæwÞ);v”ÚµkÇ¡ô6‚’\x½ë®»¤F¦Íp1B@ètÛm·™’kx|ûí·ŠwÒÛOÏž=MÙˆ—jÖ¬iLp™°åb^zé%yã7ŒÈ ƒ®˜|¤1x\²dIûÚn;Q`ðnMX/˜À@6¶‡‰A$@$ Ftùí·ßzJRÂU BLÄ…^h® pÂä¦RX(6yòdéÚµ«,\¸Ð\'#!à)W®œ)‡9eÊSf×+8Þ¡Ì&¯5ü#          ø&@ÁQ|Ÿ¶Ž–܇æÍ›gFíÚµË+4Qj%[¶l©JpÁ ‚Ûíös LB8ƒÒZÎG<Çzßr`(U–‘T8çäÎ[Z´ha‘?øàS: 톳E‡dôèÑ™vøh ƒ¾M›6•f͚Ɉ#äšk®1ån¦OŸ.p}ÂëG}Tn¿ývÃÆ(ÿ „•Üä¶oß.Û¶m3ž£4æâÅ‹Ø;Ëž=»¹&À1®^½zR¾|ù „¬amh˜7×;L‘ ˆY!þe ¸‹Gî:_l- ¸šÀ¦M›dÖ¬YÆhÁ‚¦<n­[·8øÀqåeâ=àVÁTÆ åk6oÞ,=zôÁƒ‡­ùpO‚cöƒRn Îâ5„F(7à  H›\‡ …›Üí|'S>lJP¢ ¥=AhA,Þó ]«V­ê)IY©R%W\¿|ƒ¯I€H€H€H€H€H€H€H€H€H€H€H #âT?#GÅuH€bJàÔ©SràÀÙ»w¯q‚˜3gŽýôÓO¦]¤E 3ˆfà T¬X±˜¶7£;¿îºëŒ£Ñ 7Ü`ÄF ^½zets×+^¼¸,Y²DPÎ ÎJ<òˆi\o xL›6Mžxâ A)Ê`nypÀÃ!D¥… 6ös8ÐÙzÁn—Ë‘ @¢ à(QÎ$ƒÂHàÈ‘#7‡P† ˜PÂë÷ß7B"ˆ‰œÓž={<¯!6²ÎÀmçÎÈ®<(u–w¦åË—ËÆ¥V­Z;¤)Q¢„T«VÍ<Çë‚ š2i¥K—y›nY!þü‚‰A$@${pÓ{òÉ'ÎFçœsŽ<ôÐCÒ¯_?É›7oìÇ Ä5$àžqÆQm#’£6lØ 3fÌ0 RQÝ9wF$@$@$@™ @ÁQ&àqUH‡–þýûËË/¿l\š6mj„Bgžy¦` Q:%½ $òÎ?ÿüDÁÁã  ˆsÇŽ3q[¶lß Ž{ˆæÍ›Ë‹/¾(W\qEœ ›G$@$@$@$@$@$@$kü±ôíÛWÖ¯_/ÅŠ3ý —_~¹`BßBÑ¢EM5€'N¦?ÿüÓóX¦L³N°Ç€*‹/–o¿ýV–.]jôÑG¸öÚkƒÝ —#   ˜ à(æ§€ Ø@¶Æ„ ¤W¯^¦ZÅŠeĈR¥J•Ø5Š{& H:Ùagâ~?ÿü³¬]»VÖ¬Ycñ|Û¶m¦“Ï^^x¡qÙkР)V£F çÛ|N$@$@$@$@$@$@$@©|ùå—Ò»wo#ü¹à‚ ¤N:¦ßaöìÙR0‡åGyÄ–²fÍp•† "/¼ð‚?~Ü,‡å!2ª\¹²\tÑE2wîÜ€ëó    ˆ7ÅÛa{H ÂþùçÙºu«´}þùçå»ï¾3nEo¼ñ†´mÛ6êv±>\nžH€H Î@DôÃ?È¢E‹L6wìØT+Ï=÷\)Y²¤´jÕJ=ˆ,C”òÄ”3gΠ¶Á…H€H€H€H€H€H€H€âŸ„öïß9"9rä\¹ryMè+@_ÃÁƒåÀžé·ß~“¿þúK *$—]v™.\جo9œ… 4‚àÛèÚµ«y?~³È¿ÿþ+Û·o—M›6ÉæÍ›ÍsT€Ó–,YÌ#žŸ}öÙòÚk¯É AƒäwÞ‘áÇËm·ÝfïÆóøÞ{ïÉc=f¶SºtiùßÿþgË–-k* `Á+VÈ×_íY‡OH€H€H€H Þ Ppïgˆí# @†ÄêÕ«Í´qãFsS„›#ˆ :BàFªGÒ§O¯›­ î’«‘ @@è|›1c†,Y²Dl›p”ë¼òÊ+Mö :è༇ G¸¡coW]u•±0Çr        ð€'_¾|¦|Xø·î‹p=Æ~.\h’“нoß>9zô¨ÿ|æBôsòäI#:òy+ÕK$+Ax'#ì¢ûî»Oúõëgæ;WÀ{(­†é¦›nr¾•ê9yGmK-[¶¸/¿òÊ+&QjÕªUÒ­[7#$‚X꥗^’.]º¡Rª q ¸ŒGl\vÂØ\p@–m1!ÛbåÊ•fB&ÄEÈì°ã¼óÎ37öÔ®W¯^Toí¶ð‘H€H y ›°]»vòöÛo› Àë®»NªW¯n&”ðDgƒH€H€H€H€H€H€H và$Ì´iÓL#à( ‘ ¦Úµk޳u¿þú«§ô9ú¡óäÉc\„l'!<æÎÛ³ ú±:d\ˆð¸{÷nùæ›oŒÈ}Ùv‚,Ê‹]qŦûâ‹/6%ÆPf SöìÙM?8ÖwNüñ‡éo@©uç”7o^A©³_~ùÅLè?·Ÿ£|ûí·ß.Ï>û¬qRö44ƒOPÕ©S'ãlôøãËĉMâúßQš U>ø ôïßß´1ƒ»áj$@$@$@$w(8Š»S‘€7;wš’3‹/6YÈî°EFö˜s ܼ/^\n½õV©P¡‚\}õÕ‹V8DàÆ‡A$@$@Ñ";óæÍ››,>~ݺufZ¿~½TªTÉ8x¤×J¬‹r@ö û\`œ:Ð÷ÇŽóÎ;OÎ<óÌô6“ÐïGêú–è}’ ý¡àÁ¹’þ—áŒï6$òÀÝhíÚµ²zõjùá‡ÌãÊ•+SÑUW]%×^{mšÇùÊ+¯þ‡.¸OG Ï™ýÎibã›qD€×·8:l ¤C€‚£t¥õö4­ÿ…L"§Ó–Á B³fÍŒ@åÖÒŠýû÷›lÔX& fºí¶ÛdòäÉÆù(˜ub¹Ìž=¢îL¢N>"zÿãŠ.*b£'DÎ=µ”½vµ(»‡IˆÆªT©"(;ã[';jIài²Žv@&ðòÐH Ìxm 3ÐÛ2-h¦“'Oêuô\©ZµªÔ¯__êÕ«gΊՅ5ÁXópH€ÂG€×¶ð±ä–H€HÀ&°sçNùî»ïÌ€ö í`Aíç‡2®D›6mü†tÆ”)SdÕªU2nÜ8ó{Òùžý.š(ñƒ>“;î¸CPÎ@iú±cÇ:g%ÕóH]ß½O2©>$9l @\Àï<ˆÉíiûöí‚yÎ oNoôQaÐý`èïºüòËåüóÏ7"t<ÚÏ!J÷u$²"£ž={š2¼×_½|úé§R²dIó6¾»[¶l)ü±´Ñ¬¢Išuh ÞÞ^²=Fòú–È}’Éö9áñ†—’H—.]j¾Š/°Â¾3çÏŸoúÿçÍ›gœÞHŒïM$_sÍ5æ±lÙ²F<4bÄÓç?[;”/ºè¢tdc|‡¢O¹E‹©Æ PF B#ì§5:á$à"¼¾¹èd±©$@$@$à À‘"Œ`Ÿ¢ôÕ^(KNGCµZÁü@uã‘ÁQÐ0¨NDGþGøQ5fÌ{1óˆ¬_±‘½À¥—^j“ñe:âUp¤ã“Æaè®»Dž~ÚnqàG,! DG„"×µÞí¨‡‰äÈ!*ÐiÞÜrÇÉž=õšpǹç‘´Ä'Á:ݨŽÈ¨¾ÿÞ4¡„ôdyó~«Ž;%´Ô*_ä-s»té¢OML­íxv¢JM'üs`Î¥÷Õ2t¨%4Òûu#:ÂçÃ_EˆÔ0 †|"2T>„ÑÞk«e»hùAï¥ x‚ ç¯\9ÑìM \¼ EçÕ«¯Zn`úµæ ÕjÊŠ"5kZç ç©D Q¡ƒg> ^ÛÂ26ó*1QîâQUïÛ·O4h °z/æOš@ÇÍC!H¼¶%Î¹ä‘ dœú¯à®¼uëVóˆçHrƒÈè,™}"»v–äÉ“GrçÎmœ6ðü /4îDaÀüÄ>Íš53xŽ©¨fz9®}V ûËûï¿ßˆÙ!2ºIoÈË—/oÏ‘´wÍ@‰}aoˆ‹6Éë["÷Iºè³©q@NF¡ŠÀÎ;M‹JiJŒgÍšUÝÔ2Óµb_­ÖÜv?šÍ5Óýùõ´#÷Þ΀`iåÊ•¦D%QNr¸v–º?w®ë|^N³%ûhv%ÄEÎÒjxóÍ7Íþo¸áç*|NqO€×·¸?El $@ÁQ@4þßÀÍÀŽ;å¹Ô‘]:,Ñ>Wv¼û®ý,åïCü¢¦fÚÑ™2?Ñž©S½¨#³:·‰f¼Z"=û!‚Ã:=«øQ䡇,Qžý~8!tÂ~öúëÞ[„y&ˆÔà@†rŒÐkbÂ÷Šj4M¨†Âœ_Ÿ¾ïñU@¼¶D“0o ³{÷îæxP’ƒIè0-]º´y<¬Vo([Ò¬p6B&$2ØQ*£“ª4ÑqÊ  7àµÍMg‹m%HDCÔÆwÛ ½AÃãÚµkŽ4þ"gΜšL•_¾jšß}p¨Äï?û1W®\þV‹É<ô«¡ÿ¤‘vÈ|§7|÷ÝwŸ:£Ø(ÀÙˆäõ-Qû$ älHE`ýúõÆuí«Óop.B¢ñj™‘¿À÷0äNjF*ʤ¥%”Ì—/ŸWB`™ÙðWZ óàÊw# ¸¯on;cl/ ¤ à(…EPÏ`‹êŒV°´ 2Pƒ>½€û€ì«U«–ý2ÍG89#žG«VYÎ?êÆ-(=ê˜%g AI,E‚ $ð©¾Ë¸AèJ,(òöÛÁ¯åmÑÎܬýòøã«Øéys£‰*yZy/èб^A™¯PY½ƒ-¨Žè¢ÿÌp.Û··Üj¢Õ¸W}ñ…è·Uj/½ýâßQM>Œ(JOgBsp–BÙAhàåŒgž±>ßàñt`ÎÐDZ-%)ú}'*àô¿eM 3¥ðœåðàbQ!¾W´â“qBÒ~ FðÚ–h.Z¥Z!6B‰W\£à²ˆŽÔ9sæÈÌ™3=G÷#e!2j¬ƒ¤b €[ ðÚæÖ3Çv“  ÄEß øíf;h€Ð%—\"7Þx£)ÛŽq$Â!Ñ žGÓ¥(g "x$Ñ¡úÎX(0ÕH^ß±O20I¾C)Ži–œ‚†©ý:\V:tè >ø \{íµ) x†ï[8ÄE;œ¥Õ Ô¢6òŸjf^ë֭͵!ÚíáþH ³x}Ë,A®O$@$@±#@ÁQˆì?|1†:óኟÕZä7ŒþŸdNÀZ5˜¸êª«L™”¨ë¥k×xˆÝ»E-E øüs« R¨íÒd7SÞLÝ´¥wo‘K/M /¿ §!”q»à‚ô—Ço½õ–Àcïh ·;aËr::v´Ÿ¥ÿˆcprÒäÍêKy7-(5Ì0n6p¤‰EÀ©n>ÁÜ—Ô¤.ÅFô¦Õ .ð3eŠhg„ç"üÿb‚ X XåÃ}þÚµ -J«¡¤Ê«Á¥Iû܃Ëܹ¢å,\Ð+&肼¶%è‰ÕÃÂõEˆš«z§ˆ©øí:+k×®m~K$.  @2àµ-™Î6•¢G¿Ÿ8 î°{ÍtðàAu4®! ªXoŠÞ€a=‹Ð‡ƒÉ~Žòd9*TÈkY/~øá¯ÙW\q…×ë´^œ£#ïhÏFÔ&Òø[>(¨t[ZÛ ç{þ Ôµjq¤jÕŒo.G(‹gš‘#ÓßÄz:$¡Oú[M½Ä¦M›LÞgZë ¥hpž§ký-t†pBÿö[«„L%N»÷†º™L-’ZØoÆ]!íO+ÿ &·D5:V¯ ¢BVi±h Ø2®^({võÕ׆з/<÷-µà4w#u»—ºuï#Úï@x4~h{EÅIˆ áf†ŠÉ¼¶%îÙÇõèÞ{ï5ðóæÍóá¨QZír­Cˆ‰A$@‰D€×¶D:›<ˆʺuëLY”ÈAy{:zô¨AlätBë0À{·ÚùöèÑÔªõ×âmÛ¶É Aƒd„ F\äo$/T;`”«X±¢)o‹Áoq$‘¼¾%bŸ$?5$ôãwS[|ôé¢Ìä(ÍZ…«QZ%ÑÒÚ^¬Þ³K«­Ò8”Ïd€Ûðúæ¶3Æö’ €7 ޼y¤ùÊÙ ]zÚjçÇT”>& Í~Ï÷±N:êÎÓ;Má‘ÓÝëãf'”€ã’3°½ŒŽ –úã?dáÂ…fs¬šAµÄ ¸ÏiÓÆÙ²ÐŸC@g8þ d’¯`Âw‹×\#G¤ÌÜO0U¯nuìl߾݈Ê`ó=wîw²k×ÝÅ>s3Š24'N4æÙ¯®*A@œ¥ó¸oŸèö2²µÐÖÈèõ×E4©G­ƒE*WÑ$ÊL‡º¾GªìÙ3½©˜m |y«”˜ö›’cà¡%ÙÕM+¥%š«YL"XJŒ9ßÇ’cÇŠv>ˆLž,š!›²n°Ïj×¶–„¸'³‚#¸FÝzkÚâ¨`Û•‘å´ß”,|óM‘Îy‰Iq“ëÌ(ÎÈöÝ´N²\ÛŽk­MؤÛ×6œ£jª€t[gb°Ÿ-”K»C­ò0@±‘¯H:Øíp9 w€ëé®]»ÌAÀÍ ¿ó“!’åÚGLÎkÛõ×_ïºRJÉð™ä1Æ?”,ëå¨Ï|Þyç™ÿ%ôËü‚Ž Ä K–ˆäõ-^ú$!öÃÿŠóÚáÝñœý•,À8Nü~ÿý÷åMí Z ÞÿiçÚ=÷Ü#ƒÕâ%)ÝHB†³1D­}‘±Ëp%š± §9Üí*®<˜ 4:®oÀ‚17œkû‡ñ<8•1H€H  ÀݦôM"™‡‘¸(8 áÜÂ1ÈM›6ÍØ–ÂV;­øJ‹-RAÉòÐCù]?8œªàÈW\„΂Œd5ì߿߸4½öÚk¦9è@˨àŽ=šÈ—Jøà<Î`Ÿãž©IkRÓ† J«»mçr”Æ@í–-[õF­¾uL÷UG¶oß&èø°ã¢‹Fè@u'u]Z¤µ½¯NW ˆŽùÊ¡C"·ÝfoÅzÄÇîM(oÕ¢…È7ŠŒ!Úá轜¿Wp%¶áŠ÷”¦=ZtpÙßÒ)óЈœ  1Ä)(_§É8öh‚–v XeÆTcaÄlpó,½ÏF Á¸ í ÕMÈw{(±8|¸èwblœ¼ÐýZ3 ñ5·páee}ßá=Ž’éÇO²\ÛpMÄd_Ûp®uP-ôb’-[6u%û‚F8Ù HR‹/Öß0ú#Fãw­Û‹k\2D²\Ûpÿˆvçµ ¥¶qÿÆ d%€ßñpžÆ==ÄåÍ›7 ŧŸ~j–›9s¦q j¥Ó µmÛV]`—è=ý‹2cÆ ãz\]³–òê >œ1 ]_o¶áBQ7³™¡4,A—]¦7Õ(„À÷ ïw~‚¶9,ßc g¿d¼ôIb}oÎkÛ!C(8Jäv& B…·4{sÇŽR¸pa¯ ""üþEΤI“Ìwú}!ðlÙ²¥üïÿ3׊L6!æ«—.]Ú8èż!l@† À¡êmtÜjà÷ý!tþ&Q$Ãõ §b£5kÖxÎ/Äì%чJIFb#û7=~ã#œ‘¸(8 áÜúÞ|CmŽL6gÇ=ndPF úÈ(Fi3;ðü•W^1™pþêÒûnß×±ÈÞN Gßå}³“­ç;¿X±b&ÛÎþ‘ëû~(¯ÏÖO„á=ž~Zä™g,·£?Í Ç–S¶,ª&ªj‚ƒ‘Çõ¡·Šê©h‡€ ¨kÖ¬«e¶òi™‘G©­eiR¶èDA‡`œî2(QeÇ»ïŠf1ˆ $–&NšÉ~/½G”˜{þy‘•+-áö«J­Z–âßÐïuA©»^@眨û…¨õ»%H ×¹Â>!~Z»V4SÈ·î{ 1–öK˜Ï2xã³L@°«É°^î§ûFÍ|ðו™ŠOyD…#uÓO(w<úV]„ èûï­ó !Ž7™ÿ<‡Û”&Û‘Yˆæiž6às·¯¹sE3mD³q=o…ôBDü¶¨W/¤Õ‚Zÿ_ði‚WºÏ&ØÌ™“ßdƒÙ+”-[Öd0Û¯ýÑ÷Ú“¨×6”¼„Ë2ÿ!p½‚@ØR¡¼žïSkÏ  ä%€ŒmL ¢Ûê‰N$Y®mpY“]¢\ÛýsÉã‹8@\‰²8¸—Ç`2 b¡Žà R/ƒ7)U´sålá&q¿ÑÇ#8'U‚e3#, À„€CÉXXù&IDòúæ»mß>Æôû.ŸÑ>Ilÿ‹¼¶¥G<¹ßÇý0~×¢_~Ö¬YÚä?Øv‘C?=BT”G¿¼ïg6¹‰òècMåT1!V¬X¡c O›çÉòÇ÷ξIßm‡ú¿ï»|F¯o8—eÊ”1cƒ¨„  D'P£F Á„À÷úý÷ߟ臜ÔǧrF°|•Öp-²YjèD€¦¸ùY«Š‹Gµ¶²,ìx^Õ!­ ë¾?~Bu8ÊîS·*m¥ûõ<½9´ÊŽ©{¶@¤€ãÕW­’k]dÍ õ/2[ÐA‰ Å:hÆK S^¬téW531eko@„Ò©“%6šéf¨¥æàb„€ ‚!8Ç0¿² ð‰˜pF‚¸å¿ Ë‘Þok©¨”•pï Ñ œ¢TLïÏÀ%ÇW“²VÆŸÁ)/O‘nÈø6âiMˆPªï»ï‚oJœi xY¾<åsúðòà¡&,ƒÏ‚3 >kÚT´£-e.D>8Ǫ]”.]RæÛÏà2Žÿƒ† -›~¤Ux Úé-ú]d/•ñÇÚµ­ÏÖ7ßd\0dëùÂÜ‹s4ˆývÁw„vê4mþ·!ì_Õgý¿œqzñ¹&¯mñy^ÒjÊH`P ™œþ%?0àV±bEos $<^Ûþó“œúNÐ3W3!àæhÛ´£¬ “QîÙ㓵–ôwz“Þo"lŽÔ õ&*³eÍP*mœÖ‚ µ®Ñ'SÜî°HòsÆÃH^ߨ'žsÄ­dž@'ílEÊ"EŠ˜ÄO|"Sîܹåƒ>0nE{öìÑ~œ³Ìw~{ÍðÄw=Ê-â~Ù9Alt£vÂB„ÏïäÌŸn"A€×·HPå6I€H€H z(8 µïÍ·½êã?®UxøÜ®¾új“U×±cG#>Â"°ƒ8É×Aè (Xª¾ÓM ›ñU_;6íê§·Þj‰e ¨qöÝõé#2uªh¦›HFG£T{7X#CçgZÞÛ”S—KêTkJÅ9 ¬¬7Òù Á‘:¤ê rÊ‚pj‚€IÝÕµ,[Êü`žiÙK³½»îJqL‚KËÛa–½ hã f‚@ làÒ£ÕýºÀ¨¼<ñ„h¹@QËw{+¡=ÂeIÍ7ŒÛLhkÆïÒ»‡Ð!¸¥À@ä,aV³¦¨CVê5ÿüSdëVQg4k‚€“&®{ʰAÌ•ž»\˜~øÁr4‚HH5Ža l 1~ÆG(-¨•žÔ%Ìl*làø„¤5üOù©Ôˆ±ÀÔ®4Ó|w¨Œi…­1.Ú¯m.:YÚTü†@¦>:W‘PPÕ(ׇ ’ ¸„¯o.9Ql&  @ÁQ0þf£†¸oT®\Yî»ï>ßÙ^¯ó¨Í F­[·ö̇5&¶ç]䣒9räˆgù`žœDý&G ë#VW þwí™ÀÉ“('öÞ{–»IFî+Ñqù°ZÏ\¡~O7d‹°}‹:±Guì€é´&Éž•îcÑ¢¢7ËÞ‹éý±ÚE£4›÷üÇE;H-Žªò]!N;®Z/ô¯olkÛ6KXѳ§h'¬gQ¿Oàxôõ×¢¹aÃpur–Žó»3Í´ÍB $ Fp„Ï%>§Á”÷Òòñ!¦ô"=±‘½>ú·UÖ@Ù6è´rS†¬¥KE…}¡ÿÿ¤·C¸„a»C¡Šþ¯œRpZuJÿ×SæB¬×/­x´‚#^ÛR>nx†ÌÍUª\íß¿¿<õÔSnh2ÛH$@Q'Àk[Ô‘s‡$6p‡þA3'V¯^íy„ƒ‘=àŒþˆ¯!.B²Ðå°,õè«Á ô‡š0pà@?K¤Ì²ËMÂáˆAñL ’×·D꓌çsȶ&ð±ZË?©Ù˜( þfûA@ŠäZ¸ý¤Ùy(Ÿ —ß:uêH-ÍrôÉÞ2ß!ˆw¼¾ÅûbûH€H€H mg§ý6ßuÈKŸèÖ­[P78תå ÜŽ0Hˆ8uꔹQ‚ݶp'pF¨‚#dý9q±¸î ŒJAEJpä{\ZþÖ”ŒjÐÀ÷ô_£óµ»q~?ùäcÏë\«zu«”Ê‘AQC¸‚!ˆR €ðÑ›i†¥åJǦ´Gêì)Ϩ]ÍšYî9¾û´¼~TÍqBtÄH!à¡]z'¢}ûÒ[Ê]ïãó†*NÁˆ¨ü™V*P±eæ„lþ¶kÏ{ùeKå+6Âû:æ cÆxÿ¿)b9NAa^8ÿ¿í6Åû#¯mñ~†RÚ7Xkÿ½ûî»rË-·ë½§pá3 ð%Àk›/¾&ø$€> ¸¡œ—áJt§ƒÉp±€À¨R¥JF`tÖ¹>3ˆ¬¬‹ßL¯h-j”ºÇ¶¿@ß JÑ–×L8c0H ž Dòú–(}’ñ|þضÀP³M›6Æ©}³¶[Jeâ:ÀRhÙñH¼¾%ÂYä1 $3õaKÀß8âè sÆ–-[œ/M9çŒPGû|” ±½óU¢µ±GÙçpäéÞ=µ³Oz{…=o“&MThpØ8:Ÿ(GÃ)ˆÂ0¡í=z¤Þ*ôbpÇA94ÑÆ_ˆT©â]¢Íß²˜¬ØË¢ÿvÜ8‘aÃðŠa@I=šy0ñJ‰Á,é®e2*6ÂQ~ù¥u¬-Õ—)ðd…ZÝҫĶw÷ÝVé;8™%cðÚæŽ³>gÎO¶ç$UÀ2›Óç­$ˆ ^ÛbÃ{%ô cæÌ™ÒSmwQòeàkÔ¨a~ã ¬”;wî,£G6â#,¿YëL¿¯5ÎQʉ\ÁˆìvÜŠzì(«(–/_®¥À÷‡µœZ }q> d–@$¯o™ÅKŸdfsýèÀg}³p8ù裤2Ã$@IE€×·¤:ݨ¥ßº¦Ù&ô{Âeà@5EJå’æÊ~ÞÔ²ãróÍ"ª ÓLM? œž¥eÉàâ$_Áʱ!5²ãå/*û!š©šx‚£xaìÖvüñ‡¾Ö´"‚~?ÅÏQ@KŠRl¥KÇO›¢Ù^Û¢I;ô}Ue)ʈÀ‰o–~ñÓJ>t†\ƒH ùðÚ–|çœG?àT1Cëcš?¾&#i6’ÜŒéÍk}­^W3kJëïH÷Yœ¥õ ›i}ñqjß §¤Ë/¿<(ŽòæÍ+×_}ª÷8ƒâ@$¯o‰Ò'oçŒíI›@GílEIM¸ØÝ{ï½i/ÌwI€–¯o {jy`$@$@IB€‚£Ntn­ÓS @°çÀfÐWh“¾ŽF¾](ç…|Û†¢tÎeÍš5Ð&=ó!N‚cõêÕ³Ÿòñ4_~ùE¦N*S¦LQу%æ‚«Ü‚ uv& ¤9÷Ü`Ö¼L±b¢6ñ¢çV¤hÑÀËa_ÚGjʪÁÅÚ/*… ‰\u•snìŸ/\(Ñ‘&«&uLž,Z&@ç:åüà„Ïñw„ ˆ~O‰0·|f–Òuý.µœ‹ð«Õ¨IËçŸï«&kðÚ¿gBetº®]»V d\â·µl Ä^Ûâç\°%ÉAàgͨA81bàÉYçêM3ʦA`„©bÅŠzo«7·Q”Uƒà.GO<ñ„×Þá½råJiÓ¦MH¥Ú¼6Â$E‘¼¾±O2Š'2‰v…¾êõë× œŒð.w˜ð¥4ßzë-iÚ´©<ÿüóID…‡J$àK€×7_"|M$@$@î"p¦»šûÖÂ9ÈkÖ¬q¾Ló9 ›ygœ©õšœ6Þè¤[¼x±s‘€Ï‘9èŒ:°Æa˜úߣF2–¼¨þ˜ÖECgh»víT€0G>ûì3u Nwwé¥"º)-k°mÛŠ¤W¶ Î+Ú/+8½NC-­®£¥àD6 O[mâï¿Q'ü BDê¬ø/ÎÏÝw[NO‰z˜øêƒ¨*ȯ(ƒN]ˆhކ éÓGô;@tpA´|¢¨ØÐÚ?ÿ¦&Àk[j&±žóµÖÍÄà܇~(wj]Ïž={ƺIÜ? ¸Š¯m®:]l¬K@ ²7³gÏ–—^zI˃? åË—7Œ=zôU«VÉ-·Ü"o¿ý¶I¤úꫯ¤wïÞÆ=(b#`E2V®\¹ŒàÈ3Ü#qLp^b€[DêúÆ>I·|ÜÓÎ7JåÊ•5Qò*#:…“ÊhÖªUË8ݽøâ‹R®\9sÍÀçA$Üx}KîóÏ£' p7þšñü¡®´3†n:¨œóü=GÇÛ²eË<[¶lž×öØ};c̘1Η~ŸÒ_Ó¦Mó¼aMÑ´lsüðÃòþûï«#Q+“]‰,Kt4ÂÚÝMa›UÙî0h;£ŒU¤+çU¯n‘R£ Bµ\*îuå9㌠VqåBpÍÑJ¦<˜¿HÁÌÞô_,$'«,Ç,ÌÂ=ÏÁ•L«8/gÎô÷wª#Gj¦¿`‚-Ák[ìOèÌ™3MögU3.]ºT:tè Nv›d„ Z 0@-ÀØ7›-  ¸%Àk[Üž6Ì%Ð7pfÆÀñï¿ÿ®åÅkH·nÝäõ×_WÞùFld'ôÀ­9K–,qyt(«†€s¤(ï3wî\Sö e<$à‘¼¾¹¹OÒ-ç/ÑÛ ‘*D©ª(P@DqÑã?.pÂC_-Þƒ©}ûörñÅ': $0o^|%olh”Þàõ-J ¹  ˆ ŽB„ ‹×§Ÿ~Úk­çž{Nžzê)9qâ„×|¼Øµk—¼|ºT§7^°‘ ÷ß¿×[ýû÷75­QãÚØö=÷Ü#+V¬ðÌ.Q¢„™ç™¥'GŽˆLŸ.JáÂQÚi»-/2fPZnÒ¤I®¬…ˆ )ˆ&ì:TTD%ǘH>¦Øw°‚#í¯Uǯ´Ý"ÙÞhm»R%‘cÇD6lð¿G޲gíœ÷ÿ~"Ì…Ûµ&¦IíÚñy4—_.R¶¬ˆj8L9BM²* TÚ¹s )ÅÔ ²¯m±;‘ȶ¿îºëŒ vµZÙuéÒE~RåÛØ±c¥X±b±k÷L$@.'Àk›ËO ›Sï½÷žÀ•åÐp÷"ßRj(‰“Ö¶.8ÁAãÔZ>(_‹.gY{û=>’@<ˆôõÍ}’ñ|¾’©møŽEù4”Ýl×®:µ¯6%Ô’‰•‚% 9Ò&aW ®E+¼2”¯oü €{ œíަǮåèXà ¸³ÜJšÍÒ_‡È*Y²¤ [îÇ”-[¶Èßÿíi,2çÕ‘V4mÚT_›N=,‡Ò`5Mœ8ÑÔ¶FÖ ?;ð³Ï>[žyæex´ýv0Yºûîhï9õþà8)ÔŸ®*(·9ùœŒ üèš3=Í&"-6ÂN ªãà²x±%ÚH¯¤:Ê©!´Z]BGÇŽVy.‚"® Dé°ôx%4¤888ˆ‡Pêâ/M¸*ðÖ·ïvÙ½»ˆ\tQP«$ÌB¼¶E÷TþñÇfïµ×^3¥<éùØc™,Ðè¶„{# Ä%Àk[âž[Yd Q ¿I-Z$¹rå2¥o †ŽEC8}( µ.6Q.þü‚rjˆF…sWÜ D…@$¯on쓌 tîÄ/ŸþÙ8Þ}üñÇ2cÆ íG¹ÈôÅú–çó»2g’€‹¨FYàHÇ{Õ0›>Cta*^\´/'øƒ9tH䡇DòæÑJµ¢ùãŒÓx}ãGH€H€ÜI€‚£ ž·G}ÔdüõíÛWË悔Æ1µ“9r¤ZÆ3PVmáB«UæX94dZh³¬Ze‰hÒÚ‰â7®2¡Üd¥µ½x}¦#ŒG´’>,ú¿¯­OžvÝv›È”)¢vÞÖ÷S0G®_í*îl­Nmª²KÂàµ-:'¥R»wï.(ARS¿d!:*S¦Ltvν @’àµ-ÉN87d¸Ç†gêÔ©zϹÐd—wîÜYž}öYÓ‘°‰[4ÎM}ô‘)åƒr¶…ÕžùÊ+¯L#äa$H^ßÜÖ'™lç>–Çk ŒPVÓ¯¿þêiDF£GªßÛ³Ÿ@X¿^t|Ár B¿ü_ùo¬æ=kZÿïù›«ÕU-Z•A´R…¿%’{¯oÉ}þyô$@$@î$p¦;›­F†28®½öÚ4;ȇT¶þæ›o}Ó•Uíkp“†õð<­@y¶·ÞzKË™i=³]–.©RE$gÎÌ7°o¿AmrÚ¶mk Pïˆëõ—þÀUù_Âd(‚ÿ¿ÿþkvŠÒr·Þz«º™d7ö½°~O”PxiÐÀ*Wíc‚àáоY3|þÂIFKµ›vú¼•T/QN ‘L‚£ƒ­côwûv«Ü¢Vbˆj¨“·lÜ(òÒKÁïöŒ3‚_6Q—äµ-rgv£~ ëÕ«'mÚ´1î…p.\°`ÅF‘CÎ-“ €!Àk?$àMà þ€?~¼Þ»50%ÓàbåÛ5ƒ%pF•Pb#=œŒàt„’?øM†¶t7òþ\ð•ûDêúæ¦>I÷5÷µ× ôË"‘¶¸Z¹´oß^à.$O\? æD2 \æƒI²u¶8’à4Žä?Õ=›ÎHî+Øm«æZEûj¬¶ÁÕH»rdäH‘uëD+‰ é Øès ÖUûÿê+Ñß`VuŠŸ^ß³á;$@$@$èp”ɳQ œ àijV˜6©ÅIµxAi5LWhÝ¥lðÚ 1 TêÚµ«qìA¹¶5kÖ¨ c·–.;n:áâS·nݘgämÞ,êò”¾ûM°‡W'ð¬Ð·‚d0GésãñO R×7·ôIÆÿrg O:¥‚Š/d„ FHtòäI#0êСƒÜtÓMæÞý´ 8qBÔ)QTÐ+¢´ßšl?GÁT2½î:5ô„~¬ôº,òûïÖ,$ :‹ìßo {à¤oOáHvö4 À$N"Pö ®éµk[ÇffñîEZ½5U€•vɈ&š§zÛÌP#F-e{®ÿ7“l.¯oIvÂy¸$@$@®&@ÁQ˜NŸ-Œ¹V4aŽ ôWèmZS<† ™¨P!<­ƒ°ê*µ&yðÁýnÎG˜PbmܸqFhôÜsÏëwd+VƒB&AC 4‹HÔù)z­Ü5×X%ÝàfÈ™Ú_­Ñk[,÷„›â~µá·êuÛmÃQ®\Výn{^"?¢Î¸ŽUÈb­@HlÁ>7( Èpd¾¶…ûL!Ûó/õ߯ 2µ$@$@±!Àk[l¸s¯Ñ'AJ¤á·D6([Ž8÷Üsã"DFÍ›7W—â0ØGÿð2´G8"Ã%¥îQ– \ H‘º¾Å{Ÿd¢œ¿x9ðùòË/›äZ$~ÖÑΜûî»Ï¸Ê㻓‘8þøCô<‹ö±[ºÔÕÄÊ+Ž œ`¨Ýñúy9tÈJVEôŠ»îò¡ùÀ$3/_.rùåÞk®Z%êí=ï²ËD…Ó¢Õ¼ç‡ó\‹ :ë¬Ð· 7$ˆ”4ÇLK¸z¯¯EdË‹”|B§;îu »\“©µs™aðúÆ Ä?³ã¿‰la¼§àh¦ì×ô…[œé@åÞ·o_Sr ®F°G¯_¿~€¥c6²A´bœÔ¨Ýãˆ7~¨] ;YѺµœ˜’¥ïŽSZžÞ¸ûh‚— í—ü?T®X˜å›ç!Ë1~`ÁQÏž"µjy ³ÌJüCID`Ñ¢Ef@Ù     ˆ”!G鏸>|ØìæÒK/5‹=£¼kF˜#ÕÞhn·iÓ¦êpŽÀ©ÎNèC` X¨òå¿ç¨…yaÍ®ëׯŸ&<¶•"EŠQ‚øùg‘nÝDfÎô>0ÍëõýóåÔƒ@õê"åÍ›²µð€ J£A¤ñDL¶ p-‚çÚkSÖµŸ!AQ‹C˜Éžg?^}µåœ¤´êƒœ’`R¨ú7-O/š|l/™±G-T!O ¸–µ–ë—²èQš€A$@$@$@á$ðŽΘ1CF%_}õ•Ùô5jS{ûí·gÅPî¯ÃÙ®xÛV.µ¢Åï±Ï5{„åÔâíì°=$@±$°dÉsÍØ¡ŠŽŽ;ʈ#(ÊŒå ‰Ð¾ÿüSäÅ-÷­§ZSÃnÒ¤IrÏ=÷Äe;“­Q?lõ9BtóÀ"™5K†桇DÇTD®¼RT¤l¹‘§Åâ™wÞ±–Ø»W%М¡™¨úq,½z‰Š‡3^Z 9Ïhÿ´i¢‰Ìá= ”{Û´ÉÚ>¶(ß~{,½Åø> Ä ˜ ŽŽ© ÈêÕ«µNïsCs3|5Ó‰ùóç˘1cäÇ”'N¤Zº¼þbCß­·Þj„H©àŒ°€ÀâàA‘ ³é5kÖ˜ QpžáÚ l ;}zÌfa›;~¼h-÷ðe„«½ÑÚ2f϶²apÓÝ#GDmo£Õ‚øØœ·–.µnöûô±:AÚ«ó/nØcÑùTØ H!€rjˆêð g @& Ô›ðÁƒ ô­\vÙe2`ÀÍžï _|q&·žØ«7S;L  Hv(»Ù^;oÞÿ}uw)iË–-›ìXÂrü¶xå«Ïݨ €>CLU«¦v¸Ù¾]´Œ÷®Ñ¿øÓO¢Â“Ì b¶mxI¥Â† ±œÎqTeÂâ!P¶í7,±TfJ«éð‘qeÍ™£rö‡"9óÐ!ë çãï:@¼bÅ ý´ÌŒëÛb¢3U]ºti¹Wíý*ê*&T§B øûï¿?|ã–⎀G'žzê)ùðÃCÞÙ_|‘¦Øè|•ˆû+¯¶råJ“ù÷Øc…¼O®›´¸ñÉ“'¥\¹r±i÷4M‚’ ¬›ï WJÀ‚£<¼ R"?nMÈ¢B½y $+” =¤ÞÙ,§–¬Ÿ7 dœ:ñ ,€ðÞ½{UÈ_Ä”R»çž{èh”q¬\“H€’’îKQzI½È2GR0­0'/¼ òÒK–ó“Ë¥—Šüú«sŽÈªU¢eèDÕD|ÅHXÒÙ½ ÑPcRcB½¦[îàšŸ­âa‘lÙ¼·Ö+´â%”{ðÁ´–³ŽÉ$dØ¥Õ üºä’àQó“Ò>xB\’H€H YÀ(}ûuï'­ãŠ1z{‚ &DBéú(nÕ:¥×©¥"¦ Z)[(?lÒÛßw ¨ަë/¿@b£s´ mÑ¢EýÇVá¾’[½U¾^¦L¹XköÀVü믿6Ëî@ÂéxWÓ àtÄ·M$¾QN AÁQ|Ÿ'´7ʬz'úý#ZP´©èwˆêå®»Dòæÿs­Rl-ÒÜO¼X´h‘iGñz†Ø.  ˆ??kíj”N›0a‚É"DŽ0P|nzvñw8l @Œ û®x(oÇ1cƨH&GŒ[»ÿûoQq¯he‘,¡Ð“OZmƒ0“?³b8=ú¨h)ºÐ®ImÛ†¾ÖèÔÉ*χŸöíE«;dl;‰°J«a %t¨H6l™5+4¡W(ûà²$@$@$/PY¿çÌ™£ã˜ßéof‚s2Ê´£:ƒoäÒÁ_¸*שSGÇ?/“¬ZƒÓªöµñ;%Þ/â /¾¤}qÁ>¬¸‰ñÊ•+« ÿA¹öÚkv˜áÃŽ6g”-[VüoHΜ9=³QcºQ£FRµjU­GÜÊÜ<áMX|͘1CÚ´iãY–Oâ—€-8—ƒÜBÙIú5c2‹&M¹å ŽÜrîØNˆŽÎP•fµjÕ¢±;îƒH€H€HÀÅ–.]*C´&ñG}$°$GÉ£:šÙR-fÏF c „@ýòHæ}R4¸ŽŒÖZ\,g‘EmÙ"£‰EPzL«¤yò¤»HD€³O–«8ÚÛ±cDv“…;Ô;ïˆ\y%ÅF y‚yP$@$@†taúòË/°odQõ…^h&8åUççkˆŒ0QDÄRFD¼Ç fXq9£[·nÆyÈ9Ïßs¬ë={öô9ßÏ;·¼üòËÒ¬Y3Ïl¸QpäÁÖ'K–ˆv„Zö­ÅŠe~Ó(;ƒlÍ’%Kf~cÜ D‰G¨9mšU×½P¡(혻!pŽ®ÔÞ,üFa €?ø½Ð§O™?¾*7lØP{HíÚµý-Îy$@$@$ÀaUU,X°@æÍ›gšÖ¯_¯e¿JËÔ©SM&zÀ“ìoå#:Î · ®0%ÈÜ€¡KÑ«"Ï?o9%ùº=ü°H“&"õê¹áhÂׯ'¬m¡”œ¿xóMQçHË%ÊßûœG$@$@n €ä¤üQ¶nÝ*¿üò‹lß¾Ýó7Ë={ö˜Ã8묳äú믗 ˜ %Ï0A‘ qÁ‘¯»2ôàlLàÆÈåË—8#¥¥J•’Zµj™+,‡:ƒßkacì—^ŸnÝܨ©TXG(“ÇÌͰàäF¢D‚#„~t¥~}ë9ÿ’ àÇþ¯¿þ*7&   HEŽF}ûö•/¾øÂÜ·k×Î00Ì   ` @¸:{öl#2BÅ”Ï@,XP…4ÝT˜ò¼)ƒìö’a9”âÂåö©§D³ûÝuÄZÕDºwéÕK"”V³CRhB¶È¡CÉ%8Âñ¢_öòËE4ÿÜo trÁ´ª ƒH€H€\E`ÿþýò¹Êã÷Qͨ°?~sQóæÍÀ¨nݺ \œë†ó9~—ìÜ)òØc¢â¦pn™ÛŠwíÚµKV­Zåa€Ú~ƒ R[Ò3=ó=Áº¤sʦ5kÖôް<Ú@ÁQ0äB[fÅ QG"­r—é@­H(1!c€›Ø‚£«¯¶2¢ÜÔv¶•H ²Ð鋨^½zdwÄ­“ ¸Š’¢ 4š5k–É0¼[ë·ôë×OŠ/îªã`cI€H€bK`ñâŦ\ÚÂ… MCråÊe^ê«ò¢žÚÛ 17ÙãàAË™Ü)ÊÜ]»Š–aµ\Žî½WT¸lÍO dŠHÿþn>ºÐÛ§ªÂ…E¦LÑœugà_dÝ:¸?r@r.Ïç$@$@$ p¢„ åñãÇMÉ3”=Ãt¾^¬ðˆòh¡¥r!,ºZ#ÛëüÎ+¬¿Ë.»L iéTŠuèaAô7ßX×dˆ¤ÉA ¢‚#Hœ»®KQ9ˆX¹reª¥ $ &ŠùÔ÷‚x‰~¨\±Q8¾Ãàn„(W®\øÊ-’@ 3F ÍMmwÃM“ ¸€ÝéKÁ‘ O›L$@$@ pôèQ‹Ñ4­ÇŒD¬;ï¼ÓXV<°¹I H`«W¯–Þ½{˧Ÿ~jòxà3ð„„Û`}ס©Ù“hr¿9":('R­š×Û®~‘=»åráÔäÉVi5\|ÐÍ®ãŽI:þjÜž´Ø…ìÛ—úÐ_{ÍšdáÔà  ˆ‹Ð'0vìXx<½È“'ºóÝ!7Ýt“™òåË—Þ*1{ïo¿™8ÑrìÐ!fMᎣL ¢‚£;vxޝÈëMŸPë9B¥¢E‹:g|{÷î€ËòŒðÍ Éø–DÖ¬YcV§à(3¹n¬¨K!ƒH€R€Ã2 01H€H€H€’›,Ïo¾ùfA©Xœ?÷Üsrå•W&7= @H~úé'éÓ§º¸¨‹F«V­Ôɦ¿”(Q"¤í$ËÂC‡Š:XB”ë¯O¼£~è!ã€"j–hJ—Tª$‚). K–ˆøº)hùàK|V²d2’á1“ ÄèÆ'ï¼óŽ>|ظÁí¸ƒªr0~ð矚éĉžçyóæ•ŠZf%Ü‚r§š;WäÑGE]“RèÌŸ/*j9ï<«L)ÄÛ¡Ä9çˆL˜ Ò¢…HÓ¦¡¬ÉeÝN ¢‚#ß’hÁ †Õ×á¨råÊA³†ºåÛŽ;fÖÙ‰‚Œ¸&`;]uÕUqÝN6ŽH€H€‚!ðûï¿Ë?þhœ ‚YžË $.ô4hÐ@6lØ`ž~úéÄ=X @X@¨ºNk@ÙÓÚµkå­OñÏ?ÿHÆ åùçŸ×ÒQZ;*NC+€hErä6,ýFîÙ#êØdM(0|¸% IÍÀK¼ñ†åüsã—qó;`Û­›~VèØ¥¹ùxÂÑv_±¶9~¼È_‰ÐÝ(„¹   ´lÛ¶ÍüvC)4L[µ<ŠýÇcÄ5×\cDFmÚ´‘œ¨ …P-“ù¥UÝå³ÏDlŸ8AV¨Ò­Î«}¢‚'‘`”tDÔ„É+(6ò‘/"*8òu8 Vp¡:✚„¡DÁ‚e3<45öàŽ…× 8ºð ¥@qÝN6ŽH€H€‚!;TÔUf9µ`hq  H\7n”n¸AÐ?2räHéÚµkâ,ŒH€H Sþý÷_ÁàÓW_}¥e¡¼ëBåÒ úõë›Rjñ~Ÿ©ÉûÒ©“¨8Jä…R#™7ƒm¢p"3gZ`(v ·Ðž(S&ó‘óÏIT±‘ ‚#ˆ³àr¤u@°ßá#`ÀtÌ‘üùE&É„H€H€ÂKBpŒ ÌíLýQ³~ýz¯œ£–?p/ªR¥Šq8¾ë®»%p£úÓR&M²ÄÉše¿±ð›Aõëâë)ÆÇߺ¿ÿ©UK‚ï¿x½C‡Î”ª^€ï¸ž@DGøGrF–,Yœ/>‡»Ñ©S§¼Þ¯à”Øy½ãÿ…­Ä»9 ÷gÄ- È"K§R²ú½Æí™aÃH€H€2JåÔ5jÔÈè&¸ €Ë  |ʨýñÇ2yòdiݺµËˆÍ' ˆ$I:"4uêTü¹JËP45SetT%8/¹ä’Hî:¬Û®YS¤vm‘§ž²¡œ× "f€ Ž3v +þÎ;E7MÚAù³~ý¬Á°ìÙí¥øèœž|RdÎK\sÁþ–JÎy(¥†ÁT5—0ŸEŸ¡ªä„£& šÀnµ‚[1DE«²ö´_/2³gÏ–Ï?ÿ\:d¶ #”víîWqÑõR¼xQ)V¬˜\ª¶guVÐû ç‚Ó§‹ôê%*‚5üLÔJKÏ%~9µÀø`àVõß   ð"Œ5kÖƦ1Ah„ÊK¶®àLýa‡ÉÛnë-Y³VP‘Ð)I’œ9ÿUqÐÙú{çu-Ê¡ÎFuU`C†µ\ñ{H+§IÞ¼–»?XÛ¡ž,^‚£uëR~«Ô­k¹fÖ [”¶…ÕÜûô¹øb»„p*kV‘{ïuÝíãéÜYäÄ ‘×_O_,•#Ç©Œïœkº‚@DG¾G6lHÊo¿ýfÊk9 µ.5\œáÛç{|:+¬uB¬rpGøbGÐá( "¾A$@$à"Ë–-dE„úûÅE‡È¦’ œ&pàÀ™5k–ÍÑz&‡Q+F£dÉ’šÝøïsOsâ @`ÇŽ“˜²i]ºt ¼`½g#ˆf̹ûno‡¢Ì6vpÈH`Ð C(§Å    $M™2E>üðC#0Úªµ6ÿûï?˜¼ªª]»¶Š…ª˜éz­íš5kSzÌöQ™9Ór(²WÚ¾]¤Hë÷O­Z"·Þ*Ò¢…HöÖ£v˜Òž(ï™?¿÷{%JˆŒ+²hÆÇÃó[êé§E…Q–(ÄÂQÞóyU¨È§ŸŠÔ¨a9=ü°h99ˆÄqü ˆ¨àÈ×áY~>ø Z‡ H5ÿèX0”;¬ûÑGymß·^oòEÈÂ-8‚‚ŠQÔ#g €Û ØÂçP~¿¸ý˜Ù~  H6‡ÔBá^M=§N2÷´•+W–&MšHãÆƒ*'ŸlÌx¼$@$@þ ¼üò˲oß>㎗%Kÿ ÅÑ\ˆPNb£»î™8Ñr9Šuµ*(JÁ X«V±n ÷O$@$@$KGUAÏX>|¸üúëQu%* W\q¡Üyge“ L—À²ÇOŒ%êb$¢ºp#r.R¸°ÈˆÔ¬)Z×ùŽ÷s¼‡É_Å 8uè`MÞkeüEÍ2#W_-2mšhŸ‡åœ„ãŠÔ¾"rÜhD DTp”M‹6lØÐdûá(þý÷_4hŒÒÿRL|™€q‡âˆK/½TU‚EsÒ~:Cïtì]X2«z|Ñ9'mf¡¾ ÁN¾\Â8_%TÊ »y ¸À"MK@'q%wn?8¶ŸH€H€H@3·š¾¸8C\ÔR-Ð÷qaZ=äF$@$@~ÿüsãdc „APb  åÍ›×ïÛ(W·$¸ã¬Ð»§ÐÈ^îJt°i„ç_ZPKV¨žíÙåïpcÍ   ·ÀïD`îÜ~°l? @ÐðÕШ‘¨ Q¤re‘%K‚^• ’ Ä _|Qž|òI)P €|òÉ'zO¦›â89>6ƒH€H üà†‡¾éìÙ³ûÝø€4³þ¸<÷ÜsZîãL¿ËDzæ›oŠÜ¿h"°è œ¨‹_ÊaÚÛºµÈܹ–èïÜu—h‰’è•Q»øb‘'žéÝ[å;ºtIiŸóDIç'ò¿ÿ9çò9 @"ضm›Ô«WO~þùgý}U@§—õ7T+©Zu½ ð»q‡Rõ„2„˜a9R¤fM”tCb™2›¢ÕãŒ0åárä¼ß!HˆŠàèüóÏ—>ø@^xáy÷Ýwƒ:¦ûõNçÑG ¸ììٳم¢aÆrŠ 2ÂJ™-ˆpõ­Ú‚3:Y\ù—H€HÀÝðûÅȤHÔ@GôCiÎÈï":ö*Å‹§¤ãƉôé#2gŽè_úËs‰ð8rDD+ÿˆVÖr‘ðÞ.tÿ¨_Ž,ž¬Y½ßã«ðÀàMÉ’Öoè‹.J½m ô,\˜z>,‘õ¶Fš7Oýç D‡’›:wî,ãôb†ûÖ™jíP¨P¡èìœ{! p%¿þúKË€ 5B¢3ôÝ]ªÒé¢JgÂ%ÿǨ‚¦²ªÑQª3Ü"Zt@fÍÑzíÁ`DIJÃv06Lԩמk=âÞmòd+ùTÍ|E ™ä†¢'6²[÷%­^.wßmϱڄA6”Pûþ{ÑÒæV)5»ü[Ê’|F$@$@$6oÞlÄF;wî4÷ç'N´7}Ô+Š VÖ¸2&Âq–//ZNäæ›EWäý÷EªUód'ŠÀ ràÀøqhòßRÎMtQb–,Yäé§Ÿ–Zµjé€SÙ¿¿_¶¨UÝ£G¹ï¾ûü¾ÌLXœ#ó~¶àu³Ãp8Ê–-›-Z4›ã6H€H€H &þUÕ#?ýôS#xΙ3gLÚ颓·MQ!¹µ't^?óŒH÷î¢åeRïÜÈÆøì3«ƒ;wîÔË$Ü?ÿ´²M ü¹öZË·J‘´>&è<×*ĦS%¸êÖõ&özŸ*àD‰’Ø (B`ðÀWpÔ·¯hI ë}Øï>õ”õ<½¿¨%ŽÎ~œóW^qW‰0ð@Y3dkÛS4’É‘-;ä@1jTà÷ÇŽµj£kµ ¹à‚@[ÑþA=z;pœj4«I"ø¼1H€B'ð½Ž`¢o‰2Hhzï½÷ºT„¾u®A$@$ˆæh–ÅCš¡±iÓ&œ—4×Ñ£G &8áBxtË-·˜~r“àrîÀ}Øwˆ|ô‘h9‘cÇDæÍÁ} îGœ‚#ãÓúжAÁ/L±ÍeNu¯‚¡$U Ð>ü¦×! @œX½ZäÙgEæÏ·§Äƽ©†iöy­[·Nêׯ/P1ôd¹óÎ;µò‘%<†˜:}{Þ-Žì+¦Nµú_ÿÏÞy€IQ¬]ø%JN0 ’(xUPD &DA¢^1‡ßD³PTPÌ"Š ¨\@ŒW’ YPQ@2JF%üßé¾³ÌlœÐ=;=s¾ç¶cuÕÛËÖtõ©ór LÈîNÎ~ÕÛow'7R®Â$4ÁQ¨‘§Øÿ ¦Y¶lXâçùóçƒù?üp{hiŒ ˜ýi©Ðá1ýäù·ÝvŽ¥œQá  ŽøÒ‹³G¢ >dwêÔ Ï>û¬½˜²7SÙ‚‚#ÞsÎöQˆ€ˆ€ˆ@ lß¾ÝyÈ3f N;í´| ³}K—º3[)²ˆ7LSåˆ.ºÈ¯PÀb_½ðÖ[nžè&M"K.QÂ@PGþøãù l"ÏLŸ5 z8#—üMWoi†Ý¶ñA˜3†™}…Ù'5SdBW(_dчžyßéŠÃ0üä&gêÞ3ÎTÎþ ŸW¹Ün_ë·*.Û×8{YâŠÎؾ ŠlîMnpó°sFP:{kõË/®£ÓÞ-®pŠ˜*"Úï¸áçç¶œ]ü“Û1áÛ,S4vî ßâ.oÜ覸`vÚ(óÿZöÿgœÉÔ£‡+2ãwõЬn¶‡/™(ä@E›6•s^@[D@r%ð—Ùù=h#¢ƒvžU0uíÝ–Ë¥XnêÚ\KÐFL#ðÛo¿ÙDŒ>ŽËY³hS͹ΔjSMÑñѷí üEö0U³fMg2._œµÎþE?ApüNÉç5~äd>7„^Âñ;²Í N‹à³wÿüÓýðyæ°ÃÒ¢ij„ˆ€ˆ€¤Y³\¡Qh²£™:‚"âð±· f¡ÓM+m¼´¾éŠ£r.CWßÿ=Úµk‡M›69ãîÿgÎqg¦zM×8÷\à»ï`Bu7e,]ì9^œ}2¢ÄFéú¬vÚkZóÃ?ñD{sЪU+ûÃTÑfje³¶[˜æàxŠÒ9Q ÂtÑ"€䢱cÇšÛtëÖÍ^f­Â­·Þšu*×étun,f­(|˜…ÈYgen2_;ÂÚ—LP‚O;)œEBÁËäÉîlÖ?t…G±Vñþûa³raßÝÜAk634Cåá‡áØÖrFé}÷EbóœÐw¬× òñ6¡7Üà Œ˜C›‚«k¯…=<»Â¦Ï¢€„A¯¿î¦¨ o/HŽx`î÷‹3ƒ8Àž[0eB4æ‘´æå'Ö¸à€ß M_gÎ^gÓ0k2z½ÔýóL`“—²^$„^(ð'E\üjiÚö¬ àóÏ];aº 1­\x”/ïÞ›LŽÐ‡é'LpËb ˶ä xÐAŠî_ÑD^)íè‚E‡0¦¸¸ë.XÊ 7•á7º¥R`E÷*þ_<ÿüÈÔx\·ìO6kxã Îj?ÁÄm󢩎ŽŒ&À—Ât5âä¨cÌbøðá)p2Ž/" "ƒÀ6ûÒúÄO8NE\îܹ³}w{,"ýfóæÍÁÓ¬ñ™ñ¹çžÃ³&0`@ŽòÙQtÏÙþtË-µo"×+ÌsùB’  Â%`óuœï¡!qÓ9ŽøƒfPÄ1²Ð:Š´‡ câè÷ñ¥ îÜixÝÞñ1'ȩ斎37s&ÿ|gŠº ï0›ÆL¹tê©q d:µæ?tª¤¾½bwÆöÌ|ÙI·vè¡Álj¾ Mp”(Òž–€Er ð% ó}Gߨ[¢jö4Ë™;tŸZ¹r¥ópMG#ÚÒ3ñMˆBD@D@F€n|àá I jzè¡”rì£k SdÙ{R'èpB}çøš6 8]r8ù–n)¡HÎŽå9x®¼4X¾9roÙáÜ¡­ï¾ dw…q[†Š*´Ÿ«PTÄ™9üPäæì >`óÐ~5²\gè4ÄOH,ôóÏÀôé®»M¸C¿å÷‰³w kï‘GÂ\?ÜÖ2m[¿~n)†a»˜ÂkáBÀ29iÜÂg.1U±ì=ŒãêD1Vx0ÝÓÅñwÄ2:¦ðýáËöõÒI¾Ë6n‘kŠ?‹MÙƒ³è"Ä™Q–:î0­½“Fb§Ð@JÜ…ýïD’i«V075W F¡ÿR`uÍ5nš “=,‹‡3«BÀ>}~¶öÛ Sˆ€äJ€˜÷Ú((_3Õ;_³ç²BD@D@²àçÓ6{`èСàì|¦Oã:]‹òŠ*ö%‘㣷ØLÕöŸV('X^'İb#~WäóÒÙHÆ|1Ô¡" " " yàŸe]v>ÿÜMg:˜)ùºžcnU«ÂÞýºûé5Áñ(Žoþúë¯6~8Òͤ=·EiPíСƒMn=ÑÆ”çX6¤ÆöÞÍy¯m­w×wïÞmc…cýúSœ1UÖƒ)a3%8vJ19ÇÝé†ÏÉž{·9Ð H9K™[‘ú¡MS¢D[íÑl›nM5*gïðçã6½ŸÔ#FŒÓ©12ŸˆBD@D@D`îܹÎCÓ²oû÷¿ÿôÚ/^ 0= ™2*$bE,­µã„ÂTK ÑÅ2Ï:é˜Ø—3—¥»ŽÉµ‚Œ¼,ZY68éâcî¶<é¸Dl1ì9ÙI‰Æºó]4ó†‡E-ö<Œãßšs™÷/È&Œõíë¦m`Š6›Üí|B-¥°-ü÷æÛo]!‘e tStÏ yq†ÅrªQäÆÁ º³LG'8"#N¥¨)Ó‚“ï¼ÓÍ0@a9Ó¬qbñI'e µ7U Øë…øC€Vw»¬:ᄜÔwŸ~ú©å¿ÄlßÞpR©•gN 9ùÃ_¥Š€ˆ€øC€)A[šb‡vùoZ© iïSÁÙt0bÐ-†Ž0¡ Í™gº3[™š+]äŠ Lì<ÒèŽ;B{ûÉm¦T‹&î¿ ð„"ŠJ‚˜o›¢’¶ow…EÙÛÍñ Ý–ø{Ïï-~™&Ž.AŸqögÜdwÒ¢2Ì5ÙÁ" QdÄ4tüŠÈ '|G^(—5 rø{Éôptl¢ˆ*Ö XiÍWØMJ»XËçñåʹŸxÎÕ9" ¹à試Œ\²d‰ý¸ßúÖ{ì%­uj #À”›wÚ›žI“&9[[µje’}ì¹ëÌBwºe*Šö™ú˜.êÆÂnœE@D@D@¢&°`{høü¦d}òIwŒîæÙÇóÚµƒ¹E^‚ÏÙ={ö·ô®¯Ø$ÍТE Üu×]γwn.ÂnÚ×"6qóxç3Èì|~4kyº pÀ¸öZw<Ñ4H–U'òZ™´F#MºMÙ\©c®™ÄAmM=Å «JÌS½ÜrnpP)I8«ãP›Ò| É#5¸WXwÅÛë2ãD¾I´ØÇò®Ðþîºë®s솹EÅð<ܨ&0aÂüùçŸfyF KlD<npFE"ÙSoñÁÏ´P¹…0t_¡í*gFPÀл÷ÞC9;‚i¡˜‹Â$>Ðy–˜þرÁ¥; SŒQ°’h05Ó¿r¶ Óœ1冖é´C7&/‚ì™<‚U–ÂqeÊ-­bö^‡ž{«y_i¡\PÖc²ËëþNVØû"çÿ SàQœËï䈰ÙW®È¯4ˆ……M×@`ZÔv62Ê´8Ï?ÿ<®¢rP!" " Ù0íæÙ6“ƒ©ÓºÚl ŽæCLŠDÙ²À'ŸÀ–$6J‘[¢jˆ€ˆ€ˆ@ lÞ {WïN 4óF'ÇIJ+Ûkݨ‚ïü)zÕr»RhÄI»œØÓšü1]$œ´jëΘd,Yxb¼\`§Ë? H%IQdô€MŸ6mšÍßžƒE ËÀ?<Ìg½?}Ø%ðõ×_[:ŠR¦²´\ÿ Z?g¹S(0»Ï’w6iÒ$´K?E@D@D 8³•Ñ–S 1(†ˆE^U>”X7ífºwßã>ÄqÖ m™&Ì2XyŒkœB7 [(~bz5º2%’^Ìvñ y׎ñöÜ‹š5ó>&¿=¦—Ï1‹'¿ãƒ¶ïƦ‚£ð(»àˆÂ6.Xju|øaÐZ]}‹Û“kLƒgÆœQÿÿbz=²Ûo?à™g¢»–Ž(|ìÏÏ8ã l¶V:^@[…ˆ€ˆ€äB`¤å(cúÍ',ðüâ—‚ñ¿Œ$)X3UID@D@D 0 ìÜéN076‰øã÷çÆnš´PÝ8Aspbq¢g–›oMôÑG9Ÿ9sæ8Ål‹||Ê)§„Šú'S· K½æŽÃ²NUSt¤HMI½ýöÛŽ²‘)Hò *™zkòäɸâŠ+,·ãÕŽeZ^Çk{j ƒÕ-ŸÆ±–K#·üå÷š%­ñNä­bj6]µHsMW3µLݺu“Ú+‹¬Ç@IDATÒt݈nºÉÑ {,gøwé¥îL‰ì¹9Nl‹e]u³}˜Ž$~(ü kN´A§&º2ñÖP×n‘Ÿ\ælº)1 šiŸã г˜ž€¸¦‘O»0³QGôE‡«Ÿ~˜f,C†¸©ã( Kç`¸Å‹Ýß¡hÚI/8#Œi ™jO!"7ÅölÔ¨QÎËÚ2…øft¢Ùùu4«@>·Žµ?zt9Rˆ€ˆ€ˆ@nØWÅ/½Ó+V¸ã¯sçÿŸáQ¼Åê< Dñ§Ã›«8#˜k ÊøÛraÐ çW›2ü8§Y+E€ÖôL7J§–[åOe^…ˆ€ˆ€ˆ…ѳ,Ir>…Å[¶:ÁfvÀÜfÍ¢M™â eèÚýõþŠ]ªW±a š9c™êÀ™6ü0¥?Ì N¡Px˜#¯‰šÝÏ€@ûö{÷rÀ=äúD7£ð`Ú¹×^^| h+Ö‡TNÐáù|'Žb£+²¡ƒÑSO¹ùÙCÛ›7‡¥twCÛÒõ'kÑS>ÿÜu’^!Zj:. °ÿÿÜuzâà Í9ÃSÏÓ ŠyåGŽtó/I{E ól²\/wÞy§ã\Ì4۸ݦ%î²ÿ8-[¶´—˜+ÝQèܹ³ïp(¾ÆÞÎŽ1ÂfGaÓÇ)½·ïÔu>>ÿ}ñŸܦÚתU+%´mÀ‰LAMñ»BD@D@D@˜j•4mŽ3~ÅñÓxƒiÇù¼NW#F#³gª´3Î8Ã&rž`i×ü—˜$Àqç¸[‹ñ¶D牀$‹€ï8›1ôG)Ô¨ãìÛ°aÃPªT©Ð&›é_ÉeOKÇ·4Ù,r›Fn±uëV›å>Ö Ì:A )M€G‡z¨å­–ÒõTåD@D@D ´ŒeÄ#8âyüêC™ÜÂú-ÅŒë–ÂÜÚ|¼õ`™_pÑEîznçeÚ6ZÿÆcÿâD—¨XgÅØûr'‡yß¾¡RÒû'Œøû8d@ñQ±béÝÞ¼ZGQï¹½c¸"µpÁ…F“'ÃÏò*AÛE s Ð=¨Gøý÷ßqòÉ'ÛŒÄÌ ÌìÀþcÆŒqúÒnݺáC11§jÎU«V™Øôú(®¸â s_(’kÃè|LAÒ2ëøè@Ä´g^Æ›fiwÒI'aýúõŽ«ÑÀQ´¨ïC ^6Ae‰€ˆ€"ÇÜÆÞrË-¾Ö‚ÝŸ½ÛÇÂúN˜Ã¿›.üþIw׊ôµ*\D@D@D úõƒ{DV–®úf œ¯+<ŸÓ§L™bãÔ¡K—.ÎÄ fâ„!š‡ÐÑñËÛÊý5kÖŒ¼€ÖD@D ¾§TË.8ŠV„Ò¸qc{˜ªˆ?ÿüÓ©>ËÙmö Ìçn¦È. ŽRäF¨" " ž`ŠX~‰%‰˜ŽŠ)ª¢ (wï®jÑòJ丕+Ÿ~Ê;øÛo³fœT»v"W Þ¹U«ºB#:<õì¼ú«Æ" …C€ýäËÇÈÔÚÀ,(ºvíŠ9sæ`ðàÁN uŠ• „ï2µ(ëA'¥,'â±Ç›h±:_D@D ƒüñÇx饗œ”Ÿ­[·ö¼åf¼g)K€… ß~ËéˆË—†tÓä§Q#÷''A(D@D@D@2›=>ú÷w]د»öμ`|F¾ÆÍo¼ñöpv¥'1íùÅ6hͱnþ¬Á/ ˆƒ€ï‚£•|“xŒ6jÕª•%8âlGÎLŒåüh¯£ã¼%@ÁÅbGu”·«4(DS§Nu®­ÃÓQQ¬qöÙnz´B¬º. ¦¹;áàŸ`©`]£Ða½ü2ðê«®»”eáÉÈ03ð£h Œ7΄œ?áÿþïÿòM£^‡æ[ÞÂ#FXѺæ(w_øî˜–?4{ˆÞ–ÿ®I-[¶Ä;ï¼£™™1ÔÁ" " $0ÔfŽlݺ~¹ÑüölWHdïøœÔÍLßÌnc>× È ÿþ7°cl‚Mtb£¹sç¢sçÎŽƒQ›6mо}{gBS¨)Ýxý⨩"à3ßG!µ$ÛQÂò”-[6ê&Õ¶©äÌ ΖT¤6¿ÿþÓ§OG«V­ò´ÎOí¨v" " "; Žè´xÌ1Çä~@¶­Ã†¹3Ui‰¯H=œdNÁ¸áàÉ'¨ˆ¤¶maBw˜xÚMsW¹rêÕ_5T$ð¤ýAåsÿµÌËe°oåLK¦?»ÿþûÁÒ0ëDKÑÞ!ÊX±b…ý=¿£G¶4¤ûâ¹çžÃÕW_­gÒ(ùé0½8¶I—¼8\pÁÞ.5lp‚Šu™ ˆŠÀGcÇÂÜ„“O.ø”‘#G:ÎFÿØ`'Ó¤ÝtÓMŸ¤#D@D Q˜­ÅQj§pà1–ˆe€1–ru¬fΜiêÚæ`– H#Ó¦MÑG•xš¢sàÇÁíÚ¥„4k Å`üÊb¦šYÁ¯«ÌƒþÝw€M™gfíÒ‚ˆ€ˆ@>˜mÒ¤IÎËYºÇåË—Ç—_~‰sÎ9=ÙFO³»%çV'%=ýôÓNÿL±_ /´ü4´‹§E¼BD@D@b%ðúë¯;}пÍB xqÿæêÆ8Lk3t¼ˆ€ˆ€ˆ@°$@¸ñFÀñðÃù7Œïh¯ºê*\vÙe¨l³(§L™"±QþÈ´WD AI%XWL§Æ8ñÄP[UQD@D@¢#°fÍ›ú+¢M§6f °jìáŽ9±£»†ŽJ>òý5Э[äµ9‘¹yóÈmZÈŸÝ|AO”³ü2ï¿ÿ>îºë.}~‡f–c†î¹¹ÅÆñâ‹/:Ç\ýõ¨T©>²éžo¿ý¶R¨åLÛD@D@¢"@§þG}ÔqËëÙ³gTçDsÐSO–uT!" " "¡-r'7ÆÛüÁƒanÀ°ä€%Ê3˜âœ†t ng³`¿ÿþ{üñy¯" "à ޼ ¨2²|moíŠ+õ Ù¬µ " " )L€îF ¾üŒ&,“ J–zôˆæh#" " Á&°nÝ:Ђ›Ç{lÜ¡+Qÿþýñæ›obÆ Nš5.3h?ÖüãébT³fMðE0S°ßrË-˜?>Î8㌸¯«E@D@D€¾úê+Ì›7Ïécè¾çEôíë:ð¡é™" " " DÀ’ S'àˆ#€ý –ú;öÆ3 ëÀ0g_X*ñœçS0=qâDtíÚ -oëìÙ³ñÀ`üøñ¨ZµjδED@<&àŸ/¬ÇUqÁ @‡£F³S" " ".¦Nê4%‡£&O.¼¨V-]¨" " "7çŸÞI­¯»Qö’/ºè"zè¡èر#ºtéâ¾ýö[PØDQR«V­p饗¢sçÎf)ïÍ áìuкˆ€ˆ@æ˜0a‚ÓèóÏ?ߓƯXsLŽ9øä¹ßzU…ˆ€ˆ€ˆ@0L¿~0ÑÛÿŸuP¡púé±Wž&ÂÛ·C†á)Y—.]Š#F8:ó3Z¶l‰ûï¿­[·ŽýB:CD@â$ ÁQœàtZN¿üò‹¥Yå úæÜ«-" " "\t8ÚgŸ}œY"µÂÞ¹:3W¯¹¦ #µ_D@D@‚O€ÎCÏ>û,8àœ{5ˆNIìY&ް)¡}úôqfmòZ ðšÀþóT¬XÑB¦ò öÛ˜4 &¢u_2zP¤ŠH!ÿ {nvî¤+/ðÇï9µ¨åâ„Ô»ï†)ÇWi –?øÀ-'¤!šl…÷35ÒÝhÿý÷wR“_~ùåÎÄø®¤³D@D ~ÅÏNgf#Àtj Úè+D@D@D ð…g“&MlI‰|›µclV‰k“{òÉùª" " "Þ}÷]üþûï4hŠ÷vˆ¡V­ZøòË/Á™›õêÕK ^j„ˆ€ˆ@jØ´ièl{öÙg£X±bžU²iSÏŠRA" " " )FÀLxÑ¢Ed¥øXܽ;pçÀa‡Eî˾öÌ3ÀÇ4WäXòAí=‚b&¦P+[ÖuL¤‹SŠ5 ¥J•²sÎEFíÚµ3q“©›" "PH¼ ,¤F販A€éÔ¥ÆýP-D@D@¼!@?¦paJ—‚ÂÞ¹bÃàÞ{ :RûE@D@D =<ùä“(S¦ zöìéKƒ(ö•ØÈ´*TD@D Œ]víÚ…¶mÛ†mmqóf`ÎŽÆvžŽHm[·÷Ýç¦I½øâ½u5cD<ñ„›êŒB£’%SNêÔÙ{L~K º‚#ŠŽ˜2­wï½G?þ8°x1зï?xñÅx衇,µÚvœwÞy–²õQÔ­[wïÁZB$ ÁQ!ÂO·KSp´Ÿy׉¶'M7jˆ€ˆ@Zà,WF³fÍ l_óæîƒa·nªD@D@D ðþûßÿ:nW_}5*W®øö¨" " ™K€éÔñ ŽèppúéÀüù®èèàƒ3—¥Z." " éDÀ{qÑE€ ᬳ€pÁ‘ͽÁ7ÆßZŠŒn¾˜5 æ®YÇ—¿ùf† ë€ß~û Gu8á§M›6‘jMD@ ™@RGÿXË÷ß?ê&/_¾<âØO,Ye… "¶E³rî¹çFs˜ŽI€Àf›Â3ǦðtêÔ)Rtªˆ€ˆ€¤à¨9ÕDDýúîl”ÓnH Op*§Å ôyWˆ€ˆ€ˆ@€ PptÀXê“rŸäÒÆeË`éLºÜ? ±Q.´ID@D@JÀ2}ƒéÍž~¸öZïA£¢YÑž={0}útŒ?cÆŒÁÌ™3QÑl”(4êÕ«—çi̽oJÈDIÝqÇqs0`@\çJp¶˜NâÌÖÝ»w+ZLÔt°ˆ€ˆ@L›6Íy°ËžÎe˘•-ЧP©RZ¢:Š€ˆ€ˆ€wV¬X÷Þ{Ï^°¶Ã‘Gé]Á*ID@D@’L€}ÚBS õèÑ#æ+[nœ|2Ày³ÙS¡Ä\˜NH9Lê²t©›.ÍÊ­_¿Ÿ}ö>¶¼jŸ~ú)Ö®]ë\†B£k®¹>ø ªU«æÇ¥U¦ˆ€xB ©‚#Oj¬BR’Ó©1NP’ò”¼?ª”ˆ€ˆ@|víÚåÌ$9þøãQ¤H‘¬BÞ}¸é&ÀÆ¥Q¶,€ž:«L-ˆ€ˆ€ˆ@p¶åÎ;Átj 2xÓ©mÛtìè>Ž \rI)¨î" " " $@1ñAE²(Y2rÝ‹5fŽyàðÔSO‚M,¯Ú•W^iiZOÇ£‹×k|/X«  è/•¿|3¦t ŽJ—.£>:cÚ¬†Š€ˆ€¤?ùóçcëÖ­hÖ¬YVc9¨P¾|T§é  ¨ófe¯51{6ðÄÀmÚøÓ·/Y²§Ÿ~:ø³eË–xúé§Ñ¨Q£ &¯¦‹€¤ßGé,–öüôÓOf«{ø@ΠbõzÊdcŒ/¿üÒfËŒÀâÅ‹±zõjçlÚëU«V -Z´ÀùçŸïXÙÇX¬g‡oß¾ýõ—”¸žUA" "º2¥oã`ÿ=gΜy晩{CT3„ dRß–0¬ÿ0Ù¬Š/î –zU¦Êð–€ý[ªIzAŒ‚£%JओN*°¸;ÝjëÖ¹/&ë×/ð " "à1õoÍ â¨1þâ WdD¡Ñ¯¿îm|—.Àðá@É’{·y±ôÝwß9cËüñžyæôêÕË‹bU†ˆ€¤ Ž|ºÿý7nºé¦,±Q<—YfSfn¿ýv̘1#Çé{öìÁš5kÀ”uü´n݃¶Y5ÉŸVCw#†ŽrÜ&m´"I}oÜ÷ß6¢žNmÑ"àœs€ÿû?à’KÒêöª1" "‘2­oóâ&3eú6JËþ±\¹r^©2D@D@<&hÿ”1ÉD±ñyoÊ”)8þøãQ¶lÙ‹3­-®¹–‚ 8ûì×" " Pÿæ1Ð +nØ0àw`Bc7-êe—Ç ›Lã}ŠÔ?üÐIÙJ‰1cÆ C‡F\ÍÈE3¥¡Énç#<‚E|+g¬]»Ý»wÏUl”[‘´´ïܹ3x^²ƒÊ\F¦§ÏK6w]OD@’M “ú6²e:5FóæÍŸüÇ4HÖ¿Eõ *‹‰D@D È2­oóâ^Íš5 |T:5/hª ð‡@"ý[Æ$¥G×Í›7GN×»â àž{½²Îˆ‡€ú·x¨éœößÛݲÅu9zå O˜Ë¡÷b£¡C‡:p8I‡Á…î‚~Š€¤#9ùpW93æöTqÓ“õèÑË—/Ï*aŸ}öÁ 'œ€O<Mš4]…øPüæ›o:ÆÝéOå4—ÿívœý¢6LìÛ¼¸cœìÂàÈ š*CD@¼'Hÿ´1ÉDé1£mÛ¶‰¥óE@D@|& þÍgÀiVü¦M0çz rå½ kØpï²_KÌNs÷ÝwcàÀ¨W¯>ùä|ðÁ~]N劀ˆ@JH Á-Ù/^Œ9sæ`îܹX½z56YoÀ&Œ}÷Ý*T°Ž¡24h`/ù;¨‹+–Ã+±Î’xßqÇá›b^~Ç<ý~üñǬó˜G|¸%mÚ´iÖ6.´hÑ^x!ºuë–%Nbnõwß}\pAı~®„Ž”RÍOÊ*[D@ @&öm¤ýûï¿;éBõfêÓ£~ý»º²ˆ€ˆ@â2µoKœœÙ™%K–t&ÃxQžÊðŽ@¢ý[ÐÆ$%GÁÇœÃÓh'Z¦Îðž€ú7s‰œ0j aLèüxï^”;¾×¾öÚkñÆoà_ÿúÆŽ‹ªU«æu¸¶‹€ˆ@Ú(Ô„ täyôÑGÍ®î$Ë{}¶£ú¤cgLÒU€)ÉøaJ>ò¡÷Þ{ïÅ9çœã<Þcþw)¥JP¹J±Ñ† œ*U«V-æª1í /¼qÞ€rˆBì¿ÿþxøá‡C«ÎOrJfÈá(™´u-H.LíÛH™‚ÚìbZ>°šö)¨yNî/†®&" &É}[¢·m§Må$ž–.]:Ñât¾ˆ€ˆ€‡íß‚8&™¾-–O…îñ­ZµBñâùÏÉå¼ÎgžIäj:WD@D ^êßâ%—™çÍŸ<ðÛo°÷ÎɽõÖ[8üðñQÇŽ÷Üeæï Z-™H PG¨P,tÚi§9âæ5¶nÝê8ùt6™*??üðC¬Ex~üˆ#œÁWÌÙ1wÝuWÌ×3f Ö¬Y“u-})ÆÊ/è|Ô¼yó¬C(ÂZ¶lYÖºß !ÁQö—²~_Wå‹€ˆ€øO Sû6’Í.8b÷¼r%,µ©ÿÜuÿdrß–(Õ3f8NÄJ§–(I/" ÞH´ â˜d"?ÿüsüóÏ?¦S³9±6 {Näj:WD@D ^êßâ%—çíØÙÎ#®º øê+àºë"÷ù±Æì=íÚµÃÅ_ì|¯x饗0zôhMÐñ¶ÊHYI}ñÅhß¾½#òŠ 6L!Ö·o_PˆT±`ÁÇ­)tíû￵jÕ ­Fýó+ö‚aѦM›°µ¼O<ñĈüqĺŸ+¡”já)gü¼žÊHLîÛH8»àˆîF Ëìª(LïÛ½mt#fHp”(I/" Þð¢ â˜d"é¦ÏàdÏüâ¹çܽ½zåw”ö‰€ˆ€øA@ý›Tƒ_æòåÀ 7‡ \}uÎö<ñ,KNÎí^nù믿À÷À 6t2ô\qÅX¸p!zôè"EŠxy)•%" )O ©‚£ & —=…*ùÑ)[¶,Ž:ê(sh‚hR“ÑVñµ×^Ãe—]†7æW´çû¶oߎ>}ú8êUΔo:tˆë:Ó¦MË:ÒÉ'ŸœµžßB¸ÃK¦àHGùÝí`Èô¾ß+6oÞ‘RmÖ,÷^Êá(˜¿Óªµˆ€dzßæÅoÀäÉ“™šL©¦H ^õoA“LäPp´ß~ûáˆ#ŽÈ·˜(:ÒÄ“|1i§ˆ€xN@ý›çHÓ¢@¾þ=õT`È`×.àÀ“߬>ú 4Àö%á°Ãs2ß¼øâ‹¨R¥Jò+£+Š€ˆ@ (ž¬:|ú駸馛¬° — ëÑI'„:uê nݺȞےjÑ+V`¹IWg›Åóa®[·.GIsçÎÅ¥—^ Ú,V®\9Ç~?6ôïß?ÿü³Sôþûï{ï½7®Ë°Œõë×gÛ¨Q£¨;(ªhK—. ~ cüôÓOYåø½ÉáÈoÒ*_D@’G Óû¶ 6`÷îÝ9Gœ bݳBD@D €2½oKô–1íÌ×_N8¥J•J´8/" "à/ú· ŽIÆ‹pÕªU˜7oºuëV`6Ô‹k®)ð0 " "à1õoMƒâøzù¢‹`NBÀcÁÞ9'·Q3gÎÄ­·Þ :ÿÒ4ãá‡Æ¿ÿýo/ž´WíÉm°®&" QHŠÃÑÚµkqçwæ*6jÚ´)Þyç<ùä“èÔ©Ž=öØb#¶…š|°#JºþúëÁ™•=ôã‚”½­‹-Âå—_žå8”}¿—ëR½ËDÞE‹ÅàÁƒQ®\¹¸.ñC¶dàTÆF%J”0%ï^)/ƒ7mÚíé G‡#¶½|ùò •£“E@D@Rƒ€ú67ïF¥J•²n SªtP¡BÖ&-ˆ€ˆ€„€ú¶ÄoÔwß}‡mÛ¶)Zâ(U‚ˆ€xFÀ«þ-¨c’ñ‚Œ6Z¼åë<ĨKŒ_ºž}ÛmÀ'Ÿ–½,©b£eË–9ÙuøþzÊ”)vý+°xñbÜrË-¥ë/›Ú%"¤È.©òܺukDÅjÕª…»îº íÚµ‹ØíJÉ’%ѱcGç3uêTÜqÇŽRè|æÊ|ùå—-g. ;·£µMD@R“À'6Çg%ÆÒ¥KsuˆMÍš{[«tíÛØWqòGx߯TßñN€)ˆ:gq2N9唂Õ~ðÀ矎/¾øÂ)ŸNètªÉÔð²K•1É-[¶€.÷á}[¯^½rœšÈ}ÿì³ÏœÓÛ´i“H1:WD@‹:€iμ¦Y¡z5ô„)ÍxýDb#“†E¬‚£ìâ"~1=ˆV 1_¾RÐEQ£ ;@þ¡ˆµ®1VI‡‹€ˆ€oø7/ô÷.tº¶eb¤s߯¾ŒŸð{ŸP6»àÈÜö±s'иq&þf¨Í" A%ÀçƒÐß½L}¸O÷¾­X±bY÷˜¿§~~‡¡Ë0mã›5kÔÿª·ˆ@ ¨2Ô·mß¾¿ýö[´*ö&xÝ¿¥Ê˜$û1>§…î1É4.+=ºÂ7Ι4~ìå0U »<¾ØTˆ€ˆ€ŸÂû6þ}÷úu÷ºìtíßȉY\ø<ê{ªV­ê5¾´-Ï2{;éMëÖÞ{6Ôߦò{ÑÓO?miÛÆ l<¸±#4:õÔSý½°J4"Pºt鬿wÔpüJ‘¾|=:‚¿,½øâ‹ž‰B…W®\Ï=÷Î<óLÐÅ€A‡ ŠŽ :̳ŸC‡ÅôéÓòøŸæ‘GIø‹`ö‡ûXÝ5²¯ž_tø¥§gÏžQñâË òWˆ€ˆ@ ðïWøß;¦øä LŒtîÛxŸ«T©q¯ó»ÇÙG¸ï>À&²(D@D 0N8áðÃà‹µ>ú(0u÷ª¢éÜ·1¥5?áßc¼â–½>[sæ5ÝòrÌ~ŽÖE@DÀLeÁƒ)-˜â"Ãëþ-UÆ$Ë”)ã<ûٷѱÏ{;wÎóWgùr€i[øü'ÁQž˜´CDÀ#œÌÎcæÌ™ÎÇ£¢WLºöo¼|çÆ1g?û¸ÀÝð(*LmùyçÁØ~T«ÅIqÂïO<ñžzê)ÇMøàƒvDG—^z©¯“{⬮N”&P¯^=ðÃX²d B£)]iU.n¾Z8ìÙ³Ÿ›ÕqxtíÚõë×ßäÙ27ýû÷(oâĉæH`–]›¨n SÃÕ¥´6ÁÈþp«k›Ãƒ6ÄÉv±Ö5õÒ5D@D@¢' ¾-’UvÁQ:Àý÷fª¨õmÞÝ(Š˜âFéÔ¼cª’D@D ^~ôoA“Œ‡!]ò:uÊóô^,Û:®½6ÏC´CD@DÀcêß<šÅmÝ œ}6`™ñÚk0až?Z·nøž·Ž 3­+³ôŒ1‹-B·nÝ$6ò»JH#¾ Ž˜4ä6Dfœ ɼÛ~ÆI'ªNCA÷iÓ¦…VþIS©íâS§EÛ¶mqÁ$\. ÈžÚ%V‡ Z‡GvÇ£ð}^-STÆ´r•*UòªH•#" "dêÛrÏ.8Êy„¶ˆ€ˆ€¤2õmÞÞºA0$8ò–«JX øÕ¿qL2Vv<žã¹cÆŒA£F²f\g/‡Ã«Ã†œ~zö½Zðƒ€ú7?¨¿LKD€Ù³~ý€sÎñ§=ï¼óŽõùaàÀNfž7Þx ,p„F™œÞÐÚ*UD ] ø*8 ¥ Ákf‰¯“!‚9ãŒ3B—t~Nž<9b=‘•û,ŸÊrúêZT3ï¾¾}û&R\Ĺ,/<6oÞ¾Zà2gœ†G2D@œżºr8 '¯eõm9ï—G9™h‹ˆ€‰€ú6où,ß´iSo Vi" " 1ð« â˜dLàþw0Óð­5›„üÜÞXµ ¸új˜£AÀ¸qã²N4h*W®œµžèBÕªU#ŠˆUp´cÇŽˆó½¬[DÁa+tb$CÜvY-Š€ˆ€xD@}[î ÃGfæg.„¹§­" " ©G@}›·÷d«ùØO:íÛ·G±bż-\¥‰€ˆ€DMÀÏþ-ˆc’Qƒ ;ð½÷ÞsÖ:wî¶5rñÙgR¥€+®ˆÜ®5¨ó‡k:”ÊÇÏK/õ¾%t<¼ñÆñÌ3Ï Aƒøøãw#ﯤE@D 3ø*8Z¿~}ÅÚµkG¬ûµ’}Vg®xƒÎ*¦qãÆØ¾};&L˜µ-ûÂÏ?ÿ±‰ëáÇS5{ÜqÇe“èÃ}xú:š ÁQè…¬޲n£D@D PÔ·å~»Ø¿1­ûjÓ;³[GŽN;-÷ãµUD@D u¨oóö^|ýõ×`ún¥Só–«JX øÙ¿qL2V~thßì‹?üpy䑹žþí·€™ ¡kW Û¼Ð\×FÄ ¨Kœ¡JˆžÀ¶mÛW£±cÇ¢M›6 9™y¢¯¡ŽàHªà(ûë_¸ªW¯Qtv§¥ˆ1¬„;Ͷġ½{÷Žál8*Y*eCѰaCŒ5*´j²‘G+W®ÌÚÍÂï¿ÿžus‹ò%©ßr8’àÈoÒ*_D@ü! ¾-w®ѽ¯¨yèÏš³ÝjÔÈýXmH-êÛ¼½“&Mr ”àÈ[®*MD@b%àgÿÄ1ÉXù}óÍ7àXëyXÑĽK tiàÎ;c-]Ç‹€ˆ€ÄK@ý[¼äÒï¼1c€7ÞpÓ¨ÑmÐëX½z5Î:ë,L›6 ݺuðaÃP¢D ¯/£òD@D ãøš‰š@áA§€dÄÎ;#.³iÓ¦ˆõT]É.”š9sfÔUå—²pR“&Mg†¨ ˆóÀÑRªÅ P§‰€ˆ@šb߯[qÙ4Æöð ›Ë5…ˆ€ˆ@¦jßÏ}£³Ñ[o½¶™.¿ ô$ }[(Z§Nr½‰Ô!-] <ù¤žýr¤" "@™Ð¿ð¶äZ対‚9¹Nƒ«VåzHB.\ˆã?ÞÝ{ï½1b„ÄF ÕÉ" "°—€¯GUªTÙ{%[Êžb-b§‡+6lˆ(Í+÷¦„ÛºukDÙù­Pøžæ¬\¹r®CÙS¿vØaÎ@nèœüѹ^Ù²e󻌳â$æ ­“r8Je]CD@ü# ¾-w¶…fù¾ô`]2J–ÌýXmH-êÛ¼»/¿ü2~ýõW 4()Z¼«¹Jô#àgÿÄ1ÉXï0G‡r8I3{<ó 0z´û¢³gÏì{µ." "à'õo~Ò NÙÏ?ïNø?¨SÇÛzó™–ïLך…=Ÿq/¿üro/ ÒD@D à ø*8Ê®Oùå'÷ì‚£ì§x¯=nܸ˜N]²d :tèuN÷îÝqýõ×g­g_`Ú–3Ï<Óéð¸¹Å¿þúk´k×.û¡9Ö?ÿüóˆmɲ» Žäp_+" "êÛr¿UÕ«WÏÙIý´M€Qˆ€ˆ€„€ú6onÔßÿþýûƒebM'îM TŠˆ€ˆ@8?û· ŽI†³)hyêÔ©X¶ln»í¶‡~ÿ=póÍÀ¡‡/¼c·6ˆ€ˆ€øL@ý›Ï€Rüðမ¡Ao+L#ŒÓN; «Ì6éí·ßFçν½€J€¯)Õ²;øP<“Œ˜1cFÄe¼EêÓÊ9çœQò Q<éRôóî»ïfW·n]tÐAYë~.„Rªyå"åg]U¶ˆ€ˆ@áZß¶gÏlÞ¼ÓÎï‹®*" A ´¾-¦/¾ø¢órööÛoG4®»ñ\C爀ˆ€¤tîÛFå€Îí%ã~ûÁ&{Â^Bå˧ÎýPMD@D@¼!Îý›7„R£”âfáµØhûöí8묳°hÑ"K™ú¤ÄF©q«U 4$à«à(ä âöí·ßbË–-¡Uß~~ñÅeyä‘멼røá‡g9*°žsæÌÁo¼‘g•ÉóÚk¯Å¶mÛ²Ž¹à‚ ²–ý^Ñ߄U¾ˆ€Ÿ@Ðú6Šié2(ÁQð÷Ôð‹@Ðú¶X9üõ×_0`jÖ¬‰^½zÅzºŽ tîÛ˜NíÀD³fÍrÜ™êÕ?š6ͱKD@D@Ò€@:÷oA½=¿ý\s `¦º¾Å®]»pá…‚ï¥ï¼óN¹öúFZ‹€ˆüu8:Þò”›òÏ?ÿày&âô1~ùå|O/ܰhÕªUØZê/^uÕU•ìÛ·/Fމ;wFlgŠºË.» 3gÎÌÚ~¨ùÿr[²BGÉ"­ëˆ€ˆ@° ©o ¥f¥àhÚ4àǃÍ^µð‡@ú¶X ð¹}ÅŠ¸ãŽ;PºtéXO×ñ" " %Ž}ljþùgtêÔ) wEÕH”@:öo‰2)¬ó_{ hÔö®øøcÿjq)šÆŽ‹nݺ9“iü»’J0“:ÿ¢dÉ’hÓ¦ >øàƒ¬‹¼òÊ+ ÏµÍË…‚ÊÕPT­ZÕløûìƒéÓ§ã7ʀâ¸y>ðÀ(Q¢DØVépÄèR¥Jù{!•." "hAêÛBbZ Ž®¾X»–R&ÐøUy©o‹¥ù´4hj×®mý u„ Œ!Ž}Ýá‚#3µ5GÛŒ¹­j¨ˆ€d!uË`Â×É6¸wI5ˆ•@:õo±¶½0Žÿýw O NXJ3`¿ý\W£wÞñGl´gÏôïß½zõ¡‡Š>ú¨Àw«…ÁE×t$içý÷ß©S§‚â”PÌ™3´1ä¾3Î8#n¢‰':Î>óiM-n¼ñF”+W.ÛÖä­²S[´hQÜ,Z´(z÷î=zX.ÓAfœiÊA`ÚÛ3-]k{;zÔQGÅ}DOä=­[·n¢Åè|€HǾͺk\r‰ké;y2P¥Êév7ú`éR{"¶àÈÁ D@D m ¤cßïÍzæ™g°fÍÐåHi³ã¥¨óD@D 5$Ò¿aL2Ê¡tj;wÎ:üÓOáL,éØ1k“D@D@D@ý[j߬¥Ka“XóˆÈšÈy÷Ý0ñ/`¯<}‰Mft™Ùޱ™¤7v~V«VÍ—k©Pœ’"8ªR¥ úõë €víÚ•U v}LâúÔSOÙ‹¾Kpš%ì¬Q£FÖþ¼þþûo'uC,Xëa3]xá…¹î ÚÆ2eÊ€ÆáǩҦi¢7±©r;T TêÛ¨Û¥•þ#À^°=VÌ8>êXý¨=§*D@D@D @©Ô·XÙ\Øb–ƒ¶¨uœI/¹¢M" " F è}S©ð…cË–-³îܹçß|vXÖ&-ˆ€ˆ€d ÷o©z»V­r]äé&xüñ…F:ø[[¾#>×:wš?tíÚ/¼ðJ—.íïEUºˆ€ˆ@¤ŽxÅSO=Õ™%IÑÑöíÛ#*±Ô$¯´ºã‡‚#*P™[»|ùò¨P¡‚©`ÿÂo¿ý–õYe½íñòŠ“O>ŒÛ5)¯rµ=’…_¼—•*UŠÜ¡5 š5aéY-[ú™èèwû>òþõ¯RfÃÀƨÊ" " "#!C†`ݺufw?%K–Œñl." " ©E`Ù²eŽ[ü•W^‰bÅ8©Ä º+ð%¨BD@D@DÀ[[?žc«@ûöÞ–[it2¼üòË÷”O>ù$n¸á†ÜÓ6Ÿ $MpÄvPôꫯâꫯƆ rmÚêÕ«ñÙgŸåº/šçœs|ðA/žÔ¦ESµ´;†îFŒŠ+¦]ÛÔ Ì%°iÓ:kü«øüó'­+•¹ ÔrŒ!°uëVsú{tºwïž1íVCE@D@Ò—ÀÔ©SÆ…»¥okÕ2H -Zø_Ý»w›{ÒÝ4hcbñÑGE¸ú_]AD@D œ€O3Ã/¹Ü¨Q#S¸ŽG—.],_§w—§3­òh¿Ï>ûD^Tk¾øóÏ?råpä ^*" "PH(¨-R¤ˆã²XHUÐeE@D@D ©¾±Ü2œtÝuסD‰I½¶.&" " ~˜6mšSl³fÍü(^eŠ€ˆ€ˆ€åË—£uëÖŽØè_ÿúfΜ)±Q!Ü]RD@ x§ø /µ€e:âÜwß}3f Î?ÿ|”-[¶€3òÞ]¿~}ôíÛŸ~ú©ã ”÷‘Úã59yMT剀ˆ€¤öoü®â¥0:Ú¥:ˆ€ˆ€ˆ@^¾ÿþ{gWóæÍó:DÛE@D P,Xv°ß~€™šãÑG ¥ºh PpT¾|yp옱gððÃÀ¢ElŒª," " )JÀÌr1o^r*7zôh4nÜS¦LÁõ×_ïü¬]»vr.®«ˆ€ˆ€äI PóŽf#ýúõs¬ï&Mš„3fà‡~ÀÂ… ñÏ?ÿäZé*Uª I“&8úè£qÜqÇŽIŠÂ!r8RJµÂá¯«Š€ˆ€øC€‚£Ê•+ûS¸J$@ÁÝýø¬­T!ðã°ìÀúõ@ƒ0Çt€fÛ7ßœ*5T=R•ÀSqœù˜cŽÉšHòÝwÀm·ö¸‡Rµæª—ˆ€ˆ€‹ûÖ—^Ì4M›úS÷mÛ¶áßÿþ7† †jÕªaܸqèСƒ?S©" " 1(TÁQ¨¶¥K—v:‡PÁü›[¶lÁÆŸ%K–tœ*T¨ {÷´ør8RJµ¸ª‚ˆ€ˆ€gØ¿U­ZÕ³òTˆ€ˆ€¤: Ž9äÇ "Õëªú‰€d%K€SNÖ­Þy8÷\௿€µk3£ýjeb~4µÇ•ÃÓ©}ð[fÇŽ‰•­³E@D@D@\&Ï>ë~g3_bÖ¬Y¸øâ‹£ŠvíÚá•W^AÍš5}¹– ˆ@J޲W)L(.âG‘ºäp”º÷F5ˆŸGõêÕ‹¿)" " "°Õ<ð/^ŒN:¨Öªªˆ@ lÞ ¼ÿ>pðÁ@‹y·àçŸ]g£Õ«7ßtÅF<ºT)`ÿýó>O{D D€éÔÙG̺ҬYè(ýH„@±bÀGÇÃs))÷s‡ ‚[n¹ÅÙùÈ# OŸ>Ž3oîGk«ˆ€ˆ@aHIÁQ¢0 ä8#…ÊaÚ6…÷B‚#9yÏV%Š€ˆ€º,n¶7!êÛ ‡¿®*" "|³gÏû¿¦~ùß'¿Iº¢ˆ@!°?+˜<èÜ9R ´cЭ›[¹æÍ‰rå"+ûë¯î,ùß^{ 8ÿüÈýZhd-X,ZôêåÏ Ñhê¤cD@D@D Ý0õí¼yþô­÷Üsú÷ïúõëã7ÞÐójºýò¨=" iE -G˜Gn(Ýï–GþüΆW¬XÑŸ ¨TH2ŠiùÒU‚£$ƒ×åD@D@ Ó©1ŽöË¿ÐZ¦ ‹€$‹€}…SjŒ|ò °r¥{åˆr+ h@IDATU«Œí»tiN±Ñ²e®ØhùrXº ࢋ’Õ]'ÝPpÄ4ÙuëÖuš¦tjév‡ÕT!à‡³ÑM7Ý„'žxÇwœ}·üz™*w[õÜ ¤¥à(÷¦j«×äpä5Q•'" "PØBbZ Ž ûNèú" " É" ÁQ²Hë:"^Ö®uˆ( úö[`×.·}G\r Юì%QÎ6Ÿ{îÞiá{7mrÅF"½ü2еkø^-‹@ôvî܉Y³f¡U«VY'QpÄù’a›²öiAD@D@D z6OE‹F|,Grè5×\ƒaÆáä“OƸqãÌ 3›f,êX¤à()˜Óó"|)[ÄäË*THϪU" " G`Æ N›%8ʸ[¯‹€ˆ@Æ à¨víÚ¨^½zÆ2PÃE@¢#ÀLŸ}¼ôðá‡ÀßåËgŸ œ~:о=@W£x‚e¯^ ¼ðн{<%èp Ì;Û·oG³fÍœ +Vfx„.]€%DID@D@D ^[·'\wУG¼¥ä~Þ.S¯w³Ü»¯¿þº}§lo®˜£QºtéÜÖV”" ÁQJÝŽ`U†Gû©™}’3 ‡j+" "äp”7QMˆšÀ?ÿüƒyóæ¡mÛ¶QŸ£E@2—À™gºiÓ8 Ô¦ på•@ÇŽ@É’‰3¡piÍØ‹¥ÄËR ™M€éÔ!Áј1Àž=îïjf“QëE@D@D 1W\Ìœ üo¾fb……ý·©Ø/¾øbGdÔѾ\¾ýöÛöýÒƒ/˜a×Тˆ€ˆ€$8òmÚ—Ì—²Êšö·Y Œ" ÁQFÝn5VD@2žÀüùóñ×_áè£Îx "P0¦J£i g´×©Sðñ±Q¬˜ÄF±ðÒ±yÈ.8b:µR¥\®¼ÏÒü<öLtî ÜrK~GƶoË–-¸à‚ 0~üxs#ì‚W^yÅ‹ëÕulu´ˆ€.ýÕ.\þ¾:Ž$8 ô-TåE@D@²à(­Š€ˆ€¤5¦ScHp”Ö·YÏPp¤T'0uêTKíwjÔ¨ºÄ矧”+—ê5WýD@D@D 5 L™Ü~;pä‘ÀðáÞÕñ¿ÿý/.½ôR,Y²Äœ3¯ÄóÏ?¯Œ*ÞáUI" "4Ê…•4Ôéw! Ž*Uª”~ S‹D@D@2–€G{ëÕpÈHeämW£E *Û¶o½Õ¡:HR†ÀöíÛT¡¡tj}XöP'õ_ÊTRX±æ@”)Kyæ€wçθï¾ûТE ,_¾O>ù$† &±Q€~/TU' ‡£pZމ€ŽbÂ¥ƒE@D@@@‚£Ü$UQD@DÀ3ѵö ƒò¬L$"zöÞx(_èÐ!=Ú¤V¤?ök|‰™Ñ:uÎ:+ýÛ®Š€ˆ€ˆ€×þþÛM¡¶v-ðÞ{@ýú‰_áÇD×®]Á¨tÚ}ýõ×qÄG$^°J(4r8*4ôÁ¾ðæÍ›±k×.9û6ªö" " ÙHp” ˆVE@D@Ò–Àž={0{öl¥SKÛ;¬†e;€?þÈÙbÎF¿â `äHà·ßrîÏkËsϹb£sÏÎ8#¯£´]R_^2B‚£“NFªWO½ºªF" " "ênº °¬g¸ã€ß çìK&EF3fÌÀwÞ‰ï¾ûNb£D¡ê|H¥ÀMbB/d9V!" " éB€ý[‘"EP¡B…ti’Ú!" " ¹øé§Ÿ°iÓ& Žr¥£"zlÎWŽøà eK`ß}#w›É‹¥–^~¸ì2 Nààƒ=€?vïŽ<>|­cG [7à•W`ßÃ÷hYR›G|ž;öØcS»¢ªˆ€ˆ€¤8‰gŸÚ´úõK¼²—^z)zõê…5j`Ê”)0`J”(‘xÁ*AD@D Ð HpTè· ˜`:5F¥J•‚ÙÕZD@D@r!@ÁÅ´E‹ê+R.x´ID@D 0í ƒ3L" ©GÀLÈ0y2н»ëÎÒ¤IÎ:.^ üðж-иqäþâÅ]ÁÑŠ°TÀUWÁ^êÇ»)ÒêÖxX¾<ò<®ÕªŒá¦S˹W[D u PptØa‡™ÏTx ¸Ð=óšk€²e—^‚“ÆULÖIýL±ôÚk¯áì³Ïv\v[´h‘µO " " Á'`7|jA|äp7%" "ÚØ¿IL›Ú÷Hµð†ÀÌ™3‚$8ò†§J¯üø#pÏ=A­[».CœxbÎ+ôîí¦Rûè#à’Krîç–Úµ.]€çŸ-–.î»  éþûÝëœu0v,›‹ËPˆ@lܸ‹M…J§¶}{j­:Š€ˆ€ˆ@ê (}É o_×%3‘~øá‡¸÷Þ{ÑÄÔóo¾ù&Ê—/ŸHq:WD@D  Hp”‚7%U 9)¥Zî–ê(" "- Ž*W®íá:ND@D@K€G¥K—Æá‡Ø6¨â"(ü™3xâ àøãúõþýÝ–Ý}7°p!0c0thÎÖÚá˜gœ3µ…FQdtÆÀøñÀyçkÖ伆¶ˆ@PLŸ>Ý„t{ÁÑêÕteßû)(mP=E@D@D œvpá…À 7$V›y–ß·k×®¨V­ÆŒƒ2eÊ$V ÎHIf°¬Ø „Žä;;!" "ºؿիW/u+¨š‰€ˆ€ˆ€GfÍš…† ¢X±b•¨bD@b!°lpóÍÀçŸk׺g–+ç¦P»ì2 U+ H‘XJŒíXþ×?óL÷ôk_}å¦R‹­-©C€éÔt8š0øë/àÀS§~ª‰ˆ€ˆ€…¿‡ò“HlذçœsvX~¶ÌŽó@uʉàÔ¹" "Ò$8JéÛ“º•“ÃQêÞÕLD@D >»wïÆ¦M›”R->|:KD@D @~ÿýw¬6û‡Ž;¨Öªª—S•ÙWM”(±· +ÂfzĮȈéÓN: 6ó{ï1ÉZÚo?w{²®§ëˆ€(8*^¼¸“²eøp÷ §žêÇ•T¦ˆ€ˆ€ˆ@~vÙ—ß .¸?ýô“¥õ}-[¶Ìïpí8 Ž~ «ú!Á‘Ž ëèº" " ^`ßF ~õm^“Uy" " ©F€éÔM›6Mµª©>"V¾üxí5àƒ€ÁƒnÝö6¯|y`ýz€®F Ä PpÔ A']èsÏ×]Ô¬™x¹*AD@D@D 6}úôÁĉ­/¾W]uUl'ëhÀð]pÔ¡C¬\¹2©`¶nÝšÔëeâÅB)Õ*rJžBD@D@Ò€@¨o“à( n¦š " "/àèè£Î÷8툞€e¢B…Èãß|xáਣ€R¥"÷qMb£œL´Eâ!@×¾e–§°}ûöÎéLظq<%éÈL_ s n¿=±ö¿üòËxê©§,%[+<ñĉ¦³E@D@AÀwÁÑöíÛ!P ~bª¤ŽbÂ¥ƒE@D@@@‚£Ü$UQD@DÀ1íLCærRˆ€ÄL€éѾý?˜> i‹–,‰,ê–[€oê×Ü®5o Ð݈ѬY3o Vi" " "Þ{xë- hÑÄûÉ'ŸàÚk¯ÅA„Q£F9Ïœ‰•¨³E@D@‚@ÀwÁQ ¨Ž±àKÙ’%K:6űŸ­3D@D@D õlذÁ©”ŽRïÞ¨F" " Þ àèðÃÇ>ûìãmÁ*MÒ˜ÀÆÀ§ŸãÆì¦CcsË”‰÷†Yv^)²ÂÁï]Ö’ˆ€$8ò­JH•+?[)6êØ±£9~VÀرcQ¥J•ø Ó™" " " ÁQ nWêT–Gz!›:÷C5Hœ€Žg¨D@D@RŸŸå~ùå\z饩_YÕP ™Œ8Ûû¥—€/¿þùÇ­PÓ¦Àu×gå ˜¾I!"Px(8*]º4=´z8÷\à°Ã ¯>º²ˆ€ˆ€‰ÀĉÀ¼y@õêñÕ:$6*o–Ÿ“&M²t–OX!" "1|qsóæÍ4SÊ—²+VÌ”æª" " @@‚£ ¸Éj¢ˆ€ˆfÍšåP8šv, < ,^ ›¥ ÌŸ2íÛgž tèì·_ž§i‡ˆ@! à¨I“&øæ›â¸ã€"@¦4Tˆ€ˆ€ˆ€L€¯úN<±àãr;"\l4Ñ”KJÛ%mô&à»àèòË/Oo‚Ú:ΊÝO#lz÷ÕlHO¥ç}U«D@D@" 0C‚£H.Zì<ÐM‘v÷ÝÀÍ7Ã\ž³¡uT @×¾uëÖ¡K—.˜0Á­Q»v©P3ÕAD@D@Ò›@v±Q£FÒ»Ájˆ€ˆ@®|åzUm < Ž4høv¨" " "" ÁQˆ„~Š€ˆ€¤3 ŽÒùîªm‰ذ¨\yo ¥JsçE‹îݦ%Ô#@w#F³fÍððÃ@Íš€Þw¦Þ}RD@D@Ò‹Àøñã-…é¹`5:Il”^÷W­XhØ$Z:Ö!°sçNlÙ²E)Õôû " "V$8J«Û©Æˆ€ˆ€äA€‚£ƒ>ûî»oGh³dGZ¶¶ol»ÄF‘<´&©H ”*´nÝᇀSOMÅZªN" " "ZÌ ­Z_}{½&Mš$±QìØt†ˆ€¤- ŽÒöÖú×0º1*ÉOÜ?È*YD@D é(8*R¤*T¨ôkë‚" " " ;vìÀ‚ ”N-°uÀ¸ývàÖ[]'£M›SmUTDàV®\é,-\x€óSéÔô«!" " xþy`ÊÀcŠ f ÚµkW”.]ZÎF1‘ÓÁ" "¾|O©v«Ú0v(hÖ¶æm«,DÅŠÛU\D@D@²`ÿƾ­¨¦²gG£u4!0gÎìÚµK‚£4¹Ÿj†7ÌÄ'œŒljUÞ”©RD@’G`Íš5N:—)S,¢EÛ¶É»¶®$" " A$ð÷ßÀË/õêmÚÄÖ‚Þ½{ƒbß‘#G*Zlèt´ˆ€¤-ßG3fÌÀŠ+²nÛ¶-kY Á$ ‡£`Þ7ÕZD@D ɽ/FÚ+" "lL§Æ8ú裃ÝÕ^r!À´_ |ó ðßÿÂ&»Ý»çœ”ru¹œ0Ú_ûì“ënmHq«W¯F5ðŸÿÀ^|ºÿ÷S¼Êªžˆ€ˆ€*Q£€µk;½G_•Qvâ›o¾é¤S£Ë‘BD@D@HÀwÁQ¼˜‡Ž7fÞ«W/”,Y2k] …G@G…Ç^Wðû·*Uªøw•," " …L`öìÙN š4iRÈ5ÑåEÀ[^¼óÎÞ2kÕæÎÆw]‹ºt.¿8昽DŽ–ø’Eb£ ýà à¨jÕÖX²–â%xõWE@D@D Ùž{ÎýþKq~´ÁþöÚk¯EµjÕ0tèÐhOÓq" " @ eG¯½ö–/_žu ®¼òJ ޲hîBÈáH)Õ ÷>èê" " ޠ਽„" " "¦è>\¼xqÔ¢C!%°t)P·ndåÛµƒ½üN<Ñýx ;kÛ†–`óÙðÌ3î‡î'Ï> ”+Y†ÖD@‚I`­Y4T¬ØÚ©<ÿ(D@D@D@ò&@QþW_ݺ•+ç}\ö=W_}5Ö­[ºU¯^=ûn­‹€ˆ€d0”eð=Iù¦‡Ž”v&åo•*(" "%Ý»wcÓ¦MJ©%/&" "Lœ•ÊÁá"±øæ³©ªušر1 ™nÎ&¨eÊìmäWì]-Q€tÓMîgútWxd ðÃÀé§_:R?E@‚J€“"ÿ²œˆþÙÜq*kÙ2¨-Q½E@D@D 9ènÄ0³¢¨ãÕW_Ř1cpÉ%— S§NQŸ§E@D@2ƒ€G™qŸ=m¥Ž<Å©ÂD@D@R€û¶={öHp”÷BUðÀš5kP£F ÿ. ’EÀ'ÿüÜvP¬˜;›¤pÁQA—=öX€ŸG6n„ý?(è íök–+WŠ6m”1÷Lu(<[¶#GG w\tõ`&šn¸µkׯ!C¢;IG‰€ˆ€d Ž2êv{ÓØàHGÞðT)" " …O@î}…Tÿ ÐáHéCýç¬+ÄO`ûvà“O€òå¶m÷–ÃõñãÝ—#±ö–à.í³ Ù™h]‚L€ýš%„AÆ¿á¼ó rSTwðÀ믛7Çænt…Y‰n4Åþ›fªw‚¾ß"]@D@I h k­J*ÐKÙŠ+j=tqðŠ@¨oÓƒ³WDUŽˆ€ˆ@ªØnJŽ­[·Êá(ÕnŒêã˜88ÿ| jU˜h80'˜OŒÍÕ(g Ú""n\ÁÑï¸ûîïqõÕéÖ:µGD@D@¼%Àtj*]ºDWîСCñÙgŸ¡gÏž–’Ør+D@D@D r8ÊŠ6åO äp$ÁQþœ´WD@D 8$8 νRME@D@â#°jÕ*çÄêÕ«ÇW€Î 0¥Ã«¯O? ,Xµ)q-[º‚£sÏõøb*ND - ¸)Õ˜&±FZ¶O¯|û-0{6л7P¶lÁ¥.[¶ ·Þz+êÖ­ki‰-/±BD@D@ò ÁQ`´9o|)[ÞüÌ‹+–÷AÚ#" " "°aç¶r8 ÐMSUE@D@b" —²1áÒÁ>øñGà™g€#€M›,ReØË  W/Ø /¬¢E@ÒŽ€ëpHL›v·V ð˜À7߸ÿk®‰®àë®»[l†ÀèÑ£÷Ñ¥£D@D@2‘€G™x×l3ŽôB6Aˆ:]D@D ¥Èá(¥n‡*#" "àÐKY¹@øWEH`÷n`üx`ÈXZ`Ï qcw†õ%—¥KX„Ô·å@¢ " " "+›ovS©Õª•ëîˆ;—ØõSO=5bŸVD@D@D ; ޲ÑzøRVéÔ Ä¤D@D@D@‚£Ý,UUD@D .!‡#¹@Ä…O'%H`åJ cG·Îë¯wÓ§%X¬NÈpË—oA‘"ÿÁ‡VÄe—e8 5_D@D@ Øh“YÞpà ŽéÀÿ³wpRUgÿèÒD°¢€ (¨h좽£Fcר¯FMÞ×»&ÖhŒ1Ö¨DQlØ[ì%öö+ŠHD‘ÞËÿùÍÌݽs÷ÎììîÌî”ïóÙgïi÷”ï¹sÏ-Ï=çšk®©%G¢!@fqÔ™€f8Z#—+“:çÌ€ ¦!€ÁQÓp§T@h<ÌÑx¬)ÉlÖ,³NªI¬µ–Ùwší°ƒ™Ü |øöÛV>cÚpûöÛ|äF€ œsÎ9öÝwßÙ?ÿùO–,åp€ œ4Ï)‰ "À’j!8!@ ,`pTÝH# @ Ààˆ޲@"ªA^ÝL³uïnvÄ5³:äŒjR!h~X9±{ïÞ É…}!@åK`ÆŒÜÛöÖ[oÙ 7Ü`Ûo¿½}ôѹïHJ@¨hUt÷×½ñóæÍ³%K–°¤ZÝѱ 15oÞÜ:vìXĵ¤j€ ú–TëÖ­[ý3aOd!à«/ØÃ›­»®Ù/~‘%!Q€òD`Μ—là o°m¶ÉS†d@(#Ÿž4øÿÇ?joÔÒ¥Kíøã·–-[ÚÍ7ßìK–6«}'R@€œKªqÔ‰€f7’téÒ¥Nû‘€ PÌdpÔÉ×ýÑ@(Gšáh•UV±V­Z•cóhS#xóM³sÏ5»í6³uÖ©.xØ03}Aýv5\€@á,X°ÀæÍûضÜòmëÙ³på3 @ T \|±ÙÂ…¹} píµ×Ú‡~hçwžm°Á¥Údê @M@€·jM½”‹ –œéܹs)7ƒºC€Òh|Ø6 @(3šáhµÕV+³VÑœÆ$ðå—fh¶õÖf/¾hö 饷n±Q:|€@! 3÷±Th!)“7 ”*ùóÍô¡À®»&¯ß³µcÒ¤IvÁXß¾}íœsÎÉ–”8@€@ ÌpT Ù0ÃQ6:ÄA€@©ÁQ×®]KµúÔ€ P+Íp4pàÀZÓ‘Qn«f]dvË-f¾Ò‚í»¯Ùe—™õëM‰€@ãи&Á˜¶ñ˜S ”víÌ>ý49imµþŸÿù›ïJ7Ýt“µiÓ¦¶äÄC€Ò4ºÁÑsÏ=gݺuK«DœgÞ¼yiÁ=öX½º}õ4 É f8Ê F2 "# ñ­OŸ>EV+ª@ÈeË–ùRW3x)›œ“Ëøñf×]gvçf¾r‘m·Ù•Wšm»mÅ  ¡€@H5gl+â>¢j€ д´švm“Ü>ðÀöÄOØá‡nôF2@¨#F78ºúê«ëXÅdrMçW_ÁਾäjîÌpÄ’j5Ù@¥I`ùòå6{öl[e•UJ³Ô€ P -;³bÅ ^ÊÖ‰hóãÄì©§Ì®½Öì™g’D¶ÚÊìì³ÍöÞB€ЇÀøñ¾VŒÍ·ÿû[;ôÐâ©5 ” E‹ÙÿýßÿY§Nì/ùK©T›zB€@‘htƒ£"k?Õ©#`†£.]ºÔqO’C€Š“€Œiõ–±­8û‡ZA€@à ËÎtï޽ᙑCÙ˜<Ùl—]Ì>ÿܬ¥?-:ø`³ÓN3“Á@ Ø|ñ…¯ñhmܘ¶m±Uú@€šŒ€OlëDf-ZÔ^…k®¹Æ¾þúkÓD¹¬LS{ޤ€ J$мM›ëO€ŽêÏŽ=!@ 8 `L[œýB­ @ 4ÑdµÚæÓÏ_‘äT‚zô0ëØÑ쬳Ì_<˜±Q v#U†@Ř<9ùX{À Ž*¦Ói( ÔJà¸ãÌ 0›;7{ÒiÓ¦Ùe—]f}ûöµSN9%{bb!@Y0ÃQ8DÕ$1 DM6„@€@iÀà¨4ûZC€@î˜á(wV•œ²¹¿»ë­J&@Û!R"ðý÷IC£AƒÜR @ 1SéC%—B^yåì@Î9ç›3gŽÝ}÷ÝÖªU«ì‰‰… d!Ppƒ£|Ж/_ž¥ D•à¥lçÎK©ÚÔ€ ‘@0¶aL›€ Pâ˜á¨Ä;°@Õ¿í6³_ÿÚ¬-“ƒˆ0ÙB…$ðã24Za}úüñv!›AÞ€ ¼¸çW˜ýîwÙ³|ï½÷läÈ‘¶ÓN;Ùž{î™=1±€ ZüŽ Ã”Zz Ä¢5ÃQË–-måÚÌ£K¬]T€*—G•Û÷´€@¥`†£JééÜÚé2ÛG˜éëçI“Ì.¹$·ýH@ ˜Ì™ÓÍŸQN·•Vê^LÕ¢.€ &#pï½fk¬a6dHö*œ~úéÖ¬Y3ûë_ÿš=!±€ Üà(‡:”M’Å‹Û?þ˜PZ­µÖZÖ¢E‹¼¶oáÂ…6kÖ,ëÚµkÂð'¯™ç™^ÊbD–(’@(•0¶Í˜1#Ñ[ÌpT&-Í€ P JÛ¢˜á(J¤²ýÿ{ÒØèCÌÎ:«²YÐz”BoMýL2ÚW ®i;Nõ` Ž¢lðC('•6¾Õ·ïÞßì‹/’³i©äLrÿý÷ÛË/¿l'žx¢ 80S2Â!@9Àà(gTñ §OŸn<òˆ=þøãöÉ'Ÿ¤%Òº§={ö´Þ½{Ûî»ïn»ì²KZ|®žW^y%1½á—_~iÁ—©²>îÖ­› <Ø<ð@Ûl³ÍrÍ®Aé4Ã/d„!=JÛ˜á¨èI*@ Á*ml‹Ó}d»ví¬}ûöÑ(üHàŒ3ÌÖ[Ïì ƒ*°ñ4eF Ðã[1=“ wÝÌ™Ë|ɘ®þŒ2ýYl8 n@(]•:¾5¤Ç4»‘äàƒ“Û¸ÿ‹-²3üf@“ \|ñÅqIƒ Ô™GuFV½Ã“O>i矾͞=»:0äZ²d‰ÉHHúôÓO'ŒŽ”>ׂ¾ýö[;óÌ3íÝwß åšt®ð…Xõ•êƒ>˜ÐaÆٕW^i:t¨‘6Ÿz)»Új«å3Kò‚ ""P©c›ºƒÚ":©  <¨Ä±-ŠO÷ŽÜÇE©T†ßß)Ø7ߘõí[Ý^_%c£j¸ P² 9¾ã3ÉpG½÷ÞÏî]ÕǶyá`Ü€ P*y|«o÷ùëB»ï>³u×5Ûzë̹\sÍ5öõ×_ÛÕW_m«®ºjæ„Ä@€ê@ ËÄzuÈ¥“Ž9ÒN;í´ŒÆFqH4 Ò{ìa_}õU\tZ˜,¸<òÈXc£´„)ÏóÏ?op€i¿BŠf8ÊÕ`ªõ o@È?JÛ˜á(ÿÇ9B(•:¶Eùk†# Ž¢TJßÿñÇfwÝeæüC'³ ªÛ¤—£G›õëg¶×^fK—VÇá‚JŸ@!Ç·b}&îµ?œ“ðöè±$Œ€Jœ@¥oõí¾7Þ0›<9ùQ/Ž+Ó¦M³K/½Ô?Dèk§œrJl!@õ!À Gõ öÞ{ïÙUW]•¶§–7Ûn»ílÓM7µM6ÙÄô-° &Ø£>jo¾ùfUZÝ´k–£»ï¾Û´,ZœhZã>Ú¦L™R½ÒJ+Ù¶Ûn›(cРA&Ãå;ÚŸ Ι“¼Éž4i’}öÙvë­·fÌ»*Ãz8–-[–(‹ ê] 9JÛÔ-28jî‹›wêÔ©È{‰êA€@]TòØå¤ûÐ_üâÑ`ü%J@þøG³n0[¾<½]»š­½¶™O¸lãÇkG³ßýÎ|é¡ôtø Ò%PÈñ­XŸIF{ë³Ï'‚Ö[/þÙj4=~@(~Œoõï£\–SÓ{ɹsç&f7jÕªUý cO@€@„@QMœ8Ñô%fCe›m¶ihiûké²¥¡Ï×ö§y÷ÜsO/F7Ûl3;ðÀíþûï·sÏ=×ð%Ÿði‰´qãÆÙ>ûì“–oà3fŒ}ñÅ×4øßqǦüÂ2xð`Ÿý ;âˆ#ªŒ“´¶úرcmĈá¤yqÏš5+Ñf8Ê N2 PT*ulS'ÈàHÆF™ ‹ª£¨  äL ’Ƕ0$s‹/®q¿Nƒ»´ÈÈÈoûýƒ$³“O6ûñG3_‘=¡únInÿFÉN?Ýì¼ó’FG¥ÕBj d#PÈñ­XŸIFyø#ã„ôïß&…€J”ã[ý:.¸7X}ó âóл½Q£F%&5ØsÏ=ã @¨'&58’5í[o½e¯¿þºzê©Ö¡C‡´fÜyç‰|ÒëáùüóÏë±Wü.šEèý÷߯ŠìÞ½»išÇlÓÓk©3-£&£¡@þö·¿ÅéAð-·Ü$Kl5ÍaÔØ(H c'ͶtÈ!‡A¦‡…08Ò¬Jf8ªB€@Y¨ä±M¨±Œmeq(Ó@U*}l«áŽà#Ý»"åA@“2jÙ„ž=Í ¦Ë£M´È@!Ç·b~&¥³ÞzÚsÏÝcl°{4 ? ” Æ·úwÚ‹/šùjivüñ™ó¸ï¾û«²{ì±™@¨'æõܯA»MöÅDÏ8ã ÛrË-íÄO´»îºË§û®¹æv0#Pƒ ËóÎ<òHZŽ'œp‚õèÑ#-,ÎsÚi§™–E dêÔ©6cÆŒÀ[µÕÌG?üðC•§v²½öÚ«Êç1’XòñÇûþIcž¥«ÏÍ~ûí·ÛþûïŸçœÉ€š’@%mâŽÁQS}” @ 0*}l S î/³}$N»¸hòcÿ^©†ôê…±Q (@ r|+æg’Ñ®íÔé]ºØ?Ř6Ê? R$ÀøVÿ^Ó §ZFùàƒ3ç¡IÚ·oŸX‘%s*b @õ#ШGË–-³Ë/¿ÜvÝu×Ä’bòRÚ´icù^Ní³Ï>K«òÎ;ïœæÏ䑱Ñzë­—ÍK‘¯¾újZšáǧù3y¶Ó\ê!yâ‰'B¾ü8µÜÌQGe[l±E~2$@( Ññ¨’Æ6uGEqR @y%Péc[&3…i”Ž[K#l½µY¿~fþý’=üpéÔšB…#PÈñ­˜ŸIF‰2¶E‰à‡ PÚßê߇®YmÍgý‹ÏC+À¼áÓ£j%–•W^9>¡€ h4ƒ£yóæ%f3Ò²bõ54jÛ¶m­Mmݺµ|òÉv÷ÝwÛ;3Xî¬Öê`šæ&L‰–_éÖ­[à­u»îºë¦¥™"Ó㈼ýöÛU!Í|nô!C†Tù³9Â3)]! ޲•O ”.JÛ–ûÛ¼Ù³g³¤Zé¾Ô€@,JÛ¢@˜á(J¤4üÍýiMÿþfÇcöì³æ3—F½©% PX…ßJ除 Ž:tè`íÚµ+,pr‡ F!ÀøÖ0Ì­ZeÞ_³IŽ<òÈÄ–€ |h™ï 3åwúé§ÛK/½½êª«Z«l#bj¯§Ÿ~:áš8q¢úÜsÏùú¤ÕF@Zo\3l¾ùæ±e540\V]§¤ÿî»ïÒŠ ©M?ýôSUš7ÞØ´ŒY.²ÑF™ ²,XH>a„\v#  @ m­´±mΜ9Ö½{wŸŠ5Ž@(#Ü·Uwf0 c]5“bri&£[n1ûôÓšK§¥Þ Su©  ÐÄ 5¾•Ú3IÓê> ò ÀøV˜~Ô‡–wÝu—õòõ˜sÜ 05!W@(gbp4f̘Xc£vØÁFŒaC‡µ–-kVE3üDEI¥ÁRi2dºêª«ìÞ{ï­JªÙ”ßÿøÇª°|9n»í6[±bE"»º|E³páB‹N ¹AdŽÃ>ú(­šë¯¿~š?›G[묳ŽizDÉ’%K36tìØ1ÛnÄA€¬’Ç6-~¨Áá@åA ’ǶhG¼˜’izÿ믛ÏÐlöþûf=z˜]|±™_š €2(ÔøVJÏ$ï¼Ó샞´ 7¼0#'" @ ´0¾¦¿žõ©R5Â…^hqï[ S*¹B€@¥¨iå“gsçεË.»¬F®—\rIÂØ¨FD´æèE]d»ï¾»}öÙ,Sö¯ýËo<7´}öÙ§Ž9fO5Êžº:VFQ‹-ª ÐìFQc ðìFJعsçªô¹8ôÒ4,Ê/ZF8>“[FK~ø¡m¿ýö‰$+­´’Oáîs¸#€Ê€f„ O)+ƒM]Ñsj6½ªI•0¶}ýõצ¾Æ65^³$¶iÓ¦Š@åFàºë®³±cÇ&š¥ Ú·o_nMÌØžJÛ¦Nš0š mãÆ³UVY%‹fÐ9Ñð´Dx•€&i>óLó¯Íg{6;ë,³sÏ5ÿ6j5( %I@/$G¦¦ÿÒ,ç•öò¬Pã[±<“œ1c†Í›7/í¾M–ê#Ë@4©ûòåÝ­[7?"€Ê€€>Øÿûßÿžh‰žK†ß#•AórjB¹o‚ð¾eðæ›oÚSO=•`¢NþñäÄ'.ÑC™ýå/æy˜ —ÂìŽ;îH\+~øáñ … P :×ýùÏNä¾lÙ²Ä$)*Šl‹€@Á Ž´ Úüù󫚪—^z©í·ß~Uaùpl¹å–‰Áyß}÷õ›NŸ“ÜåbÿЍwúQ5*mÿ3Î8#Í/ϬY³ÒÂêjp5.ÒÃM•XWéÙ³§õë×Ï/VüjÅ¥yóæuÍ‚ô€J†@ÿœüN}"™’=öØÃê2ƒ]°_¥mKml[k­µ|æ€vã7VuUëÖ­«Ü8 ”#Ã;ÌöÜsÏDÓ^xá{õÕW˱™ykS©mݺu3-O¾Ž‰3˜Ö GJ[i/åóv`ä1#Æfnè_›?l3Ûu×ä2j}ûæ±²‚@™ÐóÄaÆ%ZùöÛoÛý÷ß_æ-nxórߊ噤Ʊ¶mÛ¦mk¬±F„O?Õmü™grú´H<€JÀ¯~õ+Ûb‹-5?~¼]ýõ%؊Ưr)o¢#£*s'žxb–>ôoˆŒmöŸÿ˜/1ŸËÌ™3M¤h)µú¼'ŒÏ•P@¹ø`»çž{Aú"FK­ýþ÷¿’4êV†O7Ýt“ýíoK+wï½÷¶vÚ)-LžèÍ}ÜÃâ;…¢é£_'…’fuj¶]ìp’‘€@™ÑIø|§—qZfîÜRÛÔÏѾÎÜJb ”ÍhÌjóÉ'Ÿ0«[†n-Õ±MËjkæ¢ðuL\5Ñ–%Gš–€ÛEØñÇk ³Þ½“³ùã¨#.]º˜T¢×|D`]Æ·by&Ù¢E‹Äýx¶±í”S¾ñ¶µÖš¹ñÄ@(!ú<ø˜üçŸö0™Á-[÷•âø¦öè›Þáeã²µ;ç¯>í±ÇÌg4Ÿp!SíÖ»QÍt|ÔQGUâ‚ ÐH´B•T¢Žôü )_ºæûï¿OLÆWè©ûN=õÔ´¥Èdð¤ Æ–Ï>û,±d\ÔØH3«¹Òc$zs_׎:tè–«–B @ù"ÀØ–/’ä@ÅB Æ6ÍpÔ=Óg¯ÅÒe\9sÌü1…m½µ™ÛýÙ9ç$·•q§Ó4ºŽo¥ôLrÅŠïð«ÓÁqF 46rßêÂRK1¿þºÙWdÞKË©éeÿþûïŸ91€ <(¨9Ùút/$›nº© 80’§ŒtöÙgŸªõܧM›æÓ þǶÝvÛü“ãlŸ]ëíj}qYì…e·ÝvK,'§©ã$:Å}]¿ÒÒú¾a‰ÎxŽÃ @È•c[®¤H@¥B Rƶ ˜>Da†£¦92§L1Ûf3m}6q»ùf³ 7lšºP* Pê;¾•Ò3IÒJ0¦­ŒcšVBJßêÚÓƒeÞãÓO?µ·Þz+1»Q{Y'!€ (¨Á‘¦nK°m8¬î>}ú¤eûÎ;ïÜàHÆEcÆŒI,Ÿ¦i/âe Î<óÌ„!T8<êîÖ­[ZÐ} YY´Hk˜WK0Åtu.@€@îÛrgEJ@( •6¶/e18jšãsíµ“3í¼³Ù±Çšùʽ ‚hèøVJÏ$Û r‘) ¢$PIã[>;`äÈ‘‰ìXN-ŸTÉ €2(¨ÁQp¾Æk΂n{÷î–Ôð)-2MãxÆgØçŸž–›¾:øàƒí÷¿ÿ}Õ¼i "žUW]5-¤®GZ5,2tB @õ!ÀØVjì@ÅL Ƕà^˜Y dêvüÃͶÚ*½¬±cÓýø ä›@>Æ·Ry&9}ºÙ§ŸjFùVÌÞ—ï‰ü Jßò‰^FZwÝu—­·Þz>˪O³Š@€ L  GÁÃÍ  k®¹fà,èViX¢†OḆºGe—_~¹E—3ÛÆçM?묳¬ÿþ9ÑЛû(o ŽrFOB@`l ÁÀ @eA RǶà^˜Ž wk‚ãK.1û׿̟ ˜Mj¶òÊ…+œ!„ äk|+•g’÷Ücvà §:‚‡XR-| à† Pf*m|˵ûV¬0»è"³40 ~¯§Ÿ~Ú¾ÿþ{»øâ‹}†U¦X§D( ä“@A ŽæÎ›V׺.ñuâ‰'&f 2éÚµkà̺íܹ³µhÑÂdÉ+™®Ï_ò,j›–I{î¹çÒrîÕ«—}öÙ6dÈ´ð\<Ñ›{]ÔE¦êÉfJZ¶l™Ó¬JAz¶€ Æ6Ž@(7•>¶GÌpT¸#{¥•Ì´b&t>þx³æÍ W9Cä{|+•g’_$вå7V×çÌ;¶€ P¼*u|˵G^z)ip¤ÙU}„XÑrj24:âˆ#bã „ ä›@A Ž¢3ì̘1£Nõ×W˜õùSK‘ÆF*pÑ¢Eu*7—Äš½(ll$Ÿ“O>ÙŽ9ækݺu.YÔH}üÞ{ïÕH“)@Ë©… ” „õr&X„C€@,ƶX,B€@ ¨ô±-˜·>÷Õ%ÜíZõ¶mÍtëÞ³g£Ka€@…È÷øV*Ï$'N4Þ¹Äg7ò)å@(;•:¾åÚ‘·ßžLyÔQñ{èì#¡€ <(¨ÁQtF¢°ALžÛ‘–ÝO?ý”æÏ÷/wÞy§=ûì³Ue(ÿ›nºÉdäÓYýõÓ…¿øâ ›7ožµoß¾Öleœ6²>|x­û€ `l H°… r!ÀØfÆ Gù=š?øÀì–[Ìþñ½ð®Îc£j¸ Â(ÄøV*Ï$epÔ²å[}õî…M € Ш*y|ËôìÙf<`¶ÝvfýúÅïqÇw$&`ÐÄ @ ±t²ï54§xH^y啯pÎO>ù$-ó¨áSZd=“&M²+¯¼²j¯¶þ9ã-þı¡ÆFʰ¹Ï½¾Ç{Tå½|ùr{íµ×ªüÙ/¾øbZôСCÓüx @™0¶e"C8 ”*ƶdϳDg®(Õ~mªzkÉ_9ݶØÂìÖ[ÍÞ~»©jB¹€@¥(ÔøV*Ï$µ¤ÚòålVú±@û!”JßréË{ï5›?ßìè£ãS¯X±"11‚îýößÿøD„B€ @  GƒN«ò«¯¾j³e†[`yþùçÓJèß¿š¿!ž‡~Ø–,©ž¶÷ÒK/µ7Þ¸!Y¦í»÷Þ{§ùeÌT›Ìœ9ÓÆŽ[•¬§^Ù«W¯*?@€@6ŒmÙè@¥H€±-ÙkšáH3ò¶jÕª»±(êþøc»çž{ªüQÇܹsíÄOtËf7mNɈLWA¶€ ƶ œ€ PےݨŽx)[¿Cú©§’3í³ÙÔ©fW_möŸÿ$ê—#{Ah8BŽoÅþLR³%e"c[€‚- 2!PÉã[.]8~¼Ù›ošx`Òè(nŸn¸!±ŠÊñÇM @ `Z,çTÆ»í¶›]ýõUÅÈxfÏ=÷´M6Ù¤*,ŸŽ+®¸ÂæÍ›W•¥¾æÜh£ªü q|öÙgöí·ßVe¡··Ýv[•¿®ŽwÞÙd”]üßÿý_Uð%—\bË–-³C9Ä×)¯î²©þÔóä“O¶ðr}úô±Ã?¼jß’t,Zd6y²YûöÉ«'™m·hQø¦8ãÄ“dõ±®ùgÀf;šm»míe÷Ù‚f>me õ¥ñüJϬY³¤nm•ÿª«Öžc¥xé%³ï¿7ŸŠ,ÙŽ¸rUïp·nf»ì·GzØEUóÕlan4—Ð9sª·Z³ ]»ä1 ã ÐÌÎ<3=¿8ßokþcM~ú¦¼ü<àO£ÒuõÕÍÚ´1?a$UF{rk)ȽöŠË5=ì¹ç’~ÕÓ—VLô»Ž›LªÜÓ§›Í˜¡ù¾“Ìn›mföûß§ççÓ±'.ÚO¿`ÿ¸´:öTŽŽcm‡ 1?ùÆ¥LÛa‡dõ»“ºahB•_m"ƒË,‘U»_vY²QÖúÍ„Ë »µ³ÚëcˆùÍR­²ýöÉãgéR³@ÅBnñˆªÚÄë-Ò¨QµQ® Ûʵgi Ê%ÀØVÝ÷šáh€®¡‘œ èû¥óÎ3_ÞÜl¥•ÌN;-¹œš¯L€@hR1¾ó3ɉü}IµžÕÉÙB€@Q¨ôñ-—ÎÑìF’LË©}óÍ7öøãÛ{ìaë®»n21ÿ!@D Úz¥@uÔQ6zôh·ßð—ï.2œù­Èð(<ûQ>ŠW9ã4ßyHT~‹<«h:°¼ñÆ&­¯¨ýqG{¹±ÃË/¿l>úh"ëåþ¢üOú“92±|ÛJþÔówÞ1]D„EÆH¹1GIN—?eŠÙO˜_™ýûßIÃpãdÐÑ¡CR{ô0sÃ*[o=sˬڑ´,ݤIIã„U!2L‘jnfÅ…Eå|ùe8$Þ-Óòú jGäØŠ-䯓Æ@q† 2f’aÍÏ?'G´ ܾä^b €W^‰Í6-ð„Ìܰ®^¢ur18ºûîšLUÿÀÀLý¬'û2´QŸÈ I†*M.G2œÒ1%c ùLa‰ŽsiØN;åfpô›ß$ë—KžÑ4³fåfp¤ýƒ›b×ÿJ'†aäLé”6,2úQ¾2ìëÚÕ|¾Õ¤*¿ÚD¿\$08 §U9ú]«¤òk+#¼`ÊWµ¡S§ð^™ÝcÄJç{fêÒV~iÀGŒ âÌœoÄ0¶U@'ÓD@F€±-Ùáº÷žáÆïݱ”Éé ¥ÒÎ8ÃL+´ëÛŸHØÎ9Çl­µrÚD€ N 1Æ·b~&68Zmµ} Λ @ qTúøVe}³}×]fë¯o6xp|ê›o¾9ñîõ¤“NŠO@( @ €ümlaee‰}ê©§ÚùçŸ_UÐÏnqØa‡Ùå—_n;hvÊa®õFd„¤£¿¸>ôÐCC! sNÖ¬;$2šåF 2< dŠPH㤭¿¸×LR›o¾y\tñ†köç?›}øa²Ž2Ðx[oœùDÆ&á™o4óŽÒ¾øbÒᬳjoÛƒš=ýt|:h¦1©Lm×^ÛL³õÈxAF¹ˆŒOvܱz#7ÚÊpBŒnåZ† §>ø öÚȈ¢sçä¬>j[¿~I­}O3Ÿ!Ìt+#Õ;N‚º«-aU™¹È[o%£TŽžä«ý26ÊT^§ ª´O.g4¥cÉ¿ðNSÍæ£²Ã³)i&¤\äo3SÿÉ`G*‘ÁŽf¬’nmÕ'aVµµ5™›Ù믮Âmß~»py9kí …Yë·žOѼ²H½0¶Õ ;A€@`lKvÎtÿ¸B¯°¤Zí«&¬ÕÃ{Ýnø7Kþü¬gÏÚ÷# Æ$ÐXã[±>“¬68úcÚÆ<ð( €@ TúøV^}£ï+eÛé§Ç§\ìï8þùÏú÷ùë™VUA @M Ïo|ã« ÏþòꫯÚ3Ï-´ÈpJ2™D³Ãhé0Í“«AK4¯\–‹îS-Ñ@IDATW®†IÑ|5c´¾¢sT3JåCFŒ¨[.Á¬:uÛ«“”ÁQÛ¶ ü›¯YÓætÄ€@i¨ôñ­¶^Òrjz¥uÄñ)xà7HúÁgk=Ã_ eøˆ<~WB!@y!РÑgÅŠwy-Ë¥&²²=òÈ#í]ÍS#Ûù¬6;ú 1o¼±mè/§[Kê¤ÒêËL}¡ùz8Õ MÞòYRzè!·¿ˆ7À8à€|âŸ9§ dþüù¾Úؾ*ÔÇöý÷ßûÊPómÍ5×ôÉxzذaÃlÀ€ymåK¾Õ->›Ž ¹ê-ZÒJ³í¹gö,4‹P%bd§C, Ðúk¯½öšOô•ãrnMPÇr(²±Ç¶÷ßß.¸à{ä‘GÊm€ Pg=ö˜¯^üxYaëœ;d$ÐØcÛ„ ìØcµ^x!¶NÏ>ûlâ W}ÈrüñÇǦ!€@)Ðó«[o½5ñ1b)·£˜ëÞØc›ŒewÛm·ØçÇ묣Éпñ—ªë&ž ¯±ÆÅŒŽºA¨÷Þ{Ï.¼ðBž_Õ‹^î;5öø¦šÝtÓM¦‰ÎѺÍ9Ê´iÉE9vÙÅÌoéce°OÕª÷®zwºÊ*«Ä¦!€@SÐÒ™z.õ¼Ö°GÊ‘ÀÚ2ÑÈÉ€Hêé>ïŸf;ŠŠ^îJ%ÍÝEË¡iv¢:øŠZslš¬Keœ’ƒìî3åœwÞy9¤,$í|¹'PI‹^4½æŸ¿òJ3}&ú«_%—ÍÊTñ|Ì.”)oÂ!@ h ”ÔØV´© bÛ˜á(óÑñÎ;ÉÉOû÷Ïœ†@Ð ôÅóLrÜ8óÙn±ÿ»™uëÖî Ô›@1oÙ¡áîá‡ÍºvOõÑG%Þ«j²Œâ @…'ÐhGjŠŒˆ´–¨¾>ºöÚkm™–ÓŠÍf¤%Òâ–I‹I^ÔÒWÎ:ë,ûÍo~S†£ |ñ…Ù¯mnNm¶å–æS$e76jĪQ @€ J" iõ%«­¶Z%5»Ö¶Þy§ÙokÖ¯Ÿ™O€XïÕ¨k-ˆ€ W›njþ1êk‰ªzŒ@€Ê€–Róù2Ê 7܈;餓2¦!€ PhÍ ]@4­!ªi³ÆŽk;í´S^ÖUž;ï¼³i­RŒ¢ÄÉ?j”™îü?øÀìÜsÍͪÍúôi¤Â)€ @€Â‚Ž08ª¦¢odŽ:Ê|f ³ÛoÇØ¨š .@¥A@cãZiôµ„ ˜={¶ó·m¾ùæ¶Å[¶0r‡ d!ÐdŸƒ 0ÀþñؤI“ìNÿÄPë®O™2%KUkF­åKvi}RMØ»wïš iO=eÞ É%Ô4«‘÷ @€ @MG ˜á¨{÷îMW‰"+yýõÍg\6ÛsϤÑQ‘Uê@€@-4¶m¼ñƵ¤"€ Pþô^uîܹÆìFåß×´€@±h2ƒ£LÏž=íüóÏOxõ•ÊÛo¿mŸþyb9µY³f%¶Zb­sçÎUÚÇgΑŮ Ž&&0~¼ÙA™uêd¾ˆ:³5qwP< @€ ÐýuÛ¶mmå•W®X _mÖ«Wzó>:Ý€JƒÀÒ¥KmÆŒ†!miôµ„ †xä³AƒÌÖY'>Ÿo¼1±ÌèÁŸ€P@€@#hrƒ£p;5%î{ì‘Ðp8î"%ðãÉOC,0{挊´›¨ @€ Py*yÙ™ï¿7;ýt³‡2ûðC³þý+¯ÿi1 r#0}út[±bKª•[ÇÒ@¨AÀ'.²4>Üì‰'jDÛ‹/¾hã}2€?üá‰Lj¦ € Ðxš7^Q”TV/6Ûo?³‰Ín¸ÁlÇ˪y4€ @€@)в3ú¨§Òä®»Ì6ÜÐì¾ûÌvÛÍ|†§J#@{!”'ÒJ˜á¨<û—VA€@5-&¢WpºŸ‰“Ûn»-| 'ÄE@hT5*î2*L2¯¼böûß›{l5Œ¦@€ @(}28ª¤—²Ó¦™í½·Ùᇛåk¦%4ÃÑÚk—~_Ò@H.*•hLKÿC€@e±Q¿~f»îZ³Ý .´qãÆÙÖ[om}úô©™€@€@#À਑—EqW]evÇf»ïn&7@€ @EC`æÌ™þEìâŠy);z´Ù€I#£C5ûä“äêßEÓ!T€L@†´’J2¦m042€ ’$ åÔ>ûÌl½õjVÿ©§ž²9sæØˆ#jF@h5ô’.RŸ‰žu–ÙÀfzªÛœC¨¤û“ÊC€ @eG R–Ñ»çý÷7ûõ¯ÍZµJÎh4j”Y—.e×¥4€@ÅÆ6f8ªøC€*šÀ˜1c¬Y³fv ¬’@€@ÀZ¤:¡¤ª ™ºv5{ôQ³JªêT€ @€@%f(ç—²Á¬F>hvÐAÉYöÙ§z—6B¨LUf¿Ój@¨&°`Á5÷¨m»í¶¾t4kGW“Á@MI eSNÙ%H`ìX³‰Ízö,ÁÊSe@€ @åO Ü_Êž~ºÙµ×jY3Ý¢p@ù÷)-„ PécZ–T«ô#öC¨\O<ñ„Í;—åÔ*÷ å€Š’3e·q¥ZºÚúëq© @€ Ê&•ëKÙ#Ì;ÌlüxŒ*ûH§õ€@%ÐØ¶òÊ+[»ví*©Ù´€*ˆÀìÙf˜Ýv[|£µœZóæÍýƒ ¾¸ˆ'D( 4f8j ê” @€ @(`ˆr]Rm›m̤ TmåjH[9½HK!@ çžK~T±xqÍTóçÏ·Ç{Ìlk®¹fÍ„@€šˆ35xŠ… @€ ‚@9Íp¤¯{¯¾º”È€J‰€Æ¶r5¤-¥~ ®€ P8¾bZBvݵf26’ÑÑM÷Š@€Šˆ3QgP@€ @€@C hˆ–¾v×®]šU“í?gŽÙñÇ›Ý{¯Yß¾f¿ûY«VMV † &&pþùç[ÇŽ›¸@(§ž2Û`³ž=k–Árj5™@ÅAƒ£âèj@€ @È Í±êª«Z³fÍò’_Sd²l™Ùo˜í·Ÿ™f9ÂØ¨)z2!ßþö·ÅSj@È3?4ûî;³ƒ®™ñܹsí ŸþhÈ!ÌöW!€ ÐÄ08jâ x@€ @€@> h†£R_v¦sg³ÿüÇlõÕóI†¼ @€ 'ŸLÖ)n9µG}Ô,XÀrjÅ×mÔ€œ@s(@€ @€ P>4ÃQ©ýü³ÙŠé}€±Q:|€ @€@yð Œlå•Ͷ߾fû´œZ‹-lÿý÷¯I @ ‰ `pÔÄ@ñ€ @€ |XáV;Çwœí»ï¾ùʲàù¼ô’ÙÀfýkÁ‹¢@€ @EE`Ö¬ärÒÇ›µn^µ9sæØSO=eC‡µnݺ¥G⃠–T+‚N  € @€ |hÖ¬™]}õÕùȪày,_nvÉ%f_lÖ®Ùk¼H € @€ PTžyÆléR³Ýv«Y­qãÆÙÂ… YN­&B @ H`pT$A5 @€ @•B`êT³_ÿÚL³mº©Ù}÷™õí[)­§€ @€’ž|2¹ÝuךD´œZË–-m¿ýö«I @ °¤ZtU€ @€ T 'ž0Ûd“¤±Ñ)§$—ÀبRzŸvB€ @_Ûdp¤%¦{ôB“ÛY¾ÖÚÓO?mÃ}­µ®]»¦G⃠  ŽŠ¤#¨ @€ @ œ ,Ybö¿ÿk¶ÇfË–™=ü°Ùu×™µiSέ¦m€ @€â |ðÙ´ifq³=ì7L‹/f9µxt„B€@‘`Iµ"éª@€ @(WZBíÀÍ^ÝlÛmÍF6[grm-í‚ @€ P;þýÍ}Ô¬OŸšiµœZ«V­lß}÷­I @ H`pT$A5 @€ @åHàå—Í¿Ê5ûï“3]v™YKžF”cWÓ&@€ @ Ú¶MÎÝeîܹöì³ÏÚN;íd]ºt‰F㇠ ñMWP@€ @€@yXºÔìØcÍæÏ7;Öì€Ê«}´€ @€@¾ ¼òÊ+¶ÄפÞe—]ò5ùA€òJƒ£¼â$3@€ @€šÉH†FmÚ˜i¹€ @€²xþùç † –=!±€ &&€ÁQwÅC€ @€Ê™À&›”sëh @€ üÁQ·nÝlàÀùÍ˜Ü @y&Ð<Ïù‘ @€ @J૯Ìî½·BO³!@€ 4ÀÏ?ÿl|ð :Ôš5kÖÀÜØ€ PXÌpTX¾ä@€ @¨Ó§›ýêWf“'›mµ•Y¯^Ñl @€ @ o^|ñE[¾|¹±œZÞ’ G„KÖ€ @€ J!pÔQf&˜Ýr ÆF•Òç´€ @È/-§&Áà(¿\É € Cƒ£Âp%W@€ @€@E¸î:³]v1;j6… @€ 728Z{íµ­oß¾yË“Œ @…"мP“/ @€ @•C wo³SN©œöÒR@€ @ù$ðßÿþׯÏìFù„J^€ PP/™C€ @€ @€ @ÈN€åÔ²ó!€ŠGÅ×'Ô€ @€ Pôþõ/³Ñ£‹¾šT€ @€@IÀà¨$º‰JB€@ˆG!8!@€ @ÈN`Å ³k¯5;öX³sÏ5[¸0{zb!@€ @ v28êÛ·¯õèÑ£öĤ€  ŽŠ ¨ @€ @ L™böË_š~ºY¯^fO>i¶ÒJ¥Psê@€ @ x Lž<Ù&NœhÆ +ÞJR3@€@„G x!@€ @¨I@˧m´‘Ù¿ÿmv f|`¶þú5Ó@€ @u#ÀrjuãEj@(-‹£Ô€ @€ b$0s¦ÙI'™ÉàhõÕÍÜl·Ýб¦Ô € @€@iÁQ³fÍlèС¥Ùj @Iƒ£Šìv @€ @¨À+¯˜ýú×fZJmß}Ín¹ÅlÕUk߀ @€ ; 8кuë–ûN¤„ 41–Tkâ x@€ @€@1xë-³]w5›5ËìöÛÍ|c£bì'ê@€ ”6Ï>û̦NjÆ +í†P{@¨8ÌpTq]Nƒ!@€ @Ù øóîªeÓž}Öl«­²§'€ @€êG@³I08ª?ö‚ ¦#À GMÇž’!@€ @EI`æL³-Ìî¿c£¢ì *@€ ” µð°!C†”M›h Tf8ªŒ~¦•€ @€ œ l½µÙĉfíÛç¼ !@€ @ ŽV¬Xa/¾ø¢m¶ÙfÖ©S§:îMr@€@Ó`†£¦åOé€ @€ ¢$€±QQv •‚ @€ʈÀ‡~h?ýôË©•QŸÒ@•Dƒ£JêmÚ @€ @ˆ!°t©ÙGÅD@€ @# åÔ$Æ +Xd @( Ž E–|!@€ @%@Àgð·ãŽ3Ó2jï¾[¦Š€ @€Ê„€ ŽZ·nmƒ.“Ñ @¨$URoÓV@€ @€@„Àþ`6r¤Ùðáf›l‰Ä @€ @!°Ô§š}ùå—m«­¶²víÚ¤ 2… ’@ËBfNÞ€ @€ 7ýö3ûæ³Q£ÌZò” ¸;‹ÚA€ @eCàwÞ±9sæ°œZÙô(  Pyx”Xy}N‹!@€ @U4s?³÷WáÀ@€ @ Qlºé¦¦%ÕÖ]wÝF)B @ù&€ÁQ¾‰’ @€ @€ @€ ,Ú´icC‡Í’‚(@€@qh^ÜÕ£v€ @€ ä‹À²efÇgöê«ùÊ‘| @€ @€ J$À G•Øë´€ @€*ŽÀÒ¥f‡fvß}f‹³ŒZÅ4€ @€ @y$€ÁQa’ @€ @  ¬XavøáIc£4»í¶b¬%u‚ @%B@WÍšÕ^ÙåËÍdõ]_ié¯pš×²PEc•±d‰™Ú­ò¢Z[ûV^Ù¬uëì©”ÿœ9ÙÓdŠU_¨ŒV­2¥H†7«pŸ‡Y…ùÉ‘³fY ¥G @€@‰Àà¨D:ŠjB€ ÐÄæyù3RºoÃÏÉôŒHÏ3=×Ò~\ýÙ™ùR6‰´JVŸi"¯­ôP×®ÌwÇ›®þüÌ:ºös ËÄE¿Ð÷õÊ,ómA9r«ù¥æ~=»’äé;¤puîl6Ó5Òä¶üÞ5,ïzúq^¹æž‡ÿ%4*>xH<k¦‡¡®ÚíîâÛ-ÌÚ¶5›ëî'qU~™DcœÊÒ©GÛ#\ÃO:¾uÿXW‰Æc®êïºó¥”WõPý¤Q·ÊQÒÓ\Ãc¾ê9ÒUûuquÖiò–ûžK ‰÷ˆ¡Ê‘žç¾ÖøÂý×»J4&\pUÿSu ê¯m&O•q©k¸ŒOݵ«öÕøög×°¨ ¸}ôK˜UP¾Â$qm“p%ÿO…ɧ2®#$OºÛÓÇ“òÓ1«¾ T~i\j‡xÆ•ñ”‡ßën‡Òí ÚÞÞèñ+¹ò±;ÄGû¬æúw×°¨/î DÜAÞav7{šh—y˜ÊP;2•Ô=hOà×V¬ÂÜns¿®+ùîÊèîî¿©m¸Ê?È;(K[I¸=ê¿p¹ÿOJä’ «pÞá2Uv :Ãeál!ÐPÿý¯Ù[~ÒÖ4€R?D· ‹S]g¼Ù AÙk¡ü/¾ØÛÁ(&¹Ö?•*OiàÖö/~Ò6,f§PЋ/š|²ÿfý‡Ü«…¢«œÁõcôšò¦›Ìvݵ*Y¬ã9Ž>º:*šGØ_ªÚõ¯™í¹gµ?Îõ„ß8Ž‘dÔ5.]¦°1cÌöÙ'Sl2üñÇýißìi±Ñv=à'¤ýö §¨é~ì1³½÷®žkH%•ñ¤_T8«Mü¸´å–¹¤ƒ@~h¬[è7l‹ü/ºÕ˜'c¾k/ëÁÍÜh.1n…Ï—Á9<Óø¦±®W¯äÚßµ•rþùfÓ§'ËÈ”6\žÜ*WÛþýÍ.¼0Ó^Õá¿ý­™® ´O´QPVvÿk­M4Î~÷]õW[úpü[˜i­M~ùËdA:Õ=Sýƒ4Ávë­Í4ŽÖ&Ûmgöí·é©‚r‚mÀFþ°l»­ÙÇCâÝÛlcöÍ7Õ×5A~ñ©ÓCs-cÓMÍ&Mªîà˜QYµÉ;øý¾_Õ&}ûšMž\[ªøø/c=ïûôl)[zô€@€ Ê&°À›ÿµëW®´õ ÿç7ÚßøMÅÌæn(âoã–êmMJvñ7‰­'%4_~¹¿ðð›I]3·qíèúƒkXÎ}ÃìF¿9ª‹œè7!ͼ2º{þyÑ4Ô,§2P~ÿž&—¿mvëà´ Z=çèQ–î¢2ºzg&½‰vD Žn~§îe\ÜÛ3 •ÑÅË8$TF´Wy·ù g]ä¯j‡ßxJÔŽN^ÆeI¯­âÛsSî`3òC³ÛëXÆõ›ûÞ©h•ÑÞËÐ gIW×®êçnvwþ}ßF2•ÑÒË^ЭëÁ¿­Î>áºf¼Ù=u,ãâ¾ëÌdF*£¹—ôsONuU2ÿ?ÑßDŽZÇ\Û»úï¡VÑÛÒEÉT*£•—¡ºwrÆë’QUÿõÿÈ#«¼É²Öw?מ®+\ýW•êv¿kJTÆ^ÆOîW»¸ª¬°Ô(#™ƒ[e õ2²É¸q‘vdK—Kú›ß#ŽˆÙ¹ö ž× ¤" è½æõ×›í6ÄO§»ýÿììûˆ>èþð‚ÿ¸ÿ`×¥®kº¾å–¿¹'8„ó¹§ûo¹«Úé¡õGžx—Ô=}=Ý:ÝÏçÝR rÜ´ô–m| _ÉÏEzÉø•ï÷‡Ô¾½|{L$Ÿ¿¾ëçë_DkñνÆÏ7¦“Ÿlô0ZõvÆ Q¿K¹ƒÍU¯ûi«ŽãÎ'GyÌó1Æ™oôÅžÙßSªŒ ‚ÌSÛ‹s#Ô="µx_÷‡Ü*CƺcÇ&‰ÛRûôöíŸ#û_è/U_Û?X‹÷EÝ|®Ùê«›=ý´?¸÷ôw¤öQWDö¿ð^?ÖtàÕAžÙÂjoÇk˜ýûßn°ëûÞžÚ?®Œ??döê¾u(À“>ÙÇÛ1ßs×N#ø¡i÷…Êú&Èõœ‘førÛ>¤š³êÑà í>ñ)îÚU툖qÆ­fŸ—Jà¿©T+%·î¤¾uÕEº.ˆCúÌäûé­fñkiûµ«.ìý>¡†lîù­ÿÏäMB ÝdIýBšðëf¯èuÃ¥ m»náùòpß·[7xà¹Þàª2ü™Z ÙÙŸN¸+µ*ïÄ 7Ê[yz™òë¦EmÓ¶û^^†—¥2tóÖãü{¢ q÷TøSÇ™I¢/í' nT“>÷rVx™Ë];ýÊC½Âú2D|uSw¿«ž×y²²»ß”|s“?ütmÄĉi0«’ŠL¸Sm¿ËAÎ1•™ìùŸ}é*‰kÇΪŵé7óÒŒ’*gÕc«ËèÕËo¦}‡—]õ20®?öô'Ž?ø‹Õöþ²?<ÔV/À%º!ŽªÚÑíw^%/O¢2Äê3W+µ÷²Gy½t܈•k3¯L¢Õ&]êk¨··çéž.ÅJeè&øuW?œ7®¾I“¾~à­éy¶þÞ믭«úEîD9j‹ï‘¸ÉO¹w:;½S9~í[õeT5Ûú}gé•‘ÎöþÉ&«ùÍù‰½Ì«›}‡ S;âÛ{Rî`3á—fCÞô¾ð>Xi‘«×?¡înãÚÊÏ¥^¹eÎJÚÊÛ¸–:×Eåôé“<^ãêŸL•|¹tÁ/~«ßLðÀ'Øa*£6Ñ ,YލNÒ`ß ¯`“ÏøñãmvÀ,&ž 2%à§ŸGÏòCúz³ý”±Ñ«~Ø ŽikkÓ!¿F(NaÝ][º® œãÇú¹ÊÏËü÷"]ê¿«e~>Ò6áö“× ×e>pI—ûy°Û­¾·ÿu®ÖŠë»WA~8' }“&ÿ>ýþûL$H‹ y¼ÌĉØË•aâ‘Ï'·*CG›¹÷ WIÜC¿I—{Ä”D´Óñ­~èÒ¨[åxþÒ‹ßó­×K“ep´•{Ç»êôêïÂjÈ´«=èj× •ãúЗ¾õ ƒÖÛ¹×OÅ Ñi=*-ïðÄÿë¡Aý}«sBpžouþÖµÁ„ï’Íœï}#âªñ@íPó£²ÚC~Œ\èÊÎe©|4&Ë“¸=\Q ý:Ii‚ä;x˜®$J•þÏz¼Ot\OÈ­Ìšé`tmæ«ÜîoáÇ™fUT{%*c¶«Ê+cÕÑn8¤†ƒlãyiÛÚóiåšÈÃw ÚŒo-V÷Ì\‚—×CÝ­jÅå¯t;ú1ÒñŸrÅ‹®=š«-žAp-Òj#w{¥ƒF*C‡C¦vìõ•?LÖuVŽ¢‡ÙÍ}‘„ËÐOGíˆkË^~Ö¥ åm›$þ›^âK†»ú¡’QöŸäƇ{øqç^ÜØ>v«2Ù%ášWUá8Êž€f^AÞGùÀöaõ6ÓËy?;ši6×y>(úî‰óµÎC>ÙÎb·ðY`ßñßNæþMœs|»Â³ ¿¶®+ü£0mÏðÌÖv·î UÖOâÕK̪Ÿ~Ãai±›¸x]tN×ù6Nô›Q\ /¸Û³®¯¢æªxž^v Ë„ý>Õ&Ågûý).P?¥$îk}“IþÿJ×¾®¸FO73› øOò¾Kû÷wA•oàv§yßVÈ›‘þÿè¤Óvôíó)w°¹gK³§ž|Ù·*Oeø°“&÷¹ïd×u]‡¹ªMaùÆû|݇ýŲª1$“ˆ…£M“KÝwN*ä`ߎN‹5»föþ3˜Å»¡Ç}‰ÿ³ûÏuÕñô×¹†eɦfÛŒªnÃ×9É5Ó;Çá÷œkXÄé©€?øö/áHwŸ³± "qqÞÚÊÐ¥Ñõ‘¿ô2†ß”ü­Nô8é„Ôö{ߪŸÃr„{¤&ô‹ÔV¿™@.vÇyIÏ·ï½gß\xaÃ¶Ò hÖiŸ­Ø&øA3CK·f•ÑÌ@šÁåµ×’ÏŽ~v`:¶:»®7¹,·ž_ó¶÷kßvþ|¤­i®äׂm’Ú¬µŸk\WŸé3ÔúÉHËêÞJ2ÉUc©îÃã’{2è%Îäy-iá¿W?aÅ©NdAøŽ^ÙÓg$ÇÐÀØõ$ÏéYWýÞun=Ê5,«}î×áÍ“!Êg¹;Õ>rk«kÉpè:?¸_ðŸgÂpБ˜5i÷»jßöÎ\üô»Õ˜ ü–¥Ô7U”«ß¯4,~H\(ìa×½åH‰ö{!z"3l/ôð "q{¸ÿמ®gºþÂ5ÿ{=ôMòÍdWµ-›Üâ‘ÇEôv0–¼íîÍCñ:/?u[( ç­žæØH:{³\×v}ÐUìQƒîOÓ_»{’ë7®~èg”Ç=f·Pìbw¯òçî5Cþ÷ÝýPt@ ÅÇ9³•¡Cï+W± Dí~s²þÝ-àš­-xü&®hÿ 'Deè8 Ë3îsI8¤v÷‡žÄ‡Þ*QýR¾¸2Tçͽê«©®ú¨­ÎswT¼íÓ~øÊ>ÑL HÙhY¶-+Ó†-tËãYnµÜÕ¿rl©ÙbĺvpÕ‰) j“]—¹úuGâÂÛ7U¢ ¢é®ÄuÂÔ6¬qaüº§JT®ÊPþ _×5,~­Tuc—·ÊXšÒ%¾•qõë¬*Ñá÷Õ‰‡rm|»CULÒ¡6¨Í]•ŸÚ«màûƒða¯¼ñ禉A§oWvíD¤¶?úv’«Ú+Þ™$È_mên‡X¼áªzúµ`¢¾© ¾ŸWùrs ödá2Ô§»ª?TFxtoâk]Ý¬ëØŠ·ÒJu˜Kw3wK¢e¨︪­êsµ3,5@,´U^Ñüƒ²<ªFês=4R©Oº†åg÷|ëªAU:ßU}¨r‚úùk+æÛ»†]•ñ®«ê'†;¸†EíP¯þÔ6pgj‹ò—¡ Ä×]U¾ß_ØŽ®aÑqõ«úBÇVÐ/rKÂmÚµ£‡GËÐq¥ºù}‹ýÒ5,Ý£c"Ü¥•*,È7تÌa®á2ü^$ñÔ>ê“h~?–0ÌÐñ¤~Pýµ TáQÙ5€¿14ùضP'‡ï]ueì?²ÕüàÙÀ¶MW÷‹øõ’3 ¬²Šß0pÕÖµÓÅÕ7®¤»GÌöè­ýAªkCåÄ,0È¿6tm¨„o£yí¼™?”wm¨ìŸ%ƒ}7õ)í]*}²d°ƒßII*:‡g’ƒúùË ×†J¶,öòcRÚPÙ&Kç÷2;?K|lÔvé¡=ÝûI*Hç⨼¸ŽŸÏ];z„ÚVÿ &ÆQ³m»š¿Ü¿ÀBŒû:÷ëaQT^÷' /¹æ*b¢±2,tÏu®^¼ã*X~ò œ-\;{ ÆšÙ1ªôŠïâªc4:viÌ Æ>wÖý¸•*Æ?±9ÊD_ÊažfzB…@“mº.>Õ“7}µ’e®îM|0·»;4­íÚÊ/ ç|á÷^ù=…_€ŽøÔVþà×ë~Á®—¸:Ý¿åšI¦ÜnöõS~mèjZ:QÚ1µ•[ù´ö Z= ®Úî—ô_Kêgyl¦<ü´“Ó³‡¿0 ‡ÃTùê?Pm5ƒ’¤“k¶!xäeÉ—ÐA¾z0Öà¡´Œ!‚%´ÕÃ}µMÒÞuƒ„+þßý7ø9ÌObª—ê”ÞªLÅkrt”‰V?º}æhHÝý^|싃 §F®úoUFªkb3ù×m±Áu tÄiËÒFw~hL4¤î~領çÑ®».Rw¿Ê¯LrÅ™brW©Ã8v§|”›q(ðÒKCžº9¿|é%7Z¼µn;‘ºÞš|l{ÿ}¿Îó =ißÇÇ´ãÍzú‰¾åêþœV½ŒÓ4³*&é˜â›]»»fúë·Ù<¤ºî ‹â5.(Æ ¨¨\G“ˆWÚL¢¸ ¬h]üRÀnLí¸¾o?O¹ƒÍ[îðKÄ Š×5n¸Îry»3¶žëz¸_$d@jÞøeoU|8<έ²âÆ—`ŒžäñcvÔåñ®:®ãªûáµ\Uÿ8ѵKT´ÏI®zžw?=ÌÃ;¸FùxPÕs0õq áãIi$A3Üw»|¡‡?é*Q9jƒ˜ötUÙQÑ=WTvlrNÝÇ <9lk+c˜“œãú§„«ú_«««?`¨ÍìÚͣΌüP/ò°‘©]®ñíé)w°ù¬Gò½‚ν:Þƒó^ØëÒÖKCÒÆÝ:ŸkuQéæ'lÇ”ˆËWù‡¥‡p-ÃîÖ-Ç‹©0¿UKœRÞÄ{†ûÝ£qA¿S¿´ˆ•”¯tQù•¤º&ÍØEé´ßArä AŤŸï]ßuÕ8ÅÝ쪾è麓«#å—I‚óZ8þp÷è|&®ÝÂîÖørj$L^‡Áy:¼UœÂ5ä8ÑuÆ×®QÞ³<ìÝUõ Ë;î ÷¹ŽñÞ®{¸ªMþS¨Á,òÓHÕ!,Ϻ§¡e|êyìÊ4ŽÕ=wr*>×Íž°[(±ú|xʯß~?ayÚ=ÿÈÁ­ã_Çh bµWÊWƽwJ8Ç­~Çú="V{¦<º¸ú6ˆHmŸðmCËÐqµ{*¿¸2FÖ£ ¿‡C‡@Qmû ô—¤~’ßÀO†ZK¸}ûÆ@)¨D+Å4úû«køú$&YÖ ÏÁ—P×eºþ˜éª‡³S¸¹¿•«ÈH£<(qÓ¼½ou ÒRÑ×#aÙ¼ºþ ®]‚t¿sÇ-®ât¶ëù®aÙÒ=ï¸×Ùªs—”v¹õfe×M]uE…@Qmüì‡þ±ár³÷Ü}ÜÝ~K¶þŸýk”Ùã~a¬Ù!´¼LXd¤¥Q4ã].2fŒ}·ñߌ~4’C)PÆ¡ls™],”¼^Î`6™zíÌN€šŽ@Qm½úúG[§ûuÒPÿ¸h#ÿVÄÌLõ‹¡Ï#|t ¤çznãã`šèzóRW¥‰»íÓó˜·\u­h‹[aò‡Uy…E×dvâªgSªCøåçaî?ÜÕ«^où…ïùQ–½ð8iCdoßYõÿÂuaLFÞ‰¥U£/•b’f ò®¬ñÁ`8ñÑî‘6Döð¥™äbêùXóL‰j ßÙ㥙ä6Dvñ¥™ädøƒk/×®õ9¾Fø~ÒL¢>o¨ÔVÆH/à+W]^öN©îmê"GÕ’øÌZâs‰þM-‰¦zü—)Õýã:®ë»®çÚÖ) E5ÆÝ{¯Ù]wù¬7>x,ØÊùø ²ÙI~ïó d©Goêú°Ç‡å—îéàªßŒÎ¯Q¹Ìô,D¿/©ÎÑ­Â'÷óx/5>„߸7!oûÿ¸ýRÑ9mô|(›<’-2Ç8¿•­š™eÛ˜}¾ó°èø“,kÐYb›yœwyƒåÁT‹}Ãt,Lw ¿J%¯Óæš,©ýYƒ]›%>×(›™DçÍw]{¹vÉ”¨–p]·e«§ÎÑÙâkÉ>][ý<•ú|]WoÝ]ë*jÿåYvÚÐãþ”%>—(•‘-½<^ŒôYõ«úF礢 ´¬èÖyã¿õ)Ï<óL{÷]MÓe…O3ýƒ}úàƒ&tذavå•WZ‡E (/yÞGDò×´N,:I®£m<,,J{Ž«NÀqy¸.ü5@jà k4,ðë"*,z¨p®ë2׸‹x]ïì-CáúuèâJ[©Ú ÿt]îm£ÒÉPHz!¤üÕ^åÝ*,Ð耩v\ä:Ï5µ‡« q‹÷à„ùk«‹€°ôvÏí®j‡ò‰Ê`¸1X‹?Úëxz غŽ+c¿9'–j‹úNé üâ)‰–¡v(µ1î¸ú¥‡ß›ŠW©òRþAÞá²<¸F==ì:×E®qíØÊÃ/qUùíRÛàø ò—'æÑŸ¬Ú!Þª_ÜE­ÚqO*^itlÛpÞAyj[4Ÿõ=ìNW•wìnãá—¥âÔN¥‘Ê­ò‚¼ƒ­Êˆ¶CeüËUu‹¨¨£\ƒºk¨Êú$ت¬¸2Fz¸ÒGã<(1Õï|«ß¯úAõ×6pë8‹JܱMƒ¿AŠrlóYíÐCÔ.v†@ zýÓ€¬2îªó{¹Eíɤ™äÏ1Éu¦«Æ]séz%¬îMÄÿìÛ¸±K×z8×5®¾ºfÒ5¨Æ4]Sª,å%ýÎõÿ¹êº1½hâôÐ(ضǶ·ýØî-nÕi¹½|ò[óÏ~«/e%š©O3e ®Z¾³.Rè{Ϻԅ´€ WÅ8¶Ù—þpã…+“íÔs€ \wuÕ3 àèš^~ÆÝë{pBt]vvÊ·ñ!²ÆWÙqé²…­á‘Ì’@ÏWJEôž;æ]w¢úq/šK¥]áz®ö”°{·®{¸ê›»GZê¢sÎKR¤èåw“?@xég¥7ùq1Ð7C]µÕœ“åŽKñpi&Ù)SDÂ÷ô´ÒLR*ÏÖuë+36RÛ¢ïSVÌ’éÚgÕb®tŽukåé6Ë1m1'ÓõÆAÅ\Áë&C)]#ˆÐkX¤ LŸ>ÝŽ<òH›2eJNµ{þùç퀰Q£F%f>Êi§ú$æ;=䪋Ý@kwqãÁE×LÊ›\cË,ñ¹Déä-ÃL’ ~]“©ß$¥Y’ÔÕÃSœŸ%Õ “6DÔŽ£²dàï!SðfIRk”Ž•S³¤ÚÐ㤠 tÇgÉ`=“6Dt¼Ÿ’%ƒ|Ü«Œ²”Ñ×㤠õùo²d߇úãð,eôó8iCDe‘%ƒ=NŠ ¢ÛІJšÀŽy¨ý±ž‡4“ü%SD(|‰»ç¸Îum ÇYÅ:¶½p÷T[¶°«=½p'ð§WÝ ÞŸüþÆ/;Ì-‘†»ÁZ‹‚ð S@(}Å:¶%ž]à|·NiçÒgM @ q í7xˆÏFã_éý›ŒŒ†¸emׯeCi€ úàt}Ép¿E‹ÙÑGfl´ÒJ+Ù¶ÛnkÛm· 4Èg¿Ÿio¾ù¦=ÚæÌÑÿ zÒ$;ûì³}ùú[MK®DdÈ#E @u PÔc[ÚAR@EO@_åãëü¢ohÓW°˜Ç¶3Žšnÿ};[ç—náý›Qfûì“4:jzlÔ€Š˜@1m‰YÈ/,bxT €Šš@Qqj—ý#ý¢&Kå @ Ò `pT„GÀ˜1cì‹/¾¨ªY«V­ìŽ;î°Í6KŸ7nðàÁvÐAÙGQeœ¤ugÇŽk#FŒ¨Ú @ © 0¶5uP> ä›@Qm›lbë|ÿ¦YwM ‰@€r#PÔc[nM  @ –c\,!@ &мÁ9A^ ,^¼Øn¹EkµVË¥—^ZÃØ(ˆ]{íµíª«® ¼‰­.œ@€@±`l+–ž € /%1¶al”¯î&@A $ƶŠè  @ù&À—o¢ä@¨&€ÁQ5‹¢p7Î~øá‡ªºì´ÓN¶×^{UùãšùhË-·¬ŠúøãíÛo¿­ò〠4%ƶ¦¤OÙ€ PŒm… Jž€ ДÛš’>eC€@! 0Æ’.yC€@¥Àà¨ÈŽ€W_}5­FÇOógòl·ÝviQO<ñDš @ ©0¶5yÊ… B`l+Yò… ¦"ÀØÖTä)€ M€1®Ð„É€*™GEÖûo¿ývUš5kfC† ©ògs„g8R: ޲Ñ"®>ž~úiûé§Ÿê³+û”)É“'Ûk¯½V¦­£Yù$ÀØ–Ošä•OóçÏ·ûï¿?ŸY’W™¸çž{léÒ¥eÒšQŒm… Jžù °dÉ=zt>²"2# k]û ÈD€±-‹€Æ6qÂyä›9sf87b 0ÆÅb!°‰ ¬X±ÂÆŒcË–-kâšP|1øàƒlüøñÅT%êZ `pT+¢ÆK0qâÄ4ƒŽ7ÞØºvíšS6Úh#kÛ¶mUÚ &T¹q@ ®¿þz–êËÈ2ÊC>z!‹@ ƶltˆkj³g϶+®¸¢©«AùEHࢋ.²Å‹aͨR1`l+†^øÿíÝ °œU}ð“"©@¨ Ï“‚ ¯Z*`µ˜ÇÁ‚­ŽC)V[Eäa©µà„GE˜ª8´*§ bÁ‚#팅ZÚÒi"åQAä (Ï‚!Is.½›ûíݽwïîžo¿³ßogÂýžÿïœßÿäü|ìjC;8wÅ9Ì‹@³Àç?ÿùð /4¶O`D@m3ª.pî¹çúþ¼êI@û.½ôÒ°råÊ<Ù#sPãrÊV½Úýå_þ¥GõJû¤½½ùæ›Ã¿þë¿Nz TIÀ‚£ ecÙ²e…Ö,X° °?ÑÎæ›ovÞyçÆ%ñ_|Äÿ‰æE€) ¶ Rß³  @ …€Ú–BUL¤€Ú6H}Ï&@€”j\J]±  @€@3 TG ù㪶Ùf›)5nöìÙ…ëc¼­·Þºp¬“ø6¤ñÞï}ï{#—ÇvÛu×];¹Õ5C,°fÍšðÓŸþ4Ìœ9sˆ{©kSxì±ÇFþ…lîoïÿø£>Úèúúõëý«¹†FïU©mqnü3ZÛbÏbm‹5Ϋ¾?ÿùÏGþQîóX}3˜¶ç÷Þ{oØb‹-Ò>$qô8?÷Üs#Owrvº;™IDATYºtixæ™g?±á«RÛâG#Å?ckÛÞð†°Ùf›Õ#zÙRॗ^9®¶µä©õÁøQ ÷ßáµs‰µl´žÝsÏ=:—c_ªÔæªÔ¶øóyüXÛ±µmþüù!þCK/ñûó±ïðO„@œ3â'=äþqØñg¶Ñyø¡‡ «V­’Ü> ŒÚކÔÿw{ê©§ÂÏ~ö³F‹¿oØqÇG›åk âÿ‡ˆ¯ø=­ïuj8Út9ÎY±¾åþ3}|wÝ8ïÅ×O<FWѦÛg.`ÁQ…8ú?F›4Õo|šÅI©›…B?þñCüÆöÌ3ÏiJüŸ±;í´Óh³|­©@, _üâ-8ªiþ[u;þ®øMÂÇ?þñV§³9ßîÉ'Ÿl´7þ">.L™;wnã˜îªRÛî»ï¾‘olGk[ìQ¬muŸÛa¸3þR2ιÏc˪õaÆŒ#ß OŸž÷ÂÆH0úËêøVÝ[n¹eÕ¨³lOUj[ü™-¶elm{ýë_oÁQ–£ªŽ¿´Žs˜ÚÖ?Óa‰¿ï‰·—û¢ÄÑHókÛk^óšaIÑ@ûQ•ÚÿgDüockÛ;ìà ttTãá±¶uÖY!÷ïÏ«¡9<­ˆ5á /Ì~ŽˆÿSvt޵-÷Z]µ6j;Ú®Aý·ÿþïÿwß}w¸ýöÛGš¿‡ñûçѬÔóküûëÛ'?ùI¿£®çhÙëø»¼øýοÿû¿·<ŸËÁøÿŸ~úéFsãx÷^ Ž*”Ûæo|šß±h²¦6_ß¼r{²ûGÏÿÅ_üEˆ¼ @€@¯U©müÇâ/ Ы@UjÛïüÎï„øÇ‹ô*P•ÚvðÁ‡øE¼ @€@¿ªRã¾õ­oõ«Kâ @€J äýOv+EÙ{cš¿ñ™êJ뭶ڪЈÑÍ\8h‡”( ¶•ˆíQ PŠ€ÚV ³‡ @€@‰j[‰ØE€¥ ¨q¥r{ÔPÀ‚£ %½ùc]fΜ9¥ÖÅûj~Ç£±çl @€2Ô¶2”=ƒÊPÛÊÔö,(C@m+CÙ3 @`jÜ Ô=“ê$`ÁQ…²Ýüy­ñ³{§òzùå— —Ï™3§°o‡”- ¶•-îy Z@mK-,>”- ¶•-îy P–€W–´ç @€@],8ªPæ·Ûn»Bk¦ºàhÍš5…û·ÝvÛ¾ P¶€ÚV¶¸ç @€@jµ-µ°ø P¶€ÚV¶¸ç @€@Yj\YÒžC€u°à¨B™ïõŸ•+WzcÁQà @@mºG @€@Rµ-)¯à 0µmèI€¥¨q¥0{ÔXÀ‚£ %¿ùŸÇ|J­[±bEãú3f„­·Þº±oƒ B@m„ºg @€@Jµ-¥®Ø 0µmêžI€e¨qe({ÔYÀ‚£ eûí·/´féÒ¥…ý‰vâÇ©] ´ÿþû‡iÓ¦Mt‹s @ ¹€Ú–œØ @ dµ­dp#@€äj[rb @€ ¨q‚÷X¨€GJõ‚ ÂØo~î¿ÿþðâ‹/vÔ¸8iݺuk:ê¨Æ¶  0(µmPòžK€©Ô¶T²â @€À Ô¶AÉ{.¤PãR ‹O€u°à¨B#`úôéaÑ¢E­_¿>üèG?jìO´ñÃþ°púmo{[aß„€Ú6uÏ$@€”j[J]±  @`jÛ Ô=“ÊPãÊPö ¨³€GËþ±Ç[hÑW\QØoµóì³Ï†ë®»®qj—]v »îºkcߤ€Ú6H}Ï&@€j[ U1  @`jÛ õ=›R ¨q)uÅ&@€º XpT±°÷Þ{‡=÷ܳѪåË—‡k®¹¦±ß¼±jÕªpê©§†Õ«W7N½÷½ïmlÛ @€ƒPÛÏ'@€~ ¨mý- ¶ :žO€©Ô¸T²â @€6ëáÜsÏ}ÏÆû÷ë%†{Ç l¹å–á–[niœ¸í¶ÛÂìÙ³ÃÂ… C|ûÇÑ׊+ÂÉ'Ÿ–-[6z(ì±Çá‚ .›mÖSjñl @€~¨mýPƒª$ ¶U)ÚB€ýPÛú¡(TQ@«bV´‰†@à’i½tbÆ Wm¼ÿ¤^b¸·µÀé§Ÿn¼ñÆÂÉyóæ…ýöÛ/l±ÅáÎ;ï ?üpáüŒ3Â׿þõpÐAŽÛ!@€UPÛªm @€~ ¨mýÔ‹ª  ¶U! Ú@€)Ô¸ªb @€@ÍæYpTÑðâ‹/†}ìcáÖ[oí¨…³fÍ —_~y8ì°Ã:ºÞE @ lµ­lqÏ#@€Ôj[jañ  @ lµ­lqÏ#@€²Ô¸²¤=‡j$0¯§ÏÝò‘jé†ÊÌ™3âE‹F>Bíî»ïk×®mû°C=4\tÑEáàƒn{ @`ÐjÛ 3àù Ðoµ­ß¢â @€À Ô¶AgÀó  @ •€—JV\¨±€TË!ù«W¯7ÝtSX¾|yxüñÇCÜßqÇÃüùóÑG.\˜C7´‘4Ô¶… µmH© ÐPÛ6 @`ÈÔ¸!K¨î @€À |¤Ú ä=— @€ @€ @€ @€@†ó¦gØhM&@€ @€ @€ @€ @`@ Þc  @€ @€ @€ @€ä(`ÁQŽYÓf @€ @€ @€ @€°àh@ðK€ @€ @€ @€ @ G ŽrÌš6 @€ @€ @€ @€€G‚÷X @€ @€ @€ @€9 Xp”cÖ´™ @€ @€ @€ @€À€,8¼ÇèD`íÚµ!þyå•W:¹¼£kÖ¬Yž|òɾÆûà”ñSÆÛ‡*nÿò—¿ +V¬Ë–- ?üpX·n]_›™Ò6ר}Œ‚@nõ-å<aRÇ/àWlG}kŸ:‹ö*Ψ®€ÚVÌMç°œk[ÌbÊÜ¥Œ]ö臀ÚVT¬ó¦¶ÇÂØ½:‹±¶ ä$ ¾³Uçy,çú–2o)cGŸ½a˜1,ÑÃ&ðƒü |ô£éÖÁ®¾úê®»xÛm·…¯}íkáÿ÷GÅ@Ó¦M sçÎ ‡vX8î¸ã›Þô¦JÆOÝö®;]ÂO=õT¸á†Â?ýÓ?…»ï¾»ðÄÍ7ß<ì²Ë.a·Ýv ïz×»Â;ÞñŽÂùNvRÚæ»7× Л@.õ-å<SÇï-KiïVßÚûÖy\´Wq†@õÔ¶WsTç9,çÚ³—2w)cWvÐBù ¨m¯æ®Îs˜ÚÖþïoÇE{gä! ¾½š§:Ïc9×·”yK;ÙA+{˜ÖËÍ6l¸jãý'õý´ˆ‹â7?ñÕí‚£Gy$œyæ™á®»îjý1G<òȰxñâ°ÕV[9:ñfÊø)cOÜ«jœ½ùæ›Ã§?ýéðüóÏwÔ ¸è(^¿Í6ÛLz}JÛ\cOŠæú&Põú–r‹ˆ©ã÷-Q‰©o­aë>.Z«8J µ-íÏU ¹Ö¶èš²þ¤Œ]õ1¡}†A@mSÛrü½dü»—²þ¤Œ= ó†>ÈA@}Sßr¬o)ëOÊØ9Ì ÚØyõÅQýxæ™gÂá‡âÛùÅW7 Žâ*ÝN8!<úè£7.¾cN|'¥øÎG“½RÆO{²~Uá||7ª .¸`ÊM‰y‹÷î±ÇmïMi›kì¶XN Ðwª×·”óXÄL¿ï ës@õ­5hÝÇEkG ä# ¶¥ý¹³ê#!×Ú]SÖŸ”±«>&´À0¨mj[Ž¿—Œ÷RÖŸ”±‡aÞÐ9¨oê[Žõ-eýI;‡9Aû&`ÁQß("Ð'—_~9|ðƒ,¼+ÑTÅ¿ÿû¿î¿ÿþF«¶Øb‹ð¿ñá-oyKØÿýóÏ>þó?ÿ3|ó›ß /¼ðB㺷¾õ­á«_ýêÈG®56m¤ŒŸ2vS7*¹»téÒðþ÷¿?¼òÊ+öÅ…D1op@xãß^zé¥ðÀ„o¼q$‡ 7nxàaÉ’%-ó—Ò6רcíl V ÎU®o)ç±(›:~Úìõ]}kmX÷qÑZÅQù¨miî¬úHȵ¶E×”õ'eìª í#0 j›Ú–ãï%ãß½”õ'eìa˜7ô@ê›ú–c}KYRÆÎaNÐÆ¾ Ìë)ZüHµ¼èƒÀÆE?¾óïlظPh N<ñÄ)=áßøFáþ… nØø±j-cl|»¼ ?N­pý?üÃ?´¼vô`Êø)c¶¿Ê_?þøB.bnžx≶M¾îºë6ìµ×^…{®¿þú–×§´Í5vK( è«@.õ-å<ASÇïkÒSßZ£Ö}\´Vq”@õÔ¶WsT÷9,×Ú³—2w)cWvÐBù ¨m¯æ®îs˜ÚÖúïpÝÇEkG ä! ¾½š§ºÏc¹Ö·”yK;ÙA+û(°ÓôžV¹™®6þE_|qøÈG>Þõ®w…_ÿõ_guVX¶lY×1ãñcØ®¸âŠBŒóÏ??¼éMo*Ý™7o^¸ð GwG¾^{íµ…ý±;)ã§Œ=¶UÝ~衇Âý×5š·ýöÛ|DÚ;ìÐ8Ö¼ßÉêø@áð¥—^ZØ;)ms=Éú"c}K9EÔÔñû’¸„AÔ·Ö¸u­U%PMµm|^ê>‡åZÛb&Sæ.eìñ£ÐzPÛÆëÕ}SÛZÿ>¼îãbüßGT[@}ŸŸºÏc¹Ö·”yK{üt¤Õ!ËúXIõë×, ºå–[ÂO~ò“°víÚ¾´óÿñÃÊ•+±Ž>úèð»¿û»ýVq1Ò!‡Ò8µ|ùò°ñûc7RÆO{lªº}à 7šö'ò'aþüù…c­v>ö±…ø‘y£¯+V„§Ÿ~ztwäkJÛ\c€ì Ð7ë[Êy,¦Žß·ä% ¤¾•ÿ=U¢T K ¶jÛøÔ«myþì3™2w)c…Ž Ћ€Ú6^¯îsX®?·ÅL¦Ì]ÊØãG¡#ô* ¾¬û<–k}K™·”±Ç@Gê `ÁQ²¬µø·û·B:ê¨Â~»·¼å-…S7ÝtSat'eü”±GÛ_å¯÷Þ{o¡y¿õ[¿UØo·í¾ûî…ÓͱRÚæ»f‡Ê ä<פl{å·±Í5I}{5ku9Œ]m$Z å<2vtI?µ}¯ñs­m©sW÷qÑë¸r?aH9¤ŒíSǯz~Õ¶Zý>¼îã¢êãVû”%r.H;ú¤Ž_Vº}N®õ-eÞRÆî6OîË[À‚£¼ó§õ LŸ>=,^¼¸åŸÓO?½ëžÝqÇ{§M›Ž8âˆÆþDcßá(^×ê¬x.ÆÿMq„@µÔ·ñù©û<–k}K™·”±Ç@Gê 0£ÔGUˆ‹Ž=öØ–M{ðÁÃE]ÔòÜDã}¿øÅ/—ì·ß~áu¯{]c¢}÷Ý7Ìš5+¼ôÒK#—=ðÀã.O?eìq©è±ßøì°ÃSjåc=V¸~줔¶¹Æ.`Ù!@ ¯¹Õ·”óX„M¿¯ÉKL}+÷{ªDi–@­Ô¶búÕ¶r¬m1‹)s—2vqÚ#@ j[QѦ¶ÅÑüûpã¢ø÷ÄÔ·b–ÌcyÖ·”yK»8úìÕIÀ;Õ)Ûú:ôË–-+ôqÁ‚…ý‰v6ß|ó°óÎ;7.Y»vmxþùçûq#eü”± ¨ðΕW^®¿þú‘?—^ziÇ-]³f͸«ÙgŸ}÷§´Í5vÇYä<פl{ÉÛØHõ­Üï©rÚI î)ëCÊØ1o©ãç06r¬m©sg\ä0rµ‘@Z”ó@ÊØQ%uü´òý‰®¶…Ðüûpã¢?cK¹ ¤œ RÆŽî©ãçÛë[ʼ¥ŒÃxÐÆ4Þá(«¨"0öÝb¶Ùf›)µcöìÙ…ëc¼­·Þºq,eü”±¨øÆØEBSiê…^^~ùåÆ-ñ݆!oÆD#¥6Ô^ å|2vL\êø9 õíÕqPVmÎaLh#iëCêÚ“:~ã#ÇÚ]Sæ.eìÆ„6 ÷c Am{õoq £?»f6¢@ʹ eìÔmÏetäXßRŽ‹”±sÚÙïpÔS Là¹çž+<{ª ŽF˜ Ò\xRÆO{´?Ãøõûßÿ~¸úê« ];ãŒ3 û)ms]²C€@åržkR¶½ò‰ë¡Ã\ß"‹qÑÃàp+!H9¤ŒùSÇ’ëÆ k[êÜãRîÚ ¤œRÆŽ‰JXƒÚ6qf'û]ûÄw;K€@URÖˆ”±£_êøUÉQ¿Û1èú–2o)c÷;âå#àŽòÉ•–˜T ¹P4¿cÑdš¯ŸlÁQóõ½ÄOÝöÉÚ–Ûùõëׇ/ùË¡ù£×Ž=öØpôÑGº“Ò6ר ;T^ ç¹&eÛ+Ÿ¸.X‡úYŒ‹.‡[ ™@Êy e옆Ôñ‡,Õ¡*µ-ua¹úC`ê)ç”±cOSÇŸºfµïPÛ:ËOóïΛ×ÞYW 0h”5"eìè–:þ sÓïçW¥¾¥Ì[ÊØý·xùXp”O®´”À¤Í…bªïp´ÕV[ž±jÕªÂ~Êø)c:1;÷Þ{o8çœsÂòåË ½Ùk¯½FŽnÜIi›kìf#ûT[ ç¹&eÛ«µ©·®.õ-ÊSî 0l)ç”±cRǦ\W©¶¥Îq1L#W_t'rH;ö6uüîD«y—ÚÖy^&û]{ç‘\I€À RÖˆ”±£YêøƒÌK¿Ÿ]¥ú–2o)c÷;'âå#`ÁQ>¹ÒR“ L›6­pÍÌ™3 û“í¬]»¶pIó¿ÂH?eìB§2ÞyþùçÃe—]–,YÖ­[WèÉ1ÇÎ?ÿü0kÖ¬Âñ¸“Ò6רã @ Ò9Ï5)Û^é¤M¡qu«o‘Ƹ˜Âq)!H9¤ŒÓ‘:þ0¤¼Šµ-ua¹ú@ 7”ó@ÊØ±×©ã÷&[»Õ¶úý»öjdV+˜L eH;ö+uüÉìr8_Åú–2o)cçomL#`ÁQWQ D`îܹ…ç¾ð …ýÉv^~ùåÂ%sæÌ)ì§ŒŸ2v¡îÄÅE×^{íÈǧ=óÌ3…l»í¶áÌ3Ï ï~÷» ÇÇÍ5öXÛT_ ç¹&eÛ«Ÿ¹‰[X×úUŒ‹‰Ç†³ê rH;æ&uüœó_åÚ–:wÆEÎ#WÛ ôG å<2vì}êøýLµm“{¿×¾)²-ª,²F¤ŒMSǯrÞ&k[•ë[ʼ¥Œ=™¹óÃ+`ÁÑðæVÏj(°ÝvÛz=Õ‚Ö¬YS¸?.fûJ?eì±}Èm;¾ãgœî»ï¾BÓã*äN8!œvÚiaë­·.œkÞIi›kìf#ûT[ ç¹&eÛ«µ‰[WçúeŒ‹‰Ç‡³ê rH;æ&uü\ó_õÚ–:wÆE®#W» ôO å<2vH¿ÊåFRÛÒþ®½ÜlzÝ ¤¬)cÇþ¦Žß­é ï«z}K™·”±WÏœ€Gƒ³÷d}èµP¬\¹²Ð¦~/8š(~ê¶:–ÉÎÕW_>ÿùχæº{ó›ßÎ:묰÷Þ{wÔ“”¶¹ÆîÎETF ç¹&eÛ+“ )6¤îõ-rS4.'0„)ç”±c*RÇÏ1Ý9Ô¶Ô¹3.r¹ÚL ¿)ç”±£Bêøý•.'šÚf\”3Ò<…@õRÖˆ”±£lêøÕÏÞøæPßRæ-eìñÚŽÔEÀ‚£ºdZ?k!Ð\(üñ)õ{ÅŠëg̘1îsRÆO»Ñ©L6V­Z5ò1iÿüÏÿ\hñ®»îÎ>ûìpÄGŽO¶“Ò6ר“™9O€@µržkR¶½ZYš¼5êÛ&#ãb“…-uH9¤Œó•:~Nc"§Ú–:wÆEN#W[ ¤H9¤Œ5RÇO#ž&ªÚ¶éä‹4cLT¹ ¤œ RƎΩãç”Ëœê[ʼ¥ŒÓxÐÖþ XpÔ_OÑ T`ûí·/<éÒ¥…ý‰vâÇ©] ´ÿþû‡ø±]c_)ã§Œ=¶9lÇw/»Ø(.þúÈG>>ô¡…™3gN¹ )ms=eD7 0Pœçš”mhRºx¸ú¶ ͸Øda‹@]RÎ)cÇ|¥ŽŸÓ˜È©¶¥Îq‘ÓÈÕViRÎ)cGÔñÓˆ§‰ª¶mú}¸q‘fŒ‰J 7”sAÊØÑ9uüœr™S}K™·”±sÚÚ_éý 'ƒX°`Aáˆûï¿?¼øâ‹5).NZ·n]ãÚ£Ž:ª±=º‘2~ÊØ£íÏáë7¾ñpË-·4š:gΜ°dÉ’pê©§vµØ(Ji›kì° ²Èy®IÙö,’÷ÿTߊÙ2.ŠöÔQ å<2vÌUêø¹Œ‡Üj[êܹŒ\í$N å<2vI?z#«mÅ߇ý_¢ÈU å\2vôN?—œæVßRæ-eì\ƃvö_À‚£þ›ŠH``Ó§O‹-j<ýúõáG?úQc¢þð‡…Óo{ÛÛ ûq'eü”±Çu¤¢zè¡°xñâFëfÍš®¸âŠßmª—WJÛ\c÷âé^ÊÈy®IÙöò3ÑÝÕ·r¿§ê.Kî"@ l”õ!eìè”:~Ù¹èæy9Ö¶Ô¹3.ºIî!0\)ç”±cRÇÏ!Ój[Í¿7.r¹ÚH ½@ʹ eì(“:~zýÞŸc}K™·”±{Ï–¹ Xp”kæ´›@c=¶p&.X™ìõì³Ï†ë®»®qÙ.»ìvÝuׯþØ”ñSÆÛ‡ªn÷»ß k×®m4ïüóÏûí·_c¿—”¶¹ÆîÅÓ½”/ó\“²íågbêOTßÊÿžjêYrƒHYRÆŽV©ã"Syf®µ-uîê>.¦2†\K`XRÎ)cÇ|¤Ž_õœ«m­^÷qQõq«}ÊH9¤Œ}RÇ/+Ý>'×ú–2o)cw›'÷å-`ÁQÞùÓzãöÞ{ï°çž{6Ž/_¾<\sÍ5ýæU«V|\×êÕ«§ÞûÞ÷6¶›7RÆO»¹UÜÿÞ÷¾×hÖn»í~û·»±ßëFJÛ\c÷jê~ÊÈy®IÙör³ÐÝÓÔ·Önu­U%P/”ó@ÊØ1K©ãW}$äZÛRç®îã¢êãVû”!rH;Ú¤Ž_†/ÏPÛZÿ>¼î㢗1å^Ã$r.H;æ uüªç9×ú–2o)cW}ùä°lÙ²ÑCa=ö\pAØl³öÓCÊø)c7:YÁ{ï½7|å+_i´,ü_üâaéÒ¥]ýÙn»íFrÞ¸q#¥m®±ÇúØ&@ ½@•ë[Êy,Ê¦ŽŸ>{Ý=A}Ü÷TÝeÌ]LU@mK÷sçTsQÖõ¹×¶è”òû’”±Ëʱ稻€Ú¦¶åö{Éøw6eýI»îóþ(S@}Sßr«o)ëOÊØeþ½ö¬J\2­—flذáª÷ŸÔK ÷ 0^àÁ,¼»ÍÁ®¾úêñNpäôÓO7ÞxcáŠyóæ|D×[lî¼óÎððÃÎϘ1#|ýë_tPáx«”ñSÆnÕ—*‹«¬?ñ‰Oô­)_úҗ‘G9.^JÛ\cCr€dU¯o)籈š:~²ÄõX}ì÷T=¤Î­t( ¶¥ý¹³Ã4”zÙ0Ô¶–òû’”±KM¶‡¨©€Ú¦¶õ:ôñ{ÉØæ”õ'eì^½ÝO€@gê›úÖÙHiÕ ê[Êú“2v{Eg†P`ÞŒ!ì”. °Qà¼óÎ Ï=÷\¸õÖ[>úhˆZ½fÍš.¿üòŽÅûSÆO»Uß«pìg?ûY)ÍHi›kìRà=„¾ ä<פl{߀ûH}›´ŽãbrW¨—@Êy e옥Ôñ«8†¡¶¥Î]ÇEǪ6¤@Êy eìh–:þ óÒîÙjÛäÿP¤Žã¢Ýxqœ@RÎ)cÇœ¥Ž_Åq1 õ-eÞRÆ®âxЦtí?3©ƒgúHµ\B  ^ßÚ1>ræÌ™aÑ¢E#¡v÷Ýw‡µk×¶mÉ¡‡.ºè¢ßI©ÓWÊø)cwÚ¿²¯ûö·¿â[ó÷ës¿ë®»Ž —Ò6רã @ ™@Õë[Êy,¢¦ŽŸ,q=Vß&ǫ㸘\ÅòPÛÒþÜYÅ‘0 µ-º¦¬?)cWqLhaPÛÔ¶^Çô ~/Ûœ²þ¤ŒÝ«·û èL@}Sß:)í¯D}KYRÆn¯èÌ øHµ!Lª.'°zõêpÓM7…åË—‡Ç<ÄýwÜ1ÌŸ?äc·.\8îž©H?eì©ôq¯Mi›kìa̳>fœçš”mæœwÒ·”¶)cǾ¥Žß‰Ÿk¬@Êy e쨖:þ`33ا§¶M?eìÁfÅÓ èT å<2vì_êøãu©mSÆO{s­O†U å\2vÌGêøÃšóNú•Ò6ר¸¹&kyÓziþ† ®ÚxÿI½Äp/ @€ @€ @€ @€ÙÌ›žMS5” @€ @€ @€ @€ Xp4ðh @€ @€ @€ @€|,8Ê'WZJ€ @€ @€ @€ @`à <@€ @€ @€ @€ @  ŽòÉ•– @€ @€ @€ @€¸€GO @€ @€ @€ @€ÈGÀ‚£|r¥¥ @€ @€ @€ @€.`ÁÑÀS  @€ @€ @€ @€ò°à(Ÿ\i) @€ @€ @€ @€ Xp4ðh @€ @€ @€ @€|,8Ê'WZJ€ @€ @€ @€ @`à <@€ @€ @€ @€ @  ŽòÉ•– @€ @€ @€ @€¸€GO @€ @€ @€ @€ÈGÀ‚£|r¥¥ @€ @€ @€ @€.`ÁÑÀS  @€ @€ @€ @€ò°à(Ÿ\i) @€ @€ @€ @€ Xp4ðh @€ @€ @€ @€|,8Ê'WZJ€ @€ @€ @€ @`à <@€ @€ @€ @€ @  ŽòÉ•– @€ @€ @€ @€¸€GO @€ @€ @€ @€ÈGÀ‚£|r¥¥ @€ @€ @€ @€.0cà-ÐèJ`ÅŠá}ï{_ãÞ<0\rÉ%} @ Gõ-Ǭi3L$ ¶M¤ãä( ¶å˜5m&@€ÉÔ·É„œ'0^À‚£ñ&Ž @ uëÖ…'žx¢ÑÖ§Ÿ~º±mƒä* ¾åš9í&@€vj[;Ç  @ Wµ-×Ìi7L$ ¾M¤ãÖ>R­µ‹£ @€ @€ @€ @€´°à¨ŠC @€ @€ @€ @€´°à¨µ‹£ @€ @€ @€ @€´°à¨ŠC @€ @€ @€ @€´°à¨µ‹£ @€ @€ @€ @€´°à¨ŠC @€ @€ @€ @€´˜Ñú°£t*ðÔSO…ÿùŸÿ =ôPX·n]˜?~Ø}÷ÝÃn»íÖ6ÄúõëÃÒ¥KGî‰÷¿öµ¯ sçÎ tÐÈ×¶7ÖøÄË/¿î¸ãްbÅŠðóŸÿ1bûúhƒ%~Þìßþí߆‹/¾¸qÌÆ«W^yeX¼xq#¾{Ô…^fÌP 0vÔP@}+'éê[ÿÕ·þ›ŠH`XÔ¶r2©¶õßYmë¿©ˆ†E@m+'“j[ÿÕ¶þ›ŠH`˜Ô·r²©¾õßY}ë¿©ˆy Lë¥Ù6l¸jãý'õýª,?ã4.*j~m¾ùæ# bþèþ(LŸ^|£°gžy&Äã÷Ýw_óma›m¶y‡™·¿ýíãÎÅÅ2ïyÏ{B\ 4ú:äCB|+¾aµsŽýþà?>ùÉO†Í6ÛlC\”?JmåÊ•s£Ÿ÷s4ì¯Gy$}ôÑn¾ùÍoY¸Ö8ðÿ_ùÊWÂ%—\R8?ð‚ .héZ¸ÐC)ÐnÞUßú›îvÎñ)ê[{kõ­½3´h7çªmíͺ9ÓÎ9ÆRÛÚ‹ªmímœ!@ ½@»9WmkoÖÍ™vÎ1–ÚÖ^Tmkoã  ´›wÕ·‰Ý¦z¶sŒ£¾µ×TßÚÛ8C Àõ©Ðj±Q¼ð5¯yM8óÌ3G>zmôÆø.>ö¼{Òè±n¿~ç;ßi¼3S·1ÚÝwÐA…Ýwß½Ýé®ÿáþa8묳ÚÞ¿ÓN;,¤9é¤MëãÇÐ-[¶,xàmïëôDŽfÍ}ûÒ—¾¾ð…/ÿÞïýÞÈ·æÅr…‹ì PKõ­˜võ­èÑÉ^*³æg«oÍ"ö h' ¶eRÍÓ~v+:w³§¶u£æõPÛŠyWÛŠì¥2k~¶ÚÖ,bŸ‰Ô·¢Nª¹ÚÏnEçnöÔ·nÔÜ3Ì svõ-‰ÀöÛo?² h¢à­»Äoâ»ÊLôÚk¯½ §×­[ž}öÙ1õúúë¿þëÂǺõoìýŸùÌgú¾àhöìÙá£ýèØÇ´Ü>øàƒCÌÉØw9zê©§Z^;Õƒ¹™5÷ï²Ë. —_~yáðñÇÎ;ï¼¾,b+¶C€@öêÛøªoãM&;’¬ù™ê[³ˆ}Ú ¨mãeRÌÓ~vï<Õ#jÛTÅ\O ¾jÛøÜ«mãM&;’¬ù™j[³ˆ}&PßÆë¤˜«ýì6ÞyªGÔ·©Š¹¾ÅÏ‚ªCõ‘@qõï¯üʯL¥Õ¡£Ž:jÂ{âÉvØaÜG´=ýôÓ“Þ7Œœ|òÉaë­·î¨kÍ µâ"­º¿â»5/6:ñÄ-6ªûÀШoàôñ”úÖ¦úÖ›Ÿ» ÔM@m+'ãj[oÎj[o~î&P7µ­œŒ«m½9«m½ù¹›@Ô·r²®¾õ款õæçîáðGÛ[=K$°Ë.»Lùµ¯}í¸kvÞyçqÇZ˜6mZáðK/½TدËÎ[ßúÖŽ»ºí¶Û®}î¹ç ûuÛ¹øâ‹ÃW\Qèö>ðpöÙgŽÙ!@€ÀXõm¬Fºmõ­{[õ­{;w¨«€ÚVNæÕ¶îÕ¶îíÜI ®j[9™WÛºwVÛº·s': ¨oåd_}ëÞY}ëÞÎÃ/`ÁÑðçXû,°ÓN;u1.Ú°aCãÚùóç7¶±ñÙÏ~6¼òÊ+IýÆ7¾±ïq;uŽž9sfáùýêgnfañâÅáÊ+¯,xÄ}öÙgÜ1 0V ÓyW}«6õíNcdõm“¯ú¶É t:çªm›¶º²Sçx¯Ú¶IPmÛda‹Î:sÕ¶ÎM[]Ù©s¼WmÛ$¨¶m²°E€ÀÔ:wÕ·©¹6_Ý©s¼O}Û¤§¾m²°E •€G­T#0Àë_ÿú ζ?µÍ6Û´?Y™cŽ9¦„§ôï³fÍê_°.#åfvÇw„Ûo¿½eoÏ?ÿüW¯¿îu¯kyÞA¨oåŒõmêÎêÛÔÍÜA€À«j[9#Am›º³Ú6u3w ðª€ÚVÎHPۦMÝÌlPß6Y¤ÜRߦ®«¾MÝÌõ˜^¿.ë1î¦OŸæÌ™Ó}wv$g̰²#¬1MôÎNñcæâ;6y @ •€úÖJ¥ÿÇÔ·îLÕ·îÜÜE îj[9#@mëÎYmëÎÍ]ê. ¶•3Ô¶îœÕ¶îÜÜE€@ê[9£@}ëÎY}ëÎÍ]õ°à¨^ùÖÛâÛ5z¥àÜ»ñi§N9å”B ›o¾9üË¿üKá˜Dón9ã€sïÎê[ï†"¨‹€9·œLsîÝYmëÝPu0ç–“iν;«m½Š@ NæÝr²Í¹wgõ­wC†SÀ‚£áÌ«^ PS¸JýsŸûÜÈb£øÃaÞ¼y‰sÏ=7¼ð …cv @€@ÕÔ·ªgHû @`ªjÛTÅ\O€UPÛªž!í#@€nÔ·nÔÜS' Žê”m}%@`¨fΜ¾øÅ/†ãŽ;n¤Ÿ[l±Eø«¿ú«BŸW®\/^\8f‡TY@}«rv´ºPÛºQsTY@m«rv´ºPߺ•s_fÔ©³úJ Î'tRX½zu‚SO=5¼ýíoO{As3;ðÀÇåáðÃï|ç;Ã÷¿ÿýåµ×^-Z=ôÐÆ1ÈU ·¹º ι™©oU5Ú@€@™¹ÍÓeÚ´{Vnfj[»L:N€À° ä6OW!¹™©mU5Ú@€@Ù¹ÍÕeû´z^nfê[«,:F (`ÁQÑá¸çž{ªU«’ôïé§ŸNwÐA‡ÅìSŸúT¸í¶Û‹/¾Ø =çœsÂ7Þâ» y @ ga™«ËÌÁ°˜©oeŽÏ"@ La™§™M]@m›º™;ÈC@m›zž†ÅLm›zîÝA€@>Ã2W—)>,fê[™£Æ³ª.à#Õªž!í#@€@;ì°CøøÇ?^ˆòðÇË.»¬pÌÈI@}Ë)[ÚJ€¨m(¹†rPÛrÊ–¶ @€@§ê[§R®«ƒ€GuȲ> P{?øƒ? .,8üÝßý]¸ûî» Çì @€œÔ·œ²¥­ Љ€ÚÖ‰’k @ 'µ-§li+t* ¾u*åºað‘jÞaý#ðÿ·ß~{2‹Í6Û,YìA&³˜£óÎ;/wÜqaÆ #¬ëׯñm¿ýío‡3”ƒAŽ5Ï&@ {aš«»W˜ÚÃd¦¾M-÷®&@ aš§Ë&3µ­¬Qã9”)0LótYnÃd¦¶•5j<‡²†i®.Ën˜ÌÔ·²FçT]Àÿa®z†´@ŸfΜ٧Hõ 3lfûî»oˆ+®—,YÒHâ½÷Þ®¼òÊpÊ)§4ŽÙ @€@NÃ6W—a?lfê[£Æ3(S`Øæé2ì†ÍLm+cÔxe Û<]†Ý°™©meŒÏ @ la›«Ëð63õ­ŒQãUð‘jUÏö @ §vZ˜;wn!âå—_|ðÁÂ1; @ 'õ-§li+t" ¶u¢äÈI@mË)[ÚJ€ ¨oJ¹nX,8ÖÌêZl¹å–#£6öÔ/ùËpÎ9ç4>jmì9Û @ õ-‡,i#LE@m›Š–k  @ µ-‡,i#LU@}›ª˜ë‡MÀ‚£a˨þ @`cŽ9&vØa…«îºë®ðÍo~³pÌÈI@}Ë)[ÚJ€¨m(¹†rPÛrÊ–¶ @€@§ê[§R®Fi½tjÆ Wm¼ÿ¤^b¸— @€ @€ @€ @€læy‡£lr¥¡ @€ @€ @€ @€/`ÁÑàs  @€ @€ @€ @€²°à(›Ti( @€ @€ @€ @€Á Xp4øh @€ @€ @€ @€l,8Ê&UJ€ @€ @€ @€ @`ð >Z@€ @€ @€ @€ @  ޲I•† @€ @€ @€ @€¼€GƒÏ @€ @€ @€ @€ÈFÀ‚£lR¥¡ @€ @€ @€ @€/`ÁÑàs  @€ @€ @€ @€²°à(›Ti( @€ @€ @€ @€Á Xp4øh @€ @€ @€ @€l,8Ê&UJ€ @€ @€ @€ @`ð >Z@€ @€ @€ @€ @  ޲I•† @€ @€ @€ @€¼Àÿ„¸Iû ,IEND®B`‚blis-0.9.0/docs/graphs/large/l3_perf_has_jc2ic3jr2_nt12.pdf000066400000000000000000001031221422157504600232630ustar00rootroot00000000000000%PDF-1.4 %ª«¬­ 1 0 obj << /Producer (Apache FOP Version 2.3.0-SNAPSHOT: PDFDocumentGraphics2D) /CreationDate (D:20190328153319-05'00') >> endobj 2 0 obj << /Length 3 0 R /Filter /FlateDecode >> stream xœÌ½Ë®m¹•%Ö¯¸M»[|?n8’ಠ™. p£P-•RigF¦+”€Qþz1ÉEr’;nèܪ¬8±¸×âkrp¾çÿÎ~1øß÷üW®îË~øÎ¼¬‹òtþ…Çÿý»ô²\.òŒÿKˆù‹ á‹Oò.žÿðõ¡âiXc-þ6ó6ýÓwÿçwÿŠÞÿ„ÿþ<›?þñ_þñ»ÿã/ëñ¯÷›ãç#Æïƒ“¿þEþʉ3A£üñOßýÅÆòa<ÚŸ¾û/ÿ?úoß¹/ÿýýßhJ!ï¿ü¿ßYóå?½íûw—úÁ4~˜»Ñ‹óx‚òœÖöÈ¿¼7ÆØâo ¡$tá}ðÑ>CÐîa²,º~’ñw­µØükРžøÕ¯í›^Äßÿ#†ÓúúÓW†³{YSv¯FW^Åg_\$ù»ßOxùÞÙWÄ׿üþ‡/ÿårXùÿùËýòûÿøÝø½LýçûªZrÖ”>ÒW8úºuvHÜØÍ.ŸÝu6iÈ]HrƾJ>;íïulSyýö§»õñ•ÜÙo|±cã^g·òð>Õš—wè1Å›ä$rÒ^%'v<ÈIõ{•œ¤ÛANºß«ä$wrÒÝ*rúy\·Ÿ.® ¿u/ãˆë%°Æ®cú‡/Õ ¯Á\’ÆÆóîp_Æ%õ‹z1·P(5Ùw7Ôè%ü¢^ ²·¼‡Ïåš}¤_Ôø•—ÉœR-_館N„—(¯¾@ñß›—‘0àïg‡ËHÖ_X–)”àp†ÜàÕ+D½wþH¿bÉo~ýÛ¿ÿ‡ßýêÿöã!­ìÍWW G+¼’/)| ì¢ÍÙVî¥'·ñ}h}ÿùOüᇳúÌ™Ÿ„ð‚1a’_œÃ\²C»±„t[Êhs©ê°l4n²£ôR"N–4pMÁøyp¡¾Ø"møfâz'²p4›£üÚ*¾YÙ_åÙL/ã±þ Â6|“cÁÁÔø—«)–hä›ß,쯷ôª Ð rBQ8s,¤cm~› ÍJ¾ñÍ“´9œc}–6|“cñèÎFLÏG¬ce“Å'ÉæEÊ ºÂ62‡ŸšÒ}Ëí«Z00iÚçÄ€ÅÄÐ3%2s(¬2ß %&0ºAÚâË>+fÃË,°½NšðIÅao9Ì+VÉËì@(™;T@ ü¤ËأؚðEŽ$Z'¯î0`'³óø$7(‘ÇF[Î8¶}2àJãH¼‰í½H¾¹®˜½åeG“ýe/mEßV„_¸AÙ;™ÞÇ‚zy/â› m+îC“¶B®Ûâ¤SbûV·‚•ßWÐÖDÚð­‡`­u€d,TŒQÚð-¬w_ÆàMaXà_¨H ïYìfJFv-c𶬴E“¢ÉEÖ#“¶Ñˆ±É0öÑ•F%8àô`·²wjƒw(8WÝŽÚüdÀ¯ÉjÔö˜–ÃË Ñ¨¶ ˜ Ÿ¶ñML÷cNlã=[úlS…w<û€m|\jÀ÷lsê{ê9`m€ |&ž°û‡ fŸü„m "ð^Œ&¸ÍŽ@%©Á¼‚m,1‰,–†y ¶9/‡F é€m|’TÇËà€m|ÓeãËÛø&v7H`Û~#ø!+3×°íd^°®)æ¶Ñ–D<ÃÛø&¸!°rú5nã?i²ú·9N ®A{à¶ð,ØjÜÆ7#/x/Ä¢qïYà@Ú?¸¡Gl&¹‚ⶸ]¾ø/î‹ÿt“‚\Rºòf…nœ l ö×ÙÉró¨bz1žÐeˆ@ÝЮ ÝǸ@’·t; ŽugÇvc÷À2ù~,v;\ؾÁV+ìΰp{6^dÅnt‡n=΂;Á»â`@¾Ã6Ÿ,wÔeü¿êNðÆi—Vš:Hƒ7ú#¿ä“=ÁôG·áÞüè9út²Ü:Ø ÛÀT7ÞÃG’‰ö xã Oé/àÍqa¹PàEçðzòÜÎÿ,8om¼=Þ‹ €ò»9„ì&`âw.Ô»)$à‰kȧÁ›Ë¨þoœ‚’rŽ7ðv/ ÝàœŸàí(\¢É7®A·|§¼o·BoÁ©jj²Bo™_J´w 7¾™°Ð8çÓ©;ÊÀ>Ÿèmã0p[»½Áƒ£ ´L7¶ ‡Ò‚,Ê;ô8]Þ›ƒéæn¾¹u'z£oÙ]gOô†IV1—x¢·ºÆ7ôÆÎºS¡7V;@ioЫ‰åò>¤½!§ ·ìB8ÑlQû`âÉus×yù6 íAo<ÀØåþåÚÉ_†Þ˜4ÀÀ“·óz'"trrÂ5và,`É´›wÃnH´ø\hlŒÆn²FdÎŒ9Õ%À`|<@òˆv‹Ö ?5þÄn"+ð£d¹ö6u ™È|å`»qkíAøo´%€nô¶é tã6ðÑù`N¾;p¡5кÐI¡±¡Ñ Üü ¿/pSmƒÍÇ1Ìpƒô2r8L>YÓvÓ)ÜvrÌð¬Æ·­ð7µóLnó„àjµm˜ZW‚aBRÇe~2ÝèÏr2]§£ÛbçŠ7A,¸) &Êop›z Æ£GYq¯ùŠ{ê‰Ûüdtµ6…ÛäA¼¬NÜv¢G¶±)â4n{âvN½?Û r€ ¤AwrÝÀmOýEçÖ•®‹Š?“oT¢”%¸B t‚ n£Í€Â1×|à¶!âÜ4›Ç¦,¡&Á•·-¢La¶—R–€–nâ&olÊ’Ê 䶤¾Ø=Çÿ8´%ø&ï$\Ϧ-)´»GkK´v&´¡ƒiÉ&>Èu7_ÛrL— ÿj ¬zÕÃæ]ßWÌbµ;{Œ‰ÝèT'ž$‘¢[›Ööèº{ è~÷°Ù]‚š²,º~rÝÃFM¸íºùª‡Í_`zƒŒØf îÖ».5ž0¯ƒ¿ˆK5ó¬P¸²{É-pÏqg™(@Ú•t‚Õé]ˆºxÔ¨~ïº@ÔÕ£F÷{×¢NÝíEš•j ¬Í¦^$'ép“îô*9±ãANªß«ä$ÝrÒý^%'鸓“îöc5Ôay(K¤k5º“[5º—[5ª—K5ªoò¨ù‡O¡#€T²+?ã¯bV•?ÿ{þ*¾nþ* PQøU³ª_j¦H ñ˜2Q ^cH´SAVE卨m̯b@¢G Tl ½§·C}u bc ´•ª`umm›·J¤®W$¢à”ö%a££zSÚ”ö%qE nU¿x›Ôöˆ^04ÃQ—g-o ï“§p ‹GžÅ{X-ü¤ …ª!ϲ;ÈêT™²-Pë=äÙ@¿™:IÛꬎ4ÒëD¤ü6g“)·×¢rV 8ÞÑaϲ´)o°«X¬"_bÿ©êò,ÚÈw+RHøæ”gý«fçjÓj8†R íèê•mÍ.£P›jë’ vÕØµ /qӨ͈Äå,jY Û úAšââÛô“ Úv"Wئ(Ðó´] ¶i‘òôKõ€íÜtx¡Š EÃ65ÞdÆš÷˜†mÇ…6)øv»¬°í=¦ãM‚h~À6Í9„C' | ÛžfÃýòló6©»¦ Ö°MM@M¡qœÑ°íɺÄÇ.«aÛe^Õ8BͶåäFú0”¶½£ª1XסY)Î3‘‚f7a[¼… ²ö€m^àÀ#ì±;`?½ „öÀmO 0õ6îÀm¬G`šªWã¶£š­À¡·=Ç…äK8p›ëŸÀ„dQªkÜæžVljpõÀm:mnhÇn“±£RÝ5ð²›ÁTŽ;UnpÛJH*°íÄKÕˆ¯ŠmqÊ »i:0[†›,¤ ¶mÙlãzÕ”w̦[I®Ž^Yf³7`rj¦(Ùx/˜“X·4dÓöH·‘Ε­3`ž ûvC(ĦïA 2bTֈ͑€cóÅЈíè œc¿ŠSûµqà"rú˜ÔøaK§mÞàØ 4¬vv¤B@”žæµ£Çl°mÞԃמ=âîÉá`¶±Wžz‘Ê7f›fC0â6ž¼6v‹Ž,¹U ü )Ôîcœüª…˜íèöïD"O¾yœgjPp® [eÈß"ß$¿ªab1לD£˜¨Þ€ô– ç_i3£RFÞ «&Pêq¢v£IŠ=¤)†öÈ £RCò†˜Ý”)6óŽ6 Òn‹Ê”¶æoÞ/6câqžÒªƒñ4â%6X&è$ÿH´twÅH@2”¤Tçž–º\(H¤ù‘h1”jÑY*­IÅyR4–+7󮊬6K¨}âE)ΙQÃcE–ʦ8Çèé@/«RšÇyWF&^¹f8KU©`áõ›*>9u‘‘‘h“Är§ú¨`(ˆ‡fÓȼÎj½@ ¤ Ò¦T0Ž‚†Ã DŠ¥jã¡Vé¨FÚ^ä=»yœg“l7}e«T0Ì,@wíØÚðÍA­TÁ8n0—1;¥ÁáÀÖØd[ótj¥ß~ÈAæÏ&¥€±âÚ³¨25ƒ\©œ Œ{k2ºWše}êŽã¸U´†ºËвIä çô÷Ç2{Ùš”Ãy%fP¥Ì<( ŒÅÖ3ÈFÎ0“,&õÀ¹ŠrñûECÝS5µ¿æ¨40t’wÑ;Ñc ÛUS¨­¤»¤40UBJI­Mi`*úf`[kËJÎ02lI¼2rV@ È翵)í¹£Æôt  ›êèº. ›[ϵMñ†;·£6c…§a@£6­/ÙÓòçwÔvŒ¦5ÙRµ£¶³Ø‚.šnV¡6Û°>ÎEÑ£*Ôv†AÆžAKn‡íT_TË¢v©ÃçºFWÃ68ZÁư- OÄ¿ò‰ÛÉ¿¦IGÃvÊ/!<_ìÛ 6ì#ÓÛ (Ï FØ^ ÛÉa 51,c‡íÒ3L1"vA ÛWå0ÛéѸ+†ÉÝu¼ÆíÈhS¬xÌÔ¸¡Øqöиè¾ãl·¥hàXMCsœ ŠîpÃîÜ›êÏDjð¥€;Ð’[0“7ÀÍœ=÷pÂÓÀŽ2ÃúÛV¸¦pÆó¯q;xL²tƒ‡†mPZ*5tW-ÛAv —XÚnÙÁÜâ-5l£)0‡CK«a;0?-ƒÓ ÛLHæ³uù¶1oŸåkØ¢ ”tÀ6Ú<ͤîDm§&ù\ÔFNXƒÖÝŠÚ¾23Gàþ¨í™L&FlG=PÛ“Íà:‹¾]£6¦š½!Jŵɗ9 OݸFmfš°ÖÔ~y*Ô¦5ÌËuÔötŠ3Þ ­ “™®¹”ø1U䇞¸q·€°`6íÀ ±€w ~&Ô§€›l³ƒTëÁnãAíBcšÝ&Ðuô!œì6ÁZú±¨Ùm’{ ¶+^7 "ì ¿MÿÀoöáà )©Åxm ·¿·Ð1QsÜ牮åä¸`VËÝî:ݸÏC®[ÔèÆq U^…tã= +èf5ìelAÞº1¦/·âåô®dV™ºiå‹"O<¡›ù ®O]³Ü ¢Ä¥Ü¯rÍsKâ( W˜Åç¦åi^`ÏmÑkbÆ…ºÉÌ¢,ezÇs\Ù¹“å[Pã*ÂÜÁr3“\'ËOâ£åùd¹ÉÌ‚ï‰ÑÕ<7;Àºr°Ü‘zHˆ /5ËMÖ`Ûm YnË6 …}Ãr“uvƒçÁrSðÇÞ‡“åsÁ,Ö¶*šåN4ðZRð¶L'Å$Bîd¹ùzè™ ¼]è™&6–;’ÍÍLëq²ÜÔ‹¦BSÍrÓigD¨ÞXnlf*¹¶Ay3zb-™°%,7®;\ÊÙ5iC7ÇÒ,Hƒãfî çE{ö FÏBï“–>ؘGé/ŠÈæ‹fÏ·½ßP]öyü°LíJ7¥î†ÏíÑu«c q7|n®AMYV]?¹nøT–è'ßbøŒ¸{psÐõœ¸vÕðI7zÜŠ™a2²Þ6|Îó:€áJæk3ŽÏåóºÌ'~†éS:¶*ÝéU[;¶*ÕïU[•t;lUºß«¶*é¸Ûªt·MŸ Ý^>ÃöÙz¥{½›_,^E©Žï¦ã—~IéŽïæão6¾FSºßÙ?)Ò¿hdŠŒ+ºeÝz¹eݺ¹eÕÝ\²êNnAAO¢(M4#~ÝšWè¿ÿx/è¬Å¦MÊ˜× ÐÌj¥¨*ÊSR{ aµB˜3¹@š³Ò–¥L¡{zTU%šÕÊdªö«Ä°èdÓ:CàmNÉ%æÕêèhk)é±-™E'“_Á9Óu%>Ä,«EìT%åU%IÕLNt…”0%\&Ÿò™:[i ‹JÆUH×ÑÛ¦h‡X¸ªd¨Í5l£L¼˜U%ƒ6ƒÍ÷’6¬”°¨dDÍàJË» XX52ª= FœÔK5S#Ñb(7Êk5h?tš[«5íµ¼jdÜ‹Îùµ9Cæ_52L3Å §âÛ^MX52hÃ’7=UePàªaþ2´qâèUgÝ’hŒ{@·ƒ©¡•=‚ï7èjó«™®*œ£Ì¸2ØÐÇ -°æ@‘àŽÊ¨ y>gZîÄCÃvñÔ{›# Q›È%bµS Ò+‚bC±'h3ï]5-ƒ·ÆìÄhP4ÄhÌÆn²Úo…ÙLÖ‘f^pFcv¢9'®é™5fG¦÷N-³ƒù~'h.—ÉѶ-XAëã|zRkjÐŽ¸pëÔF]´c¢Þ/ûvfÓÒPX¸á„l¦Û¢-‹ Dc6i¢¡çJ>0ï‘b®ò³i‚KØŸØÎNmPîßL>ðmÚ8qªOîmÚM«+¶•¨Ð ŽL0ô³h‹°$ç; ¯ g…áõþh&5 \¥´™%Ûæ›YL¡6> ¢£òº¨íYô†E,Ä”©Q;0ÜŽiX¢PÛó 'PhHj㛧ô aÚ&…ˆ–—A£v vÕ’šÓ—Fm1QÛa5l{jœhR1e‡mzZѸXk9`›¯Ñv’Ú¥¤`›¶L#YYÝÛb“)5lË0sÌÍNÃ6¶’9ðks©Ð°-$Pˆå€mš MÆ¿„’ºHÉ8¤Âºr]ù¸tCnÜñ^h.È£[ ˆ¬œü6Ñ9I»ŸäÎâ²ç6lì¶ã€\b8ùmgâs¾4r"í(÷  Ç™±q¶ 4» ™3PJk½)ìô9Ä^Õv½(즧€Çìšw”Ænòé8–Åô¶»™èºÆÊ,ïømWˆ}!ØMGš9[$æÆp3Ý;PÑÛ îL--8ÙêO†;¼pô˜Š|2ÜèPr°'Ã͹Ò]Ãèm ÏŒ ¹qÕšã¦Õ«ß 7¹OÐwÏf¯ÑÛI=ŽÄÒ ŠåÆmÌT6åËx­ökB¡7-zt‹‘ßXnæ•7L9²Ü:`wc¹Y@É<)]7–»²ÐP|Ý妇`nœºb¹U4âÆr“ù÷äÞqܸ§miÉ<6Ž»ò>xD¯ƒãfær²K'ÇM::·÷4Çž,pnÜ¿æ¸qç‚™ ýzÕ,78 Üã”è–›åbõý&Ô,wÂZ‚Ê›=ùd¹YKÀØ»™æÖ{þÆr3CËc¤“ã¶ìŽâãŽ;Râ«®tXW·#¾ðnʺ-ƒ¬°N¸“Q—1Íù/(¬ŠÓ¦%pÐtâó¸Vy¡njó¥kdþî·ÿÛï®9¥'ÜöÌ­/Jl€9VÂà¿X5Ž~8ÿ@&õ^Û†úñSeúp+ù"ðŸšêßÿ?ü׿ûíÿúñé~Ô«SMÄâ%K¸Ê}ÚkÛ·LÛËQ¦=Ðu Ç´ÿÃÿõ§?þë7Íùƒ>Që´ËhÕžTf›¶jû–i3—ƒeé;{è3ǬÿÓÿþÛo ë_6g‰í·LFlµjû÷ËÝ’(λͿ¶2ñl¿Y'þmÿw¬ñqq³»Ò$gpx€gj۳떾È<¿€.7¡Ÿ} ÖY·¥×®;:è9÷!¨G¿¼f<Ów½“½9QÜt|È>–¿ ¢Ãß’ãÃzŽd\ÙÑ%®Ÿc5£(¹Ã“úúf—³t¼îö²µ:.þºçËæê¸z@l=_¶WÇé±u|Ó b¥`+Žï•m7 «¥"„¥»½KX"£ÂR=ß%¬–Çk–îù.aI×aéŽ?æ ‘ësÖA9Ü+&¿õrËbëæ–'„îæ’'„îä†'Dn!•Qög\!Âêñç{ÕÚ UžLø%‡öÏÉ÷Hü¤7 ¦1…¥cfº[)wJI¹BPN³O¹c4*_ˆúŠ…Ù.Ec S‰ FäyêxJÄÓЃäåcÐín´B£ò‡ð/fhí ¾Õ!`@YטPóÉÈÚ"šO>Mm¤Ñ¶yD`U³maÚ`m•KD}¡c–Èk–Ï$9_CG·xZqúg©ýtÏÝÃXž˜íP>kÒÒÒKžé Ån¥ÞókkKb”•m¬wV+Sw7êj+Žhi¶ŠZÆC°@‹H‘V ÝSñ…aB½VJ®éÈ@,)ö~ÐRi!­/kKÞµi,;Üâm­¨R×€[ë¼sÍLb%g*¿Xt›Õ—] c<ÙæDq‰Eê9±m«ækZfIÎ5oA–VÍr”­²(Õçå!c)œfèøÜȆš|ûб(W CÁ}oT[š&ÜS¶ÓÒ¸xIÄC›]KàkYùÔ:¶FŠÑ2íakÌ’®¯Ñ1ßôL-ÛjX‹Áujm‹m«´ðN½-ƒk±jѵõ¦Ft2µ}n¤ù´ÌŸ°¨nW” ¿}5+Ý-™h¬ìÓä!”̙Бcë“jÑAÉ–‰ŠIݶM³(õ-“cb’-w•þ€Z@:-O ‹ï½ê¤dÉÒü”ùµ4õL .Kd3E°i_­YW*cM1†W‰–'«NRf‘¼š”°Kã’Ÿ¤lÖØW4®Z\†2e L;XôXreð£Ú‚c,]Äü dø"²hkÌÓß)Ù°¶xr-£fç)* ‚¬ÊÍðñç¥6z’ò¡ÐKehÆÛ5šÓ@ÏtÍT¨µüèY=Áø¶k;ÎKyl‰žOœ¯-yq‹®Ý`tby »†G æñÃZÐ*'ÌçJ_›â#¼á|¦ÎÇÜ5¨Ò8Ÿ¹ÁŒ¶2ùÄùDNªd—Š=q>ÓFŽ+©÷©qžñ⬼Þg©q>ñ¤ ®Ã£Âù„K@²Ó¶[Iá|J’7´”Î3¾»D—R?­ èÛžAò-î}zÂÀ¥Úúèceyÿt©p>Òo¤Ý"G7œÇ‹>Ó-½ž0ÏX–u~p¹Á<£×Mz Öo8éÅGÅOœ,CœjK¼Á|$_.j‡\ó ®¤Ú æ+#âb áDù(у¸û-¯P>$ ·gbÏåéÂí­1ž(Ï€õšp÷¤Qž^63-ȆòXŽR3γyƒòAÊW¤ÜY+ò¬'ë¥o”ByƘƒÓÁöÇåYÀ4 ±o(˜[ø2w <¾Ê”çÆw¢<“"N· åƒC×̹ÊÓÆÑ\Ú¨J£<A>6[ýóhdDr0ý~P0ïqRbe wÂ|`æwPCK Ó¥VúÎ×§ ÃÍrÂéék\äµs"½aZœRç<ÒSVaz܉ôânáŒÏ-­ÌÎÒGïÍ`ò[–’(¾ÞάÆz¦{ˆ$[¬Ç!¿šmpþ O/–o“|‚=9t©¤ì=ÓHЬÓ¦ž. €Vãe{¦fb‘âØO´fê01Š›ë ö,jN_UŸË ötÚð¬{÷•©/¬2ž“ïH½”yÇ™z öd¿YÐÂõC«Àž9Ιû¡/íÆÕgÖÆÖg¢Ðž® pîÞ\qõ¢Ê޲ ÜÓÿ×]nžî W ë^ó;W_¤z­}ä$ÍÕW$ZŸùi®^Û7\=ï$ñÇ/o¸z–NØ—GP\=}•Àµ¸~¡ï\=Nw¶‹QŠ«gÊrVàì_Õ\= šöË;¼gvhˆtX´ú†«,‰Á$÷ù WOç–Žè·½Â{ÖÑ5ìLGmÍÕ;BäóæŠ÷àw33rt†G3õt¡HÆ.)¦¾y̦Ü?ªàc%=Ko™zHÄž&N¸7Ir£ÔÜ¡WÁ=á½Òg¸7j®^Ž:+h¿{žA&poe]6¸7’?g¶ØÆÕGPwæ÷>T=~Øp±œlùAj·Œkü«×~Gkûë’÷MïW”ª}?,s»Ñ…Z(óœØö(Š:·¤kS¥vÔÜíCÐîar[öíQ™!£Ÿ° }úÑ›!ü¬â–š`V^¡Û¿A@`µ1àß_ÝZ‹Ç„gǘ‘𑾮[kiOt¸RO¶#Âí3»Î'Mƒþ]0 LZó”æÞ{^Ûî ÁÓÑë9ÛTÛÅ!œËî¯.»ÿʲûû˾’´™(|Ô¤C=gÝóçÌy#55„O 5¹ì÷HM:üʲ¿%µŸ¿$Ýqaˆp—þþ\b¡wó_Ïœ«;Iô§Î.mf?m›´¿¬—X!ù”¯Y@?l3Ö½¸@}aªÔÅ}¥ÿËz1TÉ”B…Íáôû“†iq£c¦Õncß›—‘ f}¿ØçPÖ_0TWReÛ$š÷,%ŠBÀ#IøWlCùͯû÷ÿð»_ýáß~üã1¦Õ•í«kÀJýãîªK}ÚòTЫ£úÖ6 Ày–K‹±ƒJ©F2T°xÉÞFÕª“¦–Q<:9Ž–„“õNÔ¯f–ï{æëXq‹CÀdtÔµ™A]àSøÍãp6-ùšÁkÎH|&Fá7è”{o~ɀȦh8-ºo ™M `rOfwG%1ÂÈEÏ€“j{~7ÇâtcèÊMGè¾ò¡å?„ˆîå“,$^ÄBçâ’þ_´0\ÐeQn¹²”{ã0xôú-îÊ’úoÙ:ɺÎrožõMßÿº$>ôÜŸ0öŸÙ#Ÿò„Òû0‰+@oRÈLҔ§ö@fO²×”fŸ_fY,…Ìl3$ 33tGfú)0*­™¨52s‚óPÈÌØÖe23Õð‚¾+0ÓñaAD…Ìž&x,m ö€fæ7òó¾TØ,ÙøÇý¡À›%Ü<ØÌÞ–lÅf· Í,CXf@v±çòÐÀL²£…¸-”Ff)uœŸ+L!3s1hd–:Í`Úú5 ™™w'G¤¡Y +ðؤœd£}ΊFgÆSƒ3£˜'¦+p¦£Ê¼ž5³<¤_YŸ‘6¶~4ËS×àEéð91V6=cÔœ³]ÁTÁ3Œ<–ø`œÛ¹UÀŒÜ ¶evÌó0n8…Ì‘Ìà-v–yëÆ2§åDo3x÷8;kÀÌ_Ì5Ð3ÏOxNsÌÌ<’d¯°LÎw¸ÍiX¦¨ò[~™%3O‘FeʾËÝ¡P9²ÒÆØ hXŽêŠU°Œ×æ@VPŽ ³§1™òÆ”T52ã-ï&«ïÅq¶40S<›T«€™IõÓ©pù¡1ÈqE4 ãÜZ;¡™¯œd³4ƒùb9žÿ ƒhN(ŽLܺ@¦‘8–•“WHL´ Ò¡s}¯rÓ½F1¹×.È@ i8–·¬²åÏKK#q`f›qj(¦åòÓ²"±µ«¡˜2Å`â£/k‡,¬p˜Î6nœÔMNt³éj Í'Ó3 ÷c ¹äHO½®Ë٘丞·]±âú¦¿X$ÀCa‡âhS_„j‡u¯6Õ…ïŸÄ±ûƒ €k¡uL Áfc‘Óz·h¹Œ«ýàAl¡}}2Èee·4‹L;îRÍ Ó§÷]ã¡dæÛT¡dE0š? ¿{ÌÒ}s•4{¬ÕP ˆ™Ôrª5{¬7Eâ½iÅb°Mv!]…ÅÈ8\Š!„‰P»ö¢Ôç®SHìÓzEk,f:©±V›ò‚©.ËsiiD¦¤66F2špà•‚d®¢“Ö€ÌM:% ËâÁÉhX¡lÈÞ—éâ5hTp™}DÆS„oò„¡Y ç=Ôlrü«Yž%Šö¢'̻ޯ˜¦êã’1çv£ŸÍ4qµ‰m®»¡DsxÂl®AM¹-ûöèº'Œšrßyó‹=aÓH1EpaNŠ«Ž0ž_|ÎL'û7ä3OìĆ+˜Ü‚ ým–ù$‰f—Ké.íÎ ªçOpN¨‡ŒÂg8'ÔÇF÷|uÙwçÕóýe_Iz©t~Ô¤C=gÝóçÌy#55„O 5¹ì÷HM:üʲ› d÷bx8c%nùÁèNnùÁè^nùÁè^nùÁè^¾Éæg¼L¼äB§)Æ•Ÿs2±«“ÉŸÿÇ='_•EÓMx=£¼LÌ¢d¢BÇ I¸ºU?ÌRtSÔ;Ó–A_•‘p–ÆÉ©< ÔƒL¥d]nLN·¸™09¬{,LÁm*s7Åäà”I3¬úÙàV]_ÕBÁ/%7›&ä±B‹…vê%36Ô.4솩—¤RáQ]„°ÜdoSùª¬!K?4–!(e[õú!*m͓ƆBÒ—/¦ÂÀŠ S5I±i©´) ᡵ i)´)C1Xtê'-m¿Ö%Ñ „¼9šøòhÁCÞüL¸CCnZsÆÇnÞeó3qÃʪ¬‘¨ÉG£ʦ5C€Uy™,†ÜêæfR楪ò3©«Ù/åhç™h”§ÉjF9šÔUíêh˜_ßíÁÑ*G‚Ê Ýh— ›Íý#<ÆÂè– ›â®až]ŽnÓÖDºr‚‰ÖF“oõnû¹Œ^ik0ü2ÆèguMczšE¯&ÆçÞ×,³[Ù°e¶KEìcv+ÌÅÍÈéÓcݘf·:@k˜N'<Ó3e‚£æ–óâ¶°1Ëq,óÁ,3aFÐàL¿9\Í+‡Åe`ã•óz|483 9©fôܸ崰¯›i?Ÿ³Õ¼²”¶é×ìÆ*»Åùlc• ò=ãØxe.ýäè¯l߯+Cx°±Êx+t“¼†esÑð¬Âå˜VÎgc•ƒ‚zÌAj˜‹eEfÚòen̲[ÜÃ7f°S†¡zãš-ñü‘Ì6®Ù¬âùÆ53ÕÒê¡™¼þˆnÐÀL¾ÃåOíÇKÕ¬[6“}4û,jß´¬ü«ÙØzÓ²ù®÷ÊÆg?,s»ÒO6³Üz›ØöèºY1»4 ®÷µÕ®AM¹-ûöèºeSM¹ï¼~ô-–Íàj" Wæu¼lÚ IÜ©pê)ÿ Ù6ç™èpe ‹[°áâ™]æ“&QÜ£Íà¤{¾opâ6ƒ“Â'œdç²ß38I‡_YöO°m®$ý)¶MéPÏY÷ü9sÞHM áHM†p.û=R“¿²ìßfÛdâ>È"Ó]³mêNnÙ6u/·l›º—[¶MÝË Ûf œJfÈô3ÆMb‹ióǾV*ê§4!ýÖ† °êV5:=yÅ|–\œ‰©' ~q&§tèæŸ8äWM­«¾9ù8ËhzúíN¯õäU(óFšÇ’(àö4x>Õ«„9®a@YjÖwíM¢öÃôx¢`2ð•⪢aIå©ôL1Î"ší½¡cM±Ì"š ;ŠæQ(¦´êh’7b 3£—Ú…ŸÒª£¡í`ªTRË<Ð$a‰kœW Ë‘NõSÊeVДȊG’OE©hÜ+ +Z*JU£¬—8å3w£—‚¦OhbªJW“—D ©ÆY<“Ãê÷T›YÓöÊ™*‡4ùý0#c³Q‘@i]UÖ?Ù©òñÑÅd«B⑚­²i2û‘Ï3u ƒ:9¾¡çÏn Zbm3• u†e½³Sa@™¯®¾ÍÞÎüŒbŒª©ì•’f ¤Ë~UÒà­©ÏaÕÒ0øiªLsPZ³¤‘ÈaUÒ0ÄÐ3 H]£#–qÄUEÃø°G¯˜£RѤÅ=>§UEƒí Óü““вkÌaNJE³†㈆êÔ©ïÍY1óì3¼jhðÖb N€k>ú¸e×ÜÙÍ€öãªÂÓ LKþÔIkPökÂÊèeF¤)H¦¥4N•´‚ä`œxðwÛ„Âäj׌•ÓH®A¹¤%m‰ÆäÇYA2ü§åS#r k˜‘†d¶™q£(DÎE¨‚dQ–t É…v»G͸ar:Ø’ :cä6P¶‹‘]ƒrTY94(¯!T&Ó´52%l ¬L°,«<6Ï@ü šóbéÝ9.É_d^"ª7h¶‹«ÑÍ~ñR8 yzQid.˜ú¡‚f&ä ­9°6ÁRÍ:TtÃf·Ü’6›ÅH|@ó„K…ÌbÉCD}®¡™Qw j¯®&Ê,»as]c¨48‹Rü!^͘ʴklÐÌb³#vMcsXS54³ièñ56Óˆ2‚™4»Åî¢US£³w#¬igÖ'™¢Ð™¨ÈM{˜@§<•YIóÌà}›qR³Ë`S§)LsËIùivÙ*&[3Ì,…>X@Í1/v? Í £é£¹eúNPAs\=‹42Ó+fá±4ó´ÄÉc+ƒ¦yÍ’Î ˜éFÍcÏÓÀLve¹"4³,¥¼žó¢‘™že?Ì!/z˜™;hù¢‚æ5׿ Ø·Ìt}šÑ—˜ãš}B³¤J{6R3ÞfvÌâÕ3ä%Ìt´®™Ñ4%AÌÁ.—½FæÕ!rCf³„ùjh¦%rù6®Ù¬’ †æ Š13…ÍŒpŽb8'q-yEÏLl3 ÈžyPÍðÐÕ¬sT7ˆÂg_+±†gŽJó_%q Ï~õšÑèÌ!Ž0xÎ ]è@Á³¬Ö° >óÑH\óaã&‹\÷ô½Æ<*}ù³™¤öEóæÛþo(Ÿ‰ü°ÎîJG¥îÎíÑuëb q7pn®AM¹­ûöèºSM¹ a{ô-ΘˆüÑ‚›3õ²“¥èf˜«2¦Þ6pÎS;ñáN™àq†nŸÚeFñ3LœÒ¡6€èžïÛ8„Íð v'¹ì÷ìNÒáW–ýLœ Qƒ‰ø gëQÏZwýI³Þ¨Má3’æËΕ¿˜5_züÊÊ›hÎÂo· [/·,[7·L[7·l[77ŒÌ€D 0ëç²…S²›ÖÎÿñ^ g¢¬n$>„Ьc†êT —°”²£/{š‰=KȫœZ•GÎ)TRL‹§¡°ùHL…Ù\§Ås¡*1¯O»¨§K2‹',6ªÂ\‡Sã$ÍTËáÉ[,žnIŸ[²Y ž”£» µ°ÎÞ4wšÕ×2åªÁQ1~¥˜U…S×XÍRªÂÉ«…¥°ÈÞÔá$ÉÈÛm ¥šE‰£r‚–V%NšæœÂòzS…“Öœá•Õõ¦ '­YžÈÀ.ÚuZKäi^õêvM [YSxjÖÝêtM§‚E³îÖÔ¿•…ª[Zí±!•¥ô¦þÆ¿ìˆjª,¤7ëÌå6”ˆ ÖU³Î“'£öfÕª¯¤Ää.J©¾8T)€¸Oå¸äRû¿dZ‡%Ir¡ô'9û04"3?ä½Ü 9/~‘YªqNhDNåefà Fäì–hH ÈŒÒ +‚ÂcêÞ§cƆÇ*nJ#2 3·§FdFŒ ÏÈuQ o¨%çÊER`?Ø¡AÙ.ö“ŽÉÌÓ8·”Y;aFþm¨Ì¥~Ü!4(•VX#3sgN–BC3K+§'Ï®FfÚ'çÈ52ƒà†íA!³ÖîoÈì»…ie‡}@©@™,ËÈ5(3ýà©Ñ¨ŒyÌX} ËTÄO|R°Ì<ˆó¾Q¨¬Õþ –=óú³†e&Ïð¦QYg“Ô°Œá/ªPÙûÕŽ Q™0·ÜŠ –%xž…Ë>.™!.{·:®]4yjl¦ ña¦Ṳ̀¹Ëì%küƒ+B3NtVJØXf»D¶jŽYö~¤ýÖœD¥÷$«;ϼ°Ó¥ wr¦yÆÄmL3×k\> ¢™ÙxœÏi6KFLЪHÇÆ2Û5ê[#4=ÌfgŠc ¹´S<¸hziM,Û9æ% §hº ó«h23y2á ¡åµÇ ¨Z-ÈÃ4‡5:hü~”ÒøÌì'õ1‘møLkð€ Ïi-×°Ása¶<»Å7î€ç:Ýo4>»uˆ;hæ9+™J£tQ“Ó0½æ8ÞPº¬¦ñ ¦ëºÝšw6KÎù ¤ë’ßiÃhz¯ƒt^£[?^¸òX„em†OþÙk7óW‹7¿Á%d¶Ï9Á+=±@¹ø*ÅZžÉmÏ®›A{ÍÊ—ƒqcúÙ' bu_üíÙu ¨žõ3ýì[l L$2p—m ™p&T‹ùÿ Ù@×ó;±âÊ6>ðpÿüª9EÉjžÌ¶7»Ü ë¾?Ã8S¨ħX§âc Ýú¾»ø{UgÝ÷',þJÞ¶ 2C0¹JtMK¥ç­ûþ¤yïD§ñD×tÔçâ_$:éòk‹ÿmFÑ”¼8“‚ù÷*l¨Ý¢ÍÛP;ÇÕSbƒmÌw†Ïo°û¥Ø¡nÝ`;ÅUƒ»ávJ¯~·iñÞ¶æ¿»ÙRgÈËÛu)%»Ãv”ÑCwØN‹qq‡í  ]Cw\“cöv?Vä¿×Ž|3MfZ¦­ð›@¶L[ãw^¢)7øKèë‰ÞKté†Þt¾†Ó ½ÃY¯Ñ[Jië_£8C­f¤Ï†â’ ù)±»a¸Ñדq³F]o(îU€ç†âŒê)46÷åDo±ÿ-ȾZVÓÊeið¦ÃòÔÙoΨ¬‘¿qCpÖ|°‚«Jr€ûðZnߪ ߆ßÞ­¾~=…²_£#oVÕ(ÎÚwve4ŠÛ^ug»íš ~g»Œf§½BxR€²±ÝK Ðéö‹ÿÈÎt›•ëÔèMhsËu¡™î²”‰Ü™îÅZ|ÀwP>|Ól7‡ªÑ›me˜Ë6ø&Ÿ3¼†6®Û¬N>|KyÔyT|¬Ãt/)|äiÉr»!wH«ánƒnZN‡¯é†Ü’æÈpºI“#ê{‡î¨Q#7Sƒ<†ý¹Ñ‰HC·_ Ï;vû5ÅÊŽÝtõ›r€ÂnæW-SêQØ F:,¯)ìvK¹ŒºWRÐØmWž »wÞ {qõÐÈ-ªËSºþ€î…CݼŠýz\xŠj±5„ç÷ü·_ò"ìàß`vžiEvÈ.«kÎÚÜúð–ÙQ[Q^í´×ý¸µgÂï~R£ü«íZÛ_—,­oz¿¢Øìóøa™Û~œo²kžÛ¥`rie©Ù‡ ÝÂ:å¶ìú‘3·í«jÊ}êÑ»!ü¬²ÀK‘+‚Åæ$—k‚0øFóû «,èŒp?ÐÕuÛê ì‰ WŠ9v<¸}b×ù´|ªRRý.¥ÐÒ î†'Ûൎ­h÷~m×;^ƒ^fJpG¿Ï㋃y8»•‡÷ÉÖLO–{ä$rÒ^%'éø!'ÝïMr4ä¤ú½KNÒq''Ý­"§Ÿvr©©¸á¶ì$ ÅåÓöí¦P݉aÑH ^Á¼ñÌùv¥êSH,?^ßÍÞz˜?Ö N™l°ã¾ÒKúe½°vNÛ•w6ÊÑKQ½üê×´n‚ë·_~ÿKŸß3²‡ÿ¸üåûÅò:‡²þ°J¡Ê£F²xÉzðéI¿bÊo~ýÛ¿ÿ‡ßýêÿöã11S…ëcúê0WY$_’8Ÿ‰tTè~µ éþôÇ{Ñ«6/%•íôyf°`½,ÙÇ’e² ×MãXZö1Þé d:rÓ<(¢ZÁ7Ÿ¨ÀÖŠJ oš£iµ¢/³…ûƒ>`[­Ï­­¥ «ô­…|LxÍÞ5éº.9ÈX÷Äñ‘%48³ÔUb¹4D“|k[’E†€bã›3³¬ߊì ‹Å£‰K^/†*o¹±±µµ,dÆB6å{®i€Š´µ4dí"d¹Q_xb6±øÈ³Ö ^¡õQÚ¦RFÞ2§MuÒ´¤!‹’ÿ‡ .ÏÍÞ¡‘ÄÁuSfÍ>§Ü!広+„­7\7sgfÝmË©Õ%iW|jGhªKpú€ÂæäºYˆ!gÈ MÕ Õ%¢_Îï©Õ%ÔÅ‘e ùàº%ñFz·þ´ºÄ³ºMK¶«ƒA ÙL«K‹/ù’è–×"þDbÝ´%Ü›ðè´¶„É6¨Øx§-áEÁ‹º)ã´¶„Ej’€ØÁu3Ë<¾×µq›¶„Å`CÂ5¾c7 €ÏÍeÓ–x"d09ØÅ‹4—PeÁ6m‰#nà\¶+FkK˜ Òqn ­-¥Sn‘µ›¶„ÓÅò?v¾;ˆßØ¥zòÝÌß"çÊÖƒïV’×S«ûðÝôý2&rùx?6tpj&A–¼n–@þÕlÚl½éaó®÷+æ±ú¸z̹Ýè'¬Ñ!mbÛ£ëî-8¼»‡ÍöèúÔ”Û²ëG÷=lÔ”ûΛ_ìaã˜gm¸,Ë]O°/à¡Äÿ­ø×Ìó:‘áÊö%·àÂE?že>I‚×›Xqˆ‡Õé]‡ˆºø×è~¯:DÔÕ¿Fõ{Ù!¢NÿÝíEÿš•l—šÄ÷ÈI:ä¤;½JNÒñCNºß›ä$h0ÈIõ{—œ¤ãNNºÛù×@}½õ¯ù×èNnùר^®ù×è^nù×è^¾É¿æg¼W §@°·Ô>–8¯üÓEçæy\l ø¤ ±e‚a3«&ù§jr®)GõC¸…x ù(_¢´-¥ó¨ÆÁ+TžÈ{v)%dò¤-J¬S·)È>”äÛ{J“˜ŠtˬEÃäÜÎbe,Néch]„Å|ÂtòÓ#S†*¶´×üRBO^3öqƒ,ó7mJž3±VK[‘P§nSbJçdýЖ*z$6œ”Äe“6í¾‚3T±r2󰹯4°à+‹Í.î+ ÆÏX!Q0Q™r_q%»îîhØ™6%I•éº*7¤¥ŽžØôAZ¹Å…´Ò•нèKÆŒÃSº¥]µ`Í„·ys_ÉŒÐiÆIV_Wî+Îö‚l{ô1vš¨BÙô1 ;çu¥Ž¡6¶Ð˜ÜÚ”:†Ÿ4žÑ6l«›÷J™uÞBݼWpdmMý=¥ŽÉ˜³u¹=šÍ{¥š€} \4»÷ ^.Ѷ6¥A[ÀäZà´«>†VP‹M§žhwï•ê€ö¢v©¨×ÜB<Î$“è–ŠzâZèî]Ñ)+¨y‘(ºñ:º¥¢ž¸wÈ ÚXüæ¾B5úNIÛ¬¨'„íAÎcôJÃè(@e=.Õ#¹¤¬&v€9m¤M™AY0»>FHé}õ^‰òŸ(Åå0=1OÍáŠ*EA£ÒÇÐ…YÉÅN-&Ó'Á¤¸¯Dç²Æ$šÉRŽ«{úA÷• ºi¹Ç ¨¾Þ¡›õ‰4ÍL¨ ;1¿§‹ Ôó;t‹}Áäîq¥‘»:±6=ç@!wª’¡'Ûv\íæ½â°pƹx"7vÇÕ½è¡5rSg,3®Bn`Rìzè¹%5zm𥑛Ô6ÑY!w’ª Ö·¸Ð ¹Ã ×Rä}p 7Ña¸dlÈ_tdÄ®…¹Y©‡Ó•†8 ¹ëŽ;¢Fn¹?±ŸÅ4rW&ºõ…¹é‚5°Íœ¦‘›ß,ÌÎØ.4…܉¶á’zèŸFn.Ùˆ+íÀ-Ùƒ˜Üܼpk¹éÔÚ÷ô@îHŸD±z¹¹É•‹ß„X+4r³ò-føðuó_ñâÐ,Y34r3/6Ù·KÜt]uù1&kä&RiQÈD!wd†¤Öv 7#g{@îܤfn#·6…ÜQ Þ&ÓJwâŽÆp·$ôÁÏÒàffo[cÊàæ™3ÞQ²kà&g“Çm­›¬ nkìŒ=›©;*^œM4pK4þpÞ€;Ðö@ ©n™ž¾çnŽ…IÞó)ÀÍý4- ûCB䇭 »meÞn ·Ë;vÇ\Wûf»YKÖ&l‚lžf»Åe1¹RÍ Þ¬MÏœ¨³V\wÆïb÷d8˜nÐÉãɼA7nt›“íÆt³¦@´Þ6 RL7“Dƒ,K»˜4t3K´É ?@7ñƒËƺºíê?¡¡ï5Ÿ÷†{AAÁ/E2´tÓõMò™˜“éNLm—¹ ºÝ̸²·{1ó mppó-&%1 ðàÁös [ûÑkà¦K™mâÔÜôlÏþñuêÈÝÃ<‰6äö/†ÞwëÛÆs+7 ƒçŽÓJ#7sX-7§æ¹3W»Ü¤DÍsÓSDQÓ[ž»ûNÚ“çVÞäÏ-q¡Û®5Ï rþ1Ì<·/s"·dQ÷8B ÏANA7È Ò¤ÜåณM¸q­=9nÖ `ø&l(à–¼k©¶ƒãNâþdS}Ãq'úØnŒÕÀͼ–ºKÂÆqGÒugàÖÖØã–ãnx"OŽ›FHÁΧÁqGÂÖ)|0·W³€2N¡)mY»éjùW³:°õ¦ô]ï7˜Ï<~Xæv¥Ÿlf±æ6±íÑuócvikîk«]‚šr[výè¾TM¹ï¼zôMÐÑ–®¿€=9Ç®:†dáÔ3›Ëߎ tžØ‰ W6°¸.žØe>i’Ä](šF+ÝéU£•tü­t¿7VB&Ãh¥ú½k´’Ž»ÑJw{Ѻ’í§Ø@¥ÃANºÓ«ä$?ä¤û½IN‚ƒœT¿wÉI:î䤻ý˜ Ô³”Tñ"µ]³êNnÙ@U/×l º—[6PÝË h ì ÙÑ™D3ë׌ Îk#èÿ|ËÊ QKštêîÁÝÐÊ¥žštW™3›^ò”3’‹3Û# !¶µ­Ú˜’˜ÁÏÆ˜)²$¿jcÀІPs*">%g==FþãO0@â@ž¼R¥û—e%ïþ=u^Ltþgäè9RXÕ1YÜqcjºÕDE‡é©óøÖá‘ä 5õ1,¼—ƒ7âìbœõhâµÓ—‘´£¢^LTt4~ŒÕZÔ1Š™ÖŠV"¥8³=2¶´à¤ÆêÚ{JÃ%aƒ)Û‘ì‘ʬGév½”• ”ÄÑ'zPÜF³ª+Î<1$©(} c)‡wv*Jã˜M•îÍ­­Ìt¢es$QF§ªô1•¡Ù%µ™T㬫'Êè–SVº6}Œ¤nö />ÌÔs<+ZyÚo–ÈÁ‹>†s [/*ãL=ÇC°Ý7m’Ù*} 5K"¯Y¥Hg„» ¡‹ÉÔs zežÏd”r> ô¯Št&...6SÑñÐk™Ç\ŸO:¥GÇHzhJïLEÇ WR!ÞsM½R¤Ó0ÏŒ®½§éôôÈ64aJ‘NEˆÝŠžÃ¦IÇ‹k±½9lšt<ÔE‘£Ò¤;Ž…ñYÚV… èÜÇD­’4)Mº}T*^Ø–”&Ý¡í±Íå¤éŒçðO€eU¤{Z@K-ÉY)Ò¶r‹HÏY)Òi{ÜrVztVëÄŸNN£pz¾·  ¶9ãZ‚ÿ¶Ñæ°Ý–¬a›èaxvÚ1]a;Iv\WšéG¡6ãmñ€ µ%þ «Zž…ÚÉp‘=/Àµ+s$tRÛQ›Áô M7§Q»z±ôáðœ¨Í2‰¸¯zH£†m \€,m|o[a»´4Ä=i§†mì>¾”*Q ¶y»çòD{kØfгômù!lgGЩ†mÞ&=aF¶ñ^NâLrÀ6óË;€ƒoŸT°™Äf„–hØÆ{ØŽq(Ø–‹Îâûí=Û¼° ãØ– •Z~Ñàn°Í.æ((Ø&Á²»PÃ6.pããÛYª.­?…Û©¾pÙîq¤qý­gXáv¦Ñ$awÜÛ`Aܯ¸ZÒânKÓ¸-Y²óĦq›7x5ïP›¹!¨”/­7…ÚÉ3 »$N&µY´tO×¢Q›©/¦ƒFm¦·à’·ã¯P;³VÍHb£Q‹’È;Ƕ µ3“ò&ï£0f¶ÉK€‘Ànå¶%©DÀÆŠ}MÃ6ßã­DU®a›†t ø¹°nó›©¶°ùŽÛ ĮĤvÑþ©¡›e»ÑmÊo ›!µ(Ýáyn:¡‹—rEÍqó¢KôãzËq¡ZrÜ<•%'nûÁq£f nåÜ9n-ÜØÁWØ]ÆÕÙ+=l ·çmài›?n:2Üä«^¡›ÖÊÈ€Pû†ãf}cð}æi3€cw¸Ú8nV½¢¿¢w'Ç-Áì¹¶ØlÍqC¬vèf~ÙhOŽïYÈ(¹1ñ »£„>vaÝänìðýÚXnKýúc¨ÝXn ˆÖÉr‡% üÃqK ×ÐÍBNO‹ßf‘s÷xÂnü¶c¢£ñê ¿-õ&z-ŠßfÎpÏ,þä·%…¼ï)F6~›†ðæ·zàvbñгMiÜfÆ ™ºË¸M?8–ÈYU¸Më®±Õ¿Ízô­lÓÜ’›,‚$älü6¸ ©… ž¢¹ ìÁú·]¹™1‹Ôã„î4¿M’g††À ¹ù} ÁnÓK›Ëa¡D”ê‰Ü|/¶Û)àfIª„kU7ɾH ƒ¸YÏò^JõÏ›Ç!øÁÒêÿ4iˆæµÅÊØüIQ§§6æQûËŸÍäÀö›зýßP_>ùaÝ•ŽJÝM Û£ëöÇânÝ]‚šr[wýè¾ TM¹ A?ú&(®tH¸L)À*&WM ¬î€›‘e»êG¬­·M óÌNt¸Sfxœ Ûgv™Qü #¨t8¬VºÓ«V+éø±Zé~oZ­„P†ÕJõ{×j%w«•îö¢t!\0 Ÿam=‚Ò½ÞÍÜ/=?¥;¾šº_a”êørî~é¹Ó”î÷c–P<¢Î¦0m½f Ýz¹e ÕÝ\3†nÝܲ†nÝÜ0‡²lÔ‹F<Ê_·†–i ý÷ï„©+øhf¨Ä«”ãڽȼ43ª(ЕTRÃRFKå;Ég8cJXÊß{y1 §\-k±¸(Y¾Rè)^ M SGI]Dû #%æU3S!ZCp¯5%™E3ã)ž3Pk «f†>É.MYkfœcµPÑ-•lVÍL€4†ñ„/,Ñ753,îGûŠ(ñ!®šKK¢pM@)FkfèÇì£()KY*ßI’Zˆ‰ôÛ•¶¬“âz†"ïÕYøN"eFàJ©a5…25ixdÈÂ}Ó²”¥È¢iÉ»+ëóMÅL¢ÂRé&maŲ0“jòª˜IŒNKÝô ù{Ṳ— #c+=ÅLd2]g¢ÐJµùÕlX”Ù3.WÖæ›š–·d¢&QíUÖæ›º™@…Ëc¡«.¯ºV8ƒ¼]ĦQ½Yu3ŒÚ®Éоé_Ý ‹Ë¹d‚øÜWV曺0cŠ&k0Z7ÃÊy=[ a±…2ê›ÖÂ:+#9§-”™a3‹ÆÉÌ£Ym¡Ç+Õ¬~5†ÕJ…Kt=N©2Æhêf¤Üweh¶Qc¼1ilO,USжÐR.)é@îDœ¹ŽT ¹…Í!¨„¹éJTªõ-ŒQ#7‡ÒT¢þ@n–ª%ƒÙ¢¾;rss5r§Å´#wfùQIû¹YÔÛÓÊä¹É¾`}{6I ÝxÏÏœåºñhäÑÔkè–îa,È Ý¤PÖ,î먠mySkèfˆoæ‰ìð¼BwRÙ¦5tÓz„óŸZ(¬†nfy¯#©ƒ†îDßXn®KÛ6ÏÍrÚðã‡Ö5ËÍrf36Ο,7Cyq;ºÆÌ*–›Rÿ4'p“Ïu -¤ƒçÆbC’?yn‡Œš+¸Y~€©Õ ¬€W¯÷R"×Àu®¸éºñuc¹åž0ÌÖs²Ü‰OŒ£f¹+yÙ'Ümã¹rÙ±9²m<7¤†(‹ø“çÆ0q§õ,ÏÏ ŠÆ¯cóØxnf,7ƒ¥Õ<7  ¥ƒ­æ¹éìg¼ŽÜ’G?û^mi㹕§ÝÆssqí¶ÚxnÃœÇ ¬ƒ;ynpÖ3Cu<™nJt¾‡‘jà†€ÎÉ…·¥hÔ~p;nKù 0º ¡lKngz¨þÆq3³¶9ç·m¡”î€mÚö$ÿ‰Ú’B¦GãÉp3:– £žÂmNÏ;“«`›öÕÀ°iwÀ¶˜Äs´-=­†mj± oæhÔ&´ûÜkØfù£é!©a[ì6×Yj³ÛBåÞn\ÛÚNªa›‰gÜÈÚ;´r§Í6öüã§MæHam›9TH¯Õœæ®~;‚;jÌ8,¢s‚Wz²¦Yþ÷ÉmÏ®$qÊ›í¸ãÆ ô³OÄ:ë¾øúÙ}»¨žõ3õì›,£(†A0š=ç»–ÑìyïƒÙ†t’þ†,£ëéHqep¸zÕœDÇÆð’xš–:ÔºÛËæ¬¸H·žïÚ³âj"Õ=ß6hÅi$Ý:¾i%]IØV)ZLÅÚMÂ’.'aénïVS•=„¥{¾JXMÔ„¥z¾LX-‡K',ÝñÇL¥)y¦Æ ”ËîU¦Þz¹e*ÕÝ\3•nÝÜ2•nÝÜ0•f‘´*„ ËÝVV[éŸïU~6’—¬VIÞCÕy¢IÇ×vO2z¢–Ôø#®ÄR]·ÒuÑÝ8:¤1tµÆUënü%i “ˆˆ”f›ŽÜ¶ŠÒÍÜ@½H`ÝPáµ8¦»z¢ јu&Æ<3­¢÷E“Ý ƒ ª)èø‹„øxZbŠë•ªMQ*œJyŒµìÚLªÒáùV¼máÕª€šØc:Ë!µ‰P=âž ëQl¤%^¾j²œ¦WÏ–k[ãªÇ¡Š4Wg[qY4â³¾—\tã™LJú´vÑä$I#ÊT»µµmªˆ½L,Õ_Ì’ÛKÊŒ‰H"5%‘¨µÔ•´Eo1—”-z¬&•6§¼ZíØút› M¶WìµÖ‹ëw•J©´œüÓµûh ’àËs âòÌ|Ž^ ˜,Ë&VT^†ná’âKH¹U¯5ñ½‡”›‚è©v‡6¥ÓñÌ«‹i’²›!Ub_Zô¥¬n§dÎ’tÚÆC•É d†-ëÓ³àISY$•G¤d´iµ¦RÇ×L˜­ _”LEk«XܳÒîÐÃsdEcÐÁ¥†%¥[|³Ó‹C~n%ôT2æ\íãQ@Ï‹YÂës>ŸµÚ9 ô yÅÊb=Òô,^@[ä†8è/O–¼î ®€>‹ªÜÛš¤ž,B»ãÜ ô4]æVÞòzZC (ÇÇp=»É±Ïè©. âŠäO ç±Ï¡kÏ6œg ¡õµ§RÝp^{—m8OfǹÇ£q>ÉßxµÆù$±Z9´z¹Î'÷"ä4Î'FRÖÇ6µá<+¡ƒÕI©œ0Os+0Í· ®ÎK´akù‰óLªê%ȹœ[ñSÞúfRô¼^z$Ö‰ôŽ¡·à.›Æ`ƒz,"Ž@ìYêi‘½3@=™úBSÝ(ñ·1õQêp<:Sϼ"ti(õÄz&Æe„XG$ǫ̃ úxø¤©—PHû°»SÁb<ÿB=ïpG¤–AzƒzI£ÛòêžX[ŸZ ÖÓ¨[ ÆŸ ëÉ*ZA æÔXÙh¦ª“©÷¯ò²ÏxÖ“ ð‰‰¸3õŠŸÑP/a‘Øô“Ô³JFñÔwPÏBÕíõ+–Þ0Ì4ʦO¤g×<"ü7¨—Œ·•¥¶ß@½TÔ;‘ž!ŒØ§! )¤ç‹/‹í]*¤çg¼$ÀyÃÒ÷b¥Ôk¾!} ËšÀïtagEzVD­ÁÕ¥¹!=fEÌaúéÙ°è1Ùé™ :¤IŽ é¥8èÈw¾!½ÄãýðéiföÍeó GïèÈêMéòžBz4²²ŠÏ'CÏl·+ã¡€ÞÖµ~œV6 ÷ F\.®ùlo@ïù;©ÉÎe¿GjX_Yö7¤&7“'¸¿ô¦ žŠ+¾)Ø‚éO”ØÎ{âÛÍ˺ÖóLêkf_ûËz/þcŸXó¯iÃV½„Z™ 5E&‘úJ/þ—õ’%•n 5`ŸÿRCùOñ ß3®„ÿ¸Œ»Z³çPÖ_0S"U:L1IŸ9†¶YfÝxȳ2ðŽ¯‘ïíi4m9ܘ¸ mþÅ<=ç—³-‡[»71ŸbiA0s¬µÅ¡PlÏÌx6•XÎÍ"V|UÄzª9ç–nì.He3JÕÎ/5¬d$L'×ÌýÎ/)ÜØf–Ùù–ÂÍ@î‘‘˜8Ú+:1ÃH|/a1k38jWæŠY èáBKáVcö²šm½Ä ‹K · ÑŒqÆ¥ŠŽÑ«úò„c-I 1eÞ·(g—–"V¹ˆÏêá.-IÜøZñs i)bű{¼÷ìh^’¸q| ëÑ»ËK7iÂ'[¼¯ËK +™1–Œ+¶²äp“•²vŒ¤,%¬8JÆ*v3³+K7îLôcâuV°"|N-—«K·†¬á9oŽiðžŠkü`gØãÜÔ§â—²µ‡Ö¶dp“óö”@á|=‡›/a#X%Tšì’¾M:m’P¿g6¼A«TœÏÄ´Þ.ùÛ¸Z)d×’{Ùz ®IwvpÞ-éÛH:bUôrj0Å©öâ¾Õ46À3ÞSpMކxÈAÄë3fA†Rüs4<ëlMRµ,Ýõž06ü”)O$ß5#¶lZžèÁ²# +ÙDCv›BxL ²™Ÿ6m°FlV,Oz"ö  ±3˜lmiÔ5b`Z)=o£ì’®€Mòòš`ã‹À1¦8ïhÀ&Ü §^3'ïD4מ¹Þ]ô’¿Xá5¨rù¢‚ëBG7ÞRx¬—‘Âkê„–yk¼¦ÿ Njû¤‚k‚É2oרýj¬)´.,æ`bÕhͰv,³BëB§ÊÌ(ì­ÍÊ'lpíèsô`Œ†kfl3u›²‚ëBÿŸw ­™!ÿ„˜ªáš¯97ƧðºËÞi\Ã5#È—åÐphM+¬áÚ.µs5\Û%3é×fe4\3Ã-ÚšB^£5]êSAƒ5#Ù‡_¡u,m> K£µÃzààµd­™Ÿ»Œ»M£u±3‰ªk,wî=ÀªÀšÛ”ÝÀø«Ù”¦ºo¹0JcÂè¦Y‡v”±NiNfNôC ýA´ÆiZÍúõ´ãtv«áEÁ´Ôý Î:³¦…´¹ð)œ–c7NšÂiL dõP£‚飿ðL+L—À /Ï(LK¸ñ LsÃT¶Á4Ûìä´V”.Á+Öy…iE×ɯ(Í©qsŸ£» 4ßZÚ Óœn¨1þ¦e•‡}[¡4{‹8žýU(]h¨Í{V˜fœø:ʦ9qú =òÄŠÓ%Ø5b^á4Û†‰tÃi~3L.­á4úEpYqº²?§FÁ4ûq~ŠW+L,€›8¡pšï¥E†Zqºx©d9%/…ÔúD­H]ÄŒ=˜x…Ô$äð|µ|qa‚W¤.Rwð" «‹¸ L]±ºˆÇêsJV X¬ú ØE<@cçR^óƒ •!4¬xMrî9Û¢ž¤£ÂD²›.C ¯éTòœµ ¯y…,2¿ìî!°â´0s-3ÈÓ"Ùq¤7~šÆúEs²i@ÊÊ+ ilð!ZBy~Ê׊Ÿ6¯v(:â®ü´X&ð(~ZÒðŽf¨±¢ýÃh†šEÊ¥W~šys&k†šá¡erŠ¡Î_Q€H9‡‘dE3Ôh  °‡…TuÖ,¤â¨Éƒ÷ì«f©ñÞ¢)P5mµÞ‰_qԀ̩ù‚_îBÅQg:ŸLՂ樉lS 8êÌwC²Õ,5óÅ!Æj–:[µVŠ¥–¶I\𧦔=éUñÔ™ õÊ`ÅW–š™Ö!o婳U²Žbª3ëw}ÅÆR[ Ç+OͼF“¶¦:Ô÷Lµ[èXóÔÂ×!n<µgzƒÑ™â©ù^™ƒÔ\µ[R3ÕâRõ°#WMÉkØ’4oͶ45š·v ¯µ±Ö¹Ÿ‰ kW6êÃ>?tÃjF@Vo¶?þÕ,Ül½éóó®÷+&°ú8ŸÌ¹Ýè'ÄæÚB>1õèn¢9|~Ô£O‚šr[öíÑuŸ5å¾óæûü8fÓA›-L5qÓåÇå!d'ÞòŸæñã­a¯ÈàÆò·éñ31c¢ÓJnÁ¦‹žEË|’¤›ñ.înkÏŸá†Q=„OpèÇîùîô•eÿŸ•¤— Ô÷Hn¤¦zþR“!hRÓC¸Oj2„sÙÖW–ý¯áñãZ)X‰’¸åñ£û¸åñ£{¹åñ£z¹æñ£{ù&ŸŸñ§´õÿ7w.I“ãÈÞë0¿$žÇÐ-´™ÍH÷7…ƒ$Â=²¦FÝj¦õªª•I?Ãã¢ÞéèÇø#á4ÿõb8Í9%œ¦l7€ž)ÄÓ´í…Ä~JÛzd J¢Žˆ##‚h¿¤–Lû”˜”ïHŸp¬ä·[²8“—¿'ågÒùÓŽí¼*Gð&‘\ §9¶×¼œÔî©ê*kA߯ýz¾â?¶{¡ÀM³_Ï¡ƒ µB\ªÿ’Já(šBªr)Dƒ¤¥ý¥*A4ºL5ˆ²^í½ [ã~+Ÿ‰chJ£6ˆP£r{J£6ˆW`Âö÷”¥ölÉ §ò¸J—šƒ”ÆÒ%‚f@¿¤ØÂRl"Å"Bg;aËÈ™!WaHäLbAªL‰œ98d«LÑb‡n”)Zìø9\©‰GpžŽGí®I´X >©I´Øù³4òk 5³[ÖãẌ5³ßÈ&w¸FT3u?Ä×ÚØ‹Rê~ˆXÛz&pHìÌùcÔ{°zP÷CLœ¬ž"ÈûÏgÿÖÓ›âh³ïÀ¤Š‘;Ùφ̬]ñß«é‚ü3‰žq™Y†<“ÃðÜWgõ;elD¡ðr!QTbgH BU”]ïsÍ€®\»¢Â(Æî­Ø¥3꺻&«xn•fÊçZȹ«x¶·ã)%p†Ža {ÔZ…3Úémh`sãˆ8eóHìðS6C”ð£ Ì~žÇÁ!:Ϩb²ïyå3J±íxå3êZo‡êÍi42§'¢pºOYuá4’[ie…Ó}•ð}œºÊiÈ2›€Šép8Á4:Ž-M+¦»3N'ö«+§ñ›®_§»¨ë jИ;²MA uÎ)5.W@mßc( ¨! ÄÔºdBjì'?$Âm(©Ñ⡵Jê5½­)ªQ$dî)©±ú 쎠îP:wà•‚—ïÌjÄÏlâE9VQ½rêï‹P ³×j!õ²½<~YP"žÔ’"%X7RZ.¬SZp ´ž?Wƒ'õ@‘x[j»´¿´¢ÉUH=I#  ÆÂm=3€ú$K9½<ÔûÔ#§ÉöQN£++Ö‰)´ÆèÚØ­=x)кp¤€ÒºO¶}>i½˜Z7ç̃ëΑ3¸.dæF\».hÝX÷UZã=ÀC>p½ÉðëÎûô×…Mg‘cÑNí|ªÐ\0õ¹g"®·æ`]Š­Wÿ´©{ápEu?YUTc§º*PmKéAÏÕ66ž ÏHêLg¢¤nôÈþµ£çƒÓ§ïýÀé&ORµý$½K(ª»šâ‚j»×Ú¶¥.TÏÕYæŽ4øÃz,ZÇ].Z´'¿<³øÛ¥?`ôM=öWGÃAùÌã4·WŽÓ“;:¯‰ÉG_CûÑü¡q¯-ô…S)_Ë>z]•)ßW^?ú3zl9\†ï¡2Ó«‚l1à‘Í"8¿©È¢¥œ‘ïÌíï)È:4O¯ì¡qœ^„ͧù®|—†A%“#A%[§ *™žÂû*Ù:…ÏeO%[»õ7ËþA–·ôWY0l59ò¶Ú:Ýjz ïoµu ŸËþÞV[ÀúͲÿ‚ì‰^dã\¯o ²zŒ·Y=Ê[‚¬å5AVò† [ðö\†½}5h¾¿SdSÙþ »àÿ¦È6xhž6w£“@b=$_v²Ï¿Õ뀮Ïcj;ýÍzôŒåv²×?K:O;«÷e\¹´þ†k¯ã”ˆ•èmº­Ò„WÝDû"pV:øÅ·ÁIó$¡ÐBi;Ûµ­·'i¤ŒâÏ«o«Õ{2â{WUÔV‡÷c uZEvp4zÏï’ŸøÞáIÇ­‰(;ø}¹!¼{ ^èê¹½¶hŠL• :;´ZÞÚ vÂs=û‘fc7j¢ÊNNncx±OžmŠ,[QØüv4ûWvÅ }=·C±ÍåHš‰+(ô”½#ŽCRdOìHÂùztxhž}ºê¸²gÑg+«4=KiÛ¨õvÒt8ižmºÊ/l·•írgE¿éðÑÜût¹vN?Ø4%¸Ÿ”µ¶Ôо½ý”4ÙήÐ~² ¹0žO„×7røW9^eö oy/ìD²•*žnв-"ÌÚi>yT½’ êkÚÅz•²’¨Ü»‘YàÞÉÞD™Å…Ù‰}½±ÉVŒ\÷+[boT$n—-ŸÀ 'ÚlrEf9@Y›¥l¥e-Ø)œÇ>½·´Yå4ʸ<÷nä´F(§±Ì®)§KuqV1}fN£QLÈ×yÔ^¥ô!µf„Óùäz Ôú,QR/Î>—TI+_R%u.œ ­¸Î¹Ú…Ö'"b õáÿø õ¤è%…uçdN5~Ñ“î…Õx®eOÐVãktþŒê±Êsû`Tc)=G>ú!!õÁ‘#©Oª·@]Yã  î\4B@½ä;¾C8½–)oï|àtZ²á­ëROñÞÔRTÛóŒRAõ”ÔáÀk´ìÝPå5ªÂÔ'ÅSpΪ¸†xïºÄ®3=P×6FW”ר‡ãŠQà5úK:И×frµ&ð:ÛÌg²DÒ4ÎtS^C›ðòFר®õ„\Ÿ?Óc÷×6sœ×(ù±µüEk\i¿¥_ThØuîdþÈëc Ó„×¶ñ=ZqmwÝYìeÊxx‹{=1Ûöbãî¦ÜR&öŠftkLˆ½î:"/* ›ñLì%ÊlC€½¶ºV °—=àõÔ¾£&ľЉì#%6bY<ÈNüÏmWûÚf@±¨j_«N«ö5ÂÈÔ!ê‘ìd1¯ñ“»J2¥<Ü>€Sôý¡ÀFÚø.b ¼¶!³ïr¹šÔ+°¡Oop)¯1äy°Êkäýz ž ØöJõ1ÿ°LkÙ§LsJ6°þzéS¨ýåñßð\>ùÏî•¥Zùè :é,5JµòÑNA¦|­{øèu©V¦|BøèÏHµµ­®€ÙÌÓ4ß•jѲ,¨öüø#ªðÿ[ª­x7-†ÜtžÓäYç†êžØû.~›4£ú µv¬#ÑräÈ_ÐÖ)¨„¦§ð¾„¶NásÙß“ÐÖ~ýͲA­¥Mm†Ì7äÚuİÙäÐßèΰÎAw›žÃÚ3¬sø\ùû3,jýfåÿ ÉÖ>BEØQW»¾—4Ûp·DÛp˜·T[=Ìk²m8̺-íx¹6€ý›ºôGgÙöþù^"íU„p˶ÃkRmKâLZyÝZ÷\¶=؉:w”J[¸&ñªˆ¼{ëÏ;&|Õ·tÙ6›ñ¸Ý¥£v–m)Á£%ò. ;ÉüÜ¢H &ï’DcÛŸä]Bíù•0zâðÿÎ )ï·®‡5.Ú>q䙊ÓyÇH¬ÜVNûƒš5/7ª™’PÙë4f"1 “çš ·°ã·o @´ûWáÝØ^Љž’®‡V%f*ìXª?Sgá6“¿}æt[$§×Pa5 1Ygî?5æÇNt‘ÜŽ%x©·Z4ÑDÒÓj+yó öŒpÚ^ͦ¯ãœI Ò#9ðÞèû#²-%Ltt?hæÔÁY’*·Å «ÍRHH ?Q’å[Êâ5±Yµ˜µhQzJ™h!éÛ5³º8[ÒÄZª6:[Qù–î¨Ù:ë·‰3á'úGŠ~ëÊÿìE2kÇ΂½³p¸'kâmÊÅÛÉ#%”¤ßyæsP#Æ+ÓøÕçLšS;Ý4WUõĽ6Î&îfn©ýe4àÿ»®ù–r«¨Fšñ#FTöµ)©Õû¨¤¶½DùJj³r¼ˆp uãì¯@êÊB€¢ºQµq!õ¥D>þßêA^cõ —)»*k€õ B Õ0ñv\C`ug÷i`õà˜‡Àj„el'º²º³×õÖTé!Àº±rûkr7Àz¸ÐúkÏú°Î¤¥´F”ˆ'‘ß´—üVXk[¥õj§âXZ¯ø‰ýì ´¶í_·X§´•2ÍÖ|ž:êÕ2Ø.&õà­¯ ÆEwiFA­ÊÓ'¨wzrzH7åôÒf÷×ÓCë(¦1i‰ ˜¶Ã•gAÒPJijBiär»ô8}P7õX•Ô5HI¯Ìª!¾z¹eEõh^\ ¢ZSO/T£!ÁÞ¦/ª¶ k»TO}ϳºpo…µAw?óÕ°ŽÝ`T‡¸5a5`G¥‚…ÕXš}o©µM†Õ«¨Èk¢¨†DïÑjXðd?}•Õ0Ò¼à¯Â[ÈU`…5Æ<âAaÞNH…5*'ÐsƒamC °F”‡*¬W»˜mž «1ä éÊjÜWþ“ÊjDÔnùOYmC”¦¯¬Vaùf5Ò0w! e5Dj$ª‘K„ï*Ø’ôª¤F†æçÔ+qßO\H~RX½*2œn;¬‘·ï/kHÇdà ¬ÑÍ#È‹VAàǗп¹K)¬‘ÄëV®ÂÚ^5Ž»J€¢ÝÞøDQ ñÓ#"ÖXcž«!a¯7[Åt—B9ÝG«)§»ÜdÊi,=“…Óç½®r%Žw Â…iÍŽþã}ÍíHv«µkÓ]­Íñ^ímþË3xÇoY·`ë|åH†¦õž~T»,÷ää³/è¥ö°¼¤I›ç±O‚?ûÊIð¬ïÅŸ½.Û꬟“ÐÏþŒpk6"CZ…aþ®pÛíÉ`oJf«ä³}S¸íyÅ©ÏcœOá– â´ze#=€zŸ 2§ºJá–§ò‹‡ŒíÎåØ_QÔê‡~Nâ’Z}Üpì—ŸM¿[üoˆ¸¼½ó\m°kK¯nºå3 ó–ccÓ]9ºéô$¾°é.çsñ_Üt‹a¿[ü¿BɵW8xÆ‹Yåµèá o)¹á0o)¹z˜×”Üp˜7”Üž‘ª²Êxµüo¤ÜÂBî¿×`<Á™ƒ*й@mC7ø”ê‰fyµ± fƒìk*’%iƒìn:&I,9¡”Ìz¿ÌW –§FØXYEÜìí¼-}×…Zi@’Iìû‰Òo ;»ñÛ?6•TG½êµQê“ vNìÊ” `yvò¥ •UËí‘ÞœãyDÁiF½ÕsJšˆëé96&‡ÙÛÔ@33s¹ÚÙRþ*E«ÛXÑT\ªåhƒ}Õtk6¡K”v¿þ×Ͻà×Ïúüó!*A×)"$VHr^Ua.— NyF6XVa·³äq O9Dz„‚ÃE›[Z…ÝÖ¶½’¤èüá}öïÒÝIcƒAڥ엜kÒ”\ê0mƒhêroà%Öìl뫺ÛÚÀ+'ÓËÚÛ»¡ Z{²— ÍöÚUþl«{¯˜í3µSy·reaÙ`JG¼ ?س…C&UÎx¥ñ-œØwdƒ"ñr¡R뚢»Â¶í7÷¾«ïîÉ oe/‘uMÑM[!°šVß­{ÿ&—#l¨üœ¾{‹â6(Bïɹžö´©÷”wØítúþM”Pbc}õÞº·oæ’ª·w½x…Ï×z–£Àܸ"?> ¾Jêmõ5@¥¨šf„ú!c õÊÞûO¬“¢­Xǯ’ô¨X_5¼®¶rƒÓ•väì2‚ìCN6€}pý…öÁk{ãdÚˆöÊ:ED»YJ®FG´Kîˆv›íî—Ôp?Øçá^¸ ã'Üy¸w „ÀõUè þ‚é‰Ò‡´àT¤ÃcD4P¦£ný–TÓÇÐ'vRðáaué+Õx é£ñË[d:ºšz×j…ú"–ë™Õbå:Dò´-¥zþÉ^‚åë1ð vZ:åúöÉë£s"và:ì+n `•æñ”"¦Boö¿U¶7¤:Þ—âƒíŠÉFT¶gÉ4 l‡=»#hí«Ã‡—|W´w~ÖD´¯×ëíkIû/ѾÂÜî¢ç窯RÈ|$¦:®Õ³ ƺ™rˆƒ±Ž"¿ôΡÖú@XßNJuˆŸ™­nV‰¥«¨ÛD(÷=@Ù»úuÔlço Ôµ'A€:ô»&˜~©éþ¦C<½‰yá|å²9Î8_ °lÈ3Î!š&-š£'±ë} óŽ|p¢’ª‡U¬#‹t×XçÚÈ õ¥ÒÒB Ô».ª#–‰_4Ç—bPÔíWOž…@}ýª¯0u±O²I„éèfËæ¿0}™ý=\Ž‚Òôþ*LG‹b L·ÁKX8_±þXRž£¯‡#žc ô(TžëçöE{ÙxÊݱöFà²ôÿüÿälØl endstream endobj 3 0 obj 33249 endobj 4 0 obj [2 0 R] endobj 5 0 obj << /Resources 6 0 R /Type /Page /MediaBox [0 0 1080 792] /CropBox [0 0 1080 792] /BleedBox [0 0 1080 792] /TrimBox [0 0 1080 792] /Parent 7 0 R /Contents 4 0 R >> endobj 8 0 obj << /Type /Font /Subtype /Type1 /BaseFont /Helvetica /Encoding /WinAnsiEncoding >> endobj 7 0 obj << /Type /Pages /Count 1 /Kids [5 0 R ] >> endobj 9 0 obj << /Type /Catalog /Pages 7 0 R /Lang (x-unknown) >> endobj 6 0 obj << /Font << /F1 8 0 R >> /ProcSet [/PDF /ImageB /ImageC /Text] >> endobj xref 0 10 0000000000 65535 f 0000000015 00000 n 0000000145 00000 n 0000033468 00000 n 0000033489 00000 n 0000033512 00000 n 0000033942 00000 n 0000033811 00000 n 0000033706 00000 n 0000033869 00000 n trailer << /Root 9 0 R /Info 1 0 R /ID [<7030C6040E75E4BF5D8333CC4C29B67F> <7030C6040E75E4BF5D8333CC4C29B67F>] /Size 10 >> startxref 34023 %%EOF blis-0.9.0/docs/graphs/large/l3_perf_has_jc2ic3jr2_nt12.png000066400000000000000000002767771422157504600233310ustar00rootroot00000000000000‰PNG  IHDR¬öEYa )iCCPiccxÚ•‘gP”‡†Ï÷}Û m—¥ÃÒ›T) HYz•^E–ÞY–"bCÄDiŠ AF¥H¬ˆb!((`A³HPb0Ѝ Ü¹3qîüÈóë™wÞ9çÌŠ*’*àû¹Ø³CBÃØð ‘¼Ìt®'ü#Æx ÿJtL&V Ÿ—Î ¹ •#H Ç€•”.@Γ€ÜfÜ_>̨¿|˜ü?@¢Å}ãQßø÷¨pù‚„ؘ\¶Z¬ '’ÃÎôs±g»98°}øi± É1ßü¯Êÿ€ &Wà–¾…Ÿ/`ÿßPcC##øûï|„5ø¿ÿ€oziœEìÀßYT5@÷é'gjÇD ºîñ²øÙe8‡ÏÁá+ñÍøNü ü(~ÿ@ °šs‚+!”HØJ(%%t®† S„E"‘(CÔ%Z½‰‘D±ˆXMK)Hq¥b¤öIµKH-IËIÛIÇHKwHJ–aË8É$É”é–y&‹“Õ‘õ•Í‘=&{Cv^Ž)g%Ç“+–;+÷D•ב÷“ß*B~P~QAQÁE!]¡ZáºÂ¼"KÑN1Q±Bñ²âœCÉF)A©BéŠÒ+¶$›ËNfW±ûÙ ÊòÊ®ÊYÊ ÊCÊË*š****ÏT)ªÕXÕ Õ>Õ5%5/µ|µ6µ'êduŽz¼úõõ% M`½Ý³šÒšnšyšmšZt-[­ ­F­‡ÚmŽv’öQíû:¨Ž©N¼N­Î=]T×L7A÷¨îðü‹5©k׌ëÑô¸zÙzmz“ú,}Oýýný7ja  ¾š&6>5’0r7*0ê5úÓXǘg\küp-}­óÚk{Ö¾5Ñ5‰19fòÈ”aêeº×´Ïô‹™¹߬ÝlÎ\Í<¼Î|œÃäøpJ9·,ðö;,.Z|²4³XžµüÃJÏ*ɪÕjv溘uM리U¬#­¬…6l››ã6B[eÛHÛFÛvªvÑvÍv3\mn"÷4÷½¡=ß¾Ó~ÉÁÒa›ÃUGÌÑűØqÈIÂ)ЩÆé¹³Šsœs›ó‚‹©ËV—«®xW׃®ãn n<··ws÷mîý4ž:ž|Ï^/ÔËÝë×Äzõõ©ë»½ÁÛÍû÷3MŸ ŸŸ} ¾>¾µ¾/ýŒüòýüþ›ý[ý?Ø”< Ô Ì ì  j Z v .†„l ¹*šÚF k[Üà´áð†épÓð¢ð±šs7ÞÞ$»)yӥ͢›#7Ÿ‹ÀGG´F¬DzG6F.F¹EÕE-ðxGx¯£í¢+¢çb¬cÊcfb­cËcgã¬ãÅÍÅÛÆWÆÏ'8$Ô$¼MtM¬O\JòN:™´šœÜ‘BJ‰H¹*‘š”ÚŸ¦˜–›6œ®›^”.̰Ì8œ±À÷à7g"™3{LAº`0K+kOÖd¶MvmöÇœ œs¹â¹©¹ƒ[t¶ìÛ2“çœ÷ÃVÜVÞÖ¾|åü]ù“Û¸Û¶#Û£¶÷íPÝQ¸cz§ËÎS»(»’výR`XP^ð~wðîÞB…Â…S{\ö´‰ñ‹Æ÷Zí­ÿ÷]ÂwCûÖî«Þ÷µ8ºøN‰aIeÉJ)¯ôÎ÷FßW}¿º?vÿP™YÙ±„©ÆÚuÈëPW»¢¸âýá͇oWšTÖ¡É:"¬ò¬ê©V«>P½R_3Zk_ÛQ'_·¯néhôÑ‘cvÇÚëêKê?O8þ¨Á¥¡«Q£±òáDö‰—MAM?p~hi–m.iþr2õ¤ð”ß©þó––VùÖ²6´-«mîtøéû?:þØÓ®×ÞÐÁê(9g²Î¼ú)â§±³gûÎqεŸW?_×Éè,îBº¶t-tÇw {B{†/¸_èëµêíüYÿç“•/Ö^’¼Tv™r¹ðòꕼ+‹WÓ¯Î_‹»6Õ·¹ïéõëû}û‡nxܸuÓùæõîÀ•[Ö·.Þ¶¼}áçN÷]³»]ƒ¦ƒ¿˜þÒ9d6ÔuÏü^Ï}‹û½Ãë†/ØŽ\{àøàæC·‡wG׎=>Š~4û8ùñÛ'ÙO–ŸîœÀO?{Vù\þyã¯Ú¿vÍ„—&'_ø¿x:Å›zý[æo+Ó…/é/+g”fZfg/Î9ÏݵáÕôëô×ËóE¿‹ÿ^÷FëÍù?ìþ\Y˜~Ë»úgé;™w'ß›¼ï[ôY|þ!åÃòRñG™§>q> |þ<³œ³B\©ú¢ý¥÷«Ç׉ՔÕÕÿB,¾;E^ cHRMz&€„ú€èu0ê`:˜pœºQ<bKGDÿÿÿ ½§“ oFFss0ˆÚÿR pHYsNNÆÊ/¥tIMEã$9·-ç vpAg’Zó!%Õ€IDATxÚì½{œ#Wyçýclƒp ÆhlL5,˜™R¦±MJ&x`;[‚72½oØRÜ» ä³àRñ ðÛ¹ã8xÿûßßp? ˆaÐIf?ûÙÏâÉ'ŸÄÙgŸ Q[äT×uZ³‰™aYE±ãÚO²Ý?äa0Žã`aaÁË?2 £!´+N#›Ízç’É$ ÃðÎg³Y$“IïZñxº®7œsŽã ™L"‘HÀ²,ï|:n¹V¯Ï'ˆ^è$ãÝÎ5ËÛ òJòMŒ›QÊ~*• Ýåw‰DŽã4llÄ tÓWši–SZ³‰YaPYïöz’í]à¥X,ºÁ?CµZueYv···Ýíím€»½½íEÑ•eÙu]×;_*•¼óù|ÞÁu]×àæóyïœ$I®ªªÞy×ÚÍó ¢:Éx?ò_*•\nµZu]—䛘~F)û𦵼OµZm‘k‚dÖu]W–e·X,zç›å”ÖlbVTÖ»½žd»ÈÃ:axÈW*•òBz‹Å"DQ„ae¹!,LQïgÓ4½°Ó4~ç»4Á× ‚AzO¯Ï'ˆnt’ñnç$Iò" Àªª 2IòML3£”}Y–[ÞïÐï1,:Él;šå”ÖlbTÖ{y=ÉvÁ:aDQD±X$“IìÛ·©T Iè;Èf³ 0E† &E'ït`4A¥d›˜%Æ-û’$AÓ´†ëİè&³1/ *ë4W†¬†RÊçó¨V«(•J0 º®C„ŽF«$IÞ®  hšF¹KÄÔÐIÆ;˜ÒnY²Ù,Ç!Ï1SŒ[öóù<4MÊ"†N7™%ˆyaPY§¹2|È`0¼7LEQô¸“¶ÇivY–[ŽñÄo‚˜:Éx§süwEQÍf¡ªê¤? AôÅ$d_d2d³Yj»@ •n2 t #ˆY`PYïåõDÁ:ax^Ò‰AAøPHð Þ·oâñ¸JFóŽeYØ¿?DQ$™'ö$ûAáCV‚ ‚ ‚ b*!+AAA1•üÔ¤0,>ÿùÏã/þâ/ðÜç>wÒCé›ï}ï{8÷Üsqî¹çNz(}sß}÷ᢋ.šô0úæ±ÇC$A.—›ôPzfyyçœsΤ‡±+fYN{ì±™\Wî»ï>üÍßüͤ‡Ñ3´†O†Yž›_|1>øÁNz(=Aë÷ø™õõû¿ÿ÷ÿŽX,6é¡ô­ß“a–çf¿ë÷ܬÏyÎspÅW`uuuÒCé›\.‡C‡aqqqÒC雕•¬¯¯Oz}³µµ…S§NMz}qÎ9çÌäw ̾œÌ⺲²²2é!ô­á“aÖçæ¬@ë÷ø™õõ{VŒU€ÖïI1ës³æÆ`e:„Lz»"Ø– Ú1«r2«ó’/´†ó̬ÊȬÎIb¼Ðú=Á:Ìâ®giiiÒC f€Y•“h4Šh4:éaS­áÄ<3«2Bë7Ñ ´~ÏTt‰ ‚ ‚ ‚˜JÈ`%‚ ‚ ‚ ¦2X ‚ ‚ ‚ ˆ©„ V‚ ‚ ‚ b*!ƒ• ‚ ‚ ‚˜JÈ`%‚ ‚ ‚ ¦2X ‚ ‚ ‚ ˆ©„ V‚ ‚ ‚ b*!ƒ• ‚ ‚ ‚˜JÈ`%‚ ‚ ‚ ¦2X ‚ ‚ ‚ ˆ©„ V‚ ‚ ‚ b*!ƒ• ‚ ‚ ‚˜J&j°–ËeT*•]Ÿ'ˆi†ä›˜wHƉy…d›˜wHƉYâ§&ñ¦årš¦yaqq™L‘HP©T iÊå2@–ed³ÙIWÑ$ßļC2NÌ+$ÛļC2NÌ"ñ°jš†D"˲pòäI@.—óί­­!zçËårÃy‚˜fH¾‰y‡dœ˜WH¶‰y‡dœ˜E&b°V*:t‰D‹Å¼žJ¥‚­­-,//{ç—––P,'ý]DO|óÉ81¯lóÉ81‹ìÊ`Íår8rä$IB.—Ãææf_»/‘HÄ 5€D£QïgˆÅbÞùàd"ˆi‡ä›˜wHƉy…d›˜wHƉY¤oƒ•¨‹‹‹ž€G"lnnbee¥§kd2œ8q‡ÆUW]…r¹ŒÕÕUè8)jµZÛs=ô,Ë¢°¢+[[[øÌg>ƒo}ë[#¹þ(ä¾÷½ï!—Ëakkkr_1är9Üwß}#»>­áÄ$ÙÜÜÄg>óÜÿýC¿6­ßĤáë÷¨ŒDZ¿‰IÂuð~×ï¾ ÖJ¥‚ d2¬®®âÀXBöúú:¶¶¶vm¨ÕjÈår8tèŽ;†cÇŽ!‰xBÞiBœ>}ºí¹sÎ9^x¡æ@˲~?pà.½ôRœ{î¹C¯QÉ7œ{î¹8tè7ò h ZÉI‹Åp饗âYÏzÖP¯Kë71 ðõ{Øò ÐúML®ƒ÷+ß}U æ¡‹‹‹-çb±b±X×]ÆÍÍMÔj5ÜxãÞ±h4Š#GŽ`yy¹! ¡îÑ ãœsÎÁóŸÿüб{]בN§¡( òù<&GŸùÌgð“Ÿüdèï7*ù˜ÂCòM4cYÇ,ËÞ±ÅÅEüð‡?ÉûÑNL®ktÓ7ú…ÖobX\\ijŸýì‘l:ÒúMLšh4Šhô2<øàúz]_V>yÂnµZ­«w`;4Í“0;Ïwƒa •J¥ëÍ€˜ H¥Ûn>î N#N#‘H Nü^º®C×ulooR©TÃÿAX|–eA×õ†cŽãÀ4MØÍ‚À0 †Çqúz¯d2‰l6‹D"Ó4¡ë:p×]wäó‘Œó É61ïŒÓÀ©SÜwßsûzM_+÷¢®¬¬4§•JÅ+ƒÝmwE–e”Ëå†<Ž'N ‰xy±‹‹‹ØÜÜôΛ¦‰D"1Ñ/—è ÇÒi€ëëŽã§–ÄãìgÓô_cš&âñ8A€,Ë( €x<ÞÎË•~]בÍf{ÇqDZ°°€D"T*]×Q,!òù<,Ëòähq$ß{]בL&aÛ6J¥L&Çaš&’É$‰„çùO§ÓH&“XXX€iš°, ñxÉd†a4\Û¶m¤ÓiϨåÆj¡P@±X„¦iÐu–e¡X,âŠ+®Ég$'æ’mbÞ!'Æe1ý¿nüÒ/Uñ’—ôWg£¯`X__G:Æ‘#G°äÙ Äb±ž Çb1;v +++^XÏéÓ§±¾¾î=guu+++ØÚÚB­VC$ÁÑ£GÇù]}bš€,3E@’ØqÇ’I@˜áúþ÷—ñõ¯Ÿ€mº.¶m˜¦‰B¡‰¿¬(WðEQ„eY$ ¢(B@"‘€¦iEÉdš¦AUUO™Ïd2Þs X,B×uhš6²Â$ß{ 3°óbš&LÓD©T‚ ž ‚Ð Û¶mC×uˆ¢Øðàd2Ï8ÕuªªÂ²,†MÓ`Y²Ù,lÛF±Xô®-ËòH¢š!'æ’mbÞ!'Âp_ï]g†i&ÃlA0á8{ìuøàÏ… Å"ÓÿæÌê#€¬…¾ ÖH$‚õõu”Ëe/4˜÷qê•¥¥%,..6”φ(Äb1Ü|óÍž—bâ§nÞrKÅâA¼á é3 Ë EÑèa<ôЧqË-çC–eˆ¢ˆßÿýþÝ¿; Å¢A°°À ]QT•)à<œ`“CUÙϦ ¨ªT*˲°±q¾üåËêÏ 2Òiv=U H§ˆ¢Ó.¼ð"ˆâ7Gò½|Ï.Ü‹oY–glòãŽãx›&–Åä[–eï9‚  T*5\/Ì€E™L¦ã8DQD¡Pð" $Ij˜ “†dœ˜WH¶‰ià?è/¿¯HÆ÷.¶n”&“ì\©ä˜A¸¾0½F×™N^,<òR©*øß8xð<|ò“@ =Ã…F,ö6œqF ¯}í Èç—`þæoþ¦ïí¾ Ö­­-¬¬¬àäÉ“}¨a°¤Ûö1ñ<< BȽ>ýâ8²ÙlK¥]Û¶!Š"$IÂ×¾v^õª³”sUU=¯‘mÛ°mïyÏë…?ÿó?Ù¸HƧÛ¶aY®¸€iš8uê!üýß_…g>ó™øÜçÎE:ÍtbIbúõYgUðš×<7¾ñYøâ/ðôv¾oÛ6^ýêwà_þåßá›ß|ÏxÆ7ðìg_dò9uýþ=xõ«ß QÞó@?uÃöQ(°È²DâO Š".½ôRœqÆ}}޾ V¾ cš&–––Æø§#vWÀ5MC"‘ðò9ÛÁOI’ lÛF6›…¢(( m_›H¿ó;€(¾(ô|sÈ#G–jµñ˜$ùdÒ7ZUÕ7^ ^ð†ÁB øïÍ× C’€ýèQœ:5ºLbrÃtæù4 à =wÉdÒ»†I’ ˲WIºR;¡"‚ ö<&“É´ÝÀä9{Á[‹io|ãñÂ.ãõ¯Áq¤R)ÈrßøÆ8qâ?ãꫯžôÇ#&H2™„ã8žc¨Ç²Yæ¨ SÍyÑQA^†›o~7®¸âoñØcؿߋ_üf?þn¼ô¥×ࡇ–ðÚ×~‚ `{û(þý¿×qÁ·ye,ÕND*\w3táBw„Ž=8U厤ÆÈ²­­-œ:uª¯ï¤/ƒ5‰`uu¹\®msaÞ|˜˜,\X¹‘ÊÄL&Ã0 ë:dY†¢(e†axí_¸7Õq‹ÅŽž$^TiØÎ&IbÆj*ÅBÚÙ CØ|"ÚÍf¡ªjËF÷®O ¾cšfèB.BÃøxþs0\·T*y‹ùn£¦Ûf7ŠÂæ!¿‘Ýu׫&=4‚•ÊYxüñ³&= bΈÇÙÚùæ7¿þëgâðaæ•ä:–ªªH$PUš¦`¯7M¶&çóÀ•W>…7¾±€Ûn[õîY’ô‹øÈGþ¯xÅ%€_ûµã­o}ÏzÖ_ceåzììÜ6鯂˜ét—]v=´„ååÜvÛF¨Žò¯ÿú‰$)ë¥à=õÔ3qÏ=?Áë_ÿ< …z–?ªi׸¶é*iL,…îݨ‹rã3K˜(}ç°®­­666BÏïƒÕ¶™RØÅ!Ó÷ôðbAÓí)ò¼ rMӼХТ T*yÅ[R©DQìjœ†ÁåQ I“Ÿ {•T*Û¶aFæ1Ïd2Pëñ×AÏ|»ðJËe“çƒòëòðY–Bq¹<ókض EQ:îh÷‚ žr1‹XS¦D‘­EÁ#Çaç~ú§ïô0 ¢-–Õ¸iYì~â8ìgN&ÞgLÆùÆÌ?þãspþùϘôÇ FŒeY°,˻ߌÛ¶ñ‚|?~üUüÎïü£§WqÆ H¥N#—»’$Á4MïÞ¨( R©ðÔSᡇþçžûÇÐõSEßýîÿÁ¿ü‹‰ÍÍïࡇ"-:“m_ýê åãÅ/®á†V±²Bë^„ë<‚P‚$–µŽ••ßÇ_ÿõ~ë·Á—¿ü D1‹;ïdЇþ0.¸à¿"Ÿ9¶N^ýO ËOƒ(úþ^ÕQôŸ›N³µ8Ÿ¾Sj7ôm°6ç2Î;–ÅBS›ó#MSÇm·ý÷ î¸ã\pÁmP¿÷{2Þö¶³ð±½¯yÍù^aHöºW7«üº¼{ Šk  LSÀk^Ãd>H"ÁƛɊrä¿nbLèºÚ—Ý0 ¼ó‡ÍM&™L‰Ä),,,à¼óþ#®¼ò¥8zô¿B’>€ÉZ",/³ùÀêµ<Í;—ÍîÞñÓ¥6äØéÛ`ÝKpcõïüWüå_F Šwbgç1üöo?ˆdò,.–ñ®wƒ¢œï-ŽÜÓ,”‹½CFTUõ¼­|€+û¼5 _ì¸'*¨¬«™òÅr·§AŒI¢°ÜY‡‡ˆs/§¦i^®ßÕ^XX@>Ÿ÷~/‹ž·•Ëž¢(H&“Èçó0 £ÅËߌ(Š-…2™ 4MC6›H¦gî-åÓ2öC~§¨P0AxèºßÎL˜Ì~~oo¦ªLŽ›¡æßY4GÖÛ¨buz÷óA:ö6ÖS©ŠÅ"¶>¦R¬Bi3–ü‡ÿðÞøÆ¿Â-·TðƒDqôhÙ;ÓM/B$ò¯Ø¿ÿH’„GÙ¿û»ÿ‚ßÿý{qäÈ»½ç}ö³@<ÅC5Ŷ-¶UïOÉ0 &Dzìo¶7p%<½)“ñ#ˆù#QÆç›ûaQªª"•Öºb˜ ×á]5Ø|hÞ¼¶•™uve°nnnÂ4M¯—åââ"dYž«BLÜX-€dò—ëàæ›ozÓ›ðÑ2/T¹¼‰xüÈç™UQ;¶é…ýf³ÙÐ>£ó†v«Æ»`‚5ïF>Œ bƒ0†(bÄðßvªª†.¬Í­Y$IB¡Pðòy:-²à=L÷"¦‰†ê}œv¥æ bRóôýÌ=^ªÊŒØD‚×uvïR¿(OhÞ”²mÛ‹æXñ]‹Óeõg˜ñÈ1^c@×ud³Yhš†/¹ŒsÏý’ÉÛðÄâì³ÀSO=?øÁ;pç—ââ‹ß‰hô2|úÓ¿ŽÿüŸ/ª2¹L$€×¼†E–}}êw„ÖÎaž)Iòe›#ËLWì¶¿v‹íT ’˜,þð'qóÍ·áÇ?>Çq<#“;•²Ù, ÃðÖ0žÞ$I’çtEŽ£`{»Q´ñoÿv7þðU(ŠâEX–¿Fò^¨ýD.jšÒÌ<íù÷m°ær9lll`ii ËËË€Z­†µµ5”Ëe;vlÒŸi`XÏN¶Ù¶Y–§FØÚZÂe>ü|¼÷½E¨ªÃ\7………ºâ^òv ƒ÷Û`_Ñnw©yä ßÕÅɸ2Ob¯ôâ÷ÊÂBcË¡ ’$¡Ú\ú™èYnU’ö¨íNL1ŽÃöW¿º Û¾ªªBQü›¿'Ù6»Ï±{–………¤—øÆh0Ò‚o ñÍX¾ñ›J¥Â.‰é¤SF]oo°ž<ùUÜ}÷ñâ×°hµL&ãmRäóyÄãq¯ÝG&“,¿ïxÇ“ø§z€n8¼Î ¨V¯¯-Õkq0yâ^ö xÒé§C×Ù\ÙÞfº”,3}^Óú¯ìM¾ ÖJ¥‚ /g-ˆ,ËXYYÁòòrÇÞN³€,û¡wºnâ7/ÿMï\ØB|ç1oWi £‚”B6›ònì’ÄþÏçýœ¦”Ô¶pÃ6¨¸f³LØU•M„xÜ¿ö8à“s—N4bJ0 #ÔKÏÿ¾AåëB-¬\ÖlÛÏe¦Í Þ#¸¿›Ži²×íæFEÌÁBZã",…¥—q~ðƒ?Ä|ÿôOÇ Ë2âñ¸Eä8Žçu`›½¬öE2™ 4 6¤ÚãXÓ4$“I¯*+üÏÿù?ûnò ˜æ3êáè/j;® ‘ÉΦhįQ¬¸‘àAå^SÓ4ñÿý€}èÕxó›}GK}Ê£V«á¬³Î‚(žHltàX–&î{ÑÏóÆÐ¼±C!áÝéË`ÝÙـЛÛââ"b±vvvfÖ`åÅ•+ZÈ[yàµÚ(‚Ø¡³ê‚'û»Ð|W+¥<–ð*ÎÂO ˜ÐΨ Æ·Ë2»v2éǬÌüݲü ŒügN/†'÷è þ‚OÊlÃC׃4Ëm3Á&^<%¸!3Ì"\Íùœ“†1àcâ›Hé´ŸKÂC û)H ÷'ö|cˆQ”Ö9ÇóAwãiçUw¹2”Nû÷®˜Y–åÕXàm¬tÝÏ›V¿ÿû'ñçþb<ñÄ3ðãÿ+Î>ûKxç;#Ð4f‘ðüuî ã­Ò¸—Œ÷o׆ªƒ™{ØDQD:ÆK_úR¼ä%/™ôŸÀ×EI.»ìA\yåwpæ™ïF¹üÄbmÛH$RøÔ§þ¯xÅ%Þ}FQ‚‹ß‹\ÇñÃ#yJÔ?ø†PÅ~·÷*¹wàÕw›» X–…D"EQ¼ üR©„lÖß„çÅÞ­‹KK‘– ç†ÑXc" éÎý³«ÖZ­Ö²³Y«ÕÚöfšcÃ`áÀȰÐÖ`m¼€ºÂ‘J5*ýÁjž’@ì/üç ?äÿ0êÊzGEÖ 5z…9Í¿óòÖ¼xE'# ›eÏ—$ö|¾ôíÚˆˆȳq7|o¦ÿÝ£‡{6DQòŒN^q®¹*v;‚J´ª²EZQü|Štº5ŒžË’$ù9›|žjÓdsˆ+@šÆÆÇw&¹"Ãs£lÛÏMâ9K€ÍÉ4n µóh%“¨‡õ³ßy8?ßpjÙq6¾àP>Ï¾ÇæÜÓd’3èyà»ü¤<Í7\éáëfpc¨Y± ¦‹ðyÜÔpo}ë)lm]‰³BCЂs‡Ãç¸mÛÐuÝ g»å– R)àÿð=X^>²,C’L†…l–)wº¾XïAùb¯kx?Þç˜çlqxïN9ò½ÂsÛya·‹/¾¸ïÆóÄàðnð²—]ƒ/}éK¨VK^ë2I’°°`ãå/ÿE|ãY¾ GŽDɼ“í~”­‹Š6‚À+¦NúÓ³H°Òts/É =òuJ×ýû4ÿŸG“5GBñÐò T q¸}rÍ5׸×]w»³³ãÛÙÙq¯¿þz÷Ê+¯ì÷rCãöÛow?>Ôkªªê~å¿âº‚ëºù^°íº®\ÿ¿d×-Ý캊¸ÄÇ]wû"×uµß=>·2×­Vë—Þf?—J®›Ï»n¡0œ÷p‹®ë*!Çe—}Ͻ|w¥>>ó¶ëºU×u›Æ_*–†./£æºë®êõòù¼«iš+I®«¾Ïí^å7„jÕuUÕu‹Eö{¡Ð(ßÕªëŠ"“+þ^\æøï²Ìž#Ë­c)ÙXùõ··Ùõù±R‰ý,ŠLnýÏê¿£,w~/N¡Àž¯õ9Ï4=‚×埛‰žÙÞöÞpØò2jF±†O ¥’ëJ[c]—É $5ÊhUeíímW–e÷’K^á¾àÿ×-]÷æ›ïtEQt5Ms/ºè ÷ãÿg×u™ e2¾üs™*‹®ªª®¦inµ> dYvs¹Ïycãs²Z­ºš¦¹ªªºù|ÞÝd11³&/³6Ã(•J®(Šî{ßû÷ç~î îyç=ìÆb;n4ú¤«ik¹ë2ù„Öã¢Èä¿ù8á3kò2­óQUUWUÕ¾^ÃïùÍhZëšÝ¬?½±yéÛÃÊ«´>|¸áx4Åúúú¤íïÁàù õÝj˲p¹r9óú5{› :€`(­ æ5ÌPüë´Å¤`?èßàÂú5š±Ðè•LÈôð>="ÌT,ú^§†z§þž½|¶võׇ}辶æ8Àko>¹ÄžÛ )Kÿ |õÅìûË8YÃ¥«—âžkîÎ7£ðp`Þz‚3H¨Š 4î4ro+'›m¬€Ûü^<„½]8mXÏÑfïT0T—ýU¼ú·ªöž/ª(€âðj!½WçÈdXn¹aøs*èd ީ峆U4ë”èê8~|vý‹:ç?èëoG Ÿl–ý%©Ñ«Î#gÚy—òyv¯M$ôzq¿ýÛ7âWu ?ùɳñ©O݌Ç/ƒ¢°pÞûïWP­ž‡¿ýÛgâž{îÁ¡C_E6û}¤RvC¿íx<îµIÛØxvvü4&›{·B7¯ ÷¢F"/ÀùçŸáõÂN§Óxÿû?‹÷¾7U züý¥'H»´ž‚DEŸ‰acYLÓô*ö²Õ<z÷zòHª ©TkØ/ÀÖj ï}¬±X ·Ür ¶¶¶¼pœC‡aqqqÒŸe €m®<Èp` á¡ÀVýĬ?W3^9zýw¾Ái²÷H–oyå¬S!o<›`äóÞÚÝ\0Z¯¿w @»‰¯×¿þùåÀú¸óõóÜ8Mx°nn¸@ ÜÜ «€¬<üÁcÀÛ¤%à‹÷ßüÛÖA†ßg¡ôBŸžz&pû?ý<÷½ÿ~|ÏýÞð¾¼cyù¸í¶ P(Œ>9”W¸vö§é¥‰õ®Ãc»$Ž Bã†LOðšóÍrfY~E5^æ¯é½‹¯z?{_û±i\ºÎöÁòM×M&}ùåñÍ*9ñF­Ü ¯'|½õÖ[wù%Àç1‡¥tp‘qº®{-x/dÖwTôBv`cco|ã÷ñìgÿW]uQý:ŠÅ"²Ù,öï>ö±8$éÚÐñ(ŠMÓ ñ<«iÉ'Ƈ®ë^hïO\ˆJåëxÑ‹žI’ IÞô¦ßÁüÏÆM7±Ê¨Žã X,BE¼þõÆ&+ŠÔû{“‚OŒ^ÜMQ//^–e¯ÏËç´KÇÉdZe”·ŽiÞd¡µsŒìÆ•»³³ãÞu×] ®Ý`ˆð¬¸—9¥RÝý_tYhªËB¦JÁø½æP_©~¬ÔÈ®ëfÜÆ0VÍõÂŒyøt¹ën§ø š®ÑÚ*×ÇËŸZf;þÏÕú˜Ã"#”Ÿ#ï²P]µ~ ·>†æP­þ9µÀ¸ø¸ƒ×âßA&ãºo~”=wéïXŒeÓ´ÆñðÏ­Õ?“$±/,ò×®«žXª¿w>ïÇncŽJþßlZÃW:1Œ¡jÕu/¿üGîóž·áæó½Ä¹Ue¡a=…¾V«~ìd;Âbs2ö&}†ÿ„ …l³+IìxµÊþ Ÿ¬VÙ8UÕ=æqÈ,æ³ó8xÜð.bŽ(¤lr‹C···]UU]QÝL&ã‹E·X,Nuî´1kò2Éùؠ˸,D’$·Z­ziÍ¢\b¹ŽRêEß!†­ßýQ­Vëëév‹,󔇰ãüXµJ¡½ãd7òò´~ ÜÍÍM>|¹\Î;vâÄ >|›››“¶¿w…×¢CàøÍ%Ib!¬<Ô7X±7S?f÷ðø^QŽ/¬VQ˜³¦ð›€x^ý|sA¢˜çV©£9,7xí€c›À«`O~Œ!ÌûÛìÑå!É*€*˜W”ï,)ô,°¿_ÂRP €žô+Ðw©LøáÀ‚œzŽço2·[&Ãâ-_eãáãäŸ;à…ç1™ _ø@üÏ‘û{eU@È’Ú¸&yt÷ðŽØÁƒ?ãdñþ÷ÿÀó²ìîaäa:ôiÒ4@{Û&A3 „W&jw=Ód^E ð>òxT*üµÉ$ §H§[ß7x­DÂ÷¬†uñN§}*w/„¹ Á÷|no3Ù-ÙϽÄ©*{>…iN„tš…uLTƒ"Çi}^ð¨]G^•R’$looCÓ4/lW$×1dt]G2™ÄÂÂÒé4²Ù,t]G±X„ ^𝆠øÑ0ÜÅ‹/’7iÄd³ì‹'ú&™Lbuõ=ÈfEd)uï‡xwz.Åáa²à×êÞþ¾<ä¶9ĸPóŒÄÆ2¤lšÖðqÂC}›«FóÐ_I╪5WE/ì>ŸÏ»²,»²,{•z‰Á•¼LëúÝ/Á°ßv¨jã²Ç—ß°abÄ( »ßhšëf2´~w¡T*¹ªªº’$¹ÅbÑ m¯VÛË.×÷y7brŒ%$¸§OŸîéy¹\•J'Ož„eYˆF£ØØØðί­­!²,œ J%ÀqXsúR©äyQUUE±Xô<[Äô2²Ýö˱¬ÆÓlõ2Fû b„ˆ"»ßh ë#­ò>Ë2®ë:âñ8Òé´×ÿY–e˜¦ÐNvy?wOÌ}¬‹‹‹ˆF£X[[C­VóŽ×j5¬­­`U„;Q«Õ°¹¹‰cÇŽ!aÕ`ßö¶·áÀ€J¥‚­­-,//"‘–––P,1ld™)\÷ÔE½5H[Õ àGÿxá/­Â‹™ÁŒÐtšåur$?þ1°pGàZ)àÿü„–6˜V”JµÏ…ýð¯ßü÷ÀO}åÝ™&Ú"øã¿ðF#BÓ|EŸk`XíëÏb¿ÇãlK6 †´Î°íÝ•“ä9©Å"{í¡œ&ùnæu¯ûC¯)v¶Íþ®ñx£F³[xî'Ï5î•N²ÅKôõ{Í^P”Ñ\wN™fß ßþö#8yrßýî& ¶$³ªÖ–—û—Íf‘J¥N§‘Éøm9t]‡Õ4_R©2™ ¦3Ȭ˶ã8^øyØæˆ®ûj@>ïËq ÿ\?@Qðª»îÉÛ̲ŒsÙ. (‹ iŠÒ¨b:°o_«:ê³Søï,Ò·‡5›Íbkk W]uŽ9‚#GŽàª«®‚išX__÷&@;x¼|,C¹\ÆÖÖžõ¬gauu°³³ãçÄb±¡ÆÑ;ŽŸ{ä­çPþr©…”ïé4ÁŒÑTŠ­àGb@<¼ór¿( ïƒúäû€ÿù·þÝÀ0€g-¿äúo,À›n¨J5æÛ5Qâ¹|ß»¸ù3üš ¿X3dØxö_ hM[KªêWuâ¤øûe€í+•b†isþ oŽ9ˆWil×Nƒ|‡ÁúäYá+Ïÿäy›í …½. Þtr˜ ;Ï•Ý#r4ÍL«Œï†O|âKe ¿ù›á/ø{¼úÕ¿ Q~ã7¾„d2 UU±½½í)HÜ 0 ñxÜk£ÀÖt: EQÂç1õ̲l;ŽƒD"QQ(B7L¸ÿ¶œ6§!&€¦áŸ_úÒ‘\zeÜqÄãq‚€|>ßRœ.¬F£ 4:¤‚4÷n'fƒ®}X+• jµš'¼¼«išžà/--A–宯*à‡ ¯¬¬xãôéÓX__ï:)jµZÛ÷¸÷Þ{që­·¢\.7„ Ã0û¯€Ì‚Ko¾ßs°±b®¿ò¨æqå}uÝ78ÿùÀü—ºÇTbÞÐÛ +&ÃŒËkÎîwg ßâ¡”¼ð‹…ð×`ˆ.Ÿ‘–>;Û…6rø–j§mÕ9ºƒmnn⦛n™gž9ôkJ¾à¾ûîÃÊÊ dYÆÒÒR_ãŠÇAp«òIjïi öåLÁŽ+ÎÊÊ î¾ûî‘\{ÖðaJYØÜü7üÝß<3NC×  …BƒáÉ•¥t: Ã0Ïç!I’g´f2†R/†‰pxõo{Ýæ¾“Ëåpûí·cÿþýC}ûi]¿»ÁUUU;ó"Ïé˜ÉfýB”}°rìîþö·Q.—»F-öË,®ß|ó°l§ÓL¶›¿fÚ7œN¸ÞïúÝÕ`€ T*,..B–eÄb1¯ ¿ww¸Pçr9¬¬¬àäÉ“ ¡ÆÍœ>}ºíd¹øâ‹qõÕW{»Dp@ù^ã±Gîx¶h³ÐZ®‡›hÌÑ”êÇ4Æp—{2Æ ¦AòùFC·UmŒWh7á$É7¤ƒÇˆ®,--!âÔ©SC¿ö¨ä.ºè¢]Ý, xõ«Äã·Ùtnœ´Û˜˜£ ‹½Àúú:VVVFríiXÃŶmlnn¢PÐ Iþx2™ E(ŠmCz3M© ’$¡P( ‘HP(ð ð6Q¼ÀO:ã=Wê¹æ«««8tèÐÐ×ði\¿»4VEQmÙWä„<'„·XSÕö÷Èæ¾W¶Íþ@<²)äÅ×ïa«Àl®ßŽãt܈áûíÄl°[¼kHp4E6›Å7ÞˆX,†ÍÍM9rkkk^¿Ò~8tè4õÑ£GQ«Õ°µµÕq‚F£Ñ¡|YšH—¡¡Òw¾óM“̓æ…B’˜Ñ¼[¤M9³&ã¶m{º ÏU媌ãŒ%ð‚Ã`s&›eÀzýç~æ3øÁ9çôu©¾<¬[[[X\\løÝ4MD":t¨çØõl6‹••oBð„oÎêê*VVV°µµå%y=zt(ßeù€`ÕzÁü=íEþ“°\ÕŸú—֦хIÊwtº‡zéôîÛ ¥ÓTxi2-2Þ‰tšéœ…‚ïDªªâî»Ï¥]yÛf_ Wâm›)áù|9ë<Þ”çä_Û­àß2 ²ÍqQ/‚^§*ž ;ªÓ‡dn2™N7–A˜|;»Oñö|Åbk?ï°/ˆÏ…9d–dܲ,hšæm¼7döLäÀ¨±m? ¡ÛÊN®\wø½$èás‹7À­/Hw_|1í3‡µ'ƒµ\.CÓ4T*¯|¿išÐ4Í ØØØÀ±cÇzª~‹ÅpóÍ7{ÞØ ÜËùÝbYõ5OóˆÖ VÓ4qEü \€ Ø^\éÌwò|.XÄ蘔|±m¦C‹L¾Û¶³Ùí† …ïi¦AÆ»!Ëþ^Œ(2Ç!` P( ™¤4^¥Eé=¦Ž/,|íàÓ`q¤gd›cš¦ç} Ú\A'£mO¡Ýeš½WÊI§Ùó‚жýŽ \Á6ŒÖb—Á×ðÜèx|Æ-øÁ™%·m‚ ´§ñ8õ \äÂøühéÿ 6‡¸kl~ï@ûÜì`7’­­¾‡Ù“Áªib±²Ðž»Ê{¯nll —Ëõ\®=‰tœÝÎïèª[–å/3AËcýÞSsq&ÆÏ$ä;H6ëGÑu4Xw+ß–E…Áö8“–ñn 6Òi‚ zÇæÓôJÞœ0,œŸý¸' ÃoÓÁÃ&ç”i—mï­mšLWä2í8¾ÑºÛš‘Â{}wë×Íe¹Ùâæ=ìMÓ÷ø´kÉDQÚ7 ÝcÌ‚ŒÛ¶íå¯6W¿æÝ#÷|¤Ì0àmÄT•ïìúïÂæÕ„v º¬[[[¨T*¸ñƽdìZ­†r¹ŒcÇŽyÇ–––ËåZ†§ ˪ÇI°j¿^ûÒ¦¤n̨½üw&=d‚ØÁ{¼mÛá—xyý^i®n@7}bJáο xëºY–Û¶ý˜ ¸•›ò‚5úp`ÓlÍ/%ˆÃËkX–5ýiíàÕÞ ?Z“‡ù~!ÓdÇùçlWdŒ6€ôÌsW766°±±áå³Î )6{ض Apö5g{ýX b–I§C!MÓ®R³Çw÷ˆÙ XO,›ÍΆÒC»çDè:ðÙÏ~i´rÍ+ÈO{=1—$w˜‘Æf‡E' }¯y\…åw¬ ͱžéÉ`ÝØØÀÒÒ,Ë‚eYXZZÂÆÆFK»›iÅ0-ët&Sæ%IbÆjóæE°44AÌÁ.5N}‡f¨y{”·JL9AcÕq˜¦ u‹R˜fã}† V¢GÁÄë_ÿ¼Ñæd7÷ᡊº,,°¯ œLNú+!æV7mV[e³¾Ç4¬9²¦1E{[)b­gº¬¼]Íòò²wluu¼V7ÓNCj@êP=ðw?b†ÖliÛΆ³›M™ ÁJJ 1…óWu]Ÿn覆‹ ¦à̪‚FŒÇÑG¿ ÃóWý7e ¶e±pÆím_^In‰!òÇüo°m{ô!ïýâ8½éM†Ñ}NäóLŸ !ºÒ“‡hÌUD"“w_4l^«èn°ÄŒÓuÁÔऊuÄ”À?.ö†aLλÚì=mžo²ÌæŸG~IôÀ¿x¾þõ³Æ*ôÉ2ËÅËçýã’Ärëf1l“˜ZŽ;c:£bt­ã‰3Jyþiósz-T¦iUÓ'=]še‚abìw»}8M0®’ f„æˆB˲:‡Ô ºPÒ!¦„TÊߨæN!?‘*“¶Í”?6¹1—‰£ªÌËJ»ìD¤Ó6b±#ý¨m³HУÖÖ”kbÄ|å+ßÁÓŸþ§PÕµI¥]gÑŽãïŠb£.ä8{ª/긙{ƒÕqšÖÙ`kJÂS/1óLR¶Ã°, ÞQ¼¬õdX•_¾££it]ÓÌ´Éøç?ÿC¼ìeO~!¾‘ØMG±,_ß—e¿Í ß줜թ£g«iš8|ø0VVV°±±á=VVVpøðáïÆææ&*•JhxA§IQ«Õúþ€Íß<òHgežòˆˆ§|þZ ô˜¿ªª»—sIb 9í>îiÆ-ãÍðTê0ºzXe™ að}ºí¹{ï½·ÞzkK5ãííÀ/2°qéÆäªGSÁææ&Ž?Ëê%F¼?F%ßpß}÷aee›››-ç¸jÛvwù&ùŸ{VVVp÷ÝwäÚã^Ûéä0ê)^QZÃ{ý ø+Ïùã›3²ìïÈëúÔnÚX–…D"ÑðH× ˲¼Ÿ›IB¥ Ã@<Ǿ}û°°°÷œr¹Ž?Žo}ë[C½î¤Öïn†Ð¾MÏU æS›&yˆf¾~÷ãê•I¯ßípà-où…Á>\0r&8š¡ù1Q¸ÞïúÝSHðÚÚZÛ*a²,C–ehš†µµ5ÜrË-]‰D`š&LÓD¹\ÆÎÎr¹–––:VîTZûâ‹/ÆÕW_Ý5)¼k¸1÷,--!6„¶‹QÉ7\tÑE¡m£Òi?"±c˦aA}#§žõõõ]+ݘôÞ©7{[ïj2É hl懵×bKŠ2µañNÝ¢ç9g¶m#‘H@Q8ŽÓv£Î¬'¶m#•J¡T*AE8Žƒx<I’¦f³wuu‡ú>‰õ»Ž|ík¿Iº(ü ™ {’®3¹äae´FÏ,|ýV7Ž “^¿ÛñÓ?ýi~^Ódë·ª¶_ã§÷už »ÕÁ»zX·¶¶P©Tð¶·½­ãó–——Q©TºîuËy=pà€Æ°„J¥²«>P¦ÉÖp8§|Nç–61ã”oNp#±'ë HÒ`fˆ™g2DÛ¬º®C Û9o^Û%)ÜËÚëfÌ JEÑ3<{§ðû¤ Èçó=¿~–™´l‡ñÅ/~W_}Sû'ð°_^_€zF˜F7M¯}íw¿OÓ»I$¬…X2ÙØÂ†˜ºzXËå2¢ÑhWaå»2ÝbÜ&K.—€†]™ÅÅElnnzÇLÓlWê^[ÃÃè°CdÛ,îʾ0NùZëõ9™ Û¢ÝÉ=˸e¼™v›ã¦iB–åÖ É° Yö‹s4?wrþlÛn ý•eÙó¢v‚‡ž.,,@Q/Šj/0iÙæðTj&º‹Ã‡{ðæ«ªïe‘ÍbüL‹Œ›¦¿ÔÞrKe8‘aÁ>ÃÍn?ót5X#‘H×ÜŒa³ººŠ••lmm¡V«!‰àèÑ£}_‡§vp¾ø_¾ˆÿíß̋Ĉ–|­2ÞuÑ7Mö¤ª)¯ŽJm¦Œ7“L6Õ&¨£ëzxº‡m·¦²^˜c—ÑíòBÇE/Fe/Æ*§T*Á²,†t: Û¶Q,§&$x’ŒR¶9ºÎ6#H§Mx8{'T•*¸CaÔ2nÛÌᩪ̾üÄ'®aÜ1ø…{™'ÄÌÒÕ`Åb¨Õj]CxÁ¥H$Ò×ÂâÝc±n¾ùf/¼x7ms8ÁµûöoÞÞ^¡ï´3C»dÔò ø›écÉ_(tžh`2αíðhGÛ¶aÛvïž@Q ß Üåü™´²yÞ‹¢ˆL`SÊ0Œö}ܰ•eÙ3PÓé4t]G~Ý#Ç)ÛAüŽl¥§u]ȳJôÍ$dܶYT® 0uâ¼óФ«¿0m¨Í5=¬±X š¦a}}=Ô ­ÕjÈårX\\Z’x$x’4´&Kûöáà<ØúÄ^úòĆ|!˲zó°*ç”ÃJôÀ°d<ˆ(†t4Æxsøfšó˜˜“6X»ÑÓÚPÇqèºÞò™2†×œ›¦( DQÄ‚×Ç4MïõÄèñ;stëæ|‚˜‚‘ë#¯»AÌ =µµ‰ÅbX__G.—ÃÚÚZËùÅÅE¬®®Ž¤÷ Ø6@@°vø.±eQN1“¨ª¯c÷Ô²iÐp^ò®$‘hÍ_åJ}[`¯2¯(sQÇ@–e¸®Û÷¹àñ|>ï…Y ‚@ å±,¶¦sE¾­\7„Äìà8þRÛ¶Y3é4{QØí8”¿½èÉ`|£•·®)—Ë^¸p4E­VÃÖÖÖHÃdúe{@€@å¯sGP¤y;ŠŽÌITbïÑN1M³³wUz—ù9ñ°ƒ`kb|H‹òM§Î¡æ¤·3J0Š=ýÑVŒ=‚ë´m³ß5 Ö9§gƒ•Ã[Ü4/¤år+++m›’O €Ú¡ M°¶6A̺îŒE¹l·ÃI#†÷„o=nv.Ô©"¶i²”Rü‰)Ã0 ”J¥ð“ÔZŒ˜z –$jM³Çé)‡u±,¶¦Ã ³ü¾ÐÐI¢&ÂÄÌbì˲z+ŠB!½ÄŒÖµ§¨‚NÈ23Z bJH§o,C–åð5]×Ùƒ6YˆÄ4™ŒlSfÚ ÖÓÃܬ¼ð/ê‘bmwqˆ™…‹tÏŠ;å<3J˜Á:…G–ÙÎÏ´E{˾þõárÍÕb‘Â׉™„çh³Ÿ­Îë·ã°Â96X%©*Y—lëa%ˆ†G;öܶ¢Sx$AL1aǺ*<½ ªlË_×'ý ù|— v2V‰FÓü FÓ4»çiSè;Qgn VÏqZß4ï«©qâVVV&=ö¶4Gú¶õ°Ä Ã×ôž .ÑâOÌ íŒ¯ö`±=b4ZÇA:öB¨ƒç¸—SE/÷5³KÏF/íµ Ã€(Š(‹Þƒ™‡7³Wîß]ô”ÿýe³L»§°HbNà!Á]uA˜«ºÄp˜ï` €ÊnÖ-“ƒÊe3OkÊf{Èå3MÚ¥'f’D¢Õ©Hù«>²€b±ˆd2é?üûRUétŽã ‘H@ضL&AÇ‘J¥¼×d2Ïã†išØ·oŸ÷»,Ë( Ïó¼Õ ²,#Nc{{¦ibaaÁ»ã8^^툢(ž›Ïç½ð`A&–»:Ù"ŠÀÏýÜgØß‰ò÷ˆ10nçKGÏë7A˜ˆÁZ.—¡i*• "›Íz“¦R©@Ó4o2ɲ&ÔQ¬ëæÉ¦ ªÙ¬f`Û´ƒCŒ„QË7§¯ªïäa%†È¸dh•ñž‹Œ{^éïô=ÛÇôúšqÑnlã`œ²D€G¹‰„â7Ø&ˆ0)E2V‰Ý³«ÖAYYYÁââ",ËÂÉ“'±¸¸ØÐimm ÑhÔ;_.—‘Ëåú£`Õl¶±èŒ(RH01Æ%ß©”ߢ'HÞ‰!1.çU%uÏ“ô ™o‡áŒM? à8¬ë˜eY{ª1&!ãõLƒÎŽ–µ'ë½Ñ³Áº²²â=¶¶¶ZŽñG7¶¶¶P«Õ°ºº ˆD"X^^F¥RA¹\F¥RÁÖÖ–——½óKKK»Îa±mÑlݱTUò8Cgœò-I}ô` Óü bŒSÆ'ÜÃJJý÷rÚ·~ÂiénD¹«Äˆ˜„Œ;Žï/êh°u3 ÚÒ5$øÀžàÙmK›X,†õõuD"ïØÎÎ61øÏÁ˜úX,æ….ôE°Ó6nøò—õuR؉‘3NùÎd]ïq7r-!ÆÃ8eÜ4à ֽÐâ„?cÕOÈ2ðµ¯}ŽCÄh™„Œ ‚ï/êXpɲ¨:0Ñ–®k4õvb†A$i0v+• r¹–––F=ïmµZ­a’õÂË?ÿyTD„vä‰10nùnÛc˜ FĸeP¨žwÞ°¾c‚艱È7üÈ™® ¨ãPå=b¨ŒKÆ“ÉÆß{nic@½¯'ácÛ6LÓô~×u‰DététÚÛp6 ‰D‰DFÝhYt]G:ö^3ŒK¶9¬ë9 Ëb+AŒqʸaøáÀ] VÚ¨!:Г‡umm-´S,Ãââ"––– iNœ8Ñ5ßÕ4MT*ȲÜ+¿¸¸ˆh4ŠÅÅElnnz×2M34Ä©#ðÕ“'ñÅ—¼'ý-{†qÉ7ß±´{1DuýOžXbŒKÆÃ‚uzîáG^ªƒRUU8Žã­¦iB×u‹EX–…D"Y–aÛ6Òé´W4‘H@E8Žƒl6‹B¡MÓǽ0ãyalú‰÷~LL½È°*c1DÆ-ãÁ:J¶mCi·‘hYÔ†ŒèHWƒ•—À~ÛÛÞÖñyo{ÛÛpøðaÏÕÛÞˆ8,\ïî®®®zísx’÷Ñ£Gûûdià!ùÇø·_üű©ÄÞe\òmÛlmïIywœ=¯¼Ãc\2.I@¡Ðxíž#Óllc6j:ér¼@w,U%@ ƒÕZC ÖŸŸ®?Ÿçó&:<¿LÓ„ªª²,{ß­®ëžá ²,Ã0 Ȳ Q½çq#vž›~R‡×˜±,‹)òºN‘ÄH™„Œwõ°îáô ¢wº¬årÑh´ÅåaÀ~~gg§£ÁºººÚÕ ‹ÅpóÍ7{kW-tLÀ¬¹È×!f‡±É7Ë2{“oª¼G ‘qÊxžóW'±SßKר¦RPÑÝÈ”B®Ýc‡ªLsÅ*´Fd7¼‚k‰ã8^è07h÷ã–mÛf{‰©”ÉZ5¥Räe"FʤÖ¢8Þ Fb&éj°F"œ>}ºåxXñ€aÒ\z»ovÓÝ+7Zb¶T¾y¸dW«i6nqĘTƳY¦Ìwç{*0fš$ï= LÓ„,ËpÇó®pÏ)7xç5WuÖOêXð+¿r[LJ¼LÄÔ0 ÖQêºáH²Ot¡kÑ¥X,†Z­Ö±7ïün{4 ‘í&“‡•˜GªÕ*r[–_Ož f Ól è9$Ø4)¬À¾}ûa9­¦i"•J!™Lz÷JUUaYR©R©”gÔÃ'Ÿ¾ùÍ¿er¬NCs€$ù­ÉlÛ¦u„ˆ®ÖX,†X,†\.‡X,jÖj5är9,..ެ w_Øžz éø &AÄá8®}úÓýûb±QÙqVbµP %ˆ˜I‚iM=[X…=¾[Ö҆ÕFÇqP(X;IòŠ.@©Tò6Äø&,Ë '/ÊDìQ (ò©[Ç bŽàKq_5"„žª;v +++8rä–––ŒÒS§NassÓ{ÞT`x^ßúʨB01·8Žƒh©Äôæ¼½xœ§1£½«ÃÉx^&׌h¿g’É$dYý~I¹-–ŻؘÈH“Û=¾ÑBÌé4SC§Ã†£ãP8<Ñ=¬±X 7Þx#666ËåZÎ/--ayyy ^dCçÁ±oÿþI‚ FÆ_ý*öïßÞ®¦T¢BKÄÌÒ\'¬c8™®3eGí³LîGEÏà €ÂõÆŒmwÝõ$ûEQ(Œ˜;L“…†ÙÞ`Õu¶ØÓúMt¡'ƒ`U€;†ÕÕU¯r€¶aÂEþïsn·܋'=‚²m튟‘±JÌ0ÍuÂLÓl_pɲHÙÙ%¢(öjM Iž|ÒÂ3žAÄ|ÂóW½¶MaŒ»1³ôl°r†Uo¤ÀßùGœõ³?;é‘Äh°m,ž>M»òÄ\bYþž ïõÙ¶€õð#fQtýohÀ˜[xІiÖÛ6…Aë7Ñ#]«Ï,¶ ÷…/œô(b$d:¶ \tÑSxËOÂNÌ%<Ò·k„ ­ßḐÁ*Šxàì³ÉÃJÌ-¦iÒ† 1÷ðüU )ëY–=/«a¡Jc*•‚aÈðê(ÄX°màg}½à“ AŒ^8Ï4Íö+å¯}ÐwÑ¥™@ñÄ;&=‚!´!CÌ;í -SÕ»¯)]´>|ËbC–$îlÛ~ ÙfD‘=Ç/@ŧ{Ø{ñçQÙlŠ¢À4M¨ªÚàuåÇTUE*•B¡P˜ô׸g0MàÙßùGcÒà ˆ‘ ŠÀ+_Y@ÅO‰á1—VI’È`%æÊ7#æŽÅ:ˆ¶È²ì}o’$Áu]ï\ÐÛÑüÝjšæ…__C ŸÿðØbóŠ+&= ‚ ’XÖç(Å€*Sïa-—˨T*}½F2X‰™`7ò PŽ61;ìVÆ-Ë Wxl¨·b!ˆI³ùÞúÑpÖ+_9é¡DWv»~‡n8:H°ÿ ¢O¦ÖÃZ©T iÊå2¶œÍf'=,‚ $ßļ3ˆŒ[–åo:òʶ¬G3V© 1a‘ïOF"ÐhÓ‘˜bÕQZê8L²Ä} &vÁÔzX×ÖÖFaYNž<‰r¹Œ\.7éaÄP ù&æAdü±›oÆÇn»íƧÓì‘Hº Ô˜8ƒÈ·(Š%CL5ƒÈwKýÃâqf¬¶«úN]˜JƒµR©`kk ËËË€H$‚¥¥¥öÕÆb† ù&æAeü?ðœûàƒ@±Øø(üþ.1!•ï ESÌ òÍ‹¸Á¶™WU×ÙúMÆ*1Si°îììb±˜w,‹í*Ž~ØÜÜôÂ.f ò öÏ^“o`vå¤\.csssÒØ9öšŒÓ¾·Økò=«2Bë÷îT¾EA€˜Í²¨EaÆêו¡õ{6˜ÊÖN“¢V«!‰´øá‡qçwâĉ¸ôÒK'ýúâÿüŸÿƒÓ§O£V«Mz(}sûí·ãСC“F_<ôÐCøÊW¾‚‡~x"ï¿ùæã>qâÎ?ÿ|œþùûn™E9€»ï¾wß}7¢Ñ複Ò÷¸ï¿ÿþ‰½?­á³Ã,ÎÍ{ï½ßüæ7ñÄOLäýw#ß´~ŸY_¿+•ÊDÆ>èú}Y4Šýû÷ã{õWìäÖÖØ?C?Ðú=^¸Þïú=•k'¡9}útèdyÚÓž†jµŠ“'OΤÐU*•™÷þýûqêÔ©I£/î¿ÿ~|÷»ßųŸý쉼ÿnäÎ>ûlœ‚˜%H¾‰y‡dœ˜gH¾‰y†ä›˜6¦Ö`Xâ7/5½¸¸8éáÄP!ù&æ’qbž!ù&æ’obš˜jƒ• ‚ ‚ ‚Ø»Leë¬R.—;6.—Ëû[u:ßíµÃü Ã÷8ÇNŒ–QÊw/ç‡õ†=6’ïùaŸWùר‰ÑBë7É÷¼Cë÷äÆ>\b`îºë.÷šk®q<è}ºãù‡z¨ãk¥R©`ccÃkóçÙí¸{9OÌ£ïQËI'ùt죞›ÄøÙŒw“ƒY•oZÃç Z¿Ç;vbüÐú=¾±O 2X‡@¹\ÆÊÊ Êå2n¼ñƆݒ ;¾™h4Úñ|§FÍÑhtàqonn"‰À4Mär9”Ëeììì —Ëá¹Ï}î®ÇÝËybv•|ZN:Éw¥R™ê¹IŒ—ÝÊx79˜Uù¦5|~ õ{üc'Æ ­ßãû¤ ƒuhšæÅÑ7 Kºç+•Š'0Îw{í :t¨í„½à‚ v=î^γè仗óƒÐI¾É÷|±[ŸWùõ؉ñAë7É÷¼Cë÷xÇ>)È`Ó4Q©T Ë2¶¶¶ÛÉX\\ÄææfÃk‰D×óÝ^;(‹‹‹X]]õ±X Àêê*$IÚõ¸{9OÌ£”ï^ÎB'ùŽF£S=7‰ñ1ˆŒÏ«|zìÄx õ›ä{Þ¡õ{ïÈ÷>×uÝIb–Éår¡ý“À²,~¸B4E­VC$i¨jÖé|·×û³”Ëe¬¯¯<î^ÎÓϨ廗óÃü,Aùtl$ßóÁ 2>¯ò=α£Öïé;1:hýžüØÇ¬c¢V«¡\.›ït¾Ûk§uÜ“;1>fYNfunãe9˜Uùžô؉ñ0Ë22Ëc'Æ­ß³/ßd°AAAS å°AAAS ¬AAAÄTB+AAA1•ÁJAAAL%d°AAAS ¬AAAÄTB+AAA1•ÁJAAAL%d°AAAS ¬AAAÄTB+AAA1•ÁJAAAL%d°AAAS ¬AAAÄTB+AAA1•ÁJAAAL%d°NŽãÀ4ÍIƒ FÉ8±—…üÓœ"&ɱW YŸAôJ'wÇ“9A ª*A€®ëžÌs Àã8PU•䛘F%ÿ™LÙlûöík¹f6›m¸Ä0h'Ëü¸aY–dT’$˜¦Ik613 "ë²,·]Û’íÝ@Ö Ç‘N§0Ã3™L6œO§ÓÈf³˜²’L&½IÙlÖ{ã8ˆÇãÐu½áœã8pÉd‰D–eyçù{ïæùÑ dÜq,,,x.†axa7Žã´ÈÛ òJòML‚QÊ*•‚axà®™H$<%ˆ †E7}¥™ ŒÚ¶Mk613 *ëÖvþ|’í>q‰‰‘Ïç]AÜíím(.ÿ³loo»΋¢èʲÜp¾T*µ\Óu]€›Ïç½s’$¹ªªz¿kšæ]k7Ï'ˆnt“ñb±è—¡jµêʲìnoo·È©Tr¸ÕjÕu]’obúµükšÖpjµÚ"×1 ºÉ²ëº®,Ën±Xô~Ê(ÿÖlbÚ†¬wZÛùóI¶ûƒ<¬ĶmȲ Q½cÁP_Ã0ZÎ+Šâýlš&DQôª—ç»4Á× ‚à…#´£ßçD'ºÉ8?žJ¥`š&A@±X„(ŠE’$y†a4„Ô_|ÓǨå?. ÀÛ¡Þ'bt“åv4Ë(­ÙÄ´3 Yï´¶7? Ùî2X'ÏKm‡ã8]_Ïs•‚æALŠn2.Š"ŠÅ" ™Lbß¾}H¥RÞyEQv’mb–·üK’MÓ®Aà›,ļ0 Yï¶¶ýCëEÑó„r‚Fª VI’¼]þ( Ð4r—ˆ© ›Œóâù|Õj¥R †axyØŠ¢À²,d³Y8ŽCž#b¦·üçóy¯På?ä›,ļ0 Yï¶¶ýCëQ¦iz;èÜ[|š¦Mz˜±+H¾‰y‡dœ˜WH¶‰y‡dœ˜&j°nmmacc£åøÚÚ¢Ñ(,ËÂÉ“'Q.—[&AL;$ßļC2NÌ+$ÛļC2NÌ3XkµÒé4dYn8^©T°µµ…ååe@$ÁÒÒŠÅâD¿(‚è’obÞ!'æ’mbÞ!'f‰¬kkkXZZÂŽïììb±˜w,‹Q=±{,kìoIòMÌ;$ãļB²MÌ;$ãĬ±+ƒ5—ËáÈ‘#$ ¹\›››}… lnn¢R©`uuµå\§IQ«Õ&ý}“F×û{¾i‰{8ÎX†HòMÌ;$ãļB²MÌ;$ãÄ,Ò·ÁÊ ÔÅÅED£Q,d`ss+++]__©T°±±cÇŽ…žï4!NŸ>Ýöܽ÷Þ‹[o½µ§1SJ*ØvççØ6w'ŠE@QØë, ›››8~ü8¬x^G%ßpß}÷aee›››C71D, 0Œþ_—Í2yÝ-é4ÛÐqüÕ•WâÕŸûÜH>­áĤÉår8~ü8¾õ­o õº´~ÓÀÊÊ î¾ûî¶Õ{ÖobÒp¼ßõû§úy2ôõõu,..z“I–eD£Q9rår¹!” l ‘H¦iÂ4M”Ëeììì —Ëaii©ãk¹ÆÅ_Œ«¯¾:tLj˜2R)@€L¦ñ¸,3Oh¡HRøk3f ¤Rþ1ÛD‘½FUÙÏœR‰ý/Iì‘LbIQð‚ÿôŸðåÜ F%ßpÑEa}}}èc&†L2ÉäÛq˜<6“NšÆž°çµ›ÛfËb×ö»®û¯Ñ46²Yüº¢ óÓ?=’Gk81iVWWqèÐ!œ:uj¨×¥õ›˜Ö××±²²ÒQÞv ­ßĤYZZB4í{ýîË`å±í‹‹‹-çb±b±X×C‡u<Ïãé+•Š79‚?374›ý0/¨(²ç( SÀ¦Ðsåž?OQ_Ë•ùNH°½ d³¸lyßxë[‡þñH¾÷8Ù¬/»‰;fÛ)¢È¼ýüwn؆·€yÀ7q ö3¿.Gü ÷Žh§›dœ˜WH¶‰y‡dœ˜Uú2X#‘2ÀæÔjµžÂ ^žûÜ•Y\\Äææ¦wÌ4M$¸òG̎Ôk®Œsc5ŸoÿIb!¼Ù,Sê5y¤¶·;¿—(6zV;¡iøê•WâÑ!ïÎ$ß{ÓdÿÛ63Pù† ÷ä “cn\e3hœòÐöN²6_t½GóÆÍ 'æ’mbÞ!'f•¾ VîE]YYiˆ¯T*8~ü8¢Ñh¨÷µ_VWW±²²‚­­-Ï8>zô褿+"ˆi2¥YÓ|ÏO:Í~æJ´ °ðÞlØ¿Ÿïd¬rxh¤i²×¶ “œQH¾gÛfòhš,B€©A F4y5Ñ3$ãļB²MÌ;$ãÄ´Ñ—Áºµµ…••œqö¿ 0ÛBØL“ M’ØÐv)³}…×§Eß'fÇaá¹A™ÇÙ†Ið›J1!k>΋!5G AĨpÖò,“i¼'¥ÓL9 Þ«R)œóƒLzÄ10á?ÑSåè i^Û £³ÁšNûÆ./æÆ+O½í¥Ï¥—>†ZBn&¿i§RÝV.„í„-“™»H±—Fë„ѼÑIC‡{ºÚàÊVµÊ^cìÁïiüZ‰„o¬L‰ SR$ i¹ÄŠÑÛ“þˆ= ÷b…xÒj€¯f%tö³$)€Hvˆ“¨®³I³_mø£?: ‘H¤¯¡õm°À¶™dðÖ0|7Ã0€èg¡ÜÆŒUÞ}ƒG›(Н4Ó.•‚‡Î‹oÏUÀ÷ìóÜé~UÀW>¡ñþN‡ÛÁc™Lw‡˜òyf†ýáyîO;w=Ac#›ezúövë¹°:gAøô¶,?Iý3¾ñÈë$“ì^‘Éø§œG½W^ùIļ‘ÍúŠP>ï± *E¼G<ß­—e8’Ìtšú¦Šã–#AظÒáhã{´ÙuQUÄ0I§»|ÂG „¡(6¯ñ)ÁSy„£®ûç¸c+/IÀù/÷áÔ©ûúú »2X777aš&¶¶¶°M²,S!¦Q!Š0~ûËp6¿õrÓ¿³—JÈ7 UP(¸ð=ª@c7 ªÊd8¸AÈŸfÒU$(ô<’ ¸+ÃC„ùó‰V;ì33L>ÏþÐÁ?<àç­Î@˜¯mû!óí†kš&²Ù,E¢(ÐNlÛÏA—¤Æn=wÝõªIÄŒÁõp9Ãñµž×„Vo§a0Ù/}48¸R0Y-}Y +†Çwã9¼^gkënœ:EiÄ. ´,°,&÷² (/ýï{»õcY›¨¼Z¡Ð Ôóy£(¾ÁÊä; é0{ÎÂ;t^ñ9Éøµ7" ¾þ½ËJp¿Ÿ??mHãã/üFËâ›N– h 7]¿N´5š ®Ùƒò´~_Ëå°¶¶†h4Šååe,//#bmmÍËoUxTÇTÀ=¨|l;KKHX X„£e`;Š.%oF×7S²Ùðhž:1®Ý=^ IוÃ0°o߇®ûÏ£ê¾{„B¡5, !®}òp}…w×±,àÈ‘;ñïÿý_â—~é'¤öëH:F:†ªª°mñxéæÎï™H°ÿŠx=ŸŸúÔÇ~ð9È2ðÓ?}錄*bÊð•hF2Éä‰ÿÏï Á4q^³ðƒd¹ušr½ž+EÍsÀqZ§±,²ä@²êy}Édë ù(‰¼R½r)H³m þ‰·³µ=Ÿ÷[Ȳ'žº!ÀÎ[ÓdòÏwQlÍRÙÞöƒ„t½†¿A´ƒ—çH¥üMéT žŽÜB]±¶i$.ùW(glzâ 0ÕÿæBoç$½’a&FƒÊ7Æ'M_ÖJ¥‚ d³YÈMæ´,ËXYYñ ØY„çGZV{ão$pK9˜€É·ªëð];înç»Ü½ô3åù¬€¯¬ âíüQ,˜¦ ­‡'@p§(NC’$8ŽÓ”¼zÄìeÔ ß¾|%€ïR4ïBðxó ‹ÞqýضýsUþò/?JågðŽw°u®PÈã _ø!¢ÑWãŒ3d¨êME¡éš&Òé4dYF±X„ P™L©T Édù|–%àŒ3j8uêO`Û¾ùÍ+pæ™g®ç…4σà43 ÛÛE8N¯|åãd°îQ ÿ¥ðu•ßJ²ÙÆ*ê\ž:¥V„­½ÁÄ}÷¥pàÀ24í¨¶ámÛF:F©T‚ã8H$8xðि^"@[z—F£×2nÜ÷ Ûtm7÷û^ÅVjsˆpó{F›–Ǽ¯r§EžÇ'“l’:^øœçàk¯{Ýp¾Lb¦á!êÙß~™Ê[`Ÿ©Yó£g‘HC· áÁs Õûë¥R€ð3…LòdPUýö|€¯7ñ=Öf96 2B‰öðÍC.ƒ¼Û†(®%I¾¼;a´KÉ ¢¾òëÐß[üÈï@øßB&¯¢q©_[¹ã«¹µ}pÜüÿ~ì Ü.pêN A Š"î¿ÿ~¼ìe/ëëZ»Êa­Õj-ÕjµZÛÞ¬³ÏF Ð“ ^é¨yµão¬iLŠS©éàÉÌÜËÊ_Þ¯AÝÍ»ªë:R©¶··[ À^H¥RPš¦!•J!•Ju4ZÁ`CDrýïE±nÈ|ö³ïÀ…Vðò—çðÊWþdY† žáiYìúŒ/ žñ`Y’ÉdÃg$ ‚ À4Mˆ¢ˆ‹/¾x(ÚY‚ËÑÈ.Î{Ì5ÿÍy–`B2?>‚†‚axÑ‹~?|IèÞP·Ð,]סišÒkYVêªEögßÁyç}çW…¦ieÙk‰ÌoFÁMÓ :l{šöG^^k&“eY0  eš¦µÌÏT*…L&A  …^óš×Œåû%zƒ+*¶FzùŸ¼W°¹×2l9曬îÍJ{˜!ÞDÁ‹~´<©¹¯r;xk=©öî­-<Úg?b¾°mßX̨õâ”…DÇAṈ̃稆¯ÿüùŸßˆµµ@•¤º·óy@ZñòY¿ž§¹~FðgžW<–ªÇWvÛ´àm¨›¦ Û¶=Åþᇞô×K ,ãivÉ$Sëy /EñU%ÙÉá†bKí£°Pâeç ó{gòmÇc†§Cs¸Œ·[‚óy–w=HÄ)˜äŽ"³>?ó™Ïà‰'žèïbnŸ\sÍ5îu×]çîììxÇvvvÜ믿޽òÊ+û½ÜиýöÛÝãÇïúõ’ÔzLU]·XÂàTÕu ×ÝÞfoT(ôõrMsÝ|~ðaT«lá窮(Šn&“qUUíûÚš¦µ¼NÓ4W–eW–eWE7øüý …‚+Š¢[*•Ü|>ßö½K¥’«i?B+‡€IDATš«iš›ÉdÜb±èn×?L©Tò®ü9ŒíímWÅåe\wÝu½>ø÷×4×móõO©äºŠÂ~–e×ÍdØ›µ£PÒÄê4$&/¥’ëŠ"›vW\ñC÷üóop#‘oµO¥RÉ•eÙ•$ÉÁUøçr}™­vúluòyö‘$v¬XdKÂn¾ÿ|>ïJ’Tÿl%7“Éx¿73¨¼Œ›Yœ“ý Šìo)o>noûS¦Zõå§P`¿óÿ§•b±UÞƒs ZeKCè—Òî¦Ô…Y“—Y›ã"l­äÈr£nÖ|Ûåº:U­ö¤[q=E’$·Øç=¨P(x:G’Zõªb±èé=ù.Š[p=Ïçó zˬÉˬÍÇ^)•˜|JRû{öö6»§‹"“Iþ>Ÿ¯ß¥Rê_XÅ¿¸¦õ}3ØÞÞvAhѯ‹EׄîêÚö¶¯guúR%&“É4èPAv#/}¬wÝu—{Í5׸lx\sÍ5î]wÝÕï冯(&K©Ä„p`D±ñ÷>…MQ†h\´ƒ®ëº’$¹¿÷q×mÒ#ªÕª«(JË"ÌÝNŠ|µZu%Iò^«(Š›Éd\×mœÛ»T^ø5z™Dš¦¹oyË[fnqæ Œrõ?Á`loû+pµÊ¶ÏM™ \Îz1 Û!IR}¦è)Gw/¿|Ë}ùË?ª¬pƒ4(?ªªzó"8GúùJøï¡ {NJ[Ø8ùfP&“i;gHᙂ{:®ëO“^ÿæÍ›–L¯p¸bÔë€ê/ Š^³?3ߤi˜?üà.™5y™µùØ™ŒëþÜÏ}Á½ãŽo÷ýÚf[³ZmR‘¸µ°½íŠÂDÇ›S|£´|³ºZ­zúB7}#“á›»ìù’$yz Z³MÊá°û ‡_OUÕ¶÷¹Y“—ižÕ*[nø£W}š‹^>ß(“ªÚhÀf2Ãq*yƒÕ4÷ÑóÏwÿîòËÙ…4dYv …‚+Ërß5®Ë6aše™Ëp;ù-‹킱¬®Ë<ª…BÁ=~ü¸{üøqwcc£Áã: ¦v²4k*» ÙÞþ™àq4Ms>ïa×-º®[W²¹Àw]·7c•ÃVUU]¹I{Ïçó=íØÞÞîÉà­V«n4m¸ñ̃ÜÀ¶·[uQ®4˲¿ïr¿`¨(Šâ*вkyÐ4Í}Ó›þÔ½ãŽo{ êöö¶'§|<ì}›7c¸Ì …žå<Œ|¾UŸ *f£Ø”"…gzSlûQp¶·}…~{{ˆ÷„LÆ·BܸÅb±í`ËgªV[„XŒ>éºÅ¢›yïãîW|Þ‹âq]wàH‹™ZÃgm>vƒ®ëºŸþôiP<8ü|>þgVU_~¸L‹MŽÒàQdòU(¸¥|´1§þÜ £y}çÑ]Ü[f\rã†+ú|³ë@Ü3ÊiŽ+•J®$I zI·(0άÉË4¯ß|/Ž?‚Ëv:ªÉaÕ/Õª»³ºê¾â’K\UUwñ¤P(x^N.íž§ªj‹ÉdÚÊ+×ÿîÕMÆÇb°ÞtÓMîÁƒ&Óu×]çê^yå•¡oò±}Ì=xð`_žÖÛo¿½ãóïºë®ž¯×χo 9áë&‚ùE]=!E·%”–½°ç¯¥nL°Ÿ Þ5ßõ( ^.›¢(®,ËÞΟ,Ë® Þ^Ä‘ñB~f¸Q|ø²ÃîÃç=̶àºnàf’ÉdØñªëºý̧¢Ë^3AƱ¸S¾]w°X¿¼b‘齆vÊî•fe6rÂBMÓ<™ÿô§¿àæóy÷íoŸ›Je]MÓ\AêóÁ¿.ßXiü|Eo®ˆ¢Ø5y{{»ï ¢à@<7¦PÍÍq ϤÖði€+Ýüo8ê žím¦ÌöéV«U÷³ïx‡ûðyç¹k/x+B[¹¾é†Ü»¢Ñð02nd”Jue'üýø8眻ܭõu×uÝÐZ|£‰ß»:mVñuaccc¤ò2Më÷(ááŒ<Ì–ëG–;îøä(ŠâÕ¡è'2&ŸÏû›A ˜Ó,èAe,@sÊ—!®<óñuƒËV¡Pp‹Å¢g`v[ûùý©Ðæ†Éõ-AzÞ„¥õ{÷ ýmÀðìþgÉZÎ\õ® x{=êé'|Ó#˜†äº¾lóÜQ®· /zŒË*_?¹-Ð\;†_¯9µyÎæóyÏíí£•<]J–åž^·yé«Jp¹\F­VÃêêj˹ååelnnöÔÖfss¹\µZ k‰“Éd¼ÊÕJš¦¡\.`mt²CìZkY~“çxCõ¦*ºÁꇲ\ï¹%°[Ÿ‹SŸ}&ð‘g4wêÏï±ø®mÛ0 ýè%xÚÓ¾Ã0 IŠÅ¢W!TQÜ|äfÜ&܆¿xÀ«Âõýû¾€We¥½ Àiš^‹ þ½nooûŸ–{m6›ÅÞü‡Ø¯ï(õGýóxía{xQ< €T?&ÐêÏK׿@¡þŽV}[B»*Ü3Á¤å; Ëê¯u… Û²(ìªë€ñ2¬‡^áÂg@yÓÓ*Çñ>ìšæWÚåÕŸóœïàá‡ïi¸¾ã80MÓ«ÚÌ«=óJ·«ì¬( ‰Ç¢($ –eá=ïy:î¿ÿðŸþÓ I24í Ö×OyÏ ~ÖB¡àU^ô>Ÿ,{ïY*•*ç…±›ªÙ¼o2ïéÚ¼Þ𠪩Ôèú"Ši”ñqPïÇîɾ,û_Þ›÷YäÓ¶í\zĶmض]ÿ™Ìô$ŽºîÝèLÛ†®ë°, ‰àž×½ùͨe³Èf³È„”þðßÿ=¾ø3?ƒ¿ÿ}¼ë}ïc-™x‰K(ñ–·|gUÁ«_}ÀÑ–k<ïyã]ïú'üìÏþ‡®»«¤ÇašfÃ:Ïç½¶O–e!•JA’¤†5!NÃ0  üèG?©T Þ ²ÍhšßŽ…·r‰Çýï²ì÷ .‘Áöh¼Ê­$IEñxÜÓ=²uùRUµAaàÔ'? ý»ßÅöö6Œdår±zëD».¯ügÞ¢.¸N[²ª¶m{ÕÛv1 –e¡P(ô¼~K’„B¡£^¦Õ²¬ùk‡ ÛŽ ‚€L&:Ï&Á¼Ëx¿ë­,³5œ7;Ømë1^—Ï ØÿÈ#¸rk —îìàžw½ UMóÚ,Ú_ÿº×îÎq†Û¶äD‹Åyç×çs„wÈEÑ›'R…O_ïoƒÚ­]BLç’F/ßýX··ß~»{ðàÁ¶ç¯¼òJ÷öÛoïx î¥åáÃ>ú¨{íµ×ºúЇ¼ç\wÝuîõ×_ï¿æškºZâýXëšæºù׆p½œÍ–ãõ—jµž?¤º­þé|Þu#íºç~®Ñ5UtÝí”Ûàt]×ý翺ßýü½Û +á;#E¡è¾ì°›ÉdÜ›oÞa»><Ÿ´yãB³æ¶z<«®ëJ®ëŠkäëjýxÑe^Ô^¼=ü» îD©õG¾þ^ÕúC­?/_ëºn©þœÀwëç¡ÅúÏÅúçÑê!xhGµ8*ùæ¯Û ÝàŠ¢ëŠgßïmG6W!ŽÅvÜóÎû¨‰|Ë}ÞóvÜ+®ø¼ûö·¿Ï ÑýØÇ>ÓÓ.hxÑŠÆß¹§‹WTxú:÷ÀµcT9ê£Ú¡Ÿ†5|Rð†Ó7{¢v¯jêºLŽše¿Z­¶ÎßBÁì#wÜኢضÐXXR&“ñwÝóy×Ú¿ß}ôÅ/ö ]æÅºä’uï¸ã‘–°3îy½ä’W¸ï}ïGZ®_,=ÏZ¡Ãäà!jÁ¼A¾{? y™Æõ{Øðfí¼HÍÇóùÆ\SêëŸoôªr]†Gimoo7„ͪªê^ð »ñ¼ç¹?ºür/7ëGzž!bÈs¨yív^¼§³­ßýV+bÔT«U/â‘{GƒÝ,¬lÖ½ëïh˜™¦0à½ÈXrX¯¹æ÷Cúûè£zÇ}ôQ÷Cú{å•W6o7Èf£÷øñãÞäÜÙÙq<ØPqøcû˜{Í5× íëªëßÔæd“ñW­V]®û¾ã+\f8©®B¬i®{ðz×=ú¤ë^ôÆUýhôI÷²g>àÞõê»Üíím÷ã¿ßÅnsŸñS÷gÎxÊ}ÞóvÜ_ù•/¸ÿø?³Äþ·»n~©)œPuYXqX´â6¨Ü8)ÖæÆjÞõÃm×7*]—†býó÷\rÛm5U×u7<,º™jýó´3> õϦÖ?_Ñm5jwɨ×QÉ·ëîþÖÉ`â (}Ò4Íý§?í>¶,¼ÃÅbžÂ !i.ÆÅÓ5‚ŠO¡ë‡N¡:__õBÖÛ)8ÁÐöR©äÏÏúdá R;šó»ÃÚ7‹E÷ºC‡~g$»ŸærŸór›SMÚDqöõ„UÃ…¼Lãú=- #i–Íjµê ‚Ð"sA£Ó“­¦*K¤ÈûÐúÝ?Š(íMÓ\ !´ÁPZª«i[ŸúêY³·yH0d³Yhš†ÍÍMÄb1,T8‰`}}Ý )hÇââbƒkvvvð¬g=Ëû€wmþs¥RšWÙ¶¹Øî¤ÿ£ã8øµ×ü>÷ŒÏáô DÞ PÀ-|ï¿}øðœwÝ€g=ëY8ûÏ>ŽKž}P/‚ƒt:3~ô3xÏ_ü.ü­^ý†£øö·Sxû›ÎÆZôù€ ØR†Å…ÖCì Ý— èÅ×ÁBxE°0Ü8X¸.ÿõóX8o@ÐË/(~—ÀBt³h snGØóò÷ï†PW;‚!ȽÀC“'^9 òÝð•8,ü+,R£¹¹y©TB6›ÅÃý(¾ó¢5„ç†t: Y–!Ë2¾tÍ5øµ÷¾Û/|¡®hš&âñ8dY†eY(‹^(• ´Ž¡TB_Xk¾],†‡ìäó,|­‡^íc£[³mQôC¨g…i“ñQÀÃÃl›ÍêÞoótAè/¿N)‚—„7eÏd28zÙeø›«¯ÆegŸ³n¾E˜¦ ˲¼9†¦iH¥RPUŽã •JAQ”†0HY–a‰„Æ_(`Y,BØu_‡ÛnÛÀÂÂEi³ÏfYˆÞnÃÞAðÓOF̼Ëö áé¢4GÃ9‚  Z­úOªç£‚àÝSžÊw2y1œBa°]I¢gº¬•JµZ­a·€çi„£G¢R©`cc'NœÀêꪗÆéÓ§ÛN–{ï½·Þz+Êå2Ö××Û^öñ<ø‚¸œ9õGýÆšH$ ª*–Ô%@ 1üÙâ¨Ê2½àïpÕK¯‚ ÿÜŸ;üY˜:ÿ ý sO_&åëïeÕ6áTÙúÏvý<À<‹Fýx° nX*õׇÙ3¨,ô÷ «`Åœd´zl¹±ø^677qÓM7áÌ3Ïéð†)ßpß}÷aee²,cii©ã{sÏj˜¡”Ífá8Sd ƒ-¼üEºÎþY€{ñttU`B$¶î‡•s’eæYí×Ã5i&åí]YYÁÝwß=ò÷™Ä>lx¡$€é×c×?²YÏõeÖ‹W‚€g…ÿ÷G?‚`Û€$y^NEQ¼¢Dž1Z´(€›á­QUµmñ š¦!‘H ŸÏ÷UpC’|oWècße.—Ãí·ßŽýû÷ÿâu&¹~‚l¶»BoÛ6ÒétC% ñoË哲’$5†"px²ímf)'“l!Ÿ×Ý»!Â×ïr¹Ü¢{“yX¿&f|C;ü<+bÊ7^lÛ†eYPųcú²gL“)#ý†‰|¼ïõ»[ÌðÎÎŽ{ýõ×»×^{­{üøñ†¸öaQ,½˜ú°øúnÅžú‰‡.•\7Äõ þ4SpÝO¾õ“ež«U–¨óæX~E½5Øö¶ëV¯p]íí®»}‡ëç¿ò"Iný=Âòƒ¹m’Û˜[Êÿ—šŽáð"Oa4Òªÿ]Æ™o1 ùvÝþrZÂ:¸nkniCq%Þ›qÌI ¼8Q²<ºÏygœ9sã\Ç ÏËë7—z(ðÞQšæºÛÛ^ñ³`‘¡û?þq¯jS©TrEq¿}Çî+.¹dè¹~³–;8.y™Äú=l¼b‘mÏwnsוz?I^ô+˜¼œÉLh¢Í&´~÷:v¿ßöö¶WSƒ?x Þ·X,víÚPÝn é÷#ÉaF£^9kÓ4±¹¹éíú,..öíeÍår-;0,‡´!2Çf:P,Â$“Iˆ¢ˆb‘-d<ìþ·¼øÆ7€x’,ã—ŠEœyË-øÈõ×÷ä9í‡a_o™Ù#›õ×QJÎà ¹7U’¤žZ|…b÷Qd“+x-ÊO f]Ƈ-Ÿ¼.†$9P”,Òi¢(z²Ì帡R/è:{pŤ¾NÏd^Üñ´~ž,Ë2Ž;†o¼‹‹‹ØÚÚ‘#G°¶¶æõêÆ¡C‡°µµåå¿lå“!bqq››› ç‰Äp?9729: ø­Oý.úàE¾€ï)àÉ»€^ï‡ôïë*üß <›h æ¤ëç‚×àkºiŒJýXˆ2O汆ќÓ[¾¾ñuÜóŠ{0l¦E¾ÃtOÃ0ðgžÉd›‡p Ò rˆðþÆAD‘Òž¦‘i‘ñn˜&‹B »5e³²5l]ÄqXÁ½t: Û¶ÇñÈ·¿Í4­D½îuЩlñxŠ¢4䈪ªêç«f2Lù—eÄVWñOïy~ñëw¹W˜Ùî‡tø_ÿë'xâ‰?B<‡a0Å^Ó4‹ET«U‹ÅÞ뤛]g÷‘àk{nLŒ›yqIbË¢aˆÇãXÑH.Ç<ÔW–åþŒUËb7‡b‘mä—JlG“dy*è»è'˜ÃZ.—aš&666pìØ±Ž1÷‹‹‹XZZ‘#G°¸¸ˆœ>}ºa·guu+++ØÚÚò’¼=ÚuL½HE®Ì Vø\ùs8ó¹gâuÿõuþñ_ÿ`×Ý¡y0²Ù°ê× êþ\I “sA¡Þ^Ì%¥}f˜´|LŸÐ´Ö|ÏʉøE¾“šH°'¦£ÊoÜ­(Ì–Îf§«Ú/á3 2Þ <ø‡ë†áoš‹âðuÞ Þ²,˜¦éU˘Çô5¯y Ö^ð¼[€?þcȲÜb¨¶¥>à_°nÑ™Y‘m |¿‘ç.ð*Á~ç;o°Ž'Ÿ¼º¡rû®ß´žè¹¹t)øÄL0K2ÎI&“øÊW®Æ܆³Ï~N[eÅbÑ˵Ça;œÍ‘ÄÔЗÁºµµ…ÅÅņßMÓD$Á¡C‡°ººÚÓuŽ;†ååe¯:Yðš«D|óÍ7{;@ÍçÁᑸg”c÷ô¿ƒö¥ÜH4ÍÆP–`±$N²þ³ç5‹VãV­¿¾y>dBž 4¶²!f‚IÊ7wœ†y&ï¸ã¼ã7~ƒý¢iLј’CEñÂÓi žv&)ãÝà‘îa­T¸“ _ýšW’E¢(z&¹ À;f„òâG¦i¢ (ÃQ°ˆ‘0ͲÍÑu¶©—N³=Yf-Ž ÃÀ[Þò6œ<ùf¼ï}g㪫xœ·öÿ&¶ÍÞ(x31MRië#FÞÔ™cdb¤Ó¢¹wµ§*ÓÓd;÷MùÕ-ÕQƒ¹ªSöÉ»JŒÓô뜆ѿwÕ¶™,½§d¬Î ]û°Æb1”Ëe¯ZX­Vƒiš-a¿[[[ü¦ÃÓFC¸:—]€|ⳟ@"ÕÔcêæ;;›ô° ¢g …p]Ù²,(ŠBðˆ¹¦]„a$Éïk: x/J2V‰"I¾Ù·wð«òÃâ¹w•Ë®ã°G³,Ó½ƒ1¢èË·išýo´7RÈX#ºzXc±±²²‚¥¥%¯/¤Z­†S§Namm ‹‹‹«ŽM’`5ö ×ô¡?„CµCƒ˜dg~ ˆFœ;é¡Ä@ô½ O3+ÒÑz\×õÑ«€ßlž Æ€ã8ý¯ë<¬+++-Çr¹Nœ8Ñpl}}½ç7ç9°±X¬íùH$2Pëó <~{@¿}žbŒC¾ög¨ 1jÆ%ãaèzxŸx]×ûoeÃÛ{tÚÔÉfÙÒÆÏž`’²ÝL*Å”ùL¦ÁjÛ~ny`‰™wàŸþéë=@t¤«ÁzàÀ†‚KœvÞ årš¦¡R©`ù±ÙlÖ»f¥R¦iÞd’eÙlvWïåTñ`Iä]%FÇ8åÛ¶ÃŽÙ¡q§2쉱KÆ)ãa8NxïUžêÑw+›l–Í‘vùºÎÞzºÎ=“–í0¾ùͧpß}$)ÄÓ¤ëL~5ŒU¢'¦MÆ- øÿãûø•_!ù%ÚÓ5$8buuµçG/¬¬¬`qq–eáäÉ“X\\l($°¶¶†h4ê/—ËÈår»û„ç€õYå(=ô1 ëB=2NùVÕÖh™¶¡c¤ÌCb¬kx¶Ý¾ÐØ®Â&3™Î…ÉT•ŒÕ=¤e;Œ_ÿõ…˵e1cµT¢Ê©DÏL£Œ»n‘IDGúÎaÝÚÚB.—ó¼íM?¯¯Õjžq‰D°¼¼ŒJ¥‚r¹ŒJ¥‚­­-Ï«‰D°´´„â.š[Û6 \Vÿ…ë"jJ͈wK‰ùeœòÝŽÐ ©ª?I}2 2.Iáâš»Ý ¢ØTì€Ø‹Lƒl‡ª³Ø¶ß^‰ÂÔ‰™F—e`gg£1$ضÃû{–žsXMÓÄñãǽÎÆÆFK8A'b±Ö××Zãììì`ƒÿ¼V,kyß^ðÚ© l"ðõ^âäiñ'vÉ8å`ë9ï øÕû‰$ˆ·Œ7Ó.Ý4´`G3ŽÃ&¢4VúÅÖ°yÓdÇÈsµg˜´l‡qòd 'O¾…B“Þ’L²ÈŠœ!ú`eü–[*­)L¼";AÔéÉúµµMÓpàÀd³YX–å=²Ù,8€#GŽôämD"X\\ô~¯T*ÈårXZZB4í8)jµZ_βáOh`E—,àáß}¸û<)ûÄ.§|­Ýjº†»Ä€Œ[ƃðM÷°%º¥•S3Ž$íÛÒ4+G¦I÷‚=Æ$e»Ù¬—½ìU-‹É&EÍÿ?{ÿæÈYÞùÂ_8áÆÈÈøŒÆÄÑ`m²o`Ԍ؅¬R"ç@Æpš¨ÃyŽ{7¬´îл{i3'a7й¤Mö$×(鬔=‡vâÝ%­¸ÁNÈÙ  CB¬Ið†Äš]ÜÂØ]Œ8,©÷§ïRI*ýþQ*õ÷s]º¦GU*=’¾Ï]Ï}?÷s?#²ˆÿÉŸ|¾²Ý•ŠÚs5“Q¨oâb(‡ukk š¦a{{»k0ì~~kkkè7n6›(‹¸ë®»H$páÂçù^\»v­ç±/}éKøÈG>ÒVÍ8›²g\'é@í³µþéÀL [zöööpñâE3ü­§­oxôÑG±±±½½=繡ׯ’ÅÆÆ®\¹2Ó÷˜‡ ïDíGé}¬ïVe†¬¬¨ÙÒ^…•ÂávûošŒð/(Åb/^Äg?ûÙ™\^ö{>÷¹'ð?ñ²î L.-b¿¥èÑ,ðÃ~÷âúë¿¢l·a(_­ªÁ †K‰ŒÁGµßS‚kµ~ã7~£ïyëëë8þ<êõúÀÔàz½Ž­­-„B!Üÿý]©½èWZû¥/})^ÿú×w~’´û$ðxäq|ë¾Õÿ[Sl–‰$^¾|y&ן…¾àÖ[oíÚ6Ê-Õ¾éÀå2SOÛÛÛc †e®6ÜE8Ü{œ®ëz[á6d­_?Û¶^â½`aÙÜÜÄÙ³ggbÃçi¿ñ…/| >úr¼õ­·¶ˆÇ©Í%Fì÷$»qôÃ/ûí…®_ÿú_"ÿa5ÃJ–žqÇàgXëõ:"‘È@c,"&e ›Í:yôãÔ©SЖ–Ðh4ÆÚJ² q૵¯âÌ™3#_‡Q˜—¾ö‚Öº®÷N‰ä€L‘yj\­&½°ŽMÏ`®+/wпÓæVP'?´Ý‹|þñ¸É‰&2UIã¿ÿûßÄóžwEÙnÓdæéÉ@‡5 Lu]×Ñh4 ijµZÛPœD"Ñ–6£ë:’ÉäÈïe|€ èóÀßýÝßáŽ;îÔ@¦‘±™§¾M³Ý5M³·ÃÊÁ7™óÔ¸Óì½óLßêÀº>Ül”¦µKL>‘ø¥í^|àß·½í)¿¿²D,žÆ¿ƒ·¾õx¢‹Y¤S‚c±šÍæÀ‹ˆÝ]yÌ ÉÉ÷JW“5…›››ØØØpÊo‡B!Ü}÷Ý#¸Ò&TuàcBß áú7_?ø…¨1™§¾*ØÎÿÍÞƒv†èÉ”˜§ÆÝô‹%ö-¸T©Œ¾‡jgç"'¿´í…z;ï|ç[ýþZȱH¯T€oüdËv{m®MÈ1C9¬±X Ùl¶«¶ ‹·‰ÄÀœûÍÍÍ9î±X >ø Ó±ÜÍF!þ½þVý­ë:ÿÁÇqgû¿ˆ†LÀ<õ݉Ùo•+™~iܲz;¬}ׯîï®V>‘øi¿;1Í ÞúÖK<ÖB¡wñ0Bú°H‡fó—‘J=è÷×BÀPû°^¸p8þ<Ö×בH$œò×µZ ;;;¸víšSelt–Þ]¢U ú õÃ0€7ÎöË$dX&Õ7Ð>¦¸¥!sfw3hySϽ‡Çq<£Qΰ’žL[Û˜&ðgöHJ…+™)³Ö8XVo|ã‹ýþ¨$ å°Êâìb±è¹uM"‘ÀæææÌ*šƒ®ÚßÑ·¨ÿ[–Åý)ÉÒ!cjÓ4Û7ÞvíšÈÐ+`ª{—˪S±¢6ñ‘røÀžÀ¯þªÇe–ÅÙxtøð‡ÿo|#Çåd8†rX–ÓÚh4P¯×íkb±ØÌª‡M‚aéÓ\3PYF$É’Òw†•Ûs€Ó¯Rß‚Kã¼ÀþB|åñÇÇ«_ýuA}’ÀS.þç&vv~E=¡ëê_N,‘ ¬ÜI$¦iØÜÜ„¦i޳Úl6ÂK‹€eÑ´þošfï”17œ"!m â™L–™pXí'ï…®ëH¥`0ÏâdÆÌLßǘ¦Éôâ+³ÖxçøÜsýª®3[†LYkÛÍßøÐàÌÙÉ”™—Æww[ÛðuY’I¿¿|uX†çZØF£óçÏãüùó¸ë®»ÍfG¿¸üÕ³ÿªÿ9¬žJfÈ,õ]­ª¢KÔ2ñ™ÚptìY“ PàÌ™*³Ö¶`Y*Þ2p ¾r™Û5‘©2/jn¨gTN‘!ÚaÝØØp‘q?'ah4Ðu½g'ØÚÚB$a¸téêõ:ŠÅâhŸL¿îñÁ—ØQÈ”™‹¾qRÞ 5 !dÌKã™b•J¥w:V2æi¿eºu]i;ÕÏ!-—Y£€L…yjܲZÉ/žAf !è°ž:u ëëëˆÅbÎ#‘Ht='a¨ÕjØÛÛó<Öh4P«Õ°¾¾…BX]]EU¦”†Åž:|jðyL§$Sf.ú>ÆI­1 ØÉܘ—Æ×ÖÚÿï¹~µRáÌ™ó´ß€’ïOüÄû/_ÒuU}Œõ Ș§Æ+•Öߺ®wëœKóÈ|× "‘677§ú¦«««X]]E­Vëš•=<<€6ç7‹žGŸ>ýýŸFü5fX±$Sf.ú>ÆqX½Ê©2#æ¥ñN?´g„ž+™ó´ßº®Æêñé_HŒ³«dŠÌ[ã2‘ë™lœ8"Cá{Ñ¥NúuŠf³9ü…âÀ7žóÁi8È'sdjú†+ZIg•,ÓÔx>ßú»ç?.í sbšÚTºd4Ú£˜›|ž4d.L[ãî TÏ Ë¢ý&C±pk¿qíÚµžÇ¾ô¥/á#ùH+Z”W£¯ÃÊNr"ÙÛÛÃÅ‹aøPJ}\}À£>жTžp8Ü ÓrÌÆÆ®\¹âË{Oˆw.mòÜ•ÎꉤX,ââÅ‹øìg?;×÷¶ýù,¸Ä€ä‰Bìw½^Ÿû{Om ÞÕ«0$mø‰CÆà£Úï)ÁB½^ÇÎÎŽ³vµ—qÔ è·6‰ô<öÒ—¾¯ýë»Ò—ûÞÜá{rbX]]E$ÁåË—'¿ØˆŒ«o¸õÖ[±½½íüßék¦Éè;ic{{{è"xÓfZ6¼\n¯lFw‘kN$›››8{öìÜmø4í7 L÷ü@û “6Ä~[fšLs nš­lßžYî“ȉ`Ü1øP3¬º®ãüùó¨×ë…BÎó›››¸pá‰B¡.]º4ñ9uê€ö´„F£1ðfÐEÒUA•ajú†ŠXjšÆA;Y(¦¥qÃhŸXòœ…ŠÇ¹~•ÌiÚo@cþê¯îëÖµeµW«!dNLSãéÀžH»»~d†rX·¶¶ izè¡6ÑÆb1¬®®b{{gÏžÅ}÷Ý7qƒ"‘‰D[ÚŒ®ëHޱ±p”i4dÁ˜¦¾Û`„’,ÓÒ¸¬ïú v4é’dnLÛ~§Ó=ÖõårÜîƒøÂ45·j…õœae° ÉÀ”àZ­†f³‰{ï½·ïy÷Þ{/îºë.gªw677ý^›Í&B¡î¾ûîá/`ßþö·gÍçK$d&Ö÷1†a —É´Jð² LKã‚çúUB|`ZÚ6M”骜jY*kæàÀïJN(ÓÒx8ÜKX•> tXëõ:"‘H—*iÀ‚?<<ÚaM$žk^c±|ðAgÁy"‘íSÀ‘}Ô†µ\V‘‚ÈŒ˜™¾]¼à{¾øžïñû£’ʬ4e`†Ì‘YÛoÓþÓúbw ¦P`š;™ ³Öx.§JÅ ¬‚MÈ tXC¡ge°ÎâÓ& M4ÿÆ-¶´áV ÄG&Õ70y3BfÉ$ï4Ï«¨2G¦a¿à–[þÏ~vÇ8E×jÕïHN8ÓÐx¥ÒrX¹DLÊÀ5¬±X ÍfµZ­ïyrÜ=ëê'?þx‡•¥´IÀáž,+î­ùz:«++~7“±Ñ4àÙÏþxûÌ“d~1u’,ROÉs6Üx£ßM$bà k,C,C±XD,ótH›Í&ŠÅ"‰„/e¸½øÖ·¾Õ@oY¼)À Ød™‘Bׯ’åÄ0”o ¬—ˬšJ–1Û¦izϰҮ“jÖ .`ccçÏŸÇêêj›Szùòe§šØ… üþ< ø/•ÿ‚z¬Q•ün%!ccš&~â…/l-!dIáþ«dY[Âa³ŒÑuDgê$YtÝùË{vUשu2C9¬±X ÷ß?vvvP,»Ž¯®®b}}}âêÀÓÄ4M屮eÉ$+«’@cY¾÷oÿxÝëün !3Å3%¸³*!B¶lꊛ3øH–]Wiï=3dL“YŽd$†rXUøÂ… ØÜÜt*‡è™&¼t­ag5nÏ9#$`†Í«WÕ%¥kËÁ4YI•Ã"‘ǸÆ(´åd‰0ŒÖ>Ãi¯ñ¶iRód$†vX…iUÇ›5žkü*:«di¸ñk_ã,YjzFç (•ün!caÀ³žõu®Í&K‹Tzï¹~U%#³”+!ËÎ×_ÏY&²ÔôÝ»Á`òyàÉÏ^ý‡+Y2¢QS칤ƒ6œŒÁR®aÕ4­=ªc*톲$Üö–·°$²äôL'#$à†±m¦¶“¥E×uÚo2UN†Ãªë¼1BH€`…`²¬üõŸþ)nýÊW¸¬ƒ,-†a´/é°, \ö»Y$À,§ÃjšÀéÓÊQ5M5»ÊVB žédå2«ª’ÀsÓ§?¯±Ê;YbLÓl H&•ÓJȘ,§Ã»»@.¬­q!„ˆžéd†Áà# óüÎïü>øÁâöÛo÷û#ŒÄW¾òìïïã¾ûîó»)#óè£bccÃïfŒÄW¾ò|õ«_Å 7Ü€ÍÍ͹¿ÿ8úÔ¾f¯{Ýëpã7âæ›ož{»'!ˆ:€§žz O=õ”Sx"(\¹rßüæ7}{Úðàľù裢Ùlâ¶ÛnóåýÇÑ7í÷ü ºýþƒ?ø¼á o˜ûûÓ~‡ öMƒj¿Òau§!t‰D<ŸÇ;Þw¼ã~7Œ£oøoÿí¿ùÝtB†‚6œ,3ãè›ö›Úo²ˆ,dJð©S§´§%4¾ƒyB‚õM–jœ,3Ô7Yf¨o²ˆ,¤Ã‰DH$Ú뺎d2éwÓ™ê›,;Ô8Yf¨o²ÌPßdy†mÛ¶ßð¢^¯ccc‘HÍf¡PÛÛÛ=×÷$¨o²ìPãd™¡¾É2C}“EcaV@-ü–Åò‰DÂïæ2U¨o²ìPãd™¡¾É2C}“Eb¡VB!„B!'—…\ÃJ!„B!„Ða"õz½ï~_õz½ï†ÌýŽzí4?Ã4Û=϶“Ù2K}s|ZŸaÚm£¾—‡I4¾¬úžWÛÉl¡ý¦¾—ÚoÿÚ>l21<òˆ}îÜ9ûÌ™3ö™3gìsçÎÙ<òˆsüððÐ~ÛÛÞæ÷»ßÝöú~ǽvš\¼xѾçž{¦Òîy·ÌŽYê{˜ãÓ¢Sß“¶ú^&Ñø²ê{žm'³ƒöÛÿ¶“ÙBû}2ôÍÖ)°±±D"Ã0péÒ%$ d³YçøÖÖ"‘ˆs¼^¯£X,u|Ðk§E­VÃÎÎNÛs“´{žm'³e–úæø4ðÒ÷¤m£¾—‡I4¾¬úžWÛÉl¡ý¦¾—Úï¢o¿=æ óðÃÛgΜ±¯^½ê ýô=iÛ¨ïåb\/«¾gÝv2?h¿©ïe‡ö{¾m÷ :¬¢ë:4MC­Vk{*’‘H$°··×öšd29ðø ×NJ"‘Àææ¦óˆÅb8uê677ÇÇn÷0ÇI0˜¥¾‡9> ýô‰Dºo’ù1‰Æ—Uß³n;™´ßÔ÷²Cû}rôý Û¶m¿dŠÅ¢çþI`€VºB$A³ÙD(j«jÖïø ×Nû³ÔëulooOÜîaŽ“ÅgÖúæø4?‹[ß“¶ú^&Õø²ê{žm'³ö{1ÚNfí·ÿmŸtXçD³ÙD½^à7ßïø ×.j»ýn;™AÖIPû&™/“è ¨úö»íd>Y#An;™´ßÁ×7VB!„B! ×°B!„BYHè°B!„BYHè°B!„BYHè°B!„BYHè°B!„BYHè°B!„BYHè°B!„BYHè°B!„BYHè°B!„BYHè°B!„BYHè°B!„BYHè°B!„BYHè°B!„BYHè°B!„BYHè°B!„BYHè°B|C×uX–åw3™;ÓÖ¾eYÐuÝïE!„L:¬„ßH&“0 Ãïf2w¦­}Ã0L&ýþXä„R.—aš¦ßÍ d.Pïó‡+!„B›J¥Â<91Pïóç»ünQ¸£5étÑh´ëX4…¦iÐuétÚ9®ëº“ –J¥Ç¹\Ùlår–e!#•J9× ‡ÃÈf³ÎuF=Ÿaé§o( °,ËSc½ô Pãdñ™¥öóù< …BÛó‚eY( ]¯#d¼ô,ÏU*€¦i]ú”çh¯I˜Dï–e9Ú ‡ÃH§Ó‡Ã¨íqà ëÉdP(¦ibeeÅé ¹\Î9V©T°¶¶æt@ vÖÖÖ¨ÊÊÊ ÊårÛ1˲`YÖÖÖÚÒÐ …r¹\×µ†=Ÿaè§o9.kùzièÖ·û85N‘Yk?“ÉxFú-ËB2™tB„LƒAzvã¥OÚk$&Ñ»eY8}ú´p¬T*mK6¨í1°‰¯ìïïÛ샃ç9MÓìl6kt‹F£¶¦i¶mÛÎñýý}çx©T²Ãá°mÛ¶ À.•Jαxæ.ºá®B&ÈÂoB~úõM‚ŒŸÚ‡ÃNÅJn½@¦Á0zFÛ„IõîžYÔŒ+S~'ƒ3¬>FQ*•L&¡iš•‘ò×Çd ´%¹\Îؘ¦90ÏžyÑO߃ ¾Iñ[û©T ©T ™L†}†LÌ =‡Ãaär9'õ‘ 3©ÞÓé4*• NŸ>x<îdǤR)¿?Z`y†mÛ¶ß j0"‘pY§$)`ÑhÔÙ‡UöhÚÝÝu^ë.²$©d„,^úê›jŸ,½ôì¯tî5LHP™Tï2C‡¹”iBè°.0¦iâôéÓØßßG<‡išH&“Èf³Œ`B!„B–¦/0î”˲œt:«„B!„“gX !„B!„,$¬L!„B!d!Yš”àJ¥‚ßú­ß­·ÞêwSFæÑGE( 7ÜàwSFæÊ•+¸ýöÛýnÆÈ\½zÏzÖ³°³³ãwS†æÜ¹sÔ7l4›Í@~ïW®\ÁG?úQ¿›14´áþ侇ñk¿ök~7e(h¿çOÐí÷¯ÿú¯#‹ùÝ”¡ ýö‡ ÷ÍQí÷Ò8¬/}éKñú׿›››~7edŠÅ"Ξ=‹D"áwSFfccÛÛÛ~7cdjµ._¾ìw3FâÖ[o äw _'A´+~7a$hÃý!è}3(Ð~ÏŸ Ûï 8«í·_½oŽÂÒ8¬A&ˆ\bG!ó'¨:I$¼‰‘ùBN–™ j„ö› íw0àVB!„B! VB!„B! VB!„B! VB!„B! VB!„B! VB!„B! VB!„B! VB!„B! VB!„B! VB!„B! VB!„B! VB!„B! VB!„B! VB!„B!ž†zø…¯k½^G£Ñû8!‹ õM–jœ,+Ô6Yv¨q2,¦ ¬­…°²¢ɤzèú|Úð]~|ðz½Žl6ët„D"|>P(h4Èf³¨×ëMÓP(üh*™2–„ó¹¶iѨŠår@<äóêX2©þÇÕy_üâí8{ö±™´ƒú&Ë5N–j›,;Ô8•h88è~Þ0Zcz]25îN¥¼¯cšÊé½ñÆ›ñ’—ŒÖ_fX³Ù,’É$ ÃÀ¥K—ÅbÑ9¾µµ…H$â¯×ëmÇÉâ‘ɧO·ÒÊåVô%—SÍdTTf’”»®•Šº¶¼w¥¢Î‰Çjµå¬­ÿkNÅâ¼üåÎä» ¾É²C“e…Ú&Ë5~ò(Ô ©Œ¿M³ý¸iªq»®«‡e wÝx\9³€_ïï«çu™‰]YQãôLFó›¿2ògðÅam48{ö,  !‹9‘žF£Z­†õõuçøêê*ªÕªM=±”Ëêщ®“RIE_D¨©”rK%%bËRÿÊ9…B»ãjY-G´3½À²Zm ‡Õÿu]½>Uïupd³ý?S<®Ú i³ýî¨o²ìPãdY¡¶É²C‹µ5åô>ÝžŠ›Lv;ž^d2ê¼l¶5F—I%@“kÉÜ}íLÆÛð"îv`«UõïÁú;ï{+%¸X,¢V«¡^¯c}}‘HF›››C½> ¡^¯#‘H‰Dœ¿ ‹9ç»;Œe©ÙÆqEaÊyÜßo]O¦ü÷÷Õ¬æÚšrF“I`w·%PAÎFÕ£ÓIŒÇU'ØßWï·¶¦O‰ìd2ªs¥Óêo¹~8Ü>sºˆPßdÙ¡ÆÉ²Bm“e‡»»ƒÏY[Scg‰+”Ëjܜ˩ñwç¸9ŸoMy¥ûV*j|¿¿¯×RÉïoa ‡µX,boo«««h6›”ø‹Å"êõ:¶··^#ŸÏ#—Ëaoo×®]ÃóŸÿ|ÜÿýзS4›M'Ǿ“/}éKøÈG>2t–ÓTNœ{]¨L¹÷Cf4MSu™íŒFÕëK¥ÖlæÊŠr&óyõ\©¤:ÁéÓÊ¡ìtV‡AÓZ0“Qw¶YR¤-Óboo<ðžõ¬gM÷Ç8fú€G}Ð4 «««3i;YL,KõQ è¸û«ô£µµVÊûÆÆ>üášY{hÉŸ‹E<üðøñƧ~mÚo2²–oœñP'çÏÿ<.]z67ëmŽã´ ý£hªÓ© ‡Õx!î=yÕ/Û0•Rcòp¸åO ƒj¿GrXvvv°½½D"Ѷ ;‰àüùó¨×ûw°f³‰b±ˆ³gÏbuu×®]ÃÎΊÅ".\¸à8Á^\»v­ggyéK_Š×¿þõCÏòrY T-«)‘™I ÝáK¥Ôò”Cêå¼J'p§Ñ®­µRlEȽÄ*‹ª9Æ^躎x<ŽhTy¡2“ëÕF÷¿Óbuu‘H—/_žî…1;}À­·ÞÊÁ‚P.w§âH«VÕñQ3ú [[k­‰F½£Ùl+bº½½óç~&Ÿ6œÌŠ\NEöå~&}¢“ÍÍMœ={vê6œö›ŒK.§l°{VË yÞ0ZK¥ÜT*À'>ñ ˆÇ/"û±©·“öÛt½ý·Îå”ÄÆÉ¿©Tkì ŒÆ ‚ˆ0 Ó¾x1î|$‡UR$ÀM,C,ë+v@yÖÍfÓ‰æpœÝõõõ¾Î®¤,œD C‰OE‡Ãj랥”i©e©sö÷[Nß§>u¿û»„Ï}î‡Ã‡5¤R)ÄãÀøŒ8‚tú…ÂÇ×° ë˜®Ñy8†¦iˆ»¼UÃ0P©TP©Tu©Ü²,ÄãqhšæœÇaš&vwwÛÎÓ4k¤Fèmº®C×u„Ãad]^¸eYÈd2ÇŸ5Œx<ÞÖîiC}Is7 àíooàßøS¼øÅ/F2y#þÉ?ù‡NdSn²fZ¤õÉO~ <òûøÔ§À-·Ü‚;î¸gÎ|Âá=œ>]ÁOüW¼êU/Ç+_yÃñû)>úèOáÛß¾¥’ÕÑT_•5ÞA"ù¿®ëÐzŒ„¢Q ñ¸á8­ßúV}&ß5Nú!KRâñ Ò%rošêaY­,wêšדÀ«¼®P~þçŸ7õ¶SÛÁÄ4[5-ƹ½‹ý•áˆ;X8,îúÑhï­>Ü«i¶þŸÉ´2gªUà—ùÊL¾+j|~HFT*Õ**4Ñhw†¢ØB õºY×\ #9¬YñJ h6›ÎŒk?¼"4îÜùS§NP³¹ò¼ûa´ ÊquϪþæo~ÛÛÿ…°\å½Âá("‘s¸ñÆO"úLSÃÿü??÷sY˜¦ ]×Q(‡Fñ†‘L*KFaR©TÛ Ù0  †á8¤âÄîïï#Ü1%Z©TgRŽW*$“Iäóy˜¦é´%BÓ4”ËeT*”J%X–…B¡ýø fg£N[LÓthÃ0L&±»» Ã0ÉdÏç‡aY Ã@¹\F½^Çë_ÿú©ÿNÔ÷l­Éohšf›Î¥Wù÷÷_€Ïþø®ïº†Pès°í<ã¿‹—½ì…Øßÿq<ïyÿ››¡R©àðGñÊW¾ŸùÌSø½ßû2~û·ÁßýÝüÃøw¨T>øüçßç>÷1˜fýXÇ:Òé4þäO>èY>ýé"c¿ð Ž·½­ˆ?û³‹€d2‰T*…HäfØöo#—ûS4oÄææ?Æ=÷œÅÚš…Xì>$“v>c<G:F*•B¥RA¡P@4u4J¥œ ô w?=ðªA?¨ñåD×[¤ÐkÐ.ËF¼(ZN«;ðbY­Ì÷^Ž­àNg“”xÉbøêWŸÂ´“d¨íà"Î^<ÞÚ^Ãí HF™×¬Q<ÞØÏdÚ5.Y/¢g©áá긳ՆɮéóG,™—¿ü§ðë¿~=ªUÕžg<ãkH§SÎñAK>LÓt2kR©t]o ÌèºÃ0º‚E“Bû=…Bûò‰QT^‰[–Jíkú*•–É”-7Üï#hk”…J¥‚tŸÆÈõ/]jâ§úËxÝë~ÏyÎ7œÀ¸èKÑ^2•­ÿd„TªuŸtÚïé0LàË\®}Œ±(¸56êñr¹ìdTjš†ü±Á¯T*(—˨V«¨T*ÈårÐ4 ÙlÖÉ´\[[C:vú˜dxÉ„™û=%ã±ÓVK¦\:ÆK_úÒ‘õ2²Ã*Ôëõ¶*Á£V2k4må³û¥šµÆï,½¢Ï“âžE’µœ©pÏÔô"—½³‘þÌÚ¸N[ßÀìn`bHÒCLR·ÝçJÊ6ÐJ×–4U™÷rLÇAR½d&H‚„kk­ Ö½ µÌ›J¥5‹Ã@ÚÈ´/Öóz¤Atæy!û?É¢ÀJ¥mû¬È‹bÃÂÚš²á€Ú¥ îYÈr¹åT«­û“dÃËL§{ýÞ éHAw€Ý=SåFjHº˜¤ŒY–…oû½xõ«_|øíß~ ÿæßü |æ3;N J œª(•”L_øÂÿ„Ûnû<âñ¸“9$©ïœ¼ØqFÅÖÈ2‘jµŠB¡€b±ˆ7¿ùÍøµ_ûµ©ÿVA²ß“`--Ž:Æp¯µ+Zé¶²NY´ÉAÈ^‘–å]ˆÑ²€&~øz¼ìeÏt G¶ŠPN6ŠišÈçó=³Ád‰…d¨Jë2ï—Y–ådËÈkR©”Ó?€••G¿îå*“òZMÓÚ‚¹î{¤®ëø¥_ú%üáþáÌ~ûe·ß2;.c|)XèÖg?mJ°d>±—òû÷rDÅÙtëFô´2-E·b[Ãá°c»ÝNèÊÊŠ³äheeÅÉàê|?YjçÎV”÷Ÿd\7Ž^FrXkµ666péÒ¥ÑÄy3ngÉåZ[ø£ÒnAаr|'ÑÈlYJ¥ÒЩµkkíþžX$‡'žØŠ,šq†i xÜÑ0 u“×4 º®#›Íz¦{ÈZgI—s P( “Lâå¯~5>q劳îyxXt½U);Ÿ÷î Uø|Á=Õ •î†oϺ½åqtNêÃU*­R¿RYmw·÷ñ€d†É4[Sxš¶ä~±ONw°EÒpEårË™M&ÕóãÌÎþâ/>?ù“C¼âp5î»j‡‰L&ά“;bnYΜù<÷¹ŠßÿýëÉ$Á°¶¶†nx ^õªŸÀŸÿùãø«¿ú1ì÷( ïvR%»Èkà–Édœ4MÓP¯×£—EìbS%Þ%³ìÃèJ¶Ïë4ó’5âCIÑÈl¶µ]žª|žsŠ,–J%˜f´Í†K`Ã]Œþæo¾—¿üÿ‹ïÿþÇðš×ü'm\Õº®#—ËyNX–…h4Š|>ï™ö(³úîÙüL&ã,ýÐuårP*•œÇp8ìÌXõC‚¹R€Rœ ™­’¾ö—ù—øÄ'>á·D†f‘ì÷±éòœ•Û«»ÀQçZûY;©ê}”Ö$Ht/‰r/Ëý¹5Û¹”°“Î:3ï/iÞ¤ñB–ßMš1ÐÉXz±GàêÕ«öwÞi?ðÀ£¼l.<üðÃöÅ‹GzÍÁmÇã¶}t¤þŸÍfít:í‹Fm;›µíýý}ûHN:fß®V«öÁÁóÜîî®Ífíh4jg³Ù¶c“0¥Ë,6Õªm—JýÏ9:R?ˆü0î/¦TRÏ É8zñ›{î¹g¢×W«U;Ûš¦ÙÕjÕÞßß·£Ñ¨½¿¿oÛ¶mØÙlÖŽÇãmzÏçóv<·«ÕªóÜÁÁN§ít:­tÚ¶¦ÍäsïïÛv*¥$2sŽŽZZJ§ÕãøûêµñxÛù»»¶]=ónõǨìîªïÕëµÑèÀvMª—yÄ>9K:í~6«GG½åT*•ìp8lïzœP­Vít:mï÷Þc¿úÕsî_¥RÉ^]ݲ5M³£Ñ¨Çíh4êyÎë}÷woÙÿè=jk}ÿèèȱ/öcM/‹Ô{)ZfoÐë£ÑáßOÌêÑ‘ºw¼éMuû¦›~ÖÎf³öÑÑ‘]­Víx˜ÏçíT*ÕuŽÜS©”3nœ&‹¤—aX”þ(·îaqëÝã>bOÓé´­iš£Ýjµêøš¦9iëvœöfG7O“qô2r•àÍÍM‹Åž› /BteX …ÖdDxãñ82™ J¥€w½ëßamí·pÓM? ˾û»?ç¤EIn·;*æÎ Ÿ‹Þ83¤ü ~Ù„O°î¨N8¬Â¿Ù¬ ãºëЋ·Ø`Á( Ø=^,ù¾÷ý:>õ©«øèGwS>€x\EËå2’É$ªÕ*r¹LÓÄÇìÇð\WO"âÇVásÉ/“ð¼a¨i¢ýý‰Òâñ ×xzá•ïcš­°²> ³²‚²¸JòâÜE¾¬2pú @ª€‘‘ŽeM€» 3ªLfÃÚÚèûéuž+™?á°÷ X¹\vÖ!It:íl7&[~e³š³ €ãs€jõgGúLš¦á­oÕQ(¼Ý4£T*!™L:3¢d1*·fMöxv§ûÝ3Når+±Ã½¥»>¤ººÓ¾ …VÈŸû¹TÛš·jµê¤F³Tj–z’ì IöÊ Èf³NáÈÇ ¬{åöX*©þP.·2†®ÈzNÉmK†ˆ#;¬îRÅAĽTLìŒÌ®J”¬T*!—˵­Ã‹ÇÕx4™ Oo­œ¬þîs±JeÌN2Ù{ý[?z}8IüwÏ>-‡¥Ÿ•p‡q—ôºßëxý]›ƒÑ^›øI5 ÕViû 3 ¦ ¼å-Oà†þ/üôO{LDW*¨Fu ›†e×]÷C¸îºÇ`šÏFæíGøûîGü·"õ‰Õ>ú.—[{È ¸ñ‚e€ôX.0i.³£²`ÊÝŽdR=/{ˆcênKçÆÆýçVÓÔkúuÐ¥N ^X–å‘A|¥›žÈL©ÉðôÈÚs·C°»»Û6°%r>nL¤ßú)¶ÅÂ]¨¨î Íÿèý$þæo¾ç<øƒ?XÇO|7Ö׿ˆÍÍ’§C:­{‹µ$ÑiœÉn÷P@28:–5ËîàD4]¸Óegd‡P%±u]w¶¶I$Ð4 «««~žž¸·†é¼¿J °›^7ûlVùASqX×ÖÔ¿½fŸ, é¯ý&©w~íTjt'¡PP_’euÞ¥$Ÿ®· »¤Ó­ºònÜ%0ås޲ÏÈ4nvîç¿KÇéÎåpëk^ƒË¯zÕäï~ìÇøÁüïø“?y–÷ 89Ö‹Jå€g«ê¡¯ýMXoû-µeF¸„|Ô•*ÖV-{Ýà%]8—ó¾›Hµ)4”J©ªÕ>:p—ú“ݽevÔ òƒ¤”åéÓÞA‹QFìÑèX3Æ$¸HªÙ0Ñûd2‰T*˲°²²âÌ@Jº˜{€ãv<¥o:vfDe?nwl;йÇô(x­¸ ËaôJa#©jëÞû\¢IÀh»B2 2•á›{NGl°e¹uØBv )Ú%…°d¿P™ e¿v2;FvX‹Å"vvv°ººŠõõuªüõÖÖêõ:.\¸à÷gòD×[þ—û/‚ì›ÖáÚ¤NÓZOä´ærjжzhÆ¿¼ñ—€yŒ\oX§UîfûûÝ~ùÒ:S*Åsïl{<®œT±6ÑèxyÓÄåÀS¿ø‹þ¶gŽ|ë[ÿ;;ÕÞ'†rØ*•.½Dõ2¢ÿûK€T»'š©Tù|«h­T‚´¬öª“ñ|æÿváõ‰ðίt¿: ”J°>õEäþÅ×ÿÄ{~J•ÜG*å]ŠÒ­iw€ÅëÆ"³¿Òç&7®ƒi¶ÛûdR м$P©¿ø‹ˆç<ç?À4ï@8 œ;÷oQ©|©TÁ©¼›N§‘ÍfgµŸãÇ«§ª¯Ó§O#wmA0*ÃìÁê+²o”L>¡^¶eµìn¯x™Ä’;¥!öùßý»:ÖÖÞÓ–æ*f²?n>Ÿï©ÇúÕŽh«Õ±/ñÒ¯~ÕïO1wd¥—›J¥U®Dnß++ÝëT%‰j¤â³¬÷ïœ1å û”‘:'ºŽï¹õV\~ÝëFzùHk£ÑÀÎÎŽ³íx…õõuD"¿¿ÏïÉk‚Ï]Rº'šÖÚü1z–Õ4ÊÏ\Få3·#üÝ!ÇvåÞõMT¶ w=cm 0;Æßæß|ñ¯Ç°{°ß¾àHêÁKx\f‹¼n0òWVZž„a´7Ü0Ôu2™V ñ ¨½¬«ëUŒFf r9ï4ÑàèG~¸|ÙïfÌ”J¸é¦O;Âz"é±î ‡ä0êºg°!o¿aÈrU™Ä”›‹ìÍÆêrw?†ü³u¤Jš+k;Í’š[·©BhÙ÷÷ÿpã†ROüÞP¤º®LšÈ}e¥ç¹I„hÅãd…ÄC}ßùÎe¼÷½?çºêsðš×<©”²Ùl¹\+++°,kèYÒÖ¶¦SØfZô]å3Éþnã"´|áòH}ƒQÖ™/2ÖËf½ãЕJkµ†¤GÊ×išÊY}Ï{~ ù|¾mö(•J±hд‰ÇÕ!™?Ã`-#dšxí7¾á÷§ðx\uýNyºÇò§O÷ÞÚ¼¦i"—ËÁ²,d³Y®C™à¦F‡ØóJ¥µQxµŠ/|ö³#ÁGrXe“a¯7‘H ‹áððp!Ö^E/$²2Rɉ˜¹‹‹–ËêÚù¸ÉäÌtkðùÏCûv »¿÷rD_yüœe!õ×dÿ} ß  G6bæÇ#¡ŽJ¦âXHê£a(g³3Vsåfß¹½DG)& :Õ“‚Ì ½öµ6Æîß1néJÖŸ9“#±‰^?{*¤´çºå¼•HVlšWÝ"BfìÁ-öW׺S÷½Y â½ð…W‘ÉüsX–…?þãݾ¾TΕýFG%VZš»V]ß2 ²TÀ½‰f§§>m¢ÑV÷t¡Tˆ?¡ÈW.&Z–âëzÙÙƒ4•RßÕßþí§ñ3?s/yÉsqï½· Ÿ¿ ÉäµH–~ÞYlÏ‹ÎM9e铦M¾î«TRc.1,’ïª*¶Ÿ+KU$‹ ÇÙØÀkýþçÌÚÚèëéG-˜_(P.—‘Ïç9ƒ:î•î]>:ˆ\®µƒÌhLx¿k k³ÙD(êz®×V7~ãÞiìj iêBÇeÈÜÙ±š ®òÅòÙ0Šªô'´îÑ{¥‚8 à]=Fõâ,˜fïY$ù0Ñh˸®­µÖv~XwUÝNÄQåÌSàqÉ ‡•á_[û=¼ç=#¦%¹5;mï±ÇžÓ2 î݋܃£Q'™Òi•¡óã?žsÒ|‡eܵ§ÓBvk’ï@k{*wŸ—l™BA ¾UãÕóRxlÒÙ¹ÎY(¹¯yq‚sRÝf3ŸW1è·¼å;0ÍþÙ?ûwH&“ØÝÝuf>úÑÝãm7þ/ll¨­WüÖÝĈh½>‡ˆZ¦¢Öt3àÔW%ó[YjŒq×阄Ý]ðÔø«W_á6e°¬îêåã ëP;Çõ–e9³ª'¢X’Üè$h“JõŸ -”þ{'Á]o-Áê7µÝoöbLFrX‰"‘r¹.\¸à̤6 \¼xÑ9gÑ蕹ªëúà‹ì# ´ªJÄÌ0wÂðávãT*yÀAYl2ÊÚ™5wamÐob€ÀXVËaµ,³oI~BNRwK&9& ®ëºŽB¡0•õ¤~àÞÖIJÍ,÷^7Ó+uB"ìÝ_N+r6èÞ"Q62Î"Yj¦õ¾øÅ—áÿã·âüùcmm­K“²µP ‘}®®zkk­`Ê êí‚WU{@§¤(ƒûK—õÔç÷º& ô Í í·A*¬w.·Ðu¹\n9úB?¤X8«r£s©tŸ+“\²×{*Õz¾3ÝMþq·‡i2ò k¡P@6›Å]wÝÕö|$Áöö¶/b¼ü8÷†ÖC·¯íë4˜ÑhëÇ÷M¥ÛžÞ‡$'÷ú;@E—>í‹dû2©×å. &ãG÷öœÍÞ;‘ ’²æOsYû$³=’Š+›rO!r-·(ÓDË‹õ¾Õ«†A<®f`íç3µ=â–ŸÎB3jö´r<[q,ãL]&£DêދЋ u!“ JêUð dÒ3 Ã@¡PÀþþ>LÓÄÚÚÒé´Sõ:ŸÏ/ÿxHœÍÎ>¼ì´LÍdTß&•ò.!?Ì~X3fd‡5‹á¡‡B­VÃåã³gÏž]È™U¡×w\©Tú§q¹K wÒKø‹´“å¡3BY©TPt?}šéHdi9»YÔà%ÙUàH*öÊö1kkkmëšdÕ²,'åwîÙ îz¹W%“Sqôœ ’_0½LIéÕu9è—Qäø%žt- …R©ÔbgÐô*Ò‰TŒêe2êßi:£“°ìô]KßÓ4aš¦“î+{QÇãqìïï#—Ë£¨’ÌpŽ’‚îug7‘^Y5 ÈXkXB¡677µZ F#PÅ–díj_cot@I ètV‡Ò÷°ƒ B@¯”²L&ƒT*…L&ƒêñ>ÃRé^ îÉßÉd†a8³©sìH‘ w¿í|ÿR©ÿÞ&òeovßVªÛ…”KÈ¿`FUw¥œí %0Ëœ¢7%d©% fVËå2t]Çþ ìy")»’FÛo—€J¥5¥&ûowê@œUêãDÐkEB/r¹t]wìsg@R Ü-¦çúÁ3G}ÁÞÞîºë.‹Eç¹ûî»wÝuöööüþ<]”ËÞKdÜBo;Y*^êŽÎõ$t&x¦Ëæ¨Â4² ˆ¯×þ\ápØI+ NŠogvM8vŠqd³YT«Õù:«²¿õ ¤z·ÔKèüVV”ó E12™VQ>×ÛÑ(`=úõžû€OŒ¬‰G¦„‡Æ4Ålßia´]@iMv$ètVM³UDÒkóyïòðîý¤ÈÒ3JüܰÉçó}÷^xŽ ¹¢TRý ós$“jì&ûi®¬œHgq†µÙl¢X,b}}Ý™]€íímììì`kkË)Ì4ìõb±˜çñz½ŽP(4ñÌ­×oªëzw:°ëf~| &›yéè^¿ªëzwtQöy“Ù:¬dBæ©ñAT*íK&%MLÒâóù<’É$’ɤ³¥£Tû*™Œºß 3éWШ³àŒ¦©~ß±.)ÖÞö,d_õk˜Ù'Îf[û€wŽF|ýê"iÛ4W¿úëxßûtÿשv®o“½ý$m·Wÿqo‡1ÌŒþkcYX$÷K( ˆF£H¥RmkU̦‰Ö½–Åè/‹yê[8ÞºÍÁs»& ÓËߣæàrŒï‡Ä^Âa¥}]×Q©Tœ5ªB©TB¥RY¼ý÷:.Ãàuêõ¹<®ÖÓÏFü'_1»Ï%³l…BwðwA‹¦m@éûû¿ÿÿ7ßËn¼±µu‘¤ùí¿Û í2Mc½„a5ÞËÿÊd2Δ¹cýÉZÕÀ!³©B¥2xoéÎ>‚'FN îǵk׆:¯X,¢ÑhàÒ¥K0 ‘H;;;Îñ­­-D"†K—.¡^¯·¥ OJϽWÝzÎ>‘1ñCßn©ö¬~íNq_[ãV26~ÛðN*à¯xÉd™L¦i"›ÍvÍ–F£QÿfPû!³«s$´;¾ íí·Ìöz¥vÊ$ Æ¢iP_Ó_ÿõïÍ7í±PPÁY‹,i¾¿å$»"_X4K}¶N2Çë˜wwwQ*•ppp€ýýýà¥ÿZVkÌÕù<3 †f$‡UÒ}·¶¶Ðl6ç%Z gjûܽ½=\¸p¡Ppï½÷âÔ©STd§V«a}} …°ºº:¸ÚiNŸî~Îs@ï5x§ÈˆÌ[߀¬·/Míã°ÊÀbÒ(ɉÅâÊ•+øÍß|=Òé4ªÕêl·0è¬u0 ²mWÊ쌉FëëÏšë{¶áó ^,¢¶å#޼ ß4H§[3£»» ù›‘ÑXDKÝ-7år¦iv-mšËÌj§céE¿=¤e{™\N~’I ë ö,Ò:ô0ö>¬{{{Žs*yîÛÛÛNè…¤Äb1'Å8‹9iƇ‡‡Îq!‹¡ÑhŒõ½´ÝÓau?Gg•ŒÁ¼õ tï a†wÊ£;š7h?9Bzà‡Æû¡ë:sø£?ú]ïÌ™i"Åez ÜM³µ ¬¦©Ù)I¥ì¬Ö+çÅãƒÓÂfývMÛnzf†Mƒr¹} % [A›Õ"ž,¢ÆÓéö±ºeYþ­S'³Zm#IÑJ©"ûM{Uô•ý²Ãau®{ŸS26cïêëº#üÕÕUhš6ÐYZiÃNǸví¶··vŠf³9Ô{¸ñrXMÓìлëÆ2&óÖ7 Œ½{,áYp ˜|gnBàÆûñÞ÷~¥Ri¶Îªe©(¹¦õÞ2—k­IÚßWg2­ŠhíëµÞa̪EÓ6 |É~ô‹ÓÍm4¢Q¥Ñx¼U˜‹u –šEÔøBì1lš*mWÓZöÛÝçr¹Vÿè·|£3ÐC#;5:¬FÉÀ¸Ñ4m,êŽîlooPùô¸téR[ªq'×®]ëÙY¾ô¥/á#ùêõºs]Ëò¾ŽišÝ3¬á0#ˆ'„½½=<ðÀxÖ³¦Ÿ7+}À£>Š hš†ÕÕUçy·l-Ëò¸[õ}‚ØØØÀ•+WfríyÚðA|èC_Ç_üÅëfŸ*)û‰öÌçó탕pH—•b±ˆ‡~7ÞxãT¯ë‡ý„ÊNÔ§¯q€Ëò Êtδ’¹#ö»^¯\f7*‹d¿…r¹e*-ËB¥R™Ïìj¡ 5²$Ð=êîo•°ÉDÈ|Tû=ÔÖœ?ÅbÑû¸œ={Ú* ß}÷Ýh6›¨Õj};g¿êÃ/}éKñú׿¾­£Œ´Í[g™U²´¬®®âÞ{ïÉ wVú€[o½ÛÛÛmƒÓl_F¡ë=6ÜóðD±½½Ûo¿}&מ§ Äÿñcmí“3ùœ™ŒŠ’Óù\677qï½÷âû¾ïû¦zÝyÛïaÈç¿ÿûL~¿r¯Ë‹ÇÕ,ÒÁAk€{ï‡JæŽØïi;«ÀbÙo@ÉÒ]ƒc®³«©”ZGzp ´ï¨1MåØr½éÔ1ø¨ö{à k$qÊY뺎½½='ê“H$Fžeí …BÎñF£át÷ߣҩùžzB¦À¼õ-«tÞ…9´"' óÖx?ûf[õWŠ+q±ç‰`‘´íf*— …îõ#0ÓléY4—Ë­ñË\gWáÆDá°rVY ÛwFª¬i.\¸€û￉DµZ çÏŸoÛÏi±X¬«„v±XD$qŽ% ìíí9Çu]G2™œÊ6M3˜û7‘@0o}w³ë9° ‡é°’©à· ~õWŸž}åT¯ÊŽdiYm ™ ð¿ñ¹éÌ®ê:Q²p×õVòJ¹\žÍìj.§¶ qOå ƒ8 ÃÈE—÷Öz½]×±³³Ó¶ùp/ …666œ! ¾…ÍÍMlll V«9‹¼ï¾ûî1ÚØ½ÞÙ4Íùn¾MNóÒ7Ð]Üz¦•$ 9fž÷Â4•ÃúÖ·Ny­eµŠÑ\Ëwñ[Û‚ø˜ÑèÞäk¹ì[%j²x,ŠÆËe5~ÿÔ0 ä'Íf‘J¾bà eÇ÷÷9KpFrXkµ‰DÛÿu]G(ÂÙ³gÛrâû‹Åðàƒ:ëaÝ׿ø$†ÑB&‚9Ð'S`Þúv{cÈ<ðÓ†j sÓM{ÞÛ7Mza€ƒûŒßÚ¤išH»~Ú²Ô€½RQvB°8—ÝcÃ0& ¸Ë¾Öù|kW®Ë^†rXëõ:²Ù,Œc躎l6ëäµËìê°B¡PßN0èø0Hô¦s*ܽC1(dªÌC߆Ñ;•Ʋ]$SÅ ¿ó;¼àˆÇ§\I¶ !'?µ-ˆ¹²Òc›²a.P(´¶é ý'.üÖ¸ÔÞ_²R©L')U¯™³t µ†5›Í"‹áþûïwžÛÙÙqž{衇°¹¹‰b±è÷çiC¶znùÑ™WIH@pg¾ôLw·,µ¿!K€a/}éWñ£?zv6ç½€øŒ¢1 }¼¬ÓT3M»»jOg•,šÖ^`*õ¸%ÓR3Ða­Õjh4mkS›Í&êõ:VWWŠb«««NYìE¡s§š™è dΤRí«ç +·´!KD¹ „Ãúô sÐY% ‚i*Û>Ñ®¥í> S›a%KË@‡µ^¯#‘H´•–ŠÀîÈ_¿RÙ~á^Ì-ívfXOŸn¼xÆ3hÔI`q/m²,Ë{pÃt`²Dè:ð¢ýÉôƒîý¡ñ‘hT_t]oRËda©TZ;†*ØÎÉ$2ˆk(B³Ùl{Nöa]D'ÕÍñö±m)ÁÑ(ptØ67&Eê Êè÷<‰7²$̨ÀV² ¤Ó€e){ÎmøÈ²Ñ9$©T*“9¬¦Ù½ÇY::¬±X õzÝ©Öl6¡ëz×blI>uê”ߟÉA > mkü¸ð‚³«dAÐue²MSïÞ‚¯²}M8Ì*×$pŒµM¡ ´N»}bªJp>Ÿ‡¦i¨o˜ä.Àtß}÷9U„'Þðw†ô"$ ÈV“é0dÉ1 5Ÿx¯¾rYEäÝhúd!°,©¬¡P.\ð<¶ººŠÕÕÕ…šYT”ÒÉ ÁdÙ°,õˆFû-Ðuf¥ Wår9s¼õ«²©¼ey/ a@“,é´ZÓ7´Æeùô”÷$&dtnZ ë#d…õ~j†PkT‹Å"ŠÅbÛÖ5‘HdáœUÁÝ)8E– ]o­Ó¶,Ë»8G4Ê}ÉÈR1Ö «e©|âpXy½tNÉ‚bš#ÓuÚxÜ—LÓ}2I-ð¦æO C9¬ÅbØÙÙÁÎÎ666P,ýnûH´Í@årJð„w¤²­ ˜no@–)0fšæh«8«é4‹í‘…GÕ!`Q=Ük¥RAzÔ™Òp˜59N(C9¬;;;X]]…a0 «««ØÙÙéÚîf‘è§›¦Éòðdép;¬„,3•ÊÎ* L¥ÓL!# ®·–x ¥sÎ4‘€á.Æ>pýj¥¢ì·eµž ‡„?¡ tX%ýw}}Ýynssœ­n‘N‡Õ²¬éïÛGÈ‚À‚bd™‘¨üÈÌçrêf@g•Ãn¹åÃÛsV·&Âí¬J§Ö 8}Zý›Í2ƒ€a «{j(ò»Ý1Íö LÛ ÷k"K€TMÕu+Yj$ý}d­ÇãL&Á²€ë®«¯ñh”EõH`0Í–\Ëå²÷$’̪îî*ÛM}“c†vXƒF¡Ðî—vÝ•$K@<Þ§àR¡ÐªÊDH€1Me²GžaM¥'Á0€§Ÿþøð+ƒ1$@hZK²º®w¯_­TÔ¸eŸŽ*ébiÖx¼•zÀ(²Œˆ=ïY5ÕCH€;%˜ašÀ7¿ù5N–šžk´+UP‰AFâÁPû°ÀÆÆF×sÅb÷Ýw_ÛsÛÛÛ#7¢^¯#‹y> …ÆÚ6Ǹéšrç 2cf¡o =¸Þs«é‘90+ ¦É1 ñ‡Yk[°,•`ÆèûR2óÒ¸dúö <ºs† é` ÃzêÔ©¶‚K‚—¸Ç¡X,¢^¯·9ºFÙlÖ)ê¤i …ÂH×u—Îî*ÏŠªƒ±˜æe; 4UaÆñóq÷o@ôø±ÀÌJßn8À!~2ïïYéÝ0Ô¾ ûû~-d ˜‡¶…pX!o¼Ñè¯sËbu`25æ¥qw]Ãè¡qØI¦G"lnný…Z­†®ç·¶¶‰D`.]º„z½>ò¾¯Édëï®Ö“Z1Ò<~t² Òñ\ÀÚ×͘d©d-ç8 åŒÊó)(Ç5Óñë¸}ÔÏzöÓÏž Ñƒ™¥¾–Æ=òºÎH%™9³Ö¸™\.«ª’„Lȼ´íf Æ+`e…Ybd*ÌSãѨš]Ô˜ÜSç³>Œ¼†µV«¡X,:ÙöfTšÍ&r¹\W•°F£Z­æÌê†B!¬®®¢Z­Žtýö U³ý}Nb¡ @òøÑIÊét;³YC^ׄr4ÍãÿJ­Ô4”“ ¥ã¿V\íOØGk8w|ìôñ¿9('÷´«.§üÖ_¿·þÍ­3ûºg­o]o¥Hz¦Óa%3fÖr95q:Ô^Üy"S`^Úv“Lög}Ö¯Z–ê ÕêÉ º“©á‡ÆeÌÒ³î!}z «®ë¸xñ"FÛó;;;ˆD"( #¥ ommauu@û~®‡‡‡ÚSŽc±X×ûŽÂP“@ Êi+C9†€š¡ŒÈC9x»PÎÛ–d D¯ÂÊa´ÊÊñõÜÿ·\ïe¿wþø_ëøõ§ö–ޝÝëùäL¾êYèžzê)Ôjµ¶kôL­‘MZɉ¤V«áêÕ«3»þ¬m¸IˆxÔu:¬'„z½Ž+W®àÚµkS¿ö<í·›juÀ@žéî'±ßƒ45.ó´ß‚®÷‰µ¸¸’¥GÆà£Úï¡Ö­­-hš†ííí®·ûù­­­¡º³³ƒ .xï×!ú}¸§Ÿ~=ö._¾ ËjeCêº>¸PÇ<ðš뵦tšXP©´b ¢PŽœ¬Ÿwßÿ²ÇÎl£8”³WBË -ÁÛÑ,¿Ç¾ëùú÷ÑJ÷•™Ù# ç„N‹¨Š ÎÊa•¾5à¹|ù2Q.Øb5gJð æòåË3ìÌÆ»[–Õ†•éÀ'†Y9¬ó²ß½0 Ã[ãŒY„± ™9b¿g™·ýîijæF.Çb¨'ƒÆÌ®nrOIDATOÝa•ˆà½÷ÞÛ÷¼õõu4¶Ô/ööö … ëºSìððÅbF£oZq¿ÒÚ7ÝtâñxWĨ+bišÊøÏŠº éh9ˆn2P3•“–L´f@“P3™Ò÷+P¨Û>ÈLhçóatWãuEË ö9'‹ù:¡#’H$ðæ7¿ß÷}ß7õkÏJßpóÍ7css‰DÂÙbÕê•<‰ë´‰Ãææ&n½u6k´çiÃM³˜é;ÃÊtàÅêê*Þüæ7ã%/yÉT¯;/ûÝI.7`XR©0s‚û=­ídÜÌ{ ´—Ôð,,æÞÖƒ,=2Õ~\ÃZ¯×‰Dvù ¨þÙ³gû?uê’÷tÿ= áp+õ kqw¥¢R&Üxmû"i¶q´få4vÞkäæ4¬_!E‘v;žÏ@ÍÞJq¢ðñµÅaôªÍFûÚN25æ¡o7,^@æÍ<5nš­À{_3˜LyÛoÁ0€ýÑO÷Ö8÷Ô&S»÷ÑQ.Óv“¡è°†B¡©¦%$‰¶£”ÊvGe‰öööœçt]G2™ú=:³!Ûnî|áN$ŲÓÉË¡µÆÓ}nª’®8‡2›évN-(‡²„öâE¹ãçz•¤’ 5cªy´Ë<~ïÎ-Ù÷}cúÚ³gè°’y2/­eM—vd³,FC&fžÚvcšÀO|®·-ç¾ÂdJø¡qÓlù¤mK;,K9¬»»c_›œ:¬±X Ífs`„EZ‡B¡‰µ¹¹‰ Ôj54›M„B!Ü}÷Ýc]Ë0 ¤;KÀ÷øhmÑâ& 区K©B[q¯C¥Ãz(gµ‚Ö̬û¼•ãódÆ5‡Ö,®lï"HuÝ(†Ÿ¡% Ã4ô-I³Ìn'd\¦eÃÝ™b}3tVÉœ˜æøhiÜ0ŒÁû 2f¡q©fR’Þ^(¨ í7‚¡ÖX,†l6‹íímO‡´Ùl¢X,"‘HŒ´µ Ï|÷X,†|ÐYëµæc†žò*‚Tr+hweÆ3yü¯Ì¤Êýf ÊÑ,£•Æ«¡5»Ú¹VT¶“úmy•<~f-<³Ö·çº>µi%×<‘¹0k‡Ã*ÂÏL2oæ1>1 5^÷ ®2cæ¡ñ|¾}ž(«1J¥Âì24CU ¾páΟ?ï”ÃT^ûÞÞΟ?ß³Dö¸„B¡®Ô…qè*J#ùó7zœ‡r(Ý)ö²TfS)<”BkÆÓídF¡R†e&¯EÇùÃW«è_‰,<“ê[dìY9Õ²€~û³2¦aÃe00õ,ÓŸ­tIÓ4©q²0LSãîÄ'Ȟ˩iWV¾&C2p†PÑ–íím‹EÏ­k‰677Gž]žUTe€o¢ÝqôJ¯M£åH–ÑÚ?4îñ÷µÄ¡œ…߯BWá%³§ÚožåáÉ1pöI*zpàCˆ¤KöÝ•3¯$ èºŠ¡§R»vÄãÔ5‰¡V å´ÊÖ5õzÝIžEéíiÑó&†š=•þ"cüÎÓÅ1Õ Š&UŽî5âºS†Ã®×2eÜ{Svaš,O–ÉjïÚžÌT™d¥I@ªÕ>)ﺮØ“€âÞÒ¦mv–i‚d4†vXÙâ¦3 ±Ùl¢^¯O%}`ZôÜ£Ò‚r$Ýkd;š(T¤}×qù¨Nnçõ™3=5ÎÙ&² 5N7 ®×&¦ïödL&&n GLf‘ ÙaíE½^ÇÆÆF÷K>ây¨VUÑ# ÝaZ³«ñãc:ÚÑ^!:«Ä'<9¼)%À4U*Y8lößÒ`F $º®â-žµÖ" Ç=D1MÓ[ç„ ÁPE—‚Œç@GŠ%¹ûM­ôßZ3°ì[$hÈž7„)"iš&·û K‰eI¼[ÚЖ“€S.·þ6Í!‚„ô`©ÖžéRH©ß¦Yh)›Y ÕSûÂ~@J*¥¶üè9·8!Á¦âÚ]ò,˜Y[ó»Y$€,½ÃÚ72oA[Ò¡ *¹I‚³«d¡qŒ'À“%@ê( L#ãì+ 0}·³‘=o †Ñ^Nà >2CÆ`©V #%Ø²Ô yüj=«ÉöE%d‘8:ò»„LŒ{¯aB–‘\n@`Ú'ƲZkX´w]g!12‹.Õëu‹Åj6›~–.º:†q\åà8Xî^U~wAÈBÃ{ ï2rN‚‹eµVl8G¦¹“18ËŰ½½íw;Ç&Üž@|íÆî“L øB‡•,+2Ðé[U2ez ,j©OµMŒ{2Õ0 ¤Óiΰ’±8ÃZ«Õºf)›Í&jµšßmHWdÞ4›_Ý>›ª£{ý*!AÅ4™&IO«6‡ÅmÈR"˜A@H@Ñ´öV'%˜…òÈŒ•|ß}÷accÃï¶Äs sýõíÿ×Týn)!£ã9Ð)—Õ:mBŒŒi˜öN–ÓNŸþõM–Y­Ñ·6!C²ÔU‚=ÖOÞÈU²X–åJÆ 8îX gXÉ2bYÀ×¾öµÞ‚9óJŽ»A<çúU2Kë°^{Qš&ðŽÏ¬ÑA! ¦);Þ×a-—¹ï0 $ñ8ðÚ×>Òû„\ŽÙ2$°P(¨¿uý¸v4 äó~7_Öz½Žz½Þ÷x£ÑëÚ–euG.-‹Ñ27f©oÀµ­{Àn\BæÆ¬4žN+SíiÇÝT*Ü«’Ì„YÛïh8<ü“Þ©’¯3K‡Ã-ùöÝk˜!X%xÔëud³Y§#D" Äb1@£Ñ@6›u:’¦i(H¨fR) €2Cæ¥o˲T>“Z˜BIfÌ\5>êÉ™—¶ËeõoO‡•)ÁdFÌCãÑhk «atXÉÄ =ú±±á<¤B°û9y {­D"Ã0péÒ%$ d³YçøÖÖ"‘ˆs¼^¯£X,ŽôÁÐaeäžL‘yj; …1†Am“™0/[–*§Q(oM&AuBÆdîE—B¡‰„óÿF£b±ˆÕÕUD"‘¾¢Ùlö<öÄOÀ0 'mÁsJ<'žZ­†}èCøìg?;õkÏJßð•¯|ÅbÑIÉÇãjvU‹XVkÑ9Ñ‹E<úè£3¹ö¼l80D*4'’½½=|èC—¿üå©^w^öÛ4UŒ±¯¾©í‹Øï©MÔ¸˜ßÇÿ\ªTTpœxd >ªýÚa•EÚ²;{>†¥Ùl¢X,â®»îB"‘À… œç{qíÚµžÇ®»î:ÜrË-8{ö,”à\øÃÏ)§•œhN:…Ûo¿/|á göÓÖ7<ïyÏÃÙ³gqêԩ”*>ÃpöìÙ¶ú,˜µ ×u½ÿ–6\¯}b‰Åb¸ýöÛñüç?&ןµý6Mà÷ÿ›½OVÞìì¿H²ˆýž•¾ÙÛo‘¯išx•Œµ¨i‚Ö|T}U%X×ud³YD"‘¶AÐææ&B¡t]G½^ǃ>8Ô›Öëulmm! áþûïïJ=èE$éyìºë®ÃK^ò’¶ÈQõ¹AC$Áí·ß>0">.³Ð7 <¢ïøÃ>|s$($ Üpà 3»þ¼lxß(É9#'ŽX,†f³9>ûýç<þøã½õ­iÜŸ`Ä~Ï*è8kûí^dš&nøÈGL'ãŽÁ‡šaÝÚÚ‚¦ix衇ڋŰººŠíímœ={÷ÝwßPošÍf<úÎÎ!³Gî´„F£1ðfÐIW•`Ãšß ð@fÌ<ômš&+ïßðņw")ñ„L‘ùh¸å–oôÎ  ÃJfȬ5nY-ù:ëWé°’ è°JE±{ï½·ïy÷Þ{/vvvæÜ뺎F£MÓP«ÕÚ€ò¼‰öööÚ^“L&Gú`Nz²uü0Mà9Ï¡ÃJfʼô +_ûÓ"ÉÜ™—Æ{Vz'dFÌÓ~?öØŸõOy'dÌC㦩VÃ0pË7¾¡žd†LÈÀ”àz½ŽH$Ò]I$mé rüðð°o$FÖÀzíÙ*õÍÍMg¿×f³‰P(„»ï¾{¼O˜†ê,Û“3O}ßö;¿üøûý‘É cî6œ91/m‰|c¤º„Lƒyh\j?꺅ÿí»¾‹³«d* tXC¡çBëííí±Þpsssà69±X >ø Ó±ú®Kõ ­XG@ø8µÌ·µ!3eúÔå¹=ƨ%™;óÔ¸{3{Bfͼ´ O?ýqƒ÷®'dšÌSã†aà€+™ V)nP«ÕúŠVÒ ¦µH¼³ôö¨8ëûòôãâÜñƒ,“êžûýßï÷Ç ¤'ÓÐxß”I]Wvi•dÎLªíT ¨Tz¤¼†zp‹2â#Ó°ß–eáëÿÇÿÁÀ:™ ×°Æb1Äb1‹Åž¤¨ëªj !Ç0 ®Ó&Sc¨mm.\¸€ œ?«««mNéåË—ÅÙ²“ßhš¦fX×T¡œU®!KÄw}éKÀ…> CUÁfQ&²lXuM–®Ó&Ób(‡5‹áþûïÇÎΊÅb×ñÕÕU¬¯¯\Ú}–De:5 ¦Ö¥ãõ/{5diadž,;=õÍt`²$ Ì’!d†rXUøÂ… ØÜÜtbÊ™ÕæÆñ'í&¿[AÈL¸ãúë™L–˲ϰr0DŠ®ë½õíÞÄ’€bY~ñïÿÞïf%bh‡U˜ÆBì™cÀöãÀƒoô»%„ÌÙèŒ%d¨ÈûüçûÝ ²dÐa%„ ,KU&dÙ0M \ö»„LÌç~ø‡ñù·¼Åïf%cùS‚ !„,• ·þ ËI¥¢2„˲˜E@¦VB!‹‰{F5W³.Y6Êeå°V«~·„‰IÑF“°ð)ÁõzFÃïf2¨o²ìŒ¥qÃP[’­­©}´+õ·iªýµ Y&¶áå²zT«Üª‰,£EaagX²Ù,êõ:@Ó4 ¿›EÈT ¾É²3‘ÆãqààÀï@HO&¶á– * Cg•,£EcagX·¶¶‰D`.]º„z½Žb±èw³™ Ô7Yv¨q²ÌL¤oÃ’Iõ÷þ>U²pÐ~“Ec!ÖF£Z­†õõu@(Âêê*ª\ßA–ê›,;Ô8Yf&Öw¥äóêAÈ‚AûM‘…tX±XÌy.‹-m}±XD­Vó»c±±±áwÇIÓ7\Ôj5F•Çà¤iœ6üd1±¾óù@­ÅªFh¿Çƒö;8µoŽÃB®aí×)šÍ&B¡P×ó—/_Æý¯ÿüàqûí·ûýFâÑGÅÃ?Œn¸Á歷̕+W×a¾ò•¯à+_ù ®»î:lnnÎýýÇÑ7üõ_ÿ5^÷º×áÆoÄÍ7ß<÷vOBuW¯^E³ÙtÖñ…+W®à©§žòíýiÃCûæ£>Š«W¯âE/zQ`l8í÷ü ºýþƒ?ø¼á o˜ûûÓ~‡ öMƒj¿Òam6›=]»vͳ³Ü}÷ÝX]]E$ñ»ù#Óh4ðüç?¿§£²ÈÔëõ¶(\Ph6›¸víšoïÝ‹^ú€ÿøÿc ¿k ø: ¢]ñsF‚Þ7ýzï^ôÒ7í÷ü ºýöë;§ýA°k¿/¿Wg…B[¿Ï‚ØQõ2޾½nÑ jÛƒlWüüÎiÃûæèŒ£ï ~ÏAn{m í÷ü ýž?ãèe!×°ž:u @{ZB£Ñ´¨¨o²ìPãd™¡¾É2C}“Ed!ÖH$‚D"½½=ç9]ב”2ð„ê›,;Ô8Yf¨o²ÌPßdy†mÛ¶ßð¢^¯ccc‘HÄYä½½½Ø”BÜPßdÙ¡ÆÉ2C}“e†ú&‹ÆÂ:¬Úª»% ¿›CÈT¡¾É²C“e†ú&Ë õM‰…vX !„B!„œ\r kP©×ë}·’¨×ë}÷·êw|Ðk§ù¦Ùîy¶Ì–Yê{˜ãÓú Ónõ½èµÓäâÅ‹ö=÷Ü3•vÏ»ídvÌRßßúž´mÔ÷ò0‰Æ—Ußól;™´ßþ·ÌÚï“¡oΰN $ †K—.!‘H ›Í:Ç·¶¶‰DœãõzÅbq¨ãƒ^;-jµvvvÚž›¤Ýól;™-³Ô÷0ǧ—¾'mõ½sæŒ}õêUç¹ÃÃCûÌ™3ö#<Òö·ðþ÷¿ß>wî\׹ǽvZ\½zÕ¾óÎ;íw¿ûÝN„g’vsœƒYê{˜ãÓÀKß“¶ú^&Ñø²ê{^m'³…ö›ú^vh¿O޾9Ã:!±X¬«Ô÷áá!  9Çb±¶×H>y¿ãƒ^;-¶¶¶°ººêl=¨]Ó8N‚Á,õ=Ìñià¥ïIÛF}/“h|Yõ=¯¶“ÙBûM}/;´ß'GßtX'$ µ•ûn4(‹X]]E$é+Žf³Ù÷øÁÁAß×Nƒ½½=4 lnn¶=?I»‡9N‚Á,õ=ôÒ·|–qÛ6¾IæÃ$¤ƒ ê›6|9 ýö¯íd>Ð~ûÓv? Ã:%šÍ&ŠÅ"îºë.$ \¸pÁy¾×®]ë{ü‰'žèûÚIi4ØÙÙqÚÚùyÆm÷0ÇI°˜…¾g­“~úž´í³î›dþŒ£ñA:ª¾i× Úïù¶ÌÚïùµÝ/è°Nz½Ž ÔëuÜÿýmÑ÷t|'‘H¤ïñ~5G"‘‰Û½··‡P(]×Q,Q¯×qxxˆb±ˆ›o¾yìvsœ‡Yé{Ö:é§ïF£±Ð}“Ì—q5>HAÕ7møò@û=ÿ¶“ùBû=ß¶ûÖ)Íf<úN‘H^º{z¾Ñh8‚éw|Ðk'åìÙ³=;ì‹^ô¢±Û=Ìqf¥ïaŽOB?}OÚ6ê{¹Wã˪ïY·ÌÚoê{Ù¡ýžoÛý‚ë„躎F£MÓP«ÕÚ€Šd$ ìííµ½&™L<>赓’H$°¹¹éèµÓþ,õzÛÛÛ·{˜ãdñ™µ¾‡9>ÍÏâÖ÷¤m£¾—ƒI5¾¬úžgÛÉl ý^Œ¶“ÙAûíÛçÖ9Ñl6Q¯×xçÍ÷;>赋Ún¿ÛNæGuÔ¾IæË$:ª¾ýn;™AÖHÛNæíwðõM‡•B!„BÈBÂ5¬„B!„B:¬„B!„B:¬„B!„B:¬„B!„B:¬„B!„B:¬„B!„B:¬„B!„B:¬„B!„B:¬„B!„B:¬„B!„B:¬„B!„B:¬„B!„B:¬„B!„B:¬„B!„B:¬„B!„B:¬„B!„B:¬„ßÐu–eùÝ BæÎ´µoYt]÷ûcB!S‡+!Ä7’É$ Ãð»„Ìikß0 $“I¿?9Á”Ëe˜¦éw3™9Ôúü¡ÃJ!„B&¢R©pONÔúüù.¿pÒ1Mår¹ëùt:h4  ɉF£Ð4 º®#N;çêºî¤‚¥R)Äãq@.—C6›E¹\†eYˆÇãH¥RÎõÂá0²Ù¬sQÏ'dÃè …,ËòÔX/}Ô8Y\æ¡ý|>B¡Ðö¼`Y …B×ë—~šÖu¦i¢R©4MëÒ¨®ë´×$LªuMÓ`Y–£Ýp8Œt:p8 €ÚΰúŒeY0 Ãyèºî `%êB¡@EtÖÖÖœN¨ÁÎÚÚšs­••§“É1˲`YÖÖÖÚÒÐ …r¹\×µ†=ŸA Ò7d2çÿ½4)×rëÛ}œ'‹Æ<´ŸÉd<#ý–e!™L:!B¦Á0švÓ©QÚk&ÕºeY8}ú´p¬T*mK6¨í1°ÉÂpttdÇãq;›ÍÚ¶mÛ6ûààÀ9'Úš¦µßßßwŽ—J%;Û¶mÛìR©ä‹Çãv:vþŸÍfks>!£Ð©oÛVšsÿ¿T* ­oy=5NYißýújµjpÞË­kB¦—¦5M³«ÕªóÿNÒ^“ 2ŽÖÅ»¯¡iš3ž§¶G‡3¬ D&“A4E>Ÿ "2𦵥¥R)ço]×FêîÿK”ÆýÚp8ì¤#ôbÔó –N} š¦9»õ7Œ¾;_C“EdVÚw¿^(½û^AÈ´é¥éN:5J{M‚Æ8ZÝf2躎p8ŒjµÚ¦gj{4¸†uAÈår0MÕjÕynЖ’v )Ã‚× †?ñÒ÷ ¨o² Ì[û²~*“ÉàààÀïO–q4MHWëÑhÕjÕYÊgYÒé4J¥’ß)°Ða]Êå2Êå2ªÕj[„%÷uZãñ¸µ$ÏuKdQè¥ïAPß$èø¡ýR©˲P©TœB „L‹q5MHИDëR8©T*¡T*9ÛŽÅãñ¶¢©dx˜ì3†a “É`ww·k ’J¥œÅÞœŠc‚» ™ ¿ Yúé{Ô7 2~j?;+¹õ™ÃhzPf!A`R­»gV5ãÊÏdÐaõ©ø›L&ñŒg<Ãyär9D£Q”J%$“I$“I¬¬¬´¥„É $—ËaeeÅ©"¹»»ë÷Ç"@}‚ú&AÆoí§R)¤R)xÈÔ¤ép8Œ\.ç¹!AbR­Ë6§OŸF2™ÄéÓ§FY[`žaÛ¶íw#ˆ7’F}Xe&÷ÀÅ]ˆCRÉY¨orR¡öIpYÜeY6†ÕºdH†Ãa.eš:¬ Œiš8}ú4ö÷÷Çaš&’É$²Ù,sà !„B!K‹.-0î”`˲‡‘N§é¬B!„BNœa%„B!„²,Í ëÿñãw÷wñ}ß÷}~7ed>ûÙÏâ…/|!^øÂúÝ”‘ ê#O>ù$¾óïà½ï}¯ßMšw¾óxùË_îw3Æ"È:yòÉ'iW ÃÀÎÎŽßÍÚprß|þóŸý¯ÿµßM Úïùtû½µµ…H$âwS†‚öÛ‚Ü7GµßKã°þýßÿ=®¿þzœ={Ö歷̗¿üe|Ï÷|n¿ýv¿›22?üp ¿ó+W®à _ø‚ß͉k×®ò»‚­“o}ë[lûÃ?ìwF‚6Ü‚Ü7†ßÍÚïùtûýüç?ßïf í·?¹oŽj¿—Æa½îºëð’—¼‰DÂ歷ũS§Isó–·¼%°ßy³Ùô» #ñ¼ç=/°ßuPurêÔ)Ü~ûílû 7ÜàwF‚6Ü‚Ú7`ÙpÚïùtû …ünÆÐÐ~ûCPû&0ºý^‡5ÈUl°ººêwHªN"‘H obd¾Ð†“e&¨¡ý&Ã@û žéw!„B!„/è°B!„BYHè°B!„BYHè°B!„BYHè°B!„BYHè°B!„BYHè°B!„BYHè°B!„BYHè°B!„BYHè°B!„BYHè°B!„BYHè°B!„BYHè°B!„BYHÂa­×ë=Ÿo4~7‰ ¾É²C“e…Ú&Ë5N‚€ïk±XD±Xl{®Ñhàüùó8þ<îºë.d³Y¿›IÈXPßdÙ¡ÆÉ²Bm“e‡'AÁW‡µV«agg§ëù­­-D"†K—.¡^¯wu(Bê›,;Ô8YV¨m²ìPã$Høæ°6›Mär9hšÖö|£Ñ@­VÃúú:  auuÕjÕ×/ŠQ ¾É²C“e…Ú&Ë5N‚†oëÖÖVWWqêÔ©¶ç±XÌy.‹1ž ê›,;Ô8YV¨m²ìPã$hŒå°‹Eœ?ñxÅb{{{#¥ ìíí¡Ñh`ss³ëX¿NÑl6{{úé§ñå/µZmžß FW®\Á“O>9“ëÏBßðÔSO¡V«ñÆAR«ÕpõêÕ™]Ÿ6œøI½^Ç•+WpíÚµ©_›ö›øØïAšÚoâ'2Õ~ì°ŠƒšH$‰D¨”½½=lll ÕÐ\¸pÁóx¿ÑïÃ=ýôÓxì±Çpùòåé|£di9<<œ™Ã:+}jÀsùòe'JH/._¾<³Ám8ñ›Y9¬´ßdû=‹€ í7ñƒªïïådúöö6‰„S [Ó4D"œ?õz½-• “½½=„B!èº]×Q¯×qxxˆb±ˆÕÕÕ¾¯Ù‹›nº ñxÜ3bDˆ›D"31¬³Ò7Ü|óÍÔ7ŠÍÍÍž[L m8ñ›ÕÕUD"‘©ÛpÚo²ˆý¤©q ý&~3î|$‡U"ƒòfnb±b±ØÀ¨þÙ³gû—|úF£át÷ß$8˜&`Y@<Þþ|2 ”J@4êw §õM–jœ,+Ô6Yv¨qTFrXC¡•2  Ífs¨ˆ~"‘hsxeí«;*“H$°··ç<§ë:’ɤßßÕÒaY€aºd³@8ì}PÎå°¦®•Šú7WŽk8 ìîªS)u|·ö¢¾É²C“e…Ú&Ë5N‚ÊH«Ì¢nll´å¿7 \¼x‘HÄsöuT677±±±Z­æ8Çwß}·ßßÕBbšÊ14Må\Z°¿¯Ž­¬(Qª‘—ËꯎåóÊÍdZí‘å@ ÕË!õ¨»s¬¬¨ØhT=/Np4ÚrŠ£Qu¾ÌöêzëûÉåÔëòyuN¹¬^#ŸKÓZmž''Uß'™^—e…'“ ÷>±ëîÌ7Ò¯<§ µM–j<øˆ/N{g.†÷ÿçr­1uµê=a”Ë©ãB<®š¦®-ã9GÆáñxk¢IÓÔßëë7Œü9GvXC¡¶··Q¯×õª¡P¨ïBíq…BKÓILS9z€K:ÝrLe†Ó=›Ù™~+瘦åî®ú¿üÝ/"âu~çÚvï㽜ÑqY[SNu.h¯ý&¢ø2€h×ût:Å^Ÿ§óxç5 å§R‹‘мLú& ]Wý\CÒOçB.§:Ä N>G¨ñÅG~^È`Ã|‘û”×€F(Ô£TRöÖý¼\hÝ åššÖÙÓɢțÚ&£bšªOiZ+CÍM¿¾èÔø|0 uû‡•6¼ÆØ•Š:Glf§íÇÕXZE]WçËP<Þ²Ån‡S ´jµ]ƒ™LkB,Vcgñ7ÄNK†§sû#é´z­iv·»V»ŠQkæä°Öj5lllàÒ¥KSwP—™µ5õcºoÞcK÷lf/âñÖ,$ÐÐ0 iÏÛBºrR©(’IÕŒRö˪ÓÁÁd×î±86›UF¢L„ BfúÝÿ7 Õ%ý½RiÝD4­%ßÓ§g0‘Wˆ4Vw—BA‰}QFödꈙ“GÉ:‘h4ÚÒ¦;ã¤PP2I¥Zu$š«ãå²øÈu%ûÇíTº—z¸‘ãÙl» ÖuumYžÒÙ':ï}ƒî…Ò þ×ÿÕï_‚ËRú³¬V&š™L«ÞF*Õû¼•u- ~‡ÃíÃ)Éö’ 1Y&%ýSœ  µ|+“iÝ[¢Q5füüçßì÷WG† 3óÑ w*¬û<±ËÜ–ŒH™äŠÇ•-=–ËJî÷/3œ€ÒÙþ~ÿl¯••vÛŸNwÛf©7#«{Ø1¨Ÿ£Ô¿ÄÈkX¥öêêêtZ0Üë<9…ã S$È P¢ëg$G¥S0c#£•^£iә׫iÈf£°¬ãß$|œ-À°ŸAzÐÊ–‘Vá0Õ `%ƒ›“Ià%/™Ïg'ÓÇ4aýÖïŸþ4Âî(»B“–þÍ׿ùQ¤þáXϺá7ß1ôå%¢éN#QF:nQ °ÚCæbèÝÑÒÓ§[¯'·ìñ÷ˆÿ¿Ÿ@üÿ;âo¾æÿó7H™DêAùíG¡ñÝÈÿ§›çò¢HU«-ï RÁMO=å÷¯D†D~6÷àGjÈE&DÉç[÷6˜¸µêÖ—T*•V@g¥v‰îË5:c"&ue¥5à––W¼±óž8)ѨºæÙ³ÏžÿE|AR¥nEçØ0Tÿ霡’¬ÑŸÌpŠciYÊé”þ ¯qÏxêÚ2¬™,ÉÚÒ´–³)ˤ:qÏLyÑ9 ÛÝR©Ox½ß_=€e)íN·Ç[3™áp{À"UÚ‘ô[ -¸õèÆm×eéD?]õ;–N·fmMÓûý,i °Gä°ï¼óNûâÅ‹ž¿xøá‡=ß?›µíx\ý»¿?ý÷M§Õµ…£#õ°mÛ.•l[Ó|ûJÚöÁÁìß'Ÿ·íTjðyûûÃa¥’úaå˪Uõ¼Nw¿öàÀn¼ýíöüÓ:ûÏ>Eî¹ç¿›0UŽŽÔϳ»;Üù¶}ôž_µíxÜ.}÷–­½ì önþÀ¶Žì|䢽›®Ú¶­¤ÚvþŸ³2ÛÎfíhè«öÁ­w¨ƒ.ªÕÖßѨm§þÉã¶Ï·õã¶Æv~€RIMkÓãþ~»äKïzÄN¿¢Öe„òyÛŽÞò´]Ýþl÷÷cZönºjgoû€¿ãì#Óêù½ˆs°ÿƒ0ïŸt"zÙð “Ï+i„ÿÑ1©”’–[‹ó0˓⾧¦Ó]]k¦O/Ëf¿§ÁÁAk µ»ÛnsŽÚï ûûª?ÅãªOåóí&y¿¥ÇýýVŸë5î;8hïsnö÷[ãýýö!Eç5òùÙ|7AÓKÐúã0”J¶ xSDÂþ~k( 6¿ßØfQlüînï~0KÆÑËÈë™3gú>ü¢×‡×´Ù C|¦~Ç;ý©…BÛ£Ò5šð^Že/¼~°l¶ýÎ$Qˆ^×”ÑS6ÛóóѸíÖI§q—|4Úû5GG­s4Ͷ÷7w<;ôÁ'¿fk±Cåt¦¼ã¥­¯*mŸ”þ¡GlMk?÷àc_jéK,ð y‡ÖݧGoýíƒâ‡[Žm6«ÚoýÙ‰GûâO§Rê³f³¶}Çÿyf¿å,˜wŸ<:š^Ó=ÀµíVÜ,lú†‰å-2GGý"h6<èö{d/Èà^Ìêînûíú訿ɕ×Ïr ½»ëï„CÐô´þhÛJCý4*-V«­¡ƒm·lÞ°ÁvÒÍ8z¹è’áU¾oÁq§¸ó¶'AªnIÚ–ó¬fس‘’úëU"7n•æ ‘ÜÉe”_-ynA¤R­ŠB>¯Þ{m­•WÑïGÌç[{úHÎélš;ÃôpÙÂMúK&£~&MÏßûVär¯ð”“oIÈ»´~ô•7 úÈ =K¦kí&ê3fÞòð­CTÿ¤ã:wÜ Ü‘WßÇÚZëÅÃ,—ŸL¥Òi•S.Úÿò,Dßùàoh-Â;ΛÆòŽpXý|²^*¾4­Ÿo))—Õ¿’fÛ¯ ¸ çÉšQ·}7Íöúº~¬ï!Ò©æZœkÊHj¤icñ7àSŸz™ß_9FVãÈmY¶ÙóéFÒÚÝCwÊx8Ü¿œEgq—Y ÅfÈr"ö\~ãrYi6VÚÊåZiÞ^©±uiÈìÙa€½½=躎Z­@•¼Ö4m!×µº·uZ‹Þ'šì5´|,K9lîª++­EKî·8ˆƒœO©º!×XYi½Fc¯kŒH§Õµ¥xŒP*µžt§’ÑûIÙWdR còq\­Â´ÂÈåŽûÝw¾ƒý³@>jµ]N!šFö_½¹‡þý–Vtúú"ô¿ù§ØÿÔÿ0t3ýärSÂM7¡ôÀM½Ot/VEGâÅ×rɶUæ¦ÂÚ˜¸¨Ošk?ÜkÔd}›òBb~RôHÖ¯y \zý¼R|È÷`攨TÔ÷6I­¼qyÕ«®Â¶?ï÷W°ÔHµæÎ‚+@«f‡8£²^T5ò·32Sg!Çw@k›E±×R hÄYu(ÓéÖüÐ2JÖ«’ùòÌQ_P,±µµ…H$‚õõu¬¯¯#‰`kk [[[~ž.:,·&Å08úV.«Þ·»ÛÚ˜iwW…Œ:÷ÊÍf[f:q{ûRhõÖr¹U¶ÌëK•棒JyoÄ7Œ³:é{/–¥ r&Ó^å¶'“î ÀúWïEfÅ@2©$·¿ì¿õ—•†’IïZê"ü¡÷£tׇ•Lª+dþh ¿ü ‡²L…Mù>†šLw3ÕtÚ1<•J«ò$Y,:‹hI"‡—TÝ{@K¥\‰Åõ’¶ñx»iK&»ƒªA"žNÆ’C¯ýlÈÈLª«L¦ÄÉåT2ÖÚZë'’¬!ŸWZ(—Õ¹RèëÄ Í’IàÆÇëÜ£“ŽeGGJs¢ÃÓ§{›rY -$ùÎk ÀYõ ‘rÈCð¼+Wpó£ŽvýQò‡í3gÎØU…?ü°}æÌûðð00ùГжîn˜…P£/hÍçç³zß;‘_VK¾{íàÁA«ªÁB/Ôõ&ˆë-†]Ó+éìîªuR¤¢ç2É~‹Hm»µPC*ctrtd§ÂU;ÿ²ßl׫¬u´Øû˜ýß~ÄNßýMç-Ô:¥¬‡4o×Îf³v6›µSsXX*•ì#Í{=W­úW\k zS­z›-¯eïìC—….Êç²Ø1m­õîÑ‚fÃçÙ;×€Žcƒ¼Ê?ìïw-?Š¸Ì„a?°m·ª×ˆ±ØÝ=®þw\trÐu:*xÒ~Îþ~K{²ÎyžÅà|ÿð~“J WÐ`w×þf$bàg~f¤Ë4ÃzxxЭ¾”d²{ÀèõÅËôœ{Qîþ¾zÏνx:ß[î›AÉ•ž¹œz”Ë­¯K¶zIĽ£¡,ùXúÔ]]oe§ùYcHfW5Í;cS8Þ|¶~ñ"¾rë­#½ÅÈ)ÁÐl6=Ÿk4þ}YôrXÝÙ¬Ñõö· ,«U­^/Žì0Z”qœÛk2MÕf™xŠ„3,z4 …–ïcšíë°A`Y¾±tó)’£ŸË©@‡l_­v9Ïlö= Áø. …Ör(©kãuÎqµÚoE"£öQg|Ï;gßsÏ=m©¿‡‡‡ö»ßýnûÎ;ïôm&Ú+¡ß>[²ÿW4: 4µ»vúqëì«?f|òkÞùcýRd¥NvçëäùTêxïŽ}×!×4¿lØç•ZÒ¹‰™óô®Fí’+/âèèÈÎçóí׃|>ï\çààÀÖ4ÍÖ4Í>pµ¯T*Ùñx¼í¹a9::ê™~9)‹¾2*ƒR„FÉÎv~ŽlÖ>úàÇÚŠ½êúK®™K;m)7GGSŸ4MkÓäþþ¾Fí££#[Ó4gɦiŽFåxûg8°£éÌîëõþüêµÑhÔN§Óv©Trþ–G'’v¬>sÉ9'›ÍÚù|Þ>::ø¾ó„)eÞŒ»›×´=zeâO“t:m‡Ãa;;ýOÓ4;{.ñ©V«v:¶£Ñ¨£yIõ›îÕGœýªØ€l6k°¿ô±µíëspp`çóy;•JuÝ·: š ŸfôJi—í¬d+Ž^È _35­­vÚÜ££#ç9O{Ú9¸;þ{ßN¥RÝãjÕîÜÃìcü ì~ög‡kó8˺z‘Ï«%UšÖszRí·l ¶ ·ÑÅC´/Îcnd9–ØÑq÷ãf£mw*ðÁA÷رcÛ¿¹ìÃúÈ#ØçÎëÚõܹsö#<2ê妯¸E¾W¯{¯mÛÝ=çèÈŽ¾àIuWðº3t®×Ëçí/|ò“v8V†·×ew·KDù|Þ0¶c)h|Äãqg Ífíh4:öµ³Ù¬N§Á…¦iönNP­V÷¬XÜ"–x<î ŠâñøÔ€  vl{ð lœµ¯y»½í;N %›=–æî®Ú1»ã¢GG¶½¿]sŒQ©Ô§ïx Z<::²ãñ¸3ø­ºàˆ»úQ6›í¼Š£é…¬gí(qëUÖÀºÏí@I;ݸÛï~߬‡7$}Ñí w²¿¿ß³ÃIð "ö¹ì+<zvl»ÕßÜHßÙÝÝuú©³¡m;ý3z÷¯jÕþo½ÕþÂOü„ý«ïyÍfÛì·ô…|>o?pö¬¼£išÍfíýý}ç½{Ý3‚fçÙS©n ©¯²Ÿ¶Åp}åóGÖtjšýõ÷¿¿g€Ð¶•‡½ÿ‹®$øØo¬!çŠþG Ç Å€÷<‰öûà +>Sö÷÷'ž¸™G½ *„Óâ¤æóíÎë Üùa¦È\ÖÎ7»xñ¢ýðÃOõƒLëÃó4à=vD?8°ûÏ$e³­JÇŽZ<WÙ!f Ô{¨Áîî®­ 9²éìxƒçƒƒƒ¶s¼f¢ö÷÷íjµjW«Õžƒ}¯Áû0ŸGf¥¼eiK*•²óù¼ç,­´³T*Ù©Tj"C´ÁŽmOé–JµwŠý}gcl‰Ð;}Áãû•xKöÿÍ>zϯŽT“¶í¶A® H;<ш۩“ȹÐo.¸gMÝz¶OI;$pÒ©·jµjh¼ôšeu÷Åjµj§R©¶ÙÉ„ðú>¼8::ê«ÿ££#ûŽ;îþ‡YæÑ'%AÀo:ê«ÌîÃf³öϾõ­í’ƒWdª=ð³»»ÛeÛÓé´]=ްK&m·gtòæ;î°?öêWÛÖ7ÚŸ¸ãûž³gc¥RÉÑø‡Ÿ÷<ûðÁmÛVÚÎëÉ}ÁKëA³áÓt@ÆÕðÁÏÎêqöŽešv!“±¹îº¾³è¶­ôâÎ èå,ÊØA½Í¾PöÜAN±;ë@‚ÿ½^㸔̶ÝÝ]ç~tppàŒ·Ü×:88°üÇܯ_i,¦ÕçY¤PîÓÐùÛþyºÆNd©Zm¯žv|þ°È„Ò‡Þÿ~5ö;¶ámqøiš:GÚÑ‘íÙ6£±»;Ò lZö{,‡õðð°m6õá‡ö­:p¿ïÎæ–6'wÄ¥ãjYO¿ç=Îv'Ï=Ô9#sttÔÕAdp.ÑoÐêHò:÷ AýËI:hgTßíì…DýÅ‘¾Üt䦿5«&7yØvð;¶ÝÀÓ##Üë‹ì«i×DJ2Ø?:²íìOÃÖžû§#åíôà¶¿w_ÝÉ zÐ@Çý¾¢÷ î4Ø÷tê³mŸSúŒ×yñxÜÉ(6Éóî˜dtöSù[f «Õª“=ñÊW¾r*Ÿq^Ì£Oß³}g”`êØÕ¯óyû±»ï¶ßì¸ÈÓq`Rf™¼fMÝÙ™^ýjµÚ W ßFí'_ðÛ>Ö¦¼æêM793°½î+Ò.MÓœ¬ž£££ÀÙði9¬’R>oÆ ‹Ýr~œ‹,6k¨qD>ï¤Á}æÁ=Ç 20w#KL:ï92Vðz}6›u^㬦Óé®,²|>ïÙ™1–kI°^²Ìäyy¸Ÿ ‡ÃŽÖOšýžw5}wÖÓ$ãÙ¶eìïï·ÝŸ;yçÞàèë¸aíÓÌâ Ú­À¶¼g¿qŒØÍÝÝݶ@K×RÙýAR5­µµDûfÛѨýÛn³?öêWÛï|Ñ‹ ÷SÉxD&¤äþ1‡õ°Ïœ9Óf|ï¹çûÌ™3ö<0Îï=¼>¼¦Þ drÔùOGŠ^Ÿ*ûíÙv*eÿÛŸþiGÌ^i^t_·ó)FR„hÛí3"è~)ºHú•×ónƒž]Ú§Ó­-aŽîº+GGGÓ†Ýn¢5ï-ÈZ÷*w³ß=C bŸ;gìvwwíp8ÜwyJ/N’ýö#óEƈ^6lXJ¥’ý+o|£}Ç­·¶~_qúlײ¼|ÞþÜm·ÙD"ö΋_ìèï/îçì?~Ñ‹lÛV6ö/îçºfTѱè¾W™0hÜÑoò ¶½mæ8óÅ{y_çõ:Óðe|îÎ$“L¹t:mW«ÕÙ:¬W¯^µï¼óNÏ7yÿûß?ò>¬ƒffyä‘¡¯×ËaG+‹ôev¾ÿkÛ£(nCêNctGíd°/3ˆ^Uö£”Á¨¤fÉk:ÓIÝü‡ÅÝ:":Ò‘¥N¹‰õjïÑÑ‘ËåìŸq¨Q™¦¾m»÷ ¬Gæzbl¸é&ûgoº©-ÊëŽôöоç=O;7g1†î{fPלÑ}P(•JÎ`Åæ1à™µ ÉtFÛ³âñÙÏHíïïÛ&û­; Uظí6ûé[niŸµô 3-íèèÈ~ò/n9I6kÿ÷W¼Âþýw½«ç)ÒÏ;9iýý²(ä;rúp>oÛ.»1 GGGö›ßüfû§~ê§Æÿ¾0/û=*éô|÷9•ÉA™Po BˆFvwwgh•J­Þ²¯’e3lrwww¬€R©T*8*c®IïqnN’ýö(á2sÜAAË‹zñ_ðû›?ðö×_ô"û÷#‘Ö޻ǚ‘Œ‡£#ûS?ú£ö#×]g_ûàíÃg?Ûq ìWÞv›g4ª_²Î 2Ûö^^áõù{]OúVgFA¿õÞ¼‘ñd8îé‡d³YûöÛoyÒh$‡õᇶϜ9Óóø¹sç†ZÏúÀØwÞy§S°éž{^½ê?<<´ßö¶·9ÇßýîwÕ¶ÎÎ2ª8{Ö~äºëmëºwÙ¯~õÇì7½é~ûÌ™'‚n޳)J¢ ©TÊYóæ%št:ÝUQ¢zƒ £×`}Xƒ: Ó.#T«U;ûâ„Ì2lú¶íÞ7°a3×c# è¿÷Δi)BäŽ.Ë€Ut ë0;#Ç2°žfp#ÈÈ Ñf9à™— wÅ÷RÉ{uÖ| àŒ’ÙÒÅî®ýØÝw;ÿ•µúïáfÿ8½Rî;}û-·ØµW¼bxíIžiŸ¢7âtŽ”^çª4Î=`V6|Þö{Tæ9Õé`ºÓ å^‘N§í»"ûC·ßnn¼Ñ~çÞ`o­®ÚD"ÎuÜUÙ‡¯ ,6Ó+3lY8)öÛ:kbÈ2³QøÓßú-û¿½âÎ çWb1ûÉ3gÝvÚo7¿ÿ®wÙ_xæ3íRG@Ñ« c¿¢dn$°4¬–Ý ÜˆS*52d镸-Óìo[[[#OMÕa½óÎ;:¬2K+éÃW¯^µßö¶·Ùï{ßûœsî¹ç§ƒ\½zÕ>wîÜÀŽàÕYF ÚØ~Þóœ0ÏÑÑ‘½½]³ßõ®Gì7½©nkZ+DœMq\Å»…&é‹^ë$êHücVÆuVú–×yᑹîqNÖ¾x÷Ý­Á¨Œð=p;ÀGGGö»ßýíx|ö2]f5à™§ †¶Ba>à.âÕY;@ÒX‡ FÞsö¬}>s²:îYÖO}ô£NÊxçZçªјÖlO©dÛÇ[—õ?­4Ú Ó„ž×,l¸ö{Ç_Ûÿ‡aØ?w^Ó4€ ÀYOéUÇB²fj¯x…}$[òç*_={Ö~ú9ϱ¯~ô£]¯›Eà{Y9 öûx‰ûÜét %? Dqðd=ò §Qª°»‘û‡Ì–ë¬v^c˜`gáJ/§´WaÌi0—5¬çγß÷¾÷µEc®^½j¿ï}ï³ï¼óζç{5²Óé½xñ¢Ó9í3gδuzÿûßoŸ;wnä?JJp:¶¯ÞtSßsdðÑɰ!‹Ã¬ÖYéÛ¶{ßÀ­_Ãtíƒly¢2¨õ<¿=¥Òo‡€ŒÇ¬<ó´áÃà*xë k6¥8–{ 1Ùú«3¥J–/tÎ^öJ×4Í~åm·Ù?ïyvýMoêݨind8‹T)M>³°á~Øï~H±Ð¾ãÅ[î8K@]ô'…W:{:¶²W¨`ñº ¨”³©þDqì÷€3Ã+X–6ÉR%Û[ßýÝví¯hËBóZn!»lL:!%µ-f½œ(•J9Õ¯'­–<*ãèå»0"…BÙl{{{ˆÅb€z½ŽP(„íím„B¡¾¯O$0 £í¹ÃÃC<ÿùÏwþà\[þn4#µÓ4x|ØsM<ýñ#ôÃ?Ü÷¼p8 MÓºžF££~dI™—¾ËRÿ†Ã½Ï) Èçó¸þúë[Ojšzx¥Rû©Ãö%²üÌ[ãƒÈçgÿ™s¹Êå2J¥R©À²,är9¤R©¶{@6›hš†xGÇÑukkkH§Ó‡Ã( H¥RØßßGØÕ‰ÃápÛÿ…ÝÝ]uÀ‹2 PŽßÏa£0 †Ñn¦A8ÜÓþøÉ"iÛ²€LØÝmÙ_]W»Ú§~åWðË—±ûÅ/âó·Ý†J¥‚R©M4Y*A×uÄãq„+ RÁ7^óì¾àøV4Š’ü¶…P©¨ß¥RR)àà õf¦ÙÝÈü IE㦩d¶¿?ûÏlš&*• ÀaH§Ó]çüÅÿ8žùïÿ={îsñÏz^ýâ#“LâGGøöõ×㿼ùͨëºs~¶Óî]ö~\R©”sŸ™%©T kkkH¥R-;°À tXšÍ¦#ÞX,†‡zº®£^¯VWW¡iÚ@gµ“ §sÜÿýÎûõ¢Ùlö|§Ÿ~_þò—Q«ÕH$?Éd2ø×¼xÙËfüu“E ÑhàÊ•+xòÉ'gú>ÓÔ7<õÔS¨Õj8uê"‘ˆó¼‡ÝlC×ueŒ …±>Ç$Á£V«áêÕ«3ŸYÚðaqõ¬°, kkkˆF£¨V«Èår¨T*ˆÇã(—Ëø¿o¾+™Lë¦ X–ç`PNìþþ>r¹ Z­ŽðlsbK%`eH§»Ói >*•é9½S¦^¯ãÊ•+¸víÚÌÞc^ö»…‚Ò¶Œ- X[S>¤ú¿…ßü7ÿç>ö1üÙ¹s8÷È#øÌ;Þl6«t¢ëÊãM¥ ¥ÓêoËòyO#0Ä~3? ~ÙïidÆÜ÷«¿Š½_þe¼øo„¦iÝA@ÃP)™loäy€ã}w >ÒV÷¬ª®ë¨ÕjØÙÙÉy-‹¨×ëØÞÞvž“Üy8uê5e,Ãý÷( £GÃ0ð³÷ÜÓZ÷CÈÌSß@kœÚkLÙk½Æ 4­5&'Äͼ5Þ‹aá¦i¢P(@×uD£Q'-WœÓx<>ÚÚ#Y7Ú«_e³*ßíôéVMSý]­z¿Æ0Æïlù¼rTR©é;&¥Ò¦Ï‚EѶ—´ …ÒétïµmÑè|’@³Ÿtv5—Ëá‡î¿zê)ù,77•a|P§ Í$Õ ñÓì=~1 £{ýÞ ²ª„,8•Š·Ãªë:LÓ쟟ɨww[g¸Tn{Fæ‚»&AÛìê46®$Äg$^؉TtïÚKÕ²úê 'Šk(B³Ùl{®^¯#‹-”“ÚÉ qˆ3 ·,¦c‘@Òo ]©Tº ŒšþHÈ‚qpà_tf¢z!Îj瀨†¡¦»r9:¬d.èzkìÒ¦iÎ2‘%À0¼‡Û’Óµ„‰âb Ã‹ÅP¯×jaÍfº®w-Æ–T`ÙtxÑ1 £5ÃJH1 ïÀŒc¦¶•! L¥RA4í]Ahm0,…‚ZãšÍª‚HLÛ%s@ô¦i¶Í‹Ç9ËD–Ã0`†wÀ±\æfðÄa`•àX,†D" ¬®®:û2Éà ÙlâòåËØÚÚB"‘è[ul^hZÛnYLÓDز8!%õÖy×þ«„,å²Ò|§´àc?­U-Zû¢J Úþ>—‹¹bšJã¹\¹}?­­”ñ Ù6µ“žã•qª¸“¥f¨*Áù|š¦¡z\zß]€é¾ûîsªç¡€Å1ý‹D–UAš~‹ YpÒioùz¦{-!$@ôZ‚=•M*¥<áTJ9ª¥U2WÄYzÔ $ÀôËó´ßÑ(·û"m µk(Â… <­®®buuu!fV‡¥\.«ÍˆËeJÈRaG%=·³áˆ˜|¾Û\Kµ÷‰ÓߣQFò‰¯XV{Á%nIF– /3Ýœ)—UàP´Ïñ9q1”à ¨5ª—/_œ={ÖYÃ$GhEãñ$ ¬¬¨É 7ÜΆ,+#¥“0d™*U²Œ¸ Š –eµkkVI†rX‹Å"vvvœÿïìì`}}›››~·dÚô\BL¯|i”â2„ÃhmŸÚþü€ÔIÉ¢a‡Ó4Û5}ú´*MH€ñZ1¨ëzKë¬ÄN0ÔÖ¬®®:Õ¼VWW±³³ÓµÝÍ¢#ûš1"O–ÎåRLÌ3:ÏjØ$ÀôÚ u`FA¥Â,’Ie¦u]o·áœm%KJ[À±×ž7„3Ða•íjÖ××çdfU¶º år¹ÿÆò„]×{Þ57XL³[¾žÁËRNªû…ð“€v̰rÖ‰, ^ÛÀ·9¬^9ĸj†h_« …ün÷XèºN‡•,º®²ÝôMôÚ„€àUa²-ÌM¹ d2Êq¥æI@Œ™®Y'âÉàŽ# mAGΰ’ í°. N±%YEH1Íî,_ë ËŠ×D©çvápkäŸÉpDG— g¥T²tˆì °3† àÄ8¬†a´ß*¦ÛÀâµ…pW±B–€^㘾õJ%õ ÃJ€a¨”É®õ«¬=@–„θKÛ˜œÎ*‚¡·µÙØØèz®X,â¾ûîk{n{{{è7—5°±X¬çñP(4•­sºfŸL“•#ÉL™µ¾x'~3Þ+830›€öLÀ<Ç';ï ¬{‰Ÿ)1/†z¸W䙦٠8ê:uN2Ða=uêT[Á%¡—À‡¡^¯#›Í¢ÑhPëc …‚sÍF£l6ët&MÓP(&ú ]éî]º ™"óÐw§ñïèt’Ëyו'd æiÃãñ!Ö¯V*ªSPãdBüŸ¨¤išÝ…ó™$SfÞ7Œîd]ב•}ÊX[† ÁÀ”àH$‚ÍÍÍ¡ð±±D"Ã0péÒ%$‰–plmm!‰8Çëõ:ŠÅâDÔs†•0/}·ËyÀŒ“aøýµ%bž6<bý*#ôdJø1>‘øy—®£Q:¬dêÌ[ãUޭ㔂0µMF`ä5¬µZ ÅbÑyȶ7£¼¾Ùl:Îm(Âúú:êõ:jµš3« …°ººŠj禓#Ò¶¾ùòdFÌKßþçÀVB¦Ä¼mxg5l ‡ÃÊ`2!þO”_juÖÕH§ˆ!SÅwʺoýBz0ôV]×qñâE'…@ØÙÙéJ'èG,ÃöövÛÖ8‡‡‡TÇ¿Ý׊Åb]ï;\Bfļô}tÔþ˲ú;¬Ì( SbÞ6<—þ^©ÐY%SÁ¯ñ‰Ð,šGfŽïrÓa%ã0Ô k­VC6›Å©S§P(`†ó( 8uêΟ??Ôlk(B"‘pþßh4P,±ººŠH$Ò·S4›ÍžÇž~úi|ùË_ölC×z'Y0BN$FW®\Á“O>9õkÏJßðÔSO¡V«y^£­€9ñÔj5\½zu&מ· ï ì{ÚsôOõzW®\Áµkצz]ÿìwŸ}…ɉCì÷ MƒcpËjrëºÞZ«Í;N2Õ~å°nmmAÓ4loow ŠÝÏomm ýÆÍfÅbwÝu‰.\¸à<ß‹~îé§ŸÆc=†Ë—/w3M³=Wž—N4‡‡‡3sX…iëPžË—/;P7æ T¦ Ÿ(._¾<“ÁŽ›yÙðNSÝ•Ì çO³rX…yÛïÝÝû “‰ØïYé˜ïÜMWÔ\ŽH' ƒªï)Áüßø¾ç­¯¯ãüùó¨×ëSƒëõ:¶¶¶ …pÿý÷w¥ô¢_ií›nº ñxܳðS×ì“kq99yHtqa—Yèn¾ùæžúæúUâfssÓ©ð8 æeÃM³»`‡gÅwxN24 >oû ´ .uͰ–ˬ zû=-“¼˜÷¼TjýÝ–IP.3Øxw >p†U:Í Ž#"&ªŸÍf<úÎÎqêÔ)hKKh4uÜ®5Oá08dfÌ[ßmÅ™óÒ¸a¨zJ­ÿw êY˜L™ùÛoàçþOºgW C¥K2eæ­ñÎõ«N:°®3 C†f Ã …¦š– ë:4MC­Vk{*‚“H$°··×öšd29ö{.Å ”  <á5*¸T`¦ø¡o]×oiÃA=™óÔ¸a´g³w­óûÿ·ww¡q¥÷Ǧ-}¢ÄÙ—Œ–¤J 9wEÚx`h £«b´¥D`]Ùd`z‘ƒ.r%è]Dì›È «lÈEâKz•qrJ)ÅgÙ')ÕYCp:xL¶lhª^œ9ó®y;ï¾+Ï3£óŒö?Îÿy]YaÃ%D&öûäDzôè|¸óØ$Á4µjµ:VætÏê¨ÕjªV«½í· …‚nÞ¼¹ô›Ì}²*IŽ$[Ò²Q-I’ÊÝïƒ_É=Iw$mIº;ÇÏqº¯e€z¢4â{æÁüQ@d’ŽñÁÐvgè¼@âQJ£ýÞÚ’¾ÿýÒÖÖ¿¦ýöq $ã÷îõÛð“““~Ç Óݱ ¹V˲T¯×Ƕ‹·K¥ÒÌõ«µZíÂuƒ×|ðàAïƒ5¸£Ù¢ÆFŸ‚Ïò6%x«ûµ¬ùÉÍî÷·ä'¯Oå'­·5œ´Þ‘?*û¾¤î¿íî÷ó$·—PÒñ-1%ÉJ2Ægxuâ:? "i´ßRK_ûÚ_Ž?lÛù»OAæ%ãår?augxwà÷ßOû×™k—àÝÝ]yž§íímžžöæ¶{ž§ÓÓSmooË󼙂E[o‡ýcà8ÎðÁ÷îùwAy28÷D~Ò<~[~"9-d4èÌz4ð3÷å'±ûÝçÜVêñ¾üdvcàß?ï¾ö`ä·»¯tÒý˜¨â[š° 6QÅxŸÎœI$$Êöû;ßùøâN:g’¨b|0aí¿cC{ŽÌa•ú 7‰G×”J%Õjµ™£«ih·ÛÃkC‚Ö< Ⱥüé¸ÁHè;ê”Jþhé¦üÄrp4ö ûX`¥û³4òØ£îµfäÞí^gCþcu_s¢~r{»[Ÿv÷‹™±à&&ì[dt&úÑþZÿüÏ•v5€XËT‡îUZ-öÀÂæJX¥~Òêyž\×í_cYVl[oGÁqÝœ'ßjEßkiüwKýÄ-’7¡~¹ÑýzGý©º5ùIgp“gË}-«ŸXN3)‘½èyAÒº/?¼Æmõàv÷yR r«[ïœõdÑ\7ñ¶í÷d’Ø"gö:ÚÆf˼óŽDI,rìÿþïZ[û›ñ‚Ñùð@½óŽôôéȆyì«%̰‚#nFw´ët:r]7’)2Qºp‡àÍ—œÍâÈY\øº-?Y[&!»'?ñ ªÜV££À´õ£kÏ-˟‡ Iÿ}AY0ÍXê'®GSÈ–Ÿ´Žº:ž¶Œ¹8óLo·íáy9@N ö5ŽÍ–a‡IäÜñ±«Bá÷?øFÎ ®_e† ˜k ë<\׸ëXÚÖ†·˜ô§·4œ@Í2é¹wä'XÁDûòà[òGXוNË)îHz«û}[ýÝ|' ·ÙRV&ü;xkêʪû^ß’Ÿ¨ÛòGŽ×ìëo1ÑØM<`ˆvÛŸ»á¡9÷ÑGÿ«¿ø‹óÉ…¥]= ”`r—DŠð"KX³hl‡àà\³`êì¨{š|VéÆÏ@\¯9ª®þèí¦úÝëþû@þ(ìWºu 6? FPmå3a]D0 |Wþç²ü6è$X‘ŸÄv8ßôé’r‡5¬0’mû{ä†6cUàßÿýôçþ›´«Ä¢Ýî7ÓÎvædtÂ:¶{ê`w­ñ$ôžüdut×Ý÷5ž4Îêü >—ûê¯?½%?‘mwÞS OŸ{Ý2“;¥FßÛ-ù¿ÛµòŸ<ï-ùÉj[~¿ÈH¹æÚt)o»bòov‚É㜛äÜþgG–õÇiWˆ…ãøÍôP²Új ÷DsZx kžŒOÙnûŸž 1I­ËO$¿"?Y FQ'͸œ÷^i4!›w$ixàËdôw;˜Ð®ÉÝRƒ§²üÿòÿß;*·ÔßùØäÄ”mû_’ÿ‚iÃÈ™Áõ«L'ƒ‰^{íLÿ÷…ð?Ȩµµ‘öÛq†×zs2>aÝÜe¯\ö¿‚ã`F§•O½«þ±,A‚äÈO|öåÀNÛøÉF_[ê'¹u OëF©ï¨?²Ý–ÞüäMýêõ_¥ýB™:¸x%S'‘{c;sÃ|éK?ÒÄ5?ív¿ƒÈ©µ5ÿVäà`$a¥óK˜™°º®«F£1óu:´ß˘±Ö ymË‘»=ðd[ývËò“ž[êîm¨?˜ûÿlý›>ø÷?Ñ®«?Úº!uV;zñÛi×<”©ÓWVUE®mnö÷™xž67óȱv[ú·ûݽ;¡v†Ìà¹N@γd†Ž—ä V,)²5¬…B!sGÚ\(èœßPÚ“Ç%uô3ŒÊòY˧`‡â-éÅ×^è³?û,í…2¶©`™;ÓKsé׿þÛÉ…Ì €‚í3ÆÖ°Òvc 3GX-ËÒááaÚõ\ØØ²@[ý¹5õ¦±5{šï­ç)›kÃ% §C{l½[—qq?LÒnK¿þõO%ýÃx!7õȹVKºsGÚßgÿDcæk³Ù ¶N§£f³™vݧj·Û~½ïÜÞ%u0á,ËULb§Y‘¿c0cSÞïÜa÷=ap€‰Ž˜hkKzûíÿ˜\ÈÞȹ`—÷¡½6‚mƒ%,5%øþýûªV«i×}ªÞtÉÑÞƒ3m6äOïeÔ946êtrÂÚap€‰‚a¢Ÿüä¿..dgwäÜÆ†T¯û÷)½ýHX‚±ç°özåGׂðHý3Nƒ —€Yž3éÿ! Wh9váò Çþñ¯^ÜÃVbh„•Ž„`lÂÚëÕ;l^ûüž¨Þ*c.œð‡Æh·Ofjߨ,þCŒh·¥7ÞøŸÉ…ì€ ܾÝ? ¾w¯²¿Ï} ––zÂ:m-¬ëºòùä“áäûûÃ76¶$:x.=Ïóôá‡ê7¿ùM*׾ȴø–¤ßþö·j6›ò£FoæV˲dY–Æ…Û]w:5 •J¥©;Œ%oMº“v€°9.«;4êÈ7ÇqÆVÛfý*Œ1´¤ƒŽD`®cmvwwU­Vµ½½­J¥2””>~ü¸·8{ww7í÷Ó×jùGÙ0c&bý* 64lT°™ccS‚WVHXaö @”æJX-ËÒññ±ŽŽŽÔh4ÆÊ+•Švvv²s4G0ú´!¦ÃLLƒÁ.<ÒFâ¦fÚßO»@dZ­Öä°%Í•°Jþ.À»»»cÒ[–ÙºÕÈ8ŽŸ°²~¦r΢„±VVV´Å†b0Ô£GÒ®«v»íÏ"h·ýÙ@Hs'¬H6‹IŸ~Qº-éçiWˆÁÖ`¬ w¢d–ã8~ÇúÁ›.! '¬¹P.K*K’vE€˜p¦.£`ö ³666¤“–p 23w Î-[÷5`fÀ$o½ÅÌ¥Õjùߨ6gÅ#2æ&¬Ž$:v@7ötÂÀ ­VK›_ùŠÿb17am‰V0ÉÚSÌ`Žƒ–wÀ8ív[ù«_1ºŠH™™°²;0˜‡„¦h·ý5Ù$¬0ÌÆÆ†þî÷¿§­F¤ÌÜtIb:0Ȧƒnèa¤µµ5º;gÅ#Bf&¬b„dÓɉôsÎ݃Ø103aÈ¢{÷üz6¤‰66]EäÌ\à 0Ï;i×϶¥z=íZñX[ã¼lDބޓv €ðö÷¹¡€d>au]Wžç¥] Ä7LYŒÛvÿÜJ #–Šo’Uä÷(ÈŠÌ®aõÑǬ+W®¨V«%~ýeâ[’ž>}ª½ñƹ‹•<ƉäÇʳgÏr÷‡Úqýò—¿Líú´áù‘ÇÏæG}¤gÏžésŸû\*×_&¾i¿“—÷ö;­¶ö;?òøÙ îÁm¿3™°v: Ë^¾|9ñÃbY–¾þõ¯ëÍ7ßÔW¿úÕ´ßÂB …‚®^½ª«W¯¦]•…ýîw¿Óµk×Ò®ÆBž?®7ÞxCW®\IåúËÄ·$½ýöÛúò—¿œËXÉcœH~¬<þ<—mʾð…Ô®Ožyül¾þúëzöì™>ÿùϧrýeâ›ö;yyo¿_ýõT®Oûyül÷à‹¶ß™LX§!Œ*‹___×úúzÚU_J©TJ» —²îiY&¾%é»ßýnÚU_q’¬´ß´áù‘Ǻ§]çeâ›öóJû÷Mûy®û¢2¹†uuuUÒð´Ïó¦ÞÌyA|ÃtÄ8LF|ÃdÄ7²(“ k±XT©TZ,oÛ¶677Ó®ñ Óã0ñ “ßÈ¢+ççççiWb×uU­VU,{‹¼/\ßä ñ Óã0ñ “ßÈšÌ&¬’¿ð;Øjú2ÍÓÆå@|ÃtÄ8LF|ÃdÄ7²$Ó +àòÊäÖ¼r]wêáîëN=ßjZù¬×Fù¢¬w’uG¼âŒïyÊ£zQ×ø6G˜75¾“ª;âEûM|›Žö;½º'â¡=yòäüúõëçëëëçëëëçׯ_?òäI¯üìììü[ßúV¯ü½÷Þzý´òY¯Ò÷¾÷½óoûÛ‘Ô;éº#>qÆ÷<åQï°u#¾Í&ÆMï$ëŽøÐ~§_wÄ‹öûrÄ7#¬¨V«*•JrG|ðJ¥’êõz¯|ooOÅb±WÆ\å³^•f³©£££¡ÇÂÔ;ɺ#^qÆ÷<åQ˜ßaëF|›#LŒ›ßIÕñ¢ý&¾MGû}Iâ;íŒ9ï~úÓŸž¯¯¯Ÿ¿xñ¢÷ØÙÙÙùúúúù“'O†¾üà?8¿~ýúØsGËg½6*/^¼8ÿÆ7¾qþÞ{ïõzxÂÔ{žräCœñ=Oy&Åwغßæã¦ÆwRuG¼h¿‰oÓÑ~_žøf„5$˲ƶú>;;“$ …Þ÷–e ½&˜O>­|Ök£²··§J¥Ò;,zV½¢(G>Äßó”GaR|‡­ñmŽ01nj|'UwÄ‹ö›ø6í÷å‰oÖ …ÂÐvßžç©Ñh¨R©¨X,N ŽN§3µüéÓ§S_…ÓÓSyž§Z­6ôx˜zÏSŽ|ˆ3¾“ˆ“‹â;x/ËÖ-‰Ï&’&ÆgÅA^ã›6Ü ´ßéÕÉ ýN§îi aH§ÓQ£ÑÐ7T*•´»»Û{ü"/_¾œZþüùó©¯ Ëó<õê:ú~–­÷<åÈ—8â;î8™ßaë÷gÉ[&ÆgÅA^ã›6Ü,´ßÉÖÉ£ýN®îi!a€ëºªV«r]WÇÇÇC½%ƒÃñ£ŠÅâÔòi5‹ÅÐõ>==U¡PmÛj4r]Wgggj4zõÕW—®÷<åȸâ;î8™ßžçeú³‰d-ã³â ¯ñMnÚïäëŽdÑ~'[÷´°F ^¯÷æÑI0/}pxÞó¼^ÀL+ŸõÚ°®]»váöµ×^[ºÞó”#?âŠïyÊØßaëF|›eÙ75¾ã®;’CûM|›Žö;Ùº§…„5$Û¶åyžÊå²šÍæÐ—ä÷d”J%žž½fsssfù¬×†U*•T«Õz_–eiuuUµZMK×{žräCœñ=OyÓâ»X,fú³‰ä„‰qSã;îº#´ßÄ·éh¿/O|_9???O»yÖh4&žŸ$IŽãHêOW(‹êt:* C»šM+Ÿõڨߋëº:<< ]ïyÊ‘}qÇ÷<åQ¾—Áø[7âÛ acÜÔøN²îˆíw6êŽøÐ~§_÷¤°&¤ÓéÈu]I“çÍO+ŸõÚ¬Ö;íº#9yŽ“¼~6‘¬0q×øN»îHFžc$ÏuGrh¿óß$¬€Lb + “HX™D È$V@&‘°2‰„I$¬ˆT³ÙT§ÓI»@lˆq˜Œø†Éˆo˜Ìäø&aE¤ªÕjïbÀDÄ8LF|ÃdÄ7Lfr|“°2‰„5AÁP½çy:==•mÛ½2×uutt[ÏHpíN§#Û¶eÛv"Ó<Ï3zІ¥ãiÅ·DŒ_&´á0í7LFûo˜v.“jµªJ¥"Û¶eY–šÍ¦J¥’ŠÅ¢šÍ¦ …‚†vvvT«Õ"¿v­VÓýû÷eYVïCy||¬b±Ëûu]WÕjUårY¥R)öß/Ò—VŒ§ß1~ÙІÃd´ß0íw¾1š°f³©èððPµZMÍfS’ôðáC«\.ÇÖÃsÿþ}êððP<Ð+¯¼¢ÓÓÓX®5øAÙÝÝí÷‰ìI+Æ“Œo‰¿¬hÃa2Úo˜Œö;¿aMØææ¦ …‚$ɲ,IR¹\®®Ný°S.R©T.ì­©T*½k ­®®Ær×uuÿþ}]»v͘ æ&Æóß1~™¥ßA9m8âDû “qž_Œ°"rFC¯¼òŠ?~lļy`1“ß0ñ “™ߌ°æL±XŒ|n}ÔשT*ªÕjúæ7¿©F£aT╇ø–ˆq,'©ø{-âË ý†éòã¦Æ7 kθ®«F£qay­VëM9Hë:årY…BA»»»ª×ëÆ,øFüòß1Žå$ßa¯E|c´ß0]bÜÔø&aÍ™b±¨›7oN-ÏÊu‚ÉÞÞž>|˜ü/ ¹“§ø–ˆq,&©øŽêZÄ7Aû Óå)ÆM‹oÖœ) ‰ô”DuÝÝ]ݸqCF#±©pȯ¼Å·DŒc~IÅw”×"¾1/Úo˜.o1nR|_9???O»Œb—`@&‘°2‰„I$¬€L"ad + “HX™ôÿû4²/¨$JP%tEXtdate:create2019-03-28T17:36:49-05:00T¾=@%tEXtdate:modify2019-03-28T17:36:49-05:00%ã…ü-tEXticc:copyrightCopyright Artifex Software 2011ºÅ´1tEXticc:descriptionArtifex Software sRGB ICC Profile †2tEXticc:manufacturerArtifex Software sRGB ICC Profile\~=Ÿ+tEXticc:modelArtifex Software sRGB ICC Profile1(‚¡!tEXtpdf:HiResBoundingBox1080x792+0+0_Ýx+tEXtpdf:VersionPDF-1.4 G:xIEND®B`‚blis-0.9.0/docs/graphs/large/l3_perf_has_jc4ic3jr2_nt24.pdf000066400000000000000000001045671422157504600233060ustar00rootroot00000000000000%PDF-1.4 %ª«¬­ 1 0 obj << /Producer (Apache FOP Version 2.3.0-SNAPSHOT: PDFDocumentGraphics2D) /CreationDate (D:20190328153323-05'00') >> endobj 2 0 obj << /Length 3 0 R /Filter /FlateDecode >> stream xœÌ½KÏ%É‘¸¯_‘ËÑ¢.ýýXÌB ˆ„4Ø#˜… UÍžiU·Tl` ýzcæááæ~™Y_#ÁêGÞûùð—ùq{ÛÿøÎrøŸïùOíáÓüν|Èò×ûþü?¾+/ßñ‡P›ü_sK¹~ò)}ŠEžÅßüÎÇÔñá¿éï¼Çgw`Ó?~÷ÿ|÷ÏèýOøþùÛýãŸ~øôßýß?¯Ç¿Þ|ÍŸBÌLA>ý7ùT g‚Fùðßýìcù0íOßýçÿ‚ý×ï§ÿ€þþ?4•”[ŒŸþÿï¼ûôßöýû‡úÁ4~¼'öD/!ÖW ׌îoñ£sηøPÇxûkö;¿<Þí5CYÙùÿ”Þ{óõÙÙê~ŽÏG§¿úµÿäË‹gûÿ€!èûÿô™¡Ÿñ¥¤äÍ¡½Z¬±…$èðw¸!ãûà_|úßþóÿÁ5þ7Ÿþ˧?ü‡ïþÝdº_ì+8^=Ä’ªÏé«}=uçÁdÇaø<®³)7< 3ÁùW«g§ãÏÏuìK{ýŽ¿>ØmÌrî÷~ÇŸìgèìVþø<ÕºW è±ä'ÉI:œäd;}”œØñ$'Óï£ä$ÝNr²ý>JNÒñ 'Û­!§/ß!¾ãÕ-´†¡â·áåq½ÕÖÁ¬ Lÿèåa; —\+1;Ü$ÇÝ®NÂ/ëÅ5ÜB©õâßÝP³—ô‹zi8ÈÑû\ù\wåõQª¹Š+>öö™NšéDx‰öÂemy‰ïÝËÉð÷w‡ËHÖ_xÝ+µp†Â'àÕ+å˜c ñHÁ?YGò›_ÿöwÿû_ýñ_~úáÒÊÞ|vjê¯â‘¡JŒ¡¯Õ÷xîe$·ñ}Ò¾ÿü§~üñãì†=sî/BxŠ1•˜€¡Xš˜KŽ¥ÒAn¥¢-”ö)xÿ ®ä¦xç[Ʃ’&®)¨Si­t‘VÞIÉ.O¶ƒ·ª©±­ãýu²\îÕ#zv1JÞɱààj@†Ø"´É;;ÞÙØ_k8nõ•žlMáÊ¡xPŽéå †’„߯ÌxeÍ…§ô•c#;Þ¤ ¯äPb—ÇpsåÐCb&[^™)Ò¹F°¼ ªkƒ£÷3¨àY›×ç@Ÿþºñ\ ÍûÉ|­JÊXÏeÇS9É;˜ÞkÁ|Åû{jÙëcx%‡°µ8–/ôÔp6¥;ÐIå5‚!‚(šoÝK^É¡d¤ÍÕÐKÍÒ]Ä;¹A8‡h‹¯’}ì E¶%\iJtYÚÀ‰gì–¬XÂ;ç’a,Õ‘–’Œ%ñh²¿å9,sÂ;¥-ãÜ¡9–ðat~ïäXb)Ò–zr˜`¶F®›',b@sücÁË.Šõ>dJ…Éà ^vQ,_LÆ›½¶áeXÖ'í±à©cØ8jØš$ÐÇ2Få¢ 5¿qéc$”\‘yáðdîMËŠ{U@4Þ!ïÄái“`]Ǿ¶RÔ6¼sR,žK¸?°EÚðÎI±è¯dW[î&àð´¹üµÒb‘EÄÉ \\t¼&^¸†"èOŽNN®×MЧ ·Zé5âèt ÄǤÏe¬WèN”8:ƒ_ë;È:Ä mí58› 2µ$‹ýê“^j-ØÐØ¥ ¯œôŠ5)#ÏN^‰Q&½òý1„e"ŽNçšøT䜢Ðvé䕵ëX\Å ýàôî0½Tx{âì€ÈR•cqv:öÃàsç–[Òµ-ãä^ôŠþŒ%w°ˆ³S&½ò­×ÓP×ð× Ìœu§6›¤ØÿŸfšËÛaÃí¶ߘp@r>a'?y<ëãÛ§4äØlãbÌ 8ô:`»aŽK\K9`[È7‚Ôó Û)á„T¢?p;Ù€O5° Ô)íô€¬°OFØFo ø‘¾°yDðÿ±¯l'àa‰ó–0°çbm¸{rØaÝápÐF8`;ñLZ(l§ðŠNn¥¶c²Äj¶¶#n¬ê-í@mðÎx M¾¿a‚ÊfXÐÆZªà üÚ‘d^cjºú´9_A€6Ú°ƒ1W%ÚXSÀ= çp‡M”” hã9àlÁ©k;hc±‚ ÒØÆìj&» ;j`;ò4†Rñl“*œÞ¨lsêbr‡mv‡ë¯Ýa«)g=µpÀ66¬;†îÒÛx'®unD9`Cé.#K>`ÏQ>¨øõÛ|'_n‚ ¶yŒµ±Ž¶¶1pœþÚø]ÂýîÞ.IGŽF¬EÿŒ°í'l·OñSø?‚ÜxÀí…7 7ÚÀ±áž«r;²–¼Kß‘;@XÆ`dQ6ä/ù”â ܹ=ÓüÜ¡±ÈdýëÜàïвg ƒÜ\uHZ)ÂŽÜ8¡¼°ÈþÈÉ­–Žñ•¹#Þ:@8È °5Ë”Q7ÈM0«$ܶ7(*Ü“^ù=Ü€-ЇAoÁ ¸! ` Úĸq#»N¼(¬àÎ$5Ý» ¹I™Ø*—ó‰ÜØHEs 7V ìP<ǹq1ežÈ¨S·È_¹`JiAn¼ Dˆ³ ¬žEnÜx+8A݃Ü1`ΉÛÝäÎ(lb: `_³þ ºÑNó¯tc’ #ÁKû Ý8uØ Î ÝŽ”(ÐÐݰ¹ã”È«‚Fª*èYävœ®ƒz7£+®ö¸q÷dL¿)³j;ð9pf9ïÀ ¢ d•UÎ;€$‰KPäµ ¸kYÜÆ(ñZ‡OÜÆ;0mð<íÄm*VJÃ5XÜÆ¶V068BåÄíü¢Êº¸—t0C”9àÞÞ)ÀØŽ^çç«%!pCx©88 ìƒåæYŸÍs€³Vœ Ö2Ü =œePè©&Á’x^de@ó ÛŽqŒ«Rƒ…m´,%àð„mkxÊÈlp3q´­z^<°Ýئ¬$ȹ1°Ë¬€h›“EÙô$ ïŒôœØ`Ñä”ú¬žC)µ 9[ÔÆCoÃFµµÑVÀKø$lϦ%ÁD=ÕŠ|VKB;dǪ“³ZRät)Ú\¬NQ®gS’t –ÊÚÔ9á Ï1½Q’t^Õü ÚØêDåjÕõµ:HÙ]µl‡Ž’;Nf­hCJNÒí$'Ûï£ä$r²Ý~Ì=Â-œ”Êcî1¶“§Ücl/O¹Ç˜^r1}|•{̼O¢Ø’[l›ò¼OÜê}òçÿùœ÷Iì›2ÂZ§€ÞÌ­ºpÚg]¯$r\¢¶bŠ©bÉ­ÍOÔVL1rs* â°ˆ†‰êŠ)¦&Ê/ J‘(µ·Ure].ÉßÌ—v­Üå•Á(UhÒö`—Ä= ã|Bm/TkKÛ¢TÁc„ëTØOÔWL)Õ×W--ç$ —$Ö—iÌOTBõ¦æÁD}ÅSéER UŸKxç-¦znÔ¦öÛ”V¥J¢ƒƒÃÕ•¥É8Ÿ$Q”GÕW¤lœOÒË7W][ÊF­B}X¤ .ÃÌxç”S±#¹æ\¼¨óSÁ;§œJG ˆÙ‹:?Qo1åTHÚ8Q¥©U{üJSN¥ƒ €1'¹R5Î'žN2€N1;à«^…ú+Ì.‹dŸª*VDréà›Q¬Ä½AÆ–iF±ñu^Û6çîSò¢³KÝ(V0±ŒµU{}êÆûÄaß|]Èžv£Xdç*dgg+8Ð5`Ûš¶mÞ'%•R³îÙÅJxa­²KBÎø…U¬`àØhyÌoþ'E§ªÑ­äºª8”¨}çrfê,¼8Ä©#IƯ‚:åä°ùŸtGÈè”(‹è(ópú¨S'™ãæ€RA˜Žè¨ÌÆXB¢ÎˆÕବJÜT+•¯$d™i¿ÇP‚ïUÕ.@õ>Ã^YÕ ¦„  ‚3½ªV€a!ÓJ.m8>'Ù¥ªê“6rÞ+ø…’ àðДM ¾´yR2Ðh(@D×’°Ó^÷”ûɆÛ4ZávÇ>í¸M&nžÜÛT¡·’bLBy·ÈëC>a'¢F^”¢I³¸ÝÝ‹ÆMìö‰Û-¡;]º·[' äDóhq[|éÿsâv«¢X­øß·›*éZ-n7:ÐC|#,n7*ÃqŠ‚¬Ám<“6ê¶ãvÃ}žjÅ n7pxx½¸ç2•z¥Ô·Ñæ°­‰ÔâvshpÜn4‡ÕBO’·+p«!Ðâ68«P¡vøÀm€1†Í-lWZ20Ju°ÍÓŒû´)¬YØŽ¸6kLN-lÇ‚õh´0·¶¥ $©ËÑ7÷“NÖª·µ)àfÄ%WÔŽÂׄ’Ä eQ›‘\`eIOjczôÀ’ÙQ›ž:¸nƒZ* j£ ûÁˆÇµÑÈðdq±¨M·zg)YÔÆj’­÷ºÛµ#SâÁÔ¦oG÷êþgQ›ÏáåÕ×µÑ.Ü4¬¾µÅ¬VD-»µñ\É‘ìD=P›ïu¥NÔÆP NÒ‚ÛÔF„à@=pm¼¬¢ÚÞ,n {Iš—C %ø§L—­ð1Íç‡Í˜º=ŽŽî'}Çn¢[#«Ñm Ïsë2=”õ<ž›¢iƒpѪ?ynáJ}ì'vË‚Õb‰vÓ»Ëѧ¥÷»!­DÂnüøÎs†èõc7„ ‚Äq8±;ð…@Vä^µØ¶HHZ±Ø—xÊ 9…»ÑŸ¸®©‘Ð`7_éxeçz`w pÃ7Ôv`·2€†‚òê»1U<VV¯&ƒÝx»ì¼Új,vÓú^ºHêvª°(ø¶»9N¼,Z:°;0ìbJIùoÎ=Ò~ðêÞxÀµ(·ËÞÄŠfêr`Ám!ʆŸàM+W‰à!ßðÜÜ› >ªŠ»›Eoй¯ÒÄËÝ¢7CêNä/‹ÞŒ'¸›ÛÞVKj ™½Ñ_“«)èÍ&ˆz¡Ÿ,wèX”·±Ø"]Zð]¹qƒÝî³¥ú.·ÿ†ÝáEïߦ’ Ån 嵐ùHV¥ #Y°*c²qïŒ]÷^Íøý­TASöet(ySªTÆóªB²£T‘\M£µj1:'QÎQmk1JG>(9 !Än,JÄ\©á‘¶U©B„Ò\Žº*UÄm¢ðص¡ý=KOõ!9öƒvÌ´_ ¼µl¶àÂY³%ì­¦ Y> fKäIDkÒ3˜ÍkÂh­æ†Ù¼ô#Ál¶Ñ 5¢9 fwZ´ã¥´˜ÍÎÊØIî`1»1Ü!´J:@W-3&¸Ñ´bv%4€1îîÄìÒ!Ü*ñ´µ‹¯º×3 ]Ê‹A‚^Ãe,h%;Ƽ MÂŽ¸#šc ÚÅ1úÛ—ú´3íZØ+U©ZÐδ•ÑJãNÐf8#úëšäÁ‚v¦½Ø¹¦Ñ(´y©2¶SS}XÐÎ Åbz½p´Så‡õk—íDEkêUÃl,j'æ‚ñœ¶?P;I¢€ÅÍj3þ4RŬ'Ø 6C&.…¶¼†3šâ“íÄ(4—ýÀѶ1€¨F¾mºg%:Ÿ+vØFwŒF‹YØNŒ„ª=ºµÑDëíA·¨$¾Ó jó9‰rÌù@íDzº,¿µ±b¸x„µÑ7Ž.N\?@;ÑQËœõ¾2 Í=ðœ{ 6FrÆÙOÔf€g ÈNÔf ,a̾¨Í0·D6V™ƒÚITá•2Ê…Ú)Ü¡{Z1-p“ŸðÈæw䯢aq4¹‘AnºS€•Ó©(k¸íÂ|ed*±ÌvaÒ*\ŪٵÌv&¥”Ö•Ö-³íÉ0ì°ã6vŽQ€N=6^;“ÈLô“×&÷¤AίMóEˆ mãµøÆ\Pz+Y^…­$<œÜ6¸æ’˜w À-™Ã:Oo:¹m„ÁkD½CVàcQÙK˜ÚÆmCàáñ*ÔXn[$@oʓێ´¼'&“9¹mrÍàE”ï·Ì6Ú3,ùäµ x6‰]ñàµé±BÖì†m04H~ ¯ ªe\üblܘmz ‚)Hz¤,³6HÕ¹ö¶Ñ†“)íÞñÚ‰–ºÔËÉl’.wxÇl¯\³a¶FRKˆoxm¹—ó‘Ksãµ1qì åö“×fl:°2ªH°óÚ]ÃÝýÉk»5ŸŠEm2f™¬¶bžåµ=mДyÚÚ¤;·@ç²£6Y{\VAƒ­7^|†£w{ÇjG ¤zƒÚlË…Î`oym`ÄĹñÚL \ðî ¯‹âÐßòÚ„û®+Ýôç5CR.é«,˜M2J<5>ÊàËGárØü  ómïOè,Ç<~\¦öH7 šÖÄûÛãæDpä·s~y¼Ûk†²´óËãVÌ1Aéõúü5VÌ\$¦œ>Ù5jxj# œêZl¿ž¤ãax²Ý>hÇ\è¶SEó¼!S{œe{}6¾sþ¦(Óñ³9ð¥ßIR¶ãg“à«ÁNiÊöû1c&þD~¯å vý1kæÖËSæÌ­›§ì™¶›‡ š¶“',š¹É”)Ž~Á¢YW‹æ¿þô\pfÓ”Ÿ·r¼;¦‚–³Mô Ó¢iídÊQr‰-¥Õ¤ÉŒj°€]Ku5iª8ÅØ¶e·hYZzÑãSD2¶¥Õ¤)ùg#Ä/mu5izILª¨ Zq‹š…I˜g:Hx«š¥Bœbæ7A¨†5 µ?öœØ-‰áŽš ÿwi¾‰2µÕ´êY-3=j"0ˆ{VÏÒ‚£ &ciκŠÚU»Ü°ƪ‰õËISsV_qVΩ9ªz³u·èYxÊcOE$ëiÕ³à±P!íŠtÚz]õ,Ôÿä‚W² ²üªg¡pïq&d‡@«ž%¼h®ê-ésuQ´PeÐd}c÷n ÏìTr@Å  ü*¹25WÓh«Îf*êrôB *†©hñG:²ÎÄðwt&sV»”Џ wª©hñ™Òsìj éÑ­Ñ™•Êý“hZðæ5:“Ñ`®3šBÚê¢igm@S‘(¾žÜ‰3 `qªçêÌ#|Q,Ó½×¼"]‚3©Žo¤ic*ýI±ž19!´&ŠË¢jaŽªÄÀ`¡®..SÕ’(Êtý2uj:'Åz¨ 5ãÔÚ¼WÄ•4ª¶—º¨Zlv+ÌËf¾ª”.ÚÒŽÃs[5é™BsJ”Íîxb²GÈ@d ªZT-Ì/VµÒ2;¢ÈOÌ4^À…(V<üqQµà¹x§‹ÅpWU ´3†©j[ZU-€ZTï Ìy ϳfÂoâ¥á»Bö]- O™57äfEˆŒÌSº#wdµ â‰ÜÔl:ÚÍDfOH¹oâÄb;HIŸs “An/VUr¸ÊJ 8üynT†0øšå´à–L¸ø¡×À¸™ òùRÜÌoâöÀÝy 278À-C0ÊÔÛÜÜ}ÜÁÇt7¸¹ÚSñâ®aq»g|‰ wà6nHPz[©ÅíîÖdË·9Œ9±à[ÜÆH˜dÚkx¼ÅíΰNVº¹Åíî‰ayœ,Û¡¼Ôǵ&ÇÀô¢KQ»Qy™—ØfÔƒ\lj2°Ýè•qà$’ÈÂvn8‰DÛLÁtwêvaa;Kú_Ð’0(¶³¤‰±×µs§å*ybP_"ïq­°¨MmrMhr¢vŽ/°RQ3SZÐÆï€’9%½O hg†³vчXÐæPÐ’Õ9Á‚v¦±Áó€ø´ÑƼ—Aó [ÐÎUlÚHµnP›á7ç!êP jÓ¾ÝAxzö-j3õ%ÈB=P›z{¾´¤v 6‡É¯®KfPÜ^ÇNaå@mt±\’ eGm1eã¢neê±¹üL†îÚDzƒÜ®i‘›¦:føšäÆA¢ûš÷'r‹Ñ™”-rËÀ(ßiYn¦ñ§3`=9nÆ{2£µJËq—Ìk•)œÛÎq–Î`E„¸é_ÁRµH¼§å¸™&—°g€›ùÆÎÞúÉq'n¢ -sc[R¯6ß5Žß7Ýt±Š1Å7 °¼ûàÆWä¦{FH’ørGnFh빋ŒóMcÞܱ¿hÉËêCe‘;1à³\qùñNnIvb¸µÈÍš 3-©EnˆuŒ…oj³ÐÍpV‰ëvþ†nÆ ­Ìßýößÿþ17óB6™£¢&»F@/XãÔèùBæÁÒUÛ6u˜*ów³z‹cžé¿4Õßý÷þùï~ûo?>Ý:jšiƒVÀÆ\¤LöÚö5ÓŽŒnb9ÈþÒ´ÿÝÿû§þù«æüA7§uÚL‚Vè%ã±Û¦ík¦Í| @î˜ý¡Ôœ³þÿ×o¿‚¬ÙœŽ>¼µ÷9¯m_á·àq6.s¢®ê¸ÀZtíOV]Ûÿ3&Š|ù.ÌÙ=Ò÷«óÂòõq7út½–žë·ò_˜“Ôõß÷`¸æ8ú­Á‡áÃةס$](„?ìÑP™…išcAþ†<Ö³9aà‘]¼NþãgÓÌH*ꑳÌOÃÎRˆÝvû°:/Ž ¶ç‡íÐyumØz~Øo熭ã'½V f\Øÿ\Ü£„%]Þ„e»}–°Ôü",Óó³„5sÉ…7=?KXZÕe–íøc.IE ±6=Wš}ëå)‡­›§\l7¹8ØNžpq æUC tjø¼‡CZýþü\ésat˜p;K¢‰ÞÃ1L× ~–«w.ÇêµÂ.5MÂ)XÜs1”±†’ó5x?ƒè5cqâ½îñz)ì%Õ¯™™³2pPXhL’/Š'>Ž%ºÜh\•®©KnN_µË¶º9$fÇËETµhÂ;Á.å–G"ÇÌÀùë¹UëÊ*œµ¥`ÇÈ·ÕÑ!ºs]u+=IRÐë†Rem yÒ±d¦féy§Õx?°D¨»-£Ñ¸?0B…I´³³ÇN:– WµÍé™É¶OB–'A¶Z@Ñ‹‡ÒíAÚÑ—N³<$}µ6R×9)Ù1Vˆq´Úe_T²L«IÝ¥O:Ö¾êdù\fRY1ñbBNÊ)!SOôÂlÚ˜^q2ëùȲŸ£qUË2™6Ë5p׿êeñËÆ«§èF©w2ž”ú_QêxzZ¨Ê$d&¿Î…ñôýR²Èűþ˜þæCªÃæ£àqbÑ´æç×]a¬ÌS8e¸­êÜ-ÌÓéUT» Y˜ç2…VÕc‡y.p‘énàõ ó|?@…¸ã<¤Á[ê ’ˆœ£Ñm4@Oe!ÓºÆq@ Ћ‹FfšÌ '‘óÚHËŠ{«KÔI-K}´Þ<ê{[ËÞnPO—Ú Ê„é.r»\mH¯>$åz"=M¤ÀM0…ñDzØDI7¤ÏÚpzYæòDzšùRxÐ ³ *hì зÆBÝxK‹ ÐwM|™´Bìôâ«ÁJ–åÄùF«¶Pëëm8Ͼ˜y ŽëÈà|¦Í” ÜO˜ç—;ò†ó…K!¨[ßô`ÕEq §¡¹ìcì'ÐÓJÌÀ¹Þ=D\zs¹qÓœguà’t©œg‰ãNs£‹óÌÚ#†šã‰ó™9HÀ±tWOœÏù&…çé6ѲNkúļ4\tÃyæ ßÌÒÕ'ÎÓq‚É S}ƒó䎫†pn8á¤î½æ8Ý`>»—2ãAóôhöÖÞÀ<謱¸g½Q/c~½Ÿ¬Ïkqh]Yª„‰íœ§›©ÔG-‹ó\}80×à1p"p´ì6_Ц­äü†¥Çk `E-»èÅ»¡Š‡ü ô¬ý ù¢»w@O OÉí G/éðyEÄzâ°üô\Þ€ž"-ÓŽµÒO ç,ñÚáö°½æôÆâ©`ËR#X£ø)èœÑªŸ2Ǿéýmê˜ÇËÜžè'DÍ­sº¿eÑÞ¶òØ£“¤Ðc-¯/w{ÍP×öþÖî ÏGç;öôúò¦Û/jaòÒ€¨.…~ÑóDÕ7ÊÞ_hz¼`aÄÍÁ$Ê?¿¯ÇM¯óÞ'þ‘m§üés¸Î§ÜÖùg&Ñ»ŽBX¦£çµí¹!Dzb‘Û‹’–É Á´=8„sÙã£Ë?³ìñùe_IÚÝxû©I‡vζço3çÔ̾©ÉÎeŽÔ¤ÃÏ,û[RûòíC>¶´Ð/0:äg° Oà×Ûfm'…ÏÃeÚß¿lhô¿¬—Ñ&Qiú@E°í%0øÀ—î)[üå^â/ë’¬d§*Ìûôs­ÌâF«·>`ßÓûœÿAû~1ßCYáœJÔnR‘ÎO8W¢#ØGRðOÖ¡üæ×¿ýÝßÿþWü—Ÿ~8Æ´ú¥}v jb ©. õ,’Ì´³:ÑÑu\S~ÿ×?ýð\€<ÓnÏRj‰ä¬L%l s ÎX¢`>éM:¦ôJ.¾ â«—;µ²‘¼#^#K/ö4<[©æ-Ò (+ÖÈB¯—йköAÑåF¦3eŽ8…:jÕ§†)2Ò§ÅQQ“ÚøYAÅ ñP°4Ì(ic[W´í® é`Dÿr-Êh¯£ê)'¶Ñ°‹W*Ñ•œA:â†3íºeÄá°ß0.gŠ£¬Ê&zÙ uŸF:ɘ™g·§Z'F§^ÔØÔ0”k$aI>™€õ¯D{*ž«~ZÔ¨³¢•ÜB\rJgZ?M5÷ +ÕËJrÓd×drÑak@¤žC”úh%ÞîÅò¤ß¹ŽI3öŒ³ÃÇXñk,H^2²‰QܵëÖä¥tZ$Áõ–‡ê/dfŒŒÀóÔ‘ÚBY*§ñ÷ x]¿²ä”W¹4t´øË]7-2[l¸êІºdd_çA¤ýP—¬ƒ|ŠIͯõ«KÕ4væ*£Lå±¶$ŒX²œ¢+N›–šilªÈ'¢Ð–¤ƒì ø46¤ßÓ"3©¶4w±/ù¾égìÓ6^%þØÔç~DçEe$þøFüh,otKºA;æô!† êL8å @TôKªA¾®ò(4‰°ŠZkzP'H{QNڶ䌒¦7Jœ.Û¨ÿ¹ªûɤG ¯´-ÉùœTÓ¨ú–dƒ&äÎË ™ºñªîÇwl§KYÛ–dƒò΀×hú‚È¢n7‰Vf¾È@ئõÅbvÿ!G×Ú|-2·—rÉŠìÐÌhÏ’ž/‹ÎXû4xNL¾ˆc©“0ðŒ¤9¿(…xN>¾îDƒÎ, Éȥ뜯ðÌš‘†~=+:'W1DwaÑÎòBzpæS’©GzÅf€€dy@°b3ê¥ÐÃͼÈXŒcÔaX±™eC¯kqƒfV½“æD-Š¢7¿C3›°}¸þêÌ*ûžF_š;} &G¼a3U6@ 4Óh&fh–r‚-2w!áp Ì´rbF׆dƨÛ0`¡#˜<†ÌÑÊb3nxÝ™›+ÓëLnÛ`s)@šÉçXpΠ^V*(8WI(6pÅbs¡´Ò릙y7X¸g°ô›+y_=Ypf}ì[ì0ØÌ¼¬ò2ÆmЙ5¼Ñ;Ó/ͦ1õE$´èÌuÏ“XÑ™î:gñp¸6Ùâsaõt   ‹rº©—  M¿¤+3Me‰Um°Y¹ É€t^Ô†ÑRnì£åŸ Ëɧwª "“»€Õ"4P"Ù`¼.ņ{@Þ£éÇs ¤ÑtWFØøg\©hJš;pSm$Ûè@-èTåX:¾D#tqåFËCK©‚Q&jc¡#$¡ò–…Ž+Í[Àrßg–…öâöó¢¹Ä%_Á¡Ýp©÷É^¯<4ˆ—‚öÆC«`8ˆÍB4=Ÿ(‰œê îg½ˆÞ"t$w‹ÐÌ&3f:J& 4Ø'‹Ð‘®Òi0“ ÙdùëB3M¯¬©v|–GËi>ìýB³ïXV^mvü¤–iq°~Ðûå]úå)qÏí‰~ðàâýr{Ü %‡Åûe~y¼Ûk†º¶÷·Ç½_ÆÇž†_àý˜s(0t çîaï€SŒ±¼Xý§ÍÓÞ/÷9¼Oü#ÛVÂrÞô²YæS$ ]îšgfwI0=—„~x¿˜!| —„~y¿Øž]öÝ%Áôüü²¯$½”ŽÔ¤C;gÛó·™óFjf߀Ôdç²?GjÒág–ýë¼_X¹KƒQ{yÌûÅvò”÷‹íå)ïÛËSÞ/¶—¯ò~ù‚oIÔ|â¥K6Ø/ø–øÕ·äÏÿó9߬ &UQôõ`îÜî[2­ƒ´¶¹)àv‰QÙ…ÁÅ+£†â•r>ù¥¼%U:’‹Zm½‰ê)Þæ¶Ø_˜2nÑÀ4ðS¹ åT FcúŒ ¦¼¢yuVLº-ê).Õ-ÙÂø Õ-%Vàœò-ÍryÌ…mM—Æí—™ñø2U¥´·Kßm?b^*ã^2‹8Óbl½K …-Í‹&¼â­)§ °(a<Kˆ¸ã±&K*áŠ1ð2Ð¥²T¶¤ ©ß©,•-ÙÛmwN¬¿yÛˆoÄa\Nus0!áû!UcƤ ùž\½Lª›aç©“FÙyØ=SÛ"7|«wh5IŽ3¶!4–T£´vt¯—N~hÂmAå @KÄòðL° bÃ8ÔÛih/È2ÌŸB3Bö²ˆlW{Øиvæ¬w„^ bCèŠòá3zç: Y>Ú£ú Ób4ó› ‡£ ¢EOq™ø-]Iß7Y:1 z"íÊB3 zúwXš®aᲞo4hç¾ Âæ¡íç5½ñÏi!FË>3 øÊErðÏ$å · ÿœ%‡¿^Ÿû|ûÉmÈÌšYàÊh[¹g|Ö|ŒëÜ^wòæsfjÀ†Ë¬Æ¢3#n×g‹ÎÌMs¯¿…gŠ· …ç,Iï® ßÂ3%Ê›7²ðŒçèŸ4ùÖÐ}u¸P€n·?ý‡Í˜¬p§ZXÖ–Wå+?©‰¡øg͘ïzByÍãÇenôSW3æýíq{bM‹s~y¼Ûk†º¶÷·Ç͘cŠcOÓ/0câd ¿ŒÕÓÃfL¦~b¦VpüáC&ӧ͘÷9¼Oü#ÛÖÂrÞ<‡Ë|ÊMÏÌf[²=?o[â6Û’Â7°-ÉÎeζ$~fÙ¿s%éobÆ”íœmÏßfΩ™!|R“!œËþ©I‡ŸYö¯3cF–pkQ„¶Ç̘¶“§Ì˜¶—§Ì˜¶—§Ì˜¶—'̘ ’Á‹ 7°þ_2cB¼ZŒ˜?ýÓcÅʨ߸ª&ZØ’Ê}@Õ`¢0Ýb8*!ßÙ©ì(·ÿ| «’œE¢ãŒ@/qÕÁtZ6¦Çg‰ù®fÉX”@£—êH!ü/Z˜Ú_Lî8Œe…ZŽ‘¾Žþ÷©\uIFGNË×ô-Tt¸‘¼.JUˆ+à¤äMIî¦*¬ä|—²Œ’7ï L-¹Ý•,EDŸ RV= v=Mk`Ç{Q”R3n££!‹Î‡Éÿ¯¼‹¢©Ÿ±O¥®ŠQâý{» Xòï·Ú©4£…é¢ ¼ö«-L¹V3~'[dÓ¢y,ÝhaÚ¢%(ØôY¾’1çP;”®JÈù~š€«ówùJ¶Õ© ¯Îè` S_Ê–!›IE-6u­Õ›8Læ÷›FêM¬÷~^i• ŽI ¢3»k0 r†p_ú¾JýÆEžÌ¹p£Õ°ª`ìSToLò¤zéî+n¡>¬[©Êç &Rõq¥ˆ­É¨`âê PÓªƒ¡Qü6Ödt0h‡½´f£ƒ¡yð2Ô¼ê`˜µñÊ Pó¦‚)wÌ\-FÃô·í ü¬Å¨`ÂÏP‹ÑÀPOwYP0«€YR^Ôj0X­;¼8±(`Ä`èΕ ñ+=eÁܰ9ݾó;8Ó¢ä.„g.þ Ó¶Ø,ñÎW$Œf*©o+¶Aæ-lÝ 3cÓY‡wh¿VdfSò—Ø ³„¦3­n‹AfZDsž),4wf2žW’ænbê 6Ó6ëÊe³Ø ¸»5×››_4ë›ÓF_–-ƒÍ„Ö«Fª…fÜoeR©Eç– (xÆ—%äÌÂ33™Ý!nŸ%мŠª]AêQ?h»|ÛÿšÇk"?®³{¤£^ëåýíq3bÏý¶^Î/w{ÍP÷þö¸õrLQû_¾ÆzI? ÀV`YÎð°õ²87ZG„…°þv¬—÷I¼Ïü3{Ç9þ$.3ÊßÂ~)Zë†íùy£‡°•̾QI†p.ûsF%éð3Ëþ ì— Q÷Þ¿…S{´³¶]£YoÔfÆð-RÞËΕ0ç½ôø™•ÿ:#&þDiâ‹S=eÅÜzyÊŒ¹uó”sëæ)CæÖÍ–Lu Jë™"ì—,™m Èüןž Èl±Z[æÐS`“[³2ØîŠh)­¦Ì°d›ji)+GvlõòhmæWKæâIÚrZ-™EÜ.é¨åºZ2ƒd,ÚíVÜ¢qâç?TŸjË[Ãdr3’goÑÇ„%uZ«Îªcêt¾n¬|w«cœäj‹V몎iKØbkÎjcZ¾ôí¥USÐY¹Ü¹‹Þ­¦¢:ƒKZ¿‹È©£÷½È=­nåqu)n¬wwkdÒ«MMkgµ»[#ÃÇf,9XãWî™Çôj««NÆ/!&mÀÏ¥¢ ÛÀ¢’ ë‚9ŠE“¬™W¬³ÀÝmÑtKö°Îòv·EÓ-ÙÃz¨V#³díÑm?SíÒcZ š«"§3»ÓmϤ6á¢üžœ ø‘2k¢™í)-öL¦¼œzÍÎÂv·=“1]3UUÏnÕÉÐ\<•=§U'Ó#xgº³[%³Rbçep«dúbÔé%­?”µ0HµƒöRWL_òAu´»2}Ýäš–€ŸÊøƒ¡vcFœ²ê ïð­ÎRvw¼Ö{VC\g%»[%S—4ÁøÛª’a>Ñ õîVuLc¸Ë_¼÷dC}î,òìnWò*y¶‡vPyƒ´Ú矲enØY€å pg÷. :SxçF·ð1È™°Ð sŠ«aÇ€s e:lØÌ¦Û²¾B3YÕ¯{ƒÌ)0aÝLAi™mqJdN¾®anšéAsgƒÌLd>óó`NR±~ÎkæÄ‚îíÒ'\–®úŒ4_™O-¹± 0'×Wƒ‹féíž™Af>7w\f„Wž65ËÌ<“mTföó;`Û¢2íwìÓ@åÊÌþ³€„EåÂøŠë†²¨\˜2g‚A岪®-(Öh¸Æf0™vÌûðLf.Ä~y[XLæŒîh)ÊL‡{¯«Ádêˆgt·…dd–Å@2Ûú4Ð[L¦ýç¶-ZP¦ÃP]Ú’ôY@Ô€2³IÞ{‹ÊÔ€O°2¨Ì »w¨­…et–—\ÆlîÔÌ—‰ýf 0ÓHuN-8ó•Ó¸k±Y’%}¸…f)ã’.uþA5w~óM™žÓB\óÌ쯗MÒÂ3àè¾w6æ¹®i§7æyc óL3Ô´HXæ¹­Æ ïL g<øæ&lØfÉœ–¹SäÆ3óù } ÇL/Ä™ûÄr̺7À,ž ÓZjæÖ̆c¦«Öz¸AXŽYâ+¯Ð=Ë03ió͆Y¬¶“ÏÞfÖ¥¸þ_^¥ª_΋WæÆ/ó˜NÞr°Ëß~¥ Ù¸e“Øwc—ãêÿ²ñË}}¥AfŽàrjÜ¸å ™b/^~g—ã,°±ËaµòY~™@zeX·ÐÌ C³²ƒ…fZ€±þøqËmÉŒj‘™Nawˆî†Ì~Éül™i&ñnÜòšfÃåÕuÕrË…Y&ûmÙ岊{¿\V‘ô`˜;—x¼ÓrÌý60n°ìÀoL÷É3ßÞÁÓœE|é^Óœ1ûãe”]ž†DaQÕÉ£’2ðh)å·#xF™§-óžà#=y¿3—¯›=`èµô\¿•=sNr¬ðýõq‹æ5Ë«çú lšÕñjwÀ‰Œƒû¬M³Rކ[¥|È~úxYååLÞçÿ‘­»ŽüógÒÌ)K¶Ñteœ}²Ë­Ì¯íû[›òaÚ´ƒø&Ö¦|7·¾Ÿ]ü½Æ²íû,þJÞ¾ CÒ|”èÔmÞÎÛöýæ½Ä· :åÏÅè¤ËÏ-þ×9KaJ¢ž<ūnjœ[/O9·nž2rn݇¶ñK­‰¶EŸC«ã ‡6Zë.ÊehÁ=ÎjìŸmͶŒÆM¥s B[•Ò@J¹|0ÎJžL?*Å”r© J3”áËPÛf½=륚}ŸÄËTSwFfÖ·[t;â> h2ººd’y:)¤´K3$õñZ) I*G)ñRq|+~иÙC—‘âh¬6Ѻ:Ä£‘‚ÝE»²ä“¤ ìI ¥Ý´šúfuì;Üý±Èœ3µc>‘\RÕ-Øi ÜTÆÝ<Iô;¬‘Ê™mÐÍŒÃÉ™Ú6LÏ‹ä‰éŒn•¼Ar©ìygµHNûçRñÌB¹Go¢…ršG{Xž\Áœ¹k]Ƴ‚9M‹=Ö:Í1‡ ÎXIýZÔâ9šK„ºÁs>¸$y³€N‹§¿¯Vƒçl»lâ;ž‹ùdsABØl¥µ\ ~-šKñéå\0§ëû´¤m`޹”Ì+Xè6•®š—º­npÎ8È,¸Áy1uð6nÜ9ýtãΙ2uæAÙtœÝk¶±ç ·^Y#Þã²Hí5{ÞÓs ÝŒ¡eÏq–.ËáÆœ‹£E5‘wæLc÷d™ó²Dçí¼yZBðvÖÜd<ßyó°&3Ì9!;Æ÷Ìy\’ÊìÌyX3çîÜ98·4Zö¼,và;_‹OŸÜù¦y²çî.æ¾ñçmÉÐs²çáv'=ô;EíΟW#@§luG†î€î^‹aà¼Zšß¸óò†+ïk¨æÆ•§¥–ÄΕçõÒܸò²¸íL9Ð1L+îΔÓuefqÙ¹ò~%!Ú9òÅfgÈI~“4•!€¡ËQàãWiÁï~”2 ü¤AÇE«~zÈØú¦÷Gô c?.s{¢Ÿ5XYçt+wTÉC%ìœd}ky}y¼Ûk†º¶óšgM¬cŠcOÇ—wÝ~Q_ê!âKº5Š[`æqBÚz£üý…öU€ ]HÀŸWÉús»zܼ:Oá}ÞÙ´qÆŸ>…ë|4ÿ©T1^JšJ Óéøóƒ³|ÃÙ¯þõA8e6ƒpô{ýùÁŽYêèVþø<ÙºÛmå9r’'9ÙN%'éø"'Ûï“ä$h0ÉÉôû,9Iǃœl·†œ¾|‡--´Äœ]D)Õ ãý­¡¶ÇrŽ«’{ãœóõVJÓ ¦b:œÏ™\ëáÇzaJ(W=+~„ÏôR~Y/ԇꮼ³SÎ^šéåW¿öŸ<ùOø‡¥Ïï)[ñ¿P?}¿_¿ðŽ‘6-Q¬”ñ)‰ÅPYNiIÁ?Y‡ò›_ÿöwÿû_ýñ_~úáH¬‡1¦Ï®AeÞ#Êû-HHsÃR×@Qù³Bÿø§ž‹Gõu©nT¨‚ÀªB&cm[òƒ•HÓ‚JÆMóƒ9ðNŸŠ£eÛA†Uq®áWò)ÂF¬Ø‹j.ºU˜-Ü…–¼\ð"{uMÖ)Àe©ÎÒ!·yQ£ô%GX.Ò¸ê@5CpK‘#y®a N›–a™YëfåE#Ü]å(3æ¡4ŒªRœ ÄXª‰rbÈÕk”ÁkŽ0Z†Ðɱ‚|Ä&¼æÓ‹Q•ªýÈ–bâPRƪÐ àˆU$ûîJG¬TÛÀ˜6(›–,a|Ì嚀܄—rGlkу tæqÉ–©âð +Ò*InöޱFYü¸©ÔeAH^ô@8'¼ààC¢Rmxç½dx§ S6=$MÖ3Võf4_m9ä%YX ^ZDgòRñˆmT(Q‘"mŒË–â5 ÁDx e©xĶ šÐËeI–Å*X[õã¹¥äQ†`ÏãT|uÉ&ïÌÕ7l•´-ù²è š‹L¬.5rª¢,è R¶µ%cX–ä_¸”ÚRóˆyàuÚ][r†eq>OØ9t¡ß5²”  ‰2*ô%e¯L\GÓ§d®ë”fÍD»{‹8:ýªÌ%„BÃSQtnÉ–ÅTI$^ÚÚL/ÇÇj-®ÑnE¿¤ Ó mAë¶E¦^›ôÊ"wØy†¤mÉ&£ä5‘å€G–fºêsÉÖÝÑ\1,‰Ãd™ý`DËÃ’9,³¤hpµ5ññŠLÀvUè’mÍ.fY“¸$ãHpJ\ó£­‰ hPk¡ï¦ šPeaH9y÷QÐÇŒ²µ!¼:,ˆhwÔ.ýņ*ëoA›ªhL2%9:´ õ¥ØÈDÜA»HʼÓ;hcÝ%f¤SwÐÆÚ¿h}”´ c\©Xômí¼”n|± ] BŸª"É Ú|¬ø– î«´Afø2ÔÈhó9PJñ¥î˜ÍǪï×ÄWÌæÜp)õìÄX`0›8ÅbåÄb0›Ï1 °Ç–Ì&ù ƒ/Ù1›Ùò@§X)`6-žæfÁì²–½³Í<ºwœ*;-d3Ô+r¡¬ìB=hÁ”j¿![Õ>b¬'dãeþ²Üì]Xþ;e¢öÙ,ë1/Òž…ì"¹ ‹KâVa![Ú’÷>Ʋiî^ö€lšq_¯÷›ÁlFéå|k1›¹‚CÅ2ËÙ1˜]HA8Y¯oÚ\ÿ ²¡ Í-ŸXäÐF[¢…-+¬ÐfÂÔ‚mеî Mg·ž ¹“´+Ù2|Mñíº„?í ÍÙáôe¯,h3b‘q¹·´«úûâ솴+3\\1l³%õcöä,Ôæc F 'j3ò1^™êUàå¯AÀJÞí^wÜÖ3Ú‰ÛÒq#•t7gZ1 8ÜYÞÄŠ^'pZùÅ:s7‹cß…¸yQ~†]ÃwŒ/¥¶Räö] ¤€›Ý‘;².µÀe:‘w8Cl éžÈÍäÌ©¹.Än‘›ÃÔÓ;ËBw ¿VÆöì6%ÞvÒË Ý˜]Ž–nsë¦sœÁmâ=ÆJÉ;l—ØðZ'q‡m¹B°«ã:6°Íic„ÍEe§WÜ.’’YÔþVÜæs ‹ep›m ÷|Sc»âv‰àhj¬‘V± ·YÀŠf³Eûdp›Š{¼ üa9Xm.0K`_lñŠÛòVïÂØ·q¯3Fµô¢ÒŠÛ$-±f&íoÅí".SLBn;nñŠJô,=xí"µA=ò†Û| .؉·Ù†»´àòŽÛ\c&þnzR nó¹°²QYÕ·µ t¬èµÀ67oC*6°Í§œ.lØq›‹"GÈË( nóU3-À;nËH z5È nËb¦) Ü–jg˜xWÖÌ·®fkÓàæ8AF8[Âcàæ;A*½ÇÜü9(û1½ä/îȨåŒ;÷Àml=îÇŠ-ÊnSÛ€«ã¤Z- ŽvŒ07VK‚cÛ|¤ËWÜq›Úì=0¹”·ùN|V¡ÆêH¤Ì=¤æ6!«’„~b£Wï«$Á !ë8œU’0;WÊt²;jË !”]Èl•$¸ ZçÐf•$äÜ„¤Ó†ÚddYÃöbœ’„ù H@Mü¬’„{jLC—`nf0-züÉpKzðé@n¶¡¯æÒ~›jžDo–z2ÜLY¾cl‚e¸éó¦µèj†[òpï3‡Ž$a@1&¿Mm€¸"ÞðÛŒ2‘OÊÁo3|Ü 8‡ƒßç÷]лѪH 1¶/YhW‘ày\ßoømêŒSͽӑÐåHÝæ~›: NëÎnSP19õ¨Út$IÔ’X¾7:’Ä$_2¿Õ‘0ƒƒá`·©aHrŠÛÎnƒ÷bÁŒA›Ž$O.cÓz0Hõ®Ü4$& ºr€¶´ÝWÒ¦! ¼|î¥Ì6ÓÉ£³<ôVCI6­ª3Ϧ#‘0PŠh7 &ŽQå±&IÊÄrÖÛ]~2ôSR# ËL«íŸÔŠÍÖ'ýdÞõþˆA¬_>÷Üžè'åÕOæþö¸Ã }Df¿óËãÝ^3Եߞ÷“S{~ŸL`‚’€Û7Y}ÖO&Òƒ—¸µ¸ä<í'sŸÂû¼?²i%,§ýAœe>EâÐUHx^ÇÓ鳎 }ñ“±ý>êØÐW?ÓïÃŽ ýö“±Ý>è'³’íR ø9r’'9ÙN%'éø"'Ûï“ä$h0ÉÉôû,9Iǃœl·ó“ 43“g¦–ú)?ÛÉS~2¦—Çüdl/OùÉØ^¾ÊOæ ^(=¼Èg’êG¼PþñA/”ØJz©V²X4·êŃ$=¥•"  ÝT4:æÐ­)©~ˆ9f@M-в˜¯9“;f›L‹î¦ÀJ•„¬á8‘¼Ñ¯Ôµ9*÷§`œP ÍÞ/E–eõéÅ E 樊Wæ9¸, ´‡,¦^( áH⡦’qYn ¬L•×} ^T¥LŸ¦ÀÊ ÏÝ¢ßf ÀD1ž*†^*¹‹§BÊ/Ñæ »õ+Ì~ ª,â’òæƒB±¯åÊ» ÎMð¢—MLÙ>%V‰¦¦ET©,åêØG¿CŸÊR®ŽÏ-öÓÄŠz·ÄÊàpªñ‘êæƒÒK.`¼eªñA©LWØzV«ª_aJ_,zÅxjFÁÂÌÈyQ¥ÉèWÊ«CÎÍQi¤mú†û5/&žÔ ã•z¡©PÚŒ~%¿h§¥[…´ýJY Ùm.(1׊?tiÛõ+ ¥R#Hv›~¥âzÙîì­~+ òýDö› NgŠÐì—²u21äŠ ‡¥nu(8m—‡S›Šk´m‰(‡¥nèzz®>‹•7ÇÍ ŸâÐúçx¯“[ÇmøvåhT,t£a)[iJKí:ñ†©ù2{‰gõA:%ÉÁÉ6£aÁ!Æø“ªåÜ^AHB­Ñ-ýåÍ ›ÒiÄ–¶¥|´5Ž–¦&$IÆR×ÕJð”ʆÚôƒ¤ýPkƒÚZC"…~‚6ì¼ÃYïÚ4tf¶!‰g”mêà]ÆEÚâMR««¢¸4˜M+›¿«ÞÐæcØÒKi@[¼PJ¼[VЦ-0ò 8Ñ¡Ð6sêQ‚ h‹JhÙ lXA›ÝAäÆiÖ€¶Tt¦û ´ùJðrr%ã…R˜e@B ÔnŒy•f8P›u<€Ñt¥9P»D&+Å};P[žcÅl±úYÔÆ¿à†Em¾ƒ¢ÀÆ…µé­+"d½ êæ†¢¡þm†þÆ úÖ1ÐÆ€ñ@½… j3µ@%O,jÓ›äΓcQ›áÃUlzí@mŽ%¹2>-jKÎ.šÃÄ3Ê¢6 ÁúÀ¦x 6Þ™b½4ûµé2B íÙï°&qÍQ©ÌÂ6=}pNËÕ¶Âv•zà—š×Â6ýÌ\-]}F,lW¦Ým*_fa›NN,àWK:`¨Q˜–§m‡íJ“ 8M–ga›>D©„k5 nËP긪-l³˜+®{á-ls”˜'ÝLØ&¶a¯pÀ6žÃ+‹r -lS•Æjʳ©@é_#ã·üP>nδÈM˜Åœ|!Ú w QÍ$ºñ>Ì.Ä1Üßfå󱑿MBºóéà·Ëzȃññ›×7ÆÙ‡KŸe¸éIXñB¡(ìÍH Â+Ã]Ä};fñ\µü6ߨ @·´yç‡ã§å·YÜH­/»Í þ‚[ċ׋a·i(ì¹Óûàà·‹˜•Êcº1µ¤»rB7FÙÃåô½A7/˜Ôh¶!7‹„‹W<‘›&_.ÒŸü6ÛÚ´ímÈí_šæÛÈ;Ïd̺(ŠÜü[›Þ͹i1v4þ §g‘›bÄ‘Rr5È-Å ð˜æe°ÈM¿È$%õDn¦‰O‚(rK±{¼Rm¤¹%Ù­JZ~Rs[Ÿ4h¾ëý Íå5—¹=ÒO] š÷·Ç-‹5-Íùåñn¯êÚÎoÏ4ÇÇž¦_`ÐL,ÁqÅJz4é‹‹'›Ñ€;ÍûÞçý‘Mka9ížÂe>å&‰gáå¶@ÙNµ@IÇ—Êöû¤JÈdZ L¿ÏZ ¤ãa²Ý>hÐ\Éö›4¥ÃIN¶ÓGÉI:¾ÈÉöû$9 Lr2ý>KNÒñ 'ÛíÇ šTR99ì1ƒ¦íä)ƒ¦éå1ƒ¦íå)ƒ¦íå ƒf‚PðbJpð_0h²(æjÐü韞2hŠ’öªV¨òžµåˆ™aÕŒ‹‹c½ÃpfvEêª 3%Q5Òôy«Æß%U4Ûâª_i²ƒÅôBõÎ,V—Y‚LÍ(Wâª_©¥:³Vi+ÉÏüŠÔæTˆMetF€.Ú•Æ‚—Ci¡ÄåFŠº\4)^ט–’~%A¾ Ñ·•œï²u õ£kuUî’Û]¸Žm˜w/q_ŠQ°ä×(Ù+ã,ùN¯H‡óNœöÙ´)X2vzX4¹]WnEqÒv ²^×&£_q¯ðnµ²à.ºk׉Ω©;3ÛšQ°0½‰F¦K›1hv‹b{Dä.­Ý¹ÕÞÅÖ”Vúª`ásMë@J[¾ë×IFwi¤JWK•B¯Ã0Y©¸¸È•–æ»4`uF¿’hê¼ÔÕz‹‹\ùX†¨­ê»8£æ&,oô«vMÌx‰жv°“ w|u F»BϬ\©·¸¨•9  g5‚Ö`”+K¶Q´Qo1©•…û4%k”6£^aj?Ýyi3ê•Ĭ8\±k2ê•HçûÞšè°kÚÔ+ÔþfݨɨWâ’ݸf£^É/œ _–¶E½Â™g-*M«z…YóÁï{ >©eÕ®0[挢–U»Â°jÜ ²(eÕ®°T`öqy­«v%‹Úê2ÔºjW89@FÌÂUÔºªW$²Äæ´­©ã@b3žLt¾A6sT_¨Ý1»Êú”¡î±˜»È§†-ÄÅlú $°&J ³ ‹:ÞË`6¿`×&0¯˜Í #Ì»à5Ðzmš3±Í¾t1ÉЖ1“ªv·‚6í™ ( [ÛA›m8µ¨ÅÏ€6Ûšï,Ð[wЦ='‹þym±uFfI~mî ³« ?ƒÚŒEZ6ÔfÜí±¹‹!΢víÑWÔnR ¢·(*A‹ÚgöÌØÔndžB†j‹ÚLiŒEw‹íFƒ¦I9@»J®ÑNíåÚø£‰´RNÔ®’À|XÄ,j£‰€1t¼µ+‹>.»‚—mVË“w¼ÁmYF1¤·™Ž™/Ô±[ÜæRIIvܦW;çRżkq»2±v\<·!5hŒ«¾Òà6³K‹8°MsfǦi> Û<âÙ]ñ¶і"8eµòZØÆj†ŠUý¶ÅíJß—GvƒÛD`%ˆ¡¸Mä,ôú ns”€—‘çÅâ6%ß'Üâv£õÔe_õ1¸M£x½2†bp›ˆÓ´é[Ü&¸µ+U¿J“€&ɵ?ä„òqk¦EnÞª%µˆÁí6¯åÀlýn;IJ”%{ô†Û´bÈÀÜXO^MÂ-­öë×n¼ À¶ ‘½”q}úÈ|ؘÙ$³‰ÆSå£Zù¨Æ¶?iÎ|ÛÿŠËk"?®³{¤£^ƒæýíqËbÏý6hÎ/w{ÍPw~{Þ 9¦¨ý^_¾Ê ™‹ÄšSf­áYƒ&çxG„ U±þV š÷9¼Oü3Å|Ç)þ.3Êߤ)N”íôQ”t|Ù l¿OÚ „P¦ Êôû¬ ª4g·š4ÂÅåÿ-lšÚã$(Ûë³Éñ¥ç‹¢lÇfÇD˜$e:~8=¾s~Ò”í÷cvMü‰…®äŠÖ3ln½ÚÜ<íl±Ö±ÀÝpy€er]B{,p7ÉJÝ£ŽÁ·XoÄJ‘àn4‘cYÕSÄ7}+†dK pWroØÀªøe€»±BG©×c¸i->XÜ&Ï“ÉA÷ràvcÅ–>¯3Ü~|fzé|7Þ‰7‚û*nó•q–¸´À]yÄû•PØw¥w’c!‘·¹’8Ÿ¸ÇZftq,nWVˆè­k–_‹Û´[×Ì­|à6Mè´ÿkÚ] Üb€ž%n,p3lG%?›ÓJ3ºèA §Åî¢Y݉`'Ï]¤rÒp‹ÝL¶<ü Nž»1„©¸ÞÊÁs3´d† ‡ƒçf‚[³‰–ç&4äNŽoç¹›¸l^»·ñÜ’7b>yî*¡ª—Ç„å¹+oráÓÉsÓ} ` o˜nÚQ°9AÝñ,Ó]Š’WEùxËt3 põ'r ‡/.f*ܬ,7c_ G[mXnVð]kuXŽ»H$Þõ˜å¸é½ ·¹y%¹c/ù丙ª˜¦d=A–ãn/ÅfE|Ër£í®™p±Ü<ŽÞ¥qt,ËÝéËv JË­Þ #¦wc¹ñN#¥‡En‚™K2™“åfÌ2ø§ «e¹s;B,rgæÐ¥uMo ÃrÇ®þ6¼Ù,rS:¨4r§Xäf VÇÐJ Ý"m0ñEltó‡àXq[ĺñN° WÖ ÝœøUñϰÈͪÏGGf˜åàPB/ê¹e›•« UIù`¹5¹Â¬nTÁ×tÕfn,7¡ÔO‘È@·øC3 ú t3••Å¡èÆbB¢NyÈ/ºi W§zóÜÅUBI_Y«ÙåifþVÍœB~Z®™?x´^óÛ<£ÊÌÓÒyO𑞼_MË×ÇŽ ›ÅØyûûÕÜy}ÞÞyÍòê¹þ‹'.&z”CÖâY™8ÁAÂ!*ý Y<×yŸþG6î:ðÏŸH3§,ÙKÓ•¬öÉ.ïζۇÍTy1|n=?k§Ê«éÓöü´¡*ßÆÏ­ã'­Ÿ+ û.õ~E?÷ aI—7aÙnŸ%,-hs–íùQºTƒ°LÏÖ•¬ðMÇ3F9Ôž<83n½÷‰e™EÛƒÆúuï4 Æš£5­„‹A”>Õ3o&Ú6‹( 匚7h¬’O‹A:¢WH-_Á¼§D—\Ãò*Ë£© Æ()R3™hÓÆÓ*ê‡ͱ1ÆŠéíT¤W ˆRˆI²j‰MŠBoÄfvMxLs³¨i3(²ô²>BýÇEÈ"'«u6jcbx’²Ú8ƒtÁÓª©a$ÉUõµyUÕ$©•G!ñÚIÈ´‡EUòjc•ìZJÈâ@0« A2r¶\:pé"²¨k¨aèèHKÒ¦Aé dšÛ$2AK$újl¤¬Ž%ñ^—­#) !fÝTi¬R4hÜi ìjÖ’†ÞS2i™^Ý.\9BјlZ[ÜiWl)«Ík›è¯AQ F¼vÒr’º¬~XÜиKËk \ÇÓ«Mm ø ¼&+‹qJù ¥eæ½M³Žq'-óê§ìG£1˜â„ûÀj6¿m(Xªq~Wœ´ÌĸÁ]é8Ñ(áoƒ–™/øË›ŒEs8ÿÑ=i4Ý¡žê€T%êþ€zÉðy/›…úÂ2H³˜ìõ$åŒc×[8 žU;ÃrÏB½Ø@»ôzB=m®@ÝK7o ž…¯”;ÔóJ×܆C“ÕŒõ4Ü»¶C=/4)`ëk8 ^ì Nc½°§"|Ì,ØóÉÞï%0`/É~‡Áó{J›FÂÄìíU.¶O¬o’.þŠ{Ú°¾IÑàžµâî†õ–Ö,Pß$F'ÊÇÔKàV ëÂZ¨g`ê]~ƒz†BI¥Eר[ꕜsCzR‚zÛ„éiG)™%¾Ó‰ôæ”o©ôÀÐ(ß é*1‡õ Ò“e¹kùnHO‹ª¦6ðÒ³Þbî—_Á†ôÁtÐLBÝŒª85#¥ÅôLBrÊ6 çúÜ•Ð6 ¯â2’n,7†UŽ‚Ç}f€žªu Í05m@Oˤk=Ä ÌWãj¤I#Ö>.Bô@,mMZ=}zî—0JUèñÚ.yŽ•ª,Ðóµ˜rzè,гÑÓEO¹A ôŒn2LÒ ôUÊôâ¨ëqUá•IŸÊúÀ“5>-Ö±‹+ ˜O¬§m—ÕБnXÏš©7ššS6¬Ç‹°Wô>·l}“ô˜ PoÙzŒî"«tûº"Ê,WÏŒ#1q[Ϫã˜bÓË[_5: Æ[/~3MéÎÖÓ‰~%ßûþ¢û3ùŸŒ=Ӗ髵1öE|[\LöÎ×»&If¤—Çœ¨ß™úÌÃ{U]ß™ú¾ÖXÜ€^’ù‚ ÛÅñ¦^2ª_…Þw¦¾éë¸{7žžH,©é OOrHmd°<=“„9²¼áé3eɼð–§ÏL‚ÞÆEfž&HÈ,Õ  }&#q¦*ßa‘>‹˜xuœHÏFõƉoxúNsûUç~ãéiÅ{‡¬¸ñôÜ ôæqí¤çÈÅÝ+¶7<=)W]hn ^ê£Ä«õõÙ¯åîwž¾ÑëÖ¥±Ç–¥g‡ ëcžšòÐùdé’™Þø Ò£‘4ƒÖûÝYzÖdÅ––öéI8æ]S ì,=݇ãåv¼³ôÌý4*õœ,=S€çk¿ŽÀ–FnäÁÑ“à =M>X´b˜dÁ‘`ÏYf '’Ÿ´ÜhMüÄVýô9öMïhUÇ<~\æöD?àE7¬sº¾5Éÿ¨=oÍ~Ç—oÐí5C]Ûû›Ú;¦8öôúò¦Û/êb=¼|o⛄'tfò(,Qó×6Á²Ê7Éé|þ@W» öW¿öŸX —ÑþágͱJ} `¥…€ ¸iÔ î=ÓMoמ?ñ¿?ýŸŸþÿ÷iÿ¾ nÌy„pÎ<ë|4Û«nâZaWEœ}öžMÛƒCˆôùŠzÛîCXÛ¹ìíÙ›å3Ë^Ÿ_ö•¤˜ ¥ÜÆs¤Æ7R3=R“!XR³CxžÔdç²?GjXŸYö7¤&7+Œ…Ÿ{S­.-´¤n ÅJÊaç=ñõ&cÛ‹ãT°)%ÖÏ™rý/ëì5¤+pØÔ±þíÒ¦ˆçáEVœ)X?ÓKüe½àåÌ• œûŸmüþK<Ã÷ŽUC)ôUÜý·…úÊú _î…®›Ç<øžJ££åd$ðOÖ¡üæ×¿ýÝßÿþWü—Ÿ~8Æ´Rçx˜þ*Tj4ºÊG­“‰žþk¦ëÿúÓƒX}]*BÑw>Ç”—@[r¨5ލ€Ðè<ß4‡šKXÒÆ"'•ÅDnt×}'·ÜÜ(¹ÖŠA-¹?P)¤/ê°¹?´Ø¹ñ@r¤/„+- gÿG"7û?â•qf÷Ç+ß;iv÷‡m¤•äp¸@¤O>qjæþ/ÿºÜ1žç§®Ú˜Èè=qjô‡höD™S£UZ$ÌùˆS£FE÷{!ÿGÕJ:y‘EâÔ¸ÏkAÉäÔ˜g~êˆOË¿2qcw‰P|oG"ÔUƒLH¨µq¬½nL¨åÙŠj~‘H©$&oÓÂÛȨñ³«™ FðB´ŠQ‹L©1æGµÈ¨ñLPÄož«ˆR£á{/¿Sjä踃†)uÕD/ãȩћ ßË]EœZî$¼2Ì©aŽ\Lªõ’îV R§Œì1©Ö½L÷º"Õ•N›LªÑZÄI“j<º^9&N­©@v, JfpkêÉ©ÔiÍ?~9rÑTCöC7í¡öῆ¦Ñ“‘;?šýˆèÕW”‡¯íÄ<)ÇÈõ×BhP8Àæ|`ڵ±·þ×ñȹÄùLŸ?¹ó ® ¢"³ ÿÙÈáp¡ðRý• ¡?¹óÞW‘@}˜ö׌Üq$pÌ9b8å ˆs0B(¬§hZ¿~ðÎBÜNgþD8Eÿ¹Ã·ðpо"wxæ³_–Ÿlû"w¢I‡ÎçL n¦F3ÀÔôØÔøΛšÞÂ÷m?gj X?Ùö?#rçѬç¬9 §"wxŽS‘;<˩ȚåXäÏò»"w~#.FÎP7ªö÷AŽÿ?.æãbÞNq1täºp\×¼¢_Þvüt¾í0©ËÜ£w ÚcºBsÁv¡YñÒÞÓz ÂÝ”‘A2ÜM¨­q¹•q·Ÿ‘¨D+={xL¸äCþ!´?nKQKû‡^´X.…ô†Ö‚pô„p„ˆ®d¡8ˆùw\/®d!_ õHà–L)tT-Ý…'”ûrÑR­¹RÚâcJ2ÇXÊ[€Lp~¥¼Ȥ„¤kü®i ØÔ²nYÝÔÛR }5¬Æ]9©„¾‚X@p•'´?t% ÍàŸ%£§º…ÇÈs[è™ê#ç멤:$WdZ™×:µ->¦¿KLH$W„¤¬ãzj[t Ú®Uõ=:&ûÞw’\dº^ê[t ºÀO÷D¾öè˜noM¾HtEER©cŒTWôe×:°0ò|GÕõ¡én’]Ÿà®Ïwh+¨‘.ùŸÐUPeêo~¶ø˜  ç'4Ô±²"ÛòKªëÝœùõ¦‚Xuñ¸¦ü’êšbmüœBSAõẠ¤ÕÌVñˆ«‰iZµßm ©Å¶+‡®‚ î6Ób­n«Ð0ìÝeUfÅM ÓéS;VÒ€JË×t*<†ÑZVÝämR°ÛÑZ=š¯Ù+¡uAo’š§{šáZ},â5ÂHà²_øñZÕBÓï¯ñ³&“F?wÂë†2 d’\å ÿ<+p"âµØ‡Ø|]ñ…„×ú*æx%¼F)é×DxÝ.d-Zx¶ìtPî°ñŽÝËÒ7ÀÎH1]ño`W4`ŸÀ›·™ ‰op-ï•Ǻl€-Ü¥© °Q_ùZÑ[`#,¡W»6¸†DvµeD ×)-¼®ú3QkÃk@ß ZÙນ"õ ®Å>ä‹14Æ ­…‰»ì±¡µðÝñÉûÖH¹5M~ëî¹ØßÀγu‹±q ÖPžžõ>m`-Û»¾½VWAV[ÛÖ¨$cÒȆÖÆW©„ ­Kd\£du]á® ×H&~×åÝcd<yCëò%¯×i­;é¤Z×(-lh]¿f¦ ©KŽÜ€ý, iu‰ÞeWëÜLóÙ±ZN€A™"¬Öýp1”°ZMíÅefy‹åݘ5ìÉlÔðbavµf†ÉÔZ -ñ†©µ Ïc¦µQ뤵oÌ:—6ã46býÄgº1kT3J‘<¢í7î1þ}i9…”²ñ ¦¯vÎ0€'YÈìRÀ0ê:“À0 X|-•aZÆâYƒ€íLÍbœnÏÌ1˜Ý@ÏË:–B·+œ¡µÓ†…2D£±‡‡t2F#Nýƒ{D}7FøÜNÂgôiI&W2>ÃßîIŒÏ¸ÅjÁu„Ϩò88á³l˜<²õAe„Ƙ00Bë˜í#4êçôõeb€Öf-¦œ2@k7™¶H tíá2@£‡×—c€n¤›nt• —ŠÎø,7™/á3ŠJÉÿf£Æh«.è3H‹†XniX©Ç-ü²âZî¥  ã÷ðÒ⿆Ñ“Šëf?á¬\ëøgXÛ‘yjT\×_>eI®¸Î?>0íZáØ[ÿë¸â:—8ŸiúŠ« ˆ†°ÉÁ åQN*®rÀA¢€ÆwøAÅ5áû˜Ñ%E>¹IÁÕÀ!çˆÝ´'ÎA ë)n•gnSÁhæ¨`z ¬‚ñ-œWÁô¾oû9L­õ'ÛþÁ5šôGWL¸™ÍüSÓ[`Sã[8ojz ß·ýœ©)`ýdÛÿ ÁõE¯öê ò”àÊsœ\y–S‚+ÍrLpåYN®)U-LŽô¯ß\Ÿ—×ý^ðÿ ®—Õ:.ü¾¤9Ù'º…JþÊždƒR¿V‚³iÅè•·ƒúÁîÁGH¹ûpP²Ø=ø¨¹ïI…åÍÞéþïöš+iÝ…å˜fSàr™e Qø t«´]Rôà_²xË;Eh‹Š—õF ¢dr ¡˜Ÿ%W‹åy£C­¦P—Ò\ró>‡›œ\ ù…Z\ø9f:Uø_–µj–«eÚÔ‹|øè ¸|°Þ—e«#ç}%,Õ›|ø)ª£õ&>ZæeÞ—e«êU—K¬›|ȉŸ‚‡¥Âù2MUeŠq}ȃ7}9|ž—µgU¬õÝÜ÷¯©¦õ%ÿ=6j©a8Á÷}Šn¼šÈ}OÚDMä¾O±FÍ侇Øg Ëì½+¾Æ¯6±µ»F[ ¹ïsLsôîû'ÎVÈ{ÿjÊøtÂ! xïѵҴ Äæ“ÿ¾W×]øÈ‚¿ dªíW›RŒ½&§¤VÆi¸á—C}Çi¼ìVÑ„aº—È0Ý7cd”F>^$Bi$º>Ë((M‚P¹Ï5=í Ò)ÁÉoC¤¡Ü>&ðHc,” ÆX 7QZËŒŒBhü{+š²!4dÛFI1­>2?¡Û]caBè6Ú‚ÚˆÐú±[² ásƒúâahŒÙܺ]ýkt÷º¡Ž³Ï ñý |4¾œ·gk@ãcœ]$„Ƙç°BËMÊf˜:LÝðø-Bè&ÿ¿ðÖF€n÷=õÐXòÕf‚:#t/!4~åáAѺ#áA ±àú'”ãyWi<°!4>ãY=î3ßð¹…‹1:÷`xn±>ËÏ Ýz××™àÏRì½¶0³Žyœá3Œô’kNÕ‚ðY×ìȲás±7@£Ú¹}oÇùÑ·â ¾Ê]/Ôx´#´<¨ÿ…ÐO‚­P<†èû‰ª8côUb€ÓƤ¨+ž Zm! f€h …º „ÑÌi£Uñt¾¶iˆ[ö9Þˆ4JA™4ÇLàµØÐÆ£Ñ%©ü¥¡Ù„@+æÑMPÿ¶ÜÄ£âÁ,Ü…y4Úf¸6ËDFè©’L¤eÌk0‘F°U­it-1’it9æÌ¢!²yÏdѲŠäÔšY4Vh¡Ì¢ëç3¦Ñ¸¤U.`­wgÛÄ4z¼ÇFɈFW°^Ëòe¼JK¸'F~ds<#]é„@D9”CðeŸÈ¾Ï“ÑèúD!•y4úµyµ&æÑšdmº'ã4ãj™”Œ»ïwqí'¼ã4| ‚Jkƒ‰FëMúˆF#U¹[82óh{îu!+zq(FiÙIyB“É1Hã‚Á°Ú¸oùà/–ùË«ê*› ÎpÌêýã'EÖÎÂC¹òϸº#ÍrcUë¯è=w—Yç˜v­pl®ÿu\fKóÚ¿GfÍE3ôÑ7°>geÖ"/6ÒåŸGÛŒ|NfÍàHI@ñ’ð_Sgu,pÔ9ÓKz"Íy,+ÊŸPZ1á&ÑÌ¿ôXþâ[8/é-|ßösò—ÚëO¶ýJk0já&ŸZuÆÍØhêOt@Ð{`kã{ø@ ½‡ï;°‚¢ÖOvþÏ[åŸÐ­å,LJSzë6É)Áu›æ”âÊÓ“\·iNh®Âº]Ï8Wÿ†æZ£æúŸKrmoškñ°^ÛtEÍeÜ-оqw½ºwë´¬žxw½1'U+FWQórÄZ;Ñ]E9Ö Gu¹7úIËk!ƨ”é¾"Ôdµ2h ÝÝWTBæ,êd_Q¥á1£Püü¬³/êãOQŽÉV ‡kW³pø5´µ+úŠHh-EÍõÎ͆®Œ1wгZ¿‚äŠô„¼ò‘ZOQr}b}:6As•£¶Kµý£š•V-Ý~¥(¹Þh8·«~Õ(¹Þ±Fy¿¯(¹>Á€ ‡ ¸>bæ5”ÿϬN¬ÓÖÑ„Ñ×ûK±‡´Ûу1f¹zÖfj”\ïX|¬¿WÔ\Ÿø8eÏ8Ë5TGíè¿èšëýu¹@ÓÓ5WÙ*Ïë)—>%wt9Œi#òН°‚ž¯¨»Þ¡flÏ) ¯äÓï¨oêÆ '­eøõrEéõŽ™§½¤(½R z/5ºöq‘%t´^Œ¶ê®öš‚oÿŽ&Ž HÁ·G!©ãHåÆúĬƒŽ®‹”“íañò¬½6wèö~Eí×4·m‡*#BDGð…Û+z..Ò Ðýî)õ•[án¤8쀭’¹•©cÀ†Cú¶. ØE»£,KgÀ†ŸÜ³~°ÑRÔ³D°GzÐôÒG¼Öz¨“Ó·Ox­ÕŠÅ<‡Ë”ðZ«Îú#%ÀÆØÕ %#`£€|PÚ °G¥†åþ$¼†Ü‘­”4Á5”¾)Bp­cÞo"â5ô2ùù*«Hx±×«©^CŠªžnDx­:k±ò„Ø*êzYBlý ;'ÄÆ.Oå"ÈFÚ˜ űq­7›ÒAˆ­ê±G b«0T×bë%‹uS!ÄÆÏBEBl½d²HBl\34Î&ÄÆï¬\7#ö˜n%`c¨yÑj즻í-"¶ÎfÍ>°1$OÖ>G°‡¿‚Н±¶'˜AÄkŒ¹TLx+Ƽֵy¨ áµ>´Ò ®õŠ*RÃl@ç&F Æ/B™ jüL5ž²@@­‘vÅDXjü.ˆhó`IŒè Ë`Î÷ä¦;ZžG6"#õó¸b¼ë‹½2NË;|yåÞXÃYjÐF¬ï¨¡0±Î±<ÈwbLjY·/m20žÛF­Ÿ ¶Që+¾3µ~b-ŒZËXئÖW¬ÒÀÔmšçþG^-'¢êqgÌ«[‰9ñÌ«q¹lEJ˜W·GmkÊb̬1æi¡Ì¬‘`èm¥˜Y7\Ä’¡™Z#vMnÔº¡®µbj­o±ç˜ZCw6ÞÃÔº¡,ˆÉfL­‘aëá7L­åÙ6o½ÄÔ²'G2µÖ`x«/AÔZ~äQ¦ÖÈAµÈ3fÖPÑ=#›©5îÒ› 1µ®=Dó2³†t¾êFíÌ@êGcfÖ¸K/œÀÔº]±o Qk\ÒÛ_1µ®•¾åD­ÑîÓ‚T™YËØàÊ`gf–éá°GÌb¾¾PLªqá“M¤ºŽ泎ó`Õ²·77ùõÞàòÉX¦œj¬ÞhŽÿÃÑþà?¼ƒ3>Ìl‚¬/ðÈLèšèЬýùmô,ú 3×O‰²¶È¹ÃþçqYv­rÍ\ÿ€0[/|ñåpñ ¸œf+ªL\¯œ&…Ú|R˜­·|›s¾„ ´÷¯)ÌFTp:b< tΣ­)kÚ´JœroNsD1ËßôÙí&>!™å¥ÐnsþÞüló?!ÒFó¾»¶’Îå:jtzÆÚÖMsÂèô&6£ã›ø€Ñ OË÷Í?htŠa?Ûü?C©-åESaÄBøO)µÛ$§”ÚmšSJ-OsL©Ý¦9¡ÔVôiªO‘ÕóBmŠ2í¿ÏõèVÒ†ÌiMˆTGX nAݲëÊ/Е&g0sqË`ô&ƒ°µªºJt(=ý è=ÏŽ÷U/mV•o4Þ»_ S÷Á¤…Ó^„Ü©Wú6Ï® ’O©ÈÏœC÷Õ‚÷_,>”ˆDTºQe%M•wH•±èÿ‡lz­œiÉ«ÔbgkLZ=m`Cßv^›g}­0ègÓû¾È³”C–Œ‘g iB檕A¹ªÜOº§¶|yÃL97DÝ–»É ·)jLò´ŽZ‘ ±É§à¡úš;>óJ­è´Œ‘vû†Æª@´¨Ý¾_u¢¼o8pnðægŠÁ®sÈ`ÒJj¯ÅÈ{ô¶¥28Ô[Ĩ›z+K»´¢ššðž-…[µmô°á: cºhdŒÜ'N»ï¼)¸!¹J¡àMVEÒ5r¬Z\MM»ÑŒMVå[(Ö³© ±zûx¬¿ŒÁ2MWkU»gGf'ýV®éÑ2˜¸Lq¨S)ƒU{YMã}ä½ ;Šs/Õ •Á´5ó^ìd¨r­âð*ÝZ<ÚL7…¶”PðXÄõ†2F*®\Óõ¹§KûYMÓ•ÁÛÜ·2ˆla3Ý'ä§Èé¸)¶]–> ¹oH—1Mï]Æ›¼–€Vmj57EO›eXUòXKoFumã;Ä7T×îîË?·:¬ÀC 6P.ô7Üèårç†çè¿ú}3žãž]c<ÏT¥qÃóü†NОãE C€ØópÏ›úo½.á9+Á 炳ëŒçCf oaÄsh¢ù±&Ç„ç㇖MÂx®u”=N„Wõ’áŒçøaõ„tÍ\DKÎþ Ï1¿Ð1_ É èšÃçQ2б8/~Èx®k3i”á·ñxŸlÆs Ê[6“·Îq!x†á¼)lØ;Êp.“s,¤ðÊ:"t•(ñö(0¬«Â.¯ï²§J"o‰Õ•çX£AuÝ€>hÔ5¯º‡/k#¥Wh`ñ­‹¨Ž­ó´> endobj 8 0 obj << /Type /Font /Subtype /Type1 /BaseFont /Helvetica /Encoding /WinAnsiEncoding >> endobj 7 0 obj << /Type /Pages /Count 1 /Kids [5 0 R ] >> endobj 9 0 obj << /Type /Catalog /Pages 7 0 R /Lang (x-unknown) >> endobj 6 0 obj << /Font << /F1 8 0 R >> /ProcSet [/PDF /ImageB /ImageC /Text] >> endobj xref 0 10 0000000000 65535 f 0000000015 00000 n 0000000145 00000 n 0000034273 00000 n 0000034294 00000 n 0000034317 00000 n 0000034747 00000 n 0000034616 00000 n 0000034511 00000 n 0000034674 00000 n trailer << /Root 9 0 R /Info 1 0 R /ID [ ] /Size 10 >> startxref 34828 %%EOF blis-0.9.0/docs/graphs/large/l3_perf_has_jc4ic3jr2_nt24.png000066400000000000000000003004061422157504600233070ustar00rootroot00000000000000‰PNG  IHDR¬öEYa )iCCPiccxÚ•‘gP”‡†Ï÷}Û m—¥ÃÒ›T) HYz•^E–ÞY–"bCÄDiŠ AF¥H¬ˆb!((`A³HPb0Ѝ Ü¹3qîüÈóë™wÞ9çÌŠ*’*àû¹Ø³CBÃØð ‘¼Ìt®'ü#Æx ÿJtL&V Ÿ—Î ¹ •#H Ç€•”.@Γ€ÜfÜ_>̨¿|˜ü?@¢Å}ãQßø÷¨pù‚„ؘ\¶Z¬ '’ÃÎôs±g»98°}øi± É1ßü¯Êÿ€ &Wà–¾…Ÿ/`ÿßPcC##øûï|„5ø¿ÿ€oziœEìÀßYT5@÷é'gjÇD ºîñ²øÙe8‡ÏÁá+ñÍøNü ü(~ÿ@ °šs‚+!”HØJ(%%t®† S„E"‘(CÔ%Z½‰‘D±ˆXMK)Hq¥b¤öIµKH-IËIÛIÇHKwHJ–aË8É$É”é–y&‹“Õ‘õ•Í‘=&{Cv^Ž)g%Ç“+–;+÷D•ב÷“ß*B~P~QAQÁE!]¡ZáºÂ¼"KÑN1Q±Bñ²âœCÉF)A©BéŠÒ+¶$›ËNfW±ûÙ ÊòÊ®ÊYÊ ÊCÊË*š****ÏT)ªÕXÕ Õ>Õ5%5/µ|µ6µ'êduŽz¼úõõ% M`½Ý³šÒšnšyšmšZt-[­ ­F­‡ÚmŽv’öQíû:¨Ž©N¼N­Î=]T×L7A÷¨îðü‹5©k׌ëÑô¸zÙzmz“ú,}Oýýný7ja  ¾š&6>5’0r7*0ê5úÓXǘg\küp-}­óÚk{Ö¾5Ñ5‰19fòÈ”aêeº×´Ïô‹™¹߬ÝlÎ\Í<¼Î|œÃäøpJ9·,ðö;,.Z|²4³XžµüÃJÏ*ɪÕjv溘uM리U¬#­¬…6l››ã6B[eÛHÛFÛvªvÑvÍv3\mn"÷4÷½¡=ß¾Ó~ÉÁÒa›ÃUGÌÑűØqÈIÂ)ЩÆé¹³Šsœs›ó‚‹©ËV—«®xW׃®ãn n<··ws÷mîý4ž:ž|Ï^/ÔËÝë×Äzõõ©ë»½ÁÛÍû÷3MŸ ŸŸ} ¾>¾µ¾/ýŒüòýüþ›ý[ý?Ø”< Ô Ì ì  j Z v .†„l ¹*šÚF k[Üà´áð†épÓð¢ð±šs7ÞÞ$»)yӥ͢›#7Ÿ‹ÀGG´F¬DzG6F.F¹EÕE-ðxGx¯£í¢+¢çb¬cÊcfb­cËcgã¬ãÅÍÅÛÆWÆÏ'8$Ô$¼MtM¬O\JòN:™´šœÜ‘BJ‰H¹*‘š”ÚŸ¦˜–›6œ®›^”.̰Ì8œ±À÷à7g"™3{LAº`0K+kOÖd¶MvmöÇœ œs¹â¹©¹ƒ[t¶ìÛ2“çœ÷ÃVÜVÞÖ¾|åü]ù“Û¸Û¶#Û£¶÷íPÝQ¸cz§ËÎS»(»’výR`XP^ð~wðîÞB…Â…S{\ö´‰ñ‹Æ÷Zí­ÿ÷]ÂwCûÖî«Þ÷µ8ºøN‰aIeÉJ)¯ôÎ÷FßW}¿º?vÿP™YÙ±„©ÆÚuÈëPW»¢¸âýá͇oWšTÖ¡É:"¬ò¬ê©V«>P½R_3Zk_ÛQ'_·¯néhôÑ‘cvÇÚëêKê?O8þ¨Á¥¡«Q£±òáDö‰—MAM?p~hi–m.iþr2õ¤ð”ß©þó––VùÖ²6´-«mîtøéû?:þØÓ®×ÞÐÁê(9g²Î¼ú)â§±³gûÎqεŸW?_×Éè,îBº¶t-tÇw {B{†/¸_èëµêíüYÿç“•/Ö^’¼Tv™r¹ðòꕼ+‹WÓ¯Î_‹»6Õ·¹ïéõëû}û‡nxܸuÓùæõîÀ•[Ö·.Þ¶¼}áçN÷]³»]ƒ¦ƒ¿˜þÒ9d6ÔuÏü^Ï}‹û½Ãë†/ØŽ\{àøàæC·‡wG׎=>Š~4û8ùñÛ'ÙO–ŸîœÀO?{Vù\þyã¯Ú¿vÍ„—&'_ø¿x:Å›zý[æo+Ó…/é/+g”fZfg/Î9ÏݵáÕôëô×ËóE¿‹ÿ^÷FëÍù?ìþ\Y˜~Ë»úgé;™w'ß›¼ï[ôY|þ!åÃòRñG™§>q> |þ<³œ³B\©ú¢ý¥÷«Ç׉ՔÕÕÿB,¾;E^ cHRMz&€„ú€èu0ê`:˜pœºQ<bKGDÿÿÿ ½§“ oFFss0ˆÚÿR pHYsNNÆÊ/¥tIMEã$9·-ç vpAg’Zó!%Õ€IDATxÚìý{˜#gyç‡CŒíX¦Æc4vL5 !âêL'!@È–L–ƒÉö‰¼0¬{— ­{Ó¹Þ,R蜓ÎJl6i¢Êž`òUèÅæ°Á*2á¸îI!á ‰I`Œá‚.¬Á&†€~<}W•JU:µ¤*©ïÏuéšiÕAUÒý<õÜçcív» †a†a†a†‰‰ú†a†a†a&VX†a†a†a˜X +Ã0 Ã0 Ã0 KXae†a˜ƶm†õe0 Ã0ÌD`…•a†afÓ4‘N§£¾ æ£i,ËŠú2f*°¼OVX†a†a˜‘ÑuðÌ‘å}ú<ö7ó73ê‹8êØ¶Ó§Oã½ï}/LÓÄþàâÒK/u¶kšæ I’ ë:E†MÓ`$IÂSŸúTç¸b±EQœsÛ¶üÁtÎgš&~ò'räýfPzÉxØ6MÓ`Û6dYvΣë:>ö±AQ–of&˜”쫪Šr¹Œý×¼ýío=ÎmÛÆoýÖou=æ0ô’×÷¾÷½ø×ýW\zé¥e¹KFé=ž³™Yá0ò.IRè¼Ïr=ìaÛ¶±°°àäéºÞÚU,Q.—mÙlº®Êå2²Ù¬sžÅÅEhšæKÛmÛ†mÛÈf³H§Ó0MÓÙ^,GÞŸa¡—Œ÷Ûæ—·ÃÈ+Ë73m&)ûù|>ÐÊoÛ6Òé4lÛv › sXú­UüÉ(ÏÙ̬pyÿô§?ÝóX–ëi3‘R¯×ÛÞŸa¿­ªj{oo¯½··×ÐÞÛÛs¶Ë²ìlÐÞÝÝu¶U«Õ¶$IÎßÚÕjÕù[Q”v.—sþ. mUUGÞŸa¡—Œ#ÿ»»»míýýýv»ÍòÍÄŸIÊ~¡Pèúœýýý.¹f˜qÐK^Ûív[UÕv½^w¶ûe”Þã9›™#ïýŽe¹ ö°F …|åóy'¬·^¯C–eèºUU;ÂÂ2™  ,˲SÒû7Yi¼çI’ IÒ@×3èþ Ó^2Þo›¢(ND®ëÈår2ÉòÍÄ™Iʾªª]ŸGVzzN0̸è%¯aÉ(ÏÙÌ,pyäX–ëáa…5bdYF½^d³Y;v ù|€Iò,ضr¹Üñ z@0L”ô’ñ^Ûa ñ.ÚY¾™YbÚ²¯( …BÇyfô“W†™'#ïüðøþúëñ;¿ó;Q_Ê@ðüâ4^ï¿ÿ~¼ñoD*•ŠúR‚çïø§1;Êü=7 ëUW]…ç?ÿùX[[‹úRÆÆêê*677£¾Œ±±³³ƒsçÎÅâ7¢k™%.»ì2–‡˜§1»ººõ% Ïáñ'NcvÖæpž¿ãOœÆëêêêÌ(«Ïß³@œÆì(ó÷Ü(¬óõ\Nœ8õ%01båaÞÆ,s8æMæqÌ2£1²0oã•9ó&³>fYa1ËËËQ_ÂXI&“H&“Q_æQæmÌ2‡cÞäaÇ,3ó( ó6^™Ã1oò0ëc–‹.1 Ã0 Ã0 Ã0±„V†a†a†a&–°ÂÊ0 Ã0 Ã0 ÃÄVX†a†a†a˜X +Ã0 Ã0 Ã0 KXae†a†a†ab +¬ Ã0 Ã0 Ã0L,a…•a†a†a†‰%¬°2 Ã0 Ã0 Ã0±„V†a†a†a&–°ÂÊ0 Ã0 Ã0 ÃÄVX†a†a†a˜X +Ã0 Ã0 Ã0 K"UXšÍæÈÛ&ΰ|3óË83¯°l3óË83K<.Šm4( Î@XZZB©TB"‘4›M 4 €ªª(—ËQW 3,ß̼Ã2ÎÌ+,Û̼Ã2ÎÌ"‘xX …Òé4LÓÄÙ³g•JÅÙ¾±±d2élo4Û&ΰ|3óË83¯°l3óË83‹D¢°6›Mœõ©×Æ0^’É$n¼ñƾ²: “’o@,xX¾™AXZZ•W^9‘sóÎD ­5Æ=‡óüÍÄš¿'atäù›‰šQ×àCyXið}H«Õêë]„…Æ?½±ód}ô†%4›Í¾†)‹Èf³(‹Ðu–eul×4 ù|¾ëýqÂòÍLÃ0`Ûv×û–eÁ0 ‹E†1Ñk`gæ–mfÞag¢Ä4Í‘Ja%/êêêj‡rÚl62Øý¬+ªª¢Ñhtäqœ9s‰DÂÉ‹]ZZÂöö¶³Ý0 ¤Ó驱ÌáÐ4`ص³mÛ0 £C©Ô4 ŸwÏõ{¿÷N¼ä%oÆk_ûWxûÛ¿„·¾õ¹\Š¢À4Mäóy,,,àùÏÿ\yå;ñþ÷_Žÿñ!NãþèðÈ#ŒýžY¾™A›´ Ã|‹E,..BÓ4d³Y,,,àøñãX\\D:F>ŸwÕr¹Œt:=‘€eœ™_X¶™y‡eœ'd,ëXXX@>ŸG:ÆßÿýßýYC…Àææ&ŠÅ"N:@$Ïnmm!•J ÔX8•Ja}}«««NXÏÅ‹±¹¹éì³¶¶†ÕÕUììì Õj!‘HàÖ[oè—ÎŒ—}è~¬¯/~ñ›¡(¿Ë’¶ üÕ_ý®ºêœE»eY°, ²,;/1Aæñ?þÇë‘Ëï~÷7pîÜ{‘ϯãäÉŸÃ÷~ïkñ¹Ï=Ãø0Z­ïÇÓŸþ·PÕTU|~&“e²L^)¦ ¼å-@"ñÜsχñ•¯˜(Æ{ß,ßG Ã0 ’ÐyÞó¾oÛ6LÓt¼£²,ömH’„B¡EQP.—a†#ÿ~dYF½^‡$I_×ý¯ÿu"÷Ì2ÎÌ+,Û̼Ã2Î Š®ëκ$“É8k]×5$IeårÙq4I’I’`Û¶³ÖQõzÝYß¿á oÀ³žõ¬¡®gh…5‘H`ssFñàS§AY^^ÆÒÒRGùloˆB*•ÂwÞéxq9&~úX–ðlærBé\ï' ŸiJew;A!¹¿ñ<üðSN§ñ}ß÷7øÂƒxžøÄ›ðÃ?¼„ZíÊиXØ·ñ±½ OyÊ#°mªª:/¸ÀÞW]$ PÀ4lØÝ…£8d2töÇâ-o¹?<™¢4,ßómÛÈf³Î„\*• ª*ŠÅ",Ë‚ªªŽ‚Jã¥T*uœÃ0 ”Ëe˜¦‰\.7”BÚUUqóÍ7OìþYÆ™y…e›‰ MÓ`Û6EÁ£>:±Ïa?±Ü­Iü†Ó4¯©ªªPU–e!›Í:çÌd2P…Ba¤5‹ªª¸âŠ+pîܹ¡ŽJaÝÙÙÁêê*Ξ=;”‚D2™ìOá Ìä1 Š¢tÞË^ö(’Éžóœ'á‰OÜDZcoÄe—5å¯\.ãܹ×à{¾çÇqýõWàÕ¯~>ó™÷à}ï{Nž|!vwI_EQÏ/A’$¼÷½UÈò!ÞV¯¬kšx¯PÊe ù<ÉüºcÁé…ª^G—mµZçù½üè>„sç&÷@`ùޤTzeȶm‹Å®ÉÖ²¬ŽQY–Q(:Ž5 ù|…B¹\–e¡X,"ŸÏ£T*¡Z­t]ô0˜UXÆ™y…e›ZìK’„ܶ̕m”ËeG!EQ ( TUu¶«ªêx >ô¡Mô:YÆçR2ƒ¢¶H‰%…–Ö!´o&“éZÇÆŽ8C)¬d…1 ËËËQ_ûL¢ëB1«×'û9ä٠ò€w¾óø³?[wr>3™ r¹^õªûqáÂy¼øÅŸÇ/ÿ²ŠO|â8>þñ?ûßý=÷£c{û“ø•_y2žýìg#›ÕðÌg>¡CQTU{{{Ç ¥¨VÅw¢ªÂšÏé´¸¾Ý]@’ŒÂ ëG òRf2d2™P™¥0[šhMÓD¡Pè;‰jš†r¹ I’ ª* …‚3‘S¾3_UÕ.Ë#åŒÊ² I’ãN­Vsö“eµZ-ꯒa†™¦i†ÏÉJá“ôl(‹e–e!—Ëaoo¯ãGÏ5Û¶}Ñcýûú2óCP:E4Ò €³F·mÛ Ëà8œTUuÖóÙl¥RÉ1šÌC)¬‰Dkkk¨T*¡Í…©ù0L&#5ʯì‡išŽE.ÈOBë]È“ÀÖëõ®ý-Ë›ßüüñÿ4.½TÅßýÝáG~äÇ—Ïçñïþ]ïÞQ:½ÊŸi ¥rw—î'3Ò€ÈdÄK×Å÷¡ªÂZ«¹¡½cŠŽdbJ>Ÿ‡$I(•JÐ4Í)ê@‹ʇ )EQœPÛ¶‘N§!Ir¹œsNïäN µ-—ËNq.¯Â ÔÓ™ËåËåœñ5¨÷”a†™-,ËrrñÈHIŠƒW™ í^ƒg.—ëz>”J%gß f=ʆ †Œë½ 꺮;ë÷L&ã„âÒÚ‡äKUUT«UGI¥uàmÛ†eY0MÓ‘]Û¶»Ö8óÀÐ9¬€­­­Àí¬°ö‡µ^Î!²ØY–å)£4òù­V䤢p1ñvï­¨;ˆ—ȶ…ò}É%oÂîî{–˜‘1 Åb±#¥T*uõµÄ9Ã0Œ—|>ïD†MÓ`ªÕ*Ï1s y:)'¢h(¯úB…B¡£Â){<™qáõ†zÓ“HÞü5‚ ÜÔãÇ;E·Ž"¦)‡eh…µR©`kk ËËËXYY ª™mll Ñh`}}=êïfd £3?Ó«ãÑÿ%I(´å2à‹ˆ Å›kêZ;÷¥Í…2Lвm»?´W‘ö¢ib{0È2åɲ²Ê ⢅¢ß*È#æèà ïæê¡=(º®;ÏKËEE­&òÞÓé4^óšÿ·ÝöýQÌx•Lon(=C¨š»·R»¿µ›7¦Õ9‚ Z÷ŒËJíÓȲDçÝÝNêþè:|ûÛ`˜²GC)¬Íf[[[ÎÄâEUU¬®®bee¥go§83hgŠBXX ¤÷0 :\*‰m¶m#ŸÏã²Ë’°íj‡RIÏ|šÇéë¤0ä0òy¡œærb’3 ¡<çrâºt]œCQzub‚Š$ùsJÓé´êÂ0L4PíÃÿqFÆjš8§e‰ç…¢¸˲xÝuW¿ø‹Å—¿|W]u¿ök?UuŸ}þ"!Þ Þ€¡e OD¡H’…7¼áoñÅ/ºŠçÂÂqȲJeozÓ»ˆ{¦û/ H&oA.÷llüžøÄëñ¢}!ꟇéA>ŸïhCï(ÏT×u”ËeȲ

å?S¯ÜL&Óâ;*£yŒ+š†Ž¹ȹç=Æ4¿ÿû+±²ò9/ø\C)¬.\ï¿´´„T*… .̬Â:Œ!¥PVE¾ÿû¿ˆï|ç­¸çžÆ•W~šöhšxp‹–…МW¯Â*Iý•ÌRI„úpòQÉ3{P‹‰-uÌÀP©tå÷5Mƒ¢(]…•˜ñbÛbBW”ÎVNŠ"¶e³âß ›e‰UÏåÄ|R,râY„RA¼Ï!Ë¿g&#øºÞ©ÀzWçe–UÄ?ÿó·qà ?ç>÷2¼æ5ÏöÿVV…$YÈfCU¯q>ײ„Lf2€eñ—yVV*ø¥_ú!üüÏÿÞúÖŠÅâƒü^ûÚ—|žŒ—¾ôqþü·ðÎwþ´ãU ŠÅ"Tµ„W¿ú7ð‘ÔP©ü6^óš ÜtÓ€o|ãøð‡/À4¿…lv/{ÙåÐUsáÔ©N^Øÿù?ÿ'yä$€WDýÓY(|— ï(-ØàÙËÎJIc¦yQUUuZÂ(Š26Eu Úþ²×ñãjI‘šæ¥sÓ³C×Åÿ]cfgg‘rY¬UDÊâçÑj=:Ô5Œ”ÃÚjµH$ºÞ ëÍ: ‹ƒ‡øîƒô­oý66~ozÓ©Ž>]‹Ær¹·":¬> IÝXê_:®8qæèP.—0«r¹ìxYËårh;f|”Ënè?{Ëd\¶Zíœüi*)æo>=ý ««QßÓ¯’jšâ¹Q«¹¿g¹ ¼æ5_…i~ñ ²¶xß0 ¼éMwâÁ/Ã÷ÿ÷ãŠ+®ÀÅ‹‘L~ùÈ]e¥R ²¬à¶Û¾Óü>ð,¾ó¾þu _ùÊ·‘LVð?‘À‡?láMo½EN UÞ1øÇüßÎsí]ïzòù<¾þõ¯ã?ü‡âŽ;JPUº®cuõÿâ±=‹÷½¯3ŒÎ²pp-ŠÅd`’aÉd2¸þúëqîܹ¨Â# u3ðæz«óR1&ïŸmÃÓÚÊØ¶Ý³QÔxCiÃ.‘":ÔZÃ_+JEÎ0Iê4–RD' >ËÞî׫h{.ìì<Œa§ï¡Ö¥¥%$“I‹E¬¯¯;žÔf³‰Ó§O;û̶Ým©öÖÉ4MüþïgqçÝqî$l@°wd°²Ê …dQ!€……X–åR:ŠáYƒBžQJ XXèT,s¹îH±Ø™F`YbÁÒ«ƒ÷' TRf™Ù‚~ï\Nü~¦)”Šâ÷&Zð¾÷=ŠK.Y¿¨:="iŒ %Pvþ¾ùf’ôblm½©ãsßùÎÜ`¶mãOþäóxùËŸYÞtö¡Š«Ô†¡WÿÉR©„cÇþ…ÂïàiO{"¡@>ýéáÊ+Ÿ Ã!ËîÂ&Ÿ ˜\.çTüefRV¹â©‹aôž›)}Ëk’¤N¯ª¦‰}ØV<~¨p›i ã\uZÜ!/f¯z9Š"ÖÞtFÛrDQW ‡óÔR½ïñªÅå½Nº# gýžaÚÃJ™[|<“É$677‡=]lË_Õ4Í©ê ì7a“G• ŒL\ñzW‘#FE–Ø»*ÔÂÊŸ·Q,º9~€P:½………ÎÉÛ²Äî´åá&ê;[˜¦ë5§Bz‹‹âoò¦& Ã}ŠË² M“ñá_À£¾Õ1ˆZ–å´ìð†YÓ4^’$¼þõRàûÆ[.—– açøã?~}×û?ò#W¸Ò )–e1Nêuw\°r3[”ËåŽ>’œI¬¬ºPZy ²Y·Ž7 ú£¡å¶AÏæðк¦T*ÍŒÌjš“ÅEWvüPj¢w{:Ý©w è§ÌÒZgØš8¦Ùý™‡ OZaM¥R¸ë®»°³³ã„ãœ/þ¦¼ÐƒèH§ZwqÖoôÑ 0ò¬¹Ìü@²K!Ü$’$äú§-hÚ‡iš §išøò—ŸÛV±³ãŽEY–'žSÞKQõã­P_. ™Wq â~÷ö8`V)‹Ž‘DUU(ŠâÜŒC¤Ãæ÷bq_(Þ˜ÏwFÏ”Jî(z$N¹©×'æKo] åÄZƒZiù¼ÙLFÈšw;MˆLFÈœ(v'ÞóŽtšŠÚuÏÕ$Ÿ£è2“(ú:Rk³ÙD"‘ÀÚA=â4›Í™-¶D‹ÉÎ÷„²J1îµZ éƒßb±8Yëb€ îFÃL MÓºZð¤'ý>>ñ‰Çw)ŒÞ ®W¾7u]M–jÃp«mA…Ç‚&ÙA>ƒB1½÷X.»UX)üm1ã¿]w(–%î‘óóÉ-…ƒ“"G‘;´h²=ñP?ÿó:r¹\ìCÓzA9xþg(-šX¾gêwJëMÓ`šf,U"s³øx{Öû¡HYÇ–Jn½‘Ñ¿+ñ™þèï×äÝV*¹²ÌQx“&ŸÏO½Gsæ vvv°¾¾Žååå¨ïi(¼– /år¹Ã"CÖíl6‹z½>9eÕ>xY`…•™TØÛÄš”¨Zí ]:ÝÙnITx VJ³ÙÞ-Âz S¸Tµ*>׿ dÙͧsQ!"ª šÍvæ’RŽYÕ½C˜ ‡]Dx´ ¢÷2®9Oض+‡ÞÔÊ—¢W.—ëð¤N{5n2·å¬1Ñi˜0MÅb±£ MÜŠ'‘A•òõèòòy7’d“Âò½9uþÅ>AŠ>¦¨¯gŠ 1TÁݲ†Kí _® <¼½Ÿ Ãpºu ðEXýäóîs¹Ðo0ñS*¹2 t§0’$ÌX“˹Ï(Š‚ñOJmØ5Ä¡ÖV«…J¥‚••Ç» ›››ØÚÚrÙA=­TY8•Jno4H$õÜÒä…ŠÎø™Lív{b×0!Âg#Ì>zH¹WúìS^ÆA¾ƒ Ðv/䥇w­ÖÞä}¨“2I o± oØJ±èæï‘‚é}‹®‚I•r½ùnõº› Oí[r97,póƒ€Î‡ƒªûûþûv McýE úæ‘¸Êø$1MÓ)€äUVÅX0ï.+ 3“75 ´p§pàyã(É6åøY–I’P­VcãIÕõî|8ÓsªªºíÉcINªHJÞÔ^Ñ8T‰æjUíôÆJ’¸oѤZMìã넸Tž7§t=ê©jšæÐm•ÈpNk“°}Dõóàídè –sax{k“œÓšÊ¿Fé%cd¤ C–ÝâŽa÷ä7ÞÄ‘¡ÖF£V«Õ¡¬+++ØÞÞ¨k«ÕÂÆÆŒ“W*•Âúúº3hšÍ& …8Â7 ,«ûaK½™&yPÄ<«³`xï—k[>¸Ã(z‡Gç!¾³°9©÷ûžRhCœä;ˆ –5þÉÎï}ôS«¹J+µ_ñ/(ÜŠÚu%Ú 7#¬]“·]K’Ùo¢ö2íÈKonß¼-èã.ã“Â0€••ã'~ÂD:]Ä·¿ý;ÈåIÒ±°P„¢(3æ;ì÷Q.O¯þ48j²­ë:t]Ÿj‹Ãèìߨ wôæˆzŸTyÔß>p˜y—ö뵿¢tËyLtú¡™GWåjE2EF‘ r9áa#—ºE¿ˆ3ot€· &ÌcÆy²‹/´_¥RA³ÙÄÙ³gaš&’É$¶¶¶œíH&“0MgÏžE£Ñ@¥R™È@ÉïõËLÊ%bB(Yaädƒnd¬ƒ×¨Ø÷aöØG†P6syzíÞë Ú®C|§½®sÌÄI¾ýø[Ö˜fï–NaH’ð€V«^Q?T VëÎÓÊÝcT8–ôqgŸ¶ ¼úÕMüäO^ŠZ­U•ðoü8t=íäû‰÷çÌ:ÑIêÎ×›uŽ’lSøo­V›Š²ê-DD!µý ¯©¦‰¿m»ó8Êñ;,ýÎÁ2_g›%ò¬ê!ëN]k¦ Î"é´ºëm_E_‘Ü‘Ç[¨éd(…•Â}766Ðjµœ÷ÉZ 4´À»ïöö6Ö×בH$·ß~;Nœ8@Xvvvv°²²H$X^^žX› 8ÇD½«À`Ѝ áY £Øgû h}®Åè³]ƒðXöš2è‡KÞæ^÷YB¸²)¨A(ÅFÈö݃kôãøã'îú‰C~‰ÝÄM¾ýhšÖaŒ¡âE£0¨…ü(3uk©7YkBÄ]ÆÇ‰¦¹ý´mÛB2ù2¼õ­ÿ?"µT*¡P(Ä*„ršyf™£$Û–e!ŸÏOMvËeW Ê£ ‚ÒJ(L’R@” ¦?ó&ã¶m;r|e•<¢€»¶ ªoCQetŒ÷x »ØVÂJu@üQcT±ú>Jbä>¬ÛÛÛŽrJqî›››ÎƒB R©”bœJ¥œ0ã .8Û‰T*…f³9•/DÓ4Ôš²tE-l¡šîqü"„’ÕKgÖ!”±^¡¶½Âum*q]Ç÷»†ÚÇëÿÍ#Ń÷ƒ®Ó8¸ÎBÈuz¿gúœ «ý2: Y]ù÷Wâ?ò (cN޳|Û¶ ˲: 2¹Üœ…«R%‹YŽ«ñÆPnV¿§X±è&]•ËøÙ¯}m"—g'Ôʈ¢{ƒªM%oêQ`Þe›<ª–e9ùÕÃʰ¿XØ>~ÝAÓ:ý¼Hd{óö,¥¨Tö@μÉ8µZ:ì\¬i2t:ÊY&ÙN§ÝÜР¾êArJmò¼µ8YöÜ2‚¾ k³Ùtpû°†áþòò2TUí«¬nØðêêª30.^¼ˆÍÍ;ƒ¢Õj…~Æ}÷݇»ï¾Fé^<ÞT#ëÀr(kcB1 ³Êèíu¤µP/e´ŽÞJ¯qpAç0MÀPÄ5öònz•@ÿÚŸ,F2\/hÐ÷@Ÿo [a5àK*#8¿”Îë?Öò?ÈÚ?xŸ&ŒäƒÀêÇ?~ÊSpù‡ÿçÊÿƒWà'“’o¸ÿþû±ºº UUGªÆ­ë:¾÷{ÇñªRe¸¹*3•ËâI0H=vê/0‰¦¨TB2Èêë-oéU®5Í]íQ¥*2ýÊrp‰a*—œÉ8ýDVWWqþ;ßÁÍøšã6‡O¯²ªë:òy Š¢L.U„ŠJ¥‚{î¹Çëyã<òD•J¥‘÷Ô¿º×¢šž/Þi” ;ââ¢gþiÒ¯ b_Oqû¹euuçÏŸG£Ñèµ8,ó4ëºî´[:,~PÍ oou@üß+ÛAòí­,Mçð·Ô;jlooã]ïz×Ðó÷@!Á[[[8uê*•JGöÚÚÖÖÖ°¼¼<² tZwîºë.Üu×]X^^Æêê*t„ûé•#{ýõ×ãæ›oz x…F×õ×o'ïeZŸí4î¼^E¢G9|ýÝdžxZ¼¬|écÀ/½¯{Ÿbø¿ç…‚ØKa¥JÅAÞM¯73(4GólWœ+KJªêù ÛvïA2ÝïÉ x’X$dh x ïdcA(°êAüÐÂðù?IµžÕ~9.yñ%©Ü9)ù€ë®»›››#/vΞý".^\šË"@Ħ^f|ÛŽŽ¯…W~¼PÜO6ëV‘$± NöÆÿPsÎ…qnz?îöì º‡jÕu}S_žÝ]±b ŠQ¢„bO¶ÍÍMÜxãùšã6‡RVs9‹‹‹0 Õj¥yLFžQÖÖÖpûí·ã~àÆzÞ8Ï߇%›ÍvµVªˆM‹í°PGªŒJá¼@ïj©Õª˜~É{J¶< »æAL£RÇÍßãVVù™¿-ËB±Xœh;Š& üý¦©…^ØãÛw·gŽËËË#Íß}Öd2‰r¹Œ;T ÛÛÛ8uêTG…±a8yò$tT¾õÖ[Ñjµ°³³Ós€Ž»´6•”&LÓ<œc-@XTš¦Pu„{_ Ûžû1àó_‹î þãZWOz§"X,º}Bþèz §w}¤;I±Z.œ$[ošbAí]ÿæ7”F+¬¸ÞÍ KëœæÐrxÏ7}_<€VË­þ›3ÜżaŸü¹nSÕ¿ë6ׄ} èšn–;µ·€ß~¸äÍâóm[<å>ôkÀO¤Äy/¾ñáÑçÄI¾ýÜ}÷•ÈfϯÂJPéàý} Ý¯½½`“)ußÝcƒ¼•‹‹Bs šãÒi1fÊe±}qQŒOï8„‹`wW|v½î¾ö÷ÅûA]¾{–øE•o¦Dœeü°¸-’td³Y”J¥#›Ÿz™WÙÎçóeydƒ<)«Þgå²;^*CSM‘@øEyЦ)¦ÒÅÅðB5< ϬË8å^§ÓiÔjµ±ÌÍÔÊÆ®‹åœz{ò®½›Z÷‘ˉ%È,g)Å…¡rX½qâ†a`gg[[[H¥RXZZÈr×Ë›H$œíÍfÓÞÿMë´ú ¤°öÊ ýì—€½:°ò~àSwºï—ËBÚÿ÷߹營» ¡ˆ•óÀ½Ø{"ð4ˆ§Äâ¢ØçŸž ¼ÿ—r¢#'ÓY:ü&`ÿ¢ø|ºQIv“A.Y^þZà¯=ñ 6€·_*¼“Û«À#/Œ7‹íÞFf4ø¼_—m«¿üÝ)àyºÊn߬¤{­E—ÿ!°°åÆJP¶¹‰Åßs^À{<©…*°´,'ÜØ YJ0>ò`÷u€ôºÎï—Öú°ÿ—ûÀ¹±‰’CœäÛ‹iš¸ôÒ—ÎWð¸ñ7Ç£|P?~3¿e¹]»@J\e|ärÀ™3gP.WP¯×YQ=bÌ£lçBã‰ÒõîÖb¥Rç"ß²Ä~²K­=(C£T1Þ0æÜ˜fYÆ-ËÂââ¢cHßyƒå.“q'A­÷€ÎžõÌd¹­ªªX__ÇwÜååe4 œ:uÊ 7#•Ju•ЮT*H&“ζ¥¥%loo;Û Ã@:Ƹ¡æ¾œ"=1Ñ»rîüð’gW¾Ó}ϲ„f\«ô»"TV‡PÚüüŸo?ÿÓBú_ðl÷}I3þëÿø‘”Z­vøÔ=a†jqC>• /©ßëÊLŽ¡<¬;;;XZZêøÛ0 $ œƒ< ?½<ö@æõîg¾å[À5¦Pl³rwµ^Ê…Íx^^d¸† Á9¾Ô7Ö°÷}ÔjkU–Ãò\ÈàP°ƒ‰ùöòѾo{Û/Mô3"#Ÿ?•8bDe|,Ë‚®ë•R÷ñõ¯G&ãVœœFOÊ#CPÉØa £¯iºîUÅ%/|áD.wÖe›(¤Ã•Éôþ K¥ð=Û}âÇ,ʸ~P9Ü•Ù-YÁDÏ@ k£Ñ@¡P@³Ù„yëh …‚&°µµ…õõõ ¤R)ÜyçŽ7Ö«²}PóišLMÓì_Ò„«8ù'árø¹œP¶χH’k^üzøÂ×ùö1 àü—(¹Z´‚no.)}@pµaÊ ÿãoýB}PeÏߦ︎ó)ÀCp²ó3>õ=À»е€ë¢¶6AßàzCËÛÃ~†4zWO¶¶‡­5ÃúµŽ™8È·ª~ý‚ VmæàÑÔ‰›Œƒm/|áßâ§úxÅ+¾]ÿT«Uض ]×±;OE£„½¡LAP%ì°…¨$¹ñ¨4Ö5 ©ÛoÇ?¿ò•c¿ìY–mÂ0 †16YÄ¡Å6žÙae¼X,Ž¥°íÏaè³Ã@ k¡P@*•BÙ“°@¹«Ô{ukk •Jeà x‰D¢ç è·ý°PO i1M³¿%Ò†ðÞÉ'³, î{(ûƒÞ?{)ðÑßè܇.À@·2å·üp«ãÝÊ¥×# t;!ýûÛ!ÂuÏñ~eq˜òÁ¹$„+¤6„ÂæS!¤ö“‚ÞëÁ)õÙ>èýŒ¨åÛ‹axøá·MçÆ§ ›G##N2Þ *ÖL¢Òh<ˆ+®x~åWžY~:Êå2,Ë‚aÈd2ì]ªJB±£Šâ–Ô Óv(Á‘VŒù¼XEær1¤¤°zÉåðÉþa|åÜ `vd;Œr¹É¾´è¥‡¯ÁÞ;]³;… Köäy…¿ý?ÔXõ}Vw2ëûÛ¯pú{­úZÝ ¯àz«ïæÜ ‡B~…↑P6{ÍG{è݈ äïø2žùÌk£¾ŒÉ`šìaezR, }§^j5—\ò|üãÏsĦP( \.£\.=7jêP[0ªdÍvœi—É”bQ(–ûûnµB!XY¥ëËçÅJqoOvé_vw MÓ ËòP¡“ºî6 (•„âªiBœØ&ÈD‰išÐu…Aúª÷€šLPS¢Wp/úzX–––:*‹Q;ï„8hÖicYžT¢3$ÀèžÜM3XŠ?ðUà#—¯»Ì}¯T YÁ!±€Øî}?H1ôœ÷šet·ñ*§fÀ95¸^Izèøî’ïÿþíÖÁ}Uî!Ha— Â{é ýÖ :½ÇÌX°m÷Ý÷¿ñ¶·ýZÔ—29Ø#Æô€ê¿b1ï÷¢ªªêä®Îd¡%j~IõÈ=&ËB)ôºÈÈÝLUDdÙ5Ϊªx`z¿ª~M„%3z#‰¥Âc³øýÇÛ¶Q.—‡ÔuaС¯¿^?½¿20ÃLÛ¶BKƒF¾P&ž—bQè^·m±Ì?"µ£…žM‡´ ôUX‰DW#áF£T*[%ÕK&#Š×úŸ‘^«Jh;ÿ—«ø—Ÿ~ ð:_{o`Å/è=z>÷ʽ$z)›~ï)]/­5l„熆ФŒîüWÿ>‚{²2‘¢ë:^ñŠ›çwÈæ&ËênQ«iZàb¾Z­Æ7˜V[t}þ매,ïj̽±Î#ËER\MSh$»»Ý«qâDÔ_O¤˜š¾[ïßõ_DõÜ¿8¾{›WaÍ¡ÛÛi¡S¡$%Ï{¼Ðx«ˆ‡Evy«ûJJtPDEmiÐÙ®ÆK Áù­ÞÏa+l,yÿûÿ/|ðuQ_Æäà`&„l¶ÓžA•àƒó²,ÇSa%ïi½î¾º/¾Ó´ðz`ëuÂ[*¯Ør9±MUÅ+“šM6{¸ðafì†ÅÅE(ŠÒ3w•l–Å?ãX0Íþa÷ù|ðmšB³",KÄe{ß;ÂPÍœaCij£%}©$ìvþ)ŽºÑ1‡Ä4»Ó' oújUX±^Ha]ZZÂêê**• VWWÑjµœZR`‹Å"–––bÑ\Ø å/y¿O#ëÀ¬þÞŽÿðx]÷½ÀåÏëžTÂÚÝAU}mϱZÈ1ÔŠ%0wÖsœ²)´a×Gù¶þå óôÒéÙàK>õ©kð”§<%ê˘,¬°2øÛèêºÞ¿|Ü(—ÝF€q@QÄ¢ƒ#beYÈçó(‹¨Õj}÷”›ª(bQÈ´ÀÙç0Ê!Eb¡F¡à*¶d-(—Åß^G‰,‹Å4…ÜxáBÔßN¤†1tK&²ïy#kzMªŸ©5–PÜt”\.w%ªàæý %éP9}V(•JPUÕ ¥ò`:sæŒSEx”ªt“&“/¯ÂJi`ˆpàÍ¿~©!³npg~ ·òÎWº=¢þ‚B¤ŒÒþAÏÿ*Äç©öŽRõ]áÞQòÒæC¶Ó­—®tÁ é ¢ë:žüäÿ0ßÑ{~­„að>ŽlÛvªÏ ´úŠ›VÁñ¢± N#ŸÏCQìîî%fYÍ Àm¹T.÷V6-KlÏçÅþÞ…¤$ ³Zï‡-ìeÙ £÷BÛÝíþ1ÈíW¯y…Õ²¬¡£^L³·~Å i ™ûB5MŒZ­Ó¥MPÒð-µµI$X__ܶ¼¼ŒåååØyV Ræ©p¡,wV̧0±PÒi1|èCÀ¯®¹ôRàRIüXTnÌÞ«B*òâ/Š$£3œ·ßo´&§ÏÑÑ¿ê=Îè±]Ûÿ4 ^›Ì$†aࡇÞ4ßðæúæ˜Q ÖÖÞyžŠ-Íqó®2±Á0 Ȳ<´Ê4ç$ RÓÄbn”ùŸ”UjŸ-`BQ¥pû u"K«U±o½n(7>É2Þýc?†›£ùv#'°ê@DZýº’õaû1SD@PÕvÃpCܽ ©_æ'PÍj + rT+• *•JGëšd2[ep4Oøi¦iv ï„£ªbrLœ^}ÐÄ„[²ŸF‡xS(GÔ‹ W ç5 <£= €° ¼·½ "áJ§tp?l•š;Îû.»ì2^ï2G Më4 Û¶ MÓf¯e7ˆa<˜¦9›­ÇsónÕÑaÑuWYÍ庫²š&ÐZMìG±£aSÊó^\ìN'c†fTù>rýÜÉÔúWMs‹ëùu#òª c÷žÂ@ÖJ¥‚­­-çï­­-¬¬¬`mmmª; Å¢[§"hŽ –e7ä‰Ê Ÿz“»½@Qݳ_þ'îá´ <¤aë½ ù{©†}F/úõ?ef]×qõÕ?w´&o†x¦zkåóyär¹x-ð‹Eaý&ïaˆ‡“w0k 635,Ë:b€Dl¦ñVªf±ìÍ7­Õz»áÒi±ÿ°åcK%•¦i†æc÷êr¤VÓºI¡Ð[î ±Ÿ×Áfš_”i ªŠ‰"LöÉÐyX·¶¶°¼¼ Ó4aš&–——±µµÕÕî&îøû˜T˜ÂNÎþœû^PUÿoë5hx«õzICx6ÃêWP%á^‘ä! #(<ÙOPÿUf¦1M—_þ¼£3y3 ÜE9=—‹Å"$I:tÓù±Beþ©çB:-X«Ÿe‘a‘aØv°Ceæ ªSN]¡Ð¹Ø¦ñÔ*ÛïK¨×¹×IÄ„­Í-«³UôÜTÎfÃ=öT¤Ë0Ü/‚ 3Þg‰$¹!ëš&”WÿóFQ\å(ƲßWa¥ðß••ç=ò¬R«›Y¡»°1X;›Z ¸äÏèôZúóSé½~zÃŽ%$E·×%–ÐÛ;ÖΆ™kLÓÄoüÆæ?Ås˜Pf®¡…:=w5M©ÒäD!y¥Ü z]XǃŠV0̈ù;®PtàLB7S*u{x¥»mL±Ø.)IIíLl ìÚqÕ¤¢Íºîê]sAà'— oCº^wCu…œû¿?U_Že¹E’üûP³3p«7O5‘HD}ÝÑ/• ËJ©A(£~üT¿Â t+䵞ƒZ‚PX{=Dúå-‡å¿z·sdّömüÈÜWCÙx°,. È8P 3U‹žr¹ìT¶ ªÚ]õÆ Ì0=ègh¯Vź“Ö§´ ÏåftAOÊjPNݘiºaöT±w&o–éùèBÉd\碿 êLBE’ Ñí}CÕªñoØ—@!ë3f1°Â:«ôš³º†~ðò ˆß ª¢SAíÕ¦—•”Z^«0c¦Õ:9ÿá2G*a…éE’8ŸÏ£T* ÝalP¯E?3ëâbâB¯‚4~û·¥ß̶Î5Mq#½æzòQx}œ¢*˜¡è¥°zu9 S¾G-+‚âö …Îß ¨ÕØ +£ƒ0÷ ka%Ò¯°ú~…5 ½ 2ièí]e˜°, <òbvÚ0GJÓ€r¹ I’¢iccYn^*ÃL˲ôšÖ=H zØáì‰ACs9‘ׯ¨kÂò³M³[!•$aÇ0Í9*Îì_¸QX0åŸᨲªÀêêj×{•JgΜéxosssè‹h4H¥Rï'‰‘Ûæ„U,BÂjèO²è:½¤öÁK†PJËèÝUᆇ­›dpuÞ#À¤ä; ˲ð’—|™Ì‹£¾õÉr„'î¸1m÷R,ºëY˲ iv‡í;7® ÑuagÏÜ¥lašf`^¶atwA’e±:R²GæFÇGœdܲ¬ÀȘ°UUÓ®®{{SýÚÆa„WçÕõÁІÍ1}Ö'Nt\"‚„{*• F‡¢Ûl6Q(œ¢Nªª¢\îWê¶E Ÿ»LÓì¶ÀkpCx½úKó`ßšg{½B‚Ù»:÷LR¾Ã°, O|â~Ô·>yl{b€fŸ(dœð‡½kš†B¡0ýP`Ê››ùã%JÙÛWJ3áøS¡l&>ÄIÆ{…F°0—s»»ÌA÷_(ÌÑ ŽN_…5™LN¬ßêÎζ¶¶°´´ÔñþÆÆ’É$î¸ã´Z-œ:u •Je¬×ÑU=Ò@¸ré/Zäm£„ãxk'òÕ13@Tòý?þÇOãOþäèZá˜éå{…W75M¹i÷‰£òÄq+ðÄЍe;ˆ°‚Kº^k%“ N§f˜¸Éx¯‚bÞv6~ªÕ9q¬Ïl¢ùtˆ,‡µÕj¡X,vŪ7›Mììì8^ÝD"åå呪=‹½Zù$ß[ xw VréàÅ #É4ä;Mó˜/DWlfšpßÊH‰JÆ ÛvC‰^-&õÒ9¡ZóFÔ²\²íεa„+¬TefáÔ‰G·m;Pa5ŒÞÁTs¡¬bMÃQc¡ ­°îìì R©8/êÓ:,X^^Ɖ':Þ¿pá€ÎãT*…f³9¶›6 £{QcB„ö*~àg:·ÕÏ 9t±Çéà¨G”¨ä[Ó€k¯ý‹Áú Ï:sQpv‰r7MQÛ¨ó=sòrošÝ hך;¢”í^PÁ¥tÚ-°D­kærÊ·¬®oâ(ãþ9<ŸÊê‘ÉþakOVX ÃÀ-·Ü‚ÕÕUlmm9¯ÕÕUÜrË-N¬û loo£Ùl†ô­Vk¨›+•‚…<,©2D¥àÄçúŸ|‡Ã¼T-c†bZòí‡*¢ö³ïú+˜3í6˜m¢’q"¨ú¯v‡†ÎÙl÷6ö¬ÎQËv/¨‚êî®›Ï7óÔ^Ì­&-q•ñù—¯!›•œÚTk(“™ƒ«ƒp$´òÑHaÝÙÙA¡PÀ‰'P.—aš¦ó*—Ë8qâN:5·µÙlbkk ëëëÛ{ ˆ‹/†n»ï¾ûp÷ÝwV3öcYVwÙlÊ_ 3 ‹„èÕ²¸Pd,ÙÞÞÆéÓ§aN ÔhRò ÷ß?VWW±½½¸]×Å|w$¼«LOVWWqþüù‰œ;sxP‹ƒÀyý0ض0ñ/,ˆ%IUŠùø2MétºãU<ðR™¦éüßOÚÓŠG×u,..âØ±cXXX€³¦Î•J§OŸÆ½÷Þ;ÖóF9÷ömXV·f*Is¼Î=¢i4ã”8ÌßAX– UŠ* ¦Ú#Up}n-OÐ|Øù{ ¶6¡UÂTU…ªª( ØØØÀ]wÝÕ÷B‰ Àah4¸pá*• –——{VîUZûúë¯ÇÍ7ßÜa1 K- ¬L9¬† (Äê+诰Æ{]sdY^^F2™Ä¹sçÆ~îIÉ7\wÝu=ÛFÙ6ðõ¯bú9|LìØÜÜyáÐiÎáa˜f÷BÆ4MÆškÛ¢—j&3s•탰2Ê9³, ét™L¶m‡ꌃ¤H˲Ïç±»»{/icqqТį¶¶¶†“'OŽ}rþîÇ;ßù9\sÍ5ãý"ãÎõ°Òü=®n^â0aš&žð„gίñ…qu Þ×ú³³ƒf³‰Ûo¿½ç~+++h6›}-B'OžìªHæ…âé½a Ífs¤>PAac@Hb76ü-lŠ®ôKû½¹”éÁ4åÛ$O{ÚÞÑ(¸ÄDF”2Þ‹ÐTQH§…µsrSeYvÏA ÂUdø’$ Õjuàãg™¸Ê6Üyç|ß÷}'ê¯hºØvp_Jfdâ*ã¦i¶å£hŸ`¤¯‡µÑh ™LöV²Êô‹q_ZZê,•J:¬2KKKØÞÞvÞ3 £#\i"U'¨MMØsÚpâꙉR¾K% XœBá™8`YÂ"u$[âEÔsxPù±\šñ> –eu…þªªêxQ{AaÕ Èd2NÕQ jÙîÅ¿øXÜ~ûåQEÓåˆzX'I\eܲ¬£ga†¢¯ÂšH$úæfŒ›µµ5¬®®bgg­V ‰D·ÞzëXÎX˜Ã:x=“Mt÷a á}[¦“”oÛ¶†‡•ÖX3YïÎÙ{Á¥!Éň+™¢T¢¬»»»0Mº®£X,²,Ôëõ£a ëÃ$e»_üâÕxá ¿?êÛŸ.ìa„(dü£}^úÒDÔ·š&ž;<džÒWaM¥RhµZ}C¨àR"1œÀÅ»§R)ÜyçNxq¯ð…^åë۶ݽ°1à*¬–ü—뀿{¼»=h¤€‹*1}™¤|{1 ñ¢¶ 3-¦%ãD"°.Á0P)ʉÚé¦É²Œ’§€‡®ëÐ4 ¹\®ï¹H±UUÕ™KŠÅ"4MCõHU@™¾l‡!±e.HÍŒ¸È¸,qû³eqÅù> ¤°¦R) lnn*¤­V •JKKKcKO$$=Xe¸ÞUMîý  kX‘º Ða†qË·aˆ¹N×ǘÇg ƒ-ï1gRsx¦iN™*gZaíÇ0hÛ¶¡iZ×=‰ye@¦)Ûð¡ý®¹fòy²±c 3¦)ã†aàðÒ£]pÉ4ç¢fÂ$¨­Íúú:šÍ&N:åôoD"ööö6N:ÚÓ)J .u=¸U¸^TÓ®û¶ç$QßÃô§T¢ŠØs"°½ÚXç6Q¨xïX1͹“%Ã0pìØ1çå­ ìßæÏMËd2e N[Ã0ÆW™š{îù?ø•_ùÛ¨/cú°Âz$0M?ü¢¨/#zØ(Ø“ÚÚ¤R)lnn¢R©`cc£kûÒÒÖÖÖ&R‚û0µ4êÙƒ•H$ܼV–fF0Msö½ ¶ d³Bð`ËšŠª ïj.7wJÓŸ ÝÒ0ŒÃ…Á‡•“ŸQTUE»Ýz›÷ýjµ ˲œÊËœf-–e.äabŒmÛøÛ¿½9êˈ–#ÚsxRXWi¥Ö5Fà N&“hµZØÙÙ™j˜L?‚ž±VP¤ì{„›Óz”C˜™!›r9{ö<¬º.”TYÿ‹",ÆoY—e ^û±<:ÆEU'Pp‰‹wâmmÃDK½þïQ(°Ñ€™OLÓÄë_ß>ü‰fžkû2°ÂJP‹¿—²Ñh`uu5´)ù´±,×C†ÞUÓäÜTf¦°,¡Ç†1y«m‡‡ã[4@ÓÄKUݪ¿µZ¸ç”'t&€C{ŸL“ Ll±mßýîOs@ 3·X–…׽/#:b¢7ÅrXgZÿz ìÕg¢3ì—Å&ÜÖ5 c¼a’Ý+Eh®¦uoËçÅvRjËåð}±O½.BK%ñ^•1=X\ì~/0̓aæÓ4ñÿãßD}Ó'›ú ˜)`Y®½ö9°í¨¯$Bl›×>0· «¢tGy†[è,¬$I@ @¢ÝÍQDÌL@)xÏaÍçÅ¿{{"”—þ&êuñïâ¢[§T¤i”J\d€˜°TSë0¹?†Á &Ö†¿ø)Q_Æô᜾#išøÚ×þûÑþ¹y4C‡Ï ’ÔëÔ·à’ßÄS‡3±Ç²„qFׇô°ÂKÊ)…NÖëÁžSò–zápKf )¬Q3ÃÀ +st8qâyQ_ÃLÓ4aÛ/:ÚÓ°¢ðshæÖÃJQ‰^‹sx=¬¶-Vþ€"XYefJ):<› vÿÉü†›bQX€üŠ'·`¦ˆeM àR©4——lÛF>ŸÇñãÇqìØ1d³Ù±×—0MÓi{C¯b±Ø±Ýû·˲N§¡ëzÇûº®cqqǎô°”‚#€eYxä‘n¼ñš¨/e¼‹â†¦qÍ‚#‚iš¸ñÆï‰ú2˜ ¯‡µÑh R©ô=Q«ÕŠú^:Ð4±îö:{‹.ÉpSYvá”ÃÊkrfFÚÓT­ ¥uwW(¤š&òNëõΕ þP 3e £»¯úXòWç0+NCUUìï‹ò÷†a N£^¯-ÏÝ>0lÕRHÍd2P¶m÷T’5MƒmÛÐuÝ)šeYòùÓì6š2s‰a¸æšWÍ_4¬m‹Xþ £ )«¹œp’é:+¬ÒWa¥þ«³ˆw¾£èØþäƒÁ!a8$˜™)F ÌåÄB,Ú¼H`bHXªéÄ Í ay½™LÅb²,CÓ4ÔëuH’„l6 I’ Ë2ŠÅ¢ã1M§ÓŽZ.—Q«ÕP(°¸¸Øáõ‡ýâñ¦ßM–ed2躎B¡à»°°€L&UUlhÃ0ðìg¿}ìœdnÙ¶ˆè©Õ‚Ÿ3ù¼X¸s̓#ƒaxìcsó¥¯yÒ^Ûhû\Ýüd™Û¢K~,Ëê~ˆî¼xýs»0:-ÃDŠ®S¾ö€ÖlV„øz•[ùebŽªÑ9LTÓÄ¢y\ù«T; Eégš&p/J¥nM=è³2™¾9å’$9žÊ\.ç|w¹\ÆA.»ªªNÕeUU¡ë:TU…,ËÎþý¼¨†aôU2u]‡¢(Nd)¬°»» Ó4¡ë:ŠÅ",Ëk(ó¬ ë:®¾:7û6DòªRLØïÈ!ÀG˲ð¬g]6?€ÈÍVÕîù˜R® ®ÿ1"}Ö¬®®v䢴Z-4X…÷#°õAóàŠ@¾µ{› fbÏP=XËeñï\=˜£ÊÈ‚'‘#7ʹ¼Vö1~–,˹£†a~_^C—mÛŽò*IR_ÅS–åŽð` )îwœ¦iPåƒ9ɲ,çe™®µX,BÓ4TçB¶E‰§¦Xì¬ùãKñ ½ÊûŒ¡jiGè÷cÃ4MìíÍQË&ê¦à7NÚ¶êÎ믑)ÖäÌ™3X]]úÚ{â×O‹s\v°œ>·´af€\N¬úVK¥°_^403HSq$…Õ0æ>üBl½J«mÛ(‹È(Þmäå”eÙÉ}-u1HÕf]×!Ë2êõºó¢k¦ðc?G-ì›<Û4¿O•|¾¿ç¿PãÈ4Åb¼XtÇ•ÿ÷Ïdæ²7s8,˵×>s‘žn¢×|P7À}Ÿ•ÕC1·!ÁªÚyèa5Íð‰4ŽVM†ñáÿz.óyaõ;b ?fö [И¦é(`£is?$IB½^G6›uæú®r¹ŠÅ"lÛF:†$I°, ¥R ’$aqqù/iš(•JŽÇ5Ã0pìØ1çoUUQ«Õzn§¼U/ªª¢X,boo†a`aaÁ¹vÛ¶¼Ú£‚išÕ–'ròð°ÜrY 8*~T*¹¡Œ{{î~´Ïfݦ÷Gì7b‡aøÚ×þ»Ó–/VÆ`–"ÓììQ»™/"UXQØ)l{"‘@2™úÜþuŒmÛÝÖ3k@õYQ~Ì3Iù&4ê&Yá;•Ëb"e+73f¦!ã’¼¦Š²C=†cc9^EÁÞÞžS XQ”/¥ðÞåº"(”ÎAûz÷ñ*ív;ôTUí¹ÝK&“q”Øjµê„K’Yîê4d; a`¨B×Çþ(‚AÈçãÇ]í™rPƒ _^CÅ‚¾!Á'Nœp×˨-mR©677‘H¸Õy/\¸@ ú¿7¦>•J9¡ ƒâ[]h G³0cfZò ¸ÑZ==¬ŠÂ“-3V¦)ãAPuà¡*DzG‘€(eÛ4Å‚~aáxÅ+žîÔ'˜’äz8úæH¥Œ““ÿ™ÏL Õ’'ð¢ëÂ0´î!åt_ ¸A‹+1± ¯ÂšL&KÌ8H$Ên³ÙD¥RÁòò2’ɤ㽠¢Õju ²AqôÜÞª¸m 3v¢oì1a¦Æ4eܲº×Óƒôùd˜QˆjþܦOxÂob}ý/FSVu]¸i31pzUmbcæ‘$*×u·ðô3žñ ¸ùæ?pÉxoÎ4Å@’¤Îmj½¸mgXþgŽHrX!ø•J·Ür –––°¾¾î¼ÆÅ‹áE’î»ï>Ü}÷ÝNX²¿oŸ,Ë匛&ð¬G£ºu&b¶··qúôéŽ^„ãfÜò ÷ß?VWW±½½ @ey°Þ‡ÌÑbuuçÏŸŸègLz‚#Ú ÃàÌ>¤Óé®—¦i0Mš¦E}y‡¦R©àôéÓ¸÷Þ{'rþiÌß~$IûÁüÒhýW©º©e‰b1‹‹ýû©2±„æo*z4 ¦1{±,7"ý߸oxÃÕã¿©|^(¤þ‚bIÀ}èc­Á‡¿®Üh4°µµ…••¤R©ÐJ‚ƒ(FH$¸ãŽ;ºBÂèUZûúë¯ÇÍ7ßè vúõQ S>3t}M¯z] ˜R©…_&¶ÐüÝKÞô×à€[B`böbQXy‚ž™ W´Ž£®Áò°†S§N9=™ˆµµ5¬¯¯cii ‰DgÏžèC …‚Gï'Nœ€Žxùf³9T("·mÛb€xòsðÐfâɤå›eñ íÁj\Pƒ™Ó’qÛî\sëº>¸wUׅljq°, †ç©iÒé4ŠÅ"ŠÅ¢cpÖuÝñÌê^:ò΋Eç˜ydZ²í… èQ~v(Aó9µ«!e•`e• ! ' Ãë,Ãó=Ö›kò°nllöaJ¥RXZZÂòò2 …Μ9Ó7ßÕ0 4›M¨ªÚ+¿´´„d2‰¥¥%loo;ç2 iŒoºÆƒ@`<‘3cZò À)Êj­Ô4žÀ™±3MÏå:×à}ôTõ‘¬ìG8̯Pær9ضí¸ À¦i¨×ë0MétªªÂ²,‹E§*h:†,˰mårµZ …B‹‹‹Èd2±èÛ:.¦)Û^Êe7½£§AfaA¸b½Þ"Yæ>ÛÌÀD%ãé´°©X–…̸¼¦)ªýR5_vDÍ5}V*}ûí·÷ÜïöÛoÇ-·Üâ¸zà˜ü p5²î®­­9ís(ÉûÖ[oé-Ë!PEˆ`ƒVfrLS¾5 å‚9$Œ™Ó”q¯h÷UVaeßÛ›~p¯µU¬/0” þiÂR 3AæÁqÊÁqaŸEûåK’UUï–ŠZ‘b«ªªŠ-˲³)±óÄ´×'µË¶,«ÿ|^,Š`¨;sx¢’qÂ0 TÇeH$c +ªG‚¾ k£Ñ@2™ìRB) ˜ í.\è©°®­­õõ¦R)ÜyçÎÀµ… Š¢ˆ… hr‹fbLS¾3AÆ+«Ì„˜¦Œ‹n¿öBÉ¢ÊY¤E¡?/1‡þJ¦pîÛ!–!ýé^åÈ;ضí„“B{˜öú„°,à±ýdoù6 1é˲§à G2N"ô¼Q°m±®ñÎE¬¨)ú*¬‰D"°2X¯âãÀ_z{Tœ´ì¼Á–I&rÆ!ß…P,Zî"‡r™T•# ˜È9¬Œ[–XŸ¸÷ %ó/f˜žH’Ã0 ª*lÛv¼+ä9%…w^sUøÖ'„eçÎ} ·Âª(b.šowZsfÌŒSÆ©=ÙÈù«úË)NGš¾E—R©Z­VÏÞLœí‡éC6.TÕÇ-ËBöxV(¬Ü$˜™l[<:<¬š&6PQ®ŠÇÌ0þ.¤\…â¯ÐtÄ9vìXÇ+(§Õ0 äóyd³YgÉår0Mù|ù|¾ÿ÷Î o8pÏżªºò]*ñüÎÌ –%Äw ´?¤¬ÖjyÄéëaM¥RH¥R¨T*H¥R )õsZZZšXîQ±, ×McG†PX%~ 0óm?öc߀i²L3óI¹ì ŒJÆôD–eÇà €Ã~#"“tý,Z-–of>©×{¤t†ÛG˜(Da±B•UÆa …U€×××±¶¶æT& ã å‡½3sȽ÷ÞË‹xfnñ¦¤JÆ …,ËìÙ‹¦iö6‹Ôt;êKe˜‘’!ˤ7úQ’„g•a<ô-ºä‡*‡Ñ+®Ê* Â^ýµï5É̦ |Ï÷|Jü¡ëâÅ0s„·ÅgÏþ”€XÐ{K 3ÌŒ°°0@È»®³²ÊÌ$¦)¨F*ÉÑÌ ­°Î_úìg¡6’¢A;ÃÌ>Ø^Ì0sUN Öu;À4M¤Ói§*aÒé4LÓ„iš]Uƒ‹Å"4M ÜÆLŽë®û6÷Ó¸3Óˆâ!FÇr™[Õ03× ë•wßïþ»çl¼aæ I€«ûX·Ì$ÃÌ ^‘îë}òj·ŒÓSU÷E]èºÓ4aÛvGßUÈçó°m¹\®k3Y~õW?Ô;˜çwf†Éd€“'?Ù=‡³w•’¹VXà¾ûpùæ³YaeæŽZM(¬ÏþÀ¸73wx‹_÷íOÉíʺP¥Ké óTçóy¼¥ 3VœZa°ÂÊÌ0² œ;÷î¹Ç[Ua`nÖ¯þóP¾“€(Ì0óÇ÷~å+"’Cj˜9C–];LhuI‚Ö@TUu¼¬º®~‡ù|º®£Ä Ç©cÛÀâbŸ‚K¦ÉáîÌÌbšB/í’qÓä^ÂÌÐ \%xÖøÒéÓxìñ"®Ñðzž™3,ËÂÿîwYYeæZÛ ”¿j@ÄÞA_ºhȽ¸•EH§'Ù õŸµíîµ]ÐgÑþ^2™ Êå22™ Ã@.—ëðºÒ{¹\ù|5®Ê9U CȆ®‡³m ›á4òÎÌ T^£kW®Ì ÍÜ*¬Ç>øA\õoï2Q_ ÃŒŸ¯~àxöw¾ÃáÀÌ\ætˆI¸ä  +ÕÏ!…5ì8UuVÃÿ殺Òþ^(,˜rRýŠ¿¢(Nðââ"t]G&ÃÌiaÀ5×|8\¾¹%3ãè:P«qmf<̧ÂjÛxÊ‹ï>ýrŽfæ’'ÿÁà£/y ^õ…0Ì1 £·ç/&áÀƒDÔúmKªÚ¿Þˆ,wŸ{˜èÝL&ƒ|>¨y«ÒV«U¤ÓéÞÆf¬ë;¿sö@13Œ®‹ùm (†€ùÌaµ,|îñ¯Ä^ý„¨¯„a&Â{žó\õ VW™ùÅ>hÄÚ³ m‹2”L ™Lf Ï©¢(( Èf³„¡àرcÎ+NG}+s-æ Ã`¯63—†˜š{æh3Ì̧‡UQpé7.Áe·^õ•0ÌD¸«ÙÄ‹9¯‰™cú†\e2UUïMQ´Ûmg[½^ïØÏK¡P@á 'Þ{ 3~L¸üòÿÛùäó‘çb3Ì8 T†BÁê¬òn"‚S™˜ˆ½‡µÑh ÙluÌCÿðöŸ¸HCÆ0Sgù„÷If…•™F•q¶Ì3³À¨òýðÃ[®|ûzæ2L\E¾É»Z.—#Q2˜Ãƒ™‰­‡µÙl¢P( ÑhÖàr¹<бŸþô§qïOÝ‹çáyQßÃrùÀm(˜ØsX7 ƒ{ƒ2±å0ò]* ùÖ4ö®2±â0òÉŠb!›5…ŒÛ6N‹8xVX™‰­‡uccÉd¦iâìÙ³h4¨T*ûÌ—<7üü QßÄrùÀž'&öFƹPw#ßáîTö™#f˜qØ5J¹\F.—s•Õ\ŽS8˜CK…µÙlbgg+++€D"åååŽü›^H’Ä z&¶V¾&îVÆ?÷à·¿õ- Xt_Ù¬Xø,,ˆ9Œ’‰ˆÃÊ7õÀ ¼«ÜO›‰‡•o˲ð÷wßœe‹‹BYå¼UæÄRa½pá •J9ï¥R©‘òDf™a¬Y³@£ÑÀöövÔ—9,ß‚y”‡y³£rXÿ¹Ûnÿð nø˜ªŠE}½ìí‰g ºê¼ÉÃ<ŽÙQ8¬|¿àû¾Ši #Œm÷ïoCæQæm¼ŽÊaåû’O÷øÇ‹?vwgVY7y˜õ1ËÖ^ƒ¢Õj!‘Ht½ÿµ¯} ŸúÔ§pæÌÜxãQßÂX¸çž{pòäɨ/clœ?çÏŸG2™Œô:¾úÕ¯âþáðµ¯}-’ÏE¾éºÏœ9ƒ«¯¾W_}u$×>Nâ"ã$.cöüùóxà"ûü±ÌáW\!^×_/vø·vv"»§Qˆ‹<Œ‹¸ŒÙûî»ÿüÏÿŒo~ó›‘|þ(òí¿Ÿwþ<°ÿâãáoœ9¹â# ã$.ã•æïf³É÷;–ùûíoî½wê×?.â"ã".c–ÖàÃÎß±TX[­Vè¶‹/–Ç<æ1ØßßÇÙ³g{?K?~ç΋ú2ÆÆÅ‹ ò{zàðÅ/~W^ye$Ÿ?Š|À¥—^гgÏâÚk¯ÅSŸúÔH®}œÄEÆI\Ƭišøîw¿Ùçó.ˆ‹<Œ‹¸ŒÙ{ï½_ûÚ×ðÌg>3’ÏE¾½ó·õ£?J'fT>â" ã$.ã•æï|0å‚çoA\äa\ÄeÌÒ|Øù;– «7 ÁOØàý™ŸùüÌÏüLÔ—Î0}E¾àÌ™3Q_:à ÏáÌ<3Š|óüÍÌ <3q$–9¬'NœÐ–UhÃŒ–ofÞagæ–ofžaùfâH,Öd2‰¥¥¥Žä`Ã0N§£¾4†94,ß̼Ã2ÎÌ3,ßÌ<ÃòÍÄ‘cív»õEÑh4°ººŠd2é$yonn†æ÷1Ì,ÁòÍÌ;,ãÌ<ÃòÍÌ3,ßL܈­Â ˆÄïF£XZZŠúrf¬°|3óË83ϰ|3ó Ë7'b­°2 Ã0 Ã0 Ã0G—ÇþæoþæoF}óÎÎÎŽ;JÑh4ð­o}+p{¯mƒlŸ­V –eáIOzÒH×Ç{bFç0ò=Ží“ —ŒÏâý0‡£—ŒÏ¢<ðÎGmþîwMq¼æpðüÿ{ˆ631Þõ®wµê§~ª}ÓM7µoºé¦öm·ÝÖ~衇œí.\h¿êU¯r¶¿þõ¯hÛ Û'ÁC=Ô~ýë_ï|æ«^õªög?ûÙ±]s÷ÄŒÎaä{Û'A/ŸÅûaG/ŸEyà9œ!ŽÚüÝïšâx?Ìáàù;þ÷4 ±¬<´Z-T*¬­­Á4M§™r¥RqöÙØØ@2™t¶7 g{¯mƒlŸ•JÍfgÏž…išH&“ØÚÚøšâxOÌhV¾Ç±}ô’ñY¼ftúÉø,ÊÏá p4çï~×ÇûaF‡çïÙ¸§¡ˆZcžWî¹çžöM7ÝÔñÞéÓ§Û·Ýv[»Ý–Œ›nº©Ã:ò¶·½­ýÒ—¾´ç¶~ÇNЇz¨ë3/\¸Ð>}úô@×Ç{bFç0ò=Ží“ —ŒÏâý0‡£—ŒÏ¢<ðÎGmþîwMq¼æpðüÿ{–ÇE­0Ï+KKK0M³ã½ .àŠ+®pþ©TÊÙžJ¥Ðl6{nëw줠Jq©T F­V ©T kkk]Sï‰ÃÈ÷8¶O‚^2¾³³3s÷ÃŽ^2>oò=ŽkfŸŽÚüÝïšâx?Ìáàù;þ÷4,¬°NÕÕUGî¸ãè){{{¡ÛZ­VÏc©_Ö¸¹xñb×½\¼x›››}…zkŽâž˜ñ0¬|ÇUzÉø,Þ3>ü2nFè¾q•žÃ™ ŽÂüÝO¾ã¸æbÆÏßñ¼§aáÖ)pë­·beepæÌBÂøêW¿ºíâÅ‹=%¡7^ëÎ]wÝ…»îº ËËËX]]í{?ƒ\s÷ÄŒ‡aå;®òÐKÆgñ~˜ñá—ñY”žÃ™ ŽÂüÝïžâ¸æbÆÏßñ¼§aa…u ,--ayy·ß~»“ íu»íF2™ìyl2™œÈ=œ zÉø 7Ü0s÷ÃŽ^2>oòÍsøÑâ¨Íßýä;Ž÷Þ¿ãOàë„8yò$vvv7>†áüøÉdKKKØÞÞîØžN§{nëwì¤H¥R]%´+•Šc™9ì5GqOÌèF¾Ç±}ô’ñç?ÿù3w?Ìáè%ãó&ß<‡-ŽÚüÝO¾ãx?Ìáàù;þ÷4,ÇÚív;ꋘW666°½½¥¥%\¸p¡#A1é«««H&“NRóææ&‰DÏmýŽô™d¥æ~Ʊ‰‡‘ïqlŸ½d|ï‡9½d|åçp†8jów¿kŠãý0‡ƒçïøßÓ0°Â:a¼%Óƒò$Z­–còoïµmí“à°×Ç{bFç0ò=Ží“`’c’å{öè%ã³(<‡3ÄQ›¿ûmãý0‡ƒçïøßÓ °ÂÊ0 Ã0 Ã0 ÃÄÎae†a†a†ab +¬ Ã0 Ã0 Ã0L,a…•a†a†a†‰%¬°2 Ã0 Ã0 Ã0±„V†a†a†a&–°ÂÊ0 Ã0 Ã0 ÃÄVX†a†a†a˜X +Ã0 Ã0 Ã0 KXae†a†a†ab +¬ Ã0 Ã0 Ã0L,a…•a†a†a†‰%¬°2 Ã0 Ã0 Ã0±„V†a†a†a&–°ÂÊ0 Ã0 Ã0 ÃÄVX†a†a†a˜X +Ã0 Ã0 Ã0 KXa¶mÃ0Œ¨/ƒa&Ë8s”™„üó˜b¢€åŽ9*°¬G+¬1Ã4M¤Óé¨/ƒa&Ë8s”™„üó˜b¢À+wš¦Á²¬¨/‰a&‚ŽeyŸ>¬°2 Ã0 Ã0#£ë:/à™#Ëûôy\ÔÀ¸–I’ (JèvY–¡ª* Ã@.—†á„)d2™Žã‹Å" …4MƒmÛP™L¦ãó …ÂÈû3Ì ô’qÛ¶™“$ ¹\’$AÓ4Gæ ]×aÛ6r¹Ë733„Éÿad¿T*¡\.>3lÛF¹\îz&0Ìa ’ezO×u€ªª]2JïñœÍÌ aóö ò®(Jàܰ\ {X#fqqÅb€P>³ÙlÇöb±ˆr¹ @,X²Ù¬3HÊå²³¿mÛX\\„¦iα´Ý¶mضl6‹t: Ó4íôÙ£ìÏ0ƒÐKÆmÛÆÂ‚ctÑuÝ »±m»KÞ#¯,ßL„Éÿae?ŸÏZùmÛF:vB 3.ú­W¼É(ÏÙ̬0Œ¬òþéO:tn§}Y®G ÍDFµZmK’ÔÞÛÛsÞËd2múYöööÚ:¶Ë²ÜVUÕÙ¶»»Ûu>@»Z­:+ŠÒÎårÎß…B¡­ªêÈû3L?úÉx½^o{§¡ýý}G¾ýò¿»»ÛÐÞßßo·Û,ßLüé%ÿ‡•ýB¡àKçÚßßï’k†ýærUUÛõzÝÙæ—Qzçl&îô“õv»·¼÷šÛi_–ëáak„X–UU!˲ó…úÂ*ãßžÉd‹,ËNå2ïßd¥Ðq¬$INHBÃîÏ0½è'ãô~>Ÿ‡a$ õz²,C–e(ŠâDèºÞVã=`ùfâG/ù?¬ì{Ã… ²ÒÓs‚aÆE¿¹<ˆ å9›‰;£È:àÊ{¯¹`¹VX#„òRðm»ç±”§ä}= &*úɸ,˨×ë€l6‹cÇŽ!ŸÏ;Û3™LǢ囙%zÉÿ$d_Q …Žó0Ì8è7—3̼pXYï7·3£Á k„ȲÜá :•TI’B•VEQ« ½jµ …ç-1±¡ŸŒSjµŠýý}ìîîB×u';“ÉÀ4M”Ëeض͞#f¦è%ÿ“ýjµêëà(fœô›Ëf^8¬¬÷›Û™Ñ`…5B2™ Ãp¬èä1õn7MÓIܦВ€=ðþ ¸Iß úÉ8£‡,Ë]!¿™Låry †‰½äR²/I’S­’Û.0ã¢ß\Nï1̬3ˆ¬ÓûAô›Û™Ñ`…5B(|+›Íbqq a_²,£Z­"N#NcqqÑÙN‹’b±ˆÅÅE§Bp­V‹ú¶Æ¡ŸŒS^ÞÂÂÒé4œ…:AÆö®2³F/ùŸ¤ìg2d26`2c£ß\.IŠÅ"{‘˜™§Ÿ¬½å}¹žcív»õEu,Ë íÑgš&dYvbê©O)¦Þ"K&Ì0q#LÆ Š"Ú®iÊå2ööö¢¾ †‰^òϲÏ̃¬W8ו™zÍÛƒÈ{¯¹VXcŒeYXXXÀîî.EeYH§Ó( ÉÌ=N³¸¸ˆ\.Ç´™#Ë>Ã0 øpHpŒñ†;v ‹‹‹Èd2¬¬2GÓ4qüøqȲÌ2Ï)Xö†aÆ…=¬ Ã0 Ã0 Ã0L,y\Ô0.šÍ&>ùÉOâꫯŽúRÆÆ}÷݇믿>êË<òyä‘XüF<òó˜ÇàùÏ~Ô—20ïÿûqÕUWE}c#Nò0.â4fï»ï¾™*òÀsxü‰Ó˜}ä‘GH$f&7Œçïø§ñzß}÷á…/|!‰DÔ—2<ÇŸ8ÙQæï¹QXÿñÿº®ÏÌÃkî¾ûnÜ|óÍQ_ÆØxàð¥/})¿Ñ<€‹/ΔÂúçþç3u½ýˆ“<Œ‹8Ù»ï¾{¦VžÃãOœÆì<±¸–Aàù;þÄi¼Þ}÷Ýø‰Ÿø‰™QXyþŽ?q³£Ìßs£°^uÕUPkkkQ_ÊX™§ûi4h4X^^ŽúR°³³ƒsçÎE}Cñä'?™åaˆËoÔh4¢¾„¡à9<þÄiÌÎÚÎó÷l—ߨÑh ™LF}Ãówü‰Ó˜eþž…u™§©T ©T*êË`bÂ<ÊüYæpÌ›<Ìã˜eFceaÞÆ+s8æMf}Ìr•`†a†a†a&–°ÂÊ0 Ã0 Ã0 ÃÄVX†a†a†a˜X +Ã0 Ã0 Ã0 KXae†a†a†ab +¬ Ã0 Ã0 Ã0L,a…•a†a†a†‰%¬°2 Ã0 Ã0 Ã0±„V†a†a†a&–°ÂÊ0 Ã0 Ã0 ÃÄVX†a†a†a˜X +Ã0 Ã0 Ã0 KXae†a†a†abI,ÖF£ú~³ÙŒúòæP°|3óË83¯°l3óË83 D®°V*T*•Ž÷šÍ&N:…S§Ná–[nA¡Pˆú2f$X¾™y‡eœ™WX¶™y‡eœ™"UXwvv°µµÕõþÆÆ’É$LÓÄÙ³gÑh4ºÃÄ–ofÞagæ–mfÞagf‰ÈÖV«…b±UU;Þo6›ØÙÙÁÊÊ ‘H`yyõz=Ò/Ša†å›™wXÆ™y…e›™wXÆ™Y#2…uccËËË8qâDÇû.\¤R)ç½T*ÅqôÌLÁòÍÌ;,ã̼²ÍÌ;,ã̬1’ÂZ©TpêÔ)(Š‚J¥‚ííí¡Â¶··Ñl6±¶¶Öµ­× hµZQ_ Ó–ofÞagæ–mfÞagf‘¡VRP—––L&ˆíím¬®®ö=¾Ùlbkk ëëëÛ{ ˆ‹/†n»ï¾ûp÷Ýwt ÌÑf{{§OŸ†išc?÷¤äî¿ÿ~¬®®b{{{º_3s¬®®âüùó97ÏáLÔT*œ>}÷Þ{ïXÏËó7hþ«Þ{xþf¢†ÖàÃÎßfgôÍÍM,--9ƒIUU$“Iœ:u F£#” èB‰ Àah4¸pá*• –——{K r×_=n¾ùæ@‹ÃxY^^F2™Ä¹sçÆ~îIÉ7\wÝuØÜÜŒúëcf€ÍÍ͉-xg¢fmm 'OžûÎó7hþî%o£Âó75£®Á‡RX)¶}ii©k[*•B*•ê2pòäÉžÛ)ž¾Ùl:ƒÃû†‰3,ß̼Ã2ÎÌ+,Û̼Ã2ÎÌ*C)¬‰D€ ÿ­Vk ð…¥¥¥…—r_½V™¥¥%loo;ï†t:õwÅ0}aùfæ–qf^aÙfæ–qfVJa%/êêêjGü{³ÙÄéÓ§‘L&½¯Ã²¶¶†ÕÕUììì8Êñ­·ÞõwÅ0cå›™wXÆ™y…e›™wXÆ™82” ˆØúb±ˆS§Np§R)”Ëå¡/ (Þ=•JáÎ;ït<¶ãP‚& X¾™y‡eœ™WX¶™y‡eœ™†VX‰677Ñh4œ|ÕD"1öäðD"Áƒ„™[X¾™y‡eœ™WX¶™y‡eœ‰C)¬;;;X]]ÅÙ³g'R½Œa†a†a†aˆ¡ú°¦R)§6Ã0 Ã0 Ã0 ÃL’¡«¯­­¡R© ÙlîÃ=˜˜Y Ù¼$êK`†a†a¦Cç°nll¶¶¶·³ÂÊLÛ/Yaº˜& IÀµ×>?ú£Q_=Ã0 Ã0 Ã0½Za5M3êkfm–(JÔW2†!^¦)îC–Å«ZÛËeqoªêþ­ëBI-ÜývvîǹsQß Ã0 Ã0 Ã0½ZaefÛ²Yño&#”:]Û2™¨¯.üšÓi`wWüN åTQ€\.Ø«jÛB¡%…UUÅýõóÀ2 Ã0³eüàq|ë[WF}) Ã0ÌIaÝÞÞ†aØÙÙ z4©ªŠååå¨ï‡ @×b(•:•SEJ,)qC×]ÅêõþÇ”JÇñ¾†aŽ*¦)æeÃ0™Œ0@=Ëd¸öÚËÙÉ0 sDZa­T*ØÚÚÂòò2VVV­V h4X__úž¦)õz·—Q–]ï帱m±° Å‰¢ˆ÷LS„æ¢Hºˆ…Ç]¼ˆ'ßÿä>€a†A:íwçUÏ rYìã…”XË4Í RñÌ’$Jëx(êÛc†a¦ÀP k³ÙÄÖÖÊå2T¯ë €ªªX]]ÅÊÊ ’ÉdÔ÷Å`áá³^4mx±\ç )¶m±¨ØÝuóN)””W@¼GŸ_.‹kÈåÄþçÕu ŸýnÔø·+®ÀCW]5¹/ža†¥X‚_¯»ƒab‚iŠiØ0D-€AŒŽšÖùìÙßïÜî­?„$‰}¨î{T†aŽ&Cõa½pát)«€ N¥RÎ>L<ÈdËQ%¥ÒÿÞâ¢XtøÉçÅÆ{Œ¦‰57 %UlTU¡c:žUÓtB»è8MëtÛÜüZbÇrÙu/.ŠŒ˲†* öèe—Mù×`æ Ó®¡q¢£”Ë ù¦sZ– dáa˜)¢iBÄ]e­6xª…¦‰yT$I ‰¸ÖY`†a†Ã4Gk-9Rk«ÕB"‘èz/¬7+ƒZ¤K%±0ÙÛ‹ U¯ZÍ݇ªòæóâoï6Àµ€[–Ù0ĉ¼1Ç'lÈ) ŠOý Øöðñ?ˆg=«Œtú.(Š‚BAF[¥ªîyJ%|ãÝï†ùOÿ„ç{n®²²‚ŸýË¿ÄeO~2>¶¿k®¹W=ýéTÕ­0U(°‰ž¦)À ÷ß>! ¦iB–eHAÞSp€›\àÛ×]‡Ï<á ¸ócÃ7Ÿð€$IH;†g>ðžðæ7w]“½» Ã0ðÙÏ~6êo‰™aÊe1çW«ÝÓ¦e‰©Üû ðW §¨žr†afËóûajÂPKIYÿÿÓ?}^ô¢êC)¬KKKH&“(‹X__wB›Í&NŸ>íìÃÄrÎ bá–e±^ÎfÅqdÑö.6Þÿþ/ãõ¯¿×\s¯xÅŸ¢XE$I°m†aÀ0 œ~ôQ|iF.‡g꺳@ÿò[Þ‚ýÝ]œyÊSð³gñ‹Çíw߀“Iär9lm½ ¦iÂ0 ”Ëeüâ{ß‹/?ïy8Å"LÓÊðÁ¢ÿ¿ü¿ÿ/dY†mÛPUßûå/㺃kÑu–®ãø߈¾þz<|Í5HXpà…­×ë¸þúë£þ‰˜‚äê“ögøíóçñÿýÇÿˆ”,ãñÿëáù¿û»ØßÛÃaš&lÛÆ-—]†ä-·àÜç>í LÆ /¦iB’$Èqö¶mÃ4M¨?öceY¼°ß{x_úë¿Æµo;^þÝïâ‡ø‡ñ¿>ô!dHÙ,Eé2*2G Mó?å¦ÓbÁQ(¸¹¡”2R(ˆ EÓ ½Ÿ´èð“Ï‹ã2™ÁŸ= ü‘núÐ+£¾æˆA©|~èyašBOÈå†S^)¢’ œ¹ðÃ?|~èC{XËå2 …n¹å–Ž÷“É$677'ÿ2c½# Ãpתª¢PP‘ÏÿëÝlö¿À4M¼öiOéGÁç ¼é«_ůþêžùÌkñ½ß«v…પ JG²K%ˆ ’'²,d2”dçWVpÉc Ã0`YÞü½ß‹kÿîï8vÌQF[¿ÿûHœ9ƒg<ãøØ£â’G'Êdð‰cÇðÍk¯Å7¯½Ö9¿7ÕÂ4M(Š‚j@‚Ÿ³ß›ß h,M¾ñ  ZÅ®ÇË»ººõ×ÏDˆmwz@k5á5]X‹LFxOéA‹•AÃo÷ö:ÿ–$W9¶,7וaæŠ2óbš80Þ»å5Ä~…Bg§ƒ0l[{öööñŸÿó·qã×àÂ…»üdÔ·Ì C8¬êuWM§Åî ÛÚz¹Ü£¸xñqøÒ—.Ň?ü~äG®ÄÛßþ1\{í7 Ã ïMù3 Ùl²,㡇ÂOýÔO uC+¬©T o}ë[ññ>ø ‘H@UÕ™,¶Dy—Tµ0—›íz'¶m£\.CÓ4¼ð…·á…/< Ëú!˜¦é¼ÈKI/EQ ë: #L&ƒÿò_t”J%d2|õ÷~Ÿüâ¡nocïoþ¦·Y…b…«UH2™L‡‚Ð…¢ qÐ)ˆ'>íiBñì<@¼™ªª]y×;;;8wîÜÔf<*˲óÛ¦iï¿´]–e躎r¹ I’`Y^þÄ'¢`Y¸qm ?´µô!h=‹ÄæfפpòàÕU 2 Æ$9¦Ê›LS¬nBÆ“:È*蜰|cmoï¦~&j¨2»ß»)IBäü5ëH|dyôÊìå²wg %f˜YŒ„aX–Û^’€ÏþëøÃ?üCüÅ_ü! … ž·»kãMoú^ûÚ§¢Õjá†þ ŸÿüŸ€c”WUÕyV>ý‹¸üò·`yù«øð‡m¼éM&®¼òJ¿õ×Â̦é†ìÒ2ãôéE­ÖÆóž÷e¼õ­W§"y°,1‡¿üåßÅ+_ùnœ?9®ºê¤+¡iºãà’e‹‹²-öú׋z2ŸúÔ¯A’®ÁË^ö”ËeضG9…G½†q ¥R–eaww’$´ZaÝÞÞÆÆÆ–––êêê*NŸ>õõõ™ëÅêM³¤ã(ÒIáUãR€u]‡eY“" &YÝS¡H×uÜþêWc¿P€©ªÐuïxÇ[œI²P(t îA•£L.‡/üõ_ã¯î¾Û(¸ú o€ ˆÅp±Ü •ú×ô+ùÈDN¹<[azš¦¡X,"“É@Q',—,x>À §•$ Š¢¸ùwšÉˆÕº®‹Á)I€¦áxÐ"å ;‘ɈŠ3~wÒ øOYK•ëUòje2âÖ.¹ä‘Iÿ<Œêu Ku©4ÝüMêkJí_¦A:-<·þâJÜÿš‰”ƒ˜Ž!S–e|êS7âž{þõz²,w¤yáwÞù*<ÿùÿªúOC¹ü d³Àóž÷tìíí¡X,baa™LÆQBUUÅߨàéO¿üÇe?^F©H’Ã0ðÞ÷~ Ï|¦¸ŽBá ¤ çólÛîk¬gކá†ã*Š˜oýׯ ^ð{øêWÏ¡Ù|1¾ùÍk‘L¾—^ú%|ò“'ñ¤'= ÙìC8sf ?ó3ëøêW?à¤ÐQä£×záÂ/àÉOþ'|ûÛ»h6Uœ<ùlû,²YÓÑ”>»ˆ@(9åj>ò‘GðÜç®C–ߌB¡€zþ0C)¬­V •J+++X[[sÞßÜÜÄÖÖ–£ÈêiÝÙÙÁ‰'B÷o4H$õÜz[¾”JB,KL*ƒxïüضX4躮ÅEqÞQªÒâœÚÙ¶t:­µ5H–…ß~ðAÇ*Hp¡P€´¸;ñ}0Ï=¥wõY§Óâ- 7¼üå(ˆµ{?U7Ô˦PpGãùöâ ]Šú§¢I“î4ŠÐt±òÕuš¦aooÏÙW’$Ôëõ¾ÖÂ(1ϲ:KoÒ4òy·j 4|š—W!‘¤ÎöOþjÞ'NœŸøuÅMÆ£‚„ªºSkÐÜoYn Uus„($—DÓ0Üßšì‚ôÌ/Å”,Ëb»m‚8.dY ™y¬â˲=} «‚,Ër<<œÈ0øú×ã _x:~ù—Nd ¥‚|æ3ßľð \¼øøÎw>@ÁýЮ»®Œóç/þ?øÄ'^ÛñLñ^Çç>—Àe—%ñïÿýÓ`š:¾ûÝed³2Eš`Δ€IDAT»ß-Ž©V«N[Ðó©Zuço±®Ìá=ï^ò’àñ*Ižô¤'MüûfŸ>^…Ñÿ+ ûÅ?ÿó·ñ•¯¼—^ú^¼éM)ض‚'<á=xÑ‹>…åågCUÙ#o¯è:þ%/ÊåMôfüÜÏ}Ïþ3qÛm¿6ò½y—TÂ?p$éMØÚzÓX¾»¡ÖF£V«Õ¡¬+++ØÞÞÆ… ú ÷öö6*•Š“C¸´´„R©ä i6›( h4Ä"–¼(ãÆoÄ¢¿Óé|Çâ™8Hµ µ g³ÍÍ-K¬}e¹ó˲ išcÑóaÑu]\QUÔëuGyÖuï½õV<ç›ßĽî:Üðt/¼wwa~èñ°þó;‚“.ˆbу¦›0¥’ÐÀý‰N´êbÄK¾½rsØ)$³ýÐ4Íñ†f2H’ä(¡$ó^C äóyd³Yär9‹EÔj5H’ÖÅÅΆ¦)h&Ó)Ãx4e¹û¼„ \²ì>߃ø½È±ëVàvo“Þ§mãvÜö"®2ŠÒ\’˹Eì¨+‘e¹6úi¥)”:%‘’jšâ çõBá½¶½PU]ÛÎ81 š¦9–}¢X,:óÇcó˜¡s e{|Ð:‡"düP ú7¨áõðÐBÿþwÝõt¼ô¥ƒ®ëxík_Ç<æ!Ï3'ƒÿôŸh‰óýc嚃ñõ|b|úƒÎdYu–Mª Üvˆ§B!8RÉ[#ï#ÓSb#XÆÇ S,ËêP:½òàOÇ#9÷T KËø¼óYŠòBHÒÏ tmªêæ‘f2b¾ö.û‰w¾ó†±uÏ›”J0R[›0.^¼ØwòÒ®­­ayy­V «««¨T*X__lll ™LâŽ;î@«Õ©S§œcÆ…ÏM¦i¢Ñ¸çÎ=©cRÊçÅdFÖôz½[|ã¿€npãÅ%Ɇ¢”‘ÍŠ°]o(c¡P@&“ ìVp%“Éàëü ¾ùœçàÚ'<ÁíEãE’`ÜÈ+Ï+¦jUH«÷|ÔHÕÛv†VÍaPUYNò0q‘ï ¨ʨaŠ–e!›Í¶mÔjµŽÉ¸X,v(²º®<ÜEÞå4ø 0~jµª…žñ¢aç¥/ÅÕ$k"ì¡SöªU!ßµ`š°ÿÇÃüÙßügg!«ª3ù%®TâtJ1dÌ:(`íLò¹\çpSˆeœe<*ü¢ ˆßuw·ÓKJx‹XÐñô^¡à>cɰ÷âÀ¶m§8]/„¢QÆe—=ˆbñ)]EÍüj{VEÞÐKz6Ò>¹\º®#N£P( X,BUUìïï;ç¦ïö °l]×Q,‘ËåP.—<-ê)uC’¤Â ½ã§ Ë>ó@’T*ÊeW™¤ÂbÇuï>šæ©[BPÎ÷4ƒã†e¼7¦i¢\.wÔ¿ 4/Òúž<ñd|§ùï}ïKâÔ©G:æ:o:žm»ÝðÂænÒ5¼7Àõ-<Ðs„ê„Kâ¾´©­ÍÆÆÖÖÖk @eêyi)×5‘H`iiɱä4›MìììàŽ;îp¶///c{{{¬ƒ…r}‚Ð4 ¿þë ÞúV oyËûñ ¿ð¢ÐÞ£P(ìãî»ÿ­ÖÿãĈSR=…óîîîÁ0YX¯2JÖÀAy⟈'^{­ôãLÈUSÀ%ª›˜ëÅ = ÜT¯'q‘o?äá‘åΉpÈ^.—Q*• Ë2²Ù¬£´æ‡7çÆŸ+=L>Nþë_Þò–ƒ?ò®ûˆV! ……<úYÈ?~L¼ÊOüg(—<êk^ n¯HoõƾHÒÔ´CªâtmqRPýÄUÆ£bq±ÓîçgeÒ¯ÐN Ã0ºªSÓxÜqKÞ@( ^£kµš;(Úg8ùæ4þ©7I+ ]ŸG¡pÞ´úÜL&ã¤Å—\vÙecý>X¶Ã¡ßÒÛY sÐ~‹~’ ò€z“ô^//ªiº @¸ÁF×Åüî_Öôkdž® "—s¹0o°ŒCKu]ÜÚ1ÞNŠ C‹mK=JɱE©^¨ÎÁ ÕØÓéñyáé:è¹BÁ•ÞgŒ·Ã4xêÛߎ§?2\‘ÛÚloo;Ê)Źonnöíý·´´Ôe½p᮸â çÿ@§â›J¥Ð÷cPÕ;qù凪> [[âAF}äYlïþÔßý©ŽxJý-_†ñÎ@×Nô‡¬å­~nHÕ%žx~E ®¨A\¯¯q•ñi`šâw£t)Ú7z\“ÈïÎårŠm'%Šª®ëeù|¾#d_<ûX–]×aÛ62™LG~ mÛFWªO‹¾ÅÅEn®¡_Q%ñªV›7 |õ«ï¼á vwwâa´@wÓ3ž‚g>óGñOÿôx<å)?ä|Žˆ"¾Ër#ÔÐßð(ÚwbWþ%@×±PÌ@Mý2¿øT”~IÈ2¥“zs;‡mZ ¸‘ÃÓÀ-®¾È™õ€…8Éø$ k9Uü-—ÅÿIIi4þb4¤4Rޏh5°èD=Pî UD¥}È; ¢~voÕLðŒñæ–{é¥dJJŠ‚’رÓ@×~BO®-zùn±>·±û'ØK{ÞeÛ…êÚ¶ MÓ IªÕjhhø0Qa¶-yDöö„ ×jBØ3ñå‘ð÷ú"÷÷Å>Š"&£R)xÐîî¶OŸ>Ý~å+_Ùþ…_ø…‰ÝJœæïI±¿¿ß. mY–Ûªª¶UUmçr¹v&´ñþtûûâ'%q,ÄüH¢°»+¶Q­ºÇѹf’wzɲû hÁW«u> ëõvãĉö_^ýÄÖÞÄ<Ïßõz½]¯×ÛÕjµ](Ú¹\®-Ër»P(´wñ.†Xµ…üÒ4­hLcÚÞÛhùÎþ¾¸èRÉнgõz‡üÓ|Øù{ …õõ¯}ûU¯zUûôéÓ@õzÝ 40¼½ççž{îq\ÞI2ˆÝÝÝv&“ 8ÎÌeY>Ôd^¯w>ƒIQ»Xš^ {R&ÕÛ÷ÎÑO± RržÏ÷Ÿ£t°=ÓŽ”Aäe\ŒC¾ÛíöÈ‚Ý]1a¶Ûív©Tj …vµZm+ŠÒ~ÝëÞÛÎå‚çR6ûB+ßl[­Š1Gs™#÷´aŠ«ZC𫉽½î[ÙÝm·%)ÚÖ4Ӛçw?ÝëËq±¿¿ï,¦Hé¬V«Ž¢©(Š£˜û¼¡sO…ýýþV RI „°‡œ÷\C®Ö¦%/QÏß“À«¨–J¥ÃÇa!=ÌkÄóÿ¬^±)ú¯sj5ñȈÂÓqS¤€ á„Q7¨¥”´ˆ †çïá©V«Îz=“É8óhµZx^¤)+l½0n¬×]#÷´¦îv»ÓHTß¼·]ÿùwºà ‹ûþ¾XHÒZ¯P_–_©Qä¥oHp2™tÊY†íím4 ¤R),-- ]±ªR© Ñh`ssÓybçàĉDXµÇñþT(§³WÄ…7ØË^/ŸÿPhŒ×Ý–‹`¼,ôÎ sï›y¥ ÂÃ})ŒW9Øßû• b¿ ‹Î°_ãàÚêžsxKeÛǧþóªdÕ|÷¶©×£ÈIËår°,레ɋC8:‰â† !ÜË!§Z•ö<û..ºÉ¥S ¢ùQûEZ–›NÕÅ龂Æ)z¢¯cwŽBãã(ããf”V-þ–Ô®À†fšfGIow*êAEÎlÛvÂv…Z@M ÿ2Œþ±™ƒTÁ¡\¨{}àhȶ¦i(—Ë]ùzãB–;Cƒ~~¯È ŠHiNS˜õö£¢Ißû ’{JTô~ƒÆvÊrçbp{{"·52nš¢ÞŒ,Ë=»ô‚êJâgÈfÝv”Þ6d㞢¨vªªŽ¹-Z‚ò -K¬ÓÓyÀ²`|Ï@ýIôn#Açñ—¼Ÿ"Cå°z{!†lmm ¥¼žxÜþ*¾þc¤€sû×0ÊÁq´¸SîùõzT3Šyôk”±•|÷‚¢ LÓtʵL¹,–Åb°æ&I±t'r":OêÑ3q”ñÃ`YbAB¿UP·0Û¶Q,jÚ¶m;EŽLÓ„¦iQƹh1M oYö÷Å¢<î C*dšnóÀÃ(—ä±¢/9Š*1O²íõêè(´5(ä¤Q1.híë÷¢Rõ왩zN7CF›ZÍô¯¿äë Ä\YæKÆmÛF:îèÆF±ØiŸÈçÅ4DA~Ùõg¥VG±EÓ\íZ–û÷’—$Ô=U-+új÷1ḻÿïßýÝßmŸ>}ºk[?.\¸Ð¾çž{B{衇zn6Z–{_¯×;Š+ Ú½óG ív[î³] 9Ç~»Ý~Ö¿äP´Eñ"?™¶È+Ýmwç‰î¶E)Qó}N.àœÞ÷2íîBJ{íð\X‚Š8ùWÚÁ9°S`Òùã–ïv{´¨zÝM§‘û ‚~T«îɼ•†f„a /M£0Ò¤™tÔ´çðIÒ+…¯V«9¹~^vww|©q掕½=77´T Ï%õ'f×ë_Êînp^Ó(Ôj£WOó0Iy‰Ëü=*ûûû#×ÛØÛs‹Ç©jxí+÷³Æ'c…d¾” «(ã+t0xþîO.—k˜Khéâ‡IaœUŠžM’‰ä°ƒZ(Ðl6k5 §0ò®R3â~$“Éž1ñÔÌx\ô³üQ¯±CAù™½(Ax1ðЙ#êEðƒ_nPÄvÞLÊm•=çò¢ 3Y>8§ó%Àõ¾UϹMt‡2ËŸcC„É›jûŽÏ ;„xN˜¶|‡a-dBò³‡‚ŠÂ’œÍFX4:aé”’—ˉíÅ¢xoXãúQ#.2> ÙJ½îH„)¿O’¤OT÷TQ”‰äŽ Ãn„R©¿«ßßtÒß úBà ŸÉL¿Ký̲lprT‡ ‘$ï) ~þ~} -K8v( %VË“ú Ñ>ä¢\€#¬Ë8µ–$jLÓºå9ÖSÂÛWpÌP×°\Î;d§B¡€T*åôiàä®ÞqǸ뮻°¶¶†J¥õý„ÒO8-ËLaí¥lJÊW¿¼²v~Á9®&€›öÅÿýÅŒ€îüTÿö Öôlëõ…e5,äR>¸ÿñ9¸ÊêâÁËÿ™Ç!¬™‘0M1ßÅ #IáR¹œÛCnšt]D„ysMg ‰9$”FI¿¹išX\\tz‘îîî¢Z­¢P(Dêëm¸=(Å¢xÕjãY„KY%FÑgúBE¾ C$ÆÙ¶[ ¯^¬Ï)mWÕ)Guëº[Í. 2Ô ºÐ÷6*gb)«A½S5­SóFÊÆ ªP, yö6lõî“Ív[,zþ¤ž¯@ ¿›ú*¬;;;h6›¹©­V FËËËNáååe´Z-ìììD}O]Õ°¦iö_ÐÛÕmÃÐ{¢ RØêõ`–CŽ'…•Šù·{×&äý¤kRüdϱa·Ÿ8·õàžz-òKèÎWõ~»póz©pTùà= Bg††òW Ã8¼‡ÕO¡0siï\Ï‹‡-м·5#NcfD¼Åk5MC6›E©TBµZu”SQá:Ú"é´ØA)úÁƒhww̽Ûㆮ÷žTRV¡ örkÊ[˜‡Õ€ëm4Ð]œÈ«4è•-@<]$©³X’¯ +p=§Vý©ØR˜Ð’ç8ì+êUh‰f@І؂x¦'†Aµ%”oÀ•Œaá¤q@s·|=3ŸäóÝž¢7¿ùüÝßýo¼êUßI’ ë:,˺ÍÄ(—Ý 7„$‰Ê TI–Ý8fZÐxñ†îÇU÷«8Òù@×uì1[VŒôİýC¨ò¯iŠybŸ;¨{&“ öv)—Åüoš1JÒ0T­ºJ.ÂÓ Ñô»ñB_…5‘H Õju¼Gå°ã¬¤zé×OoàpÉ 61^¨¥M®ÇvZG)µ^•rT½—•ƒð<ÒµúZÿM +ý?èÉS+!\é²á¡É SÁõzo‹žì~­'u¨p`Êe£ÙÞ²ÜÐÂ9 Vs½¬±yˆ1c‡Z(zu9Ë~ë·þ/{Ù.Ló¢oi=.‹Û|Þ ÿ êuG­_¼­ ¨ÅÌ0áq@U§Þ‹yÞ±m¿ò+‚t:j|ÉçÝbÐ4ÿE¶Xíå%E.d9Ø€ÃÌ4Ô¶†æjI ÿ})WëYŽÐöNÞS/£ÎyZ¬”Ën‡±Y˜Šû*¬©T FÃQR[­ Ãè*®D¡ÀÔt8Nô[«[–5Xß;ÝE‰¼Ûh…ys½ h?ý<±AÇ:Žž=_òjæzGJèü~óp¿ûA<½G UÒim¸Ey¡ B±r9±Â™óÛL"º‘‰^'#ÕRÉdöqüø±µõ¦¨/¯rùbòHÊåºcàfˆcÁ²,”Ëe†ÿñ?Àg>ó’Ð}IQ]Xp£Ë#Óï(š€ž/¶=ºsþé\bš&²Ù, …r¹ à óO–Õ™«Z«EXLȶŪZí\?Ålž6Í÷î›&}sXS©–––°ººŠJ¥‚ÕÕU´Z-'˜Øb±ˆ¥¥¥žUÇ¢`Üä=P9„+DA ¥Ÿ~ÞÙ¬o_ozmóŽ@ ®§v½Yy_‚[åw©Bxš©âñ¢ï^òß“=Ã÷8"¥ i"„f¨¢1Ô¬Œ [Ä=¼a<øÓ"5 øÙŸýþùŸïA­CY>¬ËŽ JÌà†|>t:íT¬¾ãŽ—áþᱡǷ‰Ò"ŠÅî:/SÁ¶Å3¦|ë£iƒaŽ ¤¬Öj5Ç¡¤ëbã… é‘Z¢ò»årDl0d98˜'® T%˜šò’—Æ[€éÌ™3NáAÊKOÓìWšÝróT©T Èå§Ò>z퀨~Ûk»ÿšiM’˹¦%¿6ˆôW¦‹¯ð; (ßOõàßŃ{ö†hè4Ì9¶ ¼ýíƒaƒK 1\9ã¸Yf†ÐõîÅL­üã?Þ‡Ÿÿù¿?|¥ìqcâÅãŒÓ4|¾½½=är¹ŽbÒÞ  „×ÖM û ¨Å©ÍŠ…å2S ÃÀ ®ÕjΜM2]*¢Äª+E ÔjBÖcÚ7†TŸ¸=èk"‘Àúúzà¶ååe,//Çγ:(º®»Å£ú,\€PŠ‚öó†{sG½Û½Bá÷Ôúä :cšË½’å=&,NŸ<µ½²€ùÉÍÁmù£À ÎÀUZeàÆ¿½_:ù¥¨¯vbüÖoý+ÞñŽ÷ãoþfˆ…0åμˆffŒ {¶má1y!Þüæ˜õLµmáUâqÆ ‰®ëÈår…/ C( $ÿÞ¼†Ñ™ßˆm‘­£ÉëT(ˆødÎ=eŸÏÇ2ú€XÌÌŠy›‰ †atÕ%ðʾ$‰ú.Å¢PTîÈñHÅΉ;¨x: tÌT >ÂþJצÙip!½·zlÈåÜ ŠqʆhyõU Î@ k¥RÁÖÖ–ó÷ÖÖVVV°¶¶õõ÷¥×¤l,Ðà:z÷Yíµæ9ŒLÚÞTÿùéœye+h@RÎf/çðbQGƒçâ£;ͨ/fr<þñ¿†ÿôŸ†üÑýV†™!‚B¨ÛØ{IŠ¥Õ‰7”Æä¯lšQµ²,øu[Q‹ñ‚ž™>Åb¹\®K¾ýu#½µçbÇŒD Œ±CÎT(‡ukk ËËË0M¦ibyy[[[]ínf ]×»2ƒ„Èøó\mt‡ûqû‹•áæ¹†Y8¨õR ¢_«³Ïvf® ªo¹ÙÃ+3%à NТ¼\.£À¹qÌÑ‘Æäª¤ú¡®G±zÉ3Œ˲`FלãºE3Ï,ù(ú*¬Ô®feeÅy<«F#êëïI¿Ç.…µˆp…µ WQ *¨¤ùOîÛî¾PÿS ¼(’vðònK§»ÏÓKàL¿*ùx 1Þü&Ó4ãé]-—ݤB†Z·H’ÜQ {¦l1­˜ÊDeY]u7%fLd ¬°Î"’>‰wyWÉÛY9>ºÀ°BL½æe¯‡5,ä7sð>Û4» ªŠËyLSXÙmÛÍÃÊ03Šw®÷¶D˜È80ÍÁ|çoÈ0C@ëMë¿™QXûõdŽ,Æ£0 ¥g±°ØcÂ-ÌŒ¹VX©Ø@] «¿íŒïv y§AŸ¡ÀUHƒ 9Éžc{…ò˜¾í<Ñ3!•Ý4ÍÑúMòBš™A¨;Œø¿t:B¡0™ž«¶-úêI’ø7›‹“~^#MûÖjÅÀŒ ­[tÝ-°dÛ3Vlšú0Œ¼–åv„™I8Rmb ÜÖfuuµë½J¥‚3gÎt¼·¹¹9ð‡Sl*• ÝžH$Fnc½…>ÐúN9£þã¼ÖLÿaE„÷A5’k¡Q$Ö!f–IË·šè-Ë­*jÜÂ'™Ø3m›ßDýûr“2Ëg³bœärâ_ªâ_ ”ËbáBîL3f™~ÄA¶½ØFÛ–!Ë®ízqQØAffÏÊjlˆ“ŒŸ=ûI|ç;Ïž©ªµpÁÄè«°ž8q¢£à&àƒÐh4P(Ðlо"ÉdårÙ9g³ÙD¡Pp“ªª({6ÄۣɋaÝʪ¡XRè¯ò÷Ÿ‡Ø0…Tòœ3ìA"è§#x·sŸÌ™`Zòí…”Uñk2Þ%†9 CU]=0¨?åØ(Å ó*ÃaãLU]E•šb23AœdÛ [òG•×jœÊ GeüÏÿü"žñŒ‡0m-Xa}C‚“É$ÖÖÖ~ Âêê*–––`š&Ξ=‹¥¥¥ŽâH&“ÎöF£J¥2ôÍ…)¬¡9~ D/T¿sŠO"7L7,”¸pp.H¯—a×0Ü's&˜–|{¡ž{ 3 ¢ñ0dYè„ä©àØ SýCQ„VQ*qäÂŒ'Ùöbš&~ìÇþL³SaUvZ2ÃGßÝ}"þÓº4ê¯æð°‡ub ú³³ƒJ¥â¼¨íÍ0Ç·Z-G¹M$XYYA³ÙD£Ñ@³ÙÄÎÎŽãÕM$X^^ÉjÖ»)0ǯWñ"­adtæ öëƒv^ Ý=]ûÁ!e±fšòíG’„lsÁ%f’D)ã~4Í­SÖŸrld2<ÿÎ9q’m?†aàºëžÏ¥˜CW¿æš_Ç _xuÔ_Ïxà5ØDXa5 ·Ür VWW±µµå¼VWWqË-· Ü“5•Jass³£5Î… ˆAÿ÷†§R)'taŠ!Ê eYÝ‹z‹j¢¿iÃí»j#\aM£w!§a›!+ /˜bÎ4åÛ Éz ls†éCT2„¦¹kÓ4¹ç*s(â$Û^h^W”9pØó³&Râ*ã÷ßÿOóalçÔ½‰1º³³ƒB¡€'N \.Ã4MçU.—qâÄ œ:uj ok"‘ÀÒÒ’ów³ÙD¥RÁòò2’ÉdÏAÑjµ†º¹0¹ Ìñ£ð|o»Bó½' BÂC~ ôVX3aÃ’ÉpHpÌ™¦|{¡Â3#W+§Í0>¢’q?4¿ÓÇ0 VX™CÙö£ë:ÿø_\UsXK=3Nâ(ãÙ,pÝuÿ.ê¯f<̃ÒSRX766 ª*677»Þ÷766þàV«…J¥‚[n¹KKKX__wÞãâÅ‹¡Ûî»ï>Ü}÷ÝÕŒ‡rF’ÂtŒð~®ÇþDý‹*1Sg{{§OŸ†9Áç¸åî¿ÿ~¬®®b{{»k寎ìa‹•C¬®®âüùóýŒiÌá½Ðu7— -*• NŸ>{ï½w"çŸöüÝ;ïü|ík?2ûVì}š¿\…¨ço²€O~²…g<ãɻשaYÜph >ìüÝ·JðÎΚÍ&ÞúÖ·öÜoee§NB£Ñè[A¸Ñh`cc‰DwÜqGWèA½Jk_ýõ¸ùæ›; ?Mî¦iåð†çûçÔ*ºÃ~I&{ºac,!Kâ¹sç&rþIÈ7\wÝu¡m£h­>ò­‚sÅæææÐ ‡a˜ÖÞ ]w 5º®OVaM§E%VŠcÁÚÚNž<9‘9<Šù»_úÒÛñ‰OüÒØïuêpáÈ ùû0Ý8z‡ù›eà—ù°¬Y·Æ »Š<Ȩkð¾ÖF£d2Ùw2&!$d P(8qôþÁqâÄ èKh6›C÷ 3äÙ¶¼°ñ¾å7AkyŽ dB˜†|{1 WÞíQ<¥†Á +3Ó–q?þpà©ä¯òBûHµlû1M?ú£OŸ}ï*â&ã–eq:Ó—¾ k"‘èê2 †a ÙlBUUìììt¼aÁYZZê›1 étz¨Ï 3äö`µÐ©€z &ÜK^ÊòpC‰§+ˆ=Ó’o/Ômäp`Ëâb^ÌÀD!ã~,«³•ÇȹÛÃ| 3÷ÄA¶ý¨êÓæg1Ïù«‘7Ïç¹»3}C‚S©Z­V_ »·òX“®F9…kkkX]]uÊo' Üzë­Cݘ$ у•VÕ÷` Z«(ïÁ:)x²=Ó’o/–%dÝ0F .—)´e`æƒ(dܪº ëØ½«¦ÙmíäÅÔ‘ ²Ýù™À±cŸ˜…Õ¶¹ilÄÄQÆm{Dc;s¤HaM¥R( ]¥° JÞ^ZZês¿¶¶Ö7Æ=•JáÎ;ït–·¢Ù (J°‡50ôÀEY‚ëeíUXç©2LK¾ RVa•†õ”jšX@ðÂiËx?£fC±(z‡¸ñÄ®‰q“íZm—]Ö€,óBƒq’qÞõ¬GÑlÎÉú#ŸªÕ¨¯bn¨Jðúú:šÍ&N:…íím'¶½Ùlb{{§NB³Ù:ÙºTz{ÜÅ í2Ñ™§ªÀUXýÛˆ ö7“¶…bÁÌ ã’oèûÐVËšƒÆ~L™Ôˆu1ö ÁŠÒ©¤Ú6ç¯2LR¶½Ü}÷¿ “™“Å<3SLCÆ ¸ä’OÏG…wËbãæ„éëaÜFÕJ%°uÍÒÒÖÖÖ&VÑlŠÅΰ1 OŽŸ÷mÊgUá†í¯c²hš«¨ªª¨RÉ0!˜¦‰Ì°%ÕY¦˜C„¹ª`È™ ª}‰9•‰ˆÏ|æZüíß~Ô—1>øyÃx°,à²Ë>> «·Ï3RXWim6›h4NûšT*5Ñêa£j‰·þ6!Ö0㦠·µÍa±íî .Åûµ‡k2¡ø zs1ñ3L¥sÝkªPš¦èX_*u.4Å­d&>€ósöì'qüøc!I×E}) 3ÄúåÍØÚÚ‹úR·Ï3VX jqã·h·Z-4‰‡È JP”chVž*…è­°¶Ý’m ÅÔ0€=߀eK$3™ŒkëyáÎ03†·ÍHFŠ^©ÕºÃ}%©Ó«Ê9ÞLœ9ó<ç9ñXO1̸±,àê«[ø¾ï›#»¿Ï3Êa„F£1ÑFõã ´«ßS*C(° €I¥÷Ù¶hF/ËÝÊ*à ˆ,» ëÀ…gL“ٙś¿:t;Ë^UձÔ]YvÇ+¬L|ä#oÆ»Þu2êË`˜‰ ËÀòò[磶ap8ð›Â7‚ZF…Zãƒ<¥&„—uœë ó%e5—ã‚7Ì¡ gs˜dÿ|žVffñŠú@ù«¶-µ²Y1着ð¬öª¨í/¼Ä0SD×õùXÈûñæ†3Gž¹‘sÃà´‘)0· kÐzܲ¬àà uIÀ°…ym[(ù¼X ù‘e`qÑUVs‡)fŽ:$f¡Ñ~Êe±çÉ•™A £Ó):‡•ª7ær"šey—V&BLÓÄwþAÔ—1^ ƒ»0¯{Ý¿"2,®Øvpïnfì Ã:+øÇ€mÛÁÆPNë¾÷­ƒ÷Õ)MS(ª™ŒøpÃïysQs9¡(˜&‡0cÄh +µGÚÝú²f$ü kÏÊïDXSî^d20ÛëßrY¬sªU7’Á08´žqxÇ;¾…×¼f çº.dšŒþ¶Í5g¦Ä\*¬¶Ýý^h8°‘«êG0ˆ 꺘˜u]LÎ$Äa‹YæI›ä,²m»h •]ï É01Ʋܩ5PYµmú[¯ò LÓõÎ2Ì”øÒ—>†~ôò¨/ct ¡´..б£ëbmÄ)PÌ'O®#“Y‰ú2Dzܴ¾jÕ}Ÿ×ôS£¯ÂÚh4P©Túž¨ÕjE}/¦Ù-?¡‚+¬Ÿý`ü9LªèëTú0E“2 -3eHüì +ªŠÊ03Š7ò*ÐY.7Üݶ9ß›™*¡Ñ`³F¡ Æ¢® JçÏ¿ŠÒ_·ˆnêæQ(päM„Œ-‡5‘HĦ¥ Ð=7†ö` Z‹Ø6pà @ëj·$e6VF=üæáÃ̦)æQ`€â3dÅa9efËêß@…uÜéÆÈL™÷¾÷³ø—ykÔ—N6+<§^#©iT¢¦É¬¬2h°¾þÅx÷Œ§Ý ⣠+«‘Ò×ÚJ¥°¹¹õu˲ ÊªÈYõÎytç¯Jp«¨€–«ªÿöþ>Ì‘ô¬ïG¿kXl¯½ÚÕzY¿hÖ,Û¬rbV͈€96¤Ú>±ñB:G ÁC¶sp¤³zù‘\±ôc~óÒ‰\¼ŒH 'ô%n¼û;vÀ]aÀ¼êta‡kl3e`[»ØìNy4Þõ[Ö:<}—J¥Ò{IU¥þ~®KWw«¤ÒSêûyê~{î›ia$TXVׇ2²k­ÆÅ–Dšd²7ÁÅ4MdÝ2í¶jgA*ºÓ`% ä?þÇ6î»ïæ ‡1˜BA)ô««J‰—VQÌÞ!cP.?ò#ÁsÏ…x]Õ4¦ !##¬F£ÏÒn·Ñh4‚û@4­´išÀ*wñÞAz~*U¸Zí> )ñQìxœ+‰<##¬~—†¡=Œ‘ò'òuø®ïúRpåü”-P¹œ2ZÅX sÄŒ„‚ZMéçW®|(˜k½®döŽ;Töd­¦ÒÔX½:L•|éÒ%lnn=ö±1MoºóMý xï_uCO !º®téíšœ°Š‰8ëëÝß=÷ùù¾+ë>q² T±wß÷}ß2ïéGÚò­®ª¬²|¾[í× é#_*qޱ¨Õ”ÈŒUÝÝO CÉ´®+y½vMɯi*%ŠÙ“‘`)«»1Mßòòo¾ ½mjL2g¤Ú/{!Òé!û³ YL³wËœ®ëý2/ʇŸ°ª)Y õ:‹˜““<ŸWJûÑQï\)Õ‡ Ýl2щ†Í)fí I&ÒYÜYÓ´;#r* V]×ñ=ŸÿeœšP{XãèFX¥÷`2V…`B"L<Þ»+C×õþ"c¦é6 ˜dìï·ñÚ×~b>'¯Õ”×çêÕÞçËeõÓmIJ1ñ‘yøûnšÖ+»4L—ߪO˰½°Íf­VkæÏ°, _ý•_­ Ö)fgØ¿ „üèˆÅ5ˆïÌ[¾“É!=† Y‹XÃãñÞåY×õþ‚K¬‚M|f²-¨za&î½÷¥þ_H½® V¯Z’Ö˽ڧ’Eɸe)Ò3;ÆêuU½:™¤º¤j°¶Z-Ͻ°­V çÏŸÇùóçqÿý÷£0cZ–aH|!¡²lÒP†ªe†ÄžbA%2æ-ߥRW?¸‡µ\fA27µ†Kû&`Èþ'öÂ&>²(Ù’I൯ýõáíɦA ËìíÑ(%=,RÆ¥V×X57&Á²TƒZMU­.xXRÆ6X777í‡xdœÏÉcZ­t]8 ¶··‘H$`._¾Œf³‰JeÆÃRøN ÖÕU dÒX%¾³hù6 cpà·‘øÎ"eܲz[<Öëuÿ•zBND?Zª}Í–‘"Jõ:3ÈHAȸŸÙ3~ CEUÓie¬RÆ—š‘ë™3g°±±T*e?2™Lßsò‡F£ýý}Ïc­V F€X,†µµ5Œun7¶2/ÛS“þâˬ FæÆ¢ä{uUýô¬˜*Ð`%s`‘k¸®÷nM5 ƒ+™‹”m'Å"ðñ´Ñ')#pÀÈ*é!Ïç•Ñ:ÔÁ> ΖJ,Žw*Yt)‘H`kkË×][[ÃÚÚF_TöøøzŒßT*5u½>æÔÙ_uøTEíg¥ÍJ|fQò-kþÀ¢KjSTÐ_YB¹†»}.¬ŠMæÉ"eÛÉW}Õ3xÕ«^2Ý›% Á¹¯›E“È‚ñtº[!؃Õ'‰]r3lR´Ûí‰ÏgÞüUoîZ-Ûÿ5¼›Ñ8Ð`­×™öxЍT*¸xñ">þñ/ôsý^¿ ]Ë!Æj.Ç-NK„¬ßÍfsáŸí÷úíd*ÔúžÏ/ü» óAtðI×ï±û°6›MìîîÚ{Wyg5†íƒM$½ò•¯ÄßøÆ¾ôe˲ð²ÜËÔÞU! «§˜µµ5$ .ü³§•o¸ûî»±³³@­ß¦©¨÷<é:÷vœRvvvÆ.‚ç7~®á–ÕßÎÆs/ÓßO[[[8wîÜÂ×p¿Öo7å2ðž÷¼ ¿ó;ß>þ` Cíá+h¬.²~[ÆOüÖÁ¥ŠèºjÛ4ñíbQ)úhЦR)¬­­aggçÎÃ¥K—fP"‘@&“éK{\•’¨’N§ºëIgS?BˆŸò-ë·§’cšTdH ø)ãñxwöÀt`©†JÈœñ[?þà>‡×¼æÆx/N§UTõêUÖ( ¾3/O&'¨\,ªàRI=¸¾Œ‘Üh4Ðn·ñÐC }ÝC=„ûï¿ßõÎÂÖÖ–ÝïµÝn#‹á˜ø<º®ãÜçT5`)–gY,ÎAÅù–ú†a çe˜&“4XI`øµ†×jjv29Ä`uç 2Gü’m'ñ_ÆÆÆ×~!«þ’à·Œ†ò±Œ¬lÊPÕ4U%ÄÁHƒµÙl"‘Hô¡’,Èñããã± ÖL&ã¹ç5•Já‘G±7œg2™©.β,|mçk{÷«•²æ)ß²uhVBæÌ¼×ðz½ëwèœa¯a2æ-Û‚e/|á“lÕD΢dÜ0Ó4F˸e©öœ ă‘k,ó¬ 6¨x€_Äb1&‰·}åÛg6e1½€ŽòéÁJHÀø!ã΀ÒPï<×t²@ümÁ0€/}écÞʼi*… èaâ#•BŽHIr9¯~õjÝ^_öö¨£¥!—Òéºwáryº“’SOèÛÚ4›MÄb1$‰ñßdÄ·¨î=|B†2•|(¹÷c—ËTxH(™VÆ™E@¢À4òmgäó¢Ý}„x2ËúÝc°Z3 ÈL„Ö`mµZ( h6›MÓP×3G·à!!d&ù>y}ºÎ ³È8Uvf•ïŸ{ÙËÔÌ !dV¥^¯wë–¬®*Yg-2%¡M ÞÞÞF"‘€a¸|ù2šÍ&*•ÊxoN`ïmbf’o7µšòÐ3ÂJBÄ,2n÷>‘P3‹|Ï«_ÄûÞÇÖ$´Ìº~ÛGÃPÆj.§„LI( ÖV«…F£ @,ÃÚÚA"K€ïò].ÓKOBŬ2žËf‘T;²ÕUõ({lBbVù^ûÄ'¸o•„?t”|ë[UÊ{>¯ZJÒX%3JƒõøøJ¥ìçR©Z­VÐC[(ûûûAÁWd<íø"ߦ©”ö³g#Û²iåaÙæì´Ì,ã–¥<óé´ŠBU«ªì¤óeÙäaçì4Ì,ß{{‘ß·ºŒ²°lóuZf•ï4€oùÕ_U2~t¤Öë²lòõ9Jƒuؤh·ÛAoaèºô|åøø‡‡‡A#p|‘ïZM)ìGGÊ{A–Q–mÎNËÌ2žL*¹gL2IƒuÙäaçì4PGYNYX¶ù:-3Ëw:­jjD<ªºlòõ9Ê¢KÃ&Ä7‹ÅúžÿÓ?ýSüÆoü~ë·~ ÷Þ{oЗà ?þ8677ƒ†o<óÌ3xæ™gìMüAñéOû·‹Ûn» [[[ ÿüiäLÓÄ·û·ãŽ;îÀ]wÝ´ÛÀ… ¿_„Eü$,söÊ•+øüç?Øçs W„Eü",söñÇG»ÝÆ=÷ÜÈçO#ß}ëwÄ ‹,øIX櫬ßïÿûñæ7¿yáŸÏõ[yð‹°ÌYÑÁ']¿Ci°:ÓÜ *­ýö·¿oûÛƒ:!#™F¾à·û·ƒ:!cÁ5œ,3ÓÈ7×o¸~“0Ê”à3gÎèMKhµZ÷"$ŒP¾É²C'Ë å›,3”oFBi°& d2™ž Ϻ®cuu5è¡23”o²ìPÆÉ2Cù&Ë å›„‘›:N'èAxÑl6±¹¹‰D"v»X,†ûû‰”o²ìPÆÉ2Cù&Ë å›„Ð¬€Úø-›ƒ3™LÐÃ!ÄW(ßdÙ¡Œ“e†òM–Ê7 ¡6X !„B!„œ^B¹‡•B!„BùŠw¾óï zËN£ÑÀM7Ý40÷¿Ùlâ‹_ü¢çñaÇÆ9>Úí6LÓÄWõWO5¦0^™žYäÛãó`˜ŒGñzÈl “ñ(Ê×p"œ¶õ{Ô˜Âx=d6¸~‡ÿšÆ¢CæÆ{ÞóžÎÞð†Î}÷Ý×¹ï¾û:>ø`çúõëöñãããÎÛÞö6ûø;ÞñޱŽs|\¿~½óŽw¼ÃþÌ·½ím~ô£¾9ˆk"Ó3‹|ûq| “ñ(^™a2EyàN„Ó¶~S¯‡Ì×ïð_Ó$0%xN´ÛmT*lmmÁ0 \¾|Ù~NØÞÞF"‘°7›Mûø°c㟕J­V —/_†aH$ØÝÝ{La¼&2³Ê·ÇçÁ0âõé%ãQ”®á8ë÷¨1…ñzÈôpýŽÆ5MDÐó²òØcuî»ï¾žç.^¼ØyðÁ;ŽòdÜwß}=Þ‘_ù•_é¼õ­ozlÔ{çÅõë×û>óøø¸sñâűÆÆk"Ó3‹|ûq| “ñ(^™a2EyàN„Ó¶~S¯‡Ì×ïð_Ó¤|eÐó²’Éd`FÏsÇÇǸõÖ[íß •JÙÇS©Z­ÖÐc£Þ;/¤´y*•B³ÙD»ÝF*•ÂÖÖÖXc ã5‘é™E¾ý8>†Éx£ÑˆÜõÙ&ãË&ß~Œ™2NÛú=jLa¼2\¿ÃM“BƒulnnÚÂððÃÀP!¸zõêÀcív{è{¥Á³ßܸq£ïZnܸ‘B=Θƒ¸&â“ÊwXåa˜ŒGñzˆ¸e\×õ¯ «

†Éø=÷ܹë!³1LÆ—M¾¹†Ÿ.NÛú=J¾Ãx=d6¸~‡ÿš&…ëœ8wî†Æ]×í~"‘@&“Áþþ~ÏñÕÕÕ¡ÇF½w^¤R©¾Ú•JÅöÌÌ:æ ®‰LÏ,òíÇñy0LÆ_ÿú×GîzÈl “ñe“o®á§‹Ó¶~’ï0^™ ®ßῦI¹©Óét‚IJ²½½ýý}d2÷lTNúææ&‰„½©ygg±Xlè±Qïò™â¥šäzü8NÂÅ,òíÇñy0LÆ£x=d6†Éxåk8NÛú=jLa¼2\¿ÃM“@ƒuÎ8K¦{í“h·Û¶È}|رqŽÏƒYÇÆk"Ó3‹|ûq|ÌsNR¾£Ç0¢

_<G¡P˜úõ„ŒË0ù€r¹ ˲r¹ 0M+++ö)‹ö±z½Žõõu{’”Ëe¬¯¯P ÊÊÊ jµš}^9nY,ËÂúúzOZ¹\F±Xœúõ„ŒÃ0ù–ã²—oL³Ë8å›,šyË~>ŸG½^Ç“O>i?oYVWWmEˆ¿%ÏNœò)¯ázM¢Ä´òþgög8{ö¬íl¬×ë=[6(ÛSÒ!rttÔйzõªýœ¦iB¡Ð¹zõjß±d2ÙÑ4Í>vttd«V«x¬Ò§ioo¯ç5@7Œ°á%ßãB'Q†²O–‰AòìÔWܽ† ‰*³È»Dgãñ8·1ù Öcš&Ξ=‹££#¤Ói˜¦‰ÕÕU z0 !„B!KS‚CŒ3%AÒ€s¹UB!„BÈ©€VB!„B!¡„U‚ !„B!„„’¥I ®×ëøÕ_ýUÜ}÷ÝAÅ7®\¹‚{ï½7èaøÆõë×Ñn·Cñ?º~ý:n¾ùfìîî=”±yë[ߊïÎ/Â$~¦9{åÊüîïþnÐîáá'LsöúõëˆÇãøÅ_üÅ ‡2\¿ÃO˜æë•+WðþÃ@*• z(cÁõ;ü„iÎN³~/ÁúÊW¾o|ã±µµôP|css;;;AÃ7Cñ?’±D‰»ï¾›òrÂ4g777ƒÂDp ?aš³Q[ù~‡Ÿ0Í×ÍÍÍÈ«×ï(¦9;Íú½4ë2²L2™ 2™LÐà !aåaÙæ,™e“‡eœ³d:–Q–m¾’ÙX6yˆúœåVB!„B!¡„+!„B!„PBƒ•B!„BH(¡ÁJ!„B!$”Ð`%„B!„Jh°B!„B %4X !„B!„„¬„B!„BB VB!„B!¡„+!„B!„PBƒ•B!„BH(¡ÁJ!„B!$”Ð`%„B!„Jh°B!„B %¬Íf­Vkêã„„Ê7Yv(ãdY¡l“e‡2N¢ÄWñ¡Íf…BÁž™L¥R ±X ÐjµP(Ðl6š¦¡\.ý]2”o²ìPÆÉ²BÙ&ËeœD‘@"¬…B«««0 —/_T*ûøöö6‰„}¼Ùlö'§‹|XYLSým@­‹Àú:°ºª^S,v_$”o²ìPÆÉ²BÙ&ËeœD‘@ ÖV«…sçÎb±R©”íéiµZh4ØØØ°¯­­áàà èïŠÌ‘b8{Ðuõ·e©ç Zöö€dRýmÊ0Õ4 PPDzY VS†¬œ¯VSFïw(#÷½ï½ O?}Û\®…òM–Ê8YV(ÛdÙ¡Œ“q1M¥G—ËJ'·¬àÆ2•ÁZ©Tpþüy¤ÓiT*ìïïOä}‰Åbvª#‘HØ¿@*•²;'‰bp®®vgÏ*cè¨òw.§ Ïb±û>1PÞßs9 TRk: Äãêw˪A×kökÔóò÷Ñpíš2r[­çã©§bs¹vÊ÷éÅ0 äóyÅÛ²¤PÆÉ²BÙ&ËeœŒËúº2XÅPõRmŠÅnpÈ g6¹a¨×omÝ‹}ìî‰Æ2ñV1P×ÖÖÐn·(á¯T*h6›ØÙÙyŽR©„b±ˆýý}ܸq·Þz+~øa:)Úí¶cïæ¯ÿú¯ñ|`ì1œt]yHr9%x–¥ 9@ D+÷öz#”ƒ0 ñxI§é¢\6ñ ¿ðr¼æ5¿‡ïýÞÇ‘ÍfÇaYÊå2VWkÈf³Ðõ2n¿ýö“qÖ`YŽŽ (UÄ4—=Ó4Q«Õ ë:4MƒeYXYYA©T‚&Öª‹¿ú«}<÷Ü{ðÙÏÞ à»|ÿÎç!ßðøãcssš¦ammÍ÷q/#"€JƒŠÇã”—Ëe$“Id³Y¤Ç~õzº®£^¯Ûï5Métš¦Á4M¬®®boo¯ç3ÝŸS«ÕP¯×étÉd9—àëŽ;a°.Nç59ÙÜÜÄ•+Wæö½r 'AòÎwþ*êõ8VV®ù~n®ß$hdýn6›=†£_pý>œ¨Èf§{¿aH@H‡eY0 ò'ÿ‚—½¬…?øƒ'ðÂ>‰vûÕøå_~;®]»Š{îù÷xÕ«^@éD_õU?‹¼àå°¬}À£¾ _þòÓxî¹Cܸñ2L¢ƒOd°¶Z-ìîîbgg™L¦gCv"‘ÀùóçGN°v»J¥‚sçÎamm 7nÜÀîî.*• .\¸`Á^ܸqcàdyå+_‰7¾ñØÚÚšî?³¤èz×-•z êõ:~í×>…ïû¾ÿ>úQåa³, ÅbÑVƉ¯Çg>óüéŸ~ét¦iâoþ欬ܗ¾ôƒøÀ¾õWoÂÙ³¿‰{îù ¼èEg°¾~þÎßy¹­¸§Ói†MÓpõêUÔj5hZÙlõzš¦!ceeÕjÕ~}­VëSÈMÓ´'=†A±XD±XD6›…¦i0 º®C×u <ôÐC8<<ôýûž—|ÀÝwßÍÁ†a”Ëå`š&VVVìß Ã@¡P°("S^ŽÓ4ÇÇa’ɤ-wÕjuà8jµVVVlYN&“0M…BÙlÅb¦ibooÏþ|]×±²²b;[t]G:î™ò·Ì-MÓ iZÏëvvv°¹¹9—ï—k8™”Z­·¾€dÖê¾”Nw½ôÕªúûÄÏÔã¸4M•móº×ý3<õÔã¸ûî'}'×odýž‡±Êõ{y°¬nÐɲTö z^é=ôÍøüç_ˆ÷½ï×ð²—)G„áX|Å~åʧð‡ø |ÅW´±±ñ"NNT¯—ašuÔëJ?WzÏ—¤ð¾÷i¸víkðÑÞbŸ¯\¾µZ¹\×H~ôÑ?C³ù>¤ÓJ§‘8Ò•+/Å3Ï<3ÑõNd°Jª@&“é;–J¥J¥† ;ìïï£ÝnÛÞ¶±»±±1t‚JÊñFq‰ÂÄãqÔë|Ó7ý týK” ×j†ýÚl6‹ù =dâ%/ù5ü‹q õzwßýk8:ª"™¾ç{þGG/Ç[Þò|d³J‘8sæ‹ØØø^üâ,ªU‰d¾ýäÑŠbˆÒ^«Õppp`?¯ë:Ö×רÉ$ÑY7ƒ¢§ò¾ƒƒ˜¦‰z½Žb±ˆt:B¡€jµŠr¹Œ ¼õ­oõý@ùö1>Å Sò[³Q§‘iYLÓ´#¦{{{=h¡P°£ªNC37N( r¹œõwFaËå2òùŸWÞ~Ùrë­Oàðð ¾^+e›X–5Ðy9LÓ„éXàåïÇ{l.ŸGn¹H&“=ºÎƒ^ÇÁÁíxÍkþàÓŸþ~é—žÆK^òÓ”.qñ"ðÉOžÅ»ßý~ê§>Œ¿øKÈår¶óÜ4M¼ë]ÏáãÿV|ÿ÷߂߸/£Óùe¬®®Â², \½zÕs|–üèö>W(¨u;ŸWÑÝj¸ÿþ¯Çý÷}ßûo½õÖ‰ƒF¬âYñJ h·Û=9ñƒðòÐ8sçÏœ9@Esåyçï§]×me\ ¸Z­f+à‚¤&“IX–…K—žÅcý·žsItÈiôýáÿï:ÿ„ïû¾?ÓO¾ÐV(~ý×ï9ù<õH§B᫼~ìñ{˜Éd%—–¢iŽŽŽÀÓP„d2‰B¡`{‹„R©„T*…?ÿó?÷ýÿDùîÅ4Í‘7~q,H41›Í"™L¢\.£^¯#—ËA×uÛ(Ëf³=õq‰Çã}ò6oÜ×.Ʋª†¡”Ãä¾P.Ça”JJA7ŒÞý!¦©Þ#©üʤRés9uÓ0MàÁß=—k¢ŒG ÓTʃÓàtÔqñØ;š¦Ž‰([–’ÇAçs’Ï+¥eŸP<®¶¯¬®vÇrrk˜”íhãÜ>!Î?¹·8‡€w¤IÞ/,Ùg¨ÜŸ$k¦^¯Ûç¹óNUÄè©§ímr:<ÜÁ¿ø~¼âmýKê0M³O?:sæÿ‰3g>:—ïˆ2.œ†©ü.r(r!ò'¯ùò—ÿ^ö²—akë¼îuðÙÏތ׿þ»·Y)*ÒµkÀûo¯‡3!Lì§èiÚóP.çqt”G­6¼ÀÒ µ?™Të¶dÈøÉD«DQ777qáÂûùV«…‹/"‘HxF_hš†ÝÝ]4 ûµ—.]B,³ÿÎd2Øßß·S t]Ǫ¸Z—/Ož¤º ²O„KÒk%MÑt£ëÀý÷c,%=þÓºétƒì€\n:ÅcRf5TÇáÞ{ï™ 0 §Q¾-ËÂêê*âñ8 …‚‚],m—ÔlÁ0ºQ~@¡¥RÉÞ[ªë:r¹Ü@ï^Ô…ß)ÚºÞUè7 ÷tÕ´Þã^d³ý7/|á̃Ó(ãQÃ4•¬ÅãJÎâq%k@¯œH © Æh<®^[»ãqå(E±̺”‹ÑZ«©y!)üðÄOø£l‡s›è⨔Œ1Á­Ð‹c4™LöÔË`gW‰*ÈsNË]Ài'“I{<†aàî»ÿxÁ þ-J¥’I ¿üËŸÄÏÿ| ¹ðÎw¾†¡æÜÑ‘šWµÚ¢PøAÛÐ5MÓÎÂqR¯«¹óþÁ|"¬”ñ`þ}ïkâe/{z)"¯†G<ÞÝQ¯«µ°wMîYVWî„RI9þŠEYGUM›½½Þ5ZÓº £_™„yØ 7u:Î$oh·Û(‹h4=ϧR)\¸pa¬œûýý}looÛ)Ä7nÜÀÎÎŽýÞf³‰ÍÍM$ ;𻳳3tH£ÑÀááa(óçëõ:jµš-ˆìè‘„æEÉú£‘Âwž/M‹”p&“‹12£Æ<åeò ¨B Aï’½â!–ª¸"£¢\X–…jµÚãåv* ÝýÚ £ ^UóÒé®a`YêfáL—CBöë̓yÊËi[ãD¹¬d«PèutFWI1ŒùÜ$B«ª¶÷¬bˆaáÜÂ"N,9žN§{î}†a`}}¹\étW®\Á3Ï<Ó—A3+˼~‡gTI²Ç¤Æ…èA’%&NÐyP.«y0cE"PNñcAÖw¯b–âJ§aµñx×i$é÷.pýŽΈ¾èI·ÝöOðÆ7>Ï®£ßú­?†ßû½ÿ>üá¯x®³g•:©Oβ”ÃÒK¯5¹\V?½î–¥ŒãyÛ ÓÈËÄ«Ðl6{ªOº9¼Õjõ”Ï–b<*j;íÅϹùÊ[,¡ë:ööölÃUŒM§7O×õžu?X]U ñ‚¶bDŠyË‹ßò „Cá‘ýÅá—¢AîT«I«îF Ëê.ø’~kšJÑHªDªºÊ‹°ºÞ5(æ™L0oyYÖ5|™1 u_ÈfÕ½A©ÓÎW¹Ç˜¦R¼%uØ™zV¯×íÔIgD è“1ÈýP ˜b±ho_)‹=kÍ<åeY×ïE㬂î,^t£J¢9ePŠÐùuY]U ¼3bäì’0*‘GÖ|YÇGùHÊåÁ)óâ8ÊfÕùdO¶®ßáÆYÈSþ–uLÒÆ76þø‡ŸÇ[Þr ßñßr"Ïq¬¬tù<ìí?B­¦ädHMÇÈ3¼L”Üh4°¹¹‰Ë—/Ï\½,‘H ͉w¦'DIA‘j ù|޾˞L¯ý”Â<<ˆìóË ßîý§ÅbñxÜÞ錆8Y6cUö™J±ÉØ—©,Jº{ KES Wq'Å7 ,ƒŒ/ÃZ8[8];é#Uªu]ï©~-8÷MyíýÓuwÞùø÷ÞÿwÝõû¸çžß€iþ! …*Í®6/Q²IÖqÞJa¾Z­Öç›'”íÑ8uÙ#*Îúxöi<þøŸàùÏÿfXV _ÿõi©‰*öuî¸ã>|ñ‹ŸÂýмøÅÊP4M÷\–>Ô¹\n®Õسô”FŠb±hGÏ…|>ß—5æ'’ÁR¯wÎx¼[]ºPPF@¹¬ô*§²ŸÏ«àÂ4‘Êa®vö)»íJL¸~ý/ñK¿ôïa†Í!º|.§õ’tßtzòmw£l€Ri¶Ê¼ËÎÄ«³åJT‘q§—-™4ñ‘¬âóŸ¿ ¿ó;€iÞ‰R ¶Ç¥V«Ù%È‹Å"ÞùÎ?@¹ïi€÷9Òõî^ `±Þºj•)¤ÙS&ýN5Mëñf³ÙH*šR™@Oÿ1IÍ‘y8(RjšÊ@h2Ic• ƲÔÃk-—ýnîc’Áã|^æâîîñïÿýÓ¸í¶CÜvÛ7àñÇoF,à _ø³ØØx~ï÷¼Çѫؼôä¡á:m(2©ò®ij'›Œ(Q¯w{„IZŽ(C@×x•–Nš¦æž{?”üLöî)‘–„8ç£8 K%µæKQ®½=¥€çr–]ÄHŠqÔëÀîîñÅ/¾úЋðÁþÎ;‡ƒƒ,+Žõ¯€O}êýø¹Ÿ»…Bv¬ÞÙ„L‹´Þ0 Ãΰ‘~Ú¦i¢^¯÷ìožg»˜|^­µAõm§Å+šËu+QW«4ÈdHK,Ù¦L&ñÜs¯Å?ÿçwã/x5Ló[t·Ý~Ób/ˆÜ²UdpLl°V*ìîîbmm Tùëíím4›M\¸p!èk‰;ú(¥ó%º´··‡õõuÄãqüôOÿ0Þõ. PˆcooÏî™%Ñ…‚R`¼¼íN£1—S}•¦M ®ÕÔ{ÅKïTœd?‡»ú!ì*›?öcÿ?»º·yâ=”6,âõž9‡eM¿ ×ëƒ3¤·c­ÖuüŒ›–ã~xR÷ö¸G‰ Æ4»^vg1I ”< ݈)»Ÿ¤*’^Ûê>“Ëå®ÓðÏI_*u£³ÔqȸÈÞTé ß¼»WÚ­·ˆ~Q.«×1e7H&2X[­vwwíbCN4MÃææ&666†–Ê’Z­¿I´¤8½‰étÚ®pÇðmßÖ}½×â;n4SŒ[¯œxiB-Ê‹¤’¢( “ŒÝÝFƒU2ˆr¹ ]7 i·Û†›¦ueì¤s…½'è¦ÙJZ­D2MÏéoç|Ï ¤_©D¦d¿’xÕí80 5>IÛ¹Îx\ö§ÐX%ÃI&a·œ½µãñ$ªÕn%^?*£2¤Pä°ö@ñxüÄXí:ôœHÛ©¢+:• Û/æÕ®…Æ™g/g 7C ènåËç½[ÉHV€è$8&2X¥É°——"“É •Jáøø8´«¤©8ÑuÝsßÞ<*üŠ:ÉM@ŒQÎÆ±ûþâ,MÈ ¤™õí·ßÞ³¿zTÚ¸8Qd¯†W$Spg w§Báœoõz·O¤<çuα’z½ëÉ)ò!ΦõAH ¹[¥PY©TÂêê*J¥’Uzª=YN$ÅWÒ|½*†Ñ]Ÿ¥¶‡8Ë%»K¢ªRÁÔ)îR; ŸWF.}6$ Ôëu˜¦‰túÀv®xEèE–I};x¦ÚÃÚn·‹ÅúžÔê& Diç±Hjµne<©R,ôÓ俌ӼŒœ êõúIë¥É¢ðRxhÔk†«4x1K¥¢¼²2™K^6„‹V5&²— §žôR¯×aY–ÝsX¢DNt]G­V³£¨X__·›Çd?ª§Î¬1/ŠEo§8 t”••á…ëêuUÏcàOÈpË=ÔjuhZ7z:èÞOvø™È`Íd2H$(‹¸pá‚ImµZ¸xñ¢ýš02Èî“¢‹$—›`rH•qïª×5r@)ÙO?}Èb<¶œ‹%)2ëÎ3s"yhGGý9:ÒÁ[ª{xpŠZÉ’1¹|ù#Èå®áöÛÿ!ÞùÎÄë^÷yhZÒvnÝ>¨* XÉ–³W1!aA”viÑ1 YF‡© ÝŒ/ªUö«&Á³¾¾Ž;ï|7ÖÖ^k«µZ]M&ް–Ëe Üÿý=Ï' ììì}=‰ìF}Õ[Ç;¹~}½·‚”sã+ ŒçÆÄAHOl¶ÿŽ$õç#Øîä´cš&ÚísxãŸôP¼×uá Ê…_(¨»‹aô¬â„‘ÊbuW‘&Èî¦}„ àòå6¾ã;ž·¾õMøõ_¿À¯Â4M˜–J¥÷§’Ðaš&jµ4M;ér°>¶± t‹( Cú¢V¤˜X6ûÚžZå²·úL¢ÇÄk*•£>ŠF£ÃÃCÀ¹sçBY¼l.éGjÄà”»Êúzwöɦ‘l¶k¬:7Èq}J‰=çfF@½§^W¯•*8@·Ù ÕH¢ë:^ô¢pä£R*‰årJ– £ÿîâ¼i²êFú9I)Iiê7O¤ë=ãÈ`YÊå2î½÷à#yÞýîÏáû¿ÿ/>`¿FÚÑDQ—65ÃŒUÓT·y‰¦JewFGIT1 Ãî,Ù’¢ÖKVoÏËÁT{X[­b±¶¶¶F­V+´Å–ï«ôÊ =¥’Š@¹#Oª—‚ºã¸«4ÊÐ#Uú˜¸{ú8_;®ajÝêPbp¤ÓݘŒÙOäN›NÓ€]×ñ·û@ø¾®z]É«sîI”ÕK>GYÜâN™“¬ID­ÖÍ,pžGŠbQitš6Xæ4Í?ã¸Xìn ¥—!ú”ËeX–…û±¿ à¼ýíWðó?ÿoƒ!S!¿¤o¯Wå^'î¶a^…Å 3RÿÅ0 O²¯²Ù,r¹œÝV/›íîbtuy˜Ø`ÝßßÇöö62™Œ|éÒ%4 \¸pkkkA_“'^‹r—ÆBz¹³H>Ž×hÔݦPPѬRÉ¿]åb”ÊùÄ€†GÀ £Ûû¤P=vËêF~¥j®wo¯ÆYÄÆ0’xË[žô0¼æmM{gI§û Æjµ·GŽ—ÇªVëßÔ*iö±™óz­äȉ3É}~iÚ,wOë wo©¤^+Ê5­;g€Á}x܆6ñDö¡ ZxUÐC"d&òù<ë’$b 2Z¥‡T–ŠÀ„DÃ>ñ‰§ðÿãz_‹&©V ¨Û¬»%‰6¬ív•Jvtvvv°»»k²ãFZ¥²p*•ò<Þl6‹Å|‰ÜzÙ¥A\ Ù%îd¢JM®÷¹£Y³âÛ8Ñ §q*ÝÇeߢ4ŸuÑÙ¤Ó}L¢Êno£äƒ)Æ3)ßnêõ:€l8íyw¦À¼pÊÁúz·ƒ§<¤ÓJ¥Ð™È×(§–¤!W«JÞäsK%%çΜò»Tp™é´2Ü%Úêl¸ì–]ÓTcº‘`iˆ[.ãÎv{î_q2> g¼ýíï³Ï>Â}¨d,Â,Û€Ê}«‚Té]_÷î÷îì“-ÅÖ¹7õôvwS,ozSßñ‹ÝÝRß–>]§ŒoÿöCÜwß¾ó; ozÓuüÓú3øéŸn‡áž-ŠEåˆY]UŠËÙ³ê碾++]ÅéêUïl Ÿ»l†ÕÕÕ¾ªÕN='›U>4'AûHx»ŒJ~ËŒišxñ‹ÿ1r¹vwSpÛÏÎt`ââ \_W¿zÍÙ³½úÕœ˜È`•tßíím´éfâ­00µÀùÚýý}\¸p±“ÀC=„3gÎPžF£ @,ÃÚÚZÏ>I‘í`Nt]oÁ¥Ób°.š|¯AÈ·W¯~m8+`Õ_*ïõZIÚ…ŸçCþu6» ‚0Èø Þõ®C|üã·â‘GÞ‚ÝÝ-|ìc·bmíkÆnóAN0M¥5)ËÁúݲºû¶½Ò³òªÝÔžaÔë]çæœkN„]¶u]ÇúºÚ»ç®¿Q«u—4iàü™& V~º·2qÒüèžG.—³“òœË VŸ‘Ú{{jÝ—ŠnNLS9¥î‡õ2^݈)˜ºëþþ¾mœJžûÎÎŽ=!)©TÊN1N¥Rvšñññ±}\H¥RhµZS_¤—žÚ‚K$Ò!ßn h6ïŸýDó (ƒ5îÕÞ¤e™˜0Èø ,ËÂOüÄ/âg~æGìèÓ×~íí(Duc“l<Ôu¥H®tº¿Ø4 ›µw?'Ù^c]_W¿;·cÈ^m¯=Ûã°ÀÐ`˜ePE–Ü…f±·×û÷‚íð"Ý Æ‘)éL0Ë=K”twyf]ï "ì2îüº>üáëø¡ú#<þø ™/Ð~÷wÚt`g•Q2ö÷÷ñž÷¼7ß|³ïçž—|Àã?ŽÍÍMhš6´}TËY¹Ý«*û¼Èå”'˜¡ëBÉÛc=†;î¸Ã×á„aý„®ë¶“ݽÏYý×M½®Ä¢Óñõ« ‘_éÓ3©Ê.E××½çU±¨”Äz½k¨x©’õxw7p#Ž&é >¨óãÚþø»¿/ºõV4›Í‘Ûì&%Ìë7ü‡ÿð%¼ä%o›ÞtGGG¨ÕâX_üov;o"M¹Üí"YaîjiÃÇùeˆÜ‹ÌKç éVàå ×Y9é}â$3Htð;ž~ÿl’÷wFp||ÜyÇ;ÞÑyÛÛÞÖ¹xñbç£ý訷 å±ÇëÜwß}=Ï]¿~½sß}÷u{ì1Ïã^Ïy÷âÅ‹}Ï ÎÁAïs\.7Óũ5h2WÉ‹ç‡|w:΃>8ò5ÎoýÖïu ”¡~’É G°PÆ‘—iXô>.;;ï¼ô¥2—kž˜ díÚ5µÈãèÈûuGGÞÇöö:Eß³YuÏ4ÖÌc zýF:î\»v­s횯k׺Çr¹~=ljóµK…¦ ¿ðNG}9𦾴A2V­v:€zíÕ«ÃÏW(¨‡œ7VB¡Ó)•†ëo£ÆêxÝï|Ã7Ìå+ ëúÝét:ÿÇÿñÑN,ö_;{{{ös×®©¯y˜ §Ójé ×®)¹r?稬ٚ¦djÔd=8Pk¦¦)™Íf•Ü•Jê‹ôþ££ñåoL#/##¬‰DÂ.g­ë:ö÷÷m¯O&“™8Ê:Ì‹Åìã­VËnãü}R¼:ÄX–Þ^|’þE"É¢åÛM¹ |Û·=ô×NØÇÁ‚–ñAü¯ÿõ[xè¡Wø{AEÞk¸at=æÎ½¨RíÙ‚YãzÆ}N6»ø`Õj7Ó0Ôø …@îƒa•miÃÇíL<ÞÍè•5VuÇÙ?gêB‡ÉB©¤¢GGG]eÏ-ÛÕj·§õ ¹Ÿ¤™W¨Ï4Õ?Á²†ÏŸqõeMÃ{¿é›ðÆ9|½a•qxï{oÆ/þâÝÈf»Û™ÆÙiàêî4L³?R ‰¼Æã½½Ô-Kmðj\.«çÇY{“ÉÞüggƒƒƒÁ“} 27'ª¬i.\¸€‡~™LFçÏŸïéç4ŠT*ÕWB»R© ‘HØÇ2™ ö÷÷í㺮cuuuª ´¬þ5"´ûWÞV$r,Z¾ÈýºÝþHx[6 ¿_RƇqt´‡|SÐ_ÏàJˆ†¡&i¡ Ú²\»¦ Qpüî¿âqõìí©ï%VFHßGXe»^¯Ûkº³…s.§lý9w±òqܸÅ]”úk×”,¬®ªTu/$­q}½[ðË‹yWOO&Õ˜#°‘2¬2nšÀµk|Çwü ¿¢áÕÌu½·Í—T@—´[÷žÎb±×Xu¬É¤ºŒë(t;^Òiõ9ÕjÄ.^k£yZS¯ÈÂX”|;1MÉ, ¡|‡©ïi±HƒÕ‚q/j5૾êü³öÖ ¿E癈°È6л…)’v™ôçe4T„IÆàÞ{ÿßôM_ì—"©ê]Y™=fÚþÓ¤±ö° ¤R)<üðÃös»»»ös>ú(¶¶¶P©T‚¾ž><*⇷¥  òÜ©ð Ñug[·Ê÷°¾ ‹Dn@dixÿû¿ˆx\ÜÏÚ·‘ÒÎFê¼DÙ¸ºÚÝ»Ç9AP«¿ù›üžLvÓ€¥ý»‡ Œ‘k£Ñ@«ÕêÙ›Ún·Ñl6±¶¶fW[[[C»ÝF£Ñúš†¢ë!Rlöñ‘Ð!5B]Ââ]çüZ, xì±/áþûç_Ár"Â"ë$òÈþÕõõˆ¬†¡ª£Já—J¿„  \®]; ^7w=M§½£^$F¬Íf™L¦§¶Tvî“V*;HÜ…ÍXp‰,#R8Î4ÍpVÀÖõp(ññx8ÆA|¡Vî½÷ƒÁ+:NJ%V¤&¾a’Édt:Þ9Û}Œ³Çœj,K5Y[†Œb¤Á‹ÅÐn·{ž“>¬a5R¯Ì¬P·´Q z$bH¡:õ{ˆ]ða˜wAô™$sÃ0€—¿üÂe°â¦iÚ²Í6Òd·u4!# ÖT*…f³iW k·ÛÐu½o3¶¤Ÿ9s&èk²I&û‹„>Â¥žD é „Ø!–Teî¥Z*öö€§ž: §Ì2#Îý«‘Nw2µZ7‹ P(·¡gd•àT*…L&ƒÍÍM¬­­Ù}™$tßn·qxxˆíímd2»jpXaÚY6’ÉÞT±P:d4nTâ+RÛ0ŒpÊa>ó™îb K‰´fE )l÷ÒÇX}Xc±.\¸àylmm kkk¡Œ¬ºõ˲§Ü8 KaLS‰Øƒ¡Oy'ÄLSmE6 =|ò^,'Î]BfÁ4M|èC/Š–Á©üe$ÒíÎ0 äèÔ&#Ë`ÔÕÃÃCÀ¹sçì=¬a4TwfJ(òä‡!½IÓìÕB]t‰Ÿúõº®5ÑUâ’-c+¸Ä”`2&†¡õºì:®ë)Á}ºË`­T*ØÝݵÿÞÝÝÅÆÆ¶¶¶‚ÿD˜¦>o¼÷fDB&À²B¦¼2gBç„t¶ô dt]ÇË^ö– ‡19!ÛF‹a¥RHô–0ÛÀ˜{Xwww±¶¶Ã0`ÖÖÖ°»»Û×î&ì„"OžqFWC§¼wÖí»Cˆœ=«~ÒIC–Ó4ñ¹Ï}Kôü‘0 ’PÔÝ`fZ$i°J»š û9‰¬J«›°âÞJú+!âî5Jù®×ƒY"œ2ošfðÊŽÖ! >a¾û»_­ý«„Œ‰e…‚Ê$Üé(ÕŸH¨+ ôîUÅbA{,ÜÙY¡/ºDȈ~Š…a‰ºÞ[;tNÞcÈŒH-MãÒI–“x\ çáÈ| Û}„ô1¶ÁEzeÐ {õ:ÕA9èQáÎd ¥Ájš¼ß0ŒnM: É2b^÷º·²à.YZd—i\p PÅNy/ =Km°º |RŒB×™KO&Â݃5”2ÎB4ÄG$ªë!lictΙÑu?þ¢·›B×U['BFP.‡dÿ* Ò¸n‡ž±ÛÚlnnö=W©TpéÒ¥žçvvv&D³ÙD*•ò|>‹MÝ:guµÛψBä’ŠýR2/ùú» …Ò`e˜`é™§Œ;1ÍnŠd( .e³\׌Eɶ˲ðÊWÞÊî0d!!ã…Bˆì$”Œ4XÏœ9ÓSpIðîi¨T*h6›=†n«ÕB¡P°‹:iš†r¹<ñ¹ÁÊÈì_¥—g©˜§|Ê¡-JMh2¼!-5ó–q'¦ »M(•öÑ^*)ÛNLÓÄÁ?:ÖBaѱÈ”Œçr@±ÈÎd|F¦' lmmý˜„F£ÑÓßUØÞÞF"‘€a¸|ù2šÍ&*•ÊÄçl¶úý«d阷|½ÙW¡tÈpÞ-5‹q'šÖk†Î`%KâeÛÉ_üÅÓÑ]:Ãx"ž!㦩Ò•úJ½…„’‰÷°6 T*û!mo&¥Ýn£X,öyWZ­†ÕÅbX[[ÃäöN€sD¢kX#ddb!ß@7ºÊý|€Jsû¼#S±(Dhö?‘¥#HÙV‚ ÑÛ¿J"EP2^«õá×[,Kí$¡gì=¬º®ãâÅ‹hµZ=Ïïîî"‘H \.O”&¼½½µµ5½ý\ô¦§R©¾Ï…iªì”HehQùZæ-ßB©Ôý=”Ñ&gU(²T,JÆËÖ×»u ØW›Ì‹E˶“ßÿý?Ág>³-ÝE0 °ql4BÆ-Kµe¿z5DÑUÃà¶¥ˆ0V„µÑh P(àÌ™3(—Ë0 Ã~”Ëeœ9sçÏŸ;Úº¿¿V«å™Bʃ8/ƒu^ò (…çððÐö€:;D¦¨Y‡‡‡sSv‚ZÃÓénFA­V Ÿ¼[Öò¬ã!g^ë"×ïAü¯ÿõÕ(æôÅ‘H ë÷<2A­ß€ÒYD¶MÓ ÇÙÍâÑEtpß Vñ>ôÐCC_·±±V«Õ“ZàÅþþ>b±t]·«“£R© Õj M+VZûÎ;ïD:XøÉ »"wsÝÂLñäe5×ñ2Ù{“F¿AZà Œ$OÞ#ˆ¡yõäýp·  Õ€‚ë\‚qò¹u(Ãw=Fm&“Áwãwã5¯yï_ϼäîºë.lmm!“Éè]g™Iœlmmáî»ïžË¹ƒZÃ躎lØRÃ~Y"ÖÖÖð]ßõ]xÅ+^áëy¹~{Q«/xÁàî»_¼Ø/Ô/Â`€,²~Ï£Lë·ivƒ™¡Ézt§î¹“Éd¦Z¿Gîam6›H$#'Žù(¯þ¹sç†?sæ å’Ïtþ>.n§IèÒÇŠeèiè7M(ÃOìêT¤3ç8^‡26 àèä§×ï”Ñi9>;`Ïãs‹J'?5¢«¦ïµNÆlœCŽéPFkõä½yà®ÏÝ|£ÿ_ߢäè]gCa­Õ"¶‘œŒb‘2îäìYµ÷ɲ¬ð(;N¸*ò%ÛB­Ü~{éôïýUL‡³¨ %Aʸ,¦i†K'§³?Œ4Xc±˜¯i ™L¦ÇÃ(¥²^™L&ƒýý}û9]×±:a/§2¯ëz¸&GPPÑJIÛu“8ynʈŒCzºÆaùä˜ ©‡2*áz Ð5F ®Ï”×XPÆh]CS¨žŒÍ:y­×=Ñ‚2ž ŒR'”‘ì0jÃãÀàÌ•©Y”|Û_Ã[:,Kå,Ó`]*-ã@ïz^«Õ “L9çï3‘&Ùv²·¬¯Ï'•Ÿ XwÌ Ã‘)Á‘a¤ÁšJ¥Ðn·GzXd£u,›yP[[[ØÜÜD£Ñ@»ÝF,Ã<0ñyBU:ÛOÄp„¤äf=ž×Јº)B‡ò¾$”¨¡käzu(±ÐÝ/ê•¥'{NÓŽÃñþAÚäÇK'Ÿ•ò~@ÍÓucò¿äÛ™šÅß9¸ÕUzÜO)~ɸ ë][°^¯coooêsÍ…õuuÃa §¥ÇoÙî…[;HðÌWÆCDbë½È0–ÁšJ¥P(°³³ãi¶ÛmT*d2™‰ZÛðÌwO¥Rxä‘Gìý°Ãö| BÓº ÎB+¨Ö¡ŒÉqä_<óét7¹?樂z¾*½Uƒ2.½è7M×s’âsÁ¤;uVIDAT›E4PFÞÞÉõ¬£7ºê5¦«ŽËy†­OY 6fÇ%d[Ú€ùÉ7Ð:™aðJõ'MSƒZ]U‘Õ0EÂÈ\˜§Œ ¦©DKÖò@•ñÉ=%ŽŽT…à°9ŽÈL,B¶…Z xî¹§Âç|$KÍ¢d\×Õ:žË)%458ß"ÃX}X/\¸€ÍÍMœ?Èd2H$vƒáÝÝ]ܸqc`Õ±iˆÅb3M§ÃIJ¬¾êÆsa÷àÿû õgÀ‡ß4øu¦©”§¡«™¬§ï=ž€2” (Cw±ëŽ>ÆÑÝêN÷ÒèÀƒ†¦A¥âÓ!¹&ô0«|]ÿ†a,(½Æ0”ajš*wÍù™¹œ:^¯«hS©Dcõ”㇌ †¡ªK–Ëõ`É(zûMÆãÌ&8Eø)Û‚aׯÿ ¾á"auZ$$òø-ãºÞUBUƒ€ëvdË`M¥RØÙÙA¥Rñl]“Éd°µµ5qtužFwrL’tF÷¤ªÃ;’gYÀ¿2€4ÿÈçªG´\V®ÔB¡{\×ÕsɤJ×C‰Î6 ŒËx†uô¦úš'çqÞûÜëC*J;Ê MÃÛHv¿†,ÉŠœ{„Õ²”Ü꺚ñ¸2JFk2©Ù¬·Ü2’€R¯×qtt4û §AŒÕ\®×X%Är9à?ÿçÒéo z(ÓáÌÛ'ÄE.§Öp˲“L"ÅX+Ð5Z¥uM³Ù´Ó…çQz{VŠÅîï‰#¬bx«?ø9 ýÂ~£ñ‡~øŠª')Óùÿ¡”úd²×ƒ“-z¡×¸Ô´þzwŠm ê=ÎÏ•ÔaIíužB?yÞé<ò²#4×ÏADÔé{0Msº ‚rY)áÃ<Œº®œ/¹œJ{ööØÆƒ,ITµ÷…îñÓõîO]gš;™é4P,þþí¿}hö“ 2 ]Qt•Dб VAZܸäv»f³é{šÌ´8çÃĨrÙÛƒþïÏ| øç¿ ¼÷z«:}óÏ/;ùÝ€Š2y'‰ÞŠ·‚e”J$SCo”5ŽþbIÆÉ¹jÇ’èé=J– rNÝc8—VVT´?W–eõNËêOÿ¸ïƒ,ŒdR-§¾÷ҮՔ̆Z§Ý†èÊŠ’sYç«UÊ=™JYt‰,'Òá.T—H¤xž_'j6›ØÜÜ úzlœA£‰&‡e)Æ­¼è:ð… ðï¾xá[»Ef§ÑXƒ2@ …^c½EŽœ”Ñ M£[íðÞ—Z…2dÝéÀ@×àŠ®ó‘H#¶¥ú}Â=¬õAˆÇ•¢.‘ÖõõþïÙ,•t |Û÷T¯«¦®†¡B·ƒö[)#µTòÞBˆÔëë_,ª{F±¨RåÕ=*RÊeõ3t-mt}öó…0q„5jLä•×<ü°»b“èbñ$œu Ð|mï>=Ññe­Ž;žs¾¦UØÈYWŽYèM÷ÍBµ‚‘qye|&ÑmU3Ê);ª‰ÉdoO³±½òµZ7¢(§ÊÊŠ’ól–{óHèX]U²>s„UוÖ$“‡Ê5 †\»v gφð&mšJÿÑ´^ÇN©¤ŒTËRÏs>‘!8{ƇÂ`µ,¥lk–Ö`%g¢ÉQðÿ üù/ô>ŸÏügÀJw+ê:‰£7ª¡?‚š„ª¤ (cÔٺƫ“Ü·¤2ð –1·s‘´à4·À!‘g¢²r¹kéª7+£Õ4ÕOBB†ý Ø>%Eà *'$tXp÷ÝŸ>Â*E!•QL*£´PðÎB ƒ“ŒIh .I‘SqÜSï‰ Kk° yåoypß}½{SãqàÚ5e4 îè©»ïªTù…ÇëÙË*QR¯*¼’:<ÌØVÿC>#Î,â/âØÎf­É¢«ÎÅ‹ÈsÕᬛZÙ)¨˜ÐbšÀ§>õ)¼íms¾Y‹¢îÞ®$Ç,K¥Â«~iêo©q@È”H陜ŽãR¯w-N,Ke †Ê ã2rø¶‡5L8·áM4Ažÿ?€£á}Ì™–ëÖ{j®¿ÓP‘O¡ìñš,ºE“ïV5Ù“Ïœv^Iª° Uu˜, †!:Ř’þB¥DÃ0X†,%¦ ¼øÅ›Ÿ|ëºJ;“~²çÔI.×m[¨×iUâ ¢¯ÌÕ`­ÕºÛ>Üϯ¬¨çŽh¬F”‘Öf³‰J¥2òDív;èk±1Í^yk‚˜þî÷~Uÿ1÷þRg@JÇèj¼^T9‡ï‚J8ùÌYæ¶ÌI}ÆóP2‘Q.{GW 1†Ñ[/{Ÿ™×®]…¦ùœí"û¶Þtx¦ò’bœèȦi";/Ù«ÕÔùåIpï¿&‘Ä·”àX,š–6@ïï±&ˆÀ|9ðuè/r¤£7­ÖB׈Ã{©æxàm0Z˜º®¬KˆdºÆ½‹,KyÓ}T ‰¦Ù»‡u"d’0BDBN2 üíß6ü=©i*cÕkß6çY ’¡»¾n Zõ± ŠE5 õóàÀ[¶é¨_ F¬©T ;;;As&ÆòÊ›èKrïQuöC•×–¡¢¦ƒN=¬ ’P<ùÌy:;‹˜=RKB‡iª›€®[}=‘û~ÀTRHÄ0Œ®®1QtÕ²TÚc¡Àh =Ù¬…zýæéO`YêÑ›Zæm"dÁˆŠâ[/mÃè¶–L§Õƒ{­—ž‘{XFŸ¢Ðn·Ñhøì ô‘x¼»n›î¾’ƒ0 Œ: ý«;âšF׬ 8Ÿurƒ ÒæßjFú¹2eé{mN§{!’Éë¸xÙÃPû•r9«$üú¯bú½}✩³Ñ: 'ª~—‚ÓiåŒ98Pº ò§‚©Š.]ºt ›››A} ét7]½g‚ Ë(ûØ—º)¾nݨ„~òe:§ UYX*{ó7$½ÆN"dGŽUˆ†J;‰(R\lh³yÃP­ÇΞUŠ{>¯zfsω•Jbú‚KëëJÖYP„Uœw†þ«RÌ€œj–²J°Ð—~ðBÀ3zRAý¦—Qi¡?òêDæeжÂ0ƒ™Dg¦ Ñe&‘J–LÕªêS­ªÉÁ9A"Ä+_Ù½µÃ‹bQÉ?3$ÄŒ\ÃÝ83j,K9eÈ©g© Ö¾Úƒæ‹àËÿ³«ä8³'ëè¸ÝV5Ãî1èo³h’'ã K…ˆêÀ›ÓÃÈà,¸40,™ìn’J&™F"G,öëÃ#¬õºs2¨”÷z]¥Âs» 9¥ÒVi.oš*SFöeK-:!O=¬ÍfÍfsèñV«5ÓgôÜEïlI‡Uj¢kÜ–áR«AEQ©‘,B¾¬R€92oßs´›{ÃyB,bý”NþÄ/žò^.÷÷GÍçUF4dJ££t÷°uÊHû¥dRmc*—»éîÌ ð±­Í$4›M {"$ ”Ëe¤R)@«ÕB¡P°'’¦i(‹0O@Oé—ZDßÓçÕ›ºKäTƒŠzͱ4«s“åaQò Pâ¥9¾¶¶†ƒYû‰‰n¿çzÞð‘W÷F¤²PÆí ý«„ `‘ò=ÐcÉ+™#‹’q]ï¬CÛÚ¬®ý•%!ý¤Ùü^ýêW}éä”°h×uå?¸¥Cy:ÙÉF¦' [°ý •Jagg±XÌ~îøø€šò»ÓøM¥RSåцœ¤äà]tÉð¢_Òé5e°`™ˆEÊ÷@ ƒi4dn,JÆ5MíFì_·×6!#bý~â‰ÏáÍo~Úû aP‘'¾„Œ?÷Ü',—Ù’‰ŒÅ‹.Åb1d2ûïV«…J¥‚µµ5$‰¡“¢Ýn<öÔSOÁ0Œ¾´…E'µ‡Uw¾@\ï?áYÇ{ÈRÑh4ðÞ÷¾ÿøÇ}?÷¼ä>ýéO£R©Ø)ù{°2%øÔS©TðøãÏåÜ‹ZÓI•(`Ž2H)ë§Žýý}¼÷½ïÅO<áëy¹~ Ÿýì̓Óݹ–ŸJdýöÕ‘}¢upµ|[Þ2.ÑU¦¼Ÿ*DŸtýÛ`•MÚ² ;N{>Æ¥Ýn£R©àþûïG&“Á… ìçqãÆÇn¹å¼üå/ǹsçìçzgÑT§þs¹ííÝIbxËYΜ9ƒ{ï½/yÉKæö~Ë7¼èE/¹sçpæÌjvßœ³,*8çÎëñ Ïƒy¯áµšz~h±ŽIzû‘¥!•JáÞ{ïÅ­·Þ:—ó/býž}öÙÁÜÞq*‘õ{^ò ,F”ÁÚn_öv®3ºz*|Rù«J°®ë( H$=JÐÖÖb±t]G³ÙÄ#<2Ö‡6›Mloo#‹áá‡îK=D"‘xì–[nÁ+^ñŠÏQÏM@ kè°¾=\õ¨¬” Ö%%‘HàÞ{ï韖yÈ7 §|{B‡Èd2¸í¶ÛævþE¬áõºÊlÚpž)“§’T*…v»=—5|Ñë÷-·ü’É¿‘ò}êõ{^NÇEéà€RGú   šÆèê)dZ|¬ëöö64Mã>Ú#°©T kkkØÙÙÁ¹sçpéÒ¥±>´P(ØyôîÉ!ÞGgZB«Õy3pÓ—F&[TãèFXu 6JK ÁJ¦bò ¨”à>Ï|:Íý«dî,f W?G6œgJâ#‹Z¿…DbHõÕR‰Hâ;‹”ñjuH…`FWÉŒ4X¥¢ØC=4ôu=ôvwwGæÜ뺎V«MÓÐh4z€²¼3™ ö÷÷{Þ³:a%Ⱦ4²´ãçŸ={R‚lMC|eQò-ô¬ñ8=òd®,JÆ{Ê 2JYp‰øÈ¢×ïu™‹–q`Àö%B&ddJp³ÙD"‘èó®d2™žt9~||<Ô#{`½z¶†ÊÛÝÚÚ²û½¶ÛmÄb1<ðÀ”™Q˜PÆ©ž,K=LÇs„øÀ"å{d1BæÀ"dÜ0ºÓžjïnL“(â‹ÖOr¹¯Å7~#Û2‘űH/UƯœ—Yi°Æb1ÏÖ;;;S}àÖÖÖÈ69©T <òˆ=±FîÛó@×õ®çÒDo¡¥/~ ¸óMj_+ƒQÄG%ßè™'°wÖ3MspQÕà/评, ‹\¿ÕÒæk¿¶ôe“SÄ"e\ü‰Œ®?i°JqƒF£1Th%À¯MâîÒÛÓ`OwÍŽÛ³@ì*ÓI`ø!ß}«§¡!KBÀ,2îtÈíÁÊýÚ$üX¿à*H§ËÐu:dH`ø!ã{{*xÔ·†¯¬GGA_"‰#÷°¦R)¤R)T*•¤ïtw]W›ÿØÎ‰DÓTâÛçX×4FXÉÔ,e„UÓ´nK›äɃ%¢/í=¦ÁJ–Š‘VàRO"ÉÁpö¬éÝÒ&›eµwi¤¬ÀÙ³F¿ÁJÈ”,„5 µ‡µÈ>6dy¸zõjïôÈ“%ò,¦“¥…Ùd™a† ñ›¥Œ°ö`ÐkJ¹!dIˆÓ8%KŽišÝLB–϶d„,}ûW ™‘å°®øÉÿ8û@uÖ×ÙXž,5æ(ùfJ0‰(–eõ;¹ž“%¢Çá¨ë ‘™Ynƒµ ÑþÑ×±‚*Y.4iîdi+lo)Á$’†Ñ_=•ë9Y"t]W«eù<‹df–Û`ý/_þòAFWÉò‘Ë©®«h+{R’%¢¯º¤T€HD1MWÁ¥b‘z YzúÄ—Ë,"F|ay÷°¾÷³ÀŸ<”¾—ÑU²œ”JÊXi"K÷ø‘eƲ¬nºd­Æ*ïd©0 £]eOaâ¡7X›Í&b±‰ÄdoüÇ7þe·¾6!!djù”‚“Í2ºJBÍ42^*•‚6!c1“|[–Š@}„x2­Ž¢iZ7ºÊlâ¡5X[­ …šÍ&%üåry¼7?úgÀÍ/~ýíA_!žÌ$ßN ë ¡Ä7t]E£,K=èµ'2‹|§Ói%ë«j g6 ³È·]-¹NßíÖíím$ †Ë—/£Ùl¢R©Œ÷æoýzà¿¿*èK d 3É·“xœ©d$”ø&ã¢øÈ>¿ƒ*A$pf’o1Vs9f‘P2óú],R¶‰¯„Ò`mµZh4ØØØÄb1¬­­á`Ü´™8:,IH™Y¾ 93˸iªÊ’««ÀÊŠzîèˆÎ f–oQæ©Ð“âËú­ë”oâ+¡4X©TÊ~.•J¡Õj=´…²¹¹ô|¥ÑhLaY2(ߊe”‡e›³Ó2³ŒÇãjïÓÁpõª*0A–M–qÎNÃÌò]­F^™_FYX¶ù:-3Ë·e)8Ë&QŸ³¡ÜÃ:lR´ÛmÄb±¾çñ_ÿëÅoýÖoáÞ{ï ú|áÊ•+K5a®_¿Žv»mOúÓøô§?[n¹[[[ ÿüiäþüÏÿßþíߎ;î¸wÝu×ÂÇí7a‘? Ëœ½rå žyæ™À>ß·5|?°kðƒ°Èƒ_„eÎ>þøã¸~ý:^úÒ—Ff çú~Â2_eý~ÿûß7¿ùÍ ÿ|®ßŠ°Èƒ_„eΊ>éúJƒµÝn®_¿ÞyÇ;ÞaæÛÞö¶ÎG?úQ߯Ä5‘é™E¾ý8>†Éx¯‡ÌÆ0¢

*• Z­._¾ Ã0H$°»»;ö˜ÂxMd:f•o?ŽÏƒa2Åë!Ó3JÆ£(\à p:×ïQc ãõéáúkšˆ -æeå±ÇëÜwß}=Ï]¼x±óàƒv:åɸï¾ûz¼#¿ò+¿Òyë[ß:ôب÷΋ëׯ÷}æññqçâÅ‹c)Œ×D¦gùöãø<&ãQ¼2Ãd<ŠòÀ5œ§mý5¦0^™ ®ßῦIùÊ  æe%“ÉÀ0ŒžçŽqë­·Ú¿@*•²§R)´Z­¡ÇF½w^H¥¸T*…f³‰v»T*…­­­±ÆÆk"Ó3‹|ûq| “ñF£¹ë!³1LÆ—M¾ý3e<:œ¶õ{Ô˜Âx=d6¸~‡ÿš&…ëØÜÜ´…áᇀ¡BpõêÕÇÚíöÐ÷J¿,¿¹qãFߵܸq;;;#…zœ1qMÄ&•ï°ÊÃ0âõÿp˸®ë_VyàN¼8 ë÷(ù£ÎEüƒëw8¯iR¸‡u<ðÀØØØ\ºt €€A<õÔSݸqcè{E¨ýÆéÝyôÑGñè£bmm ›››#¯gœ1qMÄ&•ï°ÊÃ0âõÿpËxåk8ñâ4¬ß£®)Œ:ñ®ßἦI¡Áº2™ ÖÖÖðÐCÙ¤aw¯×"‘H }o"‘˜Ë5œ;wìô@-ívFcä˜f=NÂˤòVy&ã7ÝtS䮇ø‡[Æ—M¾¹†Ÿ^NÃú=J¾Ã¨sÿàúÎkš¬s¢R©ØžAö‡À™3gô¦Þ´Z-$‰¡ÇF½w^ KˆÅb39ˆk"Ó3‹|ûq| “ñ{î¹'r×Cfc˜Œ/›|s ?]œ¶õ{”|‡ñzÈlpýÿ5M Ö9qîÜ94 ;Œº®ÛÿüD"L&ƒýýýžã«««Czï¼H¥R}%´+•Ší™™uÌA\™žYäÛãó`˜Œ¿þõ¯ÜõÙ&ãË&ß\ÃO§mý%ßa¼2\¿ÃM“rS§Óé=ˆee{{ûûûÈd28>>îÙ ¨œôÍÍM$ {SóÎÎb±ØÐc£Þ;/ä3ÅK5Éõøqœ„‹YäÛãó`˜ŒGñzÈl “ñ(Ê×p"œ¶õ{Ô˜Âx=d6¸~‡ÿš&ëœq–L÷Ú'Ñn·mûø°c㟳Ž)Œ×D¦gùöãø<˜çœ¤|Ga2EyàN„Ó¶~:Æë!³Áõ;ü×4.4X !„B!„„îa%„B!„Jh°B!„B %4X !„B!„„¬„B!„BB VB!„B!¡„+!„B!„PBƒ•B!„BH(¡ÁJ!„B!$”Ð`%„B!„Jh°B!„B %4X !„B!„„¬„B!„BB VB!„B!¡„+!„B!„PBƒ•B!„BH(¡ÁJ!„B!$”Ð`%„†®ë°,+èa²pü”}˲ ëzЗD!„̬„ÀX]]…aAƒ…ã§ì†ÕÕÕ /‰œbjµLÓ z„,Êûâ¡ÁJ!„B¦¦^¯S'§ÊûâùÊ pÚ1MµZ­ïù\.‡d2  ëÉI&“Ð4 º®#—ËPie’ –Íf‘N§ís‹E Ôj5X–…t:l6kŸ/£P(LýzBF1Ž|@¹\†eYž2æ—ŒS¾É"Y„ì—J%”ËeÜtÓM=ï³, år¹ï=„LË0yÖu¦i¢^¯4Më‘Ït:m?G„DYå=NÛrÇ‘ËåÇP®§…Ö€±, †aØ]×mP‚].—(Îúúº=IÊå2Ö××í󬬬ôL09nY,ËÂúúzOZ¹\F±Xœúõ„Œb”|@>Ÿ·ÿ$“r®YdœòMÉ"d?ŸÏ£^¯ãÉ'ŸìùÜÕÕU["ÄÆ‘g'Nù”Huf‘÷?û³?ÃÙ³gmgc½^ïÙ²A¹ž’ ×®]ë¤ÓéN¡Pèt:ÎÕ«W;:W¯^µ_“L&;š¦ÙÇŽŽŽìcÕjµÇí¿tªÕªýw:îär9ûïB¡ÐÑ4mê×2 nùît”Ì9ÿ®V«¶Œù-ã”oó’}yÿÁÁA€ý9N¹&Äo¼äYÓ´ÎÁÁý·[¾å9ê$$jL*ï²;ß/z»¼–r=9Œ°†ˆ|>d2‰R©@ye4MëIËf³TªX2™´«C:ÿvòp¾7Û) ƒ˜ôõ„Œ‹[¾MÓìßò7§|“ ˜—ì;ßt 9É}‚y0HžÝ¸å NB¢Ç¤ò.2›Ïç¡ë:âñ8zd™r=9ÜÊÅ"LÓÄÁÁýܰ–¦iÚû”œxÝ  /ùeœ,‹”}Ù+˜ÏçqõêÕ /,!ÓÈ3!QeyO&“888°·ñY–…\.‡jµôåD¬! V«¡V«áàà ÇËÇ­étÚöÚâ}ç¾%&É÷((ã$ê,Zö«Õ*,ËB½^·‹€âÓÊ3!QdZy—ÂIÕjÕjÕn;–N§í‚©dr˜0†a ŸÏcoo¯OÉf³öfo@),RtCÓ´ž¿î¦oBÂÂ0ùeœD™ d?ÛÕ*ÙvøÅ8ò<,+Œ(1‹¼;#«€Š¸ÒÁ3;4XF*þ®®®â¦›n²ÅbÉdÕj«««X]]ÅÊÊŠ&JI±XÄÊÊŠ]Aroo/èK"Äf˜|‚2N¢L²ŸÍf‘ÍféÜ!¾1Jžãñ8ŠÅ¢g+B¢Æ,ò.-lΞ=‹ÕÕUœ={Éd’µfä¦N§Ó zÄIK&“vVéÓ$Š‹³‡¤‘²LPÆÉi…²O¢‚S_q”!dGÞ%;2s“Ð` 1¦iâìÙ³8::B:†išX]]E¡P`û,žxâ 4E~$‚´Z-\¹rO?ýô\Î?ù€gžyFƒ72’F£ëׯÏíü\ÃI4›M\¹r7nÜðýÜ\¿IÐÈú=J¦¦…ë7 ÑÁ']¿'6XÅ@Íd2H$TÊÀþþ>677Çèîî..\¸ày|Ø„vqÏ>û,ž|òIúó’¥åøøxnë¼äP Ïáá¡í%d‡‡‡sSv¸†“ ™—ÁÊõ›„Y¿çááúM‚FtðIåû+'y±úÎÎ2™Œ] [Ó4$ œ?Íf³'•ÀÍþþ>b±t]‡®ëh6›8>>F¥RÁÚÚÚÐ÷ŠìÅwÞ‰t:íé1"ÄI&“€¹,¬ó’o¸ë®»(ßd,¶¶¶¶*˜®á$hÖÖÖH$|_ù~“0 ë÷(™š®ß$h¦ÕÁ'2XÅ3(æ$•J!•JôêŸ;wnèqɧoµZöäpþNH˜¡|“e‡2N–Ê6Yv(ã$ªLd°Æb1*e@~ÚíöXýL&ÓcðÊÞW§W&“É`ß~N×u¬®®ý]‘ 1Mõð"âñ Gè?”o²ìPÆÉ²BÙ&ËeœD•‰ V‰¢nnnöä¿·Z-\¼x‰DÂ3ú:)[[[ØÜÜD£Ñ°ãx èï*ò˜&P,É$P*–Ôë@6;ã±VëþnYêóãqõùñ¸2Z‹Eu¼Pðƒ®šÖ5|“É ¿ÅÙ¡|“e‡2N–Ê6Yv(ã$ŒLd°ÀÎΊÅ"Ο? Ûx8•J¡\.O<¯|÷T*…GyÄŽØúaGËÊee¸ ÊØ†i*cT R1s9e:_·²ìí>§ÃPã’h©iªçâqõ¥Òès ʰµ¬~ƒUŒY1Xóy ZíØ¡|“e‡2¾üÔjêþtŽÕêhG§e©uÛ²ÔZ/k¹83å±²â}®lVݳÓTŸoÀÖÖ½xÃþr®×MÙ&ËeœD…‰ ÖX,†4›M{¿j,ºQ{b±Ø©œ$b”V«Ýç CÝôÅðÃreE½.Vï‘÷ÊM]Ó”!*QI1$…x\) Ù,°¾iÕõ®ò’Nwë$†o<®® è*2¥’ú ]¤Wµ¦?¾A8¥'ž¸ÉäÇæóOƒÓ*ßäô@º®Ö=·³Ò0”CÓI.§ÖsY5­ûpfâ”Ëêž´·7øs- X]íÿ\¹9×ò££þ÷‹ÓU~—sÉ=°R¹‚ÃÃOòR¶É²C'ƒòºA*§ÞoYʦç³Y²#'2X677qùòeß TÒM›¯³Ü¬‹EïÈbµª^#Îlvºèc:­ù k”ЇÛ0Ôq‰„з܉¤O‹ôÊJ÷úœJü.Ê‹ËîsˆG^ÒŸ˘Ÿx¿ÿ!„Ì‹ZM=Ĩ[YQëš‹ù¼Z¯™4ºÞUd½–µ²\VçK§Õzè\Ce‡§s¯³…‚ú\1„-K=’Iµ>;dg„T>cœûT2Ùuf&“Êy¹ [BÈ鯲ºº–sÞ²$ëPr'å $SÓ0ºr*ve©µ>¡ŒU±ÜNÑY˜x«”Ã^[[[äw¼Tèzï¯d²7² ¨›þ t]§Œ« ¢PPF (é´ú\ËRÇeló^XK¥®€ŠÔ&“ÀÕ«Ý”d'N7V¯œÑ€¿ÿ÷Çááõù^ !„Œl§ †ŸdšÊpu®k…‚Z7Ëee̦Ój]ç¡{-º†à ’ÉÑk½Ü«ÜÑOy®P®M •z²œŽn‰$ Ctx\ÍÕz½ß•¬9MSç—9)YÎy" ätR«uí`¼ízbPšf7ðU(tQ"SάÉ̬׻¯w“Ïwƒh^cp©ŠEu>ç˜ç•¨«ÛΗ‰«omm¡R© Õjy¾†=˜†#‘KùgÊÂèµ(f³þÞðG±·×MõÃÏùsQU}ǽæQ“xÑß!„¸1Œ®2t ÓìF E9–5V”`I»u¯½ÎµOR c± o2Ù»]cÖLB!óFÓºiëƒ 6z¿”2'™ â½AF’ïÖ9$[Atwê¼àt¬;•u™;bœHš~>Ü}÷ë‚þºÉœ9vw˨׻2-—õõÁFk½ÞkzÉh6«äéà ?ëÅ]­×{3sâñ^gé(ä܃œ<{{½»I™xëöö6`ww×ó8 ÖáHê–;M* ÈžVBÈpt]-îâ©ϺËòN‹¤˜¤·[ìI4ÅØ©œ¸#˜Î¿-«[„hœ{NfÍ´™–elQFÂ…DòÅà£ue¥›~è^;Ýû·%¥iÝÈd&¨¹æ4(s9¥¯‰aôn‡]Î9¯½6?œsÖ9w77ÿÀ÷ýµpAºF¡8;wE2eëŸÔa‘{Ã8A™tº»dTf лdR{`Ýe–ûÓÄ«áÌE"ã\Ü!þ £³Š¨sÑÆ/¼ ë]ƒR¼ðbL 3Jctzß C)KGGÝ Û~Ònß9¿/œôàN ”âqš6¹sR¼Ú"o„œ$j ¨5ÑY°Ëk³dH0ÉR¹ô:}¼Òmåƒô2é®Ëu3äÊeî©>­È}Û]`’î,‚ tï–¥î^¥×Ö¿I;zŒKس'6X`º®£ÑhP%¯5Mã¾Ö1àGˆ?Èf1L½<ìÎB“ {=œÊ³ö´‹úÊŠÚ-…$ÝÓySš…Z­{s|úi¦”͉ÚÈÿL¢íδÀY Mg±8B¢€3]w¤õÐÝ‘V~år7Òéµ–Ë w,ãœ{ÉéD¦©ÒuNùY«)ÝÃYfй¥kŒý *ƒ&,Ll°V*ìîîbmm €v»íím4›M\¸p!èk -†ÑÍO'„LO±Ø-Væ.©îDž/'K·•Â~ ÎóIôÌkÜ++ÃÛ|Hšq2Ù,‹BçüŒÍÍ÷xã<¾þSìi¯¸×NBNÒ2Nê|^­ÑµñšgÏöFu܆g6;Ûž·yÁ,¹ÓG±Ø¨:«åJ‘$ +ûâÌ× íu¿'ýLd°¶Z-ìîî¢\.Cs™ùš¦assH$A_—'RÁ*WÊÆ¬}='Å«ª-!d4¦© Ù?4éÞŠx\ÍýaÎ"I'“*vóJ»†Gh5­·]ˆs¬´®’uËo£šŒÆÝn‹Ò¿&W«]'›8EÑ—B.W¯Ž>ïiŽ(‘ÅbYÝŠ»N‡r¹ÜméèDÒ‚ÝÌSw8ÍLd°@Ÿ± ¨´àT*…ãããЬõzwãu‘Êž»Y:!¤1NÅ“)½¾¼zÿŽË8ûKÅ ç‘qÅOöBjZÿÞ\à é"Žx¯µÙÙKWªcS™'ad}½›Ò®iêïlVÝY{&o\E+(Â<¶ÓÈ´¼‰*õº2N¥‚y:­²ÔŽŽÔZ-{Piˆ’¨Q,ö·s"żÂP5W×uèaÜ̽`&ް–ËeãþûïG:F:Æý÷ßf³‰ ¯gbÖ×ýo'á…³qNdÔ)Ç^¼öµ1|êS1 ÇöË=D> õZ ¦i¢X,â@*•_±,õH&»Ùe Éիʹ±ºÊ¾‹$úŒ³´\î:ô‰ëëÝ=Ó++½…“¤Ç¯W¦e˜)‹ÈårH&“Èçó§Z˜ªk«ÕB,ÃÖÖ Ñh Õj…¶Ø’i®ÎëT”ùìÀdm0F!UǼp+ØbPZ–e¢Œ;‰Çã}Ïéºn{bÄh5MÓ~6›í1ØDù¥=£P(ôœ×ià†r¹ Ó4íó†aPÆCYÜ\ŽkŒÇã¨V«}Æô<1 ëëëÈž¸ˆ-ËB±X´[2-+RíNúÚÉ"½²¢pç¢-ýó„IìyÓT²müCäμI‡½êe8Z–…ýÑ{qûí×pîÜP¯B×ãH&“¶<‹\麎z½n϶»II™GË ‡Ê«_-¯ï>çœGÎÔ‘s÷ØÒ>y·t]·?coo¯ï¼–e¡\.ãèèëëëÐuΟ‘4ñl¶·Ú£³È+1“eBR!ÝŠ»®+c5™ìVñÃ0P—âèu&zá\se7 £gÍÍf³özoš&êõú@‡½—“Ñ}J§ÓH&“#uç¸ Ã@.—C¡Pè»÷Ƚ.#—Ëõƒóó4à\·ŽÔÚ.º<='Œ™ª'“Õ0 ‹E [7Ò4m®zèîa`bƒuÛÛÛÈd2v ð¥K—Ðh4pᬭ­}M}$“ã¥rI3`@)2ÅâxïsG?ÂcšÀ¿ù7‡øÃ?¼ùü?ëy{±t.蚦áæÏ~ç>ò¼p‚»Ç¤‚;ް;vy­Ü4’ɤíý…®ëX]]…¦ižÀ=–z½Ž|>t:R©4•¡ÏçQ­VûŒôþáÆÙ³gm§Ë²±¾® ÓB¡×›~tÔM‰±,eÀ&“Ý׈ܻxùÞ>ñ‰~ÿ÷ïÂÓOßÓTï={ö3¸÷yFë¹OÀ<ÑþÅØÌºrÉ®\ù{¸é¦;ð?ñ)߆oùƒ›ñ—¯zZ/{™­è‹E{!Îf³}çð¯{ÐyÄ©S.—mçŒ33Á9ÿ‡)BíJ”ŸõõuõÌ‹r¹l+jÕj«««¸êê!éB¦iâàà 47–°#²›N÷*1c& ‘¹%ë;2þãìC}pÐUâe½Ôs¥R×a)ë”Û0ô2¾Äh“ÿ£dn‰Âít&ŠQ)¯wfy¹³·äž°¾¾˲lå9›ÍbooÏs^8Ï+úšÊñx|躩iš­ã”Ëe¬¬¬ —ËÙç}&NÃ0 ¬¬¬Ø÷¬z½n?_*•zç†aPÖ}BÖsçm7_ìŽz½nëÄNýGíIÕ4 ù|{Ž‹( X]]µu«t:r¹lÿ-Žk@„N榦iv ÀéÌ}^(—˨ßñ ˆîãèš7u:θ/n·ÛøÎïüN¬­­õ)ú»»»¨T*xôÑGÇŽ´6 œ9sfàë›Í&b±ØXç“e? ÕÕn› §WÏùO‘Ož3 Íæ-xË[^†Ûo¿—.¥ð5_ó~ê§¾¯ýÝã¸e©j“îüv—Ež¯T3àž¨²xË ,›ÍÚæjµj§DV- ·üØ!uþüXŸS<¹—<4ÐyÈ‹×gø%ß°¹¹9Ö>qIiœv±¶,¥È¤Ó.]z¿ù›ÿŸÿüG‘L&ñøãÿ/~ñÇðñKøîï~#à‰_ýUüŸ¯znüÓŠOþñã=ׯ÷yÅå¼++ŽÔJËR.ýZ­·l·®«çy·™PÆ©ó@×HõJÝw"k…;;â}?ôCøÂÃãÍo{^ðó?Ó4û TqÞÈ E²Ä£_«ÕzŒÖqåe¾†{ašË‘â+ë¨Sùuß‹L¤D¸³"Ɖ 9³k&E”-§#T2F9Aç-/A­ß~S¯«åÔí÷–ín…5۲喩A뛬ã`Îl®y+¸óÀ4MÔj5ÛÀöB”|Y«MÓD>ŸG2™ì™—¢ïhšÖ³Õ%NãÃþ0~çw~g®×ÅõÛMŸ^á#N]Õ)û¢ŸÆãqÛ1#Æ ;º>ˆqÛÃdÌI­V³×ÑAY`–e¡^¯ÛN(g惌Ùhk­V«¶ƒÉk«•Èn±X´ù"Ëét…BÁs]¸téþæoþ¯F¶˜È`m4ØÜܸ?ìþûïÇ… FîgÝßßG¥R±Ûãd2”J%Äb1*å¸P( ÙlÚ_ˆ;ÅÔklƒ&K±8™×ܲ,Ôj5>‡FãïãùϨ'>øÁ—âÝï~^óš¯Ä÷~ïÍÈåºÞÊtÈf/ÈÄHóÉtZiW“V¤¹é&•ó3k.›ÎÒ[d\œùE¥Ò豟ì†oŸ;‡wÚ©5NÞ÷C?„•_þe\|á ñÜ÷?à…Ÿÿ<^øùÏãÚí·Û“B&ŸWÔJ˜çâ:ùÆSxdñW\$j8(íã%/ùnüÑ=€ÿëÿº¹G”dñ€\6 ÖkªU×ç:'Åâ€FÛ"c'çe)Ùu/æ²ñUŒKÉk›Å™R¯+95M%ߣ檌չ¬Tƒºa¨kpçãÞ÷ðÃvŸw¿êUøÞù/ÕÍêä;#Ö™êïL%®Õj¨Õj¶ƒæâÅ‹xôÑG§ÿn†°è5Ü/äß7p>ãQ÷§GÜ­ø8#ò»3RådнYÎ/F‚SùrŸÃs*hnåʽíÄ©išfGÇDis{èÝ ‘ YîÌ7ó’— ×o¿ÙÝ}ÿæß¼/|áøº¯»ÙVNkµZSѹ%ÀXé²drÄPïÖ9ÿ¿aøÙŸýY|èCšË8¢º~;3éÙ>ŽÝ#k’ÛÉ&ë¦;òí^cën<·×°eJù™ôÒÁG!²œÍfmÃUäÆéô2 _ûµ_‹×½îuxç;ß9þt&à±ÇëÜwß}¿á oè<öØcCÏqýúõÎÞð†Î{Þóûï·½ímŸüÉŸ´_óàƒvÞñŽwØÇßúÖ·v.^¼8rlƒ^“LŽw}×®]ë …N2™ì …ÎÁÁÁ€×©s^½:É·çâè¨Ó)Ôcã¾ÎI©Ôé¤ÓÎÞ^÷¥’÷k‡]ȵkêÙl§S­Žþ܃ƒNGÓÔãà ;÷g\½ªŽïíu__(¨ÏI&_ïµkÿýÚ×vŽßò–ÎõW¿ºsýÕ¯î<ûò—wr¹N¡Pè …ަiMÓþÿ:áò2 ó’oyß8_ÿ SµZí$“ÉN2™´¿£QßÓ$ êómr9õ¿Ìf• ãÚ5õºA2*räF}ß…‚:§üÌåFö¥îÙóàõ¯ýDÿ¿q b ÷¯Ÿç¾Ö9888—œs¯P(دwÞkä!÷ MÓ쟅B¡³··×¹:ÓM§Ó¹zõjçàà stt4—ï@äOÓ´N6›íìÉýÇõíííuªCþGGGt:m¯Q…B¡S­V{®òôú=ýw¯–ÏJåo:Õjµ“Íf;Éd²óÚ×þvç;¿³ÙétÔÿ¾Z­vJ¥RçÚ˜ë ŽyÉKT×oç­}oOý-êãè÷ªõ7›ÍvªÕjçèè¨gÍÇzHº8¿où®§‘—‰ö°JÖíímlmmÙÞ˜v»J¥@UF³ÙD»Ý¶÷ºÆb1d2Û“ÓjµÐh4ððÃÛÇ×ÖÖ°¿¿?•çfÜÌXgqwTN ׈C¦\ž¡ “iv7¦Óêï•q¥)TX@>XÆ–ÏŽ^JauµÛùØËU«uë€KÉV'ñ¸:¦©qf³ÞŸ'U9|隦Þãþ²LS˲z_?Šx_ñá#¡ëÝM –Ͳ 9?ÃÙtð'7‹–o7ƒ¾Æb±]×mÙ–”?S²z²仿zÆC—€¿·ôù”¤ô¿y؆)[ypÐûÿó “årê³óyõ»lÐ*¼Ûî8¿0MSŸ5(£XT¯qÎMë¯äLßS¢°TêÎ ÷5;Ç"Ñ4Ó´çi6›E6™ ›'Þs¿ ZƧEŠ+y9ÅS>,ªä¬Pí.’'ÑCÓ4팉šÈ~lI×.—ËX=ÙîáUlKÓ4Ïm ~0ÏÈ™ì-”ÂÇÇÞ³—N§qt2¯œ{_þò—û~-Q“mÓ>øÁgðÅ/þþê¯>‚Ÿù™3xðÁ¯@¡P€i¦Q.ï}¯z­{9DMÆ÷mWú¶;ÿÜBû¤˜5~é™]*—Ë( Øßß·SÉsßÙÙ±ØAd2™¾´¥ããcÜzë­öï@¯á›J¥Ðjµ¦ºÀqš½ËÆb/åPº ´Å‘LÝ©«™¦šmN…D×»õ¸½n(ñ¸z¾Vë=.郔Z©6¥ëýƪ³ƒt/—U'ð½½~ãYÆ %Óé~ëháéõдÙöØ:ß÷_¿»šJ¹¬ îR ÐuÜý¹Ïáð¿qúÏÀ¢åÛ‰d»¿Šü‰ñèÜß8×…ûdÿªUXÿ£P-ZN÷?Ïåçûx]GµªätuUý>nîg©¤dDRÙï£pCÂ]ýaFY,/ùÓT úó]ƒ”ñI29$]g% ŒÅB¡Ð×âKRje»Rè$ÌË Óì:ª £›¶/÷’)½¼^û#MÓÄûßÿ~<óÌ3¾^BTd[øñÿ~ï÷~ßó=mìì|¿#í®[€'Q’qËRª±{×ìPS»ƒ,‹e»à‘S‡Çã,F¸DŒ4X[­Úí¶-¼Ò‡U×uÛ#³¶¶MÓF«n677íÉ!Þœa“¢ÝnüŒgŸ}O<ñFÏZË®#KEÒA{®í«ûðL}œÒéþ›¶4ü†Wo)klƒ/R"¹nÖ×»%Åàua鵬þ±„½ÚÓµ®Ýw^ð<ýÉOÎõ#ý”oxæ™g†I(—ûƒÈRú|Q½»òy PÈ!y"b㥵€Ôt'æfS*M§­U«ê‹tÏ™°•õŸch4¸~ýú܇±ˆ5|ÜU#öÅXge­V³‹µ‰‘4nôÈ Î÷¼R•Ö¦?o­Ö– nÀlÙ-âÐ=ß¾ðÜzë­ö¼y°èõ{RÞõ®Oà×ý ¸xñNär?ÜslÖÖ4$Xdý%S³Öõ[×ÕÒQ,öw:âqÀ4 ¬¯ç‘Ífû*è“ðÒjµpåÊܸqc¢÷aÝÝÝE«ÕB&“¦iH¥R¾ôþyàÐjµ°»»‹K—.akkkè èÆC'Ë“O>‰ÃÃÞÉbƒƒ µZ º®å‘Ã3G¶½…Yf°bÚq”ï‚' H?ÑhàÊ{ß‹Ï~ö³sý8?åP Ïáá!x*<îÌk©®|4Ïæcõº’¿c.™T7)Bæˆ5éôb«ωÃÃù*óÂ"Öðip÷™”{@¹\¶+»'“IÔëõžÌš\.ž´I‰XеíWú¾¤ ¹ïCår÷^"IîU¥RÃóx|ö@ ^Çõ7›M\¹rÅŸïc‹^¿'ûJ üëýyüÜÏÝy%¾!ë÷(™š•°­ßù|79CnÅ^Ëž³ [µZdµéÓÌñññTë÷Hƒ5‘HØUžt]Çþþ>šÍ&R©”mÀN‹u,C¡PÀÖÖÖÐ=°Ãù;ï¼étÚ3Ç~À—Ëå¡‘ÕH iÊBp"49‰=¹åaÞŸã‡|À]wÝ5t‰[oY__G©Tš¯|»¢2² TRç£ì߈2[[[vÌ ^Di¸žL&±··g§ùN]Å}ˆÕm]c2—ó® 0.bPz½_5KÕÔ—Y*Ÿb>îZ#[P„a[Dêõ¾ckkkH$s]ý~ËÏÿü³(_†ïú®/áÁï™Ûõ“àõÛHü0¶~ŸÄ"1R‰|®Îx27¦ÕÁ'ÚÃꌪ꺎F£ÝÝ݉Œ×J¥‚f³ÙSÞ]rçàÌ™3TÈX&‡ó÷I”Å'i`‘6V·WÛ0Æ«ñM|gÑò-H=!ÑCËå²Ý¶`®ˆ}B:­ž’.1dùJÆÇ%ŸïM¯Õj(—Ë=mRfÍZ’לÍv Õ9÷‰Mf¼ŽS…0›í¨Ò´vÒhë(Ü‘×|~p/®z}†¢“vÙV{S ll|¿ôKïXÈg’9 iãfY½éH¦‰WþíßÎå£Ã,ãÃ’,ËêÙ¾ANÏ›öš¦áÂ… xøá‡±¶¶†f³‰óçÏôêŸ;wF£çuº®Û“!‘H “É`¿ç¸TUœ/¹vVuŒöØc}ÿäOþdçâÅ‹}ÇFq||Üyì±Ç¾ïúõëC{Í« ­WSaiBãt9ž”RiþŸ±d̻ɵßòÝé o$žNw¯V«B¡0·k³98ètñ9d*æÕx^XÔ>н=%ÿò÷^'™L·Æ_»ÖÐÕ«ªÃ}:­~‡I^ëE¡ÐOpŽËoŽŽ:lvöóìíõŸgÈw1Ï5|Ñë÷0J¥RçÎ;¸óÚ×6:×®]›ËõúƵkÞ²ç$—SsBÈfÕ£Zíÿ__½ªÎ9 ¹É0ˆ££N'™TãK§{ÇàæêUõºlVéSš¦>C^ãÌåÔër9õ𣣙¾ÊÓ²~Ë×çüºŽŽŽ:Éd²S(:{{{£¿Ë…st¤dÁ-'jç I&g_¯ŽFËú0äÞåüþ¯]S2žÍö^ߠϹvM]·óW¯v>¾½=±¼Œam6›( hµZvÿ&]×Q(ì4‚ÝÝ]\¸pÁnF<ŠD"14'^šÏŠ—3YºÂ<¢ŸÎ‹ôJ& gQò tû¯vÿÖ—LN-‹”ñaF7½\Výømoš*z"žñ\N nuupÙKç{Ùúø ªŸ°|®ó‹šG´Ò£(ÒTd³½÷G?¾‹) ‹l›¦‰Z­†ü@<ÜÛ,$j鎂Iø,—ëf8+ë «Ê>Îÿ~ÜžîÒŸPõ^u’ôûqq—%a‘q ÷ßìn5jµÞ(þ°±åóýë¯iª(d:ÝLjšwßörYÉŸ×6‰AxlÏB:­nŽ’Î-­0Ý}ß¼L¯Ú^óãàÀ;…Ù«R|2‰kÿðó(ºT(J¥ìjÁìbK;;;ˆÅbØÝÝE¥RÛ`]^ë˜išÁígš÷”trjp¬ KyŸ5]…,$˲P«Õ‚¯üî•Î+•}½Æ%ýKãq5™g-”w÷„:S´Ü Å´ˆ2&çÒuÿZA¹SÊ¢žþ:#år…B!¼Å!©¼’nîÕ£}uµ›¶ä=#_жeË„3ãÔ²,äóù`ZÕF7ÝýÙNãmœ J§ûçA2Ù}¿ÌIm7ÍÞ¹#ë«8{œó_æ›`Y]#ôà ßÇ»Fk­Öí ÞîaYƒÛŸÅãÞιïÌ‘‘k£Ñ@«ÕÂÃ?l÷_j·Ûh6›¸pá‚ýÜÚÚ*•Š/MƒýB¶FôË÷x’åÁ4»ëD½^_ÜB¿Àb(„¸qÔ' ”ûl6^å~м4M•z~(Ô^{BýʺÈåT¤ÀéÑŸW4¬ÿË`š& ÀiVí@LhX]íþÿ¥Oð £ìá^_W³ q uf¤°R.—›o@I SM뮉å²2ÝÆj>¯ÖÒAÆ›ó"¤;ǰ‚{³»Í—ŒA²œŸÛýÂÔC¬ýake<>Þ¼SeÈÕwQ(„.ø5Ò`m6›Èd2=Í‚õ“°¯S¨æÙÜxZd¼ó;·,+¸4ƒEÊR䃜œûá ÃX\öÀ¼[æ2ÉìÔº®ëz4 Ò”Jê!Q*¿,Q´D óë¾ ifd®äóy|ë·þg<ûìUIÙÄ#äÀ0åÝ‹tº;Y©ŸœEÀWW×SXIÖ¯rY9 e^½ÚÿÚx\9þF¥çrꆴ²2Y=ççxE;›‡îeYê²ÙÁ-Æf¤Á‹ÅÐn·{žk6›H¥R¡4RGaFp«W¸×Ÿ‹êöÃdÿÕS‡s}¯×ë(SÕ“ˆãÜ&Z,‘ËåÂ]‡i+BÒŒ¥Ç)‰ º®ãK_z1þÇÿHÍ?ƒÕ4•ò.Î’qdpšyvš*¼’± ñ|>d2¹¸*Àb ŽÒ•J¥ñ÷HW«½[%æÅµkóûNBîˆi°¦R)4›MÛHm·ÛÐu½o¯j£ÑÐm:¼š†aD[©„”T'§ É I&vƲ`ÄÉ,mªa(zR,ö·f M£±At]Çí·ÿ{|Ó7-@”VW•£; ó‡œ*T®]·°ֽœd¬Qÿš+Ïõ‚T*…L&ƒÍÍMT*lnn¢ÝnÛi‡bÀ‹Ed2™¡UÇW@3Дà}+gFúŠ‘S‡at{3ëºNƒ•œ œýÈëõzxúóÕëá1VIdùƒ?xõW¯^LÂÔÕ«tv“…#ÑU]׃+‚J"ÅHƒJ¥4M³÷]¸p©T péÒ%»ŠpSÝÁÔ@£PÙìün ,$u*‰Ç»úñÂ1ÅbЗON)Îú Ý·= ]gÕlâ ú§oƃ~E·‘â Òekáë·ÓÛ¤X¯­M,Ã… <­­­amm-T‘Õa,mJp·êÓNÎmo†a,¦ÿ* ”sFõI¸íÂФÂûÕ6†œjLÓĽ÷~¹Ü÷=Bæ†Ä·ŠEs±=³ëõhe8õ¬S®ße°jêáI“×sçÎÙ­kÂl¨¦Ó^}t—øŸ-‰C¾qšÌÓ4ëŒYFÇ =N»Ð4¬ì CÚ2†aàÛ¾-z- ™”P­ßaF ÕõuïjƧ„± ÖJ¥‚ÝÝ]ûïÝÝ]lll`kk+èñÅ]ùY×õåé4Ó‚O!Å¢´µ±+Û¦ô¥“SŠ®w}r¡Ú·mštâ™0Màßý»¯Áÿð>luUZZVˆ„–ZMÚ‹°~GMOvÖ¨9åsu¬=¬»»»X[[ƒa0 kkkØÝÝíkw6Ür¹ð”›yçÎÆ©èÓ†¬c O‹”þ|„,‘wYÆMÓ ÇþU€k/™™Z xÞóÞ³¸µœ2KÀ4•Èúç¸Äãþ÷èŽ(# ViW³±±a?'‘Õf³ôø‡â® ¸rã¬â7š&.«à®,Yø—:{€ÜûWCSaR×¹ö’™)•€O~ò—³–3K†„´7 Mý0#VfðŒaz÷ªÆbÑÜ_aF°Jý<…MÓN½÷å´« Á •mFóI¤ÓÝzV˜Š~ÅãÌ8 3³ÐJï§\ù%Á³ð¬Ç(:%Âʬ¶ñ‹.Ewí¡…+õnæ=Q,ëÔ ôi%ì¬dÁ8E.4ÑU ·\7!SP,wÜñI¬d©1M•úžÍ]šÞâì¥êÆs`ì+™‘0EÈÒ û´ÍE§w1Œ€s›ÓÉÈ2¡‚( ÚÚÅHY Dg UÁ¼°++jƶόaÝÜÜì{®R©àÒ¥K=ÏíììŒýá²6•J <‹Å¦jcYª´DYˆJz`BÅ<å[д€JßâÒê¤Ë"d\0ŒÞBz†a ÇõŽÌ‰EÊ6 [ÔŽN/¨5Ò)W~ÉâeèvhÑuYw+yãÕë2 ìí©ªÞ§œ‘ë™3gz . ƒ|šÍ& …Z­µ?¶\.ÛçlµZ( ödÒ4 å F¯q¡{C1oƒ¹TŠæd\2!ßÂÞP¯3ÒDË"e\H&U=üÈ<B¶ ¢˜‹YË™ñuª JÆå˜Éf•ñê\ÐA<ÍÌËRúý)gdJp"‘ÀÖÖÖØqØÜÜD&“a¸|ù22™ ކëÛÛÛH$öñf³‰J¥2ñŹ÷;ªÜ,âA£%,J¾¦F’E³h”ž!Kx¨ö¯óoYFF²½ðv,vª BƉ°’ ˆÇù¥aŠ=¬F•JÅ~HÛ›IÞßn·mã6‹acc­V Íf­V FÃŽêÆb1¬­­áÀ]Ai 5XYUõT°HùÖuÕ)‰‘&²H‚ZÃu½»u:ðžÚîE­=ñ$(Ù6MàyÏûËÅ95ë)%Hܲ”Ìý«dÆÞêë:.^¼h§»»»}éÃH¥RØÙÙéis|| @M ùÝy®T*Õ÷¹£p4 Ãèñ -†óO‹’oAµçZP™ VäSÉ¢e\(—»)Á÷ÔvÂþ×KCP²mÀm·=' YZ‚’q ] ¼Å$‰$cEX …Μ9ƒr¹ Ã0ìG¹\Æ™3gpþüù±¢­±X ™LÆþ»Õj¡R©`mm ‰Dbè¤h·Û=ûì³xâ‰'ì1¸š¡òÈ“@iµZ¸rå ž~úißÏ=/ù€gžyFÃ>‡¦ä©ÕX%8ä4 \¿~}.ç^ÔîF¼ó@ÈÒà™ã¶pšÍ&®\¹‚7nøzÞE®ßNJ% ¯S‰'ºë÷(™š† Öo@é,…B€5eVVÿ™¤ÑÁ']¿Ç2X···¡ivvvú¼ÚÎç···Çþàv»J¥‚ûï¿™L.\°Ÿİ‹{öÙgñä“OâððÐ~ιöóF@„ãã㹬‚ßò (…çððÐö€ ª~mš\è#Æááá\”'‹XÃ*¤*ïô(Nó2X…E­ßn¨§ »~ÏK¾àÖïx<@‡#‹…ÑÁ'•ï‘)Áâ|×»Þ5ôu8þ<šÍæÈÔàf³‰íímÄb1<üðÃ}©ƒVZûÎ;ïD:¶óò‘§À .‘P!ÞÅqãi˜‡|À]wÝÕSجVž{î¹ù/üù|ï„bû¤Ð³µµeWxœ‹XÃ8mÂPEW¥…%=ù” Ñ y¬á‹Z¿¬¬Éä0ëëªÄ< %²~ûÙNÆÉ¢×o!ŸWÛ:s8ÒÓêà##¬2iFMòq¼ú…BÁΣwOŽ3gÎ@OZB«Õšiâ†ÂÏ¢§†EÉ·i7nŒ½ }0µP,z«×½+Jrá?Õ,~ ïf݆nÿ×ö¥bѲ-[ š&ÉHÓ©fÑ2.¨Ây‰¤ÌGž‘k,ó5-A×u´Z-hš†F£Ñó”'“É`¿ç=«6Íuêß /Jã›þž %߀RâŸ|òÉÙ].+ÃÔe©cî²Ü¿zªY¤Œ N‘ ]Á¥ ï-Ä7‚íx88Pr½¨¸Ÿj‚qao/À vêˆ<#Ã3©T ív{¤‡E„ÝYyÌ ISÛÜÜì;fœxª·¶¶°¹¹i—ߎÅbxà&º0§ÓÛ4Md³Ù}¥è:SÆN ‹’o@é¯xÅÑl‹­Ö•ÍZ­7Õ·\VÇz«—qÑ?å,RÆ…d²+¦W|ï½`¬KD²-,, ŒŠû©&HO§z=À-AgZ’™Ë`M¥R( }¥°Ù¼ÉdFî_ÝÚÚšã.ŸùÈ#ØËYÑl\œA¡À*’©W‰û>ô°"ágQò-¼àŸ›MÑÉå¤7Ž2PÅ`5Mu½zµ÷õ^‘XrªX´Œ½þ¾PlñpŒÎÈ¥!Ù®Õ”"¿P™Ëü! 'TÜ&™ 0€ÄÌ‚È3Ö¸ .`ssçÏŸÇÆÆ2™Œ]þºÑh`ww7nܰ«Œù»ôö¤8íÓ…¥Úx‘Ï+#€Mâ`VùÔúkù±ÇãÒ­AuZr9*èd,üqA™íd¯ ûjŸjü”ízxá ÿp±VBFà§ŒÝDÃÀ¶è1³ òŒe°ÊæìJ¥âÙº&“É`kkkdtu‘Hvc N­&Ö„ú;,ékd©PQÿB¡»¨§Ó€—TŒ[BÈê*píÚ÷?I†at×qÓTs‚ë9ñË^þòÏ-NOaUk7poo"‘cì£b´¶Z-4›M»}M*•š[éíY¨×»ë½9é´r'Y–ªáMÈØÛSŸ‘žyÓ¯8Œón b#úf°ŠAšLö;f¤Y6«æA2ÙÍg£ÂCæ@ Y`„,ÓLSn{4‘gâžÒâÆ]¥±Ýn£ÙlúšBà†a,~¿S:Í(™;éô˜)Á–¥úîu÷.­¯+g ÷2‘à4XsÓºé¥êµªƒ<î…B•Ê™Ò_x¡•¯M Y²54õHä𡉣¢ÙlbssÓ®2$Î!X–5ù@ %iÚèÃPJм›p[ÊŽ¿µ“GÏXN^qn›Ù<9ž;ùÝ qø2 JLS‚øc¬’Þ+-jŠEu÷àƒD >‰Â3Qê¤ì9µ,5a²Ù^Ç !âì/¼0æ­«âÂ0pÌ¥cdÖ(âÌ~œªÉ|>¯´£ZM=Óî¸C)>B±¸¸Äü$”‘š†2<˜Öè'<€ºÇû÷d¡ Öü€ÏÉŸû‹p|¶×ׇ2Zã'×儨BEU³'çpžGƒ2t×"PÆpÊÈ%¾bšÀg?{óð€4>#$ˆŽ=°a(…äà€+‰õºÔhCO‘âyÕêxNGÉ®±,5G¤uÛ2‘S«ÉäÒ-«ÛVRŠïìØyF¬Íf•Jeä‰ÚívÐ×b#щ*›&ðæŸŒ¸·á(Ñ8ydãÞÊ‘nQ#'«P†[*ŠêÄmâä5y(C´ïâGItèa—©qlÐk$RkCÊ0uß­“s¡ p¯ñÉ~[n§œ˜Z ¸ãŽ[‡¿È0X­šDÙû¨õ¼à¥lK–Æ*‰µðS?u}¼¯¯«É ß½Fzi; ë%“,6F£\ …D÷ëõþ>Ã…å~Ið-‹ÅB×Òf¢"É$ð©d7ªéù(ClP¬®aêÔ«êPiÖõZ1l½†(FlÃ#”Y×yçÁ0›'ç¸f Ê@­:¾Cã伌RÙÏ›?yóäûáZãÉÿñãž{†¼@×éM'‘Æés¸ÿItB"F.<ýôÿyR!*%*ÕÃk;ëR(øX!xXæØ¢  ’@i°¦R)ììì=Ω˜¸·ÁÆÑ:T¤1ÁE“Ö¡ ¯"zLýFe½‘X/£³½ 3É“ïD?«{)A¥,K gTUŒíÕ“÷:ךòÉëdϬWÚñ)Æ4ç=ƒo’CÏ"‰0aé|¤ÁJ"H6Û[o NE¼TVVº (û$äärÀêê =´MS9m¤‡vù¤°J©Ä,²SÄÈ¢KF£Ïû×n·Ñh4‚ûH†ztŠE%ôîØ^‘Àq÷jK˘´ã=¼£¶²Oµ†ÁÌ8¢±ÿSÖ =ôBÝÂMeôç{'Ï—Ñ^ R°5t#×Î}¾ò½*B;èTƒÚƒ»dXpÏ=1øõ:÷¯’È“Í*e‡íÈ2R¯º®O^9U*¾Ó!IBŽ´à›ª- tõÕU%ëGGªV[ùþ!QZÙó[u½WŒRëäub¨:òŠ/ºò"à– ¿”éQ¾kp®³*‰¶‡y³Òjggvwfv~óÛïLbÖ3?û;?Ío~ÿZáoå Ãkú!t/ªü,9¯ æÑ¿—tý‡üÆõLR·t÷Ö^äÀo”[þ\ü79·¿íáßâû׾ϻD#‹Yµ=QAíÐÈ!Á7²^uŽ(³³/ÖïÜáÞ‘Tx­ð _Ä7X{'t³±JçäÞ`š kÛ6\×Mïd ô_Œ&˜ç8îÒô6.álþ$Ð…ÛߢøÃ}‹$Zܯçú6¢{q3U¾?ú(fH0â 1ɲ=í»B0Q†²ÌöùŽÕžl7þ3 §uPƲ~wœÖ X]õ³Î—!׫뺡sa]×ÅÒÒ–––pýúõð½÷b„ö®®øÇÿèý!lŸø Ì‹½©fÌâlj¿6Û ã×o‹ œd™o|€§ÜeqÀo¬Ž´XQYg;Ø)ôÅ£ãp‹Ê\Öwœ³UÞû>¯†ÿ+l›&¢sžÃz>Ôžçõ|-0È8®ë¶mlnn†___‡ªªØÞÞ†çyXZZB­VCµZ¸`–eõ>ä´+Àß_x‹s¾ ø=±7à7€¢zä‚^Ô>{xƒ[¢M¤qä`ƒ•ò3ŽŒ/݇+ÓØŒ«þü‡ùЗ1–Å=´)3ãʸãøÓ:,«ÏŽ­–_Ñsÿ`@lëÌÌ –——¡iZç—®ë=_ ~ Â4Mìîî†s]¦ibyy ( Êå20'¯ë>èEýÍoâèp¿•Má[´ÐÄG¾û.ÔÑ}ã^’Á82¬9¹íGðÀC”’q=Ÿ”JÀ³g_„g›[ÖP†Æ÷ 1Šðçi߸Á)L4ØVUUGzs¥\.£\.Ã4Íž^Úf³ ]_MÓ†GoF÷›ËKð{BÃî‹Utï¿ÌQµþøýaRþüÖ~½«4±Æ‘ïð-oa%£Œ#ãÁÛùF#b…`Ëêž H”Ð8² ø VÃø.¼çlE|¦„Þù®T®ëâÉ“'øá‡r9w?Qù€Ÿ~ú ¦ivþŒž7ó;;\´€øoÐONNr9wZuxÐu§ƒ`OÔ²mOž<ÁéééXÏ›fýmY!/Öƒl°N´ þŽËTÒ|\piu•[ïM¨à|Øú{à«mÛXYYmÛü®Ã~%uCDîÙ³g8::ÂÁÁ€æ œm{ržÞE•Jð«¡ÿ–4óàÕ‚j6›¹5XGÍ7à?ð Ùl† ŽÚ®‰&ÊÁÁA.;@:ux°X³6M¤¼¬iÕ߀¿‹2‡•Ã'^P;ß@zÏà€ŸñžgñÀÓ§|13¡‚gðaó=ТK†a`eeªªBQ”Î׫Õ*Ea°m{{{‰ 5VUÕ¾Ç._¾Œùùù®áË] èùøn˜ý]w#Õ@ÿFi”K8[Y˜ E×uèªXÇeÔ|À+¯¼ÒÉ÷'Ÿ|ÒýC ÕòßÌsq‚_7/Ç-:Ü0΢¹B°aðá~•Ëe¨ª:ö:<­úðgnX–Õ»+§tL¼ þŽËTÒ|¿qÃ_o£Äí™èœQŸÁêa]__G©TÂþþ~W`5MC¹\F½^Ƕ¶¶dff@÷°×u‡¾q{ÞÊÿþ¿_ýè¯ú{þÞ Û¶ð‡úrÏnJYZù.¼ÙÙრ!Œ†ÿò=tÈäE|ICc’fý½±Áý…I̳ÁJ ]!˜‹ERr7X ÿ‡ÀjÞB”>àÄB껿!ïK$I«Õê}sã_@’4B§t°w•»Áº³¸Wºç¯É€U’\lï*WT¥‚ }3?pUl’DìDC’{«ã×UàzÞB”2Î_%‰qK’‡»“¬BG%$o+{ Hfœ¿JhÁ%nBOõðáü/(3=½«FÞ—D·Áô@­àÎ$#¾!I Ô`劓TP=Ùæöd$Ç9·mS«|ðAÞ—DwH°ewÿø¸­ Éç£ò¾¢Ìܾ};þ›66Ø`¥âsàή JÒ調wvüň’·‡Õ²€ýKàN…""’ G vv8½ƒäÕh°ÁJ©³ÁjYÀŸÿµ?˜½«DDD$"®G@²j4ü‹|¹H)¾ÁjÛ6\×þƒ?Þnƒ½«$´‘óMTÌ8É,q¾¹@$ lä|sW76ò.IBØ9¬®ëbee¶mJ¥>tâö¥yÀ…ß`%P¢|@foµÎæEqëÊI*ù¾s‡Ã%IH‰óýÁ¬£)UÂö°®¯¯CUUX–…ÇömÔjµÁ>| W'%Ê7Q¤šqÃð‡—­®¿þ5WU¥Ü%Î÷;þÙEJ”oÇñ_*2Û”"!¬®ëÂ4M,//EA¹\Æ£AWÑ»€SBHP‰óM$¸Ä·,`qxñEÿ¿;;þCP©<}ê?ñÍ=å$q¾WWýÿr?VP*Ï(Ì6¥LÈk³ÙhšÖùš¦i7J¶7Û¶±»»›÷eäŽùöɘÙîÙQ%Îøì¬¿uÓ?úÛ}<|è7R ¶8lyñžEâ|ÏϾ÷IÆ,Èv¿Ž*•ú»`uuÙòPô{VÈ9¬Q7…çyP¥çëß|ó >ýôSX–…yI0øì³Ïò¾„Tâèè(÷†Ùáá!¾þúkLMM¡Z­Žýü£äž>}Šååe\½z¯¾úêØ¯;m¢ä!M¢Ü³–eáÛo¿Ííü¬Ã}¢ä!-¢Ü³_}õŽŽŽðâ‹/ærþQòÝSooçríi% iå~ êï¼êBÖß>QòQîÙà|Øú[È«çy}žž†Þ,š¦áÍ7ßÄk¯½†×_=ï"¤âùóçXXXÈû2Rs||ŒãããÜÿ}ŽqõêULMMårþQò o¼ñ®]»†Ë—/ãòå˹\{šDÉCšD¹gEÁË/¿œÛùY‡ûDÉCZD¹g¯\¹‚££#¼ôÒK¹œ”|³þŸ(÷kP_¹r%—ó³þö‰’‡´ˆrÏÏàÃÖßB6XÏC¸HUÕЯÏÍÍann.ïKO•®ëy_e`”|À{ï½—÷¥S QîÙ¼¯ƒu¸/ïYåý÷:J¾Y‹/ï\‰r¬¿}yÿ;P7!ç°ÎÌÌè–àºnäÛ•“““žs6›Íöƒº&ËD£K’ï4Žg!*ãE,%•ñ"æu8&­þŽ»&ËCɰþ¿LÃúEÞ fYéº˲º¾Öl61==ÝùÐ4­s\Ó4¸®y,î³Y VŠÓ4 ¶mÃ󛕨ኢ$¾æ<ÊD£K’ï4Žg!*ã×®]+\y(™¨ŒË–oÖá“eÒêï¸|‹XJ†õ·øe¬YXX€išn|0 £ó¯ª*t]Çîîn×ñÅÅÅÈcqŸÍЦi=Kh×jµÎ›™¤×œG™htIòÆñ,Deü­·Þ*\y(™¨ŒË–oÖá“eÒêï¸|‹XJ†õ·øeÖT»Ýnç}²Z__Çîî.t]G³Ùìš øcÒ+• TUíLj®×ëP%òXÜg³œ3xK5LyÒ8NbI’ï4Žg!*ãE,%•ñ"æu8&­þŽ»&ËCɰþ¿LÃ`ƒ5cç—L›'áy^ç ÐÅãQÇ9ž…¤×$b™htIòÆñ,dyO2ßÅ•ñ"æu8&­þŽ;.by(Ößâ—iPl°‘8‡•ˆˆˆˆˆˆ„Ä+ ‰ V""""""¬DDDDDD$$6X‰ˆˆˆˆˆHHl°‘Ø`¥T™¦ Ïóò¾ ¢Ì0ã$3æ›dÆ|“ÌdÎ7¬”ªJ¥ÒÙt˜HFÌ8ÉŒù&™1ß$3™óÍ+ ‰ Ö1 ºê]×Åîî. Ãè³m›››™½ Îíy Àac6ຮÔC¨[^Ï+ß3>IX‡“ÌX“ÌXÛ/ò¾€IR©TP.—a4MƒišÐuªªÂ4M(Š‚Z­†ååeT«ÕÔÏ]­V±µµMÓ:7åöö6TUͤ¼¶m£R© T*A×õÌÿ~)ye<|Ìø¤aN2cýM2cý]lìa3Ó4±··‡z½Žjµ Ó4ûûûØÞÞF©TÊì ÏÖÖêõ:êõ:ööö0==ÝÝÝLÎuþFY[[Ëìï“Ä“WÆÇ™o€ŸT¬ÃIf¬¿If¬¿‹‹=¬c¶¸¸EQš¦J¥RçøÌÌLäÍ eè§\.÷}[S.—;çT333™œÇ¶mlmmaaaAš…—$ãEÈ7ÀŒO²¼ògNYbýM2ã3xq±‡•RW«Õ0==ƒƒ)ÆÍ]ÄŒ“̘o’óM2“5ßìa-UUS[ŸöyÊå2ªÕ*Þ}÷]Ôj5©ÞðP¶Šo€§ÑŒ+ßIÏÅ|Ó(X“ìŠqYóÍkÁضZ­Ö÷xµZí 9Èë<¥R Š¢`mm +++ÒLø¦ì!ß3N£W¾“ž‹ù¦Q°þ&Ù!ã²æ› Ö‚QU·nÝŠ<.Êy‚›d}}ûûûãÿË¢Â)R¾fœ†3®|§u.曆Áú›dW¤ŒË–o6X FQ”±¼)Ië$%tEXtdate:create2019-03-28T17:36:49-05:00T¾=@%tEXtdate:modify2019-03-28T17:36:49-05:00%ã…ü-tEXticc:copyrightCopyright Artifex Software 2011ºÅ´1tEXticc:descriptionArtifex Software sRGB ICC Profile †2tEXticc:manufacturerArtifex Software sRGB ICC Profile\~=Ÿ+tEXticc:modelArtifex Software sRGB ICC Profile1(‚¡!tEXtpdf:HiResBoundingBox1080x792+0+0_Ýx+tEXtpdf:VersionPDF-1.4 G:xIEND®B`‚blis-0.9.0/docs/graphs/large/l3_perf_has_nt1.pdf000066400000000000000000001066671422157504600214470ustar00rootroot00000000000000%PDF-1.4 %ª«¬­ 1 0 obj << /Producer (Apache FOP Version 2.3.0-SNAPSHOT: PDFDocumentGraphics2D) /CreationDate (D:20190328152433-05'00') >> endobj 2 0 obj << /Length 3 0 R /Filter /FlateDecode >> stream xœÌ½K¯mIv×Ï_q›v£Žâýh¸a*Âr ¤ÅÜÔ’ŠE›LÂ*0ä_ï1fÄÚ{ŽX'3ëÞ亨²$ŸÜq׊Xñøb¾bÆÿ!~ øÿ~Ãÿ_ŸéËýñ‡ðSµ_ßáçÿþCûˆ?¤>ì7þg¥ö/±”/¹Ù³øýÇb.üÓú#†ñwxÿÁ¢øáÿüáŸQûñßm¿½ÿñŸþðåïø?þ¼ÿíÞ{ý’rEûsIö×?Ù_½ñKPhüÃö‹Ñ}h›öÇþóÁ?úo?¤/ÿõýß(j¥Žœ¿ü¿?Äðå?~Z÷ß=T>ãÇ÷‡=QK*í£öXRËsÖñSþÈ9„G~¨ 9üã4ì}»gõ§Ç› Ÿl®¿ôÖÑ€:¾G¬A—_ÎúÿÝoã—Ø>Hßÿ=Z³ªúãÏ´ ÏÔÑBša|‰5‘{©Gþê÷o¸ü&ÅŠ¾üþÇ/ÿùŠ)„ÿùËùòûÿðÿÿ½}ù/Ö•bÌ=¤‘bûªºR9ëzjå¾ñÈ`n,<¼rý×´Öæœ#ö‡ëø¨µ·™Ë8k–²çš0ÒGŒ56ÛÙ_ôü؆œPo«Ov:+<:]jþÎ&h§K >ëô_æQœ¨f¤1 µàߦȈÑoˆ€ˆ°ùðµ ÒJ°}|ä9XîJW%õWÕRKùè»Æý;СSsóñQzT˜ÿ&|û_ê_~ó®Ï5Äÿ‹ÙÒG¡ä†f`=|”škÎ)ß‚íËoêjË_ÿöwó·wkŽß[~öã{)†1gÌ_ÊÄN{3ßQŸ‰úß”Uí¿üñ?þøõ¬× ~’i õl¹|‰³Ô˜Ú¬9’#b/EY²½ ï-ü Ž£b¢;KÚ «`K* ËðÎÆ¾nèžÌ 97l§\th÷4Q Êš-È€N°2¼“mÁzùSAgU̲Á!C}mIù£Œ:Q'ß™BüèlKÄÔŒH@³Ö­ ï¬xg¯ eõcÎÒRÜÏÙ,G}¯'–éevV‡}ù£Š&z|ëÌèžfexåØ2V 飔‰¹”º•arÆ ò(k-‡>²5xgSÐ…\b)áf·¦¤ú¯CDþ”cµWB&(lJÂØb®¶×?‹0O:hà%,šòD(V„²!. k y”ÖW^ÈáiXEx UR9•øÁ/ øo>Õ{è­'k}Á ¯ÞÂ`ô¢aÎYW$ëB«ð^ŒnLVTñBMÇ,G]üˆ:ÖÅ/d307øfß 0›¬ LÌÒ»½§á=×4å?ÎX;£[ÃÞsÍR<…IP¦”áMè„1ñŸ(J±°c9SÇ 1+ŸE ³>£uVT?ölЬ #‹î_Ð9ÑQ6jáSè§Ö×b­Œk~Îöù†f –Jº¦§|èà~´ç& bÁ÷æ5ÿ°LÆÕÙ\”a4ÒJð6ö6/ø{¢{Aû&´¨ö½Õà©Q0tÙú/cNM´ŸŸÙ¼Zк1»á…‡Ùí),tÌÆÒ¬³g%г![e¬ùš” cœˆ´Šð¾×¤lœ»Xÿ¦ŽPPo¯I‰Nš1´:Ù‹c²/"jF(r öÖF²÷¡kPÔK+¥XÓ±4ZglºÖŠš°Y„¥11X×öVv(aµK#¿ædûÀ¤G׬bi47'{­àLÍ[eFwT ½ }ü°¸þŸ6Ýöfr:˜|Cr#gKÇŒ7$C´xr«&Ï(’Ï2ä2Ñõ-bÌ’:ÀB/Ì’Q–±`ú2Er®1q wÅ’+pÝZC¿å’•BÊ”ØN$a¹öžÖ:$“—˜ú¯2dîÿ<-H ’#9Û!;-\ ’¡ŠA À,_ðHŽ\™%ÕPO$ó1,ÍØÐ˜“É,KÄGܼvPFûÐ.{¯kOe–µ†‡ÖÜ,Û;1u[²Y(\fY&éÇú<f¾sÌ©Xodæs`F½Ÿdæcør,ý’_p¶öasˆ{oðt¶6€ÿ`d;ñÌ~Ć_!„Õ“Ï,K“£±èÍ2Lûm½Ÿ„6 r‰MßÑ|‹¾¶²vni>ÇÇÂÞÄ<¥ù\îÜ3ûÉikJ@Wí}ÖúxʃÚ* XsqI%žÔ6ï Z±¤A5˰€5#¼°ÚÞ‰©5ûFüÖ,œF}'«ÙÆÉM8Û6(°¶ö£°ÇIkûìYYwâše¥¢SkºñÚÊ8/êúOlñŠ9TÖÆá‘Í…šÐhø<™me‘BWŸ'´mc ¶1/C'«™R­ _…íøÂöø’¿¤/ù+È¡Þ`òr ŸàŽ„2—ϸËÒ)`ÍH¨=ÝÁÍ^/K‚9$iH±bΕxÃ6¤l4ãc›ºb¬ÄS=6“²Iš}޽1Ý©õßÛÀç-zj£(pç15_¡ÃÇÄa9™½v¦ŒÎ\LóÈfs1I “Øx*M¨“s‰tغã« • á.BC¸ ÕêPE„ÆžÒgÅTÍ7mÇ ƒúM„fÏO|ÊB¡ˆÐZ—ˆÐl–=¯ÎZä)¡! BŠïaõÓ¢E„Q!SžÂÁV2Dˆ†Ì1rc?å…èCöB´œ§í»ü¢;iº¹(R´ê"Eã ü |Ì'r46ΙÓO9z@*gWôž9‘*ñœob4„|ÌÙ­ú©æ_uI•‚怙Å5ôED/G£1’Tnr´hUŠf¼°@«msËØ^†bƒ‘Ç}'3CïBãÝôõ’4ÍØÿâjÈ!J»žWQz`2b?ªfÁRQZÖ°ŠÒ+ cÜߢ4ˆŽe_Ãäð+™iÅÂ*ø”Ê)sÙ•-PÆÜè„n3D¡Œç Ïä˜S¾aƒZc›í†eîÄÜO[ºKÓa~$p­¯Q±ŒÿÈxäâyrù`¥Ã2ULõ1óM–¶F•«ŠeÌ‘ÐZŽåfܘ|CÇÇ/©W°Ñ‘ÐÒIµ¡Ålvî%²¿,;â‚/T"eÇÙh ”È✤èóŒÙhEÝ[ÇGº”{y«£¶°o«#&bŽ{ ¯ßŠÃº ¯ßR¼ìrþáõ[4:ñîòéõÛö1hˆŽ¦´”éõ[zÑ Ùì$ezý¶q ¯(}N¿­\h˜‡f«¬Áë·h!v˯Xƒ×oÅ3 ï­ßеFõÞ‡ á,¯V`¡Ô±‘Î!„~·–e¥öȾÀ¤³öÑ“´VBMÞyß7‚WÏõ¤l^5O1iÐÖdÍÞêX©;[¸«á…ƒˆ¶öNq˜ç°wÞÇÙª·ªè—h4 £Q¬ŠÚ·kjQß=”hªóʼÅQ‚0,“ •^y>…Ç{`EÞâ)7´ž®"¼îÃÍÊŸBÅŠ4…ž¨vÁSÎ{Å2–^Æë̹}b=Ó0À­/„ –KÆ—  K¤P,Wð}®®7,÷üQB¢à_oXî˰°ïú ËØ"0~XÆ­Þ°\¡ìà…eب)–kø€ÊÐÛš!‚eÌ)¹/Ÿ¿b9ͼö²n*–S o/¥½C–­cÜ?Öb,ÇIÛdÚFBÁ2Š0C+ÞSO,G3iB0iýÆenHØX.†€Ùüf¥,SèAfÛÈò»Ç<šY‡q;!„Í,ãšêqËÙïÌeeᾋóžÆ²ØÅ{Qïé2.>óÌ'Ø YF@…¶v£!ÞûDÓZ½$‰!Þ{”¡(èãd´y 3zª¬ú¦xïñ[cËIi =hÅö«ÓæfWûŠTN[t´ów' ¶è :·Ò‚ZôîûÄñË.¤>[âQÍ2T10™û k–a¦3Êÿ„µÕ:6¡‘OZ[¨FŠ ›ñj^sfœ(7^ó¹0°EŒ×h\ž ÿL_g’û•¼nôpÓA֯׹h©š_øäuFE(|½§¯S⧆©¼Ž >Â$já.kûð;¥5ä± qy{'Z'º¨Û%&)­¹«€?wI›Êy§=b=åa͸(¹—ÐèY=4Y¯ØAE5ŠÀ~hÕåD5‹h÷²ý^@¦Cb¼š. &é"ƒÖÚ Ô\¾õ¥>¨±2"ÖÓÒúÔèŠL­~ е:5Ôê£PÓù‹ieƳƒÓôðRþ_ñª‚éÁÈ¥‚ÿ“Æ‹Ò" ŒfËrHÃBC…ÐÃLwy,ñFí]Çck¯ê×ÀëÅuÏçãsÄîAm òB:ñL‡5„®Ð6‚úõ! ÌD$pÖ^»G`„`»ð«n}ÈsèÃ… 1{ðä çM”ÖQ.«×\íòwÜʲP™~ýFÉ|YK–Ù%F³TfU52Zæf÷ÐÈ5|@.Âæ\ãÚ¦ŠºõÑImŸ¿QÃç!ž*sžHfK Œòž'‘ùBô_êKuhéX_í×ç.‡ %Ìågá_ö6>è×ÿ¬î',û3~|Ø#µŒåÁŽT×g?=îVïõôëë/7@>غ\yÚ¯ï?wxýu~}žÙÂŽ Í¡óÅ£~ý‚7/m<Ûùò¿¿þ{¾€ðÈàäpðÜ:u_³NÌÛô,~³Ôü\Ìl‚º˜¥ÏûõýØ~¿>+<:]jþÎ&h§K ¾É¯Ÿ§w1iþ1¿¾Vò”__jyÀ¯5û†¤C¦ûy¿>Aï×ÿÓ?>å×oìL°À¾ø…ÁØ‚ôëˆtK^©m…‡'4g+Ë^©m™s>Ðne+^½Ó¾ÂS£t#lYºe¯Öhš‘¾2uFˆÌ=tsEž ¶’ñ±þðgÚ‡iPJã’Í©•‡Fþ¦` S«‡û( úsæ*[ëkÑ&êHP ÖQ“VWÄú6ÆC4îè’„Üš¸êGMárû6žº}[ã O¶Lh©ÖaMüGTQR½êƒîØ_Öxñ´îÝGúv(·¦ô·¾­ñ<%¡- {x÷QÀþßzh®2ï> ÔÅò¥÷µ±B×·yóaŒ²¸´)–HF&@…[©M2¾­;x ™Ôæ²Cr*ñˆ£i|*ä5[ͤŒîŒ+ؽï; JU Ë’Ò©C¾&kàÁÏÁÓµöX;$Sµ­I×£wƇC û¹A qOV¼³¤˜ÊRzzC$B¿K6:UÉk²ºÐ¡s-“hOb‡äYÞÑËŠ‚èÔ%_Ó¯Œfñ2cPÏbˆL<¿G5“OÏb‰ä€êÚLÃïE,‘ù£ðTÏš#½ˆ%’ 0 8®3ǽˆ%Ý2Ñ›fžíU ‘ôÍWÚõ­ºêM‘‰ù̓V$¦Hý‚&¦È„ò”£Ñ¤·Ã™Ñ½såèML‘ôûáëÒêÍ.ÆÈ„UÄ iÙ[d§G}›Ãjö¶ÈÌ3áqŸ•µýf3h¾û0åSNe6{’$šqcv³Q¸¼ÔÊlný k4ا)³Ñ…ÍN™ÝÛÍd;‰Š2›ý[\&Evë ª‰;/‹ ›9r*Û¹­ÈÆcÃÁÓð7hWÏ­ƒ- íÊÓN¹—«ÌC»Gîs½S ]w9LY³9*´Ñ ¥ñXÉ¢¨@;Ó¶Na¹A›î´ð² ´Ñë˜_q } íÔQ7Vj4K¦B›AFeØze6ŠhrÛ‡0•Ù(K »m_Û‡0“£¥ñgƒÙC;18/«7Ú èk+LþEmý÷JíÄí (YÛ¢R›mÀRÛqMŠm|A¼Ñ[³­(½él˜­+ªWéÍø$Lw“Nz3Þ¿Ä•áhãÛØŠŸBÉ7|3 ˸7|GznãµA*¾#yƒ9´œÙŠo†-¡%uÍ!Å·W)¾#ƒ0ƒ¦„ÞŒâá)õO„nÖFÅ,ÙÐ(½ùu&¯ÍBèÍ2î¹+h@éͯc4ó¦°Ð›­Lé:º¬ôf“…lùRèÍ.bðòJë¥ôÖ06¥÷QŸ§·ªJo”…Ú.Ç©Òûè2¡7žcÚ”í:Uz3º/Aè7v37ÇuÒùd75Y¾oÉ`Ên<×éXßÙÍW1®y¥ïz0@ÙÝ;Ïèg0¼ÞØ]h7§…~ÞåîÒ>&“Z…vgwa,d×ð‰Ü E)ÙvBewj »A§/ÙMÙͽ¢Œ0–ïÙM ¾ ¯ä<»##N15ûÝZ‚T¡WX¿²;28(]Nde7`‘òŸ—Ê!ìf{£”v·–0Ž`ÛNv3àˆ’Ãê0!7ON@„I+y‰[#Ç„Ü$à@KK»[C„ÛÓ²r®D¶™Ê…UíÍÌS›ç:§éz¡‡6Ãä¹ÀW ­0g†ÔþF6Ú-xbóÑÂP§ s­ÅDJùJÀ$¼fÜÇÄ-w\3²Û}KwZK0¾°š9öð¥cÔÕú¥žÔ<P™“±Ü¬#ìƒ01;ãÓGó<¦5]£Pšç[ nÑA M‡Û`ÂFÏheN©t°Q4!tä²)¬G @S¼nŽГ)á˜aSünð̬°öVgZ’s¿bŒ…Γ6 <ßòÉf” ~0,œQ„© [“Í“+òÎ:Å$hfÛ™”hÛ†ýcÌŸ+ãÜ+9zâѤ?'í€Rm³nDnÍ ζ˜ â0˜‡/ÛVþW¿ûßþî)Sy¢‘¸ïL <û01l5YV1ÀøÏŸüÔ¿ùþðÏõ»ÿõë?÷+­MúÙ+™H®­ÍÛgû²oùìL`,!åþägÿûÿëøçoúæ¯Ûìå³S@Ë&t±œo£-eßòÙŒØÃöã&?ùÕÿñÿÝ7Lë_÷ÍL4Ô©ÅÛPKÙ7ù‹W‚|:Û–×Õþ4!’ņù|Zû×ý?ºO{¢è9g ÏñÓãq6“@ ôÑ_žo€ÿ`ësýåé@ÿ¹«zÿï¾$„ILÁFHqT⟠ûÈ‘y€ªÎT¿*Äèé°Ÿ÷º}â‘›,.(<½ný÷Ôïø3ì ‘Ä HÍß!…MÐiÁó?nt'Ú<ùc5Ý.UÛYØíwiÂ7Åþà§À£OP"Æ|,øç¨å©è­æð& aÚÏ¥÷îã  ïþó¯z.­#<]øýS Ö12”à,Z´ƒ¼J tÏÛ¢Õ ns—•uoÑšµÐ¦›58‹VAÃëèÛü1jq-f¯*ùÊø;jw­\¨?_öóÑ‚x#" Ž+—ìhÅ[´ÆG 3›V6è~[´\C§ÂÛ¢ÅacBsŒŒ^œE‹Ê,Ãâ«iùx»÷Fp­\vƒ1‚÷F0­a¸ÒOúéß¶Ý@.3NÛçîmZ4S@ŠZfíaé/›O ò´ôzå,>þ§}ÔC]™Bê¼#*˜ˆÃ–==yŽíQ!ñ"“a'ïˆ y™¡ûøŸLËJ*6y(üQÁ\m¬3=Œ¸sá?£1c· LëCëLæLÁÅw×°¬ø ž†Ô´N©O.©wOûðÄ‘Yëæ¥]'Ý 3 ÙGñdJ¹r!ÌÜ}S¯–VމÅã"€"Æ‚G6f).ݘzÁfÎÒ}oÍ—%kÖà#€üqÃÉÛ^F.¹b3ÓÇÿ UP³·õ|¶à¬\rŸËÄÊy[¹x@%ö¼Ò&C2¼ùv5O*¾ÈÿÈÙL¨•o+×ü๕@’‚²‹ýÑ.Á™¹$ÍE’ ûÆcɼí\è6Æ Ö …u§iüu§ÂšÁ<Ü ëŠê˜£eèWX×ô‘Ê+Ÿ„ºT"aŒfb Âº0síëØ¬ÂZóŽ(¬y X_)PÖÀJËѲ?ß` e™QøŠrƒ5éy ž²šKKÃÿÉåÆêL×e[þ4%5ã–J¸†NQ2ìWv`eµæTÙ¬Æi-L7V'æk§Ä3n¨f–ÉXé'ÕŒXʱíc¯ŠêÄIô;®w ªSeÄbßþ E5ÊhÁÞ©ëÕx'º¢ï¤A‚j¾²0/›íõŠj51s8Õ NêXùë¼ °Ú"‚xmÎfšÀÚú(_qªkKNcÜŠYZ³Œ1±;+àÚžc~¨å/S`£l2 À…åâ¢~hîËW¨£›ÁB%}Ï‹Û4Ûy/ȶयÌÂl–A›¸’¥ ´Ïç<µí9žŒZYaÛz¸z)e &a‚ðúµg¿Ö²z ³%1êʼnîÖ˜Ú+ìTwŠnè‰üÐíÊUvW&Àç­èöCЦý‰áU©ÞØ]ýésA{rxN;Ù]¸‹¼·a7áR€ùwvcËnÝîìfœd†X–í‚ke74¥¸¯ÒSvcÍò¤úN¯¦ìf„VkWvs¡`VÞ:E·N\A7žÊ}̼R8)º01;—t«èftOW¯×”ÝzŒ@ÙÍȹÎËV–l#ôNå\>¥7ÛBl.—ôAoIsÑ[zSéŽèâuÉ’â›RœgÝ"‚ßšdñÀ7¶ öµ½¾#S¾fºâõ5Þ1²‚=ß̉^ì°:Ëã[c(¾5ÖoŠ{¦Ö^ŠoVÇÈñµû+¾#ϯ´K4z ½5&CéM‡zÁ„ù”ÞÌâÒÂ>ô-ôf°ð2/ô&{£=ãÞÇÀ*½AaA›7xó1R;uüoþÓ¹¬ýNàÍ^é?7#½¸ˆ»™3]yZ ûQvc°2Õˆ+7v“¥õ•QCÙͰÝ{¹±»0ž¦Žuš¢«RÌØR Ó~X„Nº¡›Á㼞§lù9HÔ[?ŠîÈ«$¯ü¬‡‰DÒ¾)¹yµs¥/qDÉ ˜1MÞ›ˆ›‰e 'Ã2Ÿ¹5ÙŽ›8…‘3ã&t3ãè`’¡unÞ„ÃCPsížÛšR°Í @^B‘§6cPhkÚüòОËz¸¿Y˜Í½C´CÕÙ\ üä-ðybkˆÇ6#Bf¹B7…×üç¾Úp3Œ ˆI¿.qÍÓšqŒF^Ý*°–8A5#Br¾ÒÑ ©Ù &Í[ñRjÞµxSÉâ§4BcOºD˜õ…iű ¥ùU99Ê Ò|*§+ñ0š_Õx Ç6lxsCçy’eíba$ë¼Ú©9„'—âä*€žŒÓ¿T0o a™Ñ rq5BûHgˆÀñÓÓ1úÉ»òÓ7$é+¼Ÿ›aGtf/ç©¿ È¿n_ˆxd/*<¾n勪͋rÝò`•‡ŸZëþ.Žêzh¾C„€c;þƒí˜öÇ»Þdý£ë¥îïÑõ–ÍM»^ÚðMAМ!JÑIÿ± £–§‚´š‚:ï^´ë:y¼ú烊ø—ÇB°üºå½l•Q¡Ð±3áÚÚ„ÐÜ ÊÖÌ{Ä-qẋƒ‡Õñ”Sènló*pc8::vy6b€èÜL æ-ê•ùçx49.!ú%owaÝè>© öu1ÔŸ(„rûë<ôT§CU‰‡õË_©aò¨Ù¨ë2øIe}%A¡W…-å϶U8ÅŠ)Kƒ¹V1c F¼n¸Da·D˜‹®ÔêR.mY½£yP}þnwˆ/R­v!<¬Ã¸kS"ið²Zh^q%ø`Ùu¤0Úª—iˆõ©ÂšQ2®ä×/_,u‘Vó.ê–³áƒLáçY±¼î®´ëì>ÏQÀC%ûò⸜¯°Æ,À!vIâx‡“Éî¦REsJKûôÐàù´õVF w ÉŽpÀüº9ìWì/gö†¹ê¢zMdË[1ز ‹¥H^Y“ÊFZÐ]ø@â}µak”ô˜úøãµ•¯‰¬Ù+obÉ2×DÖ´Ñä¾Cx&›F¨wǾ¿î|5ïèk3òêcÌû]bкˆ¯qêEóÓv¹s€Gw«¯iì3 Gúqçkó¹/;dd ¹§Øf[Øß1¼u“ObJ‡uP)F»ªóšÄš<:Ò…â \\€IÔOì2ÕÖÄ›’¯YÌëfé3YÇŸPf§yÖ$fq^[¿Á‘ÂRðŽ6Àù“11ÙYß=ƒ™ò›¾Ö•¯†7þØý˜{3igJP´_*¯ÞÔóTTÁÉw¢#ׯë…O¾óòßÄ ?Öµ¾ßñyeÆüãÀ;­^säS¼ãæ7³xÇqÇ;ÞÚ¯~oíŽwž*{_‹¡xgòYnuW)xÄûÌŒ‰ºã½3>…×õŒxÇ;w1Ôx]Û¬xo´Ðú³˜©xo4DÑMõ ÝÍ>K?p«wºÓí—hr^óFéÎÓc•BÙ2•Ý+)®¬ËÝy£pcæ<î|GaÈ çêtÅ;s¥påç=ð^™à:ÝñN£÷ˆ#…6îx/”^ùžšÁ §Kr|ǯå{äà»z(¾^ ©Ñî|çYÞÏÞ÷× ß '¦GîíÎw:Ly§wÊåÎ÷Ì[ÉA¢¼&|σá5=z'<ó–×õóáÑ´Êϸß*„§ˆƒ-3öÝmBøŒmº³ö'„׿ãy%6cæü„ñ,¼íºå;ã1¨É¢òÞ„ñ(äR¦‰þd¼ù:oÞÞý#Gae–¦hŽc…< ytÄXo”g` F9Ô´©ë1ÏÂ:^–cå¼=™+ÞbÙíô,ÄWaÄËôŒÓá”Èk,/ÓLÅë8ÿƒqì™ß ‡ú]˜ßyMf…=s6¡Áa¬¤´¯q@éZÊJ{‚Ô¼vÝC˜§Þ†E¹”Ü…ù’1ŒWƒD˜Ÿ<’þÊSažù=ˆ‚ô‰0Ÿ™ˆ„˹Î;í3«è%ô­?홼 šZ]Zí™…iVÊ„÷¼—þ™æ÷Ìš‚€`»ãžÑ6hòNB§¸§G”—€_ Zp¯ŽÞ÷âÍ=pOÇ25¡KÜ'&,W³÷ô€_·DÞpO/$oŠ»±‚{&rY‰qŠÃ=Ít—¿óÀ= -cÉ:Š}àþ¬LpÏ'y9Ç r>p¾VpOÇ:i¶îF:p™°}Å÷Œ‹¨q­¡½šg(Ù%ë{Úó9ÆÕÔ èžöšâæ }4 2ó ='ïòÖÈ*ïùèaig¶€­µì# ‹5¿Ã^ü×ëÙTF}/ðÁz½^ã`=»c”·f¦¬g¦¬°u:…=íPßÛ|KõG|ă {ÞXÒ)›Ò¤qƒ}á%YW¾Ìƒõ…·Š1+ìštÊz€Ó6ìøÞƒõŒì3\ÓUY¯ýp°žJ\þyëžõ‘ÎÞ²ÑêõðÄz¨/òðõRA}°Ã/å’0õœd™…[™ð¨gÀ}dÌr'=´ˆfWü“‚ž×IZš¾rë™4¤Ïú2¡8Ìs¡ª­ìWzʳ͌û\£B~òÖ5¬ñKŠô§<ðžÔõyÂxññ àéNfŠ›ù‰µf2?E´ã=7¼“³_—nºOæ¥y%WT¸O`cã*¡ÞØÎK]é0¶½Á£÷{TL4¨dg#FºUYûJd0wbIåúäMU½ïûxë¼4„GiÂÝL3-p„i.Çê, âËÖï<Ôù ¼Õ$m™Ø3]¯/Q¤£¬pI]ÈŸ­8†½x £¬p¬ä2Ês¶3Qõ’ÏÏyó ­·[þû z³Ç·ÑÓœe…IC>3Ï@ð@Ÿìc' s½3å0ÏhSÔ<™Ôvt’œ—ï@ Ú÷v*ÈùNz‹ãVö½7‰…ý«2¯PÌ–üøC.Éþú'ûk (]=èðIíø”öwüè¾í‰zRY·z@™ûÃŽŸªù±ì2ªgšãºÙÃÞ·ûVz¼ òɫ۟,ÄrÝ»õza¼þôI~Ñï\­vità;ˆ0‘¡©ÿæA¼£ ªöUu=äðZ³o:<2„›O¯Yÿ=ëî³ã> £l÷r/9ï¬YÊl‚Ù²èɳÄ:Ú_öüð†7‘žëvVxt»ÔüºÝš Ý®Mø¬Û™J”€ àúl£¥¡µ—AÃÞ¿]dƒVRèavÅög·†\•¤_W‹9Nsí‘þÓµ©ÅrÚ0¹aÔœ6¿¡ÇÿAºý ¥x7Åÿ‹xBhЦb7ôðvÄœ Ô¹[J°ßäÆ4 u5æ¯û»¿ùÛ¿»5È'ÙùÙ€fÄ›XͶ dHÜ6!åy¯×ßÎòßþø‡çÒ30íÂëÊÑÂDcK(äÆpGó`œ:µ§¥Ž•qÔT (’ë”äzÇ`*î`i²}ÀŒ¦½Ï?S}Þ‡®·wΕq”—"¢Œ ©<2xºŒ£¹òì.4Æu #Z^—Žæåuª;ÛНÃЃ¡ÈG¦|lVö¾t4—Ší¿ÐåD™>ñ,ÕúZX–,«(ÜV¶2ŽZ$)yá5$ÍtìWÆÑ…ZÝ FM€O¼•M¡õlåÕNé}ã(~ùˆL;½\{)¹L£lA`¶ûd›)»;GùÜŽ#±–g—j4ãýy5a=·ršÏ%'žä} æ_H%š¶xLeyT—k3ñbÔWO%»¦'ïÃÑ©¬t£vÆše¯¸}”U—o43M,_¹üÏ©º«GùSn×i—$†¢ÝØÜí£çÍå…Ì0޶½çøé})Ÿ£‡l®{'RwYG­³ð`–I$u—vôìÈîî e}ôU탑i¸Ô£|Îêp·²,õëFù4\òQùI<ßײèu@„E.û(Ë ³òP˜}·^÷ãfZÊޯ̼Þùº ×zóÝc9¸¤ü:^˜Àx+¯¥Í¬Ãï(¥]R>æF;3‡ëkÆò†w˜¥÷öž±2x™g¯{rYÖ6g¬Ì¥!Í<4¹»ˆE.©õßYŒ2™©\¯›rϯË.©5%]'3oM}Ï×ÊË×9tÛüSñ x,–ÂóMa€™Y€n¼nk.ðꉯÛô3]yM×Úš°ùÆë*üT^Ówæöá5½Än¯É¹÷sÊkŽ ƒÍò¯I¨tÙá×Ó`‰ò ×¼µÁlráŽk;ßôæàšÇuyÇuÉãä6Ͼfžb›¯xÏ<Å65;öÉ:z`›vNžr2£Õíì©¡Ôæ™'»}:ß©?ÞçµhÂêô3¬ÖÆmVë6(¬¶§¼e—yVÇé%óƒÕ´þ ¼vµYYÍÛ“mª7Vã;^%ßX}”)«ƒlzÂêó9kzð(©„‘OX³ÈM|u|“ôÆj;ÌHìxcµ®Üן¬¶ë)Þ@ö¬>Š„Õô“¼77e5¿ž§E>(«£]Rú:#¦¬¦sòÝ™Êjž½~K ë8½ž¤°flëkê+«£MaMç›k~Æ%è>¡¼ÎoYø^»W^@•×c­¼¶®9Q^wùLå58ïß©òuñ«¼f…“®T¾N~J{\g™ì‚ë,bÐz—Ö„Ö9ú‰yÐZô¥õüi);ÉÜ;pý ¥‡È}JéÉ Ý¶ïÁQLgYÝŠifËy‹8Êé,‘›™t~ØÚ–l*ÁnÛ`³Ì©W*\óRÆÐËrÉ)°F(°§l…ì£-l^‰öcØì¬÷ôV`£Ìëlì£Ì;gÙ«ØvYFgZýr#v¾ƒ:G멱Rn(¨³J¹ÔY$ µ¶@AÍp1\uòN5¿Øéê,j§‚ZFAÍopÄRó:ÑYHÍï{Ë{˦–ü\|2–AHÜöu’ºŠ.¨¤®Òc‡d- ¾’ÝðgÔ:x‡`­b Ö:]Ô˜NBö Žå'åêX Bê¨ !uÔ†©£Š¬žÔQ&Š’:³'5ϱ8*²Êà6Av,j×ðÈŽYè%ÈŽ^MTbó>-g5b£Ìï_BìãÓ±£,ðCÄΞ5‡ˆÿBì(«K‰} ©ŠØÚ@±½&®À¶+ºÞ²ƒJØjÆR [›"¶Ž¶JØQaî­“ò±³ŠÑ"bK©ˆ¼5ó±e‹;DlQ¨[ôªCÄ~Â"vñëê±e{?Dìàˆ’›©aß–ÜCÆf‚F4¦®î,ëŸ;Iá«ÃG²¼HÜa–óˆ-w¡T~0|á³ÚñÍ+|áýmOÔSÚòÒÛI†õaÇOÇÔ<^yAw×Ê/7@>xuúñÓãÁ þ‹÷°Ë/ߺ¾;ŒøpèHZ±Õ^ÿ7ÿ’BÞëõM†G°%Ç…C$Ü÷´÷¤xD§Ý×ü=|èóº Mx>tÁox_^ð\·³Â£Û¥æïÐíÖívmÂ7….@ ¥¼j¶….h%O….h-ߺð ±Ùn“†0˜©ñýBl@ô±ÿò?ž‹ Èóˆ xyG°q‰ N*Ô4_F·c î2ÒÌDáo…¸Dw)][î•Ô5_ Fm^àåfÎr)b}Ib¹ïhI^!ÎÓ+4%yÓ¥8GKvw‘FÂ+SßFüáEðB]óípÞ”WŠ»‹”:½sÀ•â—C¾¼ˆñrxɽT1^v¯‡RÔrVÌ&Má•©o‡ëøË C¾4w©ÕwùYæ.$=|Í…—¦¾=®b?.ý°b:Se gŇBéËí$:F" 2ÄŠ©9Äí4e ÍÊé ËeJˆ€˜ƒË”é£Kj·“¸–j8¬˜nPké;¹FoŲF‰˜Þù^£»¢Ôìífµ±ãf5¹;JÍúü2 Õ$!Óiü5¹;JÏÚ²„H‡Õü¾¥ÔLä¼ÕÙ̪‘]€Àô«¸wM©÷ß6•Z$@@|!µˆ-S´×ZÝU¥çT‰°®îŽÒÃvn{kÿàS‘BëÜÅä¤uK>æAqÝŤ®¸®¤¸F—qç•Ey ¶:còš‘ïS^“>o¼òZCO„×⣼NpvðZB^ç¾R\'±Y+®ÅèsàZbÃ×Q6Škut¸Ž~±¸ŽòœâZ¶o¥uøiZó40Õhö µ¼²_1Î殺¦Wûž ¬VïôÁê Ì=CÜf2ßSópf®ƒÕâžSVó¹÷üQVG‘„ÕQöXeu”½RYÿÂjªPXÛgKW“n´>š™ ·â„Öñù#àÄ ÅµD@(­ùåoÒš§¾ß+Ni­JkÓPl[\±bÛŽI¿|+Æ(¹›3>Ÿä®YVœ’[" A[¼,‡ -Ñ9Jî"Jîâƒ1ÜY›©‚¶¸ôUÐŽ6>Ì}r´}dr[½Ç·eMÞälgZp£jƹ¥•cIÁ­²‚‚;ë"à>¾NÀ­~V÷ñN·ú|•Ü\¼o­ý³UKr*ÍB7~tAGŠî,×Êî³L¢$ÆLÙu·vÓ#üxQvg ”Qv3ð[v?äìä^”Ýìä·à5XÀ¿QÐÍ;–Þ]|ˆÙbP9Äl‘PÝÌBã´Aw–E·5¨ ]¥™‚î,NOEwöNOEw–@ØCÐÖWª -á׊n6Ùí­*qg/--k–wb?3pû­ÝÀ­ú¦€›ó–)‘{þ´…DÏ"wõâ”JÜE˜¡wòR› ÜŠ=ÏmÔìá ÜŽE,î˜ä•n–y#ˆ·Æ ¸ã!Œ1g‘¸z*qG¿êÜQù&àV³‚;¦Ÿ”¸Qäí*Âmõƒ+·Q׈ú3à«"·V4Ž˜¿ƒ#fÀ7B¸}ôÇl–Û–½ %ÈyžZ®ïû |ðvL¶ìÕà–¼i³QÁ܉Ԏø|¢Sƒ«X̰©1»€3D´êõà"gR[­ïû ésš[«ã}!µuçÉmM ˜²Î[«ïÌfšzy¦DL7(˜Ý¹]¥Hì—ÁëaP¹ÞWš½Ô}Á8ì—~8‡Ø/ÅEÓÆx§þ;NBµ)öËä­ À‹os(wm^öK§Ãw*˜×<=l=§œi£SÁ|ÍSõôöxÄ 8Í­G‰˜…nn†kª½º§ã´“Sù:5ÌkÆ&Ñ›z:ÂüçQÁ|ÍØ$*XÏGœ€ KèY ˜2Ozñаž6ëåp˜^$R@¼½½‘ÎcÝ«S„%ö€’±‹sŸ˜>R@¢z“Hme;"\Ì}ï^NÓMz×H…~„ øé|ÕS!ÊëèðßxÝ}—¯ñ¼,8áõk¶‚›[¯/óà+€íª7rw9Ú äæÕæŽ Bî&®%w•cAJî*v$%wéÞ§£ä.b¥Tr9D¢ä.r´IÑ]įè–I{ ÛûYr‹]ç ·Àè ·x¦rKô×An92~»Ê—or‹7á ·œzRrg9zu»ø«äÎr,KÉÅ`­äÖÓž¹eKrg9¨äVǦ’[ÏßÈíl|7r¿ Ï7p;{õ ÜÎÓu÷[D¹ÛcVÀ-îõ¹}G+¹»ìYJî.r'q³äî^]9È=”øžÜ©Ëvmä–)F ¼ Úk‰ìνû™yÈÚS„ge·¤_RvO9+yÝ’ðëº}•¢[EOºe†èöæƒÜ͇X)¹k“ê„ÜU|¢Jnš\íÁÍÉí¾[À]ÅE&à®â(Vp£ÌQȲ·‹OÁm—S¿œg î"^Vw‘¼L ®€»HJª î")¬ÜZ‘‚»ÔŸw‘‘Qpë‡)¸µ î"C£à.ñ(à.€¨à.’LÁMo¥.ÜÅgÂPn«þ¨àÖ¡Qpñ¿*¸5^Á}Œ‚÷ñîcÜGSÜlÊO»H®-·ö˜pû|Ìs›ƒ÷ÖâÛE„c”Û¼=à’.Op,²™€»K@„‚»7¿{*¸iqË_À]ûOƒHéÙ‘»ø„T î,c àβ¸uËUp3Ï›ûwÒ=DÀ­¬JnŽÈK(Rpk €;ª˜+à>óàŽ ¢ä¶ÛWœ8.1Ú+Bn<ç¼ÈJî(C”ܱ‹r³ÈÍsÆ !wRñXÈE`Próö“÷BpG9€rØJ¢7q)¸£$$Up³?ÜFáÁQn¼Ò…K(¸£¬*w\¹›6½ÜÑGâ(·£ª+·£øÔ•Û’¢C±‹[TBí£DBtËOÛI4)Æ!mK¾…¶æ QhGa‰R;.æ¥6oЖ<ÆìXü|u¸Àà±¶•œfúå±±?—“ŽåO |ZÿîšëC~ô_÷DE<8BŽŸ÷Øcõ!úËó ð¼zýøéñÿÅ»òË·„ Ô^Q ö³Èû¡Ÿ š,N´ÎT¿*<áé÷Š}³á‘$þ_±þ‹ê÷`…‡÷ZjþÞkk‚z¯µ Ï ¸Ævú=¢¬Æ£ã¥êïq7…µA{^ÛðMqø‰w·ZyUêSG-OEÕ<:ÀL ó\·þ|èÀðÙþõOÏe`˜˜ pö,OfÒéSRõân´Lo5o”®éüs5x½XLô£Õ‹Æ0j?ôbW_ N/Ìà…‡o QöÎUÎXF §Ñƒ?%NÙÁÛߦýâ# ¢û092FðaÉûÚÆ(>Œ@l¹ƒÖ Gð–ÇÇ Fà4º1‹O7 îáÁkßΨà¿`†àϯŠG";¿*Žªº†øw2ךO7à!;oÍXüÊ“w›ž!Óò…¿|QÞ±2™ýÞ'pæë™Üýæty+î3 "pö¹éÇ÷Hn0yÁ¡"pÆ´Y‚&p–×YŠ "4—cº¤UÔ ‚·9pÖ A¾ºZÄe?u§ÿ+F\P~ [ñ.(¹>b¶®.(gp¼Þл œ–:{”ÿÞ½ JŒ “·úàg_Ÿ¼ÝP\PïÕ‹ÕåôÕ9ƒº ö}ÍöÜ,Þ%œÉë ßóT‡Ú›ÄˆôTð€òÚŸó9xÍÓNnÎ ¯ñ¹Î<"¸æa'8$¸æ!)7׳+æ=®‡,EÁõ#€Šk=[«¸nbOR\×îE*ÅuõÇ •ÖUN¦*­‹Lu¥u‘”ÞJkZí߆;Áu‘㺊kF1¸ê×%*’=®‹Dv)®³8š\+Ÿ×â„V\gÉFsñZÒÞ¼n~×S`gq*°³¿wByåbåu/“ò:‹ãPy­1~ÂkŒP^kHÑ×'¯ehNp;Ùün?4 nݪNp;“ñ Ü®§n ÒOn¿­ò·»L®“Ûoõmáé ÛŽ 7lûN±-Óos[¼†(ºƒóœ¢ö‡¨-U‡¨ÝýtWQ»ËAewSº »õB0aw•)¦ì®ÕožÊnÍä}°;Ë®¥ì«øo‰íRxkôðo‘}nðv3Pá­R¿Â[ü}øÀÁn±Ï+»‹„U)»‹(Êî"©Þ”ÝEzs³8—½²[Ý·ÊnõË+»2·^_¤ð.²ý+¼íZûW‰Â»(<¼Õá­ðÖm\á­nj…7gÉ[µRxÝGÞEi oŽPxYY ﳬHü€yzÑo•ÞEb±•ÞE™ßEâ­ßU®üQ|Wï Vz«€¶è]%çÚƒBo p¦T¡w¡Héݧ å½½åBè]½^|³“xcÚI´Lì$â~Txg‰Txë!€ÃN"ãªðN2ÝÞêÞVx§¨6ï$7Ÿ(¼“Ïe'ìÖ«œ”Ýš7IÙ­)¼£„2*¼£PQxGÙ±ÞQÔ…wlþ’® ïø3‚7ÊÐE#œÈ'ìf=NÅv/»Š ;Ê ¡ŠìãU‚ì£åÙÇ+ÙQr„*²£ˆuŠl 8PdkÀ";þ ²£\©ÈŽºí²£¤dGõ¨ÄŽUäflf$y+ð ì(Jº;Jøœ;Êy(vT…HˆåžÇEìø­76®ðêËoF‰?À?—¿ÎþÁ“Ÿ·àÏM}…¼?ð‘šðª3†àüíq>0¼üå)¥þj„þö‘n‘ço‡èW_Ðß¾%œ G¦|™c!ö?NЙ’dDF¥¯º áép¿~߬xd/<<¿~囪MrÝfð`•‡k[ëþ.¾íz‹*8ñ ü03o*U[x´ó×yí|©û{tþ²±jçk#¾)² 5&ÿ›Y©Eµ<YpTóDdAç t9u†übdÄüËcqX„Ý’ôµÊLÉ ÿ\¡äŸë]'Àõ¨2²`½é8°| ØÁu6ýsp½Èî|p=ù˜–»Ìî…–à¥NÀ»`‹ðâŸ>/éyNÂW±”ðå§ ¯1á¹§¸O _$Lù ¼†¢„/>Pù|Qž ßK<àïù^‚2bñ½ÄŸá{ ÞUvð½½Ä-݈ïEÂ$¼— »†ð]côÐó„·Ó…ôü*¿M éKÞЗO¤õ"YnÀŸ½,€/ªÉ*à‹D €Ï?'®³[Þg·•ð§ð"„/þ†´ðGsðñ¾H*öðE|àá‹äÐ?¯òÛ s>=Á „g¸Ákó»þ4‚á«ðõgL2 9pC¬|ϺQ+ß³düR¾g{•ïÇ&®|O >å{RÛò]C¾Çq Üó=Šð=ö;ÖÕÿ­XG™¬Áºzü¬ÓËíõqÁ:öþŸÆz¬jt®þ^{,Š{̲cn°ÇcO°GÉ'v€=f•Q…ìQ¬ÒÙcÖ²ÇüÓ‚{Ì»%Âá0œy°ãAÙñìzlÿ {””CâϯÄG•ŠñgâÙíÞV'ˆç} BqøxhZññ° âåÞŽñzQÅx…8u…+âõ²ŠñQ®]<%%ÝëŽ7ö¿>äkÆ‹¹K²¿þÉþÚ‹Òõ×CáŸÔþˆ7iÇîÛž¨KÍ|ù©a¯;~j]¹×Uö¾Ý·úÓãMO^Ý®?YVŸøôza¼üôY~ÑßzB’ X ãKI<~:«x÷þÚ‡ ÊFŠíkªz<Àáµbßlxd7ž^±þ{Ö-s`3~E-òoöÔìˤabr+ E¬g¤ìùá ï°«çºÝ*ÔnךŸïv›ÈÚíÒ„O»ý—™D9¨4(m•ÄÃl¨s¤~÷Ï{<ƒT’{cLõ¨PâÏÄÔ_WKò^îP¯ò­ôêÅVåÝ¿û-¯N€¼¿üþï]¥¿ Áþ—ú—߸Šw[ü¿˜L- a-7û^‹†¾ÇKÔo-iL§PWcþú·¿û›¿ý»[{0&3íöülôJ„Ñ©&š¾§6îáÔL_Ñÿõx.‹CìîFÄð-aòÞ5Rc¸ä† ”•ÐëR\ÇJn°w}©7ä¡41{à•—*_¡Ö'½.§ËŒ¦Öc³¥j…Nû,+a®ä†“®ÒÊÓ#Ðó÷§Knuçƒ'N0ö”ŠÃòº‘·§ (×%˜ª‚KoXy5SŒë¹÷ˆ| Ë*£©ö鷺f ŒW)¶”«ÙR\é ééÿ‹Ü0 ÐL͸œâJo¸@ˆd—4ñæF6¥ÔhMIë¥Ö”ô¾‘1^´ÓÛRré «]ÍZi¦³¤ìîD¼•¹ü†, £q †•­ü†¡õUß •EìéTV´Ÿje¥ã놩$‰«^]–yÞóy™ÈRYù gíyµêQ©fALÕå7´úÐ÷XxVäîD´Ç†‘!˘ÌÄ~ĸoƒZjîND–AÜ…êgÊVj.½aÍ<és™ë»š»ÑžƒŽVƒuqwé YC¬ÍÔÛÔ]vC¾±¥Žn´pƒÔ݈,ƒØ‰Õaö4\vC–eHæ{ @H}_‰hïó×>n¸ì†öXÆzìfÝIó}#"‹ 9b*™Ï/M—Ü×ÖÑ1îͦ$sD^Wxò¹)ÓÚTÁMw·P`–‘Gл•¹ô†|çØf<+{ûÔì–ÃÜtóWSaïéZ?rÏàm±"=xÍV&p*e«ívµø{¶â âë$òÌëO–…”°š¡('—àЪc€r5›yþ.Ýz Šw3›–ÿ\7xZuà0MVæòVÞçÒ(›_ëxÓk²Ò§R´Œr©Õ¼«kz.À<Gá™]±«b’ ŒW¿C›é8—­èd6þÓÈ2›³íÚQaF…Ù“3“f¹ÙvÐÄêhwd·òQ ííC‘]éÅ´_ë[ˆÍ Ô¡…ÆIlÞóÐÑúnTbóÜ.0êçØ<ëS±ÐVX‚›'çòîË“Ø<ï;ZÉÝ®±b[ÈXC½›§+Z×~$Ä®ô!¡Ç6„Ø,c¬ýÈwb3ù.¾{`‰ßˆOÀž“&ÇØ5x뜛a†K)¯w ±ñÕ°Ë-î ²+«ºFù…lö±U“oÄf=àØ[oÄæcÕ®I"ÄF?fì²sy–Ù•Wµc$ç’„Ùxgíè¶Åe6­·-¾¶a6ŸÃô³¬^'³yœ´ƒ¾  í£=´í\&¤ßQ…ö14mV{‡m}§B›+×–$Ðæ±KÙûÙv®C:¶È+…6[‚ÏkkQh㕹†’BUhó¹–M*»A›­Ä œ}Õ'Ðf3;¿Í¶9¥6ŸÃ6×W˜ŒR›“rD4tÞ¨-SÓ Í‹ k)>œÆAem^\<(3×›°Ýâò›|&l7žÄà äQÆ n+à éuÜ„íF¾w9!7˰¸!-‡µ'w[™4Ò…ÜV,HÔ@_;ÑÍ2À¸¥VÚneü›ó Ý™‚zo1å“ÜhZÉÚ%O{ró1LZh­ÜÈ=éÄKKŽòäž¾ªÑàNn<–ÚæÜ|é´ÞÈçBÆ«ÌY¥àÆcæb¹ßÀÍÇ g³Å#+¸ù\­/1WÀ=í¤6Å*7¯iØ ê'²6{­¼”¨n~W†ÒÕ–ì(ä>(äÆs½Ák3r³ñhÅg²öÑî£ín>í"`ªßÀ=펌~º ÛxjÇkcp³>üN™ú÷ñån~9úb« ÂmaÐ.D¹}–yn³ÃÂ>{p›u ß,wae Ö¥(¸êÜì0°/I\ÀM÷4zgë” n>7eÿ|·‚‚›‡ë’ênàÖžVr³¬Ak&ºe©=!wõ ð`ÿÌ7‰»a ÍaèêMäÆò›Ìjh7rWzP d `/q—:iÜ‹Ü4?`´¾B‚Dä^7Ë\’ˆÜÙ<Îì,7™;[pCn‹À^äf–ªn¬¹‹ÜºQ¸Íã%âDYÆ7G :s¯kpó:FÀ ¸q›Qe`*oCˆç6K4v´;·Œ7¶ÒëÛ<»AR/'·Ánó±Êù_îàf°1>e„ø‰•$Ðþ€Ue†B7?¡5,«%æzp3Dy…>”¸™T­E¾µÞÀÍ2Àüè7p[d3¤‰j{‚›¡Ír‹Ÿ˜IcŽ ‘y7SµaHfXPpó´ v‰-]*¸]ÊjØ n.NÈtŒT¹ÀÍW¡ú-Ä~u\cM–ƒ‰!x˯Ŀ–'‘¥OÆ5|Vû#.¥yÅ5¼¿í‰zJ[îû¸¼õaÇO,£÷ºï`w­üòxäƒW§ëOÏG5ø/ÞÃîù¦˜hv{tÏÚí£1 ´Î`£ äœA1 ïÕúæÂ#Ã×’£Âƒ±î{Ú;“dz:ëRówp®Ï[Lƒ4á;Ä4øá o=×íV¡v»Öü|·ÛDÖn—&|[L¤Ù!ßÂq‹iJ‹iÐZ¾-¦á¢r-¡R¢‹ìØŸ5ðF ä)–Ltî• Ûfðúðh4瓹ÿé¦/;Äl)äuÒ•9Â_§¨GC)éÛaÍÜ⯔†µÑ`Q¡RYP,œ…·IŸN¹t9?K”°ùÁ$;¼¾$ àÍ}Ðé×Ir^gñVˆ‹]¨71U­-ɇ 䳆³ö—ìnEäcµ.k†•U;°ý°ó#›éw½’ªæ[àf2ÊV„Jq·"2jWH±¬26À{Yrë–¾‰ÀÑå5˜¡T‰ ÓdIÔ@íõ²€ÞÝøöÃB×:³´¼ÒÜ¥ˆGÐ@iîRD ÈV3ÙÞÝøöâ)PÚ0=¨tQˆÂСÕ)]¢ìòƶõ Ò—B,Ñ eQ.Ì  ‰èÐz¡ú™ª  Ó óX¦ PŸ Û…Y¦ ðô{ÏÖ)ú0•ôm¿ªAb˜Äúu´‰à!AšÂMï 3Àó$é2 Õèc°l*¦LµFÖ(1ÙP£»цÿz©µ$¹+H2@[÷¼l»Ôø^Áþ,[–]Ûºh;r1h O9»RРv¨¿E±”p™}ÍÀõž«ÜFB©mµ²¸K-‚§†ù¹Ö2¬Õ‰àÑyY*éqz…ùÛç•qYbk• Åi§-ŽZÝ­ˆg;Ûúçø ìMó«²Â}eÔ€0›.~:; ý'³yi$Æ>-û€0]ú‘ `]©ÌëûZÜwfÏÄYsY…”ÙCò®+³ TóéPfW0À‹Ã¬BÊlŒÆq´u M™=?VÌYþ„Ù´k•˦̦ݲ-•Êl”…hӨߙÍÄ£Ðá–ƒF˜Í¢h‡Næ Ú…Ô¦™Úø‡‘kuNQh³l`ÿÜh³‚Œµ´Ž+µ‹]ª›JZ£.ÔfÀ„ÁÍ7j¦yèuëæJí£>¡6Û‰½e[š6µ¹ü"ĵYïÔ¶¥Y.šRÛ «í2…)¶ · ïYÏ´ñ;½‰<vƒ6義5sJ+µ$Ryü*µun)¶Y0“%`ló•ÅÎ%ζ5&E±ÍJ¬#¦u¹a[ƒ+•Ûô£q@ó¼q»ðJ‰É<úÛ”®lJÆ·™%Ü:È,ÖÊmÆÇ0AŠ;*¶ùF€†9šnØ>jl³•ÅNü·¶YÖ µ¶Á615£´¶²vÏãi»~TtŸy‘r›‡»IÛÇ?ã‘)à¦ó¼XÔ€ùuÜ|%þh˜Hí75Ð8È%Fyn·¹¿´¼pï±Í¢1éeYyl³,c+Àמ¢6‹Öñ›)ŠíIÎŒ±­äŠíÉKØ@Vd€beÔ…«ØfšÔ6"U;±ÍêÐ-µµù¦èµµ9Œàã%’ µùJÌØ͹©Ô6úÔ0«Ðæ+-¬w‹ÓÚÇ+Ú(›<û¹À¡Ðæ'`ÙïŒE m–¡ý³4í£÷ÚG#Úv{ùIk>@gΞB룅ØGO±õ9%¶˜[ÆYÍWòfÝ5Ø(¶.mK­]¥Àæ+{ÇÂXRª{R52 ãÆk™ŠkíÅ5߈žÝÞaÁµ~¶ÐšßV `µq®ùXÐWLV\³—G¾tZÅõñœàÚÈÇÞó×Ǩ ®Y†1Ür„ášÜñ×…m ¨ Ý™Ü;&ÜmFcCæZÑ6j©¼P~öTÌ¡¦‚6ı„©2WV`´É0HÓaé*hó æåö§Æfƒb¤ðRÚEÐÎ4ìG,Ë\n‚6Ë µ='‚6ç„ó¶R(±™Ç*ô+dS‰MÇsƒ ›WS„ØtéRFÝ2¿[ñBlúÌ¡¨– ­Èfƪ.™M‘MÇ3Ä9ôÌ]Ðæs¹®É"[}ôÊlúܱîÂlýÆl&fÄ7Vº e6?'ý·ùJ˜Íú*ÈÜ–ŽÑx”ú%¯nf³Ñ5su• [£5Ù­¡äfÛ¡?l¡RÉ}´AÈM׸½ÿr3~¢CQ+én!¡¿`dÖ^¤ä>Ë$`€Ië ùnÞD èX‚+ÔQÉ͘ü?qŽt#÷ºù¬\,rKG+¹ùJ`ã3ró?j½'%7Ë ƒ÷X)ä^W‚,ÈyC7½ðxAX¹"ÝtÇ÷K?ì#ŒÄfãÜ À¡ãÜ(Ãt${îäæ½n‹<óFn @Xj”%º~u°$æí¹aúˆå°á_ËEÇÒ'ƒ>«ý _Íõ?ºo{¤žÑÞ¬;~zÜWEåÐ_o€|ðêtýéù`ÿÅ{Øë¯ (yZç䓟 (ÃN+R¤èõ/(Xà½Zß\xdøFrTxpµºïiï)ñ,†¯µÖü¼×ÚFN½ÖÒ„ï,à‡÷» X…ÚíZóóÝnY»]šðmÁ™·—As¤ðX°€TòX°€ÖòH°Þ÷‰?G?,² üéŸ hÔ3¯ëäZæÙŸµ`0y ÄJo¾Ì´<¥´¬-Õwê@;æš0—ڒׇ©cÇ×nײׇ{Šò:’Ûr}_€h—÷©÷;%Ômg,¹^õÌtÇU_×é±HÜNÉ"äÔmeã4eÐsG]ÞÄV¿SD%ÛÙj}ßx8_Z泌Ž.šy…¬·&~'žÔ ¬ÍuÖZ}ç ¬LùŠf%Sk[¿Sù@£®eÚ fö—?A5ƒú¿äöÖÅíÄN‡¦¶nÍûþC>‡Î‚æfÞ”6Äí”𒆥c¯âuÒ¢ñNhÚKNÎÚ§S‚Bý¨„UVßÃe-™ËóleËé$Íë!¾o?´ÏêTÃLYìAœN<¹hõd+ïD,kh|6-¦Gñ9EžÝO;õ^âwâáKèÿëðE§–ùš­LŸ:KÆ´g÷$~'ÎO<µ6uª™×tµ¬«9î°=‰Û‰G0[VjäN5ó5]™Šv¶±ç²„ ÐLá^ž™ž%\€ÇJÛž{‘pzmZÙ¦…^¼6̶ŒEѦk//@XœÛeÛ«Ä Ð S9¬¾êã&SŤíU£€ìâxžx\ðÞ$^€nÙvüoâxÒ.k/@÷˜ýµúºÄ ð–,ÔeÔê]â˜Æ2˶+ƒ*×¾¶9>c9*nØÆsèä:V šbÏ­ˆ¬vÇ6;¥Œë»b›Ï¤[ÀRl£¾Ð0£–ùS±ÍÁÃö¿¡¶ñÏ@|òׇy}ê@7Ãþ˜I ·;ºÑc¯£ž¹Ñ„¹°¢”ÜÌÍäGÿuOT¥üŒ8~zÜ}%tÄè/Ï7ÀðêuýéùøÿÅ»þ—oŠ¿·ßÊÀØgãÀ&Ë`T'öÉ¿ ø÷z}“á‘$ÿ _¯þ‹ê÷ˆ ° Õ•­5?ïʶ±SW¶4á;D¸Ævú=BVÚñZõw¸»Âæ²ö¼´áÛ‚èf ¬Z6×§¢´–ÇÂŽj‰# ‹ XÙÚþ\ÁxGü럞K9À€1EPèm º'}œï(‚öQj¸n¨¥ø(¦*˜—Z0J×(‚Y_ÑñÃ2ë¾¢*S±_iF->Š }ŒÐ™´¸XY×0ç–-HóB Þ“èÃÖy,SFë>Œ€ßú „=ø0ê¦õÊ‚:xMâ;ŒŸðçj 6{‰" ¥wÇ÷|A`nª¸}ù(>Š  ³âÎã:xŽ×‡^ù±ŽO\A¦Ñ6í³ÀØ}AbÖØ5’,ëFà!Î|õ‡}ž™eÅÇP-€f1ÍE1C×@‚JgÏ:þ=cðŽÀ]”>S÷qtvb×ÐÌ| /[Eg­Tӓʺ$pÞôÉ“ìH­s§¶ž%ø@»óv¶b“y–". `Ú±fH@mm5h z¥ì<‡X H€ô6Ã*ëHà‚ &¯qþ‰@‚ÙŠWޙӕ-Ñl] ÞËxòFDG€E\÷yÙÙ‹ÓÇÇ÷5°½k&Èu"jò6DGð¾ébò.Ä·j|<Ö5ŒtÙ‡%æ F€®}9÷&ÖŽSy‚»\†ìI#­#x§ëXÛ,OÌxa{*Ž@¹ÍSƒæ&K£Üæ )%ž9¹Ýû.¶TÍ·"ÜnŒds¤ñܦÉt†—c_¸M/V`~÷açp„ÛŒ1(ãuAˆp{:kÄÉíQIÐ׎ð)·;ï z%¯Pnw¾­ íÎ+ùÊPnÔÆ°ÀwJR…vãx’Rhc»šô>¬È6…vÃF€7n‡ @߉: §;´!é ü?Ûã¬ÐFÚ_· H¡Ý›ö²0oÐæBѼûííiê,9Ú]¡ mfÑâ %i Ìlþ›ÙòV¼îöQfW¨\!;Êlæž`äàšÊìʵݮever»k'ߘ]yhñålRf¯Óe•v7fÛù™×Ja6ŠBy9†”Ù™}>ç±ÍçJªWè­`›e˜m}O0á6(üË'r›eñú ƒÛ,£0´£T<·ÏÇ<·í141ûÛleêËbÛ’4@0‹›7Û–beúˆ'¶­7Ãkwl³ ›|¹–7Ë01ƺºiq›¿ËØ0<·92!¿r° ·ù03öMÂífw<§+QŒpÛnÆÃ c £“Û|'û4¯ÛM„ÛÖ¦SÚæ.Üæ;Q[Z+ÙcÛ’n@WØéóÛ¦ÞÆ|b›e¶¬Ê<µ-Ц¿â…Ú‡Æ,ÔfÙÌÓB^Nj[‡½³8 µmÐó†­Çc›Ïè;<Âc›Ea¹ín¢6yŸ l3…I…ÛÚ%<¶ín÷YÁ¶¥>yÁjÛ׽Š´ù”EM-_«@Û0ÄkË×.¾­j )ˆeß@ò`ü€@›‰µ˜€ßvÜÚfíÈsì¬ðj%¡' ^YÝ# ‘Q±~ÌM¨F^oY˧6‚:¾înP Ãý8ßîܶœTøs‡ô¨¬]Ø;z^n²¶PY›ZR˜Wx‘ŠÛLGCÚ 3Uq›÷bbâÛoܶ¤nåu«ÊÛô½¯=<ßäíÌ ˜–åÿ&ogfÉA;W0†ÊÛVär™Ójõj„þö‘nÁÇoÏGèW_ß¾)¢ÐK´³ð$Íx6¢ S³1Äé/'¢À¯Þ7)Ä ϯ^ù¦jyüËu¯Á“Uªwû¨û{¸·ë-°@ñ=" ü0lj›4Ôµ';©ÉÚùZ÷wèü•lJ;_ñmÁ­Yðg¡kµ>\ µ<\pTóHpAçUt±AÍ_ .(>¸à_ .À"ì–³vô/Íî.Om}B¨nr¡F³ƒ2{wXÖ;бs@‡*²âRý[×$«¡/]6†ìŽ?æ°µ´Ú©Žë6 ‹¥íË34;Ô ±8Çl* ½öÌí"º¸lÄéÏ}PÅHaÅUSÊþ°D£.×Rß·¯B¯@·É» /;k Ókм㰯¤`«°Xò¾µ†x¢4E^]½úÀ}\tã½táµÊc â´ÿ ½MßÈx¶A!fgYž…ž^Çm ô8=ºÒ\./ʼ"ÍÓ}èØíÔBa·~¼5Ñ ©„­8w"ácwú:¢µäŠlF¡W¥+d–b}µÚš¼2]ñ]/e•wÁBê`BÕ´î4n¼qª›é…vö8ä×åËm]±^›û¾j»m°ýJMõšÈ–íZóv¯£ö{*[>óœ®;üP(qƒÊã•îT š5ÛeâF!^{Me¦«ÀØ—u9ʺ¥ó[3¹ðLÑ>‹ÈÂ&¡<´®äÅ(ô±Ì”Y/ %Êx¨éšÉ…—´mGE$ø ñªô¹Óí£ÐkÖ(ÄA6/ûÉn—®‰Ìôÿvùx%„ݸ&ráž=.ó3 ½r]x "Aûm»Ðk×<3-îúê­¯‰lAþ<¹VzœN¿.<RÚXyLºvY´id u[¦økw®‰L:`Ÿð@!“\3™§p^þ¢Ì«ØfÙàÙä5\øÛgÒ¦á̲ÚÇUhçHöD.´PV×!7ÆÙ}€k"Z½ZØGw¼ T—›ø©`„ƒóÅòš;àÒ£EëÔF¼“«¶ˆ<s'=On¼Ï¤g&ÌwRs%=Ã@÷zÝû-¤çåÞ€ÃåËÒ›»æåï?@Ï{Ñ–}úúÁ+2ûu9èzN\lËûž”ôÜx€ò}KÄú‘)ÓòbœO@¯ÙÐwf }åì8@¿BÔ/¯‚ªvÉ£_Îó~RT9WÒÁyŽ@<Uï ‡ÈIpmg zl¡fGŽcÜAÏQ‡²[ÃÆ«€¾1| í¬÷çÏ4w>é9ÏÃ3{x•ñ.þZ⺂è`<æ¥]_Ö™x0þ|Ð3×ÉlF~Âx¦I7r¾CžoÁ‚J×N&§@‚iÇ; îo‰Ó´u¥üyÊØ4Íï )…< ±Ä·ý€<_‹öÇk+È3&ÔÒq¬U%o” ÏPŒ;ä5'ÕyˆVæÆZɈÈóÉÖë¶£”—Œ#ä)°5¼¢nT ä驱‹J¼C¾Ñ仺òyJxvV?|uÄÙWÞ×­œ·µÃ4µ¡Þ9ÏŽÃÜ€8û çyB‹tlwÎCZƒ¸ò’Ö”ó ·m/7íÁùB«Ö°DTwÎ3Ëg™ôóôîF|…»@ßì.ë:.™D8ÏÝ *º£íär庼sž¡1¹ôt9Ì3ÁFÍm¦K÷0Ìó×\sÙ—n+ê©_ÎîöFzBè¼î²PÔ³°½CJõ,,;(í†zòò¯í@¶ÂµÛóºÞѶ××’KÁåh<‹Þ—;â{?ÞÖËÄð4@0·"‹Â|)ß)®<‰‚²h99÷%†)®‹·t9¥C7y(ñ J6„1êèàaׂ›õ!¥÷ÝŽ|ŒÈâQ<+rùÏWfw·#SÕ¡³ Ã[||Ê.A£¥±»Î °l%h ­¯¦X”ºf2•h¦†àX}ùà’xå«Ç,õ&ϤõÜJЈ®ÍVÖÑÏÃZýû„³æ ¼³üÿÍK¶ã8’D罘<ü¸ŒÚEOjRÕû?sJ‚]W*«_dR'gÂã¼4¸gXõ·jK;ƥχZUžQ¿½f|Œ[ÚQmÛÅ÷«Í 4êöºkòB‰6[Ú1ö¹´g•Õ­YFµ-W ü«ÍîÜU p>ífK;FÛ¸®Ç2[· ùöw[Ú1nÕxne_·n%Õ¶D1‰h:çÊŽ±U½²¼ÑdÛQ~m(í¦*—ϵHãÊÇf»Î>Þ›ó¹©öYçáöÅ*4ªmû|„µv‘àÕ_‡¶/Õ¾ZFµ }ýLÓ슺ÎþZd{Î0ÖPâ˜ý—°«ìÁs-Ò8Þ¾<§œï›UhT[Ÿëmï›UhÔ%”v-'©6M_y®EÊþºïV!.!–ÿˆ·W•‰Ù_µvù¹ ¸µç_‰ÝköÇ«¢ÿÄøf/öP3³W­^•JÛ³•b™ÌŽu>µJîQ!³õŸm<•+`Ofwï ‰ÙÅ¿„vÃm&µ[ÚΰÝ6¿ÝävÛý“Û¸wl·ÝË×ÛmÛ*m1o4±ÝäÙûq9¨ˆí¶yw&¶ÛöFë†{OZ«èèxž¨>i}í Ö=0¸ƒÒéj@iáÒ¾]¦e¿œ}‰˜V›#Ü1Ý6<[`Z·-RQ‘§$¦ÓvÀtº¥À´Ú戀˜OÞt 1n0ÍÎä˜N·˜¾žè¬+TMç˾A:ófÎì– 3ûé¬]N}E:k»ùþ“Î줳JFÏé¬}NÅ@:kŸS½Îi;à9oçxNçYÞþüNË]ì#Ÿ -ÛÅë«K@W뫵ÆÚFa(q>ÇáÆÕ-×tnð9®`êNdzšœŽçå´÷ñÌ—7U·sNç›éœŽ¶9Bq^çæ¼V›+açu>•àulðê"Àu4ê×qÉ’¹×”fàZm®ì×ñÐì 踎N¢ [/":®»²{öYq\«ÍžšÓZMÞGœÖjóK0\ÇÑl\à¸m××O txÐ@é$©œÒ°9œã®ÓÎÏ?7&ë)ã? Ó€ÉomÆdµ¹èw&«ÍÆæ`²Ú>(f5 ìÙ 9Ú ×åús8Ýi­p${93¡ É­C‚ɪÞnc@0yôÀdU™?ögE(j抔šY5“l0Í<>Þ]¡™ë–¥rÅמR¹RA*WŠWhe-5¨Ê1¥ÄÚL*«BÆìW”Êéš •c"ÊÄ´+åJ‰ É\!Ï ˜G“£Š9íÒ¹B¨Q:×Wé\ìó’Κ%36x,@é|y2_ÁHçJZA:WÈ0JgÙ'ÆñÖk!6Jçºà“é\ÿ@:ëfY7…t® :¤óhƒ@6í\‰~hgM2}ÍÃQDóÙPD«€…Å#\DÃYp“"z´9@!¢G›ëyˆhmg±ˆèr:c(¢µìÚ¸eçµ\&Etå×"Z·ì“ˆ––4Ñ]WWÖîtÀÿØ!×Ê•&ªÇÓ¡ ]Ù@µÞéø½£ß’:Ÿþˆymw§—  HÊ]†Ÿ¾`NP ¢çR [k¿|ápÁ×MO?ÝîŽð+~zò(Èn»µë¢ÏäQ@ÈÄ…váB›Æ í K+…v9}üI¡]ð‰ƒÐ®ÃPh—3q¡¡M[…v]Þôõèšö()° C,®° t vaè »`O…ËüÎh6-TØénÔdM€2w…öylÙ©ñck¸#,Í æ#9£]É8µÞiMø½£ß‘—y^Ç?íÚn9N?æ² ×…á§/8ä­£5ÁùÂ à‚¯›ž~ºÝšàWüxìõÏZTÍ`|ÛZEï[­ E‹€©”î®?_´&}OÇg·Œü= M·ô ¾˜n†]Ï1{å½$LIrù IòxrH’ã îw&øÃýŠ3AL7GþÂMnŒ›Ž3ø œ »ÖŽë{ Dîr&ðw9p”[œ cxµÿ¦%‘Ç_ÿØ™ ÅÑÝ™ð¯_àëÿÏ™Kö>—òÓܨ—˜o膜b”ªöúªÂ(¯Å>T`Ö< «;y9/LÊW-Ü×â“íl>°8ö”óša«C£ÝGÕºH·LoðQóÚ=ª«:ò¯P›&ßZ°HE‚-ë…웪 /žúµÀQû\{2âàv²^›½z‡fÀÏTf0¨ rñ\‚ îŽHœÌd‚…ކ¤—g'ŽÖçÊ“iFëÑ‘óÂ,Ü£#çµúäè}\T›¬Ž9¯ÝG3ã›KO¦¼Óq>§ÜÎØYÓP÷Ù]Ó%·¹/„6š†ºÏW÷ikN}Í›ßÖ”ú²çÙ4Ô}õVÎim[J}Ù›Ó4Ô}vWÌ©m[J|YÒ¥iÄ;{+.`O‰/‹šG뉯ݺ1ò^~+ çÝÆOHwy@3B³‹"†Òªç»`;’<·|×â#nÍ#²|Â$W} ë£Ö/oŒõQKWÇËã}ÔooC¾ ¡¥…‘ï²ðÖõ…]¾áN ©ws±dRïäH½#zJRò¤^1 ¤î+‚, u_¦vTËÔ`Yz¢úDfœ¨îý3ªG›E·‰êÞ‚ uÇD\’ºó4ê^üÉÕj3˜9ª£(ð+/OTÃͰ1QÝ=zJRwôf’º#IRwÌJ¤>ÑUHjAž¤F€+¡;K¨>]!$TÃ{”X"‰Õ© ¬F'I¬Æ…‘Õ˜À›`ÍÓ$¬»w„Dë´hÝ<ËŸp¤DÂuÃ€ÜÆ<ØnŸëJn|MÜö1DÂ6ê%l7/B‘°‚X Û‡çG¶S°} ?ô·?¿Ñ¦4¶Y(3¹+2$wAÑ’{ÇÇ“ä.0‹ÜZå|Þ’{G…({+žQ¹û¶ùçäV›oWáW€ äV›+bG·Ú¦¹û† ¸ wß8*9`XÀ. ÜÚÊ¿ vœ@îÜÖaWØñ|Ýjƒ7të\Œ¶@·Úüóé莛i߬ó²+`\tóv€Üj2ùêàÖ©;iÜ:šCÖÁ­6·Ú,M p÷ Pwºûwêv·.Á®À¹­£YÊ ÜŽ+˜ÝÜOÈiéØŽ3™ï°½uö`;ž.ŒÛj2Ÿ¸­3)ÀW7/ܹ­Í¬3¨£À'àØV› )pÈåØŽ¶9œÚ†÷nb{µHÂv;š Û!mÄîØN_c`;ÊzÙø¡úÆay;ÄF̲§à®¨ºBÁ]!R(¸kÃP‚»¢Œ#w=<‰JÅ]wÙPq6ÿ¼@qWÌxâN»„â®P7”Ü•!©¹ëáA(H‘”ÜZ8Ú¾<ÜÞBJîŠÒqÉ­¥PM™Arsg”Ü#J…”Ü£ÍGÆÜ¹Í%7/š’»”ã&¹ëN¨£¦D%w:Hî´OHîŠï-%wE±FJîÚˆ|—Üu£xvÉMÿ47jŽPr­>†J* ÆQsWxþ©¹ëîï157‹•PsW8®¨¹ÓyöëÏí=ü±qAÝçQï\aú+yÿ¼²uj¿Óºð»Ç¿#só¼úÕÝq s`!™ðÓ¼çµ>¨™ü—oœ€_ðu×ÓO·›üŠg€_~żPå±Ò¢”ã µÝk^lÚE²:DýO|Ú¼P5-¸ËÐÀO÷ÂdƤÓ-ë"<‰t;3üŠê7ü =\óH¥ãÈ_H¥Ç³C*gp¿Áïø ÃÀGL·‡þÆbÑ“qßq …aü¤µÕz­½ŸwyÒAî21ð0·¸T»A«ë–XÌì] Í] ÿ÷¯ûê+È;ÃKÅ÷´,aÝ T5*ÃöbKIÊ©`#ºîes1̼L×Ðjš¼Îi¯¶Šäè ®Žû±˜‰×®/g¦#©~4š,´×Ûâ&†âïj×j—>!Ò/\ „&†Þ71 V×{qf+t-u‰ñ4ôs‹ÁYý,îbÀܨ®u.=ElƒÈsYÜÆ€™9cHå6Le:—æ6Ÿu*“é3"m¸$ëШ˜}|®íQpÁnÇ©•-gn óS [ÎÜRÑçÖ<7†ª‚ç¾xnŒ×¬•>gh “àN-j9sc‹Gϲxn ³ŸÎR,7† ý©u-gÁÞºxn =á¬Å+.œ–:µ¨¥»n,²4F¿ž[<´qÅSc¼c^¸C‡³Ññ)¯Â,¸ þÙŠ\€s_ªÝ . hâ)q: .`ÞÄ©å,_VEC¦weü˜ .Ìwõ</¸ÀíÆËcR[cÁ;Ïë›ËŠw™¸Í€Á]|‘r›3ŽÈíêï0±][·£˜ôÄÀ-»ƒ…QÜQ«ÇÎÒÁ­énööÜ'JÜ'÷‰˜ Á­5‚ç[NpÑšà>Ý+FnŸdºs»Ã;BnwÔò$·ûö™Û}{Ãu‡M‰¸îp>‘×¹ÍyÝ …¯ -ò…A¯I òš8 ¯Q+%ñS¹¯½úGÂ5É\£ž qݰfSÂ5æ¢×"ߌ&^£BRâ52‰×ð‡’×PþÄõh2i\7,;E\7è“Ö´$Ö 9ÒšÒº!I@Z·ú™Ö Y#$¨Â½ ¶×C~6zm"6j!Øk>%dïÞÿˆìÈ¿bðDv¬ØþJ¦Ù¥à4ì±™½ @v>G¶VŸð}:²u<›dÇiNJÙŠ6ø¹8²£¬}vœÙQvÂ>ÆìhšJ ÌÖ.Í•fëTŒõ`vxgbðV×±}Þr›¸>vx‡ÅÄ¥Ã[m®Þy‡wT ™n,À[ñ Ç¢Ã;ÝÀ»ïý£ØŽã9ÞIûWÉé­wÉ?ŒFo½yùÊC§·¶3b:¼ãLæ x«moÁîÌwìÖøÈÊÙgiÌwx«íƒÖÖ.} äðÖfÐÌF︗öuzÇáæ(ÃáWðÞ±Kë¯ïÀàü&;»/B¾Dà#†‰Þ7ÈîÕ–Êì^ R”6%Ì»Ãj„IøÁfœDËUYpÂã$,éÀ8ɱRлܮ<ÈíŠ ‡”Û2;|Š“È˜`1 Èm™¦c™r[Vùô©·ëxŽëíÊK‡Þ®ðjSo3O½]ÿ¢ðæ>)¼eú0•á]}ØFÝ]ñå}ènfÙ©»+–Y¤îͦvƒìfTw…G›ª»î TwÅG•²»bENÈn-2ª”Ý\H„²{´é…ë[,wBÙ]aö§ì®øˆSvË–`ÈîJõ ÙÍêÔÝ\:º»b‰8ên–÷ ð®pÅQxÓ{DáMÏ…7=ÞºûHBxóò.á]a±û±¡a]êËQ §ôp4\@.sC½×ÒðûgpO.§¾L óo9ÒØUv5ð·/¸ ¯ þ¦µÏ“ðß¾rÛ›·!ÿv»¹Wý< þö+‡6®d|ŠÆpã^ƒCS¹–!™úvl?Y£âOÚª2ãË0DÕþ÷488A&­néHO@ÝO\S%ÊsE‰™Òí<öWòí5ûx_0:øC^5mlÈ„c¹õÖ_#uÞzû·þ%áÖãþ¯Ãq슷—ñÅ)õ.¯C:È]^æ¯CÓB„û6„æzþ7¯Cq§Ã¿os:Œ·±E Å£j2ÄP·zC‡²?†Ò®{»¢ˆ–È>zß1…f4úð‹qm½ÄÊŽcP{Mú2óh,Q@q?à<}euˆué6„?*mŠIŽ+é1½cêÑèƒøŽqÖºœ>Šïð¾Æ…¯÷¨c>ÐhlQIñâ[Ç´ªu]| ßHp<`ëh»Õ˜f-WôÃæ;ååž,d0Ú`z@ßÑØ¢žâ1.)MÙ·iùíqÓ¯|ŒÅæF#l˜F!¸ï1Õ!ÇnW©ŽíÊvø hcfUÜËÚ# á]oݯ\Bãò–(«=ør“¿Ò›£qìïÙ•Õè+”®é4„ Öµ"Ÿ†I £qìöÙ•Õh G¯3?{rød&e×qmžR+>øžSC4}´éÁ={rÂã$UK{mH«íR-||vv©ÃWO–+ȬaÄhDjÍ‹“Œ®8ö:;2Âq£Ñ“kp÷‡Ä·ìÒà±ä£#cH>ǘ|öd,X?‘aã |[‘bƒ‘j4ŽÿÏžŒ‰£±ÅzžÌ›÷œ’e)Ÿ»,™ð6Óð õ %ÔW¤ ê+êÝ$ÔLÜN¨ßÓ1úli¨×7±oG½"Î~¿zóœ¬@½–N²„Q¯€´EÀêOX\êOÞ=¢žå)êOÞ þL/,P¦×¨?Wn ÖŸ(ñXß‘I¬æ·K¬ï'ßu°~~¾o¼w }ßÞ ßW>X'|‡4¾ÃÌ—ß‘ÏL„ktÂw¤Úá;{> Ïb`™ðH»½rTSOÝè¢ÈŒG1ŸÌxxn2ã‘éÎŒç]MŒç‹OÆÔÃIŒ/ã güÞÿñ{Þп^€ñ;E'ÏÌ<+rÌÄ6¯FK ñjÉœñ}'VVº*\\®pU`¢8 ¯FÃðQ¨ðUÀdDÀ«Ñ_J>ªAùëì€W#$â~y+`þ àÃ1³<$¼?^3gNÀç®À‡©Ä‡9NxuGêuwXЄÂk¯` > õúµ%“¾þ 6‹t>Nx”ôʈO«ÕñaØÉY">\>rÖkKåÎzµM#(QŸl&D}˜Iì#ÔçsêãÖúä–!꓉‚¨W£KÖ+Ú‡ßnt]$Ö¯Bxc=K¢‘õaÚ5”õ1›Äô`}ìõiµ&²>­÷ÈÐÍ”n ÝT÷¥ÈM…«3En*¬ )r#‚´ çS#å|%°¡æY- ©ùZWWóompap„E5_ £(Póu'b¡æëÎ` Ô|e¡š§‹ ©yÎãªy!Hb>·¹˜—IÀ¯bžé÷$æ™Ob¾& 5_½QóòrLÇ6Å<×ËHb¾&ñÜ’-ñB1_“І˜çúIÍc‘”$æ¹(Kó\î$©úº2”檞˞$U_½dQõÕnIÓWTßJš¾®ŸA¯F|? éëÊ/4}]yÌmÍôÿøŸÿŽÀ endstream endobj 3 0 obj 35142 endobj 4 0 obj [2 0 R] endobj 5 0 obj << /Resources 6 0 R /Type /Page /MediaBox [0 0 1080 792] /CropBox [0 0 1080 792] /BleedBox [0 0 1080 792] /TrimBox [0 0 1080 792] /Parent 7 0 R /Contents 4 0 R >> endobj 8 0 obj << /Type /Font /Subtype /Type1 /BaseFont /Helvetica /Encoding /WinAnsiEncoding >> endobj 7 0 obj << /Type /Pages /Count 1 /Kids [5 0 R ] >> endobj 9 0 obj << /Type /Catalog /Pages 7 0 R /Lang (x-unknown) >> endobj 6 0 obj << /Font << /F1 8 0 R >> /ProcSet [/PDF /ImageB /ImageC /Text] >> endobj xref 0 10 0000000000 65535 f 0000000015 00000 n 0000000145 00000 n 0000035361 00000 n 0000035382 00000 n 0000035405 00000 n 0000035835 00000 n 0000035704 00000 n 0000035599 00000 n 0000035762 00000 n trailer << /Root 9 0 R /Info 1 0 R /ID [<56BB4CA6AC6EDBC523D4E54DEED618B2> <56BB4CA6AC6EDBC523D4E54DEED618B2>] /Size 10 >> startxref 35916 %%EOF blis-0.9.0/docs/graphs/large/l3_perf_has_nt1.png000066400000000000000000002420061422157504600214460ustar00rootroot00000000000000‰PNG  IHDR¬öEYa )iCCPiccxÚ•‘gP”‡†Ï÷}Û m—¥ÃÒ›T) HYz•^E–ÞY–"bCÄDiŠ AF¥H¬ˆb!((`A³HPb0Ѝ Ü¹3qîüÈóë™wÞ9çÌŠ*’*àû¹Ø³CBÃØð ‘¼Ìt®'ü#Æx ÿJtL&V Ÿ—Î ¹ •#H Ç€•”.@Γ€ÜfÜ_>̨¿|˜ü?@¢Å}ãQßø÷¨pù‚„ؘ\¶Z¬ '’ÃÎôs±g»98°}øi± É1ßü¯Êÿ€ &Wà–¾…Ÿ/`ÿßPcC##øûï|„5ø¿ÿ€oziœEìÀßYT5@÷é'gjÇD ºîñ²øÙe8‡ÏÁá+ñÍøNü ü(~ÿ@ °šs‚+!”HØJ(%%t®† S„E"‘(CÔ%Z½‰‘D±ˆXMK)Hq¥b¤öIµKH-IËIÛIÇHKwHJ–aË8É$É”é–y&‹“Õ‘õ•Í‘=&{Cv^Ž)g%Ç“+–;+÷D•ב÷“ß*B~P~QAQÁE!]¡ZáºÂ¼"KÑN1Q±Bñ²âœCÉF)A©BéŠÒ+¶$›ËNfW±ûÙ ÊòÊ®ÊYÊ ÊCÊË*š****ÏT)ªÕXÕ Õ>Õ5%5/µ|µ6µ'êduŽz¼úõõ% M`½Ý³šÒšnšyšmšZt-[­ ­F­‡ÚmŽv’öQíû:¨Ž©N¼N­Î=]T×L7A÷¨îðü‹5©k׌ëÑô¸zÙzmz“ú,}Oýýný7ja  ¾š&6>5’0r7*0ê5úÓXǘg\küp-}­óÚk{Ö¾5Ñ5‰19fòÈ”aêeº×´Ïô‹™¹߬ÝlÎ\Í<¼Î|œÃäøpJ9·,ðö;,.Z|²4³XžµüÃJÏ*ɪÕjv溘uM리U¬#­¬…6l››ã6B[eÛHÛFÛvªvÑvÍv3\mn"÷4÷½¡=ß¾Ó~ÉÁÒa›ÃUGÌÑűØqÈIÂ)ЩÆé¹³Šsœs›ó‚‹©ËV—«®xW׃®ãn n<··ws÷mîý4ž:ž|Ï^/ÔËÝë×Äzõõ©ë»½ÁÛÍû÷3MŸ ŸŸ} ¾>¾µ¾/ýŒüòýüþ›ý[ý?Ø”< Ô Ì ì  j Z v .†„l ¹*šÚF k[Üà´áð†épÓð¢ð±šs7ÞÞ$»)yӥ͢›#7Ÿ‹ÀGG´F¬DzG6F.F¹EÕE-ðxGx¯£í¢+¢çb¬cÊcfb­cËcgã¬ãÅÍÅÛÆWÆÏ'8$Ô$¼MtM¬O\JòN:™´šœÜ‘BJ‰H¹*‘š”ÚŸ¦˜–›6œ®›^”.̰Ì8œ±À÷à7g"™3{LAº`0K+kOÖd¶MvmöÇœ œs¹â¹©¹ƒ[t¶ìÛ2“çœ÷ÃVÜVÞÖ¾|åü]ù“Û¸Û¶#Û£¶÷íPÝQ¸cz§ËÎS»(»’výR`XP^ð~wðîÞB…Â…S{\ö´‰ñ‹Æ÷Zí­ÿ÷]ÂwCûÖî«Þ÷µ8ºøN‰aIeÉJ)¯ôÎ÷FßW}¿º?vÿP™YÙ±„©ÆÚuÈëPW»¢¸âýá͇oWšTÖ¡É:"¬ò¬ê©V«>P½R_3Zk_ÛQ'_·¯néhôÑ‘cvÇÚëêKê?O8þ¨Á¥¡«Q£±òáDö‰—MAM?p~hi–m.iþr2õ¤ð”ß©þó––VùÖ²6´-«mîtøéû?:þØÓ®×ÞÐÁê(9g²Î¼ú)â§±³gûÎqεŸW?_×Éè,îBº¶t-tÇw {B{†/¸_èëµêíüYÿç“•/Ö^’¼Tv™r¹ðòꕼ+‹WÓ¯Î_‹»6Õ·¹ïéõëû}û‡nxܸuÓùæõîÀ•[Ö·.Þ¶¼}áçN÷]³»]ƒ¦ƒ¿˜þÒ9d6ÔuÏü^Ï}‹û½Ãë†/ØŽ\{àøàæC·‡wG׎=>Š~4û8ùñÛ'ÙO–ŸîœÀO?{Vù\þyã¯Ú¿vÍ„—&'_ø¿x:Å›zý[æo+Ó…/é/+g”fZfg/Î9ÏݵáÕôëô×ËóE¿‹ÿ^÷FëÍù?ìþ\Y˜~Ë»úgé;™w'ß›¼ï[ôY|þ!åÃòRñG™§>q> |þ<³œ³B\©ú¢ý¥÷«Ç׉ՔÕÕÿB,¾;E^ cHRMz&€„ú€èu0ê`:˜pœºQ<bKGDÿÿÿ ½§“ oFFss0ˆÚÿR pHYsNNÆÊ/¥tIMEã$9·-ç vpAg’Zó!%Õ€IDATxÚìý{œ,w]ç¿N8rB&©$B’9\¬¯‰ ›Πˆ"V ‚8_zâw=kÎ*vËüÔÕ¥{9«ëeNãþ~bæ»gò²s֣”žM¢a•. ÙeS€ K‡À)9B §’>¹aùýñéwUuõ½§/Õ5¯çãÑ™®ª®®O÷»>ý~Þ·»»»» „B!„BÆ%“¾B!„B!¤4X !„B!„$¬„B!„B VB!dÊñ}ŽãLú2!„¡Cƒ•B™r\×E&“™ôe}ŽeYð^þò—çt]ßýÝßÝ÷±„ôC'o·Ï²,ø¾]׃óض~ô£0 £oy¥|“I0*Ù7M¥R O?ý4àþà ?é¾ïã—ù—›~Ù+döÏÿüÏñôÓOã²Ë.ƒ®ëMrjYçl25ìEÖu]ï8÷S¶ûƒÖàû>æææ‚ü#Û¶B»ŠÅ"J¥R°oyy¶mûK¥–——ƒs-,,À²¬¦ý¾ïÃ÷},//#“ÉÀuÝ`±XìûXBz¥“ŒwÛ—·èó~å•òMÆÍ(e?ŸÏ·\å÷}™L¾ï7,l²Wºé+qârÊ9›L {•õn¯§l÷É.™8åry7úU\¸pa×4ÍÝsçÎíž;wnÀî¹sç‚ýº®ï𦹻»»ìßÙÙ öollìjš<°»±±<7 c7—ËÏ …Bp¾~Ž%¤W:Éx?ò¿³³³ `÷Â… »»»ýË+囌›QÊ~¡PhzŸ .4É5!â“Ìîîî¹[.—ƒýq9åœM¦…½Êz·×S¶ûƒÖ !_ù|>é-—ËÐu¶mÃ4͆°°l6üï8Nvà8NÃsY¥‰¾hšMÓº^O/ÇÒ d¼Û>Ã0‚ˆÛ¶‘Ëåd²_y¥|“q2JÙ7M³éýd…>ú;AȰè$³íˆË)çl2 ìUÖ{y=e»wh°&]×Q.—ËËË8pàòù<’Ð ;(•J VŠ !“¢“ŒwÚ¨š¨ÒNÙ&Óĸeß0  …†ó2,ºÉ,!ia¯²Î{e¸Ð`MRHicc.\ÀÎÎlÛ†eYÐ4­£ÑjF°j#­­- æ.‘ÄÐIÆ;í”Òîº.J¥|ß§çˆLã–ý  `þ:Ýd–´°WYç½2\h°&)¤$†©®ëAX€(,’´íû~ƒ°›¦Ù´M¿ I d¼Ó>yžÍfQ*•Ëå&=Búb²¯iÖÖÖP*•Øv •n2 t #dØ«¬÷òzÒ;4X€ä%ÍÍÍ!“É`nn.PTt]ÇÆÆ2™ 2™ ÂÂD1)‹XXX*ommMzX„t’ñNûY˜¡w•L“’ýl6‹l6ËÅK2TºÉ¬¦i(‹ô"‘©g¯²ÞËüNzçÀîîîî¤/‚(Ä‹ªiZÎ+Å“t]‡çyÐu=%‹¥Ñ"K&LHÒh%ã½ì³, ¥R çΛôÊ>Iíd6ª³t*NCÈ´°WYï4¿“Þ¡Ášp<ÏÃÜÜvvv`<ÏC&“A¡P`x$I=J³°°€\.äæ’v(û„Bˆ‚!Á '|àÀ,,,¡d„¤×uqõÕWC×uÊ<ÙWPö !„=¬„B!„B =¬„B!„BÉÁQž|{{‹‹‹MÛ+• fff0;;ÛòuÝö·âCú~ÿ÷ÏþóGü‘%ƒ'žxO<ñÇ»‡óÍÌÌ`}}}às´“o`42~ìØ1:th(ãŸxà¼ð…/œôeLíxxàüÙŸýÙÀ¯·|sO7£˜Ã_ô¢áWõWz=çïÑÂù{ïç{ßûÞ‡ùùùÏA|tpþÞûùúž¿wGÄùóçwo¾ùæ¦m?ò#?²{óÍ7ïÞ|óÍ»ïyÏ{úÚ߉}ìc»·ÝvÛ¨†“88ÞÉž¯•|ËöQÉø»Þõ®¡àx'w¾IÈ7ç´t“¤9œó÷èáx'{>êࣅãÿù†\­Vá8NËŠ†'NœÀìì,\×ÅÝwßJ¥Òàáê¶Ÿ„>|GŽ™ôeì»ñv’o€2>L¢ý†÷I/å{|$eNÛOã¥|$Ìgûq¼ÔÁÇCæ³ý6Þ¡¬ÛÛÛ8sæLÓöjµŠíím;v 033ƒ¥¥%”Ëåžö“FfggÛ†3¥‘¤Œ·|”ña³´´4éKØwã¥|¤Ìiûi¼”ïñ‘„ùl?Ž—:øxHÂ|¶ßÆ;tƒuii 'OžÄêêjÃöóçÏ@C<þüü<ªÕjOû Iíä Œ“é‡òMÒ å›¤êà$­Œ­Jp'¡¯Õj]÷wãk_û\×eøéÊöö6n¿ývÜwß}C=ï¨eüá‡Æúú:¶··Ç÷a‘©d}}<ðÀPÏÉ9œ$…3gÎàöÛoǃ>8´srþ&IAæïa‹œ¿IR¼ßù{lk'¿xñb×ýÝ8t访þú‰ÇX“äsøðaÜxã¸æšk†zÞQËøå—_Ž#GŽàðáÃãû°ÈTräÈÌÌÌ õœœÃIR˜ŸŸÇ7Þˆ+®¸bhçäüM’‚ÌßÓ$ßœ¿I¯ˆÞ¯|´­M”N¥¹ggg»îïÆ¡C‡pà 7L<Æš$ŸÙÙYÜxã=­öèeüòË/§|“žX\\Ä•W^9Ôsr'Ia~~µZm¨s8ço’dþæ¢#ço’ÕÁÇæa•UÅhØAµZ n„nû I:”q’f(ß$ÍP¾Iš¡|“igl«T˜ŠV/s™L¦§ý„$Ê8I3”o’f(ß$ÍP¾É´3¶`X]]ÅÊÊ ¶··Q«Õ033ƒ[o½µçý„ ‚ë†1ž÷¢Œ“4Cù&i†òMÒ å›L3#3XáºnöùùyÜqǨT*Á1ýìO+¾¯Œ*]WV,/«ã4M£iÊ‹öªv]Àq€\Ní·,µ¿Ý9“€ã„c‘ÏAÆä8ê¯<—ñù>àyj\¦Ùø™8Žz˜¦zضúlÛ†a0"Ú°çyð<fkÔó<ض ×u‘Ë厗s†­®!9Ž×u¡ë:4Mƒišp]~]C×uzýƒs]®ëÇi],¯þ+«Ç>øóçÏOúc& )R<,þõË}¨ëa~äaah—,š¶R°EAÃWî_QÚº¥­Dó™äöYXP狆»e³áïb«²^ù¸A,¯ÙÞþ:"-#É„‰×݈Öꢇår(«[[íâÆ^«È—¸7¨ƒP¼™Q¸à¸‰ÊœÔŠ…Aöï‡Å÷iëø~(àR ɶÃð)ØÒ€@àןG÷ù<Ùú£éÍ#ÇÅ‹êrõ×gꯗ‰Ü`×_gÖ÷ °2ïy4MëªD[–…R©MÓ°¶¶(ôžçÁ²¬@A7 #Pü=Ï ¶ëºÞPáN”QæEùƒ#®ØË1žçÁu]†B¡MÓà8ÞûÞ÷⦛n¶h¤×U«á²2¾>úÅc=†7ÿÔ›»kY<Ï ¾»èvÈf³Ð4 žç¡T*Á¶íŠcš&lÛ†ã8Èf³ †dTþòù|`\Ê~@ºbІl6¼¯išpŽãÀ4M”J¥9•sù¾ÜQ#U OÃ0‚í–eÁ÷ý@Îå:åx¹f¹¦l6|W^yå¤Å†´@ xIQ 3Œæ@Å+[G¸á'…8€Æ*Ñb¸ ñvŠbFo1*ÚMïâme|FCÞz)üA¦Y䯩‹²p"ôš&1 œ$x^XcemM=ÏdTØ-0’ Ö>Å=— WŽ£ÉÌðë·€òoC‡”ahB˜%(£²~,¬úÿPÇ}þÅŸÇþîx³ófYC½&|ñ_Äf>€·Ì¿7ýíMxúé§q÷§îÆß÷ǸþúëqË-·àfãf€ã9p²LÍ„ °€§þÛS¸sþN<|èa¼ê^…WüÒ+ðÔõOá ïü®}ãµÐ=0”ßÁC¿ò¾çûñ…—|Ÿ}ëgñèÕâ3§>ƒ#µ#8uÝ)Ê£óÜŸ‹~ù£ÐuÏ|î\úm—Â÷}½î(>sýgpÉý—àöŸ¸™—fð¼gž‡WÝÿ*¼åµoÁ]¸ ®ë¢T*Á0 ¼÷Ú÷âÅÞ‹ñé|‡#SÓ4ø¾(èbx†(îrž¥¯-á±kß<ú'rÿÖ—¿?ýòŸÆ|ô°°°Ã0àû>~ôG»»»“§©Àq”Ì‹²ÜJ®5(Y—°?(‹0-¯xò¸çïÁ÷~è{ (•J°, š¦ß»†a`aaÙlº®£T*![׌2™L`° lÔ>¢ÞKÁu]8ŽÃ0‚ãÂ1:M^UÏóc±Ùl–eÁ¶md³Ù¦sç;pãZÓ4d³Ù¦ëu'ø Ëå2þÓúOC¿Ò?) |<41šûÔùiE¼WÀz)/æQ*…ØÐ³Û-$ŽÆêt/”É4z¥da%*c㪻AȠ躚Ϣ‹uŒ„œh°öe…¹zqA&òÒó€~À:JiGýÿ¨Ò{^,a[6ÖÖÖP´Š0Š~ò–ŸÄÖÂ6>°l6‹_9ý+ç1›Íâ·þûo©°ÄbÆ9#P¼ ÀíÚÈÏåOŽñR她ǽ·¿úv€{ÆÎÏ{æy€ |ñƒ_Ä«Þð*˜«&®Ï^GöQÜò»·.}õ¥¸ü{.ÇjaPý*®}ìZ7ýíM€ ¼Ö|m8pÊß¾Ãÿ|‡ùÊè/pÖˆžå¬|æÊ–Íf•äªÏºd”Âs:êÞ³ó¼G¾påðÒµ—bû«Û8Ë2Ám‘R8bg§Ç•p@@xtùQ¬×0ûÐ,þÅ=ÿ¿sõïàÑ…Gaœ3 AÃg^ÿ|å…_ÁG¾å#ЮÑð‰?ù®üçWâ3w~üö#(ì„^Uñdº®‹r¹Üà=/c”VFf§0ßVûô>–þs¹r#Œ2M³k˜r/ÇÑ#ÓhŽiT4â_Q/‹@“È™Cza!ô¼z‹çí¤‡»ÈæÖ!Z!‹éÑô ÷ÅNYpÂh!yýg?ûÙI/HHIeÚ5eöB¯Q•í^ë8NàlÊFVµî½÷^<òÈ#}k‹jÕ1šÑ íQ ð—½¦m°m–eÁ©W Ð4 ¹\;;;¥X,âæï¿¹\ç:,™¦‰8Žƒµµµ®‚ÕR;ÿ›óÀo¶Þ7ûç³6 ¼´>”1.è€Cm{[d{©~\Êp¾Æ©o_ƒ2Pu;PFé2Âpf½þ¾q[ÁPFcس¼ÔziÏc߯H¸—(ÙMv›õý >g©š(!çeÀõ],›ËÈår˜7çqÿÑû±à/4LXoüäñ_û^üµã;Ÿý@}îºé¦›€Öß'ˆbP¡åê¡d£ßdXJä‚,n´w‰vˆ‡ÞK%ÃÔH¤õ@«iTZH ³iGŠÌHØq;//™n|_é8Òß9þ='ÍXõ}?H-Êvqí:±Ê^’"Æ¢(Òº®é"ñèAÒ ÃhH)ÖRJz†(øbÐÊùâ†m4-D¢…äØK/½tÒóÔ"•Äeá%^wc? u:€ÆÅ×uaÛvͦ>//[¹|ßG±X îIm’ÈÆV úÑ{-šögÊ™V,‘ÍfaÛ6¾õ[¿7ß|s_c¢ÁÚÝŒUÈýš”] ç“ü7É7+ (wˆÓZ[[ •ôH„w¥ŸIAƒ2âÆ*ÐlhÈo’ e¸:hmˆtºaNïW'ýA%é™j]S#ò ¨¾¿Š/|ó x¦ð \Û…eYØÚÚêºÂüÃïýáæ²!¸Pß·„ØëPß½è”w߀ú~µÈ~ñøŠ¬˜‘ÿ£2f!4¼}„ùàQ¯}¡þZ«þÏ$:7˜h-Ÿ^} ^l»†pa¦$‡]Gc>¼†æ{‰ èÂ% þ·,eÔ™fz½­ÂŽ÷‚„·‹òßx…ïû8vì¾ó;¿sÒÍÔã8j¡¥—þð£DŒP‘1þ¢‹úRó"Zƒ@”`9‡x7}ßêˆìH~¿®ë0M¹\.H¥ˆ§µº>Çq`ÛvÊ$9w/^ÕND è­°‘vßø~Xy:›nCUæÈ\.×Ò %¶„ܲø¢>?¸G`aa!¸ŸdÑ%úZ1Z,¯4ÍJŽÏf³ɸÔ×ô­ûï(G¬=Ò«Ýh{6\;,$+pÑ¢@í Âì;rhöŒFé´8Û<-H1 â5² Œ3¡1æ~Á‡å(¥B÷ô@Ó´ _5úC¾gäv2¡ŒÅøiµúv3ò”âfƒ†»û¾|>\‡®ëA¹¦i …Éd…?ZdL¼²âŸËå‚¢hËË˸á†&ýO5²Ó*ÍiTX–““T ‰8“ÂubxŠœˆ‡¦U ñb q/f7z•mñ>µóèC§£^¸7¤²ú4åS‹ŽÁæ]Ã0Édš ‘ÊžÔj‘AÓ´†{dmm­¡KA÷ÏÑÎ#躾紧½Ú>4X»P*…y|Ýxô'Ei§xEÇiÊ·#$iHoÄ On¡q„ÆTAG’•d™766F+ãÝæÈ¨:ÈþV´òê]Žo…Ž0tZž¯uy½Ÿ>ÂmòìE¶Åß'z^xç‡ßÙç I+l[Ý#ÑB{¸ U)>×Kd¾¾ %Ñ<îQ©ê.‹«RÉZ” L&(+Ѽ;!Z­zcc#8‡¼N?ºÞÔÅb1˜ƒ£¹¥¬G3yh°¶A ´CŠZd³YüÆ{¯ü·¯œô%Ò;. rt`1T¥H'k’V\Wy †Z&ù¢™L&¨**¿kkkÈçóAxˆ¯mÛM7ZUl$¤W¢íÊzÅó¼`1>š—ÚK«2BFI½€nϵezEjèºÔ鈶¡$“‡k 'ìãÔŽR©¤ª!¦jAy&S„eÚa ÛF–~\‰_U” 9š¦¬MKn’HÄXFzv±Xlmm•v3™ Êår è—Ëå–ù§íòGSc¨zhÝÒI¶G1#û¢Ó EÕ |!>§nÒ£J4MíÊÚÉd ¨ü¨P_楒$á8Ê™´³³·óHIéu*óp6›mˆ` ÊdAƒµÅbgååžÛïÁ-÷ßÓ2ÕgÝ[oôƒ´  âMF€ëÖ@ù×Û#–5YKÌf|[©>Ã5› µ´¸¶æyê—O \@ÝkÑV¹\çš¾ßx¼œƒÊÝTaYê1hÞªmÛ -^¤•ær¶ÊçhÅÞBhع9ab9Fž{õmÒ×7~)Ný!­’äyp¡‘÷2êÇ¹Š±óeÚ\³ÕÇP…Ý „Æh ÊšXy^¬¿·(¨‚OOœ}øÇþ?Æý‚«Ýb$?šõH’‰ö ägVz:KÓl6›<‡t„kŒR©CøL]Aø½ÿô{øÅ×ý"ð“û+vÃu›Oêy*QVšH¹®ú_×Ãmñ¼%Ï c"À¶ÕtÔ¬>xA~µ´Š.²’Tt}ð¹ZRør¹Ó›¦¬DÏmnàNÁÁ—/û2^ú;/íý„¶ÝÚ ƒS<3ݼ:€:.ª°öª¼nm)…×q”âmšw~+Å?“Q×íʽöl¶Ùøt5f1lãcnµàºêšŸ<FV’zù¡Ñ4U‘¡]U†V²Þ ]W2Øïëâ^ Ûï@Éjü²¬0/!î=Ö4eÇ“-Å–{Æ÷ñö|8Ÿ}J±mõõô«ù¾ßú+´¬”*žÍ8b¤:õcÌú#*.>”S¼&Ž£B<Ò'*®kPFñBý¸54ÏzäýúõAÖPzJ¢nÙ¾¯~[Má¥R º®£T*¡T*y© û%IgМU)xÇüëé‡kŒµµˆ#ÎK € x†‡R¾„B·òdRbض•uÐnYhÅ9n°öóºhSAÛn¼¦V†@7£Åóš·éº2ú™ #|/Qèãcm÷ùÅ‘fsÅ¢ºŽø,W,®‹o}ì1ÜäHÿŸã”"yz~íµ>NŠÃ$jR"ÆÑl­ÃðlöÒØ3—ëÿ×YäÀnÖ³ð†É|RSA?ÓT´Ê¯®ë0 £9ÔWÂ[ÅcY„ú ‘it®¾}§þ·[ É(:…dGt^’ŠÅÖ뻞çÁqœ  Œã8ìIO>¯äyP1•êë”óé'•«8±]²„ ½6îSÞÔì0ªG‰ä^G©¯oµ°%™U§¥ŸjâÒ›ö‚‹ÆBuÔ=#©'&ÂB{ÂZËhŸšbDίVEþ¤žÛ.EÿìÈ9¤&Bô·ÖÁ`)$V* T«Õ Ú¡ã8( ˜lnnâøñãXZZçW30¢ßZÓëjm• ‰8lpPxêx˲ò”:âûÃoEÈð°cÕ‚š0t9¦¨Z4íÅ(Œ†qÇ—C%t!n!d³­ÃÊ•?-áå4VÉ‘Úv]ñoÙÃêÿZÅìÛfÕý"?Ô€ú]ÉCÊ‚Æ*™Ø*‹Å"|߇¦ip§eµêÄ!…Æ P:› ¥‹ùP•¨7"ÇÉ~ù߀úm+"ŒnжB’c€@¿ B÷¥¨™xƒ$Bb­~l©¾-ª ºh¬Êý™¥=º> í›Zy£,pAcY™£ûM¯¶m¥R ¦iŽ¿-“%R8ÞG(³"+qfÔ“)ˆìŠ­ÈnÔ—ú"OñBzÑZz¸ö¸šÕÊ”‰·˵xM7ȆºçþsÿïÁB¡€ùùy”"Å=6771??“'Obff›››X__ŸƒPzn&äÊP_ì (†®ÇVq|º2ÜûêÃ$…Y™>Ù”ãº-O‘#CdŸ(ü¢0ÛLñ4EC]„÷n¶~¼\ÃV}»„Mê‘kCýµ ‘k3 ®JõsJ•né9¬E®[ޕ׹hl µÏƒóJ¥°n 8žúÉP’‚x{ê/25$£í+Ń-xmë%ÕÜãooĶɢF½FNò›7£ÑvÄ ñ “a”6}t»ÿ—¬V«8}ú4fffµZ •JǶ---a}}½)l8Ɉ°Û.]ƒšдB u‘aê«¥R–I E4s1Œ6á4Y÷€$èI(‰Ãb1’`,+Ñåå5ð¢Þøèg?Šý¥E6›Eá¿:¯ÐSô{É4ww´q«jÙRÕ^Ž‹¶TÓ4Ì<÷¹À«^5é‘%‚¸nnÛ6²ÙìhTQ죈’/J³‡Ð ºVß¿ŒPAw î!ÝÃM´6è²m¶µûY‹/Vµ3²mþ7ìÆŽÇHÔЈõÌö ^‹/ã¯Doøäþ*™'uçΩÿE7ïÑg6VÅÃ/ß…ü'˜ÑŸ…^Ö×ã26Iãàââb`˜­{0F÷O…·ùŸŽ½Äwëa›FÓlqS¸ÀùBÓç@Hb‘~Œïj[;2pŽªª‘}5Œï§(! @Ú×4é0Òç"ôª¸~¸ãwষÝ4éKOa! “U5>³ÙæH£¨Á*Õß õ¿¢qä¸6íÞØÞöIá¼v8N(ßQ¢ÞÕðšbüyPÞAÊè’>½QD™¶bŠ^†æâcb´Nc¤BtáEÚFÉçÕ6éÓ-è: k€‰Ê“Ïì¶_>ô¼ü‰'¼}Ò#¾zS¥Ëc¯WQ}X™–Ûv‹"QZyDÉX8X«Õ6T*ÌÏÏO­‘E¯Úå½®ØõÕ›ÆùÅ÷}X–×uáºîÞ&|BƉ…påÊ“—o¡"’SùÙŒ iFtÄÀÞñz7¤HEdš·`Á{·‡µ·Mñò·(Ññ¼òøâ«$‰Å•i‰Ése EW¾t]Up“‰E¼¥ÑŠ…­òÒ;Å`·[YcäFW,«Y±÷<¾ï÷ïe’¾À’‡Í¢¹š&†£¸OJùwbֶȽçEú¿EŽÍçC¿®‡¯—ûJöE‰.îêºzDûË·úŽÞÿ€÷¿¹²‚“úh&Á^3êÄ»Ú5gUr”¥®„q“Äs°R©Fj­Vƒã8M¹ªÛÛ*ØøðáÓ¾Þþ([Q}Üà†Mµãr-y¼…B¡¿žMÒ;”.™:‚¼Ñ[ÎÛõªnŽãÀ¶í '!iÄó"9PT8bm[Ì”J¥ÉW•´mõ#%7p6z1]Wm+Ô–¥^'Fèñ‘¾àqƒÕuU˜‘¥©°C„èÄÒêw2I=œSL´|@˲ú¯,¡»ñ|Ï(íZ[LÇ Á8r¯Ä÷eê ‡­ LÓl-Ó¦¶E‰èD«½v×»‰:©¡«wU gI…Z¹=$„L±²²‚¥¥%loo£V«a°µZ gϞʼn'°¸¸T žFÄËZrÂßÿ8Žã \.CËk9Ýð(B&…¬Lõ4Ö6³ÿå,¶··q§{'#Hêi˜–u¨Õô6J‘eY0Msðü§~ñXi Ïó°¼¼ Ó4[Û(Rˆ’d©à ©­XZZÂÒÒÒtzV4žjþ+_†–“´ã8a¥~lóV¡V„Œ É9ªã~°N- VÛ¶q˵·àú×\ßÿûØ6g’hGE¸F Vóß8‚®Õ|¥ØàÀÞUÉùlN( •ðh(`«-„ôˆŒÔ4ƾ±±×uá8r­}(j4_/IŽBÏS^…ø}aùÑ$• ¢Zxž‡L&ƒµµµÆxi9«O@¦ŸƒvN¥¡*Hå¹:f´Œº‹¦ÉÚq%ôú›ÈL&‰†úÖ]€ÙÆyêº.þÍ×ÿMÿyH²ÒM¥$˜R)Œ®Õu ¼†®s¹ïû(•J°m[[}äD ‰AÚÊEÀ°[2¤mŸã80 #x4«ÒvFòS£­SÆM´—ã( %^¨Ÿê®$5´ ml0V¥÷.¤’ƒ€*ªt¶^þÈ‘#SÓkµ#Z mïiÐÞÃBcYön0˜L’X‰uÇ6Z„¿ø¾k?u-.}õ¥ý¿Ç ¿(„Œ Ë » d\hÿY¡Ïf³ØÙÙé^]RŠE«ƒJÕ\Q!cDtô޽âEy×ÐXÝw\HÏ)Œdõ•¤2£ H@©Ô¿zÑÐ’/Òù K5×××±¹¹lØÜÜıcǰºÚgŽ[ÒháEm‡çya(˜Þ'v†“Iéaˆ£40È¿mÛxÉë_üÄïaÛÍUI I¾¯”ž¦Z*]æië”ëU[’B.½T%dÜ}÷§ð—ùJ¬­…aìm{ÅO²ìÈÂB˜˜È}Ò†A·‚–|6Tž* ÕdíKÜn[›¾Ú½ppssKKKAë‰'°¹¹‰[o½uz{±F+áÅq¡V#ú·mÛá¤ï¢?ï* V2IêýW]¨N[[Pò ‰wGMðýþ8têGHBK "êu뺽«çz2qÞüæ{pèЇ¡ëWÁ¶íÖÞÕiaóéÕO+ýGŠˆ‘ÑíOìyEãm}?Œ@ò¼ðG9Z¿a‹½àرcÁ†ÕÕUœ9s•JezCƒ=´WÌ 4)3®ëª‰ßG }.Ǽ>2Yê2›_PÆj Ž‘–Œ¾ïãûËßcm ¥L†“Dãy-ÒG;ý¯óÆ×† ç:xûÛƉ?˲ ëz³wÕ«?†m¬Jh¯ã„¡½R ‰:Çé?x«T*á7^ö8tú2Vì²7ÄßǶöé–yFîùv« ºÞ¾§â84WšZ¯j}MØ®ëÂ0 å•êGáDM&M}‘»aAÛ·À§îDÙÁV!m›«å$Ñ òûØPž“Ï«pwËrð}ß§C×õömu(%~˜ÌÍ)•á½dˆÔ;Iö¼åº.ªwVñö§Þ|4V{ÅuÇä”GiU‰Û0WŸáàÞO1…hÀ÷<€?úØÁ¶í°Ê˜ †©Âÿg€ïµ˜St>à¸ÖO¯Ã8eàj\Ýÿ0_L#]¥ºjoçrCš–ÖöêÂ.mü†=]ŸcK2|úɨ³, ¥R †aàgßô³¸äG.¡±Ú ×UúZü·JÂøûYtJàïÝþ4X àÝ?ðn¼úß¿[[[*,̪ïcò6™<À½8V³—écÏ| ó×Σ¶PC¡PÀMo»i°÷`80I0ù¼ú nR|L4(4Åb±Á+ÕWþj±Ø¢¢!£Ç¶Cý²k{MmÎI*†Ñ[¢çy°, ŸüÝObæûR: ¢m¢¢Et½uQ£”èq`ee¥iÇúú:N:Õ°íäÉ““¾Þ¡ðÅg}ÇÃ~0ÜØÏ÷ÉB4$ x€÷-­Åð.ýl}m KÚÒ¤¯’‘áymVé#Û\×…eYÐ4-(RÓsþªÌõŒ2 c&ªƒ6…°G[yÈsÀ^#v‹Å=Uñ$¤Wz±R©„ßœÿMÌüÛU,u¿ˆ¦m‡ùâQ2õWöéú¾ Õ?-¸$ÌÏÏOúº†G>¯¾ÐH5½/>닸ꪫ’ØýV+•Â8B&…ä~-óµ}ßïÞW’)§­ã3R)^ª©Z–…\.×u{Ï_•Ä„ŒË E¯)„=ƒÆEv­ûÎ÷ŠïËËJ§áï!ž§D­—v¼A¿Õµ à6¤? Xz}KùäV¿Sû8ÚçàÔ÷[í†ç5ÅK~è?ãßÔ'ÿAJb;ξYÑ FGKÙí+?4’GP|ƶmœ;w¾ï£T¯zØóýÁÄdBø~É×Âõ4¹Pë *‰ï+¯M.—šÐA’\,«÷Ò¥RIEŤuÍPÚÀÈÃ4•çtg‡ G-hÈaÝÞÞÆÙ³gƒçGŽ™ÞÖ6‚ç5}ñžç©BKƒèô®Ë~|$¸@æç€òG7Å`ÍdÔ¢ £HB™›ëP¦>åG{l d2ø¾r/«ÔŽÓº€!CB›kkÍù|Ñuß÷¡kºŠ[Ch¬úP‹3Àà¡’Å¢Òih¬’"öX¯UÝ}ßGÖΦ»šû‚ £`îž8(÷¶ÛnCµZmع¹¹‰ÙÙY”J¥é nÿýܧž\¡¤Ó1!£ x_¬ÿïºâÑWA™VHch*ê$¡H±¥¶Ô•ýhiÈårAËžÞ„ÞU2B¤¨§¤«yžšÆ76Âuö í^Í‹ìT$ßßûX–šï©,“!!À-‹ãu஼ ¯¾òÕÓí]G2Œæ-Vàî‹K¶··Q(pøða”J%¸®Œ£Gb{{{Ò×Ú?®Û¼Í4qS¥2ø9i°’¤`Ú5PеhðŽÓ{A™v8óöHbÉ×=JÝVê}߇ëºaÛ2¹\½(çÅbëÞt„ ×U"&²,y«Ñ 0Çqðæ'Þ¬ŒÒV] 4 æ]u]UƒÆ*!Å¢ .ôØÃ²,ü«oÿWø¾Ï®ýëk'}ùýã8ÊBŸ›S?VÒvÞ9xâÄ ˜¦äöD1M¦i¢P(àĉ¸óÎ;'}½ýáûM ǯ~5~èßì|b¬2¶œ$¿hå JÎwvgÿéŸ`~êS{;q? Ò#¥’Z°îÑ먇­Û-ÃÉzŠ®1 Þdäø~£˜Åa|ßÇ_~à/ñ3_ýàùÍÅX¥>CFˆ´ÿì…b±ˆ«½§ž:…Kþüà['}õ}P*©'ÃPáõüý:—T«U¼ûÝïîxбcÇP­VQÙ‹grH¼M„Ï=ó :¶+èVŒ$ Âuýà—BwÏ|ñ‹{Ï_¥‡•$¹95mwÒõ‡z–e5xWû"îæ"d¸nûÌ ß÷‘Édð»Ïú]”üU*ù$AÌÍÕÿq,@õXmC©TÂW¾òü»ßùwé®.IRA»<ìR©„l6‹Wž|åàíjI]§áW9“®{Ëuý…“‚m7æ¥ök?¡p°V«¡Z­vô²JÁ¥™™™I_o´PÜ=ÏÃk66€ßú­I_!ƒã¹%¹#á¦HEÔ±¬}ݘš$@¤ë«ððÐ6<Òqü”þS¸üy—÷ÿFÒáðd øõʾ­œ2•»*8uç©éÊá#$†aô°þmÈNqú˰ʾ®F \ÌŸ0—ÌÏÏ£P(´ ÷­ÕjX__ÇâââØ[ÛT*•¦V;{Å“ÜUÃPIȄس|Ç”ö ÿjà’€­-¶³!CcsxPÄÔA×ÐHÏópù?^ ¢÷”J­C½iÁ^eÛq”ÈÅñ}kÞ®ºêªá_´ôÍ!¤F¡ƒ7Q_Ê‚û°pœ°ZÔÎŽú¢±:q?~+++8zô(Ž;†ÅÅEÌÎ΢Z­b{{›››¸xñ"Ž?>´7]__ÇææföÅÅEœ}µZ GÅúú:VWW{ßo2HƒÜ@w/Òò²z='wÒ'c‘oÞ×"ÿ×#4MS²ÍâId„ŒKƃ5C¡×ÔEË ’A„Á 9¥+ã“ív:ñÿ<ÿ?aüøænßW¿ 컺Òiñ0’:1ïªç©¹ß4™ 2Tà“'O­k*• æçç1??ÙÙYÔj5loocqqq(ozñâE,..¶<ŸxvOŸ> @ÝDKKK8sæL7‹x™"ÞQ×u{_Áq]U–’>‹|8—+® lÛ[x˜&ÃÝÉH—Œ;N݆tzW—´˜š=ÏCn•qÏS¹Ûô®ŒO¶[â¨üÕBaeeQ†ì{Ʀ£tR¡KêSnƒ3i\¸®rL ¼/¦„K¢Ofggaš&VWWašfPˆ©R©`eeeho*EœÖ××±¾¾<ÔÊ€îüü|ÿqô-°_ûÚ×àº.Ö××Õ†HH°ïûp¶m÷f°Ú6û­¦˜íímÜ~ûí¸ï¾ûFöÖoxøá‡ƒ×¬O4-ò³ûUvŠÅ°d%IëëëxàFú#ŸÃ )‹–0 <®‚ú~ŸTR÷ WاŠ3gÎàöÛoǃ>8’ózþöýYIpÿKïÇü[F”»Ê÷©AæïQ<õümYÖÁ cÏ_-ÃztLMÑÁû¿ŽûB«Õ*Ž;†[o½5ˆ™ŸÅúú:–––:Þ/^lÛZçСC¸þúëqäH½Í‡ç†R©Û¶aš& …BãM!Iäñð×åªKŠ9|ø0n¼ñFüÃ?üÃÐÏ=*ù€Ë/¿GŽÁáÇQùøãðž÷ϨÕÉl\á/k·…ÇQÆ*å=U9rûØÇFrî±ÍáP¢iÆu Ž3 C³½¹f(ðÔ2??‹/]¡×üÝ2ˆËîš½k4¡‘ŽÃveS„ÌßW\qÅÐÏ=®ùÛó:¨‚Z¥Ri<ÞUßW^U]ç½0aDïwþ»‡uvv««« B/7ÉöövÇâNzÅ:t7ÜpC“ïy€¦Áqlll`mm­9¿É0š³Â}­—?IZ˜Å7Þˆk®¹f$ç…|Já‘*ÞξíÅê=Z†ÓHá¥Nø¾ ‡dŽÔ±¸¸ˆ+¯¼r$çÛŽúôœG£GÕ@“'Õu]uhèÝ`Å…^§©c~~7ÞxãÐúqÍßMÅh<>pê3§†¯¼[–Òu(çSƒÌß@e\ówÛ̺Èb£mÛpkãèÄQ,ª(ê;Gtð~çﱬÛÛÛAèpñâE*¹ûðáÃêÕj׃&"gÛËVÅièm"{`lòýÐC0^Vƒïû­ d³ÝÃ]$LŒ‹3¤Æ&ã¨ëØ:«· þÂÇ¿£d¨Bý@Ù'Æ%ÛMÞ' xêž0‚ÐÈl–­ùHÀ¸dÜuÛ¬‘6T‘¼b±ˆ­­­ñ |cƒºý”s°—bJÝr3úaff+++Ab@ÅÒGŸ/..6T$s™L¦÷7‰x–ün¹yºÞØG×)Ôd`Æ"ß¼¯\í–o =Kqt½³2îyj±†á¤OÆ%ã@ñŒyQÏþ—³ø“ÇþD)B#(®Jöã’í¦¬#øð/|x4¡‘ô¬’ã’ñnëåËËËX[[ koÒ…žrXgff†ÖÒf~~ÇŽÃÑ£G±¸¸T$‹6%^]]ÅÊÊ ¶··Q«Õ033ƒ[o½µ÷7‰täîj°†úõ`‘%2Æ"ßü‡ŸñÃ/ƒÓO«¦(¥fÈ@ŒKÆ;²‹Eض۟¸Þ3éO†L;ã”í=ýðwÅ¿k²ï‡ŒG4bp'«jdGYìβ¨ã¤Œƒ'Ožû›®®®bii)¸QâÆðüü<î¸ãT*•–û»¢ëÚuõF×{+NCHŒ\¾x_Ÿm¨Ü¾¯dž¹d@Æ!ã® ¸g€ÜçÄ¢Æî¹ý|åÞ¯àÓ«ŸÆ¡¿=ÔŸ±*i œóI Æ!Û­j¾¸®;XaBúdÔ2^/!ÓbA!Ô‘aÛlã”BÆ^%X˜í¿'¯n=²«wPJK>d2*σ+œdŒT¾lÝó*¤ïUyMSýÇÙ£–qÛ´GкˆR x× ï¡ӇšŒÙ,K¨®«~²Yubæô‘ŒZ¶È(«¹|¨á‘\˜!¥Œ·µë)NQC ž§ ,1Ý)u\Wv¥RXp]·7k¹¬4VɔՎ!Á­ºÓÇO@HÉå€\}êwû]|Çw|‡R€ÚMñù¼R^ àÜ9e¤ŠáJù'IÀ ¡uá¼½"=† I#÷®æój®§ì§Ž¦*Á§NB/…˜¦…±5#N®ë"“É4<ŠÅb°OþMÊ·m 8pàæææ`YÖ¤‡•Jº†KŽ6!S†®ÚÓhè· ¨º•C\öK—R 66£f Cmc(’zh°’Ô)œîû>^v÷ݸî3Ÿ¡Ç‰¤†§® ï¸p¡}EëlVyY;aÛÝ!dRøÀ©Ïœ¾w•µ ö—œ8q¦iâÎ;ïÄììl°c~~KKK8yò$Ž9‚S§NMúZûÂ÷}*ó$Õ0$˜¤šH@ÏÙw¾«ÏyNc(0!ÓL øÇ{ÿŸñ‹Û{Šr9åIêxž«b“äRV¤¡zXÅ»J§Ô¾â’Z­†w¿ûÝz÷»ßÍÍMT«ÕI_/!¤Î4µm"¤o¤à’ë⦻îÂÓögTPHzp€áãøæë_ß^®u]y_Ûõ@÷¼ð8BJOý³{…ÞÕ}Ë%³³³ žUA° ûÏŸ??éëí¶ü ûÊ8I-uý¦¶²‚õ×¾/ùçÿ|ÒWDÈðXžzîSÝùl¶½—Õ²ØÆ†$¨þ@u¸ÞUÛ¦wuŸrÉÅ‹›6ž«¯¾ÀòòòЋn¹®‹L&Óð(‹ û£Ïãxž‡L&;–¿cÛ6pàÀÌÍÍÁ²¬Iœ#EÐHjqÔõ‘oÜwt× iÃP¿a]e¿Õ|/Ê;!IľðȆ§‹û¾Z¤¡wu_rI­VÃöövǃdÔëJÒM&“¦i¸pávww‘ËåÉd†j$If¹\F¹\ÆÆÆlÛÞÃ÷ýŽïgY|ßo0X=ÏC>ŸÇÖÖvww±³³ƒR©”J㎠2$ÕÔOÿù…/DŽ^$’6,à¹>Ø›÷)—SŠzÛVÆ,=M$©xÀC=4<]Åq(óû˜ƒóóóX__Çüü|Kƒ´V«a}}‹‹‹Såuu]—J΀ض MÓ°©Æiš&ÖÖÖP*•`šf`Lú¾\.‡l}•×¶íÀ£)Û]×…ëºðñrêºä¾¶ÊQí×u»~w¶mC×õ XS¹\®YÂã¤ÍKÓËçDÈ´s3«A’4rï?â©gÆó¿íÛ&}%„ŒŒþÒG÷¶àèûÀòò¤‡AÂÁI_À(è©Tx_ýÎg§n!•({Ž+•TºRl°2Œlo†sçΕ€ Ãhøq5M¹\žç5„ïJþ¨œCŽ5wwwÛ^ƒiš÷GÉf³»±±„kš–JY`H0I=®‹G®¼’+Ißò \è*CÈÔc¿÷¬ßÃOk?ns] Ÿ¶¶Ú«¥’ê~±µÕÞûJö%©4X à’3B¸0yZUq&$Uxîaè;I#¦ ·TjªÅ@HjЀ/_öåP—J Ñ|^W.«ÊÀ„DH¥ÁJHÚIc)B<Ðu¶ð#©† ë$µXÀ#$|.”:Éååå`Å8—ËÁu]äóyäóy8ŽC+!¤/¨ÐBÈtâyžò®R÷#C‚!Á¤%­ZÚb|ú¾­­­ €„]€ÀC"Чi𠆫e"„(ô®’4Ãül’v^sýõÀ 7Lú2HŠ ÁJöÄòò2LÓ„ã8MzH!ƒàû>ç’j˜ŸMÒŠïûøž¯|xë['})$EÐ`%£ëzàaÀ°_BÈP`ŸJ’f¸CÒŒëºXØØØ˜ôeB!„BR VÒÓ4/«mÛ-«çóyضÍ"„B!„¡Ã¢K !–.ڀ؉® ø¾Š¶Ð4ÀóÔ£º®¾¯^Þîø(Ùl¥R ÙlŽã —Ë5x]e[.—C>ŸÇÖÖÖ¤?FB!„BHŠ Ášz5X=O–b°¶{i†ªã4?ow| –œÔx8°aAðÂÂlÛfuOB!„BÈРÁšz‰¨Í埛f÷¼v]o†#GŽLú2¦r¼÷Þ{/|ðÁ‰…sxw8‡Η¾ô%|îsŸÃSO=5‘± "ßœ¿ÓÍ(æïjµ:‘ùóww8ŽèàýÎ߉4XkµZÛ}/^ly³\rÉ%¸páî¾ûO /^œ={vÒ—2uã}ðÁñÅ/~W^yåDÆ2ˆ|Àe—]†»ï¾×_=n¸á†‰\û8¹úê«÷|{¼®ëâ›ßüæÄÆÂ9¼;œÃç¾ûîÃ#<‚oÿöoŸÈX‘oÎßéfó÷C=4ƒˆóww8ŽèàýÎ߉4X£aqÚݼozÓ›ð¦7½iÒ—NHW‘o8uêÔ¤/žàNÒÌ òÍù›L œ¿IIdëáÇ4†%L*4‚aCù&i‡2NÒ å›¤Ê7I"‰4Xggg±¸¸Øàë82™Ì¤/=Cù&i‡2NÒ å›¤Ê7I"vwww'}­¨T*XYYÁììlä}òäɶù}„L”o’v(ã$ÍP¾Iš¡|“¤‘XƒP‰ß•J°¸¸8éË!d¨P¾IÚ¡Œ“4Cù&i†òM’D¢ VB!„B!û—Dæ°î7¶··Ûî«T*Á W»ýzfuÛ?nº'z\ÆKídüüùó” Èÿóóó ¯‘¸ñnûÇM·ñ'NœÀÒÒRд:~ì´Œ—(ÚÉxÚä»—1”ï´Á9œsxšT¾Ÿxâ‰à˜èñIþ®÷"ß”íé„ó÷ôÍß4XÈÌÌLC ñjµŠõõu,--avv¶£Ôjµ®û“68sæ ªÕjËÉcÚÆK:“6ùîeL”ïýEÚdœs8‰ÒIž~ú鶯Kêw½ù¦l§Îß$e¼4XL­VÃúú:Þö¶·aqqǶ·ãâÅ‹]÷'m<Õj›››ÁóV¯›Æñ’ΤM¾Û‰ò½I›Œs'QZÉÃ4׃È÷4—t†ówøº$Œ÷à„>7Ò…J¥‚'N`ff§OŸnrµ·cvv¶ëþ¤çÌ™3˜™™ã8p•JçÏŸV€¦q¼¤3i“ïNc¢|ïOÒ&ãœÃI”vò0­ßõ ò=777•ã%áü¼ù›Ö„R(‚¸ó¸0H|yÔ _­VÁè¶?iã9räHC¸Bœi/éLÚä»Ó˜(ßû“´É8çp¥£–ÿB¡Ðpž .4É5!à›,ïîî¹[.—ƒçQ•眳IÒ†¬wšÛåxÊvïÐÃ:a<σišÐu=Ø õµm»i6› þwº®ÕË¢Ïe•&úZMÓ‚p„vô{â?„LŠn2®ë:Êå2`yy@>Ÿög³Ù…²M¦‰qË¿a( ç dt“eBÒÂ0d½ÛÜNúƒë„Ñu=ð„ Q#UÓ´ŽF«aÁª<¶¶¶P(˜»DA7—â¸pávvv`Ûv‡Ífáº.J¥|ß§çˆLã–ÿ PóŸÈ0é&Ë„¤…aÈz·¹ô Ö “Ífá8N°‚.ÞÒè~×uƒ¤m©8&D« ’øMHè&ãRHL~ t]o ùÍf³(•J=…ä’$&!ÿš¦Õ*Ùv ‹n²,Ј%ÓÎ0d½ÛÜNúƒë„‘ð­ååe,,,`nn®)~cc™L™L ûE1)‹XXX*ommMzh„è.ã’“777‡L&ƒ¹¹¹@Ida†ÞU2mLJþ³Ù,²Ù,/ÉÐè&Ë€ÒIŠÅ"½Hdª†¬÷2·“Þ9°»»»;é‹ *t U¯')ž¤ëzS/=š¢Fi´È’„ ’$Úɸ Q­ö[–…R©„sçÎMz„ 埤…N²ÕY˜ïJ¦aÈz§¹ô Ö„ãyæææ°³³Ã0ày2™ …Ã#Iê‘Pš……är96Ñ&û Ê?!„ÂàÄ >pàÍfi¬’}뺸úê«¡ë:ežì;(ÿ„B=¬„B!„BÊÁI_À°¨V«øÔ§>…k¯½vÒ—2ž|òI<ùä“ïÎwÉ%—à{¿÷{'=´žùЇ>„k®¹fÒ—16¾ô¥/áE/zѤ/cjÇû¥/}iªŠ;pO7£˜Ãgff¦&'ŒówºÅüýÆ7¾333“ZOpþN7I˜¿Sc°þýßÿ=lÛžš¯½òàƒâË_þ2Ç»‡ó]¼xqª ÖßÿýߟªëÝ+þð‡ñ†7¼aÒ—1µãýð‡?`Y€mOúJ!„BFû°’©ÂqÔ_Ïr¹æý¾¸nøWŽßÙQ]W=^ñŠI„ì'İ,ÔóbÐuõDn×ÖBù5ÍÆó”JJö CÉ¿ï«çrœçù¼úÿþá“6!„BÈž¡‡u‚ø¾zL3®;œs,,„^"Ë2¥œËþ¹9µÍ²”ÚÊ«T,ªcl[½Æ0€r94VµÏó&ý©í|_}_Q9ÙëçïºJ6,kt÷ãËËJ.‹ÅÎïåºê˜R©ý1™LãsÓTŸƒÈ²,¬D Ôb±ñs+Õk²Yõ”Á»¶¾NÓ€ %÷oxÃïŽæÃ!„B#ô°ßWJ«ë*¥Q×ÕsMS ¦¦)¥ÓqÔ±ºzKL3¢Î!n,a”ÏÚšzm«ûã‘GÞ>顈Gvåóáü'úºD\•Ëat˜<$Ò2®ŸGÓ|uL&.Þ‹!+†côX ´–—çR1rÅPÔ9£º~\Ïo¥çIT¨œsé4X@V,4-ªaKñÕ‰na®½ ëݽMÓ ÕÑ ¡¯Q¯#½Øãg÷?!q,+T^¢©#bJ(|TÑZ…´‹ò% ©­í¹\èYˆ†ëKªLü7°ÕŠýövÿ+ô„Q/–ÿ‹¿‹§ME÷G NÇQ2½GÄ‘ûKöe³º™a¨çüÇð†ILûš¨çS¼Ž‚ÌaQÇÐìäiE|þlåŠÓ*QÎÓI·ïe.”ø|>jh°ö‰ï«UÉ£¡4Y¢‹dxÈÊà áÚ„½Ïýé„ã„•¢eµ>®<ˆGsmM)È¢xŸ;æ™ÇsÍ£yÛ€zT¥–¢w¢d‰1+J{/Äçm1žGµA&‹x£þūϕ‹§iH4®«c,+4ôDvæÅ©¥ yu²ø*ÕÔ£²êya=Y¤ïT4å£ñr½¦ÙÚXˆß/büœ9ó䤿²T"Q‘³h«x*%íI<@óbF4/s¿3.G Ö>‘•3 é„‘åѨ  Ñå²+®˜ô‹ä.3g²јžaVKâK»½,aÆa^ôÕ¯NúSJ5ñ<©â,¹ÜÑöZ¢ÅÃÿÄË)J9ž#—S¢%UϣӜܣb0в ¨í@ãñr®èón¡ýñi5ú›—Ë)…?ŸW×0hz€ä{Kq³^¼dòˆ\‹/a<Œ;¾x×›DnåoUÔ/SšÜÙlsQÆè5͵âyu­¼ø­Ø«7J®©P~ª錄ي÷Q: H(k+GÇÖVãb £›’ Ö>™úI§Õò{+¢Ë–­â¿¤±¤ÄqEckä¨ÕÝ.%’e‰+øýµd)_Þ#žÜj,Ñ%4)ãwüÐMú›H$¾¯”БäLF+sµ«$°— Çî´+c'De<Þ/&ºÜ%&û¤4°T>ˆËäò²’a±bâÖ‰ï7'v‹ÌFÏ!ãK(®ÝËN¬ÃEªÀKaº¸Á*¼¤ÿ³xŽ¢bÞ*7(º¿U¡Žl¶1 Pb(ŠX|z.”HŠ8:NóšÊ0VÄ76ÔûˆB>¦©ÎAc5¹ÈÔ}ĽžºÞü›Ñ‹±—›øtÛ*‚*>GIš~¯öNƇ, †vèQÉ…kHpϹ’ýÄsê‚£ GåWFʉŠ…¨A(вô*i—¸(=qúIâÍdÂ_:¹–n³C\£ë…V†lüWƒ}mÚ"•ÞÚ"ŒhåJÔI)»hï#Iô‘˜ÂøkK¥FcM4Ѻ£•W¢¯‰&—GûÞˆÕÐjy?ZöÃ_9éu§]©bYXiõYH|Q?´ª¤ÛlõyǪ·ýÍÊ þeÿïLêD×äÄ™mÖJâôú¥Ý4vhUÁ1Ц)‘ËçCoï¨Øk†¦©ùF>[2y¢SY.®ƒÉwÕJ¾YŽ$b1\D‰ÿìr~™~h°ö@©Ô½o"€Ð²Õ´ÖÉ<’/†¤ôM/ @’@$J{\kÊçÃ%uQÆ»…F=F’äÑA4•af{w‚Kd}S,†2Þq•Z*1‰a&ešEŽãK˜í´‰u´¬Öý•¢žQéû´° ž·2>ÛÅîär÷K|_ü}[yò{a‰w=MBdÈTÞïšÜ¨¯IZuóhÊz`4_0©$ýúö²0#9Ÿñ[þ¤’$ãyJ ‘<~’Nh°vAV»Úg¢á´óŠw$ªlËRy;ƒ²XTJ»xl%0›m³™Ëõƒ2åúžçAç,50¢¬ô¬”Ä+1 Í¡®B´ìhœhn”v½¡•Ó~4âN×Kö ¢¼'-ÄP Åôb<§µ*<¾öooxEHÒqœÐ$åHz¡ÁÚ©FבnÆ*ÐÚ;ÒMë(Ôrº(ѽ^éQÙv]š¦MÜÐsfäsp]NÝÏårÐêïûp#Ùð¾ïÃqœ†c  Íó•vF#<’dm0‰-œ¤2Ã/É^q]¥² ¬O¦É4*˜'¼_ ÁÚÛîâ]•ÒcC\Þ±, º®+CnÈÞOÏóÏçƒÿMÓ =Çq#Oˆ‰qŒº‘bš&4Mƒëì8 Ã@¶Åçâ8Jõšá¥R)0  Àað} Èf³±5l=ÏC6›ÅÆÆ|ßG>ŸG&“iš°m;¸.Aöe³Yض»îº oûÛ‡úÙ¦é-9Ì’JÈ>`y¹¹¢n’HšM¦×Ur^.s‘L/ºÀ#û¬´·¶7D>¯”û^JõA©T‚®ë(•JÈf³gP J×u¡ëzðWŒNñFÚ¶ ˲`4Mƒ¦iÇÑu]¬­­F¤eYX^^ŒE3æõ{&ÃÏÆ…ïûð<Žã4¶bÈÊä=e b¨ …¦÷‹R(`Û64MÃF‡%4MÓ°µµÛ¶áy¶¶¶š®ymm –eŸéýØáìÙ³CûΦ•†öQcUv CMÞ“Å]×'îÝ'$Šd[$ÕX%dXlmÑXMlKÖѶ_dʇ؀º_" ÖJ¥‚ùùù–Ûgff0;;;‘ë uJF÷ÖVã½¶6ôåÉÇ,—Ëð<–e^O]בÍfƒP(‹XXX@.—ƒã8Ð4 kkkqày^à錿6—Ë!7Àoôøk—Ëå‚ë“1t3TMÓúº¶lM3:Öí1V Nª|*‚À0 ŒSÇ c÷ µËb† "Û†a¡àÑ…y]Ô£>¨aëy|ßïYNÉÞH²Œ÷Ê ½DÉžñ@RÙ^¶Çg3ÜøØc¸ÿu¯ù%¦A¶…¾jÝ«Žãàò}>ñ \wÝu¸ôñÇqðK_ÂÅ‹ñÒûïǯ½¾aàk?ÿóÁñð/î¹³=„ç?þ8.ý¶oÃeßýÝ€G}Z,Úm”L‹ŒKtÃØÇŒ”É—::B6 _×áû~xˆã#.¿²Ò°‡„ù‰¬ëëë¨T*8yòd°­Z­¢P( R©P¡â•ëç³Ý«c(ˆ†œ«÷´‰OZý«^ý¡×Q\¨}ª†[®¹€š$×z ^[[C¡P@©Tj2{1 GÍÚÚZbrfÇÍ(ä{˜¸.{ùGß²zJs]7¹~ðoÄ«^ú*¼åß½>iåóù&CQ×õ–žúb±ˆL&D†£iZƒ¡ ð}Åbš¦5,ÂÈñr}bGï QÄ8ƒxT÷‰îQ£\"Z- 9‘v>ŽãQ †a4÷ÑóËxã‹;_Ó }Òe¼–¥{mÑ’T:E5Ä—ú½¢òüÒûïÇâG>‚gžy&Ø?33ƒç_z)àûøâ³ž…ïýÇlù›fgqýÜ^÷ŠWàˆ´¡«J×ñôÓOÃ}úiO?ý4î»â \ñ¢áyÏ{þèïDíYÏ RMÓÄ÷}þó¨|ýë¸+ö¶F]ßÉf³p]õW…üÇìkÌ5X···±¹¹‰ÅÅņí'NœÀìì,NŸ>Z­†£Gb}}«««=W*ûªƒJÿ=MrºÓC¯^. Ê(5¡ Vf#£þ0ûw0ÿ–úJ— À‹œC¯Ÿ'rnÍ×BãVÎ+Q´Nì:<(#¤ÓL±¾m­~-òšNŸ¡œËеóþ[Ö•| YÓ¯ª§h˲ðÛ¿þÛ8õšSxñÙãW|~æQ\zã¥øÃÿ¿øÄ/6¿Ro„–ò±¶¶ÖÓ ¶ä]Û¶ ]×aÛvðr ðÈFCÂ%=ŸÏJ‚(6¦iFnôÇX”)9^Î/JM6›…ã8°mŽã`mm­ÉXŒîŽMm4MC©T‚çyÁ„l—ãåýu]‡eYANwôsÃ×÷}ÌÍÍûmÛÆsŸûÜ‘ËPÒe¼ù¼º†Ñq+ÑjiE´(\'ž’Þ iZ °È9£u¢Q ²Ï4Í@©.ù¾Èä¯}ó›XüÒ—p᪫ð-/âë³³8XÿŽ¿±½¯~ã8úìg¯7 7¼üåxææ›qó{Þ¼·Ü_²¸t!ò;ý¼~ÏuñÿȽ¢ipë×ø?ÿº®#ŸÏõ<ÏÃßþíßâ_þËÑužvÙnÅ^ŒU‘™h´LtŸÈ—ÈC±X.‚ˆ Ê›_$%\æÙL&ÓPÃ":‡‹á7¦äÞÓ4 ®ëâò'xñ_þ%pþ©§0{ð ^ré¥xãããÔ[Þ»þ ë:n¸ì2¼ñóŸÇ¯½þõ¸êª«‚¼°O|âxîWà;~ø‡ñMÃÏôñÙ™¦ Ó4±Úaüwseeex_|¦MÆÓã8,Ë ~ï¥n‹ëºëÆòûò†K.kÛØ9w7Þx#^úØcxæŸý3|üÿþ¿RõV«U¼¦®<øÔSø‡pÕUWáê…|ÏÊ >ÿùÏ7Ü×ò»õç·Þ,êDëËÈyÿ4¶PdÛ6>UO/ü™È}]D’q?÷¹ÏíÛ51ƒµV«¡X,Â4M\¼x1Ø^­V±½½Ó§OP+´KKK8sæLÏ7‹¦5{£{Á¶ÃVŒ’Ï„’Ý¿å+†¥ eÌ­A~ÑÓ˜Z„5|°ôAlý@} ) eœŠ.£!46ã‹]Ùú{ÉÿQýljk(ÄŽÉÖ¯SðÕfýX9ÏFý½¢´\›;‡´~ä\ƒL:výõY„†x·þˆ=JôzFÌ(å{XH;ƒ&ùöêŸUäsÊçóð<óÓƒC~€\«xÝû_‡òÏ”ÕT„ú¾Êê”êÏ£²Q_¤ÑM]}_6Ô÷—CS‚®ë(o”q×ú]xü‘ÇQØ©{­ºWQL¼æ×Š¢º~\]N:y”Äû$žP™p———ƒÐö d2xžä\—J¥@áÚè¡|aÔSЉ¢ˆþ˜IÞ¹àû~ðc°³³ƒãÇ]f¢LƒŒw¢®OÅX-‹¢-ß‹ã8(‹MŠ=ÐèYò}?ÈÓÿ€‹UlÛF6›ÅNÝ%7 ;É´ K/~16t]M­Ünõð­—Ô¯ï£ÿå¿ væ .yéKñ¼Ÿø ¼ìoĹ.2+‘íc;~}Rw¡2ÖB¡€o|ã#«C0í²E"ñz©ß(iHQϦ(™²ØÑªÖÐz.ÖÎÅ7º •k‘ó†EŽbèº*Žù“?%‰Èn¯ßÚÍ ˆV&Ó$ãÅb2òVÅ(™•{!:o[–ÔS‰Fɽ ¿27JT˜ünüø‹_Œ—½ìea˜á÷ù|ÿìsŸÃsÿìÏ‚î#OüÔOÁõ<üáÃãÂUWÁ¯§\‰þ½Ï4Mí±¹ûzßÓfÌñE×Vó¶lo7ßËç=×öövßó÷Ä Ö'N`ii ‚°8þ<4ÄÓÏÏÏ£Z­ö|nÃh ³î•bQÅÆkZ}r÷}õƒÞkÍlÀrý¯€}G"äá`";54•íˆËR/¯‰_g¶þ”!á£ÙÈáËPGÊ)Öÿƒ¢e,´B |€„|d×r=ùúcŠ;_¡X>»~>=2Jù2Xõ~oðè«Å÷Ì~6þw›û@fo‹ä¸¬¡ñ3–çÑ…J®¢Þy3ò¿]?^D¼E p šcdÁDd¨i õñD£ìú6JV´ú¾lø~1X_¼15æZóD½³³ƒb±ˆ¹¹9är9”Ëå¾V{>h÷CÝ_cóÍiñv¸®Z ÜK.”x¥[TѺçÔG±m™L¹\®Áó(+Û@¸@¯+MÌÍé,:Ôt(í­ `Ä¢~ø½ïÞûÞ‘~'êm;ß7ѨQÖ!˜fÙ\WEd³Ý=«®ë²,8ŽƒB¡ß÷‘Éd‚Ú^ëNÄé–rÑmN ù¼ú&mí$Œi‘qÇQq¥l´òØG³Ùl`˜Ù¶ÝÐuCöË⣨wÿÞïáÙ/xŒ×¼¦qþÎdBZBC øâÕ›5MÑg= øöoÞÿþ`ûåPg;£s,÷Ù˜ˆÁzæÌT«U”J%¬¯¯7ìëtSÔj5ÌÌÌ´Ü÷ä“OâÁÄöö6ûö°¶ì·jÛ½‡ûP–lЋ§e"ôzIåúg`Gž·ðªPFCʈ°¡ ËB#RĶåëïãEÞ#n„f#ï£Z­â^ç^<òÈ##ù¸F!ßðÄO`{{‡ZÓDèIÏB-D¾3Þ1ó|ä·>2„7‹=϶ù½åÖŠr-žw»÷â‹>_ϲqÍᣤ×nMRÜKrwŠÅ"²Ù,ÎÀ”êî‘j‚â!•jº-ÂÇÒŒ¬Ãfæï^(•ÔºE\°m;a@y@ã‘S‡TÙTJE³â³gÏ¢V«u•©A˜¦ùÛ²†?­¹õWÞ.a¾í"ezÂóÔźn8G†2.S ÃFtð~»ÁzæÌÌÌÌù`•JçÏŸÇúú:–––Z–Ö:Mò×^{- Ãbì5­EÈc¤z~ƒ\E*öÄ=¤€ÊT#Šu/DÃŽûe˜L¦£È•|ÀóŸÿü=çd2JÖ·¶†JiFËï¬T¯h˜†P’‘ýÌZ}DqÛ#ž;îA-ØH¤A¯ã¨Qí"4tµpß•¸½ò×xÞ1ôak%½L³ê¥ilÛ†ïûCñ¦ö„Uͯ¦Ç ZÃØ—}J–––0;;;ô9<éów/x^ëpwYp› ŠLFý*x’æy{j›‘VWWQ©TF²°1-ó·ï«…—a†‹5›Í6lÌf³Ýï ¹±Z•*Ž¶åšæ{kL ªƒÝ`=räHÇý‡ Väæˆþß+¹\ï]gZ†kZ÷˜1 Ž…QŠëº=i!Ée\ò=(AŠã„?ø-ô])PFE¢ˆµ::‡<÷Âô²¤Ëx'J¥ÞVì¥ÈÌDä_úìðÞ;Ó,ÛB>ß:„RtÎ'#ûŽqÉw¿Håk]‡J qµJèC="2,m^¦>TŒŒ„¤Êx/ôÒoU Ð d¬F•œl¶ûj»DϦ)娇žÈdøL³l Ùló¼„Aî$©Ù°ë†+HÙlïJÕ=‘d/ÃPöV!íýà8NÐÎÎ0 ¬­­õ–rgÛaYbylmÑsšú2XãÉÔÛÛÛp3338räÈÐâÖWWW±²²‚ííí ÉûÖ[oíë zÎÉbô®í;GRÍ0ä»_ŠÅzJ…µ Q\b…\×Åòò2¶¶¶h¬’™„Œ÷B/vàÀò¿°ÐØ2#“ Cv%Ť]A$ßWŠ’4…å½—X’*ÛB<VúXwÍRÖ5Š„Q6t@0¦² Ò~`2.S ˆé^Ôáb±Çq°µµÕ¿^ÝjÅ'íøPéI>T$XB‡ß“ÁZ©TP(P­Vƒ˜o).a›››8~üxP&»WZÅ»ÏÏÏãŽ;îJmb{žZ¼ëe>ì{áDú‰Æ¾Tiq%z³H‰w ¹¿˜ô(#ébTòÝR-}#ç¶nÈ‘cQÖ¹xBz% 2Þ+ݦX)H3üǽWkk¡ò.E8Ú¡iSŸw—F¦I¶-KÉ·¨’³ê8666F[‹ ^®ô†l0NûÉÑ"c%)2®iÃ)hžÉd‚êím%Õ¶Uxå0ôGë}¾ƒZâÓƒ¤8£Ž°S@¶~žh«A¡Ý!Å¥8c ª~…´ê“Î#è²hlçgD®OêÏÈ>aÏúµ6¯)E®k ôd° ÌÏÏ7c›››˜ŸŸÇÉ“'133ƒÍÍÍ i{ÌÌÌìé&éµ^’”~°,µÔÓ®¤»¬BD”|ß÷‘Ïçáû~C¿2éÝ è«'½šòù| ‰±ÊüÕýÃ^å»J¥º8K¯(yOÊ:!1Æ)ãݰ,¥£tr2I®SËP`éÉ-ùLÙlo½Dy'©"I²-D Ô”J%X–…B¡0½B×Õ ;RÃ8e\:tíÛ¶;W[÷}•ä-)½F³8[/ÊHU*õKW ¹Ý¢†¥`"ì(E‹ý/Ï£…¥7½Â[PÆb¼8£t>ˆ@u#ç5ê¯÷"¯“G Ô8F›í6”]$Èç$ç‹vFØ#] ÖíímT«Uœ>}:(g]«ÕP©Tpüøñ`ÛÒÒÖ××ÇÒC¯WzéàǪTj_ìBV."»]×E&“A¡Phê[ÖÉ£ªÞ_¯4È(qœzŽvÆiNÖ®·L‘׉Êq"dHÈBz'òù< …B¸*ïû*¬WrKÄ}U(Ð[DG¹ ø¾‡åå<4Mn ‚hȺ놅DŠz¤uðÚú_i»%a‡¼…H eiA&Ñ*Ø-±,¥ßçrC/£žI1:m4{E5tîWëel 7³Ãþ^»j´k¿ž~:z´;G+¿žñ‚“‹þß·NWƒµR©`qq±¡÷’SÏOˆaè4`z€IDAT£hn¼Wº­ÚèzL‰±m¥´sÍJû‰ú9%߯\.dt2˜Œš†<îøDî@MÄrœ˜·JÒ†,Lvšn-Ë‚¦imÅ–—•r3ÎP]iQ”4<¨¹hV6Ú)Hd¬è:°°°ŒB¡0¼öxÒ[Ķþ¿ÀuoVŒ›”>d# ”¿â‰Ñ¡ŽqëÏ£½¢%RMäÆCØ[ºåu Ñ3ÕI±'SE²´Ç@€b±ˆ\.׬W‹ü† Aˆê8”ŒÆCgÈÿšÒqõ‰ŸFâ¿ѵiåçƶûòþ¾NÝÕ`™™ij$\©T0??ŸH#5Š´™ìdK6ȶä_´ÂBèj‡RpJ¥óýH¢é؋ؠ«0ÓߘHo;Çi® ìy{_òï†Ý”·]€ú‘œ&YüîyPÒÏ·;§¬lëõc¢yQQ%_Ê…E„Uðs½d>Âð8ÙÖ)/*yy·~[‘c¢¡tÂþÂZ}ŸäVÉy‹À}#îÝý£û~¦ÉÔÒ4 †a g·meEÜñlàu¯Pо¯©ïà¦ú1khTÜ[yN⊽ÖÞù®õýÛeQžG CÙYÞˆ#÷ŠäØIE|yÿR}»<_FxÈ}#a”2 ÄÃå~£ 80¶½÷iÖqxž×:ü]úòjZ8ïá¢JüþÆ…Ž`Þw·]<|öá¾^ÞÕ`ŸŸG¥R ŒÔZ­ÇqšrU···„=œ’€®·ùД¿-Q§ 憘¦9ý ¸Iêé˜Ë]O¨/æ‹ì·JR‹ë¶/Iàº.òù|sUàVÅɆM¡SÑh|12e¿(ÈQ¥PŠ´{.ʶ GGcf´HG;¯F¯†Fü˜ø4ÒË´²û$ÔNò½ä}ÿ5à Îð˜ûØ@}špà}ï{ ïxGix)N}µâ°ü¼ºNêÎ^”þ¸Lç:Þÿ¿ÞÏ66$ÕÄ3=¢–‹EµÂ9jo« †¤‘¡ñÁ~ozÓÁþu“bQY»ÿþÿ <ü½¡×½S¥^Ò™Váëñî (ïµä¨·ÃÙë@*µ§ô—ÌOd°ú¾£¸u}]£añÓÔÓ³Áº½½³gÏŽ9’˜^«Ýhåm¹ˆÞæÎq²œ¢Ã¢4dêÐ4 «ÕEàëbžÏ燛óDHÂp]UAUjqD‹s4ôZÍçÕÍ2Ž”‰p dxž‡Çÿßøõ_ÿ‰Þ_$½…MSµ9[Ö,«£GGçòº÷õk+_›ô•Žßï3ÕP¾ùÁoâØóŽaõÇâÖÓ§GCCOëúú:677ƒç›››8vìVWW'}ý]ÙÚRùªº®dºç4¨}±Öº‚$!S€õþ'‘ý­÷@û«?iØ^,¡isWIª‰gy4ç”¶´¼¬Úë½à"l“!ÕF‹õç‘V, á‚„ì|>“'{Xt”¶0pþ3¿ ^©òú¸O&„m÷a°Ö{þ>õ¯žÂk¯y-~~i ?¼¾®ÙŽoßÐSÑ¥ÍÍM,--Áu]¸®‹¥¥%lnn6õgM"¶­VÙûJÓsäüÛ —˱Ï*I6 ­7[%Ú-o…¿¨B"ÇI\4B†M.ê2ŽãÀuÝF¹·¬ÞŒÕ =Bd›ô)Ãt­-L¨J¥k‘s´j@OÈäóy\{í‘Î=WsPr»à5¿<ÿ'^É"4dâhZ¶fjþÜ~ùé_F6›Å¿ë]ª70Õ}EW«ôW=vìX°muugΜA¥RI|h°iªGÓ"d±º]Å u¡n¸ë¦»àTl¶ú|GBÆÈZ+ŽÔfÃm o3b€¤›R½1¼Ø¡¾ï£X,6÷é³màÜ9õ¿‡Æ~¦ÒÇ´€Ð`¶¡ÑêÛüúös].JÎEÈð}™L¦iÂuOÀ÷#ºUäg¡œFsR_~ðÓ?Jc•LßïÑÖ¬×ÃF¸ØÎºû—žsX£Å•fff&}Ý=ÓR/w]õдÐýº¶¦Âf €«»øùÿÀ¼U’l¤Ú` ¯óþÏÀø®HX|åò¯ÀüN“$µ”J*Ì,ºNS*•š{ Û¶Ò˜êyQMÅôÈsÍy§4>ɘ¹ýöÇqë­ŸÇoüF¹\™LL¿q <ü2½ÇËrÐE&Ìòr˜ªÑSWjþ-•·¬æEG²¯Øs•à©Äq”Û5 æ¿úñ ?½P$ÑX€ó ?¦r8ŽzàÚ†>]x¬ |êYŸb¥k’jl[Õ’ k*ù°m»qU¾Y`-†ê'’H|_-Äœ:õ~臶‘Ë©Ú!ÁzºT§=JŒe©yù\·h@-" ŒUËÂ~û·‘½å.¶ïsö§Á꺭ó–tàÇþèǘ·J¦0Ïå—z]iÑuõ£àãºÆuøû/ý=Þ“}Ϥ¯š‘ -l¢ëŒRh©añÑ@hœ2T—$œ|xö³?ÙÙÍÍÈÂK4:` ,æEM©Ydé„§×Å×åW°|饸+‰Ü÷ôl°®¬¬4m[__Ç©S§¶ðœç|…B¡1Û‚Š Èu9Äa2A,+ì‡Ýób÷\z)f––˜ÊDô`°ÎÎÎNE¿Õ<¨ ½URw´*p˲ð©ÿô)üÍ›ÿfÒWNHÏØOÚçÏÅ3€v‰ŒðsÏüîø©;&}É„ŒŒ\Ðê ¼ã8ð<±ŠdËËl4O¦ßžyæ —‹¥r8è­‡ªm«ö„LžDÐÒÛ·Ø6.ììàçÀ[ð‘:}ç°nooãìÙ³Áó#GŽ$¯µŽ°Äû:Óp–eá#ïûžûðs'}å„ôÆà.…Úî增÷¡Âh¢É"®ëâ9ßõœI_1!#%W7V}ßG>Ÿo®ò.ýnh¬’)Áó¼ã±*5ó°Û!q˜ô°’iÀ‚Šð< XÄ¿>t››“¾*’ z6XÇÁm·Ý†jµÚ°}ss³³³(•JÉ ö}@·W^ð/€_ú(ðÞnyh©TÂÚÚžg>oÒWMH_¸ÿ&ŒKlÀXS Œ Àwšò¿]ÿ[ä´n±c„L/¥R=w{(™ªÐRC¥ë*žÞ&2Eœ>]Áw}Wl%‡°(M'úŠÃ$d4ÌÍõPØCئÏvñ•ŸýYŒ£Gb{{{ÒãidÃV¾°<Ãq`|<™:l0_ø¹Æb”b™ä}ßÇ}q¾û²ïžô%2¼Èô^{V Žã`-F–Ï+åÞ&2Eض‰l«‚IÝÄØóÔßžªÜ2bêH{$'²Yüæùó­åžìkzò°ž8q¦i¢Tj®ìbš&LÓD¡PÀ‰'pçwNzLJ)‘R©>€§W€¢¡&ñl6˜Ä-Ë +/@UÛ#d p]À|ôOÂ8È‚¿ûÕ_Å‹þø1)\*•ð·¿Ï}7ÃÝI:Ñ´° ý;_üN¬åbƪm·¬]@H’ñ<šæAÓ"‘kE¨hšnº¼m³20™8†Ñƒ“߇êrÑ¿›zg‚<¬ÛÛÛ¨V«x÷»ßÝñ¸cÇŽ¡Z­¢R©LzLÎ]¥îšˆÁíy|ß§w•L%Î]_GöÙw„+蚆—ýÞïá«_ý*× süįÿDXy”¡i*UÏó<¸®Û<§Sy'Sˆã8X]ýLl#‚vf¡Ì“i¡µS°, ¦i² i¢«ÁZ©T0;;‹ÙÙÙŽÇIþj­V›ô˜ÑPoªm. ¾4” B)yo)bçèû›’ ßøÏ¸îèQ‹Ejâïµï…fQ¸I:q] žÙ¿~ï_ãO_ö§xžzpa’LŽã4/¾t깥禗„ŒŽ……ÊAuô¨‡±;Žƒ\Ž57H3] Ö™™\¼xqÒ×¹7b¼çy7…å‰%dZˆ­ »®‹ƒÏù.\·¹ Ó4Q,ñµ_û~ð+?ؽW!SŠe©{ð÷ù{Üxã8N˜BÈQ.?|ßP¨bŸ/f+2a\·Ëš‰Uÿk@Mâ™ <σçy,¶DZÒ5‡u~~µZ Õjµ£—U .ÍÌÌLzLÍXPFk]¿oÈ]T˜ PdšØØhø5p×½:t lé[xÓÁ7áYŸ|e›¤ßWöèÆ†šÓàúÀs_ËÕæJ=™BlÛÆå—Œk òûºUY%$a8N‡²TU`¡Tr9X–ÅbK¤-]=¬óó󘟟G¡Phî[«Õ°¾¾ŽÅÅÅä´¶‰¢£áæ°m»ù¦à‚™&b¿®ëâ¦[o@Ëh¸å–[0sß U’Z¢A¶mã¯xå¤Çqðo¼Ú{lLújé×í‰a ¬ ¶O9Û¶I„Dè©­ÍñãÇQ­VqôèQœ9s&èÅZ­VqæÌ=zÕj«««“Ok"UõZ&t» ÁJ¦Ïó`hõð± àªß¾ŠE Hj‘V6ÙlX@ïºêu4XÉÔãyîºë!|Ï·]®60ýšL!ž×ÁÃj ,iY€iâßþÚ¯acƒ«3¤==µµ™ŸŸÇÉ“'±¾¾Ž'N4í_\\Äêêj2½«€Rbê7ŽmÛÍ7EyÒHÈà8Ž£r>t°5I-®«Â€u]µU”B”Ï—T=\x$SO©TÂ[Þ² m a“½Ée*4d²x^‡–×E¨"Kr`©„S««Ðصƒt¡'ƒVi]S©T‚páÙÙYÔj5loocqqqÒcj TŸ£<Ã:«ç‘¬„¤€,ÄC×CÜ÷}8Ž£!¥k™ï«ò”ç˜øG¦ ñ®>ç)oDíÈ,‹•I"pÝ6ÞU‹0ù<žø…_À¯üꯢ̅Ò…ž VAZÜÄWB*• VVVàºý. Ž Ø>³ìGrW}„J‹ê‘)Åu]–'饠 ŒÕxé†ödç‚ìAI¦ŠLF‰¬ë–pë­·bÉŒWöyÛVÈ™0Ùl›)ØBص X ÿïW¾‚l6KGéJßë´òø·=xhTì}¨paêúdJñ}¾ïs²'éÅàÙó´mÛØÙ‰ÄÁ{ž*OÉÕz2HÔÀư±qÿðÇñ‰¿Úèϳ (—@+I.>TGYS1 À4a-,лJz¢§¢Kià?~ì?bñà¢Ês’fÆ:T¥2ê SŠëº &éÆŠÿµy³´@Ð4M…™¡Vís¹ T„$‡RIÙ˜º\}õïàä‹O†ý)ûÁ²ØÂ‰$AñS@6 §®¿pÁô¾0X}߇mÛ¸îºëÔM³5é+"d8ø¾ÏjÀ$½”ïO÷¾»J¥0bÆpÿý*•Š;™l»±í‡çyxáó^Øz’4$f,ËÂÖ{K’þ™H[›••,..Âu]Ü}÷ÝX\\lÈI:qâfggƒý½V*ŽÃUK2 Æ%ßìÁJ&Ÿdö§øÁúAåY}ð¹Àé[Ch2lIúY]]Å‘#GF6‡cþ†l›ílÈtáyÀåǯÏÖM„t «‡u~~µZ-(yÝÙõºN MÓh°’TÞfd?ðå?ø\vÙeTØIºØPn¾p¡³Á꺀eu7j Iž\üðØc1Ú‘ ž Öùùy¬¯¯£V«µ<¦V«a}}‹‹‹˜ŸŸŸô˜!„¤€§þÛÃ'öп•D¢Olnâ /yIãvÏSU@ªËËÀÖ[ÚéãÒçãã|œ+=U >~ü8VVVpôèQ,--5¥gÏž  ?~|Òã!„’<ÏùÌgpåm·MúJ:ºëâ©VÅ,(MvvÔ_B¦ Óþ‰Ý:ÈpéÉ`ŸŸÇéÓ§±¹¹‰õõõ¦ýKKK8vìXSa&B!d J%Øš†·q…ž¤ ßÇõ>ˆO½ìeÛuØØ˜ôÕ²7êEÅXp‰ “ž V@U>~ü8VWWƒf€2f“·J!$%ø>à8Xð3 ‡$iöñWW_7p1†¤€¡ .år¹I_ I =¬Â°šÁB!-qx¹ V˜$iĶñGÏ{na¸/I#õö¾ï³*]‹.B!c%›…Ãjï$­ll úœçLú* :VÉ¡ÁJ!$q0ÿ‰¤]‡Fï*I+:àú.eœ ¬„B‡ã84XI*q‡Ñ$Õø¾Ï–6d¨Ð`%„B#ô>‘4ÃE2lh°BIŽãpuž¤×e¸$I?4XÉ0¡ÁJ!$Q¸®Ke‡¤†K’´ãº.eœ •¾ÛÚB!£¤P(Lú¾ïOú)Œ" ÆVB!„1Á Ø$íлJ† VB!„BÈžaÁ%2 h°B!„Œ‰r¹<éK ddø¾Ïp`2t˜ÃJ!„BÙ3†a0$˜ ¬„B!„=Ãp`2 L!„B!$‘Ð`%„B!„’Hh°B!„BI$4X !„B!„$¬„B!„B VB!„B!‰„+!„B!„DBƒ•B!„BH"¡ÁJ!„B!$‘Ð`%„B!„’Hh°B!„BI$4X !„B!„$¬„B!„B VB!„B!‰„+!„B!„DBƒ•B!„BH"¡ÁJ!„B!$‘$Þ`­T*¨V«“¾ BF囤Ê8I3”o’f(ß$)œô´£Z­¢P( R©LÓD©Tšôe2(ß$íPÆIš¡|“4Cù&I#±Ö'N`vv®ëâî»ïF¥RÁúúú¤/‹¡@ù&i‡2NÒ å›¤Ê7I‰4X«Õ*¶··qìØ1ÀÌÌ –––P.—'}i„ìÊ7I;”q’f(ß$ÍP¾II¤ÁzþüyÀüü|°m~~žqôdBÙ/¤i¼”ïÞ8sæÌ¤/ãÊxwÒ4§í·ñR¾»“¦ùl¿—òÝ4ÍgÓ2ÞD¬nŠZ­6éËKçÏŸÇÙ³g'}ïP¾{ÃqœI_Ç; ”ñî¤iNÛoã¥|w'MóÙ~/å»;išÏ¦e¼‰,ºÔ醸xñ"fffš¶úÓŸÆ?øAü÷ÿþßqã7Nz#ç‰'žÀO<$ħaŽ÷á‡ÆW¿úU\yå•X]]ûX‘oð<¯ýëqõÕWãùÏþد{Ü<ðÀXYY™ôeLåxï½÷^<ýôÓ çðîpœxµZ /yÉK&2–Aä›ówºÅüý¡}o~ó›Ç>ÎßÝáü=8¢ƒ÷;'Ò`†!Ä™m¹ýï|'ÞùÎwNúÒ éÊ ò ñ1éK'¤'8‡“43ˆ|sþ&Óço’D|øðaa Õjµ£2OÈ´@ù&i‡2NÒ å›¤Ê7I"‰4Xggg±¸¸ØÄî82™Ì¤/=Cù&i‡2NÒ å›¤Ê7I"vwww'}­¨T*XYYÁìì,jµfffpòäɶù}„L”o’v(ã$ÍP¾Iš¡|“¤‘XƒP‰ß’໸¸8éË!d¨P¾IÚ¡Œ“4Cù&i†òM’D¢ VB!„B!û—Dæ°B!„B!4XÀöövÛ}•J¥cߣJ¥Ò±És·ýã¦Ûx¢Ç¥a¼DÑNÆÓ&ß½ŒIŽIËx çðvÇ¥a¼dpùžÆïz/ò=ã%œ¿Û—¸ñî’‰rþüùÝ›o¾¹iûg?ûÙÝ·¾õ­»7ß|óîÍ7ß¼ûÖ·¾u÷³ŸýlÃë~äG~$Øÿž÷¼§é¼ö›nã‰rÛm·í¾ë]ïêkÉßõ^䛲=pþž¾ù›k™™™ièyU­V±¾¾Ž¥¥%ÌÎÎv‚Z­ÖuÒÆgΜAµZm9yLÛxIgÒ&ß½Œ‰ò½¿H›Œs'Q:ÉÃÓO?ÝöuIý®÷"ß”íôÁù»‘¤Œ—k‚©ÕjX__ÇÛÞö6,..âøñãÁöv\¼x±ëþ¤§Z­bss3xÞêuÓ8^Ò™´Éw»1Q¾÷/i“qÎá$J+y˜æïzùžæñ’Îpþ_—„ñœÐçFºP©TpâÄ ÌÌÌàôéÓM®övÌÎÎvÝŸ´ñœ9s333pŽã R©àüùóÁ Ð4Ž—t&mòÝiL”ïýIÚdœs8‰ÒN¦õ»T¾çææ¦r¼¤3œ¿“7ÓÚP …Bw‰/ºá«Õj Ýö'm–^é$ß²_rùâ26LùäxBö¨e?ŸÏ·\é÷}™L&P„Ýä9J+ùä|M¦‰½È»ïû˜›› mÛnHÙ l÷É.™8;;;»vÏ;l3Ms·P(ìž;w®iŸ®ë»¦iîîîîûwvv‚ý»š¦ÏìnllÏ ÃØÍårÁóB¡œ¯Ÿc é…Nò½»«dNþßÝUò;*ùäxBe²}}¹\Þ°{áÂ…&¹&d¯t“gÓ4wËår°/.Ÿ²ó5™ö*ï2 .\Ø5M38e»?œlÛ†iš abår€Za‰ïËf³Á Œã8Ðu½¡:¤ÏóÐh4prr’ô¡eÖ”'¦¶mû“®§%­ÕjÅbq¤Õ&ÜO”´Iñ­/…ñMY—D쟜œÀ󼼸¸¸üЇ>tùÔSOÜöáøò§ú§/////_ýõ˧Ÿ~úò¹çž‹}û4Ÿüä'cß7x¾É<ß´ø¾¼\oŒøÃ^é{šv<ßÍ?_’ñÍ2-ßÒP†³üÞžo2ÏÇ:øfð|7ÿ|+Üëõp~~>vý`0@¯×Ãþþ> P(`ww×ßnÖí4ªV«áðð0éÃØºóßc|ÕŽ“>„­;_Æ÷椥LÛ¦óe|oNʳm<_ÖÁ7# åÙ¶ïÊÖÝÝ]ØÃ‡`dxC¥RñÇÉϺ( &Å7À§ìc|Sž1¾)ïX§¼Zë¢KºiA?gÞN”vŒqÊ3Æ7åã›òŒñMY·±„uZÀ?zôhæí³¼òÊ+øøÇ?ŽƒƒƒMeÔùù9ž{î¹±7–µîõÕWqpp0qH‘888ÀË/¿¼ÒçdNiqtt„çž{Ÿþô§Wöœ,¿)-¤ü–ÅVå7¥…ÔÁç-¿¯mê§­tV*•fÞ>Ë{Þó|àH|Œ5¥ßîî.J¥îÝ»·Òç]wŒ?ùä“©™'Cév||¼òŠËpJ‹ÃÃCܺuk¥e8ËoJ )¿]!8 ËoJ‹Eëàëa½~ý:€Ña ƒÁÀÿ"̺H8Žú s]À¶ÕŸi×·ÛêÏuƒûýÒ/};¾øÅ·¬ô¸ã´ Ï þoÛA¼F1MÓò‰qÓ,Kýÿ¥—Þ¿Òãc|Sž1¾)Ïß”uKXK¥jµÚÈpÛ¶±³³ëö,ñ¼ qŠªtÊí+‘:—¨¤OOè¤ò>în7¨ëI m«Ûä²ã¨Ûwv‚¿v{ô5å>ò:Ž3zù»yØÛ ulÝ®ºoÔûÞj†‹Áù oÄ—¿üÆ•¾§Ûã³HŒKò¤ÿéŸ]ø{0-IÓ£Ç^˜Þp¡Ç´\±¦'}€:6¹lšê>r|ãúyIŒê÷ÑÏGžãÆñ¸ǽ¾ÝmŸm«çc«VUL ‰q×UÏW.oû++ýLß”gŒoÊ3Æ7mŠãŒvIÝ϶ƒ:Ìÿþ¿¿eîN£ Ô0žƒƒôz= ‡C <ûì³±oO#ÏSÅ¢ú“$¬\.»®ºlªb)ÐrYU< Ò+—àÿŽú×4ÕsµZê¹õ 8 n“ úɉz¼ô¸Ôë@£¡^coOÝ&#Ç/÷‘×–OUy½¢,÷)—GÏUžÃ0‚û[–:žj5xýœÔõûHòR­÷ïÇ£+GÙ0€'žx÷î}nåñÇ’¨Y–zOËeõ9Öëê³ïvÕ{Ûh1.ôxÒMy.‰õp©“Ï]bLžOb\'Ï'ñ%Ç#qP­ggê˜oÞT×Ëíõzp=>%ÆM3øî6Áí¢ÛU×KìK¬O÷Žúžw»*Q•ûÈ9ëåĸçŸúÔjV ßñMÄø¦M‘z—ç©ßýwжÏþ=+MÆwºéu&`´Þ1#ñẠ®“:OT\E½–ãupž!M®«žSžËuUªZ êEFpY¯çFÄêu·oþæ¯Ìõþ°ò÷å÷lzý[èõo=ôÏM:£¥¾¯×û%$ _‚Ž! âí¶ŠŸN'è 7Ò‹iÇ'± ŒÇý¤<#Ó Ê鸉—ö°j3âi_‚Y·'Mz(ÏÎÔår9^¯à¼ùp0E=Ç<µŒpÏMš¬+I_FÖc ÄNgz﵈jéËŠbqv/(òßTÈ¥²$•ÎAoŒ&ªVÇ+k޼öšº,ÉgTù,­ìÝn0’ÁóÔõá†_I*„Lïøú××ó¾0¾ç'qÔj©ËÒKÊBêK{{êúðh°0I[-uËR÷—Qb’$HüH¼éÿJXõé"úñé=@z=LF±HR, ¸áQqz}ÐóTco¹¬Ž?ê»P,ŽÇ|§ ‡¿`õ ë¶Ç·LÒ{%ö¤¾3i:_T<èõ¢8¹@Ôgç1úý$þ§‰*Kã¼Ö"õéMÕŸ6ž°fQ³9Z¸I78Q^5›ª"ä«×‘hÝ$”ÊMTã£T˜%é›Ö9©QNzsôÛ¤¢ÕéÉg·TŠ¥7Ƕƒ†špƒdTEìÁƒÑ×–ãÕùìlô1q+G’ëɯ.êØ ×[ÿg¹dšS¹<Ú«(‰§ EÔG•I<‰ð4œ¨ï€4ú‹F#Þô ù]’×¹ö9…c1N;ÜH¯ŸSÜž¤b1^C«¥<”˜•Æé=ÔËÍpìʼnpŒÓú1aA n½¤x¼«ÉˆÅã8p]×ßÕÐJòÕ¯œ{Õbຮÿý>†aø÷•û9Žãÿ•Ëe‹ET«U8Žƒ_ûµ_Ã÷|Ï÷$ý¥VœJѶ‘é Ò:/sŸ›Í`¸–Tæ%)•¤NÓhëÈ0iõ¢÷É.é 8; æÉ áÄ!jݳ³É£"âTÄ¢æL/Ò°•æÑ;ÛHFéq^ÿ!J8!œgh Ñ*íí©z»”‘zÙ*×Q61a¡X †¹l;T{ _®V«~"ªßæº.<σëº(—Ëp]†aøI¨$òyžr¹ìß_>¹¯Ü'üÚžçÁq4›Í‘×,—˨V«¨V«hµZ#IqµZÅ­[·F–oßf²z›ôäÄé¡ ñĘQã–ûI\ëñ«?Vb9Ü(#1åP†!÷—çÕïcÛ6þÍ¿ù7I¿E™§ÏI2õ©¥_ÛÈü==1dѵZzãi½^ŸÙ(õxÛ¶qqq§žz*éÓI=š^¯sô̪Eu<Ä%å¹þ»'¿OŽãp„Ì2"Lë¢íÁ„õŠiŽ.5-ó7tÒSX¯×G*‡R1vNg¬’iš&LÓ„a¸¸¸ˆõÝétÐjµ`šæH¯‹ôöH‚ªƒeYhµZc‰0‘Ѓi·ƒ}³âð<Ïz-ñgY Ã@½^INõF™r¹™dÉwCÉF£á'¨€ê9¯V«þýdsIõïѪ{íçQ.—ÑÙ@M0©§¼’ÞT"yr½²â6$rÒå¨ûËw»X,ú±òÔG££nôé7oÞôËI£ŽÂ#¤ìù‰Ÿø ‡Ã¤ßºTó¼õŽK’4þOªïØ&…Kƒ8FõÿG=—a#±¨ž‰C^S¿¿LY’×Ðáío{Òoq*É ŽØ>LX¡*-¦9ºšÛèf½ºÝ.lÛF£Ñ@·ÛE·Ûõ{MUa>‰X™IzMõØIÖr¹¼ðëÐv°,•°ÊÂ0ó,$fYÚí6δÚO§ÓmÛ0MÓO¨Nb>qÜï†ÜñM«´·ÌyÊÚp²pr'•pýz© ë$9”^JI2õ$R¿ï$r›üþÍó½×u:˜¦9ò<ºi Q²M& l¥¥ ;¼À¢žp†I¤>LÙ£Çz±X]nÔÔA_„1j=¨©!ëV¯×G¦7lôõÓJ¶.’ršÓ"¶×Ö'¬2—cÚ>“;;;0 ÷¯&ú5 ¿5ììì,±ž¢Yd YÁtÚt_Ïó°··‡b±èÿxÚ¶íϳ¼¸¸˜8•=”%íöê{S%”äKzSô™I½–ÒS#Éd¸÷ïmÔ+úúeý» dYšÍ&ªÕêÂI¦nßûuÌeßvž4N®2Yu–eMì 'ŽaÒ0" ¡þ}0q*Ó|çîm<Ù¤õqœ ‘¶ÛV'¬úp™Iå[»Ý†acCþXI§,­é3‘çyØÙÙñç[›¦éWl[­crÃ4W¿ÐX»Ý†mÛþH©0‡{&UÀ%#½R/â,Â7ŒÂáH…|Ó·¦YìñAÌÊbnÒØ! ËÆ¢XÇï “Õ|á*¿Ù¥/BþMûÕ_ýU¼ñoœëù¶:aµmU¨Ojô<–eù=«DY"eÏ _=Y•ÞŽ“““¥{_ˆÒ¨Xþ1MxvÇq`šæÈÂv2;êw"îü6Yp…h¦©)ç,=’”Ê"uVž¤Åáº*ž·qM$„l ïPu}ÄŒ Ò“Rº/ë“è;|æ3ŸÁw÷wÏuŒ[°ÎÚ ¥Ýn³¦Ìj6Ua?+|›Í¦¿ /QéC$cì‚@}/ÂC‹Å"†¿½mÛc í%!Îô&}a<õ˜`uõjµŠû÷ï³¾C‰±,•¤*ae²º8™+þ Óç†OÂ/s¼W¹«>G{‘5¶2aÕçõM"4{™(‹,KUZfUÎMÓ„çy«&¨/CL”;;jXYœdÕu]ìííôšÊ¼þÃÍi!”2 xÚô&ÇqÐl6ýäT³c‚JiÐlI*›L'Côõùß²’µÜ®ïÿ^{dÚv„i¶• «eM¿Ý4Mt»]&«”Y–5{“ã8èv»Ë yw]Õúã8AM©^_ʯÝV÷™ôKµüŸ<˜ü¸Fc<9–BÜuƒ?yÃà¯áг°ì§kY:ÎHkð´í3ˆ’fYÓ‡·ÛmX–…³³3Æ1¥ŽüdǪ‘W’€Ê(Û¶ýÆ%镦z½Ž“““L&ž‹ÚÊ„Õ0¢[!ÇA»ÝF¹\ž¸"êBd•ýùªÕøcÓÖI& pf{®”˳ó²f³‰“““èv×U cÔ$ï«ýP!óÙ{ä4Aâ¨sõÏ ^Sꡖ÷I>yOä6ŽŸ#m$³Šr©Ð·Z-©¾R.2›ßÖ%¬¦©ê‚áòÛ4MÿÉ™d¬e]YQ•äryvmI§÷òH¬÷bE›$©2 \V½b†$|aŽ£þ #èkµÔùt»êº¨DRÓÂoà¤s”d£ÑPÏ!Ž£>ŒðY*ã’\w»êrx%!ÇQïþÒËU¯Göþ}£Pˆ÷™d´UL[xcâê×z‚?)IÌû²¸ r8QŒÛÐUVÌzlTÃñ<¾’ßGe:IV9ýƒ²Æó¢BeJS½^g¯*¥^·›ÝŸ6é%•v%1•ÎùîqJÉjleÂzv6zçyèv»¸ˆ3€^zŸêõéÉè"-šQÙióþU±žÔ£4©Ò=i©ÌiKh.2ÜpÚ{0éu¦Ï$ÕêÜ“¾þÄxýmo›ÿœ2`ooúÛ1uõkIVYÉ¡ ÚÛ›ÚN˲üi€~ÕáPêx¤!1jÔÀ$2Z!ªHF ÐBd{&ý-l6›ð”W¶=“•‰éúlUÂ*£IÃ帴FÎ,ॗoZïÓª1øiNQ#º…¶‘=J¦9ýÁD)&ƒS&埮ë¢Ýnç³2oÛó7’ʰõðãÂ#V€`Ú‰ _O 9ïúˆIT«Uu|ÎèkÙv0O¾^ºÅÉ“ÚvvÔó9þb¿?ü[+éw>2ŒR/ªmÛ†ëºñÞ‰R@f­¥‘¾-Lxû'Î/MÆV%¬2T¸®ë·˜Ì,äåy“É*Ѧnìv»“{”,köâID)U­ŽžÑ5›Mt:üU4šÍ [w¹I§¾r¶>e"j~ŒŒX‘©q±ŠÅèÚ¦©×ÕýeBµ,\&ë+„˪“uì>õùÏãssîã—²Ö›^Ñ÷<ívgÓ¾D)“¶ù«úJñ2ßTö"åÐúäm]Âzÿ¾*ÜoÞ¼éäÙÙÙì`”Vå¼Uv(W¦ —eÑ#à/XE”!2ºtR1Þívã¯Q°I“¾w²ž¬G0ÉÕ\Ü¿½_›ž¬ÊóÄí‰g1¯y† ëÊåùÉô!RŸÿüü¯—q¶=o5ö(1Z}!=Û¶y“F˜¨FYL3¼ªýÕs¼ÿ[¿5é³Z+9ý4$¬¶mûûš6 ÎýN©­IXõ†âv»‹F£Ö<ƒçÓVÑ!а·LZìÔ²¬É«E–ËÜ2kooòâÕŽãÀ²¬ä‡JÊ–JQCià6Y#!¼¸œ¸y3øµ$|Q¿QÛ²_Ä…üÏÎÆ‡;Ž“||§ ybÛÁ¨t_ËâúŽÒ"UÐÈn ’¤Ê"“Òµ>H»­¾›2*B_p²ÕÂoܾ<x_dêèÃ}-ËBµZõ÷5¥ôÚš„U¾®ë²,na@¹µ»’Îqœùiˆ2@Ÿ*E†'Úb.Kº†» C†ýËŸMï­ŒZÝ›rK6ˆZçÑó<4›ÍüïÞ×¾^ÿné[……M=°èjì‹l¥þÌ&íO”S¶½ù—ÇA»Ý†çyœšA[“°Ê£Ùì²ÒN¹dšÓ[,ÃTåÁ´Q¥S÷Þ$ËR•ÑIIsšW¡ÄMjáÀ™)×eNux¯k} ¾¨Ìðj™qzÂø}J-i›ÛTغ®‹n· ÇqÐét’ÿ= ¼õWoùÚ׿zŒŸ°öz=Ôj5è—mÛF¡PÀ­[·FnË*Yd)v·¿¢Yù1 ­&s´£Ø¶ÍBšrgÚÔkîu=’Ò«³hˆ¬.O4§IŶ,¹’øÞÙ>êĦý>1ùÌÏS }ÆôòVÅq˜¦ Û¶Ñjµ8äwÕô`ý»­¥w¯†Œ|ËüÞøÎwÎõr×úý>Z­ƒœ«“·T*NOOqûömìîî&ýö,¤Ý–÷sÎÞÕn7˜0O”b2MfÚv6Ƥm"NN¸ØeR·«â>*|e¨äJ†[–ú’É6,Æè¹¨ýÒ„ }àwŒæ$‘QEw»ÝNW\æ_Ê÷²ÆT˜¶×;å^±¸™ –eÁ4M@£ÑH×÷$ ²â;0y<ý÷L!-—Ç?<×U?Âò¼z¢*]èáý¶ xð¯özs¯ò~­Õj¡R© +/ • V*£P(àôôGGG™MX]WÕ1LÓ™¯wÕu¹Íe¬i„!«Š²"M$ àFÑ2xeC%en›ü@ß¼9š¤F%¤W&nE‹’":œ°6›ÍÕÆ÷"d"™D^.SÃØüEJµv{òTßUñ<;;;þV4[;ªÌ¶ƒÕªÃ‹<8N¼9ßÕj°õØ$^ÔïÚ`0ÀÝ»wQ(Ãáý~·oßö¯ÛÝÝÅÑÑÑØ°á¬8;Sö¹ ÷´¬·Mô—\×E±Xïi’}…‰2¨Û®¯t(pØ<Û°T«Áþ¢l¢D…N·Û…çy›ë5’Þ’pϨaLÖCtE^^'ÇqÐl6Ñh4ÐÈKÝ]ïÝ”•«ÕÉjQs¾åw§ÑˆÿÛ“÷ìZ­VóS@%vÀè^úíY5÷>Ù(ÍlèvQŸ’xF6ÖȲ٬HSÉ”ÒI½«'''Éï£Çé$´¤p•Ų¬ÍlÑ$›dZVÐ;NXùÛA1­»#Îqìííáìì,; …Emó Cëõ¹¢²½R½>ùMÍ鈞kÃápäŠ~¿J¥’‹$nÜPî#‡DNwM”BNÑ€3ø„ÛÆÚí¶?'ÝuÝñmdÏ8¢ š4Æ4M”Ëåù‡‚¹nÐ s}\wò¦ÆDk&¡¨‡r»ÝÆÅÅÅúcZصN§ƒ££#\\\ P(àöíÛ¨T*€çŸ§§§¨Õjë-(×@VX/—ìº,´)Êeoø~#‹çy~ïêTÜ_˜2,ª$-ísëv9ìŠRÇq‚ú­ëºðžŒS ëËOe„m”qgñáa¦É=()ºÝèÎÛ¶qÂ!Š”qáý²çåyLÓ\|X¼NVËfÙŸY×ô—D¥RIú¸–gÛøïzWt«L»­÷µ×Æoc+eV€Û¶¿wÏäuìäM´fábÙ²,t© Ù6·$ TÐ÷‹¿Í]¼GI²`Öc(AÅâò!(½«K ‹·¬`²‹ Ž0˰kYßou"×Åç¿Ìñóç-ÁrÕ“’S4¥£Žãà¯=ñD¼Æ©°e„ãŒöB-µv»ÍÅ5(ºÝèå5lÛ^nqÓä‚K”¸eÛ]×…mÛ‹Í]õ¼ GÕ0TW/p2/¿‹.¹.îÿÙ?üÅ¢ú…TïԤŕg¾EšˆfYþïO?8;VÊju4Ç\¸BošêÉXq¡„yÞäÞÕ¥V™ìÍFwJ˜,°hu£Ýn£Ñh,Ö»*uý‹ Öwrd$aíõz¸wïžùÖ­[¨ÕjIãb¯Ý¸ïЯ3 Õòµû¼à*Á”!2tìMozS¼°A†2β,œ-2iÞã‰ÖdRï* F,¼ß¤e1Æ)dGÉEX–ÏóÐXt¤À²“g)•®ªEï¹çžÃ`0¹ñôô¥R Ýn7{óZ]~Lo]‰3ŒN⺮Y,Cݵôd±8Ïõ:d(3<ØÛS åÀÕ¾ÚÀbóû¸20¥HT8zžo‘Ý Ôƒ¹¥Æ¢+{ž‡v»½¾ml(³ïõzhµZ¸~ý:ºÝ.ÇñÿºÝ.®_¿Žgžy½^/écO[XfîŠ ÷c¢ ‘ üX%ŶÕ_øWƒs›(CÂõ﹆Kº.W}§Têt¢Û —ÌFJ‰EGâ6›M4xuwiÑ”E•(׿sç ÃÀñññXA©_çΤ5¾«ZŽã8I ÑZù=¬a÷ï«äTære¬—!lÛF=n¥¼ÙdÂJ™²Ô‚b¶Í„•Raѵe(p¬!ñ®«öT­VÙ¿% øÈG>2õNûûû è÷ûIo<å2`³ ~ÛŽÞµ›(#üácÕêhe¥XT…xT/+QFÍU¡w].¸A™²p+‡SŠ,ºÌ\ەɊ½5/•J(ÍØÃQ毇ä7žr^œ‚Û0T… |¢ ™Ãó''jÈ c›2ho/øÿÜ•y&«”!ÞÕh€…ç¯rý J‰pûy\±$m[Å<§ðm•Ç=z”ô1¬EìÀ/—UKüÞ{¢(s\×^Á1 .´D™dÛ£akÛvüÞUî7L³ÔüÕr™Ã)5Êåù;û-ËŠ?ÝcÚ2Û”[‡Ã±ÕÃdÁ¥B¡ôñ®^µ¬¨ÊŸ2f,Yõ¼ñ†—V‹•wÊÛ­ô8Ž3ß‚Kl¤¡ Yjþ*QÆÅ^Ÿ@FE²wuë<^©TÐjµ&÷‡8::B­VÛøÖ6ý~f2=‰mÛñ†Ö†ªÜÄÙò†ÖÏ`_ýå¼Ã{™ø½ýeqÅjµJ¥ƒz½NOOñèÑ#ܾ}{e/ztt„ÓÓÓ‘ëjµŽƒÁ­VË_äÉ0 tXí4VððàÁúÞa]€@¶—2¡’2ArV¾úk]ýkB%o«ËÖÕuez®â¨h\=—ÜGOÛÑî¯/œY½zn¸quŸû¡ãu´ã*_=^ޝ}uLgWÏe_]–ó‘ÇÔ¯ŽÇ¹:žÆÕk{W¯]ÕŽI«_ûêr]»Ý»zͰÆÕëJòºüägžÄÿQþ?Öò1o*¾ÇZä›MÕúÈÆZ³Mĸ¾fÒÜ•yö°Îæ!(cç}«äqÓ¸ˆnt4´çß­bÄý]¨2÷Y】M•ߺ¥æ¯Í)‰ŸÆ²¬øå{§Ãc[êZ¥RÁññ1ŽŽŽ"·®©Õj8<<\iïêDZ»»; úpã;wî T*áîÝ»‡xæ™gptt„ÃÃÃØ¯á¥q;ƒ:T¢'ª’SýwÊÖ.MN L®\„¿ïz…âAaR¹ÎÛÃk8Èã‹* ÐýÊWç9­Tðšv¹ºœI‡§o¥R!Š˜œpê‰Z0pÙ·#ÎãÃÇ»J—ãÏÕåןx_½÷Õµæ&â˜0çi]CÊ$ñ÷_ªrÙEP©Ö+“Àhïw8 Ósí¨y¬Þ¨«C¸²õØ0ùîDUžå¸ôÇÉñÖCÇ5"B ¹¾º~ÒGãiÿ†ËЍD¿qþ>\½O¯|#=º•Je¡qô©^Ó†2K[aSñ „bÜ0Vßú(=¦áÄ,ªb®pNj8 ?6|Ÿ8yÉ"•ݨ¤Ñ˜ð]¸¹HCIœ†¦"KfÂÇwõÚ¯œ¯/a]wŒ‡sÓ¹æ¯ó7ÜHüÈ×)NBç3Í¢¸uúÏkަ”m²ü¶m£µÈ¼<Ûæ\mš[1>É\Ãi«=žÔ ËøùápˆƒƒœŸŸÀÔ/Å´}`_yå|üãÇÁÁUÁI½'†RáüüÏ=÷ÜÊ`¢¬:¾àÕW_y®±Vyïéë<!vÇƇ½Rêàå—_^ëk¬» ‘ÃÅ\WÍÙ^•"æŸÇI‰9::ÂsÏ=‡OúÓkyþM”ßb©ù«á¡” R~ËÒuØTù=‹išñVæb’¹!uðyËïksÝ{ƒö÷÷ñì³ÏúcæK¥ŽŽŽ°»»;õ ñèÑ£‰[ë¼ç=ïÁ>ðÈÂ\­ñ뤑¤TØÝÝE©T½{÷VþÜëŠoxòÉ'ýE€ «O#s…'MïÖçdʼË:¿t||ûlì×0 c³«ŽéËûK!+*+C[eñ ÄÜgØ„ªxˆ¿ò'Ñ ›Šq1¶egË®ÛP•J»<:UöµTÐ…‰èŠ7m¥MǶmÛ‹­·áBí»]¯uùJ<˜p};¦9w}šÛF“¸8u¡ð1@}§%O’$\:äŠÝ}AŸê’_™Ú"Âí\.‚$U¶/³¯/I¾lw%m T£@U{Žú”÷TöÏ–ç“$Yê‰r|‚íÉL ý‹mà+·éŸÄ4MÜ¿£ðµ,®„M€kQ‹¬Ûáá!vwwý/J8®T*xá…üÒV•,¯ÍTK¢U9ઓ[lñí÷°Jë¹¾§ õ#/ñ˜¡Ö_ʆM•áŽãŒ÷>MÚ¾ÉàÚê¶.‚!Œ;*ñ;P7e¨ûDíkK[mÓõ“¹Ö6‚Äìäª/ 2S_dcoŸ²ªRñö6FÆ:¢G·…óžFŒûDm5¦_çA•%ÒÓ+ŸÑF÷'—áÕò{­o£%Ëò{Ý:Ÿêàx+’¯ƒKý%ÖÈÇáp`À*ÁBö|d•½ºk%+Lê…„­·‰øþö7|»ú‘{‡M¨ŠBA¥œhM6ãžçWè;¡¤ã?r ¼ëoö‹ªçI†Cš*—áJl\TŒ"mª~Ù 3‰$>÷1š ²ó)YáëFèrœÞåâíï½BIÖÁçÚ{Õ¶““x÷¥\{<<NV Ë4óí5¹ÌëtÌÛ ÚÇqð—ÿð/pù‘”ž}&«”®ëâ­üÇÁ<¦(Õ*°ü`AݯÑPß ™Ó:©q¾6.R¢æZ Rzð8" ÝøÛ;“mÛñö^õ<ö®’ol•àçŸ~mû÷mTxºuh‚? ”Ïóðæ»om•eK;åŒëº8üØÇ¦'¬€JJÿëïS-ñÒ#{ö Rª¹®¿‡ÕÂÕ¢†¶ÖÆ·µÙéAÍ/]¶l· æ>™W—M¨%Ý=°BD‰ø/¿ó¿äv”{ßù‡ˆá{ß;{…Ȩ¹¨œŸJ)»‡U_Á¶ÝV ÑeÐ\É4ùLXU°Ÿ XtcRÒ*û•ÙÚå6TB*“ä«P­õÒ›Õ€šG•W)!ç-‡[&Qî½ë7~Åwü?UÃcª¬&Ê Çqâݱ 5åöÕ>Äqö®$J¡ØÃ)›ô­¢Õá'ÛkÉßð¾Ã÷ÍýÔ‰-º´1-¨äUV‡ ·¸{æ¼ÊâFè¾ìÅ¢´‘eø‰r¬ö¹¿€o*Vƒ-ãÃd+¢ ò{W=O œDÖ&ØksÊ,Ïó¢Ò£õ’­•d”†¾Õ :ç¤íL s¡F“Êeïê>²%“Þ XEðÛlat!Zyœìo|õ/?ñ2po¾ÓÈ ¨TÞà"‚%Æ[Po Þ ¬á´Ê;ÓÄÿ÷Í}ìK£ãMS0Û6eëºê?²ÿe«¥F„·– "LµÀXÜEšˆRf®áÀ¦9y ³m&  ¼mÉ&ä3‚Q 2QßúÐDtJ¤/Ø©'˜òºöÕíuLΛÂíi“ƒ,°¶ï5#‹, ‡C„¯IìÙº2zÅÆç6¥™mãÞw};öå´U¡wÁD•2Ïu]üÝ?ùµ êýó`4X£kcXþóÿüT¸?éÃ&Z˜mÛhµb.ü" kž8’F:îÑt´ûJR¨÷`î!ØÇPÉcG{Œ$¡úÛþ½Œ³ÕRx_‰ÿî^Ûßß»2ûŸ.ƒ•"¢ôr] ?õ)üÅÂ\ׂú1>§iPæ}áÞ=Üü£?Ì2ðõïUsS;e5’@ß} ÀüoUbwEa¢r'Þ"cív¶{W-½šÀhòy‚`ˆ?0Ú£i@}÷§vxíœê„ÿçеÃÃ䈈(`Ûxý»ÿ |ßËß7z=)'¾é_ÿk|ý{¿Wõb”€õ;jXpª—ÕÀUÔU«?xô!-̶íxÃ=OÅ{ÚFx憵¡zK;¾·g˜>’3<QŸ÷I‘ò»J0eS£÷«ßñ0é#!Z‹·½þ:¾üý߯*­õº ¨U}HÏãBK”y¶mÇë]ívÓ5šÀ††{ê;yj׸š[Ž`çI8eØ/­Ô5è÷û8==Åþþ>*•ÊĠн;Ѿù³ßŒon|sÒ‡A´ï~é%ü¹w|B](ÕbJŽ£þ•aEp‘%ÊÛ¶qq1c/È4ô®ÊÜR}a¡Æ ¸“Ȇ=nÛ6žyæôû} ÿ†ÃÃCܾ}µZ …B/¾øbÒÇJDD[¢ì–1|ï0éà Z=ÏÃ×¾ññMßôMÁu†ܼ©æï•ÁJ0å†ç© ¯8«×4‰ÞUªÇTúãdh®|ÿü¡ù}*mÌãwîÜaøØÇ>†R©äßP©T°»»‹ããcܺu Ï?ÿ|ÒÇJDDÛÀ^¹öJ¼!dDYcÛø“¯ÿ_Fç¬5Àå%ÐáDmÊ—XÛÙ8`Ûëjh¯ ëµ0Úƒ*+ð2!MLJÃ!>ò‘L½ÓG>òœžžb0$}¼DD”w6ðÛßôÛ³[䉲Èqðç.ltÛ¢œrgvÂZ­ggñžpQ&Ô‚fU¨Õz\ýËÅŽ2áñR©4Ò³ À,äö‡¹­™ü£7ý£¤‚h-†/<Ľû³ìÅ¡­{…àUocã@-˜$ ˜5 Vï­ƒCî3èÚ£GÆ®<>>Nú¸ˆˆh[•·}çÛ’> ¢µxí{ÿ[¸ü[ø‹øËI ÑZÅÞ{uUÜ«?ÖÛ{Psâñápˆ^¯7õNr»ÞëJDD´¶m£œÕMã‰fxôoáÕ¿òjÒ‡A´v#óWÃ;8ŽZx\M¨¹©²ÝLLVsäñJ¥‚££# ‡Ñ«1‡C¡V«¡R©$}¼DD´8•òêú›ÿ¾ûýßôa­?µÙT7n¨=‡ØÛ[>aÕÕ*Ô¼ÔFÒgMëpíöíÛ888À3Ï<ƒÝÝÝ‘¤ôÞ½{8??ܾ};éc%"¢-à8VÊ-×uß´\×E¹ÙTóSïß\Wm_ÓnËÍ[m#Xå÷$é3¥u»V©Tp÷î]œžžâèèhì»»»Øßß[˜‰ˆˆhªÕ*‡SnyžÇ-›h+”Ëeàä$HLåòɦ‡`~*wÚ×µ ðíÛ·qxxˆ~¿ïßX©T8o•ˆˆ6*ÖŠ’DU¯s?Ê?-‚U5>:PÃWlÓÜ*×ô …BµZ-éc""""Ê¥Fƒ“ì(ÿV>ô½5ô—ƒ¶ÒãIå‡ëºË–qܼúLV·V"""""Z™où•_Á;¿üåÅŸ  `\P‰„†-ãÇ<@å¯þÕùèA­ì¸5˜¶{X‰ˆˆˆˆhµæÃêAí©Zp&«äcÂJDDDDD+ñ{?÷søô{Þ3ÿÛP+·’>J &""""¢•øÆ¿ü—øÆŸûsó?óUiö°ÑJ\û·ÿoú#Þe0ÑLX‰ˆˆˆˆh%žøüçñŽïû¾xwn¨'}Ä”vLDDDDDËsüö7}ŒjÌMS9 ˜b`+-ÏóÐó›gßÏ`'}°”LX‰ˆˆˆˆhiN±ˆ_ÿþïŸ~'@@ÌNX"&¬DDDDD´4×uQ.—§ß©  î³J±q+-­Z­NOXÛÊàBK4&¬DDDDD´´©Éª5oõ"飤¬aÂJDDDDDëãBõ®^€CinœÃJDDDDDëS†JVËË>m#&¬DDDDD´ÞÕ¿LViALX‰ˆˆˆˆhõ<7“>Ê:&¬DDDDD´z€FÒAYÇE—ˆˆˆˆˆhõŒ«?¢%°‡•ˆˆˆˆˆVËJú(/˜°ÑêxºIåV"""""Z.8˜V†sX‰ˆˆˆˆhu,÷“>Ê ö°Ñj˜êŠIå{X‰ˆˆˆˆh5º.’>Êö°Ñò,¨¹«å¤„ò„=¬DDDDD´¼:¸Ø­{X‰ˆˆˆˆh58w•V,õ k¿ßÇ`0Hú0ˆÖ‚ñMyǧ‹ÝÝ]”J¥¤#†Ã!=zÄó]òù’:—I&Å7üÓúOGZ<ó®ßïó|—|¾¤° Ÿeøjž/©s™dR|³üηu”ßI½,¿gcù½šç›G*Öi_ÒIoV¡P˜XÑÏ#žoºžo‹Ä÷¬ÇåÏ7]Ï·ª×fÎóMãóÍc‘øfy–o,¿YžåYÊïTÎa½~ý:€Ña ƒÁ`kZ2(ßß”wŒqÊ3Æ7åã›Ò(• k©TB­VÃùù¹mÛØÙÙIúЈ–Æø¦¼cŒSž1¾)Ïß”F]^^^&}Qúý>P*•üIÞÇÇÇ[ÕOùÅø¦¼cŒSž1¾)Ïß”6©MXŒ¬HU«Õ’>¢•b|SÞ1Æ)Ïß”gŒoJ“T'¬DDDDDD´½R9‡uÛôz½‰·õûý©ÛSôûý©{fͺ}Óf~¿<œ/)“by9_b>é~y8_Z<¾³øY/ßY<_bù=é~©;ßKJÔÇ/Ÿzꩱë_zé¥Ë§Ÿ~úò©§žº|ê©§.Ÿ~úéË—^ziäqúЇüÛú§zìy§Ý¾i³ÎG÷ÜsÏ]~øÃžë|Òv¾ˆŠñ¼ÅwœsŒï|a>Ž1ž‹Äw?ëeâ;‹çK Ëïqi-¿ÙÚÁ`Û¶Ñjµ"o?88@­Vƒã8xñÅQ«ÕFî{çΔJ%ÿö~¿£££Ø·oÚ¬ó½^§§§c×gí|izŒç-¾ãœÀøÎ–á,Ãól™øÎâg½L|gñ|·Ëïì•ßLXÒëõF– ß6qxx@m°»¿¿Á`àw·÷z=ìïïû·ïîîâââfޞĹN;1Ñn·aÆÈã³v¾¤LŠñ¼ÅwœsßyÃ2œexž-ߟøÄ'2÷Y/ߌílbù½ò› kBvwwq||ì®R©Œ-þðáC*äÿ•Jeä12n|Öí›6ë|Ä;w°»»ëoZ¾oVΗ”I1ž·øŽsNã;oX†³ ϳEãûK_ú’ýþiþ¬—‰oÆv6±üÎ^ùÍ„5… …ÂÈâƒÁGGGØÝÝE©TšÃápæíi;8??Ç`0ˆ,<²v¾4]Þâ;Î91¾·KÞbœe8é¦ÅÃW¾ò•‰Këg½L|3¶ó‡å÷¨´œ/Ö‡8::Â?øAÔj5ܾ}Û¿~’Gͼ=mç3 pzzê_Žz\Ï—¦Ë[|O:'Æ÷öÊ[Œ³ ']Tççç( °m¶m£ßïãáÇ~ PÏ—¦Ë[|O;'Æ÷vÊ[Œ³ 'ݤxÈêg½h|߸q#“çKÓ±üN_ùÍÖ”jµZþ¸óp0Èør½~0ø1ëö´Ï­[·F†+„eñ|iº¼Å÷´sb|o§¼Å8ËpÒMЇ¬~Ö‹Æ÷;ÞñŽLž/MÇò;}çËÖ²mƒÁ†aŒmh\«ÕP*•P«Õp~~î7·m;;;0óö´ü Y [KŸ¥ó¥éòßqΉñ½]òã,ÃI'²ôY/ßY;_šŽåw:Ëo&¬)$ËLŒÝæ8HþrÕ…BÏ>û¬¿Y·§í|fÉÒùÒty‹ï¸ç4MÖΗ¦Ë[Œ³ 'ݬxÈÚgÍò›t,¿Ç¥á|»¼¼¼L䤥 ‡C?£ºógÝž5Ûv¾ÛnÛ>ïm;_Ú¾Ï|ÛÎw›mÛg½mçKÛ÷™'}¾LX‰ˆˆˆˆˆ(•¸è¥V""""""J%&¬DDDDDD”JLX‰ˆˆˆˆˆ(•˜°Q*1a%"""""¢TbÂJDDDDDD©Ä„•ˆˆˆˆˆˆR‰ +¥V""""""J%&¬DDDDDD”JLX‰ˆˆˆˆˆ(•˜°Q*1a%"""""¢TbÂJDDDDDD©Ä„•ˆˆˆˆˆˆR‰ +%ʶmxž—ôamܪcßó<ضôi­V"JÔÎÎÇIú0ˆ6nÕ±ï8vvv’>-Úb¦iÂuݤƒhíë›Å„•ˆˆˆˆ–fY+ñ´ë›u-é Àu]˜¦9v}£Ñ@¹\´ä”Ëe†Û¶Ñh4üûÚ¶í«×ë¨V«þmív­V ¦iÂóÎaM‘v» ×uqqqá_7kËv C†ET%†(IQñ= ã›ò`Ó±/ó§šÍ&”øâ¿ˆ/~ñ‹<ß%žïßø~ög6éS‹í'ò'ñ]ßõ]IÆÆlÛÖ5«>_ÇqpzzšôiÅÆ2<ßÖQ†?ñÄø©Ÿú©¤O-–ßù¶ŽòûÎ;(•JIŸZ,,¿ó- åwnÖ?ýÓ?Å·~ë·âÖ­[IÊF¼üòËøêW¿Êó]âùþàþ éӚˣG¶æó€O~ò“<ß%Ÿ/KX†çÛ:ÊðÁ`ôiÅÆò;ßÖQ~?ñÄIŸVl,¿ó- åwnÖ7¿ùÍx÷»ßZ­–ô¡lÄõë×ñ¾÷½ç»„áp˜ôiÍå[¾å[¶æó€ýÑåù.á-oyKÒ§4–áù¶íe8Ëï|[Gù](’>­ØX~ç[ÊïÜ$¬Û¦T*ef¨Ï—±»»›ô!ð|im¶­LÛ¶óÝvÛVžmÛùn»m+ÏÒp¾'ý&EaÂJDDDDDD©Ä„•ˆˆˆˆˆˆR‰ +QŠx`Ûê_"""¢mÇE—haž‹“o·mõo¹¬þ¦=O· 8Np]£Ôëê:Ë Cý9Ðn«×=9}}ÏS·†ºì8AÅ¿ZU÷5 u]†V‹§¸®ú7w®ÜqŲFcPñ#ñlY€iª8m4ÔóJ¬ ÛVÕªºŸiªÇÉclØÙ‰>ŽrYŸ®Û YÏ=—‹ õ¯iªãþú×ßœôÇ@DDD´4&¬9Ôn«;à:©¨K麪BÜj©Š²ôêÔëÁs¸®º=j/lËR÷9;S·›¦ªLK‚ສr/I¢Tðm[UÔ«Uu½vTÚõÞ%y< wq¡··TÒ â¯'¬’@Èÿ»]õÙk>UG}Åb?«~þ¨X³mõšrÛÍ›£·K,‹*†›žÄG·«â âCîwÿþøkJ\¶ZÁuòý‘ïHµ:³’,Ê{d£1Ùh¨?aÀåeü÷Hä‰nµª>›ŸÿùÕ~>DDD”/Žtö”ËAC»tI]]HCy¸Ó(,ÜA ô:Ø<˜°Æ¤W¦¥ç¥ÑP®þ¡HoŠ$k˲mõÜRÉ•¤ALÛ®“Êy½>šðí퉛ÞÛ)•|@Uèà>Žzî½=u.’dŠjUUôåñR÷<õ•ÌHE_?¶rxð`ü¾ò¼Q Œ¼žô¶Jb~v6úºzb ¯-z½å?›<ÑÐv;è‚«ZUïu±ô.ê ’ ùÎHo¢|^ò<ðØc£I—$yõºú×óÔóV«A,„LÛïÅ—ÄUÈqLJ²ÃÇN,£„Ÿ«Zï]ÅçÒíïǬc’ã€óó/¯ö`ˆˆ¶˜Œâ’ß¹¬“ßÍz}rý%ŠÞÀ^,_ý*GÈl‰ A%ñK¦äÅ¢ª„ó©Ïé÷z}_+Br¹=œdº®ê<Ð뀎ÔvvF_CÇ„uM\7è¹ët‚‚ªX­dK!•ßr9ÚêºAÅ[†¶îíEW õž"ýy —PÏÕ¾®¼GÑ{c…a¨dRzO¥0•÷!Šþ¾DÑGyÕé¨ÏF’ÖU÷øm‹v[Å”$üQ±Öjö>ÆIð¤w\Õ»(4@0ô{š8…߬ûD[èå QôJù¬ï‘üVÈãôߢi Wúã-+¹Ðn«ç $pà¿ûï¾%é·†R.\Ò;$ödDšt@Hõ;(õ8iü”ŽTþ¥¾§?vgg¼ž"¿;Ž43a͉=†Â ø"\êSŠ$oÐË:i—XÒëÿÒ™¨ç»y3(£[­èú\¸î%\ÎG%¬r?=ÒŸwõ)&¬SxžJ*;ÑD+œJàè:ÑLy>}hkTÏbX8Øâ$«'I‚$3á šO£ OƒE[ßòjÖ åǤ²LŸæ ݲ¬ 1 Wž¥ò4‰$—ò½?9QÏcÛê6éÑ—^~h6ƒß»ð¨yÍE®„4ÖÊ1u:“óz½/áÞ½Í}6´Q½’BïI’‰é) âr]»Q¿³¾O@0"M-Ön«ÊÿÅ…zþfSì ¢™ÖÀ«?¤.9é8åuu…Â6÷¡l‰»¨˜Ð;OÂSê$ùŒš¥—UºEÊA}”ä$24W:¾ô‘eÒ% þ›èÀÑ_c¹ Ö)ÚíÉ?ÌqèfÜž+š>T”æ#COØ3M´y2¥C~öö¢G¨È0y è…‘ûHÒ*½9zFî#ý““à6ÓTú´!kH¹®XÉëYÖèð¯ð”Œ8ºÝÑ™Eki5ÂɤLy’ø“Xêt‚Æ ©ÌK2)÷Ô“LN$õž$=^xõ§fSÏýûñë\Qõ‡NG}?vvÔ9Å¥E’ ùN±1v½LS½×ú(Æz=è@Šš>Œ–òX¡'‡“lªC§\ž‹yŽ1&¬úœ¦¨ÞYIg½¬x-ç8«7wyïêuõžñ÷vsÂu}­ `t É–Ê¿(—ƒùõ“„<ŠÅxŸó"ñtr²ºu$¦gír0Mµôβ1fµ¤‘DÊX}7 `|cÜÎðˆIvˆ¤Ö –_I”V2W`ŒÓöÑ{w¤‡HŽW¤õ¡]á^¡ð‚áVz`zåy“É™^á'‹’÷e™­–êÅŠZI’VGQ\7h™µP]”på}™d. –í­’•äiµ\7XT†‘/ÚhFÙÁ„õŠÌ11éœ7Fy$=Hi—L´.ž7¾çm¹=,6ʤÊkxAŠI T¤Ešz døž ã¤Õ‘…`dy½>Ú€Âò3˜D­ŽÌÍ”r›¶ Ö+²uDZž!Z5ÙiÒP@¢<“U 94/]dnˤÕi6U4L2i¢¬“9©ŒçmÅ„õ çÎPÞÉ/¬Ò6‘ù›\ -ò>¬4 ,ç)YØòãñ¤ i¦ÉmQh;ÈÊŽDÛB¦zLÚFƒ(/¤ `²JùÃGbÂj²Å&‹Ö@ç2ik¢<ó>ÞT¨¥B»­VæÖM´ LScïj6DMu¢hì]¥°­MXg½Ã¥‚ l&)ìt:~åœ=2$,KUà§…Ÿiš#õz¦iâæÍ›~Òæyžc@ЛÞh4FK$¹œÕ`"#nÞ¼éÇë¤Q–e¡ÙlŽôþ›¦é/—Ë~Ï­ëº~²)Cëå²~{µZõ“`I(…žÐÊñœœœÀóög±¬$c\4›ËWÞÇñ{µ¥2=O9®W²' çÖï#ÿ—é«^ oÖ}¥¡%¼ø]œFP1!kL»¿Tê‹Å"nÞ¼ Ã0P¯×GF#è÷•cßÔjµ Ó4ñðáCüøÿøJß³(iˆí(Fóô®zž‡îÕ’«úç$ï½>2Fè庾@¢ž°Ù¶=VnÊã<ÏC³ÙôãH•Ôù|…$zzÜéÇ­»¾.‡Ü®RÑcß¶m4›M?ñl4èt:#‰âèû|O¥rQß¡¨× ?ÿÁÁÁB¯·ˆ´Å8UŠ’xÂztt„~¿?2tm0 Õjù‹â†1RX-˲ִbªëª'/ñï~ù—aœœ¨_Û–i 'íöøsxžº¿T2ÂT'xœ^ñ<õx zÓÍpÅÙqF_Ë0Ƴ©8Ë&Xår0¹ÀuÕåð9Ùöè:ä²³V™Ž<¾è÷UŽ»Õ/ÉÚmõüWÉŠEõ'?€Ž¼öÚØó}Ïá!þðé§WûùGH"¾uŽ3}Á%Ó4WÒ°²he;n‚{rr‚f³‰½½½‘Þ`£ZnÞT'jšãt]­ÖxŒîíñbÛ£q_.«ëñfš*îõû_÷¿ímÀÿ0ðþÂø1„¿wò=•÷,jL_µªî•ìÊw<ª¥=æ=JX“Žq9íVk¹}úÚí¶?L]zäÇA»ÝF½^G£Ñ†­^×óL€ÑÊ}³Ùô×+Ð{ìõûHEvooodƒ$€úÐty]y¬>Ô\^_O:dn¿kx¸¹Ð_gïj#Oyœž(Ê úô8–òZß™C×Û‰&¬½^§§§¨Õj#×ß¹s¥R wïÞÅp8Ä3Ï<ƒ££#.ýš’ç-U6I•úvgjå6•Úíè^ýUá°úØÒ㮫:Ëã¶Ê›¦é÷ȳa8;;›ø=½¤79(—˸¸¸€iš¸¸¸9–Y­Õó|‡ãÜ7Üš.ç¿îuÒ$ ±=ˤ˜—Eež¨Äy«Õš;Y¥üJ[ŒoÓºœQÓBø[Uêó¦'•×zë¾H£$œÒÓõû!Ó¤ô))ó4BÎbš&vvvüF_yniä8>ó™ÏÌ]÷L,a½sçvww`d?̇ÀÈxúJ¥‚Á`°’×ûKáyªgR>Ìz}f¥–+ÁQRñ­“Û“H¯RfÈðzŽJ…4ĸiÎW¦w»]?!œ´RsR¸š:FG •ˉ5^¦!¶£HudRÛ4È´Z­µl!GsˆšÎ!S£¤$Ü€ ÓNüŸ×¼èRZb¼ÝŽž–zR©O[žGÉô46_X–*ìçn`” ¯s|Àú¢”>çççøèG?Š7¼á k{þUÇ7¼úê«888€aþÍ4³†IF-¶”Zž§VÕÉÈðå¤àå—_^Ûó'Q†G™§ÓOh¤¢0k±/ÒÈú @Ð`5}Eo%sœàO†éãº* ³í`y¼M19::Âþý¿ÿø×þ°â^Ÿ´”ßQöö¦—éÝn—‰ê¢&M‘ø ¥÷oÔïÒ´5Cdm ¸_Ôy5íäàà/ãxrÂbHËJKù-oMÚÃU†ÝJä¤íê€`.¸a#‹kÍJ@3Õy°$©ƒ¿õ­oëqOXƒNOO'Nà‡ûèÑ£‰_–÷¼ç=øÀ>0qÈ‚i.¸‚¤ãÌåÆÙ¦‚’³»»‹R©´–;Ößðä“OÎõC0­ü“A#I3¾e©ÊãÉÉôžŽnW}ÁŠÅÅçyβ³³Ø¼è-u||¼¶U&“*ÃuRŒû/ó0ïç±wÞq‚dˆ^/!<–¦ÅµÒdÑ:øÆÖóós OÁ~¿‡âèè»»»S¿ ‹.­- µ åsf¹¼Ý’ˆïI¦ý.ëû<@*œ†¡†ÞF+¶mÕÛY¯sºïß]ÓŒ^9:|Yïyi4ÆÇvÊk˘¡ oEÑÒãÍæ|Sò»Ýnì=?ã8êû£/’µB¼žœÚvÐPT,½Dáó”ÕeÑ<`v’(½FüÏE¬ŠÅÔŒLCl‡ÉG×éÌ^@oÓ[é­LÔ’úõQcFå»"±)½ ò&5ã?€‹¬ã‘¢ø\…4Æø&É¢@úŠê25¤Z­N]Ï€Vડé-/¿Œ7¦}Ñ¥[·nM½ýúõëT+|9ôÿ/"ªþ<ðþpÓZL¤•“¶SñÅuUEgÒïóȰuËòW¸Fµªšñ¥ÀŽŠeIfe{ù>LZŒ Ty¾pE8j¸•¬J],r(pŠ$㦽Ð$ÒržÚÞU}DC§3½aFVhÔwCÿ®“+Ö‹.¸·e’Ží(Ž3ûã“¡‡©ŸâÕ˜"ÛôéÛÑéôa⺴ŸkJ¥)ÆeÀºÉ¼RÙÂK¦†lÕˆ„eMk “ΩOê®Fí>ó¼)í‹.Õjµ‘%´eü¼>Œ V«¬HfÛ6v&íÑ9ƒŒhZ´ls]{{{~Ë¥çyþÊjõzÝOdeõ+ÏóÒÿ£Ak³éøžfZ½wlØúÅÅ|CæÙG˜=<*êµ·hUÒ,I:Æ»Ýùò/éyJ¤bbYÁÐÚðöKú~Ú†o{&½·'G½>i‘tlG‰jË “­§ï;?édÂó=e›>Úˆ4Åø:毺® Û¶GVÚ•ý…×¹Q¦yžúÒG9Ȱzé5%KÊœðH¼i£r®:9^íõðú:‡÷z½‘@ïõz°m…B·nÝÛËiQ‡‡‡888@¯×ó'y?ûì³ =—e-×»Úl6G6tàï-Ôn·ýÞÔyƵÓv[e|K9M;mçÛ¶G+7YFF©µÊ×ÍÛ»ªcn~¯aâày“瀳¢žIëŠí(“¶GÛxŒËbZá0Ï0rJMŸ뮶ÝMßS{Ý+í¦–>¼^ŸŠåyACRx´‘ç…|o£Õ Ûp#Y¬„µßï£Õja0ø+^Ù¶V«å8==ÅíÛ·ç^ý.j‚v¥RÁ /¼à/µ½L"¼ÐÊÀ`Y¸÷…/ÀؼÙ~`ë·  ™Öߎ¬„r¢Ê˜v{úZ[§UZwŒëLs¾oe{ 뽡Ţjm?§ô@H·A«ÅÆ ŒÛdlG™µ—6ûŒµ6–»®š8.4©2›àVD´˜$c|Uƒ¨dä£ëº¸¸¸È’êyªÒçºão¢¾6Hø{:iô§ô ¦\¬„µÕj¡R©Œ¬*vzzŠJ¥‚ããc œžžú“¶W¡P(¬äK²ðg`Y¸ó›¿‰“ý¯Wr>DºUÅ·tÒ¸®Úò˜=üÛ.Ñ&¬*Æ…´ÆÏS1Msù…hnß¾í_·»»‹£££±aÃYõÚÅ*Í&‡øRª‹ÁZ2ÊcVÙŸ¿µ0QJÍÛ,ûæ-µ¦€ç©žÓV+h©ž4 ŠÉ*­Xœj×¾ Ø² Eð<5heÞ°j·Ûþ(±V«•Ñb2*•J*“T]Ô¾Ñq ž^¹œ½/mYÀmþüUYŽÉ*e€L¡›gÄ—išÓ‡ˆY–ªŒË<ŸpË&W㥔³,ký ëQû™-)jkÝY]ñ=ÊÕž¢#ÿŸ´=·æ[ÚÌ„µR© ßïûIêp8„mÛcsU{½€`§4X´Q|ð뿎o~ú餟h¦yG¸®«æ;ɪDà8ó…«ã8¨V«Ó§tt»ãû˜êøý „íìLn¤q]®ë®H$“UJ‰Tì§^€Lÿ~‹óoH±ÅJXkµ°»»ë/s-à ‡Ã!îÝ»‡;wî V«­uíMy×ïþ.Þûk¿–ôaMgÕñ0Y5ŽÃL)3æ Õ™ûRÊŽõ¬XPJÍÚ£r% Š…É>iõ:¿´Víö| îŽã¬ø{˜| õ×,—¹øXBs§N§3²×íÛ·Q©TÏ?ÿ¼¿Šp'EË"»n°ËÀ<þÿãÿˆÿðíßžž!D˜æ|C‚¥×éê{(·,Ëš¾rª¬zJ”RåòôQ„3c|^–ܼ9ÿdq¢99Ž ·yÌl„\åÁu»ê»°·o©nÚˆXÛÚ ܾ};ò¶ÝÝ]ìîguÑ…´>ñK¿„¿þ#?’ôáÍdšó {÷{WeSi¢ ˜wñ¼™©€°Á†2Ê4Íå{›l[}õ)ü̃I>Ñʹ®«*òœ¿JbÛóu†Ú¶=}¨¤irÕSJ½v[Å}¸ãyLÓÄÙ2‹¸ìì¨Êx¹¬~ Z-öªÒZÉèÚEFÓú‹E®ÃÍ›êKÖhp릔‹•°áôôÔ¿|zzŠýý}&}ü9Îüu’ 9 Z’4ÎÃqµ¢d·Ë…4(3dg™8bí½Új±åœRoR¦ÛíÂ0Œx{Ä»nôzœƒG¶Ì,¤µÖÍ“^ĉb‹5‡õôô»»»þH»»»8==Ûî&Mf-XE&u¥ãÌ_çv]W !«×ÙÃJ™1Ï>Núœæãy€aàŸYüØôÑÅS­¶ Çq°··‡û÷ïOÎî8ø‰J¿æ8ªþµ×’>z¢•r¯Vfš8Ø49—R­Û *öá ¾Lé˜:Ü]bœ=«”"ž·xH.4˜[ÓäÖÌ„õúõë# .‰J¥’ô±¯†mãµËKÎ{¢l©VÇwµšA·Û¸©ökÿÉ‚÷Þ¼© ræ”!7nq¶Åž:Xzž¸¿6¥˜aLž¯mšæìŠ;÷¦ÚÛS 0‹.„:u‹2;ÏFš­03a-•J©Þouþ·¯}óû({ÊeüÖ/þ"Z­,ËŠ®´{^{í5Æ7eÒ<óW'—ìvÙ»J©W­Ú¸y³‹‹‹±Ñ23+îD)$Ël,Rý˜9ØqT6|vÆ}å·ÄÜsX{½îÝ»ç_¾uëjµZÒç1ÊóâïRìºø·ßøŒ8é£&šOµŠïüÔ§Pø±ÃÉÉ vvv`ÆheÇuñ»ozVʤ‹‹ÑËÍfNg$ÆeeàÈQ2œ×G)纪bïº6ªÕ*nÞ¼‰³³3¿Ì޵ØQ u»‹wüOìyLV·Pì„Õ¶m<÷Üs #ןžž¢T*¡Ûí¦g˜°ëªù†áo´mÛ6l[ý ´Z­à‹àyø\?à ڔ5†?ù…_@µZE±XD£Ñ@»Ýi‰w‹Eüݯ} X¨SÆ9Ž˲P,G†¿ïíí¡5©V$½«2F)eš²Ð’‹V«…F£½½=¿Æq\„[nˆRNzW©Z»®;}TÁÎŽÊ„Y¯Ù*±Ö^¯‡V«…Z­†|ä##­¶mãüüÏ<ó ŽÓÑÛZ­ª¤ÕuѾÚü©Õjáìì ¶m£Ûí¢Ýn«ó¨VÁÙ«”IÕ*~îßÀ_UÆ[­nܸ1²¥iš“+óD)fšª(—:‰mÛhµZ~ã£a~9>±н«”bú€n×ñ{Uïß¿Ïóâ­­Ñn«FVÞ)E–é]Zoi6UÌ=U·N¬„õÎ;0 ݈ ÀahµZ¸sç>ö±%}NJ½X\×i”ãu´kfnÄM”FÅ"Þð]ß5rU«ÕB·ÛÅÉɉ?ºà›¡ ²íÑ:¸´¸×ëu¿WÕ¶mÜŸ”zžZdŒ½«”RÒQŒ&§Åbqòªïa–µø¾!Dk°LïªÔ["ËuË ÊuÚ:3Ö^¯‡Á`€Ÿû¹Ÿ›z¿ýý}<óÌ3è÷ûé\¯{{p¯’Ò0Î飬sg¬RÓh4ü^VÎ}¢,sÝ aõT²Xä^|”ZzG‘m;‹ÕI‡=«”:Õêâ9¥,9Ö`ãyj4GÌl­™ k¿ßG©TB©Tšz?IR‡ÃaÒç¤”ËøêW¿Šx×»’>¢µ˜4dìääívŽãà·s¾Â7å—ÞÖhÛöH㋬CÀ†GÊ¢v[ý+£¶m/¶µže±Q†Rg™fºÝntC¤m«á1³µŸu‡B¡€G%}œ q ûߘ|µ4_Ò‡I´¿’ã8#×W‹Õëu¼ù—9éÃ$š›ëŽni# æé˜¬RV…{ \×],žm› +å†leÙxS¯sÞê–›™°V* ‡Ã±ÕÃz½•à¦ÅÙå%þÒïÿþä;ØöXeŸ(KÊå²j®·¬‘ëONNÔ¢ŒoÊ }800ÞÃ:Âó‚ISr™qO)å…V‚°HÏ,Q MÝʆ¶^¬„µR© ÕjMî;qtt„Z­–Žù«W~÷3ŸÁkÿÙ6½•à (£çjÞÓɉJZµ1”årYÍa/emE³ç“ÈÜ&IRMs¬‡(w8˜rfjÃ$m½™ +ܾ}ƒÁÏ<ó ÎÏÏýÞÖÁ`àoi3 p˜²ùr®ëâ;þù?ŸÜÉ (Ã\×UIi¹¬†Ê4›á;$}ˆD ét‚-¢†(—U£ÍÞ^°7‡ŽQFÌŒïIg¼«–(£&ö®²CWbmkS©Tp||Œ££#ܹsgìöZ­†ÃÃÃTõ®ð·­™rö°RfÌóhµÔ –TbÂã*‰2hêò¢ZUYîÎŽú?‡IRF8Ž³Ø‚KAC921aÝÛãÊÀ f Ië`0@¿ß÷·¯©T*3WNÂÌadDµ¥ Z­Ñ„•('bUè%R†¸®»Ø0Hî½J9bY–ZwCÇQ¤‰° Ùâ&Ü2Ñï÷Q«Õ’>'Ù³ÏgÛê¯Óaï*eZä–6†1:,ضYy§Ìs綉Ƹ³ªŸ÷ê9WQ/sèÓwËdt´¬KwÚ£ {õÉÚÚñêW¯ç¹ÚÚ1”¯Û¸:ææÕåÖÕ}eͬâ„÷ÅÞ{û½øìû>»‚7-Y®ër¡ÚjÒÁ4ÖÏyÚ¤™;a¤ßïãààNJVgŒìa­VU…¾ÓQ-7¬ÌSFMÜ·¯\mŒaŒSÆÍì]m6çߥނJŠ¢~®:PI’ ‘,#Hà,Éjýêz=¡sBÏa#HТ’\ic’­wB·;W3 º2*ql H»W×w´×Ñ_OÎGê{’oQ½:Ϊv›Þ`\=gñê}Ø“ ÀÙÕcn^=FO¬«c×?&W{ÍûÚeAb+ÿ/k÷½:¿ÏüÄgðêðÕy>õTš«A†(‡d;›1ÒÁD„&¬i9ÌFæ|HRÍVʰȊ|£$¬,è)ã&6ÌèâTø=¨d®•lIâÖÂôžRA²$=—÷¯ãB%SúãÃ_¹òÕëØÑ2‚žÏ2‚DU„/GK£=›Òó)Ç%|lgWÏ)íºÞÕ9v¯n+G·äI¥”e©dÕq€‹5õ&Ô{4i¡U‰W‰‘$Á•øoѹº=ï:}UR½QHßÞB^ jyÍy·ë L™Úø8kÁ¥UoAC´BsMí𮂙Ã)Ãf&«‚# )dfÂZ©Tp||œôq®Vµ:_ë¬.U¡Ÿ•È…O%yšöòáÅ> Ì®Œ#îç§%«óÛ»:wéÉ•7ÙCOzr‹¶ÞRyÏdûÉŸ$¡‘íø¼:å²Úê#Îi¬˜v×:F·¶F'–€Š+}ÕðÂ3úë{ÚóHò)?QIn8I–†}»ée×ÑCÐøbB5Ö„ãXÿ>Ë9EÝ'< `äý¿zm¹Ox ’8ɻޣ ¿Nø}í"X<'fn“6«‡Õ2(µælÛìu¢L‹¬E˜™°öz½±ýU‡Ã!úýþÒ=ªý~€JŠ'Ý^(P*•VæqçØˆÞ«o[T1ÚÓ)ÄˡÛÃIK8¹_¤·4ã‹ïjðªÀ¿‹ñ¼úˆEE5– t$W³îŽ‹8qµ]Ç,ážwi\‘!åUŒ¯¼ZÆøöḎç.cvò.·éïiø²NÊ&;ôl°°îŸX©‘ÏiV…ßÁhc QLëŽmÇqæ[8Û|ЊmºŽÂd•–±Ðà矧§§³[¿'è÷ûhµZ €R©„n·ëiƒZ­–ÿe2 Ýnw¡×Zš¾÷ݶ ÍÿŒ^7)iÙB©ˆï[ïþ×ÿkЋEzŸ8òF™”T‹81õÕ÷™õZqGPÌ1n›ˆqÛ¶U…Þ4UE]¯äÈž¨“O‚ÉC݉"lªüž{KÇæ™ïº¨E)ëBýÖl{})’¨£¸®‹r¹<=Yu]õÇ‘!‘mmP«Õà8^|ñEÔjµ‘…îܹƒR©äßw᧵ЇÅŠø¾³ ü/ŸW•ˆ¨éÚ6ÔðV&«´€MÅø\%¬{{@[[EN*Õá:”ô8ËÿÙOsÚTlϽ¥a¬^_jšÃ€·btáÆ›W@°P¢ü‹ï/L—DÅqœÙ=«¦ÌÕÞ$©MziYu›G[¦ÀÆÖ^¯‡ápˆÃÃCj±¦ýý} ôû} ôz=ìïïû·ïîîâ"Îâ1ë`ƒ•Š-ñ½U¹ùKß, vª""=Se÷“~·(‹6ã¶mãoüÆo''Àý«`•V~ѽɒÄJå#'syi36]~Ï•°®³wÕƒú}ð ~.¼†Ñ©÷1ú›áBýÖì@Õ‘V±8ã¤cs—~º’TÅqœé‹¡«™§í`4±ÜÁèZmí:i„±1:mGîãhÏik×Gţ܎Ðcl0~Wdãû°Ê"N…BÁ¿îáÇÔCþ¯©¯T*þÐ…òÀá-4—Å·¬ì® ˜í5•9Ç@°ðÀ¸¦…m*ÆÿóO|_yÿûƒ¡À«Ú³Þsž¿\·°¡…m²~2÷–6ë$s½ã6ðÈïŠüÞèÓNd䎜š,p'‹åéß_}Fêû¬ÿ¦ÙP¿u@°ð£¯,òHsIªnÛöôx—žÕyFèÛñé»ýÐcj‘u1ô…'m¨¤U~”û†ø“uäÿ@ðÐãÝÒR?Æ÷ˆ'¬áíoƒŽŽŽ°»»‹R©„^¯7ñ±ÃápäK¶vRFsÚX|7 Z·ïc4Am`ò°–Eæ%…l$Æ]ï~é%üñßÿûã·É¨ÛÞöÀŸ~‡º|ãߢ9l²~2×–6ë¶h§VT‚ÛBd껩/ %œ ìA}‹èµ¯žÇºúÿTåž «Í%‰:¸w•ŒN÷Y½«ú0t‰™²§os¶ê:¼µSBxÅðZ qêWç¥oi©Oi‘ó‹êœðß7Œî®ãuIb'¬þÿ‡ÃáØu"î8ÃáÐ_¼ißž ÏåÑ£G¿,¯¼ò >þñ£ßï¯nYÝ“råüüýèGñ†7¼am¯±êø€W_}0 »»»ªb°ÕZ'?Ü ä¶°¢øðòË/¯õ5ÖZ†ÿí¿ÿþ;¿ÝüÁñ;Êp`ËþÊ€ŸúŽ ÷…±¿ŽŽŽðÉO~o}ë[×òü›(¿ç¼N«î­,bt¥öE†Tbª'Ò+e h˜’$fÒðÿîÕó´ ’*Ù-c´K¶Q‚ôÜÉCЛ¼Š•õgò»ßïO\ÁwY›¬ƒÛ¶={8pœU°ËmœHr·‰Uô€†O7j K *Ž[W÷—Q‹œâV’zê;c\=FE“-úôéazâ]Fð]j‡ŽÉÔî&÷‘D^ÿNélà7~ã7ðë¿þëøã<×Û53a½~ýº?–]·Ì–6ý~wîÜA¡PÀÝ»wdžL2mií÷¼ç=øÀ>àéV‚=R¹$-‰÷îÝ[Ëó¯#¾àÉ'Ÿý!ÞÔ·b|¯TÚjÇÇÇ‘ Š«²‰2üÿõ€Èu)å‡»í¨½†«P?à ¼5qëÖ­µ”á›(¿çÚÒÆ¶ËRs¹×A*Ãi"[ˆE Oy¹€ªXß@PÑv¡’ÝFGé{TËÜB÷êöºv_ AÂì@õø60ºøŽl}& ì›­?‡$2|T^¿¬ƒ$>’pxÀqá¿õÊo­-YÝt<Ö‚K¶=OÛ}>Û&\·“!ÅeírY»o”p"Nrõç¿lí±²¼;á5 Ý.s‚¥ÑÈ ^çýÅ÷£\*Ã~÷¤ é£ÍLXK¥Òj“@­V µZ ·oß»íúõëÔ0ùrèÿߨ6¶b¿PZ­Æw é«lPîm"Æ'VpŠ.pcGíÁZ.=«)é°¢lÛDl˱Øöz÷_•d*«d>­ô‚:í™Õ;ôíÁ¦í…­?¾ 54L_Yæ2ꉨ •@œh×ùûG#è “ÖÃÈÐÎÿùóÿ3žÂSkyË6]wÆ”lsÚüÕðÜÐm·Šß9ý{0­£#\·ŒêkD±Ê€²ªÀÛWµ»mlu§µØTùí8Î| ëÙY¼û."/òúBO› 'ùáÑxQ#žÂ•ý*FG…”1òY|ùÅ/¯å°“¨£Ìl ™´÷ª$ñÜK›0GÂÚï÷ý±î•Jebë·ã83Ÿˆžÿ*=<<ÄÁÁ¿üv¡PÀ³Ï>»ùw‡!šS¦â›h›ˆqÏó¢+86®*ƒõdöë£\ÛTùýÎßù|÷w÷ì;¾ø)àMÿ©I°8•dËlºŽkþjµ=Š€ñIšX «,G]*•F&\¢P(À¶môû}¼ð 3ŸëððpæãJ¥‚^xÁÿb-3_vaá¥Ú‰bÈL|-h1>±‡Õ_-±¾Þa’´•6U~?zåüå~øGÿHÍÃŽ.i¸]þÚOªË2LVÜÕ‡Àâêú:Fç¤ÝÀèþ¨í«ÇÔ¯®“…XhklºŽbÛöìù«“„Þ¢­+a½sç Ã@·;ºF¥RA­VÃîî.Z­žþù•Íw /½=ÁÊpó£{~­ØRñM”ËÄx½^NXõzOZVY¥­³lùýŽŸüI|S£¡†Bîì¨áz<·¼ü5à›Ÿ>ú¯ÔuUŒîg* ¤žc¸‰Ñ9˜gW×W¡*CÍÇt F+äe80­Üªê(®ë¢^_ UDÃb1OWf&¬2$à#ùÈÔû}ä#Á?øAÖD•¬Ø§aG–F—áÜˈ(1cÃ=¨ 7W¦ð )—ÕʨÝîè*À€ÃŸÞ÷W‚ëÂ+ç†/ËÂ?]'u }lœÅSˆV Ö Á:Ù—Ô§åшÇgÝ¡ßï£T*%¡µZmdx°ÜþðáäÏI9ÁèæÕQ<¨–Ì›W—ïCøLV‰ˆ’ãatéü68t‘òÇPm¨…•Ü«€—Æö»GÑC…‰2dæâbí¶ú×Â.ûƒÊ–DDWfö° §@jÞ†yu¹õEá<("¢ôã\;Ê#ª!檞RP¼ª˜pñkÊ Ïó¢·´iø±×€_Ü>ÌnUŠ'Ö*Á·o߯ÁÁžyæìîîŽ$¥÷îÝÃùù¹¿Ô©bt({T‰ˆˆ().‚dÚ¿;`ƒ:å†ã8ø™¿þ×ÕÈYõÝÆÕê¿ÿ€s´i.±ÖJ¥‚»wïâôôGGGc·ïîîb?ùÕ‰ˆˆˆÒ,jˆ»l?C”®ë¢ð£?ª¶m:; Ö&øï‡Àß±€û÷“>DÊX + V¾}û6ýÍ„L&LDDDD1ÔÁ•°)7\×ÅáßÔë€lkãAÍÑþ¿ýÚΩÈ-9(¾Ø «XÕfÂDDDDD”/Žãà¿øìgUbê–Õ0ø2·­z\9˜æ4wÂJDDDDDåõ~_®TðV«<ºÒ;{ViA3·µ!"""""Š£ö¯þþãOü„|`~6“UZV"""""Zžëâ±?þc¼÷ÃNúH(G˜°Ñò<ÇïyІL´LX‰ˆˆˆˆhi¶çá?øƒj«&#飡¼`ÂJDDDDDKó<ßóÕïá¾Â´R\%˜ˆˆˆˆˆ–V¯×j¢aÂJDDDDD«a¸ŸôAPžpH0-Ï…Ìlh…˜°Ñò\p±%Z9 &""""¢å1Y¥5`+¥V""""""J%&¬DDDDDD”JLX‰ˆˆˆˆˆ(•˜°Q*1a%"""""¢TbÂJDDDDDD©Ä„•ˆˆˆˆˆˆR‰ +¥V""""""J%&¬DDDDDD”JLX‰ˆˆˆˆˆ(•˜°Q*1a%"""""¢TbÂJDDDDDD©Ä„•ˆˆˆˆˆˆR‰ +¥V""""""J%&¬DDDDDD”J©OXûý>ƒAÒ‡A´ŒoÊ;Æ8åã›òŒñMiq-é˜d0 Õj¡ßï Ã@·ÛMú°ˆV‚ñMyǧ4¢¥1¾)ïã”gŒoÊ3Æ7¥Q*Ö‡*•Š]¥Rá8zM¿ßÇùùyÒ‡Áó]ã;žmkÍÍÓù2ÆgËS™¶mçËøž-OåÙ¶/ã{¶<•gY9ßTÎaö¥‡( c×ÿþïÿ>~ù—Žã Z­&} k÷™Ï|Ÿýìg·¦Yåù~æ3ŸÁïýÞïá±ÇÃáááÆÏe‘ø€`ïz×»ðîw¿{ãǽiÿøÇ“>„Ìž¯ã8øƒ?øƒÄÎ…eøl,Ã÷éOŸýìgñÖ·¾5‘sY$¾Y~çÛ:Êï¤ÊB–ß³±ü^î¹~ï÷~oîò;• ëp8œxÛ£G"¿,•Jïÿûñä“Oâ}ï{_Ò§°v_øÂð…/|a+ÎuÕçû…/|ïz×»ðØc%r.‹Ä7|ÿ÷?¾ã;¾ßöm߆oû¶oKäØ7ék_ûnݺ•ôadò| …Þþö·'v.,Ãgc¾¸w¾óøìg?‹·½ím‰œË"ñÍò;ßÖQ~¿óïLä\X~ÏÆò{¹çz×»Þ5wùÊ„U†V*•"¯ê©§ðÔSO%}èD3-ßð÷þÞßKúÐ7ªV«%}™=ߤß;–á´NYŒo–ßùÆò›å7­W*ç°^¿~Àè°„Á`0µ2O”ŒoÊ;Æ8åã›òŒñMi”Ê„µT*¡V«Lðµm;;;IÑÒß”wŒqÊ3Æ7åã›Òè±ËËËˤ"J¿ßÇÁÁJ¥’?Éûøøxâü>¢,a|SÞ1Æ)Ïß”gŒoJ›Ô&¬€šøÝï÷$?¦ŸhÕß”wŒqÊ3Æ7åã›Ò$Õ +m¯TÎaÝ6½^oâmý~ßoáštû´}‘fݾi³ÎG¿_Η”I1ž·øŽsNrŸ¼œ/± Ÿt¿<œ/-ßYü¬—‰ï,ž/±üžt¿Ôï%%êáÇ—O=õÔØõ/½ôÒåÓO?}ùÔSO]>õÔS—O?ýôåK/½4ò¸}èCþí?ýÓ?=ö¼Ónß´Yç£{î¹ç.?üáÏu>i;_ DÅxÞâ;Î9 Æw¾° ÇÏEâ;‹Ÿõ2ñÅó%…å÷¸´–ßìaMÈ`0€mÛhµZ‘· V«Áq¼øâ‹¨Õj#÷½sçJ¥’{¿ßÇÑÑQìÛ7mÖùˆ^¯‡ÓÓÓ±ë³v¾4=ÆóßqÎ `|ç Ëp–áy¶L|gñ³^&¾³x¾ÛŽåwöÊo&¬ éõz#K†‡o‡8<< ìïïc0øÝí½^ûûûþí»»»¸¸¸€™·'q®ÓÎG ‡C´Ûm†1òø¬/)“bñ‰Ì}ÖËÄ7c;›X~g¯üfšÝÝ]û¤«T*cˇ?|ø€ ù¥RyŒŒŸuû¦Í:qçÎìîîú›V‡ï›•ó%eRŒç-¾ãœÀøÎ–á,ÃólÑøþÒ—¾äßG¿š?ëeâ›±M,¿³W~3aM¡B¡0²„ø`0ÀÑÑvwwQ*•¦Áp8œy{ÚÎÎÏÏ1 " ¬/M—·øŽsNŒïí’·gNºiñð•¯|eâãÒúY/ߌíüaù=*-çË„5ņÃ!ŽŽŽðÁ~µZ ·oßö¯ŸäÑ£G3oOÛù œžžú—£—Åó¥éòߓΉñ½½òã,ÃIYþ¬‰ï,Ÿ/MÇò;x\Î÷ZBïÍÐï÷qçÎ ܽ{w¬«}’R©4óö´Ïùù9 …lÛ†mÛè÷ûxøð¡ß”Åó¥éòßÓΉñ½òã,ÃI7)²úY/ß7nÜÈäùÒt,¿ÓW~³‡5¥Z­–?î< 2¾\ï† ~`̺=mçsëÖ­‘á aY<_š.oñ=íœßÛ)o1Î2œt“â!«Ÿõ¢ñýŽw¼#“çKÓ±üNßù²‡5…lÛÆ`0€ac×j5”J%Ôj5œŸŸûãÍmÛÆÎÎ̼=mç#B–ÂÖÇÒgé|iº¼Åwœsb|o—¼Å8ËpÒʼn‡,}ÖËÆwÖΗ¦cùÎò› k É2Óc·9Ž@ÒÁÁ¿\u¡PÀ³Ï>ëßoÖíi;ŸY²t¾4]Þâ;î9M“µó¥éòã,ÃI7+²öY³ü&Ëïqi8ßÇ.///yiiÃáÐĨîüY·gͶï¶Û¶Ï{ÛΗ¶ï3ß¶óÝfÛöYoÛùÒö}æIŸ/V""""""J%.ºDDDDDDD©Ä„•ˆˆˆˆˆˆR‰ +¥V""""""J%&¬DDDDDD”JLX‰ˆˆˆˆˆ(•˜°ÒJɦÁDyŧö±áîÝ»0 cm-<Ï?ÿ<Žq||Œ^xO<ñÎÏÏ×òZúåöíÛk{?)}’ŠñMÆ7ÀßV,Ã)ÏX~Sž±üÎ.ö°nØÎÎ … R© Ãðo¿~ýúÔ/‹ e˜dwwwbkÍîî®ÿš…Bׯ__Ëëôû}<ÿüó¸uëVn¾(ß21ž…øãÛ,©ø–ÛY†Ó:±ü¦ö±Í¿Y”9YŠo€1NóÙT|¯êµß4–ß”wYŠñ¼Å7ÖŒ) i)YÕëܾ}üàqtt´±¡p”]Y‹o€1Nñm*¾WùZŒoŠ‹å7å]Öb> stream xœÍÍ®%;rçõgXe ·’ÿÉ` ÈÒ¹3A£–Z†ÕW¶$†ýôŽ+‚ŒÜ{ß{~n5P–¥îÃbFæÎä"#ÈøÈ}9néåÀÿØþþç/éÿóoÿôåxù]jÇK*³ËÿM­/ÿö_þð‹å#¥Ûìéåì³ÜZzùùKîuÞBÉWt´Ùåï?<ÔÙWyÇkÚËÿù"O\ç<òËãùÛ¿ø’J·³««d¤|›x–×UFË?Ç¿G¿u­“£ÜF‰Ïç%Á’—¹¥ð÷²„ç;gî/ÿEÞö¿~Iú!^ì?~ÿóËŸÿôåÏþv¼äãå§?|á÷‘·Ä0~G™·RòËO?ù»¯ù[ÿz¬ÿý]:r¹Õöµ^Š[ÿûŸþòËþéËß<ùT£¤[I%|ª×§Ÿ¦·Ü.µÜÖL}ÞR¶¼$ÚÚµÜV¬µlõZo£F[Vr±µj-[¡Ön6)·lyI´µk¹­XëÚ£%6É×»F­x÷~à&×g–wœn§¼cýÀþõ~—ÒK·ÖùòÓ?È?¤ðië?å‡jƒÿR/švQ½o*÷’:ìïåÿáK~ùËwéüñ•Ý«úõY#¼Súó&xoçW^lÆ‹ÅKýÞn)öfg¿U§¾Ù¿øÖny”Z¿þ—oò½yô¯õ-·Vûüú×ë_ÿÛ7ù ½ŒúõUVogé럭þýÿ\×üÛ7ÿ甲$BÜo“Oø¹—q+Cjt;N>ò¿ÿ“|¤”ÿýù[)úJø\üP'ºHùXéåØM¥WÒ¶Fjè¹´Ÿ“7~Î[íRrŽv›§¼Ï3Ÿ·œ&d)}È@Iï·)¯kÊ»5uí6ò¹ÇmB"StW‡”œò&8OyÛr‘Ô¹Mù[ú¤„;LùªªtÈ¿ˆVåïnò/uÊo•tƒ éëäaЧî%/#ç~äœäIT«­ÒH–ÿ‚‚|äÛÐi9*Ä, I·y;ЂJ:­dÈ£tÔé톷ê1ÑÞ¤d&±‡’*•õæóä­ê9n2܈t(iYG뜖[—ÇAGQ+é22äSK-÷*σ:uÕ9åy´ÎÉ.HZ“<ÞD‘†Ðµ¤ÉóL»Š%Sž§j‰ýö³àçÀLåÏ:‡ú‰~©å¶vdâ¶bdâ¶v-·k-[+2Y¶Bd²l­ZËV¨µ›G&n+F&»áy-·k]›c´äNôµG+_ŠôýòJ~Üøå=š|e÷ }Ú¯ªÞïí|8&¨´‰mäüûÿýh8P¤¿¸‰¥#8­µÂ’ABÃõ)¤£èÝ'<ð†.·4ñIÚÉp 4-‘ž» F—>½W-‘ž[¾£„2¢ –.ãû o¿Ó‹+]Y1¨€ZÒsë!ÿO» ¶æ÷©Êør6‹ô’3w…ƒ}9Å/'o3 Ÿ î?=2ehç1²þ-CGW7^VÄ}>t¹'.¶juŠZ_Dfh Ýdq…;<3)iŒNdˆ“§¡«Ï]e̽é¼AÉC£8Ùò4SƒÝÞh¯æ’cÌ­E|¢¢uNݵ ÏÑð´»×#"ÅuNêW$M¾âmê‹hôVÛÑáÌÀ7*zQ1rÜ,"Óª%¡®áïlIbÒ©n~ã—kˆ'‡†î_Ëâ9W}_½[{ž>Œþj($9ð£$¥éÔ HFQ4†_‚Ìò2F‰‚,ò‰{‚¬ò ÏÙ¤=Ðó1IJ(`‚£"ÅÓ¯Œ'\“ó¬Ÿxirb.§\$yŒa¤$ç)¯4EJWøM’ У܊<Ð/Š„«Ý/Š<´Úz‰òš¥ÇÃú‚­Ç¤ËVã1ØV¶1•s^Ô("¦Ý¥FñX© Wã1ù·\ôx´t§G4Ë« Œ‹"s6M,E&Ï‹"%dáÍ—"s­VBEJßËè` 2M{¾%È4LlKyw‚ÌÞu.A­Z‰ RÞ ZÞ‚L“‘ødj|â-HÄÝ= 2IóšAâuå ÈÕŒ¶sJVeyK¸Á5w›ð‹Ã|䔸òŒ~×Ù~ý}}•×y¼æc±@ïÒã=Üa•ÞËÜ_ /~”#cv.Nû[I°äe{²{ýýc.ÆÀïø-±Àãg“hþ@€™Ž~ò™0C0.µÜÖöòÝÖe•Âl…³k-[ËË_¶â*…ÛÚ+n+ÔÚMȽ|·uY¥X o­x˜­XëÚ£¥51iÀÑʇ×2$ÌÐE¥4xäߨ½À_Ÿ¶Á«èŸ·À{;ºŒhC»ök(ðo"œñõŸ¿½/臌[3‡x®|üSFUùAßúÛž¤×®p;ä%ëº@OÒkëJôãAÏð$Å_P_öÔøR§êƒjÉ©µ'·Í[ôγ˨ ÑÅ[Á1»ŒR‰UdG×>¤W툫¸Ò·ÏîlÖ’¡/n绌!Ä™ÐA%2T ø‰#Do˜SÃ8h+½‹¯`]ÕÞEÒ“ó~ )úo~øÜ ÞzàhBg¤ñÔmå‚“Ný”á}N¨ÕÊÙ ä ׃ó÷]ú{[ÿ˜tr:†g.Evºù]~/ƳƒÞî8¹Ñ­àTàNš“¤È‹–LCÆUŒ]î¨ pˆ¦–`z›ƒé¿³¼²–#Ñ.æ¹ü¡ïd1¯­˜œÓE\ ÍÒRXÒ{´½ª¢iNfÀq× RÔÑgÏM…S—ú+ed·‰V›Þ÷%q¢þ^…¥¨C]x©Ì’rêDk>鉌>†-~Øœîâ9k ̹CÞ£ŽšxãúÈÓë\-âè8Åﳉ»¹ ŸðÚw 7¦8;:Ûš,4 óäTå¡À¥˜í"ÊS¤“ÒE”˜]nQ”hy/Q&ñmKÔ$æäóˆš,µsqÁ5Y¥ŠßK“Mt—sÔ$&ÏK”dÃ$‰’„ÌJŽšlò‘ÓˆšÄÄmnQ”ýðžÆT)ul©ÃU)uNóÌL•R‡‡‹rvy[¹QN|v^d¢œƒir"ÖÒaÜ59õ IJ/SL£¢H eF¤ønÅJ=J»—£¸Å\Qr5N,ß” F)¨A‹rIƤ(-(Qža¨ Q®ïA…óô–h"œ:É4(Ý"û*—àœw ”[zˆ{\ô‡‡ÖÞÌä§/¢õÍiË.>ynN?¸öä&ƒ?Ô¤'œ"råé«8ƒðv ÓÜ–Áæò¯NÏùqwÿì]tBŠŒÃX¶Ùc¿×Ù®û}}•×y¼æcîþ,‡Æfû«$8é^æ>Iø{9éKG-."¬’hÉÊ–¥ý÷wv÷§(´ãw¼åî—ùËîþãg;±2—êÅe{ú™_j¹­íÈ»­èÈ»­]ËmÅZËÖrä—­àÈ/[«Ö²jí&䎼ۊŽünx^ËmÅZ׿-¹ÓymÀÑÊGÝýýÈL?®¿ÿÍ?¾²{…¿>m„WÕÿB¼³óañAÔ¥’N}ùûÿûÛï¤>ŽüUý~ýo?“¾RüZ]Ðÿö¾X@WWµ%ÐTùi£èªö9ºŽKÒÅ¡«Ú'†¬¦ÉgÂX2±Ì섳éºöÌìåQ21L$°0¥a]Ù—bbâ %CW¶Åƒ°9Éyº²-ê81‰’ª+ÛSÆ5&,èMÑçŸ\–’”ue[ºT:Ò"T[Ø–^3³®¡hz’þYmUû(œšù\«Ú'/)ÉWµ-5e–f«Ú©pL›eÚªv²´§Y‹­j'[KPh¯jkîTKždrp6n¶ÆUíœ9䋵Vµ¨H´äI&âިݎièn…šÇàÚ‡ÏÎiòaëÈèÛé–r¦MB¡b«‰ŽêTSýøbï/ö<ÍGWËKZ‡)b+þê¡w&wšdÝÒ°Ž£5$Í6_‡ÀÇ^Í9­N*åÆnidÉp,@c‚‘®Ž¨CÉYX®ÌÐj>©ºbo“«/LÜ¢³‚9|>Ë‘üY°*¢VÊ´ûÔÊgÁ0Ÿ¥ê ¶ÞÉ®jÙž¥±Fkö,­Ú½W§Ò{V¶e¬w6èqʶ3èq"áG=âõ©—ôx2¦v=Ê÷aVßÒ#Þ~‹rÄZ°†óKŽø9gŠr,@G”#–¦Ô}_r,ò¡gŽz¬MÓƒ á‹¶ Iñß&&R¶$E@‡éŠ”ää€+RÔÑymEÎÖ-nqEJI甄)rö–¸"'’xyo*rJiü­H©RðP[‘³ËïŸQ‘SÓ‚rP¤¦R¥ H©R½ Él«9‘vDANôÈš6ä‚”`¤rÅÇ9‘t¶ I r ¢œH3+%ˆr"K)— J–ô JxòA‘úúôw»"çÙŠÉ‹’Ô_ë"UQʯ´×碔çn¦7jrN]¿tAÎi©?®Ç9¤9Ôô(¯g^ä(o0qaÚ9‘O—Î Hù}6.…!IW\Çð’뼯"„K ¿Âÿý±þÇ¢ƒ”¤ÝÞb:Ï*‰`ƒ•-fÿ½|ú”û·,yI´deËÒþû»ƒ Xê)ïX ø•èàÉKH9»Nó?ùD™¯uÌRðúÍÒ%6PK¡ŽYºÔqKÛçwK12 ¥]Ç-Å:«ñ,ß,]âkp«ŽYºÔ¹4Ãhg¹¯¡ÙF d˜Ó‰6&x[ãO^×EӯϛÝEçOÝÅÆÇÑLìiÂ[±À¿0‡×u~‰<~ý9Õ¤D^¯Ž‘)ÕŒùÐ+ÿêHI‡ó|ÊH@¿$%¤H‡|ôÄÑMJ*¦ggæ’´–œÈ¾ž¹ØaJ=«^àá1»¸7øƒê?4Þ¼O<Ž Ô+‘fÿª%6§1šÙrßÓ©éë+æƒ!¯³Ò« Ú=5|jZû÷©>¯ÎkÑÌìú0Ó&å3èb¿ ¯ìñ]¸œ-±“›óqbP“* ä”õY͉© išQÄLxðKr=nÍfyøe¾ÜG¢è’“Faü»ÙºÍÊIÉl´âÙй_Y¯f¥ru£Ú(*>~º,ÏKIã³`ª¿±ä´géÕJºNôcŸ×t_ä·yÌ”ÇÑÌŠ ùyÔÊìçuÕÐ ÷á{ÁP®v-yDJº=KókNELvV²Í5X©+û|t® IÊ‘ìYœ¯(Gã³äÃþfîCåò‚è»ðIÖ³IüaOrÚÛ–ˆƒO²rÆMôhìímç QÞüY¢µ¡žAˆ¿ÀDF!Nd¼Ï‹A¶¨CP>©D&q‡RŠ:ÄÇ8.BÔ˜sF!fôA)*Q—•ˆL¹£E)–aSóKŠ˜8/RÄlõ¸H±ºh±ÊÝKbÄzcÏA³Ú|û#²ËÕ¨ÉäeÉqÂWäL޳Í~¦ÉQ;r r”È 1 ¢% ®ÎÆ> ñ)¨QB†ÄeWã0¶ÕOî=¨QÃŒ³5NôÍ^GÕ¨ |wªFiõ'gZ\ê<Ó«75J¼ 9=[¹Aô•U«$%ˆ‘Ît b”0drõÉÅ8ÏÓ‘-hQCƒ¤(F à2%ÎQ†uö¦D¹¦+)b%èPúcëlM†òØ^¬ËPœ²Jª>÷Á&\~g;Ò‘qè%›Hó˜ qÿðPk_·k=»îƒî¿Êû.»Dzê^)Ëü>»ÖÀʉjy3Ëá‰WɶåeÛÖ* ¶¾/ÛŒé¿~–߯6ïŸå´îþ€¯O?‰ÝXkÙB`Ù#Cì%[«Ö²j-[³)<lYÉÅÖªµl…Z«!Õ¢ ¢Û–—D[»–ÛŠµîe°µšéëCc¶B­2Î Ø‘¯AÁßß>+HG¼þ©½F¼8ÿZðì½= þõYk|èž·ÆG[»x&§4™·@ç:>:Ë5 sý- sÇD؉õöbüò­~+ëÜ‘(•íÓe‰õˆ÷ ™B¥.?\d‰Ežáü‰ˆ FYVÏ3tY¾œ KÀ-sDY€á„…˲•ÆÄÈ%Kxlõ.Ë0#nB0*ÚäE—-ÙÄÿÒe[·ë²%ÿ•®KX6íš.:2æq]bÁ–÷r]¶ã´`ÏuÙD©T”é2cª£G]¢¡å Ë2}bÆeYñ-G”e]i—°e þ£_d)=®2lY"ì­Q—µô(ÊêÑ%Âì‰gQ{bg¾DYå·ö3Š» ètÁ%À|FQiÄÚL–(± Æ»›(«gÔ.Q*YX‚(èJÔeŒ󈢬¶üýxÞž†3Û·ñ:1L¹¯µ¯Ûµž]÷9ìyße—ìÄ˶çµJBHâs°µJ‚-+ ¶¼ä»‡7Ž>¿Þ¼}Þ?ËaÞèœ>û\zc­ek.ËV\–­UkÙ µ–­¸,[!pY¶V­e+ÔZ i.n+.«®Zn+Öºo”ÁVp­ïs°õ‰ðÆè3¼yOðì½= þõik¼ïž·ÆG[Ÿà eX”ÿ”Áì3|…·ä¼r—]s;" Ý* r–$/5ZÐÕ '/‡òe‘¼yR$/¦§5ÃÉKé°9‡åà¥fæªCnä¥ ´Ók#/ž!òRGÞ#ÒÐATë¡ ½W±q ÒÙKºŠ$¦ _ª__I?“¾Ô``~&}9àG$Ö!})%c¢ó—RR9;©u´ÿuþr€k$üLS<àÊ7êæ@¸Æh`ÒEWôÓLõ›ù€0Öz&‰L˜Råä„§˜3c|0å"›us û¬€&€90Þ"€90èòù ÀX!O‰âDrþ0嵟t3œÀ„Sñ²ñKõâx‰á—r¥¢Ž_MN‰ø¥–hÌèøåÀ€C‹,±ÚT‰ MZªÄâàÙ¢*5î›A•-t:·®J‰škÐTyÀ%ÎQ•@NËE– NŽd™¥Ìe©þ} ²ÌÓðgW%ö¼R~©YUì"\•؋݈«PýìQ•2RÑI^ª¬ãˆ’LÀÜ#­~5ÛªKŽçŒH´ô4k-M6iû)nQ ¾÷·(ox®É†½´Î I˜1š&1ŸQjÐdÆf‹š/Â} \“¥z÷äšÄÅü ®Ið,T×Ò¤ÄȘk´ _èÒd1èek¹A5ÊR[ÝeY.å(K ì ]–ØøìlQ–XÝ:/²D¾EçºD:g‹º”ßG÷Æu‰B›ÀÖå´I£¥ËV';’­ËlóÛ“:¹œþ„Š˜†TloÁëDÇÿ¾Ö¾n×zvÝçØè}—]²|/Û¾Ì* N¾sÎqáÀK¶-/‹ÓåVòÝç£SÀðøø½Ìf?ù\¤~c­ek…ËV\ép[{ÕÄm…ZËÖ –­¸Òá¶öª‰Û µVCZ¡€Ûº¬txÜ«&f+Öºo”ÁVœ×¿kÌÁÖgÖCÈIÿ˜ñÂ{z€g¯íQï¯Oã}ð¼1>Úú,±GØc¼ð9^ZF \fGÒ¿Î;—ÙuÿNí"Ëì+Aɹ̎ô^Ìf*•È« ÌÔCÝ,3Ç!¾åÁLñR½,3•#$ßidæøª­“™â¦ #¡ù\âÉ0ǹÌQN›ºw.sÀ>Pã2öõ1R“\¦–b˜ä2eØ?ìù Ì”a,sVÎÁLõÔÏv0“³å‘—HöÖáÐÙL)É^B8SýTr¬ 3åÖ…ßÅñL ÓØœÏT™'ṳ̀ òÐ@_õ#8¡©ã%÷57HS ŸœòuJS‡ouêÔÔyÏJ4“¤¦:ç:ßç°&K4×ÀhM¹×ŒlÇ5ò~BÔä5Õ²z@l$‹äHllÚ"²©^‰úDÆlŠáÌÀÊ¡Muóõã9µ9 £Îc›[%ĪÉmŠ3h“µnîpÁÉMšÕ†ìè¦&™dJ³#Ó•äµI³Ÿâ»“76iv$«ègYÒÄÆFú®–4S2‡mi;ñ¨S·Ä™˜úÄ™¤)h\âL§mɼĉ~êˆÐôÀöVbâz¤Žé'&𹂋³È-ŠK«µFqê.Çq3ƒÙ±Ö–8Ëa]Ûg9Ìÿ^âÌØ%vFu,ŠÆÍ váªuê¾a9ª³X ¶Ä‰ÎmÄý tBsæ–8‹üîV¢85Ií"Î2¸‡ÃÖfµPni»QT®ÍZ'û­ ÍlýÉÖ&µ%ÍZèé/ib§;‚Þ.M¬¤ñݸ4³óìKšháìƒ\š@4x•K3Cz–4‘óÖ[”&(Ï»*g!C’’AÛað:Ñõ¿¯µ¯Ûµž]÷9¾zße—l7ß˶;³J‚›ï¬t°µJ‚-+ ¶¼ä»‡ ÎX¿2¼‡±Þ?Ë©áèñ=ý\JÇZËÖ –­ ,[«Ö²j-[+X¶B0°l­ZËV¨µÒ ÜV V\µÜV¬uß(ƒ­à¯Þ7æ`ë!ƒ³Ö?fÌðž.àÙ{{üëÓÖxß üBk|°õ)à:kì7¯1ß‚¹–N£¡wÞŒgGò±ÎxvÌÕT"ÊxŠ/`#¬3ž:ªÏÀ\w$YŒÈ\wlG¢s?yŠ2t8ä9à)‘~4ÈSGf<ä9°?öÿyê ½¦_ã©sÐõГô"ƒ<¦u+±ÏÓ×Ö3 œò”´ÛUFyêT-å©’'“´Š%¼$·LÊScŒ¹kñÙ-21ÊS šƒ ¤<XQrÍFyäTèï”§fEÈS3»zÄ®‡:r»Ö¼ý¾NyŠ‹|pFÚ)OM#lk”ç@ŠGŠØµfÍ^ä ´Hy °LÝ2ÊSêØîûyêÚˆ§šé‘¼–ïYnNV+ç)m5ñ•:è)^”92zªd'ôÔÑìôÔ•"æÏ‘õHwá5d=%dLŽ‹’õHýgÒ»Ážâ‹Ùä¼ÃžÒ*º¯Ö%¤ ¼ãh†¥LlÕGT&ö =/ÊÄD¼úTK™ÙÞÝRf³m;]˜˜Ö&°íÂÄâS-A˜™c¦&=Õ Kq«áΦKuÚy(„éRJÊE—âÅ7k2¦Ëx˜ ·éRêL»·é²c“…(ËÎ(Ȳ£Ýjf”ËR ö$&Ë~"4,[–º3"|ÝõÔ-K &×\–}vÃÛ]–yBd¤]–XÏ©]Â5ã½]—–ÂZÔ%ˆµ‹,q& ; —%B‘‹*Ñ{—‹*уr W%vŠ8£(¹ë©Æ”£$¯0ŸÑ%™0ëp‘$Ž¿p¹Q’€"z‹’L©û&I>£FI"0$Bä’ÄVt-nˆ ádQ”éôL%Â7@ (1r\4‰­ÜæE“ÃûÝêƒc”‘wº±½¯q $.uüš]ãÙ5ŸÃ°Ã=VIà0¬,ø7^Gªƒ­UlYY°å%ƒ(öÛëï@±ã+"d| "?•‚Æ—:nin)†´´ë¸¥XÇ-íÐÀ-Å‚–v·ëxÚYº„lx»ŽYºÔ¹kŒÁRto/M8XúDèàHö:¼-ù§ïìNâ¯ÏÛß쟶¿;;Ÿã²1÷žá³hv‡üæˆÐŽÞ¸f¡sùdíÈ4͆{*Ú1#[‰` í]öb%Š„vlNÂí3 í3›/îHhŸ>ñíH¨Œl‡cšDBCÞµ!¡›€**%ëîDB5·‚P‚!¡ºŒa¹ÙDB¸2D•H¨NþMƒ¯™w¿ÕK Øí?G@› Ç–Ô­Lèžd'ÊÔ\þM&Tc—™PõR9ˆÊTE×)ëá)¡P¹Æ&– p0-|ìÄn˜(fmWƯC¡#‘¡0(TJ’ ×…ê¬|Ùˆ6qû›€gíé…jÄfoPè€#77:²;œN…ê %ªá½;R¡š!ø`ú,“3«Î…ê†Q É^Ë‚8É…jú4?š‚¡m ôƆ=Iƒœ7áP Jéתq1ní!Œüv„°‰TŒí^à å(Hì\4.zDcQø:†V›‘¸AÇÍõˆ-Nóˆz”"û®Ça{yºûpÊÄåØuvø rìØO¨FB»c{eƒ(G#Ž(ÇŽõÔå(%§w”cGÔŒ„¶Ä ™Ë<.G]D0ÙPŽ]O¥Œ&tì m l©Ê娧‡,.G隊uŒ&ÇŽÐêØˆ¶D Åv£09JÁˆ`ÉðHŽŒ¶xæþ})ÇCžß±¬dÏR]Ô&G¬GÍÈh‹Ç¿ÞŒÊQœ+QŽàÌØIºõH¼¸c‚v¤½n9Âo·wir„Œ79"W¨EH[3ÝÆ¦´åξo’ËQ>º…Û®ÇÔõv=&ÏÕ2=¦Óy}×#v–ㆮGÝúnD=b‹„±õ˜œæ~ÂjììÖJÀ&½d3׋gvXx¨µ¯Ûµž]÷9V{ße—›ƒÚ¬¶ßççPâËÖ›ÂO¼J¶-/Û¶vɶõ}Ym$?îå|–ÕÞ?ËÙãý_Ÿ~.²Ç±Ö²î?E¾ÚK.¶V­e+Ôr[»ŒlyI´µk¹­XkÙÂÊj‰|µ—\l­ZËV¨uß(·­ÝL_ó¶k}”ÕÆbokåã8yXð¸ÓºêÉNÇǤþµnàÙ»{ýë³ùÐÌk#_ yí\Ê#¯ÝÎ×ÖVÙ”­m|äßÿVX»T&îl,´€'ÔS£B+‚©ÐªSÔÜŒ’ThEvwå|#©ÐªGIèL©PQU6"٨Њ)Iº:F…VuZ8GE*´bŸñx2uE"½ @¡Ò÷ûŽOœÎ”÷nÈ„j*ð™Ð:»eu8ª©ÀŒÒŒ ­“Ëö\Lh;˜ÒðÇÅ„6$½p°6&´Èއà6tÈGdBö¢³lLhC®ýˆLh;NK‘v&T|U;ÚÐ:“A Ž„V¼è‘Ð wQ H„6Lgó‡ڎý "¡bÄ&Ù ­˜?›‘Ô®ØU]5GBå2fp"´ªó¢è¦¡ ã⌧àV€&#J(´" ¿ÅS©y«—Í„Ê*ÝQgBëôtwgB¥Î`¼åL¨ü†J‡Ù™P-!InLh~Äš1¡òÛ´3¡^l §àVœµNf՘ЊÓùÃ}|QŽàèÅ–$<³%Ùšy÷®É2†T‚& 2FÎ(I„G)‚Úõp"Å%)}àeûy9î&º"‹¬·)?ý–¢ KsW^™ÇÚ%ɹòß\‘¥ôsR‘H ³­‡¨ÈŠX¼ÅÍÔ Sdm¾Óµ+²b–s"¦ÈŠU0Ær¦Èª FEV¤24EVäû³1EV¬‘04EVÌ€P).IepQVÀm)bÚr¯Ì`s‰±—Þ}‰Rç fT%&¨/WeåÕA•˜K1vÛT …u\•Õ –*5™«UÖ#îP›qèŠÄ~|6Wd«6‹¹ ЦÝE6NQnÃíÒx¡Ü×Ú×íZÏ®û¦½ï²Kv4âeÛáÚ%;qÜ:ØZ%Á–•[«ä{G6Ži¿Ù¼ÓÞ?˱ãè“>û\ÄŽc­ekÅ,ËVˆY–­UkÙ µÜÖŽYÜVŒYÜÖ®å¶b­ekÅ,ËVˆY–­UkÙ µîå¶=êûƼm}&²qLûÇlÞÓ <{w¢}Ú"ï;‚ç-òÑÖ§PmYQ`‡ ÿý“á‚c¡Es¸KàB –ëG¤µ+ŽY êl\hm¾[¤s¡U·lŒ\¨ô.~­q¡20f¤ Õ€4©q¡ƒ¨Î4ZAv, Z‘Mp•\¨ú¼O³&*£i¢Ûà`hž±9âÚgœ*J0´á4ÚÁP±Ü˜}à`¨†gĵÕÙלgCN$iil¨Zn‘ ­g²PÃÙÐg¶ •ÍÅÙІéÁyíŠޝn˜÷U_ÌÙÐvøÑaƆj(D.ÕØPÁR<0Wýô3²¡{§È†j F^ÓØPõ§ùË •{ÙÒ±³¡êP“K76´"+åˆl¨þ*u6´Á¡%9kl(íD6T¿1YUcCåw5#6 ÕpHAcCõZdCõqÎÀlk¤CúÚØÐ:-«ÊÑÐ ?J‰í}½zo\ÔêÛqÃÒf™XÃÒÄ:ÆŒ'Xä1=H³`Ý5Ç*Ž5æ9í.MÍ|^¤‰ÀAýÏ%M$©Ô¥‰ }nã`ÒÒâN UwØÊ¬ù´4ÿ¥LdìëLöRf©Ê-e릞M™™ÿ=*Sì ÛÁ”Y±“m­@eVM¸JA™U £2+ÎîNq#=(³b¥‰3eÖâA¡+³by2¨LEŒÛVfÅf\3³ÂIf 6a‚máã¹0Aòô¸‘BÝÉ›.±qß„ëoëHQ—¨SfÔ%ð­zÑeÅ’VºK¡|éR^)—]—ò{[®Ëš¬_ºÄ›H]b—Ž|F]"Ñü5u©?"ϨË6,ÛÎtY¥Õu‰ ¢Í(L„Q#e­Aʈ̶2ã í0‹iÀÆö¼N îkíëv­g×}ÚÞwÙ%Ûå÷²íÕì’íò;|W¼dÛò²8oî%ß;|phû7…Ð!äË”ö“ÏE9ÖZ¶V`°lÅ%·µ—OÜV¨å¶v`à¶.Kf+,Ÿ˜­XkÙZÁ²—<ÜÖ^>q[¡Ö}£Ü¶.“ûwyÛúÔ¡í7zxO/ðìÕ=jþõiƒ¼ïž7ÈG[Ÿ·«žrýÍæŒ¨8­Y‰žÍ‡VÍ“|(äȇVä7—ȇj@R#Z‘ž"º]±ƒj|híHßP;ƇVdnW5>´b x>Žñ¡uxªƒó¡r•yj·Êz0¬r>´"«@/2<´"ÝH«á¡r‘éÓñЊ÷©Îœã¡©gd·ëô}g­'riT4<´bŽY#ÇC+° 9*vçó:ªóég<ëºÏ7v´âùÐzvJ¹ó¡l°€xhE† árÃCåÝT~<çCõ‘y¼¯ñ¡õ¬¶‰¾ó¡úÓI|ZuN6²Û{â÷ÀnWœD|Æã®÷Kw@Tîhþ²¢z+ÂÜ\h’o\ÑíŠ|ÑmyÛ¯ÓùP-‰x¨\d åï$·uоlªPô4é(ÊQ,psQ–“3EA”Gê^bºÄ Ô•ZÂ<—„=êaǃ,]bÕ!]tyØúÞ’e:m·Ù%ËÜš‰Çe FŠ».¸,qæ^Šg]WœŸA1»,Q‡'Å»,3Ò G”%V7ˆˆ»,qH9÷äq]Væër]꾺gÔe6]¿t‰eÞÝu‰„8õW©KýsF]Ðé3êºéK—µØvGK—()ÛÖî,àºÄ|>7Cp].wéRçêsÔ%>Ñ…ÛÖ‘³GaÖî'^›.1­_ãž uõÈmWÅÎjÔ%ÖHlÃÓ%vƒ*=èt÷ p]nØÛu©bä¨KDÊĽ]˜íˆÔvEÖ { We; ¯_ªÄ–¾¼µËR£®|ª éJFfloÁëDßÿ¾Ö¾n×zvÝç¨í}—]²ý|/Û¾Ì.Ù~¾Ó×ÁÖ* ¶¬,ØZ%ß;fpjû͘á=ÔöþYN!GwïéçRŸ%ÖZ¶V4°l…h`ÙZµ–­PËmíhÀmÅhÀmíZn+ÖZ¶V4°l…h`ÙZµ–­Pë¾Qn[ÑY½oÌÛÖgb§¶Ü á=ÝÀ³w÷(ú×§-ò¾#ø…ù`ëSäöÐ0  l»àì[ 7Z4ÛW lƒC5©’U8TF Ë›u8´æz=*»êŽó‘­škéЊ<² „Ckç¹Ý›•1."Ûud;ØÑЊü&Gª.,éfcC+Áyü…±¡2>ÚXîlh=al’¡nªéS« ?Ø^‹“¡ârÛf9F†Jmµèdh¾¹Š‘¡:]M ÝÈP&ÝD`»Nê‘ oÕfàœ ­3ÙùÖ†V97ª+:êN9Z§"N†Vdió˜CC+ÒÉõ»9ªW•lkd6 U6´bÌïƒ*Zuo!0ÿ+1<ÛÂèPù, •o2®´¶|Ï%34TîìçžÊ(Ç@PECµÕð>$C劭d¨¦Ë©J2T¼uŒ ÕHèˆgój”½@4´"ëß8uëÇÏñ¾ýb—"u³¬xXvéÓ6z]ŠT”àÜŠ,Øáˆ)T LgäáˆÕdBèy$V¹fŠŠD>|û(Tœº×j%Ž&dz”‹2'£:—(³©Í‰Ô§#ÒÚÛ€ö‰Í•ØÄ]”Å71[¢¿R"®­ž<¥â¢Ä7A“Å'é—& ¤¯¯ÀðËE“pÕG¤µ«²P¢&‘ðÓâáõÒ’l]s‰8?Ç\”ÕŽ~\šÔÍ fÔ$F\v=®Iì q‘da$ ,GE¢¥Ÿ5*ƒ$m’¬y¥å’Ôc€jT%rLj<½¾‚;éq}£—ì%È–—æªÄy"LÎrYê¶=ÊÄš#Ü”%‚;†Ûd‰$C¸M–ØÈ×ùlÊøõe‰d±ûÌ%‡,#õ€c{^ãD\êø5»Æ³k>Gl‡{¬’@cXYðkVÉvú¼¶VI°eeÁÖ*ùþ4‰í·ÞAlÇWDù@<~*%‘/uÜÒ ÜR hi×qK±ŽY aYºj)Ô1K—:nin)†´´ë¸¥Xç®1nK·öÒ„·¥Ï„ Nlÿ¸aÃÛ²úÞîdþú¼ ÞIÿi¼³ó9j{Üg(}Od»Žñ›-謥$!ZzrÄ×Ñ‚)Ôi8¶"¢n%žâ[1Î84ªˆ¨¦[ˆˆj0Ñ""*ƒã­ºçoED´6ΰþq!¢µëžZBD´¶iþ¹#¢òàÙN§2D´Âû:#"*®át8–ˆ¨x¡ÓaC"¢ê…:ªˆ¨.)øHDT£f|¶"¢âÏu®/†u¼@ކˆV¤s8Ÿ­ˆ(ÃxНxÉ~PŸ"¢:µ}Úø,#/†[Q ] 4%"Ê•‰ˆjš±âDDÕý5,“ˆ(ƒ™HlË=‰½ër‚¸‘$U ÕŽ·!!oDB´â\ßc¢ó…$6Œ­pƒ[$D+Îv§Ãa„(—ø( D5¼0 œ„¨¾– Ñ >¸Db[êôÅŒN .ýe!ÊŸL+$DåƒTóŒÕÕn%¾$•ÓÛQÂ$ô4F¤ë‘í¢g׋ ‹ûw&È‚d.ã±)Hq¤m‚ œ Ö‰·3GdÂ1¢"Ñïó“¸"Ñ„xÀ½§ŸnŠÌÍf–"³Ÿï‚ÄigŽ‚Ì@7Z$F›·P¨8Ó»F=bæÃšƒé±¸»¾ô¨G¶¥­GÈÇÕG=âÜ Û£Àôˆà!Ç41©[ˆ~.rÌ8µá"Gd7±ór9JëZçlCŽÕ÷N]r¬ ¥‚nˆgÜW¤Í¦­F¸Ùqû„ bÆS#ün;ÂÓÔ(a¢Å¸T#d}kªùUv¾ ©aÄ8£-YW¡jÔ쥋u£F5ê¡p9ªË"uóÚ-ßµG5â »ϸ'\Ò¢‘C–ÚV#>Â(×à`†[¶ÌÀMzɯ³îL2_.‡k?\·k=»î“‡k¯»¬œV^-Ò±2¿ÏÏ¡„ÜHD±Ã{I°åeÛÖ.Ù¶¾3°-ñ)è·®½~Ö:Äz}À×§ŸË±µÜ–ôqºcöå%ÑÖ®å¶b­e Û’çx ¶—\l­ZËV¨µ–ÏY{I´µk¹­Xë¾Q[«™¾>4æ`+ÔúðáÚÒ5ã]h{'y²_Š!Òø®‡kÿJðì½= þõYk|èž·ÆG[oÁÚ;NÀÂëù‚‚–Œ~&Y}æ¯/¤¶Ïóëüö;P™ÎPø/p¿YñŸ¿áä7©É·|ŠcS>|. ¸\d xJ ÏŠã_ ïeâò¼¶þÙAñv:(.ÿì xûÍ 8NØMÅØöÿ÷[Aq=&ü PªD@6#éPjÙèK‡RÓ8M˜N¥&¬$pVÕ¨TñH,%بÔ| ùÌ'Ðá늓|KTb©95æ½8–*+D#—š1nºÛ†¿Ö¦/ÄR3rYlëÅRs:×hO,U¢Ûa †¥f8z¶¯±ÔŒ©`zɆ¥fÌ&–Šk à ÃR3Ò*8iXjF’==tÃR3ö˜ìKÍØË²EP\~Kut•OŸîIq}{%’â;Ø·HŠçäGí–šq>Ý#ÃR¥J53ÄRÅ—´]KÍpL¬„XjÆ.®3ž, eUmXjF66ã5,UÃ…ÏHênñáŒ3SdÅ3fzy¢0©ÔŒ ^dTªÜ<1Nv*U’>²S©‡·ñ*£R3ò“%¤Rõæ3°âj¸EV\|qK 42UÓR625c™¡“·î/'—·*W%’yaÅŽùÖquɳ`Ü×eÙüÅ,Ybšt¤ Ë„MélÙMe™ºçLº,%dª·T™°+.ÉR>‰‡&Ë4Öv Ð¥TðIÓeÂ)m]ÊÉ·‘£.~,§ÓM—éLÞC˜.“F¯=è2Øj9ÈRZ’%a¹,F3Fš&Ë4š]dª”{ÛF &JùΛ(å7Ù"†iR:?<Ü4™ärÊÄ4™°úÂéÓ¤ÔµÖ4)©Ç¸¦I¹Øv"7MŠFËuû)±s‹\“ ›—ˆŠëÓhåšL˜Â9Ï É„iŸ5™0)2ãþ RÇtM&l^l;:P”òël>ÃE™0qÆ ø„A“ óR¼•iRyøn Ô¤> ±ãªÉ„i)@vMÊcÖ‹ë§£øM’ÏóÔo÷\±âuU­Cx—ƒ³Ü].•׉ÑÑ}­}Ý®õìºOžé½î²JB$äeÛáÛ%;Z'xo[^mYY°µJ¾wTµ`ñ7£ª÷œé½~Ö:;;øÄÏ>—j¹­/¹­/¹­]ËmÅZËÖŠ—–­/-[«Ö²j­†´â%·ã¥ÕW-·kÝ7Ê`+xô÷9ØúDTµÎôþ!£ª÷tÏÞÛ£à_Ÿ¶ÆûNàyk|´õÞ¨Š‰ó×£*lgõ,¡ð_ÖWoT¼DUŸ gœd×dìÏüV’=<ŸË&=JKérÃeu ×HÄqYˆÚõÜñ4u\6cqžUl¸¬¸ÅÉÈWÃe3²ØˆËfÝÕQâ²9ù†©ŽËjDÃc‘ÉË2byÙ¸¬\c™ŽËf€« 8.›õH¢íÄe3èkÄeuR˜¤eŶÙk§eÅ 8ï6ZVýiœ–ÍØ¹DŽ=#ëF=!§euκ‘l'-«Îõ…–ÕwÃãŠ–ÍØŸ¬.iÙ Vá >K\–ó²hY ã-WÇiYqmúõØqõ¿GÄe¥äà9éFËêIÂ-›5>Ò²x ÎÕ:-›‘ŽÏ“Ó–ÍØu4GZ6ãh9}ƒe3¶ñìñ€ãœÆl°¬<_³ÃÔ –ÕP×=–Õf¢MÔ`Yy¾v…eåÞÓNE&,›³o æ°¬~Ì ,«uÔãrXVcDXÏ„–ßqì‡Ëù²ÁDÂ&¯êœ.Y*a7˜HØÇH½Œ%KœxUê¾LW¥4¤ò]”ò åpQŠƒhAœ‰RÕO+MÁD)U|k S%ƒ“T™`-2ì ì­˜(õ"#Ö)Jéì¸xWeB@G]˜*µ Ê„Ÿ’ƒ(u댢”’n(¼‰2a­XŸØE©a›¾a%ò3ˆR®"«cšLØÜxF„]ÅCQjzMjô—[ÐdҜ̨IùÙvȇ‹RêØ$Œ‹2¾8å¢Ô_`P;E™ÛyFQò^#ˆ2ÉuU&`Y¥U&Ýw>Uj\6ΠÊ4 rU&d¦,§*õ§#¨2!„ŸáØq©bgVº*“"gPeB¶%¹wS¥†GDØå‰íH‘gçŽï¹]?xy4^''÷µöu»Ö³ë>yîøºË* ˆ—mk—ì@d2ÖT¬$Øò²¸’à%ß;¨Yûo j?à:ß;Nô?ù\v¾w¨å¶v¸â¶.‹@f+,(™­XkÙZáʲÜÖ^Pr[¡ÖjH+\q[—E o€{AÉlÅZ÷2ØŠKw9ØúÌR‘;þCÆ4ïéž½¶G½¿>mŒ÷}ÀóÆøhë½1 f(ÛÓˆf¤)¢qºþyDó9º~À½I#p¼ +*y–„T”ò&l†Ù#]Ÿp¶wf AÞÈ]gìä÷…ùÆñê¨ÑŒƒ¼{~ÓAÞ„œïIÞ4»íáâ$oš"tò¶Fò&¤õNO’W£«û¤;s½l7¯¼äÍÀ ÈàÈ+uÌ«tW|v ;äÕ%õ‹äÍØtËÐ^‚¼êÆ÷Ø'lRÆãÛ äÍ8'fŸ¿,aGµ¸ äÕY×AÞ¼Îs7t‡7È«v2‘{‚¼òþl;Zyó!n°~;yÅgO¸È›q²}§£Ë½ì8FyµŽr²ÆñòMDW>Œm6æ o†SJ®Ø@^ÁŽòÊ—±8ÃAÞ¼Žg0W¾¯m˜ì o^R9È›ŸyvWWÏ. ¯¼esœåe³ˆ,¯\ÕèN9Ë«sä—˜óáéUï=-·]”™m l+³¶ë¾ ¹«Ä>áðœ3"öðŽŒweâ|Iî¨aÒl¾™ì’&dcÛc˜4á}¨G»¤‰ìQ Ó—4QB-¸4Qr9=!÷j¦(ÍÑlƒ%×&=ã Í„ô,j\š [h”ÈØëziy“¦:êGdì5d‘±g3£4 ÌAšâP¦ÒÔ?)“fBPÇcÅMš ÙˆÜïÁ¤©Ë †¹4Õ·OQ™ÈâäYé¦L©bkX®Ì„ÌÎQ‚2Â’{:îgPf¯e—I3ÝÒãÒŒ%”¦”L"¥™Àæ•x6zÂ’Üöä™°) ÏO7i"îJQš¼hi¦sõ&MùéÓ.M©c[ º4€0IoÒLö/[šúzøµÜw`­îâšušñN2ó“‹—Wãub|r_k_·k=»î“‡£¯»¬’‹xÙö¹vÉŽEÖQèÛ–—D[Vl­’ï×,Ìþ­¸æ]‡£¯Ÿµ!néÓÏÅCÈC-·µ#·#·µk¹­XkÙZ˲"–ekÕZ¶B­ÕVÄâ¶bIJàªå¶b­ûFl§ú¾1[ŸˆkÖáè?d`óž.àÙ{{üëÓÖxß üBk|°õÞÀf& ËéÝ¡MŸý1´éó­Šß!´ñ=®¡ÍŸbÒ,áK ŽuÐîˉ㔛Á=FË#¾)‰c‰w8Tq,n¡N'Ð<ވㄭ­æÏ8ÖX¦³„ıx­”µÇâÆ–úfÄq>ì,Ž5ra¾œ1Çšä‘cñú³m`È13¾´Äã¬'㱤yRSc†#Ǻ¦Â´;CŽuy‰7's¬‹ƒÔ²¤¦Ó¶¤2æ8ƒ´.ñàv]PØc] ¹œÛžA]tâÄDŽ3csoȱ<^¢ƒçÈq>Òõ€h½¨Åmô §¸ @Æ©l|7Æk¬E*™ÈqÂìµ!ódŽ3>ái„±2ÇÚ»ÚQÎdŽõÓÙ ìdŽ5DJq'€Œ‰{ÊgÌqÆè1â!ÑG•xH´_gdŽ3¶À³'$sœñX~´2ÇÒÜš§H’9Ö¼vÃ’9Öå®i”¿"Ç[=›a"Çš{i0³uW˜‹¶³Žßµ€üzý^[— ?U=À¥KL¤Öué;^/] áÆ&L=sFa"Z™Q—zØêuÙº·±t‰ÔŸš‚.Só}]— ›²ñ™0SÏÎÖ›0¥äôÍ8¨L Üq:WfêãtôŸÊEYŽ©+3¡S¯ß•™°`A‘™2•qªa7ù†~¸2VÒ<:S¦>1wõ0ej&X‹ÒL›F».M5s¶ My>—¼IS3ÕJ”fÝ¢o×fêž èÚL8þé²€f rÓ¦.’ô¸€®·•Ä)O˜-ÐÄ©yh=îÑ!Oè9°&Ny”©™t¶••™pX'±:SfB´bG³S™ æ¨LæÊq7y˜ÃUGaâWžA—÷(L©rwx».ã1=Є)ƒP73æNb{˜~——¶N`<ž¶¼¼¯q t.uüš]ãÙ5Ÿ<¼}ßÃK"çceÁÿZ%;0YGµo[^mYY°µJ¾?çc[¼¹xóžÃÛÃ+²ƒÒcóø©xPz¬c–Bðb–.!ŽZ uÌÒ¥Ž[Ú¡‹[Š-í:n)Öñ&´³t oØðv³t©s׃¥è~_šp°ô‰ÐfÞþC†6oKþé;»“øëóöw'û§íïÎλ©¸’XºÿáCß§àíæÓGËãèà÷)@òzòƒä‹NÊD(­Xt¡ì#-ŸpüÉ✱aèhMi»PÑ ,Ÿ‘ŠNâ¦Ù™‹„¢“ž¸aG¼)pìâå$ëŒ3Kf<ÉZJª‘M(ZÜÖäÏG*šþ9ïE*:§äGqF²wX²W² Õ‹Öô/; Xt†/×"­ a¶ÝAb¾Zr”šX´NÉ­Ixtá ‹Ö„0;ùhÖ–¥<9­Y[vcbÑúj ê'­pȹw)G)¾U±huÄ‚PÖ)#KÄ(nbѺaû.tŃ0{w)ä´ƒ¡ ŒÖè"Ѭ3ά{›½³qߣueÇÎŒ'±-W‰Yë/ÊüÕ£õãûß FglÜuôœø‰@ºÅm ¤Ä–# FË·,×m ãçe`tˆÖ Œ+Îçû€’˜ùÎm ptÍ9fÐc‚å3Ê™Rl*[Žv´Î’#ö“jq—¹8­ ¨Glxe²6=âí¢Gt¯$o\:iQ¢ [«~w RC³CA&ìrDAj–œí6BAŠ0laÀ™p0Óˆû†$m\3RìT‡ø)H¥cZ¤.,[»¢ ¥/ÊÞFSÕ†x¤æ˜Ù(HyIÃ÷6  9aÓ— åïÕ©Hi'ÕÚŒ)RÑCЍH¾Ø±™°çu ‚ÔXÉqAdB™o$¢‚Ô¸£Î%HM€ãÖ-&HMÎâD‚ Rn4L¤ 5pnAŠ•Ã·J¡ 5jQI·V;$¬‹Y—25íoÚ,‘ 2é<ƒõq}#‘ÆG‘Çå¦ ªG]ïÉq£‚4Ö6¦Ç„c»¬õ¨y¦ó\-‰:•9aÀI¤…X«É8Ü?ÿ–Æ×¿é¿b0þúúMÂNŒ¼ˆµåëþôW_~ú÷õ¯õÿ—eWü‹üïºî?ῬË.ö¤‘E×êËL<S:l‡'ݯ˜ ‘˜vÇÛ„—ÀÄß|ùÿ¡Š0endstream endobj 6 0 obj 17382 endobj 4 0 obj <> /Contents 5 0 R >> endobj 3 0 obj << /Type /Pages /Kids [ 4 0 R ] /Count 1 >> endobj 1 0 obj <> endobj 8 0 obj <> endobj 7 0 obj <> endobj 9 0 obj <>stream 2021-07-16T15:25:07-05:00 2021-07-16T15:25:07-05:00 GL2PS 1.4.2, (C) 1999-2020 C. Geuzaine gl2ps_renderer figureOctave endstream endobj 2 0 obj <>endobj xref 0 10 0000000000 65535 f 0000017933 00000 n 0000019448 00000 n 0000017874 00000 n 0000017740 00000 n 0000000267 00000 n 0000017719 00000 n 0000018026 00000 n 0000017997 00000 n 0000018090 00000 n trailer << /Size 10 /Root 1 0 R /Info 2 0 R /ID [] >> startxref 19670 %%EOF blis-0.9.0/docs/graphs/large/l3_perf_nn1_jc2ic8jr4_nt64.png000066400000000000000000006551021422157504600232470ustar00rootroot00000000000000‰PNG  IHDR¬øSzgAMA± üa cHRMz&€„ú€èu0ê`:˜pœºQ<bKGDÿÿÿ ½§“ pHYsNNÆÊ/¥tIMEå-Ð㡚:zTXtRaw profile type xmpH‰­VK²ã ÜsŠ9–@²ãØMÕ,çøÓ Nb¿ç¤ÞTÅ.ÿ@¨[_þþþ~á˜d– ›6Ÿ=Údj7Ëž$šX6·ÅªñÚn·[Çøb‰#Ù5§¢1I!;ÛÒì«caV_SÍÉð„BU,צ5®P²F)>ÛäQŠTož/ÁH€ÀÒ"’4KÚ’‰ÜUø¬+Û ùÚ$‘ß¶Yuå9Úî8ºŽ‰‡x7æ©c·nÖœJŽÂï†sû…î*RuÁ5IÑIU604;u•n ï7‰˜¯j0vð0]Á??Ãä˜$ÑÙΨ+x5ï‡T‡Ô®Ø¥tቷ2 Œð(C žêˆMóΦýì[òü.tázˆIE4+Ò¸€È0)Òcg£R!Â÷B°Yæ.•úp8£ˆã£xm¾ÕðŠÏX²3Ò=†qw1a›%ÏFQqÀWLˆT˜(P„-F4ÓÍJoµW†±à? ì™u60 _8Šáärf{W´¦BAµÆPƒ „Ñ3‚+ÓÓrÂYqÞÇxÜߣnª+ G­O¥£Êv\z,™×°áÿp¯•6\ˆ ò^’ZáËM%Ǭ{½%\Š”9©,e©„·ì4QÓ˜ª=2"ÆØ¡`€yÍéºÐ‹´Iñ¾4î‰~œ9HƒTÐ`/ʃÉ~’=PXîî¡Ü˜eö-ÖZJ;qÀ&÷ö¾*š;žØM¶¼g¸4öìšÌö¸ö“o–oX0C *Z6NyWS¯J*¼ó „ô¢cFÈ‹mÏnI9Ôm¶[ÊÚß}³·ÿ®lÅÆÃE…a»†³©l`¦=–Ð)Þ»O/ɱ”“¸¶^O'îcÇ*{4ÿþ9!õ¼;Ý>‹ îÇB`çE†ƒ‡æÖS²Zßyqßa«õns>¦&qˆ{HÖ—ᓯœÃîƒSâ©g6Óé«1¨AæËÖ…ðšÃSÅÃw¸§txW_¥}G}Œ~û@ÑÆ ágøŒš®è3œ>Ɉœ.{Òõõñïþg[Ye3|¸¿caNvͱ¸ª€IDATxÚìwxU‡ßÝôÞ)z( ¡†Þ› ‚ŠQD”^U:Ÿ¢t ½÷*½—@(¡„T ½oÚ¶ïkB -É&8ïóäIvwvöÎäÎÎ9÷œó;2­V«EBBBBBBBBBBBBB¢”!×÷$$$$$$$$$$$$$$òCrX%$$$$$$$$$$$$J%’Ã*!!!!!QF¹wï£GÖ÷0$$$$$$Š Éa•(£DGG³víZ}CBBBBB¢Ø0Ô÷$$$^4 ÉÉÉ$$$`llŒ££#fffhµZRRRˆÇÀÀGGG,,,P©TdffbjjŠ¡¡øªR©Tddd`jjJvv6FFFÄÅÅ‘‘‘³³3VVVDEE‘––†öööÈd2²²²Ðh4¨Õjbbb011ÁÙÙµZMll,J¥WWWLMMõ}ª$^#4 ‰‰‰$%%abb‚£££nŽå\‰‰‰鮉œyoff†J¥’¬¬,ÌÍÍQ*•h4´Z-QQQh4š<Ÿ™žžŽ‘‘&&&ú>¯Œä°–RRR8}ú4QQQT®\®V«¹té·nÝ¢nݺTªT …B««+r¹•Jŵk׸rå îîî4oÞ   XYYqøða233i×®ööö=z”иqcjÔ¨\.'** CCCbcc9wî+VÄßßŸØØXΜ9ƒZ­æÍ7ßÄÒÒRß§K¢ ræÌæÏŸÏõë×±´´¤S§NŒ;+++˜={6Ó®];ÆGzz: .äÃ?¤nݺòóÏ?3|øpV¯^§§'ëÖ­#66–:ЪU+/^Ldd$5kÖdæÌ™ÔªU‹mÛ¶Lxx8GÅÖÖ–O?ý”;wîpàÀÒÓÓéÕ«S§NÅÈÈHß§Kâ5@£ÑðÏ?ÿ°`Ánß¾­­-]»ve̘1˜ššröìYæÏŸO`` têÔ‰1cÆÇÏ?ÿÌСC©^½:çϟ篿þbîܹlÛ¶¸¸8=zÄ–-[øå—_tŸ©Õj9uêëÖ­ã‹/¾ÀÛÛ[ß§ABBBBBâ•‘V=ÁgŸ}Frr2–––„††Ò»wo&MšÀòåËY°`^^^,]ºggg4 ýõ&&&Œ=šÃ‡ãááA\\VVV,Y²„ÆŒC¥J•P*•<|øŸþOOO’’’P(Lœ8‘M›6ѤI&NœÈ£GP©TÈår®_¿N«V­ˆ 44”M›6±|ùrlmmõ}Ú$ÊÆ £E‹,\¸k×®1fÌ6lHÏž==z4åÊ•cÿþý„‡‡óå—_âííÍG}D`` {öì¡V­Z°víZbccÉÌÌdÛ¶m´hтիWB¿~ýà—_~ÁÔÔ”wß}—+V0oÞœž={²dÉΜ9ÃÔ©SiÕªmڴ᫯¾¢qãÆüôÓOܼy“o¿ý–úõëóÖ[oqúôiªW¯NµjÕP«ÕüñǤ§§cffÆ7X±b}ûöeþüùº(ªF£áøñãŒ9’aÆQµjU}Ÿ‰ÿ ¬]»–Ñ£Gcoo¯ïáHH jµšõë×ÇW_}¥ïáü'jXõÌ‘#G bíÚµlß¾qãÆqëÖ-Ôj5J¥’гgOd2ÎÎÎŒ;–7ÞxC—6|æÌ¾ùæúõëGÿþý¥L ½ÆÆ¥ïR‰×FÃéÓ§9|ø°¾‡òŸAŠ°ê™œZ¼}ûöѨQ#Þ|óMú÷ï¿ÿþ;}ûöE&“áëëK·nÝ `óæÍT­Z///®^½ @»víØ³gM›6ÅÅÅ…¶mÛ"—ËñôôàÍ7ßÄ­V‹——*•J7–Ö­[ãîî@… °··§}ûöÈd2êÖ­‹¡¡ažz) ‰çaôèÑÌ›7åË—ãïïOûöíuéŠ#GŽdÙ²elݺ•FѱcGZµj@÷îÝùå—_ˆˆˆ 22 ZµjE\\FFFºùšƒ r¹F£»¶rpwwÇØØ8×ö9ÙÆÆÆ:Ã_B¢(077gĈŒ?žŸ~ú‰f͚Ѷm[|}}øî»ïX¸p!«W¯¦I“&´oßžš5kЫW/zõêELL gΜÁÅÅ…Féöíãヵµµîqvv6_ý5)))üðC>|ÈæÍ›ILLdéÒ¥|úé§\¾|cccîܹÞ={8pà'Ož$$$„ääd6n܈££#ƒ&..ŽM›6‘À{ï½ÇÀ9vì111<|øíÛ·ãââ§Ÿ~JXX[·n%%%…òÞ{ïIßáEŠF£! €ßÿ«W¯R±bEz÷îÍÛo¿ÍÁƒ9wî))),[¶Œ7Þxƒ;vP»vm¶nÝŠ¡¡!3fÌàæÍ›¬X±B0êÙ³'ï¾û.FFF¬_¿SSS.^¼È‘#G¨Zµ*C† áüùóìÚµ ­V˘1ctvüé è™:ðù石hÑ">øàÞyçÖ­[Gvv6áááX[[ëVÕe2™N°C¡PÅåË—ùøãu?›6mÂÈÈ¥R‰±±±NØ&‡œ}å‡Mžç Û^BâyÐh4Œ9’µk×òñÇ˰aÃX¹r%Z­–Aƒ±~ýz† BVV#FŒ`áÂ…€ˆ$y{{³{÷nvìØA:uðððÐ÷!IH<###FÍŸþÉûï¿OHHC‡eãÆh4†κuëøøã‰çË/¿dùòå€X0ôòòb÷îÝlß¾FQ®\9ݾs}7ðý÷ßóã?²víZ.]º¤ï×xù駟صkä­·ÞbþüùlÛ¶ [[[¼¼¼011ÁÛÛ vìØÁ¸qãøçŸhݺ5§NbÔ¨Qܹs‡o¾ù†ÌÌLÌž={èÓ§¾¾¾Ì˜1ƒëׯsäÈFŽITT£F"&&FçÈöïߟš5kòã?¤ïÓ"ñšϨQ£ÈÈÈà›o¾ÁÞÞžo¿ý–ÐÐPÜÝÝqvvÆÖÖ–5jžžÎ²e˘8q"ÑÑÑ4nܘ¬¬,ÆŒÃýû÷1bÕ«WgÒ¤I°qãFFމ¹¹9_~ù% 8;wî0hÐ ˜4i‘‘‘ú>¥)ªGrÔQ{õêŨQ£ âСCŒ;gggìííÉÈÈÈõžœÇ¸¸¸Ð¯_?æÍ›§{ýáÇ( îÝ»§ïÓàÑ£G|õÕWL:•!C†0hÐ &L˜ÀæÍ›éÓ§ß|ó Æ cРA 8ùóç³bÅ &OžŒ££#]»veÑ¢EÈd2–-[&¥:J” îÞ½Ëĉ™5kC‡eðàÁ|ùå—lÙ²…víÚ1|øp&Nœ¨»&&OžÌ¦M›1bnnntìØ‘ùóç£V«Y»v­Nˆ/? èÔ©ìÛ·~øµk×bgg§ïÓ ñ²k×.Þ{ï=úõë‡\.ÇÍÍ SSS\\\¨W¯æææ´hÑ@¤Ç¯]»sssÝ>ªT©Â„ pvvÆÂ‚öíÛóã?âééI£F8wî= fÍšL˜0Ôj5}ûöeæÌ™ºÏ»xñ"ÑÑÑÔªUKß§Fâ5"11‘ãÇsæÌ6lH›6mhÒ¤ YYYÔ¬YOOO iÞ¼¹Î©¬[·.sçÎÅÐД”öíÛÇæÍ›éÞ½;;w¦nݺ¹27nÌØ±c‘N¿bÅ ¦M›†ƒƒžžž 8ääd}ŸŠRaÕ#†õë×3jÔ(ÒÓÓ©R¥ }úôA­V“’’BÆ Q(?~œôôtÂÃÃ9qâ„îý-Z´àÔ©S\»vŒŒ =zĘ1cظq£¾MBB‡ƒƒW®\aÆŒìÞ½›¿þú‹C‡ѲeKlmm¹}û6Ó§Og÷îÝlذ-[¶èVâZ¶lIBBr¹œúõëëûp$$ž [[[Ο?¯›÷«V­âÌ™3´lÙ{{{®^½ª›÷ÿý7ХƒȾ ÁÚÚZWïý,LMM1bQQQüý÷ß¹J>$$ŠŠN:ñ×_ñù石råJêÖ­›ë;ûiüýýó´ sssË“æêê ˆyü䤇‡G®r™L†‹‹ fff….æHH¼,¶¶¶´hÑ‚#F0zôhΜ9CÛ¶m ´kÑ¢…n>Ó¡C¦M›Æ7ß|ÃhÞ¼y®ïó*Uªäz¿‰‰‰n¡ÇÊÊJÊr|é*×#4k֌իWÓ·o_\\\¸yó&­ZµÂßß;;;Þ~ûm>ýôSüüüHJJÂÈÈ333är9½zõbýúõôïߟÆBZZãÇçþýûú>< @üñ«V­â‡~ÀÎÎŽ÷Þ{ÁƒcbbÂÒ¥KY±b?üðVVVôèуÁƒëÞïççGùòåyë­·tŽ««+Ÿ|òI®Ò°aÃtõ2™Œ¶mÛ’••ˆ›HJJŠîFR¥JF­{¯µµ5  R¥Jú>]¯ NNN¬\¹’Õ«WóÃ?àèèȧŸ~Ê Aƒ066fÕªUº×lmméׯ_®yïïï½½=}úôÉe¼·jÕŠ´´4Ý\vwwç‹/¾Ðé L™2…˜˜”J¥dÌK93fÌ k×®ºÈÉ“'óÍ7ß0|øð|··³³Ëcx>·1þ"ÛJHÎÎά[·Ž}ûöqâÄ ÆOVVkÖ¬ÑÙOó¤2vŽísøða:ĬY³HHHà矦sçÎRÆØ ÝÉôL“&Mضmû÷ï'!!®]»ÒºukœœœÈÈÈà½÷Þ£Q£FÒ¢E 6n܈J¥ÂÈÈccc–/_αcǸ|ù2þþþtíÚ•òåËãêêÊš5ktuOFFFê rsssfÍš¥[õœ5kV® çƒ>à7ÞÐ=öôôdÓ¦M¸¹¹éû”I”Aš5k†ŸŸÉÉɘ˜˜`mm­K‹ñóóÃÛÛ›ääd ±±±ÉÕ‡øòåËÒ¥KÑR¡B† –ë3ÆŒ£û[&“ѵkWÝã:äÚ6§î)[[[†ªïÓ$ñ!—ËiÓ¦ 5"55SSS¬¬¬tó¾iÓ¦Ô«WäädŒ±±±Ñ½¦V«9{ö,vvv´oß>×~;vì˜ëqÅŠs-¾¼õÖ[ú>|‰×”¤¤$–/_N‡˜;w.©©©,^¼˜E‹è°JH”EnݺŶmÛ:t(}ûö%::šÏ>ûŒ¿þú«@‡õI"##YµjŸ|ò Ý»w'>>žÑ£G³råJÃ*ñüH«ž144¤ZµjT«V-ÏkwîÜá믿æÿûo½õaaa\¸pèœK{{{zöì©kõ‘ƒ••VVVºÇr¹œÚµkçz\¡BÝã§ÕVti ÒžN]xÌÌÌò¤€å`jjš'e `ÕªU¬Y³†jÕªáëë+­²K”9,,,°°°È÷µ‚®‰Å‹ó÷ßÓ¸qcjÔ¨¡ïCÐahhÈüAPP#GŽD£ÑpãÆ\‹ÙJ¥’ŒŒ ”J¥¾‡+!ñÒ¤§§3{öliݺ5áááDEEѦMÝ6YYY¤§§ØAcþüùÒ»wobbb—J›^½:¬iiiÄÇÇS±bEÝs†ÄÄD±´´ÄÙÙù?+ç\­Z5:vìÈ Aƒ(W®±±±Ô«WO't QúÑjµ„……áää¤3Z5 QQQddd`gg‡­­­ôÿ,333:vìÈ|€¥¥¥¾‡#‘YYYDFFâéé©›ÇJ¥’‡¢ÕjqppÀÒÒRZlxÌÌÌèÑ£üq.¡ ý Ù*±´´dÆŒüôÓO¼÷Þ{R¥J-Z€¯¯/åʕ㫯¾bΜ9Ô¨Q#O”J¥.£ÀÎÎŽÖ­[ë¾#LLL¨W¯öööxzzbgg§;·NNN¹êeMMM©_¿¾$0öŠÄÇÇ“­« 1Ç=zDff&öööº¶qÿ¼½½™4i«V­bÉ’%˜ššÒºuk¾üòK]¿ìcÇŽñõ×_3jÔ(êׯ¯k•P¾|yfΜÉ_ýņ tózüøñÔ®];W’‡‡ 6Ô=677§aÆ.xþ×iõÔ°M¥R±fÍNœ8ÁÊ•+uÏŸ?žßÿÐÐPùè£h׮ݶG­VHll,öööÔ¨QCš¼eˆÈÈH† ´iÓ¨_¿>J¥’ýû÷³fÍ’’’¨\¹2ƒÆÏÏOßC•x)Ž9ÂÌ™3Ù±c¦¦¦( þþûo¶oߎF£¡víÚŒ1B'¨"!Q–P©T¬^½š3gΰlÙ2ÝóçÎã÷ß×-H~ôÑG´mÛö?c«$%%qïÞ=]öUN¦€F£!,,Œ””ªU«V`VDé!--Ù³gciiÉwß}ˆEÇ}ûö±fÍ’““©R¥ ƒ¦^½zún‰Á£Gptt¤B… º Çììlnß¾©©)^^^öŽŠŠ"<<;;;*V¬˜§¼Äó¡·¥’K—.±xñb¢££uÏ%&&2qâD¼¼¼Ø°a}úôÑõâú¯b``€¯¯/:t ~ýú’³Z†HHH`ƌܻwììl™5kýúõcýúõT¨PñãÇ“––¦ïáJH¼0áááÌž=›°°0´Z-Z­–­[·²qãF&OžÌÒ¥KIIIaîܹdffê{¸/ÌùóçóµUÆOÕªUÙ°a½{÷fúôéܼySßÃ-1lmmiРuêÔÉå”Êår<==ñññ‘œÕ2ºuëØ¶m©©©ºç˜5kï¿ÿ>ëׯÇÅÅ…‰'þ'm• *ШQ#¼¼¼ri½S§NªV­Z ³ "ÒÚ¨Q#ªV­*9«¯@‰;¬Z­–G±bÅŠ\é5.\ÀÌÌŒ¾}ûbggG§NðððÈÕÊEB¢, ÕjÙ¼y³N¥6‡ãÇS½zuÚ·o}úôA&“qéÒ%}YBâ…HKKã·ß~ÃÙÙY÷œZ­æèÑ£´mÛ–† R¡Bú÷ïϽ{÷ Ñ÷%$ž­VËÇYµjU[åüùóXZZÒ§O­âîîÎÉ“'õ=l ‰çF«ÕÄr©Û‚°U¼½½u¶Jß¾}Ñh4\¹rEßÖøRâ«F£á·ß~ÃÃÃ#—Š'À7pttÔ˜àããÃåË—õ}ž$$^ˆ€€:ÄÈ‘#s=õêU¼½½uui...¸¹¹ ï!KH¼»ví"66–>úH÷œF£!00 èž«U«™™™„††ê{ÈÏZ­féÒ¥xyyåQô¼~ý:ÎÎÎ:[ÅÔÔ”ºuëJ¶ŠD™"..޹sç2`ÀjÕª•뵫W¯R«V­\­ä\\\$[EBo”h±…F£áðáÃ3uêTŽ9’ëõœ¶&&&€H‡upp **ªÐ}ž?ž‡âîî^fêGÔj5r¹¼L ‘¨Õjd2Y™(º×jµÄÇÇ£P(hÒ¤I.!âæÁƒ,Z´ˆ~ýúáéé™ëµÄÄDÌÌÌté#XZZ:Ç3339vìJ¥ggç23ÇU*U™kY³Z­&::™LF«V­JL”J«ÕrõêUöìÙ£ëÿù$III¹JP©T$''¸Ï””<ˆ¹¹9ÎÎÎeâ{Q«Õ¢V«ËÌ|)«c ÅÆÆ†víÚ•Øgj4:Dhh(S§NåÀ¹^Ï鉞“ÞghhøL[%))‰½{÷âìì\f‚´Z-¦ÐtÇÒFY³R©$,,L§„_R¨Õjþøã¬­­iß¾={÷îÍõzŽ­’cïYZZbaa‘+5þi"""8sæ ®®®eF,®¬Í@§H\lqÙX1114hÐà•zÝ—è]ëîÝ»üú믌;6!_ÉEƒ¸è.^¼˜§ciçìÙ³TªT‰òåËë{(ÏÍ¥K—prrÂÃÃCßCy&Z­–´´4nÞ¼I¹råJÌaU©T¬\¹'''ºuëVèÜ}’¶KKKãìÙ³Ô¨Qƒ”””2Ñh:##ƒ³gÏÒ¬Y³2S³‘••Źsçðóó+ŠÄjµšÔÔTnÞ¼‰O‰9))‰Ÿþ™:иqcΟ?ÿÌ÷äÕ+Wðõõ%55µL8¬ \¿~–-[ê{(ÏMRRW®\ÉÕ–¡´Ï•+WJÔa½}û6¿ýöãÆ{!«°9žžžÎùóçiݺu™±S"##‰ŠŠÊ•1QÚyôèaaa4iÒDßCy.”J%QQQ$$$”˜ÃªÑh8yò$çÎcæÌ™ù¶”+ì½ñðáCîÞ½‹••jµºDŽåUyðàqqqøøøè{(ÏMPP@™iy–––Fpp0fffeÇaÝ´iYYYœ8q‚S§N@BB , Gê ¹\ŽV«E©Tæêú42™ üýýË” eåÊ•±µµ-†qÕªUÃÜÜ`Ñ¢E4nÜCCÃ\ÆJvv6ÆÆÆ…~×S¯^=z÷î­¿“ù‚dddàçç—§¾±4“™™‰Ï+ %M:uعsg‰~æÆÉÎÎæøñãœ7)))¤¥¥•)Û*--¤¤¤<½åK3U«V-Q‹äädþøãÌÍÍÙ¶m2™Œàà`>'''²³³ z¡hlY¡,}™æP’iµe333Z´hAVV111ºÕÈÄÄD’““ñöö&22’¬¬,LMM‰‰‰!**ŠæÍ›ë{èEŠ‘‘Q™2Šáñ€Dá8::Ò´iSÒÓÓIOO'11€ØØXÒÓÓ©Y³&ÁÁÁº9}ïÞ= prrÒ÷Ћ33³27_LMMËÜu©ªT©Bfff¾¶JVV5jÔàÎ;$$$àèèHVV·oß~ílkkk¬­­õ=ŒÂÒÒ²Lôõë×'""‚ØØX@d\\jµooo"""ÈÎÎÆÄÄ„˜˜bccsõÀ}(‹s¼,9ªEI‰:¬½{÷¦gÏžºÇ«W¯fëÖ­Lž<###LMMY¾|9gÏž¥}ûö„††réÒ%¦M›¦ïó$!ñ\T©R…1cÆèggg³uëV €¿¿?ÎÎÎÌ;—û÷ïãééÉùó牎Ž.S)zÿmüýýs57¿xñ"ÇgìØ±XXXpûöm>L×®]111aÿþý8;;çõ(­¼óÎ;¹¢ý+V¬`÷îÝ:[ÅÄÄ„+VpîÜ9Ú¶mËýû÷¹rå ?üðƒ¾‡.!ñL¬¬¬8p Z­V÷܈#°³³cÔ¨QÓ²eK~úé'BBB¨X±"çÎ#66V²U$ôF‰:¬O×Þ “Ét"K+V¤GüòË/9r„š5kV¢…诂\.×Íg@W‹gdd„‘‘7Æ××— &àááAPP}ûö}í¢O¯/¹Ò¼s¾×MLL022¢W¯^\¾|™¯¿þKKKî߿Ϙ1cÊÜ*¶Ä—ç±UÞ|óM~þùg:Äýû÷iÑ¢E™ªƒ“øï"“Éò”½Èår tsÜßߟÇ3~üx*T¨À­[·èÛ·ï6º'¡ôZù?`Àúõë—ë¹ÁƒÓªU+®_¿Î|@:uÊŒ@„ÄÓqéÒ%4¼……Ó¦Mãüùó—.]ÒÕŠ»¹¹ñË/¿pêÔ)233iÒ¤‰´ #Q¦ùè£xÿý÷s=÷ÙgŸÑ¦MnܸÁ€¨]»¶d«H”YæÍ›—KìÎÒÒ’ï¿ÿ^×…cĈe²”MâõA¯ß®9Q§\24ÄÛÛooo½ž ‰¢@&“媧‘ÉdѬY3}MB¢H000È3Ç---éÔ©“¾‡&!Q$ç‰HR«V-)Õ]âµàiqÊœ(ì릯!Qv)M|$$$$$$$$$$$$$þsH«„„„D’ÓââIA‹§ÉÎÎ~î½ùqëÖ-"##õ}¨ÅŽä°JHHH!iiiÌœ9“ päÈ‘|{-\¸|߯Ñh8r䈮¿i~ûŸ:uj‰÷¦”Ð’B€ÄK“••…R©|fÏ3FCRR&&&XXXä»Mtt4ëׯ'>>žŒŒ  =ÂÆÆ†‰'âåå¥ïÕxÍÐjµ\¿~{÷îÑ´iSt¢)†ÌÌL233ÑÀÈȈäädnÞ¼ÉÕ«W©W¯Õ«WÇÆÆ&—XÅñãljŒŒ¤eË–ìØ±ƒíÛ·³`ÁÝ6©©©ìß¿ŸZµjQ¹rå<㊌Œdذa|úé§Œ1"Ïë7oÞ$))‰‹/òñÇëû4JHHHHHHH+’Ã*‘/ñññ9r„ÐÐPš6mŠÎ1ÍÊÊâÒ¥Klܸ;;;&Mš”ï>âââ¸sç§NâôéÓtïÞ½@{ÕªUdffÒ²eK¬¬¬pppÀØØ˜ß~ûû÷ïK«Äs‘ÍíÛ·ÉÎΦ~ýúÏÜ~çÎ\¸p7R»vmìí퉊Š"++‹ÄÄDd2ØÛÛãèèHHHÔ­[—¿þú‹¤¤$ºwïNïÞ½‘Éd$''³nÝ:FŽI½zõèÓ§ýû÷')) ;;;@8¤>$00®]»æOJJ ³fÍbäÈ‘œ8q‚ôôtÌÍÍsm³ÿ~úôéÞ={xô葾O¹„„„„„„„D±"9¬¯†ÈÈHó·*•ŠÈÈHÒÓÓ166ÆÒÒ''§\½ADœ>>¹^wuu%,, ­V‹V«%88˜ °k×.RRRtô¶mÛèÝ»7U«V FB:uP(lÞ¼™Q£Fa``@58yò¤.š+!!!!!!!ñ:"9¬eœäädöîÝËܹs©X±"uëÖeÏž=\¾|™œ™>}z®è‘¹¹9ä7Þ 88˜„„ ?üðuêÔy¡Ï÷ôôÌUG••U.ÇDjBBBr9¬×®]ÃÜÜ<_ñ;;;jÔ¨ÁÙ³géСCã8tè®®®œ8qBrX_3¶nÝŠ··7µjÕÂÀÀooo’’’HOO'33“*Uª`bb’ï{e2†††XZZbhhˆR©Ô½¦ÕjILL̵8ó²´jÕ ­V‹‡‡Gžˆ§——gÏžÕ¥ '$$P®\9œIJJÄÂÍÉ“'™>}ºn¡ÇÌÌ ???Nž<‰³³37n$--J•*àææFHHˆä°JHHHHHH¼ÖHkçâÅ‹xyyáéé @íÚµŸËaËq Kƒ|¼¼¼Ø·o}ûöE.—sþüy¼½½ó8¬ "FºÇ™™™,^¼˜¡C‡æJ~š.]ºpôèÑÖ¸¸8Μ9ÃŒ3˜1c (PX¢ôpïÞ=V¬XÁ矎»»{¾ÛDFF²cÇ-Z¤K³533+t¾ä‡¡¡!666Ü»wOçðˆ°æ—Šþ¢8?œœ E£Ñè~œ©P¡Ô¯_Ÿ`jjJ¹rår­K—.|÷Ýwœ¼ÿþûùn—’’Â7øì³Ïôv<¦¦¦dee¡P(°´´$88¸@ç¢|ùòhµZ²²²022âÚµkÔ®];Z1W¯Bv6üëÈZXX`kkKdd$•*Uâ—_~ÁÚÚšb$“º~=ÍúôÁÐÐþýû³`ÁZ´hñʵ‰/‡B¡ÀÔÔ4ïÿõ_bbb5jÝ»wçÝwßeöìÙüïÿc„ ܼy“ 6èúñZ[[3zôhx׫`ooŸ+Â…­­í3ûÅç&$$––¦K™·³³£zõê¬[·5Øþþþùž3WW×÷ݰaC–-[V¬ã—(Œâããñõõ}¡ôúŒŒ LMMóÍÆ‘Ð7J¥’ØØXìíí155E¡PÎýû÷9yò$AAA˜ššòûï¿ëî!*•еk×âêêÊÁƒ‘ÉdT®\™6mÚpâÄ ²²²7næææ(•JœIHHÈ#”)!!‘—WvX ÉÉÉÜ¿[[[ªT©BVVVVV¹Dw$³fÍÂÔÔ”1cÆä{~²³³9räkÖ¬¡oß¾ìØ±ƒŠ+Ò¬Y3@Ð$%%‘‘‘ÁŽ;hÖ¬Y‘DŸ^333LLLÈÌÌäÑ£G(•JÜÜÜòÝÖ‚ÔÔTðÍ¥K—èÔ©SÞ  X·êÕ## (_¾uê'Ož$::333]¦›îîî´iÓ†=z°víZ4n?>ýôS\\\xôèçÏŸgÉ’%˜˜˜0{öl]ëACCCÊ•+Gpp°ä°JH<¯ä°FEE1oÞ<Ž=JJJ ]ºt¡OŸ>¬ZµŠ¾}ûÒªU«"4y]ˆ‹‹ãÂ… qìØ1Ú´iˆ•æÓ§OÌ7HHH`ܸqÔªU‹ºuë2iÒ$LMM¹qãÇ×}ÑÉd2>úè#½. ˜™™ajjJDD†ZµjØVÆÚÚN·¥¥%!!!Ô¨Q#ï†Á²epíÔ¯\.§^½z,X°€ 0wî\®_¿Îµ!CP÷ìÉÅJ•þ¯“¹¹9;vdÁ‚Œ1â™)ÕEGLL S§N¥~ýú8p€ôôt ÀßÿÍ™3g2d+VÄÙÙ9לurrâÇäÒ¥Køûû[ý±““ÉÉɺǺިÅMõêÕ¹víiiixyyÂ`©]»6Щ¿ÖÖÖTªT)ú±„Dq£R©X´h 4 S§NLž<¥RIFF›6mB©TâççG­Zµò¼7::šÝ»wóÉ'ŸP¯^=@ûýõL›6M߇'ñ’‘‘Á¥K—t‹¡IIIsïÞ=BBB011!--zõêñÕW_áííØÛÛçº7ÅÅÅ‘‘‘‘KÈO£Ñ V«±±±ÁÄÄ„J•*Q©R%zöì‰F£ÉU~"“ɨZµ*!!!ú>-e‚—ö&322øõ×_ fêÔ©\¼x‘„„jÔ¨AõêÕ™={6/e„½ŽhµZöìÙÛo¾I=øâ‹/°¶¶F«ÕòçŸbllLíÚµyï½÷¨\¹2ÔªU‹2sæLêÕ«ÇøñãqssÃÄĤøS©®_##xBÕ÷i ©S§÷îÝC¡P¼2ž’‚©Z§§'÷îÝãÁƒT¬X1WXΟ‡cÇ`øpxâµuëòÕ‡Òáí·±´´¤Iƒ2aûvÞ9R'Â#“ÉèÙ³'...Ì;333>ýôÓâÿÿÇIIIaÞ¼yøøøðùçŸóàÁ¦NÊéÓ§±··gþüù…ŠÙÙÙѾ}ûb£ƒƒC®”àäää³^ŠœÅ‘|ÒzkÔ¨Á®]»P(´mÛV÷¼»»;7n¤GªÕ™ /¢ljjJ=$‘1‰\(•Ê<rQ’ÍüAVVï¿ÿ>vvvLš4‰éÓ§ckkËäɓپ};ÑÑÑù:¬÷îÝÃÆÆ†€€Ãš••ÅÝ»wu‹ŸR†–DQ£öìYÖ¯_‰‰ ööö(•J²²²t­Èúô郹¹9æææy2ó³kÌÌÌÈÎÎΕݒ£;òô÷qA%-ŽŽŽ>|Xß§HBâ™dgg#—ËŸ„LMMeÅŠôêÕ«È3e^ÚaMHHàܹsL˜0fÍšéÚ£ØÛÛ3xð`._¾ÌÉ“'%‡õ_’’’8tè?üðnnnôëשS§bjjÊÇL‡òr¹œÎ;Ó¨Q£’OýÝ´ š6-Ôa(W®'Nœ ))©`çðÀd7nP¹F ®_¿NFFmÚ´É[³wù2”+¾¾¹žvÓjéyçü½5ÈΦBÏžTŠ‹£“¯/cǎѹsç"Qâ}U\]]Q*•¤¥¥aiiITTÕªU+ºزìí¡]»|˜Ÿ~úI—¥P³fMþ÷¿ÿé²nΟ?ÏíÛ·s-ÐäpëÖ-zôèÁÅ‹u*©9†¿Z­æÑ£GE»˜$QªP«ÕÄÆÆâààP$úùʹsç¸uëwïÞÅÉɉ¡C‡R¿~ý"ùL ‰ŒŒÔ•–Ü¿WW׳̞ÆËËK]’(õ¤¤¤ðÓO?ѺukZµjUàv*•ŠÕ«W³lÙ2êÕ«WzV•JEfff¾222¢\¹r:UW ¸q㺈b¯^½¨T©•+WÆÞÞ¾PƒÓÐÐðåœÕmÛÀÜ:t€gEc7o†Zµ 'E7#‚‚ÀÆ!¿zД¸z•šÕ«óóÏ?ãââR°‘!—Cj*µªUcÇŽ¨T*¾þúë¼ÛÅÅÁ›oŠ¿££ÅãZµÀì­aãFè×,-±;–™ &gÎÀÎ0qb®]ÙÚÚÒ¤I“bWý/£ÕjÙ¸q#Ìš5+—Е««+ýúõ+¾×hÄB…ƒƒ˜çÏØÖ0.s##°´´$)))—ó˜/jµøyÄÉ æÏ™OE•¬­­Q©TXYYéj˜@(gwïÞ åËÊ õT•xI’““Y»v-GŽá7Þ ==1cÆðÅ_P§Nï1iiiܺu‹M›6qóæM*UªD§N¨Y³¦.eÒÑÑ‘J•*aggÇÖ­[9uêÓ§OÏÕ† È•b_£F vìØ‘çó”J%L™2…1cƇ££#‰‰‰¨Õj4hÀ7$‡õ5$ç¿iÓ&<ÈÊ•+ñññyéýiµZ¢££¹~ý:ÁÁÁ¤§§“––FXXééé4nܘfÍš1lØ0¬¬¬ŠÜðòò"66V÷8,,¬Àmùáää„F£ááÇE²%$žÁåË—yøð!;vÔ-²dddpÿþ}œqrr"88˜ï¿ÿ[[[/^L:ut‹ Z­–ÌÌL]†ã¥K—8}ú4ï¼óN±,ļ´Ãjbb‚­­-GŽá£>ÊõZRR—.]¢E‹%uÞK=§N¢yóæº•=##£âoGsü8<ïgÜ¿±±VµÞ{O¤(ž<™¿ÃªTÂÒ¥¸öíK\l,¦¦¦¯,öê½zá©PpöìYZ´h‘ÿÍム§7ìýû0u*Œ ;Â;ïÀêÕ™¶°@flŒ)‡:8øñ>®^ÎnÇŽÅ{~ÿ#h4Μ9ƒ³³sžŒ‰»wïòÇ0kÖ,lllJv`™™ðý÷0pà³ç¹F+WR!5•øøx<<< {väwçNP©àí·Ÿ=ž–-!) @²°°Ès}¸¸¸0mÚ4¬ll`Ð ¨Y3ï‚  D©%J'Z­–ƒrñâEæÌ™C… Ðh4lß¾qãÆ1uêT4hë=YYY;vŒ?ÿü“¬¬,ú÷ïÏçŸÎÍ›79tèÛ¶mÃÒÒ777a“˜˜ˆ««+3fÌÈã¬>““ñññyž¿wïFFFxzzâââBll,ŽŽŽÜºu‹ÚµkãááÁ­[·è(}¿V<|ø_~ù…ÐÐPúöí‹››çÏŸi‡U©TràÀ–/_N­Zµ¨\¹2&&&T¨P^½zQ¥J•b_¬vrr"22R÷8::ú™×Å“Èår*T¨@xxx±Eš%$ò#>>ž™3g¢R©HJJâý÷ß'99™… êÚOV¯^   :vìÈ»ï¾Ëœ9s8tè}úôààÁƒüñÇtïÞV­Z±|ùr>úè#ÒÓÓ F«ÕiéâK;¬NNN|òÉ'ÌŸ?ŸË—/“••ERR¿ýö›6m¢F´lÙRßÿ“áÌ™3$&&Ò¹sç<«Øjµš[·nqéÒ%† R²þݺå‰ôHpàÀãÇ––âý‘‘0}ºp`ŸNßup€éÓ1œ4‰Z&&;9~ƒP«±HO§Ž·75Ê¿íÉ“=\›4|Î ÀË ¦Løx˜=FŒ;;ñž'jµvìÖ""!!)S¦`nnÎòåËqtt„³:nÜ8¦M›FíÚµK~`ffâ|óæ³Vµ*W¦íÁƒ¤¥¥¡P(DÍua™ aaBükþügåÔ)1{ô(p___ðX¦¦¦Ó’k׆ôtáðÚÙ 'ûÖ-غLM¡yó’?Çe‚ÌÌL6nÜÈøñãu}°år9½zõ¢FŒ3†o¾ù†Ö­[“‘‘ÁæÍ›Ùµk•*UbÔ¨QÔªU ¹\ŽL&ÃÃÃN:éúKÊår´Z-†ÈÈHœœœre „««+qqq¤¤¤äš÷.\ iÓ¦cooOdd$5kÖ$ €† âááÁœ9sP(Rmök@HH»víâÈ‘#¼ýöÛ|ÿý÷ÈårîܹìY³øðß;…„¡}òäIÖ¬YC5øßÿþ‡«««^Ê"¸zõªîqdd$ 6|¡}xxxNåÊ•K|üeƒ¨¨(]/ö„"Õj5—.]"00Þ½{ckk‹F£!,,ŒŸþ™þýûÓ A4 ›7oÆÏÏÁƒ3vìX"""¸víuëÖeÍš5¨Õjþùç:wîL³fÍÉd >œÏ?ÿooo®\¹ÂÎ;ùúë¯9rä¿ÿþ;o¼ñ:tÐEZÕjµ®ÔñÌ™3ÈårZ·nýÒçá¥V™LFË–-111aëÖ­\¼x­VKJJ -[¶ä£>*–Ú™ÒFzz:?þø#ÉÉÉ4kÖLeÒjµDDDðçŸrýúu>üðÃ’¯ãkÛVô3U«¡°Bi¥*T€k‰ÐjÅûŒŒÄóO§îjµÂ!tu…úõaìXj¯YƒA¹rù¯&'ß c~Ñ">îуjÿ^¹öyႈ–æ¤iÊdÂ1Íqle2ñ =NÓ´¶†¯¾Ç™-¢ÄññâGâ•ȉÜÔ«W333þüóO† Fff&³fÍ¢K—.y"7%†L&êEÓÓŸ½íÑ£”„Í¿m  –¦¦È¾ÿ¾üœEÚúÓû8žUçzÿ>üö,Z$Þ£RÁÅ‹b±å‰¨s×®]ó7Ì´ZáðÖ©wï™3bL™™°d‰ø“û=J¥È4ø7GâõA«Õ’‘‘¡¡!FFFy9Õj5ÙÙÙ`llŒV«åÈ‘#T¯^=êºL&£V­ZŒ1‚_ýkkkÖ­[GVVcÇŽÍ·¶L&Ëó™2™ ¹\N¥J•žû8,--©^½:—/_Ö)9)¡ï½÷ Ô³oß¾M»ví¸}û6}úôÁ¹\NFF†ä°–!´Z-*• •J¥k³k×.víÚEãÆY¸p!îîî:ÇÒËË ­VË;wò,xj4¢¢¢033à§NbÍš5ØØØ0zôhêÔ©£KGÔnnnºt^­VKddä —o9;;sâÄ Éa•ÈFÃòåË9tè•*Uâƒ>(p»þù‡%K–P¾|yîܹ÷ß~˃˜5kžžž,\¸E‹¡Õj9zô(ãÆÃÁÁqãÆñÛo¿Ñ·o_:w¡!†††tîÜ9×g8::Ò£G¾ùæ¼¼¼˜6m5jÔ qãÆ|øá‡ØÙÙ!“ɰ±±!---—ÃzëÖ­Wn5ùÒkTTcÇŽeذa,Y²¤¤ÿ‡¥¥RÉ’%KèÔ©&&&,\¸ñãÇc``À¥K—˜m°GDÀš5Â@—Ë¡zu>5Šìììü#È …P~ÿ}(WŽ&&yS32D4ëiç8?øÞ=èÒž4f´ZØ·Oüüü3|ñ…8&‰WâÑ£GlÞ¼™Ù³gceeÅ—_~I:utFȇ~¨¿Á…†Š¹úoÞB¹x|} 4Ãäd¼RSišœ,Ì7„ØW×®¹ßãá!~îÞ 7¦¦_»wO\ÆÆðûïЧOnußíÛÅÊ¿ý“š6múøõ“'ïÿÁ1g—-nŽÃš”$®O>É«|á¬]+t$^4 .\`äÈ‘øùù±`ÁC©P(8qâgΜ!44KKK† ‚ƒƒË–-cñâÅFªÚµk‡‘‘ãÆãí·ßfРA%r<õë×çîÝ»:‡511‘ôôt]¸råÊìܹ“4 UªT!33]mkvv6éϳ(%¡7”J%W®\áï¿ÿF¡P––†¡¡! 4`åÊ•y2K@”E5kÖŒ3gÎP«V-í Ñh8rä?ÿü3–––8;;ceeEdd$ŽŽŽL:µhÅò^OOORSSÉÌÌ$33…B§§ç í£N:lݺ5W{ ‰Ξ=Ëõë×Yºt)'N¤eË–T¬X•JÅÁ3Ƭ¬¬¸ÿ>çÎãǤråÊüùçŸ|øá‡XZZ2lØ0üýýÙ²e #GŽÄÍÍ ___jþk‡WªT‰éÓ§?×xÞ|óM èÞ½»Î¯‘Ëå¹j·mllP(:ÁS…BÁ;wèú´õ‚¼´ÃjhhˆJ¥ââÅ‹øúú>wþ}ZZ'Ož$ {{{Z´hA•*UtïOMMåôéÓâááA»ví°··/ÙTÚç$$$„€€fΜ‰¥¥%ƒ âÖ­[˜™™1oÞ>>4jÔ´Z- ìÛ·èèhêÖ­KãÆs‰•´Z-û÷ï§fÍšxyy¡Ñh0`S¦L¡yóæôïß_¿}–F331 3b’’ Jœ4ÂïÜA•–Fݨ(1_U*øá1§ľîÞ…J•ÀÄ–.…Ï>ƒ*UľbcaØ00@Ôf׬ ÿöTÄ5âë+œä'Ö¶lÙBÏž=IKKcþüù¤¤¤Ð¡C>üðC®^½Ê÷ß½½=uêÔÁ%§ö¿Z´hÁêÕ«u-ÓJ‚êÕ«³lÙ2]›š„„LLLt†ŽƒƒÑÑÑDFFê ªW¯ÎõëשQ£‡âàÁƒ :´Dÿ©©©œúˆ * “ɰ¶¶ÆÎήÐT]???–/_®nQ©T8p€¿þú‹ &P±bEÂÃà ãƒ>ÀÃãT‰(cbbB||<ÙÙÙ/Õ×ÛÔÔ•J•«=NIÅ©S§¸}û6nnntêÔ ''' ÐjµÄÇdzoß>bbbðññ¡qãÆX¾@Û5‰WC­V³yófúöíKµjÕèÙ³'K—.åóÏ?gýúõܼy“V­ZqãÆ ´Z-³gÏÖÕP¿ÿþûøùùammMÅŠ‘ËåôîÝ››7orìØ1þþûï—òM¬­­y÷Ýw Ý&'Ó4%%333BCC133{ålˆ—¶6mmmyûí·Y¾|9ÉÉɹVÈrhÙ²e®•5…BÁܹs9uê­ZµâÎ;¬_¿ž±cÇÒ®];d23gÎäêÕ«4kÖŒ;wrìØ1¦M›V¢7Ùç!33“E‹ñÆoàâ⢛ «W¯&--Î;ë·†7(H¤KÖª»w §1?ƒ1+K8‰õê‰hÓ£GðÏ?B@&'*¬PˆH­¯¯0¦ÛµË›Šhj*¢¡[·ÂÓ­m,,DôÖÈH8“'燱1tï.Ú‚<‹üŽÃÌ æÎooñX­i”zXµ"B¤Á7i"ž71yóGTsjº32Äkr¹¨+ß°A\‡ E‰Ÿv•JÅ_ýÅš5khÕªÉÉÉŒ7Ž>ø€?ü   Æ»»;öööLœ8‘!C†Ð»w﫾IHHàŸþ¡Q£F¸¹¹j¼‡……1{öl>ÿüsš7oN£FøøãÑjµ;v 777&Nœ¨[Üõòò¢Q£F¬_¿žž={>s,2™ì…aŠ‚ªU«’@bb"\¹r…J•*é 777âãã Ð)vËd2j׮͙3g¸}û6«V­¢Í“ B%@ZZsæÌáìÙ³´lÙ’Û·oël•¶mÛ"“ɘ>}:7nÜ iÓ¦lÛ¶£G2mÚ´ÿD)”J¥"00Õ«W“À[o½E§N^øžàîîNjj* …3336nÜȆ ˜?¾.Réì쬿²“çÀÑÑ‘˜˜ _ªìËÒÒR§"_’ÄÇÇ3|øpT*7æìÙ³lܸ‘ùóçS­Z5âãã5jZ­–5jðÓO?áïïÏøñãKtœÿeΜ9CBBíÛ·G.—Ó£G<ÈàÁƒiÙ²%¿üòKN ‘‘QA3¾ùæ ðÌÎWÁÄÄ„J•*qíÚ5:tèÀ£Gpz:õ¼´Ãš––Æ… té§OŸÎ³MíÚµs9¬ÁÁÁœ8q‚¹sçR§N²³³™1c;wî¤iӦܹs‡óçÏ3nÜ8Z¶lɃøøã9~üøsÝK ­VËÙ³g144¤G:#¤M›6ìܹoooÞ~UÑâ"3SD<=…xËäÉkX ˆŠ†°¡¡pþFŒŸL& m¹\D\sprÂG+VÀðáU|ŸD.*¾?þ(j ŸLvrÊuµ´Ûä|fÎs¯’. “Á“gjªˆ¸Ö¯ÿ|Np²uëVÚ´iÃèÑ£133£Q£FÌ™3‡   nܸAtt4‹-ÂÃãG2uêTÝ ZiA£Ñ°qãF4h KßËÁßß_ßÃx{‹ {{‘Qð¯z4©©âçßÞx€.ú*·²Â8#ƒìcǰ˩•66†qãÄï³gEôsäÈÇb_Õ«çŽèW«ö8’_9é¾ù‘“ªÞ½»˜·O;1––âXr“âãEVÂgŸ‰Ç §uØ0‘!qÿ~‰žö´´4¶oßÎСCéÕ«ëׯgçÎtèÐuëÖáèèÈÌ™3166fÕªUlذ¦M›ëM²4rîÜ96nÜÈÆñõõ¥S§NxzzbmmËyÍÊÊâ·ß~£]»v4mÚ™L†#FŒ`Þ¼yôîÝ›¾}ûæÉdrsscäÈ‘ú>Ì144ÄÕÕ•¤¤$صkãÇ×-n[ZZR³fMöìÙÃØ±cuïóññÑ-^öÙg¤¥¥•è¸ïÝ»ÇéÓ§™3gŽÎVùñÇÙµkM›6%((ˆ‹/2qâDš7oNDDŸ|ò 'Ož¤{÷îú>íÅJjj*K—.åÎ;ôèу&Mš¼t@ÁÁÁOOOŽ=JBBçÏŸgêÔ©/œV«OlllHJJÂÈÈ襔~ÍÌÌÉddff–è¸Ož<‰J¥bÖ¬Yxyy‘””Ä!C8|ø0ÕªUãÀÄÆÆ²dÉÜÜÜ8|ø0?þø#}úôÉÓ-@¢hP«ÕsîÜ9îܹÅ ˜7ož.ªmnnθq㈋‹Óe4½(VVV%’ÑW³fM"""Ðjµ¿TöÁÓ¼´ÃjccÃ×_Mv!u‚OŸÓªU+êÕ«'>ÜÐGGGÂÃÃQ©TܸqƒòåËãëë‹åË—§aÆœ?¾T9¬YYYìÚµ‹·Þz+×êF¹rå˜>}ús«(¾ŠHP³fyU{s05Ѧœ1<¹ª¾~½HÝ]·NÔåÉ幄aèÞ=¯Ãil ß~›=铸ºÂ¨Q"ô$·n ‡õ_uY”JQÿúî»b  çùezÍ„…¨T>zô8•³„ðôô¤E‹ºÕf'''är9IIIРAÜÜÜ000 N:º¶¥Éa gÇŽüöÛo%ŸÒ®R‰9ò¬ô‘…[07jÁ9À"wåJñøÎ±»;F¦¦DÖ­‹|óf49R™L,ì4l˜7÷³Ïr®¥eÞšÒçE«…½{EºqAíÔj˜3G\—Ç‹±„…‰ëÒÖÅ‚“™™^2är9~~~´nÝZ—æ[®\9222P(:Qœ›lëÖ­Ù¾};!!!ÿ)‡U¥RqúôiH:u8tèË–-C¡PàããÃСC1ý·.:,,Œàà`FŒ‘ëzkÑ¢5kÖ,ñÈhQ‘£0ʆ èÛ·/Þ9Y0ÿâííͶmÛt=ÊA|gš˜˜P§NZµjÅž={JtÜ&&&´nÝ:—­âààÀÇQ«Õ\¿~WWWêÖ­‹...4hЀóçÏ¿v«B¡ 99WWWbbbøþûï±³³cúôé:Åø—ÅÀÀ€æÍ›3yòdêիǬY³J]6ݳprr"%%¹\þRçÃÌÌ ggg’““KtÜææætëÖ*ÿÚGVVVX[[“ Sí._¾<øøøàêêÊ•+W$‡µÈÎÎf÷îݸ¸¸Ð¤I222X±bgÏž¥Q£FtêÔ‰Ï?ÿ<×÷¢L&£jÕªeâü»»»³sçN4 AAAE2æ—vX tjDD="11///Ê•+—oóäjÕª1fÌ”J%áááܹs‡3gÎУG,,,ÆÜÜ\—ÿlddDÕªUÙµkW¡cÉÌÌ$44GGÇ©“ºqã±±±ù¶òx:Uä¬Y#]6n„ÂT?¹‚"jò:vQ̤$HI¯]¼("²95ŸööùG$Ÿ7J™ßÊè¢E"b•óenh(¶ûí7˜8Q8A‡Evš4ÄT¯Nò•+˜TGXL|ñÅ:ÑÐÐP¶oßNùòå©W¯?ýô“ND:‘³³3AAA…î3--û÷ïãææV"5<Û·o§iÓ¦¯l¼×® UéiÓ v  áhš› Ç®gÏÇkíÚ""zó¦PŒÞ¼Y´œqwÇÄÄ„[öö˜4nŒG~Ð'…•òC­ F*ä^ÔÉýûEàÏ>{<6•JÔ€}Í!%E8Î _œœGy[´€¦MQ*•ÄnØ€Ó¾}hŸt*f¬¬¬7nÄÄļp¯N}¢P(øæ›oxôè–––Èd2:wîLïÞ½‹L×ßߟ±cÇÒªU«R©åð,lmm‰ŽŽÆØØø…T´sP*•]¢ãnÓ¦ Z­–¬¬,îܹCPPÑÑÑ|öïí;wèÒ¥‹ÎVqrrÂÁÁÛ·o¸OµZMDD5kÖÌWhë¿À¡C‡¸uëµjÕÂÒÒ’ºuëê&sgáÂ…ºÈú’%KÐh4xyy1kÖ,\\\Ê|-¼··7?ÿü3™™™$$$ V«Q«Õ¯´ÏWRL çÿû§OŸÖ5766¦zõê >œfÍšå2<är9ÆÆÆ$&&²råJöïßµµ5>>> Ñhtòù V ž©˜ÓøöUOÆó R©X³f =zô(’÷ Ó¾½hWó¤y󦈢æ;÷î‰úÍ#61Q(Švì(„’žL!;rŠZNýÏ?…óY®œHmŒŠÊå•Éà7D¤éêU+bÕJ­VKZ³fD©Õ8ýÛO°¤ÈY49}ú4¿þú+aaa 2 Ôju®¶r¹\ס0²³³IHHȵÚV\¤¦¦òÏ?ÿ0[_ ´µk gpÃøè£üëRÎã›oŠùd` êAÏŸ‡·ÞuÔ*•XŒ Ï!V•14$A­Æýy£û÷Å<íÙS8ÊóçÃØ±"JZîî°k—Hιai4"]¹°Z'¹\,ää¼ÇÈHONZý¿N¼&+‹4ggƒ‚0yÆü)Jd2ÆÆÆdff²cÇÖ®]Kbb"}ûöÕ‰.=ù½ohh¨kÅR …‚¤¤$ÜÜÜJìXŠ’#GŽ`oo¯¯/>D&“é®Y¹\Ž……Œ9’Ñ£G³lÙ2ÚµkGTTãÆ{-õ'‘ÉdT©R…jÕªåŠ(?IÍš5™0a‚n¡:‡§.>>¾ÄÓ%sl•„„–/_ÎÁƒ±µµÕETsl•œïñç±U´Z-iii¤¥¥• ‡5==ŸþGGGæÍ›Wlš–––¼ùæ›ú>Ü—ÆÝÝ£Gbff¦»ö_•J………‰‰‰%:îñ°0}útnÞ¼‰ŸŸŸ.èò2¶ŠV«%99™ÌÌÌÿ¤ÃšÀ¼yóxã7 äÊ•+Ô©S‡¡C‡ê².ƒƒƒ™6m¾¾¾|þùçqóæMÒÓÓñóóÓ¯eboo=âáǺl›Wá¥ïŽ …‚E‹¸qãàêÕ«lݺ___&MšÄZmmm™kŽÛÛÛÓ Aƒbo”ÍâÅ‹yï½÷ô“v²s§èIúõ×ÂÑKKçäÉ¢ÎT¥N_``îÔóððÇ5Ðr¹X¬©SG̯ŽuóËÔÔ”„„âââž_íP¡€C‡ÄßYYbÿÏó]ãä$>÷É´]##QÿúD22™ˆ?y|îîŸ> ÙÙ˜˜˜àÕ¼9Þ}µ”3MLL}úèM¤ÓÕÕ•Õ«W³oß>²²²ž¹P]X®¡¡!µk×~á^´¯jµš¿ÿþ›wß}—/¾ø‚¯¾úŠÅ‹Ř1c8xð cÇŽeÔ¨Q|øá‡ >Ý÷_£F^g5gggöîÝK½zõhÚ´é+ßK;¬‰‰‰ðÕW_Ñ­[7ÌÌÌ055¥J•*|ñÅ899qêÔ©\ï¹}û6'Nœ@&“add„ ={öäöíÛddd`ooR©Ô­¦ªT*¢££q}Rݲ„¡(~ç'D’,QÒ7D;Œr§ ÛÚ”)"=2‡›7aõj¡tš#>ST´k'Œê¬,õ6,ÿíDªfçÎÏAc‡I ÊÅ+ :Dll,˜˜˜Ð²eKœ¹}û6ŽŽŽ( ]6@jj*©©©¥¦¶ïÁƒܸqƒŽ;]JŠB¿þ*œÏ}û„ˆP~(•B9×ÁAü|ö™Hß°Adôë'œEµZÌñ'ØòåaêÔÇsI&בR)"£ÿfXXX`ooOllìó;¬vvSè Ä‚ÑóDgíí…:ö“έ\.Ò_ô‹;5.]ý•,Ð=­54$¥bEÔ%x£‹‰‰áСCddd`hhˆ……½zõ"..ŽèèhHÉ9_ÿnodd¤ŸŒ”"F«Õˆ­­-¿þú+QQQ¨ÕjÖ­[ǻヒ££#ÇŽ#== .иqã÷ekkË„ øä“OhÔ¨‘¾­ØxžÅŠÒFPP'OžÔÙ*¶¶¶ôìÙ“   233±··';;;—­Sjl•WA«ÕrôèQ}WÖþw%¹¹9(•Ê—vìŸÌ,, T*çÎãæÍ›ºŒ™òåËÓ©S'®^½ ¯­’––öZÌñâ ::šS§Né:žÈd2ÌÍÍ™8q"uêÔaÍš5øûûó믿ҦM›×.›&?lmm9þ÷ûïE˦ŒEOÔ' † Ä{Ÿh —Ë)_¾<ùF¾òÅÑññ|¶·‡?~vý*ˆyïêš{þ_¿.÷%5U\ÿ·n Á%=ö4gÒ¤IÜB8** 333¬­­ñ÷÷çäÉ“º×®\¹‚©©i™ˆ,= ­VËñãÇùä“Ohܸ1 ,௿þ"))‰>ø€O?ý”uëÖ€™™Ù3kÚÜÝÝùàƒò¤ÃJè—œ·ùÙ*4iÒ„Gþo䌌ŒRe«¼ 7oÞdáÂ…Lš4©Ì¦ç—$ºÖMeå:Öh4ìÝ»—eË–éú¿j4¢¢¢tÙ Í›7çòå˺4÷ððp"""Ju‹!}rðàAjÕª•§lËÚÚšÁƒóÇн{wÊ•+WæëSŸ—u颚3/í°šššâààÀîÝ»Q(hµZ´Z-ÙÙÙ„‡‡sõêUªW¯žë=µkׯÄÄ„™3gòÏ?ÿ°sçN~ÿýwºuë† >>>ØÙÙ±råJùã?HOO×o?ÓQ«ÕlذN:Ük+9YD9ùåù¢¬·o 3'eÐÀ@¤ *"ªôdÝΑ#"¸°º€ŽEä´bÅÇGáä$ÚsWKŒ-„Q½m>\<ŸQ ±±±¡~ýú¬X±‚Ý»wsâÄ .\Hvv6íÚµ£yóæ$%%±~ýz®^½ÊŠ+prrÊÓ/K¤¦¦ròäI:tèPðêŸJ%ê+ŸW âÆ q]të&æöçŸC›6"eüi…[wwxV·Ë—…H—ͳ¶ºuÅÏS-·rT¼Ÿ;âgjúX”,;;—ü'U(s§¥ gûÿ˾ÿ¼äÔƒ§¦ŠkK¸¹¹áååÅO?ýÄÁƒ9xð ³fÍÂÏÏooo:vìH@@;wîäÔ©Süõ×_4hÐ ‘«2†R©$$$„5jðÁ””ÄŠ+øì³Ï022ÂÛÛ›ZµjéÚ¡H”MêÔ©ƒ‘‘³fÍÒÙ*Ë—/§{÷îX[[ãë답µµÎVY³f YYY´Ðóµùªdffò믿ҿÿ×âz- ¬¬¬P(¤¦¦–‡ÕØØ˜¦M›ríÚ5~ýõWNž<Ɇ Ø¿?ï¼ó ÊsÙ*åÊ•£î“ Ê€°Ž9B=¤Œ„'ðôôÄØØ¸È«_úÌ:88ðÁ0{öl.\¸@“&MÉdDFFròäIjÔ¨AÓ§”+kÔ¨ÁŒ3X¹r%K—.ÅÌÌŒ®]»Ò§O]ýÎÔ©SY±bÓ¦MÃÝÝ©S§æÅ-iî߿ϹsçX½zuÁÆ|F†èÙxîœ0, s.ÓÒ`Ö,!6ôtM€PJ i‘––"rÔ¢EþÑ×EúíóÔ€ ñ¥âŠ>*"tå ´jU<ŸQJùöÛoY·n7n$==ooof̘A… Ðh4Lž<™U«VqðàA|||tÆ®¾ÙµkÕªU£fÍšo*Òz+V­Žž•Öâí sç>v.ÍÍáý÷¿ž’"æ ‰Éóµ‹qwûkÖ,w„5?ÌÍaÒ¤<õ¦nnnXXX¼X=pjªp°€ªUEßçÁÄD¤òß½+Ž;5µpuï‚È©õ®[7·€™°¶¶fúôé¬Y³†U«VP·n]ˆ½½=íÛ·'++‹Í›7“MãÆùðÃ_‹ù•+W(_¾<îîîðÃ?pãÆ Ý5cddÄgŸ}F§N7nœ¾‡+ñ’x{{3}útV­Z¥³UÞ|óMÞyç]ê÷߯³U*T¨ÀÔ©S_J%¶´Í¢E‹(_¾<ï¼óÎ"e±(°µµÅÆÆccã2¥rܱcG”J%{÷îåäÉ“8::2zôhÚ´i@•*U˜4i«V­bÿþýøúúòÅ_” [¥4Êo¿ýFÅŠ¥Eʧpuu¥ÿþEÖ½å¥-CCCºv튅…»víbË–-¨ÕjlmméÞ½;ï½÷^¾‘ÈÚµkóÃ? P(044ÄÚÚ:—Ȇ——ãÇ'55ssóç¯3+fŽ9B›6m ££Hwüþ{¡Ì[˜Ã*êîš4ÉûZNÕQ£D„ªqcèÛ÷ÙŽ¨\.jZŸ—âðÉȵv¹k ÿØÚÚ2hÐ úôéƒJ¥ÂÆÆF· #—Ëiذ!Õ«W'333×kú$!!½{÷òÝwß¾af¦¨;ŽŠ‘ÆÂ¾ˆ²²Ä+,ýåÈ‘Màâ½{?V¶.‘>ÿàÁ³VÈWÛÚÚ›[ ?p@DW/]z±¾¾ÆÆðå—ðã:=ÿ{Ÿ¦[7q]iµÅVóý¼xxxðí·ß’ššŠL&ÃÚÚZgÈЭ[7š7oŽF£ÁÖÖöµpV5 »wï¦S§Nº{–³³s‘òåËëZYI”]êÔ©“ËV±±±ÉåÄU®\™ñãÇ“––¦S.Ë„‡‡sëÖ-¦M›öZ\¯%‰»»û++ êƒ.]ºÐ²eK222055Í¥ì+—ËiÔ¨5jÔ(U¶Ji!==-[¶°{÷nÚ¶m[´B¬¯ U«V}¶Mù¼Ò·’‘‘íÛ·§Q£Fº6Z­V'À”9…È…E7ÌÌÌŠ]ñ÷EÈÎÎæèÑ£Lš4©ð …AýÝwÏV½­TI²­bZ[‹táJ¹rfEÎÖ¶pEÔ×CCÃU1A8M¥Iö=00kkëgg3T®,æ÷åË…o—žË– ѡ ¹·Þé¶!!"Í÷YÈ寜ëííMƒ ^LÖÚZôO yñ6PåÊ %o3³Ws4cb`Ó&Ñâ¦&&&0r¹¼Ðù_‰‰‰áúõëŒ3æ™Û–åH›„àyl•g½^–øûï¿iÕªU©,KT¬X±LF¤år9VVV…F†K›­RR„††‘oš\\K–,!>>žï¿ÿž*/²ˆý"G°®¨x%‡522’ùó瓘˜Èï¿ÿŽ••¿ýö{÷îåã?¦[·ne2}@£ÑpäÈ6oÞŒ‰‰ fffT«VjÕªþƈ‘âø<‘ŸçI,ëôè!ê‹ZÔIâ•Q*•œ9s†“'O’––FXXƒ zöB‘™™¨¥®S'o*û“„„ˆÞ¥Ïã 9:>»æº)W®Ç±7y{ §ï¿ªÁ/JQµaapâ„pX%JœëׯãååUæ#iOsþüyîܹÃ×_ýŸ„)Júõë§ï!HJ¥’K—.1gÎT*÷îÝãÝwßÕÙFIIIŒ?OOO¦OŸþÚ,X•^ÚaMOOgÉ’%DFFòÑG!—Ë‘Éd´mÛ–ääd~úé'ªU«F­çqÞJ†cÇŽ±téR†Š¥¥%†Ê•+?;" ”NEË™'ýÀ™©\Yˆ-…„ˆ¯3¥DùV"7‰‰‰,]º”€€zôèA•*Upqq¡|ùòÏ6VDÄðéUøóç…S—³sê”pjŸW‰·‘Ëå/~“qq‚Qú\|qwjÉepðuàĉ¯… ¬„Ä“dgg³iÓ&Þ|óÍ2UƒYšœ–×­VËúõëÙ·o#GŽÄÕÕ•9sæ’’B¿~ý8|ø0Û·oÇÇLJaÆIÿ÷æ¥sâââ8sæ £G¦K—.:‡µzõê|þùçT«VãÇëûø^˜Ã‡óË/¿0mÚ4Ú´iC£FhÒ¤Éó5. †í£G°nx.3Sˆ®$$ˆšÎÌL¡Zë$Ê>ééé|òÉ'¨ÕjV­ZÅ»ï¾KÆ qwwvÝ’F#æuLŒpPÿüS<%Z®(pñ¢PÃíß_´)ƒiRù"—‹ã‹ŠÒßÜÜ uë×眖!¸uëÍš5Ó÷P$$Š”Û·oFÛ¶mõ= ½¡ÑhøçŸØ»w/Ó§O§iÓ¦TªT‰Ù³gÉ Aƒˆ‹‹ã»ï¾ãÛo¿-5ú:ÿ%^ÚòÉic“_O!###,--uMµË ñññ¬\¹’É“'S½zõO©REüØÚ>î)ùè‘heѬ™pV÷ïʹe\þ^¢lrùòeÊ—/Ï·ß~‹©©é‹ÍñÌLá°Ù؈ޢǎ‰9 ê•--EK§3gDÝj‘ø.”Jᔟ?¯¿1Èdz[ú/’Í’%Kxçwþ{})µZ±P%ñZ’žžÎ¯¿þÊ[o½…ƒƒƒ¾‡#!¡7"""X¼x1cÇŽÅÃÙL†L&ÃÒÒ’iÓ¦ñçŸ2lØ0üüü$Q2=ñÒ«µµ5U«VeñâÅ„……éÒ222øçŸ¸xñ"¾¾¾ú>¾âÆxxxP·nÝ—+ ïÚU´»¨TI8¤ …HnØPM˜ T¿ûîõ¯_•(•œ8q‚®]»¾œÌ¸\Ý»‹N??¡X›˜(€Þ{O8©ß}'2 bcõ}¨E“”‚[%Ë¥K—ˆŽŽæÍ7ßÔ÷PJµvî„Ý»õ=‰b@£Ñ°dÉèׯ_™ *UÄÆŠ`„D™#33“ü‘ž={R»ví<¯›™™amm-Õwë™—^&°±±¡_¿~Ìš5‹¯¾úŠ*Uª`ooÏ­[·xðàÍš5£þóö*,hµZ‚ƒƒ_Mí++K(Ëd¢Ö „£Zµªø»bEñ[Ï}%þ›¤¥¥qõêU>}YÑSSèÕëñãÉ“ÁÊ þíÛˆ¹žóüë„¡¡è‰\ kr%еZͦM›xë­·þ[-T*X³Nž ­7oŠ¿?þXª¡~ ÐjµrúôiæÍ›§ïá”M’“ŵµXØùç¨WOttP(^¬Å „^P«ÕÄÇdz~ýzlllèÑ£‡¾‡T6ÉÈ€Ù³…-زe±}ÌK;¬r¹œ6mÚP¹re:Äõë×‰ŠŠÂËË‹>ø€¶mÛ–)…`•JE`` ýû÷ùüò |òInÑ®]õ}h>"›š wï ç5Ça½rE|†ƒƒxV+œêädáÈÖ¨!Ô®ccÅñ89 Ç´Má¨9">#!¦L;;L=Â&8X¯óãuàáÇ|ùå—888àââÂÇŒ¾‡U:ص œ¡cÇçÏ;â45Íý¾*UÄ|—(Õ>|˜ÄÄDf̘»»ûËÛE¯Z-¤¥‰²®) HL‹›åÊÁ AâÞRŒ¼Ãjee…¡¡!ëׯ'==Š+âçç‡6e<ú‚­­-åË—¹ÄÆŠvN?I++qóíß_ª{“(œ>}Ÿ—¯UJK¢K9ï¿wO´o’œU‰2NTTŸ|ò C† á­·Þ &&†¸¸¸âoͦPÀåËâÞQ³¦ˆfN˜ Œ!Co÷ùç"ƒ'2òñ}¦ysñó4 "JY­š 33Ÿ±u«Ø¾qc±uãtè Sµöîï0à±³ "àysѪÍÈHDUóë=ùdÉøŸÄÊ{¹rBß„îâ"¢¸ii··²ûõó{íÊÎÆ¸Œ 8–6²²²X²d =zô`À€úNéâþ}±°sç΋9¬*ˆëõi\]¡O}•Ä38}ú4~ø!sJõþË$'ìY0fÌóg’=|“& §\9qOzûíbæ 9¬666tïÞŽ;’@PP§OŸfíÚµx{{ãííM5ptt,sõ>gÏž¥iÓ¦/ŸÆlc#Äfr°²Ñ'gg}š„¡¡¡:cü¥ˆˆÇ5luëÂo¿éû°$$^™#GŽàââÂ_ý…¿¿?åÊ•ãŸþ¡~ýúØgïÝ„ÞAíÚ@{{˜8Q¤Ù;:æV†65œÂ05çÓ´n-œNcc±èdl 7‚§§ˆ|nØ ¢›?ýTð¾_4EW&ƒNDš˜µõc'ØÆž®30¢„O‘U±"±e¬Ÿ{iãæÍ›¡!´k—û¹³gá±èô_Žä•‚‚‚HJJÊW`éµåÆ Ñ/¿ûÙÙ³Óâ33EVLfæãÅɧIO5«Ý»çîx’-öãèX,í÷^¸†U&“aff†››nnn´iÓ†èèh®_¿Îŋٹs'4iÒ„Æã\6•JÅ™3gøî»ï^~'ÆÆ¹Å”ŒŒ¤‰RCLL iiiT®\ùåwÒ ˆ°ä`l,Rÿ$$Ê8‡fèСlذãÇÓ­[7Ž;Ƙ1cŠW=ÕÀF÷ŠœÏ16~,ÐW”掚:;C«V°z5̘!²%fÌÈß@yYd2)}‘Ú@‰"E©T²lÙ2Þxãâ]|)k¨ÕbÁõÍ7¡}{±û"Vê¥T ÃÝÉI<þûo±õo7 ýrñâE|||Ê”ÎÎ+qí (2k~ù%ïëÛ·‹è¨©©ÐD;Ê—'+KD²žÀ0- ƒ¬,}Ÿµÿéééœ:uŠÏ?ÿ\ßC)9ÜÝá÷ßÅõsæ<î€P³¦Ðß12ó4"BDes®¥RÌãüÄ5­¬Ä5S,ëK/'$$ššª{ÃúõëÙ´ir¹œÏ?ÿœN:ù€‹ƒÈÈHÜÜÜ ^I·³ƒM›DmOb5:4T<Þ¾®^Õ÷¡HHäA­VséÒ%ê¶‚*æð“7ÍÇEúaΪðíÛ¢ÞNBâ5!%%…M›61`À ¨S§ŽŽŽLŸ>Ž;_t52–-Ó÷á £ÄÓSü-9«¯ìß¿Ÿ·ß~CÃWŽO”Nœ)îÂñXºF-š4aPö™˜÷jµÍŒ‹{¼U«DÚãÙ³y÷ã†H,SSñ“SŸ=x°p\³³áÿiÈ_~)4!ÓˆÌ$¡¦!==ÔÔԗ׫)‹ØÛƒ¯¯ÛpÛ¿_¤ýXZ>ξ14>¥¥¸?ìÚ%v9lÙR°¯ca!¢¸Ëa¼ðÝ8::šo¾ù†®]»rêÔ)@ÔÆõîÝ›%K–°víZ>þøc/^ŒJ¥*–A5W¯^¥iŽÊáÓ(•0s¦¨Ý{²Æ¡BøõWñ„œ¿’(…$''F½zõòß #.7í'PjÖi"9_d?ÿ,VÎ$$^Ο?“““®–ÉÈȈ¯¾úŠºuëÒ0çæ^ÔDG÷ߊºU ‰bäþýûx¿L{¡²‚Z-Å®\×–Z-Ò{—.©››Ø®aC‘š;x°0¬ŸD«jÛ9ˆäd8Ú¶ÊÜMîÏ‹‹Ë_p)ss¡Øš*lÜ÷›˜Eì¦M§]i5k’VÊç^öïߟŸN9éÚ¯3©©baôéű¨óÞ{°cGáûhØP´iR*E@cëV±ø’rùãÔ〘6Mdî/´ä¦V«ùý÷ß¹ví_ý5õë×G£Ñ°uëVŒŒŒ3f ^^^ìÝ»—¿þú‹N:½ZÍ\ ñàÁšä#ö>"B9_| D*ž¤B…Ç+Õ¥ˆ´´4¬¬¬ B‹‰sûË/s§qôè!æx¸H)‰Š*–4 } Ñh8pàíÛ·ÏÕÒÀÃÃ9sæ_½ß‰bµ»Y3}Ÿ‰×­VËþýûi×®–––úNñ‘œ ëÖ £ÜÄD¤âæ¨h?Ia P9%/‘‘B«!=]Ôxûù ûïId2‘Þ[X­·±±0Ü/_*ÙcÇ>®ymÐ@ßgì?‹Z­æôéÓ¯¯RvN6œL&êVW¯úO—X[‹(hhÁÎg•*‰ë)=]¤Ô;;?[c!=]´VóöÎ_ð%y!‡588˜³gÏ2lØ0zü«ðÅÙ³giÛ¶-íÚµÃÀÀ€pìØ1Μ9S&Ö‡,•‘!¾ÈªWœãýè‘Xipsµ õëÃ7ßèû0$$ò%%%++«‚{IªTbÅ÷É”áèhᜆ‡‹:œŸ~7üü  ‰2Èõë׉‰‰¡M›6¹jû °··/¾.fé €ððp.]ºÄСCõ=”¢%:ZDoÚ¶)‹öö"u÷UÉ„YŽÁïèãÆ‰}?-Æ)—?»U¡L&R*÷í S… 4I”Z­–“'O’˜˜HãÆõ=œ¢'.N´%k×Nh阚 uö-wvx##‘ð,Å"ˆ6iß}—[¼/?llDú}óB)ÁIIIÈd²\}颣£‰ˆˆ iÓ¦ºUj¹\Ž©©)1e }055•ììì‚VGGጋ¾“™™¢áy` x}Ï±Š¦TJ p¥’›7oâää„qA7ÍŠ ŠÝ¾-i~ùE¬¾åÔ°FDÀ°aú> ‰"!;;›M›6ѳgÏ‚rŠF\O9õtňV«Õõݶx:ýµ¬ TæNŵ£pîœH5<}ºè>ÏÏO@óO¶æHM »9ß¼ùl{O¡Q_)“¢T••ÅŸþùzFWLJ?s.'›¢Z5‘%W‹¯ˆšZXˆl;=ñB«Z­F«Õ梸zõ* …???½Ä«HÅŠ N™16õ«r9¬Y# OœѦœÖ5[¶'¶ŒÔìJü· ÁÛÛ»`…HCÃÇi! ŠÚœž]ÆÆ"ý);;oÝ„DåáÇÑâÉrÅIPhÊþ¯ÈŠ„Dq¢T*9vì]ºtÑ÷P^ެ,¡™pâÄc§uÃ!Œdo&ˆ>¨Å•¶æŒÈ.ÊaÑ¢Ç&—/ÃúõÏvX-,`îÜâ£Ä ±gÏlllhÕª•¾‡òâh4"Å7GS£©æaaâñðá"ý÷³Ïžâû2(0i’° õ˜{!‡ÕÅÅ###Ο?J¥"==C‡áãã“ËዎŽ&$$„O×y–B‚‚‚ðññ)xƒøx‘·­ÕŠÆë[¶ˆT”…±fÍ„aêTîÕ@ ‰RBHHo°?\¿.þ®UKÔuè Ò:@Ì÷´4ضM߇"!Q$ìÚµ‹-Z”L_ÊÔT!3`€ÈX(fîÝ»‡Z­.Þ¶LEAJŠH½}ð@¤3æ,èŠ:ï_~Îã£Gpü¸è™*—‹Ÿ®]E\Qòõ×âzýë¯Ü‹Knn¢,&>^,æzy=޾J”znß¾ÍßÿÍwß}Wpk¿ÒŠZ-H>ûLØj ìµßœjîì\4‘Ô‚07µâO.âèªa­P¡þþþ,Y²„[·n‘’’Âõë×1b¤¦¦rõêUV®\I¹råhPŠË¯]»Fÿþý Þà̱²öÕWФ‰Hùè£Ç¯;9 GvÛ6©-€D©#%%…˜˜< S©D?᜺º–-ÅbLçη14‹6ÿ•~¯5 œ8q‚™3g_Ûš'14)÷uëJF®D±£R©øóÏ?騱céO>’’DT(9Fb0^^BMׯÅ}ꫯwe(.22DéWllîÅ¥wÞ©–¡¡B„¦\9}Ÿ9‰|HNNfóæÍôíÛ7×Üß´imÛ¶-¸ô¯4£ÑaÌ_~®°x1|ðAÉõð60€)S„ãªG;ð…V>ûì3LLL8uê†ðæ›o"“É8yò$óæÍÃÍÍï¿ÿÇ|Zرc—/_F­VÓ²eK:uê¤[é~øð!;wîäÚµkT¬X‘^½záååU,†ERR‘‘‘º–ùòè‘pJe2¡¶5dHÞ‚ãªU…+9¬ˆú¸K—.±gÏ…Ïæøqa;YZ §0-Md«yy ›ËÏOd·ÉåÅï¬ÂcUà=D/ÊLMÅs ®ë×dñöÞ½{ìß¿Ÿ€€¬­­éÖ­þþþ˜šš¢V«u¶Jtt4õêÕ£k×®¥ºé®]»˜={6~~~øúúÁÕ«Wùßÿþ§ïá=?ÑÑÂ.«PA”ú8šªÑˆv1%;Ÿì’¢'^ø›ÕÚÚšádzdÉ–.]ÊW_}…Ý¿v½zõ˜1c?ýôµjÕÊóÅ‘‘ÁâÅ‹Y³f ÞÞÞÔªU‹¥K—²|ùr²þÍÍþñÇ9tèÍš5#22’iÓ¦[,Ÿ˜˜ˆ½½=Fù)håàèøØP—ÉÄäyz’ØÚ §õ5ù“x5.\¸À7ÿªFwîÜ™€€&L˜@xx8±±±Œ;–èèhüýýÙ·oóæÍ+¶±DDD~ƒ14„wߪr CÃÜsÙÀúõ+ÞÿyÔj5[¶laÖ¬Y”/_ž¦M›²gÏfÏžMBBW¯^eòäÉXZZR­Z5V¬XÁ¦M›ô=l=zıcÇèÞ½{Á5ÝE÷aB½TZ*sddd°hÑ"þøãj×®··7K–,aÅŠdÿÛÓðûï¿çÈ‘#4kÖŒ°°0¦M›F\\œ¾‡ÎÁƒñ÷÷/Xd¯41b„:’ÉÄ}fÐ 9ÊA&+Ù¬„ž=…ªjÿþyí¹œTdCÃ×"8‘œœÌ„ 8rämÛ¶ÅÁÁ &°oß>­‡¿¿?{öìaþüùúv(•JŽ9B·nÝØñooQµZͪU«h×®]©v´u¤§‹l‚°0¡y°t)$$äV™–ËE ðk0_”ध§³k×.Ž;Ftt4uëÖ¥oß¾T«VòåË:)‚ƒƒ9zô(Ó§O×ÉJ×®]›‘#GÒ¿î߿Ͻ{÷˜3guêÔá7Þ _¿~ìß¿¿X”½âââ°´´,|E´GÉ•x!6mÚDÓ¦M™4i†††tèÐÏ?ÿœ;vèz¡N™2;;;¼½½>|8W®\¡^½zE:µZÍåË—iV˜J¡‘ÑóEþ M¶%ž‹ÔÔT¶lÙ AƒøðÃèØ±#={öäòåËìܹoooÆL&ÃÑÑ‘5kÖкuëâjBzz: ,à“O>¡â³úȽ*‰‰B¦_¿Çµàe†»wïrâÄ f̘Aÿ½½½ùöÛoyï½÷¸}û6!!!Ì;—ÚµkÓ¥Kú÷ïÏÁƒyï½÷ô6îÌÌLNŸ>ÍÌ™3õ} óð!ܽ+ÊMrl©øxáøgÝÝËàè(®]¥2ÿV ¯'Nœ 33“yóæáåå…F£ÁÊÊŠåË—óÖ[o±mÛ6är9S¦LÁÆÆ†êÕ«óÍ7ß ‹^–&uãýâ‹/ ÂÈȈëׯ³jÕ*}// ,[&ÚÐÔ®-•¦L×ÉoÀ?À¯¿ŠíJÛu¢'^héJ«Õ²wï^fÍšEdd$666lÛ¶ &––öÌ÷«T**T¨€ŸŸ2™ýl%Á€IDAT ™L†‹‹ éééh4îÞ½Kùòå©T©2™ 333üüü¸víZ±|ll,nnn…;¬ju±|¶Äë‹¡¡!íÚµÃÐЙL† ¦¦¦¤§§Dݺu±´´D&“áîîN… Ìi“T„dee‘’’R¸ð†F#j"¤–LωV«ÅÆÆ†æÍ›ë¾ÇË—/J¥"33“Û·oÓ´iSär92™ ___²²²ˆˆˆÐë˜=ŠB¡ }ûöÅ] éõíÚI že•J…‡‡¾¾¾ùÚ*wîÜÁÅÅ…Š+"“É077§^½zÅf«<Z­–C‡Q½zu*”Dúìóòð!̘>¾ßÌžý¸5`i"%¦NýO¨ygeeáçç§›Ãr¹ggg-„¯¯/Èd2<<22²p±…nÝz,H#QfP«Õܺu‹[·n½ðBFQφ øñÇiÑ¢…îË4?”Jå3÷uáÂ…šã …‚ììlÌÍÍ Þ($D(ššêåI¼<9â^ááá%¾(⋊ŠbÁ‚,Z´ˆ!C†PµjÕ|·Õh4Ï4Èîß¿ÏÕ«W‹ôzÕh4œ={–3f0räHêÔ©S¼'åÁx†Ó"ñbœ={–˜˜½|¶R©äîÝ»Lž<™3gÎ0|øðBÅà ³U´Z-÷îÝãþýûÅ2ÖsçÎaoo¯¿èªR)jðîÜo¾­8®^¯¹ºÂĉB€ÌÉ þ-%(uØÛ‹ E : …‚³gÏ¢P(ôrÈ9iäcÇŽE¥R1hРB·/ÌVQ©T\½zµÄk¹>|ˆZ­ÖÍ}gggêׯOÛ¶m îPhµ¢ ÊBÑ·eK5=pàñ6-Z@ÅŠ"§±,Å•+W^yQæ…—‘äry®ðº±±1¦¦¦Ï½š••ŲeËØ½{77fΜ9T«V­Ð÷J\¯y-Ã눡¡!Mš4!++«ÄW›5 W¯^eΜ9hµZFŽI‹-0-Ä)4}†ÃèêêúÂMàïÝ»‡««ká­ LMEꢔ¶Xæ033£C‡º…Ä’D¥R±gÏ–-[†——?üð 6,ð†d``ðL˜ºuëÒºuë"çÑ£GY´h£G¦Q£FÅ{R”J‘Nؼ9T¯^¼Ÿõ¢[·nìܹ³Ä?733“eË–±gÏš4iÂܹsŸÙ×´0[E&“Q¯^½Âû¾¿$J¥’¿ÿþ›ê/ºzð H÷íÞ]ôH=xP*åSËݯŸ~Æ÷< 硱±±¡[·n\ºt©Ä7**Šß~û³gÏÒ¹sgÞ{ï= }Oa¶Š±±1­[·.Ü®.¶lÙB‡tÙdŒ9²DÇ/YYð÷ßðé§B8©kWhÖ,ÿ ˜>³"Š///Ú¶mKrrò+í§DÏPzz:‹/& €qãÆQ¿~ý\_ðnnn„††’––†¥¥%J¥’°°°bÈ \aý´<<„"!ñœ={–Y³fѽ{wºuë–kŽyxx€R©ÄÈȈÄÄDâãã o­ô’ܸq__ߟ¢o¾.ñZ£R©Ø¸q#›7ofРA´nÝZ—!“S—ýdD,<<##£gBEMPP ,`þüùT®\9÷‹©©`b’[}ñi4Ø·Ξ++¡êæW®À…¸õó-”JX¹RÜ3Þy§DS¢èQ(,Z´ˆÀÀ@&L˜€ŸŸ_.CÝÝÝèl•ììlÂÃË_Ì+´Z-û÷ïÇÆÆýœ°ÄDa˜/®‹N U+)s§“˜˜ÈäÉ“122âçŸÆÃÃ#WÇŒ[E¥RahhHBB‰‰‰E.ùªÄÆÆrþüy–,Y¢ï¡äåαâç÷ø9I„ï¥ya‡U­VsóæM4 äßSRR ãØ±c¹¶Í)€ÎáöíÛìܹ“%K–à‘\¿~}¶lÙBhh(µk×&33“‹/Ò¿ÿ"?ð›7oR¯^½ÂW#ML„|´„Ä °jÕ*üüüøè£0xª†­qãÆlß¾…B­­-‘‘‘„‡‡ëêFŠ •JÅåË—éÖ­[án´KH3:UÔüý÷ßtéÒ//¯¼:ÿ-´ >ûì±qèXå®[W¤j4âÚhÙRÔäådÕ¨óæ ¥Óïƒ EyÉH  bÏž=,Y²„š5kæy½AƒlÛ¶ððp¼½½ÉÈÈàÒ¥KÅÒÍàY$''³~ýz†®?q™Û·Åuñä¹’®ƒRÍ¡C‡ˆ‹‹ãçŸÎ¥9CãÆÙ½{7éééX[[Adddñgª¼ —.]¢jժؗF%Ý:uD[LéZ(^Èa•ÉdðçŸê q­VKvv6>äâÅ‹¹¶_¾|y.‡5((ˆèèh>ýôÓ<Ć ¨[·.Õ«WgÞ¼yôìÙ“3gÎ`mm]híßË R©8}ú4o¼ñFá>|(B÷…Ô×JHÏã½7¹979É=çÜ÷¼'44ôª8¶´}ûö·åï“ 23Íó² ظќÇàÌó\Usr%¡RÜR‡ÕÃÃ×^{’’’›züÃmÛ´iÜ9s®úX777ìííyóÍ7Yµj6l Q£FÌš5ëú‰‘nC^^7þâýðté½zUêë 5—B¡àõ×_¿êœî²µŠgϞͯ¿þʦM›èÑ£ƒ ªô9ˆQQQÝø¸k×^½Q.×àëë{ÍßñÆÀÔ©Sùã?ˆŽŽæÁ¼#uüZ222øå—_xçwÊÏßþýwóüÒÌY|£¢ ì1½z™ÿ•”˜gîYmÛ¶½fwqqÁÞÞžiÓ¦YÚ*Mš4á©§žºþ£; **ŠÅ‹óÊ+¯Üì×eŽ3¯!i0ÀÀ0rä]=o¡bär9C† ¹êzªeõ¨víÚVm•ž={ÞÕßñ›‘ššÊåË—m¦|ìDF¾}ðùçæëHãÆæ¬ÀãÇ‹Ðß;à–:¬J¥’öíÛ[þ.**"--’’”J%žžžøûû_óù-Z´¸á$^|ñEL&“åŽne»|ù2...×OFc0˜×âúïÜ'A¸WW×ra’ÿÕ¤If̘$IÈåòJ¿FNœ8A¯ ´¤¤˜çÞÝå¹…BõæïïÏèÌÓìܹ³%tÌÎÎîί{z… 6ЩS'š^™øH’ÌË lÙ£Fý»½Y³ò#â÷¼–-[ÞðŽe@@'NÄd2Ý‘ßñëÑjµìرƒ¥K—Þ„b))°w¯y@§V-ó\íW_5'ë»›e¡R(ŠÎw–Éd4mÚ”™3gÞ±¶JE˜L&~ûí7Fމ§§çÝyÑ~0_KžxÒÒ >Þûì3æÍ›Ç§Ÿ~Zå2w%$$ Õjo<U’Àh47tªX§[®çðáÃ4nÜøúëK›³ Ú*³¤ T¢ÂÂBþúë/¦L™b½Ãh4‡¾‹LB  ×ë)--ÅÇÇçξPYì«Ìs[;rä½zõº{M›Â’X wÔ-}ÒYYY¬_¿ž|!C†àââbu—ÒÞÞžvíÚ1}útΜ9Cll¬­Ï¯œƒzÃEìII ÌsY¡9|ø0={ö¼þ¹Á¯¿§NÙº¸‚P)"##ñðð qãÆÖ;΃%Kl]lN¸4~¼9$Xª‰ÄÄDüýýq¼^ø£Á`n”Lžüï’‚PÅÅÅ¡ÑhèÝ»·õ22à¿Û¡š:yò$íÚµ«¼PHI2·y,€™3̓ôÇŽ™§BÙj}KA¸“ÉÄßÿÍ}÷ÝWyß+àÀóÝ=fî¨6h B€«˜[ê°zyy!—ˉ‹‹#88øš·âµZ-™™™•¾~jEét:œœœn<2Ù­tïn®¼‚PäææÞø{çà<"c„A’$"##iÑ¢ …Âz§½½9¬ËÃÃÖÅ„ Óét?~ü†ËJÝÐÙ³æzÙuàðaó25eËöìi^ƒ^ h ULNN‰‰‰Lœ8±ò÷Ýg¾«*ê|•uKÃÁÁÁøúú²~ýzŠŠŠ®ù¸Ý»wSPPpÕE‰mI­V#—˯}÷)/Ï<ïè(ÑÕR^^Þõ×$;q’’DgU¨1ŒF#§OŸ¾úõF.OO‘8O¨07^²ìF-‚ÂBó¼<¥žÞ|W©ì{¢Pˆ†»P%eggãææV¹!ñæõ…ÝÜDÛ¨ »¥«££#/¼ðgÏžeúôé;vŒŒŒ rssÉÎÎ&..Ž… 2oÞ<}ôQ‚ƒƒm}~Vbccñ÷÷/? æÉß7¯³$ÕÔÅ‹¯òž—g^ž@’l]LA¨4z½ž¬¬,5jd½ãÈX»VÔw¡ÆHII©x»*%‚‚ॗÌS0wZEC]¨víÚE»víPUÆzÚ‡Á¯¿Úú”„›tË1¯mÛ¶å­·ÞbÞ¼yLž<™:uê`oo$Iäåå‘™™ÉðáÃ?~<Ê*v—2--íÚá’z=<S§Úº˜‚pÛ pww¿úÎÈHó¢XOO¨A²³³)))ÁÏÏÏzÇŽÿ†8 B pîÜ9ZV4L:æübÊ“PÍH’Ĺsçxê©§n=;°$™sÈåæšâbøé'3ÆÖ§%ܤ[þŲ··gàÀtêÔ‰pìØ1JJJ°³³£gÏžôíÛ·ü¢íUD^^ÞµÚÖj¡Møï(½ T#ÅÅÅ×î°z{›GÕECE¨AvïÞM§Np¾2„Q«…¨(˜0A„ 5FBBÂW9ø¯âbˆ5gA•ËÍóõn´¬Ÿ TAÑÑѨÕjBnguƒäd˜2žz ú÷7ÿíî·ú}læ¶[®žžž <˜ÁWÉ"WXXÈÂ… yòÉ'ËzÛPZZ ¸úNWWxñEñC.TkæÚVq·I¨aL&d„ Ö;d2˜6 ªXâ?A¸]’$]?JìZbb`åJsã<$D,Õ'TKF£‘mÛ¶~õi}ÿ¥Ñ˜WDpqÔT˜5 † =ÌûëÖ5GTйÚÕÆ¹ÕRRRÂ?þȈ#ªL‡Õ`0””tõû¢"sž^²A¨²³³ñøoFTΜ2$D$j”¤¤$222Êßurp€æÍm]úèÆ.)>0'Rš4ÉܶŸ>®œÿíâbëSnÑ=3Ô–••…$IøøøXï0™Ì dÿó­‹(‹‹ .ÿý!¾x/6w\¡‰/Ÿl);Ž5ÿ¶ B qèÐ!:wîŒÃõ¢ÀRRÌað<Ë–™î‚PìÝ»—ààà›°9rrsaÜ8óß*•ugU¨–î™ÉlYYYW¿»zð ùîÓCÊ¡š¹|ù2ÁÁÁåÓ^»:v¡/BsìØ1Zµje½qËHOw•„Ãh4²{÷nžyæ™ë?°Ns"A¨AÔj5ëׯçµ×^»þ€MxùeðõµuÑ…JtÏÜa-(((wÕh4HΜ U$tYnWrròÕžµh£F‰¹KB“””DÓ¦MÿÝ Ó™£eËt5FVVùùù4¿V˜{b¢ùŽª Ô0’$±oß>j×®}íúæ•>²²ÌÿíÒ®¼.5Â-Ýa5 ¤§§£»Ahavv¶­Ïëªeòòò²Þhg'RZ 5FZZÚÕ³`ß¿­‹&wDqq1ÞÞÞÿnÐëáÁ¡¢KB’žžŽŸŸöWËðn0ÀÏ?Ã# ¡Ðëõlܸ‘!C†`wµAHƒÁ¼„Ù† æ¿§M3ÏÝjœ[ê°^¸p×_ŒŒŒë>Nªb µK’DjjªuÃæÒ%ó§À@[O*ETT÷_Ù9‰1gKmÜØÖE„JWTTD^^¾W†}9;C¿~¶.š TªóçÏÓ°aCóÚ“&\¸¥¥Ðºµ9jv6ôîmëb B¥‹ŽŽ¦¨¨ˆðððk?H§3¯òQ¿>89ÙºÈÂrKÖºuë2eÊJKKoêñ·œ~ý1™LdddÐîÊ9Më×CíÚ¢Ã*ÔÅÅÅäääxe}ÞºÕ<§ItX…(22’&Mšü›d,?rr aC[M*U||<]»vEf4šs,Ybž£Ý¬™yžÞäÉ"ë©Pãh4-ZÄ„ ¬o8¹“j4š* fë¢ wÁ-uXíííñõõ%00Ïj´ŒÁ` ¸¸777ó½¢£aà@[M*Eaa!^^^Öë“;}úغh‚pG\¸pÁzNÓÂ…æAHÑajƒÁ@TT=öØÛƒ·7üú+\™“C$Ôj ­[·bggGï+£RSáûïÍd­ZÁk¯‰ü÷ˆ[ú”“““ùä“OˆŠŠ²lËÈÈ`Ñ¢E [ŸË5™L&´Z-*•ʼÁh4gM­"w€¡¢ŠŠŠ¬—³)-5Ïãûï’‚PH’Dllì¿ —23áüy1)Ô8ñññ¸H IæÐßÿ&„Æh4²víZFm½ÃÙºv…W^gžÕ{È-}ÒZ­–üü|«ÎiNN¿þú+¦[\óN§Óqúôi4Õv“ÉDbb"ûöí#**ªR:ÂF£‘’’œËF!á±Ç ìŽ« Ü!±±±åæ| Î;ÇHJJÂh4VøuŠŠŠP(æ9N`“yùes]„;èìÙ³XmÓh4;vŒ#GŽXÖÀ®L%%%ÄÅÅjÞ V›“-ùûÛúíj­VËéÓ§ÑjµVÛM& ìÛ·èèè;6hüðaJHÀþ·ßlýV5TNNçÏŸ/·Ý`0ÉHNN¾åvþíÊËËcÙ²eøúúÒ©S'óƤ$󠤻»yÐ&, <úè#¯hT¯_¿žß~ûÍÒˆ4h=ôпwGoƒ^¯G«ÕþÛaÕj͉ *pLA¸‘‚‚¾úê+†jY캴´”~ø;v —ËQ(Œ?ž!C†Tèµ qqqù·ÃªÑ˜³`_",•H’$222˜;w.¯½öîîî€y Ž pæÌìííqqqáµ×^#$$¤Ò^;;;•J…R©4o 2ÿ„J$IçÎcáÂ…|üñÇÿÖ7`íÚµ¬\¹£ÑˆL&³´U+qP¯Ñ¸¿9ûû“Oš“è B%2™LlÙ²…¨¨(Þÿ}Ëö’’K[ÅÎÎ…BÁ#< AƒîXY²³³Y³f {öìÁÛÛûßuWµZ˜7ÏAÓ¢…­ß2ÁFîú½ôøøx~ùåfΜIaa¡ÕÈ{jj* , OŸ>üòË/¼üòË,]º”S§NUè5/_¾ŒÏ¿!“ýeNƒ-w@QQ;wîäý÷ßg÷îÝV#ïÇŽã×_åå—_fùòåôèу¹sç’››[¡×LMM¥~ýúæ?L&X¹ÒœIRî€ôôtÖ¯_Ï[o½ÅåË—-Œ&“‰?þøƒ'NðÙgŸ±dÉüüüX°`ÅÅÅ•öú………øúúšhŠŠÌYR¡ÅÅű|ùrfÏžMQQÑUÛ*ýúõã—_~aâĉ,]º”Ó§OWj²³²8XXˆÝ»ï‚««­ß¡†9zô(ßÿ=_}õjµÚjß‘#GX±b¯¾ú*Ë—/§[·n•ÒV¹žmÛ¶qîÜ9ÞyçæÏŸO½zõÌaðÛ¶™£hzö´õ[&ØÐ]ï°¦¤¤m5ùcÇŽáííÍ!Cptt¤C‡´iӆݻwWè5 ºrôýÌ™jyç)##ƒçž{Ž‘#GZþ;–Ù³g“••@ff&¯¾ú*û÷ï¿ê1ŠŠŠ˜4iÿüóÕ¶Ÿþ™áÇӱcG:vìÈÔ©S¯""ÜXII gΜA­V—«çûöí£}ûö„‡‡ãèèÈàÁƒñððàСCzÍÜÜ\üüüÌ xƒÁ:#ævwHnn.çÏŸG’$äWÔ3“ÉÄÞ½{4h5ÂÓÓ“±cÇ’ššJ\\\¥½~JJ ÎÎÎæú¾z5Tð!ÿ•œœLLLÌUÛ*GŽÁÏÏÁƒ[Ú*­ZµbÏž=•Z†Ä”R°ûô‚ T¦˜˜þ>¼Â¾}û§}ûö8::2dÈÜÜÜ8räÈ+OTT£G¦¡É/½eíÔZµÌÉ•ªa»]¨<·Ô¢µ³³C&“‘Í¥K—¸té©©©F,ÛÊþétºrÇèÑ£sæÌaðàÁåöEGGãá៟ …‚fÍšqîܹ dzz:þWÎmŠ‹3/÷QÍ”””°k×.\]]éÖ­ݺu£Y³füú민ñÆäååQRRÂŽ;HJJºê1ôz=Û¶m³ì7üøã̘1ƒððp¦M›ÆË/¿Ì… xñůyáÚjÕªÅäÉ“yå•WðùOrŒsçÎd óóóÃß߿ƒYYYÿ¦}7Ì!Áb~‡p‡´hÑ‚·Þz‹ÇܪAo2™Êeïmܸ1Z­–äääJ{ý””Z´h,?ß1S6ÏI*IÏž=™3g¯’È+** ///ËÀJ¥’&MšT¸­b%=ÜåËéСƒU(² T–ñãÇóþûïÓ²eËrûÎ;Gpp°¥îùùùáëë{Çnd”””˜éÕªo¿mÎnƒïØQ,Ï'ÜÚV™L†\.çË/¿ÄÎÎ0wxL&Ï?ÿü¿óçþoñâÅßôñÕjµ%VÌd777ËÝÃkÉÎÎfݺuŒ?Þ2êJIIIôíÛ÷ß óæUÛ5Ë ƒ¶dN3´mÛ–—^z‰ääd\o1l(33“Õ«WóÔSOñÆo`gg‡$ItëÖ‡~˜¿ÿþ› &Øú´o™^¯gïÞ½ìÙ³çª [)..ÆÁÁÁrWÊÑÑGGG²oÒ˜˜˜Èï¿ÿN¿~ý®º¤Tzzú¿Ÿ½Jï½'ЮáÔj5[¶láôéÓtîÜÙÖű*וóøÜÜÜ0 ]÷yGE©T2`Àìí¯iŠŠŠ2¯³³¡C‡j9)Üœ+V”K\gk·ÓV‘$‰C‡Ñ Aºtérý0á?H9|˜ˆ—^²õé wP^^+V¬(¿Î¨ý·­¢R©nØVÑétlݺoooÝâ gÏž¥nݺø™Û/ÁÁæeœ„j/**ŠM›6Ñ¡C‡ ç–jCýúõ™1cÆUïœ^MY¢™ŠºQ†I:wî|ÕÎ*˜C{^¹6_ ¯±³³ÃÅŇ6ò®Æd2¡×ë)((°¼Ï2™ŒúõëóÉ'ŸXF«…BAïÞ½­UÙêx`` cÆŒ¹æþÜÜ\¼¼¼ÌÈdb¾Ó=ÀÙÙ™x™Lf@¬ª$Iºa¿éäcEEEÔ©SÇ<êþâ‹¶>=á7n7n´u1nÊõê¸L&£S§N7î¬äçSð×_\ð÷ç ±®pæééɸqã8~ü¸­‹Ra 8ð–;«—"#iݲ%2{{hÒÄÖ§"T¢fÍš1dÈr« ܪ[êḹ¹U¸‡|=ŽŽŽ˜L& ööö˜L&Ôj5X/5;;›‚‚sãÌáÀŽŽP·î;2YYY8p ÜÒ=·¢uëÖVáuƒXÒ‹çææòý÷ßóôÓOLZZÚ-ßßߟ|™3grðàAFŒA»víhܸ1áááU¾!\Ý899¡×ë1™LÈårt::îß„I·¡,cª¥ŽGFš×éK|6àèèh5¨©V«Q*•xTRˆzII Ôöö6‡¾‹¥›„»ÌÑÑ£ÑhÕV)))©P[åJ’£#Ò®m[q lâ¿m­V‹N§«´QWÒÐiãFüF²õi UØmßo7 –a­V{Õ5Èœœœ¬rÜH‹-8yò$YYY ÓéˆŠŠ²¾;z‹òóóñôô4‡+K’9AGûöw¥Ã*—Ëqtt,*}+þ{×T§Ó±yófK’­VKJJ z½½^ËÇ·³³ãÉ'Ÿ$00íÛ·óÝwß¡V«©]»6 àõ×_¿ê„|áö´nÝšK—.¡ÕjQ©Tdff’––Fÿþýoû˜—.]¢víÚÿÖñ/¾€‰E‡U¸ëär9­ZµâÂ… DDDæÄvvv–ÜuñâEêÖ­‹ëæ±;¸Ì‚ \MHHgΜ!;;´Zm…Û*€ù÷Ûh¤D’8¢ÕòbX˜­OU¸GµnÝš‹/¢Óéptt$##ƒÌÌ̫柩(Ùºu$&%áÑ»7b"“p-·Üa5™LÄÅűfÍBCCéÔ©S¦Laß¾}–ÇÈd2¼¼¼X¾|ù-Íaíܹ3ß|ó þù'#GŽäÌ™3œ:uŠùóçßö –eO ¤Ä|‡uĈ»òæz{{sß}÷Uê1œœ˜5k–e+ÀÉ“'4hõë×§G·uÌaÆ1lØ0Ào¾råJ/^ŒÓ¦M»­pc¡¼Þ½{óÖ[oqüøqBBBøóÏ?ÉÏÏ·žc}‹’““ÿÙOO‡¼< µõ© ÷ ;;;úöíËÆéׯÎÎά^½šÀÀÀJ[‡õìÙ³„Ô® ?ÿ Úú”…{P—.]X´hÛ¶mcøðáœ:uŠ3gÎðôÓOWìÀ°lC‡ü5#wYïÞ½™1c'Ož¤yóæüùçŸÒ»wïJ­‹99üÙ±#®’ŸCÊÜr/$..ŽÉ“'£Õj­ÂƒGŒA§NøóÏ?‰ŽŽæÍ7߼³3>>>Vá.¾¾¾<óÌ3üüóÏìÚµ µZ̓>h{«òòòþ½C(—CÿþPMçe^K‹-hÖ¬'Ož¼åkdd$'Ndݺu–½fÍš1mÚ4rrrØ·oÅÅÅ•Îw/±··ÇÏÏÏ*MëÖ­yà˜7oNNNh4&MšT¡»ØæõÊÀ<õþûm}êÂ=B©TâççgÉ,“É6l˜å P($‰7ß|Óê{p»L&'Ožäþúõ¡Aƒ÷[.T=...øøøXE‹•µU–/_ÎÎ;Q«ÕŒ?ž¦M›Þþ ÀGA»v;ž€€ÜÜÜl}úÂ=ÀËË«\4dhh(Æ ã³Ï>«´¶Êµó÷ÇG’*å!Ô\·ÔaÕét|õÕW899ñå—_Ò°aCòóó¨]»6÷ß?ýû÷ç믿fÕªU„‡‡_3ûèÑ£­î–yàèСñññÔ«W Tè333ÿ]ÒF¥‚ë$®©®.]ºDLL #G޼åç*•J233ùý÷ßyòÉ'-z½žÔÔTEJýÛÄ?þhµÍÑÑ‘‰'Ò¯_?233iÙ²å¿É’nS||<íÚµ3ÿáï>jëSîeë6_ÉËË‹9sæpöìYt:!!!•ÖÈÉËË#99™f¯¾ ÎÎæA¸ƒÆŽËرcËm1b;väâŋԯ_ŸÀÀÀнPl¬yªÒ£ræ½÷‘MÂ]ñÎ;ï”Û¦R©x饗èß¿?YYY•ÒV)'& 9}ú4÷Ýw_…¦Ï 5ß-ý&$$À³Ï>KPPÐU£R©?~hÿ.IF£Ñ²ôŠ-•––šç °oظ]îîî<ûì³7|Ì3Ï>žÆbÀQ¨éêÖEÿæ›lÿõWKÂOA¸ž›_s,‰Ξ=kéŒÊd2 …Uò¤œœâââ*žâ½deeáîî99æ,ÁeÉi+2™ ¥R‰››®®®¢³ZM””” P(ÌŸWr²9LRŒT 5TÂÁƒ´ ‡JZ"Gª„#GÌí 11ñެu)6W\ ›7›×ÏnЀ¼€._¾\¡ÄªÂ½ã–z%õêÕ£GüüóÏ4hЀN:™ïìüŸ$IÄÆÆòÑGHxx¸MO®°°ƒÁ€§§'(•ðÃæuûª9£Ñȹsç¸|ù2Z­WWWš7oN:uniÝÛÛ¥Óé8þûÌÿj׆ÿßàZ¹r%;w®´5º…ší–Z¶2™ŒqãÆqüøqf̘AïÞ½éÒ¥ µjÕ"77—Ó§O³}ûv yë­·l“ž˜˜Hýúõq,›ßWÑðõ×_³|ùr$IB©T’››K½zõxóÍ7r„žbÝU¡&jÝ)**Âh4â+ê¹PÓ8;ÃÛoƒ·7‡¦Y³f"ZN¸i·u;ÆÕÕ•Gy„Aƒ‘••…Z­F¡Pàáá¿¿?ª*®•––F@@èõæ Áõ냧§­‹uÛŽ?Ζ-[˜6mšÕ€€——3gÎ$33“¯¾úŠÐÐPŠŠŠ(,,D¯×³iÓ&$IbðàÁ´jÕ {{{L&ÙÙÙ¬[·Ž¨¨(ÂÃÃéÕ«þþþFN:…··7qqqìÞ½777|ðÁk¦ðwvvfĈüôÓOå²_ÏŽ;ðòòâÕW_å¹çž#::ÚB‰‹‹‹U¦iwwwž{î9Þxã ƒ­?›ËÏÏ7‡¼gdÀÆÐ¯Ÿ­‹$•N§VÓøèQê>òˆ­‹"•ëÒ%óR{µjqáÂêÕ«‡‹‹‹­K%•K¡€+–òÛ¹s'}ûöµu©„jä¶'<ÚÙÙáççGË–-éСmÛ¶%((¨ÊtVÁ¼BHH”–š'{ÿd§º:räJ¥’áÇ—»{íææÆ¸qãØ¿?YYYüùçŸ<ùä“Lš4‰ôôtN:Åý÷ßϦM›óšº£FbõêÕØÙÙ1oÞC”””œœLƒ Ìø¡C«õBó:ŽØØXj×®}Íp¡æÍ›“žžn騥¦¦2qâDæÍ›Ç÷ßÏ!Cøä“O0 ,Y²'''¾ûî;>ýôS¾ûî;´Z-«V­²¯¸¸˜¯¾úйsçòÑG‘””DZZ`Ož7oݺu£[·nDDDðá‡2a„›î°FGGsöìY† ‚‡‡ýúõcïÞ½¤¤¤Ð¸qcfÍšÅÑ£G™0a=zô`êÔ©lÛ¶¼¼<¤{<üU§ÓQXXhÎ(éåe^U4t„(«¸˜ÈÐPäÕ|ÐQ¬ æÎjƒ Î;G›6ml]*A¨\.ÀŠ滬`™Ú%n:·¢Æfh),,D©T¢T*Íá6#GÞýB¤§›G•JKÍË0 jÞþÏ?r9tì-Z˜'¤oÙjµyY’~ýÌ徂\.¿n'M¡P I’å1õë×§_¿~ØÛÛãîîΰaÃØ±ciiiìÞ½›6mÚpþüyΟ?@:u8tèü?ì®_¿~–äµjÕ²z}¹\N÷îݹï¾ûsöرc,Z´ˆ›ZGnß¾}äåå¡Ó騾};2™Œ¼¼<8ÀèÑ£‘Ëå¼ôÒK<üðÃ:tˆsçαk×./^ÌÀùæ›oÌKÝ£ðòòÂÙÙZµ²uqáŽùëÈ ÂÃQŠPI¡&Q«¡W/¨S‡ô´4 iÒ¤‰­K%•kß> …£ÑÈÆ9rä]YÕB¨9jl‡µ  ÀÜÙÒjÍÉ–®1÷òŽR©Ìófu:psûw»¯¯9Å·Löï]ß²eI´Zó¶ÿ„ü* 7nÌÎ;ÿ›ûÇŽ£nݺæ  R©¬:tžžž899‘””Daa!‡âòåË–ýZ­–¶mÛb4®úeär9íÛ·çÁ´l3f ÇçÇä½÷Þ»î[c4ùã?P©T|ôÑG€9™“N§cçÎ :”¤¤$ôz=-Z´`РA 8gŸ}–¿ÿþ›gžy†]»vñÀÜýϵŠHJJ2gâ..67|ÄÚ}BM#Ipñ"Q{÷2ðÑGm]A¨\®®ðä“`gGZZM¯˜ã'5‚ÉЮ`n·$%%ѱcG[—L¨fjl‡U­V£R©= [·ÂìÙw¿îîЭ[ùí-[šÿ]I¥‚®]¯y(™LFçÎùâ‹/ؼy3O<ñ„ÕèTQQË–-£cÇŽ–ᢢ"²²²,‹gggS\\L`` Œ1‚çŸÞrŒ£Gâææf™{«óh”J%ÎÎΨÕê>6::šÈÈHæÏŸOÏž=-Û¿ûî;~üñG Y¶l‡bõêÕ¸¹¹!“Épss£cÇŽZB‡ïU999æA…íÛ!7žzÊÖE„Ê¥Óa˜;—ìÇi;ož­K#•K.·,·i¹V B!—Ã!–?“’’¶,‰(7«ÆÞÏÈÈÀÅÅÙæÍм¹­‹S)BCCyâ‰'øàƒøé§Ÿˆ‰‰!--³gÏ2iÒ$¢¢¢xýõ×qýÿ]Û¸¸8–/_Njj*111|òÉ'´iÓ†Úµksÿý÷óÓO?qäȲ²²Ø¼y3?þ8—.]º©²H’Ä¥K—8pà`ß¾}ÌŸ?Ÿ}ûö1pà@d2’$‘`yLÙ¿¤¤$Ö®]KóæÍéÝ»7uëÖµü;v,jµš?ÿü“aÆÍüù󉋋###ƒK—.±|ùr222,áÈ÷"I’¸|ù2Á¾¾°i\‘IYjŒ¸8bƯG{:ü_¨23aÊs„ pîÜ9ÂÃÃm]*A¨\¹¹æe÷þïï¿ÿ¦ëunÎÂµÔØ!ŽÄÄDó\øxèÔÉÖÅ©r¹œçŸƒÁÀŒ3ðññÁÍÍœœœœœøôÓO­Â,\\\ظq#ëÖ­C­V#IŸ|ò 2™ŒÑ£Gó÷ßóøãS«V-’’’ˆˆˆ gÏžFìíí­îàÊd2ìììÉd–;¯?üð+W®Ìá¼ŽŽŽLž<™#FPRR‚L&ã§Ÿ~²JäðÜsϱk×.ºw¿¿Õ>???ÂÂÂøûï¿yôÑG™:u*Ÿþ9k×®ÅÍÍ µZM~~>3gμéäN5‘F£!..Ž!!uëÚºH‚Pé$IâDXõÄm¡¦ÉÏ7gMýnˆÄÄÄëNÄjG’ÌÉ–BC¡K$I"::Új*™ ܬÛaeüøñÈzÈÖE©T̘1ƒÉ“'sðàAòòò ¼ê|€&Mš°zõjvïÞƒƒæ$T˜“(­Y³†Ã‡“˜˜H›6m¬æÏlÛ¶ÍêXM›6åøñã–¿8pÝrººº²wïÞkîŸ>}úU·{{{óçŸZþ~ñÅyâ‰'8xð 999øûûÓ¾}û*µ|’-”­±ëÛ¶- `ëâ¡oÒ„..Œó„š&?A©ääɓԪU‹úõëÛºT‚PyrsÍIFÿßß¿?µk׉ńÛR#;¬jµšäÄDýýÍ#<5p©úõëwÃǹºº2äŠùÿÕ±cÇ*?ù]¥RÑ»wo[£JÉÊÊÂN’pýšxA¨q´ZôEEá-–³jšfÍ 8ììØ½{7¶.‘ T®Ë—Í+xx`2™øçŸD=n[œÃzâÄ kµx¯Zeî°Þƒ\\\ÄW5Ø©S§MOÇiÍ[EîŒåË)X¶ ½^/:¬BÍãæ>>¨ÕjöíÛ'e…š§m[˜10'[ºpá‚U’MA¸5î«$I;vŒ~:xzÖÈ»«7càÀt»Z†b¡F8ü8c Ìkø BMtö,'\\hÞ¼9.býU¡&ÉÉ“'¡o_’’’ðööƒ2BÍ"I ×[²`Ÿ}:þù''Ož¼¹ÈåDGG³ÿ~ÆwK6‚p78p€C‡1kÖ,.\ÈØ±co©­B³f¨Õ,X°€nݺá%"„ ªRÖcÇŽQ»vmúõë‡B¡ yóætíÚ•]»vÝÔóuÅÅ´.)Á4hª¤ýû÷ÓµkWZ¶l‰B¡ wïÞÔ©S‡ýû÷ßÔóMùù´ €6ml}*‚PŽÉdbß¾} >œ€€\\\3f ÙÙÙÄÄÄÜÔ1¤˜¶?Î+¯¼"tUÒ‘#G¨[·.}úôA¡PвeK:wî|Óm•¢¢",XÀ‹/¾ˆ¿¿¿­OGÊÙ·oÝ»w§yóæ( úöí‹¿¿?¼©çkµZ>øà6lÈÓO?-~Ë… «R5(>>ggg<==P(³ûÿÙô®F’$L&:£É„Çœ9(‚ƒ1 ¶>ë:|ø0ÕêbuòäI|||¨W îîI’„$Ièõz[ÅJLL ]»vµÌåðòòÂÛÛû†y“É„V«''j}öxxTé:^ZZÊáÇéÒ¥ ÿOk_Õét:>L»vípvv¶uqnH’$óïžÑˆTEÖ›6™LÄÅÅhÙˆV«%--íºÏ5 èt:Î ä ޳³s•®ã¹¹¹œ;wŽîݻۺ(7­  €S§Naë¢Ü´²:^•ÄÅÅáêꊇ‡ݰ1_VÇ·mÛ†··7:t¨Òu<%%…ôôôj•ø,==Ë—/Ó¡C[妔ýŽ›L&[ÅJLL ½zõ²\¿½½½ñòò"66öºç¢×ëÑëõ¬Y³†ââbÆW¥ëxjj*ÙÙÙ´nÝÚÖE¹iQQQÈd2šþ?q[Ug2™Ðëõn§T©«V«E.—[Âcär9*•м¼¼ë>/==ŋӪU+ó—+)ÉÖ§rC±±±DEEY.xÕÁ¥K—pss«ëÅ™L&RRRHLLäÁ´uq,4 öööÈÿààà€ƒƒÃuÃ%%I">>ž¹sçÒ A”J%ÄÅÙúT®K§ÓKNNNµY5 ÄÆÆ’ššŠ£££­‹sSå'77·J­¹¬Õj­’k¨T* jµúšÏ)»3{ùòeêׯOþ}Y¿~½­O床‹‹IJJ"77×ÖE¹i%%%$$$Ü|xvp+S‚î–Ûi«°k×. ‘Ëå4kÖŒíÛ·ÛúT®+77—üü|’““m]”›–ŸŸOVVÖ Ȫ FÉ'hÖ¬™­‹R®\ööö–dy(Šëþvèt:V¬XALL ©©©„‡‡³wï^[ŸÊuåææRTTÄ¥K—l]”›–šš ˜;®ÕAnn.çÏŸgàÀ:NµhI^o~‡½½=£G¦¨¨•JeéTuek V§õ«[™5 &“‰€€[冮WoÝÜÜxæ™gÐëõ8::V›:Þ½{÷jSÖ2]»v­6e–$‰°°0ìììðõõµuq®K&“]÷} àå—_F&“U›…åË¢8ªK}©®enÕªUµ@‚ë·U|}}yóÍ7Q*•Õ&ê¤:Ö—êVf“ÉDûöí-‘…UÝõÞ×–-[2iÒ$T*Uµ¨®nõ¥¬Ì@µi‹ëõz"""¨U«V…ŽS¥j”‹‹ F£½^B¡Àh4’ŸŸÝ‡L&Ãßß¿Z…Ö ÷.777´Z-&“ ¹\Nii)¥¥¥]ó9öööV!–‚P•¹ººRZZjù»  ‡ëF“(•J5jdë¢ ÂMqqq!33Óª­RPPpÝ¶Š££cµ á„«µU4 Mš4¹æs\\\Dî˜*5¤Ð¶m[rrrHIIÌa7§OŸ&$$ÄÖE„JÎ… ()) --äädZ¶lië¢ B…Éår¬Â8###qpp nݺ¶.ž TŠvíÚ‘••e ÍÓh4œ9sF´U„#<<œóçÏ[SRRHMMmÁfªT‡5,, ƒÁÀÚµkÉÎÎæï¿ÿæâÅ‹ôíÛ×ÖE„JÑ£GâââØ½{7YYY¬Y³ƒÁ@—.]l]4A¨0;;;z÷îÍž={8uê ¬\¹’F]wd^ª“ððp´Z-ëÖ­#;;›;v@Ÿ>}l]4A¨=zô &&†½{÷ZÚ*&“‰Îb xÁFdRUI/ùGŽáÛo¿%77gggÆŒÃÀ­’xBue0ؼy3+V¬@£ÑP«V-{ì1:uêdë¢ B¥(--eéÒ¥ìÚµ I’ dòäÉÕ"»¸ ܬC‡±xñbòòòpqqaìØ±Üwß}¢­"Ôz½žM›6ñûï¿£Ñhð÷÷çñǯ6Ù—…š§ÊuXÁœQ*55__ß OÒ„ª(99™üü|quuµuq¡RF0 V›¤9‚p+rrrHKKÃÏÏ???[G*h«UE•ì° ‚ ‚ ‚ B•šÃ*‚ ‚ ‚ eD‡UAAA¨’D‡UAAA¨’ìfÏž=ÛÖ…¨î²²²8qâ111ØÙÙáááaÙ'I)))?~œ¼¼<<==±···ì7DEEqöìYôz=ÈåÿŽ#hµZŽ=JBB8;;#“É*­ìÅÅÅìß¿Ÿºuëbggg)szz:Ç';;«Ì‡F£‘¸¸8NŸ>Mii)žžžVeÖëõ;vŒøøxìííqqq©Ô2 w—Éd"))‰ãÇ“€««+NNN–ýF£‘ØØXΜ9ƒF£¹j}8zô(ñññ(Šrõ!77—£G’žžŽ³³3*•ªRËŸ™™ÉéÓ§­²ÔF.]ºÄÉ“'Q«Õx{{[•Ù`0pâÄ ¢££±··ÇÕÕÕªÌ;vŒ””T**•JÔñjL¯×ÏÑ£GÉÌÌÄÓÓËþ²úPö½úàäädõý¸ò››‹———Õ5 2\ºt‰Ë—/ãïïoUæ3gÎpáÂd2®®®Vu¼¸¸˜£G’””„££#NNN–súï5ÀÝÝÝêýªŸ²µbO:…F£ÁÃÃêqìØ1’““oXnµMPNœ8^¯ÇÝÝݲ­´´”£G’˜˜X®}$IYYY;vŒ¬¬,ÜÜÜP*•–çšL&.]ºÄ‰'®z ªŸ‚‚Nœ8Áùóç‘$ɪ=-I™™™?~üªõ¡¢m‚ŠÒét8pOOO«reggsìØ1222pvv¶J`h2™¸|ù2'Nœ   oooK;¾¬ÌgÏžåÂ… ¸¹¹Uë:^¹WÍ{ŒÉdâèÑ£|òÉ'Èård2jµšgžy†Aƒ¡P(صk_ý5öööèõzÚ´iÃĉñòòB¯×³dÉvìØ££#:Ž!C†ððÃcooOff&óæÍ#::¥R‰$I¼üòË•¶–Édbíڵ̟?ŸþùÇr:zô(Ÿ~ú)r¹£ÑHãÆyõÕWñõõàÇdóæÍ8::¢Õjéß¿?&LÀÑÑ‘ÜÜ\,XÀ©S§P©TFž~úi±–n5e0ذaßÿ=...Fìííyùå—-Kñ,]º”­[·ZêÀxôÑGQ*•äää°`ÁNŸ>££#&“‰gŸ}–Þ½{Ç{ï½Gqq1r¹WWWfÏž]iK ”––²páBÎ;gµÖíÊ•+Y½z5J¥NGÏž=yòÉ'qrr¢°°… räÈT*z½ž &0dÈùðÃÉÊÊÂÞÞ…BÁ»ï¾Kpp°­?.á6èõz>ûì38€‹‹ ___¦M›FPP|õÕW;v •J…Á`à±ÇcРA$$$ðÁ››‹ …‚÷Þ{ °gÏ,X€ƒV­ZñÒK/áååU)åOKKã½÷Þ£^½z´iÓµZÍ¢E‹Ø¿¿¥3†Ñ£GæÌŸŸ|ò )))( är9Ó§O§E‹?~œ?þ™L†Éd¢aÆL™2Ed­¦222øðÃILLÄÑÑ‘ââbZ¶lÉÌ™3qrr"))‰O>ù„ÔÔTìíí±··gÆŒ4kÖ ¨X› ¢$I"::š7Þxƒçž{Žúõëæzÿù矃ƒ2™Œ×^{°°0Ο?Ï;ï¼c9F:uxóÍ7-ƒ:¿ÿþ;¿ÿþ»åÁ“O>‰³³³­?.áI’Ĺsçøøã)--ÅÎÎŽââbFŒÁÃ?ŒR©$22’9sæX_¯^=¦Nj©iT”Édb÷îݼýöÛüòË/¸¹¹Ã;#N§C&“áííÍôéÓ©S§7näçŸÆÁÁ­VK—.]xæ™gpss£¤¤Är pttD¯×3jÔ(ÆŽkëëöIÂmËÏÏ—žxâ iòäÉRzzºTXX(-]ºTêÕ«—%effJcÆŒ‘>úè#©°°PЉ‰‘z÷î-ýú믒$IÒ™3g¤.]ºH7n”4´fÍ©k×®Rll¬$I’´xñbé¾ûî“âãã¥ÂÂBiÖ¬YÒ#<"åççWJùÏœ9#õèÑCjÒ¤‰TTT$I’$åääH&LfÍš%åååIñññÒàÁƒ¥ï¾ûN2 RBB‚Ô¹sgé·ß~“4ô×_I]»v•Nœ8!I’$­X±BêÑ£‡%©Õjéã?–†.åææÚúãnC\\œ4dÈiþüùRaa¡”™™)½ñÆÒˆ#¤ÒÒR)>>^êܹ³´råJI£ÑHÛ¶m“ºví*:uJ’$Iúõ×_¥=zH111Rqq±ôá‡J#GŽ”òòò$µZ-½ñÆÒsÏ='¥¥¥I©©©Òã?.½óÎ;Riii¥”Ó¦MR«V­¤Z¶%%%I½zõ’¾ÿþ{I£ÑHºté"íÝ»W’$IÚ¸q£Ô½{wéĉ’F£‘æÏŸ/ 0@ÊÎΖ4ôî»ïJ<òˆ”œœ,effJ/¼ð‚4uêTI­VÛúãnáC‡¤nݺI«V­’ôz½-7Nzë­·$I’¤õë×KÝ»w—N:%•––JóæÍ“ $åääH¥¥¥ÒìÙ³¥Ç{LJNN–222¤çž{Nš6mš¤V«¥ÌÌLiܸqÒ| H111Rß¾}¥åË—K&“©RÊÿÑGI-Z´¦M›fÙ¶k×.©[·nÒ¾}û$F#-Y²DŠˆˆ²²²$½^/}úé§ÒèÑ£¥ÄÄD);;[š,uéÒEÚ½{·­?*á6èõzéÕW_•Æ/%%%I%%%Òï¿ÿ.õîÝ[:pà€”ŸŸ/=ûì³Ò›o¾)eggK Òˆ#¤ Hz½¾Bm‚Ê/ÝÿýR“&M¤¨¨(I’$©¨¨Hš’4”šš* 4HZ°`TRR"={Vêܹ³´eËI’$i÷îÝR·nݤ={öHFZºt©Ô­[7)33ÓÖ×m«¾÷†«µZMzz:?þ8µjÕÂÕÕ•‡zˆ¬¬,²³³‰ŽŽ¦¤¤„Q£FáêêJãÆéÛ·/;wîàÀ´hÑ‚nݺ¡T*éÑ£ÁÁÁìÛ·0Ì8àà`\]]5jùùùDEEU¸ì,X°€=zXm¿téŒ7‚ƒƒ4h»wï¶„,ѧO”J%;v¤eË–ìÙ³€½{÷Ò·o_š4i‚““ÇÇd2qúôi[\ÂmHKKC¡PðÈ#àêꊯ¯/#GŽ$::ƒÁÀhذ!½{÷F©TÒ©S'š7oÎÞ½{sîß¿?7ÆÙÙ™áÇ[Bsrr8sæ ãÆÃßߟ€€Æg áªI’8sæ +W®¤gÏžVûŽ=Н¯/ƒ B©TÒ¶m[ÂÂÂØ½{7ûöí£{÷î„„„ T*:t(*•ŠãÇS\\̱cÇ5juêÔÁ××—‡~˜3gÎ’’bëK¸ QQQ„††2pà@ìííiܸ1ýúõãìÙ³€ù7-""‚–-[âèèȰaÃpppàĉqüøqK}ðóóã‘GáäÉ“¤¥¥CQQ£GÆÍÍÍrì¿ÿþ©‚+Ê™L&vìØAtt4Mš4±Ú·oß>:tè@»víP*• 0ooo<ˆF£áСC<ðÀÔ¯_ooozè!âããIHH !!ÔÔT|ðA<== bðàÁìÙ³­VkëK¸ QQQ :”Ö­[cggg©Ï‘‘‘”––rèÐ!†N½zõðööfüøñÄÄĘ˜Xá6AE ~ýõWœ­Ö5™LìÛ·!C†Ð A<<<;v,éééÄÆÆ’’’BLL ?ü0>>>Ô¯_Ÿx€ýû÷S\\ÌñãÇñòòbÈ!(•JÚ´iCxx8ÿüó­?*á6F.^¼È£>JݺuQ©T >™LFRRIIIÄÇÇ3~üx¼½½ äþûïgß¾}¨Õê µ *ª¤¤„ jµ=33“ÈÈHÆŸŸuêÔaôèÑ>|˜¼¼éééŒ?þšõA£ÑÜT}¸Q›àv¥¥¥ñÙgŸñÐCY5ÚË”””X•ÉÅŽ^Oqq1z½NWî{YPP€Á` ´´¹\nÉÛQ–?¡¢ßKÁ6ìììèÑ£FNŸ>Ík¯½F«V­èÒ¥‹¥>ü·çççc0*Ô&¨ˆƒ²lÙ2^{í5¼½½­ö †«ÖáÂÂBt:™Lf©Ã2™ 777«2ÿ÷àèèX­ÖEÒ¥ ’$‰ììl–-[ÆŽ;h×®“&MÂÅÅå¶y'³fgg³téR~øaêÔ©CFF`þrT¤1"2¤Ö\’$Ïwß}Ç©S§;v,cÆŒ±ÊF÷_¶¬§NbÆ |þù縹¹YêµÁ`¨Öò„;Çh4râÄ ¾þúkòòòxã7®Ú¬ ŒF#[¶l!++‹)S¦æï¨ÉdÂ`0\÷{y#2™¬Âw~…ªG’$ŒF#ëׯgÕªU¨T*fÍšE:u®;ý¢"¿ãy®^¯gÙ²eÔ«WîÝ»c4,u\ÔQá¿$IB­V³lÙ2þüóO‚ƒƒ™ËkÕ'''\]]‘$©Bm‚ÛÃŽ;ðõõåÕW_µœÃ/¿üBbb"O?ý4NNNVe...F©TZ–Üqpp°Š~(((ÀÇÇ…BJ¥Âd2¡×ëQ(–ÈµŠ”Y°I’¸té|ðr¹œiÓ¦Y 8–Õ‡ÿÖá²úP‘6Áí:pàQQQH’ıcÇ,uyΜ9 8fÍšYêpY{¨  ///qttD’$K–$éªý‹+¯¦Z¯f n7T@~~>óçϧU«VÌ™3Ç’¾LPP …‚‹/Z¶8qÂ2ï"44”¤¤$Ë|½üü|«¹$mÛ¶%22ÒòÜØØX$I²ê0ܪvíÚñüóÏÓ»wo""",½»víJPPuëÖÅÝݘ˜ËsNž>>Ô©SOOO¢££­Ê\v=ªŸ5kÖûï¾Ë°aìiÞ¼¹U}8{ö¬eN_EÛ·£V­Z<÷Üs 0ÀRÇ•J%Mš4¡mÛ¶(•JZ·nmU樨(ìííñ÷÷§V­Z”û^–Íé ¡  Àr ÐëõDFFV¨Ì‚í .\ˆ³³3|ð;v´Ú_V'þ[ÊæùW¤Mp»5jÄĉéÛ·/–vûöíiÒ¤‰%YØÛGµkׯÙÙ™fÍš¡ÓéHNNÌöS§NYõ/âãã-S•233III¹jx}u!î°V@ZZ‡¢aƬ^½Új߀hÞ¼9>>>¬Y³†§žzŠ´´4öîÝË+¯¼@=X¶l»wï¦gÏžìܹ“ÔÔTËš¥ýúõã§Ÿ~bÈ!xzz²zõjüýýiݺõm—¹Y³fVëãÇóÓO?1nÜ8\\\(..&88˜ßÿ___²³³Ù±c‡e-«nݺñÕW_±}ûv†Êþýû‰çÍ7ß OŸ>Ì;—ÈÈHX»v-NNN„‡‡ÛúãnQÙ`bb"ÅÅÅüòË/Vû}ôQºwï΢E‹øë¯¿4h{÷îåâÅ‹¼ýöÛ€¹>|ñÅDFFâççÇÚµkquu¥}ûöÈd2:uêÄš5khÚ´)z½žÕ«WÓ£GK"Ûѽ{wºwïnù[§ÓqéÒ%yäÀÜ@[¸p!›7ofìØ±œ§N"88˜uëÖ!—ËéÒ¥ ööötíÚ• 6Xÿ~ýõW:wîL½zõðññ¡V­ZüñÇ<óÌ3¤§§³gÏ&NœxÛV•JÅ€¬¶=zÆŒ@¯^½xóÍ79|ø0mÚ´aóæÍÓ«W/”J%={öäÏ?ÿ¤k×®(•JV®\IHH7F§ÓѸqcV®\‰¯¯/¹¹¹üõ×_Œ7®RÖÕî.­V˶mÛpqqa÷îÝVÙ{›4iB—.]ˆˆˆ`ëÖ­tîÜV®\IëÖ­iذ!:®Bm‚ÛáããÈ#¬¶-Y²„Ž;rß}÷!I}ûöeÍš5ôë×V­ZEPP-Z´Àh4ÊŠ+ð÷÷§°°-[¶0`ÀÜÜÜgáÂ…lÚ´‰|Ó§OÉ“O>iëK¸ ÅÅÅìܹ“Aƒ±nÝ:«}ݺu£~ýú„„„XêCAA[·neÈ!¸ººÒ±cÇÛnÜ®úõëóðÃ[þNOOçË/¿dÈ!4mÚFCxx8¿ÿþ; 4 ´´”uëÖÑ«W/¼½½ ÅÞÞžõë×óè£ϱcÇøàƒó5`Ë–-:tˆvíÚ±uëVòóóéÝ»·­?®Û&“Äd€ÛvàÀÞÿý«î›3gíÚµãÔ©S|úé§–ð“Î;óÌ3ÏàêêŠÑhdÕªU¬Y³Æ2â9jÔ(xàììì(,,äë¯¿æØ±cØÛÛãèèÈäÉ“Ëe=­ˆóçÏóú믳jÕ*K¦˜˜æÌ™c WnÓ¦ 'N´d‚]·n¿ýövvvF† ÆèÑ£qpp@­VóÝwß±wï^ìííqppàù矷$ÉÄÏ?ÿ̪U«®º¿l.ÔºuëX±b…¥><ðÀŒ5 …BAqq±¥>( ”J%/¼ð‚e433“Ù³g[ÔªU‹3fàççWiç±fÍþúë/-ZdÙ¶mÛ6~øáär9ƒòàƒâèèHii)?þø#;wîD¡P`ooÏO[¡(‚ÿúðÃQ©T–ÁP­VË/¿üÂÖ­[±··G.—óðÃ3pà@À^ùÙgŸcI02}útK&ظ¸8ÞyçË5 U«V¼ôÒK–k€P}dggóæ›o’––Vn_¿~ýxå•WÈÍÍåÓO?%..Î’€húôé4hШX› ²L˜0|Ð2XSPPÀüùó9sæ vvv8;;óúë¯[¦e¥¤¤0mÚ4Kâ³ÆóÚk¯Y"aþúë/¾ÿþ{är9z½žòÐC‰A™j(>>ž—^zéªû&MšÄ€¸|ù2Ó§O·Ô‡¦M›òꫯZêCEÚ•!;;› &ðÕW_Y~‡ÓÓÓ™>}:EEEH’D½zõ˜6mš%›ñÞ½{ùúë¯s”@ß¾}yôÑGqrrB§ÓñË/¿°eËË5ࡇbðàÁ¶þ¸n›è°Þ¹¹¹ÄÇÇãééIppp¹Ä/—/_&55•àààr u“ÉÄ… Ðh44kÖ̲ôÂVPP@\\®®®VK:”IMMåòåËÔ¯_ÿª õ .PTTDóæÍ­ÖOj¦””’’’ ¼ê< óçÏ£V«iÞ¼y¹¹ž%%%ÄÄÄXÖÀ¼2“ß”‘‘Á¥K—¨S§N¹eAÀÜHËÍÍ¥E‹å:Æ"פIÑȹDGG“ŸŸO‹-Êý¦i4¢££‘ÉdW­yyyÄÇÇ[Ö±¼[É¿âããÉÊÊ¢iÓ¦VKS9ò ::£ÑHÓ¦MËÍ¿òpå’BͤÓé,sêš4irÝúp;m‚;¡lYNG³fÍÊ­zPTTDll,NNN4lذ\H{ff&/^¼æ5@¨Y ‰‹‹ÃÉɉF•ûM«H›àNQ«ÕÄÄÄ T*iÔ¨Q¹A ¬¬,.]º„ŸŸŸe€éJ×»T7¢Ã*‚ ‚ ‚ TI"é’ ‚ ‚ ‚P%‰« ‚ ‚ ‚P%‰« ‚ ‚ ‚P%‰« ‚ ‚ ‚P%‰« ‚ ‚ ‚P%‰« ‚ ‚ ‚P%‰« ‚ ‚ ‚P%‰« ‚ ‚ ‚P%‰« ‚ ‚ ‚P%‰« ‚ ‚ ‚P%‰« ‚ ‚ ‚P%‰« ‚ ‚ ‚P%‰« wÝ¥K—8þ¼­‹!wÝÁƒÉÍÍ­ÔcŠï“ ‚P“‰kôé§Ÿcëb³zõj-ZdëbÂ]÷ꫯræÌ™J=æªU«øæ›ol}j‚ ‚pGˆkôý÷ß“`ëbÂSZZJqq±­‹!w]^^:®RYRR"¾O‚ BeoëæÆ{QQööö¸ººZí“$‰¢¢"JKKqvvF©Tb2™ppp@&“!IÅÅŨÕjpwwÇÎÎÀÒ(2âàà€››ƒÂÂB$IÂËË {{{t:2™ ½^Oaa!ŽŽŽ¸¹¹¡Óé(**B’$¼½½-Ç„[qþüy¶oßÎåË—éÑ£Z­Ö²¯  €þù‡={öàääD¿~ýèܹ3ÅÅÅœ:uŠV­Záãã@VV'Nœ ""‚””²³³ÑjµlذOOOFŽIii)[¶l!;;›‘#GÒ¥Kbcc)**¢  €Í›7ãïïÏðáÃÉËËãÏ?ÿ¤  €±cÇÒ¾}{är1Ž'TŽÒÒRvïÞÍÎ;ñññaÈ!H’˜;®;vìàÀxzzÒ¯_?ÂÃÃ)((àÌ™3„††âéé @ZZçΣ[·n$$$PZZJii)«W¯æÃ?´zM“ÉDll,IIItëÖ GGG[¿ B wèÐ!öìÙÃÔ©SÑét¨ÕjÜÜÜD{A¨‘¦L™ÂĉñóóÃd2•k· w†h™ÙXBBS§N¥ÿþŒ1‚ŸþƒÁ`ÙáÂ&L˜@Ÿ>}xæ™gøå—_øâ‹/Ðh4ìÙ³‡§Ÿ~šž={2jÔ(~øáJKKX±bK—.åÕW_¥OŸ>Œ3†uëÖñÞ{ï1xð`î»ï>¾ýö[ ?üð?ýô“&M¢oß¾Œ;–72{ölÈ€øùçŸ1¶~Ë„j&22’û￟õë×£P(X°`üñ‡eÿgŸ}ÆÛo¿B¡ %%…G}”þùƒÁÀ믿Î_ýeyìúõëyõÕW‘Ëå¬]»–qãÆñå—_âääÄÚµk;v,o¿ý6ùùùÄÅÅ1~üxâããùå—_7n‹/ÆÅÅ…eË–1nÜ8Þy犋‹9þ<>ú¨ˆl*^¯ç³Ï>ãé§Ÿ¦¸¸˜ØØX&MšDQQ3gÎäÃ?ÄÑÑ‘èèhÆÏñãÇÑëõ¼øâ‹8p0w@ýõWfÍš…Ë–-ãùçŸgÚ´i$''[½¦$I;vŒÇœ3gÎ “Élý6÷€øøx6mÚÀ‘#GxöÙgÉÉɱu±áŽøõ×_IKKcÉ’%¼ÿþû¶.Î=CÜaµ¡’’&NœH~~>sçÎE«Õ²`Á HIIaòäÉÔ«W·ß~›={ö0sæL5jÄóÏ?Ozz:'N¤OŸ>¬_¿ž={öðÁàèèÈÃ?ÌÁƒY¿~=}ô“&Mâ­·Þâ…^àùçŸçÛo¿eݺu|óÍ7DDD°gÏöìÙÃܹsy饗xóÍ7yñÅyþùçY²d +W®äË/¿¤K—.4mÚÔÖoPM .\HÓ¦MY´hµk×&&&†áÇ[³lÙ2^|ñE^}õUJJJøâ‹/ÈÍÍÅ××—Î;³uëVxàT*«W¯føðá888àêêÊ{ï½G³fÍgذa,X°€®]»rîÜ9{ì1bccpwwçã?¦Aƒ4mÚ”G}”#GŽÊÉ“'yê©§HHH 88ØÖo›PdggóÕW_ñþûïóÈ#`2™X²d }ô?ÿü3sçÎå‰'ž ///¿ü’¬¬,:vìH»víØ¼y3 À`0°nÝ:FމB¡ 99™5kÖмysËw¡¬³úâ‹/òÐCñüóÏ£T*mý65Á` 77—¢¢"<<<,Ûõz=ÉÉÉ9r„ÜÜ\¼¼¼Ëå”””àèèH^^&“ L&&“‰ŒŒ ðóóC’$233Ñëõøûûãää„Éd¢´´…BAaa!ùùùxxxàããC^^¹¹¹¨T*üýýEtŒpG““ƒJ¥²D{i4Ο?OJJ jµ•J…ÉdB«Õ¢T*IIIÁÛÛôz=YYY”––âêêŠr¹œÒÒRËsrrpvvÆ××—ÒÒR²³³¨[·.öö¢«¢ÃjS >|˜Õ«W€L&ã™gžàÔ©SÄÇÇóÛo¿áååEhh(û÷ï'//€_~ùfÍš…§§'ÁÁÁÄÄİ|ùr~øaÂÃÃ7n 6ŒðòË/ãéé‰B¡`Æ –¹O]»ve̘1Üwß}DGG3qâDÜÝÝ‘Édlݺ•’’[¿mB5’žžÎ©S§xì±Ç¨W¯AAAtïÞÝIиqcV®\‰»»;mÚ´á7Þ°4ÂÌ‹/¾ˆZ­&++‹ØØXfΜi9~Æ ÀÍÍ €°°0ìììðööÆÙÙقٴiS|}}-•Éd„……àççg¹àBe8|ø0^^^ôêÕËÒq6lóçÏÌõþ§Ÿ~B&“Ѷm[¦OŸné<˜Y³fa4¹xñ")))ôë×Ïrì°°0Z´h‹‹‹eÛÙ³gyöÙg)**âþûï¡ÀÂóÛo¿ñÃ?œœLpp0:uàäÉ“,Y²„ììlæÌ™ÃŒ3pwwç“O>!""‚ï¾ûŽ6mÚΙ3gÈÊÊbÇŽ¸ººòÔSO‘””ÄÖ­[)**bðàÁ|ôÑG¨Õj>ùäÙ¸q#ÑÑÑ4iÒ„^xeË–qêÔ)|||˜>}:÷ÝwŸè´ •*22’÷Þ{ÏRÏüqþøãvîÜIii)|ðo¼ñ111¬Y³†Æ3oÞ<>ÿüsºuëÆ7ß|ÃÊ•+ÉÎΦnݺL:•²páB”J%{÷îåÔ©Sð /°gÏvïÞ ÀK/½ÄOÿüsôz½­ß¡Ú°a³gϦW¯^lß¾ñãdzpáBÚ´iÃc=†··7o¼ñÁÁÁ±cÇæÏŸÏ AƒxôÑG‰ŽŽfþüù´jÕŠÝ»wÁK/½„$I¬ZµŠ7Þxƒõë×sèÐ!4 »víbåÊ•¼óÎ;üþû拉¥ñÆo0nÜ8¶mÛFýúõY°`%Ü^*CFFO=õƒU«V1gÎV¬XÀý÷ßOÏž=iÓ¦ ¯½ö...¤¥¥ñý÷ß³aÃÞyçBCCÙ¹s' .dæÌ™üõ×_têÔ‰ùó瓜œÌ¡C‡˜;w.Ï>û,Û·oÇÝÝW^y…-Z°yófFÍ¢E‹¸xñ¢­ßŠ*AtÙmÈÎι\nÕ¼²qc0Ê5°Ëk2™0Ó½{wËþîÝ»[…èÜJ]tH…Êæáá···Õ\»ÒÒR.]º„ƒƒÅÅÅœ9s†±cÇòÄOpéÒ%>ÿüs>úè#ˆ¯¯/;vdåÊ•”””0dÈËTA¨Ê5jDnn®UTJll,z½ž¢¢""##yâ‰'xöÙg‰‹‹ã£>bÞ¼yôèуºuëÊòå˹|ù2O<ñÎÎÎ×}½ˆˆ~øa”J%ï¿ÿ>G¥K—.¶~„D«Õ²}ûvZ·nÍk¯½†J¥¢AƒlذŒŒ ”J¥%Ù’§§§%R`èС<÷Üs–6IëÖ­1b>>> 0€Ï>ûŒ‰'âïïÀ’%KP«Õ–ç=šöíÛæÁu…BÁ AƒP*• 8ï¾ûNDÈ•êüùó$&&²téRZ´h˜ÃƒŸþyœQ©T888Xn8;;3qâDz÷îL7FC»ví¨U«¯¾ú*111–DM½zõ¢OŸ>€9Ê166– &àââ°aÃX½zµU’Ê{™¸Ý`Cááá$%%YæØ™L&¶oßnià„‡‡“™™IVV`Îú[¶8¼ƒƒ¡¡¡Œ9’Ç{ŒñãÇ£ÕjIIIÙù„*¡,3ê?þȶmÛHMMeÆ üõ×_Èd2´Z-“&MbéÒ¥¨Õj<<<¬îš*•J†Ê®]»8~ü8cÇŽµõ) ÂMi×®nnn|ùå—ÄÇÇÍ'Ÿ|‚^¯G£Ñðä“O²bÅ JKK-û²z¯R©1b«W¯æâÅ‹<ðÀ7|=¥R‰R©d̘1tïÞéÓ§[æA Be(..æÜ¹s„……Y"ÁÀÜ辑.]ºX  ” [/kø+Šrm˜   «¿U*•%Ô^„¿ w‘#Ghذ¡UDXÏž=¯û7nl¹AXX]ºtaøðáüðø¹¹Y¦sü7g†B¡°ì‘ÖÄVª_¿>]ºtaΜ9c0X°`NNN´mÛ–€€¦OŸÎèÑ£9qâ'Nœ Y³fÈd2ÆŒ÷ß~ËìÙ³5jgΜá£>âã?¶õ© `¾kÿøãóÏ?ÿ0qâDÐét 2www¼½½yüñÇYºt)Û¶mÃ`0 Óé¬êpçÎqww',,ÌæA›+Ðíììpqq±ü-—ËQ©TØÛÛ£T*­ûß%¤d2NNNbžˆPiœyÿý÷yýõ×9vìr¹œ   Z·nM@@&L`þüùV#èeó[ÁÜ ppp OŸ>åBêÿÛ@/«ßeû'MšÄC=Ä_ýŃ>hë·B¨!är9J¥Ò’ ÌͬPÑN¥h¸ w›J¥B’$«ú~£»øööö–v„$I³`Á.\¸ÀáÇٰa6l`Ñ¢E¶>½jG´ÎlH¥Rñõ×_óá‡2gμ¼¼xâ‰'(..¦nݺԯ_ŸÅ‹3kÖ,¦M›F=:t(ÅÅÅØÛÛÄ?üÀÂ… yá…ðññáý÷ß·ŒÆwïÞ…Baù¡/ËŒZÆÝÝ‘#GâççGŸ>},ÙÏZµjŸqã,{xx0jÔ(«ÇÂÍðôôä÷ßçäÉ“äççnUf̘Á“O>ÉáÇñðð <<Ü*™ŒÁ`ÀÓÓ“|ÐjÔý¥—^²znݺYÍa `ûöí€9‰Ø•hI^P¯^=vîÜië·J¨Aär9C† !<<œ£GâççGÛ¶m-Ó>z÷îͤI“8qâ>>>´k×Î*ìW§Óáëë[®Ã9kÖ¬r¯5mÚ4«¿[µjÅÙ³gmý5Œ‹‹ ­[·fïÞ½àîîŽ^¯gýúõ¶.š Tº:ðþûïsñâE|||0™L¬Y³æ¦Ÿo2™øñÇ‰ŠŠâ³Ï>£ÿþL™2…&Mšpúôi[Ÿ^µ#:¬6V»vm>þøc²²²,)³ËÂfâââøí·ßøòË/Ñét¸¸¸ðä“OÒ¢E K£'""‚ÐÐPrssqqq±dAx衇¬^«k×®tíÚÕò·¯¯/o½õP>,¡OŸ>–¸z0‡9LŸ>ÝÖo—PM9::Ò¹sçkî¯]»¶ÕR7e._¾Ìo¿ý†““:t£ìBµS«V-† rÕ}–Û~éÒ%~úé'êÕ«G«V­l} ‚˜ÃGŽÉ–-[xíµ×4h‡¶ZL¡P Ñhˆ·šÛ'ÕMÓ¦MéÖ­o¾ù&?þ8………üòË/x{{#“Éppp //øøxêׯ_îùe üñ4hЀ£GâííM£Fl}zÕŽÝìÙ³gÛº÷:…B‡‡ÎÎÎV ò’’-ZÄ¡C‡0üöÛoœ={–©S§R·n]Ëãñôô¼aRA¨nfÏžÍæÍ›™2eŠÕ`‹ ÔdS¦Laß¾}¼ýöÛ´k×ÎÖÅ‹ºuëÒ¤IöìÙÃßÿ››o½õ–%ÜÝÓÓ“³gϲwï^K4B¡ cÇŽ–iF£‘ºuë‚’$áììLŸ>}ËåH’„mÛ¶ÅÛÛ¹\NXXÞÞÞ€9ê¦yóæ–D8F£///¬W BE¨T*K"¤M›6‘››Ë‹/¾HëÖ­i×®µk×fÿþýÄÆÆÒ£GK[¾]»v(•Jd2 6ÄÃÃM›6ñ÷ßc2™˜9s&]»vE¯×Ó¢E Ëül£ÑHíÚµ-ËDI’„B¡ C‡VQg÷*™ôßÉwXQQÿüóÇÇh4Ò½{wºvíjélåääð÷ßsæÌ4hÐ=» ´$I$%%±|ùrRSS©U«ƒ "44T$UªÂ ÑÑÑlß¾””Z´hAïÞ½iР&“‰´´46lØ@zz:mÚ´¡gÏžVs3…egg£ÓéðóóóK«FñcÇ,¡mÛ¶¥ÿþxzzb0ˆeÆ F:tè@×®]­’´×—™™‰ÑhÄÏÏOüÖÛHQQ»víâĉ˜L&ºwïN—.],m•ììlvîÜIdd$ 4`àÀ÷L[Åd2QTT„V«ÅÕÕÕê»-I………èt:<==Åïv–ššÊž={8yò$îîî 0€0™L–$‰„††qO¶UJKK)**ÂÑÑËwÜh4’——‡½½=nnn×üî›L&òóó1 8;;ãää$¢ÅnÃ]½ÃªÑhX´h?þø#-Z´ÀÞÞžŸ~ú Ngé„Íœ9“Ý»wÓ¦MŽ?Î?ÿücu‘¸—Èd2ÜÝÝéÞ½;ƒ """‚ÚµkßÄêìØ±c¼üò˸¸¸Ð¸qc¶oßÎÎ;éÚµ+:Ž)S¦MÆ Y·nñññôîÝÛÖÅ®’œœœpuuu¾ 1¬[·Ž÷ߟúõëãëë˪U«¸téaaaÄÆÆ2mÚ4œqqqaùòå8::ŠÐÖ[àìì,ê½ i4.\ÈO?ýDË–-‘ËåüøãFÚ´iƒo¿ý6ûöí£uëÖ9r„={öÐ¥KKÒÄšL&“áè舳³s¹;šWîõ·ê***bÊ”)9r„öíÛ“••ÅâÅ‹©[·.7&++‹)S¦››KÆ Y³f 7•º¦Q(8;;[îš–‘Ëå899Ý0›¯L&C¥Ráì쌃ƒƒè¬Þ.é.:þ¼Ô¿iûöí’^¯—ôz½´iÓ&©S§NRzzºtäÈ©_¿~Ò$£Ñ(¥§§Kýúõ“V¬Xq7‹)2uêTé…^ŠŠŠ$“É$%%%I£F’¾ýö[é矖† &¥¤¤HF£QÚ·oŸÔ½{w)22ÒÖÅ„›’ŸŸ/=ZZ°`¤Õj%ƒÁ EEEI:u’víÚ%½þúëÒ /¼ •––Jz½^úù知‘#GJIII¶.º Ü”ÈÈH©ÿþÒŽ;$½^/ét:iÆ R§N¤ÌÌLéðáÃRß¾}¥C‡IF£QJMM•úõë'­ZµÊÖE„›òçŸJƒ–N:%F©¤¤DúðÃ¥‘#GJ’$I?üðƒtÿý÷Kiii’Ñh”öìÙ#õèÑC:w‹.Ü£îêðWII îîîôèÑÃ’ú¹Y³f–[åQQQÔªU‹æÍ›#—Ëñôô$,,Œ'Nغ_/7M­VÓ¿ËœäºuëâêêJ^^‘‘‘´mÛÖ’\«I“&Ô­[WdŒª²%,úö틃ƒvvv4mÚNGqq1çÏŸ'""GGGìííéÔ©%%%$&&Úºè‚pSJJJðôô¤[·nØÛÛ£P(hÚ´)ùùùF.\¸@íÚµiÚ´)r¹///Ú¶m+Ú*Bµ‘——GHH-Z´°,×°aCËÚÍ‘‘‘´k×///är9M›6¥víÚœ9sÆÖEîQwurAÛ¶mY¾|9€9.|Û¶m4mÚ•JÅÅ‹qvv¶¬9§P(hÒ¤ k×®½æ1%I"++‹’’‚"XH’„F£Á`0P«V­»:nÞ¼yÈård2’$qâÄ 2331bßÿ=ýû÷·„QùøøàççGTTÔ5g4IKKÃd2¡R©Ds/))A&“áïï×’xzz²|ùrËëéõzvíÚ…§§'þþþÄÆÆZ%…kذ!:ŽÔÔÔkS¯×“œœŒ½½=*•J„L ………(•Jj×®}×^3,,ŒŸþ¹\[¥Y³f8::‹‹‹¥­âàà@ãÆÙ¼yó5©ÓéHJJB¥R¡T*mû¦ UFÙ|`»:?t¹<õ߀IDATôèÑŒ5Ê2Ç8//þù‡¶mÛÃ!C,¿ó¾¾¾øøø}Íc“™™‰³³³˜»,XèõzJKKñõõ­Pò¨»Z£är¹e2wnn.‹-bïÞ½L™2wwwËâ¼e™L†L&³,ª~5ƒU«VGË–--˜ª.55ww÷j577##•J…›››­‹rC&“‰ääd233yä‘G¿k¯]ö¯ÑhØ»w/_|ñ!!!ôêÕ‹ï¾û¸µ:^PPÀâÅ‹1 U‹ÆŽÁ` 55•:uêT›¤1F£‘ÔÔÔ»Úù«ƒÁ@||<†)S¦Üµ}Y:I’P«Õüúë¯üúë¯L˜0¦M›ZSF.—c4Ñëõ×^ýu\]]o«­’žžÎ{ï½G³fͰí›z“ŠŠŠP«ÕøûûÛº(7M­VSPPpW8*B£ÑpúôiÚµkÇ“O>y×^·ìºl4‰‰‰áÛo¿%55•9sæÜVŠŠâ»ï¾£eË––Áœª®¸¸˜’’üüül]”›–““ƒL&«6 °rss‰eøðáôíÛ÷¶sׇ@t:¿ýö¿ÿþ;Í›7çóÏ?'$$äºÏ¹^½ìîÂðáëÍÀ¡C‡hРAµº”-p_;»wï¾ë&“ÉDLL ü1ùùù<ýôÓôïßÿºÉ8nTǃƒƒyì±ÇîêyTDii)‡¢k×®ÕfI«ÕrøðaÚµkWmRÈëõzÖ¯_×;xF£‘þù‡… âííͬY³èÑ£ƒáª·³³»î €\.§gÏžŒ9ò®žGEäææI=l]”›–ŸŸÏÉ“'«Uâ”!C†°qãÆ»þºZ­ÖÒViÙ²%_|ñ…e•k¹Þ︇‡ýúõ+·>zU–œœLzz:íÛ··uQnZZZ‰‰‰–¥AªƒÄÄDŽ?~×_7;;›Ÿþ™?ÿü“ˆˆÞzë­vÜ®WÇíííyüñÇ騱ã]?—Û•’’Bvv6mÚ´±uQnZYD^³fÍl]”›vòäI *tŒ»ÚaÕjµ–/Ç /¼@=,ërøùùqùòeJJJprr²Ü¥©N#Ø7+,,¬ZÜE¸R«V­ª]™máÌ™3¼÷Þ{têÔ‰‘#GZÖØ °°ƒÁ€½½=äççW«ž›áèèH×®]«ÅÊ2têÔI„2Ý€ÑhdëÖ­,]º”aÆ1xð`|}}óàJ­ZµÈÍ͵<>-- {{ûj3|³<<<ªU£ÀÍÍM¬g|´Z-?üð;vì`âĉôèÑÃj«V­Z¤¥¥YÚ*z½¾F¶U¨U«–­‹qKüüüðññ±u1ª¼ââb>üðCrrrøä“OhÞ¼¹Ugô¿m•üü| iݺµ­‹^©üýý«ÕÝU€FÙº6qW{QQQüúë¯Ì˜1ƒÁƒ[uVÂÃÃÉÈÈ !!0‡J=z´ZÖÜ,…BQmB%«s™mañâÅ4mÚ”W^yŪ³ йsgN:…Z­Ì#Ø—/_¦C‡¶.v¥* ­NsËÊ,e®¯°°E‹1zôh{ì1KgÌwJ;vìÈþýû-ÛNž}z¹¶Ê÷ßO›6m`Ñ¢EŒ3†½{÷bggG÷îÝm]tA¸!NÇéÓ§IHH`âĉVËÞÞÞ,]º”ž={²qãF¾ûî;ÂÃÃùõ×_ ¦eË–¶.¾pº«Ö† òÊ+¯\u_Yæ¼3f°|ùr-ZDƒ ˜={vµš3)ÜÛd2O<ñ¦Ü¾fÍšQ¯^=f͚ŲeËøöÛo cĈ÷äh™P=¹¸¸\ów< €ÀÀ@t:üñ:޾}û2fÌ!T5âå—_¾ê>GGG”J%3gδ´U‚‚‚˜={¶UvlA¨ÊºuëvÕ¼/e‰@™9s&Ë–-ãĉ´oß^´U›º«5/,,Œ°°°ë>¦~ýú¼öÚkh4ptt´é$·ÂÝÝ &\÷1mÚ´¡I“&èõzT*Uµ Gîmõë×çÙgŸ½îcúöíK—.]0™L899‰ÎªP­´oßþ†‰†yýõ×Ñh4(•Êj‘½]Àœ¯¡_¿~×}Œ\.'44”¦M›¢×ëqrrUÁ¦ªdísppól„M¥RÝÕµaán’ÉdÕjÉ.A¸¢­"Ôt¢­"T"»ˆ ‚ ‚ ‚P%‰« ‚ ‚ ‚P%‰« ‚ ‚ ‚P%‰« ‚ ‚ ‚P%‰« ‚ ‚ ‚P%‰« ‚ ‚ ‚P%‰« ‚ ‚ ‚P%‰« ‚ ‚ ‚P%‰« ‚ ‚ ‚P%ÙÛºBÕd4ùí·ßØ´i/¿ü2íÛ·G¡PغX‚P)ÒÒÒHNNæôéÓØÙÙѼysêÖ­Kݺum]4AAá ¢ÃZ\ºt‰Í›7ãââ‚££#îîî´oß__ßÛ>ftt4k×®åÁdÞ¼ytïÞçž{NtZ…*I§Ó‘’’Bݺu¯ZGu:‡bß¾}\¼x‘‚‚j×®MHH’$±fÍRRR˜6m!!!¶>AAáÿ*­Ãš——‡nnn¶>§{BTTGe×®]3xð`”J%z½žcÇŽ±dÉ1ÔªU‹ÂÂB$I" WWWŠ‹‹ÉÏÏ'/////T*­[·fäÈ‘˜L&>úè#ž~úi @Ÿ>}xýõ×Ù¾};ƒ®pÙSSSqqquE¸.£ÑÈùóçIHH 11‘ØØXt:éééÈårêÕ«GÇŽILLäĉH’„5bäÈ‘´mÛÖr¬œœ¾ýö[† Âøñã©W¯r¹õŒˆM›6ñÓO?ñî»ï¢R©l}úådggsàÀBBB ÄÎÎÎÖEAA¸ã*Ôa5 ìß¿Ÿ-[¶˜˜HÇŽãâÅ‹Üÿý„……¡R©0™LFìíí‘ÉdF233ÉÎÎàòåËYŽOjj*íÚµãÅ_¤I“&¸ººZ½–F£!;;›ââb¼½½ÈÌÌ$77—¢¢"<==qww·4Ú‹‹‹ùã?˜|8'OždРAúLF#S¦LaìØ±Üÿýw¤~èõzt: …I’îì‡*XÑétÄÆÆRZZJÆ ±··ÇÎÎ;;;är9z½ÞòX™L†L&Ãd2Y¶•} øöÛo‰ŠŠ¢E‹4iÒ„ÐÐPjÕª…§§'z½ž˜˜øà«»L]ºtá»ï¾#??OOÏÛ~8@ZZÛ·ogÈ!ØÛWnTº^¯gáÂ…?~\\\xà*õ5„«+))aÉ’%?~WWWòóóQ©T8;;#—Ëñôô$)) wwwìííÉËËÃÉɉââb\]]1™L(•J´Z-yyy´oßžE‹áâârÕ× ° ª”©_¿>Ý»wç›o¾)W6{{{¯Y~wwwÆÇÒ¥K A©TÚú-µ(..fçμ÷Þ{'%‘ôË/|þÎ;ä{zâ_·.;w¶uAîIûöíC§Óѯ_?[Ej¬Ûî-äåå±fÍÆÏ£>ÊO?ýD||$&&²|ùr~øaJKK9zô([·nå7ÞÀÉɉyóæñú믘i·ÓénÌh4ŪU«HNN¦uëÖ<ùä“8;;àâârÍ»£w’§§'………¨ÕjKYŠésô(²‚øˆüÕ8::òÈ#°}Áº›L(:u‚À@JJJ˜={6cÆŒaêÔ©W}îåË—1–«s©©©|òÉ'4nܘ_|Ѳ}ß¾}üöÛoH’„^¯G&“1oÞ<«ßTÃѣȦNåÁßǾ¤\]¡{wÿù‡f„„„ˆF’p]F£‘•+W²fÍó¢Á`@’$† ÂèÑ£ËÕ[£ÑÈ·ß~KRÒÿØ;ïð¨Ê¦ß»é½FIЄЛt¤ˆ *6DÑWÅ‚ ˆˆåU_+ è§"¢b§ *JU¤CB THï½gÛ÷Çc–,)¤²IxîëÊ9»{2g÷ì93ÏÌü&‘O?ý´Á1%%%<ÿüódeeñÛo¿ûm™ÂÂB233qppз*5'©©©¥RÉÌ™3ùî»ïxá…èÖ­ 8ÐØïf»F¥RÉÆIKKcÆŒ<ôÐCtìØ±U¨H[YYáííMll,}ûö 0- /GG¨Ç÷¯W¯^ü¦Õ’xûíøÝ~;˜›“ýÃuêÄñãÇÉÊʪæØÄÅÅñ /èKù§M›¦Ï”†‡‡óõ×_3vìX"""øê«¯˜={6111|þùç,X°€ž={baaÁŠ+øå—_¸ï¾ûÄŽóò¸djJDß¾Œß»FŒ€^? Aê´kt:eeeäääPTT¤¯Ê±µµÅÑѱÆ9•J…Z­ÆÒÒ…BÁÁƒùõ×_ùøã±··§¨¨ˆòòrt:©©©¼ÿþûѽ{wƒý“••Eaa!ûöícÒ¤IõÖ(++ãÓO?¥gÏž„††réÒ¥:+j$í—œœ8ÀO?ýDYY¦¦¦h4Þxãf˼çççóî»ïÒ©S'ºwïŽV«E¥ROjj*®®®xzz2xð`RSSINN¦¤¤„nݺqêÔ)þùçn½õÖÿÝÌÌL\\\èØ±£ X%’¤Ñ«³³3C‡eýúõh4***±ÂõÝwß‘œœÌàÁƒ}|×…´´4bbbÆÒÒ’-[¶°cÇ.\ˆŸŸŽŽŽ­[wØ9³Î€ÕÛÛ›äääZÏÈÈàŸþáí·ß¦K—.lܸ‘AƒannNvv6ÿüóo½õ–¾Ÿ1 €öïßO¿~ýxê©§Qn^Y²V©ûá‡2cÆ NŸ>ÍÚµkõNš™™÷Þ{/~~~üøã<þøã2£ÚBÄÄÄpáÂŽ?Ntt4³fÍbÒ¤IúrìÖD÷î݉‹‹Ó¬1qqXC=Ôè:e ßDEñÒ¿å»·mãM>÷ðà×_å0xÍ»ï¾Ë˜1c¸ë®»8xð 7nD­Vâ»ÿÒK/Ñ¿233yä‘GP©T8p€Y³f1räHý~zè!^}õUn½õV‘Þ¿Ÿõëq{ôQLüýEpúoÖ˜›o• vì0öÛ-i iii˜™™]3ËTRRÂŽ;Ø¿?fff¨Õj´Z-ŽŽŽdffÒ§O¦L™B= ²Ÿ;wîä·ß~ãæ›oÆßߟµk×òüóÏãîî`PEÓ©S'î¸ãÞ{ï=V¯^mpŸª,­¿ï¾ûضm£G®·‚ö¶mÛ aݺu|ñÅ>|X¬7ùùùœ8q‚´´4ÒÓÓ9yò$>>>,[¶Œ~ýú¡Ó騲e Û¶mkTÀZVV¦o  ¬¬Œwß}GGG,X€µµuƒö§T* kTÀš‘‘……>>>DGG·JÁ>‰¤=Ðè€ÕÚښǜ>ø€7ß|“´´4´Z-!!!899±lÙ2zôèaìãkqrssùïÿKii)ëÖ­ÃÚÚ+++Þyçº{ÝÔjxï=3Fd6›3ÈÒh 2>ý–.Ðé ?,,ª;íññй³°©¼¼¼(..&##777ƒÇ´Z-Û·ogÊ”)x{{ãååÅÉ“'yûí·éС'Nœ`Ĉøøøè_3~üx–-[Æ´iÓxøá‡õÛ«öÈš˜˜0oÞ<žzê)–,YÂ3ÏûL_JlkkËÌ™3™:uª^9ÒÌÌLß§îêêÊ믿Îk¯½Æ-·ÜRmLTïÞ½™8q"ëÖ­cæÌ™”nÛF¾…wNŠ¢¦ÞqÅ5¾·ãQ©ZíèèH‡ÈÈÈàСC¤¤¤ P(°³³ÃÞޞѣG3bă2ÅÒÒRV¯^Mqq1/¼ð:tÀÔÔT¯|žŸŸÏÑ£GyóÍ7™6mš>+ñâE¶nÝÊ<@hh(›7ofîܹµ s)•JýbàgŸ}Æ¢E‹ôEEEáââ¸qãØ»w/'OždôèÑ×<îÒÒR¾ýö[}|ÓM7±aÃî¸ãƒ€W¥Rñõ×_³uëVî½÷^¦L™‚££#EEEdeeU»ÖKZ'III¤¦¦ròäI.]ºD\\AAA¸¹¹Ìm·Ý†···þþ¬P(˜:u*O>ù$‘‘‘Ô¸ßòòrHII!??Ÿ””âââ¸té>>>dddàè舛›ÙÙÙ¼þúë VATíܹ“òòò‹íEDDп|||Ø·oŸ±? ‰¤ÕššÊ©S§¸å–[šeX 9xð ?ü0wÝu—/_ÀÎÎŽ.]ºÐµkWc¿W-Nii)ï¼ó:ubÑ¢E‘’’‚ŸŸßµ{÷LMað`X»Þ}®¡àKh(üßÿ‰ÀrÀQhj ±±PV&úÚ:u%¡¡°j<òˆØor2„…Á®]p×]àâ~~WWGGñü«‰¯ÆÎÎŽþýûsâÄ ¦OŸnðXá¥K„üò /}ò J¥¥RÉc=ÆÇŒ¥¥% , wïÞNPP/¼ðãÇ×÷Ö„¥¥%óçÏç÷ßgüøñ5fP E«RumËdeeqæÌ¢¢¢øûï¿quuå±Ç#00°a%¿§OÃÉ“ðoæ¼YQ©Ä‚̹sðòËb[Y|õäåÑmÊþüóO@”lYZ[ãÜ·/lÝzí}ÿò vôë×3gÎ`aaoŸ>pÿýø*•X=Ê¥K— â§Ÿ~â÷ßç“O>Ñç+EÓjB¡PÈ|€[N¦?ü£GÃåË0j&&&Ü{ï½Üyçœ9uŠJ%w¾öZ­BgÊcÇp:zT,|IZ†Í›7“’’‚¯¯/çÎÃÆÆ†û￟޽{cffFNN‘‘‘ìÝ»—ï¾ûŽÁƒ3sæL:vìÈG}DAA/½ôRjû¶¶¶Üñïh£+VŒ~±còäÉLž<™üü|ìììê¬<155å±ÇãñÇgþüùú,ëùóçéß¿?<öØc¬Y³†¾}û^³ªâرcôîÝ[ˆtîܵZMnn®ÁwãÏ?ÿd×®]<ÿüólݺ•}ûöáããCXXJ¥’¾}ûòÈ#û£”ÔBvv6›7oæØ±cxyyÀ¬Y³¸æ4'''ÆÇž={ð÷÷×·K•––rúôiΞ=ËÑ£G155ÅÑÑ‘nݺéG“õèÑC?_þĉ„††²lÙ²FWûTö¸æü»ØÙRRR?~<;v$))ÉØ‰DRo¢££155­µò%''…BÑèÉ ¬\¹ÒøkAA›6mÂÒÒ’Ûn»Í`æa}P©T\ºt ___ƒ¬XRREEEÏíØ±#ÍrÀM¡´´”¹sçâèèÈØ±cIOO§¤¤„^xKKK,--ëß´_T#GBt´0ǃýûáãáž{àŽ; Ÿïç ˆ,¨¥å•¾µ¿þ‚ãÇ¡ ^z zö­V®™'…B8÷ü·Ýýûòeðì³PÙ¯äàW©›nº‰mÛ¶1uêT½”••Eȇ²ÄÒ·*7 www^þ7˜¨)ç`gÇŒ[nAqì²B¡`ðàÁ 4¨Í•û&$$`cc£/ýS©T$%%Q^^np|¾¾¾­"à>~ü8¯¼ò Æ £K—.¼õÖ[tîܹáï{y9üø#̘!Îu€k-â¨Õâ5‡¹9,Z¾¾’ÇŽ‰RØ®]ÁßΟ‡Ü\Q¥Pù¾½õË/âFFFùùù$&&2©¤Dd|«Ì­•¨(¸ùf&::òùçŸcnn.²WXétÌœ9“7ß|…Bëׯop&ÈS«…W^‡ O}$œþeµyóflll°±²ªóû¡ìзãÇ1­Ïqµ111xxxèö’’RRRô%ÑxyyµŠç–@«ÕrâÄ õ•Eqqq„……ñÖ[oáááN§Ó_+ÿíØ±#;vdôèѲk×.V®\‰J¥¢sçμõÖ[×|ÏzôèÁòåËyùå—;v,fffLž>>úý^½o{{{&L˜Àøñã›4ÓÝÜÜœŽ;RXXØà€5&&†|P¯å[¯„Z­&))©šŒ1ÈÏÏ'''Ç pií¾ÊˆV«%==¬¬,ý@__ß:ÇõÕ„Z­æ»ï¾ãã?fìØ±¼òÊ+ú:ëׯ'**Џ¸8LMMùôÓO¯9³&Î;Gzz:aaaÍrüX]\\¸ýöÛÙµk}úô©±ÑÜ¢FGW§ÓqùòeÞyç^ýuƒ7âwÞáâÅ‹ŸE‹1a„f9àÆ¢Óéøí·ßðõõå–[náðáÃ$''³lÙ²:³ƒ5’ |/¾s戬hTüü3<þ¸dA8Ø¿ü"‚Il^ͼyâ§*ÿ*äêñõŽ}å>ml„c_IYT:E©©PÇø‚ÁÁ¼·j:DŸÀ@.^¼ÈÚµké×¥ #¬¬0MMAÔ~Ñj!#þïÿPÌ™õèkºæP£Ã‡!(Z‰ÃPRR† ô7T+V¯¼ò ™™™úç)•J>üðCƒric ÑhøñÇ™?>3gÎl’@f¦(îß_,¨„„ˆLëµJ¶}}¡wo±(óo¿&&¢l½¬L|wüýÅbLïÞ†û»ã}i»ò­·°´µ%??ŸÌÌLºffŠÀö¹ç®<_§ƒ¸8ñ·ª^¿ ooz"æT*•ÞQää0Ìɉø›o& €AŠ›·B!ÎÁòra¯™YÝeþˆEª Ä1Œ?ý‹£P*E¯¡N'öYºNÀÕ³5®':Žüü|Ö¬YÃSO=¥W@ˆˆ`ÕªU”””TùX}yíµ×¥ÂÙ¨ëdeeÅÂ… éÛ·/6l`êÔ©¸»»_óú¥T*qppà¾ûîcæÌ™ÄÇÇãááQ¯_¡PÄM7ÝÄ×_Í—_~Ù(uîʱf>ú(³gϦ  €ŠŠ :wî¬|ÆŒ¼òÊ+Ìœ9³Ö@855•ŠŠ ƒ ÓÜÜœ~ýúqòäI† ÆéÓ§Ù¼y3¯¿þ:þþþ€hí0`€Á¾/^Ìÿþ÷?:ÄÂ… ¯ûçªÓ鈋‹ã½÷Þãõ×_78ß~ûm¢¢¢ >×Å‹3nܸëngssXXkÖ¬ÁÔÔ???´Z-Z­–K—.QQQ]ºtá½÷ÞÃ××·Ñ É;vÄßߟ 6Â-·ÜÂÿûßgtšt¯BT˜™™‘››[çó´Z-ÑÑÑtíÚSSS}FµS§N˜šš2hРΜ9S¯€5??Ÿ'Ÿ|’µk×UŒS§Ó±ÿ~BCCyõÕWõÛ³³³yùå—ÉÊÊ2xŸÖ¯_···Ñìmh4´Z-¦¦¦ús¹  €#GŽPTT„——666lÛ¶ˆˆ¼½½ÉÎΦ¤¤'''}ôQzôèQ¯…„òòr¶nÝÊŸþÉ‹/¾È¶mÛ(,,ÔW'\¾|™}ûö±råJ:wîÌÇÌÆyöÙgÜr—””Ä­·ÞÊ©S§œÔ¬‰F¬eeedeeÉm·Ý†——Wµ‹ÆG}T-Õœ˜˜Hhh(_}õ•þ"X•ˆˆ¦OŸnÐÿÚÔ†/]ºÄ×_͇~HÇŽ5jTãw¶iøø\É ÈŒ~üñ•ßKKaþ|‘}i¦t: œã*«ï€È¶>þ¸d׬?¬ÕÙ¶‰Œde^¿>ú(ŸcanΊéÓé3s&ʸ¸úõâþö›è%|øa`DD€“4peÓ€sçDú¡‡Dß®)..æÜ¹süñÇìÙ³‡›ªd¯+¥õ.\hàðÛ‘×jµüøãhµZf̘Ñd//Qînf&‚±Í›áàA˜4©úsóòDÆtĨ©ÏÎÝ]œ£U©É‘¯r0qs£gy9ÅÅŤ¥¥á›“#lªºš­Ó‰Ìf—.ðä“W¶?ööÀüù󉌌¼’AMNÆæÿþ‡ß}W|_vïûí×OTK¼õ–€Çƒ[o­ÙN UU¹óN±ˆSõ}ÏË׊ÿüGì³466\œ;®g JVVgÏžeÛ¶mDGGdS+–g«|fÆqt½8yò$½zõâöÛoçå—_&88˜‚‚î¹çžïËÊʪÁúJ¥’ 0kÖ,½°RcprrÂ××—}ùzU'¥ÿþL›6?ü%K–ÔP?~œ.]ºTsž†Ê /¼@pp0|ð+V¬¨¦J|5ÖÖÖ<ýôÓìܹ³ÑÇÔXô¾ŠB¡Ð÷WÁ­·ÞjÐÙfÍ&$$°jÕ*žxâ ÜÜÜHKK#77___lllðññi¶J SSS|ðAÞ}÷]^{í5úôéÓô{O#033# €ÐÐP† Rëó¢££yðÁyøá‡õÓzöì©<1bŸ~ú)·ß~»^42;;›””½Jqåñ…††rüøqNŸ>m4ÒóçÏsáÂÞ{ï½j6‘ÀSO=…Ý¿íb …¢EƵ7222'--éÓ§ëß¿šˆç‡~ >>žQ£F1|øpRSSyûí·éÚµ+®®®9r­VËèÑ£Y´h‘þ^ªR©8}ú4}ôeee¼÷Þ{5¶T%$$„½{÷òÞ{ï¡T*Ù¾}»AÀºoß>¦OŸ®0Ÿ|òIžxâ >\m1®¢¢‚òòò¯´´”„„žþy>üðCúôéÓä÷µÑ«……ƒ Ò«àÖDM«d‘‘‘üùçŸWëóÊÌÌD©T2zôh\^Ò’lݺ•Ñ£G7¸\¤ÙÙ¢xݺºŸgb"T{ûõ»vVª¡Lœxåÿ……¢´ÒËK8àÂQ®í¤?vŒóç3àÔ)ÊgÎD€ÕÛo‹ ¸jÙVa¡^ÍÍE`Põüýáµ×®çÏÃÅ‹¢T¹¶cU«EÆ®¶ì©……P:î×Oü^Q!‚}#PPPÀÞ½{«­¾ƒpæ?~<öööú2*c“ššÊ¯¿þÊòå˛ÕÕ?óùóEö¾&ΞýÕÇ7ۈŭ·¢üùgrrrHOOG³p!¸¹‰Å¥zô6jµ†åðeeW2¤ÀèÑ£ ooQVœ–ééðÝwP¹*íﯿ.²Ë5/Þèt¢ºÁÆÆðXÄOU’“Eo«‘ÎãºHIIáÏ?ÿ$--ÍàüÕétú’¾‰'¢ÑhZï(¯f¢¼¼œ]»vñÈ#зo_V¯^ÍsÏ=Wë¼Þ–ÂÔÔ´IÁj%&LààÁƒx89ÑËÁ~ø† ‹¬*÷Þr ó.äܹsÕ2¢ ‚÷ª-#•x{{£Óéxýõ×Y±bõ²G©Tåºxñ"{÷¸¸ÚbKff&&&&ÜtÓMzm†Öpo*ååålܸ‘Ñ£G3lØ0LLL®¹¨ÐTüüüX½zuÃ+ÕšoooNœ8QëãZ­–0vìX<ÈØ±c‰‰‰1pÄ»víJNNGŽ!,,ŒcÇŽé…œ<==yóÍ7155E«ÕòçŸ2þ|BBBôsã¯7G%44´Æ yU_ÅÖÖ¶Õø*­•JÅåË—ùúë¯9þ<ýúõ£¨¨ˆ¿þú‹çŸ///ÂÃÃÙ¸q#yyyôèѵZMXX#GŽä®»îâøñãüøãXZZòŸÿü‡¡C‡Ö©ÊnffÆÐ¡CéÝ»7_|ñï¼ó/¾øbÂc—.]¢gÏž8;;£R©pvv&!!Î;£Ñh8qâ„~bˆ–’|7Ò±cGlmm111aß¾}4Ú²²²bR•lIII EEE×ìåš0a&L`Ó¦MìÚµËà±”””J%'Nœà¯¿þÂÊÊŠÑ£GãïïoÔÞÅØØXþùçÖ¯_ßôuè ʯ%`n³fµüÁi4¢—ÕÂB8ÆC†ˆ`¯¶ç&&Â3Ï@P7Š ÃÆFdHA¼Àöí"‹daIIPuvëÕŠ€Ó¦‰×üú«è³MICÕšùÓ§EYó+¯ˆ`ãjzö?•|û­a}騱#+V¬ ::š§Ÿ~Úà±ÄÄD,,,ؾ};ùùùxxx0zôh£ö±±nÝ:  /Ïk§O‹€®êˆ€º*¾ýVd›ñ;®˜>ó¨(._¾LNN³f‰óûˆÀ´²T¾’~çÑ¿„¹¹¹aŒ½½8— ÄsŸyFô—ƒØ¿§ç•,®Z-àªÙѤ$!õ 5Øùã:Tü˜Q"Ý Ö¾}ûÒ·o_þúë/V­Z¥ß®Õjõ£¯6mÚD^^]ºtÑ;=í‘_ýý8‹=z°{÷nc›ÕhÌgŸ|‚wJ c\\Ä5¾rÜYl,6ëÖñtz:g^yï¯T‡hµ¤§¥_cÏ©R©äÁD­V3|øðV¯G0iÒ$&MšÄçŸΞ={ KNNF©TrìØ1<ˆµµ5£G¦k×®­þ¸j£¼¼œÏ>ûŒ’’æÌ™s] Œ¬‚è?މ‰©õñ²²2:ÄÊ•+9vìï¼óÅÅÅÜ{ï½úçXZZâïïÏÆ3f ¯¼ò þþþäääð裒œœŒiii\¾|™µkײpáBRRRŒrÌ•‚f5•ÛWú*[·n%//OOÏæIÚ´C’’’ؼy3aaaÌš5‹¥K—bmm­Þ[¶l™~ÔÞý÷߯¯/iii¤¥¥1oÞ<}ÛÅèÑ£)..F«Õ6(¸³³³ãÉ'Ÿä™gžaË–-ÌŸ?¿ÖçFDD0æ_‘F333úöíË™3g1b©©©Tø( &NœHVV|ð*• +++üýýyúé§ùùçŸùöÛo«ùºgÏžeøðᘚšâææFjjj“Ö&]YKKKÙ³gO>ù$³fÍâž{îá®»îbíÚµdggW+¡¹©©©deeqìØ1***8zô(K–,áÌ™3u¾.++K47.\àÅ_dÞ¼y* EÚ?'ö)û'#CôjµBøé§¯9ÍŸ/2Q5¡TÂâÅbLN` (#¶²"Q•N½‰ œ8!ÄvFŒ½»v‰Ìrn®Ô¹Z ÆÆF¢•×sçàë¯ ŸÓ¹3LŸ.J‰óò +.û¯‚ÎË‹˜Å‹9¼k*# Ò\Mrr2ñññœ?•JÅ?üÀsÏ=gÐ'R•e#×ê±i(ùùù¼õÖ[XZZòÈ#Ìrl¿ÿ.J¯v@´Z‘!¯‰‰…bv3¢|ILH€‚ì*a|| +K|+Å$BB`ï^\?^·Z¶R)ª …ÈY]}©©°|¹ø{ þæ¦MWˆjb÷nQZ "h®£ ¸¸˜íÛ·ª¡clt:ÉÉÉ„‡‡G~~>Ÿ|ò «W¯ÖÏô¬“'O²k×.ƒòâÖHEE ÄÆÆröìYvïÞݨÒßÖŠ££#'Of¿¹9º·ß†çŸ¿RÙâë K–0tÍ|ƒƒyöÙg 9}mt4åË—óëË/3xðàZËÒ&MšÄ”)SÔ}÷ÝwÄÅÅûm1 %%…¬¬,Ž?NEE‡fñâÅ„††ÖúNDZcÇ8r䈱Í7 !!÷ߟ pñâEžyæ™v»¸T>>>“““Sãã‡ÆÓÓ???fÏžMyy9111‰ Ï=÷ëׯçÁÔ/;991}útvî܉V«%<<œnÝºáææFÿþýyÿý÷ký»Æ¢ÒW ׋ô,^¼˜ì«|­ªTTTðÛo¿Õø·U*Ο?OBBeee”——³wï^/^L‡X»v-wÜq‡>Ãibbœ9sxþùçñ÷÷gÍš5L™2…ž={2vìXî¹ç}°Z‰M£;…BÁ’%K8xð Ÿ~ú)«V­bÚ´iüþûïÏËÏÏ7H,öèуÈÈHýbs¥æÂÕÜsÏ=|ðÁ|ðÁ¬ZµŠ§Ÿ~š¾}ûòÄOpîÜ9öîÝ«oñ,//çĉ <¥RIïÞ½Ùµk—€Wch´wªV«Ù¶mëÖ­£W¯^z‘–ôôtvîÜIdd$¯¿þzƒšç;wîÌÒ¥K7nœ~ÛÒ¥KÙ¸q#¬õu... 6¬Ù•„xõÕW™>>Üu×]ÍjKqq1|ð¼øâ‹_å.(Áž››ø¼\Ì®JY™è^²¤úë[¢’@­¦ËÎëØ¯ÈHÜNžP:‰*µZŒ‰úÏÄ"ËÏ?‹ T§«Ÿh—©©á÷¦&*ÏéõëáÑGÅw&'G?ÕvèÒE”Ç AÕ€ ·Ýv …¢Õ”Ý*•J¦OŸN§N:t(Z­–Ó§O³téRŽ?^§xÞ AƒªËjmðá‡rùòe¼½½Ñh4Œ9²î™Ûm’fNŸN'//ìºvßJ,-ÅwÜ×—±RöÛoüôÊ+ØÇÆòƒNG¼¿?OW­¦¹ŠÆdï¾ûn~ùåc¿+x{{³lÙ2½¯RPPÀÒ¥Kùâ‹/j,“áP:”áÇÛ|=•"€C‡eùòåµÎC½°¶¶¦sçÎÄÄÄTëç,//çÇdÁ‚úÞìE‹qäȃòK…BQ£ªP(˜>}:=ô³fÍâï¿ÿÖÿ±cÇÖäìSs3pà@úöíËØ±c177'66–çž{Ž­[·Ö:jÊÜÜœ)S¦4O¥V+"&&†;w‚……ØÚÚâàà@JJ ‹/&((¨Æû°©©)ÁÁÁú œ–B¡Pйsg–,YÂ/¿üBPP...œ8q‚›++dɪ Š={ö$''‡ŒŒ BCCéÞ½{­±Ž……E5m777}ôQÞ}÷]qww'33“ŠŠ ½¶Q·nÝppph²ºt£Öììl¶nÝÊܹs™3gŽþK«V«¹ãŽ;xüñÇ9räÓ¦M«÷>{÷î­Wšá7ŽM›65j sSHOOgÉ’%ÜyçÜzë­õ»Ñæå‰ÞÌÀ@!ücj*V//‘qôð¸nö׉©)të&‚Ö‚Qæ;fŒH#"„(Rÿþ"ë¥Ó‰l…üù§8–† K<û¬Èª¾ð<øàµ{r]]…hMV– rrÄhoo‘ýªTÏ=zT.UÅÚ^yÕ?ÿКØ+K1*ñõõeàÀDEE¡V«›žálüñ%%%¼üòËuöI“ùù¢lÜß_^Û·‹lâÒ¥5—kƒptÃÂDßgåÂDY™(îÜÙÐ)n&<4Ò#"° Å|Ñ¢7zˆïâåËpê”ø.øøˆï©Z o¾yÍyÄõÆÜ\ć‹ãsr‚ÿþ·îE¡iÓD%‚J%lìÖ­Ùß—–D©T2«Ê„R©$88WWW’’’ F»´²²²ÈÊÊ"<<œï¿ÿžqãÆÌ*511¹®ßÛk¢V‹þg—+‹{¹¹W®åu-Li4°lî»O?Φ6LLL˜:u*#$7!‡½½±:yÛÇ…úu;¦OŸ>½‹vvvŒ7ޝ¿þúºû*E«ÕòÑGѽ{wæÏŸßfK™›___¢££«¬•½­U#zõêE@@@½ ;tè@PP$>>ž|Pÿ7j#’ŒÍرc ~÷óócÀ€z‘½VuÍkÊÊÊç§Ÿ~"99™ &°fÍìíí)//'66–ØØX-ZÔ¨‘/-Eß¾} D©T’žžÎ“O>IAAöööDEEáììlPÖmii‰¯¯//^$::Z¿Þ‚‚‚3f «V­bÅŠdddàìì¬ÿnøùù‘žžÞäê©F_¡ÊÊÊÈÎÎfÚ´iØØØèEÌÌÌðöö¦_¿~DFFÖ{*•ŠpôèQý6…BF£ÁÔÔôº9"""ðòòbÆŒõÏÐ)•p×]bäF¥ú±©)LÚz‚ÕJî¿_8êÇ‹ŒNå jm-À³gÅïü!zK¶m3‡S_¬­EÀ2s¦ÈÕçËðè£Wz]ÿöí»ò˜V+ÊŽ7löØÛ_™){ÕßÕ5·`U(++cÇŽß …BAEEE­# Z ­VKDDãǯ° "8ݱÞyΜŸÅÖ­b¡.”J‘1LL¼²-)I”ȶDɶB“·7Y11XYX ¨\dQ(„- "PV*…?¾8›7x¶·ß77±ßk•Úuë&в³…bw#??Ÿo¾ù¦ÚØ&•JÕ&œø« á¹çžcÍš5„‡‡óØcñØcáêêª_mnUŽ[zºþzýõ+¥èÇÃܹpß}†Jô‰‰Õõ Ž-,õ\”T*•8yxà7x0nØùû£ˆ7ö»Ð¢¨T*öïßϱcÇôÛŒé«4–Ó§OsöìYƒy¹7:\¾|å­üñ+W®äÍ7ßdêÔ©Á©B¡0CRÆŽËW_}…©©©~de‘Z›(¡(--eûöíDW¶§ü{¼•×ñö~¾”——³zõj>þøc À|À<€‡‡ÖÖÖ8991pà@fϞݪ‚UŸSåçãîîNÇŽõ%ÚôëׯÚç×­[7"""HLL¤[#ÉMMM™3gîîî¼úê«„††âçç§¿vìØ‘:––Ö¤ckô•ÕÄÄsssâââªÕ`—••‘””d-­ÏÇÆÆ²k×.^zé%|}}IMMåçŸfܸq×½ä-44”‘#G6lî½=Ü~»ø¿B!2˜¹¹ÕE†Z•6eg‹¯J||`Ëh+•BpcÑ"‘YÍȨ90¬ _u/(vüö¬\ye»™™è»]¶Ld}ßx£öñ!­ 8Ào¿ýÆóÏ?ƒƒgÎœáØ±c,_¾üºÞÔj5—.]â¶Ûn«ÿ‹ ÅbÆ’%¢¬öý÷Eæ„ 5Ï¾š… ¶ôt1¾©%<,ßx³øxl&L0ü¾÷žžŸxBünj*úEãâÄ÷ÕØ3æòò„pU‡·¬¬¬Ø´iIIIÌ;…BÁÞ½{Ñh4ôëׯMeW5 ;vì`öìÙL˜0¡ÁÎéuA­†ØXqݶ´ Jýú‰ª–ÊÒöà`øþ{ñÿÊû¨J%FM;'ª"æÏ×øèhÞՆ l)-­YT¬`jjJtt4¿ÿþ;/½ô>>>¤¤¤°uëVÆßjÊóë"22’Õ«W³téR|õÕWœ={–ììlúôé£/ ºž¤¦¦bnnÞ°!àÎÎB]º’)SöGKKE)nåN•±X-BNõí‹[Q‘P®ÌXví*Êš«¢VÃ¥K¢|רôî-ê6 <;räHFŽ©ÿ]¡PpóÍ73jÔ(NŸ>F£¡ÿþ ß3†ÔÔTÜÝÝõ- yyyXYYµ^Û?ûLœ×«V5nÑÇÄD,VV]°lZÁˆ’æäÁÔ÷VâââÂúõëõ¾JMZk£¬¬ŒÅ‹SXXÈ;ï¼C—.]ŒmR«ÃÕÕ•o¿ý¶EÿFMﻩ©©QÅ!ß}÷ÝjÛùꫯ %''‡ÀÀ@£ŽßkNrrrxíµ×°°°`Æ zÁÉÖ$ˆÖ\xyy‘MBBŽŽŽ5Š‚¹¹¹1sæÌ†%éjÁÁÁÁ`ÔS%æææM®>iÒòƒƒ/¾ø"ñññdffR\\Œ««+žžžÕʄ닉‰ FU«‹ŒŒ¤gÏžõ¿€hµ¢Ï²j“z‡‘h­}[VVÂÙÉʺvÀj,†‡_~™¸vä™™™Õ©z}=8yò$=zô¨;s.6ÆŒçxiiÓ>‡’¡¼fø^¨TÂÑn©r›„üùEˆ(Ýyç•íýúU-ef&ÊÎÀ·ŽŽ"¨/(¸ö¼æVŠ £G6¶õ¢´´”ï¾ûŽ-[¶ðßÿþWŸAÇ××·ùfDŠ…Bp5¶ä[«™ÌùóÅu¼µeU:×¹jäzÓ|•ú¢ÕjÙ±c¼ùæ›zÁ0‰¤.ÌÌÌÚ]¾´´”>úGGGž{î¹V1¸%éСœ;wÇZü +++ž}öÙV?ΪIµjµšS§NqâÄ FÍÔ©SÉÉÉáÏ?ÿ$±ª¸JB§Ó~mYîœÑë&K…ªÖ†+™h­µþvv¢ôñ¿ÿ5¶%µãîo¿Ý®‚ÕÖBxxx­ãL~öÙ•ž·øø¦‹™š ‡½²,äÓOÅw§¥èÔI|O== •y--kVßõðh½Ð¦¦BmÜØ¥É7‰‰‰,_¾\/¨ôÅ_èKóŽ;V먂FñÉ'BÍüÅ¡Rx-)I”€ïÛ'úI+9zΟ FUÉÈc¼Ôj±˜ÑD32àØ1Qf/idee±uëVzè!¬JnXJKKÙ°aÙÙÙ<ûì³­n”PK`ccÃÈ‘#ùæ›oêL$:88´úþûFGS†~ø7ÞxƒððptÿÞœŠ‹‹Ùºu+¯¼òJ“¡ŒAYY—.]2¬¯†N'”sY( !(ÓÌs`[kkÑ_ÛFcÐÚíkƒ”••M```íOŠŠDƉòÔ÷ßoº™™ÂT*áÔþõWÝ#^šŠ³3Lžl˜]•HªðóÏ?ãííÍ«¯¾ÊôéÓÑjµÄÆÆRTTDtttÝ÷†2w.|õ¬]+ʾ.\€>sºËÊ®<÷Ä ± óÚk"¨1êƒDÛZBA¨oÊ€µ±{÷n‚‚‚ð–‹`’NÇŸþI\\/¿ür¥±í•ÑêÛ®E£k‰233ùᇸ÷Þ{¹ÿþûõÍÉwÜqAAAüç?ÿáÈ‘#­^„àjJJJ(//Ç¥R<©&t:Ñ7nœÈÞ´E QÜÎzCˆ,µg½Ô`ffÆìÙ³111á‡~àÇÄÊÊŠüü|†ÊsÏ=×æê¥“’’HKK3ÚHOâ3 Ì™}úˆ±I%99ùÊüUîŠ:©©)Ü{/ÜuWËer\]!$>ÿ\”7rü•DÒrss)++£cÇŽÕëÚµ+o½õÎM|Ój…ûz¯pwÂm={Öý¼¤$øî;xüñ+ó`‹ŠD«Ñˆ¶Y‰Ñ`þX´b=ú¨X¸53“=ß-DII k×®¥wïÞŒ5ÊØæÜXhµ¢¢îàA¡Œß 4(`-(( ++‹Ž;êª?òÈ#<òÈ#$$$PQQA‡Zï õ:ÐétìÝ»—b]5»”–&‚T33¡ÜFf J$5‘••EVV>•ΡF#²ž•£•J1C±¥9R­_~ÙvÊ%펄„ìíík\q755mšØRa¡aóŸÿܸ#¹†‚SWsâ„h«ñ÷?ÞÞðņÏqq+®üÞRí í”òòr¾ýö[–,YÒæ{ÖÚÙÙWj+g›V.Ø,^llëÚ%?ýô¹¹¹¼õÖ[Rp¬%ÑhĶÒRðó>ÞáÃBøð+£ ›HƒÖüü|¾þúkrss2dǧC‡XZZ¶y¹ôŠŠ Ž9‚ èÝzõjݪŒI=Ðh4lܸ‘±cÇ^S*á¾û„“x=èкw5Ù?-1§OŸ&00°ù{z41Ÿnì™!CĬ؂رCŒ—rs×›¸8Qþ{çr¸ˆŽŽÆÌÌŒ=zÛ”ö‰N'²GJeÝ™QF”ÿfe‰û‹‹˜+_uœÊС°k—(oêØ8 †ÜÜ\¸xñ"üñ+W®¼aûV)+Bš-}/º|Y´tî,ª¦O‡À@xë-qÝHLlòŸiЧعsgV¬XA\\ýõk×®E©TâííÍðáÃñ÷÷o³C©£¢¢P«ÕÕ/òr¨¤αcÇØ¼y3ÊÊ¥òú—åfgÃÒ¥Æ~;$7(jµšS§NñÜsÏ5LˆæÜ9Qæêì,]jÊÂÆÇ ¡¥/¾hÙJ…ÖŽ¹9œ> Ÿ}& ±}à@ñ#i1þùç‚‚‚0111¶)m‡ÂB‘ªt®ë¢¨HdEo½µöçÁ;ïˆÅ™À@xòIÑrsõìO++1Âêôi9·¸8pà«W¯¦oß¾øøøðÊ+¯à#nܺU,„Ô6åA«? è „¶@r²Hè "t>ùİ¢¨*m¼ì T*ñ÷÷ÇÏÏââb222 cçÎdddЯ_?‚ƒƒñññÁÁÁ¡M¨R©Õj¾ÿþ{fÍšeØï"¥-‘´a´Z-[¶láöÛoǦêEåÔ)qa¹ž}b|Ë—ƒ——±ßÉ †N§#""‚²²2ºuëVó“JJàÝwÅÊt¯^bNªµµÈ˜ÄĈ¬Š½½X5±Šmm-¶{zŠUåÊíF&'î¹GÌp¾‘³Í×­VKhhhõJ1IÝœ9#úK/®½šN£÷Ë.]Dpû曢t½juR¥@˜©)Œ+tO:uªûzàí-‚ÕÓ§ý.´i øþûïyíµ×2dÈ•Eù™^½`ýz‘ñ¬)ËÌþØsωê·úpö¬¨éÝûJU€‰Éuiitž\©Tbgg‡]»våöÛo'%%…“'O²k×. ?~pà€¸ðÈ€UÒÆ¹páÉÉÉ,^¼Ø0«ôõ×¢4ïz¬¢7\¬’ëLqq1ëÖ­ãŽ;§ÉÒî¿_dSÏŸ×kkèß_üTåâEQæçí-T¶§N•çu%Ó¦Û‚Ž˜˜ŠŠŠèy-±+É EPyþ¼¨þ©­ï7+K8ÿkÖˆþô/¿UU•ÆOž X7Ý$Ëݯ#Z­–Ÿ~ú www† flsZýûC@€8w«ªÞk4BLÖÞ^Ä8?ý$DÀjC¥£Ê¼½aÔ(ñc°VTT P(ô7ý²²2***èÛ·/C‡mS«»wïfРA†ÙàâbqñùwDDÒVIKKãwÞáÁÄ¥êjpZš¸]ï½{ï­ÿjžDÒLTTTðÑGáççWóBªN'JzÝÝE‰“¯/\k4[—.ðÒKâuvvRíSb4´Z-»víâ–[nÁRöCÖŸ;EU…¿¿¨ ¨°ªTWª¾ÿ^ˆVöb?ø áÈ¥²2ؼYŒh’\WrrrØ·o+ªŠµÝè:$‚Ò'Ÿ4Ìðk4ðóÏb±åÅEŒ³fðíìĽìÒ%Qêëâ"¾6ˆª#¿¿ Ž*Õj5GeõêÕœûw†J¥ÒÏ9zä‘Gxíµ×ÈÊÊj uÇçðáÃÌš5ëªwF wß}cÎГ´òóóYµjݺucäÈ‘†š˜ˆLÒõ._ 4\í“HZNÇï¿ÿÎÙ³gùÏþƒEMç|B‚>kR·­ kk!¨2v¬Xø‘}ƒ#‘••ÅÑ£G™t­E–öLv6ìÛ'¿t:(/¿ökBBDyãòåPµMàÌáÐïÝ+öÕ»·ùV™Œ15e–—.‰žÕsçDÀ;dˆ±ß…ޝ¾úŠàààÚÛ<Ú3±±âœ¿š£GŹjeeXæ~ú´È¨Î›'ª‰œœàÕWÁÃÂÂDÅÐWÆnÚ$ªêÊÀ^'°îÞ½›gŸ}–¸¸8´ÿ®.íܹ“Ÿ~ú‰áÇóÀŸŸÏòåËIKK3öñÕÉ¡C‡Xµjÿûßÿª«[Y‰QVVÆ6S"iEEE¬_¿žîÝ»³xñâêNº««,Û“Ü„‡‡óå—_²bÅ «?!?V®7ñ66?\"8yò$5ŽjºaøýwÑgªPˆŒÐã‹ ¶.¬­Å `SS‘}R©ÄÏ©S¢Ì?$D¬ãÇ×,$³}»øéÒ^yÅØïÀ Gxx8‡æ‘G¹ñÔ€€gžI‡þ×^çpy¹Pî Ïûà1fĹüâ‹b¡µ’Ê*‚EÙûÿþw¥ìwøp‘½^“$ê AkVV[¶láæ›oæ½÷ÞcàÀ²ÿ~úõëÇÓO?Í<ÀK/½D~~>QQQÆ>¾ZIHH`ýúõ<õÔSøûûWW‹ÌÏ7¶‰I“øõ×_ÉÏÏgîܹÕûõ*WŸÛPé¾DÒyóÍ7yâ‰'¨ùI …PR7N–õJÚ$;wîdúôé7†:°N'J¯žïø÷ߢwÔÄDd¼¼àرº÷µltì(þÿûï"3ef ÀìÙ°dIÝ÷É1càÇ…6Cm×I‹ñý÷ß3}úôs¡æ×_…`Òˆ¢_õüyÑæ¥Ó‰>ëJ%ûîÝÅx1ýúÕ¼?33±€cfvE9¸ÑëÚ î‹ òV())aÖ¬YúUêôôt¢¢¢˜4i’~›§§'žžžœ:uÊØÇW+{öìá–[naìØ±ÕƒÕôt˜?¿a¥aI+B£Ñ°gÏî¾ûnCUàJ.^%¥¥Æ6U"i1ŠŠŠX²d ·ß~;ãÆ«][ÁÞ^Œ©HÚ Û·oÇÜÜœàÊŒJ{D«Y£Ê¾Ñ_å‹U™?ÿŠ&ƒR)ôRSëÞ¯µõ•€ÔÍMd£âû‰~Ö¬,c¿C7ÑÑÑ„‡‡3}útc›Ò²”–Ьhf¦áö5kÄ‚‰B!Îã¡CEübii”N™"ÊäŒ}$M¢Akqq1Æ`Öj\\©©© lC³ÕJKK9uꃮþ`¥¼xïÞPSé˜DÒHII¡¼¼œ^½zUP§=²ä]ÒŽÑét|ñÅ1­®Ò÷˜˜êŽ€DÒFÈËËcÛ¶mÌ™3§våë¶ŒN'ÈõëEÙ~v¶pÐo¾YôïÅÄ\yîÀ†#”ºu: 5QTo¼a¸­{w<ØPL©>Ü~û•,­äºPQQÁçŸÎwÜÑ&ôrê…N'Ä»T*ÃíQQ¢ì¼2 XQQsöC‰,DDõêƒ_lóí. X133#==]¿íСCxyyô€ªÕjòòòjîjdddб¦ ŒN'”µÚûФ]A@@@Íj‘*•pÐå9.iÇdddpøðaüq¬­­k~Rq1¼ó¤¤Û\‰¤Q;v kkkmJË ÓÁÖ­"Côî»WT|==á±ÇÄXš¢"8rD8òUQ*E¶); KL•FUqr‚¥KÁÙÙØG-¹aaaÄÅÅqÇwÛ”æA­†?þAç7߈ó¾OO°N™"~ÿüsصËðõ …H²étðþûÕ{·]\jžÅÚ†hP‡²îîîlÚ´ ;;;²²²øë¯¿?~û¬ˆ;æÎ­þœ¼<1:)(Hüžš*FnVñ) èÓ.3UÛ ¾ºöíÛ—/¾ø‚ˆˆ´Z-={öÄíßÕN‡¿¿??ü0ƒ®yÖW2@~ø!ï¼óŽAÀºe˶nÝŠ %%%Œ=šGy¤fá˜F V«9þ|ÍMÚZ-|ò‰q®MEK"©'ÙÙÙ¬[·ŽY³féÖââbÖ¯_ϱcǰ±±¡´´”;3»ï¾»Ùþnaa!ééé5÷u¨TbÞÜÒ¥­B¦\ÒvÑét$$$ðÞ{ï±lÙ2}Àš’’š5kHHHÀÂÂFÃâÅ‹4hÐu³­¢¢‚n½õÖºšöZF)i´Z-gΜá“O>áwÞ1X¿úê+vìØ¡÷UÆŒÃüùóëÎè73¡¡¡ôë×[[[c¿UC£¤$1žcâDá„wê$ÆÑXZVÏ4Õ„R)„g®UÑ7p ¨¤¨ü ÛKßcÑjµlß¾ØØXƒ€µ¨¨ˆuëÖqâÄ ½¯r÷ÝwsçwÕ^NÇo¿ýÆÐ¡Cqww7ò»×ÂÂDõìÙWy+ÉΕ.."cúË/WÖ¡CëÞ¯­­ZÛ! X•J%J¥­VKvv6zÇxðàÁ5 U!22’°sçN¬­­ÑU©ÓNLLä‹/¾`Μ9Ü{d„„ðÜsĮ̈ʙ@M$&&µZM—.]ª?˜–&JGjkÒ—HêAAA‡â÷ßçèÑ£™Î'N°{÷nV­ZEpp0ß|ó 6l`üøñÍ&pæÌºuëfñÒsê”Pœsp0öÛ$iÃ$''sðàAvïÞMjjª~&·V«åçŸ&..޵k×âèèÈš5køä“O0ìkIBCCqqq©³Ê‡”¡ÜV}I‹ráÂ<ÈÎ;±³³3ðUØ´i=ô³gÏæôéÓ,Y²„2|øðëbŸV«%44”>mÙ9ݾ]ôëUÍŽÖä›Õ…RY?=…¢îLí ÈáÇ9yò$[¶laDeyõ¿;vŒß~û5kÖп6oÞÌG}ÄØ±cq1âbwQQ{÷îåÉ'ŸlÛÙÕŒ ‘<¨)9ö×_/f¬FEA×®WkncÑàzˆ°°0æÌ™ÃÊ•+ùè£xä‘Gxë­·P]­jU 999СC‡j|ø0ƒ&(( &OžŒ««+Gm¶¿ÿÏ?ÿ0bĈê¥Z­˜3wÏ=²RÒ$ŠŠŠÈÊÊÂÙÙÙ DL«Õrøða¦OŸŽÜu×]¤¥¥}]lÓh4ìÞ½›‰'Ö^¾V^.FbTU•Hª““Caaa¾Ê‰'èØ±#“'OÆÂ‚    Ь¾Êµ(**"22²í¬ZíÞ€¡þûÈ#2ãiÒÒÒ¨¨¨À¹†~ÇÇ3tèPúõ뇅…S¦L¡C‡»Ö\Û&>>¥RIתA\k§°žV¬s~Õj1¥¡oßšŸ?l˜˜\R"„ÀZ©Ðõ¦A«Z­æóÏ?ÇÌÌŒ_|‘·Þz‹›o¾™ü‘‹W«­Õ°aÃxþùç?~|µÇ¢££±··×¯Þ˜››Ó­[7.\¸Ð,[Y&6dÈšŸ óæ5çû+¹quuåÑGeþüùÕn.\ÀÛÛ[_.ïââ‚››[½¿?×"??ŸðððÚÏî»O^ü$M& €§Ÿ~š»îºË@ @«ÕI·nÝôÛüüü¨¨¨ å:)ñæä䘘X÷¨µìlÈχÎöJZ7#FŒàùçŸgìØ±Õ‹ŠŠÂÁÁAÌ6·¯RŠ‹‹Q(5WÒ´VT*1;òÈñ{Ÿ>BõΓ;¥K—Ò½ñ© .àã㣿¾»ººâââÒl¾Jc9|ø0 ¸®¥÷";>üP«¶¶¢OµOQUPZ**jË{xˆ‘LYY¢ÿº­-Jµ X³²²HJJâÁäæ›ofРA,X°€.]ºpîܹ&SZZŠR©Ôg?•J%¶¶¶d]c s~~>‡¦¤¤¤Îç’——‡§§gÍOpv–}}íFCHH!!!h4c›£§¤¤333}öÓ ²¯– ¿Šôôt°ÿü#Ú­t:Ù;^…ÂÂBöïßÍëãõ¦&_ÅÜÜœœœœZ_£R©8~üx‹}_ øûï¿™8qbÝbzÆæøqxðAQÉck+ÓŽE¿êÿþW¿6”W_=ÜeeÆ>š&“ÀÑ£Gë]‰[ þÄÍÌÌpuuÕ×ŽÛØØàèèxM‡»)\«NÝÒÒ__ßkÍV©TØÛÛW(ÐéàÛo…\´¤] P(ðôôÄÓÓ³u_تØ[vvvøùùÕ®lý/EEE5÷—h4ðÿ'Vû$í|||èСC«ïåQ(×´ÑÍÍÎ;7ùXN:E```­¢x{‹jš¶>á k×®×­÷¹©Ôuî* ÜÝÝõ"•MåôéÓ 0 U¨¶VC§ci†ôt±- þû_X¼X.UÁÂÂÿº¯W­ˆºÎq¥R‰··7vÍÜV§ÑhHLLdåÊ•tîÜc¿ †hµ"8­\lÍ˃×_j½Uß/…¢îÌjU Ø¿_Œ°iã8::6Ë4Œ&{òõqDꋵµ5F…kµZ 騱c¯³°°ÀËËëškYYÕ/ bFWm2Ñ’6‡R©ÄÝÝww÷VåÌÛØØPQQ¡Ïˆ•••QVV†‡‡G¯³¶¶ÆÛÛûškvvvÍëï¿‹æ}ÙŸÝn055ÅËË GGÇVuŽ[[[SVeU¸°°ssókf‚œ›e)44”!C†Ôþžde‰ «ìãnøøø4Û”€æ¢ÒWQ«Õ€p¨ëã«tèСƞ؆RZZÊÙ³g« å´ ´Z1õñÇá»ï®dˆ\\D…\$2ÀÜܼ^÷öëMM¾Jyyy¾Š‰‰ ;vlVÕjµZÍúõëyöÙg7n¯¾újëZ¤‰ŠÓEV®„Êê‰É“…˜RSî199°q£lãØÛÛ7˽½Á¯Öét”––RPP@AAEEEh4ÊËËõÛ*ZÚHnn.iii€(y '  YÞ´K—.áááQ=`={Vô¯¶‘.IÛeÀ€ÄÄÄPZZ ˆRßÔÔÔ{HCFF†ÁÌW@ô > ³fûð%í¥RIÿþý ZD.^¼ˆ©©é5ùæ ..Ž¢¢"zôèQó²³E–ÇÈ}X’¶Mß¾}ÉÎÎ&ýßìayy9Íæ«\‹èèh›MY¾É¨TBõ´¼\üÞ¹³™yûmhmÙ0I½0`ÑÑÑ”ÿû™¦¥¥‘––f Op=(..æï¿ÿæÍ7ßdÆŒ­#]Zz%›zø°øÿܹàïß|ÃÞ^”Ë›z¼ÔUVVÆG}ÄæÍ›‘‹‹#!!ÐÐPƒç¾ùæ›x{{×{ßC† áÃ?d÷îÝÌž=›3gÎÁc=Ö,›··wõ•÷Þ½E?“DÒÂŒ3†¥K—rüøqú÷ïÏ®]»(**b̘1ͲÿÜÜ\zöìi¸Q¡¾«·K$ÍŒ‰‰ ãÇç§Ÿ~bâĉØÙÙñÃ?Ð¥K—êçe púôiXs¶¢¤Ö®}Aµ´I=:t(ëׯg÷îÝÜyçœ:uŠ‹/²páÂÿÛ:Ž[KèåËðå—!æJúûËïW;`̘1,_¾œãÇÓ·o_~ùåÊÊÊ=zôuµãÂ… øûû7Û¢~“((€={ $žxBTe>ôPËü-330òÌÛÖFƒVKKKF¥Ï€VR›ˆQ]%ºÎÎÎøúúŒ—qvvæé§ŸfãÆã½)ùù`m-œêðpðò=á^^ƳIÒh¼¼¼ª•köë×ûî»?üÌÍÍY²dÉuWç­\„l|ô‘èÉž?_Ža2 XY¼xq³üá3f0cÆŒjÛ'NœH¿~ý¸|ù2žžžx5ã0++«zð›˜(VMz÷n¶¿#‘x{{³~ýzƒmæææÌ;—Q£F‘••E÷îÝ›Uå±´´´ºàAl,XY‰ñI3Lpp°Á6{{{žþy"##Q©TtïÞýº89………ú*Y¸÷^c¿e’6Æí·ßÎí·ß^mûäÉ“éß¿?ñññtêÔ©z+F QTTDvv6~~~×ÿÍÈÉc9.\‚2ÞÞ0mÚõ·CÒ¬,]º´Ú6 æÍ›ÇèÑ£ÉÎÎ&  æé-ˆZ­&$$„%K–ç ³º'LX°@†µ¦ÚˆFu¿kµZ’’’ áôéÓdffbooŸŸ#Gޤk×®X6aÛÍÍ­Ù”ôª’””TݙٺU¬ Ê€Urñóók‡£´´´úMåãá®»dÀ*¹n˜ššÒû:_SSSS±´´¼":¶w¯}±²‚çž3ö["i‡T û]O~ùåØ,âM æÃ…³þÔSbL‡¤ÝÓµkWº© 1--¢¢"ü›³7´>”—ÃêÕb±Ú´+ª³³QÞ‰ Á«Z­æàÁƒ|ôÑGúÚrwww’““ùóÏ?Ù´iwÞy' .¼¦jïõD¥R‘ŸŸo(üQZ*æ%Íœiló$’f!//ÏpDV–P±“ý«’vΉ'8pà•ÅR''1 oð`he œIc(++cß¾},_¾¼åǵÂÑ£B lölpw‡gž‘Jó’ëFBB®®®×GX­þ’‡‡P§O??h+sŽo°žùäfÏžM—.]Œ}Œ€è_­VBãà .ÊI; --­º v÷îâG"i‡|üñÇX[[ÓÉÑ‘9‰‰t „ëc:*‘ÁªÄÈdffâÓØ9¾ðÊ+bQæ–[ÀÂ"#aÝ:È˃aÄp˜“ӕUÓ €5;;µZ}ÍÙª¦¦¦8;;ë‡j·òóó ÕXu:ÑTýàƒr¬¤]––f(Ž•6À¢EbµDÒŽ(**B¥R‰ÅS[[¬JÚ5/^¤¼¼__ßú¿(>~øAdÆŒêí·‹‘4•czìí…c/•O%­ˆÂÂBrsskMŽÕJy¹È ÚÚœ9ðÙgbMåÜÔ%KÄbŒô‰Ú X­¬¬011¡¸¸¸ÎçiµZÊËË[Mÿ*ˆV1š”¡vuÖU"i£$$$0~üø+¢¢DŸöuž›&‘\NŸ>¯¯/¶))¹Îj­Éõ¢´´”uëÖñðÃc[›J%’BCE`êí-ªlzöóR+ÿ«u…B«’VDZcÇèÑ£‡¡ß~-Š‹E){·n0c†èCýè#HKÛÛË@µ Ó ™9ooo,--Ù¿?µ>/11‘ØØX}|h4ÒÒÒ K .]‚Q£d¹¤¤] V«ÉÌÌ4̰FG  ÓFM¯’HZ5ÑÑÑôëÙþïÿĤDÒN¹páeeeŒ9²ö'……ÁÛo  ±ÍÏO¨Nž 20•´NŸ>]mÆw¨ÕâßK—Äø²ÔT!ºW™˜j4È“uuue„ lÞ¼™€€&OžŒigX§ÓÇÛo¿Mÿþý[^Ý«žhµZ*** çSCÿþÆ6M"iòóóQ«Õ†óo½UögKÚ-aaa<н»P 2¶9I‹±wï^n¾ùfÌ뺞;9Á /eߦˆ2I$F¦°°S§NñÈ#Ôþ¤‚رCTÍš%æÌ¯^-{¯Û1 N½ÜsÏ=$''³zõjvîÜÉàÁƒ±¶¶F£ÑÇprrâ•W^ÁÉÉÉØÇˆ kaa¡a‰r+*W–HšJnn.†ê‘Æ,/‘\òòòHII¡ÏԩЯŸ±Í‘HZŒK—.qæÌæÎ[·:°ŸŸ±M•Hš…ÄÄD\]] ugªré¬\)zRŸzJl³°¸RY i—48`upp`ñâÅôéÓ‡ßÿuëÖQZZŠR©ÄÇLJéÓ§sÛm·–&™Ê «>`MJ‚³gaÊ!m-‘´qÊË˱··Nÿünnr¤¤]’““ƒ««+f'Ê2GI»E¥R±iÓ&¦M›†{m=Úqqp䈘·mffl“%’&EçÎQÖæŸ;9Áòå¿‘×ÿ†F5·988pçwrÛm·¡V«Ñét( ”J%æææh4BBBèÑ£G«^Òjµ¨Õjì*‡^ïÚe8›I"iã_Y¬¨€ï¿‡ºÊi$’6Lff&¶ff(ŠŠd ˜¤Ý’‘‘Á¥K—xúé§k~BI ¬_cÇJ­I»áøñãÕç¯&%Á¦MBí×É j˾JÚ-N/*•J,,,°±±ÁÖÖ½Šp^^O<ñÉÉÉÆ>>JJJÐjµØT ,ÅÄ@ïÞ2`•´ 177V• rsE†U"i‡$&&â•…bÛ6c›"‘´999899a]›ÒûáÃÂ7Nú3’vN§ãÒ¥KôèÑãJ |E|ñØÙ‰q5’’Y’Ójµdgg£ÑhŒ}|ÄÆÆââârE°@ö=IÚÉÉÉøøø\) ~䩌'i·DFFÒ?) …³³±M‘HZŒS§NѧOC1½ªŒ!~ä´I;áÈ‘#xzzâíí}ecl¬ðkþóYö~sC4p&&&Ò¹sç+Æ“³)%íŠÜÜ\:TŠ,ÙÙ‰9|I;%;5•N0p ±M‘HZŒ¨¨(ºuëVýµZŒ¯±±‘Áª¤Ý Óé8vìC† 1| [7X´HN=¸Á¹!Öììl±Z£ÑÀ… ¢ïC"iGdddˆ±MÅÅB„C"iÇ$edà±q#tìhlS$’!??Ÿˆˆú]] ¦ÓÁï¿Ã§ŸÛD‰¤Y)((àìÙ³Œ5JlÈÌ©¦¦²XÒ°€U§ÓQVVFiii?eeeÆ>.ÒÒÒDö©°P\äóòŒm’DÒ¬äåå Q±ˆØ²ÅØæH$-Fll,¶¶¶¸Êy“’vÌ™3gðóó«>0'Gˆêal%’f%==+++ìíí…ÇÚµpú´±Í’´ÔÚœœÌæÍ›ÉÍÍ­óy¥¥¥Æ>..]º„¯¯¯È¬Ê¬’vGII‰X”9{VŽj’´k¢££¨TbÆ6G"iÎ;W½4 2&M‚  c›(‘4+ÿý7~~~bºÈŽB<òÙgm–¤•Р€µ¤¤„ÄÄD²³³¯ùÜ~ýúÕ.pÉÍÍ¥°°N:‰ò‚îÝeχ¤]Q^^Nqq1®®®P^C‡Û$‰¤Åˆ‰‰a`j*¤§Ë€UÒ.)..&22’É“'WpÐ Ñ»-&%툢¢"þùç/^Œ‰‰ #G‚Ö“üKƒÖîÝ»³aÃcÛÜ rssqpp_X²ÄØ&I$ÍJRR:t D³fÛ‰¤ÅÐh4ÄÄÄp«N^^Æ6G"iŠŠŠP©T†åÀ……’Æ6O"iv~ûí7\]]éÕ«—Øàëkl“$­Œ-ÑÅÆÆòüóÏsöìYý¶ÒÒR"""ÐjµÆ>–ÉËË»¢ž*‘´C"##ñ’λä   €ÜÜ\¬g΄ªÊïI;"-- +++!¤BLïå—…FDÒÎÈÍÍeçÎÜß}BPlï^c›$i…4(`-..&""‚‚‚ý¶ÄÄD^xáÔjµ±¥FŠŠŠpqq¿lÜ(ÊÈ$’vDff¦(x÷]¨òý”HÚ%%%899a>{¶lí´[N:Eß¾}±°°víbKÓ¦Û4‰¤Ù ÇÑÑØ´ ÜÜŒm’¤Ò ’`­V[-“ªV«ÉÉÉi6ƒÞ{ï="## ¶Í;—aÆ5j)))ØÚÚBYìÞ ·ÝÖl¶J$ %77—÷ߟô* ' …‚•+WÒ±‘#:ÒÒÒ0`€XŒ9}žzÊØ‡)¹¹xñ"Ÿ}öEEEúmžžž,\¸°ºâi)ÈËÃ"=3©,12ï¼óÑÑÑÛæÍ›W³PR‰eêÔ©W6ôì ƒË9”’ëFvv6|ðúm&&&¬X±¢Ñ¾JM”••±iÓ&~øa¬þù†‡Þ½}ø’VHƒÖëÁþýûqvvÆÝÝ]¿Í¼ é„„„3ß¡ƒlà–•ÂÂB8@ÿþýõ¢dJ¥e#4t:ÉÉÉ̘1CÌö÷3Ë$#‘À©S§WÈχ·Þ‚Å‹ÁÞžŒŒ ƒ2cIû¦°°}ûö5KËDsORR‹/Öû*Ó§Oç™gž©ÕWQ©T;v ///:uêtÍ¿ñóÆ<ƒëøñÐLU•’ÖGBBGŽ¡{÷îMÚOƒV{{{ÆŽk ìèèÈ”)Sšå ÊËË0`óæÍÃ××—ÔÔT–/_ΦM›X¶lY­¯³±±¡W¯^WõþE£Ñ““ƒ£|ôÜ~» XoLLLèÚµ+IIIÍÚsÑŒ9’ùóçãààÀ‰'xûí·éÓ§ÓêP€ttt$00+++ƒíeeeXZZbš  kÖÈþ333zõêEbbb£+PšN‡µµ5Ó¦Mãî»ï`÷îÝ|þùçøùùÕY>éååE=juÜŠ (.,ÄWÎ绡èÛ·o³ ;6åååóÐCáããCrr2+V¬`óæÍ,©eÖ»B¡ÀÛÛoooÃ,,à™g @do嘲+++úöíK\\œ±M©Æ¨Q£˜?>ööö;vŒwß}—>}úÔê󛘘€sMZ1:> G‚Ÿûôádx8‹úI,´7Cÿ·¤uâââB=šì§4(`õññaùòå-vP“'OfòäÉúßœœ˜9s&?ÿü3jµºÖ’233³KÎ*‚íí…è’µu‹Ù.i]( qttl5Î<Àã?nðûĉ9xð ÿý77ß|s­Áµ……Å•Ñ5U(..ÆÌÌ Ó‚()‘ÙÕ:tè€M«9ÇMMMyçw ¶Ýwß}lݺ•ððpú÷ï_«­vvv5;:ÿ’sô(7«ÕXËëø …««k³–!6S¦L1pÚœœ¸í¶Ûعs'Ï>ûl­¾Šööö†--…0bCBBB«ª ’´,¦¦¦¸ºº’`lS X¸p¡Áï“&MâÀ>|˜I“&Õè«(•Jœœœª-¬PZ [¶ÀÍ7ƒ§'ûöícØM7AÕjI»ÄÚÚgggòóó›´ŸVSƒ ÕjILL4(ýQ*•8;;cbbR­?¶>\ºtI(ƒ/=¬#¢V«‰‰‰!77W¿ÍÔÔ4M£öM§N015…~ýdÀ*1*ååå\¸p’’ý6 u ×£ÓÑáìYzÊ'‰‘© *SSSõÛ*ut:]ýwV\ ûöéU©TäææÖ¸8)‘\/jòUÌÌÌšä«`i «WÃ-·À A\¼x‘ñãÇûP%mˆF«`DEEaff†»»;ß}÷]µÙ©Ð°VNÇ?ü@zz:¯¼ò ÖÖÖTTTpòäI¼½½5Ú&--Mô¾ZXÀ“OÊ’‰QÑét¬Y³†ððÃcjjJVVgÏže̘1*]ÎÌÌÄÓÓE@tébìC”ÜàTTTðôÓO³lÙ2ƈ…ÃÌÌL:wîÜøLpYЍ(h†—ISÐét|ÿý÷äää°råJ¬¬¬(//çÔ©Sx{{7l´Ml,ìÚÿ:îjµšÒÒÒjZÉõD«Õ²zõjÌC=„‰‰ YYYœ;wŽ &4®ÍJ©Ó:þåòåËÍ2)ArãÐà€µ  €·ß~›_ý•%K–0yòdþùçÒÒÒpww'::š’’î¼óÎj=¥uabbÂÔ©Syþùçyæ™gèÝ»7QQQ$&&òÆo4êàbcc Y§Ø"‘´fffÜzë­¼ýöÛÄÇÇãîîÎÑ£G111á®»îjÔ>óòòÄ(ss9T^btlll˜6mo¾ù&ÇŽÃÄÄ„¿ÿþ›#F0tèÐFïW¥P°ÉÔ”É2`•¦M›Æ’%Kxæ™gèÕ«‘‘‘$%%ñ¿ÿý¯a;»|ªJj4T*Uõ²a‰ä:bnnέ·ÞÊ»ï¾ËåË—qssãÈ‘#˜››sÇw4|‡QQpêÜ{/ 1]]]$Ê*‘4(`ÕétüüóÏüþûï<úè£éü›o¾™|óçϳnÝ:<<< ÔLëCÏž=Y½z5‡"&&†€€ž}öYº4"s¤Óéˆgúôé°w¯Ën®yiI#™0annnüùçŸ$$$pË-·0f̘F;(¹¹¹8::ŠÞ›n‚z(óI$-…R©äá‡&00 V«Y°`7ÝtSÍ}Mõ¤¤¼œ0`šƒƒ±Q"¡W¯^¼õÖ[:tˆØØXzöìÉ¢E‹î«\5¹ °°­VÛ`ßI"in&Mš„»»»ÞW¹õÖ[3fLÃÏM~þ:wÖo:{ö,­F{AÒ6hPÀšžžÎŽ;˜;w.>ø fffäååé·³³cذaØÙÙñôÓO3dÈzöìÙ ƒzõêE¯^½š|`%%%¤§§‹¿ÿå—0sæõyG%’:077gàÀ 8°Yö— Æ(üò H¡I+ÀÖÖ–qãÆéK‚›Íùó¸ü«@,‘´z÷îMïÞ½›¶“«ª"""èÔ©SƒªÓ$’–ÀÜÜœAƒ1hР¦í(;[T<ô~Ó™3g9r¤±QÒÆhèRjj*†áÇëû4”J%öööŽ„··7...œ>ð﨧ôôtJKKëa&‘ÔDƒV{{{  zév¥R‰›››è£û—²²2²²²p2♢¢"¬­­QXXÀðáF³C"i)222ðôô™ÕŒmŽDÒ2”—Û£>]»¢T¶šIlIÓ((*ÁÿúR†èèh|||Œm™DÒ|„‡CNŽþ×ÜÜ\¼½½m•¤ Ò »¿ŸŸìرƒ¢¢¢Ÿ£V«ùõ×_ÉÎÎfˆ ppp@‘œ,n I;#557GGHJÂI{Äߟã]»ÒµkWc["‘4¥¥¢*æßE˜¼¼<4 ~~~ƶL"i>6l€øxý¯™™™2»*i X­¬¬˜7o!!!,]º”'N––F~~>DDD°zõj>ýôSî¹ç£^x“““ÅJå»ïBLŒÑìHZNGbb"îï¼cPV&‘´´ZÔYYDœ?¯¯¯±­‘Hš®]áÕWÁÒ-r.¥¤]QVP%8{ö,ݺu3¶e’6Hƒç°<˜—^z‰>úˆ'Ÿ|___ìíí)))!))‰ÒÒRîºë.æÎ+zHÄ¥K—F‘ ®®F³C"i ***ÈÊʯOÐjõý!I»¢¤„¼×_ÇR¥ÂËËËØÖH$͇™TÓ”››‹<;ïþ€IDAT‹‹‹±­’HšÒRÑ’WåZ­¶A¯÷ c@f¦±C"©­VK^^™™™£Óéêÿb•Š¡âU\lìÃHjE£ÑMVVeee ;DZ±øöé#ÕS%­NGQQ4ØW‰ÇÁÁAΖ´Zšä« Îñ„„&NœhìC‘´LmÀÕœ?žM›6…‡‡<ðÆ ÃÔôÚ¦ªT*ºäæb#E:$­µZÍáÇټy3YYYôìÙ“x€Þ½{×ëõ& +*0•åÀ’VJii);vì`ëÖ­h4‚‚‚X°`A½ƒOmn.ñ›73õ¡‡äüUI«%,,Œ/¿ü’èèh:vìÈܹs4gòèÑ£ 4 cŠDR µZÍßÿÍ—_~INN½zõbîܹôìÙ³^¯×jµüöÛo <gggcޤЪ¼¢¢"^~ùeLMMyûí·úˆŠŠŠzí£<:û¿ÿ–ý«’VKQQ+W®ÄÒÒ’·ß~›àà`Þxã bccëõúŠŠ Nœ8Á!C¤rª¤UrñâE^ýuFÅš5kÐh4¼öÚk”••Õëõ%%%;vŒ &ûP$í„V°ž8q•JÅÃ?L@@÷Þ{/öööüwøðµ°upÀrÅ ÍÝ’VÊþýûñòòböìÙ0oÞ<òòò ©×ëݼ¼°X¶ …­­±E"©†F£á×_eøðáL›6àà`æÌ™Ã™3g¸|ùr½öa–›KG??ÌÌÌŒ}8I;v ­VËC=¤÷Ulmm9TÏÙØgΜ¡C‡øÿ;§R"imìÛ·Î;ë}•‡zˆœœœzû*çÎÃÖÖ___cŠ¤ÐªÖððpÜÜÜôs÷,,, âÌ™3õÛ©)´‘ŽôôtJJJŒmFƒÈÌ̤¨¨ÈØf´iÂÂÂèÓ§6ÿ–ôzzzÒ¹sçzß°·oç¸Z­&99FclSêF£!%%•JelSÚ,Z­–óçÏdG)//¯wÀZbbBï^0ö¡\“²²2RSSmFƒ(//'99ÙØf´yÂÃÃñððÀËË KKKú÷ï_o_%""‚©S§Ö«ÕɘTöè¶%JJJHOO7¶mž°°0úöí‹••:uÂÓÓ“ÐÐÐz½þ?þàŽ;îп¾µR\\Lvv¶±Íh¹¹¹äææÛŒëN«ºZfggcff¦?ÁMMMñðð௿þªõ5:޼¼>>úïe[@§ÓѹsgRSS[ƒ\†ÔÔTìììZý*¶N§«SEÕÆÆKKK}æª-œ3Z­//¯6q=¬j³O›²9..wwwc›Q/꺎kµZ¬­­‰ˆˆ C‡m"«£ÑhpvvnSç‹V«ÅÕÕµÍØ\QQArrr½…M]縣£#EEE\¼xŒmn½ŽÇÆÆ¦Íœ/€Þl+6PPP@PPP“öÓª¢;…BN§C§Óéÿ¯Õj Vë¯ÆÄÄDÎ1“´”J¥Á9®ÕjÑétuŽ6°³³ã0¶éI½¨¼vW¢Ñh033«sŸ›› .4¶éI½hŒ¯âîîÎ’%KŒmºDR/ã«tëÖE‹ÛtI;¥Uõ°vïÞ¢¢"}éXEE/^l%¨I}èÕ«)))zÅÔÌÌLÒÒÒä9.i( zôèÁ¥K—ôÛ¢££155•3U%톀€ õ}dåååDFFÊ븤ÝЫW/’““õšééédddÐ¥Kc›&¹AiUkpp0ÙÙÙœ;w•JEFFgΜi3½ɵ6lgÏž%--ŠŠ ÂÃÃIIIaÔ¨QÆ6M"i2&&& 6ŒC‡QTTDYY‡ÆÑÑ‘€€c›'‘4 ƒ "##ƒóçÏ£R©HOO'$$Dú*’vðaà !==]﫤§§3bÄc›&¹AQèªÖnµÞ~ûm<È!Cˆˆˆ cÇŽ¼ôÒK899Û4‰¤Éäçç³råJ²³³éÞ½;'Nœà¦›n’¥b’vC\\+V¬ÀÑÑ{{{BBBX¸p!Ó§O7¶iI³±zõj>ÌàÁƒ ÇËËKÞK$m¼¼ÊÊÊ1bݺukbaI})))áäÉ“œ;wŽîÝ»3dÈé«HÚ :Žüü|8@rr2C‡¥W¯^ÒW‘V°J$‰D"‘H$‰D­¬‡U"‘H$‰D"‘H$’JdÀ*‘H$‰D"‘H$’V‰ X%‰D"‘H$‰DÒ*15¶íFƒZ­F§ÓajjЩ長µr ¸Z­F¡P`fff Ê ÓéP«ÕhµZLLL011©öxåÌNSSS”Je³Š:hµZT*æææúý^msåß½ÚfFƒ‰‰ ¦¦¦ÕlV©Tú÷£¹m–\_t:þ¯<LLL oÊùPyÖt®5•¶[XXÔxLײ¹¦ïe¥ÍÐ2ßKÉõåêsÜÌ̬Ú5¯!çÃÕߺîÍAåý§ª°USÎákÝ$mÊó¡Ò׸úš×”óáZ÷€æ ¢¢¥RYÍ¿ªÍ?ªÍuÝ$mÊs¸ÒרzÍkêùp­ëiS©<—¯¾÷\í{Õf³R©¬1¾hI›¯72`m"ÙÙÙ|÷Ýw=z”ââbúõëÇC=„··7iii|ýõל:u gggfϞ͈#033C«ÕrîÜ9¾ùæ._¾L÷îݹ÷Þ{éÙ³' …‚ŠŠ þúë/¾ùæ***>>”––²cÇvïÞ‰‰ ÇgΜ9XYYû£’4’cÇŽ±sçNÂÃÃqvvfúôéL:kkkT*•þ|ÈËË#88˜»ï¾[/--eÛ¶müú믘™™éÏKKK222ؼy3§NÂÉɉ»îº‹Q£F5›jrYYŸ~ú)jµšgŸ}çý™3gؼy3éééôë׻ロ®]»ê_óÛo¿±mÛ6@Ì\¼ï¾û°·· 77—Í›7sìØ1˜1c'NÔß$m‹òòröïßÏ/¿üBBB]»vå–[na„ €8vïÞÍŽ;P( :”9sæ`kk 4Í'h y饗˜ø —/_fÛ¶mÜtÓMØÚÚÂÊ•+™4i'Nä×_%**Š›nº NÇ?üÀO?ýÄìÙ³ñóóãÛo¿ÅÆÆ†=z4ËJ`||<+W®$??ŸûÎsÏ=Gyy9<òˆ~ÑièС899qñâE–/_Î!C¸í¶Ûøã?8sæ 'Nà—_~áË/¿dæÌ™ôéÓ‡ï¿ÿ…BѬšäú‘’’ÂÓO?££#=ö–––lܸ;;;úôéÃ… X¾|9ÇgÆŒìÙ³‡ÐÐP½³¿cǾúê+î¸ãzõêÅwß}‡©©)½{÷F­VóÖ[oqáÂæÍ›‡••_~ù%Ý»w§S§NÍrŽ}úpçwrøða:ÄÔ©SQ*•üñÇlذÛn»àà`~úé'ÊÊÊ B«Õòá‡rìØ1æÎ‹££#_}õ;wÆÇǧM¯Ðߨ=z”•+W2jÔ(î»ï>øöÛoéÛ·/üþûïüßÿý·Þz+AAAüôÓO”——Ó¿´Zm“|‚¦¢R©Ø²e ß~û-C† ¡OŸ>èt::Ä{ï½Ç´iÓ6lÛ·o';;›Áƒ£ÕjùüóÏÙ¿?÷ß?îîî|ýõ׸¹¹ÑµkWT*‹/¦¤¤„ ——Ç–-[à•´´Z-ß|ó ›7oæÎ;ïdÒ¤Iœîºë.\\\Ðh4|ýõ×üòË/ÜsÏ=x{{³eËéÖ­*•Š—^z‰ÌÌLæÏŸZ­fÓ¦M 0WWWY²d ={öä®»îâèÑ£ìÛ·iÓ¦µÙE™amyyy¨T*¾ùæ&OžLIII“|‚¦râÄ öìÙc°M«ÕòóÏ?̼yóôÛ?þøcf̘‰‰ {öìá±ÇÓûf‰‰‰lß¾#FpæÌ²²²X³f ½zõ"88˜'N°wï^}‚¤í V«ùí·ß¸çž{ô ÓýúõãŽ;î $$­VËÞ½{yüñÇõúøøx¶oßÎðáÃ9yòd£}‚4Év­VË?ü@dd¤Áö´´4vïÞÍœ9s˜5k™™™lß¾Q£FI||<¯¿þ:AAAÜtÓM9r„ß~û^½z±gÏìííyüñÇqrrÂÅÅ…'žx‚Ó§O3tèPcdB¦š€R©¤_¿~ T=‡ÝÝÝ133#55•ÒÒRrrr ÷óó#33“¢¢¢&Ù}þüyöìÙ£/ìJjj*zgÞÌÌŒÎ;Øìää¤?æ:`ccCbb"dffØÜ¥KòòòÈÏÏ7öÇ%i3fÌ`Þ¼yúҮ˗/óÇ0zôh@œÎÎÎúÇ]\\°¶¶ÖŸYYYÕÎ᜜ ÈÉÉA¥RU»ÄÇÇ7Ùî]»vÏý÷ß_­·499GGG½@££#NNN\¾|FCzzºÍÞÞÞ“M~~>%%%µÞ$m… 2aÂý}ùðáÃ\¼x‘‘#G¢V««>>>’““ÓdŸ ±TVyzz2iÒ¤jb3)))6{yy¡R©ÈÌ̤°°üüüjßËÔÔTÊËËIKKÃÜÜ\055ÅÛÛ»É6KŒƒ¹¹9o¾ù¦~a½¢¢‚­[·biiI@@T;RRR¨¨¨h’OÐ233Y»v-3fÌ0Hlˆ'òòòªÙœžžNII (•J}Ù½B¡ K—.z›“““qppÐ/´:88СC‡6}ŽË’àf ¢¢‚ .ðÉ'Ÿ˜˜ÈË/¿LçÎk}þµnúu=^© ÖXJJJذa=zô`Ò¤I„……Õëu×ú›-i³Äøqüøq>ÿüslllXºti,M9´Zm“²OÉÉɼ÷Þ{Ì;—Þ½{sòäÉz½îZß˺lÖh4hµÚFÛ,1>ÙÙÙüþûïüøãôéÓ‡¹sçÖùükÃuM ütÿÏÞyÇ×tþü}ïMr³§ìˆ‘H±Wmj—Ö(¥Tµª¨j}UíR³vi­¢FQ{ÔÞ{…‰²Eö¼¹ã÷Çùå‰28ï×˫͹çžóœsŸóœÏþèt\¿~M›61lØ0±PÒËð¼ó¾hÌÒ^ú¹wïÛ·ogûöí´oßžF‘˜˜X྅…™ãZ­–ƒrýúu¦L™òÒEør=jÏóóÞ-’A¦t£Ñh cåÊ•3dÈ|}}‰‰‰yæþ…™…Y5 Ë—/G©TÒ¹sç—Ž*{‘|Tý¢¤#)¬…$''‡¥K—Š9KC† É>Y¹Vœ×ù\OO¯P9DgÏžåôéÓôîÝ›ˆáÅû÷ïÏgáyccãçæ[=oÌr¹\ª ZŠINNfúôé\¸pöíÛÓ¾}{1|òY¼h>¼èð<ÒÓÓY¼x1666ÄÇdzgÏbccINNæÀÏÍOzÞyõõõQ*•dggø¹‘‘‘Tp©”¢Õj9sæ ¿ýöÆÆÆŒ3†*Uªúè#œœœ033#22R  ÁÍÍ …BAùòå9uê)))˜››“‘‘ÁíÛ·ÅB¹×¤ÓéÉd%J :”:uê0eÊ”|‚xî|Èí1EJJ ®®®áêêÊýû÷Åü§lll°°°ÀÉÉ ¥R™ïàééùÚÊŸZ­ÆÔÔ”¸¸8V¯^ D ëׯÇ××—òå˃J¥ÂÀÀ€¸¸8bcc©Zµ*úúúxzzrÿþ}±Þõë×111ÁÚÚFƒ¹¹yï€Â’$Š£G2iÒ$¾üòKZ·nR©矾¾>Ü¿___®]»†©©)ÖÖÖ˜˜˜J&x²²²°µµåæÍ›Ü¼y 5§NBOO²eËâããÃýû÷©]»6 ôôô°µµÅÌÌŒ2eÊä{.Q*•xyyFbb"VVVäää*¾$JZ­–eË–±cÇÆŒ“§æ!¼666:ŽK—.qýúuH™2eP©Tâ×étqïÞ="""Ðjµ$&&råÊ•|s8×bxíÚ5T*XYYáããñcÇÐh4h4Ž;F¹rå ÕkøóÏ?Ï3ÇÛ·oƒƒ³fÍÂ××—ÀÀ@âââ¸}û6Z­–ôôt.\¸gŸ?žÌÌL´Z-·nÝâÑ£Gabb‚ŸŸ_ž1?~www\\\Šû'“xEt:»víÂÜܜ޽{£P(ÈÎÎ&++Kô4V¯^³gÏ’••…V«åæÍ›b?VSSS|}}ó̇£Gâé鉓“ÞÞÞ(•J±Reî; N:¯­°š››óý÷ß3{ölqŽR«V-&Nœˆ­­-Õ«WçòåË$''£Õj¹ÿ>< víÚP¹reŽ?.ŽùÌ™3ØÚÚâé鉫«+666œ>}:Ï; ((Hª\ Ñétüû￉ÂjîÏÉÉÁÐЀ€€<óáôéÓ888ˆ­k #¼îîîŒ?^œß³fÍÂÒÒ’.]º0hÐ ,,,¨V­š8f­VË… 011ÁÇÇGGG\]]9~ü¸&|üøq*W®Œ™™ÄÇNjŒ Ο?_¨1K*•ŠuëÖѹsgÑh4ydq'''œœœ8qâDž9ˆ©©i¡d‚×%000ÏüÎí0:|øpºté‚££#^^^ùä#___¬­­ñóó###ƒÐÐP´Z-999œ:u*~"¾œòåËóßÿѪU+<<<øì³Ï7n™™™€Ò5zôh¬¬¬°²²¢C‡Ì™3‡ëׯ‹E:tèðÚ «\.ÏS1„ðM¥R)F*4iÒ„={öðÓO?Q¹reöîÝK“&MÄŠ’=zô`ôèÑŒ=###Ž9Â!CÄÝ»wgÁ‚ܾ}›èèhâââøæ›o¤°÷RHBB¡¡¡„‡‡³aÆ<ŸuêÔ‰I“&Ñ£GÆŒØ1cP*•=z”¡C‡Šó¡02Áë §§—o=•Ë嘘˜ˆs¿[·nüüóÏüôÓOXYYqðàA¾øâ 1’áóÏ?gêÔ©„‡‡óèÑ#nÝºÅØ±c144ÄÏÏzõê1aÂZ´hÁùóçñðð aÆÅýsI¼‘‘‘Ü¿Ÿ &0a„<Ÿ?ž.]ºÐ«W/f̘ÁÝ»wyôèwîÜaìØ±(•ÊB˯ƒ(“bUz Q†éÓ§'N$&&†´´4BBB;v,&&&”/_ž&Mš0eÊš7oΕ+W°··ûÅ7jÔˆÿþûŸ~ú‰ÀÀ@öïßOãÆñññ)îŸëµ‘é [[ÿ=æÑ£Gb¸ÊÓT¨PKKK2339xð çÎÃÞÞžæÍ›ãîîŽ\.G§ÓÏÿýÇÍ›7 ¤Aƒb•]­VË;wغu+ééé4hЀ5j¼Ñ|ÐÔÔT®^½JPPî¥R©8tè§OŸÆÚÚš¦M›âãã#†‚>zôˆ}ûöqõêU|}}iÔ¨vvvÈd2t:<`Ó¦M$&&Šc–rCJ:Žû÷ï]àçAAA( سgׯ_ÇÏÏFakk+Îለ6nÜHrr2 4 zõêâ|Ðjµœ>}šÃ‡c``@ƒ ¨R¥Êml+p?éåOJJbÿþý\ºt š6mŠƒƒƒ8‡£¢¢Ø²e 111âÎU¢µZ-ÁÁÁìÛ·™LF½zõ¨Q£F©mÆý>£V«¹uë–˜?ô$FFFT®\NGdd$[¶l!66¶ÀùpáÂ8€L&£~ýúT¯^]œ™™™:tˆ³gÏbggGóæÍñððx# çs¹qã …B ÃÔétÄÄİmÛ6"""¨]»6µjÕ•­VËÕ«WÙ½{7jµZsn!5•JÅáÇ9}ú4VVV4iÒ„råʽÑ1K ÙÙÙb¤ÓÓØÚÚâííV«+«kµZq>ä( #¼).\¸€‹‹ vvv€0‡oܸÁŽ;ÈÊÊß-¹yFÃáÇ9yò$fff4nÜ___qÌIII8p€àà`Ê–-K³fÍÄw€Dé"--+W®ø™——vvv¨Õj>Ì©S§077§qãÆT¬X1Ï|x]™àMÍÅ‹ sc5 'NœàرcñÁ Ž955•ƒrþüyÜÜÜhÙ²%NNNâ˜s{¹æ¶¬]»v©6¬K «„„„„„„„„„„„„D‰D2—JHHHHHHHHHHHH”H$…UBBBBBBBBBBBB¢D")¬%Ia•(‘H «„„„„„„„„„„„„D‰DRX%$$$$$$$$$$$$J$’Â*!!!!!!!!!!!!Q"‘V ‰‰¤°JHHHHHHHHHHHH”H$…UBBBBBBBBBBBB¢D")¬%Ia•(‘H «„„„„„„„„„„„„D‰DRX%$$$$$$$$$$$$J$’Â*!!!!!!!!!!!!Q"‘V ‰‰bìØ±c‹{ï;ìß¿Ÿ•+Wr÷î]<<<044D&“‘••ÅöíÛùçŸÈÌÌÄÀÀ€P¦Lär9iiiìÝ»—+Vp÷î]111!))‰°°0²³³Y¶l¤L™2( Ö¬YÃæÍ›pqqA¡PFJJ —/_fùòåDDDàììLXXÿý7ÇŽÃÛÛSSSd2Yqß2‰w„«W¯²aÃÊ—/R©,îáHH ÁÁÁlÙ²… *```PèãíÝ»— .àççWÜ—&ñž£ÑhÈÎÎF¡PH²‚Ä;‹N§#''µZžž^qç½@¦ÓétÅ=ˆ÷™¤¤$~úé'>L½zõ¸sç†?þøggg&OžÌš5khذ!·nÝ"++ ccc6oÞŒ¾¾>½{÷&44” Ftt4+V¬ &&†P¾|y¼½½ ãÎ;øøøàää$*ºëÖ­£yóæ|úé§„……áî­-;vìÀÇÇCCC\\\¸xñ"&&&¬[·;;»â¾mïÛ¶mcÚ´i¬]»''§âŽ„D‘°nÝ:.\È?ÿüƒ­­m¡7vìXîß¿ÏÒ¥K‹ûÒ$ÞsNž<Éï¿ÿÎo¿ýöFæ¶„DID­V³páBâââ?~|qç½@2 #:ŽpèÐ!–,YBõêÕILL¤mÛ¶œ:uŠråʱ~ýz/^L:uˆŠŠ¢C‡‚°Æ‚ ¨S§ôïߟ%K–кukär9ýúõ£cÇŽDGGãââÂçŸÎ?þHBBÝ»wçÒ¥K4oÞ¥RÉâÅ‹177ÇÞÞžE‹±}ûvØ»w/?þø#QQQ’Â*ñÊhµZRSSÉÌÌÄØØssó<Ÿët:âããQ«Õ˜™™all,ZçµZ-ÉÉÉdeeajjЉ‰ r¹N‡J¥B¡P••EZZÆÆÆ˜™™‘™™Ijj*zzzXYY!“ÉÈÎÎFOOÌÌLÒÓÓÅq¤§§“––†¾¾>–––ÈåR¦„Ä›!wîfggcbb‚™™Y¾ÏãããÑh4˜™™add”gÞ'&&¢R©Äg"wÞ?9—srrò7×Ëehh(Íg‰·‚F£!11Fƒ¹¹9FFFh4"""8vìÉÉÉX[[£ÑhÉdh4RRR°³³#''N‡N§#)) ===,,,Ðét¤¤¤ V«±´´D©TŠûæ>Kúúú˜››£ÕjIIIA£Ñ`eeõF"$$ "++‹ääd èëë£R©¸rå dgg‹ÛôõõÉÈÈ@­Vcee…N§#==ôôtôôô033çªJ¥B&“¡R©HMMÅÐÐsssT*)))ØØØ P(Šû”$…µÑh4œ:u ___j×® €­­-üñÆÆÆìÚµ 6l€»»;|ð—.]àÀ8::’™™Éþýû(W®‡¦uëÖ”)S†*Uª —Ë)S¦ uêÔA©Tbff†££#Z­VO5°²²ÀÊÊ 333ªV­ €§§' …É!/ñ:lܸ‘¥K—rïÞ=*V¬Èwß}'Îùììlþùçþý÷_’’’¨S§?ÿü3îîîdgg³mÛ6þøãÂÃÃñ÷÷§W¯^´k׎ÌÌLæÌ™ƒƒƒ»wïæÒ¥K”-[–Aƒ±qãFŽ;†……?ýôµk×fÞ¼y¸ºº²cÇ®\¹B… 8p «W¯æôéÓØÚÚ2räH5j$ ù…F­V³nÝ:–-[Ftt4 2„   @‚–-[ƦM›ÈÈÈ AƒŒ5 233Ù¸q#þù'111Ò¯_?š6mJJJ sæÌ!00 6`bb’Lj¨V«Y¾|9qqq 4“â¾ïééé¬\¹’åË—“žžN½zõ4héééüõ×_ÄÇÇ3eÊ~üñGŽ=ŠR©äÒ¥K>|˜Ó§O³wï^®]»Æ£Gعs'ôëר¨(¶mÛFrr2;vdÔ¨Qlݺ•ˆˆÂÃÃÙ»w/eÊ”¡ÿþܼy“;w’‘‘A·nÝøþûïÑ××/î[#ñŽÅôéÓÙ·offf4kÖŒ~ø­[·rèÐ!222˜>}:={ödÙ²eT«Vþùkkkf͚ʼn'˜7o!!!X[[Ó¦M „¡¡!‹-B©TrüøqΜ9ƒ««+ àØ±c¢LÿÝwßÑ­[7IiE*ºT¬èt:222pppȳ½råÊøøø—OØÈµÌ¤§§ÇÍ›7™:uªøïâÅ‹”+WŽœœôõõ_Éê( 6oƒ#GŽðÃ?иqcÖ­[G… 0`QQQܺu‹3gÎ0þ|,XÀ‰'X³f äæ5ŠŽ;²mÛ6¼¼¼:t(ÁÁÁäääðßÿ1þ|zöìÉüATTß~û-þþþ¬X±www~ûí7"##Ù¹s'‹-â‹/¾`Þ¼yܼy“ÁƒS·n]V¬X¥¥%³fÍ"55µ¸o™Ä;ÀÎ;5j:ubÍš5”)S†¯¾úŠäädBBB¸qã‹-bÚ´iìÛ·-[¶‚ç—_~¡oß¾lÚ´ [[[¾ûî;®]»FFF;vìà×_ÅÃÃ=zˆçÌÊÊbîܹ¬\¹’ `ddTÜ·AâäÏ?ÿdæÌ™üïÿãï¿ÿ&::š!C†P¶lYÚ¶m‹¥¥%½zõÂÙÙ™cÇŽ1zôh²²²6l ÌýÉ“'cccúuëðõõeàÀÄÆÆ2{ölúôéÃßÿÍÙ³g¹pá“&M¢lÙ²lذggg @FFóçϧ[·n,[¶L4äKH¼)’““ùᇸ~ý: .ä§Ÿ~bûöí,X°€† „={öD«Õ²}ûv&OžŒ··7Ý»w'33“¡C‡bkkËš5kèÕ«Ë–-ãÔ©Sá—_~A¥Rйsg1ÞÏϵZM×®]122â£>â?þ@­V÷m“(ådgg³råJÚ¶mË矎R©dذaÄÄÄ””€½½=ƒ " €²eËR³fMqÞ/X°€Î;Ó£Gär9ãǧcÇŽìØ±CTPkÕªÅèÑ£Q(ìÙ³FÃ_ýÅâÅ‹™;w.uëÖ-îÛ ñ’‘‘Áš5kèß¿?mÚ´A¡P0räHfΜ‰N§ÃÑÑ}}}ÜÝÝÅô%+++¦NŠ¡¡¡x???zõê…­­-ü1üñßÿ=ÎÎÎX[[óÏ?ÿˆÆÊ•+Ó£GÌÍÍéÔ©ëׯgذaØØØ`jjÊ¿ÿþ+†PJH¼)îÞ½ËÁƒÙ¶mÕªUàÑ£Gܼy333,--IMMÅÍ͈ˆêׯϨQ£P(¤¤¤pñâE~øáüýý)[¶,žžž8;;‹çhР;w iÓ¦DDD0`ÀÌÍÍÑh4ìÞ½›ÌÌÌâ¾%Ia-F Mš4aûöíìܹ“jÕªͤI“øñÇ©S§¿ÿþ;«W¯¦I“&„‡‡³gÏ\]]APÿî»ïعs'5kÖ$**ŠÁƒÓ²eKüýý‹ûò$$HMM%<<œnݺ‰Þ–,Y‚áááØÛÛãîîF}}}´Z-™™™Ü»wÔÔT¾þúkñ˜899‰áì^^^yÎill, JO{˜žÞ×ÄÄDÜGòFI¼)‰¥S§Nbõkþúë/”J%gÏžÅÕÕU,4&“ÉÄJ“éééÜ¿ŸS§Nѯ_?ñ˜±±±ÄÅʼniuëÖÍ&ößÿFjjªTUâ­CNNUªTç_•*UX´hQ…ôIjÕª•/ÚËÉÉ)ßš››º¤¯¯Ÿ§òª««k¾ïÛØØBí )\Râmp÷î]œœœpss·uëÖ µZýÌ9÷äºlhhÈ_|Á˜1cøë¯¿¨[·. 4Ès)ÔÈåò<ó^&“8ï5 zzzä1<Ö¯____ñï§S8\]]™3gS§NeÚ´iÔ¨QCJóxãèt:d2YžµT¡Pä™ÛOSàý*‚¸$´KZ­6Ÿbª¯¯¾¾~Åî ïºl``ÀäÉ“ æØ±c>|˜… 2uêTºtéHsûU¤·bÆÄÄ„)S¦°sçN¾úê+þúë/V¬X™™™Ô©S‡;w2`À–,YBùòåñðð-üñ[·nå³Ï>cîܹü÷߸ººÒ¢E :$† R©hÔ¨‘xÞ•+WŠ9%+V¬`ܸq⸠”Gé-_¾<çÎ#00°¸o™D)ÂÌÌ www>Lvv6€h”Ù³gÏ ¿[¾|y¬¬¬èÑ£½{÷æ£>âÎ;¤§§KʧD‰ÅÒÒ;;;Nœ8!†£ß¸q???Ξ=ûÜïš››ãåå…Ÿ}ö½{÷¦}ûö„……‘™™ùL' €êÕ«3fÌ¢¢¢X²d‰Þ.ñƱ··G.—sñâE1ÊåÈ‘#TªT‰÷ð$$Þžžž„‡‡‹õ6´Z-óçϧM›6/‚~ûöm¾ýö[\]]1b[·n¥M›6¬^½º¸/­T"yXKzzzøùùåkúþàÁ†θqãhݺ5aaaœ>}šAƒ‰Õðäryß}ÚšjùäßOZŽž¶"Éåò|ß—š#K¼*J¥’ž={Ò«W/¦OŸNýúõù÷ß‘ËåT¬X‘àààç~¿G|÷Ýw8::RµjU6oÞ̆ èÚµkq_š„Ä3122¢{÷î 6 WWWªU«ÆÊ•+177ÇÛÛû…E4zöìÉøñã±³³£\¹rüóÏ?}ú<÷{2™ ___>ûì3,X@›6mò…ÁKHSSS:wîÌ¢E‹°¶¶ÆÍÍ©S§âíí““ÁÁÁdggóðáC©«D©ÆËË‹Zµj1f̾øâ ’““Y´h}ûöÅÌÌ ¹\NZZ>D£Ñäû¾©©)»wïÆÚÚšO>ù„èèhN:EÛ¶m‹ûÒJ%бcÇŽ-®“?zôˆÐÐPÅmZ­–píÚ5233±°°xo=)666(•J¦L™ÂÚµkÙ¶míÚµ£_¿~RϱR‚V«åÂ… ‰ù:†°°0nß¾ ‹Ú»âé鉭­-»víbãÆ0~üx*V¬ˆJ¥BOOZµjahhˆN§#-- WWW*Uª„——...¬Y³†õë×0qâDªW¯ŽN§#55•*Uªˆ‘ÉÉɸ¹¹‰­CT*r¹œZµj¡V« ÂÞÞ€¤¤$¼½½Å¨ììl Ì·’x6ééé\¸pGGGq­ÎÊÊâòåËDFFb``§¿èûBÙ²e±´´dË–-lÞ¼kkk&L˜€§§§Ø#µFbŽkZZÞÞÞ”/_ž *`ggDzeËØ¼y3J¥’_ý•€€´Z-éééT¯^]lg“––†½½=•+WF.—S¡B±/ñ“áó¯G||3™ÿ]G«ÕAZZ&&&888ˆŽDÉF§ÓqåÊ Ào¿ýFõêÕÉÌÌdÅŠì޽Ğ={ÒªU«âî[E«Õ’˜˜HZZVVV¯¼øÆÅÅ‘žžŽ´p— t:ëׯgÖ¬Yìß¿###âãã™?>.\@¡P`iiɰaÃòä_¾/hµZ=zDFFÖÖÖ˜™™½Ò÷cbbÈÊÊÂÆÆæ•¿+ñfÈÊÊbæÌ™\¹r…U«V‰Û7oÞÌš5kP©T( Ú¶mK—.]ÞYE£Ñ‹Z­ÆÎÎN¼îÜ9Ÿ••…½½½dü+<|ø1cÆàììÌÈ‘#ÈÌÌdùòåìÞ½™L†‘‘Ÿ}ö-Z´(îá9YYY<|ø}}}lllÄhEµZMll,zzzØÚÚ>Ó`•œœLBBÆÆÆØØØHÑŠ¯I±™9ÂêÕ«óÄGGG3kÖ,>øàÖ¬YàAƒX¼x1/^,îûTlÈårÜÜÜðõõÅÝÝ]RVK±±±LŸ>¸¸81—ìüùó¬\¹’o¿ý–Õ«WS¯^=¦NJBBBq÷­"—˱±±ÁÝÝýµN;;;<==%eµ„Êï¿ÿΣGAXý÷ß9sæ Ó§OgñâÅØØØ0gΜ|-ºÞär9¶¶¶¸»»¿–Âéàà€‡‡‡¤¬#‡bíÚµÊ*Mš4aÍš5 0€E‹qùòåân‘¡P(Ä ªO*é¹s¾ Ê¾%“åË—søða²²²ÄmgΜáï¿ÿæ»ï¾cõêÕÔªU‹iÓ¦‰íèÞ' quuÅÁÁ!OjžžÎÎÎb^÷³°°°ÀÓÓ{{{IY-E®°êt:BCCYµj5kÖÌóÙÙ³g±±±¡]»vb¸”¿¿?GŽ)îû$!ñJ¨Õj–.]š'„ àØ±cT­Z•š5kbhhH›6m°°°àÌ™3Å=d ‰WâáÇ̟?_ìO‚ÂzôèQZµj…ÖÖÖtéÒ…ÈÈH1^B¢4 Óé¸~ý:k×®ÍS¥aÞÎÎŽ6mÚ`hhH­Zµðóó“d‰R…V«åرc„„„àáá‘ç³cÇŽDõêÕ144¤mÛ¶˜ššJ²ŠD±Qä «V«eñâÅ¢Ðþ$aaabuE*ÛV¨P+W®÷}’x%N:Åõë×ùâ‹/òl¿zõ*ÞÞÞ¢EÚÎÎiŽK”:6oÞŒAžZ­–ëׯç ÿ-W®ÙÙÙRQ‰R…Z­fñâÅQ£F<Ÿ…††bee%R*•’¬"Qꈉ‰aáÂ…ôéÓ'ŸÂš+«äFõÙÛÛcggǵk׊{Øï)Eê›V«Õ¬Y³†ÌÌLºvíʶmÛò|žžžŽB¡]î … >|øÌcj4þûï?îÞ½KÙ²eó¸ëK2”ªð€ÌÌLôôôJÅ=ÖjµÄÄÄœœL«V­ò5g~›„††2oÞ<±œù“¤¦¦b`` †ŠyÏ"==ÿý—ììl\\\JE˜•V«%33³T5¾Öétddd`ddT*Ч¨ÕjdÙ²e¸ººŠFù’NNNjµ:Ïó\ÒQ«Õ¨Tªçö…-IdggFåÊ•iܸq‘W¥R1wî\|}}©[·.ëÖ­Ëóyjj*J¥R\‹ŒŒ044|®¬rãÆ ¶oߎ——W©IcÈÉÉA£Ñ”ªÜóÜ¥%E0))‰ˆˆš4iB¥J•^û8Eª-]½z•þù‡iÓ¦½Ò‚ý¼ºPZ­–¨¨(œœœppp(‚9¼eË–-UeßO:…ƒƒNNNÅ=”—ÂØØ˜àà`>|Xd kNNË–-ÃßߟZµjXê¼ ž7Ç333‰ŽŽ¦V­Z˜››çkATÉÈÈàâÅ‹4nܸT(Ø ¼.]ºDíÚµ155-îá¼­V‹¾¾>çÎ###£ÈÖ„„-ZD×®])W®ÜK…ˆétºçÎñ””222 Ä¢ÈîaaˆçÖ­[4mÚ´¸‡òÒ$&&réÒ¥RU8%===OOð¢ $$„ 60mÚ´WzG?oŽçÄ<<õë×/†””îÝ»WdçÔjµìÙ³‡0mÚ´WrœIH¼6vvvbˆi@@mÛ¶eúôé˜šš’žžÎ7ß|SªBÃ%$žD___¬I “Éh×®ׯ_çÇÄÀÀµZÍÿþ÷¿RUÔBBâILLL°¶¶ÿ¶³³£oß¾¬ZµŠ}ûö‘ššJ—.](_¾|qUBâµ°°°Èã™®R¥ ­[·fêÔ©¢¬2`À€R“-ñîQ¬ k·nÝèÖ­[žm:u¢V­Zܺu«ÔåÚHH<Gÿ622bðàÁ´hÑ‚ØØX*Uª”Çh#!QÚ¨R¥Jž9nccäI“¸|ù2ÙÙÙøûûK‰RͧŸ~ʧŸ~šgÛÇL:u¸uëîîîR:D©fÒ¤Iyþ622â»ï¾£eË–ÄÅÅáïïŸÇh#!QԔȞ*ÎÎÎ¥*É_BâU©P¡*T(îaHH¼ôôô¨ZµjqCBâ­"É*ï:+V”¢%J¥£Œ„„„„„„„„„„„„Ä{G‰ô°J¼:•J…2™¬¸‡#!ñÆINNF«ÕbiiùÌ9~ÿþ}âã㉉‰ÁÁÁAòðIHHHHHHH¼H ë;@HHK–,aÀ€RщwŠýû÷³ÿ~îܹƒN§cÔ¨Q6žNLLäûï¿[Q<|ø+V÷ð%$$$$$$$$ ‰\BÉÈÈàŸþ!,,ì™û¨ÕjV®\ÉØ±cñôôdÒ¤Iœ;wFSÜ×x&†k×®1|øpš5kÆÁƒÑjµî7þ|jժł 6l¿üò K–,!;;;ϾgΜÁ××—É“'3iÒ$LLL¸páBq_ª„„„„„„„„D!‘<¬%„„fΜÉŋٴisæÌÁÖÖ™L†N§C«ÕrãÆ V®\Ill,“&MÂÇLJsçÎ1aÂ~úé'jÖ¬YÜ—!!‘NG\\«V­âìÙ³|øá‡´nÝšY³f¡P(¨_¿~žp߸¸8d2­[·F¡PP½zuÆÏܹs166¦k×®â3BåÊ•Ñ×× M›6lذ€€ôô¤eNBBBBBBB¢´"IrEŒZ­F§Ó‰‚õ“h4˜>}:>>>lݺ•Ý»wóÓO?1nÜ8ÒÓÓ9qâ@OOV­ZÑ©S'ärÁQ^³fMFŽÉ‚  B¡P÷åJ¼gäÎaGGG¬¬¬ÄíÑÑѬ\¹’S§NѲeK–/_.ö¦µ¶¶fĈ( êÖ­+~çþýûøøøä™ÇåÊ•cäÈ‘ :”?ü RSS¹zõ*Ý»w÷kÖ¬ýõwïÞÅÇǧ¸oË3ÑjµäääHùçÏ@RX‹­V˯¿þŠ\.çûï¿ÇÐДØèèhÖ¬YÃéÓ§éÖ­­ZµB.—Ó¬Y3®\¹Bÿþý±±±!00!C†P¡BŒó£råÊh4nÞ¼ù¶)Z­µZ €L&COOOš%^­V˱cǘ4i... 0___BBB˜5kµk×fΜ98::æQB}}};v,óæÍ£víÚ¢&666Ò›‹••æææDEEaaaArr2yž===üýý9{öl‘)¬çΣL™2¸»»¿Ôs¤Õj9tè7nä—_~ÁÒÒ²HÆ)!!!!!!!QšÖ"ääÉ“\ºt oooFŽÉÿþ÷?Y¿~=ÁÁÁ4k֌ŋçÒõôôøî»ïèÔ©®®®zfŸD©TR½zuΜ9óB…õôéÓ¬Y³†œœLLLhР­Zµzá9 âöíÛ˜ššboo_Ü·Yâ £Ñh8zô(öööÏìǦÓé8zô(óçÏç·ß~ãáÇLž<KKKÔj5#GŽÄÏϯÀïÊårªU«Frr2111899Y`C}}}Ê—/Ï™3g¨X±"·o߯ÚÚ“<Çlݺ5‹/Îãy}[$%%1iÒ$ŒŒŒ˜9s&vvvÏÝ_§ÓqöìYþüóOt:¤cÇŽâgwïÞ¥L™2˜››¿õ±KHHHHHHH”d¤¢Ko€Í›73{öìç;ŠŒŒdΜ9Œ;–ñãÇãêêÊ!C=z4vvvÌš5‹¾}ûèQÒÓÓÃËËë¥ÉÚµksîÜ9233ÅmOþ?@vv6ëÖ­£víÚôíÛ—–-[²gÏ~üñG.^¼øÒ…›ÒÒÒØ¸q#ß|ó üñ999ÅýsäA*@Uxâââ=z4Ó§OÏ÷ûêt:222¸xñ"Ë—/gøðáøùùÑ AæÌ™Cûöí™1cÆ3•Õ'qvv&)) ~·ˆˆˆd¹\NíÚµ¹xñ" ^üýýó=¹Õ„O:…N§{åëNOOçÈ‘#ìÝ»—´´´çî{ìØ1ìíí bîܹ¨TªçîÂôéÓ6l£FbÆ $$$Bøtÿþý™1cF‰{ž$$$$$$$$ŠIa-$ ,X°€íÛ·ýÌý6mÚ„¿¿?åË—G©Tòí·ßòÃ?ðÇЯ_?œßXΩ««+™™™¤§§‚Â1~üx"##Å}âããyôèÍš5#((ˆ¦M›2wî\jÔ¨Á´iÓX±bE>%÷I´Z-!!!Œ;–#GŽ0fÌ®_¿. Ýo“pðàAnݺ%^ãÓ<|øÿý—µk×’••õÖÇô.³råJÚ´iƒV«åäÉ“âvFÃÅ‹1bþù'_~ù%UªT¥ÒÑÑ‘6mÚ`mmýRç177'66€¬¬,RRRž&@TT111\»v __ß|û(•J>ùä-ZDJJÊ+]shh(?ÿü3Ë–-cÓ¦MüðƆ>sÿÝ»wÓ¹sgzõêEll,[¶l+?­ìFGGóË/¿0pà@ªV­J¥J•ðôôdçÎ$''3eÊ:wîÌÝ»w9pàÀ[þu%$$$Š–œœ"##ߘAùرc¤¦¦÷eIHH¼E¤àB V«Y²d mÚ´ÁÎÎŽ?þøƒQ£F‰ÅdrrrxðàGåäÉ“LŸ>]ô) ßʸ¬­­±±±áòåË4nܘ 6püøqìììܹs___*W®,þ¯†N§ãĉ„„„0g΂ƒƒY½z5ÕªUÃÐеkײuëV>ÿüsêÔ©SèðU///Ѩ’Û¶ÆÈȨÀ}©Y³&K—.E¥R=Óƒ[«V-¶nÝÊÁƒéСCžÏÒÓÓÙ±cjµš5jàèèHtt4ëׯçÒ¥KôìÙ“úõë#—Ë9tècÇŽ¥råÊ|üñÇxxxˆÕ‡ïÞ½KRR5jÔÀÌÌŒ#F0tèPV®\‰©©)zzzŒ=ooo´Z-Ë–-£~ýúâ±:wîÌôéÓIJJB__Ÿ>}úаaCƇ§§'åʕǓ“CFFF9ì% µZM|||XT $^ ­VËúõëùøã±²²¢Zµj¬Y³†+W®˶mÛ˜0aBeª08;;sìØ1T*F,LV5¢S§NôîÝû™ ¹‘‘}úôaÒ¤IÔ¯_@¨@3gΤ~ýúsþüy:wîL‡P(dff­­-–––ùæ‘L&ÃÕÕ•¯¿þšnݺ±~ýz¾ýö[lllˆŽŽæÿû_ž}Ÿ ƒîÞ½;éééŒ3†ððp¾ûî»|÷ÍÐÐ#F R©Ä¢S …‚Þ½{ãää„R©¤nݺy<»iiibذTÝ[âI222ˆ‹‹ÃÂÂssó|óùÂ… ܹs‡Î;÷P%Þ²²²ˆçêÕ«lÙ²…ÄÄDj֬ɧŸ~J¹rå044D___\«5jÄ7ß|CDD...âqt:·nÝâï¿ÿ& €¶mÛŠò†F£A­V£T*Åý£££  C‡üòË/8;;‹Ñ[%‘øøxŒ¥‰ç’““CXX³gÏF__Ÿ¬¬,ÂÃÃÅÚï#…RXÃÃÃ;v,/^$33“V­Za``ÀܹséÔ©;v|']Øjµš5kÖððáCÚ¶m+.Œ|ð«W¯&**ŠРAƒb£••fff$%%Ñ¢E  5û_–/_>O8pA( 2d}ôæææ¢‡êY´lÙ’™3g²}ûv*V¬ÈÂ… Q($&&bkk+¾˜jÔ¨ÁÈ‘#Y¶l“&MÂÓÓS<ç“Õ^4h€\.ç§Ÿ~ÂÐÐ-Zàææ–ï¼2™LRVß ýõGŽaöìÙ˜ššÂ=®Q£]ºt¡N:888¼Q¡ÀÊÊŠBž²³³ósVSSSFõB ½\.§cÇŽLœ8‘cÇŽÀÇŒ»»»8gLMM_XU„ùiccÃW_}E§N8|ø0Ï CS*•ôîÝ›/¿ü{{{j×®]à~¶¶¶ù¶éëëÓºuë÷·¶¶ÆÑÑ‘‡Js_"‡æ?þ@­VcccÃÔ©SÅ î:ŽcÇŽ±mÛ6Ia•(?~œ}ûöqëÖ-Œ)S¦ Ÿ|ò ÏmÕekkK¥J•8~ü8]ºt·_¼x‘I“&Q£F V¬XAFF={ö$11‘ßÿúöí+˜ˆ½½=þþþ|òÉ',[¶Œ_ýµÄÊž¿ýö>>>|öÙgÒºýž³nÝ:ªU«†··wží·nÝbñâÅܸqƒž={Ò¤I,XÀõë×%…õuHKKcúôéÈårÖ¬YÃÞ½{¹sçAAA|ôÑGÌ›7råʽµ<Íâ"%%…yóæqÿþ}¦L™’Géspp`ñâÅXXXä±&L@.—‹–¼ºuë²|ùrfÏžÍøñã_ú8 …BT(_DÕªU©]»6Õ«W§nݺâv|ûV«VjÕª=÷xr¹œúõ룧§ÇÑ£Gùâ‹/Šû¶¾Ódee±dÉ.\¸Àœ9sò…vëééÑ»wï·rn¬¬¬çÖ­[”-[ö¹ûëéé‰ÞßáèèȼyóÞèxmmm_Zà755eõêÕoå¾I”~t:7oÞäÆT­ZUŒÚy’œœîÝ»‡‰‰ &&&\¿~={öpâÄ &L˜@õêÕÅ}Ïž=ËàÁƒiР .äßÿeÀ€€P1þÚµk¤¦¦rãÆCú5 ÉÉÉ/]0Mâý@§ÓñðáCΟ?ÏÑ£G £|ùò´oßÿWWlß¾=óçϧM›6(•Jþúë/öíÛÇ/¿üB… HJJbäÈ‘ìß¿Ÿ„„êׯώ;èÙ³'âs“;‡sk¨Tª©°æF#†‡‡ãââB³fÍŠ{HoµZÍÆ166¦I“&Ï4¸gggóûï¿sòäIV­ZEÍš5©S§·nÝ"88˜˜˜zõêÅ„ Äy\«V-¶oßÎÇüÜ1\½z•ÿþûÁƒ‹ÑXï ¯Ü—˜˜HXX¤bÅŠâËÕÐÐÖ­[S¶lYNŸ>]Ü×÷ÚDDD0þü<f5 ¿ýö111Lœ8±@o£]‰PV<==qwwÿÖ××ç“O>!''ç¥ÐWÅÀÀ€!C†äQV ‹L&£N:Ï a–x5t:—.]bÇŽyZ¾œ={–3gÎðË/¿¼°—èÛÀËË‹k×®U ÇQBâ]$..މ'²mÛ6¾ýö[Ö®]Kbb":NGZZsçÎåçŸføðáôêÕ‹™3gâååEÆ ¹yó¦x¬¬¬,¨P¡ …‚V­Zqúôi±YFF4hЀëׯ8ž7n0dÈ<•åu:)))¤¥¥XÝU§Ó¡R©ÄtŽ‚ÈÈÈÇ!Q:Ðjµ¤§§sþüy¦L™Â×_ÍáÇ©[·.³fÍbüøñÔ©Sçµrë<<}X¶l=z£Ç—(>rrrXµjëׯgûöí|ûí·;vŒ¬¬¬|mõNœ8!Ö¿Y°`ffflÙ²E¬ÙòÇЦM›}Ь@ØÓ”+WŽ[·nCùòå‹û6IH¼u3f M›6¥[·nùä“|Þ…˜˜ „¿¿?ÿûßÿ ô€edd€N§C___2Z3*•ŠÕ«WsâÄ @Hùùúë¯_˜Nô²XXXP¯^= €··7sæÌÉ—ÛéääħŸ~šç;QQQ899‰’ÜþõúúúÔ¬Y“cÇŽ½TŠÇ³ˆgñâÅèéé1lذ7v?Ïœ9C5hÒ¤ Œ1‚ºuë.Éd¥œ­[·røðaþüóO¬¬¬8|ø0Ë—/çŸþ¡qãÆ¢§§G||<óæÍcìØ±âúöí·ß¾ðøvvv”+WŽ#GŽÐ²eË÷Ñh4œ:u +++nܸ‘GŽKKKÃÈÈè¥ÃÐu:qqqæyÞ322¸rå AAA4gĈ˜ššâååEPPÐ3Ó ^•×VXMLLpuueýúõ|ùå—¢UU¥RqóæM.\¸@›6mÞÈ ‹ƒÐÐPúôéÃÊ•+©R¥ Z­–yóæ1hРR«¬‚OWت|¥µZMdd$Ÿþ93fÌ`úôéìß¿‡7¶¸¼>>>lÛ¶ôôt±ø„Ä»†J¥"99™´´4–.]Š““]ºtAOOOOOÆÇÝ»wùóÏ?Y±b~ø!Ÿ}öY¹Ò...ܽ{FƒB¡àöíÛùr¢|}}9þ<•*UâÈ‘#4oÞOOO>|HjjjÃsDDW®\aÁ‚Lž<™5kÖˆÊĸqãptt$88˜={öðÏ?ÿÐ¥K²³³Y³f ~ø!çÏŸçÊ•+Œ1+++d2iiiüöÛoT¨PÐÐPnݺEÅŠÅsjµZ}šæÍ›¨,FEE¡R©øôÓO9yò$ 6 ))‰/¿ü’þýûÓ¤I“çž#33“7npøðaöíÛ‡››3gΟ— .0pà@¦M›FÓ¦M󤮨T*–/_Ž··7mÛ¶%88˜iÓ¦1iÒ¤7âm}m…ÕÚÚš>}úðË/¿pùòeÔj5iiiLœ8‘C‡Q»vmjÖ¬YèYYY\½z•3f0oÞ<¶nÝŠN§ÃÆÆ¦Ô^“„Ä“v^^^\½zwww©ŸžÄ;GFFû÷ïçÈ‘#$&&‚€›“—Kna¼©S§’˜˜H™2ežyL777¬¬¬ £\¹rbÿí'©U«–¨øÞ¹s‡Úµk£R©Äpã'Ö³gÏâëë‹ßÿ=_}õ*•JÌ“•ÉdxxxЮ];Nœ8Áš5kËåŒ?:vìÈòåË|H¿~ýh×®]©í*ö8ìÚµ+¿üò ÙÙÙŒ7®¸‡&!ñF8~ü8~~~”)S†ÁƒóÍ7ßиqã>>chhˆ³³3×®]Ë#ÌÑ£Gqsscýúõܼy“#Fàïï/Þ ÆŽËßÿ-ög–x{Ü¿Ÿ 6pîÜ9*V¬È¨Q£ðññ)q†COOO¶mÛ†Wccc±’=Æ"##ó¼Ïbbbغu+cÆŒaõêÕ”+WŽ *Æ_ýEll,]»v¥zõêbdƒ 8xð -Z´x©~î:ެ¬, òyw9’'„^¢ä¢Õj9rä»víÃv]]]©W¯DGG³}ûvŽ;ÆG}D‹-ÞJôÁÓä®ÛQQQùÞ :ŽË—/S¾|yñððàÂ… ”+WŽýû÷3eÊvíÚÅÔ©S>|8—.]bñâÅ$&&¢P(066ÆÆÆ†.]ºàïï¹¹92™Œ~ýú1mÚ4ªT©Â©S§ÐÓÓ£ÿþ$$$°mÛ6úõë@jj*K—.åóÏ?ÇÜÜ\WPP•+WfãÆyª¿¯­°ÆÅÅ1|øp† Â?þøÖ¨¢äúõëøùù!—Ë©X±"7ÆÀÀà½.'-ñnqìØ1>þøcd2nnnÌ™3SSÓb¯*§P(pwwc!XEAjj*ãÆ#;;›œœœùôÓOñóóC­V³nÝ:öìÙèQ£¨P¡ÂK ¿¯BÍš5™4iÍš5#555_Ž¡••L›6nݺ‚ÂÀ¥K—hÞ¼¹x÷îÝÃÕrßÏ£ \__ŸJ•*Q©R%>ûì3²³³E/®‘‘‘X6++‹æÍ›3wîÜûRÓ¹sçSÈð]D§ÓÌŒ3 bÞ¼y%:íÉÆÆFì×}ëÖ-ÜÝÝó…÷zyy–§G÷Ö­[ñ÷÷çÃ?DOOiӦѲeKV­ZEË–-=zt¾¹ìååÅÊ•+_:œ1==Ÿþ™Î;S¯^=q{NNdàÀÅ}û$^‚#GŽ0þ|ºw­-ÙÙÙœ8q‚Í›7ãããõkרZµ*S§N-ÒÔ%###üüü8yò$y>Óét\¿~¾}û"—Ë©U«GŽ!22gggìííéÝ»7½{÷f̘1ܺu‹þýûÓ²eK’’’HIIÁÙÙ9Ÿ¡¥B… 8;;³nÝ:NŸ>Í!C000 {÷îŒ1‚N:ÃÂ… 133£aÆyÞo¹% Dttt¡®ÿµ¥Scccìíí9xð /m]ˆŠŠbË–-cmmMãÆ©[·®ø²ŠŠŠbÛ¶m\¾|www>úè#¼¼¼Þø þY¨T*.^¼H§NěݧO©g–ÄK‘™™É‰'عs'YYYŠýcµZ-·oßfݺuÄÄÄȇ~X¤EŽ"##‰Íó2[U£_}}}Z´hñB¯’Dñ’˜˜ÈÞ½{9|ø0†††T¯^–-[biiINN/^äßÿE£ÑP³fMZµj•Ç ò®qòäI4 S¦L„BH'N¤ZµjröìY~ýõWœßÊùÝÜÜÈÎÎfÇŽxxxX ±]»v,_¾œªU«ŠÛ‚‚‚ø÷ßQ©T°aÚ4iòF#ŒŒŒò) 4 33ÜÝÝ‹ÝPV‘‘‘lÙ²…K—.accC“&M¨]»¶(«DFF²mÛ6BBBðððà£>ÂÓÓ³Èd•¢ÓéHJJbûöíü÷ß 8êÕ«—ÈßâIlmm‰ŽŽF£Ñ^`_öJ•*‰^X€+W®pôèQæÌ™ƒ­ZµâÎ;lß¾©S§âíí] |çêꊱ±1—/_k™Ü¿ggç|JòÇ?~<úúú,Z´ˆ *ˆï±¨¨(ÒÒÒ^ت­¨¹|ù2{öì!,, ggg:v숯¯/úúúh4QV‰¥J•*|øá‡yB@ß5t:ëÖ­cëÖ­L:wwwñynذ!ñññ;vŒ¯¿þš2eÊyë$™LF³fÍ;v,:tÈS¨+++‹˜˜Q býúõ?~œ_ý===d2?ýôÿý÷?þø£ØéÄÒÒò™=“•J%ýúõ£oß¾Ô¯_¼½½iß¾=Ý»wÇÉɉvíÚѨQ£×[[[ ô Ç/âµWVccc6lȉ'1b‹-bñâÅyþ%$$äùNrr2¿ýöÿý÷uëÖ¥L™2üúë¯ìÝ»W,Ú4qâDöíÛGݺu‰ˆˆ`üøñEZž933“ÌÌÌ_Ø7‘‘:tÀÛÛ»D®CÉÉÉ̘1ƒ={öP·n]¬­­™8q"û÷ï½m&LàÀb•×ñãNjŀJ7nÜ`ðàÁ\¸p)S¦P»víù[<••666DDDˆùwOãììLTT ü–sçÎ¥}ûö¢€®P(øê«¯øóÏ?)W®Ü3´hÑBlÿvìØ1úöí˹sçòí;gÎùõ×_©Y³&3gÎÛ"îÚµ ''§%GFGGóóÏ?síÚ5š5k†V«eèС„……ˆ²J||<µk×fçÎüöÛoÅ=ì·†Z­fíÚµlÚ´‰áÇç3>éééáàà@çÎqtt,¶ß²\¹rÔªU‹ 6äi/võêUìììÄæ\…ÚÛÛ›€€qM÷óóãûï¿ÇÖÖö¥keË–å—_~¡W¯^bŠ€\.ç£>bÊ”)üþûïtèÐá¹Õà íô{íÕ)##ƒ¬¬¬HLLäÈ‘#ùöiÑ¢EžÐ’›7orúôiþùçÑ£¤ÑhرcMš4áÒ¥Kܺu‹iÓ¦áïïOëÖ­éÖ­»wïæ³Ï>+Ô…¾, ¨T*±Lº„Ä«²aúvíÊÀ‘Ëå”/_žŸþ™àà`‚ƒƒ;v,VVVøúú2xð`.^¼H•*UŠd|çÏŸ§FÅ}›žÉ“%J©©©lݺ•Ÿþ™FB®ã²eËhÓ¦ +W®Ä××—‘#G"“É(S¦ +V¬àƒ>ÀÃ㸇ÿÚdggsïÞ="""HJJ¢B… ”-[–µk×R¶lY±ýY.vvv 8N÷Ö½nr¹œªU«²iÓ¦g •2™ŒÞ½{çÛ^£F &OžLƒ ˜1cF¾ü×÷‘°°0Ο?Ïš5kDY%''‡íÛ·Ó¸qc.\¸ÀÝ»w™>}:•*U¢U«VtïÞ½{÷æiÁR‰ŽŽfÕªUœ8q‚aÆQ«V­Rãa®W¨P'NpíÚ5úöí›o sæÌáÈ‘#tèÐ!_µé—ÍÍmÕªýõëÖ­cõêÕtïÞ¥K—âç燹¹9*•ŠÙ³g£Óé4hJ¥’^½zñã?2wî\°°°`È!%*JïàÁƒ˜šš2cÆ ,--iß¾=_|ñ»wï¦R¥JlÞ¼¹\ÎØ±c±°° |ùò|ÿý÷XÜÃ/4¡¡¡lÙ²Y³f˜‡YÒóŒ?þøc¾ûî;Ú´i#®×GŽ¡Y³f¢ÑÉÈȈÿýïØÙÙ½‘y÷dˆ{.&&&EÚuäµV †ŠZ­WºV«ÍscžL¼AãïÕ«—hÓjµèéé¡ÑhÐétܼy<<<ÉdQµjU._¾\d7$$$ooï"I –x7iÖ¬( t:2™ ™L†F£!44”€€LMM‘Éd¸¸¸àêêJHHH‘)¬7oÞ¤gÏžÅ}›$J)J¥’.]ºP¹red2:N¬öªÑh £_¿~¢È¢E‹xðàA©SX5 =âСCìܹ•J…··7†††üûï¿XYYË„  ôJæ>ûo™L†——5jÔxfNÕ³ÆÑ»wozô艉I‘Œµ4`kk[ ¬¢ÕjÑétbCwwwd2ÆÆÆT©R…Ë—/—X…5·î¬Y³ð÷÷gÞ¼y¥¶u˜§OŸ&;;»ÀkÐÓÓ£^½zœ8q‚¡C‡R§N×>—¡¡!–––ÌŸ?ŸyóæáííÍ¥K—8qâ-[¶äôéÓœ:uŠE‹‰i¹­K–,YÂG}DãÆKœ!ÖÛÛ›nݺåqÎèéé‰2}hh(âºàææ†³³3W®\)õ «V«eÕªUhµZNœ8ALL •*U¢wïÞæÒ—4lmm©^½:;wî¤oß¾dddpöìÙw,©©©œ?++«B[FΟ?O“&MJÄ#ñúä Îׯ_§ZµjEzîîÝ»Bèí… سg*T ZµjLž<™-ZˆÖÝ2eÊ`kkË7ž{ÌGqúôi*UªT(cJBB111ùú4J”>²³³¹xñ"÷ïßS*оüòKÔj5W¯^åܹsìÚµ‹¶mÛâêêÊÝ»wó‘^^^¨Tª\¸sçÁÁÁøûû—OÄöíÛY¶lµk׿§Ÿ~¢\¹râg999ìÛ·FS"rÓjÕªõZ½ýJš ý4§N*Ò´ rú===ÅgìâÅ‹œó˜jµšË—/ãáá‘'¿²¤qþüy±ÏuiPPŸFOOÏ>ûŒ>}úpñâEÑùQRó‹£££ .t1Í×VXu:!!!L›6äÙnllLïÞ½ùè£ ŒóÎÊÊâèÑ£9r„ŒŒŒN•JõÜÏõõõ߈Û;22’k×®1dÈBG¢ø‘ÉdXYY‰ë‹ƒ›7o²cÇ®]»F«V­òä­Zµ*îaæ¡´¶’{öööbßÍ¢&33“#GŽpôèQ²²²066~nÅØçÉ*2™ ‹çæy½it:ÑÑÑüöÛoèëëó믿–Z¯ê“8;;“‘‘QdkEn¡™\*W®Œ««+_}õ]»v-”ÇQOO{{{1綨IMMeç΄††bmmýB9úy²ŠL&ÃÆÆ¦D‡ÔªÕjvíÚÅG}T*•Õ\lmm™1cIII888”èB•ÆÆÆ”)S¦Ð©¯ýíÔÔT-Z„B¡`òäÉ8p€ƒ²nÝ::vìÈܹs¹víZßµ°°`ذa¬_¿ž¶mÛ2iÒ$±‰zA¼hòŠÅ#^NÇž={¨Q£†$Ì¿Èårqpp(¶üœfÍš±xñbæÌ™Ã‰'رcÇ3÷}‘—ÃÄÄBÍñ””¶lÙB§NJUÎ’DÁèééáææVlF¥RIÏž=YµjcÆŒaþüù„„„¸¯B¡xáÜ-S¦ ...%fnÞ»w¥RI@@@‰Óûˆ§§g±)â–––üøã¬_¿žV­Z1qâD’““Ÿ¹ÿ‹d•2eÊiéôôtÆG¹rå?~ü;¡¬‚ 988¼ÕBfÏCOO¾}ûÒ¼ysºwï^¨bUJ¥bkÝäààÀœ9sX¿~=æææ/,¬ô‹www¾ûî»íM|*•ŠíÛ·sìØ1q›¹¹9õë×Ó“re•ÜȘ„„quu-îá¿6¹ëú| VÓ•(=¼¶ÂªÓéÐh46˜Ö××ÇÜÜ\,éKtt4¿ÿþ{ å7ppp@__ŸjÕª˽{÷A‰   6mÚDåÊ•ßh5·‚xøð!!!!ôêÕ«T¾`%J¹ý…ÇŽKëÖ­سg-Z´ ===&NœÈœ9s°¶¶æßÿ¥U«Vž÷ªh4¶mÛFãÆ‹4ßP¢äPµjU\\\2dõë×e•^½zannNåÊ•ñññaúôétèÐãÇciiIýúõ‹{è€`ìŸ={6Ý»w/’è¢F&“Q¡B…âF©EOO-Z0fÌFŽI`` ‘‘‘œ8q‚Q£FФIvíÚÅôéÓ©Zµ*7n$00Š+÷ðŸ‰Z­&11›|i‘‘‘Œ;–¯¾úª@G›DÉG1vìØ±¯óE¥RI™2eX²d ‡æòåËùä“ÿüóçæ|deeV¨Â[¶lAOO¶mÛÙ}xûä®nnnbK…·UªTA&“qéÒ%âââhÚ´)Ÿ}öfffbk²“'OrïÞ=Ú´iÃG}ôÜ­ääd¢¢¢Þºáæe eõêÕôîÝ»T…1¿«dffrãÆ"m¥aiiIåÊ•EY%++‹®]»Òºuk DY%!!#GŽˆx\]]Ÿ)«dggsãÆ" c=|ø0W®\¡_¿~Å–)ñò$'']¤Ê ³³3ÞÞÞDEE‚¡¡!ß|ó ÕªUC¡P`ff†¿¿?W®\áüùóÔ¯_ŸÏ?ÿü¹rvLL ¦ÐÕ`_—;wî0fÌêׯŸ'ª >>ž#FбcGZ´h!yW‹˜˜²³³ ÕÚîµ=¬ …‚ °dÉvíÚÅõë×Q©TØÚÚòã?ÒªU«'…»»;C‡«I*Š< ¼ƒƒß|ó Z­™LöÖ'–Z­æÏ?ÿäã?~«ç‘x055¥}ûö´iÓÂor­}2™ŒråÊ1jÔ(t:]žÏÞ=b×®]¢åTB¢°ØÙÙñùçŸÓ«W/ ï:®P(¨]»¶:öô_’ÈÌÌ$<<œ¬¬,’’’ؾ};<૯¾’Z?½çxzzòý÷ß?SVqttdàÀhµÚ"YÇ_–ððp,XÀŒ3Jtñ‰â§fÍšT¯^]ìÿ¤¼-“É(_¾<£G.2Y¥°¬]»–vïÞ-¶ÌÎÎfôèÑøùùñÑG•økx6¯_Úìÿñôô¤K—.X[[“““CJJ FFFÏl˜ž»ýy“¦¨ NDZcÇP*•%&”GâÝ@&“=·r`QYøt:6lÀÇǧP–- ‰§yÞ:ý¢ù_Ðh4ÌŸ?Ÿ'NàããƒZ­¦iÓ¦T¯^½D·(J’¬ò²èt:Ö¬YÃ|P¢ @I”L^Æ)TZ¼‘ñññ\¿~™3g2þ|7nŒ½½½]Ö¿ÿõ¬J¼:…’(®_¿ÎرcÉÉÉaݺu²xñb1œªwïÞ%º‚Zxx8³fÍâ÷ß—,‘ï$gÏžeß¾}Ì;·P-q$$Þ%²²²˜7o±±±,_¾üì_*ñþÆùóç™7o^qEB¢ÈÐét¢á±^½z\ºt‰Õ«WS³fMV¯^-­ñﯭ°¦¤¤°páBllløòË/Ekú'Ÿ|‚µµ5þù'AAAT¯^½¸¯±@4 Ë—/§yóæ888÷p$$Þ8 Ì›7/¾øBšãÿV«åÀ\¼x‘iÓ¦I‚ŒÄ;AJJ 3gΤÿþØÛÛ÷p$$Š FÑ#GĶ”­ZµbÔ¨Qœ?ž~ýúI©w„×ö'&&·ß~+àÉd8::Ò©S'8uêTq_ß3ǾxñbîÞ½K×®]¥0‰wŽøøxæÏŸ»»; 6,îáHH”t:§OŸfíÚµŒ?^êI,ñÎpøða iÔ¨QqEB¢HINN&22R,hæááAëÖ­ ¢E‹%¶†‚Ä«ñÚÖÜØ÷‚”=F#6.I¨ÕjŽ=Ê’%Kðôôä—_~‘Ê[—f48v ªVÉKÏ^XXS§NÅÏÏAƒI­šJ*H¡Ûo+W®ðÛo¿1tèP©¨’Ä;Cvv6[·n¥G’^â½cÿþý`kk ¹å:uB§Ó•øZ /Ïk¯l–––T¬X‘¹sçråÊt: ôaݼy3W¯^%((¨¸¯/ Ì;—>}ú0a„b+½-ñ†ˆ‹ƒÑ£aß¾âI‰áÖ­[Lœ8‘ž={2xð`©dicÁxø°¸GñNrïÞ=¦L™Â Aƒ¨Y³fqGBâqðàA ©U«–äM’x¯HKKcûöí|òÉ'yŒ5J¥R2Ö¿c¼¶éÁÌÌŒ~ýú1}útˆµµ5ÖÖÖܼyºvíZ¤}Ó^†œœœKl^­Ä+’“-ZÀ<Þ¦ÓÁƒ’% §cQ…··7Mš4)î¡H¼ *•0g=‚Í›¡_¿âÑ;…J¥bäÈ‘´mÛ–ºuëJ^(‰w†ÄÄDV¯^ÍСC¥ž«ïÄÉÉ OOÏâŠÄ[¦P!ÁLŸ> .påʲ³³©Q£U«V%00°Ä¹âsrrP«ÕRµÔ’Nd$˜›¿8Ì×Í ~ú)ï6®^…… aìØâ¾’"'))©t{UµZصKøí4(îÑ$& óñm–÷ …;¡}{˜2å±Âš‘!Ìi“¼ûGF‚R ¥ù·.B®^½Š‰‰ mÛ¶•”U‰wгgÏbnnN… Š{(EÎÊ•+ùöÛo¥uý=à•~á»wïòû￳mÛ6nß¾J¥ÂÎÎŽ–-[òÝwßñ¿ÿý/¾ø‚   §¬ܹs‡2eÊ”<…5+ nÞ„åýæä@p0ܺ%xbŠƒ˜HO»ç8|–,yñ~ÙÙÂ32`Ø0Aˆ—˯ëÔ©°u+¤¦Ï}*&âããKwn^Z,]*(co’”X¶Løï‹Ðj!,L0zdeÁàÁpïÞ›‹Fÿ ±±·íÝ žžP¥ ,_.l»rú÷Ïò ÇÃýûoö½£dffòûï¿óé§Ÿbò´â/QrINÖ‰g¢Ñhزe ݺu“¼«ïÿþû/ÎÎÎRŠÇ{Â+)¬vvvT­Z•»wïòÛo¿ñóÏ?³iÓ&âââÄÛ%ÙÊ‘žžŽƒƒCÉËñHIéÓŸ¯„êtpá,^ gϪUÂ6NP`wî|óãÊ=þÿç'“ž' !·Âþý?KKƒ;wa¿ ´ZAP™ó5j$\ã‹îÇÂ…ÆÆBx¸ ´úøÀ?‚©é›¿/%˜ØØXŒ‹{ù¹{W0D¼ˆ‡¡F Aq{rîþÆsêÉõI§æäÓçBwwÁ«êæ—/¿¹{ [¶À“F½G R%a|FF³4}:|ô´l)ƒ¯íÕÓÓ£|ùò|ñÅL™2….]º`hhÈêÕ«ùé§ŸXºt)wïÞ-–ûö,=zT²ÚØhµ‚‚–”­[?~‰ç"„fe ûÖª%xU ૯ÀÐÖ®…fÍ%ïe¼@99Âwúõƒ_},ˆ_½*Ä))-~·n /Œ… …¿SSáÓO…ÿ·¶”PGGA9tv†®]áÏ?‡êæ’œ,xÎÚ·,|ääʈV+x—fÎ,íFFÂç:—×ãcœ;'(Ĺ÷èÆ (_þñþr9´jõøï÷”œœœ’ö˜-¹––‚QãIââ`Ñ"á…Âs½)2™0ÿ×­Ëÿ"ÏÎæLjjþgæY4k&Ì¿M›[­†¿þ‚Š…çiÊÁøÂÜkÑâ±]¹²0·ßuêÀ'ŸÏÖìÙ‚2ÿô5êë Êu.íÛ âA±ýÿþ¡ ccÜvïÆàu”‡÷€‡rõêUjÕªUÜC)ùäzUA0üuí*Dé=~\˜Ï=zÏWAQN˜çË—ÃøñÙ¬™ðÝvíå„|q·›3þ‘‘Áùóçß½pHN0’'$ëãáÃÏ÷Bîß/ÌËØØ·Ÿ®¤Õ 2Ó˼w<œ aaÂ;æ“Oùè›o¯íU«‚§'6S¦`òdŠˆÄsÑét?~œöíÛ£x×Ö‰7`ÇŽÇs,1¦M{¹t¦â"3SÐS-œ¹òLvöMË+´éR&“aii‰¥¥¥Ø´7""‚S§NqïÞ½U¹+55‡âDv¶ ´)Â"ûë¯B¾¥Ÿ_^ ÊàÝ»‚Çiøp!D*—ÜʸeË ˜Ë—EtúôçŸ_©,ç]» ž¤ädA™pt㯾‚QC‡>3–Á\d2ð÷þåÒ¹³ ÈfeåÍA´µ…yóÿ’"´ïHN†Q£„‚2õêAóæ‚šË£GÂ}²´*þÊdBèÏÇ І»{ñþ–%GaTœJ»F#,^ÆÆ‚áäIA¸mÛVxa?I\œ0ou:¸~]0Xtî,(ˆzzÂ|>:t<޹9"xöË—ŽÛ°á‹Ç•ÛÂÊÝ]3¬XQp~ùE§¡¡ Hÿü³ü$¹ ×!:ZP4›5{lLyÒ³š“#\ãìÙÏ_/Súö”ê€Q™Vr§Gl¥üµY·nÍ›7ÇÙÙ¹¸‡R²ÉÉ"22 Ká}à蘿¯¿Î¿Í×W0^‚°V$@ªTðÏ?‚ð2nœ°ŸD¡ˆG­VãúäÚø.˜(DLš$¬ï¿ü"È5jä˜ÒhJ:‚Ñãm¿ûîÜÂÕ?ÿzõzö{!'G¨ÅP·.<Ù-ÃÊê±a&÷ï/¿$50Œ;wŠãn—J>÷ô,èmÛ>þÌÚZPd¯]„ã'ya¸qcá¿qq‚¢kh('úú÷Y²Dx)ýðÃãûTäÌÁ£Ô¿¿P uÈÇ…fž£ äi¿õàÝ»¡zuaÎ<‰V+(g7 †33ÁãòùçÂjÕ*ïþqq‚ÁEOO°’GFæ5B¸¸!OŸ§V­Ç-‹^”£¬Ó xíí…ãøùƒƒðŒ)X¾AW_¿þÙÇIK K}û ‚üËæÌ˜™ ùåjµÞ{þ¼ðLTª$|Þ£‡ €¿ŒBüÁÂ=~2W.GenŽî= }ÒÓÓ9yò$S¦L)y4aÈdÂÜÊ5*êé ÏZR’Pµª ö³²„ï+•Âþ‰‰0c†ðß¾}_},O á ëYY‚Áæ§Ÿ„9ÿÅÂ{ ×¹(Mœz$8<<à³Ï„ó*•ÂØË–}v*à+òÊoŽû÷ïóÝwßñå—_ @XX àðáƆ2aÂæÌ™Cfn¨_ 99•J…ÛÓÞ“7‰J#F æÓ$$Þ›Š/¬nnBˆm®°ªV ¡±ÿüóØËcl,äs¾hÜvv‚@¬R=Þ–š*äu¨Õ‚à¾alßþìc(‚Ç´ Ëú«ré’p½ “ûIú÷¬ì/Ê'®][ó‰Âß>>Bî_Zš"ü²á ï éÿennþöN’’³f â“ètÂo2s¦ „åR>ýô±4++ïÂU±¢0g „üãÉ“ó{^Ê—ÏßÒÅÌLXÔÁãúu!¡ ²³a(·Ê¯‘Œ#O zff‚Òú¬ç,W°Ÿ8QÙ!œÕ*ÁëùtHoNŽ Ð˜š !`ÇŽ Â΂yÃÛ+êËä )y ?Ï%22…BÝËæ÷—rràß…[*Ç÷ï/üûóOa›R)D¶,[&víÚá÷t˜k1‘˜˜øö—´4ÁóWPžlzºà•zrá}Úãd` ,¾*Õc¯ë«Ðµëãc'& ‚Íùó‚çªwoÁc™æû¶iÔH]LLóíD^¶Š­¥¥Pøéi%æÈ¡XÁ“áÈŽÆuíšmæá!|wÀ€ÜÓÓ1ˆŒ,t׎WRXïܹÃÍ›78p XÄ"**ŠË—/S¿~}*Uª„\.§I“&¬]»–Ó§O—…5!!áíWÒ³¶¬Ùáê*X!^Da,r¹‚™V+XÖýüïÎ!P³¦  ûø¼Ý{‹žžp-…µ0ôýË—Ë‘‰ˆˆÀëÉBUoƒ ÏfZšðç>S2YÞ\‚°³ÂÌÌÇÖé  Ÿ3<\0¶Œ!„#·i“÷ó5`åJa¡OK„wccaÞ»º Í [\&Ë ''á={>ööÇÄcÉÍÁá¹´°®{À©˜LqéÒ%üýýK·êi¢£…ž½£G?6䙘<;ÒØ8¯ÐƦðÏÂË"­Ïo­Vˉ'¨V­Zé¯|­PøàQ0Ëåˆû—ÒÒÒÞ~…àÜ0Àääǹ–©©Â„*ŠðÕÄD!Üëüy!—00PX4çÍzT¨[ôJæ9…BL&CóDŸK—.¡ÕjK|/¤äää·_œ`Õ*A Õházî\!tõÐ!ÁZñ¶óÏ aèÖ-Áë”òU’Zù¼©ë”ÈGll,¯÷åÈHÁ’ö¼¢d©©‚!¤n]!4dÂ! }éR!êE UF-,+øËVy66r&rÒ§ 2™0¦\žö ¥G3·Ø€D±CfffɨRü¸`ånÓF˜?ü ¼#êÔ¼ÿeÊ!W!!Båê²ec‹B!ÔC~¬¸¹åÏé–x¯ C©T¾þZÿ¶É-´Õ¤É³½/IIB1ºW E/_^ø÷d½€‹óz¤<<„ ¬Å/N±¶R±’“-1QHíx²²x•*Âõ¼™Lª3ð ÆÌÌŒ²eË÷PÞ< Å‹;h4œ××Þ¹í$Ÿ‡]þbz2™`üìÓç寖ÛIáu‘ɈkØäädʽþQ^ÍÃêââ‚R©ä¿ÿþC¥R‘˜˜ÈöíÛ©Y³&ÆO„ݺu‹°°0ªW¯^ˆ¡½Ybbb0{×uAìÜ)”–~š§{îÞ-L¤rå„ÏŽâÈ¿ý¶h<›&&„·²`I±{¯ˆŽŽ~ý…|Ä!GáITª¼Ö눡°F#ÌñZµ„ùmi™7WõY(‚5O¡÷WéX§Žöd¾’„Ä38tèÕ«WGYœÆF0æ,]*¹†“Y³„ˆ€'éðp¡=ÇÝ»B5÷'…r__!´ñmGOH”xrrrXµj}úôÁ´ù`¯Ev¶°æ¯Z%ü}ó¦`„üá!â„y=z´`Äô𔿠ò‹¹~]H/y•–<¹!¸¹Ïtf¦æ[®0"ðÿ£P<6ìGF Q\ãÆ=îÍݹsþJØEJjj*‹-âã?.ººÏ*à% èqá®ÌL!Uãÿ{ül$$!â/Û8>þq!½g!“ 5\¾ýöUÞ-M¼’‡ÕÁÁ-Z°|ùrΞ=Kff&QQQôêÕ ¹\N||<‡bÍš5TªT©Àp,N‡F£Aõÿayò0t:jµšœœ È ú©ÓéHMM}½:vò´"-#F{d¤0™\\¥µm[ÁZþõ×çM¼-:t*1–´Z-*• Fƒ¾¾>úúúâ<Öéty>ÓÓÓ+ô×jµÄÆÆ¾^H°J%Ì™§ÃUª‘N™"Ìñ;w#×øÒ·¯`nØðå#ÁÁB8d½zù+ëJ”*r×qN—okµZ²ÿÿe®¯¯/Fçjµš .о}ûâ½A:ðtH¢Aþ¾ÛÕª ÿž¦eË⽆÷˜âU^Ä;wˆŠŠ*g@zº6{åŠï ‚B:r¤ ÿ䆹›˜ä-ˆ¨§'ä€îß/DÈd‚§´\¹×ëo•%W?ø@P$ß4•* ³·o ̼NÌRBîV©TÈår”JežPÛ·!«¼î8÷ïßµµ55_ÅÐ]X~ÿ](HÔªÕã‚AçÏ rÑÝ»ÂܯTI08=*xûk×ö³´ ìÇ¿\{£]»¯éÓÅXŸD.údø¡`ðyÏx¥ÕB.—óÙgŸammÍ‘#G033£sçδhÑ™LÆéÓ§ùóÏ?©R¥ ƒ *0g4**Š¥K—‚F£¡nݺtïÞ‡ÿÏ÷ºqã«V­âêÕ«¸ººÒ£GªT©R(‹ŠF£!>>þõz°ªÕBøãÓU»… ¹nPæÜÖöq•R(ú&¿¹¼Í–&/EFF»wïfûöíÄÄÄP®\9:tè@Æ Ñh4œ;wŽ+V‡¿¿?Ý»w/tˆKbb")))¯E``ý•{n¼Ë—…ÊÀvv‚À‘ûB34|õråQQöæÚgH ¬[·ŽcÇŽ‘ššŠŸŸŸþ9>>>dgg³wï^Ö­[‡F£¡FôìÙóí×xbl=ÊSk¡XÐÓ{q¸–D‰%""‚eË–‚V«¥^½ztïÞûÿ/ƪU«¸vínnnôèуÀÀÀ·êýÙ½{75kÖ|;•àµZÁkdjú8 9Y0TV®,¬ûõê é¹uúú‚B÷<¥ÎÀ@¨<|8Ô¯/ÈM…)H¤Õ ^¦3gOÓÛy¹îçܹslܸ‘«W¯bffFëÖ­iÛ¶-fff¨ÕjQVyøð!tïÞï—éwû†‰ŒŒdÍš5Lœ81O4ç[#'G˜Û}$¤öåv!°´ê 4n,týÈ’©PÆÏ{ ¹\ÐÎ{Þ 8´,-…ŽƽxlO†ª¿g¼²+N©TÒ®];~üñG¾ÿþ{Z¶l)Vëª_¿>þù'£Gƹ€›šœœÌŒ3¸rå }ûö¥oß¾œ8q‚Y³f‘žžNvv6ãÇ'>>žaÆáììÌĉ /ÔEj4RSS_o¢ëë ™ì± ^£B>úHßÊÊåòåßÂO$QÚ8pàÓ¦M£N:Œ;¥RÉ”)S !<<œ±cÇâîîÎСC‰‰‰aâĉä²(Wff&666¯gýÔhoÐ… ‚W5//!O5·4zõê…oÉbm-X(Ÿìë%QªÈÉÉaÅŠlÚ´‰Ž;2tèPâãã™4i9r„yóæÑ¬Y3zõêÅñãÇYºt)êç…W½AîÝ»‡R©,¾*’Z­àMŠ-žóKš\YåÚµkôë×¾}ûrôèQfÍšEff&YYYŒ;–ÄÄD† †½½=¿üò »Ú»ðŠVòåË—sòäIñññ¡GÔ¨QsssÌŸcí '88˜Y³f@™2eèß¿?ƒ&,,Œ¤¤$FE… ð÷÷çÔ©Sìß¿¿Pí:t:r¹üõ˜ÌLÁÚ’”$T“›>]ìÃÃ…p”‘#…ÜŒ“'¾´—™—(4»wï¦I“&ôêÕ ===*V¬È×_ÍÐ××ÇÚÚšþýûcaa……ß~û-.\(T¨KFF&¯SŒE«BQªVÌÙ³…–'å4מ•%,ì…µfW¬(,â÷îI9Ö¥”ôôtöïßOß¾}éÔ©þþþ´jÕŠk×®±yóf‚‚‚èùÿm¼4 .¤C‡o½XÆÍ›7™5k½zõ*…U£jüý·Ð«N¢Tr÷î]BBB˜5k–˜JdeeÅ7ß|Ã!C¸zõ*©©©Œ7ŽòåËãççÇ™3g8pà}^¶É+²sçN(÷&r6 bóf¡HRnèãÂ…B¡¡7v[¡‚V¼reþ֝еµž,ñÚœ>}†Ž««+5jÔ --7Ò¯_?þûï?lllèß¿?fff˜™™1dÈ.^¼H—©Yñ†ÈÊÊâÊ•+LŸ>ýÍP¥Ê+{lÜ(t->\ë<zôxü¹±ñë;£ôôž]ÈríZ!´7·*ð¼yoý^–v^ÉêÕjY½z5«W¯ÆÖÖ–úõëÆÈ‘#yøðá ¿o``@½zõòä¶š˜˜““ƒN§#44;;;\ÿ?_©TR¥J‚ƒƒ u‘Z­–ÔÔTô_§zÛ–-B¥F[[Á›zíšP\àÉÐË›7…ÒEäA(Ùxxxðᇊ¡aJ¥™L†Z­æÊ•+øûû‹Ê¥““®®®\ºt©PçLKKC&“½º‡5+K˜ß©©Â¢ll,ô[´èqQ±”¡ÐÒ¥…¿9Bî’ÔG·Ô"—Ë ¤î•™Q«Õ¨Õj®]»&öé ;;»Ð‘2/",,ŒÑ£GÓ­[7š4iR,¹V„† i"S¦¼×¡[¥êׯï=BMLLÄ|Öëׯãàà Ê*FFFZVyááá¬\¹’ï¿ÿþÍ…k4Â?¢ÇnÞª†æÊI&ü{÷Uñ6pü»Ùlzï B ’ÐBï‚°ƒüìXPQ,(Ø(vEi** ôÞK5!¤÷ÞûÖûþ±oVÖPÒ`“0Ÿs8‡Ý»{óÜÝÙ{gæÎ<&4íì߯?ÿûøÜÏI¨;ÆŽk )“ɰ¶¶6ÜAŠŠ¢gÏž†Ž????|}}9÷ßåSn°øøx\]] Cñ%* þ÷?ؼYßpMMÕ'7N? ¾o_øþû¦Ê‘påΕ1cô±uV¯kii)»víb„ |úé§¼õÖ[†áŒ§Nºîûyÿý÷ ù’’Ö®]KXXvvvdggciii¨Ì+ üüüHNN¾æ~•J%YYYWr¦ÕjÑjµ ›ß—˜¨ï!±¶†ÛnÓWäóòôsúj?®¯.î®6:޼¼<òòònrrŸ™3gŽL&C’$vîÜIVVýúõ#33GGGCò'''œ¯[™¯¬¬$##ãªÃqÊË˶lSU•¾×»fÞÒ´iú;þ[á¶´¬$¦1BBôËy¢ÕjÉÊÊ¢¤¤ä¦–qæÍ›g¨èTWW³víZ¼½½i×®YYY¸^¶´¯¯/jµšüëd@,**";;]}Ö(ýÅÅÅ|öÙg<ðÀŒ7Î(9N½©Tú¥þ›þZj²Evè OÆw¥å—„IOO§òò ³7A·nÝx÷Ýw u•ââbÖ­[GïÞ½±µµ%;;+++Ã4#…B¯¯ïuë*………Ö;ž7Ò§OC®&qü¸>yLuµ¾#ñÃõYÜk¸¸4ý’`ݺé+颮d R©®ym¿QÆŒÃÓO?mH²”™™É¦M› ëûfddÔª«8::’ššzÕ}Ö$¬¨kfÜ:8wî\£óØxxè;ej†¥è‡†êÏ×úºOS®êá꪿s›•eü|ÇŽ·Ìªeee ¾¶_®^gêêjÌÍÍéß¿¿a¹€:àïïORRR÷SQQADDK—.ÅÜÜœ7ß|óšÉëÍ}ªªª"..ŽÀÀÀ+VT”J%r¹¼aiàÍÍÿ]×ë¾ûôíòr㤧LÑ­¼™ë= ×$I©©©¤¦¦6,snˆåÏ?ÿdÏž=L™2…ðšìqWp½2^ZZÊ¥K—ptt¼âHÒÒÒ†Íaµ±Ñgû­9qvﮟÏ1fÌ¿åÙÂBŸ »©Êw+κx3©ÕjâââÈÍͽé25?::šeË–‘˜˜ÈÛo¿}Õ©:Îhýî+ÉÎÎ&)) ÷z^Äu:[¶l¡S§NÜ}÷Ý«ØdeÁèÏñvvúa½¶¶úQ5G꧇Lœ¨ÿ}TTè‡QFGë_?ož¾Âcª¹³­ÔÅ‹)..6Éß®¨¨àäÉ“,]ºKKKÞ|óÍkN½¸Öy\’$233ÉÎήW²ÔÔTŽ=Ê‚ šfÔ@Q‘~ÔL` ~dØÉ“úóûÍHŠÖ\׎5¡êêj.^¼Ø¸N¶F(**bÛ¶m¬_¿žnݺ1õ:kª_«ŒkµZ ;¥Ó鈌Œ4L/©—ü|}gÌåõ ww}&ßÁƒõõš›Q7trÒßàŠŒü·£~Çý²~ ¹ÉÐ’@—Fæù©÷/D&“¥½–Ëå(ŠëVFjTUUñÉ'ŸpâÄ î¹çîºë®+&hºÜõšNNN„‡‡_õ’ššŠƒƒCÃNÏ>ûïBíúÿ-d¢‚ÒìÈårÂÂÂ(//¿é­VËÁƒY¼x1^^^|ôÑG]³"}½“»——×5“mdddàîî^ÿ µµ>óãå.=úžGS®g)\‘••C† ¡¨¨Èèœ|3¨Õj~ùåÖ­[Ç Aƒxá…èܹóU›cu^ë®]»^³SçjT*{öìaúôéï…wsÓWÞýüôÃäk~—C‡êÿ)•ÿÎã63Ó÷ž‡‡ë—¤ÚoˆÑ£G³yóæ›þw+++ùøã9yò$ãÇç®»îÂç:CY¯UW‘ÉdtïÞÝh˜ñõ¨Õj–.]ÊwÞI»†4öt:ýh__}æ[Ðw¾˜›ë3÷¾û®~xdaáÍi° µ8880jÔ¨:RljÉÉÉ,Z´ˆôôt&MšÄرc¯™‡®]WQ(„‡‡_÷wRWdff^q‰ÌkÒhôC{«ªô¾Üß~»þ³ëì÷Þûï”ÁÔTX±âÊ˘µRþþþ 8’F®{SkòÅÅÅÌ›7êêj¾ûî;Ú¶mkTÁ !!¢¢"œQ©TÄÄÄ4:vff&íºª¨„õ´e˾øâ ^ýu†jtG400¬¬,T*äææ’MX#O^%%% +ãIIúxC†Ë ·$•JÅ×_ͱcÇøøãéÑ£‡¡¡(“Éèܹ3)))†Ægll,æææx4f)‹kغu+þþþtíÚµá;Ù²E_‰>üßùËWêTµ¶뤶RÅÅż÷Þ{¨Õj¾ÿþ{Ú´icTWéÔ©»ví¢¸¸'''”J%—.]jò%?²²²HOOçµ×^kØT*صK?:`ÁýüÔmÛàçŸõÛaòdS}Ì‚ edd0sæLzöìÉ‚ °±±1*ãÿ­«äää››k”ŸàFKNNÆÛÛûºµäæêמ7OÿøäIØ´I?Òj†ÚWWÃÒ¥ú9³¢ƒ¨ÞêÝ-¯Ñh8rä¿þú+¿þú+›7o&??ŸèèhÃs5ÿþ;Œ'66–cÇŽ1mÚ4\]]©¨¨ ¼¼œòòrt:!!!äååoH”i”Ü£!òòòê>ÌL£Ñ§·ý:_§Oß”/Bh$Iâ·ß~cذaôíÛ¥Ri(ãJ¥’>}úpîÜ9Š‹‹Ñét$''“‘‘Ñ ;K—+++«ûmµZ_Æ%I¿ÆXn®©?6¡)--eÓ¦M<üðÃPUUe(ã’$Ñ»wo>ŒZ­F«ÕrêÔ)ìììèÔ©S“ÇRPPÀ¦M›øßÿþ×ð‘úŒÎÎ&þd…æââÅ‹DDD0mÚ4\\\jÕUBCCÉÉÉ!!!NGii)gΜit]å¿jÄ– ábe¯¼Ó§ëÏó’“&wÄËdb¾õ-F’$öìÙƒL&ã±ÇC’$C¯™/Þ·o_Μ9Cii):ŽÄÄD²²²njƒ5--­aNNú2_“¡wëV?Þôå\¡Ð7š'L0},-P½®ðfffØÚÚòÏ?ÿÔÚVTTDTT”Ñsaaa8]–ÒùâÅ‹äçç3á ™çöìÙCPPäƒ>0 ‘èÔ©ƒþ;d±ž²³³é^“:úZªªôÙï¸zõÒ/MpyzkA¸Žš—ãÇósM/öÿ{â‰'˜:u*;wîäÍ7ߤGìÙ³‡Q£F5ºg¾¨¨¨nsFÊÊàµ×ôåºsgHO×'ˆ„:JII!33“×_½Ö¶Ï?ÿœ‡zˆ·ß~›7ß|'''8ÀÔ©S›&Ëãlݺ•öíÛãïïßðìÞ­OºÑ«×Mü…æìâŋ俿2~üøZÛöïßO÷îÝ çƒ>`ĈDDDйsg Фq\ºt‰víÚ5¬ÁZQ¡Ÿ«êí­9Pãt -‹R©äüùóœ?žÑ£GmóôôäÀŒ9’;w2{ölºwïÎîÝ»3fL£–˜¬¯³gÏ^¿þ¯Õêo4]þùïR4/½Ô[¶l¡ººšwÞy§ÑCÞ¯æôéÓÜרu" ÒÏO„ÿ7vìXÃZñÿUSyùå—Ù»w/çÎcܸq >¼nçàzHJJ¢GuËM Õê;$krlìÜ©_RcæL“~–Bó£P(xæ™gxàjm«Y6ÉÙÙ™÷ߟþù‡ôôt^|ñÅ›ºþ*è§ó]w>lR’~˜í'ŸèG=ªoœþÿúÉ€~Ú“ÐâÕ«ÁªP(Œ&þOqq1¶¶¶xyy]saxŸë>GGGî¹çî¹çž&;È:+pqÑ/œ”¤/ð“&Ý2Y¼„¦aeeE¯ëÜ©ñòòjòÅåóóó붬MM‚˜šä ï½g¢OJh©éÝ»÷5_Ó©S'¦OŸ~CãP©T¤¦¦6~Þ ˜K$üG]ê*NNNL˜0áŠ#ÆšÊÅ‹ë^JLÔ¯÷øÙgúdKÛ·ë—ì„ÿËå×=oÊd2¼¼¼xòÉ'McEEÅÅÅ×MÊÊž=ÿ6H‡¯¾‚W_5IÌÂUïI?’$‘ÍÚµkÙ¹s'jµ™L†L&C«ÕÈ“O>I¯^½nzæÊ+)..¦²²òúë—étú5™œõkéüÿzT‚М%''cmm}Ýì~À¿™®¡…;vìmÚ´1ŒÎ©·¢"X¼X_¹Éõ„f&))‰ªªªºwÈœ:¥þkf¦Ïú[3‚FZ  .àïïýŽø´4ý’“ ŸÚµ«öÞJÕ»ÁZPPÀ[o½Ell,·Ýv}ûö5dô½téüñ¯¾ú*|ðýû÷7y£µ¢¢—ÚqTT@^Þ¿ë‚)•úô×ï¿/îª -JQQÑõ{!Aߟ”#Fˆ ÿB‹wäȆ Öðk̶múekDcUh†bbb ª{21­V?WÕÌ <<ôuAhÊÊÊØ¼y3ýû÷¿þpøY³ôsVA¿¶i¿~¦_¸AêÕ`Õh4,_¾œôôt/^L¯^½0777¨0vìX>ýôS>ûì3¾ýöÛ’h£> ¯œ°`ï^}ÏÌsÏé<¨¯¼4‡‰Ù‚P™™™Wî…üþ{ýÿš‘ýuåå9¡…)--åôéÓ<ûì³ ÛAI‰> ü´i¦>A¨E’$bbbê–,²Æ}÷铺B Å·ß~Kvv6;vdÔ¨QW±V«Ÿ³*êì·ŒzuMçääpäÈ|ðABCCQ(F½ffføúúò /‘‘All¬©•Juå!c±±ÿ.¤ ú»O#Fè{'¡)((¸ò²MQQú»GyyúÇ—.A` ¸»*´x9998;;×})§ÿ²µÕ¾,'ƒ 4ÕÕÕ$%%ÕomaKKhèÒN‚Ð lÞ¼™€€–.]ÊÇl´ÊˆF£_SuÝ:øñGýt>á–P¯ÖYff&†Þ½{Š¿OOOˆˆˆ0õñQVV†µµuí 2tïkÖèï´>õ”¾Á*-L^^žQ24@¿ÖªL¦_÷kÆ ÈÊ‚‡sš„V!&&† V©ô“¾¾¢‚/4K5ëv_±ÂúNÈœýÿ5ý\ìøxS‡- V³–ñý÷ßå•AªªôõõÂB}’¥]»ÀÇGtÀßBêuµW«ÕuZï±NiØo‚âââ+7X}ôßÞõ/¿Ô÷Òˆ»«B #I™™™WN¸ôÊ+úÔî½{Ãúõ0dˆH¸$´ .\ $$¤þoT©`åJ}UAh¦ÊÊÊP©TW¯kÅÇëç¨ë+ðçÏ‹¡‘B‹vòäIÚ·oõ|EE°u«¾:`|÷Üv›h°ÞBêÕB«éÑ>þ<’$]õu•••¤¦¦Ö¾ëcÅÅÅWžGë⢿û4i’~½ÕóçMª Ô›R©¤   v&I…âß5„y\]õw]¡ˆ'00°~£ÕÕúõú"" S‚ \Õ™3g ºú÷ðp}Gäœ9šªÏ,’‡ -”Z­f×®] >üê/:v ºuÓ×e@?^¡0uèÂMT¯«¿¿?íÚµcÆ dffÖj´J’„R©äÏ?ÿD.—Ó³gOSéé鵇ÕdfÂßë'm¼õ–Hƒ-´HÕÕÕXZZÖ¢öì¿CÄÜÜ`ʰ²2u¸‚ÐhIIITVVÒ¡fù±jµ> Çåt:}CU§Óÿ³¶Ögƒwv6õaÂUedd¨/Ï——kvîÔ|à}V`xé%q~Z¬’’òòò®d,, |PŒ„¼…Õë›W(L›6œœf͚Ŗ-[HLL$##ƒ´´4"""˜7o+V¬à©§ž¢M›6¦>>4MíñðQQùïPOOÑ;)´HÈd2ã«N§_²CÌiZ¡“'OòoöwI‚˜˜;WŸýôú={`Éýü¾ÒRýÒO>©¿%ÍX||<PV_|¡œ ?ý¤?ÇÛÚÂĉú«¯¯)´X±±±ØÙÙáZs÷ôJüýá¿”Â-¥Þ':wîÌG}Ä7ß|âE‹Œ†dI’„••/¾ø"'NDÑ n×—––֞Úš ;‹ž¡ÅÓjµØØØ7XµZý¼&/)%MM’$bcc8pà¿OææÂÇøqPÓI*IúŽI ;;S‡.u¢ÑhÈÎΦmÛ¶úŽ–¤$}磯¯þîjx¸¾±*­Ä¾}û6l˜q'dͨ‚âb}‚1OOýT>á–Uï«™™aaa,Y²„ .péÒ%”J%fffxyyÑ»wo¼½½M}\•••µ×aíÓG$(Z…ªª*är¹qƒµ&)©Ã„&U]]Mbb"O<ñÄ¿Oº¹Á;ï@Û¶ÿvBÚØÀ‹/š:\A¨·ÜÜ\är9^5Ëî-^¬1`k«Ïòþß|‚Ђsþüyž~úéŸ>>pñ¢~Ϊ8— ­”Z­Æ*3“Ž¿ü‡ë¬®®¢Ž.\Qƒç°¶iiiúÿåT*}Ò%AhÊÊÊþïT£²RŸ[Z™´´4úÔœ¿ßzËÔáB“Òh4”””è;!Û¶…˳a B+£T*)ŠˆÀí…`òdS‡#4sõj°VWWCuuõ5_WXXhêãôsAjUæÇŽÕ'¥„V    vìI“à¿å^Z8­VKrr²>‘ŸF£¿³*† ­ˆV«E§Óaoo¯ŸÇ'­X||<ôë‡ù}÷™:¡¨WË-&&†—^z‰œœSÇ]'iiitêÔÉøI''S‡%M¦¨¨Ïÿ®·êïoê°¡ÉEGGcccƒ¯¯/üþ»¾Bfê°¡Éh4ŠŠŠ°V© 6VŒ”ZµS§NÑcð`Ì\]MŠÐÔ«ÁÚ¹sg–.]ŠºŽYýM\qÎËËcĈÿ>Q\ ÿü'Â噃¡Òh4TTTàzùÉ>9 !4ÔÔá B“ÊÊÊ"¸fI²mÛôËB+¢¬®Æ¶°û;ÀÊJ4X…VK§ÓQÁh±T“PGõj°VUU‘žžN÷îÝÿ]ÔºËÍÍ5žÃ‘‘ðÀ¦M-33++«פرC¿Ì‡h° ­LLL ÞÞÞúålÊÊô i¡IKJbpA¶eepǦGn˜üü|z%$ÐN”s¡Žê•~.;;›o¿ý–„„ÃsiiiÌž=»Îw]o–¢¢"ŠŠŠŒç°ž8ýúý»· ´`EEEú üåbbôë— B+R]]Í¥K—èÑ£88Àܹ`ccê°¡édfr!"‚òG7Þ€L‘ Ü0‰‰xa6|¸©CZˆz5XÕj5UUUèt:Ãseee:tI’êõ‡«««Ù·o•••FÏkµZ¢££ùóÏ?9qâDƒÂjµºö’6ýúÁС7ú3ƒÈÈHRRRŒžS«Õ9r„7réÒ%´Zmƒö——‡Óçdÿ·-7ÐÁƒÉÏÏ7z®¢¢‚;v°uëVÒÒÒê}}ø¯ªª*d2™¾¼[X@P©[¸ETUU±oß>ªªªŒž×jµDEEñçŸròäÉÆwÚ/^LîÞ½xúù‰¥l„›*++‹cÇŽÕz^­Vsøða6nÜHlllƒë*W’’–FÔ€àèhêÃZ“¤ËÕét9r„¥K—Ò­[7l.ë)ÿæ›oغu+~~~äååÑ«W/f̘ƒƒC½þFII‰QÀ޽Mq¸Â-*++‹%K–0yòdÃ|îÒÒRæÏŸÏ¥K—pwwç‡~àî»ïfêÔ©õÞNNŽ>›äå&LëR 7…$IÄÆÆòùçŸ3wî\ÜÜÜHNNæý÷ß§¢¢[[[¾þúk^}õU† Öà¿UQQJ¥ÂF&ƒèhýÜ>‘í]¸Át:‡bÅŠa}Y¾úŠ;vàëëK^^!!!̘1£ö9¹®Êʈ/.æ®À@S¶p Ñjµ¬]»–ÌÌLú÷ïox¾¤¤„ùóçk¨«Œ?ž§žzªIþ(Üs©_hAnúÿüùólÙ²…;vàììlÔ󞘘ÈüÁÔ©S¹ï¾ûˆŠŠâùçŸgÈ! ¯ç°¥R‰½½ý¿wX õ‹_>ßOn€¢¢"¶oßÎÖ­[9sæ “&M2l;zô(GeñâÅôèуß~ûo¿ý–»ï¾»ÞóÂËÊÊj =óÂM’’ÂÖ­[Ù¶m%%%†ó¸N§ã?þ ¸¸˜¯¿þ{{{-ZÄO?ýD¯^½j¨#¥R‰B¡À&7V¬€> Vá†:{ö,[·neÇŽ†Î˜‰‰‰üùçŸ<ÿüóL˜0sçÎñâ‹/2lØ0†40‰L¥µ5¹~Ù&A¸ vîÜÉ¡C‡Ø¼ys­r{äÈŽ;ÆçŸNPPëÖ­cÙ²eÜyçËaSP+Và˜˜ˆ÷½÷šú#Z›^»U©T899Pk[DD>>>Œ=…BA×®]8p {÷î­÷ß©ªªú÷έFŸ|7ûp…[N§C£ÑÐ¥K—Z½í‡fàÀ¡P(1b¾¾¾>|¸Þ'77gggýƒòrxðA}ÇŒ Ü` ºvíŠùe Çš;R&LÀÛÛ;;;xàòóó‰mðß;þ<íÚµÃòÒ%èØQŸAUn •J…³³óë*'NœÀÏÏ‘#G¢P( "<<¼Au•9/½„]Û¶ÆIôáR©Tøøøè— ûC‡1xð`ºvíŠB¡`Ô¨QxyyqôèцÿÁC‡àÑGÁÌŒSUUÆ+ÂuÔ«‹ÚÜÜ™LFRRVÿ_aHIIA­VsêÔ)£Š @PPÑp_€°°0ÂÂÂøé§Ÿøûï¿¶%$$`kkk¨„+ :tèÀþýû¯—N§C¥R!I’áŽjYY …BÿX­†¼<¸ÂRh$IB£Ñ˜$˜««+<òqqq:tÈh[ll,Dñÿ‰¿\\\puu½ne^§Óî2™™™¡T*ÉÎÎþ·7>'G?D̹eH’„J¥B£Ñ4zŽh}uìØ‘Ž;ràÀΞ=kx^§Óo´¤™¿¿?J¥’¬¬¬kîS£Ñ R©þ=o_&;;›6mÚè×ÑîÔI {¿…(•Ê&;WW}úô¡OŸ>,_¾œíÛ·m‹ÇÞÞÞ0bÀ‚öíÛ_·2_sMRü7ñ£FCQaa‹X}AhZ5õ×ZSØn‚;þ?Cï… jm‹eøðáXXXúz‹‹ qqqWÝ_Í5I«Õ"—Ëk¿ S'øòK P;Vkä‚Ð:Õ\Û©WƒU&“ammÍòåËž·´´ä7Þ¨õúü‘Ž;ÖyÿJ¥333CA733ÃÚÚš¢¢¢k¾¯¸¸˜½{÷rÿý÷cgg@aa¡¾‚ Iú$—/q#´jZ­–“'OròäIFŽiêp ª««177Çìÿ‡îZXX`aaAqqñ5ß—••ÅÎ;2dh4lll°´´Ô¿ ¸ºtù[Huu5{÷î%66¶ÁÃo„šŽ•ÖÖÖ†5ƒ¯åÂ… ¸»»3dÈZŸtëÖ šÑq 7ǶmÛÈÌÌ4uFRW‘$‰sçÎÑ£GBþ›ÉýÇɵ±wWoA¥¥¥lÛ¶ÍPwm.jê*5‡(ŠkÖUÔj5‡¢]»vÿÖ¿/çé Àùýû 04†…Ö-99™гgÏFí§^ ÖŽ;òÙgŸ¡Ñhêôú¦š‹qÅžšË8::jt77;;wwwýÍÚZ¿Èüe „ÖM.—JYYY­Êosdv¹§žžž >ÜôC©T[·nú¡’¢Áz˰´´dðàÁ”––Öº#ÙÜÈd²ë–ñ®]»Ò¿ÿZç{I’HLLÄÏÕªªÄyü3jÔ(vìØaê0êäZu™LFPP¾ãår¥¥ðÏ?äÜqíÚµ3õ!7™½½=#GŽ$::ÚÔ¡ÔɵÎã …‚ððð+()ìlèÔ‰¸¸¸Ú¿¡Õò÷÷gàÀ(•ÊFí§^5y++«zBµ³³C«Õ†ÌhµZŠ‹‹k'–ù¹\ŽÑ©¤¤„Î;ëÔ4Z…[†L&ÃÊÊÊ0t½¹ppp@©T¢Óé033£ªªŠªª*Ú·oÍ÷™››õ¾kµZ¬¬¬þ½Ãjm-Êø-ÆÌÌ ,,,šUƒÕÞÞÞh ’’,,,®›pÉÒÒ²ÖÐ'1Óh4t8}ÒÒ`ìXS¢pÙÚÚ6»NG;;;rssê*%%%×­«XZZþ{ή‘—®®Ä¥¦Ö;¹¤ÐòÉårlmm¯Û¡w³]©®R]]ýo½ú jFaÖòpð \¸³fÍ#°‚‚}Of^žþŸ 4C† !>>žýû÷“——ÇüF£aÀ€õÚZ­F&“é瀜= 'N˜úй\Έ#8pàgΜ!99™õë×pÍžùkÉËËÃÅÂt:Y%…f OŸ>(•Jþúë/òóóÙµkÉÉÉ Ë—`c]»RVV&¬B³1dÈbcc9xð ¡®¢ÓéoØ»tîÝ),,ÄÉÉIÌ_ê­ÞãlNž<ÉŒ3hß¾½Q*ì'Ÿ|’±cDzeË8À믿~ÍuzöìiThœœxûí·ùþûïyúé§±µµeæÌ™6`!íªª*}²ÄD™È°±±!44Ô(u{PP/½ô¿üò Ë–-ÃÓÓ“wß}×hAúº¨Ilcaa¡&lêÃnANNN„††–o’ÉdÜ}÷ÝäççóÁ Iþþþ̘1£Á”ÜÜ\:õí &ˆu´…›Î××—àà`£aŽNNNÌ™3‡¥K—²oß>ìììxõÕWÖ)“€ÊÑ‘üüü¯S,XkHr=xá…X¹r%ßÿ=^^^¼ûî» Ÿfuï½ —S)ʹРõj°VWW³|ùr:wî̇~ˆ¯¯¯!c˜µµ5ÁÁÁtéÒ777–.]JPPÐUÓV3†1cÆÔz¾oß¾™™‰»»;žÿŸU¬¾JJJô•¨.]Ä02Á$|}}ùàƒŒž377çž{î!,,Œââbüýýk­ÕZiiiØÛÛë+QÝ»‹ù«‚IüŸÎkkkž}öYÆŽ‹F£Áßß¿Á•­VKBB‚~B~'‚ÐXcÇŽeìæM÷ïߟN:‘••…‡‡ û‹“:t(mÚ´ÁQ,K&˜À´iÓj=§P(˜0a}úôiT]Åàÿ硉‘BƒÔ«ÁOVV¯½ö>WY"ÆÒÒ’{ï½—7ròäIÆWï \\\U “““±··×ÿ¸nðG(õçççר,ÚÅÅÅÿ¦oÀA¸‘äry½–4»FCII GBx84³¥„[›«««ÑšzS*!+‹SyytíÚÕÔ‡#µ4¶®‚V óçë“åõéCTT”È,4H½æ°£Õjñññ1d¥´¶¶fâĉFãÚÍÍÍqtt$66Ö$URR‚ŸŸŸ>Ƹ8}RAhE²²²ô2:¾|7rAfAhŽ´Z-Öee¸nÞ,–lZŸòrè×ÌêjüýýM 4½²2ý´¥ÿ_ꦠ àª7¼áZêÕ`µ³³C.—-liiÉwÜAïÞ½ Ïét:T*•É–ZHMMýwhÍ[oé×9„V¤¼¼\ß³ 3gê×§„VF­V£9}סCÅüU¡õquE÷ꫜ9{–^½z™:AhzÕÕàáa혒’Ò¸Q Â-«^ Vooo,--9vìjµúН‘$‰¤¤$èÑ£‡I*77Wÿƒˆ‹ ãå…V¦°°Pß)S\ ÎÎúr.­Luu5EÎΘ?ð€©C„¦%IP]Mqq1ùùùv)Í•«+L›vv¨Õj*++¯»^± \I½¬žžžŒ5ŠuëÖñÏ?ÿ T*¶×,yóá‡Ò½{÷ZÉ8n–ââbýÉ¿¬ î»Ï0Ù[Z‹ììl}§LI ôî-ʸÐ*EGGã=`о}MŠ 4­ÂBøî;Š33ñóóC.—›:"Ahz …~­a¹œ .àîÈ-#4@½k¹<ðIII,^¼˜M›6Ñ¿¼¼¼(,,äìÙ³œ:u ^|ñEœMrPYYYú¬’ÁÁú ª‚Њ¨ÕjT*•>éÒeKK Bk“œ˜H»»~®¶Y½— „æ+?bbÈ 1Z2GZ ­Ö­Óß8²´$99™SG%´Põn°º¸¸ðÎ;ï°oß>¶oßκuë `Ú·oÏ<À]wÝe²ÕÕÕäçç î: ­R^^F,¼-´zÚK—¸]£ V¡õIOOOJªªðúÿ„4‚Ъ¤¥Á¶mðàƒœ9s†Aƒ™:*¡…jP‹ÎÆÆ†qãÆ1|øpª««Q«Õ˜™™aii‰µµ5æ&l(VWW£P(ÀêÕðÒK¢¢#´*ú»«¹¹°i<õ”©C„&§ÑhðE>v¬è|ZŸ¾}¡Gâ7l C‡¦ŽFš^T”~”£¹9………$%%ñÒK/™:*¡…jp-@&“ammµµµ©ÁHee%³Ü\¸pA,÷!´:yyyØÙÙA|<ÄĘ:A¸!Š‹‹qV©°8ÐÔ¡BÓ³·{{rrrèÒ¥‹©£„¦×¦~þ*úållmm›]›Ah9ZÝ­G•J…ƒƒæJ¥¾gGÜ]Z™òòr,--!1DϼÐJ¥¦¦òKÛ¶"Ðú”—ÃéÓ”––âîînꈡéõèÿ?g5)) }ÝE Õ³R*•ú!ÁÝ»CP©Ã„&WQQ¡ŸóÔ¿?ˆ“¿ÐJ••–âíç&ZÏ[n˜³gaóf¤^½HII1Y‚JA¸at:}Ò¥ÿO(I×®]E6l¡ÁZÝíÇÊÊJÌÌÌ»º‚¨ì­NNNŽ>áR@€~È ´Fññô//7u‚Ðô΃Nˆ‰‰ÁÉÉI¬Á*´>»vÁ»ï¦¤¤ÐµkWSG%´`­®ÁZRR‚‹¥%ægÏš:Ahr:Ž’’Úx{ë×`s´…VÊ1!!âΓеi#GO &´FgΆçääP\\,æj Òê¬ééé¸$'c¶q£©C„&§Õj)((ÀáÔ)øì3ý°Ah…’öíìgOS‡!MïÎ;¡];NŸ>M§NL 4½ÊJèÓÐîÖ­VVV¦ŽJhÁZ]ƒµ ?·äd 3u(‚Ðät::ë¨(}óA„Vê £#¥"©˜ÐJUTTK˜¨«­ÑôéЦ :޳gÏÒSt> Ôê¬Êêjœ»tðpS‡"MN«Õ¢T*±°³ƒÐPS‡#7Daa!)¶¶Øøû›:A¸!Š‹‹±µµÅÞÞÞÔ¡BÓsv33ÊË˹té’˜¿*4Z«k°fçæbóøãàéiêP¡Éét:T*–3f€HÔ!´R1çÏ3¤}{±‚Ðj¡P(PüUAh***°±±ÁÅÅÅÔ¡-\«k°–––â!² ­”N§ÃÜÜ[77±Æ°Ðjå:Å£ÅŦCn˜ääd<==õß¡•ŠŠŠÂÎÎ;;;S‡"´p­ªÆ«Õj ={ß3gLŠ Ü ~[¶`Ÿ“cêHᆱˆ‹C&–lZ±¸¸8‚‚‚0B+¶gÏF-:f„FkUgÊÜÜ\Âär,ÜÝMŠ ÜÕ¥¥ ±²Â\œü…Vª²²’¢¬,¬»u3u(‚pÃdffâããcê0á†III!..Ž>}ú £…FjU Vo{{ú…†B¦En ÿþÈÄm¡•ÊÏÏg»£#÷ßoêPá†P*•ÄÅʼn%m„VK’$<È!Cptt4u8B+`nêþ«²²’'Npþüyüýý:t(uë±´„Ù³Aü8„fJ’$JKKÙµkÙÙÙ†MÞoåîo¿ b>ˆÐLét:²³³Ù¾};Z­–°°0ºwï^çä2ùyyX‹B3WQQÁ‰'¸páíÚµcÈ!u®«$''ãç燫««©C®H’$JJJعs'yyyZ纊R©äøñã<òÈ#¦>¡•hvwX?úè#>ùä X·no¿ý6EEEu{³BbÞ“ÐŒ1sæL6lØ@^^}ôK–,©ûlm¡cGS† \ULL /¼ðÇŽ#>>žY³fñÏ?ÿÔùýæ……ŒV*M}‚pMóçÏç³Ï>£  €5kÖ0wî\Šë˜(,::ZÜ]𵂂^yåþúë/rss™?>_~ùeߟŸŸOII ¦>¡•hVwXÏŸ?Ï‘#G˜5k#GŽ$55•'žx‚C‡q÷Ýw›:ø ECThá´Z-¿þú+ŽŽŽ|òÉ'XYY±|ùrÖ¯_Oxx8žuÊîR^Î0­ÖÔ‡"WuîÜ9Ž;ÆìÙ³>|8ÉÉÉ<õÔS9r„;î¸ãºïOOO V¡YÛ½{7YYY|ýõ×øûû³}ûv>þøcî¿ÿ~:tèpÝ÷ïß¿Ÿ=zàììlêCZ‰fu‡õüùóxyyÑ»woär9¾¾¾ôë×cÇŽ™:4Ah‘‘‘ôéÓ‡6mÚ —Ë Á××—ˆˆS‡&¦Ó鈌Œd̘18::biiɨQ£(--%11±Nûð³³ÃµgOSŠ \Õ¹sçðõõ%,, ¹\ŽŸŸ}úô©s]e̘1 :ÔÔ‡!WI¿~ýðóóC.—†··7§NªÓû³³³¹çž{Dl¡É4«’”€­­-NNN( ˆ‰‰1uhMn×®]¤¥¥™:Œz9pàñññ¦£E‹ÅËËËâÝÕÕww÷VWÆ+**ظq#Ê4´³ººš¿ÿþ›ÒÒRS‡ÒbI’D||ÍéÓ§MÆM׬†kµZd2™¡GF&“annNEEÅUß#IiiiDEEѶm[ÌÍ›Õ!]ULL /^lQÃ%âããqttĽ,T“0 %%…ñãÇ›:Fƒ™™™!1‡\.G.—SYYyÕ÷hµZbccY¼x1ÎÎÎ-¢Œ+•J.]ºDQQQ‹ˆ@­VséÒ%²³³±²²2u8×¥Õj)(( ##ƒ~ýú™:£¸är¹á±B¡@«Õ^³óB¥RqðàA222pvvÖÿ>šù¹¬¬Œ”””ºçXh***HHH ¬¬ÌÔ¡ÔYJJJç†Þ, ©«²wï^Š‹‹qpp0õ!ÔI~~>EEE¤§§›:”:+**"77—ììlS‡R'†„„¼¼¼LJ­¸þ[W133»f]¥ººšßÿóçÏ·ˆk(è;ñJKKIHH0u(u–––†L&#**ÊÔ¡ÔIee%‰‰‰ 4¨Qûi5Ék-8lnnÎÔ©Ský¸š;I’ZL¼-1fN‡$IX[[›:”ëºVUÞzë-´Zm‹+ã-%Ö–³$Ièt:d2Y37šŠ™™Ù5;.Ú·oϼyó ¯m ZÚùðò¸[RÌ5ç½–àZu???.\hÔÐmîZboi1לÇëšEÝÔ®gXXݺukqõh9å¥%Æ\SÆۉѬ¬NNN¤§§£T*±´´D£Ñ——‡··÷UßÓ*k‚PÃÅÅ…ªª*Ã]¨òòrÊË˯9tÆÌ̬E gggÊËË óóóQ(†©W"—˱··7uè‚P'NNNäääÕUòóó¯YW177o1wVÁÅÅ…ÊÊJ£ºJEE]»v½ê{ E‹ix -O³êæëׯ999$''úa…'Ož¤oß¾¦MšÄ Aƒ8}ú´aèXzz:ÉÉÉôéÓÇÔ¡ B£ÉårÂÃÃ9tèá¹Ó§Ocee%²` ­Fxx8™™™¤¤¤PUUEDD„¨«­Æ AƒˆŒŒ4 NMM%--Þ½{›:4áÕ¬¬={öÄÖÖ–U«VǺuë(--eÈ!¦MšÄÀÉÏÏç?þàÒ¥KüüóÏ8::Ò«W/S‡&fffÆèÑ£9uê;vì ""‚5kÖгgOüýýMž 4‰ž={bccÃ/¿üb¨«”••1xð`S‡&MbРAäååñçŸê*ÎÎÎôÜ‘I5ƒ¡›‰øøx~øábccñõõeÊ”)ôéÓ§ÅÌù„kÑét?~œ+V——G=˜2eŠX“Oh54 ›6mâ?þ@¥RѧOžzê©•`N®'..Ž~ø¸¸8üüü˜2e ½{÷u¡UÐét;vŒ+VŸŸOpp0S¦Li™…Ö©Ù5XAŸÉ°¤¤;;;1çCh•ŠŠŠ¨ªªÂÅÅ¥ÅdÓ„ºÒét Óépqqóš„V©¦®boo/æ` ­’¨«ÍE³l° ‚ ‚ ‚ ‚»"‚ ‚ ‚ 4K¢Á*‚ ‚ ‚ 4K¢Á*‚ ‚ ‚ 4Kòwß}÷]SÑÒedd°gÏ"""Ëåxxx¶ét:âããÙ½{7ÙÙÙxyy% Ñh4œ8q‚Ç£R©pww7Ê2XYYÉŽ;ˆŠŠÂÊÊ GGGd2Y“Å^RRÂæÍ›éÔ©r¹I’HNNf÷îÝdffâææ†¥¥¥QÌgΜáÀTTTàééix/€J¥bÇŽœ;w EæÄL§ÓË®]»ˆŽŽÆÉÉÉ(šF£áôéÓ;vì0”‡Ëðèt: ×OOO,,,š4þ .c´tZ­æàÁƒœ8q£˜‹‹‹Ù±c±±±ØØØààà`(Ã’$‘’’®]»ÈÈÈÀÝÝÝè ´<•••QVVÆÛo¿Íž={˜ûŒï¾ûŽÊÊJ¶mÛÆÙ³géÛ·/VVVäååñú믳ÿ~ Yµj*•а°0Î;ÇË/¿Lbb¢a}ºîÝ»ãíímê¯Kh€ªª*^~ùeÖ¯_F£áèÑ£¬Y³†   ¼¼¼ÈÍÍåµ×^ãàÁƒ°jÕ*´Z-!!!œ={–—_~™¤¤$CyÆËË €ß~û÷Þ{ââb>ÌÞ½{ k² ø Ìš5‹ÒÒRFŽ è£³gÏfÇŽ³víZŠŠŠèß¿?/^dÆŒ\ºt‰„„V­ZE‡hÛ¶-Û¶mã7Þ °°'N°uëV£k€Ð²$%%ñÌ3ÏAee%ýõ;vì`ذaØØØÍŒ3ˆ%!!Ÿþ™N:ѦM qu‚Æ’$‰cÇŽ1sæL ôK Θ1ƒ .’’ªU«ðòò¢cÇŽ"n $I‡bÚ´i¤¦¦’ŸŸÏªU«HOO',, öíÛÇ+¯¼BAAlÞ¼Ù¨<4¦NÐX:Žß~û¹sçr÷Ýw:eŽ;ÆK/½Dvv6çÎã÷ß§W¯^†íßÿ=‹-¢¼¼œ={öpâÄ z÷î ¥¥¥¼ùæ›lݺ•ââbÖ¯_OAAááá¦þºN¬  @š}º$I’´fÍiäÈ‘RBB‚¤R©¤+VHcÆŒ‘233¥ŠŠ iÖ¬YÒ´iÓ¤‚‚©¸¸Xzíµ×¤éÓ§K¥¥¥Rzzºtï½÷Jß|óá0nÜ8iéÒ¥’N§ktìFš={¶Ô­[7iöìÙ†çÿþûoiøðáÒÙ³g%•J%ýöÛoÒ Aƒ¤´´4I©TJï¾û®ôè£JyyyRii©ôÎ;ïHO?ý´TTT$eggK“'O–>ûì3©¬¬LÊÉÉ‘î»ï>iñâÅ’Z­6õ×%4ÀW_}%Ýu×]Rll¬¤Õj¥ÈÈHéî»ï––/_.UWWKsçΕžxâ Cy˜3gŽôÌ3ÏHÅÅÅ®4Vvv¶ôØcI]ºt‘Ö­['I’þÜþÑGI<ð€”““#•——K}ô‘ôÈ#HR~~¾ôøãK~ø¡TZZ*åååIS¦L‘æÏŸ/)•J)66V9r¤ô믿J*•Jºxñ¢4hÐ iëÖ­¦þª„P©TÒsÏ='=ÿüóR~~¾¤T*¥Ý»wKÇ—öîÝ+åååI>ú¨´`Á©´´TÊÍÍ•&Ož,}ôÑG†òÐÐ:Acét:éìÙ³Òí·ß.uîÜYЉ‰‘$I’ŠŠŠ¤gŸ}Vzûí·¥ââb©  @š:uª4wî\©²²RJLL”Æ'­ZµJR*•RJJŠ4hÐ é÷ß—$I’¶nÝ* >\:}ú´¤R©¤?þøC0`€”––f꯫ÁZî½áf ªªŠ²²2&OžŒ““ÖÖÖŒ7Ž¢¢"Š‹‹‰‹‹C¥Rqçwbmm··7ãÆcïÞ½€¾÷¤G„††¢P( ¥k×®>|€#GŽpÇw†ÜyçTUUqñâÅFÇž––Æ×_ÍĉžOII¡  €‰'bkk‹§§'wÝu‡F©TrüøqG¡PЭ[7BCC9xð Gå¶ÛnÃÇÇKKKÆŽ‹B¡àìÙ³¦þº„ÈÏÏÇÞÞž‰'†\=š””´Z-ǧsçÎôïß…BA÷îÝéÕ«‡ôåaܸqx{{ciiɸqã033ãܹsÍý÷ß““ÎÎÎ<ðÀœ={–¼¼¼FÅ-IGåŸþáî»ï6ÚvêÔ)¼½½:t( …‚€€ À 16ŒvíÚ¡P(9r$NNNDDDP^^ÎÙ³g™8q"...888ðÐCqñâE222Lýu œœLïÞ½üðCCÕh4DGGãåå…™™™¡<ÔÌÙ³¶¶ÆßßÿªeØÇÇ…BAJJ ååådff•—ÀÀ@²²²(--mTÜååå¬X±‚ñãÇÓ®];£m‰‰‰ØÚÚ*@ …‚Ž;Åìëëk˜ âáჃ TWW“ššjs—.]ÈÏϧ°°ÐÔ_—ÐãÆcúôé†á‹ÄÅÅáççè˃ŸŸŸavvv$$$PUUEZZZ­2œ——GQQYYY¨T*Ãð`З—ØØØF7Xcbbøã?xöÙgæõÕÄìíím8&ÜÜ܈E£Ñ””ds@@eeeäææ’——Gii©áøkŽ)11µZmê¯Kh€çž{މ'Êpvv6ÙÙÙøùù¡V«INN®UJKKÉËËkt ¡t:{÷î%))‰Ç{Ìhx±$IÄÇÇ][Úµk‡J¥"++‹ÂÂB jý.SRR¨®®&)) œÚסeQ(,X°À0MC§Ó‡$I¸ººRPP@aa¡aˆ;èËCrr2J¥²Qu‚ÆP«Õüú미»»3nÜ8£m¥¥¥äää•ñÀÀ@222(//'%%sssù_&“Õj_xyyæš»¸¸àááALLŒ©¿® ÖF°´´¤sçÎ( 4 ›6mbÖ¬YLš4‰Î;£V«‘$ sssÃ{¬­­ •q•J…\.7\Där9”””ú†ååïµ´´D§ÓQQQÑà˜u:7n$>>ž'Ÿ|²V" FƒV«­sYY’$ÕŠÙÌÌìŠ1×$>¸¼(´<ŽŽŽ†9A%%%üôÓO¬X±‚^x++«+–aKKË«–áË˃N§C£Ñ%þ°¶¶¦ªªªQc¥RÉ·ß~k¸›õ_*• 333ÃÅÇÌÌìŠ1×”a…B™™™á7 V«kÅ\]]-î>µPžžžøøø’´,Y²„'N0uêTàÊç4333ÊË˯[Ôj5:îª×€†ª¨¨à‹/¾`äÈ‘†9}—S*•Èår£2¬P((--½bÌ5¿åêêê«^ÊËËÑét¦þº„h×®...èt:bbb˜3gjµš|ðªeX©T^³<ÔµNÐP©©©,]º”ÿýïFå*•Ê(&+++4 •••hµÚ+^[***Ðjµ¨T*d2™á “ɰ²²jtÌ‚i˜™™Ñ¹sglllÐh4ìß¿ŸY³f1`ÀúõëW§òÐÐ:Acìß¿ŸmÛ¶ñâ‹/ÖÊipµ˜+++Ñh4†:ÒÕÊð¯æææ†k@KeÞø]ÜÚt:ÑÑÑ,_¾œÌÌLî»ï>~øa£,_ÿu½Lt×Ú~ùI¶!’’’X¹r%Ï>û, Ï úá×Êrz½¿yù…ãJ1·äÌd·ºšLs?ÿü3jµšY³f1tèÐk~§)fffʸ»wï^öîÝËgŸ}Fee¥á¢”››‹££cƒb†kÿÌÌÌDoÁÊËËÙ¾};k×®ÅÃÃO>ù„=z\ó=×;O_«<4æ®V«Yµjjµš#FŸŸo¨œäåå’ˆÔ÷ïÖ”á«5JEÕ–K’$ŠŠŠX¹r% W¯^Ìž=WW׫N¿¸Þ9­1u‚ë)//çÛo¿%((ˆ:››‹N§£¬¬Œ¢¢¢«Ö¯.ot\mûµ®-‰Y0-NGjj*ßÿ=qqqŒ1‚É“'elÿ¯ë]³S'¸žÂÂB¾ùæî¼óN,,,ÈÍÍ5<_Ótµ˜S†[òy\ü:A§Óqüøq>ùäBCCyùå—nßÛÚÚ"—Ë©®®6džËÏÏ7duttD©T¢Ñh077G©TRZZŠa{ee¥aÅÅÅÈåòkVH®çèÑ£äææ²bÅ ~þùgÃÏ™3gòÀàää„B¡ ªªÊpQÈÏÏ7,UâèèH^^ž¡GV­VR€_³$IÈd2ÊÊÊÐjµ¸»»›úë@«ÕòçŸòÓO?1qâDÃ<§ŽŽŽ”””•‡âââZå¡Fii):777 666TVVÊt^^ža>xCíÞ½›òòrj çååQXXÈ´iÓ˜={6ööö¤§§£R©°°°@«ÕRTTdsUU:Îp'M¥R~¶¶¶FÇT3Ï·©—ãnµZÍ¢E‹8}ú4S§NeÈ!ØÚÚ¶×”‡šsZyy9jµúªå!//lmm±±±¹æ5 !JJJ Ù*ßxã @Ÿ{ÀÌÌŒY³f1þ|©®®6”áÊÊJ*++éСfffØÛÛÅ\PP`˜£®T*±°° ²²Ò0àòk€Ðòäææòþûï£V«™1cƒ 2º#jggW«<\¾ÔQcê ‘œœLdd$ÖÖÖ̘1Ð×Ö¬YCrr2Ó§OÇÁÁÁ(梢"Ã’S–––XYYÕ*Ã5×{{{õšk@aa¡ÈôÞBI’DTTóçϧ]»v¼÷Þ{F#O®Vj–vjL ¡"##IMMeóæÍlݺÕpÇôÃ?äÎ;ï$,,Ìp¸æwWÓ!iii‰’$¡T*±´´D’¤+¶/´Z-r¹ÜÐyh꯫ÁÄ-F(((`Ñ¢EÜqÇÌš5Ëh¾`.mxîØ±côêÕ €þýûo˜ûVXXHll¬!Fÿþý kè~)I’hß¾}ƒc1b‹/æ•W^aúôéÜÿý€~ŽË€h×®ÎÎÎFI’Ž=JPP …‚þýû“ššJvv6 ï =þ¼Ñ1EDDz‡âã㩨¨ sçΦþº„8þmó™3g ””òóó ÂÎÎŽîÝ»Å|üøq¼½½›l)áæÚ±c§Nâý÷ßgìØ±FUЗ‡Ó§OÊCrr2………tíÚ{{{‚‚‚j•a___ÜÝÝéÔ©VVVDEEmnð(fϞ͜9s e¼f¹gžy'''ú÷ïOTT”¡C233“´´4zö쉥¥%½zõ2Š922GGG|}}iÛ¶-®®®œ9sưýèÑ£tíÚµÉ×nŽ•+WRUUŇ~ÈàÁƒî,YYYÕ*§NÂÅÅooïF× Âßߟùóç3kÖ,C·³³cäÈ‘†Ä9}úô1ŠùüùóXXXжm[|||hÓ¦ 'Ož4йfØhhh(………¤¦¦úáÅ‘‘‘ŠY0µZÍÂ… éÖ­ï¼óݺu3Úîçç‡Q’¤šò`mmݨ:AC…„„ðùçŸ3sæL¦OŸÎ“O> À#<¨Q£ðòò¢C‡FeøØ±c´oßGGGzôèAUU‰‰‰€¾Ñ~üøq£˜/¿dee‘œœ\+A_K"î°6BVV/^ÄËË‹¤¤$£m=ö:uÂÇLJõë×ãîîNbb"‘‘‘†^ñððp¾ûî;þùçî¸ã6nÜHii)ƒ `äÈ‘|õÕWœ8qÖ­[‡¿¿£Öaõññ1ÜÁ =7áááØÙÙëÖ­ÃËË‹ÌÌLŽ9Â3Ï<ƒ……}ûöå“O>᯿þâÁdçÎäææ2dȆ Ƽyó8räíÚµcݺu¸ººŠuX[ I’ˆŽŽ&##ƒ;v°{÷n£ísæÌ¡oß¾,\¸M›6qß}÷±mÛ6òòò åaøðá|øá‡9r„6mÚ°nÝ:ÜÝÝéÞ½;2™Œððpþúë/ºvíŠR©ä¯¿þbÈ!µÆõÑ¥K£ßÈ¥K—8uê”áwŠ$IlذÇœƒ’ššÊ믿À!Cضmû÷ï'88˜uëÖammMhh(r¹œAƒ±mÛ6z÷î™™ëÖ­£ÿþF¿+¡eP«Õ=z”’’Ö¬YcT‘÷ðð`úôé :”·Þz‹ĺuë°³³#$$¹\ÎÀÙ²e ¡¡¡¬_¿žâíí««+~~~¬_¿’’’ˆˆˆàÕW_mpƒÕ¢Öùô×_ÅÎÎΰÎê Aƒøý÷ßÙ½{7áááüöÛoH’dXsèСüñÇ 4Ö¯_O¯^½hÛ¶-†®]»²nÝ:¼½½ÉÎÎæÐ¡C<ùä“bʨªªŠ£GúµG//waaaÜsÏ= 2„72`À¬¬¬X·n!!!´mÛµZݨ:ACÔ4H/gaaA@@ÁÁÁH’Ĉ#X±b8;;³nÝ::wîL@@:ŽÐÐPÖ®]‹¯¯/………ìÞ½›ûï¿;;;zõê…L&ã·ß~ã©§žâÈ‘#¤¤¤0sæLS]B”––rêÔ)är9óæÍ3Ú6~üxzôèA¯^½ å!??Ÿ½{÷òðÃckkÛ¨:AC¹ºº2pà@Ã㚟š Þ*•Š~ýúñÛo¿Ñ¡CÊËËùçŸ7nNNNtïÞ;;;~ýõWžyæΟ?Oll,O?ý4 ¿¬_¿ž]»v1pà@6lØ€N§3\#Z"ù»5ãæ„zËÌÌ4ÌU*•Fÿz÷î½zõâàÁƒ¬Y³†3gÎ0eÊÆ‡\.ÇÞÞžŽ;ò×_±nÝ:*++yå•WèÔ©2™Œ:`nnÎòåËÙ²e ÞÞÞ¼òÊ+†ÌvM¡ªªŠÜÜ\n»í6CbŽÐÐP>ÌÚµk ËLœ8sss¬¬¬èÖ­[¶laÍš5äææ2}út‚ƒƒ133£M›6899±lÙ26mÚ„««+3gÎC‚[ I’ ™ U*U­2>zôhìíí äï¿ÿfÍš50}útzôèL&£M›68::òÃ?°yófÜÝÝ™9s&nnnÈårzöìIll,¿üò ‡",,Œçž{®Iïäafff¨@YZZÄŽ;øå—_HMMåÅ_¤OŸ>˜™™áåå…‡‡+W®dÆ ØÛÛóꫯ2#‘••ÅÏ?ÿÌÞ½{éÚµ+3fÌ•ùH©T:ÿ[Æ---2dÞÞÞ¸¹¹±råJþøã™9s¦¡1ǯ*++3dýï9ÜËË‹ž={ÒµkWÃ×Ý»wÀ+¯¼‚M£ëM%11‘ÐÐPÚ¶m‹L&# ­VË?þȶmÛhÓ¦ ¯¼ò ˜››Ó§OŽ;ÆÚµk9~ü8£Fâ‘GA¡P`iiI÷îÝÙµk«V­"99™iӦѷo_‘‹ ÊËË###…BQ«ŒwëÖ:лwoCy8qâcÆŒaÒ¤I†òÐÐ:ASQ«Õ¤¤¤0räHËå„……qön /‹€IDATìYÖ¬YÑ#G0`O>ù$XXXУGöîÝË/¿üÂÅ‹yî¹ç #(\\\ðóó3\är9¯½öšQ¦ä–F&56·¾p]ååådggcgg‡§§g­žõš%<==k%…Ñét¤§§£V«ñõõ½i•⊊ ²³³±¶¶6TÌ.WXXh˜r¥á›éééTUUáççרùˆBËPSÜÝݯء’––†R©ÄÏϯVV*•dff"—Ëñöö6ÊŠw#“››kXòã¿233)//§M›6µÊ°Z­&##™Lf´|ˆÐzeddPQQqÅò R©ÈÌÌD&“–nº\Í5 fË›U)ÎÎΦ´´__ßZC5 èt:|}}k•áÊÊJ²²²°¶¶ÆÓÓSÌ_måjʃ$IøøøÔ*­ÜZ­–ŒŒ 4 ¾¾¾µV=¨ªª"++ ¼½½k•á’’rrr®z Z—šò`ii‰——W­òИ:ÁR]]MVVæææx{{×ê4¬YþÆÑÑñŠÓ’j®>>>->φh° ‚ ‚ ‚ Í’û ‚ ‚ ‚ 4K¢Á*‚ ‚ ‚ 4K¢Á*‚ ‚ ‚ 4K¢Á*‚ ‚ ‚ 4K¢Á*‚ ‚ ‚ 4K¢Á*‚ ‚ ‚ 4K¢Á*‚ ‚ ‚ 4K¢Á*‚ ‚ ‚ 4K¢Á*‚ ‚ ‚ 4K¢Á*‚ ‚ ‚ 4K¢Á*‚ ‚ ‚ 4K¢Á*‚ ‚ ‚ 4K¢Á*‚ ‚ ‚ 4K¢Á*‚ ‚ ‚ 4K¢Á*‚ ‚ ‚ 4Kæ¦àV§T*)//G’$Ãsr¹{{{ÌÍÍÑétdff’——‡§§'ÎÎΨT*Édèt:²³³ÉÊÊÂÁÁ,,,P©TTUUaiiIBB†:`ccCbb"eeeøùùáîîŽL&£¬¬ ¹\NEEiii899ѦM*++IMME’$±°°0õG&´"EEEdee Ê–pË((( 77—€€ E£÷—‘‘R©¤C‡¦>4AAhr¢ÁjbÛ·oç‹/¾0j°zyyñî»ïÒ©S'N:ÅK/½Dff&;vdܸqäääðþûïcccÃÆY²d ¸¸¸pÿý÷3cÆ ¢££Y¾|9nnnüþûï¨ÕjÆŸŸ+W®¤¨¨ˆ®]»òã?âëëËW_}ÀˆŽŽÆÕՕ矞pôèQt:O=õ¯½öææ¢ØMãäÉ“|óÍ7|ÿý÷xzzš:A¸):ĪU«øþûïquumôþÖ®]KFF‹/6õ¡ ·¸ŒŒ "##9r$666¦GnNÇ™3g(//gÈ!¦ç– †›Ø°aÃøâ‹/øüóÏ™?>VVVTTTàääD||<Ï<ó wÞy'.\àå—_fáÂ…DFF¢Ñh8sæ 3fÌ`âĉ¤§§óÅ_ðÓO?ñÃ?PPPÀŸþ‰$IDEEñã?²xñbŽ;ÆÞ½{Ù¶miiiüöÛo\¸p/¿ü’ùóçséÒ%zôèÁÌ™35jgÏžeæÌ™¬^½š‹/šú#Z¥RIaa!Z­ÖÔ¡ÂMSSîu:]“쯼¼œ’’S– ÁôéÓ)((0u(‚pÃhµZ~üñG.\hêPnâV™‰988Э[7´Z-ß}÷™™™üüóϸ»»sðàAÊËË™>}:vvvÜqÇŒ5ŠÌÌL~ûí7ºvíʤI“¨¬¬$,,Œ|7ˆ=ôæææ„‡‡0yòd\\\P(¡T* ±Œ=šBBB8|ø0÷Ýw666 <˜ï¿ÿFcêLha’’’HKK3zÎÑÑ‘nݺ I………lذüü|†ÊÀ±´´D’$Š‹‹ù믿ˆ‹‹£ÿþ <ggg4 ÑÑÑ899qáÂŽ?Npp0cÇŽ%22’}ûöáêêʤI“°±±áâÅ‹¸¸¸púôi""" e̘1=z”ÇãããÃ<€½½=2™ÌÔ›ÐÂÅÅÅ‘••eôœ³³³Q¹ÏÎÎfõêÕ”––2|øpú÷ïB¡@§ÓQTTÄï¿ÿNjj*ƒ bÀ€8::¢R©ˆŽŽÆËË‹ÈÈÈZ I’ÈÌÌ$--,--MýQ­Ì¹sç(..6zÎËË .]ºDuu5gΜÁÑÑ‘œœär9ìÚµ‹Ù³g“žžNYYJ¥’þùWWWî¼óNª««Ù¾};………L˜0   RSS©®®¦´´”mÛ¶áííÍwÜAII ;vì ¬¬Œû￟N:‰ó¶Ð¤jʱJ¥2z¾k×®‘™™Iaa!gÏž¥cÇŽÄÇÇãííÍÉ“')))aÒ¤I”——sðàANž<‰§§'ǧsçÎÈd2.^¼ˆ¥¥%)))ìß¿ŸN:1nÜ8’’’ؽ{7>ú(¢l#¬Í‚V«å?þà»ï¾cÉ’%tïÞ€ÈÈHÜÜܰ³³ôs[}}}ÉÌÌD©TO\\“&M2ì+''3334 vvv¸¸¸ý­š}Éd²Zs§Ú´icôX.—†ô( ñƒäï¿ÿ6œ|Ž=JÏž=Y·niiiL›6ÀÀ@ª««Yºt)K–,áÁ$>>ž'Ÿ|…BA·nݘ;w.îîî¬_¿¹\ÎK/½„$IøúúbnnÎ7ß|C¿~ýËåxyy±zõjŽ;Æ»ï¾ËsÏ=‡µµ5ÞÞÞH’Ä×_Í AƒË帹¹±råJ"""X¼x1ÖÖÖ¦þØ„î÷ßçøñã†Çû÷ïgÈ!¬]»€øøx^|ñE)))á»ï¾ãÇdìØ±\¸p§Ÿ~WWWÚ·oÏÌ™3éÖ­Ë–-£ªªŠgŸ}–6mÚ••ÅwÜaø’$qöìY^|ñEÆG¯^½Lý1­ÐÒ¥KIOO7<þçŸxæ™g˜:u*'Nœ ¢¢‚]»vÑ­[7,X@FF¥¥¥øùù°zõj–/_N`` þþþ¬Y³†+Vàè舿¿? üøãìÙ³‡eË–ñçŸÒ©S'Ú¶mËÏ?ÿÌŠ+°³³Ãßߟ˜˜Ö¬YömÛjÕa¡1 ùôÓO #Àòòò8vì›7o¦ººšøøxÊËËÙ½{7–––<ýôÓtèÐŒŒ ÆZ­fÖ¬Y?~œ~ýúqôèQ/^ÌæÍ›éܹ3sæÌ!55•¶mÛâââÂ?üÀŠ+°´´ÄÏψˆvîÜÉÚµkqss3õÇar¢ÁÚ œ={–÷ߟgŸ}–!C††µ†JÖ<677ÇÊÊŠAƒñÌ3϶WWW£P(Äð0¡Ùxúé§ùßÿþ‡N§cß¾}$&&òÄOàèèèËìc=Æÿþ÷?ª««yâ‰'8vì>ø ?üðÖÖÖüðômÛ–'NðÌ3ϰiÓ&&L˜@‡øâ‹/P(<ñÄÄÅűfÍ:tèÀ?üÀO?ýDii)ݺuã£>B&“ñÐCQTTÄÏ?ÿŒŸŸ‹-âŸþ¡²²R4X…F{ùå—Q©ThµZ¶oßn(÷VVVTUUñ /0aŠ‹‹yì±Ç8yò$cÇŽåË/¿ÄÛÛ›~ø777:Ä´iÓØ¹s'ƒ @¥RñÓO?áííͧŸ~Š$I\¼x‘^x1cÆ0}útÃß„¦ôñÇ£ÑhP«Õ¬_¿ž„„&OžLpp0S¦L!22’W_}ÕЀŒŽŽæï¿ÿ¦mÛ¶†}˜››óá‡Ò£G~ýõW|ðAvîÜɰaÃ8}ú4O=õ±±±€¾Ã|áÂ…°lÙ2ž{î9öîÝKÿþý9~ü8Ï?ÿ< ¢Á*4)///V¬X$ITVV2cÆ lmm`Ê”)<ôÐCÈårÚ¶mË!CËåXZZâååez¾{÷n‰‹‹c÷îÝ”••áëëË‘#G û0`öööXYYagg‡ŸŸ:uB.—Ó±cGt:!©Ù Aƒ°µµÅÆÆÚ·oO»ví0777¼Vš‚µµ5ŽŽŽ$$$ðñÇó /pÏ=÷ÎÍ:u2Œ°±±ÁÝݵZ Àž={ âܹsìÙ³•J…³³3†ýßu×]`kk @LL ?þ8yyyL™2Åð¼ 45[[[9xð _}õK–,1L;º’!C†Ð£Gœ ϰ5‰ÇŒ¹¹9ÞÞÞØÛÛÎÇÝ»wÇÇÇÇðZ333 „¹¹9~~~X[[‹s·ÐäÌÌÌppp@¡P°lÙ2rrrøú믱··¿ê{î¹ç:vìˆ ffføúú²víZ6lØ@uu5Ÿþ9£G6¼¾oß¾899annŽ““NNNôêÕËP'‘ÉdFIYoeâ« i4V¬XADD;vdîܹ†m=ô}úô!$$„çž{ŽÛo¿˜˜RRRhß¾=2™ŒÉ“'óÓO?1uêTîºë.¢¢¢Ø¸q#ß}÷ÑÜTA0µÔÔTfÍšExx8O?ý´Ñ6++«+ÞÑÌËË£¼¼œ}ûöcx¾²²’>}úFÔ§b.*ñÂÍ"I ¼ù曌3Æhêè´WºšMUUÛ¶m3j jµZ<== óš |¤¤$fÍšÅêÕ«ùî»ïøðÃEFwá†$‰sçÎñþûïóä“O2|øðk¾ÞÇǧ֔"+++C§åõX[[‹NxÁ$t:k×®eíÚµ,_¾œ€€€k¾þòó²µµ5«W¯fõêÕ,Z´¥R‰¯¯/ü±!—¨“Ô¸š™L&cذa899ÕÚVÓã¾páB¾øâ þþûoFŽÉرc)++C¡P`ooÏO?ýÄÊ•+Yµj~~~|ûí· <˜ôôt^|ñEþår9‹-¢S§NXZZ2eÊÃ0ƒGyÄ0Dô=¢—ÇåááÁ«¯¾Š¯¯¯©?6¡z÷Ýw©ªªbîܹW,ïWâî§'=öO<ñ„áùˆˆœë\ÙSP*•Ì™3^ýuCþ€ëñòòÂÝÝ7ß|“{ï½×ðü±cÇðöö6TÜÿ[1bÏ=÷NNN|öÙgÜwß}ôéÓÇԃРeggóÚk¯1lØ0¦NzÝÆ¤È!´TÇçóÏ?çÕW_¥oß¾×-Ë—ÿJJJ(,,äwÞA£ÑpîÜ9>øà–,YÂÒ¥KM}h-Žh°š\.gøðáW팊Šâã?fÁ‚899QUUÅC=Äðáà C‡{öìÉG}„J¥2Ìkhß¾=íÛ·7ìËÜÜœ3f+ Ægx|ùÿBCC 5üðC.\h˜ûô_5#|ðAöîÝËûï¿ÏÊ•+k%Þ„ƨ®®æÕW_¥¢¢‚É“'“““cHöرcG@WJ£ÑˆåÊ„-!!gžy†aÆѿ°··7 c×jµ¨Õê+Û-((àÑGå‹/¾`øðátèЗZY‡…º ÖfÌÝÝòòrüqÂÃÃ9{ö,¥¥¥L˜0Áèî’……¦Wj)--eË–-äääðÖ[omÛ¼yóußÿÈ#°ÿ~&OžŒ··7ñññŒ1‚¡C‡ŠaïB³UTTÄŽ;ÈÌÌdæÌ™FÛöïßÝ÷?ýôÓ<ýôÓÜÿý¸»»Ëý÷ßOÿþý ß«±µµeÆŒÜ{ï½lß¾‡~ØÔ‡ÐŠdgg³oß>$IâñÇ7<ïààÀáÇiÓ¦ EEE¼óÎ;Ìž=ÛÔá Bƒ]¸póçÏ£T*Ù»w¯áù;ùóçÓ¦MþüóOæÍ›ÇC=TëýmÚ´aĈÌš5‹€€JKKQ©T,[¶ÌÔ‡Ö"ɤ›<›777—µk׉V«eèСLœ8ÑÐ[‘œœÌo¿ýÆÙ³gñ÷÷gÒ¤IÞ’Ãÿ$IB¥R±yóf’’’hÛ¶-ÇÇÝÝ] ±iƪ««9tè›6m"##ƒnݺqÏ=÷лwo´Z-ÑÑѬZµŠììlBBB¸÷Þ{²'¶&’$¡Õj¯ØûhnnŽ$Ièt:är¹!¹@Í=¹\nx|èÐ!ÒÒÒ %00333þÍÌÌ ÃpjzôkÎ:ΰÿú¼Vü¾®­´´”¿ÿþ›}ûöQRRBHH“&M¢mÛ¶¨T*Ž9ºuëÐjµ„‡‡sï½÷M9h횪ÜïÙ³‡ÜÜ\úôéC@@@Ë}Íkd2Ù-yíl 999¬[·ÎPW>|8ãÇ7ÔU’’’øí·ß8wîíÛ·çá‡6œ›Z³k•m…BF£áøñãäææ2|øpC‚333Ãyµ¦¼Ö<§ÓéÐjµ˜››~5e¼æïü÷µ5£Ì®ô{ê&**ŠM›6qúôi¸çž{9r$666hµZ¢¢¢Xµj999„††rï½÷ÞR™˜kÊÚ™™™!—Ë)//gÏž=8880`ÀC¬)‡5çñ‹/ræÌ|||èÝ»·a­÷ÿž·k~W5¹jʶ¨“èÝÔkEE ,àôéÓ<òÈ#hµZV¯^ÍÀ™9s&<óÌ3(•J|ðAŽ9Bbb"Ÿ}ö™aý.AhîöìÙÃ[o½Åĉ æ?þ 33Ó°¾çóÏ?OPP à×_ÅÞÞž/¿üR\l…¡&YÜêÕ«™4innn¬[·wwwÞyçâââ˜7ocÇŽÅËË‹5kÖ0nÜ8žyæQÆ…¡¼¼œùóçsîÜ9&OžŒF£aõêÕ 2„W^y…BÁSO=…N§ãþûïçСC¤¤¤°páÂZɰ¡9*((`êÔ©ØØØððÓ˜˜Èúõëyþùçyøá‡ ë£Ó¿Ö­[‡‹‹ K–,çqÁ$nêàÄÄDŽ=ʧŸ~j˜Ù±cG¦M›Æ“O>I\\|öÙg1tèP&OžÌŽ;Œ’®Bs¶qãF† ÆŒ3077'<<œçž{Ž-[¶`ii‰••³fÍÂÉÉ ^|ñE"##éÝ»·©C„ë*//çï¿ÿæé§ŸfòäÉ€~9Š;3³gϲqãFzöìÉË/¿ 臨.[¶ŒÛn»:˜:|A¸®„„Nœ8Á§Ÿ~JHH Ÿ{üÒK/ñÔSOqñâE²³³Y´h]»veðàÁ<òÈ#ìܹ“G}ÔÔá Âu>|NÇ|€¿¿¿aÄÇ/¿üÂÃ?ÌæÍ›±±±aÖ¬Y888ЦM^~ùeNŸ>MXX˜©ÃnA7½›$((ˆ=z;;;£T*ÑétÄÆÆâééiieeEhh(çÎ3õç$uæääÄèÑ£ Ãû Þ~ûmúôésÍ8®UÆår9<öØc7õ8£²²’£G2xðàÑÀ}ÅáèÑ£ôîÝûš•ÒæD­V³qãÆ›~×]£Ñ°aÃ~þùgzôèÁG}DppðU+3æææ×¼lnnÎ!C¸÷Þ{oêq4FAAçÏŸgذa¦¥ÎŠ‹‹9uê#GŽ4u(u6räÈ:-ÕÔªªªøòË/Ù·o#FŒà¾ûî»n¥öZçqGGGFŒÁ¤I“nú±4TZZYYYôíÛ×Ô¡ÔYVVÉÉÉFÓš»””N:uÓÿnzz:_ý5.\`üøñÜ{ï½×½‰bmm}ÕmLš4‰~ýúÝôciÌg››kÈ«ÓDGG#“ÉèÚµ«©C©³Ó§OSRRÒ¨}ÜÔkYY‹-"%%…>úˆnݺÝõ÷÷'))‰ÒÒRP©T$$$Ôi¡õ–¦oß¾-nør¯^½ZÄSÛ»w/‹-â±Çc̘1FËytèм¼ª5z«]»v¤¥¥ê*J¥’ÄÄÄVWWñõõmQêžžž¸»»›:Œf/77—7ß|///~øáÜÝÝ:>;vìH^^jµ…BA~~>­.9¤··7^^^¦£^ºtébêL⦶˜bccÙ½{7³gϦgÏžµ†ï†„„““CJJ  ¿ãqêÔ)“ ç¼ÑÌÍÍ[\ƒÕÜÜ\ÌŸ¬ƒ5kÖ0pà@&NœXkíɾ}ûröìY***}ï^jjj«+ã2™ …BÑ¢:8Zb̦PVVÆúõëùßÿþÇðáÃzÜÍÌÌèÝ»7GŽ1³ÐÐP²²² ‰Äª««‰ŒŒluçq33³××c6…={öPUUÅÌ™3ñòòªU·ëÓ§§OŸ¦²²ÐßmOOOoQwOëB.—·¸ò"—ËoɺøMý–¢££ÉÉɹⰯmÛ¶LHHóæÍãî»ïæèÑ£x{{3tèPSN‚P'ùùùÄÄÄpìØ1Ö­[g´íÑGåÿûÛ¶mãÝwß%,,Œ¿ÿþ›ܲ=fBË“ššJjj*³gÏæ­·Þ2Ú¶páB|ðAÞyçæÍ›‡‹‹ ÿüó?üp‹»S#ܺ¢¢¢ÈÎÎfâĉµ¶íܹ“ž={Ò³gO>øàî¸ãŽ=Н¯¯¸{-´ÕÕÕœ9s†óçÏ3zôh£mžžžìܹ“Ñ£G³cÇÞ}÷]BBBØ´iƒ j1sƒ…Öç¦6X `”]òrÎÎΘ™™1sæL6oÞÌÉ“'éÖ­wÞyg‹IP 666|ðÁWL¾áïï››ï¾û.¿ÿþ;§NâÞ{ïeĈ⮞Ðbøùù]õ<Œ»»;sçÎåÏ?ÿ$55•^xaƉ2.´ƒ¾jN GGGÌÌÌxíµ×ؼy3tïÞ;î¸£Õ {Z'sss~øaFŒQk[M®www£ºÊƒ>ÈðáÃÅy\0™›Ú`íØ±#;v¼ækÜÜÜxüñÇMú¡BCÙØØ0|øðk¾¦]»v¼úꫦUÄÍÍ1cÆ\ó5!!!„„„˜:TAhºÔUÜÝÝyâ‰'Lª Ô›¹¹ùuófÈd2Ú·oÏk¯½fêp¸ÉsXAAA¡®DƒUAAAh–DƒUAAAh–DƒUAAAh–DƒUAAAh–DƒUAAAh–DƒUAAAh–DƒUAAAh–DƒUAAAh–DƒUAAAh–DƒUAAAh–Dƒõ&Óh4hµZS‡!‚ ‚ ‚Ðì™7ÕŽ²³³Q(¸ººšú˜š­ÊÊJ¾úê+*++™þøcJJJÈÍÍåå—_füøñ¦>,“ÒétDEE±råJ¦L™B=ÄùTA„[Nƒ¬†_ý•eË–1zôh())ÁÁÁèèhNž<É_|‡‡‡©Ñäbbbxÿý÷1b=öæææÜyç\ºt Ú¶m‹““S­÷-]º”sçΉkèt:ÓmÛ¶ñþûïóúë¯óæ›o2sæL,XÀž={Œ^+‚Ðèt:’’’8qâ'NœàìÙ³(•JS‡%B Ñà«R©¤¸¸˜ ÷“Éd8::Ò¹sg£y™·¢ÊÊJ>ÿüs†Nÿþý‘Ëåõz›6mnj¥]’$öïßÏ /¼ÀÂ… Y¿~=o¼ñÑÑÑF¯Û¼ysƒ¿Ûøøxžþyüq~ýõW ›$ö 6pÏ=÷°bÅ £‹`ZZš¨àß@UUUüøãLš4éŠÃ~û÷ïOTTÔ5÷qá wÆíííéÖ­Ç¿!1—••ñûï¿søðákV˜ÒÒÒx饗øî»ïü·T*999WÜVQQÁ’%K˜2e 'Ož4<öìY–,Y /¼@hh(æææ 8§žzŠO?ý”ÇßÏEáFY·no¾ù&Gåï¿ÿæ7Þ¸îµA¡Fƒ‡›››cmmÍ©S§¸óÎ;¶•——m¸ëÚši4òòò$ oood2Z­–´´4~øá¼½½™6mZƒöíçç@BB‚áÎUC”——sñâEìííiӦ͓8ååå±råJΜ9Ãܹséܹ3‘‘‘|üñÇÌ™3333>ùä´Z-¿üò >>>Œ9’±cÇî_V«e÷îÝ,Y²„Ù³gãëëËüÁ£>Êܹs »îüýôSžþy–-[Æž={xóÍ7›ô;o-rssÉÎΦ[·nWýþ´Z-999¤¤¤`ggG·nÝ /•••Ì›7û￟~ýú]ñý,^¼˜êêê«&`Ú¶m<ò2™ÌðÜí·ßÎ?þȨQ£®ú¾Ó§Oóþûïóâ‹/2bĈ:³N§ãÇ$&&+++-Z„‡‡TUUáææÆØ±c‘Éd|ñÅLš4‰5kÖ˜˜H‡®ºßS§Nñ×_Ñ·o_ÆŽ‹B¡0|>‡fúôéLœ8™L†Z­æðáÃ|þùç 8?üyóæñÈ#`ccÃW_}ÅâÅ‹éÚµ«Ñß4hß|ó¡éî»ïF£ÑP^^Ž$I7©Ô‚ \]UU111ÄÆÆ¢ÑhP©Tìß¿////^Œ——'Nœ`ÕªUtïÞ]LãZ•””~ûí7Μ9CÛ¶m;v,>>>œ?žcÇŽñè£Ò­[7S‡Ùâ4¸ÁêêêÊÈ‘#Yºt)””” V«‰ŠŠâçŸF­V_µÛèt:ª««Q(†;G5É*++9vìÇ'..Î0dÖÓÓ“’’’ˆ¥wïÞ<úè£ ŽÁÜÜœàà`¢¢¢êÝ`ÕétTUUqþüy¾ÿþ{,,,$‰²²2ºté„ èÔ©Z­–dzjÕ*:vìh¨À× å®»î2 ó5jÿûßÿP©Tœ={–Ÿ~ú‰ÄÄDžxâ ìììŒb$‰ŠŠ âããÙ´iIIIÌ™3‡~ýúaffÆ«¯¾Êرc™3g³gϦOŸ>F–ËiµZŽ?ÎÂ… =z4{÷î%11‘ÀÀ@"## àÞ{ï套^â•W^ÁËË‹§Ÿ~ºV\‚þóüñÇ9pàaaaL:GGG’’’¸pá‚a¨jFF´oßžäädyä‘GˆgÆ hµZæÌ™sÕ¿ãééI‡8vìÆ «µ=66–ÊÊÊZ[íÚµC’$Š‹‹ñòòB«ÕR]]m(ûöíãÇdРAüüóÏ„„„àìì|ÝãÎËËãÈ‘#,\¸___ÊÊÊP©T€¾cçôéÓ¬_¿žøøxÞ~ûmÂÃÃ9{ö,.\¸bƒ5''‡åË—sêÔ)†ÊÊ•+‘ËåŒ3†ßÿââbæÌ™Ã—_~‰»»;=zô`ñâÅdff2kÖ,°°°à­·ÞbÑ¢E”——3kÖ¬ZÕíÛ·gÁ‚,Y²„?ÿüN‡­­mì‚  %I’ai>­VKnn.ÇŽãâÅ‹†×$&&bmmMhh(þþþ<ñÄôíÛרó1$$„ßÿ“'O2`À€«^û¡¹Óét(•JòóóÙ½{7ÿüóC‡åõ×_çâÅ‹üõ×_deeˆZ­fïÞ½¢ÁÚ n°ZYYñôÓO£P(øù矉àäÉ“tíÚ•>øàšw$š»ÈÈH–,Y‚··7½{÷ÆÊÊŠäädÒÒÒÈÎΦcÇŽ 8gŸ}4 ‘‘‘DGG3`ÀfÍšÕ$ËÑôêÕ‹]»vq÷Ýw_õ5999lÞ¼ÜÜÜÐjµœ>}šøøxär9O>ù$ýû÷ÇÜÜœ‚‚8À·ß~‹J¥¢´´Þxã zôèqÅýßwß}¸¹¹áèèHïÞ½°´´dРAôìÙ“ 0{ölfÏžá}ÑÑÑÌ;OOOÆŒÃK/½Tk¾nPP¯¿þ:ü1“'OF¡P Õj ¢S§N€þ"¹qãF~ùåæÍ›GPPíÚµãË/¿ä³Ï>cÇŽ<ûì³€¾4cÆ ¢££™2e GŽ1i9j®JJJˆŽŽæ«¯¾âàÁƒÌš5 333œéÕ«îî¸0|øp‚ƒƒ±²²¢²²’¿þú‹ àïïÏË/¿LPPÐ5ï®Ëår&NœÈ† aêÔ© 6 KKË+¾_&“Ñ·o_fÏžÍßÿ……¬_¿žY³fѳgOâããùå—_xóÍ7 `ذalß¾~ø333ºwïnØçøZI’غu+ݺuÃßߟvíÚ1vìX$IÂÕÕõªKÐØØØ0iÒ$&L˜€B¡¸nã°FXX‹-"++‹ÌÌL¾ýö[òòò°¶¶¦¼¼œ§žzªÖ{,--2dûöí£  €íÛ·3cÆ ÃÝ[[[ÚÏãÇç•W^!** {{{–/_޳fÍ2újµZ¶mÛÆÄ‰ë;è;U¾ÿþ{£ß V«å÷ßÇÌÌŒiÓ¦îtêÔ‰wß}—/¾ø‚W^y___Ãóßÿ=UUUtéÒåŠóÙ]\\pqq¹éåA¡†F£áÏ?ÿ䯿þB£ÑîªÒ½{wú÷ï­­-VVVxyy]³îp=]ºt¡¼¼œ˜˜BBB ϧ¦¦òꫯòÌ3Ï0jÔ(S$Â-N§ÓQ^^ΡC‡øý÷ßpww§¤¤„ªª*ÂÃÙ6mþþþ8::^s´@@@†””£ŽFCff&ÿüóAAA 4H,c÷ n°VWW³gÏÚ¶mË<@›6mêõ~¥RÉ™3g6jPÅÄÄÔJÄÓ©S§›Ú¾xñ")))¼õÖ[X[[3hР›ö·ÿËÎÎ…BA^^žQƒµ¢¢‚… ’™™Éœ9sê=¼ÀÆÆ¦É†$ØÙÙñÄO°xñb/^ÌìÙ³Y¾|9]»vå¶Ûn»îûÍÌÌèÝ»·áî-@Û¶m™7o³gÏfÉ’%Ìœ9Óh»••=ôO<ñï¾ûn³í…ŠŠÂÉÉÉÐpQ©T\¼x‘ŠŠ Ãkd2½zõªÕÃ|£°iÓ&>þøcCÃÉÓÓ³Îï¯oœVVVðÅ_ššÊSO=ŨQ£ Ãh®6G5<<œùóç“––Æûï¿OÛ¶m¯øº¶mÛòÄOðÚk¯áççGß¾}9pà{÷î5ªì\¼x‘ªª*X¯ágžžžôêÕ‹­[·òÐCúäaëׯgñâŵÊ^—.]øúë¯kíçzwN[ªˆˆ:vìh’ýìwXSçÛÇ¿™ì-KP@÷À½êÞ¶îUW[µÚZµ®ÚíjÕÚV­ÖÝ¥V«¶uÔ bÝ ˆÈÞ{²Ç9ïÏ›@dHX|>×Å¥9INî“<çœ{ßEEEˆŽŽÖ¥Z%×êQ¦46är9BCCѱcG½kUdd$ ô^[ߺJ]põêU?~ß}÷\]]‘••SSÓ §Ô;;;̘1ßÿ=¶mÛ¦Ë;pàLMMqóæM 4Èà†•ÃÈÎÎFzz::uê¤Û¦P(ðüùs=]…Ëå¢cÇŽõ¦«Ôááá¸{÷®NOñòòBLL BCCu8<þ666˜7oÜÜÜ‘‘‡ƒÎ;ä´ðööF\\œÎ`-((ÀÑ£GqãÆ øøøàÆð÷÷¯R™SmÀ0 ž?ooï}®¶Áêè舙3gâôéÓ°··/·ÆÒÍͭ܃g?Æž={°cǽſ}ûv$''ë½oåÊ•õæeS©T8sæ ÆŒÓ NJ@gggdeeéͲø7nÄÒ¥K¡Ñhðõ×_W{£F‚¹¹9Ö¬Yƒ9sæ”;‹¶cÇŽøüóϬ6//ß}÷&Ož¬3Xóòò°iÓ&( ÷ŒËåbÏž=ºzŸºæöíÛprr‚§§g½}ƒÆ©S§ðÕW_é¾ .—[é9æèèˆíÛ·Ã××÷¥JàСCáëë [[[ØÙÙaРAøä“Oàãブ-[B,ãçŸÆØ±c+4+cܸqصkŒüü|üøã˜3gN½ýf –e‘œœŒ]»vaíÚµº›kxx8>ûì3=%ÓÓÓŸ}öš5kfl±ŽL&ÃÍ›7ѯ_?½Tø»wïâÌ™3h×®zöì OOO]f Ã0 Á;w°téR=©°°fFPªÃ0xôè~üñGìØ±CïÚ±uëV¤§§ë}ï«V­j´õä à 22ÇŽÃêÕ«uM$µM’êŠAƒáÑ£GØ´i¾üòK$%%!11+W®ÄÞ½{QXX¨Ë¦©O ‘ OOÏ+ñ2™ ÙÙÙpuu-w_ …jµºÞ ¿û™3g§g°æää`Ó¦MP*•:/ŸÏÇ÷ß_¡ó¸±P\\ŒàÏ?ÿ„X,F= ‹qúôiÄÇÇÃÙÙ;vĨQ£›› •J…#FÀÇÇG§³Ô¤jûöíñäÉ 6 .\@FFöìÙ;;;|õÕWøý÷ßñÖ[oUeU«Õغu+h°þErss±víZ,X°ãÇ×m×h4J¥zM•J%Ôjµ®¬ª2$ 222ôl—šPmƒU,#<< X¾|¹^£-(ó£FEEáúõë8wîÌÍÍËt·LMMÅìÙ³u©Ÿ@ýF& †yóæÕÛgVǃ"##ѧOdìÅùóç±eË–a¬j133Ç~ˆï¿ÿÓ§O/wMT>Ÿ¡C‡ÂÍÍ ^^^åž´¦¦¦˜4i’±» EEE¸yó&.^¼ˆÿþû&LÐ='“ÉPTT„7ê~;‡S£ïÊP®\¹¢wQª†Š¡C‡ì)ïß¿•^' õjæÛ´iƒ=zàçŸƤI“°wï^(•J 4¨Zò{zz¢  K–,µµ5^{í5Œ=ú•MÙIKKÃ7ðÏ?ÿ ##CotTnn.,--±nÝ:Ý6333½záW¥R‰;vàÀ8vì˜^öÎãÇaff†¼¼.]º¤S’볤F(âÝwßÅ·ß~‹?ü………xÿý÷áãã@€¼¼<£¬ÇŽéS§0kÖ,,X° Fëþ¯¿þ±cÇЦM 6 ƒÖ®ÅÅÅØ·oŸQŽñÖ­[¸ÿ>~ýõW~©E««|ôÑGºkw}ë*uALL vîÜ Fƒ™3g¢[·nµÒoÆ|}}qóæM0 †a„… êê^-Z„•+Wbøðáözüø1þüóOäåå¡gÏž5rXÆÄÄ€eYœ:u LJ©©)X–Å­[·°oß>Èårp¹\]&^nn. „7Þx£Ò2¦'N`×®]8vìX­|oÕ6X---1kÖ,=eüE\]]ËlËÏÏGQQ “ÉôžÓz+»t颻ùÖw*ˆv4EéæAÆ„Ãá mÛ¶8yò$>|‘H„½{÷bÍš5õ!«*ŽŽŽØ¸qc­yû+ê–ÚQ(HOO‡¥¥e™brr2еkWXXX€Ïç׫øàÁH¥Òr#ÖuI}ŸÇ\.óçÏǺuë°}ûvL:ýúõ«vÖ„™™6lØxzzÂÌÌì•5Vâ°ÌÍÍ…½½=²³³uÛ†ARR¼¼¼Ð­[7(•ÊbT—ˆD"dggC,ƒa¨T*üù矰±±ÁêÕ«£3XU*âââ0mÚ4tîÜyyyؽ{7¶lÙ‚©S§âÓO?Õ~úå—_t ò~øá<~üAAAå¬Ïž=C^^¬¬¬àääWWW½î‚‚äææê^ïëë«{.??[¶lAË–-ñÛo¿ÁÅÅÇÇСC_Zž˜˜½¨dZZŠŠŠàááQnL&—Ë­°çA}’ŸŸââb888襷kC««´mÛ§Q¦­J$;v ÿþû/±mÛ¶*5Lªm,--±jÕ*!ѳgOîóäÉݘ½ÿý7oÞć~kkk°,‹gÏžáÓO?E÷îÝ1qâD´jÕÊ k3Ã0ÈÉÉîZ•‘‘›7obÇŽ8vì¾øâ ,Y²¤ZF¥¶+ì†  T*ñÏ?ÿàèÑ£2d:t耟~ú vvvF‰ZfffB©T–kt$''ÃÑÑ]»v…¹¹y½ë*µ Ã08~ü8NŸ>  oß¾F+%kÞ¼9rss!“É–eõ‚t®®®>|8:„>ú¨Ì=´¨¨û÷ïÇÇŒ“'O"##ã¥ë§¨¨–––åžW®\Á¼yóŒÛ·ocРA(**Â?ü€eË–é® |>\.2™ ?ýô-Z¤3–  »7%&&âìٳؼy3>úè#L:U—]W]ªm° …B½F7b±/­e D`` >Œ¿ÿþ[﹌Œ °,‹¿ÿþ‡†¥¥%ÆN:Õ‹r˜7nà‹/¾hPʨ„B!‚‚‚ V«1sæLtéÒ¥A^<8Î+« jqttÄ[o½…˜˜„‡‡ë=—––‡={ö 77îîl]SPP€ï¿ÿË—/¯w¢1°±±Á¦M›  kÜ̈Ëåê¢ZR§Û¶m[aëÖ­ºí,Ë"==2™ Ÿ~ú)D"|||0mÚ´:©kˆ( |öÙgˆ‰‰­­­®Ã6˲À¢E‹Žßÿ]÷™L‘H{{{p¹\8::bíڵزe ,X€#F`ĈP«Õ8}ú4ÂÂÂ`ccƒ   ¬[·7nÜ(W–¬¬,|þùçðôô„B¡@AAæÎ«k¢WPP ›±mnnް°0|üñǺ‘twïÞ…­­-6nÜ–e‚£G"** óçÏ×ët]š´´4Ìœ9~ø¡®»¶6íŒaðx< <ãÇ×¥’gddà‹/¾€››[ƒ˜Ý§OôéÓÀ¥K—ôžËÈÈœ;wN—Q0aÂtìØ±Aé•Á0 þ÷¿ÿ!""_ý5<<<Œjt …B¼ÿþûàp8ºï0 ÿüó¦L™‚ÂÂB>|\.‡ÆòåË!•JñÍ7ß`øðáÉdX³f -Z„áÇWéwP(øá‡ðÏ?ÿàwÞÑuˆøð!Zµj|ñÅغu+vî܉/¿üÒàãzöì”J%ºté¡Pˆ¾}ûâñãǸt邃ƒ1vìXtîÜOž<©÷ïüõ×_@2_$-- \.ß}÷òòòТE Lœ8±Ñf\»v 'OžÄgŸ}¦g»ƒfÍšÁÃÃaaa8{ö,ÆWÆ™>räH¬\¹‹/Fûöí1xð`têÔ <<ÇÃСC‘‘‘ãÇcõêÕe>§  W®\Áÿý‡´´4¬[·N/í Y¥OŸ>Å;ï¼.—‹³gÏbàÀ8þ<<<<н{÷2:½­­-Ö¯_¸¸8„……A,£¨¨Ÿþ9Þ}÷]tîÜ_ý5Þ|óMŒ5 999øù矱jÕª}oÕ6Xµ_Æü3gÎ !!,ËÂÒÒýúõòeËàååeQ•žžŽüü|ˆD"ôéÓOž<ÁŠ+ðÑGaذa¾/77gΜÁÌ™3«"«Ñh°oß>téÒ¥ÁE.›5k¦§r8œi¬6$T*‚ƒƒ„‘#G[)))HKKC=ЧO\ºt .Ä¡C‡*­‡LJJ‰'ðÚk¯U»ÿìÙ³pqq)3ó´)S×õWÆD"‘àüùó ­÷ˆyE°,‹ÔÔT讥ýõþøc<|øP7»¦OŸŽ€a¼ñÆèÓ§Ž=Šüüü2Ž™ . [·nX¹r%8bbbðùçŸÃÁÁAgöíÛ³fÍ@®OK–,ÁÎ;accƒŸþY×|Ãáàµ×^Ã!C°eË,^¼óçÏGß¾}õ”-¥R‰Ý»wcÒ¤Iøí·ßàåå|òÉ'4hæÎ‹¸¸8\¹ro½õZµjggg\¿~o¿ý6BBBðí·ßâí·ß†P(į¿þªÅo¤¥¥é²ÅúôéƒGaùòåøä“O*ì¨Ï²,îܹOOOôîÝ»^åÍÉÉÁýû÷qíÚ5´mÛ¸qãñÕW_5˜Úò#ëÝ»wÇ?þˆ¼¼<„„„ÀÞÞëÖ­ÃÚµkqúôi<~ü~~~˜={6úô都{÷bðàÁº}±,‹¤¤$Ü¿wîÜA^^X–…««+ÒÓÓÑ¡C|óÍ7Ø´iÜÝÝѱcGœ;wN7¶Q(bÓ¦Mغu+>ýôS¬\¹æææˆÇ³gÏ —Ë‘––†þýûë5†HáÉ“'1yòdÒÏårѵkWtéÒ Ã@$aÿþýFI ®Œ””¤¦¦¢gÏžðõõÅ… pþüy>¡¡¡øæ›oœ1H TÃ}ðÁàÏ?ÿÄŠ+*ü=<<ôfyJ~~>.\¸€O>ù¤Q¦®QÊbaa &4¨tD.—‹eË–ÁÞÞ>>>`Y={öÄÒ¥KqïÞ=Œ9²Â5Þ½{wŒ3ÆØ‡P),Ë"::_ý5x<lmm¡P(PTT„¼¼<ØÙÙáý÷ßÇ€*Ý©©)x<žn¦·T*…B¡(“&+ Ë8#zôè#GŽFŒôìÙW¯^Åo¼¡{]jj*®_¿Ž-[¶è¾¾¾X´h>ûì38::Â××Ó¦MÓ­OOO¼ñÆسg:vìˆV­Zé¥k×ÚªU«ðèÑ#ìÙ³—.]ÂÒ¥Káéé ‡ƒ„„¤¥¥aãÆèÒ¥ ¾øâ ´k×VVV˜2eŠž¢3qâD}:<ˆ©S§‚Çã! @÷; …B,_¾›6m¶mÛÀ0 u]e[´híÛ·ã믿Ö3æòòò™™YnvŽö\²··Ç´iÓððáCcÝzŒ?£GÖé*½{÷ÆÊ•+qæÌ¼ûî»å®q¡Pˆ‘#GÍXer¹ ÀeYüûï¿8wîœññÇ7(v×®]1oÞóæÍÃÍ›7 R²[´h¡—Rlff†ÀÀ@ìß¿J¥²ÎêZŠŠŠ°sçN¼÷Þ{5α¦P*£t@j:wîŒäädh4š:‰,)•J|÷Ýw=zt£¬ ¦4´ÞT-¾¾¾puuEff¦±Å3˜§OŸ";; ǃR©ÄÎ;1hР̘1Cïµùùù033«r´››òóóѺuk<þUJÕ···Ç† `cc£S(ÆŽ‹mÛ¶aüøñ …P©T8xð † V¦LgÀ€ ÃÂ… Ë8ô¦OŸŽèèhüôÓO6Ë055Eï޽ѽ{wœ?ï¾û.6mÚ„=zàâÅ‹:t(¬¬¬0`À¤¦¦"88Û¶m+S3æêꊱcÇbìØ±ºm-[¶ÄæÍ›ñþûïãøñãèß¿ƒ‹>µlÙRÏ0177ו:Õ¥®b(.\ÀéÓ§±eË–F›ÊÙ³gO|òÉ'èØ±# ‡OOO9rDïˆÁôâ9¤ÑhÀ²,fÏž]agW.—‹É“'#..K—.ÅîÝ»Ëü†¶¶¶øòË/qðàA´jÕ }ô‘Þ¹^PP€àÓO?Õm ‡££c£œ¯ýbÚlóæÍÑ©S§:ÕUj‚L&Ãü›7oB*•¢¸¸:uªU«Ð¡C‡ôqvvÆòåËõ®}•annŽbàÀež5j6oÞŒ;wî@&“ÁÛÛ;vìÐËÆxçwðþûïc×®]9r$Ôj5 …Þy1cÆ ddd`òäɇLJ>ûì³:ùÎja•H$åv“³¶¶†ŸŸ_¹yñ•íïܹsàóù;v,¸\.X–Õ)u%û÷ßuÞO ¥®Éd8rä:uê¤k*¡V«‘““[[Û:‹’EGG#::K—.5öW@iââ‡~À´iÓt¥ …"‘¨Ñu ÎÈÈÀæÍ›!•Jùóçãüùó077×Õe–ÆP¥ÔÁÁAW ™`Ј¤•ÉÖ­[ƒa¤¥¥ÁÓÓñññˆŠŠÂÂ… ˼—Ãáèê3ËÃÔÔ|ðFŒñÒò@€1cÆ@ `ÇŽX¸p!BBB°mÛ6]fÐë¯¿Ž &TXïZžžžØ³gLLLÀápð×_öãÕ!*• gÏž…P(Ę1cÀårÁ0 òòòê\W©*ÚŸüñ>ùä“Wæd~~~(..Æœ9stß­6šSYYYz]Ëy­ŠaΜ9°´´D÷îÝË}ÞÊÊ +V¬(÷¹‰'bÕªU¸~ý:úõë¹\Ž«W¯bÈ!®¯‡L&ÃáÇѵkWtïÞ]OW±³³k0=Z$ 8€çÏŸcÓ¦MºkMƒ®)_¹reµÆì½H›6mðÙgŸÃáÀÆÆ¦Òßèƒ>ÀéÓ§ñóÏ?#&&Æ ÓsúXYYaýúõ rÍVÛ`åóù033Chh(ÜÝÝõž“H$ˆ‰‰AçΫ¼?@™L†cÇŽÁ¾¾¾HHHÀüÉ“'×Ù¢‰D8~ü8>þøãwRšfffHLLDPPÖ¬YƒfÍš!88<ÀöíÛëÌxäÈŒ5ªÁE)(M „„„ ??‹/—ËÅ_ý¥ë¨ÚмÜ¡V«ñ¿ÿýݺuÃŒ3ðÙgŸaÍš5ˆÇ¯¿þZ+Ý%}}}ñüùsŒ7qqq•vÜ<žžž Ebb"<ˆÑ£GW»^«Y³f/Mk.ýÙ£FŸÏÇêÕ«±xñb½h^u;sk;õçççWû{© ¤R)~úé'XXX mÛ¶ˆÇéÓ§1uêÔ¡ GEEaûöíX¿~}½4ô«KZ¶l‰#GŽèu¯®…B½”`Fƒœœœ*}–‹‹ –,YR-9±bÅ ¬[·ÿþû¯®óvEŽ¡†Œ™™âããqëÖ-¬Y³¸yó&žƒMMMñÖ[oeYœ;wßÿ=rÁèÖ­>ûì³2‘×ÒŒ7®ÌÅÝ«V­BZZ222àääT§©,ááá ‘#G\>>¥ñÓ²eKÝy¡ÅÝÝ_~ù%ââ⠉ЪU«:ó* üþûï˜0aÂ+3R„R¿tíÚ]»vÕ=æp8èÒ¥ víÚ…èèhh4x{{”ZŸáäÉ“¸xñ"ú÷ï¼¼<ìÙ³J¥~ø¡.’jkk‹M›6Õêg;::"##ÉÉÉ011©Q‡ÃA= “É0`À£ÔÌñù|£‹¨ &NœXÆinaaÕ«W#-- ™™™pvv6ºCF£Ñàüùó8yò$–/_þÊ–8ik,µ°, kkëZ‹fU—ËE¿~ýŒý̇~Xf›¶–<66EEEuª«T—{÷î!$$[¶l¡Æê+@¬4 ,_¾3g΄\.‡D"µµ5¬­­«Ý±—Ëå–i¾Th›RÌŸ?¿FÝ…)CáóùhÛ¶mNll,ÒÒÒªœÚG¡Ô¦¦¦UŽŠ™L†[·náĉpttÄž={ààà‡™LFSçCåÝÜÜ V«Y+ÆŽ½½}e#QÊÂãñÊ4_2&çÎÃñãDZsçÎÕ µ>133+c¸¨Õj$''[´F ŸÏo°Ù‡aaaضm6oÞL›¥¾"ÔÈ`U©T8}ú4âãã±zõjp¹\œOCäÉ“'P*•:t(M•¤4I®_¿Ž#FÐÚU ¥"‘›7oFzz:–.]ŠîÝ»ë¥ÎÖ—§ÞÄÄîîî¸xñ"íÞM©ÏŸ?ÇñãDZnÝ:¸ºº¾²:‰‰ ,--¡P(ô¶ÛÚÚÖJsJÃá—_~Á˜1cжmÛWv½¿jT»;€R©Ä÷ßýû÷C(ꌣ£#°råJ$&&ûø*$88Æ £i”&‰B¡@HHØ š€P( …+W®ÀÜÜDÏž=Úl/ —/_¦+¥Ú$%%á£>Â’%Kôf‡¾ÊÄÆÆêþ/‘H`aaÑ`ÉP çæÍ›(..Æ´iÓ¨~ó Qí_:''W®\ÁÛo¿+V€ÇãËåbðàÁøüóÏÁãñpûömc_¹H¥R„††ÔŘBiLÄÇÇÃÜÜÜèuUJCBëÈ2dÑ•û-Z °°°ÁÕ†Q,Ëâ—_~A`` ¾žnnnzßCrr2ý^š"‘‡ƬY³hÀé£Ú«Z­†T*EŸ>}Ê4,jÖ¬|||ì ø¼¼¾ryôèüüüŒ¿àÕjàäI 2hÛxûm Ž 4”J%RSSë¼Óv£‡e§O33 ŠC·)›K—.aÀ€ fŒ™@ @Ïž=+DRpõ*PX,[…À™3Àó瀩)0mо=yÝþý@Vй3ðæ›@E”CC‰±úí·ä±»;°iàåEöÿý÷ÀÚµ€££q½#—Ëqûöm,\¸ÐØ¢4(œ!•Ju322hô¹ p÷î]:tݺu{eG6½êTû®Íçó1qâD888àÔ©S8räx<†Aß¾}1{öìãÅ~‘„„ 2Äx¨ÕÄûRSC‡€Ù³ÉëéùU%²²² ‰ÌX†‚@ €J¥Ò=æñx´F¼£V«±ÿ~cÁ‚ 4¶H#aÁš——‡””x{{ÃÒÒfff>|8†ެ¬,¨T*ØØØ4Ø!ñ™¿%K–Oˆ <˜?Ÿx›[´(QäÓÓÌL 1äç'%'NEÉ×èÓ(/r¡Ñc²±©Ø#_,K”/GG têSr2`o_½}6anß¾.]º4¬4¨C‡€ÁƒIÚaCŠfΘAðÒ¨Õ@QQâµÊsv6pø0ðÆdjƒš “‘Ï®,Ú§R‘k…¿Y9)/åâÅ‹ÈÏÏǸqãðøñc´iÓvvvÆËp$àî]rïhÓ†8;e2àÀàÙ3bø­YC2u""€cÇHæ@ÿþäý))d=—wož:•¼ÏĤrLMW×’Ç, (•À–-ÀîÝ@iõÛoë¿—Ç#2k4äsJÏvlÖŒÈúá‡À;ïûÛnܹs]»v}õ꟫@ZZšîÿ………pvv6¶H”j’““ƒË—/ã»ï¾k°e†”úÁ ƒU¥RáÆØ¿?Z·nîÝ»ÃÓÓNNNæ‚ðìÙ38::¯f¨ €(¬o|iQ©€ÿýس‡³5¡°( µé@(.&Ê“‹ QPzô FvNN‰w¾4ùùÀ¶m@l,àáA”›—)F¥ùþ{àþ}bì®YC¾³ÄD’nöð!°nQÖ‚š_MFƒàà`¼õÖ[ÆEŸÜ\òû|þ9°cQR — L˜Pv{~>Y§}D"páQªÿûÔ÷-]J M•Фô‡……üêUbÌVäfY²~mmI9@n.°x19—8àÜ9ÀÍD¤LM‰Apà0t(0~|‰­uâÐÚµ ÉÉÉÁàé鉿ÿþ|>3fÌ0¶X/G&#™Œœ'Íšqq$jtïN^gf,\Hœ@*U‰ÁØ¡ðé§$@ë ùýw².K_X–üTON6 HK~û©|>9¬­Ë:bøüò3¦¦À{ï‘{È ó3)å£R©põêU,[¶ŒŽõxooo<}úT÷X$ÁÄ£2 â4<˜d8Èdä<¤¿Añßÿ¡wïÞ´qV]¢R‘{Ž‹Kùz|Á ³ÌÅÅË—/dž Ю];ü÷ßعs'>ùä\½zyyyÆ>ž—oooãµ9·°V¯®85ÒÃ\ãâjþYAAÀéÓD)©)J%ðÇ$…ùìYâ)·´ ¦O'é^å}§ööÄ`=~œ¤™•>È_eôèA ‡o¿%uPpû6Qô?ÿhÕ 8x¤TD®³g‰Áÿ ’žžŽììì†×!xð`R÷fgܹS?ŸYXH¢Oׯ“¦/¥¹u ˆŽ.yüøqɲ·'Nžë×Kž¿>œDnÜ ÙJ%IíÿärÞ²,1 wî$Ÿ[*°y3Qò'M" ÐêÕĤ}þÐ!âÐÊÉ!׋… _~!†üû/I£¼pøñÇúù.!QQQhÑ¢>ÿüs¬X±þþþ w”YéæCW¯’”ÙÝ»Id FåÚµÄi¡Uܸ\âøpv&×FmAâà+mNšDÎôô’m!!ä³j‚@Ì›L™B>O,¶n-YÏU…Ï'Ñ[OOr\½JC”r‰‰‰Ã0hÿb*6|>_Oåóùµ™ þü“ü¿ €\ÿKu$6• ˆ‹ƒIDL =g^BBBЧO:š¨. #×íî04Ø-ÄårѼysŒ1+W®Ä_|)S¦àéÓ§X¿~=>ùäœ:u ‘‘‘‹ÅÆ>>=T*žMÖmÛ¶$röÑGdßÚôíI“HzÞ¼’L„€€’ˆYh(ÉÐàó©SÁ+(€Ó¥Kuû6RΟ?ÂÄÄ=zôÀÊ•+ë'³&'‡¬‡¥K+wΨÕä÷üàrÍÓÞ/‡ #Y6»v;ÖŽL­Z‘úÓü|âML$ŸQéÑB!àäDαýû‰±lk[ýýq¹äüZ½ZßÀ¦†Áå˗ѯ_¿Ó<¬!ÁçóõF*ÆÇÇ×Î÷$—GŽL€¬ó¢¢²ÎЗ‘Mt)m_„‹azí„51|›( ÈÈÈ@=Œ-JÓ¥°øî;’mffF‚eK–Œ™ÿý¯|= ë75•Ø?Ç×ß?—KÖ¿ŸYÛ/^;Ì̈1ªu(ðùúkÃ!ŸU:BÎãgöƲd‰®–ùðCH¬æŠiº!** K—.Õyæyõ•êÄ0ÄùáîN”ZˆŠ"Ëvíˆq׺51XïÜ!×ñ>}Jjñ…ÂÚ/oàpJî j5I/ ¬ü\4.—D{{ö|ù½²2x<¢<¥§c :׳&ŒR©Ddd$Þ}÷]c‹ÒpÐhȵ–ÃAsWWp¹\°, ‡…BQ;}U¸\rО3|>1^·m#Žö—IdYà×_‰ÓräH¢ÿØÚK—B””„â‡ý-68âããáééY×îÆË’{ŽVÇ2±è×üq8Ä)¯µUœ‰>"—“õ®ý8bï;FïÓ¦D©$Á KKò¹œô¹9wŽd¨Õj¬‰<O7¦¸¸qqq`YcÇŽÅ[o½¥RYû?N ¸|ù2lll ó²«Õ¤^²wï’z¶òˉBòá‡DÙX½š(®¶¶dß|cX£–ÌL²X´ P[+Ѷ-‰V=Kfá-ZTòšÌL’ŠÕ¯yleE ‰šC>gĈ—¿¶ys [7ò=ÄÆ«V•ÿ:WWýæ9këê5³±° u~1D^Q?~ ±Xlx=†DÇŒ||*~HD ­¾}IôñàA²´$7ß_%k_"!i³ãÆåüí·ÉM];ÂB­&ëÊÓ³ìMþìYrqˆ<¯¿NŒc±˜|†–ü|Òéòeb$CÒÝÜHŠzEu’žü"B!9¯JcjJ<‡üÌœYùù_|'r9IßmÝš\È;v,kà‚•1„J9ÜX;;ˆ½½kf 4ANŸ>Ôo“µš(ÎÎ$JZ­ñLÖ}ëÖd}£ÖœÏ'Y*µ©)ibVðx亡VWìáEINN†D"yuºk4Ä‘]Y‡ö#GȵÖÃS¦@*•B,ÃÜÜ\—Xc„²Á„víÈ}HKq1¹N+•¤ìÃÝ\„Bâ\MK¶o'ç?å¥Ü¼y“ް©Œ§OIf[j*É {™þfiY¶FÕÝ]¿+¼©iÙ¾§O½¾cGr·´$zà!%Ùa±•N¾úŠè~©©$ˆwð TqqD†`pJ°L&ÃéÓ§ñÁàÑ£G±XŒ 6`õêÕX»v-Þ{ï=ܺu«Á¤«°,‹ˆˆüùçŸXºt)Ì^æ +Mr21ú8I*zÇ0äÂIJäB:m¹yz÷Ö-¢ä.]j¸!öÓO$m„e‰7ü›oÈv W/à‹/H¤F+@<›6•MÇÒF­*ãã‰QU’*YP@Æ}’n8oñ°¯Z¥§XSê…BƒböìÙ†5˜`YÒ¼*>¾¬áEþß kkâÀ±¶þù‡(Àƒ—D…,,H¤2<¼$[zÞ"ÃÔÛ›7Éã”rÓgbÐ>Lþ^<Ÿ‘AÖõo¿§ @ÎK–%ÙZÏÝ A$í±6¯;’ uu"^\.‘wíZ 6Òvy<’‚L½Í•RTT„àà` {Ñh¬ Ž'×¶·Þ"™ñ(GE‘tØ ÊŸ…)õX³¦nŒÅ¦ˆ@˜™£T‚[e-M–eqþüy 6¬AOc¨…‚dЍÕÚz¹nòô)q^¼XÓ¬Rý çÔ矓vmÛB©TB"‘ ??EEEä5ÚÜÂBýÏd¢ó\¹BÒ!K_§5¢dŸ8AŒÍŠP*‰3jÓ&ò8?ŸèTï½Gt9•ŠègkÖPcµŠ°,«›JÒ Ñ–XdeÕþ¾•J¢GýôÑ™^ >yB®“o¾I²Â Ò²ôõ’aˆ ±b¹Od]_»F UaÌÒÙÃ)ѯìíõU€8j{ô z“BAJQÞ{¯v¦* ëñãDZuëVØÛÛëÆüñǸ{÷.¦M›† 6ÀÕÕŸ|ò ÒHý‰R©ÄW_}…×_Ýp¯ä… $uÊÆ†\´îÝ+©5Š'ÉÄD¢ÐN—KjÑæÎ%?puÌÖ­‰Ç0+‹’Ú¨©¯"i¼RTD¼žže£-/–(W¥ÑF`ôhR+úûï%Í]®^%‹rÀ€ªËíâB”jªX×+OžŸ¤ƒhÇ̤¤ôà.]€•+ÉÚˆ µ“o¿­ŸÒêéYq ¶V™·²*¿v; €Di£¢ÈßÖ­•Ÿ;~~$« ¾¡]8gÏžEŸ>} ˤ©Œ¨(Râ0bDùó±;v$t¬V éÚ™±±Æ£A///ãÏ–ˉRmm]þu»¨ˆ\¯×®%¥Q1CC‰¾¤½oØÛ½éøq✟<¹ìþ† #Ye¥¾Œ ¢Ã”nìX F¡€|ëVXõîÖÚ¨”£#ÑÓÔj¢Ük4$}14”8&G&úSHч,-IÊïÖ­Ä®ÌáØ³'ÑKg•ÙÛ“´IJµ¸qㆠV{×ñÚ@£!÷>ŸgŽŽ$ʸiqXH¥U×—¥RržØØ”ô»Ð üý‰íáíMš0j³æT*¢£ee‘çJg®dÍ}ò q’‡‡½©eKbK´jEì˜ìlò·}{ùöBm`hYZ1È`ÍÌÌ„J¥Â!Ct‹('' x÷Ýwañÿáa[[[888àùóçUY¡zâòåËzòDiïN@IAÔÖÀZZZmªZÜ܈ú²“PHÆ^üùgÅQ nÝHN9@n4¿þJŽaãÆ² _J+]1åè%>>sçÎ5¼õ;—«“?žÔ4têD.Ȧ¦Äp9òå)Ã/òèI#nÕªìs|>I«”JI§ÜF2ǙҰ‰ˆˆ@\\ÞÿýÚƒ–|ù%qäU´¿RúÒTј™Aª1ûŠsõêUômFÐŽ¤>mçÎò› ¤D#)©Ä` I¦LéÌss¢˜÷êU2 ©¸˜(åqq$bêçW6sæÙ3ù,Ý8¯EööÈš<f™™(LJ"--õ³}IÏm€èx¥ë÷ªÚ¼ÑÞ¾êÑ*ÊK‘J¥¸qã¾0†“º2T*è¹s‡¬ûiÓH.//âÔ¯*……dÝ%%}ë‹/Ⱥï=â$ïߟ¼ŽÇÓw”ÈåÄ MJ"eS/¬ >¼ù¦þãÒsïœHCÌFˆAwZ™LFóR„gÏž!''=+Šm-C‡ {cZñ¼½öZ‰gÃ)¿¨¹®f^VÕ‹jnNjf+¢ukR;“새dž»nh4•¤>U–%5 jµ~÷6 ‹’‹¥x %) øùgr­¨†Áܼ|ƒ–B1…BŸþ“&M2ì\HÊíÛD‘hÖŒ(ÑJ%é„8x0qäÐë%ň¨T*DFFbîܹõ÷¡ 1ɹ1l¹f |ÿ=‰²–g°š™óçë§ùjkðË£´Á÷Ï?¤¶ÎÍ8Nµ$'“:ñ>"÷¨JÎG CûúÂ4;»ü5oN²‰J+ó”Arr2AƒÈÐÔCÛXnòd¢;•Žú³,1h}çfAéGG#ãÆ=kñbòZít >Ÿ¤ÜvëVQ}KKR­ÑèÓ^ º;88@  Uû¸uë<==áXÊÒW©TÈÎήŸ™w/!??BCÒµŠŠˆ1:ÚØâצ¦%žB§$Å™Ò$ÈÌÌ„‰‰‰aJzx¸þüϺ oßÊë(”Z$11ÉÉÉèÿ¢Ã¥"rrH-@®‹Q:´)„B!ɘ7¦ûRŒÎ³gÏ`oo-ZÔ߇ªÕ$Ãàüy¢Pkñ.]H†VyY]*©ëfYýûË”ôǨŒiÓH}ÝG‘ZHO…'OˆB_I]¨R©„T*…F£©8¥T(¤Æj%<<­[·6¼Ä©¾01!k»ô}A$"ý8^ìjžšJ"ùbq‰ÃF '§’2ss2Þ¬²¦™ @UÖ ¸ cP„µU«VhÓ¦ ¾ùæ!77AAA˜>}:x< 233qìØ10 cx˜: ¨¨ö†¤j0 Y\^^¤öŽËS8¹¹¹†5˜‘ËI ù'Ÿ”¤kÕŽŽÄH•}J£R©päÈLž<UI‹IÃ<íÈ5¢P(·nÝÂСC!¨+DÛ 7,Œ4y|ýuríþæò[QfŒHTbp&$sà@àäɪǫ `Î’ Ñ£G¥/åñxËåP«ÕËåuó}QêŒ`DMÖŠ!dfK»v/Ÿlñ¿ÿ‘Ò¨ Ê>gbBR…»v%õ¥[·’DíÛ“ùð´t¤Æô š˜˜à­·Þ† °råJ°,‹.]º`ܸqàr¹¸{÷.¾þúkdddàÃ?¬tö•L&ÃÍ›7ѯ_?½ÚRFƒ§OŸ"""-[¶D= ‹Ž–ó9Ö†´TærI gssj¬RjÌ;wàèèˆÖ¥ZÙ«T*ܺu YYYèС|}}k4*==ݰ¦¦d^p}D? ±Ci”\¹rþþþp.U‡\\\ŒëׯC­V£K—.hÙ²ezË‘€uëÖU­võæM’ÎX“¹¸”W©TŠàà`ôë×O¯J£Ñ <<Ïž=ƒ‡‡zôèQgƤR©ÄÝ»w붦/#ƒDƒÞ|“Ô†jÏ×ʲpnÝ"NŸÒ÷/±˜œ[$B{æ 1bûô©^·õÒ @öó´\–eë7"ÝHIMME\\¼0B¥R!88ÙÙÙð÷÷‡¯¯/xuÜí¾¸¸qqqh×®]íô!xññdt¥“12+ÓÅ22*.23#k3(ˆÔXk4¤öº–;å¾Ê¬%·iÓ'Nœ@bb"X–EË–-u ØÑÑS¦LA¿~ýàQI÷)†apíÚ5:t;wÖ3X·oߎk×®ÁÏÏ'OžDëÖ­±qãFÃk’þŸüüüª¹¹¤;ܰaU¯¥P*!%%;wîÄüùóukaa!6lØ€ôôt´lÙ‡ÂðáñråÊjNQQ©ÙygΔ¬yóhª.¥Æ°,‹ððp|ûí·øüóÏukLL 6lØ@+++ìÝ»«V­ª39˲xüø1ºuëVuÇÍðá$êS—)ñ”FÃ0¸zõ*Ž;†.]ºè¬[¶lAPPÚµk‡'NÀÇÇ6l€MmÖ™ÐÀçóáV—³Í}}I£GC8xD¥J×Óåç“&e––%ãfø|2í 6¨‚>W\\Œ¼¼\]]+}Ÿ@ €ƒƒC¹7 ¹\^ö‚eeÌŸO;D6a´u¤¶¶¶ J™·µµ…\.Ã0àr¹J¥H$/õž›˜˜ÀÑѱÌv¥R @PVÉïÑèÛר‡K©Cx<`aaÑ Ö¸µµµ^#¦‚‚‚—vz·²²2Xщ‰‰•••¾2ïáìÛgì¯RK8::–u:kkkdggëtµZ‚‚‚—ê*VVV†Ù©—íÚµkÕ9;“Y‘­[—8,_hpYk˜˜}ß¿OÒ‹'M"F±‘áp8HLL„©©iƒº6–ŸÏ‡££#’µ%j „u‰D©T __ß ßÃåraggW­”^‘H„ÔÔT´oßÞpae2`Ý:¢Û÷ïO2jjkk’>÷.I-n`סƂ¹¹9ìíí!‰j´ƒ]m,Ë"''‰‰‰HLLDjj* D"‘n›ö¯ª˜´tëÖ 999HII@jf=zTn IUQ(e›.¹º’Ùa´Ý9¥žéÕ«ž>}ªK_OKKCJJ :UÓ+-—ËÁ²lY¯§«kåíÙ)”:€Çã¡Gz9ÂÂÂ`bbR騳êZrî0 ñ°Ó® ”:¦{÷îÈÌÌDjj*r~üøqt•òP(¸ÿ>zöìùò§§“¨ê¨QÄh­¯ìš¾}ÈH’ ìæVóY«µ€©©)ø|>d2YƒO n¨ôêÕ aaa:çcjj*ÒÒÒP'Ÿooï—;tÒÓÿþù‡Œ¢d|Ú±ƒ¤òNšT{óß…BÒã&>žt¾®£9Ë”ªað™,“ɰwï^Ç“eYdff">>¾L§Óï¿ÿž4zÑ^ìOž<‰ùóç#88©©©8p`µ°L}_z:ñ˜Ts®+…Rúöí‹“'OâÊ•+ ĉ'ÀápУGjíO[£­g°ž< L VJ½Ãår1xð`gЭ[]·”WKKKôïß_OÙðóóÆ pðàA8pmÚ´ÁöíÛ«Ýd@,C­V—¬11¤ê¸qÆ>|Ê+€££#ú÷ï¯K÷åp87n$ ¶nÝ F,_¾\oüMmpåʘšš–DXÏœ!ŽÈºJ¤¼’xyy!00PïmmmÍ›7cïÞ½˜?>œœœðñÇWMá6€üü|˜šš¾üþBþ­îxšš 4HQBBBƒOn(téÒ¥LÊy‡°nÝ::tû÷nÝZ']—µ ‹/®øE*—tìXR'ÍáÔO“¯^ýªP-ƒU‹F£F£Ã0àp8àñxUN¿8p`¹ÞÈöíÛcË–-ÈÉÉ]ͧ¤¤ÀÙÙ¹ä¢U\ ’´ ¥ŽquuÅÚµkõ¶i#PíÛ·Gqq1\]]Ëvø5€¬¬,¸ºº–œwYY@«Vµ—C¡TB»víЮ];½m3gÎÄ Aƒ ÑhàêêZëJŽX,ÆÏ?ÿŒ÷Þ{¯Äé™—̘AÓ¶(µÊàÁƒ1xðà2Ûýýý±eËäææÂÞÞ¾Úf*#>>îîî/?¢¢ÈLTj  5sàñx4ÂZÞ|óÍ2Ûx<† £yóæuö]ŠÅb(ŠÊÏ¡¬,2nfÃÚæ¥ZÉýááá Bhh(òòò`ii OOO 0eëF ÀÆÆF¯quIIIÑO¥áó!Cê}ˆ5…ò"ÎÎÎpvv®ñ~Š‹‹áààPâ”ñô$J;…bDx<^¹³ýj‹‡ÂÉÉI¿žjÕ*c6åCÛØ¯®ˆˆˆ@çÎ_Þpiþ|c sss0 ¡PX;3=_ajKW©ŒÂÂBp¹ÜÊëWÿýpw§Æê+ŒÁ«\.lj'ðË/¿@"‘Àßß;w†L&ÃãÇqíÚ5ôîÝ6l0z‡Ö‚‚ýÍÎŽ(ó´ŸÒDHOOׯ tw'JE£ÑàÒ¥K1b¹¿°, E†6Ò£4X–E||<&hÇ11  V“ ‚Òz•BAtšF0¾­¾àp8HMM­“ôUJíÖ­[WÁfÍ2¶¨#b°å„ï¾û“'OÆÜ¹sáââ¢3Jår9Μ9ƒýû÷ã믿ƺuëji­)eZds84]ŒÒ¤P*•hVºf/-Ì £ëœÒDÑvÙîÓ§¹÷’9}DçSš ™™™H$¤qeQð…äM­TIDATçŸÀ£GÀ²ed†<Ë’ëý©SÀk¯~~ƹÁ`aa …•ÜPꇈˆtëÖ­òL‚O>!]{)¯,¹£E"Ž=Š¡C‡béÒ¥puuÕ‹ šššâ7ÞÀš5kpåÊÝxc‘ ÷ÒѦŸîÝ3ªLJm’­ßÌæÿ#ÃÛ)”&Jpp0X=¹~4Å Š)¥ ¡:™šš’®¨Ïž‘ 1­SæßIW`–š77¶¸ ŠÒ‚Ú _Š> …OŸ>­xþ*ËJ%uÂS ‹°¦¦¦B$aáÂ…væñxèÙ³'œqçÎ2 9ê FƒŒŒ }ƒ54¨fÇa ¥!RXX¨?¬>2’·¦4Yär9x¦[7V`GP(/R'Ú­H$Âúõë‘iÄzºÌÌLðµµM\.0y21Z)”&€¶·‡vL“…Я5X)M–ØØX´×h€Ã‡i£%J“„IOGÑîݰûðCšFiÒ<|ú®¯¿nl1(ˆ:ÑnY–…T*Ã0F;0SSÓ’tI‡Œú yJA¡P ==Bí©”¤S(M†a@‘ˆŒ= £›(ML?úûƒ;hm&FiºÜ¸a\\‰ÃB©M6“˜˜žÖ@-.¶lärc‹E¡Ô ÃÀÉÉ fffdùsÀ¥KÆ‹B©d2²³³áؼ9Ч±Å¡Pj—°0 <çþú ½‡ =OFiªDGCºu+dffpuu5¶4”FD“5X…B!¬µ哒ȸç²R(¥R‰ÜÜÜ’±M t}Sš,b±EEE0ÿâ ÀÈ ý(”Z%3زù¹¹ ÂÈ‘#K®ëJSãìYÜ Ñ*06Æ¢„A9' ุ¦Ò×6€f)))%­²“’??c‹D¡Ô ÃÀÎΦZ#ÕÞžÖhSš,*™ -LMamiilQ(”Úå÷ßÀ@D™˜ÀËË -Z´0¶DJÁÌ™ƒ¿#"0·[7c‹Bidd°&&&b÷îÝÈËË«ôuJ¥ÒØÇsssØÙÙ‘]º;[$ ¥ÖP©T‰D%ÞxЦS(M Uz:¦À„e- …R»Œ8;#ýÊ4kÖŒFW)M–%Ó:¸\ðùÈ‹K&P(UÄ ƒ•ÏçÃÙÙ¹$ªS ^^^%)¹F 33³DNš'Oib0 kkë’”ZóDi¤?x€>îî4íÒôðñdddÀ‹fÉPš, „†»v›6!U,†»»{•ì ¥4¬-[¶Äúõë-s•P*•°°° –²²ÚŒÒ„P(‰D¤±XX Ñî©JD‰Â6m`K;§Rš‘‘Ä ãå…‚‚øûû[" ¥vÉËvîfͼ¼ö,š7onl©(ƒš."$$¹¹¹Æ–»R `ffrCØ¾ÝØ"Q(µ Ã0ÀÅ‹¤N›Bi¢ü­R!‹˜§45Μž>dgg…BiJp¹ÀÌ™ÀàÁ—‹Ç£}ûöÆ–ŠÒ1È]žžŽÝ»wã½÷ÞC³fÍtÛ>Œ5kÖ€_ Þïââb¨T*½muËÎΆ¹¹9y’Ð&”BEËlllJÆ0Uœœ888@¨Ñ11ÀôéÆ>4 ©¯–H$zs¸y<¬¬¬Já€T*E†H„æ¾¾Æ>4 EGu• HL¦NÕíÏÂÂÂØ‡E¡¨=]ööÀðẇðôô4öáQ!Y˜J¥b±XoâÂ… XµjU­´k×.<{öLoÛ;#Ty2™L¿ÓõÌSùùùøòË/‘‘‘¡ÛÆår±}ûv¸»»Wy?¹¹¹°²²"ÞËiÓGGc…xþü9¾ýö[ë¶µhÑëÖ­«Ö|ÉœØXôQ«Éz§P;vìÀóçÏõ¶-]ºýªªoh4D7qq@34ÂJi(äååáË/¿Dff¦nŸÏǶmÛàææVõåçVV€@€ÜÜ\¡U«VÆ>œ(õJ@,ãÑ£G;v¬Î›Îáp ö¬K$8::&&À!Æ>, EGJJ ’’’0qâDÝ6{{ûjÏÜãFGcXlìâPôøï¿ÿÐ¥K´lÙR·ÍÙÙ¹ê;05%™1\.¤R)†­­­±‹B@"þ?Ƹqãt‹\.·${±ªìÚ̘´k‡[·n¡]»v0£ (Õ A¬"‘ Ã`êÔ©è\ƒ2®ÚÎÀt01¥‘›› kkkÌŸ?¿ZÑ&-™™™¤q6ŠE£O”˲ÈÈÈ@›6mðÎ;ïÔÊ>` 1(”:F$eYL›6 k22ïÿS+ãããѼys…Bc…€”ÙØØ`Á‚Õw¤¨TÀ³gº °øøxt£óW)Õ¤A¬ÚÈhJJ rrr`bb___8994›,--DX#"€7€¥K}h }²°°@hh(d2š5kƒo*•Ф}û-е+0b„±B˲HKKƒ™™nß¾ÂÂB4oÞ¾¾¾ÕcÀ0 b am@I…Rפ¥¥A  99YYYÕÓUnÞâã7ßDdd$M“¤4(RRR`ii‰'Ož@*•ÂÑÑ>>>†¥­^^€ƒ4 âââ0‚ê*”jbðV.—‹ììlDGG’““¡V«C:––ÂÃÃà4°ŒŒ dggã‡~@óæÍ‡Ö­[cÓ¦Mzi7/"‰pûömŒ5 æææ`†Ô°Þ¿¼ åÕ@£Ñ <<Ož%;ÖØ‡E1 …wîÜA|||ƒYã à ==Ïž=CZZ 55sæÌÁ›o¾Yic¾¨¨(Ü»w]»vÕ5õÐh4ø'?“ 2ö¡QŒÄõë×õêè¥uWWWÄÅÅÁÛÛ›6mÒïŸQ –e‰çÏŸÃ××—Džþ_ùÏÌÌ4¸ô‰Ò4(..Æ7 ÊÔéé鈋‹Ã·ß~«ÓUúôéƒÏ?ÿ¼B]E¥RáÞ½{ððð ëÙÁøà€ÃT*…L&£#m^ARRRp÷î]´nݺFû18ÂÊçó±sçN½m\.‹/.óÚ£G$ @ À”)S0{öl8;;£°°Ë–-÷ß~‹¯¿þºÂ÷™˜˜ E‹:ƒ9##ƒ´Í~þ˜=»fß4¥QÂápàââ—ju&­+ìíí±páBÌš5 fffˆˆˆÀ|€ãÇcv%kÕº5®V«ÑÂÆ°µÚµ3öaQŒÇC‹-Ý`”‡ƒÖ­[cäÈ‘?~<†ÁÕ«W±eËøúúVÚÆÁÁnnnzÇ¢V© ÈÊ‚-Myeñòòjp«@ À´iÓ0{öl899!??Ë–-Ã÷ßmÛ¶•û‡ƒfÍšé&, ¸øÿtâ´´´ãt¢Ô/B¡žžžzX´hfÍšSSS„‡‡cõêÕ8yò$fΜYî{¸\.ÜÜÜ`iiI6ðxÀÿ—ç‰D"˜˜˜ÔÊ4JãÂÚÚîîî†u—.ƒVŽ——¶lÙR¦•{EêIéׯŸžBcccƒQ£Fá·ß~ƒJ¥*ÁÕbjjª3XY–Eqq1œœœ€ùóšfóJÂårukCQæ`ú ãg|}}ѽ{w„‡‡C£ÑTxBk V-©©©àZ[«VÑ,‚W>Ÿ-ZÀÎήÁ¬q‡Õ«Wës¹\ 8{öìABBúöí[¡¬Íš5+Ó}R TbT||ˆnݺUÙó˜——•TJn ,UŽBùâ‹/pþüyH$H¥Rܾ}ÅÅÅhÓ¦Á‘à´ëבçî3šLi p¹\\¿~;wîDzz:är9²²²põêUTMWILž>@R% B¡Ô!<‡ÆáÇQXX¹\ŽgÏžáÑ£GU×U´Nxkk¤ß““5X)ÕÆà•“ŸŸ>úwîÜÁ† àé鉸¸8]þýû÷!‰ðÖ[oÔMŒËåbܸq¸}û6V®\ OOO¤¦¦Þ{ï½*ïG©TÂÖÖüÿ%¹ó/¤`R(Æ‚ÇãaÆŒøòË/‘œœ ;;;DFF¢eË–5jT•÷£P(ÐÒÙ¸sèÓÇØ‡E¡è055ÅìÙ³qðàAܹs\.Ïž=ÃØ±cÑ©S'ƒ÷wW(„ÌÇíHÊ3…Âår1a„„„`åÊ•ððð@JJ ¸\.V­ZUµ}ú oß¾üËå‹ÅàddÆþ~)=±oß>„„„ 77cÇŽE@@€Aöììl0 `i ÐÜ”—ËÅ´iÓгgO„„„@­Vcîܹðõõ5¨c¼–¸ìløùùû°(=<<<ðÝwßááLjG¿~ýлwïªë*IIÀÿ§Á¦¼S}úôÁ¾}ûpëÖ-äååaܸq†é*¦¦Àë¯ë¡k×®Æ>,J#Æ ‹2==!!!˜={6† >Ÿ¯3XR<ÞªU+,_¾ï¼óÆŒƒrrrÂÈ‘#ktPNNNà>>õøUR(/GÛÙuÚ´iÕÞ‡F£“‡0|¸.݆Bi(…B´mÛVWßWm$´ŽŒ„§ÙJ}áììlPfŒÞÞ:‡z^^°RZ]ez-e)¦¦¦Â‘ö•¡ÔƒjX³²² Ñhн{w]ô”ÏçÃÓÓ“tåýœáììŒÛ·o×ûI¥R‚3f àî^ïŸO¡Ô5¹¹¹`„B o_€Ö>Qš(Ь,tJLÔ5á£Pš £F‘î©èlJJÓãðaàÔ)D/ÏÏÏ/ÓžB1ƒS‚è¥úš››ãÝwßÕkãÎápÀáp ‘Hêý€X–…‹‹ ø&&@š¿I¡Ô ॣ#éÂGÇ}Pš(Ò´4Ñ&”¦G©¦5 åK”¦Fz:€4\²µµ-™ÏJ¡Tƒ,:í¼¿èèh°,KvÀåÂÖֺ׉Åb¤¦¦Âõÿ×'‰ÊÐPðöï¯÷ϦPêƒÌÌLØ\»üþ»±E¡PꌖÅ=ZÖAiâÈd2Øÿc ¥É›««ÓNLL¤Y”cÁêéé ///üùçŸÈÉÉÑ­ZX–…L&Ão¿ýµZnݺÕûi4Øæçƒ'“ÕûgS(u ˲P©T°..ììŒ-…Rg¤3 r;t0¶JRPP;z-§45>øø#5//¬”cÁ* ñÖ[o!)) o¿ý6Ξ=‹¨¨(dff"66ׯ_ÇÊ•+qüøq,\¸žÿ?»>ÉÌÌ„07š+Oi‚0 ƒììl˜ÛÙ­Z[ ¥ÎÈËÌ„#Uä)M¹\Žœœj°Rš¥tðøøøš7᣼ò\äëë‹;v`ÿþýøæ›o`nnµZ ©T KKK¬X±ãÆÓ«k­/ŠŠŠ`5s&PÃNÃJC„a¨Õj, ]°)Mߨ(8Ucv+…ÒXHLL„››íLi²Èd2¤¥¥Ñ†K”c°ÁÊãñйsgìÞ½QQQxúô)233aii ///têÔɨ3ÅÄb1}}iº$¥IÂ0 4 Ìš7Œà¢Pê Éýû°éÙÓØbP(uFTTZ·nml1(”:C.—ÃÄÄ„6\¢Ô˜j·_èС:4°£¼ÌLxðù€F£×‰Bi h4˜deÁêÖ- ];c‹C¡Ô¹99P˜™öÁ¦4U’““Ñ¢E c‹A¡Ô …,ËBH'PjH“›ûb'•¢Ó… mºDi‚°, Çü|ØÅÇ[ ¥N¹Þ¼9dt–6¥‰¢ÑhöíÛ[ ¥ÎJ¥P(0111¶(”FN“3XóRR`ak ÐÙ}”&Ã0P¦¦Bئ±E¡Pê Fƒçj5Lš53¶(JP\\Œ¢¢"Ú=•Ò¤‰ŒŒDË–-õF_R(աɬ,Ÿ~@5X)M†aíæUÆ…B©3RSS1ÜÜ6ffÆ…B©$ ¬¬¬ŒÒœ’B©/’’’ЦMp8c‹Biä49ƒõAa!rÆ£õ«”&‰F£A²¥%#ŒŒ¢Pê‹èðp¼£V/Ìú¦Pš `|ê\§4až>}ŠVt¥hR+˲075E3GG€zs(M¹\';;˜ÓÈ¥ £Š‹×Ì  uO”&ŠD"µµ55X)M–ÂÂBdff¢mI©š”Áš••…Iùù0ÏÈ0¶(JÀ•J±6=ܬ,c‹B¡ÔÏ““‘Ö¿¿±Å PêŒèèhx{{Sƒ•Òd‰‹‹ƒ‡‡­_¥Ô MÊ`577Ç33Z¿Ji²¸ØÛ£¹…@o”& Ã0x”•î˜1Æ…B©3ÒÓÓáêêjl1(”:#%%…6£ÔMÊ`µfØ›šnnÆ…B©Š‹??€á¦4QD" Ut(MšÂÂB8;;[ ¥N`áááðõõ5¶(”&B“2XaflßЮ{”¦Š‹ °t)m*Fi²äååajz:’blQ(”:A£Ñ 66–FX)M…BÜÜ\Úp‰Rk4­ÜYÀËËØRP(u‡‰ mDCiÒH$4OO¸MËŸJ¡hÉÌÌ„@ €Í£4QT*”J%lllŒ- ¥‰@5 …B¡4ÔI$>Qš( ð¢ÎuJF$¡¨¨¶¶¶Æ…ÒDhZV …B¡4j’³² ›5‹FX)M–ŒŒ ´hÑÂØbP(uƳgÏàããKÚoƒRK48ƒ•aäææ"''ÖÖÖhÞ¼9x´^Ò„Ðh4HMM…D"££#À¥Ê9¥ ¡T*‘””†aàââkkkpª8{̤IÀ¤IÆ> ¥R†ANNrssaccWW×*ë*‰‰‰0ö!P(•¢Ñh’’©Tj°® c¥ Ñà ÖÿþûûöíCZZììì0{ölŒ9ÚH‰ÒP*•øë¯¿ðË/¿ ¸¸-[¶Ä¢E‹Ð«W/c‹F¡Ô b±‡Â… À²,|||°jÕª*G”J%ŸÐ¥‚ýû÷#==ööö˜3g†^%]¥K—.h×®±B©¥R‰sçÎá—_~X,†‡‡/^Œ=zTéýaaaèׯŸ±ƒÒ„hPaÜÜ\lÚ´ ;vÄ_ý… ૯¾Bhh¨±E£Pj…'Ož`ÇŽX´hÎ;‡víÚaãÆ(**2¶hJaY'OžÄßÿíÛ·ãèÑ£`Û·o‡L&«ÚNBCŸ~2ö¡P(¢ÕUºté‚¿þú sçÎŶmÛðôéÓ*½È!tl¥AóðáCìÚµ o¿ý6Î;|ôÑGUÖUÞÿ}têÔÉØ‡AiB4(ƒõÁƒ°¶¶Æ¤I“`ff†þýû£M›6¸uë–±E£Pj…àà` _¿~033äI“`jjŠ[4 ¥Æh4áµ×^C‡àèèˆiÓ¦!)) ñññUÛIQ`jjìC¡P*äÞ½{°³³Ãĉaff†¢uëÖTW¡4´ºJß¾}uºŠ@ ÀÇ«ô~???c¥‰Ñ  ÖgÏžÁÁÁAçy411A‡ðäÉc‹VëÄÅÅA$[ ƒHLLD^^ž±ÅhÔ„‡‡£mÛ¶077¸¸¸ yóæM.‹@©T"22jµÚØ¢TµZ¨¨(Èårc‹ÒhaOŸ>EçÎuÛüüü —Ë‘””TµXX}úûP^ŠX,FTT”±Å0©TŠçÏŸ[ŒFODDusT›ª®’ŸŸ„„c‹a………ˆ‹‹3¶žððp´k×fffWWW¸¸¸ <<ÜØ¢Õ*Hid3¿322‘‘al1êUÃZTT>Ÿ¡Pàñx°··GVVV…ïaYr¹éééP寯æöíÛhÛ¶m£êxïÞ=¸ººÂÛÛÛØ¢T µZÜÜ\XXX[………055Õ5.077‡……²³³+|˲J¥HNNŸÏok\"‘àæÍ›033ƒI#™«P(„þýûÃÚÚÚØâT ™L‘H†aŒ-ŠŽ¢¢"Cììì V«+uб,‹ÂÂB$''Cв%Àá ü†œû÷ï7šµäÖ­[j6bNNÄb±±ÅÐãE]…ÏçÃÎήR]E­V£  ©©©¦‘d||¿Q­†a`jjÚhdÖh4ÈËËCÛ¶m-J•¨ì:îàà€G!$$¤Ñ8ª†˲f½dÍh42ËårˆÅbÖh? Ê``< Ã@¡P Y³f¾‡ÇãaðàÁÆB©B¡,Ë‚Ãá@­VC­VWÚ€ÃÒÒ&L0¶èJ•z©à …B¡VVV¾§Y³f˜={¶±E§PªDut''',\¸ÐØ¢S(UâE]E¥RA£ÑTððð kœRg4¨˜½¯¯/Š‹‹uu’*• QQQðòò2¶hJ­Ð¾}{¤¤¤èÒrrr••OOOc‹F¡Ô.— ???ÄÆÆê¶ÅÄÄ€ÇãÁÑÑÑØâQ(µB»ví ‰tÙFJ¥ÑÑÑTW¡4Ú·oääd(•J¤";;›ê*£Ñ  Ö^½z¡°°ÁÁÁJ¥ˆŠŠÂÇ1jÔ(c‹F¡Ô Ä“'OðüùsH$ܺu ÙÙÙ:t¨±E£Pj —ËÅ Aƒpùòeddd   ÿý7\]]éyJ“!00yyy¸uë¤R)"##ñèÑ#ª«Pš ƒ £G ‰D‚àà`äååÑŒFŠÑhP)Ánnn˜…··w£)D§P áÉ“'HKKC÷îÝáäädlq(”ZE¥RáîÝ»P(èÞ½{£ê¤K¡T•ÄÄDDDD M›6ðññ1¶8J­óøñc¤§§£G´¬ƒbT¤ÁJ¡P( …B¡P(Jƒªa¥P( …B¡P( E 5X) …B¡P( …Ò ¡+…B¡P( …B¡P$¼O>ùäc ÑØ‘ÉdÈÉÉAAA8LLLtϱ, ‰D‚ììlÈår˜˜˜€Ë-ñ0 ƒ‚‚äååa…Bp8ÝóYYY(**ǃ@ Ð{¾¦¨T*dddÀÒÒR·_–e!•J‘ ™Lðx<=™ ‘›› F=™†AVVD"¸\n­ËL©_X–…X,Fvv6Š‹‹! tÏ×t=ÈårdeeA*•‚ÏçƒÏ¯ÝæåR©¹¹¹°²²Ò;¦¢¢"äää@­VÃÔÔ´ŒÌ¥ÏéÏK…BììlˆÅbÌt7^†H$BVVd2LMMË\ó²³³QXXX¥õPúüxÙ= 6‰D‹Å077ד977PFf•J…¬¬,ˆÅbðx<½5ü²{¥ñ¡V«‘››«»æ½¸•J¥n=¼xM«©NPdggƒa=ýJ­V#++ ÅÅÅå®a™L¦“Y(êÉ\ú R©ÊÜ(…BœœÝ|äÒëÐõP ¦h4ddd”¹÷he–J¥zú˲(..Fvv6”J%ÌÌÌÊȬ½°,[ë2×7 j¬Mc$==ÿûßÿ ¹\ŽÖ­[cùòåh×®ÒEpïÞ½ˆˆˆ€µµ5Þxã Œ;B¡ ÃàÖ­[8räÒÓÓááá7ß|Ý»w—Ë…L&Ù3gpòäI¨ÕjøûûãwÞ»»{­É÷î]lÙ²'NœÐÈÌÌÄîÝ» Œ;S¦LÑÝ(îÝ»‡Ã‡#)) Í›7Ǽyóлwoðx<( \¸p?ÿü3är9Ú·oÅ‹£uëÖÆþ©(ÕäéÓ§øá‡‡ƒž={báÂ…pss˲¸{÷.>Œääd¸¹¹aÞ¼y Ô­‡óçÏã矆B¡@‡°xñb´jÕ PTT„½{÷"$$B¡X²d‰žâ]Ôj5N:…›7oâ§Ÿ~Òmüø1<ˆ¸¸8899aîܹèß¿?ø|>”J%._¾ŒcÇŽ¡¨¨~~~X°`Å8xð ®^½ .—‹.]ºàý÷߇¥¥¥±*J5¹xñ"NŸ>ÄÄDXYYaèС˜3g¬¬¬ T*ñï¿ÿâØ±c‹ÅðóóÃÂ… uì‹‹‹qàÀ\»v |>_·´×Óääd|ÿý÷xöì,--ñúë¯cüøñ …µ"»D"Á÷ß>Ÿ?üY÷×®]ÃÑ£G‘ŸŸÌŸ?º÷üòË/8þ< S§NX¾|9ìííYYYؽ{7ÂÂÂ`aaÑ£GcêÔ©0555öOE©2™ 'NœÀ… ““WWWŒ3Ó¦M@ÖñcÇpñâE@çα|ùrÝ“šèµA~~>Ö®]‹‰'bìØ±ˆ#ò?þÀŸþ †a€¥K—ÂÅÅPPP€;wâÉ“'033Ãk¯½†9sæèÖphh(8€ØØX8::bîܹ0`@­;L)õCnn.:„Û·oC,ÃÃÃóçÏGïÞ½5´sçN„††ÂÌÌ Ã‡ǬY³të¡&:Amƒ5kÖ`×®]:}Y$áÛo¿Å½{÷`bb‚þýûcÑ¢E033DFFbß¾}ˆŠŠ‚æÌ™ƒ!C†@ @­Vãúõë8zô(òòòЦM¼ùæ›èÔ©“±ªêÃRªX,fW¯^ÍN›6}ðàî]»–}ýõ×Ù¤¤$V,³‹/fß}÷]6::š½xñ";tèPößÿeY–eSRRزß}÷›’’Âîܹ“1b›‘‘Á²,Ëž9s†{ïÞ=vÒ¤Iì?üÀªTªZ‘ÿÑ£GlÏž=Ù‘#G궉D"vôèÑì¦M›Ø””öçŸf‡ †‡‡³,˲ÿý÷Û¿öÔ©SlJJ »jÕ*vúôé¬D"aU*ûÃ?°&L`oß¾Í>~ü˜:u*»cÇV©Tûç¢Tƒ¨¨(¶oß¾ìöíÛÙŒŒ ößÿe‡ Æ~ûí·,˲lHHÛ¿öÏ?ÿd“““Ù•+W²³fÍb¥R)«R©Ø½{÷²'Ndÿûï?öÑ£Gì”)SØ]»v±J¥’‹ÅìÛo¿Í.[¶ŒŠŠb/]ºÄ¾öÚkìÅ‹Y†ajEþ_~ù…íÔ©»nÝ:ݶÐÐPvÀ€ìÏ?ÿ̦¤¤°}ô;~üxV"‘°†=rä;zôh688˜ ggÏžÍ~öÙg¬B¡`¥R)»jÕ*vÑ¢ElDD{íÚ5väÈ‘ìéÓ§YFc쟋R Ξ=˲§Nb³²²Ø}ûö± `¯^½ÊªÕjöСCì˜1cØ[·n±aaaìÌ™3Ù/¿üR·j¢Ô©TÊ~ùå—l»víØßÿeY–e†=qâ;lØ0öúõëldd$»`ÁvíÚµ¬\.ge2»iÓ&vîܹlhh(ÄŽ;–ýõ×_YµZÍŠD"vܸqìÆÙ””ö·ß~c‡ Â>yòÄØ?¥¨ÕjvË–-ìˆ#Ø6))‰ýâ‹/Ø1cưOŸ>ee2»aÃvÞ¼ylXX{óæMv̘1ìï¿ÿÎj4šéµANN»páBÖÇLJ}þü9˲,«P(ØÍ›7³3fÌ`>|ÈÞ¾}›0a{ðàAV¥R±EEEìÔ©SÙ5kÖ° ìÙ³gÙ²wîÜaY–eŸ>}Ê0€=rä›’’Â~òÉ'ì˜1cX±Xl쟫ÚÐÖPTT„ÐÐP,\¸]»v…··7Ö¬Yƒ˜˜¤¥¥!** ééé˜3gÚ´iƒáÇ£C‡ø÷ßÁÁÁpttÄo¼wwwL:B¡wïÞ\¾|½zõÂ!CЦMÌš5 ±±±ˆ‹‹«±ì2™ ?ýô“ÎS£%>>QQQ˜3gÚµk‡Áƒ£gÏž¸rå T*nß¾ +++LŸ>îîî˜4i¬­­¸zõ*:vìˆáÇÃÓÓ³gÏFFF"##ýsQªAbb" °lÙ2´iÓ:u¢E‹¥R‰X[[cÚ´ipwwÇ믿+++ܾ}påÊtîÜÆ ƒ——æÌ™ƒ´´4<þyyy¸}û6&OžŒnݺ¡{÷î˜0anܸ¡Ké© 999Ø·o_™9·÷îÝ—ËÅìÙ³áîîŽ &ÀÉÉ AAA€ëׯÃ××£F‚»»;æÌ™ƒ‚‚„‡‡C,#((£GF`` :uê„éÓ§ãÖ­[ÈÌÌ4öÏE©<@‹-0oÞ<¸¸¸`ðàÁ?~_WÅçóáèè¨'³………®!‰µµ5LMM‘••µZ¢¢¢22C,ûç¢TƒbäÈ‘ˆ·;44çÏŸ×m{q=ØØØÀÄÄÙÙÙ®‡¢¢"ˆÅbC­VëêYµÏk×Zua'Nœ—ËÅÈ‘#ˬñ¼¼<˜››ëj---aee…ŒŒ ]ƒœÒ2;;;C.—£¨¨¨Â{@vv64±.J5˜:u*ºt逪ÿüó¢¢¢ðÚk¯é޽¸d2Š‹‹k¬T‰D‚ü]ºtÑÉ^š‚‚=™¡R©PXX™L©TZæ¼ÔÞw Áçóuõ‹<NNN5–™b–,Y¢ë«Q\\ŒC‡ÁÖÖþþþÉdÉd宕JU# &$''ãÇÔEvK£P( ‘HÊÈœŸŸ…B‘H‡£Ë’äp8pqqѳ/^¼X[[7ê5N«Ëk©TŠàà`ìß¿|>[¶lÑy˃a˜J÷W™RÀ²ìKß_ÅÅÅøæ›oпôïß¿ÊÞcÊL1>yyyøçŸð믿¢sçÎxÿý÷õ:¡¾HMÖCénuˆ‹‹ÃîÝ»±jÕ*´iÓ¦Êi^/SÆ+“™a˜ZIñ¤ÔÔTüòË/¸zõ*&L˜€éÓ§Wúúš¬áš\†Á;wpíÚ5|ùå—zÆpUÞ[Ùs/{žÒ¸yòä Ž?Ž'Ož`éÒ¥èÕ«rrrÊ}mM×CMœgΜA^^Ö®][齦4/»·Ô¥Ìã£R©pëÖ-=z………Ø´i¼½½‘PîëkºjrMT«ÕØ»w/<==1zôè*gh½ìÞò2™ó§k `Y………ؽ{7BCC1yòd¼öÚkºôH§‹Li=3jµZ—ÚÂãñtŠ®öuF÷<ŸÏ×;!Ôj5ø|~º‘Þºu QQQðööÆþýû‘––8räzõê.—[®ÌÖÖÖàp8àñxP«Õ:™Y–…F£ÑuÔʬ}^£Ñ€Ëå–©±¢4X–ERR¶nÝ ‰D‚åË—£oß¾ºÈ|ykX­V—YZ´ëA…çr¹zP•JssóuPýã? P(†§OŸâþýû(,,Äþýû1bÄðxŸ???äåå¡°°P÷ÄÆÆêÉ\Ú›•œœ ‰D777cÿ\”j••…O?ý...ؽ{7F¥w‘Ö®‘H€¬‡¸¸¸ ×pRRär9ÜÜÜ`eewww½çÃÂÂàääT#§Œ››|||…ÈÈHdggC¡P 22ÅÅÅðññX,Ö¥ÖkkúJËœœœ¬»Qddd   033ƒ———^ã³ððpØÙÙÕÈ¡˜˜|ñÅèׯvî܉^½zé9üüü””¤[ééé‰DhÙ²%ÌÌÌàéé©·ÂÂÂ`oo[[[¸¹¹ÁÄÄDçÔ>ïååUíyx¾¾¾°±±Áóçω¢¢""::J¥íÛ·Gjjª®IRNN233áåå@€6mÚèwÏž=ƒ……àìì $%%éÉܲeK:ò£‘råÊìÛ·K–,ÁgŸ}ooo]ÔR(ÂÛÛ[o kG0ÙÛÛ×X'¨<:u‚Z­Ö­qµZŒŒ $&&‚aøúúê­á˜˜ðù|899ÁÁÁNNNzºHXXÜÜÜ`jjŠ6mÚ@"‘èz%¨T*½{¥qÁ0 öíÛ‡lݺU—¬5êš5k†fÍšéô] d=…ÂéÕ…Ïç£{÷îÈÏÏGdd¤®7MBB222`ccƒæÍ›—Ñ\\\`nnŽV­ZA­V#;;1ÚÃÃÃõdNKKÓõÈÉÉAFFF£^ãÔ`­YYY¸rå †¹\®»°FFFB,Ã××æææ¸yó&d2òòòpóæM¼öÚk€>}ú &&ÑÑÑP(ˆŠŠBll, èׯnÞ¼‰‚‚H¥RÁÒÒþþþÕ–900_|ñ…îOÛtiãÆ:t(¼¼¼àììŒ+W®@*•"??ׯ_Ç€`bb‚Þ½{#%%áááºOŸ>ÕÉÜ·o_ܺu yyyÉdøï¿ÿÀ0Œ^óJã€eY<~üqqq6l²²²të;22½{÷FRR’®!K||<"""ôÖCpp0òóó!“Ét݃»ví àÒ¥K(..†H$ÂÅ‹ѹsç9e¦L™¢·ÆGŒ'''|ñÅhÛ¶-ºw¼< Err2 ž°²²ª‘NP]Ú·oÏ>ûL·¾W¯^ X¶l&L˜€æÍ›ÃÏÏ/^„X,Faa!þý÷_tïÞèØ±#”J%îܹ¹\Žœœܾ}C‡ÕɆ¤¤$( „††"-- ƒ 2öÏUm¨»´$%%¡  ëׯ/óÜзo_L›6 ÿûßÿðäɤ§§ÃÉÉ Ã‡øûûë H___DDD`ذaº¡Á&LÀDZråJØÙÙ!""K–,Ñu®@¯D«€˜››C èZÞoÛ¶ Ïž=Cnn.x<ÆŽ ‡6mÚ`èСøê«¯àïïÈÈHÝh>|8nß¾•+WÂÅÅ¡¡¡˜3gŽ®'¥ñÀ²,¢££‘••…7ß|³Ìó>„ŒíÛ·£C‡ˆŒŒÄ€t]QGމÿþûï¿ÿ>œœœ†yóæéÖÃܹs±~ýz¬]»*• زeK™qK† mœ E €Ãá蚟µjÕ #GŽÄ®]»pãÆ DGG£{÷îèÚµ+Ò„çÆX³f Z¶l‰Çã7ÞÐeOÌœ9ëׯǚ5kÀår‡Í›7×(*L1R©111 ÅŒ3ôžkݺ5Ο?ÁƒãæÍ›X½z5Z´hÇcÊ”)ºqI³fÍÂúõëñᇠ5ÔÛ·o‡¥¥%,--1mÚ4ìÙ³Gg4:88`Ĉ5а¾h8òx<ðù|Ý ÄåË—±qãF´jÕ ¡¡¡z)rS§NÅÆ±zõj˜˜˜ ::7nÔeOÌ;›7oFdd$òòòÀ0 ÆG#¬üü|$''ãÖ­[øë¯¿ôž›-«¡¡R©”>a2™ V«qúôiøøø@©TÂÛÛ›M°t:Î;‡Ë—/#22ñññpvvf¯¹®®‡‚F£A÷îÝøÌ›&–ú.D«Õr–K¥Rðx<èõzœ={W®\ATTâââlâÁ:šÓ­[·Fñ`±XpëÖ-œ8q Ã@©TB.—¿p2ÏE«Õ¢¾¾¾ÑÚ ½^‹/ââÅ‹ Cbb"Äb1{ÍZ­ùùù¸wïºw  v]­ÅbÁ;wPPP¥RÙhúyu˜ÍfÔÔÔp×"ØÙëê꟟òòrÎx(++ÃñãÇÙxhß¾=ÃF£EEE8sæ d2;2ëÈ·îimpZ,Ô××£  %%%P( e;s, ***pìØ1FtéÒíÛ·g×w=þ ðöö†R©„C¯™ü;L&4 çf+b±˜=å ¼¼ÇŽƒÙlfãÁ9£TVVÂÕÕ•Mì­'&äççC§Ó±ù‘5†Íf3®_¿ŽÂÂB¸»»£K—.hÓ¦ {Mz½—.]Â… Ф¤$ö@^-ƒÁîé‹Å0›Í¸víN:(•J›xxÑœÀL&*++!‘HØßb± ¸¸'Ož„X,†R©DÛ¶mÙknhhÀ?ÿüƒsçÎ! J¥...ì5[gµÝ¾};wFXX˜M‡þ«„¬„B!„BZ$ „B!„Ò"Qƒ•<7ëÑ%48OZ+ŠqÒÚYA óUIkE÷qÒÚY«ybœ¬ä¹aîܹ¸wï^s_ !MâðáÃÈÊÊBMMMs_ !MB£Ñ`îܹ¸páBs_ !Mâòå˘7o{ô!­Í¡C‡••ÅžãÚšQƒ•<·ªª*œ}š,öªªª°}ûv´k׎=G™´nƒ„››ÊËËqâÄ …B¤§§C*•bÛ¶m¨¨¨€D"Áˆ#àçççz«ªª°{÷n( ìÝ»ÅÅÅpuuÅ Aƒ””ÔdÇ' œ2™ eee())ÁÕ«W9¬Z­†s='''H$›ÞNk?|ø«V­Bii)²²²ÐÜ_9ù—¹¸¸`Μ9ðññAïÞ½‘žžŽ¡C‡b„ àñxprrÂP^^™LÖègëëëñàÁÎØãóùH$œ=ú555èÑ£¦M›†a P( R©pëÖ-ÎkuuµÝM7d2ç½™ÏçÃh4bïÞ½X¾|9222žžN¯“É„ØØXLŸ>b±>>>˜?>Ö¬Yƒ=zÀd2áîÝ»8sæ Þyç›{rMMÝÍéž{eeeøôÓO1xð`ðù|„††bõêÕÐh4œ ÖŠŠ èõzÎzÄb1çÏ<ž«lܸ¿ÿþ;T*”J%å*¯‘ºº: 2Æ ƒÑhÄÇqøða,\¸‘‘‘¨¯¯Gjj*Μ9ÃÙ¬¬¬„N§ãüÝÎÎÎhÓ¦ g™Éd‚X,ÆôéÓ!•JQZZŠ’’¨Õj›zL&***`49—§§'ÜÝÝm^·Æquu5V­Z…»wïbÉ’%­2W¡§R’H$ ŸÏ‡‡‡är9 ›¸»»»Ã×××n€.^¼7nÜà,8p >úè#βÐÐP„……„B!‚ƒƒ¡V«9ß[VV† àþýû6e"‘ãÆCÏž=½nMf~ùåäææ¢oß¾èÔ©õX¾†üýýÙ©~~~pssCDDÛ™Ò¶m[xyyqv¼”——ã‹/¾àÜôE(â“O>AjjªMÇCbb"Û8ððð@»víìnë~öìY¬\¹’óãíí9sæ 44´Ñë à®®«V­Â®]»0kÖ¬&Ù"-[XX› [;;uêÄÞ 8;^Ο?+Vpnúâéé‰Y³f!""¦Ì:ºemÌÊåò§NÇܽ{7;Rö$???|óÍ7pvvnô:ŸÏ‡P(DAAŽ9¹\ŽPcõ5#ÿ‹q…B'''899!((¥¥¥œ÷Ø}ûöaË–-œ¿Û××K—.åìxôññiôwg÷>¾zõjœ={–³¬[·nÈÌÌäül°mÛ6äææ¢ÿþHLL¤\å5ãáለ6žáî¨(î·vsñuëÖ¡°°³¬sçΘ3ggŸÏGbb"»¼âi¹Jmm-æÏŸ»wïÚ”ñx<Œ9ééé6e ÃàáÇX¹r%òòò0wîÜV›«Ð“©;v,êëë9Ëž¶¾èÉû§% 2™ S¦LálPðù|øûûÛ¼n6›¡Óépüøq¤¥¥!//ÏnÏ!öH$L™2…sw;>ŸöíÛsþÇkãÖQ.{¢¢¢0{ölÎ…P(„¯¯¯Íëf³7oÞ„P(DZZ~úé'ôíÛ—ó½„Ø™3grÆž@ ༿Fþ__ÇçóŸ:"Ô³gOΆ/ðh€k½”ÅbÙlÆÁƒ1pà@äåå!77£GnB’““ÂY&‰l:J¬„Ba£˜þ%ÇÇ!C8ËìÍ63›ÍÐjµ8qâÒÓÓ‘——‡´´4(•ÊæþÚÈ+äý÷ßÇ€8Ëž¶|‚+W±wwuuŤI“ìÎ"°—{˜Ífܸq Ã`ðàÁغu+RSS!—Ë›ûks8j°¶` ÃØ=ÔÝQ½àÖ?({ÓÅì5†Aff&âããqóæMlذ111ðððh"x<†áÜ`ãi±÷¼œœœ ‰ì6¸ê·X,ð÷÷‡J¥‚³³3¦NŠü“'Ovئ ¤õ{‘Ø{Àn\þ¿Í=F…>øƒßÿ=lwŠ!Oz™Ø{B¡Ðn=OÛ<ÉÙÙ™™™ˆEqq16lØ€¨¨(Îé•„pyÑØ{^öþ^x<žÝœßb± *• Ã`êԩغu+&NœØêrj°¶`›6mÂíÛ·9ËRSS1lذ—®ãþýûX»v-4MÃ01bç\{‡àà`H¥RŒ?™™™Ø¶mFMSÊÈ3Ñh4X·n>½{÷Æ–-[Я_?»ÓÜyœT*…J¥²;‹@,;¤žøøx,^¼˜3Æy<Þ3%æ}úôÁöíÛ±~ýztîÜ™’yòLbcc±hÑ¢—нgñÖ[o¡Gœe|>ÿ™ž~~~>|8¾þúkôêÕ ½zõjÞ/¼úôéƒîÝ»s–ñù|‡ÝÇ?þøc»k Ÿu”+!!={öÄæÍ›Ñ¿ZâAžÉ˜1cìn€ê¨VWWWÌž=Ûn>dojý“RSS‘››‹ 6 ))©Uå*NóçÏŸßÜÑ™L&têÔ‰môéõzøúú"&&À£n½^¸¸8´k×ÎæwX×pý³÷Gb0àïïßh=“^¯‡L&Cdd¤Íûù|¾Ý:œ9{ M&„B!’’’àââ>Ÿ¨¨(FˆD¢V»à›4ÖÐЉD‚ÄÄDö5­V‹èèhv‡:“É>ŸÏÙÈãóùOq®‘zë¨Pddd£s/­#E\ë^œœžã\Óáàåå…¸¸80 ‘H„ððpèt:H$:£ò5`µ   v;àÑæ]»v…··7€ÿÆ'$$ØŒb¾Hì™Íf˜Íf$$$ÀÇLJ½£ÑˆèèhöµÇ »uXÏåæªÇh4¢cÇŽH$àóùˆŒŒ„Á`€ÙlfŸS¤õz<®¬kÞ¬£’ÉÉÉì=X¯×C.—#22Òæ¾ü"±g2™ ‰Ð©S'67›Í°X,HHHàL²†±[½®\%22F£ÎÎÎ lîÿÒĬq•””Ä®75 ðööFRRû>­V‹ˆˆÎüõEbÏz}SBBBlÎí¶.Ï{ž|x”«x{{#66–½ÎððpÔ××C*•¶ªå<‹½¡5B!„B!¤ÑAT„B!„BZ$j°B!„Bi‘¨ÁJ!„B!¤E¢+!„B!„‰¬„B!„BZ¤ÿ‰…„âÇ ê%tEXtdate:create2021-07-16T20:28:36+00:00Â7$Ÿ%tEXtdate:modify2021-07-16T20:28:36+00:00³jœ#"tEXtpdf:HiResBoundingBox1396x1123+0+0x{JXtEXtpdf:VersionPDF-1.7½8;í(tEXtxmp:CreateDate2021-07-16T15:25:07-05:00VÁìÊ6tEXtxmp:CreatorToolGL2PS 1.4.2, (C) 1999-2020 C. Geuzaine´‘u(tEXtxmp:ModifyDate2021-07-16T15:25:07-05:00â?ÐóIEND®B`‚blis-0.9.0/docs/graphs/large/l3_perf_nn1_nt1.pdf000066400000000000000000000427661422157504600213670ustar00rootroot00000000000000%PDF-1.7 %Çì¢ %%Invocation: path/gs -dQUIET -dNOPAUSE -dBATCH -dSAFER -dAutoRotatePages=/None -sDEVICE=pdfwrite -dLanguageLevel=2 -dEmbedAllFonts=true -dOptimize=true -dDEVICEWIDTHPOINTS=1396 -dDEVICEHEIGHTPOINTS=1123 -dNORANGEPAGESIZE -dFIXEDMEDIA -sOutputFile=? ? 5 0 obj <> stream xœÕ}M¯-9rÜþýŠ»ìg`Ž‹,~T-¼°[° @–nïZIV÷À0ì_ïLfFfÔ9§û~ôã£V÷É›Ìb±¬ ’Qü×—íV^6ýŸÿû~þR^ôúç/ÛËïJß^Ê~ùÿ¥ïÛËŸþéË~Ñ>K¹£¼ãÜo½¼üü¥ŽvÞÈòSø”­ŸC~ÿáÁ'KÁç±Lù__¤Æí<·úòø÷—_J/çmç¨a™¥ÞN­ËkØ,òÏü{ŽÛX>u¯òŸ“ë E‚ ‘èwDÒúg/ÿ!­ý¯_Êz/þ¯øùå/~üòïÿn¾ÔíåÇ?|±ç#u«çíÔûØ¥ª{}ùñç/¿ÿ¡|?lñÏïʱo·£þP/æ>þþÇ¿úòŸ~üò·OÕÜ‹ÜùNêõ飑Àµ_¼ë,㼕J±`áXé…Xì±Fk·Ù8–[.±Â+b‘Wv›R·ÛN±`áXé…Xìuí‚ɺäë]§å(ðxïîRn;ª´q¹ÒÆëãéý®”—6o}lçËÿOÞþ¸]ÿTþÔ§ýe,tz¡vßU~ÿR†VìïåŸüR_þê]8l²{T¿>ë„wHÞïãüJÃVmXmÔßiëì)ϵÍÝZö/¿ö[{k?üç¯bßÎmüð×_Ëvëmœ?üMüõ¿~•:öÙ~xýZøÚÈ®û+x·CÜf¹É¿WMþퟥíÿIþùù뾯ÿ·ÓS°ö?tä“gP^þ»_U»)]féý½L©­6äqÞÚÐÞ·~›ÒLG=nµœb©í¸jãvNíûÓ~~nâ[uÐÚ{3‹À©Íe‘ˆ]-‡4¢jrG?ÉíVydÇú},‡²M!(–¾¯ •í”Úè¥Ûh7z)»Ôfù´q+˲®Ò¤/®ŸµHUú "ÃݲH•–aÀEzÄX›C†ÃÛV–¥¯1·ìSê2Ôr¬š´íÔ^$¿Ïºn°4iuËí4cÞä¿{•Ьq|««!K—›è«NéFj›ÔdµViYšÔd¿X©‰ùx;My×ô¶"oÖN³K]N¾Ö<¥6æãqŽ½ßŽehv‹Ç”ê¬qFžÞj†³ì·54mîtv©Íà+ÉkòvX;XÛÕM^+}µÔ9×ïqØ›ÐKO½m“ê_K“šXK«j9¤*ÖVeµn­Uª²û™eÔÛvÐÕ]+µû-™EÐÑ¿ƒU»}Jm_½IŸÝN¾zëRnÏÚNm£lÎÚeØ»_Ü,³Þ 5g‚ücðµs¼qŸWAcÛòÿ ™å ¹Ê¸ qïõ‚Å&½«^°ØvÃkbQïk^°Øº5fbqXBc+›D# Eh,Ös7T8ït‰FiÑyA#p”h<‰ÆøL4º…ðè=“ð„&"Õ„I¯``ýŒ1yÜ!Ò”@$z+#ÒÇ)B¤_›y\ðXü„G›xô¨„G@xf]€×/ˆ”+;ހɾÙ=%&K„IÇaÒ{8aÒî’1éW'LÂLZK$"£6„H¿R"Ò«Gˆô°‰H¿KBäaq ‘fyMÒ²ïÒ«;§ë½Ê¯•’ø¡¸óÉRðy,ƒWò"#ú:þUBÒ¤¿ÝN¾BXˆFÀ†¤‰~yhצH°p$·E¤üý É.ÏôÐûx‹Hêô‹„äñ±í»àó¬—œòÙcš§ööB¬¤ˆÅT±Ò ±Ø+bÕˆXD5"VxE,òÊ.ªXL5²ãÁ ±ØëÚ9²âkæ(%$»ŒþÒ$ß/!yæ›ìá¯O;áõÏ»à}œÓ&ãn:vΚtàßþ÷G‰ÀÞdÜžMhEY½µ *×;b«öþß%‡°±½îÕ,½ Ûwj×`×eä^Ï5Pï]P¾F÷ý´¬~R|î­Ö5RïC®ÚWf±Yا´¼­Û #üé\Ã{+È”—û±Ò†fYÎ~èÄÉ*±­±}?$¹Ù—eØ+v?åíQ,ˆ½idªÖ·Û´ßG¹•3uÕ¶m Ë+ìµ,m¾Pžy…$#R™Id+»TyÅ\¡;ç¦M^º·Â¹¾$urÑ“²ëV境ó×¶Ë€¸s®ßvu8‘oMÞ‰'½æš²¥•GöâlG¿­7lñk÷*µY(/¥õRP‹½bÛÌd\|F“¤­Ò[WX–ÔfÆÛ]:ÔôñÅßî±0ÃUü¦4d[­Uìõ. ¤ÔÆÒ#o‰Czøi>«Ì)”õ|ü–ÇÞìŽü¦OÉž‹yØ•»våÓšÁ2Xyã6©¤}¤*ª"ÿÖÿ°{Ë ]ãl©’=ÏB×îU²çf>ë: uoË7¸)ðëš93 «ä–û{†¤äXW@¶ÍRôd+Žœäî@I@‡h²Z&Ÿ€lŽ·„d7V‘túNœÖ ’ž]$‡=zåp$(x(§ W Êv8p”êÓ/ L&(­-”‡w¬åá]:@q”1H”’PÙÅ”`¢ J'Œ J­Íq¥Ñë„d\9 ©CÆyIG?ÒÛ&A¹Ýƒ2* Œá)@ÃSÀ2n*€ EÀôú0Ã`n÷ÀÄm0Q?æfT’€‰¸ L¿s‚¦S@"ÒºEo™fOã>™àßûd)ø<–ù)‡ 4}§+„…RyظÐïHåçN|\îŠ[LcçïoL †àøÐûø-¤àñ± «ß¸ÁÖM=yLBžÛ¼x!V¦ûˆuYðX´–á±Ø+bEº±xý±r-±È+»Ò}ĺ¬?DÇ‹µ Å^×îÈ‘bÊýÒ9ʇW)„o¬å¢ï”¼ò-vð×§}ð úç=ð>·9Á—Û¬œàOœùÿ|}#2¬êÐ~Í-¬SÈûO’ïsêèùŠ ÛòŠ8ÏY×O}aë…·i#ý¨ò";uì/½¬·Ê¨m·÷C‘[^AêQm`¯»ölIFÊÖÕ³/ƒÎä/‡s³"’ذ¾KN¹ÆÓ¶OÖw¹â £ùD-ÎMV)ÍèÖëAÈÙzŒÞåNôZûÊeÔ"ïÙÕ­÷ÑÍgìÅ^º´a%+É:ŒãŒ)ɯ-ˆœ–ˆ)Ý®­Wåf "cÃçJ=‡¼ÜOK²,eÇØ}Îus‹Œ÷>çZ¼ÔÙŠÏ—nÆ•Æylž—©ÃÜd·9×z®ßÂÄlªt‡‡Ô²Ê÷fÙ»O¹z2' ÂîS®Ír·©kW}½oÛò¨òHmÂu·ªM}>6áÚ,[™{=|ñÂYÚ”ÔÒAÚòh›Ï.á·8nFü,EŸ:™½‚«!äÕiÉ{”:¥Ú*H·ô9ËŒ ÙÏnku¤àmó®é€T¼MC``²Ê»_0Y‡­Þ%&ëÑ·Àä¾Þ\ɽzL–“réyÅä€%0 ä&Ûfë‰IÛ˜Lj_™L‚Â$&1§˜l»='¤wX¤€ª]1Ù0Ù|PKLŠÏ¸bÒ»(0Ù;‰Éa™)¡Ò×) •ár> r< rXL¸t¶D¸œå—ž¾.§c*‘9-“'l:Ç"l"NbsM¨2k™a2¿ñD¦/$2¿ÍD&J%2Q*‘‰R‰L's„ÌÃo3‘y€«!8ÆX‹?´=HÞÔ:õ‘Ù|2¹¿÷ÉRðy,ó1BpêÃ.|…°P²úi¼ŒSG ®«[x”Û‰~cBp "½7·-ý2x|j‡.â•vÉéž>%¥Î/ÄÊL±8ÓG¬ôB,öŠX‘éG,Êô#VxE,òÊ„L±8ÓÏ~/Äb¯koäHÈJ¯ý—£|”:¨œåû%ïüc“Ýüõi'¼‚þºà]œ‚S†×õz—!>øÀÿüú;©·­þ°xÁú¯Ÿ¿ÊxyžÇZ9Xÿõ>® µ]ëßg9×mÍ}-~ŸSç‹t=æ\‹ßçZKTÃQlõ»ø¤ðqt_ý.ÓfjŽã´ÕïºY*#¿}õ»êN·e™¾ú]‡q…sÛ|õ[¢Ë²4_ýÞ‹eôçvøê÷.ï×µ¢T_ýÞwËK¤¾ú­S«ËG÷dØÊ†ÎÀ-KóÕï}zäzøê÷>Ýg/¾ú½;—¥ûê÷~úƨýÄŽ”Í&mOÝËa²žñœmÚú7¨Â©Öký»/Ô»­·jm,‰¢¯·j¹Õ9ª¯KN´~ëÎóðºL%æaÑ9ugÀz?VßN2%K´éX‹rè¾€étbÝã!Md“¨»½ ä5µÙ|‘fc+®Ü¶OÆúŽé‡O¢:åÄvÝnÒï7ÎÏÄâ[K’üûÈv³øÞäÚºße³8ÝÊTÉî&¥cš ît·ËÚ—âÙoYëI¶?MY¢íˆÁ•”ïYòå;U¤¦^›ama‰Å±+õêu§_©w¯Íĵ1 h*ØÞf IMzÏF¨ÔqÞf>Jåâc XÖÙÜXÖã´í€€%¨@Âro^(`¹ïŠ ËÃ!°lÛv%hm‚²XÊèŠÊè®J°Ý%’ü%ø%{¦”ÞÑ”ÝÃ$(½%(‡u<¥oG$Pú£%Xz¾N°œ ‚ål÷°ôÕ æÊÅ –‡ßAÂòð+%,ÛéF°ôu‚¥§ÞË´–¶2Ay`»g€ò@·PbƒdÂÛ¼–á°—nÈq"‘¥nË1>ÊJ)k¶à»eocüIs]0ýú¼Û]pþ´Ó]b|\IP7_~~‹üÛé€T~M§ „«-èFaMâOÝ•8Öè_4M•þ¹·i?‡.}Ÿ:×dÛéyö©‚ ³4MªOÝÄyºÏ¡« §Nu‹:êÂÊÔ Ãæ£ ŠG·Nï&!窋®]Û˜:÷U•s±‰yUæt6 cËÚ ržžÏˆ¡¯ºèJ¶Å8β:¸¼ç|oô¹ÛÜ|þQ,ã¼Ù–ßu]7ß°aÿt•¼ÀâàõV·Ã&V v×Rmá»Tì¡.ë•­¯XÛd]7«nëµ2µm¥û«¬ê¶¾Ež¿]i·åÄé»ÿ«m+Ë–ÓërîWÓ¬µZ£û8̲f]å• ßÅêR%ë:ÌÒ­.uÍ*/ËauÑew¬©ÇºO¿Ãáû4¿3¹Y]j^ÿÙš1Æ^àcûÕzw£ËoGõÚÃë2šËEÉœW© Ÿs·œx÷VPk–Ãîq—fµ(«M—¥{]²o§ýöëìò?‹r ŒR_˵·n^—³ùÞxC½Îè¾CQ$ž¥¯“¨\cFâØ×:QùAÛZ `Ôt±0uC:CQzrÛˆòû€zÀ€(½©„Cíµ“`h‰"ãPû_÷«­¿Õ k=Î@bmý‰ºäŠÄ:Ñw€Äzì¢í‡ûÆ(Äzc¢Pã ×üû…˜‹ ÷V/”qÒKƒ»ôò~Á .Ê Âà>šÇuWÒ¸`p—^}^0¨[Ç ap?\‰K îÇÄ9÷³z)àÖz^0¨óW ¶­\¨+¥!pív½ PgLÊ ‰À†Ùˆ5£D ¦P­z/bÔßíšîC„8´/m•$‡°¤$yžÛÚ?ÁBæÇréõ¬ÜS—(çUÒ"@ólÓm¸NzÍã\ %,Z¦‡%cÁ–±ÂB±¾­¸YÓ…qì¿MÜœ·¹n>À×§Ë$»ì±”UÃr‰^‹¼"ÖÙ—ÞŠb¹å+¼"yEGÒEЃ%ɰp¬ôB,öºï”+ºéëCg¦XäõQ‘sWÚ¾Õ+!¸ËùûxB-ù§þ6…xCáükCÀ³v{üë³Þø0<ï±>¬tºûBºÌ[Jç6ÿ|Jçãv/9tµ}÷šü£<‚ß*vž›Î¡$¯œ]gDYì<Ƕ¶§ÀrÊËÐú=–S·ÕVXΡ‰¦Mµ-åÇÚñõS,§¾1O›K2åœuÍXþ˹fj-½1¥-#)Ò"ó6ííjË9%±(– ,åÔ»þ²\Ë)÷d·¥XúÍ’XNÝÓ=֫Ж§Ùx%Åq¥XÚí`ѳX¦Í:@`¹–ëí\`)–i͉%Ev‰¥XÖ_~ ‰%]Ë%–TC—XÒµLd9—+‹,W`KvMdIq]dI×v‘e^ "K¶˜È2/‘eÆÈ’-&²ÌCd)–µ¯#E–Ù^Y²ÅD–bÙ òYÊZ÷”YN]˜K¬é2Ëì+.³¤‹»Ì’nÔd–S÷‹/> ™¥Ä=ŒQÄ×~§ðYj?Tv@ÈšlŸd†Èœ‚Õ­02•Hì‘9¥Yσ9u¨Â¬³!w”È 42Gq¬2ÃÇÌYmLd¦K ó°[Jd ó² ½1ék4ÌÓo)€©ò†~fZL•zð×Är\>F ¿Ñ,#JÀrž>þ,ã¾–qS€¥ŒŽ[¿À2\KÔ%Pe•î’ D]”› ô[JL"nbq’(ˆ”¾t– "Ñ0‰È¸t 2|‘i"q)rÚÔTâ1ÂqÓG” 8¢ÌÕs¦ÐCdÂæ÷^Y.½ž•ûœö9¯’–ä°e:âÐ1S¬°P,·Q,X¾9gþùMÎòýsÞ½œq>{\¦êe¯ˆl$b‰Xá±È+b‰XÄF"VxE,òŠŽl±˜D /Äb¯ûNI±(_¾ïÌëœ:è¼gxÖn€}Úïç½ñ1Ö'ÄÐM^•§0†ýÊ>¯‡žšl;É/çÒ–-I¤Ë/%köj†ürêþäi i“_J>ìC ä—É ¿L²ùe’È/“,¸üRò˜îMS_N%‰c•1õ¥é–ÙB}™üêËÌÝ ¾Ì<êËd P_f)¨/3M„ú2³¨/)Ž«/§®ÖtSVšú2¯õ¥XNk¨/%ήûáS}™9<Ô—ÉC\}™ 2Ô—™ö¹ú2³j¨/éÚ®¾L¦ýe è/3‰†þR, ©¿¤örý%UÇõ—T×_R»»þ2szè/éZ®¿¤R®¿Lè/³y\™)<ô—S'xO³¬mZ™C™|úKŠëú˹ö¯˜xÚ¡/£´¥ñï”FOÝÝ!›°9¤¬$.±–À¦$m† `s–æ °© '+l¦O`³•ÛšºÁådh¢›<`O ±‰^ØD?Jl¢¯%6AÍÀ]`,ƒ° %6Bü6¿M¤ú‰Mç&M\< 9wGš7 µ4£2ÍxBW h‚á$4#N@3|š9 ¥šQ* UhFã4=1OdF•™“ÈDu™adâJLÄMdFÜ@f dF©@&nü‰2šf']7‘Y|˜Ü{e¹ôzVîsúè¼JZ2Ù‡-sš°P²­3Õ8, 6š ‡å›h¤qx|€Pý^¦ªŸ<.Sþ²WÄ J±x±rI±È+b%ˆX¼ŒX¹$‚Xä)(b]–1ÐsIÄc±×}§¤XÆú”`ºÖ§¼ásšé1äå9w’hÎržÖ‘ ÑœºdΪiék&‡6yæ\ßYZB—gNÕ+&Ø4y¦d»¥†.МšÒ “H›@Sé~ÑLK^Pì½}¦ä²ÓÒè3ÅgÚ»úLɦtÐgÊÛz·—ô™S·¬ÌúÌd=ÐgŠÏôvp}&ù¸>SÞ?Óè3å­Õ½>®ÏLf}¦ø4{‘AŸ)>¶¹òL1TWUÛËš6¶Ï„»:S,¾'êÌ©»èWÂuæÔ=+k®êL±Øþ#ˆ3Åp¸Ú´™d0ifqefÞ2”™b9í1A™)…ª58”™Æ…™d0]¦D9n®Ã4]&[L™Iq]™É–¥Ìœºýü0µ)3sÎÊL± {²Pff e&ù¸2s®^`SfNÝ=ÜM!mÊLŠ´ãA¾S2=ËÚ¿MpÔ¯U­Ç®®…ñØ¥óm¬˜–ö9½c’Cû  ©sæå HŽÁ1˜ „uà HË™xFÈèÊÀã,ýJC <êÜ|­ŒÇXô<ƺHàQ—ð;ë¥ÙâxŒÕÆÄ£³¡€cºÁQà€HpÍ$hc2Øg2XV2&‘Aª’dqLa P¦ Œ‰€eZÊ UÊ kËXÌ Xù XFª°ÌÈ€e X†%`…–Èï–  Kåç–à ˨`Àtè‰`š¶¹d"³øp¾ï•åÒëY¹Ïɦó*iÉܶÌaÂB¹=$Ð\cXhƒ•Ûhƒ,ßœ'@:ýö¦¨·¥ÓyWs–÷ôi-A0{E¬ ‹@Ä ¯ˆE^+@Ä"±Â+b‘Wô£ ˆÅ ú_x!{Ý÷IŠE9ê}_¦XŸ  PŸ<á=#À³v{ÄûëÓÞx?üBo|ˆõ)µ&º€iŸCJ=4•ƒt›ò¦î–@·9ugn'ݦ¼a·—mÒ¶&mʠآͩ2¬Î¢My¡Mk!ˆ6“ @´™l²MI{{ñ@¶9õ¹T–mÊ[¦9l“vP¹l3SÈ63…l3²\¨6iˆ«63­„j3'p]µ™ÙT›¹¶âªMÚ4âªÍ\Kj3·bAµ™IT›™@Aµ)–jÍÕ&Y\µ9U=oÍîºÍXël“ ¹l“\Lµ)†ym²ai6£$›äašMò(¾Ùûk Ù¼X–d“ ™b“ &ØÌ s6ÉÅôšìbzÍlè5³ ×”grÞ ­î^1„åBê•9ÖÊ€\›Ï'²Íjï²K¦»š%1©½¯&ƒ}&‡NùÆäÌøÜ/˜Ô.Ñ/˜ t&jó‰É@W`70´80´80Û“Ò<~­¥2ƒýÊ€J€7@}>@[¹Jg‰IéVáÀ$V’“`‰I°‘Ä$ÖÇ“ ‰I¬Å$&àiIPbw_¢2v(,É⸌ý‘LDfll hÆÊ€flu hÆ´Àf^ àÌ8gZ€ÎŒtÆ.µ@g^è#It’£>OÔÔôV_ZŒÌ"àqá”Ige>§©¦k„…ò~·Q~ s×Gs,X8–Ù8–[¾½°ÂuÕopˆ÷éªé¶\1|!jɤ.>ˆ”䑘BX¤ôA$öA¤¤ˆÄÂ"¥"±ºPt¡ÖñÒÇ#]|î:#EâôöÒ…)Ò'¨ôÕß'uxòOÛìâ¯ÏûßìŸö¿»8ŸYëj÷{8ÃguÖ£­¯Î§¸sèò»oJ6qçÐLb¸Üs‰;¡‚ø)ijØTÏO¡îœºóu¸øzÉ;gÃÓ/×wJ¶;o»[–Âs®ïÀ¸e)<§~isiõÒxÎõ¡Tl›^õY‚:«©<}AÏ©Ÿ&í,ñœëKžv!“xNýüa¥Lâ9×GMxhÏ©/.­^ÏÙí!ý"Ϲ¾ìÏ"Ï©ªé)Tæ)/ù †É<Årúm»ÌS²¿Ã2È<å%³džS_€¡çìÒÀ¾;Ü„žòj.¸’ =/²Õ-ÀÖ.ô¼XºÕ%Žä2§¸tO‰—ÎS~¨¾é<Ų{í:O b2O6맯rAå)–êº]å9»mÛþ)tžb9ñˆTç)Yzëݾ*í4Õ8, ¶Œ•–Œõm5×û¦o÷öÛ4×y[Ðç|}ú¸LCÌ^kêù$¬“†å+¼"y!VÓBÌN±`áXé…Xì±tÒag4,—Xá±Èë¾Sf¬ì¦¯9c±×G5×Ã[ïûÇ?Â6ðø¦(õä+LÛÇO–þµaàYÛ=‚þõY|ž÷ÈÇXÖ]ï’Pyîºîûÿ[ݵ0­J³yt«É?üVÑuÓM {%ig;õº¾ôêÒξm|¼t×ÝÅuߎírºtßæfÉ”Ë:ÅãôìÒe}mvæmåÍÜ0al²Î.¯x!ëŸ6¢×‘4G'P Yg×}#žv,Yg—Pç€ Yg×XövY§XÇu®R纎Ë:—ÏÁºÎ^tÆs•r]§X½¸®³«Œ±±®s]ݰ5Yg×{Ñ[“‹é:éJ®ëËîŸÖr]g×]窟ë:éÎM×)ŸŠ†®s¹XJfºNŠâÂNiÐárag†²3Ã@ÙÙuãúa'Øš²3n ÊN¹O¯¡ì¤B.íÌF‡¶3ø´3ÛÒÎe,íÌ&†´sY&K;)Ži;×Ã\rl×vf›»¶sì¨\×vÒ…0èè]η©JâQ÷;±Ôº ƒ*áQ¬“ðØ4Ó>ᱩºÂÖMÕ³% ×ûóÑ È6޵%Ù4Õ¶¯µ9 ÉÇÙt‡ÜYȦ«‚ŒÇ¦É¹Ó‹…G1 cp,RÇb[ëŠ|Ú{3Ò”Plúù=ûª‚C—q6Ý©¸1—¥ïÄu³©.ŽDº#‘";qi‡aÓ]†É«)†Ãêb0dƒÁÁa˜ Ùb0Ì[ ÛÚ±Æ8Ìú‡«yäü:pH>D¶›Ò.û悱é²Ö¾W}._= RÄe°8©!‘îÊ‘ØÖVă¸,c\i T™-@\‘ù |˜nÜ{e¹ôzVîs2ë¼JZ’ZÀ–ÙSZ’Z@.M±ÂB±ÜF±Âò­i dÖoÒ”÷Ȭó¶ æóÙã2Ù0{E¬ ‹HÄ ¯ˆE^ˆ•±˜€ Vz!{E¬ ‹HÄ ¯ˆE^÷2cqz|ß™3Ögh dÖß/MyÏ0ð¬íAÿú´GÞÏ{äc¬OI­õÜ鮋SAþÛ'IM'¿«­›Î%ž¬èìúÕɧO÷mT?ýÖ]wyvú­ :…'x>A§Ð‚bëwt.Ÿ=-I¿}@Òõœ+Cu5¶é9-Xk®ç\D´×&çì:ÝUìdi“s®ä³±œ33BÈ9#%„š3óS¨9³ÔœKôw²ÒZ,S+‘jÎ^ºOjB͹Jm¬æ\TÂT¡®æ¤8.ç‹« çìzÀß 9'…q9gr—sŠAšÂŽš69纒i@]Î)–•a¤œ3ÇÕœëìxjsÒ¥]ÌIwàbNŠëbNº'sR…]ÌI5v1'ÕØÕœ+òâ¤Psfd¨93Ž«9³‚Psf]͹¢TÖY¯§Y—‹«9óùBÍ™õ ÜGàwꬅ*øVÄ@¥ÎåFeÓyú“@ÙtçÍq*›Îe/šT&Y*›¦¿«n@eÓ‰ù•ç–Mõ³&.—ËÆ¸l*žYtÝq¹²ÿÁ:ëÌaÌÌOÌLËÌ,d®R;ë¬3i23«2ƒX˜™°˜™j˜™°˜Ye“â80)Ž“ L lÀÌê9.é.—t!Çå²|(|†q`R}˜ÆIÍçÀ$‹“ªãÀ¤8L¶0©‚ÌLÕÌôq`&)0©³éOiL*äÀÌ&0)L$TˆóDfM“‘®¶ÈŒ>Lî½²\z=+÷9™u^%-™ìÖùLZ2Ù‡\šj–ŒM‡å[Ȭqx|€ _f¦Ÿ<.“ ³WÄ J±xå±r±È ±’ ÖeåÂcÑ*ˆÇb¯ˆ” bñÊbå*b‘×}§ÌX—9ú»Îœ±>µ¾a2ëï—7¼gxÖt˜}Ú!ïÇçò1Ö'¤ÖcMýœ7|NmÝô„êr¼³éSGº¼³é×Fl°tygÓƒbŠI7Mީミ~kêΦ;z;ŸQ-t¤ûÑצî”wK· Oy·L›½…À³ëv»¶ <}¡êΤ4wöMò¡jbN“wöMÞ5kç"ä}“¿˜àÓåbñ­5wŠÅ³0È;åµÖìÌZWwv=%|°º3ÉÔB¨lòêή|¦­6uçZšYs¸Pw²åØôç„rÓÔ]¸0í¯«;Åg·ýPwÊ…\{u§Ü€O(CÝ™‹@Pwv–<ÌbêÎÅ«é=MÝ)–ÝÔbéÐ{šº“,®î¤È®îìz|Ê" Pw®R«@ݹ®5ÌbêNŠãêÎeitP5Ý–«;—egÑu><¨;ÅR¬ç@ݹggu'[lË_×3*T->ÃÀ÷úÌ÷wì† \îÒfªnzö—ubàR—!)\öé{–—‰fS5ˮ۰£f˜ÃÏB \êñŸT-ij±æ.›ê,,®C³éWÚ¬6M]±dÐlªt:øôøeY¹' ™äÐ\–“¡)Yòæ²oÇæ"QþmÃfÓáëÐ$ƒAS Þ¯ͦ»ŸìΚ+ßãìø¦ýË4ÂÍt4›/L$4×Mgh’C³é'í& ¡éç·L5ìÐ̵@sù¬¡ÐËâh M²84“ôškͨñ÷Ulü=„$€æŠ³³ð:מšIAͤ©€f.jš«Tåï!$-4©”C“®åФRȨb¥ç‰ðšö¹º"sø0¸÷Êréõ¬Üç„×y•´d¶[f4iÉlj®1,´ËÊm´Ë*,ßš9@xýöΨ·…×yWsÎ÷ôi-!1{E¬ ‹(AÄ ¯ˆE^ˆ•”±˜ Vz!{E¬ ‹(AÄ ¯ˆE^÷}2cqÆzß—3Ögˆ„×ß/sxÏ(ð¬í1ÿú´GÞ¿Ð#b}J|ý°àðçP^7={±“㩬p½…¡ól3Ã]2Ϧ î»é>MæÙt;íf[/™gÓ³ðŽUÆežíÔŒí]“y¶S_á,½^U.ü´Y[¡ÂO“y {ðêAæÙ·ê;9 ó>በdžÂ'ª½V ó®Pl^2O±TWDºÌ3“fÈ<3Ù…Ìså¤Õ6…˜ÌsM¥Ù×øW²"‡µTž™ºÊs¬z.óÌ„2Ïdyæ¢džk)hÍB湸Ìz{Bæ¹XÇÊJ!óìkó¹YLæ™KJyf: ™§\}÷Ý0.óK÷Q.ó\Ûïå2ϵ?Í$ .óìE'hm;ŒÉ<ÅR\!à2O¶˜ÌS,{?—Ì3´ ò\.¶ñÆDžbh¾»ËEž« œKäÙuCG㓬/–E ÅrXÿ‡ÈsùøÁ¿&òì*4«îszuNKß)ÁnzF_ᳬ›žç}°»uÉûIØìzê›*Ÿ9è³M×#lç°©_zjüY„&Œå›ª9ù³M?‹`ß pl&é6›žÇºr[`³é¾‘ý$l6ý´CS Ãû£C39 ÙTQY-–®MhÒ.‡æZ‚©ôYÚÀåØLBáØlúu;ƒ¼c3°™”ØLJlæÖ0`3`“,ŽÍLüM²86ÙbØÌüØL °y±,l&6“d›¼yͰÙTeLÂ&—2l^, œ+N= ´åÍÑ™\è¼Xš×§^γ&ƒa“ Ý*sú´KdZay¢¿¦ûÒed" ¸ø Lz<+ó9ý5]#,”þ»Rœ°•p5Ç‚…c™cÁòÍE®¿~ƒJ¼OM·åºâ —x|TKW|ñA¤äˆÄLÂ"¥"±G"†à‘.›*;6?úzé>[_'Û-‹é>›J;w+eºÏL2 ûlú—tVëõ’™ø™Ú&ûlº/¢²ì³é'Ç>ìºé±z~®¶é>›ª»«<—î³ú GÖ`·£ûi±.ûl:KåÊn“}6É» œ0å§ yÓö@AùÙtyu-èR~6Ɇ ¶4åg&(?›&g.¹PågSJ¸±»é6tkÊO±œÐ3šò³’ÎT~6ýƒ5„+?…†5§ºò“-¦ülz¸¯§ÊϦi¢=KW~Š¥ù§Y\ù¹,®ë4ågÓm%®ÙTå§üÞ\«âÊO±4?6ׄŸ¹¼á§Xv-¯ÅÝól×}&‰„îS|šQ4è>Å2 Wݧü>ü›*®ûâÙŒ7A÷)–ÍWè>ÅR<_ZºOùíjc—}r“}.KŸ\ö©‹c¾=Þ°Œ÷*ìµY§ð±ó­–}hÜCßãhÔï1»ÈÙѨÛcæM «ŒÆ®Ã7AÈе‚c¬q»Ðhÿ¸ÃQµö“eØ2 ÿŽúÿÜÃqX¾KxúaÛÂx«0Áqa¸ Q•ñƒÏ¼¦Qh qH qèY}©Ã^T§1‡ä£ÞÉŒ±¼`ò6:ó{ò(6ï@ã;­Á8â{Çb°#Ç¢®Ðœ¬Ân¶“ƒ±¨iEåOP]¯åê8‹Ãè'1ÖpŒl1žvàŽF¶uEÈGG£ZhÉZ)Š£q½j%4&q34ÆRИDh\–ÑØtÅÞåÞ+ŠßϾV!Ø~’–SW=ãq!ï^Y.½ž•ûäÁ×q•°è—ºšm…„ ×ù™,&!ay5ÕŠ[ÆJKÆúÆ"lQy@¿íà븭8`:àëÓÇåL“bÞ,œ†…c¥b±WÄÒ¯ØW>¬–K¬ðŠXäIUg §aáXé…Xìuß))VtÓׇÎL±ÈëÃ_÷Û©mý¡/5IÍ~‰@Èñ-¾þ•!àY»=þõYo|ž÷ÆÇXo °FºþzHï#ýüµè:ž çÅ”ØÇñÃøú;·³dü£‰²û›Žÿòum)oÝZùNü½„Éõ*þ–B.þ.âo¹ÎßÄ_]ü=ö·ß.þ®’•Ýkò~«ø»œsê›(ŦUß7+S‡Ø´ê7ú×[zÓZ;>¶êzÓªÖ’ ô¦b™–Í»ÞTÚŽS|MoZwÉÝü‹¡¦7­ûŽé¸Þ´îÃwzAo*éǤs}Åá°+CpZwa>žU/Á©¸4|pÅ4§ÕE§bxI›èTj×}ÚÏE§rå«N«~P˲"WVý ÖåÄmñ9|Ï…§–@Ù±½&<ËæÔ…§§yŠë{7$μ±î”nÂu§Æ~šî”êbºSùû!ªéNÅÒ\•oºS„pÑiÝ|‹ÌE§y;VÕv5¸‰N=§U7¼¯ÜŠÓ¬§Uw˜øÚ§Y5(NóÁBq*>¶1‚ÓªÓ±~ð¶ NÉâ‚ÓlZN«îDê&A]“ÉRh÷S¿]pJ.&8¥(.8­*òjËÃ]ÜÔ;µßE7 Ghµ%À±œ«­EqðƋΣ_°XΣ_°(³{îîXK¹bQ,sφŢÖ?(gX,JF  Xy= Šb9ã#K ŠÊLÉPL‡"ùŠÊgYÿ5% £PÙìqA¡;‚Äß~ñwÀÏÿìåß}yEG_x|ÊŸ'ƒo“º ¿Œø…%à·m¾Œð‹¸@’‹0\€¿Œ ü嵿(ü¥Áá—e¿púÒ`àË |ááØË À^ÞO¤‰ˆòìLíÈLâÀÛÈ…àôæÞ+˥׳rŸí÷ƒÀóÞøë½tHçM»DùU:¤Ÿžz`9jüc|£ê Ç úc]Æhb,¿U‰Žì&5¯µnþ5"h^åæ§ÒAô*l¤â$p½ ©–­AôZuz7‰«‰^“@ôš4¢×$.zÍĢפ(.z•¬ºÚü[X\öëÙÂâÒmÇ™k^)Š‹^Åâù,D¯Iu z•ÚøšD¯IC z¥8®z%W½®Dær¶0]ËU¯b™×³…“ª@õJwîªWº–«^óN¡zÍ«»ê5Ã@õšýÍU¯ÅU¯ÙÈP½æÓƒê•}|tÚç‰CÃÞ%GOöh Wq®hJf{Þø‚gçg@fÑÕ¸E×Ì¢´eÕ ÈL*dŠÏaû;€Ì¢+gö…Cfr “\ ™בÄ"€iy?P™4)`iÀd^˜L:L&&ã²Iê€Ì¿ø»1ÿ,ú߈ùwÃ!Õ 8 z€Iy`ü& ˜A²8#•F\ 0â€áüeà/-À_^ø#Ç®ð‹B€_x}èCå|éðE`/¸JfuåÙ¹Þ9ùŠSw#s“{¯,—^ÏÊ}ò\ï¸JXˆpÀ–yUZ’pÄ)ÞYcX(l4Õ–oM^Bpþ[ÈËãŒó³y&þÉãòó³É ±’– Öe•ÆcÑŠÇb¯ˆ´$bñ* båŠb‘Wt¤ %ˆuY¥AÌÅ^÷’bñšÄ]g¦XŸYËñs½¿KîòžàY³=âýõig¼žwÆÇXïå.ºc ?e.³|OÌZøçÌåsZøÒÇ⩹-ºkªñÉã™ç@s[—@c)D]s[õÛWëuÍmÕN­,šÛª' SÔ.ÍmÕv&WuÑ­P¤ .&º­µùgé!º­:g{9~¼ê!#;?^«T¹±¾Êc°w&D·dqÑ­Z^Rq+A|ƒ·¹zÅm28(n«žo²ˆ$·TÊ5·k¢ÒNHvÍ­øøA¼ÐÜŠO÷›RÍíº}eÞ5·â°»ZÕ5·šÛº?6šÛª[(—|Õ%·äâ’[ ì’Û\$ƒäVJÙÆ>(nÅP­5¡¸K³.ÅmÝ÷‚ƒMq[uVÆŽpvÅ-ù¸âV|¦Ÿ²îŠÛ$ÉPÜ’)n«î]K%PÜJàáÒbWÜŠ¥áðcSÜêž"#PÜ®}•·Ô^®¸%WÜR{a\Ò]Á¥¾ÍZ˜óløÚ€) ¹œA^–l´0× ½|ïÀ,º}Ѻ‘³èæÄƒp™+3ŽË$?À% ŽË¢[7Æe.ç—TÊq™t¸” ß)p¹Ö,ýs\æ  ™œ Ð$‡&Åqh’C3i I>Mòqh&/ZÐL@3É É>Í :@& ™I~€Ìtq`²‹3]LãGÊà@%Å*ÉÇPI>@eú8*ɨôK;$³„C’J’^xÄO£ÿt$RqG"Y€Ä¼(ÅxÏÏ-_88Rø0¹÷Êréõ¬Ü'«„…ˆl™`¥%‰G1N5v onsmn Ë·&1¡}sCÚ;»ŠÃ½)}ú´ìpoòB¬d'ˆÅì±Ò ±Ø+b;‰XÄN"VxE,òŠ~챘Dÿ /Äb¯û>I±(¾ïËë&ÿ.IÌ{F€gíöˆ÷×§½ñ~ ø…Þøë½$æÔ3·×þÈ÷јqŽG3η¿qaþ•Åü9„ùE›ÛùHô¢Û3æòߢ¯ô•ƸüW^ÃR@È3gqùoUý÷äSÑ«jÍùæ*雟3âêߪMïêßZt™•ùRªù¦WÿV}ÏVæK©i9Ô¿U¢•å¿B¢ºåÇÿVmíˡ贆«ˆ]þK×rù¯DƱÍ.ÿMrãò_)tø—ÿ&õrù¯°ªÍ¿@àòßÌú!ÿœ®ìòߪ3ÆÖ.ÿ•ÀÍ¿[àòߪ)Nai¾øœnqù¯Ô¸ù}ºü7™ä¿Af þ­:ß9øXtqñäêßôú7© Կɤ þM®õoÝ-Íü)Ô¿ìcê_ñ9±éÉÔ¿yëPÿ&wú·.Ô°6_IšýlV04hƒBû[WpÿrKøpŒèºü¢"íʺü²Rºƒ)òüÉ€‰ef Ù€YNmc¦@¬ÌdH@¦ð¡ 84dC0Åà{ LA¡ïª0ËÚ¢R ˜´ã͹HÓÉŸÌ(º:ã§ž0ËRpLÚ'çÀ,KÂu0Ù²€™£€Yt9¡·f$“,̤g&Y˜¹:`²Å€™´ ÀL`&k0©”#“} ™¼!Ðy±,df) 37æ90Ù0½u`0XrXƒ%»,T²‹¡’\ ”ìb ¤m„ŽË‹eá’-L l¸¼¸œÇ%̳CÑ3ë°SŒ#ËÇ…ç\|P&=ž•ùä¡èy X˜—¸ò¯°ÇÁèË-—XfãX°|sÑ Dù¿ÎqÞy(zÞ g’óø¨ìröñHD^<Ò…â¬Häã‘.>ˆ”Ô‘˜àX¤ôA$öAJââ‘.ôÆ:^úx¤‹Ï]g¤Hœ~_º0Eúµ‰CÑ¿Kjó6䟶ÙÄ_Ÿ÷¿;Ø?íwqÞ-±Ñ¥êVÿ? 4øbÀÛœæ³_ X2d¸R£\ôˆøÊ圆F™¶¾»F9qr]yrËÒ(Wõ\NŠ®¥ã,1×(çZ4ʪÇY?M \UBíbh(³Åʵêa†VÊÊb‰˜@Y8H³D eñ™×3Û…„à¸`—(_,Íê3pȼK”Ùbe_ÿ1}r.A \5g,PަN®:¡nB•¥NóÀÑå¦N鮩““.AžÌQÚZtÊËš<9™äÉk/¼”ÀäÉÉrLžœ, òd¾²É“¹¾&ON^fòä\Ê‚<9É ON® y2ßÊ““4BžL¤ÂåÉÔR.O¦Ú-y²ün&\py2;˜<¹ê.¤‹<9WÕ|\ÒYÍã ­Vc ê¬É@œúéªÊ@<ê¤ ˆåζÄrÈs÷¾o@,Ú|…¿ÝQβè@L L ´i†Å¢S.…? ¼h,,Ý~ÔùcbÙýs ŽE±àÃŽÅäNÀbÑoºt~ó=\ú4Çbî¿WaïE†ÅTå÷äs• pL D&3D¦, ˆÌu, ’-†H±@±¶É¿ ‘¹ÒD^|« hœ!2)ÉCäŲ™¼ÎYôûƒÉ†È‹ÏBdrAC$—1D’‡#òbéV—Pg-D&}$Ùà É>É$”ž&Æï$`ÚU…`«Ø¬Éó^/à¿øZæ-ùÑÑñ¯_˘úÖUž}–—ÿúËÿî÷?üÍúãÿð]”¢ÜÔÿˆb——u¾ u³œ´Ê©GÍ® àÂiÖÌ,o-B@¦Z: ‹†øÛ/ÿT0Âendstream endobj 6 0 obj 15268 endobj 4 0 obj <> /Contents 5 0 R >> endobj 3 0 obj << /Type /Pages /Kids [ 4 0 R ] /Count 1 >> endobj 1 0 obj <> endobj 8 0 obj <> endobj 7 0 obj <> endobj 9 0 obj <>stream 2021-07-16T15:25:43-05:00 2021-07-16T15:25:43-05:00 GL2PS 1.4.2, (C) 1999-2020 C. Geuzaine gl2ps_renderer figureOctave endstream endobj 2 0 obj <>endobj xref 0 10 0000000000 65535 f 0000015819 00000 n 0000017334 00000 n 0000015760 00000 n 0000015626 00000 n 0000000267 00000 n 0000015605 00000 n 0000015912 00000 n 0000015883 00000 n 0000015976 00000 n trailer << /Size 10 /Root 1 0 R /Info 2 0 R /ID [<290A54DC8FBCF24A60AE69ADE9D7C3A6><290A54DC8FBCF24A60AE69ADE9D7C3A6>] >> startxref 17556 %%EOF blis-0.9.0/docs/graphs/large/l3_perf_nn1_nt1.png000066400000000000000000004542501422157504600213750ustar00rootroot00000000000000‰PNG  IHDR¬øð1íFgAMA± üa cHRMz&€„ú€èu0ê`:˜pœºQ<bKGDÿÿÿ ½§“ pHYsNNÆÊ/¥tIMEå-Ð㡚Ž.Ûq™±ž~û?€¦+ÂŽð7ÝÑg8}’9]þì¢ëõñß-ü¬Y‘,Yf*caNvͱ¸ª€IDATxÚìÝw@çûð';!!콑%  A”å¸GݵUëhkmÕZWÕªuŸÚª­»­¶uµZ÷QQ¦ì½Bö¸ñûãl¾TQЂ|?´Éår¾w\î}î½÷}^I’€ ‚ ‚ ﺡ € ‚ ‚ o ‚AAw ‚AÚ ÃV¬X‘‘‘aè‚ ‚´j(FiW‚8qâDYY™¡ ‚ Òª1 ]iWH’T*•"‘Çq333SSSj9µP§Ó™ššš››¡R©X,›Í¦¾¥P(Øl6N×h4,«ªªJ«ÕÚØØUTT( SSSÇ©***0 ³³³ãp8J¥ÒÒÒÒÄÄ„F£ú o‚:D"AB¡êN†™›››šš¡T*9‹Åý[¦Ñh8NYY™@ ¨¿YµZMŸÏ7ô."‚´.(nN—”””‘‘aoojnnN-ÏËËKHH°´´ìÖ­[mm­ —Ë%I²  àîÝ» #::ÚÎÎärymm-ŸÏ¿|ù2NïÕ«ŸÏ¿}ûvEEEDD„‡‡‡\.¯««c³Ù×®]c³Ù={öd³Ù±±±UUUÑÑÑîîî†>H“TWW/]ºôÁƒZ­6((håÊ•^^^r¹|Ñ¢E …Â××wÕªUnnn;vìèØ±ã¨Q£@«Õ~ñųfÍâóùppp8vì˜T*>|xçÎøá‡ªª*ÿ-[¶H¥ÒŸþÙÚÚúرcjµz̘1...û÷ﯮ®ø¿ÿû?{{{CäM}óÍ7III8ŽwëÖmùòå®®®"‘hÉ’%½zõ6lXhhèÇu:ÝÉ“'}||úõë׳gÏN:?ð¿þú+((hĈC‡ èѣǘ1cbbbºwïîè蘞žþÛo¿ 6lèСþþþ}ûö5jTLLL×®]‹‹‹ }&Y¼xq=’““?~}ú¤¥¥=xð cÇŽkÖ¬¹xñ¢Íœ9sJKKOž<Éd2‡šžžëééùÿ÷†>Èš5kVLLLZZZJJJ=–/_NIJeË¢¢¢’’’žü?þ())騱ãÕ«Wóòò†:gαXlèýCZDuuõ²eËîß¿oè‚ mCrròÂ… E"‘¡ ÒZ >Á«®®Þ¿ÿš5kþúë¯;w2™ÌÔÔT­V»yóæˆˆˆS§NýòË/ £ªª ð‚‚‚õë×O›6íôéÓ'OžŒˆˆØ´i“\.×ét£Gþ믿¾ÿþû[·nuìØñĉû÷ï·°°¸{÷®V«-++›2eÊ_ýµiÓ¦«W¯vïÞýäÉ“{öì †> H“dff:88xyyùûûoݺu„ t:=++ËÒÒÒÏÏÏÇÇgíÚµÓ¦Mãp8QQQÅÅÅ™™™pöìÙ®]»º¸¸€™™Ù”)Sœ ãÆóõõõóóëÚµ«T*kkë)S¦ØÛÛ6 ðI“&uìØ1 00Zi‹222\\\:tè°k×®#FP ííí}||üüü6oÞ=z´••ÔÔÔ|öÙgFFF+W®4333ôþ!-B*•ž:uª¨¨ÈÐAÚ†ÂÂÂ?þøC¡Pº ­êÑ8ƒÁãñnÞ¼ijjêêêzáƒQZZzÿþýµk× …Bccã÷ߟŠfžÜÈÈÈÎÎÎÉÉ Ã06›íéé¦_aĈ<ÏÉÉÉÞÞÃ0C¤IfΜ¹xñâÐÐа°°=zôë×Á`L™2eΜ9!!!ݺu‹ˆˆ8p ›ÍŽŒŒäñx·oßæóù±±±7när¹Àãñ¨.4*|¡Ñh‡ZbllLE9õW Óéú¶èÓO?]³fMhhh×®]ûôéÓ»wo˜9sæÂ… CBBêŸN}ûöÕét‰‰‰†=yòdÇŽTÏrkkkooo}§ð¥K—RW'tõh4ÍÑ£GÏŸ?_UUÕ¥K—/¿üÒÔÔôСCUUUÇŽspp šKììì¶nݺiÓ&SSÓ‹/ÚÙÙ:tH,Ož<ÙÏÏo×®]ÑÑÑ_~ù¥D"¹víš••ÕþýûU*ÕÔ©SœœöíÛWXXØ»wï è‡4 mQiiéÁƒ¯_¿Îd2‡ òᇖ••|ø099™F£ýüóÏFFFÓ§OÇqüرcÇŸ7o“Ù¶Ãȶ]ú·ÃÚÚzÛ¶m?þøãéÓ§mmm»uë¶lÙ²ââb.—KÕ=T€BÕ=ùùù*•jÚ´iÔwu:›ÍÖjµÀáp¨(‡òâ&W?ŽA#œÚ’${õêõÛo¿¥¦¦ÆÇÇoذáÊ•+ûöí =vìXzzz\\ÜîÝ»/]º´wï^KKË>}ú\ºtÉÊʪ®®®[·nMÿ‡Ð¹ÑÎ$9tèÐN:¥¤¤Ü½{wåʕ׮]Û»wo=Ž?þøñãøøøM›6]¹reïÞ½ wïÞçÏŸ§.,ÁÁÁÔF Fý i̘1cÇŽýàƒŽ=:wîܶ^W!—/_Þ²eË´iÓlllöíÛ·qãÆU«Vy{{óx<++«¬\¹ÒÇÇ'44ÔÒÒòéÓ§ëÖ­ëҥˤI“=z´hÑ"ÿ)S¦¨Tª5kÖ¸»»;99­Zµ*<<|ÆŒwîÜ™;wnPPÐäÉ“E"ÑÆýýýÇoèFÞܶmÛâââæÌ™SWW·qãF“þýû»»»s8___>Ÿ/‰öîÝû×_9::¤–+•Êììl''§””CïÒâ¤RéêÕ«»ví:nܸ±cÇÞ¼ysРAk×®ýñÇ]]]§OŸ>bĈ´´´ššKKËáÇb0µµµË—/8pàĉ'Nœxúôé÷ßãÆT3a„1cÆÄÅÅõïßëÖ­`Ô¨Q|ðAIIÉØ±cy<^ƒÛìׯ_ppð—_~¹zõê¾}ûz/‘ÿäúõëvvv³gÏ622 HKKc±XÝ»w766 uwwðàAË—/ïÑ£<}úÔÄÄdÁ‚‘‘‘cƌٴiÓ¸qã¦M›¦T*ïܹSXXèäädaaA=¹4hЖ-[¦L™2yò人ºØØØÂÂBCï1òŸœ;wnÒ¤IT—<.—kggdddeaa!‰ ""â믿f2™ë×¯ŠŠúðÃY,–»»»\.§¶ãììüõ×_»¹¹¹ºº;vlñâÅ]»v-))¹}ûvqq1 ‚Û¿ÌÌÌY³fýòË/C† 9uêTEE…³³³ƒƒÃ… :tè Ñh®]»¦V«áŸž /^ŒŠŠ"Iò§Ÿ~Š=xð ¡wyŒŒŒ¤Ré¶mÛ‚àñxÇŽ‹ˆˆ011Ñét»víb³Ù&&&ýõWHHõœÑÉÉÉËË+##cùòå†.;bH ªªjóæÍ†Á`ìß¿ŸJ #—Ë·oßN’¤‘‘Ño¿ýN…¼žžž………½zõzõ–‡ vöìÙmÛ¶íÞ½»~ê4¤Í‰ŒŒ}útÖ¬Yúû%oooê~  ÆÜ¹sõ[Ðße!m”F£ùã?Œ—.]*•JÓÓÓ8cÆ 4v iD"Ù¿¿~ý6oÞ,“ɾÿþûÝ»w7Sd2ÙáÇCBBÖ­['“ÉNœ8±téÒ%K–z?Z ‚G§Ómll&L˜P¡F£Y´hQLLÌŠ+d2Ùܹsœœ,--€ËåFGGGGG×__(ê(°X,ê5ƒÁ c€þrÆápô+0™LªEi+X,Ö‹-²L&“:=ôâããøá‡¼¼¼áÇ£n°ÙìúϦ)/žNׯ_ÿþûïE"Ñ AƒÐ™óŽ Ñh÷îÝ{øð¡µµµ©©irr²™™Õ7†š5P£ÑºŒH+Âd2=š™™9þ|‚ ÒÒÒ¨t:J¥Òétõ×g0gΜ‰¥ú§¦¦ÚÙÙ½ ——– ‚år¹H$ÒyAÔÖÖÖÖÖ kkë6ÝÀÎf³'Ož¼}ûöÓ§O+•J&“¹}ûööÑEÆ H’,,,´²²¢&w%¢¢¢B¥RQ3·éSåe8Ž»»ûìÙ³Ño¯E£Ñ”””¸¹¹Qg…N§+++#IÒÂÂB ¼ Wmççç·téRý¤Aí©b³Ù_~ùåÂ… çÌ™B¡pïÞ½Tg˜€€€M›6ñxm033ëÒ¥‹¾wDÏž=©»):îããCÍßD=^ Ñh={ö¤92 ___gggCïôÛ#‰´Z­¾ÿ4õ˜N­V››››˜˜´­S…"¾ûî»mÛ¶Mš4‰ÉdzxxìÞ½mll>ÿüóM›6™™™…††R½¤ŒŒŒ¾ýöÛÕ«WO:•Á`8::8p€ÅbÙÙÙuîÜ™êT#zöìI0l6;((¨tÀ£Q9 Z†aGŽ©?,,11ñÇ,((°´´œ2eJŸ>}ÚzÖžüüüüü|‡Cõ~*àRRR2kÖ¬Õ«WwéÒE§Ó]ºtéÈ‘#‰¤C‡3fÌÐ'Bëׯ¯_¿þ¯¿þâr¹ …â×_ýóÏ? ‚ð÷÷Ÿ;w.º£@(†>|øîÝ»?ýôµäÞ½{?þø#u³=eʔ޽{·¹ H­Vçääèt:ýƒG¨©©ÉËËóðð0777tÛ$¹\¾qãF@°páBÐét/^}ú¬_¿^,Ÿ8q¢G=2t‘VáÇìÔ©Ó²e˨·‰‰‰gΜ‹Å«W¯yòÄÚÚšª€¸\nçÎQ„ÔÔÔlÞ¼ùƒ>ðóóÓ/|ô葟ŸÕUÀÞÞÞÎÎU@íXó÷ˆ"âÚµk¹¹¹«V­º~ýº~y]]“ɤºT3 ‹ŠŠŠ¿ž˜˜XVVæèèØÊ;lá8N§Ó[?`’$qãƒI’¤H$R(ݺu«Ÿw½Y”––îÞ½{„ T²[Jmm-Ç£²Wòù|@Ðà©¢V«oݺ¥Ó鬭­[ù©‚aX+/!…$I‚ Þ8o(Žã•••4­GÍ›’–$ÉG?~öìÙõ—K$j$%XXXP»_üºT*½r劑‘‘µµu+ÿÁ¶•S… ø/† LLLúôéÓì»zõjAAÁªU«._¾¬_.‘HX,5v™Éd¾¬’H$.\°¶¶nýY)ÛÊ©‚aƒÁxãßN§+,,ôòòjö)q?zô¨P(ìÛ·ï… ôË© ˆ:·ŸÏ¯¬¬|ñëÅÅÅwïÞµ··oå‹üÇ«úÛôOi¹\^UUòZ µšÿ'ôôéÓ={öèsø¿u}Žã<`2™&&&­üþèÑ#}ÛvkV[[ûèÑ£ž={¾Ù×I’”Ëåééé666ÍcvðàA++«!C†4x2è5ø©\.OHHðññ‘J¥úÑ­ÓÅ‹û÷ïßú‡—••ý—i0q—ÉdéééÍK$’;wöë×/,,,11ñe«Q—û—WUU%''Êd²V_¸p!&&ÆÐ¥h5g¯>eõ‰DÉÉÉÍgeeíÛ·oéÒ¥V„ ž*J¥211±gÏž­¼öQ«ÕwïÞmt¾@ƒÃqmm F—.]Š‹‹«««€™]SSƒã¸¯¯oqq±V«åp8UUUÕÕÕoüµ5mb¾t6›mSºùƒàÑ£Gëçw=|øðéÓ§W®\Éb±¸\îþýûúöí[PP””´zõê·¿ÃHëááá±xñbêµV«=}úô|н{wkkëÍ›7çåå¹¹¹%&&VVV¶þ§~H‹êÞ½{hh(õúÁƒ·oß^²d ŸÏÏÊʺvíÚ Aƒ8Î¥K—¬­­ëpAÞAcÆŒÑ7ù8pàï¿ÿ¦* ‡sàÀ{÷îõîÝ;///99yÍš5†.,b0ÆÆÆ}ôùÏ< sçÎ533[°`›ÍŽŽŽÞ¶m[~~¾‹‹Ë½{÷ª««QÔŽ5\¿w&Õž çââ2|øð]»v]¿~=???""¢Ùû¹#m N§Î  ž€°X,‹¸lÙ2ggçÌÌÌqãÆµÚf§öD¡P€££ckkf0úÔ†Ãá°X¬Q£F=|øpÞ¼y //oñâÅ­¿{Ò¢^Q :tçÎW¯^ÍËË‹ŠŠ 0taƒ¡Ñhõgx¥Óé ƒ:Uºwï~íÚµ¯¿þÚÉÉ)##cܸqoÜ¡iýZ¶ïÿ|0aÂýÛ3fôèÑãÉ“'“'OîÔ©S+yðj$IÖÖÖ2kjÏì2«P€H„ÕÕÉL ’dfÒT*Ž:8hY, ‰D(“ÕW(4š+AðÙl.‡Ãôñ6jk!#401à`Ðj!1*+A§ƒ¾}ÁÒ Mn.®Õâ<žÚÚšFÜ’Zm-d™™ÂȈ¥ÑXTWóµZ&§‹ˆàr¹› wï‚PˆùúÖ™™‘Z-·ªŠP(¦ÆÜ\Ëb™Èd••PÆãðùl6ò„Þ¥KËO‹•””De¥áóù«W¯NLL,--ýâ‹/ZçÓ´WÓh4R©T*•\.W*•ÇÕÕµÁàR£ÑÔÕÕI¥R­V«Óé”J¥\.W©T2™¬¨¨ÈØØX©TJ M¸Ü ‚¨‰ÌÍÍ+++ëêê¨##ÌÍÍ© è, €F£çäðy¼‚‚ €‘P¨ÕjËÊÊ—ËÅq¼¤¤„ê$S]]-‰LLLh4A Tbtº¹µµ•••1ƒ¡®®æ3j¡PÇd*•ʪª*6›mllL£ÑH’,+.ÆE"› <ðùFQVf,†uíÚrǶK—.IIITu‡]»vݹsG­VwëÖ Ý,!õM™2åý÷ß׿ýøã{õê•––öÁøûû·é i^[¶lÑwEß~û-•¥jîܹ­¿7-ò_´ìU€jØûß?Ædúúúúúúz¯Ãàþ}(+ðòª‰$z>B§$)—Éžddäåç×ÙÔÕÙ¨Õ5:Ýy©T¬P «©éN§[xxp§L)05eˆÅ04š:SÓ›AA©ååÞOžø——ËÅâ_„ByÇŽæBaÐÝ»˜Z­xèçgîîn_Y˜žnZ[›èìœêíÍg0º%%1¥ÒZ­öQD„™›¯ªÊæþ}P«ÖÖ5ÑÑ ÑÀ;’§OñÒÒêž=1kk…"&;›£ÑdÚÚ&wíÊİÀ'OlKKµ4Z¬Ÿîé)T«=ž>5–ÉòE¢¾¾²³áÑ#MÛ©SŽ¥¥›ýžD“ɤ8~ÅÃ77 Ó;efª¸Üt›\cc‹e]Q1 S§–ûkÐh4}¿%Æb±""" }Š4‚z”F ¡(--­¨¨ÈÉÉ©¬¬ÌÏÏ///—H$žžž8ŽcfÆá** 0&†nc#—ËR©¨¦F«Ó•”ÔI¥v4š«Zm¥ÕÖØØTÙÛ›ššÚŸ:Å)+s0]¹’ãïobcc¶c‡ÌÞžxï=«¾}éL&ìÜ ¦¦r>_Ò©S•LVyö,üø#ƒF«îÒEûÁ¦ž¿ÿnÂát22R̘Á÷õ…òr8xPÈfó¼½aÜ8 øå¸x˜óç› È(.†Í›¡¤DÅfΟ_SSüpÿ䉀ËUÇÄhûôŠ 8y’£V›ÔÖÒæÎ[[Ú͛Ÿ~âá8  }¤R©ä›7?ÎÊâ¶ä@ƒQÿT 0ô¹ð .Œú¿,I5d^?”› €$F:h´ÿ]K©u¨õ©… Ƴ%úZ›Í®ßÚÇd2ýüüP‡™Æéÿ4õÈÔBêï«ÿku/A’€ã@’@§ƒñ¿·ÏþÜÿÔ§@£=ûJy9TU`a2\º … && ÷ï‹-†ÖöM5·õ(H½c·Âåå“*ôïPQ¹¹PT¦¦„@ HKãß»‡‹™Ì”ÐÐ[·nùܹã';ÙÙeûû«½½Ãìí}•Jàr¥ÞÞáááv®®†%&&9w®lÿ~:îfoïåêJñù¶<^tt´Ý¸qööö&&&Ý+šÿ¿ß*Šà‚‚ââb©T &&&ŽŽ •J…cÇêW366vrr¢naÃ>ü÷F½ð¯Œ©¬¤†Œ;;;¿XŒ1/Ù­[·m¡s}‹¨©ôtP«!(ˆ´´,)))**ªªª‹Ååååååå"‘ˆS[ëjmmãêê8 2Ò-'Lj ÀÉ ºvöî…ª*5v³¦&U"±g0Æ$&òårÜÆ¦hútÏnÝèIIpã0™Ð·/tî 0jètÀ`€“P©pÇŒû÷ÏV%DD€\55àé ¶¶ «VÁ?³©<—7ÃÃ@*°±˜< °·:\]a×.àøP_y®ðñ@£ÜÝ͆ñãaüxýç<¹x±øÏ?ñÖ±š¨¨œÁÂÔjHLµÌÍ¡sg`³¡ D"Àq°·v¾<j589A¯^ @J ìÞ  11€a°f dgƒ,^ ÖÖPZ ÇŽAu5tê“'ƒFû÷CFäçÊÆ-)±Fs¼5r9Èå`nl6èt• p8àí ,þcƘ±--§˜™A½\Óú`Éd†‡‡‡‡‡7ûžñùü–h´°±±±¡ ¤­V«T*³³³322úöíkkkËÐé@«>P_½*»x±V$Jòö¾Q[ˉz*•sKK×>²´´´¼}ÛæêU¦‘t냃Lùù ‘@q1S§‹Å¥Ñ ©˜Locc Ó!4þøõÌ‹XŒ Gÿ½ôï{¡^Ý–χzhØÚÂke8ápžEÒˆ‘$èt ÑA€@ h4PS……@£A÷î VÃéÓ@àè¡¡`deepõ*”—ƒƒPÝ‚‚°´„ {wP*áÖ-07{{èØØlHM…GH‚Àzô ­­ét:ÃÄ„æèˆóù8ŽƒV ¶¶ðÑG ƒAå²d0`êTÐé€É*Ÿ”‰ ôèLæ³3&O>Ÿ µ±©ýi†ßuðO+¬T Z-Èå`aÆÆ ׯCe%øûÃСÀfÃwßÁƒÀãÁòåàí r9ìÜ ÖÖàîÀbA]ÔÔA<«æ¸\ˆŒ  ‹g•©›°ÙÀç•*ÞÈ&Nôý»¼½Éï¾Óiµ‹…ÉåA3fü¯°55„…¬Xñì}UUqq±Çë||ÊÊÊ >žv÷.ƒÁ¨’J•J%H¥´mÛ˜Lfyy¹X,úǨ]i!m<^³æÙ³’¡CÁÂââ௿àý÷¡o_¥V›rýzõÉ“Œøøt;»4—°°°èÏ> …†ߺuíÚµòòr:nffæçç7{öl??¿V>çÒìt:]llì… Äb±±±±­­íüÙ³vîì_YYY]:|xjiiII‰‚$;„†úûûÏqwôô„ØXÈÏww RýÀœ9ÿÛ¨±ñó­°õžÉ0Ðêç£B ƒj¥“H@§ƒž=FƒòrHN†ÒRðóƒðpJáçŸáñc02zÖæš’G‚¥%ôî @§ƒ‹ <~Œ_¿^Êf—ÓéæÑÁÒ’nfúîõ (•J‘HD’dí£GÆÆÆÌ?¬«««®®®»|Y¡PˆD"B À0¬ìÏ?Õ¿ý&¨Äí‰Dvò$Õ÷Z­VÓét777>ŸÏår9N]]”–Êår…B:®&>žšÖ‘Ïçã8.‰*++Õ÷ÝЇ»µÒjA¥Ðh 5ÊʀǃÈH02‚âb¸ròò <üÙðºuP^îî0màê Ï¢ä%Kþµq33Ø»÷_K¢£!:úoy<ˆŠú× NNj+«ªª*P*¡¨H.—‹ÅâÚÚZ­V[WWGefÕétùùù@£Ñèçn455 …Ô6›]?¯¨¥¥¥><“ɬß@Ãårë?¨¤¸úO‚´Om*&IÉ@"¹<<€Í†÷Þ Ÿõ=1\\tgÏ–Ðéÿwá‚Mvö¬À@á¾}}}|ʕʫW¯®]»ÖÁÁÉd²Ùì°°°Ž;ÚÚÚòx¼Ö?‹Òœ0Œ¨®®¥ÓïÜ»wáÂÇÇŒíçädÅå²\\ rs‹œ›‘aß©§¼ÜßßìØ±VVV&&&ÿÛÂsMªòZ4P«z Cj*dd€ŸDGƒB.€Dò¬%•FƒÒRHM'' Ú\Œ`Ð UïÞKaÚ¢"ŸÏýâ :—+“É2Nž|úôi]]]ii©F£aåæ …B‘Häêê:pà@MEEÚ–-iii2™ŒN§cæææF›Í¦ÑhZ­ÖÆÆ†Á`8::š™™ÙÙÙÕŸ#@.—‹D¢¨¨(&“I `Åq¼ºº:;;;99Y¡PPÛ$ÂÖÖ–šÂØØØÑÑQ(A£Ñ?~Ìf³ûôéÃf³¥Ri êaPWJå³&sbcáÄ ¨¬„1c`ôhÐj!5ÊË!(èÙWh4 0ô)¥¿ü8žµÚ:9““F£‘Ëå„HôÜ?Èápx<AZ­V­VS/pW«ÕEEET`Êáp*++ãââ*++KJJ¤R)5šV¡P°X,www022222²··çñx€ZÔí¾9‰ÃáèSÑéô7KXËår©&aivm*V«aî\`0Àß\\€Íj¨VHõyJzzjVÖ­6ÿÇGŒ1ríZj–€ÀŒ3fÔ{@ƒ¼³”¥¥U&äÐh=='Ϝީüþ;œ< ÎÎðÕW®^^®ß}õßÿy‘B§O?{6½bðxðð!ܸ]º<{Ðlj _}õ¯¯„„è/qW¯^ÍÍÍ-//§tP¯jµZ£Ñ¸»»wîÜÙÉɉÏçÛÙÙQѪJ¥ºyóæ_ýÅãñ `kkÛ\YŸzÔï¢ó:Äbqqq±Áþ†¢ÓAFäåŸxzBY= ¹¹àç3g‚±1¸¸À€»û³‡EÆÆðÑGÿÚ‚£#LŸN½”H$"‘H§ÓfggWWW›™™™™™)•ÊŒŒ …BQ½&LMMŒŒ´Z­B¡àr¹:ŽÇã©Õj6›-“ÉÌÌÌT*•µµµL&“Éd‡ ˆàààÑ£G …BêÖÅÐAþA Vƒ‘ˆDðè`˜™A@°ÙÜÒRÅ?7]MÔ¦‚`V®cc áßÙmd2Ù‘#G×âñx111}úô¡Óé(/ØÛ†aPS2tèt:üþ;ܹ®®ÏZpììàÓO$Ë}–dÓÙþ=dY¡PˆÅâšššÂÂBª^+--MMMÍÍÍÕét†™˜˜xyyùùùuêÔI,WTT…ÂY³f™™™éO&“É`0‚P©T:¨öZ*•2—Ë¥b¦T*1 322âp8è)Ò‚4P©@¥##01 ƒÒRËA­__àñ 'îݱ:txÖógófˆss˜3‚ƒ¡ª ®_¼½ÁßXR)ýŸ>6MÔv.ˆ"XX@CÓÿVVV®_¿žÁ`¬[·ÎŽjMAúÒÓá—_´ç²³ÿ8rdô{ï5ê÷HB!ü3Å‚ü'J%lßVVðùçÀdB^ÈdЯtì`l¬<øáÇ©§N=~üX©T µZmjjJMí;oÞw½ ¢¤¤dÑ¢E={öœ:u*ºÊ#ÿRPªöóÛôèƒG6lÜèè舞 ÍF,†k×Ã`Â`åJ Ñ€Áx62:úY×^™LöÛo¿:uÊÓÓ3$$äË/¿´¶¶Ö7ÍÒét6›M™ú–HÛC’PY ••Щp8:›ýì)ÓKZâåryyy9Žãl6»¶¶öìÙ³EEEìÞ½»“““‘‘‹Å¢ºnã8N£ÑÐ 10d2¨­{{àóA&ƒ‹¡¬ LL`âD`±àï¿áÐ! Ñ`ölèÙètàpÀÁôSGFBh(ÐhÏ.•|>Lúìþú™xy=Ÿ%©¦îk A°V ;vÀÈ‘/Þ1gdd|ûí·#GŽ9r$Š€‘ÿÑjáÆ Ø¹>ú<?00P­Vûí·*•j÷îÝ...(ˆiŸ´Z8yއž=ÁߌŒþ7 í%ªªªÎœ9sýúuccc&“©P(H’ìÛ·ïܹsMMM_\ŸQ/Y'‚¼= €\aaÀbÁΔl6,Z¾¾@ Õ‚8;?K´×£„„€™Ù³Û?¡Æü{ç_ýõÑðÛÕ‚`±`ÈúËpONN^³fÍ‚ """P×%ä_ !öïµZ}ðàÁ”””Í›7›¡ÄdÈW\ 'N€—  ¶¶°s'˜˜ÔŸ[K§Óeggß¾}ûÆVVV:N$q8œàààÙ³gSƒÕö©®*+açNhh*" AEEE§OŸ~úô©H$¢ÑhQQQ›6mj‹óÃ#íVr2TUAu5DE‹ äåÁ¢EàèÝ»?KƵ`Á¿Ö71I“þµÄØøi¤[±¶ÛÚœ9õë‚ nݺµÿþ%K–„††¢yž‡,_NÍ}}ñâÅÔÔÔ5kÖ yst:Ðéš [¶€Ÿß³Ml¶¾õ‚$I©TzáÂ…›7oªÕê°°°+Vx{{Óh´’’™Læáá"àvH.‡û÷!7ÆŽ++˜;÷ÅU4MQQQuuµB¡xüøqlllTTÔ¬Y³¬¬¬,--ÑcLÄpt:`±€Á€º:8v **ÀÂfÌ.îß¹üYÚipu…_~1HKmKk A°R FFúw8Ž_ºtéðáëV­òññ1táVF«…„èÚ•jýàÁƒÃ‡oÚ´‰Jï ¯M­†{÷àúuxï=èÔ ìíaëV°°xn-’$ãââöíÛçïïÿÅ_t¤†ÁýÃÕÕÕл´ æÎ>øºÃ!âöíÛ'Ož¬¨¨èÚµ+Ç377ÿá‡l_k²Fi^qqpéh40u*tìJ%p¹Ð§øø<ËR2sæ¿Ö§ÓÛe m ®®†­[aõjýÔá‡úúë¯QŒ4 ¬ Žƒ  àrsrrvìØñõ×_wèÐÁÐÅBÚ¬ãÇ!%úôy6BÙÒR¥R¥'%¥§§[[[»ºº2™Ì´´´‚‚‚;wîÌœ93::M<ù¡ÓaÙ2°¶®ßRAH¥Ò;wî\¾|¹¶¶ö½÷Þ‹ŒŒ¬Ÿ³ AÞrr °t:èß8 Ñ 2\]Ÿ]Öìì`ÊC—Ò0Z}œ”B¡>Æ0l÷îÝ#GŽìD=‹DçÜ»T…ôûï¿wëÖ-䟉ä5( P€µ5Lš~HuÇ"I2--mÿþýµµµ!!!ÅÅÅ'Nœ Ñhîîî®®®{÷împ$ÒÄǃ­-xx@CÍü<øñÇMMM‡ …:< o›N……À烈ÅðÃàì ]º<ëÑaèò½9‚ *++U*õ¶¦¦¦ººº¶¶V(VUU¹4”H÷Z}œŸ]»R/I’¼sçŽã#FŒ@c«‘†YYŸ0R©ôñãÇ6l0t¶¦®._†óçaÂèß_NDFFÆÊ•+§N% i4šZ­4­À»%#~þŠŠà»ï^üð˗/9räã?Gá/ò–$H$`l L&üú+œ= <Ìšvv`e›6µÚ© p¯««S*•ÔkF#•J©ž>}Šã8Al6»ººZ¥RUVVR¹€ÅbÙÚÚzzz2Œššš§OŸ¾nG£V®ÏŒ¦Õj=:~üx4¸y©Þ½©ÿ=z´W¯^Î/£ +,„¤$˜=þý ¡¸¸xݺu_}õU·nÝô ¹Tÿ9ä]3p téò\ÐétçÎ;xðàš5k:wîlèR"ïŒë×áÞ=(+ƒ¯¾ggèÕ zô[ÛgÙʨ½­†T*-+++,,T«Õ………999R©Ã0’$mll‚ B[ª­“ËåZYYùùùY[[Óh4;;;ccckkë·œœœ\×Þ&˰·×¿¼r励±qD[nÆGZA@I ØØ‡“››{çÎýû÷ºLHÛ¡VCY¸¹Ÿ¬^ýÜ(šššeË– 4(,,ÌÐE G,:þ=êH’ÌÊÊ:{öljjª¹¹ùÚµkýýý ]V¤½“H@.{{ Ó!#üýáãŸe%3h:|‚ är¹R©¤þK…¼ÕÕÕb±X©T–——Ëd2777.—kgggmmÝ»wo;;;*6“ɤ¦ ¢&ô~ ¥mÝApZ`PïΜ93oÞ<Ô Œ4L©„Ý»á³ÏÀÉéòåËݺuC­tÈk¸y._†Í›Á€æ#Ðh4÷îÝ»yóæ½{÷zöì9zôhÔíáÝ¥ÓÁîÝг'DE=÷IqqñâÅ‹cbbV®\I•4tY‘vM£S§àüyèÑ&OfÏ6l‰rss‹ŠŠJJJÊËËÓÓÓE"‘““I’ÇÔÔÔÚÚÚÊÊÊÓÓÓÌÌÌÜÜÜÞÞ¾õr­û·zò$téBÁ………R©Ô×××ÐeBZ+•  ê¡Ïµk×¾ýö[¯ M‡Ú5õó‘×ÖÖ~ûí·J¥rĈsæÌ111ACÞiùùš ³f=·¸  à›o¾™?~TTºæ -ÃÀË© á›oÀÍ Þî)§ÑhÊËËËËË5 ”””$''q877·Î;5ÊÅÅ…F£Q?Ú? }øÖŠƒ`‚€¬,˜<™zW^^ngg×j#bxææÀã•””Ðh4” y ¦¦ðõ×PÉdß}÷‘‘ÑÊ•+MLL ]>¤HO‡Q£ÀÒR¿€$I™L¶bÅŠnݺEGGº|Hû…ã“ǃµ5|ò XYÁâÅoáŸ%IÃ0NWYY™’’òèÑ£¬¬,&“iiiiooobbB’ä Aƒ|||lmmÛè„Þ­8–É`Âps£Þ{zzºLH+fg«W@öýûAAAhP6òþýˆI¥RíØ±ƒËå.^¼Øè…ÁOÈ;jĈçýõ׃ 3fŒ¡ ‡´k99°aŒ={¾… ðâââÂÂÂüüüÇËår Ã|||‚ƒƒgÍšeccÓžž‰µH,—ËãââRRRÌÍÍ£¢¢<<<¨ìñ2™,>>þñãÇÎÎÎ}úô177UË®‰ ¢—™™‰†¤´?†åææ^¹rE­VtíÚ•º¹‹Å/^¬¬¬ìܹsXX˜qS¦ Ç0`2àéÓ§NTp¤Q«Õ)))qqq</88888˜ÃáQ\\|áÂÇCBBÞäæ§ª î݃¡CëÿC{÷î­ªªZ»v-Š€Û"™L÷èÑ# ª¢:éR³W¤¥¥¹ººöîÝûõ¦®¨©ssø§î'I²¦¦fõêÕááácÆŒA€Û¨ŠŠŠ;wîdee988 0ÀÊÊŠÁ`$)‰.^¼XUU& P8 ƒÜ\P( 8ÜÝaçN02j¡Î†)•J…B‘“““””tÿþ}6›meeåãã3bÄwwwKKËö:ƦùÃy…B±yóæ-[¶`–ýÙgŸÝºu‹$IX¿~ýÎ;u:ÝÙ³gW¬X!‹›¾ÙÂÂBC.¤™ÅÆÆNŸ>½  Ã°íÛ·¯Zµ Ã0±X¼`Á‚K—.i4š;vlß¾½IÛúýw¨­Å0,%%%((ÈÐ{†4' Ã~ùå—E‹I¥ÒŠŠŠ¥K—þòË/8Žgdd|ñÅOž<©¬¬\¾|ùÙ³g_o»:ìÝ úZ­öÀÙÙÙ+W®lÒ­ÒÊÈåòM›6mÛ¶ 𬬬úкuë¾ÿþ{NwæÌ™+VÔÖÖ6u£OŸÂ²e ÕêˆÅ⯿þ:::zÆŒ(n£D"Ñ_|ñ믿2™Ì„„„éÓ§çææRË,XpåÊF³mÛ¶;v p2:+WBY‹|~KDÀ‰ä¯¿þZ½zõÒ¥K¿ùæ› .8;;¯^½zÿþý7nœ6mZtt´££c{€¡%Z‚sssccc7oÞÜ©S'­VûÝwß={6<<<;;;11qéÒ¥ÑÑÑ¥¥¥S§N½}ûöÈ‘#›²M­V[[[k_/]Ò>œ>}ºW¯^‹-âñx]»vÝ´iSfffZZZeeåîÝ»oÞ¼¹jÕªqãÆyyy½jC œ= ÆI¥RÇ ½gHs’Ëåþùç'Ÿ|2jÔ(øí·ßΞ=Û¯_¿ãÇ[ZZ®_¿žÍf:tè÷ß·kzz ‘òóaútý‚3gÎdff®[·ÍýÖFåääÄÇÇoÚ´‰ª€Ö®]{îܹðððÌÌÌ,_¾<22²¸¸xÚ´iqqqÆ k|‹ lÙcÆÀ?qAÇwqq7nŠ€Û®¸¸8 Ã6lØàîî.‘HfÍšuíÚ5//¯Ë—/WWWÿðÃ×®][»víØ±cßvoL©H¶o+«æÝ0Žã555•••?~òäINNN@@@tt´‡‡‡P(411i£]{ßXóÿ€Ùlv=¨¦8ªuQQ†aiii¶¶¶ ÃÖÖ644411±‰Að“'Oìì쬚ûl@ ÎÍÍ-**ŠÏ瀕•N—H$)))!!! £S§N>l$ÎË.I^Žã¨fjgètzpppÏž=©Þ666*•J¡P¤¤¤Lš4‰zXÙ³gÏ?ÿü3??ÿ5‚`cc˜=[_ÍÈåò£G¢¸Mãp8={öÔW@eee8Ž?yòÄÞÞ¾sçÎ ÃÎÎ.$$$11±IA°LîîЧ~AVVV\\ܦM›8­iäu 2ÄÃÃŒ…B!õt:%%%44”é`ooŸœœüö‚à¸8 ˜1£y7¬T*cccoß¾]RRbffæêêÚ·oß¹sçR“P¼¥½k}š?VðòòZ¼x±N§+**ÊÎξ{÷îðáÃù|~nn®‘‘5ΚÅbyzzž;w®Á-¨Õê‚‚KKK}÷¾ôôôÏÞ„¼5ATTT”••µÄU`öìÙÔl‡þù§­­mPPжmÛúôéCõ#·´´´¶¶ÎÌÌlðër¹té¢/üÖ­[Çò0¾¹¹¹2™¬Ù7ëíí½páB}tïÞ½Q£Fñx¼œœ@@ÝÞ°ÙlË—/7¸…ªªªÊÊÊÿõ¾³±¹sõŸJ¥Ò-[¶LŸ>ÝÑÑÑЇð Ñhòòò¨„\Í«W¯^$Ij4šìììÌÌÌÊÊÊ?þ²³³cbb¨ ÈÊÊÊÂÂ"++ëůã8^\\ܱcG¡PØ<**‚íÛÁØX?7B³(((xøða\\\II‰§§gß¾};uêÄçó¹\n;‹}%IQQÑëvànþ ˜ší£¶¶öàÁƒ—.] … ƒ FÕ@4Á`PSE¿Ã0‰DBM MyðàÁ‡~øV'ò’$¥R©T*möȨûœøøø={öΚ5‹Ïçã8®O+H§ÓétºJ¥jðëZ­V,ÛÚÚ‚©)@AA uýBÞ2‚ $‰R©löS…F£±ÙlµZý×_;v¬¶¶vܸqÔÀ8}PËd2q×Öë¸YŸB¡H$ÿê'£ÓÁãÇL½ËËËKII™?þ»ö4ÐPD"‘Z­nöÍRX,Þ¿ÿ•+WLMM©Ö_ªÒ'.}YD’¤\.—Ëåÿ ‚i´úÓÞ¼yS tïÞÝÐÇï]a˜H$Â0¬Ù·L=0,--]·n]zzzpp°‹‹ 4±"I²®®N­V7[|å 89Á§Ÿ6×Ç¿ýö[RRRÇŽGåååõ²Ù†ÛµZ-‘H¨ËM×Ry.LMMW®\yõêÕ=z,_¾¼Á!/Ç-õŠTVVæåå¡Y( …Á`øøøøøø´\p0xðàÓ§OïØ±ãܹsÿý÷‹+¼ìT177 1âp ;”JxôèQ‡ÚÙ n[ÁápœœZ(‡Ã™1cÆ… /^üÝwß=~üø¹ètúËz¸ººRÁÐÿegÃúw?~üë^@‘7Öµk×–ëáfff¶jÕª+W®„‡‡/_¾¼®®îÅu¼ªÐh4ww÷ÿe/+ƒ©SõŸâ8~öìÙ?ü°õÌwÕîñùüÐÐЖûaÚÛÛ>|øâÅ‹fãÆ ®Ó`« “Éô÷÷oΰòÃá‹/þcL’dYYÙ™3g>ûì³+VØØØ8p`ÅŠ‘‘‘í;[[ÛÎ;¿ngÈæ¯«²²²bcci4‹Å2119rdVV–J¥277×étÔ­?†a•••MèV[[ÛrÕ*b@ …âêÕ«ÕÕÕ ƒÃáDGG[[[geeYZZ* êQ€L&“ÉdôòÔh`ÿ~¨©€ÚÚZWWWCïÒ̪ªª®^½ªR©˜L&ŸÏ5j5¶ÃÂÂB*•ê×a±XfffMÝhNüsªdddôêÕ Ý>µu™™™qqqTdjj:räÈÌÌLµZmnn®ÕjõPUUU“* êj¨:) ???tž´u†Ý»w/==zÊdkk;`À€GÀs\.oÁAù$ ÙÙ°{7“ ÿ!Ρ:.>|øóÏ?¿{÷îøñãwíÚ5eÊ@€žn½Âkq…B¡z%“ÉîÝ»_RRòÜj?^½zµB¡ Þ–••™™™1™Ì®]»VVV€Z­~ðàAóþVUUÙÙÙ¡ ¸ýÁ0lóæÍ·oߦžž×ÕÕi4ssóÈÈÈ””¹\%%%]»v}Õ†t:¨®@*•–––º»»zÏf&‰V¬X‘——G½­¨¨àñxB¡°{÷îqqqÔÂääd.—û3r8Ыà8þË/¿Œ? ½m=zôí·ß>W1Œnݺ•——€J¥jj$‘@½èÑ£GÁÁÁh"žv€ ˆ .üôÓOToc*‚¤®‘‘‘>¤zË·à¤ÇaÁøÏuÖƒ6mÚ4wî\©Tºk×® 6DFF6[?v­IíÆ*•êìÙ³W®\™2eJDD„L&[¼xqZZN777Ÿ3gNdd¤þVÃßߟÃá¬_¿¾wïÞr¹üðáÃC† 111 033;xðàûï¿§T*›8ÏdMM­­­¡ÒüLLLºtéràÀ‡cbbréÒ%­VÛ§OFsâĉß~û-,,ì矶²² xõ@º:pp“̤$GGG4ÁAûãàààîî¾mÛ¶ñãÇÀÉ“'ƒƒƒ}}} Å®]»Îž=knnþË/¿„„„8;;7u£}ûRí.UUU‘‘‘†ÞK¤têÔ‰Åbmذ¡W¯^r¹üСCÆ  …B¡ðàÁƒ'N¼}û¶F£‰ŠŠj|s¡¡úÙ1 {øða= ½‹H3`³Ùááá7nܳgO—.]Š‹‹/]º4gÎˆŠŠ:}úôo¿ýzäÈ›Î;·T9ž<©S¡oß7û6I’¥¥¥GMII‰‰‰Ù¶m›µµ5j÷}-M ‚;¶gÏžþýû[ZZÀ‰'þøãFº9;÷ß@yy¹ŸŸŸ¡÷ i~B¡pݺuGŽ9tètîÜù£>277ïÛ·¯F£9yò¤V« ûðÃ_£CØ?kfee™ššR‰k¶Î××wݺu‡¢* ¡C‡Ž3†j»ýöÛo© ÈÉÉiÕªUMê7edÿÜT«Õêââbô ©Ýèß¿¿N§»páB\\œ¥¥å¢E‹zõê+V¬8tèÐ¥K—gϞ݂#­'N|㯪Tª?ÿü“š‡áàÁƒ¨õçÍ4^a”””œ;wnÊ”)Ó¦Mãr¹b±8666""âý÷ß722òòòš9sæ£Gêç‹ñ÷÷_³fB¡`2™B¡P_âîîþõ×_Ëd2##£¦§±àp8¯ÑÏiSLMM§OŸ>vìX ÃLLL¨›%:êíí­V«õ ›"##Á핳³óW_}%“Éh4šP(¤ª%ƒ1dÈÈÈH‚ LMM_#¾}rs©1O7nÜЧäCÚN:é+ }Wº:|ýõ×r¹œÏç7u URxz‚PEEEL&M\ÚžÄÄÄDGG«T*.—«ï<@§Ó»víêããóºÐkP©àôi9^„%ŽãÕÕÕ±±±Tö­•+Wvèеþ¾±ÆëŒÊÊJN׫W/jÞ¼êêê‚‚‚Ï?ÿœºí011177ÏÊÊrMOO¯®®n☶fZ‚‘¦Ðjµ555(”A𤬠>ø€$É«W¯†„„¼I´{*0™À`€V«MHHXºt©¡Ë„´}µµðà,_¯óô Çñ”””£GÒéô¥K—vèÐ=¼jÁ,«¸¸˜êAuçÎ777ªs0ètºªªªÍ?'‹Qj¤Q$IZYY¡¹â&ùüs°·W)•wîÜ™ÑÜÓ“"íƒýûSy[óóó ‚xÜ#ò2¬X¯“ʳ®®nÿþý<6lØèÑ£QøÛŒ‚;tèàíí½mÛ6‰DRSSsëÖ­÷ߟÁ`P3”9r„$É&æyx3†½î¼²F&“Q Ϙ1Ýn½M­=bH$(¬Aš‚F£µè¤-Hû EUUꄼÊòåPUéééžžž†. Ò6aŒ AA¯XE.—oܸÑÒÒrÖ¬Y(~ËšÔLDUUU^^ÈårF#‘H¨·GGÇ$“ÉPdƒ4EEEº| MbbAeNê ¼”Z *X[ëtº¼¼<4Sò†,,`ÈW|®V«>¬Ñh.\ˆL½}M ‚ÕjõîÝ»©Þ–$IVVVæææÞ½{W¿ÂîÝ»ÝÜÜZ¢|r¹¼S§N†>JH —ËÑÔ_H“ŒööÕW®8::º(Hk%“APp8’êj’$Q*=äM”—IÂ+‡¸Ý¼y311qýúõhR0ƒh<ï¿ÿ~mmí+Ö …-T¾²²2”ùi •JedddèR mA§NZ­6777,,ÌÐEAZ+++X²ªªªZ®‚CÚ3vî„Þ½_çååíܹsÛ¶mè.ËPš;–zã¸N§ÃqœN§3Œ–ÎÉJ’$Aè‘%ÒÕÕÕ¨û8Ò8‡§OqÇQÓ òRÔX~&S*•ZYYº4H”“%%ñ²Ï1 ;|øpLLL =HG𢩬8Ž?zôèÖ­[©©©"‘ÈØØØÙÙ¹G-W‘Èd²’’4©)ÒL&ÓÕÕÕÐ¥@Z½Œ رß¶ Ã0Ô‰y©ë× `àÀ²²2”!y:Lž /éæKÄï¿ÿ^[[ûõ×_³X,C—õÝÕÔ>Á¿þúëñãÇ5MçÎ=<øÀÆÆ†ŠwÕjõÙ³g÷îÝ»yóæ¯¿þZ 4{á”J¥\.G)£‘¦ IÒÖÖÖÐ¥@Z=üü*++ŒŒP_Oä¥D" €¢¢¢C—ik Ðjá%Ïêêê6mÚ4tèÐŽ;º ïºÆ[ÎêêêŽ9Ò¿ÿO>ùÄÖÖV’r¹ÜQ£F-Z´èúõëEEE-Q8Çù|>š1iTMMZ­FùeÆ……Á!éééÞÞÞèÑòR}Dåv­««Ci:‘×ö×_pãÆË>üí·ßètúˆ#Pxcp×%%%R©´ÿþ/öýe0¡¡¡¶¶¶÷îÝk‰ÂiµZ‚ PK0Ò(•J…&>@š„ͧ¨¨ ÇF^ÅÅ…êÍYZZªŸ0AšD«… ^Ö"==ýÂ… óæÍC][ƒÆ»CˆÅb Ã^–P“Á`?—@M,ÿõ×_>Äq<::zÀ€¦¦¦PVVvöìÙÔÔT—Q£F¹»»¿º%F§ÓÑh4ÔZÓŽiµÚ¤¤¤óçÏ—––úúúÆÄÄøùù‘››ûûï¿WTT4¨ÑxE&“¡‘þí›B¡¸~ýú­[·¤Ri``à¨Q£lmmu:]rròÉ“'q ‹‰‰i¼_Ö?ˆ¥¥¥(?Z{%‰Îž=›””DD= @E±¥¥¥gÏž}üø±««ë¨Q£ÜÜÜ­\Ôjµ‰‰‰………¡÷ i999—.]JII …C† éÞ½;—ËÅqœª€*++ƒ‚‚ ôÚíD"°µ…úD´aÆ¥K—¢¬ö­Dãñ%ŸÏ§Óé/ËL„J¥ª_ñ¨Tªï¿ÿþÈ‘#¾¾¾~~~{÷îÝ¿¿F£€µk×^½z5""¢¤¤dõêÕÕÕÕ¯þ§ ‚°±±AãÚ±û÷ïùå—0pàÀ”””eË–UWW/Y²¤²²²{÷î/^ܲeK£Û‘H$Azo–‚ãø©S§6lØ`kk~þüù7ŠÅâG­\¹R xyy8pàĉlH£K—@ (**B¹Û%•Jµ{÷î£GúûûûúúþðÃÐjµðí·ß^¿~=""¢°°põêÕ555n­¤¤„ ÔÓ.ÕÕÕ-[¶ìúõë½{÷¶°°X¶lÙÅ‹€ª€jjjºwï~þüù­[·¾ö¦mlà믡¡‡Ø—/_¶²²êÒ¥ zÄÝJ4_zzzš˜˜œ>}ÚÏÏïÅ>—=ÊÍÍ Õ/ÉÍͽyóæºu먆ÿùóçOœ81///''gÓ¦M:u|xöìY__߯¿þšF£YZZ9r¤gÏž¯Ê”'“A¨p·å4NHõôéÓØØØï¾ûŽª•|}}¿úê«I“&eeeåççoÞ¼Ùßß?&&fâĉW®\™4iÒ«·¦Ñh:4Ôž‡´±±±jµzË–-îîîAïß¿ĈgΜ¡Óéß|󉉉··÷—_~™’’ø›¦Ó¡¡.4•••þùç·ß~‹¢šÖ£ñ\ccãáÇ_½zõøñãr¹Ã0Ç1 Óh4‰‰‰Û·oïÙ³gýˆaNNNÁÁÁ4F£ÙÙÙ)•J‚ ž>}jkkëêêJ£Ñx<^pppjjê«ÿi‚ ìííQKp;Æd2ûôéÃd2i4š‰‰ —ËU*•™™™;w4ÍÑÑÑÉÉéñãǯÞN]]N§3ôÞ -…$I“ÈÈHêªbkk‹a˜Z­ÎÊÊ §Óé4-00P£Ñ¿jCB!¬Z%‘H ª‡Ú% ÜŸ«€²³³íìì\\\h4š‘‘QPPP£”––¢Ž›í•F£ ¦N :nmm-—Ë 33300ÏçÓh4ggg‡'Ož¼ÆvIvcvàÀ¨¨¨: ‹OëѤørĈ‰dß¾}'Nœ âñx8Ž&%%…††.X° ~¦¡ÀÀÀƒR¯ ÅŸþéççÇçó x<µ&›Íöðð8yòdƒÿœN§‹Å666¹¹¹l6.†E’¤T*­««k‰,x›6mÒÿ+ñññ&Løþûï @eO´´´´²²ÊÎÎnð릦¦ÆÔÔÃ04éŽÁá8.‹ I’Í»e33³C‡Q¯µZíùóç---óóóõ ºîîîZ­¶¼¼¼Á-ÈåòÚÚZSSSZ§Nº¢"///C­w]MM ÕM®yïß¿ŸzMU@:u222*((àóùTÄáp:tèpöìÙ· “Éôc T*êlX†ÕÔÔ`Ô~ÍjôèÑ£G¦^‹D¢Ë—/S¯sss}}}©›+++ ‹§OŸ¾øu‚ jkkÕj5—Ëý×¹¹˜}ôÜúiiiOž<Ù³gê]ÓB”JemmíëFŒM ‚9Î|ЩS§Ë—/'&&*•Jƒáææ¶|ùò=z48*_§ÓíÙ³';;{áÂ… æã¤úi½H&“%%%¹ºº2 ”›ÆàpÏÈÈÈÈÈh¹þ"‘èêÕ«‡ŠŠŠŠŽŽþþûïŸ[áe­¼"‘èþýû‘‘‘UUU¨ÁÆà¨aŽEEEÍSp¯®®>räÈ•+W>ùä“§0 âe•e^^Þ£G"»vebÕlè£õ®KHH¨ªªj¡ëtº‚‚‚½{÷æää,\¸°Áø+ ’$srròòò@©T¢U K¡P$$$µÐöÕjõÇ<ˆaØôéÓ\§Á ðGùûû?Ÿ6 %ÂÃáß‘1A§OŸŽ‰‰A§SË©¨¨HNNîüÊ9J^ÔÔž</<<<<<ü¹å*•êܹsÑÑÑõÃ\FóÓO?ýý÷ßaaa›6mzY£Ë˲ºš››wïÞ] TUU988ê€"&“Ù­[7FÓýR‚xôèѦM›H’œ?~TTÔówÕÐàB°··‰‰FccccèCõ®ãñxýúõS*•-ÑÔaØùóçúé'ww÷5kÖ„††¾ï2Œ—M¿Ô¹sçž={Â;÷í‹î® nÈ!/k‹ýÔjõO?ýtþüùnݺmÞ¼ÙÃãÁÕ¬€h4ZPP€H$BÃ2112dHRRRKl¼¢¢bß¾} œ4iÒËZý¬€ØlvÏž=Hœ /Ô•iiiOŸ>;w.jn9îîî½{÷®««{­oý×°F*•.[¶ì?þÐÁJ¥òûï¿OIIYºti—.]ô‡‚‚¹\.t:]aa¡‹‹Ë«7®P(PÞ«ö-!!aÆ Æ 2dˆ¾²qvv‹Å:ŽÅbÕÖÖŠD"ÿWlÇñšššú£3‘vð?þøãäɓӧOïÙ³'uµ¡ºŒë[‹ŠŠX,V#¯e2P« Žã†Þ'¤E(ŠÝ»w?~üxÙ²eÁÁÁúðÅÑѱ´´”ª€´ZmQQQ£H¥R}@Œ´3µµµ+W®d±X;wîtvvÖ?K¤* ØL¦X,®­­}õ°ìç½p^i4šŸþyÔ¨QT®X¤Uù¯7%$IªTªúÙ©²²²Îž=»téÒÈÈÈú·Ú]ºt©¬¬,((µZýàÁƒnݺ½zãh°vïСCÁÁÁS¦L©ßÜöèÑ#êuIIIQQÑ«Sº¡P(ÐÊvL&“>|xâĉÆ ÓßoÓéôÐÐÐ;wîPoSRR¸\îËšýža± 8X£Ñ˜››zŸ‘™™yþüù¥K—†‡‡×oÀ )//§&7U©TIIIV@P^^ŽúYµWW¯^­©©Yºti‡êÿ•ÃÂÂ’““•J%—””tíÚµ©­«ƒ¬,øw¾Î¼¼¼âââž={z‘4Ü™™YYY9sæÌúÝ“ÿý÷Î;{{{oÙ²eäÈ‘wïÞ …ÑÑѯÞTmmíËn"í€X,ÎÈÈHJJºzõª~áøñãGõ÷ßoÞ¼9$$äôéÓ¾¾¾¯ØI’ å:!WRRRPP°qãÆmÛ¶é®^½zôèÑk×®ý¿ÿû?ssó“'OÆÄÄ4Ò*2”—/·Ä(O¤5ÈÈȨ¨¨˜1cFý èäÉ“žžž›7o1bÄ;wLMM£¢¢^½)ª‹9J‘Ö.i4š”””¬¬¬±cÇêO++«S§NõéÓçÂ… ›7o>uêT```ÇŽ›ºÝädˆ‡E‹ô ‚8sæÌðáÃÍÌÌ ½ÓHš?øöÛoŸ[( ™LæâÅ‹ÿøã¿þúËÃÃcåÊ•NF§Ó­¬¬ }ˆ–Âb±¾úê«çFˆ{yyÙÚÚ~óÍ7¿þú+ÕÝ|РA¯îG…ãxYYÊ"ÒŽYYY½xUñôô´³³[¸páÉ“'³²²&L˜Ðè©H¥RÔ3¯½ zñTL&sÉ’%Täåå5}úôF;û*•J‘HÄ`0 ½OHó£ÓéC† y.û/õäÙÞÞ^_õìÙ³ñ«J}‚—Ô;gž>}š––6{öltÍi‚ ‚J¥/ëB÷âLr¾¾¾/k·³µµ={6A4­)W–üü|ô(ª3666lXƒyyy-_¾œ$I:Þ赃$I333ÔÜŽÙÚÚŽ3¦ÁºwïN=¬d0M¼R(hº¸öÊÏÏÏÏϯÁììì>ûì3j¸¦D$8ŽÛÙÙ¡~Ví‹ÅêÞ½{ƒÑh4ooï+V4±úcc¨7‚Çñ¿ÿþ»oß¾ &ÈBZƒÆÞùùùÛ·o‰D ~ú²4g/ÓôSŠ$I.—Û`þ5ä]Ðô‚ ÐÌ‚ï,öºaJqq1 ‚ßM¯Ó( 4©Ê;ë ŸÌ˜QÿR©|øðáÊ•+ ½7ÈK5^y°X,GGÇWÜÇx{{›44CàTRR¢Óé^– AôH’d³ÙèTAšÈÔÔÍ€€4 Ã0.—‹žb#o,66ÖÅÅåU¹#†ÖxlooÿÉ'Ÿðx¼·Ü3ÁÒÒò›o¾1ÔqAÚÇ•J%‡Ã1tA¶¡°°°ÑAQ‚a‹ÅB-ÁH“$üþ;ØÛÃ?וJuòäÉ9sæ ^­Yã÷¸¹¹¹ ,HII¡ÞJ¥ÒëׯÿÎÒx<^§N }|6€ ­V‹.4H1 ”{i”F£¡:º H[ ÑÀ;P/pbb"‹ÅznìÒÚ4þóV«Õ¥¥¥jµšz[VV¶~ýú–˜ÈAÞŒF£133Ca ÒD2™ Ý2!ÂqÜÂÂe‡@šD©>lmõ Î;7tèPC iDãA0I’$Iêß¡R© ]lùN7|øpôÔi"ª¯§¡K´vr¹üÅôGÒ0>¦M«ßœŸŸÿ²D%Hë’¿ mž³³³³³³¡K´8Žóù|C—ií´Z­‹‹ J‘†4 ‡žžúwÉÉÉvvv( Më‡z;!òn©ªªB‘ Ò¨âââ¦'ŸFÞu••PT¤wãÆ=z ¾4­_ã5N§Ñh …B,€T*%B,ןИšÎÐû‚ Ò…BaaaaZï©%‚4ˆÁ`4:«‚<óÛoààÎÎ ‘Hâãã§L™bè2!kRäªÑhöîÝûË/¿€R©”J¥ ,¨¼nÝ:Ôì HëWTTDÝØº HkWVVæîînèR mDM üÓ¸´´ÔÌÌÌÜÜÜÐeB×xlcc3mÚ4¥R©_óÜ:¨ƒ‚ m‚F£ñðð0t)6@¥RºHѹ3øøP/“““Q‚×¶¢IAðĉ ]NAfPXXˆRC M¡ÓéPâE¤©Þ{Oÿ2##cÀ€†.Ò$h`‚ ï•JeiiièR m€X,FA0òºT*UVV–···¡ ‚4I“ú“$)“ÉîÞ½kmmíáá±}ûvýrÀáp6lØ€ú#ÒúÉår@`èR mƒÁ@Ý:‘&IIë×aþ|HHHpqq±²²2t™&iRK°H$Z¸pá’%Kòóóq/((àóùþþþ …¢´´tÀ€h¨5‚ mBuuµ™™™¡K´¹¹¹hfA¤I*+A£¡^ÆÇÇGEE¡Ù¶ÛŠÆ[‚qÿñÇŸ>}ºiÓ¦ððpF¡¡¡³fÍ*++Û¾};•LÑÐ;‚ Ò8¥RigggèR ­†a|>¥HCšD­''Éd™™™Ó§O7t¦jüf¥¬¬,!!aòäÉ={ö¬ßAŠÍf»ºº~öÙg7oÞÌÉÉ1ôŽ ‚4.// ŒCUQQ¡ÓéPûÒ$ÁÁг'H¥R###”/« i<®¨¨Àq<44”º0™Lwwwýý±µµµM||¼¡wA¤8Žã8Þ¡CCií4«««¡K´NNàè555<õ¢iCïA’$èoˆŒŒ>ûì3ýüp4F£ÕÏ"Œ Ò:I¥ÒÚÚZÔ¼‡4 Í­4A@y9XZ‡“››ëää„‚à6¤ñ–`333–••EEÃt:ÝÄÄDßÚ/“ÉŠ‹‹ííí ½#‚ ÀqÜÍÍÍÐ¥@Ú¹\nbbbèR mBë×Cu5$%%ùùù¡QqmHã*ww÷Ó§OWTTPq0…$I…Bñ믿’$bèAi„T*E­¦P«Õ(•Ò$8AÕÕÕhBʶ¥ñÇ=l6{Ö¬YsæÌùôÓOßÿ}???¹\^PPpòäÉäääÙ³g»¸¸¼øE­V›‘‘áíí­†BDqqqqq±¥¥¥‡‡zØ„è=}úT(êûšc–••UWWçäädoož_#z?vvvÖ·Ò©Õê'OžáææfiiI£Ñ^ñ]­VËáp ½ÈÛ Ñh233}||ôq‚ ŠŠŠJJJ¬¬¬:tèðê Í”ñî‰D•••¾¾¾ú%†effJ¥Rggg{{ûFZvi4pq>¿´´T¡P4!­V“ÂPooï­[·þôÓO»víâp8t:ÇqF# ¿üòËÁƒ¿Ø†$ÉŒŒŒ;v¬_¿^ÿùçŸÇŽÃq 4qâDt•A ®®n×®]C‡¥‚`•JuðàÁ«W¯Òét‹5iÒ¤!C†ºŒˆá‘$YYY¹eË– PApuuõÎ;SSS™L¦@ X°`¿¿ÿ+¶ ÓéPóÞ»€$É´´´Ý»woذAŸ>}ú·ß~ÃqœF£QÐ+ò„èt:ÔÍï]@Äùóç333×®]K-Q*•TÄ`0X,ÖäÉ“ ôªMÜ9ÀãeggwìØun[š3Œ€€€­[·fgg§§§WVVòù|WW×€€€'ÔÉÍͽ{÷îüÁb±ô=(ÊÊÊvîÜ9nܸ?ü011qÉ’%¾¾¾Ý»w7ô@ I&“%&&^ºtéÖ­[111ÔÂüúë¯k×® ;xðà–-[ÂÃÃÑÔMï¸ŠŠŠ„„„¿þú«¨¨ˆº‘&âäÉ“>ܾ}»……Åwß}·sçÎ-[¶¼"ÌU©Tõût!íRNNUq¹Üç* I“&Mž<9!!aÙ²e~~~aaa/ÛHQQ ‚Û½û÷理¤üôÓOõC‘ÄÄÄãǯ[·.44tÿþý[¶léÖ­Û«* :ø|xüø±———¡÷ y=¯Ñ}›Åbùùù3æ³Ï>›:uj¯^½^vZ”––fee±Ùìú >>iii†Þýf T*oܸalléããó믿.Z´¨¶¶V©T^½zµ¸¸ø¹¯ètºK—.QËq?tèÐòåËCCC—,YòÅ_dddÌž=ûÅoµK666óæÍ›;w®¥¥¥~aZZš››õ¤ÒÚÚÚÖÖöݹ+@^Æ××wéÒ¥S§NÕ7AdddtìØ‘zëéé©ÑhJJJ^±‰D"‘H ½+HËêÙ³ç·ß~«²DÉÌÌ477·²²‡ãååõê hìØ±ŽŽŽ†Þ¤eMš4iíÚµ~~~õ¦¥¥¹»»S½h¬­­­¬¬©€îݵZ.—Óét4%{›óö†¦) ª‡ 0 ¡PH5—¾¨¦¦æÌ™3“&Mj+jX,ÖàÁƒÇŒ8Ž}þùç%%%ÆÆÆ~·ªªêĉÓ§O_´hƒÁ I222òý÷ß¿~ýú‡~hè=Ðét±±±·oß~®Ri9r¹œÍfS ~\.—ËåÖÔÔ4¸faaáï¿ÿÞ¯_?téi  Åùóç=zôÖº9) }·N¡Pˆa˜L&kpÍû÷ïs8µZíããcèã„?~¼²²ò­ýsM¬€H’LHHpuu 7ôBjkk?naañÖþÅúÇ{Y¤Õj/\¸`aaáQZ NN2™ Çq4Wœeffž;w®k×®¯õ-CægxYçĈ4ÍPÙ>^­V7ý+;wÖ?‡Å0,>>žª\Åbñþýûg̘áîî^^^Þèvlmm'L˜°bÅŠ»wïŽ5*88ØÓÓS?Iõ»ÉÈÈH§ÓA§ÓµZ­V«uvv6t¡ÖˆËåjµZêµB¡àp8¦¦¦¯XõØ{gq¹\ÇõR©l=ÒªÔ¯€4V«ÕçîlXp0äææúøø¼Ëwõö‚`__ßäääêêj;;;­V›™™Ù¡CCïþ3t:Ëå¾:Ãèsê7ôjµÚ¿ÿþ›¼¥ÑhJKKu:N§kÊv ÆG}äâârùòåŸ~úI¡PØÛÛ8𫯾zg¬tîÜ9??_£Ñðx¼ªªªòòòþýûºPH«C§Ó;uꔑ‘Ñ£GÈÎÎf0Ô¨ƒ—y­ß8Òžøûû§¦¦ÖÔÔØÚÚR)„[O„´*;wÎËËÓjµ\.·²²²ªªê¹N *,,|ÝñHkðö‚àîÝ»ïÙ³çâÅ‹£GNMMMIIÙ±c‡¡wÿ ‹¼ñ׌ŒV®\Iõ €äääAƒ9;;GGG7ñëÆ 6ldffþöÛoûöíc0K–,y7çéÝ»÷Ò¥K“’’üýý/^¼(‘HúöíkèB!­ƒÁèÛ·ïÙ³gûõëÇçóOœ8áââòê<ÁÈ;+<<ü‡~¸téÒÈ‘#SRRRSSg̘aèB!­QïÞ½—/_žœœÜ±cÇ‹/J¥ÒÞ½{7ú­²²24’²-jÁ‹Ïç[ZZêŸXYYÍœ9óÈ‘#7nÜP(&LÐw'hg|}}}||’““›?yòä³Ï>;sæ õ×ÇÇgÉ’%"‘(..N.—¿úÙn»Ád2­­­õ½©:wîyE XZZêêQÐÏ?ÿ|íÚ5…B1iÒ$oooC—iÌÍÍëÏ 8lذ͛77½’J¥"‘M˜Üµ`}úÖ­[ïÞ½‰ãø7rrrvíÚõŽÿ¢¼½½QS Ò(&“dèR mƒƒƒƒƒƒƒ¡K´>>>MO§XSSÓŽÛõÚ·w±Ëió277ÿꫯ¤R©~ɨQ£ú÷ïokk[WW·`Á‚ú ;h4š¹¹9Ç[¸papp0°X¬9sætèÐáâÅ‹?ÿü3Ç œ3gÊу ‚ ­_aa!zbÙF¡ ø¿211™5kÖË>š9sfƒMŸ>]ÿšÅb 6làÀ†F£ñx¼ws<‚ ‚´-8ŽP9j6[­Fãp8ïN'`Ait:]mm­¥¥¥¡ ‚¼ 7ÇÓÒÒŠŠŠ4±±qÇŽê8ý´Zmzzº~JXfffF¥æÖjµVVV v¶&I²¨¨¨¤¤¤C‡¶¶¶úå†åååeggë ìääd裈 ‚ m‰N§£ªQCy(nuuußÿýÏ?ÿL’$‡Ã‹ÅNNN‹/œ‚ ÒfH$†‚à6 µÿWIIIçÏŸ_²dÉÀ©vVssó+VTUUíÚµ+00P&“I¥RNwîÜ9’$Ü©S'jþúššš3gÎdff†††öêÕËÖÖÇñ”” ‹œœœ[·n … &¼˜Ó‡Ïç5êðáÃõ³R4èêÕ«æææóçÏÿøã³²²¨.Ož<ú¹þøãE‹afèÉ ‚ mÆÓ§O===Ñž6 µÿW‰‰‰gäÈ‘ú¹ñ@(Ž?þÎ;ÕÕÕ/^üè£æÌ™SQQ‘’’2|øðsçÎ@AAÁ{ï½wâÄ ƒ±mÛ¶÷Þ{¯¦¦F¥R-\¸ð³Ï>;tè\.?uêÔ¬Y³ªªªžûGÕjõ7¬­­_ò]¡Pœ:uªwïÞ}ûöíÚµ+•É<<µ···²²z;VTTP!fYYÙ¦M›F¥P(–,Y²qãÆ!C†üøãFFFûöísvvNMMýè£þøãÉ“'€\.ÿù矅Ballìœ9sÊËËmll0 Û¶mÛñãÇ@§Ó­X±ÂÅÅE,¿¬xYYY?ž1c†©©i¿~ýŽ9RZZêàààéé¹råÊýû÷'$$ðx¼^½zõéÓ§k×®¦¦¦¨O0‚ ‚4QEEEhh¨¡K¼!@E\¿*X[ÃС7oBn.Ðé¾¾ •Âùó P€¥%ôëFFú¯Òét’$_Ü$‹Å"I’úÈÙÙ¹_¿~L&ÓÄÄdذaW¯^-//¿uëV@@@zzzzz:888$$$PAp¿~ýLMMÀÆÆF¿}:5`ÀÀ0ìÁƒ?üðƒ¿¿¿§§çËv+..®¶¶V«Õ^¾|™F£ÕÖÖÆÇÇ3†N§þùçï¿ÿ~BBBZZÚ7öíÛ³gÏCÿ1A¤màr¹hrÓ¶ ÁÀã³3hµ >[be4PyOX,prŒ¡^·‹åééyíÚµòòr;;»ú›|ðࣣ#ŸÏ§.ÍÌÌŒŒŒŠ‹‹¥RiBBBQQµ\£Ñá8ÏmŠB§ÓCBB&L˜@½;vìÈ‘#:´fÍš÷ Çñ“'Oòx¼õë×AZ­öÚµkC‡-..Öét¾¾¾ƒ Љ‰™5kÖõë×gΜyãÆ#Fú ‚ m ¨Ši‹P &&ù¯%~~àç÷¿·<DD¼ø=Ö½{÷íÛ·ÿý÷ßÓ¦MÓ'–ÉdG £ºIÈd²êêj¨©©‘Ëå...vvv£Fúä“O¨¯Ü¿_(R‹›Ò'Ãáðù|…Bñ²²²²žüðáÃ]ºtqssKLL\´hÑæÍ›_L¡G’d~~~||<‘””·~ýzF’dAAõÅÉÉéôéÓ;vìÝ»·~qãÆíÞ½ûâŋÆ ;|øðŽ;&L˜`ll¬T*Oœ8QYYIõµ@Ai÷Pü_ÑéôO>ùðåË—[ZZ …B‘Hddd´iÓ¦°°0j@pöìÙ3gÎ( ’$7nÜH£ÑÆŒsýúõ©S§ÚØØ÷èÑ£gÏž8Ž3™L}‹2Fc04j>xðào¿ýAp¹Üyóæ5J©TÒh´Ã‡ÿñÇúR}üñÇ7nÜˆŠŠª?Kœµµu—.]®_¿þÁ,\¸pëÖ­§OŸ … …B"‘PÃì }8AAÞ7SSÓåË—Ï›7ïîÝ»µµµ...úð—âååuâĉ[·n±Ùì=zP mllN:uï޽€€}ÏúK—.é¿èíí””D½®ßÐ[Ÿ±±qllì‹Ë—-[öÜ ‹‹/R¯gÏž=mÚ´»wïŠD"[[Ûgè‰ ‚ ò–  ¸Ù‚~ýú½ìSccã!C†¼¸<,,칈ù­áñx½{÷6È? ‚ bXh²Œ'Ð$‚ ‚ ­ j nq111‘Ï¥ž@AA Á-ÎÄÄÍ@ ‚ Òª î‚ ‚ È;ç­¶ã8ž•••••åààÄb± ½ûH+¥Óéîß¿_]]íãããááÁ¨7K‚Ô§P(îܹƒã¸¿¿¿££cS&šAÞM8Žgfffgg;::¢ yN—˜˜XSSÓ±cÇ:  ¨{«Að÷ßáÂGGÇêêêÀÀÀyóæ õÓ#È?¤Réºuë²²²¬¬¬~üñÇaÆ͜9ÓÐ…BZ£‚‚‚Õ«W+ >Ÿ¿{÷î èçGDçìÚµëòåËÕÕÕAAAóæÍ£&3BúêêêÖ­[—MU@#FŒ˜>}º¡ …´”·×"//ïÔ©S“'OÞ½{÷Ê•+/]º¤Ï€‹ õݽ{÷îݻ˗/ß½{÷ĉ=ZQQaèB!­A§N’H$Û·oÿ¿ÿû¿®]»:tH"‘º\Hk”——wúôé?üp÷îÝË–-»xñbrr²¡ …´Fñññ +W®Ü½{÷¸qãPÔ¾½½ øÁƒöööýúõc±X;vŒˆˆ¸qㆡwiîܹáççÇb±z÷îíààpçÎC iu‚ˆ‹‹9r¤@ ;vlMMMvv¶¡Ë…´F‰‰‰ŽŽŽ}úôa±X~~~Ý»wGÒ ¸¸¸¨¨¨Ž;²X¬¾}ûÚÚÚÞ½{×Ð…BZÊÛë‘››ËçóÍÌÌ€Åb¹»»ßºuëÅÕH’$B«ÕêtºVÞ½/55ÕÒÒÒÞÞÞÐi„D"IMMŽŽ~³¯“$I’¤N§{kÎÎÎŽˆˆ zì™››[XX¼,²!B£ÑÐéôV~ª\¾|¹oß¾úÙ°[­òòò’’’ÐÐÐ7û:I’Z­Çq’$ßBi ‚ÈÉÉÑÏõíââ¢ÑhÊËË\Ã0­V«Ÿ¼ÕºtéÒ€ ]ŠÆ¥§§³X,OOÏ7Þuª¼µçä䛚š›Ívss{YdC*­üתV«Zçǽ¼¼,,,Þl ÔU… ˆ·Væììì^½z±Ùl°°°077úôiƒÓét­?P©¨¨(,,4Ôœ\M§P(îݻ׳gÏ7þé¡Óé^·öy{A0¬PÌét:Ç«­­mpÍŠŠŠ}ûöuêÔ‰: [­ÂÂBcccsssC¤ …¢°°ðeG»QA”––N˜0áíX­V3™Lê—Àf³ÙlvƒÏ¸I’ÌÍÍݲe‹««+5u«•’’¢T*[ùµjk‚cÕ€IDATkE"QYYÙ›}ðÜÜ\±XüÖck4ýð&‡a˜B¡xq5ªÍ¸¨¨ÈÕÕµ•7ÉÉÉjµÚÐ¥h\II ƒÁHOOã-¼åîpM¬€êêênܸ!•JíììÞfñ^—N§ËÎή««3tAAÝ©æææ¾q÷kµZýðáCŸ·Vfª¢.×l6›Åb5XiµÚãÇggg·ò¨‰¤ºººõ÷èÐh4OŸ>•J¥o\QŠÅâôôô˜˜˜×ú–!ó78â’ÉdŽ3F&“ñx¼V^]………µþ†%ø§)÷¿LµZM„k… / gΜ©Óé¸\n+?UºvíÚ&ÆÿÇS…$É.]º0 +++ƒ”ŸF£5Xx;;»/¾ø‚F£ñx<ƒ¬éÚЩÿåêשS'.—kÀ]hð8[YY-^¼˜Ãá´ò&ˆˆˆh§J÷îÝÿKEIDHHõ ÙP¼ªøùùÍ™3‡Çã1™­z¾…ÿ¼5ÑÑÑÿ¥œ:®G666¯õ­·÷Ç8Žët:‹…ã¸D"i0¨¢Ñh¶¶¶¶¶¶o­`Hk# 5 At:]¥R©T*77·Wc2™úGáÈ»ÉØØX¥RQ¯ëêêØl6õ¼û9ÇÃÃÃÐ…E I TUUé+ ººº+ .—ëíímèÂ"†ô\¤V«½¼¼^\M  S¥x{7AAA"‘¨´´4Í£Güýý ½ûHkš‘‘¡T*áŸ^ª~~~†.ÒêÐéô.]ºèŸª?yò„Íf;::º\Hk\]]MuõQ«Õ©©©¨BšžžNÝ]—–––••¡ ¨{{Ap—.]0 ;}útMMÍõë×óòòúöíkèÝGZ£èè蜜œ[·nUWWŸ:u ðððpC iu FïÞ½oß¾’’RPPðÛo¿yxx4Øfƒ ¡¡¡æÌ™3555W¯^-((èÓ§¡ …´FÑÑÑÙÙÙ±±±TDD÷îÝ ](¤¥ÐÞÎ8nJbbâÞ½{Åb1ŸÏ;vlLL š³y†aÿý÷ñãÇÕjµÍ”)SºuëfèB!­‘J¥:pàÀ7H’tqq™7ož“““¡ …´R ûöí«­­ãÆ0`ª€étºsçÎýþûïjµÚÖÖvêÔ©]»v5t¡–òVƒ`‹ÅeeeVVV¯Ûyy×”””H$4«ò 8Ž`æââbØVHë'‰ÊËË­­­­­­ ]¤UCÐ;âmÁ‚ ‚ bpm k‚ ‚ ‚4/#‚ ‚ ï#‚ ‚ ïÆ7ß|cè2´RUUUyyyõða–œœœ••Å`0~j©Tzÿþý’’Çãñ¨©q”Jåýû÷ 9ŸÏo‰‰å0 ËËË»ÿ~EE…™™™~ê` ÃRRR233étº±±±¾œ2™Œ*'—Ë522¢ŠD’dyyyRRRMM©©).ýrrrd2Yýi Åýû÷‹‹‹Ÿ;Ô•••<¨©© …ú)©pÏËË£¦V677o‰©}4Í“'O’““ …©©©~Š#…BñàÁƒ¢¢¢úg)UΤ¤¤êêj“úåÌÏÏONNn¹r¶{©©©t:Ïçë—TUU=xð ªªÊØØXÿ&¢  àáÇr¹ÜÂÂB¨_öÓnF2™ìáÇiiiA˜˜˜èÿ‰êêê—•399Y*•ZXXè'0Ã0ìÑ£G™™™4­…ÊÙ¾‘$™˜˜hjjªÿõQTTôðáC‰DbiiYÿP?yò$==$I¡P¨?Ô þ´›Weeådz³³Ùl¶~ê`‚ Š‹‹“’’^VÎçΫ·PQ¶ouuuéééÖÖÖúCŠãxFFÆ“'O0 355Õ/W«Õ÷ïß/((`³Ù@¨üi7#Ç‹ŠŠ¨³ÑÄÄD?m'Žã™™™?ÖétõË©Ñhôå¬JTWW'%%UVV ‚fݪ§û3 ‚ Nžüm‰L&Û»wohh¨~úºÒÒÒM›6³X,:¾téR*-rròúõë€ 77·¯¾úŠ¢þóÏ?ÿùçŸ\.W£ÑôéÓgêÔ©Í;»¯H$Z·n]nn.ÇS(žžžß|ó±±qYYÙ¦M›ŠŠŠ¨r.^¼¸sçÎðèÑ£uëÖQåtqqY¸p!u+øë¯¿ž>}š*gïÞ½§NjdddèÃßfP·Û·oŸ5k–~Z錌Œ•+WR£“íìì–,YBMcvâĉãÇs8F=}út@ð²Ÿv3ÊÌÌܰaƒL&c2™2™lðàÁÓ¦Mãr¹™™™ß|ó Žã`cc³téR{{{8uêÔ±cÇØl¶F£‰ŠŠš1c†@ Ëå?üðC|||ø?ü Óé £¢¢Ž9¢V«oݺžÐ¼ådÈ;v(ŠôôôîÝ»Ÿ={–$ɸ¸¸ÈÈÈ7n¨ÕêÇGFFVTT¼ì§ÝŒ…¬®®ž4iÒÒ¥K«ªª$É®]»úõë—ŸŸ_^^>lذmÛ¶ÉåòŒŒŒˆˆˆ?ÿü“$É»wïFDD\»vM­V=z422²´´Çñ·PQ¶cIII»wïŽŽŽž:uªZ­¦&''GDDüý÷ßjµú?þˆˆˆÈÍÍ%IrÏž=111¹¹¹uuuË—/ÿðÃëêê^öÓnÆBfdd 8ð‡~ËåsæÌ;v,I’©©©ááágÏžU«Õ§NŠˆˆxúô)I’ûöí0`@nn®T*]¹råäÉ“%‰T*ýâ‹/æÎ[YYY\\>>Æ c±X®®®ƒ züø1UÎîÝ»p8œÁƒ …ÂÄÄD•J•˜˜8jÔ('''KKˉ'fddçååUWW7ÎÔÔ´C‡1117oÞ¤n¶FaVPPõDµZíÝ»w‡îââbnn>a„üüüüüü¢¢¢âââ‰'š››»ºº2$66V­Vß»wÏÁÁ¡ÿþ'$$$ àöíÛÍ[Nê2Ô¥Kƒ”ššªÓéâã㇠æââbff6~üxê|(...((ЗsذaqqqJ¥211ÑÖÖ6&&†ÃátéÒ%((èÖ­[†þ ´ …¢¸¸˜Ïç×ïnTVV–‘‘1yòdKKK''§‘#GÞ½{W*•>|øÐÄÄdèС\.7  k×®7oÞ„—ü´›·œOŸ>|8Ç+,,,//OOOŸúÈÊÊÊÄÄdüøñåååuuuOž<¡Óé#GŽäóù>>>=zô¸~ý:UΠ  ®]»r8œ¾}ûÚÛÛÇÇÇcö*Êv¬¼¼\"‘è;¢Pâããýüü"""8NÏž=]]]ïܹ·nÝ4h»»»P(3fŒH$ÊÌÌ|ÙO» Y\\ljj:~üx>Ÿocc3jÔ¨´´4ªœ¾¾¾‘‘‘'::ÚÝÝ=..nß¾ãîînllüÞ{ïI$’ÌÌÌÊÊÊ´´´÷ßßÚÚÚÑÑñ½÷ÞKHHH$ÍRB7`„ _ýµ§§gý…nnnTfcccff–­V«óóóõ3µúúúÖÔÔTVVfggëzxx¨Tªòòòæ-dhhèìÙ³©‡e$IRz¨rºººRå´¶¶¶°°ÈÌÌÔh4yyyú"uìØQ,WUUUTT(•JWWWj¹ŸŸ_vv6†a†þ ´ ÆÆÆ³fÍš3gŽ­­­~!†aOŸ>Õj///ê˜j2éСµÜÏÏ/77W«Õfee™››[Xü?{÷ÐÄù>üÉ@ÂÞK62àÀ­p[kµVëê²®VmmÝUëjµµuﺵnqoeÊ&HÈÞ¹»ßgóã«(h‘€¼Ÿ¿rÇ%~üøºÙÀduÇò„‡‡kµÚ‚‚2e‚F£…„„‡ºÞŸvÓÆ9cÆŒnݺ‘¯ …Ñhär¹2™¬ªªÊr=$ãÔh4=âr¹dJF µÄéããC&³:999::6yœ¯±¸¸¸yóæ 2¤îÊââb:N¦Ê@DD„åP{yy‘ÙSB¡ÐÕÕõáÇÏúi7aNNN_|ñ…evF©TÊ`0 FII •Jµ<§®§§§'ÙX  ÝÝÝŸŽó”¯±äääùóçwèСîÊììlwww²bÀçó½¼¼,_åPûùùaV^^þ¬Ÿv:{ölËM]uu5y ÌÎÎvss#+-<ÏÛÛ»Þ8ÉTx™L&‹ëÆYZZªV«›$B”ÜX†Ì[6›Í`0jkkq×ëõ–\r2IK£ÑhµZËJ;;;“ɤR©š6Kuª¶¶öøñãüòË/-q’9æl6›ÉdÖ§^¯×jµƒÁl6[ÖóùüÚÚZÍŸò¡Óéê~ûƒA­V3™L“ÉT÷PËd2 ôZ-F#{ª‘.%IÓ†D¦ÙQYYùûï¿Ì›7ïé8F£Z­¶µµ}"N¹\Þ§ yçM§Ó yï¥P(ȲöÁnÅ( ‡Ã©ûís8‡aƒÁ¨{¨ét:—Ë%Ûÿèt:†ajµÚòг©¨TªåË—ggg¿õÖ[dy½q²Ùlrè¢'âtrr"㬩©y¥q¶5äd½^O¶p( ² Çq“ÉÄ`0ȆòP×ûÓnÚJKKüñG“É4{öìîÝ»[âd2™z½ž|ŽY7N‚ È8 ‚xNœèTùÈ3„<Ô T*Ÿ>ÔƒA§Óyyy=ë§Ý„ñà8ž™™¹xñb__ßµk×ZK’‰ÏÓh4êt:2e¢ Ê¶ÆÆÆÆd2aF£ÑL&“V«%¿‚º‡Z­V3 {{ûgý´›0 ÃŽ?¾~ýú¾}ûΛ7Ï2æì³â´±±±Ä©ÑhètºP(¤Óédœdl …B(6Õhn¨ºÓX111yyyF£D"‘T* àp8ÁÁÁYYYä6÷îݳ··wrrjß¾½eeNN“Élòâ*--íСCÓ§OŸ0aBÝ^111ùùùdœdŠg@@›Í µ„tÿþ}@@vDZ³³ËÏÏ'×§§§XFvD^ƒÁˆˆˆ°êp8gggww÷ºIœéééd~gTTTMMMuu5èõúœœKFTS9zôhffæÂ… ‡ fyRI§Ó랥>d³ÙÎÎή®®NNNÙÙÙ–8}||X,VûöíÉV0 >lò8ÛgggËWžžNæw†……©Õj29Òl6gff’‡ºÞŸvÓ†´nÝ:øé§Ÿ,™ÁàèèèééY7N2¿344T£Ñ1Ífóýû÷É8£££ È’L,‹ÅbKŠ9òr‚‚‚L&SYY¹˜žžn9Ô………Z­jjjÊË˃‚‚žõÓnÂx$ÉÊ•+»wï¾xñâº'a`` ™ÄùtœEEEdJ†D")++ ¢ÑhÍPP¶5ÑÑÑ¥¥¥dç6™LV\\l¹zXu~~>…BqwwÖO» ãÉÉÉÙ¼yó{ï½7mÚ´º³.DGG—••) Ëå–>KOÄI§——×+ŠU‚«W¯^iiiµµµGŽ1™Lݺu³µµMLL}zÀ€\.7!!A¡Pœ——W^^¾wïÞ   àà`Ÿ°°°Ý»w‹D¢‡žØ­›»»{\\Ü®]»ÊËËsrrŽ;Ö§O>Ÿß±cG“ÉtôèQ™LvëÖ­{÷î%%%Á3~ÚMN§;}ú´ÝáÇÿüóOòTÉÊÊ"ãܽ{wyyynnîÑ£G{÷îmooGçíÛ·ÓÓÓ-qfeeݾ}›ì® Õj{ôèaíƒÝºEGG³X¬C‡I¥Ò»wïÞ¼y399zöì™››{ýúu™LvòäI™LÖ»wïgý´›0ž’’’´´4 …²oß¾ÿª®®ŽŒŒäp8–8oܸ‘’’BÆ™ŸŸíÚ5™LvêÔ)©TÚ»wo:þª Ê6¨GÅÅÅ—.]’ÉdgÏž­¬¬ìÛ·/ôë×/55•âï¿ÿvwwoß¾ý³~ÚM Žãäd^µµµÛ¶m³œ*˜˜XZZzñâE™LvîÜ9‘Hd‰óÂ… ÙÙÙb±øï¿ÿvuuŒŒtuuíСÞ={ÊÊÊrss>Ü«W¯¦ÊÔ¢ ^PÏòõ×_ÛÙÙÍž=›\$b}@*•þôÓO%%% …Çã-Z´ÈÓÓS.—¯ZµêÁƒäìPóæÍkÚkN§[½zõåË—ë®tqqù믿ôzýÖ­[Ïœ9C§Ói4ÚøñãûõëGƹtéÒÂÂB²«ÍÂ… ½½½ ''ç»ï¾3›Í†ÅÄÄ|üñÇèÔ ©®®þþûïû÷ïOK “ÉV¬XANëekk;þ|²±¤°°pÑ¢Eä3 ððð3f—›cÇŽmÛ¶F£™Íæ”””·Þz« §í‘J¥_}õ•¥m†”˜˜8oÞ<¹\¾råʇ’q~þùçd÷Ûâââ… F ÃBCCgÍšEÆyâĉ͛7“q&''=úUL/ô{ðàÁš5kÞÿýèèhrMeeå矮×ëq˜3gye?wîÜüA¥RM&Óo¼1ḟó¬ŸvS)//ÿý÷ŸX9uêÔ!C†TVV~ñÅ:Çqÿ¹sç’q¦¦¦nذŒ³ÿþï¼óù ~Û¶m§N"ã7nÜ€¬}ì[™ÔÔÔ}ûö}ùå—äš«W¯®Y³L&SŸ>}Þ}÷]2Ç`×®]ÇŽ£ÓéT*õí·ßNNN¦P(Ïúi7•³gÏ®\¹ò‰•Ë—/ ¹~ýú¯¿þJæÉôêÕk„ äƒï]»v=z”N§S(”Ñ£G4ˆŒó•”mÁo¿ýVQQ±`Á²õÊl6ïÛ·ïàÁƒäÝ7ß|sÈ!4M©T®Y³æîÝ»t:ÃáÌž=›œìY?í&a6›7nÜxôèÑ'Ö?~ð}ûö8p€ŒsäÈ‘C‡%ã\·nÝ;wèt:›Íž5kVTTˆÅâùóçk4Ç}}}çÍ›×T³z¡Jð‹ÉËË«­­ ãñx–•ƒ!77— ˆàà`KF³Ùœ““c2™‚ƒƒ›b­üü|©TZ·Fk‰3((¨îœdr¹¼  €Çã¡\ˆ¦b2™rrr0 ®{¨ EAA­­m@@€eîb¨¬¬,))ñòò²”yͧÙl~â,U*•ä@]OÄ)‹‹‹‹-~‘ÿN¥Råççs8œvíÚÕE¸ººº¨¨ÈÍͼYµ¨÷§Ý Ôju~~>›Í®7NWWWËŒ‰¤‚‚‰DòÄ·ÈK“H$………NNN~~~u×VWW …BËÊgý´›-NGGG??¿º½ŠŠŠÈ¹êV³¬[P¾®Èá½,“S¿Ó) †ºc5>ë§Ý JKKE"‘¿¿Ýtrt½^_oœä@¢Mø¼U‚AA6å#‚ ‚ mª#‚ ‚ mª#‚ ‚ mª#‚ ‚ mª#‚ ‚ mª#‚ ‚ mª#‚ ‚ mª#‚ ‚ mª#‚ ‚ mª#‚ ‚ mª#‚ ‚ mª#‚ ‚ mª#È+”———ŸŸoí(ÖçáÇEEE/ýv©TzãÆ kï‚ H‹†*Á/lÏž=çγvHë°eË–­[·Z; ¤õY»ví^úíŸ~ú©µwA¤EC•àöÏ?ÿ\¿~ÝÚQ ­ƒF£Ñh4ÖŽi}ÔjµN§{é·›L&¹\ní@iÑèÖ u0™LJ¥Ã0Ww½N§S©T ÃÎÎÎl63™L*•J„Á`P*• ˜L&`f6›©TªL&£P(|>ŸF£) £ÑÈçóÙl6†a†Q(¹\N¥Rù|>…BQ*•äÇÚÇidz²²Nž}º««kFFÆÑ£Gy<ÞŽ;(ʸqãììì¶mÛV]]ݵk×åË—gee9s†Á`ìÛ·Á`L˜0vïÞ-•J»wï¾zõj²2´p7oÞ;vlpppûöí—,YRZZ:dÈË—/Oœ8±wïÞ¶¶¶‹/.**š6mÚæÍ› ƺuë ¬¬ì½÷ÞÛ³gÉdš8qbpppTTTyyùèÑ£CBBÂÃÃÍfó‡~h6›§NûèÑ£‘#GGDDhµÚÉ“'oݺuРAÖ>ÈË8{öìÔ©Sccc/^\XXf2™æÎ›Ý³gÏ´´´¿þúk×®]k×®m×®Ý÷ßÙÙÙ“'O>qâDYYÙÌ™3ýüüØlvJJŠåc«ªª¦M›Æçó£¢¢¬½‹H“1 »vízï½÷‚˜7oÞ¤I“zöìií íÌ™3Ð¥K—_~ùæÏŸoíˆZT nØ/¿üòÇ|ùå—QQQ¿ÿþû¥K—âããM&Ó?þxóæÍÕ«WËd²o¿ý¶¶¶vÈ!|>îܹZ­víÚµjµú믿–ËåË—//))ùå—_Þ}÷Ý;w9rdþüù)))?ýôSaaáœ9s  ÓéV¬Xñá‡îÚµk×®]sæÌ9räÏ?ÿœ••5þüáÇ÷ë×ÏÚGi€Édúõ×_;vì¸zõj''§»wïŽ=öìÙ¶råJ6›PTTD¡P ðóÏ?ùùù:t("""888++‹Á`Lš4iøðáÆÅÅ%>>~ñâÅ:®²²2++«gÏž,ëã?NNN–ËåB¡pÚ´i³gÏ–ËååååYYY¨ÜÆÕ«W÷íÛwéÒ¥àòåËãÆ½^¿{÷îíÛ·:T,“W•äää?þø£¼¼ÜÓÓóàÁƒ;wöòò*++S©Tƒ ;v¬­­íÙ³g ‚‰DŸ~ú)—Ëýᇜ­½—È%“Éjkkmmm) à8^[[{ûöíF&“©Õji4šÁ`ÉdƒÁ`TUU™L&WWW‡#‹5ƒƒƒ@  P(z½ŒFcMM —Ëurr"_ã8îááZ^Z;½^_]]㸋‹ ¹F£ÑdeeQ©T­VËb±t:›Í–Édä6ä¥P(8Žƒƒ‹Å2f³™B¡ˆÅbæââB¡Pjjjôz½‹‹ËkМŒ*Á ÉdG}:))ÉÑÑìììÚ·oO¥Ríìì(JLL ƒÁ°\¡ÀÞÞ>44”B¡ØÙÙ¹Y€‘ ­Î£GD"Ñ”)S ::º}ûö@§Óýýý7lØ T*ãââ/^Ì`0ÄbñW_}UPPÀáp.]ºôî»ïòù|puuíÙ³§@ ?S£ÑLŸ>ýüùó¿ÿþ»¥DZ¯»wï~óÍ7>tww'ï®årùï¿ÿ.‰Ö®]ëàà0pàÀ5kÖ¸¸¸\¹r%//oíÚµ›6mrwwßµk—Z­:thXX؆ ª««Û·o¿bÅ __ß­[·ªÕêôôô›7o:;;ðÁiiiçÏŸ7™L&L˜={6Ž* ­•T*]¶lÙ©S§Ìfó!Cd2ìØ±ãêÕ« eÙ²eï¾ûî/¿üÒ£G7FEE}óÍ7§OŸþå—_  4oÞ¼+W®œ={Çñ#GްX¬ &ètºÈåònݺýöÛo­ýN uŒk@aa¡Z­Ž%¯žžžd.ă0 #Óò¨Tª¯¯/ƒÁ€ÒÒRƒÁðí·ßNš4iÒ¤Iýõ—R©4 ìíí-ŸLÖxètºårtt$ ³'6 ?iù´Z­Á` ë¦@ÞLÀÇüí·ßæää|þùç]»v]¹r¥N§srrŠ?tèPZZZ~~þˆ#ÈwÑh´ç§÷Ñét”ÿ÷šQ©T†YšUlmmɺ,‡ÃÙ¿×®]·lÙ2vìØ>}úܽ{×ÕÕ5..îðáÃ×®]«­­8p ù.‡S÷b4###ß|óÍŸþ¹²²ÒÚ»ˆü'dºŸÏ?tèÐ_|±}ûvàóù3fÌpss›:uj=àúõëß|ó§§ç7ß|S]]½gÏž‚‚‚ƒþüóÏ«W¯Þ¾}ûü±cÇŽìììÝ»w@zzúÒ¥KGŽyñâEooïO>ùÄÃÃãðáÓ&MÚ²eKVV–µ÷yy_~ùå‘#G–.]zðàÁÊÊÊŒŒ xë­·âããf̘a4Ïž=»zõꤤ¤wß}W"‘Ìš5«W¯^.\øàƒ¶oß~÷îÝ¢¢¢uëÖ … .¼õÖ[sçέ¨¨Øµk×wß}wöìÙÔÔTkïå…*Á  R©T*•F£YÉ×d'6ò™X^˜L&@Ðý_ÉÉÉk×®%˳ºÛ׫Á ÎÑÑÑÎÎN,“‹*•ª¼¼Üh4Þºu«C‡Û·oß±cÇŒ3–,YBVJ’’’.\¸pöìÙÀÀ@k‡X««+‹Åª®®&e2yÕÖÖæååMŸ>ýàÁƒüñ‡­­íš5k ))éôéÓçΫÛÝ퉫‡@ øôÓOg̘!—Ë÷ïßoí]Dþ“ŒŒŒššš~ø!,,lÀ€“&M&èt:ŸÏçr¹ä–_~ù%Y' …&LðòòJIIÁqüí·ß kß¾}ÇŽU*¹}BBBRR’››[ß¾}™LæÔ©S}}}Èb±Èd ¤5ª®®¾|ùòÌ™3ûôéÓ®]»Y³fyyy€­­-›Íf³Ùd> 4èƒ>Öëõ………ÑÑÑo¾ùæÆÝÝÝ ((hôèÑÎÎÎIIIF£qêÔ©ݺuóññ±œE­ª7ÀßßßÎÎîúõëdgíüü|òæ8""‚ r4{ ÃrssF#’ýá&L˜0a„àààŒŒ *ç6ÁÕÕµwïÞüñÇÅ‹E"Ñž={®^½Šãø† -ZT^^Îåry<ž¥²cgg÷Ûo¿‘  H›ååå¿~ýú›7oVTTlÙ²åÞ½{ —Ë'L˜päȽ^oooÏ`0È‹IBB†a[·n;vì³>“J¥ÚØØñÅk×®½~ý:AÖÞQä%ݺu+$$Äò,ñ9Ýà,9 \.·î –昺°}}}-%•J%G@b2™¨E¦UËÎΦP(áááä—@V‚ŸÖ¥Kr‡?þxÚ´i‰‰‰ßÿ½Z­vrr'''ËãM OB:þz¤Ê¼ûðJñùüáǯY³ÆÑÑ1<<|ãÆ …8ΠAƒ–.]J£Ñd2Ù®]»È¶áÈÈÈðððO>ùdÊ”)ƒaÉ’%qqq(Ÿ¡ P(|ðÁíÛ·?øà'''‚ ÈLßQ£FM™2åí·ßf±XR©tÁ‚d»¯§§gtt4†a±±±ä'Ðh4.—k)~lmm-6›Íb±žÞ€|4A¡PØlvkOÏj³(ÊŒ3¦N:iÒ$¡PH£Ñ Àb±¼¼¼Þzë­ï¿ÿþ¯¿þÒjµl6û‡~€€€€ÐÐP;;»°°0òèt:—˵ÔfÈó„|1räÈýû÷oÛ¶-..!­‡Ã©{óœì4H",‹°•\$âY÷À–†Ëå~õÕWo½õVZZÚ™3gvîܹbÅ kïÇ+‡*Á ûàƒ`çΆ 80))I 0Œo¿ývõêÕ‹-òññyë­·öíÛ' …Báúõë/^¼`ÁƒÑ§OŸO?ý”Ífûùù <˜î—Ëå¾ÿþûd¶(“É8p`hh(“ÉLNN&s=Áûï¿OÞ‘³ÙìAƒµk×ÎÚ‡iƒÞ¹sG«ÕvîÜÙÒK)--íæÍ›f³¹}ûöžžžäJÇ)JÿþýÉÑ‚ {÷îu³¬ªªªÈ,kõêÕäë¾}û’/ètºåi—Ëýã?¬½÷ÈË <~üø7Ìfs—.],ùÁëÖ­+((ÈÌÌtuuŠŠ"«¶†Ñéô””˹ԯ_¿ºÈÔ]´±±9r䈵÷ùO:uê´~ýúòòò   ÃþËl‚H[B¡Pnܸ‘@£ÑÒÓÓ žÿ–ŒŒŒ%K–¬Zµ*>>~êÔ©ï½÷Þ¡C‡­½+¯ª7ŒÃá|òÉ'£F"ÂÅÅ…lÖ56l:tè”)S¸\îöíÛíììÈz­››ÛªU«jjjÈñDÈ–¼˜˜˜˜˜òù|þo¿ýF¾ær¹}ôùºsçÎä ˶¶¶3gδö1@^‡ÃéÞ½û+y<ÞƒÜI¥Ò«W¯^¼xqÛ¶m¯Çs%ä?âr¹½{÷~z}»víêÞ×ÔÔœ;w.==}þüù–î Èë-&&&66væÌ™ï¼óŽX,&Û\€N§ã8^\\\SSC>¼F£Gþý÷ßétº··÷üA>?¤P(ä3………OkÖ,kïÇ+G[¼x±µchÈL)g)rp?zôè–-[¸\îåË—7oÞüÁÄÇÇ“e0|>ŸÇã¡l`äYŽ?þÍ7ߤ¤¤L˜0'HãíÛ·oÉ’%o½õÖÛo¿míXfbkkÛ­[·ôôô'NhµÚéÓ§‡‡‡GGG»»»‹ÅâcÇŽùúú›Íæððpr€NÇíììâââÈ'F£±GäpÑ8Ž˜ÍæÀÀÀÀÀ@ …‚a˜££#yONïСCÝñFÖ…=óСCwîÜ9räàÁƒƒƒƒÉùtRSSËÊÊzôèÁáp:wîL¦ü’£s^¿~ýðáÃb±xܸq“&M"ÂÙÙ9**ŠÁ`Ád2{÷îÍf³ ‚ R©QQQ­}øEÊ«è*¡R©.\¸––†aX÷îÝ»víjccR©ôüùó÷ïß÷ññIJJruum½e?A …âСCwïÞår¹ÝºuëÓ§šÜøE™ÍæÜÜÜÓ§OWTT„……õîÝÛ××ÇñÊÊÊ#GŽˆÅ⨨¨ž={’m¯µZMÎvÁápP”éõú;wî\¾|Y¡PÄÄÄôïßßÞÞÞl6ççç9rðN:uíÚµ-üU*•B¡ppph ;ûT*UjjêÝ»wqïÞ½{—.]ÈH"‘œ;w.++‹ý 5@Z­V¥Rq¹\Ë| Óé …@ @ÙÀ/J$]ºt)==Ïç¿ñÆL&Çq‘HtäÈ‘ªªªèèè=z´ÞÈl6Ëd2 …" -g;†aµµµL&³n/m µZ­V«9Ž¥ÃÉë­é[‚õzýúõë7oÞF§Ó·lÙb4£££i4ÚÂ… /^¼•––váÂ˵©5"û!EGG8°oß¾AAA¨÷ÛK¸sçÎŒ3lmmÉ!Ÿºvíj4?ýôS‰DpèСGÕûŒ¸µ#¯A Õ€„aØ¡C‡¾ÿþ{ooo''§}ûöÅÅÅåççñÅ666¶¶¶Û·og³Ùä¯7‹Ež9Ö¤%Òëõk׮ݲe Ù/~óæÍ†EEEÑh´/¿üòÊ•+‘‘‘·nݺtéR—.],ʵ ÃÖÖ–ÅbÕ½h+QJÕ‹R©TŸ~ú)9~eMMÍï¿ÿNÎPSSóé§ŸÖÖÖ8p ¸¸¸W¯^Öö%‘CÄÔíKmYÉf³ë-z˜L&9ŒZ«»E|IDS{øðaÿþýOŸ>m2™L&Ó±cÇâããÅbñ­[·úõëwíÚ5 ÃÄbq¿~ývïÞÝäÿi]æÎûÑG©T*rÖ½‘#GnذaëÖ­ƒ®¨¨À0ìÊ•+Ý»wÏÊʲv¤ˆ5Éåò7ß|ó×_5 f³9'''>>>55uΜ9}ô‘N§3™L[·n1bDYY™µƒE¬)++«ÿþgÏž5™LF£ñÈ‘#ñññÕÕÕ7oÞìÛ·ï70 ‰DýúõÛ·oŸµƒE¬éäÉ“ÉÉɆiµÚüqĈAlÚ´iÈ!•••†]ºt)11ñÁƒÖyU𾦝Õjù|~bb"9Œ\HHˆ\.'Ë-—ÐÐP*•joow÷î]kß V¦Ñhú÷ïoccC¡P<==íììd2YVVVLLŒ££#•J òôô$ÇLEÚ, ÀÌŸF£FµZýðáÃ=z°Ùl:¯ÕjKJJ¬,bMZ­ÖÞÞ¾[·nä\›ÁÁÁr¹ðììlww÷àà`*•* cbbPÔÆÉd²ˆˆˆ°°0*•Êáp$ deeÅÆÆ’ùÁÁÁîîî÷ïß·v°È«ÒôPbbb¶oßNŽF©ÓéN:Ìáp mllÈ,{ƒtðàÁ§ßNDMMV«µ±±i+­ñ-Az½Þl6»¸¸4yâÊ•+©T*…B!âîÝ»ÕÕÕÇÿóÏ?û÷ïO>íutttvvÎÉÉyú½†UVVâ8ÎápЩÒ¡Õj)Š««kÓ>¬···ß¾};ù™&“)55ÕÞÞÞÕÕ5??ß2FX@@€Ñh‰DO¿Ýd2•——Óét”~Ýr(•J‹ENIÕ„âââ¶nÝZ· a³Ù=²µµ% &“IH÷ôÛFcYY‡ÃA3“·8Ž«T*@Ð䉹o¾ùæÈ‘#É4™LváÂr§¼¼¼””òjãäääè蘛›ûôÛÕjuuuµ JDi!L&“N§srr²Œ/ÙMÿåQ©T2µ¼¶¶výúõ—/_þôÓOù|>AðïÄžäüÀƒáé·›Íæ}ûö„‡‡·ðqÝ«««É Ö¤z½¾ººÚÛÛûåÞŽãxyyyuuõ¸qã:vìØ´±‘½^ùòåU«VEDDôêÕkãÆÐˆSE¡Püþûïf³ÙÏϯ…—XEEE¾¾¾-¿ú¥V«U*•››Û˽Ýl6?zôH¯×úé§M[¹!ç¸"B£ÑìܹsçÎãdž:sS©T ÃÈ™ŸPQQ±bÅ ‡º“cµL………þþþÖŽ¢a‰„F£Y&0{ ééé\.÷ûï¿oÚÀ,D"ùí·ß®\¹2gÎ;;»F@b±ø»ï¾ yé_Aó0›Í"‘襯ê͆ ‘HDvÿ}¹OÐëõ÷îÝ‹%gŠnBd¯/ Ãòòò6lØ ‰¾ýö[2fhÄ©’““³qãÆððð>€†F£Q(M~·ÙäL&“H$òññyéO¨­­ÍÏÏ6l˜e(ýÆx%w0F£q×®]{÷î ]±bEDDD½›Õ[q!›‘† Öò¿³{÷î9::’Sµd2™ìþýûäTò/íâÅ‹¯¢£(ŽãyyyK–,‘ËåS¦Léß¿½]UžuªøûûO˜0áU¸¦sòäÉþýû·ðêˆD¢òòòN:½ô'˜L¦Ã‡¿Š=Å0ìÂ… k×®uppX´hQbb¢Ùl~bVo 4•JíÙ³çˆ#^ññkÿüóORR’µ£h؃Èz/ý )))G}± ² _µj•eR½'Ô{Uýúõ3fÌ«9lMF¯×_»v­å÷Æ0ìæÍ›AAAŽŽŽ/ý!%%%iii¯"<‰D²uëÖ“'OöèÑcþüùäøqO«÷T¡Óéï½÷žetÿK,[Æom±ÔjõÍ›7{õêõ_ŠôôtrN߯kúJ°Á` Ϫ>ú(11Ñ2å´³³sii©V«år¹ä]ì³f²n-È\"kGÑ0>ŸŸ`í(êwÿþýï¾û.>>~Ĉ~~~äJ777¥Ri6›étºB¡Ëå!!!ÖŽô?éÕ«WËo—–9Þ>†a'Nœøë¯¿œœœLI¡P\\\jkkÉm*++étzë̈Ôò«5$²¾2 ›6m:{öì´iÓ-Oê\\\*++ɈlsjÕ‹ÅêÚµ«µ£h•JíСCËLP«Õ?þø£T*]ºtihh¨¥¦[·’ËåJ¥222ÒÚÁ¾<'''r¯ÎÆÆ¦{÷îÍ_P6}.''gçÎ ,HNN¶Ô€ cÇŽUUUÅÅÅ ×ëoß¾Ýòo¡žÁ`´ŠQôÈçƒÖŽ¢~¿ÿþ{ppðÌ™3-5`HHHÈÈÈÐh4P^^^ZZú_Ú&[‚'†4j±žÕ’juJ¥rýúõo¾ùæ„ ,Õt*•Ú¹sç«W¯’‹ééédïkûŸ´–¡^É~ÏÖŽ¢>Ü»wï‚ ’’’êæªuêÔI$•––€N§KKKkÕ…Biá9`–8™LfËl-:}útaaá7ß|]÷`&$$ܽ{W«Õ@YYYYYY“ç6§{Uyª4AÙôW±ÜÜ\±X¼`Á‚ºçýüéîî¾~ýúÑ£G_¹r…B¡¼ösR#Ï'—˼e¶9!ÍÆÖÖö髊›››ÑhÜ¿¿ÑhìÛ·ï¨Q£ZÅÃäÕi׮݌3žXÉf³Y,ÖÂ… ÉÈÏÏoñâÅ–qE¶©[·nOt="gïòññY¸pá¶mÛîÞ½Û¡CT½Þšþ«‹‹‹‹‹«÷OÞÞÞŸ}ö™^¯g2™­å©òêðùüñãÇ×û§¨¨¨   “ÉÄápZÅ£ä•òöö~ÿý÷ëýSß¾}»té‚ã8—ËE5`¤C‡:t¨÷O>>>sæÌÑëõ,«Uä ¯“Éìׯ_½¢R©ÑÑÑÁÁÁ&“‰Ëå¢ðë­¹¿]&“ÙbóS‘…Ãá4ù°ÄÈë‡B¡´ÞÙבf† ¤‘PÔF [œW@§±lmA(²iJ*:x< sÔjÐjJ RA£ÐëÇT*(+>lm¿K¡£ññ‡Ðh`0@i)˜LÀb9ª¨F:èõÀဣ#ètPVB!…ð¬N f3H¥`2›ÔmBS*Ç{üÂÆPë‚ ‚ ¯6P &ˆÇ/,½ p€J 0ìñj … rsaåJŠ“eüxJPhµpᤧCXÑ¿?ÁáÀÅ‹ÄéÓÀáýûqqTŽzþ<¥ª 4=Ü݉Œ â?@"7ß$ÆŒbΊLFm׎2k¸»Cj*¬ZööУ1v,Á` B^ÁdÂwßQ‚‚ ºšòõסâç3f‹{÷Â?ÿ€^O|ó  ±r%H¥J]°(;w9 hß¾0r$¨Õ°{7df— [¶= »wƒ“'C·n TÂòå•ÞÞðÅàì /ÂæÍ`4B@|ó À?BQðùðÉ'Öþ­>@£†T EEàâ¾¾€ãpÿ>ØØ€Ÿ0PP7o‚tê®®€ã¬ÚZ y¸–ƒ?¢ªÊÏÑ‘ •8a¢Ñª««µÞÞvááeiiæ›7™L¦X¯·ur 7®_gÚÙÁÓ¦©T*•JU½zµB¡P›Í”€±X _Íãñø|¾ÉÍ-88ØÏÏÏ13“B¡ÂÕ^^‰D~ófͱc&“ÉdcCãñôr¹ÓO?9;;ûøúò"# Aê är9«cGZLŒ:'Çöôi.—Ë÷õuúüsW*\]xžž^tëVÕÇçs8úüüîGŽpÙì|½|¾ÐÅe˜Z­ÈÊ’Dþ)-.6ØÛÃgŸy¼Ú{÷˜YY^t:ßÞ\])f3·¢‚Š*Á¯ZI Èd–ÎJ%Ðh`cr9¤¦‚ÁNN66Ÿ§NJÝ»C·n{öÀÝ»o¼îîPXkÖ€R ‰‰@¦éïÚ©©àäo¾ ±± Á·ßƒîîðÉ'ààÇÃùó£GCçÎ`4Âøñ@§ƒ½=|õ¸¸@j*lÛ0d f3ܾ b1€¯/0™T£‘®ÕZû8¶a&ÔÔ˜Íàé  H$PV~~ ‚N R…dúlI äæ‚V ÎÎÐ¥ hµpú4(À`@J ðùPV;v@EDGÃäÉ;v@u58;C×®àçr9ìÞ j5xxÀСÀåÂÁƒpâÀˆ0p À‚PQŽŽðÙgàæYYK—ÚÇÄXûx!¯§×±üë¯`6ƒŒþþF£QʼnØàë íÚá½ziœäÉ•+Wn§§ËóóÃ;ur èÂçó¹\nmmí‰'¶Îkcccoo/àó]‚‚"}}œœlll8ŽYã,--ÍÈÈÈ­­åóù*•J(FGG³Ùl2O‘Á`yE:.77÷úÝ»F£ù|>•JŠŠâñxvvvu;jà8.•J‹ŠŠÒÓÓM&…B1™L<Ëåúøø´oßÞÎÎÎÆÆ†J¥F‰D’ŸŸãÆ rŽu³Ù,\]]Ùl6•JÕÙÙ•>|XSS£Ó銊Š\\\\]]M&SAA9$FóóóS«ÕƒÁËË‹B¡hµZ²ßô£Gª««Íf³­­-‡Ãyçw¬ýÕ6)‚±h4pv ƒŠ |ǃFÃ^´ˆB§C~>= ÄÂ…z@‘­øá‡Ë66¦ððv~~AK—R]ííù'NœØté’½½½Mß¾NF£›ƒCÔС®o¿óx]„Âvvl6Ûd2‰**ð’šÁ ððð°MN¶µµe³ÙÃh4ŸÏ'Jì(ݸqãL^žyà@[¡ÐÅÅE%‘˜L&^×®£FQ©T²?³­­-kÔ(¦ÕjÓÒÒvîÜi0lmm C——ç,—kµZnt´¿¿?ŽãJ¥Ò$¥WU‰*+M¥¥p÷.Ì`0Ôjµ@ pð÷W(ü¤R©ÑhôññaÐév'OšŽ‰D2™LC¡˜jjX úúújµZ&“)‰\¥Rï«WA‰ÑÒEn)Ìf0@¯.8Ðh #lmÁÝBË—áÔ) Ñ {wèÛÄbX±=Xµ àòeز$7ÈÑ5Ëÿ¿-– 8lmÁ2 Od$…À`yÙqp€÷Þ,#»÷è!!`gäìÁ°iÀ¿D OèÒ€LÈf0×’ùüÇÉT}ú@Ÿ>ÿ¿›l6¼ûnÝýÖ{xÔ>c.7¤a&sù2™@f9WT@a!„…£#”–Â?ÿ• íÚAb"ÐéØo¿á§N±h„…AYÌK¸ºšâ³Ï€N‡'àŸhL&mʬCL*…œ³R  å@f&• ¨)„Á<ÃhL&èõ8…T*51(3ŸOS©( “ "(•†Bxd$ `k F#BÁcbGG z{ÓF M˜@£P€Á „BÃh~~ŠÉ“•"‘µ8Ò ¼ÄCH Ñž2˜ÍæÃ‡'$$40m²Z Щ0™pï¨Õ P@×®ÀçƒÁ@^ÙM&Ó•+WNŸ>]^^noo?uêÔÐÐPr˜ô;wîdggÆ:tîÜ9&&¦-ô–0ååå&“‰\tttlÌD2%%%z½þîÝ»Ïêvm2™ìðáÃ/9m²^©©°f Ìœ ýúi‹Šò&L8+“冄¤ŒÛ¯woîºu˜·w¾Ÿßµ‡ÓÓÓe2™¯¯obbbÇŽííí­½ëÿ‰X,&'–...ÏßX"‘÷c&“‰ÉdzxxøúúÖƒ€DÞã•••i4šŒŒŒiÓ¦µ¨ñ§JKKoß¾mµi“kj - ! L&ÈΆÜ\0`Ô(`2áÈ8y”J˜2zô€êjøí7ɀɄ*är¨ª‚ÚZpt„À@0™@¡‡ÿÄ\R:øø@«êÇS[[{ôèÑgc-J¥òرc-eÚdµâñÉ¥KPY :$%³3¤¦ÂÖ­ Bß¾šnݤ2¬\i*+«´·‡7Þ—ÚôtÓ‘#FCÌãA\Ðé’¬,}u50ýýyäó@“ÉTYYi4yÌd2œœ …L&³··¯¨¨ Ñhnnn`0$‰­­mmm-ŽãT*• &“ɨT*ŸÏ±X,ꎥÑhôz=—ËÕh4<B¡( ¡P¨V«u:ðù|¡P(•J…B!Ç ÃT*•@ Édîîî|ðµ¿ÿ‘‘‘a0Zõ”+Vf6CM ØÙY (Àçÿÿ_ (,\]ÁߨTHOµôzèÔ ø|P(àìY0›ÁÖÞx(8|XtæLyRR§””ÆGÑ [‚ jj`Õ*€œHìÈ0À×—ü;F§×ˆÅ7nÜ8vì“ÉLJJŠˆˆ¸ÿþ?üàääT]]íåå™’’âêêʯ{Ð_wL&ÓŸìE÷"|||@,·ÌYK¥­ll7œCjªñûïÅ<Þ¹M›.§¦ºDDÄ÷ë×ÓÓsË–-'þù§w—¯]S:Õ¡C‡‰'zyy=N iý\]]]ÿ-äèèèèèØà¹':::::Úd2µØ¹ÄšƒN'N“ù¸ÊK¶®mÛÁÁàã TÂáÃ`g3 ;v„ÐP°·ô<Ìû?S äŸÀd2F#f¨ª2™L¶¶¶<F~róÂq\¡P˜Íf‹Eþ. Žã䘆AFƒÁ@„ù_F£‘F£ñx<‡†Èü2hµ€ãàá \¸¿ÿf3Œi6L¯×ë/^4j4Z—’›7+jkk ÅryMY™:36mÒétþþþì€Fÿ{×ÞÞ^¯×³ ðððp!:ÿNÂd2Ÿ!ŽJ¥²X,òÑ¢¥•„F£‘_•J%ï{1 Ójµ–†3F¡PÌfscv‘ F#të¾¾@¥Bf&TWƒíÛ?®.S(@£=¾ù§P "B¡×^ðÚÒ Ë* ƒ£GÁÇÆühÁËu:ÝÞ½{;öá‡ÆÄÄU7²/;;Û×××ÅÅ¥u×çÆ#ˆÇu߬,س 4†‡ùüùëÖ­ËËË‹ˆˆøbÁ‚ÀÀ@ò/^ÌÌÌ|ë­·:wîŒF)FVPj5DG?îCöàÜ¿ |>$$@÷î`i;wp¨{½2ß@¯×çdeÝ»wïÎ;K¡PÄbqee%†af³Y©TjµZ:Î`0är9‹ÅrvvŽŽŽ&[ÎÀÆÆÆÑѱººšl]«ËÉÉÉÛÛûYŠŠŠ,5:îææö¬‡c8Ž:t(778ŽT*uvvÖh4ƒÇãaFVŽ•J¥“““V«5›ÍÇqÇ ƒÁpppÐétx›Í7áÞ=((€ÐPˆŽ™ 6l€ÊJpw‡iÓ€Á¨õö–Lž\aóò æÎ%o'˜L&QTd/—uêÔ-%ÅÁÁÁÞÞ¾9ŸM5Ïÿzâ‘cIIIZZZ³í#ò¤òrxøÔjpw‡øxÐé`ÿ~¸u ”Jøþ{ðð€¬,øóO0›!>¦L8{Š‹ÁÖÈdn‚‚À`È&’Aƒàí·¡nñú×_ —ƒZý¸ݳ'ôìù?aüo>ðù0|øÿ¬ Ô«Õ˜BñB;×*Á55°};TU_~ l6Œl¶Çur¹ NɃ~ùåooïüÑÇÇç‰ê‹@ HHH°öÎ ÍH,†]»ÃˆO>Á¢£é R@`0RSSwíÚ÷Ã?¸¸¸Ômâe³Ù 0`€µ£GZ*±΃ž=ÁÊ‹aÙ2P*aøpˆŽ6ûqV®ÙüxlÁ/Pz½¾nó§Éd‹Åååå·oß.)))//ñññ'N¤Óé—.]úõ×_9޳³³§§§““ŸÏ÷ôô$íÈ–<½^Ÿ••EN\SS£Õj©T*“É4\.×ÑÑ‘ü_F"‘à8^VVfkkëííM£ÑÈLn&•J5 N÷òòb³ÙATUUÉd²»S„ÉN8Žóx<“ÉTUU•˜˜øÅ_°Ùl ÃÈùÈ‘Ùl&›É–E2NòßÑét ÔJ¥F£!"'''##ÃÚße³Àq¨­©ôz  þþnß&ÚµÓ3™òÊJ¹Tšïé™o2‰«ªô_~Y^^Î`0„B¡¯¯¯——׸q㜜œÈæ[rê; ʹGþ# ll€By<î\..r9lØPY ;wƒååpõ*88™>ÇdBŸ> 89DEÁ?p¹?ìØÿ\•ÃyÜ%×¢Þ»©:O½šMk¨ÛÛÃÛoƒÉf3Ðé@¡€Žã‡8räȇ~صkW Ã~ùå—ÌÌÌ‘#Göë×Í„€Á @@|üñ®ýû‹‹‹§NêèçWSS³òë¯E"ÑÔ©S»víjí(‘V… àÒ%X»"" wo{{øà ‚'®9ÿ&„¨Õê[·n]¿~=//ÏÇÇ'66V õ?FãèèØµk×øøøÀÀÀºmlíÛ·odD¿a#S·+**˜L¦ …B±···±±–ú.I"‘”””È®WàààÀår€B¡‚§óÂÉ2½½½D"y5ßS #“Á’% Ñ€·7øù‹e2ä‚£ãÍ›7 —-@àææßU  …|>ßÑÑñõH¾BZ• 6n„ü| Ñà§ŸÀÆ®^…7€Á€!C¸\HJzœªK^Çâã!>þÿ?F{Ü_Ö‚ÅzòØzÎÞÖP Öéà©Æ+W®8pàã?þóÏ?8 V«–.]êää„î’Û( ƒ-[ =zö„!C€É„+pkÏþýÇïÕ«×ÇÜ®]»¼¼¼ÄÄį¾ú Í„4ŠÑ—.Áöí°jðùàæ_ ‹>žª°â8.‰ÒÒÒnܸñèÑ£   „„„qãÆeeeåää(•J??¿éÓ§{zz²Ùìæì’kIÝnpK2¼9ók¥º€›7¡G˜0ìíaÑ"­ÑX"åœ;wíÚµ¢¢¢ÀÀÀ=zL™2…Ëå’óØ¡$=¤iÓu  9/BM  DZ±0|8³iSR 9h´Ç5W&}þhñ•àÊJض æÎ­»®¦¦fíÚµüq÷îÝ£¢¢Ž=êääÔ§OŸ¶Û &M?¿ÇÃõÛÙݹukÇŽ?þøcûöí»wïžšš:tèÐØØXÔÊ‚4ŠÉüwîÀÛo?@:(èùï(--ݹsçÝ»wCBBúöí;sæLËÞÞÞIIIÖÞ%äÕ++³>üÚ·'¢¸¤äÔ©S—/_f2™ýû÷ˆˆpuuEí5HÓS©`òd Ó!.¦N¢£ÁË ìí7ßr8УÇÿ¼¥m÷{iñµÆK—žhf///ÿúë¯ ”˜˜|>ÿu¿y9Læ3ÛýóÏ?¿ýöÛòåËÉÁ ‚ƒƒåA€  ª 23¡kWàráí·áý÷¡¡l‚ îܹ³ÿþG 6ì“O>!G GÚ ƒÔT8r’“aÀˆ‹ƒ¸8½^ŸššzìØ1¥RÙ»wïåË—7~Ti¬S§àøq¨®†±caÐ °±¡nv“·÷ÿÞ(Š;wîÔÔÔ…B¡Pø¬+*•jooO¥Råryii©L&•••Þ/¸³-¾œ›ké!h4¯_¿¾aÆ.]º ¢W ‚˜ÍLJ¥»víºsçΜ9sPÅyf3:»vAûöî ŸØ„ ½^_VVF&nêõzKÖïàÁƒç̙Ә᷑×ʵk°e ¼õtîL—žž¾iÓ&‹5jÔ¨„„„¶0=Ò²³áòe(+ƒéÓÁÙ‚ƒÁÍ \\w5£Ráóû[ ƒÁ P(>|îÜ9www77·ÂÂB½^ÿ¬J°H$b³ÙeeeŽŽŽööö2™,;;Ûí‰|冴øJðû˜L¦_~ùåÁƒóæÍ‹ŠŠ²vXHËsö,ðxÐ¥‹Édš>}zTTÔo¿ý††#E Ç €N¡Ö®…g7ÚݹsgÆ 8Žëõz@`4ƒƒƒ{÷î½hÑ"Ô%·mÑjA¯{{èÔ‰¼e2›ÍW/]Ú³g^¯çwzöì‰2}‘&—ÁÁ€ã°?x{ÃäÉ@fíÿ;CB+¥P(òóóóóó¯]»&—Ëãââ¾ýö[ˈ¥/*==]ñº ‘öo:]vvvffæêÕ«Í>‚Ò:\¸))p÷î];;»3f  Ò(8¹¹°cŒÁÁ‡}¨Z­Þ¿ÿñãÇ'L˜Ð«W/‚ ÈÉA¸\.ÊïlsÔjX±ìíaÚ4`±ŒFcnnîŸþIÄðáÃ;uêd¼A^^E¬X $%APÐhðùç-!‹W­V«T*NÇb±lll †ÑhÄqœB¡p8¦ÑhȱÃÀh4æççWTTTTTðùü˜˜‡SPP““ãéééëë;~üx___‡f¾–¶ìJpv6@h(8p G¨ŒÔO¡€œ˜?ßl6}¦L™b A^Re%ìÚ·nÁ˜10x0зï+úW2™L£Ñ¨T*FóèÑ£ªªªªªªÊÊJ¹\àààlI)äñx ÅËËËÆÆÆ`0ØÚÚòù|.—«×ëu:†aÀd2Íf³^¯7›Í666vvvvvvOg :Çñ2FSË®ggÛoÀ¶mÛúöíû¢þ6„Á ›ñ233ÝÝÝуH¤Q¤Rppx~09rdóæÍóçÏïØ±c ¹p#Vóð!Ðh þþr¹ü·ß~ËÏÏÿì³Ïž˜éA^’T ¶¶ðóÏàéù*>ð’’’¬¬¬ŒŒŒ‚‚>ŸO¥RíììÜÜÜÜÜÜ"##}||ÜÝÝÿ(•Ãá¼èdÚ ¥å\H[p%X£Þ½Áß¿°°ðôéÓ›7o¶v@HK…ãPPîî`k›šššœœŒFŒF€ãpþ|øÐ¡CÑh¯…BQ[[k©f¼pô¹ºÂš5àìü«¿‰$;;;;;;//O$ñx¼nݺ}øá‡ÁÁÁ4J¥¢¶¡z½ªJ0AÅÅÅË—/ÿî»ïœœœÈ•Ë—/ÏÉɱ|³gÏîÛˆŒo.—+ Ñ÷÷ÓjµëׯïÛ·oŸ>} ¶¶vñâÅ555ä_©TêÚµk}||žó~èÞàóKKK‡ bí½A^‚  Ųe˦OŸ>üé§Ÿ´Z-¹¯¯ï7ß|ãHŸù|žžO§Üá8þÃ?äççGGGOž< 3ÒQXX¸råÊï¾ûÎr>üüóÏyyy–¢ä³Ï>ëýìáðžþD  Ä0l×_ñx¼Aƒ¡ðk€ ˆóçÏgdd|ýõ×ä©TºhÑ"‰DB.Òéô5kÖ4q—$‚€¼<8|>ü^0¡¶nä&“Él6Ëåòýû÷_¹rÅ××744tÔ¨Q®®®-'ï¶%{%•ಲ²ŒŒŒmÛ¶á8Žã¸eýÇSRRBBBÈ۰°Æ|ZaaáKœŒ´p&33óôéÓ§Nêñï„æZ­¶¸¸ø“O>±<(h ZãîS§ê´Ú²²2Ôsÿu%‘HîÝ»wðàÁüü|KÓoee¥Ñhœ5k¹hkkK¶7@¡€¢"ˆŽ~bõÕ«W³²²æÎ‹aX=ȉّV§´´”,€( A–õ>2dˆe ÉÐÐÐøÐÜ\(-…þý/]ºtñâE”üzÈÊÊÊÎÎ^¹re§N,+ÕjuiiéôéÓíìì€B¡4ý7nÀÒ¥ðÅ/=»›T*=}úôÍ›7kjj˜LfŸ>}–/_îùjúÒ½Þ^I%877÷Ì™3¦îp‰555T*511±}ûö ¥ñ-»L&Ó®uNˆ4H©Tž={¶nó TVV …Â>}úðx¼Æ?Ä!ÂÑÑåç½®D"Ñ™3gÄb±å| ¢¼¼Üßß¿_¿~†½@³GQ>üD%¸¸¸ø×_ýá‡Úµkgí}Eþ“œœœ³gÏj4šºwD5554­Gááá/T`¬Y=zÆmÛ¶Mž<ùE»Ã#-Óõë×322žhÑ·@¶¶¶¯*‹ º¦Mƒ:5ïF2555'Nœ8þ|ppð˜1c\]]]\\Ы—öJ*Á}ûöíÛ·ïæÍ›;fY)‰¨Tê­[·.]ºÄápÛµkטÇIb±}Á¯+77·¯¾ú*??ÆŒ–•eee,ëСC …ÂÕÕ511ÑÝݽÁÒëõd9gí}B^‰ÈÈÈÈÈÈK—.ýôÓOäÇ+**`óæÍr¹ÜÏÏ,·þ,©žJóݺuk¯^½. iùú÷ïß¿ÿ?ÿüóÔ©S–•T*õÆ.\àr¹‰‰‰ÍgÈÌ£ÞxãÚµkT*µgÏžÖÞE¤iL™2>ù䓺+ÉèÀr¹ÜÝÝ=11±){’Àd‹§íI$’7n\½zU,üôÓOhÐØ&Ñ|)M•••ä·h4¯_¿>gΜ»wïÖ»¥D"!+@ä"Žãè¶ÛŠL&ÓùóçSSSM&SóüÇŠŠ r C“É´wïÞO?ýÔ’žõ„’’’½{÷Êd2 ‚Ïç7ªSòjh4šC‡edd§¿jATTTzôh³ý;ooïÏ?ÿœ,€”Jå¼yó6mÚôôÔ’ %>>¾K—.ÿ³ÖÎììj**ª««Ñ¤ÍÌÞÞ~ôèÑiiiÍö;tèÙ«W/&“ùèÑ£O?ýôÀd›q]L&sàÀ/=uü8:óæ5fÞc©TºqãÆ¸¸¸DFFNœ81$$¥¡?_HHHJJŠ¥ý´‘š¯Nvè›Þ½{oÞ¼Ù`0¹H¡PÈ«JdþÅbq£FýD^,+55uåÊ•………R©ôÌ™37nÜ0`@ƒ× Fãåå…µgóæÍýõ—X,®ªªÚ±c†aQQQ WSNŸJKK {÷îÖÞäÕ¢ÓéùùùK–,¹{÷®T*ÍÌÌ}ÎÛÉɨ(¸}ûvçÎQaôÚc³ÙçÎ[¹reQQ‘T*=uêÔíÛ·ûõë÷Ÿ*ÁÿüÿÖªŸE§ÓíÝ»÷í·ßŽ‹‹Û²eKlll›Ç¸™5ê(çää|þùç‰dñâÅíÚµKKKûþûï}||\]]ÿþûïŠŠŠ¯¾úêét:Æd2ɉB¡ :4##cÑ¢Eööö …" Àò(ó9”J%ºî¼ö(ŠåV›B¡Lž<ù»ï¾›;w.‡Ã‘J¥‰‰‰ ~HYYšçµG¥R-§ ƒÁøôÓO×®]›‘‘A¡Pd2Ùĉƒ‚‚þµx<ÈÉÉ C)4¯%²ƒ¥1bDFFÆÂ… ɨ]»vÇoøS:t€‡>@Œ¼ †åvˆB¡L:õû￟3g‡Ã‘H$={öŒ''4~ 99°};üøã³7!$ÉÊ•+e2Ù·ß~J±æÔp%X­V/Y²ÄÓÓó·ß~sww×ëõ{÷î \±b…››ÛÍ›7gΜ™ŸŸÿtwqãÆ7βèèè¸zõê‚‚‚ââbOOOK~ðóÉd2TD½öÚµkwðàAËbDDĶmÛîÝ»'•J#""<<<ó!†ùûû[{WW«[·nݺu#_S(”7Þx£{÷îiii†EGG7v™Ï>¡Š‹‹;wîlí}B^‰ &L˜0Á²èèè¸fͲòòòjäTMðïàŒ¹¹¹o¾ù¦µ÷ y%V¬XQw±}ûöÛ¶mËÈȨ­­mß¾}cè|&‡Ã‡!9ž1ã)A÷ïß_¶lY—.]/^Œ’š_Õàââb©T:iÒ$òT¨©©ÉÏÏïß¿¿‹‹ „††úúúÞ¹s§1}fi4Zpp°ežÆP*•hº¸6ˆÁ`¼h/ì²²2Ô² ²±±yá©Ýºt Ã233Gmí=@šÉ @:”—ƒ¿Mm­ÑhDÓqµ £cÇŽMðA ŒNNõþð[·n­_¿~ܸq}úôAùVÑpš‹B¡ Âçßû˜ÒÒÒâââÄÄDËÃk¦Õj_Q|%%%h¦ ¤1L&“«««µ£@Z¼š¨©€‚‚ÇÑp›È3ååÁš5`6_¹r%!!MÉŽ¼0*üýëÇñsçέX±bîܹ @5`ki¸Ìåri4šZ­&oÞ¼ikkkÇq²óþ«ÇqN‡žq#Q]]®#HÃöî…Û· ¢¢"$$ÄÚÑ -XI ¸»cTê¹sçž9Ató&œJ¥îÙ³çôéÓ mhüç—c2™ÐD¸HcTTT ñц …ЮÉdÊÉÉA]çéÙ(”òôtwwwÔc y1*(ðÔ½ŽãùùùK—.9sf#‡@^©†+Á ¥ÿþàÚµkAÄÇÇwîÜ™B¡äååݹsgèСï¼óÎ+šÖX«ÕªT*4\Ò “ÉD¥RQÃÒ°… À¤Õêõz4ûò< dee½¢VäuF§Ã¼yOw‰+,,œ7oÞôéÓ;uêdí€FŽÌ`0¢££µZ­‹‹ Ù4Û·oßž={Ö`¯É™Íf>Ÿÿê>ymTUU5Á´–H›¡Óé ª#Ï”•×®ÁÔ©YYY#GŽ´v4HkÃá<=CrEEÅ·ß~;yòä^½z¡Ö½¢Q•†šššåË—ß»wO£Ñ¸¹¹M˜0á7ÞhÔœ“ÿÁ`Àq¼ ¦+D^wƒ%# +*‚k×`ìØââb{{ûWô yúè#&“¹`Á‚’’’fÎ`0p¹\Ô¼‡4¨ªª =1@VQ99pýúõèèhtÎ ÏT^;F#ÅGÆÚ·î߯»Â`0üüóÏááácÇŽE£¾¶( W‚årùýû÷G=mÚ´Ñ£GþùçB¡ðþÿ~Á¯ˆ^¯§P(¨%iŽãNÏAþŸZ ööPXXˆ=‘ç5 :t(++£ÑhhÖRäÜ»uR~q?|ø°^¯Ÿ4ijÔkiþ>L&ƒÁhß¾=ùå¹¹¹¹»»7OK°X,vqqA' Ò ‰D‚Zõ†€¿?TVV¾ÐÔ•H›ãåš²2¡PhíPVÅd‚7ß„:cgeeíܹsõêÕ|>ßÚÁ!Ozáú%•Jm¶Ú†J¥B=WÆ0›ÍÖŽiñ@.—kµZ{{{kGƒ´tµµµÎÎÎÖŽiU˜L4Ȳ¤T*×®];qâD4ívËÔ¢3 *++ÑL•HcTVVbfí(ÖA§Ó¡&¤1jjjÐlMÈ 0¡¤êF/^trrÃá ç¯=½^óæM½^oYƒaX~~þ™3g233Séõz‚ PžÕk¯ºº:##£î³Ùœ––vîܹ¢¢¢Æv¢¥RaÜ8ðö¹\þÏ?ÿ 6 ÝAµ|â9W‚ 0 {:!Çñôôôµk×._¾ÜÒciçΰ±±Ñjµ‰‰‰S¦LACÖ# •Jýõ×#FSk4š5kÖܸqÃÆÆF§Ó½ùæ›ÏlœJ¥&%%Y{'WŽ ˆÒÒÒ•+W~þùçd‹H$Z¶lÙ²‹aØgŸ}Ö±cÇ?G,3 kï ò á8~÷îÝ 6,_¾œÍf“+·mÛvøða²êÙ³çäÉ“¹\îs>Ã0.—‹ê1¯7Ç:ôèÑ#ËhWjµú×_½uëY=úÍ7ßløƒ˜Lø÷>|èàà€xm®»ººÒh´ŒŒŒ§/jµº°°pܸquWæææ¦¦¦9r„ËåZÚfÊÊÊ6mÚ4nܸ1cƤ§§úé§qqqÝ»w·ö@¬I©T^¼xñäɓׯ_:t(¹òÖ­[Çÿé§ŸâââvìØ±~ýú>}ú<§­‡‡Y{F^c.\8~üxee%9l9Žãû÷ï/,,üå—_Á²eË6lØÜ`+¯Ùl¶TŒ×Ovvö… Ž9bggg)€JKK7oÞG¯×«ÕjÔü»råÊíÛ·wîÜÙµkWËÊ7nœ8qbÙ²eÑÑÑ[·n]·n]¯^½ø,±”J €ÔÔÔºˆ´d ßãzyyÅÆÆnß¾ýþýûu§Ì ¢¶¶vݺunnnO \[[«T*Ÿ˜mòöíÛÎÎÎd±XÑÑÑ:t¸xñ¢µw±2ƒÁ ‰lmmëpvåÊ•N:ÅÄİX¬899]¿~ÝÚ‘"V¦V«%‰P(´tTÂqüÊ•+)))>>>|>Ô¨Qb±8??¿Á2 L&ÓÚ;„¼*µµµ*•ê‰èÖ­[nnn `±X111±±± @†yzz¢É_cb±Øh4 …º+¯\¹Åb±èààpãÆ†?ëêU¸v ôzýýû÷Q%¸µh¸L¥Rß{ï=‹õÕW_ýõ×_÷ïßÏÏÏÏÉÉ9yòäܹsÏœ93qâD—ºoIHH˜;wnŸ>}ê®ÌÏÏçñxäí“É ¬7“iSœœœÞÿýÉ“'×½ egg{{{“]—srr¬)beÁÁÁ3fÌ5j”¥þŠãxnnn`` ¹èïïo43»Ñh|þsp¤UëÚµëܹs{õêUwe^^ŸÏ'kÆ,€´Zmmm­µ÷y…FŽ9oÞ¼   º+³³³}||È댓““££c£  òrpp€«W¯zyyY{çFiT¶“··÷ºuë:wî¼ÿþwÞygðàÁ#FŒøî»ï¨TêÊ•+ Ô˜Adt:•J%睊Tª­­­D"©wK…BqåÊ­Vk탃`–žžžžžÞl“liµZƒAæÞ°X,‹%•JëݲªªêÂ… jµÚÚ 0 W¯^}ôèÑógYoB:Î2΃­­­ÉdR©Tõn™““sóæMòÆqU‚­îüùó•••Íöït:F# fccSoDÄÇÉú±Ñhôðð@-ÁÖ¥R©ÎŸ?ÿ¬ßõ«ðDÄd2ë½2™L7oÞüÿsØÞ¼¼àÊ•+‰‰‰hd½æWZZzýúu“ÉôBïjÔÏ›B¡¸¹¹Í™3§¬¬¬²²Òd2Q©T>ŸïïïÏçóõz=‹Åz‰ÞÏʵb³Ù¾¾¾¨çJ A¡PÜÝÝÝÝÝ­ØAäY§Š¿¿?z´ÝBÐh4Ÿ‚‚k¥QR(”gýkggg///ò¯b±Õl¬.  ººÚŠÔ{ªP(ggg(--e³Ù('غX,V»víêŽÔüê=¨Tª··÷ÿJ4nà¸F£ÉÍÍ4i’£m³Ï‹Þ~¼@µ†Íf&&&öéÓ§W¯^±±±@"‘ >¼¤¤¤Á·s¹\ ÃÈJ:Žã*•ÊÍÍ­Þ-Y,–§§'ª·T*ÕÅÅÅÅÅ¥Ù £ÑH¶&êõz½^ïêêZï–\.×ÛÛU‚[:îéé)šíTár¹–1°T*“Éõn) É9²»Â³6CšOsŽD@äÈh†=§rpp ³&pçóùÖ>Nm“Élæ‹üÁ`¨·¢Ñhnnn¶¶¶—) Ñ¤R©º¼XÇ{‰ÖºÿÚ¶‡aXaa¡ÑhlpËöíÛËd2±X ƒáÁƒÁÁÁÖ;\HËP@Ž0]UUUYYùD΂•JŽŽ¶ÌÔ“““C§ÓŸU³±(//GwMmPdd¤T*­ªªƒÁððáà ‰D‚Foƒbccóóó ˆÅb±XléxðLÅŰm(•J‡ƒ4µ"Í÷€»sçÎz½þøñã2™ìÚµk>|ã7¬½ûHKÔ³gÏììì›7oÖÖÖ;vL­V÷ìÙÓÚA!-FëÓ§Ïùóç³³³ËËË÷îÝëççúüw tOÕÅÇÇ«Õj²ºzõjNNNƒZ­F¹ãmPÏž=䢢"ÔNÓ…BËwíàà0sæÌÍ›7Ÿ?ž ˆ©S§6æ^èÿv#¯/OOϺÏУ¢¢ÆŽ»víZÆd2çÌ™Óp¤P€‡ää䄇‡£ VZ‘WX |ˆ:;µ: W^¥Réž={ÊÊÊÈÅ¢¢¢‰'’CŽ#‚´"Z­V¥R¡J0Ò ½^ÒfÆòñÑÒhÅÅÅ/Ô?i ®›Íf Ã,‹ƒ¡¸¸øùÙ‚ -N§C³à"!‘HØl¶µ£@Z;;øè#€ S¯ÕAi ‚´ÏšAž T*Q…i*lmUjµZ­F7N­A¶B­VkµZkG´&“ PŽ4ÊéÓàè¨a2y<ª·:¨%A¶Ã0ÔßiŒššÔ+i”+W@­.))qrrB³«´: at: ˆ+W®”——@ee¥N§Û³gOÝ/{àÀè¦AN£ÑèõzkG´F£õôG¥¬ ¼¼ªRSQÛÖ¨áJ0Fspp¸téÒ¥K—È5NNN;wM||<ª#ÒÂj6HcTVV¢‡H£Lž ^^J¥MqÚ5\ Þ¸qãó‡ƒ`±XÖÞAH¥RFcí(V€Åb¡á®FéÚ*++;tè`íPÖp%˜J¥¢\oA^AxyyY; ¤5jHi<™L†´F/Ä]UUE£Ñx<ÞíÛ·«««ëþ©wïÞ|>ßÚû‚ ò<,«}ûöÖŽiüüü¬ÒjF¹\îîîní@Ö¨J°Ñh}z\\œµ÷iÑjkkíìì-Z„F^Džƒ ˆÊÊÊÐÐÐ¥K—Z;¤¥Óh4&“iÆŒÿ¥CÚ‚ÚÚZ·xñâF>S2›Íƒ¥C´R­ÿw••• C¯×çççÓétggg.—K¡P¬}§¢¢ÂÎÎN"‘TWWóù|¡PH6 #H]AˆD"W^^®T*èô滦!­ˆH$b2™dÄ`0œœœP„Ô«¢¢‚ÇãI$±XܘH©Tr¹\T n¥š¯À(//¯­­ýé§Ÿ8NUUUçÎgÏžíêêúô–r¹üòåË)))(ɦ%0›Í÷îÝ»{÷n×®]›ç?–””ˆD¢¹sç2Œššš¤¤¤Ù³g×û°©ªªêüùó;v´³³³öqB@¯×_»v­   K—.Íðï‚(--}ôèÑ'Ÿ|‚a˜V«ýðÇZï³Ëìììk×®uîÜùùO6‘fsîÜ9‘HÔlÿ®¬¬¬¶¶öÇd³ÙUUUñññ³gÏ~zª[‚ ïöôô AÃ-Gdd¤eøùf`0âââ&NœèããSQQñÕW_mݺuΜ9OlF¡P¼½½½½½­}xÇ8NdddaaasþÓîÝ»Ož<™ÇãݸqcÅŠ|b, ‹ŠŠ<<<¬}œptt yÑÒ§ù*Á 0`ùÚÞÞ~øðáû÷ï7›ÍO?¾d0è±fËA¡P@ h¶G‡}ô‘åu¿~ý.\¸pùòå7ÞxãéZ8‹Å²ÌeˆXFspp°±±ižS…N§/_¾Ü²8vìØ±¼îß¿jjê•+Wú÷ïÿDD¥Rííí9Ž\.÷ññ±öqB€Ëå …B…BñBïj¦vÇËÊÊ,¿¨TªP(¤Ñh8Ž7óaBZ8³Ù\PP “ÉÈE:îèèˆa˜µãBZƒÁ­ÕjÉE‹%Ð%yŽã¥¥¥•••ä"Y}¡ÑhAX;4¤ey¢b0 @‰µÅ´^ÍT &bïÞ½«V­"K,£Ñxûömooo4Jò‚ –-[¶wï^³Ù ‰äÞ½{ÁÁÁ(ã y‚Ñhœ1cÆ7ÈÅ¢¢¢šš///ÔÛ yA{öìùå—_Èùž Ã;w¼½½Ñ°VÈp_²dÉßÿMV|%Iffæó ‘H„*Á­W3¥Ðh´¤¤¤¹sçΜ93<<|Û<WWWÇÄÄß>Çãñxõ^îq¯©©¹råŠP(láÉåû÷ï6lXËïˆSVVVXXØ£G—{;ŽãUUUÅÅŠͰD"áóùäk“ÉT[[ûôf†^¿~](¶ð>.ÿý÷È‘#­EÃÒÓÓ™LæIÖÏËË‹ÅͰD"a2™l6 †‹‹ËõëןÞÌ`0äççß¹s‡Çã5[l/A§Ó?>99ÙÚ4ÇñÔÔÔöíÛ¿t²¾ÙlÎÊÊÒjµÍsuuuçÎ-]½­H&“éÞ½{‡<©Z¬ŠŠŠ¼¼¼^½zY;¨TªÔÔÔAƒ½ô%Z«Õfdd¸»»¿Ð»¬YuÀ0ìé•T*ÕÙÙ¹¸¸˜B¡´ðšV«ÍÏÏ·v ÀqÜËËë¥ã$¢¦¦Æl6 …BkíB½§ “ÉtqqÉÊÊruue0ÖŠ­1‚‚‚ZE"†aŽŽŽ/}ª`VYYiggGÞë6?‚ pz½ ›Í&Û[x%8((¨å_R€,øÿK¨………...VÜ…z¯*8Žs¹Ü‡:88X1¶áííÝ*NWWW™L¦P(^îíF£±¢¢Âº}£ë=UZ­ÎÉÉ!Z¶X†9;;·üS… ÿÿÒUL©T*•ʘ˜˜zWóÕ2) AA/p·4áÔE£Ñ ÔlQ!-•Jµœ*8ŽQo«ŒÝ»ï¾kí`k"/&äk à —Ë}z3ggçO>ùÄÚÁ"ÖÔÈÈÅÅeΜ9Ö±¦F@³g϶v°ÈÕ|Ïgƒ‚‚Ôj5ù°Òh4æääøûû[{÷‘–(,,L$‘ÝükjjÄb1:U§Q(”¢¢"r1??ŸN§£!Òz«T*™Lƒ!77]Uz………UTT˜L&¨ªªª®®öóó³vPÈ«Ò|•ุ8©Tš™™i2™ª««ïÞ½Û³gOkï>Ò%$$Ü»wO,ƈD¢îÝ»[;(¤Å¡Ñh /^T«Õz½þÊ•+ 88ØÚq!-QÇŽ«««³²²L&SUUUzz:*€z%$$¤§§WUU‘PUUU×®]­òªÐ/^Ü<ÿÉÁÁA,ïܹ³¸¸xçÎíÚµ3fŒµr‘–ÌÅÅ%##ãØ±cÙÙÙÿýwÿþý_ºWò£P(îîî'Ož¼|ùòõë×Ï;7yòäèèhkÇ…´D"‘h÷îÝEEE;wî ~ûí·[x—&Ä*Èèøñãd4pàÀX;(äU¡4ç€Z­öÎ;÷ïß Œçñx-¼“ bA(•ÊÔÔÔòòòÎ;‡‡‡×›è‰ ATVVž;wN¯×wíÚ500°…w‘D¬H«ÕÞ¾};333((¨sçΨBêE„B¡HMM­¨¨ˆ CÐk¬Y+Á‚ ‚ Ò´ôKAA¤É¡J0‚ ‚ Òæ J0‚ ‚ Òæ´è)Ù¬ Ã0Çëö³!Âd2A£Ñh4š¥SŽã䘂t:J¥’ëë]Ù´‚À0Ìl6S(ƒa™•÷…â$Ç'?„\oíßú˜Íf¨;Áá jË÷H£Ñètú+:UL&ŽãT*•Á`¼Ü)Ñ q¾öL&•J­;!¼å'ܘCý¬Ÿv"O ò_Ôý×--Î×yŸ>Ô†‘Wûº‡Úl6ã8Þ˜«}Ó"¿z‚ ètºåê×ã|½‘×êÆj‚ ÈÑ÷Ÿ8Ôõþ´›Ðs**-!NT ~¦ .dffΜ9“\4›ÍwîÜÙ²eKmmmLLÌèÑ£}}}@§Ó=zôèѣ䨥ãÆãr¹ƒáÌ™3ûöíÃq¼sçÎcÇŽµ··oòÓÒÒ<˜••ÅãñRRRRRRlllÌfsZZÚÖ­[%Ittôèѣɾu:ݱcÇŽ9B¥RÉ8ÉÉ¥RéÖ­[oݺÅçó‡Þ»woÔ¿þ…`¶iÓ&ww÷äädr^¯?uêÔþýû >>~ìØ±äÜT …bË–-ׯ_çñxƒ 0`“É€ÜÜÜ;wfggûøø¼óÎ;íÛ·¯[IúïL&Sjjê‘#GJJJ|||RRR @¡Pôzý™3gþþûo‚ ȳT €R©$ã´³³KIIyã7È8óóówìØñðáCooïwÞy'22²iã|íÆ¥K—&''[&öT«Õ›7o¾zõª­­í€LêÂÂÂ;wÞ¿ßÝÝ}ܸq1114íY?í&¤R©Ž;vêÔ©ÚÚÚ°°°Ñ£G“CΩÕê­[·^¹rÅÆÆ¦ÿþƒf±X@7vïÞ=77·qãÆÅÆÆ’qÞ½{wëÖ­555QQQ£GFÓR¼(N·`Á‚Y³fyzz’kÊÊʶoßž‘‘áää4nܸ:Ðét Ã222¶mÛ&‰"""Þ~ûívíÚ=ç§Ý„jjj¶oß~çÎNסC‡wß}— µ¼¼|ûöíéé鎎ŽãÆëر#ç½{÷¶mÛFN€üöÛoR(”æ)(_o™™™‡úâ‹/ÈKŽã™™™Û¶m+-- 3fLHHy¨/^¼¸sçN³ÙÜ©S§1cÆ8::³ÚM(//o×®]™™™ £ÿþÆ ³··'ãܱcGqqqPPИ1cBCC)ŠÑh¼téÒŽ;ŒF#§““h4šmÛ¶]ºt‰Ëåöë×oèСMgóÜŠ(•ʪªª~øN§÷ë×\™ŸŸÿÅ_tèÐaذaçλuëVÿþý)ÊñãÇ7mÚ4lذÈÈȽ{÷Ѿ}û .¬^½zРAñññ”Ëå;vlÚ{¬ÊÊÊO?ý”Åb}øá‡|>ÿÏ?ÿd0ÑÑÑ=š7o^LLÌðáÃSSS¯_¿NÖxNœ8±qãÆaÆEGGïÛ·Ïl6GFFâ8¾jÕª»wïŽ?žÇãmݺÕÏÏÏËË ÝŽ7Žã …âÞ½{kÖ¬ mß¾=qöìÙµk×2¤C‡û÷ï×h4±±±8ޝ[·îÚµkï¾û®P(ܶm›§§§¯¯¯Ñhœ1c•J4i’X,Þ·o_×®]ëÐõ¥¥¥¥ÍŸ?¿cÇŽãÆ‹ÅÛ¶m www?þü¯¿þ:hРN:8p@©TvèÐÇñ 6\¾|yܸqŽŽŽÛ¶msww÷óó3³fÍÂq|òäÉÕÕÕ{öìIHHhò’õue2™ärùéÓ§÷ïßß­[7///ø÷öéÌ™3ï¼óŽ››ÛŽ;œœœüýýM&Ó¼yóT*Õ”)ST*ÕŽ;:uê$ ëýi7í}ÈîÝ»ÿý÷‘#G&%%¥§§Ÿ:u*66–ÏçoÙ²åäÉ“cÇŽuwwß±c‡££c@@€Édúâ‹/ärù”)S´Zí¶mÛ:tèàààPTT4oÞ¼ÈÈÈ#F\ºtéÊ•+o¼ñº_j$½^/‘H¶oß~óæÍ7Þxƒü‰Æ… ŠÅâI“&±iÓ¦èèhgg犊ŠÏ>û,00ð­·ÞºuëÖÙ³g“’’h4Z½?í&,€´Zí/¿ürõêÕ±cÇÆÇÇŸ9s&##£sçÎ4í믿®¨¨˜4ilÚ´)22ÒÅÅ…,­F}çÎÓ§O8N§§¦¦¾ê‚ò5¦Ñhª««ùå‰D’œœL6ÆK¥Ò™3gº»»;6++ëŸþéׯ‹ÅºzõêÒ¥K“’’ºwï~äȱXOD½?í&¬H¥Ò Èd²É“'ûûûoݺU*•vëÖM&“Íœ9ÓÅÅåwÞÉÎÎ>~üxŸ>}Ølöµk×~üñÇöèÑãèÑ£ AlݺõŸþ3fŒ§§çŽ;„B!y¿×!ÈS–-[–’’9gÎËÊåË—7N£Ñ‘žžÞ·oß;wî(Šñãǯ\¹’Üf÷îÝ#FŒ(**úàƒ,X@®}ºV«={öìÀsss ‚ÉdC† Ù²eKÓÆùÝwßM›6<%´ZíŒ3æÏŸo0¦Nºxñbr›#GŽ 2¤°°0???%%åäÉ“äú… N›6M£Ñœ?~àÀ999A(Š¡C‡þõ×_ÖþZììì?þ¸k×®ñññW¯^%W4èèÑ£äâ?þ8uêT¥RyéÒ¥¤¤¤ÌÌL‚ t:݈#Ö®]K<ã§Ý´q¾ù曫V­"_Ëd²îܹ³¤¤dðàÁ‡"×/]ºtÊ”)r¹üÊ•+III÷îÝ#Â`0Œ9ò—_~!â×_;v¬R©$âþýû½{÷¾uë–µ¿V#55õí·ßŽONN.**"WÞ¸q#)))--\|ë­·–,YBÄÆG%•J ‚ÈÉÉéÝ»÷•+WžõÓn ‹ŠŠúõëwáÂr±   ::úþýû·nÝJJJ²œ–cÆŒùᇂشiÓ›o¾YSSCD^^^Ÿ>}.^¼h4›¡ |mÚ´ièС±±±ï½÷ž^¯'WîÞ½{ذa"‘ˆ ˆâââþýû“…δiÓ>ûì3r›S§N¥¤¤äææ>ë§Ý„A¦¦¦&%%ååå‘‹ˆ%bïÞ½C‡­¨¨ ¢´´tÀ€ÿüóA3f̘5k¹ñ™3g’““srrÊÊʆºÿ~rýòåË'Mš$“Éš$BtËUñãÇÿöÛo–G–¤ÄÄÄ-ðÞÞÞÎÎÎYYYz½þÑ£Gñññä6:uª®®‰DÙÙÙ–•QQQz½¾´´´iƒd³Ùýû÷www …ÂårÉ4𬬬¨¨(r*>///77·ÌÌL½^_PP` ©cÇŽ‰D,WVVjµZË$[ñññYYYd†+Ò 7}úôeË–‘‰1$³Ùœ››k9Ô111*•ª¼¼¼ªªJ.—ÇÅÅ‘ëããã³³³ Cvv¶‡‡ù$‘ËåFEEedd4mœŽŽŽIIIdö “ɤÓé&“é‰8£££5MYYYuuµL&ëСƒ%Μœ½^ŸíææFÆÉáp¢££›<Îט¯¯ï—_~ùÕW_Õmã'ƒ–¯ >>¾  @­Vçåå …Bò¤b0:t u½?í¦300°OŸ>äk.—K†aµµµ•••OÇ™ŸŸ/ÈTÖ±cGKœ‘‘‘dœžžž÷ïß·ö7ÐjtèÐaÙ²e|ðAÝ•………\.·]»väbBB‚åP‡‡‡ÛÙÙ€«««¯¯ï½{÷žõÓn i4Zlllll,¹hggG6²Ùì   §ã ãñxàâââïïïÞ= Ú¡ | >>¨sîA§Óɬr1''‡Ãá888899 ‚òòrr}ff¦——ƒÁ T*• …ôz}~~~“'uûöí¯¾ú*%%å÷ßïÞ½;™¬I£Ñ,qæææ²X,GGGGGG{{{Kaff¦§§'ƒÁh×®Z­–Ëå`0òòòиWÿ‘½½½“““%U 33ÓÝÝÍfûùùéõúÿcï¾ãš8ÿ€²$ì62e ‚{oípµÖV[ýVmm«]j[µj[W­­]ÚÚÖ½·UT\(ÈRÙ{È ;¹»ßÇ/_¾Šâò¼ÿèË\/ás—Ë=Ÿ{fSS †¼¼<òT·ùÓîØöîÝûÛo¿­X±â›o¾ 1vi°··o§““§N§#ãÄ0,77·uœdÏ¿úúz‘HÔáqö6nnn8Ž» ܽ{×xªí×b±¸¶¶ÖËËëQ?íŒG©T~ûí·ÙÙÙßÿý’%KŒ°››"ˆ³¾¾žŒ³±±±¦¦ÆËË‹J¥vAAÙÛøùù‰D"•JR©´²²’üv|}}§º¤¤õÓîÀxD"ÑçŸn0vìØñæ›o¯C???±X¬T*@&“UTTqúùùã,--ÅqÜÑÑ‘Ïç;88<'Y=?”î<©¨¨¨ŒŒ ¥R‰ãxII‰H$ŠŠŠ233 ºyó&9=xrr²«««‡‡Gxx8¹‘¬„³´´4ŽièA\¾|™F£½ýöÛd­žF£!ëö¢¢¢233 Žã¥¥¥B¡°ÿþ§uœ©©©ÎÎÎnnnéééä„Û7oÞŒŽŽFó?r¢:ã©NKK³±±ñòòrqq±³³»uë–ñTGDDp8œðððÚÚÚòòrÇåryvvö€:0r@nHHȸqãÈÙ"5 9XX˜1Îôôt>Ÿïíí-SSSq†‡‡›™™……… …B²Ç¡B¡ÈÌÌìØ8{!GGG77·¤¤$²i2)))$$ÄÒÒ²_¿~‰¤¸¸ÇqµZžžNžê6ÚAûöí›ã¾þúë«V­ZµjNOJJúüóÏíììfÍšµråÊ+Vðx¼«W¯.X° ÍþRÏL£Ñääädgg6̸ÑÙÙùÊ•+£Fº|ùòçŸtáÂcœ³gÏþꫯV­ZÅ`0’’’>þøc›iÓ¦ýüóÏ………ÕÕÕr¹üå—_n½òò´˜Læk¯½öå—_~ñÅæææ×®]{ï½÷Èê×_ýÇ,))©¯¯¯­­]°`“Éìׯ_ttôš5k†~ëÖ-__ߎM.%Innnaaá©S§ŒÇ÷ý÷ßÏš5ëË/¿\¹r¥……ŵk×Þ}÷]{{{˜={ö?üPZZ*‰*++W¯^Íb±BBBú÷ï¿fÍš‘#G¦¥¥õéÓ‡,ÞgfooÿöÛo¯_¿¾²²R"‘®ZµŠÃá 4híÚµ£GÎÌÌtuu:t(<ê§ÝQêêêÊËË7mÚ´iÓ&ãÆÏ?ÿüÍ7ßœ7oÞúõë«««e2Y^^ÞêÕ«ÍÌÌüýý¼~ýúÑ£Ggee¹¸¸qŽ1âÒ¥KË—/NHH1bDÇf`½¯¯ïÈ‘#7lØ››koo?jÔ(>>¨;ÄS!ûØÛÛoß8Žçææž?^¯×“§šì~­×ë¯]»–ššÊçó‡îççGžj‰DréÒ¥»wïöíÛwذaØ-[«Õæçç?0ÖÆÆ¦OŸ>8ŽçççŸ;wŽŒ3**мJÉ8oݺÅãñ† Ö·o_cœ—/_ÎÉÉñõõ1bDÇÆÙ477—––zxxëZ0 »~ýzJJ —Ë:th`` yªe2Ybbbff¦··÷È‘#œœ(Ê£~ÚE¥R=<—™»»»““†a7nÜHNN677:thPP§\.OLLÌÈÈðòò5jTë8ɉî ƒUyZd߆>}úÛ| yª]\\ÆŒãììL¥R ‚¨¯¯?{ölEEEttô€¬¬¬(Ê£~Ú¥¡¡¡´´ôädm …âÊ•+wîÜcÆŒÆ8Ï;W^^gŒ³S ÊÞ ¼¼\­VK‚ D"Ñ¿ÿþ[RR6pà@òT—””œ>}Z¥R 4(**м´õÓîd[P}}ýÛÉu:Äbñùó狊ŠBCC dŒ³´´ôÔ©SJ¥rРAÑÑÑÆ8oÞ¼yóæM‡3tèÐàààŽŠ%Á‚ ‚ H¯ƒêüAA^%Á‚ ‚ H¯ƒ’`AA¤×AI0‚ ‚ Òë $AAéuPŒ ‚ ‚ô:( FAAz”#‚ ‚ ½J‚AA^%Á‚ ‚ H¯ƒ’`AA¤×AI0‚ ‚ Òë $AAéuPŒ ‚ ‚ô:( FAAz”#‚ ‚ ½mÕªU¦Ž¡0 999;wîÌÎÎæñxÖÖÖ ðôôôþù§¨¨ÈÎή¸¸ØÂ‚Édêõú;wîìÞ½;99™Ü™J¥666©Tª;v$''ÛÛÛëõúýû÷Ÿ>}šN§ ‚ÆÆÆ’’©Tºsçδ´4¥RyàÀ3gÎp8@@¡PL}g!‰~ýõWwwwKKKSÇ‚ô$µµµ;vìðòòâr¹OûÞ‚‚‚¿ÿþ{À€¦>¤sá8®Õj€JEUZHû0 Ójµ4 e$ô³iŸ^¯ßµk×Ë/¿\\\|ãÆñãÇ_¹rÇñ£GΜ93//ïßÿ6mùo½^¿sçÎ3fäççgddL˜0aß¾}ƒáÚµk'N\´hQUUÕ©S§&Nœ8gΜ”””ÌÌÌñãÇgdd\¸paüøñ~øaMMÍ&Ož È3’H$ýõ—H$2u H#‰þþû簾¦gxoYYÙŸþiê#@:]CCÃâÅ‹SRRLÒ3ܾ}{þüù¦¤» ›:€@(nÞ¼ù“O>yóÍ7õzýŠ+:õÃ?Ì;wéÒ¥æ³Ï>KHH€¼¼¼Ÿþyݺu/½ô’Á`ؼyó?þ8a Ñhï¿ÿþرcïÝ»¼xñâùóç×ÔÔÌœ93;;›ÍfÓh´O>ùdÈ!ÉÉÉqqqË–-›5kVII ¹ƒŸŸŸ©ÏÒ>‚ T*Uss3“Éäñx4͸½¹¹Y¡P°ÙlGVÛwf0|>ŸÜY¯×ã¸L&c0–––8ŽËår 쬬˜L¦N§ Ãär9“É´´´4 r¹œ +++ƒaês€< ‚ ”J¥B¡`±XÆ+„Ü.“ÉT*•™™™………ñÊQ(J¥²õeF^ä•Óú“ÉÊBƒA§£~φã¸B¡P©T‡Çã!‘HnÞ¼9|øpƒÁ@¡P Fkjj"ï'z½žN§Ëd2ƒÁÀçó™L¦T*Õjµfff8Ž“;H$‚ ø|>¹³qTYØÓa&‘H0 ³´´äp8†UWW'%%Éd2²A[§Ó1 ¥RI„¥¥¥V«mnn&‚Ëåš™™€Á`À0ŒB¡H¥R*•Êãñ(Š\.×ëõ<Íf›úŸº'¶¯  Çñ &°X,‹õñÇ …šššÂÂÂíÛ·³Ùl6›=f̘ëׯ@III}}½½½}RR¸¹¹ååå©T*pvv ˆ‹‹c2™VVVvvv8Ž€»»{ß¾};ÄÇÇ3 [[[kkkr¤ûËÍÍ]¿~}VV–½½ý›o¾9}útr{rrò7ß|“íååµ|ùò¸¸8*•zûöíŸ~úéÎ;6663gΜ={¶……Å©S§ª««+**.^¼hkk»`Á‚¢¢¢sçΩTª™3g.]ºôСCr¹üþýû×®]sttüÏþ“““sá­V;wîÜ… ¢\§'ºsçÎÆïÝ»çèèøî»ïNœ8p¿råJBBB~~¾¿¿ÿòåË£¢¢(Êõë×ùå—¬¬,ggçY³f½öÚkçÀŸŸþüùõëד‹ãøÍ›7Ïœ93þ|oooS%ò\Ο?ÿÛo¿z{{/]º488ø‡~¨««ûý÷ßíìì,--/]ºäìì¼mÛ¶ßÿÝÜÜ|ÿþýÎÎÎ{öì‘Ë导òJ``à/¿üR[[ñÍ7ßH$’#GŽØÙÙíÞ½[«ÕΚ5ËÅÅå?þ …ÑÑÑ6l°³³3õ#ÏN©TîÞ½ûï¿ÿV*•ñññï¿ÿ¾R©ü믿Äbñwß}÷É'ŸXXXüôÓOñññüñ‡¿¿ÿþóŸo¾ù&55Õ`0ÄÇÇòÉ'®®®)))×®]#âØ±cl6û­·ÞÒjµGŽill6lئM›˜L¦©ô¹ îíS*•ÖÖÖÆ 6—ÈÈH‰DÂb±ŒÙƒÁ šËËËu:݆ÿ·gÏžÀÀ@2…e0¿\X,ªÆëÑJJJ/^lnn¾{÷î·ÞzkãÆçÏŸ'ÿ×ÁƒçÌ™sðàA++«-[¶ÈåòÊÊÊ%K–p8œ£G.\¸póæÍÿý7ddd¬_¿ÞÇÇçÈ‘#`áÂ…*•jûöí3gÎܵkWvvö­[·¾þúëÈÈÈÇ[XX,\¸~ýõשS§þöÛo¹¹¹¦> ÈSËËË{ï½÷öîÝ;sæÌ/¾øâÆ Õj?¾xñâýû÷cöÃ?¨Õê²²²Å‹;::ž!?Çñk×®-]ºÔÏÏÏÅÅÅÔG‰<—ÔÔÔ>ú(<<üÈ‘#ñññ‹-ª­­9s¦­­íK/½Q^^þý÷ߟ>}úý÷ß÷ð𨫫ûóÏ?oݺõóÏ?üñÇ6løå—_V¯^½uëÖ”””C‡UWWÿöÛowïÞݵk×Â… ¿úê«}ûö­]»výúõW¯^=yò¤©y.¿ÿþû÷ßÿÙgŸíÙ³§®®îƒ>ðññ™8q"ŸÏŸ3gŽ@ Ëå'OžÜ°aCXXØÔ©S¿ÿþû{÷îmÙ²eëÖ­þù'Žã………›7oÖëõ:tèÒ¥Ksrr6oÞ¼dÉ’£G’•}=ª1j—Ë …äàÈÊÊJNN8p V«5 äF•JEfºÞÞÞÎÎÎ.\ ·ËåòôôtSÒnܸ! =jmm^PPÐÔÔD^3gÎ?~<¼úê«7nÔjµ'Nœ R©ëÖ­³³³óóó+..Þ½{÷âÅ‹ _¿~¯¿þº¥¥åË/¿|øðáeË–ÙØØp¹Ü£GÊårˆŒŒœ5k‹Åš2eÊõë×?üðC²§ÄÉ“' …©Oòtp¿xñ"ŽãkÖ¬áóù¡¡¡wïÞmll´³³£ÓésæÌ9r$L:uÏž=ƒaïÞ½ŽŽŽ_}õ••••——Waaáž={^ýu°²²úî»ï¸\îùóç ‚¸yóæ²eË^{íµ×_½§WØôrz½þСCÁÁÁË–-377÷ôô¼wï^ss³««+‹ÅVVVÀáp–.]jiee5þü·ß~{ÆŒqqq*•*&&†ìjoo¿`Á‚€€ooï ¼ñƱ±±r¹<<<uíÑT*Õþýû,X0a¶bÅŠï¿ÿž '''ƒáîîNöv€1cÆ,]º”F£-]º´oß¾ÑÑÑ,kÛ¶mjµšÜÁÛÛ{Þ¼yîîî3fÌøæ›o-ZêääôÌ#º”·/00ÐÚÚúàÁƒ3gÎÔh46l°°°˜={vHHÈüñùçŸ+•ÊC‡i4ð÷÷çr¹¿üòË”)S0 Û´iSEEETT”©é EEEäÕB¾üâ‹/(JEEDGG“ÉÊ~ à ›šš>ûì3r{ee¥H$Â0 \]][§,d÷‹eìaìááaü7•J%Ë?6›Fˆ÷D†‡„„ðù|rËwß}G¡Pòóóétzxx8¹‘¼r C~~~CCòeËÈí%%%2™Œ¼r¢¢¢Œ½ôÈ«K,kµZÔ¹³§S©TeeeqqqæææÀáp~ÿýwƒQUUÕz7777ãK333GGGãKòNB¥R‰……Eë>ÆX,–©y.B¡P¯×‡……‘%EXXØŽ;ÚìÂGîóÆolܸqĈ111C† ‰‰‰!ïöööÆýmmm€Á`¼ ×( nŸ­­íG}ôÕW_?~\«Õ*•Ê#GŽ˜››/[¶lÙ²e™™™4ÍÊÊŠËår8//¯>øà“O>Ù¿¿Á`hllüí·ßÈÛòÂÃq¼uÜÖwcÎjÜÓ`0¸¹¹ 8иÑÌÌŒ h7eAÉî æQW…Byà»ÆqÃ0///ã•3pà@cöÜz0‹ÅZ¾|yQQÑæÍ›_zé%4²¶§#Âx‘P(cM^kL&³ujòðõó …‚^HA´þöi4Z› ó“×_=,,,999%%eáÂ…“&MÚºu+¼è J‚ÛG§Ó_{íµáÇ'''[XXDGGóx<ÇmllN:•žžîééYRRòóÏ?ÛÛÛÓh´™3g’3<°X¬Áƒ[XXP(”)S¦Lš4‰Ì„u:y;ãñxÇ'¯Ô3f;øúúw°±±¹páJzz„>}ú=,--1 {çwlmmß|ó͇÷d0!!!¥¥¥S¦Láóù8ŽïÙ³§¬¬ ië…h4šÏÞ½{ —Ë5 Ó¦M 'g•y“É MMM}ùå—-,,ôzýŸþYSSóÀSp¹ÜqãÆI¥Òëׯýõ׿þúë3Ì7ŒtÇÃÃ#))iÁ‚G&“=úÃ?DÍŒH›¨TjffæÀ©Têõë×.\øï¿ÿ>j‰D²~ýú¡C‡þç?ÿY°`Á©S§^ýõM›6™ú8:J­ž…Bqrrzùå—GÅçó)Š^¯ß°aáC‡&L˜ Ž;Ö·o_²œB¡8;;¿òÊ+'N´´´$¡¨T*N'ÿM¡PŒé( N§R©íî`ês€´oРAVVVŸ}öÙ¥K—~þùçÛ·o4èQyíĉëêê–/_~óæÍ}ûö­^½šìÕ€ô6T*uäÈ‘ƒaåÊ•‰‰‰Û¶m+((ˆ‹‹{TíË´iÓ²³³W­Z•’’òçŸ~ûí·ÅO¡Pø|þ‡~xûöísçΑí HOÄd2_}õÕ¬¬¬uëÖݸqcÆ jµº_¿~T*Çq±XLŽ@—Ë}å•WvìØ±gÏž«W¯~ûí·ä€%*•ªÕjE"ÙÓÈÌ̬°°pëÖ­—/_¾qãÆÂÂÂzCâѹ+Æ566æçç;99‘/q¯ªªÊÍÍU«Õ­'Âì‰h4š»»ûþýûwìØqðàA{{ûµk×%‘§…ãxFF‡Ãáp8€aXAAAII p¹ÜžÒcmmqéҥÇWTT,Z´hÊ”)A¨Õêðx<Ðjµt:=66ÖÞÞ>22òÚµkÿýw^^ÞâÅ‹_ýu:®P(œœœBBBh4Ù›sܸqä9Q«ÕÑÑÑä°†€€*•ªÑhX,Ö¨Q£È4Mÿþý’_HJ¥2##ÃÉɉ¼h4šœœœšš&“ÉápzÊ¥ò{{û   ‹/>|¸¶¶öã?5j9k\\Yƒ«ÑhÌÌÌbbbìììBCC/]º´{÷îòòò¥K—¾ôÒK4M.—{xxP(òÊ2d…Bqwwg³ÙR©4""âá ã˜X,.((xa 777—„„„C‡iµÚ5kÖ„……Y[[—””9rÄÅÅÅËË‹Íf“›@§ÓQ(”˜˜²¼¾¾~øðᎎŽä$Ó^^^äЂ˜˜‡CDCCèQ£lmmÉ|}}}||L}Ð]¤²²R(’½]áÿ{Þ—””P(”T=€,DöîÝ{îܹ/¿üÒÖÖÖÊÊêÖ­[/^ŒŒŒ´±±1–Mt:=**êÞ½{{÷î½|ù²¯¯ï¦M›¬­­Õj5—ËŠŠb0ƒA©TŽ;–Ãáà8®T*ÃÂÂŒ¿¯ŠÒyuZ­vëÖ­™™™äì•pêÔ©½{÷êt:*•:qâÄ3fôô™–E"‘X,f0dÏñúS19‚ îÝ»·páÂ-[¶DEE©Õêþù‡œaƒÍfÏž={ìØ±¦Žñ)ŽE¡PH$‡cccÓnAÛÜÜÜØØÈf³[_A… ˆÃ‡“ÕG,oß¾=##ƒF£ñùüeË–˜:Æg?´ææf‰DbnnnccÓîÍD&“555q¹\4™k›4 9åÓÞ½{É-'NœØ¿¿N§£Ñh'Nœ>}z+€p—J¥ÍÍÍ<ÏXç¢P(D"‘½½=|òlD"ÑW_}%V¬Xjµúï¿ÿ¾pá…Báp8o¼ñÆèÑ£Mã3Â0¬¾¾Þ`0ØÛÛ“W;ŽãÆÁÁáác4MCC•Jµµµíq¿ŽgDtš„„„±cÇ’/kkk‡úóÏ?«Õê«W¯ÆÅÅ%''wÞ_Gzººº7ÞxÃ××—¼$nܸ—˜˜¨V«·oß>dÈÆÆFSLjt ¹¹¹ƒöõõU©T†ýúë¯ãÆ+,,lll\¶lÙ‚ ÈåŽäßÿ ™0aù²¶¶vðàÁ¿ýö›Z­¾|ùr\\Ü­[·L#Ò-lܸ1 `åÊ•äK2?¹víšZ­Þ¶mÛðáÛššL#ÒY:¥=ˆ ˆüüü½{÷öïß߸1--ÍÆÆfÒ¤Id{Mpp0¹ÄÒË †?ÿü³u“JRRRxxxÿþýÙlö„ x<ÞíÛ·M&bz"‘hûöíäKÇoܸ1vìØ>}úX[[OŸ>½¦¦†ìBƒôfAäåå8p õ ±Û·oÛÛÛO˜0ÍfÇÄÄ¢Áq<))éîÝ»­ç•KJJŠŒŒ$gœ8q"—ËEÐ ¬S’`ÇwîÜIæ1Æ|>ßÞÞ˜Lfß¾}ïÝ»gêÃGL/555//ïí·ß6n¹ÿ¾··7Ùcooïèèˆ.Nœ8Ád2Éõ„Çñ¼¼pW©TÏSPJ¥ÒêêêáÇ=ù»:> ¾ÿþÁƒ7nÜØîM„hkLŽãµµµÎÎÎŽŽŽÝ¼¸ºs玽½½³³³©iGSSSNN9À³133ËÊʉD›ëõú]»vÇÄÄë]=J›—ŠZ­®««‹‰‰±´´ìæcÞ“““'MšÔý“àêêêÊÊÊøøøg{;Žã #==]¥RulÜÔÔ´cÇŽ3føúú>¦i’ìãõðv¹\®R©BCCÉ :º³¤¤¤©S§š:Šöegg3™L—gþ¥RyÿþýìîÝ»GŽÙ¸qc»ãÛ¼T‚P©TÝ<¿Ôh4™™™cÆŒ1u íÀqüÚµkAAAÏ<|Ã0¹\^^^Þá%$$TUUmܸ±Ý½ÍKE&“™™™uÿ*˜ÚÚÚŠŠŠAƒ™:v(ŠôôôqãÆ=sAiaaAæÁ&N‚8 ×ëýõW(++ …K–,Y°`›Í&WÉ¢ÓédÊßæpx …bmmÓý“K[[[ssóî_¬ªÕjÖÍ=ÏÀ`0tøO=###55µOŸ>}ôŽã°}ûöüü|*•j0p§R©:N§Óµ®'6¢ÑhƒîºSù¬X,–¯¯o÷O‚===CBBž'³ÑëõMMMþL’PSS“påÊrµzr16›­ÓéÈ}T*‹ÅjsšB:îããÓzq¾n‹ì*fê(ÚçèèH£ÑÈUvŸ‹‹‹D"éðÀöï߯×ëùå(--­­­]²dÉ»ï¾Ëf³1 k·b³Ù¾¾¾±±±]x.Ÿ…^¯·¶¶îþS˜á8nmmmkkû<5‘ÖÖÖwîÜéØÀšššÈU]¿ýö[ÈÉÉa2™+V¬øðÃ9Ž^¯7@z½ÞÁÁááO`0aaa‘‘‘]{FŸš——WPPÐóÜÕ»†N§sttôôô|ž‚’Á`Èd²§zKÇ'ÁC‡ä¿É©[úôécffæï™)‰œœœt:]~~¾——W‡ÿõ®ÔýÓt¹Ô©£hƒ““Ók¯½F&1†%$$¸¸¸899õëׯ¼¼\«Õr8œ††¡P8räHSû\zÊŠµݳi/ `úôéä¿kjjnß¾íããcgg˜ŸŸO>Ñh´ž>_XÈ€ Ûö6l˜››ùo¹\ÞØØH@wïÞ‹ÅŽŽŽd {.€ F÷Ï€€J¥¿Žn…ÃáL™2¥¾¾ž|YXXÈáp¼¼¼ Fpppyy¹N§c³Ùõõõ Ý¿Æý1¸\nèaÅd2Mò“ìø$xÔ¨QÆ–÷?þø£®®nñâÅ`nnþÛo¿%$$L:õÞ½{™™™ä²ÔH¯åææ6þ|òß:î矞üË/¿ÌÊÊò÷÷¿pá‚L&CÐ ¬ã“àÖÌÌÌŒíevvvóæÍÛ½{wbb¢\.Ÿ6mš¿¿¿©ÿe@§Ó[·ç¡ÓéÈÕ›È-d¿ò¿l6›Á`<ÜUÀøi†aF§ÓY,–±»ý3#ƒ1†¡×ë™L&…Ba±XAèõzcï¥Ö{Í©õIärÍ4N§ëõzrÙ˜N=ÿöööäi ™8qâ¦M›¸\®R©\´hQ÷yÅqœl #»Ÿ’­« ƒ<«Z­–üÈËC­V—””`VUUÅ`0ÈJnhÕÃ,??ß`0Ðh´ÊÊJrœ¥J¥âp8îîîþþþŒ¹‹ÅB¡Ð¸¼6•JÆ%ZÈËŒÜS¥RUVV *•Ê`00 #_ººº r=9‚ „Bacc£ñu:ŸÏwttäóù§¶¶Çqã:ÞATVV’ƒÏh4y1ã8Îb±\]]ét:†a 輯€\›(ʤI“òòò>ùä&“i0>ûì³Þ2Á;òÌÍÍ«'ÚÛÛÏ›7oïÞ½—.]jnnž>}zOiŸAºÇ36‚………?~Æ d´páÂnÞAy¸b\›jjjŠ‹‹ÝÜÜ<==ÛÜÁ`0œŸ|8Q*•R©”¼Ji4ZUUÕ¢E‹þEtƒÁ““£Õjƒƒƒõ°TYY™––öòË/wMHÈ“hjj:}úôœ9sºò’»»û£zˆÉåò3gÎÌš5ËÔ§ù¯ŠŠŠ;wî¼ôÒK]ùGóòò‚ƒƒµ }VV–V«m=,br™™™2™lÈ!Oþ–έ ~˜@ èšÒÇq™L& KJJòóóy<^¿~ýlmmu:Z­.**ºÿ~qq1…Bñöövrr h]÷vïÞ=:îèèèææÆb±8F3Ö3Ñh4333rþ¥RÙæ³YAK¡Ph4šÁ`ËåÅÅÅJ¥’Åb …¦¦&òÏéõzF.qýúõ;wêt:.—ëããÃd21 "Ǹ¸¸P©Tò¯“Å`0h4š`±Xd­*“É$+) ‚ ë)[ïF¥RÉŠdãK333²RÜY£ÑÿëÎ;]\ÇÖ·oß.è‰ã¸H$*//ÏÉÉ)..®««svvö÷÷·³³S«ÕeeeõõõÅÅÅÞÞÞvvvNNN$ד4ÎÌEÖøªÕjòœ3™LƒÁf³ÉŠÿÖ‹<Ÿd¼™™Ù“Œ{üDTZ­V©TjµZcòGþéÇ/Ù.ÑI£ôôzýÉ“'»r²:ÞeéѺ¬Bž9~.àºYeês€tº®N‚»†X,>yòäÍ›7Y,–@  ‘Éd'NœÀ0L­Vs877·áÇϟ?ÿ17DcÄdz´´|¨Áþ¨ôz½R©lsœ»©TWWwó랎ã)))IIIùùùÖÖÖaaa&Lprr*+++--ÍÊÊrttôõõ1b„O‡ôÇ W¢ª·<~Ö‡óìvQ©Ôì{DĄЋ‹Ø¢R©„B!Y;@¡PÚ|,7¶p’ …qŒš9ï8ùî?ÃÒC½ I0AÅÅÅ999ååå………ñññŸ~ú©‹‹ ‡Ã!K}rÊh²wã3OÜÝ5 F·Ê€{4ræiµZ-ÌÌÌ´ZmeeeRRRrr2‹Å4hÐ[o½ÅãñŒÙds¼¨Z–³oëAE­VK¥R©TªÓéär9XXXðxåÈ‹©G&…ÍÍ͸~ýú¸qã²²²vìØáîîþõ×_{zz¢œ1ª­­Ý¾}{ccãºuëÜÜÜJKK/\¸0~üø˜˜˜çŸ¦Až–J¥ª««#‡0VTT”——“™L¦«««¥¥eŸ>}Þ}÷]ww÷ššãÀDkkkr”09s69g …B¡P(ƒÁ`0`VXXHæ=‡ÂqÜÞÞ^¡PH$WWW©TÊb±<<<ÙwË`0TTTà8nœZ¤¶¶V¥R‘•|vvvƒA¥RÙÚÚÚØØÈd2Ç™L¦P($+¡É¨,--›šš”J¥»»»J¥ªªª²²²¢Ñhä` ‡ÃçóÝÝÝkÏÚÛÛ¿úê«A‰;A¶¶¶¨V¢M¦ªªª¢¢¢ººº¡¡Íf—••‰D"©TêààÀçó5X,5jÔ€âããÝÜÜÈo–ÞPSS2þ| òR¡R©8Ža9*€ r;ù©Tªq7òÛtssãr¹è B^x=ïW©T7n”ÉdëÖ­suu¥P(*•Šl 1uhH7‚ãø¶mÛ¸\î† È"00000ÐÔq!/8²?ŽãÙÙÙYYY)))jµÚÕÕÕÌÌ,33ÓÜÜÜÑÑÑÆÆÆÕÕuüøñvvvîîîwšlsHèÃë˜1 """"" CcccëQDdªÚØØXZZÚÔÔD®}åììLÖð‘IpŸ>},,,ŒÁ`P(dÎ$‘H0 ãñxƒ j]Èçó[¿¤P(666äyR©ÔÌ̬Ýîïäì¦þºL†üŽÈÜT$ݾ}»  @«ÕÖÔÔ4662™L???OOO>Ÿß¿rÎ"òÙ†B¡xxx<<ÅÂÂâQË m O’Ô²X¬Ž]óAº³–K¥Òo¿ý–Ëå~÷ÝwÆ’ãyÖcD^H:îÏ?ÿÔëõ}ôº<.S__Ÿ”””‘‘QRRÂãñ¢££?þøc¦Õj›››/^ü¨é–: N`‰×6î<Ϲ–ro@Ns™ššZ\\\]]MN^éääD¡PlmmÛ\§¬­­»çlÒCõ¤$X£Ñlܸ‘ ˆ÷Þ{M‰<ÆÍ›7¯]»¶mÛ6”#Š\0E§Óétº³gÏž>}:00pĈï¼óŽ««kWN‡t[†)Š¢¢¢œœœæææ¢¢"‘H=iÒ$²“7*Ñ䙑ÍVÏÖ{§Ç$Á†íÝ»W¯×¯\¹òÉg%Cz!‰Dòý÷߯Y³Æ8ôA:Á`¸sçNZZš^¯73R(`ýúõÞÞÞ¦é.4Mnnî¹sçÊËËÍÌ̽¼¼ú÷ïв^y˜R©${ÓÃÈå@.—K¥Rr ÃÄb1…B!—ú‹Å¥¥¥ŽŽŽ2™,66ö©þbI‚ïß¿îܹ;w¢ y Ç/\¸0pàÀàà`SÇ‚¼h0 ËÉÉ9|øp}}ý+¯¼B>eÑét.—knnnkk‹æ"¤ÆÆÆ¤¤¤ãÇ›™™1böìÙNNNhà òB"[ÃŒC4 ŽãƹùHr¹¼ººúþýû666<Ã0•J%‰$‰V«¥P(%%%dm®³³3¹«V«%ëwu:F£!Çp¹\µZ äw333ŸaÆI$’ŒŒŒ§§Ç$Á§OŸž0aê°<^SSÓ©S§¾þúkÔt,Nwâĉ#G޼òÊ+'N|ÚuO^ÇñüüüM›6ÙÛÛ/^¼8$$å¾È C.—744Ô××+•JÐétµµµ"‘Çq°³³ÓjµfffMMMŽŽŽÆá³"‘ÈÃÃÃÞÞžJ¥–””3÷ûøø˜››s¹\c³­‹‹Ëóü^lmme2ÙS½¥g$Áä*óçÏ7u Hw—””äâââêêjê@ŠD"ùí·ß*++·nÝêèèˆæ×C†aXEEÅùóçSSSç͛׿Ôçéþ4R©T*•Z­–\í¯¼¼œìiÐÐÐÐØØÈf³…B¡F£!=!ëbÉ”×ÊÊÊÓÓsÆŒÆ!¿ ƒÉdÒét*•Êd2[OÃ×== Öét¿üòËÌ™3QOäñôzý¹sçÞzë-Tõ‚t  .üóÏ?žžž_ý5šúyAEEEûöíËÏÏŠŠúæ›o©ƒB¶Éd2r"꺺º²²²ÚÚZ‹…ã8Ù»ÀÙÙÙÕÕ•LX§§'ŸÏ''-±°°èâÙfº@H‚sss%ÉøñãMÒÝýûï¿l6;::ÚÔ /ˆÌÌÌíÛ·3ŒÅ‹GDD ‡+äaB¡ðÈ‘#ׯ_Ÿ2eÊÒ¥KÍÌÌP_,¤›P(B¡°¤¤„\¦§±±Q*• 777{{û¡C‡’ë®S©TÆ`0zUKWH‚ïܹƒ–®AÚu÷îÝW_}•@H‡ÈÊÊúöÛogΜ9zôhÔiSffæ7ß|Ó·oßÍ›7£^XHw R©Š‹‹³²²JKKïܹãàà`mmæîîncccccãàà€&5ꙥ\.÷öö~ÚHoC®öéäädê@ž ‰DríÚµ|öÙgaaa¦Žévp¯®®Þ¶m[MMÍ_|æ¢ALÈ`0ÔÔÔTVVÜ»w¯¢¢ÂÅÅ%00pÈ!ï½÷êÁõx= –H$½ÌòÐëõt:½õR®òT‚8sæÌÙ³g›ššx<ÞªU«üüüLÒÕÖÖ~óÍ7áááË—/Gs!&a0Ôjõµk×Ξ=«Ñhx<ž¿¿ÿ´iÓ¼¼¼ìììP‹èêI°\.çr¹¦Žéî •JEµ"ÏìÎ;ýõ×ÇŽºÿ"ñ÷ßÍ;¥HÃ0¬¬¬,77÷Ö­[ååånnno½õVddd¯êÈÛz@¬P(PM0Ò.réZÔwy6ååå[¶lùꫯBBBL Ò}qûöí‚‚‚­[·¢ éJ2™¬¬¬ìàÁƒ555¡¡¡ƒ~çwœÑûóèCSSjoBÚ¥Óé˜L&À„<›Ÿþ966uîDO©TîÞ½ûÍ7ßDU3H—)++KJJJLLäp8ãÆ2djï(Ý= .++377·°°0u Hw§T*™L&êŒ<-ÇOœ8¡×ëçÌ™ƒà"aØÉ“'ÙlvLLŒ©cA^|*•êþýû{÷î‹Å‘‘‘+W®tpp@éoÇêîIpCCšwy<u‡@žV}}ýÁƒ×®]kiiiêXî‹ ˆäää³gÏ~óÍ7h†)¤³Ý¹sçŸþijjš8qâ¸qãPîÛI:%c¨­­=yòdVV–µµõ°aÃâââÈ[FmmíéÓ§srrÜÝÝ_zé%//¯v»r×ÖÖ¾x+” Fjµ:99ùܹs&44tôèÑnnn8Ž—””:tH(†††Ž7îI&>“J¥...¦> ¤³H$’‹/^»vÍfGEE3†ÏçëõúÌÌÌ£GbÖ¿ÿ±cÇ>mQaØž={ àååeêCD:FMMÍÉ“'³³³mll†K@555§OŸ¾{÷®‡‡ÇK/½äééùTc‰ þùç?þØÝÝÝÔ‡ˆtŒœœœ„„„‚‚@0uêÔ€€ƒaYÕ×ׇ……7®+“Fsûöí?þøƒÃáÌ;7 ÀÜܵPužŽN(“ɶlÙrþüù¸¸8[[Ûo¾ùæâÅ‹ä2ÓëÖ­»téR\\\uuõš5kD"Q»Ÿ&‰PõÌ ,11qåÊ•NNNñññ kÖ¬Ñëõ"‘èóÏ?¯¯¯=þüæÍ›Ÿä£Äb1ê¥÷¢Òëõÿüóϯ¿þÚ¯_?__ß]»výý÷߆eggõÕW\.×××÷Ï?ÿÁ/°‘#GŽ9’¬„£P( ðüüüò ØÅÅÅÕÕõîÝ»í~”R©D=g^T,kúôéýúõ#S:Žã8†a  R© %44T«ÕVUU=ùÇŠÅâæææþýû£Ìæ…agg÷@„ã8A………NNNîîî ÅÌÌ,,,¬Ý¨µ‚‚‚¨¨(t¼H¼½½gΜieee¼« ÈÏÏ %;!¸¹¹ ‚{÷îuj$R©ôûï¿?tèЇ~8{öl”w¥Ž¯ öððxûí·µZmVVVffæÍ›7çÏŸonn^^^ÎápȾ L&ÓÇÇçèÑ£m~Bssó;w¬¬¬ôz½F£AýÁM‹L5òòò""":üÃgÍšååå }ûöˆˆøöÛoGMÎ}hkkkggWXXØæÛoݺÄf³PlZZ­633³²²’ìþÔÌÍÍçÏŸo0ÈÞ ÿþûïĉ]]]ËÊÊŒ•¸^^^:®®®®ÍO(--ÍÊÊ nÝí¡¨¨ÈÛÛu¸2‰ÔÔÔ'é÷´<=====ÉK1333%%åÝwß% sssò»f±XÞÞÞ§OŸ~øíA”””õéÓ§õöêêêiÓ¦™úœõFJ¥òÖ­[Z­¶Ã?¹ÿþäç߸qãþýû2™lòäÉPRRBv;;;›¢¢¢‡ßn0rrr<<<ž9‚ îß¿¿eË_~ù…ÍfwÙ‰}ñÔÕÕeee=íРÎZbD£Ñܸqãܹs2™ìQ5:®Íí ÃÞÞžF£)•J†Æû›…B±²²2>.w†¢¢¢³gÏfggóx< ÃÞA¯×·ùF6›íààÀ`0D"Žã|>ßÔg«W£Ñhvvvt©`–‘‘qîܹ²²2÷pªã8Y—ó0KKK[[Û+,, @+-™„ƒƒCçùjµúúõëçÎknn633#û? ÍˆB¡ðx<×z£\.ojjz’á¹H‡£Óé—477Ÿ;wîÂ… L&óQÚ,€(ŠÍóÌLODnnîêÕ«_yå•O>ùeÀÏÉÌÌÌÖÖöiïçu÷çñxË–-;|øðĉׯ_/‘HÞçQW›Ívuue2™Z­ÖÜÜ X1-*•êäääèèØy¹ÂÈ‘#wîܹmÛ6r¢‡wxÔÝÁÜÜÜÃÃÉd¢n3ÝNwssë¼ç%‹5{öì½{÷~õÕWÛ·o¸“ F{ÔâI¶¶¶...\Ù™™žžž¦>m½”§§gçMÏçó?ùä“Ç;vݺu2™ìá}UÙÚÚÚÛÛ·Þ’’’„Z L‚ÅbyxxtÞðŽŽŽÛ¶m;|ø°¥¥å£ÆÀµYÑh4@ðÌWAééé«V­Z¸pá˜1cPüüx<ž‹‹ËÓfŒÿtuûöí²²²éÓ§‹Å1bÄo¿ý¦ÕjAyy¹B¡àr¹z½¾¢¢¢Ý‰f4 Fëô$Ø`µèt0ÞÉ-Àáb1°ÙÀb‹ hµ@Ö"0ÀfŽƒF ØÚ…8 S‚È:*ss RA§¥8œ–µºe ˜LÀqP©€ €F6¨TÐjA­ÌÍ,<ÊËF¬­É­”J RBKK P@$½ °³´Z¨®n9.²V£±¤RP©ÀŬ­A§ƒºº–0¼½D"¨©Zc#tt‰%“ÉŽ?>tèP²£^XX˜¹zSS“^¯g0‰¤±±1((èñ%‘Hº¢Û y®èt°²p”JÀqÐéÀƨԖóÉbµ5˜™Á€a€ã …2cÒ­¬ÀÚp$P©@¯`2A¡€† `³A  A­6¬­ÅƒÄbÐjFGG Ó¡±ȶB ‹–都4`0ÀјLP*A(°´l¹>E"P*É[Û–+ç C$‚æf{{°°µJKA¯üü ¶ÀÉ @£òrÐhÇ©¨¶•••—/_~ùå—---étúˆ#V¬XÑÔÔäââÒÐÐ`܇Á`ØØØ<ág …B™LØé— Ò…RSS+++É® l6{Ĉüñ‡N§sqq©©©! NWYYùä3¥§§GFFšúÈŽ¤Óéø|~||<XZZ8ð¯¿þ²2 t:½©©I"‘´;,ûiá8ž••õý÷ßüñÇ‘‘‘¨1Ê„ž" –Édt:ÝÜÜ“““1 ðõõm½[]]ÝÏ?ÿŸ_]]]YYIvÞzŒææfòÊ| uuPPvvT*dg“  ¸¹ TUÁ߃L~~ðúëÀfÃñãŸðñÇàçB!|ðÀbµ\99pú4`¼ú*ÄǃH¿ü:èõ°q#P(P\ çÏÄÇÃàÁ Õ©S J%¬^ ÎÎPY gÏ‚Nnn0{6@R$$€½=¼ñøú‚\;wBm-8;Ã{ï—.Af&Àˆ0bÀöíP[ ,^ NNPS‡ƒÁþþðÒK@§Ãž=PP|>üç?àáB!|ý5˜™Á A0m¤¤@Bðù0kBc#98:¶$ÁYY@ÎGöòË0z4Èåpî`ÐhÔN蔢Óé~ýõ×ÐÐP²4*..ær¹VVVQQQ7oÞ${òeee±ÙlŸ'üÌ’’’>}ú<ªæ¸Á0¨¯‡ÒR°³??Àq¨«• Àݽå!ª¼**€Ï‡à 7rr@©„qãÀÅ!3$Ð逜oáÖ-¸~àÕW!:”J8Ë… ÀÒ’’̶€9s:öhjkkýõ×Ñ£G?PEFFž8q¢²²2 @­Vß¹s§Ý¹‰HJ¥233sÑ¢E¦þžº–X dû­«+°Ù-Ò8@®–wÿ>TT@SÄÄ€(ž*˜›Ct4p8PR ƒ—ÄÇ\¿ 0ЯØÛC~>\¿à僃ÿþ UUÀáÀˆàär9Y`q¸\êÿ¦ÏJ¥feeÕÕÕEDDp8rrz777èß¿ÿÙ³gU*•¥¥eUUUuuutttÇþõ»wïnÞ¼yåÊ•ýM"÷DùeSSÓŽ;®]»¶téÒáÇ … H$6›­×ë,XðÒK/Ë’ÐÐPOOÏ%K– 4H¡Pó ‘Jýüü6oÞ ââ–,©úö…™3ǃÜ\X· ˜:&O <<€ÍWW ;P;:Š ÓZ äQL™£GdqÎãÁ_€^d£L\„…NdâÅåÂÌ™-¨d´ÁÁ@¶Î“Aš™Á;ï)BK]·7|öhµ`,ƒÇ‡#€BiùLÞ{t:àpZ¶DFBß¾ÿÝÖ¯‚*µå¯À_°Ù-aÌ› ݲaÛ6Èúõ!C`àÀÿ†mc üÏÙ&w PÔÉÉÞrinn>~üø;v466òx¼k×®YXXŒ3F«Õž={vÓ¦M‘‘‘Çïׯ_»wŠÆÆÆ6zìét P‹ÕrÆjj@&…üü€Çƒ›7aÇpv†‘#ÁϨT¸s²²ÀÉ fÌàr!6ÌÍ¡OŸ–¯iÚ4À0Ðé€l³·‡­[Él©­€!: †–—öö°lYK0d}h(µÚäùg³aútxùeòtøùµÔÁ›&O†Q£Z®"àóaÉ’–&ò{Ÿ<ÆŽ0¶~þyË…A¾ÅÛ–-‚ ¥åï¾ójÉ\\`Û6 P€ÍniÁ7†­åÀaùr ÓÿÕ°a0xðÄΖ, ôzÃÉ“}¥9“ôªU«Æ £G ¡ÓéëÖ­Û¶m›µµõÑ£GÇŽ+ «ÏŸ@EE… ºÐ¨Õ Vƒ™°Ù-Ù'*8:› B!Žƒ«+øø€N – ¼öôéœ 2XYÁ¬YÀ`À™3pö,h40w. õõ°jUKÃÂÂ…`o{öÀ¡CÀåÂܹ0b`¼öÈåààkׂ@ׯï¿BŸ> ~~€apù2”–,^ ¶¶PY ÿü––@Öšã8Ô׃BNN-­\ÙÙ`nþ߯4;;ˆˆƒ¡åK§ƒ‡ØÚ¶4s€««fúô¦§™Ÿá …‡‡»¸¸|ðÁ$  9sæXZZöëׯOŸ>›6mš2eÊÍ›7ù|þ@òÖמÊÊJgâñ p8Àd‚Nåå Vƒ¥%¸¹UUPVþþàè ¬ZC†‡éépáÀ! üü344@M üø#ØÚBz:|ÿ=ÀСðöÛ ÑÀÞ½‘žž0w.¸¹PG‚J<^K,•BuuKùBjh©ø| Çu47Cu5 `æQT••ЧOË[øü–'j;; «B03£åBb±`æLptÔÖ×ã%%{FétúèÑ£¿úê«+V„††ÖÔÔ$''ñÅ0|øðÿýwÓ¦MáááÇŽ õ÷÷憎‹ãx~~þêÕ«-ZÔ‹2`½”J03&0 ÈîIL&˜›…ÒÒ‚ ÿßðHÞa@§gg`0ZZ¤•JÀà ¸{·å-±±ÀfCI \¹l¶™\.{ʳJisÄÀ¶nÝzäÈ‘™3gNš4ÉÕÕõ—_~Ù»wï|àããsúôé„„„={ö´nZ*//?räHII‰¹¹ùðáÇ Bö¾ …‡ÎÎÎöññy饗|||n0 'OžŒuvvþûï¿)Êÿ<¯«ÕðË/på 8:Âǃ¯/ܺûö› '¶}:33“B¡ôïßÒ¤I–––†ÝºuëèÑ£fðàÁZ\´²²2--íeòa0 ûú믇:˜Lå; A€PffÀãJ©©-õ£3g\¼;w¶$¬“'Cs3üð…`n~ŽŽP\ÜÒÄ4`Lž 7o‚R t:„†‚44@V`XYAX°XP^2ØÚ¶¤˜deŽƒ¹9øø‹ÍÍ Õ‚µuKžA-ýX˜L°¶Ó¸hjj:}úôœŽ® €ÒÒÒ£G–””XXXÙá²®®îðáÃ999¾¾¾S§Nõöö~¸’ËågΜiÝJ™˜˜˜˜˜¸víÚ.:/uuš 8nn°v-””€J|±±ÐÐß}ÍÍЯÌ $&BBØØÀ”)Ч pñ"— QQÀfC}=TT¸¸€³sK?²ÖÆÑÑ„×Àª¨¨¸sçÎK/½ÔៜššzñâÅÊÊJ''§É“'‡„„0 rB½}ûöÕÔÔ 0àQ+ÆeeeiµÚv[)PZZºlÙ²%K– 8°Gö‚¨¯‡ÆF[[°·nÞ„Š À0˜6 x<(*‚³gA"77˜7`íZ((­>übc¡®6m ‚3€Ã={àÌàp`ñbˆˆµ>øÀÊ >ý¬¬ #®\‰†‘#A§ƒ‹œhæL07‡òr¸},,òD¢z7·!C†<ùµŸ—””|ðÁ¯¿þú«¯¾J¥RÈô÷‹/¾`0MMMóæÍ›1cÙ ˜DAäØmÖz” Žã8ŽS(”Gõôm¯_¿¾_¿~ãǹ !0°%å·³«¥:“ìpI¥vÿ_rÖII0AÎA¥R[ßÈé¥ØØš1 ÖëõŸ~úéŒ3¢££¡¤˜Lpu©´¥º‹JmIvɾª4ôÄ[OÑyI0üÿÝþ÷®b¼~¸Õ´öp¬R©Þ{ï½O?ýÔ÷©šY ššÀÌ 8Ðé   ¥c R᯿ !¨Tx÷]8¤R8tÄbpph) †–‹Á: †–Û—±– ZF¼èWiç%Áí@¹«<œ¯]»ÖÏÏïÕW_}®˜È>ú445A~>H¥àîÐÜ ¿ýyy`fï¿}ú@^\½ \.xyµ´m·  ÈË ¥a‡‚B¶ü¼ Ów^L^'A<œ“´[=C\WW÷駟Μ9Ó4«®ÈdÐÜ 2ôé,H$œ  ØØÀ!`0À±c”\.Lž ýûCY¬Yõõàé Û·$&BJ Àÿ÷è“ËáÔ©–Fò!CÀÞd2(-++ ×¢×j[É Ç[nƒÆûÙ\@¡T*D˘+ãä] Ýcff¦L&{ª$¸ýîäÄaaaä¥ ‹«««gÏžM΢Ç`0ÌÍÍkjjZ¿…\õ ÍKç1—ÔäR)ŸÏ‡òrX³[:<ÐçFCéoF¡PÚìöýä"qg0fff˜¿ý ‚«+ðùð@ &ª÷íáÚ¼{<êúy<½^o0ÚoãÆqÀñ–TãÀ¸xjkáƒ`ôhP(àôiÐë!  ¥ɬY0gÎoG|>ÌŸÿ?ŸF§CëP)”6®Ic—äYuTD …£ÈþHOŽ Z²Ò†عîß&³¥óII œ> àæÀfÔ)0y2ðx-÷+x ñý"ïáËæE^ê<©ëðùMMM«W¯9rä°aÃ:%6>T0™@¥BI $'Ce%øøÀôé ÓÁ¦MPWl6,_¨ÕPPVV@Ž'¦P 4àr[:2¹ºÂ¦M@¡€qÒÀaÃ`ذÿþQKKxýõÿ ƒÇƒÆ>0³•úà–‡oŒìЙwÅö ­V‹ã¸±˜ÉÊÊ’H$OÛðl …££#$&˜1ðê«/êc.òœ0 Óh4½Ž‡uëà‰‡F!½Vee¥••Õ㦒À°–Î R),Yff `\CÁÚ–/ÿŸ· IŽ^Dµµµ^d…Ö“P© ¦îÜiÉny<˜:–.ýo¡ÕÒÉÄ` ûUo R©¾ùæ''§éÓ§wØ`ÜæfÈ˃†°·rö’  ¬ ¾ø<<ÀÒ  méÍÏbÁ½zœá£þû’F__hÝ8F§ÃÏ·ÓCµŸ“‹äååyxx`výúõ€€ãÜxr¹¼ººº3Ú)p‹ÅVVV0mÚÿŒÈAÿ…ã¸R©dòùðÉ'€Cž@FF†¿¿•=8 (•°w/ØÚ¶Œ¦€'žQ ya &“ÙN‹\B!8:‚¥%Ü»»v«kËhW :nLÒC †C‡Ñh´%K– ~ú   jéŒÒ!ûØ O£ýü’N§/X°@«Õž:u ÇñqãÆM˜0J¥Þ¼ysóæÍ,ëóÏ?`}aaa±âµ×`Ëxÿ}ÔΈ<†N§ƒ;wÌ¡ÕÈ'y ÄBáƒó•—Ö-O3¨y±577»#@ö¼¤ÑÀÌ >ù¼¼  ëAz ²²²]»v-_¾¼ý±Âj547l6ܸ»vA`àûà~ñEKg_¤ãþ=÷ çdnþJ\Üÿ 7AGS©T-óš‹D°z5øùAXJ‘‡iµÚGOÖÔÀ—_‚·7tÂHä#‰îܹ³~ýúGî¡Ñ@UUËÒŒ,] NN-+j=0CÒ9ž( ¾råÊŠ+x<žµµõÕ«WSRR~ýõWŽqq NÂdŠÐ9ÕÌÈ‹„Êb1?ÿ:¡OòB’H$äÔÂpî88À;ï˜:"¤›jhh°µµÐh€J&^z FŒ@9 Ò®“'O†……=reÊÊJøõWÐé`Å `2[–âCºVûI°R©ü믿† öù矛™™]½zõ«¯¾JIIÖz®¸N‚2`äItE' ÑhZª÷¦OGŒÈ£455…††ìÛt:¼ñ  ÙŠv'$$ìØ±ãÁ•¹Â<8!!0u*êóiBí÷4hnnÆq|ĈÖÖÖl6;,,ÌÓÓ³¬¬ÌÔ‘#‚<‹ææf‚\ƒÍ33S‡ƒtSAˆD" P«á ³araiÏ™3gââ⬭­ÿ»‰\V}õjÀq`0àƒ`Ú4`±ÐeBOÔÝ–J¥šýQÁb±ÌÍÍU*•©#Gyjµ:*;Ž5u H·¦Õj¥R©««+Ü»£GCHˆ©#Bz’´´´‰'þ÷5ŽÃ­[-‹c“k\£©º4/‚ ½‹^*åݾ ýeê@nM£Ñ´,³ýú™:¤'¹wï›ÍþŸÉ(P*aùr BU¿ÝÇ%Á8Ž—––’#áT*•B¡¨««KOO7î`†Zé ðº:›ðp4’y…¾¾¦yœ'J‚›››·lÙrñâE—øøxGGGµZ••µk×®óçÏûí·žžž4ÚAîO,v³³£ ¦Žéî4@@#×°E'“›› }ûö…={ÀÏÈ*a¤»z¢$8!!áÌ™3ï¾ûîÔ©Sù|>™ïêõú¤¤¤M›6ýðÃkÖ¬áñx¦>AöÐéû¹Üyh6¤=êêêª**†¡ñLÈ“KMMeɰy³©ÃAÚÑþo[$íÙ³gÖ¬Y³g϶²²2Öø2Œ¡C‡®_¿>))©¸¸ØÔ‚ Ò>)@¦­-êÄ…´‹ÓÔ«ÓA˜:¤Ç0 )))Ñ¡¡pð ,_îiGû5Áuuuz½¾ÿþŒ¶zv{xxxzz¦§§GDD7a˜N§&“i\8› ƒÁ ×ëi4“ÉD=(Àq\§ÓaÆ`0 yUaÜH§ÓÑ¥‚yW!¢õUã¸V«ƒA£ÑÚ¹Tp¼¦¸eÀ/¶Ž*€´wïZôéƒõ¿ÀÈKB§ÓQ©T‹Eýÿ*ÿg.€¤R©V«uïÓ–,SÒ¾öÞ2™ ÇqGGÇ6ÿ/•Je³ÙJ¥²õÆÚÚÚ?ÿüóîÝ»†ÅÅÅÍš5‹|{aaáÞ½{ïß¿ïêêúú믇……Ñh4SŸÄ”T*Õ… Μ9# }}}§L™2xð` ÃÒÓÓÿù矆††àààY³fùøø˜:RÄÄššš:”””ÔÜÜøÖ[oõéÓG«Õ^¼xñСC†EGGÏž=ÛÚÚúqŸRUeµi“­þõB«®®Þµk×Ý»wqŸ5k–ƒƒìÝ»777×ÍÍíõ×_ }|TÌå ú¢¾/®ôôôcÇŽÝ¿ßÂÂbüøñ'N´°°0 d$‰BBBfÍšåííý„(“É|X,6A  ¸§hÿçÍçó©TjUUÑV«^¯—H$­ç –Éd›7o¾wïÞ¼yóæÍ›—œœ¼uëV¥R©Õj׬Y#‹—-[&Ö­[WQQaêÃGL,11qãÆ Xµj‹Åúî»ïîÞ½[QQ±jÕ*ww÷>úH(®[·N¯×›:RÄ”ôzý?ÿüsüøñ©S§~ôÑGb±xýúõÕÕÕׯ_ÿé§ŸFŽ9gΜ›7oþù矃áqT_ßP_ïììlêB: Yåææ¾óÎ;óæÍ»qãÆÖ­[ÕjµF£Yµj•D"Y¶l™ƒƒÃÚµk«ªªÿQyz½ ¥2/®ººº5kÖ477/_¾|üøñ;w©Y¿~ý“@òúzÏ'˜‰©yRí×ûøøX[[?~<""‚Ëå>ðSRRêëëÃÃÃ[***²²²¶nݶ¶¶ ,X²dIAAT*ýâ‹/úö휚šzùòe´Î\/wáÂ…áÇϙ3‡N§ûûû¿û‰‰ ÃÚÚzÁ‚<Çã½÷Þ{ýû÷7u°ˆÉ(•ÊË—/Ï›7ïå—_€ààà±cÇæææž8q"22röìÙ€aد¿þ:eʔǵ(•YÁ&×2E^DeeewïÞݺukpp0XYY-Z´èƒ>¸ÿ~ssóêÕ”Žý€IDAT«ýüüoß¾˜˜8wîÜG~Zm©RÙ£µµ_\·nÝb2™Ÿ~ú©««ktt´B¡8vìØ;ï¼sþüy› XXXXXX|ðÁ™™™ÑÑÑOò™uwîô÷ñ¡ ÕUzŽök‚9Μ9sÒÒÒ¶lÙR\\,“É Ess³P(<|øðÖ­[_zé¥Ö¹,“ÉŒ $_š››ëõz‚ òóóííí]]]€Åb………eee™úðóðð7nÙ(Éb±(ŠÁ`¸wï^pp°¹¹98;;»ººfgg›:RÄ”¨Tjhhh\\ùÒÌÌÌ`0 †ÜÜܘ˜rcHHˆV«m§})&¦<&¦OŸ>¦> ¤³0™Ì/ÍÍÍÉÎÁyyyŽŽŽdÄápBCCÛ)€23c‹‹Ùl¶©é,fffcÆŒ@¡P8Yã{ÿþý~ýúq8pqq999Oø™•wï:O Ž©yROÔåРAK–,Ù¾}ûÕ«W}||X,Žãõõõ%%%£FzçwÌZÍ7Ô·oß5kÖÿ–Édû÷ï'«…B!‹Å"3ƒáââ’’’ÒæŸÓjµuuuöööt4"¡Àq¼±±Q$=Üðü–.]Jþƒ ˆ‹/ÖÕÕÍŸ?ÿÆÁÁÁä·Ïç󭬬•Ù¨Tªšš{{{Z§À0¬®®N&“= ÞÒÒò믿&ÿ­ÑhöïßïäääááQWWgóÿ Ö@¯×‹Åâ6?A"‘…B{{ûr¡…j‚»êêj•JÕá°jÕ*òßR©ôÀ‘‘‘æææB¡Íf“EƒÁééém~BSSSSS¿¸¸ÇíP•ž©étºšššÎè7jÔ(ã¿kkkO:5dȨ©© 7@<¯²²òá·“YR©$³Òu…bÌ´i\4ØÉÈÊÙ§½½?Q–É`0^~ùåèèèk×®¥¥¥) öÙgŸµù¬¬T*ÓÓÓÿýw:¾|ùr‹¶æTï=µZ]TTÔ·o_”wATVVVVVº¹¹uÒŸ(,,<~üxbbâìÙ³cccÞáQ—Š\./((àñx( îôz}QQQCCC‡'ÁÆÏÏÍÍݹsgiiéÊ•+îL…ã8†am¾W(–••YYY©Tª¾}ûšúT!——'•J;éÕJeZZÚï¿ÿÎb±–/_Þ:M1jó®BDmm­P(4“É X,T™œF£ÉËËë¼/B"‘œ?þàÁƒóçÏosŸ6/ ÃJKKÉG,rKQn. ó JäñšššJJJüüüžê]OzaÑh49sæ´Þ®T*wîÜùÒK/µ”­V«7lØpûöíÉ“'Oœ8QðˆÅ™U³ÈçócccÛ¼m!]F£EDD(ŠÎ¸ avãÆï¿ÿÞÑÑñÛo¿ ls¼ö£.GGÇaÆ™ú !-Ølö Aƒ$ µÔëõú={ö8p >>~ñâž¾¾WÑéôGµ_ûûûÇÆÆ655©T*”Ùt#GŽ<}útg|²J¥úî»ïÒÒÒ¦L™2qâÄGƒl³¢P(AAA¹ÍÍz4t»°´´1bÄ;w:ãÃËËË·lÙR]]=kÖ¬1cÆXZZ¶¹[›ƒÁˆm}u±nÞœÊãuÆÝyîîîqqq2™ì©Þõ¼…AssóÆhL‚¥Ré×_­Ñh~ýõW777ã{>>>%%%‰ÄÊÊJ§Óåçç?ù´#È‹êܹsÛ¶mûôÓOl¬ÍíÛ·o]]N§c2™ B¡°õ,ÔH/¤Óé¶oßžššúÝwß“OJ Å××·¢¢‚l=(,,¤ÓéɤV«ÑÔ/6©Tºzõj½^ÿÛo¿¹ºº  >}ú\ºtI*•òù|­V[PPðø¨F.gwB0¤û¨©©Yºti¿~ý¾ùæ333ã¥Òºª¯¯ohh0|xÈ!ÑÑÑZ­–¼T´ZmTTTNNŽT*Åq¼¼¼¼¦¦¦Í>Hï!—ËO:5sæLµZM^*ADFFÞ¼yS¯×cvçÎ.—ûøAoÍÍͦ>¤såå奧§/Z´ÈÚÚºuNŽcÁq\.—gee=¾Òjµ6h~´A‰‰‰ åÍ7ß$‚¼TÈNêÑÑÑYYYr¹ÇñÒÒÒººº'I‚±¦¦;©©¶aa¦>2äét|³`^^žX,ž:uj뉉‰qqqk×®%›6úôéoêÃGL‰|(ºuëÖ?ÿücÜ8wîÜùóç_¼xqùòåÁÁÁ‰‰‰#FŒ@½\EEEmmí§Ÿ~Úzã?ü0cÆŒ•+W._¾œÏç_¿~}þüùä²¢ÓéZâE^ÜÔ! =‡Zͨ¨ÐŒaê8§Ö~Ìårû÷ïoooß †!‚tãjº‚ F«½ïãCCÓ‰ô@íO‘VYY¹zõêû÷ï“/<ˆzA ‚ ‚ŸÕÍ M'ÒµŸk4±X¬ÓéÈ—õõõ?ÿü3J‚AA@¥RK$žžž¦ŽyjO´XA­_â8nê°AAL lj£G…IIhÖמ-r ‚ òLt:,5•ÍbY¡•2z ”#‚ ‚< “à¸=šv¦gjvF¡P¤RiMM ˆD" Ãjkk[χgoo¦ÇCA¤wa³KÆŒ¡§¤˜:äY<ѲÉ8ŽÿôÓO, t:V«}ï½÷Z/¼´mÛ6S ‚ ‚ H¢Ñ( Ô¢gj? vqqYºt©F£yÌ>¨?8‚ ‚ ½N^ž45ÕÙßßÔq Ï¢ý$ØÊÊjZAAä×®‰oß4ÈÔ Ï ŒCAyXv¶ÌÌÌÎÎÎÔ ÏâIû×ÖÖž;wÎ××7,,lùòå)ÿßœB¡XXXìÚµ M ‚ H¯bÐ0™\.×Ô Ïâ‰j‚…BáG}´cÇ…BA„F£‰÷Ýw½½½ÍÌÌ>ùäGGGS‚ ‚ H—2¼õ–€œ9éqÚO‚õzý–-[4ÍîÝ»'L˜@nìÓ§Ï;ï¼ó×_9òܹsz½ÞÔ‚ ‚ Ò¥ ƒL&c2™¦yí'Á•••………o¼ñ†ïCsA›››¿õÖ[………ùùù¦>AA.…ã8“É4333u ȳh? &WǦR©À`0"""¼½½ÉÿËçóíííoß¾mêAAéRÇq”÷P팣Óé E§Ó‘/ÍÌÌÞzë-F¾$ÇqƒÁ`êAAéRåååÖÖÖ¨;DÕ~M° •JÍÍÍÅq( ‡Ã1~ßR©´¬¬ÌÝÝÝÔ‚ ‚ Ò¥„B!Z1·çj? vss ß¿ÿ½{÷0 3n'¢¦¦æ‡~°¶¶ŽŠŠ2õ ‚ ‚t)‘Hdcccê(gÔ~wöÆoܹsgÙ²e“&MŠŠŠ²³³“J¥¹¹¹§NªªªúøãÛœ"M£Ñ¤¦¦FGGûÊ`VPPPPP  †©é.222lllŒM z½>--M$õíÛ×ÇÇÇØýAnܸáïïokkK¾T*•7oÞÄ0,((ÈÅÅ…B¡˜:@¤[P«Õ·nÝêß¿?‡Ã!·`–ŸŸ_XXèâ⊠„TWWWQQcÜ¢×ëoß¾-‹ýýý½½½_566¢šàžë‰ËðôôܱcÇÞ½{/]ºtðàA•JE§Ó-,,|}}?üðè¨(:ýÁÏÁq<99ù÷ß0&Á?ÿüó¿ÿþëââ"‰BCC?üðCKKKSŸÄôêêê¶nÝúÚk¯‘I°\._¿~}AAÝŽ;&Mš4þ|SLj˜A………?üð×_~I&ÁåååkÖ¬Q*•æææÛ·o_¶lÙ!CL&bz8Ž'%%íÚµ+00ИÿôÓO @$………}øá‡¦Ž11 Ãöïß_[[kL‚e2Ùúõë ÉhÊ”)o¿ýöc>A(º¹¹™ú8gôDI0…Bqttüàƒ^}õÕÊÊJ©TÊf³ííí===Û¼‰Ü½{÷ܹs VVVAKKK;6þüW^yåþýû .4hÐСCM}S’H$.\ø÷ß³²²fÍšEnLIIIIIùþûƒ>üË/¿Lš4 -ÈÒËUTTüûï¿çÏŸ—Édä]ÇñcÇŽI¥ÒíÛ·[XXlٲ寿þ åóù¦1¥ìììÿý7!!ÁØ\¥¥¥Ç_¸páÔ©SsrrÞ{ï½!C† 4ÈÔÁ"¦tñ⍤¤Ó§O·¾’““SSSøá‡ÀÀÀìܹs„ )€Øl¶@ 0õ¡ Ïè‰VŒ#Ñh477·øøø &Œ1"$$äQÑ:ŽÏçûøø´Þ˜žžîììbbäÔ"~~~­¯¥›7oÆÅÅ2ŒaÆ ‚›7oš:RÄÄ “Éô÷÷7¶;‘µ}S§Nurrâr¹Ó¦M‹Å………¦Ž11Ngeeõ@tûöm—áÇ3ŒÀÀÀØØXT!:ÎÙÙù6))iàÀþþþ cĈŽŽŽ)))ù 6 6ížë)’à'±`Á‚ØØØÖKJJÌÍÍ­¬¬€Á`xyy=ª¸Âq\§Ó«Ó"B¯×wÒ¢€666¯¿þú«¯¾ÊãñŒ œœÈ{ÖÖÖ666¹T´Z-9o brAèt:ƒÁÐ?^ooï¹sçŽ;ÖØ•Çñââbc?rwww­V[WW×æÛ º«t+Z­¶õHëµ`Á‚þýû·ÞX\\laaA¶0™LOOÏGÝU Zµû óNºÉ?~Á‚ôè-,,tvv&§À²±±±¶¶.**zø½äí®“®aä<ÛM¾S’à6iµZ*•Jv0§R©G"‘´¹§T*½råŠR©ì²ØÇÀ0,-----­ËfƒÖh4t:\œ…Éd2™L©TÚæžuuu/^T(¦>I€F£¹råJaaa—åšZ­Ö˜s8ƒÁð¨ûƽ{÷’’’P‰Õ}œ?¾¶¶¶ËþÜ@AäääÜ»wÏÔ§i!—ËÏŸ?ßÜÜÜe‘,€È!¶L&“Á`´Yéõú¤¤¤®¼†‘Ç+//¿~ýúÓ>Áv]ü°G¸äñxDë¯t4-<<<<<üáá]†Lˆæàà0tèP.—k²³ƒ´Âb±èããcª)(Ê£.ÿ˜˜4ÍH÷1bÄ'''ÐæÅ@¡PLÒš……ÅðáÃM;„±Í» ƒÁˆEƒUºww÷¸¸¸§õ¥ë’`.—‹a™¤c&•Ju¤Ñhfff*Ì.F¡PØl6›Íhiiiìä V«Õjõ£.:nnnŽ.•n‚J¥š™™1™Ì.K‚-,,Ôj5ùo™LÆd25*ŽÅb™™™¡ Ôºssó®|®ær¹Æ~†Éd²GÝUX,‹Å2õéAZÐh´.¾É?Pi4š63]rá04Ñ^÷Á`08ÎÓÞä»î kll¬©©­V›ÔÅç颢¢òòòT*ÔÕÕUWWš:(¤Û¡R©wîÜ!_Þ»wÉdº¸¸˜:.¤; ‰DdãµF£ÉÉÉAÒ¦¨¨¨ÜÜ\ò麦¦¦¶¶@/°®K‚#"" ÃñãÇÅbqbbbiiéˆ#L}øHw4hРâââk×®‰D¢cÇŽ †˜:(¤Û¡ÑhÆ »~ýzVVVyyùÁƒ}|||}}MÒEEEiµÚ'NˆÅâK—.•——>ÜÔA!ÝÑ Aƒ oܸA@8Ž?0Êy‘tbk”³³s¿~ýÈ!–ÀçóW®\ùÛo¿½óÎ;æææK—.íÛ·¯©éÌÌÌÂÃÃ+O¾ÿþû{öìÙ¹s§ƒƒÃªU«ŒÓÝ#½ŸÏ';R(”I“&‰Åâµk×áîîþá‡o8H/'BBBŒ­Õ|>ÿ‹/¾øý÷߯^½Êår—-[†ž—Rß¾}[w·^¼xñßÿýÛo¿9::®Zµª+{"]¬“àQ£F5ªõ–èèhŸÚÚZ;;;S;Ò]‚µk×_ÒéôÉ“'GDDH¥Rwww´ªbb|ÉápþóŸÿŒ3Æ`0¸»»£² 13f̘1cZo‰‰‰éÓ§O]]½½½½½½©Dº‹E‹µ~É`0¦N…  Þ «Çû[[[[[[›ú¨‘ÀÅÅõïDÚE£Ñ¼½½MÒ3ØØØ[œä1PÔK aõ‚ ‚ H¯ƒ’`AA¤×AI0‚ ‚ Òë $AAéuPŒ ‚ ‚ô:( FAAz”#‚ ‚ ½J‚AA^%Á‚ ‚ H¯ƒ’`AA¤×AI0‚ ‚ Òë $AAéuPŒ ‚ ‚ô:( FAAz”#‚ ‚ ½J‚AA^%Á‚ ‚ H¯ƒ’`AA¤×AI0‚ ‚ Òë $AAéuè]ùÇT*ÕíÛ·ïÞ½ëîî>xð`KKK …bê3€t;AÈåòK—. …ˆˆ333S…tG8Ž … .`Ä`0LÒM)•ÊÛ·oß»wÏÃÃcРA¨BÚD„L&»xñ¢H$ GÐ ¬Kk‚¿ýöÛ 64668p`åÊ•‰ÄÔ‡tG‰déÒ¥G‰Dß~ûíÖ­[MÒMåçç/^¼855µ¸¸ø“O>9{ö¬©#Bº¯õë×oÚ´©±±qß¾}_~ù¥T*5uDHwÔØØøÑG8q¢¡¡aýúõ?þø£©#B:Q×Õß½{799ù“O>>|xeeåܹs“’’&Mšdê3€t;‰‰‰ÕÕÕ?ýô“§§ç¥K—Ö­[7}útoooSÇ…t/†:tˆÇãmذÍfÿñÇŒupp0uhH·““““ššúùçŸ:´¼¼üí·ßNNN?~¼©ãBºË—/×ÕÕmß¾ÝÝÝýÂ… ß}÷Ý«¯¾êååeê¸NÑu5ÁwïÞuttŒŒŒ¤Ñh ÿþ©©©¦>|¤;ÊÈÈˆŠŠruu¥Ñhaaa ==ÝÔA!ÝŽã£Fâñx,kĈr¹¼´´ÔÔq!ÝQNNŽ@ ˆˆˆ Ñh...QQQ¨BÚ”‘‘Ñ¿áäätçÎS…t–®K‚KJJÌÍÍù|>0 Ÿüü|SþsIII)++3uí‹Å§OŸ6uO¡°°ÐÑÑ‘Éd€]O¿T<ˆã¸©£h_EEEbb¢©£xRA»ºº’/===µZmmm­©ãz.û÷ï7uO$===''ÇÔQ<…ââb.—Ëãñ€Édz{{÷車J¥:qâ„©£h†a.\ …¦ä)9ºÀÖÖÖÖÖ¶  ÀÔA=»ªªªK—.™:ŠöÉåòcÇŽu}AÙuÝ!0 £P(T*( NW*•ïFDUUÕýû÷ÝÜÜèô.·÷´ÊÊÊ,--mllLH; EYY™L&{¶·“£***¦L™Ò5 *•JŽY¡Ñh4M¥R=¼†a………ßÿ½••U7¿Tîܹ£Óéºÿ(œ¦¦&‘HôÌy$†a555ýû÷1 £Ñhä¿ †aZ­öáÝt:Ý7jjj¬¬¬ºù·žžŽa˜©£h_ee%F{ž<¸¢¢¢+{å>aÔÔÔtåÊ©TjiiÙe±=N———§P(LH;p/((())yæói0JJJ»,æ *•Úf¤ÑhŽ9r÷î]6›Ýe±=‰DR__ßýŸC4M~~¾R©|æ[´J¥*--ªw™2u «ú ˆNŸ?~ë«°Û"ºyÆPŸ'NÇ ‚àp8¦Š¿Í!ÿÖÖÖ+V¬À0¬û_*S¦Léæ’žó’&Çq …bªÁÔT*µÍÇ!OOϯ¿þšÜÁ$=¹^r©ùË5á!´Y¹¸¸lÞ¼Ù˜.wgÏyWïÊ8á¹ï*¦õ¥Í¿ÐýKŸÞ“¨—ÊÓ>“t]Ìçó«««µZ-‹Å2 "‘ÈÉÉéáÝLX‚"Ý„µµµZ­&+ù …B¡ðññyx7*•jnnnê`S²²²2V†‰ÅbƒAv¸zF³°°0u°ˆ)ñùüúúzc$‹Û,€ètz7¯F:›µµµJ¥2@J¥ÒßßÿáÝ šñÐu»ýû÷¯¯¯///­V›––mêÃGº£øøøÌÌL²±²ººº¼¼<**ÊÔA!ÝF‹MJJ"_fff²Ùl4‹Ò¦ØØØÚÚÚŠŠ P«Õééé¨BÚŸ‘‘Av¨¬¬¬ªªŠŒŒ4uPHgéº$¸_¿~æææ»wï.**:pà€\.4h©éŽâââÄbñ±cÇ þùçjê n‡J¥Ž9òÎ; éééûöíëׯŸ»»»©ãBº£~ýú™™™íÙ³‡,€š››hê î(>>^$?~œ,€¬¬¬úõëgê ÎB!û‹tâââ;v ‚Ù³gGEEuÿ~WH×ÃqüÖ­[»ví‰DÁÁÁ³gÏîÓ§©ƒBº#ƒÁpêÔ©cÇŽétº¨¨¨·ß~ÛÊÊÊÔA!ÝTQQÑŽ;ŠŠŠ\\\fÏž‰ äa8ާ¦¦îÚµK,‡„„Ìž=»ÍþxÈ‹¡K“`P*•2™ŒËå¢~WÈãI$µZmmmÝÍÇÞ"¦…ãxcc#ŽãÖÖÖ¨‹òxddaaúˆ#‡  ^¢«“`AA19Ô„ ‚ ‚ô:( FAAz”#‚ ‚ ½mÕªU¦Ž¡›ª¬¬¼wïž›››q‹^¯¿zõjzz:F³²²2Ž,njjJHH(..677·°° —›Ín}IÔÔÔ\ºt©²²’Ïçw`œ( n›Á`ضmÛ½{÷FŽInillüä“O®^½*‘HöîÝ«V«É ´ïÝ»·dÉ’’’’¢¢¢þù' ÀÙÙ¹¨¨èÃ?¼ÿ~EEÅîÝ»½¼¼:6BµZýé§ŸþóÏ?ƒ!==ýŸþñóóMMMŸ~ú)Y|îÝ»W¡P+MÜ¿ÿƒ>(..&ãôóósqq€Ó§O¯X±B"‘¤¦¦&$$„‡‡óxøàƒ¼¼¼²²²þùÇÝÝÝÃÃ.^¼øñÇ755ݾ}ûܹsáááä|^ß|óÍŸþ©T*Ï;wÿþýèèèŽ}©®®^°`Arr²Z­>sæÌ™3g† bnn^XXhŒs÷îÝ®®®žžž˜˜¸téÒÆÆÆôôô³gφ……‘q~÷Ýw;vìP©Tÿþûï½{÷:<ÎAÅÅÅk×® tuu%7Þ¼yóý÷ß‹Å'Nœ ³±±€~øá§Ÿ~R©T/^ÌÈÈˆŠŠâp8úiw ÔÔÔ… –——755íÛ·¯¸¸˜ü–“““ßÿý†††¬¬¬ãLJ††’qþôÓOÛ¶m#ã¼sç§D"ùì³Ï.]º$‘Höïß/—ËѲOÇñ´´´Í›7:Ô¸âŽ;6oÞÜÜÜ|õêÕ”””ÈÈHssóæææåË—Ÿ;wN*•ú(++«ººz÷îÝ|>ßÏÏRRRÞÿýúúú¬¬¬cÇŽ…††Ÿ»ž<ääÉ“üq¿~ý>þøcãÆÃ‡>?22ÒØá„BaqqñŒ3,--mmm§Nš––&—˳²²lmm‡ Æ`0<==xýúuxÄO»c㬩©™5k–­­-ƒÁ}º¥¥¥ÍK/½”žž.—˳³³ù|þðáÙL¦»»ûàÁƒ¯]»FÆ9`À€>}úâè蘚šjêo Ç P(...¬‘yÿþ}‡3jÔ(‹åââ2räHã©ŽŽŽö÷÷g0 ððð ÁÛüiw` …B­V¿öÚk–––fffcÆŒ‰DÍÍ͹¹¹ c̘1,K Œ5êêÕ«dœ #&&ÆËË+99™lµïì‚òF§Ó}}}X(>55µ_¿~ýúõc0‘‘‘}ûö½yó&$''O˜0ÁÁÁÁÌÌlâĉ …"??ÿQ?í R(:88Lœ8‘Åb‘· òRLMM g0áááþþþÆ8ÇïààÀáp&L˜ V«óòò §OŸÎãñlll^~ùåôôt©TÚ!¢$¸ cÆŒ™3gÎI0¹ÐÙâ`ggÇãñŠ‹‹µZmee¥±ß°¯¯oSS“H$*))1.ßêéé©V«…BaÇ9bĈ¥K—’íÑ&??Ÿ ¸°°ÐÙÙ™ìôikkËçó‹ŠŠt:]EE…1Î>}úH$±X\__¯T*Éí~~~ÅÅņ™úèÌÍÍ_z饗_~¹ul0JKKß¾···B¡hhh Û ŒUß¾}ËÊÊt:]qq±¥¥%Ù…ÅbyzztlœóæÍ›>}:Ù‰°¡¡¡ººÚÍÍ Ã°Öqzyy©TªúúúÆÆF‰DÒ:Îòòr­V[RRÂårÉ8™L¦——W‡Çùsvvž1cƘ1cZO¼/‘HD"‘ñ+èÛ·oee¥Z­.++c³ÙäEE§Ó}||ÈSÝæO»cã\¿~}LL QZZJö)”J¥ Ä©R©ÊËËY,'FëÓ§ÏÃqÚØØØØØtxœ/0ÿÙ³gÇÇÇ·ÞXYYI¥R£üüüŒ§ÚÁÁ,¬¬¬òóóõÓîÀ 7oÞlooÿßÇã™™™UUUQ(c;u›qòù|‡‚‚Ç»  |ÅÇÇÏ™3‡ì-`TTTdggGv™µ°°pvv6~ÆSíîîŽaXMMÍ£~ÚdTTÔW_}E>ü †ÜÜ\@@ÆckkkŒS <§››Žã5552™¬¾¾¾uœÕÕÕJ¥²C"¤wηóÒjµ4ì£Í`0h4Zss3Az½Þ8̈Ãáh4F£ÓéŒØl¶Á`P«Õy€ÚÚÚ½{÷^¿~}íÚµÇI§ÓÛŒS«Õj4ƒÁ€ã¸1T‡Cîlê“ݳéõúÖß¾^¯W«ÕL&ðÖ_B¡Àq\§ÓQ©T2C¥R©,K&“ul<äÃŽãÅÅÅ?üðƒT*}íµ×à«”Œ“F£™*ÎÞðNµR©Ä0L¯×S(òTS(6›Mžê6ÚÙMð”””­[·†„„ 80''ç8U*•Á`xò8;¶n©"[猃á8ŽñTÓétrDNg0ä©nó§Ýñp8òRÑëõGݵkל9sÜÝÝu:Éããd2™äö.(({ò××úT“Ï­O5‹ÅÂ0L¥R=| "Ú••9¤¤©©éðáÇúè£ÈxŒqÒh4ã%A^*Æ8q'ïŠ'J‚Ÿ]›£ã©TêÃC¡ÛÜøüT*Õ¥K—vïÞmeeµaÆçŒóQ;#ÏãQ§úQ—„ñÐQ‚Éd{÷î½|ùr``à|`gg÷ðc´ÉãD¨Tj›£ãuª;ü×JDMMÍ/¿üRPP÷ú믷¹¾½ÉãDžêTwF„ãxVVÖ_ýÕÐÐ0{öì—_~¹Ía²&ióT_ð¨ŸöóÐjµ×¯_ß½{7|ùå—±±±Ý*NTŒ=)§Ñhp§R©J¥R«Õ:88Ðh4.—kl>‹Å\.×ÂÂÂÒÒÒ¸Q"‘0™Lã ߎ¢×ëú駤¤¤wÞygèСÆiGˆS£Ñ8::R©ÔÖq666’³¤‘ÕÃjµšl­‹Åè6ô<(Š………ñT755‘ó¼`Æb±T*Ù$‹íííÉÙ²$ ùE ©TêääÔ±!555­^½Z¡P¼ÿþûñññd±ôpœ,‹ÇãÑh´â´³³c0––– :ŽÉd rê.SŸìžÅb±Ùl¥Rinnb±ØÖÖ–ÉdZXXUïL&Çqrö1xÄO»cCÊÏÏ_·n³³ó_|ѯ_?r#“É$ã$b‘HdccÃd2¹\.ŽãZ­–¬°ill|8N•J¥V«h±Ežy…§ÄbqëSaFS«Õ …ÂÛÛûQ?íŒÇñ¤¤¤70à³Ï>3v¨#‹¡'‰ÓÕÕ•B¡tAAÙÛðx<­Vk0ètºV«•Ëåä·ÃãñŒ§Z*•Òét++«Gý´;0ƒÁ°ÿþ#GŽLŸ>}„ d­ð“ÇI£Ñ¬­­q’±‰D"kk뎚›¥;O*&&&;;[«Õ@eeeCCCPP™™Ypp°qxÊíÛ·íííAdd¤qcvv6‡Ã1NŠÔQ®\¹’””´zõêñãÇ3`2ΜœFä`,2ÎcHiii¶¶¶ŽŽŽžžž–––999äöÔÔÔÀÀ@TÃ÷<˜Lfxx¸ñTgff’žÜÜÜììì233Éí)))þþþ,+**ª®®®¦¦T*Uvvöcbžß¾}û¤RéÚµklür FDD„1ά¬,sssWWWGGÇŒŒ cœ}ûöe³Ù‘‘‘õõõdœ&++«ÃãìmœœœÜÝÝÓÒÒÈ—)))>>>æææ¡¡¡R©´¢¢ôz}zz:yªÛüiwlH›7ovww_½zuëf%GGGcœ©©©ÞÞÞ\.744´¹¹¹¼¼0 kçÝ»wÉvíêêêšššG5R!O(((ˆœ‚ƒ|™ššj<Õ¹¹¹ …„Bayy99"ªÍŸvÆS[[ûý÷ßÏš5kéÒ¥Æ  ƒ± xë8óóóÉ® ¥¥¥ýúõ£Ñh]PPö6111EEE‰ÄbqQQù4Û¿㩾ÿ>•JõððxÔO»ã¹sçÎÑ£G?ýôÓY³f3`2Îââ⦦&hjj*,,$㌉‰1Æ™——G„§§§ƒƒƒ——×qZXXtH„(ÝyRƒ :{öìµk×BCC<Èd2#""ètúÀÏŸ?M§Ó<Ø¿ww÷¡C‡îÞ½{øðá<ïÀ}ûö}`çs"g™–H$‡:r乑ÏçüñÇ~üøõë×û÷ïÿ÷ß«Õꨨ(*•Úæ¥Ýñp8œâââû÷ïçååé6~ôÑG½zõ233;uê”……EaaaAA1ü ::úÈ‘#Ä„nÿý·J¥ÒÅùF3Ê(**êÏ?ÿ¼råÊðáÃ/\¸ •J£££`ðàÁüñGzzºµµõ‰'ÜÜÜ|||0 kóÒî¨`0 ËÉÉ©­­ýçŸþûï?Ýöo¿ý6**jÏž=ÿüóÏèÑ£/\¸ ‰ˆÁ ƒÞ½{7QŸxâÄ ¢©oß¾'Ožtuu‹ÅW®\3fLGʼnËx¦êêjGGG]› ­­­M||üßÿÍb±V¬XÁf³Éd²¿¿]]ÝáÇ}||>ûì3&“éåå¥R©8píÚ5—åË—wÔS A¥R•——(ÿqO±±±±³³;räÈ™3g˜LæÊ•+íííÉd²ŸŸŸÏ'âôòò"â$f'¹}ûö±cÇ222&Mš4~üxTüRÔj5Ñ,@Œ]%‘H>>>R©ôàÁƒ×¯_wss[¾|¹‘‘•J »{÷îñãÇräÈ©S§qúûû_»víÈ‘#ÕÕÕ‹/îÓ§ê9óRär¹H$ #†ÏS©Ôððð{÷î?~<--mРA³fÍ"Nu@@ÑÝ¿¼¼|áÂ…‘‘‘d2¹ÍK»Ãkll¬ªªb0­“Ч§gXX؃Ž?žšš;gÎ"ÎÞ½{'&&9r¤¤¤äÓO?ŠŠ"&1`³ÙG=}ú4ƒÁX±b1i?‘H¤V«#""ˆŽt:=000))éÈ‘#ùùùŸ|òÉ€ˆ–bGGÇ“'Ož:uŠD"­\¹ÒÉɉL&·yiw`xÕÕÕb±X«Õ¶N*‘‘‘¶¶¶AAA7oÞ]£Ñœ?^$ž>}ÚÀÀ@ßgy<oñâÅ»wïîÝ»·¾cAº“ŠŠŠ¥K—þñÇ^^^/ûÞ¬¬¬ 6$''ëû 7K*•&''899é;¤¨©©ÉÌÌ>>77÷Ê•+ú> È+Òh4Fß ÝÌ뤥RÉçóõ}ÈWWW·råÊû÷ïë;¤{xðàÁÒ¥KõHWj‚_ŒF£ùøø`–žž~õêÕo¾ùÆÛÛ»¹¹999ùÈ‘#¶¶¶666|ðÁ–-[ 777??ÿСCL&“Éd.Y²dúôé"‘ÜÜÜÞ}÷]ˆŒŒ€Y³f™™™yxxxyy)•JCCCŸqãÆév˜3gމ‰‰¯¯¯«««R©Ô÷i@^L êJ- £W¯^ÄßR©ôÒ¥K©©©¾¾¾ãÇ766&‘HR©ôîÝ»)))vvvï¼ó›Í&“É••• …B$ý÷ßl6{ôèÑÍÍÍ×®]‹Åï½÷ž——Wyy9†a ׯ_wqq9r$ñ·\.Ÿ6mš««+‰DÒ÷™@^N}}}II‰®¹‰Éd)Çq±X|æÌ™¬¬¬ÀÀÀÑ£G³X,‰$‘H’““SSSÝÜÜFekkK&“KKKI$Rssó¿ÿþF|ñ =rww·¶¶Ö÷"¯ŽÃáTTTà8N¼466öððÈÉÉ‘Éd‘‘‘t:ËåZZZ9rdòäÉååå–––/^ …ãÇwqqùûï¿+**bbbbcc¥Riee¥¹¹ùÙ³gårù„ lmmÏŸ?_YYC£Ñô}ÐÈ«ËÉÉijjÒ½´³³³°°(**R(ÙÙÙ¦¦¦4íÑ£GNNN·nÝ"‘HcÇŽÍÊÊJIIQ«Õ111‘‘‘T*µ®®®¾¾žJ¥ž?žÅb;–B¡\¹r¥¶¶vôèÑ}úôéîÙ *·W~~þÂ… gΜ9wî\‰TPP@&“mll€D"ÙÙÙQ©T¨¨¨P*•ï¿ÿ>ñ.¹\.“Ɉ"¬‰‰‰©©©î‰¾Â …x#˜››ŸØB¡èûè‘vÉÏÏß¾};Ñ}¼´´T$;wŽø7lØ`aaafföÝwßeee}÷Ýw$é³Ï>»sçN\\\VVÖÎ;÷íÛ³wïÞsçÎyyy9;;ÇÇÇû ~úé'}%òZnܸqáÂâ︺ºîÛ·ïÖ­[ÍÍÍwïÞíß¿]]Ýúõë`ܸq ,ðöövuu­¨¨Ø·oŸ¯¯/›ÍV©TÄÝÆÐÐðÓO?õñññðð(**Ú·oŸ———½½½D"ùå—_N:5lØ0}4òêöîÝ[]]MüýÏ?ÿ|ôÑG~øazzºT*½q㆟ŸŸV«3gN@@@uuõôéÓÏœ9óÕW_EGGã8þÇ|óÍ7³fͺ|ùò¦M›üýýÝÝÝSSS8`kkëääT]]½sçÎÔÔTooo}èkA…àvëÖ­óóó›;w.Qf¥Óé8ŽëʵZ-ñ7‹Å²³³Û¸q£n»X,&ÊÊÈ[/22òСC8Žs8œO>ùdĈ~~~|}}¿ûî;&“¹oß¾£GŠÅâôôô{÷îíÚµkàÀüñï¿ÿ4mëÖ­žžžûöíûä“OnÞ¼yïÞ½O?ý´¬¬ ¨TêîÝ»íííÝÝÝ7lØpýúõ>}ú¤¤¤,]º´²²‚»ÁƒGEE@qqñ¢E‹ÆŒãééYXXˆaXß¾}×®]Ë`0~úé§›7o*•Ê+W®ýþûïýúõ«®®þè£öïß¿{÷n(,,<þ¼»»{zz:ŽãkÖ¬‘ËåÛ·og³Ùú>JäµLŸ>}âĉp÷îÝòòò÷ßßÃÃcÑ¢EW¯^ýàƒbccO:UWW·|ùò &˜™™ñx<2™lgg7qâÄ¡C‡nß¾¶oß^[[KTèP(”5kÖDGGß¼ysРAÇŸ4iRqqñŒ3òòòP!øí'•Jׯ_¯Õjøásssb£¯¯/FËÏÏÐh4999*• ÜÜÜ0 ³¶¶öôô€+W®œ:u*::ZßtF£ÑÁO?ýäààðÕW_éÆõOš4‰¨vtt$™îܹcbb‚ãxbb"øúú?~œØ¹wïÞDAÖÒÒ’L&%cGGG&“IÜ•BBBlllH$’¥¥%ƒÁˆˆˆgggâÙLß§yi4ÍÔÔ´¡¡áûï¿÷óó[±b1ÿ N7n1¯ˆ£££F£! ›Í–Ëå àíí­D´bËd²¥K—þ÷ß{÷î%j‘nÁ`0Œšššõë×;vÞ¼yOïãææ6xð`+++⥙™YXX…B±´´€¨¨(ƒã¸ƒƒq'±²² !“ÉÄ[úõëÇ`0ŒÙlvë ‘îˆ¸oœ;wn÷îÝ»wï&³Ÿ6iÒ$777pvv¾{÷îáÇCCC—-[¦9çææFŒÍ%RÑOÆÚÚÚÜÜü-H$¨üb<øóÏ?ÇŒCAó}vçλtéÒï¿ÿîîîþœÝ œcccããã‰-•••<eH=Ö_ý•œœ|àÀç×Ú³’;::îܹ“ØRZZÚÜÜL¤œÖFfffëׯüøñĉÏŸ?ÿá‡êû‘×õÓO?UTTœ?þYcI$z}ú,_¾ÜÞÞž˜VßÑP!øQ(;;»Õ«W1¢¡¡!11ñ§Ÿ~Ò- F¡PÐò`=Э[·ˆQØûöí#¶|ñÅD‡Ý§EEE :tùòå^^^€Éd¶ÙÉyëi4𤤤ªª*¢ë±ñÛo¿uqqisÿFEE-^¼ØÃã®®ÎÆÆfêÔ©Ïúp*•:sæÌ3gÎìÙ³g÷îݨ©¡›’Éd×®]ãñx›7oÖm";x¢€G£Ñ4ͽ{÷êëëhjjúĦ¶¶öÎ;4-""ÂÎÎNw'iHˆT§ËºÑEÔ¦Ž/K¥Òï¿ÿ>++kæÌ™Z­öèÑ£ÑÑÑŸþ9Nÿ裔Jå”)Sˆ^~þùg¢5é±×®];qâÄÀÀÀ³gÏr¹ÜíÛ·3™ÌO?ýÔßß¿_¿~§N266ÞµkWw¿ÒסÑhýÆšššƒ:;;;99uñ_!33344TßQ¼‡Ã¡P(¯S.ÉÉÉÑh4OLÁÞQ Å£Gþøã¡P¸jÕªÖëGè´™ñùü={ö+2¾±“×Ôjuaaaן?žhvppxå ¥R™““ãááñÑG½‰%ÉíÛ·9bjjº`Á‚6÷i3*))9zôhPPP‡× u¬¦¦¦úúú®¿¸±B¡(..xå[tSSSaaáСCGŒÑþw½‘B°B¡ØµkWbbâ Aƒ¾øâ bE¾§éåkD"988¼ûî»]ÈBff¦M×Û' ³³³Ÿ³`L{$''¿‰‚&†a÷ïßÿùçŸ ¿úê«ððð6¿¥Í¤B¡P<==çÎû¦N\Ça2™£Fêú-555çuuÔjõ… ÞDżF£ùûï¿ããã~øá‡ÀÀÀ§s&*•Úf 4•J0`À¤I“Þðùë £[LPŸ——G£Ñ|||^ù|éÒ¥7›\.ßµkWRRÒ AƒÞ}÷]WW×6wkó®bjj:hРéÓ§¿‘³Ö¡Ç˜’’2lØ0}òZ­655Õ××÷93¦¿PeeeFFÆ›¯ººú×_ÍËË?~ü¤I“žX×S§Í5_étúôéÓŸ5f×Áãñ?~ܯ_?}ò‰$55uðàÁ¯“Qfee577¿Ô[:¾,‹·mÛVYYùÃ?øùùéjs]\\?~,‰LLLT*UYYÙ³ ÇÝE```¯U"˜ššÆÄÄè;Š¶Ý¼ysÛ¶msçÎ6l˜nr+ww÷††•JE§Ó‚‚‚ôék6lX·H*l6û9k4è‘Z­>|øðÕ«WW¬XIäI$ÉÕÕ•Ëåû<~ü˜J¥¾N^Û¼T†ùúúvÍ$-‹þùçššš~ø¡us¢««+‡Ã!2 ¥RY^^Þ­3 ƒ¸¸8}Gñbd29""¢kvW«¯¯_³fÝŸþimm­ ÒÃã¡¡A­VÓh4>ŸßØØ¦ï`_­­í³ÖìRX,V\\\çßU:¾jª¸¸8!!aõêÕAAA­û3Ct+++@©Tfddt÷ű¨Tj×¼¶Ÿ@&“»lÇ’cÇŽEGGOœ8±õô®}ûö}øð¡T*€êêꪪªîžTètz×,1tèÐk×®mذ!$$äâÅ‹ÄJXúŽyS:¾ܯ_?Ý8nsss2™üùçŸ_ºtéþýû~~~cÆŒéâ#7ÍÐÐpóæÍO Oqqq±²²Ú°aÙ3g222&Mš4hРnQм9ŽŽŽOßU­­­×­[wîܹªªªE‹é¥5 éRú÷ïÿôxSSS2™¼råÊK—.=xð wïÞ£Gîî=g×A¥R§M›6hРÖ‰ÖÖÖº hÊ”)Dw•·XÇ‚=<<<<<Úü/+++Ý2Öbhhø¬áz®®®+V¬Ðw€HWaeeõ¬1@!!!!!!úé*ž“Y[[ÏŸ?_ß"]•J}ÖP‰äææ¶råJ}Ljt†®ØSAAAÞ(TFAAzœn0fAôN©T¶ãŒã¸B¡P(Äv###:®Õj ‰Db2™d2Y­V7666551™LSSÓ§—µS«Õ|>_©TÚÚÚ¶9å á8^__O£ÑºþŠ-‚ ÒÕ BpWT\\Ìãñ¢££»ÅÌ&o+•J•””TYYÉápêëëMLL\]] †X,®­­T*•F£) *•jbb"“É´Z-Žã&&&ŽŽŽUUU E­V“H$sss:Îb±lllˆ"raa!ñccã#F544p¹\6›íîînhhøøñã»wï666úùùùøø<1ç¿P(¼páÂåË—Y,Ö¼yóbbbžN-8Žóù|ƒabbBlQ«Õ†éV”àñxÅÅŽzõj=JÃ0‡£V«årymm­V«õôôttt400xâóE"QVV–X, ´··§R©"‘H à8®ï_AA^àí/cá8.•JµZ­‘‘‘F£©­­­©©)..V*•555ööövvv,‹Á`H$©T*“ÉŒŒŒÚ]aX]]Ý‘#Güýýãââž^sH*•¦¥¥]¸paøðáC† !JJ¥ Žã"‘èöíÛ÷îÝ2dHhhèëyjµÚ«W¯îÛ·N§s8œ &<±„=ŽãB¡033Çñàà`KKKµZÍápø|>›Í¶··×h4eeeW¯^õòòЉ‰±°°P«ÕµµµMMMDüùùù<ÏÓÓsðàÁvvvF.—“ɤÑhÕÕÕ)))EEEîîîC‡544”ËåÅÅÅÁÁÁúþ1;Žãeeer¹ÜÎÎÎÜÜœÏç_¿~===ÝÔÔÔÖÖV¡PäääØÚÚ†††2ÄÉÉ©¶¶¶¶¶–ÃáøûûGDD888Ðét¦Ñh«««MMMq'ذaÃŒŒŒ”J¥\.W(•••J¥’J¥òx<•J5mÚ4*•š}áÂ…ŸÐÜÜ\^^N,Å9`À;;»ÌÌÌ#GލÕj©TŠa˜———J¥âóùÞÞÞ?ÿü³P(ܵk×ùóçííí?~,“ɬ­­åryMM —Ë%‘H†††Dúd2ÙÀÀÀÍÍ­¶¶V"‘ØÛÛïÙ³ÇÚÚÚÝݽ¦¦¦¦¦Ã0FC¥R‰9w™LæÙ³gëëëmmm««« Õjµƒƒq-ôêÕËÔÔôĉT*Çq™Lfllw‘‘‰‰É¡C‡|}}«««Õjµ¡¡¡@ 077—J¥J¥rРA™™™gΜ " FÎÎÎ,K£ÑP(”^½zÅÆÆ–••mÛ¶M.—›ššR(­V‹a˜T*533 ž6mZyyù®]»ˆç‰D¨ï߳ÈD¢‹/ž:uÊÎÎN"‘gÞÇÇgÊ”)†ÕÖÖb6nܸÖó?g})[[[???ÝKGGÇÖ“«š››€»»{›o‹‹{bñ§æææÆÆFGGÇÖóá+•ÊÆÆF ôZmcc£±±±»»;…Bquuݶm[JJ ƒÁ½ºŠP($–/133“J¥jµZ"‘8;;Ïjµº®®Ã0KKË+W®  A¤ë#uµ†KFsáÂ…¨¨¨§çz|!Ç322òóóY,›Í¾zõªB¡Xºt)Q‚‰DD«4…BÑÍü§Õj‰ò†a@&“Éd²D"ùí·ß²³³I$R`` ­­íýû÷›››ÉdògŸ}¦V«/_¾|æÌ6›bffFÔ°Ž;vàÀ†††‰ä?þHMM ;v,‹ÅºuëVuuulllß¾}‰fôììì’’ Ãp'‘H•••ÆÆÆS¦L±··'‘H ?ÿü3ŸÏŒŒìÓ§O}}}ii©F£1b„»»;‰Djll¼{÷®›››¯¯/•JU*•ÅÅņõîÝ›Á`hµZ‡“””æáá¡[‹…8@ât)•JFClÁqÇq Ãh4±ÂŽã*• Ã02™|çÎ33³ÐÐP}'ÿ!úÌ;÷¥ÞÕÜÜœœœ|øðáððð>úˆ¨×,++³²²²µµE¥·×¤V«/\¸cgg§ïXþ§ªªêþýûO¬àƒ}º¾éÒžH*/K&“íQíÜ¿²²2##ã‰Pô.;;[©TvëÅäÞ>YYYÍÍÍ/µ¢ø[’åŵ+W®=zÔÅÅ%**J«Õ–•• ><..N×!’hb~…ByúFoaañå—_VUUY[[oŸ?~UU‹Å²µµ%Þõî»ïŽ1â‰þ :ÆÆÆK–,ùðÃußþDU"“ÉŒŠŠŠŠŠzÖAY[[oܸñ9+îÚÙÙµ¾/Ðh´Ö…T*•êææöœúK‰ôüÛ‰DÒuíšK¤¶1ˆ­¼¼ÜÍÍ­±±ñ»ï¾Ã0lÆ ½zõ"м ãYF"H·@<Á€î^¡{IlQ«ÕYYYææænnnO¯a«P(Ž9’Я_¿©S§ZZZÞ¹sçØ±c4m̘1qqqT*U­V‹Åbsssâårùýû÷ïܹ“™™éàà@£Ñ˜LfIII@@ÀÌ™3>|XZZêëëëããC£ÑD"QZZšP(„ÿ»]———K$’®V~ <‘ž€aØ•+W<==½½½ŸµQ)ÓæiµÚ´´´¿þúkéÒ¥¾¾¾$I©TÞ¿ßÅÅÅÁÁ¨L)//çp8aaa, Çq‡sùòe{{û>}úÿ÷ßÿüó‹ÅÒ}Bë€qojjJLLttt %š¤tÉA:Ü[R...þá‡ììì¶mÛæääÔ!ŸI£ÑZw ¦R©O7g?«L Ó鯹¼»® м ÃnݺõÛo¿Ñét¢È;yòä¡C‡>ÝÜ z$ «««]]]Û|P±X¬Ñhˆ~5OËÌÌ<þ|cc£»»»@ ¨©©‘H$¡¡¡!!!‰ä¯¿þÒh4ÄΦ¦¦ºû1 777$$dóæÍ7nÜX¸p!F³²²zÿý÷5ÍÅ‹÷îÝkjj*ÌÌÌ$‰‰‰‰B¡À0ÌÕÕuÀ€Ë–-ÓŬP(Î;·nÝ:°²²òññùóÏ?ù|¾±±±X,vuu%“É|>ßÊÊ*44”ÃáèûÄw?b±X"‘ñHçáp8§oß¾íl›m†_V7.½y<^JJÊÕ«Wg̘1räȧGª!=–F£9þ66öÛo¿½~ýúÂ… ûôé# ãããW¯^=dÈ]»vÙØØÔÔÔ\½z•Íf/[¶Œ˜G&“©T*2™ìéé’““£R© †Asssqq±Ïüùó‰Þ?ÎÈȰ²²òóó“H$ú>÷=†aºF¤"ÆCc‡žnejý™b±899ÙÇÇÇÅÅ…˜‡ Í=¥RéO?ýTZZõá‡ÚØØ¼0’ÄÄÄýû÷/]ºôª·ºkŸ`©TúÛo¿edd‡„„ÝdõûÛ,99ÙØØ¸{õ >sæÌåË—üñG¢ Ò zrŸ`¢-++‹è¦ommÝúÞMLWWTT”––VXXÈb±œy<^uuuŸ>}Þ}÷]¢»Nvv¶H$"JB¡Ïç«ÕjWW×¾}ûjµÚÛ·o'%%±X¬ØØXb†;1b„•••¾OóËA}‚_Á;w~úé§þýûóx¼ï¿ÿžF£ÕÕÕ%$$¸¸¸„††nܸqË–-ÆÆÆ_ýµ···Íƒär¹‘‘‘T*åñx¿üò ÑÂyýúõ]»vùúúŽ=ÚÓÓ3##ãæÍ›ÞÞÞ³gÏ&úûòùüŠŠŠ¢ú@£Ñäååy{{w~MêÜQ4 qÏ!‘H...¶¶¶Ä#4ŸÏ×MßY^^þèÑ#ݼø$‰Íf·®‘•H$`ðàÁþþþ ¥  `Û¶mMMMcÇŽ8q¢AfffAA ‘ù*Š„„„ÄÄDooo.—khh8tèÐáÇÒJ¥²°°ÐÕÕÕÔÔT¥RíÞ½[,/Y²dïÞ½ýû÷÷óóstt433³²²¢P(r¹¼¡¡ÁÎÎŽhѪ®®^²dÉÔ©SÏ;gee5nÜ8b¾vê~5Á8Ž‹ÅâíÛ·Ëd²ü‘Íf¿f—ä­$“É.\¸°dÉTFÞ(bU‡sìØ±ÆÆÆ°°°„„„ßÿÝÖÖÖØØX$577;99 ‚ÆÆF'''ÿ5kÖè¦þ Ú‚‰üÆÒÒrðàÁÏù®qãÆõ¬D¹ÄÉÉ©oß¾ú>HG"*ÌLLLž®ýR(Gýàƒâââ6oÞ¼oß¾^½zíß¿ßÙÙ9--mçÎr¹|ݺud2yýúõ¿ÿþ;•J}ÿý÷---U*Uss³•••³³3ñi 633#*ÏFM"‘t•yVVV­Ÿ¬¨Tê[6KæÛG£ÑˆÅb…BAô}Â0¬¦¦&++«¾¾Ã0¡PÈãñ ÜÝÝU*ÇÓjµ*•ÊÍÍÍÝÝÏç …B‰Dâîîîïïogg'‹«ªª€B¡à8Îãñ„B¡‘‘1©èÖ­[]]]£££80cÆ 77·£G.[¶ ¨TjHHHaaáÍ›7ËËË]]]©Tª••Õ¦M›¼¼¼$IVVÖ¿ÿþKÔa1Œ³gÏr¹\2™ÍÌÌlΜ9“'Oný`ßþ†) …Šã8Q¿´yóf©Tú¬á¿­Q©Ô±cdž……%%%ÅÅŽNFßÍ ÁÉÉÉ?ýô*#Ï¢R©âããÇŒƒ Ò±pÏËËÛ¹s§ƒƒÃÎ;»T¿g¤ëS*•ñññ±±±ñññaaal6ûСCJ¥rß¾}Ë—/?pà@ppð§Ÿ~·zõj Æ ²uëV6›M,c®+ò’H$¢¶ y‹UWWŸ={6--ÍØØØÜÜ\.—cÐÔÔÄãñÌÍÍþù玚ëe‘Éä×™.ž\Ëd2Ÿnûœowpp˜1cÆkEw*Ëd²Ÿ~úiÖ¬YúŽéŠd2Ybbb|||ttô{ï½×ÎÁ­ò|†ñx¼´´´´´´ªªª ÄÆÆ¢Yö—õèÑ#>Ÿ¿víÚ›7o~ÿý÷C† ÉËËûî»ïŒŒŒÖ­[7oÞ<&“ùÙgŸÑh´ÀÀÀ={ö¨Õj¢&F£¡$÷Ö‹Å.\¸{÷.“ÉÄ0¬±±±ÿþ[·nÕ=ðP(4qjÇêN…àk×®÷ïß_ß ]Ôßÿ’’²dÉ’¨¨(Ôé(7oÞܽ{wppð˜1c‚ƒƒQ Ò~† b„Ù… hjj:nܸ;wîlܸñèÑ£D{Â’%KvìØñÑG©‹D"éF°!=Daaá¶mÛŒŒŒæÍ›GÌgddôjv‘öë…àÊÊÊ­[· …ÂíÛ·£6n¤MR©ôÖ­[«V­B}ãŽRYY¹k×.@°uëV4 #ÒåååºI‘5Í·ß~›””Q\\¼bÅ b™úõë×òÉ'žžžÄ»\]]wìØ¡ïØ‘Î†ãxEEÅ… 222H$Òœ9s „Ú0;S7hœŸŸ¿xñâÞ½{ÿòË/Ýn.L¤Ó‹  ÕRã8—Ëݼy³»»ûöíÛQ i¹\þÙgŸ>}Z«Õ@aaá£GþüóÏààà#G޼÷Þ{º>”&&&º0Òá8®V«¯_¿¾jÕ*‹µråÊ={ö <•€;Y7¨ NLLœ:uê´iÓPâ@žC*•ŠÅb}‚¼ 8ÎêÕ«GÝe×M@º ””SSÓÄÄÄÈÈHÿC‡Mœ8ÑÓÓÓÓÓsêÔ©úŽé*Ôju~~þñãÇëëë7lØ€…Ö£nP‘‘‘¨Œ<_cc£••êA…¼&µZ]XXxèСaƽûî»úé6ÔjurròŒ34Í®]»¦M›Æãñ† ¢ï¸.D¥R%%%?~ÜÐÐpðàÁqqqúªG{ƒ…`¥R™¨›ó¢°°P èvðòòzb²î6•––¢©ˆÞzùùùfffļ*•êÑ£GR©”ø/‰ü™S t#©‘·Øƒ<<<ˆ¹$E"Qqq±J¥"þËÐÐÐÏÏïu–äp8'OžÌÎΞ4iÒ„ ô}¬È«S(> Òµ=zôH(êvhgÔ~B¡ËåÛÚÚÞ¿Á‚ñññ¨ˆÓõÕ××?ñ’XÅW—‘Éä   öOÝõ|‡JNN^¶lYPPZì¶+xS% ò²²~ýõ×­[·êRÏ–-[ªªªt?üòåË_ø”\YYI"‘ìííõ}¢7¨±±q×®]“&M" ÁëÖ­S*•Äìßd2ù×_}á´Þõõõ¾¾¾ú>ä Âq¼ªªjûöí«V­" Á¹¹¹7nÔÍâêêºqãÆW9 ‰V¯^ݧOŸ;v ²K·†aXffæü±uëV]!ø‡~àr¹º‰ÆV¬X1hРüÒ””WWW"å|ðÁžžž}úôÑ÷™@^ðóçÏ—••é Á ëÖ­S©TDû3•Jݽ{÷ëOÖ!•JOž<™™™ùÝwß9;;£Æí.â‚‹ŠŠnÞ¼yñâECCCÇuÛ«««gÍš¥[ÏÍÍí…URRЦ»z[‰D¢äääÿþû/55uüøñÄF¹\.‰¾úê+ÝlA666/ü¨ÂÂÂŽÍÒ.¥¦¦&))éŸþáñxºåˆù|¾‘‘ÑêÕ«‰—L&“•ÿ  Å®]»BBB>ýôS4g·öèÑ£¤¤¤‹/·Î€jjjæÌ™£ëÙž ¨ý4Í7æÎK²gΜ©ï3¼ÀíÛ·ïß¿ìØ±èèhÝF""Vòƒvg@/tìØ±œœœ 6 –í.å‚H$²´´”ËåºÄ#xhh¨ŸŸ´{™òÜÜ\///}Ÿ%äMQ*•\.×ÈȨucSUU•¥¥eŸ>}X,•Jmϳ@ hnnns‘qäí ‘Hø|¾……E}}=±ðÊÊJ77·°°0•Jõšm‹×®]+//ÿõ×_Q ¸»b±ØÒÒR×Ojjjˆ ÈÇLJD"uTÅJssó±cÇÜÜܤR©\. Ó÷Ñ#/¡¶¶V¥R=ÑìSUUemmݧOCCÃvf@ÏG,bš™™¹aÆ)O#è‚£¢¢¢¢¢:tùòeÝF‡ãøåË—:dddôÎ;ïíÝÏ¢T*sssßyç}Ÿ%äM±¶¶þè£JJJrssukjj(ʯ¿þÊçó'L˜ð ª8މ‰ j1x‹ùøøøøøÜºuë‡~ ¶³˜Éåòo¾ù¦¹¹ÙÛÛ{êÔ©fff¯ðáUUUñññ_ý5*¿¢£££££÷ïßõêUÝF/^$ZÆôü ¨=®\¹’ššÊçó ÇŽ‹nAÝ 1òµºººõÆšš2™¼k×®ÆÆF''§ &¼f£ÁÍ›7~øá[[[}1ò¤Î›'˜ËåÕuÑÑÑ8Ž/]ºôÆmîÉçóÏŸ?ßÜÜ, ŒŒ,--õ}–z4µZ˜˜xóæMµZÝ9ßÈápjjj ¢££ ?øàƒÊÊÊ6÷¬¬¬kú3­V[UU…ºÍô4d2922’ø›D"ùúú²ÙìÚÚÚ—ýœ3gÎDFF£0‘·•³³³®*ÎÐÐè°÷ü è…Μ93vìØ×ïSt)½{÷Öýmooüü è9îÝ»§Ñh† ¦ïcBžé%~TF£{ÞÕh4b±Çq&“ÙžùóÔjõÅ‹©T*qËÀq\ 0™ÌçW.–••ùùù½Á'lbŒ9™ *à8É@Ü5P«D*¨TÀqP*[þþ¿Ób1€g@.• Èd`±€L­d2ÐjÁÐh4 ‘@.¥pŒŒ€F­D" ˆ%$P(€J ètÐjA"­4 zÓËd-_Êb‘`47ƒJ$XX• ˆD@¡ƒFF-ŸI‹Õò¥ `É`l d2ˆÅ “±¤gSà8P(Àb… H¥Ôæfño˜\.?|øppppDD‰DÒh4 fffÏIjµZ(vÒ28/•&u©‹B:pÔj : ‰ô¿h´ÿ%0µ4 ÓBiÙA«­ˆÙ P(Z~V]ú$šˆ- Èd@"ƒÄRÒ"hµÿK D&‘ÀÀ ‘@&ûß'q* T™ FF@&ƒBr9`‹R) ÌÌ€D• ©R)´’ÿæ455íÙ³gêÔ©®®® T*›››_vv>ŸŸ››»eË–žU”Á0P*[’‰Z-¨ÕÿK¢ T†‰túÿw‡¤PZîfD‚hI´Dj2èt ‘Zn¡ºÇA¥jI?[é®V«/\¸@§ÓÇŒC&“1 kll|aÔ&‘HD ¥âóù<„{ËÈåòC‡õéÓ'<<\—™››¿B9„ÏçÿùçŸË–-{å)kNЮB°V«ÍËËKII‰ P«Õûöíûï¿ÿ4M``à‡~øÂnã4M.—ÿõ×_,Ë××÷ñãÇgΜ™4iÒó3žŠŠ Ý´Y/€a—ÁÁ ÕBQp8P] #G‚½=46ÂíÛÀã­-L˜*¤¦BNðÞ{àçÕÕpàp8àîk×\½ gÏ…S¦ÀàÁÐÔ¿ür9øúÂ{ï‘dgÃᅢ‰ DG±¬Ô®]PZ ff°x189Áãǰs'Èd0f ŒT*8 Õ—_‚ŸÔÖš5Àb»;,Y4üó$$€¥%Lž ¡¡ÀçÃþýÀçƒ@‡ääÀ?ÿ@S  ãǃB.À£GÐÜ ëÖ½=dfÂÀ`@p0,Xpö,ƒ3g‚—45Áo¿T VVðñÇ`dçÏõk@"Á”)0z4Àöí T› 3g‚¥%Ü¿‰‰X§ÌøÃd2+**nݺõÅ_XYY¥¤¤òóÁÐ/77ÈΆS§€J…€˜5 àȨª&¦MooàráçŸA*…ˆ˜1X,¸v ®^™ –,>}@&ƒß‡‚°²‚¯¿ccHM…«WA*…˜˜2d2øãÈÍ ví&ŠŠ(»w³%j§ÌUÇb±îܹ#>üðC2™|éÒ%bøû{5hµÚ'Nôïß¿ƒg"çñÀظå)´²0 ø|èݘLhjêëÁê«A"‚‚€Å‚œHMpv†~ý@«…sç@&:FSS¨¨€cÇÀÕ¬¬`Ø0ÐhàÚ5ÈΘ2<< ¡Ξ…ÆF02‚%K’“á΀~ý .$ˆ‡Œ °³ƒ+ÀÜrsaÏP«[’(üò ‘,X½{Cm-¬[8AAðÁ`h—.AA¨T0r$ôë*,Zvvàá“'ƒ‘deÁÉ“ ¸qðÎ; —Ãþý— lØææÕÕ–ùùN€F£Éd²}ûö±X,Ÿòòò³gÏN™2åeŸ|¤RéòåËëëëGŽY[[;`À€Ž]nã L£[[ P@ €æfÀ0`2HØéé •‹þþÀb@ØÛƒ—Épí46 vvÐÜ ÿþ `g™ ÙÙPX"DEA` pêýt׬xð®]0bb@.‡óçáñc Ñ`Þ<°²‚ü|¸rT*pub)ò¿ÿ†¢"`0`üxððâãA&GG˜4 X,¸~îß::qÚ&“Y^^~ûöí/¾øÂÒÒ2999;;ûùгœ ,ZQQÀçÚ5`m NNàîL&dfÂõë ÕÂäÉ-…àM›ÀÈ,,ÀË X,06hhh©X%‘ÀÖššZ*ò€Éww02jùH$°¶OOpphùáŒaР––+‚¯/ˉ´Á`Àðá0`ÀÿÚ‹ˆçp ÝÜ“'·Üc‰ -,à³ÏÇÁظå·0úô kÉŠh4øì3`2Áа%9ùøÀGRÙÇC\ÐhÄ—j Uo² Š……Eë%$'MšÄårÿøã ÃÈdòðáÃÇ÷RˆaØ¿ÿþkmm½råÊë×¯çææ~üñǯÑ¢B4žˆDP_2XX€£#¨TžuuPSÓ§ƒ•<|G‚Bžž-·‘S§ ;xK@FŸS IDAT<øøcˆˆ€úzØ´ xÿàÂP*Bðppv¡ @£SÓ–†…ÆÆ–¾IÈ‹‚K—.Í™3§Ó¾Q«ÕÖÔÔÔÖÖÚÚÚ>ëaI$]¾|y:QUùTÀ|ðÁ† Ûû•Àå‡þþàâ"> ¹¹@"ÁÎÀ`ÀÇpñ"ðx0z4Œ ܼ "É0l˜šBCV vv-Ïí •‰66=ä>VYY™‘‘1qâÄNûFFSZZ*‰ž“egg+•ʈˆˆ§ÿK«ÕnÞ¼ÙÞÞ~Ñ®ò¦ …PY \.øø€‡¨Õpñ"46‚@S§‚«+ܽ ÿüл7Lœ ÄÇCAÈdðá‡Ð»7TUÁæÍðÉ'`bW¯¶<) AA TBBH$`dƒƒ—àæáá RAyyKï)gg “A.>¿¥G¨MK{Ñ÷ÒÚX,P*[jyÍÍA÷jéÔ ðÆzq ÝWnnîùóçwìØa`` à㎎@£­-Qª¦ÓáõV¡CÞ.\¸{÷îþýûÛ˜" ¬ Èdps™ .] [ºÀMž “'ÿoO žè}N¡¼Ü([¤;8sæÌ°aÃ^qâRS!/$Ø´ ?ÀÞ¾%ñ˜˜@\ôï66-ã¤#" u…4‰þŸÉd>Ùh ëèBÐuiëy^\633£ÑhDûQrr²n/­V+‘HŒÞмeeðõ×°w/ Ù‹çÀqHKƒýûaß>*ÐÒ”Èsmß¾ý‹/¾p“Ëaùò–±ª/_©Œ¼ÝΜ9sòäI77·ï¿ÿþÉõ33á×_A­†÷Þ7701/¿ zÔL#Èÿ/55µ¾¾¾½cúq*+áÞ=ÈÍ…I“ $Ôj Áϼ¼Zö:† 2¹e˜Šèû(ß/.;99Ÿ:uÊÅÅ…Ïç'''‡……Q(ǵZmJJ —Ëm³[ÌëÂq¸| ‚N™™ 鯔Jˆ‡vÞtO,Éš›###I™™0lDGCç̯‡t78Žïß¿ÿË/¿Œ‰‰i©V(àÎð÷;;pq+ÀÍ­¥¹‰DBÕº=œF£9þü”)S Ÿ¨jm Ã@­†ü| ().ú÷oé<`k OLÄ„ž©Þ¤vÕ/^¼xÍš5D¯_éÓ§S(”œœœ={öܿ֬Yíï¾ùˆy+ß}ÝVJÁÓ:eZ.ä-@IOÿˆÃ¡R©Ð·¯¾cAº´ššKKËÿ³©¬„ï¾&ˆÀ,-Q/p¤µººººº:Ý">mJáðaHK++ðòcc:†Õwà=W»f2 Û³gOVV†aÁÁÁÐÔÔD¡PV¯^=lØ0ƒ7Ñí’N‡eËP y1 ‹–‰–¤5¨§8ÒÕÕÕŽ­ÇîðÎ;0p`™–yY\.×ÌÌŒþÄXb1#©´e¤JPŒ=¶n—Ò®B0…B±¶¶vuumjj"“ÉÄŒz 0`À›•€‘ö@c%‘—ÁãñšQß_¤êêêZ…WW› !!-MØÒ–”””èèè'‡ÄåäÀ¾}``7‹õä”2ˆ^µ«\ZZºaÆššÇ)Ê”)SæÏŸÿ ëh#‚è]Q¿~ÚÂB}Gtµµµ6ææpé\½ ›6µÔä!H[Ôjunnîˆ#þ¿­Äœ!ÆAL j@è‚^\Õh4{÷îmhhøðÃmll._¾¼gÏž¼Î,z‚ úÒ •RPC$Ò\.w• çÏÃΨŒ<_^^ž71#¯Ž¡!|õ•¾CCžéÅ…`@PVV6kÖ,b¥u77·ÒÒÒÜÜ\TF¤›Q«aëV>†¹öî­ïP®N«ÕÖÕÕÙÏŸÓ§Ã3–8E†a))) øß,"›6ÁСð2«—!ïÅSo`F£Ñ\\\ˆ®ÀæææVVVµµµúŽAä%ÕÔ@NŽ˜D2CkL"/"•Je2™‘—xxè;¤«“J¥999!D—q­Nž• BCõò/ݯ—D"‘Ѭu‚tG••ЫWuu5«ÓçDº©Tê¯P(úé°Ùl±„BX·M@Þõµ·8‹ã8†a†á8Þúeë‚ ]Z¯^0¾F£yÞTö˜D——g Ñè;¤P(ÆÆÆ†††€ã`j Ë–¡p·Ð®š`…BñÛo¿9r0 +,,¬®®ÎËËÓí°nݺÿo2EA.ÈÆ Å›Zéy‹°D" Ž™™¡©:‘âp8VVV4µ’’ 6ž˜*éª^\L§ÓýüüètºB¡P(*•ÊÃÃÃÖÖVÑ ª F¤» …¨;òBbµºÂÏG¥¤„B¡­­-df‰ Õê;¤½^\laañÝwßé;NAÀçó-,,ôÒÕ=äóyQQT4›ÒÕÕÕ...gæîFÚ;0𦦦ÂÂÂÌÌ̆†ww÷ˆˆkkkZ¬ An¢ºººe 0y “p8–––úŽéD"‘¹¹9|ü1ôê¥ïX—ЮB°V«½wïÞo¿ý–™™éäädii©T*ÿúë/“Ù³gÏ;­‡ H·ÀápœœœôÒåñx®gÎW¬ÐwH÷ lmmÁÏOß /§]…×üüü¯¾úÊÕÕuïÞ½ÞÞÞt:Ã0@pøðáøøx­V;wî\j3B¤ËvvvúŽéòÒÓù*•…©©¾ã@ºAq±ui)øø ¤ìN^<0N©TþùçŸööö›7oމ‰±±±133³°°ðôô\»víÔ©S=ZWW§ïAy1.—kcc£ï(.¯¦&ƒFCÝ!ö.<žuA Uº›ÿ`••••••3fÌh™ºƒ÷Þ{Á`Ü»wOß‚ òbåååÎÎÎúŽéê´óçç™™ÙÚÚê;¤ …‘ÆÆàã$’¾cA^΋ ÁõõõjµÚÝÝÔÖ¯k```kkËápžþ/¹\þßÿI¥RÝ­VûðáÃcǎݾ}[¥RéûØ‘.$--­¬¬L÷R­Vß¼yóĉyyy4Y=ÒÊ7Z7=‰Åâ‹/ž={¶¢¢ðç¿W©T …B}òÆÉd²«W¯Êd2Ý­V›}ìØ±;wî¨Õê翽®© '“ÑòÚ=Auuurrrë-jµ:11ñĉùùùÚvÌwÆçóŽŽÐ§¾yi/.P(¥RÙæÿâ8®V«ŸîŒaXbbâ¾}û$‰nã–-[V¬XqïÞ½­[·®Y³¦©©I߇t gÛ¶m%%%Ä˦¦¦eË–íܹ355õóÏ?ß¹s§¾DºÇsrrvîÜY[[Kl)))yÿý÷OžøàÚµkÏÿ±XŒã¸¾y³0 KHHØ¿ëZ˜ï¿ÿþ‹/¾¸wïÞO?ý´víÚæææç|BCCƒ···¾yã4Í¡C‡Î;§Û" —,Y²{÷îÔÔÔÏ>ûl÷îÝ/ü±XÌ ÔÄÔ ½x`œ½½=FKKKó÷÷§<Õã›Ïç—––~øá‡­7fdd\¸páÖ­[VVVºEEEׯ__²dÉèÑ£‰·Ü»woøðáú>ˆ> ‚óçÏ_½zµ°°P·1%%¥°°ð—_~ñññ¹téÒöíÛß{ï=4¢¿‡+//?þ|BB‚®nð3gÎP(”;v°X¬_ýõèÑ£áááÏéÇ)‰ŒÑZ¦o»\¼x199¹ug†Â„„„Ï>ûläÈ‘EEEŸ|òÉýû÷‡ ò¬©­­577×÷¡ oÖ¥K—nݺuãÆØØXÝÆ[·n•””ìܹÓËËëÂ… »víš4iÒó×Ä•45Y™˜èûhWñâš`{{û=zôÖ­[­Ûp¯®®Þ²eK¯^½‚‚‚Z¿…F£y{{´Þ˜••Åf³û÷ïO£ÑÜÝÝ£¢¢RRRô}øˆž‘H$33³ÈÈHÓV£°ïÝ»éååE£Ñ¢££ÒÒÒô)¢gd2ÙÞÞ¾oß¾º‰ÉµZmzzúèÑ£­­­ Ç'tí m’Édh™Œ·^›Pff¦££cLL FóôôŒˆˆx~T[[‹ž—Þz†††AAAOôJKKëׯŸ§§'F‹‰‰a³Ù/õÀ娮Ö÷Ñ ¯¢]S¤Í˜1£´´tóæÍýúõëÛ·¯¡¡¡V«-//¿råŠ\._¿~ýùJ````` F£¹|ù²ncYY‹Å"ºXÑh47nèûð=377Ÿ8qbIIÉõë×u‹‹‹ @§ÓÀÒÒÒÚÚº¨¨Hß‘"zæêêêêêzëÖ-]†„ãxII‰.suuU©T<ï9"“ÉHhäÊÛ.(((((H©T^½zU·±´´ÔÈȈxئÓéîîî·nÝz·Ô××ûøøèûP7kðàÁðD·¸¸xÈ!Äö¥¥¥……Eqqñs>D«Ñ˜ÔÖš†…éûhWÑ®B°Í¦M›Îœ9“páÂ¥RI&“ÙlvttôÔ©SýýýÛó!jµšL&*Èd2ƒÁ‰DmîÙÔÔ”’’2fÌ‹¥ïóƒ€F£yøðaffftttç|£J¥¢P(Da…J¥R©T±XÜæžuuu‰‰‰ááá¨Î¦+P(wïÞ---íׯ_ç|£Z­Ö­ÔÃ`04\.osÏGݽ{W*•š¢™_»†„„.—Ûi_×Î Çñüüü¼¼>>J­ö¨¹ùBË]!"VVV¾¾¾/›û¼ÄÓ•Jµ´´tqqqwwwssc³ÙB¡pÞ¼ymN‘öFCÌŒ¦ÕjÁÓh4š¥¥%Zй‹ ºíš™™uZÉÆÌÌL¡PÓ]Éd2©Tú¬¤Â`0¬­­QRé"(Š¥¥%‹Åê´¤bbb¢'' i4Ú³æ´266¶°° @½³¶¶îÌRfë H£Ñ…ÂgÝUŒMLLŒŒŒÐ¥+ R©|“oI¥R™LÖfR!“ÉæææL&ÐSQ]Œ¾ZXX¼l£Áë61hµZמ™\Èâ²R©ÌÌÌ ÑßéBº®ÈÈȼ¼}º¾¾þÊ•+ÕÕÕqqqú>|¤+Љ‰©¨¨¸qãFmmí©S§H$Rß¾}õÒåÉäAƒݹsçþýû¥¥¥'NœðöööððÐw\HWJÌ©W__ÿï¿ÿr¹\”!mЉ‰yüøqBB‘Q©ÔðððçìO¹}ÛM©D…ànê 61¸ººöë×O—2Œ¿ûî»_ýuþüùÖÖÖëׯ÷õõÕ÷á#]‚‘‘Ñ€ìì숗~~~k×®=pàÀþýû½¼¼¶lÙ‚:ˆ#kkë}H$Ò¸qã¤Ré?ü Õj–,Y¢›@ éáÜÜÜ¢¢¢t·“ï¾ûî·ß~›?¾ÍúõëQïp„Úº ½wïÞ«W¯>xðàŸþéííýÃ?}úY+L¶^”²=LMMÑEH{ØÚÚ¶^ð AÚD¡PÐj‚H;c|õÒ ´?*ðò2­¯×w¼È+zq!˜Ïç'''744ž`´2‚ ‚ Ò¼¸lee5nÜ8}lj ‚ ‚ æÅ…`ŠŠ *•jeeõï¿ÿ>~ü¸õÍž=ÛÚÚZßÇ‚ ‚ ‚ íÒ®B°T*=pàÀùóç?þøã¡C‡þóÏ?eeefff\.W¥R 2¤õD‚ ‚ ÒŵkŠ´þùçàÁƒÃ‡ïׯ±eÒ¤Iظq£‡‡G¿~ý,,,ô} ‚ ‚ Ò^/® nhh8yòäÔ©S—,Yb``ÐÔÔDl·°°>|¸¥¥åÚµk===õ},‚ ‚ Ò./® æñx*•jàÀ@"‘Èd2™L&þööö655½ÿ¾¾AAAÚëÅ5Áb±X«Õš››/ŒŒ¾ùæƒA¼$“É ƒÇãéû@AA¤½^\lllL&“y<1úB¡ØÛÛ[ZZÿ«V«E"‹ÅÒ÷ ‚ ‚ H{½¸ìééimm}þüy™LöÄiµÚ7nTWWëÌ!‚ ‚ H×÷â†S¦Lùæ›o~üñGb>`:®V«%ÉåË—Oœ81vìXww÷ö|™X,V«Õº—,K×­At0 #:á趘ššR(}Ç…t9jµZ*•bF¼¤P(DË•¾ãBº"”!í2 ¥]ó4H"‘ìÛ·ïÆ½zõ²°°‰Deee`̘1Ÿ~úi;»Clß¾½  @÷ò“O>‰Õ÷@º@ðí·ßê:š“Éä-[¶8::ê;.¤Ë),,ܹs§X,&^:99­^½Í؈´iëÖ­………º— .ìß¿¿¾ƒBºœÆÆÆo¿ý¶¶¶–xI¥RüñG}Ç…¼í*Óéô &ôë×/555==Ãᘘ˜Œ3&66ÖÇÇÇÐа_–––èââB¼´³³Ó÷á#]‘D"ÉÌÌ;v,ñpE"‘P§s¤M§²²r„ ÄK T·‡ßÄÄdþüù¨JyÇy<ž——×'Ÿ|¢ïX®®¹¹Çñ©S§é;¤Kkhh055}ÿý÷ÍÌÌô òƵ·üú¸\.•Jåp8 Ã×××ÆÆ†D"éû ]‡Ãa±X>”ËåVVVÞÞÞèf„< Çñšš&“y÷îݦ¦&{{{___b:syBMM F«ªªª««CòÇÈÈ(;;[&“Y[[‹!è;(äMé¼B0Ç«¯¯ß³g½½}YY™‡‡Çºuët-S­577ß½{wÔ¨Q¨ ¢+Ðjµ¹¹¹ÙÙÙ6—Ë}üøñ®]»ÌÌÌŠ‹‹###¿ûî;:þôžõõõ·nÝêÓ§ê/Ñ(•Ê´´´òòòÎI*†q¹Ü‚‚‚šš¨®®ž={ö¼yó¨Ô6nkEEEééé}úôA\ºˆ›7oêº]v]Äf³ËÊÊ<==×­[çääôÄn8Ž?zô¨°°Ð××Wßg‹ÅIIIù¸ÂårËÊÊvîÜId@ÑÑÑ›6mz:R«Õééé...¨cgÁápîÝ»çááñRïê¼aÔ4mòäÉÜ·oß¹sç ÅÎ;ÛÜ“Á`899Ñh´N‹ y‰dggggg×iƒî-,,>øàƒ£G8pà?þÈËË;yòd›{²X,”Tº …âäädnnÞ99‰DòððøüóÏ?~ôèÑuëÖ?~<55µÍ---PÍ_×áææfddÔi_G£Ñ¦NJd@ÿý·T*ݽ{÷Ó»‘H$++++++}Ÿ¤Nwuum³ä ±´´\°`Á±cÇ8ðûï¿?|øðôéÓOïF&“:3 #Ïgbbâèèø²ÕWÜ¿ÝP\SSÓQ£F?~\­V?]‚100@…ஃL&…àN+@L›6M÷·¯¯oxxxnn®V«}:q…`}Ÿ!¤•JíÌB0…BY¹r%ñ7™LŽ‹‹ûõ×_?~ótVVVh|w—âêêš››Ûi_7`À€›››9òÌ™3mf@ÖÖÖ¨Üu0 WW×ÆÆÆNûÆ3fèþöóó m3¢P(¨Ü¥˜šš:88477¿Ô»:©nhR×MOC"‘˜L&•JE3ÈT*Õ½{÷ˆn P(L&ÍüŠ!!!  ÍÞ{HOF¡P>|ðàA¡P¨P(=z”‘‘†ºr"OÛ¼yó¿ÿþ+•Je2ÙÝ»wÅb±——*Ù O “É7oÞܶm—ËU(uuu (Bž@¡P:tèС¦¦&…BQPP™™‰2 ·X'ÝÈdò¸qãîÞ½»|ùrWW×êêjX¶l™¾ér(ÊôéÓ¿ýöÛªª*ssóG9;;5Jßq!]ŽÁ¬Y³8––F&“ ÆŽ¬ï¸.‡L&?þÎ;Ë—/wqqáp8d2yÅŠúŽ érˆ èû￯¬¬433+((pww1b„¾ãBÞ”Î{vqqùå—_222ÊÊÊ¢££cbbмWH›¢¢¢öîÝ{çÎ>Ÿ?vìØÀÀ@4Oò42™ÒeggoݺuÁ‚/^ìÕ«×W_}%‰ôÒåà8~úôéË—/oÙ²%>>ð-[¶Èår}Ç…tEDzéÒ¥9sæüøãyyyú éŠ222¶oßþñÇ_¼xÑÛÛû믿FÐ[¬ó Á<011™8q"“É0`€——×íÛ·õ}øHW”’’Ø¿&“9qâDƒè;(¤ËÑjµ·nÝ:thïÞ½­­­§NZYYY^^®ï¸®(==ÝÜÜ|„ L&3..ÎÃÃe@H›ˆ (&&†È€h4ZFF†¾ƒBÞ”Î+XZZÚÛÛƒÁèÝ»wvv¶¾ÿµp8¡P¨ï(^L*•ê;Š—››ëããchhvvvöööÝ½Ñ 77Çq}GñbMMMݨ‰aX^^^HHñÒÏÏO¡PTVVê;®×’““£ïÚ¥¦¦¦¶¶VßQ¼„üü|kkk6› oE¤V«=z¤ï(^ ð’’‰D¢ï@^Bnnn¯^½˜L&°Ùl;;»ÜÜ\}õêš››ËÊÊôÅ‹)Š‚‚‚ÎÏ(;¯O°H$¢R©t:(Š……E]]ÝÓ»á8®P(¸\.tñ1.÷ïßg³Ù®®®úäø|~jjª©©é+‚F£áóù,«snjj200 Æ"²X¬úúú§wÃq\&“UUUQ©Ô.žT,,,ºþèŠÊÊʲ²2âîÿjäryss3†a°H$"–ÀÜÜ\£Ñ477?½ŽãMMMUUU]¿è7¬­­õÅ‹eff2Œ×ɱ:³lÔ:¢R©æææmf@F(VWWwñasr¹<99ÙÌÌLß¼€V«½sçNpp°­­í«}Žã\.W©TvZÌ­3 ‹ehhØfRÁ0¬®®®¦¦¦‹ßØ9NQQ‘î>Ùe‰D¢›7oš™™½rnNü"/{“ïÔqOGüôF2™Ìf³srrªªªºømÇñÚÚÚ6Ëg] Žãæææééé¯üv‰D¢Ñh,--õum&:nooŸ˜˜hbbÒœн½}·èÑaƒÁx夂aXss3“ÉÔ× Çñ6‹e,‹N§'%%½Î£`çptt|åóß™4Z­~Pù|þ+Œ:D›wFÃ`0nݺÕiÏü¯ÌÒÒ²[$##£ŠŠŠWn¢Ñjµ>>>z<„6ï*–––™™™wîÜa0zŒí…0 c2™]?©à8nccsÿþýWþ…B!‘H¢¢¢^ê]W¦Ñh†iµZ …‚a˜R©´²²zz7 …2hРN‹ é‚ètºV«ÅqœD"i4FCô¢y‚‘‘Ñøñãõ,¢O4M£Ñ+•J:nllüônVVV³fÍÒw°ˆ>µ3²±±ùàƒô,¢O­3 µZ­ÕjÛ¬rqqAIå-ÐyÕø¾¾¾b±¸±±ÔjuQQ‘›››¾éŠüýý9ÑþÕÐÐPWW×õûœ L&ûùù•––/KJJ(J·èK€t¾^½z577 P©TÅÅÅ(BÚäïï_UU¥R© ¾¾¾¾¾e@o±Î+GFF655¥¤¤Èd²¢¢¢ŒŒŒQ£Féûð‘®(...;;»°°P*•Þ¾}»¾¾~È!ú érÈdòÀ¯_¿Îãñ„BáåË—Ùlv@@€¾ãBº¢¨¨¨ÆÆÆÛ·oËd²Geff¢ iÓÀ333‹‹‹¥RiJJJcc#j~‹u^w‡I“&íÙ³çúõëgàÀ(»BÚñõ×_³Ù슊Š3f˜››ë;(¤Ë!“Éï¼ó΃–.]Êd2y<ÞW_}Õõ»r"záèè8iÒ¤ß~ûíêÕ«gÈ!þþþú éŠÂÃÃÃÃÃ×®]kgg÷øñc”½ÝH‰Dj½°§.I´¾úp‹Åõõõjµºõ©~Ö¥ÝT*U}}½@ ÀqœÁ`è¾B—$Ú'ŸÏ£q¾Ýp¯««{âê‹Å J¥’Éd¶>ÕÄïÕúTwBD$ݦ¦&2™¬»û+ŒqêÖoœo7¥R) [' @ 0 k}ª5M]]X,&“É4íù—vÒÝ%Äb1N§R©º8…BaccãqjµÚºº:‘HD¡PÚŒ“F£é>äõésÙä.îæÍ›ùùù_|ññR­V_¿~ý¯¿þjnnîÕ«×ûï¿ïçç‰äСCׯ_'“É!!!Ë–-311‘Éd§Nºpá†aAAA‹-zS$$$œ:uêñãÇ,kðàÁ³gÏ633S«Õ ñññMMM¾¾¾óçÏïÝ»7g||üÕ«W‰8—.]J,!ËårwíÚ•››kdd4nܸwß}·‹/ÙÕh4šøøx—wÞy‡Ø"•J?~ùòe Z²d ±àPCCÃŽ;rrr G5uêTxðàÁÁƒ?~lgg7wîܘ˜˜Ž½)•Ê3gÎüóÏ?uuu¶¶¶#GŽœ9s&‰D’Éd'Nœ¸xñ"ŽãÁÁÁ‹-"ÆAóùü;v<|øÐÐÐpĈÓ§O'âÌÌÌš óeI$’o¾ùfÍš5NNNÄ–¢¢¢?þø£°°ÐÌÌlöìÙC† !–KLJJŠçóùžžžóæÍ ~Υݪ««wîÜùèÑ#•Jåëë»páBbÂââb"NSSÓ™3g6ŒF£iµÚäääÇ744xxxÌ›7/$$„ˆ³2Ê·[NNÎÙ³g¿ùæ:†¥¤¤>|¸¶¶ÖÕÕuîܹaaad2Y.—Ÿ;wîôéÓZ­600ð“O>qpp€g_Ú(##cÿþý?¦P(111óæÍ³³³Ã0ìöíÛ‡ær¹...óæÍ 'â<þüéÓ§5M@@À'Ÿ|âèèÍÍÍ;vìxðàƒÁˆ‹‹{ÿý÷;,NyJEEEJJÊ AƒV®\©Û˜žž>`À€Ó§Os8œ/¾øbòäÉR©T£ÑìÝ»wܸqwîÜÉÎΞ6mÚ–-[”JåñãLJž””TPP0oÞ¼µk×*ŠŽ ²¤¤dàÀ›7o®©©IJJ1bÄ?þˆãøƒbccOœ8ÁápV­Zõî»ïqîÛ·oìØ±·oß~øðáôéÓøá¥R)•J—.]úÑGܸqcøðá/^Ä0Lß¿@÷ R©JJJŽ?yôèQb£V«ý믿FuëÖ­¼¼¼Ù³goذA©TÊd²/¾øâý÷ßÏËË»yóæ¨Q£Îœ9£Õj›šš† ¶iÓ&‡sðàÁ!C†ûlÚ´i<O,Ïœ9óóÏ?///¿|ùòÀSRRp/**Š‹‹Û¿?‡ÃùöÛoGÝÔÔ„aX'd”o1.—›ššúî»ïΛ7OwÞ***âââ~ûí7‡óóÏ?9²®®Çñ³gÏ<8!!¡¨¨hÁ‚Ÿþ¹B¡xÖ¥ÝAr8œñãÇùå—eee<˜4iÒÒ¥K‰íqqq»víâp8Û¶m1bÇÃqüüùóƒ ºqãFqqñG}´lÙ2¹\®P(6oÞ|(“É’““GŒ8mÚ´´´4.—[^^^ZZ:{öì^½z <8<<üÆjµZß¿@÷ ‘HöíÛ/•JuU*Ubbâ Aƒú÷ïïïï?}úô¬¬,‡SYY™ŸŸ?{ölÿ¸¸¸èèè„„…B‘––Æ`0f̘áèè8qâDKKËÛ·owlœ©©©QQQãÆ³µµ6mZxxxRRQ­8pàÀøùùMŸ>ýáÇUUUUUU999³gÏîÝ»wlllÿþýäryzz:•J9s¦££ã„ ¬¬¬RRRôý tUUU¿þúë¿ÿþK¬ÅJàr¹ééé³gÏ Љ‰2dHbb¢D"ÉÈÈÐjµ³gÏvrrzçwìíí“““á—vÇÆyçÎÉ“'ÇÄÄ899-^¼˜L&çååñx¼ôôô™3gGGG:411Q,gffªÕêY³f9;;;ÖÁÁ¸ݼyÓÃÃcìØ±ŽŽŽ3gΔÉdYYYúþº¬¬¬íÛ·ß»w¯õÆœœ‘H4kÖ,WW×1cƸ¹¹%&&@rr²³³óøñã§OŸ®Õj322žuiw`Ÿ~úipp°ÏgŸ}VPPP__Ÿ››ÛÔÔ4{öl77·Ñ£G{xx$$$q:88qN›6 ðh4šNÈ(ßbW®\Ùºuë¿lJJŠ­­í¤I“§L™B¥RÓÓÓàÚµkýúõ4h··÷Ì™3‹‹‹ËÊÊžuiw`%%%jµú“O>qwwïÓ§Ïüùó‰»YJJеµõ{ï½GÄI§Ó‰4ýúõÈÈÈÁƒ{yyÍœ9³´´´¬¬¬®®îÞ½{Ó§O éׯßðáÃoÞ¼)‰:$BTnÃòåËO:ÞzcvvvPPÑUÀÉÉÉÆÆæáÇr¹¼¸¸¸oß¾Ä>áááuuuÕÕÕ¹¹¹º2™¬Ã¯m;;»3fè0 #ºÎq-ŽŽŽ¶¶¶D]Naa¡.¤°°°††Çáp¤RiPP±=""âáÇFß¿@÷`fföí·ßîÝ»×ÃÃC·Q­VçççëNuHHHsssUUÇ¡¡¡Äöˆˆˆüü|¥R™››koooooL&3000##£cãô÷÷Ÿ}º³³3ñ’hg&âôôô´°° öñöö~:Î^½zá8^ZZÚØØøtœ¨üQ( …òDýÆÆF‹Etó711a2™uuuZ­¶¹¹™¸€D"‹ÅB¡P·ÑÚÚZ¥R555ul111ãÆ#î>………çÏŸ9r$§¡¡!§±±1‹Åª­­}:N©T*‹¥R©J¥Ò­4Ëf³ëêê0 Ó÷/Ð=H$ …¢ùAÀ0¬©©Iwªmll”J¥H$’Éd …ÂÈȈØÎf³ëëë5@  ÓéÄÃF³²²âñxç¤I“ˆÛ‡Z­¾víZvvöˆ#poJ‰8›››e2™\.o'1œN(Òh4"N*•jmmÝáq¾ÅÚL* …B&“é~6›ÝØØHÜ+( Ñ›B¡ØÚÚ§ºÍK»cãüôÓO]\\p'†ÐéôçÄI&“‰8ÉdòqýÚŒŒPRi?2™ütR!ò{Ýs,›Íær¹ðÿŸj‹ejjJ´)·yiw`vvvŸ~ú©Žãõõõ{öìéÓ§›Í&¾åYqCžçÊ(ßbDRyº Âd2‰¡·L&ÓÜÜœ¸úîT[YYƒçžuiw`AAAÓ§O'‘H†UVV=z”(µ·ŽÓÀÀ@gcc£.KKKlj8¥Réq*•ʉkyum1 {z;Žão¨dÉår;võêÕ1cÆÌ™3ç5ã|ÖÎÈëxÙS­ÕjßD¹¹¹'OžÌÈÈøè£ú÷ïߺ áY©´“ãìÉ^öT¿‰«U«ÕÞ¾}ûèÑ£uuukÖ¬ñõõ}ºŽ®:GqöpÏ:ÕmnCD"¹uëÖž={,--7nÜheeÕ5ãìá^êT?ëÒ~M Äp·èèèE‹½~œDwÞ‰ ‚Û‹B¡部|Åqœ˜]L&ë~$µZÍd2 ˆ‰†N§·žj­Cà8žžžþÛo¿±X¬õë×÷éÓ‡xþ¦P(Dúx~œL&S&“hDŃF£155E“Ô¼¦Ö§Z£Ñ0 CCCâ$kµZ¢ÚF­V›˜˜òÄuN&“q×jµ­[Ì;„J¥ºråÊÑ£GÝÝÝwìØáîîNüÄm¦R2™üDœÆÆÆDÛÈ›Ž³§!“ÉÄEª;ÕFFFT*•8úS­ÑhˆSý¬K»I$’#GŽü÷ß±±±ëÖ­c³Ù@"‘ž'¼0N Ã:<Ξ¦õ©€Ö§Z—+a¦ÕjÍÌÌà—vÆCTâþøã%%%Ä"ÄìD é:qö@í<ÕT*ÕÈÈèY—vƃãxqqñÖ­[ÕjõŠ+úõëG43>+N*•úœ8‰íjµšÅbuTœ¨;D{ùûûs8¢¿lmm­@ pqq100pww/++#öÉËË355µ²²òññ)//'6Óh´Ÿ¡¦¬¬lóæÍaaa;v숉‰Ñµ@ùûûWUUƒÛêêê\]] †‡‡‡.Îüü|sss6›mddÄápˆí>tqqAS¿*•êíí­ûõ=zd```iiicccnn®ëñ–““ãèèH£Ñ|}}›ššˆF@…BQ\\ìîîÞ±!¥¤¤üúë¯óçÏß¼y³¯¯/1“…BigQQƒÁ°²²²¶¶¶°°¨¨¨x"N‘HDŒU*•………gOcaaagg§û rrrìíí ¼¼¼ärycc#h4š‚‚âT·yiwlH¸víÚ·ß~»téRGGGâV`aaÁf³[ÇÉf³‰.ª …‚Ïç€V«ÍÏÏ×ÅÉápˆFÕúúúúúz¢ß0òÊÜÜ܈ÉS‰—999Ä©öóóãr¹ …ø|>—ËuwwÖ¥ÝñˆÅâï¿ÿ^&“íØ±ãÝwßÕån®®®8Ž?+N¹\555îîîd2¹2ÊžÆÏϯ®®Žhèkjjª¬¬ÔýºSM”lmmŸuiw`<5557ntuuݱcǰaÃtíüüüêëë% 477WTT<gyy9†avvvæææöööOÄÙQÏK¨Ü^ÑÑÑ< î8< …ÑÑÑ,+,,ìÆ"‘H,ÿ÷ß>>>ýúõ»yófSS“T*MHH°±±ñõõíÀ`0 »~ý:•JŠŠ*++{ôèÑ£GJKK‰8333kjj EFF†@ ˆ‰‰144 OHHhnn‹ÅW¯^õôôtssóðð°¶¶NHHÉd )))..®õLþÈËb0‘‘‘‰‰‰ÍÍÍ‰äÆŽŽŽ^^^...ŽŽŽ×¯_—J¥ 11±ÿþ†††µµµÙÙÙJ¥²ªª*;;{ðàÁV«=w¯¯½½}II ‘Tjjjh4ZTTTbbbSS'›Íöññqvvvqq¹víšT* … 111,«oß¾ YYYJ¥’Ãátxœ=½½½··÷¿ÿþ+‘H„Bá7"##MMMCCCÅbñýû÷•J%Ç»ÿ>qªÛ¼´;0FsæÌ™É䢢""©"a\¹rE"‘455]¿~=""ÂÌÌ,$$D*•¦§§+•ÊÚÚÚ{÷î 2„ˆ3++«ººZ©Tfff644 0@ß'»{ Ôjµiii …¢¡¡áöíÛĩމ‰ÉÍÍ­¨¨P*•999gàÀϺ´;0žªª*bZ$©TúèÿÈårbâê»wïOG)))º$QPPðøñc¥R™——WYYIL)ý¦3Ê(::º¸¸¸¤¤„¨ª(//4hôïß?))I(J¥ÒäädSSÓÞ½{?ëÒî¨`p¿wï^]]Ý Aƒ¸\®.©q–””+•Ê¢¢¢ÒÒR]œÉÉÉB¡P&“ݺuËÈÈ( ÀÎήW¯^º8¯]»Ö·o_bPÝëCÝ!Ú+66öæÍ›«W¯vvvÎÎÎ~÷Ýwmmm`úôék×®ýâ‹/(JiiéæÍ›MMMß{ッ¾újÅŠ,«°°påÊ•˜°@¡P”””̘1C·ÑÞÞþæÍ›ýû÷OLL\³f««kVVÖĉíìì`Ú´iDœT*µ´´ô›o¾166666ž9sæÏ?ÿœŸŸßÐÐ@§ÓÇŒƒj‚_•JÙÝ›¹¹ù‡~¸jÕªòòr±X,‘H–.]J§ÓÝÜÜÆŒ³sçÎÛ·o—””„„„ãŸuiwWWW÷ûï¿ÿþûﺫW¯ž;wî‚ V­Zõøñc©TÚÜܼhÑ"ƒáêê:vìØÝ»wß¹s§¬¬,(((22ˆéÿÖ®]ëææ–Ýáqö@NNN&LسgϽ{÷***üüüˆçŠðððÀÀÀuëÖyzzæääê‘Éäg]ÚåñãÇÍÍÍË–-k½ñäÉ“ÁÁÁ'NÜ»wozzzUU•··w\\gppðúõë½¼¼rssÇG´3¼éŒ² êÛ·ï¦M›|||òóó‡N´ÃLœ81++ëóÏ?755-((X¼x1ÑS¥ÍK»£‚ÑjµÅÅÅç‰KEEEQQQDãd~~þ°aÈI–ÆŸ‘‘±|ùrssóüüüO?ý”(ì¾ÿþû«V­ªªª’ÉdB¡ð“O>é¨8Io¢ôÛûLÌêÿ·æí­[·jkkûõëçææF4+ã8^[[KL]áèèHôkll¼uë–R©ŒŠŠrrrêØ’%†ab±˜hÓ¡P(VVVDœ·oßær¹‘‘‘îîîDZ!Z©nß¾aXdd$'ü_2ÍÈȰ´´ŒŒŒ433C}‚_ 1ó†®uÇñ†††””µZ¥kVÆ0¬¤¤äÁƒfff‘‘‘Ä©V*•>ÌÏÏ÷ññ n½&j‡„×ÔÔôÄ´w¦¦¦8Žóùü[·n©ÕêÈÈH]*Å0¬´´ôÁƒ¦¦¦–––º8srròòò¼½½CBB:6Ξ@¥R‰ÅbcccâÖ8Ž—••Ý¿ßÈÈ(""ÂÚÚš8¥*•*//ïáÇîîîaaaÄš¨Ïº´;ŠF£!ú`ü¿öÎ5¨©ã à77ä&Þ1‘y˜@&á¡”@µ¨@ñ‰0Cû¡Ž¥Š}h}T«€ ¤¶¶µ£t‘Ñ:•R-v†¶”‚ÊCEh§(«Øj+ÒŠ@ –€@B¸ÉÍÿÃ&³A…`!–óûÆ!vv7{Îîž=Ç'''£ÑxëÖ­úúz.—!Lí¼~ýzccãôéÓÃÃÃÍÛY[[ÛÖÖ!‘H åh¡ŸÃ»¸¸˜I’üý÷ß§M›6kÖ,SWkµÚ‹/Þ½{7,,L*•ÒågõÕ~ZhµZËUîîî,ËÔN‘H4kÖ,.—kjg]]Ý;w …T*¥+rÿÛ†r2Ð××§×ëM†Ûh4Ö××ߺu+$$D.—›ºº§§§¦¦F£ÑDFFz{{ÓSëQ_í§gF£Ñ ò©S§Òílhh ÷ϦvöööVWW[¶³¥¥¥¾¾ÞÞÞ~Ö¬YO±à“ˆ &à?PEWʞ膶L`„ÐyÍ 3+ðD`UFïìš*à?455effšRÏÀ£¨®®ÎÎÎ~Z%%ÿ0jµ:33ó×_膶Îü‘••ÕÙÙ9Ñ lóçÏggg?ÝÚËÿ*à?ôôôÔ××[˜Âýû÷ŸnéKà?ÉÐÐPCCè `„´··_½zõ2@à“ÈŒµ¶¶þôÓOb±¸¢¢¢¿¿_&“-Y²¤¡¡á‡~`2™qqqQQQVÔÐëõ555tÖÓ§O“$ºtéÒ±çk¬¬¬Ôh4III¦\KÀ8péÒ¥ŽŽ‡óçÏëõú9sæ(•ÊÒÒÒ¦¦&.—›˜˜h]ê\FSVV&“Éš››kkkY,VTTTLLÌØ·§§§¤¤ÄÃÃcáÂ…Ýy“’$«ªª;;;ëêêX,Vbb"ŸÏ/,,ìêêâñxÉÉÉ"‘È Í===eeeJ¥²²²²¥¥…Ëå.[¶L¡PÐéÇØæúúú›7o.[¶ ªveee~~~õõõÍÍÍ|>?!!a``àÔ©S}}}b±899ÙTdkT´´´444\»víXZ«Óé ŠŠŠÒÓÓŸnoà‰üòË/EEE¾¾¾3f̸qãÆ{ï½çãã#•JýýýOž˜èž›\$yöìÙ?ÿüS"‘H$’ÚÚÚwÞy‡ÇãEDDxzzwwwïÛ·Ï Í===_|ñEyy¹T*¥5gff9rdìõ“Ïœ9“½~ýú§[Ux<ýýý………†OŸ>½¨¨èÇtppˆŒŒ¤(êØ±c\.)40Bnß¾ýÙgŸ‰D¢ÀÀ@//¯3gÎÜ»wïÃ?äñxci°N§;~üxqqñöíÛ!§ïx¢V«>, gÏžMÄÑ£GÏ;çèè¨T*›››÷ìÙ#fÏžm…fFóÝwß!üýýéøogggë´™7xÿþý7nܰq^†aXooïêÕ«£££ûûû;;;[[[wìØ1}úô„„„¸¸¸ëׯ#NðßÿM’$¢ÄÑÑѲÚZ­Þ½{·ŸŸŸ^¯ïìì¤ šC’äƒ ƒ¹Á`¸ººr¹\s ƒÁÐjµÇŽ+**ÊÊÊŠŒŒûñ0Z¬Õj»»»‘ÁÅqœÇã!§;>œ7oÞ¶mÛ‚P*•*•êîÝ»ˆLWGGÚcgg'EÇq½^_YYyàÀ””ºŠáD÷ÜäÂ`0§¦¦ÚÛÛ»»»ïÚµëðáÃóæÍ3 —/_~ñÅÍ—‹‡Z>{vpÛÛÛßzë­øøxÇýüü:¤V«'¸««K§Ó!Úìíí‘™ P~~þ÷߯R©"""À3Ë—/_±b…^¯ïëë«®®Þ½{·\.×jµ±±±—/_FÜÖ µ0 ãp8S¦LA„ƒÁÞÞ>55•Ïç·µµµ¶¶677›k3 ]]]HÑ% Ã\\\œœœÌ%ô¬èííÍÍÍíèèØ»w¯ Xï0 Ãx<žD"¡ëà …B’$iWÆÉÉÉÓÓÓrà÷ìÙsûömD¸téÒ×_úùùùûûcÆb±Äbqss3òööö÷ß)ÔÄf³×­[Gœ¤¡-Ó7ß|SZZ»ð ÁËË‹¾È‰DŽŽŽ2™ŒÞùL:ÕÕÕÙuvv¾ûî»ÈÃ#‹õæ›oÆÆÆš  Fhh(í9;;{xxX¦˜¹råÊÁƒ‘EÍÍÍ-##ÃÏÏÏ$!b`` 77÷ôéÓ;vìû!`þþþ´'Ao¡ÃÂÂèo1] Ù]½z5''yxäââ²cÇ™Lf.¤ iÏX({W^VVFŸ/š#‰>ùä‡c’à8Îb±jkkkjj„Bá’%KÀìììèz“ôTQ*•L&“Édúúú¶µµ!KÁ™3g %žžžûöíC¶Öîîî¦Y'‘Hèr\È:tèÊ•+ˆpöìÙiiiH#1 +,,,--]¼xqhh( ñÇÙÙY&“ÑsÃÇÇÇÉÉ) Ã0oooKGåÈ‘# ˆ0<<<##â8JÇA k€úûûwíÚÕÑÑa.d0¯¾újbb¢¹ ˆ¾¾¾ƒ–——gffÚ¾‚%ÏÖ®]«Õjá°tæ§8Ã@°eËÄyÂqÜËËË\BQÔààà… ÊËË-÷|€ Âãñ¶lÙ‚¼“Åq|Ú´iÈ' †iªÐ‡…–Úvî܉8O,ËÓÓÓ\BQÔ;wX,VBBÂW_}‡|°Ad2ÙöíÛ‘Áµ³³CÖ ØL¦)ÇñaOãæÏŸ¸Î†q8$ÈÏh4RUUUµtéÒòòòÒÒÒÕ«WOtOO`îܹ‰²Ùlóí ‹Å2MGmoV®\¹|ùrDhy¥IQ”F£©««KLL,//OHHˆˆˆ˜èžžÀË/¿¼dÉD8l¼b€,W.—»iÓ&ËKKãBQÔíÛ· ‚ˆ?qâDll¬P(œèžxà[A–æ­;D¡'Ÿå¥¥DDZZÚÌ™3ïܹ“——äìì<Ñ=<ƒAòeØÁ L&“Íf[úIˆ~£Ñèåå¥R©8ÎÖ­[¿üòËÍ›7[÷`7F8¸#ÄÎÎÎrÄõÌeÕªU¯¼ò I’Ÿþy||¼åU)`SŒjpŸ‹Å²Ô6ìs7‡“––ÜÒÒ’——€Üƒ¶ÆÈw$XÎ1ƒaéöFooo•JEÄÖ­[Oœ8±qãF[6@à[ñcÇîÝ»‡cccW¬X1ZUÿüóϧŸ~ªV«Í…A$''#9 C,óùüõë×§¥¥®^½®/mµZ}äÈ‘îîns!‹ÅZ¹råóÏ??ZmMMMùùùH8„‹‹ËÛo¿m~åD’¤“““H$âóù¯½öÚÞ½{#""ÌCk¤¹¹9//¹_rvvÞ¸q£å±ß¹páBII " …*•ÊÜF’$Åb±½½}JJÊo¿ý–“““žžŽÜª6ÅÏ?ÿ\TT„§Nš••EÇTŒŠo¿ýöÚµkˆ0<<|ݺuæ“6lHKKûúë¯W­ZA¶Lqqqcc#" Ù´iÓhUiµÚ£G"ÕR ÆK/½´hÑ"s!I’..."‘hÊ”)kÖ¬ÉÎÎV*•QQQÝ\(kضmrfƒY»÷ððP©T–¡ZYÎfΜ]PP°hÑ"ËÛRÀvàóù*•ÊòÒÀÞÞÞ m3gÎܳg2U Æc\–˜˜˜’’’£G†‡‡ƒgcËôÑG£ÜǰpáÂyóæ!BdzF‰D¢•+W~üñÇ ,X°`ÁD÷ðHbbbæÌ™ƒq·nUyã7,cIX2þüãÇ/^¼B­l™5kÖX¾à·î$˜ËåîܹÓÒ–Yá˜Zš——§P(lÖ1wíÚ5Ñm˜` ƒ]XXíwêt:OOÏ   ÃŒF£N§›1c†‡‡‡ùŸÐX–s‹$I///SpžN§r¹Üü38Žs†Ùa ‹¥P(pÐëõl6Ûö£ÎÿK ñx¼ÐÐPúGFH?}5 8Ž#¾&ŽãÃNäüž>“Ëå¦Ü±ôù:Ìd2‡*H,ÍÐЫ«ëŒ3‚`³ÙR©tppÇãAò×qƒP___úQ,†aýýý‘‘‘nnnØÿêCBBÌeG8¸EQâîîNÿ#½^HÿhÂÎÎÎR³Ѧ×ëŸ{î9‡ã¸\.'I’¢(zõÆÓÒq“ôëܹsé%B§Ó …B¹\n¾bŒpp ›Í £ÝŠ¢ŒFcHHâ‹a©Ír³„ ¹\®×ë9ŽÏDwádA…BAõ’$éææ¦P(èßj4™L†ø#\z0 zù’H$æ¹Ìé¸Í'Ú2 Ɔ†ÜÜÜ‚ƒƒéÿ.•JµZ-ŸÏ·Ù8«až‹ÀÈóL:À &à“p‚€I8ÁÀ¤ã”bÒX«h%tEXtdate:create2021-07-16T20:28:36+00:00Â7$Ÿ%tEXtdate:modify2021-07-16T20:28:36+00:00³jœ#"tEXtpdf:HiResBoundingBox1396x1123+0+0x{JXtEXtpdf:VersionPDF-1.7½8;í(tEXtxmp:CreateDate2021-07-16T15:25:43-05:00&ÄÆ#6tEXtxmp:CreatorToolGL2PS 1.4.2, (C) 1999-2020 C. Geuzaine´‘u(tEXtxmp:ModifyDate2021-07-16T15:25:43-05:00’:úIEND®B`‚blis-0.9.0/docs/graphs/large/l3_perf_skx_jc2ic13_nt26.pdf000066400000000000000000001043601422157504600227720ustar00rootroot00000000000000%PDF-1.4 %ª«¬­ 1 0 obj << /Producer (Apache FOP Version 2.3.0-SNAPSHOT: PDFDocumentGraphics2D) /CreationDate (D:20190328153450-05'00') >> endobj 2 0 obj << /Length 3 0 R /Filter /FlateDecode >> stream xœÌ½ËŽhËq%6çWœ¡=`1ßn )¸Í†ä=RS”ݺ’›`´¿ÞkEäÎÌÈ,ò²Îվࡄ[µ³öÎWäÊxÇÿ…ÿæð¿_ò?µ‡o÷Ã/܇Yž®Ÿðø¿ÿ¢|øŽ¡6yÆ_sK¹~ó)}‹EÞÅó~ácêøáõï¼ÇÏnýÀ¦øÅÿù‹Bï¿Çï%ÏÖÿáwßþþÿÇŸ×ã¿Ý|ÍßBÌLA~úGù©ÎòÃ?üâÏþ0–ãáÐ~ÿ‹ÿü_ðGÿõáÛ@ÿ7šJÊ-Æoÿï/¼ûö?íûo_êÓøaMì^BÄü«kZÇ£ø£sηøÖZA1¦˜ý3ûèý!ìS–E·OêG©@n?ÇhÿæÉÙÿ¯~í¿ùòAøíßc4ÚÕïÿĨr ÞçRCÅ«9´kl! Žü»ß.pùeð_ÿöÛ¾ýçÿ) ÛÿùÛùöÛÿð‹ÿ[™ù÷Õ9´¼k=}¥¯tõõÖÉñÆf>°ðòÉÝgS@«½÷æëË€äAF­»®~·–»÷î£6ÿIï³áý=u1 ×’ß\lvhÛôûúbK÷ÛbÛÞ¯ÅþqLð]´ÐÞÂ߆ˆ ­^–`àÁ—Çtâ]ý.–˜¿q'<äŸÔK á#¶˜£÷åêË9:ñؾÛGøþ¥ûpò/Ôo¿\=nCÙÿ¢öíR$à|¤ŒÄ¯ü'ëHþê׿ùë¿ùÛ_ýÝ?ÿáw׈ö åO®@Í^.§ØJú–:®g_k)¹ßK@|ÿeÒ¾ÿå÷¿ûᇯ¼¥X÷Gá¡aLX†“° %9\Bø@Eó¸@ÑJûBýp¥ùî“ÜbË E¬hÂ’âιª5fa$>Y¸Ú\ˆÃàrêØyiëødgw´Ö+ØïæzÍQÚðI'má#ô–z—¶ÆMCw­°óÇÊG¾œÿ¨Š<üé£Ö„rë‡of|³bh¾°Ÿ\È]ÚðMŽ%v^·ø9xÌ °É㓼W3Ùí‚s› è¥k¾Ò_åsü襂Ïê2’§À5Õžñkôò.íÊ¡¤LV"aY8BÈ~¬˜OVª­tœr6á“JÀÖâÏ?°=&m “Ê j Ìë#5—}’ÕÆb‘ЖÑ;ÈÃŒ-{fÄ7¹C…\Mìè›#&0…ä?896(/1óå: Ÿœ+†?¬ø\qQßãÁdw«q&Šç m ûÆ ª1È7SIÞÍËø&‡ 6sík¦û“¹Ì#:œ“^eC ¾õЫÇüD"7úÁþú‡^ù-ß± ­ËØ >†åü{y›–H^l«ø v¦ÐÈv #ŒLÚòÇ -/ßLd –6|“[Ó2ưÄX¬’¢Œg§M‚ Òyi±I8;a,Ç™ 朼´áO'Áò›tY+žö,âÅ#9g'pYp? -t0 iÃ'ës ᓹb§°Ì”þpv:†‚Eä{€™MêÒ†orkp²å›«â]hÒÖ>ž#î ë€}ãJÓ?ú$X=¾Ñ+®iÃ''Áâ“ ’Šîô=|r,†‰qû±š#ë\¬” ³öpò>䓵ó–Á|0Ð&‡ b•hŽ ,ý¥„Ó3_AÇö»ŒÓ’CrIÚ@t“bÎOx+È7qxÊ¢X쨳{¡$¹ÿù)ˆéMöúÏæ2üÿÓm`sYÀà¾q`‰3q¸n܆ÑÑæêÛçŽ1»äoÜ®ØTÜX$Œ·“ ûPR‹áÆíŠMm8%ÁŸ¸Í÷z]äX.Ü†à–±á¹×~â6‡‰¯PØ£ZCŸ®Å ¶qƒ Á4éA6° ¤Àv¦j½`»á› ½œØ lãæIÔÁT½ v؆´Aæ=*ŽØ&߉‹ÐÝ/ØÆPðK®þØ.ŠV ºlçúA¹ ].ÜF[B§¥´|áv鼘ëé‚mt0Èø“¶KÄ/É5¯˜b`dá"9È·s‘KºW/ÜæíÒoE×ÃàvÆå,ˆYhp»$lýÚRƒÛ`ë@Hä ú…ÛW\Á ^òÛ™ÄUqZs¸p\AÅŽ6ï/ØFæÝAøñ‚íÔɤº6î±¶±6`ÌÐwÔæ¦uPnÔ µ±Ü[èjjs$eJrâ,jc }KàjJ?Q›lF~®} Ú ÝíÍ€6F äĶD6F@J¼@ŒºÄÎÉ5nA›„†ofÒî Ú `rC/ÐN„¶VƒÞs´Á|UØê“ZÐÆX Ýdï„ÙÐÆÙ8)á˨í'j·oñ[ø¿Ü<µ˜pÄþ\À ”b€K¹ùmÐ> |YàÆnžçw7.q[Ź<›mØ;p)¥Ü wû-à(+wl€»§†»)“køíNQ2”àv~rW‡ †c÷ pã‹Ä] pw\<‘º*¿]„6‚Ê÷¸_8; V/àÕ*ŽÌ Ü8„?Øw#8Aî ¸±[`÷›twãBθ[oàæ±Ôtá6ˆÖ‘ª{`›Œ{"ÇRnàÆ…Œ—b7¿ å~‡®£À]Ëø_O%ÀÍpg àûûÍpõ ³ðõn€,ö”o†À}ð¼Æ/à.ÛñzêpWG8n€¾›á.$pD‚n·An'ØPܪ!ÜÈÍÕ)8cÅ_ÈÈ‘‚Àªÿ º¸ž8–Å@7ÖÓŽä[èÆ}†õ…*`èÆRƒ~0YN ÝJÌD«vc7è' Äë;vc‡°’ÀKÅ`‹Ý8LL,íÆî +Ln¿°w?$3ÀR¹ 3Èð) v ·è‚П~Ñ"7~)˜ó p;œþ a£Nnã†üà ²„¯·û©À .ÅáטóÜ`Wq20)×Näærl¥ÈÍíq$Óèë‰ÜÜe­*¶Y–›'°Ø€]u¸=‡ÂcÇm¼æ:6ènpïáÒÁn–|á¶w`R†ÃbÒî3@‚ibMiv)梪E!6ïân§Ò·WR6~"æ§æEUýÿHS€€˜ ™°uÕË¥B«ë#@@Î "A½h¢89ˆD$Ó$Ÿ„8™¦üËdU|CDÆT_€© %ïÕÃ/ïAöÖ)Tu ,ãXjFOI#~FŸIÛÇè]@R;ühÀ¨]ä¢Ô¿,IÄßɺñ {! W1^¦~øP*ʪ«4Y¿ì-N•Õ³3~8¢°ø/dwø€BZUmö»_N &ÑD,zNj¦(Ée0- QYéÔs8ü$âu(ôtQfý¦*†ÄNœãáà:¤Ú ¬ðG î¾ë0V«fÑUäxø‚Ä`iKT`ã5Ò(‡™ºÃ¥bN»Ä¨×)Ô‹zi3~é#CRŠHOç9¦n…S˜§…m‡_@vñѺgê$s€t³èÈänÅè¼w÷E÷K~j ©¢×T>Cm‚vi©\°Í‹47œrE=Ûd ÝW5êØ¾ò–¨~œý¶ƒhb€O]Td¶Aô´ùf’ÆÜ­@°ˆàt·\! Ð¨¦”¸ƒ#¡PoÒ.ÜÆ’°yNÅí‚{8¶áðda»Ñ†A´/Ø’9¬ju5ž°]é2b©¢ö´°‹§*µÄ„da›nŠØÙVD“da;œNÙÉzÁ6n*aZÿ¶!ÒòÅq›ئñ;†å¸q›&š Ô.º·s§þ·D±‘[ض.¶y¼\¦CW»`ãîàÔê ¶ÕÀtQ/ØæEŒõí^ïoÛTâDaòÛ™xr¨º£¶iî»Ý›¨,l'j •©þ‚íØa‚ÃÛ Û ¶&ÔrÁ6†‚#UÕÇ¢67’5¦•/ÔF[pè-ÊefQ;Qߎ{ Éa´¨-ÖqàŽÚÕ,j'…“{Õ¢vm 8±ÔÎ À>#(ŠÔÆb6Q´Š•È¢6ºk8[ôz¡6ØŒ‰Ckj'rfû(çÊ¢vä½A’¾\¨Å( ^ûÔ¦¹4W›N¯¨çd£ž2Ä—íKr{*‹{!Çs"·§} {œÃÅp-±Ó@PåRvä& L ä.†›S ¬B½nZ0inðíf¸+­ÿ¡ ®Í"7ÐÄM¿Ú‹å/Ÿ„iŠÖ°ÜMì=¤‡tAw#¿ VKmŠËÍ£Ú0»Yì¯X@b1);n°¢ %xíoÇnò« PÒÝ´nâ¤ÑCîÂnÐ&¸{'ÒÒ‰Ýx¯ç(8|Ærã:¾µOXnÙJ›• 7»Ñ©èÊþìN¼š°²c9-ÏMë` XÑp7ûã-2®»Ás7žNÀ·Š'–çæ9¨M-&»±üŸírþžk Žæ Þb©~eÝ6Þ‘®àè’^Õ¼Ù†QÌxGñé¦*ð&ÿŸôØ]àÉ÷ø:¼@ x3èÍuÜñîæ¹ñIœ´ÜUu{ðÜ\M,¿^ÿÏÝa“kþæ¹;¯cÕÞuðÜàRR+Êe,7=ø{©^vÔ²Ü:¶]Öòà¸ËENll»9O7ʃã¦w/DË$¼ÙÁqƒ«Æu —ÏÉo‡p"Ä zðÛ¸˜èñj¿ùíòAãج8îD¡,Ððô5†[-LàÞ‡§nèýø“,_´0}Ö÷J¿1ÖÄ^饪%¥5tZÇ£×Í;5¨1…Q#ÏÊÚG¯ÁLYÝ>yÛÂdæ«›nž|‡…)á²,A¤sñíðØT¨W"ƒ}üK²1­³:Aá•íkaƒ„÷Îê6 •ëè]2fÓïëfé~3{ØÞ_¶1í{ú³Ø˜Ø¡YlÓïë‹-Ýo‹m{ÿº)vº.Eaó_³1ÙNÞ²1™^^±1%²÷©A<£FùO™Ð½12ý´ed*&¿WZÝS…H~ 9hzËðQÿ” >•žlb ψ‹«FáýJص•ÔÑræI<œK4ÚÊN[Kðª‚.Q}*A”üf +Õˆü(qWVRb #¹A¬hd¯®ŠÒ±fj¼¤áa* Eê+”$•-Wm+.·T…^²ÑU2² âq 2£8Têin„”(^c%«C¥"åÌ€Õ*ç©”]àí`ö+ÝeI;¥‡R°”ôÉ+Y)FY)Érª¯"dBŒÀqâC¥–}j„V©Æž>šRˆhÞKUJ•u|Kg×vy·Z!üi RiFW? $×’E†+M]*U‚¨bi­ˆ­¨t£« y iŠ–£@žôS‚@„4ª½›´=ALJÑ´TÊ‘±Šï<祻V‰ab dŸ.¾ú•räC­âóí,zðê²2s v\úóÆžê<„Ita•‚äC­¢ê+3Þ«†CYééü_eK«Øk”\©,ÄÄüTÃ.îb˜ ãˆ]¨Éh+±Ý µr^ß3ÚJÊ»> + Cì¶²b6¦š­¶s \PiÚ%^9¸ÔqŠñ¦–]âAl*ÜZŒ¶²£ošau÷Š cŠÜõ–ªXkÝe^2¶‘$¢ü­u—y©'Ë“*!…ïÚJZpHbãË5ÓA3)U¼gdºPÛwNY\áÔŽTK%ÕŒXØŽr&^Ô‘¶i ¦‚ ÷|Áv”ý€< J ÛòPLq!Á§ ~Ð’ØžwئÇ3&µéÄŒQÔ¨/Ú˜àfäNÁþc:'p‹®Õ‹Ü·¯´(42ž'p ”æÞo¹ã¶‘z ‰ú/Ü&“èV˜†n†|‚J¼Ëbã´À°![ç.Ž›!R ñÖ4£‹n¦"Cã¥| îJ}7NþÃUŽÛ‰§[ÔÀh Üt0Üต ¸Á50h-øÎ;pƒáºéBnÚòy¼J¹XnÐ 6#󎹠›¯e,ÊXiÝdR°/]ô|¹ckÅ?¨\È Vc¤†4_È öŒw.&.äNFe\ÊíBîHÏœµ(&ŽÜ4ùJ Œ2C¹ñ(c•AXä&¯×1/µå[ä&‡‚‘fŸû…Ü1 Ìcp!7£Ù‹¤á†¹ñM´†£ž…nºÝ$:é8wì¦eªâÆíŠ¥» 1$©ÅÍb7ƒÔF›11eŒ ÂoU´1ØMG8¬ð¼C7f膑näXhϼt#7Ú°³`ýÝÜ¢P"ªyÐ 7õµàø! rÓ:¶@/ƒÜäAøAsKXäLÝ>.äÔÓxºbô ºCäÅšV¹Ç@·ØÝôй ›!…XŒ ÆnnzQáäþ²‘©‰­_BH{Ô¬ò£hxÙü¢™éÓÞßPüyü°Mí•np†¦ãÑëVžNùךŽG¯ÁLYVÝ>yÛÐdæ+ýÛ'ßahb¹øa§.z„7 M8íÌèW)|ɨõ¶¡iÖ ¯$ uóð¼|Z·ùäŸÃÔÄõÃôûºõCºß¬¶÷—MMÛ®âúü9lMÒ£YnÓñû‰o‡½f®·íþëÖ&HX»L«õéYšÒ.SS !Wô!§r“©+ ØA±Ìt&Ã]ò¯ûuHmi—«äÇA2_Eþá4&Õn÷à6ùlæQi+–¶dåßiº$qŽë=ôÈ¿œ3÷FцvÈ„Kþ¥u¬I™ŒßÄ_p  blçp—ø[pt€IN4!wñWäd »JSڤ߆MbZ61ÈtúÊ/ÿJñïˆßÞ¥ßJq·å :™Žƒc¤_&r]â¤:Ó".é7}vbñ·3Wц£ám:¸åLŸtÇ”¦2ªì&¹2r©z1¯Mþ¥°Úp&«ÈÍ@ˆ%ÿFÑñ§ M;¹àÝ%ØHœzöA.»ü+©pšzÇcQ7ñ7ò c;²ny«{î¥J¦2] Kµ{ÇG†(àËâD tÞ½ã™Ë5Úy¥­nâ/9™I=ú”RE ’0¾.§ð-ƒÓÛ‘î >¼`;0á¡Ëšýî€m‰Nâ-”/ØføäûRåè[Øÿ‚N"ólÓ6Ñ%Zqt‡m¿b{±Í¢ZÚa;xšî[ñ“¶™k ·$»8Øæ{…úôz‚¶88ú¿ŠYÙ€6¿ÈX»PE¹oP›¡ó1K 6¡†…ÄŠ'jó.ó…ÛPnÔ¦W fWz;Q;8fBÅ&h¢'‹ÚRb§¯ƒ®¥Am¦Œ%'MWiQ»‹CÆc޶°ÍD|Ø-\éÂmÆJ€M”.Üîžóy²íYÜæ8CV☸ÍL^Ìê$m™ÅíÚŽ@ Q)YØf2@^×´˜¶éÉÚbvá ¶o*5õ^¸Ý’õðʶ¸Ý¨þ˜Èn îŸ4ˆÍ7 p˜OìB¯¸É¤ÈÌFén0ùÅ1Ó›Ówóà FnH ÛÔJg𼪯µ°ÍÞ˜3ÞëbØ®t–ÉÀ6a†,ló@tæ Ôý1°-æEtØÄJm`»[Ètmñl׌ÅÓØ  ¶™†«R5BÏâ6>⨶ô!]¸]Œ%Ój·Á`5–QHýÆíJµy5§·K㪃©Ðüp\†K߇š¿&ÞÙät@wä/̲}sÜLæ¦ÖŽzC7.äe(=8n'¹6Á0…›ãÜàïsA·—µu ~¾ Ûñ¬á”úØ.Ž›i °œÔ Ã9бdÛµ 7^#Ÿ”¿7 7-\ ÙÞúÍo3Âtr†áŒ",öU Ý ŒÑk>Ëoã—Ø@œAÌ5¹Åë‡>eíd·™ý°UæÅn7»;Nq¨]ÀM£³¬øgÃn3üµboÜ.~ó¿³°]$¬ºÐnv»J¾ºÒÕÙ̶$Ы©iμÛ<ß Ý$×ov»Qd}2l[ܦî›ìTT°ì6Ãå=É']¸Í¼Lç¯~»2®ÏÅ,t`q›Þi íTä ·¸MÝ(« Þàv¡’“V˲ÅíTè8á’Ò¸ÅíL¥'dͬlq;û“‘Ù"7³qƆƒq6 wÅÕOâÒþ rg/Ém[Th³ 7˜jÏä(¾^ÈŠÜ/MÛ r'Þ‚À§›An ›…ìUUf0ÈM‰ Û›ÇÔ rg²m[’ÃÍq‰iònk‘;‰ãDÉýwpÜ´Þ‘WR™Á w"wÉ,Ÿri Ž›ÑǼfY3~ý3ªÐ$0¹œ]þ–s&'ÜšõRü¸oC#óï~ó¿ýíkÀ8U€ééÙ¿‡ê OMŒ}!ñBˆuÉÞ45vþ<Å`ͽ¨áÏó¯ÿŸßýÓ¿ûÍÿúõ¹~Õ}nŸ³wt[é´l”sÒ¦í;f]Éí1Æ›)åÿجÿýÿõûßýÓwMù‹¾'fÖt6Á¬2½{ÏYïmß1ëÆ{Ç­°¬Ð›õüßó$ýÓæÌ¨t°)û~Íyoû;²§þfmÔIRDtþ¨Å=ÙþfuÏOûG­Ÿ[òœÝ+ý0C)¦!÷öLíxöº)׋S[ŒÂ8ÎAØg?à öYëÒÛGo[”í”ÇÌ£Ÿ\é³âÿŽë¼ia¦[ÚG«€uªÊÿ‚,Ìû)ž€ñʆ>ñú)63ÊB%éÉ£ùb—¶à§éùg0|fkh>úÛÒ¼ï­ïRÿ23Ÿ÷‹K.â“YrÓóûK®IÏ·%·ýÝØ\J—r¦z¯ôçÑË[ÆfÛÍ+Æf–"üH Â/½âÿ´µ9í¶æy¯´¦“ZI½óR«ìЛTÎ$‹fAVͱªcuh”Šj®å¤ÇUÆpÁÓ&ˆtR5"{5¬^ÝzSÅ&“¤õ‰”'D§Ö\Ïõ‚Fc» tr£ä‡wm7^0W]+•K…wï0 Ð9c­Ú¸[/˜8?£QãW̹0ø—ù‰RAc’Ü> .°] “*¦ðZÓG-ZlT¼)¨ɫ.ˆöBwU}Ä›‹^3 ýã“ÖÑæ1 ¦E±Ö{=ÄËŒ‘Jh£|§g-„ÍŽ!ý'F‰ic•?L#¡3LÊ4X•E ?Æ¢G±V´Ì…MgŒ)LN‡Ü_ªÎ$T=Ãä[Í{}“J' (1ö‚JÄ\¬#F^/þÐX ÖÀ–¼©z /Viy%µDÑQÄjEÚCÊT`Cj‰nP+U-þ!e;˜£!h / Ñv“F­•žÌúÙ¼ëÆèkÜHÌé¥"ÍCÉ¢kg5¿Q7Eªß=”,®÷$õö’njÇjü(äW{Ðñ”ݬÁ›ðDìy‰ÍxHYÂ^˜g¶%­ÎÆÒdÈjLu¨»†Œ wªÈÜ +®×CÊ’i‹%”\ÓÅ£òi’2+êOã®$+Ìqƒó›œ¨íZ24‚¶~E‰Žú§IÊ…ÑÇ ô¨u¿7±‡Ô`GRŽªc¢~{‹©¡ÇsxRq2i¢T˜PR.¢”J¬yF?ÇIÊ¢Iy­¤qו•¼;ƒ{Qá/ýn`Oì›hÊi!–?¤ŒÆœ9‘ëénS&)£OuŸ ã›e?ç‡_Äkå8o¬¯û’ò§Xh3ˆ WŸ`= É}õTrô8RÑPO•&•‹ÿê¼# Ø'PEµ ÊÉ7ÔÇæ$ÙµO°ÞƒÌcÁ&~‚õDÄTY·$~‚õ^ô¾ÈŸ`½k|ºÜ¡^¼¤èÜu"Ô·½@Œ…zZ‚°8´ñÔÓB–3U­7Ô'fMp4+|õ¬Zʰe-®j¡žþ†­ÐÔÚo¨§mç¾j ¯êñY,^ Ï=°C=Óñ1pÙ=€½C}—Ò†­hÀÇõE€p3»Vw¨oÔËžÒãràÖµQÊÊ"=£¨W{Â|ÿà–Ä0.óLMqÏk9íçq²m|‡ÅùÆ` ®ß¸‘ ÎKléc!´0ßè„UºfR>P¯ ÅVö ÊÑÌêòŒët@aïâòDu½?Ayœ¢ZcaíåYG‰QN©}‚ò4WFM·x£|c±Oôþ\Ë;Ê3þ…ßOµÝ(‹—§Ün”¯’~”©êò¼ìpáFyÚ˜*jg<@¾²Þ2ë)ù[g¢JH!Uk'Èã¬:Ûùò#­ví‹Q8_Wèž8Y›\ìî7ÎÊÑ]cmœç¹ RÁûzOÇM†.:½”ÖG«-èéZƒêó`Y++ûj.Uó’6ŸæJu²0/‚óÚ“l`žtŸl¯9ù,Ì‹PŸØŒ ÌK#3¦o–¾‰0ÞâœgŸ58Î Þ,}ãUžZ²Îc €Jo¿Xz-ô裪Î-Î3 ”EoÝøªÁylp xõÁ=p>EúeæöG_$Ý|¦dwüØNcVÁ嫤ßÇå2Í <ð´$"DÜ@¾HÎØÈD7Ê»P¶ÖÁé”3Ef$¿^B8#ë[~ÂÏ㨀q,Ã}ìz¦ýlÓ ñzä¶ZËgü<‹+ã3ä¯. /-ÊÏæéé=‹û¡¤ºõ0xÓÿÇkþÛé5ó¤Ön¤Ïô1åº±Ì =Ýd)–xµÂX¤Ot óèsì¢AzM,âùôIòÒJ=Õ é á¼ÚÀé1X³ñôé#ó!EÍ©sà|¦Yy/‚óÌhËV­`~}jôü~’@/!® sTÚ²@Ÿ¤²'v§L[–$a­¹ô¯™¦• ËÅ–¤]’SÇŸÔŸ’­úÓK6²OzE9æñÃ6·7úa TÚ€êšØñ(‹ T²3¿4„¶ÕHC°ÞÂ>e]öãQ[Q^?Ã*Œ!ØGŸ áG•¶@djqìé÷èžEV&ðJþ·¶ˆáqÁä ëæúzÝ"6I{¡Ã+¥Î"¼}f÷ùh¢K©¿û.1äìнÙa¼g_a¼g_›áN+nÁÛ{{(º»ÃWgï¾·‡Òá=Ã}Ã$Þ®© @ :ÿB|cFòöoh°³drØ®û6òOØëÂOë%€ãgbOŽö÷’~R/2Û‡g*yf®ÿã½Ó‹¸y0·n¿tLâAæ¾~ûåf‡\CÙÿÂ;\Ø©1–E„ú*>×ôg¾üÇ~YðŸ¬Cù«_ÿæ¯ÿæoõwÿü‡ß]cÚ]Oþä0 /jÈr4Q½MóHmŸ”þÛ³²þ×ßÿî½(YSêž<e ²áG¥û½2 +«Ña¯tŸ˜D78$Rñ^é>1ü‰¥º²Ägú½Ò}dN'Uib¯tŸ¨þ‡Õ ÔTºgù”$9©D‘g*ÝGHstìqš”ÒTº´,e¬~™b¯tiO(Xƒ,šSé>JF±áN+¾ï•îSLÿóí¨rO·º¦w-/gªÜÇÜé]Þ†®d¯r³ða´oªÜGÖ r{'ª"Sç«ÄZ !ªºÔÔ¹Y"/fw{ûÈè œÊám ÝG)ÏsºgG1.mÛ ÝGz2»>wg/tÏoF•Iå½½Ð=€Ó9[k´K¡ûHɰO½’)tÏ=G5ã¤)tω1·‰vÀºçØAGuøú›B÷‘)F3“fé{{¡û(ÒvO#š8ì…îeεͽ٠ݳÍa•›B÷l‹k%×)t¯ïUÿ¬ãVêž³K$ä&&RSêžÃôJÈ2…½Ô=W30G—¦ 4¥îyB6¯A+x™R÷QŠÇøœ4dr/u/—(æ96ÈÔº,+é]ÖM0¥îY3>ƒ€bS„)ucÙ'nJÝó“‘µîKÒrö[ލ(ʉJý™¾·åˆâ7=–wœoSêžm´¢Œ€CSêž¿ÖÚ8ǦÔ=ßÓ£/(J>’Ámf õë1¸Í0ëMÊ1¸Í”¼¹ONÚàvÝX¡·™@¡¦¦Â-n³Æ“-«jq›9ª ›Ámºtlœ­Ámzt„ÅÓànâ¤P³&F>€;‰sâÃï[àf¹ÁWžÀÝý ¸Y¸B3~„ ¸«Ÿ‡ïÄm:”%^XÜfÁÅuÓ%ùÝû"bã°fújò>:›8E_f¥ƒØQ25ƒ‡Óå7ˆÁº‡Ô±z ¯<¼*Ä&•&‹gÕ"¥bõA\C*4j‘N'€8%F£)üòR,ìj¦õ-3BÚªEè§|6eìÆ\ÐZ5À6Û6™×vbµO5#Ì‘CûT3‚ýÙ„C3̵b4#gʶ`F3 HeÖg±x?ÆÁƒXÀféî¾6ó^a?l ĸøÛàÃw^[ü'|}”;Êk³Øh7¾ÅkÜêŽgfÜm¯3#.B0˜oîš ƒÙx/+™‡ ³™!®ÌÍp ³ëÕ,ÆØ`v`Eáu?Ì]0ËÏhÚ!;H…Yÿ©b„ù›6qÒ`6ým—ðn1›9¡¦@l![\|(· ÉÙÔ‰âì§žýÙ´kbïÆ¼-d35ʺœ-dfìrÏ…d!;ÐéU|pãÙ!J:þ_ ds,›"Æ@6ÙµÅDXÌ&K–'îYÌF[Ú4#d5Æò®´E¨Œ8ª¶/þ¤¦Sñ~Ñ•ã³Þ_±Kõǧ`Íí~DüÀ¿Ì@Øñèu? Ș§+Çñèõ!˜)ë²^wå0S;ï~²+GèR£IBÁ^öäˆz–‹tåÿËqäX'vaÃ+X† /:Œló)Ü+÷Ò»P4œL‡ï9ôÇ‘Ãtø¢@9l‡¯Íp§•­ê{{(º»ÃWgï¾·‡Òá=Ã/9r€ƒ >Ä=ú5GÛÉ[޶—·9L/ßçÈñ#nà”©ˆvŒ,þ1/ ¿{IüËÿxÏK‚Ú%ë%¡‰.©À¥AƸIä%îP[èñŠ&·Ò%·Ó¢z° mÈàb8zÄ+ZŠZŸfÑ8,•uØÓF#ö­)^‰¹">V$*Q77 c$Ha×PÖrñ1Õ¤°»I0Ïí´€Ðz7C@baJD7‡BawÊW T˜ÊŸDA{ŠWÙ¨½¨k™áòÚ2«§´{J0àÔ>¤d<%°(uµe£€üKý•Z¹—KÀÄßù“¦­K¬ù5å«”w™?•­š–˜ã!×=O*[5-ŽÓ÷©_LE’“ ùŠÎ ìÒÀ¶zxJdðSµ :ož8!—êô”` CÕÙ¥f<%èô4=XR3ž¬Ó建ާf<%3_‡I(uã(‘vߋԣD@×kèÝ8Jñ‹F­ìŒ£DÚUÙG ºYMÅivÆQ"±ºèC”ÙïŽÌcýL.{ã'ÁÀ“©´È~+¥Åõñ5‡­Š½ 65rÆCg­OÕ óüÌø¾—˜UÕy9.Åãè©TW-ùâReäh<$¨ÊðujN[-j‹RŶ©"§ÃCÂ-#DNÆC‚Gt:Gå¼UÑâ7kžˆ³ñÚb15ç­Š–xdTÿ(úåÆŽŒiûšúö‹.X{ˆ%ñëkª%Óc×°`-Åâ¦ÞÙ‚u 'V{̨¬±O›^×€5¶lÒ¬q”©äcÙÁÄ#DR4cœkþºC/·ƒ5»[*EƒÕjˆKJÆ`5Yr§? »ƒuò,Ë—û8¬9Í?jë$â t“ñ‘ Z¶Ç~aÀšµÖ§=Á€5 VÌðZ5Ñ‚5 E¾…¡~6`M ˆyº§Y°îŒqÝÚ6°æ{®Oc¶ëΔ•ó„°VkkëŽ÷ÔS"îZQ ÖL-¼·ëv«¹Ekz.ÿhS-\3'fUÍÂuw»×†…ëÖv¶ÄÂ5Ù‹>­®ÕŽÉŒëÁÂ5=ò¼½ \7zb…ÇtfñZr^„š-\‹ŸÁ\M ÚÌy²îJ Ú¾úÚM”«eø´ZЦ/A›FYƒÚâE1½ï,j3à}™œ-jÓ̵-ŠAí&YqŸƒeQ»%©º]‹$æ°¨ÍäðRàx ³q•È»JØ¢6Ë3שJÔnaï}ÑðfÁÌZæìHš'xǸÛö-x;:$—‡§Ù±›'ˆ 샥;v‹ÿÒ†`†Ñf:›þGmœ÷LØü¦ÁnW$Îsü £]Š°Ñ® ÓVûùÍh³(F~öÇ2Ú %ÆÆŽ[ÜrÚÅøËœ6‰ª>.܆Ó.uÅÉi3/Ìò¨¶œ6]ªëºí §-îÑésN[Šu7œ-§MSåC§Í1OËi羇ÅnÊtP·Œ6ch—ãÓÀn<ŒË]Ôb7_X>„»É‰,´±Ø¥pø” vK= ´±ØM)(MëÍÁjó\Çß`7³|ÓGg0f–Õæ~ç:,W«MŽ)?.–Õ&©ÍƒuðÚ}÷2ùaŸÝ+µ~ÚߎG¯¿zʧýíxôúÌ”uÝG¯ÛßÌ”uǣﱿÇtf¦3XÙþÆTê¸éàÒ¿dë{Ûþ¶Ní‡wjOÎ3ôö©Ýf” œtèî_³Þ4ñº:|Ïz#Þ3|Ï·QKg±¤÷MpÚ£»{|wŽñžã‹ ©¥Ç{Ž_²Âáutký53ÜÑË[v¸£›· q¶›W,qØgùŒvÿ±tÁ–)î_ÿð^ \“„aSK …èT¿$In×íÒÔ3J[Ú*"ÑÜ6Mxl«{l…IMÙ¨†Ÿjß!-Í„W-§ÝÇນÖòV‰Zǰül[q›)ŽY§&­±pÓº î×­»²C—ó•V¦Õ­’äìZéë6M¡‹V®å[ݘ}j ],_9õ’­¹]KÀô33Ëjk[$Ê\[VÂÆšMË?× µ¾Š ‰fåTk}«D{ÊæŽÚX¯iÊ\Y :ù¨³\Ó²pˆäSl$O´¹ç¶]aÑÝVIl4+!X÷n÷Ïe£HøR€:ÒÊ„Ã!þ¹a×w–hšjÉw¼Ïü-»n[ÆÄê®&"¸ðUõèöP8P¨dl)ó/l¡p•qOÆ–ÎMSM@çvÿd±éÉíZü:Sû@O«ì‘&]š©c:3E-%†ÅïRÛ­g·+ ˜æ±8ôœv3 µG­Ò¥ïys…=$¯K¡ªÉœ0t†³ö’vÛUB½ÔÝ;—…í¦B¯Óµvyç&ÐëÔ†õš6AÚM”½Ö]Gw@g]¦]GŸh]¶¥]GÀ4²k(­ZõÉÝÚ»³:‚ ¡Ú–vß½ó;k2-Hl%AÕÛ›¹•—{ý[F¹¸óJu{·ÛSwYà¶)(-p3îp%\µÀ-ù£gzr Ü‘A¢™³ ¸÷`ÇlIÆ»¼< fS[œW®!ƒÙlÛÝ`6#Ô¶€,ƒÙT%çÙNM*³i‰Ù2óЖ¸íE ´i´r+û¯m1Å,TÛA›v¦-þ΀6[ð”m¶m¶+ Ú`ñÚcÄ· MwYÁ-h³™ªT‰fAm~e[µ ¶¾2.Ð×–…ä´™Öµ>žþ³±61=iÞ-d÷é`ẛœˆ®ñN\®+®»I†eñºõ-·¡Ák´lî÷¯™(rÅêX¼–¬™{Ò6ó o•l& ^é-`3Ü 7þ`É,`7¿›D,`3O.÷FO¶l¼ëÓ¦n»3öaä,`óœyÖ}3xMoÂ6,^3ób˜¾X¯kÙãH,^£myBX¸®T/Ïï®1äµ­ŠÖÌ ¹|^´Ç€­óQÖ'`'fÊóO銃Óv{ê5 Ø>ïIÆ-`;ìDÈ‚>^€í™°aÆœ¶ß}% j‚¤’±žŸƒÓλ ãà´Y-c¦•°¨MóùŠ×µœ¶$’Íë½ÓfùE77ݲÚ< +¦eµI,Û8 «Ý$Lîa- «ÍXÒ•¨×²Ú¤±akYmpýnÕ2±¨M®¿Mo.‹ÚL +áé Uµ«T£תí"„çæ· îÒ  MÃÚž,hÓ³"F-jÓ³ü~,l3jˆ>¼%,t£¿¸²c[èf­àl¡»Ð¼”†ÁBw12ƒÝ%n5D,tËÌãhYmH·yÆ!¼6cLfj ÝÉb ,t3·ÊÆ[^›³SX0ÈM+ôJEl‘;§ÝÏ 7ºÞÜh-rSÃ9ò¢ZèÆ'[X…núlm¼nJÛc bê–²Þb·fI}nÝôõZ©2‡fÎo õõŠ¢.Os˜ºš‰9Ž?Ž¢¢üƒW«Š~:‚wôŠyZäÖ_éÉ;µë±øÇ³×írvÖÏ ì³ï±ÌáÖ ®õeË\®1)*I–¹ýü.¬xexxÿüš9eÉ¥˜žŒ•ové>éòEËN~ t¶Ë7M;ù1Ñ]¾7Ëj|À“Âç/îåHpwwùî,ã'³|q/¥ËOfù%;]Ï ®Kï•=zyËNwtó–ÎvóŠ.}!9@Œø1C1ÓýË{U=¥r&éÌù ©Ã&ᤈ Rn+AÂ7â3Se„F£ñµe*cøEL`55úéî 8es\°±»"±q[FK4Šß]ëÒ6‚ß&"m‰š`HT©B–eÞ’!¾¢Ñè~ý. ­2jFÌ:hL’QGh§w•Hr”ÐÃÅT\„™lìÚ®I`¦–•»*Øò;¢‘vOˆ7>©~bEóy4nº„¶û £mW&´¸Ç¼¡±J^‚iú©•›Æ{Šëºæª¢Øò¢q×'0”n•”Dã®Pàþ¤&BMøGÀxȤr˜_ö/4&É®“o¢ú œ<ükÑ(JJ›Ë{ós’_G(YbæéåéñûáJûéÊäƒÆ]¯@½GÒT5lË»^NÑËa—QXþ!dZleCUÍÆ*9v„ùU7Sì1–oÓ,Ô°ËúhÜT 5ì¹ÓÐV)q+!sû¹òu×.T¦òœÑ$hÜÕ ¥Kèåp8Ec•JÈxsE\xOÉ}Ò1k-·d4¦£0ÑÊ[†Æ]ÅÀðÀem•BÏ}Ò1‡>ëc qW20åÑÌ„¦]ÉÀ¥Z&UPª“JJÇtï3ä àï'Ó=8ÌĆhÜõ û\õáp'Ì*4Rlxè¸lª7i¬RîBéX·Ÿx•¡¢}æˆz­èó#moþæi–œêñæ·ÂZ'ÌwcÌ—Ý}Â|ÛN˜Ç6Δ\æƒQŸ0ojL0_·Çå}ÞSóY”Oªì|bä,Ê‹Qqe3´(/óX®åiæÛ2üZ”§F|î×ó´¶qü}²Y/ƒ›i -ÂkÍì©W=žæïaÛ:¾34ÏÈŒ•…ù@xZú¶í°ÏϺi'žI,Wøìð¸¥ZŸ~CÂK=?ltÉ7Àw¿{ÝÏܘۅj¾47¶ ÚÊ,ßÚžÖÌ"¼Ü¶3Žÿ@x¾¸â„sÛ6ƒð­ì¹ „§u%(> žVÃBr@<ÿrÅÕßè%áùñLx¹j±[ˆçL–[ÏñÍxBO#Ìʨx`<˜Š•Ôù€ø 3kòñ¬3· ëÄWš¼c!^¬&yÝÄx±(Íœpo£;`€SGÊ æs¾Ï$°Ìóà†i¯9`žÞÛFZ˜÷t´š~ÌKɪ°]ÕVÝ*kœb›y-ΓvËdqž@°9¡Y çÙÌR;/E_`Ùyz,›ÈÁÎcäy%#<Øy.Èrx:Ùù¸éü<=ü ÃÏã«Öõq/[~¾§šíÁêlYõ´Ç9hy}hfxŦ`_La¹ìÑå^ q€=¨Ó—m ìKؽg°g¹%l9ОRvÙpР=³g¬pÒîñ—gôî©hk«0º…ûÂéU²ÑÀ})ö.7p_üÊpÁ}f gÎû`Ð^†3 —Ú3YÆ.²´Ï h:½Ê´§M Gk8 hOOÁ•iÿ@{p‘›Ï¢=5Eû¥fÐ[7Ó¢=Ut2„E{ÚVûtE8à>µ=·Í÷DM·¬…{N;ý\ìîY l[Õ•³ïÌì×͇àæp4XrœRÑêÕøiÀZõ§—L‡ŸôþЦsÌã‡mnoô¢æ‹¬kbÇ£²¢!^BÛŠµ!ØGïaŸ².»}ÜÛC3å1óè³!ü¨Ú p ²<1™šPÅ?¼Gÿ‰Öö'Z ÉGâ’r4ŠPvW¯ 'a/lx¥ÚÀƒ·Oì>Íù(Հ߅"pÂ&¥>ùÙïjy qÉT©vrô¾ÞßT·Þ[lép_lÛïÛ‹-¤»-¶éý^ì/^Â`IC’Xþ½AÖ»M:ßoi30­XÖÔ/õÇMSù§õ’¤Fx¤ÿÖí õ½x‹m¿ú5 [ÌV÷í·¿uúKGÕ89Ùúí—›Ñmeÿ‹N÷=pf‘tцÜ3æë˽¨ÿÉ:”¿úõoþúoþöW÷ÏøÝ5$`‡1¤?¹U\¿ð‚(Ë!7„5”öÉì5åþî÷¿{/”Δ˜/”µDN?KÌ3— ƒ»æ61%æ™F' ³.GÛ”˜gŒ‹ ²Œ–‘ßJÌão>B l+¼ú^a¾€ûápû ý—˜/.`ÓŠƒäÅOšóYôh¹4ˆߎóYjtWª‘¥ööVb>‹Ø’R×r¦Ä|¦ÎªjœÄ·£Ä<„"jBÁªkw{‰yÈH¾!œˆc*ÌcÐ]é#QÌ^b>W–|*ÙQ‚™ó¹Ò-» ¦*Sa>ÓzY3ÕtU˜g[jµ‚ ©0æ†F>⢬É^a>C¶‡ø†ÕÔ¡ìæÙ†5qQÍT˜ÏC[`ºR±™ óØHò Õ¬Åç·:™N·XÊRDQ§æù­Ô| M4»¦Â|ÆQn,^ªW…y~¬D ÓüvT˜—9uË·£Â<ßó\üTeì{…ùLË (!1ný¨0ϱ [ :ν¼ŒÁ,„¸ö ó2?ü5¿æù^[žÆ{‰y6¡_·»JÌ˲Ԍžƒ¶m%æez•j -ú¾—˜ÏXÛJŒUÖßÔ˜ç7A å“¶­ó\z¢kù·£Æq›Ë‚e n«ŸÀÍþŠª€ýî"›Á²@úÂÜÅS[Ÿ“c€wq€/¢ºnN7DÄx7¹{œ±,qp‰l êœOàæ81ø,4zwñ”ÿu;Nà.Žf·„«BŽº K/ˆ¸ã6—*bAý ®·Ù[lj˘ƉÛ\1òóžÁíâèÞÒ€êÂaÜ.®~¨)AÁrÃm2œò*7¸ÁmrX8I¾FÅÑ·¹`XÌŠå 'ns(tÃq¾”·‹@ Ýéô n˦£¯õêÙq›ãÄ9n Äw"wq‘Úx Ø rs¸"p¢?¡[–Ó~Tµ*r#òáêKþKÒ©ÿºÍ‚7î\ìFnÜà „ ¬Vó’ofðk™ö¥¼ýÎXðÆåÉÈÌXã…ÝYÀúA ‹ÝöUŒÎ+Ûf°›)æ þ´øüv³ Mo!ØÍLuŽ7ÊLìšø*ˆñ‚n½3"»+f ›Á}z`ÂÝ„ÙðÔ.èÆH< ?ˆþ€nqØbÙ Ý¡Jþ>Ÿ%¶ÏBw?‡’ƒÞ0º7¹xZèæXƒ)º —+މŽÅ@7æƒÛ¬<ì¿î xØ!wdŒv¾ë½«È%Ò6°µ¬´Õ’Hf¡öèEKÂOEòMá»2ÓµDíJÌž¢æ$þ¤fC¶¾éÄðYï¯X“úcM_s{£¦Z¢­žÔ2&v”Õ4¨-vù ŽI'j‹‹0ÓkT¥Am±•aãX‹ÆÔ„‹ôéT%¾£6]pº©\M'js(É3h®]¨-ö×$$ëDmS]S[9Q›‹ ÖE8µÅZÖKÙ ¶Ø¡f§–4ƒÚ'3ù:U¨‹\&.˜q¨/ÇÚZà+GqÑ<‘›µçðW­ÔºƒL“xØ™—V½ïÒ‰ÝôwÝ<} v“ 3ÿ8NðƒRêW1äX¦»§*|[‹7Ó]$C9-óédº kmäádyn:Gâ2ägyn´á\¹ÒÍsÉø€?Œñâ¹™kãêöbxnúiÆ Gýâ¹ ‹Qàþìb¥>xîLPcÁÈOxnÖäÅ‹^Ì Ïi„¨Ã‰ãà¹#6qư,w–š¯7ÓÁr³0)–³…›ãfföéc9î,™Ù%öqqÜ™S±Àþæ¸9°€ÅxÞ9nòWä›]½9î,¾Jô ëÇyôpuA Ç„:äšrqÜòÍJg³zqÜ,±#M¤/Ëq3‰lëÀ|aÐ,ÇÍ(Òåtd8n 0Í89t‹-ÓÇÆ?Ç-Ã=)\ØÍ6ˆ£äûÅqK} c¾n/åmFĪe¸©É%ŽËÎ0Ü•1 ¹æ4šv†›Ùžq_·6àyg¸yt âËpÓ±;O/ËpKcO[ùÝÜtŒׯ¾gn&&ÆZxuz»î,oÅÉoØa<Áw…ÍÒµIÕ€ +WíR-/[ß´8}ÖûÊ¿g?ls{¥ŸêV™GØñèus¨•ykk½>3e]vûè}‹“™òØyóè»,Nì¬E’ ½6›èKG¥"XƒødsZ'vaÃ+ØÂ† /žØm>e‘Ä»PdÌ ¶ß·Í ²k›Äôþ¶ÍißÔŸÅæ$î‹mû}{±…t·Å6½‡Í)²f„à ¥7_²9™N^³9Ù^^±9%2û©÷gþ°?itbËntúÃ{Ëè$^³O*.Å¿KÁS3·ä_–«€l¬^ûÔ°Ílq}mõ»ü ®ÑU™šÈ%,‚å"3È‚Îül »ü[Y²3<2•‚å XY+­h¤M»øK¼¼°âY)X>$›%ÇSh‹ê¨Æ]þ­ü¦®é²Ä]þ•´€q„Ö´‹¿•² €&i8kÚÅ_Ö U“¶íò/ƒžý´â'l³­ ÆÔwØ–©ãÜŒô·e9NaðñÄmÚ]Ñóc“Q©¬3sGüZþî¯Û›àÌ[".àÎ,pž$‡÷Ü$S'ÜM¿€¼lÀÉžÀMÊYiñnPpã#ìÎ7aõy »3À¡¤P‡‹ÅmNGh]g°ã6Ùž-ŠÒà6¹3r–ÑÀà¶0+#©ÁmÉS™òg`³ññJŒ‹êÿep›N^I2"»d9nÉŠûíì¸-ö¹q°/†›¹¿b˜²ÆŽÛd$KÍí–ᮼ&¤BŸOÜ&»ÄÄ&ƒž-Ã-Æ;'a'pg1Z …‹á.R]+¯+Ög˜,ÖÌt1Ü”ØòÌcnÚØ"ؽÈ,ÃÍ )°¤IS[†›(¡u;ãÅp3Àz¥° ·Mþaâ ÃM»ÎnUb6 ·$'‘¤-ñb¸I2ø¡ç›ßæ(cy\C,¿û~-¿”ž 8Ëp£qJÃkÁ2ÜtÇrÊI] 7c½Í.†[ÒÝ¥ê@õÝËnIbò÷ÃÅ$‡¥n7ÃMkx(§¾–ᦕ5@,â\an&®Æ¦²çÅpg&ñÁ4²ÎrܬTI;jŸËqKvØÔ;« -Vóh¬IñÅ‚êjqjâ±%‰ {4­ò£jyÙþ¦ÍéÓþßÐþ=ùaŸÝ+µ~ZŽG¯›|zʧÕéxôúÌ”uÝí£÷­NfÊ:û軬N™ú>Ÿ}¤à»V'b®GVÞí_1p½muZgv¡Ã;Eç zûÌn3Ê?‡ÝI:ÜM!¶ß·M!²o›)Äôþ¶ÝiÛV\¤?‡áI{Ü—Ûvüzv\¡Þm½M÷ßazÂ#²,(Ôúk¶'ÛËkƧ£›W¬Oô3·˜æGŒOm™žþõïÅ;µXwQ˜ÉàFH?Ž#Í?ËôÔèñ¨Ï[J»íÉSGδþÚVwÛU],ž ¼wïK‰3}¤n«¹‰ÂÕNrJÓVÞ„j2­E“¥¶â6Û}¯âS6©1oäòA&á@°ÐìL,å¹Daœ„ì!–7ñ½ju+mBƒïè8ËÙhÌ»4ùåC%‘š”§yŒÅS‚—ÙÖ¶º&’e&lm«jB]7ä¹GŸÒø•¥ÉtÅoYCšZ_5M¨=ž_ÍR­o%M(ÌS‹4â¼˯,Q¸îÅĺs»(Ü -øX“8 ³¨ó…¥Me8iÛÊ™ð›,Æé½(:“ÖLÁ4ш…'¤¶¼Ö{Tù‰jG(Zçžùï4jÌ—D;Ò]ŠÂD]~™=¤M–ÁSÿü¶J&|χøøWö¸2½†È7cÚmO”8ì îïÕV¦(LE~*Íi&ŸžÜn{¢ŒRYÛVy ÅÞÓYoe™žA8ªŸéy«`"¹q Ä<½.pòvÓS²°þOÐ÷ê& s‰±šQ >~…KwƒQ2ŸUk]/[ùêgj¤ÿ~жºÛž¨»©sÅXieénȦΔh½&ã{)xJ±½ÖÝöäè¬Ê,3B ÌW¼|/qkIè‘심,×Kêƒ<Ž¿,JÛª–0ÊNM`:¾-ák[!:€óîy)Ù}é¶,#a•¥º)T×aÚšÞHîWzâÀàÜ|1ÛÇ—lOn3cÐB«'nÓI?E!ƒÛTµ`EF‹ÛMçŸ@‹Û™3ÐynSÐg2" ÜL¤ãÊcàN\¶øXø,p'jäªÃ[õn‰é Oàæ09õ®% ps(· Fs·ØV FÜ{µÒHä¦*7 ûÿ‰Ü%2È0»áÀ»#·¼ÆÈ²¨SØ‘[^“ê±âÀ`›Qƽæäk'rSãìWâiƒÜÔTw±u)ÊîÈ-ñ\ý 3À-M’/Ÿ¸Í&¬îã3¯¸-)LÂ%qj0¸-—{iË nÓ⃥‹*ئþhï±í„m¶Z5äÂÀ6?økõÈ6°-f0Œœ¶®¶å›šÿ6°M+ ®ÓÚhø n [ã°gE¡fÇm¾Fë‰Û JölKwâW¢ÏÛ|-,#¤m1²x†¨(ì°MãŒ[&]Ûb[óŒ³QÔÛ`›Ÿ,èmĨØ{OÎ…Æ”¶Å^‚€¿«'n‹Ÿ~ÀA 'pó=“ÆÞ·æÔì†'pË8ñ‘aÊ3À-©i˜­e*Ùæ‡Wü—‚T¿n~:°›—g¥Oxn–Ç–;^Ø a«‚kvGæ(ŸvbƒÝät·è>‹ÝLTÇú?Z$ÔbwdDSß¶cw1,‘Æ^ì¦û˜³>‚²-ÓÍš’ ®É)ÊÄ~.¦›©WõÁtljåÔ´®–é–R”ÓËrÝ…aXþÉtvpÝ’÷‘^27×ö`gËuW±Ó<¹Ú®›ß­|¾¸î"T÷ä×´\7+)ên®›ÙØ5Øëæºñ T=ùÎu3 ^ŒO ëàºi±’‰²§–ëfùéiBÓ,Z®[ò?¸'ÈØrÝ’ÅW3|_\w‘@V˜o®›ˆ–ª…R-×M# v?kÞóƒëö¬=÷X ×Mû"¶î ÛÍÚèm°l7mh¸X'´ïl7cÇ7ðÝE¤¥0Ò³[¶›L+`|¿ð[h¡“âÍvË9¿Õ”† ÛMËF Þ¢žl7aO.Y»3l7# Á“{e;ØnI0-iïn¾Û1hò‰·Œ73hö™&á`¼¹Ôm\Ë–íô¤áªÜl70RíŠa²Ý™õP›Ô¸üÛ=*º<-@ê^¥å ãï•?xµZà§#xG˜§jM𕞼Sc‹¤“;ž½n’ª¹…õ{ç 쳟aû¬ÇâÛg쬟A˜gßeŒª8é!0.Sг¿hŒª,² é²Y,Aƨýô.¤xepxÿôš9eIC—ž||ovi Úžß·‘dk“²ý¿n”Ú7×w©§'…‡_\ruJÛ—Üöüú’kTû¶ä¦ÿï°KªF*ØÂJ%Ô[v)ÛËkv©£›WìRä 1ŠGrñ?b˜J»aê_Þ«Ôç(}>EËyC÷'ï %YÀ§hy‘¢ìÓ¯Þwga½{ÈZ" £ñPrú•¨Ï;ñ4Á6¬üä"Xe-xÆ$™A¤h9)‡ƒçxÓè9齨âPÀ£÷MÑÉŒ|¥$ÚN4Š–S»È<èNsŠP¯¹©:+Ã$ß4«6˜g“;1‰Wµ+«NI‚=ÂA ûø¤Æ44Ö6H9=õ9°V»ºÓS‡9jjmÊ{”½‰A1~Ÿ§4úT-—p®0Î-úÞô¬:Ù+Zð~×w2pvÌ«4«$ ‘’å̉¹áq–öžB©%Ë™ø†&®QS»Ê“åA]M=äиë<¥úO~*@àe®¸Q²\Œ†5CxªZœžé…Ÿ’匣‚ ™£ Z™=Ö,Å#Y-ž˜Ÿ“l!BÈ™‚ %AÍ«ˆF|ï!d¾É º0*«û´KÏxsdVÑaæ]|î´C²<–V7ó™6ËAÈÔ?3!^?+Yß!gæ6R\Ü%èNQ SÆ¢–M„¦®‹Í¤-Ú†¿}™Ã ¡ ^w!ã¡¡}~µîR4kÈ#Ù «äª×»€qa¥ÓèÎI®z½šÑæñÉv„Æ]Žî¤¹òøÅ¢q¤éÝë“LŠ·ö‡Žù&3áyJã&J3ŸKma”ËCÛ.K3ñ&„ߤմ@¬NRÖ )Óþ+U$¢èzÑÈBYƒ”¥Òô(…Æ]œnYRFµŸ²BÙBU4µ)±–ßz(™ã‘¼ôZ/°˜ÉCÈ´9³ˆ †á§ØÛ˜ûûòE}èW‹û]8µÖºŸáüV ñÄyz¯Î2>'ÎWÆ/øQ’îÀyÉøƒUŠ‘ Î3Ûàz¤y=pGÐ…‚æ æqÐN4Š`0O}ü–Bj7Ì'ócc>`ž%%®”â,Ì'¦Ó-O„æEk’Ó”tÌë…ÿ¤—9`>²ðÓ ¢=`žEZ‘èÉ èùbÎŽiZ¤S¶é¡¤§#˜Sßñé#c{Dûëo¤ ߘ•m¤gcNiÄÙHϪ¾q›‰Az‰òZ w!=ø¨4Ž9æ é%rI ƒ¤ éi1 ™9›Òô´œ Ò)íBz6’—u~Ü9;ÒKJAŸa€çŽôb÷S‚|!½Dй&AÖ'ÒKäV mÞ<;ÒË‹$˜Ë…ôʲ<á`è5Æ,€Œž[`zéÒW±@]H/µ.µ q¹^Bœ2.¥0nóVm¸8¯Äü^Ò³±­ÚUéùÕ¨×Òôb£F~Іz±÷pŸ è(5 ôWU¸…ʳ —°žÞŸlée°®³(n¿ ^Soú>"KfÝ1°²ªô}³¦ÔõaáîõL|,ùHãõMÞœo¬—¢¬8“ƒß7PÏ ˆÍ—‘=ø€zG9ÝêÑè¥÷à÷w¬÷L½­xÖ“§«3§Ÿ…z^±%ͬwêÉBÑÕh$W³P/&)ž×ŸêÅñ cT÷ õt‹J‰aVšV00ó‹ÙÙ¡žÌÅSÉà<ÝËÔ%"• çi•b`ŠKŸpôj¡‰,ÚQ.œïO7d` a,Þ¦Œ!Œ (0öî/”gôo‰™-ÊÓ3çâç™Ï­åÇÅäàçĶçü<({üÔ;øy†Þ'f.W€áç)µârFšƒŸg ê<«°üÂêl½¸½Òm/Tñ_èLŸá¶ü›Äð˜nŽ&8ôçvuÄ~õkÿî?ïoÿþÏêR™ƒäøò4 -5ΞiÌÇ×µçoü÷÷ÿåÛ?áÿ¿#§Ö÷ ÆÂ§Wj6 Lz5öùh†>))ú.¶|uÈG/vxϰ½ ø÷ ëk3Üiʼn•Krx¿·‡ìP÷ÐtøÞJ‡÷ ßÛC9t÷ × ¶1†5ü¹ØF–‘Ù¤[Ü|eŒÙ¾ß|hûˆŽIiZ£Gß°†ŸÔ „%ˆÜà‹ÖŸ\³—ôÓz)’ÿGfRþ¬Ûç—ôïå¿Pq‹,›èÈþÞ1¯zf†Žo•XG24³Ö\Wþ“u(õëßüõßüí¯þîŸÿð»kL;ÕüéÛ0{á˜úKà¨èð‰_Š)föÿýþÅbf¦†7}S[dVrU·ì5¼eÑ QHk ˜ÞôHÆkŒ)d¯áÝ(Z;©Î,m{ ï&U1$ϘÖ÷ÞŠx7/1V°ò¶ˆw“R!eõí(âÝhpƒX4g£)â]%G¡ó#+Í^Ä»öˆuh¢ÉøvTñ®tPŽñÉÖnÊxc¥¸‹?´©ã]©d¸7¦`êxWæ~ÙÞÛêxWÚv°*#ÔÈÔñæ'Kžþ±¦Žw•-iØ(‘iMïÚ˜ñiZpM%oÉ.«FXSÅ›ïlUoLïÚ˜ÅSú—UÞ«x³Íaµž¶½Š7ûÂYÛâªâ‰|@žC¹ªU¼™U¤'fàÌZ©{+«À¶´·mYn8ø,U€´Nú^Æ›ƒðcߎBÞ&<ƒß y³-§¯BÞ•š@&ïñ’@ÑTò–‰ÍH¦·L!j ê·£w·[ÿÄÓí…¼keÄYv£n)ä}µm…¼™¿¥tÇÌM!ïJŒD«Hw¦7ß ƒÓúß«Ž7™By`ÁÔñ–Éá´Ÿ¦Ž7G{sUíØ¦Ž7GÒ±^#«¤)äÍ‘LåèQÈ›mÕµYÿ{Ëq#M<"úWSÇ[?Ÿscêxs˜‡Jkì˜:Þ¦_%,ÓWM\zÍj1›ÊRô Ù´hîj 7dã| ¿÷xAv•Hç§°…l–¦¡% ˜³Í@‘>Ï€…l$¤âlœGÙEBœ×€Ù ‘|£ÐOÈfÌÊ~ÄwÈn+¦ÛW?ÙyVG)Ckh ›é%À"4%tƒØìγøa>»¥Â`®:êLÀÖ€œIx°d£ŒÌØX¥'šìÉlÎý1 ÍìtÔx€~mN›Å:Sþm^á)‹ö6ž Ý$ygã"6QÚg,>?{' ÍA€µîªí ÝBg˜ƒkñÂì&Q‡=X&ƒÙ àûăْ$Š)°ž˜S³—R2˜Ía2Ge×lg³›†2¶gwÐn4K,Ö¸ÄvÐnH“¥ÙA›Ca<ÿs¯ï Í-¥IeUÚä èµÐÕ|j@»)zîXÍÑm6ʬ[Hû X³ Q—©k%*÷Ü̬›vÎ…2`Ýlé?ÖÜìë¼v´n’w4Î `Gë&öb)ÛN´nb,© Zs7®J$P ¤û°­_‚ë/Z5-bI%-ÁTdƒ\ÑV?a²ùKœ¬“El¢ù:±[Ø™e‹ØhóôUã¢ìÔqèuu.À¦¡ Ò‹UŽl$¶ÅÑì€Í;ÀÍ­³€Í{%‡‡û°€-Ñüô>S¦×6ëð•qˆÍªˆ~2Ë;d3©†É:ÈÆ >ù°€²YáSKõù ²%Ri†bZÈ.åC+u*,ÈÆõ‘@èa —NÀ~<Ðk ;³6[|X( Ù™…©ú\2ÙY2µÏ»Q!›¥\—C™…lÜS½¬ÌNôˆOàÅlлµ§³-^’Q5]˜Yau‰i³1é螸i ÙÌ›Øën ›¡©yòq²O»ø8ÙL§Ë‹…lÌn¸¼[¸f1¯0¹. ×dYezùYØf8cÅiW§Û‘Ö†žü@ßµ#Óæò[ÔNá‘ë,bƒ%ažŽqe[ÄÆ¤êbI,b'fäŒy b³œy\·‡Al’MV´ˆÍjmŠÝ±ÓDħ|§ ¶ø¶Í‚ªoú¡ÄfÖ?‘XOÄf fFg©”l![¼*&†Ȧ¡cn–7È®=ï÷Ÿ…ìP÷CuèEHCK`õ"Þ0q³1Nf Ú3˜í¤Šä ƒÙÞ²y³¸S>®­·^d±V/RéÕP>ÃìÊåuZ½ƒui/íÖ‹Ð'´ºÉ½ˆ8n¤Éö½ˆÔ›â«Õ³[S7º¸Ä¥:¸«¡—Äv;Ý¿Y$Ýk{æ)—¨j¤ˆE¢÷¡ñ£š¶?![ÞãyÚvÕˆ /í™QСB3䯲ka¶qqÿ 'd3I­a—wÕßÛt]F7"ñ½ëú6ºFƒOšÀ¼éF¸a«ák¸É²KýÄm¾Çxú¡å³ºÆmoú]5B/´òˆ…F5B‡·¸Q£‡˜I?V5ÂÒ£8ƒ^­j„ƒ,ù¹¦­j„I˜ûd“¬j„E%1ñÁ ZÝß[ºA«‘bçóø[݋ԧ‡WµªNgúuªFÏ®¹(¾Ë¹„þ>jcùJµ…ñ'5¥²õMç’ÏzÅNÕ/‡5·7úIY}(è 0&fý žÙ]Î%æÑÏ03e]öãÑëÎ%fÊcçÝOv.¡·$Ûè\þ®o ƒqíàng½ŸÍµ„GTR2ñDûËt-Y˜±Ðé*aæ]X¶ù‰w–»ñ]0n {‡/º%ôǵÄvø.Üß3|ϵd§•­¦ä{{ÈuM‡ïí¡txÏð½=”CwÏð'¸–©FžÅü-×ÛÇ[®%¦—×\Kl/ßáZò#ŽàÜ5çBcý¿xÑo#öÃo£öa ãŒßFÛ#OåùeT‘Z5f&¹­>‘Ö…K~+KÔèy.žø¢ÄL”÷§^ÎElSxÔ ÉµDØí3)lj‰Ú+„iHÁ¸kH7a÷Òp”g’·rDt›€\T3˜¢è-†hÇ8Õ•,QÊÿÿ›»¢lÙQøŸÅ܃ XF’Ÿ$û?Q #©è›LÞÌpÏü½×Ün—E•T²­]G.IZ"@)¡QSÂÆÄ­Rb’ê3Ë’=J¡$õÓR)ICžæúص¨”¤‘ô£®Õ/¯ÜÝQT¶Äœò„.Dȳ¸»Éyå ]ˆ4Aónt è×»R*R¿Õج´ÈA Å¡]ïžpCzFGíÓ’¡J›é0°Ã­|aéÄAÈq.˜ðé©÷HA4´•JíUuKDÓ_¶ÊegÀ(l¤—")ƒ²3ÚW wdPv†VmÔW%¨‰²3:îê¢'j¢ô ´Ú4Ú¾&JÏ@ÕRYôK½bzìZѯ¥g€µ¹—ú\¯Ð„cÙEz‡&Dr­"kSoJÏ@êÆ½X”z‡&Dz‡\%¨™4 <øofoB„«©Žs»^ó–ŸñÈz‰ ZB"ó “Z(?£Èm6 ²–-Aã~ÆýæC¡Y¹èo:§}Ž|ÁVˆ5ÃÆB"\²°ÊôE-=ÏZ“§46p–+¹ˆ×œÑŒÖi:gm\fô7ƒs£qŒÒ|Y²/5Æ( µ¬”…‘Òðõ+×b- ¤¡–‘@?)W³¾ë+¢µfLTK¬!´†a©†\ëYÊÌ:D¸†˜ ³YÌÁ54%\ûÍS4 Úr&¸Ö|aË™àZõ çÆ®U×ȳþlÇí©ç›0á6”ï[`Û°9à6´¨ÑìI&ÜÆ˜ ÌR·‘¢ñ¸*@À­é]–à¤&pãC®·JúòÜäy=:¥h4ºÛR4d¡»®DÀ­×ªøb”¢Q¢LKÀÌù¿ÉlÜ8Í+ÀBÚR4ç‡ ¸»%tŽ)•ÁyKÑçf½Š ¸‘\²g¸qšI÷R½Ü8Í`BÀ­™$ëmÀ)tS#nã,©&ØÆIV-,½>`[o9ŒÍ¦~B°­ëÕùh‚m]ýYk’`%—LéÍ ØÖ ܦlÏ´ ‹ºtC§§WÖj=¨û1tOÛàù¤îÐ ]씹e·ˆFnùÏðÊcFnù‘ÝDä–ðþk¶]©Ð:a_ß±C÷_'æ÷&p ÚzKåÛí!‡3h‹´%°+öÜq¤­¥ë—Ťi7y–óÒö8ÒnôáH{ äÞ~’#íG¬GÚí«¹ØÎ!7R›=k{ ¹:¦I-Ã¶ÜÆËåo†mÜqôE›<¡vB«ó¶ž,FmÙP5ˆÞp{ÀÕÀâX·±rÝr™ãí‘éü(Þè k™™o÷ÓÍ9Þî5fìp¼5+)ÞF {ÎAsŒ·ew40ë¹¥áx[&[}%S¼ëàŠ+ÇÛøIKoñö€™ÖÒà9Þî°x,¥xÍ`S€ûo#¹Ü7Â[¼ w"‹±(Þ–-|Í–šÇñö¸b:ÇÛxà$ ]á=ÅÛ¸Òo•ûG¼Ýµ)†}âml,¿Òoã Ð@PŸ*Ž·1õÇrug¼=â•úeÕOÖúËW¢…è¤)ñ¯Ércô¤ê÷ÝÑOPˆkÿs;rœ–¼¯åœ}ô’[»ïkù^ÛøÑœMy^öí£ãªMù½óüÑïQýʼБ÷~¸¤\^%°§‡eà•R÷+x· 0Á†ô¯)û9h8<YCýàt4Â|_•gÑpJFtÀs’‘ðs†ç$#]Ÿ3<'ûŵò#²8ï!ðÜ=Ô~ÎðÜ=Ô‡îs†@öËh¹Ò³î—NÉ~|ŒS²å˜ìÇGùóe¿‚ý˜lo‰ÉŸÿ­û¡î$ê~ÿüo˜ÿO÷Cÿ%k ¥Ôò›'/XrGz¢£Õêžà‡hÞx½GY[Ku„4~VwY/Ÿ¨Tç=ë …õä)Äp ujun²…‰ ôê[¾xÑç,ªë©ñt°«rÙP³Ó[ù‰±îÊ: :µŒ]£çôÊÂó¾P*a6+r}j÷¾PÈž–EºxRí|hDìRC™+œdÍO³¼9G\疘˙G§Åe‰‡¯…)4:?1¨ ùiÝûB©Òê•pOüÄÐÖq‹xz”ñ^ã^ÇëÝíð°ûLN-?ƒHŠ;R|ϨÞjò V"þ %)dK*ÏÌ*moéò¾P8ù°«n‰J¶a[l5 ·q-Y½ ^eÖ®HR íõ£G~b ܺy6lü×jmêßdÕ÷íŽü„çøÄ@ù(iÄ*o¥SjàvSr 昸æÏ+²Ñs“íÕø ÿæ»E=ðßÿ÷ú£¤˜±,×ØÙ‘QJPÉr {—',ÃïÓä‡QSTs,àµDE0Ë¢·tþÖ]®Þ±ìtÀT'f,{mÛx ',W×4ÇÓbÂ2¹í ôíòüz¬ sÊ­¶bÈŠ1W­ÑZd+d#5»§ „æÎTô¯î¦Ïíºœ© Õxô™Š.O¾9]‘"S7ÃÅÑ tÄ‹fãÁ} U—3èZmë|ƒƒÓÇí›7ÈFaÔ‹“¿ÞRÊúÙ¨hMÆÊ1fÃÕÓó¾³xÛ³a`éÆÈŒÙÚKlGkôsWmFëÚcÉ£5jg^+·­‘dRfsÛ­1”]?$´VÏHoO@h­a³ULp=½&Í”àZ5Âl<^„k\Ó.ð.-‚k5yôB‚kÕ³¡LDkh„©ÔÕ̎зwRôÔú± UÔ |ÔºZ,ɘIjuù¬V#M@­’žÑ„ÓêÂÝ­Èp«Yëß—LÄi|ï•$£ñ WH«U§çXDÆPðû'†ÖÒìDÆ÷Š3ßÒ ¾ÒzšþÜH÷Ù€ùeÅ ¤!Þn6J Ó ™Ò 濤çOš6J ­?éº3µªŽ^E@=OÅ_訧àêß‹@­‚«§BR«RfÞ ÔŠˆ¥{ÌÍãúÁApÃj\Ͷv¬†‘¤¿a«+…[|MÅÀŒÕXGÏc CX-¸z+0V_%¦bã©vÛ]FìK 0[jÀ_Ë\“¿±%.–ó Ù õ»&ç0d'2 dÈÆ˜ÇNv.ËD—bØcI+`#!!¯'ˆl¤ŠÝVÈ6böfúØ}DÇg°<ÌMöæ6&^ñ¼Ø6ºK{ä…`eÏ­[^¾›ÚìaÍ!öø©RÍ|k·øÙ•¶áø×´yäÊñõàØ›âëÓ·»Å{ÃvŽõ²[€Ýc]Ü`óë…lRB· Vƒ»Øx|\ß!Ûf‹­e‡ìÝ+¶ØúÂÀ6#1¶Æž)À(ÅÖ(Îó-ë_XµËñµ|/ßp|=b©,Ç×›uS?ìàFºØp ±d˜`CHw_”_o0›ª‰qXo¯¨Koö˜Åm2ûíœá«é>Á#GºÒÔ½àb½&GŸý€'@9•/ØlÛIÄÏ~ä$â¬ß‹¿}v\äY¯“àÏ~.([|¸¡%¹vÇ>¨ ¶,QMo¹ÈîõùI]°]~Tò²¸ÑUû¯¨ Fq´:²@GšSU#˲ìBòí;K‡<©+Õ%n‡<üøf–¸j®¡½R듎ÞËY\ôyȃ÷rú­|sȳ³lßÌò¨„ÈD—?/òN,ǺÐn9¥òaŽ©„Ûaþ|•P¶Ú½— õë7dÂEÂkòš@Àµv ¤OôãM©fô'’íöƲ<…ëƒÜ‚ê•hE—£!›lÔ’62©—vg‚;ß’Þd¬¨£Qéy»§(ƒ‘Âeç;‹+õÀaàúMÆäWe T{}ͪ¼I Fcz,¼Ûa ì"‹!ûæ`$(ƒEm&*ÈSÇÊ`S_£ ÿ׈-J%`ŒD†|3¸É`$Ÿeã/7xÙäÈ ü,.ä¥%Ž9²8—Œ:ý,zvžCÆ"ÿ,¿òšÉ@Sg£G¦£vCüœH_ïÏ: aÐØ2ðÏ2œ]€0…NY 'y VŽ‚° ÝjðE§^e°¨ÅQ.×lWô Tõ†ÓÆož˜[»2\‘d©¶k§;úÊ`ä¢QÝéôº\†HF'\ sì‚ÔúuÙ"N—Ãz¶ #«:ÍU ‚Ë›¢H y $ƒxéƒü#¨Ùr¶WÆäW×*Æ{üb‹ÔÆèQ—ÁÈm€vrP›¶8™oÔ—¹ãu!>^ËXµðÐŒùê…+ ƒS° 6.)¼osmÒNßc-c|,“X ™µn<˜ŒE¢C¯Åš´×‰.eeóÜßV 2æRV ¾xoÓ;E®Ǽ ’î+r ½¬AåW×RÖYy¶ÖDn”'¯¥ŒÁâ ¥ 9üX7Ø Ü¡Ý·YDû‰ò#f˜o(?/yzÖüå; ÑŒ¦ÞP^Y®%aD=|H­áí϶‘Pº® ÅóÐCpÅñ¼2ãþ\p> endobj 8 0 obj << /Type /Font /Subtype /Type1 /BaseFont /Helvetica /Encoding /WinAnsiEncoding >> endobj 7 0 obj << /Type /Pages /Count 1 /Kids [5 0 R ] >> endobj 9 0 obj << /Type /Catalog /Pages 7 0 R /Lang (x-unknown) >> endobj 6 0 obj << /Font << /F1 8 0 R >> /ProcSet [/PDF /ImageB /ImageC /Text] >> endobj xref 0 10 0000000000 65535 f 0000000015 00000 n 0000000145 00000 n 0000034138 00000 n 0000034159 00000 n 0000034182 00000 n 0000034612 00000 n 0000034481 00000 n 0000034376 00000 n 0000034539 00000 n trailer << /Root 9 0 R /Info 1 0 R /ID [<04A2D892CAC4E9BFA6C9F6AA98A37E66> <04A2D892CAC4E9BFA6C9F6AA98A37E66>] /Size 10 >> startxref 34693 %%EOF blis-0.9.0/docs/graphs/large/l3_perf_skx_jc2ic13_nt26.png000066400000000000000000003170071422157504600230110ustar00rootroot00000000000000‰PNG  IHDR¬öEYa )iCCPiccxÚ•‘gP”‡†Ï÷}Û m—¥ÃÒ›T) HYz•^E–ÞY–"bCÄDiŠ AF¥H¬ˆb!((`A³HPb0Ѝ Ü¹3qîüÈóë™wÞ9çÌŠ*’*àû¹Ø³CBÃØð ‘¼Ìt®'ü#Æx ÿJtL&V Ÿ—Î ¹ •#H Ç€•”.@Γ€ÜfÜ_>̨¿|˜ü?@¢Å}ãQßø÷¨pù‚„ؘ\¶Z¬ '’ÃÎôs±g»98°}øi± É1ßü¯Êÿ€ &Wà–¾…Ÿ/`ÿßPcC##øûï|„5ø¿ÿ€oziœEìÀßYT5@÷é'gjÇD ºîñ²øÙe8‡ÏÁá+ñÍøNü ü(~ÿ@ °šs‚+!”HØJ(%%t®† S„E"‘(CÔ%Z½‰‘D±ˆXMK)Hq¥b¤öIµKH-IËIÛIÇHKwHJ–aË8É$É”é–y&‹“Õ‘õ•Í‘=&{Cv^Ž)g%Ç“+–;+÷D•ב÷“ß*B~P~QAQÁE!]¡ZáºÂ¼"KÑN1Q±Bñ²âœCÉF)A©BéŠÒ+¶$›ËNfW±ûÙ ÊòÊ®ÊYÊ ÊCÊË*š****ÏT)ªÕXÕ Õ>Õ5%5/µ|µ6µ'êduŽz¼úõõ% M`½Ý³šÒšnšyšmšZt-[­ ­F­‡ÚmŽv’öQíû:¨Ž©N¼N­Î=]T×L7A÷¨îðü‹5©k׌ëÑô¸zÙzmz“ú,}Oýýný7ja  ¾š&6>5’0r7*0ê5úÓXǘg\küp-}­óÚk{Ö¾5Ñ5‰19fòÈ”aêeº×´Ïô‹™¹߬ÝlÎ\Í<¼Î|œÃäøpJ9·,ðö;,.Z|²4³XžµüÃJÏ*ɪÕjv溘uM리U¬#­¬…6l››ã6B[eÛHÛFÛvªvÑvÍv3\mn"÷4÷½¡=ß¾Ó~ÉÁÒa›ÃUGÌÑűØqÈIÂ)ЩÆé¹³Šsœs›ó‚‹©ËV—«®xW׃®ãn n<··ws÷mîý4ž:ž|Ï^/ÔËÝë×Äzõõ©ë»½ÁÛÍû÷3MŸ ŸŸ} ¾>¾µ¾/ýŒüòýüþ›ý[ý?Ø”< Ô Ì ì  j Z v .†„l ¹*šÚF k[Üà´áð†épÓð¢ð±šs7ÞÞ$»)yӥ͢›#7Ÿ‹ÀGG´F¬DzG6F.F¹EÕE-ðxGx¯£í¢+¢çb¬cÊcfb­cËcgã¬ãÅÍÅÛÆWÆÏ'8$Ô$¼MtM¬O\JòN:™´šœÜ‘BJ‰H¹*‘š”ÚŸ¦˜–›6œ®›^”.̰Ì8œ±À÷à7g"™3{LAº`0K+kOÖd¶MvmöÇœ œs¹â¹©¹ƒ[t¶ìÛ2“çœ÷ÃVÜVÞÖ¾|åü]ù“Û¸Û¶#Û£¶÷íPÝQ¸cz§ËÎS»(»’výR`XP^ð~wðîÞB…Â…S{\ö´‰ñ‹Æ÷Zí­ÿ÷]ÂwCûÖî«Þ÷µ8ºøN‰aIeÉJ)¯ôÎ÷FßW}¿º?vÿP™YÙ±„©ÆÚuÈëPW»¢¸âýá͇oWšTÖ¡É:"¬ò¬ê©V«>P½R_3Zk_ÛQ'_·¯néhôÑ‘cvÇÚëêKê?O8þ¨Á¥¡«Q£±òáDö‰—MAM?p~hi–m.iþr2õ¤ð”ß©þó––VùÖ²6´-«mîtøéû?:þØÓ®×ÞÐÁê(9g²Î¼ú)â§±³gûÎqεŸW?_×Éè,îBº¶t-tÇw {B{†/¸_èëµêíüYÿç“•/Ö^’¼Tv™r¹ðòꕼ+‹WÓ¯Î_‹»6Õ·¹ïéõëû}û‡nxܸuÓùæõîÀ•[Ö·.Þ¶¼}áçN÷]³»]ƒ¦ƒ¿˜þÒ9d6ÔuÏü^Ï}‹û½Ãë†/ØŽ\{àøàæC·‡wG׎=>Š~4û8ùñÛ'ÙO–ŸîœÀO?{Vù\þyã¯Ú¿vÍ„—&'_ø¿x:Å›zý[æo+Ó…/é/+g”fZfg/Î9ÏݵáÕôëô×ËóE¿‹ÿ^÷FëÍù?ìþ\Y˜~Ë»úgé;™w'ß›¼ï[ôY|þ!åÃòRñG™§>q> |þ<³œ³B\©ú¢ý¥÷«Ç׉ՔÕÕÿB,¾;E^ cHRMz&€„ú€èu0ê`:˜pœºQ<bKGDÿÿÿ ½§“ oFFss0ˆÚÿR pHYsNNÆÊ/¥tIMEã$9·-ç vpAg’Zó!%Õ€IDATxÚìý{”#ù]ß¿gXgñ®ÝvÍ:6vÏSm`~°%¦lsJ6y`צ¡’L²ó{ ¥¸IoHàqÕ/ÃIÂe@•pÈ6i?ªÃ¥7ìóÀO…›µMœ«ÂæLU\b³í›Êfw´6κËÛƒÀúýñíOÝT’J·.Iýy£3#U©TRê[Ÿûç\·Ûí‚a†a†a†aæŒóEŸÃ0 Ã0 Ã0 ÃdÁ+Ã0 Ã0 Ã0 3—°ÁÊ0 Ã0 Ã0 ÃÌ%l°2 Ã0Ì\×-ú4†af&°ÁÊ0 Ã0 Œçy(—ËEŸsƱm¾ï} 3sXÖO6X†a†a˜‰p‡•xæLÀ²~ú|Ù¿ÿ÷ÿþß}g ðÐCá·û·áy^õªWá¹Ï}n¸Ý¶íðâ$ Žã@Q”p»ëº°m®ëB’$¼ìe/˜¦ EQÂcA€W½êUáñ<Ï÷û·‡Çu†ÉË ï·Í¶mAY–Ãã8Žƒ÷½ï}P…å›Yf%ûªªÂ²,|á _üÚ¯ýèv~â'~"q?`˜i0Hfû·_øÂðÜç>²,÷È©mÛ¼f3 Ã$².ËòÀµŸe{t8ÂZ0A`mm-¬?r'‘Úeš&,Ë ·U*8Žn·, •J%<ôñûÃL‹A2Û´œòšÍ,“Êzž÷³l¬#Ë2šÍ& R©àܹs¨V«DJ (íÀ²¬Ä#K‘a˜¢$ヶÂAWÚY¶™Eâ´e_Q†‘8ÃL‹a2Ë0ˤ²Î×Êôaƒµ`¨‘R½^ÇÑÑZ­ÇmÛ$i Ñª(J赡G£Ñ€a\»ÄÌ ƒd|Ð6@(ížçÁ²,AÀ‘#f¡8mÙ¯×ë0 ¸þ‰™:Ãd–a–…Ie¯•éÃkÁP#%2LeYÓHa¡¢í ®ªjÏkTøÍ0ó ´žkš˲ ëzÑ_…aF¢Ù—$ µZ –eñØfª “Y`xfÃ,“Êzž÷3£ÁkÁP]ÒÚÚÊå2ÖÖÖBEE–eÔëu”Ëe”Ëe”J¥DZ)&¦i¢T*…‚FÑ_‹aBÉø m9f8ºÊ,Eɾ¦iÐ4—ÌT&³’$Á4MŽ"1 Ϥ²žg}gFã\·Ûí} Â(ª$Ia:/5O’e¾ïC–å0•,n”Æ›,Qš0ÃÌY2žg›mÛ°, ív»è¯À0cÁ²Ï,ýd6®³ jNÃ0‹Â¤²>h}gFƒ Ö9Æ÷}¬­­¡ÕjAQø¾r¹ Ã08=’Yz(•¦T*A×õ°6a––}†a†‰à”à9&ž|îÜ9”J¥0•Œa–ÏópáÂȲÌ2Ïœ)Xö†a&‚#¬ Ã0 Ã0 Ã0Ì\ÂV†a†a†af.¹­è˜ï~÷»ñ+¿ò+xñ‹_\ô©ŒÌ§?ýiÜyç¸óÎ;‹>•‘yê©§p÷Ýw}#ó¹Ï}+++ØÙÙ)úTrsåÊÜqÇEŸÆX,²œ|îsŸ[Èuå©§žÂ»Þõ®¢O#7¼†Ã"_›/ùËñS?õSEŸJ.xý>}}ýþÿá?`}}½èSɯßŰÈ׿¨ë÷Ò¬wÝu^ûÚ×b{{»èS™\ºt EŸÊÈlmmaww·èÓ™ƒƒܸq£èÓ‰;î¸c!k`ñådו­­­¢Oa$x /†E¿6^¿OŸE_¿ÅXxý.ŠE¿6Gai ÖEæÒ¥K¸xñbѧ1ñ¹° ÓE•“E½.™Ó…×pf™YTYÔk’9]xý^ Ø`Ñ«Clnn} ̰¨r²ººŠÕÕÕ¢Oƒ™sx g–™E•^¿™<ðú½pÓ%†a†a†af.aƒ•a†a†a†™KØ`e†a†a†aæ6X†afD<ÏC¹\N×uÃý«Õ*Z­dYF(•JPŠ¢ýõ†afnà+Ã0 ÃLˆ,Ë¡á™ß÷Ã÷€$I¨×ë¹ßÏ0 Ã0gް2 Ã0Ìø¾ß“ú«ªjEÍÏ[[[ƒ¦iPUõLÍÔc†a˜¼°ÁÊ0 ÃÌ=¶mÃqœBÏ¡V« M×Íc¬­V žçÁq˜¦ ß÷Ñl69%˜a†ab°ÁÊ0 ÃÌ=º®C×õ¢O#,˨ÕjásÇq`Ûv®ó$ÃVUÕÐ@5M¶m£^¯ýÕ†afnàV†a†™žç…5©Ã‚–eõ¼.IRÑ_ƒa†aæ Ž°2 Ã0̸®‹sçÎ…ÏUUE£Ñ€çy™Û¨£0hš×u±¶¶¹A$öa†a† V†a†UUÑívGÞ½^¯Ã÷}ø¾I’¸v•a†a2`ƒ•a†a ">Ú†a†a˜^¸†•a†a†a†™KØ`e†a†a†aæ6X†a†a†a˜¹„ V†a†a†af.é1Xwvvpùòe(Š‚ìïïcgg§èód†a˜¹"T«U\¸pçÎC¥RçySý ÏóP.—Ó4Ãmôÿ,|ßG¹\†ã8=ÛÇA©T¹sç°¶¶Û¶‹þ9†a&“„ÁJêÆÆVWW+++ØßßÇÖÖVÑçÊ0 Ã0sC¹\†$I8::B·Û…®ë(—ËS5Zƒ 4›M4›MÔëu8ŽÏóÁÀϲmAô¬¾ï£Z­¢Ñh Ûí¢ÕjÁ²¬©Û Ã0 3 ±6N{{{ØÝÝÅÆÆˆyr«««¸|ù2±¾¾^ô93 Ã0L¡8ŽI’P«ÕÂ×TUE­VƒeYPU54(ƒ €®ëÐ4-|/E4éuÏóày|߇çyP%ql‚Æà!;ì›Í&J¥|ßÇçÐÿé¹$I¨×빎É0 Ã0§Mh°Þ¼y°±±Ñ³Óúú:Ö××q||<ÒÁ2wxxˆ•••0Š;êv†™úÉ7À2Î,>s'ß¾/ƒP@’’¯¹îà÷ȲxÄñ< Ëx‹ŸŒÊ4š¦Á4MȲ Û¶Ñl6!I*• $I‚,Ë0MÍf€ˆÒ’jY Ã@©T \ß÷{RUU…;à»yž~ž¦ip†a„µ5hšUUÃ×Î s'ß 3eXg–‰Ð`]YY‡ÿ'ŽÃˆk^:¶¶¶)FN†a$¢·–eåÞÎ0óB–|Óë,ãÌ¢3—òíûùŒÏQ VUÍ6X³Œã¬ã§$)ŒT꺵º®‡¦ªªðOޝª*Ǫªe9ÜXÕò½Ç¢(p]’$% VhµZð<ŽãÀ4Mø¾f³™i„/s)ß 3EXg–Ð`¥(êÖÖ®^½îÐétðÐCauuµ¯72N§ÓÁáá!öööz¶]»v «««xä‘Gp||ŒË—/cggÛÛÛ¹¶3‹OÕªÐût½WOœwÉ7À2Î,6s-ߪ*£’‘V;]º‹,Ë™5Ÿ®ëf}RÌÐ ‚ 48%IÝ”e9‘L)Åú€ó´mŠ¢„ §ïûa*pÜp¦s5M¶m£^¯þ{-s-ß 3Xg–•DÓ¥ÝÝ]¬¬¬àòåË888ÀÞÞî¿ÿ~t:Ü^–ƒƒìïï÷¼Þétppp€+W®ÝÍÍÍ0-jØvf9ð}@Ó„¡Z.Gµµì <@;ˆ l¨T†Nè½.#yô“o€eœY|X¾óCi¶q£5˜¦’ñmé”e9¬}­cLŸWàís²,‡ššÍfx¾tžY÷tiHôxÑaùf–ÖÁ™eå¶ø“••ìîîâðð0¬W]YY©ÑÒææ&677qppè,L5²ñc­¯¯£ÓéäÚÎ ‡ª ˜¦(åÒ4a@šfTòEå`µZ2sÎ÷ÅsE@1\·7hR.‹ýÛmñÜq„*Ëâ3TU|¶çEïuÝÞR´ ·¾XðWu7¾ù›oŒü;ô“o€eœY|X¾ó#IšÍ&*•Jh#ËÂø¤hf¼ŒJ’ÄóV+2Fk5-Tê÷~:?ÒÅ.]º4TÁ^Ãû£( TUÍL©•e9³FUQ”ÂD:·¢ÏcTÖ××qÏ=÷àùÏþÔŽÉë73/Ðú½Hò½Èë7sº\¼xq¬õ;Ñ%x{{;;;}=-“xMEmWWW‡nÆwÜ—½ìeì¹ÛIŠPº®ˆˆzžˆœŽ£ËY ¥ªQ:q«««¸çž{FÓ4ŒYËøwÞÉòÍäbcc/xÁ ¦zL^ÃGCÏѸ‰³7Í5œ×of^ õ{šNG^¿™ya\hÔŒ¦E$)»#/3Yò °Œ3ËËw>\×ÍìÒÁÒÏ4]dX¾™e‡upfÙH¬;;;ØÛÛÃææf8<øøø×®]Ãáá!®^½:ñ®¬¬ ¼†mg’œÌO¤ðº.¨EÂ2Î,3,ßÃñ}?Œ°Ú¶ ÇqÂN¼u¶m š4M ËoèýŠ¢ FóĘSå›YfX¾™E%4X;ööö`YVO ~UU±µµ…+W®pöQ­ŠUYŽ"ª4ûô,Ô AÓ4Fßý|ßç(ÌBB†K¿‘)€è= IËxA˜¦™x®ë:‚ €ïûp]¶m£ÙlÂó<”Ëe¨ª ß÷ašf8kµ\.C–eA˲Ðh4`J¥Rhà2 Ã0ÌY%4XoÞ¼ ™óâ666°¾¾Ž›7o²Á:hžDõ©ÄŒFèN˲ ëúD)s¦iÂq†*…ñz± ÂÈFÐu†aýÕ™3@õ¤£Y}‚6Û–eÁ9IŸ h\–SƶmX–hµZá5ÞûÞ÷ýSL÷ä‘…zòðØd´˜ŽIÁKûä½éçiô“cç=e× ×ºø¼SÛ¶CÃ÷]Çq ª*dY÷##–a†aÎ2=5¬Th~­ßlV¦t½7Š:ï)ÀA R©ÇA«ÕJl÷<®ë†ésY ¿ïû¨T*PU5TÐUUE¹\†¦i$ žç¡R©@Ó44 H’„r¹ EQ ª*‚ @­V×ù—O4ª‰aâAFÐ(úOçt]7”o0 £§)O{ÂÈ-—Ë0 µZ-TþdY†¦i°,+<í#Ë2$IB½^GµZ ÓòžÿüçãÛ¾íÛŠþY˜9aØØ.ß÷FºlÛF©T‚®ë¨Õj¨Õj¡qJ2iYEA»ÝF«Õ‚mÛ‰tR’MI’BG Q¯×áº.ÞüæA’ŽpÇïÃ{ßû÷a-xž~žçypžçá[¾å[ŠþY§ ¬Y´ÁÏ U<¥ÏóôcĤI’B£4‚PÎh]"Yaz9)ïe†a˜äV˲póæMÜÿýPŠ¢àþûïÇáá!vww‹>×3ëŠTàÓÆqœ0*”Õc¥ú à8ªÕj¨ÌSD©V«…Š|©T‚ªªh6›aúEW«Õjh 8Žƒf³ -ÃZ¯Õj ƒ6¹¢æ%t?üÃ?|ú?$3—T«U”Ëå°N2$ËårŒ;Žƒµµ5xžÊ/€Ðè4M¥R Š¢$d—3A T*amm –e…Ž–8A jÕ›Í&^ò’mXÖoâ}ï{5þõ¿~-¦)¶3 Ã0g‹„Áº¿¿k×®acc#L~øá‡qpp€«W¯bss³èók¨{¯a V2=Oìk"•/Õ{(q,Y/ªJQ›ìóŒšÃô3-Ë UŠ~’BO5rŠ¢„Ê<s¨V«‰×fÚT«U¨ªšé¡Ñ ®ëfFæIF$ä›Òx-Ë‚,Ëa„4þ~Ê 0 £G¾G<%ŠA¤d+J2"*IB¹§µ`¡4Þff€,Ëa„À™Hû•eqO#Ù/—£ë!}»ñ}qÍ´ÛÙÇ"§î‰¯ÍfdÌÖj_…ÕÕOýu†a˜S ¬a=>>ÆÎή\¹’¨WÝÝÝÅöö6®]»Æ‚‡@¥KÊ=ˆ›w½.nÆŠÒ;ŽÆóÄ ZÓÄ~£ŽW¤šÑx§Ê8ÔüˆÆÁımkkk‚­V«§Ãe»ÝF³ÙÄÑÑšÍfÒnÚí6«ÌÌ TÜôüK jÌY,—ˉ†J´]UÕžÆFB'L­Vƒ®ë™©¾ic•®_M‹œK®+ž«i$I(ðõúüwøfÆG–åžTßeöÅ=+~ï“$!Ûµšoº6aÖAµ*öuÄ«ðÃ?üî¾ûÓEu†aæ#¬‡‡‡8>>ÎóqåÊìïïóÖP T³ ¬­eïb¿¸—™RâºLµÝäG%92M³gvcµZ…¢(ac"j$C ’¨ùѰzQ†)’ïF£6ä¢uÇq`YV"ª*Ër"%“ê©ó8TÈè¤((½&Iâ:Wq=;N”%®2̲C'Õ\g‘¾({¨VË_çš•eôüçÿ î¸ã‹Eÿ Ã0̈t:·ãþ{¤÷œÏ»ã­[·Šþ~saD†(¡iȨ“Þ×¶Å ~c•"Nõz=œéÆNÊ>5@¢º=Ïó IZ­êõ:«L!ض=ptL\¾é¤ êTNŽwçm·Û¹ŒU:… ×¢® µÙº]àè(RÂUU¼Î0ó†çeßs¨$e¨ko¥õU > £Bý…ëQ™ù#+ó,ŽïûïUÔù}Pçy†9K¤&TÞÿþà3ŸyÁHÇ #¬4‡õÚµkØÞÞÆÊÊ €(U]„™$A näªݼ³RœúÕêP£ ßéN²œm¬Ú¶ŽuÉÂqœ° a,ËJ̰#uŠÉríQ¡€sã"&AÀó¼°”‚ ¦t¤Æk¨ãN×uÛÆ?Q†¢iI4¾Ü{ž¸^ãxm[\Ãdžš(Q_îÖË,¾ï‡ÝßÓP9”eYÐ4 ­a'ÝIQ¸® ßoãüƒ¯C»eøAJ5ê®ë&æÈ×ëõp §+éoY5í¾ïÃu]|ô£+øƒ?xUÑ?s† zGGÓÕ†Ù6£pÛááahœÒV×uqxxØÜÜ„ªªl¬ö¡ßhÓŒº‚V«b¿~út¼e–QkÛ64Mƒ$I°m;áÑ#e¾_*¯apg~Õ V|ÛŽ¢ªª*”ÚrY(Æ’$iYî5`}_t½Ó>ó™W„Ûi,_­V ѬQ}’$ lº–ž5 ˆkúé§-ú§cΪeÎL3Ê꺽÷Ï®^ýj¼éM7F:Öm{{{èt:ØØØ€ªªX___úކӤßÈš·HºÌ …þ˜MOÃ4òú•J¥Ä‚H)¿ýþ^‰m>éä1 ÊjÆMï 8lÓïŸOàœ˜Ü¨jÒÈ“$a´Æ³²Rÿ,+Z÷ö>‡ÿôŸþ ï{ßCDäéßü›÷à‡~H†ªFé“ú€°­¢(ðýÈ1dÑy5Q$ ®ÇjUì³i‰t‡™$›™UUá84M £­i#¶Z­Âq´ûÍo™jú5È):Œ ˆJSâÇc˜yÇó<”Ëåp.v<ŠŸ/IRxzžUUû:B Jã¥qeý³äòéÌçÎõF°l[\sñk×ó€‹?TôOË5}œQÅHd°¦'£@¥é×4MØ7†!dßó€{îùÜÈÇ¿RM]×Åþþ>(âJ,“mV¨.똅,gµ”¦B‹p¼Û)-¼Í¼în€`ZÞq÷ä˜ã <ãÒÂt V Â7§ø™¾ô[ÒNœxlò&“¬?úè£øš¯ÙÂÑÑ ñU_|þó—ñ»¿ûÿÃÇ>¼ñÇqBg A×”çE™ Ž“=&žA‘ÕAM²¼ñÁÒçh’b—¥ÃÆe‚nô4Ã3 Z:©©PúyJO~¶®Ó®ëB×õ„ÁJ¯éº¦¶O‹ ˆºíNò»Ò5I]ÙXefÍWe¢l×nÜø üò/_E£Ñ€ëº(•J0 #éç8Nb&|³Ù ³ÔFi.éy“ûiIHG°jµè¾HŸáyÀßøäô|fa ‰³€º´Ó%Ïz›¤OXµ*îIq•ÊÆ'’}]žÆÑ¬Q kÜCäº.°··ÇÆk4ž&Oɼk"5_J~NУ°“¡ª(JX·:.Dds‚zr¼q‘h†«sòÿI "¾&„ñjLv8f0ynâžçÁ0¾ ßýÝÄ×ý_ÀuµÐXt]7oþ|B¾äGîÀááï`}ýLSÁþè{ó“Ì®0·^ -yî!I½©’ IVNóÚZ&[Rò8²ÒUó,‘i/ö(^mJ ¦ZµtÄ&®˜—J¥0;êÇÒ{OH¾6IT5þ»R÷ß¼cff(âiFØœÌ0Æ»QÿÜÏý þôO¿ˆ'žh…i·º®Ã¶í02šŽ¸˜­gUº”…¢D4æl‡'5çÌ굤ª£¸yƒÌò¥KÕjbMž¶<Ð|xÛŽîs” ªªQ3ÊaØvv¹—,'Ï™î¿yt´ad޵QUW¯^Å#<‚ÍÍMâòåËa]ëY Zíïi0Mñ‡š¦nhYVO™išÐu=±àjšÏóP­V¡ëúh#h(º:ó&¡žÄP "«uLn¬ÂX„¡jÇΑ™:A‡äô«¿zùÈGð“?ùö÷¡ëÉÚë4š¦á'ò_áŸÿó·ãw~ç+Ÿ£iÉ@"uÕ^b;­ «ÅïpšÖ?üÈÌMÓP­V3»ñõ»^¯£Z­ß"*œQ‡^ š<  qO›§V~^͉Yâ鹺®£^¯Ã¶í±ýÈüÞóžWbcã&®/Y–Q«Õ ë:TUÍl²4 J‹_¢dPÈröȬc¤/qr¬Æ•|=_¾³jþ˜å¦TÊ6)ò>M¨ßH\Žãs¿±œqÈèM¿Fcþ²ÌºãÉa£¬‰ ¸ví\×Å¥K—ðÈ#œ©±6†‘m°’‡mL§`4³Ë÷}T*•DgI×u3½4cu,Ïä´¼ç2¦Ÿv;-ý„"­•)Ÿ’'ºjš&jµ~ã7~¿ñ?EiàÎ;¶m‡)”YõCT[ô ¿ðïzèY´\_8d¹÷‡È3Ÿ„™T¿:,rJã.¨ Œëº8wî\ø(—Ëáý…ê~hnj¹y©©ÖhÚòi9~*•ÊÄ3(+• vÂ,¤ßÄÓsi¤^\ï!ȸãúâÆœHûýìg/à§~êyøÀþÎÔÏ•®«¸ÒN—5•¢ òz÷£6qc–>C’¢mébÎ$ iƒµR‰zጠÙ+ih§ÏN¬Ã|…ªÚ›…äy½†ªi&í(ÓŒF ŽÅO<ѽï¾ûº÷Þ{o—h6›Ý{ï½·{ß}÷…ÛÞþö·wç™ëׯwzè¡©SQºÝv;ùš,w»­ÖtŽßjµº²,wëõz·ÛívkµZWÓ´n·ÛíªªÚm6›™ï;::êñ…NþÕ§ú3u»Z·Ûmù>ú-ÛÝnWžàZ'Ç‹cœ<2˜…¼Ìš·¼å-EŸBH­&ýh6›]UUÃçGGâÚ9::ê*ŠÒU%ǧ0“0Oò’‡E¼&§E»-®§ô²Þj‰ëF×»]ÃïØ³¦•º!Öëõ®,Ë]]ÿFsttÔ•$ià1M^íz•z½Þm·{ZóFß÷)Šê4´­VëêºÞ}á ÿ¯îúúÏweYîjš–ЋTµWG…´xEÇìw\M®ÊtÃèvã?Eúš§Ï]4yY´ëq^h6…­qb„ÆÔ¨‘QUqü8t‰Ë¡<†îM÷,B×£Ï:1cz®•Z­Û•$ñÚ8òrÞ0 ¬¯¯ã‘G Xª]}ä‘GðÎw¾ÛÛÛØÙÙßÌ_@*•Þ,;Ûîßùt¼ÏˆÒc„Sò¾÷«î7Ol(äÄôbÿQýªQƒ:ÎùÐo)C¤e NŽÇÀô"ÊL*¤ïGº6‰êGi Í4Ï, ¶=Z.Œã—d©4ý¼ fn¨T¢Úì4ŠEUO«[ä(P‡Vó$oß÷ý°«½›'w²Ô¨ÊuÝéÓÌ|à8LÓ å N¥R8'›’‰ì?Ññ·^¯ãMoº@G»ÝF£ÑHèE“F €äûã©¿ý¢@éèk:EãÜhÄíCŸ“®cM«r\¿:¿Ìb)’¤Þþ ÔøŸêAÇ…ÆjÆ!›†®’×8ô™A ÞŸý•¤dô4Þ\S’Äóôè@Ú>® u¾ÓéàêÕ«aºïññ1±¹¹Î^ÝÜÜÄññqOÚð2B€âYžžÒ`šffJd|àôÔ¡ûŤ͒€¤ai`¼Gé”âzμxè­Í•ÀëŒð<`mí³™Ê$)ªƒ.#Õ^ç.LÖ>϶“]¨PªÕjÔ…£Õ}…w<ø®wýË1C QL­Vÿ¦º^œ±ê8ÎÀZRÏó ë:‚ @¥RAµZE­V ¯ñô{+•|uÔ¼ŠR­™ù%˜¦‰oýÖ§ÐnUÂQQ­V‡Ž%"£µT*…Í“ˆNçv¼úÕw$ K2'5XëõäÒJ† |…Ô«!n Rê. RÓ]ÈÉèUÕèܨC* ^w4CÍϘùdPÇùqQ”ìæEt/˜DÆu=Y“šU«šUZB¥(Ô 6¾AÔü/nPÇýQi§NüõIfxŸßØØ S [ÙŒo?+Pkÿøâ4­æ.¾ïÃqœÌTªë˜‰BOJaàM‚ŽÙÌ:¥Ù¬ã¼¯ßùXƒ™©áû@£!Ȥ™¤óãTHw§™ljzÀ1"cµÙŒYîßµŠf«6£íú¾¸«:þŸ×¾vz¿)31Ô™‘°,ñ§ž§FGqÇAµZX‹êû>TUE½^‡¢(¡‘ ˆzݸñâyÞIMâðëˆF·éºÎëœC]¿þëïÄk^ó`eµm¾ïçv¾ëºŽF£‘˜3ˆ%->‚ƒ^£šÐqë=Ó†(‘6`ÓÙDqÀ0zp2z©Ž™^ÊûÍâ> óɰ&““7†iÄ ¿n: ª‰ñî½ñóék(ž ëIƒ5nàÆ¿l5MÜß²n“d¨ž?>>N¼@sXÏ¢‘‡þ¨”¹8ްog¦¸RwÔ±ÒzÇ%®»«˜Ü`•‘ŒhzFñ>ùè5"- øìgÅë{ïí|²"¬„dú_~a&ަEÁâQ”aÑÕSÁ²¦ã]2Mq¬f3r‰ç NËŠºÄU¢_¾e?(–f.4x振áóFµÝW¨‘Ìi«AÀuÝðaÛ6LÓìñô<¦i¢Ñh ìâêy^è\5 #al¨ªšx¯mÛá¬ÚAø¾–½È²Œ ¸cðœbY$I‚®ëPàŽ;V¡ª*LÓ„mÛ#—~¤ï”®(ËÉå“®#ê?Ô$&žºo¾N‘­¬¹Äq#5[Èjš¤ªÉýèÖ’Þ/ý=™ùšóOBº ªqÃ4aÍÓOѶsç’ÛŽÒté¸éhªaˆíi9¤È,ÌB QOéØû¦-ËçÃq5ÇÇÇp]‰(øâÅ‹ÓýôtÏô¼¤GÁ²F¯+ð}o»ñ6¸VòƒlÛg†*"QÂä5¬Vê9]yƒPiýƒå_Ø‘àùàʧF3¬û]Ô¾Üóo'üÂLœZM(«µZ – C¿ÌSÃuÅc9”š&r5éâ§ayyÎö£>ïY+w¿þñŽ3¾Áªªì¢ŸSZ­H $³À²¬0ºIN&UUáû~1ïèJûô#n°¦QU5aœº®‹z½>Ô`u]7Q*£ilÛF°m{èX fú¸®ÛÓÍ×÷}ضz½Φ÷<„3VÇqÊg¥×’x‘¢O©ŠÑ¹ ¯ó+—{ƒñ(m–Hï‘Õ •дh{µš=„|•Ü xq˜Öß+m|’lÄÓÓ)2 D2:ìÜt½·¶šê±éúH¬AO¥‰_ ñs#§NµÚ+ãõúôåûüÆÆ¶¶¶°³³ƒ­­-‡Æ°¦ibcc«««Óýô‚ð¼¤W-k{üǯÕF׫Õ*]Açp‘‚–eõ¤¼œ ’õ¡’üÂçÇ?^ÜKD¹mz Ù~Ð}æ5HRäÊÔüÄ>õ‡ÂÈÎÝö 5KS«‰«ò?1^ºñ"k~\@ŒRö<Ï £ ¤‚늕“ÂV¾?~/Ð{— wä04MœíßOiËÒˆç –]^²êÔˆÓü{žF@顪jON'1òŸµ îgÊMŠêXÇIÌÅLgeÄ›õxž—XCt]‡mÛáø7Y–Q.—qëÖ­ÓûÏ043[–åD H¼^Ù÷Ų'"CZ­ÖPÙèýœÈßHPÓ1 ºµÇÓÞ÷d‘ž­?E‰\7y­Òõ™'».~츮¨(ÙQ5UÞhDæt ub’Ôà,Õÿè¨÷µtæ Éï‹vi#³Vò”Õ@ ˆTôµäS‘èIÿÏjÂ9“+ݸš'9ñL?ü0¨‹p!FÖŒñèWš÷ £ÿèaZ¤«â5_þš0E³' i8£@ÔBÚ[*ðÅ :?ˈŒMÊ_ #OöÖï~øèïˆZCMë½’ïÿ{À3?4 ¢¶ƒŽiÛ€|âBí÷ǪՀŸ}«0¨¹©A_(d–üÒ/}"¡ÐZ–U\íªï CÕ²z»hX9=(ƒ, bÚùZYÝX“YÉ‚<?þ^àÿýõøêotpcó+‹ú Ì-´jšc]×3Ý›7ªúr¹Œ &ënM«í(j2d½+oÞžðdY1j‡î€$»Ô–Yhâ"5J ©R©@–å°ldÔ(U?ú9IeYîijDéœ9¤z¿£74åSUÕ0™Ž©i,Ë ÇÖ@«Õ ×~†u]×qûí·ããÿøT~&r6ÞR«Õ¿S–.3Ir5*Š‹šmGêE|9‹Õ¸RJr?cRɈL7RÊ2NóúéØT¿ol£(Ó…ÈÉ$?f†ãrHA3’qD D<Í\U“ו0Öjɤ­ø52 §)]Si5ë4Õ•ó€¨QÝÙÙÁÎÎNbtÍêêêÒ«AûEYÓ5YG8]KcÛvØ-Màü+Ï£Z®¢\.‡ʉ©bô®·&¢úÒz=r ®p JVÿº×÷½L¸-Ó¹Ò:wú qxå?þù?lœÐÕG?™ƒ¨Ï|¹,ÞÛlZðrÜj5à{_¼éÿÆþ)ÜþùÛ'ÿ[,!Â'Ò׳:„F€/|á‰P±$åz¬, ÓLXŒÚÓ_’„UÐ/g˜Kt\ËbZä­‹eæ† H6Çȯju¸-‹xJ}¥RØð(/®ëö5XÓÖ,ƒ1+ Kç:Ì VU¶m§fgFÇ£¬ êŽoYVî’‚{î¹wÝu×Ä¿ÓjIH’„z½ÞSŸJµšy¢ý c3nÄo´”º® £· è–Ö8É2?vúÜâµëÌb’®)Çh×Lg5W¢cÛvo6í¡÷ÉûOÜq’¾m{²èpœ$38‘ð<Õ®îííaoo/¬g]V'éÕè'xà J‡J{§{Ò" à­o}+ Ãè;8{$\ˆFD£.®zgœÊ2Pþl¾cA¤ØÕ½ÀW|Eï>¶-~àú7@’åX¯÷!Ÿ™®ñsüÄsÅKƲ$‰×óøèv½m<ýÀ§p÷‡ïùç_v¨±€ëº}GJ¤SöáyY¾«ÕäÔêx;»¼ »ƒzÂk¬öËLÈê<0 Öd Ç™9qÅ7íc!eaô‰D~èü1 F£§ÑMzÿQŽÛêÄ ô6<Šï“Õœ)q©ªjÏÚ@déÿô­VkèÌNætè7+^–¤œÇú¼Ê|Z¬©¢'¸MÏv´¼RJrÚHIXt ßïMìšV3Mã™e «R‡üñyÓ‚Óª9I¬´}ؽ#Ý)ÞÌŽ“>ƤÖ%)…Õ¬8¿··‡ÍÍMxžÏó°¹¹‰½½=¤ÇÝ, ñÙCýRGò4 ô<õz="O²,ËÂ@´!ÖuÓ«í3!ºè¶sîïû‘”¥ VEîmˆ4ÞöMíMgª Æ'”ÒG¸.ð3?ó•“§*RóŽx~É$ù6ýPÕìcNY5ÍÈmD­öâšQ^¸˜iaˆO(¢%(+p1z#–Š¢$ÒíÓT«Õ‡’çy(•J=ÇdXÆ#žýêRÓ3Ué¸yh6›=Ÿ¯(JfÍ;¥C3Å2hV|Üéí)Þåãíh¬Kœ¬?{üã)²5ìøñhgš~‘Ôi,Ãýº 3‹G<ñ+Mƒ5«¬ñm$%´mØØoT ÉqzŒ0^ÆOšv^»cFœ€+W®„/loo@8êfÙÈR0ÒÂ7lᢛ:Ý\ÓéM„±F?IV—늻ƒiІA½ÎÍÁT*Bú³ŒGRæäGC?œŽl‘Ü—¤\½åÀWÿÒd¹6éÕ>wòL9&U¢Fu×Ys?õ©ÃÉ:SWé¬z×A³ˆQ¢˜YwÇ™, ˜Üó–%†ŸU*ÑÀ>f)¡f/Y%÷造aŒ×7++íV×õ0­6 ÕÆq'ìÚ?î Fñ¦Jý Öt§à< —¡i Ã(v^3Ó—xªvš¬æëñÝòdd¥ÒS ê—n`DQÔAô: Cœë¨•'y÷ºgæ´ó!ËW?h>p|¿xÃ"2LÓÇÉsl ñÍ2p§PI2—œ¨S]YâaóYô6v§DÒŒ¸DtH¦©V0ÔC›$Ò…ˆ&e îžkšâËèzƒ•¤Þr¬82ú§àjšˆž•JÀ~øÚ¿Ÿ‘›€ü5¸ýŒŠ*¢n¿ãþ¾Lêcµ¶öÙPŽ©£')À¿ôKŸÀ—}ÙñøQ*„ègÜ Já¢Ñ5yç0fEm]WXã*Ü’$®©FC¤˜7›‘[“YJÒ5oqâ5­“A¦Gs-“çãe:“(*¼öëL(ŠFKûí›6X‡s’$-Õäe‚æôöKͦ”Úøóøí ÏŸµÑH.ËñåœnŽÓëëÖõ|ǧ´â¬Z¾¬N§ C\Æå3ÅÖŸ‘ ij²š ¥åRÚó IÙ÷%Ç)>uwVœ/úN“~EÇñÅ–”öAÄ Vêt˜9ÒƒIÃàôØ~Pë/²ÔDÒPÔÐ?2J)Š´ºZ %ˆ¨i\È)í1ó‡p,jgÖhþ*ðÛM»¦‘õÙ<9{JÇcB‡Î½÷6Š39eLÓÄ{ßû^\½ú]ãHµ¹¹³TÇŸ³:ŠÁÜ“Z^g…‰~CムÀ'>ñl˜á>‰²Ð¯ÖT̹L.r5¥kS|¶“9[u˜aI)Áy¢¦ÃR‡™ÅÇ4Í%L陋é1€yÑ´È µ¬Hï’$agÍvêÚ‡}‹Ì HUˆ« £úÖHîâÇŠ/ÃÔ?'kiÎ[Âï8BJ_#šVÌÀƒÓàL¬Ô).MüÛ/ 'í]Ö4-]MSC¾¦@ÉR>heÕÍVMQÓMjuˆ4[Q«ßU:È`¥$úøo‘ލÆgÂŽ‹„Èhå’§©@i,ŽããÒ¥7†¯ëºÓ4¾ökÿ.]úêñ>€Ú7Z‘ûˆeœ4Þz5f"ú)¹•J=ö¢=nýªxÐ×LwꥺÔx”•©ñ9§ƒ:Ç¡´àAûÖj5T*˜¦™û¸Ìbašf(Cý %š Ì´¾4¬ÎÔqÄRžn>“§AY yX[›üÌÙC–{U”´ Q?ƒ~T*ÑûÈxÍ3Is:Kiè·ÀÖÖVφ<üðÉ×vww‹>߉ȓNJ{?úuH †¥(zÞ7Žm'%Ñ’a †R'Eƒ2¡ˆO6†¸ÿ Šš‘Aëy^XcH5«ñY§ÔÕwX‡àøñǘ¦«ª*Z­,Ëâë’ž¹ÚZM,ËŽ#û´rO˶mgwÍ%#RÓ¢B:ƒFsLÒ‹ª¡fâv)2J#›ˆxc/Ê YŽ;Iè¾µTV*“51R”ùî×H÷@d ¥ïNŸùÌgF:æù+W®`}}=ñ¸rå 666z^_tú-~T* ä3X³nÔ=JA¼“.ky¡®£ép°„ÈuCøµ¬@¤Ü…¢q4?úÿ^õ\$ e3Ç£CŠ\bŒÎ´Òx©#131ž<úè{!˽ ES&jâ›w‚:¥üÒ(¥¼…K 3hôsÛ¶Q¯×Cƒu”:VÛ¶{ Ô¼u¦@2}XÓ4T*•Äè2póŽž‘e9—Jµ§Ýnw¦¿9sºAÐ3s5{¿È—8(‹jTK¥Þk§VÞ˜iØ´²<Ôë]eF‡ Qr¶ôkŽDñ$YNÖZdz(-¸š¡ÿkÚäCæ5ÉÅó<”Ëå°\²Z­¢\.‡÷0˲ðàƒâóŸÿüHǽºŸú¬ñ>/Ô@ ¿që¢ÙÌ®ŒïBÇ /²èûÑŒQ‚ôuGJ¦ Ë]ƒmºœÝÆÒ…0ûy-K¼‡Þ;¨‰QpòçB©C¬äËÜŽ|âÅK^Rʬý€vÃlo¶®k’_ËÊvá3Ì)’eˆú¾6IR’äÁqhÚ`‡§ïû¨V«‚¾ï‡MÏóFBUUEõDëI–º®cmm-¥qTƒšçÄQåä{X_AWšÍLÞã>ÖÍ‹}/þÛ¿-î|—˲2g®¦qñgªÕ"õÄ4{ý‰ä›¬ÕDjn¿¶¶¬(ÉÆN sZT«"òIëø°žé*¦tƒ& {ðÁ¢ûàÉ!JÎS]×ÃŒŸJ¥‚F£‘XOÇA¹\§«ìíí<æLÕ°ö#>©_c&‰ðv_\7Ûm¢BDówßdmKK ¢aR€l—˰‘5ÍfÒÐTúJóeÇ¥~r¾sê:Ëxð?þÇ{ñÏÿù+û7á%{²Ú<Ž‚a°±ÊNVja¼ÉE3Ó¥ûiÈë¬ë:F¢&5‚¡5¡²,#‚ž15²,£V«%”ªcÍÛÍWQ”¡Ñµ±ðÇž³†-ñ†‘œ;¸Rtj^#EÌr“î-J¾2¶{g¥fA©¿@oÝt­¶Ηx oü5š‚B%¦ibmm-tˆÒ}§T*¡Z­f«€Èj·Û¨Õjh4xþóŸ?ò9Þrpp€7n„Ï/]º„Â~ÀÃÃC¬¬¬$ÆîŒË°â{YŽÆôÓ‘i6å@,ëd“¥Á¢îÓBÿ(ç°^ë%-ˆ»u4 ží’?Ëk£cpd·ßçVÑÛ0j©¼g¨H|Ó”ïiðWõW¸ãŽC<ïyÏËÜîy€÷¶¿…~)gÆ4c¥ffÆ¼Éø¸$zÈÜØ)ÕVUUX–5´Çœ¡{H¼ïëºC£›ƒÒ|³ºº*Š2¼·Bjÿ©ï§?¶ãDŠñï‘Ö UU<‚@ÜW-+–ø¸iâ‹1}å´YÙî— Q#1Ò‰âêÕö [âãúT:@Î NÝO–EÆû‘NdLÛ äWËc°RS×´*?Ïý-Ë‚mÛ §&EL© `Tæ‡ãÔZ­VÏýŠÆ¯†1´¼e\nÄÍò¡‡B§ÓIlÜÛÛÃêê*,Ëšj ëÎÎööö¯mll„M: ÃÃŤL°ò¹xX¿ßoí8ô’Øt”VAcºƒ<Ü$$$”ßlŠ× £VGoôr\ï¥Ñì)~Z>Fku)B¾§Á'>ñ,¶·µp¾Wׂ§¿<ŸvašÑˆ#féXT‡tÊc:%7]_Úß÷ÏtÝè°y|üŒ‘£5dÞó™ Èž…\«õÎ;Éê§ï¶“‡¼ÍÚ¦ÄY’mê&UçLÉbé±´¤+JTM4 •ôx`Á»œú¾øf‘0CÎ’Œ"«3uÃKÝ0£SÓ¢ûÄ(KÛ¬!çjºÜ#‚pòC–ñ9.yú%LÒºû¶ƒƒ† <øàƒ‰t]ûûû¸|ù2vww§m½yó&677Ÿµ²²þÿÚµkX]]Å#<‚ããc\¾|;;;˜e½-)éýîïtãš^¥i«œµ~)iÁi¶¬ÁnÊô9©ªøŒx¯ 5Ñ›Òkc¼12zÆq\ŒÞ%øŒ1oòmYù”‚££.4Mƒ,g¯'ºàðQÀ½}pW j!É]}—–y“ñYBã°‰¬æDýtÃÎ2t©‰ŸçyCkME ›5åQ0t]ŸÁJ3IÒ‹JÚ€'ÍmÎ’l›¦Ù7\’ÄŸ8ž2Y.GM©!MVÈ4¶õÑ[*¦ëF¦õÅòü r–d|dƒË²øÉÓÑÔQ¢£ŠU5̦i†Y¡–e%ÊCÈy:“2A¸îp{gç¯]»UU±»»Ûs³¿~íÚµ©ó­[·°¾¾ŽðAÜN§ƒƒƒ\¹r€¸ˆ677ó5:€mgwzŒ¾«ø·Ÿ+˜àyÙQȬÔ\Û>h±KG5k5a ôx®‘]:AaøùkQã:8Â:„"ä{ž—]ô'<ç9O… ZÖ¢+I€Ôù`o[¼øÑ4ë~]6˜¥`Þd|Vô«ÔHŒd|ö#«F5ÍSïFÖ(\P—zÓì½Î©KN–lI®÷³"ÛŽã„Ͷ² Œl JÎjŽ”§;v˜xæÍwŠäȸ®ÐÅF1Vm[Xþ.dGH)lµZ¨Õjh6›h·Ûh6›áÿkEXÖy£'}8ßétðàƒÜéÊ•+èt:#wtêÇÁÁ‘–°³³>„ç@"y}}½']y-”ä0žØ`€¯ûàgžÉøˆæKÉ÷´@˜ÜHM|DW_6VsQ”|÷#ÞT¬Žãà[¿õæÀ}L‘Ö’> u/ "pn–´ÔÌ›ŒÏŠ¬ì¥¬Ž¾ªª&š(õ§7*K‘䎄ÆkЦ Z[ÿÒOyÛίÁ-(gG¶½!â_Í‘u-ä]êey~"OSeÔôFϋʿêõ¨+vœZ p]Ü;ÉÎ!,ƒŒûþpG|œôòLéî$ß@vÓ(Þt“²Óý=üp|Œa¨ÕjÓIõ%oÕä'˜¯ xçWWW‡T“àO~Ò'Pþüññ1¶¶¶°¿¿/ŠAŸÿÌ3ÏÀó<ìììdn×õá¿S¿µ'w:0ýQ/~ð?þ2{QŠ/]%ÃŽëbô:T ‘Ñ:Â|À³ÀÁÁ}ôQ|ä#™ÙgL[¾àÓŸþtÏÍež'Z”ª2×uqíÚW†Ï©¯WÇA´àdÝd›Íù+â8£ìììà©§žšégœö^ýî iã“¢Ÿýp]7óþAïËk„꺞kLÍÈT«â‹R‡^ºŽÓçÕjÍE$u>ú(ž~úé™ÖïIæqg ÁJ³#)Šš9ü@Í\tÝ9i®DYy÷­V³÷wœÑ•oE†*å êº0ZS]°ÿË÷|¾çþ`¦F⢯ߔ]šÒ…âø¾øóÑr“ûÙUõtdÜ÷}X–…r¹Œr¹ŒR©„r¹ EQÐn·óÕ’æ¥\ÎÿC»®Ø?ËyKc é࣮߷ݺukV¿i&NW®\Á<æÌ¯®®bgg›››/ˆ[·n%òìãÜqÇxéK_ŠK—.}ný¢Õ¹£«ÔàkîúÙB4Õ8éïž7‡|ƒU‚˜Këß<Ü$戋/âž{îÁÇ?þñ©{Vò wÞy'.]º„‹/æ:ÛŽ†_=ðÑ>IŠ%ÌlÉŽ$PO®ƒ¢ÜˆL..]º„ëׯÏäØó¼†Oßïõ¿ô‹¤RÄ4KYH7\"¨.5¯Á:UE„p]¡­-P÷›õõuܺukê ý<­ß“Bó~eY†¢(‰F]ä$¡Œç%ƒñÔHê‘eš“¥óÆSŒ Å4…¬ç‘wº‰–Ëâäãh§‘߬ëQÔ5æúÚ¿ÿ÷ñ£ý(Þ6Æèa,Ëúíûù ̬¿çE"@ciFqÀd1ËIJ à8l[Ì•¤Ô™dÜÄ$R ó”yU«Ùöhˉ½sñâE|ÃÝwããŸýìH§sþøøxè¢OÁA‹q^VWW±½½8]$»ŠßqÇxÙË^Ö·1T?£?N<—=ŽmÛù½Ú² |ýw¯xEöv  ¬Vó÷s¯¡7•x„‘[p>ý<²ººŠ{î¹wÍ`†ß¬ä ÏÆÆFîó†yüetض¿ówþìØ|Ýôšv‹¤UŸæ@1sÉÆÆ^ð‚ÌäØE­áEaíWóG]³ãe¾j_§Õ¥q,l{ẜ®¯¯ãž{îk–ß æiýžß÷ÑjµÂqqÙ¤f_qâëVívºcðBâ8BïÊc¬’SÖ0Dæ$Eag:VÜ`µ,ñšeEó†óÜ#ëõž&4´~OCçN³,ë÷°Iq$I<â)ÄqyV!ÿñk` 9¨Õj¥R ¾ï£Ñh„×u¦±jÛBþòBÃf³ °sºûZ¿ãd…˜=¯§Õòêê*6ægpñý¯‘~óëëë0 £¯Wåøø;;;‰¢ìI888SŠò®¬¬„ÞǸÝét¦²È³ kµ^‰išÐ4-ŸBAnIýçžJ#håtêü\p„õ)R¾ÓÄײ~â,Ë›Þô3y}?uýäí¶Á,ó$ãÓÂ÷³“Ò}FÍ5í7F&«áAµ¯SŸ: Æ’µnŸe‘íxš¹¢(Ð4-ŒÌ½õ«4—Ä;í¨!v.Rz'Áuó—¬Èrr¨Õ¢†dô<~c%«ˆ®©R)2dç„e‘ñ lkÅ÷£ŒV²¹Ò IJæ§MµZE¥R ³s¨QÒЈ*ÉZ^ý,"9M£ªQê:u©êG¿U n¤¶}úÍoÆ+ÿøGúMÎ_½zN—/_Æþþ~(¤N'iÓét¦ÖÎzee×®]K4pÚÛÛÃúú:Ö××±ººŠÄåºnØõê4ñ\¿>)–eAÓ4ü›ó¢„2BÝú‰Ì›-^st3ffÏ¼Èø4±¬ìþ'½sú¼]U³/ z$I‰ÔL¦X–E¶Ó2§ë:\× .qƒ•²õ4-Š@e)ï o¬Š/>ÚI_—ñL„´á«ªÂÀ¥7†!žgµž-e‘qгËGÈx¼VèM>:š} ÉuÝ„ãHœOÈ€‚¥R ’$…]~s—‚Pc#]Ï.6 Ñ›€ ×Aûõ«e5Í잀øá›ÍžkééòOà˜RÛúú:vww±³³“9ºfccÛÛÛS‰®"•çÊ•+¸|ù2666ÂŽdñ¡ÄÛÛÛØÚÚÂÁÁޱ²²‚x`¢Ï'D3Êr+£ÔõÑšiAD\w¢¯Îœ"EÉwœ¼MÝ<σëºhõ™—çžû|¼µ-VÌ™`d|Ú¸n4$¾ÑŸZm<%=‚Ä=£_Ã%Â0ŒÈ¸ Î4lÀ²Èv–“DÓ´p”MZÉ'O#@Ó5 ¹¼Ó Œ¾ë8M’ÒÈòhƧ,Ï]Wíe‘qÃÈg`’3ˆjUóVãMÏóP­V¡ª*ÖÖÖ`F¨ƒišß÷C£Õ0ŒñšëI’¸q©ªèø·Ôó¼Ï4ÅM0«DD׳ Vê*ßGœ*Ý7oÞì6›ÍîC=Ôm6›Ý›7ov»Ýn÷ÙgŸí^¿~½;MnÞ¼Ù½~ýzßãÒgæýÜëׯwz衾Ûe´ó«×ë]MÓF{“ªŠ›Ýn÷Ú¯w»F´­ÙìÝÿ¨Ûí*'û¢5Úi0Ã&/“2mùîv»Ý·¼å-¹ök4º]ÃH¾fÝn­–|MQ”nóD.It‰f³ÛÕõèy»Ýíýê£â?qÚíÞ73sA^y—Ó^ÃgEZ„[­Þë‡0 £[K_H©íÍÔZ¯iZ·Õʱˆ7Ý®,‹G½>xߣ#qSÓ´ä}fЗ<:êÿ|™¥¼¹~OUU»íÔZÝn·»Š¢tkµZ_–eño|í?U²ÎË0zï;ƒ8:ï¡ëƒÐ4qqG?HöçÍ ¼~O’én7ÒkêõÑDjRŽŽŽº²,‡÷£££n­VëÖ3Öù£i­Ë†1ü>’…¦ö¾f3ß=(Å8ò‚<;]¿~½{ï½÷ŽþÅO‘a_~T:kÁHZÃo6#­§^ïo1·ºÝ®ÜívOñâaæwqDÞ˜aô®qqÏ›]=&¯YâÙsͨjï*_¯÷×î™B9MyuMŽ"ÂYiòXõ®‘:˜טúqt$4«v[<4M\oYŠ«õºPÀu]¼·Ÿò]«‰ýe9:}Ö³hkøi^ýdNUÕ®¢( J\y×õ¤Mwª´ZÝ.Ð{y®‚®#ÃèuȤ/òø¾ékzEÊðú!ËÉ?g«%žr.Ò~鸓,ÏÎÇžå˜<::ê*Š’iœv»Ýñ‡õz·+IùeÕ0’×V¿÷ÑýeÆzÝ8òr~ö1ÜÅd”Ùx!a»sDMi¨õXº{¡@Ô˜VÝÑׇhœÄ09qÝÞÌ'êÈí“ì9,…8ÌÉj9³ fuÙÃf[¦/å¾P×xJ9l4DZVV:W¹,ö¥¼¶z]¤cù~o=9uÓi6ÅöEªX¿z#fáÔäëõ¯ÿA|ðƒÛ‰µß¶#Q òËB°íÞÚ»xoDiŽý œætC$ ·hQ’¢æHŽ#ê÷J%‘9oíbÏ8饖µa½³²Àeú2îû>Êå2ªÕ*ÖÖÖ`YV˜\.—£ùÙ®›lU Y‹—Wåé"U­Š/×jåoo¬ª"}—ê\û½‡®‹9svf Ö~öb¹ç®¦¡+Äø£û~d¬Ê#×è²ädž0€&´Ö +[ð}?¡´d-àt#pœ“›EÖan¦Á3Ìx¤g ×uQ*•`¦ZùA0°†¢(‰ÆKÔÔ,ãôö;PÕ^A–³AFoñ–$ Ã5ýYš&ö—¤¨ëi­6—Ê35ùúê¯þ|ñ‹ôm·!ËÂ9éž¶“<ćÖëÉÏ:•$!÷¥Re›ŒÞ¼Ð´rú4›‘ˆ™ hÞj\ýˆ—ò!fÊÍ;Õ(/¦i¢\.Ã0 ´Z-´Z-AÓ4¡( Z­VTjš½ãaâV5Nd´V*ÑZNÿæ1Z)jQ©D#hú!ËsÙGá¶¢O`kÌ@üOgà Cž?ü 5–í&'ƒf™›fädŽËx¿Ÿ.pà{%%ˆôÆ9\Ø&¾ŸlÊáº.TUEýDa-•J‰&JAŽnf²,#‚°û# ž'.BIÊÖ¢ò2ix`!;è0yÔä‹dݶŽ _ÛS_Ò)2 $›9N22J:•e‰h+)í@Ô6v’ëC’øú˜3dYøÖÖ¢×âËå ?w­Ö»}š a¶mÃó<´Ûíð5I’P«Õ²vîýp ÓGxK¥þ–µ®'e”ºðæ™Ö@ÕLótš$M™3a¥ÌܼÒ26´Þêúè+¿ „(=8G·W†!Ò©¿q<ô¤C¦gÆê ¤gK V­ãpt•Yh\7é¹O¯ýªªÂ1ܤ(J8¾ ‰Fss #Šx2Ì HgÏÄÑuqˆjL+ôãvÇN`YùZÕñ¼|úð~#hÈ‚©ÕD4аm66—ø¤"¾fm3MõÄqX–• eYy»@[VtYjé13éë(KÆ)û 4niu·Û¶¶¶†ît||\ôyN„ëæ_;©þ(1Ê&šš52D´Õ…Höp‰ 3E,þ¾ï媫Kì’eÕÆh£œfÎHgݺ®›ðŽSŠ/¥õöŒ8ËÈÁ§÷<ý_þ ~|wWª€PBØPefÌ  1ZÓIÄgÒ‚À÷…rîyùGºdİrM‹êU¨n•Y:,KüyÉ÷çyâ5-YÎÖï-KˆÕ¤v™çyaiˆ¢((•J0 #4Vs½¤èjZïrœìk„ÆÌضèY0¬¬pT´ïH®ëÊÊ 666Š>×±‰ û0B»‡hþé¨E“ÎWÖ!ŒU€#¬ÌH šíMžHÏóðÅ/>î;(*ÒÏãÃ[˜9!ïüá8q"KÑWU5¬Iu]·W9©Tz.:EQXþÅK^‚ç]¿.>„£ªÌ)0¨áR<ÓŒ‚4ýR‚'‚ò%i²æE®;¤ ýfN ±Š"lÇa¢_Ü3/9½2N5©ñî¿áX€>© ív;_ªÃL‰ à8dY†ï‹&5q‘M/áýzLDº‰Lžýû‘7Å—•ù3§qÛ¯_Ÿ­I²^MÓD=Æ*€ÞÞÞ1²œ-ËdÈæep>Ò>>>ÆÁÁAÑç5Uòf¥$RÂ<m£Q–‡ %+'Ìœ#ËÀÑÑQv˰qNÛœ3L¼¼‡jR‡Up½ÕEõ¯û#ƒ51҆ºœuÀœ"çÎõúÎ}ßç=J’]×!Ë"Èéô>“ÉFâFñ‘A BfœÎËôÁu“"S«e×]§”¦9~{ rüÔëõl§c¼£5 “–>•îfg‹žëÃ?Œ<˜ã÷X~>®/±_¦MâÃã§’R)ßhflÎDJpÇëºb A€¨éÑÏ<\ùâ`é7ð0½”`†X–…Ï|ìcX à׽蟃Éà¶ííí¢Ïa¦P¿˜,O¼mÛÐã 5¥ÄxcmÒ ô¦]AìXdæˆøˆŽ8Žãô®â ‹ƒÒ‚Ó++(ÌœŸ$6j Lé‹1N¸ë•¯äH³Ðø%]ŸB<š!Ò¯¯ëŠë"îâîØÌŒ D¯Iñ}Žã u¢·H’FZ´‡Ç÷vßãy(—Ëø¿¿á€où–¢ ¦·}³Æóĺ›å©I(ó”ú(ËÀþ5ðߟÓ[ÓÃ[1LôKÛrjöd°†#š8˜™OFò¼kšx¨K"'$ aÀ0s‚ãP÷T÷$=} ˲e% ¼Ód]dÜD†™¶ ô—JBGU·)ý7^Â!IjiyŽéòŠ¢@–e|LJ>üÖoýS0}8‡‡‡0 ‡‡‡¢éÇ¢ÒO™—$)Ræ%éD±©‰ºT±Sòj‘$nSÍÌ%©Îìr¤§I7^ât`f™ ¦åržJ”„0ÌœâyÀ=÷|nðÈQ ®6ñõÝ÷ŵAp£=æIë0Æèê‡ã8‚ ™9Ù×MdP¾ç?þGÜyå ;èç˜ó®ëâòåË8<<ÄÊÊJ¸a{{W¯^ÅÆÆVVVðøã}®cѯջmÛÉ…_>éö j¸”ž ªÔ¦OôÐfã•™âö‰‘ Öxz0uƒd¥…™CLsø>žç… 7¨† š&Z¦žÈ9¬Ì"ÀŸþ韎± $›'²Ì: SYe{£ói¾j=]Þ‘åÍz!¬¼þõ™L«1 !ìi÷uf˜À÷Åzü¹|º®‹THÏˮۈ7Õ`gŒ¼>ÏóD+Ž1 Ùž?ðŸÀí·wotÕ÷sçİJÓk}\ã·m1¢F–G7>u3o˜™âyB ©V£,Þ¡ø>Vßô&üÒñ1¤x$ªÃ`£uá9õêUt:\¾|{{{888;;;xÓ›Þ„N§ƒííí¢Ïudâúøg?þq|ñÕ¯Nî@¹ítµxN²„¡ª¬ì0 AŠà“Ï}nÔD†””tj»ªFÚﳌ3 EÞÔ1ß÷ñ’›7Y¾™…„’»>úÑ·á‹_| §Éo˜öHÓ ÒQÑZMè6ãÖ½2Ì q¡·äê{äy€mã³ßüÍø£r·à½²ž2Z9ƒ`!¹m}}<òööö°³³Ó³Ãææ&®\¹²pÍ–*ÝøÜïýnÿŽïèÝÁ0’–m¿¬ 3§ø>Ïÿý[<_ˆ Cxã¯Åç¬ìIg ×î‚ ª_e…Y0¨¤ëº¸páÐlf¬Ñž9ÛûE—Xö™9%¾4÷µ7+•pÓ^õ*¼ùÎ;ñ[¿ú«“ë,’ÄzÏ‚r º_½zÛÛÛ8<< 7®¯¯/\Ýjœø:þÜO~÷~ÿ÷G/X#l žrR»Šh¤Í´t3ÌŒ‘ed§÷ªªHy÷}¡éÓ¡iQ§¦<©4 3'äI ;;+&ÌÂáºÂWnYVÿÎÀ®Ëc9˜…%r,ͪ è:<σeYøG?þããub–†ÛâOVVV°±±Qô9Í„Ï|éKB‰ñ!Ò~Õ“èˆ"« ³@PÈO¼ç=²24MÔ2Å0š&ŠGúuf˜9Åó†ëé®ëâWV¸á³x°¶öGп‹õÉ8†Y4È!3 Ó÷ᬭA9™£­³sýÌsÛ䇘_.\ŽŽø><? (CDS9€Ê,ÔoàÿÑÃs77{wÐõdtŠ|äts2Ìü§\É÷}üÀ[ÞüÀ}º 32® ø¾1þÜU†™cò¬4'»ÍŽ&Æù¢O`–ÐEáößøF@ЫÌÒàyÂîüÙïüN¬•ËÙ;QcŽ8†ÞN 3ߤNAÀ¶m8±‘žçá_ÿzް2 ‡ï/|áðŒ`f)ñ¼á=lÛæˆ*ÓÃR¬”ñøù_ø<Þô¿Þ$ž°Ã,4ÍÀó¼Ñœxwl†™s|?9;T«U”Ëeø¾˲`ŸŒ*Y®™…ÆBm”Χ ³@ÆpÕƒ V&‹¥N ø€ìÊøÒÛ¾Tô™0ÌÔa'ó {k˜¥Ã÷…^þçûûxÕË^Vôé0Ì̠囌լt1EQÐjµðÃ_ûµÉüa†Y~á 'å²xœ¤»çDÌ0sJ|Yö*• jµt]‡¢(h6›¸þßþ^õÜçòúÍd²Ô+àÏþòWñì+_Yôé0ÌÔñ<Ñ û¶'ŸÄWý³Vôé0ÌÔ±íH?·mZžÚ½ È7èaæß÷ñ…/<ÃÈPÔE n6¹Y³Ð¯±Z­¢V«‰F‘Ž”Ë, ¿õ-ß‚².Ãôai Vù¥dàÏ[M¼â¯(útfªø~¤·üÝ[·8åYJl[Ô¯ú'…O¹:a“'‡a€ ^óšÛñc››Qêo²œo1Ã̦)ìRñŠ¢DÎGMrMk67cú0÷ëáá!:ÎHïq]@þkàc/ø^úW…¯¸|¹è¯Á0™Œ#ß@¤“¿ûŸ½p¡è¯Á0}WÆ©\O–˲òEWáÍasJŒ+ßÄ÷~ï_ãoþf?°¿ÏÑSfî˜T¾=O¬åšüÉããË~ù—{‹)J¯áÊ0)æv¬M§Óa8<< <ë–eå~¿ô$ðûG?Œï{Îsø`æŽIåÛó€{îþ4^þ£?†¿ûs?Wô×a˜&•qËÑÕ ày^8Âf ñÔ†™!“Ê7 "O_úÒÇð›¯|ðZ•ëS™¹aòbV|­|öãÇíßó=¸¬ëœÆŒÅÜFX¯]»†ÕÕUxž‡Ç‡‡‡ØÙÙÉõ^Uþí—} ßþéëX98`o;3wL"߀0X¿²¦á#¯{^ò/þEÑ_‡az˜DÆir‡ªŠèj®T`z#;(™S`Ò5ܶEäéÛ:߃K_öeœîËÌ“Ê7 \ë:PZû8>ùêWã™ÍM¬ÿüÏýÕ˜e. ÖN§ƒƒƒ\¹r°²²‚ÍÍM4›Í|xê)|á™BP«±±ÊÌË7€W?ó;ø‹ã?Áëý׋þ: ÓÃ4d¼V–\×)dž'BRå2P* m?M¼KÃ̈IåÛóDþ’Ëø—Ÿü$žû®wý•&dëwµ*–âJ92VÿÞ¯ýZÑ_Y`æÒ`½yó&`}}=|m}}=w½÷¼OãGJŸÅ¥·¼¥è¯’‹ýýý0íbÑÕãÆL.ßðwÎÿ¼èío_˜ÔšE•“ÃÃCìïï} Ǥ2®(ÀïüÌ÷á/~ññßþíJ%¡áSÇÔV+Û0m6 1Xy ?[L*ß?ýo?ó³oÀßûÓÿŽ—~ðƒsïX_Táõ{<&ÖÁO2d¾»óOpëk¿vîU^¿ƒ¹¬atQcee¥çõÏ|æ3øÀ>€‡~÷ÜsÞü¯ÿ5Šþ*¹xÿûß[·náøø¸èS™ëׯãÒ¥KEŸÆH<óÌ3øã?þc|æ3Ÿ)äóÇ‘o:ï‡~/zÑ‹ðu>ˆç?ÿù #ã‹('ð¡}úЇ°ººZô©Œ|ÞO?ýtaŸ?éþÜ'ž€êy¸øß§^üb×ëø›ç?_ìø?ÿ§x̼†Ÿ.O>ù$>üáã¯þê¯ ùüqä;¾~ÿ“þ+Üñ «8®½s(ÏiQF€Å_¿;N!ç>éú}×'>«¿òÓhÕWá‰ÿôŸðÂ{ïk]…×ïÓ…tðQ×ï¹4X Í­[·2/–óçÏãèè?þxøþI:›6Ng!/– .àÆEŸÆH<ýôÓøó?ÿs¼à/(äóÇ‘oxîsŸ‹Ç/}éKñ²—½l¡~÷E”@ü=,ܹ{ž‡/}éK…}þ¤k¸¢(ø‹ýQ„*Îx¿y ?=>ò‘à3Ÿù ¾îë¾®ÏG¾ë÷ö¶xqA~÷E”`ñ×ïO}êS…¬ÓX¿ÛW¯âü]wó7 !ç¼~Ÿ¤ƒº~Ï¥ÁOCHÓïâý®ïú.|×w}WѧÎ0CG¾àá‡.úÔ&¼†3ËÌ8òÍë7³(ðúÍÌ#sYÃzñâEÉiQ© 3mX¾™e‡eœYfX¾™e†å›™GæÒ`]]]ÅÆÆF¢XÞu]”Ëå¢Oa&†å›YvXÆ™e†å›YfX¾™yä\·Ûí}Ybkk «««a‘÷îînßú>†Y$X¾™e‡eœYfX¾™e†å›™7æÖ`Dá7µšÞØØ(útfª°|3ËË8³Ì°|3Ë Ë73O̵ÁÊ0 Ã0 Ã0 Ü]沆uQ9<<8|øððpà¨AÛ‡½wšßašç}šçÎÌ–YÊwžíÓúÓ>7–ïåa_Vù>­sgf ¯ß,ß˯ßÅû©Ðe&æ‰'žèÞwß}Ý{ï½·{ï½÷vï»ï¾îO<n¿yóf÷ÿãnë[ßšxÿ íÃÞ;Mzè¡î[Þò–©œ÷iŸ;3;f)ßy¶O‹´|Ozn,ßËÃ$2¾¬ò}šçÎÌ^¿‹?wf¶ðú}6ä›#¬S`kk ð<?þ8666`F¸ýÚµkX]] ·bgg'×öaïØÛÛK¼6ÉyŸæ¹3³e–ògû4È’ïIÏå{y˜DÆ—U¾OëÜ™ÙÂë7Ë÷²Ãë÷‘ï¢-æEçúõëÝ{ï½·ûì³Ï†¯Ý¼y³{ï½÷vŸxâ‰Äÿ‰_ýÕ_íÞwß}=û¦·{ï´xöÙg»¯{Ýëºo}ë[CÏ$çg;³ÌR¾ólŸYò=é¹±|/“Èø²Ê÷i;3[xýfù^vxý>;òÍÖ Y__ïiõ}óæMÀÊÊJøÿõõõÄ{(Ÿ|Ðöaï×®]Ãææf8,zØyMc;³ÌR¾ólŸYò=é¹±|/“Èø²Ê÷i;3[xýfù^vxý>;òÍ넬¬¬$Ú}w:ììì`ss«««…ãøøxàöv»=ð½Ó`NÛÛÛ‰×'9ï<Û™Å`–ò}rÒO¾é»Œ{n§qm2§Ã$2>LU¾y _xý.îÜ™Ó×ïbνØ`ÇÇÇØÙÙÁý÷ß \½z5|½·nݸý™gžøÞIét:ØÛÛ Ï5ý}Æ=ï<Û™Åbò=k9$ß“žû¬¯MæôGƇÉÁ¢Ê7¯á˯ߧ{îÌéÃë÷é{Q°Á:±µµ…ÃÃC<òÈ# oI<ŸfuuuàöAƒšWWW'>ïýý}¬¬¬Àu]ìììàðð7oÞÄÎÎ^üâ}Þy¶3‹Ã¬ä{Ör2H¾;Î\_›Ìé2®Œ“ƒE•o^×^¿OÿܙӅ×ïÓ=÷¢`ƒu †æÑ§…„òÒãáùN§ Ì íÃÞ;)—.]ê{Á¾ä%/û¼ólg‡YÉwží“0H¾'=7–ïåb\_Vùžõ¹3§¯ß,ß˯ߧ{îEÁ넸®‹N§UUqppx“±±±ýýýÄ{ÊåòÐíÃÞ;)ØÞÞëëë¸xñ"¶··¡(ÊØçg;³ÌR¾ólŸ„Aò½ºº:××&szL"ãË*ß³>wætàõ›å{ÙáõûìÈ÷¹n·Û-ú$™ÌùIày€(]auuÇÇÇXYYIt5´}Ø{§ý]±»»;ñyçÙÎÌ?³–ï<Û§ù]âò=é¹±|/“Êø²Ê÷iž;3xýžsgf¯ßÅŸûiÁë)q||ŒÃÃCÙyóƒ¶{>wÑçΜ‹,'‹zm2§Ë$r°¨ò]ô¹3§Ã"ËÈ"Ÿ;szðú½øòÍ+Ã0 Ã0 Ã0 3—p +Ã0 Ã0 Ã0 3—°ÁÊ0 Ã0 Ã0 ÃÌ%l°2 Ã0 Ã0 Ã0s ¬ Ã0 Ã0 Ã0Ì\Â+Ã0 Ã0 Ã0 3—°ÁÊ0 Ã0 Ã0 ÃÌ%l°2 Ã0 Ã0 Ã0s ¬ Ã0 Ã0 Ã0Ì\Â+Ã0 Ã0 Ã0 3—°ÁÊ0 Ã0 Ã0 ÃÌ%l°2 Ã0 Ã0 Ã0s ¬ Ã0 Ã0 Ã0Ì\Â+Ã0 Ã0 Ã0 3—°ÁÊ0 Ã0 Ã0 ÃÌ%l°2 Ã0 Ã0 Ã0s ¬ Ã0 Ã0 Ã0Ì\Âëœ\×-ú4ff°Œ3g™YÈ?_SL°Ü1g–õâaƒuÎð<år¹èÓ`˜™Á2Μef!ÿ|M1E–;Û¶áû~ѧÅ0S‡e½xØ`e†a†a&ÂqVâ™3Ëúés[Ñ'ÀDžI’ (Jßí²,CUU¸® ]×Ãí®ë†© š¦…Ç0M†aÀ¶mAEQ iZâó Ã3êþ “—A2A(s’$A×uH’Û¶C™'ÇAÐuå›Yf%ÿµZ –eáܹs=Ç´,+q?`˜iÐO–éuÇqªª&dTQ¸®Ëk6³0L"몪ö]Û–íqàkÁ”J%˜¦ @ž•J%±Ý4MX–@(+•J%¼HÀ²¬ð=A T*Á¶íĶ *• Êå2<Ï ·Óg³?ÃäaŒA€µµµÐáâ8N˜vA¼M"¯,ßLÌRþ«Õ*ÇÁ'?ùÉÄ1Ëår¨1Ì´¦¯¤‰Ë¨ïû¼f3 ä²>hm§ýY¶G¤ËF½^ïJ’Ôm·Ûákš¦uéÏÒn·»ÛeYšØÞjµzŽÙív»ºõz=ܦ(JW×õð¹aá±ÆÙŸa†1LÆ›Íf7¾ uUUí¶ÛíùoµZ]Ý£££n·ËòÍÌ?³–Ã0Ç9::ê‘k†™Ãd¹ÛívUUí6›Íðy\Fé9¯Ù̼3 Y´¶Óþ,Û£ÁÖñ}ªªB–åðµxª¯ã8=Û5M ÿïº.dY»—ÅŸ“—&þ^I’Ât„~Œº?à b˜ŒÓëÕj®ëB’$4›MȲ Y–¡(J˜Qà8N"¥&þ~€å›™?f-ÿñta¡‡>~Ÿ`˜i0L–û‘–Q^³™yg²>hmOï°lç Ö¡ºÔ~A0ôýT«¤o SÃd\–e4›M@¥RÁ¹sçP­VÃ횦%v–mf‘8mùW†a$ŽÁ0Ó`˜,3̲0 Y¶¶3£ÃkȲFB‰¸‘*IÒ@£UQ”ÐkCF£Ã0¸v‰™ †É85¨×ë8::B«Õ‚ã8a¶¦ið<–e!Ž1 Åi˽^upý3M†É2Ã, Óõak;3:l°ˆ¦ip]7ô S´4¾Ýó¼°h›:Žñ.d~3Ì<0LÆ©‘Ý dYîIùÕ4 –eåJÉa˜y¢ù—$)ìVÉc˜i1L– 6b™Eg²>lmgF‡ Ö¡ô­J¥‚R©„µµµžøz½Žr¹Œr¹ŒR©”ØNЉiš(•Ja‡àF£QôWcÃeœjòÖÖÖP.—±¶¶*é9f8ºÊ,EÉ¿¦iÐ4—ÌÔ&Ë€ÐILÓä(³ÐLCÖó¬íÌhœëv»Ý¢Oâ¬ãû~æ¬'jž$Ër˜SO3šâFi¼É¥ 3Ì<ÑOÆ Ê"ÈÚnÛ6,ËB»Ý.úk0ÌX°ü3Ë YŽë,\ïÊ,:ÓõAk;3l°Î1¾ïcmm ­V Š¢À÷}”Ëe†Áé‘ÌÒC©4¥R º®ómæLÁòÏ0 Ã0N žcâ)ÁçÎC©T‚¦il¬2gÏópáÂȲÌ2Ïœ9Xþ†aFÀV†a†a†af.¹­è˜Nò'‚½èEEŸÊÈ<óÌ3¸ãŽ;pÇw}*#óä“Oâå/yѧ12Ÿÿüçqþüy¼öµ¯-úTróîw¿wÝuWѧ1‹,'Ÿÿüçr]yòÉ'ªÁ¯áŰÈ׿ÊÊÊÂÔ…ñú}ú,úúýÆ7¾+++EŸJ.xý.†E¾6G]¿—Æ`ýÓ?ýS8޳07¯8žçá¥/})^ö²—}*#óØcá oxCѧ12O?ý4nݺµPë¯üʯ,ÔùÆYd9ùä'?¹ëÊc=¶P+¯áŰÈ×&€…‘^¿OŸE_¿¿íÛ¾ma V^¿‹a‘¯M`´õ{i Ö»îº Š¢`{{»èS™ýý}¬¯¯c}}½èS‹EüÍpãÆ¢Oc$^üâ/äoM,â¹âðð›››EŸÊXç¾Hð^‹ø›/ÚÎë÷é³èë÷êêjѧ‘^¿‹cóqÖïB›.TªÑétŠ<ÅSass“/”%„å;bQåd}}}!•Ó‚e\ÀkøòÁ²±¨2Âë÷`XƼ~/…DXqíÚµp>Ñúú:®^½ L§Óaá…¤ª*,Ë*ú·b˜\°|3ËË8³¬°l3ËË8³ˆaÝÙÙA§ÓÁã?Ïó°ººŠ½½½pûµk×°ºº Ïóðøããðð;;;EÿV “ –ofÙag––mfÙag‘S7X±¿¿«W¯†Åä>ø .^¼@xvpåÊÀÊÊ 677Ñl6‹þ­f(,ß̲Ã2Î,+,Û̲Ã2Î,*§žL)ëëë8<<Äññ1Ö××Ã<ì›7o†Û‰õõõ3‘GÏ,>,ß̲Ã2Î,+,Û̲Ã2Î,*§n°Þºu °µµ^·nÝÂîîîÐ‹âøøxaZ|3g–ofÙag––mfÙag•SO Ž{wÞùÎwâï|'677±µµ@\ý  -‹'Ÿ|=öXx†éÇþþ>zè!xž7õcÏJ¾à©§žÂÖÖö÷÷ üõ˜E`kk úЇfrl^Ù¢ÙÙÙÁC=„|ä#S=.¯ßÌ<@ë÷,F“ñúÍ é࣮ߧn°^ºt @²ó<€ããc l-=h&ÕË_þr¼á oÀîîîi%fÁØÜÜă>8“׳’o¸ûî»±»»Ëmú™¡ìîîâž{î™É±y gŠf{{>ø ¾æk¾fªÇåõ›™hýžÅ¨^¿™¢!|ÔõûÔ ÖAé+++‰Âo¢Óé,ÔeæìÂòÍ,;,ã̲²Í,;,ãÌ¢rêëúúzO í¬®®†Û666i3®ë¢\.ý[1ÌPX¾™e‡eœYVX¶™e‡eœYTN½éX–•¨å ‚ob{{[[[888‹¼xà¢+†ÉË7³ì°Œ3Ë Ë6³ì°Œ3‹H!ëúú:ÞñŽw„Åß#mg˜y†å›YvXÆ™e…e›YvXÆ™E¤ƒ¹òƒ.‚aÛfžaùf––qfYaÙf––qfÑ8õV†a†a†a†É¬ Ã0 Ã0 Ã0Ì\Â+Ã0 Ã0 Ã0 3—°ÁÊ0 Ã0 Ã0 ÃÌ%l°2g’[·nÃç?{ѧÁ0 Ã0 Ã0Ì ëÌ0i‚p]ñPU@Óúïëy€¢do‹Ï·ö}@’¢ÿ‰ÿÿçÿ|7$éÓEe†a†a†a0–Áº³³ƒƒƒâÊ•+X]]E§ÓÁöövÑ߇Y@‚0Ma¨jš0DM³×`õ<ÀqÄ~’4›âuÓÛèy£!ž«jÿÏ4ÍãÆýÕ†a†a†ÀÈ)Á;;;ØßßÇÆÆVWWˆyMûûûØÚÚ*úû0 B¹ X–ø¿$ #µÝj5@×…±é8Ñþ¾T*b¿V+2N@–“Ï%i°±Ê0 Ã0 Ã0Ìb0R„µÓé`oo»»»ØØØÀáá!@UU¬®®âòåË8<<ÄúúzÑß‹9e(7ý½ß§VKî«ëÉçµZ”Ê ãÖ0²Ó„Óïe†a†af9É`½yó&`cc£gÛúú:Ö××q||\ôwbNJÉ¥H©e‰è(Õ˜V«" "Jû "n¬º®ˆ°ÖëES†a†a†aN“‘ Ö••Àññqøâøø8Œ¸2Ë‹²½æyâ¡i⑎–†xÄI#žض8>« Ã0 Ã0 sö©†•¢¨[[[ ã´ÓéàÚµkX]]ÍŒ¾2óGˆGÏõ¥¶-žK’06©{/¥ùÖjƒ»ø¦ÕXD–,ó~†a†a†a›‘»ïîîÂ4M\¾|ppp€½½=¬¯¯Ã¢.:ÌÜS©C”"¤•$¥ZSEž¾;KÚí¢)†a†a†aŠbdƒuee»»»8<< ëUWVV¸ÑÒœÂ%mµD½éÚš0Pëua´r4“a†a†a˜y`$ƒõàà[[[xüñÇÙ@]ªUa ¶Z‘!"Š*I"ºš®Aefñáx Ã0 Ã,#×°®¬¬À¥3S‚ šU:Ž#ŽQ«‰N¾„¦ñœÒZ­†?üÃ?,ú4f&ضÇ{¬èÓ`†a†™˜‘»ooocggN'sŸííí¢¿ÓRày": ã2žÒb;¡(É10„iŠÈª$ ãÕ÷£ôà¬ý—Ïó Ë2¤“/]=ùa¿íÛ¾­èSc˜AÛ¶¼“‹Þ0 ¨''ß÷Q©Tº®C×uض Û¶qß}÷}ú Ã0 Ã03r ëµk×{{{™ÛÙ`ÏM‘êõÞHhˆ.¾ñ×M3šo'Þ°¨Ùÿ–ˈ]4Hq—eÚI{â à8ÇrbÑK’EQ ª*\×…eYNÚ!+Š‚  ILÓÄ7ŠþZ @ÈrµZ…çyPUŠ¢À÷}8ŽMÓ ªj(÷ÕjªªB–eX–…Z­UUaYJ¥ ÙlâêÕ«E-†a†a˜‰Ù`õâ¡=fê0VdTÕ¶]õ¨º.ñm–%R=O쓞ƒ ˆèj­¶xÑUÏóB%Ýu]˜¦*ôªªÂˆ}YÏóà8N¸­V YÏóàº. ÃÀÁÁAÑ_‹9ÃÄË*<σmÛ0 F®ëÂu]ȲŒvF›ìV«˲àº.šÍ&ä“âôZ­:d†a†a–…‘ Vf¶X–¨1M’qÑ4)köiÜx5ÍþM”¡°ïû¨V«ð}²,CQ8Žƒz½¦ARz¤šQˆ«(ÎU%4^fÖ˜¦ Çqˆ4^]×áºnèL‘$ ¾ïC’$´Z­ÐÐTUu Óñ²`c•a†a˜ec,ƒu,Vîd€IDAT®ë†Qª ¨ªŠÍÍÍ¢¿Ï£ëÙм|)õwžñ ÃH(â’$ Uè¦(×¶mhš†V«… `Y.\¸EQQQ†aFÃuE&ÑŸýÙÝå}: 3žx≢Oa抑 ÖìííassW®\ Æ'\»v ‡‡‡\75¾/þë®ýôØe ÆÓ{©Þ”Òx$"M²,³bÏäÆó<˜¦‰F£qª‘F2RI†5MK¥’$¡^¯£^¯ý1ÌBS­Š²E.]:Æç>÷…¢O‰a¦ éH_úÒ—Š>†™+F2X;ööö`YVO„KUUlmmáÊ•+X]]-ú{Í=ÔXI×E½©ï‹tÞFcvŸéŸXÈEÔX¦^¯'Rsµ¬-† e”¹® MÓBý‡JD(ÃŒþ­×ëØßß/ú´f®É`½yó&€ì:Á ¬¯¯ãæÍ›l°Áq"ã”ì6ÛήOß÷Q.—¡iZ˜NKõtT/w¸® Ïó idYF¥R®ë\GÊL ¥“ÓZD²¥ë:*• ,Ëê[çI§i\Lº×0£“ºOK’”i¤ZV4ÿ8yÎâÚÏ›ÞÏ0g »¦ªâ_Ï÷GY÷G@tÎg˜y„J˜Ïóàû~Ø@ô˲ày$I‚$I}KDØ`e˜$cÕ°cee¥çµ~³Y™ÛšJLS‰5M†aÀ÷ýpÌÕÓY–Ö‰ö#˜¦vÔÕã]rBÍ“t]¥iÚXÇbÎ.A„²­R©@UUT«Õ°¦™d«^¯£\.‡ãaß÷CeAUÕDú9ضÝãè‰os¾ïCQ”Ä,Ô輄#*„’â·mñ¯¦‰ÿ—ËÂYÅý‘˜³ˆï‹ì"Iÿ×4q­P{ š5.IâZâÛ3OÄ»¼“QJNOB’$hš–Y Ax/a&#¬X]]…iš¸zõjIít:x衇Â}˜lÈXÍš™:.Žã$¼wŽã ‚Py'Õ¶†r¹¦ŸdÏ4M躎f³ ˲°¶¶UUCb<}%‚pΩ®ë0 #4(â}& ê’Û¯æÔ²¬0J2MòIT×u{…Z­†J¥^dø†Ñ·–”"´¦i¢\.£^¯‡™T‡Ú/úJJ¸¦%GJ¹ntÍ"BdÛbßEhÆ0“âûQÖA£! Ðx’éþñ[…¢,Oßfy ÝF’¤Ä½À0Œ‘ŒOêßÁ0L~FްRªÝý÷ߟx}uu»»»EŸ¹Æ÷§k¬ÆÓ À¦i0M͘&œ^%I‚a¨V«‰ý„ãdâ)*õz=4TŸTCH‹yžÑÌÙÆ¶í°4+—šqµÛm”J¥Ðð¤¢ßx£v» ß÷Ãô«AM\7R˜kµ\×E¥RÁ_ÿõÝøñÿG3hvrz>²8¤rˆ}(Å‘a–Y×A¿’—<· Êâ±MgrŽ!ä̧) Ü.#¬ëëëxÛÛÞ†?üÃ?ħ>õ)ÀÊÊ TU]ÈÚUJE𥳋jqFMûµm¦iB–ehšÖ‚GgÑY©TÂQÃjð4MƒmÛ¨V«Ð4-L­ÐcÄùºõR=ŸeY‚``Ê1ئ Ïó´\JÇGNMÓD½^e«R©ÀH •òÈ®iFiú´«ªª¸ï¾?Ãþþ—Áqžsr¬låÚu³ÕAHR”2Ì0ËÎ$ú=•”AÀ¶—ÏóP*•Ðl63žç…Y3ôœî³6`)8À#ɦ8Îú†ýý}ÜÿýxüñDZ½½íímàþûï_Ø"qÓœÍqƒ(•¢”§Áç`Â4ÍЃH d»ÝôjµŠµµ5T«ÕÄø*ܧڻ<Ðþ¶mãܹsC#Py1 ƒU¦ª‹®T*X[[ d ]×ÑjµÂÚgÛ¶óv©ntÚM»l[\ŸµšH[ŒÎx×»¾O>ùÔë©¿Ž+Q‹J5x£ÖØÉ²pd1Ì2CΠq ‚Žã Ùl†ã£˜å¤Z­¢V«¡Z­†zá8*• šÍ&šÍ&ŽŽŽ¥R ö SVâÁ6V¦?¦)KæáÑG_Œ§žzñhÐgŸ}¶ûº×½®ûÐCõlûÕ_ýÕî½÷ÞÛ½yóæ(‡ìv»ÝîO<Ñ÷õ¼Ç»~ýzæy Â0ºÝz½ÛUÕ‘O¹/š–<^«5ü=ív»+Ër×0Œ®,Ë]]׻ТtŽŽ2÷o6›Ýv»=½“>ƒŒ#/ã2 ùîv»Ý·¼å-§r¾“’–ÍV«Õ•e¹[«ÕrÉ­a]§"ãF·K—™,w»ô‘õºXÑçòÌùMöþ<œ¦¼µ†3ó¢t»ïyÏ÷¼^¯×»’$uÆÀ÷ëºÞ­×ëÝn·Û=::êʲ® §%/gmý> šÍf·Ùl†ÏkµZ×8YpëõzWÓ´n·+þæ†atEé{?HËÅ´8::êÖëõ®,ËÝVEnÊðúÍ,µšXóûqt$ô*Eévßüæ¿èþ»÷ðHÇ)Âzxxˆããcloo÷l£ù«4ú&/;;;ØÙÙI¼Öétpùòe\¾|÷ßî¨á¨8ÎôFÉQ[þxVmž`mÛad²ÕjA–åDô)ªªìé[Š”ï"ð<årkkk0M¶m‡žñ<#cQCÚív'’qšsÜÏÛG|M‹Òrk5qý"b:,Q`’,4Y^žtà³&ãL>|_Èù÷}ßw†%'€X#,Ë ›úõ‹ŽQçUª§fjårårÛÛÛxê©§fúX¶gCµZ…eY¨T*p]Žã„¿#ý½+•J8å€ô¢,¨/ǨQVÏó`šfØ92GM÷J¥RØÓcY=¾?»l¾I`gÆÅóD¦e‹†Ðk²²Ç‚@ì É4?Ž»îzv¤Ï9%x·nÝiÿƒƒìííõ¼~íÚ5¬®®Âó<<þøã8<<ì¹ ¦A»ÝÿÇËžhÛ6.\¸¦¼P÷ÒøM™›K,EË÷iãû~hœ’‚Auª§Ù1Þ±×uµµhÜ ®÷R)2N M‹f@žÆ9æ)˜wΚŒ3ÉñMƒpàöÛ?¼·‘ÑZ­VQ¯×¡( šÍfXþ’üŒ süš¦ih·Ûh6›ØÙÙÁÝwß=³ïɲ=LÓ„¦iaY¥Çu’V«•«ÄH×õpB Hߢ²ªølÔR©N]¨×ëh·Û¨Õj|¨V#Å~кï8âÞtZ†-Ë8Dz„¾”w÷Õ 6Ç:f»-ö¬u?„QkÛâÞtm@XÆ™8–%l˜V+2(ã}=€ÈùB]ïmD©ëÂ)סd9ÒÉ&aä«eY888Àë_ÿú0eàõ¯=\×Åîî.VVVrçÚµkØÜÜÄÅ‹¯SJqÜð]__G§Ó™ì›Æp]™”xdÖ²†·ç§y‘µZ-4ZÇ82ƒYLŠ”ïYây.\¸P ( X×õSs¾˜¦ð’·Ú¶ ÄsIê5Fkµh¼Œ¦ vR5³O×U”é–#Á²Êø²àyâ:1Íée T«â>—å%§¦¦iÂ÷gžyoxÃ7'F¤éºÞ1K­Õjªªz_dÙžÕj²,£\.‡©àº®Ïĉ©ëzfZ05kj4É–ç‰ë`Øv:È”Á¿)㇔úÓªöbgr ×ëѺ—[ JÿÍ3ñDÓ„£&¢²¬iÈõÈëúú:ÞùÎw²,lll`ccW¯^Å;ÞñŽÜÑÕýý}t:ÌZØAE<ª; AüñÆuâ:N2j3,ÍŸk¡r?«Å›)Ž¢å{–P½5\¢Î¿ä„™Ã:‹Z–¸ÞÚíÈI¤ëÀÑQ¾™Žƒ¤ÙޏгÈë2Ëø2À?ü‡Ç¸yóPÕÑ0”-‡j¤²B÷?Û¶¡ª*êõ:\×ÅÎÎÅç>÷ó=µoýjáâF«øŒâ:ͳl燺¾Óè¡8½«Õjh4¨V«‰èê´¡fñó 1{YÆÍ¢ÉœÔ9>n”Ò ïFc¸þ8MXÆÇÎøQÒÄËåþ™0YXV²ŸtüÛv$§yÔ<Ã×È´³Õ†Îaít:8>>î1Fãi=£Ðét°··+k>aÐqëÖ­¾Ü'Ÿ|=ö±»»;ðh.*1ê½Ñq"/3ÝØi4¤ã8a£ˆ¸!J‹h<ʼn Ù‹aoûÛñœçô¡ÍäØó°†3”NX«E F¥Ȳ‹}èg ªo ®ß~¿£ú%ò¤û~¤¤§•EÇ¥&Jdx®­­åš G’$´( b;;;¸~ý:.\¸0ÕßrÙ×ïiB5£­V ŽãÀqX–6×s]7L#¥Üa5¦“¢i,Ë‚ëºð<Ad¦²’¦^ÝÉIºé~Š]3õúp‡gúVY«õ¾‡ÖïÃÃÃÜ ¼ðú½PÓ:UúP¹œßV‰‹<õÖé§¢Q´ßÒKFç(ÑI~×é࣮ßC VØÛÛC§ÓÁÆÆTUèÚßßÇÊÊ \×…ëº8<<ÄÍ›7±³³ƒÍÍÍÇ^]]í»íå/9Þð†7dzŒÒøþø‘êôFÜôò,¨ªŠR©EQ Ë2TU r¦x677±ººŠ7nLýس’o¸ûî» ½P…ˆGA¨N'Ï‚æyb]Oî÷6ÂKW.‹ý‚@,¼´°.CR‚mçÿÍFeww[[[39ïyXÙrÀ’‘£Çó~€h†&Ë2t]\_¤ʼn+Ü”šHÈrtM¦©Õ¢u!2N%üÖoý)¾áž7³ï¼½½K—.M} _æõ{šø¾Ó4Cg%e׸®vÝ¥9ñÍŒŸ%š¦%f{r˜P×í¯šfd˜JRò: {R³)F£dæX–8ž®g;-iýž¶± ðú½ضx®#IBF‡9¹M3[¯²¬¤±ëyâuEÿÔ‰¡ã\ºý®‰quð¡ëêêjè‰q]ûûû¡×‡ ØQ¸téÒÀí”Oßét‹#þÿiÉÊ4Åó<_¥RéÿÇuŠ¢ V«¡V«Áó5ÆnZ¥šuº§Ù¶ßüÍß ·[ Ëw㵯-ú—–ílÈ@¥¿9upN ”yGý:Š`ÐçRvÝcÒˆ8ñlŸìÏ÷¾rY¬á£Ä#4­·¡ÍiÁ2~º³QÑŒ£ªBû¬®+é(¬aDzérõ¼Hçv™Ô÷.“\Öè‹Ò€]× [bb¼RÝ+A­²ã^™ ìï¹®‹ò( ÙCH7 Ea$¥: ×uMgE)¬Ë!S ó ßÓ‚"3€P^Ŭ:%tÚÈrä l·Å¢à Êô½^Qô[BÒ©Áˬ2ä|x챚ɱ—IÆ Ó4C2î9¿páÚí6$IB£ضÞ¯³Rÿ¨JÓ„ÃèùÏÿu|åWþ>Êåÿ#Lå¥ö¶m#†v}¥ô_×uñƒ?x ßÿý¯»qÓq–ílÈqAÿWe`ƒ½ytΛfo45^Kš¾oQšý j5qÜQËÊd9Ÿsw°ŒŸñÚÿa)µ¾/ö×´l燦E£f²t¬~rH6 Eg)²Z8ŽvæÖ4 Š¢À¶müÒ/ý^ýêWt¬‘ Ö8qãõðð®ëbooW¯^8a{{[[[888Àññ1VVVðÀLíL¯³yÿxž7(\Ì÷ªµ 1 ìå{ZT«Õ°aÍ &£’®ª'¥EpÁJµY×›,Ÿ^wÄyA¤mÎF¹—eàû¿¿ ˜ÄE‘ñy…ÆPó Âó<üùŸYâZòNr©!íGÊ—ê T*•NŒO • ðƒ?ø ~ù—ÿ~ï÷„Åiš&<ÏC³Ù„,Ë‚Õj•J%Lõ$G,E^ÿüÏ#c À~I§ÂY“mÊË[_<úñÅ¿y|ûãd¤PÈÎСTËt¯„ôÐCS=‡4Íf·kÙÛjµZ×è·‘™;NC^1ª|w»Ýî[Þò–S=GI’ºÍf³+Ër÷/ø¦n»Ýžèx†Ñÿú9‹ ZOÆ¥ÕêvëuñÿÓ–—4ó¸†Ï#ïyÏwŽz_o6Åß³Ûív !+·ßþîw<Ñ­Õº]ºëõz×0Œ®,Ëá{ãÿ×u½Ûh4ºÝ®¸O©ªÚ•e9¼žu]ïÖIhP«Õº-:¡ŒsÕ´è|Oƒ"åeÖïi¡ªj·ÙlÎìø­V·+ËÃeGÓÄc”ãªj·«(ÑšØo¿QŽ{Z-/¼~O³)ä.-Ó­V·«ëÉ×êu±oÖ= tý {½>úú\¯×»²,weYî†Ñ=:ùv»n3 £Ûl6»ªªv5M ïEš¦ \7Æ‘—\ÖÃÃC†N§zk©žòÚ)º:­îw+++‰´…YBM`†y7â©Ä¾ï':â9ŽƒÆ2ºÚ˜™pšò=.T¯äº^óšÛxšÒ^]w9ºûN аN ßO6­*šEñ"¡fIÿò_¾ _ø‚Œƒƒ•„ç;í-¿páð?ðkøàºÞ =ÞM ‚ ì£o6£ªjèÕ¶m­V ®ë¢R© ÑhäÎ Ô4PU…—¿RA"5xY9+²í8$IšIŠoµ*¢šŠ’¯©¦‰Ç°ò¶û75ŠCgq¯T'x–8+2žšg=ìþJÙ1Y‘UzNÙ(ž7zÔ“jU©&•îùÃÞ?j0eÚPf…eYX[[ ³kEILˆ û 0ÝÉqr¬†a`}}=Q Cµ«»»»XYYÁÞÞ^ØelžÉ SQô0âï¡–îÔ|B’¤‘Zø3Ì<O#¬×_ˆúOó¥b¹n4:£TJ^kƒZ«ŸEdy|Å(=|žšXca î£Í&ðü[|Ë·|Lóµ¨ÕD—fS¤ZQ'nѤ¥‰õõ¯ÀW|Ed€âZ%ƒ“êMã5ÉŽ[Ó4 žç¡T*Mmæ©aL×Ã)ªf– \­ŠI§{‹ç‰)×ñº¾øZY­Fk9DÓ÷–Qª³(-˜F€0LߺM¨9d?}‰ä2>a½HQĹP{ž”ã¼PçhÇq iZb$5“„>ã‹g¨Ázpp€N§ƒGy$œ¿t||ŒÃÃC\½z5|mss;;;888˜k¯L|1$T5_Ƕ¸’WZ–eØ¶ÍÆê¸˜–¼æi‘pêÈ@Qø¾x-¯!¤ëѵDc˜þŒº¾Ó*¤ùêæÇ †fœzžEQð¼çý4‚àµ(—©¤fðÄ#©Ôøˆº°ÆçZªªŠjµ ß÷Sr¦:ŽƒvìB&åcZJFÚ¨`’­z½>RÃH×÷<ª'Í2(e92f5-šÊÞ‡ÐÄ÷¡Æ2}åÞCÎÔ˜> -9) ® en'F0}p¡ÄÓ½Ä4£¿' <ÛªªB–eø¾Îø¦(9‡ƒ ¤b_±øº®›ÈîÑu=Ó%…aú‘ˆÈE:EÇêADz?,h@Fk¿ñ´O£!ö‹ëÚª:Ú„qÎŒ ¥óú¾ßû½—ÌݼlÄd ÒºCN´ºŸ01¨™•œ”J½™;42@Q”Ð`ð}?œáíy^82-®Xжt„U’¤ÅÊøaæ†jµ:òX>*¡ûÄ rWÏÎÐ<™†’4\ùWî‰ÀÌUMÞƒ)⚆fœã8(—ËX[[CµZEµZÅÚÚJ¥,ôèÍ¡)ÁëëëØØØÀÖÖ677ùLt“<>>Æ7píÚ5lll„]ƒç‘A•ÒJ¡aD Ò zÞê4íl"š9®~dŸC;9¯ISƒý“㨘Nô÷ bÛBöƒ @³9¿×ò²@¶E ¬_¤€™,ÏŸÇ–é9D©>UQ¢Ž’šüÚ¯½ï~÷»!I×Â÷Pi‰ªªaSCêô+Þ§ÁqœÐˆ%dY†çy‰Ò†Ó4ÃHÿ(P pE×2f‘ r:a%Ý$©\×À4–aÓ4ᜤrªª UUGÊæ´m¶mgÖ /ýbh„u.ªª†£®^½ŠõõuÀÃ?vž÷zÏë/Tñ4êœc#<‰TG´x¢ ‘>;é±$3ó2¢zZc ç7Rå“çܵr(A„]!i!ö¸Ýç©R. ãµVãÚßE…ÆsÔjHtÔ'þìÏÞ…ßù·…Ïã „hp&°xÔTÓ4¸®Ûsß¡ {/b !˜¦ Û¶áylÛÆÚÚ€Ñë™)$=q¡šÊ–rœd<Ã,¦™}/–åHO¢}¦qϦFH­V ívš¦Á¶m”Ëeø¾^»kkkaµ\.‡F®eY°mÍf3ó¾°èÆ*s¬ÍÊÊ ®^½š¹mss›››sY%D÷ÓáûyžXŒ£Vë‚@9i¹î,n:0 ŒLÂhäk'Ç™¤¾1™•LÚ=?ý· TNŽ;©óŠeY‚õz=\ˆY>\Wdrè:SXThÖp²ÎÉ„¦i %ŒN6B%I kŽâ³îÈyÔo¶*Ãä…Æñù¾×u!IšÍæØÊlÚÆõ×É×L“ço3óƒç‰Ô°À%õȲ¢²Áqd›"¡´Ö˜ÊÏܤ«ã8¨T*‚º®':½S¹eÛ4›Í¹ìî;-r¬€¨Q½qãàÒ¥Ka ë"ªÄ aÓ¶-PQ’s½nÞüV¼ô¥ßƒ/û271›h¡ {’ŠÉ;Ç£™düNÃãC—£^snÆçSº±îBœ">|”dÊ(ðó %f¦5jàt¹ÅƒfDÚv²vjQ©>5ÚßG­V ›ö¥ VEQ2;üjš–yM҆ɋëº0 c CrmM¤8­~ÛÅX¦hû ™” ÄbYù~tfbLsð¦~s}ãкßlŽV·ê8N˜~7.õÅÑ4­oZ0ÍÔ^˜&°¦)<óc.¹R‚wvv°µµ…½½=ìííakk ;;;Eõ‘ ¤®ú~´R‡e9zíÊ•¼úÕw@Ó´Åõ`ÄËn§a°Òõ`¼æKåŒ×<Œ×€)@¶‘[;9¦3á÷]",K¤ RÖ"EpþÇÿøK( zêå˜Ù‘§¹3?¸®hžT*‰ÔÇßýÝÏâ—~é8¡´ÐõO«§ô_Jñ;Í×0 BR¯×Ù`erC¥ƒÖvÛÎŽ’&Ó¿y%¬”ÌÆjŒŒR°ý»iFÖ3H®%šú‘&Þ™¿º>ZÝj¨T*aÊ®Èf‹nK¹Ž[V²>Àu“©«cË`ÝÛÛÃææfØ•pss{{{=ãnæAë@z(°,‹×žóœ§BÁzà¿—©8,,&Ư•ˆ:F7ûñ4ŒgLK蟞\?ù®|@¥"2­–¸HQUùÈGp„•aú!Ë¢éF«%t̾°†7Þ–ØÇ÷}†‘0Xㆥy¥›`ÄëVãô›“ÇN%flÛÚAšæMja` G]±¹ BŠA?Š,Gi'Þ°—ÿÏÿYô/%µZäTICå€ÃÔ|Uí ‚ ¬=¥G©T‚¢(¥ßÏ=i‹~Äj5*nŸ°YíPƒ•ÆÕ\¹r%|m{{ÂQ7‹B,õ»‡x!u<Âú×ýáoù-«×ŠþÆ1\ˆzÎ8:Æ'£#‘CÆâ(£d|ô±C黣˜ê€ãÉ'Ǭä?ܲR«E]îÈ`•e²,ãé§ß]fC2 # y¹éäÄCÆi»g¬YŠK«ÕZÜ f®¡ÚéAPwëxÆYj×Izé¢R˜ ¾/ÂvÃ~”ZM(ªªŠo≢Ïzé 5š–mpV«ƒe{Ô©T*Á÷}Ôëõ0šÚjµ–+Ø•¦ZÍöd‘¼—JâGŸÐÉš+ $kUWVVŠþy¦Žï'=.¤K¼ím¾6òo=Íy D-æ¸Hèm²$Ÿ¼6~D”5¯‘™'ˆWð]’ÏU;lsÆ£¬q¹Ñˆ:’*Š‚§Ÿþ³“4ø3þ#1L Ꟶþû¾ßc°Rä4>[5n°RZ0GM™Ó‚²fúEw‚ ™"Y«õ¬A¿qåR7óýÁ9ÑD|] K(¯3JÓðÿ¼öµEÓ¥"ý'Kûn,kpä´qCNÇZ­^k²,/¯Ò¶…1 ô·ôëum™Üë¢CEÒýˆ¬qÙzÏ{¾ùdÒ*cz’aX–0Þ¨ÙóR Œg§£ÇeÍ{¬x l?nû»À÷løñÊÃw3Ý-ض“£šD—;74Xÿà¾ü¤GX §Z7žQ8ñl½8A„Ù ää¡×$ Ötúoºƒ0ÃÌ’aÑÕt¶ª¦õ¦¦Ù¿îo©!å‘ ÕrYüÚ¢X–è`U­ ¥rQã,!Ž“Ô}€(è ˆgx*°ëº0M•Jår.\@¥"R÷ÈP](ãÔó„<ªglû¾ˆ| ˘’ë̬4[54ì^ô¢}H’4úïMc_¦•@„Óîv;n”5K×¢GyÈ[&ùÛ«ÀñWÿjHúù(Ÿ¯9Æ«þ÷ÿŒWÿáŽþ{-0®›¼Ç>úè_â¥/}Møüüù€÷½ï“\Ã:)®›à8âæàæ(¯×E‘¤ï ÃuTMÑuñÞûÞ¢‰…Ä4{³›²tŠšö‹¤ÒlÕ¬F7õz}h=!ÃLŠïûáA+u+×a]W,EgRd%I|yj Ój ãsPæW¼Ø]–9?ú1Í^ûKU{ÿ²íçyÃ;þV«Uض Y–ašÍ&ŽŽŽÐl6çËPuѬdAÍÔó¼HÏäˆqa¨íSŸ{¬ÍÖÖVÏk;;;xøá‡¯íîîžÚÉ‚¢ þ]i„MšW¼âÿ Yþ!xÞˆ)Á¦3æ%}¼q_æÉ{³Þo@¤ßŽr3jŽøzâ»xÀû_ø? žÓB ôØ _¾ü£——1¼î•p]ñK/"žH¿Œ/¾àGðÁo{^?æÏ¹ˆFR†÷önâyÏ{søüÕ¯þ">ó™Ç8ò3 ”KGðh¡¡Ü¹xŒ¦ y´,qW%Ù”$qÓHGµ%I¼Ÿ”%מVæ8á]ø±oú&|{Ñ¿ÏBé¿årôçÌRÔ=σ$Iežç…£jHq¡NÁéñ6 sÐìFEQÐh4Ê`–-kÛbI’$±ü,ê4¿¨@·ŸBçûIe1½Ž‘Â_³³FvpøSÇ0„íEc*þ·LJ}³¾ï£T*A×u†I’P=qV4âѬyÅ4Å7ÍáÅæ­Vý÷¼H Aµé÷{žpÄTº2Ô`½xñb¢á±¾¾^È ‹$ Öóè÷'½“þNþð_‡“‘ÿF„¡(c4c°ñûÍ 4‹AA³iœŸèà#~¼/<8xðÚÿÖ+ð–%.†ÿh9‡X½ùµÀ×oÿ°Ô}à¿2ù>lj¼ 4ZU£º‘øÝXQ€;8nLøŒ´ü~ÅW¼¯~õ«Ãç?öc+°íß(ú4šŸ§iâ.™çfFE2ÔÅM–Å5cšâõ¬Œ, mѲĘžÇqœhš¹aªŠg2œŒÌ`(ŠdâÏbYýõMß÷ÃÔ^ûÄIA"^–e¸®ËÑTæT¡6íA&¥Ef-;ô-qKãs¡/MJ,‹µ7¢¹>ÃÖò¬EÁq¦R§ÇŒÝBUUüù*ñ¯iöw¶dU>™¦‰z½ÏóP.—Ãì˜ú"DÉéb­Õ¢ÔõA©èq=:ná÷£`ùj°®®®†]ÿ3lÑGà Àí·_†ãL0ÏYÅtf€êHÖ_ÒqóžW0dßQÊ+(ÝB?ùÁ,+º0èGþý¯þ×ßé}ï¸ÞÆk›À– üï×ßýÍèBó}àÿ|1ðÊïøbÒÃI5'ÃÂëgQ›š”ãv»‰ŸýÙ>ÿË¿ü8Ny¹»Ù9a€ìh=y(G%~cPUqœa©Ø†Ñÿú¡;õ¼¤%-(²ýÄÃpмUI’Â4zÏó×¢(°,k1”fiÈÓˆ|\Y_Íu³k¸–ø…íyÑ—ôýÐÙ7¼öý Éž"¿m©4Z6¶ã8‚š¦…ÍñlÛžÏõ›RH·%‡ ]¬‹ ‘Ü)ÁÄÁÁn܈BS—.]ÂÆÆFÑßc(q{ª§u^Ô¯xŵñèç4:§Ï{”èj^,ˆ”ÛaÇ¥†I¾/¼8šÖ;3È€oÍ~¿alâ¬QUà=@ýÁä!ËÀkåì߃êH˜°2~/ö}ŽÕgÿôO?SÞ_òb¥Ý´ÓŽšMòÛ³²4Fɤñ}¿'ý7þ°™›ú&æLàºîPÇ#5š¤‹÷‹¾. y¢Jy {3S(>’–IEéuªèúð?oa£<êöÛŒÝçUUÏ”4g-®ßRt5^j´dä6X]×ÅC=„N§“x}oo«««°,k®Ó„}øz’Ö?}ßÇ _øÙé À0Y‡ZÙž|µ²y¾ƒ=v}RšR³íøw-ADcõÔûG…nÀä ßèÃeúBÎÂ4Mhšljä^’E™ÓzZX–×tôò?) ­iÜ(ãŒáyÔl©Ã0Ž˜IwýU%s¶ªªªœ±Àœ:Y¾Ò˜æð„§S]³j@'%ž%3Ëûšï/¥0oXVïÏœ.9Ž3èð<•J²,‡ŽF]×gç´§ÍJwåÕjvY®ç“ÁµµÞÓ‚«KðÁÁ ÃÀÅ‹aYVØHÂó'/5$ bgz\Mâý!Ç뺨Õj៕²Q‡)ê MµHe£NŽí¶øw™v&r긮výí¿¯Ÿ¸NÈ`ͺv¸~•9M(¸RéßÈ–:ÆÏhÒ°cÒ'(‚4*¦)ò@Ëeñ¨TÄz?²—óœéÆ9®ÂŒ„a™¥¾Y€ø3:ØÀqT*4 4›M´Ûm4Ù9ƒ@œ(‘gŽ/½dײÄ1t=Û“$Ë܉ê‹'—ÁzíÚ5¨ªŠÝÝÝžèKüõk×®ý}ú’G =/YÃJ^Eãoì!‰Dƒ3/ú€×‡Í>%¢I³cé=ñ9MkkâßQ#¤2„Ñ DFë¤Ðº2ínÌKŽïû0M3ìvGú5e ,åk #Ib¡§±qò¸3K¦ª@’$xC”e×užxUU{¢® S®ëâ‹_|` £}XÑSǶ“á^MÆj5RÌl;z-ýÅ‚@¬ñ€Xß›Íäc_Öu“sQ–ÕÑ;GPóTê1H¬GYvÇeYh6› ãL×nJ×$N:={'m€Ñ‚RIè1YºK*•èX <xhJðÁÁ:Þö¶· ÜïÊ•+¸|ù2ç258nšIÖZÂÕpÀ@õS1ܨF?ƒÕ€H¹õÐ?Š*!߸â'ÿ+ð;¯~äq¡QkúqFÙJÔ! Ö€i5qpÀÑÕ!ÄËk*• êõzbq^Ú±«ÔÅ—:餻E3Ì A@³º½“TygÈþA‚£( ¬Láˆì€z84 EVçf $E:®hQQ"Y&ž—l0’>ùÿ?{æH~Ö÷Â_¯×6¶±ìZ;ë—ž5¦ÚàU<à­Îˆ;S2OLvqJ!0dç§Ó¿OÔi¬;r¤ªƒ{O†£VY€"©AªU¡ÂÎbw–J%T«Õõ:‹Ea å›,ž'B«^® …0ãý¦¦çr9ܺu+éu.̤ý„F'WPtun¢RÔçm6darTS…0"Ç=Ç 3MqE¥ B¸ÿï[vÄ…´¨Ã'Û×Lê¡>4)EÓÄŸt\#L:ÞÈCµø85̙ŶmüèÖýÒ"Q%jSEªcµ, º®£T*Áó<ÿž„Õ5iÏÚjñ<µZ ò'ß5èO*¥è©ÁqFÓ³Hªò«7ZmÔÉBãFã¿F ’$Å÷´4h8lÔ{’b¶ãY’D„7UžªÙ™aÍçóèõzèv»£¬Ôp)—Ë%ý™"÷w²m†aàääž7Çqó„Ƕx©°ó4ç 69ŠþÀýÏÞý@ýâèð¾ßr×ùã:¦Í¤4ââíÿ¯7ÎzK5–%ŒÐðØÎ(ƒ•ì¼Ì:ˆéN–Ik›I’ßú­á?þÇŠûo÷Šœzž‡âmKÖu]ضÓÓSȲŒ6N“À²„q3Kà¢X,B×u¨êóÉPÒpIˆe¥È6¤’f3»ŽEYæúÕCøYÕqÏó`š&\×…ëºðËuß4¦dŒ4BsWg½ì©±’ªªÐ4mù£ú þLÀ(ƒÔ¶Ås2:>&­ÄšÃzéÒ%ìííáÂ… ¸xñ" …¶¶¶ÐívÑn·qtt„[·náÒ¥KIžH,Kì)QJ¼ëºÐ4 ¦i¢P|ãÌ1›™y³FŒ6] z'‡Öù/ED6ˆ @þàmß2û{;üñç¾2‰@6\”0®‹©ãˆ½5G÷"ÞéZ-ã7“$ŸùÌ‹ñö·¿¶mC×õ‘ëƒêX-ËÂI@cb£uMÐfFYAá†$ ‘%æyt½ryØþºVnW‘=ØÕI ø}î&8eЊY:Ô\w–˾\.Ãu]4›ÍåתÒxUlŒª*póf2_ÚË`Íçó8<3¦9,ÇTB…V¥ÒÀh•åa%È4‡»¤1‰„ŒÏƒiš¨T*þ5ày^÷ºçà[¿õëñö·‹®4aƒUÓ4”J%ލ®j[>­ÏŠɊlS§ëqbJs+WÞl)2ãkÑåL;MÓ.ã³®ÉXm¬B™¡4÷p¹³Vb¬¸ ç„÷z=t: …©¯ÑétP©TÐívý׬ÕjþEÓívQ©Tü‹IUUÔjËœ…"°mÛWPt]G¹\†,˰m'êÉrëM ƒzP ¢“èšÐZMÜiJ6€—İÁ2owbf.’’oÊ ‹Ò¢Æp‰«4V)¸¦aÀ’¢ªëƒZ‘ph@’¸3c‚¤eŸ… ÓÆq<ûÙï "©ÔË ÜA’-eÃÃ2S)]×ê<Æe­&6®àµœ˜M5Ùvg¢’®ª"‹qåÛe8S†I-YqÈ/³¦iÂó<4W)ƒl¬&ÎÔ±6qét:ØÛÛ‹õܽ½= 8Žƒ«W¯¢P(  `kkË?ÞétP¯×ç^[±=½…æRð•Ã0Äæï`þh¢‚ÉMCˆ1åÐqÏÑ%jJð3/™oe š$1kcÝòdœÞ2­&»\Æz‰epó¦¸)ßj5zNÏWM”$e|VlÛ†$ICsµÇÁéé}à°‰ºF6ÂX„¢5¯Â•òX* ¿ÞÎÎ`LÚ´Iφ.ÝãRÓ¶V%ÙD„5PÑ4%¢p™%CdAÆgÉ0MÕy<2q‡ÐK«)`ik\Úí6z½ö÷÷ˆ18/^ôS©‘ÓÅ‹ýã»»» ç¤Gé¶á¨“®ëÐu](--ˆÑ4óD'%Ä7ˆzS‚Šºå¶ÇRš?BZÅäù­ÌÒIJ¾É{jÐ9¦\^óxCÏtØc2G’2>/𦠬ûسð·ÿöçˆèÁÂcÌÒD”wVU3Nâ`YbcØÙ‰ÞšMñC³³šMa€Ž{>uvÛÞÏ£ÙÉ)i’5Ùv/|áÅ©ºôééœ_spˆ+Q« eí^NfdEÆãÚŸÔÙ}æýÛq„—JÃJÍŽ’}&QfN ^ª… ŽÇ¹qãqaÐÿƒ9õù|ÞO]˜‡qʸã8C^¥‘Â.„Ñ:«^mãvgޘϗ ŒR@©8\£êÜ~½yÒyh–*§¯$ä›°mˆ ïÛÔ”cãš8® jýÇd’$e|ÈYãn§§-4ß `a]ë@ùE F2©ÆÛq Ë¢j uc;ó¡‘$š?5WQD*Ôü8* ¤ç¤È@ “EÙþ‹¿xÛj¶SˤlSó+Ú»Sæh`â“Ð\hï¦}Ò4…áêyƒý”#ª©cíÖ\.7TçÚívQ¯×±»»ëÊG¯×›ë=Çí«“¢N00˜›:+6FGËLÃðúO;¥P#,–Ò;K´—Y˜$ä›0ÍèàÊ´èÑZõ×MÙôzfV’”ñyp]Š¢@–eßhýèGÿ’4<Â&€k5¡8mo‹Ã½¨) ‡ŒÛ¶02©€ýä$Ú¥i⹓Ò)(jÖlÎîT’¤èyZdøÎ[çºF²&Û¿õ[ƒçɫѭ5MÈÒÉÉ`Þh«5Z¶ÁdŠ,ȸëÆO™Û`U”Á>I½3NOÅÞW­f{>ð†²vƒ•èõz¨×ëxàP(ü®“.ˆ[·n=ögögøà?YGµ·N³J —æ1Xg‰®úïg_ÿ>à¾{øqËëðËŽqùòå¡Áe³lù€'žx{{{8>>Ž<®ªã.M’õµviwž§¸öööpýúõ•¾Ç:÷ðE‘$Éo®Ÿÿü;‡2¾¨$Q( ­RŠÍ~ מJÒ@©¢2$¦ÕvëúøS2V30³^¯ãòåËxüñÇWòúIìßóð;¿ó:üƒðéÅ_(Ø@+ 5Àc%~mÐþMMVAš÷︫çycçË3é…tðY÷ï©)Áq‹­gñ¼t: —ËáÊ•+#©ã˜ÔZûÕ¯~5Þò–·øyùÄ8gòD!ÎQU!Ò‚gqàÌ£÷hÚà=‚#i˜¥CžÄk×®­äõW!ßpÏ=÷àððpìñ(}Ûqض=±‹¤$­Ñ~ÌRÚe†9<<\‰áG¬s_Çq išo°Ê²Œg?û«†¢RjÒé_®+ Ó`Êì¤NØó*hº.êLUu8åRy3’ù°¿¿óçϯdOjÿž‡}l?üà Œñë:Ç0 “”|;ΰ²nÛ6lÛÆÉÉÉü/º,l;VÄ̪HË™o6SS¢&/›)ɲŒ«W{økmí ò™ &ÙöŸÇÃ?ì_XóÆ„aŒ–ëLM† Öeʷ늚6Ý«ÞÀâéÅÌZY·| z(MÓLG*0Ý‘œÁÉ,—$eÊÆ*3Át`×uaY,ËB³Ù¼Ýå:¢žÏ0„s„r&Øö¨ÍIjKP}1Mªª Y·m¡ÔϺ«ªÐÇ£Ú0™bªÁºµµ5µvZ 6¢b¦{·&e¨·J3Z–üܽÀ£¯þîÿ|÷}âÊ£IbÅ…YÅ¢ð‡Ø¶½üq6ž'êDh8š¦qÓ&1ø™][[¿Eùùõ-ζ­/f\w ´›¦‰J¥EQP*•P­VáºnôÏÍí˜ V‡)K,˜oYªt€ŒÎY©TD”•Ë•2ÏF×°FEX'FŸ\øµOŽoº¤ à&5 xÛ·ˆÇ_ÿbqqpÓf ÐoÛö샴ãP. Cõ䄽”LâÄ "é:ðÉO~h=‹ªÕD]U¸µ+ÃÌH°>›2fEA¥RA©Tm>p#/&3D5 Bj³s[÷ûq4óé’$®qʘÌÚ9¬Ë€B„ëºSº›Ày9ð7hò ›æôÔM‹ž~Ì0KF–…(†=_³%jËu. þcï=“J¥ÙÊô¦–,Šë K’„C‡fANOÅ¿–e •0éºUU!sôžÉ0áqdUQ É4ÍáÓ"rÏî6‚Øk§ÓÁÑÑ.^¼ˆ|>?V1vÂaÍîfíNßèm8ý‡Àßþ4€—E?Ç4ÅOœzTVò™5âyÞ|ÊL­6è0)Ëbs§ÚT4Ï0)`V'ùJ VÃÕy=ÿ 3Ó4é·ñ÷wRnØxe2H”Ø*ŠP­Eè2ÿâç~÷°îÁˆ•lÛ6.\¸€N§ƒ\.ç?¾¿¿K—.¡P( —ËáêÕ«Iž!*•1uÈ6ñu_|ì·¢9ŽPî[-ö¤3©Á0„½éºîô”ਙe–%dúô”•o&ÕÌR†dÛöj V×5Q€ˆªòõÂ,‰ZM¨®ëÂó¼ñ: =‘a2†1fl$%rIð›ï{¾¸µ•ôR™”Ë`=88€ªªxä‘G°¢|>ÝÝ]âüùóx衇’þ=PÎ-+ÚûN½äƒ†eñh&˜æô¶¶mûe)î¢=Gd$˜¡.|<{˜YäŸ8žÌ²Xþ˜L"Ë“³dlxê©§ y^qáBÒËeRÆTƒµÓé`kkk(² ÀO&èø7’þL„® 2õ®^9RüŸÿÛ°+ßuÅ‹qM*“R>ó™ÿ6H#ï»a ®¶-ŒS*!xv“,kz@Ó4M”J%8Ž¿ Ä4uÜŽ#Üü†!2jt:ÌÚå£elF˜ã°ÁÊdIš¬†W«ÀK^RÅw<ïy¬—0#L5Xs¹nݺ5òøáá!òù|ÒëKØ“óìÏæŸXÁèU*q*0“Z¨æ €P¶GlöbÖÍð“)‘ž8ÍÃ&¸îô-Øq4›M”J¥é]በ£§VÔys}*³FhøÀÔñd–ÅéÀL&W¿äƒï¿Ø·YßfBL5Xóù ˲ð¯}-žýíßžôr™Ë`Íçó¨×ëèõz‘Ïéõz¨×ë( ©‰ºŠ®©âÿŽãàÕù—GÓ†›ÏXÖ`^B9âÅØÓä” ŒË²<ì}ùeI/‘a&ŽžnÛƒ9ÄŠ¢àæÍ›Ñ)Á4w˜aRž˜ÊÎõ«LF‰³‡×j5¼å¥/e§ I¬9¬—.]ÂÞÞ.\¸€ÝÝÝ!£ôÚµk8>>öŸ—LsPrêyòù—ÃA«‹âÿ¶-<ê¾N˜ !ËB”wv<ÈÀ ÍAQWN!c2L\ƒµ1nn_©$^@UÃþ¸6•I–eM®»¶m.ã`2 uÀG­Vƒ¢(xª²ÁÊDË`Íçó¸rå ŽŽŽP¯×GŽïîîââÅ‹#™’Äó‚¥I6¾þyÏ~‚$ ŒVŠ *`ƒ•É.Q£TUhûl°2fš;Ž39*EÔjâ_6V™aÛB_qG”vPÁv8»‹gÀ3ÅuÇìᮋgy¦iâää„å›K,ƒ]€/]º„ýý}t:ÿñ|>ŸšºÕ ÁŒ¯W|ä#øâ×|Íè“Èh¥t`_+L†0 @Ón§GÝTU\ˆ(ª I• ¢©µÛÿç±{LÆõ«¬ ³¨ê°ÍY«Õ† Ô*ÏLe2ŒãÐ)\³Ê0€i’®âà[ññ’}ˆUfff®aÍAƒD!· ‰a*Ðo?ÆL&ƒPgI×u3…fÃP”aÝÆ²n7¦a˜ À¶|¤+º\³±Êl µšp:†ÿñk¿ÆrÎÌÅF¬>.ð7~áëðà¿8ˆ¨2Ìáy¾û%/áÆÌFâ8B¡'LÓ„¦iÓ»Iº._L&Ð4à®»>0yþ*Ãd˜FC8Ö=Ïãl0fn6Û`5ßö¿ÁËŸûܤWÂ0K…¢«–eá­Ï}.{,™Ä4SÇ‘¬Ç™¡jYl°2™@–Çû+òÌÆ¢ªBWÑx<³m°þÅü |öÙǸ«XLz) ³ThnŸmÛxý_ýí`6ÛŒ6MªªÆk0fY|M0™À4¯ºz•#¬ÌFbÛ"á… VfQ6²éÀþèUÂ߸ñyV\˜Ãu¿õ·>‹÷ÿÌCîŽ;¸³qmNÏóP«Õprr2ýDš½ÊדrLhµ/})é¥0ÌJ¨Õ€yÕe\xæžfÀ,ÄæFXMàÏÿaôÿõ¿Nz% ³txÖSÀ¯~á b ÃlÁè*užZ» K—=ùL¨Õ€ïyêŸã¿õ[“^ Ã,ê?ðuüKHqJ9f©7X;ºÝîl'9À_>¯ éKŒW~ÿ÷'ýf,sÉ7€Æ?éàëßõ.ô¾ç{¾0)f÷<¡ì¨ªhÖ1Sg`6X™52ïnšB¾ßð‘GðòüÁ¤?ÃD2¯|Â!S)þ>>øW…|0éÂdœÔ¦w»]T*t:€ªª¨ÕjñNV€Ï<ùÿÁÇJ%œOúƒ0L É7å#áï?ç9øùŸú©¤? ÃD²ˆŒmNÃ0P©TâEW9˜Y‹îáµÐ*þ$~å9ÏA™#¬LÊXT¾MSlÃçéøé¯ÿz|Oœý›a&ÚëÁÁ¶¶¶à8®^½ŠN§ƒz½ïdÇÁ“·þüþÏ“þ ÉBò ÀR<ÿþû“þ 3–Ed\ÓD¦;)H~g`šsœuC¸.`]eÖÂ"òmš€úõŸÆ ~í2®çw&ýQf„Eu”Z ¨¼¤÷zxù÷}_Ò‡ÙRi°v»]´Ûm\¼xËå°»»‹V«ë|O–±ÿÜçr7“J•o@tæ1LZYTÆ% p]¦i¢ÑhCµXé8ƒU’Dz<§È3+fQùv~ï‹Øÿ/ßwårøß9K†I‹Ê·mÚÿ^öïÿþñ—}wf–B* Ö7nòù¼ÿX>ŸGïº.þÖ?úGIŒØ´Ûí¹k’æøø8é%dŽEå2ž¥›@Vå„nÜÌl,*ãOÿ÷ÿŽUÅ‡ÞøFHå2P.‹k«T«â'Œ$‰¢ÀRÏx?[,*ß·¾¿ñW‚õk¿/Õ=a²*#¼ÏÇ¢ò­*~øÿþ’„_úíßN½Œóþ Ri°Nœ^¯7õ|EQâ7èH×®]ó7ˆ¬aGE:˜‰,*ßfŠÆ¦¬ÊÉ7píÚµ¤—‘9•ñ=õÎ]¼ˆW\¸ "¦''©OÆ{øÙbQùþ7½¾íƒÌLXVe„÷ïùXT¾;¿þëø…¿üK´Û©7VÞ¿³B*›.Mº nݺ…\.7òøþáâýï?~ù—÷Þ{oÒa&ž|òIœœœà¡‡Jz)3óÄO`oo/éeÌÄ“O>‰O}êSxñ‹_Œýýýµ¿ÿ<ò ˆ¨ê›ßüfÜu×]¸ûî»×¾îEÈ¢œÀç>÷9|îsŸóOd…ëׯã _øBb↓=ü×É{œr/2ïáë_s¯×Ãk^óšDÞùÚ¿¿ê«ð³?û³øÙŸýÙDÖ?+Y” ûû÷oüÆoà­o}ëÚß)û÷àÒ¥Kk_û<ðþ½^HŸuÿN¥ÁLC³µµùøÛßþv¼ýíoOzé 3•yäþóþÏI/abÁ{8³ÉÌ#ß¼3Y÷o&¤2%øÜ¹s†ÓºÝîDeža²Ë7³é°Œ3› Ë7³É°|3i$•ëÖÖ …ÂP1±mÛ(‹I/a†å›ÙtXÆ™M†å›ÙdX¾™4ò¬~¿ßOzQt:ìííakk ½^¹\‡‡‡cëû&K°|3›Ë8³É°|3› Ë7“6Rk°¢ð›Šå …BÒËa˜¥ÂòÍl:,ãÌ&ÃòÍl2,ßLšHµÁÊ0 Ã0 Ã0 Ü]RYÃÊ0 Ã0 Ã0 Ã0l°.‘N§3qÞW§Ó™8yÒñiç.ó3,sÝë\;³ZV)ßqŽ/ë3,{m,ß›Ã"2¾©ò½®µ3«…÷o–ïM‡÷ïäÖ¾úÌÂ<öØcýûï¿¿ß}÷õï»ï¾þý÷ßßì±Çüã7nÜèß÷}ŸüÝï~÷Ðù“ŽO;w™\¾|¹ÿŽw¼c)ë^÷Ú™Õ±JùŽs|Y„å{ѵ±|o‹Èø¦Ê÷:×άÞ¿“_;³Zxÿ>òÍÖ%°··‡B¡ÇqpõêU T*ÿøÁÁ¶¶¶üãNõz=Öñiç.‹v»£££¡ÇY÷:×ά–UÊwœãË J¾]Ë÷æ°ˆŒoª|¯kíÌjáý›å{ÓáýûŒÈwÒsÖyôÑGû÷Ýw_ÿé§Ÿö»qãFÿ¾ûîë?öØcCÿ'~îç~®ÿý÷<7||Ú¹Ëâé§Ÿî¿éMoê¿ûÝïö=<‹¬;Îq&¬R¾ã_Qò½èÚX¾7‡Ed|Så{]kgV ïß,ß›ïßgG¾9º ù|~d6Õ7¹\Îÿ>Ÿ:‡òÉ'Ÿvî²888Àîî.Î;7òæYwœãL6X¥|Ç9¾ ¢ä{ѵ±|o‹Èø¦Ê÷ºÖάÞ¿Y¾7Þ¿ÏŽ|³Áº ¹\nh>U·ÛE½^Çîî.¶¶¶& G¯×›xüôôtâ¹ËàøøÝnûûûC/²î8Ç™l°Jù^‡œŒ“oú,ó®m×&³‘ñirUùæ=|3àý;¹µ3ë÷ïdÖžl°.‰^¯‡z½Žx…B—.]òÇ­[·&ÿô§?=ñÜEév»8::ò×þ<ó®;Îq&[¬B¾W-'“ä{ѵ¯úÚdÖÏ<2>M²*ß¼‡o¼¯wíÌúáý{}kO 6X—@§ÓÁÞÞ:®\¹2ä- †ãÃlmmM<ôE»(ÇÇÇÈår°mõzN7nÜ@½^ÇÝwß=÷ºãg²Ãªä{Õr2I¾»Ýnª¯Mf½Ì+ãÓä «òÍ{øæÀû÷ú×άÞ¿×»ö¤`ƒu T*?>,$”— Ïw»]_`&Ÿv?~ìûò—¿|îuÇ9Îd‡UÉwœã‹0I¾]Ë÷f1¯Œoª|¯zíÌúàý›å{Óáý{½kO 6XĶmt»]¨ªŠv»=ôOF¡PÀñññÐ9Åbqêñiç.J¡PÀþþ¾ÿ“ÏçqîÜ9ìïïCQ”¹×ç8“ V)ßqŽ/Â$ùÞÚÚJõµÉ¬Ed|Så{ÕkgÖïß,ß›ïßgG¾ŸÕï÷ûI/"ËÔëõÈùIà8€AºÂÖÖz½r¹ÜPW³Iǧ»ìÏÒétpxx¸ðºãgÒϪå;Îñe~– |/º6–ïÍ`QßTù^çÚ™ÕÀûw:ÖάÞ¿“_ûº`ƒuMôz=t:Ñyó“ŽO;7­ëNzíÌúȲœdõÚdÖË"rUùNzíÌzȲŒdyíÌúàý;ûòÍ+Ã0 Ã0 Ã0 “J¸†•a†a†a†I%l°2 Ã0 Ã0 Ã0©„ V†a†a†a&•°ÁÊ0 Ã0 Ã0 ä6X†a†a†a˜TÂ+Ã0 Ã0 Ã0 “JØ`e†a†a†aR ¬ Ã0 Ã0 Ã0L*aƒ•a†a†a†I%l°2 Ã0 Ã0 Ã0©„ V†a†a†a&•°ÁÊ0 Ã0 Ã0 ä6X†a†a†a˜TÂ+Ã0 Ã0 Ã0 “JØ`e†a†a†aR ¬ Ã$†mÛðÕO•Ëeœžž&ýQ†aβ,£Õjù¥|žçA×u4¤—–YØ`MaÃÔ¶m¿èz’Ѫ( $IòÚ„=ð “4ãä;Ø8, –o&ë$!ûFžçÁ²,¿Ã,ƒyå™a²È"òN:|£Ñ@£ÑðÇŽ)ŠÂ×ËœpÓ¥„ÑuŽãøi_žçù8(ý7x,Øt#Ø…Œ Âo†I“ä{,ßL–IRö%Iò;VòèfÄ‘ç8²Í0Y`QyFVqå”ßÅàkÂȲŒF£b±UU}¯ µ¿#E(%†aøŠëºSóìf]L’ïi°|3Y&iÙ×4 š¦¡\.ó5Ã,Ì4y–$ †aø© “e•w]×aY¶··¡(ŠŸ£iZÒ-³<«ßï÷“^#”ò„S¥€É²ìÏa¥MÍfÓ?7Ød‰RÉ&MDÉw\X¾™,òÏlãä9¨¯„g 3LVYTÞ)B+I—2-¬)Æu]looãä䊢Àu]‹ET*ö`2 Ã0 Ã0 ³ñpJpŠ ¦$xžç§#°±Ê0 Ã0 Ã0ÌY€#¬ Ã0 Ã0 Ã0L*á.Á Ã0 Ã0 Ã0L*Ù˜”`˲ðó?ÿó¸çž{’^ÊÌ<ñÄÈårxñ‹_œôRfæúõë¸÷Þ{“^ÆÌ<ýôÓxÎsžƒ£££¤—›ûï¿?“ò d[Nz½^&¿÷ëׯã·û·“^FlxO†,_›’$áßþÛ›ôRbÁû÷úÉúþýÞ÷¾ù|>é¥Ä‚÷ïdÈòµ9ëþ½1ë«_ýj¼å-oÁþþ~ÒK™™z½ŽóçÏ£P($½”™ÙÛÛÃááaÒ˘™v»k×®%½Œ™¸çž{2ù]Ù—“,î+{{{I/a&xO†¬_›Y÷ïõ“õý;+Æ*ÀûwRdýÚœ…1X³L/p"‹ ³~²*'…B!“71f½ðÎl2Y•Þ¿™8ðþ ¸†•a†a†a†I%l°2 Ã0 Ã0 Ã0©„ V†a†a†a&•°ÁÊ0 Ã0 Ã0 ä6X†a†a†a˜TÂ+Ã0 Ã0 Ã0 “JØ`e†a†a†aR ¬ Ã0 Ã0 Ã0L*aƒ•a†a†a†I%l°2 Ã0 Ã0 Ã0©„ V†a†a†a&•°ÁÊ0 Ã0 Ã0 ä6X†a†a†a˜TÂ+Ã0 Ã0 Ã0 “JîLz ³ <¨ÕËNOÅc†!þÕu@–Å1Ó=ýô½xÓ›þ4ée3 Ã0 Ã0 3ް2™Á0€bqð{¹ Ø6à8ƒÇÉXMT$ñ»¢Í&ÐjõúuÜsÏ“I$†a†a†a&ÀV&3( P© ~×4Uu] ÑÆiøùAd9éOÀ0 Ã0 Ã0Ì,°ÁÊLÄu†^­&"š², Çu€š6ü»ªŽ© Ã0 Ã0 Ãl#)Áõz.\€¢(¨×ë8>>F½^OzÌpQÇIPŠm±8¨í R*‰´[׿kšH§UqN¹,^ƒjEé5··EMiϯaã—Ö´½=üûÎŽxoz_È^Ã0 Ã0 Ã0›ÍP„• ÔÝÝ]ôz=@.—C½^G§ÓÁááaÒëexžø G:©‘m‹ßONÄ¿Ž#Œ@Eçèú ¾“êA)å–ê=ƒÐûèºøqœQôZ?´ÛüÈòà½)]WQÄúÈ8UaÛ¶0ZE¼}†a†a†aξÁÚívqtt„ÃÃC t:€ªªØÚÚÂ… ÐétÏç“^3ƒAÇ[ê€ëºÂ@´,ñS©à R@<7HÐÐm6…‘[,Žªã׈†ñ:Î ý–Òs©®ÓuÇNN†£§q©T€›7—W*Ë"Ú®=‹$‰5M3Œ“bœ|,ãLöaùf6–ofÓaœÙ$ük.—ôz=ÿÿD¯×ó#®qév»ØÛÛƒã8CU*•¡èmŠc?KXÖÀà¤T^`|¤’­—(ù¦ÇYÆ™¬ÃòÍl2,ß̦Ã:8³iøVŠ¢îíí §ÝnØÚÚŠŒ¾†év»°m•àü‘ÛÐë8Žƒ«W¯¢Óé 5tšv|“ð<¥½Ä¶Eó¡ aJõ ­–˜/zzÊFiÒL’o€eœÉ6,ßLÚq]q¿¼ukö!,ß̦Ã:8³© u ><B¡€B¡°´®À“„¾×ëM=>?û³?Ã?øÁ‘›PZ ™§º.ºðr$59Žqùòå‘ú¥EYµŒ?ñÄØÛÛ!`V i ŠM­&RùG(Ö§§Â fcU«Ã®×1¢iooׯ__êkžõ=œY-¦)F™•Jâ÷jupŸ´,q¥1jõz—/_Æã?¾´÷çý›I ´ÏÚ;f¼3itðY÷o?šÏç‘Ëå`Û6vww—¾ÀIëÖ­©Çà¼úÕ¯Æ[Þòìïï/}íË@–…¢:kç^fùìîîbkk ×®][êë®ZÆï¹çž…¼D\W(ÇáñO4Ê4Åï4w˜ Öàa`¾ëZ–£Upxx¸tÅá¬ïáÌ|XÖ ó€7ÔÑžfv—Jâx¸+<ý_–‡¯Óýý}œ?~©{8ïßLZ ý{™c$yÿfÒ¼:øP—àýý}Ôëõ±ž–EqÒ…·µµ5õxÖpq£V1Ö…g‰¦‹n·‹gžyf©¯yÖd<«8Ž0+q]Ú¶¸F]WDLé÷p&i 2¦wËTdy0£x¶m£0MŽã Z­Bº­Ñ¿ç=áÊ•`™ú1Ë73 ¦)®'JáT3mö÷:F›±|3› Ë7³jõ©W/u ,ßguŒÐõ¼\u­iìïß‹~ôž™ÞkdÙññ1lÛF»Ý ¨ªº”ºÖýý}ìíí¡Ýn£×ë!—ËáÁŒ}<-PØûäD¬4¢†jݘåâ8Žoxº®‹Û_¸®ëþ¬1ŠJ™¦ Ã0àÝö´Z-?B¥þ8$ßËfSdPM–gKÓ¥ýÞq„-3MÆ©^°AÞ¤ò Ó”‡Ôë×qíÚŸÌöÁú._¾Ü¿ï¾ûú?þã?Þ¿|ùrÿòåËýÿñ÷[O?ýtÿÑGí?úè£sÇ£>Ú¿|ùòRÖ8 Uí÷ON¿7›â‡™ÎÍ›7û•J¥ßjµ&>§Õjõ›Íf¿R©ôeY𜞞öoÞ¼9öø*åeU2þŽw¼c%ëM•Šø!NNúý°¨hZ¿_­ŽžK²5éïÅÉÉI_×õ~µZퟞžÆ>¯Ñhô%Iê7¡5hšÖW¥¯ªj_UÕ¾®ëýF£ÑoµZýjµÚW¥/Ër_Q”~£Ñ˜i½''Ñ{ÍÉI¿^úªäeöðMæô´ßo4Äu¢(ý¾,_SaNNÄsšÍ ‘HÆÍJ¥ß×õÁ{¯‹UÉ ïß›MPFçÑÛèº lû‘4›Ñ×,G_'Õêð½Ž÷o¦ß²¢(ñe•ös’ÏÓÓxû8KÏ—åñçœ;HÓ¢e™îAH·£×œG^|ƒõÆýûî»/ÒxôÑGû÷Ýw_ÿÆ‹}ó+d]Ë͛ь,pzz:“BN4›Í‰fÜ÷»yóf_Q”~¥Rñ•ùfà*$ƒC–å~¥RéW*•~³ÙœÙ‰C7×MWxZ-±1ÿÜ´1Òæ«ëâ'Ê!¡ëz_Ó´‰ŽÓÓSÿXPÞšÍf¿Z­öUUí+Š2u­dxžžžö5MëkšÖo6›}Y–‡ ØI4£Æø´çËò°³lY“—,^“i€¶XºVTU(¿³øøNNÄu<HŽUu6™^„¬ÉKÖ®Ç,¡iñ”rRæƒçÍ"¯äœ¡k-Š›7ÅëŽSæQ²ÑVæûýìÉK֮Ǭ0ÎI=î¹a¡R™î\‰ºW„ƒý¾g]zÚ¤ë&Ôw]Î#/~J0 ŽêDIóXoܸqæ °%i=MY–çy(•Jð<ªª¢R©ø©²AÇçy°mÛÿWUU¸® Ó4Q­V#Ï#\×…mÛ0i&I’ ª*,Ë‚®ë~j®mÛ°,Ëïr*I4M‹•É$ Õ-PúG±8{7lÛçKÒ %˜Zˆã­ÖàwMÅÃÎŽ¨«i6›Půmn6›C)亮û²dlÛ’-EQpÈ_¤QÃ0P½ãyŠÅ"<Ïóe_’$´Z-H’„f³‰Z­˲üõÌòŒKU¦:AEßëòh,fÓ?''£×Ê,PZï¼ Ër:*1›G°É%¥ÚNºÿ8Î ý˜µ„+ØH“îAuÈqDÃ1MßA^×E™ç‰Ÿà¸'†!,K쥊"~\WÜûÇÝÿƒòTA4mrÏ:/\ÆQ©½.ˆiÆ»WhÚ๖5ÿ}i„ µ{ß}÷õŸ~úé«öé§Ÿî¿éMoš9E`¬Ã»sóæl^ë¤8==Š^Rd“"?Fcèw‚¯T*ýjµ:Um4~ô3ÝjµZ}]×û²,÷UUíW*•¡ÈêÉÉI¿R©ÌœÖ»J²è LÊãJcо(Šø §îNJ; S©ˆ×ŠðË EßONNüˆ¦¢(C2ŒžRÔu–taEQüè~ðZ¡tõe}¯áÏßj ¾ÇVKx3%i¶ï–`}öG_¦yÖ›Íøé^›FÖä%k×㺈*g˜¥,Òõqz:>â|þ<*ÈÍ›Ó#Tý¾Ø¯e9^Ä–î“’y²&/Y»×ÉɉС*•x2HÙ.Á½¢ð“ÞcùnµÆŸ·H‰‡,Oï÷L î÷ûýûï¿¿ÿŽw¼c(õ÷Æýw¿ûÝý7½éMó¯| ¬ãb *“i%¨`kšæ§8†ÓqFì4…>œ¶•Ú›²¸¹&u£Ô¸vÚéé uŠŒ\UUH–&¥~ëºÞ—$©_½£HF*qrrÒ×4m¢3džTøÓÓÓ¡:Óu@Jײü:¬ðdp]CͦxœîAi¿­ƒ¬ÉKÖ®ÇY99™ÝyÒh  Š2[*zø½%Z9×ôE½Î¤->îº%þÞ}ó¦xͨïëôô´_­VûÛÛÛ³}™ “µëqVæqª„úÔ[`Ò9á`@`:;ÇitŽÓº&­#]?³^ÛÍæäëa¡”`þ…x`( »µµ…ÃeN Ï(¶½þ6ýŽãŒM1¤TEY–ýT]Ã0 ªªŸIÝIõPÎ ¥4‹El¥8NB’$T«UT*?Ex–H&{T*³¥¡Òu2)=в,Ôj5¨ª EQà8 Ãêülš&\×Åéé)Êå²?²¨ÈGQÍ`ŽWò­èâÛ€çyÐVØv—:ì‰÷\bê “)¨“c8°ÑÝ$Ë<2I¶-ö²Yö/פ J’ø½\i„ãx®®Þ“4M¼^ð¢n©ãº`âuLsЙÞóÄïô''ã?ƒa RzÇ=Êè>äº.,˺Ý=~XÇó<Ï/¡ú†oø†uþ ™ Ш=EN)ŸD¹®×~<Ïj–Åb‘3q253šE¡§?m0cd¤ôG©Q"Bs·§E…dyМƶÅÞJ ™¦Q©ˆ{ß,‘'ZoðÚuÇž’nµ.+ÓœÍ Oe2&§9e¨YÒ¸ç›nŸÇÔ4q‘á9Ëçh6'7mÊw9>>Æ<€z½î?öÐCáÀññqÒkÝh¨».¥çš¦é+ì•JÍfÓ÷ЩªŠV«5¤Ðó¸».³(”ÊÛjÍæ‰ ãº.Êå2vvvàº.Z­ÆÔxµZE¿ß?7zU]žc€I†¨ˆÐ8\ØÞ(ì­póæj"¨áníIAÝà‡¿±7,B·ÛÅ3Ï<“ôÇÛ8dyrWÑ µÚ 2 e=Î9“"˜”’Kÿ/…’g$cÓ4g»¦$I¼þ¼×¡išØÞÞ†išeÍf­VëLÜò†,Ïf´Qt5ι¶-ž? ’eÇ2NéÂq¨Vç‹zÎú¹Óˆaíõz¨×ë¸xñ¢]€ÃÃCáàà…BáÌFZguéÀ”Þ«iÇ ÒzƒÆ'Õ©2Ì*¹À_Ïóü1/Õju(E†Zij^“T"dyzÊ䤚P@\St}‘±:Kö‰,OÙ¿Ï¿–\×õ3Ýh  ¢(hµZ‰g30ÓÑõA=ê´?9`‚÷ç „özŠdNBUÇ¡™ÆYî_à¬N½^oÈX%.^¼ˆãããœÃœ…5 *ô_6d¬Î:¿‘aVAœûmT#0šÙK?‚ ]Âó€ýýÏámo{/J¥?âNY8dÀFu…CÏ –œB¯r]w¨…5”Ö«ªªOE8›0”Í,¥ùÀah´LðwVç×ÃP—`šÃZ«ÕP(P(péÒ%<üðÃ]¥ùaÓˆ[è\*•°³³3RˬUec•IŠbq¼ƒ&¼ñ†1$ÇäÐ"4Mcc•ÙHl{ ˜W«Ó³kTu èÂÛždº—ëº~dÓ \ð”ö®m¥ŒŸ8]…MÓ„ëºCÏ%#T–eÿµƒ‘Vñ©þŒe"ª!Ӥπ39– Í¥ Ê+¥MF¡ªÂãyvvv°½½íG.AÍŸišxÍk~_ñ¿‰oû¶¯D¥RÁéééÐß_–e4 躎ȚkÛ¶Q,Q.—¡( NOOý¹ñ45!*ê®( †ŸýS­VÙX=Ãи™ixÞ A^”Ld}TL–¸³Ó錣”Vqˆ«oÇi@³·†¿¹ÒÀhÇq¸V•IM?=œöNóäH¥f“¡¾³ê¶IFTG?ƒã§ÜÖ„”RÕ©Ùlú3S ˲†Ò.é±f³éײÓûÑs(jêºî¡iÚˆÁJk´,k(âEœç0³cšÑzи2(RÎËeïE¦()Ý\×E>¿¯ýÚïÇý¯ÏŸºª9-•J¾þI²ëºîBóL%IbÇ*ÇÞÓ©SoXƧõ«‘¤Á¬_Ó\Í m&š;ŽŽŽpáÂÔëut:¤×“†±œqÔñPQœœœøJ>yÙXe’F×Çg ÏÓ³ükÏó†”S†ÙDÈk®(ÂøÌ²Ï–.‘Ãtð鸣é~E‘SÇq`J6†0D<Ïó Ó4}§¡ªªß18ldܼys$Féša(’KPJ'ííéóT=ODž¢ì¹à˜ÜZ­†×¿þͤ›~-(?ÒY­Vqzzz{Öv •Ê)._þ'øéŸžn¬=¥¨{±XôÇÅœ• ³:ÂÆiTæL`«›H³)®-V‰Ö˵Z W®\A>ŸÇññ1.\¸€ƒƒƒØi:Y§XÿN2X ctã·, wÝu—³w]wäM^A6T™¤1ŒáNQ™A=28Ž¢ÑhàæÍ›]e6Ë ú2—IP iZÔ €ß'c“îñA#V×u¿6JX‚u©¦iúѪJ¥â¬áÔßYô2P‚Ʃ뺾±ìyžÿÃ{P|Z­éié–5Þ©i™Q,á8þÁ?ø|ã7þ¡_ò4n.¼$‰û‹,Ï—OæÃéà 3/ž]úÜï©Óo%^©³\üVUUqéÒ%\¹r…Bívû̯º>Yð¢æŠ‘··X,.Üa‘aVm{Ñ]w8¢ §¶„£Ü1‘Ùd #Ù™ñ×iŒÔ™ÒÈ‹Šn1Üðˆ:ñÒãÁî¼Àp­)Õ¼Rꮢ(þ¼TÅFû‚,Ëe¦iFî³DÅ(­”¨Õj¨V«~1u€eâ3®ËiqéÀ I¢¼¦ih6›øÁ|9~ã7¾§§§glKRüy« ³¢Æ‹yÞ ‹Àq„ó†UøtsGÔƒAãuwwN.\ØÈ”áVkúÆÕÞݶm¿Û¯a\_äš=”ñJeÐT&Ì,c&&ëØ¶pX¦ÝX0¶aRІQ§à`P8¼Þu]‡çy¾–Æ|ìì쌌ÃÑuÝïFD×õ™ Lª«u]×ÏVÒuÝ/BŒ™éx°³#þ?­‡V£1*÷¦ib{{¿ÿûOáø}èº>2Guì[`Ò‚eEë:ÁfI4¦‰ýòéÆ7XÛíöÐv»íGWÏŸ?ï§ o"T@…çnèÁ<¥ÅhšÆQ(&•Ôj£^tZM:®m"®á?†Ùd&¥E&E°N0sAÇñSyé÷཈¢¦Á뚎{ž72~F×u´B¤¨ k8ESUU¼Høù³FD)Å8ÜœºÈòž`7Ôi†fð+uÅb¶m£ÕjỿûÝxÿû_ È7úaÖ‰ãŒf‰Eaã3(›MqœGÓ¬ÚcŠÅ".^¼ˆ~ô£3g§ÓA¥RA·ÛJªT*ØÚÚáÒ¥KØÝÝMúó.DT¤”„Õ¶£6ª‹X8=©g.Ã$À¤è‘¢ ŽÛöà9”=À0›Žç‰=>mânÛ¶ŸK£”ê9Éè¤Ù–¶mû3)ÃóOkµ$IŠRªªêϨŒC”aºLt]Çöö6€Ñ{j•sLccYƒ”\Y2ö¥çÓ¼Ò`ÖXðµ$)]°Ì»®T&GF)‹2 ׯ³â­mã yÈaÈ)J%‚¢¦ÕbùŽ‹eY~yF³ÙŒÜ«iÖ7uú¦^¶mO¬}ÃÝnW®\A.—ôz=t:\ºtÉlwwõzív…B!éïlnh&¦}R¦¥Ntãç›*“e¼ÁJ׃išøùŸ>ò‘þ—ÿåùÜÜ„93hÚúÒ)ý6œÚU3î8Žß=—®GškJ ¦iCçR@EQFNQu¦ÁzÖ´À]a#¬¼KÒ°ÁjYdY½­¤?8Q—9=ÍFm7sö Ý&Xòäy"k’|/ÓÔô`+3Šëº~4•šõQ„tä< Þ·,ËB«ÕZØnº³P(ø†)?̼‰gÓoœŽ«ÑÐuþö<Å÷`só&+LÓÿZ-À0¼æ5ûøéŸþÇCc+†Y–eÁ¶m4C“æiÆqð¾âº.Êa˜”ú ÀïU—•ÒO#ª‚ÐüLΦØ,k8}WQ g¨þyX6&+,LZ¡´÷àvZ« #6E>¸TCÎOúÜ+lÛ†eY¨T* eáȲ¼´ *wöz½¡:òùüÆ©AexîRðÿ“š ˜¦é{ Çáz&P}Ç$d·7ª@Q”T¥2Ì*¡Ô±UlçÛÛÛ8==z,ªa) 1¥çQUp6i°n•w]wÈÐÕ4m¨¼‡ ¦IaxÛf¡(Ã#U4^¢fV;;\³Çd׎z×£NƒšïQÊ.0NR°’$-œÂ»lîìt:¾‘Úëõ`ÛöH­*u>wî\Òë]ˆju¸°ë"®QžD×Þö¶?‡¦i¨V«~ã îVȤê|=MÆjƒ=’Ì™#ª¡Þ² ñ,Áè%Õ Óxi|‹eY¾#45 ŽŸ ÞwèñpÄLÓ´!#—à(êÙ ÊߨªEUÓ5e2a݆‚PÔ XÓ6'Å—™³f¼£¥Á߃*Í׎2FÓœAzg¡PÀÞÞvwwÑn·Ñëõ|‹»×ëáÚµk888@¡Pð»gEmóN¯¨¿‘ë/|áu_Q`o4“$)ÞlÛ¶ñÂ~çÔÔa†Ù4V•(CŠAØ`u]º®¬Žã@UÕ!—jUa¤RýP¸ó¯mÛ‘µªœ%q6瀩TèùóTYa²Ž,›\7}Þ¥\.ûϸ{ºiš0Ms¤/Á$5KÜQ­V¡ªªßõöÒ¥Kþ¼Õ‡zÔE8ëi°¶-ŒÕà†®ëƒß£vUþâ/þYªšR0L$)^‡ëºøñÿË•Ešf“1 ï'%¨Ëv8ý—²s‚Þojªìð4h© %ܬ‰FÒp¶ˆtÈR)úØÕ«=\¹ÒÁë^÷p}“}ÂæÈÉÉf5P2 cÈ.+—ËðBu‹Žã`{{ÛÛÛ(‹ØÙÙã8h6›¨V«C?Áñ2YæÎ\.‡K—.EÜÝÝÅîînæ#«€0XÃQ§ s𲍆ãŽÀLö =9ŽbÂ3W™³Ša,eJ¿¥zÔà1JVUÕo¤D õG ÚSSÀ¸zž7tR½¬ ô—qY2—.ý,¾ækþÞûÞ/çè*“y¢êW7 *õ ¹×F†a X,¢ÑhøNÏR©4Ô±7ªÛü¦q jTëõº?º†ØÚÚÚc•ÿ-ƒŽqÓÌø@€IDATtÓ#J¥tµüg˜8„>c §,2ÌY"¼ßÏC¸^ˆ£4_"x­‘JéÀ|%$8ƆPU5ÒiªëúÆ+(L<%:Õײ,ÜqÇÇ·~ë×àè*“}jµá†©Y‡êË Ã€a(—Ë#AŠ”–J%†1b¬8÷‚;ëõ:ŽŽŽüŽŽŽpñâEìïï'½¶•P.Ú^ç7éúèEðñ?› V&SxÞðܽI›»0ÌYc¾š¨k°•z¿©þ4œæK~£ê¢ Ö¬—é0Ë#ª~Õó<†V«×ec•Ù l;[õªžçÁ4M¿‰ œ–Š¢øŽKJÙUº®GTUÅÉÉ LÓœ: uS¹óèè»»»~ZðÁÁŽŽŽðàƒnÔhÇí NʈH«t ª»qß‚I”æ¿¡é"Ó0Íé³W‰à( †9KLcÿ5¼HÅ‚ŒØ`GààøªW¥&L„¢(þè‘ <ùlcBw§ŸÚ¶È+ñ†a@Ó´Û#’’þ ³8®›ÙÀžç¡V«Á²,hš†J¥â™ÔdoÖ²I’Îtó×;àâÅ‹þYít:I¯mé(ЍY"O£® ¥}gg€0j‰«W?Ž—½ìÙI/™™€ ˆázư¬ÑŽ×†aŒìˆL?d˜³€ã,®ø1n°Ný0M¥‘4á”ü AË0Ä´z=Ï>îº.ŠÅ"$Iâ(<³QØöêF‘- Êl »âääÕjuÈ0¥~g1JºwªSݤ¨ê$(uÒó<¸®{;|püCú$Þð†/$½ÌÍçYbÖ\N¥@ ãL­¤„‡qÇqü¤ׯn®»YE= à8ÃŽÇI,Ú´#Ø”þ5î„–0§§§ }sLZ©T&;W‚ÎÛ¶Q,¡ë:«ÌÆ·Ü) ¨5l¨rÓÖåqGÒ X·»CÃóDŠãˆh¥e ·°pjµ~ï÷¶°·WHzÙ›@…0X_ ˆT`Àî§7éL­ã¢FÁ¡Ñ„eYÉI’Ðßc¡×)•Dq>ÓÄãqŽ3Þ`5 #²65 Õª,yžç+(d°»þã¼ëìDb˜æt' ‰išh4\êÁl$¶.ƒ•ºõnooò,È²Ì†ê ¹3é¬IöÒPª–®ë¸÷ÞÏ¢T*ãÏÿükñ½ß{7^ÿúç%½ÜÍFЂ0* e‹ÓW!<µšØÙ´ÿ _&Þã ìãJݨ–.¨L›¦éÏøbÖˆçÅ¢ø·ÕZüæ§Ç?ÏF¼4_UFÇÉ þç_û{¸ç£÷¬ä+_·|Q_}ÐëNݰ7®Î‰d2l¨QÄ1®+^£Xoð‘N]W|idÔêúô.»e ÞÀiê¤Þ†‘ôN~ƒÁx²hÙ/GKé\j’¼>Çñ:ŽãŒŽ†g«;G2Ù&iÙ§(¿‡ªŠŸÍ3´ÿ0‹‘&§ºTÊ"ˆRGK%ñ¼ed?zžç;=ÏC­Vƒ¦i3i‘ñ Z;®NÛ4ço„ÞßÉXm4¨V«¨V«¼ggˆ;nݺ•ÈFðÞÞŽ`âE1É`þ³?û3|ðƒÊß„PdìÕ)ó€O~rø±yÇ8:Žˆ„Nk7j-³ bŽlC8f)»»»‹­­-\»vmED³*ù€{‡‡K_óÜP/úY•%ª¥<ê* ‡Í¢Þo–ô]bÑyÃäððp&Åa’ØÃƒX–ØReYˆ^±8ÉYCJ‘é+*Ž#ÄŒêUǪª#£j¨S°$Ið<ªª¢Õj¡X,rD+aö÷÷qþüù¥ïáiÛ¿ƒÉQ"÷›¿ù›øŽïøŽôgÑ03Aû÷2JðÂ$½ÑõáYÃáHjЗ=+µZ Õjš¦ùÆ*×y§ƒyuð;òù<*•ÊX!íõz¨×ë( K¹x¶¶¶°¿¿?$ôt‘´Ûí‰ï1-uy‰8Tª¾ñÞáhQñ µjupMRq5Gݘ¨f’F1ÎÖUüØGçü2 Æ4<Ä‹J†d%âüeÝ_e$ÓÌj IÈ70èf•Qdÿ gÈ«ê`üJÔi\nPаe#)'¨0Pr&ùßøÆ/cgEUGŒ¦ù’Ájš¦? J’$´Z­³3ꌑ´lñ¼É>jÛ¶ñä“÷à'òï&ýµ1"M2 ßÒƒÛªço$9 ×uaÛ6t]÷;µ7›Mvìdœ;.]ºä·°>>>öÓºÝ.ŽqáÂt»Ý¥[·Ûí‘”JKÎår8wîœÿþÄ´ð4ÆÙp+´­``t2âG5M®“ÆcxžHö¼é³UeŒìVTàw ¢¡Ó¨ ^Ã$‚–e@¼‡6ãù“¯ÛðšHB¾!jÑý€V\Ÿ¡ªãSxÇAƒ«Õh' Õ±ÎúºÌZHJÆAýip««V';%_ýêÇȾA¼N‚µªá+ Ï.–$‰Ó“ÆuqÏ{ß‹»Ÿxb©/›¤l‡‰j[Q,ŠÛ=âxík_»É• ›KpTàšI“ŒS2aðk±¬Á×2o°É4MN“ß@îÈçó8<<Ĺsçppp€xŠ¢àÀÁÁÎ;‡ÃÃÃ¥¥&är9 åæ!ŸÏ#ŸÏckk …Ba育mEª]›‘83÷– ]}&ÆGŠÊ6 gQÌé<Çw/E‰wU«˜U FÝÄ5Zç¡z{–aMë–obž‰0s¬œ4Ñž˜µ.ZÓÄ9‹6cVBR2 2ÉgáoþÍ?‡¢¸~¶HCci‚óSÃ5¬Š¢ø#˜”˜—üÅ­-øà\ïGEÛÑÇ–ìÝò<±é4€¥ˆ(bÔ\Â0<`ßÞ§EHéëq|éÓÀ”ÄûĽ¢mLD*·×4͘܆˜ç:¾‡¬[¾‰¨ùe+Iß¼UuòMÖ4Åyo§$7ontS¤,“”ŒBŒ3õ(ˆmÛPW®<Ç[mp,,Ëp]wdT 93Ïœâ¼i†ÃÙAÈÑ:é9Ó°¬Aé œUQ߷늽Ƕýú“í6°äÖ$e;ЍÑÒ?þãâu¯ªÕ*'¡¬ê ¢iÂÀ ÷B îót\ÓÄm y®TFoÊ4†-Á{[šd<ìP”Éåq0 ãìíÙi†®úÃJàyxñõëxÞ3ÏÌôRw¡7ᆽ^N'rfÓ<ìïïcww׿P¯›ÏçñðÃû EÞW–ÇÛt£«.f–˃‚*rÊS×ÓàU¨@¤Õþ¿{À§x˜apV\|ðÊÊóã¯ÍÀ`,Ì$h.ÄÜÓ*†gœ.Òá÷Œ°Nù& cô~J5zKÃ4µÒ„$÷†ýyš±±šj’q ºés4Mƒë¾­Û²tVR”•¢®ANNN6?ý—º}ËòÀ¥†¤QV«ÑgðjÝì8Ã2|ó Fi¨ý'Õ´ûÃÆ SÖR$%Ûa¢‚zO=õûø£?ú~ù—EÃY7gÇ÷°qƒ› 2VI7‹r¸ϧfµš¸N¢ŒÕð9 ’_&žç¡T*A–e6XãbYBΩ?ɬ¢ Ò™Â÷?*.ë}dç„÷èà=ð“¹W¾_6ã½õÎ8Oêt:ØÛÛ[jÄfÚü×\.·”‹dî>-46%n`ˆ:ÐÆF׋ªFþPà] ¨m@~Ùô×vÙ=zžˆ¸!šMSà\Ì^ç)ß~íðŸ|Ñ¿g„uÉ7±òQbáxªc%å”j«e™5ª fÝ2>ï´-2DƒFj0šJk”az&fô‘‚mÛ³uáv¤§â3ò¤3@çq^Ub>;ë–í(\—ôF ¶mûY¯xÅc¤ç­ý;Y9"×Yu‹¦áû{¥™šWRýhPÖMS¼¿èÈ6{$49]„4Èø2üÒ®+Ê= Ã@¥Racu,Kìù”åbÛBöÉñþQ‚À ¯{ܽƒÚù‡x¢ÝÆÓ3fÈÄ2X³ 凿÷©3Xuˆ:Ô8PƒRÎ= "‘Q5~4óô—ª€ù²x£nÂT Õ8F«ŒÉ#h&GògbÐÝ—ƒ_©#ê^¹´”wêþ1îNÑ`¯ë©ñ&3›Ã<:!e Ò`½ª¢(cg«f*sœQ¯­çˆ-š‹7F)aC’ d(ómgG#s#¶Y20«Uq¯¡‘g€cš]E û(4Nf%IDzHî© 88>- ß³ÖJ¸~uVlÛF¹\†,ËPÍfól8'A¥®;\^A÷‚°ÜÓ˜Ÿ :‰¨ðG¼m¼ÁJ{_Ôw:QA±/ºJ…÷ÁH’ a°Òß68û)¨Ð«ªˆV–1Ù`õn?'©×ë%½Î…wQŒUP‚Îw"re´*JtXkRšÎ$¥h\'߸§†ÑŽ¾Ò”õ0™ÇóÆ;en@p†7G&]Ì3k8˜OÖ¨Úî…ÓÊh€`0•§_©%Ý0ÄïÕ*G‹˜l›4ÑÞiŠÊ¢Qª¥BÍZ¨y09g™7©´º™U3oÆ ÖJ–kæéâdµgùó­ˆXÖut [Áý’æ3Ñܽñ'aÐ W‡èÈ;‹NN ŽƒŒñé¶fOÅ¥±4*x Íf£É0gšy‡ÈÎWQ«Õ–WÛ ê‰hTc'IB §æ’—|\7@† à8NdY%w¥&#’êPUu¸ŸÇ¤ûß›Î4¦9ŸMæyÇI¾ç€ëÏ §lˆ !:ÉËÊò?3w&½†•ÜëMÓ„mÛhµZð ¨êÔ:m†ÉÁÉIq —~мե@ KTà ô(XYa&@™à†­§œž ûpåb•%ày£´“ÆZ0Lª:_—eYéh´îíœCMi¼ì\*w„½½^ív;éu-áÎý TU…AéXã—4”n?¦>ŽE Û¨Q:‹ÜtÌf2ÕiÛ¶ 3àñ›Û`ÝÙÙö“Ì&Q.Ïw^Ð`Ue¨CðBМá(¥$iï?“YÈ3„£XéMSú¡è‘iŠûCTm-«Ì Ì[­dÛöú V*ùB+ýPdUUEèxÒdf.î?ðÐC!N]kV :òªWo?0©™ G;£Õ‚(™Öåf‘Æ\µˆÇ昵Μ‚u ÁÒ\éÀ†1_± ì˜yD2a•eyÈ©‰ç :2–J¥}š£“a„ìD[C3„Ã,:Àx’íð5!I¢8=Êw©$ UÛiˆp1™f–f‘¶mÃ0 ‹Å±×ÄÊY« Ù猵ÄÙø.ÁD°n©Z­F <ˆj­p-À‹Ñ5už^B…¥Ãi¼LLÈSi*•Êä†;;Ã5FAT—ÍÑÒÄÙhƒ•:íU«Ã¿$IÑÝS)÷\«F§õš&°ÿS¢™QÑ£fˆn¿óFEë ±¾O0Sð<º®£T*AQ”èT2Ir%ÿ–Åžs&µÌ£§„~j¼‰ã%¦ÙdÅœY;T£ÜšÇ)çãÌü†³tmâk‚YË[¬®Ço¸dÛ6TU/ ˜‚P”®|\–‡£ýÒøI&QîXü%ÒK0‚«n©Z‚½1ƇòøaLNÊ*[Dç§1:„½Ö¯ŒÉ Å¢ø×ó<_Áq]7ZÙ©Vùfajµù Kf…Ì[¯¾$IÂ÷ó7 ¸(–¬VÌ™ ©H„mÛcëW—òf,çÌš1 ±ÅÎÒضíùS€%Iȹãk™¢Xº>ê¬ñ<±°FƒÕ”²ÑVMŒb5 ¡°ŸøÿøöácÁ¨Tðb w^4*A¼Û·ß§ KÃL%h¬jšÛ¶£ VÚ¼=oØ»hY\»Ê¤×½CpT:¥â8h¸.ð÷ÿ~´s†Ó¾˜ o¿+K6OËm†Yyæ®.4OžÎ‹åë!õÜ `¨ÉR¯'¢‹Q—²<'vgHMŒmˆ™0·¡&Qé35£UÃbÍ–‚T1húÄö3…V °íÁ\2MÓP«ÕÆoòš6¨_"æŠÆ0k œ½5ê_­VGç­ÞNùzþé)¦Lêpœá-x¬ÓqqçûZÖèŒ`†Y!ó6 ›-Æœ9î¼xñâȃ…B!éu-…bqÝŸiöޮ盔*ÙàA®;¦ŽÅ›&ñõÉÌ@0ƒ@–eȲ<ÞA£iÃ2M粇‘I)qì®ëú5OC{¾ãˆN§Q3S&Dդά¨Û¶ØÛ«ÕÉQ%ΦaÖŒ¢D÷3íå wîïï'½†•B{òÔŸj:l3ïááã“4& "*jC4\b}ˆY#"¨ä E“*•ʨÌ‹ƒ=š'LÞø…;x0Ìêg°ž‡V«…R©MÓÄ5áyÂXåfJL†˜+R×…1j"k¦ÙŒ¾pfµf Ìî‰Y¿J5ªô®CÝH6ºé15ºJ³–ˆo|ù°w° àÜÑ—Y¶=thš6l°†óqªUž+Æd†ííxÏsá¸Ñu¦iŠk‚²eØXeRŠçEù+R–Λ»62éÀ4gožç8Îô«i ‡¤r{ädµÊÆê†r't:áâÅ‹Èçóc=Î,“~S-w¤–)Œm”Öá™ A%KŽãŒŸ½JO nâœfÃdˆ¸&Úç+•Ê öI’XÞ™T¥ZMu´So YŽvÆPƒ=UƤêëÏó†šIA#]W¬<'õLp‡mÛ¸pá:r¹œ`—.]B¡P@.—ÃÕ«W“^ëÌÐ>uã¶  wýe˜ãºBÎ=Ï›<Ç0&N£ã8C×@£ÑÊŽ¢°ÇI5Š2씫¨–ììD[º„ªÒ$&af |N­_­Õ„±Ê} Î wDSÏçó( ØÝÝE¥RÁC=„,Õ»†g°N°;³ì3!ö¸×eO;³ÑLUò&¥„û:Ž3^–)¸ÕšlHuœ<Ï08=žI„I"GÍòlÛö÷q×u5Ü–5œ)C3³™3Ž^ï|ç;'>éï|'ŽŽŽÐív“^ol‚C¸'FŸÂ©’s¨g˜$ð<@–Ýéæ)Ë0ò¢ëû„#¬ “jµáú¾‰:K©?\vRZߘµãy"…ã8(‹p]•JÍfš¦áÿøûûþHÈ»ap– ƒ;·¶¶°µµ5ô ¥tüÆ#ÏM+ª:pÆLŒ°ëW1N†Ë˜Œàº12&Óðéµ- ×u'GXƒ›8w{g2D³³ 6oøL†!ñ$ë#û|¨Ì…aҊ늚½¸®‹jµ -l”ÒèŽyGÒØ6¬L"LRQ";—JƒS©°îÂøÜÑëõÐn·'>‰Ž£®iÇ4ý¸ ³©ˆ‘ªS"¬Ü%•É0Á‰LÛÛÛ(•Jð"F2yž7|„G91LJ‘ea°V«UT«ÕèýœzmÌ+Ó¶Í} ˜D˜T‘äws'(‹`ÖÄÌÆsG>ŸG½^G¯×‹|B¯×C½^G¡PÈTÔÕuEÞüÔî©•Êð  ˜ôÊ&–EsX§È8oþL†ñ<šÐá@Ó4(Š‚b±;4crdì;"™ @Ñ'š!<–Je~Ç#§3 âyÑ~–‘NÀŽ3Ú•ansç¥K—°··‡ .`wwwÈ(½v펗.]Jz­3¡ëƒù”oÁ‹….1Âq„ør +s°mŠ¢ R©@UU”J%œžžúÇ9ºÊdŠ>Y–»º.׆1*1Ã,ȸi#ú¹¢ˆ™ª Áù|W®\ÁÑÑêõúÈvwwqñâÅÌ4["‚‚㟀;e3œ2k´&Ã˯]×õëúEñGȲ Û¶‡•}Ñ>;éå3ÌTøÂ¾°Ú‘LšÆéÀLbŒì8*•JÒËc2€è|éÒ%ìïï£Óéøóù|¦êVƒ˜¦Pè§FX&£~ó'™MEQDc1@DXT1UUý“@¨Wm³ÁÊdM>üá6¾ìË"ôÊ^T–9ºÊ$È8ñcýœ™…;‚¿är9 ÿ'«Æ*0h9u+XJ¶Ìe˜$1Í‚‹Emb˜ CÃ䃨ªê×­ŽDX6X™L ËÀ£þ§hÇcx@+Ãd¨CÆ*ë(L îXü%Ò Ù¨‘-³àcOßö߀6€ €SœYÉdÏ£¦Köx%):œ.ÌdÃŒü˹¢(C›!…ŸG91#û¸|n–ÄdÏ‹ö¹ø{ºiŠža¦°ÑëØúUÀ7>xÅ+DÍjg%0‚¦1¹®;ì ÞL“ë–˜LcYÂî—:¦( lÛ†ã8Ã+›g2B­ïðþÍõ}LƩՄß%Œï¤a9gb²‘+xDWMS¤H>õð ¿üÓ'9¢Êd’±£Êå·Ò²xœ “i¨aä4ƒu$e˜ë¢˜Œ°¿ÿÌ@vK%±‡».ïßÌF ªÑÛ±mÛP%ID—عÈÄ`# VšÛ7RפëâêÑTàÆO±RÃdj?Ò!¸ÙÀΧ’1™‡D{d¸üm4Mó V†É"_ó5¿7pÆœœå}g‡³c˜ Ê`-—Ë¢ã;g13pgÒ X%Á1>ZpÀ*±W‡É,Ž|ÅW\­Ï–$1tÛ4Ù`e2e‘óq|'IrÖp§l&‹Xà8!Çz¥Â)’ÌFày£ÆÊå2 Z©ˆŒÇ@çw†™ÄFFXeYèê‘id&EnÞLz™ 37žôzWÇ+êºÎ&ÓPߤ‰Å º³ÁÊd Ï£¦b.ö`6’`ýªçyØÙÙ$Ib<;Õ™ÙXƒU–)d†1(lUp“q(ØoÔÁ]ö˜ ƒ Öi ½®ëÙ4†ÝåƒaR„e‰lHÇq ~Â0É8<ÿôý_¡ª*ªÕª8P«q63i°¯<Íÿ …G7Zb2Oµz»iª O%G˜˜ ÃuIòr>Y–G;eó('&åØ6ðMßÔÅžpàPg˜ &HàììàÛnÞÆ* <îë-ÌLl¬Áêûð]< ˆ‘6 “q†º¢eœa6ª{²,k´Aœ“9Å’I1ž'úßû½:¾û%/áÔHfã°,!ÖÿéMo\ø/ÿepP’Xgaffc Ö~«ím‘vðMûÀÎíìxg6¿>Û0ÄÆÏ%fƒ ï¼išÐgMãh“rÈÇøÁ÷¿¯{â Vޙò€·œÿ8þ_> …æ“1̤Þ`ít:èv»³ä¯ÿ“×ã%÷½ø«ß~h ¨Bü0LŠ˜K¾!Ò¿>—wî(ɤ˜ydÜq€gžéB’¤Ù*qt•Y#óÈ·mÏ~ö1~æ%/Á?ðI†˼û·¢Ç÷àO^ÿzv¨3K!µcmºÝ.*• :Ñ ²V«Å:×vmüá[Æ÷\»|à÷×€#«LªXD¾aýßžû\QÌÊ7&…,"ãš\¾üïfO¶m®‹bÖÂ"ò]©Vé]øÚW¾’ŽL*YD¾% ØûþO@þ./úèG“þ(̆ÚëÁÁ¶¶¶à8®^½ŠN§ƒz½ë\Y–ñÏ\u¿þÅl¬2©cù€·~îsxáÿüŸœJƤ–ÅöpàWõçgOöŸ÷Ëçóñóèh6“þ±©×ëh·ÛI/c.ööö’^BæXX¾ ÕÊ”²“U9i·Û3E¾Á¢2®«*~ôúu`{[ÔiÛö u°ªŠŸ¨Hêéi"³ýx?[,*ß·öö dÈá˜Uáý{>•oÛ²ðKoyËìý‚÷ïlÊÖIE¯×C.—yüÚµkø…_øüò/ÿ2î½÷Þ¤?ÂL<ñÄxôÑGñâ¿8é¥ÌÌõë×3wÁ<ùä“xòÉ'ñ‚¼ûûûkÿyäþèþo~ó›q×]wáî»ï^ûº!‹rO?ý4z½ž_Ç“®_¿ŽÏ}îs‰½ÿ¢{ø}_ù•xÙsžƒ?ûöo§“Ä¿ðâŽû|ax_/O<ñž~úi¼üå/ÏÌÞ¿-CßyeÈþþý¿ñxë[ߺö÷_ŠþêWgFfxÿ^/¤ƒÏº§Ò`í‘rÁ­[·"/–|»»»ØÚÚJzù3Óívñ¢½h¬¡’f:Î.+ôz=ܺu+±÷Ç8ù€Ÿù™ŸÉäw d_N²¸¯$©¤ñž²~m&õÞã'ß¼¯Ÿ¬ïßI}ç¼g‡¬_›³JƒuÒ—?îbÈår™¶IŸ) dñB’•—yä{Úyi'«kÏò¾’äwÎ{xvàksvæ‘ï¬~ÏY^{–÷Þ¿×ïßëgyIe ë¹sç §%t»ÝL Ã,ß̦Ã2Îl2,ßÌ&Ãòͤ‘T¬[[[( 8Ô(Ù¶b±˜ôÒfaX¾™M‡eœÙdX¾™M†å›I#Ïê÷ûý¤E§ÓÁÞÞ¶¶¶ü"ïÃÃÃ̦0L–ofÓag6–of“aùfÒFj VCÝÝ …BÒËa˜¥ÂòÍl:,ãÌ&ÃòÍl2,ßLšHµÁÊ0 Ã0 Ã0 Ü]RYÚU:ÎÄQNgâ|«Iǧ»ÌϰÌu¯síÌjY¥|Ç9¾¬Ï°ìµ±|o‹Èø¦Ê÷ºÖάÞ¿Y¾7Þ¿“[ûZè3 óØcõï¿ÿþþ}÷Ý׿ï¾ûú÷ßÿ±Çó߸q£ÿ}ß÷}þñw¿ûÝCçO:>íÜerùòåþ;ÞñŽ¥¬{ÝkgVÇ*å;Îñe–ïEׯò½9,"ã›*ßë\;³:xÿN~íÌjáýûlÈ7GX—ÀÞÞ …ÇÁÕ«WQ(P©TüãØÚÚòw:ÔëõXǧ»,Úí6ŽŽŽ†[dÝë\;³ZV)ßqŽ/ƒ(ù^tm,ß›Ã"2¾©ò½®µ3«…÷o–ïM‡÷ï3"ßI[ÌYçÑGíßwß}ý§Ÿ~ÚìÆýûÿØc ýŸø¹Ÿû¹þý÷ß?òÜðñiç.‹§Ÿ~ºÿ¦7½©ÿîw¿Û÷ð,²î8Ç™l°JùŽs|DÉ÷¢kcùÞ‘ñM•ïu­Y-¼³|o:¼Ÿùæë‚äóù‘Vß7nÜär9ÿÿù|~èÊ'Ÿt|Ú¹Ëâàà»»»þ°èiëZÆq&¬R¾ã_Qò½èÚX¾7‡Ed|Så{]kgV ïß,ß›ïßgG¾Ù`]\.7Ôî»Ûí¢^¯cww[[[…£×ëM<~zz:ñÜep||Œn·‹ýýý¡ÇYwœãL6X¥|¯CNÆÉ7}–y×¶Žk“Y‹Èø49Ȫ|ó¾ðþÜÚ™õÀûw2kO6X—D¯×C½^Ç<€B¡€K—.ùãÖ­[úÓŸžxî¢t»]ùk žy×ç8“-V!ß«–“Iò½èÚW}m2ëgŸ&Y•oÞÃ7 Þ¿×»vfýðþ½¾µ'¬K Óé`ooNW®\ò–Ãña¶¶¶&Ÿ4¨ykkkáu#—ËÁ¶mÔëut:ܸqõzwß}÷ÜëŽsœÉ«’ïUËÉ$ùîv»©¾6™õ2¯ŒO“ƒ¬Ê7ïá›ïßë_;³^xÿ^ïÚ“‚ Ö%P©Tü<ú°P^z0<ßív}™t|Ú¹‹rþüù±ìË_þò¹×ç8“V%ßqŽ/Â$ù^tm,ߛż2¾©ò½êµ3ëƒ÷o–ïM‡÷ïõ®=)Ø`]Û¶Ñív¡ª*ÚíöÐ <…BÇÇÇCç‹Å©Ç§»(…BûûûþO>ŸÇ¹sç°¿¿EQæ^wœãL6X¥|Ç9¾“ä{kk+Õ×&³>‘ñM•ïU¯Y¼³|o:¼Ÿù~V¿ßï'½ˆ,S¯×#ç'€ã8é [[[èõzÈårC]Í&Ÿvî²?K§ÓÁáááÂëŽsœI?«–ï8Ç—ùY‚ò½èÚX¾7ƒEe|Så{kgVïßéX;³:xÿN~íë‚ Ö5ÑëõÐétDçÍO:>íÜ´®;éµ3ë#Ër’Õk“Y/‹ÈAVå;éµ3ë!Ë2’åµ3ëƒ÷ïìË7¬ Ã0 Ã0 Ã0L*áV†a†a†a&•°ÁÊ0 Ã0 Ã0 ä6X†a†a†a˜TÂ+Ã0 Ã0 Ã0 “JØ`e†a†a†aR ¬ Ã0 Ã0 Ã0L*aƒ•a†a†a†I%l°2 Ã0 Ã0 Ã0©„ V†a†a†a&•°ÁÊ0 Ã0 Ã0 ä6X†a†a†a˜TÂ+Ã0 Ã0 Ã0 “JØ`e†a†a†aR ¬ Ã0 Ã0 Ã0L*aƒ•a†a†a†I%l°2 Ã0 Ã0 Ã0©„ V†aömxž—ô2fí,[ö=σmÛI,†a†Y:l°2 “ÅbŽã$½ †Y;Ë–}ÇqP,“þXÌÆ4M¸®›ô2få°¬¯6X†a†a˜…°,‹•xæLÀ²¾~îLzg×uašæÈ㺮C–eOŽ,ËPU¶mC×uÿ¹¶mû©`š¦AQ€a¨T*0MžçAQhšæ¿ž$I¨T*þëÌú|†™Fù€Z­Ïó"elœ|,ãLzY‡ìW«UÔjµ¡Ç ÏóP«ÕFÎc˜y™$Ó¶mÃu]X–PUuDFmÛæýšÉ‹Êºªªð<Ï—]I’ ë:$IÀ²=aMÏóà8ŽÿcÛ¶¯ÀB¨kµáÑ)•JþEe§T*ù¯µ³³ã_dtÌóÃLcš|@¹\ö'“ôZAùggÒÆ:d¿\.Gzú=ÏC±Xô!†Yqd:HXFy¿f²Â¢²îy¶··}‡£eYC%,ÛsÐgRÃÍ›7ûŠ¢ô+•J¿ßï÷OOOûú§§§þsdY:tüääÄ?Þh4ú’$õûý~@¿ÑhøÇEéëºîÿ^©Tüךçù 3 aùî÷…Ìo4±å›ÎggÒΪd?x~«Õêðß+(× ³l¢dZUÕ~«ÕòË(ï×L™GÖi?¾†ªª¾>ϲ=;aMår²,£Z­UU‡ÒÇ4MóÿoÛ6dYö»C'/Mð\I’üt„qÌú|†‰KX¾ UUýÿå/Ž|‡ÏagÒȪd?x>A^úགa–Í8™–QÞ¯™¬1¬“Ü–Ëeض I’Ðjµ†ä™e{6¸†5%†×uÑjµüǦ< ´J&¢”†I’(ùžË7³ ¬[ö©~ª\.ãôô4éÏl óÈ4Ãd‘ye]–e´Z-¿”Ïó<躎F£‘ôGÊ,l°¦Ó4aš&Z­Ö‡E’¤‰F«¢(¾×† <×-1iaœ|Oƒå›É:IÈ~£Ñ€çy°,ËoÂ0Ëb^™f˜¬±ˆ¬Sã¤F£F£áSe¨i*N NÇqP.—Ñl6GMÓübo~Ç1"Ø…Œ Âo†I“ä{,ßL–IRö%Iò;VòèfYÄ‘éi™a “•õ`dWvð,¬ C‹Å"žõ¬gù?†a@–e4 ‹E‹Eììì ¥„‘Rbvvvü.’Íf3éÅ0&Ë÷4X¾™,“´ìkšMÓØÁÃ,i2-I ÈÂ0YbQY§6ÛÛÛ(‹ØÞÞ†,ËÜ[`žÕï÷ûI/‚‰†RÀdYöç°ÒŒ¦ âlÄA©d ³)°|3g–}&Ku–`C†Ù4âÊ:eHJ’Ä¥L ÂkŠq]ÛÛÛ899¢(p]Åb•J…sà†a†a†Ùx¸éRŠ ¦{žI’ ë:« Ã0 Ã0 Ü 8ÂÊ0 Ã0 Ã0 ä’‰°þÎïü>ðà«¿ú«“^ÊÌ<þøãxéK_Š—¾ô¥I/ef²:bä3Ÿù ¾ô¥/áÇ~ìÇ’^Jl~ð¯{Ýë’^Æ\dYN>ó™Ïdr_qGGGI/#6¼‡'C–¯Í½èEøgÿìŸ%½”Xðþ½~²¾`kk+é¥Ä‚÷ïdÈòµ9ëþ½1ë_ýÕ_áË¿üËqþüù¤—23ŸøÄ'ð•_ù•¸÷Þ{“^ÊÌ<ú裙üί_¿Ž}ìcI/c&nݺ•Éïȶœ|ñ‹_ÌäÚ}ôѤ—0¼‡'C–¯Ín·›ô2bÃû÷úÉúþý¢½(éeĆ÷ïdÈòµ9ëþ½1ë ^ð¼êU¯B¡PHz)sqîܹÌxÒ‚|×w}Wf¿ó^¯—ôfâ…/|af¿ë¬Êɹsçpï½÷frí/~ñ‹“^ÂLðž Y½6líἯŸ¬ïß¹\.éeĆ÷ïdÈêµ Ì¾':‡µ×ë¡ÓéŒ=Þét2åA—B¡É vww“^BjaùU9ÙÚÚÊìÍ`°Œ xߟG§ÓA¯×C>ŸÇþþ>àÆþq"ŸÏŸ‰ó™Ï,ýµW%ßð¹Ï}ív;³Ýì˜õÑn·ñôÓO¯äµyg’¦Óéàúõë¾,. Þ¿™4@û÷4™šÞ¿™¤!|Öý{í)ÁAïÎ#<‚Gy»»»ØÛÛ0¹Íñ¤÷Ì3Ïà“Ÿü$®]»¶îÄdŒ7n¬Ì`]•|Bá¹víš“a˜q\»vme#?xg’fU+ïßL ý{Ùò ðþÍ$éà©7XiÀ-¥Àƒ>ˆ^¯‡v»=”†f’Wòe/{Ez]†‰¢P(àmo{¾ú«¿z鯽*ù€»ï¾ûûûì½d¦²¿¿{î¹g%¯Í{8“4»»»xÛÛÞ†W½êUK}]Þ¿™4@û÷*"ñ¼3IC:ø¬û÷Ú ÖIé ¹\n¨ð›èv»œBÃd–ofÓag6–mfÓag²ÊÚ Ö|>?ÒB»^¯ckkË?V(p||ì·mÅb1éïŠa¦ÂòÍl:,ã̦²Íl:,ãLVY{Ó%¨ÕjØÛÛó/*ø&ö÷÷±··‡v»íy?øàƒIW  –ofÓag6–mfÓag²H"k>ŸÇÃ?ì‡k:¦g˜4ÃòÍl:,ã̦²Íl:,ãLIÄ`D®ü¤‹`Úq†I3,ß̦Ã2Îl*,Û̦Ã2Îdµ×°2 Ã0 Ã0 Ã0LØ`e†a†a†aRIb)ÁLv°mÀóM›ü<ÇÏ#dYü€ë¦)~×õáó<¨ÕÄù€xŸðsñ×Ïs]@UÅ,‹`g$ Õ¿†x_I¬Åq€×¾ö^¼éMšôWË0 Ã0 Ã0ÌØ`e"ñÉè3Ma,jš0ƒF$00>éueÑüýädØØ £ëƒÈ«¢ŒFx%ú³1 Ã0 Ã0 ³°ÁšBl[tAcÌóD„“sœAd’RjUu.KéµAÃ2ÈÎŽ02)mײ†#©Q†*±,#1lÄFŠŽ2 Ã0 Ã0 s6˜Ë`­×ëh·Ûèt:¸xñ"¶¶¶Ðív±¿¿ŸôçÙ c8jI鱊" JŠ€Š20t5m6 ƒ6ɤ4_JߥZP‚D†a†a†aÒÀÌk½^Çññ1vwwÑëõˆyMõzN‡‡‡I¦ÌbÛ˜l6‡›Q­æé©ø]–Ås2RÇ5Eò< \œ_«MOáe†a†a†Iš™ Ön·‹££#¢P( ÓéTUÅÖÖ.\¸€N§ƒ|>Ÿôçʦ)ŒÑJE¡†1ˆnÏry8b:+²,ÞÃó©¿ÁæH Ã0 Ã0 Ã0id&ƒõÆ€B¡0r,ŸÏ#ŸÏûQWf:”†[.‹4_MNÍ véTëC\†a†a†a˜´sÇ,OÎåri”öz=?âÊLƲD´“ÆÂ´Zˆ¤ñ-EBÃ/ò¾ŠÂÑU†a†a†a²ÁL+EQ÷öö†ŒÓn·‹ƒƒlmmEF_™¶=h DQF»òR­ê¸n½³nÆÄ0 Ã0YÁóDé Ã0 s¶˜¹éÒáá! ÃÀ… ívGGGÈçó¨EYb̲,ŒÆe¡ ä˲`Û6<σªªPUòS<σs{¦Õ)uYc˜ÎúŽ‹e Æ·…G»ÂXå !†a˜³ÇÌk.—Ãáá!:ÎP—`n´4êú{–o¶®ëÂ4M˜¦ EQ ( 4Mƒs°«mÛEQ ͨ yž‡Z­˲Ï}îsñmßömI%Lq]¶mû?dœº®;d¤Z–…R©Y–Ñh4¦Ê¬eY¾±Ixž×uýëEQÿýq-¨ªêË·mÛÐnwlû⿘ôWÅœ! Cd5ÂЬՄJ³ÂÑdÊ\¢î…T¶bÛ⹞7èá ªœ!Ä0 sV™É`m·ÛØÛÛÃÕ«WÙ@Ã7bj~t– ¨“mÛÐu§§§ð<¶mÃ0 ȲŒjµ©Ð MUU!Ijµ\×…$IcÛ¶}e^’$ÿ|Š:µÛm\»v-鯆ÉŽãÀqX–娕JÍ ÌÈS«ÕP,Q­V¡ŽéžflÛFuÌdŠœ’³G–eH’ÇqüÌ]×Ñhô{{{ImLÊqÉ$ã1µíáf¥ÒÀð”$qLÓÏ×õáÞÕª0LMs-¥×£sÈÈm6Gǵue†aÎ.3¬ù|¹\¶mcww7éµg׊AV½ÃîmmaRj#E}ÇñŸOSÔ)¨LK’]סë:jµvvvÐh4†úZ­Ó4¡iNNN&F¨(â$˲¿N2ŠÇA³Ù\kj&³z‚{UU¡iš]Œƒã8°m®ëúQL]×!Ë2LÓD­V’EQÐh4f–£J¥UUQ«Õ|ãÒ»­ùSdV’$´Z­‰2õÙfù¼ Ä4E”Ä™:Õ“ÑIÇifwµ*ž{{«…m;;ƒÈgÔe!I“›V«â}'%°ˆ3gÃ0ü,›Ï~ö³I/‡aRÅLk.—Ãþþ>êõ:ºÝnäsö÷÷“þL©Ã²’¿é’!)ËrìÜp­¦i~Èó«s'.¶ |êS¯^Ék3Ù‡jB¹ùÃÌO°ï€$I~ÏG}/}éèõ>ëâóŸÿfÜÿóý²Žb±MÓàyz½—á+¾âŽhšŒããã¤?à áyƒ‘œäô¤žô»¢ŒÚ;†!ŽÓs‹E X¼¯zÕlï?³Án ÂLÆó&fŶm˜¦9±a ™ôC ½,ËcQŠÎ/•J~£Šô„iI’P­Vý÷Xezíª”x&yÇA¹\†¢(~“dP×u?µ<œ^­VÇÖw‘e­V –eÁ4M?EœR}Wç Ï¡ªŠ:?YdxÞ`”Uµ*öƒR Xe_Ódƒ•†”†ÓS6T™ÍÁó<”Ëå‰ýfÁ4M¿OAX¢2#ú!G©$I°m¯xEþ¶ªÀ0Ä= RŒ3|ÆKÃt]ÇÅ‹uüÎï¼/}ékñ­ß*®QË^ô¢$ýÕ2'h`Fáºâ‡T-˲jÛâÑj î®+ôM2MÎùryЯZ¾·„û´ZÀ·û]xÓ›îžéóÌl°Àññ1lÛF»Ý ¨ªÊu­Øö|éÀÁÚ¼b±8TßLm vÛé¬V«ØÙÙñ¥Ri(º5 Žz2ób,Ë2F…ŠÔo2d—1Že™©à¤@xÞ žÏq#7l[lÈ”ÕK>eVP£ Þ*Šø ¾Æ,Ð,JËi›t³!£YÓÄã{{ÿÀ÷.å;`Ö‡m7’åAgÝIP¯’+I‘\’¢Á0›‚çy~‡eYsïùTRBÍeYF­Vó3Ôˆ?ù“Ïà+¾â7oþ(*•†m §¤êïí€H·7M±/+ЏwD57ÛßßÇ… ƒ}\×…qûþ÷¿%鯗É8ž'¢™Íæ@.ƒ²G²I²ç8ƒž¦)zйÔ/hüªªs×5ŠËeñ>Ôû ˆ$õúu\»öäLŸgfƒµ^¯ãèè»»»¸xñ" ×ëáààN—.]Jì“FHÙˆ‹çy0 ®ëúF*ÕÖ5 Ôj5xž71µqÕjåržçÍd¬2̼P}N¸&¹\¦¹ÄÒÒ<äË‚"¡ª*”ˆ`àß4Åñ““Q‡¥[²<š"C£;f½ôg`˜¶ZâÿA¯&—kg“°'œ"ô”¡cÛÀöö@é-•„’pr"ž[g÷ UJ„¢ÔLS†IÔ[cVÈX¥ò¡Z­Ë`u]þðø×ÿúÅøð‡_‡g?û*¾å[þ¾ó;¿Ö¿?‘Óˆ"IŽ#œ„wÜ|Ã7ˆkÓ4i޲,ž~û #3H¹<¸/D]—• ðñÿ 6Z™ÑŽí€I2Fú õ' #³Tÿº®cê]@x"¨§èºÍry`¨Ž»L£WÕå÷'˜É`ív»8::òkφ§boo/^ÄÖÖÖrW™afQ¨®OÓ4´’Diº¥RilC™Y ŽªQ)/ ³l‚Í$ÂPMƒx^2´£"ž7Øä£.‘E×I5³®³TïMÛ/m’”Ý.ägú»’':xk¥ñ1ä4! ìµ+ “¨=¦5Ÿ3MÓŸB@)¹tN°±¤x.E~L9K?ûÙç?ÿ“øÕ_ý4nÜøüؽ/|¡xRÔɈßðUu¸Ükµ¬Ñ8•fd€Ós!w†Ð›‚Íó\wø~ (£5œæ;ðu0 «pžÏd°Þ¸q@ta¡P@>ŸÇ7δÁJ£04Mɇçy(•J~ý]”·‘šÏ,‹y›Ë0gÏóü4uºéSÚmP^I–QOJJ¸l€°1åI\ÔµUF c ¸¬U¼w\dy8­ àZĬbYƒ”ñ¨¿kÁãÜY—É:d¬6›M?“l{{{Ä)OÝâ)å—ôÏ`_Ã^ö²_‚eY¨T*0Mà=ïy®ëâoÄÔqd/ß{¢öÕ¨Óç½?#ŠÙ¨Tg\ç<”ËT’åI•Š=Mè1” ÕêƒRÒ%)Û:ÃóœÔëõ"7êæ¬P.—ý͵T*áòå/Œ <·, ÛÛÛ0 Ãï軳³ã× ò¬P&mŒzž‡V«…““_É(‹þØ#JÑ¢ MÓ ëúí6ý¢.‡®‡Ri0Ï‘XçFjš"¦R ¦)ÖcuÕ>YÆÈþ…ç fUòö°Æ@¾æý»‹ÅØMkµš?«z,óµ˜Í†d”Rh]×…eYCý3dYFµZõæÑ}¥\.£X,B–eœžž¢Z­úŽ„CTìÕ*ðßx/ÞûÞÿËÆêç?ÿ†Ûi:$I†ëŠ´úq°É,‚a šk- 5r†#¢š6ê$¡ûÈÎÎ䨽,gÛXf4X …¶¶¶`ÆqÚívýq7…B!éÏ”Á´ÇV«EQð‹¿ø.|ÕWýÿªO¥Z½Óæ9ŒL¡ŒFchfuÞmµZø‰Ÿx^ùÊ.þú_ÄÏÝr…baÛÂ8¤4ÛAW¹ ²ðá¾Õê ‘ÙºÆ 2›9Ž£ ôóÓÓÑç†p”ììy%Ã6¸íno‹Çé}ŠÅñe>] ÒhD³›ÆÌM—jµ*• xà¡Ç·¶¶pxx˜ôçI㶤Ó+• ÅÆ»Þõv¿yÕ§Rgß8c:&I Ãð=ÚQH’Œg?û·ñu_wŒÝÝ/úŽMžFÑPi8å‘¢…aâFû<â†0®.c—d¾$E7ó`²K­6[Í©çyðŸÇ#<‚v»k×®Ο?f#«4ë$¤».àyBÑ7 •J¶m5Sb˜´AƒŸeÐà¢Õjt%5Ma`R­§®´Ò´¢öúK v7]ÁÆ5iÀ²F*JŸ®T3]™ÍÀ²fëžHiöy"\×4Béœ`'îZ­†V«Ïó†F!«( J¥,˂뺱:Çkš†¹ VŠúa®ëú†8ÍO¦(²ëºCõ‹®ëâÒ¥K¸÷Þ{×ô—cñ½Sz¹,ËP¶mã]ïú |ô£¿¾ðßàà@Ê+•F£BµšPâMSü?x=xÞ Ééï=¸ïпaã@Ó4œœœp3IféPV˜iŽ“Íæ°ÆqÏÞ¿'9©éßïÇ3×Ön·‹\.‡ýý}@»ÝF·Û=sÍ–(Å7ª¡ ÍÄ«V«(•J(‹¨T*CŠäò‚«ªP ¾é›~Žé;XŠ5 î¥Ë`U:¥ƒ…+¥ZmX!«ÕÄzÉXe²¥z麸Fh&/E”Ls¶(~¹\†¦i0M3ô>ƒÁq_A·mÛ¦ëº?Ë›¢`%¥çÒ½‹jã–¦H’t;Ýß›}1þ;²ýÏEuŠüÏ "Ç’$AQ¨ªŠZ­†Z­EQüÈW½êUkþ ŸM(rêyžß— ÈüÀS>ŒO}ꇮ?ÏÜ4Y"D¥2ãä8“Ž…»¢âœð<È l¬2‹ fêŽ:· q.‡å9Jܨ”‡FË0Ëafƒõøø( ~ ðC=„v»K—.awwwÖ—Ì,tÓÚ m{ ¨F¦ir*“Z‚i»W¯þ¾ã;îÀ}÷ý.Êåç#jæêÜétÆ>¾ªÎö=Èy ¹^ãÆÃ‡À“ÒÁœM’ï¸Ð i@È«ã8xûÛ¿ ¿û»_†ûïþÚ§e9ǃM Â3+Ó ¥§™¯YíT™f_%ÔmÞôFc¸>O–žzÓ4ñþÃ×øÑQê¾M=‚±G‘,ФSä‘'#‘š¡9Žã§Öƒh%¥ÙÎ CdØ ¥ÏE ¡‚]]%Iò›΃ªª¨V«kÍT:k²],º¸reð™É1¯ëº "Iƒº¾ ¢Ä×Ä$ÏY’qêä–cšÐl ¶(š_JT*ƒl(Nߌ 7á#çbð‡p¿õ[¿…Ï|æ33½×LÖN§ƒ^¯ç§¹xñ"ŽgžÃZ¯×Ñét† àn·‹J¥â_D”´,,k °š6¾À8(xR=jœù«Ìæ“„|Ï‚a 6Ýà\<Ñlýë ÖÐÎ µ„ÏJ¹¸ˆPdW±K»Œ¯ Ǥ4ƹDE© w8'XkJߟmÛþcd„ Ù`´S’¤¡š×àëX–5”¼”ÖKk·,Ëï„¿ ©™gM¶à~W¯þ:ßÅ{Þóý¾“f›RJ»ªùàÜɨÎïLº9k2N)é¦9ȼ¢,™““ѽ<œ~.Ë›é'ggê)àºîS’œ ’$ù=EñÇz’3QQ”!Ç"Õ¿¯|å+gã9W ë8nݺ5ÓóÛí6ŽŽŽF6`kk W®\A¯×Ã… P¯×# åy b}IBºêª8éË^uó&ý$%ß“ •tIŠ>†Õ¤pÝÅ•œr9}Í•&‘åJ4Êø*¡ñäkó‘B¾¶È¨Õj#k°‘Ÿ¢(~$–"´ÁcŽãøéÀ“Ð4 wÝu×Ò2~4Mó6ÑçlµZ1O|e›š]9ŽãGD(zZ«Õð»¿{‡‡9Ôjßf3Û¶o7÷Žþ òÞlŠë!Šry´á “>6QÆã ëƒ9ìÀ Zåx̲ß-ØÄ.H­V2Hƒý‚¨ªêgæ¶mûûGµZ[_ 6îËL+Ía=88Àþþ>r¹€Aª0 ºÇ¡×ëù#3‚†n·ÛE»ÝÆ•+W¹\»»»8>>^ÚÅü~«ÕAJWjµ$Iò~‡¡.wÌÙ%Iù‡ã §ÊV*B©H‹± šÕÌ ¥úsþêI£Œ¯×O GLƒ(Š2¤8aôNÿO©¾Áó©Deš¡Hʇ¶$KBQœ†ç>öÓN§ƒ\.‡ÃÃC߈ÆÁÁß )˜?ãÆ Ã†o>Ÿ_Z}¹<ê«£Óðõi£i³Á˜³GRò= ËÌ÷rœò‘c˜?*jƒÍq3V™å’F_Ô )ø»m |ÞT0Û¶'F5)µ¶R©ŒmdD#D¨á¡ª*vvvb§øžð2•M”ír¹ì+®5ÛÒu® |ó7žG ffÙ›7-erÙDŸF°;(£YK±mےʲì; Ã0ü1š’$¡V«a{{Š¢d:fjÓ¥n·;$Ì4‡µV«¡P( P(àÒ¥Kxøá‡cGWÑív#½5“.Š^¯7öØ3Ï<ƒO|âh·ÛcŸã8ÂCfÚæêº.ŠÅ¢Ÿî4­áÏNL7Ýnׯ_Ÿ¹à;.«oøÜç>皇àÌOEJ¹ac;]'Ÿ4³qŸÉóÄ5Üj‰Î|Ý‹—J»ÝÆÓO?½²×Oj_–%F<‘bS.ÇoÐGý ŠÅâH3¤I× ï ¬AƒVQȲ¼´¨ièt:¸~ýúÌeHqHëþ½”N>innXo)‡gB3ëƒöïi25/›¼Oƒ.êà>K†eÒ˜¦‰íímß¹yzz ]×Q,ýûÎöö6ᘤZÓjµŠ›7o¦ÆX%|Öý;V„õèèÝn…Bªª"ŸÏÏîv»8::[À=邸uëÖØî3Ï<ƒO~ò“¸víÚH>>1KÍA-Ýø‡ÿøy?B;Éf¥èUS Î7nÜÀõë×ñÙÏ~v鯽*ù„ÂC9ÿóÌ<7s]w¤V. P$xž'"«)[~*¸víÚÊ”$÷ðUž+¼³3PàƒòH]vÃÓZ­Ó4ýšÀr¹ìÏ7fLRª.ÍMrŠªªê7¶³‰i¹“ ƒuÙ¤yÿžŠŒ:ŽÇqüÌ0Ì砑K¶-î A•NÓiR ãž)hÿž&Só°©ûw$i8£’š<¦ª1k•†ÊE¨$ltRj/uˆOƒA: ÒÁgeªÁºµµå¶mãøøNù|Þ7`gáøø¹\ÎosÜétpãÆ ÔëuìîîNŒÒNÚä_ö²—AQ”©9öQËRI($QÅ0 ¼ð…¿Ž«WïõOkÒ4n6“h3]Å ¿UÉ7Ü}÷Ý Õ„Àr¹ŒF£±ÖqˆÊ‚Ç4çÑYe쨂EIz_Ô9žöx]ŠLx/÷<¥RidTÕžœœø×9;ÉÃ= j`Ôsóe®ë¦*")vww±µµµô=<Íû÷¬”ËÀ?þÇ_À¯þê`¢5 Yž'œìaŸ —5%íß«pllâþ$ÜX2ˆe æ©ÉÈ8eÜPiGø~AoÁQ04³{œ1JuªYa^|¦Ö`TÕ¶m¿ÃØ,Æëùóç'?wîᢋ#øÿE0Œèôßq‰_ù•ßã8øð‡ïz¼Tÿ8açèêÙ%Iùž¥—J%?B“dñü$â:Ãf=¤UÆg…uUJLx< =¤\.ûÍ+‚£hjµÚHdTÔŠ,†8F&)*“¢±”þˬ†M‘mÚïMÓÃ{ÞSñeƲ†gL›9¦ƒÏ¦Èø8ÄÌëèlJÓ\o0‰Æ–ǽˆ5ŠTÝT«Uhš†b±èדH¥n–4sµ *»N¶mãèè—.]šè¡¡ºW‚º ½2…Ba¨#™mÛ(.˜hNÝC£ˆÚ¬k5à=ïùSü‡ÿ0z°Ñ˜\g·„ñvLFIJ¾'á8TëiB’¤Ô¥‡‘¤A÷¾qŸ§\æTà¤H£ŒÏC©4ˆ*³kµEšCH†h©Tò• jp¦Z­Î4BfÚµôÈ3ËgSd[Q€““^ùÊmH’Q×å ÌæÈø8t}Ѓ ¼UºîrƒI¶m£\.CQ”‘l5Ó4ýqeã²f*• J¥’ßKDç´†‰,ek>ŸG>Ÿ_Z*Àþþ>öööÐn·ÑëõËåðàƒ.ôš³ êÕ«€ïüÎ?‡ªŽ¾¯$oB@F1ëÌ8V!ß“ 1/†aÅJMLª«ŠÂqmé™ô²nŸªã›¤ض ˲àº.Êå2€AIrj‚Cd™æYj¬”VÒ.ÛøÀOâßý»ÿŽ/}I<2)+Œa‚dCÆG1ŒÁ¸¾p/ Ï[^-vpž1õ)ØÙÙA¥Rñ³jTU*‰B’$´Z-ضÍÕÌd°¶Ûí!ÏL»Ý†mÛÈår8þü\…ÖQFn>ŸÇÃ?ì×`-£€ÛuǧÒ|Ê úéO¿¿ð “Ç×XÖhZ"E^¹«¬O¾'A³Vd¦þR5ƒØö ~<#ãLŸÛ?S¦“¡V«¡ÑhŒ½ft]‡e‰†6Mö l$Y“m@ìºÞ@µZÅ·~ë AÎÿ¿½óqä<ïû÷l¥ršˆ åËY2×®ÁK v€ê¸8B8ÀlŒ•„lÂ5М­mÑ’õÒD&‹ÂâMÈHYdÙC.ˆ³6ѹ6jï‡4A"žwE14Š­§ÑR—4²¦âÉ’%ÅØþñîK‡3äp8äüà÷Òqøãî3Ï<ÏûüâôâDeŒ±“N©iRÞK¥Aoëë§±d_Ã0`šf¿”JŽ’Q¥ŸUS­VQ,ÑjµÍf':ªvè¬zÓêë:ªÕ*ºÝnßð•]e^»L–sf%•Jz‘Œ‹°¦ÓëÌI—N7ê†/ BÜZ¾¨Õ„)ì­ØDgJ¥áÆK†18§áõ$š,BƧÅ4›ãÔ{»ÝF6›»ÁS,Q«ÕXWº„DQ¶%¿ò+/àܹ‹}}oâA»„LC”e2Ýj =^,ŠÿÊ}CÙGÆê¤jš÷ÌÇ hšÖïÀ+çXf³ÙXd°ÅOkµZE.—jƒ-›-íîî"•Ja¿ße,ІûîŠÝÖøÜçþo¿}mâg*ÊðP«± ‰VgUv¥Û‹Iqµœ&iµÄ )&þ6‰0†sÉr¹Ü¿Fòù®â _øÍ¡ç9þ‹$ ©Ç×Ö­z½Z.-2Mo¶y­VC6›eÖL™è°ÊA××®]ëÏ_êõzÐuÛÛÛýçÖ××Ñl6GÒ†£Â¤ÁïÖˆÎ_ÿõßãÒ¥{ú\y´Z"JË› ™#G3ÊÙŽq⬛;…,Ip¸õPU{{{ØØØè7Yò5ÛuE’‹‹Q©ñÐCê?Ï.À$I´Û"ZZ¯d{ccÔVªÙ0éðÙ¬(j·ûy´Ûm¨ªùÆ”ËÊ»&½@×u …¡aÁr6õfôpã qÛ,×4ílGEüÛ4M<÷Ü<üð}ž?»V«‡ yB掌"Idú~œ×…›¿8]2]ÞÚ$#n× Yn4MÃêê*òù:ŠÅQÙå¾ I Æpz{±(äÛm±ÕQØtZû,òù<Òé4Úm6}$ÉÁ0DTÕ0D†ä¤Qd’r¹ EQ†6"e£%6SŠ7žVé¤:±¾¾ŽõõõHFV%ã²½¤1¯iÀúúÿÂÇ?þ¦J&$*Ôjâ¿Ö}#UUé°’¥Æ:`Þ4Íþx6™yÀëƒÄ‘løò—?EQúó&¹ÙN’B¹,dºXãù¼P«Õ`šf4M>Ÿ‡išýof›ÅO+ jToÞ¼ ¸|ùr¿†5ÊŽª¤Õršm5æMxöÙóø¥_:ör ñS7Häd™i·6kkk(‹H§Óýþ„Ä Mÿ½~½‹Ÿþé_†¦1˜$iÔ³ªªPUGGG0 ÃÒˆ¬ŒjµÊ> À“ÃÚl6±¿¿ßÿ÷þþ>677Q©TÂ^ÿDTU<œVk÷TE‘-¯…qÃÔv7œ”»¦i¬Ó KO6;HãÈwLøð‡oCÓþ_øÂ{ptÄfK$YL3&Ò4M”Ëå~5ŸÏ£^¯cuuµß\‰ÄŸ‰]‚á ®¯¯CÓ4hš†õõuìï‰"¦9¾~Õ:K6ŸÿzBâkXɲ£iÀŸýÙoÂ4MFTI"Èf¯}í+g³ƒi³ø"kTg¡V«¡T* EQ‹Å"޹A™ &:¬r\Íææfÿ9Y•£n¢Œ¬íp>¦ ó­–È•çmGd +!d€a¿÷{Oq¾*I ¥ðçÞ?½rû<eU\øêWñCwß½øß}N8õðYÚk«%þÞ†1^§¥Xœ êûÚmq¤Ó£;i^>_ÓðÁú§`Î;&ÈŸ^þ‰²Y೟}üàÃ^!3!kW¡4Í{ò!QEše­Ö æSÒÉn/—Ë(‹œ«º¤xN –t:ܼy³ÿïË—/£P(„}®ÔjΈ ÃXîÝÊz]8o^/|Ã]Å=ŠY* Íc7°5MDT³Y¡¼Ž—¨V…cm_c6+"_ÓþýªU±UÅÝ/¿Œï~øÃóÿD>ïÔi/&5¬šæ¿Å «%gÏuÃZêÆ8ç_¾ßk·'jµAl>/>Ëïo²„«ÜœTÕñóÐC/âî»ßöÒ™‰v»=ÔdiY“gH²·Të8™.³’:«Ë‹g‡UUU<õÔSèv»CÏïïï#“É ÑhD2MØkÃ¥È"‡Tù5‚¥³h7ÄóyqÌ˸ŽFÃÛÚbQ¤ÝZ×*køü ¸•®=Lîw£!î§x¾Ôéà-ËÆKÜI§G–X¤Ë˜¦Ø‘©·å²÷ I‹â³'9¬2=Ýigk²¡R:휪ëåü¥³[,úû 'J%üÙ³ÏâßóKÆ©&¤Ó wß}5×!.ÈèªÜ`Ë>$!“ tÙìðX>û-PÓ´¡n²œxêÜétP­V±²²‚F£MÓúF£••\¹rN'ìóÁÉÏ“Ýö"O­6¨>÷ƒ¦ ƒÝÍÝsǽ_Žß8>žìp¦ÓÂ9°nÿ*Š·÷º!; z¡ ùÓk‘Q%‰[S±HašB¾¬c¹‰2Íg¸,Êf©Ánï•s¬üDì[­A€Ÿ÷Ë5hÚ ÛoÔÿfÂ>ÉG–°Ë¾k†üÅ_ü@|6' q@UÕ¡ÒŽ F86ÒüÌf·}§ÊÆÆ¢oÓ¹âÉaÝÙÙ¢(ØÝÝ©‰³>¿³³öù ašÎ¶o,VYëypà/-P¦ð¸ßÝd ¯Ó{ËeñÝM½*ŠRi´ëï¸÷8nêÙc §{ØV§9ÑB:«¥Ò°|+Š÷ñ1†!>cœ|É;r3&öÑ•›IÇdz¥2ËôvZ ¾°îÊQ0 !FÏ=w+‰5†aŒØ+´ÛIܱWI[]ӆ˛dF$õ8™è°v:t»]<ñÄc_·¹¹‰n· ]×Ã>§>N‰­Í æN­æ¯ØD¦:¥Ú-4·ߨ˜”ZÁ’QÝY"£^0 Ì ÐXÂY’¨ª:‡UzÓbuVíõ(^V9ÿ·^Ÿòkw&eTµ\ïõ“j/£²öÑ2da¬®Š}©Þ c8Ð.û²?ÿî°—JÈLØ{0%˜$ûBeÍç‡oéö ²¼LtXu]G&“A&“û:Y¿ÚëõÂ>§±,\ø½8˜VÆ9«ÖF7³ê%òãª×½5cjA8~I¨[>k @PÍ$ ~^ı:¬¦iBUÕùïHJY†qΪ<‘q«Ìh4DdÒKšºÝ)u3fo3°BÄ0F7¤_«ÕÎ:I Q{à×Ã^.!3aßx4Íùî#²ìÕ?ùü@·[E>‘d!LtXS©îܹö:}á´©ªêâ„?›.Õn»;«Àp¾›µšÐÓã¥Òø:Öq4 œB¿¤HŸª ÿN«jù,ÈP°4éÁr_Ä4M¬­­¡T*Íßa-•¦ß)—ÝU‰u6‰Y3*›ù9¿tzúQN$R´Ûõ&U^>/ëV †ÕÕU|ô£‚l–p_œzøé GHÔ°·ž Öò&™]ÀÚUxpXs¹z½ÞHw`;²áR*• ûœúØ›,4VÕ4}6;¹Kh±èîûiþ’N·nMn„S8KCW»3Y:{øqZ³¯ýó–dVTþ(•J‹iýžÍºM{åà`²Ãhmó*Ñ4á©ÌZ3Jb¦ ÖlVˆ…Ü•7 GGG(•Jxæ™áÑG3³}!!ù^„øDFSí´Û‡•ÑUbœÚËåP­V]Ó}{½šÍ& …BäFÛX/ˆv»½ØNn‘"7òùÉÎæ¸”ÉEÞØ ˆˆfÞòïiqj¸duZ§ùLQuã"ÝAXÓ€V«…t:½Xwr.gEŽ2²OP#_H¬±N¹’Îí»õ¥R ÇÇǬ}Š*²ašl^&ÿˆ««À¹sâaGÓ€{ïï[[Õ .¼ôRØg2Wœ"¬µßÇ–Ù5>áƨ¹ªªB¶år€+ÆS—àíímt»]\¹r‡‡‡ýhk·ÛÅáá!®\¹‚n·‹J¥öùŒÅ0ŒÅt³Î[˜65 ™èø¨…hLÄrT'±Θ.ýVÃp ¯]›òÜÆ!Çw­tþCˆ…±xå®(Áwñ²qC–k:0 ÄDªXMÓ†¢Qì*9Ór7ž4M<¯ª¢n¼Ýü[>ü G Iý!w!ŽŽ€ÓSñ°“ϯ¾*^st„šMüß| ì_q®˜¦9$ÇKâÏD92­V_6%K¹¦¹ÊëÉŠ¦‰ ¿%Z1ºé(‘³Xå~»Lf†A ‘óååõãpm|à·~ w¿ñÆT{——år9ìîî¢Ùl:Ž®) ¨T*‘‹®!ؽö¸¼ ÝŒ'§¡S“Èç‹Exa£¬ á$n8€»Ãè…¬íýG˜®ã¯†a‡×N£)¾n˜gç6.°(<©âü/l\Þ?ÃùG”…×zLŠ°Ê›ï´Ž4›LsT”ŠEq?4 ƒÆÍ44Â:¬×Å=ÊIwhš}ÀóèküD±ÓéÁûwÅ0ŒNÕ8òÞ¤ªƒ/6“ªŠ~ ÒÆ²†ÿ†_+ëÊeçСiŠRû{TUØqrlà¤1„ ÂÍa=:[h¿™e¥\”Zù½wÊýÙìÀßQUqíŒÉý^*…÷¼ùæT_åÉaN«]£ëz?]xRa7ä7GW×u¤R)ߟoUì¦iÎߘ—JÎ:×QQÜwÌäø™ikHK%ñ¹Ó^Ì2÷³wϵ;‡i Ì&–10>…×J Â!=8û;¦‡ï“(Ž{?~/>rñ#À“æ-ß©4M[\:p­&dpœÊÙ"ì’X%ã'ñ–âW«iŒªzÅ0Ä}IÞ{ÆÍêž–ZmúÍÔ²hÙvÂa•‰¥Ñ²ÄÆ“¨“Òr ›lO›ÍÏÆÆ·a ;ãl-''X¶¿u³9³ÙÁ$‡rY¼>g5,·FRíÔj@½®¡Ñhàˆ¶Ã|GäúryØN+—›^ÜÍÜ^s*‘Îå4eˆƳ©Ÿ=6àÜXI~ï4ŽÎjÃu¨«éY”|K²YyïžÓDùFCÖt@§Ô'‰”qûî5I ‹–q`°âÆÂẕë4Ýtt$ ‡[·œ7†ä=MUcŸäCÖ§ÚÓxå܈yecäób½ù¼Ð/ CIU…±cF{8v²íF6›E£1¿®ª‘ÿùü!Oðà@ÈŽÝV“õÍÇÇâqt$nzÕê๠°M(aËøžËt Ã0ð­o}GGGñ×åvd²SKnÈll šÑM²çd™) ¯ ùpº_ÈûÊ­[ÖÖ{“£+Éfç·ÑéÀV¯t:ôz½~ƒ¦T*…ÍÍÍ~ªq·ÛE§ÓÁææfÿøúúº¯Ôë}ZUÕùìÖ4âìugcCüѧ?Œ:jSýpvëtåæ³'é’³Ô[Ž«ý&;KNñì3kgŸ;Ë,Ø€Y¤|K¤Ã:ù–ãdêõÁÎÚ¸BUJY¦­“ĆŒÁmLGYO:͵# ˆz]ÜS¬‹lPd7üdiçsp0¨’Íi"LX²í„¦ixûíŸì¥=é~t¦9Ú”ËÍË– Yä.ÔÞ˜yéôð‰Ëè¤95 l7 ÷M—_ü{ì±äEVånëÞžóF¡t<«Õo 7/^tŽjÖëƒû…×ß+æ×ËÔ)Á³"ka­óZONNˆ Cþ¿5§>—ËMœëÄ«¯ÿ{.ax¿ù—˳íP”à¿a’ ÷šÑ¦kÆ”÷ð@8È{QÖUÖ ƒY2÷”³Ïª}n„tÛ"å[bÀsÏýÉ|2A¤T¦,8uLíµ?$q„!ãÀ dÚ‰¹–|øEŽk›šòºÑƽYYûdÑ×f:=¿hnÀ„%ÛN˜¦‰sçVû&C6Q_ÖŠZÙÉfG=mëÅÌÍÍ…¶Œ·ZκÜ0 ¼÷½ÿ¿ýÛŸû'òŽ&ëf{‰öõƒò?7Ýk÷!ªÕP#™Qeák*•ªsív»h6›X__G&“A§Óq}o¯×ºÈ¬¼ñÆxùå—Ñétëhºí‚WƒCÖ_ø5PjŽÚ„cyŒéRj'ùÔ²ÓÆÙkƒ,«bP‡*;ú§\¿Û9•0u©n·‹^xßþö··£iv–MŒ¬úÚÞp$ŸŸœŠ%ñÚé°Î‹Eêo7LÓÄ+¯ü«¾-,ûkÍÙd¯Ý.²©‹”ç½½a¹÷Û’¸"õ÷$™š…Eëo‰›o·Û8ðÓ„tÞXgO‹ƒtôq6=»EÚàÓ2ÑaõZl=q¤ë:vvvJ¥píÚµ‘Ô7Æ)ùóçÏ#ŸÏ÷/:©c%Ú´Ó¶5ˆFEAÙ³Fw­ò/×äÕi•N¢—ÌekÇÝ2²õ;f9•,¦wvF*Ó›S¶ÔöÊ<ä.\¸Ð—o+Õ*P«éÈçç¼c-Mct(âT*•~‡Çy°ngœ±nÆHçú©°%ù¼o«Îá—‘BFƒæ¡Ã­¿ÝÐ4àÃþ.€ï0ËÀ³­›)¦)z‹£zÇÍ“'"õ÷¼F&…¡¿Ç!3 #WÖ Uf†_<°¦Kö4ƒqT«Õ~½ýâXYY€¡|ùn·ëëµêÖ©wß §Õi„j IJޤ—ư~5Õ1Ꜫ˜¾~vÉX”|[1ƒl9©;=úD–Ž0d|¦iúsX[-ÑÔB%·n±{ɉŠlÿÝßý(eX϶obY‘ã,êuçN½$„%ãíöèt"hµZ‹K–é¼µšè+cíªî´+º·Çôõˆ01Â*…:(TUE·Û…¢(#¹ò…B™L…B‡‡‡–h©Š5ûŒš)ð5îCFí~€l.à%Å«‘ú:«ž×Îö¯”×·¬ u[RþR›åoǸqö9ôU\ C¾/^²Y¦qy•b1â5ãÆ0Ú´Ô„£ÃÇï‘øÒñkkâCY_DÎC¶%2È/9o¾ù‹ÿ1ø“”cÇüL* ±'Lwª&D:ðqÐóheýµµ\Î!-Ã`éŒÆ†‰k§ÓÁÖÖÖPJm¯×ƒ®ëS7ÆÐOSsšÙ*¿£R©`kk«ß~;•JáñÇ÷}’žçó )rŒ:y²¶Ãë…ÕÆ ­x–Ôb/u+*„SéäK¤1»“™…húT†hÎD C¾Ói»aùµv+µ#åŸÂÑáî"ë«áR«5˜_GÈaȶDŽÇmµÄ~x.÷Æ|öQjµñ÷’h”q§j"Ù Ц¨ÒÖ±Ö’f³b³›“±ÅWÓ%Y¨=u](Ä…0)Ç=—Ëáé§Ÿî_X~cUlzÞ}O§Åõǯé<{3Ng¹ì½y’ áàÕ!:ïj#^ü0n$ œÑÛë­Kl!˜ZÜ"‚íœ@%ßV„8zIi ËG;4dˆÂqMsW»ªªN_òÁ&HÄ0d[¢ª"®_ÿ:L3 ›­œ) ui¸“¥$LwÊ”ñ¥¿'áf«ÓY5¡u žÄ45±nÈkÀs„û_þ%ýIñï4ÎRaφ_{5t Òg Òƒ øKÍuJGã컪éÀ)ßOæNò ‘|çw¼ïN‹¢©†Ý`1 áÈ–C–– drî–¹Õh4&µ7M¦?’ÀR¶¡z­ò}ãÆ»ñ}ß÷Àô$‡\Ú»øÞ ¹Ó!‰A˸œfÇwÿ7äìë(È!¾¬éRÔ(•†E zÙ„@Q€¿ÿ£ƒ—ðÈwâ­éÓǬgýìß&¦ž:µ£[‡p˜k„¹©”X4 ¸ï¾®÷ ™tZ\ö¬ƒrÙ¹Ñ! ^wvX[­EqO nµÄ}, !Bš’7ßü>þñg½€”óq©„„ˆ[YG #Éq-°Ô#‘$ÖaÍfzÛÓ!weøúŸ;yïùeà=ÿЦðü6\žW!œÈi²©ý8œ%ˆÈnƒÆI$q¨*p×]Ó _F>?w@(øtš;’$v4 TÝf}llþà€)$Ò‹€¢˜h4¸xñ"^}õŸúÔ#“ߨn‹®{†!êõööè°’Hâæ°Ê‘6S¡iÂnq*Kt å’ØÙ”àY‘ ‘rà)Â*we~à1àú×G?"RÉÚmàK¿ü¼uÜ5àE-bº&Hª‡ïËiÿüÏÉMgd»vEÖÑÆ†¨ñÍ ˜ L"ŒSsë‰ÑUÓd1 h·Uhš†£££ÉúÜ4…ØåšÄ§jº©¢«ÒV‘³²³Ya›[ËA8+8ÑxvX­Åz½ÞÈs’ GàÌB»=찎ž#óOÿøÒï ‡UÎ%DÓ¤ ˆÈå8‡3ñ –¬©mÑPeÌkÙu›¸°·Ôj/"› $íö ‚jmåžÍ …Ï]yQ Ãy#}bíj³‰ ™²ž¦i(‹ÞœÕµ5aà°y‰1ž;¼—ËÂQ­V‡Ó}/^~¦qó&ÁLtXWVV°¹¹9ò|ÅØóÀšÝè)údÝ•ùÅw¿yàÉá×É®¿“lûi"¨%ˆ¦H²1³2É”hš†Ò$ÃEÓ†½5\EO"L:=]UUu|t•˜ Ç^†¢×²Œj•%$V\¼8ÚûËs„UQœëRíȹª‰f¢ÃšÉd&¶ÀŽ"Ò~WUur:°a ù'ï^v¹È—©¶[iÀ{ݨŒ ªs[kNk "¸çÙªdé‘3û€ ›2Œ4‘#û„Yñ4 Y$ȲSÏÓ Øo€Ä ·²RO›í€wy§³šhÛtÉšBæ)ÂjôF§ÛIC8“NÍ“Z>¬@¤C8ª²‰kÛÇg‘¥@6ú8gØ.ß„ÄUmj­iÚøQ^go2TÍ$éÈÊ#;Ž)Á¦IýMñì°êºŽjµÚ$œÏçQ¡VÿÕ4m|„Õ}2áÍIÌC8—ò”¥ãªb¶šÓ4†kZÙ3„¸ ("Ur↠Ójªé‰µOn!BNÓÓ4m¼ŸLÓïHÛÓ5øëÊ[° ] ²¬Š~ƒæE±3ÂJbŒ}B»Ýö^ëGH„QU±ãj¼¢+S¹öR ñM­æœ%3b›7ƒI^1 Fd—OëÎÎEÁõëבÉdúÏçr9¬¯¯cww—/_ÆÕ«WÃ>ò;qÆS>?ÚÑÃOéÓD44 6N" ¡\ö¸!°žÄ{t5ðAó„„„i Õ¬ªª»ÃÚ;'À7KIDAThp<‰5ª:ZÃê(óš6}}¶ªŠ4œr™Žk™è°v:ôz=<ñÄc_÷ÄO`Ýn7ìs*ðžhÐÛÑàÏaDduÁFX qAÓ<¤¼«*tØâÔ¬Cv&$îÈì׫ܭa7l’0eÞOù’¢ˆ÷9yÅ$QLtXu]G&“Ьè§Käñ“““°Ï À  4±!LÃ%‘GŽ›¸!S*Mn FHD±§˙ڞ:¿³;6‰8†1èì¸ ÃrsÜF£Ž4ÎóÛk#›uoCLÅD‡5•JáÎ;#Ïïîî"—Ë…½þ‰L=§6‰R?OLy'$ÆhÚp6»çè*ÓÃH ˜¸±Î†y$æ¸eÉŒàæÙzAQx,Ö\.‡^¯‡N§3öuò¸5êÙ¬xLL—”­„­äÁ+‰<ÒŽ™:åQ,g´OU¿Êë‚DktÕucVs¬{.¦i¢V«¡V«aoooô…~e½ZÙd$ÑxrXs¹šÍ&z½žãkz½šÍ& …B$¢®Ù¬Ý±÷LSÜ ì”࿆•a°’T俣Äs‡`¦“P* î¸ #e˜4$ÆX#¬kkk€ãããQ™O§ý;¬öI$žºooo£ÛíâÊ•+ØßßG§Óé?šÍ&{ì1t»]T*•°ÏgUUÝ#¬í¶óÅÁñO$È]K× ÃÝ% ‰1Ö$˜‰³W­Ða%'›ÙýL°v{Xàg‰8„­"Ë—êö©·ç 9ã.//Êår¸víö÷÷Ñl6Gޝ¯¯csss¤1SpMskŸ]ƒQCH„ÙÛsHyo4D{÷tz¶ÝJB"‚uÌp»ÝöÞ˜»í$âÈ”`Ó4…\—ËrÆÐÝòAHPU•åKd&<9¬€è¼½½J¥]×ûÏçr¹HÔ­:¡iJNyí2ØžC°~•ÄETÕ–ò®ib;Sp³†Ä{ýjÕKÇk¦É“Ðh "¬ÿõÁ…R¯Vµ5àø˜©À$ö¨ªPÇ¥Ò{œxJ ¶’J¥P(ú¨:«’‘2Ó77ÇY $&ŒDXå ]¥ÁCbŽÕ¾ñÜpÉ> ‡’NR%àK_Â.ó„YÎA€ªÌFXɬLí°Æ dž4å²0æí;=ÕÓÇ †:«*t’(¬£T=7["$&ˆ’½³,Yèpn6I ¥’0·'n6¶Za/•ÄÏ)ÁqñC°¬ï+ÕE­ª¬2d!Ò³gB"ÎÐ VÑ)ì%2eR¤¿{œ¿ ðZ ±À0ÃМ»¥² IR Õßíöp³B\H¬ÃªiÚ¨Ã*£ª5ç´:§$¶ EXe£%B‚5³WUÕѹ}nðZ Ç0D²W>Ï4I’L CĈêõ ú»ÕbVñDbS‚MÓiÓ>ûo@tVI¬á V’ddUϵ«„ĹCÙ&IÅ4uIÖj‰0,»a,O„U…pXYE‚ç™”„Äk:z’$ä^ãÏ#Ël’@ä ‚±ãÈ àˆs$‰7a zf„0Ô!˜õ$a¨êÀaeÃ%’4 XYùG<úÖ[L_'‰D:¬š¦:¬­–x( û Ï$Öaí§Ú˜&°º (àŒU’†šŠml„½BÅ4…/ÓÞ§Ê&X[ {ù„ŒÅ4Wþü‹xéÂ^ !sÁ0„/ú•?üC¬ÿê¯Z¾›­ÕØ\ŒLEbÖ~ k£üèt&$¨ª*ä[ÞIŠâ3ºÊŒq XýæçqÏÇ>öR i–hš†ÿö®wáÝŸþôp&ÁÞðê«Ì. S‘X‡µO» üÃãa¯‚ÀÉçóƒÙ„$9ÎÆ—ÃÊzWqòyàotðþO}*ì¥82ø«¿ó;¸Üë &t2‰tXûó)[-`­ ¼þ}L&‰BÓ4œ÷»E±o$øJ¶¦QêUo½õ~衇Â^ !“Ï ³äƒð¸k{;ìå„y‡U×ut»Ý©ÞcÆ ú„’˜·JHñ#ß’ýå/ÓY%‘ǯŒûNfŠø`ا0©T çÏŸÇùóçÃ^ÊÔ¼ýöÛ¸|ùrØË˜ŠW^y÷ß?Î;Ê÷û‘oxøá‡ñ¡}(–²G9„¬¼òÊ+±Ô)?ò#?Ú÷ϪÃ?ôàƒøçŸýYÜ …Ôá‹å¾ûîÃíÛ·ñÞ÷¾7”ï÷#ßÔß‹'îúû¾ûî åûiƒÇ‡8^›ÒŸVGÒaÍi÷žÉdŸ¿té.]ºöÒ}Q(Â^ÂR®=,üÈ7|æ3Ÿ {龡œ,–°oêðøǵ‡½f?òMýM¼öïMýâ¼öi‰d ëÊÊ €á´„n·;Ö˜'$.P¾IÒ¡Œ“$Cù&I†òM¢H$ÖL&ƒB¡0T,¯ª*ÖÖÖÂ^!3Cù&I‡2N’ å›$Ê7‰"çNOOOÃ^„º®ckk ™L¦_ä½»»ëZßGHœ |“¤C'I†òM’ å›DÈ:¬€(ü–]Æ–)O›,”o’t(ã$ÉP¾I’¡|“(i‡•B!„BÈòÉÖ¸¢ëúعSº®o5îø¤÷yA®{‘k'óežòíåxPçôÚ(ßÉaOª|/jíd¾PS¾“õwxk_§dfžþùÓGyäôÒ¥K§—.]:}ä‘GNŸþùþñ“““ÓŸÿùŸïòÉ'‡Þ?îø¤÷ÉSO=uúéO:u/zíd~ÌS¾½ »|Ϻ6Êwr˜EÆ“*ß‹\;™Ôßá¯ÌêïåoFX`kk …Bš¦áÆ( ¨V«ýã;;;Èd2ý㺮£Ùlz:>é½AÑét°¿¿?ôÜ,ë^äÚÉ|™§|{9Nò=ëÚ(ßÉaOª|/jíd¾PS¾“õ÷’ÈwØsÜyæ™gN/]ºtúÚk¯õŸ;999½téÒéóÏ??ôÿ’ßýÝß=}ä‘GF^k?>é½AñÚk¯~ìc;}òÉ'û;<³¬ÛËqæ)ß^Ž“|Ϻ6Êwr˜EÆ“*ß‹Z;™/Ôß”ï¤Cý½<òÍëŒär¹‘Vß'''€T*Õÿÿ\.7ô™O>îø¤÷ÅÎÎÖ××ûâ'­+ˆã$ÌS¾½'ùžum”ïä0‹Œ'U¾µv2_¨¿)ßI‡ú{yä›댤R©¡vßÝnÍfëëëÈd2c…£×ë=~ëÖ­±ï ‚ÃÃCt»]T*•¡çgY·—ã$ÌS¾!'nò-ÏÅïÚqm’Å0‹ŒO’ƒ¸Ê7ux2 þoíd1P‡³ö0 Ã½^Íf>ú( …¶··ûÏ»qçαÇ_y啱ï•n·‹ýýýþZíçãwÝ^Ž“x1ùž·œŒ“ïY×>ïk“,?2>Iâ*ßÔáÉ‚ú{±k'‹‡ú{qk :¬ ë:¶¶¶ ë:®]»6´[b ÇÛÉd2cÔœÉdf^÷áá!R©TUE³Ù„®ë899A³ÙÄ… |¯ÛËqæ%ßó–“qòÝív#}m’ÅâWÆ'ÉA\å›:<9P/~íd±P/víaA‡5ªÕj?Þ.$2/Ýžïv»}w|Ò{gåòåË®ìûÞ÷>ßëörœÄ‡yÉ·—ã³0N¾g]å;Yø•ñ¤Ê÷¼×Nõ7å;éP/víaA‡uFTUE·Û…¢(èt:C@ìd ½gmmmâñIï•B¡€J¥Òär9¬¬¬ R© ŸÏû^·—ã$ÌS¾½Ÿ…qòÉd"}m’Å1‹Œ'U¾ç½v²¨¿)ßI‡ú{yäûÜéééiØ‹ˆ3ÍfÓq~hš`®ÉdÐëõJ¥†ºš;>é½AŸ‹®ëØÝÝyÝ^Ž“è3oùör<Ès±Ê÷¬k£|'ƒYe<©ò½Èµ“ù@ýµ“ùAýþÚÖÑëõ ë:ç¼ùqÇ'½7ªë{ídqÄYNâzm’Å2‹ÄU¾Ã^;Y q–‘8¯,êïøË7VB!„B!‘„5¬„B!„B" VB!„B!‘„+!„B!„HB‡•B!„BH$¡ÃJ!„B!$’Ða%„B!„Iè°’@ét:èõza/ƒ¹A'I†òM’ å›$™$Ë7V([[[ý!Å„$Ê8I2”o’d(ß$É$Y¾é°B!„B‰$tXˆ Õw»]BUÕþ1]×±¿¿?·ùݽ^ªªBUÕ…¤ t»ÝD§(aÂ’ñ°ä Œ/Ôá$ÉP“$Cýoî {ËÄÖÖÖ×סª*r¹: …2™ :R©šÍ&677Q©TÿîJ¥‚«W¯"—Ëõ/Êk×®!“ÉÌå|u]ÇÖÖEA¡P˜ûïKÂ',C¾Êø²AN’ õ7I2Ôßñ†ÖÓétðôÓOcww•JNpýúu\»v Š¢Ìm‡çêÕ«ØÝÝÅîî.ž~úiÜsÏ=8<<œËwY/”ííí¹ýž$z„%ã‹”o€2¾¬P‡“$CýM’ õw|a„uÁ¬­­!•Jr¹@Q”þñ•••±‹Lepc}}Ýu·f}}½ÿ©T +++sù]×qõêU\¾|91 ñÎ,2ù(ãËLXò-S‡“yBýM’ mðøÂ+ œf³‰{î¹7oÞLDÞ> endobj 2 0 obj << /Length 3 0 R /Filter /FlateDecode >> stream xœÌ½K¯.Éu%6篸C{ÀÃx?X@Sp› ÉM4zĦ([*ÉM 0Ú¿Þkí;âÅS¥,VÝïÆÍŒŒ×еßÿýgþ›Ãÿû9ÿS{øöÛï~æ>|Èò·ÏŸð×ÿýgåÃwüE¨MþŽ?sK¹~ó)}‹EžÅß÷3SÇþYÿà÷ø³{þÀ¦üÙÿù³Aï¿Çï¿•¿{þñ~÷í~öüe=þû½Á×ü-ÄŒï)ÈŸþYþT G‚FùÃ?þì/~1¦ßÃOûýÏþËÅ?úo? ßþ#úû¿ÑTRn1~ûæÝ·ÿôiß¿~© ã»g`oôbý(aŽèù?btÎù_êoÿXý®¯w;G(3»~à?Ýæöî`u9ÇŸÏ>ñKÿÍ—žìßü¾@_ÿû?ó%Ågü()ù†Gsh-ÖØBlø›ß<€ñóà?2øö›ï¾ý—ÿ‰3ü?û¯ß~óö~#£ýÞ¾‚sᣇXRõù+}•«¯·Nã:ö¯,à8ê/ŸÆ}4壔Þ{óõeñ5|´îxŽ~·–»÷î£6ÿIï«áý5u1 ×’ßœlvh&ÛôûúdK÷ÛdÛÞ¯Éþ~üñ]´ÐžÂ¿ .Z½ ×üÀƒ¯íÄ»ú\,1;ãN˜äÕK á#¶˜£÷åêÓ9:ñؾÛðÑÂ÷Ï݇“ÿ…úíçOÛ§ìÿ¢öíRä6À9øHC¼>¤à?Y¿äoù«¿ûû_ÿâ·ÿú‡ß]_´_(vjêÅñè…þ-u\ľÖRr¿§€øþó¤}ÿñ÷¿û¼Ý±îOÂCÀ7•˜p.ÓGÀßôœ=¡¢y\ h ¥} 3ŸRÆß¶Œ½ˆM˜Òð\®t-KÞÉ[Éÿ-`żëÞg!ޝì쮆]úH…sP£´á•üœ˜o{½úä|¯MÚ ݵ†=À•µ7á0ÁùÊOñ‡Ëá’OãaÞ™ñΊî}©KÝKñÒ†wò["ºË…\!ûÒ+›<^™HH¡±a’Ç mxe ¯ûª`ûÈ…ÅÁ&?Á5œ¤ +ÚpiW~JʤŽß|ò\͆%@§Zñ™Ò„WòS––¯t -È+±O*¨a’0#9áø}.â•ü”ì1+‹F-Ÿ¥ ïä•ÊþÜG+±`ÚexÉpt.: Aì̉:Ò†w®)ÃK° SwMŸãþ`XLËGÃI÷IdœñN®Pü–øÑ+p {Y½Œwò[">" Úp £kÒÖÈs0Ì)w^(xÙܱXt„ƒÅýÄ6¼lîX¾ s§‚tTð2L. :0D./¾mïÄÚ4@|`©©æÖåãkþ»Ëk[/Ù…"߂ӓ¹8-ã[BÿÀÌ` ^ÚpzÚÚ² Á-WþNOX[ï¬ø²t[âôäµe1†–[Ò‚ÃÓÖìc¦Jçö’ÕÆÙ œ¬Ú­ÏUüËæTÚÃÙ \¼K&,æ–q ¼´µyÂùJìeü”ãLÿèkÃb}ðùÑÇ mxåÚ°ü°[’¶á•φ ”¶1mQÚpv:ç@Újèw”¶áòÊÚe..‡S&mx'¾eù¼g@6zä,a}Nú\Åå hÖ¶Œ{{mØÀ—”œs6¼óÙ°¸Óþe’½)÷?·VÈÀBç¿B3ýÿó@m€sy;È}wøÈX¶‚{í3àöü 8ÀÙ7¦’W=Ž×ܘsŒ Ê.º;Bè¼!wðœ§èF1ÀÀ-0uX=É;p©Kh¸‚Z¹€·4N?¶³lLÜx‰-wàŽh‰k·¹|w °$B¥¸ù]XPï¸Ý1Ÿå¥'nË$`ã¥NÜÆ ±Õ±Ó«ëncpØgµû|Á6Wø• £¶{n¬¢¢†m\žKàkôlw³V±ãÛÛ]L)qÊÛ^v”E'ÌÀ6úkql¿ÛD+|%7^° .ˆC Ù$… ¶ÙQÀë²®šmÂÜv¥ØÆGD|\Í!\°þ°²˜óœ.ØÆ¦/è­ôT.ØIÃ=…‹¬_¨Mþ†¥é nP»q7•̹ya7nžØ–dxvƒ]R_§¯Ü±‡snw`7_ß Á^{;±ó)@{3ØÕ?nç”óU”¦ðÖYÀm–”ïàÍþp`A0Ó ÞXe­„i 'xsúZô˜=¥¦;xóâ/Á‚)MÞÁ›ýå‚ÙÈ:†ÞøKl„šUŒ2àMdšÌ¤¼Ù‘ë¸<ÇNØÁ›[¦g|EÍýožcÑ~æ ¼@8䔓²à¼yÅã·„Cày!d7z7Pƒ‚ŸÓ͹+vzÄ,çAŸôæJ¥ÈÚÛ…Þ¸¬]ü¨4Ø¢7°BJüÝè]+HÇÂɽeÑ¢§«MHʼnÞèRdn­÷½;·66|½Y7„ç±,ät£7ä„MŒCr³î.ÒlÁ….ôFØÖqÞ½9V^\½\è]p‡:ÜÙ`7zã‹`ÜÊÞ…ª¤ñ%¢òÃù…P†Íû5«ÆÄn`iäÝJ~pb·çEßxi;±›k1>&,ì‰Ý¾€×AB#¿&¾ðÖ‚`íåtY…Iås4&\¼›Óƒm ÚÝ “ò€¯Né…I¨à­ˆäcx7¯-ì>W/è¦LQ²õ©KÙõ%¼a2$7¯`ô%”¥0¿Í… »ÙæpH’oùäÝ"æƒx;¸Õ—ౌ¯‚@›.ìÆ0r ¸Ç‹xcaƘ3wëKІIZ¦ »9<ì·~zcw Pó¨ýâ6Šÿ¸²ÛE¼ñÎÒ ®­xï@Yó¹”»Cúà Gå6»ñ€Ï D^é§!Þìæsëñæ„c) ¡ÝØx´(¹‰ŠÏb7˜H Ø›N/O«/IÌ­zƒÝ2‘ ¦¬Á`·'MÆ™¬é‚n4QÛP]:¡Û{vÍ=Ùnèö…à‰Ô›x{`"Ö¬ê¬Xèf[Ê–xC7–CÁÉ)ù„î@½g¡&õ†îà¨lLYõžºñƒ2 €tƒmtÜ\­Ý†>Ñ7Ž;2·œ Üe°¥¸Ñ±[1 ùn´õˆýÙÒM»ñ%¼ªû˜K «Öœ¾F»ÕO!öiω–%þI?º¿ê§ðY߯˜•ú0l¯½Ñ Üüž_¯; ä°ù)¬¯w;G(3»~¼í§0ƧË>÷SøK¼€1$ô9ÉßõLˆ`å¼$ x|É âmÏ„çü­ƒþÊ’•°ó÷ ¶Ñˆ5J/™waÅË÷~ß7–wë™`{Ù3a_S'Hã©›}o²Ù¡™lÓïë“-Ýo“m{ÿºghh='±,¯y&ØNÞòL0½ü0Ï„ï±üãe⚘Xó÷XþÝnùÿãÿxÏòûaù3„ðY)É&g H7M!Þsƒ$JˆK§CMcô¡9‘%Ä)€°ƒ™Gþ&ÍM”§\@ÓžB—Ç(".± CžÚ)â$¾ÝòJÉ&‹h™‚±üƒwð….öÐÌM­åÒv6ˆYÆò©(Í‹u?QD\rè'øº¨Ûh®[r6 d%Š ^Ú¨¯œà•D'È€IÌ= "b]rä>ˆØ ÂwSÚ-ÿžúЈ…î’±ügªfR­¢*L¼[þ!É6ŒÏ‹J'ecù/_ À;$ÄôRAÍñ–aÌJëcH¥ Ù¼hC*5åø‚˜7ÅôR1tìlHÞ²zÕXþÅ%,² ØZþ±¿RV 8Uµücþ+­%"ú¦vXþÑE—»Ë?4dÏ|D3–líØkH"(¥n,ÿ§!ªâôË ûaù§Y*ªV0õÃò_ êÆ,bði·üC¶, N]&9;cù§ª‚Y½ÝaùÇ\€tÉ·d¿Ûþ©{‰/iÇÛ?Ä©ìÞ#ŸB©·M˜Ç0eØñ¢½Ì”½x#©CDÇ%9]ÛŒí‡ÕgG£´áò•¹‹sF.¾Ð>öhdYñ ª¹‹f3Œ¡©GUÚ8TDÙÛ?¶F(JlBžkÑfª¯A*8¢8Ç~ÙmÿV^“è6r2¶Oñ@¬Ÿ™é!ç¨'•í.<² ù°ýC2­=‹.%ãø{ cû$ït¥‡*§N.Ø(—G˯ZþàæV/ÛðÂm ÍfYæãÀm|)ö'槆ۘ~L›.ÜÆÚ`†z¬n*Ɇ;—n*±…ѦG?–À =AÚ Ü4NÐ ¸Oà&]ì cuõnš2pÃ;±…অˆ[\á¸y-q¿TÕ Zàî´½Dì¥Fü« „Ïâ6û+Z?^ïvŽPfvýxÛ|4Ƨ˙~°ù@Ð!^;õô²ùrHÿ¾dªzÛ|ôœ¿uÐ_Y²¶cþÞùÛF£!žrͼ +Æ¢aú}Ý¢!Ýo ÛûËæ£}Mó;4“mú}}²¥ûm²mï_7Ea €p÷×ÌG¶“·ÌG¦—WÌG ã@ Øäï1¡{c>úÃ?½e>*Aö@þ‹˜Š£”ã(†Ã‰DÝ oíÔÒS΄Ðæ'ÁRÒd´\cÃd_•¸Ë±x«5.®DõƒÄ¦ŒÒ†] ±N)\4ñGÔB¦ŠðÎB ˜ì•ÊK>8(ÐﮄČ÷ÂeÒÖ>áöâð UâS(l”¼ ²bÐÆÛ›!«#äÒéD¼ &õƒ\*-Ô££„d ý¿Å{àÃ=*Ê K¬’¾³ì¢l‘¸éœ‚x•Bôþ˜<RfèDl.u—d[k§/\ÖÇÔr¨t°%}@õSÚ.ɶÑ’Á1¢¶)mei‹‹XÕ ”¦~*p< »"K€Xé»([%Ð:¨«Z è—\ÀÇbmÉË6ê*È&ÊS˜_ÑÃUJˆs»B¢`Ï–(m» ‹™‚Lƒ=(âU¥„8·+}l!È@Za£ú]-ÜÊâH_¤md±„tÚ&P)"Îý*ß’»o*×°K²U ( i"ïTŠˆc¿RþÅSS7QÃ.È¢;œPƒÈâ•âܯòs(ðkÜ%ÙB¯Wü3 `o’ln¢ŸÁ;5IŸ‰yN¤ÜšŒ{ú õëêŠ?n’l‘XíÐ’ Õ¼K²ôZ…Š1È·äM’¥³™ÕTUó.ÉæNGZ Pöy-»$›¹Ñk¬EP‹¼I²8þ‰L¬e—dñ\á|iX­»$K%M Ïk›‘d!¨‡Lu…LYÝ%Ù>h[uª‰—ëU$dkÐQ’ý’õèÂmÜ_8r*ÅXÜN ‘ŽÍ‹‰Îâ6Ä«”©v 7p‹ÑÖWUkXܦw×p;p;0â,»<ðÞXCÍÅqùÂí,ÊHœ»rá¶ÇW¢·EMoqÛÓÞ,1ÞþÄmñfwŽîOÜŽJ"‰™ó'pÓ?¾0^AC pó9 nÕ;dn>T+œcp[šr¦ö?¸Í›‡!¸9 lÞc¯±û·å¹Œe(ºv;nËs¸é*åÄmi£Ã¡úPܖȧWë‰Ûòö<õg'pó9@ ¾;>È­i!0Yrà–›83b\Ñ˙У¸ âÀm6‡µ bá5¸M‹fÄLÀÆ·i»kŽûl<·á6Û°Qfò ƒÛ`ÑÈ÷%Ãuùjp[¢‹JÀÝX/Ü–çÐAWWƒÛbbdØD• dp[,šêjOÜæ;S£E-”·%*¬¶:ôÛ·%>Ñ“‚ÞŽÛò-ÕŤŠê·9ÓÉó«õFÞq[VèçÕ Üà¶¶9ÆÅö·¹W–•!g'n³‘a®ê*ì¸-6gP— Y·5J3_â…Û4,cÂ@‡ôÊj#p=JRù’û×mGtc»g̘»‘;d‰èÓ(n Ü ˆ _]´²¸QÛ4,Á"·§÷Kî ½>‘›Våˆõƒ™YÆMä!Á÷ýDnL%¸ ¡¨ŸÈ-ñrØ¿M“Íä¦i/2“O­r3: Ë ‰,^È-qv¸ì@ëE¹+-4µ ¹iªb¸AXeÜÌU†£Cðɸiwqˆ"ÆÍÞh® ƒUo-毈3ß2nROl2ÝÊ–pÚö]Ï7ߦ a ê[aÙ6¶ŽšÆál[â³û‹usþŠø°eðáF`¢Rî…o[¡1fÉ®A]˜„­€õ£·È¶6½ zÕKûã¾ ­Ìßüêûõk޽LËèbØöߘz›É]ÀHéeP}é˜Ð¡™¦¥¶ûËÇ)Fh®ã«ÿÔ8ÿîÿùÝ¿üͯþׯõ«Nqû˜½ð+à@W׊}Ц팺jÞqJhW½¡5êÿðýþwÿòƒ†üE3jztª®zºF½·ý€Qƒ°QÚN =zÔÿéÿÕØÒ?ṉ-{f˜íט÷¶` f"îi¹Q¹UƒÔšl³†æ§ý¿£ÛÏÓH¼F÷J?ÌVúX‰·Ÿ¯Ûk=ÕÖsý© Åk:¿ë×Û¦â9ÄÑmýÜXüåzšÕ‘×;–œaÊêWMǬU6ËdåKfê×ëin'sÀ+‹8Ïýë'ÓŒ(Ë.I3å‹]Ú²š¦çŸÀ¢™­ùèÿmò¾¶¾?n/N¹HDfÊMÏïO¹|À>å¶ÿ¯[‘©pø s¥‰à-+òÑË[VdÛÍ+VäÊ<>ÌŲyÞˆœvòß«_)7 Swf ÉMT®±Ä£œÈBM5=Ys…iå*cñÄð†F£ÒjRÁªÅÑfTZôoÎ)øª2s׈ÜÊz3,‘Àý‡:ê" #rE3©•TFþH4‹^Ã0?­;å]s6ªÅ·–‹Whcª|Þ¼¢ë÷,æé;j—­ÚxÄÂztjö®ïV zÒ3ڇИ$µŽµ=˜§:4ÖQÙ.k$3QccïÚ­Î4òˆþ»z »$0•I{¬ì~zÐ'?¢Xå‡aYÒè7ërùJÏߦm»† .3½Œ®‰dâ×%)C£¦ŸßÃeÐY¢ÿB7œ[ýž°+¹íþÛ5yÖíZ.Vû( âÆë¥ö¤Eèªæ )ú’Fc’L;‘1‰òd\´~h dgØI»“—Bœs'³dGfÑÕQ @ͽLu!wdÑ <¥qíeÆ•Ž$Ú¸«¿¨ŸŒô­&¿k¿dí˜95¨PŠ£ÍNfÙÇPÆ“R´qìdF TtJâP’²®6K–Z¯¼¼‘ÞQé¬eÓ¨gœ!n¦±7,Ô3›©¸ª¸ü)Ö'ÇXï?Áz,Xš'Ö3\4ïõ‰¾I¾ü„zÆ=bz»–ô= ž>J¬§¥eª¨ÜÔ~æB= Þ ™Ë¶ÅzC½äAs¯7Ô{ÙhmlÐŒrÆJ àqÆ]ÐÃðl9žèÝi·?qž&c¼À1aò…ó|§‹;»Ý8/•FŸÕ¸,ÎÓêM}²›WK0¦hZDRæ…vἤ y>„ æyŒsZÕØ/˜—`Í„ÑkŠÊó§I#û¸ªv˜—ð<ºËhC óò>æãkZÕÀ<qÁ7°1éês¿¶ å¥1ðÜ„åÅÔTñtå¥6KŠã^-Ö(͢΂҅òR”/òº—Y5fizÞf©Au¡<1 ‹Ø.”×®ØbZhÊ¢¼4fzÇŒÝhPžEP%gq ʳOQK§t<á{µáë òb{g–Âqä È‹Ù75WÇÆ1 ¯£Œ´„]/6hœ?,u¼0^>‡In£ ³(/.¶ŒzÑo5(¯fh0¯¤[Ä ¼Nl,óÊVGGðë,o—X;€žî1õèY›L¨‹ÁòäôL±ÁÄ ƒ'[ wÂ.Y/ö çþìnd <€^â i]Õ9·HOÿÊ>]Hïš,yt)\HO÷ÐäV©Ez©œ Ò–ÃhìÆCG¶°Žk¾‘^’m4íûé¥,`×iÄ×AêÙ™*XkZR¯”¥ú1ïêɰ± pFŠ¿H½Xƒ£»ëMê5¬0cÊMêk‘zZ)¦hH}¡ˆ&?ûMê ³õbòÒ€&Kêqz~[nŸú*ÕË[´ÍzÚ”ñ–æÆí3H½c®tú¶OH½‡pVA•”YRåÛÊvyzñjAìÊ,©—ò<Øšwà õÌ–‘9åã5¤>36?ñôßœ3SbMRyðäôœÒ°Œ#§'ùάWêÍé¹R —d÷7¥ÏôóÀË4ø ô˜îØC#f}Bé¹YöhÈ7Øs¸@ºzQž”žÅ>1«nl+Ké1ô¹r§ôkÉ”æs¹ ¥Ï¬aÑZëµÞ”ž‘º8°µ´O(=}k›–·»)=3܇aŽF˜´cÄ ´¾àAê3OO’tœŸ’z†GÖ>î&IY>è|=¢¥¿nþ¬²å;)ò–šø§ChÕ?½düú¤÷W4’cßmc{£Ÿ5½¤Žéù•Eû)™‘_ªÑä$Åä˜ËùãõnçunŸ_í‰Ñzu¼cMçOºý^m,®H–Ìd:g¨@_ª,ÆÁ»UË?ÖÔx R<™©.¾Ð×릮uŸÿʲSþö9ÜÇ£Ù&¥rí»ÃDÈg‡îÍã=Âøêã=ÂøÚ÷½â {o ¥Cwwøêã=Â÷ÖP:¼G¸¯á÷ã¥äl¡1‚!Ð[—j*)ÿ-q¶“ bX]÷Õšÿ´!.ü¸^ÉX ‰DõO÷’~T/L %u-º—bzÿ I iý7~Îtü¨öÏ7ãó)û¿ð.J)¦`§¼Îú1&±œ_R🬟ò·¿üÕßýý¯ñÛýÃï®oÚ}JþìTñãìr9Ó}™µ„=Yë'•õöÔ¨ÿí÷¿{/¬ÕÔˆ'[êQS¸5â“”py*…öñ‰yU¤¿¢²ç^#ž•4“ä§»F|’`”JU]ó^#>IIçNý„È,{xVßô4Šÿ€)©¨hs,zoS">Ò „ïm¹hùø§ÆäQ.ãjÚkÄGHV×ÜH¿gjij™YÆLøHßÿFƒQÑbï[øH—åG߳׈4”PÈÔS#>B–…îüèn¯Ïç¤$“ĦF|-Ök™õ½F<ÛÄi|<·×ˆØ¤,ùÇlî5âc¦í¥ÐKIÛ¶ñ^dÛxn¯ÏïÄÍÅÛKÄsÆ0+Ø[‰xŽÙ%ðD5i›ñ|€82W{/5`—UÙ¯ñ|®ç dJÄGFiºXøðÛQ"SøA}ÙðB{‰ø˜ÅvX½jœM‰øˆÃSkNó;÷ñìϳ¦¸“˜ñ|e+…9Ðd>¶ñ‘ªB†(¬_¹—ˆ™z—[¿*ij d?¶"m¦B<ÛîÑR‚ç`¯åwoúxäf¦^ %‹\ÈM!oÜ‚¹±˜ >yE‹ÜtÄxÀÍ ·è,¢¤ÆŠr;MøÒ'âï*¦ˆò³>§U‘PóÔYMÍ×¹Eòbz­mU$`uX×îz8‘[÷M‡`U$’«{î†nQƒÄµ®—ŠGi¡À®"ÉR2`IFEBoÖ¦ÐdU$’.¹ÓÁ¢žÐ)ñÐ=qªOv‰¤KŠ•NÌ'vSüMê¿Nì¦Ô¼QŸCEâ¹÷ý”3ŒŠ„/aò¬©Ùu$ŒÇUQ†ZCu$R!gÁ/£svóht$ ö¯}QO£#áÝ9dw«#ILüÝûD}ƒÞI(ë­Ž„•üð7sŸ‰LÓ"§‹s(0{yˆ•‡’$½—Q’ÐÙTzi•$’ ‡B£¬–„ 6c˜mVKUïq§)eµZ²ITj0JòG·JV-˜‚¢äÙ(I"¥¹ÖY‘çïÈÌme}‰Ñ’Ðͯslµ$r?®˜ra7‡]¦èvb7^™}iCŸf•$’<».þo”$ò’>…tQ’°›Òª~Á—ý5bŸ–MŠ)j ãŸÔ–*•/úk|Öû+†ª>mûÏØÞènþϯ×'rØü5Ö×»#Ô¹}~½î¯1†8Ö4ü fªF0Áb¬/ûkàhDyÕÖ/ù†¼í¯ñœÃçÄ¿²l%lçýE¿m< ‡´ð*À [¿éð=[Ÿþ¦Ãmý}úkØ_á¾W¶¢£ï­¡tèî_a¼GøÞJ‡÷¿ä¯V@yÄ·ù5 ÛÉ[þ¶—·ü5L/?Ì_ã{¼!À€)B”.1‘ßã áwoˆ?þ÷¼!¨y²Þ˜Z±¾‚)¸Ã"> ÕDz©½èFÒ´.‰bm©½¢ÄdMã~ò[Ý*¾$Æ¥l¥jÚ-Á‰¢Ëcg¡zÿQÒjZ¼©¾RKÉr‡ <_¦E=…]ÖÇ90Ïí²~_û!¸Rw¹b8¨ˆÌ3©š4ê Ýc^fú³Ât’2-¢órùÈ ÊQ9@¬ˆKp" Ãú+ªYŸŸHÍÿ)wO•÷Ô3SËýÈú4ÿWæ­Û9ss‡0vÃÄòZKrÂ?LmÉRÙêVñ3!?O5G*[Ý*Ï?"q*’2lˆNB2+zjª»¬Ÿ«äz¬T,ú´g§:ý!‚×ܳ©í‚>G•—CFjÆ‚!;[Û.è£ 3<…·Ô3„ÿH&?uã X©0 ­HêÆÂ1®Š¾ìŒ ŸY*GM×™Ý.èKæð6}f²Û}™”2u±Ùï‚>3r/?•ìwA?axe-vö[Õ*¶1½áp\Êa«Z%.ašs0r~bRA̺¸z0]Ï Ò ŽI"™õTåhÜ!øÊÜGÝŸ²U8C­“£q‡`‚fÌ‘sÚÊV±»Z–•,'ãA ›ª¢œvIŸÚ¼l­9o…«Dm•VÜ;D£€6½jrÞJWq ©®rs£›šý4‹¿åqàvd6U†]¸Í óØìãXܦ^dYþ-nS;X™éP £·÷›>Õà6Q.àL&5[[ܯ9 ¢*F n§ØÑM»²<·ù\_"QÒì¸Íǘž`¸±ܦmª>i· nóG/SvÐæ@.¦ñÀ€6 €L?4Ÿ;hÓJÃÒߪà1˜-Ÿ |Mêed0[LŠîY6îm7Ì/ŠÇeË`¶Xpv­Z2ƒÙtˆH=+¿l61·éhªÆ"}hf]ÓzøCø§6¨"6­‰>,Sœm®zh⃓OЦEd¿i›±­¹ÍÌm0›¯Ìq™Ï f‹;Ä6ÃÝøCt©=º3˜ÍwbScªj91[ Eë†6˜-ŸùpŒ³Õ|¶Ü# f‹-è9R³¥í±ÛÌæ¨²ÇÍ€vÒ—Ì d@›Ï1'ˆS‡ÚzIËumñÀh©¸1cѸDTnÞ:¼f h³­Çe5 - 4TªuЀ¶´…eZ3 ¤ît^+”OçÖϛڀvòr>â°‰ˆ@ÉÌ}qª}Ñ´vàvøheø&ž¸Í\àkÅmŒPŸ‡aÔâ6vîýyÂ-Ý–z;sÿYØfòö´ncÛ´™2ÿ°2t›I—×>²tÇ×fìãšØévca:á–n×N_µ< Þ–n³¨NÂõ¢fXK·›Ûè–nKúï8Í·†n7K Ýn’K}zEXºÝüã:~ÒíÆ>ËcÊÒm Ï?V>K·›3ÔØÐí BÛs³t»æÝ¡ÊÒíŠc‰#}ÌÝfª¢Çr=è6 ·L2þÒ0n&!¢R¼°›ýl^Ë–pWÉe¿nbC¸kÜ¡Áî‚Û=d§e®-ß®”+—{œåÛxe¢'ÈL÷%Œ='K·+‹½´ÐnèŽbC\þ*–nSªä׿o趤6ïÓÃØÒíÂÔ§Þùv¡7ê²±Z¾ÍPïÇ Îòm<×)Ù lÛù6š*ùâÚÕò#€®]ŒµÔrmnêÇ l¹vaª¾E-ׯsîñr³\›ýAªÉjµ\›ú%ͨï'×Î’Ô?g5Ø~Ù¬VüT@Ó¡Eu–R4\TÞÅ¿kVû¬÷7ô‰sßmc{¥Ÿº›Õž_¯Û·jÚÌjëÇëÝÎêÜ>¿^7«!Ž5M?¬–Ä=!±¨4ݼjVK2 U†¥ý™ÕžsøœøW–­…í¼¿x·ñ”gS¼ 0j’±¾f’a‡ñá{&éðá{fµ}¯ü$f5éÐݾ:Âxð½5”ï~ɬY §E9^3«ÙNÞ2«Ù^Þ2«™^^1«±Zä<ÈÇøß÷˜Õ@Ö7£Úþéµ"-”žgU¤D+Ð #€„#òAÓ .!? Ò‹s…0…üålnËZU¢QÎôóSÇ‹"8³ü ’Ǧœ•ºau*g Åç‘PŠŠƒNÁD5;%íºYIgDs‘ê£#]Ð!]NkNÉ»”ߥVËKKÎO!/q¨î+Z­äöò¢_ÃñXŠ‘òÁ0žÈÅk%E‹yÆVä@)»˜ÏìP,õ§ÚÔœ¸SjbÑ­œg¼N©FʧtZÒðTÆ <…¼(Kj²óÒvŸYž˜ˆÒvÂ.$/ Ѷö$BÅÀRΖnä{*?—¿téù)áE™œEb‡>¡t‘ï©–ië*%ç¹YEr¦¥J7HuFÀg°e‘­çfeGÖ©ú]¾—P ¤­~—ïk ¥ 3(Ö•¢óÜ«Tõø¶•j0>ƒÐk·•¢óØ«T…àìMmb FÀw{”N¥ä<÷*G°™£j4¾cµC\£‘ði˜‘%5"©ÉÈ÷¢”Y“’ù>æ‡wlÍF¾oOÛvùž¹‘iEwÍ»ŒW6Ɖ¨sl-»ŒOÝÑãÃ3°ÉøE*m—þYË.ãcßEFx«a©Ö]Æ/´¼`j¬u—ñkbæc P¿¥î2>_Bïq=reS»’üŒËžvA¶gXª.Èæ^[Ú격Vô3ªÚB6 ¾·4ƒ,d³í±[ÈN”š²þò–µ,M¶lú¹?±q²q{l²îϴ̲y³Ì ¯éÿ”±Ó¯ÙÆÔ#u ÞŽ×Tß¶¸RW¼f[®ËqÞà5uã®2Q¡"å†× tyÅé¼Nôç~*Á¼ tÓaÁ€6Ÿ«IÓ€6ûc|Ïð7 Í¶ÍmP›ïܴεÅùœdEm‰n£^L? ¶hÖŸ ƒÚ|Ìn$[0 ­æÌ}h@[šÒ–mÚÁ™$ž ÍOÏÑO¯ Úü’ǽ`Çl~/eæ1˜Íèô­æ²ÁlZAY›sÜÛ³i‰ ¿˜_A­ó“Ó8§´ÙæWزm¾åe1 Í!ä'ŽÀ€6ͧå¡H;hKo¾…~l@[ç‹ÑÇB= h ‘{ÂC h³ Ûk^;;fË„=A³Åtãf„l~e²žþ‚löÐÛdMãø¿VeæËf´®¥€°º|p <Ûâ­,\óì‚bL*iàš9¯|.®qvËi®=/ÕÁ°™*b1×R: ·º…,\‹b…G[¸fmbì–a¸´pí$ TOjê0ˆM3$>÷ÏÁ°™f8˰ÑVŸðI˰YfâÉ(t0lož3 ›á]uº [’-Ì4K–aÓ.•ݰ Y–ͦ™ädÙÌœyŰlZ_Ńf#Ž4›.à pÐl¼Ì±çD^C³YWX5ø‘¥ÙL¾„]¡þÍf¸ÕT,Ï®Ü3i†ú<›¡_+fÙòl&Þ~²#<œòñ0<›…y÷&óÁK´Ö²¿x6«td?wúÁ³;c¿fÉõƒgãÂÄ,øÏxvÜÝù¢XºvúYD»Ñ1 W­ƒhCÂð+ÄÞmºGÔégymÿ#•%Úø”'«‹åÙ\ŸvÐ쌥[I–,ÍÆcR@w¶SŸç) [š ¾ÙÙ[h6£nûJDõeSZwÉÆCU**µ|ºˆhlÓ˜öiÿo¨ç@¾ÛG÷JG½læ´ç×ëv­žûcN[?^ïvŽP'÷ùõº9m Qû]?~ˆ9-‰·e®†^6§á®a ‚”=øë1§='ñ9óï”xçüý“¸(ÿ5éÐݾfŒiâLuøž1F:¼GøžAmÛ-]*¯¼nQÓÝÝã»cŒ÷_L-=Þcü’Q Å2,-SSýšUíèå-³ÚÑÍ[v5ÛÍ+†µÜXY3uŠß—½—äÿ1­ýÛÞ‹Wkt‹5¦5Èy!Iõ!ˆWÖ´æór‰li«=DOæ}™ŸZª»i-잢V¸]ðß’Ê6æ-{Lk}wko¹î‚¿Û’´â6Á?ïN«%’ÁŸñcm¦MâÁØÿá˜Q5ó­ºÝ´ÖXcÒÍÏd}¤Gð§ËñR85JÃKŽj»)£5·[Ö°ú®•á‚ÞÚVnˆ‚n˜24Ôµ‘–U%'å̤ØúSlˆ‚M%¢ˆQÃ6¹_\P—¿hc]¤Ý²ÖŸT–]c§ö˜Ý¥]ð÷ø®¢›…muüYŒj©;»w»àÏl+n*àiÐ~ÎvõpAÇá‚e¶+õ‘ï\|c_ó+óIgÌÅ#ø·]vì¡ZÁSk÷è¬-+<­E§üq e*œ4cô:3À=‚¿¨0¦/O[y!JéIaÒSÚHÔ%NëAgŒÚ`éw;SÏ[m!f7Ú\·ñ±»àÏTq%Ï5e¤µcmâèÎÁµcä÷ø`÷²âsäÃ#-R/[]!M§´Br:í‚O:%ΧéÇÜëSUˆþ¦î !cNŠÍ–VË Òè,€´¶,óÕbñ†¡³þÑãFKo^\vêbŽ¿Ü3øó™Ýín´uÒè8>Æv³Ôvš·Ù_JáÎÄizƒ³j[]vÑ·llvç'³ì…Ý&ÁÑÝeK-{@7UÑ+/³…nQµ™ÐÊB·”EX©ž-tǺ»0èÆAk´¬è—ä¦VË-›ªEnžÏ§\œAnÕ:cÞ]:›ö°ø$3ÀÍÇpbgÄ—AnZ²[ñˆ¹%…/£—uïä–´ƒOæŽÜ4å²¾7ŸZ–Ó¸%ö¬Æ²;p³­ñ¨…Á7Súø`€[ß)JÙ|·8´<ù¯ pS_«’·Ä=©£ÎÜŒ—ÚîiܼޥØÚ@ĸ%Tìqø0À-´oÐÜÒ_p~ö··„­mGnM‘;#&vÜ–<5B nK†Ü'cÁmÍ»\ nÓlÑ-©Ám¶a&G>>Û$=þI(l`[|†žlo¶%rk»±vØæ;³”ݰÍùÒ°»¶é¾Ô¼Ÿé» lK˜sæOhN6di+³mI…ùDÕØf[|ÜØ–çÜÓßÛœpñÁÍT¶Ä_iÜÆ%Ê/[ÛàNOv³¸›Vú9 Üj´ŸaEr³¶ùL ~qn·qu˹ýî€upîÈô§3øÌwKX᛹e]—÷œEnž §õÅ"7íž,­º÷CY¨¾#7(¾-çîbƒŸ“b(wgvžè`ø¸qRÜ€Õ 8,åîLv·rÕ[Ê-ÕGX¹R&ÅRîN[OžØ–r·ÂŠì3 ÊRn:Ϲ>ó¾ZÊç<0@mðãfÈîòŒß¾ùgYÆÝXˆ"NaÈ2nÎ)V5ŽÇvÂÍ~ŠD¶„›žiý‘$ á&‰ün,áf„\_¹B,áfžØÇBgw5ŒÍnš6¥$§ŽÎn¦L++}¡%ÜÜ„r3¦ ¸)Ô`GMyÎn:Þ•UÀnœ‡ð$f°„3ï'K¸i-|²ÇÂ]ãRl 7SKK¶+/‰å¬jɶÔ^É-Ù¦ýôñвd›ã} Z®ÍÐÆíê4\»Rg²ÒC ®Í„Ëñçë¥;]^–.õK›U„󻦶Ͽàõb^ƶg€¯ôäýnmÛ~¾n÷wÚìmϯŸ c¿[ܶŸ¯›Üæ(gÏõGݪ$³€´Ü_6ºUŽC¨ÃíR¾dà{½”çv&ŸóÿÊÒÍ#ÿþ™4cÊ’Í0Íœ‘ové>éòE£Mž¶7Ûå›V›<­oG—ïrß5¾ ´Iáð×RS^|Ò廣ŒŸŒòŵ”.?å—LpH!uCViz¯¾çÑË[&¸£›·Lp¶›WLp4·A–Ã;Á¿Çgìo|¯z¦Ü¶Ì’™%D•ú÷Q=‰hBE2¸{ެÿÂlyiÕ%@£QãÒ“qÕ]b‰Ÿ]PèÚ9}Ý!m8©Á\Cº¬[E$M¤ 5¡[Y4*l·0k ¹¶ë<$ ?i9Ú‹ºÜ¨wr}Ï…Fc‰køÀ©ýó®ïj-E² V8ˆLf£G´³ÜЏCc•l6ŠÅ=mÞ‚ø2£`Þ‹Uƒ“Ym â ÛñV|Oò” {ßH9b㈛V.4íÚÈ™‘ÖÍùRÈÝÌhS0 ×ÁŒ¦©÷”¿uΣušÐX%¹lc*e&=‹­ª b7mw] §~ª&ÐÆ ’cSíneÂWmÛƒÐhÔ~‚dv9©¡Û˜ˆO‘Yï)¯mÌ>ⶈm×HìÜR² qWTºÙ.ƒ‡TîkÓñœAdjóDã¦4(mסþ`wÐ-{HlU'5$t#ãI—Vú4²`çÜÈ|Rÿv×ðoÓŠÃrïjƒÂ”HO2,6ä…µƒq0N• h¬RBBw0_[ÒtM^¶\\0Ó«ýµJ›Â§ëH6t#<·å²Ïj´~ißö,‹³bšâŒw*ÅÂ2 à¥LÖ µàm¡8 îh̔Նq€;C¿@òÔàpˆy•µà.ù,Ÿ’Ü¥¸Û“çË¢»f ôÏþu‡ÉŽÞ aøŽîÚ¸‚ º‹e.¥i ³ðÎÆÍ:jáêò­‚®…÷$uVÂT`[x—À'M_›/xgãæÇaáö¹ÞVm" ï¼ÇŸ$–ÝùÄÕlÑ],fø’¹ŒÞù¤{" -¾ÓF—q",æÃ€‡ æ îÏ>ß3T×¼˜÷ëªxÚðŽurv€ûž[uœ-ÀÓ>Ö}žéê,Àk­®• Õ<|q ¾ž¡­p9 ðìo™©¾,ÀÓDŲW“q€ç“.­\Öà¥Næ¾b}·ç¥ ìsþxÉGðô´/6ŸD¡àù$Ý­šFEXœçÇ&îƒçi¸ ËÔia^ Çm»ËÀ<Ä:,J¢–_ò·UYèÍ2oÒ¯ÒôÒ'R™èf9M‹ô,eÌ<㎷HO\~ Ÿ\Þíz¸g(Ý£È?àž–ç¸Ê~Æå{:¸<Œ34ýäò¬ò÷ˆ6p/+â2ž\ž™òV°æÉå™Ê`¹)d¾1±þŠ÷:ÈÉ|¥vÆêžd¾ÒKâ!ÊJæ»—ÌãÈ\^RcN?Ž“Ì f–Íç½æòAç)¬ìƒ?éüæÝvÒy†IV¿„C祴Û*6}Ðy\Ú.¶…‚†ÎsËï<·Æ¿­ÖëIç™>c“-geãG¾¾èüÎø:Oûø¸] •gU4øI/ •¯’\f„¡òýKæ‡*ÏÄ?On̓ÊW¿—–8©éÏÎA…”[({5Ò9ĆJûdöm¿ýýïÞ x3µØI ‚×¶tÖb/EŠIP:Ðzë[-ö"e¼b¡(,m[-ö¢<ø—èAhë^‹½ˆ2%÷š¼ðï½;Óì°†»kJw÷Zì…·:ÄÌ¡”ß‹±ãm- Éà(Æž)µBÂ*í7[ŒM#OÙ]ÅØs+ Ò’í*ÆŽigí- Zì™NœØx×bÏtº[Qж§`›˜ÁT_j•ïµØùÊZX.Øk±CЧ¨ ùvÔb‡üG-‰ÊnG-v¶áß1©¡Ö[ßj±ç*:ï|Özë[-v~§ ™¨|Ë^‹]¾¥¸X Ñ|;j±gr›'••©Åž™€¦K!3­áÎÀO:`{1ëè·£{–ⱆ(úJS‹/‹˜b)mÛ*Fp`­C8ïZ}¯Åž%’o•í1µØù¶7vÛUŠ=Sêk–«Ö´ßK±gš"¨ËYË­o#Ø]ô§Ö9ÞK±³-Œ=I¾³½;GÞ¥FÒ¦-ÑMÆ4àKv¨VpßJ±gš¯fi*Sˆ¨tC ]«­oynä©å ¿bç'vOÅ&w©ÃΕƷ;~;ê°³ɰµoGvNrÈ’XêªÃÎî°Q±(Z~¯ÃÎ̼k­ëàöBì|g̘)‹j ±ó[ É{¯m[žC’=ùí(ÄÎþ0!˜Z?EãJíÆ— ý|Õ†fA;Ó¸‚‘ú´ÅGq6·9ãƒpH/Ð._šB½@;‹Í ²‰j0 hKz“8”²ièÓðÅ ²ùFì4 A*œÈÆÔÓ º:î]R!ŠyîʲùJˆo¬êÖNÈ.™T$éûÌfö³ˆ“ÚûÙìnDgIJKbJ³ìtoÄæ÷;@$îüt"6;ÃÑxôv"6{˘…æå Ä.¬–ˆ{1‘Þ bóSxÛÆì.Ä.Œ‰q}Ë b³¿PIûÜ…ØLǪz5û°Ù]c0RN`—$‘C5êØÌJç hO’ód›ýxÆ´îOÀæ˜>´eaаٟàgV¸Û›ýQ †cQNÄ.’;”l@/á±Ùþ U°Ä ¶Ì±o®½MwÄæ·xïb7æ†Øü”Ô1¼’ʉØò)Œ©¢ù3ˆ-s"fËT?­Álö×¼âÚÚì.»Ö²ôf@»Ä.¡’ƒwÐ.b92Í Ú2ð,—f:A[!uZ Úü”ZS` È Úüü+pfYXÚì²\sYôº´%õa•ôwámö×(¸yâ@m¡¨­aÌ_ó£ô_7‰]l»ãƒS+7pÓ5e‹Àíö8ä¸Yfº»žÔne€[Êv1Tß7Øþ &WÍ2ºñ΂ap9ƒÜ‰v§ænæhölBwôÜx!á¶´žoà.ªñn:õa³·æÛ ÜLõí°5ÓÜ…Û/ê y 7‹3»DUIâ„î ™f„Ç[èf]P@Öñ†n€ ­ ±ÅvA7:¸!1þ†n0º„_Ž t3Dw.(Lº ›å†S ú”nI9ˆCÒõ2°ÈéÐn “¢ÈY;®&f‘›Æ8¼j~žEîN»dfø ¹±ÅBK¥^È)'`‘šnƒÜX¦¬aúýFn!±WO¸‘›C˜†^I¹Ñp¬Æå ¹ÅEs«^È]yÁ›ôÒ²È$‘›6`¬TTDxÓ™Á 7ËàUÅà ¹=ýCLÉêb›º"Üm r‹d)’^½(7Åi,¬k)ÝÈ-† ÿDîÜ!ØÄ†?ÞЋ´6œNìÎÌÉ[›C ßõ$Ed3Ü䥜ØÍ6ˆ_yi­žÝ¥V£K"‰XE‰Tœò'vgQב¢µKQ¬.XøëE»s¦{óò—°Šb°gBçxB7FÁ¢ø^FOÂJê@. P;¡›“hzÚÝ|Ÿ-e°Oè–6ÈÖÖž„’½×RŽ'xgÑ$Ja°À›éiónéÖ“$ú`4t W®Ñ“ðeÕÕ!Z= «¨c¢q.ÚÍA;þ4üÄêIø\µŽ:ÿFQ"UÔ§^|5¬¢Dä/ÈÏcM¢„"³JÇNðféH,zÔ Ù%‰iòi÷íÎdòoˆéo¶eægè ‹FUBJö9è™U•pèM´Né@o~J×cOôæ¬àúŒU¥«,Aw1&J˜¬²„…Ô!`Šã‰Þì[6iåP«+Áµ‚ XT݌ѕ$­W‡¼e¢›Ãñåo>B ±»ö¼e¦N`a“v˨ÎBH?È?!öiË£/žZ•ø'µ²õMÿ„ÏzŨԧ-ûÛý¤¼û'<¿^w m~õ»~¼Þí¡Îíúõ¾ÂâXÓð#üÜè©ú®=?x_äV¿â ñ¶Âs ŸóþÊ¢•°öý ¶ñ‰œUaáUx±&sÓïë&ónýLïoû'싺•l|o²¥Ã}²m¿oO¶lÝm²Mï?À?””Ú&qŒ}Í?Átòš‚íå‡ù'|ùlò ƒàRþŠùÿ_4ÿ3—«QH‚œŠñW¢3Ö–tÀ% JÚDaqéwgMçD8e¼jÜõ;2f*I¬–zÇCèË,µ¨¯¤°¸Ô;,XâÁ†•ÍKb¬G¦m,.1tÆßlÿw=Ø®ÒIÄõØþqe…%ÓJM«eûO:¦²Bju- ¡IZ×FobiË┯uu©Ã9œ–„ ÑšTÎ dË%Ÿ†éRWQÒ2VÙïZ€V˜ÆIFŒñ2-öNj¢dKÙÿ“»Îà©·ÿ!©ˆL"mMÜñ‡9ür…Ó÷©lenÄÜWM*[™ùÎê³kBõS—øiN¥,æÑ"‚rª‡ñ ×Ǫ±ýÀD#'ªÑTE¦•`K©ø%«Öv™–@ˆ˜ßÞŒíŸÚªV“š±ýG9 É'ucúwn‹="¯ìÆôÏZاN,Ï©Û£Ó ³2qú³;mÿÒªì»ìv‰–%93$>‘¥²3–‡³ÒGÎFö»å¿|ˆSª„ngo ÿ$„I(¤m«pÃÎ ÎB„q+‡­Älƒ¸lÁ9ÓgÒ©–Îa+q#þ ûGóläh¬ÿjEBÈâSâ†ÕZ°—E÷™£1þã1–Æ*²[sÚJÜPÄêzŒi—6cü‡¬ èW‘Ÿ©HØŒÿ’ðuZ>¨¸X>÷Ò_g^jQ ç¼ ´…1m 2­­sÞŠÜd ‡`‰2OeÅñ¯=~‰~Ñúc¶`‡Khã±\=:ÑÕYÔ–ÝýÕ-jÓ^ò´°{2„¼úfXØ&Ÿð¹ª~Ö 6Íÿ %„µÅVŸX§QÏx8ÌÿÉõXÆg†ÃüGØÍÚüJŒ[A/‚µiþÇ×¥µÅ"¹¦%…¼µi0ÁQGôöŽÚlÂ~˜Ö3ƒÚâ04¢²Å¨‡³ÝÙâkjð¹a[Ì)q9£Ħ-!Þ'b³;@+6óhÛ[=)p"_ˆ-µâp“õ–/È¿‡Ö’‹¢.UÈÃ, ÀNÈ.ZÉ“aõþ„l¬2¼¶*!h‡ é©íh [!˜Œ1ç²ÅZB¿1U¯ÈKæjXJ d‹Å×óp60˜-óÍI%Ÿ -CǧØÐæ§`w—ÅcP›Ÿ‚# TKjóSŽ‹úkÐfoXþ¹ hËÈû;@[,î8§®W0 -ÖÿXÛ°±ì -®ày®ŠeÖ€6»ëa,äÚâñÁB‡µÖ´Õ_àÜÚò)€Õ4n@[úƒ,PTÕm@[Œÿ𨀶zŸ”ŠŸhóJP÷rQI‹Û µÃ%Ówâvd¢ñ†4fq[òmƒ–~³müày–'n3™@w e¹è6)uÕ=Ñmmð¹ã˜Þt›î´IÏÿE·Yf°²<µL«¡Û,ô-6%Y†n^u¬îSº ðžö¿ƒnó›SOêké¶°%š(ù ÝfL©oy\â–n3? ĺ)\t›q³ø‡i»è¶÷ø–pÓm¾Îr”:Ó†n3 (¦›õoÎ&ö hK·™eYÑuZ,Ý&&0OÍèƒo3?Öp+|›n™š§·Ü|[ü €íý¦ÛLÔͨÔoºh‘XýX¾çÔâo~J¯LaË·…Âã5­ÄÏø6ÓúhbfË·«ÀF`ÚŒ›pó»’§qó"ÜLÖK*.lâbÜØ‚ïÖnÆÍóAsü'Œ$TuI –qséÉïÅbhw¡UÊ WCK¸‹ÔzRévÂM k£ñß_ØMRí*ÚŸî:¨b¿åÛ¬=Ù“¾ãäÛ´-ÇŠ3 §Ñòm»Çænêß{1rË·™/€IÑܲó°¶!6è²?u­ ÿU­ÿ4ÊiûwíGŸõþ†ÒoŽã»ml¯ôSwûÑóëuCNM›ýhýx½Û9BÛõë}ûÑâXÓô#ìGL9FD/QÒ»ö#È2LÏŸ˜Aç+¦ª·íGÏ)|Îû+‹ÖÂvÚ_<…Ûxʳ%Þ…cÒ°ý¾mÒUÛL¦÷·íGû¢þ$ö#épŸlÛïÛ“-[w›lÓû°E–^hQHükö#ÓÉkö#ÛË+ö#: 1Ë2}ý(Dk?úÃ?½e?*RõgÔÂ(õ¨Šd禊dIðH¶H_ە߉jJÖÇ¡Ä+mF™>˜×ÅUñ1-Ѩ"‹˜ìð òΘŸÒ-ô|öàçàˆEÚv]¤ÄE8ÈüBÙE_0â|{t‘žÊ$žÁjBWéNßVGÇñUº…~¤9,9u²* ŒåÙÖriwÐuÝMâêJÙU‘NþoMðÌ礪ƒ†b„á2Rêõ©U¼=¥[ «‚ÚÇ”º(aKÛµ‘¡°ËX[^&³ímcµ>,™ÓÇړʉÁ½` }h*JßåY¥®~$rb9ìU¹%Ós µEQVºH³]ÙБ’{Љs³æ®žÍÃÝ»º]œí,ƒRŸúêړÉïÄÎkÅiq{¿ë"k†àÜ눫ßÅYŽrkWûDåZ¬ÝʤaÉgœHŽ«†]œÅ·H˜ºV Šc·²É3:‰³t »8ËÏôKÓZ)(ÎÝÊ©JêŒ+C»<+Á°¹ŠhDp(7yVœ3˜9N<ùkÚåY ¯AZǿѶ]žåb?YkÚåY¬!è`’ÎÑ–w› kÐ!Ø&iÛÚΨ{¼IU]5ïmç¾Ã>×(ïZv– Š=…HÙxµì-üÅZv‰–CÛ’µîm§&¹‰šYÚv‰–¥ƒÚŠã©uWFb£Gn•&²¼Ü®¢i¥Š è-ÒÚŒR¯M"È.Ô.<ÝÃ×ûíòñþ,f‹R;A5볩Ȣª^ÝÀ-fS3à;6z» ›Î ®Ö2Ù2ŒÃS,ï+ËiètŸ%$} Ùlc$QPU€l´u,yÒƒe1;3é2vlR<7˜M~¤ÁùÂl´m>ü´Ùæf1ƒÙh‰OùN‹ÙtgѸýxb¶´%罜8 Ù´îDGBÙlîNc¨Ål¾r¤5;1[fVÌN¢~5 Í6É›[›_¨M]}| j³m˃gP[Û4ŽàDmvqz‡RÖ¢v–}ç†ÝÒ 6Ûw‰™ÿ.Ôæ;q?”°µùܘ€t 6 ‚ø`LœPƒÚl£7ÀÈ·`P›¯t¬½Øë…ÚÒäžRG›± 1/ƒÔ%³…AmžlsœHw¡¶˜^«_COÆ„ÄC‡ž}¿P›mOѼ´åOBIÚx­••/Ðf¸ô”. hKМZïó Ú:cqÝs;hËf ‹éЖ6_ÕæaA›ßâŠmè9¡'pÓ«¬Iæ½|6䦩§Ö•:Å 7³€b‰òübÛ4¥d‡S™nq8þ6Û®ÂàË\׺œ˯⾖nÓõÇ('©Þù6ÇS˜/Ä…‡p’U\QI®!Üò2üóÚE¸5cfaF–pÓSeH•ró1f¬×»ÑÒm~IbM‰p7½µÛS°t›ÂhT.~Òm1ÙN²eÛ´Ê) y±íB±›PC-Û.Âp±ƒã…Ûb`Yn^–l£ ˆM"!F–l3*Ô g ^d ÏX{K¶Y?Žz† ÙFfuæ>·dm`€99–lKˆáÜ=–kK>™8#-×fEv±9·‹j3]“ðû‹jÓVE®ï'jÓ’ŸødUdab@æ†Ô—­GMœ¯$“ sSÃ*Tí.Ûß´}ÚÿZ¿9ïöѽÒQ/›éùõº)§KÖšÑïúñz·s„:¹ë×û¤1DíwþøA¤\$š’ÐPû$ h à¹ŒÉÛÿj,HÏ9|Nü;UõÆ)ÿn#Ê?… I:ÜͶ߷Ͳn›YÃôþ¶ i[VÜ?…I{ܧÛvüzJZÙ½Û|›î€ åÄ‹ ,¾¿fG²½¼fH:ºyÅ’©…j:Ò÷ïID ò¼ìHÿö‡÷âóÛì*IO 3íã<ÒCóQI²êߊii+BŸJ¯é’´muBÔXÔgö¶–Ý&Ú¦Htºò–Ó&Úb7ˆ8N£EZ®»hÛö°üVž!´ÐбÂP•¦´‰¶–ñB†#Èg–­Bm&¹Ó1_Ì7­nBŠ£«YŸ%–MjKÉI œ›´_È'•ºKZè Ðòeäkm«BQz•m[qŠÒ’€Duf%6vÕ<ä€Ô¢ˆP­»M¸… !›"·žvßȲ‡75V1YÒBcŠ£%¹wš–¸@K‡_q9,Œü·]SMйMÚ¶² ¢)ðš(ƒmÞmÂm— ³áYMûífK L°F`N§)N´ºGDàí,\ò“"ëÏ÷¢¶¥Ý˜ä>4Iäx®îÆ$ÈQ2ɘãV„:‰ŒÍ<¢IzL»1I*¨NkKgÍ’%Ý2ã z§Ý¥­›zŒ1i.ÞžžR Ôd$/ó(åéY¶ä £N@⤷¼¡–CbÔ Ó³Û’¨2j=D‘º:k–,é»0§6mI÷h$œ«„µV…Z/i·%Õ=(­—­w^aö3õví’üricŠž… Êò^Ÿ* œ•ÄjˆªaPý#Þ¢­•J nšÅJž KÓ•¤1‘Ïd­’Ý–T}˜á[øËM¾å?¬+½Fï[¾Rí„›ÞÓ&àÒ±ø©XØY¬díX¼3y‰¢éKmX÷Š…î Õž‡ÁÏB7 ,âÁÖ¬ÖÍa^.™ º=-À8½jƒ³Ðíx®%—ÙÝBƒKŸ-tûÀж02fèvLvÏätµ_¬»3²žEÂk» ‚À-vKºé•VTËŹYQO¢òC»97ëj/ƒŸåÜM&3ŽüùéÆéŠšKz#Ý4 qmÝÜì(§åÁaI7¹„÷Àg¤ûn˜œ›Åéba ÓŹi˜Ã¶Áçç߈™ÌÂ’nv¡gضNÒÍ2IƒùÒÍ @:Ö¹›tWIÿ×Hä/ÒM›8 ”›)¥œÜÛbd‹ߪ—¡Ü’(^ò©¦›rW–­šÁå¦y2Ϊ¿†rWÆn/9ÐRnn°3† ÊRn:$5 l½(wŸ„Y×Rn™ŒH3­”›U„!í)²”[r.G@K¹±:+£<³Äºe¢JóêTøõ’{./«ŽºKiaï0õ½ò^-»÷é¼£Ì˰ô 𕞼ß-KÛÏ×m<ˆô±õ\*ãÒä˜áõó}óÒåì¹þS•Âñ˜¥l÷‹¦ÊÀ`S#òü˜öùœþWnø÷O¤S–”oiæ¾{³KS‰Ïöü¾Ý#[;“íÿuCÓ¾¸¾Ka:)Èûâ”kž¯}ÊmϯO¹ìâ}ÊMÿ?ÀÖÄdšäÿš­Éöòš­éèæ[Se"sæ {™²ôEœÇ Ÿª¨mËÒs¥CÒjhßβôŒ^¢¡*h|†-K/Ö* [5ë·²ôR¤/KN†»,=%naŒ´î¶,=EÙ,jÛ8wõ¥ë $ë®ULLYz:¢¶†9œ¥Þý.“-@ÔRÍŽ-KOyËfëÒ7ÊB?ªËoué×i‘%͵Nø^—žOŽÉ»ëÒ³QµáZÅÐÔ¥ávÕî±eé©ZÀZ±8ûh=&¦0z ßκô’±6œŠQ}¯KϾ:Xµ„…­KO%@•p‡v×¥§Ÿ”F1[—^âpVJ….[—ž¶Â*gnêÒüvZžsºÕ¥sóªQÉÖ¥— ®.©×´Ë½.=mg9Úë¦.=ŸÄ}CµÚhÜêÒSýQÏT)¶.½6:JǺÆ{]z‰7òšÏñÛY›^ã›D‹}צ—ä:º“µªýV›>K±s6c–Â5ÆÄ4fkÓSáà[Š­M/žÎ¥°Ê–ŠwÆ2Õé =³‹Øâô|2:¦jÒ ¦8=O¬D[ên5µéÕ ,`uI³¿(ø¯±¯Ê;°žZ€pc=Ó[I¢¹xc½$ŽY™N¬g,†®¶þëѨs¥,Ö‹Û0ÀJÍ;Ö³òEo~9µXÏP)ÀCP‹ìõfnÄÅXÏâDKùu@½X¾ÐTz¾¡>ó’¨ú˜õL€ìL=õx-~Ú~@=^ËS7 VY¨gV#¦Ó"=u^`Ôiܾéù9¸yGæôRþ£¸=p =®æ^°mÆF¶HOsxÂðÖ>>³ÖÊ óµHÏ' n;•÷¤gÛ8ŸÒÓÄ…I j´H¯æ¬4SkZ¤çû$Fs^Õ†A1²ãÐK¿üÛ¦®1ı¦óÇ'Ý~¯.ÖSâ%Þ³1À“YÃ+º”wC°%Ðh_Reö´¿¸«ÓÐõ‹_úo,㈫è7ÿð±2W7DaVº&°Kž‚Ëî£x»öüÿûîÛÿòí_ðÿ@.«‚æ¼²qμûx43žTÜ|âZ¾:ä_½Øá=Âö.ˆß#¬¯pß+N¬W’û½5d‡º†¦Ã÷ÖP:¼GøÞÊ¡»Gø¬¡`Õzá/Å6òÀÒBkôu u#°Q½‘퇛mÑÑAZªnÿ9«`øQ½¤No¾ZÄpðgzI?®—Â<ß7’òÝ>?wRÅÑÐõóÍÖù|Èþ/¼ƒô–ýo%/«§’3²àH¾¯$ü'ë§üí/õwÿë_üö_ÿð»ë›ö]ó=·!½øº0LMWRþ'þ&¦Øÿ÷ûë™2× Iïž~†ù¬rÝèèF³èWö*×t»…æGþ5SåºEJV#iÍ?Û*×-2e³-©°²W¹ndGGyS庹—¸a4U®µ Ô5¨ÁT¹®TWú'Iíß­ÈusRYzfm3E®+> rW!ð;Š\³ÍÕÜg½í½Èu•1q”ÔjÕ[‘ë 1‘žNC}¾¹æc¢T}›)rÍÇ’²¦Èuí”÷!÷OÙ«\W¬ˆ—†Zy¯rÍç’«›©rÍoÉOk’©rÍoÁ˜Dkòí¨r]é¨+.ÆN«Uo)fø-Œi*ºYL•k~K~¢ã´Ê5ˆí³hKM‘kùö©78Š\Wê@=“f/3E®ùúìYMm¦ÈueÖg£›"×ül›™-ìE®kcÕï#aŠ\ËÚ@ü¦=Säšß™ò²4š"×|N˪ÉáÙ‹\ó1÷èL‘k~ VlÚ4L‘k>—;œ)rÍç ¹9Qf˜"×<;ì¦Áo/r]E?VòÈ/gŠ\³;5¡™úÖòߎÂÖüË@隦Õ¶æ§Eã,¤½W¶–Ý×.0•­k«ø‡xHO…©lÍ6—´¢Á·£²5Ç´¥Ú3•­å;Ye{´%ÝÔ!—Y’ã5ë¦k¦§ ,Cu5sݵQЂuc Ö֌єúóêaÀšµÅpKN+¼k>÷À k–,f5ág¬ér‰iî'X³?î¾êÚ ÖTÖ‰ÕJ4ä¬ùÆ––¯€ëVË×Ï55`ݨTë±FÍTgÀš‘#Øp³HÅÖ¼ùÔÔëã ÖT‚-;Ò°fw@\Õ(oÀšÝ5€ °úkœ²½ž¼k~KÀ æÇ=µƒ5û âZ¢eïw°f%U×Ç;w°n…áÛÏøv°fúÚÆ-,`Ý «W=7ÔŽÖ ?â“Í 5;Ê.L3‹AkÚa§—ƒÖò\ÌÂX°æ§¨ Ú]`ݘ: _’ÇÆÛÁšÝX§†k޹<å, X³¿Xñ!j/ßÁºIyÉ´O°fÛˆÀŒ'XóS||PhkYn¿ ׬ن8?skvBšÄ€5È—ª¢˜Al~ФyÓÞvÜ–IÁÀ6o¸-_âÛ 84¸- ”«¤€S2I· ·ut²\ýÄmiô ²fp[hÍ´È ü„øE\ÿuCå‰Û÷¶Ü²póì—™n[Êê¸c.àfQø±¸™ÕALÕ„c€›&ÂBãø`à;p3¡ Vcš¸=˜á°·[ànŒMõ~þ†ÜBåžWä¦Wè¢à¹™dùOÈ-…&G2Èͳý¬(gÓ>Òu|‚Ü‰Þ yÒJ‹ÜÑH¹£©×è pÓ¨õìg Ü,k[òê¸5Pq8áXàæp¿D¥k¸7õDµZàfx—zØLÐ&åÍ“.XЦóÄSÌË‚¶Ôn[ùp-hW¦TÍŸRl9uøò‰”µ%»T7n?ƒÚ¬øúD/[ÔfùÜ(®Ÿ 6“v¦u)ÔΑ^kì¨]ÅJBnЦÃ*»{€6£Æ MŸ!¼³ ªl@;yûÜÚübºª†~ƒ6!Ì…!¯XÐf­­‡)YÔNô…W‹øÚíY‘ µ%¼¿³hQ›ýaWÌç j³dªx´ësµëlדs 6ÙkU*U%ýÖûœý7=L p3Sªo渙äs” ¿€;±Êzžé‚-p;ÞI‰vøp·“<´s6 p£_ö™ûP0O)£`ú¡É ¥%Lžk€;0 úsd7àA›ç|`ºÑücᢂ‡Q0 ÿp\gV=R%ëvQ÷'n3ÍguëÊ2êƬ?§Äâ¶ šA«á‰ÍYƒ³­v¤Ò]5ûÁC¬vÝAÚ÷K˱kG$R;Î ÙjGÄ‚­Ê®¡é¿ú22ÎZíH)»²Ã(GăbQ©¡¡+ª¸<Ýʾ*†:²NYå+Šã±r³íJ6×Äý»žÀ]qSEìÈy1Ý•€›ÒÁèFH©EÏ—ó Ü|gÙø¯Ñà»NËèF(š<ÊC£á½ sF7¶@÷‹Ñ°h"hÆP?YÝaV”4 ³F7²ªÉèF( >ñËV7BJ©ó*Y ïý$qÖíDnù™¼pëIè`ì–"ÂêI€¤iQ«&¡ øÈFK"ÞpKWfµ$G½*ÒNÜæÈwŸôñí±4_ó œ>#tãQ»«Aª9ŒRk*[ßôù¬÷WLU}ú#¶—à3ò= ã´û—ΪN_ñÈøÇ=2b7Êâÿ¿¹kI’å¶{f‚dñ{ ÄÛ÷#AD²'B~zª mQÝlV±²ÀL Ñ¿$SäË22ªgØ2Žòƾ•YS¾ìºrp=úƒÌs¥¼stý~ä Š–û–q7æ >dèõ5ùÞ‰n@o’œÊ¤ãs"ºA¶Ÿzyéá.'ÊÆ¨¨µ–&•“§Š–»-ããü¸~?š!ûfñVm‰ì7@¯™Â”q’·ÜÆäf¬v99»Ž?ÈWxäÀR×ò²OÇHÅßÔ[ΔŽ!gÉf}s¹Ò1œHœË•ޱ*³ççºÖ°,¡[î\léÍÏU×ñ„C=鹺Ž?XÞ“í|šÑñÆŽpx<åö,E17JÇ€£äåæÌ7ŒàÈm¦cÀV¯ôEÞæî)”Wk´šûQÌN4wÏ9€8¯ò¦\×P>(—s±åcFþêî·<§é†dûì òPjÆ#ÌŽ’]ÓM£xêθ*™R3ÐYáÙ¬|É”š²ØlJqmð[B¬«Ùd)”™¡I;Û]}Ì¡ SsÙù±:ïfþUÙ_Ìʸ»¡ÏÑ'oĆo@3eŒ»O42bƒiކ鵑&!×d%Í0j÷@K¨­=;K ß¡v{P…½w¡¶ê,ê¹7ßÉçe Ë¬5¢"Ô^ycIË„ÚУj2áœP[%šå^jc>AÂ`áQ2°¿ÒùÊËpô8¡¶NWëzÀ ´5-#ôE™f÷Ùèj7Ø$ÌVKÒnل٘-Êu^Vê„ÙËòx-ê“0 Oò¦^¢ a¶êôòê ëwVÆ´;W”!ÌV=çø«fë]Oö•#A€­ 鈶ëådÀt¥ï.`ØÈ>·±”8lÌ×’:„ä°5ûôø`«äî ·â•“q:b㧸$9Bl½Ù±§ô±uÛe‹[±g¶Ãìˆ~#¶æ€ã¹ ±õ² þv¾s`weh¾ Øš˜dÚ%áõ¼?–YKxÝÕÅÈ])ñô™#¼Öd”#´`ëEñŸs€­éBç•S§V[.`~Ù ™aïÅjÚÃvyÐîyç›0lË•}$j^Ùt ÛÕ"]t>¦lÃtXÐÌÁ¶ì”ŒØÏg¬½į̂Øõ.0j‡gKþ„Øaø†¶ŒØ²8®)FìPáTb/Bl¨ylÍc²õ–òEˆ­Õá-¬À„;ÀÂ$ìôFlù)ºAWèH€…Oú.Îîpd®i‡yŒÙ~:–tqÅÙ¸ÃigÙ]qö@îÂNaá8ÍGÔêø²ꂵCö|…Ï0ýV¬¡+GÙÃ?4d#°•MhÁ9%=ãpTv²Q«/ÿا ²Õ¹Ç„²5Ñ4>+™›1; ÔTï÷,cv’sa¶À˜1Ë4#ÈŽpxïKÀbĆٷlŸõ`0bGÔD› ͈¡vʉjæÐ0bLJÞ„Ø2æQÙv>™;‚G²ŽÚŒØ·Ç^› Ù¡ù4-†ì€†5§©^3dã;cÚý—²aä°ì¯åFÕ$QÐ<=\ËgŠö5M`Ëvpe¿¬éI±xKôèœt%þm²Ý}SÓûnö7¨Ä½Ž¹µ½2OóšÞþëÄ5YÒÑôÖ?0í^á¼¶ç¯×5½µÄuOóohzòŽUkt5Îïjz¹¥†/‡¥Ñ¯È‡¿­é!1J°3H ^ÿž’Þ‚9¯ì›žà¼n=õìÊwnÊA4á{rNø¹Â÷ä ÝŸ+|OÒó{åG$=L8ï!MøÞ=Ô ?WøÞ=Ô‡îs…¿!é=hiÒ=þ¼%éñoIz4Ëk’Ïò×KzH¢—Xηå$½ô°¤÷ï?ñ†ùÿ$=47²®Krš‘ãÈ:¿ ˜$bˆ5w|3‰5•cS×q­šUg¢é¡´ªÇô¹úxªœÛÛ"¥êSN×%d÷ßjßÔÏÎÎo°jl›Bª8Ç/o/4ƒjpºž”aÍži€a5Nó0«ÝµÂªÍ”¾ÌfLšHÚNB“çÔ‰ÃÐÓº.áDèš²Á^4Ÿ\ÿ­í61V=Ý c®PP=Ï®£çn˜W«çà€}jàÛì¿“ÙÐAËÑ Ƈ›<«­Ÿ®K}º_o»v¢ÀãMQ»§ˆAo¨µrܵ÷ãK‡Ÿ)ÿýYöÏuxŠ8¢FrÙhÚnm—ptu©ãu(C,ÿ±Ö†ƒ¼mX9ösjmÁ3ÄJ•ô]ÙÖp· À°¦¿Þ¢'‰‘”žñ¯ÊH·èIâ}%uÃY~oXÐ(C;<ê-mÉQMI7ÕÞp–ß;?³™ÕYmM´ Îò¶cås½¤±8µöxÊAײ)Çþ™§‚º»ÙwfO9$ád¿ÊZö”ƒÚ}çÕ¯eÏ8„Ç«­xUOËÆŒýhÅQ¸“'e»¢ Ú¢¤[%ÊAÞ² VR|«D9 ØÁªP[õªÞ¨¾¼¿5¯êÁûŠ#·þñüÍ•Œê¦b ‹¦\QÃW>ûà-iï¸s[¶ÀݽÜÏÀ=´áâë·Q•PM„`ÜꃘV}-ãvC9|Ü’ŒÛ8í‹€[†BM›deàF1W4n˜S ndÈÒ0p£`kØSÎÀ-cNaàž…^;ñ€[»Š™GwƒÔ`ô'7Ê ÜU!à–±ØêX*7J’•¶3pC'Mðodî¦ íÍJÀ-ß¹» 0jc`VTÂvC9sØ´â‚m”òó†m¬þ”ó0lC}¬Èƒauë}—T3jcH~À†CBm|e·¼ Bmý)E›¤ÅÔÆ>õ„ÚøÊÒëôk!ÐÖzý 1hk) UÄ1hCr=$8ƒv…tØ 'Ì®°lÞ”;C¶^æf¯Âlܳjµ©„ÙSÙ¶JeÂl ƒ1 (–ÙŘ-c' ³QÙw¡A6†f°£ÕVÙêúЭ ™ w‰Q«æ![=ÌIB![µu{'¾¨ì1jwõ¿Ÿ¢ÌÚ€M¶dÔFÎç©ÊeØ.¨K*š=l«¿Ø Ò=l?Õ+‰ Û:Jš’H°Rd}>¶ñ,¡áúÌ!`ØŽ ^â[bØŽÅg2lËm4ó¸âm¬Õêe¶%²‰GÈbØFÛá÷¬›Œa[>×KÛNIÛèrºLN>Âm¹“rVA)¡6"9E¨¢Äm£G½•2hãcÚ¶b´Cô%ãv ûyÆm/G}š¸­IŒ§ªú ·‘OÙwVÈn£»®,xêtW¸M­« ¸1Ÿl¼wAÀ­Êä‘À®pÕÑæSEÀ­‡.²tÀ¬«(¸·ÞÑn#©ð$½rk6ÜcבûÊ\#ä†gSXÕß7tkþàØ9aÝZž*Çߥ]tc }µ%Þs¸ ëèÖ-ÆuЯ”ãÐ.º$èÆ¯Ì§¼ còœíZ~‚n|'\kVJ(‡Û˜o½>?ÂmP\£ín<nËX=HDØ­½Ù2‚”3CôÃ_VùpÈ^®¤à}&…©ÿ:)pŒ¿©ó};ÿã^È¿üê^™hT§ôí¿~@rè?Jßúã¦Ý+œ÷üõºÒ·–8çµ?þŒÒWª"ãå#öªÒ‡îÆ( NI=üNé+HlÊhÁ€Î0K©ï`ÁAwÚ.¤y ÜŠÊOˆ}˜p E4á{B‘Nø¹Â÷„"ÝŸ+|Oìs»EÞû?¡öéŒó.ÒŒ/:w댟k|Ѻ[¼Ï5þ†à'ÿ Íz@ôñ–âwMò–äÇÓ¼¦ù]Óüõ¢_A®¡¼ä@ïÿ³rj^ôûï¿ß«ãëOóÜ1 òâÌÒPÉËBäܾÙ%¨kNôs&§•y"•£©ýp¾¶.®Ðë Q2’Š¶Ô†?è—}®$Ü” #¼¥á‚9,ªŒkÔ†ÃBÀvoìþ¨•8,tÖ7»ªâQýäK£}ëHˆæ³/A];BîKËÛ¹u.³6­@Emå ú4»ø˜èŽ,+c#8F±mç¤÷‘= Ñü¡å?‡;y¡I×Ò 1œÚ³hÍ2Ë}Î@k„Æ„<5»TlÈ·¸ìâîst¡±;b¸kÜø\—@vi_ó¼‡KÕí¡yQö»Àû@ÞØ-xé\µ»åjF‹S¼-(•ÌPü#ÞŽOÛÒ+c÷S}׎+ÞFîW3äóØ“·ê¼âí ßêý0_ñ6.¸¹`^ñ¶¾~ΘÇî„(¦oá’Á;%ŸoÂà’¯gðŽf¼q.ˆVÔDàz ì|oýJËTcðdÍñÙ)YWÔ ÅÑ2t®°»!CgØ3xãÛÊ¡Èyݤf$æu3“›FÔêÈ4ozÌAy÷V“^[&L2ØÔ“hnemÓââmå¤@ôžá¶òÉeÌÓÈŸv«Ô~+{+ß«lž|Fn{>_ÚˆÀ_èN¶dllÚpd½è¢/ˆ±²íäïcs¶’AO@kͨ[d÷ 4—DÙ’ë÷€°,WG6á®Á“ÁLµ‚möë™—u\<ƨÖM¶jж#s#‡è½ˆ¡“~=¶‘žºÓ:OCË Ë>—‡ÞóМÒ.ƒè&hY“Ñw“ClÚ}dmd˜ Êu]`·B ¯“½Ö¤õBúv x?‘ ÍõBz¤…Èw-EéBz4˜:N»Ò÷Ç·â¹¾Ã(¸î¢µ é;êÉêyGx¤oÃד]Pßµg¨—)ú‚/¨‡ ™ãÞ¬Œôè”tøª éUü3ïBz˜§ÞúBzô-’û;I¾ èÑð©=¥íçÕ½Ìèjb/ WÒºË^@ű¶Ý+õzH•É£ è¡GYã·@¯ýs#¼€^‹ ­½Ðô ˜õ>Þ@0Y%ØôFº‰­У·î±9½€â©û½€Å—FÙ_8gØV·ìpá<Ê„Âö‰»`¾i?÷]ÁÏ8UÕDË æås®m×ó<ÖŒó*Ùís<”Ðc p<êëðˆÏj¤ äÕk×ä‚ äq;Œ©¾@¾‘%;ƒÍjåÞì xá|>•8 S/xá<~ñiá¼n\3 ¸p¾ .ß&Ì?GÝË÷‚y4ñ:oÂ+ ï¾Tì‚ù§ù>ÒÌ?꺒/”’w>¼úCÏíáqÁ|ªèÿWŸÀ; —DÚÉ\Ê£kà0=ó‚ùô ËNJórlµíJ¿ æåƒ²ø[Ì'Mß;-Çóž#í·Çóxµ”çyÇóC—v€‡ãyÀÌpáŽçåF˲Ší,ž¯ŒŽÏwhK¬曺›çnpÅñ¼5–¸cùâóXãÕ~ù}ûj{Œ‡%ût—Å}ÆòΗ„@ß*EÝü¶‚|ewœ%œÇBœ)ã¼&õÉ'§C Ã<®]…ùÇL|c˜×ßg‹Š˜Ÿu¦–ëÀ0¯MG5_E« Çê•Ó”ÿç?þ]6R¥ endstream endobj 3 0 obj 34245 endobj 4 0 obj [2 0 R] endobj 5 0 obj << /Resources 6 0 R /Type /Page /MediaBox [0 0 1080 792] /CropBox [0 0 1080 792] /BleedBox [0 0 1080 792] /TrimBox [0 0 1080 792] /Parent 7 0 R /Contents 4 0 R >> endobj 8 0 obj << /Type /Font /Subtype /Type1 /BaseFont /Helvetica /Encoding /WinAnsiEncoding >> endobj 7 0 obj << /Type /Pages /Count 1 /Kids [5 0 R ] >> endobj 9 0 obj << /Type /Catalog /Pages 7 0 R /Lang (x-unknown) >> endobj 6 0 obj << /Font << /F1 8 0 R >> /ProcSet [/PDF /ImageB /ImageC /Text] >> endobj xref 0 10 0000000000 65535 f 0000000015 00000 n 0000000145 00000 n 0000034464 00000 n 0000034485 00000 n 0000034508 00000 n 0000034938 00000 n 0000034807 00000 n 0000034702 00000 n 0000034865 00000 n trailer << /Root 9 0 R /Info 1 0 R /ID [<894D4D1CC21AAA5E5F8E4F25EF75E7CE> <894D4D1CC21AAA5E5F8E4F25EF75E7CE>] /Size 10 >> startxref 35019 %%EOF blis-0.9.0/docs/graphs/large/l3_perf_skx_jc4ic13_nt52.png000066400000000000000000003123431422157504600230100ustar00rootroot00000000000000‰PNG  IHDR¬öEYa )iCCPiccxÚ•‘gP”‡†Ï÷}Û m—¥ÃÒ›T) HYz•^E–ÞY–"bCÄDiŠ AF¥H¬ˆb!((`A³HPb0Ѝ Ü¹3qîüÈóë™wÞ9çÌŠ*’*àû¹Ø³CBÃØð ‘¼Ìt®'ü#Æx ÿJtL&V Ÿ—Î ¹ •#H Ç€•”.@Γ€ÜfÜ_>̨¿|˜ü?@¢Å}ãQßø÷¨pù‚„ؘ\¶Z¬ '’ÃÎôs±g»98°}øi± É1ßü¯Êÿ€ &Wà–¾…Ÿ/`ÿßPcC##øûï|„5ø¿ÿ€oziœEìÀßYT5@÷é'gjÇD ºîñ²øÙe8‡ÏÁá+ñÍøNü ü(~ÿ@ °šs‚+!”HØJ(%%t®† S„E"‘(CÔ%Z½‰‘D±ˆXMK)Hq¥b¤öIµKH-IËIÛIÇHKwHJ–aË8É$É”é–y&‹“Õ‘õ•Í‘=&{Cv^Ž)g%Ç“+–;+÷D•ב÷“ß*B~P~QAQÁE!]¡ZáºÂ¼"KÑN1Q±Bñ²âœCÉF)A©BéŠÒ+¶$›ËNfW±ûÙ ÊòÊ®ÊYÊ ÊCÊË*š****ÏT)ªÕXÕ Õ>Õ5%5/µ|µ6µ'êduŽz¼úõõ% M`½Ý³šÒšnšyšmšZt-[­ ­F­‡ÚmŽv’öQíû:¨Ž©N¼N­Î=]T×L7A÷¨îðü‹5©k׌ëÑô¸zÙzmz“ú,}Oýýný7ja  ¾š&6>5’0r7*0ê5úÓXǘg\küp-}­óÚk{Ö¾5Ñ5‰19fòÈ”aêeº×´Ïô‹™¹߬ÝlÎ\Í<¼Î|œÃäøpJ9·,ðö;,.Z|²4³XžµüÃJÏ*ɪÕjv溘uM리U¬#­¬…6l››ã6B[eÛHÛFÛvªvÑvÍv3\mn"÷4÷½¡=ß¾Ó~ÉÁÒa›ÃUGÌÑűØqÈIÂ)ЩÆé¹³Šsœs›ó‚‹©ËV—«®xW׃®ãn n<··ws÷mîý4ž:ž|Ï^/ÔËÝë×Äzõõ©ë»½ÁÛÍû÷3MŸ ŸŸ} ¾>¾µ¾/ýŒüòýüþ›ý[ý?Ø”< Ô Ì ì  j Z v .†„l ¹*šÚF k[Üà´áð†épÓð¢ð±šs7ÞÞ$»)yӥ͢›#7Ÿ‹ÀGG´F¬DzG6F.F¹EÕE-ðxGx¯£í¢+¢çb¬cÊcfb­cËcgã¬ãÅÍÅÛÆWÆÏ'8$Ô$¼MtM¬O\JòN:™´šœÜ‘BJ‰H¹*‘š”ÚŸ¦˜–›6œ®›^”.̰Ì8œ±À÷à7g"™3{LAº`0K+kOÖd¶MvmöÇœ œs¹â¹©¹ƒ[t¶ìÛ2“çœ÷ÃVÜVÞÖ¾|åü]ù“Û¸Û¶#Û£¶÷íPÝQ¸cz§ËÎS»(»’výR`XP^ð~wðîÞB…Â…S{\ö´‰ñ‹Æ÷Zí­ÿ÷]ÂwCûÖî«Þ÷µ8ºøN‰aIeÉJ)¯ôÎ÷FßW}¿º?vÿP™YÙ±„©ÆÚuÈëPW»¢¸âýá͇oWšTÖ¡É:"¬ò¬ê©V«>P½R_3Zk_ÛQ'_·¯néhôÑ‘cvÇÚëêKê?O8þ¨Á¥¡«Q£±òáDö‰—MAM?p~hi–m.iþr2õ¤ð”ß©þó––VùÖ²6´-«mîtøéû?:þØÓ®×ÞÐÁê(9g²Î¼ú)â§±³gûÎqεŸW?_×Éè,îBº¶t-tÇw {B{†/¸_èëµêíüYÿç“•/Ö^’¼Tv™r¹ðòꕼ+‹WÓ¯Î_‹»6Õ·¹ïéõëû}û‡nxܸuÓùæõîÀ•[Ö·.Þ¶¼}áçN÷]³»]ƒ¦ƒ¿˜þÒ9d6ÔuÏü^Ï}‹û½Ãë†/ØŽ\{àøàæC·‡wG׎=>Š~4û8ùñÛ'ÙO–ŸîœÀO?{Vù\þyã¯Ú¿vÍ„—&'_ø¿x:Å›zý[æo+Ó…/é/+g”fZfg/Î9ÏݵáÕôëô×ËóE¿‹ÿ^÷FëÍù?ìþ\Y˜~Ë»úgé;™w'ß›¼ï[ôY|þ!åÃòRñG™§>q> |þ<³œ³B\©ú¢ý¥÷«Ç׉ՔÕÕÿB,¾;E^ cHRMz&€„ú€èu0ê`:˜pœºQ<bKGDÿÿÿ ½§“ oFFss0ˆÚÿR pHYsNNÆÊ/¥tIMEã$:.$¶­ vpAg’Zó!%Õ€IDATxÚìý}œëö]ç NI6Ó*M»4>i»š–Æ<Ý´rÏôfK"·]hõCåeá@†·s1Ù.ì"m]`X ®kã{§µxØÉØÅ¢CzZÊ6V å¡wæ`‘ÂfqZµ$Çéc޶>$m(sÿñ›¯,˲-{ì±ìù¾_¯y3–,Kž¯~ú}~ß§3‡‡‡‡`†a†a†a˜ŒqݼO€a†a†a†a’`ÁÊ0 Ã0 Ã0 Ãd¬ Ã0 Ã0 Ã0L&aÁÊ0 Ã0 Lp]wÞ§Á0 Ã03+Ã0 Ã,0žç¡X,Îû4˜SŒmÛð}Þ§Á0'ÛûÉ•a†a†™ÇqxÏœØÞOžg½ýíoû¼Oâ´.^¼ˆ÷¾÷½ð<_õU_…o¼1ÜnÛvxsH’Çq ( Àu]ض ×u!In¿ýöð}¦iBQ”ðØA૾ê«Âãyž‡W¿úÕïÏ0ifヶٶ  ËrxÇqð'ò'P…í›YfeûªªÂ²,|á _üú¯ÿ:èqþÃø}φ9Ãìõ½ï}/¾ð…/àÆo„,Ë}6J¯ñ˜Í, DZwI’ŽûlדÁÖ9VWWÃü#ÇqzB»LÓ„eYá¶R©Çq–e¡T*…Ç) °m;|/m‚A T*¡X,Âó¼p»išïÏ0if㣶Åíí8öÊöÍœ4³´ýr¹œ¸ÊŠÅ"‚ 6渌š«ÄI²Q³™Eá8öþÈ# }/Ûõ„2s¥ÑhFÿ W¯^=TUõðàààðàààÀáÁÁA¸]–åp;€Ãf³n«Õj‡’$…¿8¬ÕjáêºþnÆ¡ªªïÏ0ifããØ³Ù<pxõêÕÃÃC¶o&ûÌÒö Ãèûœ«W¯öÙ5ÃLƒaözxxx¨ªêa£Ñ·Çm”^ã1›YŽcï£ÞËv=ìa3òU.—ðÞF£Y–á8TUí Ó4 €–e9¬ýVi¢ÇI’ IRªóI»?ÃŒb˜Ú¦(JQà8t]ï±I¶o&ËÌÒöUUíû,XçŒ,Ëh4€R©„3gΠ\.! ƒð}AÀ²¬žŸ¤ÃÌ“a6>l h¢“v¶of‘8iÛW†aô‡a¦Á({e˜eâ8öÎ÷Êl`Á:g¨R­VÃÕ«WÑl6á8lÛ†$IE«¢(᪠ýÔëu†ÁyKL¦fãöbÒîy,ËBì9bŠ“¶ýZ­Ã0€s ˜©2Ê^f™8޽ó½2X°Î*¤DÂT–å04€&,”¸Ahðªªöüt“¾&K ³ñaÛèwMÓ`Yt]Ÿ÷¥0ÌXÌÃö%IB¥ReYÜv™£ìÆ0‹Äqì=Í{™ñaÁ:g(/iuuÅb«««áDE–eÔj5‹E‹E …0,Œ&%¦i¢P(„‚ëõú¼/‰azfãö´8ÃÞUfј—íkšMÓx“™£ìU’$˜¦É^$f)8޽§Û™ñ9sxxx8ï“`zQ%I Cz©€’,Ëð}²,‡¡d$L£E–(L˜a²H’§ÙfÛ6,ËÂÁÁÁ¼/a&‚mŸYÙkt¾2¬0 Ã,DZ÷ac;3>,X3ŒïûX]]E³Ù„¢(ð}Åb†apx$³ôP8M¡P€®ëanÃ,;lû Ã0 Ó…C‚3L4$øÌ™3( a(Ã,;žçáÖ[o…,ËlóÌ©‚mŸa†aº°‡•a†a†a†É$ìae†a†a†a2Éõó>iñ¾÷½¿ök¿†ç?ÿùó>•©ñøããŽ;î˜÷iL§žz O=õT&þFO=õVVVP­Vç}*©ÙØØÀM7Ý4ïÓ˜Y²‡i‘¥{öñÇÇ{ÞóžyŸFjx Ï>YºgŸzê)¼ð…/ÄOÿôOÏûTRÁãwöÉÒýúøããç~îçÏçç}*©àñ;ûdéždü^ÁúÜç>ßøßˆ­­­yŸÊÔØÜÜÄÎÎμOcjìïïãòåË™øѹ,7ÝtÛCÆÉÒ=»¹¹9ïS óO–îÙEÃyüÎ>Yº_777F¬<~/Yºg'¿—F°.#ÔsuY8{öì¼OÉËhËvÏ2ÇcÙìaïYf2–Ñ–í~eŽÇ²Ùâ߳,X3Ìúúú¼Oaªär9är¹yŸ“–Ñ–ížeŽÇ²ÙÃ2Þ³Ìd,£-,ÛýÊe³‡E¿g¹èÃ0 Ã0 Ã0 “IX°2 Ã0 Ã0 Ã0™„+Ã0 Ã0 Ã0 “IX°2 Ã0̘xž‡b±Øócšf¸þ§X,†ÿw…BgΜÁêê*lÛž÷e1 Ã0Læà¢K Ã0 3&AÀ÷}‹Ehš† ày^âû\× ÷/—Ëh6›eA P(@Q(Š2ïËc†a˜ÌÀV†a†9&²,‡Â3 ¾ï‡ïI’P«ÕR¿Ÿa†aN ìae†a˜ ð}¿/ôWUÕЋ: êñ·ºº MÓ ªêÒõýc†a˜iÀ‚•a†É<¶mÃqœ¹žC¥R®›F¬ÍfžçÁq˜¦ ß÷Ñh48$˜a†a"°`e†a2®ëÐu}ާу,˨T*áïŽãÀ¶íTçIÂVUÕP š¦ Û¶Q«Õæ}i Ã0 “8‡•a†a¦€çyaNê(‚ €eY}¯K’4ïË`†a˜LÁV†a†™×uqæÌ™ðwUUQ¯×áy^â6ª( š¦Áu]¬®®†"7‚ž}†a†aÁÊ0 Ã0c£ª*ÇÞ}½V«Á÷}ø¾I’8w•a†a`ÁÊ0 Ã0s"ÚÚ†a†a˜~8‡•a†a†a†É$,X†a†a†a˜L‚•a†a†a†É$,X†a†a†a˜LÒ'X«Õ*Ο?EQP­V±··‡jµ:ïód†a˜LÊå2n½õVœ9s¥R žçMõ3<ÏC±Xìù1M3ÜFÿOÂ÷}‹E8ŽÓ·Íq œ9s«««°m{Þ_'Ã0 Ã$Ò#XI ®­­!—ËVVV°··‡ÍÍÍyŸ+Ã0 Ãd†b±I’põêUB×u‹Å©ŠÖ FFµZ ŽãÀó<A0ô³lÛF}‚Õ÷}”ËeÔëu¢Ùl²¬©‹m†a†™a[›v»ÝÝ]ììì`mm ­V €è'—Ëåpþüy´Z-äóùyŸ3Ã0 ÃÌÇq I*•Jøšªª¨T*°, ªª†‚2èºMÓÂ÷’G“^÷<žçÁ÷}xžEQzŽMP²£Î±Ñh P(À÷ý°}ýŸ~—$ µZ-Õ1†aæ¤ ë•+Wkkk};åóyäóyt:±¾¿¿Ÿx¼V«…•••Ћ;îv†Éƒì`gŸÌٷa( I½¯¹îð÷Ȳø‰ây@’x‹ŸDeMÓ`š&dY†mÛh4$ ¥R ’$A–e˜¦‰F£@xiI€Z–…z½Ã0P(Bëû~_诪ªp‡\›çyáçišÇq`Fø^X]]…¦iPU5|í´9ûf˜)Ãspf™ëÊÊ  Óé„ÿ':NèqMK»ÝÆææfOˆQ»Ý†a=Þ[˲Rog˜¬dßô:Û8³èdÒ¾}?øW°ªj²`MÇIÇ!IRè©Ôu=µº®‡SUUøGÇWUŽã@UUȲî?ʋꎸ.Çq ( \×…$I=‚šÍ&<σã80M¾ï£Ñh$Šðe#“öÍ0S„çà̲ Vò¢nnnâÂ… áív/^D.—¸¥Ýn£Õjaww·oÛöö6r¹î»ï>t:œ?Õj[[[©¶3̼fßÛ8³ØdÚ¾UUüŒKBXíHt}ä.²,'æ|º®›(ú¤ˆÐ ‚ œ’$ônʲÜL!Åúó´mŠ¢„Nß÷ÃPà¨p¦s5M¶m£V«ÿ}-™¶o†™<g–•ž¢K;;;XYYÁùó籿¿ÝÝ]Üu×]h·Û©WYö÷÷±··×÷z»ÝÆþþ>666îúúz5j;ÃdAö °3‹Ûwz(Ì6*Zƒ €iš¡Œn#O§,Ëaîke1}t\9îŽà8dY 55ð|é<“žéÒïñ¢ÃöÍ,;<g–•룿¬¬¬`gg­V+ÌW]YY«ÐÒúú:Ö××±¿¿ßSY˜rd£ÇÊçóh·Û©¶3LdßÛ8³ø°}§G’$4 ”J¥PøàL*3úN§3r{<¯6Îg?ûYxžÇá ÌHö÷÷qÿý÷ãoÿöo§zÜYÛø§?ýiT«Uœ;w.Ux>sz©V«xüñǧzLÃûQa%`EQz¼”ªªB×uø¾ßöKù£t Ú7ºOT<&~¾ªª·ÅÑ4­GÄÖjµ0LX’¤…Ê]ÝÛÛßþéŸNõ˜<~3YÆïv»=µÂG<~3Yæàãғú²²×u±¾¾>õVaøÚµk#·ºYnºé&¼à/À¹sç¦~îÌrqöìYÜyçøØÇ>6ÕãÎÚÆo¾ùfœ;wgÏž=Ù/ŒY8Î;‡‡zhªÇä1|0ÃÄ^´}LÚ÷œƒÎ-ëäóy\»vmªÞ¿™¬@ã÷-·Ü2µcòøÍdšƒ;~÷T ÞÚÚBµZx㬚 óÚær¹‘ÛGqÓM7áöÛoç•Kf$Ÿüdÿù?ÿX]ý³©wÖ6~óÍ7³}3©X[[óŸýì©“ÇðñÐSnb&ƒÚìÛjoÔ1Áã7s’Ðø=J$ŽßLVÈår¸óÎ;Ç¿{rX···``½ãVZUŒ†8Dÿ?j;sº±,À¶ƒñ»iš&Ú"NÂ÷~ï'pxø€ožÚ9²3Ë Û÷x,¢çò4ÃöÍ,3lßÌ¢ÓS%Øó¼¡?ÇÚâD«—¹®‹b±˜j;s:ñ<`uU´Dl6»¯kpT³$AÐÝ_Q€W¾òsS?W¶qf™aûf–¶of™aûfëˆôlmmassûûûa÷Ýwßz;³X¸®Š’$Dâ¸|(•€Fˆ;+¥+`=p±íÿ<Ëÿó'mœYfؾ{IšÌišEQŠÁÌâÀöÍ,3lßÌ"Ó'X÷ööàº.ö÷÷ˆXzUUÇ.Ä´¶¶Öç•Íçóx÷»ßV«î3Îvf1p]!!ƒ@ü®(@¥"¦$õ‹Ð8岨Ô~²,ŽíyBä’Ùx½VÇ™&Iö °3ËÛw:\×M¬ÒÁÒ÷4]dؾ™e‡çà̲Ñ#X«Õ*vww±¾¾6ît:ØÞÞF«ÕÂ… Žý+++Co‚QÛ™láû"·èŠBÛ ˆthèÚ Æà㺮›±V‚‰H’Ø/;'Û8³Ì°}Æ÷ýÐÃjÛ6Ç «“ÖqØGƒ§®ëÐ4-L¿¡÷+Š‚Ê´WÛ˜¡°}3Ë Û7³¨„‚µÝncww–eõô‚D¯·ÍÍMlllp6Óƒ, au&ÔëÃߣi]Ñ:U,x†a²‚iš=¿ëºŽ àû>\×…mÛh4ð<ÅbªªÂ÷}˜¦öZ-‹eAÀ²,Ôëu†B¡ \†a†9­„‚õÊ•+Ð'VÏçqåʬ Q¥W’†{R!ËÀ Ô.òزSa˜Ü£Ÿ$Ô£€ @@cŒ9ä˜4ÎØGïÿG?:vÚSv]èºI’ ªj(šfAMA¯ÿN$¤¥&…ì’zÛÛDóZƒ €{jB‚–a†a˜~BÁº¶¶†\.Ó4qáÂ…ž>L/^ ÷a²ãˆBC¶ ‹"ÔqDµ]Çû¤…¶-„n<<ײ„ÐÌ#Uߺ8é³4­ÛNf¡¹£ fö “u&±Ó P*•Nì]×E­Vƒçyܲä Ë2{Ó†aæ„‚µÕj¡Óé„¡ÀQ666ËåÂ^­§ßâSU»TškZ×SHžCÓ !BM³[´ˆ(—[o”ö¥ù«¢ˆcLsAÞ¶mؤ¢SâyJ¥Ò‰V±, (‹]ß0¯•mÛ(‹°, ×®];±ëaN†r¹ŒR©„r¹œZA€b±ß÷ûî Ïóƾ_âø±›žzmÝÞ›ÓIJ,ضÍB˜a†a˜¥áº´;ò_Î ÞM¡år¿„h½zU„òÖjB|Æ اVÛÙ¢¼¹¸h ‚–e%V§$ÏS½^?º~?õ碰L\èzž‡[o½…B¥R –eõL®Ëå2TU…,Ë=ï ‚år¦iÂqœOšçy( ¡À(ÇÜÒ®ë†Û+• ‚ ÀÆÆ~øáÙ|ÙÌLðqJû&‰Vß÷áº.\×M¼/\×E¹\?3úºvǯëzß½?-­®®¢X,buu5QÛ¶B¡£P(àƒüà¼ÿd 3uJ%ñÃ0 Üúú°noockk +++º¡Â€¨"|š‰VÜ¥>§Æxa¹–Õ-^Dù§T8i–”ËeÔj5(Š‚B¡û HBÏ0Œ°Ñ½iš0 Š¢@Ó4X–Õ“ƒåydY[5Ä?(•J¨Õjð}¥R FŠ¢Àó<8ŽƒB¡MÓÂI8‰Êb±×u!IR(,dYßà×jµÐsU.—Q,¡(JXè„®…NTUå0çUÇ,Ëaû-EQà8Nh#d›Ô„¼™q›u'ôà+Šã¨Ç“,ËaÏLÛ¶¡ª**•JϾ¶mÃóõz=œxSX$‰@Ã0z¼A«««‚’$ÁqœðóhâMÇ·m»G@÷'þyŠ¢„‚Á²,H’NÞèýIç9j"^«ÕBAÛh4õ-·Ü‚›nºiºfê‡QÓ4è ‚  ª*t]ïË”3H6Gljî£ë:,Ë‚¢(°, Íf’$¡Ñh X,B’¤P„މ^ß÷ûlWÓ4 èº~‰mI’ÂkŽbt]‡çyÐu=©qž÷¼çÍûÏ·ÔA.*Díˆ"@h.º0F yº®Ãu]^4C·º¾ç‰g#¥×HRrô ž½ûûó>s†a椸¾Õj…â”ú°º®‹V«X__‡ªª,VÑ ã=Ž7Ô0ºyªÓ‚¼O4ᥠS4ô±IÍW!&í$ä¢bN–å¡«ýš¦…ž'Ó4Ñh4 Ë2|ß=]BAèºEQzc£B5Š¢(¨×ë$ià¤|ع2‹ ‰Õèb€©°I¹–eÁ4MhšÚª$I=÷ϸè]]]íë«IB(9êêºnè™WU5 ‹ÕYC¡ïǨIH’„«W¯&n›ä^d²ÏÒ4-ô¶ÆEl¹\†ã8‰óÓˆç‰<ÔJ¥›‡¼®ñ÷Í:}†a†É×SX§ëºØÛÛy\IÀ2½œÄÜÒ²,¨ª:t¢N!Àº®‹Ó»v9Ì#eÛ`& Õëõ0šr‘ ÃÃ,=Ï;q± /–N¢_3¶ÝmûGÓ„¡°RòÚ¢ û È£gšâ½ñßã'°÷³Å"‡¦ip]7 ×&è5]×ÃE˜Ó ‰Õz}xnYîF ‚“y3 Ã0Ù"ÌazU]×Åþþ>vwwY¼ž0ŽãÀqضÝWl…B}iŸB€O.ÂL EPq f³ ˲ ËrO˜ä¼Ã¹³îñ ‚n´GÒ©RNಡ룽kñ°R ÿ÷$âÃÚ8Ã…ÓbK|‘…о¢eycO#A Äj­6\¬2 Ã0L”Ķ6ªªâÂ… ¸ï¾û°¾¾ŽV«…óçχy­ÌlˆNèëõzئT*¡P(„o›Í&jµ{˜…"Zé™ BÌ`\WLò‚aÂ~ÐÅb¿°PžHædÑ4-Œˆ§©jô2õÉÖíÌ4{픪ä§]ÿV”îñ§‘’Ã0YÃ÷ý¾˲ðÛ¿ýÛó>5†É¡‡ukkkˆþîº.VVVpîÜ9lmmÍû\çάóg(¬Œ&ôF¶m‡-<f(—Ëa¡-‚ €Tøú2!Ëb’O_§¢ˆUEk¢­µ¨es²PµçQ¹ÏT½T*…mŽÎœ9nWUµ¯0×¼ñ}ñ#I]ô}žmb$„×"U’Ķãx®î1fjƒ]¨ö÷¦â—áy4MÛÞô¦yŸ:ÃdŠë[­ Ã@»ÝWy\×…aÈår€ÝÝ]\¸pëëëó>ß¹3«¦çyp]·gÂ#IOð™…‚ZuP¿]ê3jÛvæ&âYÄ4ÅDŸè°Iºª qZ. ! Ë,VO’h¢(8<< ·Em=îu5 #ף%a£Á:¦)<øÑ×EØ Vê‘ Û+—»]7]ö¸¸. Vf± Þó@w¼°m²,'¶Ü‹ŠÛÍÍÍyŸ>ÃdŠë Ã@>ŸÇ}÷ݾH¹«÷Ýw.]º„­­-T«ÕyŸëÜ™Vúf<Ìu]”J%Îe *–Ų,T*T*”J¥ð}šBØ)ÇÞ'ÓýÓ^+Eé Jó^·Gs"†Im‹ŸxX¹$ͦôS©ôF5½¿“'Ô¶{=þÇÅu…úÏa²Žiš0 PŽãÀ0ŒÏCjÿÇ0L?×·ÛmÜwß}aŸÕN§ƒV«… .„¯­¯¯£Z­ö… Ÿ6¦•kYVX˜šÇSÕTûe ˲`Û6 IRO^@ÚÕÕUÔjµSeÛ¥’ð~*ŠðB“ŽÓ-”D­<Êe1YOÓ]‡Ûz2ƒ ÅUùÍQ1iYâ÷øüxÒ žYØ¡ªvs·f‘p]A„5¨R8Ã0“qÝÚÚZ(LôM:ôl?ÍŒ[̤T*õ$Óû¾Nðu]‡sÔ£¡Ñhœª =³üæo>Ã0P,,Ëê a×uÍfs)Òƒ ͘f7çâ`Tx¤¦‰ZDCƒ&-®+~,KˆT²UMë>ÃLSüNbÕ¶[o^@)Jé]útÿp3 Û¶Q*•N¬¨™ïû0M³¯h j9pÔsZpœnÛ¹YÝ~×w:ž¨+‹Ô~'}H™‰æò™¦‰J¥I’zòŸfÑøÙŸýï¸vm’t+n»íõ( ‰ýy—q!Æ÷»^Ôè|ÄóçïA>ªm Aš”wÊ^SfAÐÐ3©TꆕÓBGÔƒJ‹(ôÞ¨÷^Óºyª£ Öj¾ïŸXø"Ý? 3Ó4áº.4MC±X sD=ÏCù(®œ"Û¨×w4gTQ”ž0]I’†>¿h~§ª*Ì£Ü ÚŸÎ#ú~Ë6Ì–Y6v]¾ïC’¤°h¥$I(‹Ð4 ¶m‡½¿ÇA¹\W Àïû‰­eèuUU=¥4¯£"ÚÑEtoø¾¸o%©»é8bÁ“#h˜e@Qz@u]ÔâH“Ò4ׯ­­assëëëØßßG§Ó ½$N—/_Æöö6ÖÖÖªÁ§•´ÞUz Ë² Y–Êå2æ} sl|ðÃøÔ§^ƒ·¼å¶°@ °Xa¿A &Ã&ùÅ¢˜Tи÷Þ{±»»‹µµµS‹ŸÒ7ˆ¤\>MÓNM•Tf¹ùáþ^ó@’^Ðóz±ØõJÖjÙ­è]1J“‰ø¹ÚvÈï ¨XÒ(NùÊzøO{ÅzH°Úãu˜Ûoÿ¾ð…7á︌·¼åܼ/Ÿ9¨%A"UÓ4ÔR®¸L£v‚$I¨T*0Mõ£B^œæ<(B'.V‡-n2L– ܃äK©”¼ðbbž5Íyàu$R/]º„û'x}}—.]ÂÎÎΩÏiõ¼tE—’ŠV`±Ê,÷ßÿ·hµrøoÿíëú¶5bB}õj·eáyéÚ»LŠãˆã›f®[±(¼›t4ˆV*â|“nMÚÎ0' …‹Ç¡^»Ó~Œ$‰Nß÷{ÄBïù¹aý?e…&ªç0)O>ùþçÐóú>ð|èCšîÂÌß÷Q.—aYE m­R© ÑhÌ¥€Ÿ¦i‚ŽãÀ¶mø¾ŠUªg0ÇœJÆÝk˜aø~·NÁ<)—»Îˆ8Úž„$‰mÓ\×¼9ªÕj5l]Cär¹S<.¶m÷xWf óïük¼á >tâLá®¶Ýí¡¨(b"ž4ŸAÐ8£Â˜ŠÐÐ6*œFóžèê·e««³;G†MP¢öW,gΈÉí,Ê”Ëå¾Ü=jW•Ä$aÀ¦iÂ:FošO~²…¯ùšO¡Ù¬÷¼þû¿ÿû¸ãŽ;¦ÿ¥0sÁó<‹E¨ªŠF£MÓBÁšTÁ¶ÓWµ>.µZ ¦i†ù°„,‹gȰIù°ûÖ4§;¡g–jw7o‚@Ì—’ìÔu V@xY§)º¯«V«ØÜÜÄîî.vww±¹¹‰jµ:ïï(s¤Y ‚žçqõ_f© 6ð¢½?þãwŽ|å¶FçÆtà(j4„—^çúU*ƒCT C„¶p¨3k¨è–ï÷¦›ÄCé  V³”§~ä!ŠS*bã Xµ‰ VY–îG8ŽMÓž”“}W>øÁ/ Ïþ}ôÑGY°. Tç£^¯§.L''ödYF­V +G1 qIæ=**B×¹Ï0“ xœ'ž'žKºžÜŸÛu‡/Ȥië7×íîîb}}=,ñ½¾¾ŽÝÝ]ÄÛÝœv(aôpf˜e [Ü¢;(¹®;V5à¤7í¼•ÚÄ Ú?Z„& ¥•§?Çg˜cãy"ŒÊÿ¯®v„’ˆçóM ß÷aFXmè>èX`| ›Þ’V°R¡›¨—Õqœ°H”$ï.U€UU5üÇÁk_ûÚ©'Ì|(—Ë}m`F¡ë³‰:„ªª}bµTÏGUíži"uè½Yýd²yïçé…wÝÞ|ßŨ5ZZß-Ì—ë`cc#|akk €èÇÊôýÃ9ŽƒB¡Ð³Î ³ ”Ëeضy¨:ÇŽpÝnÈ.•û‡ðÒƒžk¡ ö‹‡Ç Ë3æIe˜yAbµ^6ÚhˆœïaoÏó ËrêœÑôç"n4UUá͘é¦(JŸ‡Êc¥ˆ#EQªÂôšišágÆ?#*ΣŸ='Ïóð-ßò-³ø13†*ï®®®¢T*…EŒÆI¥²íþÉôI½=(ô‘n‡ žÛÅ0º=ZèFàóµÊC%ÈÛJQwi§ƒ¶=H‚ëô䩞öâJi¡‡/­û¾ N¬‘:Ã̲oz0O£…ªŠ‡ºiŠüNíMÚ— 0†…úƽ—´Ð?.iÞS© OIĸSÁ¨hu]¿þ뿎'Ÿ|r¬c°`MIt¥Vš©a5åÝp80³,ÐDñÛ¾í'ð¬g}¸ÇÓq\¨8R|Ž"I\êŸY>¨§ï$¸®zXG勎K¡Ô4­gA*þyƒÒ’r]äˆ#I’Ðh4ÂÏTUµç3¢âœDP\$+ŠÛ¶ÇÊud¦‹mÛa_ÒJ¥Ò“=ˆ¨X=îß.>™TÁ4 iÂv“Ž= Ïn­Öž\¹ÂËÌ uº•¢s¡I«iÎ¥¦<ÔAŨUà$PÚG|AÓó€oü%üê¯>¸ñÆÇ:îu°¹¹ÙóT=8þ:#Þ4è†þνV™erÏžy&I¡_ìÕ`˜ÑÄCÛëõÉk’XG´Ú¶ÒyTdèºÞW5*FU¿tN¶mŒÆˆ Vß÷¡ªj(r“ÉTUEÍ4'<σeY= цAïW¬Áàœ·xOV´Èq†ÒtñãºýÇŸA 4HR÷|‡ë¬ÈBSŠHŠƒrCǬAÐ-›t½ñjÑ0dú¼è}fÛ6ŠÅbßx_.—±ººŠB¡€b±ˆÕÕÕ£T2¯oß pñµ_{þ꯶qùò6üec]ÓuÈçó=?X[[ë{ý4€Äã!.Ì2ÐgŠé‡Âó<Ð49ôô0 3*ª4œxEîqòX)ÿœÚÔ$m‹Á¸˜ˆ~Þ ”—A¹®ã $Q½^MÓ`YVß9QNæä ‚ žÑ…aáê´h2®gÕu…`Mòðx^"sÆÐ“0T‰Þ4»yªñÈŸY|ªT€W½êþÙ}À)ƶçz­°¢°$ÝB$fãŒ;ý"ï)UŽß–Õ+˜©&a€¢ø0M…BžçA×u”J¥0’ ¦ Ùl¢^¯‡ÿêºÞ'XE'š¿B³ ˜æÇpÇŸëš®§ªÀ§ ÓoRAã3yž¢6‡'MˆÀp0ïaâPH°iµÚ×àÛ¿½É 3ª„8NQ¥a8Žƒf³þ®ªjOk˜aX–]סiŠÅ"šÍÞû—žcà ï©,Ë÷M*¼T.—Q«ÕRäe%ï-½G×uÜzë­‰Åxøy{òA€b±Ã06(,˜þ~TŒIÓ44±ÓI\·›Ç÷û¤¢t{FvϹßKÿŒZMÌ]·w>hšb²ÿòÎÑ{™Åc-VÊåñó”£x^W,J’°%”Ž“|Ü$½²º*ê~$Ý^®+Ž#Iâ^ê­ÁÓ[ðû–ËâG×½ÐK¾QU¥R ¦iB×uT"'Љ·(£BË=ƒvû™±¾·S™Ãêyã—Y¦Ás­=˜#ü£ŸY”ë^0§êËMx’È0ƒ1Mà§~ê“pÝÿ=¶X-•J‰+ÑI £iB‚ÉÃIXÉ[%M‹ú¼aÏ ï'ýùIT¢ð^¬Ql{pŽjÔÃeýB7I4”JÝH;vò/.“ŠLÂu…­Їm/º(J׃Úh UÛtü¤êÒLC*(³mq/Ž«D­|ö³ŸÅ7|Ãð©OUÃJÞÑçÕ"h4=b5NRá¾4 ¥Ãè¬ûûû¨V«áÏþþþÄž­V ív{êÇ¥ Û¥…C#§ˆ`?…gÜ!8+û>.½­$æ}6Ì"“UŸ&oûçqéÒá©§¾ͱÞKæã9€qG¨ªÚ·jÇ4ÍÏd¥Rã8=“ÊUõÌk40 Åb®ëÄÄ¡IMR¾ê¤bç¤8 ¶mC3¬O*…›G1¼i=ìIDÅ$!ËÃóF5­ßE¡ÂI·K4OP’º½%K%ž™T°^b9.p—™e´qEûI½¬¶-ìcÔš_¹<8Wö`HTá Ûò¼Þy×íŠÎø½AáÀqhˆÚÒˆ÷vßìû>>üá5¼øÅ/Ç·~ë?ñ=Žžñ¢|¾ï+Rïz:á‹/öæîî.r¹,ËšjkµZÅîînÏkkkkØÙÙ´Ûm†V«uô%§…Jƒ,ws,+]h°ÈKòÃÌðÌbÝ 8æJÚ¤ÌÛ¾ å¯ÓëŸÅ,‹nãÇ…Â e9À{ß[Ä]w©J©<—Q(l2î9u]71V×u˜¦ ø £ÉG\Œ†Û¶C1™vâ@ǵ¯ªª88?·#ê56Žëú˜§Ý¶‹Ñ‚@ªüSú;ú¾ßÆ>ºMMÎã“íIJ„躘”‹ýï÷¼þ^ ñ< ÁD§ÕÆ]·Û3wR(ÚRQH¢ýŠE±}’!ÂK6­(ý•èe9ù¼Hû¸®‹rÙ FËår˜žQ©T i7Måû¦q"qŽ»yýþþ> ÃÀÚÚî¹çžžëºØÛÛÃùóç±³³ƒµµµ©\Ä•+W°¾¾ÞóY+++áÿ···‘Ëåpß}÷¡Óéàüùó¨V«˜V¾­m‹?¶aˆp]½b¢€‡(M B¬ÒâΨ¯5P‚¡£öõÌqtÞö}\(lÃ÷{+2 ±è6~|¿;  š¦Á0Œ0´u(GÈ4ÍžÀAwEQÐh4à8ŠÅ"jµZÏßÀ²¬Dá§ë:VWWCÁmi3Œ“¨~Oy°YI;8Ͷí8dYN\,E½^O=!¥"0Iá“FõPÞ©¢ô bUí÷8%iêÓâ5N¯Ûvº`ÒQÈQHö:ÌÓÕåro>v±8yHyThÓyAì¡Tu DJ‡/P%,¢gYdY†ªª=÷9¥~L3‚T’¤P°NcŒ¿n{{ªªbgg§OŒE_ßÞÞžÚE\»v ù|kkkáypÛí6ö÷÷±±±@ÜDëëëS­  ”°…æ ƒ*%2•iæxNÊý!nÅ”ûO™yÛ÷q¡É²eÎÓ`N'‹nã“@á]²Ü Œ ?I’Æö°RëUUGVä¢iêõz‚ ôTË7¥Ðã´çY©TfîùT%S¡¿§Ñ¶ Ó4ñ¢mO.9Îâ†, Ï¿£È…I¡ç•mwçmºÞ=¦ïϦ%Í¢qZm\×»žÑA=Få§ZVoÝ›AC–pnu?ŸÝŸq JïÑÐÚhx0UâÎåîÆw|Ç‹ðò—¿¶mcuu5Œz°, ·Þz+ÇA­VC­Vë{Æhš6u}ÍcMJû—ëÚí6î¹çž¡;mll Ýn‡áÇ…rc“re¯\¹=!Èù|~jqô¾ß»rBßߨ‰y.÷Iîµ:MãÜ”ïšÆÁíÅœR0OûžT!X’&ëÉ,?‹nãã`Û"'i¢ÍM*21ŒhŸÕ¨`M»M«æ´ŠnÛöÐV2”g˜ÔÒfž¨ªšï*pºl; Eýê¯Þv쨚RiøÄ¼Rézº¢"À²&”†ÑÛEC"El£ÕãVˆ]N«“MÈòð9¿¦ OhÜVâkwI¢7z÷«Õ„7ԲĿ£"æ)œzšR˲`šÝÅѮƄmÛh6›ø…_ø6|îs/Å[Þò7‚FµZ •JõzW¯^E­V;ѱ?Úk›æ•Çáº\.‡\.7t'2ÜN§3µ ¡øùN§ƒÍÍMìííÀЛbØçö³Ÿ…çy¨V«C?W–“ó!Èñ‘|„Ç1®'N…ð°Ê)ßK!Äi ‚Kºûûû¸ÿþûñÑ~tf_Ç´í>ýéOŸh14Î_]\ªÕ*üñ™~ƼÆð“"„Põ<‰“%¨Á³áha¥èƒ}œHžJ¥¶U‰Dñ ‚NóBUÕ± 5ÀÞÞî¿ÿ~<ñÄ39§e¿ÇŲ,ü«õï§;¨Ø "è6¡â—Ñ}'uòDEvRš—ª ±°Ar4~ÏR$.ûøÇu»‹!²<8,—Š2)JïbJR!® è_`¡èB’„€q$6é™AÕÖmÛÃò¢vbqT8Ý4MØ8µ>‹:Ò¨@Z–%éúè¹CsðqÇïë¯]»v¢'Ýn·±±±»ï¾;Œ™Ïår¨V«X__zC\»v­'Î>ÊM7Ý„¼à8wîÜÐÏÔ”·^\Ñ >þñs8ð |ˆðÛ«)÷§*¾ Òåšúè [À¨¹ Õþ‘(tÏž=‹;ï¼ûØÇ¦þUÌʾàæ›oƹsçpöìÙ©Ÿ71° fþœ;w=ôÐLŽ=ï1ü¤ýè†ç<Å#n¨²nš{ÈuÝž0;Y–á8ÎXbR’¤°×jѧilÛΔ`„|>k×®M}B¿èã÷¤X–ÈÅ~òÉ#ÆïSgØ{M³[%U’z+¦w‘Ô4)T±sRiü¾å–[¦~ìÓ2~ÇT97Šï‹UvD^V×M~/õ9çs‚ @©T Ÿ…B!\LŒ×$ (z‡D´({ü"F'AR¯nšƒ;~_×étF¾‰V‡ ÆiÉårØÚÚê9Ý$ûûûC«óßtÓM¸ýöÛG†Ô—‹J›½ù°»û?ñå_þå<ã…ߺ“EçBˆ[ãyrü¹r¹î¼óN<÷¹ÏúW1+ûÄ„gmmmä~Ç!š¿ºEO-kkkxö³Ÿ=“cÏ{ ? È 4L¬F‹$i©JoôýªªÂ4ͱŤ¨ê¨ &(,xÑ£…òù<î¼óΩOè}üž×uþ½Tõô8y¤ÑÚIÇ™eJtˆ9Þ¢ç©Òø=9wœÓ0~'áy½)NTø+Šmw_“$áÜ*ß²Ü+X=o¸í‘UÓ´0\·ÙlBÓ44›Í‘ã²$‰s±íã÷4=)dYî[$¥9ø¸ã÷uù|†a \Uét:¨V«=IÙÇa? = ÈË»²²®>FEt»ÝžÊ ŸvÕM–…1“Çõæ›ÿ¿xÛÛ¦½th^ÌqrÑûrÔ:€‡n¾ë¨Ï0ѵÆU>&ó´ïãB=!EAœŽòþÌø,²§EQz+;&‘@UGA£PéÿIÄdÚª®”÷Ê‹¯ÉœÛŽâyÊårØ7• GÙþ0\WÌ¡H<Æ™¤EMZFµaN›¦è©[,vÛËĉ Ѹw”*[d‰æ±:Nò¼I´‘)£X,Â0ŒžÅEI’ ªêÈ1™ªüvëî,†`%ïñ4ž9×]¸pívçÏŸÇÞÞ^h¤ív;liÓn·§VÎzeeÛÛÛ=œvww‘Ïç‘Ïç‘Ëå°¶¶ÖsC¹®Û×l…÷ÁbÀy­6<Ï[Žpà"„ › Ò V¸Ä¨Wò®£Å­{ß X˜§}OJ0M…B!,wžö^aN‹hãi¡ ‘ñ•óA$yXÓä±Ú¶Ý÷L‘e•Jeæ“F£±y°Ì¶'‚P¬’=LcÜ‚n;4UíÍOV'dP¯Êˆ”œËnãV©ˆœåFCü$…›G×Éö£Cº,§[¼)D½Ûî¼þK!÷k ­­TÄg,Š`¥ÐçiDõ\ŸÏç±³³ƒjµšØºfmm [[[Sñ®"”gccçÏŸÇÚÚZX‘,Ú”xkk ›››ØßßG§ÓÁÊÊ î¾ûîc6­ü¥û’\®…ŸýÙÏâ­oýÃå˜À˜¾ÇÑ`A䋦¬ÑüUbÔý]‘•ŽŽ1h2\T ,ÔôüûŸÜ>åïóµïI)‹PUµ'yŸz°2LœE´ñ4ضX!O²˜´jœ”¯“ô¾A­\fÝB{W‡°¬¶D¹\†¦i=IšœOšÃ꺽ó$]^VÛâÕófïaæÄ2ý,³Aú1\U{Ãwg2Ï|¥"Äcð<ž§‹pÄ=ª“BVº¿)‡U’¤©ˆëëaÀ;;;aëšV«Õ³ÚB±íÓŠMßÚÚÂúúzx£Ä›Ïçñîw¿;\šÖçŽ3X:Žƒ ¸gÎü>ô¡ëðÕ_=•S˜/ML¿7)å—¦g9謄Mº÷â)õ8‹5>pën¾gÊßÅó²ïI(—Ëxõ«ß]ÿÉP .Åâ 3SÉÆÓ¢ëãO¦ãaZM÷óÎ6ËhÛqHœÄHÈœ©ÐÌ 0JÏK.,¬²,¼\à ×0'Ï2ÛxÚ5?ʺBwTË™8A X,ö2×uÃg@£Ñ˜š¨T%¼oE¬Fc* ¥×G¡7q×m«ÕÂææfªÜœ´Œj§³²²2õ›dœÊq¶mãÝï®Á¶¯°Døi{XÇu¸ ïq ÄjÒd± Q8Í÷ïýè±÷ÇÓ» sn¶9Éó°ïq±, A@Qj(—»eÞ}ŸCª˜Ñ,‚§Áuûûs§ 'Å6‘ &ðisN™ù°,¶Ç÷r9€ï‹ÞQ(ÂáE¶S ¿?I”J‹Õ¬±Œ6>Ž)Jׯ)”w\MešæDm¹&»6)‹LLë\¯›÷…œ$ã ˜´‚AͨgE-4 ÊèzCgy àäø9hÜÞF‰í¯Ù×EÎjÒwêO¾öÉ~ÙÇó<8ŽƒZ­]wtµ‘‹V0§ÛžlF,öô¨Ã /Y–5•ð0†™„¿ø‹¿Å#\B½^ï[l‰öGU”Þü¾8ºÞ[l†àèfžŒÛÙ€æ<£Ú—%aÛ6|ß?±JPÏ¢ ÖiqªkZƒŒVp”¤ò6y¯Êî$Ç'2­Ïñ „pô÷a8HÎWU08Ä7>È,Xí„ãÇGägrÏLéKXL\×…¦iá¤E×»1t+s:ˆöÝÿ½Éé°°`ÇqX°2sã÷~ïGð/þÅÇáºJŸ UÕ®Øæa­TÄ…ùFáüQf^PXï8P ‹ãyŠÅ"œØ]×…eY¨§œö(Šr”'Ë‚u©‰zFáyÞÉ÷©s1;kôÁ“¶š¯ÑS½âqT”›‹Á–xBž[Ò¾*úŬ2`¿SÙxˆ’ïº>þ`Ï0‹ŽeM^fPèï ÂK¶m§j_À0³Àqø¾_üÅŸ„¢årïöhš¢Œž/U*ýÇ`˜y1i;£ÕÕÁÛ¨0™mÛ(‹°m…B!«'=–“`]´Öiqj«ç¥/©>—Æê³Œ*ˆzW+H'؆‰Ë¤ãƒ=ŸÑý- ÅűstI$ «$ï*]‡ûýçÒP­ÐEC¸4Ml_êõ s,ÈC4‰`VXI–åÄÖ6–eH`†‰CK¿ôKï &öª*Æ{Š2ˆzK£i¢ˆVâÿŠÒõP¹®¯S,sÂ0cáyã Öaã?å§êºŽF£Ã0àû>êõúÜZƒÉ²|Ô‹õô‰U¸~sssäNÎl Ôœi .ÑDãÄWÁ5ÌÎÃ÷„ŽÂ?ú&0“òQ-« ؘ(Ïï\ Öñ†¬IûS!&š'jGç·?ñ·¹°ø¾ð(}õW·ÂÁ–&.€¸ËeÎAZ8|_Ì"O0—fÑ¡Â1“~e¾ïœ°¨ªÚÓ"B|žð®žÖ‰3_J¥~üÇÿ~ã7n_3 US*‰ùQ<$©bj¼¾M“dY,xò³ƒ™Ž3þx>¨® Õøˆ&SUõäY1ÈÃzZ>¯O³Ó"V ‹“¶àÒ\¼«$(gåùóÑyI•tãP®)…ÏJA¿âç£Hý“Ƹ¾àè;b?Î0¯©‚^O­&Îõ¥.àéç=ØÚšâm¨úï¯üÊÇñ]ßÕoã²Ü­Ì,²Ü]8¥²qÑ´ãõƒ %ø-ŒlÛ>ñ|'†DX£,Ë8{öÛ{¥$u[9%U†OZ³TÜšª 3Ì<˜Fgß÷ÚYaAÊ,¦oœæ…Ïëwvvæ}™‚ŠÑœ(„8æUŒ’FtFñÑõ°’%XëèzJ}_ÄEÕL¼=ã÷=|Ùêâ5ª}/)£?ó}°ÿ‹ˆëøì÷Ú¹áç§D®‰Ž[.‹§l|™-8ú±¨"vé©öÏðÈË^†oçï´àP¼ßú­N¸(S,²H…ã[=©/bRè° AµšøcF*§ÜôÌé.,–Ĥ-lâxž7tÒP¯×Q*•Â0²Ó<É`æ‡y”R«Õ`šƒ'õI¯Ó㛽¦LÖ‰÷ÿ„r¹zQ ÃȤX²áé§&‡µX\õ.Ê\<¬„øUäˆ01¸ QMˆ§O¡ ñ°y²á •Ñ-bD ×¢anbíftàÿóÿ~é¿ q[(ñY*?õÉÁžWÏBóá‡=#Õ‡Ï ïï­¨LaÔ…B7ñ&zžêѾô’$žøžï™ðµ¸WéºëÞv”g7ï3š2Ž“þFÄ~¥’¸7NÒ3é8ÝE QÐý±º*þµíäJ'’$Dk¹ÞßõÁžÜ5-®;Ùû¨j”aTQ4›M8ŽÛ¶Om3?lÛ†ëºaÛ ßoR¯ºjYã· a˜YÍ»V”ã=ƒ @0 #ó…ñ Ã8µ‹Ÿ×Åóp:ö÷—3Áo” έò–ûwèIý›fNNžœÕU1ñ¥´a—øÛ<÷WºŸAs´JE‹*1$…½æ5ÀןE!j5ñ™_òÁ^ïªç‰Iõêªx* ð–sÀù-ÀW‡œã?ÜûGâüJG¯Õëâk5ñ”u]ñ9ž'ö3Ž~’ºŸDåGßð wÁ÷—¬gžmwmiÔ¬*º‹*Š"l5í"Uô Ls°HN*½lÂ^ÓV‚Ó4Ñ/¢Ñï“$qîñ÷ÒSû(¶ûW^÷º“ùî]¯7ÐmmP.—ÃP`ÏóFNj$IB£Ñ@£ÑÈôˆY>|߇mÛ=¶7îxOáÂÄ$EmfVD»Š2z~?Œ¹8ª˜±éËa½÷Þ{±»»;°ñù¢’¦¥Í\Œ– ò|’È«7„X,ŽØ—¼0Ÿ|/ðž×/qw»9à³LS= U ÃhÑ µ5M RO|©ÑÙŸ Àº¹w©KQ€_Ž=%]WLª›Íî(c£›çPz±Ïñ<àc¿ ¬ý¼8?z ’%OSéHÉÖëb?ž/ÂqÏs‘Ë}C¶Ú=„]4âš\$„Ès1óŠÚߨc»n÷}qÅ#ËÝØjêŸEûkÚ`…T¯÷FØv#ä&-%Ñ'ΰ`¤±wÏóBaêû~ØÂ€zï‘Ç*m•ÈÓØ/™/år¹'¬1mÑÉ(ÑÞ”4 ²)3YaØ£uTá=ꜚK* 36©Š.-ik×uO>t‹0¤“‰+ZBr&Á2zsS ò4Õ뀬aûòØ>ñy.yœ>û" Öì†úÒgšìþ!PpÕî–Œ_0!<›ÑkJúŽå”I’¸*chšÀ[ÀÕ/ç—ôç"¯=q9®KNg†¶3˜ûíû¤¤Åÿ“JSÆ ‚^¡I‹D­ÖŸs t½dÃŽï8â‡ÊbÆX¢‚IÈ‹Ÿq$Iܧ¦)þi®=þ™ÌX˜æðÔa۶ʾ€˜Ü4 Ȳ Y–Q(¼T†É"Žã@’¤ž xRi‡4XVwý‡&KL2w±, öQdÒAäùìº.jƒ*Š1™áTÖ´Îbªê8SȵE£€®X5!„ä²g•  4º­Y’+Ð;±NšK¾óW€ÿ5ÂØPMð6qÌèW?þ·W ÚOt´¦!ÈÓ>(‹Gïj*][,v3ëð@BäZˆˆ~w§ìAâëªÕº+â² ¼úÕŸ€ïK$ µšpDNÝ܃@x÷+•Ñ«DŽ#î]‹£N†ò>ã5Žªv=©Ñ§ZšW¯§¦‰ÏHë–ˆÇÏ¥…W˜™ãºÃÓ›I¬ á%`YÖ©Í!b² õ[m$Œ)“ŒõA ÞÇsy&+˜¦°Éqk(•J$ Íf¦i¶mèº~2ó~f*œŠ¢K4ècæáÀTà%zï´h/SBÀšfra•@nä®%-òëúè0GÀ·}›˜ØëºðU*â<⃀„^¬Žáíi¢ß³ñ*+Hö.SN,åèQÁ'ž3&R,Š?kÔæeøã?~{ϪûÈ9wšüÊ(ž'Ä0:”*x4éĪiv«à¦™=U*“ÍÐ$©{?°(Y*|ðÐHÅ‘F囆ǧâÜ–eA×õ¾•aiöèTسÊd ÊÌ˲ ( êõ:$I‚a¡§Õu]¬ ©ð°¦Í_ÛhÓ6¢j¹†Ñ?úSU^øÄ'€{îF·@RÏIøž¯¬ð+ç€ßzð¾%ybî(ä¼ùü õ½¯%=˜dt <Ñ¿Ãô0õ”„wuDTdÏç óÄJRo(1·4L¤\î®CÐ]’€K—Ú}a/C{å²x2HÒxK™õº°ÇÕÕäûÃ÷űÉs>jq…BÜ)d6me›LŒA¤î»µd˜¬@}$Rg²`†É45N%ê«ÚŒ¤ÜPЇëº¼@\›››á Nñ׈EíÙšf…ÐuÝÄ0š¡˜æhïÅgÖëý³¥hH¯eÿù÷€Û÷€ÊÝÉÇò77êÀ¿ûqaƒ&æWVÑ­þKXHÎõ”ÑíK·a9¡.„÷ÓFr%affض07{ÉdÀ÷|Ï øùŸO™ÌKÞýFC4í=zÔj¦ãÛNWª• €QÈ, Pæ˜x^rú|c……†eb˜¬P.—N¼ë¼À;9ñÔ’i@¹ÝÕXLRøË²,hšÖ·©ë:,Ëš_w,àyÝš7 Àõ}/®­­Íû¼N* 1²õµJ¡AFÓÄ 3hu†Äj¥’¼´ÿ¾OÏú°úâXþ;@iÈ9Pø°bˆs ÊºI8Hï…¤\Ó¤±“ú˜Òç_I KHצ‡™¾ß»8£iâYûðÃǿ؆žfå†zƒ’MO:«ªãO˜´Ëüaø7—wf¦Ã `ÇqÆòšJ’Ämjñ…RøÒqûJ0Ç‚zJkâˆÇc`Û¶GšҳsÔ3Žæ…Tž½{©qÝñ4~’w•PU5³§ª7"I]G ró£âù?>Ö{®ßÚÚ:Ñ“œäôhíe.ÕáO”®Û›tÏRxíˆ/,Zµ­/ÅïV²¢r²Ô+K’ƯŒÂLL¹\NŒ£êð ìû"•äààä#jÈã©iÉÅ.ËåÑUÜu]ÜÑRäT"zïP‘ ]Ç-—Y´¦€‚ZÆY£œîA Œ•…¸1fD¹Üí D69 ÏëvMu> çGôù¶—þÔOá}×wuʧ"‡Õó†yª =Äã,UM¡½aïO½Àkz_ô|O•ƒÆ¸Aá½-D^ªƒäjÂá!¤ÓÎ=Nñ0O’"ÚƒxäòxÛÏÝèxЦ‰4 ÁnØÒý01Ë03@’’35†µõð}¹Šn”Jâ¡G‚S–»÷!‰Ò8²,îkªŽ-¾ñš$%?ÇÝß$bÃêóÌ,¡6LIa–µ b•N–"s¦)à¢ÍAi_TЯTûAW *Šøå…’eqÞ…HaLÛîÿÌèŠZ­&>»PàrÌ#§ _°, ®ë&zW‰¥÷ÇÁ²zë¨jr¼µçu½°ÀQkÍØ õ„§¹cÒ*…‡í9]<²»‹O·ZcöõÐjµ°»»‹ äóùD/m˜Œ1*55UþR¹œ| ZUKº“‚Qm=Ð/=\*è÷˜&iwȶ($jËBx˜F1>›µÇBò7×Cný.€o¾cšÁÛ¶ÅWb˜ Ai׎Ó/XEˆSÓ4ÃKŽã,Ƥ…úSo`šð*J¿"™$)I|&yUÓ H~&Òd†`/ì±±mõ„¿9}Í‹`ÞáâÈÁð²Æ{mO ‰U]¼xJ• é>Jòp†8+MГ¾\jÃGÿ+¾°Ðh¤/àyŠ¡uƒ$lÛSûEišÐ4m¨X´Ø?ÍÅ|ŠHÓ%è_ÁMZ(¡¶ƒñ¹ž+€C‹£”þ˜Ôìœ<¹Ž#l½ÙÄßïï}™×“w1—Ëaee%ܰµµ…••¸®‹V«…w¿ûÝÓûr3ÄŸýÜÏá÷ M Ķ…q% (Š"þ`N5…I7™‡dÁ:ˆ¤±l8M³¢JÕ|ŒÎKå"J™'ž^Mxž ÷æŸÆ·<ò¥)XGAb5Mu_†™º.æ¼ñE`ÑžWx>J¥ÆìÛ™M*@¦iÉñ΋DÜÛëºÝð1ba\‚óÇó3®ë¶mT*ø¾ÏóP¯×³·I7$Ù÷´ž;”~ íÕõn¤‹ãô/bŽZˆ¤gNRg†øyÓ}«ªÝÅŸA×vÌÅÉë···Ãäã(ù|kkkX__‡a¸÷Þ{±ˆù®¾/lcÐÀýž'žÀ<ïyƒËYVrXG2Àøc˜çRBrÞ¨ !@éï(bpÈ®‹^ÁšöÐ Dsº(½SŒë&?ó|ßÇ3oþ'ø–G™|—Ú2QH‹U&ƒP1vJÓüÚ¯ýiüøß MÓŽ†ç lûQ.—Q.—³ßÒÀqºyåËpßQŽ+¡iÝðá4ÐÌóðu¿û»øø˜9P‹NÜñhÛv_ј4NÅÌ-jDÞ̸`¥ÉåÒýa´ô;-†ÆðI2 Ñ4pCÚ¹AÝðâÓpÏóP.—³)P£P +ì&™‘s,jó²,"€îJU±Ø­%0I}]µKQÆ_¨“ë:î¹çž¡;ÝsÏ=ØÝÝE»ÝžéÉÌ‚Q=Xÿøý/Üpþ|7ç J¡ÐÍefX•JÿJ„!½mPˆ-µ‘!†ya%ôi*ñÅèH3xc›9q5x÷}ùóçÅÆ$ºýoA+ÊË2if–’h`чX„†ÑïÑjÀ$R3ç]?°Tuùï»h!¨¤¿‡iŠŸRI<“’Ù>ü®wáÓwÜ1ï³?Qn½µë ‚®ëöU/—‡;3A´¸Wœ$e±(þþ²,V¥šÍî>…Bï{)w{”X¸­Ì‚äL‚ låtâb5Z!= ñ‚­Tr¶-B…h1ªú»±)R¡Ñÿ [EF=þ×çr9är¹ž×ÖÖzƒiû•+Wúö]t‚ Àmo{[WœF'“†_y¢Ó@¿”ôº>â÷( „y‰ç4Ìdxž'&4Š"l<¾jF+r£ì [ÆœFú'4¢¤ù×|ÍOÁ4MT* ½¹~#=«ž'~¥ƒ§‡âñã+æIù¥”`=†H®í-ÄBÿ_f¡šZl‹WÒš j‘¡èV@Ì[E,Àã‘ôþÜ[*Ž*NDQkãäñEï‰øë Z[…éÇ4»¬Ñ[=nNA X,B×õù,:Fs”“ì2 ¦sD÷£¼ +~ã‹44o+•ÄØçºÝ×N)×_»v­ïÅyŸ×Ô* ˆÉ|˜û!œúû‚LBÔ+Zp°‰á•yá=u ´È“åÕTfæ ÊWê±qMë}ŸESt†9¢•ò]·×¬=ÏÃüÀ{ñ“?y …Ÿ€ªª‰¹~}P‹ªÚ$ˤúo°¨HÕõtϋ̻¾2ˆ,ó‚ºk'š&LÒ²|4zO7¡¹C!»-†RÏQÊ/MÊư‹;Åøe„ºEuhôöŠÕT½å§M´_©ÔCª› Z­TÄófX>4…Ù‹âÿ§üÙq}§ÓÁþþ>ÖÖÖî´´’õº.ƒÆº?~Ï{ðO¿ò+Å/ºžœ71 º"•ú’F’zªF1!o£E­Œt–YZ(·>Nx#Ù7<é·7ÃÌ™ è:6]W¬ÆÇ[xžMÓ It]G©TíQµínÅ÷4êS>y`NUíÎkņï‹Åȉ…ªi q9ªÐõÅŸ¦)nFjtOä£'M¡¼¦›µ0|&3Ð…üG’Ô¿ž^.—¡ªj:±:¨6ͤP5^z>D{‹idÒ: &)ⵤ\—ÏçQ­VÑP)·Óé Z­bmm ù|~Þç;6Tq9‰Ûööðæ«WÅ/T½pP^EZlôŠS":­ç¤0\`ºb5Í¢²‚ÞœWæÔ1ÈÆÿò½ïÅO Ë;§b'¼BÍ,årtTÜŒ=Ï CŠÀ¦i}Åizˆ7JÓ‹˜aNU%Mhle“Ï6/Ëér騷ïQN8€îŠ‘¢ˆÅ~êe}©ª(C÷‹UfÑ”PªïÒbš&$IB%mÄE©4Ú¾ÇÁ²zO*Éžiñ†™:×_¸p›››8þ<Ö××{DéåË—±··¸pá¼Ïu"† ÖgýÍß w×]ݦáiŠ·Q <®='…á­dkš±#¥N=Aìîî¢Z­öí°¾¾Ž…-¶4ȶ=Ïùg=«w¦Ü$B FÇlýÕ{=  6¾?+sêIê¿ Ï98ÀÍT Žëö‡o1LÆ1Íþù%\×U#£I®@·:50çÉ5³ 8ðßÙeYh6›Ç«ž×ÛF†ÚòE'ꔇGn."V=öž2Çd QEàz½>žíËr²}G¡–ž”< ˆ}éYAÏ Í;×¢ ð… °µµ…V«nÌçó ›·J 𓏮‹»oº)ÝA, ï©JhHš2„×T:úw”.f§3ÑvQÎ|ìcxÑ7sò›¨0F&*u0Ìh¨ę̀ùJ(X‹ÅîÎôï ªŽ “aT¸|ùa^ö±P”Þž¤ÕÎI #1Ì1å[.—aÆdík CtH â_Ã>¸ÑaÄTÉ‹½eŠë£¿¬¬¬ -¾´hP…àĪӮ‹ÒääºèVý6v+|¤£W°²÷”™ÃRPÿÉÕ«X$X ƒ‹-1 EZ§¨ïû"_•&Ü”«Í fAÑ4 Pp&Ë[·[Š“4‰çg“¬#hª"KÔß7º/Un2Íîÿ=H$IˆVÊUe2Åuó>Yâ8ƒ{û>ëÆ”föã@ä‰[”÷‡l×"ï—ÁTfj(JrÕô?ü0>sË-ó>=†™”b4 ÏóÄJ|Ô»Êb•YP\¸té‘£ŠÀcFxžˆ44b˜ `šÉõN}߇mÛ£+¼;Žð¢–JÝ2òQ¨µ*NÊ$×ÿÙeP_jÛ¶ñš³gGOb|k B¸ªHö²z]ü¨ !Vyá’™2IãêÕF×¾â+æ}j 35êõÑsˆ ÆŸÔ3L†)—sçþÛð*×Ixž˜À×ëÏdšAÝõÊå2*•Êð0xR»ñ~¨Q$‰Ã{—€¥¬Iz4X–…Gï¸ct|™®Àô Ây“¼£iž#,V™`šÉãð§Þ÷><÷öÛç}z 35Ò̹ÃüU†YLxÓ›¾€?þã÷CÓ¶ïÝrÙ®ÛmÓT«qq1&sPaÞ¨iŠìÞQ} ×u!IÒð…*’4L¬2KÃÒ Vß?qÑjY4M×Èòp ¼ªG¿ë×(&Ò‡ø²Xef€ãô Ö `š&žõùÏã?þØÍûôf*˜¦H)J¬Gp´éû><ÏÃû_ûÚyŸ.Û ãûÖÖoá˾L½³e‰©§ü¨0J†™®Ûít½«æQŸ_ò¨ ¶,¡x5=§§ˆ¥¬ž×_g#8ŽƒfÚêwÑú2zóXmˆpá1ZB1Ì´‰Öàð}¥R ªª¢²¿?ïSc˜©_˜‰BÍä ÀB?Ã,”zG‹2¦ lm=jõ§F÷žŒ÷vb˜ BE"“Ú^û¾×uqpp0ú@šÆ…ÁN!K-X{"aŽðj×]t:Ý ÚÎDXZÁm=öÉóoð_¿øE¼ë÷¿[íW…¬îÑÿ ½¡ÀQˆŠÁ¬ ˜ @)ð<<ýG„ÿ÷»Þ5ïSb˜©S.'ÏY<σïûÝ<'ÇI×÷†a2HÔa*IyäÞÞP`Ëî)†Y@dypkÓ_¿x EËýO™,¥`æüíý÷#p¼âÝï¡Àº‚³Ñ?õ"D8M%_ž1B’€«ºŽ_yÉK`q¯Ifɰíîÿƒ @¹\†,ËP¶mw½«ÀàÞ “q¢k-žçÁ4M4n;ZäPHfqœÁ-Pƒ À¿þë¸íG”Å*3”ëæ}£hµZh·Ûc½'Œ <ùƒ?ˆËßÿýPUµ¿Ê¯ á]-@ôIe˜fûÄÜ\QØ6úÈGPvœy_ Ã$2©bžN´\.CQ(Š×u!˲×fæÆqì6Ni{Oÿâ/âWÿå¿D½^ïí'½æ9®}"?[’D ‡ã8ð}?ìhP(ðœÿøÙ¾™‘dÖÃÚn·aZ­@UUX–•ê½TÕ½ý=߃Æsžƒ¸xQ´ qÄr·Qæ…æ9Ž}bn.ßÐÆÿþ÷ÿ7¿ßÊ+ïLÆ8®»®˜äÈ2Â÷‘Gµ/WÛu9˜9QŽkß„mõŸx(làÁO~¯ÙÜìí%lYbBÃ}&™dZömYbh6MáúÂ'>ÿ¯ÿ ÿý¯þ º®£Ùlv# f™õ°noo#—ËÁó<<øàƒhµZ¨V«©Þ+Ë€êÛh}èCÈÿÄ®ð ýb…“X¬2'Ìqì9Ú_ûž·ãžnÀOüÂ/Ìûr¦ãÚ¸ãPÅT¶mîÉ+ Væ9®}"?[ýGáŽúV‡‡¸ôm߆ï|ÛÛzw’$ö>1'Î4ìÛóĂ̗ù½¢Þ€ªâ'ßóì|ÿ÷ãêÕ«¨T*,V™ÔdR°¶Ûmìïïccc°²²‚õõõѽÈßǵûsÜöì÷㟾ýŸŠ¼T®Ïd„cÛ7ïR¸xÓ/ýøLæ8®û¾pšÊ²‡R©„z½>ÜÎuÙccx¹ àþ?ôw?Œµg= ÓL^”Ñuö®2'ÊTæ(žhcóß¹‡îlã}_ü¢P¯çª2‘IÁzåÊ@>Ÿ_Ëçó©ãè; þàóÿ/ù…¼(¨´  ïã®feV«…½½½yŸÆÜ9®}À]_õëx×+_¹Ðml–Ñ–íž”ãÚ¸çªê†bUDlY©‹âÇóæ}™#Y6{XÆ{vŽkßæ[¿€¿¯×ñÚÏ/¾ïæ›ñÛøÀÂåËh Ëv¿NÊqíÛ÷7¿ù°ñìÄw¼óñK·ßŽ/ù±Ü„5£,›=,ú=›ÉÖa7E§ÓÁÊÊJßëO>ù$þçÿüŸ¸÷Þ{qË-·à÷ïþžÿ‚U`ÞW39=ôÎ;7ïÓ˜>ú(}ôQär¹¹žÇg?ûY<üðÃxòÉ'çòù“Ø7÷½÷Þ‹Ûn» ß²ÿSÿ?±¿¿¸ž{˜&Y¹g}ôQ<ñÄsûüãŽá7þå_¢fÿ:/})ßò\]YÁSwÞ‰§^óƒÏ|æ3s¹–IÉŠ-L“¬Ü¯4~·Ûí¹|¿Ç¿Ÿûñã?_ùM<ûæ/Áu¿üËø3º†Œ×q²bÓ"+÷,ÍÁÇ¿3)X;ÑÆÁ1®]»–x³\wÝu¸zõ*|ðA(Š‚—½ìe¸|ùò¼/åXÜzë­  Q®]»s¿¦'žxó7ƒg?ûÙsùüIìn¼ñF<øàƒxÁ ^€×¾öµa1„E%+ö0M²rÏzž‡ø‡˜ÛçOc ¯^¼ØÿæÃC`ì>+ö0-²rÏ~ô£Å“O>‰¯üʯœËçObßÑñû†ïûZÜöÜoÆáááÜ¿ËIÉŠ-L“¬Ü¯4~ò“Ÿœ‹¸˜Æøýþ%®{îsv[ü, Y±‡i‘•{–æàãŽß™¬Ñ0„8ƒnÞ7¼á xÃÞ0ïSg˜‘Lbßpï½÷ÎûÔ&<†3ËÌ$öÍã7³(ðøÍd‘Læ°ž={@oX¼B#fÚ°}3ËÛ8³Ì°}3Ë Û7“E2)Xs¹ÖÖÖz’ƒ]×E±Xœ÷©1̱aûf–¶qf™aûf–¶o&‹œ9<<<œ÷I$Ñjµ°¹¹‰\.&yïìì Ìïc˜E‚í›YvØÆ™e†í›Yfؾ™¬‘YÁ ˆÄo*,³¶¶6ïÓa˜©ÂöÍ,;lãÌ2ÃöÍ,3lßL–È´`e†a†a†aN/ÏzûÛßþöyŸÄ²³¿¿3gÎ ¥hµZø»¿û»Äíö¥Ù> :|ßÇóž÷¼‰Î)‹×ÄLÎqì{ÛgÁ0_ÄëaŽÇ0_D{à1œ!NÛø=Ꜳx=Ìñàñ;û×”ŠCff¼ë]ï:ü¦oú¦ÃW¼â‡¯xÅ+ßò–·~îsŸ ·_¹råð»¿û»Ãí?ú£?šj[ší³àsŸûÜáþ膟ùÝßý݇ù—9µsžÇ51“sûžÆöY0ÌÆñz˜ã1ÌÆÑx gˆÓ6~:§,^sø`ø±½½\.noµZáöaÛÒlŸÕjív>ø <ÏC.—ÃîînêsÊâ51“q\ûžÆöY0ÌÆñz˜Éeã‹h<†3Àé¿GS¯‡™¿ãšÆbÞŠyYy衇_ñŠWô¼vñâÅ÷¼å-‡‡‡b%ã¯xEÏêÈù/ÿåðMozÓÐm£Þ;+>÷¹Ïõ}æ•+W/^¼˜êœ²xMÌäǾ§±} ³ñE¼æx ³ñE´Ãâ´ß£Î)‹×ÿ³Mãrý¼ó²²¶¶Ïóz^»rå n¹å–ðÿÏçÃíù|ív{è¶QïT).ŸÏ£Õj¡Óé ŸÏckk+Õ9eñš˜É9Ž}Ocû,fãûûû w=ÌñfãËfßÓ8g¶ñÅá´ß£Î)‹×ÿ³Mã‚õØÜÜ á¾ûFppp0p[§Óú^ê—5m®]»Öw-×®]ÃÎÎÎH£NsÎó¸&f:ŒkßYµ‡a6¾ˆ×ÃL¸»®;p߬ÚáL§aüeßYœs1ÓƒÇïl^Ó¸pë p÷Ýwcccpï½÷0ˆÏ~ö³·]»vmè{ɨ§MtuçÒ¥K¸téÖ××±¹¹9òzÒœó<®‰™ãÚwVía˜/âõ0Ó#nã‹h<†3Iœ†ñ{Ô5eqÎÅL¿³yMã‚õX[[Ãúú:î¹çž0A:êvOÚ¹\nè{s¹ÜL®áܹs†bèt:ØßßyNÇÝÎd—qí;«ö0ÌÆÏœ9³p×ÃL¸/›}ó~z9 ã÷(ûÎ✋™<~góšÆ…댨V«áÊAù!pöìY½¡7ív¹\nè¶QïÃÂVVVŽ}Îó¸&frŽcßÓØ> †Ùø‹_üâ…»æx ³ñe³oÃO§müeßY¼æxðøýk¬3âܹsØßßÝøàºnøÇÏårX[[ÃÞÞ^Ïöb±8tÛ¨÷Ί|>ßWB»Z­†+3Ç=çy\39DZïilŸÃlü¿ñîz˜ã1ÌÆ—;y ?]œ¶ñ{”}gñz˜ãÁãwö¯i\ÎÎû$–•íímìííamm W®\éIDLúææ&r¹\˜Ô¼³³ƒ•••¡ÛF½wVÐgÒ*Õ8×3íL¶8Ž}Ocû,fã‹x=Ìñfã‹h<†3Äi¿GS¯‡9<~gÿšÆ댉–LOÊ“èt:á P|û°mi¶Ï‚ãžS¯‰™œãØ÷4¶Ï‚YÞ“lß‹Ç0_D{à1œ!NÛø=j{¯‡9<~gÿšÒ‚•a†a†a†É$œÃÊ0 Ã0 Ã0 Ãd¬ Ã0 Ã0 Ã0L&aÁÊ0 Ã0 Ã0 Ãd¬ Ã0 Ã0 Ã0L&aÁÊ0 Ã0 Ã0 Ãd¬ Ã0 Ã0 Ã0L&aÁÊ0 Ã0 Ã0 Ãd¬ Ã0 Ã0 Ã0L&aÁÊ0 Ã0 Ã0 Ãd¬ Ã0 Ã0 Ã0L&aÁÊ0 Ã0 Ã0 Ãd¬ Ã0 Ã0 Ã0L&aÁÊ0 Ã0 Ã0 Ãd¬ Ã0 Ã0 Ã0L&aÁÊ0 Ã0 Ã0 Ãd¬ Ã0 Ã0 Ã0L&aÁš1‚ €ëºó> †™lãÌiföÏ÷3Øî˜ÓÛúüaÁš1<ÏC±Xœ÷i0ÌÌ`gN3³°¾§˜yµ;Û¶áûþ¼O‰afB|Œe{?yX°2 Ã0 Ã0ã8Oà™SÛûÉsý¼O€é®ÔH’EQn—eªªÂu]èºp]7 SÐ4­çý¦iÂ0 ض  ( 4Mëù<Ã0&ÞŸaÒ2ÌÆƒ mN’$èºI’`Ûvhó„ã8‚º®³}3 à û?ŽíW*X–•øÌ‚–eõ=æ¸$Ù2½æ8@UÕ>¥×xÌf…Aãv{W%qlØ®'…=¬s¦P(À4MB|–J¥ží¦i²,bÂR*•›IJ¬pÿ P(`Ûvø^Ú‚ @©TB±X„çyávúìIög˜4 ³ñ °ºº.º8ކÝAÐgoDZW¶of ²ÿãÚ~¹\N\å‚Åb1œ1Ì´5_‰’d£M$L£E–(L˜a²Æ '(Š i»mÛ°, ó¾ †™ˆaö϶Ï,iæ+œëÊ,ÃÆí4ö>llgƇk†ñ}«««h6›P¾ï£X,Â0 d– §) Ðui3§¶}†a†éÂ!Á&|æÌ hšÆb•9xž‡[o½²,³Í3§ ¶}†a†éÂV†a†a†a&“\?ï˜ívþð‡qÛm·ÍûT¦Æc=†¾ð…ó>©ñôÓOãé§ŸÎÄßèé§ŸÆu×]‡oüÆoœ÷©¤æ}ï{žûÜçÎû4¦F–ìaZdéž}ì±ÇªÈáÙ'K÷ìÓO?•••…É ãñ;ûdé~}ì±Çðú׿+++ó>•Tðø}²tÏN2~/`ýó?ÿs8޳0¯4<ðÀxÝë^7ïÓ˜O<ñ>ñ‰OdâoôÄOàÚµk %Xí×~m¡ÎwY²‡i‘¥{öX(ÁÊcxöÉÒ=ûÄO@&Î% <~gŸ,ݯ<ð¾þë¿~a+ßÙ'K÷ì$ã÷ÒÖç>÷¹P[[[ó>•©²L×ÓjµÐjµ°¾¾>ïSÁþþ>._¾<ïÓ‹ç?ÿùl @VþF­VkÞ§0<†gŸ,ݳ‹6†óø½dåoÔjµËåæ}©áñ;ûdéždüžkÑ¥N§3tRÕjµÐn·çyŠse™nÈçó™¸QN ¶ïá,£=,Û=; ¶ñá,›=,ã=;¶íá,£-,Ûý: ¶ñá,›=,ú=;k§ÓÁöövØ£(ŸÏãÂ… ÈçóD,¼aᤪ*,Ëš÷wÅ0©`ûf–¶qfYaÛf–¶qf™‹‡µZ­¢ÝnãÁ„çyÈårØÝÝ ·ooo#—ËÁó<<øàƒhµZ¨V«óþ®&lß̲Ã6Î,+lÛ̲Ã6Î,"'.X;öööpáÂ…0™üž{îÁÙ³gˆ•ýý}lllVVV°¾¾ŽF£1ïïŠaFÂöÍ,;lã̲¶Í,;lãÌ¢râ!ÁbÏçÑjµÐétÏçÃXñ+W®„Û‰|>ªãè™Åí›YvØÆ™e…m›YvØÆ™EåÄëµk×›››áqíÚ5ìì쌼):ΔøfN'lß̲Ã6Î,+lÛ̲Ã6Î,*']ݹté.]º„õõulnn7Ä èFKâ±ÇÃ<‡a±··‡‹/Âó¼©{Vö ?þ8677±··7ÇoY677ñè£ÎäØ<†3ó¦Z­ââÅ‹øèG?:ÕãòøÍd¿gÑšŒÇofÞÐ|ÜñûÄë¹sçô–‹¾ûî»Ñét°¿¿ß†gXOª¾ð…xÝë^‡“¾$fÁX__Ç=÷Ü3“æÉ³²o¸ãŽ;°³³³ÐeÉ™“aggwÞyçLŽÍc83o¶¶¶pÏ=÷à+¾â+¦z\¿™,@ã÷0{›¿™yCsðqÇï¬Ã VVVz¿‰v»½P ”™Ó Û7³ì°3Ë Û6³ì°3‹Ê‰ Ö|>ßWB»Z­"—Ë…ÛÖÖÖzÂf\×E±Xœ÷wÅ0#aûf–¶qfYaÛf–¶qfQ9ñ¢K`YVO.%|[[[ØÜÜÄþþ~˜ä}÷ÝwÏû»b˜T°}3ËÛ8³¬°m3ËÛ8³ˆÌE°æóy¼ûÝï“¿×ÖÖÆÚÎ0Y†í›YvØÆ™e…m›YvØÆ™Ed.‚±òÃn‚QÛ&˰}3ËÛ8³¬°m3ËÛ8³hœx+Ã0 Ã0 Ã0 ä+Ã0 Ã0 Ã0 “IX°2 Ã0 Ã0 Ã0™„+Ã0 Ã0 Ã0 “IX°2 Ã0 Ã0 Ã0™„+Ã0 Ã0 Ã0 “I&jkS­V±¿¿V«… är9´ÛmlmmÍûz†a†a†a˜%alkµZÅÞÞÖÖÖËåˆ~M{{{ØÜÜœ÷õ0 Ã0 Ã0 Ã0KÂXÖv»ÝÝ]ììì`mm ­V  ª*r¹Ο?V«…|>?ïëb†a†a†aœ±<¬W®\¬­­õmËçóÈçóèt:ó¾&æ€çÍû,†a†a†™c Ö••H¥N'ô¸2ÌIaY@±Øö¼Ï„a†a†a˜i3–`%/êææf8m·ÛØÞÞF.—Kô¾2̬Ðu Ù‚•E+Ã0 Ã0 Ã,cW ÞÙÙiš8þ<`»»»Èçó°,kÞ×Ü2dYüÛhO+ D,Ã0 Ã0 Ã0‹ÏØ‚uee;;;hµZahðÊÊ ZbR@¹ Ôj€$÷^Ë4­+RK% ^ÿ—¤®h•$±_¾/>ÿe/»/{Ù¼¿ †a†a†a†1–`ÝßßÇææ&|ðA¨ÌDXຢP’ª¦ŸãˆÛb×÷û/‰ÖAxž´µðÂ>Ë—çým0 Ã0 Ã0 3Œ±k>ŸÇÊÊ \×Åúúú¼ÏY@ÈCêºé«ï¦)rUƒ@ü û%ëyâ}QOk¹,<²ª ìïÏû›`†a†afc Ö••lmm¡Z­¢Ýn'î³µµ5ïkb2†ï ‘©(âG’„xLK¹ T*â}iÈe¹ûš&¯ªŽçÕe†a†af¾ŒÃº½½ ØÝÝMÜ΂õô°º*Bp)§4N¹ †¬–%¼¢äaõýtŸáºbÿA9©ƒˆ†»®øi6çý1 Ã0 Ã0 3c VÏóæ}ÎL!:=/Y°‰µšØ÷lFºÏ9ŽW”¼±²,΃a†a†a˜Åb¬>¬ Cxžï´~á8ý¢£ZÏØ¶8Æ4eq® Ã0 Ã0 Ã, Ö½½=lnnBQ(Š‚ÍÍMìííÍûZ˜)B8–Jâß(TÐh÷Óu‡ Ö ,H)„˜óM†a†aæt3vHpµZÅîî.Ö××±±±èt:ØÞÞF«ÕÂ… æ}MÌ1qœnÞ§¦ oh<ìw”‡”<°ƒ¤n_Õø{d88˜÷·À0 Ã0 Ã0̼K°¶Ûmìîî²,¨1÷—ªªØÜÜÄÆÆr¹Ü¼¯k)‚ôUq§E¡ D£¦¥Ëûtá žç¨p`"ºm‹Ÿz}p'†a†a†aNc…_¹rúÄ*¬­­!ŸÏ‡û0“ãû¢Ân¡pòŸÝl ¡ÿ“וίXÿ÷¼þ<ÖQÞU‚ /yžð¶«8Ì0 Ã0 Ã0Ìéc¢ÖN§“øÚ Þ¬LzH *Š‹uÝéŠ~F¹Üm-¢Oé(H°ROU 9Ï´RIça !VËe!’OÚ›Ì0³$X–ŕՆa†aŽÁX‚umm ¹\¦iöˆÓv»ög][[›÷5-4¦)åˆJRzÁZ(Oå H’ &hš£Å¢ªvE¨¢ˆs¤×£¢5mU@ÖBaxñ&†Y4|߇iš( ‚¥R Aôí3AÀ¶m˜¦ —VŽFìÏÑ. Ã0 Ã,c{X-Ë•+Wp×]w…U‚ïºë.´Z-ìììÌûzÇ".êT”t=K-«›{šDˆj¿š&<·ºÞ©†1ú3$ip˜otþ\.nuÓÿ>7ßü}Ðõ Ý&#AÓ4që­·¢X,†?«««(—Ë$ Íf•J•JÅbA„–ö'ñiÛ6VWWQ(z<²¾ï£T*¡P(À÷}(ŠîkÛvŸ¦ó* ,X†a†Y Æ®œÏçñŽw¼úЇðÉO~°²²UU¹ØÒ11M‘Ç'I(‹¢@‘$uÛÏ4›]Z.‹ÿ“-Åÿ“<™ióF]·>­âKbr¹gàû— (Ãc‚=σeYøñ×aY*ä²e˜Œáº.,ËB$ ²,Ãó<¨ªŠƒƒH’ß÷”„›UÓ´PxAMÓP¯×Ãã–J%hš†F£îgFèU­T*¨×ë}dzm…BªªB–e¸® ß÷¡išÍ&Wlg†af)[°îíía{{kkk¡Guss/^Ä… °¾¾>ïkZX ! +á…%OªiŠÜOj ë¥×!4u}t+šQH’Âñ9¹¢P¡¥÷9|Ó7}Ót¾˜,Š}ŸVÈ“iÄââËå24MƒYé‘eybQh¤‰í IRGuúqW¢¦Û8³¬°m3ËÛ8³Œ%X[­:NX%666°··‡+W®ŒeÜÕjµ/ÿµÝnÃ0 ´Z-Âa «&tBhLÛ¶e”ª–f¾©ªB,GsOé†1Û »žçÁ4MȲ ]/á3ŸñP.ï…^¦—½ìoñÏÿù?Â7|Ãë ëç –¦èy^8Ù{§t]G¡P€ã8pF#üÌF£ P.—C,¡i´ Õøþþ>._¾<»/íˆE²ïÓ€mÛð}º®C–e8ŽÓ4C/&‰J×uA&Ä`Öag–¶mfÙag…‰ÚÚ âÚµkcí¿¿¿ÝÝݾ׷··‘Ëåày|ðA´Z-T«Õ¹~Q„®÷:ª*Â|ÓˆMUظ“FÓ¦çAM‚Â" Ã@­VÃ;ßù¼ë]o Ón·±¿¿ ¢ Óúú:I1¯' åN£­¢ãŒ×FU“Ã~§iš=-7ŠÅb˜¿…òåTUE³ÙÄÇ>ö’c}®®ëh6›=¢”B„)„x‘XDû^vhA„líààF²,‡9ÓårŽã„‹&Ì`ØÆ™e…m›™×uÃöcôcÛvXž íe¶qfÑ»èyöööBqJqî;;;XYYIuœííí°@…[1D…o>Ÿïéû:O¢=H'%š‹š%lÛsEUUEPUu`Xä´=PñÜ@*,³ˆ…dÕ¾O*ˆ%Í2¦ÌÃD¨¦ipårͬݜ„mœ9i¨"þ¬ƒض™4PS4å)ºØIõ8(º,‚°²û¼#ÆØÆ™Ec¢¶6—.]‚뺡‘¯¯¯CUÕÔbuooív–eõ… »):NêϘ6¶-<¢•Jú60ƒHªê›,ËB£Ñ€$Iá*à¼=›“æ¨Î“E´ïI ÜäIÿFî ˆ¿3µrq]7l3鱩¢4áºnªâZ­Çqr‘$Šm<ð3;þi±q&[H’ˆNš¥`eÛ>ÝPÆaÏžhª’aCÅgô8’$¡V«¡\.‡s­yÀ6Î,"#k»ÝF§Óé õå­v¼ÝÝÝaÑPã8×®]x³<öØcxàú’ǃïwÅ©ïw{˜Rñ¥IæÒA ¸Ã8¥R©g¥î$VâlÛû9óª³dooïz×»ð%_ò%S?ö¬ìüqlnnBUÕ¹¶ò}–e…UœÉ{Im†Òˆ=Ó4áºnèÉ´, «««e9,¦E‘¨ï(µ2f›tnTX‰&ÑÿC’¤….´äy"zã‰'þÏ{Þ;üÆÔ?c‘Æpfùh6E¡˜‡z·ÞzëT}Æof0a&IR_Ñ=Ïó`Û6\×…ªªa:ɸÐÜyXÿùÍÍM<ú裫÷¿™yCsðqÇïTÖÝÝ]´Ûm¬­­AUÕcÝ@{{{XYY뺡—öÊ•+¨V«X__zìaÕ‡_øÂâu¯{]bãI°má ¥Þ¨ñqÅuǬ–Õ g4w¦þ‹ªªÂó<”ËeT*•žÅZ”$i¢6®ë¢\.CUÕ°b¯mÛcµÒXdÖ×בËåfR%xVö wÜqÇÜd;T„‹ f¹\†ïû¨T*=+Ë´"M¶ª(JOØ-æŠí{Jí‰Êå2LÓL|Ð{ž‡b±ˆJ¥ÒW‰zQˆ.’¦Ù?f˜¦Xø:8è?†aªújlnþæLÎqQÆpfù(—Eñ­­-œ;wnêcø²ßÌ`H¬ÖëuȲŒb±.’’¸Óu}*Ï–J¥‚ÕÕÕ°Z=AõCvvv°¹¹9u± ðøÍÌŸIçà#k.— oV×u±··®ú€‡sçÎ Ý~öìYbˆnŽèÿO ;2M ®ãTut8¯ëŠŸ³g?…/ýÒwcoï6¼øÅ¯E³ùœï¥*¥ºH+qÑðTI ¸®¶ŠIãA"ÏV½^‡ã8( 0 ãXý%™.‹bß“0¨½ (½Aø1S;€IDAT°×u½Ç›:nTÜ.kµ …lÛîó„Ò¹-b±$ÇéVW”n«+Ç^Óø×F–ÕyiQËlãL/”›7¯ÐÅ(¾/ìžž­ÿüŸOÿ3ض—›èüÉ0ŒÐ®i!6úlk4(—Ëp]7±ðäq1 –eõàb±>óžzê©™|lãÌ¢2Vk4 Øuݰ$ö8âumm kkkáï?]•Y[[ÃÞÞ^øšëº(‹'úÅ躘:ŽXÕ·”‰N M³;Ù¬ÕÄ6Y ÷wâÛ¾-õuÀ²ª¡@ŒBÕåâyvŠ¢@Ó´°Âi©TB­Vëù®-ËB¡P=¤ŽãÀ÷ýžÜ ß÷ÃbJäÙR%¬`Çà¦Ã¢Ø÷$X–MÓF†¨K’„F£R©æùL³ˆQ£Ñ1þ¢ÏYD± ˆ1„nÁhçƒèë¦)Æ$EãLôöf&ïÓ¬Yfgz¡<ð㦈°Ñ ¿O¢§ûlõ¼ÙV¶íåeÐb=Ùx|!V’¤™FQÿù  IR˜þR©T`Û6~îç~n&ŸË6Î,*c]"¢“ÃV«×u±»»‹ .;Œakk ›››Øßß“¼ï¾ûîýb(šÑ0€b±?çÔuÅCÓqº-g¢aDZP,žA¥òîð5]×CHÉú€˜l;Žƒz½ž¸’mFØ72LÛÉK­f(|’þOa”ñBº®/tÎÞ"’û J+÷¹Ã‡z(õqzè¡Ã‹/Níóëõîÿ›ÍþíÍæá¡$õîG\½zõP–åëW¯&ûêÕ«‡†aʲ|(Ëò¡a#ÏçêÕ«‡Fcìë0 ãPӴé}7ËÀ´íe\ƵïÃÃÃ÷¼å-s9׃ƒƒCY–›I7œ©×뇒$MtoÌ“«WÅØa‡‡²,~R©$¿žtÚ/¾ï¼ì…˜÷ÎY–5M;l6›‡µš°WÃ8<¤ÛíààðP×Û)ÙyœZíðPQhŸ«©žO²Üý¿ª6͹ÙË"ß§•¬>³¢Ð\QÓ´ÃZ­Ö³mÞöÂã73K&±—TÖV«Ã0Ðn·áy„qý×NÞÕiU¿[YYé [8il»ëeMŠ€TàêÕä÷š¦Ù“G’$T*•г™&w4ÚÛk–¹Úï"3oûN Uê­T*sï—Uξ/<Ÿ”jÛ"CÓÄïA ]wð6ò°Ú6Ë=ƒ pŽë£P(àyÏ»­Ö[aY6~ñ¿_ÿõO `YVØž-Zä†+åÈÒë \@,àD=µŠ<ñÄ—ÍûkeæDa+¾ƒƒƒpQµP( T*¡R©ðs‹a&€t]‹[b^xë­·¢\.‡‘¶¶m£X,¢P( X,¢X,buuÅb±güŽR(§çË_þò±Îm¤‡µÕjamm­§Y°{T7º:¬aö2S.—€'öÌRÀ^ÕÁð¢6›Â³*ËÝÐÈSÒ˜YPÊe!ò¢ÎßÑDIE“DuêCèºÇ~ôG¯ÂuÝžvjl4MƒiŠò”Jߎ÷¿ÿ`Y/çyÐ4-|>ʲÂQà»¾ëƒø½ßSŽÞo†^]Zá.G‡#Eî¼ó'ð‘Ìû›eæmÛÐ4­çEE%£vÊ0ÌxP0UUáû~8.K’„ƒƒ¸®ŽÏš¦¡V«%F‹’°n£{Ó0Œ‰œ›#=¬+++èt:=¯QÖe©i*ROJ©{ 2LÖñ<ïÔ¬N›¦øt¿Ç>°,á塯fA;è0§ j¹–dÏŠ’M$*ñŠ~†ll|{8QY]] ««6›ÍPT*b1çï|~û·º®ãàà g<‘ežç…«ö=ô{až¡a°m;¬HNUÆ76žéKÓqøÀpÇwÌûëeæÙ_EQ__D®\¹sÞ§À,1ž¬®—.=¾wFÒØ­ëzØÅ„ ¯^½ŠZ­Ç‘‘ÔñHUÕÐK𔑂5ŸÏ£Õj¡ÕjáÀ®ëö%c“Z¦¦Ã‹Œï v]…B’$qø/³TÄ‹W,3†!Äg©$Â{©G$Ð-’ˆ^§ ¼$s!æ ¢†u„iš=5!f Ù­¢ôÖgp]±èBÎ(‘K*þ¯i …ßî9õo6›¨×ë‰ù¦4tP±¦$È —.µñÄß¾î8NØsœ&G¿û»Ïô<óÌ·Ã4-¼úÕß ß÷Cïj”¤v˜âsÄÜ(ºf¾P¼Ê²œøÙÇi!52$8ŸÏcmm ›››X__û2чv:\¾|ÛÛÛX[[ «/ A ~¢stUÜ.Ú|:ëèf\Ù³êûbm6‡÷w¤I»¢ˆ‰¼aZ(ˆWQ„¥µ¨FC Âiªö2Lß÷Q.—û*à’—1>9(•JSØ‘¤î3î‹x£7¼a—/ÿ¾ök?…û±/àõ=ߦUÅTUÕPtÜpCï}ïxûÛ®äSúL×}-Q@'‚ð;ºÿþgãñÇŸ?µï‰û¨Òœ,Ë¡÷œ&ÉÑ^óÓþÌ“(Täû"‡zO‚ç‰cŒSÉý(p¯zÕýÆ+JÜnLÓ„ã80 ¾ïÃ÷ýžˆ– pÇ_‹W½êeø‰ŸP¡ªï†eý×b±xT ¯WPú¾Xԯ׻ÏÓìÖíˆÃ#M¥(Jèa¥®žç…cÂý÷?ŸúÔKƺ¾TU‚+• ªÕ*VVVz 0Ý{ï½ØÝÝÅÚÚÚBV;ó<±ŠO Z J†‹R}ŽaÆ!žoeL³·ÕE¥Òm±áûÃk¹Ü£„®‹cÑÀ HR·Ú)ÃŒMàãPhT4¢Áqœ07tгtœvt<ŠŠÞž×}Î9Žƒ?øƒ¯ÇÞPÅŸÿùß@U_Ótg6¨ªŠr¹ ×uñúןë)N8b!Y†$IáØT,¡ë:TUÅ-·ìãòeÀ×Ïä<™d¨VÔÓIcò¬«ª ˲°ºº ]×{ª@‹JáC›“pø¾x7"ê}tiT’*`ssæ—È,8žç…Åê¨eذú#A æí×¢Ñ0€ï¿ «*d³•J· _±(þ¥Zq¢s%º—ƒ@ÌÙ®\¹’$Á¶…`ÝØÜÊ,‰‘!ÁB‘zéÒ%Üwß}=­kÖ××qéÒ¥°½Í20¨­ Ã,#‹lÛâ®îQÈ•¦õ/8™&zr,*•Á½•¹x3Mh…9Eá®ÑʸŽã V«%†qår9,Z4Šßø¿ÃoüÆßõ¼F =41¦ðÚý¯oÄ?ø]x晟Baû™YA‚FUÕ£|Ùþ},‹òƵ°¿®ë™ëWyZ VgTA¾Ùl¢V«¡R© R© Ñh„áƒÔk¾Ñh hšl ÄÇú¾ÕÕÕ¾jÑU$=©¿4\>~ÊÔgèæšfÿ~ÑñR)9¼˜"ƒ(´rý>Ì ñ}¥R)ñ¾(•J$ ªª†÷ß°ÅÌrY,ÎÇ#JÖTCÏ*íC÷B­&~Òår_¯øŠdpœÿ;ï¼>ªÕGqÓMÏŒõ]¤¬€ÈQ­V«¨V«=Õr¹Ü„ ýbÔóú™AóÏóŽÍ0Y&«ÖèýIžB«ÑñÁ“îárY¼?M0¸ ÃL‚çy¡‡)úš,Ë=¹œA„Uu]OÌo%/Vr^’XÈ¡‰‡çÍæs (rÏDG–Žñ5_ówp]'lR.ߊrù ¾÷{o‡eY¡·lVP¸=O)$¿\“¤ÕUqM¢±®×ë,Vçå¶Q;Šf³þMF!Ë2*•JøwÖ4- #ŽCùs¦iöˆZÛ¶±ºº ß÷Ñh4NÄi½ýTµÞX.wŸ9ŠÒõ* ÝE!šìõz²¨•e2LQB ?ü9¼üåïÇ+_ù¿Ãpû(AÅ3ŽþOtm:)JŸBy£XVrk¾46Z.‹1ý#ù? ËâYupÐÄ«^õ2(Š˜ÝrËßý¤ ®V«ØÝÝ ßÝÝÅÆÆ¶¶¶&ù;Ì$qý+ZƒžÓ³~ˆ3Ì<¡pÞPøEŽQJ½.&±iV÷(ôEQúÃæ¤ð}?¦4i§HY–AØSR×uØ6 ª:,kµïyC•Q%IÂÖÖ/àÛ¿½¶¥‘eaë´£(À 7܃ÿôŸêa @¬’èCU<ðÀŸâÎ;oG­V ?£R‚À=h³DÓ´ÑMÏ`×÷vü1[çЇ‡ò…ÉCÚh4Žm†!ì+žÛ* ~ùaû£r¹Œz]Ø®mÛ'ÚfúlÓ)Æ=R@ï( l¶R?¶-&ûñ…QYÇ,—»‘<®Û­™À0DxÝëÄW}ÕíxàW@–ÿ Þð† =û¤Ñ#Ž#æRô|4Ra‹Ý|Ý(¶IÐuñ¹O>ùr¬­ý€¯ƒçyǾ‡SyXwww±¾¾ÏóàyÖ××±»»Û×î&ë¨jÿ B¹kQ’B2¢†YFŽ[Ám¨Ñ{²ÙìÞ“I!¿IP¡ «Ì¼  ¦„çyxôÑ ”ËÝʸï|çoá¾ûÞzfžõ¬‡ñ}ß÷¾žãQJŠ,kxè¡ïÃïÿþÇ¡i@³@U­ MfÈ“IŸïy.ÚíKxâ‰ÿŠJ¥Ò7á¡PåY V £ªá‚ @±X sâ¨Bôq¡ðÅx^·iš¡ˆ5 #lhÛöÐ÷Ž#&o½5ý9Ð:‰i&GÝÅSCâ—=ªâ¯®‹÷'y§t]¼Ÿ.Ÿ"€†‚¯yÍð¯:ZÐððÃÿ¾g?×uQ­þÄlákš&¼÷Æð¢‘ñ ò¦y¼ÐtÃ77¯Çÿú_ SI3)X)üwcc#|<«Ôêf‘‘e±–ÃÅu]ö®2K7(y{ÆD£Å$¾ÿa?î\‰V³f^D‹ÐD½‰¾ïãÍo>ùƒp]Åb¶m'†ݪ¼€£Š#†±4½,™ñ!±:«|áxîv¼÷#Ðím?L¬]q©i£çp@·j/ &䵚X ¢GuŒ”bB ªÇ¡VÏ9ßϨ 51î=Iª`{»·&P.÷¡ž1þ¯þjwÞùT@¥Ôq£æ£Qè>:®ï¢ÑÞúÖ›Âsž†C$uk4Ou‹+¹n÷%ú‡&’$×u¹à³´A0pA&Ä vüÞqÝÁÊÆÁ¶EÎZ¡ & ƒUU…¢(añ]×{D@tr@!É–e…^×aH’”‰ÔæäñdY#W’îò.*Šö”.•JxéKß…|þ—àºîÈ…"EQp÷ݯÆ;ßÙßÑaÝ (BaÚ‹)²,*ÕOc,µ`ÝLèb\­Vqï½÷ö¼¶³³3Ý«Š" %!H°F“ŒãÏtj7À̇ÅÌ ðÆ7ªøžïé¶¾X]MŠö—6 !`iº{¼®V×»Q –%&š6~žÃ,=ö/qñ¢¸‡G„s}ó7«øþŸñÜ’$¥š”«šö;®‹9]˜¦ybb5-qqýHñà2yÃè>‹&ß?³–ê2ÈU.w[ŇMߊEÏ<ózüá¾Aà…íÆ¨Žµ&#¯)Ë+—Ëa¾ûoÿöö^ŠK—€Z-ÃèæWªÅ½ù'ðýàñi|úÓß7ÕïEÓ¦“â•tÞÓJ©)XÏž=ÛSp‰Èçó£Þš)ÈC]…£³As ×u\õÌTñ”Á‚5P¿Hš¯ÔjÝ’ûàpáAÛM"fYkßú­»PÕoÐ]ežVhTš¦…ý[³$<˜lCdY³jÿB§å8éÃ)Ÿróhñõ8’Ä‚u Ðñ$ÁJm Çëʰí®S˶ŸüÉ6r9ͦx1Äâ ‰± à8ŠG…p¨Ê6UE§È—RIê 3WUaï£dÆ?þÇWpéÒÓh6Ÿƒ{î¹aªß åƒOŠN=k.—[¸~«IP¯ºè€EኪÚÍÏ£>pÝ}¸÷êÌ8~63%._þ~Aïh5n|±Ø›ÓÊy:Ìi¶m¼ÿýëxéKoƒ,ÇC¶”p²2+a@¹ª²,s “Û¶§îOJ­ò¼ntMÈëDDZ¬áùuž'&ÿT…7ºo£qü^§¼ØºøØ¶°ƒAžÄù‘/"ŸÿÏ(•îÓOþžóœ2<¯€ù‘/â/þâùxÑ‹~Æ»ÂýËe!hi¸•$ihÁ2ámÿ§÷HMS^`mí\7ÀÙ³?Œ×¿~qœhT$𸤮Lìïï£Z­†?Ôö&ëP•àø E¿G×è÷ÊýWgHŠ2ôÌì à‹_üÆcç@4é]†Y4|ß[Ì â?þÇwâþà× iÞÀþ³îuL^V^deÒ@-e¦i/¾ßŸz庢¯euë Â4… ˆ¦caØZU &çCt®—Ôª†9}Poö¤œçrÙÅåË—ñ ßð šÍ&þìÏ>€3g>†7¿ù¯ñùÏ?üû=é•J7:Ó¶Å¢½iŠÿ*Š+I“/~¼öµÿ€?ù“áû~æ""†Ñ˜R%§Ô9¬®ëââÅ‹h·Û=¯ïîî"—ËÁ²¬L‡ SkÔP¢%IÂðâ†ÄáÀ3D‡gß÷ðÆ7ZêÇ>Ã,#Žã„¹HŠ¢†ý ÏóðÊW¾†ñ-(•JзÊ.ËòÌ{Sá.®Ä¤Áqœ©÷Ü¥º€®²,g4¼wõ‡‘€M3É?8è†X2L¥? à¿ÿ÷üÉŸ¼ /ù?=ÚW„ñ³»¨¦PÕn¨ë ñZ¯÷‡°gmH–eÜpC·Ýöúy•s!•‡u†aàìÙ³°,+,‘ïy,ËÂÙ³gqþüùL{[5­Û¯‹ˆæC$ ¤A,ÜJÆB¡à¯vnP’?Û8à ÇqT*X–… “êKìyÀßøåaØS½^[DIzmÚh卉L*<Ï›I™®w=£T¼¦Ñs-ª%BõCâ˜æà<¾´}ªKÂ0„m‹âD¥Òk#Aà™grxùËŸ=ñgŸ:,P_²sÓì<UUñ©O}-¾ù›WæømÎT‚u{{ªªbgg§op‹¾¾½½=ïë …´âBqíÑ^^Óªl•ÊÌcezØG?NÊýKó>áåÁ÷Å`ªiöÎ0à†çä1õ}ͦ˜Y–˜„ÜrËvOq‰¤¨¤ê½³€ïefÔZ£žÐË%ºaµãâû½ïÕ41q;üéù­ä›o¥’¾7d´. þ?܆ÇÁÞðSýLj• ŸFô ö9§‘‚uív÷ÜsÏÐý666Ðn·Ñjµæ}M‰ÐÊ%潫®‹Ÿèºt—JÔãêy~è‡þñÔÏz:‡I ¾¯§‘‘‚µÕj!—Ë!—Ë ÝòW;μ¯)2\M뮾E›íR¨Jt°£‰ÊR‘•4E €@=úw$>Ó n,X‡à8”o±d‹2 3eè9`ÛÀö¶År]’$VÐo¿ý×yÁ‡Y<σišŪãtCv1(œ×÷û{§ƒB(IO#’ÚØ0§Ç‚4©À—mÛ0M³ÇÎ÷ön[˜1|н{Ytiee×®]›÷y›h®*­êŶhÓÞ¥Ëëó­|QyÌ󡤃Ñ7@¶¼ÉƒiYLÓY˜šaN߾雾ˆë®[‡,Ëá³A’ ˜¦‰F£I’àyÞò-l2KI¹\F¥R8ᵬÑÅ‘l[ˆÌxˆe´gå8¨*‡ð2Ç'„@%‘ÚhAà!ºEèLӄ뺂†I’áû>žzê‡æ}úL FzXóù<:N_uà8Tpie%ûÉÀ´:_%tœn¸05Ó^|Xœ÷‰ýîÓäÕº*…šÒ[W N X,âÞ{Ÿ‹b,]ž6ÃL€mÛpbËñå2ðš×¼oy˳z^WUº®‡Õ€9¤žYLÓ„ªªm•¢ÐF­Ó†µ€ –%¼Y¾ÏÞMf>PQ%ß§‚G,« Ó4Q(P*•P*•šÍ& ÀeY€ÿú_߃öÏþbÞ—À¤ •`Íçó0 c`¸o§ÓAµZÅÚÚZ&[ÛÄs*¨°’JµZwuÆ÷ýår»{H'öNŠhµ´Q¡»ž¤@„§AC¶<ÊÀqxž‡ûïÿ Tµ[L†[`0§×uÞ”€˜„Ë2ðè£?Ø^×uȲŒb±Èb•É<¾ïlaõ‹ÃsQé‘A‹þõzrq%†9 TUô€Q0ŠÅ"dYF£ÑÀÁÁ À¢(au]×ñ¡}o}ëð—ù'xÛÛn›÷%0)HU%øÂ… h·Û8þ<öööBok»ÝÆÞÞΟ?v»­­­y_O"Ñö5ô;œkAŸü—€ñ\€“ ©%X]t…jš¼TõèÇ:¡ó_¨§ðãÿ€Ù´4`˜E„Z|âùà8À¿úWÚÓ´V«êÌâ@¡ÀÃ'©®ÐíS™´E¡B(Æh¯,ÃÌʇ€R©„J¥Ò³8£(JßbÍùó_{ï}>øRÄT‚5ŸÏcgggÏžÅöö6îºë.(Š‚»îº ÛÛÛ8{ö,vvv2é]„!GT2ìx5¹h#a?M©»E¢á¡” à(ôzAG1N£x>í¨±BC7¼7Í9ѹØ)ö=E¸® EÑðÿß¿ærp80sÚ ‚²,CUUÜw_ Å¢x6üÖo½sä‚N­VKôÀ2L‚ ô6 ë©XÍd9¹R°ë¦/ªÄ0'A´2µmÛCÃޣ躎gžiáóŸ¿gä¾L6Yt‰ ÑJ­kZ­V.<ª‚ð ¨Î ¡Ûjµ°²²2ññ‰h5``pØ ýÒ\„PÒ{Yǹ|BH6ÇØ?~ü rŽÃÎgTk³ZGºêÃ3ä¤ì; ”“mš€a|#dù7,Ï>˜ÉÉ’O‚ï÷Üó4þöo Šò<òȽh6+$ \vÐl¦Ô˜ecÑm›Äª®ë#Uâ½KE»³þý\w:Õ|™l°ø6.l—œO–e%öÀNB’$|Í×ÜŒ••§æ}LJR V‚ZÜÄW0:Z­ÖÖÖF£ÕjÁ0Œ0´8—ËÁ²¬ð¦i·Û0 #¼™TU ¤§…e czYé’–2ÕÅxÎBú`éÅ*{¿‡Áù©&DÁ%Úw„G˜[Ñ¥,Øw ÿ¥òJ¥ÒWd†aÒ’EŸIþÑ?ú=Üu×?@Ó4‹ET*ÝvOœß}úXÛ. 0 #U@<ÚLQú‹Rº.Wó]–ÅÆ©µÐõ®ŽãlÚÞþºy_3©B‚ÓÐjµ°¹¹™jßÍÍM¬­­Áó<<øàƒX[[ë‰/ßÞÞF.— ··Z-T«Õ‰ÏÍ4{W iõ0>¡òêžç-×DÅG×3™6$ØÁìŠÅ=¬Ã¾êø¹Ž:]Áêc.­mNÚ¾Ó@á¿´:.I‡22“EÓÏ€g?ûO{rU©@ çwŸN–öMhš–jŒ”ý$˽ýXY°.Ë`ãù–,ËZT, n©´XLM°¦eN',д²²‚0Ô¸ÝncáöõõõÔnþ4P/ÖANÔ NÞÕÓFA×Ûh ë­DÙ?Mnj šFBTF¿^ƒóX£çNïFôœxkì;Žã8Èç·›½3̸dÑÆÇ%Z8Æó¼PœŠ(Žãp~÷)dlÛ÷}¸®›8y÷} TêzO]·¿[/¼f“e°q@Ø0Ùî$ÞUfñ8qÁJ¹°Ñ~­W®\ n ú4¦>ŸÏì;ŒJ¥w Õõáå×)ìD)c¼ÂEã cuZà[bñY·maÚ&æë–e¡Rå‰a¬+++=y®ívÕjëëëÈårCoŠA}`'ÁuÅÀíyÌØ£ïû'?Yñ1;ÁM=ˆ‹º$Èû0LHDîiq‹£kŒïç#Ù;ë¡ßC:Ìσ•00$øÙúl¼äá—ŒýUŽ"+öåƒ|66næÖÌTÈ¢ý¢joá1ú?‡ŸNݶÇA£G´¡i6…5Œt^SYîæ 2‹Í¢Û¸e ÁÚl² T*¡^¯óã)àÄ+ÑétP­Vq×]wamm .\_ĵk×n{ì±ÇðÀ$æÑÆC^heQ–…8µ#ñaÔâàÄ 0»àhm4žP¸ÃÄ!A"qˆ8ì¡„~ì#9t×NØWÆàâLñ¼Û"zoo¿ó;¿ƒýÏìOôu¦aÚö ?þ8677±··7Ö¹|â_^|<]lnnâÑGégœä~\Μ9¶*sœ®WÉó¼¾ñ¾R©p8pÆ©V«¸xñ">úÑÎäøY¿ÇÁ¶íž&ÛâT’º?£8s¦7|ž9hü¦¢G³`‘ÆoÂ÷…=6Â~‹Å" ÃX®"©§€½½½‰Æï‘U‚Ó&[³òÒjµ°½½••Üwß}}¡ƒVZû…/|!^÷º×…qùQâ¹{Ñ&ÃT`‰ª¨&M`N„:Ò瀎ƒ‹þÚʈýÇq.D (ܺ‘¢¨H».DÿØ8ñ*ÃtIû'ˆóõõuìçöqùòå1.4=³°o¸ãŽ;°³³3Ö¹A€n¸a&×Éd—™NNz ?4ÆÛ¶ ]¯ô´æð}¿Oœ²XÍ>[[[8wîÜLÆð,ßãàûþÐú¾/<ªã@žXæd¡ñ{˜½‡E¿£¸.ðÒ—~åòÏÂó¼Ô…ŘlAÞüqÇï©yXãaÃ0 #Œ£ßgÏž€ž°„v»}¬>PI‚õêUñÿ ÂBÀœÂ!ÚfáK Ã@”“ XãØ£<¬ÒkŒ96’Å- ò}‘°ÒÃ8éZà†öìDÜIÛ÷0~ù—?†Ûn›³\dÉÆGáyt]‡ã8¸tééžœ=ß÷9ü—éa‘l;ŠXêõ: …*•Ê|&0eq–öcÉ›fÂ{ÅÆà¥ºÂoT«þ~ªÃHòŒÚ6¬olüsˆpà¤^°Z¾&ðÌo>Ì †À<ì{‡xþóÿv&ÇfN'Y³ñQDÇôO~ò§z&9¾?‡¾WLfY4ÛŽâ8šÍä†è¾?¾Xe–“E¶ñ\î>”J·rð)e¤`ÝßßÇææ&¼ˆ›²Óé Õj¥ö¨F¡˜ü¤p5úŒ­­-lnn†å·WVVp÷ÝwÏä ª,Ëð}?\?Q|ñY¶rxšÐ] Ñ?¨!—$FãÂqX¡…ø×4ìÜ=ˆÜØAÇ3#ï§TƒÆ¤¤cÔ\>`ß‘5û–$?üÃ<¸3Ó#k6> Ïó`VW Ð4µçužø0QͶ JiJŠ  XæzŠ‹‰ï§Oø=.A ìÑî<ªÖ;mÕÆaçµÚ 'pL¦)X“¸÷Þ{±»»Û#bÓ²µµ52Æ=ŸÏãÝï~wxcM"Œ‰`D^%嫪ª ÇqàûþÉç°ŽÛÞ*m ªàÛwÑ诨;lÿ$Œ® <î±é˜.{€}ƒŽM9¶ïŒê-´}"®žÇL•¬Ùø(hQ²T^ô¢u˜¦‰ xòÃô±h¶M8Ž302ÌóÀE÷&ÁqDÅÎJEôO9.ž'’0ƒ@üÄÇßï ä Àm3ªÈ»¸64›oæ^«ÓĶ…7Óÿ/•Ä¿ŠÒmêLoƒÏ/—Ûoë Ö“`œœØaxÞàÅ1×uCã×4 åry¾“û4s'½U‡AÕ{ã ºDýÞX«$¼® WX:¢3Ilº.ÌtEô(±jí§F¾ zžx^ïçøG;wG¿æÿÏÞßÇ9ržu¾ðÏŽó1˜X¡œ×¥íªb{p5#^’@)YÈÚ˜%xðd=ûGZ7´7 U‡9Ëš£bÙ ;Tl6mÖ¼¤‹4Ø,! ÚÌɲÖÐÅÉ.‰5ÒE’Ä]Œzþ¸ûª7•Þ¥VIº¾Ÿ>3­*IwI×}×uÝ×›xî_Ý=ä8;¦%߃xì±P­þ£y_.³‚œ•Œ÷#êE•e@׿†a@UU6V™±É‚lÑÍÇúNôÈ)Ú#âûB‰÷D½O|æ!bQ#o˜#÷é÷~þçû=žKÊv/ϯa³î÷ „à_~!ðÄöoÿé-À¹-Àú«0Q§±Œe_õ…À«Uà—¿ øÁÇÓÄ×|à8yÍk†Ðâ@ÑDÑJíösØÃºÈø¾y ¡ÝùdSDÓ ªaï &ÖgUا2¸¡$³D˜¦T¶–$¡{½‡–^†À÷ÃuTÓâzDꓨ뽿XÛY?@¿s™¡¸ûî}Ná˜&Š"6dño±(Hßÿ&å_×Ń ÝJEÌU õ”h(¯SüÍ–Þ`z¯É¦©·3 \Ñ~D 4ê#Úï÷¥÷sÐ?,×…0jÓ>ŸB‚£ÇȨLûì4ã8MçëõzÃ…=»§ã8àîÚ$·‡5 øË?þø@{.ð/n¾ö7{¿§@ùRÀúRà^?ö½¾r<5FH{–qݰ1<ñþѯø¦yË ›'FçAšË„vGm[ìhzîÿèGç}sÇó<|û·a–ÏóbÅ–%t˜T«Â¶âÜÕ¸®ø¢HßäUUU±ÆV*áÆ¡ãÄ×eò@1cáûÝ?mÛÐGíË´êP˜¹ãˆ`/ª$ •tâ~F¦¢ˆÝß9D(-½ÁjŸ†Œ¦­ÉŠÀSŸ %Çèïétz*=tWÞMB“8B›zá}>WF·j!ݽãýóg„€ªjo/¨±Ò¸^(ðÖéÓÆâyaØL½üyøâ ôN1hw2öp$¾WõåÃÿ‰ëû»ÛoÇgo»mø×/žw¼¹®‹\îOç=,fT\Whœ¤}kiIRì†ô[[[X®‚Áœv' – Qg¡†O}ª´Ã,"•JÕj’$Á¶Åí·\ËF±¸¢¹«”'JÊ7…åÒ:Z«Å×TEéíMMƒ6+aè–Ëa {Q'‚Ò†IÕÜØ²ü‡ø üýßÿ4G‹E!¹6Ít=Á÷…1lN€$e>`hƒ5ZQ¬}š žVel–±Ç!™Ò…z°S ÔzÆCƒ5z\‰¼.õb Ñ*„‘Ûo¸ýŽËè6t«‰q:Ž˜ŸûàŸüK`§(苇@û!àw¾(>A(œæmß|Ã[Åßšœ{- }Mk÷Â赯þ4wj¼¿±ÿwK•“9´½X‡ð&/¹‡Åóâ²þ裷a}}þ¥è3 …w‘±7É@.î´ÌbQÜ ¢ŸA¹RŠ?_QØ-2&–0xöÙ<\w.›Á 3SìÓÝxŠ ‹F×в´ú=åÅ%Ãû-+¨² E_À¬Âqk5aQÙ¶øÿÒ~ÙgGÒÁ­ë8-–÷^ñŠçÎ{xó"èÿQ%¼i›ÚÅ¢Ð+–h§v ÁzçwâÂ… ]Ïg)»ýtÐqªaXõó‚ú͈¢üU ñ:yÀ±äñä]÷4AZžb9'v_ÿàeŸîþR)†c£Ô¿#,4ð ?Þ@’=â’¡Ž¯á»Ð1|%aƒC³—ˆbQüTÿù?!xàÖyçl‰V¢K*.i í$Ž#”U‹?m¦Ôjݯ¡‚®¿QÐg¤…sÔjB™ÚØóJÓâF,3¨¦ƒçÿã¼íöáÒ¥yŠa¦a¨G<ƒ‘z&Ì~"…<êö¼p­õ}±Ö*JXI3mÝ<ëµ´^…™‰Iʬ¦‰Ÿû­oý*¼ýí·Ï{xÓÁ0 ^”èÞ`5 Rÿ.¡n1Ð`][[X;ËôЦó}¶ ÜäÑëg'Ckˆ|Ï~çÓzî¡wûÝ­^\Wx@©lzûËÜŸû<à£o®½.þiáÑ>€ÿõBà]/Lÿ¢u]ŒÉ È€£‹0ÜYÜ8G uZ®9Ûû2#×éyÀg>“Ã?þÇ_5ïa¥’Pl¨Šª†9ÔR —ÁªªBY¢ªwšÖÛ-GULFY?dY¼¿®‹V¥"ÞÉn(ó&ÈD°€w½ëKqÇú$³4ƒÅ²,hškñ±põhhS›*è&ã—I©§ £0ßr9; é½ gfdèÝ­zxÑ‹ÖpþüâÚ!1H(ãúŠ$…›3“ì6ѦÎæ,}«e¥¯'3oOÆh¿p÷t’Q7r¾ŒÓ–.‘@º« ¯"aÛÂX­VCýÎÏ;ïþÃ?¾þåý?—6wL @¶£Tf¦Éy½.Ö¼›oþØòæ|¤Åú§U•åô\è^ S,c H’æV°`Ù¡Ô5MKÝåËŒüÁ—Ì{X 3'Œ>}Ó›îE©tS ÛR*eVì¸TÈ8¥*¤’$&k¯<ýä¦àäØ1ãC-™¢TN½…ò' PlÉó„Áy–¤ð¦ÕMH BHÓž´K¼²ô«i¦ÿ~ž7L_˜1q!Œ»Aݪ=^›†ÐX¤|Ñ>P>_ÄÿàÃÝžÛ4%üu·Špß €_âšüÓ1 q®‹¸ÁÌ̺ÿÓ‚ïº@.÷§P”ï™÷ÐÆƒ<)/Td@ÓÐ¥ÀÌ’¨Ýu]|þó?7¼a˜‹a4âá+¿²„—¾ô(È0pœ99T¨#zˆ(#¹HÞH6:™'¾[*• Ë2ªY÷FÛ!Q8/é.½R„è3C¬Ífûûû¸páòù|OïäLóBÇ —ƒ)Y!xªxËuˆŠ¶ÃÒ+TÝ‚0p]W„ª*ð‘é¾@O._³À€8wî4½d¨sUœz~™³$ÙýIJ€vûÍ{X“A¹§@/r¦] Ì< hA@ä÷e^ÑÉ:¾/”°qvì‹E1wÇíyë8ÂmHùÞL°¶†…r¹ÔS1Œ9é¾–naÔ‹¢¤§±‚Îô!ZÈÙó6Bë°F Û+5ºS©B<|?ì—tp ÂoéØ ¨ 1ÝÓm ß¾e”h9öš.¾ïŸ}Á%òÊ$]êé ˆII ,ç¡2S¢_õÔ¥$?×IÕ³“ž°^•()ô¾^O?N°e…ÅC€t7/•‚iïib<ª:Ø*•‚°Ó?;wŸjµæóýŸ1äp6 k¶¡î¶-~*T—ì•Ã03€º(b ×G‰ÊŠà„’ôäˆq„Næh°6›M¬­­u¡…B!Lǯ]»–)ƒ5MæÇ-\Ì„³fÝvç¹§XaxT¹z++F¼¹orX„Ç6í%# „'Ô?›ï–ÉÑê‘ÄÌ«`”çF}ÄÒ¼2d ö y`˜  ND¦9ÇùY@U£óÆóÄ&'.ä‹BfÚ¢*ñÔóÏu…b}_Šôéí@Š^¯<Å$䉣M+je,â9ÿl£¬ˆÁ*~bQt&ëztS‘k0g -9¾ïömRø¥Ñj”¾/6¼(·¾×ÇÕ¨3Ë@ƒ5—ËáÆ]ÏïííÍ{ìIF(ŽãŒ¶è“'s˜—XÀ=ø7ïþËÀf"ßÀ0B“ÊUržô«¸íÛêcø°]f©Hs–xžmÖy–V{êÕš€µo)ÃŒ€héáÃ÷ýlyWÓ Îa Vd@wH-m Qú4#0Jµ ¬¯‡mzUj%ƒ²ßXÇñîE«Á1#ã8@>ß‚eY³ u×uþ˜¹@K¶išÓÕ[\Wè(QY­r¾é3Ð`Íçóh·Ûh4( =Ïk4óºÎ›^k¯ã8Ã/ü6â^Ì~X§Œ0<²\>ù PÛŒ ½=¡þéç‘ÎÐÏY žë(BÊl°®ÉšE¾ïÏÞÃJíe¸èsÆxžpÖëaáFEl{ÄÈ™YC:€ÐÈ’y€i—“z÷õ:Ôj;t¿ëõ~ž—ÞŠ„™;¿ñ‰FcïyOmviYš7ÌJ±±¦¬G ŠM.ˆ´TÜ<è„|>|>ÝÝ]´ÛíÔsÚí6vwwQ(Ïçç}Miv(wuè…Ÿ<«Ãtë1ü‹ë"ìÀqÄ,Ôuà<·û={é-„÷Õ‡0lAÞ_*ŒÄ¬ÉjضmÏÞ»Z©œUæ qÝ0壼D”ë…Á¶…G“ÂnŽ„ÒT*…Ò.Ì0ÄÅ)ÊôÃ25¨?“r³Ì8üò/ÿ5~é—^3ºlŸ§  Í ìÊ0sĶÃÍvª?0¼nž­šÌìªJðÅ‹±µµ…óçÏcss3f”^¹r‡‡‡ÁyYÂ0ÒZ&9£)óe 8¼«_û|±[MäNÞgú…ù WxI9}ðéÊBõJjC5Sj5ÎsbΜR)žz©(¢H-llœÜƒ¢tGhš˜¤N]H ÇíUìˆYI<ÏË_üë¸ÿþë}’eÅ5 ü;:l;,¦dâø¼[‡0+MÔÚ·º»ë†›,¾/úFë%U*gêÒ2”ÁšÏçñè£b»»»]Ç777qáÂ…Ì[z§ ­Ìÿƒ¿Þô3À‡ÿ =×#j4&oâ9°ƒòa©-Î0÷’ dƒ¨ÃæLÂ6V™3Dzz–¦¾Úg^èN"ï57$©·2ÅÞM&Û¶ñÐCÏé}‚i†}p0Ü&-×X×Åù²,6N–©8³pD—MÛ횺êPŠ ä–”4œŠËišoEáÍ¿%c(ƒU€/^¼ˆíím4›Íàù|>Ÿ©¼U‚R†’xž7¼2ïáÔ³jÍ;€ïxððÄ6?íäÐÍ¢ß[ÊsV} n£a8c•a_·gLÅ]²à½bV–d%ì(#Ò›TYUQÆ+FÄ0¨=uÔöü…_ø<ÞûÞïíý"ŠæF1WU!¯¥¯åÌ\0 ñ¯,‡ë¹,‹pàÔvMŢ㇑W’o× ‹°ÁºT m°¹\®oñ¥¬­fMض=šRCÑ[å2PX™GGbæ™&ð}?<êE¡‘ZÁà^©¬û0#lgSžV˜õ¦~| 3'(]©—óÒuÝÙæmû~<'*îreUfJP{2Úü™ŸùKüÝßÝÞ¿êõ¨›4º.”yfÎZB©»uñpO×ÔTÝ|ÔLå²oEá(°%ddƒuQ nQ]ÂuÝѪHz8­ú{*øÑP^Ú 2084:ojàâHÌÌ;˜z9RØ )ç\žÉT‡¨®ëήÿªi†ñÈT¼HôÑ™÷×Â,¶-d¼TòþùÏÿ~äG¦½¦ªaÒ7Ü!¶êäQ5ܲ¬ém²kšp&ñ&âR²´«ëvo"Ú¶=\þ*õ IGªHnø ë -Ufê‹aXMjA´Måtx^wl%=ïºá*®2ÌÇ™^ïÕd(@ÜH8€™1´Ž×j´dÿ~ægNr¿z^ÿ†É(Tï+Šïûpgº›¼!³´,­Áêûñ pÇ=úbE9|?,Z (ÔÌ/lžî!n`&õw*Ž4 l¨23ÀóB9·m;¾Séyb»¾\2M^Ô4i¯¤o†™3Ô÷=MDn* ŒXžGÌ1®|; ´ÇoÁ ×[˜aæÄ$2žÜ‡1M³·¼'K­2Ì0¶Ž‚ÓbKß÷Wøì£â‡>ùÉÞ‘ 3'&‘o×Ü÷?‹×ê |ªÌ0c’ÙàV«]×Ñl6ªªÂ4ÍáßÀ²ðΗ¿úùóâo"w5êK^ÖÓ挘T¾½«ŸÃëÿâÝxèöÏàˆoL™TÆ]7^ŒÆ4MH’”MàûÂÂfz†éäòí8§ù«¿ûÃø¹\?séÒ¼/‰a&ÖÁ?ü·ø©Ï¼ßûíxì?ý§y_³àdÖú³³ƒµµ5¸®‹Ë—/£Ùlbwwwè×ÿý;߉ÿxã†ð®ZÆjš.£C„óÆ&s†L*ßîûŸÅ³wüYðÕ_ÍiL¦˜T¾ÀG?Ч_ú!¼îÇ|Þ—Ã,™4X[­.\¸ÈårØÜÜìßs/ÊåâC_x/þÝKÞ! U ¢ MZj“Ôãy†™Ë7€¼ìÕø‰¿ù6X™L2©Œ»n˜Âçº. Ã@½^ï] ›Ã͘3dRù¶,@]kâKm%IâP`&SLCG©ü³¿ÆþÝ÷ã¿~Ã7°žÂL…L¬×®]äóùà¹|>?t½ÿ5_Šÿö‰¯Â+¾þ¢ ð‚öL=<<œ÷¦ -‚«Î¤ò _ûZ¼ö{¿wÞ—2Ë(Ë6gÇeR/—Mõñ+÷ß#UÅ~ó7C*•€b1|$ûÝde“‡eœ³ã0©|{‡Ä¿øØCøº¿üK<ôc?¶h–Q–m¾ŽË¤òíüÖ_᾿ü%<úoî³,›<,úœÍ¤ÁÚoR´Ûí¯÷}iü%¾ð-_ØÝ¶f Š˜Ëµk×påÊ•ycîL*ßÄ¢ïZ.£<,Ûœ—Ie¼õøãxê%/Áñ8ÿÖ·â¥çϋ߃ ^¨¼lò°Œsv&•ïôoÁ¿à:~ã¿üh Z xeaÙæë¸L*ßkõ[ïøüûßþíy_ÊD,›<,úœÍdÑ¥~âÆÈår]ÏÿÉŸü ÞùÎwâ7ó7q÷Ýw¶¶¶æ})ñÔSO-ü5Dyæ™gðÌ3ÏIüóâSŸú>ýéOãùÏ>¶··ÏüóÇ‘o@ô-ûÖoýVÜqÇxñ‹_Œ‹/žùاIVäašdeÎ^½zó73·ÏŸt ÿ²/û2|¶TB.—Ã;¯\è&»`;ÞY‘‡i‘•9ûÔSO¡Ýnãå/ù\>ùŽ®ß_ð¼çáîoøüìÏþì\Æ? ²" Ó$+ó•Öïw¿ûÝøŽïøŽ3ÿüièàŸ}íkÑ\p%+ò0-²2gIuýΤÁ CH²¶¶–úüßøF¼ñoœ÷Ðf ãÈ7¼ç=ï™÷Ðf(x g–™qä›×ofQàõ›É"™ ¾óÎ;ÄÃZ­V_eža–ofÙag––of™aùf²H& Öµµ5 …X³ã8(‹óÃL Ë7³ì°Œ3Ë Ë7³Ì°|3Yä¦N§Ó™÷ Òh6›ØÚÚÂÚÚÚí6r¹ööözæ÷1Ì"ÁòÍ,;,ãÌ2ÃòÍ,3,ßLÖȬÁ ˆÄoJ. óÃL–ofÙag––of™aùf²D¦ V†a†a†afuÉd+Ã0 Ã0 Ã0 Ã<ç-oyË[æ=ˆe§Ñhছnêûßl6ñ¹Ï}.õx¿cßívžçáE/zÑXcÊâ51ã3‰|Oãø,è'ã‹x=Ìdô“ñE”^ÃbÕÖïAcÊâõ0“Áëwö¯i(:ÌÌx×»ÞÕyÕ«^Õ¹çž{:÷ÜsO硇ê\¿~=8~íÚµÎ<ó›ß<Ô±aŽÏ‚ëׯwÞüæ7ŸùÀtž|òÉ©y×ÄŒÏ$ò=ã³ ŸŒ/âõ0“ÑOÆQx gˆU[¿)‹×ÃL¯ßÙ¿¦QààÑn·±»»‹íím¸®‹Ë—/Ï;;;X[[ Ž7›Íàx¿cß»»»hµZ¸|ù2\×ÅÚÚö÷÷‡S¯‰Iå{ÇgA?_ÄëaÆgŒ/¢<ðΫ¹~S¯‡^¿ãšFbÞó²òÄOtî¹çžØs—.]ê<ôÐCNGìdÜsÏ=±Ý‘w¼ã{ï½·ï±A¯ׯ_ïúÌk×®u.]º4Ô˜²xMÌøL"ßÓ8> úÉø"^3ýd|å×p†Xµõ{И²x=Ìdðúýk•[æm0/+…B®ëÆž»vín¿ýöàÿÏçƒãù|­V«ï±A¯TÚ<ŸÏ£Ùl¢Ýn#ŸÏc{{{¨1eñš˜ñ™D¾§q|ô“ñF£±p×ÃLF?_6ùžÆ˜YƇU[¿)‹×ÃL¯ßÙ¿¦Qaƒõ ØÚÚ „áÑG€¾Bp||ÜóX»ÝîûZjðŸï*¡½»»ìÌL:æy\3>“È÷4ŽÏ‚~2þÊW¾rᮇ™Œ~2¾lòÍkøj±jë÷ ùÎâõ0“Áëwö¯iTnêt:ybYÙÙÙÁáá! …®]»KDLúÖÖÖÖÖ‚¤æ½½=är¹¾Ç½vVÐgÒ.Õ(×3ãL¶˜D¾§q|ô“ñE¼f2úÉø"Ê¯á ±jë÷ 1eñz˜Éàõ;û×4 l°Î˜hÉô´<‰v»ì%÷;6ÌñY0防xMÌøL"ßÓ8> f9'Y¾~2¾ˆòÀk8C¬Úú=èx¯‡™ ^¿³MÃÂ+Ã0 Ã0 Ã0 “I8‡•a†a†a†É$l°2 Ã0 Ã0 Ã0™„ V†a†a†a&“°ÁÊ0 Ã0 Ã0 Ãd6X†a†a†a˜LÂ+Ã0 Ã0 Ã0 “IØ`e†a†a†a2 ¬ Ã0 Ã0 Ã0L&aƒ•a†a†a†É$l°2 Ã0 Ã0 Ã0™„ V†a†a†a&“°ÁÊ0 Ã0 Ã0 Ãd6X†a†a†a˜LÂ+Ã0 Ã0 Ã0 “IØ`e†a†a†a2 ¬ ÃÌ Çqàûþ¼‡Á0gÎ4eß÷}8Ž3ïKb†a˜™À+Ã0s£X,ÂuÝyƒaΜiʾëº(‹ó¾$f…±, žçÍ{ s&°¼Ÿ=l°2 Ã0 Ã0ccÛ6+ðÌÊÀò~öÜ2ï0‚ènM¹\†,Ë]ÇdY†ªªpår€+£P0MÓ (Jð:Ã0 ë:,Ë‚ïûPš¦ï'It]û|†–~ò ¦iÂ÷ýT›–Œ³|3ó`–²_­Vaš&nºé¦Øë|߇iš]¯a˜II“gzζm€ªª1ùT%xŽ×kf‘WÞE dW’$”ËeH’€e{\ØÃš*• LÓxž‡`‚†³m¥R)˜$¦i¢T* ÊÆÆ,Ë Þ—Žû¾ß÷Q*•bah¦iÂ0Œ±Ïg˜aè'ßtœrùzÉ$0¹Œ³|3gͬe¿R©À¶m|⟞÷}Åb1P„fZ ’ç(Qù¤sx½f‰qåýCúÖ×׃ÍFÛ¶c),ÛcÒaæÊÑÑQ@çøø8xNUÕŽ®ëããã®c²,wTU ŽÇjµZG’¤àoZ­ü­(J§\.ëºÞQUuìófýä»Ó2Gÿït„ “ŒM[ÆY¾™³ä,dŸ^_¯×;:''']rÍ0Ó`<«ªÚ©×ëÁ±¤|Ós¼^3‹À$òNë1qrrèít.ËöèpHðœ±mªªÆÂÄêõ:±Ë’<¦i\×…ã8e9V’þv]7ØY¾V’¤ $¡£žÏ0ýè'ß„ªªÁÿ£çÍBÆY¾™³â,d?úz ,äT­Vç}ùÌ’1Œ<'IÊ'Àë5³L"ïôšJ¥MÓ ªj×kY¶G‡ Ö Ó¯åçyAžR”´Ã,",ã̪2®ìS®`¥RÁñññ¼/ƒafåeõz=Hãó}årµZmÞC[hØ`ÍIÃÔqœ ñº—Ѫ( $IŠíÚ$wß& ô’o*Ö –qfÑ9kÙ¯Õjð}¶mE@fZŒ+Ï ³ˆŒ+錄×j5Ôjµ í˜¢(Yš³×¯_‡$IxÛÛÞ6ï¡ ¯ßÙ'KóõêÕ«øùŸÿyäóùye(xýÎ>Yš³ã¬ßKc°¾ìe/Ãk^ólooÏ{(Sckk {{{óÆÔh4¸råJ&~#Ë"q×]w±Y𳋶†óú}²4_·¶¶ÆXxý^²4gÇY¿—Æ`]F–i¢@¡P@¡P˜÷0˜Œ°Œò°ls–™Œe“‡eœ³Ìx,£,,Û|e&cÙäaÑç,ç°2 Ã0 Ã0 Ã0™„ V†a†a†a&“°ÁÊ0 Ã0 Ã0 Ãd6X†a†a†a˜LÂ+Ã0 Ã0 Ã0 “IØ`e†a†a†a2 ¬ Ã0 Ã0 Ã0L&aƒ•a†a†a†É$l°2 Ã0 Ã0 Ã0™„ V†a†a†a&“°ÁÊ0 Ã0 Ã0 Ãd6X†a†a†a˜LÂ+Ã0 Ã0 Ã0 “IØ`e†a†a†a2 ¬ Ã0 Ã0 Ã0L&aƒ•a†a†a†É$l°2 Ã0 Ã0 Ã0™„ Vf&8P*@±FxÌuG{ð}À¶Ï‹+Óü>¶ T*Àwˆ1]½úEóþІa†a†À-É'vwwÑh4Ðl6qᬭ­¡Õja{{{Þce2ˆm‹U$aD’©ëâyÏ‹š¶-Õjøœï‹s%|Î0Äóª*þu]À²Äy’Èrøt>hšxÏcqqŽªµš8§ÑxW®ÌûÛc†a†a¦1ƒuww‡‡‡ØÜÜD»Ýär9ìîî¢ÙlboooÞãe2‚eå²0m[ü«(âßZMüKÈrüo]¯'|_xJéÜjUüKFfôù~èº0N%Iüíyq#•a†a†a˜Å"0X[­ö÷÷±··‡B¡€f³ PUkkk8þ<šÍ&òùü¼ÇÌŒ‰ï‹É –JEäÍ$Ï' ŒÔ¨W4j˜öB’Ä{ÂkZ*‰¿Ëeaüš¦02ÉXIÞUbÔ×3 Ã0 Ã0 “-‚Ök×® …B×Iù|ù|>ðºK£ÑH}¾Ùl¢Õjõ|Ý ãÌxllã0Šeëëq'=Oa¼µš0(MS¼‡ëNÏkiÀÁ0Vap.ŠG´—|,ãÌâÃòÍ,3,ß̲Ã:8³LÖ\.h·ÛÁÿ‰v»x\‡¥Õjakk n¤ÂN«Õ‚®ë1ï­©˜3èøªày¡)I˜KzE‹EáÙ¤0ÙR)îõ$\¨×ÅÿãÏW*âÜz=4dËeVkYÝÞJU¯Æ‹:,4¶E#M¾éy–qfÑaùf––ofÙaœY6+yQ·¶¶bÆi«ÕÂÎÎÖÖÖR½¯IZ­ÇN1Ÿè}\×ÅåË—Ñl6±»»;ôñUA’BÑ÷…W3êñ„¡Íé<8ψ×Qh/o¥ï‹c”oZ¯‹Ïp]ñºz==tXQF)^&úÉ7À2Î,6,ßÌ2ÃòÍ,;¬ƒ3ËJ¬­ÍÞÞr¹Ο?F£ýý}Üwß}hµZCï²4 v=ßjµÐh4p᣻¹¹‰ú©‹mÐñU€<«QƒµZÆ#µp‰­iÐkËåÐpMCUãžXIŽŽÂçVÙ(íG/ùXƙŇå›YfX¾™e‡upfY‰U ÎårØÛÛC³ÙŒU ¥ÐÒææ&677Ñh4°µµB¡€B¡0µªÀý„¾Ýn<>ˆ?ÿó?ÇïÿþïwÝ„²Žë†^S çefËáá!.]ºÔ•¿4)³–ñ§žz [[[== ClmmáêÕ«S}O^Ù¬°»»‹K—.á#ùÈÔÞ“×o&+Ðú=jí˜~ðúÍdÒÁG]¿k>ŸG.—ƒã8ØÜÜœúû ü7O‚Jò²—½ ¯yÍk°½½=õ±Ï ë®w÷*efÇææ&ÖÖÖpåÊ•©¾ï¬eü®»îâ^ÈÌPìííM]qà5œÉ ÛÛÛ8wîÜT×p^¿™¬@ë÷4ÛHòúÍd…quðX•àíímìîîöÜi™DûM¼µµµÇ— ß=GŽ8_tY`g––of™aùf––ofщå°îììö÷÷SOžÄ`½óÎ;ˆ°þèÿ_6LS´acuy`g––of™aùf––ofщU v]·ïc¨-N4Ãq‹Å¡Ž/ä]íQYŸYPXÆ™e†å›ßûy†¸ßQŸði`@±¨àþÏ»¦öž,ßÌ2ÃòÍ,:·$Ÿ8<<„ã8h4€B¡UU§’׺½½­­-4 ´Ûmär9<øàƒC_Ø»º¼°Œ3gë ƒ \î^Gî}^ÚÍœ(•Äñz=}÷˜YQÆ™ùãya‹«O|â¸ýöÛqÿýσëŠõCÓ„gIUŃ֙׿ÞÃg>óyü»'^+I€xûÛg3N–ïÕÀqB¯¨¢Ä{„G ÔRiøâtŽiŠûa²ïxÔûZ* ﬢˆ±¨êÙÜ;Y¾™e†å›YTƒ•š«)®?êÇzíÚµ•LÀ¶,Ñ#•ÚÎxž¸™FŸ³,ñPUq|}=T0ñ/·­a˜Õ$Í „›\¶-þ¦å÷±Ç®à+¿ò pÿý¯…¢Ä7Ê¢†,íöÿ/y‰E9À‹ 3>•Š/ײU«Åï[ä½¢iÂ¥{ÝÆ†Ø˜ígÀêº8¯º. U×ï•4n†a˜Õ¡+‡•âÖ“Ïõk*¼ DoÚ²ÞLËeqCuݸKŠhÚë†Y ¢^ªƒ¡xolˆõ#ê-Н>lûÇsž£xmß÷÷<Š¢@Qض +¹1#BaºÑÜÑryø{Ÿ$z’4œ·5êMõ}ñÑEIßäa†aV Jp¡PÀÚÚ È§­V+hw³ªai7_M Ã~e¸èUÂó<‹ElllÀŸfyH†É8ž'ŒÔõõ°xÔãtp7t=¾vX–…r¹ ×uÎÛ¶¡( 4MƒMnZ†RIl¬a¸ù(¬šnšâÿ½rPÓ 0xÛæT†a¦71«išÐu÷Ýw_줵µ5ìííÍ{¬sÁq–«š¯ïûf|A¶mÃ0 T«Uø¾b±ˆz½>óÏe˜Yãû>*•J`H>ç9áå/ÿV|÷w1TU(Þ†!ø^y}²ÜãŶmÀ÷}8Ž­&Oçʧ†çyÁÿf¾?ÜPò²zÞhÆ.mîòË0 Ãô&f°æóy<þøãh4¸rå àܹs+ëY+—‹„að}µ^%§€eY°, õz=¦8‹Å˜b åÚ÷}(÷ÅL€ëºËã8©ùûQhó¥\.CUËð}ïÿ‡ð3?ó0>ÿù×AU¿š6™òïV]’eŠ¢ô5XÉh¦9U.—aYª¬ù3(=E–ã²IÆå´"t=l;3,ª*^ãyþË0 sÖøþâ8ånN>ÑjµËå°½½íííà¹UE–—§mÛpgä]Ã0°¾¾Ã0…º×yiÆj¹\†®ë¨T*Áûlll T*¡R© R©Ìû«aæˆëºp'ØPjl>® ‘Ç”dÜ:M<÷<ŽãÛ¶±±±óç·áºe ( Þô¦ñáÿ{Ü|ó{Ù¶m;¸&Ó4áP¼åضò陦i}_kÛvÌÈæ°àÅǶ»[¿8ŽðÚ“(Ø6P,wÜö;âºâ8ÕP …IJÂjõ•J¼ÆÂ4ˆ…ZM„É3Ì2bbN2LÖ0ŒÁÅïA÷§³ f°â¾ûîÃîînðÜ#<‚û‡‡g3¢Œáºƒ{Ç-ä…*—Ë0)kHa?::‚,˨T*ØØØ€išñê8*• \×íú«iêõ:ŽŽŽ ªjðÿ£ÓÊ£ãÞL¶ #Ð0Œà÷4FXù<ÏC¥RA½^‡çy±Ù˲‚Ïs]Åb’$áèèõzøÀgñe_öNü³ö–˜Áêº.~äGÞƒG}²W°%IB­VÃÑÑQà^“i𨨨z|Qª¢(©ý"ty_%I‚¢(0 †aà¸_.&s˜¦0"76âÆ¤$‰MSò@ªª¿“ñ÷Ɔ0bé5Š"òH)2ˆ¢„êuñÚõuñ|Vñ’ÄE ™åEQÂve “,+l6 tß: B‚Ûí6vwwqáÂ…À³ {{{ØßßÇÎÎNP˜i•°í°ÅYây<σëº(—ËçÚ¶ MÓ ª*666RÃ-ËB¥RA­VC¹\¼O$ åråržçÁ¶í˜‘©ªêP¡Æ’$u…^Öj5T*”J¥ÓpËþ_v¥R ¾MÓP.—‡ÊÛ#Ï—¢(œO{Æø¾3¼LÓ„$I]aâ¥R)È¥ô~¥R ÕjŠ¢àààÅb1¨˜›v>ypUU ŒP]×£O–eüøoöEù¨ªØ°":Y <‰$IÐ4-5„×ó<˜¦‰õõu(Š\3}'²,gT6ɦkŠz\ÓB¡«Õj07žxâ‰ùþèÌÐ8ޏ×PÁ"Ã[§%Å9ºtU«a%êaRWÊååIqa˜YAë~²ÿð8p11&k¸®¸g Û?»ßûbŽ˜¦ˆ–™%ÁÚl6Ñn·cÆ*qá®dVj\~Vø¾ ‡ @7W iôËå³m;0RUU *‘”{z||ŒR©xO5MëzOY–¡ëúT[hÔj5ضÍIÏ‘¦i$ ¥R ²,£^¯Ÿ¶ÿ°Q,¡it]”ý¨ÁOÅkEªªp]ï}¯áL“wfºÇ1º¡ëzêÆD­VÃÆÆTUí’;òv^¾ÜƇ>´{ïý§a³¡—³T*¯U¾ï^N’‘(¾/~Ç «õFOIëE9²,:.L²,ÞØ¤±«i*• TU…a$)0vÓ6dYŽðƒ<Ûšß7{šŽ#䌔‡QnüóØPe˜e†¢&Á÷ÃþÄÉùÎ0ó„6C'õÛDçÉúúèE÷Få–aO¼qãÆìF1èÄYîFSQ—jµS\É;³±±„Ð&¡Ü¹4¯U2×M×õÀ› Ä %Qx$…øöú¼Y@Þ)26 ×u#ºZ­ãŽz}éû‘e9¨”JÞ*UUcƬ¦i±ÂbÌxX–DqiYVà$tµZm¨ÂH$¿Åb1æý$ïh¹\Æ7~ã7â¶ÛÖ ªùÓ×Ð|Vp||Ë;¥Ï¬V«±9àºâ5´!Õ«wä°=%G!Í Ü+ª€ä¹T*¡V« Œ>`²‡ãyóÙ¹÷Þ{;÷ÜsOçè<ðÀ{î¹§óªW½ªóä“Ov²ÌO<ѹtéÒȯ;8èt4­÷qUí¸ONN:µZ­£ªjG×õçkšÖ©V«N§Ó©×ëUU;år¹ë=ËårGQ”Ž®ëY–g{ ȸò2Ozè¡3ùœããøßº.ž;9¡ÇIG–åÎÑÑQpÎÑÑQç8ù ¨×ãã(—ûÏS1†NG–;Eó¶^œ„ÿ*J÷5.#g%/Óbçd/êu!‹µÚ¼G²¼,š¼,Ú|\vNN„þE×»ŸÓ4qoIãøXÜk’Ç«UqÏJ~^š*¦iâ½'ÕjÎúº;ï¯h$m>f’Ò]¦õ£Ü“êu!ßµZ(§Dš>v|,æP”4JU;ÝÝæÈò’Ú‡Õq4›MÀææ&TU <®Ëíz¥1i)òõõu¨ª;{¡"4T8ˆŠÇ ¢V«¡X,²¬À›• ¤|>Êñ侌̰xžh‰¡ëbWÌ4üÛþó¯?õ¢*Á±YôÒ-Åü¤üŸA9EІr%+Ö‘WV’Â]o†™žzô†™>ã¯å®zˆ¢Ø6ð=ßó1xÞßQ-Š"< i·8 s¤H=*€t‡XRµoÛ=^toKt/—FãWÜ3ﯙ™ä•§<èQ¨TÂô“è{ŒZÍ×0„+J÷\I‹’e!Ï™êºñˆ8× Û³}Ý×]ǨYy·4›Í®PßdHݲA_è üTßßO¥¦i0M3V¡T–宼Êa¡ðÝaB_)Ç“a†Á÷Å‚st$Âk'T¼@U}üäO¾ ßú­¯D¹\†e‰…p𡵆!æ¥ªŠ›8Ìõúh¹?l(0ó€6pxÙe˜Ùáºã¯ñT¿ V÷Ê-ÿzøîï.…qoKkoMs=néyb³·—ú\.‹{½&j¼ÂРÔ[o}vÞ_33'MÓ rϦmüK’ÄmY˜©cÛb^T«Â@¤2å’ûÁ «U—Ëâ凎*’ž'^«ªb¡4ÍÐh&¦XˆšafŠeÅóÖ†™ –% ;º‡ŒRÑ7Ù.Êq€Ë—Ûøð‡€¨R,ƒâªæñ¾/"€Ò<£ýP”07Q–Ãêô„,sÏV&Ü ÇË5V‡}´M™qu¯¨þFÕï Êy•åñ Ö›MÓÄ£>Š|>ÃÃCœ?;;;±~ËF2‘¹×¸—ȻʅR˜EÂó⻽´«çy^ÏÖJš&¡bq´zÃCiaÔõÙ÷ñb˜Y!I\H‰af µ"Ó´°Ê{¿¢1žçÁqœÓÅù¤×‰Öw¼ç=¿†/ù’¯ÂoýÖA=;Í­zJ¥2¾Bíå-Iq“Rq˜Õ†ô*@È„m§;ÐÖ×Ã[ ,²”„Þ£×fõœ'&M‡ô}ছÒ{Ows8`/^Ä£>ŠB¡€F£±ÔÆkÒÔë‡Ç‘iÛöT{”2ÌYP­v/&Tušª0§Q.‡ÒõõðyûÙ4·¨/stÄ}é˜ÅÃuÓdR 'Áê§y3 xW‰j5ÝÈ{ÃÞÛnûCT*8Žƒb±ˆ_ø…ϯ5MÅbñ´_wïyÏ×ó7i°F7RGÜËÆ5,£kD­&º<ÜqÇ} df1(§ã!—åxÝ MKKOöRµ¬tc3éuíuQ˜I²=íÍ—Ô>¬ÑÖf³ Çq°¿¿‹/.eȰªöÿUq’$±w•YH ÃÚ I’˲ppp0°¨’¦uï¦Ñß4*•0G–#Ú™E„ Q²j5,L1%¿R©@Ӵ̤|X–xœ& XVz0…ÙŠs,üÎïÈ8wî•(—ë§÷' ßõ]ßs羕Šß÷qtt”:×H {º‡ÇLs|ï*Ý[-‹BƒÃ–„dXÓ\{òÉ'çýU3#`Ûáfæ0Æ!¥C%—VÊûŒÞOú…ò¾/Æ S'-áT0Éó¦é6‹HÀ`m4( ˆþí8r¹Î;‡íííéúœH\êµøŒZ™Ë4MX–5צ 3TìÁ¶mÕ¬'éš´q9\’YtTA/`ÇIåb\ÜÓ­ñ¨Ò:olÛ†,Ë™³¸˜æhQT )jOú~÷{xž‡JÅÂ_üżãÏ=Ÿÿü+øÿñæ Ú¼¢(øïÿý7Q©T (ÊÀ(8QXÐ:í. E «ýÒg{§.5ròPI’‚^ß÷Q©T‚‹Å þû/à®»|œÞëõ:,ËZʈÆUÀ¶…Ž3¬w’Â|Ó Öa–ÛõõÐ8%gÀ$Ë4¬Y½¥ÙlB×u´Z­Ø S×u¬­­@à]ÝÜÜœ÷x§Æ´ "B,²,÷ܱc˜,㺀ªÚgUÓ4VRB©¨TºÃ¯¨’õ´p]Š¢ÀuÝÌ̽¨B>+|߇çy3iÅL˲àºnÐaø×…­.½Ì0Â. QçB2´Ñ¶m†]×ñü/ÅOþäá™g®¡^¯C’DÆåçYP«I8MÓ°±±jµH²mà7~ã:*•7ÃqœSï«Ïó`ž–Z¥;2\5MƒeYAZïû°, ''?ßå܈¦ÝlmmÍãçeÆ€Ú©êpÞIª4'œl¹E×uäóù`²Â@ÍçóØÛÛC.—Ãþþ>vww—Æ`MzNG<’ϋݡ'¦i7qR0h·n™[1Ë -’¤„0 bg“kíyt]Ý‹ç …/ÒýnVi.äUªRê•™i!‰á1+0¾Ça¨ÕjCÝ7hÇ¢yzáyâžtp "Ȇ£ÜúÑ_Äññ1jµZ׿*…º§iœL-EQp|| I’°±±‘ÚÚY<¯»°ëvç­ÊrÚŽ¾Ç0us’áÀI(ÅbÇéº?™¦‰›nº)D]$|߇išX__G©T ÒÊÒ Öõõu†7nŒ<®[Úívì‰f³‰|>¿tFjÛoÇœ Ò0Ì¢#IbC†nì¶móF Ã@(¥R؇x6Ÿ!nä¤üFCnûå±R¤a6—&É?%C‘ èJ¥³,+¦¸†Ó4‡ò:%Ï£´MÓ`Fðž¾ïŠOÒHbf…Æ[e¤«É+É$)ÝŠ‚ àQ2÷›>†iš¨T*(—Ë(•J¨×ë©÷#Çqº6³Ç νpá^óš×Œô»ÜÜl6Ñl6ˆp`ÇqbÕ‚¡ÀwÞyçHožUÒŒÕd í´ ó“Y$)¾8r80ĽƒfœÜ*üI&aYV`ƒëºey,/%yW ‘#(Z8Žó2éº˲bŸcF×=?ªÄ}@¶š¦¡\.ccccê¡eL:®+î ôÓ 2V¤†ŒaÕRÓìžKŠââŸþÓ÷£X,âŽ;î@±X<õê¿÷{? 899ªªxÎsašjãb½™Õ†<ž$Gž'ª*òT“jRÒ€º«[G‰ö¦„±«ëÃw%IAëp¹\îÚd4M3ˆ˜‰>¢Àpí­Õj¨×ëp]årµZ ²,£V«A’$‹Å¾-%IêZ·ic¶Z­â]ïz¾ök¿v¤ßæ–B¡€­­-lnn¢Ñh Ýn7ªv»+W®`gg…B!¨¼è¤ýØÉèäî{ ˜eÁuÅ¢L›jÑ]/†YE\7ì‹7Í>Á¢åF¥Ë3äyTU ¼HQƒU’¤.#“ ‡££#lll ,‚äû~à‰§˜Zt<@h”PÕÓ(þeš&ªÕj (‘‚DF3ÞK)á¥ô}P&*|S*•¸ÿ î ¾íÛþ¦ùZ(ŠÒe(Ú¶8ª¡jš†J¥ršï)ŒS]ï®zj\×ÁßýÝ{ƒy!:SÔÑl~!Þð†ÿTÏÕê‡?߯˜AAÚ¯¸Qt¹Lþ= i…[“΂I MAMÓÓÖÉR©Ó4!ËòÀ‰b±8älÛ Š‘š¤Z­¢:ÀÂV¥ë>F÷½q¹™ ÑÂ-ÀôÈ#€ªÜ¢@»%I’¿ct‡óWfÑIæø†Á²Í¬4êU­N7 Øó¼.ï›QOjÒz­(ß•òhF1IT´ •¶Ë†ïû0 #ðú&=¬dTS…Ø$dˆ–NC•¨ OÔxÕ4-¨.KŠLÒ³ì8LÓD¹\”+ ž¤€3±a X,âž{Žqtt„ƒƒƒ.%×qÄ=„tѨwœòW I ½«æíû>êõ:>ò‘0íLUUÜq‡‰ZMæ>öÌLéU¥Ú÷» …M årG™f?zêZR,Q*•bóµV«Q-äMC’$Ôjµ ¸Ø,çEýŒË͹\/^Äã?ŽG}4Öºfss?þxÐÞf°íôdhI ˦q+‡3Ë„®‡ ¶aAhì´æW«³i]CFg4ü—zŽ’‡UŒ£Û£iY666Ÿî?ÉB7~›,ŒD-׆Éc%C³X,Â0 H’»ß)ŠxF{ÝE¿J9æS•ŠÈG¤Moò¤¦]3tJ¶I3ÒþçøÀ¦ÿ£­ Žã`ã´ ßÑÑÞõ®×öü©`tFä {©sÈu]T*•À‹UžI4é½Þð†0﯂YrŽ©_(TLiÚ5ÞÊeˆ‡))]Ç©go©Tê*JGQ4ÕjGGG8::Š­§”ÿß+Ç4 µæ¤ûÒ´ ~ÄĤíÑnDŽê•+WçÎ rX—%8Šï§+&² «ïs80³¼„¹÷?dVrJÎ:Œ<©t£v]70ɓ𼉓1›Ö2^gYdY†ã8‡“Ê;’ey`ΫaP%óŠ?JŽ©_…T¾w]躎b±Ûµ§ü*ß÷»)s*þDŸ\×ÅýÑakkk¶?Þ’CmI’pîÜÿMË›÷i¡‹äAM:ÙEÁýÐmxì1ñ7)Ú¶m!ãižÓ ûKrM#f–x^<·Ôó„Ü•Ëa…ÞišÉ²ï ñÿAulÛ>m¡$Ò((ƒî!Ñõ5¹á—¶Á4Šq8‹ê×}A㜴—÷-»»»ØßßžØßßÇ… °½½=õÁg2X£a-Žãpu`fi0 ±hÊ2‚¼#Ž`V* 3KHɈ*¾ïF(žIÃM–å¾Iår9á%ïëÆÆFàÅŒîd÷ó°R%ÇègõJÿ9#–M’¤®{')c¶mw1ý*±’ñKïüÀ ÓéLé—Z=*• <σ®ë§AC½‡Zg$õËhˆ/F¢¹®†7~¾ßB¥b…¹ú*©šê[ì`f õ›'9£¾½–ï˜0m¨ ð {Ò2êõzל¡ZQ¡]´â}ÚÆì¨Ü¼¿¿ÍÍÍ y÷ææ&ö÷÷‘lw³,ôrùSˆ „K–Åγa©y ³ˆØ6õ³‚o†YEÊåÙµ­!hw¹WE` õþB-t]‡,Ë×ÕuÝÔ|بrC»øÅb•J¥o~Ó¬(—˱÷a ¼ßR©UUñu_÷ug:æe‚”ßz½lžœÖY æEZ+`òâ^bša¿W¿ú÷`Y4MÃññq ›ýPÕÑ*¤2̨ø¾÷Ê.Q«MÏX¥ž¤IC’<«–ea}}ØØØ@©TŠ¥vPžÚœI†ÖŠëò3ù- H}Æ'áf@ôÃ!ȳJ­n– jŒDÓÂE³ZÓð¯œÁÚÏÀ§\ŒO~ò³ ±sÁ0£àyÀûÞ÷>ö®2+GÔXA1ÄŸéÇ<¬®ëÂ÷ý™n„’Ò“ôèzžDVðFìjbš&ŠÅ #¾öÛvº!š¬Õ¥ª\‰É.¶F‘M˲`YVѱ±±ª‚ðÞjµÚµ¦V«UÔëõ¡Ó†ÑÇ¢!Á‹w2Me\nZ~ww<òHì¹½½½y_ûÄ$©VÅÎâ'>q„˜óV™åÂó€?û³ßÀ»ßý¯ç=†9SÎÚX˵¤ö5Óºq÷BÓ´ÔªÀÔÞ†[X­&Ôfæ oø¾ø‹ãÇ,+=D>êˆ÷}¡;±ÁÊdE™^ª«Ê[­Vƒõ{Ç4Ït×yEQ‚e‹ ˆÈŸ´JøãpK´à‘Ïçç}3Ã0D˜@ô}~üãÀ»ÐÌÒñÒ—>‚òOnaÙfVŽd;޳ šVBÊÆ¬+s“r•DQȲ¼0J3]¨·®maL©§½4±ˆÎjåË+“E¨ø×¤X–Ó4¡ªjWÞ©ªªsÍý—$)ØŒœF‹˜³‚î}ÓøînY¥~«ý¼«€ØiòýrÑ 3*øÀïpþ³’œ…c1­:/AÊU>k4M㪅նí ìÖ0 ȲܵÎ^ÎÅ`‘d»4&Š£¢’â(Â`U”³iÅœË ãÔxX§¨ïû(‹PUŽã$ÞËYˆõYQض½Æu”iyƒoÙÙÙé)Œ”d¬ë:vvvðøãOåC¯]»†ÍÍÍØEär¹àÿ;;;X[[ã>Šv»óçÏcwwÓÈ·í'“Õª\ß_,a`²Å<å›pÝpgœrëî¿ÿyóþj˜%! 2>,gáŠ6‡§ “É´MÓfZp‰™‹$Û½ ªÀG‘XÉqtFË:ûbeÌìYd÷}ÎîûÃW&cµ\.£\.£T*Å")g]½}Z(Š\Ç*rs«ÕÂÃ?Ü÷¤ . Õj»-“rãÆ äóy …àA!Ç­V FT½8—Ëasss¦åø£îõ´P.†…yË7í<’X[–…où– °íy3̲0oŸ6®ë_ê8N¬‘<Ý3è¾Q«Õ&ÄŒéfd;êñDtÙ8T«\xYd—$!“õúðiT¥– =j3F,ŠÁJ÷™UµQn^[[ŸN‚Ün·§ò¡F€KØÝÝ þÄÎOô3éÿÉüÚqH ûvÅb1rŽ·‚»xÖç=ˆé3/ù&|?ÌÇÄb|÷Ýß9Õ{a–yËø°¸îpʺišAnÓ lÛ†eYÂcÛvÌS!Ë2:Ι_+3E¶ûašf œ{žØÄÞsYN]ÆGq0:ŽÇqbí¾’aÁ‹T·FQ”…)¸4mn¾qãÆ\>˜âçÛí6¶¶¶pxx}'E?ƒùÏÿüÏñû¿ÿûØÚÚêyŽïwïú¾Ïó`Y€ÅÜ…Ç0ZϘÃÃC\ºti¦;§-ßðÔSOÅÞ«Ô¾I’ÄÿEô™]*“A¶¶¶põêÕ™~Æ<ÖðQvŠ»® UUcžÓ~çÖëuT*ø¾x³˜³cww—.]ÂG>ò‘™¼ÿ<×ïI¡ Òc$iøÐI&Ðú=­¨Æ4aýNR© ¿¦a•ìh% ^±}Q¼«D¹\^x…tðQ×ï[Úí6Z­V_/+í¾DcÜÇ¥ÕjáÂ… xðÁƒ÷[[[Ãîî.677ûNˆ7nôÃË^ö2¼æ5¯éc¿±‘þž®ë¢Z­9Gìa=CˆúV†«sEF×0ÑÞéy)çnnnbmm-ÖÂiZÌJ¾à®»î Š"ô½tO]’eàÉ'?Y–ö f–‹½½½™)óZÃÇ ÝtÓM=½ž¤°T«Ulll{žÇqbùBd (ŠMÓ¯ì¢+‹Æöö6Î;7õ5< ë÷$8ð³?{{{¡ÌJ·¤Y4hýžEwŽEZ¿“ŒªÇ˜¦ MÓRuz2Z©Âû¢° ›£ãêà7çóyèºÞSHÛí6vwwc1î“°¶¶†ííí˜ÐÓ$i4}?c’ÒÚ齚¨¡m2¦9†ó²Ú6 »»VBht~€IDATàž!ó’ï(ÑÊŽ¿ó;Ÿ kVZ˜iê#  g+€h…ÈZ­†R©„R©„b±Û¶aG’¿£ÞÔjµ Ïó–B`Y—íAÞ¥?þã?ÆG?úÆ@ž=oüüUf9ɺŒ÷c”~«”¶ ŽB:ÿ"õ4]un¾xñ"Z­Ο?ÃÃà  Õj-mZ­ÖÔvMFWH …%çr9ÜyçÁçƒ<Àý0 ¡À÷Ú@!j¹\F¥RY¨–…ƃ0Be ç1u! Üa©a.݉ÎZ¾Ó ½\Q€¿ýÛÿ I’àyl°2Ó! 2Þ ËŠ+õ¾ø¾Øˆìe°R80€ÀÓªë:ŽQ«Õ`ÆiX½ß>vpp°²—‘,Ë6 *¿÷3ZÊxûÛÃ4/Ëâ°ÛÛÛØÚÚB£Ñ@»ÝF.—Ã>8Öç *6TjGÀœ2†7>É»:ìšR0n g\‰ý¬å;hŒëºÐu•fjdAÆ£xP,ŠÊ‘º*ôõ &¦à†®ë²–,ÞÁ,Y“í(´ùž¶–;Žƒw¿û/°¹ùÿ;o¼øÃY–qËíj’{‹ž×;R€ZÖȲŒz½˲b-ú¡( « Ä-Ñ?¨ÅMòæÞn·Ñl6Q(¦ò¡ÛÛÛØÜÜ &Jò}óù<{ì±`h’ÏÆ»J°wõ ‰ŠXý K¡vй>BÏê*g+ßI’ ûûßÿVH’ÄÍß™©2OObšÂP%'ûS–Åæe‰ð/+eÛ~˜p01Ê0M“CÇV€,ÉvÛ2-ÂÜÃuž*¡~ó7ÿað\¹,ï‡ÕRfZÌKÆÓHê(¶-”j5Œ2HkYCÇ¿™ s¬Y’m‚ŒTßa藍—J%èºÇyi°ÆK’8Îk>Ó‹¬Éxr³Ýó„>CÞÖ´tT˲&ò’³ö3Ùáæy`Öô³±{áXZl ïuôXCž‹ÏuNÇB ¶K Ù °ƒÐ{+Ÿþ½bТï8¾å[ÞÆ•"™¥&-JWÓ„¢#¼Q>$I‚,Ë])£ôàãfžxžØˆ «^‹pHŠH¶ü`c•Y$’ò+Ëbm?:ÿ¦-¿–e±Ñ¹B,µÁ:È]¹rÖ*†/Dd#nTöÃÅh†¡‹áóW¸AÛÏ¥p`Zô$Ì-,x^T«ñP1R²9‡•Y6|_xR{qtO ‰Ù¯a<³ÚDõMþõ¿þ$,ËB­Vë›ãÇ0‹@¯«’”ì8J]1–Þ`í'Ë+W`i”Pàhî lŒf€:‰ó- oHKèÝ_5 õ‡Áúâßz1g¹•U×u!I*lœÃÊ,¦9ܦd4\,UcÛöjmX2 KR—)—Ûöñþû IROeŸa…Q7]*• {WWŒ¥6XÁE—VFa¡¼Ña<ŽþécØÅÃÆðÞL q£’Æ–öZ@²”¹ŒÞÆ­ƒ¸QÞgü·¶nÅG¿ö£#~‰ÙÆuEµTÂ÷}är¹J=Ã,"Š2x#&Z§@UÕ˜Áê8NW›†É"É"wÏůÿú×ÇX”™Ef”:†aÄÚ1«Á-[[[Oj·ÛóçLX©V€~úyL ã²ßš@!¸dtz'å2Bµ”÷.§œÛëgK¶0Rzý©x ׯ\Ÿì;ÍÉßó<Ôjç°µ%òùVeo†Y †QУk¼,ËAH0=Ï- ˜E@QâÞ'Û¶ñÖ·VQ*î™b˜,2¬³Ô÷}ض£££y™9c†ò°Î£"Þ4päU®Tì» a¼ ê 4EM“q;ȰB£6y^¯ŸAC·q«H«ú<ÊÞð¹¹ FÒ(%¥|•ÄœY "-û¢‘e9˜¶m³w•Y$)ZlɃïûPõºxÞ¥è!Ãda—cÃ0 ë:o6® ·ìííÍ{ 3£\î¼RÞU 4òè²û1:úz'cTÆàb Ý^PK2Ì×âý"Ô8í½‹§ÏK‰sjü¯2‹xž0X©bj´àR¹ÌÞUfyð(Â×qœÓȱa ¬0ËÄÍÉðv»F£1ïqMYîo°®Lü;å¯Â0´;Ê×RGhXò\JH7BÓž« w®j²E‹‡Þžc%å}–POµ¬¸­€Êu ˜e¶‡ß÷}?V§@’$8Ž×uW+†Yh¢iѼÆ3‹ µ „iš\hi…é ~ä‘G0L^ë"`Y½«Hºî°ei—¡gUAÿо&âáµ£ôïì¦GžÍ^x)ÿïe8»‰óË}®©š8¦b4ƒ| öQf¥ä›Y)¢Þ¦A¤yX-Ëâp`f¡ ݲ,¨ª ‡”eŽ aYœºäœæø­L¡T¦‹¥®lÛ½=¬É÷¥&Ú›TFƒÕB>K÷bñ×~|©’p/¢ùó&º 0E9@è•%w§2Æw·ø~wøûJÉ7³2PûŽaÓ—’^TEQ8•Y8hƒÆ¶í ˜a–…ry°ÁÊÞUf© VM[ÒVçô1ì¹jÊs½ˆæ{½½‘ÞéyÑseô.Ò¤£¿Í1íâ›»RIw§(§c­(…B¯ªbÕsñÚj5\k [×J%Üý‚àä«¿z:¿ÝI+¸ÁáÀ#âºá6ï ÷ç ƒ“šÞú¾0"kµôüšGôŠ"ª llÝwkÇ ÇãyâG¦×)Jº¡K纮xø>¾ï¯ÿzÞßìÜáyÀ,2®+¦ÿ¯þêO±w•YJzEÍ”J%èºÎõ˜€[.\¸Ðõd¡P˜÷¸fJ´åÇL&¼†e´õÌ s5ˆþ¢5ôµU¼â)ÀøùDY-îaõOß÷¡ÁçºB©þúN|\ÿÏuÀ}¾ølßkRàµHÏG¾ýÀπמv8*ðår¨¬Kî[îû—âoU;¡E¦(á5§%¹#Q.‹±ëøP"†„¢ÇǸÚhà£W®Lÿ7?cÒªë-l8p¿¸ ^gýà`pÕ†^hšx‹ƒKÐJ’87z‡5MñÚz½ÛhÉgݯĵÚv÷5“–:L% :ß4CÃVÓEÁ¯nmáOö‹d úЇÅq.PÃ,4–|Í×|o»Ã½'™¥£×-ßu]H’ÄÆ*ã–íííya&ô«©Ô+TlªTæÒÁmöW,)åðô vsXœ(í2È(´¬PÁŽÆÒ%‹6=ò,ðåÖ_*¼Ñ›ã]4N¨HÀ«?”Þ.V›S庞(S{z=õnUä%aqR­ŠÏ¤$ÍaU-vp!Û&úÕŸ‰|O ­õ.\¸€|>ß3\6s…ŠÆdæ!Áê鯍P«úB ކ´&Ï„q—æ5•$ñø"øâ·æUO/Ò¤(Àѱè‘úÊ>ã£×~ñÿüï/ªoî}=„Q]pð@ÑûŸ+^{´*/ž3!é0ßâ†zÞ ’$ŒÁè\¬V…±˜Œý¬TÂÐÚ´ÐÛ$µÚx!Æ’ÔÛ#Ê, ¶mãèh Ë‚3+ƒªׯ ž·› 3iY/Ü'›éÅÍŽãàüùóh6›ÈårÁíím\¼x…B¹\—/_ž÷X§ÂÔ¼O•ŠLƒlÀ,<=@Üh«TNC!zV_ð1àáŸë]!×ð;NÃ}+Àãê]1t7‚tò—¾t¸62%é ýŸ®½Ž®ª¼ÌôI«¿3•Ö5¸RsÕª0Msp5[Iê6(©xVòµº. ÕryøØÐ¬VcÆÂóÄr9,´!)CÌ0C–?ú£ßÏ^H†™i{Ú¶mst “Ê-;;;PUf¢=C>ŸG¡PÀææ&t]Ç#<‚EÊw¥âšI&ö®RUP*Ï-ÒâAx«§çYfóüL]áŸ}ÀÏ…|uPß”2pÏ«$‰÷ó<ÀýêtRÂ`Ã’Æ™D¡½Ãèä]f΄™\²,ñTáÆ0Ò·HeYÈ(UÏõ<1úåsFI;gBœ™™@àÃbÛ6·ÿÈ:–%îyE6 šçT›ÀÝׯãc¯zÕ¼¯d&˜¦P/\×eå} Â“¾/~¸Aëɱ,w§œœÎûŸ~zÞW5SÒêrí%Á÷C§¥h%xþýÑÈ­%oi·Ûxøá‡ûžôðÃã¾ûîÃææ&ÖÖÖæýU E¯5~¬‚4ë8 oõ…‘Iùjžþ ˆ0Xa©¦Õ£tãQ–oøwÀÿ}›;¨Ê©‚и¤Ò°i!Ä„9±ý é0‘¬ûe²£L¼!cšâfÚ/ì6ºiÓëJ:4ŒxŽ*ÃŒˆãŒV‡Ê¶m¯Hѵ©ãœÞ¢ ·ë†•Ýi.G¡4€^¨j÷¨ªñ›´m‡ùë½6µ #Ü–e\m4ð©%¨ôž)ógÖÑ`!’Z~â”Vð‘d˜dÜ÷{ߣòîyq#U’ÂŽ Q*•°v‚ë†Å'ÒÞÿT¿üýïÿ~¼fÞßáŒðO³ä’zºa¼A3+hmΉA…!GœGN {^<ÑV|€ø¡£m&OÉ]¹‚/Q'¼emm­Ë¥0`‚Ž_»vma Ö^ŒìòN.Ù7^ í%/+-Pe?ñ€õÛ¡W•BÙÒŒ¾/úN`€úºð¹ D˘4’ÃNÊš‘›:L®ºÙ]ÒòWdž¼ýŒUÛ‹Sµ:8/YQFëCÂ0)ô+ —d)½«TlŒ”ã(t"e™p]aÒqM •Žh´CZ`Ò& ªŒ¬OÐû§ýHic¦qGÑ4ñ>Ô"*-^–ÉK®×ß÷–ßÓD ªËå*×Qù"E:í5Å¢øW’â­¾€ô÷º7I,«w«²qjhšØäÕõ°‚ý€EíÙ[o=ÃâìI:–)ÊséóWÇ©­AD{­'ß/M†Éa„ó7n’$#_È)ÑoýSÏ{ê~×GÜp¼åÆ]Oîíí÷efˆJ%¼FqÝ+îE+ñ¦5½Œ¾—à|A|‘£pÚ$½ŒË´jòð20 â 2Ìd–d\`‚‚KÑ0àä¢Dí‘(ì©^go)“I,ËÊv èn5µ5’eñy1“»ÞÑVJɹM¯I¶ýRàä$4L3|Ÿ~÷¿q”ñ~ëÍ(ëÄ ‚g+äy‘eÀ²œåò®Rá< lq„ÊpòZ)yžw"U&IáN“¯~Êó°ß'ÉZ±wRŒ‹ª†GC«ËN²;œëº°,k¹ åÑF]RŸ¢útŸ¢{õlOs”Jñu>j‹ô2$Çé\ñn·´Ûm4  …ž'5 ˆy]³u¤˜Â9È ê¸]¡O}ÎOÓ«Ò X éÆªÚ[‡(Þ âË,i÷бrž¨êÑQoÊúºíeº¡0™‡îÑÃ`YdY>;«ëv{ÉóC7 ¤ ­r]±D;äi¡³@zï_‚zZ÷‚Ú?eX aB,KˆŽ®/@þ*µKó §yïɃ@ó&­þAYžo„Î(þ†#Ž`ÛâÝ“ó}¥R ‹W(Ï0„L“çÓ¶ãrŸÖzjÐØvxŸè¡} ƒ[òùïå@äÃRÿÓ~C„ €sRW J±‚èU:›N&£ kß™¦ MÓ¦›óçyB‰qœôÍž,{¿˜…ƒÒ8E„øæ¯nl„•1¨ø n¹,”™ènŒ‰¸‘šìy ˆszE"$#T…0pÍÜv†™® ©Ñ–T¸Å0·®a˜Œ`Ûýƒh#²«ò;É9¶|±íxÔLœcĘ̂÷É÷ýÑóW“½A©Ÿmš[ «Fó† sÐþxZ8ðX•)zŒ"a$)ô &õEzP¥2xýg2Í-“¿EöHö0w]ŽãÄ'†euçfP=ͪhX½Ñ#5-gpÐæ¾‚ÐS;ÌÆÎj’c†€Zq‘¾áœî¤«¡ÖÓú¨ë¢ÚïÁï¤3 Á mÊ]íB’ª׎#æB¯*Ø 3g|?ìeÞ‹’vuHy'9__OWâ“¥Zf†ø~÷Æ#mÊŒT˜¼¨–¶ æõ\)})XJƒ5ÙÒÆ0 T“³Å¶»c*û)ñT‘7É0) DûNd¦µì"ºÂ"-+½¢ÝÑÑbUidVšAû*=wè£s½¦LƉ.ÕŽãôq§6Hªš^Á69aÒŒÒ^î.†™Ѷ¡U RzxÓ}%¹yÞ˜5©½ùløæ7õ¡Ð+JÈVÊ] Ür†™*Ž®×îiHA—Œ§Ý ØXeËê.,?nAUÕÅëÝÇ0¨m/‘ìûaÞ Þ»Q¨úo”^a 3#’©Ô”Ê‘j°ú¾XüÓ T«âÁÆêJ²ô«mÛÝ»•–<²î1D¾©ôž¨ÑâI.†‡ç3ehÍî*\@Z>/êÌC- {aÛöô v0Ìœ .@p`Ç [ÏLnlF«;1ÌŒ±íî:w=ÃÞ CÈ:åa3L„¥ ŽF€¥ö3;ꈪ¾6ÒóO+¹¦É{2X5ˆJ<Ÿ˜9A©Jžçuéå]e˜Âu{·¦œí˜'*™ØÍ0 B´:°¦i¨4M±Ð“¡:it ¨¡÷d˜3@’ºÕ˲P(ð}QÁWU¹Ç/Ó“¥4X‰ž¥áÝ¢ø·„nƒÕ„0FÓ61ˆv3«Ì\¡Ÿ:Žþ+¾ç5¸éþ·O†ÿzþ<Ûµ¢bQôLÈ8Ë&Ë8gÇaRùþ·üG|ì{¾g¡[’-£,,Û|—IåûÖ=Ž¿úÃK¸íÒ¥…6V—M}Îf2‡µß¤h·ÛÈår]Ï_¹r¿ök¿†ßüÍßÄÝwß <@ûôàÅy_Ñx\½zu©&Ìõë×Ñn·ƒœˆyñ©O} ŸúÔ§pÛm·a{{ûÌ?ù€øÃøÖoýVÜqÇxñ‹_Œý—¬ÈÃ4ÉÊœ½zõ*žy晹}þ¤køk^ðüã'ŸÄ|ä#øó½ÏÞzküä/üB|æ¿þW|惜Û5CVäaZdeÎ>õÔS¸~ý:^ò’—,Ì]¿oºýv¼èsŸ[hÙÈŠ,L“¬ÌWZ¿ßýîwã;¾ã;Îüó']¿¿ì˾ Ÿ½ÿ~ä._ÆåË—Ï|üÓ"+ò0-²2gIuýΤÁÚn·{»qãFêdyðÁ±¹¹‰µµµyj4›ÍØ×¢Ón·qãÆLüF4–y}v/zÉ7üâ/þ"ËCÆÉÒœçM‰×pA–äadiÎ.ÚÎëwöÉÒ|çXxýdI¦A–æì8ëw& Ö~Òë‹Îår=ýEe™& ­ßhžcG¾½nÉ’÷¹ÔãýŽ s|´Ûmxž‡½èEc)‹×ÄŒÏ$ò=ã³ ŸŒ/âõ0“ÑOÆQx gˆU[¿)‹×ÃL¯ßÙ¿¦¡è03ã]ïzWçU¯zUçž{îéÜsÏ=‡z¨sýúõàøµk×:<ð@püÍo~óPdž9> ®_¿Þyó›ß|æ<ÐyòÉ'§6æy\3>“È÷4ŽÏ‚~2¾ˆ×ÃLF?_Dyà5œ!Vmý4¦,^3¼~gÿšF!“U‚—v»ÝÝ]looÃu]\¾|9xŽØÙÙÁÚÚZp¼ÙlÇûæø,ØÝÝE«ÕÂåË—áº.ÖÖÖ°¿¿?ô˜²xMÌxL*ßÓ8> úÉø"^3>ƒd|å×pXÍõ{И²x=Ìøðú½×4󶘗•'žx¢sÏ=÷Äž»téR硇êt:b'ãž{î‰í޼ãïèÜ{ï½} zí¬¸~ýz×g^»v­séÒ¥¡Æ”ÅkbÆgùžÆñYÐOÆñz˜Éè'ã‹(¼†3Ī­ßƒÆ”Åëa&ƒ×ïì_Ó¨Ü2oƒyY) p]7öܵk×pûí·ÿ€|>ÏçóhµZ} zí¬ Jqù|Ífívù|ÛÛÛC)‹×ÄŒÏ$ò=ã³ ŸŒ7…»f2úÉø²É÷4ÆÌ2¾8¬Úú=hLY¼f2xýÎþ5 ¬gÀÖÖV >ú(ô‚ãããžÇÚívß×R¿¬isãÆ®k¹qãööö õ0cžÇ51ÓaTùΪ<ô“ñE¼fz$eÜqœžçfUx gÒX…õ{|gQçb¦¯ßÙ¼¦QáÖ3àÁÄ… <ò!½øÌg>ÓóØ7ú¾–„zÚDwwüq<þøãØÜÜÄÖÖÖÀëfÌó¸&f:Œ*ßY•‡~2¾ˆ×ÃL¤Œ/¢<ðΤ± ë÷ kÊ¢ÎÅL^¿³yM£ÂëP(°¹¹‰‡~8HŽºÝÓÎïÅÚÚZß×®­­ÍäÎ;Aø v»F£1pL“g²Ë¨òUyè'ã7ÝtÓÂ]3=’2¾lòÍkøê² ë÷ ù΢ÎÅL^¿³yM£ÂëŒØÝÝ v>Ê€;ï¼@<ô¦Õjamm­ï±A¯ýÂr¹ÜÄcžÇ51ã3‰|Oãø,è'ã/ùËîz˜Éè'ãË&ß¼†¯«¶~’ï,^3¼~gÿšF… ÖqîÜ94ÀŽã?þÚÚ …cÇ‹Åbßcƒ^;+òù|W íÝÝÝ`gfÒ1Ï㚘ñ™D¾§q|ô“ñW¾ò• w=Ìdô“ñe“o^ÃW‹U[¿Éw¯‡™ ^¿³M£rS§ÓéÌ{ËÊÎÎQ(píÚµX‚4 bÒ·¶¶°¶¶$5ïíí!—Ëõ=6èµ³‚>“v©F¹žig²Å$ò=ã³ ŸŒ/âõ0“ÑOÆQx gˆU[¿)‹×ÃL¯ßÙ¿¦Q`ƒuÆDK¦§åI´Ûí`(y¼ß±aŽÏ‚IÇ”ÅkbÆgùžÆñY0Ë9Éò½xô“ñE”^ÃbÕÖïAdzx=Ìdðúýk6X†a†a†a˜LÂ9¬ Ã0 Ã0 Ã0L&aƒ•a†a†a†É$l°2 Ã0 Ã0 Ã0™„ V†a†a†a&“°ÁÊ0 Ã0 Ã0 Ãd6X†a†a†a˜LÂ+Ã0 Ã0 Ã0 “IØ`e†a†a†a2 ¬ Ã0 Ã0 Ã0L&aƒ•a†a†a†É$l°2 Ã0 Ã0 Ã0™„ V†a†a†a&“°ÁÊ0 Ã0 Ã0 Ãd6X†a†a†a˜LÂ+Ã0 Ã0 Ã0 “IØ`e†a†a†a2 ¬ ÃÌ Çqàûþ¼‡Á0gÎ4eß÷}8Ž3ïKb†a˜™À+Ã0s£X,ÂuÝyƒaΜiʾëº(‹ó¾$f…±, žçÍ{ s&°¼Ÿ=l°2 Ã0 Ã0ccÛ6+ðÌÊÀò~öÜ2ï¬:žçÁ²¬®çËå2dYîäȲ UUá8Êå2VF¡`š¦AQ”à= À®ë°, ¾ïCQhš¼Ÿ$IÐu}ìófÃÈ7˜¦ ß÷SelZ2ÎòÍœ%g!ûÕj¦i⦛nнÎ÷}˜¦Ùõ†—~òì8<σmÛUUcò©(Jðë$Ì"0©¼+ŠÈ­$I(—Ë$ Ëõ¸°‡uÎø¾×uƒ‡ã8Á6M€ØÑ)•JÁ$1M¥R)xŸØ£ã¾ïÃ÷}”J¥Xšiš0 cìófƒä*•Jðw/™¤÷šDÆY¾™³ä,d¿R©À¶m|⟈}n±X !†™ÃÈs”¨|’'ŠufQ˜DÞ?ô¡a}}=Øl´m;–²Ár=&&3œœœtEéèºÞét:ããã€ÎññqpŽ,ËUUƒcGGGÁ±Z­Ö‘$)ø@§V«+ŠÒ)—ËÁߺ®wTUû|†…¤|w:Bæ¢×jµ@Ʀ-ã,ß̼˜•ìÓëëõz@ð9Q¹f˜i“&ϪªvêõzðwR¾é9ÖI˜EcTy§õ8úzÒÛé\–ëÑak†¨T*eÕj€Ø•QU5>¦i*&ËrP2úw´Gôµ’$! ½õ|†–¤|ªªÿÊß,dœå›™³’ýèë°Ý'fô’ç$IùX'aQåd¶R©ÀqH’„z½“e–ëÑáÖŒ`<ÏC½^žë×òÀó¼ O)JÚ ‚aæMš|‚eœYÎRö)W°R©àøøxÞ—Î,!ãÈ3Ã,*ãÈ»,˨×ëAŸïû(—˨Õj󾜅† Ö `Y,ËB½^í²H’ÔÓhU%ص!h÷ó–˜,ÑK¾Á2Î,:g-ûµZ ¾ïöí ÃL‹qå™a‘qå 'Õj5Ôjµ í˜¢(AÁTft8$xθ®‹J¥‚ƒƒƒ.EDÓ´ Ù ÝPU5ö7&}3LVè'߃`g™yɾ$IAµJn»ÀL‹aä¹_TÃ,“È{Ô³ +oðL¬s†*þ‹EÜtÓMÁÃ0 ȲŒZ­†b±ˆb±ˆ $Œ”Ã0°±±T<88˜÷%1L@?ùË8³ÈÌSö5Mƒ¦i¼¹ÃLAò,I ÃHmÂ0‹Æ$òN-lÖ××Q,±¾¾Y–¹¶À„ÜÔét:󓅀ɲôa¥>M¤¸D‹pPÃ,,ã̪²Ï, Q}%ZP†a–‘aä¢#%Iâ4¦)Àk†ñ<ëëë8::‚¢(ð<Åbº®s<Ã0 Ã0 Ã0K]Ê0Ñ`ß÷!IÊå2« Ã0 Ã0 ììae†a†a†a2ÉÒxXß÷¾÷á7~ã7ð_ñóÊÔX¶öO?ý4ž~úéLüFO?ý4>ÿùÏã'ò'ç=”¡ùÁüA¼â¯˜÷0¦F–äaZdiκ®‹ýýýychx Ï>Yš³O?ý4n¿ývüðÿð¼‡2¼~gŸ,ÍW×u±³³ƒµµµye(xýÎ>Yš³ã¬ßKc°þýßÿ=ž÷¼çáܹsóÊÔxâ‰'–êz®^½ŠÏ~ö³™¸¦«W¯âÏþìÏæ=Œ‘¸qãF&¾»i‘%y˜Yš³O<ñļ‡0¼†gŸ,ÍÙ«W¯¢ÕjÍ{CÃëwöÉÒ|}â‰'pûí·Ï{CÃëwöÉÒœgý^ƒõ¶Ûn×|É— P(Ì{(Sãõ¯ýR]ÏwÞ‰»ï¾;3×Ôn·ç=„‘ø¢/ú¢Ì|wÓ kò0 ²4gŸÿüçÏ{#ÁkxöÉÚœ]¤5œ×ïì“¥ùúüç?¹\nÞÃ^¿³OÖæì¨ë÷\û°¶Ûm4›ÍžÇ›ÍæBí N›ÍÍÍyaª¬­­ef¢œ,ßýYFyX¶9;–ñþ,›<,ãœíËv–Q–m¾‚e¼?Ë&‹>gçâam·ÛØÙÙ zåóy\¼xù|Ðjµ ëz0‘TU…išóþ®f(X¾™e‡eœYVX¶™e‡eœYDæâaÝÝÝE«ÕÂåË—áº.ÖÖÖbÅA(ÑÜu]\¾|Íf»»»óþ®f(X¾™e‡eœYVX¶™e‡eœYDÎÜ`m·Û8<<ÄÅ‹ƒøü‡~wÞy'±³Óh4páÂ@.—Ãææ&êõú¼¿+†Ë7³ì°Œ3Ë Ë6³ì°Œ3‹Ê™‡SˆA>ŸG³ÙD»ÝF>ŸÇöö6àÚµkÁq"ŸÏ¯t=³8°|3ËË8³¬°l3ËË8³¨œ¹ÁzãÆ ÀÖÖV01nܸ½½½“¢Ýn÷¬šöì³Ïâãÿ8ÆB'3³§ÕjáêÕ«xúé§§þÞ³’oxæ™gÐh4pçw.Lo6f>4 \¿~}&ïÍk83ošÍ&®^½Èâ´àõ›É´~’©qàõ›™7¤ƒº~ŸyHptwçñÇÇã?ŽÍÍMlmmè_æ¸ßÅ=ûì³øÄ'>+W®œõ%1 Ƶk×ff°ÎJ¾¡ð\¹r%¸É0L/®\¹2³–¼†3ófV+¯ßL õ{Úò ðúÍÌÒÁ3o°RÃZ ?€|ívF#†¤ß®ä _øB(Š{_†I£P(àþûïÇW|ÅWLý½g%ßðâ¿ÛÛÛ¼{É d{{wÝu×LÞ›×pfÞlnnâþûïÇ—|É—Lõ}yýf²­ß³ðÄóúÍÌÒÁG]¿ÏÜ`íÞËåb‰ßD«Õâf!`ùf––qfYaÙf––qfQ9sƒ5ŸÏw•ÐÞÝÝÅÚÚZp¬P(àðð08î8ŠÅ⼿+†Ë7³ì°Œ3Ë Ë6³ì°Œ3‹Ê™]Ó4±µµLJø&¶··±µµ…F£$y?øàƒóþ®f(X¾™e‡eœYVX¶™e‡eœYDæb°æóy<öØcAòw2§cÐq†É2,ß̲Ã2Î,+,Û̲Ã2Î,"s1X+ßo :Î0Y†å›YvXÆ™e…e›YvXÆ™EãÌsX†a†a†afØ`e†a†a†a2 ¬ Ã0 Ã0 Ã0L&™[+à ‹ï®þ­(€$‰ÿ;`Û@­6ïQ2 Ã0 Ã0 3mØÃÊLÇ C<G<çyás€00-kð{y°¾”Jâ5Ž#¥RøzU φa>—a†a†a˜lÀÖÇóYN?満iš&½ð}ñ¯i ƒR×…”ÞW’„aI«*°±!<¥Š¯bQŸ‡išó¾ž•$<.ª t:½Ûf†a†a†afŒl°ær9ìíí¡Ùl¡Á¹\Ž -Í‘ƒƒ³û¬IÃŽ†a†a†a†e¤ÖF£EQÐn·‘ÏçQ(P(ØX€ëŠ6+ëë¢Úî°ø¾Ñe†a†a†YEF2Xóùà Ã0«ÇH!Á­V ûûû0MjÂͧª*¶¶¶vUˆæ—ÃÝL¥w¥`ÏJ@šw6ùYÓÆ²,§ÛÜzÒjf˜Äu]”J%ÔjµØšåy À뺨QÜá˜×V:´Úˆ“ÔuÝà!Iª’Ü}߇eYð}¿ë\ÿ4tCêÞÁ0C`ÛÂ3ªë¡ñzt“¾/ŒYß½¢ôwµ*î‰ÑûbµÊ†a˜ÑÉÃzíÚ5è2VýXéœUaœœRIêJE¹;IJ%ñY³ô®Z–…£££@f˜EÆ÷}”J%t­Y²,ãààPI‹Wà8*• lÛî9ŠÅ"\×ÅÑÑ`¼q’–ea}}ÅbÅb¦iÂ÷}hšß÷»Æã8 Àa¨T*Ø8uMÙ¶ÝõY¥R ¥R ëëëxâ‰'æý0§TŠßo(Ì·Z^O×÷«~{:’$Î5Mñúõua¬òž'Ã0 3-ÆÊam·Û©Ïõju³¬øþx!ºTý7^ï'ËâùiyXlj)áŽã@’$(Š]×{*ñQÒ”s˲°±±ÑUœË4Í¡ v†;î¸#PèIY¥ÿo¯s¹‡ðjàû>ŠÅ"t]‡Òg‚’w5MÞmÛ†$Ip]]!ĦiBQ@’$ȲŒjµŠR©ß÷áyljɽeYÁÆP½^G½^ÇÁÁt]‡ªªÁxJ¥ ÃÀÆÆF0UU¡iŽ¡ë:ÊårlL4ëõ:ޱ¾¾>ïŸÉ0âKF«m‹É*Ë÷O“$‘º"IÂ[­ö®áÀ0 Ã0£2RHp¡PÀÚÚ ÃÀÅ‹ƒÐßV«…K—.ç¬ “„èö²Ý\ð<·KÉžf•mÛ0 ’$¡^¯C’$ض„—Ëeض ˲PîQÒ˜Â)K¥RðŽãÀ²,èºx¶dYF©T‚$IÁ±rŸ2ÉŽãÀqœœ6ªu]7PþiÜô¾€0LlÛ†ëºp'ö¼¢(±pÏJ¥¼ß7}Ó7ç2g‹çyðÇFW®\œ;wn¥<«D­6~Ø“¢ˆ\!rèø¾þÏ߆/þâsøã?>†ã8(‹(—Ë Q®^­VƒçyØØØ€¦i°mÕjªªá…¾ïÊr¹xƒ’Å[(ÇÏ÷ý ‡$Ó4Q¯×/çy(‹¨ÕjwLQ”àòZɲŒz½Ž ¨ªÚåá$Q?›ªª8::‚išC…{V*‹ÅÀ[ˆ‚4÷ß ¿Ìt1Mår¹Ë3õÓïæy$I Ε$ Åb±Ë³H^ÓjµšZ$©Z­þz½>²÷¼\.c}}=˜äµ¢ª*TUE±X ^3,Ò;m4M ¼Í£{bVÇy§ ÃŒéF®ë¶m(ФYiš6Òýa˜!Ç2¾víZÌ›úÄOt®]»¶pÖzV899é(ŠÒyå+ÿ['ê´999騪x{¡iZàAít„'3êi%êõzê`µZÊóS¯×;š¦uºŽ²³X­Vcã¥÷VÓÜÎS ͳµˆò’µ×z½Þ©V«A$y 5Mëò”’'~˜¨:—¼æ4?Òänü±‹‰¨—I×õÀs›ôVFÑ4mª;é“"Ërªg:kò2ˆEœ“ÌüX4yY´ùȤCz™¢(]×»îKÇÇÇr¹ÜQ%¸êº<úÝÇèuõz}áäeÑæ##"D§ô54gâa=<<ÄÎÎ …ööö<ò.^¼ˆÍÍÍyÛàg‚ëŠÇ46ÑÈ“ |},ˆrL+• *•J—gÉ÷ý 5ê ¢â/Izyx†maC¦4åF¡Ü»èçÚ¶=³ÉYx¶Vß÷aš&Ǫª¨T*§4êѯT*Aå\Çqænår²,ò,T*H’„r¹ÜÓƒhÛa+¨AbH-8GDHÐùÅ"P«•ƒâKý¼•T]8+躴Äa˜^D[Í0 “ŽeYA=ªC][+• TUí©7ɲÓÕ¨n€XÄZ´Èžã/xÁõ ÍšaøøÇ?>﯂Yb,KÜúëM†öÀž&7nÜ‚gŸ½u¤×Œd°¶ÛmìîîâÂ… ØÞÞžßÛÛÃþþ~`ÈŽÚ‡µÙl"ŸÏ§>ŸËå2Ùו”ä^X–"œ+ÏópÓMEœœÜß‹_?c-Úª( TU…ã8°mš¦-\ÏTªFìºnFã8ÎÄý0³Ê"ÊwT‹ä.Yp(JµZE¥RÁúúzÆ= ´9ây^P@+}LbÑUUb¯ié…Ð #ì}¬ªñž’…›¦™9£´Y=[_Ò*Í{·š–íå‚ÚFõ7Ú„µm;¨Æî8ÞñŽWàêÕ8Ž(¸gšfÌAàûbnõSø£÷.q7¨b±Çq`š*|¸~ÝÇúúéT¯}íkÏì;a_-LSØ0GGa¾^j„¢ˆ9“f°ú~ø¨TÄfhÚyž'ŽkšøÏ.\øjÜÿS#{$ƒµÙl¢ÝnÇŒUâÂ… 8<<ĵk×FîÝÝ]4›ÍÀ[ ˆªÃº®£ÙlÊ«I5ø3B¹Üm°R Ó4ƒ8ʽó}?–Çö¡ýW|øÃŠïù)ð†ú~o#¸V«ÁuÝ .-¬WEUÕ ïƒr—‘E•oÂuÝ`óEUÕàf:LŽh­V ^7.ÉωÎZ$Óv+•°Ÿ¤¢ ö*Q>åh1°ê,ºŒgj73ŒgÔ¶ÅæL4Ú Vµس::,ÛËy9ÿꯞ‹­­sxÁ nÆcÝ Yë#”Ëå˜N%Ë*løÎï|J¥o ŒXª…áû"2Ç÷…â?H;-}ÌG]×qáÂgñº×‰çÖ׿ {{â½+àÓŸþá3ùnXÆWßm̨w6E¦™¦0&£º•a¹ì儜ªª°‡j5ñ7µàTq?Òõ°EuG‘eà]ïú ®\™¡Á:ˆ7nŒt~£ÑÀþþ~WÁ¦¬­­áÑGE»ÝÆùóç±»»›j(Ï‹¨MÅdE ‘¢­(Êcì{ˆ’Üó½ –Ë@´ÈMô&°L,¢|“Õ÷ý Ì´\.íýžv8öƆXu=\dÓ¦Dµ:xç;r¹¼4sì,XD_$Hq„ÜÚ'²¬pǶÃ磽|³ µ‹¢MYI’‚ðLêw|V°l/6¾ïò,ض„÷~ðƒçð¥_zŸúÔïâûß~ßýÝxÿû.V°,qŸ)—_ ß…kµ$I ŒUòõº×Øv¨ÀGUáÕRqë­4Í9õú*ÞX­ßõ]Ÿ™ùwÄ2¾†¡Au=O¤GGáF'Ý7'ô‚&ß'©ÞÑ=gŠzfE|®ëŠÏ²,aÌFûzOÚIòæQN¦pß´Ûíàùv»H +H£ÝnqüQZ­.\¸ÈårØÜÜÌœAcYâ_Ê#=::ÂÁÁªÕêØý=3®KLUUQ*•ºrD–E•ïJ¥EQ‚ßz½ž‰ê³4ß’;Ù½¼FÃä³&ߟvÿØ`ŽE•ñ,@Jî hSF×ãh¡üŠ£;ã¶mF`–‰ö§õçøøš¦ùågËöb‘&Ú†a]H7{Ï{6ñîw¿ÇÇUüâ/žà±ÇÀ¿ý·ÿ½kÍ÷}ñž¤Œ»®M«ž¦2…Æj¹Fñt¾˜¿½ÔAaÄÊA(rÔ±!IÀW~åÌô;c_ è>1È> ï)¥}Ðù47hÓ$MSÕP¯"c5jÄz°¾Þýº´EÏL§ÆO”‘ V@äw5 ¼úÕ¯Æùóçqþüy¼úÕ¯†ã8ØÛÛC.—ê}vvv°¹¹‰;ï¼3öüµk×Ä ß|>V«5Ý+ ‹ åZ±Œcp•Jáÿ£;«…/c8ð"Ê·aÐ4 š¦ÍÕC¡¾–æWÐ|“¤pžL3ÄÑóÒ•žEÅu÷½ïûfú‹(ãgewÜ!ä˜ ïL±™iL /ÏàüÓ¤' ¥“œÅb¥è n(ªC×õ®û)Ý#Î*,‘e{úP!¾I°m»KŽM³{.Q­4‰Öùóyøþxå+Ÿw:>ñ^ôžÉ[ )òT¸,©¶Dç¸aô–$ •žßISgÆe|¾ll„ñý tŽ^&Ý'J%!“dJR\N%©¿‡Ó²ÂZI+E 8Ž˜góùά­V+ˆcÂ>¬¦i¢P( P(àâÅ‹xì±Ç†ö®¢Õj¥†ô›Q¯n’gŸ}ÿøÇÑh4Æþ2ízÛ¶ Ó4Q*•ðÑþ=<Ï zŽ%ì»n|±[4MCµZ=sV«ÕÂÕ«WñôÓOÏäýg!ßðÌ3Ï ÑhÌäÆáû>lÛÎD/à ¤ç‰…qP¨ü4PÕ噃¦ |çw~/}éûgöY]ó„e…!ºQeƒŒPÊùé%w’ÔýÚa¼²I(¤ÖëóbÛ¶ƒZ “ ç5†-ƒ(T8¨ø õn6›¸zõêÈiHðˆëwÖ¡0ïI¼üžçÁ0 ”J¥Àhu]±™Y­Æ#*•J—^Fu ’ÐüÒõxxoôVHyzôÿ¤mIWéÿ®Û­ô÷B×õ®”›F£ëׯ”©qáõ{¾îßo:P/aYÝç—JâÇ E©T*ØØØz]·íÞ›žš&d¼T^¶{A:ø¨ë÷PÖýýý †=š„½½½íímlnníYmµZØßßÇÅ‹S÷›ý.îÙgŸÅ'>ñ \¹reì/±T꯴:Žä:|êSÿ3uQÊ3ô¹ËÌ< ¤k×®ÍÌ`•|Bá¹råJ°:)ÑêI"¦M­&”…j8> +SPÎ{ÃǶ·Ám·}`&Ÿå5<+¼þõ? Ó7RnIY&Å‚”àb1TD(ÜвÒwÄ‹Åt¥Û0zïÖS5vªÌžÄ4Í ÐX±XÉhõ<¯ë5†a Z­E׬ÄÀ(f}}=ö:˲ú¦H’„Z­† œ;woyË[ð§ú§SýÝiý^lÛ†eY¨×ë=epHß:88ŒVÊÉ‹æwS¤ ë! æX?“$…‘¢hˆ~™1š:FÝ`•e¹Ë»zåÊ´Ûí™lÈðú=l;žÿœF¥7@%©;-äà@ÜcÒ<þUS.—Q,λr¹¿®Es"Zä’ Í&½>‹ÎÛÛÞ†_üÅ_ÄSOM¹èÒÚÚZ†ã8ƒØ…Baä0†ÃÃCär¹àšÍ&®]»†ÝÝ]lnnöõÒö«>üÂ¾Š¢L”®ë⇠{h²ì9µ^QU<Ò‚,Ëç÷‘R3i2238“ÏÏòž._nãðð{ñŸþS’~¥’0R£{œTmžd¾_X/ ^ëºâ|ꩪ*êõ{P*ýJ%70ì2X“ÿ„àû~Ð#Y’$‹Å¡{&S›z U~§Ï¨×ëØØØ>—¼®š¦¡\.Ã4MT«Õàø úªª¢Óé^¨i¯á‹²~/ ®ëÂ0Œ@žEã8£ªhƒ”p*jIúÖÁÁ¾û»ÿ¿xÅ+þO8ΕÓPE¶-”⣣£`¾‘>w|<»ë¤u—*«NºÁº½½f³9“v2¼~ÏE y^·ÎC!éÑi¢iñbHï{ßSø®ïú¡Z­¦F¦ÐÆ!uw(•JA»@UU»Öwªs@m€02‚ öh§º£t>‘e¹ë½¨¡çyÁ}…"}hî?ðÀxæ™gFúÞFªL ã•*Œb¼ž;w®ïqЧoµZÁäˆþZXV÷.)~–%„(êö¦Þ“âÚ¯þ굉û†Rn«ËCVä{®ë‹…µŸ¥w•òTi ÕjƒwÀg‰ª¦{,Ïš´›Íç¥þiÅbÜ`=‹€…E‘ñyQ©¹ÜÑj½@¨üÕëé‘4£ìy†÷(+ðH:ŽƒbÑ úCV*•@9Ë †dzž×uc=’IñÙØØ OMÓR IÚÄ=>>†eY(žöíˆö0–$ ÇÇÇrìy^¬"k±XŒ)Jó†e{zø¾J¥‚Z­ÈÏYE!Ž?ôCMÜzë#°m;&§’¤à7~ã—N=ôBn^ûÚïÅg>ó5д0bᬸ¡uËøü!C4-‚îói½â%L!<þÏP­VƒËh´g²*¼¢(±u˜6 é5t?Ñu=8„i{ÔN³R©L-•o¬ ÇÎxòÉ';—.]ê<ðÀ'Ÿ|r¤×^ºt©óÐCÅž{衇:—.]êùwO<ñÄÀs¢HR§#ËŽ®w:ªÚéÇ—Ëâù£#ñ·¢(ãÓ“êuñ:fqU^ÆeZòMçM Y–;ï}ïõÔcµÚÌ¿–N¹œ½9¤ªóýürY¬I''ñçÄ¿ÇÇNµÚ}¼Óß%GLS^ú1¯5<«èºÞÑu½£ÎH ÞúÖýŽ,ë“““ÎÉI÷½«Z­vªÕjð·,ËN§Ó999‰)y^’£££NµZíȲÜ9¢aÊuµZ­ïû¥q||Ü‘e9ã(œ…¼duý^’òAôû­;µZ­óßy¡#Ër'—ûtç­oÝt¯N§÷½ãäD¬ŸŽXËëõy“Áë÷òqppÐyã½óË¿üñà¹ããø®ëοü—ÝÑu½#ËrGUÕŽ¢(UU;;;Ÿîèz§óÚ×¾«óº×½5xM¹\îhšÖ©V«z½Þ‘e96g’œœœtt]ï(Šü{’¦XÌqäe*}Xóù<òùüÔB¶··±µµ…F£v»\.‡|p*ï ˆÝ E!¦)þŸÜ@&a/|a;p}£÷vd˜(³–ïAxž‡[oÝÆë_Ÿ‹å,ض˜Ô;nÚÇ*8µ*ùóÜV„-•Âï¦R¿¦Q³ùÞ¯ÍÒîþ¼e|V¸n¾Ïå÷’ZMÌ/]×aÛv6„¹¢¢U.—GŽjp»»ÿ¹ÜG<'èÏÝ©×4 ¥R)Ø-§]v Ë",ËŠy­’‡•Ú%{U&½^ãT{—eº®÷-•5–U¶G…r‘ÓzÍS5ß´4MÓpÿýWñßqw ·¾ïí]4MÿúW?Ey øìgŒég½:*På]ò®fÀa¿°°ŒO†i 9¤:’„ òå/þbø‡oÆ¿ÿ÷M¨ªŠ«WÿNNîÁÿx ×®}ü&ÜvÛ·@UUGâØmÛÆ›ßüüÍßü6n»íGck/Õ O¨®ë}Ó+$IBµZ j ›2wFµˆ“ÿÔOýTçÒ¥K]Ç&åúõë'žxbè÷ÅZ?9 =§½¨V«]×;µZ­³¶ödggçצz}Ì|™÷nà¨òÝéLoÇ•<+Õj§£iáó²,vúêõNGQº_wr"vÿFt¢Ôjâ±è;ß³àà ôF=ƒÖ©~ÌÛ£3Ë5|躘õºø]d9”eU ?ò éºÞ9ˆ¸½eYœtŽ;årydo¤øµsttÔ©ÕB|¯óŽ»¼¨år¹S¯×;GGG-:ùpttÔ‘e¹£ëzàÓç"1Oy™çú=NNN:z½È•,ËÁ¿Qï ÉJš‡çäDx™*3¸÷GH×õÓ(€øùuÒÇaC×'[7³Â¼åeÙÖﳤZ2¨ëÎ]w}®ó¾«óàƒâ» #¦Ž;õz½sppÐùú¯ÿ¿;º®w^ùÊû;ªªvê=”¤“““Î _ø±Îcýɼ/qbfæam6›Ðu­V+¨þDV<ŵSÕ±ÍÍͩҹ\.(Ž3m$i°—Ô²¬`×â¥/¾á¾78æ8âõ‹°!Ád“YÊ÷ (U–à ¥ªöŒ£ž[–ßÉvÝpèηmœ½ó/\W<¨Éz–I^ïYÍc¬ÕÂâ ‹Í1OŸ6äŒ:$ëõ°)9’¢¹£TUÓ4X–º$)(84 tïžOÑȽWŽ}¦ïû1ï—,Ëp]¾ï”3ª( ŽŽŽ‚ö7TØfUY&Ù„ïû(‹¼¸® Y–qttÈs¥RÁÁÁAjÞ*atÿÐ`ë8>~3 Èu_ { !IâÞ´¾ž^ 5,Eš,2«$ã“@Ñï{ß·ã¯øøÆo¼ª* Ìù¾‰ç>×Á·ûvƒ¥bK{{{ÈårØßߪŒeJZîu¿&å"Zd* •–æfÑA¿ š& ©K¥îçšjÛaÄdÿ9Ïç²¶ë ã†±8 }:ëyVnQ¾³UæJò¹dÔU´ ¯¦iA¥FÛ¶cEúÆiï‘lûүꩦiØ8íîžü\*r4ªÁI†v¹\ŽæÌrÝÐp]7/ïò].—aÛv Wš¦Á÷ÕØÚO©&$rÔBI–eüÓú~”J_ôAM®¿º.ž›°!ÃL ‹¿ï¾ÿŒ¼ ‡óçÿ6(läû>4M›¸8+2Ð`¥F×>úhÐkµÝn£ÙlââÅ‹Ás›››ØÝÝE£ÑÈü® åèõ>n÷í¯ª(‹íù`VÇqð_ðOƒ›¿¢„ ¡£"/Ëayþ^seQ%ËÙËSíG¹|6ó:êu¶mñÝgÝû¼ªø~تb’mcE ú& <2Z‡©¶èû>\×Zù¡"Éžª”šÖÖ`ØX]NÈ@UU¦ivUuNBºõÇr¥Çt]ÜCL3¾)'ŒÚÐûÿÏþY˜÷—ÜGIÛb˜,@ýë«Uª¿–‰jçËÊ@ƒµÙl¢P(†)€ 4~ô‡‰Ï:Ôÿ( ê”\ ‹ÅPùfå’YTÇÁ¥KnW÷2ŸG³ÙD³Ù ÂÇé ûm4¦ÃY¦ŸŽ@eÕ“Dw© Ã,?ýÓ¿ŽÏ~ö?Ï{™Åu§o°Z–Pî¨ÊÑÑêy®ÃÞö¶w­jµZ£×‹´ð^Y–c­ ¢(ŠÒ³‹çy(‹(‹‘PËéÛ˜´á;³\PQ¥r¹|Z¬«ÿ:hÂH¥½¨ºdÛñ¿I¼9*É2´aCk®a]é®ë…ìÆ‘ü¬óß!ÀfAãÄÉvÏvñ°‡@Ðx‹lxÓ¹o$»'=B·ËM ¡¶¶¹žƒ»cm1¼D‡ZjóG@k©¥vàè‘æt¹6iÝN.'”.e$’<™B:Ö«$SäÂ8ƒ.“TÆ£LØ%Gß¿~\år½ùµ^üýH­îv•]¿ŸýÔãßó{Þ°±ñ³Qée°Š‘êF¥RA¥RI„gUðZ”ú-8²Y«Àû¯’¤¡òï>ÈpTÆYhišúi·•‘#!oÙ,õC’°·^²ïUJ´“œ9skkkƒE¾´60 cìÂHårÕjÕ6eH,sS2?t]„;nll z© šæ]üÈ0”Aêö²³cõó&$ÎHh¯D¶ØU;0MgΜÁÞÞÞÉf¥Š ¨Õ¸Š‚P+ rToܸ8þü ‡5I†ªàµh7 Ã3¿§XT;ˆÜ=$IÃ4M|ô£ßÀ³Ï~gÔC‰=A!ÿRpDZ[9û×’d‘϶ÑTq2/ãóàà``d–ËåA!³IÂvóù< À¦iÐu}ÐRmVùª„ÖèUXúA«sÕfœ= Ñðné—ͪç2(€Ä{q±0úºV« »cñ°h e°6›MìïïþßßßÇúú:¶¶¶¢ÿLñË?ÊfÕ£a°h IFßÿý›”Û¬õºò¦²ˆH²©V‡=ãNüzž‹Eܼys`hîííMUȨV«AÓ4d³Yììì°™9AÆ* <¤² /UEsgonê=’dóO¢&Å[ºººŠZ­6QºE«EùšPëþþ>*•Ê ,x{{ûûû¸xñbâZÛxe„¦i3$˜^V’$4MÃ{ßûî~‡ h•µo’–ñ3Vàù|Þ5”l\fñ„x¡iªÕª¯±jšÊ«j?\.?Fï‰;b”æóy”ËåA̹sç`š&jµÚDúV"¨ª£%Ð`•v5ëëëƒÇ¶¶¶pxxˆn·;ÒÞ&{ž…³žCOIðoŒz‰Àí ©ÕRFÎÆ7«Ò@>?ì9râ,‚DHRiµZhµZ®ÆªÝcÔhŒê¾bƒ7L} qÇ­€ Ò6T+cÊH˜¨gHBç°ÚsU“æUµãep†)˜!…—±E’‚¦ixòɧ£FbHåX[KAa]JÆ¢G$©˜¦ MÓlyÑ66ÞŒlÖj­uá‚Òg¦iåŸ:7ãÖÖTèüÞu‰7^ƪÍfGŒU©l].®éÑÜ¿Œ}X—…0=ôj5ÿ†Ú„Ä ]×ñ7ó‹µkYFZ-õeeª¸ ¾¬Êe.Ú’Ža÷—¬V«ƒ>|„$z½ŽÕÕÕA‹>ÕÃ÷Í(ÕúEÄúà`Ø-Gõ[6 3 ’ÄŸjµ:ÈU ƒôÛVÏ®]¡ijCçÜ9õ!Hô„ö°¦é·ç”kÃ0B5}÷Ê%$ކw¾óÜ! ‰xR[-†¥FÃÿ3­×냼'B’†™±G˜¦Ú¤aH/I+ív{Ÿ†sçÔ´ýž°ßg³jCǾi}tõ, 0†Áº¹¹9òX³ÙÄ•+W†ÛÝÝzN¾äó£¡/¦i†2VàÖ­¨g@Hx4Mí[¬– k‘Ç{==H…w/[TB( L’ˆô>::ô†Îç1èIc•¤»Ü{q挒QíN¿³3ìa•Í}¹‡4µ+âB Áº²²2TpI( Q}"Ü"„’4ÆÙˆ!ö~„$yWÛívèzBâFµZÅÆÆ<ÊeÒxtdyW I#õz#ë]·:z„Ùx–ú4†ò® ,²/ Ö\.—º~«Nh°’4¢ë:ΜYÅê*CZ¢i*mà«_z$dVH•g¿H_¿¾«„ÄMÓ!‘çΩÜTIm88 w•¤Ã0°ººŠl6;Øwêív[}‡Û Ï0°mMü;‡µÓéàÆƒÿÏŸ?Ÿ¨Ö6n‹wÓ4™·DR‡¦ixøáçá‹\ä¥ ]÷_¼pÃ’$™F£hÚp8£ý7!i ÕjùöR­×Õ¦óÑÑøa¼~­ÎH<m°jš†—^z ½^oèñýý}är94Ć ëºÎp0’:Tß±¡ü â´x é!Èqªiû®’DbLÓD±XD£Á\;’nÚí6n¹Äøš¦ ƒÏç•±Ê çtª­M§ÓA­VÃÊÊ t]ü4 ¬¬¬àùçŸG§Ó‰z>¸µ÷0 ƒm HêÐu¦™ç"†,šfUx BZ€’4Z­ÖÀÛdô¨’ôÒjµ°æ±›\­ªfö N7¡<¬ÛÛÛ(—Ëh4#Ǥ @­VÃöö6®]»õœ|q*t¦!iÄ.×o²lhZø/]×éa%‰Ã4Í!“®G’TZ­¶yË·Y´7ú 7›ºžÌ“E˸µZph˜Ù»ÉRª$$qm;â]­9vgØ’LJœd\Ó†;Ø{ Œa° ÒâÆ™ûÓï÷ÑívQ*•_£Ûí¢V« B‹s¹Æà¦éõz¨Õjƒ›©\.£ÑhŒ=9]·ìkk*¤&›UV[Šò„5DÏA·17Â%ßnè:pçÎ?à}ï{ ­èe%s!Jwd¬š¦‰jµÊ"{$q’mAוœëºÎI25q–qõ7Jd”P9¬aèv»ØÜÜ uîææ&J¥t]Çõë×Q*•†v ···‘ËåÇ»Ý.šÍæDã’õ‰*V þ––$b6¬A…!E³Âæd^Q®EÊ·Ðh¨ŸvøÄ'¾ù|†ÁV2¢q7¤:°ZFOÂÙ¶£ëÀ믿Ê"ad&ÄQÆíÖv»MY'#ÌÌ` K§ÓA¿ßhÊd2X__„÷z=t:¬¯¯ŽW*•™äI4˜aÜiÊøÌByXƒÐ”CžkB¸”ùJ¾u])ûbøò—¿ù|~(€Y¥wÔÊÃ4M´Ûí‘0JB܈“lÛ1 à›ßüS¬¹•J%d â(ã’¾'ËrMÓ(ëd„±C‚§EraíýZoß¾ @Ýò·=¦¾P(öu£Xt_°3‰;4 Â€‹ç -¨Á #ö£ Ë{»`)ßv$œ&›<°^›¢NfMT2îÆÚšHp½^G­Vã% EœdÛŽ®wï^C±ø«Q¿E$áÄQÆíÞUq(Qg' ÷°f2™¡<×^¯‡f³‰J¥‚\.ç{Sxõ€àK_ú:Îà1©lÇXæIñjÆ ÊEÈ1•ÎX•×Þ€g®k¯×ë¯¾Š¯|å+3ŸÖ¼ä¾þõ¯£Ó錼F»m){ÓÔñÿøvl$¿Ìt:Ü»wo.¯½H„ÓXÕu}P X×uhš6hBÒC·ÛÅ«¯¾Šû÷ïÏôu£Ðßa(—5<ýôù¿‹$®ˆþ’©Iˆ“þ²Y ú¬28ýÈ|\ý½pƒUè÷ûh6›xæ™gP*•pùòåÁã^øMîÁƒ¸sçnܸ1xÌ­åRç¯6 ªòF|&Y(C4(‡U³=§âõ¥ˆ“ǹ·oßž›Á*ÌZ¾µà¹qãÆ`t0]Ýn°šxüñ»C ÈòqãÆ¹,vì,B‡ûa£ù«F†a Z­âܹs,P“Ræe° ‹Ôßa0Œ6C$—Ñßó’o zýmGÒ™e°RÖÓ¬ÁÇ•ïÀà°ÉÖã,ŽºÝ.¶··‘ÉdpõêÕ‘Ð/üJk?òÈ#(‹ƒ¸|@yžÖÖ†½¬ú2»4„o £ŸüÌÃ9a÷®@PÓóYw¶Cœ/•Ð=>jÙ]œD±†aò o{ÛÛ†ä[Ð4«¥¦ixüñ_,DCÒÍÖÖÖ ÂãýÖ£&T;)fAêÚ"å[°¦º®Ÿ™YüÜÉr…Œ»aÃVæ>‘i‰‹lÛyÃqñâ3Q¿5$%ÄMÆóykãQÓ4ìp§xh°v:lnn…Òöû}t»ÝÐU;¦æÖ³U®±µµ…ÍÍÍAùíL&ƒ‹/Ž}-{å1Á4ÍåÞ…¿âÊx”J¾AÆÓ zí—ÇäšNZPžRƒ„ºº­K!ÏæÉÏ£K)ßn躎l6‹vÛ»J6!ÓµŒªç°s#^×uX"SÙvò™Ïü>ò‘߈ú­!)!n2n¯¿aÉ'µµ¹rå ö÷÷'ÊÝÚÚ Œq/ xùå—7Ö$†1T«À­[Ã-m•àUXžÇ ìÞU³5Xó5 ½¼«”Ñl_ƒš )Ö0¬ŸÌeuW)ßP¯+£TÖé²ãô>2+-ãNLSå¯Þtl¾q±C¦%jÙvòÛ¿ýg(ÆÏ{%Ä‹8ɸ,Çóy Õj1˜ø²ð>¬a''Ö ö`=A<€å5õ‹œÓ¡ÂpÃ8¢Å¸mŸ<Ï/šÃ89Ç©“¼ÆÒÂhXoîU…Ý ëòÉ|]xÓ§ß„‡<4ù{:%³oADZÓ´|×jS¼ !3`–2n§ÑPòm{g80Y$ó’m'ò'§pñ⻢ž.YB!ãR8ocCépÌ#~DÖÖ& $\réÈb88È1.ma€à"Mm(£ÒËtžëözâ5õzm;e׸àñ¸Çcß»ó½xí;^û­Œ;;£ · I3;;£õ t]§ÁJR‡aäQ«Q®I:‘´=V&aH­ÁêÖÖÃ4MÞ5 1rÃÞ¦âõÄcz›‡{!¤,F{¦J!&7ûËi„ÊgíöѺ=V¾¸ùÅÉߨbí$ÕxethšFÙ'©¢Ñ0Ëͯ5!Qbž88òyö^%áH­Á Œ¶´Ñ4m9=PN~7ê',E{Mý† ÃÒJÀpñ¤‘s¡úTÔëêw Þ†µÓ :×¾yqò÷WÿùW'}7cÅ… Öߺ®sCf\Úm•ì~544MÉ9 ¨'扎YJÝNRˇ?|܃!i¥Ý¶¢Ãh°’0„ÎaµWë÷û# ³l3–®B°Ëè\[VWîE`ÿQ÷óÏ@yXMS··^ê¿§¬§B©CŠY¨ÕäøGà;ÿ ðêÿ´+M88Úye°ºW2€¯}M]¯\úOºg²P†gÊ l`8V×­ÝŠ,†=²ë¯ýàõ¨?˜Ù`·±–¶èŒ®«o?Á™àèDd[¾1Ëe%ÛAÏÑ4ë§Vsï›åõœá×ÏfÕnÃ͛ՃH6r C×ùz.¼÷•Wø!Ì]·Ta8wîÜ@Ÿ³:0IŸýìi|âOF= Bæ‚ès†“°¬+++X__y|¦!›-º‹¶¦©~œƒkCy+½îYð«aÚµˆg³µŒ¹|ØÛÞ÷ÿ€}—çHõ]ÓT†m¹¬®ñƒïZPFzdPFã€3gN ļïð±¦õššÜ{ë°´ÕR×(­}îcÀÎ5§Ÿö˜—®çNGŸê¾òaàCß7|Ž”Î][ÏÝ/ÕkÀÁYàÍoÞô£À—õϱYbe¬¶ZÁà,0Må5M%«Å¢’ €#—’؆¡ UMSÆfc±ÝV?òíº¶¦î!·9ol¨±H'tûsœ×)•Ñ»ºªÆšÍZ©aŒVͲ÷¦k4”Gؾ$†·¿:sÿz¾ŸÀB±«nÃ0°±±Áž}$•\»ÖÃéÓ_F6[ˆz(„ÌMS_¥õz+úu9Ik.— ,GŠÅÑàÈõbšæh¿ñV:ï[û";›UÞJ3¯ªßºTÓuµxÖ4µne‡ .•ËÀcŸ·Jm¶ÛêuËee0ï¨ÖÕêP”ÈcO©×ªV•1¸³£ K¹¾Ì¥…ÑüÒrYµÔq®ñÅû”ͪ×nd-o°ýs“@IJÎfÕû–,PùSà3ŒV>:²ÞxÀÏ­fÙó—“o±ÊÛ(ÙŽGõºå­ÕF•‰]WF¤i*C2ÌsdÜgΨ ù zžxwÛmkãËÅð~ðPtU°gì¿É4í± IõW‚‹ßà'¢ !3Ç4Õטišh·Û¸éìQFˆ ±mk3-¦9¼†Óu=š½½ÝŠxvÄ•Eº[*›„-ÊsööÔ¢øÏ_®¹<§ÕR?Ù¬u¾„Í:ײïþàþÐ:c-øíã´/è³°<¯{{Ã1¨ÎõbÞe\’?j7*½ Êè½i‹xìažRU8à÷Ý~ ©zœÂ| ·–6‘ ëÊHä꪿ÁjšÊ(4Íaï!¾‰¬Èºµm;ú:ãxãÖÖÆ;_îÏquŒ}ch¼æžRêu+r`=’n^y塯Þd$¥È×W½ÞÀÚÚëP„6X»Ý.ö÷÷±¾¾ŽB¡àiüé1)$"éö¤î…V‘4¡¼¦k° %kµ¥¼1êÎÕ0ì]m4¬°J NBhO^ÏİQ[,*ï«}׆»‘öŽoþÕoOýGëüêɹn=Ríi>¯æUvym·¾§ W%ÆÉuÛ°rb¯éñ™5¾ªâÂɹ)[ß:óW#+Z ›%ö;å²&ëDÓ”"žHç¤VWGÃuÅc¶OÛ´¡¢“lnEíáN1>&°"6I+Õ*ðçþZô3„ÌY›«Œ0 GGardÙ e°jš†Z­†\.‡L&3x|kk ™Lš¦¡Ûíâå—_Žz>CØm·…ß-XžI'Ù¬Z¬7jaÝÆhx¯W~¬ïu¿xx†Z;F P@nóð‹¶ó4¸·¥)b8Dׄ¯—=` nCŸaÖ•Îëø‘õ˜—ð®Nœ`$¥˜qÝ3ÙnÛrâV´Èi0: íí¹x’{,­ªy¯~øÅ¶”Ø«I Æ"+:/3ºnÕ˜Æ "¹Ù¤› ¢GòyàÝïŽúÝ™9¦ |üãÿ„BáAÔC!d憵ÝjµP,é]%¡ e°noo£\.£áh‰R(P*•P©TP«ÕpåÊ•Øä»Ú×˲¸™É!¹mÎT'WzÀ65#¾V³¼¬yeD®BW^¡@,/a@þWý½—^ëû<† K¿¶0Nð7åµ%ï½)CR4—<$÷\ J0yã¥Òµ¯Ð}g±œ+5Äè”k•ËÖo?¤ÄÚš2 ¿ùͨߵ™“ÍúÐ' i)ýÒŠ+²¡b¿ü¾óœJÉMþß4­:²A;œ¿Ôëø—_ùJÔïÊÌÉç­%@£Ñ w5*D #²Ô¢‡z=<ô`¼¹@ƒµÓé ßïãÒ¥K¾ç]ºt Ï<ó *• r¹\$o€=žÂæÌU«êwP‚øú¯½Mà ûÞçd³Ê0•PJ@V¼ ,1Ë'ç´½_~ȸub¯Flœ¼Žß”V¡Œ_Êë§cìÞLð\ÞÕzݽ-‘1Ví_"µšªº;”W‰0±o Š|Ë=R«Ê†#Âuð] ×p“µµµaC2È(¬{J×­qÊø‹Eõ˜óþ‘ï·è^Ëåp¯×ëí 4X3™ îß¿?òøîîîXZ4òY›¦|sÈ­—ryç'‡{; Û îFœœÓ*ÚzŸÂÛÛiByMÃ|»…âz…ññmA—&‚óA ŒÕ‚Ãkõ“±²JùÜi·•ò\àHN¨^ƪP« oØ,Ñ—,‰·htÓ4ãUp©Õ®$âÞzîœúm÷¶d³ÃEõœ‹âZmºh7ƒp–…ËeeDH;5YlÍòõËåñB0ˆì{«ç1Œ °ž²(µ/¸½¼ü² ¦Í— žù¼ Ãòì8O%‰=šfkŒ¡ëÉØ”‘MHÀ=JD6%¼ÖnØy´aèÅ$›,“è¹§&Ñ·sÞH4X …úý>:J¥’çy“ð»×5†Ö‚ÞÍ`­V<ïß»ñà`¸ŽÝ*a¾^:Õ¹‘ð[;&¬v/v {K½^Óõ9cØûfÇgvŠðö(“™":O×uìõ-—Ý («ò\©GÏI-nÝ{t]ŸmË µ’E‡³ ÓÎŽ{H¡p¸pž¤×à<î·yCaûOJŠU@íw(çâò³MS}4Û%ò·ÛÂÜîÝ‘c’K\¯[á>Â,S:h&Ùï°¢KC¬YfqÑVk4"Ì’+HÝ ÙD”~éíî¶i&†]XÏ>™ŠPk¡P@³ÙD¡Pp5Hûý>šÍ&J¥ …BÔsZoøîäH%ÒbÑÚų/Ä+õÊû_оËgbØcš‡ÕŠÆ‰[µ[·â—â…u®]$ôV®'9¦aÖròza×C¼cGàºS&–—Â~/´ÛÁƪ„ÝP’:œNHõ˜1YH°[^Ý3(ÕÛÃTÄe±2CÚmqTÏлÚh(Yv.²«U«ÕÈÛ:î¶ðö3@Yo€`ïpgšæüS:¤=žt㇒Èy6«vüÝ:ˆuf“Ì-o”ÌPU‚/_¾ŒÍÍM<ÿüó¨T*CFé7pxx88/Ø7O Ãðþ˜JÀ=,¸V¾ð-Êôkåb'‹aƒQªåŽ\ûä·Óp†KQ$7¯åšãµ«!Çèv]’(,GOŽvÛÚ½q –ÝCzMIL©V•ãNDt,”Ü$šfå9‹IÿjB"BêM©R3(¸$ùÊÎ곂›¼sÑMæH»m‰¦ióyÏç‡u½¡^yÿvh„Æ–Pk¡PÀÕ«W±¿¿f³9r¼R©`}}=Å–œxîÆ;«º…g³À9(c±âb&”‡Ón –¡<¤Nêp¯¶ë !λ*¯½wiõäZ¼Ï–Y‡‹> x{Ò0LC•ÄI By  CíªKDŠ[^ !n0vÁ%»¬çóV”X˜uB€ì™‹8Î$Š@Ó¬ÖX¦©ô»Ÿ§ŸFh*e°ª ðåË—±µµ…n·;xÜ+L8øîÆ;ãÑ¥Ú–=,XÇx ¦Aa¾­“s܆f!6.l·qrîœSH|õ‰¯òw¶Ÿq &$Æ8× zPÁ )€T«Í7§’±±1œÛ7Öb^tÞYŒ:ħº6 cü°w»‡”Ñ2KËØk’0 ÃýÀ¥OoËp¬ÎÊ“¬*º’‹êg°†ùœçå5-B m„«à+«Œî\*D´=ð^m ¸À! A:…ÙÕràî< ÀÑn[a﮹}†¡n„v[yQ¹P' Ã^ëNÓ4ï G]·ú¼;õ8×-À·D=€ybÞ§ë}à·ø?YzíÊFä–záÓæúÉq Ý ZSœæ»)Vð]BLÓj2ïzЭ… ! ­õâD»ó„Ä”VËŠ 2X5Mõ핊¾7o2ü‘$]®õ¨ëº»þ®×­ {Üt$¤Ú`u½9 ¸û#À OºWïÚö¦–á}¾¢^˜° )1Õ„ÌÕJÌcñNc•¤g öL[~ìEÚ5M³ .ÉâýèH¥(±@I ÒMFÐuÝr"†2TÏœQÿß¼ÉâKªC‚]sBþ÷C@édÚ~9¢n=RÝŒM ʸõË!eõ^2cÖÖ|Z69«’@¤«ÐjµÆ« JHÌ‘p÷v»m-䥃ï$á8Õõ`ÓÑ0TA­¦ UnȤÚÃêÊwä€ç¾[ýí·öYÃhH®óªÌ˜CJJ­¦”¿k˦¶4 ‰Æž÷$ y Ü°W’$$æhšUXl(·/›­§AHÂÚ”Ñ4A¦/*!'¤Ö`õŒ•/ç“W¨|Ããq ª%°  †p¹¦„ÌÓ4"IR‰3xh±ã…Ý $æ´ÛV‡Ž¡Í˜r™Ž$ñ˜&°ºjýßn·­‚yL["c“ZƒÕ3¿Ïø¿ÿ|TÉc½€aã—Ü>’V¤¨˜à[]RpZ¹„Ä)äj3†„¡i–:6M“ë25©Íaº9Z-u÷l¨|S{.ê ÷DÝ€wxoÙv,LËBæˆaVHp«¥vå¹ð!)À™‚­iöö*Ö1´Œ$Ó ‘0‰|ë:PþâF@IŒ™T¾Å»ú‡ß÷}ø…^`1125±õ°öz=Ôj5t»]@¹\F£Ñõ\Ó4ñÔcY¥³ (£ô¦ËÉk'3‡,iäP9Ú¿öÊ+À?õTqeZ€z½Žàu½‡ÉB™F¾×~î¾{烸[©¸‡$$b¦‘oÃÊ}wðÉOâæïÿ~ÔÓ!) ¶Öíímär9躎ëׯ£Ûí¢Ùl†z®®ëø·_ÿºå]­C…ûzEŒÑX% fù€ïü‹¿ÀÃ?L¯‰-Óʸ¦i0M3\ÕABÃ4ò½ñ÷ÿ ÿãᇭ6„ÄŒiä{­lâ—?õoðóŸþ4ÜûÅ2&±4X{½:Ö××™L•JGGG¡žÿßömx÷¿Èo¨ÜTl?Cbôò Oæ3ÈloG=B\™…Œ7ðá’7o†;0­|á _À‡œm>H,™Zë:þëéÓø™_ùÊ8™±4Xoß¾ ( ƒÇ …Bè8ú·ÿðã¡Õ†Ê[50ÜÆ&AŒãHÝn‡‡‡Q#r¦•oøëŸù™Ä{WÓ(i»g'eZ×NªI çÙêuõ“€Š“i“‡4Þ³“0­|¿øOÿ„_ùÍߌzS‘FYHÛý:)ÓÊ·žÍâÏ~ìÇŸŸ6yHú=ËV¿›¢ßï#“ÉŒ<þùÏûØÇ¬þ«OÙ~,êMÆÇ?þñ¨‡0S¾ô¥/áÎ;`™å8>÷¹ÏáÔ©SØÚÚZøõ'‘o¸uëÖ××ñØcáŸ=õTâ•i\äa–ÄåžÕuû·Ùõ§Õáïyè!ü·›7ñw?û³ø¿oûèk<òþîSŸÂ½“üª¸y˜q¹g?ûÙÏâÎ;xË[ÞÉõ'‘o»þ~â‰'ÐívùI$.²0Kâr¿Šþ¬gÌ,Öàïz×»¿F‰‹<ÌŠ¸Ü³²WÇÒ`í÷ûžÇîß¿ïz³ ¼÷½ïÅÛßþv¼ãïˆz 3áõ×_Çùóç£ÆÌ¸{÷.îÞ½ùçs÷î]<öØc8uêT$ןD¾à=ïyžxâ <òÈ#xä‘G"û,‰‹<Ì’¸Ü³™Lßõ]ßÙõg¡Ã?÷K¿äùßà"›]xâ"³".÷ì£>Š;wîà­o}k$ןD¾©¿ãO\îWÑß>úh$×ç\y˜q¹ge…«=L 'IDAT >®þŽ¥ÁjCp’Ëå\?{ö,Ξ=õÐgJ©TŠzdL"ßð;¿ó;Q—{6êqP‡+¢þÒJÔïë$òMý¢–«¸Œƒú[õç@†‰eëÊÊ €á°„^¯ç»˜'$)P¾IÚ¡Œ“4Cù&i†òMâH, Ö\.‡R©4”¬iVWW£!SCù&i‡2NÒ å›¤Ê7‰#§Ž£„Ýn›››Èårƒ$ïÝÝ]Ïü>B’囤Ê8I3”o’f(ß$nÄÖ`Tâ·TÑc,9I”o’v(ã$ÍP¾Iš¡|“8kƒ•B!„BÈòò†|àˆzi§ÓéàÔ©Sž¡Ýn¯¿þºëq¿caŽÏƒ~¿Ã0<ÛfL;æ(æD&gùžÅñyà'ãIœ™?O¢rüS?õSÇgÏž=>{öìñ /¼p|ïÞ½ÁñÛ·o?÷Üsƒã/¾øb¨caŽÏƒ{÷î¿øâ‹ƒk>÷Üsǯ¼òÊÌÆÅœÈäL#ß³8>üd<‰ó!Óá'ãI”êp",›þSçC¦ƒú;þs‡XV Ný~Íf[[[Ðuׯ_<&loo#—Ë Žw»ÝÁq¿caŽÏƒf³‰^¯‡ëׯC×uär9ìïï‡SçD&cZùžÅñyà'ãIœ™œ O¢{öìÐc/½ôÒñ /¼p||¬v2Ξ=;´;òÇüÇÇïÿû}=w^Ü»woäš·oß>~饗B)Žs"“3|Ïâø<ð“ñ$·L‡ŸŒ'Q¨Ã‰°lú;hLqœ™êïøÏi\¾5jƒ9­”J%èº>ôØíÛ·qúôéÁßP(Ç …z½žï± çÎ ©W(ÐívÑï÷Q(°µµjLqœ™œiä{Ç矌w:Ä͇L‡ŸŒ§M¾g1fÊxrX6ý4¦8·Lõwüç4.4XÀæææ@®^½ ¾BpëÖ-Ïcý~ß÷¹Ò/kÖÜ¿d.÷ïßÇîîn P‡ss"³a\ùŽ«<øÉxçCf‡SÆ5Mó<7®ò@NÜXý$ßq\s‘ÙAýÏ9 sXÀÅ‹±¾¾¸rå %^ܽ{×óØýû÷}Ÿ+B=kì»;×®]õk×P©T°¹¹8Ÿ0cŽbNd6Œ+ßq•?Oâ|ÈìpÊxå:œ¸± ú;hNq\s‘ÙAýÏ9 ÖP*•P©TpéÒ¥A‚´Ýíîv¾¹\Î÷¹¹\n.s8þ< Â¥úý>:Nà˜¦=Nâ˸òWyð“ñS§N%n>dv8ed:¨¿ã?§q¡Á:'Ο?N§3p〦iƒ?—Ë¡T*áððpèøêêªï± ç΋B¡0RB»Ùlvf¦ss"“3|Ïâø<ð“ñŸüÉŸLÜ|ÈtøÉxÚä›:|¹X6ý$ßqœ™êïøÏi\NG=ˆ´²½½ÃÃC”J%ܾ}{(AP1é›››Èårƒ¤æÝÝ]d2ßcAÏrMÙ¥g>³8NâÅ4ò=‹ãóÀOÆ“82~2žDy '²éï 1Åq>d:¨¿ã?§q Á:gì%ÓÝò$úýþ`ÈyÜïX˜ãó`Ú1ÅqNdr¦‘ïYŸó¼')ßÉÃOÆ“(ÔáDX6ýt<Žó!ÓAýÿ9……+!„B!„XÂVB!„B!±„+!„B!„XBƒ•B!„BH,¡ÁJ!„B!$–Ð`%„B!„Kh°B!„B‰%4XÉLét:è÷ûQƒ¹A'i†òMÒ å›¤™4Ë7 V2S677M‡ I#”q’f(ß$ÍP¾IšI³|Ó`%„B!„Kh°.qÕ÷z=BÓ´Á±n·‹ýýý¹íŒÈµûý>4Mƒ¦i èõz©Q ÃD%ãQÉ7@_&¨ÃIš¡þ&i†ú;Ù|kÔX&677Q©T i …:J¥r¹:2™ šÍ&Ö××±µµ5ókommáÊ•+( ƒ›òêÕ«Èårs™o·ÛÅææ&Êå2J¥ÒÜß_=QÉxò PÆ— êp’f¨¿Iš¡þN6ô°.˜N§ƒ—_~»»»ØÚÚB§Ó\»v W¯^E¹\žÛÏ•+W°»»‹ÝÝ]¼üòË8}ú4çr-ûrùòå¹½Ÿ$~D%ã‹”o€2¾¬P‡“4CýMÒ õwr¡‡uÁ¬®®"“É … \.ޝ¬¬øÞ,ÊàE¥RñÜ­©T*ƒkf2¬¬¬Ìå:ÝnW®\ÁùóçSs£ðL#ãIo€2¾ÌD%ßrœ:œÌêo’f¸O.ô°’™Ól6qúôiܸq#qó„8¡Œ“4Cù&i†òMÒLZå›Ö„‘Ëåf[?ëëT*lmmáÙgŸE³ÙLÕ™/Io€2N&cQò=íµ(ßd¨¿IÚI‚Œ§U¾i°&Œn·‹f³éy|kkkrÕuÊå22™ ._¾ŒZ­–š„o2’ ßeœLÆ¢ä{ÚkQ¾É$P“´“O«|Ó`M¹\/^ô=—ëÈM²½½k×®-þÍ"‰#Iò PÆÉx,J¾gu-Ê7êo’v’$ãi“o¬ #“É,d§dV×¹|ù2žyæ4›Í……‘ä’4ù(ã$<‹’ïY^‹òMÂBýMÒNÒd> endobj 2 0 obj << /Length 3 0 R /Filter /FlateDecode >> stream xœÌ½K¯/9vÝ9ÏOq‡Ýƒ:æû1l–ÐnR·x`xdË¥n)…vI@Ãß¾×ÚdDp‘çVÖ¹éH”dÈ7ÿ<|ùã~qó¿ÿä¿9üïïøÿÕ¾ý—Ÿr>dûõù~þï?•ßñC¨Í~ãæ–rýæSú‹=‹ßþÉÇÔñÿðÎ{üÛ=ÿ`Ñ?üôúgÔþ{ü÷_ÚoÏÿáï¿ý·ŸþÏ?­Æÿyoð5 1£ý1û×?Ù¿jaOPhÿø‡ŸþäcøÐ6í÷?ý§ÿŒ?ú¯?…oÿõý?(*)·¿ý?y÷í?|Z÷ß¾TºñóÓ±7j )}ð¿C W·¶ŸâGŒÎ9ßâKMˆ>}øRJ.xbެþôz¤Ë6èúKý( Èí·‚ñÑå—½þóþ›/¤Àßý7´fTõû?Òª’ÛG¨5x×ñhí£Å[HÆ‘ûw\~üGÆßþîçoÿéñ¨öýöŸ¿ýÝ¿ÿéßýõüë ®õײoó u…£®·VîˆW>æÄÂË+wíMù(¥÷Þ|}H¾†Ö] G½KÉ‹Õ{÷Q›ÿ¤ö»àýoê>b@­%¿9جP[ê}}°­úe°µöc°™?¾£ŠqŠ¿ . ­H€H0yðUðh%ÞÕàb‰Ùù“;áª$ÿªZj±Å½/G%·¢k-†ïö‘ªW|ÿÎ}8ûŸP¿ýî©qiÊú½°n—"§ÖÁGo±cų!”ý]mùË¿ø«¿þ›¿=š³î&´ûµxìF¡„ÔÛ·Ô±7ûZ±Qõ³ZÂýwiTû/¿ÿûŸþ:Ýuººï²¡ADÀ”˜¾…? þ«ÕɉÆö¢,”öÍ÷úQ]Ç0•NQ±eLD gÂxÚwÅž›oV†wŽuÁðÔø‘Bª¹uÊÅh÷ÑÓK'!*ùñ\Ç;Ù¬—o><çb«¨€eŸ õ5´£ ±-ÁùʶøÀµ‡ÏY¤düËðÎŒwÖ\ðœÇ†ŠOc´2¼“m‰¨ŸÑãïB¬.x¼2Qp °ÇbCד•à…mÊTÿÑCì.%«ŒSÓß`­ƒZB ö^RÙ”1(>|ôœX` ùÃ_ãÅ÷»T:ZgEx%±ÊðÑ¢ëÉA¦Iå÷i˜|%†?E ¨•á•lJöƒG *n–áü>¥²>ÎC,Ã<Þ™0DlJtcÓÈä|rÖÌ„w>0ïcîXEVÆUÉúj´çPY­ÙöðñN~ŸÙÿÑ1Úë_Æ;Ù–Xð}\7ð`úÙpBòÀXù<ǸðÎ ëñ[s=±‰Pð²{¢¢@ØvþðÓGÆ€þÞ*JÙ{®âø6CìÂs˜Ô˜àÎ_óÇœ[ã9Ìr´¤çðN~œ–ÓQO»',žãP±ô­ ï|&,fWÉsf”á÷„ås˜HÁ{'O»Ç )äŽÖذ`í v2O´¦1õ°vr]¶ e8#Ö¦šÃz‰£{%@©ZÞÉoÓëx.ã{ælk'bäï%Žwtµöbê$¿ð:e IX+Ã+ï)‹êÀßB·¦`õ”uÊf{£ã¨D¬žÎQñiN“Š•›5«'Ø+kõáÿttÞÊðN´ekg-˜P X†åÃfãû˜±cwrÞÊ2víkÊâ9|ƒRœ©Q˧¬SÍÄdÊ~ªÒüs”õ+BÆÀÿÿ5± :—ÝaC÷AnW0‰@Ò>!w@×0/йƒÜ ÂT*Xƹžs[To¹3wr}ôþ 7Æ®,-ÌɃÜ(²—B;¬+|´ /6”ØY¤‡|@;ô¢«CC: +Yﺳ ¤ØÆ¶ŽÖ7ìÄñÀvªX É@P;§/ùM ;à‹Hƒ'í ™¯bÖ9B;’Œ±cXNhÇ€ å/—v@c‚É”0Õúm?F¤%ÛpÚ±CþÄ?6\…v²ú¸àhãcÊãcíÐΘz¹zÇ™|C;xkŒ¾@oîЧ{K'´3æZ æ¥ÚþŠÞs‡8 ]Fq+ý€6¤½TßXýíBØg´PfCSHÍ•^K<˜ãG A¯³Q–+?Õ«•ÙèAw±&þÝÎlŒiÁg¼òÁl q羡è`v®l ä…ØfcT€^?å2avIøwöfã1T—}³™§ÌÆ—LÛ¶žƒÙ«ÑPÀÌ.˜±­eÌøv03 béC2³KAða{<ÉÑ14CTbW޾ VÆAìÌ5s†5#6~‚F©+|Éæ@bû›Øí[ü¾Å?Ú_Œ3DþÇíP?0Ì ÿ/ÐÆ c‹ós?Rhs¥D\Q´ IŠ!Æ^a6?«ã8ÛdWfÓFI<”SÚ Ï5—ÁÜSÚæB/9„;¸¹¶°òÝÜà[+©™¹ÉÛ(´«Ÿ²ø î@ä4%†MÞÆ®éÆî®ò6vk,ÌÈtÊÛ/ Ø]‡ü«òv£lœ(Ÿò6„ì©S(Øä튙D¾•SÞ®Ü9+'î)oƒT汸6yºØP&5UÞ.P¾ˆ/º=' Ƕ5åíÊMõ‚¢e$ÌvÊÛr3 ¬­ÝlD¯Ør[:åíBé êI<ѽ½SåmHaw ÂÃ>Œ}UØ2Ô†Õ?¶a7>ú“±òÊÎn¾í‡hOy[§—°;˜…EtcŠBdCÂn”A…ø5dãÝìz6µ9E7‹_’IDŠn´²C.ƒdt¢›ïL¯n{«¢e¥ß{«¢;p«€òêAn*â Ãçlù+º9˜»Fÿ`7›‚‡GóÁn¼ÿ®—‚’ÆŸãDÖº?ݤ÷ëØ¸ÄK¨è@;Ø}0ôT¹îìîTA:¥ñz ›ª„K˜½è†Zƒ‰!ØÈ ì¦Q‘li&€)»Q†YˆÍ¼ÅƒÝ˜SXµØ©è¦ ª_ÒŽnG{Wl˜‘§¡ïȘ}>"s»ôÁyↄÜ.béB‚Ķ|eÑab ³“ÛAiÀrm"Bn”5NŠ<´c!7ZR¹AŽÝ^Éê |ö< Bn¤ò áõ ·Ã:€Ýi…ÜŽš:Õê|’ÏA{ÄÀ×|e˜7ÄÔRbóáZ$“Üè4æÑs’›Gïý0Ã)¹ñ2,î ›¥ÄL Õ%w»c1R¤KS®^À¢òµN…ÛÝL(ØÅÓ‰m4²A:†Þl£ K"ç¹…¨™£ßñª¡®ØÞ²R› áG|hw³!Ôi‡¶Y‹±íwÛ­„Ù(Â`”iTZ‘͇ b¤6l'Blö ´€@Zb£Ìa9aÄëAl|lLPÏÄFuØ¡ÖO9|6Û% ˶ïÀîfUÉ­ÆÃ:ÒÍÈ}mì*+®Ù5H¥ iZm# 9Ú„}ñ±`ÞŸ€8ÿ5I{„/Ä~¹î .L'ÿe`á‹á ŸÕýŠ©OOúݱ7jÁü67}‚ž7»µýôzì@ŽÃSߪ»š°ýôz¤Ë6èúËÛá ÒßñÑå—³þ_ô²A¶ pCÝ› [4)„ý •?§€…g­ÞPxåó•° á½¸ˆ¥7Åf„mEï"H}èk½ïûл,hí/,¬ßÔ|uýÅÁf…2ØRïëƒmÕ/ƒ­µ=`rj€üNɳ¼° •¼° µüXÀÂ/ÄDÉjêe}ú…˜·ÆüËÿx/& v‰ €Nq­õHÏRr‹¢‹1ÿHTÑhLDòV j£, ÷p¢y[|Z‚ E±™‰ ˜‹´[^y[|"¾4‘ÒÌZŸ¼8–ÃüTS#%Þ™ZŠÃϘ‚)3Ëb.fÖIa5R:Vד7•5Q‡¼->j÷„°@ùò°Ò4€÷Í.P‡|L>«5(A…¬ƒÕÜfô©[+Ój£¬²¡…ZL@Jb£„òœ ? •òb£,4cù™>•²Ø(Í¥•®)+Ã;o‹OŒ3€¾hf0¨4õq°šòúÔ;ÉÇäcÚ32Ë=(ÓäC’ôXj3Wvªb£ 4×a¶ÄQ¶Å´qh˜|S6JO5ªô˜xM4ÝN%2egÞ‹Ô¶˜yn‹ €ªˆ½Çƪ‹‰Ò¬\ +±Çú…/ £LL”?‘ÝP#ØšÍ|™„8Z(ò´ d·…  qêÏÙkH&O®öìW %=û•j|Oáme<ØÍ2©HrLBÃ`u˜û%‡- t̺aG¥ì7Ú˜ûð´÷Xs2É5Ç="€q##ÀýhJ裕橸æ¸$º'ÇjÌX:>6ßë7‚Z ¥3«grÁæyN[@@‹ô¤Ø*Îæ˜ìŒVï¤ o˜Í¡¯ñÕ^Ù†C=céØ½Ò‰h…¦>l›+ Í3~èKjÌã”Ú Y@{@†¾SÛ÷DKGq O¨Ý0OzMSeß°?BeTIŒ'¶i«¢ oðP±8¬®Œh” Ût¤b”æ"ØŽlK¿œ=ŠíÈè#¬¬2Ø,Øntx$3îØŽ“ømöåÛhfu¹¢i'¶1£0Ñó iPnçÄG yݹ]"€›ŠkcSn€Ûœ»DÞÂÐÏ6xÊmn‚˜KØ—òÁíhͼÂÑ”ÛøBxaäzp›‹©åÑèÛÉB °>Ç;…ÛŒ• g,åv®˜V9Õá‚ܦ}³†»cÂmúÍùâúÁmŒq¡†R±zrH4ûƒÛ´€6,?6~á6ô|ÐŒ}î[T@§7¤Dp{X@ D”vp;ÓðŸ/!D¹²iô;·YDAcD^(¸ÑóÒÃ"©àƼ¨ÐKÚø¤Jî\ÐW(Ã=©äÆœ©¨ë¬»@Ý*Ý ©€;“ÎØ^Ú nè xk`@Ðn|„èì1÷„‚»Ð„ZÊ„ú¸)…±e¥-* bè@Õx€»pïÁ”žÖÁ¼ÅøŠ×”±é ¹ñž>g²™‘›?¡[uÌýãÞž–é„¥Ji‡7†ÁaBÇÒËo³—õÈùÀ£‰·'°¡ðÆRÀ•2¡/ðÂð±—åoL| âBùDæt×t¶ÉÜ‘’.c’ƒÀÝÃx¢þ„wv„@Â×è¼S.¼+ûƒÍ)ðݰf°À›K&ŒÀ­ÞÁœÿxc:…n¨!&®õSèfTcK‹ÉE o_W,þ¨ð]¨õäÞé†÷–x£-ÕÜÂ+¼‰ L2 ß)tã9ÆïÑOðÀ{ ƒVtC«ñ ’(5覂Ë]¼¦t°{+v£ µQC9ÐÓéì†çRÑ,"Ìí@Ñ͉–ÇèÆs- “D‚n<‡Iäfè» ;X·›QŠn”¤=$[:ŠnV‡50ã.ÝìBâ8 ;0J D¾^Ew°IÑÎt°;p `uaÿÙÙ‚M²˜KHÙÍWbÂÆN¡›£ܵT•Ýx'¾r-C¸Qv£ŒÑ%Œú„Ýh&>fëŽn ˆRt㕘ïm†ºuż°ÉÝ*ò «ÛÑÝh c°ºmåŠîJãn¶Ü†DNð¹½yuþÝrSQ‡Öäz8É­âJnæVrSóÁR>»>y€ö–ûi-qd‹È<­%ŽþŽÇà#äv 1tµ #’›Þÿ\ã@@Ò°"aÈ·C¡cMe@L¸M×?ú•F°—re OLCšRnÓIËÒd.få¶£ ^r‘r›Ïe0¯ £‡p{{nå6„ƒ©µÖ±±®ØfQÀL©C™Ôvfò(qœ£ÙL%â{nw i‚~oËM°M÷r†ä@>ÏÉ«ù¡ [Ç' =¦iKHÍ"ìö3VIH͈OU¹œf0IÅîU.J;Õ¡•-}1ðv„9Ƹ†ÀÏ™úÅÂÃ>«û ÿÌìÆÏOÇ^©¥ ··çɦѭí§×}ñ5áÛO¯7Aºlƒ®¿¼ ý=ÿÊpl¨ôŒ ’n' Þ ÀæÓB}#ü9…2YÙˆ{ǤŒfed25+ÛÎ,Ñû8ÅõBÍrruÃT˜y8¯™}]ô[ˆ¸}X¬:êŽC&‘ <°Ð£ù•K^Ü„G‹_23"Äi |k†®1ž2}Ù„ÒméI<å4UkeYõÛX>Bå‘X7ÊðÊÛÒƒ®¢Í×™¿RV7ò(­Ç¼± ‰Ri!˜º#ÝKŽÓ¢Yª¸•˜-\6¡öYàû°ôD¦¨Ð¶“õ®‰e’îo¨V~­ .>d¡zãÍã_Úˆ{Ÿ† <ÝüÒÅ0)F' ef˜–1®–> “˜xž. {Y¥þxÍW31†ÔxzÍÊÄ4INÐÊiF„Jýñš°fÅ„œÎÎêÅ4I7Ï9Z¨@õ»mÒW|â4ž£¡øš°x.2뀷©PƒØ&Ù@T2{g¥yMXô™³:’Ô ¦I†ü£0™¡ R‹¼',žƒÐWx$ÀÊÄ6IoTų–D1MFÚàl]±,‰i’†"@|Ø›jÓ¤÷«IL“ôû1àÇ|{5‹iÏeLôhöküýbšdà=ϵçQ$¦ÉÄóX”‡­¬ˆi’vÌ_óuÔ"–ÉHC(×øxL,“že{ƒT­b™ Œewy¬Z·K©ñTœ‘¡V1Mš…Îa mS9µ?w·³ì­xÅ6­éŒÚÁsr›3šûmöyVȆmž£å6Wá†mzƒiòí‚ÎA¡Ša,}Á6ÊB¹íÆ‚m|`š@¹­ŸØ6—%…Û<5Z4x(ØÎÌ?ƒM¼Ž ¶3#˜®ÇÕƒÛ(ÃîÒ¦/]¹Íí¥aÝ7;%¤ÜÎ>ç–šE^(·sa[BE¸³#´«™Âml!˜Ÿ~º£•Ûɼ8Ø'€%€ó¹å7ÊДvm!îD“ammD )¸ÏjyžÐO¸·]w€›ž9JPy,}7>0vSÎ…z€ÏAþ¿ÌÐ n|ü–°§ž‚›áœ€³Ù{wpSÑ›/ž¸36 Æ\ù±Q¸‹eÐàq¿¸ƒ›ãQ± FÖw²¦4¦b9Àïf¶ßO¸ÍOšðѪ¢܉çÚÜu¤_Áx·0¹“?Àë<`?¦‰‚;ÓUË#nõ·†-¸9Љ^žAK7þ.ÄÎL¿„•˜Í%¬ÈÎÌJ㯤ŠìÂhÄ‚NçÙ²#¤.g¢£»B©aˆÖ°+±¹¸‡á;]ÄÎt—D†—}éŒé×ãÚ¨ù±‚h3w€«LêaÛzGöJ¥6>(ø”†£|£67¦Ë¬Ðný­@Í'©Ð;æ\`kŠ6~­÷¾"À®s‡)`ã#抑k<€]ѳ@Ïï|n6(ìW ñvÄÔ L8`'KUr¨T`suã€Æ|›1Z Ócì l¤³cO'¯éҲмô¯SbüЧ¸Æ?ÒŒž=pÍÄ3]džkîb9`bŸrv¢:à¯óà®U ‡¾”×4í{JOéÀ5³ÎxzqÌ¿£¸FF¸äaÑP\ó¹B¨Z‚k”1² Ûi>px˜=_ÛŠk~ú6G ¹âÚ××9Ý ×žªö ­}øšÇF¥¸æÑìŒÎ´OpÍ€hlnŒŠâÚ1†ñ ¨Øpíèì¾ò(®äWo‡žâš_ヅ#®·f ®™¿2Wª 'µ“EÈÂcBµ“…„]â¡R›eîÔ¡µ· !ØfYªmº­Û±Ûš@†m }1`ÃväH0XZÅ6]´O Å6蕬öñÛ {YI¥)­ØfP+-GéI´¸×G¤r›‰µ˜ p(^Ânhüø@™^ãƒÝL̈TGŠ e7‹àuÜ[vsb Ç.ÚvC]ÊqtAØíÍ;|ù.•ÝÌ1áó2h*ìfbNì>3Q²Û›…0æKj^ØÍ¯ÇøÚ‘xCÙ²œÒÈZ°Ã›yK‰vxÓ-„Jc·x{3ˆ2õ`7Š<Ï\ûi‘æIåÌ»=ÓŠÐL5™gQ|Ž0(»YFY4¤ÓF¢9ó”Ý"¯èvßtKÅ‚nÇNrûOá@·cÂ,œÙÓšÀ80W/s*ZÇ0£[ÚB ë×™«WÐ,jÌÓ««ènÌ™ÂÓ©æÄWt7Þðsìtã3VV6ù%让õ›/`‚n&ª-¼5ľ¸¢»2¯VÖĬ ›ò¯I1èæ-W©£÷r¦è® ÑÉWœ„¢»ZJ~ˆ'7E7Û™Ý<è'䮌)×]Jîj¨¨Üt³wÓ;†ƒÜt¤;划»r&1±ð$þJnlÉÁÓ#o™Jn=¹ªäÆa^læÕ™äƵÞ÷z)¹ ¶–èè4<É]h¯N<úÖrz"RajæƒÜ4lwFÚX”°’›YOZ›gFÉÍN×ÜJ´ZÉ]í¶‘0oÍrWn¸çÌÀ¯àÆðè¡7€»rLÑèfÁš n•–Ü…nwW|5Ç´‚½ã±Ú™ØIÁ²0n4ʸù…R½¼ nfMÁ›h“ÜÁÍõ÷dƒSpóeü4r¢)¸é´c:±áˆPp›‘‹`¤`SpF%óxâøèî´ÕùsÒ¸ ‚ Ú ¸uL匙³yÕmúòUO_³®*¼=ý:$Q/;¼s3ÎŽ ¼·Ï rw¶,Ñ—¯ÊÝÉ8˜­œðΜe#Eú!wcÍÒ‘ßÍC(ðæº`ö€qe‚Â[S)¼5 e“»-™Gžw)¼é¾£çmDï+¼cáíFiz´Þô¦‡v]Ù£ðfò*üÑZ•Ý(bî“™ÙBàÍ}úfçGxG» <ê§ÜíÎ(¼¨ôÖ4&JïÀÈK^Çe‚Ò;Xj2È7€BoMQ¡ô¦¦¨z3 ¿AŒê’Ò;ÐÏìÓ(½QFßsQÞJoM$¡ôf°A¡Ü6¤A¡7Ï@(Î¥w°;ÈâdŠÀ›¯Ì®MéFà­'”ÞL¡ñlï`ׯ@(£(ðæ(bä4%òª B ZYÇy…7¿(}ÿml…o”Uæ>ÙÞ…õ•Ýx,1aìæß|ñ¯z~%»±þÊ¥äïì®4çʆn†7ù+í£¢»D~d7Ón*º™É‡áTib}E7Ó¦ðÐBñ@7Ë:wW‹˜tkÂE7ïƒÁWžI-6“‰'Ö±ì†ê èvü(õ‰YA·^ú¤è¦Q!ñ„Èh¦ Ûóâv´d¤ÊRtÓyÂÔc5+»Q]¡—wvó % Mm3™i¼x'†ƒÝf k…ãÁnM¨ºÙL<ï[êX|å`7uo~†‘wDÙͤ—ô¸Ä¡³ » '´ý!v;» 0v;Kb‘ܘBÊnFŸ4^^šNÉ›Ébý »xÃSc)»i°õ¼ktZØÍ{.ã' WxÓÉ¡bÖTvxã±D9í´˜0d…EN‹‰Ë F‚ÚfyÊn–y¦ïèá`7>!/âY·”Ý(ëžš± »QÆ+Bʸ@DÙí˜Bù¸ÈDÙÍú2/_te7“ 9(‘s"»ùÊÂS„CåvóJžJ#Úø>Ân–yÊÁ£™Ân”áwÈ fôUvó*Ÿ0=ŠnM½£è¦ÖÝÂà4˜ðÈ£“ËÅîAà©2L'Fÿ9®Æcù‹1Ÿ×ÿŽ '_Qwï^©ÇNñ5ž‘p×yùý·×øŒƒ1Ÿ9tƒv7Bû ±öz ½þôv,vy¶@~ú4"ÕRõX"îörøÐ”=˜ªÿ9…¬Ëö&Ä+_ð‚ÂëËVz”mZ¤ë¶‘«§¶Öüxµ³Flõ¿F°~[Þ‰}5s·|qÈMª’!—šßòá [†\ëÿz$==¼8ò–EA¾I°ÕòV$VóJ$ÏaŒ¡$´öK‘i#ø—×â°ìª%Î,ÙRì@;»ŽbsM;=è2/íÌyÎü‘Ã/€ÂÕ#yåé}L…«KŠÚ'fm¸&þZ*SkÝ¢8 “eÏä%Èßx eÄ’ÄŒðÒº(ÇÚªÖË(lvlYPxØ Ž[<ÕÎÂÍcÌ5 }à ”-êq ;Ølqº}ÑéZƒúh‰Ga²šƒX?üœó  «åÐ$·û"ÂåÃô–[ðÒ8hŒ€ÒÃpVxª·ŽÌØd¨Z×á›þxe§ß¦Î<ú£µc ¥ƒs­8&¾½Ê5™W2·unæ]ðv· >WážÀ솴é—¸§Y`z´¤½^Ã<-¢lé$ï žæ³GSîÌúïð%ÌHài ‚ânñöÔžñVw½·û×0 èÅ`ú™@cì8µî2ÏÐrªšºåíÐÝ5=IÄ4㬧Û_ó˜Wº6m<^O®êr·DK}žÏó–îú9ÿ…Þÿ…¼t`NdúH1î•YfFaµÜš6‘}cŽþÆ,ñã+–Ue&°ª¦™ÚóÈô­3ó„q§ÿ1žP½&2}¯Ûì8ïéÍ%y+μEÂÙ[Gc±°ò5“™"·ñòˆ€ñž:é5“íŽ]Þáü ¶ê·7ï«CyÎlQž¯FçJ­¥ZzÍdÝyûæ·£ÓŠi.Ûœ}ÕŸYÈ žÕŒ:Þ&ï5“Ù--fjo‰ï™ŒBN›<îpðf|¼­€*­´fE÷\Ü ]™Š32Ž*±²â=“ñ c ÆHêÂã»vç˜É•ö ÄHË9EÄ6Sï¾w°žVá^G¢¡ô–s=öv‘L@ÏP&»lpôOAO3Ñ5÷éy0s‰ÄßJzËc‚!½NÒóƒÓæ:ϱ éI|^ïÒs©‡zFUÒÛ’Äwí¥ ßÜw z®ŒõZçtÐ[!Ó»œÐÛªó1Lß³‚ž ©1ToöVЛ¯²µs1/ çƒÌÕ=s«(èm-g&{þ=—kž ¾¤ô§ŸÑž0Ô€VÕø ç™F¾Døü„ó<ý‰¿¹ôNÎSžË~å¼=íã8Xþb”ÂŽúðA#;sѨ§Ÿ#—t‰V‚z; ÏÀŽò‰L¿o‚‚ú-LhC}åA¦›öŸ žMϼ½¤Ï¼§‚áŠÊBz^ë驟 ÞÖ}¦7#¬OýùûvµõÉ®Câý§PÏ‚o›‡{c}äåœè“sÂúhÉõb 9ž¬™·qåT¦¸»²že50yÁ'¬Ì’ì¹ýô“õ‘‰Y°Úkh'ë¡ÚeÞ]§z"¬ç—¹´™}c}´˜UïFÚƒõ,±±ž>òVêÌ+r±ž•9ÞÍÒúÉz†{[ïgb}`8Øm´ÁžæË)ÞNÚSrŒƒûL¬ pºc´6Üóˆ{£<ë‰{†n0ÇLßqÅ=x1ƵO¬¸ ›LjÒ‰û`W]·}m¸×˜„ ÷ûè î5ò`Ã=Èöß©-´=ž!Ýñ…î9z +¼æS¬g7;3ÑϩӿÒ°ñžo#tòž¹09±¦Þ«¼ç¸Sø;Œâ^Ct6Ü3„Áñq¶GpÏ·f† Œž —ÿš’óŸ†ö´%˜s<°ç7Å®æÝzìAeæ½›É86Øó°pgò¯ÔNØÓÃ4+Ó #¬÷ŒY ×=냅˜`͘ ìƒçšÄÎ{wVØ{R~òrZpXX¹ÉúzZpÈ˺˜öSßM'§ÀžÙC9ê'‚= CŒ=ª!œ°g(}Å.â?ƒ= C2›Â)ØóâÒê\‹å´àX¬V(FþÁÞ5¼½+°wÌÌ(œRNØ3$ _÷ƒl¬g‚ˆœ¯ð±õŽæûÜnaRXBÞc A½/¬Çûð‘®Û6ÖÓµÏËhÃRa½úè7Ö£0иUÇ:VÖÓýMå,ÎmPXÏ›”Ñìád=ÕWž<™B„²žíÎú§¬Ç[1Ôî²E êñÒÎôl墹D>0KVçgõD= C¼o‹ÜPï˜òo›ŸXPϬ3ÑwÄõ¼¨†‰fFâ õŽ©KhoŠŸXpØZš>³àðš jšãÔˆz>ˆ•<³çn¨G•4Ž„µ¡žV̆ROÔóIFsw×NÖ³\ú\NÖoc ¬çk¿ó˜´#V†1U‘íýX$K~þ‰äI¦ð_ÁâOY:þõRÄ'µ¿âšýøyéÛõ`혟?´pulû)›×«•׺ý¸/„wm]c«?½Þéòöí§öœÚþ Fa~yýé“&ü¢ŸÎ3/YÆ0(°ŒÔ‹¼èüŸT`F ëæŸ^×ëA÷š}èðÊ'œDx{Í®ý׊XF¬waD%`¯Ð½Ya<{_ía<{_ëá:W܃·÷¾¡UèÎ _ía<{øÞ7´ Ï®ßð—yI))ÍúŒ‡äṩª~EŒ†V’!7Wfôû$ùÙ¢~]-÷žûÒy"êÔ’~U-¾Gfö£\èÎ{j)R‹%b²-¯‰~ç>œýO¨ß~·„žœd-ÓfÞE•‡Êëa{žaï(ëÞl GÇÒæ%©ù)Y]íb HÃñZ¶du<²- ´ýúÜæ©ó¦ëÔu fæ6‘ù4/íÙyRÃ"j£²ëW_yL‘1ƒþ±Ìj˜ë5OO-&ÕGœ??W¸Æ(}aIÝʲëïP—\ù²²-™[YdN˜GÎV;®h¿>c•¼™*˜íE–(âzdžÑH÷‰ôFÊÖÎ-,ÂÚ½ž—”­,Ž —;[ùóRQæìâo÷qüX–;[Ù°åË”%W«Õðô¿,W¶Æè֙꒫5ÒþÌÐP—\­#-a¨Ëe­üó¸ô±-)Z·QkËe­{ Ú’¢•eËcý¹«%öË’—•¼ÖÏÈŸë2áHC³qäҺï‰nÉÈÊ"¿µûã°K_õD¿äceÙò"—ÿ= i\ÎKÙ’•Ï=S'òz›ëa>¶L–|¬Vv/9þ×mkà¬-avÛëaûÃ1qÉÄÊŸëúH3ØvÕùÝÀtüõkA"ÂXÿÌñ´¼äöþ^BÚÈÓXKÑÚh‰ƒî"á,VP_ø¬œõ–äç.[9Ë|z…³ñš… Z°×{– myÉñ³·um߯[^rþ=Þ¦ïðv6Mx?žnïyxð¶È’VàÖaÉ݈«½Qä®KQ‘ËxíR¥l¯N=%0ïçYš)NEX|ïô_Þ–°´b¥¯]C° V0ŒIþìCBaí³¢˜Sý;(æý Wsš„ï ˜c<V§u¯Tó®§Bb^©tiq¢Ï9 b&&x>Š‚˜º/e+Ù éÄìÖSSø,Ò7ƒ8Åvät´cCq„4|5*…{]V±R˜&û¥h…p‘®Î7eÀ¹®š@8‹8.ÎYI»Rx‡|*ôòâ®ïA8G)çøq’8§ï’˜ Á 1žz&‹r˜/ü„ÃŒhY½p8¯ßB9œƒÐL@œï­EœEÆój¶¥ÈL¯ØÂ=A0o•Ê}ñʵ+B_^ð¶L蛓ìlB_~·g¬¾¼¾ê{ðݦ‚À7‹r"f+wôrl–Ö zù¹—¯ ìEVyPØ+ã­ìåwyH¹²7'gWöb˜‰FÑË>-8ör¡-¯øÞ³HÁËQ_˜¼‚7çïKÀ:Š ÞœçÊPðæ©)“ÛµzÞ £P󂻴󶸩++po*lsY÷ÌͶP¾K[šUîÞ$^ÿ}‰×ɪâbŸ‹½Lü²@uå-ŠV%O€dF*pÃjˆQÞ†¹ÊV܆´ 1‚Û­Â[æ‚Yº+ÀÙeàŽÛQ?./ç|ÆA€‹®Û•7„uøº!Jã…º!ž‡ R¾Pwk‚°×RùçÏÙËæ \ vùȂ֕ºv7kÿ\æµ Lï/%Ô U!Ô Å.o] }Ã**|ƒ ßj~¡MMamäfƒˤUÄ5†›ùAZ¾™â÷Á;Á*f/¦±:¨Ô­f¿ŠÏjuð+ªÕò¦ l3:ÈÚV‡ÕŠùå°Úå‡C(—+°€ÿnD;÷bXÃgµ¿â£é—ýéÛõ¤2¼÷)££cÛO¯Ç䘞ÛæØêO¯7Aº<†}ûéõ°éòüòúÓ„5DÇhÈèÑúR¨Á„5ÄÄhyžáÊÌ…õçÖð¬Ù‡¯|Â6¼>±ô§XvÛ†Þ…Ñt‰K…ï¹ÄûÖ ¾èïWXƒVøZ׹➋Þû†V¡;+|µ‡ñìá{ßÐ*<{ø¥°HÓ´CX¼ðka ZÉ[a ZË[a RË…5üBÜ@ä1ˆ‹í™2ìÇ ø5nà_þÇ{q±‹bßM”‡Ôà$r ¬¶œDÍùÒ ’_:OrË}°ö“¤“_®‚5{Å#²3,Á=^ƒö1h°¨ž)H´@XDðÄ“5~ZTyzZ­#ÅåâWú|f[ͯ{ ªô<Ú“©QŒl)-w¾ÒYµ49©k±¦$~¬¸Z((†,~,„,n,¿/¦½U'zîŸ*Ë_ò±G£Ke¹ðÕL%·æ”˜àúÖœâeàIU”ù¾XÙR/–[ ©e¾K››x±Üªj¥&ʼÔÓD—Ÿvê¢Ð‹÷+uÑèÛúÊ. }_=;‰"XÏÎg'ú|[ìãÙ‰:ß–Ï‘ýªÍ¯NíìE›‹"ûåvW8‡årW{•ÍåDƒ¯‹:ÌŒe÷É{Ù³$™ÛlÑãë¨=>÷¹ò·1 rÕ½­öƒœ–«\ï×$ÑÞWxðÒÈEy/ëHååW«}imí½®Ÿ%/¸ª%Ï6Ù°º`ÞŠPÂòÄ× X¨¹Kø:n¢®ÆîÖ…+lMkØÏ†Ö´®6ÂÊÃ'0&ÓFײb¥,Þ%ÈÊ®ñiËb–Ú@› ;hWŽiÅtv™Bi/ëþFY±èn”-‚R¡ì£”åY8'˜åa¯ç±º ¬]®[ÄÀbJœ¬«q{Cm“¡m[Ä€`x‹XË„µqcQÔJˆ„¢6ɾ¨¬åm²7ÂYqt+g¯(A¬F (cY0¯¤å»¤i“¤J €ìzŠÛ$ÑiŠÛ4ý‡Â[Þ ö oyÂ~€^P›$ÀO‰K)°åãù\ik§=² ß|f RVC ³wôÀ‹BÙÈL2á Ôª‹sCmT1W˜[e¡t{\GO©Û½–­ÔmWè›·•O€ÛdÌ…¸<¾¸ s.o00-Àµ<ù€mî߇mVº¬°ÅX*°¥óïÙ”„µ¹^»‹°6—•‚Zu_+k³Ä)ls¯¬Í²õksD kóä;QËÖÝQÔ²Ï(iy­Éò””µá,Ц$.Œeo–Aè{\ÀC9·…,Îf‰àSÐ’ PµÒÖ–> ÚæSžÕf+f9ª ¸…³y®%,]%„ÝjZ9ËŠÊrœŸ. iuz(iï† i·'„´Ûˆå-@ž[‘«^ôa¯*«Œðb`€J·î‰«Ú¹ÛÖ˜:ån CéàÖï ¹ñÒ>µ›öì·°€uQ„-.`@×òs|*å†*’ìÊ\ºzW3Ã Ý Q%J^”^ sÃ#È ¤È j±É{`Àó%òpáxenXC¹aÊ [<°·ÐVœ¹›Á׈f Úe>Hßi%t`3„ƒ¯Z¥Ú ľ٠nÓ–Ú ‚@Tò**ª½ ®“b3ÄuËU‹sn&™ï›åÀÈ©ÍÀn3+‡Ú ä\Ðf3¸S±\›Õ@ô´ÍjàW«HÚ<ÿËrߌnµÀ¨ñÀ ,Õx >þÍzp7¾„-öâË®ÿâ/Ç¿ _ ÿ5\m,}ÓõÿYíoø1®~ü¼ôí•zÚðp{æÛ~zÝï^óáúß~z½ Òå1ìÛO¯»þ¥ËóËç_íúÇ&I•õtúi^uýc'ocáµ8áÏÉõÿ¬Ù‡¯|Â6¼¸f—þ”gR¼ £á6Ö _s³Âxöð=·±Uxöð=×ÿ:W~׿UèÎ _ía<{øÞ7´ Ï~Éõy“Z‹¦W¼æú×JÞrýk-o¹þ¥–W\ÿ‰jH %YøúwýCz_ÿøÇ·ÿ…úñu}^JŒä/aõIñ Ø[ô.!?ÉS˜6êVw¿_UâW½öÕ:Xb~.xŒ5®y‰«Ú^VÏE¡^<³ÆñD좡k‹Ö^äw¡bìfÒ8–-JsÉ«â.VÇ’ós½ãsÆ‚é•Òc˜ «Á±1–Š·¡ ÁwÎC:4Ý¥”UuO«O´ðÊóÅ °¨'¥®š{JmÏŽ|`¤¶*îi½-msI­ªµ'¿!­þë°öUs§'bé³Î?±Ë”n |ZCå+5åk.ZÑ=ª[xV“ž§Ú“ÖEÏT©^ްÆÅôT½8¤ÖÄ•jò=/y€õíÄ!µD*5æk^&‰Å¨AœR~m=æ{Z¦5T½FñL‰*_ãîšZjK›ojöšVµž.Ä[­¯iUëå8rÍ«Vûb’«yÑìç¯Z½ž]fΔG««W¢–U«’* –U«¿k׺jô£SëªÑÇ5J¢ÖU¡b"µ7Ê‘™·”¼ë­¢;‚o£Œâ——ª.X!™”üþ² á–S—2¸¬®Œ Ár”DÖTç.‹^Liái£"Xù£ ž¦Æ Á«wö ð@ÜÎÞ•¢ÊÞ“¹Uú¨Ì•¨™ ½âdØÐ;Ba6ò¶ˆx×=kïÒý»ËT˜Ø]]…vÝê€?¸»®Ê¼+'•¼â‰ÞÐ+ÿ½r®MÙ›¯4ånX—îÁÝÊ]¸E¬íSîêÜ à¦õô”W·G%n’£¡‚Ümˆò°lOe‹ Xöݲ…¬ wë›ðW÷®ºå Xà¡üÝúÝF»—éòb´€"Ø·%}€˜¡VÏn¸Q¸­ÌTIX"…ÂtY­¨](œüšì5 …-ùAþ\¦?niþ áä‚» „é·[X á.áŠbÞ¦ò¼RP\‹Pzåq•}Xy\WǸp¹®>{År]íJå*®9¥r•š çý¹•Îw…‚¹W²"™}]òÁä*Q åZ„×+“-£uþœÉµŠX»"y{L\EZ"×5xTÌ^Ú¿R™íX*TÖ7 •«Jt‚e”-$*׺ªÂfAs­“å+”몄)“ëå}ó¢§7BcÞ]´@Pp\ëám:†«¨ŠáºFd*†kù>†uj†kù! =x`“„ý÷%a/¾n1oX-'$GŠÃù *TQx“@EÎ^Q»ÈÂóà‚ Á).sUe`J mDN—„£èMeã½Ð\fg»øYì +wãS¨ÈÕt]ÂܘUÞÝ£cyW¨+éºQÂ㺒ÂP™EèîJ\¾Òw+º²K¹/ÿ¾2WÓú)sã°¢ÌÝŠ$w¡»êÜF ¢VÞJþBÁmôú”¤/\=éŠÛ§ BÚèä !XC|•´š‘PQDxØìnù8›Ýa…V»ƒ ¬ÚÖµ§Ð ×ÊWð2³Æ2zÞ {œ€—Ù ŸšÔüàVi[¸Ë쌛ùAúrTAcÖÈ¡íÜåK³?Ëߌ+ø´þ7¼$WG~^{÷FEÝÅ=²`ûéu·>fËY°ýô~Ö.qß~z=²@º<› ?ýHdA&ÔÐl_»¿à" Š/–§k®u†ÖJ~X{TÓ¢äéP­«–/Oñ äjuZ;ÔÒe°fÅÀokAXí_½»5Ò@BBzO«ª¿†Ku]íNëM(¶ kÎŽ·B 6üÚšƒ¼r²UÑË›O*¯üŠŒÀ PxVP8¹"Euõq‰qM Üeé+‹û®P¸Ï¹Šá. 7I¢nE™ºb¸]wÃ(†›ÌÅ0  Ïεb¸ÊÕ4ŠaµÓ+†±á-sO0LŸÜ3ÓÃu=ZªOžR¸^‹^ø[ue þV‰\RþV±+€«ÑQ—õ–%pY£ŠÀ¥-‚¸´õ…Âß"sBø[š¢y0&ⲡ+€Ëz–T\òº# Ëš0X\®d á²&½V9å®.k@¸È& .¤ Æ ‡©Uù[VáMù[fl©’·¬Ù¼e½PHÁ[Ö,¯ƒ»EN½b è Ëîº82µõ²²wÙ·|&ü®ÞƽQ¹,ð•-QEàº&Óø–M8^á[Äf® .kð‚¸\çÂ:5ÂÃ$)ƒ³„*ˆ³Ü ¤ Îë].b¾ñiºp8_IÁY´ e0Þ¶¬*ap‘3œ á|eÞQÑÃE’ŽL óBØe} †Ë†ÚÃÅës+†³ìT‡mȯWön-øò{»ïÀw=°½±×­{€¢×­®Æ½k¾³½î¬pWߦðu·¸,à]“ÅlÜõ*¯àÕMTÉ+Ù{6òJ˜ã†ß5¬~ÃoÐ ƒ× eƒË"Xm ¾ëMþ®!&/†l’ï3cvñ×õ¹C xÍ"ppwK>¢V‰jUÓƒ¤ÝØ,’ÛJ-ÂOÁnZ³à)uÓ:ÀJÝ”ekô¦k£Þ שçÍø —BmaÐfÓ‚ÜøpuÅmaT Û¨B­˜²µbvÓ›Ýa½Ke3;D5IˆÙa+«3¤`°Ôì°&ÀÚÌ2¦›ÝA"ò6ÃÃV–4º œØÇþfr€]59#…ºa :WêÊÕ… Ýp ºze¡÷¾(PaDêàJö®æŠàҟԆɅlP5@ ÚweÜ Ì)e÷²³¡_²ñJXmÄÀlqäË¡ÞåÛ—oRåˆ%áòÛÙ¼Lðy ÞqŠä;œàéà+510¨Ä¯Îm¿½îÍZ‡ã<äÞîFèo¿A#Ö^ÏÁß~{=¨@{}5Bû‘°‚êiÉj­0ÛλQ•iW|/¾uº¯þ|¢ Öåû â•¯xÑáýå+}Ê–]?]w¼Y¥û¤Ê½Òù .Ð*ßtKç+¼`«ò½^®³Æwã].îÕoiUºOª|·—ñ“^¾ø-­ÊOzù¥ƒR̽ ¦üZŒÁVË[1[5oÅh5¯ÄÔà"46èG­ýbŒDüËk Fµ „%[>’å4"qB£ $û«g±—ÕÒš¦_?‹›«Ë#P"Š©¾šQ×OÓuiˆ÷±»qžLžY\>ÚoÍ-¸VeExŒ ïó$.ÖV=µÞüíºøºäÄ “¥!k±?F*Öáâm—,“ž‚Ì£ô/wÏYÙªô÷U¥D^Š$O°5}©_´þvÝo‰ŸWµ¿­1î(«–° Vög!5º9ºq¤Â}ô:ŠÃkÕEQ&¯vÝ[é©]£!\:ãÄÖÒ»É ßߨÊ eÃé%wŠ¢WÎrÚì´\³¨Öþš˜tŸ]?¯j¿Øä½Ï«Ú_EíG!ÞwÍLšìûú`µ…6;̓6¾½/«êߢ|¢Þ.©‹8¾¦¨¹»ÆëêæéZL=({«\‹ÂjŽÉYòbLôžŸôž %_•5±¸&¨&fW-£²}OͲš}P¶Ú]ƒ a»«˜}0]V8¦gÙLñ+„ñ{bâ×u8‚£«¬¬àÅêêçÔžÂý5/é&[F¿ÝU8&¦ºnüc3{+Þ`ƒqzþ,ŽõdpüƒW·ýÆ`¿óØ8ìı¦ 6>Ó}ò–\‰ûê‰T “‚kC…Ç­kˆð¸‰irƒr“Ûn•ÉÍ]à×õ|ΆãÚdb¯4®Yé)H®’âecrÕé­P®khÌÎä ¸T(‡kµ+“å~˜ Ê¥k3•A° °+1ͤÃe®@2—"[‰ŒZ§ÏFæ,/U2¯¹´7:³Â‹Ú+™“v@Éœ6Ê Ÿ%EïÎçpïSŠæ ]S6«| €öwóÛæ«ë¼Q:o[\ßÜbkK”ÏkHÀŽg¿X(íÄ i‰ƒÜ)í¤©Êê,«QQ»6GN¦¾ž°‘:.¹T»Õ’½!;8©«ž¾ùTÀ"’íJn“¬òÉìMæh—z ãÂë"N¯ ØšÁf#vñ[áJìíƒ+±s Fˆ%iÌÆí,Æÿ ÜYÂA•ܹHî\{e6o¸_+f‹Ërc6ï$Xy.A yÃï îœ/ ²gê¼Ja•®…ÛšÞ~ãö}§ÄÆlæpËßav.Úa¶^°A{Æ{o¸ÎY¶¼Ù¹Èþ+ÄÎå–ÍÖyMŸ±±:KN‰ Øû@ °—‰!°Þj`/ϫ󶓮¬Îí°:¯7¢m¬æKŸ¡RT_úÒ;O…ÒYDŸ Ò¢´òô"d^âô£U¼ǰq:,À:9­â›€šòîjeXAÍp¢N³l*ÆŠèTÔ¾  Ny“ P§ò9¨Ó›¾q:‰yA1%iôžØ0­Ù6NÇôG8͸èïÉ×(Z¬˜¾é7DG¯­pZŽÆl˜ý^Ž‚èý™ÑA!4ï'üž¹C}æ¦o·ü†hV¹ƒ :ÔÏó7Á²Ü¸Q™æ“ÇÏÏäèÔµ9T1( ‘CÑçË!ËŽ"X*w(–C9i6µAt;$ÕE˳¢•ÆL±Ð]`ÌF¯V¡qÈ7qW³Ý+¤%Ð!)p%Ð!ÿ‘9Hœ ÇáÊ\2PÒ„”Ý¡xSÁßýüo:ã¿þÉþ•½ÕŒÒñ¯—Â>©ý·ÌìÇÏKßÞ¨'¤qå@;gǶŸÊsìô¥+Ðý¸r ƒרêO¯7Aº<†]bX÷»Á Òåùåå§Ïšð‹>&ϬC¡V¬dp5‚C¥Gÿ‰‹éW†6G‹YË~è’rU¯G6Ü+öaÃ+pòàí»ög\ж×wQT<»¸bÇÑ´Þ§äEfº1ýYûSðþGuOÕ{ƒm®ƒ­õ¾=Ø6u—Á–ÚÏÁþeþPº)-4R4¦pFm-ÔÓÿüãaRIlLEU #6Oß÷£ç_WK2csÄätgäÆóáèZÍ¿ù ÿÍ’—úo÷ß–Ja×þ2õï–§-ë_t®‚L9bµ˜_ô×—sP-ûwy4æ/ÿâ¯þúoþöh-a¶ç“r• å<Þ½E71þ³}2~ÉWð_~ÿ÷ïå+ðu¹Îé÷>Š‹.’mÉHXâ0OAÖO”ÛÈHè°Q}+‘‹ qö ï¼N~dÈü¡$ÈÉôîMׯÎ,UÞCQP[5y¹¼„viDfʱ€OU’‰ô}ÉK˜yhÃ'hqÖ–à–Û 3=¦›»oÝÊ–ü„Ù|œ1¥nõ÷˜-s±¼=¥Æ;óï_¤:ž):ð<åç‹•$…ÎCàiPgRŽèüHR8áJ!;¸ÏöN^ÂȦ¤ì­ ê >…³¦„'ŒŸW´µÀ×ñØ’­0›™ÒA=ˆË=‡™G+°pѶQ¶¤+<ÊFºBWª7,õ‚–¹h]`öh6%º±q°¾†Oeexç=dÔN+4oˆ!„…é8X–¡•9dyÉXheµ„8$±—kYs(Åᤑjü]®¶1Že¹ýpYY²² ?”Vœ5¾,÷ ‹{¬Žª5Êê’¾Ð:—Öf÷'†º8+­,åªËV¶Ü†È2ÌØ†²N·%‰¡µ3£dŒG[®CÌ9àï ZÕFÙ’ÅÐʰ:ò˜•KD Kr¼ö²Ð—D†,òøÛìLåePo®÷DWQŠŽQRPüœ7Ü.äd:„¥’•-© y§`#½‹}˜èžSÄ,â ¯¬Óý9w`áò Fd*Èg¾â©ôò[±lÉfȦ@a‰@“•ÙÝ‹}ÜÎÉç8̦›’~™X’RîX2£lÉhÈ2,F, ÂQ¶Dœ×,‹ “܇% }&+yBÐÍÊšéås²2;X·¬¶cïÇ›P§ä×”ó¯…(µE² øNmžŽÂ£49Ô¶d+¾C›ju‡oã AíâØ!vÀµB»8ZÒCÇ7 ;´ Cé\bqÞ¡]øø«ù¹Ú…‡xL†´A»Ð\ƒ­Åm–yìXŽ'´;ºÛ@h£ ÈÀÕ ´ÑŸ†YRmí³¹Æ ĈhöevçîXÝüÊìN#þ7Õx0eŸ$Ìfw;Ñ.”~0›õµgKfÛí­X<Áæ§2»3¯g©0›e%b¢ì ³Q†ÑèÚf³ñèNõ&ê+³9-#q:íÌݣ¡)ÌÞËVhsGuþ€6ŸÃÞçG¶k¡6‹V¤žÛ¡ƒ7mX¨­=WjwžLÃîm[„B›EØU°••Úî ,ÂîÒm6²€yìíÎûA¼ 5´»¤¼ä…öVŸ`›wÜÆ¨Øæ;;àŒæÀö^¶reØ£1%lŽ)·Í  ¿¸­¯z3aE·U›Æ«wf¦à `>ÑMçLÉãsíìÆWö˜Gs+»ÁR ƒ°7乚 ²¶Càîvh±ñ´Â!p[b=D9ž·Î$¸;ï¸ÇȤ!,‰ÀÝiF ­'»yåú#!*»mX"$¾|²›b.§x°ƒâ`´“ÝØa -tÐ÷d7›‚´ÁäžÝΜS„v²Û¡«œù§¸Íë7Z½öÖ ÝüÞr¢;ð›7`à·íÐ1vX7DxE·y>]Äf¸ ›^ tÇ»z¢›Œ~3­lC·Eaúžâ)noc%ènv$<Å–ÚnÞèLκ›9#åÕÝ|g )Òîý¹Ý(Kƒø‡ÀMÿTÂÍn–AØHÃM£ì¦ÓRõÔB”Ý|/èùÞ-bbJ¾¤ÞìÁôÊðnÌ„ÓðùOvo-v7ºï‚}½ƒÝxÊo*~–­ìFY……âd7˺‰Ÿá`÷^¶²›†¡N™e">­»ùª=ˆþÝØ»}ÇBš…]ìÆÇÂ^2MoìæÅíV–’üÎnÀÚFÄP·¶³Û.|ÇwíqDVvS”Gw!›§ƒÝÉüõõ”ÝtÒ • ôÁn:°“o〘 ›y±œ8ãt3BètÛM÷ÍÑTt ›e´–A>A7/\ˤììæµ{2²°›ùA¡À ßå`7º€ç}®á”»˜Aßñ8Y©ì¶»Ÿjº®Â›I"ª1á`w2zü4±¬ìN¦EBº°eì75ïƒÝ–‹šüNº“iþÙ—r›M€Kš†›Õ`®¡§Ð,ñ t›ñÑ„Ü €¨”›Æ¶#äfZ ï’)ÎJn”á›A*Ê;™Í 7äÞ&‚›ÏõR°“´Üf„o±€f¹™¡;Edvr³ »Øz’e˜È-„Prïe ¹cÿèø!U3;)¹µçŠn$Šn&{‰üx!èF}ÍAû§¢›miP­»émŠn^˜‰7ù)=¯äæ ±ŽÙÜFS„ܬ®àí)ùƒÜlf«˜Œí¶–pŽì™|öBF2¼KئS‰ÿÎC–¾ÊðYí¯ø”úåSúöF=© }‚ä7;¶ýôzAŽé¹ã`Ž­þôz¤ËcØõ§÷C¤ËóËËO?Ê!жΣ¸_‰/øP†˜h-ŽVÓògÊð¬Ø‡ ¯|À2¼2±ô§XÛ›ÞE‘z×¥Þ×½ë]C¤ö·CÖê ½7ØVá:ØZïÛƒmSwl©ýB}:txB}-”A*y-”Akù±P†_ˆLÑò­¥¼ú“ƒþáÅ`ØÅí„ÅG87I'Á"/”Çj5;˜z)…©aKb¸[³²åþÂܨï\*ÓjßѹyÜ3)Ô¯•u·>Ás“:]ªã¹-Vrx‡œK±“WŒK¬#îÒðSØbfør¶2H‰¡ðÚ+ãr—!c°7›ÿÅʲçOß+Uý½2XQ³Ðü ¯ Uí6°¦´\jÈ2¼:Ö ‘Ò*à ÔÏѹ´… @eˆÐnì±¼‡ L­l^&À’Pè—5Ùa–Ûõ ÍŸ^ˆb~Á´ž³5á\.ÃúŸÊrµ!Ëzñàññ˜óq¾â¹r›_S•PñV§*¡â>Nu„ ˆë;5 ¨µÇÚ͸’š„ lÏI¨fvB»†!u àÅP½Mô.¡üˆ—É3u‰Guv)À3§˜éf®ÍN"Ïwv'€’–ÒÔ³_oFxoE)À ÐÛ‹i¿Ù/wÚsÅ<¨üž9,—²:ç¡ka)`J· ÓÇÂré!˰ÜTc{.J¨íP‹™rr|®=´êZ†i_ G‰ …þ²¦ÓÌV¸×–$T€Y*;¤ÓT͸¶† `tJö6Ñ®(þ}Ä²Ä h}y¹þp•2þü7¸aƒ6ãy°VÐíÄ„®ØÖªEN)´˜a‡6ƒBæ¼Nµ¡`£t‡ñQ¨ ²~47×pP›Á²Œ/¡6ƒðlšë@¨me€àºS›ÆÌñµ™<Æ—z5S¨ÝyXÌ]öÅvgÆÍÜcvåÀ6sé5 ú«l«§]±M—@}"Ø&C"†+˜K±ÍwÆá­>°M÷1THºlÓZ Z¤ÑÁ¶:²Ût vÎýrb{ukîØFæ´!óÁ¶ºÅÛê­Uloµ-Z`ñ+¶ù\ó±Í=§oÑ 'ãÕR·ÙøyPíàvç…XãÎ¼Ø nu/+ºY>¡K6¿Ý,‚PÆŽ¥èfu™¨ò‰ní‚¢›ÏY´€;ÑÍ27Sè†®Õ pìò‰n:÷¯£Lº9b Xª&¡(º·v£ºŽ‡ ežìæ;±¸áíTvó9×(c?v³ {›±ŠîÎ(ÞÆ<’õ@÷6še´œ'6K*/‡ (½¹]ÆÐîôέXÎê‡t#ôvæ3‡ 9ɾқW†ûäkÒÈÜæGjó¶2·~X•¹íúšÌ£þ¹{ÚEg1)*s3ª T·sv›Ì­Sl£w&ôK’ÃFïÄ *?ýŒ½™køŽÝè]uÖýp'(½3(ì1νœôæ)Z(oÃ=¹ÑÛŽc‚Œ=MémÎÞÌ£‘'½™ž‡ã®žô†ð ¬ÍˆæÞaVÝÅæOzì¯Ø™6zóÖ º¸lYnôæ{µdoéŒ.z“/Õ˜«g£7±ûHðJoök.‡Sèîù°÷ÌñzsªcʦáôSz£Ì£yn(žoyPf¼RáÍWB® 6ÄÊîý1 ÈìùHž»±›EÆ6[;ÊnË×-lü`7ÊÊÐéâÁn–AvË)èÞ[ѲÌ):eVA÷öÜŠn† ®4â9Ý”:Žèæ+ñÁÃ%ZK¸€ô@ÈÍÃöR«Ï¹y#t©<4nE7Ë&åÔ¥Ýü¬˜˜¨°^èÆO fpîk‰Á¾- èö")Í6Ÿt÷l^¦ÝP¶‰çQ8íèÞSAwæ—WÆv;1Å–w~HJnú¹-ŠÍÂt”Üæ“ÇúØ´’F @Kn3²IÉMï+6O»8Èê òîÄëó° C>ÅnõÞ+¸“]D¦©à¦³×‚“ÇwpÛmØÏê0 ¸ys¥3í®à¦/K8專ݨ(aso>ŸàNæÂÁü&"7êÉUìí·:ÛÜlDm´,…Ütšc ËHÕ«äV¯¹’›nå+të@*ºùqºM…´£›ÕEmÄ4)ºéáî(²YÀÝêýVt£ s#6La7˰>ˆÝƒÝô¶ƒ_eD*»Ù…°ëÝ Ú‡[ÂnjPt³¶1±|b1‘E7Šb/$p8ÐyWfú…Rtot3F¤@æ3C·Îï/‡ à£MNm—Þÿ:–¾.ðYíoøm®~ü¼ôí•zÚðŠc7¸Òl?½î«¯ùØ~z½ Òå1ìúÓûáÒåùåó¯HLÉ} ÿëÍpZb@X,}´øó xVìÆW>` ^\±KÊ3%ÞE‘x°µÞ·=ØöÕ¶Ôþv¸ÀúQ“p«pl­÷íÁ¶©» ¶Ôþᑵh"ÿkáRÉkáZË+á‰ò9t—dáà4\€—­áøÇ·Â Ëë&¸‚nCLÌÓŵVϦG–`“ÄB~òøêov¤ÚÌ/L5 ž§å˜j‰ây2+VöÃD[b~î'4wƒN+Ûe Á0”!3ª–3ouqhKØ\ã(Z`Æ)WWØ+kO6?ÉH¥ã±Q]^5`f®¦ÑÖôf&`¸¯(̼-C+fµe&¢ûžBFC@CIih6¥¬ 03òÓ>n‚zaŒÃ­MÔ@3£Z+˪W;êttF›î4~ÙnÄ5oµ=VW˜™¦=3.Doeí¹·0ó¢FÌÊéÚ(mU€ mÄÀñ bi«\h|M—)ºÏ“Í1µŒ3ñ,ë«ÌÜÐ`c6ŸH¡]åÖ' Öà0ÚŽ2S€-²zx±>W*–ׄeYO-µbþ»êV˜9öiv©æJ¨T,¯ ›yt­g™_`^S=3àYÙª^´³‹¦ÈVj–÷„å;Sèè µ3¬ 0žã¹éiz©Ô,¯ Ëk§¯-1s «þ»•Q±¼',ÓaCŸá5® 0ÓýCknÅ\¥5® °¥Ë†Î9<%5­ 0/ð˜I#¹@M«l9ÿ‹wÑæWM«l7§†_£æUfYéµD?Ê ˜¹Vâ8ï`E«Œ¦8æ&@¦ey4ày×.^Z¬lÕ€‹åaï­™_˪[òE€lœ¤«uUùÿl…¨uU÷2‰èè+3lx¶Ã2 sí¾Øˆ·B6pS8wc>à¶mùr)¸™Mc>ÓZ(¸#4y¦ƒL'·½m þ#nóýØ0¶´„Û…ñr oNyçv á|‰e¸±…Û,s73œìܦͶ>gC„Û"f¼©ïÜ.ž„Ô먳p»X¢ÓÌÀ>¿s›"ZÅ®'€Wp¦²k ]XÁ]¼tn–¡mÚ«¸·ܬ(`™Ò½ƒ›ÏAFŠÓ’(à¶C{ Ð þ7Ëz„N\ƒßÁm®-a¸ÜŲƒ†<-n–EZÓ›éå+¸ùJ¦ªÂ˜¶Ü| {ߊ#à>Êp37ûR ;¸YÖiÍÁn–yf%¾7Cx2ÖÒtõ¸Y†ÕS[*u7ßÉ´<1[rŽÜV$“íàæ+“Ãb˃÷+¸éã³ 7ŸówJá¶áÓq¶ïÜæ+±:¯³¦Âm–e³óвpÛÊ*–ê8XeŠ~*±ØÑ⯂ûk^'e7¯7¾â5wv34kÄÅÆƒÝþ¶ ]bÀTØx¿P2¯Í o:X¼F;àí™Eë>n¦ð† ß\§ëÿ€7©8NC†x£ŒÂå<´¼Á[‰©ðf$èHù}Ò› ‡àwÒ›‡cšÀFož¡Ä¾¥7©ƒÆ„q YéÍ2@ÔåQßJoÇ+t0,#lCéMG sWÊ5¥7(À•>£7Ê0¹/9¥7Óz1;é­ôØèÍc‘ñðí¤wù°X6o„¸èMo{¶§½± #¦Ç7z3ÒÐs†¥“Þ`C¼õD»Rͱ›y(<ß:ɾŠÝŒ Â(öM¨b·†‰ØÇ˜=ÁO±TÄîn]¿‚%UìFS[ŒØ•ºÙJBjJÈ"u3üÓtá«ÔÍž[Äóh¥HÝ|.™™©»3B¡õ›©R7˺ ßá½õ ïÉažP=º»E‚¶¡B7£m°96I‘¹»¡áZþ*sw›Xrã“×-Ø ¥EŸO™»S±nLÂ~‰Üøkž!Ÿûß‹Šn;.›œeÛÑ›#¬º!Ö1®F º™S‘WÞ;º©Ç'Ó¤†EAì%¼¨‰x±O§æ’bG/Ú $s‰]”oà‹¹Äî¹#ÄÔ\»D|Çtèi'·¥ô é)勽$[vGx˜`Ä^bøNž¢ö’qXñLÅ`’Ï\ñËj0Iv~ÚOµL²9ÈãôTªÁ´iºcÔ`b‰0&Þ"Ô`Âðìb¤%PƒI¢ZÁxö±'‹Á„ÑÁ.#™LPÉ.$“†Õ^Â"ñtDDN{ ÚÇP¨¬ö’DQ—WÖ¦Ó^’xVèNT{ Ê öߟ€;Qçp³ÌßV n”a ®l& n†²[¬‚…° ¸Ù¬à2Ò4(¸Á·Ì~ îĈ§`Q¹“eì¼ ƒJnÚ6M¸)¸5k‡‚›+ 3r “ îD1¸ß²§€›ÍlÁÏ…%àfºVÊP„܉‚|÷%]KÈmYÞûˆHÝÉ͘ «îÝLºûhëŠî”ìãÙìèæ;±-µp¯èN õ¤i‘'ÆnýéËTf®pç.O™ýsxéXþfÌÀ§õ¿á½¹:òóÚ»7*ê.îQÛO¯»ì1[ö¨í§÷›°vyŒ»þô~Ô€ty6A~ú¡¨L¾EZCÚ—.1ø¨èŒL–†”ð•«ÞŽxÖìC‡Wòú»{ú¾¼f×åß"nÀ*\]ÙZïÛ®lûn‹+[j;n`ù¬Ý2+¾80j\‡[+~ý‚ 缌·Tÿ¡ø‰×¯A÷h­¿; µ¼<°UóJôþ/Õ6¡»Æ_ˆhOìÀ¿þá½T-ÖÕEÐ`ÑÕ,ú>µÚ¡Ä†žF¾ÿ–Ò;€¡›Š²•ÕõÜšÛ‰\îo‡q›ä7(.ܰëð@Ôp·¶¼\hÙ#-Ü<1­¸%vÀ}0Úx&Îl¼ªðV-ŒMcÑ8fÕÊr ý ªÕ³¬º5v ð*É0³¹6^WøøºS§R |Q†ye4–ÔŒSnm¹.{*9óXgkË-€tËC×/õùžëšo€ÆÝHç=‡Oµäàq£Ë*×KZÓ @ÕÇ™^Ó^êšn€G·Jžq$.OºB ”þOoeiI7P쾉yâ«×º¦ОsY?ùhýL—«¢3¹ë“o@zЖK÷AénM7`hæc2Û‰Å{Âòà¯X3›pç9égÂJÏç[˜Ðó²Û¾<°‘“¡¥á6ØÉmw¡ßI1•Ü´MLçèAîHçaºœEBn:¼ð¡ìÐÚNnfP¡BnšIP²|XÉ]ì¶LÈ?ã¶›–×`Äá,rÓOƳ¥¼ýi'7 ¸É®¢^ÉMK/þ貨 ¹‹Ý>~Ÿ(rÓ¿æðåj1»–›aõ¹-DÈmQ±Þ»é½YÉÍ"]_a%÷æ{r³ PÌÃ^,ä6·Üœú;¹iºN³‰‚múëÐÄ+&O°Í2W6ÛAÛôÉaL¯›I¶ùc"É¢‚ ¶Íù‡íhž:l³Œj­‹áÀ6Ëм+׋`Ûbæí¡;¶YæyRmä–lÓÇ›âÈ¡$ØfY´g"ˆÛGQ]CïÄÀÆ:(´b›Î¿^ïÜVÂm 9°L0µíÜ6ï'°7M´C5Ó¿1v@ÑÍ+•Cšé­•ÜΑ±$Or[ŠÙû°±’Øó‘Ñ–±ä^ÓiïäÞX#äöYá«´“Ûñb+ˆ˜#hGÉ혬ÂênTæfÆ”Ì3w*s3•J.æG÷DæfŽ‚l“ƒÜ[•¹5‹ÊÜv+rÊá¢ú*s3ú£‰¬"7ŽTÛå¹y&:@:PT‘›‡£¯íz—¹¸S™™5TæF3iÊÜšR_eîfʼ&LenöœG-GŒí”¹™ë½Ü®•¹Ùi‡á ÏTæÖÃå*s7Æë5?3Ҩ̭)óUæf~K½6”‘¹Ùiì#[Eîf) e Ю"·&ÓW‘›'îTËVvogÚUänñƒ÷¿Ì›ÇTäf`ºÍý¹5 ¿ÊÜHmiÜZ¤27á‡/Ò273 `ÀÚ’™›³2ZÐq9dn”¹p{UæfB¯pp•¹™`äºJ‡ÐÍçè ¦ Ýx®…˜.…I„n¼Ä‡ûì¼ ÝÇ Œ>þºywÓ´#Ï/F(¼y¯}ªÐ§Ò)w3ðºÍ¼XBéÍ00{¦ÝzS±ÆÄÏy8\Õb‚©ÃÈï™úL-&PžŒ‡CîÎãzeÌX¿Á›%˜(0¤Lxˆ¸Sö‡Øm·b¥“¼s š!añ€7o±cóØ+»™+΃‰#ዲ›yî\dŠn:ú›%ÈJºyÑþ¬žÖzs-#e<ÈM/?fìÌ:¤äN¤3–ÌURróvˆ¯[î•Ü(£‡tb(¹“é³9ÇOÈM‡1»>ò(¹éò†TÛVcI²OÆ í7f Oœ—iyp«ƒYÁ2¦·™¹(¸µ/&•´H·!Ôpc£ps5@Ôš—a*¹é[oŸ“›ABfB”ƒÜ‰ßUžŸ9ÉÍä¼wdmSr'»{³f?,+¹·ç„ܼžÃbòG÷„܉WTB¾™à”Ü[™;QaåÍQa7ŸªL-eñz n”ÍËãn¦þ@G™Aê7ß ö`˜NpoÏ ¸ysG£áÚÖ¾Óî4J§µDß9À‚]WàF¼Ú—C˜örÏ™|;blþ™§ÎþàÍàÏ[ðŽ'ßáO_©‰i‘Ç•î:_»ÿöº÷@Žr3ô]Ðß~ƒF¬½žƒ¯¿½D ½¾!¿ýPAÅ´lv̾ójAeFY‚¢çŸQÁºxP¼ò /6¼¿x¥OÙR÷§ëƒ7«\}Û[Íï;·³hý¯G¬×wzQ-¥ù›C>¬9ëkͯùuO÷=äRÿðætˆÓ 8Oùµ€­åµ€‚­šW jàeÏ­ÓsðKi (ø—× °îª¥ã+Ù2s@åHãt·-JÐÒ¿1’;UŒÿP‚Q¸jÈ ïS³¶ÂÕÀIg$¶”Úfaµû5! { ¼¥ës¼Fu˜ªåutË|cüL€‚Õ¾I¢ðˆÆ€.öM¦³ó ¯·þ9jŸ¯MAg”¾ó÷…È´´/¾)Ëv§0õ®¯Î)Ì©Ùv2oi½V/”,ŸÝu¸’§ ,-ß i`çæJ¯å.þø§Ãú™1>ÎÂÕAEÁÅßV*žŒ«%Ì“ègÖ+ô«‹ŠyՒ鬣L|Tƒt]ÒŒÂú1³7¿×“碓û˜c> Î ,Lá*ÜÜT fæcå½×êªÂ÷›Ùû½§Nz¥­µ°ü¾&KГî¥Ámbÿ1ÎFïK=õÑ{c,ÒrDÜ£GÞ®I¬Öí°oFzï³8¬¨ËCG«yô•{caóÉRãoj¥÷$vL•¯›½/«ÏŠù’¿]Ò¾¬N+Œ T±~Í ê¥÷LF!&è°°°® 4cÅhHsnÔUƒÖÛÕQXív¿±¨%Ÿ§Ñ?ú5“7S> W%š©°£%%u¶U‹Öˬ1™ŠoÎä-S1 EšÙy²}Ħ lÕ¤™WxÜ líA;í’?›É,d–óóBÞ=§²eæü1ƒ9ÊV]š™…!êBÕ…~U¦QøíEYz0oIÄQXí¢?›ÉÌ ª]Ðo•—)‚íjs÷%]䋱;äy\sÞRq@žÁLí6˜íX¦—bƒ¼ûie¦àÜ ŸìPã5Â'€Ó¸:õÐ;&*mó†%=8â+Ý›Ž’žÊf¥õ/~BzÌ Jù ôñ#¸;±ôzžº³@ï ï˜Žµ„4Áª g¦Öç‚Û ô`V‹Æ¥;è隺 • znõöàl  1»ÝBè¹·`mÔ0>,ÏØâ¸ôb#=Óßâ륑ó~#½™0ß4º …ÁÛ‘>A=O€áE5®¨÷F²+1ú†zžnÂ÷±fê÷mNP¯'6ÔóÜuW–ý õ(ê‚\ܳááÎE½á>3MÉ}ÿî†ûlÚ\¡Ç÷ä=-X3`pã=—>šC!ìä=ïèŠñº÷kã=/³r¦0}"ØÛiW`¹|ÆûÄ é¨¹¶|ðžçOËŒ`ã=³”£lƦn¼çyEäÍÑSÞóDà“"lã==5£+áä=6ïˆAvþ3Þ3{x¾ý€ïíºë|¥Ò¾xÏDÙOƨ÷LÄã%ókØo—`(ìÍýœú³³¬°7?44é:²„)ìíb p»—9¤YB xI­³´ŠìYmâJǨ°ß®ÞPØ›#u¤6M#e ƒÀ[$8q¾²~\4@a(Ÿ¬·K;¢¿ímbÅÑ =6+ßJóu õ@= é|œ¹#7+ÎQ(±Þ"Ú%`ˆ‡ub.^B¸XqF”ÿ¿¹³ÉµG®ðÜ«È tZ")’xÚ=1`öü3pyÐöÈ«oFHº<_èݬÊÌÒCÐ@¶øt)JÔ'òð0bLïÊ~ƒ½ÿê^®x•AÅ)žUÖÖ!ó ö~¦åªÚó~ƒ½§.3Ñ3ùgqL$¾Úao…£ŽÿÓîC{ÿÙË]zgOãû=ã§Æ#·ÌÝ%ù¿þÛÿ5Æ\VÅ(=þõâƒÚY:Ûñ‹´í‰zR9ò Œ1ÙÕ0êžèQB^<fü½î­ú„K@“Û­O» ÐäóÉóЗð«ëtk=¼‘gÏ£[0¸ñ¢Öú»› ,·'Â>}ž¿µªh‚øû?¯_Vx®_þí?~S›}¡óÀêâ{] ÞFÝÖbÍ&ÉŽ_?jþbÿýòå¾üÏøß0ÿjL>=Ò‰N&=M mÏ‘aïc<ð,ûv«Ð=Xá½…ýYàß[Øk¡ö•Å ž1í¹ghÏ>÷ ½Â{ Ÿ{†þÒÝ[8Ÿ¡³Í’ĦßÊ63ڼؾB›M:m-*µ;Ù~Ü2Â:²-¿Vyú-ÇHú©ZÊ1[º1Qî|^µ”Ÿ«eüã믶¤þ¦¯ÏŸ,¢ý7f̼ý ÛÑc[–ÓZ=mÝóâ»Eoö˜j©4¶ãbþòçü§þ×Ûi—ùö§Ðb´1Ä·d Å·Uæ1ûÀˆ˜WÉàñÿÿùïÏEáX›¤°ìÿ}툲ÛîËV?FðýD¹ŒçöÅbŠli;æwV6~Êæ!–ˆ±ÙŒÉ§ûêòÊn âãFYLåÃneGJOi2:Û×Öæ¯íƒÒ‡ ­ì§¸’IZÙ,‹•–IÊ£š´Ì\•ãȘIí¯¿¶¥S[l§yÓÎ¥½'Óz„ž“öìe¯¹£•¡'Ï@³(¥ó lMÑþÖ–N[×»•Í\•GØ»Y]’È“Vݘœ¾Ê²äªŒÕe =ie~ÛÍe[G–ÚV9êíñ_k»4m’Å#œ·É"Η×e—#ÜänÑcb“6 7iç­Ûr=Ä´I‚J?o>à´Y¼É1úÕ+ 3A¥ý˜VT%Þ¤—f¿‡f‚J‹5(ý25‰7iç-³¦&ñ&í<½éMTZ™¼©K¼I»ÎCùM]rSÚ)ù<,a&[c_ÞgZÊVwI”I;M^dÑ:¯DªV–fÈËê ‰'Rµ2éÔy‘0“VŸô€<Þ“×ûk»ªæÃÊ«D™´Óú|‡²­÷¾:gÝyž„™lÎÍnH¶WU ù’‰¬L"LÚ)ÒÆ„oŠ"^&­¶xWU+“w+g‰0iÏ¥Î>šÍyñꣵ_—hû²ôz ó´ÁiÞÜc˰4Ÿa\Ç×p¾±€ñ˜–j¿’{ªJ y¼˜g»Ù-JãžV}˜ qO|‡Ë £CÌ"Ų¦=_±lçIw–­LQ¯X¶²7Xîë®X¶2½Ųÿ¤´N±lç„P.û¶˜ý  f+Sø+˜ã(˜c«ÌV¦°w0û%ËÝS0ûm `¶‹PÀ*˜ýâ·ˆäxSÉñÒÉ~ž|®É}Åû.ûUHŸQ8Çß8û¥È§MáleEî®ÂÙÊa g¿”ùÄçp) goßHpÙÏHÂ^Ჟ¢Ì.ÇšΡe€³\†rÙ.YþVYl‡…Z`qlNIñ^>é;““ LÎû7ÈlÉrrv'2ÙÖ¢Nî*ŽóÊSÀäëÕ"°JWôYÐxÃ@ˆ4Îàiœ Òx};HvÂG § `xÔ³¿÷”ðÃã<¥Yœ0øSš{­#mûÛ9¸V›Ïíx Äp>GâpO³R¸¼ðFÔ0Ï#†1\p-Ä0Õ¨†+~“®øZÃíè+ä/ö¿þâümwì6Ž¥»M_çÀÞ†’½ %{aˆ ìÝή°»ñ°w3‰à ãlr¸êÈ2pxÃp¿œ>[û¤%Îéë¹á ¶Xk2¼Uû$»ÈY5ŠÑýåkB¥Â&7·1ÀQ£ðØ™³¯C£°t—ò‚C£°,”sØŠ H¨XQÉ@ˆæ<”A8ÄŠQ&_\Švžü¦Š•‚ÄŠZ À@¬°džrW VXËõ<•,F}z„ »–¹ªYØiãåC³°²wšE¸Ë‡fa¸=ê‡\aiEäiA®¨AÊP¹b”éy+jBç€\Q°U®°ó¤@®¨_ihµ @¸ðô¥2Vá‚„ òz| ¡YT8Ô,,}§êÐ,0¦‚fá ˆ7±O7ˆèïA¬Èú:ÅbÅ'…ŠÅªŸµ X`‹U{( {š­|Hgï=r?JŠæ»Mf¬9Ÿ¶zÙ(ì_Ç’¥•>iâø¨öGÖƒöËM0ÛöD=¥^…’a†áÐ'8(¶\fÚ‡óÞê¡O¸4ù¸íáÐã&4ù|ò<ô#&޼˜ˆ³slØð¨‰#—#•%ð®ŸiâÈëbi“6‹ëÓÿ˜&ŽIɧG:QMB§Í"ÒžêÑ$üËø,O€Vø `¿L¬ðYàß[øœ‰CûÊ2ûÜ3´ gˆ Ÿ{†^á½…Ï=Céî-ü GrãþæVí§L¬ã)jyÌÄÁZ~ÀÄñ+.‰l®l/ë6†Úßã’ø¯]y§KbŠMc³¨a©,mRlŠÿ’Ý,9b:K²Î¶gÀ•Ufæ”iK±éýkrסܖ58%dŠQœ«N#J‚S¢Ÿž`–°#YÒs¶VϹo±m_sºªâPl*?W ‹NåK‘ÌœMW;­Lí™E°Gl:y´q‘Ø#xW7Ø#`O(–§ã5©³í£sÒYtçnot•œœ¾À/Whqc^Ó¹–®ûÔàXU}) þ̈K;ü+®¸Ã…ÑÒáXTé-þˆåë2E²ÃqÉÙe‡5bÁÍÙaÀZê¶À‘´«n ü‹6m[ 5ì:‹ÞVÕ`ØVh XåÚVIÅieÒ„-I.Î`3؇®oâ–$§;!¦k‘æDxèç À–gN;*í–!9ôS)9vÒœq4Ý“ P 6tí¾#lª 7c“ œV&難Û}kñ¦÷GÓP‘¹ýs<~JºíS&‰€à4‘ìÜÉß u¶…3y„€pWa'@k‚¾¶EüÚ*—Ö”‚5â|í]JN±!’h|;Ohì&74ž~q°#ÄaQ ö_“önX‰["íÏÊ_7#ÈO)…ýN8 €Ý‡0{*(ìËîò\[0CÈ zPøe\¯…n€7-^¹Ô= ôQîÁ!/ÀëçÉ‹º„×ä†ÇäÆ_[i}Ph­Áú èTä†Õ} 7¸>€Ü`:r½¾ùyr§É@‘{;#X”ƒÊ]?o¾)ànüÍüÒïÁÝxÞ¼òYwƒ}Ãç]ëå¦{ÐAê¦Ã盫~/HÞ\0y3VãIÞ ïÉ›Ûõº4b½¹]£[…î¸8}Õ•¼k¬$¯õ­ô†¼ù´=“¹ö'2Ps3VÞŒ¥:‚7_Ÿ 7gÐÈÍa\¬ìÍXA%{GÛµ¹`¯Sx3¶ëù1{Ç]Ö¯ Ø›0b9Ù›ØVWÒÁéz5ˆß‘Á /;E®æS‰àJ;•v@¢^=Úƒ F‡õN]÷è 8x”Plù9}<âu›†ü&t‡Qv’’CMÕÂã€%aêᎺøîúNw I€ºCMx4ÐÎõy æÚ÷àpx«:Øy¨5c¼º‡ƒ|‹ƒê€~EÕáÒs‚à"p}‘_.Œ:ùƒÎp˜ ƒÀð ÉÁÙ ãL¨ CIª ðj©aUÕ(H ëKžE4U†õíh×;ƒ|©2$Å¡2`çØw{,¹ò±Óúå*°+xVú¤§á£ÚŸX¹Úñ‹´í‘zú±t¿ZšÉ£a8ô †‚¶Ý< 8ô —€&·=zÜÓ€&ŸO~ûiOÃøhšl;êÙ-wü“ž†âŽè<^}ËÚó‰ž P:XgQœêÓÒ0¡1ñôHêIàô 4¤=uöÊgix,‡£Âç–ýÂ{ Ÿ[÷Žqoás–í+Ÿbi° gˆ Ÿ{†^á½…Ï=Céî-ü KC¶\}8r±,gÏXXÇS–Ôò˜¥µüþ–†b3¤žÆ·Íö|ÓÒ`;kÕÒð×øÂü6KƒÐ|%íý˜Qޤ°ßXt ÐþбiûEA° ¢Y4dîîQUç‚FRŃÇ^©»ÝŸbXŒÛ©ì.˜Õ#Ÿ‡#Wª³9 <Å…2,ñ«1žBÏÛT]د‰Ž…S~¥mýXí± ]¯Ä¡­7sתÒZÔ* †mô™ýxÊ™×¼nœ'So‹\}Ñ´ÓdÊgá°§ÒàÓðy—ZŸ¹C›%+–ÙUiè˜Í×®JCÇ”ñ†Ïš­_Qê®JCÇæðºo3m¨ÿÜœ–ÖÝ•†¥£ÙDþê—ÛCÖúÛ¢JC‡pÐl"uÎæaÛª:Ãh³ˆ-mUa”Émm6¿ú¤AùhfK*1ŒÚEbh6“¿údÇ6ì–ü«ƒ-Ëny+“‰yˈþ€¸–Uph’mÈ?úØŠê ­é井ZWµªm*74ì£2å†BÛTnhõi}ÓÄ«C¶ª½Ä´)4˜Åhvd÷_LËMÅ6UÆjGjð4œö&ûÇÔL!•;Þýr¿O^ø.C€.|d$oÃÉ«æ‡HÞ‚ù$oÁ†K’·Ü©[ *u=ðOÄ­e Æß n{†g¸µu;ùÀ\[·“W èµE5y¡^_p“ßTôºŠ/ªaUMY(èµ¢w «j‡¦ ÜÚAÅtËiò&·¾ï;}Œ[;OQ¬Ì Ë$`®/¬HOÚ¯55ʼn27¬h¹¾ü$øRæúZœ¼¶+V×`a|­Lžàkû×åâAàž°¡¶"%bÂâb¨€À^&SÛvyù*ƒÀV&ë– °Ÿ'·EQleÂæ,huuÍÊä„­H‘ºau§)Šý<¹YŠb#FEq,S»9J~SQÜÓÃÁKåS°T`?hn ‹Ä.ˆ4Þ P[ÆyoA¼qxLo˜Ä ƒ?¹Ý…,®À‘Œï‘\Ð%ˆä‚…Z"¹$ž§Höã‚]ErIĵ"¹`#‘\0Ð’ –¶Éåë.8É債&r¹,ør’ËaL .gœ.[ŽÎmÙv¢ &@dóo `Ìåh˜«×„q.ïaœñ$ãœÞÃ8œ§0¦ï„0¾n1LK 1œ±ÈI Óz@ çkÏ8 œa2'‡3v“ëÓàp,RģÈá̹8œ±€¾œ@$0½C$pè-Ødä(Θ+?h{ ,×}Œ@.g›âWÌI¸uXAbŸû ””Ä6)L·Q±Ý,=CµˆvùÒ(C´ò:¬ w>Ph< C4Ž¡FŒ2å=Ô:ê©FÔ+<…ÛC ß0"Úus AXýéqÔ øð HÝÁ Ù¡;ÔËóEÝa–i-u‡º ;ÔËŒKÉ–~JµcˆÉŽzj£ T…ǡᵇöàI6¨;Ôk"«Š·DPq× ÅÁR›·bCmä/Ü Cl¨õë°E€ ¹¡VŽfán8âü@g¨¤CáÕ‡)4xR2ê •eè V¦h„›»¨/TlÉ¢ÊÊzŠ7å»Ý –-ê ñ¾,ךÿóX¾³ò'ý ÖÿÄâÈÕ_´uOT´/9:pèì»mN££‡>ã´ÉÇ}‡w4 Éç%ðÐ86ƒØhƒåÒ~8Jƒe@·dæû6†,ŸéhØlÎ<>ÿãË‘ÿ Q&7&¡É×°¼^¡‡¹¡-Ú>ÃÔ` â¨ð¹q¯ðÞÂçĽkÜ[øœ©AzËnÉæŸw5xÇSD¦Lñïm|0gŠ¿x÷6þ„±a²¤Š}Ûzߟr6„Jž²6°šÇ¼ ¡šßßܰuŸ¯c¦3~ôÛæ†¦æ†ÿûësñl݈æ†QÝÄ÷·ãã>$ð¹ccvò_ëMäó&/näsAhG@ºíË[HÛ¼ªÄ¢Äî¤Í2U,:Ü\P,Æ–Ae‹†ErÊ6¥•ó [4Š.-b×P¼hTBñ¢ÁðEñÂ2Aêy*^høÏ ^4ÄV â€Bñ¢î÷.tHCÈÌLHÙÂVü…A-,XŸ0²EåÛxÈfOƒ/hk xÏSñÂÊÒñ¢ž‘š(^Ô×€ºE…=˜ºÅ+Š $‹Š4®”,*r®R²¨í½dQß›Ýa!CF5 © ]zû _„너aç mUĨ؎DƒQ)©dÔ+x-EŒ Ï3EŒúŽC¿¨xé_„›ý¢b¼~è&éïvP¬Ëö²0ØOœ ïlåpSlÏz(>¾‚gVb¶—‹b6ð‘š,x³U\…yìL ¹‡_ m{]„û”‹ÐVŸ7?{ÜKÁV_Ác?â¦hãc^-úÑ£fŠfoÖ½®ã‘íŸi¦hëmÛÒöÔóÓL¡™°z¤]|z hÓæYÊ• ãÁ*µxVùäbüvy*B•>h僶 í5u 6êòè³ôiýv¯òÁgéU~ÐÊŸ¥¿ƒ´ò'¬µúÆŠ2>‰e{ÊZ*yÊZÁj³V„j~kEKKsË1ëý׬Eÿû˜±b°£ydʺÙÎ]¶àXÆô¦Ž~¿eK¨ÛÏ=ã0ó:òÔ/µq×ÜqŠ¥!ðɉ¥æv´QX<,eÞ—zl-žQ´ä#òÒEFN˜n²ñ{cº³u—À°æ5 UHN‰gîT’cÅ£QX¥%›ö§‹ö+’K®6ªšò ‡Ç(T%yÅF‹Q8~v\GYí"Gá!%¯£`jÉ s—®«ŠÉ ¼í£°yœÊ:Z3 ‹N³–¯ç>|-¢òç<èȈô^æ@ïFï—»0€»Öo€{ƒå,€{«$&Ó;?L_ª>™±20{¼ŒY¯ðÎpˆxÓÏàmy'ÎK·_ã};¯ìØŒ6ˆ‘âÄ67ŠÒÄŽ¯‰½ðzHl~“IìÑŸ1e ±—oŒ«óBF‘Û é‘/¯0 z'¤[ ô¶wX¿:%8ç·À½ÜymµèU“×s¢Sƒ?ã-ªÓÎ6Õ=D5yfÓº˜:«³éÄÌN;'<=ú4ôL0›&D2›¦‘ÀlƒåòfŒÏ ÌŽ…Á²Â5x6.@ƒÛýCh+œ.hÿHXøï·ihoEÐh˜1HîÝ‘ä¶ú¹¹} J‡;ì9 ¹CÔ<àÛÊ–òfÈÝZ …0l¬¼žŽ „+#¾Ýïð Â$ŸÁq÷5('âMB__xÈjBˆ‡ø„xÈkBˆÏpòÛ7þëu&7*?6Êo_<ÿ@ ©W.a¤nüˆ@©päa¤nïÑí…úl 0®BPHêÆ‰?’X™„'(“Ôãeè%u£‚½¤nüêC/±l+×w@¥’ºÝ nùDÐG Ô ¼@(‰—¡$ž©B s³¡¤rPE¡„™[‚bR ù Ý$B7©^t“ çfOj¹Pî ¸#å_þîoúo³ endstream endobj 3 0 obj 35462 endobj 4 0 obj [2 0 R] endobj 5 0 obj << /Resources 6 0 R /Type /Page /MediaBox [0 0 1080 792] /CropBox [0 0 1080 792] /BleedBox [0 0 1080 792] /TrimBox [0 0 1080 792] /Parent 7 0 R /Contents 4 0 R >> endobj 8 0 obj << /Type /Font /Subtype /Type1 /BaseFont /Helvetica /Encoding /WinAnsiEncoding >> endobj 7 0 obj << /Type /Pages /Count 1 /Kids [5 0 R ] >> endobj 9 0 obj << /Type /Catalog /Pages 7 0 R /Lang (x-unknown) >> endobj 6 0 obj << /Font << /F1 8 0 R >> /ProcSet [/PDF /ImageB /ImageC /Text] >> endobj xref 0 10 0000000000 65535 f 0000000015 00000 n 0000000145 00000 n 0000035681 00000 n 0000035702 00000 n 0000035725 00000 n 0000036155 00000 n 0000036024 00000 n 0000035919 00000 n 0000036082 00000 n trailer << /Root 9 0 R /Info 1 0 R /ID [ ] /Size 10 >> startxref 36236 %%EOF blis-0.9.0/docs/graphs/large/l3_perf_skx_nt1.png000066400000000000000000002571161422157504600215100ustar00rootroot00000000000000‰PNG  IHDR¬öEYa )iCCPiccxÚ•‘gP”‡†Ï÷}Û m—¥ÃÒ›T) HYz•^E–ÞY–"bCÄDiŠ AF¥H¬ˆb!((`A³HPb0Ѝ Ü¹3qîüÈóë™wÞ9çÌŠ*’*àû¹Ø³CBÃØð ‘¼Ìt®'ü#Æx ÿJtL&V Ÿ—Î ¹ •#H Ç€•”.@Γ€ÜfÜ_>̨¿|˜ü?@¢Å}ãQßø÷¨pù‚„ؘ\¶Z¬ '’ÃÎôs±g»98°}øi± É1ßü¯Êÿ€ &Wà–¾…Ÿ/`ÿßPcC##øûï|„5ø¿ÿ€oziœEìÀßYT5@÷é'gjÇD ºîñ²øÙe8‡ÏÁá+ñÍøNü ü(~ÿ@ °šs‚+!”HØJ(%%t®† S„E"‘(CÔ%Z½‰‘D±ˆXMK)Hq¥b¤öIµKH-IËIÛIÇHKwHJ–aË8É$É”é–y&‹“Õ‘õ•Í‘=&{Cv^Ž)g%Ç“+–;+÷D•ב÷“ß*B~P~QAQÁE!]¡ZáºÂ¼"KÑN1Q±Bñ²âœCÉF)A©BéŠÒ+¶$›ËNfW±ûÙ ÊòÊ®ÊYÊ ÊCÊË*š****ÏT)ªÕXÕ Õ>Õ5%5/µ|µ6µ'êduŽz¼úõõ% M`½Ý³šÒšnšyšmšZt-[­ ­F­‡ÚmŽv’öQíû:¨Ž©N¼N­Î=]T×L7A÷¨îðü‹5©k׌ëÑô¸zÙzmz“ú,}Oýýný7ja  ¾š&6>5’0r7*0ê5úÓXǘg\küp-}­óÚk{Ö¾5Ñ5‰19fòÈ”aêeº×´Ïô‹™¹߬ÝlÎ\Í<¼Î|œÃäøpJ9·,ðö;,.Z|²4³XžµüÃJÏ*ɪÕjv溘uM리U¬#­¬…6l››ã6B[eÛHÛFÛvªvÑvÍv3\mn"÷4÷½¡=ß¾Ó~ÉÁÒa›ÃUGÌÑűØqÈIÂ)ЩÆé¹³Šsœs›ó‚‹©ËV—«®xW׃®ãn n<··ws÷mîý4ž:ž|Ï^/ÔËÝë×Äzõõ©ë»½ÁÛÍû÷3MŸ ŸŸ} ¾>¾µ¾/ýŒüòýüþ›ý[ý?Ø”< Ô Ì ì  j Z v .†„l ¹*šÚF k[Üà´áð†épÓð¢ð±šs7ÞÞ$»)yӥ͢›#7Ÿ‹ÀGG´F¬DzG6F.F¹EÕE-ðxGx¯£í¢+¢çb¬cÊcfb­cËcgã¬ãÅÍÅÛÆWÆÏ'8$Ô$¼MtM¬O\JòN:™´šœÜ‘BJ‰H¹*‘š”ÚŸ¦˜–›6œ®›^”.̰Ì8œ±À÷à7g"™3{LAº`0K+kOÖd¶MvmöÇœ œs¹â¹©¹ƒ[t¶ìÛ2“çœ÷ÃVÜVÞÖ¾|åü]ù“Û¸Û¶#Û£¶÷íPÝQ¸cz§ËÎS»(»’výR`XP^ð~wðîÞB…Â…S{\ö´‰ñ‹Æ÷Zí­ÿ÷]ÂwCûÖî«Þ÷µ8ºøN‰aIeÉJ)¯ôÎ÷FßW}¿º?vÿP™YÙ±„©ÆÚuÈëPW»¢¸âýá͇oWšTÖ¡É:"¬ò¬ê©V«>P½R_3Zk_ÛQ'_·¯néhôÑ‘cvÇÚëêKê?O8þ¨Á¥¡«Q£±òáDö‰—MAM?p~hi–m.iþr2õ¤ð”ß©þó––VùÖ²6´-«mîtøéû?:þØÓ®×ÞÐÁê(9g²Î¼ú)â§±³gûÎqεŸW?_×Éè,îBº¶t-tÇw {B{†/¸_èëµêíüYÿç“•/Ö^’¼Tv™r¹ðòꕼ+‹WÓ¯Î_‹»6Õ·¹ïéõëû}û‡nxܸuÓùæõîÀ•[Ö·.Þ¶¼}áçN÷]³»]ƒ¦ƒ¿˜þÒ9d6ÔuÏü^Ï}‹û½Ãë†/ØŽ\{àøàæC·‡wG׎=>Š~4û8ùñÛ'ÙO–ŸîœÀO?{Vù\þyã¯Ú¿vÍ„—&'_ø¿x:Å›zý[æo+Ó…/é/+g”fZfg/Î9ÏݵáÕôëô×ËóE¿‹ÿ^÷FëÍù?ìþ\Y˜~Ë»úgé;™w'ß›¼ï[ôY|þ!åÃòRñG™§>q> |þ<³œ³B\©ú¢ý¥÷«Ç׉ՔÕÕÿB,¾;E^ cHRMz&€„ú€èu0ê`:˜pœºQ<bKGDÿÿÿ ½§“ oFFss0ˆÚÿR pHYsNNÆÊ/¥tIMEã$:.$¶­ vpAg’Zó!%Õ€IDATxÚìý˜$w}ß‹¾%/IÖˆZHÌJÆ5€5ÁñƒU㈠$7ÕØ¾D2™ëçÆ²µÏ=I·=ñ*çç¸êÉ:±}ìõÓåœÄ‰&,é²c¯]Ÿ¸Ëìü+¡ËQpìX³LA-S¤ÄÌ - ðÜ?¾ý©úVuuwõïêêÏëyæÙí®îêªîO}ëóûsÝñññ1†a†a†a¦`\?ï`†a†a†a˜,Ø`e†a†a†a ¬ Ã0 Ã0 Ã0L!aƒ•a†aœ0 áyÞ¼ƒa†a&¬ Ã0 ³àø¾J¥2ïÃ`–ÇqÁ¼ƒa¦Ëúlaƒ•a†a†×uY‰g––õÙò-?ÿó?ÿóó>F¤s=ðÀøýßÿ}ø¾×¿þõ¸á†¢íŽãD‡¢(p]š¦EÛ=σã8ð<Š¢àU¯zU´Í²,hší? C¼þõ¯öéû>¾ïû¾oä×3LúÉx¿mŽã C¨ªíËu]üÙŸý4MJ^Y¶™y1Šüç‘}]×aÛ6žyæxžº¥‡aˆ_ø…_èº0̸ô“×ßÿýßÇW¿úUÜpà PU5!£_ýêW£çxÍfqe½ßºÏ²=a-abmm-ª?r]7‘ÚeYlÛŽ¶mooÃuÝh»mÛØÞÞŽöµ±±Çqº¶‡aˆ0 ±½½J¥ß÷£í–eüz†D?$ÿavÉÛ¨òʲÍ̃Qå?ì×j5¸®‹Ï~ö³‰Ï«T*Ã0áØd˜q´^§‘e”¢Q¼f3‹À¸²>èý,ÛCrÌÌV«u,ÿW®\9ÖuýøàààøàààÀñÁÁA´]UÕc]×£íûûûÑöF£q¬(JôÀq£Ñˆkšv\­V£Ç¦iFûåõ 3ˆ~2ÞoÛññq×5°¿¿ àøÊ•+ÇÇÇÃÉ+Ë63F•ÿ<²ošfâ3®\¹Ò%× 3)­×º®·Z­h»,£òs¼f3Eg\Yô~–íáàk t¯Z­¥ô¶Z-¨ª ×u¡ëz"%Ì0ŒèÿžçEižç%“—Fþ PŠ¢ä:¦¼¯g˜~ô“ñ~Û轚¦EY®ë¢Z­&dryeÙffͨòŸGöu]O|yèåûÃLŠAëui•÷ðšÍ“qe=ÏûY¶óÃkPU­V °½½ë®»µZ €HIè¥ضøËºA0̼è'ãý¶†a$”v–of‘Gþ‡•}MÓ`šf×5Ä0“ ÏzÍ0e`\Yçke²°ÁZ¨‘R£ÑÀ•+W°¿¿×uá8Eék´jšymè¯ÙlÂ4M®]b C?ï·0 ¾ïöm„aÈÑ#f¡Gþ‡•ýF£Ó4€ëŸ˜‰“g½f˜20®¬óµ2YØ`-ÔH‰ SUU£´RV¨h; İëºÞõ~3LQè'ãý¶ªªÂ0 ضjµ:ïÓa˜¡GþG‘}EQP¯×aÛ6]`&JžõzPfÃ,ãÊzž÷3ùaƒµPMÒÚÚ*• ÖÖÖ"%EUU4 T*T*lll$RÂH1±, Q‡àf³9ïÓb˜ˆ~2Þo› 9g8ºÊ,ãÊÿ(²o Ã`ç%3QÉ«¢(°,‹£HÌÂ3®¬çÕm˜|\w|||<ïƒ`EU%Jç¥æIªª"¨ª¥‘ÉF©Üd‰Ò„¦hdÉxžm€˜ÇjÛ6æ} 3£Ê?Ë>S4zÉ«¬³ôkNÃ0‹Â¸²>H·aòÁkÁ ‚kkkØß߇¦i‚•J¦irj$³P:ÍÆÆªÕjTŸÇ0e‡eŸa†a8%¸ðÈ)Á×]w666¢42†Y|ßÇÉ“'¡ª*Ë=³T°ì3 Ã0 GX†a†a†a˜‚ÂV†a†a†a¦œ˜÷LŠ?üÃ?ÄoüÆoà¯xżeê<ù䓸ýöÛç}SçóŸÿÅÜð^>¦½†ßqÇøÅ_üÅyŸf.xý.Ó^¿åW~ëëëó>Í\ðú]>ж~—Æ`}ÙË^†·¾õ­8{öì¼eêìììàÂ… ó>Œ©³»»‹Ó§OcsssâûÞÛÛÃåË—ç}ŠCqã7.ÅïN¿ _Ëãï{‘à5¼|ðÃëwù˜öú½(Æ*Àëw)Úú]ƒu™ç°–™Ó§OãÔ©Só> fÆ,Óo¾,×2“dY~w^×eú½—å:f’,Ëï^´õ› ÖdkkkÞ‡0¦áÕaŠÏêê*VWWç}3aY®e&ɲü/¼~3egY~÷¢­ßÜt‰a†a†a†)$l°2 Ã0 Ã0 Ã0…„ V†a†a†a¦°ÁÊ0 Ã0 Ã0 Ã6X†a†a†a˜BÂ+Ã0 Ã0 Ã0 SHØ`e†a†a†a ¬ Ã0 Ã0 Ã0L!aƒ•a†a†a†)$l°2 Ã0 Ã0 Ã0…„ V†a†a†a¦°ÁÊ0 Ã0 Ã0 Ã6X†a†a†a˜BÂ+Ã0 Ã0 Ã0 SHØ`e†a†a†a ɉyÃŒ‚ïah (âÿ¾/¶ÑsA þè1³\x ëâÿ®ËGšjPÕüû ‚øõž'þ¥Ïq±HÊ]ˆ×äýÚO½ÞûsHþåç†a†aÊÆREX+•yÁô¡ÔzžPdû†€m–ÿÉßQ¥+÷–\wxŽñAT*â=ñþè°¬äç8°¶&žtü€xŸçÛÛb?ÛÛÂ(‘Ï?Äs®¿Ç²Äk>øÁ[ðüó/ž÷ÏÆHô2(ƒ þÝèu•JYÙØ2Eq§ëÝdTÖj±¬¤¡kfmMüKÐ5×ë|h»|íÈFmº|?6Få}¥ÉóÄ1olˆ?ËŠ÷ýµ¯Ý8›Ža†afŠ,U„• Ø÷‘ e ¥µ^Š,b¾GmHÁUU¡„;Žø?E_Hé¦ï +*Ój%×ëâÏu…‘P­ŠÏ Ãø{¬TÄãýýì}dA‘#¢Zû³m¡xË‘(Ú½.^?2HEž<ýô Tõ%³ÿ!™²!*G#U5–uz,Ëy«%Þ»±!䆢ì-%Y$òÈ‹i ù"¹>y2i4Òçʲ™%ǃPa“\Óõ£(bßéÏ cËó9žl°2 Ã0 CYˆ²N,;Áófi…¡°²œî¦)ô´½B¶—`xúéÛ¡ªê–Ê`ÄYƒ5â—†¢J¦)~ð´Âªªñ¶^¨ªPÀE¼Ž"CûûçȒKùsó¨yP”Ø@Îbc£û{úÎ`oïI\¾üåÉ8AQs’M²ÓKN«ÕÞ¿7Ñë©×ÅïI‘T9Z: ª 4ñã+W¦óFr šÔõ“þ®VVžÎ 0 Ã0 3ÄÌe’ofù`ùf(M’œ°º.îUTNU­ÆNWBÐk€X‡K”á–"T¢ë±Òhü€·u~EÔÁ—¹¯E³)žÛÞNÊH–Q†q6¥ä’ñªiñ¾&l{!#•˜šÁzxxˆøRlúðð¦i¢Ýnt]‡-u0´}RLºŽumM,4A6Hukl .YòMÏAÆ'ݸéz1ŒÑ#ì²Êm‹Ï2È7SL¨»û4× –ïòU›G¤'PY×¢mt"Ã1Ý3èn|'ï§ZMCžàˆ¦uÀ€ØÏ¥KŸë{)²^6ä€U¥"~S2:ÉÙA™–ºÞ]æ—§,HÎ&K—- ï|xxÏó`fäé?«««ð}?ü0Úí6vwwsoù¾D5GÅuEÓ¢Õ?U–ÕÅ Ÿ|ó•ñIC©¼ûûbñeC³ü,“|/éNÕý°máñOwߨÈËÎÚµµ¸#¼eÅi޽Cqÿ”»ÈËŸS«% ùµkkâ¶·w¾óö¡¿–ïŦVKN ÇŽ#d$Ýiž¦'<š¦¸ŸµZñõBèe°Ê¤;ÌËÆfQîEÕÁê+C.è/=‘€dŠ Yi6E0«ÑˆSÀ™á˜¸Áº··‡K—.u=xxˆ½½=œ9s°²²‚­­-´:®…AÛÇEö’ézïQi(]—„sm-Î%'%½1 C„yfÆ,(A$¼‰aÂqT*X–×uÇÁ¹sçð¡}hèÏè%ßÀüe|\hl )¶Í&/¬“Ä÷ý±¯?/µp¹®‹J¥‚µµ58Ò]3|á _zÿe–ï²!×8¥[–¸omo‹kšº¼ËŽZùõ¾T¢šºt³ýýd#²z](`b[³§Téñe¾w— YÁK?n4â׈c0M`uu¸ú'€å{ð¼¤Q°±o3Œd4Šd£Ù2CÎ ¹1L½¾8:Ú$(ª¾hP .9Ó(µ›dŠÖ.rè÷"=>‰§ommakk {{{ØÙÙ‰žê©§ëëëÑsëëë8<<̵}’F|CO§q¤qœb‡ßƒ €šZÇã80 #ò²¹® «så5 è“ö}¶m£Z­FÏB1ö}ÕjŠt¥AEQÏ…aß÷ïïw¼Žã@Ó4èºEQà8N”vBÏÓ±yžEQP­VQ­Váû>\×…ïûPUªªBQ¸®‹0 ¡ªj´-†z½³ôÙ?öc?†£££¡¿ï^ò KÆó@™ä]¦býE èhÅiÙ÷<¯K=Ï‹dAQ„aÛ¶#Y¨V«0 a&^Kû&™UUUÉSEφ­ãj÷<Žã CèºÃ0ày^$Ÿô¼®ë‘,"õJ¾V]×…¢(Ð4-’iÏó ªjtÓ¾êõzt­­­EßË /¼0ô÷Z&ù.+4ÞËó„¢.h4ânë4∢@mâ÷Óë)]-=Ri˜¨E¦ú5è º­•VîeãÀ0’Ωi5#L3)…ïÒ¥Køà?8Ñc[”õ{£÷Ôdˆ£4+~ãñƽA€ ŽÏ àºnt/P%zŽÖgÒ/Èá(ŽEërN’¤(J¤ÃƒŸÿå¿üÜtÓM8<<œXã#^¿»¡IòTZwi<3yH–™¬ý¢YW¯^¸}ÐÅrã7â¶ÛnÃéÓ§3·“·D&«Õ2)ðÓVÞƒ Àöö64Mƒëº¨×ëp]žç¡ÕjE ³iš‘‚^­VQ©T"CÖuÝ(]öm¬­­A×u´Z-(н¤°ûûû°m;R¤À0Œh¡%e†°ã8‚Íf3¡t;Ž]×#¥› KŠØÒód“"ßMÓÇ :δÂNÆë°œ:u wÞy'>õ©OMô7¶ŒßtÓM8}ú4N:5ô±ù~ÜY. …²:Ïš›0 Qz@Ȱl˜ú¾íííHîu]2 HÆÉÐÓ4-zŽäÐuÝ(z ƒÎ÷ýȰ„¼eÉcÚó,ËÊ4 ÓÙ¦ifÖ†Ay^›‡Ó§Oã‘G™èo6ï5¼,d Q§L 6êh{z¬@V×ùaYôÉõõu\½zu¢ÑŸ"¯ßE†Fr”ºêÒm\U³G˜›Í“^ËDºŠì ¦r ‘aAäl'=‚œŒô~º¯P6ìh§û—a¨V«ð<•J%2FéÞ@ŽTMÓ"ý‰2y(X ë;tN_øÂðÀàæ›ožØïÄëw÷4Òõ5m2ë*“ÒÁ‡]¿gf°ÊiiVWWnÄ7ÞˆW½êU==—ä1Ä á¼£@QMJ» Ã0Š¢R”r{{†a`¿ã6'£•ŒPzÞ0 Ôjµ(bJJ?E"Óa/1¯"­(Jî×Êpz£–ÓbuuwÞyçH)Áý˜¶ŒßtÓM#{æI™æo¨Ò䟮‘„ä¼ÙlBÓ´Èq"{²lC¯—èr†ô#úNûnöè?È3K677qË-·LtŸó^ÃJß•£›µZÒYêûÝcÌä¥5m°2BŽŽ&º†yý.rF²ºêNÊ’‘Mº_q©iZtÐužçE†%éUäà¤LÓ4Ñl6‘Ò^ä µ½—~“u"C7ËIŸ­ª*n¹å–Fâ0,ÛúMNAúú×ÖĺJQÓa§y0“cT|f+yåùÿƒ¶‹¢Ì¯è™"©™‘_Qzbòx4›Í®š‹")ÌËȼe¼•ŠP f­ôú¾J¥’ˆ4Ò5P­VQ«Õ)¿ôªi&c•¨Î*o‘ɤ¨ò]t¥>²1Z X¾ûãyqÚ¤çÅÒI¥NZ–E#©/•/¥PrvˆÒm©¬@äMgÈôrpöê=Œƒ³è”Y¾å”^y|Œì`uñ™x—à^¬®®bss3ѽŒÒ(òl—aÚúC‰N ”z[¯×#/¥ëæa¨Èdy/ó–ñyBu?¥ó’»R©D^qªÃ¦ têlµZE«Õ*•²P–Y¾‡…"P4;E¹ø°|gCÝã©Ã´aå?¯ÿ0ÝÙœz¬­­Á²¬È±†!Ðh4àû>,ËŠêò)Ív‰è¤¦i‰ÞDžÈè2QùÃØy½Þ¶c#UÃÎÀr1³+œ={;;;ØÛÛ‹Š¸ï»ï¾ÜÛÇÁózÏÖJ-Ù—:_Pº# <|º®w½Æ¶pÃ0è¢ Ø|£Uë¼§*íûq¸÷Pô¹%½‡/ö¡™§Œ÷bÚ]ée¹'o¸eYQ„T×õ(å*í¨úz`æJå{ÖþMé¤<É3 ƒ@DØP],X¾ãŽÓtßP”îîÑÙï³µ£t_PµZ-zÞó¼¨ 5ޤZPñyÊÀsÌh”A¾iÍ¥úSª‘f–€ã<òȱÌ#úèñÝwß}|×]wEO¶Z­ã»îºëøî»ï޶½ûÝïž÷ùuòú[÷‘2iå[6LUU=>888>888VUõøJ–Örp||\?>>V éyí¸ÛøÔ¤ç‹tq6;Ç?ŒÒšñ9ä?¾EPŽÓŒzÓõ‘Þ–ÉÁÁÁ±iš‘ÂR¯× Ãs¯Ì4(ª‚Ü‹¢]“ûûâÚ1 a”Râ™ÙR4yDQ®Çƒƒããz]ȵª ÆŽ¬V«ÇŠ¢W«ÕッƒÈX%êõú±ªªÇÍfsÞ§ºÐE^ò2íëÑ4‡“S¦ØŒ"/'LÓÄúú:lÛŽ¢®/^Äúú:.\¸€••\¼x»»»ØÚÚšw@xt>/2eá£óŸ|PG_¹Ù‘ëºQ“¤F£Z­†ðÉ€žü`ÜUÔêì€Òq ˆt[9­f?õa”#§è£sìÛÿÓwÙìk­s®ÍÎ÷ët¶Ów¡wþÔÔw ãv¶ÑïC)Ë@œªìt¾ŸªôyÒçiÒ¿Méó½Î÷«‰ÇÚ ŸýñÏÎû[:ršâ°Ð\^¹S.µú—»4Ê)ïs#„@Å»~˜…Â÷íí8Õlý˜lÂ0ŒÆÈ5‰üÇŒ¯ýëó>¼BC#”¨òb{[¤Têz<µžçAÓ´è@ëþ•+Wà8N4nLNáí5΋aúA¥²”Šî8q‡tjôUUƒ™'ñÐCEí³ŽŽÐn·qîܹ蹭­-ìîîboo¯0-«‡æsè6sàºnTJuzÑâ캢ÃQ¼û{ÞiþHüÆ*DmiuøÏ,¬²­A|‡¤¼éÒ±¦KNä† dLxˆ 2j]&âzYªÅU:¯i¤¾?­óú\ ±+×ÜʆšÑùL¢ø×Ç“—Ÿœ÷7:uÂp´::êÈ(Ïú¥YvT‡êy^æè—™CÎrªT ä´¨×S8Â0î"ï8¢‰G³_;\‹š$mÈÙs‹Ñd'Ý@fsËM=σe O/ýp'º“ã˜f—×w}ÞøÆ7Îû«(ÛÛB¹'Å^ž‡ WëGÝÚDŽË ¢ûA¯ÙÑ “lj砦{mhšp¶t–pY3sbss31ë‰:ºÉ7’I΂š €o`¤&BŽãDŸ÷÷÷Ŭ/E†’  ‰ì13ý"‰‹Ì(ç¥ iÀ„ªI ÄÝŽ³ ùõ@ÒM¿.ëÿL7äP0}ç–e¡ÑhÀó<Ôj5ÔëuX–)+À¬‡ÅI|ô‰nù«¢ÛaB¯íu¾>ĺ ³”P4Už…šž‹ºˆPÇú´±hÛvÔ  ‘"F#чf~×ëuèºß÷Q«Õ ªj4·Ò0ŒÈ¹¥ªj4&$‚h ½š¦EûÇ–Ðñ6 (Š×u£×Pw}ñ[‰1XûûûxüñÇqùòåyÍ…Áó„ãEŽBå5Pƒ H8}߇mÛQöŒmÛð}¿çH=†–ZM8W2ÆÑˆ ÙIŒLbÊÁ‰ôàÖv»õõõÅ7RSÿôî–ÛZÄUE@ñ˜ž)]½%&EÍzž™‡?wˆ¿ïÅx¹ór@w5"…–2 ¶··aÆäÇX2¾i…6 ¢ï*„JÑö"ŠJ‘ó´ ™/Q鼌ÚíÎ{‚Î_ÇKMï=¨E eE&-Ë‚ªª‰ÈV†¨Õj¨V«‘ñGc¥E®ë¨×ëQ×VŠPÊóiÌ”eY‘áéy^d X–˲†!F4Oœž¯V«‘aI†. ÒCi†æöövôÚ œÂr¥•jš¶t㮨#ê ¥×¶ãÔßaÙÞÞF†QÔ´V«EιÇð1L^|ŸS|™á¸¾Ýn£ÝnéÀžçu¥ýîííˆ /*PýU%ØËÿ6ªáGc _#ÿ~f^䩽ûŸÿíâ_¼ì_ ¢Tðg?þgø•ßý•„‚Bãir+-4^IÆÎxŽÒ¹Év^£s¿³/"ZJ¯S;û)g²ÑÑBÒ(¥ÇMˆõ`ˆ5)4.Û0Š7¯Ï²,T*•ȘÄýÈó¼h¤š8‡ØµmÛÛÛÑ¿Íf3Šmll`ccÕj5šgIÏÓŒKMÓÐjµ¢ôÏýýýÈ@lµZÑûÈФñ#W®\A½^Œ]×ÑjµÐjµ¢×꺴ò>N-„m‹ú>ÇéýÇí(rlYVôû„aˆµµµÈYY8BdÏ›—*1…G.Á`˜¼œØÜÜÄÎζ¶¶¢ÙK´PáòåË8þ<677±ºº:ïãžNÅW:µ}.ß÷Ad¤º®+nì 8 Ã,$Aпþ. C<ñİ]<ücëÃ4ÍDm¥æÂƒˆ†*ˆëH©~ÙìlÓ¤×ÊVЍFŒîT_bØ K¯ë¾Ñ9¦iÔ¼:ƶü]ŒŠÕy?#]Î ñw<òŽ ŸÐâ†Â YªÆüëS}߇ªªÑ5G†éÁÁ*• Â0„¢(p'Jɧç]× >Ó4£ÔM9¶^¯GQS9:Y¯×3¯k£GŽÞ¸‘Í¡Ö&Áþ~Ü@Ï÷ãÚTú:m;ß¼í `YLӌҳIϡߧZ­N>“&/é,8*ß çÄ2ô˜š5ŽJb½¬#Xð;(éµÌ\ðýÁ “æD½^Çîî.Z­VVVpîÜ9¬¯¯|ðA\¼x›››‹{£q¨€åvô>‰ëºQãò0*Š/~ ³` ºlÇÁï|# º¦c¿¹ŸL§†±ñç!n~$wl®wžâÎÏÄÁ¾ Bq!%&/½ŽRˆI©¢†jâ2JY&£}BÚ@ÜA›ºVS=n­³?J–?›l¹v<€0„ é˜ÜÎ瓦ïyã{ð6¼m_jq¡fø­V1<üA`{{"#‚jEA«ÕB­V‹šÝÚjµ°±±Ó4ÑÉ^ÝY{¡Lññý¸[* }ÓŒå×÷E{€RÊ©vØ÷ýDê¯Øÿ”, Z«(p@k©ìu¶Š8+N“¶t^O†ê>’Î@b-¤H¬ØáG¥\vçýTfBÇÀFìÌ(Âú» 9é¤0L`úÉ 2R³ØÚÚÂÖÖÖbFV‰ŽÝ®üØõzªªÂ¶mqó—=| S2\×…Ñ4bcˆnÞa¬­ Í>od…¢¨*âÚ$#®HÈJÊv瘯t“bDhˆGZ|Éh%HÙ2¤ýË_aºkuÂI@µ¶@¼¸·¤}@ú<¹[¶ñ½³Ðñ1¯†JY]t©¡™®ë°, µZ-•Ç©É(ŠVcÊMzù•WÚžg‰ö<aFÁ˲ºšoM2HÉ‘ç"^×dÃÔ@ïLÙÁ‚tóÅ4 âõ¦ÈP9ˆÜÔñeÙëbÙ'öŒ¢p„@|=!;¦}éy¹œQ‡CÚ&÷‚ÙFl¯PAžï™²àÈ¡Dzí7ËØL—~eõ¤q;ž*ˆ¯Ÿ¸å±[ðâç_<Ô×u¢ßÆ…6T‰ÎZ9¡-t/^)TU@„È^0-‹C1…Ƕ…r“¥ÐP*b—G½ ÑÂO×EqTÞ~òé Î"z«Ó¶A5Çy¤•ª,ýoP×ê<Ÿ“~=3–•ŒLMÏó†Õš†aEEmÛ†¢(Qô³Ñh$1 0zÊ:¤$_‘¾ÃD³æe—”e2üä2¬´¡G³Ùç…üÙéõ´"ý_n²I zˆ¸a ìœ%£—êi)uY—öHéµ²à7~íÆ9~9Ó%¯“e!!'wúwOˇœÆ.¤tY’|õrJ‡ˆ2H#¹1¥ÿ;¬"}Ž/í—>‡ I2„ÉyJûª é@_Cì´— lH¯‘ð¨peŸ­¼d/Q_2ÔW{M•¨=üéÓ§wÖj>ª"`4È£Cí÷dy \W«Š"Üöì*b Šçõn5Û@2êétò&›MeÍÓ!)#Û*YNð¬lƒVÆ~Ó:ã>’²ž'¹'ëø¥czrïI|ùò—ó|ã'vwwqñâÅ艋/âÌ™38{öìP;*,à›Bq¯×Ñ·#hÝ%h’Ÿ¦©òž'"P“®ïõ¼x@'ú3cP¯'ý)ò\Dª_êªY=ú{ÀOþ¤ø¿aÍ MŸ”—~ø¾¸vTUì·´.V¦Hø¾µi«éù•4êežç¡R©DÆE´h|LµZMÔ2Lò¡+&ŽãD‘|J5;…ÜE¬ˆÓÿi /`Cá‰Ðï{OŸsZ ”Kcz½F뽿çwžŸ÷ÙO ËÄ"6¢î EÖë¿—‹8•—Î%}NYFâ"R€[Õõ/^ÄÖÖVä‰ÛÚÚÂÅ‹‘žÏZ\ ] „‡î6êûû±Òíº˜8ª* Ö 1Ñ>Ïl†¡.ˆ²MH^wj(¥¦Óo~ðlgsµÚž‘§®‡¬Mrísq83]ÖÖò‰ï¨loo£R©ÀïÈ2ÍC¥Y©ÔÐ&êKu« Óòñ u¦Tàz½Žãããáš)Q´Ò ×ìåa‚3j˜‘Y¨¤Dº€8µ•–nêGQE! º²s=œ9s&z‚"«4›uᙦNLÝ&a´ÊZ•ªŠÐØÁ0Š+•xÃô‚ ç%d±"%† V­V‹]ø2TÇY”›¾ø~¶¼çU^t]Èt³ÉF+3uò—`‹mÛÐ4 FÛÛÛ¨ÕjQ*AÛfò”2¥¡u~¨è}€Ø1ï n2@§Šù"La©V ]¥”_‚®fî\$›+­¬¬Ìû˜&‹–aëõX~óòåîS¸¿õúdR{…H¹·¬é† ˜Å‡ ú%,iáõ}?ÕÑuà{¨;%˜ºÖ²Æ†ÉIe'/šÆF+3Gô ›4rƒ0 á8êõ:4M‹:û²qÊLÜÊA¢ÔöíĨ£Ø$ºwT!jãê?®Ü`Ê §ô·¡É2Ï×@a¸~Þ0+"=½Ï:^;y2;âÔÏ`M÷çUûhüš&Æ‹8­Loä.†d_Ê×þûOÖh›¦X°ÿâK"íœd‹FdA-‡e·ú¼ž‚n'£uÖ³4xpòd\A1¶Žã`mm-š‰Z«Õ`šfbü Dc˜Yâ8|ßÇÆÆ*• t],‡ò¸."Í‘•rfFlo¿‰@ ±è¯Ùùã±Õ…di Ö= Ð×uç)ì‹'_1ɨ)ƒn0Š"ŒV®gezA³¹2xìïÀÎ_ý«É'øÎ7íݤlÓP÷^¤e<Ï kÇÉvähZ<>‡aF Dj_üÛjM¾WmÛØß߇¦iÑxš¡¢X 3ÛÛƒ«<ÏC£ÑÀÁÁ Ãè/—Ô4†Æ]0̇ÍÈš$igl°²¿±Ðœ€® »»»xðÁÏ]¸paÞÇ;<: *’#ϼ’÷]»–Ôt\¸é;¬‹»†™#‘Ý0„«Þ«WQ&:`ÊÍãÊ À+>ð|üWµ{ÛÞ´þo!ßr:c¿…[ד.Ò<‹|?G Ë43é,÷Iã8NµªV«Å0TÓCÛuˆl šÛ'Ïú+‹F9 qž7=vÓЃç0ì/Ó®ëBÓ´(ÒßS6=Ä= äKÁ0Sbn«‘ÏÔ…ä„Üp‰X__Ÿ÷qM3•LR:ò§~í×ð•W¿·ÉOðð~\(ÜyjU)Ex˜ù¬¾¿`mÓ˜Âá!94’gÞ²ðs/~1v3®uø~î~à;Si¹ýlH’Õ 5ŸB‡)'d¬Ê³ò |,×þôi|î-oéýÞ{V»Ÿä›Ñua‡ÕÉGp|_ì»Zå9ÄÌ@caø¦L!9!?ØÛÛÃåË—£Ç§OŸÆæææ¼qt:ëŠ/êš$‡]KÜüøãøä·{òÉ€VtOD[óbÝTû1Ž»)ÄgqZårC2í#R6UUØ•_ûµ6´»ïÎ~_/Ñ£(O/ç½ag‰RÍ—^3L#2266âÙ­ezà8BD&¡Ù¶ Ó4Q­Váº.ÇA“Æ:Y!J§¬@\wrÔðÙoßòïqxö ÂpPh®¸^>åø àÛ;\ý'À÷Ÿîïô™T3šiuŽÉ`ú€íÅMѪU@í\kiÃ3Ïu®‚çsN~I]4S» BîH.ÙXe–JƒÏãc Ï @xéxà&6^¼x«««°m{1Ó„ÉKœCW>>8Àá›Þ”|Ò…Pè›C横PÐÃ0_„hœ”àz](ö¦ÉѨe…êÙR(êô‰o|#"ßE/?‡œR˜…¦ £5ìóšôëó¢ªBžMSD¡,KÔ×Nb|S:t}4†mÛp]­V Š¢ ‚DÄÊ0Œøº¡t]93¸‰dÊlÝþîOí_¿ü†8BipÂT7¨¤g¡ ™z²"®3ÃÇæ8⾕^/G\| ×uÅÌ_" [‡p˜à¹‘La™z:0•LM°Ó¦$œØÛÛƒišØÜÜÄý÷ߟðØyž‡K—.áÞ{ïÅ… /ÚÚ‰¦¶Òß º<.¿ýöno¥”Z94†!”í<‘Ùz}ô«XQ„Wܶ9ʺ¬P00©ÏÑÕ'pW/‡H/E_ÅàÈÎ0Y£¢ëB®k5Ñ–aRŒÚÉqT«UT*´Z­(ºš 9fdÅGA2êX«ÿ¿ ½a¼ƒÌëè—0¨|ÎY饔Êìy¹Z­rºþ ð¼Þ_q†ð}š«ÅÑTNBax15X .-ן?º®ãÂ… ]›üüùóçç}¬SåÞúÖî'ÇismšÃy£Ç¹ù›¦¨™å‘7ˉ u¦I2W¯^Í~_¿)TK×é³ú2Ê\b ¡ “fÏ, ƒÆ~dA锦iÂ0 looÃó¼Þ]VÉ99'´¬î“rœÑÆ¥õ#ofu§o6…¦†"«gÒÇÃ$ÐõÞÉ]žçáOžÿñ`l¬2L€x\ SJ®?<<Äý÷ßß÷EgΜÁáá!Úíö¼w8,žp|'È«?£gS·àYašùæÄ2åDÛÔ‘wJ þ¥,g ½¶Ÿ"Þoñ ¸ä¹FeüÆ`õzáa‰¡†Ð[⢫`š&4MC½_†J¿zn@o“ª³6Íø¦åûÂ8ÌêRoÛq ï((Ê𶪊k±ÕŠ?Ÿ™9ÏüÁ38ñWOp4‰Y8|Bˆ¡ëDÓæ}fÌ´¹~uu«««}_Dõ«GGGó>Þ‘è Ä€ù°Ç{[QØA2GÝŸÆ¥Ùä:¦‹¡D"žø‘':ï‹ßX¯×{×yƒ»Lúþä Vº^¶·Å_½.þÒPÃ×ÞÆ†xݰ†+54õ[-a¨³£t*ô ª·ÿ{·ü?n™÷!2ÌÐLDM¥yª:âµÙÏW-9×÷L,C^ZZó™•í7©¨unMœC§‹ðÜ&53S'È—äÖï'[ƒ Vš[V¸AXÖRï R™Ñyò¬bfxÂ0ÄÉ“'Q«ÕÔüö/ývã”æÉüÄÀ?¼«÷Zíy“ídMMôö÷{ï—¢±;K¨mT£wTÂð<ÜþÎwâ–/~q¶Ÿ=C‚ S)DsT£Óqyå2^ò¯—{-³˜Œã';Ò›H©l¬–žëŽŽºº§ÙÛÛ¬¬¬Ìûx‡#DïÆ1t fYLB?‚Áµ>]9Ë#R­v7^"vcc2ŸÁŸŽÜV*À£~µÛCPwá~˜†+Â8HmWUq¥aÆ$§Þu]|à•€¦i¨T*Ð=½w­ªï‹õ8m°~÷«ßý5afå³MÚhSUÑ)oošë3©{É0̲ùRkk€çák««øê 7Ìþ|gDµ hÏ¡«ìÂó¼ìq6 ³Œ53[6V9Ùjé¸~}}¦iöL÷=::Âîî.677r´Ÿ¥Ðhè2Xƒi¥Ò*Êàç$oøò¾¼Î|=òÂ3åCCß¹‡*ÜðÕ¯fot‘¯U‡HÿíU†jókÀ†B6–%<ôǵ{… «´3çyø¶•oCµZÅÁÁ^ÿ}¯OŽ£!ÂP¤F·FeA|Ðþ¾õt°qk´'A£!ÎaÞ5ž'¾ÇJE‹mOîx‚ rÌ~þïÀ×n¼q~ç9eTPþÂa(‰£ïû0Bc¼ 3'H- l¬.1ן;w‡‡‡¸÷Þ{qéÒ¥(Úzxx´9<<ÄÙ³gç}¬#AûÈ-à;½ã»êWÓµ£¢(Ù©ºÄ4kNm»¿"U«MN¹q]î9hÖ°ŒŠH!ÿ–ÿï±úÌ3Ùïõ1§N½äȲ&Û,ÉuãýYÖlR©ÑL«%ji]7;ÇŠ ðì'žMdÝô×oÊ~q¥’ÝÝ=DlP¬çs½£±4y2¦át©TÄ}§Z׉®‹k¤R™ÌàyKSàü2Ä:.;Ø!24EœÃ0d$ƒ•^ß«KÌõëëë¸páN:…óçÏãž{î¦i¸çž{pþüyœ:u .\XÈèjn4­Û`&7l¸ßØ™scC™æLa¸4«{"«ÅG4~,¨ª*²jXqgß2©°†Þã÷˜¥â º_¸p!]Ón·±¾¾Žõõu¬®®âèè{{{ØÜÜœ÷ñG вîo¤äWÑ[ÑÌŠ\ õ°¬ÞƒÕ& ¥…Õsô¼¯×ÅñÙv¾×÷BÓâ”4?â8q šŸ4ƒU–ÕŽ"ܽöµÙï¤?¡Zi€³H4Œxd¯ ä4v£R×Ü(²W©ôŸp^¯‹óv]!÷,ß3GÓúûB\×Åïýãß>&=©#Ž\e¥ÿ¦QÐm(Šxo­;/i~½~ š¥<.A0ÙæVÆBGñÉŸçy¢'ÁrØìLIÊ= ì‰Y®—¬®®B×uœ={º®GãnÚí6vvvæ}¬#ÑÓ/Õ°fú™'}‘T«±1—8Ž)D!ÉËž÷ÆnšÃϸô¼ì”-§P<ú`Z¤U@¤Šu÷/¼ðBï÷NRÇVUñÛgÉФ£P$c†Ñ[é–#M£Cž¨©ªŠë'}YuŽÌL ‚Š¢à¶§oË~A?ù‘ÉÊbÄúZ„ÚÕ<¤¯"¤ÖR{&íoÑu@õ}_4\∳,°±Êt81ï˜*àul¶„í¦!Vò;JiW'UÉ«91êu…’ MËc<ì>ëu¡<ô‹(%¾?ŸÂC =3²~f@G½ýŸÇ­½Ü™“ Qó¥ôçM#å=o6 £ÝÞ sòFÂòÊw¿ïÂ÷…¡0ËœmGN±w”xäaYÉàëºÑ('ß÷ÅøšÉëdØŸ5+‹”z[LSd¼P0ƒ•ÊH'zÞûSÙ¨"ÂÚh4€“`EžYHrWÏT š=2L‡ëÇßEñ{ô‚‘Ó}³®žmˆª“FÓú7`š'Ts”·Gf7«!˜—wݶËÂgÏâö|öŸ?i²‡Ùn4€Ço¾9»>˜¼C&k¬RÐ4¡°3§2ÆWè)e¸ßœÚ‰LQ—p]‘Ýjá=o|ãäö[P(°Oø¾EQ i4M« !ëaØqD »&µ&ïÜ™5ä@‰¿¨é8’†¥Õ÷œ"ÞçExZÊÇU²9Ö ðÓ1Ì(ä¾Ýq &E¹ ÖNF`æ}™ì2UE˜6Zu §Ð ƒi&½Éº>O7Q¯çï|9®Â£ªq÷ÈYáw<ºŽOþò/ãÉïøŽÙ}ö´È²ù%…üÚµk½ß; Û²Ó…{îМʼN’I)ôÕª¸Æ{ÍǤ “hÞDï-Â÷=#(€NAªõz]8kŸL‹Fê7Ï{‘Ð4éüƒbÈ 50ó}qpó2Ñ¿+¥(Rý*Ã,0¹|Ú!¸N›é¢Ük§!G¦=hA­­|ßÇ›¿öæ8ª:ÍTEI* E2XU5ÊÕ$žFCü@ý†ÝÓœÍZ-nâ4*cºŽoÜ|óä¿¿yÐãëð<À6¯àE/zQrƒ‘j3KŠ"ßñÌÃ$"¬òçR#´´¬W«"U™š±mlÅ}”‘)$ßKL†¢ÆOæ'¾$¾Óf3þýkCì´`€GF×c¹*Ê5 ˆûÀµÞ¼LTíWR—rÇ`5 C´ð50Ì(äºO£$YxNäi¦ttt4ïãž@üùJwÚ`€ ` øÑ¿ò£X½qXÌQ³³gÒÊ<̓¥N³ûûñvE5¿4†Ò:©áÉ0Fs.NÍÙ¸˜@øæqñÎ;qZ~ÞÁl"«Ä ¹#³$í,êǤÇMQGÙ^wkªõ¦h®+4Ãt8.Jšç ÔÈð[×€ëÉïfØ.•e@×Å:[Ô5P®7ÏÍ3h®x‰ ‰@Ä /¼€?y£iÓ©ge˜E$×mÊË8ÓE®ëÊÊÊâ´ xâþœ™e¤B !nŸø¶Oà/ì¿à $‹^]_'­Ì{žÐ>{)$4Ïo?ÖP‡F_¯—O¡ï!³úIà'î{ŸXY‹?}M³¼M#ñ}çj–9Š4]ׄa 7+Ó4—.šN¸ðÓëe÷üA·ñ“×iS¦:*E‰×¿¢6/Ò4±Æg9¹FÉ:X4vwIïÁKp÷÷Ý=ï£c˜±ð¼œåêœÌdpâÂ… ó>†é ©}<*ðWþ#ª³n¹çyâæ\„:¢~ÔjÝ#r¦ÉiµòGµhd‰ï×Ùx™Ð€þ×ð;ÿãw„4ËÀ„ªŠ(IÑ Õ Ç™îâ[”YÃ~E_K¦@ú”5~T³ÞSøËÔ£´à";îdÚ·k÷¢àÎkàÙäÓŸþô§ñº»_×ù~Ýža N:s '!XÆ™. =Ö¦Ýncee%š;>×ytê0Ã0œ}3Ï‹;„±³*Ñhtâ™FÝm–’2M[hcu,ùúFœ¯'O=}÷oáçþõÏÍöÄè®TôšJU»øÊF«ª÷š´mq|EMëL1¶Œ@6XÍóGfÿü¢¨ I‹¡ ¡ ú™U”ËÓ¿ rÓÅ$ËP&ÄÄe;àš ©SýýÏþ>vOíŠö5 w¾a|¸^åŒM+î:¼$LZÆ5-§š×œ÷™3E䄦i‰4ª££#´Ûí©¦ïîîââÅ‹‰ç677AÑÞÃÃC˜¦‰v» Ðuö(mï5ˆtÈ^ÔjÑ\:eÖÑ ÃŸ_ô¨ⱬøæQd#ß«iÎMÁ™™|÷ñB/Ú¯x/~ñµ¡v91 C E—Šb¦Ö¢Bë†ç‰ëqNÇ;3ß÷E ~×jU¬ÿ4GUfн ‘6‹Ü]¾³‚™ÖgÏM¶=FVpÙÇçÞò¹¸dYd’êô Èkö‹Ðx‹Æ`ù~ü"«üb{;î“ ë…Π+ÜúÍ3W™tEX|ðA\¼x±»h‚<õÔSØÚÚJts\YY‰þþüy¬®®â¡‡ÂÑÑî½÷^ìîîâìÙá»" }:ºpžzê)Àúúzôúõõu÷!:€A¥^+gnø©E?¥Ï0R94Þ²Ä_svE3‘o ³¯V?“®í^ÀÑk_;³óîbØ.·ó†ãE1Z©£ªmÏÜù53Oc#2XI&‚ À™?ýÓî÷ôÒ_ûE_‰Z¢{¡ªjdxæ!‚è=€ˆZ7ÜïŸ8šÏìãæ%Ûî`ÿ'Åÿ}߇išÝ3…éΉ2R=Oh†!pÓH0EÇ ´t\”ÚK¯§è©aLßÒoÿ¦Ù]»Û9¾_ÿ–oÁ´Z¢ÎmýNã¢{]€[ïÒAýv€¹Ž‡Ì5ÖfPþüÑÑvvvpéÒ%è{Qô›ûì³ÏÂ÷ýè$ƒµgÓ¼n¾2´p. õºøÞ‚™õ (ÂIu9ÞÛÛÃ{Þó<þøãSûèIË7|þóŸÇîî.öööÄ!žv*"?ȵk׿çŒâQ.‹D«µX™Ô1;µÐíîîâÉ'ŸœêGO} Ï<_Ä#š2xî;¾#ùD¿¥ªß-À°=Õ¯oªA˲¢?ÙÆOôºµµ5X–Ïó ëzî÷Ï‚K—.á=ïyž~úé©ì&ë·„ïÚ÷Ë=ˆ2—jü†M ÃØqKrêj*}|$H/0M¬×g¯ÛdE_é¸ C8÷ö÷Å=‰2TæÝ-[QÄ1×ëñ_µŠÝvO>ùätŒÄsY¿e:MÆ"ÆÂð²ÍLZj5áÀߨˆûft¢ÿ]P‰R¥"èì+ÒÁ‡]¿ga=<<Ä™3gpß}÷E9ó«««ØÝÝÅÖÖVß âêÕ«‰<{™o¼·ÝvNŸ>-žðPí‰Q9y?uçxlÊ@JGÑkü²HÝÄN:…;?úÔ§&þQÓ’o¸é¦›púôiœ:uJ<‘òDêzÒÖzÝÕ«øÖ¢§oQºUÓ§Oã‘G™Ê¾g¶†§¡þ,{¡ã$»N~å£í~O¿ñYút¡8åé ,aMBéƒ<¥7D¶Ãþþ~TïjY‚ @«Õš¯Lb}}W¯^¸B?Óõ[Âu“Ùaöþ=- × †Š½é·#CÕ÷ÅóY:ÊÚÈRž:Ó©·Eí¬^Ôã­ß7ß|óÄ÷=·õqð€ˆ®Ê¢§užs±\QVjè5K‡ ¥©ÝŸK#ÄT5¿¾O×Xˆ󯆸¡3êÊÃ0ć?üa\iµðWî¼s¨Ã>;;;Ñ$¬òsÄ$f¶®®®våÁommEžG9 !ë½½¸ñÆñªW½*Îɷߌ›iÊxž‡·¿ýíØ|ùËñçýn L)Y]]ÅwÞ9Ð#>ê¾§!߀PxúuïNë9qß;…ï)>›››¸å–[¦²ï™­ái<#³SÇš.O¿ñ™gp²RI¾§_°\Vúˆtc"EmÈ´ËyßCÔÔůªj¢±ÕDæiœD†­®ë‘jYÇA£ ËõõuM| Ÿ×úí6€}iúXfúµ…ÑRÔGÉQ-ÑõØØ C¡ŒR×Ö›¦­ßý £2·õ»Cäór_c@Èx1|bÓŲ„—Š?Š’¬gVÕÉ5dM×l“AªiÙ×ð8¥Šä 2Máô¢û±iÂS¸® Ïó`ÎÜt>ñš× µûgΜézrš#möööpxxˆ­­­è¹«W¯ÅÝtF‡üÿÜB²„¾ïã­Ï=‡[ßüfÔ©Ž”)<3“o@,îŽ#d]^^ô¢Íûë`JÈLe\¦aXv…ÕjŽþoyîùDCÝ-Zs2oƒu‰‘?ÃŽãtÓÌG¿ÍyÈvÆ«å;ãç2 VrªÌ"Ó6 åÅõŸTâ±HeLLs[¿‘ ݲœõÜ¢“ÕøÓ0²#ÿmÔZ»¶& SŠ˜N) > ÃÈ¥Æ~š¦!påàwüôOão|#ªÕjäôÜÛÛ×/_êsNLrÌ@VVV°³³ƒõõõÈ“sñâÅÄãÍÍÍDG2ÏóPI{ÎQíLýÈøm‚ À÷ý/ÿ ð½b&ËÌäõ5ÏqR墾'æÒS)93•q¢†µSÅ‘Ö^õ裢ÖF¦W—`@xø§O ¥R”<ÏÃu×]=ÖuÍf¾ïgn£ŽÂ`<ÏÃÚÚZdä†a˜xMY™‡l«*PÿPú¹ a¤§é²”_< ¥7ÝÙŒYxæ¶~#•ašå,C*°ïÇõžT?6N{4B) Çû’¯kú,ßïîv ôïv="ADÆ)=Vº®Ã4Í©–Ì\£]__Ç™3gpï½÷bss3êH&%>{ö,vvv°··‡££#¬¬¬à¾ûîîƒú(*Aà{ ’ÚÄ”‹™ÉwŠt‹ÃÃCüÉ+_‰»æý…0¥c.2îAD˜ªˆÒ|'™5uë­·¦æÜ ½5p2P*cU×u÷èªÛo›ü|£Ñ@‘2R”ÚÕi3ÙN`‚~M Cô7X©aÊþþ¼¿J¦ ÌKG CÉÖ ½æ.â:,¾§Ú6“ÍFQªëq$–š8d«€ SyM Æa ÑhäÎÚ™' ÝnãâÅ‹8sæ Ö××{Þœ&5¯ôìÙ³ØÚÚŠ.”t òúú:ÞûÞ÷¢ÝngnÏ…XZv*x°(]n™…d&ò"í”kßx#ž¹çžyLI™¹Œ{ˆõ\ž`†!n»v-ùž~ —€âϳœ3òh›eb–²@ÍZDÑ¥ ²u0@ ýÓÖk5‘j³éÛÌèÌCGÙØ~EèÀ¾h>jZ—V¶¨uJFcu‘&;lŸ|߇ïû‰´^Ã0 SòrÂó<˜¦‰ÕÕÕD÷Ù³g±²²ÏóÐn·ñÞ÷¾w¢¼ººÚ7'~eee"Iú~K?ÃL“™ÈwgÝZ”±¡L¹˜Õ@È:9tE™|ßÇåïý^¼E¾±jl.Ÿ=Æä`V²†€þêœ/V;½dš:û²~Ãä`–ë7uŽü(‹"¢4Ç—š„dõ¼™µò5뛲gDÝà‘CŽÊz½^¸¾'Ο?]×é€ð°lnnbkk ¦iâÁĬë]G¦O÷þašO0L¡Ñâ iÂ"Ìf˜I!§9ôØÑL½öµó>J† M´×"‘ ày^oEQG¶²O|9˜) òø1#7·›4žÅu…¥]‚fcÔLO6NÑL¯Ùl.„]tâèè÷ßßÝÿý¸çž{°µµ5‘Na3¡OýêO<ñ„ðFr‡`fÁ ‚ì}vÌ0¥!Ý@$ Ì2 BÁ/F6Ãdã£k\Mf˜ŽÞõ«¶³m6ÃÌ–¬±½3ò„3‡î†Ñ\LˆkÉó„}0…¦E³Âu]¸®›Ð©ùÞ¢ê†'²Ò677éÁ´ý©§žZƒ©!ÅŽ~w|þóÀ»Þ5ïÃc˜ñhžq#üà>€ RwÀ0cá#™º+žïгîa ŒeúÇ=¯2ŸÕDÌ÷E$h•k¦¼Ø¶pªGºø&_¿†â/mˆ‘Ds„m[Œz¡9Âé×Oè‚5eM7G ‚`&]{gÍõ4IæÂ… }‡/éßjç#Áõ¿ökì‰dŸŽw­G¶÷ò“¥Z¨˜%ÆGW”Ô²ºå>‘FB´Kz „aˆZ­†“'Oâºë®ÃöööÄš&¾ï£R©$þ,ËJl—§ ‚•J%JQ#\×ÅÆÆ®»î:¬­­ÁqœySÃ$»ÏFÏHÖÓÔh‰a Mv ÖåIãû@¥Ò]#Äc™E\hÐjuºÕºß£ëý#°Ãu]¬­­Áó<躎F£V«…ƒƒ4Òé€'ŽŽŽ°··×·¸zooQ×B£@,ì)Y<¼ÿ~|û·ã;9òÄ,:>€ ¿xáþ—ßð†ÂÌ3ÌH˜èRÔ‡í©øñMþçxÍOtZþ¨tÞ·¤—@¥R®ë¸rå €xŽb«Õš˜Cuò4Ÿ• PÃ0ÄÐøN§É^8Ž œ7:m¨ÕjØß߇ªªÃÐ4­tÊà* fŒ·ìi°f~¸n•)0‰j “-Ñp]á½l4òÏ VÕRt© ‚–e¡Õj-lŠï°œX__Çîî.Ö××3 Ò££#ìîîbsssq¢®î-ÙQxñûÞ‡¿ãø¡yÃŒKÀëC"lÿå{¾úéÓó>B†™ ‰•BßÐÒ·¢0Ä«ßô&ñÿDÚðâ8Ê'ŠëºPuI)Óuõz¶mC×õȘ ÃÕj52]×"šô<: ±š¦%öMPwɼ ß\×E«ÕÂÆÆ‚ €ªªÑ¿¤€)Š‚F£QÚ&rÁ—³!& g˜y’°¥ÒýÆÁqÄ_«µð ‘²ð<žçEë¥ø¶mÃ4Í¥1VàĹsç°³³ƒ{ï½[[[ £ôòå˸téàܹsó>ÖñØÞÆ{ÞøF|ïßù;ó>† € 4åíNËàÿKUÑHo3Ì¢b#jJS©tô åçuW¯Ša"ªºÄýôzn3 –eAUU8ŽƒV«EQ°½½ EQ ªjä±D”– PÛ¶Ñl6aš&666ÑtÚož™}¾ïGŸi\×…išÑ{×ÖÖ¢ùE™8 ²t;‘dú®K!bÊç¥dÜÃdÖfÙX-Q&eœcÑ0 T«U(Š­»´&û¾Æ‚Õڎˉõõu<ôÐC¸xñ"vww»^°µµ…3gÎ,T³%"šOiY€®ãßyšKä`JŒ"þªM­†çþå¿DðÓ?½T^7¦ät”œ0µP*Í£¤ ›¬=õSBqÑ7eš%•JÿíšÖmdÐØ„~ÔëÝźYŸ5¨û%D´’"•Õj52ŒªÕ*¼Îl,]ףƺ®ÃuÝh6½~P•ê©úáº.4M‹F¸Á ûûûÑl@˲ÁDS™‹‚çJ'S&wÔÉó„’Î0 @"Œ–ŒqíË«ò¨™0 £ì’¬4ßz½˲Ðl6#ƒvÙ8ˆ.ÀçÎÃÙ³gÑn·£½Ò„…(³FÓðá—¿ ú`Ê‚øÏáÒNšßþüç£èÔ‚ާ(’ͧ"®‡rÝ|PæØxf#¢Z­ÁÇ€ÏRU53­Ôó¼L£O®uÃ02^E¨Ñ€y‚RнÏqhšÍ§Aö²±LÇjYÇ)e4A}húÎ`õ}á­Yp%YE*- 0¾3‘æ£.¨±Ji¾Õïç5clj Üý%¬]?!?XYYéÛ|iшwÕj¨.P÷/†é‹¸OÚÿ‹ Ï»oY,çL¹èØX¾/U@Ø ñÍ×|)£]örB©¿r5 Ãè9ªE%<σªªQ– Ð~~{‘gþ³ëºQ¨ÕjÑóYoÈézgœMêëêùý‘ÁÊ0 BÂwÞé-3ªºMƨt" Ã(­LÓjmk4X[[ú}eáÄø»(.¤¿AÏóJé¡e–”¨¾PH¯ë,â,çL©è8£U$D6Žoó}oøÆ7æ}¤…AQ´Z-looGŠ‘ïû¨V«¨V«‘âT©T ( ‚ @½^ê¤jµZôžz½žˆ¤ñ<×]w]ô˜Ó÷ÛNu«2º®Ã²,Àó<¬­­Edža¸-)>H´TEzcþN¨ S¨IÞ²‘n˜Dkì¸Ùoªª¢Ùl–®<"/¥5Xƒ ^ß©›Ô†PSc;¨ÞŒaJC'í×uSºº .ÇqðÀÍ7ÏûH …¦i888ˆ:kš–ðÈëºE[å5ƒêGiôZù5²ñx||Üót]ï»]Æ0ŒH™k4Qz°¢(¥UÎ, 0ž´‹ñsAô>_ß_¨‘ S©kÆÙ[ñ‘#©ä œtâ2—|•Ú`õ~÷KxÍË>ÅQ'¦”8^RÉÓì„aך©ÕZ­ÏóP¯×q+Ë}&ýŒ=y|LÞ÷ÌŠ^ÇV&|¿k¢ €>éÏË®b–ȶ 0üüÕ0l[È}sŽý ú¢(µ Ç ªª‰nçÌd)­Á ØÛÃÞ7—£«Lé_J<¬Ô,…3L©ðàÅe]Ýó<„aˆƒƒ’»ì§×¸ƒVÀvò¹¾)Ál¬2 F¢IÞ0ª‰ïÛÛÂâ-¨±jÛ6Çiš¬w͈ëç}Ó"<ñ~ý‰'ØÛÁ”ÿñŽþÒiŒbÛ6+¢L)ñ>žjÞÎ&‡eˆ^.>º.…aØ[® ª¸3ÌD±,a¬6›…š7ìyjµ*• Nž<‰ °¿¿Ïz× )m„5xô«Po»&î |sfJFð&@ùò ™ËÚæœ)9>à)@:Iæé?ýSX_úÒ¼ŽaF"ç×ú«“Ï÷›o»ˆc<˜åŲ:°u©'a9౿_y‚ jDÇé¾ó¥´+žxêw}+‚ãï‹a FðZ@Â4-j¶´ŒmΙ’£ …']VùÿüèGñÒÿñyÃŒDxÀ«“Ï÷5Xf‚ŽÍ™G¤ÃPthÒõ¹GUÃ0„ã8ð}AD£¾–¹ÙQQ(¯Áú¹Ï•×Aý"GW™ò€òé¿ô§V‹f'2L©0º£þÙø¢§bõ¤R©t=g4M‹FÜ0ó# | ]h8Œ) aØq4v:½|qµ:÷5Ò~ Àiš…h@ÇÄ”Ö`Õ¿ø;øÂêßåSJ‚ÐÂÿŒÿ$[Á0eÃ×%ÕõEÿê_¡}Ï=xó¼®Àxž—9R& CÎÄ(¾hï@¢†µoÃ%ßïN3`˜‰³‡®Zí.TunÆjÑÜTšùÌvC1)§Á†ÐW.Ã=ù·øæÌ”ý5O·è]s¦4„€ûk€ö·%ƒ5pûÇ?Žkï~÷¼n! ‚ au®ëF/ŠÂº® Çqˆ®Â†aÀ÷ý(MÎ÷}hšÆ™c hè2X3TÛ'Í¿e˜"“˜Àä(`B‡ïû°:5³š¦qDu(§Áêûð¿ó>ø¾Ïž¦”Ô_ýïUƒçyì”aʉ ¨_H–lÿö¦›pž×õ2FT«U„aEò<σã8hµZð}•Jº.œ`–e¡Õ1*• TUE†°mÍf¦ibcc#2p™áð} z ‰TÉžk9GW™#$‘ 08Â:C|ßjTëõ:;üˆr¬šëç¿Ú­¿À+SN|_¤Ð8+ŒL9QªXÙ \û½ßó[[ó>²n*}¶Q`Ì‚ˆ6Ôhn÷Q ¿ó>­ó¾^ŸE¯ÏóP­V¡( t]ÖÇq"Ãt]»©ª½ŽŒXf4Ô_ðSâÿaöîôîy<ƒ•Y(|_z0H=™CÆ÷}ضe†èºÎ³Sr¬ŠãÇ×õa¦ç!0LÐ4@Uáû,ãL9 ‘ ©ê–…ÿï[ÞRLMžlÍtölƒL-cß93C³ÒuÓu’²CWŽî…aÏó¢ç9 1YêugDÛ¶aFv„5 Ù`eŠ„JÒo|°ç® LÑx´, ®ë¢Ñhð:¶à\?ï˜Õ*7˜`JLG ‚€eœ)%žtÊ(Í&~ç‹_d¥cB(Š¥aÂï„ETU…¢(¨×ë\£:%4 g…ëºÙŽGÇ(–y¦ŒxÞT¢«žçÁ²¬¨[úþþ>ß7J@i ÖDJÔNygÊŠR— ‚A°Ìçäºë®KüeÕ´Ò‡íííÈñU­Váû>jµjµ<ÏceoÒ„µ})Ø™ÑUß+7[b ¢Kp/&ìŒñ<kkkp]ªªFN7vê—ƒr¦øéŸ~…”)5žç±òΔÿË@U2XmÛæô÷œd´!Èø ÃÍf3êNKM—‘ ˆ+¥`뺞0\[lHŽ¡È×…\w}—aloÍ&Àz ³¨øú-ÙA0±tw˲àyšÍf1ËF˜±)­ÁzõêUT*,´Lyá”w¦Ìˆuª©äF“e{{º®Ãó¼.%•¾)Ò‰®R˜.Çcˆº>þ ˜E¦ŸOkÌfKaFÝ~}߇ahµZ¬•˜R¬¾\»vmÞ‡Á0S…”†)Áûub1w]Ø@4;”™ ªªFVœö;Kz§¸óºÎ”1 Vß÷±½½ Ã0x~êQJƒ5 [nù$ 1Sj‚ `%“)%þ> };×Åó·Þ ww7{ä3ªªrYÁ¼Pßc§#SRüÎ_/?£ï†1ônÇã8œú»„”¶éÒW¿úUN `JM†l°2åäs€þm<.Ð{äÃ,">„ÁJY2µšè˜Ê0eÁ°Ýór7\ ‚–eamm žç¡Õj±±º„”Ö`ýÒ—¾ÄÍ”šôLE†) †èoÿ,`÷¡‡8x|ßG¥R‰FÖžç¡R©D5_é®Á–eE5aémÌ ”`šÝÄÎG¦LtÒÞ{ÒlæÚmÛØÞÞ†ªªØßßG³Ùdçå’RJƒUQ€çžû,ÔLi ÃSù˜òRpí÷píïü<¾ih¦ªë&C®ëÂ÷}„a˜˜» µZ a¢Z­vmc¦€&~§~éKE¤‰›‰1ecÁš# T«Õàû>Z­ªÕ*ëôKN) VMÞð†Ëó> †™Üp‰)=ž‡?»áN{MÓºŒÎ^kF­VîÀX–…J¥@Ìyæu‰‘)e—`„Î0e….1¥ÆuÎ|PÓ4Çßß”é×/‡.Sßì5M”­AoýMUÅ_Š÷)Jl×d}½^Æ0 ض Ã0àyªÕj"êJÏU«UÔj54sÖ”1 qçŸü žúWÿjÞGÂ0“'m°ú>`Y@NïaFuªó>z¦ ”Ò`U…kž˜Rãû>7¢aÊ‹¢àèïý=`A2 ò¬A K2X{½O×cƒÕóÄÿû¬ôzJ ¦šÔ´WÓ´( xcc®ëÂaÌ3¶G¾õ[ñ#?öcó>†™Òà^ý6˜²ãº"%$µþ8Ž×uÑl6ÙñÎä† V†Y@ØÉ”ÏóØ13º®G냦i8>>޶ÉFgz 1M3ª–ßÃLÎaJÕ­f8ºlÛF«Õâk€ŠÂw n·Û8<<œ÷a0ÌT`ùfÊÎ(2Î =³(Œ"ß<–ŒYFÒQÂ0®[M­ã–eÁ0 ^ß™¡)l„õðð¦i¢ÝnÞ`Û¶ç}X 3X¾™²3ŽŒ{žÇ =ShÆ‘onšÇ±t”0 £«n5 C¸®;°Da²(l„õüùóX]]…ïûxøá‡Ñn·±»»;ïÃb˜‰ÀòÍ”qdÜ0Œ…gÃ,/ãÈ·¦iab ÍX:Šª©õ; CÔj5˜¦¹ß™âQHƒõðð{{{8sæ `ee[[[Üô),ßLÙWÆEa¥†),ãÊw}˜VÏ 3c&¥£„a˲°±±J¥MÓ8³€™B¬O=õ`}}=zn}}ký:,K$îÒ¥KQ:J™`ùîO»ÝÆ¥K—æ}3¡¬×2ËxÊú»§á5|ùàõ{ñW¾eCÍÞö÷÷K“5SÖß=MÑÖïBÖ°ö»(ŽŽŽ°²²Òõü¿øE|ô£Ń>ˆ;ï¼sÞ§0Uyäœ>}zÞ‡1u>øÁâêÕ«8::šè~Ÿ}öY|èC¿øÅ¹œ×(òMÇýàƒâå/9^þò—ÏåØgÁc=†Ç{ «««ó>”©3­kù±ÇÃÓO?=·óâ5¼?¼†Çg>ó|üãǵk׿r^£È7¯ßåcÚë÷ááá\¾Çq×ï›o¾O?ý4n¾ùf<þøã3?‡iÂë÷x>ìú]Hƒµß—sõêÕÌ‹åúë¯Ç•+WððÃOüË-'OžÄåË—ç}3áððpâ¿çÓO?OúÓ¸å–[ærN£È7Üpà xøá‡qÛm·áU¯zÕ\Ž}\½z–BƧu-û¾¿üË¿œÛyñÞ^ÃÇãñÇÇ¿øEüµ¿ö׿rN£È7¯ßåcÚë÷3Ï<3ƒuÜõ[Ó4|Ï÷|O¡¢s“„×ïñ |Øõ»«œ†¦×Åû?ðøøy:à dù€|pÞ‡Î0¹à5œ)3£È7¯ßÌ¢Àë7SD YÃzêÔ)É´„y¥F0̤aùfÊË8SfX¾™2ÃòÍ‘B¬«««ØÜÜLî{ž‡J¥2ïCc˜±aùfÊË8SfX¾™2ÃòÍ‘ëŽç}Y´Ûmììì`uu5*ò¾páBÏú>†Y$X¾™²Ã2Δ–o¦Ì°|3E£°+ ¿©h{sssÞ‡Ã0…å›);,ãL™aùfÊ Ë7S$ m°2 Ã0 Ã0 Ã0ËK!kX—‰½½½ÌçÛívßYXãnŸ%ív»o{óqÎ¥HçÉtÓK¾òüîÓ”ï¢+“dZògû,GÆé<™$Ë ß¼~//Ë ßt,¥X¿™¹ñÔSOßu×]]Ïýèþèñ]wÝu|×]wÿÌÏüÌD·Ï’G}ôøî»ïŽŽåî»ï>~ôÑG'r.E:O&›,ù¦çËð»OS¾‹v®L7Óï<ÛgÉ82¾HçÉtSvùæõ{¹)»|—oýæë8<<„çy0M³kÛùó籺º ß÷ñðãÝncwwwbÛgÉÎÎ677£cÙÜÜLœó8çR¤ód’ô“o <¿û4å»hçÊÄLS¾ólŸ%ãÈø"'³,òÍë÷r²,ò ”pýž›é¿Ä¼ûÝï>þÉŸüÉÈ;AÇGö€üæoþæñÝwß=‘í³ä‘G9¾ë®»Ž¿üå/gžß8çR¤ódºé%ßÇÇãÉp‘~÷iÊwžíÌü˜–|çÙ>KÆ‘ñE:O&É2È7¯ßËË2È÷ñq9×oŽ°Î­­-\¸pgÏžM<ÿÔSOÖ××£çÖ××£üðq·Ï’õõõ®èt|+++cK‘Γ馗|ãÉp‘~÷iÊwžíÌü˜–|çÙ>KÆ‘ñE:O&É2È7¯ßËË2È7}nÙÖo6X D¿ûèèhìí³dee%Ñýðð»»»ØÚÚÂêêêXçrppP˜ód†£,¿û4å»h×2“Ÿ2ýîãÈø kµHçÉä§,òÍë7“E™~÷2®ßl°ˆ~?ôÕ«WÇÞ>¯sÚÝÝÅ=÷܃ÍÍMœ;wnìs}öÙg wžL>Êö»OC¾‹z-3ƒ)ãï>ŠŒºV‹xžÌ`Ê&ß¼~32eüÝË´~Ÿ˜Á÷ÅäD¯§Y]]{û¬i·Û8þªŒºV‹vžL>Ê$ß¼~3iÊö»—mýæk8uê€dZÂááa$ãnŸ5¦iFyôiç\ŠvžL~Êô»OK¾ólgŠIÙ~÷Qe|ÑΓÉG™ä›×o&MÙ~÷²­ßl°ˆÕÕUlnnâÒ¥KÑsžç¡R©Ldû,ñ<‡‡‡Ðu{{{‰¿qÏ¥HçÉ GY~÷iÊwžíL1)Óï>ŽŒ/Òy2ù)‹|óúÍdQ¦ß½Œë÷uÇÇÇÇ3ÿ&ÀÞÞvvvàû~ô\»ÝÆÎÎVWWqtt„•••D§¯q·ÏŠÝÝ]\¼x1sï8çR”ódz“%ß@9~÷iËwžíÌ|™†|çÙ>+Æ•ñE9O&›2Ë7¯ßL™å(çúÍk9::B»Ý€D—¯Im/ãœË"'“dY~÷eº–™˜eúÝǹVé<™˜e‘ïe9O&É2ýî‹´~³ÁÊ0 Ã0 Ã0 îae†a†a†a ¬ Ã0 Ã0 Ã0L!aƒ•a†a†a†)$l°2 Ã0 Ã0 Ã0…„ V†a†a†a¦°ÁÊ0 Ã0 Ã0 Ã6X†a†a†a˜BÂ+Ã0 Ã0 Ã0 SHØ`e†a†a†a ¬ Ã0 Ã0 Ã0L!aƒ•a†a†a†)$l°2 Ã0 Ã0 Ã0…„ V†a†a†a¦°ÁÊ0 Ã0 Ã0 Ã6X†a†a†a˜BÂ+Ã0 Ã0 Ã0 SHØ`- aÂó¼yÃL–sfY™–ìó5ÅÌ–9f™`yŸl°ß÷Q©Tæ} 3UXΙeeZ²Ï×3kÒ2ç8‚ ˜÷a1ÌTåe}¶°ÁÊ0 Ã0 Ì뺬Ä3KËúl91ï`ä©Qš¦õÜ®ª*t]‡çy¨V«ÑvÏó¢4Ã0û°, ¦iÂq„aMÓ`Fâ3MÓùõ “—^r†a$oŠ¢ Z­BQ8ŽÉ<áº.Â0ŒäyeÙfæE¿5~Tù·, õz¶mgÞ7Â0„mÛ]÷†‡^²LÏ»® Ðu½KFé9^³™E!KÞóÊz¯µ`Ùް€ X–@žÛÛÛ‰í–eÁ¶mBYÙÞÞŽ.°m;zO†ØØØ€ã8]ÛÃ0D†ØÞÞF¥RïûÑvúüQ^Ï0yè%çabmm-r¸¸®¥Ü„aØ%kéÇÃÈ+Ë63ú­ñãÈ¿mÛ¨Õj™žþ0 Q©T"Eˆa&Á }%M–ŒòšÍ, ÃÈ{ZÖû­íôz–í!8fæJ£Ñ8Våøàà zÎ0ŒcúiŽ$¶«ªz¬ëzbûþþ~×> ÇF#z¬iÚqµZ›¦ío”×3Ì úÉy«Õ:–—¢+W®ëº~|ppÐ%ÿûûûÇŽ¯\¹½~yeÙffÍ 5~ùplšfô^Úו+Wºd›aÆe,ëº~Üjµ¢Çi¥çxÍfŠÎ y$ëýÖvz=Ëv~8Â:g‚ €®ëPU5zNNõu]·k»aÑÿ=σªªQç2ù1yi$Þ¯(J”’Ћa_Ï0ýè'çô\­VƒçyP­V ªªBUUhše¸®›H©!†‘W–mf– ZãÇ•9]˜ /½|¯`˜q$˽ȒQ^³™¢3Š¼Ë²ÞomO¿`Ù¬s†êR{†áÀ÷S’ü—uƒ`˜yÑOÎUUE«Õlooãºë®C­V‹¶†‘PØY¶™EbÐ? ù×4 ¦i&öÃ0ã2H–¦LŒ+ïƒÖvf8Ø`3ªª&"¡@ÒHU¥¯ÑªiZ䵡¿f³ Ó4¹n‰) ý䜚 4 \¹rûûûp]7ªÃ6 ¾ïöm„aÈQ#f¡´ÆOCþF¢i ÃL‚A²Ì0eb\y´¶3ÃÁëœ1 žçEtŠ–ÊÛ}ߊ¶©ã!w!#¨ð›aŠB?9§Fbt#PU5‘£ª* ÀmÛ¹ÒϦH Zã§%ÿŠ¢D+yô3 É2ÁF,SòÈ{?Y´¶3ÃÁ뜡ԭíímlll`mm­+¾Ñh R© R©`cc#±”˲°±±un6›ó>5†‰è'çT“·¶¶†J¥‚µµµHI'È1ÃÑUfÑ´ÆOSþ ÀaìÀd& Y„NbYG‘˜…g¼’õ¦½~ÿ÷?VVVæ}š¹àõ»|mý.Áú‘|®ë.ÌÍkÞÿþ÷ãmo{Û¼cêø¾Ûn» ¯zÕ«&¾ï§Ÿ~W¯^](ƒõ7~ã7êxGåé§ŸÆg?ûY¾–'°ïE2Xy /Ó^Ã,Œ¼ðú]>¦½~ÿ¿ñ7Æ`åõ»|mý.Áú²—½ š¦áìÙ³ó>”™° çyéÒ%¬¯¯c}}}âûÞÛÛÃåË—ç}ŠCñŠW¼b)~÷v»v»­­­yÊL˜ÖoÚn·ç}jCÁkxùà5<†×ïr2Íõ{uuuÞ§—^¿ËGÑÖï¹6]:::ê«TµÛmÎó É2\(°µµ5• eV°|Æúú:+; Ëøh,úïž—E^ÃY¶Gƒ×ïÅe|4ýwÏKÑÖï¹DXŽŽpþüùh6Ñúú:Î;}1‡‡‡0M3ºt]‡mÛóþ®&,ßLÙagÊ Ë6SvXÆ™Ed.ÖÝÝ]âᇆïûX]]ÅÅ‹£íçÏŸÇêê*|ßÇÃ?Œv»ÝÝÝyW “ –o¦ì°Œ3e…e›);,ãÌ"2sƒõèè—.]¹sç¢bòûï¿§N <;{{{8sæ `ee[[[hµZóþ®f ,ßLÙagÊ Ë6SvXÆ™Eeæ)Á”b°¾¾Žv»££#¬¯¯G9áO=õT´X__çƒ÷¿ÿýÑ~¦—.]Â<ß÷'¾ïiÉ7<ù䓨ÙÙÁ¥K—æøí1‹ÀÎÎ{챩ì›×pfÞìîîâÀã?>ÑýòúÍZ¿§1šŒ×ofÞ>ìú=sƒõôéÓ’m¡ï»ï>aoo¯o å~3©î¸ã¼ímoÃ… f}JÌ‚±µµ…ûï¿*®§%ßpûí·ãÂ… K32€ .àÎ;ïœÊ¾y gæÍÙ³gqÿý÷ãu¯{ÝD÷Ëë7ShýžÆH^¿™yC:ø°ë÷Ì Ö~é+++‰Âoâððp¡(3Ë Ë7SvXÆ™²Â²Í”–qfQ™¹Áº¾¾ÞÕB{ww«««Ñ¶ÍÍÍDÚŒçy¨T*óþ®f ,ßLÙagÊ Ë6SvXÆ™EeæM—À¶íD-|gÏžÅÎÎööö¢"ïûî»oÞßÃä‚å›);,ãLYaÙfÊË8³ˆÌÅ`]__Ç{ßûÞ¨ø{sss¨í SdX¾™²Ã2Δ–m¦ì°Œ3‹È\ V@äÊ÷»mg˜"ÃòÍ”–q¦¬°l3e‡eœY4f^ÃÊ0 Ã0 Ã0 Ã0y`ƒ•a†a†a†)$l°2 Ã0 Ã0 Ã0…„ V†a†a†a¦°ÁÊ0 Sp‚ð¼ø±ï‹?†a†a˜²3·.ÁÌò†BÙV@ÓF{¿mw?ïû€aÕªPðé1³ ªÉç®VÅED+ñ^ÓŒ=}½) °¿ßÿz£ýÒ9û~|Í‘¡þÅ/¾cÞ?+Ã0 Ã0ÌØ°Á:ähOÞ¨")Þ®+”`M,+ù˜¢0ªG\‚@¼—">ij5ñ:Ãè­tS4ˆð<ñ¹­V¶-G²È(퇪& Uçäº"BEß‘ï‹ëõØ@Qñú´šFQ’ß}wt^·Ý¶‚[o½e²?4A¿U/ÈÙBrppÜîû݆¡üß¿©aˆ×Ñã ÏeÉj::K×m«TÄ1‘üR¤³ÕŠevÔh¦¦ÅÇ×!Égúztý¤¡ë“ prúìì¼ÀÛÆý)†a†aæ ¬" …²L†–e‰ç)Q6R5­„Èu…²\­&ùz=i¨ÉF_/ãsc#i¼U«q«iƒÚ4Å>*•nCÀ÷űêzáEIF£(’Eûó<¡ä7£¥ùÖëÉïkoïI\¾üùÑ–‰¢yµ¤ôëz]ü{[üVi¹$CÕuûG3ûmÄ~÷÷ãǪ*>oPt¾tT*âÿäСè.½fÈÑQ`´´xÃàÔw†a†a„N–“u6¢—®E¯£LI9dɲ*r’“nGhZR„mäûÀ/ýÒðçÅëˆÈjE·Z#)­VvMžüþJEü˜TsI?$Eˆ²Þ;¬Ò¼¿ŸlÎ2ªr,£¢ˆão4ÄþÒiãBß¡ +åó…"¦²3†RmM³Û!³¿/t´¨Q*¸ivGTÇEQÆ7(ÓQùq ÉI‚Ηªgx¨mg†a¦8™¾e{^êà¢ÌJz- ¨oé0•JüÊèRÕdYàö¶xL*ÉJ÷Íb]‹²ºèqºTɶcÛˆž§,Ì/|aøïŠ Ö!‘SuÉ@UÕl¼_´'ýž,ÅRLjŸõzl°Š€Íƒ0 †!Ô_|†ð}Ÿ•ù³… TZ É3Ù»'/jƒ¢ûó&Ñëû>E‰ä,ø¾ß÷¡i”ÎN<ÏCØ)ºU¤A=O¨ª UU¡(J´?™  ª*4MC†°m^çî!¦¼ýSŸúÔ¼¿N†a˜¥ƒŒù>H} #î©•aG¦œP`Šô© öH6¨×¬”á(÷¾p!OrvY–Ž–GgKžÒ:~–Ú,—U¥!;²êÒÙ¦l°N¹™Kµ:¸)ʰŒÚ1wÖLÊP¥h)ù¤°û¾ž²ÒNF&=O <íË÷ýèq/#¶Û¶v»·½ëûÒx^ìÆ@íG¿EmÚAÏóA°KG#E–º]×äQ62³äŠö-Ë,Étš¬ÏòIû }N+pÁLž0¿#É£ôûÑïqï™,C0ÝŸ#ýû«j²ŒÕ^}eŠDºgÍ8°Ášj¾bšÉº9&& ÃHéÃ0¡Ô§ L‚”vz€DäŠ~Ùè ã@Và³ €AìííáòåËóþÚ Ý<é¦<Ï 4Š€øm)êH£¦iÐ4-Ù$ çIfajšÉ!í“^+Ë_£Ñ€¢(°m¾ïÃì܉F‘±aÐu=Ó(íeô2 +Êih„½f˜qPr/òŽ“FŽÉÊW¥Ò­ŒQ³AßOÖ‚Ó1‘ClPyyç©NŠj«ž~zªú’yÿÌ ôD9Q%­ËeVéÆv2dXé^éîë@wÓ×M Ã$ë³ÒÍôêuñœÜ}¾èHË•1ÉÎyšW$'¥äÊò4¬.ÕKÍHGVÁX4l°f@!z*,N/NeÁ÷ý„q +är¤ˆ C*"õ}?JK¤÷Ñëä(€(ZÄêžL#efñ3õŠT’<‘ñ¦(J”V›Nµõjµš“î¸ÄL•  #ÍMwOž©Á½d`Êuž…—#¢Õj”‹9+ê˜õ9KÆÁ0 †‘™ À0£ G()ÒHu=ÔŒ‚:¬7›É(Ž¡¤k”šky®]¹³<]š4ûšŒ?¹þIÞ?¬ƒH§ý§#E†!R›Íá¿r*&S¨)E/ÉQBÙ˜#ùm;ŽV¦§3T>¤Œð}?‘Q&ßh€¨Ü‰J™ä(ùói{µZ…¦ið< ÖCó îºr_yå+qtt„o|ãØyík£›y:âIÎ’ç¢ÀÆ*3 'v¥[ûg5êË2夀IÜ›‚@Ž@ñœdK~,f  TIËŠûÐè:š#¯ëÝ×?ÔLQÆ0’óÖããá8ljʌȉO¦ìDb>}¶ {šišPU5QVBÏS†e¡É÷?Ož+‚î’MÓðéOzÞ?ßRA)ݬÖ6X%l;ž¿86®]–¦Á¶í¨–nõ™gðÿþ¯ÿϽñxðÖ[qí%/骯“¡tH2Jû!˜2Õj52^G¥^¯£Z­f#³LÔãºøÒOü>síÞò¶·áÎF>⼪ªè*ù¦ìª Õ0¢è>Ã,¤ˆ÷‚jç&Ýœo\äèÕ¬‹ÁòB‘Rù19k(«@&Ï8¼ à8NTæˆ,ê—ˆ{a‘1¨ªq4žJžä^­V+a4’1I&= ‘íC€^½ (;'M¯ÞErÐ.ä !9•”b»¬i¶‹¬Y³†Bžy£ëøÜ[Þ‚{ßû^¨aˆ+W®ˆÓEÞùŽwàô‡?ŒôÈ#xîo„ò+¿‚[¾û»çý „£O‹I¥2ÙUÏóðÎw¾/}ó›ñ¯~ó7ã±*ƒÞH.uÏ‹;µÐ|(†) ”²Hd¬AضhP;õ®'m[h-òäÞZ-1Ý÷ç7½ xê©Ìæ2¹I·h”¡šØF#Ÿ»ˆòtä}Ólš90é®Ôâ2½Oj0;ÌÇL¹óh×)š†!*• V¾ùM¼óñÇñgï~7nþÆ7ð/¿ö5Üð[¿…u]ÇNãUUû¥§n§qÝ8/3mÓ5JíO)¿_vM*O³—œ3 ù³jî˜$r”Æ—‘aIÛ{õ: YÛTÈcÏŠ Õ¢z^ÿNÍŽãÀ¶m†‘ËQ?͆,K˪ºÞ‚Δ\k»Ý†iš8<<Œ€Ö´5rmoÇnN×ósÒé/é<ô¾z} 47!Ï•O†ýíetS³ 9ÔoZn°~†Ï’‘ù5PÆ@'ÅŠŒÕ¨9WâÖím(ýò 'MÖ5DÝh$ EN“5/Õ‰q¤s‚xþÉ:¥î§¿XÇßiÖ (É‚¦PäÈqbï|á”r,Ñ÷º¦Ä§ÏÃ'ž}và øÓ},Š`Éó·é~ȵ~‹‰| §Û:ÝB #SDQT‹G©Úé†F 3MÂP¨ÂŠÂ†ê2‘Ë`5MëëëÑX@¨ëëë¸páVVVpñâEìîî.¬Áª(€þúÏáKº[MƒïûØÞÞ†®ë¨T*huŒA˲¢ÿOM‘¨íí¸¥ñ ÉØÃ@ƒÿ¨¥ËÓë 2”󜻜ŸA"48-O½‰<˜0 ³#f–賨M"_²¹ ѼI:†Õ~ögñ·~+B×…eY0M3®R(³’ë^ø~\ß:J ò ãÐuã¡}YÐ,’ßA†{Vý9ɬçÅ%ã~'²Qœ¾ØQ“ Jž C±D­›oÍ¡©×ã´í8}~ă¦f5ôÛ¿»®\Áë®^Åw}þóxßóÏÃBÒ}Ë×¿Ž·|ýë8ûõ¯ãgÿò/ñ-r«aZ`Æ•kÙ¹$;ˆ(Å?ËAÄLJ§k W" Í_§r'Jíæ93k„“››8|ûÛqøö·'º­~÷ïü¾õ…ðß¿ö5<úú×ã¹½€0RDWüî»Ñ ¼èïÿýÈ)¹®(¸:S¶ u)Ì{ÿ C±ëzw¤l°ªj¼V‘ƒ3ÃóâÃÃyÿr -/ä[_µ ×%ãS¼Žf—’lA˜¿ÎsØ™YC™ERU˜Ù1Ð`m·ÛØÜÜŒ S‰¹V„¼}ñ}@ëDÉ@¥Îs¾ï'êz½ŽZ­Ïó°¿¿?æ'Z C(ÆF<‘ç{š7,ú\¹ñÕ(,ù€­(C»ÚÆ™mãè×üƒ¿)Ø<˜Fuê¨ÓË8¦šõiB"(E›zï÷Šæ’LT«qSµI5Â*9“ï”ÍÔ4-ê’ ˆû¦lXú¾×¡êûøøí·^¸ývüÏ¿ñ7Nz=çyþÝ«_“/})pí®tîÇ´]­V¡ÞNQýF#!3´/Ø6ð÷ÿþðŽÇ<DzL2†±Ó,KÛìu }œ¯xÏ{ðŠ[oÞY2äzTù§ñ}ŽãDé½FžçÁqœhª<§”aæÅ0 › ÃLëÊÊ ŽŽŽϵÛm¬¯¯/¼‘*³½ ¨"RaÕjÉôÈ &Ö%uQ¨×ã(¥¦ÍN9æT£É@ÆY½Ž_¶,†Qld–.T’çZ-Ñœ…ì°¶& ÏQïÄÜÌ,”¤1¯Jîªi´N‰ã8‘H†¨ö¯Z­BÝÞþÓ€éÑh¡H<9©|Rd,53Ù/Dd.P½m­6qçá“ÿèáóÜ%8”ökšÉ[·ïû°m;r^º®‹ †f³É©¾Ì\ _µ~ å¯Ùdcu™h°®¯¯£ÝnGFêÑÑ<ÏëªUÝÛÛœ:ujÞç4†À ¢9oKgbœ('37(/Î"Ã×gVw½(ЗdÛùRÖ'E£Á‘ÑQ©L§A‡ëº°m»{”…´4-;‚˜¾8§5ß“3dÄAOwü“iŠ?*ÉXòL—yA~ƒ¬:mêËÑl6#™5 £X¥!ÌRáºbɤTuE‰+X,™\ëææ&vvv°µµ…½½=E^Þ££#\¾|çÏŸÇææfÔ5¸0xÔÎ_êfø*,ËBg0%AUüÁúÛ¶m£Z­;º:/L3N[äÈB©‚ÉM5 ‚ QÛ§( þÓÖ^þá‹T Yl•e¨Qa%%Š"BqÚyVWíiÀ†ê\ ñëÕEU6V¹•)Ôã°ÙäÛ/“Íõy^T¯×£¶åpîÜ9¬¯¯|ðÁ¨‹p! ½@˜ãu¾¢!E®”+†YªFýþkqtµÊ d6ŠG…˜R‘·×[?Â0įüÄO R©@UÕhædK×ñòOZ|@«%þö÷Å¿½®5ªÑž¥ã¨ÕJŽcC¥”¸®ðMPŸ.6V™"ây±‘ ÄYl¬2½È5ÖfeeçÎËܶµµ…­­­±"«”nœõüÊÊÊxQÛº¹ej¨àxu¹;#ÃL€©Ê÷ ¨ADtµN¥"Ñ«) Ó—¹Êx¨AøÈY×Zò'‚öî.ª×_Ÿùä'“†æ(–ð<œF\Ö1E•í^(J2ý7 CÔjµ¨KtºÛ/ÃÌCƩ̞ TGf¹ Ö~Œ+È»»»h·Û¸páBôÜáá!LÓD»Ý šLÈ3`‡ÂãBxî¿=ˆW¾õ­Üd€™(S—ï¬ýø÷âàÇ=xž‡ ¸>‰™8ó–ñ^Ôjâß‘ŒUÇÅTºŽúÓøÔG>£ZÅK-‹¾%¢¨²…<¶V¦V«AÓ4˜³¬Íg†yÉ8÷ d†%WJ0 š*íîîF³V'ÁÞÞ.^¼Øõüùó籺º ß÷ñðãÝncwww´±:}xä‘péèa¼ýWu"ç•Iž´ä¼ø¿a?ßÞé1ÝÌD¾ Þv €ˆ®²ÂÂLš"Èxj4£(#«a(º6¾ü»¿‹€ÿã›ßÄ=>Š“¶ÍÆêQDÙîEÄåÓ2ddðÚÏd1/§t`††\ëîî.vvvpñâE\¼x;;;c ïÑÑ,Ëêª=<<ÄÞÞΜ9@¤#ommÞÕ4‡¡ø‘\ÅÝgïÅK¿ýÛÇÿFej*©?/ç{vç=5£›ÎÅïl ¤×{¿^†lýÜ0ul€µÔg Kˆá u:o«s<ã|~¿ãš23“ï>€£#<ñÄrŽÃ`˜œAÆÓø¾è›U­?^@”Oé¨*þö?ü‡P­V‹›”-E”í~loÓä9ѧÀó<¸®ÍUe˜4‹&ã “+%øâÅ‹ØÚÚŠêXÏŸ?‹/â¾ûîyëùóç£Ñ8”vO=õ$òé×××qxx8ÚúèÛ!8|íkŸŽ2}ŸðcÔÒ‚ˆ|6!R—ÉPDýmÂh£æQJçy¹ªÒy^•^çÐÐ#7£t§J“‘K”iíªw>ƒ¾» õ=¦Ûé<Ö˜}Z÷çè³Î¾œÎvú[:nU:¶ sôœÓ9>µó™ŠôÑoNç u¾§ó9Šøœ7<ô\yÛ•Éÿæf*ßnç\S ½üÓøŸý,ÌöϦv®3‡ÎY…¥iÛ²lñµ¦@ÈcØ9Žy|Aç_ZfhWÍLƇÀ²DI騙ïžçÁ¶m(ŠÂs(—˜"ʶ ÍU%ñ¤‘»kk•¨ìƒÆó±³…É¢è2¾4®l wÏB‡Õ;KZÙ5Ð`¥ô_ò¶ÀÙ³gqéÒ%´Ûmlnný¡—.]Âáá!lÛîŠÔö»(ŽŽŽ†7uô¨ýÓz=¾íÛ†Ü§ØØ2Tš]áÊšV@Â&SGÒØÈŠ Ò™†u|U“&z×øÒç†(ÝHÑ9GEÚ§|±iã GŠéýŠôUzl"6leé5²KÇæKûSRÛÑùüÔwþá¿ûa|òò'‡üâò1SùÎ-~î¹çŠ]%Ç ŒêkÒóòk(uˆ® 2V²Hr¥õø’÷ôµäC8…Td;aìÎ6-õ±c…äË@œ•]@×ÐÙ·Šøš±Rû—¿:oº†èzw¥×øï¢ÚùŒ)7°˜©ŒÁÐA€0‚¢À¶mAÓ4‹u½03¥²B4©MŠšlÓŒÇú¦3,Ë‚aÜXȼeÜó Z]a#¾wˆƒ&âûð„^A÷šmôÖÃè5Nç5i§2¨ÌοVçsHGÐ|Lˆ{>¾t$u]¿ó¤G¥íDZÏ’V'wÓ%¹¹Ò8{xxˆ‹/ö,à>::êùÞ«W¯öüìÏ|æ3xÿûßßU<ž†ÚhÓø»·¾õóxéKÿ+€¿ÞýbâÇ$¡p:d‘R»à óžBá-:ÃÜÓã”ê`)Ú™÷½½>+¯R-VÚ•§Ùfêó/]º„w¿ûÝxÑ‹^4ô×6ˆiÉ7<ù䓨ÙÙ®ë‘g4Ó ÒÁóåÅÏãcŸþìÄÏ3ò‚©#ö$ÊF¬äØ ä×d9yy— Ö´qWGv:¾¼à§Gi'L*º3)äsN¿ãÔ‘”kùµ²¯´1VO½Çì|‡.°óïwðØcaÌ{ ÏÂó„"?”Ô)üûÊOý6þ÷ÿõzÓ'„ÝÝ]<òÈ#8yòäD÷;óõ;ê÷¥i"‚Z¯‹hª¦õî¤\×Åþ,æúFŠX™g&ÊÎŽX¿{u¬ß3í LÆë ¤(Hêìd¤R¶`ú8Ó—X}Ÿ²ɉît>» q_WÐ}e‘ #]¼†X/ Œ+ ‘ÁMÈ#>)šK¯!ç9•’^ÙOÏÏÙÐ6 ÒÁ‡]¿Çî<Ê®¬¬DuívO=õvww±µµÕ÷âìבøŽ;îÀÛÞö6œ={¶{£äýÐõ¤gò[¾åÃØøÒ_K6í™$Å’” Š\È?R–’[VÈP_ph ÓåË—'¾ïiÉ7Ü~ûíÙ7‚5Ä“ÚÏþ \ëUÓü:´€úˆ@@\+ºôÿ~FW/ú»zÉdkÈýLŠ>„Ä1ëïÉ9t°³³3•SœËÞ‡ ѧܺºë « ñ•Ÿú)¼õßþ[ÔëužO¼@œ={§OŸžø>—õ[¢Vò,¥²§ A¥¬×jµñÒ©¬€2Wäè+¾éi;e”¨=ö=H±¥’^ÇæBY§GYm:†sĘ Äú=ic(Þú=5(À$?Ê˜Ò ŒMY¦¦Õ›,m7 r†«¶g•¦_ŸGI—†8PC·‘OÑß ’Žu9›MTPF$¸ÆGÕÁgn°ž>}ºïöS§N^ º8äÿEkÀöEÀtEG:Ó+œùêWãb9ý°W„„az0Sù’͸Rÿej5L”þJž:J‘ç U©™¹Œ@QD*p.1¯ÕD~e½Ž@Q°½½jµÊÆ*`¾²íyB4ó¤µ{ž‡Z­UU†!4M>=­ÐS¶ )§ò}Å“^'¿–!”X±‚J¥DdÌ©÷Q¹…a”VÐm@qtÊBòÞB(Õè¼OŽ&Q½ß eÐe!—¥ËM˜"¬ßá´_Rô¿‰þ2PÄ´äy“6bq-ª" ¡H5qå ðÚ#à™g€—ÁGg¾x:ðÏožy 7=vÓЇ–Û`ÍòÖïîîâÁL<7ȃ¸¹¹™¨{¥üyÙ+³¹¹‰K—.EÏyž‡J¥‚¡Q祀ñ ý›p¼ä%/+uÞ]„”^¦ÌT¾¸þ@öpÍ ñ–µÈ1¥dæ2>EÉi¬:®}ìc¸ç†loCUU˜¦É³‰™ˆyËvÞ_®ë¢^¯.»”ú'÷¡ ²ÒE.I‰%¥ÖE\'§0RÊ"¥G’Ý€02+ˆâqžù’äªt¬²áIÆ,ÿµÎçËõ‰ÔCƒØî<ßèl£ã¥×S/ ¹o‰Ü?cø›b ý¼eq6ö ȳìR&I/YˆŽôâCs‡t]lÓ¤í~Gð5-™9gYb¯VïV:y߯Û~UƒeÛpN¾o¾ñÍ8wõŽßq<Ô!4XO:•h¸DL#U8{ö,vvv°··yßwß}#í‹~‹~¬|ââ‹õPŠ”W¦ØLR¾£›>Õ\HX ëÞô"¬3îJË,•ñx^Ž!ô®‹o¾ë]x;€úó?ÏM•˜‘™–lëz>;% Cxž7z½µaœeE3ÇEn†(÷ºH—nd¥+RŠ#ÕÈÖDzJKÒ¤860Ø€I*²>›Ò¥ÉA@ÏÈïÇátz eUU….:çõi–ë÷XÐT €ƒM½C!c¾ÿ?-kY:¢®Ç²*½ç/?ùI|áŽ;ð__÷:|èe/‹^îû>Â0„ïûÑý5p†UUa×j0 P{{{¸îòuCÊ@ƒuuuuª9éYû^__Ç{ßûÞ¨Õö(ˆ~Ð^…ž)¾ïã¦Ï}® -˘Egªò=×¶¾íÓÍÁ)ò æ+〸Ÿ’8" “kº®ãŸüÁàô­·²±ÊäfÞ²…ÓQsCcÝäÑWÔ }ZŒãø/R¦Ž¬ì“r/G›õØÏЃ 6Ò“ ¶¥uÈ0fÜ(É; #“1fp1̤‰î·¾ŸPlj"R‹rSf–“ÈîV†"åºñk czÑOB¿tl4E6‚…älM ¢ ±Ž¸9•<–Ǭߵ€ (ä?z’Ø"7Tʪ-%£s˜#Š"ŒÚµZ žçA×u¨ªŠF£1½ž%` Áº··‡ÃÃC¼ë]ïêûº3gÎàÞ{ïE»Ý.Tj°Ð^‹d71‰O|Û·‰ÿPWºÅwB0Ë‚‚8Õ½‚DçDßÔÛ®ŸžÒgÓx†)›ul¬2 Å F4¶m÷Ž®Öë/Óèþ;O‹#ÛA R|=/®…6Í¡òŸ)‹‚þTU…¦i £• zöeb Áº²²‚«W¯Îû8G#´7wþŸÑ$Æó¤•”ÒÁ0‹‚‹Ø`íè1¶-ŸFÐ<ÿí†ð#“^Ô¸~•)‘§¾mq]7êNÈ0‹B?%ÞqœÄ "«fÑ"O2¾/ŒQ×£MõzRÁWnb´Ìá§—ÊLzâû¢;½i%¯” äuš$)ŠMÓ ëz"õ? CTRÓØ`Í`}}GGG8<<ìeÝÛÛ Ü"Qÿ×ÿÈQVj­(q¾· Ž1‹E*ºê8B´÷÷;Žhøì 7LþsåZ†™#a(eú>¾rç°,‹;3 G¿à¡ëºÝµ«Tû¸H0Pi†®K7,f‚/²Ð2=K¨Úqbc5âÎÁAÒˆÕ´ÜQý0 áº.\×E†0 c`éJÖ¶ts¥e —Áº¾¾Ó4qáÂ…Lƒôèè»»»ØÜÜ,TýjO¨B®Éc y­²€j=U¢ëØûíßžüçòuÂ*ª×ÔëøEË‚a¥n<Á,}é’éEñZÔ%'dÉz¿y̦h©aLDNÉ@ ‚¾ïG†æ° ’t],‰Ãô9šŹsç°³³ƒ{ï½gΜÁææ&VWWqxxˆ½½=\¼xW¯^Źsçæ}> ¼On­¡O{uTìêq R‚9-˜Y¨#$­>ºSuuϽâ“ÿl ó»™0Œ„¢ÄŽnjë¿¿?Á©4ë˜ukfŠx^ïm®ë¢šîPCÝhç­¯ÈÝz ½ÏAqæƒ6` óMu×´‰ª¶mG£¨hšÊ¨}4M‹ Ö –Ò)›Ë`]__Ç… °»»‹óçÏwmßÜÜÄÙ³g‹]½(t#³i|0Mr8é`‰”ÁZ{Ъ)‡ÛÄ›ÎÐç2L Þ`Yêõ {R*ˆÇSÔŸ!Œâšp:ÏÑåF:;•š„×<êÂCÜ8‡ †fÔHÊí¼‡öG×^™ëôøó—!'2}Ç”&·|ð¼øùÏûè'F¯`Ifê_2Âjµî.½Ôx†NhÒ×#³ðT«}lAB§™÷ú6‚Þ†!ÇA†‰HêþþþDô0MÓà8€å¬_r¬@l´¢ÝnGãkÖ××±ººŠ££#ìííasssÞç”ìôëÔ¯)…~Þ7†ÉK*c øÐxû >WGW™ÂaÛ6TUÒ¥&B¡8µGZ Êf ƒUî ž©¨wž ”1¹“¨ü%õ9òküÎûÒÇ£!VôhDµó>ñH ±èKé5d˜Àšôrö†‚8²Ýùž(pfu^ 9v+è¼GC<ƒ’Ëß—†äùË3-é{ì¬+—Wðõ%“û½çˆ¦ 9}%âµÓ‚›!1#ÐWÎÉ8K|¿»Dp²"©ÕjuâPUÊ ‚`²÷º!·ÁJЈ›ô—Õn·±³³ß/Pøå×¼ºóyH–`è°f ©™Á­aé²LtÁBÉ<@2BÄ0sƲ€7¾ñ9üÑ;߉÷¾÷½“ݹl¤%Rí‘Tªòè døÊäqü¤_SEw&{ªôÙ€V!2ŒÈ0¬IÛé5YÇ׫‡ˆl,¥S÷òœ“™z]žR%uÞ*ðä?z_¾üåX|údÌÔ©f=3Þóú§ú2LN§Ï ÖYf:Ê]ª[­¡ Vyô êK'IíÕ±zž3šç¶< m°.ᣈ Vt]õ}?6¼Y gÎÚ€ª#V\;üõ_üE¨ozÓèû!¢B>º•Y†)Aœ<ù8~au·|ðƒÀw÷w>ï³Ë‰>à9ŠtNªæq\Œë»ð<äÉ Êd¦þÉéçÓ†º¥©Ô3L®ÛÇ`Õ0½LGPïyÂX¡Kµïû°, `šæÌg}S+0…r¯ Ô«—$‡&:)EÉeËVgJ€Àâ¼½ ìgD6^ôÜsãí"ÍU¦ „!påJ·üå_™S™ªQe˜)CÌ´‡aÜßY¥ÛöH(†éEßI,Ó*7ÚÞÊ’aˆY©CÖRÚ¯çy¨×ës³t]ÇÚÚZw¶%¡Ô+n•ä’äËõ»ÞtwU†):{àw2µ2<“×®]mßD´–j̦àÜñoL>e‘{03"ËXDD'³nZ²Ió'=O(øºÎÆ*3QæbkÕë#;4ÇmÛ¨V«“í@?ªªBUÕ¥l¸”Ù` €º\Cé]RÞw4ÖFn„Á0‹@G®}ò¿È N píÚµÑ6"ªÊ: Sp(aæ†Ï~vò;—û0ÌéçkÉLý›F$ÊuEQ¸aˆ†JK86ƒ™>”ÛÅ4ç¯!ËM¥N¿º®£ÕjfŒ 5vZF¬ív»»»wttt4ïsIB &äîŠ>¸Ã)S:r†’²#+ØA€Ã[oÍ_ç Éa%YxúOÿ/Ü~;n˜ôÎmðµÀÌ„^J|Ï”ài8؇¬çc˜Q°¬ãx©³ø¸¸®0PGpÖ»® ˲P­VÑl6 Y':ñÑm Äõ“ÚÑÊÊJ±FÚ„€óaq#y!DJd˜ƒ:²r< ļI†Y0xËç>‡•¿õ·&¿óåkÂÈÌ «ÇÚíû~w– E¢&M¿VÅ 3‚~ìªÍõ}q1 )ÇA R©Àu]´Z­™7Sbò10ÂJóWpµóÊfJ$æ¶§oÏ<ó ^–g'”\ŒŒ†ÉMËpÐþßžN”zL Ž®2 Kq–3ÇF…Fz,q´†™=©ž§“ßùö6Ðl•lÛ6ÇA½^‡Ñ·#3o&a-"­wIé’ €G^ˆB®Ô€Pô—3%œYp‹¿¬`{®ž8Ñ»Ö!„ˆªR«Ì"øÑW¼bò‘¡‹3Ö†YxzEž2S‚uŒ·^û¾PìY9gŠÄöï C!Óõzn‹˜¢ª¾ïcŸÕ` Áº··×•’rtt„½½½yûph®^^EzjI;m1å¡ÑˆÇ( >±²’ý&2V p³1fañ}ÀQëxÙk^3ù;ˆ9 3ezù[‚ èÖSÆ1XÉXm6§êb˜e½ ‘¼±!Úç4:-ËB¥Riš…­Ueº)ÂúàƒbgggÞÇ>ë×SOôó1Žg‡aŠ‚¬d›&~÷K_ê~ «UpÊ#³8ÈŒv†!ðè£_ÎgvÆF1Ì,è§/+YcøF¢Pl¬2sÂï%»!†wÂ8P«‰ô߃ƒ\órÇÁÆÆ`i»í.*åk£þŸ¦ž»å“QŽp çàpê³€PoDù^¿šm¢1«Ì"Ñ£{¤®Ÿý¬kצÏ€ËD˜¹ãgiøÛ†ÜQ•ЏY°±ÊÌ Eé1ÂÉÇðÙ^Õjî¡®¾ïc{{º®£ÙlfD 3å­a5ÿÑÔs·¿3úo±Ð²'YPº‡Š„÷=±(Æjl¬2‹EÝktaˆÛn»6t.NffD¿F4™eKÃêÚ¾/"Qºž[Ág˜iP­öõAA#ÛÐb¸7d¬6›M4 6V˜ò¬~F£°~Pc÷Žªª"ÝŒ Vf©×SÞJ€‹äâOWÀ>8jÄ,>ºÇxÔjpÞõM\¾üìt>“ƒPÌŒPÕ!šõr¤dEdƒ@Ü(¸#0STúe´8à6ÇI6V¹gÍâS^ƒ5=ŠÉq€7þ`¢3êÊ'VÄpx^Ç™2 ø¡?*!>ðžà[_øÖd'`†Y4<Në+AïÃ/ÇÿøÏM^ñÀNLf6„:H™éÀ!²)ž'ÏHM%# ƒ#«L!¨TzÔ±ö žú¾ˆ®9ªõªµZÕ‘»†Un²tttÔõQ˜™­’Šºm­Vq:zøýÉ¿üx¤³Ôj©.ÁðÞ{ŠW|àøá—þ0ð÷ÁÑ"f±©¢Û颪C@Ó> E™pÚ€ N›gfƒx<«;†a·¢¥ØÛvŒY¬«««8{öì¼s$"¥atÍgzîEϱ±Ê,,a˜‘!cÛQËà©(ò 3kBĵÙDªŠÀT5œühÂ`eýŸ™6 `¾b&v Ïóº£C²3…Ò%÷÷ÙXejIøË™Ê†!lÛ†çyh4œ\RæZÃÚn·Ñn·ûn?<<mç•þŽVè™i3Mùö¼”ÁJM ¤±MÜ ™6S]Ã8R޲ú> iÓÑÑkʳôL]¶Q/­¢ç8².Å» áh1]’adf"ãjµ½“}>øàÀ}íííáèè(ª‹]YYÁ™3gpxx¥ìííEžVVV°µµ5\u¨ßè'ÿB\)ò¦N®{g’1S`&ò ¡³G™`Ž“P^lÛ†aÜ™ ³’qqijㅷ,ÀQÅÚ=²­ê"6T[ÏàK…ÁŒe)ï'íùìÍ ƒÕGf­+à ÃÌe]*Še #¯»¶möm´Z-vÌ/S‚I¸ï¿ÿþ¾¯»ÿþûqÏ=÷`kk+aÔ¦Y__Ç… ‘Ú§žz €¸0èÿ”š@ÿ6^}) ^ißžfÛ¶¡ë:§K2SaVò}p =¨×£üà àº./`˜É1+Oá"³ ÞkzfSšAÔľÐwfº˜¹l“ fÔ°†é6ð¸Q$36³–qÒ‘Xª©±ÝÔj5„aÈ#k–Öv»ÕÕÕ.#”Ò€ ÚNÂÞ‹•••ÄHœÃÃCìîîF†n¿‹‚æ¿æ!øþçˉ<ß÷áº.GW™©1+ùN 9_lÛN¤ö0̤™™Œ{ˆ …€ò3Ýc†vù$vvvpéÒ¥Ìížç!®ç`°³³ƒÇ{lªŸ1í5r#w_?âˆÇâð¥Q vwwñÀàñÇŸÊþg²~w Õ0Dr¤G‡„3&ðÖωV«Lé¡õ»_ßq™úúÝA×3êW)%8ñœßW¾=σçyp*¤ƒ»~L ^__ÇÑÑööö^™4{{{ˆºö¢ÝnãüùóXYYÁC=Ô•zЋ~©ÆwÜqÞö¶·Å3cÿ¯ÿ ¬Ým'ãdâ3û˜…ƒ<‰—/_žÊþ§!ßpûí·ãÂ… =·»®ËÆ*@8ÓŠÃ$™É.‰rµ‰L^"WJp ‚Lƒ€Y\Ξ=‹Ó§OOe ŸÙú­ÐÕ‡SQM_ר½ßº>È––Z¿Ç õc&ëw‡L„ä]Æq2B±‚0 Q«Õ8²ZFÕÁFX×××±¾¾ŽÝÝÝžžòÔlnnæºÀLÓŒòèÓ¯?uê$ÒÞ ºøÜ瀻bƒÕqw,`¦ÏLäˆ{ÅC,è¾ï³Œ33af2Þê P©ëµÃÀ†*€p³&73“íŽÁÚjAt¬–~‚ HÊö¿ÿ0ð£¯LÍ2c˜Ñ˜•Œ‡!üVúIt¯Ça(¦ôÐ_ht 7XZnru >wîqï½÷ââÅ‹ØÛÛ‹þvwwñC?ôC8<<ìò¬dáy¡ëzb?¡]]]Åææf"íÑó¼h0pnžx"2XÃ0„çy}b¦ÎÌäƪ+r]×åìf&ÌLÆ­ø¿® àc· VÚCˆ¨ª†ŠÙ®ßˆëRû-Ý® |ñÕÀ÷ÍûëaJÀ,eܶïCH¬åPÐñÒ#º†!666 iëïÌà”`@DYzè!\¼x1sÓÖÖΜ9“ËC9ùYéj”¶{öìYìììDŠWVVpß}C,ÖAÿúï‰î4æƒa¦ÍLä›ð¼Hyw]—ë³™™03€ªúWŸ^ûÚÄgu)1d¬VÁõªÌÐÌtý¶ÿŸþ'€´'R‚ñ1à‡¾Þ_ Sf)㪠hß ±–‡è=ÆÆqº:ê…aˆJ¥‚jµÊÆ* §Á ¯Ë¹sçpöìÙD!øúúz®ºUâìÙ³#±ëëëxï{ß}N¿ÚÙLÂxå­Ñœ>×u±¿¿?íï’af#ß„ïÕ*‚ @†<ª‰™ 3“ñNô)Êû£7ÜxIBæ©«0«ÌˆÌtýÖ„±Ù¦R#šDJð“¯þY~‹aú1K¯ªÞ€äz¼ ÀDÜtÉ÷E½GJac•I“Û`%Ò-±§ÅXŸ£iÐî ‚Ç®ë\¨ÍЉ\GA¨*ËâE)cÉxˆhôŒç‰QÃø7ÿ7°çùFQ¨ñ|UYÃÌ€‰¬ßu@¤A5û"²äºn<žì¥/íŸ2Ì0S`2>Õ‘o¹ô4Ý!ØóRCZEV$§3irÕ°."ÔùšÑ0¥Ä÷A)®ë²Œ3åB,¯ª€úÀë_<ý’è%‘ÒƒP€Z`c•YB!Ûi_:•0)P„2ÿ¶ÿÒ;•’a ŠçÖ¿AlœRëAê…a˜˜{†!Çáñ5LCGX ¸ S>|PUø¾MÓ8ƒ€)‘®×X.`¨ñ¾¨R!ÆÙ¤ŠÕjÂkcu2ÆX§aÒ”6Âzò¤ø·kžÔNÝ×®2¥Ä Š¬÷0D§M°ÕµZ–…Ÿ}îg¹0³¸¨Q“wüÁÿù0 7>s£Hog˜%íG¨:DC<7õB)ÍÀó<ø¾§Ã3ŒDi Vrΰ2Ï”’ŽÁêyË8S>ê Ñ<Òó ¬Šì 'dûÚxÓ+ßÄÑUf1ñ(ÑíˆýÖÇDÝ^œÌ,4¾è² ëÖ>rmY§3=)mJðÁX™gÊ‹´¨³Œ3¥¤£Øh5¶Lkµªÿ¼Š¿bü•y!ÃŒF@Úþü뎟úÊOáFõÆyÃüÿÛûÿhGò»>ð~ic°95Œmõx5‹%!iµ[{’ø!%ï91~.Ñ%Yf3ý$^)Ü'wžä$±tÒç9aÃé=W»<°.¹Zr¸Ív6øn3ó'øÌæµoçFCÓšÙ˜­ö 6îóÇWŸR©Tú­R•¾z¿Î¹§ûJºR•ô©¯¾ŸïÏÕ¨C­-¨¡ÁÆ. & -q £m+ &os•ôá­žçpr2r—¬1Ã: ÍCÛV"Ý»w/éC Š#] À•Ÿþiüî3Ïp5`ÒS£¡æ­†ÊpÏó°»»‹§9iÙÃJDD›½«¤«ÓÆ¿ûøñøßÿûI Ñê¹®Ѱ^¯×9 ’ÂV""J.žGºzýG~ÿôÿñ¤ƒ(>C<Ïcï*-„=¬DD”:®ë¢\žez¢ÍòïÿößFƶ“> ¢xD44:ŽƒV«…³³³¤Ž6{X‰ˆ(u8$˜tÅÑ´M<ÏCµZÅÉÉ Z¢…1a%"¢Tá‚K¤3×uÙC[£ÑhÀ4MÆ<-…C‚‰ˆ(UØ»J:ËårŒoÚ ¶möm¦¥1a%"¢Ta錋ÎÐ6¡À§§§I i õ k§ÓA&“A6›MúPˆVŽñMº[$Æ+•JÒ‡M4–ᤳeâ»Ñh R©pz­DjÖn·‹Z­†N§0MF#éÃ"Z Æ7éŽ1N:c|“ΖoÛ¶á8{WieR»èÒ7Ífá8žþyt:4›Í¤‹h%ߤ;Æ8éŒñM:[&¾=ÏC½^ÇÑÑQÒ§AIeÂÚívÑn·qíÚ5@&“ÁÎÎ[jH ŒoÒcœtÆø&-ß²‡6‡Ó*¥2a½ÿ> ŸÏû·åóyt»Ý¤-nß¾ô!¬E»ÝÖò3g|O&_–Û@×k™1>™®Ÿ{ËðíÃò{ó-ß…BµZ-éÓˆ®Ÿ{XÚÊïT&¬“Þ ^¯—ôá%ζí¤a-îܹãœ:a|Ovÿþ}ܹs'éÃX ]¯eÆødº~îa,÷ËïÍÇøžL×Ï=,måw*]štA<|ø™Lfäöÿðþ>ñ‰OàSŸúÞÿþ÷'} ±z饗°··—ôaÄî _øÎÎÎpóæÍ•?ïoÿöoãío;ö÷÷×~^‹Ä7 †Ù|Çw|{ì1¼óï\ûq¯Ë믿Ž×_Ý_ìAgq]ËwïÞÅ—¿üåÄ΋eød,×óÒK/¡×ëá}ï{_"çµH|³üÖOÜå÷§?ýi|çw~çÚÏ‹å÷d,¿—Þßþíßž»üNe†6nií~ô£øèG?šô¡MµH|À¿ü—ÿ2éC'š ËpÒÙ"ñÍò›6ËoJ£T ¾xñ"€áa Ýn—ûœ‘ߤ;Æ8éŒñM:c|S¥2aÍf³(‹C›mÛF©TJúЈ–Æø&Ý1ÆIgŒoÒã›Òè‘óóóó¤"J§ÓÁÞÞ²Ù,z½2™ ÇÎï#Ú$ŒoÒcœtÆø&1¾)mR›°jâ·LÜ/‹IÑJ1¾IwŒqÒã›tÆø¦4IuÂJDDDDDDÛ+•sX‰ˆˆˆˆˆˆ˜°&¬ÝnGÞÞét&nÞ¼ìýëÔét&îɶ̹¤éÿØÇ>¶Òû×éÅ_<òÉ'ýcyòÉ'Ï_|ñÅ•œKšÎ“¢EÅ·Ü®Ãçg|§í\iTñ=Ëýë´LŒoÒyÒ(Ýã›å÷vÓ=¾ÏÏõ+¿ÙÚ€n· Û¶Q«ÕFî»qã²Ù,ÇÁóÏ?N§ƒf³¹²û×iooÅbÑ?–b±8tÎËœKšÎ“†MŠo@ŸÏ=ÎøNÛ¹Ò@œñ=Ëýë´LŒoÒyÒÀ¶Ä7Ëïí´-ñ hX~'–úo±O~ò“çßÿýßï·Niñ ¶€üÄOüÄù“O>¹’û×é…^8¿|ùòùƒ"Ïo™sIÓyÒ¨qñ}~¾\ §és3¾g¹Ÿ’W|Ïrÿ:-ã›tž4lâ›å÷öÚ†ø>?׳üfkvvvpxxˆýýý¡Ûïß¿Èçóþmù|Þ¾ìýë”ÏçGöì’ãËd2KKšÎ“F‹o`¹NÓçg|Ïr?%'®øžåþuZ&Æ7éüá£X,âúõëKŸë«¯¾šºó¤Ùèö¹Çßi½–i:?÷Eb|ÚµšÆó¤ét‹o–ߤãç®Sù}a ïÍ(ؽ–Íf—¾Ý:nܸL&ƒ[·n Xô\ŠÅ"nÞ¼™šó¤Ùéô¹Çßi¼–i6º}î‹Æø´k5mçI³Ñ)¾Y~S˜nŸ»nå7{XSäâÅ‹†‡%t»]?–½Ýjµš?Ž>àËœKÚΓf§ÓçW|Ïr?¥“nŸû¢1¾içI³Ñ)¾Y~S˜nŸ»nå7ÖÉf³(‹¸}û¶›mÛ(•J+¹lÛF·Û…išh·ÛC?ËžKšÎ“æ£Ëçg|Ïr?¥“NŸû21¾IçI³Ó%¾Y~S>wËïGÎÏÏÏ×þN ÝncooŽãø·u:ìíí!›Í¢×ë!“É ­ôµìýëÒl6q||yŸœï2ç’–ó¤ñ¢âÐãs;¾g¹Ÿ’G|Ïrÿº,ã›ržMçøfùM:Ç7 gùÍ„5…z½: ­òµªûÓd™sÙ¤ó¤aÛò¹oÓµLÛô¹/s­nÒyÒÀ¶Ä÷¶œ' Û¦Ï}“Êo&¬DDDDDD”JœÃJDDDDDD©Ä„•ˆˆˆˆˆˆR‰ +¥V""""""J%&¬DDDDDD”JLX‰ˆˆˆˆˆ(•˜°Q*1a%"""""¢TbÂJDDDDDD©Ä„•ˆˆˆˆˆˆR‰ +¥V""""""J%&¬DDDDDD”JLX‰ˆˆˆˆˆ(•˜°Q*1a%¢ÄÙ¶ Ïó’> ¢µ[eì{žÛ¶“>%""¢•bÂJD‰+•Jp'éà Z»Uƾã8(•JIŸm±V«×u“> ¢Ø1Ö׋ +-Ͳ,Vâi+0Ö×ëBÒ@ÁÖšJ¥‚\.7r_.—ƒiš°m•Jſ߶m(X¹\F¡Pðï«×ë¨ÕjhµZð<…BårÙNÃ0P«Õ~<Ѭ&Å84 xž7cŒoÚt‹Æ>0>þëõ:Ðh4†® áyÆÈ5C´¬¨x–Û,˘¦9£¶m³¼¦²h¬›¦ ÏóüØ5 •J†a`lÏ‹=¬)Q­VÑh4®ëâÊ•+þR¯×ýû,ËÂîª¢³»» @UP®\¹‚V«5r¿çyð<»»»CÃÐêõúÂ'šÅ¤—ûe._0Æß´é}ù}\ü7 T«ÕÈ–~ÏóP*•üŠѪL‹ç pŒ²¼¦M²L¬{ž‡K—.ù–e MÙ`lÏéœwvvvàüÞ½{þm¦iž×jµó{÷îÜ—ËåÎMÓ½|ÿíééé9€ó/~ñ‹#qM´ ÓâÙ4ÍóÓÓSÿ¾pŒ²¼¦M±l¬Ky,¾øÅ/úõy "¢­“ËåpzzêOåó<•JGGGIÚFbšáÄÔ¶mÒõ¤¤µP(À0Œ¡V›pïQŒ‹ñàâaaŒoÒÁ"±,ÿGGGð<–eù ­Ê¢ñL´i–‰u©ÃáèèÈßv¬P(ðZY]JJ¥Çqü!_žçù‹pÈðßà}Ág‚« ™øM”“b|Æ7mºEcX.þ ÃðW¬äÖ ´*³Äó,±M”vËÆz°gP=®ò»8ö°¦@.—ÃÑÑJ¥LÓô[edùëð}R‰•’z½îWj\×:Ξh&Åø$ŒoÚt‹Æ>°|ü—Ëe”ËeT«U^3´ÓâÙ0 Ôëuø#ѦZ6Ö+• ,ËÂ¥K—P(ü‘1år9éSÛHœŸŸŸ'}¤¸®ë·„Ë%þ•Ëåü}Xe¦““ÿoƒ‹pÈ02¢´‰ŠñY0¾iÓ-ûãŸÒg\<ë,὆‰6Ѳ±.=´†ap*Ó˜°¦œëº¸téÎÎÎP(àº.J¥jµ[/‰ˆˆˆˆHkœrÁ! žçùج‘îØÃJDDDDDD©ÄU‚‰ˆˆˆˆˆ(•´lY~ò'O<ñDÒ‡»»wïâýïÒ‡»—^z ™LoûÛWþÜ<À›ßüf'}š3{òÉ'·"¾Àò[?q—ß›’¬,¿u”¶ò[›„u›lÃ…`+ >U,c) Óh[®e¶-Ÿ;ËðíÃò›t·-Ÿ{ÚÊoÎa%"""""¢TbÂJDDDDDD©Ä„•ˆˆˆˆˆˆR‰ +¥V""""""J%&¬DDDDDD”JLX‰ˆˆˆˆˆ(•˜°Q*1a%"""""¢TbÂJDDDDDD©Ä„•ˆˆˆˆˆˆR‰ +¥V""""""J%&¬DDDDDD”J’>ÒmþŸË©Ï0  PP÷ÕëÃg@¥¢þÇuÕó»îè}ƒçuõ{¡0x|¹<ù¹)ýGÅÓ,Ÿc0 õ7‡—® ´ZƒÇ˜ælÏŽ]áºÀÉÉà1Žœžªß[-u¥¢^;Še©¿‘Ç´Zê6ynßÄw«¥ÎµRQÇODDD¤&¬B’®pEW*ÀÐh¨ ¹$nŽ3H…TØ¥bN®».P«©×’ç&–58F¹P¯#ÇlÛêÿrLáʵmW®¨ÛŽÇ ΩÑPÏ=©b.¹œzîRIýnÀýûߊ¿ð^IúcÕ’$ŠÓ’§`|V«*v‚ÉmÇšX­×Õß >cÛV—8”Ø“$×óÔc$.%–äu õxÃP rmÕëê1—³$†á8,—Õy•JƒÄØqÔ}rÞž7œ4W*ƒc§R¾æGïk¯}dmŸ9é-Üè :‚u}©g;¬~ôGŸ@.÷çzm&¬+à8ƒJ²T@¥²+•ÇBaP•Ä ôü{]̦©#ï!0|Qƒ„a¹Üèk·Û¿Š;w^šÿɶœ4Šˆàg%IW8a-•q纃ë¤PôF†?WI6§5L__^sRf8‚åòàv×>Ï`ÃKðÜæaê©Õ†ß£àóN»öÆ ^w…‚ú,öö~À‡{B"""ŠÔ‡¢Hr'£Àr¹áú$…RÿFóŒðïQXÀ î6®+,—Sõ¥\n㘦ªÛȱÿ•× vX]½ÚÃë¯y®÷‹ ë$ñ³¬A2*•ëZm8‰”ÊcPðwIN%¸¤ g8áŠăõÕ3;îofašÃö¨„pÁcZ´OËs]ßáÏ7øÙG%‡áX8= u-TA7-îfËàãV96|N«jË¡»DDñ›e:Rи©ERy~çHƒi¥¢¾×l[=NN¥2/Çáyƒï–¨N ©V«ÀÏÿüG“~ëhÒ‘EêIᘒ)n"ØS)u„ðˆBÇQQ¦9œ†§2MÊ;Æ ×ÝféÀŠÊqfÉ>ð¸sç+s½ÇLXÇBN憃M~/—‡{eìu ß¶*ã’U"!­uÒ¸qp0ˆÃàô¢q¹Šk…ˆÒaRÏÀ´Æ™B‘¬¼?öØp%H¦ „箿üòøÀî$ýVЊD­O±&¨…‚ú. '„2bEÔƒƒÁ4IÓ‘¢DUÞÃu)YCâRŽK^'ª2%ü˜£#`oïÇ&ý±l-ÇÄ0\7T¹dÛÀ½{ƒÇE‚‚ëN…;¢„ÖBaðšÛ† kˆt¿‡ç¹«íE$J’ç©á½R £½Ÿã _"J'©dE™eNypz 0Ú»\ÈN’€ ž6n:Ì½\TÖÂÇõÅ/ÿ~t ß½ÛÃùyÒï8M" ¨üxÞððCÛV±ašƒÇ{‹ÂI¢,Ì(1L%¹Nùè—Y’ ~g¦›Ôy&-zéÒ Cþl+•á©L ?&¬}R·,ÕBvv–ô­^pƒ´såd¢õŠª4YÖ`±/@}ɰ¯ ié·m•V*ÃÃÇU˜¥²^àLFÆ`äP¸b¶èP±IëL^Ë}ôî°ƒuí¤‚ïyƒXÒ\˜Qâ)W«èm ßÇ‘<VkÛƒéH2;¸Ø¢”½áøYz0Ù0±~±&¬ívÅbqäöN§ƒL&ƒl6ùwÓîƒç© ÞÖ®všß¸øÒã»»êß““áŠ1Q”M‹ï´ Vš€ÁB™§$•&é] j4+2JÏ©,Ng𣽑³ ? o¶Î‘Ciªä1¾g'Ó£¤÷=¼X\­6œH.²8"­Þ&ÕÁWAFÕjà è¤x\õ,ŸØÖn·‹½½=8e<»Ý.jµ:À4M4d‰î_V°Â¨nYè(—[í¼QÒ[T|ËíIÆø$‹önÐöÙÄøN ×U jp%ÅryþJ“|KfÅ2€ñ=Žôž·Ë“z’ íŽZƒ‹È¥Oëà«$å¬e F|D­ÃØÔÇÊÖn·‹N§ƒããã‘ûnܸl6‹[·n¡×ëá©§žB³ÙÄþþþL÷/+8`o*ÍoR|ÉÇxëªÇBaxN-Î,éçº.\×E¡P€1®Zî3 … Fð5 —Ë!ª%Ž{î _|qîóÛ¤øN‚e ïÕ+G}·ÈÊÀðºe¾ã¼¸Õa|÷­–dT†Gãõ¤Í’æ:ø*ȈYU:œH+OXÛíöH… PQ»ÝÆ­[·™L;;;¸}û6ö÷÷§Þ¿ ‡E1ñ ó2'Íûže.%c›ã{ÜB{Á…8ïß–ÏçÑívgºX‰˜O0é ÷ ¹®‹F£1R‘&Šãz‘\×õ+ÚfÿC©Õj0 c(‰I­ü˜¦é?6êxåX§i·Û¸³ÀŠãâHGŒÞcU §=æÇñ²pò躮ÿ¹ËmÁÏ6øxÏó††.I2+I]¡PˆL,Ëå²§–eÁ¶m´Z-˜¦‰ÓÓÓ™bi^æœJyÁÉÆÏ?ÿüܳ)ñY%^VË–E‚½¥´¹¶-¾¥ÇTŠ\nzƒ m¶4×ÁçÕj©eû ÓäÚÛlm«O ú^¯7õþL&3ñùë·~ ŸùÌgÐétpx¸y{W“8éE”J|°F† †¾ ¨ÞÍ`e?8œP’…q½‘Rñ—ı\.û_©T¦&§ó ?Ï<•ûY“‹Û·o㓟ü$Þüæ7¯ä˜EÜ1þÒK/aoo¦ibgggâc']s²ƒ1)1gÛ¶ËÁ†ˆ`£Å¸á¶‹˜Kåryáä0möööp÷îÝ•>§®e¸¬ÐÛj # ö8Qú4›M¼ð xì±ÇVöœi*¿WÁó€+W#ldKJ?)¿;ÎP¹ŒM(¿m[í³ U6Ë¢¨š|=o=©ƒÏ[~¯-aíõzcï{øðáÔû§],ï}ï{ñ¡}(5C&‘áR1·,khhŸô ëM w´'Œs–Ê~¸÷*x߸ÞÊ(®ë²,”Ëå¹{‰ÒdggÙlv¡ÖIâŽñ'žxb®/‚¤ZÑý¦ÒàlŒ(—Ë83¦gUÛìððp¤iYº•áž7Ø ²\æ\¨M²¿¿«W¯®´ O[ù½Y„FV‚çüÓÍ$å÷ª’U Ýå· Ww52LÊáàèÒÇ¢uðµ%¬“.¼l6;õþUHrn†ëºhµZ°, ¦iúI¢iš8˜óÀ¤B¿î¤1—Ë¡–¦n»”ICŒ‹u'«Ò˜!/ÒàR©TÆÎ³¤Í’¦ø^Tpˆ¤ç©ÊçB°ùñ-ûén[<Ëá†ÎV«9e)8åhÛ¶GFŽI'Á¤zWp …\.çwÌRW“ÇÊô•·½ím+màHc|ËvI–¥ÊäY¶å¢íµ¶„õâŋ԰ þàÿ§Ý¿ ëj©‘^¥`/“iš0Mggg±Ì‹£ä¥!Æ…lÝùBí•õää„ ª¦Òß‹*•Ã"s9‘¤M‹oÙ‚PɪiêWá·m{hŠH0á /V'k\är94 ˜¦9vŠÇ*§šu•Ó£V=B&ñ-»pt Íbm k6›E±XZq̶m”J¥™î_–ë6¼Žƒ,Ø"óò …ÂÆ¥ù$ãq’¡ë­þ*2J`ÒÐ^Ò‹ñ}tÄ!f-íñ- ‚IC‹ëVü­Õ6g~_xw`xÇ€`"­#Æ%›òåº.NOO×Þpšöº^ã;ΆuÒÏÚV@Í;ÙÛÛC»Ýö'q?ýôÓ3ß¿ )ÜW]¦8ŽƒÝÝ]¿••÷í–dŒ ÛV›U|Èê»¶m³•RßórõýˆÓ'˜´+üQû ‡“œóós|û·ûJ'mñíyê'—ü+oÓ&Ìïó<Ïï%•9²j;0HHW1uÄ0 T8db¢´Ä·ã¨aÀÜB‰æá'¬ívÅbÁßmÛF&“ÁÕ«W‡î›E±XYè'ŸÏãÙgŸE§Óñ3ÏýËô«R¯×aÛ6NNN¸PÌ–‰Šo ÙZ6§”DUÙŠk‹J§´Ç÷¬dQ%¶#Æc–ý¶Epû(©\>¸-UðñÂ0 !BÏóðéO¯¿þúBÇöø¶,»¹œê9•Æ–´V3‚ÓDd+2™*"#θžÁz¥­4Ã4b¢:jµºÝ®ܶm£V«ùc×qýúõ•,ÅžÉd&^Óî_T.·š1ò¶mûÃY‘§(IŸ0ÍÅgÇA«Õ‚mÛ¨T*œsM#’ŽïYx°»Ë}'ç5n˜¦û$) ö–M{^IH …ÂÒ#5 ÃÀ>ð•¯ô¤#¾eñ¤´Ž2•„TzOA¹üËÑf锆ø.8g•æw¡V«!ŸÏµn#ŸÏãðð™LÇÇÇh6›kÙ;,.®«*-‹V\<ÏCµZÎÛ#-ɈZ­Æø¦åyƒÅ•t!(Cge{³qóû¤·K~‚ÉF8q”½·Ñyyår™£‰¶”̵,Ë_àˆÓ hËÔÅi{]èv»¸uë–¿ÇR¯×C§ÓÁõë×ýÛvvvÐl6G† o’Vkñž'˲P¯×Q©T¸­ ¥^«5ßð1ÇqP­VýU¬‰6Ù¦&«’|JÏfÔ…BÁ¿/80¸FÙ[ž¿P( V«1ùL)™s4IRmÛ†ëº~‚Ê¡½´ Y,,­#(.‹Å¡ ¥¥6ز:mÃ`µZ-´Z­DV#Z„ãÌ>ÜF ;::Jý*‡D³HëJÀ’,JRLHËф‡WÊcd!"^«úKªºÑjµ†âTæ ³qƒVŶÓYFSº]èõzC7t:äóyí’ÔE&yW«U‰tÎã£Mẳ}H²ÊEÃhÓ¥u%`×uý9áü}"¥ñsžÄ3øw¤·uï§\dOö/åP_Š«Ô4¯ NÇOR{½lÛ™«Ún· 6ÞD®;_‹¥ÌW=Õm'nÚ Ó¾ ˜¬’.d¥4ìé'Ãr%Q€J¥ÂFOJ­F£V«…r¹ÌEöˆ(µ.‹EìííaggÇß{IZ}{½îܹƒ7n X,ú«oªYÖz½€«ÜÑfš¶Ë„ëºLVI†œ%Ûb/SG Ãðç”rÏbZT½ÿ•­V Fƒ‰*­·µ¡E\888@³ÙÄéé)2™ ®_¿Ž|>¸yó&ŽQ,q°%;üÊð-.>C›jRêyvwwqppÀd•6Zµªb½RI.Y•J¿išLPiefÜÚvnÒóÜ_›1Kë6ë´%¢  ’¤FÙÙÙÁÎÎÎÆ÷¬³]Á–ˆtT¯×ý9JD›Êu{U®[x¾+ý´j«®‚c¶V«±G•Çð£y]ÔUÙ€ûêÕ«þÖ5:$ªbZ±ìAɹF´éÆÅºÌËޖѤ/×MfKéQ­T*¬ôÓFnËwïÞ½¤‡(öá ÍfÇÇÇþ ÇÇǸvíö÷÷“>¶µ‘Š<‡“£ <ÏC©T‚išLV‰`Û6 Ã`¢J± ®x½¬`C¶Ø¹® ˲X‘'mXÖpe§Õj!—Ë¡²Šæz¢”pœù¶)›W«ÕÂ¥K—à8NNNpzz:מ©D‹²íåæ÷Ɉš\.‡££#6°PêXVÒG@›è0é㊕·®%&‰ÖÌqÔ¿žç±òB4÷&¦´98˜}Ñ%‰_îr@Dº»° û­†·ùp‡½«ó°xÊŒþÿþO®›(ôwû?¹þ j)s€  Öÿ½Þ|%ð»Ùÿ¡©¤eÞu] #m-Û»*ûªÊJªDi1k±[²ê@}ǯê;7Xÿ ×ä÷yI}BêXàx=Õþßô¯CÕsä¹ÂõZû‹hQúÏaí'Iá54ØûÁPÂà @*…^ÿ>Ñüß =‡$°.Ô•¸ÍÄàËK¾¨Âk^™M€ýŸJè5ú¯³Ûÿ9ÞRàqÁ/ÀÕŸøÑ'ðùw}>éwü¥)­ëRÁJÔ4§S~r0å÷(ø#€þqÖ"çbtäƒFdÕ÷yqJÚÓvÚ«V«8::Šgô¬†gLÉÐÛ2TBec0‚É€Jd[ôX¶ú™7§–iT½D¦-ÒÆ2,o—•DÏ›4«ƒHÏ«'èQS§ä= 6`Êw¥ÞƒŸù•ŸÁ‡ð¡NšHOÚí6jµŠÅ"žy晡!R¶mãöíÛxê©§pxx¸™½­@í Nœß"s7¸ËÏæ Íå +çhGh ºU]+7›@zÆÙ›õ‰6˼«¨ª’oš&“UJ½I!*+ZÇ6”]†þN*e*O0±­T¹´ì(«;j ºoYÓ>Ѝ²*ü~@%¶6É´¦åw.Ç!Á´˜ 7nÜ€išh4#wJÁX«ÕpãÆ <÷ÜsIï|ú-~ÆK¶’Úù}2dõ*™ó±I•uR*ð[»snÈ=Q Ó½(ý¸0mŠI{TÊÞÚ± ÔwÉ*’:Ö%æ'sc5Ç: -êMÝnÏ<óÌÄ]»v ÝnN'éãO?¯ÿ!Ò7DNz5¯ô„ƒáùu»PþKý« ß >Wƒy%ôÿ ÿÈûÐèÿ.+÷nAA©­`ßì5lÛvzdÖM†s„´6æ™ÑÑjµàº.ç¬ÒFpµèR”z½ŽƒƒƒøÊv)#ùÕAD)t!›Í"›ÍN|Ì_íõzIïìd…Zôs4YBjÑ‚ò´‰"qCeá— Ô0ÜàD¸õ)Ü+$ÛÂ`o¸s|–¡½5Ä3<†Ö« Tÿ pØ¡j#‡Ëv ²’´uÍŠZÜÈ Z­†ÃÃÃÈ„´×ë¡Ùl¢X,nÖÖ6í)ZP ôh®l[ƒe×eÕ·à— TŠ™lñQ± œê]ZiåF¶,Kûã\öÌ“í ì—+‰mðñÜ¢ˆ–0-µ, žçÅß#¥iD’Ñ Òà$ LÁíEdXêZ6ÆÖÇ<¸ F\gÌßxýÇË”yi¬¯eÃ[¾ê-I¿s±k4ëÖ^ç¯m9ÏóÐh4à8ŽŸ†\.Ã0üº¥aGª†££#ìîîâèèÈñ´Œ ׯ_ÇÞÞžzê)\»v ÅbÙlÝnívÇÇÇxøð!®_¿žôû8»Ð\Œiq/¤õe[ÃâÃ{·•㌟¬Ü›eÖ¿1ŒÑIm®;XÅq÷àyxûÝ»I¿ Ë+^­šR±œT™—Ź‚ {MÚÎU¯ãW‘Õ /׿j¶=øls9õ¹NÞoY£KozÞðfžádƒñõx@*áX­GÔ¾ƒW(Œ¾–m«Ÿàk{žŠUyþðß8Îèk…ö xÿýû1~ÉiµÆ—çÁ¡À[«•`@]Ÿ- æËxLê;S¦¯HÂja(šýû‚m½²½I°ñ)ª!ÊÆ`K))SÊã›öQy$¸"¼íß¾ _“ûš¤ßí•r ØÖØjµ`šæêF H1n˜Ï—(fõúè×­Op¯ëºð<…B…B®ë¢Õj¡\.¯ä;´P(àèè¥R '''K—còù<Ñl6qãÆ‘‹EìïïoVïjÔ>bU¨¹0eA©ÔËJ¼ò….­ÉÒº¼È'•ÒpeØ4‡¿¥€A‚•¨†ú ×Ú\W•òøBaÊsEU²K¥Áÿ …ÑŠy¹<úZõúàqãÖâ|°’=n3.ÓŒ>¾`å}èóòÆ'¬Á$@þß?æÌ»ß |à |ˆ)Ò?Åœôbúo‰7ò8ÿzöxÊÜÑZÿ6YðÈíß–ƒªLÎRÆÈûzŸýØIhõ°VK%’ò˜¨¤óà`ôvyþ\nðÏ7*V=oôš“ç˜Tã'êoÆÅoÔmr{Ôpí\.úï&É倣£áã﫚&¬“ 9£Fò»‹Á¶i9g$á¿É!º!6ø¶FíÆfèïg-S‚¯þ¾­/}ÛKxpçÁzÞÓ5)†‹‚¥{Weº’ ²0Œ’‘z Ž£µˆkÆEs¶möm¸®ëá- 0M…B¶mûÃ}ÏÎÎVºîƒiš8;;[ɺAµ ðáá¡¿uM§ÓA>ŸG>ŸG6›E¯×C»ÝF±XLî]Ÿ‡ÿ‹Ø¯£˜¾µ… g¬@Í©“aRÀ`xÔ¸Eú\wPñW–.]$hr_¡à÷öErœÁÁ‡+³áJºÞý$Ö4 ªôH_3L¾%9ŽJjÃi"+›À°ÈßD5¼ÔnsNøN•@þ¨¤P0èm‘Õ¨ƒ•ÒT¥5ØQ'­í"‡áXŠz_ëõA§üc(*VMS%—óŒ‹ÄÝ"Ã+r¹Å^kZâUhOKœ£H£Õ„×~õöíùŒéÛh4`Æv®büˆéUK`ü‘ã HÁ"géÞUªl/ct71K7ÑŠ0Yçy~â)ɧôžš¦‰£££±eI¹\ŽuòU-r{!ø‹lqžÿÖét°··ßb.1’z´´Ž= ªrlu®VZŽxbËL"œ4<ñÞ+ÊLªd«Æà>ùÿ<=7ëX9™V£ß€â8 | ~åÃo!30º5RA7Ø“á8ƒøv]•\ŽK¬¦%vQIé6÷€ÑR¢Š4Û¶aYÖv¶– J…zWe(wªáñ,é³ ðýw­–ú99áPvÒ‚mÛ8:Ú¢½Å, ¯Ðë@%¬IOß• UT¹2î¾àjóB’5YX,ÉÝ“öæ^¿GgãÈ©Á¶U˜£w•ÃÙ½aÜB™Q½û² þ¼Ø³0Yá}[r-ÇqP­V‡öB]T¹\F½®&«§º¡6F©žÃÚétÉdÍf~ŽpyäyþÄŸÿÀG7ÊœUD´FËÆwÔw­ 3bY9@‰XEŽ:Ô‚B¹ÑŽã ­œ¸2.T2¼d< ¨$A:YrÇ„{Fgm@÷ÿ®wÍõ”d\´èõzèt:±n6›8>>º­X,Bz{»Ý.jµ:À4M4…Þ/`´yäË€=O´BëŠïà(¦ Â*æ‰M°® †Mö+óáï}×uãÙ{µ •ˆÊ¥t*‰­@%Q/9ODrÝAâ9mOoÓ?л&¸Fkmîïö/GŸT¿‡WKæ>oRÕEº’¥7ôà`8–]WTœËµ1ëÐ[šÉºc\èú¶Z-X–ÏóP(` ÃÀÙÙj[“$_“mnÖJ’Î`"*·Ñy”e ß&I™i¢w÷.¼þú\‡0ÒÃzóæMÏ^h.àþýûØÙÙjuÈd2þÿoܸl6‹[·n¡×ëá©§žB³ÙÄþþþ\¯Óh ¦ÜLÄd•VhñíºªÎ» R ­« ÷Ö8‘JmÛ+i¹ö{Nm z«Â×Õ¢õé%  Õjóïlã䯬5¶ õ­@í/ n’JïTҽؒŒÒpãŒ$¤A¹¿ÔÖ`íåw_£1<’`“ÉâI–eùsRãîõ”y¬®ë.7‡5˜tÊ(ù.=ºG& ÃßEã“ c0Ç!ƒGÅWæ\4/‘!Á>D±XŒìÅív»h·Û¸uëuíììàöíÛs_,–„8âLĉ€õÄ·,¼9z;7:£ø­« ‡ U1¯8P/R¦O\{á!¾‹Ö“e¨nTУæÎl$M±µÅ6¸@®¬éš<²È—i.Ö@C±YkŒ÷IÇú¦'¬¶mû½ÍårgggñŒò‰`š&J¥ÒôÄXzC£9ww÷Éq~£Î%j~IXÛí6LÓD³Ù\½zÕ¿pîß¿Èçóþãóù<ºÝî\¯!-ñá÷>õã¾iã­+¾£xž·š^'¢ ÖãTÂZ€êýÄpî·ðüU*Qu †TŽâ;òwýž¢ðÞw…Âh¥€C7ÖÚbd»÷*üÞÒ™Õ«P .' ½IÒ+##¸woø1Q=5” kñ¾Mï] &ªµZ-‘z–4Ð …A/©Ýÿr ŽbPŠÞFâ$©BcyoJê…eü|¯×ÃÞÞnß¾ /ŠIûÁþÖoý>ó™Ï@ö•µ¬)kJȪr´unß¾üã±ö¶¯:¾ॗ^òŸkꎭÖ`.m½½=ܽ{7Ö׈»  ’ÊÀÐÇࣙžh¸„Áʾ’ŸA-Œ4-Y•yu¥RôýR1þ0YU³ÙÄÇ?þq|îsŸ‹åùã.¿…ëOërû?˜Ðè( jDÀ:뮫*UÕ*pé’úW†Öj£É*-EÊo™C‡µ”ß}2•qÓÚÒ=ÏC½^Ç¥K—`YjµNOOãOVm[eøõºúÞ¹tÉ¿«\.«×÷¼Á5hšêËñÞ=5¤þôT5¥ô —:ø¼å÷Ú{X»Ý.®]»†§Ÿ~Ú3ŸÍfÑl6±³³3ñ‚xøðáÐ8û ÷¾÷½øÐ‡>äY°íÑ©CÃ%-‹­[jggÙlwbØt>®ø€'žxÂ_á§~*z䆜‹î ¢­qxxYqX…u•áÛÆ†ç¯N݇ÎÁ`Qj±$1é;ÜqTcOðâ²,U)ß²MÚÓlW¯^]y¾®òàŽ~0 P é¸vìB [7ïV6Q«ùGð:ˆ”ßÁ^ÎUYkùÝ·iëmxž‡F£˲Ö3ì×¶Õ÷ެþ.?Ãé‡öoÝÐfÑ:øC Ö¨ÊÎ*ölÍf³#½³³ƒf³‰v»=ñuimYH1_®ëºÒ¹xÅ`ñ ¨ŽžXf“ÇßPj­+Æø‰¦óÐ8N~±ÿû¤ÞÕÔ_éš·¨7Íá/ ­ÐüÖÛ Àü†~U$5ìÝŒX‡@’ÕÌ˳’’¤±&œ]ÈÈÚxkq¨Š™šF®ë¢ÕjÁ¶mT*Ü[å骀 Œ~§ÈHŽÌ™èµk×FnŒsK›v»n·‹ÿ¶‡P“»¥õ¦ÛíúGðÿ³šXW·Ñ’ÖßãÂw¨‹\P ÖãA­Û@ùKƒß=Y?È…ZœÉÃlóRm{t¡Ù×”¶ÒZc;ÔdL`žöÐ`ƒd5ްt]5ôжUïéÉÉfd´°u—ß›Òv^¯×ýa¿KmG#‰©L9“­`dªHÔõÅkn&–]¦z^™LÆê -9ÇÇÇC¿‹Å¡ÉlÛFiÜü¡\ýŸ’²Žø¢;}†*ñ\-˜b²®”œö¿ÞÁch…ààj¿5 ÿâyƒJ:÷ঀuƶÛïÈ7•ŒFÙ%¨˜^u²jYƒ-g*óÝ"k-¿±¡Uí¯÷1Wª¬‚nà”áo• ‘[ûÖ|>k׮ᩧžB±XôW$ nJ¼¿¿½½=´Ûmôz=d2<ýôÓK¿¶-ÝñÁý„ˆV(ÉøªÄ3¾)&k‹ñþ–6þzÔðÈ~ýÀu[=“êÁUM-Kõ&­xSwÚ|ë,¿ †á‘¶þb€uŒÎ¿^ÛVjóÝ:IÖQÒ¨^¯Ãó<œÌ²znpè<½<׉Íèt:8>>Ƶk×ÏçÇÎ ZÕªªûûûØÙÙñ/”ðä|>gŸ}Ö_!m•C”MÓdÂJ±J2¾ ÿç ÑŠ¬%ÆsNk·?¤Ì‚Ÿ°:ŽƒŠì 7©~Ðj *2‘êô”å?µ®òÛù©PïSÿÿ~ý«‚øæ¬nB·Åf]1nYª:’¦edžªüßu]œŽ[*¼u“,fÉ¡ó‰¸`Û6jµ²ÙìÐê_ûûûÈd2°mNÏ>ûìJ_8›ÍNŸÉdâ›K+«2Å$‰øöë·"Ñ ­+Æý%<øóü.ñ2r»¹é Ñ+4·¸cÛ{ÀW…nìÏcýèo|Tý¾LÈzžj¨‘á iÊ(ÖQ~§m¹˜F£V«…J¥‚B¡Ã0&olì ­ÖKëwáÆ0Msh8 ZXŠÅ"vvvP«ÕpóæM¬{¾kl¸°iȲ,IË9‡zѦë‰ôì(@ÍUÔþmŸÂôJ=‡gQ 9ŸÌo½ý?ÿàÆ/ã/ã{ñ½ó?© W”_*6ÖP¢ÒÒNâ8ªÕ*LÓÝ¢FzN=O]3i<\èõzxæ™g&>è™gžÁ‡?üaïœMå#cež4ãºîðÞ”¬¤Ð¦sÔ€Š×üá¿_úo¾4Ø‹Rz“Z-÷¥` Ƚgôöÿðÿþþ(‚™ÉÞÁŽ3è bƒ<€Áê¿GGGjJ |_8Î`z`¡À¼`là±;Î÷g¢†‹Å¡áÁrÿýû÷7:a0y³y¢ %\iÃWÕ'üñŠjxô[È=(•TeãìŒC¶h#¸¿Tö–~E¶Ìà¼TJÇQþIuRŽôª:°»«¬\æêØq…£ÝrPóò-àþÜçó=ýÙ)èðð0éÓ^9™\M¤#˲f[åŽhSäTCxx%U$$«•ÊèP.¢3rfôvÛ¶‡‡+Îôdì¢ôIríG™«ê÷ª Ž>XŽ$¢¹þO«ÿS†Ú~KÖ™00º—k'ÀƒöàÎ|/¡×ë¡ÝnOœ\Ýn·`¨×uÓÈDk"ÝHC G6FôH-µú+WT„å:m˜Ê·bìü뱋À¸.P­ª.+Vº)å\wým)®ë¢Z­â[³ÙѹªlØYŒ µB¿ 5 ÇÀ`«­ †·Ýʈ±GýMù|Íf½^/ò½^ÍfÅbÑßTxÙ¶­V™ïA¤ ˲†cvw“>$¢åxrѹ¨çyØ}ì1Ua²J›hÞÁ0¶=MÀd•6ÀºWn4(•J8Èåð#¿ú«08¢r:ê»Vþ_‡Úÿýÿ— ’UjŸó#¨„4¡¾‘ ׯ_ÇÞÞžzê)ììì %¥wîÜÁíÛ·ׯ_OæWÀ², kXå ­´Z-œ nð¼ÅŸŒ( lÀ{๣ŵçyøÚ¯|…óUI;Cû YPìä„É*mŒuíéy~hoWåWðëø‡xÀÕ±ÃZP‰g •ˆæ zMsô ±ö”.êB>ŸÇ­[·p||Œf³9ò€\»vm£[jµZ8Îüf “&ÇA.— }a«"éà°Z€Û]´Ãu]ä¹'ijhjGpõkÆ;mˆuõ®~ég~Î_ûkØ{Ë[ýÿGµà¯“A‚z•ˆ0HNÇÉ!±žÓY]Ô*Àׯ_Çþþ>:Žg>Ÿßèy«À`»^Ⱥš}ˆÖ`(¶ßl…' Œ›å&19Šh ¼àèÛf²JÉqâïzõ{¾¶mãÑ¿ö×ý‘Iú”×KVâu0ÒëB ÛTâ)É*0ºÒ†ºü%“ÉL\|i,¶äy¬Ð“6lÛn‘çp`Ò„ã¨5•Âæ^E•hCø «,°trÂd•6NÜK X–…ú¯ü N~áÆ/R¦‹*Tb*³¾džijeÞ¨Ó×´=÷ÂòO‘n#sB8d’43”°®£i“h ¢ÃxžÇ„•´å—冡zVY– ©×ë°m{t`¸PCy]¨R@mÜ.6…sK×Eû„ÕuÝá =¿H#Žã î†bŒÓ†sÝè0vGÿuÚJCà ƒ=«D€ßhå2ªý-ÍNOOõHVm¨äÔÅ`SÙÓThÚ[ºˆ7%}qò7˜Üô!­”ëºÃ·ã°¢CoÜ¢žçá?ÿyU!ÒcˆZ-àÒ%µ³G­æ'«GGG›‘¬zÌ3—wt0Þ{5ì·†Ô/~”­{XG¾Ö½1QÌrán¨\Ž1NZˆZWÉqìüþï'}hD+çrº‘êQ­×U=¦?,¾Z­PÉjjÉp^§ÿ#U³2óLï…þ¦6ÛS“¢uÂjÛöpKŒiruIÒ†ã8£-i.ЉfT.¿ïo~3eH;¶m«é2lz‘ˆV©^W ëÁ_WOu²êa°oijøî¸…hiZ'¬žçÁd‚JšòN¤9Çqð ¿û»LXI+®ëÂu]5"¬^W#eâ^j•(MúC~qvæß”êdu*a=íÿ~ºÄsÑL´NX]×eÂJÚÙÒ†h |í+¯°÷‰´bYÊ2¬Àu'1 ÒQ¡0Ô™ªdUEr0X±—=©k§}ÂJ¤3&¬´-¤Š«`“nZ­ΤgÉu9‚€¶ZâÉj½ÿ¯Õ‹ ¨á¾ÁA¼D×NÛ„uh;ÇQ+q˜ iÄßÒÆuÕ¼Çj5VèIK­V ÿÓw|ð&­·§-#‹CnÄʧD1«×U¶¸ÖdUL’Ed`f\±7E´ýæ÷W.•Ô¹‡ÙV\×…aÛ*Æe“UÒ”eYø‹æÏp80i¥Õj ¦.Ù6ËpÚž\¹2tS«Õ‚mÛëIVƒ»\Ö1X< P « &«)£m«ã8øÎ¯þjõËÉIÒ‡C´r¹\N-ÐÑ_úHW–eÁ4M¼í÷~+½“V†*èòNÛ¢ZêDjµZhµZ8=yõ"@ j¸ï)TRÊa#h›°º®‹â/þ"ð¯ÿuÒ‡B´rŽãàoÞ¿Ï^UÚ –e¡R©0Y%­Ø¶=¼0¤ë2ÆI®«~úIÁd5¶¡ñ.TOª5ô——ÙÆÑvHðŸýÅ_Ä[¾ë»X™'-ýçÿïñgÿ¯ÿKÍY%Ò˜ëºp‡+¾“vÇ^8ÏqXg!ýÙ¶ß»jYV¼ÉªµM @ªW•_%IÏ„Õó°óê«jóa" =þOþ ~í/þEÎç#íµZ-µ¸‘fü½WE¥Â„•ôgÛ€iÂu]Ôëuœœœ¬6Y•mh57µàTÂJKË„õßýóŽö·}+ó¤­Ï=ú(¾òôÓIQìlÛÆn©”ôa­ÜÈ`. IÛÀq€B»»»888Xíö|.Toªìj™{T5¡eÂú5ßò-xõ¯ÿõ¤ƒ(67ßò–á–y" yžZÊñT*jk2"MxžÇ}´iûô“Õz½Ó4Q^E#M ƒ½SsP½©ÜÁR;Z.ºT(X™'­¹®Ë}ûH{¶mãÿóæ7…{ŸH+þÖ{DÛĶñÅ?úGaYîÝ»·Üsµ4 zP™ jOËV"Ý-]Ðm€ßüùŸÇ•ßüM®G@Ú±m{ÐÃjÛj_J"Ý•Ëøÿ½ûÝËõ¬¶\‚ö{ àÛ~´Ç„•ˆˆRé?ùI¢•s]Wõ°–Jj§xЖ°mGGGsüT’ZƒJRi+±‡•ˆˆRçµ} í~0éà Z9?Y•…Ä8?›¶ÄÜs·]¨^U^"[=¬DD”.®‹?rv†?hµ’>¢•ó+íõ:pzšôáÅÏóÛ†Þ{xš€³¤žÒ€=¬DD”.®‹F.·ø<'¢sãóŸW=«ÜÚ†¶A½8Ç™¼à’ µòï%ÜÉŒØÃJDDébšøùGAƒóúHC/ÿÛ‹÷v»ÀýXÒ‡B?YTìàÎ¥KÑû{ªP kjQ%¶åPV""JÛ¶¹G%i뇿áð¦¿úW¹Ðé¯ÑPÃON`Ûvô¨*Y­€û©ÒXLX‰ˆ(U<Ïãp`ÒÖãÿïl!ݵZja±þ<í± ‘ p/UšŠ +¥ÊR›Ê¥“UÒã¨ÞÕ³3À0ày,ËÂÙY¥T‚Zp’ôÁÒ&à¢KDDDDD´<Ïvw“?Y-•J¨Õj0 C%«6Žˆ§90a%""""¢åypp pW®\ÁþSû¨äúT+P½ª\T‰æú„µÓé Ûí&}D±`|“îã¤3Æ7él¡øÎå€rŽã`ww¿ð—O7ŸV‹+-(µsX»Ý.jµ:À4M4¤‹h%ߤ;Æ8éŒñM:[6¾ÇÁßù¿ÿüò»™_Ïp›ZZj{Xoܸl6 ÇqðüóÏ£Óé Ùl&}XD+Áø&Ý1ÆIgŒoÒÙ2ñíº.Ž¿ë?÷‡?‡ÌßÍpø/­D*Ön·‹v»k×®2™ vvvpÚ_›h“1¾IwŒqÒã›t¶l|¿ãÁ;Ðx¬·üë·\ðV$• ëýû÷ù|Þ¿-ŸÏsžHßÞÞ^Ò‡°Ífív;éÃX9Æ÷dív{kz*t½–ã“éú¹‡± ß>,¿7ß²ñýö?õv¼õÅ·jÛ«ªëç–¶ò;•sX']½^™Lfäö;wîàŸý³†O}êSxÿûߟô)ÄêîÝ»[qÁ¼ôÒKxá…ðö·¿}¥Ïû…/|_øÂðÖ·¾ûûûk?¯Eâ~í×~ ßñßÇ{ ï|ç;×~ÜëòàÁôz=îŒÎ⺖ïÞ½‹×_=±ób>ËðåŸ÷Áƒø†oø†)ÃY~ë'îòûÓŸþ4¾ó;¿síçÅò{2–ßË‘:ø¼åw*Ö^¯7ö¾‡F^,O?ý4vvvÍf“>üØu:¡–/]u»]<úè£c¸eôz=<|ø0‘óZ$¾àÿ㼟»|6¼–— ŸŒeøò6­ gù­Ÿ¸Ëï¤â…å÷d,¿—·HùÊ„uR Œ»2™L,ojmÃ… Ö‚/ÉxY$¾§ýNx-§ÿ¹—ym–áÛs-³ ŸíotÂë8ýϽÌk³üÞžk9måw*ç°^¼xÀð°„n·»-7¤?Æ7éŽ1N:c|“Îß”F©LX³Ù,ŠÅ"nß¾íßfÛ6J¥RÒ‡F´4Æ7éŽ1N:c|“Îß”FœŸŸŸ'}Q:öööÍfýIÞ‡‡‡[3ä€ôÆø&Ý1ÆIgŒoÒã›Ò&µ +€¡•æŠÅbÒ‡C´RŒoÒcœtÆø&1¾)MR°ÑöJåÖm2nSÞN§3q/¬eï_§N§3q‹eÎ%MçI£&m:­Ëçg|§í\iX\ñ=Ëýë´LŒoÒyÒ°mˆo–ßÛkâ[ŽE‹òûœsÿþýóË—/Üö}ß÷}ç—/_>¿|ùòùÇ>ö±•Þ¿N/¾øâù“O>éË“O>yþâ‹/®ä\Òtž-*¾åv>÷8ã;mçJ£âˆïYî_§eb|“ΓFéß,¿·›îñ}~®_ùÍÖt»]ضZ­6rß7Ífá8žþyt:4›Í•Ý¿N{{{(‹þ±‹Å¡s^æ\Òtž4lR|ú|îqÆwÚΕâŒïYî_§eb|“Γ¶%¾Y~o§m‰o@Ãò;±Ô‹}ò“Ÿ<ÿþïÿ~¿uBH‹O°ä'~â'Ο|òɕܿN/¼ðÂùåË—ÏŸ÷oËçóþøðeï_§|>?²º_&“Yê\Òtž4j\|ËÅpš>÷8ã{–û)9qÅ÷,÷¯Ó21¾IçIö!¾Y~o¯mˆoy]ÝÊo&¬)2éÃîõzKß¿N™Lfhôn·‹f³‰d³Ù¥ÎåÞ½{©9Oš.Ÿ{œñ¶k™f§Óç¾LŒO»VÓtž4;]â›å7EÑés×±üfš"“>è‡.}RçÔl6ñáÅb×—TœRžIDAT¯__ú\_}õÕÔ'ÍF·Ï=ŽøNëµLÓéø¹/ãÓ®Õ4ž'M§[|³ü¦ ?wÊï kx¿hFÁîõ°l6»ôýëÖétpãÆ d2ܺukdøÀ¢çR,qóæÍÔœ'ÍN§Ï=®øNãµL³Ñís_4Ƨ]«i;OšNñÍò›ÂtûÜu+¿ÙÚ"/^0<,¡Ûíú°ìýëV«Õüqôá_æ\Òvž4;>÷¸â{–û)tûÜñM;OšNñÍò›ÂtûÜu+¿™°¦H6›E±XÄíÛ·ýÛlÛF©TZÉýëdÛ6ºÝ.LÓD»ÝúYö\Òtž4]>÷8ã{–û)túÜ—‰ñM:Oš.ñÍò›¢èô¹ëX~?r~~~¾öw’ív{{{pÇ¿­Óé`ooÙl½^™Lfh¥¯eï_—f³‰ãããÈûä|—9—´œ'߀Ÿ{Üñ=Ëý”¬8â{–û×eÙß”ó¤h:Ç7ËoÒ9¾=Ëo&¬)ÔëõÐét`h•¯UÝŸ&ËœË&' Û–Ï}›®eئÏ}™ku“Γ¶%¾·å ¢µ[eì;ŽƒR©”ô)ÑkµZp]7éà Šc}½˜°ÑÒ,Ëb%ž¶c}½.$}¸®‹V«5r{¥RA.—0hÉÉår0M¶m£R©øµmÛ V.—Q(üûêõ:jµZ­<ÏC¡P@¹\öŸÓ0 Ôjµ…O4Í,1FžçÄã›6Õ²±Œÿz½Žƒƒ4¡kBxž‡F£1rÍ-jR<Û¶ ×uaYÀ4Í‘•Ûf-ƒY^SRVëžçù±k*• ÃÀØž{XSÀó<8ŽãÿضíW^ÔF€jÑÙÝÝõ/@UtvwwýçºråÊÐE&÷{žÏó°»»;4 ­Ñh ^¯/üx¢i¦Å8T«Uÿ÷`Œ1¾i“-ûòû¸øo4¨V«‘-ýžç¡T*ù!¢U˜%žƒ¢btž2˜å5%eÙX÷<—.]ò-Ëš²ÁØžÓ9¥Ê¿øÅóB¡p^«ÕÎÏÏÏÏïÝ»wàüÞ½{þcr¹Ü¹išC÷Ÿù÷†áÿàüèèÈÿ½P(œW*ÿ÷Z­æ?ß"'šG8ÆÏÏUÌ?:::7M“ñMZ™'öÏϧ—ïá¿====à¿N0®‰V-*žMÓ-"ߤŸ„ñM›nÑØ–ÿr¹Œr¹ÌZ™iñlêõzäv D›dÙX—-l.]º„R©„K—.!—Ëqm=r~~~žôAÐx2ü+—Ëùû°ÊMÁJKpFF¤ Æ7m3Æ?mŠ`%¸  ‘nfu!i§2- kʹ®‹K—.áìì …B®ë¢T*¡V«q <i‹.¥\pH°çy0 •J…É*i=¬DDDDDD”JÚô°þ«õ¯ðÓ?ýÓø¦oú¦¤%vÛ²¥Çç>÷9¼ãïÀ;ÞñŽ•?÷k¯½†?øƒ?Àþà&}š3û›óo⛿ù›“>ŒØ½öÚkxíµ×x-¯à¹“>Å™± ×OÜeø£>Š¿ówþNÒ§9–ßú‰»ü¾qã²ÙlÒ§9–ßúI[ù­MÂú‡ø‡øº¯û:\½z5éC‰Ý /¼°çùòË/ãþÑ?Š÷¿ÿý+î»wïâ7ó7“>Ź<|øp+>÷»wïâ+_ùÊVœkœ×ò /¼ôéÍ…e¸~â.ûÝnÒ§83–ßú‰»ü~ôÑG“>Å™±üÖOÚÊomÖ·¾õ­xÏ{Þƒb±˜ô¡Äî{¾ç{¶â<àâÅ‹±µ0öz½¤Oo.o{ÛÛ¶âs¿xñ"Þÿþ÷oŹÆy-¿ýíoOúôæÂ2\O,Ößú‰»üÎd2IŸâÌX~ë)Måw¢û°öz=t:±÷w:jA]—¤a-ŠÅâÆ ‡‰Âø^L6›Ýš/ƒM¿–ã‹ÙôÏ}V›\†3¶Ãò{s0ƳéŸû¬ÒV~'ÒÃÚëõpãÆ o¢|>ëׯ#ŸÏºÝ.jµš!™¦‰F£‘ô{E4Æ7éŽ1Nºbl“îã´‰éam6›èv»xþùçá8²ÙìÐâ 2ÑÜq<ÿüóèt:h6›I¿WD3a|“îã¤+Æ6éŽ1N›hí k¯×ÃíÛ·qýúu|þ3Ï<ƒ‹/P-;ív×®]d2ìììàôô4é÷Šh*Æ7éŽ1Nºbl“îã´©Ö>$X†äóyt:ôz=äóyìïïîß¿ïß/òù<ÇÑÓF`|“îã¤+Æ6éŽ1N›jí ëÇ{{{þ…ñðáCN½(z½ÞØUÓÞxã ¼üòËh·Û[3áŸÓívq÷î]¼öÚk+î¸â^ýu´ÛíXWm#=´Ûm%Ú0÷ïß-a+¾Uá¹sçŽÿ%C4Î;wbÛòƒe8%-®„•å7¥”ß«Žo€å7%Oêà©OXe³]~O?ý4z½ÚíöÐ0„°I­’?þ8 …ÂÐóE)‹øÈG>‚oú¦oZùsÇßðÎw¾ûûûl½¤©ö÷÷ñÄOÄòÜ,Ã)i;;;øÈG>‚÷¼ç=+}^–ß”R~ÇÑÏò›’&uðyËïµ'¬“†7d2™¡‰ß¢Ûír mÆ7éŽ1Nºbl“îã´©Öž°æóù‘%´›Í&²Ù¬_±XÄíÛ·ýûmÛF©TJú½"šŠñMºcŒ“®Û¤;Æ8mªµ/ºF{{{þ!¾Åþþ>öööÐn·ýIÞO?ýtÒïÑLߤ;Æ8銱MºcŒÓ&J$aÍçóxöÙgýÉßá9Óî'J3Æ7éŽ1Nºbl“îã´‰IX5V~ÒE0í~¢4c|“îã¤+Æ6éŽ1N›físX‰ˆˆˆˆˆˆfÁ„•ˆˆˆˆˆˆR)±!ÁD¶ P(,þޏ®zŽ\N=§m«ûLSý­šç©Ÿ\Nýë8ƒXö< Ñ~|¡0ˆÑiGÅ°ç©Øö<àôTÝW¯«ûåwÇQÏiI¿#DDDDñ`ºå$¹TåØuÕÿs9 RQÿ¯×Ue»\žýyeôpE;Êɉªp7êßr9ºîº@«X–zÞ\NÝæ8ƒ¤7—SIªç©ÇU«êùLS=Æ0Ôßüïÿû{ðøãoOúíßH®«ÞGÃPï½e©X 6”Ëó5D8ŽúÌ€ÁßÉç|y!$VÔó4ê'ê¸ÊåA¼O:ïFC_.7øÏS·ÉqÆð1JB+¯}t¤n7Ø”JƒÆ—BaðÁã=8>&ÛVç(×K¡0HrÿØ[ýgODDD´nLX Ô`&t©$KeÖqT² Wj%W©÷<õ\Á„R^§RQ•ÒjUý½Tb%I4ŒA…:üürì’|†Ÿ_*ÐÁ„Ñ4çõ7r›mggêwITE¸¢E^ÇóÔëïî’˜àùŸ ޝ\N¤s¹A/V¹<ü>JO”ë½ÞWáñÇWºjµ=Ø€úWÞ[Iåó‘ÏCÞÿFCým¥¢>‡pÏbðïäš ÷NÊߘæhO¼ã¨ø7ÍA² '¦9ÜøQ«©ŸI¤‘ãà`pÕëƒÕJepŠ\n4¾ÃIu¸±GâRRõ¼³ôÀÏ)x]ærÀýÐò1@DDDìdu¹=œGª~%yÓË/?\î?ÎõšLXç`Ûƒä3Øc þ­T†{j …ÑäÍu ¯TÒ¥×*—S·ïî*ÇQ•XÃ$ B^G†“©Ô^¹2œäÍšH+àR1ölÆèyÎKz–ÄÉÉòŸ™aŒ&)¦ <úèK¸sçÁò/ ÛVÉÚ½{êwÂUðˆplHϼ${’zžŠeiÔi4Ôï’pNëÝ 6Dȱžž_?ïy“?`´Ä0Ô±­zh¹aŒÆ÷"ÇÄáﴩ•M3ïH "¢MNƒÆÕÂSˆÂ¤1RGZä ’<ö˜ªWH]%ØׇG‹±¥»ã8( 0 ïœ{ý&OcL ÑjµP¯×‘Ëåð-ßò-Èd2IŸÒÚ‡‡‡ç`Òì\×…mÛÈår~ìyž'P£) p]ŽãÀu]†r¹Œ\¿@q¶mÃó<¸®ëÇ­<¿a0 cj<†ƒƒÿy[­Z­Êå2,ËÂg?ûÙ¤ß.ÂhÂ$¡VKUD¤Â"­æ“*R‘–ŠR°‡F†v_GZãe¨­ô ´Zê12Ï¿RN&£Z㣦YŒ;7yä;¶ZL˜Å¸QÙìWÐíÎ×BOñ’¸ &¡ûá8­Õ1(ëWW—NIX%>%nÂsævwÕï2êF`ñ9Ë´¥qIÄ´ÙK¥Áb³t@„{æYÔ’f\$R¦#ƒF1YÐQ(Ÿÿ,‰\¸/ΑYqv,¤ÝV'¬ÒrœË /äC‹ñ<¶mÃq˜¦‰\.‡\.7”h+÷ò¯iš~…ÞqXýZ—Ü/wIP…mÛ#þà놓“†áWæïõ[$þé?ý§xõÕW“~Ëb%s¥ƒs˜·M0F …LÓôcÐu]?Ù 6|×uaY<Ïóc;—Ëù i0ö$•Û Ã@.—ƒišp»R›ê?VŽ€ÿï¼,ËB©TÂÁÁ<ÏC«ÕÂéé©ìíí%ýöo€á”8±mÛo$‘Ø•8kô›Wƒ ¦6kËåp²Éöœ¤E|+9·Z-¿çÒ4M ”Ë塨 ¯ Î÷”^|ù»ƒ\z+¥çtUÊå2LÓä¢E[âÒ¥áE5¦-1 +ó´ Â+ž:Î A 7pr7€Õ“i%ã/¯\¹Ïó`š&>ÿùÏ'}¸©$S$fÙMƒô²u «ã¬w˜dT2Yžc²ƒ,Þ"?Ò« ¨DAÑr¹ŒZ­æ‡¬×ë(—Ë8==]IÏN¡PÀÙÙ†_±§ôÙÝ]ß\‰3‰ Ã0üø»råŠë–eÁ¶mxí< %ãÄÕ[5—•ôœÊyÚ¶=XlFæ>Ëÿi~2B-¼pž|¯ë{²6‡mÛ(—Ë~=Î4MøS­VýÛ,ËÂÿð'}𩳻«åOOÙH¸¶.a]W²êº®?l¶R©Œ$“~âéº.†Ÿœ†+Ì…BÁŸó9­¢^.—çJˆçUKz’ % ÄQ /œÕjµ`ŽŽŽ†âUz÷Ðjµ`YLÓ\xþ'ѪÈv*’¨2Y]?]\Ù=¸øÞ42jÈ0 ¼ûÝïÞªió’ùβÇö¦®×Ž™àí²Á4²º{pm ™2$ §ZÊ;8EJ¦-É:ò=gÆØ¸•ç´m;ò;°ÑhàÊ•+888ð_[F•Ëe<ÿüóI¿õ© ÃÒU·ÙĦÕت„UYZ5im“^¤GIæ| I&]×EµZõçëY–…Z­ÆJ=-%¸ ˪È|eÏóü!å€Z€hZe1ŽyÉDË89a¢šÏóP­V#Wt—5êý%˜ƒ£$©Éêéé)<Ïç?ýi¼þúëIŸZ*5êû@ªë.Š£rlµZðýT²£ M‘½<¥2¿ê-5ˆ–5ψ¥F£áù•¹@Áø&Ú4ž”Jªâ¾ kÃÉÐY`”Ê"/Á¤S’Pé­T*þõÏ^¨Í%+ÿJãÌ2mç2{\ùoÛ¶¿uY01µmµZ ÷´ðBx¬~Ð$s%¬ívÅbqèwÛ¶‘ÉdpõêÕ¡ûÒÆóf¿dH‰¬tÚjµX™'m8Ž˲ü¹Ó²ð+´Éd®ªNqžç ­l*ÛhÈ ¦ÁÔB¡0qË(Ù.£Ñhø¥ÍdYƒy~ËÆ»Œ®‘Eõd¡+¢kY–/áPö|Ó2‡ áÑìfJX;jµºÝ®ÿÅ)-kÙlp||Œëׯcgg'ésZŠçy°, ggg8‡6G½>[/k½^¾Ç†Údž§z›Êåô%«²‘$”²w£$ž"¸™LG¦i­¸^}uqo{FëQ.¯f¿mIV¥AÞu]…^#óL‰VÁ¶UYͪ5Íc¦„µV«!ŸÏûCB• æóy"“ÉàøøÍf3µ ë¬Kb×ëõ‰­ÔDi5˰w˲–ž+D”&¥Òz+>¶mÃu]”Ëå¡5d› !sü Ãð{Jƒ×¯AšG«¥†¯jAšp² ¨y ìy§8U«ê_4¯© k»ÝF·ÛÅ­[·Éd½^Nׯ_÷oÛÙÙA³Ù6œ³l/C¯¸…m¢Y{W¹Œ>éäè(þ¹O’ÊŸO}’Ôj©\¡ßjµ8T’6Z«5~hdxn6Ñ&³mÕZG8»®‹F£á¯Ó ‹“Ea…ŸVM†þšæjU’=O]×Å•+W€É*%Âó’>ÚdSÖ|>N§ã'©½^¶mÌUm·Û€‹/&}N‘r¹ñ½«²'%÷ð¢MfYãÖF£14çŽh“U«juÉU’ž(˲P«Õ85„ÖÊqT\ ËoS#êý1˜2rŒ#È(IˆB˘)a-‹ØÛÛÃÎÎÚí6z½žßÙëõpçÎܸqÅbÑ_58m&-ÊÑh4`š&‡uÑÆšÔréº.lÛæÜUÒ‚ô>­²ƒÈ²,Èü¤U¢¸xžŠëerÊV«5´ú´mÛUCDK“޽$§•Í´JðÁÁšÍ&NOO‘ÉdpýúuäóyÀÍ›7q||Œb±¸‘­w²í+ó´É'z뺨×ë¨T*ì]¥çyjÈä*ëàÕj®ëÍO%Z·IS–f!#ŽŽŽü=TY¯¡4a8n¦z½˲P.—Q*•üÅeB@åRRîˆB¡ào£&uQ×uáyÞñŽwàƒüà\Ç1SÂ*Ij”ììì,Õ³*ãnÏd2+éµ-•†/Û¶ýmzŽŽŽXQ¡Ø¬#¾áá6¶mûs—LÓä^«uŸ,B³ŠâÚó<ÿË—{g]±½,Ù’OF¿q¿]šÕ¦Ä8-O͆Π&œ’TÊO¹\öt`Û6,ËB«Õòÿ>—Ëù ær9+·z½Ó4aÛ6ürIve™ÇL + æ¨Þ¹spõêUëše¹Ùl¢Óéàððп­Ûí¢V«¡ÓéøojpØÅ>¤áß«Õ*ŽŽŽ¸ÈÅj]ñ&…ã›â¶Îo4€óóåY†¿@‰ÂÖÛ­–æ¾ÈPwÙ˜ó®i^ëŠqÇQ?l;_=I4%é N û=ÏJ*eqA!÷I¯è¤EÙfݾ­\.ûÇvpp0Ô1øè£â­o}ë\ç9SÂÚl6q||ìÿ~||Œk×®a©7¹ÝnûɃnܸl6‹[·n¡×ëá©§žB³Ù\êõÂïm.—cežbµÎø XDqXwŒ/›¬zž‡jçz¦IÖÛ²MÓ,‚[Õ˜¦é7¾Íc1îy*Æi6Ò)‰c¡Pú¾’ï2ÇqËåP(üÞÍ4å6«Ü}åM³<èøø;;;pŽã`ggÇÇÇ#ÛÝÌ£×ëù]ÅAÝnív×®] †#ïìì¬tÈÖ¼ÝÐDóZw|çrÃ-—žçqÛŠU’eø"ÇÁ•+W`š&NNN˜¬ÒXIÄöÁÁ콫Ò3âº.ªÕêÌ=DbÝ1¾ì‚b:’!³¥RièçÒ¥K°,ËVkY®\¹âÁµmÛÿ.»wïNOOqpp€J¥¢u90µ‡U¶«‘à€ýý}ܾ}Ng¤efV7nÜð·Æ‘apÿþ}OŸÏçÑív>É𠪬ÌSÜÖß@tË<+ä§uǸç©!Á‹Tzd0÷Ÿ¤Y¬;¶Å¬E¶ì©Í2ž•TŒo£à¼Qé9u]×ohªÕjS¯eÏóP¯×qéÒ%†ÓÓÓ­ÛÙd¦V`x®j&“YêEoß¾n·9¼`ÒE1©G÷7ÞÀË/¿ì'ØAŽÃýŸh ÛíâîÝ»xíµ×byþ8â^ýu´ÛíÈç°m·¡v»Äöüë.ÃUŽ/²ñ|«ÕB£ÑÀéé)“UMt:ܽ{>\ùs'Q~@ËÔ©dk &«ú’ò{™QŒ“$Q~·Zª ß&¶mû½¥²#I.—ÃÑÑîÝ»‡£££™¯eÃ0ptt„ÓÓSœmt²*uðyËï™]ZåÀ=é‚xøðáØdù7ÞÀ+¯¼‚;wîDöúãÁ[¤ÖCÚ¸ÿ>îÞ½‹/}éK+î¸âPYø,¼Ø™m«!7R†qØûv»sçNl•¤ÊðBaþ†ÇV«…V«…ÓÓSVð5" ëª%U~£ CŽ#/¤/)¿§ÅÔ"’*¿ç™£½ ‚[¸H2j\×õ盺®»òQ=›œ¨ ©ƒÏkí ëíÛ·‘Édü¸Óéàþýûh6›ØÙÙ‰\Z[LZ‘øñÇG¡Pˆl1 ïoæ8+/[L S©<¬R\ñ ï|ç;Ç.z®Ì³'i»íïï óZ¥$Êp@5:ÎSl3YÕ—l¥·ê2<©ò˜mô@«Õ‚išZTZi<)¿ãØN&©ò[‡~"ÏóüïYàHVÖ ëužçi=Ÿt‹ÖÁgNX÷ööFnk6›¸yóæÐmÁ¥±£\½zuâý/^ ZäâþUX¡§8$ßÜ™ƒÖ%©—¨YêŽã ÑhpžÍ%ÉúÉ,9¨eYܺ†–’TŒor«¬ÊmYÖО¤ã0¿ˆÇÔ„õâÅ‹C .‰I­0“‹Å¡áÍf†ZeŠÅ"nß¾íßfÛ6J¥ÒÂ'¹ÌþfDóH"¾57„ñMëTŒÛöì1.ûl3Y¥y$Û³­ÊØ»JËH2Æ7-t¥zÖD•â55aÍf³+ÝrûûûØÛÛC»ÝF¯×C&“ÁÓO?½ðó…[v8‡•’´êøÔ‚2­‰óW)iqÄ80Û`٪ñ(qÄö, æÉbKDq‹«üÞ²HŸ ùÍårLTSbî9¬ív{hÜñÕ«WÞÚ@d2œÏçñì³Ïús°–y~`t™M·uÄ70\áá¶M´NëŠñY¸® Û¶¹( ­Ä:ËïiE¶leC´JIÔQÒÈqÔëuär¹­Ü2fÌœ°Ú¶üã#K^#›Í¢Ñh,^¯‡n·;±—U\Êd2IŸÓDÚmiSÇ Õ„JD­þ¿€`"ãôNû÷*¡mõÿÖ€ê]Eà>`¸6-¼Àùx$Ûý 9ŽÃ!d¤FctŽŸlcÃ(ÚdŽ3>ÏS×cÔÒÍQï…eM¾^ …Ñç±mõwQå˜<—f­Ž£N;xZ\˜tU¬´a½Õ\Côô¢ å8vwwqttÄDUs3'¬B¶¸ F¯×C§ÓA±XLúœ†XÖŠ[v\WÕœgP)-bÏNNFÿæýgàwþ<ðò·¨ÛÚ™ÀÂGöhˆTz¥bL"Mx® |ë£ÇW© Ÿð,³Ý+•Å–p WÚg~ofQ(,öZ*íwÛm|áÎùŸ3…Z­á¼f©B[5‰o@=q.½”e8a öŽ;y>ù{i„(—Ç÷‚Ë2ƒóžÛÉÉü½‹${‹Î=Xäµf½^ÿÉ?™ÿ¹S*fŽã —Ëé1Z†¶^¸Ø[ùà2k>§åï´""ŒßcxùçU+sq²í0wÂ:N§ÓÁÞÞœ”­r®c/ýE`Ûª"_.«'–Ê= n3M5ôUZ4Oúac°ï©µ¬Ö+÷Ë0ZO²C·K|ÿF^ó ÿš­þ}&€Gç?•õ°f2™TmiÓz'Pù3µ|?Lêm:ˆø}Z0ܹ1Ë<ÛðÐêþ<áÏì}ÁG–~Ë7]µZ…a¨Õb*ì “ºƒ •|Ic¸${r Jr'¿K<\éÿ~2å5eî6úÏlt’ÿ×0H`‡zó1ØÄ¿0Ø>sä|]Àî¿x à ¤_„º[-øŽ4ÌT¡®Å÷…æ1TàÞ‡ã{cùˆ¦&¬ív{dÕ^¯‡N§“ªÕ Ç —Üo†oh¹”@¨b8H_AOV¼_ž« @hÒ;)CÒªAK´ü«ºÙjÜß„+7÷0ü…s©Ìó5–…I¢*DÒ¨¤6ü¥´…6f•`zî-•ÞP¹ß0Ô\ó“9Z>˜¬j¡Õ´QÌEFXP•Òõ˜$ë0–5¼ø–ùÐÒNXç‰ý “ £†k:8#¢æhÏB†ÀÑÑ”aŽ£ªdÅj™÷,ð] ®åoêŒÌ’í#£H‡–,&ñ\,,˜@†ã+Ü>Ë{®¯…¯çpy!ß%…ÀÒÚrœ»»££üÇ"º¡¨VS?óŠqåæ…†ß¼yÇÇÇ©­4ärÀÁÝî†a¨ŒÖuÕþ©9°'•6“ ØàF]†6TåE[Ǧïõ1·OJÞ¤±Hz8åøÒY´D –õgP_„Vÿ¼Â[?Œ{ZýRF‡×úÏ--¶"8œGCáÞÕTm\˜È¶Ue]VÔU½Ѥs–{é¡‘†Uî5­N+-ø5¨k0°ÕÂùéÄÆ˜U¬¹áºêËòÔ갪<¥Ò< kµZÅ¿ý ü.Fë6iày£= Õêð\ÒBA]OiZkA3'¬{{ƒñe½^oä6‘ª-pdRu@ög³Àï~…DÏqFqsüÅ"â[–U—ýF¥AGfJÓ—Q_pý"õû †{Þ`8V°•»PXß¾¥ ijŸ/m”™«"áýBçeY@½®bÞ4ÕB,[6ŽÒí§þ§Ÿ‚išx÷ÿî¤e@xdnŠŒº Š»q“̰^¼x×®]¹=­[ÚDêï³ê8~ð?þ ð¥ïƒÚ°‹hsEmÃ8u¨¤¬Æ+Û!D-|B”2Ázµ?µc–5¹ÈâH«" ˜±ž³õ‚£pmÛV;Di`¶yÀ@ô8LÓT1œJk4ëv6žçáÁÿò?ðñHö€%1 ï‹]«±£+aSÖl6‹ýýý¤s9€ðÑ×>Š7ÿwoœw$}DDK‰Z¬Ô7K{vh[Hoªe †?®ºE¼…ÁñðÊÜW0XõP#k+å¢z== ¶â˜$8ÿ:œœ2Q¥k4øèù(Þýgî]•¡òå2{NSæMIÀZT€;ýÞý»ï¾÷óI ÑÒ¢VO&ûE­HG´¡ÂsXÝy–l4€+WToÓÙ™ª€Ì²Çe*±,ax —:ÔÈÿù¡¶)’­šN0º‚ë† )Cm§Æ)ƒ[¯Õ,Â;‘Éñâyj¸o©¤zîÝc‚J‰“°œÆu]ضrñøjµÔœÓR)úàÔëP©3óÖN§ƒããc\»v ù|~ìÐÃyæu:@>Ÿ{&“A6›]ê$=ÏÃ_ù¡¿‚“Ÿ=þÔûFWÂ#ŠAœñ- ˜9Ž3~8Q b‹qI Ë£‹ôÎ5$XöEåºp¡’ÔþëFnÕT€JN%y0¡ >ý´íXÚ먟„çgG ž´º;0Ø£\V‰*ÑŒâŽñ™c zWÿîÎßÅ›ž©M¶(“Q6å2Ò 4SÂjÛ6jµ²Ù,2™Œûþþ>2™ lÛF§ÓÁ³Ï>;Ó‹v:Ôj5t»]jØq£Ñð/šn·‹Z­æ_L¦i¢ÑhÌôÜQÊår¼[!õ­#¾Ž¢ëà9ÙË‹‹iPŒbñTïå² -Îs´ ’ÏI=YåÐýüJÑÎ:ë'•Ê”u¤·?jø¸m«¢BA5³̧­+ÆeÛÞIlÛ†ëº82€ÞŠOÔ¶U¢êºêbcƒÎF›©9ãÆ0MÏ=÷ÜPKK>ŸÇÎÎqõêUܼys¦ÝÛÛC±X„ã8xþùçQ,‡6 ¾qã²Ù¬§ÓA³Ù\èÇmÛ8˜uæ7Ñ’Öß¿âÜ7’kˆñ~O¦ã¨úFÐÈ(ÀÿzxÇÿ=[ö¾5ÄWÔ1Î ¨¤€Ãt·Þ:ë'cËq*>w¡â2ª3ÈóÔJ¿GG,ïi.ëŠqØšõz]½¶ƒÕ7zžªqÏS LMXÛí6z½žy晉{æ™gp||ì·ØL{>YÈ)“ÉàÚµkèv»èt:èv»h·ÛþÊÄ™L;;;8]po«Õº‰â´îøjµZÑ v­ÐÚbÜœÖè¶ÂC=P?ð»Àø?ÿO \¬PG*ý¨y£ÁC8è߯^Rê[gù- Vùó³ejÝ=ŒB^.3Q¥¹­3ƧÍ_mµZ( ƒ)Ë”ÅQ•ú«•© k§ÓA6›Ã^,‡†Ëý÷ïߟø|ù|‡‡‡C+“ÉdüÿÇÔçóù©‰ð8®ë¢\dc{ø±îø–eÁó6Ë’e¤µn·‹»wïâµ×^[ùsÇßðú믣Ýn<‡üG\‚úÚí6Y[f¡…"m[­òÛh V€?9Yù{Eñ:ø¼å÷Ô„5ŸÏ£×ë$‚ar°Õf’^¯‡f³‰øÃ(‹¸~ýºû8“Nî7ÞÀ+¯¼‚;wî Ý>²Ð{X·Þýû÷cKXŪãPž;wbh40MS –GÚjwî܉¥²wîy@Ë€Z½·Ïó<”.•€oêßö9àþ¹õ½©”q%¬"îòÛûA½Ñ…óÇépT…¼RQ[lÐV‘ò;®øâ/¿gòhܧþ×§pPëǶ…áíÃÆñ<`wW%ªµšJRg]žRCêàóÆ÷ÔU‚óù<òù<šÍ&òù|dB*_,gêuít:¸qã2™ nݺ52ô`œIKk?þøã( þ¸|`Ì6\)xëIëb¸qcUâˆoxç;ß9߀Šq˲pOV¿ oZI[iß_á1ë(ÃpM {ì—ÃG?ñQ`÷`ܰ³¶÷”ÒCzƒâ(Ã×Q~[&`þ«ÑÇüØÛLýDzTEœS<¶’”ßËné8κÊïqÕmÇqà|«ƒo­k4f›¿*8¼.6Ú¢uð™¶µ¹~ý:öööðÔSOaggg( ïܹƒÛ·oû›E­VjÑ ºxñ"Õe,Gðÿóð2ÚPìa%"¢Ôq]ÙuöÏ’>¢•²m[%¬ž”JjÍ .DC:i`¤w5r+'¢1a%"¢ÔùSŸø¾ú»¿›‹ç‘v<ÏSà µ›×$ xP -ö]­×ë(3Îi LX‰ˆ(]<ºÛÅ×üƒô‘­œã8øs/?ò#À½{IÑj9PCûmŽãÀ²,œ-ó¬´å8‡•ˆˆRå?ýÐá—.]bï*iÉu]\}þyîOz2vÝ«V«øçþ0 ÛNúÈhƒ1a%"¢Tù¹ÿê¿Â¿ÿîïNú0ˆbñ5/¿ŒÇåW¸—6i¯^¯ãéoýVäŸ{ŽÛÙÐR8$˜ˆˆRÅ4MnùAÚúáoøà¯þÕ¤ƒ(vŸùÄ'ÔTÖŸþiŽ˜¡¥0a%"¢TáJ’¤³Çÿò_æBK¤=Û¶ñ¿½éMxS¥Â­ÉhiLDDD´.LVi ô®_‡‘Ëq®6­{X‰ˆˆˆˆh%¾ô3?ƒü¯þ*r÷ï'}(¤ ö°Ñò\ø?ü°ËeÎ[¥•aÂJDDDDDË3 ü¿å[ð§÷÷“>ÒV"""""Zšëyxöõ×QàBK´BLX‰ˆˆˆˆhi®ë¢Â=†iÅR¿èR§ÓA&“A6›MúPˆVŽñMºcŒ“Îߤ³EâÛ4ͤ›4”Ú„µÛí¢V«¡ÓéP@£ÑHú°ˆV‚ñMºcŒ“Îߤ3Æ7¥Mj‡߸qÙlŽãàùçŸG§ÓA³ÙLú°ˆV‚ñMºcŒ“Îߤ3Æ7¥M*Ön·‹v»k×®2™ vvvpzzšô¡-ñMºcŒ“Îߤ3Æ7¥Q*Öûý†óù¼[>ŸG·ÛMúÐRa[Z¹nß¾íGÑ ã{²N§ƒÛ·o'}k¡ëµÌŸL×Ï=Œeøöaù½ùß“éú¹‡¥­üNåÖIE¯×C&“¹ý7~ã7ð³?û³pGû¥´?ó™Ï$}ká8>ûÙÏâ=ïyÏJŸ÷å—_Ưÿú¯ã‘GÁ~û„-ßpïÞ=\»v ï~÷»Wþž¤ÉË/¿ŒW^ye+¾㺖ÇÁoþæo&v^,Ã'c¾œÏ}îsxå•WðØc%r^‹Ä7ËoýÄ]~'U²üžŒå÷r¤>oùÊ„µ×ë½ïáÇ‘K>ŸÇ·û·ã‰'žÀûßÿþ¤O!V¿÷{¿‡«W¯&}±Ëd2xüñÇñøã¯ôy_}õU¼ûÝïÆ#<’Èy-ßð§ÿôŸÆûÞ÷¾XÞ“4yõÕWñꫯjñ]Ë™L_ÿõ_ŸØy± ŸŒeørÞõ®wá•W^Á;ÞñŽDÎk‘øfù­Ÿ¸Ëïw½ë]‰œËïÉX~/Gêàó–ß©LXƒÃÂÆ-­}ùòe\¾|9éC_‹b±˜ô!ð<—°H|À?øÿ éC§‹+Æ“¾vX†O–ôç³éç™ôû·H|³üÖã{€å·~Òvž©œÃzñâEÃúÝ.÷9#-0¾IwŒqÒã›tÆø¦4JešÍfQ,‡&îÛ¶R©”ô¡-ñMºcŒ“Îߤ3Æ7¥Ñ#ççççID”N§ƒ½½=d³Y’÷áááØù}D›„ñMºcŒ“Îߤ3Æ7¥MjV@Mü–%•Ó6–šhYŒoÒcœtÆø&1¾)MR°ÑöJåÖmÒn·#oït:÷ÂZöþuêt:7^æ\Òtž4j\|ú|îqÆwÚΕ†Å߳ܿNËÄø&' Û†øfù½½¶!¾åX´(¿Ï)1÷ïß?¿|ùòÈmß÷}ßw~ùòåóË—/Ÿìc[éýëôâ‹/ž?ùä“þ±<ùä“ç/¾øâJÎ%MçIÑ¢â[n×ás3¾Óv®4*ŽøžåþuZ&Æ7é?_.†Óô¹Çß³ÜOɉ+¾g¹–‰ñM:O¶ ñÍò{{mC|ŸŸëY~³‡5;;;8<<ÄþþþÐí÷ïßäóyÿ¶|>ï_öþuÊçó#K Ëñe2™¥Î%MçI£ÆÅ7°\ §és3¾g¹Ÿ’W|Ïrÿ:-ã›tž4lâ›å÷öÚ†ø–×Õ­üfš"“>ì^¯·ôýë”Éd†–Aïv»h6›ØÙÙA6›]ê\îÝ»—šó¤ùèò¹Çßi»–iv:}îËÄø´k5MçI³Ó%¾Y~S>wËo&¬)2éƒ~øðáÒ÷'uNÍfþð‡Q,qýúõ¥ÏõÕW_MÝyÒltûÜãˆï´^Ë4ŽŸû"1>íZMãyÒtºÅ7Ëo Òñsשü¾°†÷‹fì^Ëf³Kß¿nN7nÜ@&“Á­[·F†,z.Åb7oÞLÍyÒìtúÜãŠï4^Ë4Ý>÷Ec|Úµš¶ó¤Ùèß,¿)L·Ï]·ò›=¬)rñâEÃúݮËÞ¿nµZÍGðeÎ%mçI³Óés+¾g¹ŸÒI·Ï}Ñß´ó¤Ùèß,¿)L·Ï]·ò› kŠd³Y‹Eܾ}ۿͶm”J¥•Ü¿N¶m£ÛíÂ4M´Ûí¡ŸeÏ%MçIóÑås3¾g¹ŸÒI§Ï}™ߤó¤Ùéß,¿)ŠNŸ»Žå÷#ççççk' Ðn·±··ÇqüÛ:öööÍfÑëõÉd†VúZöþui6›8>>޼OÎw™sIËyÒxQñ èñ¹Çß³ÜOÉŠ#¾g¹]–ñM9OЦs|³ü&ãгüfšB½^N†VùZÕýi²Ì¹lÒyÒ°mùÜ·éZ¦múÜ—¹V7韘¦éßñâʼn‹ egggglkÍÎÎŽÿš™L/^Œåu:nÞ¼‰«W¯js¡Ðì–‰ñMˆo€1¾Í’Šo¹Ÿe8ʼnå7éŒuðÍÅVZ¹f³‰G}wîÜÑbÜ> endobj 2 0 obj << /Length 3 0 R /Filter /FlateDecode >> stream xœÌ½K¯.;r8¯_q†ÝƒÚâû1è ´„6dHmÐÃ#¹$¡íkµKî_ßkEd&#È]÷Ö9W¹QW°ë|‡'“d’\Œˆÿþ›ø-àÿ~Ëÿé3}ûûŸ~>bªò·ëOøëÿþ›ö'þ"õ!ÇŸu”Ú¿ÅR¾å&ÏâïúMÌeâÿUÿCŒøsX`Ó?ýæÿúÍCïÿˆß%·þñ~ÿí~óþi=þë½!öú-åŠñç’äOÿUþÔg‚FùÃ?ýæO~1>ÆÃ¡ýãoþãÂ?úÏ¿Ißþúû¿ÑÔJ9û÷ÿiß÷R?˜ÆOkboô’rÿhéžÑú•?r!Ä‘_êoÿxú}~¼Þí=Cù²ÏüO›s†ZÞ­®çõç£Ó¿øËø-¶žíßý† ïÿÇŸJ‹?Z)qàÑšÆÇÈ=Tþíïdü6ÅŠ¾ýî§oÿñá7þ_¿ý§o¿ûw¿ùß'ÓýžRéc¦ÜJõ{újG_oÇç࿲‚×aù<ÚÙ4Ý #ö—a&Žù1Ò¬¥„¾÷ìÚ^B)­Î0FÌÇlÛ{C˜ó£ŒÑòÇlÓûÛ+|ä„~[}sÝÙá¶î®ç/Xw‚_w?„÷×CðëîFðÙºÿ2*ljnF#q_Ïô‘rô(!þ\(ù½pì;I1}ÄZjË£œhœîNâ¯êeæô‘FÅDÆÏô‘~U­¦[j1äŸé$»NäÞ¸˜ü½ùÛðä¿Ô¿ývuhFbÿz Xí’"ƒ•ÇÒ×\sNç@þ§êHþê/ÿúoþöïþâïÿù¿?†d¯òŸý½Ìˆ5i~+BPì=â{=gÞ¬¿-Ú÷¿üãïúéû¯V2ÂEÄY cj¹|K „ÈGÄÆ?ZG[jã[œã#¶!µQøÛ_´ð“¶‚FèUšðFJ¡áã”ú‘J£w FýA°mr;׊-Ð1"iÃ+9Kì–ö1ðzÕ&¼r°7ìÉ QÕVR-m)ÄΑDì¶Eü‡×ViÃ++^ÙkC[øèeÔž³4á•Iý»1¶Påü§ˆ7¼±b{¡ç‰|i Ç%¹ò1”ÞKÒǰ7ã}“ðí9•Yùµ$¥ÎqüœòU¡4y#>B¼>vDí1ã¤Èà!z#aMg´ÊØ1lÂþè\˜ €§FÅg2ÞÆ1Ԙ؀>ZϱI^Çei=jäÉŠ‹¦?8)œŒÊán" xÝý•p|GÁܪöTxÙSÏß°ªc R”×UüäŠtìl4á›çÙ³¼°â…Dní³ãàÍdëÀžÇ?Ÿ)LŽÕð¢{o¢¥ZZ,ò±^toMnªÜ±w¢¼¨áEøc™hÄ÷+YÝñB¬T9lÓ‰(Ÿ´c£ê.Šlh¦¼G¤r!Ð=ûª-\uõ†Ì\7&4À­aÞÒ„Þû’ƒÇÑì]”`àG½·%¿]i½å&SæÏõÁq²b›Y[ð>~ Ü2|(GJé" &ì¶Úﻌ›2÷‚¥¢¶äƒ¬h–Äà¹1¥ /äZàÈ´BŸ#¨ŽÃqŸ`P@oCÂ٘Ϧ 3‹¬VÆÙHϦŒøî8)YNTÆÑh϶e )w~ÜŒ£1ù-biòBH8OÚ„Êûº| <9Øg£ax¨êÆ"Ô$M8˜GˆZ}aê&±i‹6á…ÏÆÄ 'Žî¸í ø |©Y«|Ó?Y@Q<ÿnÛÂâ´añ Åk1ÞŠ» >¦v`1å9žßZóÆÜ’p[Z=À¸ãFÆŸ°¸éã:z³|ÚÆD=àÆ’4®çëÙZ;иd,nj}ŒŽqAW „IQÀÂ1nü¬Ë˜ïÇ×öJ-q‡ãH @ÀiÍú˜Åc`;6'¾M©u䘓Üj&sˆyGã¡>{Ù!9FÁäQJ*;*cEÙ.…å(¢IæÝ6v\æmÙ…‘’4ÇP°±ñÀÒŽÍ2Îq2óŽÍ'#øÔaàŒ;T+£/tŽø¡%oí;>ã¸C¼øšú‰-@c3PÂxÏ¡y-cƒ ó8wˆÆGÃ÷à47-F³¿Þñ9ŠÞ–¤#vvZ¿.m ÒòÊ€“Üti,J³ 2)zÂ4—‡L„Ö §)ÐDƒO×v æ+±CpÏÆ©ùJ\%ómP!éã$bËËîrX­Ã,¼¹âÖ|%Hö­ÙV"hÝK'W¡CkîƒÜ¦œ«®9HÈÍ5 v¼Ž¡Ap—+yî€Í‘$^^CŸ³ˆÍwâí¸ôz°€‚—GÛ1›‹0°Þ“ºP[_gÈþt½’vë¶Ç·ü-}Ë:rcÒ¸Y°TT v!:e¬UÁ Lõ@îˆCÜ0˜ÒO䯒C ÀVo§ QB;ï¸vŠÑ€Ë„˜PÄ ]=Ü™ûaö¸±’8#´EÎO€»ä ØênñÍp~òg¸=s¡8OànXr¼fÊÄ=pgœ-¨OU<€[£SÒnyñà\Ì·œ#œÜ‰Ÿà6”F©HO·Ñ5´•ŽAÖ·¡É@}€<ÙÜÆtpZ–(¸¶@œz¿xàN»2“BŸÃm^µB|Ð;Wq;ò€ã¯ñÒ·ñ¹{Âiï=p22Ä*àó¤mÞÈ£BuTeƒîL ¸xÇ Ýø+ì‚àü.«äMB©¼Ì¬Ðw.ë*ÿ¤ÏW‰ÃÏú~Ŧ9/¢é™Ø½àAC®_¯3x5âðùñz·÷ åË>?^'¯ êz¦?Bþ)ôpè€;çþ2U˜¡¨|ð¦ø|-ù6U¸NàsÔ_Y³–ÌA‘4³¤×¯‹æ]`Ù)#ÛóWPFó  ý¾€2š;UèFð>Uh·WØ‹"ë{ëηuw=ÁºËüºû!¼¿î‚_w7‚¢ !¡ÓÖM™»½FúNÞ¢ ]//Q…®¢ ‰ƒx [†:ö L\°LÜ¿üÏ÷˜¸<­ùýbÂz¢ œùc꣆Vx µóG+Õ Y[ÄniÃ;­,C½ásïêçËš–¡=Gž£~¾´2Èç½AwHúœ#ã GL¼¤‰Î_’#ãD<(IT“’Œ§h²· ŠWIˆ€ê,"¥žBíü!= zäK×`Í,7éÑ Œc3éS´Iß@ME*HÔÚ!nÒ#ÌFCMÒ&ÃÄ%’Ð|…ô(Å2qÐý* bEFQ-‡]›*&dÕrqГfÈøæú^øTÆ^­_ºyHø‘KHç€Mx¡!=2íõBf(æÅrØ“uˆQ·tKÆQ°lBJ“%ãHy%`œ0%¥ 0JÚJš¼i«¯¨Ñ@ô°lv'Ü„[,òqd´°[šÜae“^¸sšî±i,ƒæÎ€í.ÖÜ2-‡ö:Ú¨áËÆE*¸m*÷Pƒeã0Š&ËÆ±‰Õ\8å—±ó˜5a b6ªÑØ -!ø*U¾]¥cÜ×*â(¬y¥ …ÿ—i œF 6y6«ÞçõÞ'ëò>ìlèbè¯Ù³qÀ¡Á5‘¦JN>¤)¼·Ô‚.-ÆF€A@~§…MºÂéà‰ÀAê2¾Ú[Uëi-žŒ3û¨OÆqâ q+ŽÇä! Ø'\¬ˆ7 Ý[«åâíÁXP±‹Tœ\ò( ³êè!‰Eˆ—3¿69]%›ß"ã<Ó†7/ËæÆXE ò<ИS.‹•0摉aÚ=÷ôÑ2„œ©¯t`Œ,ƒ¢ÕûƇ¨·ºlÆTe©«éИ\\ÆFnC >Žiõ %·Ä÷ox "F¬SlHc&[E#Y;"Ó8›¯µ? û±uA²ðfbR+˜Ãd¶Qõ,Q쨔i¬£×QQÆ¡2ŸË1—CÛa9&šÎOe¸ÌÛçû_1Ö3o=27@±C3m烶º.öT‡ÍbïòšœÅà8°§§ºŠÎ|&<šúj8xci ÷ªd8£.>H 4|Π+ð «ûÐBA -_›r:.`Û3Àö@hé?P”ÌuÍQ†Ñç}¸-F³ £JãB¦àLºø¼üÊHJ“MÄÉ)]XìLºŽû'Ê~u8M®¨ãS^dÔl‹Gï ‹ÔÂBN Þv«7Ï5-äsiC.p‡Öto*P6 ³#ã°ïèËRåä8¸æc…dÝÆ×bAΤ*ÚÜ[ˆÍ‰k·ë"XÄæ dB`TÝ1›"46olêÓâ@[\­æÙå‹VÇ޵Îq|l?·!7d<||½y"·º­µ¡§Ê!7O ?>'tÓŽ“å‹yèÆqoES9ÊC7‰:Œê’7=tgÖO¥ ºdbÌB]Ÿ6è¦ûÐEt;à|… U éC¸±þÜ–cŠØ´77-OägÀMÁò¡²Þ áèçJŸÐõH8º;Zîÿå-®Q·” «á”C¯ª%‡)1-Yã]*'T-uwoI=y#-t‘œS£áW(–¬ñ ctÐ@lò\¶ÆƒÚé _sÓaËêÉ‹­O×| ÿ¯(-[ã´hü!4u¡oÔË¡|ôÐÅ‘—ªSÇOÌÕ;òFhNhÎÒ6>.=Gé@% _kÕZð‰€B)DÁVÕ•÷2£ šÑÂ,âøÙªºò^f4R“bƒ–çš±P š¡„½YÚðÎ¥QŸ§%F·Ö¬ýï ôíl¢™·Î 1UÈÄÝ=0PL ­[óô I㮺B‹_^ÕÈØ š¶ sXó‡9hï ¶ g÷ Ÿ²§¡mêË{éd›@ÆVŒömZ£CýêªðcG‹ôóMƒ+(mb@Ü•55„wªæ÷ŽÕXâšØZ iB 5ƒ}7Űةš?;6àcµ T—uëÑÆÉõ(ä­(¿Ñ£“ÃjS­­U›È„\û•VL:6ËÀ{²æ 8c XRmà ¯Ý \oØc l“g< E ÇS jù½[ñX Õ„sêÙZ˜Í¢R8Úpo¸¹ÂpËŠ¹s÷bŒœØÄ(B¼öb¹9Ø;b@ÂAµ–ƒHbjëÕ’síc`óó@I“1ÐÜP(¯Ë «”ãVH©W{3vƒYe½Jëxo–œkÜ\¹ñÐíÍ’sù#4~±Åãÿ7ä\Å©b‹˜z·ìÄ`Èž ½[›AýZ3„\Ú„:ò7ors¤wZÅjáŽ=@š>ãÏ“w&o‡»’Ü(HãЇ’ÇwäAº3¨àè(¸;näš"P@v€é ¨ÂåÖ4rÍtË>‘8=x”F[™+í@é"0YCR8ª›(€±¤~ 4ÆÀáÜC;PZæÚ²×”fLbæe"ûÇ£tj8€•ÉKìC§?ƒ*8€–à"C×Q:ˆF\è¤A¿¢%¨ ˜Y”³Û0zâÃàÛfÅ2‹Ñb±lEÃ’†,9œî ;H“Nņ™%+îgâ¥u†¡§5î0-Á@ ãêILlózgu&^ìc|û !9©e˜sK×cÎÆK«+v|”Ûßaµ ·]NB½;°Ûpêb»íhÍ©cá JÉ‘rpM)¥ö6!,æ¯y™Ó`΄ ;bKüF%aDÕ£›VôÏô]ÑÍßÏÌm¸ÍODA<Ü6Ü.ô”9ˉÛÀtÜ|8§p «•HYž¸ÝñùnŠ~â61=B€nr*=nã³C#+ ZÜnÑhÀX5i;܆,!æà=óÄmb%î›íý câ5ŸÌÔ^é†á!Y¶~½Î–á&\$Ýóãõnïʧ}~¼NÒ]”^ï?ÿIW›„û&*%ée’®…A©™†ÐþœHºuŸÃþJÚÅû€¿~Í|êWÐtìp£k\Ï_@×È<]ã‡ð>]Ã!xºÆà}šÎl°É’÷y:éq[y×õW$TU&Ë-½ÃdT Ê­½ÂQuø+hVq@+ó5®nëå-²Îwó[ç;yƒ®ƒFA«ÉdÆ«_È^I3á¢ëþÇÞ‹™¹[ºŽ ŽÚÔ)A%‹B*P" X‹-qà\ƒ j@lW[·†`ÉBiªxެ«o—6Z襭ƒBeG!—Q¥­[¶Ž¾±y¦.ÖÄA#­ %zdB›ŠQ›Š¥ëÖÿª]mÝb“õ¾lƒ{aÑu…ÉÛæ¢ý^ŒE»8 A}®‹­Vøl}ІýÒXha ÐYE+£X¶.| /šf¥»ÑAìT¢ø#>†ƒ1g‚Æl7"›˜ˆñ¼‰£K55§´ôeO˜´-DzS ˜dà–vÆA¥~1ƒ“ú¦¥êð6 Q|œ'UߥžÅˆiÊù¢->7ÉiÑ·[›Ê²&Ðy˜Ã•­0#‡S‚æ<›´fß;•ÎÒÐRcJebo®è9jïèqˆö>y”îÊ ƒyýÄ4„!Ž®|èÁØGò!˜ïáè²ØkÎÚÔ GÇmSÅ𼉞kä{ÉE›Êâè É2û¥*§eÏ ›$‹|UÕPt‰ù˜úÅKD\.ËÁ˜Ÿ"†á‰£²:¨ÊaÐ`DÁZ¹aè¨ø·>4:g2­ ëdözŒ>ÕMø½šSkAL8˜aèò‡ì1M;{±®½±WœaQ/˜`c1tGCìb¸Æ2 ]â¡Y¦…3²:†&f <¦n:7Yk C™Œå|:#á|ˆÍmòc›\–ï‹ú-$€äÞ—‘RqÆ­Û3ÿfëXä7sYz`Nܹm¶4æ̤¸ñÝG“]íY̹‘¹¿D„òÈ<%_ êÞí‘Ú ÚQÃw=2ÓÔÛ{§½û@füÃÑÈ#Ë×rÈܘV’šW=0W¦¤Œ¸Y$¬ÚsÕ¡õi0®æVÅýž9H`fh]£ñOµ=0WòÖ '­¸\È INÍ|3¾÷mŸbéõÀ\èµ I£O0Œ$6æö;0³»D˜*9²4G.2]6ÔLï±7 nºÌ›q‰ã3(M6šÅ÷dîØÌdpøD9ª_gŽ07°ÐñgN ¸¬ÙØá3Ñfžmö¼´d¤+¥Æ)ö;‡Ð¼¿IÉtÝ”¢Å(ô‰;FKŽN|Í+å¬išûЛ¬›Ci1;3¤jˆ­Ý´DÝÄšiyÞqšñ,©÷°j2¤¡`ÔÅ!5-à½`TI?‹…jII1)*ç°Zøß‚…ov`M xgäùÐõ¶h-1€8õ˜ùØáZr—⃥*[Öâµ°žƒ1Qz‡ZÀ£:ŽGɺB±eõ&“ÄÆ¸C6§7ƒPqeÇl âV×Lx´%á#Ó'krb‡Ú’€pPªNÝâ¶D¡±])wÕ™i5*ßg?ùn¢nCos@ækå@ï0xóüÄÆ£7¾@Øžë)W3³·Ö¼‰ºØÓjÍÛÀ›Ái ¯éïF·´ŒûäolŽÞÃëæÞMh'lˆö zã¶Ò²&%ØÐ›ù‹±ß4­ã†ÞšB¹Dn‡Þ•h³+ŸÁ7ÄÙô ðݱIÓ4nð]?2­4di‡ojÿA Œ ¾Å›­ö© äà;.Uk#ðÍo†F3úTqÊ÷d]ŠÉ^8àŸO)Nyøf й*¼;øæô€_á’€=|‹õ W‰j%¾é²Ú˜Œ\¥þ ¾™!]º‡‡o&a­µª'Ñß郼mVÏ ß™Á€A¨ŸÀ7]7BÁÿ}ߤ¤¶@:á›É°ë(¸Á7‰ <4%òóoì”Z4£èS ,1OòŸP>¤0×¥ºýOS¥ßT_·›“öäµ¢&-)ãa´Ž¦XJ wÓ/KsÓQ±¤§Dõtˆë] +‘ù€«D®0Šd*/I–Œ{+³±Wì¼µ3lˆxoeÉ*W"£e²6Z[µÇToOúHûå2¦…ÆQ¢FJFRZñÙÊ ³I3ä»­KZ*ÝÉx‘ι\ Õ¬9 £öÑ“–(•²¤÷N惠t ‡†ªg'Ó|BõB¿0tÌ:¿3‹q"/¬³ìÖ¤ÆôÇ$øt4]jö]û˜y 5¡¾TŽï½ÑØkÁè‚®Ó°65†<1…\hW£5ª1iVph}©ª;Ÿ}x&3ë˜Æ¬FŸ ’O¶Äiíjhôkëd3Ÿ}¤.) ìm,Üô×>f#îuÌ+i£5­Úë±â=ëkcØáY"OÍ‘‘A?ymäŒi–1Õ„nßžŒ'ñ c1nsý6èçДGz­F£GzImÈM5‚ôÛ¯BÿÒ#î>2f 5½å†ôW//HvHϺ`a`þù¤ïdèÉò‰ô- ¦9âô=“ -^¨ëžiòëõy"=§ÊĶª'ÒsZ½µ«²Ü†ôLM†Ñ¶Ðû‰ôµ±03ã÷>Aú"9]K¿î%ô;Ÿ¶Íô Ò—ÉŒ¼Ø9±H ïh­^øè¾p‘ÚŒíDz³ÄÈY&ïDúƒ’™/=_—ˆC{æÇäÖÒ öø½‹gÀ<Àž9~¡óeø7°Ç‡Œ"Ô½ ì…,+‰Ù®O°g¬VshpøöØ#@WVU'ØoÛÀƒ½nÝ84=ÆödåÑ%´Çþ€=™,²GáûÌÒßoßñžt7ûàÄ{&öÌñ6NÁ>NSñ‡-Ü3G-6}àú÷¾C¬¿ÑÕ¢½´‘ íDû$µ!C^r”E{ik؆MÁÕ¡=Ý®êu‡X´g# °€ûS®OtQm¬ˆ;O´—Fúš=ëíÙôHŒí©ÅO&VÑ4#íÙˆk"9Àžo… Y!`Ÿ„0ÆgL×K-ØËŠœñë¹ÎâýsK}ì)DN1•~€=ɦ~7°çÞb½‚G<À^*X&&Ué{Ù•Ô “ëù—“5Ó%ðZ¬OLÌ$6éº;,ÖKã`Ò‘ Ê,Öóµ³bM'Ö'Alæº/ƒõÒ°g,õõld9k ó‰õlŒLº3.4X/æ~óÈëÙ˜qtÚì§\/ã|bËõòZî©O¬××âCÎ|b½¼–Igû)ØKÓ|´K[´P/oeJ×r Öb½|‡ÌeìX/m•µJâ)ØK—™'1Ÿ‚½4”’féñX/¯˜f5Ùy¬×oHõ:Ø^s¸®‹õ2ÍÌòÝ·J`°^ž”Œ½åìåïð@RKÂ÷SøœlùI Kj`-ÿt^´êŸ^" ?éýëç5ŸÌÜÞè'eMƪsZ¿ªØY%ƒøK娂äc½¾åýãõnïê·]¿Æª÷ê|¯5½|Òí/d™ò ?+6ã8Ñ]‹îˆ‰ö£m²‘î[LßUè¦ö}½N6>çpøW–í:åoŸC;Mˆ*å²ßV:¨…LR;{¶mï !·Ù¢ .˜}®íÅ!$&\jRû‚m{‡…ï­¼tèWÞ÷üþÊsÛÊ»!|ÁÊËüÊû!|¶ò¿ŒÍ”òËÞé|\Å™º”ܳ‹¾HÆ4‘“ ú™Nê¯ê$ÓJ]# '¾_Ã`ú^ ¸BÒÍôv?׋›‹8ëг-zgßB•ÿRÿö[Cg®¡Ø_¥¨”0~, ’3$ýv~Ô†ÿ©:”¿úË¿þ›¿ý»¿øûþÃï1Y¢Ÿý½ÌFxÐv¥ˆDHÔãüÙ&ÎýÏÿøû÷"qiy~ªî”B¶ºÍЀÈar{Ñ@h SÝzhn¯À<…XIH bVS)MÝ” XF&cÖ• õ£Zgg#ÉlPºxû| “˜É5—Å‹› „¾sšÜ^™ªn•‡cIÁTÝaiûÌüqM‚]%ü `¡?Êd-Ñòq×ÝaSxL2‰”'µ° â*_EMQs{‰ãۤȹ„$ŽÏR ŽœÔ@H L¯’ü0Jo=g(”=GÓÄ]v‡o„ÎŽ7Ц.„ÛûšÅý­KÊ£”MÙv—Çd)›Ü^ÃG•.rÛ¤¬¹½XXJÚF'*뚘c’C(ïìm…ÕÖËLlÜsÚ¦¹½&K\e’¶k?¤jr{ÉX˜*Vów¦j ï°Íì`ÞG•— 3±f ïd1üBÇÌB(¤fr{ñ¹ÖX/† üÕ*¼“ÅœºIéÅW1™/Júî&¥_U×=•º©¸#m)uͶ–†IéÅWbÏ\ Sn‡…ÑÕnš†Éç%-ëusÕÚa ÍEAkì¥i²yé7ÊXD1bRá¨ý¹áè©~"³6Í]J¦î=ŸƒÉå%Uù[–6º·f–`Ê©föM/n•˜žm”™mmMæ„køzb™ÊÑdñÚ¶ffvÁ»"”l–aç¾å `S¡µ('}Ì$ñÊb,Œá—焬¸JBÉ+ûýys6I¼ä±¸fÇR@vcF@ÌPS– ŒÖÏß%º|/oé๦¥;<ãû3¦žvÓž'`>æf‹Î…YH×!ñèÌÌ‹ë{t@õÎTã5žèÌx¼€e':w’ ܧ[t–lŽ m,:×æÎ¹ƒgœb³6žËp€éð¹IžüÖ=>Òªwvg‡Ï³OH2ãÄçÊj¸Ì^ª°îð™qt­á¹œ|®BÓÝnvŸ ð÷ñP¦Ñãseã³e=>Ó˶Y|fÜ0ö:ãÕ|®Ìk¾®&‡ÏÈËh#1Ì_ø\%2àxá¬Åg†£•ÈýU|.,¶@Õãs‡ª{ 9 .Õ<Ód‚—Œâqº°Œíúލ1/ؽ›=Ts ©rÒóë<%Ng\ÄtÏ‹:g‡Ó´æ÷Ö æ§I)ßw‚Çi¼ÑÔ ùä]«Õº\“l˜ÏÇ÷p6m’Eóp-Ìæ³‹=\3DËT4K¥‡k¼}cãÌ~à5ë±CÈfï^ç¦ÑMyî,Ò4RÇAgÎ¥›W¥é²Fì›ýmÆÑ!5ó|²_­@á:wÁ5låé¼ X%x¡¸ƒêbAÂC5-ªKFòPÝc2×sªót2ªƒjIû|iÕ4¨®¥vPM„òLÏC5ÚÆ“¤I‹1éµx@5)ü¶äý]”f^Q¥œ ÝIú(u » âUÙ6Aº:ìñ‚4i¡uEyAºüq ¦°0Öwö‚4ŽÆ­tí@»SfPSó|DÓ±Ë=ôà»à4ÃoÖÉñ8•Èfì§éÉEAØ&Ó‘‹ý Çi´iÑ5û›æ9 Ô'FòlÔ,É ëEå\ÔLßN:M ^x –¶uÁZ¸F“оªÁ9´æÌ‹‘¸-Zã±”•î?ð:2oþs y¼ŽÎÅá5?Êâ=^«™áŠÇkÃXCqxšN»¾,žÇkÖ9^"£Çk>Wÿˆ|-•‡Ÿ‹Û7³V-¹ÐC7Mçr:—ÐM·Ú¥} tã¯Ú­=}7}HAQÍ­ÌÒ VVþIMûÂø¾H~Öû+ÖÍySMknoôSª¥ׯ×y¼š }øüx½Û{†úmׯ×éÃkŠ×š¦_A&àCyfjùþ2}˜©Kñº`ò¦?'úpÃuâ_Y¶–Ìy‘¦4óikS¼ 0;‰äzþiô¡ÂWHó ýÞ§í3ß[yéЯ¼ïùý•ç¶•wCø‚•—!ø•÷Cø!úÂ:Í«â×÷}è;y‰>ô¼Eú^~ˆ>ürŽuº 5hÌŒäüyr.Zrî_þç{ä\žŽœ3D%Á‘s ¡zôñ„Cºt4Îeé—%˜Â;ط̸të—<ÓOB/êÿm™ •õGGËTn‡hòÒæÌ¿R]ð6õ”dm tñ7ãLŽœ«V3*É“sÙ4eSyGØ9óJ¨õÁvk T×ùÁdSëÅTÞ‘þƒ91,£íf²òÆâŒ ¬@ùð¥nì\[Ê)EXÏÎ-»wa} K4|±ªµQJ3•wÄàƒPdæÍTÞþ&<óÂú@‹I,•Õ[ÑÅë;—ÞWúÆÎЧô›Ã`’”ƒÂ_Ž+K1-ccçr~lše8ë/“ö­57š.âò] en4aUËt4ó#> t ;O·&VÃÆÔúº†«Ël\£%ëWò ³FGÖek¦¬ÑÔÞÙØØšLíy粬Õäø:*ËϾd¶ÇCY¨¹ÒÈ7ò³Ô¼Ñv†\­yÕÞÙÈßškG?æÇFS‹©½£m£W‹£íÐVÒ˜‰• mÇ`†g;×jŠïHÛ2׺ñv†X©Õ߯r<;BoóÂhãモ¸óÐÍ´â+Ç‚‡n"ƒYÝt _윃n2wÖt“¹Ë 5tã¤1a÷}€vèæicîŒÉ×Cw×Ðˮ렻6KBxèî%UYCð€îÜ+tCÛ4.tó€®›©xæ.›™;즉tÑл˴†dÝUbÞä—ÇnÚ//Ýb®]÷ˆÇnû#Ø]šñ6ðÐÍL“ë¼zè.Ìx9/ä®´.¬{zl¼A6Ü,/gî~ÜLuÚ°2¹È] ¿åq»¨KÈ}‡8ÜΆIÙq›ÔèZPÛŹlxÜÎÃîI‡ÛäÅÖîq›~ƒ 9N» oænqèM˜2“öè™MävžðèM¯†‡xóàM(Z:Ý&tw«&îB·qjðàévû’m2÷XÎx›ÄÍ2ælȸ?Ÿ1z‰·ôãLº ÜÍ)›ÀóÃÿm·$ì~@Ý ÜÕz.·‘ 7{¸;Ë ÜÕžª ¸Ó³Ÿ^ôæÜÑ}¸»Yçï&òZ¼MÞ,©öNþIì-¾Kä}ÖûvÆ{?™¹½ÒO·DÞúõ:£Ö‹!òž¯w{ÏP¿íúõ:‘wMñZÓò+ˆ¼B Þ(M¼L䕞è9RFg°ÄŸ‘·Îá:ñ¯,ÛH漿xÍ|Úª¸ø.ÀltŽïù}:‡CØè7„/ sdžÎñCxŸÈ³;ìKˆ<éЯ¼ïùý•ç¶•wCø‚•—!ø•÷Cø!"/³àÅȢ߼FäùN^"ò|'oy¾—7ˆ¼R:­ëÐÅñß/yP ÷‡ÿòZÉ*êw‘QPo¿|ÀOrf[z<äZª+>õQoÉÒxÌd²"5Z¶–YlOËuÕå¡ÞiâèZ¶§¹ýjõ+u‹ÚÖCeó 6†çFE=\‰[Ä=|Ñ­Z{BvQ@­ÖU•Gl‘ËW·Õ±ªòP9¦©®GQEZÛ,ÁF„´²‰Í :iišÖ¬A¿ÊcqlPÔ»1­£bëŽÅÖó±õ±ªò°ÍXÛp,ž3ƒµá,ÁÃ:þ·1VÞ!Ñ1MÓ±x ÿð±b²bz\Úps˜Êâáe+°£SO¿7¬Úâ«ÖȲxÃT²ôÄ“rˆÏ™‰õèX¼òQÖ>éѱx.ܲSU6,ËÁ>Öªž‰ÇÔüOdB§®~ïØ”MüSOΚP¬ý¾SU6,^a )=ožq|îÙÙªMëÅY˜@t}è²ÅÜø°/½Ea.“a¯Î¤PiÿÜX0’‡ÙëxgÜÁ{Û(<×¶Y õßÛFáõeè}§ð–)¸wgQh´‰\‚½o^_t¢Þã™Í$oQxl‡eJÜa»&<‡Údéú2Ën¨]X:ÔîÎãÁ£6ãäV ŽGí:- äq‚ò©{Ü®ÙÚs=nsæ+„Æã6Ûƒiæ¶‹c¤=l£Íx‚{Øfáʲ·Áö´QDlWkXó°í8HÛÙ9mxØ&[²¢qÇ á ø‚çsüÞgòÌÃ]ýTžöè×ÞwýÙ\Cˆûâ»1|E:Wƒ_}?†bóðW¬µ@{)á·è¼­——ø¼­—·½­›7½ŠóLâ¨Rû%FoØÐ¼ÿñ‡÷Bóó.-ã0‹¯\nŽ¢¬‰!Xžºµëé?Š©.B8®È¯Aï~ßaRgZŒu˜zÅò“µ[ëp´jÆh«´½FM„ÍEæVÙ0…²ÌX<†ÕëÖô`Y½ !ä1óª ËÚ–ŒÍŠŽ%õX°ç!çÆ–Ô›–œÔ‘àÂe‰¬²¬Ãé#-õ|ÌUQ„™ì„cKê5‰n»l‰ƒµO–µ­1GÜ•‡l²òÉ2›Bˆâ—‹îHËö=C·œ^·6ìƒçô ¤‘HÖ]Þ°ál§`‰ú”Â)§×èm{¦z¬ÃúWÝRyÕzŠÎ<•gì˜3Kå1¶éY­É '–Ê3.ųk®v%ñ•—gR„N9Yd^¶³k¶Æd¼Àsy&÷̤n¼¸c¶n¹<ÚInÒd²¸É2 »|¦³çl™ÝcãòÖ(é°¶i¶Y…& ›,£p² þÒgÑ4áxsköïÄ‘1FáòQWØÀœÝ…“eT¯k^rCkÚ½¡5d¸þ¤åÜÐ:ÙüÉ­1u‹ž­%'óCXnhL~– ¬Ýmê°š½-ÞÎa5>Ý&J“:}«éº2•x¬fh£Ìy°Î–ë÷`»õŽØÀÚX»t›p=%7ê%è\`]ÖÆþþ|¡>¼™`¢òvRÝïªZß%î>Á;&ÅúPwk‚¯ô£åîÌÏ×Y4lbÃÞ­__Ðq´üùù:wÏòî¹ÿ ¯KUa±Lûæ»^g|ê–о‹.|½$Ÿ9“ëü¿²t÷‘ÿLº9UÙåN¶ùf—[e>ß÷W9õ`òü ¾„Í©—· â È<»×â@”ªÁ/îérÛ¾ï/Ø#äw€ÄWì5ûàñC„^k,‚…2Úk„ÞÖËK„ÞÖË[„ÞÖÍ„É;HªÅ!ÑþŸçؼy¯ ž\ìw™uÍ!si]Ä"Z%ï2ë%›ÜŇ{ov4ZFúõ²ÒÇåDm,qÁôjËEÿH™uA‡FGêµE>²qËCU¯ÔVµ¼S N—Y§ÙÎ[Ñhm4”Üá1Lkz`º®¥³H¹dÿуJë•þm—¼? àÅ:»Æ¬Ù:¡æÐhí¹[{5ñÖ»ººhm+]NBp1&Š mÖôÀPÄå Æ.ɤºº¤ÖZ:]ŒTòÃU]}‹¸@£µ>0KÖ C£5? Ñ¤>…‡×ÞÕÕÙø¸Ë¢©Hþ©­Îá˜`4Š ‚¡"¬­>¯·Qÿ÷/xß½%PcYAÑèlŽ<ޱZcƒ.–Q´‹Þû—1P+½»¤ÒýËê?¦dlÖÁAËãÆ !q…Ž ^tï_vißÚ­I‚EŒ–] Ö&A†yÅ”¡±KeëªqF L7HiÝÈ|r Acñ¡ cѼ0m,H0¬ŸDÏFƃ&Ζ÷›6šmŽø›6#¶jú×FÁì‘DâÙÈŒ„YÃÁ”,õ7-5‹O踿éN@ŠTLî}Ì(s0a©ñ¡;™].2ýºô‡eg^+£çñ½²¾6ò‰ïÑÕ2Ýð½Ù3ß™«Íî ïÓq2¾Ï ‰¾·éêE9|Ù†ÔløÎ½¹¸— ß»#½7„цGo/–¸Ç¸=3šº€ékµÞêÒ³_5GÝ!}«Î¶å¾Vk[Ýž>þÁ ®Cz–Ï[07¤oÑÀCzèæ&BcCzª.¸\f¾žtHÏèùE«oX_ÉK? ìõd0W1Â ë …Š‡¦Ü°ž&é)ºa=³gÓ™Ãzòhö»9¬g†9³]=Ö‹ø¡½6¬g‹3öX_¶‹Îa=Þš£¹êÖWoÃú”f5Öo"Çz&:]´æ†õü”ÝÌÄa=Y{ ØGd{°'‰gðŃ=y-Œ&4-òæÁž_Ï\!ì‹K¹¡=Ÿ\ñjÚSp3‡Ý£}v6´gøÜòP¸‚D‡¥uެƷ>ðl‘‡;à'˽Éǽ¾+‡éŸÎ"&‚hünã„<àÓ•ÄDÃm€¬·ÕøÓF%l ð»£þ6ÀgãÊ ¾Éã¾>ú°üñømцàûpµð£•Þ7WCØm€ßLN“î»qµØÐw¥C‰´ù‚${©9´o^èÛÁ>Xp~ÀÞ];ì[´ž;د}x°Öoûâu¥ìÝMàÀ~:ÅÔƒ}ñŸ´y¢Ñ™Ý±~ÚBŠ;ÖÖ¾C½c6w¨wAŸ;Ô'é¿C}´àõÉ+bêÉ8Z=ÓB½Ïü¼A=ƒ÷Íößäúé,ê%s·}rƒz“h{‡úh/ìPï2¡îPŸ­/ÒõÝ"Ê÷s½~Ãça¥¥’äOZ°êœÑªz‰wü¤÷W Ÿ×<~2s{£Ÿ”5ñ¥Îiýj+dâ¥ÊYA2_^ßòþñz·÷ õÛ>¿hD¾„^ﵦ×ϺýECllP'ãl½Á¤¸ƒ*PÊÞ¿:Õt¡/f‰ü“»zi|Ná:ï¯,ÚuÆß>…v>štRª¿ /´çcç©.¿÷lÛ^D¸!n*¸8%‡‚k{qôP‚\ bÕ>Ûöþ ËÙ⽕—ýÊûžß_y9K~åݾ`åe~åý>[ù_FfÊx JÖ óL¢Oî !­ŸüÕ“Š®ˆ¨ *ôœþUÙ>ß Óc3î*}üO'é×uBÕ'[¯üã½d×Ë_üeüÆ‚ðPs~÷¦Ï߆ ÿA3ý­!1×P쿈þ±Þ%Å6¤*(µ±+×ð?U‡òWù×ó·÷ÿÏøý1&©Ê}ég¿A§¥‰ºï3yf²ÈžÚ8y\yÁ¿ÿÇ߿û)t‚ó@ëcù¤‡I“ýé#ÏØ±×Ewš&)@TøVéý[J‚º$ Ð̤nGeêˆzµ5Ñfûd "2Ý^×Bš4KÒÄÙü& ZU…m&Kl*¯ŒR>˜:'l ªÓ&i3i’*É¡üÒF&m«ÐI/Ô”J–î˱Ðl‚~c}† ý»Cá‘6Í’"T­Š“M¼H›fIÒ;%7£û&VcáHJÅG¡';N@Ñ ¤U椒¤ã€f3MɤHâ T3‰± eSå„/l l4y,›I|%–*ªcÌš")´®ÝZ T[ Õ\Žë¥ï "`nÒVY,åþ^ôÅ(­äªÏiФY{Ö)Ìø!ØVMŠ$ÖÁ¨-ãü‰ý%USå„ÏuŒ$(É‘XVK•z¸,Y3EN¤¦F£ÑW”ÕÔLФ*EG0À8õ9Sä„óJ° y®›I|®2°›e^ݤHâs¬=ës¦ÈIÚêøÔ± “"‰Ï |Ç)v¾4L‘“ªIÃæú9†I’$ŸóKUNGš«È‰|<†Ï/¯œ&G’Œ„lº¤Ê¥“c½ËòÈjcÔ£CÓ‡8?Öìbs0’Ø–C¯×aË84ÏÑfr>Lá豇–£µŒ¾aÏĨmŒ¨3›¯ìXº&m&CÛ°Y1ç!ݱË]’GžËØq]øe‰¡¼=­eqN×é%“!I¦7 ë•̠鯒ä {ììçÛxȞ壄­í€ì™é©0c㢃ì!ÉøÒeXõ-¶ëk«{ÀžRñ®„ (`SFÉx~„z 6¾ú˜½q3ì=hÅë¡¥yBö cK‚lYÇÙb·G_%ÍÌuØÍ!|@öhLÌ7¯“å!òtzû'Ý™¤rªÞ6vηr<›p•5°ül‰iÅfÖ«Vñš mñÉs€=Xí©$.öØÜt2(ñxÝiA ·Ùãõ`yYl8ÅV׃° HŒº?\óœ”G˜ñpÍ‘ÈÓ8ðzŸ ½EÃëAT£ ]¸T‡×Ü<ºÖ<àzHYPL[l¤®Ùnõ”Å+ÆCö s0ó貞²9ó’¹–²ïf qŒd‰ÒÁÝ,7‡‡lÎ@d¸pB6žKhì£Å²OœŒS6¤‡lòXž×s²¹®8Ò%ɹñ=X׸ᒞ'd£ @‡=6ÄÆ6¢éõký×™ì}¾\OЃvÌü #”6O1›†ÑrjO¿Ï×»½g¨ßöùõ>¯xMñZÓô+xÅÄàfhÊD—WÌtÆámÕä{(Ì·yÅu ×yeÑZ2§ýEþÒ̧­°Öwáeg—\Ï_À.̓WtCø vi¼¢Âû¼¢Ýa¦˜Ý{+/ú•÷=¿¿òr–üÊ»!|ÁÊËüÊû!ü¯QucÄÛï5^Ñuò¯è{y‰Wôü¯ø ¬DmR¸² ™}k÷O/²vyn6àŽŠo"$’àÌ tj H ³SO_ ½V V¦k›)n­ Õb½Öèåü¤EbqîÚTÑbÈKx4VnšÐÙµP}t¬™[ C<Kr¬]`-‚Ô¦(Ì¿gX»Æœ=P7’¶YÖ®p±ƒªƒ Ûé‹Õ<Òµ­Š7óŃPGÂüš8mjê‹ ©P÷E%#€Òm¼/.„ŒX»¡ÌÎ`y»mJÜòKq¬]%åÊe\K ™FÍ6ÌÂah;IPØ£9…X’˜èg@‰• 4SÙ„mqL i2…MÈÚáôù”W²œÆ"B¨¬=æ±Ò7ÖŽÑÀÔ’¥Í±vhcÍšk(ýfíøqc;im§þò¢–±Ñv)U¾XŸs´mZXµ,¢n™mýp@–…™Ž¶‹+†œmmíš§ì×m‡k,`X“XÃÎÛAï¿X¶m¼]¡>ÞäÈÕèy»‰]ƒ.DçŒoÇ,R¤Ì¤ÍÔ6‘¡¼T’šLu“y¬iãòÕ¤ÍT7¶ ÓÃá—éå¼ÃÍz‘¬¦r\.—e%¹b BÏÕì¨;ÖH#NáUyÞŸ$IÚ[çù–Rvên‹£î°!ÉÖÈHª)n"mØRj*­Õ1wÙ&U®ÕÔ6Qö1â«Ô|+þ⼌ã[ów¾‹¹ÛP›Ih®õÞQ›ÃÇ‚Oup¨Mæk]ÅßCmaîÊcÝw¨Í›/bzÀµå–(+)6Û´îãJI,¥¶'lF½±ÒÁöT½_uì°=ÄÙ¢_ÌŒ‡m¦‡ÃŠIo Ûƒuâ“ûÛ,+p"nyØfð ôЋDt°=$“a¿®Ç²QwØ'ñà¾KVøNoƒì ̹色%ŸºO{ÀfÂZF 1Ò;ĦÔi‡Ø-jú:€ÞÙ¤É`«)Å#öœ½ÜT‚l´àâ ¿UĞݑ¬u öd6f‰Hb³ ŸeˆÍ6ËTå[’ÏT4ðÎ#6ƒòpTªFyÄfþ:ìñ’ã‰Øl“Ô{©á[xDIýZĬ,Õn˘GlJ¤M̨å@l&«ò ØŒzÁÖ åì!6ìxô°ñŽÂ _„§ö€Þ2öE­Ð?Ü žFñ°™~¨ßþØ£ø’ô`‹»DØלc­ðvà5¹Å6ï0Q×B#&,@É^‹¹\bAێטÝå\P¼â|sG®y¼f$¦Ò4îÀã5#0Kg9Õx6 êOt©Çk†aŸ3âÀk2X9Ý¶Ðø¿*”‹GlR~¸® q‡Øƒ9ýè‹¡0Y·Ð»Šr…²‡d0Æ!1é²Éëá; ÿõ=$›>îo>TõÃÁœËwÖµønîΣ6ý!·‘Ú‰ÚÈ4n'Ÿ¸HbÜlù†Û$r–øäp;P×À:ê m¸ —kPõ.È[ð·s×°‹ÜŒ¯ƒdÑK¸ ‡Ü%!x3aDä&íŠÇæ‰Ü¤^°#œ²63Sã©áYÏ%lÀë0oÈÍøP¡ró˜HUåy"7¿ß$…³7 :`Øåòã›ÿ˜…¾÷À-,¢LöÀm>VñWñI[‚Ï—Bà‘›X1rTkCn( ãú²r³¥’–7lÓ="Ý®lã6ZE–7Øî’£i¶ý ¶÷´ ®»á6뎎x‹k·™ƒ„~ ·é‚ÑT®O›Ë)£kkyÜÆíAN.¸ µ;÷Û«pCm =£ªžEjs#ÑÛ¬'j:µ´ôžÛa­öOÔæJCJUnƒm‚*v–ƃo°-阙ŷÛcB¼ÒQÖÍåòU¹4⠶ㇹÚæq£¶)òÇÚõb3?CmfÏMo\ÚJ{|±Ô†&9’vߨ=˜ÃVéóï¦íè1q¥¿£µG œòG5«³ýMâîÓþß0-ÞùÉÎf3ÔÝúõ:‡6Åñê÷ùñz·÷ õã>¿Þ§î®)j¿÷¢îj“@bHPùߥî FÐ)ºS5ÿùPwë®ÿN]¹ë”¿ÍŒêWwÒ¡§p|ÏïS8²vžÂqCø G†à)?„÷É;³ÇpS{§=úµ÷]ARW9N~ñݾ"««ŒÁ¯¾Ãxø+V[`^vˆ³o1x¾—×(¼­›—8¼­—7H<ˆžÔCéª<!}&õ‡Âûx/ o0¡äcY¤b„ɄՖeÁM=ãF1ÅEhóÅwÃOÑðFé–Ác-ô˜/EgÔ`<*•b+ËÒV,…G­$Ϧö©QMa(Uª’‹63Úª+RYc:Á•gkð-®&‚j•¸¹³Šæ²+°ÈÄòï=XÕ>n#ì`EGU+’.o\éŸ=.…Ç|-½5ŒlÝ(WwÃÔ!m uÄÌ4Xûd1xÌ6%1 òQæ*&"ŒÔ#¦s‘¦b£ðhvŽj4Ç  År"¢ëwž,{²<êU1 5G°t³aðhÛ)Œ‘jòÁ”áì†8´k5yÖž±¤§vE«‘6_v¶áÛA—wÆ.Ó<ô1³Xu&‹, ¯±HÏ¡h[±Séà rÏdŠˆÈ÷˜,¾!N¬3ËàQýÍ3«= ZªeððC\Ŷ6Yèd1x…‰®1e³„×>XùöR¾g)†ÀcЖ,Z”¦n ¼ÂÚ\7i0k°³HÖxeòžX/Tð…²>×-ƒ—év}{‡OØ <£&cš­X/c ïd5³uKá±J«2I<à$+¿8<îÂKÕÝ‹‹Á3ájLæá8<)‘¥Er'+œØ <¬¡@ƒ´Ëá‘POá óš£[%Cpx56aÎàƒðLêÐI–gíW†Òö;bcÎnIpØMc¹–·,v³¿6òå‹à±›DÈCàzèfzÑÄØ÷«jÐ…ñ©Ãû"›·¡w`¬-6üìzSRÉq^QAz3%:dh=B'zcjµ*,îèW߆Þ$¡™“U¡vGï$†¯èÍK²h©øOÐ;U¡šë‰Þä_Ò=v w€(8ªl¤ ½‰´®¯Ïr ÷|2£oèMÅÒn¢à@o€·d‚<Ñ›ßÈ«évôÎ÷Á8Ðò¾t;xgMÑžOðæ!ä_âoÖ¾« ØSÇ»9fáŸcw×ZØñáÉ;gõ†ÝtÜÀº÷ö vûcì±»}HÒü¬ÇØc7CGÛMBmØÝ˜ ²_;aÃn›uƒîaXzèfgüƒÑúgÐMÿ¥ þ‡tk¾XAˆ »é ©oˆ‹ÌÝ™¢gý »:ênºaÃn‰¼éµaw¶É6ì.Pq8ÆÌv3M#´;Ý”­ÃIdÃn—yÃn:¤JÌv=±›qàRÚsžØM§¢v»snØþ¤üKÃñàM9Ÿ©÷ë¢Þx'UñàûN¹ûªÓêê J*«'ûï*™Zߥõ>Á;&Çú{k‚¯ô£eöÌÏ×96þ†Û[¿¾ ãhÙ½õó}zïžåÝsÿ_—ÊÃÐJpÍw ¾Îxܯ¸aÚ÷p‰¯×í3'rþWî>ðïŸH7§*YËxóÍ.·ò}¾ï¯ zêÁóùA| ×S¦oÄP}v¯Å¹òн¸¤Ëmø¾¿`,;ÀÚn_±4ù ß~?D÷µ&•–˜à®¼WÌÏ÷òÝ·uóÝ·õòÝ×£´Ä´‰?ÏöËöýË{¥òäV¿ë°7æ¬ÏIusBQcë{F©²²šÊ¿Í$ÓâSÞ=4ÇùáA‘Zd,溟Wv©ƒ¡ŽúQ‹ds$S`WÝeQÐhi?&ö×Òõä0¼#þÆ“E m¤¯BìlÄG¸mRh´ÌKÛ3çeE#†i©¿*õVh,’HO*€Zh©J ¢±KB r4B™­—G,Ô&k‡`ä_ÔŒ‡Úh ÕZ ÐÆ,.W!v(8RÝéòĆli,•[>ÜF@Ò.6ˆO\}o{+»ä’BìleˆÇµ4RÛW!v2£aÄgIb²æˆB;g§F'’¬A¢0: ‹?®ÁRá¿ãIª2º.Ç«l¼p>W!v}-„ÁTu@Ylx*õœZßó ’H¶²6Ú‹’6â}÷Vfc 5^I÷/dãù ,c Wº«µK°Òü寪LšwoåB…µEî6mì’$H·2ŸlåNíÈ>6¦¯˜²Šh3¶ éqÐ'[¿•þg'³qE^aÖ:ÁÈÉjÞÚ­y‚OB—êékq²j7wCTcÒyPñOF"™IÜ‘µËa ò`¼é4Z Ÿ\¦”OÏNfýK«+1¢0"äF“µQ0¾ñWZÄ [5HÍk#3ÿ(ÞûÕˆZ9}à0ÍâÕhÍLì‹mתXZ˜]ÖØ)¸G¹J¢¯]™.ßê –.U?®]$D®¥<¶ü]×tq~­¾ž‡ùÊ\•XÁ[öv0O¬%Ä…ô ÌN‚>u0Oúpð`ä ÿ,Ì3çÔ2nå€y6¶ ¬VAËü„†<å¯ÊKa©d ?å6‚­rG©x”§¥yEAx§…:¦VñÒq‚<7Ÿ€_n'ÈKF½L ãy–ÔjIéy±`?©ò6”Ÿ 8­óò3ð(O¶‚jwÛFöôx¿l(/vÞsÎ'È3ô#²0šîcò$™ù*]]¦ÍêœéÎÔs;A~f¶a<©ÆÎH˜Ù ÆË âbÃøÁˆmÈhZxuÃx²’lî‚¢²Ñ†!³éè'Æ‹íPusxŒ÷Æî ã¾€é#~‚ñÂÏÎØªòd­ÆLœO@žl¶ã•°ry>Ùóͯo OKùxxŠ ä%Ǫbì‰òì(~E’o(Ï“TëºuÆf‡îs.§ åiÜFý*ªìPžÞ©Ù|O˜—ÁbxcŽæ% rÀuì<Ì“ï¬æ/ÙÊÃ<éhZY£f7˜—HJÎ#çæ…K|ŠxnHO#wÔÖÒ3ŠGÍwé’ßM&î"=“&ŠSJ;±¾1âS韈ôLÁU ß0è°}`w@ÚmýÄzèØ#Tê‰õl˜ÓàÄzÚ>2$ Ÿò`¶^å6ÿì){Côzôö’ÊoN§H/aYšfŸõhÏFŒ´Åk–ì9‘Œîr¾$ öüxø:wáLöšÞc|kt$y‚Æ3Êp´6Æ}Æ-Æãc < §Ÿ’<‡­¾î òlÄö“õäåIœÄ.œ³ /Of¬Q¯åyy2aò)(/ètj åù·µÆåÙˆí&Éõ”—FI N”g#‡n¡ñ@yùn÷:ï(ÏÆÒžå¥ºX8òÚ½uÖ¸£¼ŒG…§z ¼4BCŽéÒŽ,ʳ1õp‹ô(¯zK(/£ôO0žMwgÑÜãÙ.w¢ãåIõdÍÆË“KõÀxy0¶ÛÈc¼>ØrÐ,ð㥑Á©êwç1^ËI§(ÏÓ3!`_ò¬ƒxi«wlðlÃß'(é@xyp<:Õ É¿Ó`Ýï”å/Êz:Vœå– èðOZ°þ‰­ú§—èÆOzÅâyÍã'3·7úIY`êœî_C$ôWù>¼ýãé÷úñÝÞ3Ôo»~Å·IÆkŠ×šÞ?>éö-°z0~4 Þ !®ÐçFkÿê#]½yXqw0SâŸÜÕN1þÅ_Æo¬Ü ÄúÝ?üIsì´=e@%+T¦æ›RÍtž=·Äž‡öüÿýôíûößðÿ~ Û ÁœW6Î…3o#¦À”"ËïBÝè þJ ‚½g×öâ6õ š z‚m{è[†<ßÔum‚k{‡¡Ô$qÿ{+Ï·•w=ÁÊËüÊû!¼¿òrœýÊ»!|²ò‚£Ì•—þT¥ÌÉ4ƒ-ôS¥á=õEœÞô}àþƨ#$ýQ¦“ú«: ¼ˆ˜®Î³“_A¡º^J§*Ï‚Ýóç¨ÍXÿ”›î·á#È©ãÆZlê‰ýú;Ë@Ña•i§##¯˜Ø²ÓmøŸªCù«¿üë¿ùÛ¿û‹¿ÿç?üþ“Ý5¿póÎF%|Љ‰ŠrŽØ:'‹ìŠþÿøbÑÃØM ú4Cslê0L§Á/¿2åÅ¡YœBÁ'íâ†ûœG ؃Üpƒ’ÚŽ×C ˜]‹·á5?˜æ¥rÓáµ|̦LìŽ×C …íH=B¶çÆ!5Ÿ(åYRÕ!o“Ñ,T³-/6@¡šiAËBµ¼l<ÛAµ´­½ã šƒ2> f¡zh¾Æ»“ƒjù¼%-Tóv?Z¨5–n[¾ƒj™´…xØ#”Ñòí{f›{—a‰šOÐ6_iP›Å ±ß®¼¹µ£“ŽSZ4âõã º½g¨ßvýzF¼¦x­iù4b$B?’FǃwiÄ@æËYnã{Ë_M#Þ”PY ˆ´?OqÁ‚œWöÍHp^3Ÿ¶vå»·qI®ç/à’džKòCxŸK’Íã¹$7„/`íû‘n+ïzþ‚•—!ø•÷Cxåå8û•wCø×`3+;Œ,ÊÖ[,¢ïã%Ñwò‹èzyƒEd: ¨·ÀYágYÄ”=‹ø‡¸Íþ4±Ñjpó¬q;f‹’³n8%¸¥º²E Q“{[KÖº©<¾£-[q:§Â–ëª>C³!<˜€v±ˆcZ¢­Ñlp¥Ù‘¦¥mµâŒÑèVƒp娡e`.Þ¢UgÜ ûñë—œQ¾È2&‹ªbæ§²ôÅiݼ™ok7Ðf¸;f Ka–YjÍY7ÂG]´Y#ez+ŒL´…±uç#ݬ«jëcUŸŸì¾aXëFgÚÂÇüÔ†³n¨:°±rD‰®ÿZÚtÆ Zù‚•ßê32”e"hS­ÌSöXQ:í÷†Ýz…côà¬Ép~vƒ{¿Š{÷úT=:ãF´ÑH=:óÓ=æïNËÁ³_i9xÌ‘=mÖ±˜‚NÃÁ½]©/n¾'gÝ€ž°Œí†ƒg¿Š¶þ°Ð=;ûF´ Ú³£‡-¢bhÄÁt‹7)Ö‹£ºË6Û‹3pk·íÕшẫ ø÷ÎÀaÌž½n¿ÒÛfà0¦T‰7µ.ÒÆù]f»hÄic%l`ñˆhûÿ›;»d×q¿g1§(‰Éed!yI²ÿ4hÝðMMMfäš·ëÃkýXÔ'"«|¿(Àa¿eÓËVáî¤ÇäÇzª£aÝã†ÄnïlóÌí69»@¹}Mþ)•Û^„D…Û£[R¸ˆ5……ÛÐ&¯¸]™ÛpÙ9U¸íøhÉ)à†¤Ém"$âRíp—€¾I:Û%MÚƒÂ%Ý@n|g nß_¤Û3¸ñ5ʹp»ß2bŽn÷[F–¾€¢fhæÂí±^söE`ncwüœ˜IGœ!ô ¸] ®öˆ_ç6~©±­Á‚mHŒ ‰Š8dòöÁ ¶qÂgû5¶ýè"´)Øö±x•l»:bá¶+¡±an»ã3tá¶o’ùKÜv‘4$á¶‹±1•…ÛîÂmü,$¾·q,%.¨pÛýŠaGnc#ÂÿÌm·ë¶ýB'Ü^2{\¡[ÔÄJ^'Á¶»*ãælãkTk@°ÔNÁv(ÛnIû_ëAq”•ܽ†¿ùãûD ¹½¤Î¾>Jî*ÑúDî 5Úß.æDîÎ9väæ·x&· •±ól”ܸè0…Üh8Lï«™Üü€Qrßœ~”È}sNF"wçº ‰ÜR£!‘»²î©ä¾Ø ˜ÈD5å6Fè±$Ü>NXLà¾8QBÁ]ðÂË÷`Ûh7'A¸)ÿFÉç½ðdt×P¥ºeM“Ðݽô Jî)¯–JîÎÊf"÷àÛ#“›Òh¹;¯?¹o^ %rëÃGÉ}³=5‘{È/]sHÌ„rÓRïƒÜel­’»sJÙ¹)©$‘MHb•u§<*’ÐmÛ,{qœÐ}rŠÎºÏ€Ôºk$¯.tËÚýkŠö2ô.ˆÐÏ }ú?WÀãOªŠ¿ÜÿAÇ÷‰ü‹Ïî‘Í›tÅ÷§/|³ÍÐ_¾°Û÷®7>=®+¾NqíwøtÅv»Ëú4œõóY]ñ.½iÐ&m¾§+6¼rØÛ”==®¿©=1XÔy¦ùà‹4ϳ€Î¨}CZÄ“À${þ‚À䇠“Âó“O˜ä¾ -Ò³·…oh‹¾Çtíe×ß(¾ëÇ _á Õwý–Ö«/ÇðWÈ‹ö'ôçx‡›Oé‹i' Œi/O)Œº›'$Ɔè«=PÑÓåwÊœž%Æÿþû9£â¸:)Œ'gÀΣ¿ª0Ý;z=Ñ&g Œ¢Bšè’6E)&;Oê>“Ä­yV —Ï›WÕ*L䟛è³ç+jQÂhÖÂNÅÉŽÃY+IŒçòD“œ0*öŸY·ßh6j;ãV¾¨/gLa§âຽrBbìœï?ïÂc‡Ÿ`Ÿú]YbDÁ´-FÍ»³SqÊåvIŽœµ|,½ŠS‘Ì-¨À"NEž%X °S‘¬ƒ½qØ©H‹9ú8©þלE­Š»v²-;´PçìjT¤è÷ëÁ.þ˧FŶ½0¼õ¤LíÊ·Bû’\t…ö)á;6Öi”ß!Ԇ녈!Øöï Ûˆ(ÓÍ*Øö•N ¶5¦‹#ØFd8’þ…Úû˜ÌLí&ú•Ép(Ôvé1\˜BmŒ‘C“©-‰BíÎݱmÁ¶«mñ4líîH¢`Û·&SÁ6¾Ç÷8c{¸·i?áÛþÎv¦…mü‘êm ·×+Áþ=„Û«p,1½kœšJß ·]µ =F¸í1ì°` ·Ýàlá¶*¡Œm7Ó“€±í1ì‹ ¶]@ õQ°mž-½£* Û é†X,Àv—%ÑŽ½Œ¢ñ\g`û™ÅÛ{ÊNA`ûØR…ðÚUÕ¶§±ðw‰ùÂëueö¯Ï¸öz´‘|#À^õhßÄ^»†÷ök1ØùŠ<(-*²½b¬þ…Ù×͵¹Ó›¶-#ƒ.A[ ±@›ží ÚbÙ‹Ÿ¡M¸ø€6 ÷ Ú‹'hŸœß•¨]9£"Qûàw‚Dí[NA©]¢`Ebv‘•3ÛæzøžÙ T¨‡ كݛ Ù]Ð+ÈIéNVdwJíHÄ>.zMRbK½Í7±%¡"[jo'b£mèv=&bw.û‘ˆ-õ;±o®?úAl Ñ$bWÎØSdW.Й]¹dBvç$¹„l„¬¤ îʉ& ÜìŽNÜnœ\—¸-o^‰ÛÅ|åöÅ/^‰ÛpƒÇòOÁ]WÙREv‘¢7 ÙR=1»b>íËöÉlú^‚6•Ó}Aûâ‡âïçXÚVõ0Ý^ª¢¯ñVKGü‡G{:þòž 7¶-,Æ >²§ã`eqü‚Æg³›´Å÷§¯ìø`u‘>>./¾Ïò½çþ'Æî©í¹{!³ïQ±£V@¹ê@ ûo ŒÝº†Öb«4ÿ; ŒL… Ð#“ç ç© çÔ¼ g}F}p—¹Í£ìû+RSûÐÓA|CkjJ£Ä7¤FžkÇônƒÞûÁà/‘iȾ¿1ÞIr<ô ¾0VàZg€Ä_!7Þ÷sZ=†ú”ܘvòܘöò”ܨ»yBnìèxÒÏÛ–ç凞µÆÿ<×RÑß2P¶!3pô°,K7B¡¥44™íàÔx” ÈÍi6(z£,¥[7ü¬˜:£ÌÁ€ V/Ùt!Ù å•&o¶‹è8Vtî(ƒõÆ;šù˜mÏÞT<ž…BHԥɻzGÔ‡:ÊdÉqœ´>´±ê›Öí ;Qľl°{ɦEsTÚÁ¯ã(¬9ŽÂdÑÑK™6ˆêHsýþ>Hgy,;N–wmŒuG$‡Zl°{á¦Ûv僄0Z”Ÿ×¯}­ÊHa›°AÑ;G—À¥y—mÜ6{àMÏûgv®škƒÕË7]¶J_ßŒà“ ºþØoJ€¶Ó+^¿É§°;7#Õ×msï)ŒA ÀØ K6HM[Ž£‰‰ØíŽŠÚ mvOáÞ¢,¥v/ã´¦0<š¡ˆÚ<`²K V$²7Žr`ý´=‘mz¥!”ÀfG[Ÿ¯¿²i­¡]Ú`÷V0k ã+‘²|xßSGb© ² ‰Í†{ÂY‡tŸ¾‰ðÞÃÈaލ ’‰­F4߯XŠìœ£`“´xC˜×nÜ‘ËëÏSemw¢´ ²éÝ}vPܞȬFb³h·AÛlLa© fƒÝ{ü¦°"gùb×z¬û¢Rýž1ë?¨ŽšVt…”ê×Í.ÖDu<ì©ñ­Pj%Õ]Sª#òMÅL•ê>H·!³1lz9S¶£#$¥M(Û!KvÞêLºäÿb» “÷RGÙîQø½*Û—ÌI '½2ÔQ%¼k‘¿¡„w1„%¼ûEB-T»”HsŽ1²äà—œ À»Ó’GïÑgJñÂc²’çK ¿~» –~y™h³Lx8è–¯PyL‘w[Ozž>Ù²QYßfýdý)s'±þà”¡Äz(Hv¬øÊ/XߨA•Y=ëÏÐúé»\G%½=ÈYI/jy&ýÅ&×OÔŸtS&ÖŸ¬´gÖwv‰~²žŸK‰õRw3±¾Ø¢w> endobj 8 0 obj << /Type /Font /Subtype /Type1 /BaseFont /Helvetica /Encoding /WinAnsiEncoding >> endobj 7 0 obj << /Type /Pages /Count 1 /Kids [5 0 R ] >> endobj 9 0 obj << /Type /Catalog /Pages 7 0 R /Lang (x-unknown) >> endobj 6 0 obj << /Font << /F1 8 0 R >> /ProcSet [/PDF /ImageB /ImageC /Text] >> endobj xref 0 10 0000000000 65535 f 0000000015 00000 n 0000000145 00000 n 0000031355 00000 n 0000031376 00000 n 0000031399 00000 n 0000031829 00000 n 0000031698 00000 n 0000031593 00000 n 0000031756 00000 n trailer << /Root 9 0 R /Info 1 0 R /ID [ ] /Size 10 >> startxref 31910 %%EOF blis-0.9.0/docs/graphs/large/l3_perf_tx2_jc4ic7_nt28.png000066400000000000000000002706341422157504600226540ustar00rootroot00000000000000‰PNG  IHDR¬öEYa )iCCPiccxÚ•‘gP”‡†Ï÷}Û m—¥ÃÒ›T) HYz•^E–ÞY–"bCÄDiŠ AF¥H¬ˆb!((`A³HPb0Ѝ Ü¹3qîüÈóë™wÞ9çÌŠ*’*àû¹Ø³CBÃØð ‘¼Ìt®'ü#Æx ÿJtL&V Ÿ—Î ¹ •#H Ç€•”.@Γ€ÜfÜ_>̨¿|˜ü?@¢Å}ãQßø÷¨pù‚„ؘ\¶Z¬ '’ÃÎôs±g»98°}øi± É1ßü¯Êÿ€ &Wà–¾…Ÿ/`ÿßPcC##øûï|„5ø¿ÿ€oziœEìÀßYT5@÷é'gjÇD ºîñ²øÙe8‡ÏÁá+ñÍøNü ü(~ÿ@ °šs‚+!”HØJ(%%t®† S„E"‘(CÔ%Z½‰‘D±ˆXMK)Hq¥b¤öIµKH-IËIÛIÇHKwHJ–aË8É$É”é–y&‹“Õ‘õ•Í‘=&{Cv^Ž)g%Ç“+–;+÷D•ב÷“ß*B~P~QAQÁE!]¡ZáºÂ¼"KÑN1Q±Bñ²âœCÉF)A©BéŠÒ+¶$›ËNfW±ûÙ ÊòÊ®ÊYÊ ÊCÊË*š****ÏT)ªÕXÕ Õ>Õ5%5/µ|µ6µ'êduŽz¼úõõ% M`½Ý³šÒšnšyšmšZt-[­ ­F­‡ÚmŽv’öQíû:¨Ž©N¼N­Î=]T×L7A÷¨îðü‹5©k׌ëÑô¸zÙzmz“ú,}Oýýný7ja  ¾š&6>5’0r7*0ê5úÓXǘg\küp-}­óÚk{Ö¾5Ñ5‰19fòÈ”aêeº×´Ïô‹™¹߬ÝlÎ\Í<¼Î|œÃäøpJ9·,ðö;,.Z|²4³XžµüÃJÏ*ɪÕjv溘uM리U¬#­¬…6l››ã6B[eÛHÛFÛvªvÑvÍv3\mn"÷4÷½¡=ß¾Ó~ÉÁÒa›ÃUGÌÑűØqÈIÂ)ЩÆé¹³Šsœs›ó‚‹©ËV—«®xW׃®ãn n<··ws÷mîý4ž:ž|Ï^/ÔËÝë×Äzõõ©ë»½ÁÛÍû÷3MŸ ŸŸ} ¾>¾µ¾/ýŒüòýüþ›ý[ý?Ø”< Ô Ì ì  j Z v .†„l ¹*šÚF k[Üà´áð†épÓð¢ð±šs7ÞÞ$»)yӥ͢›#7Ÿ‹ÀGG´F¬DzG6F.F¹EÕE-ðxGx¯£í¢+¢çb¬cÊcfb­cËcgã¬ãÅÍÅÛÆWÆÏ'8$Ô$¼MtM¬O\JòN:™´šœÜ‘BJ‰H¹*‘š”ÚŸ¦˜–›6œ®›^”.̰Ì8œ±À÷à7g"™3{LAº`0K+kOÖd¶MvmöÇœ œs¹â¹©¹ƒ[t¶ìÛ2“çœ÷ÃVÜVÞÖ¾|åü]ù“Û¸Û¶#Û£¶÷íPÝQ¸cz§ËÎS»(»’výR`XP^ð~wðîÞB…Â…S{\ö´‰ñ‹Æ÷Zí­ÿ÷]ÂwCûÖî«Þ÷µ8ºøN‰aIeÉJ)¯ôÎ÷FßW}¿º?vÿP™YÙ±„©ÆÚuÈëPW»¢¸âýá͇oWšTÖ¡É:"¬ò¬ê©V«>P½R_3Zk_ÛQ'_·¯néhôÑ‘cvÇÚëêKê?O8þ¨Á¥¡«Q£±òáDö‰—MAM?p~hi–m.iþr2õ¤ð”ß©þó––VùÖ²6´-«mîtøéû?:þØÓ®×ÞÐÁê(9g²Î¼ú)â§±³gûÎqεŸW?_×Éè,îBº¶t-tÇw {B{†/¸_èëµêíüYÿç“•/Ö^’¼Tv™r¹ðòꕼ+‹WÓ¯Î_‹»6Õ·¹ïéõëû}û‡nxܸuÓùæõîÀ•[Ö·.Þ¶¼}áçN÷]³»]ƒ¦ƒ¿˜þÒ9d6ÔuÏü^Ï}‹û½Ãë†/ØŽ\{àøàæC·‡wG׎=>Š~4û8ùñÛ'ÙO–ŸîœÀO?{Vù\þyã¯Ú¿vÍ„—&'_ø¿x:Å›zý[æo+Ó…/é/+g”fZfg/Î9ÏݵáÕôëô×ËóE¿‹ÿ^÷FëÍù?ìþ\Y˜~Ë»úgé;™w'ß›¼ï[ôY|þ!åÃòRñG™§>q> |þ<³œ³B\©ú¢ý¥÷«Ç׉ՔÕÕÿB,¾;E^ cHRMz&€„ú€èu0ê`:˜pœºQ<bKGDÿÿÿ ½§“ oFFss0ˆÚÿR pHYsNNÆÊ/¥tIMEã$:.$¶­ vpAg’Zó!%Õ€IDATxÚìý{œãv}ï¿6r#´„Ä..1—–FÃP ¤• 4§K:E†Ó,Íöò³Ë´CáœùÛ|KiÛZ´ßÃ9Xj•–Ù²=åŒ`JÂí«Í¡-ÙŽw/—!Yo$ó!Þd“Á¿?4oY²å»=’=ïçã1]K²,ÙïÏGï÷ç}ÛS¯×ë`†a†a†a˜„qVÜÀ0 Ã0 Ã0 Ã0Q°ÁÊ0 Ã0 Ã0 Ã$6X†a†a†a˜DÂ+Ã0 ÃL0Bض÷e0 Ã0ÌX`ƒ•a†a&ÇqÉdâ¾ fcš&\×û2fG`yßyØ`e†a†aƲ,Và™]ËûÎó˜·¿ýíoû"v;BÜtÓMøØÇ>ÇqðÜç>çwž¿ß4MpH’˲ ( À¶m˜¦ Û¶!I.¿ürÿ}…BŠ¢øçBà¹Ï}®>ÇqðÒ—¾tàã¦W:Éx»}¦iBY–ýóX–…Ï|æ3P…å›™Æ%ûªªÂ0 <üðÀ|à Ç¹ò'ÒòL`˜aè$¯ûØÇððÃã¼ó΃,Ë-2JÛxÎf&…aä]’¤¶ó>Ëõ`°‡5f„˜õó,Ë …v †áïËf³°, `²Ù¬ž¹¹9˜¦é¿—ö ! „@6›E&“ã8þþB¡0ðñ Ó d¼Û¾fyF^Y¾™fœ²ŸÏç#Wù…Èd2Bø › 3,Ýt•f¢d”çlfRFÞ¿ò•¯t|/Ëõ€Ô™X)—ËõàϰµµUWUµ¾¹¹YßÜܬ¨onnúûeYö÷¨olløûJ¥R]’$ÿ5€z©Tò_+ŠRÏårþk]×몪|<ÃôB'ïGþ766êê[[[õzå›I>ã”}]×[>gkk«E®ft’×z½^WUµ^.—ýýÍ2JÛxÎf&aä½Û{Y®ƒ=¬1C!_ù|Þë-—Ëe–eAUÕPX˜¦i¼P`Y–ýêÁ×´Jˆ§<å)øoÿí¿Å})=ÁówòIÒx½ë®»ðÎw¾ét:îKé ž¿“O’Æì ó÷Ô¬O|âqõÕWcii)îK‹‹‹8räHÜ—12Ö××qüøñDüFt-“ÄùçŸÏòp’4f㾄¾à9<ù$iÌNÚÎówòIÒx]\\œcàù{HÒ˜dþžƒu¡ž«Ó¾}ûâ¾&AL£iüضíÛ(Ú¨®ëú÷*„cÛ¶ÿ¹Qçzàâþ9†a˜!=¾öµ¯Å}9 “(Ø`0„Èf³¾Ò­i€°›Ëå|%–”ÿ¨ó(ŠMÓ I,ËB¡P@©Tò÷;Žƒ|>ߢìÓ癦:ŸmÛÐuÅb–e!›ÍÂqœR-I’¯Ø :¯mÛ¾QJƽ‡¶EÝOù|Š¢@Qß@!#:N£V«ÅýsîJ‚ Éyº®ûÇð嚌W2äHn¢¼œŽãD.Zˆô¬’Ö4Í–Ê?är9ÿÿd0Óø¡{²,Ë—ó(oì8Y\\ܱÏb†™$hÁ’tÒ©èÙÒëÂ8£! Àiše¹\Î×·št¬eYPUu¨è†™Vb5X×××±oß>¤R©Èý•J333m÷ï6„Èd2Èår¾²4ÞEišÈf³þñäቚPmÛÆÜÜœïQ*—Ë!Œa( ˜››ƒ¦i!ã4x|PY^c7‚÷Ðl4¼¦n‹EßhPU5t}ëëë8~üø­Ý)ß–eùpú­„0M–e{¾É€k÷»Gx½}’$ùÇÙ6àº@7qÔ4­/ù åé$EhšÙ2ÎŒZÄJ¸aÙžlhq›:ø ’Žãø†¡mÛ~”MpaðžKQÏÇq`š¦åBÆg0†È777ýg éfEÜ! i666üsìÄ‚#Ë83IÄb°®­­ayyÙ÷pÍÏÏ£X,bffP­V¡ë:*• OA5 #îïj((ÿÍ4M!°ººZ]+ ¾w±Yq''M¾AC°y2ÕuÝ÷Nuƒ¯ºŽãø }.—ëù96jX¶“‹ëº~Ô ‹\ô$YÒ4 ™LƲÚ¡ÍÐ3Ì0 ‹E(Š!òù<„Èår!=ˆÒ>hŒu*I’PLÐ$Ï2ÎL$õæþûﯿ⯨øÃö__ýõõw¼ãþ1o|ãëo}ë[ýý¿ôK¿T¿é¦›:ž÷¶ÛnëzL\lllÔeY®ëº^ßÜÜô_¯®®úÿ/‹mß¿µµU_]]­¯®®Æ}+Søäe\òMïKårÙ—íf¶¶¶êår¹¾µµë5êz½žËî|¥Òh¯MÓêõq|Eã’—Ý8‡3õ¶ã|cc£§÷ommÕ5M«ëº^×u=ô<ÛÜܬ˲\ßØØ¨ommÕs¹\]UUÿdss³^¯G^vÛü=)lmmÕu]÷u¥ LlllÔ‹Åb‹N<¦T*ÕËåò@Ÿ].—늢Ôs¹\W]m”ðüÍL3ƒÈËŽ{X+• jµ333˜ŸŸ÷WrªÕ*Ö××qìØ1ÿÂÂÖÖÖ°´´·}ß7´Òô¨ÀÆÆ2™ ´ìkF’¤C™eZåÛ4M…@¨¸P;ù †åƉSÞBéW>àõ#9_¡È20Š[+½ó9ÎhÎg€¦y×7.¦UÆ™ö7‹ Ñó(ŸÏò,lll„¼¯4WÐ6ª‡ iZ¨¦@¡PðSRÈ‹xé%TÁ²¬P±2×u¡ë:~ú§zä÷ɲ/͕؃…ô(¼¶Š¢Ò4 ù|ÞOo >“zMOŠBUUlllô‰6 °Œ3“ÊŽ¬óóó¡b+pòäI\xá…þÿ NûûÓé4ªÕjœßÓ@´3VO™ßØØˆû“ë’äýMÓ&ßÁ"_T0@¨°WâÙÚ‚tùybx1¢ŸvT&à—¶=šó™æøCŸ§MƧ ×u}#”t £TUuàô˲Ëå ( 2™ $Iò+Ê—J% ¬®®hÔZ PM ',•J‘ X¦iúU僴+RFa™Ÿüä'ñ¢½h¤ßËöÎ,Nç8ŽŸ>|¾PgNȲìWpIX|,ã̤kÑ¥ÅÅEpÐjN§AQ«Õüû$AÅd‚ÜNÆ*Óù¼ç2Jbb&]¾É+ÒK-ÓÅûKå×½…ÿóÛP÷ o:Ž'Ž£X?0þäah¯ù!l{øßÝq¼ï'×v&]Ƨ òL9ŽƒÙÙY T¯Ï#ªÂ,šfÛ¶Ÿ¯W*•ÉdP*•üyŠªiš†l6 ]בËå|i§Ïí×û%IVWWñk¿ök¸ë®»Æö]²lGc†_(Ñqär¹ò3©¦Ð(x×NF&Ý«™TXÆ™I"Vƒõ†n@µZÅÊÊ Ž=Š¥¥¥Ž­FNŸ>Ýv°ÜyçøÔ§>…J¥‚#GŽìØ=‹%QÈ…´°±:ÆP-gmm þð‡qöÙgõÒG)ßp×]waqqªªúá<£†O Å*•J=ɰey?Õ¨Ä=“F¶Xî8¯yüHNE¡À£p.;€õu(Ïù:gx·,ϘÎfÇ=îm8uêÄHî¹Ó0‡O*†a„¼¦Ô«¸]䎪ªÈf³~ñ3Ã0üj©TàˆÚ›ð+¦š¦ZŒUUõz=tîR©„l6뇓:®VNËËËxôÑG±gÏž±}¿“8òl^“$IB`nn®¥Ê{shªÎkY–_MW–åP8Ó`qq'Nœ@¥R y:G ÏßL¾wïÞþÞ8H²ìM7ÝT¿þúëëW]uUý¦›nªøÃ*Ùº\.ׯºê*?—þLÎmÞ6ŠÞ~ÙÜܬððE ¡ ÄEQb/4ÓŠR¯o²Á—4ºª4››õºªŽå–w²@À(ä»^Ñ*V1ˆìªOûf½üGŸÉulnÖë£*·±Q¯ëOûà(¿¦z]Qê[ŸÿöЧÑõz½¤”êõºª_xI–ëõz¹\×_÷íz©´³E^&eO Á2›››õÍÍÍz©TŠ,jÔÌææ¦ÿì ŽWUU»–Y]]­+Š*HŽt]¯+Š* HÅ6{x>ÐûwŠ’—I™¿GA°0Vð9P*•ê²,×KÏöR©TϪڋźªªuUU}}¨ÙdÂðüÍL3år¹ïf}{X———±¶¶†……%fffËËË=­¬DG±ó°oß>^Xõ~ þ?N(‡B(§‡ÐuÝÏó›¸×ÛȲ¼„¼QxEm;™1¦˜dùÎçó(•JÉ®óý§@ýáû¼|èëp]ÏS8 „pÏ=#É…p¿Pƒâ8ÈÞpJnȸ. Ýóq@R¡<ñ8ÎÓ"C–óy@×;–e5‹ý9+a\mü&YÆ“‚eY(—˰,Ë÷ZQÿGêcL¸® Ã0üqiYŠÅ"4Mƒ,ËÈd2¾‡´›7“ÞCí@€F#*VCۋŢߤ—|õaÛvá¥èº}@ôUáËå¼±ðž÷\K/½c¤¿Ën–í`a,òœR‹²¨¼R"—Ë!“Éøm]H¶ƒ-fØ‹šv³Œ3ãƒÆ~°@¥£PšŠeY~ÊÉŸøD¼â¯èë3ú2X)tàÈ‘#¡ªbªª"•JáàÁƒ]Cöïß•••Ðq¶mûƒ!•Ja~~>T‘̶m¿¢nœ?†ã8~O;Å`b ÑÉåFWõe”M%]wt•mà)<ù¼§ìœ:5ze˜\ù¦B-ƒ†ï)Ï~Î=)ŒB-•(ÞyÔ—~ 0ïÆœ¥ccsðsÙ6àüý)(¹´§>yy PÒg! Þý Èòµ=¶Û´âUõ„|ŒLªŒ' ·§Þ‘Á~£”Tð©÷5m <£ÐÛl6Ûs¿(ã!8öÇûËå¼U£^Ÿiù¼÷>IVWû_Êf U²ìª†±]à,]…]I…òÇçwîÂñãßéo³[e;ªæ†®ë~õæn‹˜º®#ŸÏC’¤–~Ûl¬&‹Ý*ãLwÇñ/…¡…MZL n#èØ`ŠŠŽãÀ4M?õ„ŠʲŒõõu?~¼¯ëëË`¥äìùùù–}ététºcü;½waaÄüü?Ü ò(Ëwn*Ùùd¹QþtX¨ò˨Υëž6N×9(BÀ\: yïPù NìŸÅƒÞ?šë 0‰òM…Q†ªZýØÇ"û¡,6W†¿!˜&l97¼áJ´¢@”êCž PÏýw@U‘Ó.úå'lùš¹z2 ´1X½éÛ°yUEáõwàû>eèûbeÏÝ v)»AÆ' ªU@UÙiÞ§jð²,Ã4M¿+ ¯Aý-襎%QÆå¤öî»èÒ‘#GP(pðàAÀúú:VVVN§aŒÂK—òù¼Ÿ0Ü©?XOl÷i£*4þŠÒ>œ×²<…¢Û ªm7-Ûö”pIÊŸ9ßSÞ•gùno®‡Ã¥•wAªí‡úË¢Tº Blç:<¨_9ñ¤E(4°UOü—žýìÑþ.„a-¹Fƒ"Ã…¼÷ó°/z„øÙ¡Î%`ýe ¹œŠÜo>:ôµ×a¤ïžˆ\3RU@yÇ/Ãuÿ±í°²mÀzïP jô> à1¡ãÅ30³Y„ŒOº·Ð×í8 ·”¢ w†×ûÇø…”²Yȹ$ImVв=,­Àb‘$A~öÙxð¶>KÆ3] ¶öhBoFh5›¶ Øt‚ VÇê÷H¤ßq¼Ð²2#ö2è_5¹ÿÚˆé%7—óÇ“ªn/îØ6ßÖ…âŽöº)RÁkY_û÷2¸®jOÃÆ*ÃŒæðYr„Ñ6Ê uº®£^¯ûŠ„m‹õ¨Crã¦oƒuffGŽA¥R U g¯¨Æu]!†®zBÓFç”åÑ•Q5MÏ`-Û‡Yõj°*JãÙ,Ð&ïÊ0¼Ë—eïã)Z:—óNQ*EØã²Üªñ P¤ ¨iÀз–¹Oôõɱ‘{ÿ/†~‹ r¹]k°š¦é¯Ø÷3wCzîKoÛÖQ/Do}Zp¿óàpއ.â%}vT ‡mC|úK(äVËÑcÀ¶å•9¾D(xl{?TþB ɵª6^ÓýÏÍyC¢Pðî³\yQUhf¯÷7Y°Y²ýjaÚÒ—açûcƒ¢ ü l:ßß>ðŸöçeá xã¨9 ’¯‚ƪªª~Ê^ Ö|>ï‡ïDN m794 OK¥ÎÏ,YöѶ=Cðä°Ý³Âu½ýtÎ\Îû,IjJÄfÆyUK¥ÒÄzY&‰PšUÐÁåº.²Ùlh¬I’äç{Ó1®ë†Ž!g¦/ƒu}}‹‹‹¸õÖ[§Ê@mƲ¬Ñ¯LŒRé(—‡?Aƒ¢“ñB«C-.¢&‚ILmÎgšá®7d¨¿¦È 0 j×mhY”ßåÕÍf‘ûC ¸æ¡k»àÄ œ³K«Þ™¦‰ÕÕÕÑïã)¨HAù…'Âùü<¡å×õôÒn¢+Ë€zþgÅ@!3XµQ¢Y\åKÏÀ)oņçÑuãÆ‹QRe8í‹2YVSø¯¢@zø¤o çó­žÏ Á¬¹F¥Ð¢“$®ë¶ªº-ê†á÷ùȸögåèõªfÙ×4\üw7ÜË„ ’üår®ë"“É´¬¤°4C-b´Í_ ¢ª* …BÏ!!«iFÔKS¨÷Ø¿§\nÛA´ÄªÉNèxË´Ý C~«¢@®oç^°]ò]UýF¬”Ï*IhT± ö |‘ÿëê«ÁŒÛ¶Q(|c“rRMªØø…0¢ŠÏȲÜWj‰¢(ÑÞX×mHÔ¯knÎÛç8í³MÓ ÃÍfÛ†s¬qÕÏ#Ô£IQ:GÜ´C’F—ªÂŒœfïÃ0ƒaš& …BèouuÅbÑOáÈd2X]]º°Ü8é»JðÒÒ–——QmS´†ú6M*†5òMk´£I Ý<¦@#·¨ €¦ ¸_úUèé; Q”ƒÈþÜ£(ýð¿@zígZCÍHù|oS‹Ç6h½D(è-´-ýúà•WâÜ/y‡¿ðø¡ü:*è3 g}î™·n'‚vù¥J¡†…‡QUØ…hTíDË{©i?’V–¡<öƒ°?öóPÕs›¾³èÏRžuÆm?p¶'Ê> Ë€e¡¸ý&¿+Óo¼¢µGmO“„m±ÍÿMû0IŠ¥§±Éá}c¼lÛÆêêjè¹ ëºïeu]·ëB§®ëmÛ 4£i\× ‡;N£òVP.(•R0\× Ï ¦dضgÔªª'Ì® ÷]7#û‰· üwËÜŠdʱm¶mïH>4ÃL+äIUU54׋I’„b±8Ú”BÀ9¬‡¬¬¬DîŸtƒu,UÉÐêäb*åmwŠ^ #‘k)B¡i÷vEP¹Ò=ŸàéIö†öÓ߀ú÷oo¸Zƒß3UZ"«¦YñSUï;ê•.öÖÏÿ<¾rá…¸fç¾íØ¡Ül¯øËÎ~v&Ó›ÁJÔ×·ˆÙi™Lg£UyÆýPfÿÀvÿ8UE>ï;+„eX}Õc‘ÿ—ûœú,Ud+x½ô¢gC¹£ àiÞ†`A˜¹9ˆÛèiž~å— TïÃææ<ã´ÓØ#OY»ðÑ…p˜Ñ „@&“ªª‘Š>yMgggCýëÚ!IRφ¡$I(ÏE^Ô¨œÒf¡˜ñ`5]Ijô—àÙ*Je@VÙ+:ÍØ¶l6‹ò(S‰faÛ6 À$ICAb†£oƒÕGK• Xô¤¶m~b'Å´Ó‡Û¶§TôR•†b%©¿KÁ¤¹vP3<"Ÿ‡=›‡úÖ«ÛÚ LZÄ—Ÿú(´G?å¿_ÛnVäK¬'+%Õ„ÕÈU’eÏ@%ë…òQ»ý8¼b5ÁÜlúÚGÁÜß¼ê7xцQ?£ûÕ‡ UK°¥7w­áBHw} â¼_îùœËâö;0÷7{[ö…ÎußÏ=/´Zlär­5Ðä·¾î+•ueÐõ.à7ÌÈü»"þ @„\ærpÿçGaœY‚ë«O6·lWS”F¿šN_+˜±B9IŒÐ±­¤S…^Š·¬þ<é~¢ô6çŠi6Ä£C§›B¡àë4 Ì0½C•|©b{såwfçé+‡u’ *©AE=ø˲ÆS•±—óQ7õnd³á÷DQ(xÊN·ð3!B ùW¢pä)˜›ëÞ›²PðöËW¿â‚}~åßÐ=ÓýPéß A% Ëtƒ'‹¡æÄrPÌ<ÕÿmäŸ|+ò˜Í·ò]Ÿî(’¶½ÝŸqåeçÃýÆ#•.ú Ôsþ­£œšOµŒ½b±awÚ6 œù·ÆNY†þÿží‹-U5–ÿ×;ÂùÒãÛÞ¦AùÊQH[¸òw?×°¨÷M78L36¨Q»WåZEñŠ‹EÊ~<êm¥MÓûÛØ`cuÚ™››àµ_bcuL8Ük';ª ã8fgga\×E±XD¹\fc5 d°®­­aqqÑ/½¼¸¸ˆµµµ¸ï¥#šÖ°‰¶[ÁqËþРHÛ½.÷×à:Á-„gh’î =ûK‘mŽèKš é^Ør[,"œE§0v*çKY™DB¹ª”ë777‡b±8•…ˆ†iÅL…íZl¬Žûÿ;”?þO°Þur$96îµK+7Ç}[»Z¨4 …B¦irDB‚é+‡µZ­bee%ÔåG¡ˆÌÙÿ ÷ƒÇŸkÛ ½SõZEŒÈçe§éä¬L8 ÞûÁ¡O÷ãà‹_ô_KO¹¸çžð1. ¿ágxbÕN'×ê“-;å¾äçak‹a…AQ°ú¸ƒÉM²!Ù`ÛÈI¤7ßýA”¸µÅ½Ë) (µk4(¾e¬Z–ÁbÛž‘:;ë ÆÕÕ‘[•l¬î.LÓ„ªªÜrcœ[kØ{ÞCpo¿?ú* (¾´M% ÐÞÿ‹@>LÆ«ÿáét+¨¹ÝñÁ|æ_@Óã’ÿæ|3î¯d*¡~ÄÔ?›ÕÉ¢/ƒu~~©T …B!dœV«U?u~~>î{ ÑË‚Mô„¢úëî€õõŸþ‚ÕŽ¥uârÝíê.=ະÉwž’;XURú`õºÿå§è¹. Ýp>ä×ï÷ÞkP–b‘õ]D°:0‘ÿ•{¡žýé¡Å wmÅ×|Î-]ü8ß ·šiŽbo^“¡¶¼~ƒÕàùîõdù…w@¹öÒV¹ÝŽ"ÐÅ þ[£/Ë7ÓÃ0 (Êh«? h [  iž!K5ÊeoñdÄòZ(p˜Ý†eYñUµžl("K“˜¿óEhOß@ö7ߺ–O=±›ŒÛnz\)  ë(¯ ‹ÛµB‚ÅC …hGÁvEpë£çz‘rð3°~iÜßÖTaÛ6fggýy]×§×X¥–—Í ½Û½~ÎÓwVÃ0 ë:8ÚžJ¥päÈ‘¿n4·¶í–UvmåZÌ=ò ½8-DcV“¤Ö «SÎj3²Ö…¶ +mß”R «7xóãÆPüç!¾QáÌÔÓ âþ³ ~ˆaSµ›äY¹´ |¦ÀëgÚœv ÓDá³P\¹Ôßd€òµè^¥r. Þ hMÃìËSØ<øÇ …‚U¦ Žãø6†Æu ‘Á(–vÈro•ãĶÕ€™ÝmÛ$‰½«Qá·†0S‚BÆ{Tø‘® é(ò(-û|¶‹|äóÞ#*èUmÑ-·ŸAªºý‘nÞ;ÙvMÌÍE6@F*×Ì`õ`q1î/n:B ŸÏcuuuú‹)Ùv£ J0b“BÚÉö{0 Ož77wTßê;$8Nã–[nÁ‘#Gü*ÁGŽÁ-·Ü‚t:½cÞ+M­F[ˆò>AHs³Pf¾9|*A³Ú‡Áêº^ÄX>˜ÿã Ìýï @½ùŜœ¡ÞoY«ù2SK”± òß…óø«aþáC¿ðß/ó˜ý ª çä“ý—®Û*vÖÍ ½Îå€Ü½Ö¶¯ ·ýÊS.ýmçx¡ÉãhIÅL¤À”J¥ÑäúQˆ€a´ö›ÞaÇ{^ôR ™ Ø^Ñ0áy7eyæ¿¥±±ÑÐ݆¢é-°’ë;¢ p]˜®ê§¦Q­¹ƒÈgÝ÷âýçV±è)gÏcËâBòã"ŸÏ#—ËícµPðD4-bCÝ8ÊåP§„ n ýÑÊa­V«˜™™ÁÒÒ–––ümI¤›Œ:ŽÓª´8Žgü]øHÏz_4¨Í«ÍhO)m"—Ü{·˜yjôgt›íl›‹ÈìRlÛŽž¨z¸öZˆÎêüÎ=)(×B€UÊKÏó_ær@ÑÉ4ö+ äsª~ïc?ac£ýäGáìmÈåùË7³†ÎôU¹ï+XonÎdZ÷©jCRDã¢_ÇÓEŠE.P½›°·õ…‘†¶OB@üܯ@\ŠE¨ª÷˜‘eO¯*¼ê @¡ësûB‹¥Ràq#ÄþLÓÛ®iÈÞnÎ åÞ‚=cÛý†Ñh1¨ª­ë­ÿ÷÷78ñ˜¦ !DòCåGªKÏ!Eñ–ÕRÊ#¤”©AŒÖlÖû7Ÿo´ÎDçäá¶MßëÚÚ8€ååeÛÑ£GqàÀ¬­­ |!ã¢[Á !D´B/IÐ9ÖèYŠFñǾŒØfÕ/C8ióç»®×sÒn©)Û: ¶+Îtð.qNß®ÅqœEƶéì \Z…{gßY!ʯ{_˶“©9&XQ ìùs9@zú`öS~#ò–¸¹"ÄS_MkºŠâ›Ýôýœ“‡ò²ó›/ˇê`Ñcög~æSq‹I>ŸÇÞ½{‘Édü\÷£(:4 u=úœý­~…Wx`v¶s†nØ6°w/Ïã±§O÷ýö¾ ÖZ­†ååe? ˜8rä–––pøðáÄzZÛ2¹½ ßùCy@”Ã`šÞoÝu¡ j N–oŒêɪª€ëBˆ£Ë„è/–ÙU´ ~¤é9—&žá¶£BçÞ~i@æÏhÙ¯œ_m7V¬»Â83–eA4MÒU.Ú꘼ø…Bc¬Q7œzÝûÛÜl8pi(Ðâ)°”Ë݅뺰m{w{W£Ò¬Úñ?Àæ÷gÚ>>Š|ä#¿ý¦öÝ ²ÙÆÐ¶«oŸ¯ÛWN-¶ÃÎŽb±³Cå9Ïù÷˜¿ØÉÃØ6ж¶¶P.—'£Å“$y®ÓloTFÃÃI„âÚ#ÈåÚ‡ÑÚÉûFap¤¿‹Þ9‡Y3 ïA&ËxÞ¡CxÆí·÷õö¾ ÖJ¥‚Z­æ‡9tèR©”ß«5)DEpq]·mHp3ž[.ê3¿ƒ9y«³'ßu[5ˆ`¯½(CSQÇ" ¨v!œ45›g˜&Ú«’È—=äÉâÞ½mßßKÄGá[¿ÕÖ{ŸË¹§}ªEÆ5U`#gBq‡·g˜ö†là!oš&Eé/—É4ᯮŒJ5 m é]:EÝPà$±±º1Msº½«ŽƒÂ‹?¹9´„ˆ[¿ói†lF`nÎÓõöîæò^Û2ééOèzzõÏl|¦ií‡}±ØÛÚU°I„i§ë3¡Bz}GÏÄ MÞÍy§Ah±”ƀ붷 Ò©ò=D‚l/öð¶Ù¶ˆZ´¥‚NÝ0MOWTU@×ñ••Üõìg÷õU ”ÃÚŽÓ¸xãDѾªÞöv! Áß.÷è{±9û þ*-Ft%hD´ñ€$Áø|îËy¯»)J.É´¡]þª¢¹ÔÇY†óíhƒÕu-óÈRg¡v.yuÄF°mH® ùÕ²ÜÛdË0C"Ë2òù<„0 £e†V„Gµ]µ¬Æs›†gT»§n( gzìv¢zlO¦ ëÛsP ðéW7ž†Ì« ÷E¿ŠâªŒ o˜nm¶°‹@”ÚEúánv„“`%àÄ{TÛÑœwµŸÜôÙìø*ëQheõf[!ÝÍ¢¢<ÛüøÂ ñÈùç£úJ`£>¬‡ÆÒÒff¼b+* q•‚;éíã}€üB ¡s6êP ïµ*»°]:' ýû)È$È\Af×’oG’”ùQV,ev†$Ë6á8r1»í„ðêHÎg°ñ{UHê áTÆë>]÷”ÛnŸn]÷÷PåC’¼çN±È‘fãdd¼TplG±¬†±J y £wƒÕ²¦Ë£·µQU7Þx#Ž;†……T*|ø0R©”¿¿R©øUˆûe ƒ5ؽ™æîÏÍ4“ŒÖ íÆ=«ÓÁNÊw;„m=LFé …E iBúEåO¬ò³ §ì%ù[àüäg‰ôl°îJ’ ãípg¸•wÛ:Ž—”sfòH²l”Ã'†(GI6 ½ù†Ècì'_÷‚axj•ãÀss!=ÊüÔÓûËCïe]h|L‚Œw²¬_°QÕ†±J¯û¹†\Ž“™‡¤/ƒu}}½åõáÇaÛ6öïßcÇŽumk³¾¾ŽZ­†¥¥%ÀÌÌ :„jµŠJ¥‚jµŠõõu:tÈß¿°°0òjx¶mGOøÍI¤ÍZG“5D±¹O’¼]ôqÅb´2Ó\0Œ™<’"ßP÷~Þ_tîIÁüx#ÜG.r¯ù“²üÔG¡<éNïXP޽%‰™¤Ëx°àÒ@XÖP 1äybƒuòHºl]úÇï´ÖYTmèßYìâ¨å$Ì}ð÷ẞ®_,PU8o»Ù[Êçá¾ûÀÞ½P®I^”idd¼±xWèîý^/ðEOk¥RÁ°¸¸èo³m‹‹‹X__G¹\Æââ"ÖÖÖºž+N·´¿9yò$o`Ðÿƒ†o:öCú¡“ÂÐqÒn2XƒBÚ­²Sš-·l°N>;)ßíèä]m9öáóàV•€¿ùB8Ä%—Cñ÷ïÀŒGd¼C…»nëß'™Lx’™’.Û@¼!ï³OªÁúÀÞ²’Ïwm‘{óùXýÐY-‡YŸMaÖõ¼UÒÒAè¿ñýXîg72 2Þ‰X¼«ý@Ï®¶7rz2Xu]G:ƱcÇüm”»zìØ1ÜrË-XZZê)d`ffóóóþëjµŠååe,,, •JuµZ­í¾3gÎàÔ©S!/p©Ô>¼¼çUø Ö¥±;Î@‚ÌëÎP­VqâÄ Üwß}#?÷¸ä|ðA¬¯¯w}ptRh\ÀéÓþkégžçë÷_gßýò°².ËÞŠ8ËæD±¾¾Žûï¿,çÞÉ9|†*¸4dŠ|Þ{æpªÒx©T*8qâNæ²Q„ù»m£ÃÆ„i6Öí7Å>×k_±ºÚÓC!JÍ*ÍMï?ÒÖ&Ô?}y×óì&hþî&Sƒôù; Ó4‘Ïç1;;;¾vN¦ÙZ³¦Sú_Ôû3ï!@íkòùÑ_ç@:x¿ówWƒ•&Øo¼Ñ_q©Õj¨T*¡v6 ¨Õj= k­VÃòò28€ùùyÜxãþövtº¹3gÎàî»ïÆñãÇ{ú|·WÔ¶ÃKÁ ¨QZ»¢´ yXV«ó6Øg—'Ož›ÁJŒZ¾Oá9~ü¸¿ÚÑ!´Àu%Õ¨ Ü,ÎÚYnÙh޼˲99?~|,ÊN¸çð(Fâ]Ý^½w/ïÎ0Zƒhšu×õŽ‚‹fïã2X‰8çïnôT0²O‚FiÒ½}r9/¶·\Ý &‡I¶@ó÷¸äHæü…†a —Ëass¥AÛht‹„to!†&vÓl_p&ŠàØ(¡òù|†ï.€t𑬕Jóóó¡ð{{ z(ûéÃZ©T°¸¸ˆJ¥‚cÇŽù±ô:æÀv*­}ñÅCQ”йڵIêZ° 8ÿe°J’7úô²ªjk‹2^•ßæççqÝu×áYÏzÖXÎ?ù€K.¹KKK¡ÕÑ(úVÚzÈû×uQœûPËnªË¤>òñ±|_ÌèYZZÂW\1¶óïÔÞ/=\ŠRD¶½«BxÏŽl¶1Ý ÀìlãPIj¨@Cáç–d;î»î:\~ùå#?wÜów7ÆLÃ!h´ þõËXUŒ°M)˼z9fhþW;™¤ÎßQX–MÓ†—yÃ謧—Jž‘™Í6ŒÕaóvé0€Skš!¼ßù»«Á:33Ó²âB}Xû1RƒPˆñ‘#GZǾ}û –P­V¸í5^¡l×sI–û[‰A«cÖ¶Y¦§…’ïN´ ‰Tø4rÏù÷ÆU…óÃçœï\©ª@ñ÷ï…rûûbù>™ä‘Âqœö©B4´\†á+à=,¶½«´¸¹é-"꺧Çln6N¥iÞ6fÅ¢÷Ç΢É'©²MŒ:Ò1l(û²74^òeÞP1ÿ²†Ò“߯•M§¤ËxÇqFSdI×»ëéŠâMì…Bx‚†R‰ÃnFDWƒ5N£R©øíjjµlÛnY%¤P`övضjµ UU±¾¾ú¼œùùùP'Û¶‘Édú¾¹v«Ýs@§³FíS”Þ{1m£iaƒº]H3Yì¤|·£Ó ¼ôøA~þ¡mthö·f¢åØ4‘ûÂ"¤=;æo—IIñN×Öb° á¹G³YÏ(•e Tò‹›&¼y[©Ð4Ö/v+I–mú¬Q¬Ö…º0M䇿Ø6òúï†ô»#÷ÅìI—ñ¨ëIDÁv=Ž®ÑŠlmqÑŽòØn¤ÓiÌÏÏcqq ~IlR jµŽ?ŽÃ‡c~~¾ë* ¾ÁŠÃ„³íb\ZZò+×j5ÌÌÌà†n@¿t*¸ÔqŦ ¶³€l¡ Ë:Nª:ði˜±“òÝŽNU‚í^ùÕÏFPå¡6Kmõ YöVW:´/`vIñ(,ËŠö®FdL3º¯oÇàæ˜uªöÕ¦Ç*€-MEiÔøHr•n¦wvR¾Á¾íñPÕLJ VEñìѶ Ф ñŠ#ƒäÊxd8°ãx“ìÆFËñ¤§hZ#•E|w“TÙ&º.¶w}#ÚÜwòÅO‡$m;ÊâW°úÓ°±:¥$]ƃDFÌô‹i6tòÍÍù‘6ÌäГÁJFj ~9ìQÒ\z»_ÇSÂGbŽ)V—<[ÌîcXùnG·¬Q=€í÷~öžÙ~Ý…&y.´ÁôÁ¸d¼–eµ.šÒbcÁÅLš‡;F0L€–mÂqœÁ«¤ÂÁEëC}ÅCÇHoÞyO“<â’ñ ÃÊ;O胎¨bqè^ÛL<ôd°^Ž*•«Þ¿¿/Èq%bw£Ýjyß!5ŠÒwA¥~àELf”t« µË¾ék0O<Åß à5Ño¶ZÃŒ‘¶rî%Dkô$ñ\ÌL?¶í ÷ŸóO÷B»û&HÿçÿÆ}Y ÓÂHÂß©•Mpr—$6V'”ž Öååe¬¬¬ø¯WVVpèС‘—¯Þ ú’ÔX~g†I8¢‹ËÞ²ZçêÜÕ_‡uÂ…ôòçÇ}ù 3ýä:q¯TfEñêÌ'ö>…7>‚òÁ_dµ†I$#É_m×Ùƒ™HºV <uaaŽãÀq,,,`eeeìéÇëºÛD5vœ¾û¬2Ltó°n¸;r{nï‡8’™X¨W_/P„;ÃLìŽ(óÚÖHOÊ_z2¤?kÜ·Å0-ض Û¶ÏמõÚ—™&{S§ˆ®+•º>tè¿<«”DÚõ4íèamg˜* Wã`&†v9¬BÒÙ´l—Ÿ^‡þÚÍn§e˜DB‹4R®"ªmÀ0“FÇÃ=`¯nAÝóÏþkYæ 1&y¸®‹|>R©ÔÓœÉæ¦—󡪬»O=yXp®êÌÌLÜ×Ý!¢WÑ]×í?.žŸaN§ÛÔ³þ¥uGDˆ™"e~n®¥¢ëz­X9€™DBºK¡àýõ±ú"¾x'Ô—ÿ0îÛ`˜¶!ÍfQ*•†ï½ª(œû1eôl°NQEM…Ulj^räž3Ì„ÐIÆß%}¦u‡$±ÏL,-id¨ær!w•™Jv•ÁÚµà’ã°'•™h:]²>~>´—7îKd˜‘Ò¢Ì[VË–(¡wÜõç~÷m0Lï˜ft¨d;¸…ÍÔÓÕ`M¥RÙo5JAqz»â2¶ÍZ 3ñ´«ª'A@}îÝ}ža’MËŠ¼m·´1PNÑf&—–È™ Á*ËT&Û†ûãƒØXõ†ålçr^þ*þûW™äÒÒ¶É4½È^ B6EÖ0ÓÇÔæ°Fk  Âù«Ì„cÛv[ù6ßû(OæÌÔaÛvX™È_íg‘ža’F‹"O!Á@#U¸·}¹7Ÿïo¦ÎÚ·M`˜„ТŸ ѽ ¶^‚ˆÈfúè9‡•X__ÇñãÇý×û÷ïÇüü|Ü÷Ñ{:qùHf ˆÊÿ°mÀùÎÅÀ²ÂÂL!ï“ë¶,<Ú¶§Û³ÁÊL*m+JÁB@þW·Oß[]û6¦#¡‚KÞÛ\TÌ0¼iñ]’¼ˆšÙÙ–ÈfúèÙ`µm7ÝtªÕjhûÊÊ R© ÃHT^k&ÓšÃÚÑ`ec•™RhNg˜iÃqœFnŸ$µLú¦ÉÌdÓ’ÊÔ,КÈ2Uk1̤’sJÑ àMèám¹œ7÷wÒ §àõõu躎}ûöÁ0 8Žãÿ†}ûöáàÁƒX__û~Úâ8Ngƒ•a&œvE—…£Á˜]@D?aUåµHf²i •Ìå¼65b»HðvþS6÷•2Ìà„ä\ˆÖ‰›ŒØ(=^ÓXÉÙôäa=|ø0TU…AîøªªBUU躎Çã–[n‰ûžÕвSˆ™še\ˆÈ:4 3ñtmSîpÀL6-áÀð¢"]· \*y¯YÖ™I¥¥Ú{³gðòYY‘ÙÕtõ°®¯¯£Z­âMozSÇã:„jµŠJ¥÷=ÁqZaD”|ÃL8®ë¶l³mÀù›/xÿa˜)¢“Áê8^k3†™d¢d\Ï©šËyÓ:Õ`âÐwfRéÚ•Š*±Áº«éj°V*¤R)¤R©ŽÇQþj­V‹ûž´ÙˆZ©ÜÞÑHäf˜ &Jyw@9õQ®:ÃL~‘*¶ïŸLÆ3V9BŒ™tB…h¶) òºî©/¼ÉL2-ÕÞƒ¸.Oè € Ö™™œ>}:îë ‘9¬Ü•™blPOÿ#¬ÌÔá{ŸLpÑè=Y.³~ÃL>Á–6Öʃ°^ò®Ð~ò²r43Étô°Ê²Ì1ﻞ®k:F­Vk©Ü \𙙉ûž"‰ —ÀýW™© ª¨˜j5H¿ð¸/aFŽŸ÷´Ûd\{ƒ™>h^7òÜÞ–ýÅ"GJ2“MÈ`5ÍÖ¶¶xÑéÍ`M§ÓÐu½m¸o­VÃòò2æççÑÚFUýÂy>Bˆ–Ðê 3ÁD³m@}âí,ßÌÔáË»išÛ‘`Û­ó>ÃL*AïªëâÔCPÞü²–ã4óW™)"Ê`eôØÖæÆoDµZÅÁƒ±¶¶æ{[«Õ*ÖÖÖpðàAT«U,--Å}?m‰,ºÄáÀÌã8€ò½O²Ë‰™:üš¦ ärP`u5î«b˜Ñ,¸d¾óÈ=‰S;˜éÃ4͆wÕqXÆ™¶ôÔÖ&NãÈ‘#X^^ÆáÇ[öÏÏÏcii)ÞÕv°ÁÊL3QE ”+„:sÙíÄLŽã }æŒß{U÷g¦ ×u¡mÇúZ°±tAÜ—Ä0#Åq†r¹LØ`eÚÒ“Á 4ŒVj]S©TüpáT*…Z­†õõuÌÏÏÇ}O‘DV sNäf¦†f×.øðÊýq_ÃŒ!n7Ÿ¤’HÀLŽã T*Á4õ¬ô{¿÷%1ÌÈpÙl««« ÝŶ9¾iKO!ÁAR©TUÅÒÒTUõÛÝT*,..Æ}?‘8íú¬R3†™pš#°¿=ËZ<3•8ŽƒË¾úU@Ó¸n^Žã “É„þ ÛedÇñÿßL&“ñÿoYæææ°gÏÌÎÎÂä¼²%8Ÿ;ÿt/r/8Î!ÌTAƪL½V9ê‘iCÏÖIF]2›“ž˜)¡¹,¼W1õ*€yf 9¿RÁYðZØ0 ÈØ¡0;×u‘Éd i„mpíífž®ë"ŸÏccc²,C¹¹9(ŠÒ¾õ3RÇñ‹D–žù—¼°ÎLTƒ 4ŸlW{g˜vôía5Ô'ŠJ¥ÒµN/D毼’ÃŒo"ØÖFUyîgv†”qÀ›ÏϤÓ\¸GdYö Ï^ vA¦'IJ¥RÏïŸ&vZ¶ ªIàºàÉœ+qȸߒ,Èv=†iG¬ÖjµŠÅÅÅ–ßjµ ]×Q©TªªÂ0Œ?'XmavŠ’oÀ“q!¼MãyŸÙvRÆ ¿B0<G–9$¸×u[BUUõ½¨ ÏÞìì,4MƒªªÑ-ᦜ8d›Bà’KžlØØØ}ß=³3Ä%ã‘:ùv=†iG,+nZYY‰Üøða¤R);v µZ ÄòòòPmsØ`evŠ8ä[Q˜¦—‹ñ̸‰CÆ Çqüh‚¤Ôèh—ºSôbTöb¬p–e¡P(Àu]”Ëå]§l®ëâñ¿šçrf,Ä-ãQ}ã9·ƒéFWƒµR©`yy¹ë‰jµZϺ¾¾ÞöáY­V±¾¾ŽcÇŽfff°°°€µµµK(”I/Vž]P̘Øiù&„Øö4 Þje4yf*‰KÆo>'ã,)5:âö@6+²,£™¶, ¦i"×Ãs~WUU}µP(À4M”J¥Xïs'ˆK¶]·¡š¸®Ë•¯™±çü |³p3ý12ëÌÌLÏ-m°°°€õõõ–ÊÂ'Ož€PO×t:=T}hpd³ì‚bÆÊNË·mÛ$ Žè¯ü‚çvÚØˆûk`¦˜–ñ Žãàm—^ WVA–t嫟´!LÓl¹'i—T©K¶-«ñ÷È#7A|ûžPçêÀÌȉsþ:tî`˜t5X©ÿêNÑiPÔj5ÌÌÌDî;sæ N:Õ¹¬ax1òì]ÝÕT«Uœ8q÷Ýw_,ŸÝŽNò >ø Ö××±oß>¿!Ë2, þà·€]àa:³¾¾Žûï¿?–ÏëOÙ9ßqà¤Þœïj±m{öìñ_«ªŠÕÕU8޹¯ÇÓ4 ¶mcvvÖ7r…¡câ¦R©àĉ8}úôŽ~î¸æoÀ‹ñœâ6þôOÜwÝ %uGÊìBhþî&Sã`Üówۮ̮tð~çïĵµéZ|úô鎃åî»ïÆñãÇ[‹ëºÞL“=O Nž<‰'NàØñÏT¾Oá9~ü8„!~ø<ÈçT½2~ìzŽ?ÞWšÆ(ÇN•¤„' UUQ¯×ûÞÜ^*•àº.\×…$I‰S0É`ÝiÆ1Žã­¥Û¶‹—¼Ä…bÛÜzo—Bów7™㜿pÑ<^ W|ßUÞ/] V ºðkµ*•JÏ!Àý Ch&j’'.¾øb(Šcï‡BÉ2‡×0¾Ü’ò°“ *ßpÉ%—DÊ·ã8سçeP.ú'=1€¥¥%¿ÂãN3Ž9œpמspþù^<;ŸÆF°µMÒXXX@*•Úñ9|ó7Q,z*Šëºxù¾}ÞÆ„~ÿÌx¡ù»›LƒqÎß@Àä½ðR˜˜]Å :ø@}X=Ú÷>*ömOÔÁ°„jµ:ðÀõ‡móäÏÄΨå›xÖ³žõ‡Ÿ`gbg\2xëãÿx@–Q.óú#³³ŒS¶Y…^|óÍxñÍ7s­ &Æ)ã@SMËb9gzf ƒuœ¤R)ÌÏÏcmmÍßfÛ62™Ì@çs]× ?pVæ™Øµ|^˜ä3ŸYƒúƒ±Œ3±3'„xÅ…²¥ÊĸdÛuûO? Ïž>$]çZL,Œsþš ÀQãx†éÄå°^8Äââ"Ö××ý$ïn¸a¸“ú=?&^F-ß®ëâ^ÄÆ*“Æ2‡ÃSv ³³˜ýŸoÂ&‡310ÙvÀ©¤ ÎáC¶ ƒu&FÆ5¬Bx¬·0=«Á:??YÞ:Nãæ›oös°†É•¥–$®ÐÁì(;!ßÄý¯Çu›É©âÉìvRÆÏ`Ý„õÅ8/îÛg¦˜”mIÔß\ÉMlÞ03}ìôü²؉ÄôEâB‚ êë:Š¢(Š^ÃadLB¥|;ŽÃÅg˜Ä1J'E¥_÷í%!òù<öîÝ‹={ö ›Í޼÷¡ã8Èd2¡¿B¡Ú|ÝŒëºÈd2°,+´Ý²,ÌÍÍaÏž=˜…išq-ŒZ¶UÕûóS˜&fÆ1s803 ={XƒE–¨ìuTá¥ìÙÚ Bˆ¸/aÆŠ¢(œîÄL=¶mãâ‹÷ÿp8îKI<™Lªªbkk @#­\.Ì ¢g+õg%TÓ4(Š!DG#Ù4M!`Y´mÅÕu]äóylll@–e!077ç-TL±!G-šÇñ"Âf ñà îKÆôMWƒuß¾}8tèPËö±„ŒPE2†™Bzè2ÁÌtãº.n»í×ẜöÔ Ë² IŠÞ†ªª¢X,Â0 ¨ªê“Bär9ß`´,Ë÷hÒvÇqà8\×õ{(#ú&Rœ^‰-ËB¹\ÆÜÜ\× …¥É #IJ¥ÒÔ/ÈõÈò` M]>‹Bƒ^T!„¿rQ Ê+#, …n^ãBU@Û`YdYöC ŸÏûÛ£ Þi.D$ >òq8î3¦ú>™ÝMíÖ[¹È3=¬‡†ªªþj(‘N§1??……躎£G&*ßU_8ë,$ÌÔrêÔ¹¸ê‡'ùåq_ ÃŒ Ïó&CÞúŸ®Šûr$I(—ËÈf³¾ñH¹‘¹\…BBd2H’×uQ,!IæææÏçý÷‹Eßã…mÛØ³gÿZUU¬®®vÜOy«ATUE¡PÀææ&lÛÆìì¬íBˆq;m8ÿþr2à 1µaÏ ×Å×\÷U0LWƒu}}µZ ozÓ›:÷¦7½ ÀÂÂR©TÜ÷ÀSr.þÁ€§=-îKa˜±p×]gãmg} Å}) 36¾ô¥»ðÓ?mwT¼« DQlnnú•€E yïTUõ½­Ao&åÒ9èØà1Aã±^¯·½UU;î¢išoÄ–J%?LûOž<™(ƒõåçžË 3µüäÌÈÏŒû*f¼ÜvÛ'Q˜= |ÎûR&ŠNÆ^°}L¯ïÙ)Ú]Û4¢?ñ}€,õíÏ3ÃLŽƒã>ŠXg† «Á:33ƒÓ§O·l?räHÜ×Þ—Üu‡3S˵ý9ä—.Ä} 3>\/úÀ×ð¢gÜLqhèNÁmS’ƒ€øÎc «^Ú$,0ÌÈqÔ󘸯‚™pÎêv@:F­VÃúúzÇãhÐë7ŽãàÂï?y%f!~è2®ÌL7ù<~ãÞ#xÜG>²>v“÷2é`ó©ÆL5Õû7<ú‚Ä}̄ӓÁšN§±¼¼ŒZ­yL­VÃòò2æçç‘N§ã¾§gÿê¯Æ} 3þú¯¿÷Ÿó6€ÃȘ)硳>ÌT™©D]ÍõT]™a&•}ýëxäe/‹û2˜ §§*Á7Þx#qðàA,,,„ŒÒãÇcmmÍ?.I8ŽÃ!dÌTsÉ3îçfº)—ñÒLÀïÅ}% 3R¨…­i²ÁÊL/¸ürü"G0CÒ“ÁšN§qìØ1¬¬¬`yy¹eÿÂÂ:”˜bKçƒ0ÓÌÖÖ*®¹†UfºùÀ>ÃÊü¸®‹|>\.*æ“ÉdBÇI’]ס( ÇA¡P€®ë¡Šž¶mÃ0 ‹E(ŠÒrEQP,á8,Ëò{¹2í¡öð’„–jÍ 3M¬œ<‰?b}œ’ž VÀ«|ã7bii •JÅßžN§•·Jx}ûfºáEfšø/ÿåùøÍßä…™~1MBX–2XmÛµ›1MÙl›››BøFgЀ²,Ëo‘Ó|!²Ù, Ãð^¦;¦éý«ë>¹ 3m!xÁ‘ ]sX›™™™Áüü¼ÿ—DcWÜc¦ž÷.¿g?ð@Ü—Á0cò€g<ãvö> €eYX]]…mÛp©+et:ŽÓöyJ½Ry‘¸?P«Gxú +õÌ4Òiî`˜~èÛ`$öá q_ÃŒ§Ö7qõã÷e0ÌØ0ô-ìÝû!.¸Ô'Žã@’$Ȳ MÓ`YVh¿mÛþ_>Ÿ‡®ë¡ýªªúïiö¶FömVJûĹíGP*ÇØÅL5ŸùØÇxn`FBÏ!Á“Æç?ô!\çq_Ì۞þ£¯ò+⾆ æÿ8õ‚ÏÁùîç (ËßpŒ4¥t† º…‚çU+½Öà¦éy£Ð4 —óŽ/¼ã)-4ê³èx²,(ŠÛ¶!I,Ë ¥¶mûÿ GÕ4 †a@Ó4ض\.×âu5 Ãÿ.—C.— —iãÊ%^xö@1S‹ëâ—>ð<áMoŠûJ|„ðþxhò˜Zƒuï~€ýÔOÅ} 3ØWßâY—™ZÌ#?Æû^þ9üÁ÷“ï]í¥}s¢\.ldF¡(­çîå³LÓ„¢(¾Qéºn(ì4X‰ *V ¦œÖ(ƒªÌøƶå1_TÕ÷†3ÌÔaY°¼uLzŠž.Ô¼NlÒ¼PhYÞŸëzê“,{…ÏTÕÛÏC1¹L­Áú¤/~½êUq_ÃŒ…{î¸Ï;ÿ³q_Ì۔ Nàôc¾ÃÞ§>±, ²,‡ Ê|>ßâe톦iÈçóœ?<ЫGõfÛæï˜™J„mãǯxEßïsœpmzPt Mmù|Ãè ÚÄÁ…Àn …¶í¯¶í}&·µO.Sk°JB }íµq_ÃŒ…ÏýóðóÏæ‚KÌt"Ë€~ùðñÇ<†•ù>±m;TðrR©]M3ªª"“É´MÒ4 sssØØØèûó÷ìÙ:?{cÃÈ{%}€’ÝÏBÃLB`Ïç?Ǽõ­‘»É+ªªÔ2Rƒ¨,7 ÖæiduuøËŒz¼X®Idj Ö'>-‰ 3œ¹÷QüPžêšiÌ.F–œøŽ~WÂÏã}Q*•Z¶išæ±Á–6m“eÙ_ P%tlÐèŒ:à§íö1 ŠW­Oð´p×u9$˜™>, Ÿ¾ä>q]ï TËj¨èQ©1_:lˆ˜J™a—a&÷=õWpN:÷e0ÌØøÑWÄ} 3¶5w.¸ÄL-¶¿=}’¤ Ÿ÷ÂyɃª(ž1˜T/æêj#”˜®™‰Ÿé4X߿𸯂aÆFêž{p‡¼3ÓŠmã{<‡3Ó‰ãÛ­ƒXÆ™iäÌW¾‚3éƒÈd<us3¹jô`YÀì¬WÕ‰—©4X?ÿÏÿ Á!6̳úô§s3½8¾ôÀì}b¦“íøG˲ZZ 1ÌÄcYxÏ®Ãç?_Àêj÷jèI&—ó†«ãx^âLس˜›ó¶1;GâsX+• fffJ¥z~ÏÖUWás[[xMÜÏ0]D¾à\€·°2ÏLɸ®ã¿Û6J,ãLÂtgï*3 "ßÎ9/Á_~ÿgðþ¿; EyBÜ·04²ÜšÏ 6 /çU×½¼\Óô¢þ›QïO–½÷›¦çÉ%ƒÞ²Âmuš«ábUA(GWVn>†>»ÙئóÑ1ôYÁsuj³Mï§ ÏÔ"ˆ®©ùû8qâ"œ9sN_¿Cb Öjµ ]×Q©T¶¿ 5Ô¨¼’$ùýæ&‰ #߀WY’a’̰2ìÊ0IcXùî·ÍÃì$ÃÈ·r …+ž1‡ú«0>I K]÷þU hd :Ž÷>2°aé8Þûšófƒ3C"õ™‚zÏšf£òq.ç?h|:ŽgtÓõPþ®m‡«4÷j°’Ñ+IÞ{È>ÎOš,ŸÛ×wžXƒõðáÃH¥R8vìjµ<ˆååe,--u}¯¢(JÆ$šaä¶¶¶â¾†éÈ02î8{Ÿ˜D3Œ| !¸à“h†‘ïÝ^ù:Ê3Úœ¿+Ëa#híÅ ïiî=+˽½¯ù˜^?«Ógëëwáøñû»Ÿ0@"sX«Õ*Ö××qèÐ!ÀÌÌ ¸—3°|3Óΰ2nÛ6{W™Ä2¬|›¦ÙÒ+—a’Â(æo^ŒaFM" Ö“'OÒ¶étÕj5îKÛQ–——㾄‘R©T°¶¶÷eÄË·Ç4ÊôÙAVÆu]ŸŠpÉi“‡i³ƒ0¬|Û¶=ñÅ–¦Q¦m¼ʰòËåPìÅ—p¦M&}Ì&2$¸Ó ¨Õj˜™™iÙ~ß}÷áË_þ2Ž=Š+¯¼2î[ ·Ývöïß÷eŒŒ'Nàĉ}§5÷Þ{/n¿ývÜwß}±|þ òM×}ôèQ\|ñŸøâ‹c¹öQ’y%I³'NœÀ©S§bû|žÃ=’"£")cöÎ;ïÄ׿þu<ôÐC±|þ òœ¿ßñŽwàûßÿ>¾ÿýïÇrý£ )²0J’2^iþ®V«±|¿<{$EFERÆ,éàýÎ߉4XkµZÛ}§OŸŽ,gu¶¶¶pë­·v|ÿ$±wï^?~<î˧OŸ€ØïéÔ©SøÎw¾ƒ‹.º(–ÏD¾à¼óÎí·ÞŠË.» —_~y,×>J’"£$)cÖqüä'?‰íóy÷HŠ<ŒŠ¤ŒÙo|ã¸ï¾ûðœç<'–ÏD¾yþN>I¯4ßsÏ=±<{$EFERÆ,éàýÎ߉4XƒaÍ´¼¯zÕ«ðªW½*îKg˜® "ßpôèѸ/az‚çpfšD¾yþf&ž¿™$’ÈÖ}ûö‡%ÄÁ0£†å›™vXÆ™i†å›™fX¾™$’Hƒ5•Ja~~>”lÛ62™LÜ—Æ0CÃòÍL;,ãÌ4ÃòÍL3,ßLÙS¯×ëq_D•J‹‹‹H¥R~’÷‘#GÚæ÷1Ì$ÁòÍL;,ãÌ4ÃòÍL3,ßLÒH¬Á x‰ß•J0??÷å0ÌHaùf¦–qfšaùf¦–o&I$Ú`e†a†a†av/yûÛßþö¸/bÚY__Çž={Ú†RT*üð‡?ŒÜßi_/ûÇA­VƒëºxÒ“ž4Ð5%ñž˜ÁF¾G±t’ñI¼f8:Éø$ÊÏá ±Ûæïn×”Äûa†ƒçïäßSOÔ™±ñá¸þŠW¼¢~ÕUWÕ¯ºêªúßøÆúý÷ßïï?yòdýúë¯÷÷¿õ­oíi_/ûÇÁý÷ß_ë[ßêæõ×__ÿÚ×¾6²kŽãž˜ÁF¾G±t’ñI¼f8:Éø$ÊÏá ±Ûæïn×”Äûa†ƒçïäßS?$²Jð4P«Õ°¼¼Œ¥¥%8Žã7S^^^ö9|ø0R©”¿¿R©øû;íëeÿ8X^^FµZÅ­·Þ ÇqJ¥°²²Òó5%ñž˜ÁV¾G±t’ñI¼fpºÉø$ÊÏá °;çïn×”Äûa‡çïɸ§¾ˆÛbžVn»í¶úUW]ÚvÓM7ÕßøÆ7Öëuo%㪫® ­Ž¼ÿýï¯ÿÒ/ýRÇ}ÝÞ;.î¿ÿþ–Ïq÷à G'Ÿ6ùÅ5³ŒO»mþîvMI¼f8xþNþ=õ ¬;Àââ¢/ ÇŽ€ŽB°¹¹Ùv_­Vëø^ê—5jNŸ>Ýr/§OŸÆ‘#Gº u/×Ç=1£¡_ùNª|kkk˜ŸŸÇÉ“'C Ò€“¾¸¸ˆT*å'59r333÷u{︠ϤUª~îgû™d1Œ|bÿ8è$ã“x?Ìpt’ñI”žÃb·ÍßÝ®)‰÷à ÏßÉ¿§~`ƒuÌK¦GåIÔj5¨y§}½ìÃ^Saä{ûÇÁ8Ç$Ë÷äÑIÆ'QxgˆÝ6wÛŸÄûa†ƒçïäßS¯°ÁÊ0 Ã0 Ã0 Ã$Îae†a†a†a ¬ Ã0 Ã0 Ã0L"aƒ•a†a†a†I$l°2 Ã0 Ã0 Ã0‰„ V†a†a†a&‘°ÁÊ0 Ã0 Ã0 Ã$6X†a†a†a˜DÂ+Ã0 Ã0 Ã0 “HØ`e†a†a†a ¬ Ã0 Ã0 Ã0L"aƒ•a†a†a†I$l°2 Ã0 Ã0 Ã0‰„ V†a†a†a&‘°ÁÊ0 Ã0 Ã0 Ã$6X†a†a†a˜DÂ+Ã0 Ã0 Ã0 “HØ`MBض÷e0ÌØ`gv3ãSL°Ü1»–õøaƒ5a8ŽƒL&÷e0ÌØ`gv3ãSLåÎ4M¸®÷%1ÌXhžcYÞw6X†a†a˜±,‹xf×Àò¾ó<6î `+5’$AQ”¶ûeY†ªª°m¹\`Û¶¦ iZèý…Bº®Ã4M! ( 4M }ž®ëÏ0½ÒIÆ…¾ÌI’„\.I’`š¦/ó„eYB —˱|3C;ùFö‹Å" È|f!`FË3a†%J–i›eYUU[d”¶ñœÍL íæí^ä]Q”ȹ`¹ö°ÆÌÜÜ …ÏøÌf³¡ý…B†að–l6ëÃ0üã…˜››ƒišþ{i¿Bd³Yd28Žãï§Ïäx†é…N2.„Àì쬿èbY–v#„h‘·aä•囉ƒvò?¬ìçóùÈU~!2™Œ¯1̨覯‰’Qž³™I¡YÂòþ•¯|¥íÜNDz\@‰R©T—$©¾¹¹éoÓ4­N?Ëææf@h¿,ËuUUý}-ç#ÔK¥’ÿZQ”z.—ó_ëº^WUuàã¦Ýd¼\.׃ÓÐÖÖ–/ßÍò¿±±QPßÚÚª×ë,ßLòé$ÿÃʾ®ëþ{é\[[[-rÍ0£ Û\®ªj½\.ûûše”¶ñœÍ$n²^¯w–÷Ns;ËrÝ?ìa×u¡ª*dYö·Q¨/à­Ê4ï×4 €·â#˲_¹,øšVi„Þ+I’’ÐŽ~g˜Nt“qÚžÏçaÛ6$IB¹\†,ËeŠ¢ø–e…Âj‚ïX¾™äÑIþ‡•ý`¸0A«ôôœ`˜QÑm."JFyÎf’Î ²4ä½ÓÜN°\÷¬1By©íBt|/å)ÿ¢ Ýd\–e”Ëe@6›Åž={Ïçýý𦅔v–of’è$ÿã}EQ ëzè< 3 ºÍå 3- +ëÝævf0Ø`Y–CÞP l¤J’ÔÖhUÅ_µ¡¿ÕÕUèºÎyKLbè&ãT` T*akk °,ËÏÅÖ4 ŽãÀ0 !ØsÄLä²_*•übœÅŒ’ns9ÃL ÃÊz·¹ 6XcDÓ4Ø¶í¯¢“Ç4¸ßq?q›*J^èAð5ÐHúf˜¤ÐMÆ©= dYn ùÕ4 †aô’Ã0I¢“üKö%Iò«UrÛfTt›ËiÃL:½È:m¢ÛÜÎ ¬1Bá[Ùlsss˜ …}ɲŒR©„L&ƒL&ƒ¹¹9?)%…Bsss~…àÕÕÕ¸o‹a|ºÉ8ååÍÎÎ"“É`vvÖWÔ Zœaï*3it’ÿqʾ¦iÐ40™‘Ñm.—$ …B½HÌÄÓMÖÎòÞËÜÎôÏžz½^û"v;®ë¶íÑç8dYöcê©O¦Á"K&Ì0I£ŒEµß4M†ÍÍ͸oƒa¢“ü³ì3“D/ú çº2Ó@§y»yï4·3ýÃk‚q]³³³ØØØ€¢(p]™Lº®sx$3õP8ÍÜÜr¹7Òfv ,û Ã0 Ó€C‚L0$xÏž=˜››ƒ¦il¬2»Çq°wï^ȲÌ2Ïì*Xö†a¦{X†a†a†a˜Dòظ/`TT«U|á _ÀÅ_÷¥ŒŒ;ï¼OyÊS⾌‘qæÌœ9s&¿Ñ™3gpÖYgáꫯŽûRzæŸøžøÄ'Æ}##Iò0*’4fï¼óΉ*òÀsxòIÒ˜=sæ fff&&7Œçï䓤ñzçw╯|%fffâ¾”žàù;ù$iÌ2OÁúÅ/~–eMÌë>õ©Oá~á⾌‘qêÔ)Ü}÷݉øN:…Ó§OO”Áú·û·u½ÝH’<ŒŠ$ÙO}êSe°òž|’4fO:‰¸–^àù;ù$i¼~êSŸÂK^ò’‰1XyþN>I³ƒÌßSc°>ñ‰O„¢(XZZŠûRFÊ4ÝO¥RA¥RÁÂÂBÜ—‚õõu?~<îËè‹K.¹„åaHÊoT©T⾄¾à9<ù$iÌNÚÎó÷d”ߨR© •JÅ}=ÃówòIÒ˜dþžƒu™¦étét:îË`Â4ÊôYf8¦M¦qÌ2ƒ1²0m㕎i“‡I³\%˜a†a†a†I$l°2 Ã0 Ã0 Ã0‰„ V†a†a†a&‘°ÁÊ0 Ã0 Ã0 Ã$6X†a†a†a˜DÂ+Ã0 Ã0 Ã0 “HØ`e†a†a†a ¬ Ã0 Ã0 Ã0L"aƒ•a†a†a†I$l°2‡€ãÄ} Ã0 Ã0 ÃŒ6X™‰Âu¹9À¶ÃÛÈçL0 ï¸vï·mà?þã"œ9sNÜ·Ã0 Ã0 Ã0Lb7X×××ã¾&ÁY(x¯e(—]÷^çóž[(š”JÞvÃè|¾ãÇgðÐCçŽýúY¾™i‡eœ™VX¶™i‡eœ™ç‡W«U,..ÂiŠï\^^ÆÊÊJhÛüü<Ž9çåN,B–åkÅ¢ç$e@’¼s9oÛì, (ÀêjôyÇ;·,{Qû ïªê}¾ãxÿjZãslÛûlEñöI’w^ÃðöiZøüÁÿ‹Þ{¥±ŒYÀÛ—Éxç(½ëPU`}ý.?~ÿX¿w–ofÚag¦–mfÚag&‰X ÖjµŠJ¥Ò2 ˆ“'ObaaªªúÛfffbù‚’Ž€i†ó:ÉxSÏPÂ3ÜÈ@TÏK<½W’Û77áµÙ¬w×õŒIUõŽWUψ ¨Å¢÷o©ä«i ãð®Ý²¼ãï8º]oxLÛA†n;dØØß׸aùf¦–qfZaÙf¦–qf‰Å`]__‡Ýœ„àôéÓ˜ŸŸÇüü|l_̤ „÷¯ªzžë6¶‘‘&Ë ƒ0 2:£z3s9Ϙ”$Ïàmöª6Âô~2”£Î›Ë…÷7¿;i¬,ßÌôÃ2ÎL+,ÛÌ´Ã2ÎL"±¬ XXXÀúú:[ö¯¯¯CUU,//öïßϧ Ûö DY‡Àvò6 …Ó2aùf¦–qfZaÙf¦–qf‰½èR;(T¡V«aqqkkk¿÷Þ{á8Ž?À¦ËòŠ ‘'•éõõu|ä#Á7¾ñØ®¡_ù€ï}ï{X^^æ" LW–——q×]wÅz <‡3ãbmm ùÈGpêÔ©X>ŸçofœÐü]­Vc»ž¿™qA:x¿ów¬E—¢¨V«8tèn¸á?f>•Jayy mßwþùçã²Ë.Ãþýûã¾…±£ª;Ÿ—EsH‰,Ë£ª/%Œ}ûöáÊ+¯Ä·¿ýíÿìAå.¸àìß¿ûöí‹å{c’ USïÏq¼ñÛn»-–ëá9œ7ét§OŸÞq…žçof' ùû /ÜñÏæù›7¤ƒ÷;d°Ò*a¥RÁ¡C‡J¥P­V±´´4ô¤R©–ó,,,øŸÙ.,áüóÏÇå—_>Õa –å«–eÂmj4ªªj‹Áè8lÛ†Š¢@Ó4€išþvI’ü÷P‚½mÛpB¿zœ,ËP²,CÛ¶¡ª*¤€Õì8\×õÏ<7!IE _Ó4hš:W¯¸®Ûò]¿úœfR©jµÚŽÿ†ƒÊ7à)<Ó,ß„mÛ0¶û)=ĸ;ŽEQ ( $I‚mÛ°, ²,Ãu]\qÅOáÊ+_Œ'N„^þòG (ªz)„ðŠ£mlÌ㢋.Šåšxß=X–ÇqPìT$a œsÎ98}ú4~øÃîèçòüÍô-æG餟.D¸®‹B¡àë\çž{n,…ŽxþfÆM*••W^Ù·Þ·Áº¼¼Œµµ5,,,ø633ƒååeT*•¡Ë^¯¯¯£Z­†VrNŸ>íδbÛ¶ÿ÷È#)ìÙ3‡;ïüG¼àOŹç¾=ô³xà³ñž÷ü&žýìK|ãð&:22鵪ªúJ¶mÛ(l÷²Ñ4 º®ûÛƒç¼ 5—˵›ŽãÀqȲŒR—ò½íúɈ–$ ªªBÓ4X–…¹¹9ÿóÈð ëw]†aÀ¶mÿ˜ aÜlpáLsó}!pûí·ãyÏ{ÞŽÿλU¾O¹%§ß„暦AUU†!„/_ÁňæÅ Z`Ñ4 ®ëú¿»ªªØØØðÊw¿û»ø?ÿçÇxík+¾\²@c%ÉV°B"-Ò8Žƒ·¼å|<ãï×¾ôé–E™àù›Ï×,×Äí·ßûîûÈÅ—f‚†6|îsoÁ“žtgÎ|™Œ76/¸àþŸÿ§Š'¾Ëï¼›e< ضíËAóvó¶B¡àÏ‘ÍrIÏ I’ ëzh<¸®‹|>À{^ …ŽF«†aÀ4M¨ªêÿEEäÐ8s]ןÓ4adYÆe—]¶ã=,Ûɼéß ÎBòF²Ô<€ÆB' Y–}ýðž/¹\.4&„°, –eµ\h,ÖÓ|ß|Í4×Ó‚=à=‹Å"V·ûFå–î,ãLRéË`­V«XYYÁ‘#G0??J¥ÀØ©T D¥RA:ø‚fff°¸¸ˆt:íŸgee%ô:)Ðä4ôÈ«CƪªÐu’$ù“(m'EÛ0 ÔjÏÄ+_ùz”Ë:\W‚eŽóGøÑ~„sÏÝ„$Ý„Gý&týÿíÉëÔLÐÀ ¢öQE‰Œß^hwި튢øÊNЀ¦ï t]ïj$÷Ãúú:Ž?>²óõJÒå;èQ$È‹Ò )ÁAY6M–eùžHEQü<)©Í¿£ëº°, …BÁ/D¯ i0‚ ™ßýÝ'ãqT5ù¾^$ š¦Á¶5œsðêW_‹ÿûûû^iN £œøüç ¼ìeßÅ•Wºþøø×}2>ýéKðÍoÎàþèËxæ3[W"-K…,Së§×ùÛ½1ôdüÅ_üsï8B’.ãÓŠù|BK’äS×u±ºº EQ „@&“A¹\öe“æ[Ë´pDÏ-Ã0Bç ±sss0M¹\Î?>8—X–MÓ°¹¹é/Ž’ÁÛLЀ¦9¡X,"ŸÏ{ÏVÛÆžþôXæp–íÑ\|\$¤çOÐ(Z„Éd2þ3Ç0 är9llltý|Û¶}RÓ4ÿùdY ÃðI‡£g¸@ïÏ ¬‹‘,„ÀææfÜ?–q&¹ôe°žá¢ž¨îß>¦ÑW9›EÀX £ªêvA¶;Æò}v#É2ž4„0M3´€‘Ëå SƒíRÉ_0¢Ÿvç!…ÿÈè$e𯷮ë0MÅbÑßGç%#¢lUU;*çårsssþ¸§4‚méýŠ¢ô4Þ5MC¡PÀž={ ë:Êå20;ëqˆ–íÖH—¨gC3Aã“<딺A BÏŠ‚Q%2â«™b±ÓôÒ¥:=oši7¦še8ʰÄyD’¤ñè9CÀ2Î$•=õz½ÞëÁ•JÄ­·ÞZ…YZZB­VÃ5×\ã{_‡¥Z­v4›¡ÕÖQäѶƒ”òà÷zÇß‹sιyÌc IžÒ©ë@§Ðγ·c÷H¥•WW±þã]^:ѯ|^ˆÐ°!÷í¿O™%Ì4Aú­ã Þ–Éu=#±\ö•l»õ\†‘m{o0j2êZLÓû£Ï!„2™Æœõù°,ï͹ i¸ä’;ñ½ï=%¶ï=‰søNA¡Š”yò2Ã^)Jáƒ÷݇§>ú(þèÙφOy¦hŠ^Ð4Í7È»ÙMù¥<9 wõ=Û¶\.7XŽ7 !¼ÕEñÞvˆ¤aB`ý—96yIÚü½Pô €–Ðñr¹ù›S½Œ`è+ЈÎi¹eÄ-/»yþfÆÏ òÒ—‡•¼¨‹‹‹¸ñÆýíÕj7ÝtR©ÔÈ®S©R©Ôð'¿å-xê5×àyhä˜öbÒÌÁƒç`eé@IÁu½çq¢æèlÖS uQ#ƲÖB¡¼ã±^NÜòMùkü0¿¡ŒUÛö”Ì„U‰v]@>§ ÷-k°ÎYØ`•å°S§ù<…‚÷á”Íé|d¬vúüvÆ*à½.—Û¾®{ 3ªŠ×¾¶ >…'n%ä íÅ+hš&LÓôCÖÜfò*•Ë實iøÄ¯ÿ:Û6þ€üá?ªòþEA©TêiìʲìçÈEB+3’äý?J˜›Ù^©éš2â8áy˜>/Ÿ‡¿ŠKa®ëýE/—ææ€_þåü²ƒ1M²„¼ùUCPdYÐ+ÜW(B©”kL)l”NÓ*ãLDÕ? h5˜N‘yíêqб§Nê»AßE—Ž9‚B¡€ƒð¬dŠoŸ†Zõ>23ƒwþïÿçV*ÈårÈçó^8R_çòKU0›67“¦Ï{Èrr½¬®ë)3ÃVe *I†‹þã?⾳ؠÞýÉŸ zé¥z ëêrRO¹•€ÏÎ#Èéq@¹è[Pª·Àƒ­ü¶ù¼§_»®wûdÐF¤ûB×»{ws¹Î¡Ë]úMó¼PÌÈ ‚AÝBøÈXmçqêI’pýG>‚ëoúñÉ0¸2¯aDUÃðÃ{ZÙ!ã–¼ Á÷Pü<]£ã4FƒÈ²78\7,ü¿$É‹ øÈG€Ë/ì;`üEx Q¨r@ƒÑ6T,¯LS~q>Ÿ÷«´+йÃ0LÿDs¢kŽDU¨¦ñ À7,i;îèÑÜí#êZ¨[॰xiH¢åsh>¾¦h¢'NàÁìë{èÛ`™™Á‘#GP©TBU‚§!›ªÊ•ËeȦ‰—Ÿ{.Þ캘…®ë}M¾†Ñ‚˜ä‰;—‹Ö²“€iF‡…±íFòo/è:.ûÃ?Þð†¸ïnÇ *Ôr>tŸ‹0miç !–!Çãʃÿ |Ï…¬DŸÔÇ4Ê¡Hò¨À !¼ý…‚§ãÓsƒÆ¼izÿnGè¶¿@Ûî/!¶Å"0;‹‹_üâÑsC…Q666ü<ѨgÁPÆj“QêC‹ÍÆ)­^÷;>,+ZÞ(]¢×ß–ÕåFϵ൞'T×½cÛEñ öËáò—¿|´ãf—@aáB?|»Ù£JF«®ë0 £«L—J%¿ˆÖ0‹5Œ7dFX_’‰*ÂŒ®!c2Ø5À²,Q”ŒÁ`N7m#ã°¹kF°F€Ô´À̲´=j[7š  ÑÅ]Ûåˆ_xá…}ÍëË`]__Çââ"n½õÖ©0P›±, «««Þ¥ª8϶Q*•ʳåx 8O± <ŸQ ( í:i‹Þʼa´WN$©¿°fUÅ#ïyžqûà0h€IDATíqßÝŽBÕ;766 ¹®§¸Ž’Q*)´ˆ2¤Œ». mmiÊÓ·`Û{[DIJ°]•Û·æÜÑvÊLR”h[ÓüèÜèÛ –$yDYµT|g{N ]\0¹™R ¿úë¿>ºßcc†¿`Y*•ÍfC©!Áêï)ëÙ¬÷;F-麧Á6¬$¹\{c×»xo_.ç k¡Ðºú’Éxçê´(ü\Ãðd1hÜU¼AEs÷(#xd÷¿ð…¸âë_Ý9w]S,ÛVU<%wuuÕ¯$Ý‹;Ê*þ»ZK*GÿhfFK°Ýr:)r!H0t–ªQÓ˜ë4Ö¨Âz/­%ÛeË ²G˜ß9¬333°m;Ô£i aó…Ųü‡q?? EF¶< (/gF&…ûªY;•-M*¥’§´©j´Ò£(ž²Õl´æó­È6§ÞðÔn»-î;ÛQ¨z§$I£÷¨ò|’äýÖTwÈËRÞv-@½ô!Çû(dŸBq Ow/—£NΊZlwŒ$u°LÓ»82ææ<¹mžhqŠ qœeµ·¦UŸŸÅ•£ûU¦ ylîù 4Z.QË ªÔ;77çKãªß”h‚vµ¶Ã_[ž¶í *E ´{äržP{=–J½=—¨ R¹ÜûsŒææ1ð½ë®Ã#_ýêXÎ=PÝ‚^ PEQ°µµ÷eO<¦ÙÜù!š` ™ª1µae¶ V¶¼ñ@õTU …»Ò~òˆRÇ —ÍÕÛw}¬333XZZÂòò2ªÕjä1“Z!Œ”ÛîKY¦Ð@Ò/"•QH ì(‘åÎ+õã&Ÿ÷îIO© ~‰’ä)Uä® ö!H1¢Ü):®Íý<’Já{W\ϽƄmÛ¢1£^ õj[¯¯©Íº?ÔAà¼ÅÛ>7ç‰XðYR,z9;ë½¥í¹MÓ{ó0c¥9a•" š —f9§±O½z:|ïÿþœçàW‡û¦š`aEQÏç[Úaw5H±XôWÔ{.VFîÊÙ nï¦ÐD…ËrãaC)à öêjà¤j]äEz8õj|ŽjtD¦ªj(¬·Ÿ–IL˜B¡Q2—ë;#µÿÖǽ~ +++‘û'Ù` UOìb†÷GzŠëv¨UAFÔ¨Œ:Ï( Ì`ùÒQæ!v#Ÿ÷>+—óþtî­§ª …©]¾ª¢xÊ™ãxO‰„)Xq"„€ëº­Šõ(dˆzH’{rtñúF«îEób$‰DP§o>¾ãf>ïi¼ZQßõÄi‡¦5f;i-ä}áªín„òMƒÊ‡ëº0 Ã/fDJKTè…t©–åýfd 6„…BØ]OOlbüeËjÌ4’A.I±õ-eâÇqäóy®Ö»ÃáM ««ÞԞɴ†™ÇÄC°=൮¥g”ñOŽÓPaŠÅ§ã5¯ùl_çèÛ`u’ZœgZ¶†-nkZŒõº!ê öfh‰Â×òù†‚¶ÌMUÕÞ–{@…—*›h‰ Õ¡‡˜)×”z6jõ±ƒ×¿—¨æ(/,}9háisÓsÃjZxžp]O+Ñ4ÏꥡȀnðˎЮ8R±XÄìì¬ßó”Ži É5ù’ûb1ü»Òb­Š ²HhYáùŸ’¥yÞcPnµeY(•J¬€ò F©cTŒ›Â;¤íÎÁŒ–`¸.Ù2TÔHQ6TÇHðñ”ËŸüäñÙÏ>ýø8û÷ÉN!‘Ê|ÁJý})¼TÍ…N0 Á¦ê£:× P%W ‘¨4’ûlÛÛf­Þ% U#¯3VHi 1Ê¢]Þ‡ŒÆ¦–6Œ…íB¸1Í;#ƒFh©äçà5R³VËòc軂«™&ò¢¶ ë¢j§BˆÎ¡_”ƒL¿¯ó1E”äraOi¯P˜|pìªjÌ+¨LÒ ö|¹\ÎÏ¿fF‹a´¶6,>.€Æz]P¹ z,ÃÓ§¶ÇøK¿öµ¸oqj°mÛï;Oa¾” Âá½Ýºë¥ã@R”Кn¡ðm?þ×ô|š Öµµ5ضõõuÀüüßXs§i‚ ï“?A–àn;¨À‰®{m¯üðÚß>ô×e¥AÏRwòBÃH ñP*•x<ôHÐT ±Aæe€år‡š"® 3kÃøÊµØLÍ6RV\Ïû×Åñ>+‹Õï,//ãðáÃH¥R8tè:„T*…Çûù­“Dd8°m£ð­ßBæ-Ïókm Îöò!Þ¿£,«:ˆ2HHÉîtL/ç¥"·fKžfm×å•ÿ˜iA ë£íL^õaè!ÏÛ0{q œðÇe@Qµ!=ùqÍ_FôI¥‘KÝ+Åbç1DÆ+¯à&ÇqºéØÆÌ¶= jªýR.÷'Øî½<Ÿ2m þªåryj”sÓl¬!*M&Ó(†…e5 º{oúx¾?\°€7f©ú’ã@ú­_ô¡¿ÅHªQp瓞÷W?Ѹ®‹L&3ãÁ0ÚËÜ(“Û^ËèûÒS·ƒÍMOŒuÝ{].7Ölm»U}²?p7æžsÎù/Cùk)ïªê·âûJ›:HèËÃZ­V±²²âWV ¢ª*}vR0M3²L´»g››Åô¡RƒÆU•$¼YqrO:ëõðvŠU¡D\rS–ÕnÜÜN$¹E‹–g˜X‰Š 0zïö(Ú#õ˜Ó§|å(äs÷Âͽ¿±‘*çb[ìþý«šóÒÛÔšæí£"dt’NÕÂ;ö­a’ˆëº=¥´e”1滸=3zš[0M –Õ¨,:ŠÂDAo«C•âI¥"“Öˆl(¿ý3ÿçï®ÒÇúËò”t áh H¯=㙾¡´ÇqP,'"'•äp˜uÐNP‡@Rû©ÜB¢õSjõÞN­i'²PF €m_†Òg. ¿'X˜p;B·úò°ž}<=ºfUµ±è"D#b¢¥‘¥²ý…¶ž„dzÂg2žœ @¡]òl…¹9ï°Ñ‹ù@9¬µZ 333-ÛÚõfM*¶mû €ƒ¸² õ†‘}HxɤŸ*ªÁºèQPA£fhI’–U‚hš7cëzkÑ%J tÝFÐ:·C˜hz-(6Ùlã!Üfò¤U½®X³×?X}{·´RI‚UðŠD–Kv†ímåKWñ‚MâiY$ÍðâHP( I’­Š˜¢x×—Éxÿgcuâ¡E™±4RÛh”úÜbÏ6Š×"dî‡>¸ àh~(–tâsž˜7yW‹óÿ½J¨(Þ`»ªª¤pîéÄ“Ïçý€7º*3TZºTò䀋1@¢¼«T)¾‹îÔ‹'ÉWY4oη²VHj&¨²Ér8èP„t­(hÁtuµ5q5ê¦ #ÁayÓ…™L¹\º®Oœ± ùÿ\ƒxÝoŠýC/„ôÍãȼâGßã8@æÿ÷4¸OyœÍ'„Ï—o ‘µ÷‹É‡«ßÑu`k˺ÞH¡¿mýkœ?AßE— ÃÀÉ“'qàÀ(ŠEQpàÀT*9rd|W:b¨QðؽO²Üðuð@EBRšHÛ)àÁU#nD(ô~ñ¥æI5˜]ÍùU¢{ä(B·‚‹&m–éN@UtÑ´­)Œ×øØs}»6TØZQ þ¨nçšú½ïþâõí«©nnr—ö)Dz,ÿè¥àRKÕg†I8ä]Í%å™MyÿäâlsÈÜ\÷BJ®¸)¡).ÔÍò/¯Dž3 #Ë€ǰQxñ§áþö;[?„z#F´‘½m,÷¤‰SË*^ìÜòù<4MÛyÙ߃ò f ÿÕ[=¹ÙÜDéõ·BûêÛÛ˲¿ü#”ÎyV?ýä–24Bxª}±èýÛö«1ÍÆ ¯O Ù •ß¾ Öt:÷¾÷½( ~•à7½éMxï{ß‹t:÷ýôL§PÉl6 ƒºhP?ç#_>M¢Q1•¹\kY;šXéßæÂIÍÞ× óÏt§c8p0aXz™¤bÑ¡98ا—v4É_ÁR Èîû?í_ns¿"¹pIa.#5ì ?L¢‰ÈÚëÌ´Q(°ºº ;0Ï !:/ÞwuWé™Ý …C“ @Ö^FUí-ÇÍyïq(O¼£±¡XDÑÉ@|ÿÇ0žøNÀ²|U&ê#eX}ý²œ†óÃçC~íU­¢(ž’^,g„P>!/xª,IR<‘Ž3²²Õ-ÃDב[ÿMÀ²`ÍBªz¡à‰Yùßåm×úÛM€mÃù³Béž×x«A³³^X[»¨NêêÐÜõ#Áôm°®­­áÀ¸õÖ[±´´„¥¥%¬¯¯ãÀX[[‹û~z¦]u`SóйHRÿ }§ã)/ªWŠEø5Ï©¤W³²MîøNmл Œ$·„I>#H^†-*ÔãL©ä=ÇC—CÖ§,7ÆMÓÃÇquå Š?ú¯€eµ¬½ò񵯯ð"VØÝÝ ¿9¼Â/<Ö5Ú€½«Ì„Q( ªêø#Åúô–í’£QY¤Êjã·Ä°¬Æ ×E1µ égž>,£ôÙçúü÷0wèy°þ´~ QÁ0M(ÿôg(}ð"”¬½ä)¬1ª.H/èúxŠ2!LÓôÀcËÙ&׿öAS!?ªÖÛÂvx€T*Â0ÂÇmlr¹R¦l0o}&ŠñÈ_¾Ù;hsÓS¼\×3^›"­ð¡:ŠS_k­VÃòò2: ÿ=rä–––pøðá‰(¼Ô¶rê6¥§þY„+§Gº­ÐE®ëýQ u‚&× ‹>êšŠÅÆûÛ}fóD¤3r:†ãUÝî#:W/ãd;,´FDïmîÀ7PËe˜‹_€ü“oµÌgv5ÔÚƒVÝUUõÂ]×m)°¢Tbï*31†!D²¼«@èy@ýƒjeyžSrQqyË‚§—.cYPnx^äGH°ñås°qòR”Þu&¬k“LJz¹ õºÇ÷6´©¯Íì,·äK ¦iÂ4MlllÄ·HÔ[ú©ICr(SÏw3UõÖ@dÙ“ùbþN¡/eá©­z>EšMÉBJ_k¥RA­VÃÒÒRË>ê¿: mmÇé\ˆf¯Só{› Ø(…É4Õy;…t2VWÛÃÍVfêéè] æ‰ö« ;Nk‡è $oM› ð¨÷Çi ²F% ⊟Bá·šÿCE¬% â?/B»®s1fwcš&t]÷ SMÓ`Ûvëâã´Î—œÁL®ëÂ4Íó0ELë=*ú¾Ý}Àþ“Ï@{ÜÍž®3; XJ¥€ª´º Ì¿¬Á¾ü×:Uë BeP77=ïQ?ž#Ij„M€Çi7á8 Ã@¹\î¼ð8nÅ[ÜÔ´özõvñ-÷ö¦VLzžÍÜÏ}·ÿ5ÒˆzYî¢âOÉ¢~ß!Á8}útÜ÷ÓªEZPø_iüúý¬²‘†Ýì BݪÃÔh¨Ûé©Ð\Aµù¼Q+­t>ž|wc«L½zI†›å»ÁŠ;îðûœ XF8;[}¤;¿²!š×gô›RȽkròä™§¹øŒ¢(p®ë6æüæfŒ 3aX–…\.·cŠ»m7:Ýõƒã¹çrÞëÙ(î~îÅû!ÿÃáF%nxj“¦m­Û…_œ'½ ¸ì²þfá)öIóZïr\×E6›Åêêj¼Æ*A×ËE6±ßpâs'}驯BL°’ªÂyΠ\ñ½þ?[×wm$Ð@mm>ŒZ­æo¯Õj~[›I(¼äºnÛ\&Ç” ¿Ñ®~”Ò°ƒ3{ó ßlÐÒùƒŸ4šßÛ/šÆ%Öw!}¬ýh!ÔØ.(·AO®,#ó×ÙÐ)È9y¿âu.([eßµm{÷Bÿúo ¨5ÞhÛ»v^f ]¼¦i0 ÃÛçº^‘ *ËÏ0ˆã8;éþ˰{d“¾äº€|ý‹áËpŠeØ?ûÇÐ~õìÆd©¢Q”/Ÿ\IAî/ã!ÊøÆj±Xì\ƒ FBrjšÈÿËë€÷¿'/õ‹ð†(a?öUP2{ã¾ô‰b ¶6ëëë¸æškpðàA±÷oÐ(m~¿¦…µpÛK;-36'þGå¡öB¿÷ÀL<íú ûCiµT*5d*— Ë—,ÃÞºª¥÷,Ãïg§¸ä|âÙ/àEÄë‡g.“ V¦WÚɽ¢(p¯\[óŒÕbq*£˜Ý Õ'ØÉž“Ny úoß­‚ÌÍ5ž!MMR)TQˆFæS»G“$yQ¼ÔžÕ† ,‹Åd rÆ;`Ðÿì"O•‘$”Jî1Aì'_õ†TÜ—?Q ÔÖæ–[na˜ŸŸÇüüÚ†Á»®7ŸòRvâ"ÜM¤Pð‹iz•Æ ^Äi?$¦Û¶GŸË×®!¤°?úä—y¡‹’ÔÚ}P*A¹ïS°Ï~µ¿ÉqZ+†L/Œ¥häv H, ¦\„ýÕ˲Mãl÷c ‡ŠJyd³Ñ k’Ô°1€FË_¦?º¬©T †aàØ±cH§ÓX[[ÃÁƒqøða؃Ô9ob}}½í¾J¥2ò¾®Í = Õ‘Qô¶ôAo Jgð}ŠÒÝS;%¥¦™öì´|wÍ_:†ŽåB’%dW_}UnÒH$ Pßp\MÇ6àæŠ}ç¡ÊrtΓLvZÆ£h&©(<ÇN†î&¢ªG*u*ÙvæavøÈG.Á™3çŒõš’ ÛAzšß¡Pˆî!oßð³áEŹÀ:zÆûè0K†jfáÜÿŒÐÛ¹AòIšŒc4XÛèäößÒ žŠÜ/ÝÝX(§ºîé:M‘ÁäEmü@Å}£†Ó}å°ªªŠo¼ÇŽÃüü<Ö×ׇ2^«Õ*#·SA§øMàGA¨½^UÁ¥ÈåDx‚Oùx/¨ñÒº;-£ôâéb&–8ä{T سòËRÐι¥½áh-+–d¿Êr#g©_WNÙžâñfÆÖ‰9ÙlK] çEpÍ·¹ÜÐhX.Õê9¸ï¾‹Æv­IífzŠ é!íʧѤ@À² ² ÕÆ¶‘»ÿ/`ë¿ôk´Ékõ~0Ý¢ñZQ²I¢ŒcÈÓ&+QÓ"##Õ“+(}øbäÞ·¿¡ÒõwZä¨<¤\î iÛÜMmîÃ4^P©TpðàÁžB†«Õ*lÛn;>ŒT*Çqpë­·¢R©`yyyè›m6V‰Ž«€4‘7£iÞlÜîͪÚè­Êì*â’oÊãë+çÃu#cìì­« ¿äRͽЦÅRÄÌ ã]] /õ å±&¡ÝM\2ÅNWLegu5l” ÞôS(ô—ß(ËÀïüÎ]¸b>†]H’l73–‚K¦Ù¨tT(À²¶×!% ØØ€í&bU…|üƒÐŸõÈ|êüJîAO8+äÉ'É2Þ©‹Ç@Ђ íeu]_OßndàÉsAT]oYiÖSz nã<îÁéË`mX__÷½«û÷ï÷Æ{9ÏÚÚZä¾jµŠõõu:t033ƒ……”·LÃ'>q¢ÿÐNk¦Š1í$”3»Ž¸ä{`ŽM^‡,Ð48îöh2l­'ÿ.ÌǼ1´­ùùç‡Ù÷ªr8pÒ‰KÆ£B´Îëírò˜Çq¼Î'D𧢂úô8MI’í ¡”’1 HWÙÖerÏýLã7’$¿ ¥ª"÷•7!÷æó‘É„;çQ½I ü›3É"©2Œ!ì=è% ®ª( h¬¢i`­<è½êÿ:}¿ºMÙXLz2X+• 8 °m‹‹‹X__G¹\ÆââbÛÐÌÂÂŽ9‚¥¥¥–}'Ož€á›N§‡Ž£w`ié±oßËÇÿ­Üÿt‡|^AO 2Á˜¼6Z"õϼ0>qû­á¿ßÿe˜_œmk´ÞêêÐ_3Fâ’ñ("Wä võŒ‰f4ˆiz©ú;;ÛÙ{Ji8IZÛM’l [²m/œe2Œ½Öu8ÿtoHuiqÂmÇú’S¶ÙÃÄÕœ“OReAA¡^ÌiêÖ!Þð&8úñÐØ ª6ª È~³ë¤4Hº3=¬º®#NãØ±cþ¶••Û-·Ü‚¥¥¥‘„ tµZ­í¾3gÎàÔ©SmÈ8ûìð”§üth;åÚùØvkVt/…L†¤ ¡Z­âĉ¸ï¾ûbùìvt’oxðÁ±¾¾Þñ=…÷àyÊ劈¦ö?žÍή ˆ‹ž¤R¡ÆÍC€S ãa}}÷ß,Ÿ=®9¼®ë¶Ê=kcÁ4ýVƒ¼©$Ÿo<2s9¯Õ-µ0ÙÜôòºFýST*œ8q§OŸÞÑû÷ü݉РE bv(³ìÊ*Ìï¾&”)Ò’‡ªiþJdóüN ]Úu3] ù»›Lƒž¿ƒ ”ÖÔŒm‡-Ц0/翉ìÍ×ûÊJTÚRñŸ~PU¿À[TÇêÐÇôéàýÎß] Vš`o¼ñFÅ¥V«¡R©„ú¯.,, V« %¬tîvtº¹3gÎàî»ïÆñãÇ#÷».ð´§½¤BÛ;¥¡ð¤²C”’9˜ÄsòäÉØ ÖAåðžãÇû+ Ó,ÏÍJiÂ9ÖÈEWÀþèC!ù–¤F»`ZÌ4M^³I ÇEÙÆ7‡G “$ØXšæ5-!ù¦ѭÃPá´q—ÁçüÝIŒ¿íªì>;i¸’n/I î ‘õƒ¤‚0 hþÞiùvvþnfdáÀ¶Ýܦç}Ûã!öì…#yŸ)«Û“œ¢xÿMRÈ4@:øÈ ÖJ¥‚ùùyß0àW Vpÿ0tÊM¥Rm÷]|ñÅP%2ÄðdöG?º-r{Ç Í+=QEj8Yc¢˜ŸŸÇu×]‡g=ëY;þÙƒÊ7\rÉ%XZZÂüü|ä~Çqz[™lž›^;óÿðÿµæ°¿t Ä%Ïö·Qq]o¬²óªzrXZZÂW\Ëgk"2ضY[‚L¦Ñ~ð<¨ôˆ+—Ãc\’â©æ½°°€ë®»—_~ùŽ~î8çïn„ŠF:Ž·"Я5é8žö].ÃøÈ³[ét4¿çóýÛĆá©Hü,š¿»ÉÔ8ØÉù»™¡Ãiî§jÀޤ\Λ³È Û1ìx~‹çó1Ò®ç*ÓÒÁû¿»¬333-+.•JétzdFj}ûö‡%T«Õ¡®ë}ìb‹k¿¥'R°±RÍ ÛÏÎLŒK¾‰QTדîþÔ×\ÐØ ªÐòçȾçjÞ ¯jp2çUu¿Œ‰\¤ijîÎt†Âzé±V.{„®{¡½ÍùŠ»‘”í ‘t½ÿ–íIÚ… óëW·¬½Q=Ó¯§\’ºwôc’K\2>’p`Òß)§)"Ú†Zæ‘ÁÚÞB‘ÁbvŽ®k:F¥RñÛÕÔj5ضݲJH¡À$샒J¥0??*àdÛ62QÍÛzÄq€+¯|çwwË‚däd¥ÿß,¥ªÊ’ËôÄ8ä{$ÐÀp]È/º$œ·¤(Èi²ÜX=Ž#êÃÇ0ÀÎÊxd…` îÈì¬çE5MoÜf2Cx9Ó¥A\ów¨à€Pá€~Ø^Ì¡N6Q⃵ 4­ÿß?—‹î¡ËLqÉøHƒí&s¹È28©°c?+ºB„õ˜á±ÝH§Ó˜ŸŸÇââ"°¾¾ŽZ­æ V­VÃñãÇqøðaÌÏÏdfiiɯ@\«Õ033ƒn¸a¨s>ëYwâ /kÙÞµ'’ª†Wë§µ ¯æ3}0ù¼Ê®´‹ ¯”mÃ9ÿeh™¿WWQB£ÎGPä…à0&̸d¼Çq½ÙXíÊÆFcÌZV#é’í ®ë†•yRÂ),¸ÏÉײ<9hþݛ՛A«µ³2?ÙÄ!ã¶m‡[çP(×09U‘,Ë;%=&ú‘qIòlbÃà‚KqÐÕ`€b±ˆååe”ËeÌÌÌ„ 0=z+++˜ŸŸG±Ï_p~~>RÉN§Ó¸ùæ›}¯î 9„¢BTñ¾÷ ùm ]RŒŸöL;%ßDOáÀ‘%ñ±~¶ÂwÞ‡’½BN¹MA¨—"·½Ü}ì´Œ7ÓR!˜óWý¯Â=K%oÜó©hÓž¸e;HË A…—zÑA\×÷®ªjtç½A<ªÌä’§÷Ð\.Ë ë2ò=”ì(„ð¢I¶¶ÂÛƒ§+ú·‡uÝËé''.³sôd°’‘ÅÂÂFß>333²Aâõضqá…?Óâ`ÊdšVÛ!¼ƒã¨0ÁL£”ネÒRHC)I‚ëÌô¥´Ð)Ù`e‚Œ[Æ#+ïr Âu½b ¤LQ@]÷¶‹¤1ƒ³ÓówËÂL04¬MX°m7ýÖÛåœÍ¹†WÉq¼y›ŽÛåÇ °“2L•ßÚDPÊvé úÛ<šÕ{ËêOî%©‡î"ÌXèÉ`¼U*W½ÿ~_ã¨bÖ/Ù¬'°×^{)ÞóžÆöH[Q¢WèóùF|<Ã$ ·×\¦6ò]¸îr›È_¾ÒE¯Y fvšÈ Á»<.=Ÿ÷ŒÒf¥Œò´xœN‘rNÚr79ÒÚÜô,4-œùAo"¬ÐsD=–eµ†ÓJx›ço¾í•2 cÆ[¿¡Bª !‚r Ë %>FÎ0;-¶‡ærjG#Ëm+::_|,Jÿ0Óp<Ž3ŒÆ"MËâ^ñ“LOëÊÊ à8ÇÁÂÂVVVbkLß4A;ŽY–[ŠÈ—?ܽ™R±ØCu&†I(]äÛ¶ýíç¡´r—jg&¿BpT©Ó)† 2.Hc£t:ék1Ò4B¶½m° ¢bµ-,#Ë ù‰Êa˜qÙ{•„RU£õÇAîyŸ(𦾿ó· PŸŒI] VjWsèÐ!5¦„ìIAŽ :¿çž°D3Ì":% =+õ¶Í:3øŠ|K3íé¥PðJ)³S ÃÛÆL'Žã„óûÚ-@º®' ¥RCwÏåÓ„ä:mݧ4ßSûJ†ÙIZäh„‹WT‚XVCV Îk(l¼¶ã óÆF¨ŽdËi™É¤'+ÎU™™‰ûº{&“¡jbÞ$ߢÛ<¼íaå8f‚q§}x¤ã„ã¾²î8áâíB &i8ŽÉ}œnLÓ«L xÊXð–K%ÚU ¡9Üýô]°?ò€·ð^,²¥FÊiçb}ƒaÁ ³ÓDæhá•”&µÿîܾÎ{¡iÞó¨?õ=_— ªB››ÿ»./ÈO2=¬“Œ,7Z~å^ßýn8Nž“8˜ ¥mØX0l²‹ÁÊm ˜IÀ÷®ú±ÓK6ëÓÕÕpª š¯þd£þ?°ëò¡˜)‡€¦yÿoÛ­ùf¢°, ÿégv*ËšÚ¶×?I««ž••­Ý‡ëº¸ü¼ó›¬J÷áË¡|yÎÒŠ?Ÿ‡Öpr9oC›qBó?×/`všŽÅhÂËå .M7|I–å%ç„õ–b±m¿³ ÏA”“OÏmm[¶-//ãèÑ£¡mÿöþ=Ì‘³¾¾¿ÆcË®±ÁÔpm ©Éˆ„$R‚ ‰ ÛDMv=‰{ß%RÜ»ígßXÚÌ&@Bg¥'ïn²£¤7ÒæYzÈäIÒp6AµñrH°†.XB&nabì)Ú66'½Tߥ’Zg•T‡þ~®«¯™Ö±Jý«[÷ñw¯­­ù}NĬbºä¾kClóÁÚ…XßmmD Fd 0ÍŽX7 ®[¢ðÑ4 ±°úÑUÃh÷‘нý,Ën¤ò+‰LÓÄ/|ýë€{ê{w%æèQH?ö¯a>GqÑž2¾O¿¬Kh7X™ÊƒæÍ0 d†T@öu¤h2[];v ),ŬnônC¬‡îH¸$$ ¿}$"ÐEÂ%]ogËÎçt: EÄzŸôÙDAgYVï©5½ö]uîÝY³‰‚NtÎ\ÿ¹Ï…¶"6½—¤ö4|1Õ7ämpòaxöm·µ§¾÷H®gl_‹Üú1HÒäëóD½ˆhžLÓì ÕU1zb¾µòk°, òˆ±.–ÀŠz?…×Ðk<w²‡•{ôIô´¸7ÎîÀ91DDålƒ0`]^Y–=šµ±Êç92MW--¿ñö ÝIöˆ†ê¤Ë;²YVæi¾zngÓ‡$Ùåf±·CÖÇ›&’ OÓ©CþyJ°P«ÕpîÜ9ç÷'N ™Lú}=‰-:úícÆ=ë(*ÌhXß~°·™HÌ)Á&†aà·Ož íâëbѾæØX¥A:²§º3¥vÕ¸½X›ÇQ}š·¾Ù»ˆÑI²GZ%iü¬è²lgYߨí×aŒ«®ë8}ú4FÇíëëëˆÇã(‹›&¬ªö=õª]ÈFŸ å”` )i„nCóc ò±WÁÊÛ>ÃÂÆ²,˜¦‰ø­··Þê÷á Õ+';Ji†a´§Kªj»¶ÞUÖ{1+^Uù}@ó¥ë:r#¯+ÿòùñ;ûDƒ—Õp)Kp­VC.—ÃáÇQ,a†óS,qøðaœ]‰Å¼*î™T,ü†6Xëõ:âñ8âñøÀljõ«ÍfÓïsrˆÄî«,»¶º‰=ÌÌ } ÿ½ø6ÍΌع§'Rø8Õö¶hš}M2eÈÍÙîõ ¥ù†_€vÕRÇã… >‰PuH¥:àj]rÒ# C¬±X »»»~çDÄ”G÷è“,·—€HÏü&çDRt¹¦ÕT* ÔL†{°R¸tdÂ`o‹,ÛY(‰¦ådPu—áz Œçvt<º·è# ‹ŽýWÅvb6˜kV§¼“ÛÐk"‘@³ÙÜ—¸›H¸‹Åü>'G¥Ò{»çzh6Ù`¥Ð3\¼ë¿vI¿×‹)ö& +§W¾#ÈýU,ÚÓ€ûRã× yÁi°ºZ£b6°{ p€.¢‘uŒ°Z–=ŒêÞÂiapÊ;µÔ`M$Èår}§û6›M”J%$“É@mmcOÑÚ¿k>ïšÉ)Ár–eAUUT*v—ý÷Ûÿ²2Maæ,ípM“œÿ1´¨âw&ó ¯™¦‰W>ü°Sh‹Çtº³wÇ"QXtä•qí3i~ì{¯xçqœA@m#e >uêNž<‰ÍÍMg´µÑh`ss'OžD£ÑÀÊÊŠßçÓa_ïcWWMáŠwû}ˆDž1în@¾Ü5boÇmŽ®R8ÉÅÜûÌ‘eÙK­ÜmåB*òžišxñ‹_ì—¦ÙÕî5«ƒÄQÇt`û'΋¿õ4Ÿz‡s·Þ#·§ò D"µµ5”J¥ž[×$“I¬¬¬jt° w]×Û iòy@’P­Ú‹X•S¼:Q0ˆÞJóノê‹îàZœ*Ë0tN$ heÙ—ùí†afe2¬@Ñ©*,Ëy‘Ì˲Úý5ì,¡°Ù7ëÑÕù¨o] é’ù}ˆP#5Xv£Ul]S¯×éÂÃ2û­c®¼aé4L0 [àÀ…ø0m–ÃØk î¥×Ó²œ¶Háçä#0Œ¹µóy{tKQìk(à[ÀRˆiš= ,—ÛÛºi¯S¦RìŒ;Ñq°ÁJáÓ1ˆÔµ…Mõo®B6{•3èšJ19$µÜ`Ä7jWw³ÙD½^G2™ôûœô˜,jñ…R©ö¶œ*IQ I¤ïý°±ì"°µeßnYû×=…‘X«bqn5uY¶¯%^?4k†aÏŽ‡ÈËa†Ý›cY­S×:o¢P³,Ëž&†v†w¢%îcFQà$ê˜c-&“a£€æC–í²úþÏïë^õìP—¤ÎTUûvŸ–rMÅÉ€ÝE$Œt×Ë9ƒ€Üõ©—£X´'tÕIb†ÂÇDrÑ´v狨»st•º=%8,º{%»KwóÜðŽ<Ò ¯õûP‰¦"Ë2ÿå?hWh¬Ï}æw_ÀJ E‚ä®ÑÌX¥ÂäJä§=íWPÌ¿Åñ¿PøÀOì»_’ìÊ<㓨×èªÈ€-ˆLInm°–J%¬¯¯wÜ–L&±¶¶6Òó÷vô€!FVÝ¥ûùóÐ>ÿtÈOoB½ë˜ß§JдñÝM’é÷ï¨ųIdb@æ¾ÃïS¥ÊËïHÔ1¦Ù¹½k.ÇÊ æužJ–³uSîU¤ŸèùXÑ)É¥Yñ:¾»ïØÒFìׄÎ鿺nw²³ÜÛ`ÝÙÙÁÂÂBGr§X,6òóEB¥^½9øüç¡ßÿ6än|ÐïÓ¤jÚøDE^tÐÈ2 ]õ-À²þ鋸„|âUŒ ò 4™¦=íRßÛúÉ4ííCØ a¼Œoäg<Ž‹wÜ40t>¤ªÇ­–ߟE•×å7`/_êèx¬T7ÒåÎ1¥tÚ.—Y“ÛÐk½^G©TúBÍfÓÓÛÝÝE2™œ8ë°ªö_°­&wQ¹ß‚üê==f¢QMßn²,;Se€ª"óDÖ“GÀœä/cÜÙÒÆ½ å”4Í®e2í=.‰Fåe|+ °ñc¿‹Ïm~ßÅv`ÊLÆ"š/ã[èH¸¤ë¨M:À¼ŒqÓ4íž~‘JÒù¼]QâZ@š„×e8L[/|!ûÿÑ®­™)¶.#šÏãv9.fÊPù‡×¡Ze¶kÍÐk"‘ÀÚÚÚÈ?^óç›Í&–——±¹¹Ù÷±O<ñ¾öµ¯9•½§ÙÞÅašÝ‘ª ¼èE>|ÜFçÏŸÇ#<âëqŒßðøã£V«¡Ñh8·‰5Útu·sÞV«ÕpñâE¿cª2¼'SGno³¢VõzçÏŸÇîÇ1N|÷*¿…b0~ôøÓG齌‰Q~{=sq\^—ß–e!ŸWJ‹…c(¿£Î2øuðqËï¡S‚kµ–——ÛÉ‹`o½^÷tDµûd–––pûí·;sæãñ8J¥z>ç‰'žÀƒ>ˆsçÎ!™Lî%0ØË,išÓô/ß<“c§àÛÙÙÁùóçñØcùòþ“Ä7`WxÎ;ç<°¿TU…qjŠ{¤h/‘LçÎóµ²ãEîf~ámoódc>Wž )Ñ`õË$ñÝ«ütH—0ßiÎ4¹…ƒ(¿www§^7: ¯ËoÁ4ÍöTßìÄ‘¨ƒk¢)ÁgΜÁòòòÌN&cee¥ãB]XX@³ÙìÛ{sýõ×CQ¬¬¬è\r5¶½Ä4üN8°’É$Þò–·à%/y‰/ï?I|Àsžó¬¬¬ìû2xì±ËÿÂm¾œ ÓÊÊ nºé&ßÞß‹2¼ÛÍ<2uƒUÓ¸ö/ ð–·¼Ï{Þó|yÿIâ»_ù ˆ¥ÙÖL‹Qøˆò»»cc^fQ~ö³qùå®ûL“i€(Q·üöl «—jµÚ¾©bèx¼LÁ{[!XÖ¾ ã¿ϒ*¯â°{,¿ô¥«¡ß½ÌI{Ä´ñífYŽÀµ×ú}ZD/cØ+Ç{t<Žÿ:žÌ*¦ÎËø6M@º´Ù±ìŠÈO^—ßpñâýxÁ þÁþElk@4†@îÚH$°´´„“'O"™LbgÇ=*‹#=ß4»¦{PÑ!òÊ´ñÝMÿÌ!ÈϽßïÓ"rxã–eÙÿ1Œ‰+9ºnOæè*yÁËø6M@yèáÉ„úS?å÷©y^G€ï~÷Þþö½z8«4@6X{ÿ‚s¡L’àÉÙ»#¬0^Ä7°7ì¥_…üªËý>%¢žÆ¸¢Ø-Î †G+; ëÆ†ßŸE‰wñ HÍ¯ÂøÚ×ðSL®AáU| ÿøs‘N3¾ir#7XÝI–DöÉ^‰—¼ÜÚ&O´è\’ìzaXvE‡sÀ(€&o7EQ`î‚ô’+ü>¢}¼ˆqG.7ÖÃóùvFàj•_ä=/â;ó†ûÿõ),Zq +Š—å÷>û6(2ë)4¹¡ ÖÇciiißí³ÚÒÆ Šbÿh ™&SS¤ÉOÞå?è÷aÍ„“ ÃÀ“O^É%!i–eAZ\´3'õ!Iö–5ÌYC¡bYPO /ÖiEÐ?}õR~õa¿ƒBn¤V]×qòäIÔëuÄb1çö••œ:u Éd±X ÷ÜsßçÓqÌìœñDdYþõ[nB.Ãa%:¸Ä®el¬RØäß}…“ýš‚)ª”Vß÷†ëü> ¹‘¬«««PUwß}wGŠëD"……¬­­áĉ8sæŒßçÓAQ`qÑïÃ š™ø‡?lo4IA–eáÇ[­IÅ8˜ÂÈ4ý“ÏT†ap„•"ë®Ç/¾ã¿ƒBnhƒµV«¡ÙlâÎ;ïø¸;ï¼ëëëh4~ŸS'® ¡ˆ2Mÿù¯o~IÊïC!š Ã0ðò«®ê›¬Ã0ì‘UÖõ)lÄÁGX)Ь¯<ŠO¶^è÷aP m°Öëõž›‹iÀ‚¸ggÇïs`Wæ=ú¨ß‡A43–eáË^ùè3ü>¢™¹éÛßî»w_w¥Ÿ(,ܱkŠyíDó±¿~ÿIÊù}C“.Åb1ìîîî»}mmÍïcÈ4M¼é9Ï®½ÖïC!šë›Ï„|ë‹ý> ¢™Ðu+/ö)£i@¡à÷QG´OEX3C0EÕg¾ô <ÿÄ¥~EÀÐÖD"f³‰Z­6ðqâ~÷¨«ßžÝ£¡M†aÀzì2¿ƒh¦=úhÏ«¦²)”4 HÿÀ—|º®³ÁJ‘uøð§pôèü> Š€‘¬‰D¥R Íf³çcšÍ&J¥’É$‰„ßçä¸âÁ™:’"KQÈ×^ðû0ˆfÆ0 |û¦›zÞ§ël°R8é:¾tÓéˆaÂ%ŠªÏ|æQ¨,¨É#e >uêNž<‰õõuÔj5ç§T*áÍo~3VVVü>‡axæ3ŸÉl]~ä+ôû(ˆfæÅÍ&b¯{]Ïû…ëW)œÊe@¾°( GX)²*¿óªÕcì!O ]à أ¬gÏžÅúú:J¥Ò¾û°´´´/1“ßnh48ÂJ‘dš&®ûÖ· Ýô,¿…hfþòá‡û.RÍdü>:¢ÉÈ2Ú)®5 VŠ$½¼×^(@Qt¿…"`¤+`g>uêVVVP¯×Û‰D Ö­vÈd8ÂJ‘dš&޽þ{¸ë§¿í÷¡ÍŒÜgíªe±ÁJ!fšÎt`Ã0a0SĘ&°uÿuøåI¿…"bä«‹ÅL&ý>î¡ Ãà|1Š´ ×^ËE|Y†aôœJ–ÏÕªßGG41º {{2ްRÔhðÿ¹ì½xìG~ÄïC¡ˆi kqnŠ2Ó4ñ±ý¸}EU¿Š|µÚw—¢pèj°EMå¿~¯” ®_%ÏD¶ÁJe¦iâñDzâN‘Õøâñš{ïu~¯Tìóz{ VÓ49ºJ‘c€rÍ—ñhìa‘g"Ù`59ìDÀ/ÿò—ý>¢™ùö½÷"qà €lÖ®EB: È2t]g…ž"G’€ÌwÿþÇî.·´!ÏD¶Áúÿ}øa{=QY–…ýpiú" ¨C_ù ¾sõÕÈçí$Kå²ßGD䑽$K¦i²BO‘#KÔØ94/½ÔïC¡‰dƒ÷`¥HûÒV ks«ß‡A43ß~è!üÖƒï‚i²±JѤë:¬=ºŽû_ô"Î OE¶ÁzèÑGÙ`¥ÈzîîÓñ´ë®óû0ˆfæÿÝùUàúë±±Á¢œ¢Ç²,&¤¡hRüå ^ÀõÙä©H6XEÁ‹®»ÎÉÂG5_}èYÀ3Ÿé÷aÍ„®òwFyýr¿…h&¸~•"K–ñ•K.a|“§"Ù`•$ W<ø ß‡A43¯|Þ@}Õc~ÑLüàuŸÅÏJE¿ƒhf Ã`…ž"‹ñM^‹dƒ÷> HûÞå77Þè÷aÍÄvµŠÝ—¼Äïà š®_¥(3M“SÞÉSo°Öëu4ñžÄý($&Šoæ?>êO_ë÷á 5IŒ_ù7ƒG®¹ÆïC'j’ø¶, X¡§À›$¾9ºJ³ðt¿ ŸF£\.‡z½PUÅâˆSÄ,‹ëW)ЦŠoæ7odްRpMãëG2aÚ4ñÍÑU ºiâÛ0 –ßä¹Àް®®®"Ã0 ÜsÏ=¨×ë(•FÜwR’8%˜mªøPNüŽß§@4Ð41^(ÙÛ«’(ˆ¦‰oŽ@QÐMß™L…BÁïS ˆ dƒµÑh V«aii ‹Å°°°€jµ:Ú (г17QÐLßTƒ i(¸¼ˆq¢ š6¾ Ãà+Ëo ¢@6Xwvv‰D¹-‘HL´Ö/Ì677ý>O‰Bð c|Û¢Q»f'Å·E-¢xÍNbÚøÞØØýúÕ(ÆBÔ®×I±ü¶E-Â~ͲÁ:è¢h6›~ÞÜèºî÷!xjggçÎóû0|Çø¶E1¢vÍNŠ1n‹Z Ï<þøãxüñÇEü~y衇ðo|×\s VVVæþþ“Ä7`§‰ýë_C‡á9ÏyÎÜÛkA‰/åš=þ<ž|òIßÞŸe¸-(ñà• \³<ðšÍ&n¾ùf_Þ’øfù|A¹^Eùý‘|ozÓ›æþþ,¿mA‰¯åšuðqËï@6XÝÓºÅãñž·¿ýíoÇÛßþv¿h¨Iâþâ/þÂïC' ËpвIâ›å7…Ëo ¢@N >|ø0€Îi Fc`ež(,ßuŒqŠ2Æ7E㛂( Öx<Žd2Ù±àY×u¤R)¿hjŒoŠ:Æ8E㛢ŒñMAtI«Õjù}½Ôëu,//#£Ùl"‹amm­ïú>¢0a|SÔ1Æ)ÊßeŒo šÀ6X{á·XœL&ý>"O1¾)êãeŒoŠ2Æ7I ¬DDDDDDtpr +Ñ¥ïz×»Þå÷AD]­VÃ%—\Òwî½^Ç·¾õ­ž÷ºo”ûg¡ÙlÂ4M<ûÙϞ蘂xN4¹iâÛ‹ûgaPŒ‡ñ|h:ƒb<ŒñÀ2œ„ƒV~;¦ žM‡åwðÏi$-š™÷¿ÿý­×¾öµ­cÇŽµŽ;ÖºãŽ;Z/^tîßÙÙiÝvÛmÎýwÝu×H÷rÿ,\¼x±u×]w9ïyÛm·µî»ï>ÏŽÙs¢ÉMß^Ü? ƒb<ŒçCÓãaŒ–á$´ò{Ø1ñ|h:,¿ƒNãà”ài6›(•JXYYa¸çž{œÛ„ÕÕUÄãqçþz½îÜ?è¾QR©„F£{a c}}}äc â9Ñd¦o/A1Æó¡É ‹ñ0ÆËpfù=옂x>49–ßá8§±øÝbŽª{ï½·uìØ±ŽÛNŸ>ݺãŽ;Z­–Ý“qìØ±ŽÞ‘÷¾÷½­[n¹eà}Þ;+/^Ü÷ž;;;­Ó§OtLA<'šÜ4ñíÅý³0(ÆÃx>4A1Æx`NÂA+¿‡Sχ¦Ãò;øç4®§ûÝ`Žªd2 Ã0:nÛÙÙÁÕW_íü‰„s"‘@£Ñxß°çΊHmžH$P¯×Ñl6‘H$°²²2Ò1ñœhrÓÄ·÷Ï ¯Õj¡;šÎ Z|{qÌŒñð8hå÷°c âùÐtX~ÿœÆÅë,//;ÁpöìYÛÛÛ}ïk6›Ÿ+6xöÚîîî¾sÙÝÝÅÚÚÚРå˜ý8'òƸñÔxãa<òNwŒëºÞ÷±A–áÔËA(¿‡Åwë\ä–ßÁ<§qq ëÜ~ûíXZZœ9s€ý<üðÃ}ïÛÝÝø\Ô^s÷îÜ}÷ݸûî»±°°€ååå¡ç3Ê1ûqNäqã;¨ñ0(ÆÃx>äîc<° §^Bù=윂Xç"ï°üæ9‹ Ö9H&“XXXÀwÞé,v»÷z|?ñx|àsãñøLÎáĉàL?ìB Ùl¢V« =¦iï§à7¾ƒƒbü’K. Ýùwºc4–ßÁ?§q±Á:#'Nœ@­Vs†ñ@×uçÇ‘L&±¹¹Ùq*•xß°çÎJ"‘Ø—B»T*9=3Ó³çD“›&¾½¸Åøk^óšÐMgPŒG-¾Y†,­üßA<šËïàŸÓ¸.iµZ-¿"ªVWW±¹¹‰d2‰ŽÒ€='}yyñxÜYÔ¼¶¶†X,6ð¾aÏñž¢—jœóñâ~ –iâÛ‹ûgaPŒ‡ñ|h:ƒb<ŒñÀ2œ„ƒV~;¦ žM‡åwðÏil°Î˜;ez¯uÍfÓéê¾Ð}£Ü? ÓSω&7M|{qÿ,Ìòšd|‡Ï c<° 'á •ßÃîâùÐtX~ÿœFÅ+×°Q ±ÁJDDDDDDÄ+¬DDDDDDHl°Q ±ÁJDDDDDDÄ+¬DDDDDDHl°Q ±ÁJDDDDDDÄ+¬DDDDDDHl°Q ±ÁJDDDDDDÄ+¬Dä]×aY–߇A4w^ƾeYÐuÝïS"""š 6X‰È7©T †aø}Dsçeì†T*å÷)ÑV©T`š¦ß‡A4Œ÷ùcƒ•ˆˆˆˆ&¦i+ðt`0Þçïé~Ùܽ5™L²,ï»O–e¨ª ]בÉdØÓÊÄT°t: EQœçåóyär9T*X–EQN§×“$ ¹\nâÇjP|@±X„eY=cÌ«g|“fû…BÅb—\rIÇó,ËB±XÜ÷¢iõŠgq›¦iUU;âSQç6–×&“Æ»¢(NìJ’„L&I’0¶'ÅÖÈf³(‹Ó4qüøqçÉçóÎ}š¦aqqѹHŠÅ"Ø”ãÇ£R©8¯+î·, –eaqq±cZ±XD>ŸŸøñD£ßâ~±–¯_LÓÇ8ã›æmÖ±ŸÍf¡i|ðAçv˲J¥œŠ‘W†Å³›;>ÅcX^S˜Lï_üâqäȧ³QÓ´Ž%Œí µÈW[[[-­íímç6UU[¹\®µ½½½ï>Y–[ªª:÷mmm9÷•Ëå–$IÎïZårÙù]Q”V&“q~Ïår-UU'~<Ñ0ƒâ»Õ²cNü¿Õ²cXĘ×1Îø¦yšGì‹çW«Õ€Ö… öÅ5‘†Å³ªª­jµêÜ×ßâ6–×ÓÄ»(… .8õvñXÆöø8%Øgš¦AUÕŽibÕj€ÝËÒ}_:†aÐu²,wd‡¿†áô¬»Ÿ+I’3%¡ŸqO4È øTUuþï~Ü,bœñMó2Øw?h'r* ~Ÿ>EÌ(ñÜ­;>–×ÓÄ»xN6›E:†ªªûžËج6hËÓ4uJn½¾ ˆÂˆ1NÕ¤±/Ö f³Ylooû}DDŽ,˨V«Î2>˲ÉdP.—ý>´Pcƒ5º¦º®; ¯û5ZE$I½6ݽïDAÐ/¾Eâ°~ãvóŽýr¹ ˲ iš“„È+“Æ3QMï¢þ^.—Q.—mÇEáµ2&]òY&“q¦øö"q¸§ÿŠûDÒ UU;~Ú‹¾‰‚bP|ç0ó+ö%Ir²UrÛòÊ(ñŸw¦?…Ù4ñžÉd iŽ9EQœ™1étÚïÓ µKZ­VËïƒ »2"zÃÅ:%1L–egV±OÓÆÆFÇc€ö42¢ éߣbŒS˜1ö)Júų»¾Ò½×0QXMïbtV’$.cò¬fš&Ž9‚­­-(ŠÓ4‘J¥ËåØƒIDDDDD‘Ç)Áæž’ ¦g26V‰ˆˆˆˆè@à+³Q EfJ°¦ixßûÞ‡›nºÉïCñÌùóçqôèQ¿Ã3/^D³Ù ÄßèâÅ‹¸ì²Ë°¾¾î÷¡Œì–[n Ägç• ÅƒW‚tÍž?õWå÷aŒŒexðéš½xñ"$IÂïþîïú}(#aù|Aº^ÏŸ?ßû½ßC"‘ðûPFÂò;ø‚tÍNR~G¦Áúüç?oxð²²â÷¡xfyykkk~†gjµÎ;ˆ¿‘8–0¹é¦›¤kvyyÙïC Ëðà Ò5¶2œåwðéz]^^Mc`ùAºf')¿#Ó`¢(](L&‘L&ý> ˆ(ÆCÔ®YšNÔâ!Š×,M&бµë•¦µxû5Ë5¬DDDDDDHl°Q ±ÁJDDDDDDÄ+¬DDDDDDHl°Q ±ÁB¦iÂ4M¿ƒh&,Ë‚®ë°,ËïC!""""ŸqÖ², ’$õ¼Ï0 ,..TUE¡P€$IÐuº®CQ¤Óiçñ½·¢1 ( 2™LÇcu]G:îûþnÅbªªBQ”}ï§(ÊH¯AO¥ReYH§Óeٹݲ,‹EhšUU‘Íf‘N§¡ª* ÀeY0 c¬÷’$©ã=ºŸ/®w »+®w,ëºÞñú½žKDDDDÞ`ƒuŽLÓD¥R …}÷ëºMÓœJµ,ËeªªBUU躎l6‹ (Š‚J¥‚ãǰ¯²,C×uäóy(ŠÃ0 Ëò¾ µx]MÓpäÈ §Á›N§qüøq¨ªŠt:ÝQ9Ïd2e†a ›ÍBQ‹E†áŸ¢(eÙl¶ç{»†Ó4‘N§;^[4¨Å9‰ÏN„^ wÃFQär¹žóçÏã‰'žð;$"EŒŒ†Ñ³X©TœN#¦i:wEQ ( ¶¶¶œ¿Y¥R®ë$ɹ„Q‹"÷qY–MÓœ÷×`ljªª$ Åbщ?ñq|"†EÜ»ß×MÜ/®ÑQйˆç³sˆˆhtÝuQ‹ú‡$Iû:T'!êtâõºë-îï3NýÏ4M|æ3Ÿñûc" ”KZ­VËïƒðB­Vùsç°²²â÷¡ìcš&ŠÅ"t]G.—s’¹\ÎyŒ¨¼çr9§#ž†a8\¹\©’+*Ü£[>Ÿ‡ªª£­¢à•bq,¢â^(œ×w7Ýç^£»â6÷Ȭ¦iÎû‰Û%I‚išÎy»ÏÙýEãn<íJ¼$IÎë¦ÓiçµD#äk_ûdYÆ»Þõ.?Cc,ËËËX[[óû0öqÇ·ø’/‹NÇŠišX\\t:¦­ÌÊ ŠÄ0ÝI÷kˆ˜wwþȲ<Ñ´~÷q‰Ž~¯óÈ#„ªÒä2œ&'®q¯©~¯%:½^ñŠW„*^‚Z~‡U¯º`Ya2™ŒS×3xÜî2Tt,ŠïѡY–…J¥âÔËDY.f¦‰ïMÓœ<¢3Wtê»Êå2»s¶R©8ƒ›››¡Š–ß4މâ¥÷Þ{oëôéÓ¾¼÷öövkkk«ç}¹\®¥(JkccùíÂ… -EQœçd2™V&“ñåØ'9×°ÙØØØ÷÷ñ3^&uÇwøò¾.\hår9ç§P(´ªÕjëÂ… ­B¡Ð’e¹#¾[­Vkkk«%Ër+—Ëõ¼Ÿfϯx™T¯É°èUNB”’$µTUm¥ÓéV.—ëù½páÂ…V&“i©ªÚÊd2-EQZŠ¢´ªÕê¾ÇzlŠ¢´Êår+“É´âñxëï|§ßíÈÂv=úi{{»µ±±ÑºpáBÇí­L&Ó’e¹•N§[ªª¶TUu¾k.\¸àÔ¯ …‚¯²,;±Óýšƒ¸Ÿ_.—ÿçr¹Ž˜½páBkcc£•ËåZ­jµ:R])“É8×¢(ǶxaùMã˜$^|\«ÕpøðaÄãñž÷×ëuÄb±¾÷èÉ=kÝ£ƒétÕjuß(`¹\F6›`÷ê‰^¶  êèØ î5½ó…øÓ¿ÝSiEOq±X„,ËSx1µ·X,ö¼Ÿ¢! 15î–e!ŸÏ;³eªÕjÇc‹ÅbÇÔGñxI’ö-[Ñ4 ù|étÛÛÛ$ÉerçUà̲ß‚(OÄŒžJ¥âŒx‰‘)ñý)fˈ< Ý3Äì£Yal÷&fŒx½~_ŒBŠÙVétÅbÑ©S‰ÑIUU÷Õ—Dþ±D*—Ë9qR(z.Á…¸2™Œ³Ôª×÷™˜ò;n]£\.£X,²,lmmyöYŽŠ1NaâKƒuss¥R ÍfL&Q(‹ÅF¹\õz€ý%X,ýþ¬œBQ¬·à|‹)#£®Os'^Æ7<þøãC“$ “Íf;¶PUuß^µ~µZ /^œùû¹ Ÿ·^sÑ ,—ËÎ5&˜ªª"›Í:ës¹œóüQ+øårÙI4ãÞG¸I’"‘­^¯ãüùóØÝÝÙ{±üö‚ØZÓ4è¹ÖX¬ µÃ¢P(8k’»GãÙXŸ(¿‡ÅÔ´X~î½äÝ·‰5ß"q¬X[ÞmÐzâµz}ÿˆ™?b¦…¢(ØÝÝÅW¿úU=zt¬sðµÁzûí·£Ñh`}}gΜÁÊÊŠ³¼—ÝÝÝ˃>ˆsçÎM}±d³YX–å,þïÞ_”ÂmggçÏŸÇc=6Ó÷ñ2¾»ÂsîÜ9˜¨ÂS©T|ËFHóuîܹ±æ• –áó&–¥ÓéŽQN‘7•J¡Z­:Ó.ÅÔÈB¡€l6Û³¢? ‘q>•Ja{{{äç„h°ÎRÐÊïiˆFªHr$âÔˬÿ\åQ~‹©i±ü1ëͽ B$%»ˆ}Ý£•‚dàLïÙ·G½ÖE"½^ß^µ…jµ>øÁŽý¼‰¬¥R µZ õzKKKˆÇãh4cÏoA‹ÅËå°²²Ò1 ¡Û Bþú믇¢(Sϱ9å7ºD܉ÊìßÇ‹ø€ç<ç9Ç·Øìœq}0¬¬¬8k’f)ˆe¸Dv]Ã0œL¼b–B¡€J¥âdàvWì½X^¢ª*¶··C¹åؤÇgZ†©üž†˜n.v3àˆgð‰ò{Ö,¿½#êXbKܦiZGÃÒ4Mg /Îè£Ø¶I–eg 1w#U¿ûqbî<>|€=-A\îÿÏ’h¬íKáÔø.‹PUõ@Uji6‚ã³$Öô¹{¯Å÷„¨”ˆ™ ©T ¦ivlÃ"FOûM›š¯koD-¶Ýk£ÙP% z1>o¢¼I ½7½Hj'FIu]G:Þ—l¬{ .Ï—fI’¹$gOçÁbê@¡PÀÊÊŠتªbmmÍuäĉû§ëºs1Äãq$“IlnnvÜŸJ¥fúA°±J^b|‹ÖýÞ(z‚ã³$¦ûŠÑP1B*¾3ŠÅ"Òé´³F§\.;YUÝ2™ÌKb6QŠm6V©—(Åø<麎ÅÅE?~Ü1Õu•J²,ckk …BØÚÚB:Æöö6 …‚3ÅWüˆ†©hTºo£þÆa‹³{ÍOO$H$C×M%“I,,,àäÉ“H&“ØÙÙÁîînGoÏÊÊ –——Q«ÕœEÞ·ß~ûÌ>„b±èlYC4 Æ·¨PM+ˆ1>­b±I’ö­#Õî5¦årÙl‹‹‹0M³c]¸¢(#¯'¥` {l‹i‰ƒ*ÑÁöŸ÷šQ±K€‘·fŠâèfŒÕ`‹­{e k6›#¯™:uê–––ú6€‰>ô¡9¯7ËÜb[& ¯)¾tLW$òBÐb|¢’/Öÿ¸×õË| tîSJÑæØ^\\„¢(ØØØà4qê+Ì1>K•JÅY>´;2¹‡p0ŒÕ`£¨ËËË8uê”s{£ÑÀéÓ§©£ˆÇãçċ͌gMÌ1çèy)(ñíNYN䥠ĸ´Ä>Äb›™­­­¡US|£)Œ±],!Ë2c’FÆ÷Z¥Rq¶®4Mªª¢Z­²³' ÆNº´¶¶†|>“'O°Ó¯¯¯#‘H X,ú}>c3 ƒkû(²4Mã”0¢ŠÅ¢SIVÃ0&Þj†hÞÄ,Τ!Î0 äóygGOÃaìk,ÃÚÚêõzG–àA©°ƒ¬×fïDQÁ¢þDfGÑ£^(°¸¸ÈÆ*…J6›õ<Ë(QTˆ©¾’$9u~‘ ‰Âc¬k­VÃòò2î¹çžÐ6PÝØX¥¨S‚‰h?±gª“ïQ˜T*X–Å¢*•Š3û€:á6öÖX,]×±°°à÷±OMlÔKEŒo¢ÞLÓtÖ.±—ÂJTÆ™4’¨“;cvµZec5ÆÎ¼²²‚R©„F£Ñó1+++~ŸÓÈ8]’¢Œ V¢N¦i"•JA–e(ŠÂ}·)´ÜUVƉìFêñãÇ%’$ñúˆ±×°®®®Ö××{Þ¶++ôUº®³çÈ¥X,"—Ëqú$…š®ël¬¹ˆÌî,ߣkì«a~³'ØX¥(³, X™!Ú#¶.à¨*…]±XD¡P`ùN„á{fS4ŒÝ`€ÍÍM躎Z­ÀÞTXUÕP­kåtIŠ2‘ý”ˆlbt•(Ìt]–ït ™¦‰J¥â\l¬Fߨ ÖR©„õõu,,,`ii Ðl6±ººŠz½ŽS§Nù}N#áúUŠ2]בN§ý> ¢@po Of•J…u:ðòù<Eá´ød¬k£ÑÀúú:ŠÅâ¾/~UU±¼¼Œ¥¥%Äãq¿Ïk(n÷AQf§>Áž.–ÏçYɧÐ3M–e±ã…4MÓ`YËôæiãÒAcŠÅ"¶¶¶˜„ƒ"‡ V:ˆLÓ„aØÚÚòûPÈgc7X‰î¾ûnÔj5œ;wpâĉÀ¬vàëºÎ¹ï!ö×è8˜ªl6‹r¹ÌÆ*Eë.tišÆŽ0á>¬F±X +++€Z­†F£øìÀL>£ÌüÐu{¶»žjYö}{³À!Ë@Ô× Ã`áNN>Ÿ‡ªªì¬¡H2 ƒ±M’¦iØØØðû0(ÆNº´¹¹‰[o½¥RɹíÌ™3¸õÖ[±¹¹é÷ù tÐ+óºhÚlßÃ0ìi¼ãÐ4À4{ß.,.îŒøÝ4ãÇÛ¿W*öï©”}<Ѝªý¯ðÖ·¾Ÿýì‹fûaø€ëWé 1Mš¦±3’"‹;ÐAdš&$Iâ'0æk³ÙD©TÂÒÒ’3º kkkX__Çêꪓ˜)ˆDðD–d³öÿUuÿhäâ¢=)ËözÑa“x½\®³!¸¸ˆÎ0ðç~ŽaØ?…‚ý¼JÅþ]–íû+û5Åí¢!n¿ŸxmM¶¶ìQSUmO6Mû•qïÿçpîÜ—ýþ³xÊ0 VjèÀkûjÙNѧë:ªÕªß‡A4WœLnc5Xëõ:šÍfGcUXZZÂææ&vvvÛ`=Ƚ4Ţݰ“${´{)L.מB{ü¸ÝÌåz7ú,˽TU»™É´§Úno·gšvÃSPû'—k7ˆ»§èjš}Ÿ¦uNN§í×Óõömîïo÷qÔrº®è?ÈLÓ¾®Å´÷ƒ¦irVE–èhg‡ 4•J…É–È1ÑÖ~vwwý>Ÿ¾,÷P_È™æøÒtº=*¦ÊŠ`¹Ü¾OUí_¥b?®PØŸ¡·Ri7R-ËU5Œýàtzüì¾ÕªÝ`–åΑ[ =ºJ½Y–ÅŠûˆ‘þ 4 5­}­äröu(®Ûƒâ Ïœ¡èc"=:ˆÄŒ1–í$L´ëêê*šÍ¦s{³ÙtöaM$~ŸSO†aDbô)Ÿ·+¤½Ö|êº]™kHuÝYµ¬ÎÆ_¹lWr+•þÛLÆžn+¾'Åt^À®‹‘QI²™^%3¯Çdˆã‹R§LP‰YÅâh¯T:gô{½~, 8tÈîêþóºGUû×m¥|ìcÿÊïk.,ËâTxЬƒž{ƒŽ|>C‡!•J9‰ôˆ„‰÷aÝÜÜt§õz±X kkkˆÅb~ŸS_aî©1M»1*Ëv…´ûTDå5—kjʲ]YëBQÁ¶$F¼‡eÙ£žîQÚn^Ö#Яà Ó4YqŸ1˲×G‹5Öƒ>nM³×ë:³,»Ñ«iökˆ™Ý×u>ow*‰k°P°£(öuR­îŽèô¹õÖÏø¿?²™3DOQE¥³h±ßª$IÌÉAûL¼«®ë¨×뀅…¨ªèƪÙkH2Ü[÷ô\‘WT†Å4EwG¬,{35P’:צRp…¹S&(DB/Ó´g¸gˆuØb-¸¸þt½=A¼†¸_’:§ñ‹™étûº*íŸîëÕ=Ó@UíLjäh’4¸sçðáó~”sÁJ E•išl¬ÒáŽwŽ®R·¡ ÖF£f³¹oªoØö¼ó}ô)›8ÏÕ½ÍmqѾ­cTÕ4¡H€$ÉÎ:TI½èLˆ!]¯öÍÊfÛs½:¾Åí8|í”ÑõvK*ÀÄG4è0ŦH*&2P‹ßN^äV­¶§:öjÊöíÅâk>Å\b/ˆyËÀà…y£ÇU© ~½qjšÖ>ƈñµ°C„^pïÁä!‘H,•²_¾{M¨hlŠ­TÕ¾®Ü!mþÆ9ç)étûúÛ5årý"îkØuÏów-t Õ±ÿœ"ãR*åÝß"à,Ë⬊,Ã0B50@4)vÎÐ0C¬ñxÅbgÏžE"‘Àææ&Nž<‰ÕÕU胲‰Œ ^¯l×ëu4 ONÔ0 +6ªj7–z•d÷èIß6¤Ø{Æõ%¶¯A;Ž|~øTMë{ìíƒÙØè?"Z,ÚYd†U¨E¶šrÙnôk´Š,T£6÷ZGWVpùOLø¡æ@Åw¹<8»Ð8ÄÞFcSmíÏc¯z÷ÃpÂgkËž†«(öšP6ùŸ¹–µ¿‘(FW‹E@zêëHá×ö¥«î¨Oš&rz éJj_‹¸cº¯H¯](ìKÅ-fKHú^çÊ¡C½[Øn†ÑÞyk 0 ¼ý£õæï1À®r¹=zêî…­hEi/í÷Y‰¬Nb˜·Rig>i¿Ý×¢èñDz±ž<‰c3úsûU†wãëâ‹d”ÏH¬/½4#¾~å_Þý«/†ñÐMÀå—#ýsWôÌ ÿშ¼ý”çJìêWþ»³P—!ýÄ¿‚eÝä|}iP\ªC}ÎßB=ôä~ôJXO^J鹸rísxοºÌó,(±mÿI¸eSÐåóƒRöÒë²_€w+ ú RŒ †a ǽ i–î»ï¾ÖéÓ§[·Ýv[ë¾ûîúø×¾öµ­÷¼ç=­V«Õºxñbë=ïyOë–[nqî¿ãŽ;ZwÝu—sÿ-·ÜÒ:}úôÀ×¼÷Þ{>FQ”ñNjc£Õ’å©?›jµÕRÕVëÂ…VK¾êë­ õÙ}I§[­í}Á~PËþgï¿ûÉò€;]Ç­ª­V.×ÿq.´ZŠÒjmoï?`ñ|Ynµ …ÎÇomu>>—³ÒéÁD¹Üû¹’dß×ëøÆ•˵ϻZøÃâe³ˆoñ¼þo¹•ô÷ž‡jµ\¸°ÿïßï52™Á)—íXt] ét;T;^KU;oËåìç¥ÓíÿW«ûßc{»ó:P”Þ×S¡Ð¾zÅq·­-ûÝw°#¸p¡÷uÔÇ x™–ex/j÷ß—:‰ïQ&*/\h—¡îï¾/Ÿ¹þý­ôËë­­BµÕÊåZnG+wíï·¶NÜÑj•ËûCµûûf [Õj«<Éu4„åwÏóÛÚj¥‡}¯Òض¶Æ CqYÈr»Jä|e”Ë­ú/­ŒÚ~ÁLƾtú…f¡`ˆ×(—Û_I­Öƛ϶Ò?ô@ëÙÏþêÌ>ƒ ”ßn²õmòÐ… v@ŠºÍ¸uòß“ÄËX Ö{ï½wßïïyÏ{Z§OŸÞwß ×8vìXëâÅ‹Îm;;;­cÇŽµî»ï¾Žÿ ï}ï{;.¦IN~¬‹a{Û.qTuê/Øí÷}²µõ¡V«Õj•O~¼•yemßc +;vÃmX£ºWe>“±oÏåìÿ÷j„ îÊH¿ ø “4"jV ÖYÅw«5¸Â“ËåZÕ^ ¯~ÆhøŒ¥_‡J:ÝjÃßSU[­jµ•N»ê:ÖíÕ?¶c×Õ.—÷ÚÉ¢V¡(íZA¿÷ ÇA1í¾ŽfñYÍØ¬¬~•á½H’4ÃOpζ¶zwžtÛÞ¶ã;¶Ë|QƒÞØèý|wCTU[Û/»µµýêŸmµ¶¶Z[[ýCû‚iµ oÿ‡–¿¯¥^ñÉý2ÛÛ­òßßÿ·¶œ·Åå3‹2ܯò»—B¡Ð*Ì A~PlowVs¶ÿÏ?¶äç>ÖÊd:ˆÕj»¨}œ"Ô·¶ì׿_¸`_nêË¿n_CâE\/Z½ñg*™,·ëüï}¬Ý¹)~ö®×ޝ¡½×û곟=“Ï%Hå·ÀΙ ‰²_Ðö¶?½:ÏËeûg”6ûâ,Ëvœ0 äôÚt_l.[Õjë¯~ægÆ:Ý‘¦»§ˆ=ït]G.—C<`'f:uê¾V"‘Ø·_ëÎÎ ‹9ÿwg%N$SÏ£kº¤i¶çwÆT7å?ÿ¯{SsãÈœ~Rñû:— Zrþ1{.£¦µ7^ìEL»uSÕvš`1}°Ÿi÷¸áÔ¤¡üŠï±‰iÓ"í¤ÄTqq¤Óvœºç4åóíiÝÙl{ªw7±NU‘kÛ˜½Ìb•{^ í[o†úKŸ@Nºš© ¿—E»\ ÉöUÓlOM´qð°9\îëžkkAŠñH¬yZ\l'2$ûéZ×ì8~¼=¾Ph/}K3z-Ë‘$ P@¥²7åð —ú äÅ4ð3¿…ì_.8[¢‰"AÓ]¿™Ìµ(|P$¨ü9{Íi.d222Ñç»qïÚ)„ìϤØ6Mé@¤þ÷Ÿeõ®~Fûë§»š&³Ø‚ãžÀ‘¿„{ªoùçÿ.繚àcƒúÕÿò÷=åÛÏÂÆç? GÍ._¶ ÈØõ*I²c?gþþ¹öõ&.Ë‚ºa½XñQ,òóž„ú_o~æß%{Ýqné4N£pé¥X›Ág¤oÿ¹×ðØDnY팑¢^Óë³T”vÒQQïËdÚù4Ü{WÊrg=-¶¿ot½ý}#¾¯ÜÄ.!¢¾ç¾½ë»é;W_/þðãucœòH Ö\.‡D"Ñ1‡]¬]¿¾¾ŽR©4´Á‹ÅL&߆ó¼x<ŽZ­Ö÷¹Íf³ï^¯?ü0 Ã@©TÂÊÊJÇ}co÷aí½-t}¢ ½aØÕ†a´ (IBáÕŽÅ¥ã¨~ürÈ2P9s9Ò¿ú_ ‰ K¥zo½R,¶“¹ín4ºZ­†~ðƒxì±Ç<íYÅ7<ôÐC(•J8qâDÇ{vŸgá‹iÚ…Õ´kNE)Öžˆ×Dvl‘ÒZìýÒÝy’͆üõeï*;ìs9;Æ»V˜î}qþ²<|ývÄ•J%<ðÀ3ym?Êð^|O46Šî BŠÒ´ºnßﮈÌí¦Ùdž,Z[€(d dȲŠÌÞzO]Ò°/3'ñ˜Ùþ:k/é?ܵ Å4±µÚ~k‘„lßg{Sï­-ÿ“PonnâÓŸþ´ç¯ëWùÝ‹a(Oœþ?œÄ6~ét{ýLê _Dá·.…¥¨vÿç%¢ðÂ2¬/ß ýª7Cÿä3!Ëí¯í—Ï¡|ÀÖDóPÚûœ>KãY€ò>ç1wk¸[¯¿KÇ) °‘3ìï·;2#/Nåw£Ñp…¼”ò»ó£6Ø9#r´ˆA¨½gã÷tº3Æ*•öFï£pwÒ‹ü©½äÃr†ªÚ[HÓlçôè®u=GÔÁÇ54Kp­VC£ÑÀ©S§œ—f³‰z½Ž……'xÐl6»[³ÙD©T­·ÞŠd2‰S§N9·÷³»»Û÷¾+¯¼7Þx#Nœ8Ñãsì܃Õ0†ìš!‚D4X{°=Šè°È½îܾ?”RH#wû×±¸¸3g¯„´ôfûNI² Â^YoÓiïö6=à>Œ£Gâºë®›Ù{xßpÕUWáĉ8|øpÏûÇê¡´¬v­vÝ+ÝEÑÓ& UÑK×}]•Ë0ñ¿Âøî+ú¼È5T,Ž–¤šÚNœ81°òì…y–á½øžhlâ ^ütgÔÓuä¯ûïNæÜJíZ]_ú"‡×ö¶}—h„Šë¥»G–íKo{ÛndŠ=€;t}~=’Vï³7`ë«D"£GâꫯžÉëûQ~G‰È7 Ñç MCîÊ»þtäˆ}5ûg(üJÐ4X¯x-”ÍS(\°~êuŸEáίakËn ‹À⛟Bæ©Òè{ý š…3N²~²Y´³üF”ß³ŠoÀÿòÛí@lߤëvP?nÿtËdÚ[܉zT¹Ü®_u'ÝÚš|Ö£˜*°½ÝÞ6aZ}¾·zuðqã{èk½^G2™ì¨üˆílÜ6Nå¨^¯cuu±XÌÙ.Gpÿ¿Û ž¦+¯¼Ï{ÞóFì¹´ Ô¾å™aØÁ#‚¡{>Š‚—¤}#TÖgïGêm‡PøÕK¡œßÜß¡(È(€ôJû×}e˜¢ØØ@A¯˜…H<ÇÑ£GÌÓ˜E|v…§_|ã4<ÅôC¡ß|«ÅE»ðqǢ虽}î£ÚØp¦ÿ?ÞnÓÊ?ûjT¶ý0Q¦æó³Uh¸d2‰k®¹ff¯ïwØßCh°ŠY•Š]Þ» õîkCôÞ—OQ*Ø“Ôý[uçó‰Î݃°ýf´»¿n‚>ø¶¿´7÷<û;öç©ü×ÿéyOB) ì› ó‹ö?é4d˲gÙôngðÇlÒi¿?ž¶~K`å÷¬:ƒP~‡–eµgΈYc½ÛîNùJÅ~¼;“7÷îÛgÙ˜÷á‹bÒ:øÐÖX,¶ïEëõ:‰ÄÄ“˜b¼¶¶¶ïâ½îùòÓN‹Ðu½cê˜{ ™žÜz1<ï&zÌ66öõzäúËP¯û,Òô–ö¶=ˆ)/=;ÝþEEƒÍ;¾1×ò¹×h÷e²˜ ˆ¢TÊnmNRîÀÙ¬ýôA³Q2àÂ…hW¾ÃÈïeî ÖK.iÿ:d_îeÃFQ2g »ãT¬ws\ öµÁ¯ƒù Bl½ÁjY@êFæéÿ[Ÿú6,˾4 @: õkïÃÆ?ùÇ_ëçï‚¶þ¸ó\ô”½Ïzùe%”ŸZ‚ü‹·Øõ©a׳$ ÿ2èµ¶Ž:!ÆMÓë]Ûö•ÊþÙ–íDíïæS:šH$œÍ…E¯¦®ëûÖªŠ©Àæ»èºŽF£UU÷MN&“ˆÇãH&“ØÜÜtæÁ뺎T*5Õ‰º/Qžu4u< ýD»„£¨bn¢èL§|V®€T PÓê^¥ã5^ü}(düˆï±FWí7lǸ˜‚ânxŠQÔ­­öœ\Q“ÓÄÔÞ1 "G“˜ñî÷ÔBŸ_ex·™ïÛ×ë ¢Õrþ›ÏÛ_Ýæ¢ŽÒóKĽúoÖ ä—¡§·P.³n$A‰mÀ‡Î˜1hw~|™ÏÞH×:SÉ;ˆuw÷5äé)È/¿ ² dßú0 /»(¼ÃïÓ8‚ãP©T‚¹ÿj6»¿sÃØ›æº63û±‹‹íe{²<ú”tÙH Öd2‰ååe,,, V«¡Ùl:Ó›Í&Î;‡ÕÕU'Ø///ï»OT¼WVV°¼¼ì¼W,Ãí·ßîÙI‹völ°Š„KB¯¬¼{·¥R€7Ê'?N¦E:¸üˆo˲Æë¡t'’PÕý½ƒÙl{‘\.×1’ëÚéwÇÛí_±~\’&š)E„2°sÌ,é’¸&T:2™ÎJúâb{RH#’1ŠËI’Í<¥ZEŽ ÕÀ Jlϼ3fÜã¹»|P®ù2 Ïz=-÷³#õ¶HïúElüÁ›±ø/þ Òs.C&¨wxûyÑè‚ã@ïå…¾I¶€öÀT÷Œ™~=ìårçL4š‰‘² ”J%T«UÄb±ŽLgΜÁúú:’É$ # —¬¬¬ Í –H$ð¡}ȹ°¦ï.ü-Ëîýî[¿—åΠ½„îß÷T«€®_¨*$°±JþÄ÷ØY°Åº ÀŽw÷óEÖÒAëðúX\´ŸÖ]ÏKûû_®G 7?b¼—™4VÅtwUíY91M;η¶öwvöʉ'¶‰Ú—[«A”ض,k~°ENH§a)*4­ª —äÿòï°ñ†WBú©WÊh U7å×~廿­ï@&sý|΋z JŒ@±XœOnjض#“Ù?%Ö¤ºgšM²Ó§ÊÌÜH VÑHíeaaÁI‡í¥îÔÛÓ…ÿÐ1£¬‘@{t6C>^Æww졺+âîžE™(µH “ÍÚõýööc%G¤ñº w›É¾}†ÑN4Ö'hÅ©£êµ?$…ß,c{œz˜ò’NÃzé«Püù¯C{ôÒÙCKJ¥ÿóéÞ0“*íí¹D¡0ëŸÛèªÈÅQ(ì¯Û›¦]aI§9å+Fj°öÕsçÎ@Ç>b³Zˆí%÷?÷«ÓH¥8RDÁ1Uo|÷Œ‚1ˆÜLâ»`cÞMS,¶—~s*yMÓ´©+:–˜rÊW7Å‹Ìâ(f‰±“’fi¦SÝ÷_ó˜—¾[×/å2òº íßé·[¹ q ¹ÌetU̘é·^OìýÅ^ÅP©ÁZ*•°¾¾îü¾¾¾Ž¥¥¥±7ö‹{ôI¬)š¦Ò1ÉND³b2> cZÖþ™3b?HËêœIäMÓ°5n¸¦µ˜bo؇_ë‘—CyqÕLÏŠ‹˜-©i£ï¯N4©±gÌŒHìė˽ɾѲ÷rTÑ^gM4–eÍftUdÃsçéT?bc54Fj°®¯¯caaÁ™¼ººŠõõuÜ~ûí3ßœÞk¦iǯÈVº/VûíIé2p ,‘üÊ(9hôÔ‹™ DÝD…~è(”;‰†a´¬°oÖ4`këò½ŒñWrç{"ß’¨S‰] ˆfiìœ#¨Ø»ÈìŸõ¸w qÖÍÓL·m)«ÅÆÖ îȺ«H{½´´äÜ&FVÅ‚ì ëÞ\^|ƾ-Tm‹‹C_“×ÉXœJÅ“aOÓìŸ<˜h–FÞ·oq±½ÇŒeÙã®ÑU±6àZ«·—Ì=k@$†gç ̓išž}F£ãöõõuÄãq‹Å@M{ÇãðûÆ|Þ®½ìµB¥Ý‘ÓÍ4=ÍSC43Ná_©Ø-L7—c§&G¿Î™|ÞŽÕ´UòE¨Õ*{)”,ËšT¬xú N=ÛïC%šˆ®ëÃGX5‰2hŸ§ò Z­†\.‡Ã‡£X,Â0 ç§X,âðáÃ8yò$jµšßçãÃw¬ Ñu{ ˲ž|²ïó'LÔGäÓ´ã:Ÿ÷äå8…’‚¦WEG;û¤ãGìÊ­-6V)´†&£1Md¾³åŽ~*ÑÄN{‰"Y¡.#5XWWW¡ª*ÖÖÖöõþ¹o_]]õû|ØuvM{ »*/[[ö٬ݢ=¾çó¹¥…R&cg¼Ö4»Ð¯T&~©l¶…’(ú%¤©J‹öZír™• µ~kXÍ=ýŠE¤ýå~&ÑĆ.cÒ4®ã ž†6Xkµî¼óÎ[ZZB£Ñ@½^÷ûœ`YvÝ]’zôÈ‹9ñÅ" ü‚žëòL“ ÷(:Ö<‰…Ö@*5Õ4wÃ!šZÏé’ù<äŸL0X)úuÊTþÓ#Ðíã°þé[LuM¡6p «e±òA} ]ÃZ¯×ÇÇ>N¬_m6›~ŸdyÈZírÙn‘öé·,6X)<öõÈ+ŠÝh0ˆ5߆Åßý1l<ðC~ ‘'úM•,üÅ+¼ÀÛü>D"ïéº=ëѲ8ºJ} aÅbØÝÝõû8'ÒwO³½ìc†Ñ{Öd:Ík†B.žx^;;8)ˆº3¨?û;;‰Â¤W2š|žK3(:ú®ÑÛÖlmm‹žÎeìIDAT1Ó#õ5´ÁšH$Ðl6÷eî&.Åb1¿ÏÉѱ¤RÙ—XÌ>èÆ„Kt;l(˜Ü#Pú«ß åMÏõûˆ<Ó=URÿËïr¶E†iš½gÈ2§5ÒP#5X‰r¹\ßé¾Íf¥R Éd2P[Ûtд}=ñªÚ»3'•òû`‰F£‹Mó$;°a0áS÷>¬úý/bÇ EF÷«–Õ¡<õ7œ@@‘ÑwÖ#ÑFÊ|êÔ)4 œÃ¦Ý•sN¡§0q’І'=”]¥0°,fs§èq>i¹ é•ü>$"ÏŒ²Ï0Q?C“.ö(ëÚÚJ¥RÏ­k’É$VVV7ºª»çûö©Ùä󣬒Ä)ôB–åÉZ>& ¤ r>é:;V(ZÜëû¬ÏÞãŸC½ã&¿‹È3ûÖ°?n¯[%ÁH V Ýh[×Ôëugºð° Â~RUÕ®Ýôi°j¨¦9U¦$ðØ`¥ ê˜JfYÐu‰ VŠwÎÔ.AF5°ÁJÑѱ†•ëhL#M v‹ÇãPU+++PUÕi¬6›M'ñRà }ê¾^²Yfå£pè¨Ä™)Ì4;×j/.2çWG=]GYÊ3“5EÊßüÍË`ÜÓR)l-ü&ry߇D4;Ü?Æ4vƒµŸz½Žååe¿Ï§·1Ö÷M9PE47•ø1{*»/‰­-6X)$ ƒ…4Eγ¯¼ø·ÿÖžë^.û}8DžÒu½3C°¦q]ųk9ûö a•¤ÎUniC¡3`Ê{?Ý Vf¢¤ sgPÍŸI@ìU~‘gLÓÄÏ^[€rû˸.ƒ"É0 {Û&˲§w¥Ó¬xÐX|o°šF\¯×‡îÿ:Œ¢(‡MÝõ|f$¯Í:¾L”pÉ£¤ÂDó‰q´3¨j– å5Ïòû´é˜Wl›¦‰o¿õ€\ÎïS¦fž1žºä;ÑR:Íä146_¬F£ç4b±…ÎÉ“'që­·"7m!>â…ÁJwÂïS¦fž1nŽ•ËÀÆgÐD|i°6 èºÞ÷"X]]E<‡a¸çž{P¯×Q*•Æ~§’3 šÉØw[P,riMo^ñídÜSÕ}«ë@¥Òûy–ÅÆ*Mg^1.8±®ëìU¤™šwlÀ¹s1œ8q½ß§N„1¨VY~ÓĆnk3j 6›Í‘ß´V«uî‘êÒh4P«ÕpöìY@,ÃÂÂ677±²²2ÖÉ™#,HwÓ´g)°ÁJÓšW|{SºiZÿç0±Mkž1.H’„Ô_DõÓ×ú}úa~Äöý÷¿?öcŸñûÔ逘wŒ; —ØSNSðl„5‹!™LŽôØ……¬­­õ þö¾¯B"‘˜h½2BOŽi¶sÖpùya^ñ=ˆiÚSÜ{QÆ:MgÞ1nL°+=4SóŽmË®ùî?௻ÎïS§Âò[f¹MS:šH$°¶¶6·tQ4›MÄb±ž÷=üðÃ0 ¥R©ó"’Æ4í©“q:8jµ>øÁâ±Ç›û{OßðÐC¡T*áĉC;‡ {Oa:˜J¥xà_ÞÛó2v磮ê?ú•EÀææ&>ýéOÏý}gQ~ë:ðšo} ×\sëÜχ‚I”ßFñx|®ï=‹òÛ4M¤¹… íuðq a­ÕjûF*›ÍæÀÌbÓ4µxww·ï}W^y%n¼ñFœ8a'.pÖ¯æóûÖtQUnyvÐ>|GÅu>ôhOßpÕUWáĉ8|ø0»×2ñÄvŒwQû§Wè?>÷Ó¦9;qâÄÀÊó,yU†wÓu ý«G}9' –D"£GâꫯžëûzY~ †üÐwjœ9@Q~Ï;¾Ù”߆a@e¦<Ú#êàãÆ÷DS‚Ïœ9Ó3³˜ÜÓº êiºòÊ+ñ¼ç=Ïé¹t¦ ˜æÐEÞ¼Ž–x<î[ƒuÒøì O2™ìx\üÊ+{>¶R±ë?½¦³^}Éd×\s/ïíU.èºY–™Å~5X½.¿Àøä7qÓ!®_¥6Q~ûÑéèuù ÀîX/ç~.L¢>—ë,‰ÞG÷´„I§EH’d7XÙ"¥€ð2¾Ø-Ò®ø¶,;é’Ø‚¸ÛƆߟE™ç1àâÅä² òÝ,bû—_òŸñôø•?ŸÈK^Ǹ®ëxãõ׳§œ¦¸k<G2™Äææ¦s›®ëH¥R“½ / /ãÛ²,»uÚ5ìdvØ«*·;£ùóº 7M>zˆ Vòçõ/yâ‹xà¥/õûÔˆxã†aàeO=ÅD14µ@f°XYYÁòò2jµš³ÈûöÛoë5LÓÄ¡GõûTˆöñ"¾½m› ÃÞ©‹tížB™Írû&š=¯b°ã|í»d)€Kþò2¶+à&ÝÂeÿñ'ü>-"‡×å·lY¬tÐÔ|m°&“I=Ù% |èCB½^w7.Ó4ñ£W\ÁEOä›YÆ7àÚ¶i@Œkš=Ú*Â=XÉK³Žqáú¯~•Ks5ØÖuà_ˆ¿ìe~Ÿ.@óˆqÓ4qÕUWù}ª#7XÝI–D±^‰—¼Úgœ}]ûyéc—_îÉñyÉ‹øÐs‘ª®·GXM³wL×íÄDóàUŒßûþá·¾ûïñ~ŸÑ¯b;÷ºsøúßüoƒ(@¼Šñc.àÒ>™ß‰Æ1´Ázøða,--í»Ý“Êö¬OnwxÛÛü> ¢Ùé³F[Œ¨f2v#Õ4íéÀL¸DasÅ#ßÃ[N>Óïà òœrÇ ¤6¨r&EÔu÷ß,.ú}C¬ñx|ß&Àa`Y.;†›™t‰"H×u¼¸Ù^÷º}÷©j»+:îS){¿aÖ‹(lòý;(ï8ï÷ayJÓìòÙì•Ê("^uÙe\ÎAž\–`¯˜¦‰þüÏ3K0EVìu¯ …}·»¬Ï3Ñ…×Kžþt–ã9ºnÿ+3¶)¢ ÃÀŸ¼àì)'OŒ¼†µ^¯c}}KKKH$í„/]z-àö ×…ÐAdßå²ßGD4™·¾õa¨Oÿç¸Ãï!ò˜®™LpêKD^³,ËîX'òÀH#¬º®ãäÉ“¨×ëˆÅbÎí+++8uê’É$b±î¹ç¿Ï‡èÀ©T:Ïçý>""oÔþÏÓ¡ùŠß‡Aä)Ë䛾'ﻯoç?QØqº;yi¤ëêê*TUÅÝwßx<îÜžH$°°°€µµ5œ8qgΜñû|Aé%òšˆoÃ`•¢IÓ€¼pûÒ—ú}(DžÒu@yæßá²~ÐïC!šÓ4Ù!CžÚ`ßyçwçwb}}FÃïsüä 7ìz"Š˲pÛÎòùvb%¡Zõû舦§ëÀ³ŸÇÍo»ß‡Bä)ð¬{ÙeP™\€"ŒKóÈ+C¬õzñx¼cd€3 X÷ïììø}N€Ÿúæ7ý>¢™zÁ¹sPU;™’HàAº<ãb…‡"Ç0õÑ?Ãß=“Û5QtýâéÓL*FžÚ`ÅbØÝÝÝwûÚÚ‰„ßÇ?/Ѝ+ž|ß¹újärö«eÙ·†½… Q˜‰Äa–eqJEN¡Hü-¾Øhp„•¢É²ðàW°ÁJžÚ`M$h6›¨Õj'îwºúÅ0 {J^(Q×|ùËøâ¯†eÙ{±d[üNf¦ioÅĤE ìÆ7E–aàÓßûžßGA2Rƒ5‘H T*¡Ùlö|L³ÙD©TB2™ Ĩ«eYxî3žÁ+E—iâ}_ýFç+Q¤Ó@ZÒñ›¬ðP ËœîNÑ¥ëøæ7ú}!#íÃzêÔ),//ãäÉ“XXXèh”ž;w›››Îãˆhönüæ7Qúæ+ð{³ÉDG=“cST|õž{ðL®ñ£(2M<ø}߉6EÔã_ø¾tõÕ=×4í¦i;e2öí†ÑžE&IöcŠEû6˲+Iöýé4Ǭ¢f¤k"‘ÀÙ³g±¾¾ŽR©´ïþ……,--íKÌä—+|ßdE‡¢ì©+!ÇŸp€vnYv&¢°kmoã1niCQdøÒ«^ÅõÙYOûìgû¹Ÿë{¿iÚ?¢¾’ÏÛ RÑH—†{Ö¼û~I²ÿ-—;¦ºÞnØR´ŒÔ`ì,À§NÂÊÊ êõºs{"‘ĺU·W\}5¾óÆ7ú}D3c>zÊÏr~ß›aFOÞw¾óÚ×ú}DÞ+ðׯRTYš×_?ð!ù¼]g ÖtήýˆŽy¡W§û5²YûßBaÿ€.#7X…X,†d2é÷qô¬›nŽóû0ˆfækßy~ÌÕ9_©Ø>QT\ýo ~ë­~‘÷†¦q„•¢É0pþª«:2°¸lmÙ ÇΧÌêR(—íú…ߨ ÖPP¦J¥H;âü’+ÄÅšŽBÁï##òÆSO=Ť4iŒoŠªxÁ œk>oOÕÝØðg”Ó½VL'¦ðš%˜ˆ‚Gù‘+:¦Ãd2죡1 ì<ã¢È2 ƒñM‘d)*~ÿ˯ÇÙ³/ÃñãözÒjÕÿ:ŠiÚûÔs}k8±ÁJB½FRM8rÄï##ò€i¢þÔS~ÑÌX–ÅVŠ$Ëyäœ,¢™t‰è’åöeDaÆ =E™aŒoЬ°Lw/€\®ý{>oÿ›Éx[²,»Q,Iíu¼ºnÿ+¶à´w¬Hª)ö®•åv}¯_dYn'›[¹ïé~ñ™ˆÇ†ý»¢ØïÓoµ˜jmöó¥ý:GŽØï-ÎM„Å7Þ„üÁsc}Žl°E„¢ØŠ»& #Ã0BQá!š㛢*L2îËP4º„qiâw˲·ïéŽI¯k¿­™EfcÓ´Ÿ§ªíÛúí[ë>¯î©Ùâ9ƒö¼ûâŠ?£ø¿h<÷;¿îY~ÛÛ½[«=€sãµWÙ`%Š Iâz Іt:Í =E–®ë¡©ÐM"Œå·¹2™ö¨d?Ý4ImiVwâÌaïØFw#sPƒµûyƒ~ïw^ƒ>?°ÁJ¢w(ìX™§¨cŒSTqIͬD!IÁËÈGDD Ã@f”!¢J§Ó~EPà³×ëu4 ¿ƒh&ßuŒqвIã›#P,¿)(;ÂÚh4ËåP¯×ªª¢X,ú}XDž`|SÔ1Æ)ʦ‰ïB÷6¢€aùMAØÖÕÕUÄãq†{î¹õz¥RÉïÃ"ò㛢Ž1NQ6M|+ÝMˆ†å7M ¬FµZ KKK€X,†……TGI½EpŒoŠ:Æ8E㛢ŒñMAÈëÎÎ ‘H8·%‰7~yyÙïCðT­VcßBã!j×ì¤㶨ÅC¯ÙI0¾£ Q»^'Åø¶E-Â~Ír ë ‹¢Ùl"‹í»ýܹsøã?þc|àÀÑ£Gý>Oœ?>RÌÅ‹Ñl65~y衇ðÐCáÊ+¯ÄÊÊÊÜß’ø€¿û»¿Ãë_ÿz:tÏyÎsæ~Ü^ Jüs£ ýÂV†3‚/H#–ßþ R  sZB£ÑD¯Ñ´ßuŒqŠ2Æ7E㛂( Öx<Žd2‰ÍÍMç6]בJ¥ü>4¢©1¾)êãeŒoŠ2Æ7Ñ%­V«å÷AôR¯×±¼¼Œx<î,ò^[[ Ìp6Ñ4ßuŒqŠ2Æ7E㛂&° VÙ¬’ɤ߇Cä)Æ7Ecœ¢ŒñMQÆø¦ tƒ•ˆˆˆˆˆˆ®Kßõ®w½ËºZ­†K.¹¤ïTŠz½Žo}ë[=ïtß(÷ÏB³Ù„išxö³Ÿ=Ñ1ñœhrÓÄ·÷Ï ãùÐtÅxãe8 ­üvLA<šËïàŸÓHZ43ïÿû[¯}ík[ÇŽk;v¬uÇw´.^¼èÜ¿³³Óºí¶Ûœûïºë®‘îåþY¸xñbë®»îrÞó¶ÛnkÝwß}ž³çD“›&¾½¸Åxχ¦3(ÆÃ,ÃI8hå÷°c âùÐtX~ÿœÆÈ,ÁQÐl6Q*•°²²Ã0pÏ=÷8· «««ˆÇãÎýõzݹÐ}£Ü? ¥R F÷Üs Ã@<ÇúúúÈÇÄs¢ÉLß^Ü? ƒb<ŒçC“ãaŒ–áÌò{Ø1ñ|hr,¿ÃqNcñ»ÅU÷Þ{oëØ±c·>}ºuÇw´Z-»'ãØ±c½#ï}ï{[·ÜrËÀû†=wV.^¼¸ï=wvvZ§OŸ阂xN4¹iâÛ‹ûgaPŒ‡ñ|h:ƒb<ŒñÀ2œ„ƒV~;¦ žM‡åwðÏi\O÷»ÁUÉd†atܶ³³ƒ«¯¾Úù?$ çþD"F£1ð¾aÏ‘).‘H ^¯£Ùl"‘H`eee¤c â9Ñ䦉o/A1^«ÕBw>4A1µøöâ˜ãáqÐÊïaÇÄó¡é°üþ9‹ Ö9X^^v‚áìÙ³00¶··ûÞ×l6>Wì—åµÝÝÝ}ç²»»‹µµµ¡A=Ê1ûqNäqã;¨ñ0(ÆÃx>äî×u½ïcƒ,é—ƒP~‹ï Ö¹È;,¿ƒyNãâÖ9¸ýöÛ±´´8sæ ;úyøá‡ûÞ·»»;ð¹"¨½æîݹûî»q÷ÝwcaaËËËCÏg”cöãœÈãÆwPãaPŒ‡ñ|È;Ý1Æx`N½„ò{Ø9±ÎEÞaùÌs¬sL&±°°€;ï¼ÓY ívïõø~âñøÀçÆãñ™œÃ‰'À™~Ø…@³ÙD­VzLÓÞOÁ5n|5Åø%—\ºó!ïtÇxÔâ›eøÁuÊïañÄ:y‡åw0Ïi\l°ÎH©Trz>±>>  sêM£Ñ@<xß°çÎÊ é±XlêcöãœhrÓÄ·÷Ï ¿ùæ›Cw>4A1µøf~°´ò{X|ñ|h:,¿ƒNãbƒuFNœ8Z­æ 〮ëÎ?#™Lbss³ãþT*5ð¾aÏ•D"±/…v©Trzf¦=f?Ή&7M|{qÿ, Šñ×¼æ5¡;šÎ Z|³ ?XZù=,¾ƒx>4–ßÁ?§q]ÒjµZ~DT­®®bssÉd;;; ¤{Núòò2âñ¸³¨ymm ±Xlà}Þ;+â=E/Õ8çãÅý,ÓÄ·÷Ï ãùÐtÅxãe8 ­üvLA<šËïàŸÓ8Ø`1wÊô^ë$šÍ¦ÓÔ}ÿ ûF¹¦=¦ žMnšøöâþY˜å5ÉøŸA1Æx`NÂA+¿‡ÝÄó¡é°üþ9Š V"""""" $®a%"""""¢@bƒ•ˆˆˆˆˆˆ‰ V"""""" $6X‰ˆˆˆˆˆ(Ø`%"""""¢@bƒ•ˆˆˆˆˆˆ‰ V"""""" $6X‰ˆˆˆˆˆ(Ø`%"""""¢@bƒ•ˆˆˆˆˆˆ‰ V"""""" $6X‰ˆˆˆˆˆ(Ø`%"""""¢@bƒ•ˆˆˆˆˆˆ‰ V"""""" $6X‰ˆˆˆˆˆ(Ø`%"ßèº˲ü> ¢¹ó2ö-Ë‚®ë~ŸÑL°ÁJD¾I¥R0 Ãïà š;/cß0 ¤R)¿O‰°J¥Ó4ý> ¢¹`¼Ï¬DDDD41MÓX§ƒñ>O÷û:Ó4Q©TöÝžÉd Ë2€vOŽ,ËPUº®#“ɰ§•‰©`étŠ¢8¯‘Ïç‘ËåP©T`YEA:v^O’$är¹‰O4Ì(ñ Åb–eõŒ1¯bœñMó4Ø/ (‹¸ä’K:žgYŠÅâ¾çMjP<ëºÓ4¡i@UÕŽøTŹu ƒiã]Q'n%IB&“$Iדâ«Ï,Ë‚aήëN°»X,°{t‹¤X,bqqÑyãÇw\`â~˲`Y;¦¡‹Eäóù‰O4̰ø€l6ëüÞ/&ÅkMãŒoš§yÄ~6›…¦ixðÁ;Þ7•J9!"/ŒÏnîø#Q¬“PXLï_üâqäȧ³QÓ´Ž%Œë µ(0.\¸ÐR¥•ËåZ­V«µ½½ÝÐÚÞÞv#ËrKUUç¾­­-ç¾r¹Ü’$Éù@«\.;¿+ŠÒÊd2Îï¹\®¥ªêÄ'Gw|·Zv̹/—ËNŒyãŒoòˬb_<¿Z­¶8ïãŽk"¯õŠgUU[ÕjÕù½;¾Åm¬“PØŒï¢ÖI(|Æw³Ùlº®C’$T«ÕŽXf\kX"ŸÏÃ4MT«Uç¶A[˜¦é¬SrëõAä·^ñ= cœ¢`ž±/Ö f³Ylooû}êA“Ä3QXMï²,£Z­:Ëø,ËB&“A¹\öûtB Ö¨T*¨T*¨V«½,’$õm´*ŠâôÚ¢÷ë–(HúÅ÷0Œq »yÇ~¹\†eYÐ4ÍIBä•Iã™(Œ&w‘8©\.£\.;ÛŽ)Šâ$L¥ñqJ°Ï Ã@6›ÅÆÆÆ¾ŠH:v{v…E$ÝPUµãw ½è›((Å÷0Œq 3¿b_’$'[%·] ¯Œσf……É4ñîYìWvðL VŸ‰Œ¿©T —\r‰ó“Ïç!Ë2Êå2R©R©Ž?îL •’|>ãÇ;$766ü>%"Ç ø†1Naægì§Ói¤Óivîg†Å³$IÈçó=·! ›iâ]lasäȤR)9r²,3·À”.iµZ-¿‚zSÀdYvöaû4‰Š‹; ‡˜FF%Œq:¨ûîúŠ;¡ Qïbv¤$I\Æä6XÌ4M9r[[[P¦i"•J!—Ëq<E“.˜{J°eY$ ™L†U""""":8ÂJDDDDDD™Ö}ìcø³?û3¼ä%/ñûP<µí;yä<òÈ#ø=òÈ#øîw¿‹ßøßðûPFöïþÝ¿ÃK_úR¿Ã3AНéš5 ëëë~ÆÈX†_®ÙGyW_}5þý¿ÿ÷~ÊHX~_®WÃ0°ººŠx<î÷¡Œ„åwð隤üŽLƒõ{ßûžõ¬gáĉ~Šgî½÷ÞHÏùóçñÔSOâœÎŸ?¯|å+~ÆXvwwñÙy%Hñà• ]³÷Þ{¯ß‡0–áÁ¤köüùóh4~ÆÈX~_®×{ï½W_}µß‡12–ßÁ¤kv’ò;2 Ö+¯¼Ï{ÞóL&ý>ϼõ­oÔù>|G Ì95›M¿a,W]uU`>;/-¼¤köšk®ñûÆÂ2<ø‚v͆© gù|Aº^¯¹æÄb1¿cd,¿ƒ/h×ì¸åwd¬Q´°°à÷!x*‡fz Í^ã!j×,M'jñÅk–&ÅXˆÚõJÓ‰Z<„ýš}šß@DDDDDDÔ ¬DDDDDDHl°Q ±ÁJDDDDDDÄ+¬DDDDDDHl°Q ±ÁJDDDDDDÄ+¬DDDDDDHl°Q ùÞ`­Õj~ÑÌ0¾)êãUŒmŠ:Æ8…ÅÓý|óF£ååe†Ñq{©TÂúúzÇmÉdkkk~.ÑXßuŒqŠ*Æ6EcœÂÄ—k£Ñ@½^ßwA;;;XXX€ªªÎm±XÌ—ˆh\ŒoŠ:Æ8Ec›¢Ž1NaäKƒµV«A×õ¾÷ïîî"™L"™LúöÁMŠñMQǧ¨blSÔ1Æ)Œ|Yú°°€µµ5¬¬¬ô¼_Ì©/•J(•JœcO¡Âø¦¨cŒST1¶)êãF¾']êGLUh6›X^^ÆæææÀÇÿã?þ#>úÑbyyÙïC§€ÛÜÜÄéÓ§÷­Û˜§qãxà‘KÛòò2Ο?ïë1° §Y)•J8}ú4¾ô¥/ùòþ,¿i–Dù]¯×};–ß4+¢>nùíkÒ¥^–––pûí·;sæãñ8J¥ú>ïùÏ>Þð†7ôí1¢6Ã0 ë:dYF:î¸Ï4MȲì÷!ÎÔÂÂâñ8Î;7÷÷ž4¾ছnbÒƒ‰éNî58‚eYNg…¢($ÉïÃõÜÚÚšo–á4k+++8qâÄÜËp–ß4¢üN$so–ß4k“ÖÁ'j°Š)õzKKKˆÇãh4žj<ß÷: Î{FuN½¦i}GüE¢(€J¥MÓ:•¢®( TUE¡PpîLÓ„¢(eº®#ŸÏCUU˜¦ÙÑXuÿ_¼w÷ûè¨ìëºî4ıH’˲zž×ƒ^Oúf¼ûÝq̳Í`À§?} žxâòù½éžƒßn†a81aš&$IrâÈ0 §CEÿùc¸á†Oà÷ÿ{xë[/xÁwñõ¯?…~ô\qÅ_#Nã#ù%<÷¹ãª«>…›oþ2ž|ò <öØKqÅ߇ë®ûçs=tè8®½ö,+{îy1^óš‡ð¢ÝÓÔö"iüø·JÁ‡?ǧ?ý=;6ÿkTã[4ØwÃM×uT*§q ìﯡ( r¹666ú¾®ëÐ4 ’$A–ed2™¾³LÓD¥ReYPUu_Ü †átêˆæ°†¦hT‹Eç\EaÎç`ŠÅ¢ówãV|Ýï3¨á)îîkRŒ$[–å4äÅgño|c¶ô>¢ãDŒípu!щèîàÄmîNRQF‹çˆN÷^¯ï®uÿ©ªê|ˆÛÝßyî>¢î%¾×Äí_þò—}ùìãTc5XÖ××±¶¶†d2é̯WUñx'OžD½^ŸjC,s¦Bˆ×Y__ïøÝOÝ;˲:“²,;·‰ÂQTº®;•ël6ëŒlJ’„­­­¾ïÙ=m·I’P(ÉdP©TP­V‡NïÍçËR!êÍ¢<7 À²E‘ I*, H§ÓjΨh¥‹€ªŠ(ʵP”ŒsŸi¢-žJÙ¯+Ëöí’ôf˜&ðñŸÀ?ýÓylnÞŸû¹ ìÞ¿ûï}ô8>ñ‰Ÿ\}õ—ü~ðíFQ.w O{ZÇŽ}¦©áõ¯?„¿ù›8>ùÉïÇ•Wþ'|æ3‡°°ð0®¸â ë:.¿å¯áСùO}z|÷Ó=ÅV|‹QK÷}:nªª"“Éx2Ú(¨ã<¾WG›{¤tTâ9¹\®ãöQ¯U ]éq7fqÖ¢C@Œög~êÔW4qà ŸÀöööTŸõ¤ÂãÔŸhˆëÚÝá"~¦}]1óÇý5hÊ~£ÑÀO<1×ϱ={½ÊÅî8 îF¦išN¬R©8ß;â{ hwú‰ÛÄl™îNRQÖ‹EH’„L&ãÌÂñÚkæ$INãW’$¤Ói¨ªº¯+¾7Ä1ˆUQž†w¿ûݾ|þŒq ª±¬;;;ÐsJ€f1ê:©D"¥¥%œïÄ¿¨`V«ÕÀLG »3(—³+ûù¼} õ+TU…®·¯Í}¯&)xå+í;4mÏ|æ'}9+¿cœFã¾Þ»Š@ç”è`­º p˲œQ!1õ^Q§.:¬Ü»¢b.^[”-NEß=R•Ïç‘Édœ†‡¦iÎc®»î:¼éMošëgvcÛݸõÃ0:ê:ã², Ùl¶c‰ˆ,Ëü–e!ŸÏh\Ø×È´, šfÏ¨ÚØØ˜*‡;FÅ 7q åryàùö꼑$©çíýê8Š¢àðáÃÿ4rŒS°]ÒjµZ£>¸^¯ãäÉ“¸çž{:zaVVVÐl6ñº×½Î}V£ÑØ@î& Ó¬£SøD¡i666 (гT|a»{ÅæEŒzŠ·4 {”ro€×i`º…¦i?'›µŸ'Iƒ˜ãÐu»’ím /âeãÆ7`gœfÊ}>Ÿ‡eYNãSTE‡I±XD&“éXï©( ÊåräqË4펖Qéº}ý™¦} iv‡Žh ê:œ™ €}ÍJ’ý>†Ñî$F€=cÁ4^ƒ©'OþΞýuß>#?Êð(rOWì÷}Ó½§¢{ª¸h¸ŸkYR©”Ó1Õý|Ñk¸Å÷`?bê½èÌk¼{ùLÓìXÓïu‹Å¢“·!N;e”ŸñâGù=k"ÎD'|:v:åÅZKîÎüÅÅÅŽŽw÷t\wN1²™ËåÉd`߇£¢î)¾Qæw¼°ü¦Yš$^Æa£¨ËËË8uê”s{£ÑÀéÓ§Ç=[ÇÇçôÑÙ…áââ"ÊårGÏÚââ¢Ó«çî]w a/ù|{ª¬`öˆh:Ý9ò)î3Íý Ö\®}[>ßY™ÿnm‰é¿Þ4Vû=ÃØX ‚yÇ·X§Ù½þYTtÜ7δۃD\[¢1iO]ow öu+®ãrÙ~œ¦Ù¿bÚ¼}ݺ¯î:X:m_¯†aß׫S¿×Œ!{Ø×ÏjÞ1UbtSÌvë•EcÒ=ËGpOW×¾xEQP,; ýÝIÑúeê½ÐæLï×6¢å‡°Çv÷o‘„NQd2躎ãÇïÍêÐ;êEÝÊå2R©”#¢ã³×2ñ}“J¥Fêqw9M'ì1NÑ3vÒ¥µµ5äóyœ'AÐnlºË×\®ÝØ:¯ÉjÕ~J¥½öÛƒÜhQ"+©,ËH¥RN£ÕI[UUgDK$®SzÝÓ'Óé4aYšÑXDÜí­YØAA<ÝyÜúm' ´–nbJ¿û9Ý™±û½X_> ‘Äs’רÕjø…_ø…±ž3öÖX,]×;öh ³J¥âùªàžBØëv&ßÑ^ƒ3fhÅb±ï^rA6JR#Ãh'ý’åÎì×¹ÜðQNIÚ¿nÔ£¤4*±lD4DFQ±Ö´{Û²~YCÅs¶¶¶¦ªHÐÁ#2êFµs’((5(ÝÜ™µE<·Aå»ÈÜ.ÞËÉÝý÷^¿ƒö¤šIvê«Á‹Å°²²‚R©„F£Ñó1aÊ6Îø$ÄT_û½ì¯"Œ£«•ŠÝM§íF£Èl-Iömù¼=#A$5å³X÷Ý=ÚJ4KîÑUÀ®„L{Í ê'êE$Ò"¢éôýì·ï|?"QØ´ÈA³$zmIUc¯a]]]`o$ÜK˜¬•Jeê¬s–e'Mê^¾!F{DœÉ2×”Ò|U*Ï×Ìþ˜íŸíívâ0˲os¯ï®TÚëM…B¡s0Ñ´ÄKwÆ]Ñ›N§Q(œÑU"¿hš6pÔžˆzsï-,~úÍJ“eyê=~irc7XG ±ÍǨ,ËNÆR(´×œjš=ýÐ4푟 »2ͤGä·J¥Ò±±zPìÕ÷÷MùU±U’{J®û2UÕþSyY_#¯T*H’äd5àdðI”:„t:Í ù*ŸÏ³Ó„¨‘Ôν“›è¶/4ùkì+lnnB×uÔj5ö¦Âªª†j]k¥Rq6ÆU±hW²톩¢tn}aYí$0üî ?‰ ÖƒV‘6Œöõã&®îëK~X\\Ü·—¨¦iNò¤î‘+‘=¾;û*Ñ<躎l6ë”ïì4!ê\[êΔ-vIpoFá3vƒµT*a}} XZZ4›M¬®®¢^¯ãÔ©S~ŸÓH&}2M{ÔÔ4íJw.×Ù`-—íéÁé4“%‘¿¼˜îî5wcUQìFª®Û׋$±“‡ü‘Íf!I4MsÖ‰ÊΰF 4o–e!›Í޼—.Q”™¦‰l6 ˲œ½}%Irò°‘c5XÖ××Ì£nªªbyyKKKˆÇã~Ÿ×@º®O´iµhß*Šý1µQëT9-‘ü4ÊYóR©t&UA¬S XÛšˆl6 ÀÞ—²R© ŸÏcccÃi¼M±XD:fc•¼b±èìôÁ훢o¬ëÎ΀ÞÙ±’É$‰vvvß`Õ4mìlz†ÑYÑîµw*ÐN²Dä?GWMÓn„ªª}-d2ý£’Ô¹6•hž*• ,ËrfÚd2hš†J¥]×ç¶77ѨD–ÒqroEeYÐ4 º®;;|¨ªŠ­­-Ž ­am6›ˆÅbûnë·ÕMˆÜÇ©Œèº=RÀü5DD¡¾Ý¶z&ïewäHR»óFtì°ã†‚®Wvßr¹Œ#GŽÌlon¢iˆ©ÀD…iš(‹Ðuétš‰‘°±¬Édñxù|§NrFRNŸ>í<&È&Ù«ŒS),4M›ÛÔ˜bÑQµ¬öh*ªÝ{§ bÛ‚ L§'rÓuªª²²N‚»¡šËå8ã…Æa ¾[o½µãöx<޵µ5¿Ïg ‘AlÔÀ7M{]*+áóÚRdõÃ@.‘ç]'\ EA$²©TŠ Uê0vƒ5‘Hàî»ïF­Vùsç'NœüÈ*€žÉ¢úÑ4{_Õj•)Ć×^g.5M •êlœ‹ìÈ¡`Ëf³0]™ñÒé42™LßÑU¢ ²,‹ëªéÀÈçóNyM$L´†µÑh ‹aeeP«ÕÐh4ŸlÉ0Œ‘×T*l¬R¸hš6“ébù<à^Ò'FW™÷ƒ‚*ŸÏ€3Š*¶Ñ4­#ÑQÌs©‘ŸLÓ„¦iL,Fû†1r611˜(L¼5ÒõöUÓ´¯’d' cb> "‘IÕ8I’$lll —Ëqt•BG$œ!Šº|>ϽS©§±¬Íf¥R KKKëU×ÖÖ°²²‚ÕÕÕ@g gô‰õ ›q:dú)Ûû¦ŠßEŽ2Y¶³kZï-ˆüfYòù<ÊårÏkAUUf¦Pûj3ÙE®ë°,‹S©§±¬õzÍfÓ™ ì¶´´„x<îìÕ4º®\™×u6X)œ¦­Ô躽‡ªø?Ðþ°GV™÷ƒ‚È0 ¤R)d2Vî)28˜±lƒŠÔÏDkXûÙÝÝõû|u˜irº#…aS¿†;qj¥tçøàuAAT©TP,Q.—™I•"EÓ´¹d~'òS>Ÿgg# 4Ñ>¬«««XYYA,О* ØY„ƒhœé’ªÊŠ9…×=óÒPèºî$éàº'Š˲€qM‘¦iLÓdlhâ}X777Æi½^G,ÃÚÚšÓˆ ˲Fîyçt` ›q¦¼÷bYÀñãÜW•ÂG$¤a¥ž¢F×uΠHy8‹€†Ú`m4h6›NãTìêë:êõ:`aaªª¶± ؉ F­ÐtoãAÓd>Õ4î«JádY³þR$†Á)’iÅb™L†e8 5Òëúú:’É$TUE"‘€ªª¡êù³,kä‚߃¥€Ds5í«¦±“†ÂÉ4ÍP}J×uäDšv¢âž«4ª¡ Öx<Žb±À.<777Q¯×‘H$œlŒšFì9é9wúU¦Ùs´ÙË<Ô¸=ñ¦Ùþx-‹±/LÓî!Tèÿ8˜¦é÷!Ш, $†ý_ ýµ(nS;‡„®·3•ãë_ž|êÛo†$ŒËëW)êÄ”wÆ8b¬mmTUÅ©S§pöìY$“IÔj5œog½ê¾¦Ýó´5­}>ƒ†™r9 ›ÅŸú°¶6ýßc€yÇx7Ã0Ø`õÙ(, Èþì¨þ^ʉKüÛìòÂUår@ÎÊy;–d²¢Ÿ| Ëè.]Ô³=„ØæúÕñuÅýês–µ¿_O–Û_¢ê ˆª‹x-Ñç(ª1¦iíÓ~¯Šþõ?ÿó;gþYùã–eA×ufö€øó‰âB\Ý× ø6Ívg¡xMÑ1(fl‹ßÅu0¬ì¯Tìb^¼O6k“,/Åk_{ÿXçéÉ>¬‰D‰D+++#=¾Ñh ^¯c}}½çý«««ˆÇã8{ö,šÍ&Nž<‰R©4òëw3Msä‚_´-=k°Š†`&cÿu»ÿºÞ5‘$ûÍk6k?.¶ÿßkïQ’JRÿ”ÇÝ ¸tÚnçrí¨¢ØéÕX­TìLj¨W”ÁZUµ#ÎM”î‹‹ö¥h*Š]‘Ïçíÿ÷+àÜ)n»¯Æ9šw|ãïÁ* 2OژŢý÷é÷y‹¿µiÚ×Á 7ÛÛvÎ3^:=øbÏ·,{4°Ÿ“Ï·;DÜÇ):•DçŠ$µcɲÚ%·JÙ÷õê¤é5•]U{7š …vÐO:=ÚzI66ðÿž<‰_Ÿü¯:1ÞË8Éôh¢cGÔ\D‡LŸŽžl0t Ò÷þéŸ`~ïfä~írd~åúŽÇI†ŽÂ‹ªPîØ«ôöË€…ôA‰m®_»Õ½-¡(šÝ}òâë »änŒ..vV7òygF;¥÷Aɯ•Ï£øÈÛa]÷"'¤Åñ°•³;Së·Á¸ðB\xÍ¿°ŸöØ„öå@n5†K/-˜M‡cb¼R© ÍL#³¬v ™¦w¹œO¢jÜÝ`ì˜ìnŒ@>kÁ0%§Ú\©øÜ瀋k®œ¸¿xòOý3 b¿qÁ0:êÙÙ¬ýÕÉ´'~©j»7Mû¶²Ý;”>ÊòÇq×xÛÈŸÁX ÖZ­†d2Ùñ»®ëˆÅb8qâDÇ}Ã^§ßâF£Z­†³gÏb±°¹¹9UƒuôÇzØÎ&*¹Ý ­ÅEû1b¤E×íé^£3bd°›ÍÚQë>hY¶#õ:©îßE£°XÞøÚQ:ª^ï?NåD4æ'}¿9šw|ã¯_õlYp±hÇj¯Ï[4uÝŽQÑP ×îÇŠÑ|1ÊØ«3FLUû9Çw6âúU®%É~ÝãÇícÇÓëCµw¼‰šŠÛ¨ Èî÷èÇãÏ0k»1ÞKä.uwIOúÝ]储½w—½š†Ê/ÿŒ+æÓÖ3ž éÒ&”û/ù÷È|hò‡KOÑuŸø¶”’}¨*Ì?ú*¿÷màWÞì}ºç}¹\®U­VG:&UÝûÏÆF«µµ5Öùì³½Ýj ƒïï¥PhµÒéý·ol´Z.tŸœ};eP¼xù^Åw«ÕjÝqÇ=o¯V«­t¯x™µ Z-YÞ“.Øq)Ë­V¹<Úk©ªýœî×åÊåV«Zµú]SîÇû!Õ/^¼4¯2¼UU[[Ó–ÓA‘ÉØå¾ª¶ZŠÒ;–ÅùÙþ™_im¯þ±sׯÆÞå¶µÕ¾ªÕÖFa»¥(­–|ów[éûº}{«}‰¶Z­Vk{»µõW[î¯ÉííöˈK&—sZ&cÿ ˵Z¹7ׇ>n³.ÃçU~÷²±±ÑÊår3;7/\¸`ÇF¡`Ç„úê'Z²Üêˆ!Yîý§wÃå²'"Ü·ß÷Iç§ðš´”vZòµ´roüìþ¢;n×r9û'¶_tPýjœï&¡ßëmlô®çíϰ¯¤~¢\~_¸p¡¥:•íàaµµÕ®bÈrï?óÖÞ×*ÿöãûnßÞ¶c_|=‰8ÏåZ­òê7ZÕ_ýXk;[´¤ªíŸ^o"#Ëö¢Ø/ä.œýP­¶.˜–}Žå²«5Ü$å÷H#¬¹\‰D¢cûúú:‰ÖÖ֋Ű¾¾ŽR©„………©z!-ðn6›}÷zýÇüG|ô£E½^ÇZ׺-kÄÂb–!» OŒÊ ëå4ŒÞÓoeyðb†~½èýžÓk4'S¨ÂfssïÿûqÙe—Íý½'oxà°¼¼ UU÷]gã¬ã³,À|ç(?zåä)±Åºâ^kE·¡{Šö0“n>n–´XLcyyçÏŸ÷å½gQ†÷3Îve¾°¬ö<@1ÕUf ½ý/a|ã(|(aòÿáƒÀß^ Õ}YïÍ·23{âŸéóGá,Y®ï]ΊâLƒF€,? †ñ\@y.û0œC‘e(=¾¾º‹•BÁ1“î>cß0dÖ‹ýúGx;ºZ*•pï½÷âСC³þ v˜UùÝ-ˆëW-Ë.òÅä(ëo€þž¤Æ±ñÔYÈ/½ æ·¿ìéãP$ÛÛrÏ×I¥ì×pVHX–=ûE–!»êR¹W¹ûX{nwñí¡õ»L¼é¸ßý¾cû½o.?9—ÃþL”ßbGŽyšGùÄøvËÿ ̯@ñÿ:ý3‡yÙß úíwB®<ÈhH;SÂå‡Ïa1ƒúšoCþkœ×ÐþÓ—¡|ßó (vò,§š"r­( ðã >»*¨ë| R¥%—³§EŒ¸=‘¨ƒ[~m°Öj54 œ={Ö Ôf³‰z½ŽS§N9·-,, T*í›6<®f³Ù÷¾ÝÝݾËóŸÿ|¼á oè9eaÔ5¬ÎÌÙJ¥=¥XìÝ(t¯áT”ve¤Ç°9ËÂÂâñ8Î;7÷÷ž4¾ছnêùE0î¬ÆÇƒþ‡OBy÷­Ã,’\uOSÓ {´>$¸¢NkkkX^žå¤²þfQ†‡’˜/e2vMݵÜÃ0€ÅÞDî*™¿Ñ¹Ä¤v#ŠEÀúö^}X×íõKjzÊþš)—¯ðFûñè¬Óˆ¯¢îÙ÷^|5É2€wÜàvß>Ú••œ8qbîeø,Êï^ Ã@Æóí F#Ö»‰l Ò%¢ðóÛ€¬t¬‚¿ý÷(ü+sï»áíöm¦‰jñ×Eݼ½ÎwMk¯~ZüßFæú?‡ªºí’4^ç4æU?©"CýQ~Ï»± ̧üÖu=PÉòÜ ³ÒFêÞ Ì8º7%6ýgº7àZ õŽÛQ¨ëȾ6†êý/†õ¹¯Búå·#§(À­9Øéã\æçóËÙßi‹‹c%ÿ™´>´ÁZ¯×‘L&;‚TÌ}w¯Šy´^jÐÇ'zÍQsT*{v)W™îÑY±²XQì»_7êÛÖÐÔfßÀxkXßù¤W<¿3vÝ+úEÌ»jõJ( / ŽYÅx7_.õZËÜO.×1[Æ0é]ÏÕ*, X¼å›Øxö¿…ò×§;aÄ׋°¸ò\H'~éôèõ^öyož±=ë ½³}Œö ÓDª|Ò×V!·¶!?cê þÐUH9¥s0±W€ÉrÏUÿúÝ8þ¡_…®? òC÷"óއgzn‘ËÙ#j>u>Lb1îÛvd¦ ýÏEñOo†i…ŸüÒgßܹ'tzÀ¬Å½Ñÿî1õtY…¦(žx?*_}#¶6þ3¤·¼fþçç‡rÙ.;æð…3´Á‹Åöõ¸ˆi ^5RÝ> Àž– .÷ÿ'1j¥&—dSogF´ŸÜù ËêŸÉ—5bñmÆèÙö, Öçÿê{os¿€ÝC&ÒÎq†Ma1ÞË8Ùß'Ò«qZ,Ú;¹Ü¾J¨õÙûaÎΣ¨Tì8wgß=~0̽- ·¶€jz® ¼èEPÿäí÷Ø“$v/Czé*OÏÚ†Ž°& $“I,//caaµZ ÍfÓéi6›8wîVWW‘L&=é…YYYÁòò²ó^±X ·ß>Ùz™Qw[–ð¹8ÂD3çe|cìÁº—ÆÄo”ÜCä¯c¼Ÿ™4X+û§ßÖ^² ll@ÿù?…ücKŸø"r¿øk(¼côãîêEÁ1ëØ6 ó¸6¿ð86®ÿeÈ_yøÊÿFÚ¡}äǰõ‰énÞWÕ1gÊøÄÞñsš:HÓ™eŒ{>Ýݲ©¤ 7O X\söËÝØ°;ò5 öÒpäó½wË£p)Kp¡P@©TBµZE,éS§œyîgΜÁúú:’É$ c~'“Éž•íD"}èCΨî4IœFÉ\©¸:ÒÙX%Ì#¾1FW³YX?õ³ÿzèÄ ¢‘Ì+Æ{1 ¹AYØ'Q©ÀúoíöÃ,ÚÙe¹ƒO(ýþ·¡û~à‡/‡ÄQÒÈñ+¶-Ëšzº¤i²d!ý»©Ž=ÓÓÒ¦ È7w<þøq‘IzvŸ'{h‚Ç÷*C°a‹?ý=TŸµy%5“ºw»Øn°«ô"'{µ…ÏH VÑHíeaaÁÉøä¥X,æÉEâ¾8ºYðbþ:Ñ8¼Šo}ÔD_{‹ê¬ŸûE¨Wø}ötxãýŒ•t©ßÖcî×ûÍ?¼Yõ?þ7Ì?½ÒÒu»B/‰D.%»­<ÿ,žä¿YÆö´1• Püõ§P}Ú¿€ü3û—8õ¸DFiVæI˜UŒOÒ`íU|ëgظ"yå';b¼û¥÷&ÄôËF!2Rƒ°×¨ŠÄ'NœpÙë†ê,ˆJH2NÛñ­ßýÔÚ*ÔÕH,©)œF*üe¨V!cðÖÀDa0Ö´I‘Ù]´8»+ð• ²¿“€d=…Â}UÈÒ5(ü@ûnUåàÍϸٯóïxÚ‡ž<íi$;Ì·>ñMH×~`äŒÖ“nÇM4.Ó4GO‰vñ ØÕU2²ŽÜ‡³v t„Ù숉†‘¬¥R ëëëÎïëëëXZZ Å~ybq·X:Q(ØÓ¹²é vö°ÌóÍt`ˆí‚‰ÂÊ0 ,..bcÔÅHù|ÿÌî (PÞx%2¿ý£~Ÿp“¬ï³þìcë=ß´ôf×­×ú}*D=“Ýݲ€ì¿lÚëQ_ƒaú¯~ x(ßÞz’Œ‘³­¯¯caa†aÀ0 ,,,`}}}àÃAaYE¢e¹i1…‚vÕ#¿€‚~r1ë÷!yÃ0ì½3 ˆÂÈÝX©Ò“ÏÛ=•ƒ«(Èü6§ö’ÿ†Uæ÷•ݺŽrâwº«DÑPü"ý?†ò:{ MEr¯¹—ÕjhƒUlW³´´äÜ&FVÅ‚ì s¦×T*ödöím‘BÌïC#šJGzxMÛ›>mÿÞ•>^L# £±«¦ÙÞ3uO±:d÷íöt³!}íÍg‘Z”œ5PbÔlv/9M‘_ –eí«Ð[V;ÿF¡àȘë>÷9È?|;Þ)4ú5X-«ÝqX.ï%G5tHïp59FNºV¦iÂ4õ–+€—3Û E3ƒ@¤Ñ+—Û »jã\¿Ja6hôiŸ½¬ØJᇰÑ5«@QìF«hp[H Ã0Pv¥2*™Œk¢@µ uqªekU¿™hd¦iî۲ɲ€T Èœ|H½ÙÞWUØÌI.‘o°"æ¯ÀÚ:E˜{ø´+ª®·gÄ…ѨÙS X\”±½mgÅîE’ìF+Qé:ýùïA}Ú_¡úo†œû™ö² lmµ÷é# Ã0qÕMì²Ú®£gÔ¯WöÈâN´gäëòòò¾ÛJ¥Μ9ÓqÛÚÚšßçÔáÆ_í÷!ùNÓø=@á6JvI1}’36îé’Ê¥ŸCõYï„|ò‡û2qº …Œ; v±ØîD·CYf%…Ú`=|øpGÂ%!‘GVÅFã'¡ëœöEÑÔÝcÙ‹iÚ=öÜ4›Âl”ýûòy»Îú<…eYøÖ·Þ ãlÊ;ß ‰‰!)bDcµR±ë$[[Ì!@£Ú`Çã¡Øoµ˲Ðl¾˜EÚ°u}Å"—‚Pø‰-ÊúÑuÀü»o¢\¾ÂïC%ÛÙ³u|þSoüù7ÆÆ*E‹ÙµcÁÆÿ}?$ýÓLªD#9K°P«ÕP*•œ±íM†+®¸Š^lçƒ'ŠË‚“µK¥b¯áL »î O·âR¹o¾ËïÃ$šÈ ¯ÝƇ±éÏþ;«9î%™´éçÚïC¢y «®ë8}ú4FÇíëëëˆÇã(‹œ&|Ùe—Ùs"Ù‹CdYV{SÉ.¦i7X™\†Âνöi]‡qçHWßÕ`Ç$…ÓË?õ)\ùº²±J‘dÞÿþ_@&È•¢½NõrÃH#¬µZ ¹\‡F±X„aÎO±XÄáÇqòäÉ@޶~ýëqp+E•)¨îUæóy;E¼i¶“IrJ<…ݾ„K¦ ?nÿh”wߊúËý>L¢‰d³€þõ—áæßüM¿…h&,ËB,ƒlv¥Pðû(dFa]]]…ªª(ö˜V«ª*TUE.—Ãêê*î¾ûn¿Ï©ÃóžóS¿Sd)ŠÒ1ç·P°ëòl¤R”†Ñ¹¥Øœ2“q:gˆÂHô9JÏþ<™"Ë0 T*_±{gØX¥ a­Õjh4¸óÎ;>nii FõzÝïsr躎ç\Úäж½{6kÿ*Ël°R´ìK¸äê¤Y\´—q…Q¥b‡²Å ¦ˆSÄlGÎx¤ a­×ëˆÇãˆÇã'Ö¯6›M¿Ï©ÃŸøÿòëý> ¢™¸ñ›ßdšæ÷‘Íξ훶¶´Ó°ƒ†ÂJÓìpÖuŽ®R4Yð±ýÀ|­Svkèk,Ãîî®ßÇ9±Ë{ŒÓl(’t]·¬ŠÃ`§%EW¿¤K²Ì-›(¼Ä€“ivMy'Š3gžÀË®¿ÇžíÈ8§ m°& 4›Í}Ù»‰„K±XÌïsrœ?ÿrT>÷FÖä)²^üâ°{éæU½«ºn°…•iÒW?‡ë~ë·†î§MVøÀ.¾ÿ rÙïC¡©ÁšH$ËåúN÷m6›(•JH&“ÚÚæóŸ:žvô¹~ÑÌzôQ˜­rÝ*E–;áR±hgÂÎçá¬Ù& ³ôUÁgŽñû0ˆfæ«_½7ÜÐ`%…¦2Ò¶6§NB£ÑÀÉ“'±¹¹éŒ¶6 lnnâäÉ“h4XYYñû|:¼èE€wê‹~ÑÌœ{å+¡Êrt•"KLÖÿðAèÿÿöî7¶­ë>ãø£Ä]fÇ¢-Ûmå\eñÔ4õíÚ¦•Pqí$@åmÀÐd#æuC X/ wáF÷MÕ‹fØ„ÙØ›!صXQ 5°µA…D€5&à¢k€ÐÃEÓðÅb‡iÑÊ2׌)£Íßj/r–%ñß½WçðèûZ$>¸+ë _Ü­³~[£‡åyópBõÜsz÷‹<÷°ÂEÅ¢´oßsâì"¢éhÂ*ýÿ¤µñèš0 ›Ë…Ûí lÊ¥KŸ7Ý 1årý¬%_Þá²jµª¡¡!}÷ÿU£c»MwˆEµ*ýÅ—~Gg®ÝpÄÐôÁÚ759þ¦»‚>×ñ„µ¡ñˆ›É›Ö Öj5…a¨t:mzLM•ʰé.‰â¬<\W.—ëß<ñ„4ÊÙ¸¡\–&KõuíAÀ¦KpÒÉ“Ò3;~V?CÃ÷DÐÑ=¬ÃPÙlÖôxV¼u_ý©Ü€£~ñµ‹:uÊt/€ä\ºôùz/—٠ΗN|èIi´~…pMµZÿ¿Q‰ YlVÝúNŠçÀi?}f»é.‰ªT†ëËÞ©åpÍ»'aØ.úÆ7¤ÿTçïºËtWà€®—÷“ám¿àŒ<œîþ‘¶Ÿ˜2Ý 1÷ßÿªÞÉz8åÐ!éì䤪ժ鮉’>üÎ÷UûЇLw°všÏç5;;»êµt:­B¡ÐÑûü㟛°¡¨ù–¤±«Wµç÷ÁRqd¼)$®BÁ"Qó].K:qBA±ÈVX'Žú}ì˜téÿMÏ|ñ‹¦‡X;a]\\T&“Yµ¹S*•êøýgÏ^UzÛO¤Ñ?6=`¨ùnøòË£“¦¬#ŽŒûÛÏhqño¥êÿ0a…U¢ä»\fÁì×w”=¯½&ï#1=8 í„5 Cåóù¶ÿ¡Z­kÇ–——•N§{Þuøž{–õÉ]ß‘FíÚ ¢ç[’v¾õ–žº|·é¡ëŠ#ãKKÛµ{÷néØC¦‡¬%ß7.(‹ìöëD­ßÅ¢ôÄé7ô…[nalÄ"¶M—R©T¬´)•J’êËòù|óß;µsç[º÷úOc맨ù–¤ÔÅ‹Òm·™ °®82~ýú{LXW”|ß¼Â%Á°MÔúÒè{^ÖÒöíLX‹¶Vß÷U(:þ_œëçkµš²Ù¬æçç7üÙ+W®(‚æÕàþð·ô“3ø«…­J¥’ž|òI=ÿüóFûÑM¾%éÕW_]õÇðð°†ö:½Ñ7z”ÏçõòË/›îF¤.ÕoíøÀ^3= Xf~~^O>ù¤._¾l´ÝäûÆú].K£gòR¹Ì¦KX£Q¿+•ŠÑ~D©ßå²4þ¹»õO·ð«5¾ƒw[¿Û. .•JÊf³«žV«Õ†a¬WToT©T455¥£G6×Ì{ž§|>¯L&³î{vìØ¡ýû÷kbbB’töìŠ~÷=ìL†µFFFtðàA½øâ‹FŽßK¾%éöÛo×ÄÄ„FFF$I—®ÿ¾Fï×FÆ»MLLèÙgŸ5vü8jxÃÇ>v§±qÀN¾ïkyyÙØú^ò}cý®V¥ñê‚4šS¹\^uŸ Ш߃ƒƒFŽGýéë_—¾ü¾÷™ù%ÂZïàÝÖïžN}ÌÍÍ)›MîÞPÏó”ËåVÝàÉdT«Õ6\–°cÇÝqÇÍIô]w]Ô¶¿;šXÑ¿<ÏÓÁƒµwï^cÇï6ßRý O:–çy’¤Ò¾}úˆgd °[:Ö®]»Œ?Ž.I¯¼âiâ×?ªß¼Ë÷}{VÍç s…7kÔï^69ŠC\õ[÷gcÆwðnë·•×êK¥Òš¥ËËË’:ߥìÀKÚ¿Ÿ«O°Où‚@áÛ÷Š¿ `£82.IW¯®èãK$¾ÔÃ"‘ó}Ã6ÁLXa›¨ù.ë÷h—ß=)ÄÁÊ k*•ÒÌÌŒÂ0l¾6;;+ß÷åû~GÿW^áÊìG¾«Õª>ó™«:vÌôh€µâȸ$}ô£¯ÝW¯ò X%r¾Ëåæ®KlHÛDÍwµZ/ÙKÏ<Æbˆ•Ïaõ}_SSS:räˆÒé´%I§Nêø¿ñÝïþ¹r9³2ë‰#ß’´{÷U®°ÂJqeüõ×/Heñ VX%r¾ƒ@R,™„u¢æûðaIÅ¢*ÿü‰g°"&VNX%)—Ë)“É4?(Ýnð´kà5sæ–ŠšoIz®ßl–¨饗þHJý»é¡kDÊwµ*MNªZ­r…VŠü¥ZÕËׯsB±éxÂzã&KµZmÍk q>ÚÆó¼æ3]¿÷íÿ•Ê¿âÌ<¬%ßoœ9£—þ“õÀ°[”ŒW«ÒûûÃ,†µzÎwHÇŽ©Ìfb°X”ú­ Ð »w³$±i;aÑÔÔԚדz¤MÊeiÛÊ “U8kiiIõÁs’:¿è'{÷^Óìúuî—FGU.—ùB7•˺º{·ÞoºpFÛ kc{ë~R.KßzVÒý¦»$bÏk¯iòà%%÷x)À¤_þò¿ô§ûjâFm8çäÉæ?²dN*—µ04¤?a… bbå.ÁqعÍÚÛsÈÞxu§Jƒ˜î˜3g<íxã ®°ÂYAp+œF¾—ŽguajvvVSSSò}Ãe,A˜“FG¥Ý·ULwHÌÒëwèg—>¡Ï™îï?¥Û¼_÷ONšî ¾ÐÃ9A ŽªÊsX£Ž®°‹E9rDa®zhp.—Óôô´Òé´R©”Î;gz<’¤Ñj Ìms¦»$æç/íÓŽ½{MwHÌÒÒvîïƒÓl8ÁÄ®\®OX«UÓ=C:š°ÎÌÌhrrR «v ó}_™LF…BAš›³c’xñüy]¼ab ¸fù7»ôg}·én‰©?g˜ûûà.NÈÀI££Òáì@¬ÚNXK¥’jµšŽ?ÞòçŽ?®ÙÙYU*æ—â.//kxxØt7€Äüú7»LwHLH·ÜrÍt7€Äpõ ÎW™“ˆYÛ k†ë>‹©± ¸¡ÑÞxȰIË÷Ü£Ò½÷šî˜ ·~½hà¬jUºõ­ÿÖ'YöG±á\Æ#›·¶›.¥R)-//¯y½P(˜îû†ÞÚ¹SWwï6Ý 1Þ¼§}ÀYA }àúuízúiéŸ0Ý ,y€Î´½Âêû¾jµšJ¥RËŸk´§,¸wthhˆ3—pÚ—¾ôqÓ]3>.Ý÷Î×x¤ œV8‹ Å·¶WX}ß—ïûÊçóò}Ý i­VS>ŸW:–ïû¦Ç¤ññq–"Ài7Ÿ_ÓžÉd455µfc&ºÌß\$‡MiಠtøðaÓÝ€C:š°Jõ]€§§§•Ëå†aóõ– Ћ×/\Ю={LwH÷°ÂeœAœ:ž°6¤R)¥ÓiÓý8jûÒ’*ÃúÛtG€„”ËeÓ]Ã’wÄ­í.Ál¦åü@¿ºí6ÓÝÓ à2&¬ˆ[×WXHÒÒ}÷éà§>eº@"xä\Ç Ä +À*ù•¯˜î˜jµÊý}pËÝ‘–l–KÂeì€$0aØ$A°dºÀ„`1a…«¸GIàV€MR.—y+œuâÄ Ó]€ƒ¸Â °IØt ºÃ„`“0Y€î0aØ$'Ož4Ýè+ÖOXÃ0T¥R1Ý ä®#ãpù†ËÈ7laí¦K•JE'NœP†’¤ÉÉI:uÊt·€Xo¸ŽŒÃeä.#ß°µWXgffäyž‚ йs熡òù¼én± ßp‡ËÈ7\F¾a+'¬•JE¥RISSS’¤T*¥L&£³gÏšîù†ëÈ8\F¾á2ò Y9a]\\”$ù¾ß|Í÷ý-·ŽÞµ³Yaj~~Þt7Œ#ßu.æÁµÏl¯Èxkypñ3Û òíf\û¼öŠ|×¹–‡~ÿÌZyk«E­VS*•Zóú¥K—tæÌAàÌ–ñO?ý´é.ÄêòåËZZZ2^ô._¾¬‹/j``@¹\nÓßK¾%é…^ÐÔÔ”öï߯;î¸cÓû7[ò'[>³AèÅ_4v|jx-yˆ‹-ŸÙçŸ^KKKÚ³g‘ã÷’oê·ýlù¼6ê·©ZHý®³%q±å3ÛøÞmý¶rÂZ«Õ6l[^^^÷Ãâû¾î»ï>Ýyç:xð é!ÄâÍ7ßÔÄÄ„énÄæÊ•+ºråŠñ?Ÿ+W®hÿþý0rü^ò-IŸþô§uàÀíÛ·Oûöí3Ò÷8Ù’‡8Ùò™M¥Rzï{ßkìøÔð:[ò[>³ÃÃÃZZZÒÞ½{¿—|S¿ígËçµQ¿‡‡‡Ÿú]gKâbËg¶ñ¼Ûúmå„õÆe7ó›z%ßq´'¡UÆûq<ˆ¦UÆû1Ôp4lµúÝ®O6ŽÑP¿íSGV˜ï}ï{+<ðÀÊØØØÊØØØÊ#<²ríÚµfûâââÊÃ?ÜlôÑG;jë¤= ×®][yôÑG›Ç|øá‡W.\¸[ŸMŒ ½‹’ï8Ú“Ð*ãý8DÓ*ãý˜j8¶Zýn×'ǃh¨ßö©Vîì‚Z­¦|>¯\.§ tîܹæk 333ò<¯Ù†a³½U['íIÈçóªT*:w çyší¸O6Ž ½‰šï8Ú“Ð*ãý8ô®]Æû1ÔpH[³~·ë“ãAï¨ßý1¦®˜ž1»êÙgŸ][õÚã?¾òÈ#¬¬¬ÔÏdŒ­:;ò­o}k峟ýl˶vïMʵk×ÖsqqqåñÇï¨O6Ž ½‹’ï8Ú“Ð*ãý8DÓ*ãý˜j8¶Zýn×'ǃh¨ßö©[ÛLO˜]•N§Áª×588ØügIò}¿Ùîû¾*•J˶vïMJc§8ß÷†¡jµš|ßW.—ë¨O6Ž ½‹’ï8Ú“Ð*ã¥R©ïƃhZeܵ|ÇÑg2Þ?¶Zýn×'ǃh¨ßö©[LX7A6›m†áôéÓ’Ô2/¼ð†mµZ­å{ÏËŠÛòòòš±,//«P(´ u'}61&Ä£Û|Ûš‡VïÇñ >7g¼X,nø³¶æŽõl…úÝ.ß6~çB|¨ßvŽ©[Üú Ž=ª©©)IÒÜÜœ¤z6råÊ• Û–——[¾·ê¸ÝxvgaaA Êd2Êf³mÇÓIŸMŒ ñè6ß¶æ¡UÆûq<ˆÏÍïÇ00ÐwãA|nθkù¦†o][¡~·Ë·ß¹ê·cêÖ„äóù晆Æý!’422"iõÒ›J¥"ÏóZ¶µ{oRZ-H¥R‘ûlbLè]”|ÇÑž„V?pà@ßѴʸkù¦†o-[­~·Ë·ãA4ÔoûÇÔ-&¬ ™˜˜P©Tj^Æ—¤b±ØüÃ÷›z%ßq´'¡UÆï¿ÿþ¾¢i•q×òM ßZ¶Zýn—oǃh¨ßö©[++++¦;᪙™ÍÏÏ+NkqqqÕ ÒR}Mz6›•çyÍ›š …‚R©T˶vïMJ㘳TÝŒ'ŽvØ%J¾ãhOB«Œ÷ãxM«Œ÷c¨áhØjõ»]Ÿl¢¡~Û?¦n0aMØ[¦¯wŸD­Vkžº¹½U['íIˆÚ'Ç„ÞEÉwíIHò3I¾ûO«Œ÷c¨áhØjõ»]»ãA4ÔoûÇÔ)&¬+q+ÀJLXVb °V€•˜°¬Ä„`%&¬ˆU©TR­V3Ý 1d.#ßpù†Ë\Î7VÄ*›Í6: ¸ˆŒÃeä.#ßp™Ëùf °ÖMÔ¸T_©T4??¯b±Øl ÃP³³³‰i»V«©X,ªX,nʲJ¥âô¬f*ã¦ò-‘ñ­„—Q¿á2êwÛfº[I6›U&“Q±X”ïû*•JJ§Óò(è\”Œ÷C¾%2¾•™Êw£Ž$Q¿á2¾ƒ÷/®°"vù|^ƒƒƒ:þ¼ë曑q¸Œ|Ãeä.s5ß\aí3žçž¶>îãd2år9=ôÐCÊçóNáA²ú!ßGo6+ßQE¾Ñ ê7\×w5ßLXûL†Êçó¶çr¹æ’SÇ™œœT*•Òôô´Nœ8áÌ ßH^?ä["ãèÍfå;ê±È7zAý†ëú!ã®æ› kŸñŸß´¥pè_ý–o‰Œ£s›•ï8E¾Ñ)ê7\×ow)ß++++¦;ÀÍØ%`%&¬+1aX‰ +ÀJLXVb °V€•þ­í³22¯]%tEXtdate:create2019-03-28T17:36:51-05:00«ûs¹%tEXtdate:modify2019-03-28T17:36:51-05:00Ú¦Ë-tEXticc:copyrightCopyright Artifex Software 2011ºÅ´1tEXticc:descriptionArtifex Software sRGB ICC Profile †2tEXticc:manufacturerArtifex Software sRGB ICC Profile\~=Ÿ+tEXticc:modelArtifex Software sRGB ICC Profile1(‚¡!tEXtpdf:HiResBoundingBox1080x792+0+0_Ýx+tEXtpdf:VersionPDF-1.4 G:xIEND®B`‚blis-0.9.0/docs/graphs/large/l3_perf_tx2_jc8ic7_nt56.pdf000066400000000000000000001003431422157504600226330ustar00rootroot00000000000000%PDF-1.4 %ª«¬­ 1 0 obj << /Producer (Apache FOP Version 2.3.0-SNAPSHOT: PDFDocumentGraphics2D) /CreationDate (D:20190307162241-06'00') >> endobj 2 0 obj << /Length 3 0 R /Filter /FlateDecode >> stream xœÌ½KfÉ‘¸¯_‘KÍ¢>úû±Ð¢‰( h!hEU³1ÝÙ­.60Ðüú9Çü^w3÷¨ÊŠLÞ“è®øÂã»î×ÇÍìØãß¾óŸþ÷=ÿS{øô§Ïß¹—Y~»~¯ÿí»òò¿µÉïø1·”ë'ŸÒ§X仸ýçï|L?üóøÁ;ïñ³[?°é¿ûïßý zÿ3>ÿF~·þøÇ>ýÃwÿõ—õø×{‚¯ùSˆã)ÈOÿ,?ÕÂ7A£üðßýâcú0íÏßýÿ‰?ú_ß…Oÿýý?h*)·?ý¿ßy÷鿼Ù÷ê¯ñy½Ø½„X_%Üo´>ÅWŒÎ9ßâCãé¯Ùïüðx·÷ÊÌÎøOé½»œž}Û±ž×ÏG§¿úµÿäË‹gûÿ€!Œçÿùg†R|Ƈ’’oøjíÕb-$A‡¿ÿれïƒe|áÓ?úÿsü}úŸŸþøŸ¿ûO”×ýb_Á¹ðê!–T}~O_åèë©ó8þ#+xö‡Ï£~›26Hóõa˜ñ­¿Zè9%W÷žMÛƒCHéUrw­ùx A·=7„Þ_©µ{;F ›žß^îú-ùÉug‡Ûº›ž?`ÝevÝíž_wÁ®»Á[ëþeTöÝ´ÐZà¾îá呲Õ(!þ\(ù^8¶^>§\bK'‡»ÿM½ô^¡e¼Hû™>Â7õQrx%_Bñ.þL'Ñt"÷f{áb²÷æ÷îåä_¨Ÿ¾_ª‘è¿@«‚Ç`°òXúsŒáHÁòÉo~ýÛßýþ¿úÓ¿þøÃ1$}•ÿì ÔÔ_ÅkBÿ”:„ _«Ç|=GެߧÑ÷_þüÃçÏï¿ZíÉp?‰ˆ ²ÆTb ¥DŒÐz‘ ¢ùW©h ¥} ¡¾r -|€ôÝ2ö;¦4aN¹/›o­Ç¥ Ϥ<à ¦§—; \w´u<³³¿Ž ]ó+A²p=wiÃ39LˆíUKÍ=Fé¯ã™ýa[ú„Æ?pMÔ—àü«r,> ¤q¾§Ø«4ᑬ¹àü`¢rð®†$mx$‡Ñ[±5È×<ž˜ðÄLõÅ÷^³¸ "\€0æÚ%½b0÷Ñ%ÂÛ°?ý}Ÿá!%·–±ÑÙq©r()ûÑÖCÅ gò1÷„9HŒ¾@` òrÀ‡°´›ÍGŒïÅ6ì“ÊjØÞ¡­¬PíÒ†Gr(ÙcR0 ø ¾>^/â™\ RÙ_|qFvÛ’ñípL°@˜¢ŠÉÈ1iÃ3ç”aÖ±s0é^Æ’x4Ù_Å´@ˆL­ó¡Ò–ñL.PAú C®=JžÉ±ÄRär©øê˜2ìKÝÜX¶‚‡Ý;–ƒÈ®c)eW†‚‡Ý;;Æ•Si2ö‚ga>F,_닊Åb[Å#±4@=‘Z÷>/SU9s²µ<›0ÊËx+Ì•iØÜž8ué '§ÍÝŠÉ÷-a'YPœœpïÖ^1WO•Îppò½[Ѷ 7| ç¦]3/a–q2« §&p>pýŒ¹ªXò6FaåzßråÕk$qn#§Ãð<³xbÎDZ6i¹$½Ê·²‹1Y­ˆ qŸl °CtÊÕq#vt¿÷)ž—x‡äT¤ Ï»·)ž‡£ ìõã[xÞ½KÑ$é5ÉôÆÀ5B“ÇCðØ´¸“œ<Ç%Èó°Õñú±aj{Mx †/e65l d¬Ù¸`4HûÈ6\è<ËJ{ °8Ü­Ž TÃ4E‡­Œ¥©N㙸³j÷cª4Nóýp 6ÜÉPó™8Џ³í4RStÀDœÝp@5º+¸h0Ò¼C5îT¬ ^gdÇjåîrøã¬ÙV3¶ —«F£5%öŒ§Æ®å "tImÇkïq£àJ®¹€í‰6ÝAæpbCLyµâð;—vÈö!áC,Õ•¼c6ÛjÆŽÄvÙA››9§èãÕ¤@›‹^!3á+;jóÕk£¨]ãÛ˜ÉWwXê({ä—뜴iOÜnŸâ§ð)¾º1™ ÂOÌÝïÐÍœLìý¾C·ÇÑä%‡yȉk‡€qU@î+QÄÓMÀ†È ˆ=纳°vˆ’é°qFk˜Í7$ì|.¼€nhèFS¢ªÕ”ZèöxWÀP_3Ð]ÔQH;QŽ‚…n@>IÁ¡ñtã™@ûë Ý…ðŒ Uú€îá Qù@î  »#E¹#-rãb*T‰'r¸°8õ€îJ0Ä}ÆM¹C7ÚpLÃ%'än¾EzjdP*¡ºå^Ç«cdujd˜‡å· C[J–£Ã@Ý©£ÉptЃRÅ$È„å¢ øWªX4S6]za¨@É#¡š§©’¹ VK¼»¼4ô:U2<“¼M¶´D }ªdøô$¬¨á zš*Ú<Õð&Šcª†¢£îËçG鯊 ‹ß¸a±MTÑûtèaqMMYȦ”î/Mj–  ØYið©Û/){ü(wZꚟÃ]ë+–Zºïšž«À2c«vMÏÕW/5øBÙzŽäu‚Â-æ™ì4=—i Jz²4izŽ$œR8}Ùz¸Ü0¦f¯ ¤û´â¡ÎflÌÜî룾 TcÛ‹é?S ÷â)àë$ƒ®‚fçê«úD úhj¯1¾,Ì‘ÇHøÃ-=WšçZK_8,Ã=rIº'©!ƶ5;× ¦×F|aNJÇ(0ÜʦÚ0ØõÒdÙ9Åbæ¤Ù¹‚ãÕpúÄÆ˜qP„ÝpIØh^ñb'ÉY³sÃ-ÀÖ[‡×~¯»L8\ØAõÒêIØ:ìÂèždç6|ޝæzŠ˜øŸqgÄꔀ†n ÉR€¦Ñ3φUÕà3-_xœÇ&>W`~ï;_|†††áv߯‘ 9I;×|¾$z8êeÇçšÐÖ6´pà3†Òqø|»ªÅçBéÀT|ÆúöB‹–;ñ™Úp©X»¦i#çûJÚÈ9,u€jꀆØB`hÞ· Ï¡séè̃H Ÿw.6,B9šÆBÌ[Å|ƒ8²\. i3æwâs&³â„møÌÛÝØ ÍÐs¸¯uB‹£Mq¼0.DGâ寢ùÊBà»ì íÉ^—âà¡ Jóµ°.É Ó2¸£X= LóhÙ ‰tÇiÞþ3Rt…jn |i ‰ß¸9!Ø“¼œêA^\Nã¾ÐHM£qnÛ¬Õª¹·¼0úx`5­¸ž»¥ŽÆÂK¢DDÑhMéÃu1Ê]làÚãù=àNL¼¯ÉÍuŽÚÀæPBÂâß ƒØ²>"Öç²ùêB fó™â:ç}mš”Ïpl·-Ö ³âïƒí÷“srsÖq!A¸8%ëD¯ ÔS=‘›Ž¿¹é@Õq) ’wƒnÜrˆÒÅâo¡»nM‡›$Ð]qÃà(ôË ÝKbÀÒFBw‡°€­äå$Xè.t27È)ZÓIBÐ…{ºI a)!Äõº 媂7¼ÄgÝÕ"¬åC´Îµx Å@7pÕÓ­ûS¶”Ræ¦Â[ÐèÛ2H’ º1›Òa7Ø÷`v=· ¹3¶mõãʲ¸M÷ô0îƒÛQ®:ì°±¬¸c «ë:›À šÈáÀ-¾÷,lsÙéÎ(4Ÿ…mù=:º`Õ·![ã= 7ú·!h©t㪲¸åÁû ·©*AO¯CÞqÛ¯ÛÛÄ…ŠEaµ¸Mª _ŒÞŸÈ^xqB:‘›}€p|¹ Ojnñ·Š.ûv7ä\ñmØæ©ÉrG؆̖¨Ë…Þ‚íˆÅ åí‰m¸³  9"Y‹º6åîA|PÐöÜŒ}èEyãåÈ=cüímî6L‰¸ã ̦؛éåÛß'j^®øÛ–]ÛÍñ'‘™Øø /÷VßO¯×ø¼^ì‘^ªæåÖ§Ç 2ÖÅËÍw{¿¡Ììüð8/w½àXÏôõ¼\ŠÖT Ð'=ÌË¥ Prâ*‘;¼Ü:ó¨?²f-¨ƒþÜ To3¢ËäŠyX6~ÆôüüŒ Áò3vÏó3‚ågÌžçåôöú^Žnënzþ€u—!Øu·Cx~ÝkÛy93‚¯âå $%ºpS™yŒ—³<ÅË™^âåLOðrt¶ƒú½ÿ~ž—£c›æå~ü§§x¹B­bv`„y¹L­„Ä 'lvßÒ’¨µgÃpíõ´ÚºÔ…N—·Ñfì¾^âãðTžß51Góy¯T9»´ ×^l}úaPU€vT%* ;J[<Ý(1“Â’ªåtåuU|_¡á%ÌHÝÉèÎ-vÌ mÐx‡¦ãE½nâ…+*{ÉÚz€ó b@º‘aæáÚ{aÕr¨ÔCg(y¸ö^úôk¨”ƒ +EhE/˜•*œBZî–>Ö¡KáE†b)Úzi‹6XDÇ+˜ˆzkdô¢ ð0š–ª4ˆA%ºøœR‡kïÐɰÊj? R¶5m=t®Þ›kiÚz te/]ôeŒG\{‡J†“TèÝ…É,]›Pòj½† ýÜ/• ”{_E_.]ÌÜ@@^¨¹œªJÅüÞ°ì?Þ„NuÚ€@“fôrÈ®TÌï +tj¦î*ÓX½6 Ðk5Ò$vÌêµ¶/0W"WjæsÃ:ÙÌqìå´ýïL¿Þ0ÔÞJ­ôޯУ±%°Íån©A›£Ó0‹N¬ç•ªùܯôÆâbÃJwQÛ<#…\®QÈ6@¾²àí|adàø^Òö‰\Ä@AiÓÏ ›]:äoe@@[O8¨I ¡fmBà´œ *æ.ü½2!`'`ò©Y›°Êзê0þÔ¢m.JØ)ž,kW´ oà0–$d' CÙ³Éè"lWÙø=l£êÄ›¾VmCðŒªøû2¾§môË.¾êneŸÝ´˜¡ŸÄwÉ+ïäë6Üb¹±/ËÛ ø».4ÿ†ÛøC€s.2|‹ÛŽlÎóOÜf¸¶Z¾~Ãí‚!ø„mnnZ¯Dš4°]ñ­ƒha»Ò‚1q„ lË•ÚéÙØ®Ž¡©ãca»@a # í€mì6Üxs1(YÜÎ @ {=¸-–>¤q½ÜN8Êøb1¾·å(¹Å4ma[ž ÄtÀ6¾ÆýJ!å€mô†SŒ“5îjÛ¸°²U†i×â6žÂõaÇí=„á•q,žÁí„û¿ãÆQgnÇN²=BÀIn“q€„*^7·É_Æ%hhÇm\ J¡¡·qWáªÂzˆµ¸¶ÐRìQ(‹Ûœâeã·ÀM[Ï~¼ÐYw å:ÓY§ÀÍ<Ò‰¶ÀÍ«SRR)p³ïJþ\ün,p“ ô'8qMt),µ·ŠVHš abq›b&®èádaoŠ1F—[Þa›ipÜ\7m‚ ÀÏ*n S™¦¢¸-VíÀÈÅrà6„Ò†Û¥·1ëXLÈ7éÒT³BÀEÒhy¸oXàŽÓŽ…÷ã20ÈÍ@z—è¡wäÆÍÚ)e‰Vf›¤.þ6 @±Àe7‘kÎ'pwš4æÛYà¦7y¹1JÜì¯cíºÈC¸éÙ€Â~)p£­Ò?kB r3H{°ºïâInÖ®‰Û„d¡ ågX:åG¹‹Øü o÷fïOX¯÷ø¬^í‘nèÚ:´õéq ªðbîæ‡Ç»½ßP¦v~xœ¹»^Pz½þæ.‰ ´ ‡‡™»â(a@b¸Mÿ–˜»uça$qã}À?ƒê}òGpwìpãpLÏÀáÈ,‡c‡ð<‡ÓF¤€âpÌžçîÔëôž¼“·•7]DJÖAo™¥·cø€œ¬ÂK™µ7Cø*þ¿rÔnsf¦¨§¼­—§<ÛÍCžíä Šu§]¦êõ¯jïß|.¶®1?–æð*öœ—Ð (nšÂ‹LN J´Æ,“ËÌ4H½@NÒV•EÞ¹±8ü ¤1±ÎtöL]Çè(±›@]YšCó­Ž<-WX¶'(}n<³8cQPÿ¡ùÊPJÒ¶`r´è4JT4MeQ(’µD•ÙÆ½054(ݵ£(Ï QžÑú ×(“B¢Ï4½nÅ"SsxÐ[¡Üà}ä{-)“68ýõ¡[I­jϑߣ±‹MÝ) Zr«1 ÿÕzÒ^†E¿ŒQ2Pljhžn·tÉStVíÌ`PNЍÉÝ%eR`ã)"‹tW•IæTL+CBØ&YŸ¦iM*âOeœ$νö…ÇsžÒ¤Ç@Â\h¼©I;>*O⿨Æ{iKšÃ+¯VJÌb*ébV^¡GkÃn”¯Q œϤ‰ úùŽ„¢ð"ÃkN8Ö™Žkšh–º8†‰Ã£8¼8l³Nè£.œðâð°çðu4UËáEÌqÊsÇÙQÓÄ`%“PÑI0inÇ6“¤WGÇPx…É~ƒ˜À §k ^ÌnpO"èHÐê ¦u<'Gxtɦw­ìd¼”²'ðB¢– ·gÇÉY^ãñÖbágrEà1[íX¢üc7hsÂ%Œ3Ž–eð ŽRK×÷ªfðÈÒ‘Å’¥¼úâÂ!lLeOptÇÅ98óÎÈAMàfná!K0Â51½òûLÁïdð6ÔfB-®aõlºˆ/D;`Û7îJM³…mºh÷Š·la›ïèS é‚tÛ43ã]íã*°°]xã1XÜa›!ž¹&æc;`»'±OóÚÛ36%.‘´Ã6óe­p$S9`›†ÓRéY’Ø&;æf{¨…mK'ZØ®E¼Õ ea»Š5˜2°]$Ýßm™µ°¶™ÚwܶK”8HH Û¥{†+ÎÛ…ñÚ ga»HTF|×¶™e/M …íLëĵ,ÞÛ’²ž'jgú&0K]?@›ÆC®XÈlP›Œ&my Amô– ýúžAmͱ„~¤µ¨MÛ2A¨ÈmQ›Ö^ÜëW@ŠAm<’&‰>’•YÔÆl`o×ÔFwµ3“IaÜxuƒÚÌŽŽ ]Cml3¦fDCŶ™4µÆÿµ¸I؆zçôÀMû=$¨4îGƒÛdT$=ðØ$·Ù›oqP‚¶%@4IˆÊŽÚ’¶Â7œïz 6 ¡a=Njc‚°/˜‰Ñ¨þD >`›k€+.4ØÆËÑ×)¶ñ;Ç×êﳫ¼›ÀÛ€›^w…a$p;ˆI¸YF¶ê ¸E›Á„ \°À \€¨T.Y|nüº¶aÞ߀»0¢/óPŸÀÍtÖ¤<‡ «€;Ðc[´„ØNà. õ# °Åm‰ÛŽûÀmÁû)Ö7·¸$³I-7ܦîð¾ ·ù8Á1žâvcZf¡sÃmf<PĸI &h¡i Åw?57ŽÖ†ÛMPË/-nW¦²À-‰Û<ƒ7B<Åm&ߤoÌ ?p›‡$¦·™Âníeá6H¸p#O©n¦Æ:C3Îo!7„ô;ùŠEnñ`!ä‹Wܑ̆9ÅóE nÈ™d:¸llÈMpÂ-"›EîLWú5Y¹ÅyPäÒ[È]3¦Ñ½…ÜŒK£Æ÷vä†Bƒ ;^}GîÆ|×e´äΜ¿„½<Ó 7ÖÅYØK‹ÜræRGè¹…î”eްŒý€nb–Á­`°dˆäpÙØ°›áÀœá¼»a·8@äÊ£Ån&f)¸[…nÛ°;B{¡¡8²lØé Vï]¹cw 1nˆê— "g$¾Ã'UaŒ2IýeI£±@˜žDõÜx ãía)sŸ.‹ÌßÿöÿþÃcNÕ8,†a\«éúZéÐñi=ÿḌÛ÷ ,?“[•ØÖŸz±ßýïþåïûwï¹÷z ê— ÌÒ³¿æøå×¼hì® 3> kóEÿî¿ý—ßÿö+–ðÝ;æE!ôí¯é¿*ZÔ“¨»è ¹ÙñÌGmH¶?YòÍþŸ±Žç›{žo÷H?´ -òY}|œö”2TÏõ£øçù’c~ç§Çèû¯~ëOpÐï. 1‚Õj‰y$x‘®LÚàèëO?­¿!FZŸÍ ¬â}ò?›æ²¤Mwò×»ÜëEš¾?„Ì1½ â#èɼSÓv ÀMëæ»Ô-”°ƒ×_ÔmýMß±þËѮ¿Ä¬ÿUøK¯¿ÃWñÓ¥H½’ä%jæ)~zëå)~Úvó?m;y‚Ÿfº¦ d¤žžNšœþËsÅå>g²Û,¡åI²lJ%¢‹ZÝÙz‚xr&ú™‹ü[’ 1-—qf4jƒÞXªjðrP¦‹ü¥(!ù/}ô“¤¨Šâ„¥•±#oڴŬy¦â„ÊÚÆS›â:˜ ÐÓx V´%æ˜c´D—¸£Êº<#2‡–zMRQMïf®–:²Øf½ŒÇbxÌSuáDy «z9¨ŠAoÞ! SÅ© ñL=º gÌ¿ä™æsK™¥UÕ•‘2™Õªw±6KÖ Ç-’#Ç3ÐoÚÎXg“5õœ°Rž¡˜^»3ß¡™E=9^f«*®¬Bs0âMqðºæ<^ÙóÖEx)ÏðEW‰åäÅá%eÓâ«yçÌ” ÒÈÍ„ñ$ærc¼ëv´‘úÌËà­ŒG 91ØúxË(64 ™hÖoÎ{’¶J¶1ãG5ñ(ßžîïmÌoÒ˜Šå#I†¶Î/VßIÃîëÅsñÖ<Ì98N€—îÌo2Óe,y ˆ&ª¹‘Å&ȬŒÇ–ºŽ,á5Ìl^ì÷Nö¬†ÂI¼^žFª¹“É•3oWéژF Ž9_&WO¦Š@e>Ưújž†Ö<7²cé"ŸQA†æ8)/3v²:öêµY›6¨1赕ÒúЙ)nYÔøØ–B§ŽA$}ndF½¶ÚÛ0ˆzžûÅbWJýB&Œ6Cc“¢‹â Ú¹sRefldF80î°¸± ëÔ];ÙñbÏפg˜lšñ*#ú…·TvÆK^ À²†qnd¶Uü¯·«±J¥™±‘™Ñ9Òûi¬¥ˆNÒÿºèú;½ãße ÚQ>Ð ‹ž,ñM”ç•×kLoÀ³Æm:qž&ð ànÓ0Ÿ… fþË|Â|¢?†Û/¬20O4$×c‰Ì3¹/æ:Þ׃FùÌ‚¤áNG½Á<˲a§Lâ ó|)¬06œ0/o…á\òAy†‘a™Ê4ÞP>3•Íøæ(Ÿ¸qƒ}ß`>K lfFÇæsÉ:¨z×­l`óŠ|*n0Ov«å±‰˜Çû½ gn0OƒÎªEý ˜gíBà|­£Ì­Åy–5užÙLë‰ól„ªÖ¨ˆ8h6ìTæÄГŠ7¨çV†þœü‰ôôŠz!À†ôt~ËÌ÷†@Ϩ”SõÒV)|MŒûÑXƒ ×}®Á^±ŠL^r€½4ÖZ™Yþûñ&… щöÒH=Ê]³§Ñ~4Ö–ë…ËíG#VûìÙ– œ†7À~¼¤Áx©ìÇ‹`fk8eúñTó‘ Æ‚ýht@1ìGc¢®°—F&°),Øozf“8…úÑÈ’©—Ä®uªLä_Þe¯ŸÔ#p-Ÿ¥e’[„?…±õÑ:~zˆx|£÷G¬ž×{|VïöD?PŸ…sï´>e±¯¶òØ b_¾f¿óÃãÝÞo8æv}j«~Ü£ï{­éýán¿hˆ…žñ÷½ÇIôÒ¢… ï4]+Éx /z1%VLzG_“Œó®ÿȲ]§üés¨ßgäL•ÛÏ «!d“¡Z±÷¬Ûž4úTw^ûLÛƒC€¼ÇBåªÀ1Ýöüs þž[yéЮ¼íùù•ç¶•7Cø€•—!Ø•·Cxk忌͔òJƒ¸Mx§Ëq†€Õ ÑþYEÛIfž"ÈÄÐòÏt’¿©“ȺðÐ ™Áç¯É\Ú^œðdÔ XþL/æ]ÄI‡mÞ:é|O#ÿAÉü^јk(ú/¼£Ò%ÙѧX4„ɾXÔoIÁòÊo~ýÛßýþ¿úÓ¿þøÃ1&í8ô³sPxA˜¾•ÀTpe!Κ—:·îÿúóÏÅåŠÑõ®tBÁ,@…&–’¦R}±® Ì1n¯T_’OÊæ$f™­¢Ñ†É /þSbAèåQòäù%æö• £ö†ÎǶ‘è«ãl 2\‰îØU¢/< Z°X{9Îg]žHÛD*‹Ò¦2}E©ÖÁ¨V±Ù1‚á®ËÅb7‡Â|À Ìr9±-ЀX™IÚF¦/ñ—ã÷èÜ£XéÆ8q§ÄNT( ?`é=%AOŒ’œ,ßÀÇ4jw]ž(UJ˜×Q¢‡i˜˜aìcsŒ*a[Tuyˆj≞…” Qeúbw~ÙB©¾$ë,ûcþ¹6t·¼XEpN°B‰õ¤  J¨f`©5cÌSLQÌ!L_Pãx;¨Ù¢º†¬ò|±3ÖG+i,]Vuy8Ïá þjcž/vãXGadÿ EÕåác‹Ü&ÆPTž/éÈô#.~µ*óȇ2¦ª<_¦&ŒÀ´PU–/ޤ0^wP¡ªº<üVa•¥a‚M¥ùЉ†PúË1#4U—‡ÅJkc¢šÊòÅ1ŽÄÒã[}Uåák÷Ü“¹CWI¾8‡‰â4“¹ÒîR2¿,Ιä{Ñy±~ˆRÂ…¦J_²PAÑ©$_ü^ >]e·"jj& °_!4ï ˆ’osŠÑK•›µWãŠ^eù✰Æêu‚#‹Ý5¤"ݳGËH‚Jò%Ý‘´Žn´©$_¸i^/9À$2eÚ]EJN·˜ cTù½¢TšTåÚ¨tº˜Ø$O ^ïJ³÷ƒ¹ƒ5•ڧɰ@jl°Ái&P˜ógqš>®Òñ§ï@$¶N&. Ô «Å<,€¨¥HÌ:h¨EúliîbÔÈÚ‡çb€Z^긡v î‘5«ïl쨙QPa¿êƼ ~Þ'¨‰yòB}jI9ÏŒê–ÍP PÆM¡×µdŸ*óØ æ3ëxÔ…¶ÿ2©y]zÆâ÷z 5¯àå×g±ºXx5X]â‹Z–¥\X]%ÉÝÂ\Õ`VVt'T3ú¸Æ;.ÎBµàÙz/Õß Ö$FÔ3 X'¦½XWŠk¼‚^nÖ\7ì‘q5°ÎÌ:ý¾ Xs%Z›“oÀº0÷ Ë[‡z€5‰7áÜ6œnÜ›÷i³8ͤžÉî¥+ƒÓ¸YâÈdÃiŽžÛÃâ4^¹sŸœ¦9mÇUcqš%U™¥}$w·@G<ãU8Î5ÆÂÛ÷ÚA¨Y7Ì;Ö¢u–wÅ÷úh_Ì’€‹»ßhéP¢ì“<¤ìÈêÝ—¤µ£6`tŠL³‰N@0Aʴɰqõ]:¥ëÊc5¯$+]×N6syµiЖ³(¨m\¤ZV4 ï W‚Sº¦#à|\;³³2¸7´ÁìÕjÒ}“YÌæn(Ülõ ằòÆQÙÙ⮃pu÷me0›'œá•cCoÂ5a[¸Æ!iJŒ3˜Ízde¡ÆŽÙú4˜‰6KA0˜-‘¥,f3³Ò­ÜMÌ&ئùÃb¶ì®µÚV¾¦ËM›Àl@;P£Hó¢2 M‰·Ó±ôjÓ Ãb³ »h³ ÍtW¹Þw‹Ál¼sW¯`P›ÂPw»µ™/ÕKiµ º¹i hGfp_r¦Anr½¸En¦Êý¦­ rK^•õHƒÜ$ŒÝº r37úH-rK]ÌÓHa‘;ÐO¡Þ»EnšmVB|‹ÜŠ]Bßä–ŒáSX°È6ÑuZ䇨9ÕÃ’WXmäV€ßM*RMFXÖÒ¶Wþ4 þÂ?H*¾Õû#6Ï~PëÝžè_T¤âúô8»—ƒ"ç‡Ç»½ßpÌíúô8©x½âµ¦áHEúyÑ!Ôe Çäb¤dÏûðû.óiRqÃuâY¶Ôy¼TïSÖ¦x`vjÉôüÔR?HE3„ –úA*Ú!·òÒ¡]yÛóó+Ï!l+o†ð+/C°+o‡ðU¤"¤uJïâí÷©h;yˆT´Ó)Í‚6“t?E9Ú¡ê¬;´™c×Mƒ ´é °žiQ›Ù]¦CíÈbÄO§A›ôdÎþæÚ hóu”œ±¶7§…m€WI^ lsjOga›4âÛ²6)Õ•b×Â6=@ݳÁ¶9%lç×(›8´ ‹Û$c' fq»™Ã¼á6î–˜kq»jYÉâv¥+ÇdÈ.ànÅfÛÜ.ú"ˆ7äÆK6K‰ú´ÈÝXÏv)ºZ»´C Þ‰¹¾çºð&×·Â6ðfvúJçß‚7gåï²iÞEÜ^¤Œñ Þ^+¿'x/Ø‚·$9ö· o&\^ôêÞ‘5SnöroµY—ŒïÒµ8dÁ›zÿfx 7O]¸®w ÞÅ(XxGœ¼{œ¦„CÜŽ+[óÞ$ô×ý#àM®>ÝñÝ^ñ·µ›•5‡©“? ûzñÏrxoõþ„‰ñ~ÏêÝé§jo}zœL«IqxóÃãÝÞo8æv}zœÃ»^ñZÓô ^+UF%?Êá¥Êêò• ÞÅ>Íá­s¸Nü#ËÖ‚:ïžCõ>ed|`6&Çöü<“Ã!lLŽÂ092ËäØ!<Ïáéö!žthWÞöüüÊsÛÊ›!|ÀÊËìÊÛ!|‡Yø¢EQrãðl'qx¶“§8<ÛË^J5²ü;´Ðü%ªbð~ü§Çj/H¼ÜUì$åÂTA›%óp ƪЙùòÖ}JÈ+9ÄíëY‚¶*`ó*ÇàµUºuÑ%æU‡º$$õÛY¢‰æ`JœvW$„mds¡?q_>Ö%¿à¨Í¬…úº»r¹ˆr*JÖ¶à’5»Wr^åy¨O)M¥ä¶ÊóoS!¥hk°”_š:Z)y%$¢±ã½4¥¯k"¢T?ÓIä^àR3KÕfêa‹¦+µ­ú(<&©Ê·x¥º~oYÑøÜ´;W§Í BØÎµaŠ™…HBÐy\ýFáõµõª7±wA»*õõ¹eI5.çÙLì]{ñºV©¯ß[–2ôr‚­ÁX‚&K*Õõ¹e9+‚±F}Ç€Žé¬[£añ˜†nZFkÚX<åR“añ­p·9’¸2+P‹XŽî5o,ž¢kÖ6a&Âê·©²æ-ú®¬˜ÜZ ‹´½Ãâ±béttÇ:iÏë“U«¡ñÂ+ªi©Æ®XÓä¶Ìתí x½¤vR»óÂaïÕÞ[RÆb7ï–8ÀíÀn"Ö´“mØÝu¢¿ »+oÍ{Å-vÓ÷sY™ v‹µØM;¬Áî䢸0ØÝ7|{JXènƒ¤¼Øe Ý͸.Xèf¡à&¶èfº®²0Ê@wéd„Š< ›yùbÔˆ\l¡›‰ÅÖ™´Ð]û¹¾§¡;wÅ‚mÈMÿ…›±À%‹Ý½+-p“Õ]T…nº «{Ð7ž©(~ Ü´c.׆ ¸£ŽÁº€ W×±ÀÍ@°¾@Ö7ù™>C$-p“@Ãutñ¡¸™EtEÞnÀÍÐŒDwãp7ÝwVxÏ Ü“š2¸²Ž´Ýp»2êl3¸ j0Ýàva&¶{i6Ün$rîé?p[Å‘m¸YesaúÆå1”-4é·éJ„³qϘÁmI9{ì-nÓ3C ÓàöèÅÀµ¤/fÙ ®1Ë­²pM:qqx® T}Z«¸V.×t˜ûïÝÞ†ØL:qÙÍwÄ&›à'ëo›àïÐi ØÂNM’˶xN-!Ývì:l†­{X6 6÷j›ÄÜO Ûäóœ³M#¶Ü9‹G1ˆÍ6Å!ÄN ZûÈ 6iGEÄÆ4ßk{$Y·ŽBlÜ'X„ i ›ì¨÷3nÑ`vòQ§Û0˜MkGÏ4 f µ¹ä\ƒÙl»dû³“«K,Ø0›Äm[DþÀì$%8—”§1›úZ_!R³é©™êôf2˜ Á‰ œïíe0›ßSÞ³{3èd0›Õ[—a1»WíÃf@›_[9 ,h£í o h÷¨S]XÐfJô°€Ò€¶M `A»›D´{Ô¥m¾Ãòµ± Ý^SÚÍÞW´ée¤n\ÚLJàÓBhÞØ‡,ÏrÓ 7ÚèÍr‰½YvIˆ½çÈÝr’Eo¦ VÈÞÆŸZ(¼›ÄkâN1ª]¹ÛÌ-?»”1|Æ{³ÿ'ÌŒ÷‹|Öo÷HG½("o}zœQÃ]DÞüðx·÷ŽÉ]Ÿ'ò®WýÎ_Cäå"‘Å©ÂÃD«ÈKYF§ü-yë$®3ÿL}¹ëœ?Õå ò¤CKèØžŸ'tZL;¡c†ð„Ž Á:vÏSyjá®þ.oôh×Þvýù]9†mñÍ>"Á«ŒÁ®¾ÃWÑyø«/P†8õŸ·õò¡·õò£·uó¥—“i$êl¿Dé5–÷ï?>–×bµ¤ž†ãä´™!éü(-%mf CÒôRm©jWáMlz6Úݦ!:­ì5)§ÁWmo¹jÃpUfVœ² 3Vlšzí¯Ë0\UtO…± ‡ÅJ¶ê´]¸j÷ÕÆš(SeÃCúJý=GÛ…“ö"nÍi»0›Ûm3nMÕçÛYe[UváL+éT-[wÊ.LCèTÆ[O:*¯ëD‰ÅP?Òµñ¥;§=…6éïè¨î’¶ 3/Ôtší®jËpÖækhh6ÙO/SEìR^oÜ:ÚîX3 1 cŠÓYÿd1zد+²«³üÉbô8Ukì¡jFy«Ò{tšÑkxç”Y”DÚ’eô0ß·Q£3•Í2 3ÎjKÎfÓ q¢{JÊ2LøéCÜh¡£HC™–Úžfô’Λ†Û|še‘‹¡Ë2 á"Öù=®ð² m³é%iË0‹gÍ6½TÍè¡m£: Ÿè@Ò¾ÒNöºJ‰w½”~æøPŒ^Ðéÿ:]Ï׎Mšï¬y²=ì<7ÝtñKËè©Ô‡½;ÍèÑ]{ò#§Çx «ÁÞ«6©s|í–q¡3^u…S=EémÈ&¶7ÕJ‡·7w÷\¹ ¸«Ž¶´À°3ã¤Ù7àæ=Ê-pûðÀFe–2,pwÃÌäæU ¸!ƒÜ´AÖu~ rÓ ©<,rcõÛJôj‘›±! J rÓØ¶r'[äîE;Úä®I#©EnæÑû)änMG¹[Ôô–EnZÐ j›æW¿2Q[ä®QDZYä.];\ÐA¨A Ý´t+¬1ÐŽ”‘ÔBw :ÑŸ…îZu0 Ý•Á“°Ð]¼¤]®'pWe€»6g/ R Xà.&-­n¦\þ¸ Ñ+˜]H¡­aÌfÁËÅå[Ìæ¦Ó¸¬1»ú•3Ô 6#*—é×"6«G.Ð"63rJ¹±S bÓÓ*M—‹ØÕÐõ±1Ç*ØÊ"váËͼ{±Ù_Ÿ»øR½{Õ³ ¤(ÝÛâ6K,ÛPÛÉÒ 6“C.Î{CmH¹}&1µ¨MÒh]rµkcΜ¶y¬Ì¶“wær1°íyänIÏ¢¶ZxÜP;êÓ voӟ 6i6•`ß 6ƒ•ßÚ†Ú]ÇjÔ)¤çÞ´¨Ý³&ªOÔö3ÞÝ¢6=ã”,jãâQÞdVÞî:GƒmÆv/o> Ú,z»x¸ ´ñŽ*²kí®Ùï ´é¾djÚ=ê`¸ ´ƒ¾7ÐvºˆíÆŠ“K µ°ÝôÎ3°Í‹jM•Am:Ý´™ Ú¢6DuŸZÔŽ:•ªEmÖ)™äVù¹+Ó¯,…Á 7õÊ6cè,rÓ°¿ä2ƒÝ¤ÊZ¹ñ†ÝYNZìæ| f»kÒ‰b-vC–[ì.âÛ0÷‘Ánô×ëtÞ°›µ[§cÎ…Ý&¿çû+ö¹Ò“÷šØS§Ø°µ·>}@Ç^“{êããìÞý–wÏõø½*Uˆ¡mE?Ÿå÷ª¸›Æ„¦¼‹K|¼‚Ÿ:“ëü?²t÷‘þLšwʲ5Ò…óÉ.·B~¶ï`zòAóÙA|Õ“¢oÄ0}z¯ù.€(E†ÜÒå¶lß°F–»Ì >bÈ ¶`ñUl_)L?qîÓ±}[/±}[/O±}[7O°}Tñ^Uêð%²ÏP}y®hž\ìwUv DУî>ïXƒî®ÊNã°\Oјlˆ*&€Fc(:ò‡ŠÃk(WÙV•h IrIUvñ Ó³ÊA­YEÿx×çWéïš}ÍbAB[ZÄ–¸Lj¬—¤#ùº*ñá]×´ýWf.4&ÉtÁv 4¾‘Z mbȹp³ì—BU›)†^ 2G£aþ‚Ø=/Ф9/M øéN—…¡,ÈäðVf´ò¯i*UòIQva­ë}ŸÐQ”]Ê-Ÿm4j{•ê•“Ú Á’gËÍz8{eÞgya¢1I² )Ê.ÙË[ÆAzÉt±dx?'é‚d' ³ÌShL¬6v²„­ô‚hÔv Iœz:½Ï†¤R?¡Ñˆ‡Þû˜ݫףÊïã‘uZ]±Ð† tº¼"5è°oï|uhÂCç6–äÓ€…A.+jÉ&éTº=«Ôþû˜h¸ ºø¯“âc#'ŽËl„Ÿ*lD Ð‰:™ñn–QY8ž\gj\4&ã§j| ­Ú`±Øb|Rúcl`¾ÁâÐ(çî ì_ÃÁY’L¡Q(Ä÷z­SðÚBaÒ¨¢ŠÉ½%ítH&=#å?ÆþE£~…;—«²É>VgoÃwao6TïÌlÖéÔ¨N†IÕ²¨Þ™mæ»ÝPÑËþ¹¡:S­å;ÏÖê¸-UV¼ ÔéÀ_¦'ÆêìºJ-¦óî³Ðîé-h.iƒt¦[]H¤c[Õ@¼Az¡Æt7Ú@<ÊÜß@½š¢­¨Ã6m Ž­¬b†,¨ MuÇn ^L¹Ô ÔM¶Ó Ói[Õïa0dÛʱ¶a:¥šeòß03P”¤`0œ¦–1 ¨SJ¸¨çörm^²Ò±XúµÈŽg*§™ ÙÅF5¤6d/AçúÛ4Ôò'Ú •ÄÚLT¼A;%°•/bæ}í_íïgwtw‹ê>Ñ=èÂɼKνɛìð6ÝÀ{Ò9vxæhYxÌk¯® ïTzW¦àÞ³©áj0b©f&6Œg`Ý]¤xGx§“Qì½£Ð1jêÅB¼$O]ûÜ¢¼)šgP^j(Æ¢Ú Ê탳£¼Gk±”Wlè󼪪û Ìw§cŽ7˜oô€›äìŽóÕ[¿€žŠð¥6œ÷ºˆíŽóÙ*.i£•kâŽóP"L£Áyf_©y\qÉ5ÌóRZ~g晲t•bßpž~Y)}ucU°ùôÌä¦3âô$ûVÈüôIâçc-Ðwe{úÒ´‡Óô^ËÅç[Ô©¸O¤¯YKâé£Qî-Òc¨r ÒóBW‚ÎôxÛû=€~ºül0OHWã€ù¨Wðý$#D?Ì7k-¥ ?Ê€y\Ph?=D0¾Ñû#Îë=>«w{¢ŸGþËñNëSYÕÎr’óšËûÃãÝÞo8æv~âÅy‡ =ú¾×š^Þêö‹W_x‹ÛU“áÌIN¿ÍÓFý­œ" Eò¬C&óù]=N)ÎS¸Îû#‹vñ§O¡~Ÿ‘{Rj? /4ÜOë½çh|±C¸&)¸4KÞ‡`Úš·Ö±A·=¿ÃÜòªxnå¥C»ò¶ççW^Î’]y3„Xy‚]y;„·VþËÈLù®4L½d›ÖY§ žDÕ׳‡¦ˆ§Tû!KÅðW¥õl/E¼ÁéLòðÏN·uB;#N$¶ùÓ½DÓ˯~í?±,ói’qÂuÞY´ÔiÌTïSV0ë³ð²SM¦ç šúA2š!|ÕÔ’Ñáy’Qï0Uà—íÊÛžŸ_y9KvåÍ>`åevåí¾Šd„´ Åˆßßc$£éä1’ÑöòÉh;ù*’ñ D`ÖÌ•íì=Þ?>HáI”IJ³üEi™ÖH$ÎPx"­7FPcŠëí­£A€råã]¦Þ©¢'T"Y€ZÛ¼*z"ÑúeN¡±›:š¸K±´ ‘^ÜrÙ …—gÓS-†2ŠÃƒÂ.ÉÃøžåðDÑò¢O±>Êtlæ×|…Z”ÄJÉÅT‹^ššø4LVMÞ¼¨š'©õZâµ°EÕ<ª«Bd÷Cbi–©¢%ÉkÍ5UÃáyZ^Zqã™U[Ê• KBS^åòÖËæ›ÚÆáam±ÕÆÃÚÆáA}L,ð!m‡W çÖ º`ê‡WEßë†ÃcöYæ’U>uÃá1`¶BWÝ:;Ãá±ö•ÃPŸ¡ð* ñ2gg(<ÚŸc«I<Õ³×UW ú Ô²7ÃRAÚTÉv‡ó[—ËA•<É‚‡™¦ð´Qß Ãƒ]žTÉùÞX^yfÜ8¼Š‡A+ÇUò„à ‰F9±Kñ£¢ð:ÞÔ é)èIÚ2Nä ÎÑ<9<&›r7£@ªÜx[_ïeUòDf›Ù±gålH¼€1¯¯©Š'|$+i¦&œÃ¸Êë€WÞ%6½“ÃÛp;½Z©žY‘ܦ›ü4êZØÎ,ÄÞ¿ï°E‘8!à¶Ã6ͬ›ÛÚdðj»ò…í¨ÍêF-ƒÙƒ¿Oõ¸c¶ðw±ñï˜MÛ%׺“›ÁìâXƒ²aë÷Ö˜-¼v$nº~`6mžø MÌÆuUÈ_וÆlÞr±µîOÈfÒ‘Y,MË “`5@vgX?Nb#јM/—Ìf“Á ¹¶¤i1›T@Áÿ/âÖ`1›)X›ÏñºpëFá•Ræ_7//ZçÂl’\A6d>0»>,“:;0›–YŸ™þÄìfhK‹ÙC„½r-·Ál²cž)>ÆÙ7K0N†ëÃùÈb6«xá˜^f[ Ú|?‡–(œí–^ à„RwÐffh"ž Mæ,FHXãú0 Ý²D,ÅqG[Ðn’}¤‘<@m@4æR/h£­ao÷qè,h³¨”º4h³ž'.ý6ä9 Ú¬)…÷ÅÖ­hã‘t! ~XI hs Œ ø´iÌæ—knA›ý)·oA›éRðô\ÆýhP»1—D®§i±5$õƒ,žîÒV€á!psï·tr3·Õp‘³¹  ’ç‰ÜŒÄÄr)ÈM¹ :8›eþB¦Á}ˆz»™ciÕÈb÷pTëèüŽÝ”™>Œ‹Â`7åÁ :‹Ýø™Çç²cw ,:W!#ƒ®±‚C¡Ïõ»ÙÔÃ̹aÀ›Ì ›nq»yiví)íØMÒº¿Ä‹Ý¼ì°èt<Û±›¬ùÖÛŽÝ…øUâÊŽb°›Œ"äãÈ´+;vó¶k¼YG–`ƒÝd q˜k¾^»ùKˆ Åòm°›×*ÉãËgÉb7w6´ó87‹ÝhÃíˆS–Nè– µ›´Ð=âDo/H ÝLÿZ¡uÆx ·”„ü;œ6ä¦oÆÙOà&õ73òÜDã˜=w7™MÌ@—¿î.¡—TTýÜôjöøi¨‡¸ébQ¤Ðf?€›N3ÃÕæ”¶¥âž) ®Åm&>ƒ{½ÁŽÛ)âCï'nß’ ·£¤+¹tû ·¹â+0nA‹Û…ÞwR‡ ·éFÜpǬXÜæ‰N8ëãõ· ëŸ^Hþnèz™ƒÿ«­aE#ϲÓÌâ=›È¬T?ÓåLlN¬"MÚŒG^‘ ¥¶UÞ$ 3‹É±j¥icp]¨YiÓÆà\_bK’’¥´¶2Q]c¢É2êq•n¼ú’ÄRQŒ¬M=ë›äŒÕc)Åá Zºƒ$ql7¢[*Uõ{Çòaxûîª0cÕiƒ˨á¼]kZ©«ß;VÚp­d¹+«×<ÓãáŒT“6mQH¬šÅt°’j¦RYŸ;–5 FÄQƒ!ð³/ßDc¥²~ïØ‘y•åÄ‚4i“‚d}tÌÁÁù¨ÔÕçŽÅ÷ø¸<<ËkÔ6…DןÝEmS`IÄiž©I›Äí;û‹¯­ÉÄàA±Î˜×aZ‡®L ‰á‡ÕÅ&.ü5k“BН6Õ¨š•I•ÿFeLYƒ¬M œK öÅ-Õ¢M IRŒ]ŠJ-Ú¢ÀIJ8€˜.dÑ)!‰ã˜…‡«U[0H aõQBik5ôökŸ`S«¶(kÏÓà6nò$6R’«ï3)¼‹ÀÛp[(‚­}à6ÜC E¦Äâv¡¦Üáf·3gΰ¸M_ë\<„‰¸ãva!L× gp›±Ú•¯!f< ÛbÕj÷ÚòÛ€A Gr}P¢¶ù=G?|/VnƒÛŒ…PF7ƒÛ´”Æì¤¥ï¸MKià\›Áà6éDI]{ͦÆm¶AÐòypÀ·É¸Í#aq›Md.†Ââ6m¢Iˆìpàv§™»1ƒY9p»£«^x)‹ÛY %%˜?p›—.¦äŠùµ¸6šeq»Ó<¨Fé ·{ Ç+Á Åm¶a¦ÊˆE±¸Í`¡Šþ@íÎTÓè?¤´;3qcÉ£Ü~´æx µPp-ŽP9 Ö28Ü–ƒk6`Íš^ç|X°&‰ˆÕ¹ø Ö5{+.K9i¬›,$“ó׬لºËZså°qxåhÍÐ<,W–Z‹Öò= ¬Z³¿–æ35\ãpæ¹üù€ëFw¤ä/W ׌,ئƒ±xÝ„À’, ^³øs¦÷S<ñš`Ièû×dî’'ÏÞ¼¦[ Šux(ÌYȤ‚á}µ~ÞMÝYÈ.jb•¨²Y–<î¨,c!›~;)¶+6ÚBv”ôldKYfÒ¾CÔ¦C†SB¬ìH_¹L~Øï˜Íì•#Áy:1›Á@“9Þ0›8YyVOÈfÑ6¬¿?$mF%òîÆ›§±%ô,oº#¶g”—'bCÿÀ¡tÅç±›/²ˆÝà‡ëa\± «ÔB΋—t«›ìW€„~EóoˆMχoˆÍCY±1½…ظ;Xíü”´¥šÔŽdl’mŒ‚ë A {!ËDmpME ãwÙŸpÝ´ÊØ´ÏX÷ ±EPè¸2ۉآÆ>"*7à†¬* å¸b^ÜàŽŒôejz ¸{ÃËÆqQàfZ‰M¢Ù7ŸÉB8Þ…¸­—Šn¾/~{7õW\qWÜ¡nŒedÇèe€›LaDZº7ƒœ±‘Âpì´ÀM¢8tùiYàf]ÉÉm¸ÍÃn…ßâ6¿68örà¶8,Qëm'ns(²§j9p»KòQ쇱èmüyæîî6q|‰öÝmÞ–‡iíO’woöÿ„yñ~‘Ïúíé¨Eß­Oóh=÷EßÍw{¿á˜ÜùéyúîzÅÑïýá«è»\$˜‚n„¼÷(}‡K3ð ‡ ÉÇÿfè»u׉¦œÜuÊŸ?‡êòGxÒ¡¥qlÏÏÓ8²v–Æ1CøG†`i;„ç <µÇ:%¯ç¼Ñ£]{Ûõ¤x•ãdߌá#r¼ÊìêÛ1|‰‡_±îËì@`zŠÅ³½Óšª."A¸)„Kj,„²h<.`¹â¹ZwŠÅcÜbsWMªÖ“eñ ‹æ‘|©Ñ¹u‘xôfØI³6婬¦ðb©T)ëî’æð˜ E €$i«šÃ3bÝ;eYÈ&ŠÔ¹âðè9of ½êž%EøËÀ¢šƒ1è4MãI¿Àê‹ÂtÖ=™Æ…ÌÌðØtEŒ=¨‚"$.¥Ö–ð=ªr"äÝàd|1i OBµ2ùci«šÂc™¦ÊÌ–Ü?=©b"|f˜ÏzJŠÁÇ4¼_MU3xK×Ê5Êì4ƒW²qW|žX£Â°àwÖÛËcTßÖÍCTßÖËT_e‹ C ýy¦/i¦ï/ÏÍ“[ýNúCßSøÃêM("±t—c§]", }`µñå3šðo£ÑX¨È—ÛúÝØ½FÁ{?j€ÐÝ´ S(=*%Tj£›.Ö9ç*„«NáV_W( TqMQ~Tؽ¨èW#;®zìR[`ظãh4¤_á%St~øðõõc¡0ÆJè.Çž™ÛNê*Œðn¤‹¹p¼2ßt‡õÞÞ…¡ôÄ>êÃ;CüÑT挲êÔñïrìdþVm1²´‹ú+4‘§»ÔÚ ÷gÒe¢±JN QærÕ4ÂU㺾»ª±³-SÙ/×h‚áÿhf†º®šóÁ€K7yfTb‡QŽß¬,‹†Æ$¡£RNX»v­€4Å#Ê,…דä6c#¯Ð “ÆHHÁÜY˜>J•ÃÆÄO!\U¿|ÖV‰ÔYËâŽåA#{odá¼F=”±Tøï,ß %^!Œø#m˜` ¶T…ÑhÙÀŒ¿¼È-´UšÝ¯œ0ªñIc5| Í$‚³P2h4„ K º;¼’ˆó¾r°e¬m¼&õþ¹““äÉ u˜ Ñh8AÆ!Ìxj3œ óo1ü$Ž7¡æ?7r’}ÕË=³]Ó‚UjÜÇÕwà Jz.ñ݉oﵓimwAH´¥Wœ;™,^[[.¸dMœ‡Y JSƒ„Òîs<ƒhï̧®”¬h¬Rócld†(ºp'^½î~:ua£ú÷I[ï­²·á¼B)|uâ<qæàǶ±0O…Ôo&|ƒùLƒã톰¡<$f·]9Á6”(h#ÎÊ(¿Xû0”§Á¸Œï~ <JR ánª6Î/ûúÕa7aâ¦I¥g@^" îœRŒ—÷¬ñåßÀx 8Yu3-ÆÓl\±¯Žã¥ÑåvÑä¥$-^-  ò )}&س O‹30çŽ_µ(?ê7õ|…ˆl(ß;¶8£ B9P^¤V…såÅœ!„ºv‚|Ï’l¹Z97ÈwVÉ©©]´Œyሼ¿Ë€YÇ(Å€ÐßyæV«)],7g\DÌwìÃòäžêõ˜äiJÅÝ€‹¾œ ORNêÝ7€5?C:j=\Kl@^ff&Ý@žô!ÖÅÅæOg²×ù¨]w‡yš„YÞ/ø|‚¼¤Qõ7ű<ë­yÒ~¢¼ð™1ÆtÉ2å‰ê!Im½å9?+g†ò]B}1¡C‚´(/@Ù‘…qƒyN-DW_ðX˜g¸`²ŒTŸÎs“DHu~LÅyöY=«qB,ÎoöèAZÄ—hþ}¹áÞO&nP©]æ ÂçP£<ëkîPÏð z%iß^"ÔX¢ RúÏt’¿©Ç‹ˆuÜr?;ù.Õô’*µúŠk³ÿÇéó/¹é¾w/'ÿBŵhÕ5ýÞa”_$ÿ4Ö*º“â)Çõ‡ÿä1”ßüú·¿ûý~õ§ýñ‡cLz×|áæeMµ.RɧDû*ˤ•7èdSúðÿûóƒ¥}U•X­K7U´l*Sc†7Rh#“K˜ÔFý[¼J‡5ƒù°îbë '£Åa›e[÷b²éL=×Ëeærtð}¤sê8¨Ÿª”H©Žôe¾«tNµ áòŸ¿ NUa©b“¬œR™Þ©TN•e«D– 8Á­*,•´lÅàG\U`­Zqrb[ )³]5Ÿ‚¹œXiHFq¹Ë#ýÈå4îtç0´ °Åb8–°«´=•–£“øœµY…¥rÆ%žXa q/÷ï*Õ7¨aŠ%/DU†…ßc¼küf`hø qU´'ûOÿoýq´-à©™oç˜~Žma•Ð $7§,CÇ÷·ŠÒÈåÔså´pQGi¶e•ˉÓ2~©ê¯ða>çõæqâ¢páÒ¨œŠª¿RY°~Áw(*SÜzXQõWdQ˜yøë‡ªò8É Z©Œé‘6•ljý‘?¸7AUX8Îȃ?M%râ3ï÷MU`á÷\¥GÆõ=•ɉßKmFT†¾J°ðk¾Æù ]%r’Éõw^ÊÀtXwÁ *µFfuŸHúæ.$kɤK]¬Ñ©0PAuãæn¸¡Ü…ð ªÙVüІjÞ‡øþІjù^iL5šv¨f›ºc T7†‰–4ÌŸTóÂÀѪ1“LÉÇà³°CuãYïëÕ5bó îÅ:›óPƒ×”øYóÎEÓpÝ =uek¸æÁ&½#D \7f_T©ášm¸;ÀÎÀ5gCOÃu#áý‚r×cñW£~˜ëÆd‰ë h¸æD)Ä0pÍî$ãáu×k¼f›RÓ ^sa–÷Úx¯±\¤eïWÐx-o—ÜÄQ Û|;rE#ÆÅÀvsL9¥Û|qy—šls”®Ò­QÈ&Ûlë%Üf`›Ï¤\ͶØæ>Â5<ß\Ã6¿§2‚Ü–Ù\’Ó­ 2eæÅ%?I‹è&–¯­¹C7`–¡åã”X䦿•Ë÷¤XäÆÌ*ÑÏ"7‹úaÛu=€»0Ûåða0¸ÍBæ@ ÑdaM®”ܺÐ]¶ý%Ûi¼?Ê%żvL?ãïÐW‹×´¸uÜŒh±ªëÈŠÖÚ·MãµãÕ±ðÓˆÖdˆÔÉ7¢5Iu·„?#Z3P rðlF²î…,á½d›dÝô%½IÖ,Ý<φ•¬™s‰4›dõ¢ùš7í¢ÛoùšÀËb£þÀk¹âR^¬|mŒC¾f*üZÃò5¦QÉì»|MO´kx]é¾”ot¯éiênÜÄkˆúêF4âµ”iª‚Z¼¦ð·”ÕM¼†^ãÖEjäkÚqJòp3³ò5»“b픯«‘KŒ|M¥ƒ‚*1›¥®X9Ý1Õö%uY9›A–nb…•³+è.NiÅltÇï_¡³kÑBå!fcšV›³ƒ¹áŒœþ”'r6ö‹’FÞMmräÃËz‰ÃþÊŸ†ÑŸ­OR›oõþˆÝ³ß4Øz·'úÁµyúŽ‘!„³ßëÃt{¿á˜ÛõéqjózÅkMÃ7P›ÖQõYj3Ƽètù¨ïaQ¿™ÚŒB`ötuîío“Ú\H°0ç‘S‚Bœ)Tõ>EÂåÎ{âv‚K÷üW?¨M;„ ¸úAmš!|µ©w˜*ó÷ÜʳÃmåMϰò2»òvϯ¼g»òf j30Œ©fñ€|ŠÚ´}#\3vmK(áš_H·`geëžXb!º‘­ûÒwÙšéœÓºb­lÍ4&ë&²²uÓœ´•­Y©à5œV­lMÝM^n“­«’r6Ùºj=k—­Y½ú† +[W&£¿U”MºÎž¬tMÈ[o`¥kÖín·ûÛ&^g­©lò5Äœåca%ì¨ê&a{í3±IØÔê&m¶½:­„íµ§”•°“L i“°ýòT>$l§éC‘°ѽÜwÞM²²ê0v²hã°qò§aXgë“ôá[½?a[¼ßã³z·Gú©š>¼?}‡WZôáõẽßpÌíúô8}x½âµ¦éèÃÈ{Ñ×]*Á>J2-?Í.¼‡©üfú0ñºÄ ˆK¨üm²‡ ä<²oZP€ó ¨÷)kW>‹p‡dzþI†`9$;„ç9$Ù<–C2CøöPï°aÙá¶ò¦çXy‚]y;„çW^޳]y3„¿{YÕ¡EQ¸žbm±‡¶“§ØCÓËìaJ52‰•Ë,ˆø³ìáÿßÜ™%Ùj$Aô¿SÆä° -¤Ô½SzîA™Iõ$®éO¥|\¦ä@ºÇ°íêþþ o³¿æVˆw#46n¬jÌϤ1ŸÈ«3º¾x¨~_7Q5P´e»Ï­ ˜«Û|È_0Õýˆ–3“I?Bçš]2ú1W7&(¢ãÍ] zæêE-¬l,(¾êaš¨UëÕ¡°ª—˜±ƒCtð¨Þ¨GôœÁê¿ _A£T”÷œ±Påâ)“¨yEÒ²}•Œò\^ Û‘^‹rO=/õ²Þ.š¹×ŠÖ§è¸y…"¾ä6ŒjëÑtÆó‘ÄS»ˆs¦¬nÑÖ.Îag¥®ö¡Ìʼn,—:Ä9Äí*÷Šͽé D‡9UîØè:NçPòTƒ{®b=®Ûœ,n ¾Ö-4ˆ÷„µ¡Ð=Úš2Él«hóS8.UƒjpOXs³­©Œi=mËÚFè9 ªÁ5aÏI¿¡mm£²’Ø ø„c-|²¶‹¸[aý6{ˆnÅ`ùAâšlö[QhEÄ ˆj.`´"âºôŒû¡k‡ˆ•üÿv$÷0ܼvˆ¶Q糫É=lõöwZMæámlbEçžnh´–¥²ÝLÒF•Ù×DÚh2ÖO©j aé-ó0zß%JenÏï‰ÅÛè0V\ÐQl7D‰xЃbŠ‘çª(µ‘WûJm” }[¨½ïÑ®ÔÞwreÚêñÈ ´çQÌûëÏ€@é‡sÞŠ”@Š9o'О/dz>Úð1iê ´áVZAð3¦ƒ¡möçYiým¸¦ÔŒN 1Ê"hÛX$Ü ´q(=ªÚ ´q,s‡´»õ]ó€6^Õó·ýÅ3ÎôÃJ 0ÂlØ%L¶Y¾Ñæ@¨mñ5,Ôk…Úç˜+àBmŒMØßç,Ô¶ý…ˆÊÔÆfÖèìlø%ÔÆØ¼\·5!Ô†KÞ´@;ùçíÓ팫ÂÐ>sbý5,ж«I/†¶m‡’ñ›9LmKú‹Üp¡¶y9#ÔÆÄ£œ.Á6~³_‰¶Ûf:/þÝ)ØÎ§ÀضKÖ ÷ì#®(‰à!÷BpÛ¡ÁÊ}D%w§š/î2ŸiŸ Ý•-ŠôÅ=¸~FB7Šeú£—ؽñMWv[‡IÏ vc³Õóÿ”Ýeç”áïJžNb·Lie÷n- o2±»•Ý ŒZ%vÏ%Ÿç *ºñ“QDÑ]¾¾avA¯Öo?´m̃² Gˆ)²áÜ®þ‘¡ÈFèæiƒŠì9Ñ:ý¦ yÞhõ}½§/dc-³úc¨ÌFõqC'f7kàx½N³;‡&f7N¡OÌnœ?œ˜Ýøõ˜=?EWçÊÌ&¿,1»pšsbv±¦é÷eh°tÉ2´×ÈîKÐÞÉ¢~0›2³7¥0{nǧÀÌ^¥ØNböLØ3ÆJ‰2‘N®Ä^‘®ìA™bïdõ öyÓ„ÕʉÀ¦Äê•›/«ïlû±{ˆjöWý?ˆ<§ÈiÿyJëÓ?üvÿoÈ‹÷‰ü—Ïî•Jâý׬¼qŒp¯?>°Ûû Ï‹½î ^§xî×ÿøñ¨–L½Íç»mï:ˆs}³!±yÛ¬;ÂçįU´@Wò§…,ê¼Óbð"Íû, 3:>a"b‡ÉJ’=ÀJêWU²’ôÞ·’lú¨•$‡ð‘æØ@ßî÷]DÛcº÷²ëOTÖµcЛ¯ÇðÒºöHëÝ—cø'ŒÄù¿Ð‡£# n¼å$¦¼d%¦½¼å%ênÞ0dìÍ*ú¬üI Ó­±™øÿßßKE„ÐKÚ4bJ/s2 ̾p Ç–Ÿ"ýpl•Wk½4ÎlÙ9G¨£‘_(•VVxþCàØ' jìîhšÙBÒ’$ÃRì_#ÂqC–bç¢a½R˸¿Ó· §‡¾aáÄwMCè<â'’áוüÄʹPö#q UÏuäÞ û‰-ÊruÏ„æD~"Ò´ÆM€;~âÊüú(ì'¢ÚŽ—ëpAÝŸAÉ«Ðù℟ˆúA®Ø…ZÌÀÚ¤,Ò±P‡;½(ë9Ç#ÁÒá#Á¿'?Qò:κMóq¿TÑú†á'Îçép;n NŠ}þòí{Œ­±¡ˆ p‹Yc_ØOìlŒ9 ÅOÜâÎ t¿ ?±Eöß(‹º‰ä ŒRÈM<¾æ3{ë:íoÂM,,Œca7Ûy5áÉvÑÔݽÞ7á&V.p7Ї”G(u£v?S£6v;§÷t¾á‚¦kˆ#£±)KõUÈNDk%×!a'¢jl‡¦7ì'®‘ï6zû’dĦΠû‰ð}: ,™ ñbŒÆvbtä|«£ÂìÕÏçgbÇüDeö<ŽõœÏÌF¥0´(=«,+³!ÔF´º2ÚŏÄì *´‹˜7 í9º­0 ò⪑2ýã†+³·ÁÉUJí­Ë™3¶¡._aÉØî[¼ýÛ¨øI:¾`6É ¶Íª‹¢ÎŒmK¶‰Jr‚m+åJ§ÇضíÂnl›2Ö€`Û$è#ËØ6™ÙÍ¡6~r­ñ&`j[ÞdäÀŸÔÆK.µm&zÑ’¦”4&Ø6‰–vÄܶúµQÔM¸mRr–Âín¹Yq™Ü¶¿H¯`rCç¤S!76£”\!7Nê! ¹íP¢ ûTÃÝÇr›ºKØcr›‹ÛJNFú¡ÛÍù-"rchDé!· ƨÏ{zBnšc6 ¹“ù!ä¶‚š‘ò-ä¶T_¯+ä¶È€øTr›Gݹ&„ Qq/ZŠ ïÖ#ÿ?Ãû@ÀÀÍÞ„…÷<©ÂªšÇR%xŏïkƒ*½Ç%z¯ì *½QÑ0Ì:¥7šÏ‡1÷ 7•ÈOôžØ‰r‘zS²t¢wEGÿzÎô®Á>¡·Åƒø+Má½ó÷±ÂMŽ÷½´Õ")Þs»"ðæoç oº ‰ÞøFóŒÎDï.À½èÝùMá½ÄÛ?Á»ÑJIÙ=ƒêÎ&v£­–&vyŒ3»Ã¡MèFÏZ¥PtïJüŒîÍãJº±·x«*ºW®‚žÐ½q¯‚„î+˜>ÐMA™ Ý+G6>ÐMuè¦Ýetoñ@÷¼’×âFÁ)è½¸Ö ¸wþvVr¯RÜ4‘{£(Ñ Üëœ.²üó¾ËáfÜe0Ú‚ïl݈ðjïÆoàåñp1Nð•=­+›Œþçì¾É²ï¿>²ã•Fúóu§ñ>Ë{ÏíoxÍZQÏgzG4Ç«^cC‘€e·–ï?±5ÿ¶×ØVH!ÇÒæÛjÿwzL… Ð+“ç†ÎûTs:¬äf¹« ¾¸ËÜÎQöý×éxXŽé >a;ÓQâ®#Ï5DmW¯ëg€}G¦ ûþÄ 8+/ê ЃøÀ °§;Í9ˆÂy¬’„Œ¥¼ÖÜ1íä%ç1íå-çQwó†óØÐÙ¤™Â²ý‰ñXØvüß{­í+U_ Ò¥Š~—Ë\Ê£y“5k!´WBêü0ð:@sL„•88Y_çn=ã{k,Ðç`±*M;ž,þ=üÌ9ÈZzÍå;Ä;‰!ÖÇ—öslþê2nNbT`œƒs;K%ë2Mj¤Ðì9X¬`ÓùÐ"2J¶ÌÁf›N¦énµ®‹ø…+¡‹‘hoèç`‹D«øz¸Ò7¿uÙŠ\æ†î¡Í1ö"Ç™Jyå ÎÁf•›ê<¥³ŠQTÐX¾®«¾Û–K¤}ÍA¶#‘éµ2A¶#QGÐ]Úu…ø°â{o;³á¼© «Þ4oo·-IðŸƒíÊp$ËkžÞbœl&ã÷Ï™cá¿&²[.wS²sáÚu=Ä–¬z£kvÎd;…‰{r¬‡ÙçL>‹1c^Ôó`kò&K´8Z+{“ûrAâŠÜ;j”·¶%å:.45ZÑJNdÍÁf`Ή 5z×Í´X'˜s"w©7‹–JŸóû½”s»¦1tŸÆØc´ðœƒlQÖ¯^Ü›cÉ£ÜÎ*iö«ó(­Ì9áÈE¼õ´’¬×4¶ EÏ¿šƒbSJë²y»Å§¬äSÎ1ËŸ¸§ñ1ß 1S·ùXUŸÆ–h³ç4³¡¾iR&Âãñׯ¾â¡ÛÔBø£S¥·Lø.½s•ðxöÊæ à Zày¿0å{ÙY±S¾ïKà'ºï»g­{áÂÁ wX•TâKáeš'šÀ’v‰Ú¤ wü,}Ë)Ü- P¶$¸[£È0çîÖú,2‹îøUª«p?“=<úFán5,¸cK24”î&|‡Å¥t?“Oâ @è~f­dºŸi=^CénuCAU¼›¹×¼¬âÝü%>‡CpTwÚœâݲ;ÝGÆ;hÝŽÙñ‹¦ £ÝTî¨Od7ñu´xÑ´$×x ì&ÃFõG» µ¿°›×ȯç.*øÂ!AŠöTÆVÑn,Ã,´ÛñDÍE;~u‰À3E»OØ,ŠvK­ŠÜ#E»™>L¥h7];Ôwe;æ…­)ÛO×û±‘áí7ÿÍþŒ‰ñ[ä^=¿Å4ûŽñûŸ0 ò— È_¸Fk¢üŽäJD˘_¹¬DÂüÁYdôë|æèW•ô’užHìΰñ¿!½WJÈ ïÜ>ï zŠ!É ß¹’pýÆÍ‚èwv˜3èwýÆÐ#Ü…ÞŸ úMÚÓ%ÐÛËÅã"Ÿ 0+è%‚ ƒ¾ëšcw“ó;ÄWn®œß¿!ûàJ›O²¼hQ²[Ù]¾½|RÊxßå‹îw^+(ß §’f¾W®ªžÓò'àçŃe¼~ øiÌð=†ræûÆußQ8˜ÖR™ï{Yè\ø^¸æmæ»tSO|Ç˱ÅËèÁwŠË|GyêX„$¾£ï¸×jõRëô¹ ¾ÿöŸ?Kö:N endstream endobj 3 0 obj 31858 endobj 4 0 obj [2 0 R] endobj 5 0 obj << /Resources 6 0 R /Type /Page /MediaBox [0 0 1080 792] /CropBox [0 0 1080 792] /BleedBox [0 0 1080 792] /TrimBox [0 0 1080 792] /Parent 7 0 R /Contents 4 0 R >> endobj 8 0 obj << /Type /Font /Subtype /Type1 /BaseFont /Helvetica /Encoding /WinAnsiEncoding >> endobj 7 0 obj << /Type /Pages /Count 1 /Kids [5 0 R ] >> endobj 9 0 obj << /Type /Catalog /Pages 7 0 R /Lang (x-unknown) >> endobj 6 0 obj << /Font << /F1 8 0 R >> /ProcSet [/PDF /ImageB /ImageC /Text] >> endobj xref 0 10 0000000000 65535 f 0000000015 00000 n 0000000145 00000 n 0000032077 00000 n 0000032098 00000 n 0000032121 00000 n 0000032551 00000 n 0000032420 00000 n 0000032315 00000 n 0000032478 00000 n trailer << /Root 9 0 R /Info 1 0 R /ID [<83BB8D1597357460E59660EE5E5B88C1> <83BB8D1597357460E59660EE5E5B88C1>] /Size 10 >> startxref 32632 %%EOF blis-0.9.0/docs/graphs/large/l3_perf_tx2_jc8ic7_nt56.png000066400000000000000000003107331422157504600226540ustar00rootroot00000000000000‰PNG  IHDR¬öEYa )iCCPiccxÚ•‘gP”‡†Ï÷}Û m—¥ÃÒ›T) HYz•^E–ÞY–"bCÄDiŠ AF¥H¬ˆb!((`A³HPb0Ѝ Ü¹3qîüÈóë™wÞ9çÌŠ*’*àû¹Ø³CBÃØð ‘¼Ìt®'ü#Æx ÿJtL&V Ÿ—Î ¹ •#H Ç€•”.@Γ€ÜfÜ_>̨¿|˜ü?@¢Å}ãQßø÷¨pù‚„ؘ\¶Z¬ '’ÃÎôs±g»98°}øi± É1ßü¯Êÿ€ &Wà–¾…Ÿ/`ÿßPcC##øûï|„5ø¿ÿ€oziœEìÀßYT5@÷é'gjÇD ºîñ²øÙe8‡ÏÁá+ñÍøNü ü(~ÿ@ °šs‚+!”HØJ(%%t®† S„E"‘(CÔ%Z½‰‘D±ˆXMK)Hq¥b¤öIµKH-IËIÛIÇHKwHJ–aË8É$É”é–y&‹“Õ‘õ•Í‘=&{Cv^Ž)g%Ç“+–;+÷D•ב÷“ß*B~P~QAQÁE!]¡ZáºÂ¼"KÑN1Q±Bñ²âœCÉF)A©BéŠÒ+¶$›ËNfW±ûÙ ÊòÊ®ÊYÊ ÊCÊË*š****ÏT)ªÕXÕ Õ>Õ5%5/µ|µ6µ'êduŽz¼úõõ% M`½Ý³šÒšnšyšmšZt-[­ ­F­‡ÚmŽv’öQíû:¨Ž©N¼N­Î=]T×L7A÷¨îðü‹5©k׌ëÑô¸zÙzmz“ú,}Oýýný7ja  ¾š&6>5’0r7*0ê5úÓXǘg\küp-}­óÚk{Ö¾5Ñ5‰19fòÈ”aêeº×´Ïô‹™¹߬ÝlÎ\Í<¼Î|œÃäøpJ9·,ðö;,.Z|²4³XžµüÃJÏ*ɪÕjv溘uM리U¬#­¬…6l››ã6B[eÛHÛFÛvªvÑvÍv3\mn"÷4÷½¡=ß¾Ó~ÉÁÒa›ÃUGÌÑűØqÈIÂ)ЩÆé¹³Šsœs›ó‚‹©ËV—«®xW׃®ãn n<··ws÷mîý4ž:ž|Ï^/ÔËÝë×Äzõõ©ë»½ÁÛÍû÷3MŸ ŸŸ} ¾>¾µ¾/ýŒüòýüþ›ý[ý?Ø”< Ô Ì ì  j Z v .†„l ¹*šÚF k[Üà´áð†épÓð¢ð±šs7ÞÞ$»)yӥ͢›#7Ÿ‹ÀGG´F¬DzG6F.F¹EÕE-ðxGx¯£í¢+¢çb¬cÊcfb­cËcgã¬ãÅÍÅÛÆWÆÏ'8$Ô$¼MtM¬O\JòN:™´šœÜ‘BJ‰H¹*‘š”ÚŸ¦˜–›6œ®›^”.̰Ì8œ±À÷à7g"™3{LAº`0K+kOÖd¶MvmöÇœ œs¹â¹©¹ƒ[t¶ìÛ2“çœ÷ÃVÜVÞÖ¾|åü]ù“Û¸Û¶#Û£¶÷íPÝQ¸cz§ËÎS»(»’výR`XP^ð~wðîÞB…Â…S{\ö´‰ñ‹Æ÷Zí­ÿ÷]ÂwCûÖî«Þ÷µ8ºøN‰aIeÉJ)¯ôÎ÷FßW}¿º?vÿP™YÙ±„©ÆÚuÈëPW»¢¸âýá͇oWšTÖ¡É:"¬ò¬ê©V«>P½R_3Zk_ÛQ'_·¯néhôÑ‘cvÇÚëêKê?O8þ¨Á¥¡«Q£±òáDö‰—MAM?p~hi–m.iþr2õ¤ð”ß©þó––VùÖ²6´-«mîtøéû?:þØÓ®×ÞÐÁê(9g²Î¼ú)â§±³gûÎqεŸW?_×Éè,îBº¶t-tÇw {B{†/¸_èëµêíüYÿç“•/Ö^’¼Tv™r¹ðòꕼ+‹WÓ¯Î_‹»6Õ·¹ïéõëû}û‡nxܸuÓùæõîÀ•[Ö·.Þ¶¼}áçN÷]³»]ƒ¦ƒ¿˜þÒ9d6ÔuÏü^Ï}‹û½Ãë†/ØŽ\{àøàæC·‡wG׎=>Š~4û8ùñÛ'ÙO–ŸîœÀO?{Vù\þyã¯Ú¿vÍ„—&'_ø¿x:Å›zý[æo+Ó…/é/+g”fZfg/Î9ÏݵáÕôëô×ËóE¿‹ÿ^÷FëÍù?ìþ\Y˜~Ë»úgé;™w'ß›¼ï[ôY|þ!åÃòRñG™§>q> |þ<³œ³B\©ú¢ý¥÷«Ç׉ՔÕÕÿB,¾;E^ cHRMz&€„ú€èu0ê`:˜pœºQ<bKGDÿÿÿ ½§“ oFFss0ˆÚÿR pHYsNNÆÊ/¥tIMEã$:.$¶­ vpAg’Zó!%Õ€IDATxÚìý{œ#WyçcÀ7®±±Á©æbqÙÀ”pCpœ”Baâ_/¥°ñÏ’¤´îÐ,$»T-“ Ù¤Uv7d§—&ªì&íeòK¢ ½Ø $AœHÜ @Ðpéì‘ÍÅî²5ŒÁÜôý£ú”ª¤’Tºu•ÔÏûõj{¤º*=çÔyÎs;ÔjµZ ‚ ‚ ‚ ˆ”ñ˜¤@AAAQÂJAAA¤RX ‚ ‚ ‚ ˆTB +AAÌ0®ëÂ¶í¤›AASV‚ ‚˜acÈçóI7ƒ8À˜¦ Çq’nAì $ïû)¬AAÄÈX–ExâÀ@ò¾ÿ\ôö·¿ýíI7â ãº.N:…¿üË¿c ÏþóqÉ%—øÛMÓô;‡ °, ’$lÛ†iš°m‚ àšk®ñÓu’$ùçv]Ïþóýó1Æðò—¿|äý ".ýd¼×6Ó4áº.DQôÏcY>ò‘@’$’ob&˜–ì˲ Ã0ðÍo~ðîw¿üuîº.~ý×½ë@ãÐO^ÿò/ÿßüæ7qÉ%—@Å.åßјMÌ ãÈ» =Ç}’ëÑ k¸®‹ÅÅE?þȲ¬k—®ë0 ÃßV(`YÀ0  ÿ<¹\¦iúÇòí®ëÂu] äóy0Æüíº®¼?AÄ¡ŸŒÚÖ)oãÈ+É7±ßLSö‹Åbä*¿ëºÈçóp]×_Ø$ˆq4Wé$JFiÌ&f…qäýSŸúTßcI®G¤E$JµZm†ÝÝÝ–,Ë­ÖÎÎN @kggÇß.Š¢¿@«V«ùÛÊårKÿ3€V¹\ö?K’ÔRUÕÿ¬iZK–å‘÷'ˆ8ô“ñaä¿V«µ´vww[­É7‘~¦)ûš¦u]gww·K® bô“×V«Õ’e¹U­Výí2Ê¿£1›˜Æ‘÷AÇ’\YX†»|‹Eß­·Z­BEX–Y–CnaŠ¢ð\EQô³C?óUšàù@‚«=q÷'ˆAô“ñAÛ$Iò= ,Ë‚ªª!™$ù&ÒÌ4e_–å®ëñUzþž ˆIÑO^{%£4f³À8òçX’ëá!…5aDQDµZ :tÅb€ç’Ð Çqàº. ÃýE½ "IúÉx¿m€·@œ´“|³Ä~˾$IÐ4-t‚˜ƒä• æ‰qäúÊt …5ax"¥r¹ŒÝÝ]Ôj5X–Ó4!BO¥U’$Õ†ÿU*hšFqKDªè'ãý¶Þ¤1Ã0àº.YŽˆ™b¿e¿\.CÓ4 (b¢ ’W‚˜'Æ‘wê+Óքቔ¸b*Š¢ïÀ',ŸG>ŸG.—óÝÂø¤D×uär9?Cp¥RIú–"D?ï·ÃgȺJÌIɾ¢(P…0‰‰1H^A€®ëdE"æ‚qä=ÎØN Ï¡V«ÕJº|+ª ¾K/O $Š"Ç(о+WLƒI–¸›0A¤‘(³Í4M†¤o F‚dŸ˜zÉkp¾Ò/1 AÌãÈ{¿±RXSŒã8X\\D­Vƒ$Ipù|š¦‘{$1÷pwš\.UUýØ<‚˜wHö ‚ ¢ ¹§˜ Kð¡C‡Ëå|W2‚˜wc8|ø0DQ$™'$ûAц,¬AAAD*! +AAA‘J›t&Åûßÿ~üáþ!®ºêª¤›21î½÷^\{íµI7cb\¸p.\HÅotáÂ,,,`}}=é¦ÄæÄ‰¸ôÒK“nÆÄH“;Êø=7 ëW\o¼«««I7eb¬¬¬`cc#éfLŒíímœ9s&¿oË,q饗’<¤œ4õÙ•••¤›04†§Ÿ4õÙYÃiüN?iê¯+++3£¬4~Ïiê³£Œßs£°Î#¼æê¼päÈ‘¤›@¤ˆy”‡yë³ÄxÌ›<ÌcŸ%FceaÞú+1ó&³ÞgIaM1ËËËI7a¢d2d2™¤›A¤„y”‡yë³ÄxÌ›<ÌcŸ%FceaÞú+1ó&³Þg)éAAA‘JHa%‚ ‚ ‚ R )¬AAAD*!…• ‚ ‚ ‚H%¤°AAA©„V‚ ‚ ‚ "•ÂJAAA¤RX ‚ ‚ ‚ ˆTB +AAA‘JHa%‚ ‚ ‚ RI¢ ëöö6FÏíõz½ïv‚H3$ßļC2NÌ+$ÛļC2NÌMâ¢[[[X__G³Ù,--¡T*aaaÐh4 iêõ:@–e†‘ô³"ˆX|óÉ81¯lóÉ81‹ì»…µÙlb}}«««`Œá®»îò¿ã¬­­!“ÉøÛëõzh;ApÇ®ë°, ¶m'Ý’obâ8Ž“tBŒó É61ʾ+¬õzÍfËËË€……,--ùnFÛÛÛ8qâ„¿}yyÕj5égEŒëºp]7ôeY}Wí,ËB±XD>Ÿ÷ÿLÓô·3ÆÏç!c°, ¹\Œ±Èóñýóù<ÞùÎwâÞ{ïø}’|§˲`šf,%P×u,..²¬Xçv¦i¢X,¢X,ö”Ãa0Mù|‹‹‹(‹ÛbFìöŽ É81¯lóÉ81«ì»KðÒÒR×Dîܹs¸ì²Ëü@6›õ·g³Yò£Ÿ0Žã@‚0ò9r¹E¦iþw®ëÂqH’äÇC¡P€(ŠpÇÿ¿¢(pÅbårÙߟ[LeY†,Ë$ ¢(Âu]躎|>I’`Y*•Jäµ4Mƒªªþ÷¦iÂ0 T*À?ýÓ?áÂ… ®$ßéÅ4M˜¦ Y–Q,}9E’$AQ_×u}ùâòÈe+»®ë‚1I’ü~ÄÏÃe•<ŽË+—ïà5]×…(Š¡öÖj5‚˲|…»T*…äÞq ßu«sqh’Œó É61J"1¬œ••¿sœ>}úvŠf³éûØ£Ã-²,û \ÜÍÖ¶mȲR*mÛ†(о‚X*•`š&,Ë‚ e¥R ®ë¢P(t)–A¸EªT*¡P(@’$ìììtí'Êå2lÛMäƒH’„Z­†B¡Ó4}e¶íÐþßùÎwpæÌ™©>g’ïýÁq_´mŽãø/d¾ Â½jµ’ÆÇñ-ý\i5 Š¢@’$T«UX–å+“A%³|A†·/Ôm…¸X,B’$0Æ|E•/긮j¯¢(P¶mûÊ)÷.p¥RÉW– …|ðÁ©?{’qb^!Ù&æ’qb–H4Kð­·Þê»Ü~ûíàGqþüùžÛî¹ç|àÀÊÊJ’·”:¸ˆÃL>.‹þ6Û¶‘Ïçqøðaäóy_QÝÙÙmÛ!«išPUÕWDs¹ V«¡V«ð,°ù|š¦õTVøŠðââ"EA©Tê{O\ÑîeÕjµZ-¤tðý·¶¶pêÔ©‰¸löc’ò ÷Þ{/VVV°µµ5ÕvÏ|ñ…/¬‚MÓ°³³’Ã(eh[D¹%•˸mÛ!ÏEQ ªjle•Ã\Y–CÿVårµZ ªªbggÕjÕj;;;þ¶(ç}RQȲ MÓ|Y<ùö³ŸGydêÏŸÆp" Ö××qêÔ)|ö³ŸÚ5hü&’beegÏžõ“M ¿‰$àsð¡ÇïÖœ:uªuË-·´Ž=Ú:uêTë=ïyOëÔ©S£œªÕjµZÕjµuôèÑV«ÕjÝ}÷Ýþ¿9Qßur÷ÝwÕ†Y¢V«µÊårkwwwྚ¦µ$IjI’ÔÒ4­%Šb«V«ùÛeYn•J¥–¢(-Y–CÛ‚”Ëå–¦i­V«ÕÚÙÙi‰¢8ðÚ•J¥U©T’~\‘ì§¼LB¾[­Vë¶ÛnÛÿ•"jµZkggÇÿ¼»»Û’$©U­Vû·»»«¯ð~”õYf?å…Æpbår¹ï;fXöK^hü&’€ÆobžE^†¶°®¯¯ckk KKKÈd2¼ ì­­­X++ëëë]ûqßy8r䀰[B£Ñð¯Ex1žŒ1är9 †i-än‡ÜÚ(IR—kn¥RñãðªÕjOK¨ªª¾[¤iš!ëS/¸ ãA‚ä;>Üu5˜H‹c†¯¼¸¸ˆ\.Ã0Ïç}Kh¡PˆeõŒ«ÍeZ×õPü3†dœî¹Ãƒªª=û| Ù&æ’qbVJam4ØÜÜD©TÂêêª/ز,cccÛÛÛ]®¿þú®ýlÛö;C&“ÁÒÒRÈm†¿ð7Ôû¿ë)KæüùGá¼ës€úSI7…˜xŽÆŠÅ¢oUå–Ð|>﯂=vx_ô˜Š²6ñ˜Sîò(IlÛ†,ËS,%I‚¢(Èår(•J”ìˆE0;uœ‰tg²=EQÀëëÖ^,À_˜áVÓ~n‘±ŸðÒ–†aø} X,Bůã8þç(yçúGÒ!Cǰ.,,À¶m,//'ÚðY€¯¾Þª5ÏSU‹‹‹þJ€ä8AH·yÇ4½ì®Ãd…%öžÉš¯Fwf-—˾•5QÇ‹Ñf,V¦àýÄþàc ~õn¤°Ñð G0ámÛ¾u3Øç‚Iù¸ÂŒ-•JÈçóE1d=5¶U–eìììø“õi,NqE•²wð 9—½à¤\UÕ±&Ø|Ñ5XÎ%{ÚzEVSb?ác® ¡1—÷‡ EµsÁ‘{ÌCg ^]]Åúúz¨¨pÕÕÕ¤ï)paêµÒÌã%ø x¢¤Ypm;µîœîÅ'ýV冊¥ž)^ív^ášœ¿¿â×&Ý"At]̪˭–ÜÕ—Çñd||’Ì÷ãDõ=I’P*•FŽeíÅ´'ëC•±"¼¿pEU×u?–tR AÏ7>§¼÷- ûMgFiEQüXSn)勆ÁDbÌ¢² Œú¶¶ØÜÜŒÜN «Gçä¡UUý$ãÆúÌ-Ü"F sRÏ®˜z\fãÕp¤7£”ÂÅoÇÄ+Ÿ û½_‡zcÒ­!’€Çˆò‰FgNÛ¶±³³MÓ|÷[n5MÓÍôÎáÌD¿%ˆ¸®‹|>ï[÷9Š¢ø¬§±PJTbÚð8QI’|Y ZLyhG0£ôAbh…•‘ò‹¨z[A¸k ÿ#"°íÔ¹p3“…18ϦzÍC}ÍýÀ=Û(/ÀAƒÇšòÄEA÷F~\àM˜;7UUõÝ…-ËJÞýž ¦±ãIÄ:€qÈOÌ®ëÂ4M˜¦é+ªŒ1?I+M…·Z ­°ñ`Œ ]­V!˲_h1ÖýŒöVVRAÈòø «ëz÷HºÿaÎï8ÈçÛÛÜë¾Øu=c?ëz j±Ø~Ì¥R·…Õ4=}ƒˆ‡iš~­Ç]÷~”´!ŠP~ê1pÀ¾üµ£ŸÇq¼¾R*EË÷X|!J†=oðö\.úÞ²,ȲÜs…ŸŠ¸T>§×õÂW*|ç²Ë’n͆1Ó4GJÄì<™)«Ä¬cš&r¹œ_—žÜ}'ËP +§ÙlF~׫6ë<Â-O•J‚ @Ó4¿®jW€uZg¢“n7_F½xL³möÜ£Ë901*þDò³¾EñæôêSþŸ¸eyÅ¢gì*¼CÅûãu,ƾÿÏy±m¦i¢V«Å›43–Ú˜ãRÉ“{÷èè2¿woº,æ„ñ»Žë¢òâßö?JÒôƼ>6 ×~b,lÛöUQ}/]ek¢à  ‰¹GZ–7¸‹ÞÃð:H'|¥pŠo±è ìI+òt]G¥R=ÂB%/éW«Õ(³/1S¸®‹\.‡ÅÅE_öÇA>Ÿc •JµZm6=ÒRÎP.ÁKKKÈd2Ðu'Ožô]N:åï3ï•Õ`ÉEQP(º'®»?/X]÷'Å]© ¶K’Æ7?FoWIÇ iÅ¢×LUõæCÕ*  @¹ Ý’à~ùQ”?ýLõ•_$€ÜíYÍÓ­FÜ7Ÿ'š&Pùõ:„~1pÜçF Xjc¨Uï”*¬¼iâs/M™³m˜®Ùi'Ôæ"7 ο; û¦5O~ƒtÓ‚¿M’ã¿àêî½(•¢/jY^ßçÛ\׈}E×uX–å—,ãï>ÁQÅ_Фˆ*ŠZ²‹ž õ’7ïfÛcº(¶tAèv™—åö #?FU‡Ø6 ï’íÄ1MÓÏÛÁËpÄõànÄ-I1ûðÀªªB–e‹EßË T*¬< 0tÒ%Ã0 iŽ;ú>“É`cc#éû™:QÊ*§T*aqq19¡5MorwU>8y×Dz¼ëFM°x²›½çR(´½+ïkƹ\Fñ‡?ÈÏ@ù¿ p‚½BÏ-·|»¦…cYr¹½ÈŸºÝkŸmOú>ü ³GT©˜&ÝôHlÛû+•õEgg@–a~÷»PEÿc÷ÚW{ÄÈ:ïþÜo=¦é‰ óß›_ñ"ðÖàœýVÄŒçþ!É@+¼Òë,=÷­¿ ã• òk/‡,:žb@“ú}Dz,ìDüþ|1“‡ŒÄYy—$©gŒëT1MotíRÉëX¦éý¿\n»·tŽÓ¢èÉ£¦yã狌¢88¿ƒm{},‰gB„àu#+{¡¼~pœ÷…mÛ°m;Ù&ˆ1àq©ªªúcxµZ…iš(•J”DiZaÍf³¸óÎ;±½½3gή¿þúaYsKð>ÆqÙ2Íð$™±ö¹æ(U«µwå‡éºä)«w='ìÛ x÷ÔézÄ'?µZ[aÕõÐäG½Í¢`Ñò.Æ)¬=0 #²ÔÆ@x qÊÜ`ìŸÿ3ˆÿå§L!9£ÅÙ*¯»Èÿ·$ì®&à<à/ÐØïy£/€Ô㘿ûuH7Ý„òÛ¼ñ³!¿Ú³ÞàÍáEê‹^Õ©o¢Ï]ïÀ¶á<ëG!½ÜkŠ(‚•ª ‡Éý%ªÎ^¾˜ xnqØ÷˜>îRW™èµ8Úoâ\©äãyœû4 O)¦8ÇD±mº®‡ÊÍ(Š‚|>¹¿ã8pöæŽãø9?(^•˜%lÛF±XŒ´¢’ëïþ1R k£ÑÀÂÂVWW±ººê7ïðII?w.î‚+’ÓL¼Ä-\Ã(AŸý¬2ƒâT$){_Ãu½}U5½ °R€mÛ# ÀÎÓ^÷ÿÿWÓoànë|þ¬WŽÂyèp÷–5ð´]CºòK`ÿçãþgó/¯»õÌ“_ê>Øu!º Êïþ$ÉAû+/„t<ÚMýÁzW?ÓuOt}¢\Ç š&$Mö=3ø!‡ÄäˆãY*• ªêô&ë®Ûíé ëžÅcYž‹y”À‹û«r…7ÎâXµJq« £ë:t]G¹\½#¸<»Ù3Mù|…BÁ·ª:ŽƒJ¥B–(b¦0 Ã×&—ßdZaÝÚÚ±cǰ¾¾îwûí·ãرcØÚÚJú~¦Ê0q]ôP¦&ظñ“QôSTxÌR/:ãQxÞ¶½—”õ§ß…ò£‡÷íHÆEé^¹ÅîëkZ÷u{Y‚+û;Ó—¡'ÔŽ³ñj°ÏîCÖNËŠï~Ìœo<Íÿ(½ð[pþùÁð>® è:œ;?yš`Fjÿ\/¿Äo÷c_ƒå?=Æw~©{gË‚úºv¢:MªŸëºŽû´çÁüïÍÎC}EÔu‹‰^ÿØSZ‹B¥«¯Èrw—"¦KdføE™^‚Ƽ؇΅Et˵­ó•Š·g‚¤Z”B¢ ƒ  g>Y–ý“¼Ô_©TB­VC©TòÿÏzMCP,ÁCµZ%ÙMC)¬Ífëëë8qâD(^ucc«««X[[›kKëÈ kÜUäqeou|’î ¼~ àM’‡°Lº×<Å·\ê-äïMÒ¾~/Äü~{GËŠ¯È+Š7éêGœÕ[Z%‹dä2Ž âì0äóžœÇ•×…{É5¾>'dŸ –=ÞÇ0UõºÍß© Û§¿Ü½Vò;W@ýî»Öÿý”—ßA*öá.´þ×WàþÔ}'ßöì®ë?ó˜ÿû·¿8¬Í ]ë6¦ ÎþW8G^ÑS)%'‚é`Û6 Ã@¡PðãQ9c-fŽ c~©—ȱ­TjÇV*Þ»¨RIÄ}?ªëòHŽÎmŒ¥64þÀÀC.—ƒªª}“$ñÄK–eÁ4Mšà3 O®`øä“ÄÔJa­×ëh6›¾p'N “ÉÌuÖ±VQœ½·¯aŒ¤°š&«¼â£uO•¼‰‘(Õ¿ù^xfÒÏG¸“RÉSʉ©ÀÍ]KÇÁå†?v§4+î!`IÜ#/ ï`YÐïÿ^áŸ~i¤Œ³¿¸¯{$Ìnd¡¬½È¿Fg›õϾxæ3c=Çò‡²žuËÁúÝ{C:… xò«‡ü;^Èv$Àu\\tߦû{ ,Ë %M2;V ÇIfRTVû½›zy­ì#Ü;yq±Û‰7Cëø€ãxu·Ÿò%è+M Þþù¼÷4 ¯®^‡{ï½j_ïá ¡ëzì:ܲ,ûñ­4Á'f®¬*ŠBuTSÆH1¬½8þ|Ò÷3U%ÖèËD -N˜~~ƒ<æ–ψù}¸žÌ±ö¯—@ûîo¡\îX9ç®Ñ‹‹Þ0\’(Š™ŽãŒ¶ #Š`_8 ë«7NÕí]ÿÞo¡x×ëàžýJ¼ƒð„o›nÞ^Vmë/žàéÁÏøY8w|²ëΣ™H±+>~Ö¯~ŽÖt½ÝµØOü¤<;,P’Ñ(ÂÝÙ»p]¤¢ªž÷f¥Ò;ÜP}ö]øÒG§¼€p@p]×ÝÓ4Í/åÁkðÙ¶L½Ô¸Êj Øó(E­æ-º0Ö®žx2]zËWÓ„èØ¨½èçPÝ^@µê%Þ®V½¿àÍúúY\{íW“¾µ¹Ã¶íP‚°¸ïEQ(F•˜i‚ek(™RúJaåuX×ÖÖÐl¶c­šÍ&ÖÖÖxY„ç×uLjӸâØiMb̳ª'BA¢¬¬ÜŸ+p›Áäê ?näóýa€Aí?\ö•WLìñdxæìàøŒÙÙ3aLsf”UÀsŒ ®}–Ë{µ·ƒ¯Eþ~1 *Ë”¼¬YµZE©TÊRJ1ªÄ¬Á½ ÃcŒ”Õ”3´…Õ0 loo㦛nÂñãÇqüøqÜtÓM°mXXXHúž¦ÂDb”¦ia šŽ:“iÄm‹(öŸE)¬5® úö¬ÃxþNäYpWš”W½÷½¸áÎ;÷©AéÇ€¢)=µwüºã :ƒn¶ÝêÖuá:ŒR Ÿ{ïÈ}I~ù7=™Øó§e®è+¬ŠØOø‰Ë1ûÓÏAzî×#Ï¥¾íJìüèm]¡€'Ì’Œ‹mÛ} ÅK’×ulÜOu IÞºÿãÌú\pže»Ó4!Šâ2BKÆ9Üõ÷ ŽÛ³L, +'hUµmÛÛÛØÜÜD6›õ­¯q¨×ëÐ4Íï\)æ.ÅFš¦ùI–宺wU d0B·rÊÖ~Ás®;¾Å7bÆŸŠk­Î¢|ãÖh}⹬¸ç ÷¯Fá/F%ÊÃ’1Tó à­ñ¹ƒ}â0¸„º×þÙ§h‹·ëö¿f¯…“r¹½°%&•¿^@¡ BÀ®|%èµÖÍ,Êø°Ø¶=Ð=rØÄ4#ašžÀ§¨Ä %(šƒ Û†jµšt3ˆ}â Ê8à-ÌÛ¶¤›BŒÀÈemdYÆÉ“'qúôi,//£^¯ãøñã}Wk8+++XZZc wÝu–––Bƒµµ5d2{½^ÇúúzbɶíÑWc¦Q惻ür‚V\`°…5Ÿ÷LaãšBK‰95]Ìš|›[~Þ}¾øõ;g÷rÏzù½G[Yâå»þGé§ž÷žvv^åôO†¬¥ŠÒ[Ì4Ãë8ýª6õ»]QôÜôó''öœç‰Y“ñQˆ³ˆ£(Êt­R¦ÁHV.Š^ø¼)«ÀÁí ¦iB–åíÚ~Ð8h2ÎÑuÜÞg˜¡Öííí®ÏÜ5øúë¯÷݆£Ùlbuu°°°€'NøÉ¶··qâÄ ûòòò¾¯þ9Žgob=VQøIX2vÍRN°FGg†WþâÉç£0U*ÞŒ|Ü”ãtÝ›®Çʇ3·ÌŠ|1 c,÷ùðG!Šž(¸ûbä>ê³>AvÞô?#µZãOÚ²$I{¤÷XÂß9Å·¤êº`ï:ƒREôä^×aýöçÇz.‚(oÎLè)ϳ(ãÃbYVòî‘Å¢§¬vÕI]÷ºà5gõ›ƒ Û†A‰–QÆÏðäºnß0"ÝÄRXëõ:Ž;†••ÿ;Û¶±²²‚íímT«U¬¬¬`kkk๲ÙlWù›sçÎð:ÿwPñÍf³ûîG¯ë:òùÖ󏸧ˆY’ñQÙ÷R5†7v”¹h:Èòàœ|³ÎAí d]=x4çÐÂÌìKaÕ4 Ùl§OŸö¿ã±«§OŸÆwÞ‰ÕÕÕX. XZZò?7 ¬¯¯cyy™L¦o§h6›=·=òÈ#¸ï¾ûº¬À£ÂCmïí<–*èþ8ªÂjÛÝ“AŸ+jR*Š:x:È£ÑhàìÙ³xðÁ'~îiÉ7\¸pÛÛÛyqض ˲F*Âu¡õx žø´otíâÜ ìÇü¨·{.Âæ«º÷Ù½ÂÍ7†¾«¼ûÑ "åJþ!Ïk`O•Û®„}î:H?𸱟Ӭ²½½‡~x*çž•1|,Ë ,¤$jaåLS³Ê_3IœƒÔëuœ={çÏŸÿdfeüž4‰ß§|J|ü$S£0ã÷ à¤b)‚ÏÁ‡¿*¬|€=yò¤¿âÒl6Q¯×±¼¼ì¯Ò,//£ÙlÆÖf³‰õõu;v̯åÊ¿ïE¿›{ä‘Gpÿý÷ãÌ™3c?LÓ'J¥Z­Öèzî+Éÿ=JL«ëv[XUµ­Œªjj,ÓÙ4çΛšÂÊ™´|Þ„çÌ™3þ è8p Ò$VÖÙ—=·YQÔÌûºbT÷Õaùáû.{ÌKÂÛ@Dw\«t,ãgÄ®i½k K§n õA𲧤K$™3g¦2Ù ’æ1|,Ë‚a( °,ËϘHÉ^À4Á çº:ä¹ÿærñÊzï7ÓRX9i¿'A±X„¢(d]&–åõã!ññ{Zò ÌÏø=^s•bWÓŸƒ+ß³×ëu,--…Üx9›àjEp{œs®­­aaa¡+îµ_ l&Ó;žìÊ+¯„$I¾_þ8L´|°“Œúbˆrù LÙ 'íŠ_]œÖÀ: ù€«®ºj"ò `râmÒ‘gx¦wÞÌ1HµÄËw!m[;å×\‚½2§Þ1ºéêîIœãì%»Žˆ•„¢$š(:qVWWc%À•´áqaŒA×u?>«P(@„äVâmÛ_m ö‘ýÂ4½&ìî¦Ûy†[ƒ¦1†ÏÂø=.¦i†¼Èˆ¼¸°¢DNfLÓ[WÒ4ÀÚ¼åŸ~Ñë¨Q/Ãð¶ñD™1çj|ü$S£2/ãwù|¢(BÓ4‚€b±ˆr¹L5WSĨsðÖ………®—z½Žl6;”’„»olltuŽ#GŽ@È-¡ÑhL­ãFaÛöôV£bJ‘šâ¦ñ8èãBÚå˜Ü¢Œ£–€g>Óÿ¬ÿýwí#¾õµþûüÏ’¶Ú°¿þ¤ïÿN×q¼Ü°i‹°>tõ¾>¢?³ ãƒpÇ/ /Š"DQDµZ… ÓMÌáºÞD6*C¢ª ÇiïÂdétoŸ —Kçé]×ëSQ‰º]×;>%9žcd»¦iÂ4Í™O¢Â0úÖø Þé ÃKvÉ3íašmç6fØÈÝù«ptŸÇqÚ†IJU6Êy•qÇqüÚØù|…B!TŽ“þ’Iˆ k6› n6›°m;ä´3saï…mÛh4eÛÛÛ¡?À[ÁYZZ %p²mùŽAcšp—°©GauÝðàÖY¶†H-³ ß“ô pœŽŠJOmtù…3W„‹ö XU=ñæó öéK =÷ë]ço_çÁ'CxÅ ÷íùý™ƒišÐ4-ÔAðØØp-0êþø÷ºîý[×\îýß„ùè­¡]-«} ^6†;èðô¹œ·O±èŸ*¤Ô2î~–å͹‹EÏÓ8—ëžsð¾(¤¬Î‹l÷Âq_Y‹“ã@ß¼ÎëCºÞvé¸|ÞU*µ«)T*¡]ü´Ÿ}ƽ åÍÇ£ôGWC”Š‘çS˜ó‹24Z¯I ³ ãq`ŒA%)cí,¾€7>+Jt’$Q„_@˜'ϫհ‹€ed¡Áò§wž%QlosÝö¼EUÛ¯Qì.×Êá—î|­éºwÝyšÓüÈv/LÓ„ªª3¥¬ò–^,aœ¡|ð&Hó[žâÚo"²çòk½ÿ‰(~ò(—\(Ú^'2Œð…ω{ Ã4=7_]ªU¨¢×¯xè¹ßÇJ%(`YG!w!,+‘4ôó*ã®ë¶m”÷=Aæ#¡X0ëeyãØ¢è lg?qou“Ïu: ^'0Œd^­<üðíßüÍßl½æ5¯iÝrË-­÷¼ç=þ¶S§NµŽ=Úºí¶ÛZ?üpœÓÅâá‡nÝ}÷Ý­»ï¾;Öþwß}wëÔ©S}÷©ÕŸgww·%ËrKUãíß—V«Z 'ËÞ÷ýŽ‘åVKQÚ Ð´è}«Uo_U³¡8ò2M†•ïV«Õºí¶Û&rmUU[ÕN¹‘J¥Õ*—_T«]ò*Š–Ë-õú <õWþ¾%^rßDÚzИ”¼ŒÊ4ÆðI"F f dÙúju¤—DµÚjíî¶ÿ-˽‡x¢7IŽáIŽßã0²ÌO‹ÝÝV«Tjwˆ4­Õ’¤VK•wZQ3Þü>$ËÝó®=j·žj•2§¼þ»³ÓÚù»{Zâ3¿ëMÉøÜ«G3%)Ð Qìê´µš÷uùÍŸnµ4­U¹úþ»Q[­ÝonÏýÊeïKEñï}w·Õ*­žkí¼õ÷[­Vòò’öñ»“R©ÔÒfu •¤ÞïUmË3ÄAó·J¥-§½ôEñú¿~ðûJÅ“UQìÖWvwÛ“ºÝÝ‘õQäe …ðâXy±N–——ý“¤3õö$à cQáI|ïÂ…s$ ¢è}ËÐÊý¸‚þó’Ô?&•ûXŠ{5(%©÷Jß'E«Hƒ7 iÈw\‚«ã¢ˆá„`Fõ(ܯ¼A‰\ÌW”Ûñ TQ¸W=â3¿böHRÆaÛöhqMAÓæðlî<#Ëé*CÄ#Í²Ý Ó4§›= Ëòʤ+µsoò¿'ûjàOþ⟬è˜&àöß_ ëù²Ü{á“ÏÛ¹"Éßa\/àNo±éØYéå—ÀVÊX;|PJUðRo¿Vª¦s3ƒeYéŽW’íà¶Î¶[V[!º/nå®:œ^ f¹­8öªÿ7èYн½¸7ƒŸ¸Äs_ë1ºŽ§}ðƒxüýÐP1–…ussËËË`Œ1†ååelnnN½0ý$±mïr‹9m%ŸxÂ¥QWñxVÖ`Ö@²t3QùÞ{«ÅO–Ã9œ‡—_}¼¢@|ÿÿ‚p÷_%ýXˆÆÄ= ú`š^¦ÞUµ ©rŽB–½ŽÒþ®gÀ}iG©´=ËPîæ#°¿õŠÐ&?IpÀ×Þxç“ 쥳WQ €×W ïß~²¥1QUïÝè8Þ\>jøERX‡Åqœé&J¦Ù;Ão”2«ªmwà¨ûâ‚Ñgz²χ§¤/—ÛVÀn£[©„³ëëøêµ×uú +wÿ=qâ„ÿ·¬N³0ý4à%±dÙsÝî4Nº®šÄ$^:KQ ¤¢¤Ja¦ÿûÏȱ{Q0†êk»Mê!ß{îüêÇGÏc!Òü¢!掉ö˜f»¶)y IàºnºÜ£à.ˆXÿú<7GxßÈ2v» õ¿=;¼¿^0µ¬ÑÂ踛0OC2 …U–½ÛôÊKIõ›™g¾NA+i/ãSgŽ› årÿL¼<>5MUDJ¥ž}yÄŽa Æ©.,,$ýX†&è«iájœÎUš±çÑŒE»órÿî^ÇðÑuÌx©$H°¦0“‰ÆyDœËýRÓ[i3 ¨—ž†üú§õ>¾R™Ìl€ b2tüjÐ-g\׳ø”Ë©ZS$–e¥Âºê~ì‹ý md •ßÙ{>‘ ÀãY9º>zNJ~úýÎãÃ-»Dû)¬½ÞE¢ØnÄ…3M/— ›Âˆ­°Î\.Á›'wεmÛYXÇZ(`¬wÐÿnq1z9-(€3d}¢•Át3r¢™Ø»ÎÀþ‰ßŠEègOtmW~v¡ý–OÓ`Jð&‡²° #-ªFê`ˆˆa©˜Ð›r¬ºëýÛ ¸ïö¶!)ÃuIòæuºîyÑÉòøýo¿óø¤`mafàÞ2©J¶Äö‚”ƒ+•¼vç$™±ñ¬‘ìår`Ö8VsÇq&çï8½—öxv.éd†+¸»îLé×ÆØØq{¦ 8ó9k?«´vẮ}J%‚GѰÈ*Iß6Aø¸®ÛúѾJ>䄟—IKsbþáÙSO¶dš~àqPЇÄHÏÁôßæÈ“ùRÉ[315¿íD<¸|§®¬V*ÑÙ};…¾W03I¬,Á°²²ÒõÝúú:n¿ýöÐwIßS$®;xì‹ Ü^\ìNÄ‹8Ëd¼ØkÒøˆ)áºî؃»mگ܂²ëËýæñ‚@q{Dº0 #~àZç><‰bšþ‰ƒ‡iš(¥A2 ÈÕ*°77çsôÎ’ô…Â^„‚ûÍC“y¢'®ëN´¦üÔVV£æñŠ(¼½ †b ÂzäÈ‘PÂ%N6›Mºí¥×ª;¯Ç:¹’$*\J쌱±S¿kZ{,Ö´þýBÈÂD¤ž|&vqyÓôV\bþ®ëÂjh®M$ /e“XöTžát/±ŒÅD=|%ì…`Yíp-àh¢Ï.It2Ç!u™¯y H¯þÆÝ‚'•vú2PaÍd23[o5H¯’Aœ^i±ƒÇ¹n;,Õq¼ñ8$wŽÓNE—4eø"æÇqÆŽõvRF‰YÂ0 (Š¿ØöàGƼwyi€ËûÄá«2=Îíº€ñ_BiG÷ös]ØË]Ùv%œ{Ò4É–Cù@cš&ªCŒÏSÅuãyã¨*ý¸cp`bXÑ™p)Šb°ßñIÞ8lÒQRL‹âÜ(­TC,½t-Șft "Ûî9 2FY ‰ÙŶíø–ÕÎàYö&ÜäåE¤Û¶§“lI’¼¹N÷„evír°RÕ·8±æ³»<D±½ÈxsyŠˆòÆr¼ëO ™xlv8ƒ¿,ÓJÿ ­°nooc}}ÝÿãuZÓL¿*2œ^ —ÇsK7 .@ûã8!"F©W‘ß~Ý‚-kpCS )¬é¥+á’aDÿX½YÖÿ®M«ƒÄìašæpÙ$‹m*u]o1“ ÒÂT“ÑH’ç·[,†5«½š5ªêýY<…µTê™ UUÛëõä%IÄ%ñRMù¼—à† obrÄVXmÛÆ±cǰ²²‚ÍÍMÿoeeÇŽC½^Oú^Æ¢—K0_´, üó{5ö&ôã*«†Ør©}\°ë â8´2˜VÇiO`xí¯(Yã•Ò#~Hç3߆ôºgƒ f ×u‡/íQ*Åσåö" ðr£Óš*IÞ½XlìÈO"wâ!å3èÓkzÄó Ìð:ýÄásN"žliâ «®{òÜcÁÞ§X¤¬z KaÝÞÞ†¦i8rä ÃcÌÿ3 GŽÁñãÇSkmå®Z½Tæ@Qö Ræî®‘زöV×-+¶yѶۋ3]µÈfxæcš4Ц•…•'“éEçl\ì‘,¤›’¾‚ˆëºÈçóÐ4m*îcŒíeÎ&//"E0Æ&;¡/º¿ãÚ¦aÀ¾åPÚ|jdÙI×í?­á!±„Ç O÷…©%[âÉú-Tò•^c•w_‰UÖfmm ²,Ȩô,Ë2dY†¦iX[[ÃwÞ™ô= M/ë*ÇWv]©6xO¸yâë‰O„ûºe°¢§·Fõ'Çi»ŽU«Þ©òùÀ3nž¤þ›^Çñ&ì<[˜,û.\þB cÐ/ü ðÐ(‰áäî‚ø´ç'}®¬ªª:غÊgÖ1ùb£m󬦑&Qo»ã„‘“xÆ[,C+Që5¼ì¤,÷×h±§›Ÿ N•©$[âõ•zÿ¶½W„Þ©Ì1ZX···Ñh4ð¦7½©ï~'Nœ@£ÑH¥kpŸüâ%\à 3/"ÐÌJ¿rÖ¹€Ó¼ŠÒmiäÿæe>¸² t$¡ä)ˆCmKúéŇ’&¤_Y<á ΂&Š`Wü(ìÚå]7ûë¯Aúþï$}+›b±OY5Moå0æj›ey»K’W£›Æ<"ML<~•‡`Ì3ºö›6)JÛ‘§_s†-¬p ¨Ær¹E™¼·L„Œû Þ ¯ªôÃ$Ì@ k½^G&“A&“黯ËÚl6“¾§.ëïì8Îp.‚­œý (*€’7*çÅEïs¹ì ÊQ·û{·Cxó­Þ‡½‘›× –$JdDŒGȃ ˜z]Â++‚€ê‡Ûaþ<ßuaÿÍw!þÚÓ“¾‚ˆ c •AæOždlg'ö¬YQ¼1™&ÙDªÖp'B•ÕJ¥ÿb WDÉÅ•Ã0`YJ¥Òt’‰uÕ¨ @.4©a …uaaçÏŸOºc1¨jÌ —à'wÝž~-;;ž²ÚâÿxØéºßPƼü½{þwi§P˜-‹ðA!$ß{~ÛŽ˜LŠô=Ò´@lµ®¹Ôÿüd(·^šô­D,b%ÑuOY"yF0)$A¤ >Ö[o;DÀúÄÒ)«íöDäé ¢ëÀ¹s×%ÝŒTà8Ž¿3µÌ×¶M–¡` ÂšÍfÑl6Ñh4úîÇ.-,¤/)K¿±{PÂ¥ˆbÛ|:"êËþÕSHE–å½J¥p^œb1:ïAšp]rK#!—ཨ‰Óà¡¶ oÕdgâÛ^G“tbfàuú"±,ÏõZY å ˆ”1qw`Û·G¡à-hÆ}Ï“»/1.SK²Äéq"½ÄRX³Ù,4MëéîÛl6±¾¾Ž¥¥%ß58-¸nÿ3¶uÕ4»3§Nù‡¿õñ·£øè)Á¿óS­¶Ø4Oœèå”>B2¾÷EñÆhç ÏóÍ÷¶ÝþýÊeO [ •#ˆY gÙ]÷Æñj5^¡÷ƒBK"I\×½>e±>Ü]_&`]å¹—†©ÅS~ÃQ*GŽœMº©À²¬áJ’EÁ'ÍQ®Š‚0Ø ’H±ÊÚœâ˯éê+’DVsb¶ðãW¥‡ëz óƒjÉDÒ†1š%ʲÀ^pk×<ؾ9]¦Åñ}†1àÓŸ~yÒÍHœ‘=:á axYŽ\ŽjÍ ±V ­´Þyç0 'Nœ€a¸óÎ;±±±L&ãDZ¦‰A.,±]‚§éç.Cû\rK½Hˆ~DÕäãÖzIldzî»þW˜Ÿ»)éæÄØØ¶W9â¹þŽTïºÞ¼&Xžƒ Òˆišey¤|ì÷þX^ŽÞ˜Í¢T¢|4I°³s4é&$Šëº`ŒM&&›¯¼ B;AL.7ÙL ŸØ +'“É@–e¬®®B–e¿ÜM½^ÇÊÊJÒ÷ÓÅ kl—ài» Œpþr9]VVZ°J!]lÛ×@ùé‹R ììá\üܤ›KccÛ6^uî\ÏÌíqÑuo^3kÊ*c ù|>ô§ï™Ïcþ¿;É#X–…\.‡C‡aqq&™˜SeYÐF‘wÛ†ùè­p/ÍDVï ²zÉ@É+½E˜±cW{¡ª^hH±˜ômC0´Â:k˜fE*–uÕ¶÷GaÒ\*ŠÞ_ZæTS9}„<Ö‡®m×Þ~ ` ®»z„+DzpÿæÚkÛ…ÞGdÏK~\7x oµZEµZE¹\†eY`ŒùV‹è{¶ýgX,Q©TÐjµP«Õ`FÏãˆdá¿Ë(ÖUçÿÜûÂøJ)wôrœôW%˜wšÍ+“nB¢ôLœ7Æây,JMZgŒÄÖ~nÄõz}`9AXVHø¾H¦™p‰ÃÓ²I©D«qifÚò=ÇqÚ® óŸ^Ú¾—oÎWŸéå—$ý¸ˆ$i²²ÒÄÙš°_ò_Bß/.Æ_Øs]oá}^GŠ¢Q}Ev¼ 7 ‚€r¹ûøy"M²Ý‹¡²¨Úv(éŒyöPßòDÿ³axs&à ËjÒ<þñìËuÒ*ã¡r|qá…‚ùŸ®“ëß‘¨ÂÚh4"݈yFâãÇãØ±c£¹ºìÑoMæûá8©½ÁSX]7ù~ÙÃÓìÀ²òÝΟ5Ÿ¹î¢ÿÒ·á<ö9iq"Å$-ã0&àW.þ]èŸù÷(Û íµZü5GÇñÞ³œ8Òqèºîÿˆ Æ÷[\\„®ë~«‰Ö÷œÒ&Û½ªöêÞ$a/1<¬æ+Cs$Uõ”UÛž=Wøyc?ִʸŸ8oX ÃK:P«µ˜²FÎ Mâ¢Fõz›››‘Û×ÖÖÉdpúôi4›M?~ëëë#•ÍéçQà8NüN‘òÙ‹m{}µZM®’ǘÇ~Êw?:йŸ¾bG^%AÄ'}ö÷ž™ôc#fˆ´Èx×ûÐCøé7´ðÓå‹`ší±PÚïž<˜çÑã‰#9’4¼×Šžðj]…Ò"ä¤V«1˲ ë:ÇAµZB3ã¤Q¶{ÁÇø¸e?Œw> âseÌ늞/ðŸ—Ê×$ÏââGá8×Meê™v·m{ø±Æq<÷€ï³,§ÖÐDŒÆ@…µ^¯c}}}à‰šÍfì‹noo÷|y6 looãôéÓ€……,//ckkkèÎÂÝ{É,c,žü ŒÞü6\79…µsâwPÙ/ùD§ÂÊžúêHÙPUÀ=ÿí¤1C¤Eƃ|üãÇŸ\öWÖ{Yˆx…Àó3Œv¬ª®6Ü'm}ìtE¥ÀX–;‰ ÿ]eYöÇ]×aš&Êóâ'݇4Êv/†²®°¿ôl”ö+åÞá{Ö—ž÷¼Cz*çN»Œ3ƆO¸T,ÎÄ\‰YX°´´kßååe,//c{{»ËáܹsªéšÍfGò£g̳<öÏc×`‚J«ë¦Þ(<·ì—|Âqœö‚ŒëÂýÎe#Ä]üÁ J/Hú©³DZd<È™3ƒ#?}ñ@óhps¹ìÕY•åñ^G1ÌŠó¬!Iž²Z(x}x?âåy‡Yàܹs8{ö,¾þõ¯ïûµG•oÀ›ðœ9sbMxBò-Š_ø-Ê(}@8sæÌPa“d’cx\øô§Ÿ?’Ç̼…:ɲŒV«5ô¶à÷årŽãø‰ Óæ‰ÄÖýf?ÇïAôufÌ›’Z‹€öÏb>g=ó¿ÉÔ4Hbü;~5Éø7b,ø|Xf ÞÞÞîžf³Ù7ö8Ý:é7È_yå•$©ËǾ—Nêºî`…Õug6õ-/1ÅÕFîdii 7ß|3žóœçìûµG•o¸êª«°ººëeÐU²IQzïuû~¿D2¬®®âÚk¯MäÚ“Ããð©O} /yɹßyEÅPkšX^^ÆÍ7ߌk®¹f_¯»_ãwúÖ©ÔuÏßÝ·ï•“Éûú¼ˆÑàã÷$6†%‰ñ;cl°…Õ4ib;Ãð9ø°ã÷Hemn¿ýöÈTØ“àÈ‘#Ân Fc¤ŽËؘ5X‡Èª˜FÁ³´3«wÏ“”ï~DyÌŠœ˜möKƃ|ᣎ7|ÿ×’¾ubÎIB¶£à–ïHw`ÃðÕÀ¤ß¶%ÿm'’´ŒŒ_eÌ“ñŽ“hÖ(2™ –––°µµågÛ6òùüHçë5>Dz°26|¹ì)+5¦7MLZ¾{Ñ™PŒ1Z´ ö‡ý’ñ µÍÇá• ¹@‡$d;Šžn“®ëYŸ:²¥Ú6 ¿örÊ¢J $I¿êºžeµ\&wàHêbXÏbeeÛÛÛ~÷­·Þ:ôyÆ®ÁjYûºpK+¯=8i¨k|&%ßý`Œuûž§8="Ý쇌sø—Æ xêñ듾mâ°Ÿ²ÝE¡ÈrwÙÇñUËò”ÒÀdÞ4½÷3¤ˆ¸$%ããW cþ’±ITa]ZZ‹Ðt²Ù,î¸ãÔëu¿Qè—4ÌäÉ5»9[ÅaÌ+ãP.O¶ÏSn¦-ßý`Œ…ÜÅ$K‡D«ëÄ„IRÆ9–åà†Çþ ÿǤ1G¤A¶C0†Å¿üŸØ)}¶a„kâš& pþü£0~ÿÉPïýnÝð˜ßz ÕH'"I›Œ÷­¿jÛÞ >°¤Î%˜Ã뺎ÚQ\··Õ/V§~\gEñúû¤=U•J` øòÝÇqºW)ÉNì3Ó”ñ ÿ`9¸îª{“¾ÝTáº.ŠÅ">ŒC‡¡P(DNLÇ1†|>úÓqŒ±ÐçNÇA>Ÿ‡eY¡ï-ËB.—áC‡°¸¸Ó4“~œ]ì—l‡žË;ÎA~áWÀ\×]÷*är¥ i_üäPMaé úË?oëîÄ>„Œ÷œ›]‰Kl k0ÉO{•xi?k¶öƒ1OçŒR̺ð î9]– ¾¼r9Ïëy\e“¬«é!Ja-|èÐæ#$› B<ò¹ïâÈOìo¶Ø´“Ïç!Ë2vww´cЪÕêIJþº{Ix}V®€*ŠI’àºn_%Ù4M¸® ˲ül·Žã X,¢V«AE¸®‹\.I’R™­x?±ÿæ»íi°íM¼âGà8á4|¾|—‹Ïø.ðÕϸћÓÌIˆ1„êÆwbž`ð1à 3Pa=räNœ8Ñõý~®ºŒ‚ ôV¢úƯ:Ž'R©-¬Zõn—‡¾Œz˶í{Yê‰Ê€í>éZë‰ùÃuñÀù§àµü‹I·$5X–AP „ȲŒR©Ã0 ˲¯Lº® UU}…Ѳ,ߢɿgŒ1ÇqüIe)"¼@E_ÉŒÛÎjµŠ\.ç[Vøÿùø%ÊårìsÎ-® ûüÊo¼…‚—Ÿ s4‚à½äLÓ‹mU”Ñ rjS’Çqœp}>×…ó§%Ý,‚˜8»¥.\|<éf¤Š^– EQ ë:DQ„iš¨V«…B‚ @Eèºî[Lóù¼¯€†J¥MÓËåBÑN·ßÉ ÑŽ±EŠ¢À²,h𿻏¸EQ Ër¬óÍ;–Î gdB¿¯ë¶ÃŸ"ß¿¢Øö> sb6aŒáW_íMF;½ibI ¥Y‚§ ¯aÖ“8°«ª÷§ëž›ð°qí¤¬¦‡.—`Æ Î ¥•˜/ýùŸãù?(xa² T3J»³ò$"ýˆ²,D]+FæLA|K¥ªªþ¡ª*ì½vȲì'$”e–eA–eˆ¢èï?ÈŠ:°4<ëª$I°m‚ ø +Ôj50Æ`Yt]‡ã8uežElÕ+»ž­ëz Í¢ØÃx*Šíšvp^CÌŒ1¼P–»²\'¶ÂZ¯×±¹¹‰'N ›Íö|yL:±Ã¨ðL¸ïú¾~òJ¥ÑòóÐ"xzaŸ[€pÙw’nALCQðzéPÒÍ<FMÀDq´ã¢Ž ¼èDQŒ|÷ÊÝ\¼u]×W^A¨xŠ¢ræ.ŃŽ3M’$Á0 Þ"ÿónQöÛªë:LÓ gÅ=h4›P4ºn†~CQô¼¢¸…5A˜›šòÄ|â/€1Ö¿¼q ‰¥°Ú¶ MÓÉd°°°à¿ººŠ……ضz½Ž;î¸#éû eñóý䉞ð÷šeÅOÆDïÃt%ßîg¿ñò'%Ý4‚˜8ï{_Å¢>þ‰Æe”»Qƒþ\‹»þ­¨®ëúßñXTyçX®€êƒ¬ÆÄy¿Z–Q}×c(‹þ÷Q ¯pÀ-.å¯-ˆ.û10,U[ò "Ac^Ÿ·,rÕ#z«¬ÍÚÚdYÆwÞ‰L&ãŸÍf±¼¼Œ \ýõ¸ýöÛ“¾Ÿ^eV{&\rÝÁn] ž,¹®Û~ÎôèÒAԄѾûI'Ý4‚˜8_þò­ØÙ¹<éf¤ AP­VQ(ür3‹‹‹eÙWv\×E>Ÿ÷Ëݨª UUÁC±XD±XŒåÚkÛ6:äÿuæ‡èÜžÏçaÛv8ÆžEÕ4M(ŠQ±¸¸è·/˜T¸®éºndÙAàA)Ëíºò‘BüD‘|aŠèÏ@ ëöö6šÍ&Þô¦7õÝïMozŽ;†åååR›½Ææž —RâÊœ&4-za–ëöšæ¹^ïì$ÝR‚µ Sú§“nALÛ¶qäÈ)!I’°³³ãg–$)d¥äÊkçxÁãGù9ø¾Á}‚–ÑV«Õ³ ²,÷ÝDQ_‰-—˾{° :„'—k‡'Ëÿ …ª’ÂJ¤ÆVo¸d”èË@…µ^¯#“Ét)¡KKK!÷`¾ýܹs‰+¬½¬«Þ¶ —£Õ!Ú%¸XôÜy¢‡~Ï›Ø_‚.cŽÓž§Ð{€˜+ ýÂpÛmG“nIªé§ìËÇÄ=f¿èÕ¶…i¢RQý±{,K3Å)Æqd.½”&*D_*¬ 8þ|×÷I·½'ŽOéûÉGẔ9¨ºî=Ož>_Úq3üHêtà8\WÜû7•"æÛÆ¿<îj¨ÿîÇ“nÉÌ¡’â’J\× á3M@»î(OdU¾Í/adg™‚H<É›ÄëPÒD…èÃ@…5›Í¢Ùlb{{KKK=÷ÛÞÞ€Õ5mø~òQ0FEµ{¬=®(Ý‹¶MÆé4ð…/<„ þ–åýF1*]Älâ8¸ëOõu-n$÷¡8ð–Ë”bšÞ"c¥ˆù_ Õ–Ù˜ R¡¼ÐMÓbcX k6›Åúú:²Ùl¤BÚl6±¾¾Ž¥¥%d³Ù¤ï©çDÝqœÞƒ¾ãPgéÁ ҧÖ'’å·~ë|ß÷µ¨2á-ÙË2É61?0Wñäsÿ–Äš˜óÊʉî^Êý€pôÄSÄ|Áº•B“‚èO¬²6'OžÄÊÊ Ž?ŽåååRzæÌlmmùû¥ÆXt-7JH0¢и“<ÛÛßÁk^ó`øK]­ÔÄÌÃ>ñõ¯ãÏx•Ò"æžq_èVh…xlw`‚Hq2D'±Öl6‹Ó§Ocssëëë]Û———qâĉē-õÃ/LE¯ W‚˜!GÀòò3Ú_u•˜GöàƒøæãŸOÃvÇA±X„ªª!Ï"îŠÇš¦A’$0Æ ë:4M M(mÛ†a(•J$©ë’$¡T*1˲Èr2$VPGµ,r&æÛ¶£GчX +àe>yò$VWWQ¯×ýï{¹ §PÂ%Ûn×cERX‰™ÇKzÅ I¯jÉ3.ÄñèûÞ‡³O|"î½÷bZ‹éƒišp]·Ká±m;TnÆ4M ìììøÖ<˲B «eY~‰œÎs¸®‹B¡Ã0|¥—Qܪù˜lZ 扨Z°mo¡†”X¢±VÎÂÂBßäKiÅO¸äº^]–rÙûµJéÞ‰™çöÛÅ€ëz/zs†ëº¸æ‡Þ‰‹¾’tKÒeY¨V«ÈårÑ“Ä=TUE±Xô?G)ý\Ry­TÇqÈmuDüµ#ìlïe;¤çJÌ ‹a¼ù ­>xLÒ Ø/| «ax‚TÕë †‘tÓbl^ð‚÷áU¯údû Ó¤LXÄüÁ€—¾ô¥¨T’nLzaŒAˆ¢EQ`YVh»mÛþ_±XìJè#˲Lä³ã~i bhlÛ›¯è*~n%["æŠÈò’Œ‘—#1¡-¬³ŠëºïíÀãCÊeÏ5˜^ÄŒÃóÜþ\×[„±mÐŒž˜7Þ{ïsñ›O}*jo¼:馄èé ÁK`êz;¬$ykJz¤_Se¬]›{…F]‹ïϱ, ’$Á¶m‚˲BŠ·ÜÞØÑY›UQ†EQ`Û6TUí²ºÅ^UU¡ªjè¼DPrbNà²Ë6 ('’nJª±, ¢(†”b±Øee„¢((‹©\ ˜'¢†lÓ4!Ërϸc‚˜Ez*¬Ž“tÓˆà@İR2bžyþóÿ¯~u#éfÄô0 äs_ÀW¾òO4–À¶í®2(²,Ã4ÍÈýeY†mÛp:&<öuØ’*¶mãСCþ_¾Ÿ¿ô§—K¸iš»JÌ=.Ñ ƒca¥šOļÂÃË^F“xb>q^þ30¿û³È>þ²öÅ ê]§(НxKÚpøw¢(úÏX’¤Ð¾A‹mÔ9Oùíµãº^‡¢Èåü0^Ñ€¬«Ä<Á=…ÎlÀ…%\"b1÷V×uñÚË/÷ bÎpàÏþìÅøÑg=+é¦Ääa úçÒ/ÞˆõÓ§»’ĬbY{ʪe…&ì¦i’œsGOoj•B™ˆX̽…Õ¶müÛï}\ˆ¹Ä0€o|ãÃxòkßìì$Ý‚˜(–Îà^õ“Åv™‚˜l{¯@aù• xr,ò$ æ ×u=OGU ¬ÔLlj•$/ïm{²ìýñÌëQ³±écîÖOä#xÕý÷S2bîp`k«‰µD’ob¾p?öEÿp*Ÿ¾†ñ«CÇRDZqݽғ`Þ@¾gaíÌÖL³ŽãåroþÁôjrõÈ|¬ˆÕ©„r%R×½ýJ%oJÏKƒEy‹¢§°Š¢·/_ëEo}Hºã•»Ç;¯,“·ršH½ÂZ¯×±°°€L&3ô±®ëâ[üǸè–[’¾ ‚ˆdùö*VxÝ•WÒ‚ ‘ZF•qcåK_úx‚KyˆÔ2Š|[ ¼æ›^üÞ^½lß ErN¤ˆqæ(Œy"þµû_€§<úJ4òoFIzÇû^Ûåâ;K8s iQJƒñŠ–Aè=]âÊ)¿®m{ß9ާ,óT²ÜÝ6bú¤Vam4Ð4 õz€—Ì!X¨<§ßòüÒw¾ƒ'¼éMIßA„W¾Ç+g³¼üì3ÀŸüIÒ·D!Æ‘qÛì]Úý˜#dª%ˆi3®|kßý]o¶½7K.‹d]%Røs®¬ê+‡-)xÆï­ùÚ¥(v—ŠO“+® ø^ú~{5Í›w1æYvóº.¹ï©Mº´¶¶†L&Æîºë.Ôëu¬¯¯Ç>þ¡/|7ýéŸâqôG¿J¤ŽqåÛ4Ë//cí&B“bÏü)ʯ» .ÈM’H'ãÈ·öì-H}ÜŸëºA¨” ‘Æ‘oÆ<ïßÛ_ÿxÕÉÃ#Ç6…¦Iò¦Z¥’çÕ¼»ÎÅ­°<¿+c@±Øm9&F'•ÖF£íímœ>}°°°€ååelmmauu5Ö9øáÆgè‡ð‚›oNúv"Ä$äû‹_ü"þ[ó¿ãÊ+_MË{DêWÆÅ·½}á óyhšFÉ–ˆT1®|Kß=ì¹þš¦ Û¶Që49DBŒ-ߢ‹Úóþ#¾òîŸ8·¾ãIßÒÔáñ²Ü­˜+¸†ÑNòäºÞÿ5ÍÓßÇSpyB( wB(Qlëü|>õ3ÍèÄS€wŒ(v'Ÿâ׎s­¨kGÑÙžÎk¹ï¾k!ŠŸê§Ra=wî ›Íúße³Y4XÇ?ü±áoz…w“\__­ÀÌõzõzËËËI7%QÆ•oø÷Ÿùÿá/z‘?é™EæQæ­ÏŽÊ$d\+• ËòL[WçMæ±ÏŽÂØò]*Áq˜†Û¶C5ng…y”…y믣2‰ñÛ¾ä~°W½ åßÿý¤ogd†‘Aè6"Ñ^ÇBñczíÛkIêíHÊEà9ϹŸû\²üʾ±¼×êwí(x{‚×î<îìÙ&.\øf¬gËI¥ÂÚ¯S4›M,,,t}ÿàƒⓟü$n¿ýv\vÙexð?ÿg|ö³ŸMúVÆâî»ïÆõ×_Ÿt3&ÆÙ³gqöìÙ‘‚÷'É<€}ìcxðÁ¹þ(òÍÛ}ûí·ãÊ+¯Ä^ô"\þþÎmo'r“ -ò0IÒÒgÏž=‹ûî»/±ë;†Ÿ?_ýêWñ†7¼Û3,ãi‘‡I‘–>{Ï=÷à3Ÿù ¾ño$rýQä;8~ÿÙŸý>øÁâõ¯=ÞùÎwÎä\%-²0IÒÒ_ùøÝh4y¾ãŽßðá§= ¿@ã÷@.» øÚ×¼?þ9Šï|à’ï|´½Ž -]t÷ÜsÛÛ—u­¨kGÑٞൃÇ=ðÀxè¡ =~§Ram6›=·?>²³<æ1Áîî.îºë.H’„Ë.» gΜIúVÆâðáÃ3AΟ?‰ßÓ}÷݇/}éKxò“ŸœÈõG‘o¸ä’Kp×]wáiO{®9z4ñç8.i‘‡I’–>ËÃ÷¾÷½Ä®?‰1ü‡ø‡Sñ,Ç!-ò0)ÒÒg?ûÙÏâÁÄóž÷¼D®?Š|ÇoQñ’—¼@òÏrTÒ" “$-ý•ß_þò—QX'1~¿ä%/Ių‡´ÈäHKŸåsðaÇïT*¬A7„NzuÞû±ÃýØ%Ýt‚È(ò À_¹$ˆ´Cc81ÏŒ"ß4~³ßDIe–à#GŽ»%$åA“†ä›˜wHƉy†ä›˜gH¾‰4’J…5“É`ii [[[þw¶m#ŸÏ'Ý4‚’obÞ!'æ’obž!ù&ÒÈ¡V«ÕJºQÔëu¬¬¬ “ÉøAÞ=ãûb– ù&æ’qbž!ù&æ’o"m¤Va¼Àïz½XZZJº91QH¾‰y‡dœ˜gH¾‰y†ä›H©VX ‚ ‚ ‚ ˆƒËEoûÛßžt#æíím:t¨§+E½^Ç·¾õ­Èíý¶ÅÙ> šÍ&ÇÁSžò”‘Ú”Æ{"FgùžÄöiÐOÆgñ~ˆñè'ã³(4†œƒ6~jSÓO±hSã=ïyOë‡~è‡ZGm=z´uÛm·µ~øaû¹sçZ·Ür‹¿ý­o}k¬mq¶Oƒ‡~¸õÖ·¾Õ¿æ-·ÜÒúô§?=±6'qOÄèŒ#ß“Ø> úÉø,Þ1ýd|åÆp‚sÐÆïAmJãýãAãwúïiR™%xh6›X__Çêê*c¸ë®»üï8kkkÈd2þöz½îoï·-Îöi°¾¾ŽF£»îº Œ1d2lnnÆnSï‰qå{Û§A?ŸÅû!FgŒÏ¢<ÐNsüÔ¦4Þ1:4~ÏÆ= EÒó¼r÷Ýw·Ž=úîÔ©S­Ûn»­Õjy+G ­ŽüÑýQë5¯yMßmƒŽ?üp×5Ï;×:uêT¬6¥ñžˆÑG¾'±}ô“ñY¼b<úÉø,Êáç ßƒÚ”Æû!ƃÆïôßÓ°<6i…y^YZZc,ôݹsçpÙe—ùÿ€l6ëoÏf³h4}· :vZðLqÙlõzÍfÙl«««±Ú”Æ{"FgùžÄöiÐOÆ···gî~ˆñè'ãó&ß“h3ÉøìpÐÆïAmJãýãAãwúïiXHaÝVVV|a8}ú4ô‚žÛšÍfßcy½¬Isþüù®{9þ<666 uœ6'qOÄdV¾Ó*ýd|2nÛvÏ}Ó*4†Q„ñ{|§qÎEL¿ÓyOÃB1¬ûÀ­·ÞŠ'Nn¿ývžôâè¹íüùó}åB=i‚«;wÞy'î¼óN,//ceeeàýÄis÷DL†aå;­òÐOÆgñ~ˆÉÑ)ã³(4†Q„ñ{Ð=¥qÎEL¿ÓyOÃB ë>°´´„ååe¼éMoò¤ƒf÷¨ý{‘Édú›Éd¦r×_=øî€74›MloolÓ¸Û‰ô2¬|§UúÉø¡C‡fî~ˆÉÑ)ãó&ß4†\Âø=H¾Ó8ç"&ßé¼§a!…uJ¬¯¯û+GŽv½i4Èd2}· :vZôsXXX»ÍIÜ1:ãÈ÷$¶Oƒ~2þÌg>sæî‡~2>oòMcøÁâ ßƒä;÷CŒßé¿§a!…uJ\ýõØÞÞöÍø`Û¶ÿãg2,--akk+´=ŸÏ÷Ý6èØi‘Íf»Rh¯¯¯û+3ã¶9‰{"FgùžÄöiÐOÆo¼ñÆ™»b<úÉø¼É7ዃ6~’ï4Þ14~§ÿž†åP«Õj%݈yemm [[[XZZ¹sçBҀ瓾²²‚L&ã5oll`aa¡ï¶AÇN ~M¾J5ÌýLb;‘.Æ‘ïIlŸýd|ï‡~2>‹ò@c8Á9hã÷ 6¥ñ~ˆñ ñ;ý÷4 ¤°N™`Êô¨8‰f³é¯unï·-Îöi0n›ÒxOÄèŒ#ß“Ø> ¦Ù'I¾g~2>‹ò@c8Á9hã÷ íi¼bõ¼NWLƒI–¸›0A¤^2Îá^QÛMÓ„aØÙÙIú6b$úÉ?É>1KÄ™¯P¬+1ô·ãÈ{¿±RXSŒã8X\\D­Vƒ$Ipù|š¦‘{$1÷pwš\.UU©6q` Ù'‚ ˆ6äœb‚.Á‡B.—ƒ¢(¤¬Æ> QIæ‰É>AA´! +AAA‘J›t&E£ÑÀÇ?þq\yå•I7ebÜsÏ=xúÓŸžt3&Æ#<‚Gy$¿Ñ#<‚Ç<æ1¸ñÆ“nJlÞÿþ÷ãŠ+®Hº#Mò0)ÒÔgï¹çž™Jò@cxúISŸ}ä‘G°°°03±a4~§Ÿ4õ×{|å+±°°tSbAãwúISŸeüž…õ_þå_`YÖ̼¼âð|?ú£?št3&Æ}÷݇ûï¿?¿Ñ}÷݇óçÏÏ”Âú‡ø‡3ÕÞA¤I&Ešúì>ð™RXi O?iê³÷Ýw¤¢-q ñ;ý¤©¿~àÀ 7Ü03 +ßé'M}v”ñ{nÖ+®¸’$auu5é¦L”yºŸz½Žz½Žåå夛‚íímœ9s&éf ÅUW]Eò0¤å7ª×ëI7a(h O?iê³³6†Óø=¤å7ª×ëÈd2I7#64~§Ÿ4õÙQÆï¹QXç‘yê(Íf‘Íf“n‘æQæ­Ïã1oò0}–y”…yë¯ÄxÌ›<ÌzŸ¥,ÁAAAD*!…• ‚ ‚ ‚H%¤°AAA©„V‚ ‚ ‚ "•ÂJAAA¤RX ‚ ‚ ‚ ˆTB +AAA‘JHa%‚ ‚ ‚ R )¬AAAD*!…• ‚ ‚ ‚H%¤°AAA©$q…u{{;é&ÄÔ ù&æ’qb^!Ù&æ’qbVxl’o4XYYc,ôýúú:677Cß---acc#ÉæÄP|óÉ81¯lóÉ81K$¢°6 Ôëõ®Á9wî–——!˲ÿÝÂÂB"ˆ †…䛘wHƉy…d›˜wHƉY$…u{{¶m÷Ü~þüy,--aii)±C£BòMÌ;$ãļB²MÌ;$ãÄ,’H ëòò2666°ºº¹ûÔ¯¯¯c}}|쉙‚䛘wHƉy…d›˜wHƉY$ñ¤K½à® Íf+++ØÚÚê»ÿ<ÆÖ×דn:‘r¶··ñÞ÷¾Ÿýìgkðò _ýêWéåAÄb}}÷Þ{o¢m 1œ˜[[[xï{ß‹ûî»/‘ëÓøML>~7ÄÚ@ã71-ø|Øñ;ѤKQ4 œ8q·Þz«ï3ŸÉd°¾¾ŽåååžÇ]zé¥xÚÓž†ë¯¿>é[ R€i’äý™&`YÞ÷² ?~×]w¾ð…/ì{»F•ox⟈믿GŽÙ÷v³Åõ×_»ï¾;‘kÓNL›l6‹óçÏïû„žÆob?àã÷e—]¶ïצñ›˜6GŽxsðaÇï‘,¬ëëë8~ü8$IÂúú:¶¶¶&¶ª’Éd°ºº ð^^^F³Ùì»2y饗âšk®!Ÿûˆãt6M@½Ïª T«@©0œ>Áu×]‡+®¸bßÛ:ª|Þ„gii ™LfßÛMÌKKKxò“ŸœÈµi '¦M6›Åu×]·ïz¿‰ý€ßI$:¢ñ›˜6™Lf¤ñ{h…•+¨Áwaa[[[XYYûF¶··»\Ο?ï_‡ Èç]÷>FÛ‚ xŠjµ Bø8IÊeO™=>ç’obÞ!'æ’mbÞ!'ÒÊP k£ÑÀææ&J¥VWW}×Y–±±±íímÔëõ±´°°€µµµÐy677‘Íf‘Íf“~^Ä>cÛ@¡VPÁ³––JÞgMó¶¹nû¸Ne5ø½¦¥Ò÷%r?$ßļC2NÌ+$ÛļC2N¤•¡ÌLç΀H“?æf³9Vƒ²Ù,Nœ8ãÇciiÉ¿¦aI?«™‡1O© ”ÖJ=ºîYE%©ý „?‹¢çö[,zŸ5-¼½UxàÁDî‡ä›˜wHƉy…d›˜wHƉ´2”ÂÊÝšÍf—k@³ÙÚºº´´ÆX×÷«««X^^î« ÃcYž;mV×õþxÜ)ÿè¯|r4Í³ÂÆÝÿG~dgÎL÷žH¾‰y‡dœ˜WH¶‰y‡dœ˜%†RX¹uee'Ožô¿o48uê2™ÌÄ;“ÉPr‚ ãºÑÊÜâ"P«õv£çz@¼óFÛRʱíá”ëJ%ìœfH¾‰y‡dœ˜WH¶‰y‡dœHC']ÚØØÀÂÂŽ?ŽíímlnnâØ±ch4ä2Ž_IsÏÄu½ïâ*«ºî%- bíøÒÎï¹›nç9:3ûr‚É“Na„°…– ‚ ‚ ˆÙfèT© ØØØ@½^÷ãU(;!tPïoŒyŠ"cíý!lÕì‡ã´J^ã”_*yÊoPñåed:EOéåI“‚ûF»mÁíAÁyì^æR‚ bþʺ½½ I’Ðl6‘Íf±´´„¥¥%RVDQ¢•Â($ÉS(ƒÖPn-]\ ï˘—7/S©xÛ¸e·\öÎ[,zn¼üx~Í ¦é)ÈA%9¸o/Ë+A ƒëº‘±9AÌW½÷½ø ‡ ‚˜k†RX³Ù,`ÓK"5B´Kp”+.¯MÊ-—–ÕVE1¬,òM®¾¢è)–šärácTÕ³Úvø¸BÁÛÏ4Ã× nçȲwmÃèv=&ˆ¸X–…|>wV‚š ‚èã´WC÷¸¨Ùħn¸!é–AûÀÐY‚WWW±¾¾ŽF£¹ÏêêjÒ÷t %l˜»Ü“I’÷™[>-ËKÄ”Ï{J¦izûòcUÕ;&¨xÊr;nµ\îþÞ¶=¥™“Ï{ç Æ©r…•ÇÖÄ(˜¦ UUaJiö-gÌø4·‘ &ëzJh¿”îºîºî½”ö¸÷~N;Õ;A‘ †Ža][[àŽ‚Öýö=‹i”çcPa<…SÛÊ¡izÇóý¸¢xÿ—eïÜ|~ÀX÷9£æšÖ>ž£ªžË±,‡\Q잓Ȳ§ðîìŒöL\×…0étÇÄLÁƒ (•JX\\„ªªӚ˶ýlš&\×…F+5Ä<Á˜7ØÇåbÑSX h× /äðã‹W·Œ ‚˜+†VX).,=Èr[Á bšá¤H€77ÎÙƒÉø¹~æg¾YþKH’:ÖuÝ=Ëè`E·©îŽ„+· £dyø’6PÜ{åNÍšH-Žã@„‰.2˜¦ eO¨4Mƒa镉=WGÓ4aîùÀK’9Å’ bXLÓ{Ù”JíÞ4§¥·íx/ RX ‚ C—µ!Æc˜d0Œ1:3EP.{ç- p¶í½ïƒŠ¬¢´ßó¶mãê«ßøgÏç‘ËåËåð˜Ç|››‚a}å–1†|>=ªnMàžŠÅbߨæÎvþÝînôý ;_·mŒ±½û§ëY€1†\.ç/4Œ—{kÏ=Àu]ض uÏ·]UU0Æ"û\¯~èº.LÓôû†®ë°,+2Ö"KXäõll¦i¢Z­¢\.£X,†¯Å­Q1àòoÛ6¾öµ¯ü\‰ô`Û6r¹ÜXñØ\†÷ÓÄwßõ.üÏ׿,¸ZªªÞ ÏãP¢oº[1U”ÞûA!ø|hМ˜Ïá:äÏ÷u]÷ûî±÷ßãè8û·‹|p¨ûIaÝÚÚÂÊÊ $I‚$IXYYÁÖÖÖ¤žñÜÀpWþâ(¡–e¡P(@èºî'- “¹®‹|>AP,ýz«|Žë Ãб¸¸˲ð_ÿë ñáÿ_T«UÔj5Ôj5üê¯fñŠW¬£^ÿA‹E_a.•J=…6xmÃ0Ïç÷_a´,üß·¿¥RÉ·¨ÓDz¬.åÊu]†1p€ã²UÝ jþf®ëB×õ®s¸®R¹Â+I Àiš°,Ë·®rJ¥ …Bh5M…B¹\Îÿž_7ŸÏÃq”ËeT«UH’ä÷Ýà9ŠÅ¢¯Ð‚_oqqÑ·¤Ú¶?ûÞ÷ðWßþ6þöþ‚ @’$(ŠÒ~®š¤G*ȶ ˜¦ßvRXç ˲ IÒÈIÄ Ã€mÛ‘ ë8‹E}±m<ò{¿‡—<ôîÿæ7»úo³×BL°öZpIòâKÈÓ‹˜s>ýéO'Ýbp'z|ŒA¿¹¶eYÈår°mÛŸ›/..vÍÏøÜF´Z-T*Ȳ Aü¹Ÿ»äóyÿ<|îÃÏÅ•\Çq`Fh¾ÿ-..âŸÿùŸ‡¾ß¡]‚×××±¹¹‰ååeœ8qÐl6±¶¶†z½Ž“'ONüEcþ-Ë2dYF±Xô•¿Î‰µ®ë`ŒAÚ[U¶mÕj‚ —Ëaaá?akëJ¨ª'ˆŽã`kë6Èò^ÿúÛqñÅÿåò(‹¸ó΀ >ÿùï!—»’$á3Ÿ¹¿üË÷çSUϘó«¿z–õÈçóþ„=* WVUUõ-Z¶mC×uȲú]ø÷Üž/ˆØ¶í/”±m;;;¾ÕŸ¿âÀqªÕªß?¸Œr¹TUÕïð¶†y Þ^Þ‡¹gKp\v§}ÿðøÇãþüÏýEÞÿükñØNxÌk6€—Þ{/Þ`xÂžÞØt‚ƒb±H Žs‚ëºp]7r¬â ÷ªª¢X,†ÆvƘ¿ÈÈßû|Ñ>8ŽóùŸí|Qïþá ²(Šþ< ðÆx~¾A÷er¹œLÔ»‰·—ÿ›·ë³Ÿý,Î ›4¯5çÎk=z´U­V»¶Ý}÷Ý­£G¶Î;7Ì)'ÆÝwßÝ:uêT"׎BUÕV¥RiµZ­–¦i-AZµZ­ÕjµZÕjµ¥ªª¿ïÎÎNKÅÖÎÎN«R©´4MkíîîúÛ+•Jë™ÏüÓÐj•J¥–$I­R©ÔºúêO´Ah-/¯µÅÛ÷ÿý¿ó­……?iU*•– T[o{Û{Z;;­–,Çk÷^»ØÝÝmI’Ôõ¹\.GjK–åÖÎÎNÏkíìì´ªÕj«Z­ú÷Ë?˲쿳³Ó*•J-QÃ×ÛÝm}çE/jËdZ_Õ«ü¯ùñ»»»­J¥â·EEÿÿ/yÉKZÿþßÿû$ctn»í¶¤›à£iZKÓ´V«åýŽŠ¢´TUmíìì´vww[¢(ú¿)ÿ\«ÕZ;;;­r¹Ü5†ÔvC§[€IDATjµ– -I’ü~R«ÕZ’$µ$Ij)Š:_¹\ö÷ %×à²$(ƒýà÷Êû6§R©ø2ËÿDQlI’y½8ÔjµÖ¹W¿ºÅ £«ñqBÓ´ÖÛ.ûÍÖ­/úë®ãÓ$/qHÛ> J¥’/œZ­ÖE±¥iZKQ”–,Ë-EQü}ƒ}£V«µ>¸·<ùE±KþZ­–?Nr¹Ð4-Ôù6Ž,Ë-MÓZ¥R)t~lµZm•Ëe¿¿V«ÕV©Tj½ùÖ[[ç/¾¸õw/}idlµZ­o]{m×wü¾ù½þÝÿû¡S¥Ri)ŠÒúƒg=«õžW¾²U©Tüóów jµZkmm­õk¿ökIÿı™µþHL–Z­ÖÐõŽ*—Ë-UU[årÙ—sUUgN^æqü—jµÚE±%Š¢??êÜÆÇ¸r¹ìϱù|·R©´ÊårKÓ´Èy'8àûî;;;=ßýE^†RX¹RÚ‹[n¹¥u÷ÝwïÓcÿæ'EçD€+ ýE±õÁ>ÜRÕ–?Xõãê«?ѺñÆ›[ªªú¨K”Ë­Ö­·Þß¡õ“?Yo•Ë­VµÚjš×M@¤\nµ4-4¨öRVƒðIqÓ4-rBÖy]f­ß¿ürïsÇ=Ȳܒ$ÉŸxù Ã^ÇšÅÁu?^`ÕjuààG¾ùK¸Õ +·ý¨Õj]ŠŸœX<çÖîn«úìÛZQëB4áÙ_øØDQ”ÖÎÎŽ?Îq¥­—Ló6N©TêR(wvvüñRÓ4¬ã ™\¹¬V«¡ _8jµÚ‹z q«ÕjI’ÔEÓÚ¢è½`‚ìîö]!­Õj­R©ÔRUÕo7ŸÐU«ÕÖ7_ð‚ÖûÖ×}…žOø:ŸÃ¬ÉˬõÇ´#Ërì‰y¥Ri•J¥Ñ@Q”HrXjµZ¨–J¥®FÞ÷x¿ãó8¾S­V[š¦µ$Iòûÿ¬ÉˬõÇiÁÇ^þ{RY–ýEsEQºÞ|‘18ÏŸWF‘—¡]‚Ïxaa¡ë»^µYç™`lw¯âÿ(8sæ]ø«¿úE\|±=0‹éãw~üÇ_*yå å8ÀñãOÅææ®Ÿ|i`ØcýÓòî™ó5Móc[eYŽuñ„<éÔ( ø®mŒ1Üpçø±•Ö‰¢ˆR©äç/¹Åv (J(&š1ÖUæHET«U0Æàº.E‰ÕGx_âï,MÓ|wdwÝêérÌËÍÔjíþÞ‡êº}³æq—âž¼úÕxÕ߈WMñ7$f‡(—J˲ ‚Ÿ ß\„çṂó—r¹ìdž[NÌq?†OQ¿ –e!ŸÏû¡*²,#ŸÏCÓ´PxØââ"4Mó¯K!Lé'˜Ä¨S&mÛö+ˆ¢ABóž`è\/J¥Rìñü 2”º´´„L&]×qòäId2@£ÑÀ©S§ü} |"_.—!Š¢Ÿ&ÎýÈ‘·à×ý–—ßIIæT*•ž±LAx|¶¢(¡¼Œ2©á“vÇqPÖ4À¶}¥•+³}Çgÿd:ë§ž ŽÓ?ÆÌ}@Ì<™€P<ž®ëþ{…+œ‚ ø•DQôå¹Sqè¤Z­¢X,ú &õOonš¦¯`áJ(ß§X,†ZÀ{7vÆŽéÄq?^ŸçÏþæöÞªiÚDæ9$½ÚÂÊ_ÈÇŽ }ŸÉd°±±‘ôýì+| âV©TË墷£ê‡>t5^ô¢ï¶ÃÖU]÷t.Qì¶ JR¸TMç% ëk¢T*@¡0À ¤ªƒ-¬{´R©$«|ÀSZ5Mó¬zü!E¤íD’ÚÚþÞè=¤>™æYuùÊtœ•Á(ãAø‰¯kš× Æ@mëÒ¸XV¸ƒ[VôD½SuÝг¶þþ*H?ôŸX•Çq°¸¸’aÓ4!I’Ÿ‹+•€·‚L´×©°Æ­7ÌÜ“·ºðÅ(MÓ<åÓ¶ñ#¯}­?é²m»·¥i¯fðDäŸ ¸® ˲B™¬yr¹Z­æ[-kµšŸðŽ+–ÕjÕOè§(Šß÷x?ôî•JÅÏäÎ=x‚˜`ùþ’$u%´é„[Sƒ ø‚b’~x90nZÌH|~s€ZaÍf³x×»Þ…üÇÄ—¿üeÀÂÂdYö-®ó _m±, ²,‡^î’$E»{1[­@fÆÞ9¼¿rYëÊ(=]ŠÿÅS\+ïpÃðô1®oÞçÎ~ÒË二¨ÜÛ‹€;eß Wʹ¹wšŠm§»¤(zíì˜ÐwÁ.)¬]­9Ü:KYžÀuÝø‹õľ1”ÂÚl6±¾¾Ž'N`uuÕÿ~cc›››¾";¯–Vî9tpþý—@yà]€-C·å.¯BQôÞóÜŠ x êœr¹=àI” {rcgÿź¨$õ÷%Œ³ª®ëíý¸©¸sòíºmò¸8N÷ùãÆ>É2ÿíß/yÉøí˜#c£ÐiÁ÷’IŽ¢ô_d1Ͷuu•Š7 ç+Sè:r~¡)zœçÇÝÞ÷,R–^›‘®üìw_ùõOKê)Ï Á:ÙÜýײ¬.‹i¥S¡üš£ãÔ¡æ–ž'½óÃǃZ–'ë\ž«ÕÞr»û/ɲ¯”h{ÄUDxÒ5 ”|-6®ëY’IqM5¼nd©TòcF-ËJaå¹?\×EµZJ9¬NÃÂOh¸Û¯¢(~":"ïÇ’%“H˲üLÍ€—ЫT*‘²:mØ{æ£0”Â:ˆóçÏ'ý8¦JgØÒükZüy@¡àéYÁ÷$u[WÇ"®‚hžÂý`ºãI;ÏËå wœîD8Žã­²c u$Aí@pï/üÂdÏ?㌬¬Þ³„[ù40Ív¼h¿—Q¯Eþ|: ñú+Û_tȸãtäüâÿ® Þ’Þö¶î.h›ù[@}#Z7‘$ouË0Àîj†tù'žö/m§™+›Í¤ŸþLÂcPƒýA’¤Øñ¨‹{2Œ°uÕ²ÚñÑüs§p–a&^²Œ~ðAH’äµÙ0†ÁðÓ(ñ¨¢èÝ˸™·‰©ÁÍN 3ubÌ#Çñó"Œã}@ãP,ýŹß[€Ø,«mD¡Vîî»¶¶†f`2Ôl6±¶¶ÀKÊ4ô+/0ˆÅò[»,(qàq©Á¾ÄóÇD-FíM5Ìjx¿{Š휑wfAå>ÌÁgR,¶÷á I'©ÎfùàýžiŒ÷ZÿûÉzŸÄcΟ‚py+,>òiþÎCÀ£†TOaÞC0 T^·éx¶[¼÷~ÓÌï ZüóHØãÀO~SúO„oá®Fõ%oƒiN˜Mô†g…‡±WêùK=(tªê£¦é-èéz÷;e`†½d—ïìx1ëü|£Œ•Š2Zh€¢L?I1Åb±gL/ÃÔžåWÓ4Š ${^(G*B4x˜Êºgh «aØÞÞÆM7Ý„ãÇãøñã¸é¦›`Û6666°°°ô#™ £º». >ñ+#½Èy¡Î~%Ia«ëÈ Ê¨Ë÷qœþ´¨Ø¿àŒÜ4½í×Ò4ofÏ{°`!É(—Ë(‹B'Ü-­ëG ×£ ®ëúå8€ (¬@:ë'rÙí·þ÷X$±¿üH'^ÞÔ¡àZÿ÷(ýÇûÃvZYÒ;ŽGHìÝ£0M šû/^ór á}\×+Å (ZDÝ+Æ|oÎæt,ž6é ñ/>Ü=fõZ`SUïCÒ)¯Ã†Jáì¿Åb8Â0¨êhVÒ`ú{"qLÓôkŸž²Ê³bG!Ërè]Ò OZV­VÇr“'ˆQá¢(Ž”¹˜<ù‡ÀÐ k6›ÅwÞ Ã0°´´„¥¥%œù!@’x>œÐí ÔD• «F…×nœº²°ðç¸l3æ…E¨j·0ôJ¦ií7¼`÷¤à5ÑF='o1³8ŽÃ0ÀÃââ¢o‘ê7Éç5K£5¹ALžà‹W÷ WôáïYÙo`–àF£f³Ù¥ŒŽRçj–à¤ù@=ꄞ1@8ú}€xQ÷ä%Qý«¤ìÅ aLך ù¶WRšàwQ/¥^+È]Ûz=»^/1IêŽ×вÒFשìP¿.lÛ†¦i( ¨V«ãŰŠâdŸ/O3îË%N‰£`y¤(ÅÞ)øúIHüöú†õ»÷B~Ù7ü}óù@2¤½ëG-0E%SÓ®kgÑîTN%)Æcæ E$ï#11…•¯ntf5­T<Ù^\ôä§Zþ­âXa²nø¢Hq¤Ã0|·]ÇqüZă$©«ï˜¦ Û¶‡+– 4lÎܪ*Ë2ÕR&ìPn»˜ä@ÈMë“8OPaí¥ò™u”BÌD<…C×G›Tu¶'n jÔ ,dKð`jµ$Iò d̤Ÿ­eµPÆyÉtÆhçóžL;ªã„ÝÐ#ž¿½®ÛÜ+ibÿËSP~ÏÕþ)¢*/DM†:+¢H üÓû#åœçµø3Ñ òXð…œ‘qœvíÓ¨º¾|\TUïß4‰"R‚ã8°mÛ_¤E1¶EJ–åÂjÛ6LÓœ™24¶íMU*•É8-p§£8 0OþMèÉÂËt‘Uu xR©]]Ãu=/!>9™²s Kp&“a8}ú4²Ù,¶¶¶püøq¬­­Á1p6ÈöövÏmõzFcª Ó4¡( Êå2,Ë ×§‹Ü¿w qÈ9©ø(ÂQžC’z»÷ò‘4*ŽuÐ,Z–G¿ï [qg AÇñ„¿9z¤Q¾c¾‚ª(Šÿ76QñãžgggüÉ|ç, JÆûÕ^`¿û~8w~*Ô´ÐùT.ûÙÐ9¢D-Îê}©„®:ņÑöÖŸD—Ÿi”ñQàn#¯Äëº÷ò–¤Áò+Š“WVGðà!ú3/²n]®°:Žƒb±]×Q.—gƪţ†â&/TÄÀuãç1Ívq„$˜Gw–e‘²€W Ãðæ6½„™×ë.—'3÷ÀP1¬²,ãäÉ“8}ú4–––°½½=–òÚh4°²²ù=OètìØ±ñV¼G€g‰Á½à kg%Àûz514^OÊÕË:,3ëAçä™}‡!Žo¿ëqwƒaÎ`,b¬À¿éfù.ÀL4s㸃÷»s¢ãºûøEaet„Ò;ÖïÞ ç®/ùŸ»BkƒtÃ㻎ÓõnoúN6Íöùpïúx—V+ŠíÊjS‡‚¯²Û¶¸ç†ç¸ærçÊÙ ËÉÄ=b¸B0 ‹agãz™†ø÷’´¿.l<_KÐ̓¼÷‘4Ë70áÄ2“&îo­ë}—°- пó›á/;—Ðc$ã’.ú8äãO ‚wAÆ€âÏ}·g{yózÁõ]ˆ]ƒ¾¢Ä ÙoÒ.ãýp]¦ibqq¹\îÞÀÝÓÀ0Æÿ‘øêŰ)à‹Åv&vblfY¶G—û×U«Õ°³³“LÙž/cDœO^€ðsÿv ’iÛíñ¼×åòùø6~®R)°ÿ^QïW™^ìï¼É¸aÈårÐuº®C„ôÎq¦MºvüÕæ|ìaÏòÖÇøÄ_)>ªþÂuÛ>ôƒp]è?YïZìϾéMCßÚP k§ëÀöö¶o]½þúë}·á8çÙÚÚŠÜÖh4°½½'N°¼¼¼o±¦iBUUFô頻a#·ëY÷gÙŽÓžÔŒ`-H¯sr…µ³ ý€cÁ}â-k8·bžð)!Ò,ß|r>ÑŒÁ‘h\yˆãúí8^Ÿê3±WUÀyèpøËÎe晴7Ÿ¨A®Xì¿=4¹à³ âÖÏ=wTErX—_î«8M\׻牅Ò/ß_yä¢ß²sÜDaÁ¬ýâ&J¥ž2Á›Ð5–FÉwÇ$Í…=g{ó†ïû|×I‚·X©ò_ÿ§ÈvkcÇ)OÙïýÊóó¤‰4Ëx?¸µT*…’ÊpWƞض¸–Ï{¹\w€q‘eO¶‡=W¯‚ÝÄH̪l c …B•J%«è$é¬y=Ìsø‡G ~ý€,‡ÆíN¡ýzêïL´-^úe°è?!×4@÷ÆÛ†%•`j;€ªbqñ£S{\ó$ã–eAQˆ¢Ûç Æâ—úãõ0!"þTÊ0PzÍG _ü?z*¬|zò¨æ )ƒãù;Wa|ü•Ñê‚ëúçvþþ^°Óu¿÷k(—=ˆ'»pÝu¸ö3Ÿê1ÄRX5MC6›ÅéÓ§ýï677ýïî¼óN¬®®NÄe _§h6›=·=òÈ#¸ï¾ûú‚gþüçŸzÉ«mc¹Ñ1jñÉqùûvÚ_Œ«à­O|¥×õ&T“RXûÍ´-kúyàyVÍaé“J¿ÑhàìÙ³xðÁ§Ûö×îE?ù€ .`{{{¬‡mÛ“_I祟VÅ—§‡!j+¨ª=K‹m«fWq]¸î^Œ†¬‚u¤ï¶,Àm]µ"£úSÿ»K¡å«æ¾®ÒçÅ´²öz4º.;)¶··ñðÃOö¤1Ir „mÛ]“™r¹ ×uû/ä‹íšÑÕª7&:Îö‚Ï–‡U9çÎKLaU¾oÂsæÌtÇ™ì¥Sžeš†¨vÆ@s¥¸ð€nÝÙçi/Cîè÷ü\^‹Œ\–eôôÅ›¤[’öbi,Œr{’œ9s&‘Éì>ˆ^ò_«Õz[™¢ÆTYžL&ë |•tKiJÝõ¦ER kÒã÷$˜eðØ õ bÍ×ð{9ìˆ_ü $Íës½Üx; \Q¥Ç- `þ†7¿²,H9åç/ooìX€åÕ¯‚}^Ӽ׿÷[¾tߘ¦ Y–g&õXDMhú¡(€aD–L’e€Ijd§(ÿø{YîJ Ev?éëò^.…ÄÃA}GÛR¯iž—ÂÏü̧ñ÷_Œ;o¸a¨G0Pa­×ëXZZòS~FààŠtpû8ô‹Íd2=·]yå•$)ÒÅ!.Œ1ȲìOF£V¾]*…뾓Ò`Y˜^«$ƒòšw¦ åËAxF(>¡ç±~Ás ãeÍåÉnxv°dii 7ß|3žóœçìûµG•o¸êª«°ººŠ¥¥¥‘®,g31:4û ¨R'Fn |iY€~ç ýc]å{ÏG–»›#üÜ¿Eu³Ei'4 â8ƒ U•JÁØžî-*O8PaÍf³¨×ë~¹šf³ Û¶»V ¹+0öQÉd2XZZ %p²mù)WV®¼÷ó¦åŠigyÏ( c{ÿ4Ùáƒn/W]‘výN¸?#‡K_¹©ÕÆŸ+Š×±æeØg’’o íA0UúYÝûùÒÚ6*’îG©¹“AhU/Ð)™aÃøóžØÎE$î¶ „³öN AèßUd¹o¸õL’¤Œ÷c$ë*AH«lÇ…'¨I”`µƒñn&:„)ðΤpžÊÎ×õøã0›¯ }§üòsÏ>Ô\ {Çó —ƒû¼—Ï~v×NĄ́ú7ßñËÿYH®‚AfAÆc0 cö³ŸeÙû+=·€ÅÅp(J‡ÂÊØžú|´·Çc¹ vñK»ô“¨ÈÓD(‡‚(vÛ":/Ñù™;qòÒ¬“&–º´´„••¬¯¯ceeÍfÓŸørV×u,--Mdfuu[[[~Ñâf³‰[o½uìóö#è.Ùkå+¸€ÁãYcѹLubž–¸—ªÓ%¸“^É:¸Óx¥ÏJ\´íîKTœ+1IÈ70¥ »m‡å*êü{uåúÊwT‰™ kµê‰_Haåuz °Û?ñø ¡ó,.†›•$xÄjD’’ñ~D%\"ˆaI£lÇטO¼ cÅ@ð¤wöÎ ÇÃ+ú•ö _ÞÿþÐw‚,uMgÄ?ÚSo÷_½ªêùnÆ;;`/ÿ‘·ÄKÜ8`ýÅ m-ù1®i&Í2tkŸùØUÃë{y3ÜßùèÊL1 v¬¸Ø6 ßømØïødß•ö^©f:=¿d>÷§¾°óR«œ~ª ß¿XŒ25 ³S©TÂúú:ªÕ*B ˜n¿ývlnnbiiièÕŽ¥¥%°ˆ§ÍfqÇwøVÝýˆùˆ*ßÙ4׿jໟt&êˆòvÝvÀ]/ä¨gËÝ„ùÈu\T}žþÂûÓ´‘ÓÄi’oîî>ÉWF£–¸÷Ðÿè¹_úƒpô€¨wT_ç¢hùR¡ ÀßÜ5Pv®uÜüœ|`žõÛý&M2>Çqâ[— o0ë"bdfI¶ã ë*wq4£åaL@{±^Ó`šž%¨ü³gÀî{XýÐŽŽÛ³"˜f‡g‹ëBþÍ|—•¡çãe«ç ® þt@(ñeðT½"¶øôŒ§nz‘çR“Ï{ÏbÈ,©“fe¼P( T*¥ß[¦×\žãºžàt*›² ¶gè2ŠñEIòR+´J0žôz@zfÏËô2¬quƒwEU°BmîL¹S,F{ƒ žóÜ„ÓüYb)¬\IbyyËËË÷o_XXØ·Nâýp årÙ/[ÓK·T¹£ËØTŠác{)‰Q<%¹DNâeÔyãTÛo*ì§|SŒ_ß|›÷Qç ‡ ü—o ( «þº/B½í"ˆ7^Û= îÀºç#¡Pë^ɸՖD}²ì·ŒwÒãÛÃ@×»ý¡"@Ò²= –e¡’dî ¾taëœ4qø„OÆt$0&£ôË_‡ôKÿÂþœoG_ªk’^ô’!Y‚ %péž‘V’÷ïwýÐ@I‚§†7kïhs¿‚ ¦é]Ço“ xÏ NªùI£ŒëºY–“_x1 OpzµÃ¶Ûš\/Áˆ0Ýs™ì¹¦È$© ð¸Aþܯôl&¯<%ã<'+³’@ˆhÏ ¥]±sÚqÙ±ê°^Œêúú:Ö××C¥k2™Lꂱ‡Á›K·ð裙ÀgoÛ0}¢#Ü®ÿŽpÓOß<Ñð‚ñ€7iŸÄkØ63ã8Ó‰_3±¦ÞíaÂd»ßéX¦»ðÞþö¾ñI_õ¿Ž V}мFO»šô;˜,º®ÃØ›øÆN¸ÄƒÎÈÔNÌ©p؉mÃy_Ýëƒ|æ^­{äk?¨*į·Èȳ¬îYhùûÅAB–Qúö/AQFÐe•»÷R ïz]ÃɰžoÇeYéÈ ¼Wg´'<ãc?×oÃèZYé,µW(tLÇ÷jî9{Î/½³¯+0wéí5=ã廽ùÔ­·v *wŠë—’«“ÎÿE,…•Ç®nnnbssÓgžò”óxà a½/vŒ*†2î\á .ñu¸@dØýãÂ¥4å+€D|lÛž~Â%ïBÝÚdŒZ1âe_±^²w\åIo#”}½•Õ`Ô(—`b>á Æc°m;žu•áìÇ›— ö‘‰¸wÍž‡¤ÓÅ¥#A’¿Û[ÖQxôÝá×ÈÞÀí8Å…Dé †˜ô;Ž÷Å^ŸVÕvIûΕ!ö®'‰{Ú-7EE¼@¢*Šé̶JŒ/a“ЏÕÁ!sªÚ]è½}3XÜýgØNxÒÒ™£µWaã–O€½ö·½ª&½.3(ªEUÛÓ³¨ýxžÌÎê…(“OI,…ussËËË`Œ1†ååelnn&V˜~’È2°¼ü[øþïÿ÷:ñ°í®Z\ýŒIۢʤFÒ9™Šóë¥8v$¥™¼Þ÷M fw22Aìßù(Ä«/èQ/1ˆ/½*ôUT±¨ùßgP8 1_pøR©Ã0â%\Ú ‚Øg\×…išã+¬eczUf£ó=Ôc®Ã¾ÿ (m,øåÀ¦®I1/ Ä4÷Þ…B;eéÞ‹€O¬ #FieMk·Ù²"'t¼r 9¥MÛ¶á8Ôa¬HӦˬãº)¶?q]8ïü+Ï|òÀ<9A'Ê Â±„ò»^SAˆ^0‰ÊÕNÓìýÊ㞣qêÓïVîþ{âÄ ÿ;^˜dÏ:Œ1ll,xuùo(ü‡Ã¡ýTµ÷Öiñ@„3x$“¤°>Ê%·_:ñiXA{õb&Ù7ë*'(;ƒ–æ°íï@¼êë¢ßú/}Û+ *åzÔ»Œw§¨”ìÄü“èñVÓ4û[X¹‹ 1G0ÆËå ªêxîÀ|ÅoÂÊÍ—Á¢õœ¨Yo§,ŠPNÿ$d¹[Ÿ:¼ÓÅ›)ð´SYîZÉäJî@݇k·ü~"ÆþHi]ºpëjªˆê{Âè[ù£Êè:Ä_øq”þÛE]ÓìÎ…õ^ÖRGòàN§ È·¶Äz­eq›Ø "%ûEìÖ`œêÂÂBÒ힦 Ôë—BE&á#]ù¥Øç )»{ŸÜ?|úòN­xPýUQìí0*¼#Ò²á\0Õú“‹)¤¢—Å;äÕ}öõ~ùÇýÃ;qûWAxÍË».\Ù½æÕC%æ‹`™2îFÖ³‹ž ‘+01G˜¦é—ÿ{²Ï‘E)¢{8à¼ëoÚã{çü!*ÏFǤ?øjè\»—åîõ¤ÎÒÞ¾uh×Œï –u5ü {j·|HIÃd~^áñ×ûºè‡N Ô„ç91ìçþB×|Ç„ GÑ"=â;Öz9\F9+„®aƳˆrOÐ^s#^Ç8 ÖU`…u^ùÇü2sè \Æ^Éç“ _D”Ò/ÈØŒm°®¯Oî´K+ïp†Ho !h7XÿþýPŸþãÐ5L…é—„ ªÓ™SO–ƒÎŒUUqÜo|D©äýDå®LºH@ÐÚݽ?þÒÉÞxEq]…BÕju:ÎJѤû¤›&`îÿ•ߦK«îÕñîô^`ší·›aú?v*ý–5¸yÞáá ö¤@µ‡.¤(³©Ê"-¦’Î>,ý…ÎÁ¤kÁ4áþã·øê½¦Ö£/hdÇ –æ«øAÙé›ê4Z·¶ºeNêX-ËSÛ†Þ n–$½Á¢âË=óë[Þò>|ÅWüïîƒÂ1†áyæOéì§ë€ú¬†+ë£D]{ øòùÙ´7-—™·"Œ5ƒU%}”ó§>£þ–°líí¢¼é3U …GâHï„OßJ¥Z÷‹~K WYMæžOfŠeµRògÕ4àGôÏðâß\ôéE’B¡€T*5½5ÁÜ׃ն=Vƒ²öw­çSV$÷‚B–Õ~«è¼M r:;šl¤‰U®Û7«ëôsÍš¹Ì6ÍÖO¬ú=äÞû¦ÖŠÒ®x˜& À ß™’ÏûkB& AÑêU'lU#åMꜢxæH¡à½ÿ4³§§À9 CÍa€®ÇŠÅ"~øá¶Çö÷÷}M#aÛ6¾ê«:¤Äò¦ö&“íÂÕ6cÈ0Ú:þJéF[Šˆu£û;7üAù)ƒR‚ éÃÐã<:âîoüìs 4¿]¾gEA&Ój ÔµÁÊ\=]‡e+0Ívža´<×ê—<úO¼%ôóÅûgšý}+ªÊ”­³„eYýS {Í~$3e@°*Ûö±ÃÃneîÎ;ÿ·ßþÙE_Väp]¦i¢Z­Nç ƒNsÙ»;Èd€Ã×\Aú»^Ùz^ÇÈÃðÇ©ú~~];¤A·d!‹Ó1lŸfOÝ®éÕ!Ñf‡d‡Í¼3°„æe(iˆ ¿xìæ}hA¹Ïô%yÈw¸”Ÿ¶,N´ËN¯ø@PæÛRÞ¨ª×¸x¦‚4?‹‚cf Ázîܹ¶†KB<_ô¹O…_ø…¯@:ò—PU W:JHôɶÛgÙ6 õÊ‘Çû¥»n+ö•x¯axcLooGÒéž½ù‚{wçD@Az#ѯ¿z˜¦9Ÿléa ¥~! …ÛxôoynW&ȃùŽ—+QlÛû Þv¤$|Ù•SëeÌJþ£¤? 4Xc±˜ßxÙ ó|âçº#P2¬Z»˺ËN¹yú3¹BÞ_Èå€2z´µs]/ÇÉqz+M’n¥xôƒ]žHÛö"¨"÷uHâ%TUx®;ÑdHoaë0Êe*µÄöíÞ«h4VçFØx…tÚ»nmyŽ^IFÕ*´Q‘5SM¡ììô®ëmzùð3HÇßšÖ]âl®÷½Ÿl{Û`ä¦G¦?'Ò0ú7`ê'Gd91Ms~éÀ²ÑÈgudGº¿ú{€¦…gr™&Ì{¾;Tþ§å°ËëÌ èå —a g=)hhƒÕ²,\¸p;;;888ðvvvpáÂ…ÈÏd•Ð{p3µ, Ÿýl¬ÿ ?ýéöß;£«a=¦(py·% g¬”àÎ5Äã˜OÙP¿ò¥Èj[@XjWP‰éRL²Ù‰sYh¬¡¯Á*¡xæÎ ]÷hšç¯ Ž%‘ÈkX€ƒ ‡eYÓoPÓc)pª}ñ_¶YŸþ~êIt]Àüµ;Bפ‰÷J—ÚÕj–O”Foé0·æy^Ç’?ÿ@*E I‘µmþì›BI)oêW*ûc¿@r¹Ü;úz–Ê`­T*Èf³8wî …lÛö …Î;‡‹/F:ÚjÛÝ!uÛ¶qÏ=Oö~Ñ‹^|ä#íu¦ñšfhÚ®rÏ ¦Ûª‹1+%8èö éèë{ºÓ鮹©ŽÓí§ 6ÅèQBÈĸý4ZÓØñ“LŸASׂMÄ%¡ˆ¢ñqgú3·û±™&ýï_ÞöXÇhUo\Í­/Õ¶¥5â5 15}9ë‘§Ud&Η0l»]ié0XíŸú}¤ÏÐÿ]¬úç©ç¡ý“ç÷”áããþ=,ûŒ6nƒ™! Ö½½=躎ýýý.Gðñ½½½E_OO¦ø®‹µµµî'‹Fþ¼çuËçÛ%'•j›±äóœçÐBÊØÊKgH¤cßÚ\Ut½k˜{˜bœ•lLFÈ4é]Íå˜ o{{õz=²©Á( C}ôøóÎ;»Ÿ|*9ù×ýOè/òjH{ÖOHÇ<´—ý²h¦æm¸ÌÇ“ó^ÊC¯²mÙÐ{uz$dR,Ë á$^:ÇFüU=¦š´!÷YFJçËÄë0ažÂ>NQ<#Tt¦T Pÿá‹Gzö뢓ó¬13çK'½R¾N½ðޏšÞ•9¾¶íšƒš!…eÛ„„ƒh°Öj5Äb1Äbýk=eÌM£ÑXô5…"©GAcò£ý(þã|Nûƒ®¼À ú”qø¨`¤‰idÑôTàGE"¬® UíÎËåZÍ”z­YT<ȬèaUæ NˆizŠ™4L¼[ãúzwÍi.ç팈͗‰kþ¶¶ZaÑŸÕßqágÞÈ, „¡³çY}úfË I[ª­ë†ÇkZß”÷d2Ü#Y‡‡ƒuý0)ˆ\&e|0ÇÚ¬­­áÖ­[‹>Ï©t²;Žƒ/ú¢w+СHöŸ®Áþày¤1ÀAêv¶_¹ í[^UQNÓ]B‹ëº#¬ÒS¬íeªê=(m¶»ƒ4[êe8Žw¿`V&™Žã„Ë;‡4ŽD&ƒ¶æ"Ò(¼síªªWsÌ>’Ra:lç‹ÔoOä ,•¼=~ˆl„¡;–&“¡÷‹Q ¯éì1”àBá´mÁ[>õß¼Õ{PU‡Þœr¹ÖŒß0¦é|K­'Ý Œ°Æãq4 Ôëõ¾Ï“†K¡5¡ Fç::Žƒõõd÷ÄŽ€7Ð}Á=p>ü7N_káù¾©P­"W{0M¸Ÿ~Ó‚ÉÂqg4/¥ëÂü¿þ,üX>T«H>ï}po»«í¤Çˆ]Û FWɬ˜kÍÓ Ñ9rjc]0]·w„@FP­ºU:¥æÏ8ÑU#c#÷-Ñz@BAÁBe™ßÁáá)Œbü2ß‘ É4»+ `Uîl’”t°È<áy•5°|b8†2Xãñ8²ÙlÏtßF£b±ˆD"á§G Ñe$+À²,4›÷u¬Ü_ý_Üü/~€S/s鸯D»ƒ“?„ùäëÂ2WœQ½&¶ çSwõLƒç‰çCyõ‹ÚÓ´VJp/úE_ ™”¹Õ<-!†á¥î†aYž‘*?étË8•øš6\PB²ë)˜?ãÈ¿a*°ÿ¼ÝùˆTÊ‚LÆš°9e£ârÄži¬ùüiUßß½²å8Ù`´f2,kˆ"Cu ¾téêõ:.^¼ˆ££#?ÚZ¯×qtt„‹/¢^¯cwwwÑ×Цµ<b º®‹õõ»º÷ÑN%ÿô&à8€åô߸ƒ7kêNd‘ôLì÷šò1Ô—4N£çì°·”.Ž[[‹¾jrV™É8%Çu[e‰U¯w _w*õ‡2J¦\ö‚A§’®{k?GT]g*ð¢uˆãÊgž€óÉŒ¸tÚˆããÐ὜¡ˆ7“!Ú`-<Ë2 Iö—O6ÛJ%éáЗ‡¹—E5¬€eÝßßG±X ]“H$°»»Ùèj^Û¶Q*Ý×ý„€7ж½›}>à‰' «ÃE¬I"‹fÞþð Úœ;]ÇíÞ]!¥{0!‹À²,”ÂrQ76ZÖÚ¢PhÕ׳ªzvH'ŠÒ½¶åL~uKG›sRœ{¿ò;¿ŒÒ[¯!óɯêÿæïÓoždO:ç\ÒÉ 8;Þ¶[V©ë¶…B-ËûI§{øK¤…µªúÆiÐoÔe¢ÊP+Ð2ZetM­VóÓ…u^4ëë­›tpÿ•mk#àŽ zgô»ÿHÞÖ÷sr9o_æÞLÍ8‚í?|6´üáÑÔ~]€™òKEÏæb+Ù‘KëÔë$xpÚV)mgÃ0Z)Ã÷>t \ÿ}(›Ê#*æýæI†Ò1Û~ ]•Ô‘3òLH]ÿaÀy[xJX  _2Ùí˜ë×Ñ—,–¡R‚ƒÄb1躎ÝÝ]èºî«FÃo¼%M}lÛ†ªª(BÒÒ|S>†û¼»‡ú¼\Ž{4Y,ãDX¿ºê—ÝÀ‹ÐtN8èg°–ˬ]#‹¡gÃ%ËZ9ï¡ãxYp­{—i¶î7Šâ­EÖ_,ËBZ¼…Ž®qËŒŸyÖÀµ‘˵fMžn3Ö’bJ2$C¥¶Kû^Mó~:6:ëü5R/û_!QÕð²†BÁ{›afK“h0²ÁÚ‹Z­†E_OJ¶¢GG…zšÐ¥dw†‰þìÏË‚ñ;÷¾ý«û~–Dd';FÈÄŒÜ5Õu‘Rm­èz÷&ì²MHTè™MÐÏò„är^D@×½Œ¡ áP( 4½¬6†a@Ó´V e˜qhY^Dê´ã¤ñOCý{Ï¥-³²ó%²|ä^`šc¤J2匌À@G»ãxÂØ# êþù§ ~êým­Ê{5‚s¯\"›õd[êûé_‰.S3X£J§ñèÕðÜðÓ†º¹;ðñ_üÅ}Ÿ\g+¤'‘%cœù«°m¤Þü´ÿ«®wGX{dà²Pz*9+R;ŒrU«ÝFC*Å ‡³ŠišÈJ‘r/M&ã Èéóò_zú›?€§uîóòÑùóyïmGNX+B†À4ÍÁNö!~ëm? íü³Ú6CU  •J­’Àr¹Õ‡ƒûhtYyƒ50¥€·w~üã¿:¼Bç€ãÀ}â3À ^°èË!d ’ò> εOÂzê+üߥ Šã™HÔék°®@ª‹4þcš/ bŸ¦À¨­áòÝÚ¶ax ~`}¨w}Ê·s¯Ëåc|þç¿@H*¼iviåúƒ¯ކû,é/@ƒ• bZò†7c¸òxËÛØyo蕉£iAÆc–2.´Í  ¢(‘ÖJ$ø%kRQ¼5˜N÷ž•J¢Å<ä»)á3M³Û)ÙÙ]æð°í÷^M“Ä`M§=yä JÌW¾MÓœ O·Öõ=͘t{”q4¾-L­†ummmª‚-#rŠÅ"ŠÅâÔFæ8Ž…¿ÿ÷ÿ@—i7 ®;Rt©ÓH&¤“YÉw?\×ÛèÃZ¼‡=&ÐX%ã0ïé™Kˆ†á¥¥e³žaZ.{¶©åbÞ{¸DÞ½ñ2!ã?:×AG¨´—Át²§Ó4X‰Ç<å;ÔÓ‰m#“i/¹ Ž£ Ž÷êÄq¼×6Ê&KÊ@ƒ5cèŸi"ùóF;;;8:êê|æ™gð±}¬kQuÎWj6{oÈ!ŧÒAoØú ÎsŠ>õzׯ_ÇSO=µÐóE¾àé§ŸF¥RA½^ïù˲z¦Ö¤Ržw9T¹éfHÅR©TpóæÍEŸÆTöð~Œ<¾)¸®·—ì´#E­VÃõë×qëÖ­…žÇ(ò=ÌþÝQÆßûÞO÷”{™ x~Åí7òHQZ =ûoDÙ¿§¹8*³Þ¿VÓZ{ø –ÅXíyÏ!c±¹¹‰oø†oÀ+^ñŠ…|þ8ò=ÌþÝRÉÓG>úÑzëÖV[d§ý*5Àðµ©LŽ²ãØ˜óÚ¿ÏÉ.õ«–ÈR”²ŽL°,XÏySh³ÈTÊs¶ô+k’uAùŽ¢ƒºGrk¥RéJ=Ðñ¨Þ¦à.Ñ'M 1f{H»¤Ê +èé4=”¤?Ó”ïN‚›'²TpjŸ¶¶PxËï/{e–L•YʸÐÓ3,¼6Ã4[§ M”¨,­óï0<…Ý𜒥RKÈ’IXVï4óŽþK]ˆâÏ~˜¯|uMëPųYO(s98Ïÿ’Ð(j6Ûjb× UõÊ0(ßËM$ Öµµ5ìíí¡V«ù #ý>†ÑžÜ7]ÒuCw{Ãðа©2¯’^LK¾G%X»ZýÇÁþ–ƒñ«1 }FȨÌCÆÇ ¯{ › ?dzÖ×[Ý\Éj2ï=<—¬w¦ibccË{P<ï¹à8uøíl0LÎ6ó’o7P4í8@áß}e½£3R>¤Ó°>ø’P‡ŒŒß$ûì°üDrk<Çöö6.^¼ˆD"““@aÄ_ŽÓž&ã8t]‡m£{ø°¢Leǃ•Ê éŴ仓~ —Ú8ÈWÐJ8<¤×‘LŸYÉxÙÏCÌU;‘î“2œžc VŸyÈwÛ²×wñ_žÕÀ=ñ“­YÚÙ,°±h, c;i¬’ ó’ï`tÕ4åƒW»;ž¤(@>l¥¾}6ˆ¤Á x9ü›››þB§î#¼áRÚO;hrMë«ä$“WC¦Ç4仓ž'x™¾ˆŸÎÔ8d0™!³ñ ¶m#Ö4`΃°¥Ñg§ž-f-ßAʇ.°ñ;øÙì¹ÖEá<ö0€D¦É<ä;XÖaÛ@öÏ~Îÿ+Œ\wV#Ë–ÈÐk°É’tŸ k¼4ÍÑ6±Xl¢¢s×m7JÇí() É0ÐSI†eRùî¤gÄ ÞÍ M6¹û“90mÒ7%x†.w©OÍf½eÄF{g—YÊw†ú[ÞíãïÞº5 ªþ‹EdÕ˜µ|K ìßû,´ü\à+^óŸ·¬¢¿0sål3Ð`=wî¶··»Ÿ¥7qZtÎcUU‡7BU­ô›!H¥h´’Åàö¢×¦Ã³h•,9®ë¶œ¦ÙÞhÀqfªÙè:Ó~ÉüH&ÒÇ¿øUw÷tH²ŒHÉ4}íš_ˆªëí}2f8’! Vio½ŒõwÛ¶}o|:íé8Ãìý£Ÿ¼ŸEÑ/Â:ç,IBfJ[½¶tJM§½ »G½I†J¬ù&óÄq·þ Ô/}.ÊÇÇ(½ýí¼Æ^Áô ωBȲÌx´m@¿q¤Š¼í[ V™ÒÁ}—D²Kð´›mù0z„\§Ô‹‰™ãô°J]—2LV ¿Y‡axZM6ÛÚçÜ!8—óF^2‹žÌÃÒ_øë€®·)øâ—BÊ=Y‚NGóài¤Þú9ÿX*嬒,ò ¬¸ÁÌw[VÛ¼msû4óóÈrÐË!3JJ;!Ë€eYžÁjYž6“Jyi3£ Í€ëz‘+ÀKGcö ™7¦ ¤>ñSøåÏÿü¶ì™à¼JMó"ÿ„,ÁŒ°ã·~wÛ¾-ÑÔQúÇÕgè¦KµZ ØÞÞF<ï9>Ã^Àü»^tž¢(ôº¢À÷Ñè™NI¢N0å½ûØé  PhMˆ'dIq]·%ëAM]ÜòSªÑN&½¨*#«dºÿ3PþW¿ýz›Áªª­å“,#–eµº¼+J—G5«¤“¡"¬–eáâÅ‹¨ÕjX[[óßÝÝÅ¥K—H$°¶¶†«W¯.úz|NGMúضÝfd·Õ{ôiVcYž—³³Å6!Q¢_Ê»t3…버,==ç çóSsÆäržþDc€, ÓÒ=(•Z§hšç$d¹Q¼,–[Q¨®v†2X÷öö ë:yä‘¶×ñx›››ØßßÇùóçñðÃ/úz| £½”©ßŒÊ~E L#Ë@0å= E‹ÈJ6? ŽÓJ9“ôß­-ï÷|žNJ²X4í´VõtÏê/šæ9ÝéP!ˈišÐu}èæ§„C¬•JF=ôPßç=ôÐC888@½^_ô5ðAÐÙ>pþjWN*5õ>„L0·¬@y¶ãÐ`%KOg´ilÛKù•å (žÀZ@Äa"Ê}'ìK@–ÉxL§é$Ã3Ð`­Õj¡Ãƒ% Xã'''‹¾&žÁ*ʈeY½£«ÀÀ"UÇé›5Lȱm;Ô`•&ªh¬’¥Ç¯_ÍåÆn.`Û^$õðÞ}M:Ë™8•¬Óp:’³Ç@ƒumm ·nÝêz|ñx|Ñçß“`DÔ¯ïëÑ Ž3°é½™$Êôªa-•N•r¿ó!Ë‹_¿jYc9`‚Æ*÷tEdæ/\p*÷d¥pO£?¹œ{»ÈôE24 Öx<ŽF£J¥Ò÷yr<u]$AÛÔ¶m|õg?Ûß#ßG™§®O–_n™LVÛ¶±u×]cY›® d24VIôI§þø~€Æ*Y),ËÂ?ù'÷òí}ÿ‰z š¡ Öx<Žb±ˆF£úœF£b±ˆD"™¨kg„õ ï¼Ó[¦ÙiÍfûj0L&Q¦mÌÇ)ŽÓj € —ÈJ`Yî»qc,‹Ó¶½~4VI”QÕSƒÕqðsŸøÒì¬DVÛ¶ñÉOn"ý–º·3D†d¨.Á—.]B½^ÇÅ‹qpp€J¥âÿ‹E¼õ­oE½^ÇîîÇ'¨”8Žƒ×4ÞƒÁó€þÙTpH”éÙx#ÚóªJA&Kï˜±í±ŠOuÝóMeÄÙþ¿ßó˜ŽÓsæ=!ˈiš¸~ýËzþ¯P'!#ñìažÇqåÊ X,vßÜÜÄöövWc¦EѵmÏSÕ–Q*F+=—dp:RÝ]×+ñ+•RÖÉ’ã;fLsèlÇñœ7ŠÂn”$zH&ŒÌ…·mO^óžxþó‘ºpaѧHÈÔpwßýUøÌgõ7ÿo¶e'#1”Á x]€/]º„ÝÝ]Ôj5ÿñx<™ºU¡3ûQÓ4ïÎ ^ùtÚ›iJ •ŽP./úŠéã8muN…íS²zX–åõ"1ºªi\$º£þ–Õj’÷¿þú¯™LV ˲ðìg+R/øŸÀs–)‘‘Ú`ÖÖÖH$}Þ;Ô²,¯{j°O¼ªzw‰ ÏãpáåÅíH)0Í–ÇžUÁ¶mäÖ×û¬®ë9llÛs4úõ€„DUm©ŽÓÊŒùëoÿI¼÷9ÏÁ7S/!+Ä'ã7 ¿ÿ>¤¾í9ÀÿÅè*¡jX— ýéº.^ñüçw¤é´g¬nmy­# YR‚V™»Ê>dÕp/zÑ‹º V×õúè%“ž`V YÄ.©Áލޅz½ŽW~Çw,úô™*¿øþ÷ãÿ{õŸBýé·SI!#3r„uдV-·mÛÐï¾xÞóŸX­² 0Yj‚5¬ª€­ˆãÈ’â8Ž—)RˆšÉx[y©ÄD²<˜f+X2\€aà‡>ûYü$SÈ aÛ6îþ{ÿ ®ª¦*‡•4Xƒ8Ž¥ßØš‚ ‰:j@K×ÍÌid@ÞýÂ(B–˲B»¥Êxavÿ%ËFg³k±OM3…ç+Jר2B–™‡þ®^ý1¸.Un2+™$lä!«‚mۈž™Ìif{*åý§PhEÙ6ïd©él,&ôºyL3Ühš&R©Ô¢O‰q]¯Tþò/úÐǘCÆf¥ V?ŒÅ4M|ù—¹Ÿ ]÷ øÇ3\%ºJ§ YVlû_ÿ+tÖ0!ˈdtúÇééœ!dÙ0ÍSÕ£PÀ§Þÿ›ÔÇÉD¬tJp¯42BVÛ¶Q*¥Û½–ŠÒ1„•%&“Á_>ùd[Фax¾¦“e¤WtÕ0 ޲!+ƒa‡ÿ÷M<ý¦ŸÀkßúÖEŸYrV:ÂjÛ¶ç©4ŒEŸ !SÇu]¼ï}ž×Ò¶}:„LÛÆ'}Ó›ÚÖuΜ'ËKgý*r9À0˜LVË:Ûô¿€ê«_ͬ21+m°Z–]QÚg°²"†W¿ú†§ý0?’¬"†¾ä%~*™axuQa锄, mU§½~æ¤R)6["+iž6+ðƒõ: V21+k°úõ«R,BÈŠñó?¿†7½éÓ½óËYv, G/y âñ· ™¤ï‘¬mY¿…N㇊E¦“•@ú=êVŸJ&ñœ×¾–Ž21‘7XkµêõúȯóëWm›+‰,ãÊ7üÉŸÜïÿþ{=ƒ•id$¢Œ+ãîzïþ{áðð>ü›ó¥H§½4`ê=$JL²‡Ã²Ç •J±) ‰ãÈ·ëÙïø$`šøå{ïet•L…È6]ª×ëÈf³¨Õj]×Q!íÑq¼é+¿ø‘a9&•ïŸú©Oà¥/ý#(Ƈ¼è*µx1&‘qÛr?üeøÜK>Š7¼!†ÿçÿ¡ˆ“h1é×õ:¹—Ë0¶¶P.—}I„øL"ßšh… ›EÑ0P¢N¦@d#¬{{{ˆÅb°mW¯^E­VC±Xúõ–eáu>Ê‘$’L*߇‡7ðÆ/ú /ºÊA”$‚L"ãšâàW^ñNþö{ñ®w§±J"Ǥ{8¶¶€l9À®ëL™$‘b"ù¶,Àu‘;ÑÄidDÒ`­×ë¨T*ØÞÞ¬­­asssh¤ëºÐ]×sÓS™'cRù€O}¼†Ÿzò?{òME‡DŒ‰eܶñðË_Ž,çÖ2±|çr€ªÂÑu˜¦I9'‘bbùÖ4üî·;,ËBž:8™‘4XONNñxÜ,Gÿدü Þ~ãÆÒ§-ú¦Šl‚gIå~øY—pû… KÝliåaÕÖì¸L*㎦¡à8Kß„fÕäa×ì8L¼‡k~ùý#$“Iäóù¥Œ®®¢,¬Úz—IåÛðíïxÇÒ§¯š<,ûš¤ÁÚoQ4¯ÿªöÏp—i.}³%kÅZbžœœàÚµk‹>…3©|À[‹Å¥ÏXEyXµ5;.“ʸmÛ+á™_5yXÅ5;“ÊwζñS?÷s(—ËK;wueaÕÖë¸L*ß®ë"ŸÏ/}*ðªÉò¯ÙH6]ê· nݺ…µµµ®Çÿøÿ¿ð ¿€_ú¥_½÷Þë=¸äÞ‘Ç;;;‹>©ñôÓOãé§Ÿö‹øÅ“O>‰¿ú«¿Â _øBìîîÎýóÇ‘oÀk$ö†7¼wÝu^úÒ—.½|GE¦ITÖìõë×ñ™Ï|faŸ?­=üêÕ« »†iy˜QY³?þ8^õªW-äóÇ‘ïàþý¼ç=¯yÍkðþÃXÈùOƒ¨ÈÂ4‰Êz•ýû×~í×ðæ7¿yîŸÏýÛ#*ò0-¢²fEuÿޤÁLCè$‹…>þßùøÎïüÎEŸ:!G¾à×ý×}ê„ ÷p²ÊŒ#ßܿɲÀý›D‘H¦Ÿ;w@{ZB½^ï«Ì²,P¾ÉªC'« 囬2”oE"i°Æb1$‰¶‚g˲L&}j„L 囬:”q²ÊP¾É*Cù&Qä¶f³Ù\ôI„Q«Õ°³³ƒX,†F£µµ5ìïï÷¬ï#d™ |“U‡2NVÊ7Ye(ß$jDÖ`¼Âo)N$‹>B¦ 囬:”q²ÊP¾É*Cù&Q"Ò+!„B!„³K$kX !„B!„g½ãïxÇ¢ObÕ©T*¸í¶Ûzæþ×j5|îsŸ =ÞïØ0ÇgA£Ñ€ã8ø‚/ø‚±Î)Š×DÆgùžÆñYÐOÆ—ñzÈdô“ñe”îáD8kû÷ sŠâõÉàþýkŠ&™ïz×»š¯ýë›÷Ýw_ó¾ûîk>øàƒÍ›7oúÇONNšo{ÛÛüãoûÛ‡:6ÌñYpóæÍæÛßþvÿ3ßö¶·5{챩ó"®‰ŒÏ$ò=ã³ ŸŒ/ãõÉè'ãË(ÜÉpÖöïAçÅë!“Áý;ú×4 L žFÅb»»»°mW¯^õööö‹ÅüãµZÍ?ÞïØ0ÇgA±XD½^ÇÕ«WaÛ6b±†>§(^Iå{ÇgA?_Æë!ã3HÆ—Q¸‡àlî߃Î)Š×CƇû÷r\ÓH,Úb^U}ôÑæ}÷Ý×öØåË—›>ø`³Ùô<÷Ýw_›wägög›÷ßßcƒ^;+nÞ¼Ùõ™'''ÍË—/uNQ¼&2>“È÷4ŽÏ‚~2¾Œ×C&£ŸŒ/£ÖÖÖúôÚY!Ÿ)^ªQ®gÇI´˜D¾§q|ô“ñe¼2ýd|å{8ÎÚþ=蜢x=d2¸GÿšFëŒ ¶L«“h4¾¨óx¿cß“žS¯‰ŒÏ$ò=ã³`–k’ò½|ô“ñe”îáD8kû÷ ãQ¼2Ü¿£MÃBƒ•B!„BH$a +!„B!„HBƒ•B!„BH$¡ÁJ!„B!$’Ð`%„B!„Ih°B!„B‰$4X !„B!„D¬„B!„B" VB!„B!‘„+!„B!„HBƒ•B!„BH$¡ÁJ!„B!$’Ð`%„B!„Ih°B!„B‰$4X !„B!„D¬„B!„B" VBȰ, ®ë.ú4™;Ó”}×uaYÖ¢/‰B™ 4X ! #™L¶íEŸ!sgš²oÛ6’Éä¢/‰œa Àã8‹> Bæå}þÐ`%„B!ccš&xrf ¼ÏŸg/úˆGÐ[“N§¡ªj×1UU¡ë:,ËB:ॕI*X*•‚¦iþër¹²Ù, ÀëºÐ4 ©TÊ?EQÍfÇ~>!ÃÒO¾ P(ÀuÝP›–ŒS¾É"˜¥ìçóy ÜvÛmm¯s]…B¡ë5„LJ˜<Ëc¦it]o“OMÓüǸ_“eb\y×4Í—]EQN§¡( Êö¸0Â2™ …Àqlllø $—ËùÇLÓÄÖÖ–¿H …¶¶¶x ÊÆÆ ÃðßWŽ»® ×u±µµÕ–†V(ËåÆ~>!ÃÐO¾å¸Ôòõ’I`r§|“y3kÙÏd20MO<ñ„ÿ¸ëºH&“¾"DÈ´$ÏA‚ò)Ïá~M–‰qåýCúÖ××}g£išm%”í1i’…R­V›šÇÇÇþcº®7³Ùlóøø¸ë˜ªªM]×ýcÕjÕ?V*•šŠ¢ø¿h–J%ÿwMÓšétÚÿ=›Í6u]ûù„ ¢Ÿ|7›žÌÉÿ›MO†EƦ-ã”o2Oæ!ûòúr¹ÜмqãF—\2 ɳ®ëÍr¹ìë”oyŒû5Y&‘wÙ…7nøz»<—²=:L ^0¦iB×õ¶4±r¹ Àó²tK¥R°m–eAUÕ¶îò»mÛ¾g=øZEQü”„^Œú|BúÑO¾]×ýÿŸ7 §|“y1Ù¾h5rÊçó‹¾|²b #ÏtÊ'Àýš,“È»¼&“É •JA×õ®×R¶G‡k„é7òÀq¿N)HØ ‚e„2NÎ*ãÊ¾Ô f2/ú2!äÌ¡ª*Êå²_Æçº.Òé4J¥Ò¢Om©¡Á: S˲üÂë^F«¦iP¥ÍkÓé}'$ ô’oiÖ Ê8Yvæ-û¥R ®ëÂ4M¿ !Ób\y&dWÞE/•J(•JþØ1MÓ¸V&€M—L:öS|oH#Ž`ú¯“¦º®·ý´Š¾ ‰ ýä{”q²Ì,JöEñ»Urì™ÃÈó0²MÈ20‰¼#«€qeÊïä0º`TUE©TB2™„®ë¾gFZ`wEF”’\.ç+5Žã ̱'džô“ïAPÆÉ2³HÙO¥RH¥RÈd2\/d* ’gEQËåüôGB–™Iä=NÃ4M¬¯¯CÓ4?3&•J-ú²–šÛšÍfsÑ'AY%zÉsP_éœ5LȲ2‰¼KtVQ–1M¬Æq¬¯¯£Z­BÓ48Žƒd2‰l6K&!„B!dåaJp„ ¦$Hp:¦±J!„B90ÂJ!„B!$’°K0!„B!„H²2)Á¦iâ¿þ×ÿŠ{î¹gѧ25®_¿Ž{ï½wѧ15nÞ¼‰F£‰¿ÑÍ›7ñœç<‹>•¡¹ÿþû#ñÝM‹(ÉôˆÒš½~ý:~ë·~kѧ14ÜãO”ÖìÍ›7¡( ~ê§~jѧ2Ü¿£O”Öëõë×ñŸÿóF<_ô© ÷ïè¥5;Îþ½2ë~áâo|#vww}*Scggûûû‹>©Q©TpíÚµHüä\–‰{òq¢´fwvv} #Á=<úDiÍ.ÛÎý;úDi½îìì,± pÿ^¢´fÇÙ¿WÆ`]EVi¡@"‘@"‘Xôiˆ°Šò°jk–LƪÉÃ*®Y2«( «¶^Éd¬š<,ûše +!„B!„HBƒ•B!„BH$¡ÁJ!„B!$’Ð`%„B!„Ih°B!„B‰$4X !„B!„D¬„B!„B" VB!„B!‘„+!„B!„HBƒ•B!„BH$¡ÁJ!„B!$’,Ô`­T*¨×ë=×jµ¾Ç ‰2”o²êPÆÉªBÙ&«eœ, 1XŽŽðµ_ûµØÙÙÁ… °³³ƒF£á¯×ë¸xñ".^¼ˆ . ›Í.ú{Z)\×ÅÆÆ2™ÌDïq×]wÁ0Œ¹œ³iš¸ë®»Éd`YÀq d28Ž3—óÊ÷|±, ®ë¶=fÛ6r¹\ß×9ŽÓõº ®ë¶í¡>ß0  …¶÷s™L¹\®ïç,#”q²ªP¶ÉªC'ËÈÜ ÖF£b±ˆÝÝ]ض«W¯ú {{{ˆÅbþñZ­ÖvœLF.—ƒ®ëÐe´Ú¶ ˲`š& …,Ë‚eY]a&“A:†am†¼.ø|˲°µµ…d2‰\.‡B¡0ô¹º®ë¿¦Z­"•J¡P(`}}[[[MÓL&}c¶—‘aš¦ÿ¼w¾óxê©§¦þÝR¾§Ã0žã8H&“( H&“þklÛÆÖÖ–o0†½.“É`kk [[[ØØØÀúúºï‘÷yçŽamŸ‘Éd°¾¾Ó4}ãwcc××d2 MÓÉd¦i¶Gð=r¹ÜPƱ`šæÜœEPÆÉªBÙ&«eœ,+Ïž÷Öj54 lnnÖÖÖH$P«ÕxžJ¥‚+W®øÇ777qtt„ÝÝÝE_sE"7‡‡‡mÛ¶ Û¶‘J¥ (JÛ㢠+ ÐuétÚ7.óù<ÏðÌd2P¦iBUÕ¶÷%Þ4MBÓ4˜¦ ×u‘Ïç}ƒ2™LÂqèºEQ|cÒu]ÿ³UU…ã80M™L¥R)ôš%R%צiªÕ*@UUߨ"Ƴ¬bX¤Óißȵm¥R ŽãàÝï~7žy晩ÿÍ(ß“#ò¡išÿ÷ ⺮ïLÉf³H¥R0 Éd‡‡‡¾léºîËw6›õ/®ë"›Í¶ÉŸº®#•JakkË—wþkÅ0VUétºK†³Ù¬/¿ÕjÕ—aÉ:kEA:F>Ÿ÷="·Aãt]‡ªªþ:ÕuÝ7pÓé´ÿ½är98ŽUUñáx&Ê8YU(ÛdÕ¡Œ“eeîk"‘èŠ$œœœàÎ;ïôÿñxÜ?ÇW&Þq†áŒ½Èår°, ªª¢P(´¥dlmm!•J!™L¶)ÄŠ¢@Ó4_‰–HS>Ÿ‡eYX__‡¢(¾ñ¥R …BÁö1T*$‰E^V_ … Ãð#Žˆá¦ªªo`mll NCQär9¤R)_)CUwIaÌçóÈd2~”¨3Jd˜úQè“Éd蹇)óa×'”J%?}R6Ïq Õ^¨ªŠ|>ße@Ôëu\¿~}&)ÁA¦)ßðôÓO£R©àܹsˆÅb3=÷Y!N‘GMÓËå i²Ù¬Ùìt¾Hä\UU‡¾w:ö Û ƒœCÏåùãÒomô¢sm(Š‚r¹ìG}ƒ†úwÞé+ ³ä,îág•N'Ë"©Õj¸~ý:nݺ5³ÏàþME¥RÁÍ›7ÊÔ¤pÿ&‹@tðQ÷ï…v ~à°½½ xøá‡ ­ð»“~÷Ì3Ïà‰'ž˜IÔlZ8Ž˲P*•ºêÏLÓôëá$]Q Ñl6ë§úÉqAÒ…|>t:Ý•Ò8 $ ;­|1Èóù<ÊåòTÕ~œœœÌÅ`¦|žÂsíÚ5ÿUzÕcбzxx膩T Õjªªbcc£gT¢£ƒ¢QQ¨ç…­ëçÚµk}emZœµ=ü¬bÛ6666üÒA jh$“Ét5ðs]·­f<ø¾[[[¸|ù2>øÁÎÔ`=«û7Y’Q$=6f)ß÷o²DY¾›cpùòåæÛÞö¶æ}÷Ý×¼|ùró]ïzWóòåËã¼U³Ùl6Ëåró¾ûîk6›Íæ£>êÿ_{¬“G}t¢s˜Ùl¶Y*•šÍf³©iZóÆÍf³Ù¬V«MUU›ÇÇÇ=_«iZSUÕf¹\^ôe¬ó”—iÈw³Ùl>øàƒóÿ¢úpãÆ.™ÍçóM]×›ªªúòÝl6›¥R©©ªj³Z­.ú´Ï ó”—³²‡/+år9tíåóù¶uÚl6›ÇÇÇmϽqãFSÓ´f¹\n6UUm–J¥f>Ÿo¦R©¦®ë]ï«iZSÓ´f6›õß¿\.7³Ù¬ÿÞò¾Ùl¶y||ÜL§ÓM]×›©Tª©ªj3•J5S©T×ûæóùf6›mÞ{ï½Íïû¾ï›Ëw·Šû7YÇÇÇÍR©ä¯7nøò^*•šÙl¶¹¾¾>·óáþMæÍ8ò2rJp±XÄÑÑ677}OÌÚÚŠÅ"jµö÷÷¾¾óyÁÔµsçÎðBÆ’6üÿ2Q(J¥Újï¤~T×u¿6U¢Ný¢CR‡:¯($³$ßÒ‰W"ù¶mÃ0 T«U¿#s¹\ö³úÕH“åá,ÉxT˜$×u]¿[vp J&„iš(•J~C½\.ç–”–Hº=à¥ñKÙJ6›õ_#©ôRs. È666ÀoÈì"¬Ý.•J~f†dYlmmù÷ÉàûÀ7~ã7N=šCÙ^}‚ML¤S†á7õ“Þý>O²ä¤wƒô!qétº-{mV2”q$Øàt¤IX9Ð.óÁÌ»›7oâõ¯ýHŸ5’ÁZ¯×qpp€ýýý¶®bº®#‹áâÅ‹¨ÕjmÅÚœ?mϳ,Ë_ ±X ‰D¢­#™tç\&d4Œ4Xr]·­«o6›ÅÆÆ†¿Q Jݶé Y,gE¾E©Íçó~3.é$-Ýoà®»îB6›õÓ¿ÉòsVd<*H>×uýÎÙ½îâ ¦ÎKã=×u±µµ…r¹ìwT¯V«þØ1é<].—¡ª*,Ëò›•߯³˜¦iØØØð›Z–å7DëU.)Ã÷½Îߥע(þûÎÊöê #ú$h ÚE¹ZΜT*å;]eüX*•êÙkhu~¿qã Ãð{NÃ0`FÛz-•JmïÖœr–PÆÏÁ²Š #PdZ\ÊÄ‘|>ïï³2;^Ó4hš]×Ûöf¹Ï†á÷ Ž™;GE¦R)ßÙ(Ç*•ÊÈÇ‘ V©½+¨ŽÇãˆÇã½B‰D›››¸xñ"‰NNNpëÖ­6oÏîî.vvvP©Tü"ïx`âéQ(Ïçý?¤eYmÍbEA*•‚ã8ʼBœù6MÓWvøÍ¸:7µ^MÈrsd|ˆA)NyL2s‚ÊDXWi©WUÕšš¦éßk€V ¨mÛmÙ>årÙ ëz[Gù~”J%Ÿ÷ ÚA™Eó¾?RÆ—a'¡¦imr亮﬇£ŒÄK&“¾G5J&ŒôÍ‘ŒOqúHVŒ¼ðQÔ~Ÿq¸­Ùl6‡}r­VÃÅ‹qõêU¬­­aggñx»»»h4øÚ¯ýZ?ú:ˆz½Þ×n4~w˜÷k= s¢dóëœó8ÍHd2f-/Ó–oÀëè7(å~–È,RÓ4ý( ‰.³–—UÞÃçŒ(RUÕÏ\àÏæ F)幩TÊwvJZnpVv.—ó›rfIñöýH¢¶sÃgÅ,åe÷ïUB¦-Èx¯ÎÌÉΨ0–ÃÃ0 ¿¼KÞ_ …°ì`FÄ$/¹Ÿ-DflÛö£–€çdìlt'ÍWE¾%í\ž+sâû}Vg–޼¾Ÿ¼†¯—qäe¤«DQwvvpéÒ%ÿñz½ŽË—/û©Ã‹ÅúæÄË0ã¨#^4¾®P(t¥.ÑX=[,«|çr¹¶ÍPä[68MÓh¬Ë+ãóf³R P‰šJz­®ë¾s(ˆ¡238ø˜¬KQ®Ãê“Â"LÓ`˜YÂËe;:Èt‘mé&Œ\Jæ(ÓÁ²`*5l2¾¬3½WF¶t"å%t~’¨"é°;é{ɨ$EQ ëúTÞ—i#%âhL§Óp]…B¦iú ¤éªP*•à83_&`äÖµµ5X–…ÍÍÍEŸûÜ‘öÏ„¬"l FÈ`\×…ëº]Æd2™ô^ˆ2#ëI²o2™ŒŸ¹ 5J½ê‰V¥”¬AÅ\:Žzßæ2–eù#޲Ù,¦$ÒH'v‘Ué®+¥€Që½jŒd°®­­awwÅbõz=ô9«Ü!lµ„DÛ¶©$2itù"J÷ññ±ŸÒØ©|—J%är9lllàðð™L†ó‰ÉR‘ÉdຮßyÚu]lll„vËí…D¨dä#©$ÊH&Ö¼Èk©TòË5=#×°îííB¯ªÁ*õ}„¬*"„„“Éd ëº’õ"a€þe!ù|¦ibccƒÍùÈÒ )î2£Q΢£dçär9èº>’‘Kȼ‘ŒIñ•ÑI{6-ócdƒ58ö,aÛ6ÓUÈÊÂúUBúcÇA¹\†a0 ÃWºÅó> Q¢Gž,¢¸çþÑ4ÍŸÏ(È `…&È\afª‘(#s~K¥õ¢1²Á GGG°, •J€7TX×õ•®k Î#dÕ`wkBz#ã $ 8•Jù©Á²vFY?\k$ª†á˧È}?Å=•Jùu}òzÇq i …‚?ŽFRˆ™O¢ŠŒœQUu¤îÔd>Œl°‹E`ssÛÛÛ€F£½½=Ôj5\ºtiÑ×4dµ¤y±¾¬Žã´Eˆ:Ç5BZH7_Q`$Ò4Mfß• 82h°–Ëå¾9æº.EA¡PøB8c¤s¯ªª0M“#g"ÌHk½^ÇÁÁ …B× Z×uììì`{{±XlÑ×5®ëÂ4M˜¦ ]ס( ëûÈJ!Ö“É$Ù!˜È\½Î4ÆT*Ã0`Ûv[&B– Ã0P(ÆVÖu]÷çNJ3%B¢J.—ƒišÈf³~ã$éTͨjtÉ`=99Þ†?‘H ãäädé Ö`B¡À.vd¥p–eáøø¹\Éd’ !=Èår¡ bt]÷›rPÉ!ËŠmÛ0 c¢ÈT*å;A™òK¢L&“€6y§~¿ŒUÃÚh4°¶¶ÖõX¯Q7ˆa8<<„¢(~z²*Hz#àu-5 cѧDH$é7+ðæ«RÙ!ËŠëºØÚÚòõq‘ÆKì|M¢L.—6ýZRF2X‰b±r¹.]ºäGRëõ:._¾ì?g™ 泞BÂyydUèjpÃfm6!ݸ®Û3º*°î›,3Édù|~*N—|>ÏZnY ÀeY,ßXbFްJtæÂ… mÇb1ìïï/úz&Æ0Œ¶Žt:ͦdeFW !™LÆOg”H“Ì‹äÞOV ™«ªëúÔÌÐñI¢ŠŒ!cài¹Ù`Çãxä‘GP©TpíÚ5Àùóç—>²*X–Õ%ÔL «BXóBÎ2’uÍf‘L&Q.—ýÔ±~ÑUB–×u‘L&¡ë:囬Ò­Z«ì5°ÜŒUÃZ¯×±¶¶†ÝÝ]@¥RA½^_‰fKl AVÎZ%¤Ã0ÍfýÑúú:R©;dåc5N3"JV’ ð'|HŠzýòóy£¾àèè.\@±Xô{øá‡qáÂ-úz&‚©¿d•¡ÁJH;2ÂL”÷t:ããc«d%‘‘„4VÉ*bt]Çññ±¯ËÓX]Fа6 ‹ElooûÑUØßßÇÁÁöööüÆLˈ¤…²ŠØ¶ÍØ„±eA¨ÜUDRßYÇGV•B¡àËw*•¢¾³bŒa­Õjh4mƪ°½½X,æÏj]6\×@e…¬.Ì ¤:)ÉY!—Ë!›ÍRÇ!+‰DW™E¶ºŒUÃÚ‹[·n-úzÆÆ²,*ó„rF( ìY@ΖeÁu]FœÈÊŒ®’Õd¤«¤ûîíí¡Ñhø7 ìííðº/#¶msOž¬4aCV:Ï Öz½ŽF£Ñ•ê«ëúÊÔ|2]rõ0 @Q€`ÉŽešæýûßþÛ«ñþÁ‡}šsƒVBZ{=kùȪ³µµEc•¬,®ëÒùxƪ†õàà/^D±Xô£ª« ÖÕÁq¼uÈåÚe2€ëzFì½÷>gžyî¢Ow.¸®ËÚŽ¨âºžw…ÌÎ"&gÛ¶€Æ*YYd¦0g‡k,C¡PÀ•+WÇqtt„‹/boo–eMôáµZ­¯\«ÕP¯×gþ%pÜÇâ±ín½Ýu ï§™Œwü®»€dØÚòWU XÒ`ž+ºê7|Ó¸çž'gzMQ‘ï3ïÙÚò,Šär-OÊ°í©½ÕPDEƇ…{=–e“í †aÐX%YV·m–e±‘Øc¤Ö`°eY¨T*888@<G"‘Z¨ÕjÈf³þB£XÒŽëõ:²Ù¬¿t]G¡P˜Ù—à8½îÓÂu½0çˆR&tî=É$N{?€÷¶†d³^º¯axU«áïü“ §¬ey/ž!Q“ï3캞7­ë7MO˜ÛlÇ“Çl¶%Øbÿ§÷!ck¨>vût®·Q“ñ¡¿Ÿ³¼ÈP,«l ®ë²,”J¥EŸ ‰(Ë.ãìz}6i¬M]×qéÒ%\¹r›››¨Õj¸xñâP)Ã;;;H$°mW¯^E"‘hk³··‡X,æ¯Õj(‹3ùæ65B‹}f¸®gef2#¿ôðЋ€:N+è¤ë-chÙòUÚ¶÷º~°¾ˆ®*ÊXç7 Q’oï{šƒ’nY­|ì(aší…Ìãâº^¤Ö0¼÷›Æz.<#U Ö úZÅ‘ƒLéÿt×Dî»>3Ýﱃ¨Éx¹\NàË£c’ Ã2Èv? …£«¤/Ë,ã¹\n¥zèáÉ`­T*]¿Kjðùóçý´áAïÑh4°»» X[[Ãöö6êõºŸ~P©T°½½íßÜÜœYËê¹Ô4ÙvwAå$DÑ0c5yž4–åéý¹œ÷I_”?ü«(ÝWÀ{L/•KÓi@SÝVðJÓMÃ+ÞùΙ| Q“o`NŠz¡ÍZLËò L×õþ?.Šây=ÊeÏÀœÔ@—èj:í½w6šË[x¨ãmï…ó£?ú6²ìóô»/—‘ÿ®Ãú¯Ãññ}3ùJ£(ãa†Ó4ýß]]&]ÇXÙî‡iš4XIO–YÆMÓ„eYœxpFÊ`­Õj¸pávvvüÇ,ËÂÎÎ*• Êå2vvvptt4ð½âñx×¼Ö““ÞÂÿ ßx<>³—¾ûÝxî3ÏLý«ˆš|;Ž3%Ýq¢W'LžFd=(ÛÙl{”U ®Å3U…kÙþS=Ýî}9M pËUd3Ÿ‚a*È)%ÿýÅVVà8•CJµ=Î鹕¿æ‡Q«¼~&_kÔd< qDÒ`]b £Õ¤`c£Õ¤ P’I¼z)Ë Ûý¿2©TŠ#>HO–UÆs¹ …GØœa†2X³Ù,âñ8®\¹â?&µ«W®\Á#<‚ÝÝÝ¡RÖÖÖH$üßëõ:ŠÅ"677‹Åú.ŠF£ÑóØ'?ùIض=rÚÂ\”Çñ”Ýi¬™LK1íõYÓDrj××½ôÊ0 …îü]xz{á ç¿8ïbK¥å…b‡¼¯ÿ=ϧ×u ]¯¯|ä#¸úš×àå<2Ýï ³“oxòÉ'Q,»2úaYÖ|24mº²ç8Ýi·R=,¦ÙS>­s”õ´Å-Êu2éu[_÷ä5ðÙ¶ $S/‚m·|P¾8ËsËeäko…²ýVdëëa¾èÿçSwÁü‰$“·K§»ö„+_wþÁWÿ›éý=Dmöm¤R)¨ªê§³áÒ °,ïgXgÕ(÷@™KV­z?å²ÿsôàƒø‰{ïÅÇ>ö±©^NÔöïQa:ðjP,ñøãÏÄH\†ý»“­ÓnšÕj•e+@¥RÁ»ßýî‘÷ïk¥RA½^Ç¥K—|K£Ñ@­VÃææ¦ï¥ÙÜÜD£Ñz3n4(‹¸pá‰.]ºä?Þ‹[·nõS*µÄóðÐ{ß\°Ó%¸Ù< KmëÿyØ8|;Œßÿ2T«±¹Ÿ?¾Íƒ> ¢²‡‡!ŽH]×aœÊ‘ã8ỗŒZ’èf'¶í9aÄËbYžðÊc·ÝÖ½Î,Ë;.Ï+¼÷9–†f?¤R=ïuñx÷Þ{/î¼óΙ|QÙ¿GAºÁS¡_~dÿž•|ÑÞ¿ƒ8ŽÇqØdi…8wîÜXû÷À.ÁµZ ‰D¢Mù‘q6AExå¨V«aookkk]u¯ýj`c±XÏc·ß~;^ñŠW´yŽ1·tI`:]J3™öY-¹\{¡§¦yÞÖVûóÂÈåï}'šæ)7r£–È—a„~±X ÷Þ{ï@ø¸ÌB¾OáE¾½¯bõ©ÔtŒUÃh«€÷w vøËnkË3 ûâ¼*oÒ,©—\I¦€ªzJt¹ì-ˆ§‡mKïŽE4Í1£ª€zºWÊÛu.Mkù„ O„;ïÏbóãH$xá _8ùߤQÙÃ{!]R]×ÅÆÆ›t K0³%• ÏæÑ4Ï 3 ª ÷öS¯‚®¹@¡ã_¼ö_û™ï‚ë<Ú–·Vt½%㲆$«_ˆÇãh43Ùã´GÙ¬²ÏÊéõý;ˆišœµºbŒ«ƒ4X×ÖÖºÞ´V«!½˜²Ùl›G'ˆxëõº¿8‚ÿŸ&s5XÁ-mû¢8Ã4[3^„tÚ¯õUm…¦ hLÇS®óyï# ÀL—‘J¹L«ü¯Z”À 1›ý®¶6Œ€1Š!£(§–rvxã>•j p *Pù¼çűs$*ò-D"ª$û~†f¡ÐÞ°K×}õÑ4OFÄ ìõ^bÜXd¿Ó" >_ÚUKӦާIpI™f+ +K0—kêêº÷½;È·›+j2$ØdLQhšÓ4ÏNäÉu[ã—€–Pöº~q “Ù2$¹\+¢\ ªÈø©—‰ h@JJãÔ¶Û׈¤Ì«j+éÂ4½SýøÇ¿ßöm1õ¯/Ê²Ý ‰BÑ)3gÆã×󽀙ݖKÆMÓŒDÃ'²x¬ñxÜ.,^M˲°¹¹Ùö\ÖÐëzHs¯€IDATÑÒóp]@ôê ÜKê¢ô@ôvÒ?fˆ’Œ‡! —oÏEÇy3ÚÅ´² ‚BÖ«[U»Òu= iß±¢ åtL¥-†ñÌE¯ÒC¹©Àñ`„SÓ<N6ë½Nú-+K,«½cÙ¾ò¨Ëv®ë¶m”ú5c<+ÈÜ<éÒ é÷¡ªž~%÷“`·ûà†-uQÒ ^×áüÏc뿆ìWykFU[kbà^/5ÜrOÓ4 TB.[Þ¯¯yÍl¾¢e’qÓ4™5x²*°®÷÷|[–'§ƒ„PÊðdˆsTj–:ß_aKï$-³Rç$k ð^óß8ú÷Ђ›7o6äG~¤yÿý÷7ßö¶·5ßõ®wùÇ._¾Ü¼ï¾ûš>ø`óæÍ›Ã¼ÝPܼy³ùè£6}ôÑ¡žÿè£6/_¾<ÒghšÖ,•šME™Úi‡}Hÿ㇇Íf¹Üú=•j6óùöçT«Ý ªê½fHŽ›ÍlÖ{Éááéƒù|û9ô9ÕtÚ{egy™&£Êw³Ùl>øàƒ#}F*•jV«ÕÙ^H¹Ü.‡‡ž¼ö¢Tò„¨Um6oܾ¢„›¥’·&‚d³ÞÒM¥šM]÷>Þ_/Ï›á©MĨò2m汇‡¡ ÚsÏÕª'§"Óšæ-·|¾·ì–ËÞºè·×·/ÿRÉ{ßyݹ‡Ïcÿ–R©ÔÌvn`g]÷6j]÷î3^­†Èèñq³ü–Ÿhf‘oêwÙMõEO5Õ=ÕõÖ¢7åð™æaºÜT_õw¡÷„àóCïÇÇÍC5Û<üÙOûݸánðÖxV÷ï ªª6oDõ;mDÉÓõE§ºqÃ;®ª½õ¬ÃCo“ïܪÕv=ÿÆÖóTÕ>Q†t½¿'ï×ï<šMï=E r|<–¼ e°öãää¤yrr2éÛL̸k*åýºÖD6;ø6܇´ÿÆ7ºwϰÇú‘Íelf³ÓQ$fmÿÌ‹E¬ã0ê LUÕÞËeo#™”tº]þòùv˜Nù®V{;]nܘ©Ð{KTÖ¿ìÕA]çð0ºFi?­ðŒÊ4Öä7šú4äzÉ)•FòcN…ããù:3—mŸÕzœ‹crú'ÝR’‡Ð_†âÆv%]q]÷/—Ûo'ÁÓä i6[±ƒtzÀméø¸yÃqýS(•Ú¯]}Ù§ýÏGR§}q÷ï Õjµ™š÷&6-D‡QnÜh ¢xEBœ-_N¯cÐr|ìýf\Š<îÆÝÏhEªãÈËÀ”`¡R©àÚµk¼–ÛÒ lÑÍÆEꜤ栋°¦,£HwN”ã´ßÚên $E¤Ò u!ç( _$s@Ê“¦‘ºl)^g×uû§2;±¶Ýžª®i­±B–èÖH/‘Piš–,ŒR'1$’M©iÞš.³l¶»‡Æª¤òž"U·~‚ÞOP®e†±ŠN¡«w粜Qª>8K̽yä4Èç=‘’&émvRßÙYÒIGŽò°Õ¼÷–ÿ8òè¾Í je SÖäyauÖ]œ¦+òù<²Ù¤ü3ö>´ÚÑ ¿³,y:°¤|KŽ~\±‚˜Ëy?½6qMó—\®}²‚ (Þk3™VÖ°÷¦Óc?4­5¹¡³oL©4õ›ÂPk±XÄÁÁÿûÁÁ¶··ý‚ìe¤s&Ÿa ×iu} Ö(šÖäØK¥û­Èø‘RÂ!°ÃÙc â.ða›Ý$Ha§tØí¬­–çH;j©˜‘Â%v€ø‰¤æNŒÕ°}~Ùt?ÒBæ¯.™c¬:ÅyÎkaþË | ݵ`ÿér¿}”Û?õÜs é««Õ)W:K‹Î‘Ï·šÇËD0‘_–3ž LÓ\¼¼ƒèE2I@„\Óü†mhZû¸¥SCFötéU)½i:× ðò±Ns$]~c£Õ/Dî{™ ÛF¹œ÷Û7t^ Õp,ËZÎîÀ2…àø¸%Œ22/8³ ðd%d¼äPÁ21Jû1A¯1g3ð`e°`ssÓo½··‡ƒƒ<ðÀ3N?+ÇÁ+_¹é§mãÃ"£ã}H÷n$È 9’ù¼·A·YÒý‘©Á†Àäl2Pq6˜׋ÙkÈcýÆÎH»i`êïÄ^h©Ôûë:ùUÇ4ÍŘÅ[†QwàüÍ=°?wRß÷e€hÊŒtqœžroÒõ–î´0r+ÙØhõž[䥓ùcÛv4£PÒ¡n˜¶Ò€'ÌÕ*¶6¤— dß?äh)o}¤ÒÀ?ë[”ÔhŸü ¨wôøÍP”·h°ÓÒFÒ¹e®_0ÒT.®ë.IS¤?PZÚîÀ-•®ì’=Ó)PŒ&Ä@ƒUÚ^oooûíîîâèèµZm¦ƒ°g‰mÛX[û^_~¤•¢½ó„G$¬ uØ|È^¶Ò+ Æj?œ¤v_N[óe0ºn«eh'ÃÊ÷Œreþ)ÐíÐ$«ËÜ£«¢„HXè©- ÞRé%äïUb˜ê:Ô³ŒišÈN!…| ®ë q*5PPíí"Pw¡¹V+›LUa½ø›a¾ð;û: SYŽë«âl”®»š(ú—#«Šâ=G :Ž×úS!<>½>üT!£Cix"_Ú±±á­ ]ïvN†·´h'ñyÃ>1X«º¬QÕ Žã Ñx‰/Cš˜ £$ïj\&­ I)sÝVgèN[–Æ*†ªk’6ýA2™Öè™~H‘tó™zŒ’$+ŽeY³‹6u®y̲Z¹¹ºîmÂë.“™ì6BHŽãÌoF¥ž…‚§¬çráÏ3 ä~)7›GÆÍ{ëáø(—aÅw¶éìak"˜®'•YÇÇ­ê©Ð ,ž^9,ËìpŸ6RO=h³ÎdZi/RÚ4~ d C¬«„4¤ :F4íTæ‚3"Å{.ˆ@Ë”=DRÃ-†µŒFVMˆ …œA¤¹ÅÖ–·‡)&òX„ÜŨ¿œUfÖ¤Ãu='NçìS uÊÌÇmZ– SÑÉ´™[S)š.•¼ìéR·±Ñ­Ü;Ò?ù%¾aT—d~ïéÓL¶ôü\®Û/Á+rö˜{¶Œ8c¤æ4L¶–A+º4KŠr4x…8“«,†`Óß` ÖåÉ$èÖ Û’Až˜)*ôbœ¶6ýR)R6‰¶m÷ï¼±áýÛÁïŒáÖ_¯ŽssÂ4=Ç0¼%)ö9»¸§PuÚÞ .1HGÀ0Z³Õ ™6¶mÏ' eš­Î^B>Âü—¡P$ äóHmßÀ3PåX§ßS*£¶¶¼5Ò¯Q<9[,¤qž4±ÉŸfT«Ýºt³¶ä‰L¡ÇÚìììt=V,ñð÷=¶¿¿?ì[. Û¶¡(J[?#é0ז⨪í¡~‰> ™LK±cJ‹®_3%F“H'’*JXá¿tÖôkw>‡›I.×­èolx÷ùxÛöNÙu\»DÎÌ¢M[[c —m{ºÍ Þz„Œƒëºƒ“Ó¢‡ì»ŠŠÜ{*ÓÆF«>[T(ñ}nl„ßJd"F2Þ˜œMæ>ÎFÊ:9áE¸)¨ c Ázîܹ¶†KB<_ô¹ëº¸ë®­®´óR íÂ(ùéÞ‹¼ƒÇç·^(xÞGÖ§’aéë¡ì×;¯Õ[A£Õ4Ûdœ!€Wó4õæ3½F A&>щi`šæì¢«Ò(c€1,=˜òùÖ¼÷N;#›m9Ãдвor†±méyzŸÃ¼ãa0:´p¬±Xl©ç­†aÛ6 #×5:(Ô©#i¿aÝTg¼ËJJ«dúv¶íþÃå,h275›õ<ó2_OÆõÆPMÆFAŠ¢Çœ(e~„Ì‚™(õ’›+™dé4¶¶Zéº2"Uд–JÔ+!g˜¡4V‰àº®ßcfN8V¹Y C§ •J×®]ó?þüÒ¶±m¯~õ‹ðêW·?.Ó ÚdWŠ[{E¦¤£ð P¦Ë“Ñ髼wÊ« ¹ŽH¡4刑*2ˆi@p]ÀüÖ«P¾ì‡RÕ¶€“,I®Éç=Y•²Tª¿?ˆi`YJSì#ûGï…öôï#õã­þ’`Ðl¶?WZÐH¦ÍL;½w6LB'qè2´ÁjY._¾Œz½ÞöøÁÁb± …ÂÒ¤ kšæ÷âüî°lºþ¼ÖƒRÜ™  "ˆæ=äâsœÖðw ¥üPQ'S¥ÓsÙY§½`‚!S)o¬¯‡÷@ ˜Ü`•&¨Rs纀Sù+¤Ž¾Õ?žL¶ögIƒ”=` 5™Ó®ñ³ Ì?ü˜w¿ºæ4í™`°µÅù¿d6̬á’Lø`h©ªKp¥RA6›Å¹sçP(`Û¶ÿS(pîÜ9\¼x•JeÑ×Ó…t,Ë‚ªª¡Ó:ÔŸÿQè¯}¼ýA‰°µ“ ½:÷z~¤“¶Œö3 «dtú6â°¬n«OQZ™Ô¯v*ýÒ ›Æ*éŸ)d¶í)ß2Á@ÞBU¼³ík×üß=]§\noÔÇ=šÌ›©F¡\¹÷|bMÐa®ëáûnp 2MlÛžM„5—óœŠÄR3T„uooº®£ ˆèº]בÍf±··‡GydÑ×ÔFçØTÇqpÛmë¡r«~î:Ô_Óy½5]ïžÍ'¸îЩ’r&5µÒ=QéÛ!ØuÃåXU=Í}A…wÁ »ŸŒÙó†œ!ÇYÉcµTt-d]„¬ê:$ ض=\:°Ô8)JO]ÄHšP¾èk ÿ‹»Ûï×3 ˜ FÈ4q]Ê´…+—ó„™øÒ30ÂZ©TP¯×ñÐCõ}Þöö6êõ:jµÚ¢¯© ×mOkqÏþý=,ueGÊfß«0©WTj„hUgz²¢pm‘ñè›RÓKqÑ´…j!’=O™'ãà š‡-œæþÚÛElé7p˜¶ [9/Ä¡´xBz1Ò(›dÒs¨çrÞÿs9&ª,£þ”Þ{oàý½l/¥dÞL»OÐM“V„ÖZ­†X,†X,Ö÷yR¿Úh4}MmtÚ¶mãó?ÿûqñbÈ“OS…‡n ©ë½S‚G0X;Ç»2.};÷ŠBÍ¡M£¤¹Ó{ƒåYEÆ¡oFAdÒ8]â:c¿ ͽÖÊ÷%d º~Õ²B M-ÓûWŒÑêízÜ ‚)ò„̃‘ VÃð ­UµÕý.H.×ê=CïËJ0Ð`][[í[·}žc£ªžƒEºW{Þø;ºuôÓú>Ûñzå+¹ÛËè¶v'Ó`¬ñsšÌʱ,Ï“ŸNÓYCÆghyO§}o={sѧOÈH˜¦‰ê0¥a]%1ÜV?ÅæÃ„ M_g{'2v¬ZímŒJÚkŠV†)ÁñxF£«;p'ÒpimmmÑ×Ô…¢´2¾^ò’¯ïm*Êt ÇŽ¨«D’‚®®ËèY}t½¥(Ùv«U2 ÒDo ©”ŸîHÈ2"ÍÅÖøIçÆŽHlzêÒ“‘: ƒÇhG•`(ƒ5#›ÍöL÷m4(‹H$‘mcYždÙ±mÙ17SîÃ$Ê =šL<à,´>“ e°-£UF×Ôj5?]xPáE!£Lóø¹ŸSqï½=,ÑS«qäaðR buJó²ÎÇ®92mzz)m{®IIO¥Õ"³a`ÄÉ0¼QeŠŽB³­Érã8N¸CÒ²¼T­R ¹œ§ëˆ:"T¹“(cYòÃ4sÑõÆxUchƒU7ÞF£Z­†D"±èkò1 O¾uÝÛÄŸzêUÈfû+í#×h÷0$‡7 2/úΣ”‘3"˜¥#ÍmÒiö< ³£oÝ“„÷Ëe˜÷a²ÜX–ÕÌų¬–“|kËÛËe¦“èÒ3KFêç:ÇŽ1øÌ2T ë0Ôj5ììì,úzÚFKU¸ûî2}ÅEÓB‹ôr9Þ$È|q]·wZmÏL ¥¶¬5Óô”&«d–ô°JXIUaY,» ËMWC=×66¼ÿW«¾€'ÞzY\ÔCH” -ì8žŒsF6 0r„u™èT˜‡éBæuaÔŒ¢t׿rÈfó¼Q¹2°žoFÙ¹V8¦‰Ìƒžsûd¯VÛÊBYVºêWÅ!ØlƒNCB–…B¡€rgš¯aÐãMº˜Z„u\d~kµZmàü×a±m»wCšBÁû9eâMß0èÑ'æ'ß™Á<ƒBcÈâdÜqœî«ëzùè§«¦Ét`2>QÙ¿;³ ̃§aý¿ÅÖ–÷»eqÆ0EʸaÐu½;{À4i°’.j°ÖëõÐ4b¡sñâE\¸paìÎxÉdëÿ}G~¸®ßBR×Ç覈²º.{á™ûwI¢Ç¬å»“¾‚g]•Ùäì2oïK.ç¥If³¾¼›&ÓÉxDE¶;kµÝÿô0rŸýwоv Šâ9"ã°h/ ÝïÍM›ô`!k½^‡eY=ÁÞÞb±lÛÆÕ«WQ«ÕP,Gþœ`ii߆4’76.:VÎU%ó’ï }GÚÌ`¦‡¼% Ö³É"dù$ŠÅ"Ο?ßåê›A0eLsêÆdÊ‹E<þøã ùìiíáýîçɤ'^F°ãx>Hê=«ËÑÑþàþ`îŸ;«ý»Òù]QX–ç„é J‘ÕCöïz½ŽX,6×Ïž×þ:’Œ-ÝÏ¢ƒÊÀk¥Ré¬F£Ñ·³Ø$ôK-¾uëVÏc·ß~;î¾ûnœ?€§´t®‡Ð?IA0ª·rkË›w¦i=>˜DŠsçÎáÞ{ïÅ‹_üâ¹ö¸ò wÜqΟ?sçÎÍý¼ƒXÓ£Îùóçû*ϳdZ{x?Ç¢(Èåý©_@©ÔšA©ªÞ~L½gu‰Çã¸÷Þ{qçwÎõsç½Û¶¿ÿ‚ÿw9(8Wõ¬ û÷¼å˜ÏþÝw†6YyDU¾ÇšÃúðÃãààvG*í4¦!tÒÏÓtûí·ã¯xEOÏeÏ”É1.¹n«ùjpX7jJ'‹áÞ{ï©îzZŒ+߀§ðô’oÛ¶‘ËÑuïgŠf©4ŸïŠŒO"‘À _øÂ…|ö¬öpA”Ûö¢ýÕOýÀžg‹x<ŽF£1÷=|Vûw(®‹?ÿîŸÃÕÇÞß<ºõÂ\/•,Ù¿átœõþ ô™¡MÎãêà ŸÃÚ‰xƒi ã¤Eèz{J˜ÚÏ-²pÙâ†Ñ]KÀûP†ŸH¦%ßa„ʸ´œŽÓCæ 0KZ —2™ÓHêÆú¢/™œf-Û>¦ ll ÿáïÆO=ê…/]ô¥“3ÂnÓùHú³Pƒ5‘H„F†âñ8~ù—µZÍÞ¨8NK™öÈ){åÚ"ý˜¥|é)ßFW3™öÑ5´ H'ó’qakËë¶êgÌPÉ!3bÞ²- €ù'ÿÿìýæHŽvBFe2:CðÒ·XNGú0´Áº³³ãÿ_ eƒ Ó3Ê\×0R©vƒU×u/Ý ›¨àض÷ÓkÎäÖ–7¬›z—Iå;ˆã8áÖÓ´²qÑ5œµJÆeš2.üØ}ÿå¿|¢õ•²f!ÛBê7‘®ý 2Õ{â#dÆÌJÆ]× Á×Oé&C¬çÎÃööv×ã³Ú¬§EÏznÓl- Óô¬ÎŽÅãº@¿¦Â£M$:¸a…¥Á6ÖcÀÑ5$ŠüéŸ^k÷ÎO9{†EaYžÞ¢~Å ƒŸ€½¾ÎÆ4dåÎÐn#˜IH ÖX,6pp)Zu¦m Ä4[O²íP­\Óz¯›)õ°!dj„¦Ø˜æØ§ëzKƒãkH”(€Zí³¸x1 תJÏ Yz\×+Áyì¢JV™¡ÝU2€Èu ž†Ñþ»"‘Ôà\Û]$ŠBƒ•,]«ãŒ-¨غ„Ì Óþâ/~«]‘¦C!§Pð¶ëVi¶ÍúU²r8ŽÓ»C0kìȆ®a­Õj888Àöö6âñxOïŸ=¥™“Òž5æ´Ôƒ>)†ÑNoýYBA¨ÇrEžA+Uüz(#dI±,¯ »`Û6RôŒ“£gæÀåKäì0T„Õ²,\¼xµZ kkkþã»»»¸té‰ÖÖÖpõêÕE_O(mMkEYû,`æ0àc Ãk¶DH”p]wªécºÎ{‰–¼æ5 FÈÊaÞžëûa ¶m‡7¦!d‰éi°* SÉ@†2X÷öö ë:yäÄb­!Öñx›››ØßßÇùóçñðÃ/úz´gضíyäs¹V'0ÙGùéìå¡i^} û$jLsl“izÎNB¢„e/yu}då(Ù\ŽÓí-'dE虬ë}:¥â1Ð`•ÁÁ=ôPßç=ôÐC888@½^_ô5hÙ¢®ëz DêUÅ`•aª=C¼¨3­IÛöü:„D Ç\·cà¼i¶÷$ dɰíŽ&¶¿xñ‹é˜!+ ›‰‘Ih°Öj5Äb±¶È*? Xã'''‹¾¦6üèS0G¾Zõ4 >)7bd2‹¾BúÓe°Žiuª*ç “hbÛÀ3ϼ¯Ý`H¿BÆEÓ:ÊŒlþ›¿aê;Y9üà!c2°éÒÚÚnݺÕõøþþþ¢Ï½'A¥ã8^-HXQê€!Å®ëöà#QŲ:¢N2“fD\×3Téü$Q¤Z’I§½®¹ëdÕpÔ>ûYF¡ÈÊÁè*™”Öx<ŽF£J¥Ò÷yr<u]ÁN¾®ëâ9Ÿþt·ÕY.÷µD¥çÔB"CW‡`™>?¹3 H´ ú;=,d©éJ†q\ùøÇÙp‰¬]ÎuÁ0ºçPÂPk<G±XD£Ñ}N£Ñ@±XD"‘@<_ô5µá8^÷‚Œly¦Ó4VIôq§Ýk)EQC½H&½ÿ—J‹¾BÂ)€+WjÝÊŽ¤²¤°?9+„v¾c•‚É 5‡õÒ¥KØÙÙÁÅ‹±¹¹Ùf”^»v GGGþó¢†ãuëY±¡ƒ“,Žã´Ïë³, ›âuž±šÏó^A¢aßÿýaýY9:ëW?qÇÐî½wѧEÈÔéê,Æj¹LÇ#Š¡ Öx<Ž+W®àààÅb±ëøææ&¶··»3-š¶ÁL#+HÛ V©ébó7 Ï®¥±J¢N¹ ÆïwgЀ%KN›ZbY¸~ÇtÌ•£ËXµm«dd†2X¯ ð¥K—°»»‹Z­æ?Ç#Q·†_ä­ëTnÈJÒ6ƒUæ izl‰:ª’IÀ42²ä žûªI6‹w×jx ëdÅèj¸”Ëyé]4VÉ ¬aídmm ‰DÂÿ‰ª± ”y¬d‘ ¿)ð™_C–\ÎKèªÕv¬d©±¬î=ø}ú.‘•£Í`•ÙÙʹm{Ž÷\Î+o’fŽã5‘äˆîÕcdƒu™ðGÚ²‚ÈM`kË`è›ød0ÍŽ•ryѧFÈD8N»l»ÓDV”6ƒµPªÏà­ÃhŸ¶ ¬¯{j¡ÐòÑ—J^ÀðbSºÎ1Ý«ÈÐ)ÁˈmÛH˜µJȲâ8~x¤‰YNVÖ`õçSà YLxîsßPmΟüußççrõ„Dà„&Û¶¡)Š'ôC6ë $Êäó€â:~£<˲h°’•Á¶½ÆH€—ê~ÿïþ.à8Èç“ᥪ­Ú× ú=—••5X-Ëò¼ò–Å‘6då8:jà•¯üSïÓ„ö%ŸéÙ/“ñü6‡‡‹>kB†#ölS?ò4BgIB¢Ž¦¡­ŒeYL&+ƒ¦y?ÿò_~ ç <ïOþPÕI'ÙLL>ïÍŸ—¥&]ˆu]VÖ`u]oøƒ?h­BVˆ}ì¯ñæ7?íýâ8P5%Ô`Íd¼9w•,#¶mãm/{™§Y°Õ#Y%LH§™LV’lø•_ù Þøñ/ÅÆÇ%2•yŠÒã•DŸ•kóä‡? õ£ÞÿþEŸ !SçÍo> x‘']‡®wÊcµTZôÙ2µ+W°÷_üØ-úT™’ó®(L&+‰¢ßüù»ø?>ûNdÞòÜH&:ªj{Šr¡à7}£Ñde ÖoþÀðyÿöß2¬DV×uñ¦¯üJà{¾¨V¡¡½.CþOc•,+Ÿú—ÿƧ>…g`á¹d„L“ÓfK€—\âFMV ×uñÝûø6óSP¿úŽEŸÎP¤Ó^í­tñVUVNŠãL¯ýDä ÖZ­†µµ5Äb±¡_só€°æ‰DžqäðR%sŸú”§ô( ´ûf(ú$*Œ%ã¶ëׯ£ò½ß‹Mc•D˜±ä[×]G¡P`t•Dšqu”=ôžãü…Ñ^·H(—½aË‚_fœw/ͤÊeïß\¡åXšæÀÒJG’*¼Ùâ½ÓUµáÍåÚO&½s «¹í<™_kYíÁ ™aYžž˜Jy¯‘ª›Aç§iÞklÛ{]Øw#U˜–å}Vp‹[_÷ÎáG~dô¿Od Öz½Žl6‹Z­ÐO7÷aøƒ§žÂÕ7¿{‹¾Bz0‰|Àíÿ8^ä8­ÖwðêTƒ,!‹d"×4|ÿsžƒÒ·û¢/ƒP&’ïT ®ëÂ0 T«ÕE_ !]Lª£|ñ/ýþê¿ý·E_ÆÈ(J‡¿†B*Õ2LÛöŒJ "¨j+b+ŸÑËO ù$n¿ýö¡Ó·¦É8ò ò'‚7¼á ¸ë®»ðÒ—¾tîç=m¢"Ó$*köúõëxúé§öùÓÚÃæg~fa×0 ¢"Ó"*köñÇÇÍ›7ñ²—½liöðàþý¼ç=W¯^ÅÕ«Wç~îÓ"*²0M¢²^eÿþµ_û5¼ùÍožûçS÷ˆŠB¦ 囬:”q²ÊP¾É*Cù&Q"Ò+!„B!„³Ë³ÞñŽw¼cÑ'±êT*ÜvÛm=S)jµ>÷¹Ï…ïwl˜ã³ ÑhÀq|Á|ÁXçÅk"ã3‰|Oãø,è'ãËx=d2úÉø2Ê÷p"œµý{Ð9EñzÈdpÿŽþ5 E“ÌŒw½ë]Í׿þõÍûyß}÷5|ðÁæÍ›7ýã'''Í·½ímþñ·¿ýíCæø,¸yófóío»ÿ™o{ÛÛš=öØÔÎy×DÆgùžÆñYÐOÆ—ñzÈdô“ñe”îáD8kû÷ sŠâõÉàþýk…Hv ^ŠÅ"vwwaÛ6®^½ê?&ìíí!‹ùÇkµš¼ß±aŽÏ‚b±ˆz½Ž«W¯Â¶mÄb1 }NQ¼&2“Ê÷4ŽÏ‚~2¾Œ×CÆgŒ/£7ªòÀ=œ„qöïAòE‹LîßѼ¦Qa ëxà°½½ xøá‡xЋO~ò“=ݺu«ïkE¨§MлóÈ#à‘GÁææ&vvv^Ï0缈k"ÓaTùŽª<ô“ñe¼2=:e|å{8 ã,ì߃®)Š:™Ü¿£yM£Bƒu$ lnn⡇ò ¤ƒa÷°ç÷"‹õ}m,›É5œ?üôÀÛ*•ÊÀsšô8‰.£ÊwT塟ŒßvÛmKw=dztÊøªÉ7÷ð³ËYØ¿Éwu.2=¸GóšF…ëŒ(‹¾çCú8wî€öÔ›z½ŽX,Ö÷Ø ×Ί~ékkkŸó"®‰ŒÏ$ò=ã³ ŸŒ¿êU¯Zºë!“ÑOÆWM¾¹‡Ÿ-ÎÚþ=H¾£x=d2¸GÿšF…ëŒ8þ<*•ŠÆ˲ü?~,C"‘ÀÑÑQÛñd2Ù÷Ø ×Ίx<ÞÕB»X,úž™IÏy×DÆgùžÆñYÐOÆ_÷º×-ÝõÉè'ã«&ßÜÃÏgmÿ$ßQ¼2Ü¿£M£r[³Ùl.ú$V•½½=!‘Hàä䤭@ðrÒwvv‹Åü¢æýý}¬­­õ=6èµ³B>S¼T£\Ï4Ž“h1‰|Oãø,è'ãËx=d2úÉø2Ê÷p"œµý{Ð9EñzÈdpÿŽþ5 Öl™V'Ñh4|Pçñ~dž9> &=§(^ŸIä{ÇgÁ,×$å{ùè'ãË(ÜÉpÖöïAÇ£x=d2¸Gÿš†…+!„B!„HÂVB!„B!‘„+!„B!„HBƒ•B!„BH$¡ÁJ!„B!$’Ð`%„B!„Ih°B!„B‰$4X !„B!„D¬„B!„B" VB!„B!‘„+!„B!„HBƒ•B!„BH$¡ÁJ!„B!$’Ð`%„B!„Ih°B!„B‰$4X !„B!„D¬„B!„B" VBȰ, ®ë.ú4™;Ó”}×uaYÖ¢/‰B™ 4X ! #™L¶íEŸ!sgš²oÛ6’Éä¢/‰œa Àã8‹> Bæå}þÐ`%„B!ccš&xrf ¼ÏŸg/úÎ:ŽãÀ0Œ®ÇÓé4TUÐò䨪 ]×aYÒé4/­LRÁR©4Móß#—Ë!›ÍÂ0 ¸® MÓJ¥ü÷SÙlvìç2ˆaä …\× •±iÉ8å›Ì“yÈ~>ŸG¡PÀm·ÝÖö:×uQ(º^Cȸô“g˲à8LÓèºÞ&Ÿš¦ùQ'!ËÀ¤ò®iš/·Š¢ NCQ”ëqa„uÁ¸® Û¶ý˲|ð»P(ð<:[[[þ") ØÚÚòßgcc£mÉq×uáº.¶¶¶ÚÒÐ …r¹ÜØÏ'dƒä2™Œÿ{/™”÷šDÆ)ßdžÌCö3™ LÓÄO<Ñö¹ÉdÒW„™ÃÈs |J$Š: Y&‘÷}èCX__÷¦i¶•lP®Ç¤I"Ã7šš¦5³Ùl³Ùl6›šÇÇÇþsTUmêºî«V«þ±R©ÔTÅÿ@³T*ù¿kšÖL§ÓþïÙl¶©ëúØÏ'd:å»Ùôd.ø{©TòelÚ2Nù&‹bV²/¯/—ËMþçåši&Ϻ®7Ëå²ÿ{§|ËcÔIȲ1ª¼Ë~|½èíò\Êõè0Â!2™ TUE>Ÿàyet]oKK¥R¼T1UUýîÁ߃<‚¯UÅOIèŨÏ'dX:å[ÐuÝÿPþf!ã”o²f%ûÁ×­FNrŸ dô’çN:å NB–Qå]d6“ÉÀ²,(Š‚r¹Ü&Ë”ëÑa kDÈårpårÙ¬ßÈÇqü:¥ a7BM˜|‚2NVyÊ¾Ô f2/úÒÉ 2Ž<²¬Œ#着¢\.ûe|®ë"N£T*-úr–¬À0 †r¹ÜæeQ¥§ÑªišïµÄûκ%%zÉ÷ (ãdÙ™·ì—J%¸® Ó4ý& „L‹qå™ed\y—ÆI¥R ¥RÉ;¦išß0•ŒS‚ŒmÛÈd28<<ìRDR©”_ì x ‹4ÝÐu½íw UôMHTè'߃ Œ“efQ²¯(Šß­’cÈ´Fžûe…²LL"ïÁÈ*àE\éà™¬ F:þ&“IÜvÛmþO.—ƒªª(•JH&“H&“ØØØðSÂD)ÉårØØØð;H.ú’ñé'߃ Œ“ef‘²ŸJ¥J¥èÜ!Sc<+Š‚\.: „ecy—6ëëëH&“X__‡ªªì-0!·5›Íæ¢O‚„#)`ªªúsXeN“(.Á&’FFÈ*A'gÊ>Y‚úJ°¡ !«È0ò.Ù‘Š¢°Œi Ð`0Žã`}}Õjš¦Áq$“Id³YæÁB!„BV6]Š0Á”`×u¡( Òé4UB!„BÈ™€VB!„B!‘de"¬ï}ï{ñ‹¿ø‹øâ/þâEŸÊÔXµñO=õžzê©Hüžzê)üÝßý~ø‡xѧ24ÿê_ý+¼öµ¯]ôiL(ÉôˆÒšµm‹>¡á}¢´fŸzê)ÜyçøžïùžEŸÊPpÿŽ>QZ¯¶mcoo±Xlѧ2Ü¿£O”Öì8û÷ʬÿûÿo¼à/Àùóç}*SãÑG]©ë¹~ý:>ûÙÏFâš®_¿Ž?ÿó?_ôiŒÄ­[·"ñÝM‹(ÉôˆÒš}ôÑG} #Á=<úDiÍ^¿~õz}ѧ14Ü¿£O”Öë£>Š;ï¼sѧ14Ü¿£O”Öì8û÷ʬ·ß~;^ñŠW ‘H,úT¦Æ7}Ó7­Ôõœ;w÷Þ{od®©Ñh,úFâŽ;îˆÌw7 ¢&Ó Jkö…/|á¢Oa$¸‡GŸ¨­ÙeÚùGŸ(­×¾ð…X[[[ôi ÷ïèµ5;êþ½2ë*²¹¹¹èS˜*±XliÒ[ÈìYEyXµ5K&cÕäa×,U”…U[¯d2VM–}Í~Þ¢O€B!„B ƒ+!„B!„HBƒ•B!„BH$¡ÁJ!„B!$’Ð`%„B!„Ih°B!„B‰$4X !„B!„D¬„B!„B" VB!„B!‘„+!„B!„HBƒ•B!„BH$Y¸ÁZ©T} „Ì Ê7Yu(ãdU¡l“U‡2N–…g/òÃëõ:vvv`ÛvÛãÅbm% ìïï/òt  Ê7Yu(ãdU¡l“U‡2N–‰…¬õzµZ­kA'''ØÜÜ„®ëþckkk ù‚Ê7Yu(ãdU¡l“U‡2N–‘…¬•J–eõ<~ëÖ-$ $‰…}1„Œ 囬:”q²ªP¶ÉªC'ËÈBjX777±¿¿ÝÝÝÐã’S_,Q,™cO– Ê7Yu(ãdU¡l“U‡2N–‘…7]ê…¤*4 ìììàèè¨ïóÿò/ÿïyÏ{°³³³èS'çèè—/_îªÛ˜'£Ê7<þøãC?—œmvvvpýúõ…ž÷p2+ŠÅ"._¾Œ|ä# ù|îßd–Èþ]«Õvܿɬ|Ôý{¡M—¨×ëØÞÞÆ<àçÌÇb1‹Elnnö|Ý~áâo|cO!Âææ&b±®]»6÷ÏW¾àž{îaÓ2ûûû S¸‡“Y³»»‹óçÏÏ}çþMæìßñx|îŸÍý›Ìšquð±"¬Åb/^„¦i(‹8::B±XœÊ…Äb1ìîî¶xonn¢Ñh0-,=”o²êPÆÉªBÙ&«eœD•‘ V1P‰b±¯{ØÑÑÑT<ú•J¥+õàÖ­[þç²ÌP¾ÉªC'« e›¬:”qUF2Xëõ:Ïç±»»‹sçÎt]Çþþ>*•ÊÄ9÷kkkØÛÛk{ŸƒƒÄãñ…¤G2M(ßdÕ¡Œ“U…²MVÊ8‰*#Õ°žœœ@h«kæF£1Ñ ÅãqlooãâÅ‹H$þg …EW„L 囬:”q²ªP¶ÉªC'Qe$ƒUÒFWj@£Ñ9ºšH$B;µîîîbss³¯LHÔ¡|“U‡2NVÊ6Yu(ãd™É`•(êÎÎ.]ºä?^¯×qùòeÄb±© v,ókd Y5(ßdÕ¡Œ“U…²MVÊ8‰#7]ÚßßÇÚÚ.^¼ˆJ¥‚ƒƒ\¸põz)d.¸.à8Ã=×0€­­Öë!„B!ËÃÈsX×ÖÖ°¿¿Z­æ×«®­­±›L Çñ~t=üx2 ä󀪙Œ÷¼Tªûy–å¬å²÷»i…px¸è+$„B!„ ÃHÖJ¥MÓÐh4Ç‘H$H$h¬’©âº@.„”V —ó T1fÓéöç†g¨š¦gÌ–J€¢´ž[.{†.!„B!$úŒ\ú¶¶˲°¹¹¹ès_*lÛ†¦i‹>…!h©4Ø`Ô4 ZmýnYÞ¿¶íý?xLÓ¼A¢³×¯_Ç÷~ošv¾í½i¬B!„²<ŒÜ%xwwÅbõz=ô9»»»‹¾¦Èaš&¶¶¶pxxˆTXîêŠP(Ùlø±|Þ3$%Ú™Ëy¿kš—Ϋª^tÔq¼ç ¬ƒÒyåµëëoÁɉ‚g=+t:½è¯†B!„2#×°îííð ‡Aƒµ›\.‡r¹ŒL&MÓ .(Ìçœv*æóßùÎ'ðÔSïÁw}×Èå<ƒ²—Ý—Ëy†¢ëÞÿ%e×0¼ÿ«j{t3ŸoEL3™V¥`ô4øÜQ0 º®#ŸÏ#™LÂqäG}r&q]†a ÛËóLÓD¡P@5lÁœòØc-ú4 !„B&fä.Á¶m÷ý!íär9¤R)߀ÚÚÚ‚;Åvµ¦iÂ’ä¶¶¶Ëå>϶=#òÇügaYR)ï±V´S0ŒÖÿóyïÇ0€õu¯9’a´¢ªhš‘-—=Cµ\îýÜQ¿“t: EQP>í¸´¾¾#x²$”\.Ó4CŸ˲pÛm·accÉd™Lfªë`lÛn;×u‘L&aÛ6666Æ>?×u}çÐ,p¹\ªªvufÏd€×¿þop÷ÝÃqô1?B!$:Œa€££#X–…J¥À*¬ë:ëZ;p¦iúQT*Û¶Q(º"~¦i¶mè§¡IUUýH¨ã8p§í1þ{@:Ý?õµP(@Ó4ض Çq`Þûd³ÝFâµk×ðe_v€ýýÿˆ­­-T«U”J ,Ë‹¦Š¡©ª^ô4øú`C¤QP”髎ãÀu]¿^XQäóy¤Ói lll@UU<ïyÏÃË_þò)ü•W ˲`š&t]‡rú#Öu]”J¥Ð× èºÞ³NÛ4Ͷ”xù[¤Ói_.]×…®ëþèD H¥CPd}QªªúN´Îµc …EA©T‚¦iÈd2H¥RÈf³0Mþšµm©TªçõÏ1™LÂu]T«Õ®síÿÝ{Ž¡t:|-X–—vÿ¡½ï|§wαØc¨Õ>‹ƒƒç¾ü˯áþÏ·ã[¾åûpròÄ%ƒÌ×uCï g•L&ãï„̋཈F6X‹Å"°¹¹‰íím@£ÑÀÞÞjµ.]º´èkš+¢d(ŠÒ•F˜ËåÍfÛ”Ö|>õõu¤Ói_v]×®eY¾ÑÕ‰ã88<<ôoà™L¥R ªªúJrX*£g ¨V«0M†a@Uóp/jú†7ü¾æk¾Ï{ÞÝÐ4à?ü‡oõ?'•JùJ”®{‘PÃð¢§Ùlï4a¹.#)í“bF¨á®ªªolØ¶ßøßÀç>÷¹¹×2 ¯àßÜu]ßé²µµúýJ´Ô0Œ6ùÇeYmÆ^6›E:F.—ó1š¦¡P(À0 _icÔ²,ßø£RÖžã8¡Ÿéº.TU…¢(°, º®ûƨ¬Û¶±µµå´²~R©4Mƒã8þZÍd2þšëE2™ô¿¯n½ÜÓ㺞ªªžHU[FkPWr]ÏPµ,à•¯üQ<ð@ºþ`w÷CøèGk¾…B¦iâ—~É3fwv~uÑ"E†$èèÙ;Ëd2?“@²d™r?Õá8 r¯#„ŒÎHk½^ÇÁÁM ¢ë:vvv°½½X,¶èëš ®ëb}}ÝOñZ‘%Ó4¡iZÛãB§l6‹B¡à+¾…B©Tj`s Q®ý(˜(6år¹\ÎW˜ƒÍ‚†s:Æúú:ªUï÷gžy‡‡¯Æ»ßýûø¢/z1¾æk®·½o>ŸÇÆÆ À¦i§×è°NS‘õ¶ó6 Ã7.TU…ëº8<<œÛ&mš&Žû>GÓ4üíßþ-®]»6—sZD¦²Ù,666ÍfÛdçðð¾ÞÍÛä3¨p÷ª •èfT*Ó4ý÷•÷Éf³Ð4Í7R766xò9l#³B¡€õõu¨ªŠr¹ EQ ë:ªÕjhd«3*[*•ÉdL&Û®Ož'ߟ¬‡ßøOâU¯ú$nÞ| àø |èCuüÜÏÝ?üÃ/€¢(¸páv¨ª§ÈˆãK×½óŽvzÕ«þ À·à5¯ÑÛγPÈ`}}[[ïÿºÈr!Ñ}EQü{ɲ0íø†aÀq¿ïC¡Pˆ|M9Y r¹\›7­l˲P(`Û6J¥ÒÀ{–ëºøÀ>°è¯ƒH1’Ázrr¡©2õääde VQ¼5MóS$Åe]¢6¦iöô §Óé¶¹`Úp?4MÃáá!¶¶¶ í5^„·ÀS|¥ÆM ã!?qlH½µ•b´ëY5MóoêAù”¿w0B;,©TªçßQR¼ÇQ$²ÙlOÃyØ÷Óõ¶·?‹XÌÀ[Þòrÿ{{ÿû?…Çÿ6d³¯óŸûõ_ÿoqr²ƒ»îúy¼æ5ß‚|àß#û[¼öµ„Læ½xì±ß…iÚ°,Š¢øéÇÅõ:k;Èd2ø‹¿€ŸºÜ‰8 Ø {ùìÉÐq]c+Ê®ëúûå´‘}[Þ;¸G—ËåÐÏ”ìUUý½%Œ`&…eYþ½S¦Ò“€a êÁ†“z„ ò\­VýŒ‡°ˆ¨DþƒdAGöpEQ|ǽC–åÕÆ½ýíÿÉdÒOá”÷ée#jHD.XÛyªªbkk˯+”†¼[[[þ÷%µ…ù|¾-Úqq£oÒÌŠŒ†(’Áï.˜¶›ÍfaFW4(aˆÑŒ"ßQGד“çBQZÝÐ'ÓôÆ3mmyk¬\öÒåÓé}ûwø¢Óø×~ƒ¦àú’Ôc‰¶•J¥¾õTýÖ'‰.¢÷0EQ|ç_Øß4˜¬Û*ÏÁÔ~MÓü2Iyï\‹AÅ^”ë “h¥èŠÓQúˆ3Sœµ‚eY~¤4NÃq?;#˜… û¹Ü€ö,qže2šiFÈ)ÁÒ’ Ì»®ëËf&“A6›õ×Q0È rÌ„ZYnÁÌyLJGr¹\ß=[šoV«U_ßI¥R¾Ž£iªÕê™+¯#­ ÅR©4–Î$2$ú¸ÜO‚Çå"™<¢Ÿð9Á ÜOäÞ Ž)³je^¶Ë»<Dz,ÿd­9ŽƒÏÿüÏÇý÷ß?Òõd°& Äb1är9\ºtɤÖëu\¾|ÙÎ*ÐÙDÆqÿFÞ ‰ ã­(+€‘¢O@øX×mq¯ζ½Ú7yûVC$Õ?Çi(ºqí…¦i=Ót[‘ߤŸV;"ž™T*Eu H½£lNažäA©Õ½£6“É •¢5lÛûqœVJ®ãÇÇíÍ,Ë3P¥¶{›¼ó†x‘T‰b/ÛwG†Ãq_É파KLI…%!X–ÒëýMÓôßGöÖ`µ8ƒFdPy___G>Ÿo‹¢†!÷½\.‡|>ïï-^߃Ö9æóyß8^__‡¢(~'÷~÷K)MLÉú½ßû=|Û·}Û¢ÿ”dFˆE²º$óFÖ‚išmQJÑgD†Ãôˆàû£ÿâ  Ê¡èhÒ°R²!:K^ÄÀ”愃äYÖ‹Èó,jeI´èÔ¯doLj4}tº®#™L¶9î …‚ï$ 6Ä :0%J/²Ù«Žì¡r4dEÿFD%“QÓ4d³Y?³K^#ýD‚¯]0L¾+•ÊèeyÍyì±Çš÷ßó¾ûîkû¹ÿþû›=öبo75}ôÑæåË—§ò^ÇÇÇMUU›š¦ùe³Ùf©Tšê9çóùf6›úùår³™N7›¥R³yãF¯so6UµÙ<<ôþ­V§zÊ3£T*5S©TóF¯ ›2Ó”—yñàƒNå}ªÕjS×õf¹\nêºÞl6½ï?ŸÏOýœ«À7šÍ|¾Ù”eW­zëJÐuï'›õtúÇÇ‹¾¢ÞLK^æÅ2®Éq8<>¦±J¦‚ã8H&“ØÚÚB&“mÛþø.ɨ)÷èåf$ƒUÒ}÷ööÐh4üÇöööx]„—‘^ÑÕYÒoí¤Óžò].3ÂJ&gò=*2×TfŸf2^Õ0¼5 ¶¶„óùåé‚M¢‡DzÇñÓ{“É$’É$EA6›mëô ´¢«B6›e½Y*¤FO&L*¿â´‘¹©ÒÕšµ×dÖH&L>ŸGµZ…¦iÈårœ:±¢ŒÜtIߣ£#ß8­ÕjX[[Ãþþ>ÖÖÖ}M#3«èj&ãžaJu2飃 BN&Ej5¢^+äºíëE×½u ·V©Ù k aYV[š|*•‚a~´•‘!²¬Ìªót:F.—ƒã84VÉ\´ßt:í;i¨®6 Öz½ŽF£á§2‡Õ²,Ôj5Àææ&t]_Jc˜]ôÉqZÊ·Ì…T/bÄÌ2/¤ ^Tqo=t–“H‡_éLÈ4¥½WS£Îµ’N§±±±á×C1­Œ,Ò͘M“#qðÈhBf‰4¹c†ËÙb¨ëÁÁêõ:‰t]G<‡®ë‘V‚‡Å>Í?œÅµñ22•òŒW:éɼԯ(R(xë!8 5ˆªÒX%Óöm¸®;R^EQüT36é ËH2™„¦i3Ͳ‰ê=†¬’¬( ûœAÖ°Æb1 \¹rñxGGG¸xñ"öööüTÚeƲ¬¹(!ù|K)O¥¨„“ù ãj¢–¢eÛÞ'×¥ó†ÌÓ4ÇrNÊxzóɲ‘Édfn¬2dfüáá!Õ3ÈH5¬Á¨ªeY¨T*888@<÷£¯£R©TH$BImì,ÇäÈpöi⺞2ÞÙ±T:™’³Cä;*™ŽãÕuËÿK¥V#%²¼,ZÆGa\£3NSA:ƒ,“l‡Q(FÎ( g‹e‘qÇq`š&Ž9 àÌ2rÓ%!h¼Öj5X–…ƒƒ\ºtièNÁõz;;;~Znðñl6ë×È꺎B¡0“/Àqœ©+"¦Ù]GÆÄq–vmäÛ¶í…Ö–M!Ÿo9lXâ´:DAÆGa’ý>*Ž2–M¶;1 ¦i2U—ôd™d<“É0KàŒ3•9¬ñx»»»~Úð êõ:,ËêÙèhoo±X ¶mãêÕ«¨Õj(‹S¿øÎÓ¶i°…m·f—„áº^›Ø Ï °$DE¾ÅFXåÏ*_ƒ¢ÐXmÃu[3|&Å4½µ´±á oÌEœQ’ñá¿¢Ùì÷dµXFÙîDÆË”ËåÈ•ƒÅ³l2nš¦?>‰œ]F2X+•J×ï{{{(‹]ǽÏÑÑQè±z½ŽJ¥‚íímÀÚÚ677gâ%œUôɲΠbnž>,¶í ÝÔ4ïß°zèBÁ³üËeïý·¶z¿Ÿëz »„ôÂŽzŽcù¡°¸®W§-‘Õ…aÛ­¿ùúú\þþCŸ×ÆF·ÁjY-çŒÈ¬8mÖ×Ã×€t®J¥¼Bùr°mä~ñgvúQ“ñaXt¶Y–Q¶ƒHcŽ—!½X&7 ¹\yÖÓy†2Xkµ.\¸€ÿ1˲°³³ƒJ¥‚r¹Œž  “ÍÍMìïïcww·ëØÉÉ ´Ejãñ8êõúÔ/~Ñ'_³’ˆQ–â8áÙØð Ê\ÎS¼½Á›år·…oÛÞ—™Ï{–O¹Ü ÕubÛžR¯ª­¨l˜aâ8Þ9Ì8ú´ÊòÝÇñþd[[ƒEa,\·w4¾A/•|b–Õî@‘‚ô0‡Š”¹œ'sɤ·>zÉ—eµž”ÿ Šâ=o}Ýû\)ö­V½¢ø°Z4MóÖ‰ü­U(•ÿçÿ|¨Èx?r¹\[ª[”ê¹ItYÙî…̦äxÒeqÛ¶‘L&aÛ6ªÕ*{á Öl6‹x<Ž+W®øI³¥+W®à‘GÁîîîTRú-ŠF£ÑóØ_þå_â=ïyO›QÝÇq (ÊDHÇñôOÑ¡å÷…éDÉäìRgƒF¡ãx wÐ(Ìf=E»ŸA4L«ÕÖÿÃjT3OQvÎåZÏÍf½S©n£U («UÔ~w|Ã7à/û·gó]õa\ù€Ç|$ÇeYsÙä ó¯2™V:üÔ¡âˆèåŒ{Ì0ZÃï¤,«¿Ã¢PðäLä*™ôŒÊ࢖Tv1(uÝ3$ËeïâÃÖ€¶šæÉèñq¸<·6ýÐõ®çìììàúõëSþ# ǼöðA˜¦‰L&×uáœþMqš¶í­5ùÕÑ4€b±ˆÊ÷~/nôš‡5#湃ÌÜf7ëåFöo©!'QÙ¿3™ ²Ù,J¥÷íãèè—/_ÆG>ò‘‘^7°éR¥RA½^Ç•+W°¶¶ÀÚZ­†K—.ùmnnú©Á½:Ž C¿qëÖ-ÿó:ùÂ/üB¼ño õ…aYÖÄH±³ÇÓÅÓYæ‹YU{wŠÒ;RÙ Ãðù`[WÃðŒc¹1*Š÷yÞÆ†§Ä¿ EñúAud®Ûm$ô"Ì2J§[˜ÎïAQûÝßÅ3?ú£xßýÙlÿ!Œ+ßpÏ=÷`èϚǎ ï+žªÜ‹ Ï] G‰òwF%z)²¯iž,v¦1zÎÇñÖAðFèºÞë²YïG Þ0yÕõn‡Š<Þ)·†áý”ËsËÞßߟšâ0*óÚÃû!Í•4MC¡P€ªªŒ®Î‘õÎÊŽã±Ù,Nû>±7ýælvP÷P¾ä°?÷e0MoÙH‰ª»»»øÏ¿õb<çå·æzyóÜ¿ÇÁ4MTçlįŽÓºŒ€yð4Üß|?Ò|®¦O´ÕËþ=lÓi…ý[ÆñqÏž ñã÷•EËòu±eBßëêQø??Œì?øu(?þý)|›››ˆÅb¸víÚH¯h°Öj5$‰6!•ù«Aaê·QB¿:ÍÖÚ¶mÝ€#“ñtgÑm…žÍl%5,õu¤Î-¨0Ûvë„2™nåØqZi£ ‚ÍdÂ-ñ0C(nÕÙ…D}†FŒßIð·½ñu_‡?»óÎÉ>c æ%ßÀl:`w2uLä4hhŠá(2!9ÇÁÅ'ŽQŒ%ÔÛyýªêiÉ’š[*µGúƒ^2(ñB¿¨è2Oï…8$óù<666€5PÓ¢PðÖO©¾F:•AN#­¹\ûRó²å½úkå'N`›´s¿¬µåÕ/ò“O· èøÏÿõ¹^zd»R£½ÊÑ( Ôu[ÂðG‰¨²ºrÚ[C"¥ ((<±WÕÖ­¦Í“-¡ð“_…Ãíß”¯ƒiz?Ζ#šEw^6igk p>ü7Hýã:²ÿåU-¹’r&Ñ­tÝKiþÚ?…þ𶍬øcàŸ^‚»ù%#í1®ÛªÄ’·³,à—ùKñþÑ‘®g`JðÚÚZ—Ç¥V«!OÍH rîÜ9íi õz}ê eÜz¦Ba ç›Ô`v¦Ñv2lC]ïN±#OÓ¼“Éö†.¢¨K4üKé®Õ+•†KK >àÀÙD]¾‡EÊIžÌÈ€Õ^OÎd€»î,ã™Lwä3n—§R ¾FЉhù|”ãýjN§…Dü§Å ´æ3/ï‡mÛ¾üÂuݳ©›Ž…1Bª®eö7ý¨÷žÇÇ­4÷Ó1 ç¤a9}îª Ãð–CðÏ‘Í~×4¤®¼ùÚ[‘Ò()ï~—Öl?±BU\îÏñâßœë×ÙîÅÊ*ùnê™ÌjÒÆìöƒ°¾û×Z}+:^(索§[jÁõ{ $QÆÆï]†ýeÛ¼[ʧ‰=×®aë‹?ˆþ)2ï}p_ÿPÿü7Q}"õ§ßhÒiï=ûk°¥A2éÝ“IïñE¬Qq˲ÎVGw×, î;~™¯¸çG>¼oFÛ†õïßßr vزÏVþàÿ/{É¿ÆßûOÞú¨ÝŽä=בS<=ö¶õt0~~ ëßôåÈ)%˜ÿ‡Ãøÿ·w÷QnõÀ¿¦¼”ÄVrçàD1rëZùŒØò’Pîl Ù$­¨¦,öÁ³g©Ï"o€®¥vºKØÍÐQ—n»V;ˈžÍ¸õ¾t´™&ÞzenqKc_ÞÚÃÜ$0²!ÇøÆ–楠ýãÎsuõþv¥û2ßÏ9>ÉèÎŒîcÿî£çõ÷ ^ü÷XXÞ‹ÐÝ·u ¹_^2s0R/„úeô@µ… Vàˆ™#±!‡–X€¢Ô~ˆ~®ø•š(ɇºå"ŸûmÀõ<äÊhùê¯)„Ý»«[€êh»¹€B ž¶Ú¦²°PÝ$¿²âxú}7Äv+¾]œÏù<´o½ýÅÿ†ˆr jö XDä]šöŽHü—{æQDÞú2„B€œ8är˜Ú¯"µFäî ùè˜q˜NZÞŒ1ãõ½P}6B! õ÷ õ ñ‚ò{›Þý;Mã2‘2¿õ,>s}Ób…BÕ…Cæ³'™i7~ãÀ—7ã†ß–Ýóyd¾õ/ nAþó?Dêé­£êâqs_„‡ªÚ×_‡ÐÎg0SžAä¶ç±ðÖ‡šœ4Ws‰•’ôf,ߌM¤×Ò8€{Ð,ï³Ñ„ÕÖ-Í@=ó}DþÝ¿EÈÒÜê´»pfÀÞ;üÛYF<1Ë(>, …ìù¯¨«k4Åìì,b± …Êå²9’W.—ñØca~~ÑhÔ–Q˜d2if .—Ë8räÈÀ¿WÐ4­¯‡Aäöih'‹e³fÅrÝ™™Úƃ¸ëõTª:$!‚Ö*©6Bši×iL¥ª{M­DV^ªaÇ7`ĸm#”ù<”µ ä”n¿ØflŽZãMdºÍdªë¢Ú-ñÎç«=àn;_v.uöÚ:Ñ+pqJòQÄx+º× ú±Õˆ¯i14{&Ä~lA<¯’„œ1s’iš¥£ùÈ#ÀÞùð^óÑI:^øð¹jÇ¿R€ÝmoóŠeÅ—è¬Ö,§Ìç;?ó‰Äà[Dlädl·âëåÀ[ÿþ¹{ŸCâ‡_1^‹F1õ…cAñ\Zb™ŒÞ‰pþ/³TëÆæç”¤ óo`å‘ïC×#µa'IÆàe7–çL>>Þú¶ã:öäGH¿ÞüëÞíúmÞªƒ¶KKXøô§1úîªÁÉ÷õyÙ¢¢DjcM’ /,!P„á{¼é{ŸƒúçX85Èÿš2wþIR€±ÊUU)4ìßíç8~¡¼·ö½ûh3Þ½ ¯§R[‡)üïÀÒÛþ¡Lí ;c±ç+u©ºEQ´ó9©Ò…«W¯Vî¿ÿþÊ]wÝU9tèPåÁ4¯8q¢2>>^9zôhåêÕ«Ýüº®\½zµrîܹʹsçºúþsçÎUNœ8ÑÕ÷¦R©ÊÒÒRO÷³²R©ÄãM.¬¯W*@¥’Ju÷‹®\1~Y*eüY[kvƒ•Š,âñJåüùæßÓcjÈrí{Ÿ?ߢ€þÔK¼ C¯ñ]©T*Gíú{C¡-÷yåJ¥"ïV+‘ðÿ«$M¾¡>Žz U*‰Dó§ÖR)£ÞY_où-½ÄË0 ³ogee¥’ê¶>v©µ5£:¾r¥ÉÅõuã¹iz±;mÅÚšñ\×ÿÀ Ÿ7[¿"‘ØzÏDÂx¡þ}zàd>ìú»Wý´iFáÊ•&1¶¾nÄØÚZµÞ__¯¬eÔŠÞ¨¬eÔ¦¿«Y¼Š¯×Öº Ïóç+•……‘•éVIܹa~Juø¨³|no×ú;‘HTVVV-{OÚ~W*#PS)ãßW´ïëˆ.AËŸï’ó»ˆÄø]K[«;¦~õE¬¿á½ÕƒFOì¿¥£8ÎÉÞû­v,EûÕ\Å»µ<‰%gη¿õ-ûDž³*b§IýJÚtÚÈ?³u²Lû¶ƒØ62¬AL‘ÏÁ# S7Ér`q®n³À9x°šìNQ€ýû¡ßõAL~v ‰¹kÍ1 M3Úðk[íŒ\Pqx 8Ÿ€Cæ¯gÜ/-¿¶×Óø\!Çzz? ¥M®=ÞI–kG”8iP“,ÏUÄé"ãª$Aûô*¦”bå {€ë«ÇM‹ãÞg´5£Î.—!ýüÏ@¾çZ,Yêc‘tKä4µ;7ã¨HŸ8†Èä$.…'¢X cÓÃÛU‡5›ÍbyyÙüzyyÓÓÓ¶œ·ä„nfŸÄrëx¼}£¶#ÄÖ,½v€ÁfZêïñâÓB í°š£ÀbÊÆÒ¨\Zô;¦Œ‡Â£³#äo£8ÎÉ$ε6²Df  q¯’x¦¶>TÒéj§³Ù ’hј³|§ñŸ&·ÒiaŽØJÞU‚éf³¬vu?s–N§‡;@“ÉTC–¤.&ë×ñ8ô¯=…É»~‰ù÷^c~[}|v¯Öä~.š|ìÍÚZ5£¶ªV'd¹v¢Ãš¨p›Êd2îÝ¿*ŽEPèç¾…©oý–ÜcÆåÊJuÑ¢,[5ŸíŒÇ«ÿÜÖT6ž#öÏÌÕ–ç{®«ëòò2b±˜¹,x~~ËËË8räÈP޶&EQZ6f¬¹“š®Úµ~€×4«}‡â4m°ÎC>Ï·´aš™1â·É¿w>oI¦´œa‘þæ/œ."QSÃ>ÎÉòFFT¬Éµéu惖¡ô»15Y=m¬¦“‹¸ñ;s9ã¿6–'ê!¯^*U]‹i7;ÎÚ&ä·fèlmä[ÇÐuèo¿ êۉP]â=I4]‚„j5ý™}‰{¿"žmÌí:±µC–·ýjƒ|>]×GÛaÉ Å ±o¢¾Î«û7œ™âïiü¶^ûi¾¯Ç ±P;¬â¸šééióµd2‰ÕÕU‹EWíã膪ªM;¬33Êe,,ü€TÿCÕ<ÎÖa+'jTQ›kÚ`Šš^ y]Û&±d#ªÆìÖ!Šy}©:#]gÖhòv’¶ÐõêLÉÂBóz·‹}ryËêÕƒI5Í(RUç—Ü‹YV.Ýu%]בN§Í%¶¶±Æœ¦AÓCÈeý@B*U{ÄŸ8zm­º,]²vX·1]בÉd°2ªúNU±:&•2â^œnË!_,W·lˆ*PLlyr‰ú° y°¡ë=¬Ö½ª^›Uµj–pI¬ÊXºåS€j9GTäáÑj¿ïd”§?÷pø{SütñŽË·Ræ›çoefÑÿ¿Bý¸¥]“!…ÈÝ4MÃÌÌ "‘Èð–G¦ÓÕ£dú|6DZƒ†[V zð©u¦Ö)MÏq#7Ë'‡1@£ëÆêß•ã Ñíy º²Ul™“æN‡¬§ÈrÃçÛQ&“,Ë#ÙÊ¡ë@N‰@J­#‘ØÚþ—6®išŒHDFh÷³P2Õ­â8k]7þ0u‡3ºî°ú…õ Ö|¾š¨paÀŒeætfƈÐx¼ûó¹ê¢ævYf9rV«5D-|ð ÑÂX_‡ÂUáäQªªbjj KKK¶.öÐØ ˆ|éïFèüyhº„œ%Á§X€#ˆÆ»øÑ9Û{ºšsK«ß-÷A54Mjf`1éWÿÏ/ËÍ'­É¤©bóâ0tºœˆåõ :ž¢½S¿ýOU]¿ Ÿ©¾fO`;É9Û²Ã*²é‰ýïf=!ôªëµÜÞÜÆ5Ò4­u£Ý2¸¡§“ŒÌt¨&€$òš|>T*eûÞU±…;9”•A›Üdo|É$Àäuvή*JõHjYFõl¾mžÁ“ÜEQ”ÚåÀºÞ0 i}°…G­“u½R Ÿ¯M˜ÇÏÀ’¬©¾MS¸Ý·õ‡¼¬ë«¢(8qâJ¥RÍëËË˃Èd2®_&<¬ÑxFg`ÐãeˆÐv/ˆ¦™-UåŒ*ùƒç®†BÆ#b¶ûYŸ“Ë4]œËÄQdâÜ™­Ö{&SSý¹F×޹œ¹b WºúÿøR·¨f&»ú2äO/éæ› …R©ÆÆÆÉd ªªù'“É`ll ‡F¡Ppº<]õy ëZ;ärN“¨Ê2/+‰¼ÎzLY_tù= íÿ‡´ÚAüúY+"‡åóùÆAÉ­£÷ôõ;ØàeÆk[UU5š"\$@nÔu‡um ê|úÿwÄ?yÔòë0#­@Q%¢èæ VÑç¶<òƒ®:¬š³Uc¥ªÐñ}H?ðHÏ]j>ÈÈ…\¤é [ÿ*/ÞŽøÇ^ ,-™ÇÈOM++ cr§n;¬šL}4í÷ÿ’’ÇJñM$còiiÉaŒû_Çk¡P@©T±cÇÚ~ßôô4J¥ŠÅ¢ÓejJ4æÅM¶«è8ÜChÚa­Û¿ÊÐ$?è*Y‡®­öfY(#d~é H¤wC:|gãuUe+ˆ\C×õ¶ üx¼:“šHa_³ÄÈeºÝÃ*IFÇ4РƱcŒïí£ãÖb±ˆ`0ˆ`0ØöûÄþÕr¹ìt™Z’$i¸«¼¸I„¤Zgø­"³%ÃdKäGçu˜œ4ZïMêfM3pÖ×h¡Ú2[CäMgW·d2µc2‘påŠÓwLÔZ/9ex¾5]̰lnn:}ŸÉ9,“Mög¯¶ê8 QËÆ»$™A ñ$$ò‡ŽÖ©)£Nnq&v:m¼iöP0é¹HÓx×43©‘—t³X_~_ïÞI0­ŽÖp8Œr¹Ü¸žH¸œ.SK!K£½A:m_GS×92O#¥v»œ]%¿hÛàI§Š¾EgUœÅ]3j_ßêçȹH³„Kú»I•È“ºÉðžùÏ? yœKÈÐU‡5#•Jµ\î[.—‘ÍfF]{´ªª$ ªÚ¢/©iF †Èƒt]oÙxÏ匕‘D~ÒrÿS kZ“m­–óüp‹¹†ˆõš=ÛŠ‚™—|©·Z“÷XæY›ÞSSF®i€R "õ_ö9}«ä]e ž››C©TÂáDZººjζ–J%¬®®âðáÃ(•JH&“N—§­H$Ò:›XÃpû¸$˜FLo3Ø¢ªF¦H"¿h›¬#“éð‰DÕ}‹ÙY¢QûÝßý ߬iØ+òôWìe˜’'‰k.gIâžÏ#<Eöï·ý-cÈÔ1é`̲..."›Í6=º&"™Lºvv0`È+us9ã ììüu¡åòH]Ç’6HkNß"‘mEiˆw]ß:c[>”ˆvN>_,UUãùävboêÒpñâÿÅ7Î!Ÿ7bWU™ÓwbåþÔéÛ$ˆ$çÏW¿œ‡¬ÃR<­uT£«+Pí´Š£kŠÅ¢¹\¸Sa7GÚhZ‹¾¤Y 4ÍØ÷Ôì¢!«?â#o|!Vúä3š¦5ìç³.l9xÐè¤æóF}/ËFèéÜD.#:«boêOüœ9“5övd4H7½ ë¹;ëô­õÌ:àX³óBTÖšfLq[YtÝaÄ7õ…r¹Œb±ˆh4êt™ˆ„4bt½i‡Õ®uºÎ %4rªª"a™6ÊçXE.:}kD¶S©­AÑ®mÀhèçrÆ9}Ö•Ãm“Óè:†{îQwòy#v%Ɉu³½µf¬” iB̹A¥i¾ùÍ —k±Ú%b&1jÐÕÖn‹EÌÎÎ:]ž¦DBIj3`cG'S’¸•cÝÓ—ÏoÕ÷ªÊl§ä+b¿¶H¢—Ëï‰D¡ŸNÿÍdX—“#D?TÒ5@U›.G(Äò¬Ç¿„§Ÿž@üå òˆº`[‡ÕÍÄþUYnQÇÛ5RÉrHý±65Ù°Ùa%QUÕœq …¶’Ûq,™$U·† õÀn¢ÖÄ2vÌÌšUUçÒHò‘/|á%ø•w]†ô>Æv3umÛtXeYnÝžá20ò8ë¼¢X–½s†•|Æz~Ÿ$I³¯·>+ÜÚAPU þý¬‹ñ84MkÈO@äe.¼±'þ­í jÔóÖQÉf³X^^®y-bqq±çß%–MM5µÀhèØÕaÕ4#㇙öŒ¨‘ñ­Õ% S”ºpf‡•`gŒ[‰ýÚ““[[ú~@"ÙQÊïÄûˈ|èóç[g'²aÅ·®ëx%dÈûÏñŒÓÅ$qm‡ucc±X¬&¹S èëwiš†ýè­Ã?iF–½O1¢ìŽok£¦æT%6¼É!vƸ•¦iдPu¦eê÷>ˆcÉØI †ß‘¿ú”‘lC’ ªjë󆉆hXñý—ù8^ÿò—20õ¬c‡µX,"›íœ:½\.Ûzc›››ˆF£¶dÖußúÖÎÑL4‰£mˆÚ°;¾­––,_0Ó9ÄÎÄŒSÍJw;V5Ò²Žþ/‹þqGËEÎmð^ëïŽK‚ …fggkŽÍ(—Ë(‹¶/J¥¦§§qäÈsÍ|0D6›E,kú3×\s nºé&LLLÔ¼®ª*öì™hÿ†™Œ}K'Ùñu½±±18pO>ù¤#ïßO|Àµ×^‹‰‰ ŒÕ¼nmÔ¨*J9R,r‘‰‰ œ;wα÷·³·j˜q²; v$bì­â¬–«…Ãalnn:Ö ï'¾[Õßâ,á…ôÈúAή’Yïڵˑ÷^ý į|?x×»)¹ƒhƒ÷Z÷µ$øäÉ“˜Za‚Á ’ÉdÍïX,†r¹Ürtòšk®ÁÍ7ßÜ´}Ýu×unÄÛ™%˜2® qàÀÜpÃ Ž½¯ñ  žh4Š`0Xóº®ëfÃfm9¿ÈÈæxÝu×9öþv×áB(jún¹ìH™È=D¼×úÛ•ç° …†¥›››zÏR¦( ÆÇ¯ÍþU=jÃÎøµ1¥Ó\ÞHް;Æ£.—$ ‘ˆ%±˜$q€FήøÖ4cl¤Yª&\"§ £þ€þï{ßwœ.y”+;¬@óóó(‹ækËˡÇÃ=ÿ¾gŸ=ØþìlÔ'l@Q[vÇ·…Ÿ™©KpÊä1ä»c0VpƉÜÀ®øVÕÖãÛ\LNFý­ªÆ #ëpê—+Ïa ‡Ã˜žžÆáÇF±±±Èdz?dXÓ4œ>}Ç·ù&;?ø0RvÆ·õHE©;Ò†³«ä;c\ øÉIcé;‘SìŠïš3³ë0á9Åîú[U©_.ãw>Yf™úãÊ+$“IÄb1óAé7ÁÓÅ‹?‹#G®qº8D5ìŠo±Ï©éd*GçÉAvŸ 2¾×;Lä;âÛL’§ªFòÇ••­×9»Jβ«þÖu£³ºòÎ?ÂÌß ²üN<ªë«5ÉR¹\nxM°óh›`0Ø`¦WÏ=÷xûœœ…"‡Øß I¥n¤žÙªÉìŠq º§ïüù­tÝÈXÃéVrÈ ño- Ö´šÕYL¸Dn`GýþèóHüô3ˆüÉQ`ru ßEÛ[ÇëØØ¦§§^Ö‘6v+—;i“Ë1#$y–ªª$ ù¼98o`¶jò™†äbviC4bf²¥ºXVUq¶KÈ´G¾‡¥ß¸UÓ8CéØaé­½HUþðCí¿©fÓ‘·èºŽ·¾õ=êÚîœa% —ÒiË1©šÆŒìäYšf,0cÙ²DFQ,±mB> ýàZ •‚šÏ³ÃJqe–`»|êS—ñÚמü¹Ø¥K¯l\$Ép†•|CUUÜ Bù«ŸTú®‘Oä%ª äó[_Xb™Ù°É/4 ÁXä1M4¨®÷°‹E,//czzáp¸eBÕ%{BuxôÑkñÁr¦‰üKUU¤R©Æ}P++\.I¾¡iv^ºÒ³O¸U¼ÈVò,I²ìFªÉö®0áùB(¬½í>kPU‰fu©«VEQpøða‹ÅšCƒ“É$æææFpöìY§ËcÊ牉§/è:N;}{D6Új´ONV_ŠDؘ'ßÐ4 ëëïFüí—¬/ry–,[–×í_e‡•|AQÌØf"1TWÖùùyȲŒÓ§O×d ‡ÃˆÅbX\\ÄÄÄNž<étyL¹°wïéÆŠf†3Oä=öcü¥®ÑCä'O<ñ<ºq‰On}þpБ<Î\ŒV7ð¢( —N’/¤OÝuÏ/A×uÂÐÀ:vX …Êå2Ž;ÖöûŽ;†ååe”J%§ËU5&—®¿þJíÁÛŠb̰rYùD0x·ÑÖiz+‘?\¸ðóøu©:ZD‚õ8yÚÔ”å ËþUµí"Rþ~/"ó1® [t찋Ŧg1‰eÀ‚¸.vR(d$ÿÕ4­¶âO§…§oÈš¦! j–!ˆsÎØ¨'ŸÐ4­6¾ÛäCš¦áwnº¡wŽ9}+D¶hµýš3Qä'bP†K‚É;¬ápår…B¡í÷‰ëÖYW§é–Ì{ÈçyùÊ¿ø*<òˆq+÷°’_}ùË—ðs;wr@†|Cl[ªÇVò E©Û¤ª*ãšÖU‡5#›Í¢\.7ýžr¹Œl6‹h4êªY׆kÃa•DÞµ¶vû÷?ËÎ*ùÚ½÷¾¯ÿîw9àH¾¡ëã/Ü¿J~¢ü¯g^+êÚâD}ê*KðÜÜJ¥>Œååe óO6›Å=÷܃R©„d2étyj˜)´ÅrI~<ñÄ›0=}-—“oé:ðú×î¿ßé[!²Yeçrfº`ή’ŸhÅçz¾Èeîd›—vóMáp§NÂòò2²ÙlÃõX,†ééé†ÄLNRÍœñ0:ª©”Ó·DdM®½öÆŒ!Ÿ’$`çÎû±ç—–œ¾"Û˜Uv.¬­àþUòíÂ?"rèÈkÏ_%[tÕaŒ,ÀsssH&“(‹æëápØUûV…šMÞ|XÈgxå+¿ Yþñcœ|HפKlðŸ,,ÀuÌÁFUU‘âÀ:ùI(UQ8C¶èºÃ*D£Q§ï»#®™'?S`÷î¯:}DC5>þSÜz+;«äCuy5t]çþUòUB•u šÉ Á#ÈÈ]íaõ"UU9*O¾vùò_9} DC£ªÀ¾›/qtžüIUÍ«ÂY(òMBÏIâ ²o;¬ÀVÒ%±ì†ÈGVVÀò5EBå³ø•s眾"{ézõlx°ÃJþ¹õ*oü2;«d+ßvX5MCàÛßÒi§o…ÈvfR±™3Ë$‘Ÿ( ðOŸû3¼ü½ïuúVˆìU·˜çT’Ÿ„~ø„ÞøJ&#[ù¶Ãªë:&ž~šg÷‘/™IÅ…GÚ/iðÎÒ—0~ü¸Ó·Bd/U­i›p&Š|EÓIb‡•lÕsÒ%¯ÐuÝhÌo¥Œ'ò]×qëSOq@†|IQùÍ—ñµ¼79}3Dv‹D̺›zò­$Kêä$.‘m|;úó™gŒÿaÖ=ò!UUqðÙgÙa%_Ò4àŸlþ.¼æ5Nß ‘ý,xî_%¿âʲ“o;¬¿²s'óäkoøæ7ãäK‰pÏú^xç;¾¢¡âþUò#vVÉn¾ì°ªªŠñ+Wj’ùŠª¢üº×qù“®ãÇ?þ1^ûîw;}'DCÅ%ÁäGŒk²›/;¬º®cÿŽLFC¾uëSOáUÌžJ~•Ïãüõ×s„ž|ËɯØa%»ù²Ãºû«_Eiï^§oƒhhÞvñ"WÉ2>ùÜslð¯åóy&¥!_b‡•ìæúk±XD©TêégÆã70ñàƒNß:QGýÄ7|ó0'r³¾b< ·Þêô­uÔo®iEáþUrµAâ›+dÈN®=Ö¦T*!•J¡X,dYF&“éî‡%‰{ûÈÕŠo¿þÙÏ:]¢¶‰qEQØØ!W´ÏårH¥RNƒ¨©Aâ›U×ΰÎÏÏ# BUUœ={ÅbÙlÖéÛ"²ã›ünWU• rµAâ[×uäóyĹ­ƒ\jÐú›ËÉn®ì°–J% LOOb±ÖÖÖœ¾5¢1¾Éïñx<ν}äZƒÆ·è¬J\ F.4h|G"Æí\ÙaÝØØ„Ãaóµp8Ü×:z/óÛŒ[±XÄêêªÓ·á8Æ·Áñà·g¶_ƒÆx(òEcÞoñàÇg¶ƒÆ·¢(žñc,øíyí—õ·fXý^f]¹‡µÝCQ.—^ÿÎw¾ƒ3gÎøj)Âç?ÿy§oÁV/^Ä¥K—ï˜]¼xßþö·±cÇ$“É‘¿?ñ ëë똞žÆM7Ý„›o¾yä÷m7·ÄƒÜò̪ªŠ'Ÿ|Ò±÷gnpK<ØÅ-Ïì… péÒ%ìÞ½Û‘÷ï'¾­õ÷;Þñœ9sÆ‘{·‹[bÁNny^EýíT]ÈúÛà–x°‹[žYÑïµþve‡µ\.·¼¶¹¹Ùôa ‡ÃxûÛߎW¿úÕ8pà€ÓE°Å /¼€‰‰ §oÃ6—/_ÆåË—ÿ÷¹|ù2nºé&ìØ±Ã‘÷ï'¾à~á°oß>ìÙ³{öìqäÞíä–x°“[žÙ@ €o¼Ñ±÷gnpK<ØÅ-ÏìÞ½{qéÒ%ÜpÃ Ž¼?ñÍúÛýÜò¼Šú{¯CÇ3²þ6¸%ìâ–gV´Á{­¿]Ùaµ.C¨ ›¾>>>Žññq§oÝVÑhÔé[ !è'¾àŸø„Ó·N¸å™uú>X‡œþwð+§ÿ^û‰oÖßîçt\¹å>Xœþw Z®ÜÃ:66 vYB©TjÛ˜'ò Æ7ùcœüŒñM~Æø&7re‡5 "ÖlV“““NßÑÀßäwŒqò3Æ7ùã›ÜhG¥R©8}Í‹EÌÎÎ" š›¼[îï#òÆ7ùcœüŒñM~Æø&·qm‡06~‹E\KNþÃø&¿cŒ“Ÿ1¾ÉÏßä&®î°Ñöõ3÷Ýwß}Nß„ß ìØ±£åRŠb±ˆ^x¡éõv׺¹> årš¦µ<6cÐ{v¢LÔ¿AâÛŽëÃÐ.ƽXL»÷b<°'a»ÕßîÉå¡Á°þv™ºR¡¡yðÁ+wÜqGe||¼2>>^9zôhåêÕ«æõÊ¡C‡ÌëÇïêZ7ׇáêÕ«•ãÇ›ïyèСÊã?nÛ=;Q&êß ñmÇõahã^, ¦]Œ{1X‡“°ÝêïN÷äÆòÐ`X»¿L½pe–`?(—ËÈf³H&“PUgÏž5_æçç ÍëÅbѼÞîZ7ׇ!›Í¢T*áìÙ³PUÁ`ËËË]ß“ËDý4¾í¸> íbÜ‹å¡þuŠq/Æëp¶gýÝéžÜXêëoo”©'N÷˜ýêܹs•ñññš×Nœ8Q9zôh¥R1F2ÆÇÇkFGxàÊ]wÝÕöZ§Ÿ–«W¯6¼çÆÆFåĉ]Ý“ËDý$¾í¸> íbÜ‹å¡Á´‹q/Æëp¶[ýÝéžÜX ëo÷—©W/uºÃìWÑhªªÖ¼¶±±]»v™ÿápؼ‡Q*•Ú^ëô³Ã"2Å…Ãa‹E”Ëe„Ãa$“É®”@¦IDATîÉe¢þ ßv\†v1^(õ1®(JËïuk<°§f¶CýÝ)¾ÝØæ"û°þvg™zÅ=¬#päÈLOONž< À€V._¾ÜòÚææfÛŸAm7ëèÎéÓ§qúôiÄb1ÌÎÎv,O7÷ìD™È½Æ·[ã¡]Œ{± íb|ß¾}ž+ ¦]Œû-¾Y‡o/Û­þîßn, †õ·ûËÔ+vX‡dbb…BÁœÆEQÌü`0ˆh4ŠÕÕÕšë“““m¯uúÙa ‡Ã )´³Ù¬923è=;Q&êß ñmÇõahã·ß~»çÊCƒiã~‹oÖáÛËv«¿;Å·ËCƒaýíþ2õjG¥R©8}~5??ÕÕUD£QlllÔlŒ5é³³³ƒæ¦æÅÅE¶×:ýì°ˆ÷£T½”ÇŽëä.ƒÄ·ׇ¡]Œ{±<4˜v1îÅx`NÂv«¿;Ý“ËCƒaýíþ2õ‚Ö!³¦Lo¶O¢\.›#@õ×Û]ëæú0 zOn,õoø¶ãú0 ó™d|{O»÷b<°'a»Õß®»±<4Ößî/S·Øa%""""""WâV""""""r%vX‰ˆˆˆˆˆÈ•Øa%""""""Wb‡•ˆˆˆˆˆˆ\‰V""""""r%vX‰ˆˆˆˆˆÈ•Øa%[ ”Ëe§oƒhhãägŒoò3Æ7ù™Ÿã›V²Õìì¬yè0‘1ÆÉÏßägŒoò3?Ç7;¬DDDDDDäJì°Ž˜ª/•JX]]…¢(æµb±ˆåå塌ˆ÷.—ËPŠ¢ŒdÙ@©TòõªåTŒ;ßc|;aN~Æú›üŒõ··½ÔéØNfgg‹Å ( Âá0 …¢Ñ(‚Á …²Ù,¦§§‘L&mïd2‰“'O"›å©S§ ‡RÞb±ˆÙÙYȲŒh4:ô¿_ržS1îD|Œñí†u8ùëoò3ÖßÞÆÖ+ xøá‡±¸¸ˆd2‰B¡8}ú4N:Y–‡6ÂsòäI,..bqq?ü0víÚ…ÕÕÕ¡¼—õA™››Úß'¹S1>ÊøãÛëpò3Ößäg¬¿½‹3¬#699‰@ ‡ÃY–Íëcccm±”¡•X,Ör´&‹™ï0666”÷)‹8yò$&&&|ó P÷‰q/Ä7ÀßΜŠoqu8 ëoò3¶Á½‹3¬d»l6‹]»vá±Çóźy¢zŒqò3Æ7ùã›ü̯ñÍV ƒ¶¯­·û}b±’É$î¹çd³Y_ðÐpy!¾Æ8õgTñ=è{1¾©¬¿Éï¼ã~ovX=¦X,"›Í¶¼žL&Í%N½,˘››C*•ò͆o>/Ä7À§þŒ*¾}/Æ7õƒõ7ùbܯñͫǃA9r¤íu·¼xHæççqúôéÑÿe‘çx)¾Æ8õfTñm×{1¾©¬¿Éï¼ã~‹ovX=&Œd¤Ä®÷™››ÃÝwßl6;²¥pä]^‹o€1NÝU|Ûù^Œoêëoò;¯Å¸Ÿâ{G¥R©8}DDDDDDDõ˜%˜ˆˆˆˆˆˆ\‰V""""""r%vX‰ˆˆˆˆˆÈ•Øa%""""""Wb‡•ˆˆˆˆˆˆ\‰V""""""r%vX‰ˆˆˆˆˆÈ•þ?2Cæÿ­e­Æ%tEXtdate:create2019-03-28T17:36:51-05:00«ûs¹%tEXtdate:modify2019-03-28T17:36:51-05:00Ú¦Ë-tEXticc:copyrightCopyright Artifex Software 2011ºÅ´1tEXticc:descriptionArtifex Software sRGB ICC Profile †2tEXticc:manufacturerArtifex Software sRGB ICC Profile\~=Ÿ+tEXticc:modelArtifex Software sRGB ICC Profile1(‚¡!tEXtpdf:HiResBoundingBox1080x792+0+0_Ýx+tEXtpdf:VersionPDF-1.4 G:xIEND®B`‚blis-0.9.0/docs/graphs/large/l3_perf_tx2_nt1.pdf000066400000000000000000000634261422157504600214040ustar00rootroot00000000000000%PDF-1.4 %ª«¬­ 1 0 obj << /Producer (Apache FOP Version 2.3.0-SNAPSHOT: PDFDocumentGraphics2D) /CreationDate (D:20190307162047-06'00') >> endobj 2 0 obj << /Length 3 0 R /Filter /FlateDecode >> stream xœí½K¯-É‘9Ï_q‡ÝƒÜåïÇ * I´@%‘€‚F‹….e¡EÐPÿú¶åîaËbïsóœLß e¡ÀsÃv„¿?w·åÿþƒÿæäÿ~ÄÿÔ¾ý—Ÿ~pòxzý%ÿûåá»<µgøgn)×o>¥o±ŒwåùO?ø˜ºüñßæÞy/»ë˜þé‡ÿøÃ¿Hè–ÿv<»~ü—?}ûÇþýÏ ñ×û‚¯ù[ˆYâSý·ñW-H‰ÇÿôÃÏþ°dŸÄQûóÿé?ËþëáÛ¿•ðþo1•”[Œßþß¼ûöý‡MáH2~º¶#”Ê#WŸB‰}%Ë<Šs¾ÅMQˆ¾ÉCß[9˶G’<2ŸÔG)½w—Ó;ò`–:=¹Eàï~ã¿ùòþøÖŸ?ˆV©î‘[q¡»öÍçÐ-ÖØB$ùû?^xù1øG–¾ýñ§oÿéóÁ¹ÿýÛþöÇûÃÿùÇ‘ôêB ¾|*¬lX»Úî ‰-¥¹À°¹íêÔ”YA𝛑ä[´ÐsJ®Úɶ1 )=J–jÜ|¼EAÛöE¡÷GjMØÐn1ЦýÕË=bpKÞYîД;…ü†rQàrç(ì/wDËbð¬Ü¿Oeß%˜Z ¨×=<\)[½R†J‹’ŸÅ1|xøœr‰-ÝiŽ@ü/ ¥Çð¾KÒ>#ü¢0JäK(ÞʼnÈè7Û#UÏýæîáÆ¡~ûñ PÅDÿBBtRÚ ý*…}Ž9ÆpH”qÄ·óŒËoó»ßÿÃnñÑýø‡É¯¹?‚w­w©å©Ë¸È×ê%³ïÁ¢[ý1Í`ÿúç?ýôÓçûUnî%› Ï$JLCÿð5ùÔ21¾ùG©b Hˆ¡æâ¤!É0½e©ì’Ÿidh{„^ZÍÃ"_,Èê"™ãÒ£†–вaëòÅŽÐzÆüá‘KI5õi“/"&Ò&¥ ’}IÒ‡I>Ù˜TH6ùHE<¼Ô1¥æzI¥ “|0Ë%Òß$àä¢4Ÿž‡I>ˆxÈðP¢+‰—ììã%/ß“qŒŒÕ¦É·šÊ|ÉË÷ÚÉ 3ë®§†I*¥_]ˆ˜¤0’dˆTñ”ýÍ”~eT+.ÑËÝXȘ+!AÊùe&u&©…Ò¤ðÅäŠË¾ÄñV”ï!Ù|PR™ƒäÕ0ÉQ(¥Ž°jv¹dHþDI›ÈßZ• äë¨F0É÷ÎlÊÁQÀ!¡"˜m0Y>†Ò¨R©åc½:é]ë°È·(e#/ k]­mantöR‡s*ò¡£ZŠÉ•RKlE¾tÔJù’´hùå,ñ"_’ hÝTJ,s¬³\¥j7Éx¡Z†)HŸ…WócÕ dJÆ—0k¹|ú‘QM†îb*¨®Ò\`’ÆÑŽ:‰EvHu&ùàQ'åoyì}šy'%–:‰&$è(=$KmGf©ïÝÏÎHºæG@^Hç2>']5"8Lò¹ºº015'©OQÒ0ºDB¦êã- P:W7æÚÒ0Ê¢×ñ–‹éèy£4Œ£írPQF?«¤§Ä(Øœ&ùÞY%“ä³|Ðû6Lò½³JrPÒ0úh id…/½H‹ªÃ$ß«”¯a>2>(-£H4ä¥< «eIôxIF—ñ®wSŒQF<«%% £œõ’ # \òS€Ð>5wœ$ÿ‹ÀÚrQ8 ß “Ô©’o7Kï_ÁÙY á¤òGWº‚a™Ž…›ÝbXº?ýF¿^³ÒJ)Ô…¥†J£_5” àÌ’“ú Â’2Éè&ùe!,`l½6Á× Â]ªI•†7¿Güy鸳kO \Z)9útƒ0qI3Œ¬’¼’o ®)’”ÒÈ$fpE^Êd?=c°æ 1XzÌ$m¤¹üÂ:,‚0Ç@,Ѧ%ÍäÆa~‰@ÌÐ F«Rœ£m3ˆ9Òbó–±Ô=)!é£ò ÄR¤dHÔn ®Re2ž¾˜?H æhˆA6IýÄ#ƒ˜ÃÒ æ ˆÄU2_ZIõáFb©a!I¹¤;‰)(&1…E$¦*Æ$–"Á+}BŸH\¥&JÝ‹!ÜH,å./ÅRÛÄRû\Õ*Á$®R’tËߚÄ4p`ScsX„b1uL&ÛÓhLòÃ(c®ÏMá®>QܾÅoá[ü˜ )s®O†ÄˆÒ;Á¡±dÆ¢n°‰iì+"*ñåiÅð¶5©/¹[c0-ó¾“ðšÇ’Õ2ƒ–GydÙ»ò(Ró‘J‹dØ¢di½3Ù» Q‘neVc‚2æLIêBñ7(#VRU¥ºg å.yYFÝBY>Ø~–,•ÅâC 5æÛÈX‚’CBU‚¨,&éÇ]œ#¢²t]Rgݳ‘1÷jÊb‘‘P8P®¡,A x%z.X(‹ÉKkxª© Små`©¦²„Õ$Æ4<–gÒD]_¤¦²˜*&¯mŽç5•Q+"já*'eØæÃÇ(Xqµ°ä&9ª³døC:ê-–að¦Øîä›MyT]ÁhžsD"ó°9¹Î*¯Ñ<âßeŒ'¼e3l2–)F¾ “MڈΈ¦“±KÈ®[<ã›á2ÅçaÂ@É· GÄ VKhD¥£;™B„†©J³\sOBô°I“e4‚äËð»Þ†Ë°Õ¤®Ì~DS¶$Õj9ÀÓÃV1yhÙrÚÔ¢áè“GøfœHùÄ yʃòÞrærHtøkxâaÜ(> {‹7²/yðLØŽP„ÏCK¾É2¶ks9N! VÆÒ“í ,ç'ÛÅAÞYäúÁ“à¿ëG.øÀ¤Kô~³“°_z¢Ñ÷ý-‰WK=‘°¥ôJP@ا9ªÔÈ`­®þh/€¬(¤C~‡(Ôob Gá ¢P·b Å`¿¨«—(ô2ÛØXîД;…ü†rQàrç(ì/wDËbð%1P†ðAæ3–—mb ²K ¤P6‰Æ—ÄÀïÈm{$âUŠ]æÎËmNËmýûä¶ØIn«2Éóô-$gä¶ ?z}Nœýš¹éiC”ýš¸¥œaΖæìçÄÍÉÄM>é§s,aÒ~Ìݤ¶b€?§ÄÉkGoW<<Î)°§7Bõ‹cΞ‚r+Ej-‡7B;Zn“L©0aÆ~úÓdT„˜‡iøâ—?Mæ;-3¶„ûéO#NÆtªüiú­Db[’——Ï#%vôÊ|²·‰¿”ÙÑ«~)kG/ICRâtúÓŠ¤CÀ’ËK&îõô§É8TòÓÍa’*eCi/IæíII:¬ÊŠ›òÂaä¦%·(‰Œ!Ì·†§W뀩iG¯t‚>»2§Ö©iG¯¤ªÔ82¨±âæ}“9𘲦Ί›ŒRgÅM©B©³â¦´³ì´£7?4’Y—³ÓŽ^Òl²ÓŽ^§äËZqSÌž%· ˆ³šgis6ïlYdLÒ‘¡{“O9hG/GPÇŒ_ ’Ü:ý9jOo–YKña4QÉS¸]èŸ+U8ÒÓ|Gûy%½RmNø³´8$e$‹DbÅMð!C€ùÁÄŠ[ÌNBTÊÒ<:©KÕVÖ~^ «µ.¥† I0´.}ôËï‘ÜÄþp)Å*ÍÍ‚ØGä¡´½ÙJ ÄAh ®†;ˆ¥-¦vÒ‚8HÇ™‹ bù[>§Ï•I\¾¥¾t!Kb «M!ŒH,ý^ƒÏgúH5‰»tUʧ MX,Mwô”“ „bá-$æ Mâ±¶ÇÅ^'¿ ‰•*C$&ÝÏ’X‰(Lbþ‘˜Ô&±ôðžß0\¥ŸèI¢qÇ0w!„aÒÂÃýš”× Ã´–ca¸ kÒá.c«(„e€êóáúdÓš†0¿E–í¡/%ƒ!,%.eC 7“†0,C±•@ç*‚°®\Ì`5j`·‡ @rkc¼ÃF˜R¥sO7Óš&0I’L`k‚eì‚>LØ‚I}eó[„`ªxŒ`'1‚9g Áæ-`Nq FoÜ(µ K¢“¯Piï.Ð]ʹ?£°Œz$¹-ß1Ü„]þU†!dÄ"³m°Œ‘%ï–Êa),ã²8uv†0­–`K?Qš$-Øá°PSWý‚°Z²F–jó(Ñ q樒8ìe¢#ÅÔ‡8Àf01‡¥.2 s˜ª‡å°fá°†*q˜cA(¦ÆÂ(fxëZK¥m2Ky‚b݉(nR5–Å(îhí‹ÝžÐX­Pawˆ‹µ‡œžÐX¯Ÿê¼…1!œa¬¾gaÜd æ*9 c5³0Öüd«[«Þ‚yL+™ÇŒOâ±ä…4ø•ŸðXGÐðXU Ãc~â1Ç‚xlLšÇœï†Ç +\ë˜YYënÆðøèÙ-ŒurK0C†O«i2[ÆÚE ¡'ŒÕ´gaïpç­düt%lK(mêF^íJ–y´]̪٪iüd{(Á#ËùÉv5M§wyþ…jZŠÒ;Ë,ÝçZãf5MØ\¥À| ;¡þvÔ´«¥žHØRz-( ìk©*5so×è€öȨ*òT•VU8 ûUDUŠÁ~5MW¯·¨iД;…ü†rQàrç(ì/÷Ú¬šF1ø’š&£¦„Õ¦˜ÕlSÓ8]j…²IM£0v¨i2%”Á…”{•YÄÇjZ¬¦ýåŸw©iséeV¾ù^$g› ÑýàoÐ°bŽÚæB] 7ß/ÛÊt:›ö„"'Ÿ{ó’É{Ð0ësk¦Sâ\¨+5Ë%ì†Õ±cÚY"-ÔÅúÐz¬C/i¸Z{uu¬ÅŠɆAÒª×é"©Á%ïækò•9 škgenS§{½díC Å¸%Ïuº³YJülãRò\§;IMëtKQ.¬­’¬é”(2CwÇL]ץ腺õáROqÎ%‹ÌÐëš©ÉØ«À=3Å‹Rõ:Ý(ƒÕÁÃÇQê\§;fj}HÇ2Þ…Ò” ¢¤“aSøÒ” Afßþ?拥ͅºc¦†%Ø¡õµ±t½P×?d’.qœ…"©ôÇdMÂJ­Ê4{N¦úX¨K±®˜¡5´;™¡KA΋Õ)‚˜¢ïÇòØŠúQAÅäº4¶¹~´zv!¨y}õÚ‡@sãŠ)úQ;yb/å|ù$¬Þ¥·˜sÙŠ)úª›ö¥—þÜg.šiÞŠìCPN!;ùt•g¦&öé*WOMìÓU;!jbÂé=®™=:³ò “ ½yBIĵhIÄµðæ µ×¡Þ<¡6jp”AïêjAmg©UûHAïÌ;(wijŒã𰨏 =Ðâ8a#X]+ÖÇ «óû±gŠq´s_…KþŽãŽï·åþ28–ˆbíü¬PŒc±u_ÎoŽ¥K…nîI08¦ß„cÈ{’­p@UËã±ç²pë7KÁºíÙΙǴÛÂòXmf`Ó¾æ1Æ„R‡g !g¡¬t]ÓÛÄ<¦• Ìã7¾@r~ïçò˜vr[c[H™ë÷™ÇñáÖª½T–*©ZçÉㄇ³ßdKY4© ­ßpL‘f{)2x?g»Ó8æHŽYk%³›ŸqLéÑ8ÆK]jÄôÀŽ%(/c?7ŽwWÂÅäý'›ˆ'öç nFA£˜¥`F1yz Æ&g5ŒI1`“×›aL®h‚1úÔÔŽM cRcÆÚcoa¬½ cNp ¦{Û¨®K/#Å8z´'<î`Ï\»a€\£S; å#…>N-` Ëk>½éÈUÚ³tÿs½‚²`Æ LJ}2Kcy+HòóPkc6%5m êÇ&,côgØ ;1ÇtRÀy:_|­?ãTŸ1Pƒp2ex0×ùS¿9ªÜ·åùûßý_Øæ)kƒ%RXQцB2=R£Ç!o—Óý3é èÓ3Nžá«„ýþÿùÓ¿üýïþÍç÷Ù‰†N¤ÌªÙ&s>üJBãæJ“”/½Lè¿ùÿî~÷…"ütN çp2Ç„àÓšðøÚÃX@íÓòmwùâ¹-„QÆÙ:n9­Å^ê@Äi8ó=bÎ:#£ÀatÇkU‹¢ªÓℼ狞ÆFœ&C²ǽå±9t›ˆ † Kod$s—¡™ÜJ×á` e:þŽ¡L&†r^štËd>¡œ%B©¬ýà å"YS­ceìº9Ö(œP.Çb8A™´ ‚rÇò;©ÁS‡$(C¤ƒÚÑk”Å$%QWMPæ}»eóA‚2‰1ÊØ‚†õ RÊ,“”Y*"(C‡Ç’ºV£¥2«5„eîõ ËZa"(Ë;+æB³L–W2:ð-“!â`¹ÜˆÉq.Õ2™µ$b2ë!ÄdÖý‰É,ð“Ç^°´Y&ãƒ`¬çsιvÌ¿U46XÎØXè ζ¼aÙ£—:bi°,‘1ÀZ>e°L .Ì‚l¬œ[õÍ€9K5ŠÇêH3öab´6Çx fIB•ñÆS0gœÛîëÔ« ˜é@Df«Hf,mÛ€Yð%‘ ° f «æŽSf©þX;6‡uÌA†%B­ÕIh0ÚY6wÕdÆB¤ŽóÌçÚ&F3-)b4ÓàŒfCmÍfhÙ½®U€Ìf°™ÍR륛ËXÍÔ L2Ë7óYq˜Ìù1—÷1”ËÃIž¯³WÊ4™a(gŠ ¦”ËPîRe:#EL®È÷µß•™LçÓ9AÄdʘ·ÏöÎLæì$&K¦a]Ý\(ÃL–·œTèÕA“±pÚ#)·¡2z\HbsxÅT¦ ŒeKcù,'"2—9ãtÖ Kä ™kÎ%ˆÈÀ–´¥5¶&"sÁ‘I9Kãl>Ì)Í$2õøŸÖà<ĈåäFÕZ"þœ÷ ¾ó"ħáïñùåC‡;S·%ôFˆ³Ï¶ aØ©;™n‘àgoˆD°rœy´]ã4¯(У¯ìÕ¬X“…³¢¥!î¾J`%Z %|ê”Õí× ª–{BbK\ØÞr)EyÀ™Ž#Q7ioC¤°ß¢Èä›g"ñI&[9Žãð=NW4ßÇ­|2\ÚZþcºaÊŸÂ~GùH˜òçH¼¡ü×ÀV—?ÅáKš\)Qfú}:^¶ir&”]š³I“ã@vhr·‚à?èpßÑä’VäþºïúA‡i<Î€ÍØ»-SºÖ„*c#‹ƒÌ6»?[£v8`y¢Ì8œÌï§Q{piK—*|³óZV*1ãÇeyë¨mXQY—1s¢bòmlô­Èžé`ñã°ÈñT â¸{F’çÆYQ£#=R»°5¢O£|ï¨Ç8ÊÌãôÇ9ÝÆ¦‹Ë-a%7ù§|ö¬ÈÈ௰ë86jÖdbé ¼Í[…$qún1Êð6EU.ÅØÂj;€³&‹qžK5µ#_•—;2jMã(©aSn }…ŒÇÆ”|ÖbÞª'¹ìÆí,³‹1Â]~SK|=‹º)FŒÊWan0Ñö³óý3b¼üf·ö˜ÂÐ-ðŒ,5sŒqIË¬ÆæÊ=à+žÕ˜O£r^Àˆ‰ss’tjÊ{1lX+¿êxRg5æåb¬ã¢–Y±{FJ'O)wD*X3¦4²ízC†<¼†ëÌ×äeN,¥vž_m _±aOʸ¥v‡|5å¯ 奥`Ít9˜K˜O­õÐo æ6vT×Ûêu4æ…ªÁŸ—BÌGtçvxƒyì¢B³šÂ…Á|€`å²Á|ˆ7±Áü¸Q«j¨Á<ö¸àµu§.s^ªJÄéÂGë!γ 9ï ‰AXq^K8¶ÒÎû±‰èM çq\Íó(kzÛ` ôhwè!¦3Ñ€Þ´X½´é–e¶"4AÏ"¬=9C•9r†@/Æ„ý‚s眽ä~ÆþíƒHzÑ]O¡Ñ€Þ¡‰tÜÌ ·F=ŒØM~ÀLƒž/{3 £‡«×­øèoFMzÚïlXol„z>«Þ¢Þ?›g_Ψ§Ã•-êñAÏ0õ2ÍÁ¥@íh;šô°eù¬pz±…Ž5ÌyÒ ˜òØ ˆ™Ý\Ùä×ie®"cÆCƒqØ-RN_2‹;oMdÈDZ?rôþ·|‡’ÔúŒñ!Œ í¹Ú§f¼ ñQ±,oî¬gÆÃ˜°¨c<1>l/±Î•QÌxÄââWW­K #@t¬ÑŒÇ|%c¨º ƒ9t@outšñ¸1ck÷Â&1e }útãaLå|ÓŒ~,E*KweÆÃ˜°µyMˆñ¸Â±ã@Êc”«›ÔâkĪ?î~¬§ ÃŒ¿©c‘‘ð\Öň‡-ãàÖøñ0Æ”Ê1Î!ÄÃ"¤5îÔ„G\›ž Âß’§ cÀ⸩¡2áGÚ£Ä7¬©&`(_Îãtˆð°&àà4áa”æóÑ÷iÂÃ(SR™¬©…&<ŒîZˈc¥L„üAjÅxk”z;ï¤`ÆÃXŽÅ[Lx˜$¡ÓMø0†ç5^Ó„‡ –²JD#~øŽÒy¼3FwÝÆÂÇŨ}B)Þ0céçBæüݨ@c>·‘3èaÇK­v5ü§òL¢ÌÆ>/HÖü –ŸÆ%Žøk^ç8õ]Xç_›äÈ'¡oñv®tü¤Ò¶#œæ±¨¡H=œ 3òð°Žã¼7]næçɨã{+oùÑö(P’g¶›Gíºmí ¹°Jž=‰ÂwµOéúZ±|<ðyx~u!2ÀASe‚%]Û§ÂÚ.Džmö¢Ã–"\DØÝfuzæ¹¥ãÖê½0•pÁH_wYÛöE!–òpcYm»El£ C\HŸqÀº‚¶í¯aî‚â¾’rÉsÈûKQ0%OQxCÉ(pÉsž•ü÷Ù<Ä &3+<,ê”!oj±Ü庯+HÆud9™^¾$ÿ¢@¢Ãºoìïñ·#8~‰ºÉ¡8ìÙŽŒ,ûG¡PZÆvzxÊ=o§ÿÑA À<¢~ûQIWTô/¼“‰\j ý\¸È#F™”{¦Æ‚MƒyFæ·¿ùÝïÿá·éýýf@Í2U—Ù{ï7߬7—ßÖvϨ·ý¯þӾ͊üu7NÄiŠëà!ÁcS‡wÉo¸uoÐåÛ<¼Ë¥€qÃäáiÁî«ãÎú8®®9Ž2òX_Ž‹?°1Ì¡"6‰Œ×ú<º«ãÍ(ÓîÎ ¾«£»`»BƒØ|ÞƒkïL‚SgwE8 殓8l×í80é× )ÁÁ’li¼æDxÌÅÛZVçtöH¼-X„=»x:®„á3ï8±Õob9òº¨'„ë†|D®Ó1'Ö¹¯éhFuGÞS™Õé]xMA>Äy|—ükÆD¡/$?'³SØtêpÏ•cœò4ðê¹Æ‘r•¬ñ²ÁeuQ>©3,ã/<Ô9UÔU9qh¡¨ó»ð}tQWäØ<¯ê/óZUxY“º$éÔ‰iê/Ô(õZS·äà5]›:à 6É~Ý“ƒ/êìéê/[µá¼=îpâ˜Di-ý¸Â &Õ¤£S'yÅὉØ|ÖÌ¢ã½:ÅËD`Ö€³fR㬨\U³êÆXôãþ&^PGyÁ¦ª_ ê,/“`œƒvÜàdÚdŒê0/¼¦J3â2Ÿ«jÝ(Çx‚ón›¦ItÎõÊe‹ç©4•ó•°\âk,7]&Œedô•IŒeÆ9s®oQËe]±‰Ëý.wz¹ÌŸd.·;Žókó—ÇNWƒãÂ6âqeñ˜¸Á8¦ö`pœUqSS18Îl#EaÆ*CX‡Ì0ælµ4V¯1Œ3uW–Æú5Cc]W˜ÆáNáDk)¬³…(ÌS8ßáK]¨¡/uH†¾‘mú, …#“–(Ì_d s,™Â41¦ÛP˜Ãc ó7Ãþ khM o>ÛÖð׿7f­æp¤baÛq®1 éÌð8¾itÜuáÑq"ð0… ª5„ivl ¬KÄ0˜š*#˜¼†ÅN¿F(ö 8ÒˆPŒ%‚×™Äíà~o£lcð6†2‘·ñ`—ÈËï1yë³pû` ÌÝ$C˜*¦0¿Çn¯‡Äœ.¦p§q/A¸1q‰ÆTF ãözHÜ>;JS™j´¡²cb•—5•ÙÄXvw›Ÿ)æ†ÆüÑØu/ù›LcN1ÓØÝ!ìø:MšO Ðf§3×ON(þšŽ÷¡ÜnŸ…¾Å÷Ø!ðJÛŽpR™zWòåH˜y´]…Ãý§ÇQ˜+kéÉöP‚g¦›GÛe@âUìôä+"`tqœ#Põ~³qw1NžÁrÓ¿%ðj¯¶` Š ÅF•žrUн ²R…ü)¨ßD@ŠÂ;¤ ~9 ûE@]ÃÔõ…ûJ~È%Ï!ï/yDÁ”S0~ÕTR ?Bæ÷´#ô’Õ9Æ5‘âXí{L×"ÛÚX¦¼¦kÚ’’ºÇw)±È¦¿˜Œ+A}1MQ #Z-²G푮ɧ©¨»qÖÏ‹º‡Ý= —öhÝB©IMMß0~#IMM S=$5]B< ‰mF[Ó‘hÆ«‹¶¿×R)®¥þZ\ËŽ< ºÐ³3âšê˲{-®eÿR\Ëþµ¸–½º%ǸùsP×ä°+?‡›¸†£>ÎÕÆ6ñµº–ãuIŽ@|-®å¤®É±Á¥×âî-y!®å¬.Ê™‚Aί5µœÕ 96Qeþü+£€OjjÌbìçsç± ãR_Â8qc Ñ8’³…iv‹3މŒã õv¦q ¿ÑÛ˜•‰hâkí(fK¬«Dã®&ј¿˜ÌŠ]Dãàn–/éœg÷×4Úél¨Ü)ŒåÎx%,kG¨¡2gE=ü»º8šñ益b¨¬pÊí(s²ºñïêzØWEÓ`™¹áŒƒ—pN\¦’a.k¿°Ár¿Ó˜"nhÌ`·;ŽÛ8®ô)Â1•¢Á1ÇŽq\©kbkO¼¡1¿Æ8&áÆeÍ^æ2¿W‚@6ÊmŒæ|õ572Ó‚ ‹æ;‘yüDDND dmbß1Ì]ŠÛËQ1öª)ˆ0‡=ÛhT¬›†÷׃bª1<(&¥Èp8èœàA1Í!xLÌ aW⎣šxL« iÀcxÌ5†¬9œ™µÄáB¬% ×Ç<%bÓ'Ã4µa Ò…õ4Â@¸0¼ Â…H«œ_3˜FƒÌb¿3‹y Î,Îwó˜žYLfqþ€Å;fqb±8¿f±žž'Æ4¡ø éK嶬õÓR[ñ‡³7QNO#þZ—Àú½RÛ³ÐwxøŽtü¤Ò¶%œV®#.gÂÌ£íJnCe©Ÿl%xfºy´]jÓ)^Åž©Ô–b—¶«ÏµÆÍR[ÂèØµãØÖö7#µ]íõ"ÖlAqac{Ué)×ýo{Ady¿à‚(Á…¢ðÁeDŽÂ~©M×°·Hm#@.yyÉ# ¦ä) o(ù.yŽÂ—¤¶ˆsû[³œmR²Ijã@vImÊ©M¦ˆØ$¶ì¿#µÉlA mùçm“c{\לš~ÂmÃD ù:H† zîW‚v!D=Ý.‘|º4)1_·‰`Þ5a(‘\•BÃ4}¡b\ ’BíÒ5¶v¿­jX%_‚~/çë2ö%”Ü®»DŒ ¢ãÓ%[¾Nš>µRȉ@~¾"ÓózÎÕªžÆ•j¶KèPj»îY¡4rc¡4ã< [»NûAèâèä<ÐB@Á½/dŒÒ§AO¦+¦çG•4>Šêȉ §Ó¸ý<åÇè5Õ³a<2¾«Š™ùY%ÙƒR9¨*fæG4Ÿ Æy òµFêcò"ò† JT4ÊšŽI2ÊšªH5ݤµšÈ K¯fãÊÕ_ʬ¬élʯ]¹µW®NT!÷go1¾\54¨Õørõ{•^%O¹£G¿ÌÎë]aëÎ:o1<άc gFa¸Rb­Æp$Šá0ù=™ÃŒæpç× ‡µ9LÞ,æ0Œ ˆ.gâÆ61S·¼të2©æ SoÁ<ÖÝp¹=ñþ5ј˹W.Ù ŽUËELáSÞqò鈗>ÇáK‚œ<Â-çÖú6E΄²I’3¡ìÒäL0;D9ì­{„ìÒ¼àæcQ®éýoÿú—}ûß°ÖEÉrQï¹ùž–åÆU÷)±,w Ò[ªZ•#7aËN»ƒ½nX-'-Ë‘jÓrÕ^=ClÅ)§E÷‰\>?Uíkàð«ÓÛÝô ݆+D´§‘qTÒkØu¬›ã…½ e­%ís  {Ãõ!ZQ3§Öò96%ís ©yÃÕ!Êç :. Ñë&Uì0ÀR®rvWµ«A—E÷b7yTÖwäÍí¬»Öž•ÔUc6Uí` -¬GÇvLìaPóåŽ{A´‡AgCr¼áMÍë{JäÖÁájíaP…Ô³c?0ÙûÉVI—Ã#ìšRrÜx”h/%´TÞ馊+@´ÛW‡\éqjò †ò(h!¡ãöçŠDÇÝzŸ›¬UVãt$»£nú“Ò,´7UÞç¦Oø}1?Û%ÂtáŸ=ëÐ ºä´fúfÏ6_ÞgðKŽNÆoLlÓølkê1Ž\ïNspˆlÓ–^Y§ŠÌ«(Áì.6&à3µ»š¬…6Ã_î ˜¿íÎ_R} +³¹² §œÀZV7ü¥ú}ð÷ v©%1uÙTYƒÓ°fúr›fú¦v}%Âø2¯¾åøòk _~á[~s¹G°ðÕyÀðe×;A‚¯Þ÷`ØËo1|óºÜ_1tÙÆÐ%ÈPר*knʶð›¾6Ùý´êfœ®ìF`w/õfÀ«…{Ã]Ýp vƒÎ 3ꥵ\Œ]2v™äÌßøzLÇÂü2FyÜy$ë^.‚0ø%Eî6Ö”u$ºé0€ë“q/ñ…Ì-ž\>I¯ƒ Q®ëv~Ž€õC;&€Ùf†Â4Üu/Oò50fl|b(ü¹ð“ï¹<,göò×ÂéÓa¶1„IÞc§×&381p Æé§FÀOF¾‘Å••´û8~eÝÃy‰œË§”…Ú´¤´q?ݼG?Øz‘ÜÓìñÞåSM»¸%$nrš}¶]Î×%B: !Ô3üì ‘7QÍ>Û®ªqªHð³¯(k÷eãbkËîKå*6»J»o¡„O]¹ýR9Õ~/Vl)ÆûÛ/¥)ª‘Žƒ&wiî–ã°ß¡±ä›ÀÆ‘x‹È’o›‰Ä46]×pÄKX7än¬#HS8ì7Ô€1¤45€"ñŽ0ÛãÀ‘ø’ÎVŠÌÛjO2Mûnš3¡lÒÙL(»t6Ì­âj…*ĵïêl¤²ýuß]nSúãNñéh3ï îß[wŠKcÔ“U1j×C#G«µï¡j¯¤w2{)}])+ù,Ä8nŸWŠãÎ!}†«Úÿ0 Þ5åwÈ™?†ýq“8ÜÒô±¦=©óŒ£k×Cš/ÈìňÑ­®Úp˜Ö÷‡C~Tƒ÷N;y«Å¨½‘£á1³?nǹC:uÞ+ÇC¤5ØbÓž‡XÌ‹u«3n‡Q_Þä1Çwëqì‚¡7ƒöBÄ4ŸiïCLüf÷ÇÅá¸ÖDå™Ço‹Ã§IŒÃÿIfT¹q¸Î¨­ðûë«¥üÐVmÑñ÷’vADÏiÎÚÁî‰Q>{VWvz‰±ŽCvfu£FÒÅ÷øš®uúâ{|Œmêâ{^“Î÷ÞCÖ Xè{ïæÁ÷ÞÛë¸èÞ{)>úÞ{³³ ¿Qþ Ú´Êß›…÷tñ½ÙÑÊßèãJßÛ7éâû)íð}÷xAAˆ®»‡¿’lê¶{Øtºéº{ûâèÎ “Û®ycp»öܱÇÀ]ù’Nw¡]‹†ÜÅß3“^ó:3øÜ©p@nÖ -¸ÝàŽÜñÀ#—+<êçà1²ø Ü5¿£ÿ€ßÄoƒÂ7ïE4øæ:Ïô¶M0 c‚0~3jއüŒã!s,‰ãt©ÁxH†ñã!q¦ÆoFÂxüã¬ôž³Dax¸÷fž›Ž8™ ôÀõ†nŒ tÏb {æ2Ýô­LtÿÑM%g¢óÌÝÜÑIâ±hw M†íî Ò݉rÿ¥ëŠ>/úY˜_Êå\‹ Ëùj8ÃòÊ#tby6Ã_†ºñÆÕS'ÄÔ›ˆé†Ï„tso´AºÅ61=}ÄtÓrêþ¨;3œ×Pa¡¡Î»-Ôytc¨nËTÏܪ뙑OTÏO`Î=³œ þ`¹a'³Ü°“anøÈ07]'ÃÜ æÁž`ÎË,7S1b¹§N‰QÎ3(ç‰A¹3œ'”»ÆæŽâÃ$ww€» ¿Yg~ßl$v3èÖüž­ƒ±Í »ÁözpÍçd\³&o¸më\ê¯C|І5+ò»ŸÆíuøkÞc—gäÄ:ÿÚ$> }‹r¥ã'•¶á„4{ %ö•0ó¨\ 6]æäçyã{+oùÑö(P’g¶ó#PàØdó†\X%OžEá»TA¤ô“­F\û–UB£Ò±¶ð×ÖƒÇbZðå3Am—Ï{±aK.ìn±:=óÆqï^Á/5ï8û‡CÖ¶4lc1Šô¨ÒM™(mcd€,]èqàGAÛö×0w­ØWò#@.yyɶÄ%OQxCÉ(pÉsž•ü÷ÉŒÑ_i’u2HË=%Ìê]wúºHȈµ<:¾`›Ó¯(Óq(E†Ï.aqÈðŸ„_HÄú™š¥êÉ'_‡)”¿û Ž·”©—ÿöÇTaþènü's§•úxEEÿÂ;™ª¥–ÐͬÆüD&޾<¹™®`g^ž‘ùío~÷ûøÃ-BRð=¬}˜’\ ɵÞýØùÐdŽ-s‰v_‚Câý—?ÿi߆@_ÕM¹c:„ø ᾩãˆrá¹b›Ç9&Hû‰˜k„Ôܘ 7ÌÖmãH7WJÁÖýðȸBh¡É—Ö´¤Ïóˆ:. Ä ­Ë ë#aSçÁæš+­¥qo¼S·À³”ì\iœ:(K¹KiÇãywÝþË ¼Ë% †`ÂÍ$pä4mRYZÍÃ2&r^&bø`ìqëv?&šÝ ü’a2„ÁŒIÙ›d×\ü Ûuûn\h=D)“‘¶ Î%²ŸŒêúºLE}¨˜-æ&‚Mø*q7çÁD®T?lÅg'¿ß”âB꤉äÛ7qIÉ™aÐâÌPS Ã6&êY²v¤A©Tžñͬ&Â7[’÷$æîÿÀ{=ÎlÎØk3£¨K@ð!)Á,CüQ˜EJ„÷œTÈ–fFu Hw¾ä”f¯ª:”hdT‰˜«L›:•ïy)…,õnØÔ= ö›MJdãÙÔE JV*ä<2¸©c‰`kNZMu«_7Œ¼¯ÅÃù7LêX¢Ûkm¸Bf?[–ÌŒy¥Ýô㮓eÑ©c‰ð^’ÙÛ”¦£4›³usÆÁYgm5_[WÎÚŠ…ÿ¥Å6jÁ¸ꪭ2 €“¥'4Žám?n«á•(Aç0lê\"رÂõ0ßSçÙo⌧ã¶›+QKt{¯ ×Ȫ­Xž.?‰8x«4Ìô©±ÌgUJbvëX ”°¨æm8€c<*C»Ap{mÀ4ÝšÄky,³é²êóÛC¤õA¯±åQšÕ*æµØ²4ñT|¿ñ6áHs¾Y^‹IÆAEºÓ~ãµØ¼ .Üy-—e*=×~2¯é-¢µyKÓZ!³Jõ7Z›×ˆÖÖ¦i xŒ,·´Fx‡kÐÒÚ¼G´¦Ä«ÉB¤6q$R[Û 5 ¥FÞim^ ZK¢Zé%´áaZÑÚdÑÚÚ4­M¡­Í{Dkûž¦µ‰§¦5LR!ÜZ­Å&Øîbó7Zó{LkkÓ´[•ùMé£g&\Ã$HŽy4`Ƶµi\[›Æµ±®MTלtƵypmÞ#\›l!\›o¦`?µSŠ$bW —¥í µnÄb£pDjúØòé„%fs}[Þ“±yjS#l Rc,ù†m™úJˆ¥-›Æ¶ØŠD3­Ñ a;ae…p)¥;¶eXßdVs 5¶Ç´Û¥¸Fç„móI7éIO[ÝŒ ;aÿs‘n:–º6-†£C&t§òð}´'í„S¤¬ÜPdÝ sðS•2ºªK(OÑ-Ô•©_]%Ëè6ﺱßT •éoÂ7ÜßR9»û@éKÑb¸ðÍÕ„ñ-¶.Y¼9ã9Éš>g„ïìc‡Ë|‹Md9zw·}Oã[â"•¦‹½ÜðŒÄõ¾M†¾å›Y¦qiì&%z›\!z‹­ÈÔ©®ù$ÑÅVª+yl bzã=©ó2û÷7z#u­8Œª-½%E†ÚRråFoJÃy)U}Ó ÞòZ“Þše3¼¹\ÞNf’wíoyOøoèF‰×ÞÖXÑmB#t£©"Šsð0Ýy¸i´ùåø´ ñwzbq¯ßœ¶á¯éõ‡u§ù,ô-ŽÏ~hWÚv„“ʔڤb 3¶ €¸Vò8ère-=ÙJðÌt~´_Ô)^Å®Ÿ|IŒ.Ê( È¸#Ëhe«þÓJ¶"=@ÿÒ¯ÖzqaKñ• ¨°QçTé)×¾Õ½²*…üªßôGŠÂ;T¨~Ó9 ûõG]ÃÔ=pûJ~È%Ï!ï/ùÑ–¸ä) o(ù.yŽÂ—ôGÑ™éŒE‚ÛôG d›þÈ¡lÒ9/éßød íeN‰bk@¶À÷O¾ØIàÕN ¹€ñ‰#OL2Ń˜%•0aFMãs½¤é"Ǿ˜xMã°îU†ðs‚MÆçHyL€[Z"Q”þœÆaôï ¸Íozø’D,ù8¦ß)¾—òÙ±”rØŒ¾§ä¸´¾'ù‚ƒmæóQ]8S“YÉ‘ˆ‹ç,H‚Ì›Ëð$¤çœÅ!´91‰Kêæ‘¡Ôù&Óë2m,ða¹¸cÊ•’ö;`Ùs•jbiÊFà“‰¾ËyL—qø†øÚ£zÑÝ|¯EÏK2!ñ/uóÈOÒÒê865uóÈлJ/~¨7 ÷£\Š þ‘ërD¥jô½,ÙâûpI`HGúžÒ­R=4>ý°‘Æ×döŠÌGºi|U&éRyúp%¥f4¾ Õ|ùZR7Ÿ“v%3ÏQ¹ºÑø”d•ºÑø‚|dyز#Oò_¦ÂÒ(ÆUñÎh|J&ÊÎh|JÎÊž5>•ÇÙ^SWX[PWÀÖ[æÃ}s0_À8º„F©«žm"©|p<ÆðCØ®«G`йäR‡Èȧ”²±Jà8)Ɉn˜ê+‘Oz ¼Š 6+òÉ×8|9«ËGŒP™³ù”™³º}dØz8Ü8£'çŸïù˜Û­?°ŒÔK¦ÜÀݰˆít2¸[|][•À]¥!DŸ ¸ëpeµ%¼3¸+¶¬Jú¦ÎàÆu°•]Lî ïO„ð©wE_&ÓÙå2¸‹@ÝõCapg¬øèÒAŽî˜Á î8aÜzÀ:¼ Õç9¬&pK‘Ñ ƒ›´ævJ2€”xö;·Å¹5®±%q;EaYÃ\ì>ä› œë}¼-Ño½œcq‚¶Ø\“ø×-´%eÒË=o',Èìטšt>ìrrØNwÇ6냌mDS0µÔOÆ6ëuŒm /H]l®–¶vœ·c‰c›µ<ƶIÃ742Âj n¨0’޵¬†Á- £ÊÚ¡ÈàNXŽƒ¦³Õ¤óáôV‰R»·YÑbr³&Êäæügr³¬Èäf¹‹Èͪ"“¯U!V\cqMn‰Ê›çhˆÉÍZ“›U&7)“›•7"·ùd´BŸJ‘…WbY&7äO™Vº¹ä”ÉÍ :“[l­JÍe¿Ln´‚"½Ý2¹µx8ýfI¾¥¾~Î+z}2Z.OÜ8=økº×aÝ)ô= }‡‡ñHÇO*m[Âiå:zs&Ì<Ú®³á KúøÉöP‚g¦ó£ýBŸNñ*öüK…¾{pÊè@&i{…¾„ãØ…ñ!¢›ÿÛú®ÖzqaKñµ ¨°±µªô”«JìÅ‘{8äýrÏ(9–{( o{FXîá(ìút {‹Ð7ä’ç÷—ühK\ò…7”üˆ—))‰æxJÎ×}'c­T?—P—Ü®ûN² Xd‚wœÎS i}ågàšv•’¯CŽÆôÌ ' íæ“"Âácî[dNœpÓµÒý”ìJÕ®%Táú\IÊuñIÆz’u2¢9Ö´ëAl2½•YÞ˜ú–¦]b‹¾»8]¥µët£<ÎwÂÜmÌ7K×®î+£6?µ&™¨_Ÿà½&ÿòs`éÃõÀ/TÌé ›ÿpÚ ›v=ˆ ‡g©~ÃÖ®ކ-¦æd¹zíz0ßôÚ÷ 6ic¹ÏMI“ú³ÆbÆíe¾»%„3³ÅBªKxgf³z»˜‡qžÌwcöÀɿ戀™Íê3ÛØ¼Ñùºkyº‹ÙƤ‰Í[L™Ø&šØ•Î=df³^ÍÌf½š™Ce¤¯% Ìló1›…nf¶µ‘ÎÇá³­Më|üIb6l‚—å—gfcç­p>µqù3›7ì2³˜m¾I̶ï‘ÎÇïµ`mÔù ¶û[ –¥=A·´)Ð9ÜÑòã¼h0º;ÆÛ®·ÕT-¼¥ oë@AoêÉ‹m®F2ðÆkc»_¸Á£©Q3çnðÆ‚—:ÕS†·»…·±?¦ o§÷é²¼±kݤŠÔП±»-íú»u`ÙÝíÉxÛtÌn”È8÷ÒßÙM2 »Í°UcÉr7v«œ7v·Œ…~õº×|(ºÕúq¬ÜZ>gÐCT¥žÍÞß ›úƒnþ&³›ú2oþ¦…76w®Ã[즒y‡7ÛÞXêÖÛZÎfàM]§7uÞÆFð66‚7u¹ÞÜo¼+6“†y"‡a7¿eÙ-nK75ìæ¾œÙÍ6f·±»9.–Ýz °Ø­¢÷i­Of'ÇÁzpýLoçøsúØaß©ö= ‡ŸñHÈO:u;ê.[½Ï<Ú.·á~MÖûøÉþèÏ\çGûõ>âýäKz_®Ù¡‡ÇP`«Þ'lŠ2&~"äÏH‹»õ¾«½^dØs%Ý¢ÁööªS”ß¡øY÷á÷ë>£ìX÷¡(¼A÷Q`݇£°_ñSuLzôwH~3D.{ú ÇÊŽæÄ…Oqxǹ²Îy[ú‡/©~ò—>´œ[ëÛd?e›îg‚Ù$ü™Pv(X²úY¼óΈ”¿vé~ÿú—}ü°˜æòCàb–(“b-"JNé~Ýa‡ß!B´¤.9‘ ȣϭ~Ø*ë~Nºî>‡åMÆ J÷Càý˜Û´œ”QÈMùZ®/u?™4*ÝO¦Ks6>‰»XôÑB9˼tú¬qçå‡à³…ZuzÁ±Ã]~œÙpË¥£”GŠçf…†Éè ݯ5§u?\rNëZKZ÷#¯á¾KG)Èê²–F¶î”ð—åwAjÔp·ž´ð$ÇŠ„œ§­²ð'Å3ŽO[Ç,—Ž‚»dâ8×8ãæg%üIÉâÎéŽì®já/ÈüL"2Ü%’9Z÷ê·ï³sÜ®t?ÜœÔÇS˜ê’ý’Ï%Íi`ǵ+Zö“bŒK×è¸uå’ýHê¡jÙÏ?šLÝ— Ñ£cÙ/JÛZBu—P²ÛqùŠ–ýB+±Î%Ç=9–ý¼têqú÷{JJö£ÍžÕ^ J¤ëٱ𥢧¹¤ç¤…?R±:._¹*ì¸cÈçy|Ìîµð'áÍst¦-é-~$gõRµðÇÙ‚»W´ð§Ã«ImñëH3Ó‡‡I é~®”ºv)t\»¢u¿k7n‡E[R¯-°½U#û]çÑöî^Ê~]šŽ’ýHJì½²ì§vøÎÎR 4¼øéÃ…>¥û1¸ý8è©£g ¸¡ –k /»H{Æ™)Ë¡Kà†ã9Ž—üÍàîHA9¶Î1¸eºæK( î><Ûam'p›þ…À=v Ôã$_7Ö£ŒÖ:²›ÁÍ›Übó!†§à†¿UÆžI ÜRß’ÌÁÊÜÃàÆ?®›rܨ§¡øµõœÀÝ@Ɉ¹ÑÁÝ0 ÎØ[ã6ˬÌm±¥’Òâ=s[lnìϼcNhéyÂ챘Û8iP’}àž¸ ›+a-yXà–‡Ròq-M`p7F²jæ>ƒ6·Žrfl7 ]º¸¹g€± ‘A»ÔyÆ6 Ð…æçéŒmc#l›ojl‹)ÕáÎ7lcÕ^’áæQrG—¹Í\ëÀÔ†-ŸÃ ¦vTÆmWýFm–I˜ÚÖ¦© › ¿ÖLm±IÕ9v‰µYnglÃæÏÃÛbËÒçʘ§Ü¸-¶Ôd9s›”Æ6+=Œm|RªŸ¤/ܰ]1 ‡O)\Øæ•¥?Cnàq©%OÈ®ƒ ¹±7¯' ÞÈ-cË 7r'L¦ z#·ÁŒØrÇÑšýr gŽQÃÜRGóÀnäöå<^óFn©šÇV2Cn™m´ó@?Cî$HrõÜjÉŠ!7¿I¬ž ¹Û¸roVK‹ÂŽ1ð¹‘;»óØ“ºeuLêoèÖx&rãÄSœ²rCw’âx:ä6$¶è}Ý̧ѭAËè&5× Á±93Ýám là ýZvƒ·dU9Þ§Þú›Þ®ž“=†·!&Ñ[l­É2½AL!Ðö1½asݯaâÞ‹–Þd3ôÎkAæxÜÒ[!ÓÀ;ºs |ƒ·"à ÞÅ1·êÞà-õîX2{ƒ·:&ÂлI”Ç1ìþ½é=¢7éô‹Þ =õ¹‚øó· Ê<ñp²£Ò-õoÔ¿uýuÞ+ÿ=Á—c>À+[B’OYÐ>Û®Àë2ç2¡ž‘àgoˆD¸é€æÙ~!S}D‚ž}I ”!A©\Þ}Ë`Å^àæc“©ÆgÝ~Ë j½)¶â‡ý­—Ò”ÇY“é8þsgæ²Aû²P¾i‚‰·èBù¦ šH¼AÔuÍ÷qçݸyc AšÀa¿¡Ìq'׊Ä;jÀ<ã‚kGâKÒ`AVxÉxßÕƒÊ6iгI4¡ì+.Ȉ¡Êx OLZüë¾ËýÇ-ò§È´ueXTpãºE«’óuã&:ÚUQdòÞŽBĨåÁŽ{ê¡gy™–»GÆ-òÃ{J¨Ó!!Æ4$sÕ›§jwQå]Sþ 4œþ—aKŠæ=ò2‘„¨ue$Fí±(’a3%™Mk—Ÿ©>GÁ=Î%šMwÜK™¬É¯ë8›h’<Ëô0ÅÃkæ½Ó^‹Œëð\\'NŠQ»-¤YIM<#®ìZWÊc¨ÔS?θ’Q¦r\ÈÔ5§¾ÎH“v\dÍɰbùŽÅXÇE#/aÄ©BkÜŒüÜceúÜ«ÙbëÇu>hçE†{³ö5éÆå½H˜u—C4Nà\ØuÇ<ŒÕg\XŸ§1SŠÆó8Tîñå$ãp`ð¹M’>7Î)UÙW%Æ„ƒŽfU6§,áô#åÃ`áÙûìÌ•$d”ÏžU™OãØ¹³ª²5gn%¹N\£rd$ìU– pÔxΪ,ÆšªG¶UíÊàý±8.HY„ÑῘ¥¥ÙgUFn­kR†~‚³*ÃË’q-Ÿo6íÎH2ZÄ Ï7íÏ£pöØw0î{ígUÆ›Xá=݈bT. ±aóÚÚc:&4êä"ˆQ§ƒ3Ž‹ 0†µ·bÓ#žu™ï/£vkX£×~ >ïXŒÐÐϺ~Ñ/5[Œu\U²ê²q„켌è¤˜Úæ[öÐÀ—0x‡½‡oöÜûcaåñç ² û"}œdUpóûŽƒ¤]‰gØ÷ˆ»<ýÎö¬*2ìõ‡7ØÛþ¥½vOسzh`ßp‹ìyC½D@>}5Yg\ÔΩæãŒ:£¢Ôg°g T¸à ö ™sÒ ìá‰fû¸ÀK°oXþ_µ;öÐüòu7/Þ·ØCàųº4‚=»ž ìY;`ß°  –µ_ÙÀžÝÀöì[6°gç²=9©ìÒñÜYÏîeÃz8éÀ¬g™YÏfÃzö0Ö³*gXÏÒ›a=‹h†õìK6¬¿ïZy“ ëÙ̬g·°a=û“ ëyã—a=¼ÇÈ€5ÆbÖ³kÙ°ž÷ ÖÛÏëùäóàä$±tó†W 2ᔾ1þ¸á¾Œõ/×ЕpŸ!Q^IdÜçqP×±ûq£¯ èŠö%ãf“s_ÓFíJ%ÚÃæ®ížL{ìÌ×É»L{Ãu%Ó~ì<ìØ<·6iÚK$8¨â)ía”©MZ' 2íí›Dû¦ç¦çíË81=Úß^Ô¸AJ÷¼.cÜÃØ0=€§q?RgOzÃ=ŒEÀà 5í‡Íwª3íaLsHào´‡QêJ\ÛTíñTŠ¿åyÔÓFÉíxk5íïFEû›QÓF)%k2ía\—s˜­i_p²äL?ªio¿ª`OÁþfÔ°‡îw€WÃ~k“Êú ö#!’aåè 4ìïFû[„4ìoojØß2OÁÞffý°å•dËúQ”Ò½®S?™õ¶úëGu,ç‰;ÌúQóyç³Þ6b½¥Àðqrãÿ¼b)­[ ÷@¥0þšwÊ<AˆuþµI­|ú'èJÇO*m; ižÁ‰ÆJ=jãXî­!®ÖÄhz|oå­~ô†(P’g¶›G~·FII^%ÏžDá»\,k›ËCw¸¬~×Tdôþ«+”2øŒcKðå3AY…òï~ã¿á¢b¡Ãÿñg¥±ŽãÔ…«nŒ¢AFú=är›!Ã?}û?¾ý‹üÿ˜û 5.>m©D‹I»©¡Ó3èwJïÅa®ÛµÈØ„L¶QÀy%Ò’†CÖFAÛ6v %>J,slh¢@¶ý5Ì En\?°¯ä )y ù %?¢À%ÏQØ_ò£9sÉSž”üàhyÈÔîçrÔҤývAƹ˜ÑÜ)úuu”ÈØÐ"½\s-HþE8tDn¬3¾ò X %UÌÿ«ŒRúGʨÏ?§§ûÑÁŠyM•ëc¯˜è_x‡£[B·‹c±=¨Šnœ+t»?±àXÕ<#óÛßüî÷ÿð‡[„t•ù¸ÛÍpf¹Ö»ßüßq(Owš®müÿþ¼ñÚF_Õ-2ÍEÜ"s®¦hêt©Š­×f2µ¾—äŸUÆLç{°5Š3ïEÁá/ÒÎŽ¥xÜ…ap]À6&Q}ž.Õq­e-üÍ®N—26âç-2Èd…·àÔñR8ÀF…ÜuLÍ•L¸ì.ŸœúxMÒÏÓ¥œ—I"ÞÓQñóx©Ù»dœÕw.ý¸ì&K<ü°éo†ë&‰)›ÔéR<Šêü\Ç<ªS¥`S…â"VöX¹~®ÙïˆìŸ›a~^œäÑ«¢–½¶Â#T=zmñ%1BU¹hF¯á5%eœñ’’…èjF¯IÜÄ™’Ú¦*¶—Í4Ua€âŒW5p$€b· H 9îåè•ûŒ‰T è%RÍü…*6ÿ„ÔÜ_^‹¿![oUZ ©&´òÀ› kÐD[óMM[“b´òàŸ°[ܶ¦-V èq¬«R¢»;æïŒa—°«r0„];âï †økÊcUš’2ˆM0k¬ªjö§%DèºÓ‰‰»§ïM‡9¬;%Äg¡oñöCB¼Ò¶#œT¦R–|9FÞ ßKhÖ¹ž+kÕ“7D€<3Ý<Ú. ê¯b§'_‘£ÃU0Åט½ß+F\Á‹•·X÷Nù0zWÆÝ°nûÛ”/b\lÚR…JPdÚ(Sªô”±±ot…{QhE$ò;D¤~“9 o‘úM>¤(¼A>Ô5LÝð·¯ä )y ù %?¢À%ÏQØ_ò£9sÉS~ ù0`‡0”IÁ.ùÃØ$r »äC åKòáwô¹èÎeÄW™ÁBŸû§ú\ìFŸS529£Ï©II‚çàœ7Ž…ƒÉ©K_j.€ãÆäÕ¥/ìô§à:¸æ^O•’'ÇÍ×SÐŽ ž?§ <ŸJAËrœª¨.}1󣄻i.±ƒæG ®-v¨ézJêÖ¼·–·‡aÓ²ÜȨDjÇ.“,×(”L²œ±µ±´úœ@ê‚)ê²^Q—½ØãN­zh[%YŽ„ *½žI’m:6ȵ•96È+“šqlèÐH–óÁÎŽ *æn<ôy8PA³ÓŽ vˆdg*zÙdžʇìµcc„âµ?ƒ#•½ºÛņÔÝ.6”@ŽLPWº§Å¸KR;4t0ñºÒåö96(«sRwºØT%ãØPU»fµcƒR•Õ.6.Y{8LYeu§‹}¯Ü~¾Kc{Å;ƒc¨qº%hæk´æ²‘ވ˰é–G\fé¹Ü;³—e9Šg0úœf½æ2;û™Ë,¡1—í{šËý.w&_z©Ø1 -Åî% Mph“+h“›hûž´ ¯ Odz²†ÇïbÞK@›šóÞ,æÑ{ݨzú=´}U=¢†cym¬óéð˜Ô‘Ú¼Fȶ¯id!ÛÚXù£ðˆÝÆYd›b· .-P¿Fì¶6ÖÙÆ¢ …Gì6%”Yd®kv›ðÊ-êõBƒo÷ßûöÔ(ŒFÓãð{3šn/©‘öKj—ÄïÑh:2™ÍhšÈL2!5µ+‰LíJz1S»ròˆÚ؉ª¢BÔ6áij›àˆÚµQ'AÔ6ÁµKä÷4µK ¨µÍ¨•¨]â Öò)2É„L£i¯ÑáƒAt¸yfÕÌ’62;‡×h.< 1cg ›AôK4óìÐ ¢Iy5ƒh_›Ñ´“òhÚ¿F3ªMS̰ú>š¦Ù ¦ýk"›˜Ñô}Íyǃh˜ó š£Í’6UoÌ Úß@\¾´Á°øÃ;Û§kM8¬;ÕÁg¡ïp éøI¥mK8­\g}΄ѣ7ˆsð%°:¨Ÿ¼!”à™éæÑvuP§x{þ¥ê öÜaï/®8‰{ÕÁ„³ãå!âv„7ªƒ }eî.É›âàŒ M[jP L¡ÒS®Z¹—„F"¢ß (°DÄQØ/ÊÃEá â ®ao )y ù %?¢À%ÏQØ_ò£9sÉS~ q0âê…Ç4k—8Èal9]â …²C” 긌Nz´ì?Cdqð/_èÍ~ž8ˆË¼ÎóIÇM°ŠE¼Ñ4Ç!¬çÁLR'u›-Aû5ZÒ5¹Dí×hŽmùº¦Ö¤'X%j¿F8 ÖY6¸ð]¿–H$$‡AÃÀ­c]PÞjêT2©„´ÑnœytͳžሪtÍ3½W´_cF¡äë&´yª¢ý&˜êÏ#˜ *J5î âÚ®kalpÜ´«²4rg¶µëø%ûÍnüú½ž¯{a`Óñ쇃C¥¹ÂƒpÔTó‚ü楧£ÂƒpÖTóž7ž屨Þx:t\àB8kêðïÔ@*“ ÏÁQA9‹j ÿùë*<WåOFrpŒOEòkD]Ÿ1ÙP~ &‘_ÃØÈ¯ÁQÏäàà÷²vpp¾frpðk…#”Bòy¡A—õ PŽ@¹QI%ä*QÉÁÁáµ[5Þ¥.§+—n\.ÇÍÑ.Â1„CÝ #‰ƒ‘x¥qŒí@ÇF¨Ô8†ÞH&…c|RƒKãxî($ ãçš-DáN{y‰Âˆ‚Îb4A²)ã=ýÍbDAmS8¶¯U£ ’Máïé¨MPç”Æ±QtǬèŽñžä2ŽY|™86EÉ8æŽM@ŒcŽ áØ¾ç&¨ÃÓ8¶ï£ j(.ÏÇ86±Ó8^?F¤Ÿ+¯Ÿ'#üéŸ'#üi&%#üé4d#üifþè5#üiB#üé÷ŠþtpÅÕ:¼úZøc›ðÚMÚÞ(ü1‘ƒ#ÇYjªn=ÍJ4hnψ¬™ÇDN4f2D¾8~ÄÌvKdMd³]üFdsMd¼GcfCd¢µ"2ÞÓ™nˆüj€l;Kdè*"Û÷,‘u4‘mÒ-‘uVk"Û¸|—È&Ñ7"ëqœ&²é†~6‘oïýL"Û4|Lds fj4ßÞ3‹3ˆµŠÑ6æ–ÑbšÑö½ŸÉè•⟋æõóÏ™º†È4xVD^Áü ÿ’ý¸toÌt@Ž?§ÛöàÓðw¸þŽ„ü¤S·# î²UéÑD8\ùÉ* ~òŽèÏ\7¶«€:Å+ôä+*`®Y‚ >{œ¼UÅ.>ê!FpüÅ*`n!áfiéAâßèÁ‹öÜÏ·ˆ´:EùB 4r…ü9hDå ŽÂ~9hT–ƒ( oUë˜SíWGˆ¦ì)èw0;âÀ…Ïqxà ³£IséS~ 1PáæŠ–sk}—hÙ$šPvéÌAqYw|,V-þë_öíÄ¢åx.Ĥä´ã ¢%uAKmt KKU뀤Ê4À\:`¥3&Ñî•ØVµH“ÇV®ËYj¡uç­$­ÒaB­T­fJBuZ$)³á™ö¼ÊdL뀤0´æ´HþøÖ’ÉÒp…Ì¥·ð7»S‚ I ­'-:~­jA\.½=KE³»¤AòwtWµ ÈßôŽÏCRñ„ü®Aó^½Ÿ‡ÔqcÌ%["Ap<ªZ$wQŽw ê°!¾\: IÇ%1—Èï%Ç‚ Ž^JJäOâž½àYUþžÉ3×sÒ‚à(%«:«’墨‚êØ•¤AZŽÞKÕ‚ Ûp5Œ® dKZOªÖù×ì_õÒØ¯xÖ©j•Aý^w,êK!APH¯$žn þü.!Ðð8ÒH™xšå±ÄN§’x /µ†‹æ1v%¾â1¶¼hæjcÕ)ÿ3­¡ 7GÛ[ˆÇp˜«ÝÔÄcãL'Ã;N¯Úÿœ([4á''V'í&MxlüëšÇmÜVF†W]§JcØ(´„aصI»Iã& ÃF¨uÚíÌMAcx꓾ëo ]xÁuëÓÐmŽöj}­MÓ×Dß›­j'3]Ó6|E_£k}“Ÿèk´¢ïÍVµè-}&@ô½Ù*;™uç ékôMß›IaØÚ4†o6…a£6†­McØH%„áÛ{ Ãæ½5‹#b£h¬Æ§É‘d‡›5c™Íå6¶›©Â6ÓD–Ùܘ¿†Íš‡ÌæÂc^ÃæWceØtx–Íú=fsâñ0±9Ý‘œî$¦0’îŒd’a ’ydÇHŽÏH¬È#±na†ÄÔR$ÓCf3wÌf:2›ÙÆlw$‡g$Ö̲$&“X§Þ’XÛ,‰5',‰ÉÆ$¦ b$!ÙØÉÜÑ0’M#™;!F2ÛÉÆFHæÎ‹‘ì_ŽŒmçÅHæðÉþ"±ÿ’Ïì¼mÐåS‹C[Zà˜Í ñƒ­7>Áç_>åÀ+[B’OY=Ÿ½AkÎk¼C=#¡Ÿ½%ᦠÚgÛeANõ ~öiPú‚ð(½úÐvß>X±QXy %|æ¤Ò_, VœÙÕæ…Ú{Ò &ÈE«-éÔ~‚Pšò8Ä2çŠn Ò^BHa¿E$Ê7…ÐDâ*Q¾i„‰wˆ„º®ù>îÂ×9o¬c”ij…ýŽ0‡º\8o¨ÓÍ5€"ñk…¥È„¶ö$ýoÚv%¡ d“PhBÙ%r0;„Š >b¨2>éß “– ÿºïÒ?çRÍØM›Ôz@p òLnr”>]F3zÖ Fí‘´¨v#F­òQoÞÉ|ªŒyѸ”)Ígi†»+C€¤ ªV m‹ñ®)¹°% ÿ–iVn9æ…/®i°ÒrGïº{y’Ó8 i6RÄIÝëâàiÃùêïÖ ùÎ1j±°Òrp1V\ÐÜÇÍ÷7£Wra%‹Ø´^XùbÉøq R‘$ £¾{ÑÃÿ03{|v>ÓJa% ¨¢¤ÂÊ÷äxxŽïIJzLãT¤qãýÝ8Ôš8+á‡8*ì-CNÑZFJtÒÊaÍXÖÒa¥coÅ(Ÿ=+l]/ÔqJÒ¬°ökE‹†¶dŠR ×Çà}8ë© ½j¹Ð†Tµ^¸¾&U3_õÔäFÙW=5ù×´dhãÝ´fhß„óA×SªQ]©†ö«]ë‡Æà7¿ê)§$H»‰ªžR NKˆö³^kˆ7£|VWX]ANÑV#`®øÚ(æ³wn+ŸùÛtŸ©á¶ïÆhü×J˜cnÃMpÔ§õ,À1Æ"r6öaëü&€£“a£ñb“–Лú MruÕ!’ÃYMÍÇO6ÕeÇ®lnÆšäF»$’ÃM­Çÿ6áP“F³Drãýf¤÷7#Ý8»éÆÛÍH‡‘2(þnzª‘nœáŒt#€2ÒË›‘nïÄ$¤í”Ù>]ãŒôóû½ ˆéöÖMBúÝøÚõÍl7B*³ýn|íýf¶ßÞÔl7þobûÝf<àDKÍö»Q±Ýø¹™í7£7^p6*¶ßŠíÆù}êÖ_š~Zš¼áýNõÈÈT¤¹ZªW~“©ùM¦ºç΂¨îÝ3˜óHÝÀœBb˜›éü£9“ž`N+Mî0ç‘·9±ÅœØb`Î#os³˜ó(ÛÀœâcaΤ'˜Ç§ §HZ†3à73œŒÿ‹á_g85†ëjwc8ÿç`ø¿ÿáÿ*”˜ endstream endobj 3 0 obj 25253 endobj 4 0 obj [2 0 R] endobj 5 0 obj << /Resources 6 0 R /Type /Page /MediaBox [0 0 1080 792] /CropBox [0 0 1080 792] /BleedBox [0 0 1080 792] /TrimBox [0 0 1080 792] /Parent 7 0 R /Contents 4 0 R >> endobj 8 0 obj << /Type /Font /Subtype /Type1 /BaseFont /Helvetica /Encoding /WinAnsiEncoding >> endobj 7 0 obj << /Type /Pages /Count 1 /Kids [5 0 R ] >> endobj 9 0 obj << /Type /Catalog /Pages 7 0 R /Lang (x-unknown) >> endobj 6 0 obj << /Font << /F1 8 0 R >> /ProcSet [/PDF /ImageB /ImageC /Text] >> endobj xref 0 10 0000000000 65535 f 0000000015 00000 n 0000000145 00000 n 0000025472 00000 n 0000025493 00000 n 0000025516 00000 n 0000025946 00000 n 0000025815 00000 n 0000025710 00000 n 0000025873 00000 n trailer << /Root 9 0 R /Info 1 0 R /ID [<7D94E7FB17F45525319A3A9975F5FED3> <7D94E7FB17F45525319A3A9975F5FED3>] /Size 10 >> startxref 26027 %%EOF blis-0.9.0/docs/graphs/large/l3_perf_tx2_nt1.png000066400000000000000000002137131422157504600214130ustar00rootroot00000000000000‰PNG  IHDR¬öEYa )iCCPiccxÚ•‘gP”‡†Ï÷}Û m—¥ÃÒ›T) HYz•^E–ÞY–"bCÄDiŠ AF¥H¬ˆb!((`A³HPb0Ѝ Ü¹3qîüÈóë™wÞ9çÌŠ*’*àû¹Ø³CBÃØð ‘¼Ìt®'ü#Æx ÿJtL&V Ÿ—Î ¹ •#H Ç€•”.@Γ€ÜfÜ_>̨¿|˜ü?@¢Å}ãQßø÷¨pù‚„ؘ\¶Z¬ '’ÃÎôs±g»98°}øi± É1ßü¯Êÿ€ &Wà–¾…Ÿ/`ÿßPcC##øûï|„5ø¿ÿ€oziœEìÀßYT5@÷é'gjÇD ºîñ²øÙe8‡ÏÁá+ñÍøNü ü(~ÿ@ °šs‚+!”HØJ(%%t®† S„E"‘(CÔ%Z½‰‘D±ˆXMK)Hq¥b¤öIµKH-IËIÛIÇHKwHJ–aË8É$É”é–y&‹“Õ‘õ•Í‘=&{Cv^Ž)g%Ç“+–;+÷D•ב÷“ß*B~P~QAQÁE!]¡ZáºÂ¼"KÑN1Q±Bñ²âœCÉF)A©BéŠÒ+¶$›ËNfW±ûÙ ÊòÊ®ÊYÊ ÊCÊË*š****ÏT)ªÕXÕ Õ>Õ5%5/µ|µ6µ'êduŽz¼úõõ% M`½Ý³šÒšnšyšmšZt-[­ ­F­‡ÚmŽv’öQíû:¨Ž©N¼N­Î=]T×L7A÷¨îðü‹5©k׌ëÑô¸zÙzmz“ú,}Oýýný7ja  ¾š&6>5’0r7*0ê5úÓXǘg\küp-}­óÚk{Ö¾5Ñ5‰19fòÈ”aêeº×´Ïô‹™¹߬ÝlÎ\Í<¼Î|œÃäøpJ9·,ðö;,.Z|²4³XžµüÃJÏ*ɪÕjv溘uM리U¬#­¬…6l››ã6B[eÛHÛFÛvªvÑvÍv3\mn"÷4÷½¡=ß¾Ó~ÉÁÒa›ÃUGÌÑűØqÈIÂ)ЩÆé¹³Šsœs›ó‚‹©ËV—«®xW׃®ãn n<··ws÷mîý4ž:ž|Ï^/ÔËÝë×Äzõõ©ë»½ÁÛÍû÷3MŸ ŸŸ} ¾>¾µ¾/ýŒüòýüþ›ý[ý?Ø”< Ô Ì ì  j Z v .†„l ¹*šÚF k[Üà´áð†épÓð¢ð±šs7ÞÞ$»)yӥ͢›#7Ÿ‹ÀGG´F¬DzG6F.F¹EÕE-ðxGx¯£í¢+¢çb¬cÊcfb­cËcgã¬ãÅÍÅÛÆWÆÏ'8$Ô$¼MtM¬O\JòN:™´šœÜ‘BJ‰H¹*‘š”ÚŸ¦˜–›6œ®›^”.̰Ì8œ±À÷à7g"™3{LAº`0K+kOÖd¶MvmöÇœ œs¹â¹©¹ƒ[t¶ìÛ2“çœ÷ÃVÜVÞÖ¾|åü]ù“Û¸Û¶#Û£¶÷íPÝQ¸cz§ËÎS»(»’výR`XP^ð~wðîÞB…Â…S{\ö´‰ñ‹Æ÷Zí­ÿ÷]ÂwCûÖî«Þ÷µ8ºøN‰aIeÉJ)¯ôÎ÷FßW}¿º?vÿP™YÙ±„©ÆÚuÈëPW»¢¸âýá͇oWšTÖ¡É:"¬ò¬ê©V«>P½R_3Zk_ÛQ'_·¯néhôÑ‘cvÇÚëêKê?O8þ¨Á¥¡«Q£±òáDö‰—MAM?p~hi–m.iþr2õ¤ð”ß©þó––VùÖ²6´-«mîtøéû?:þØÓ®×ÞÐÁê(9g²Î¼ú)â§±³gûÎqεŸW?_×Éè,îBº¶t-tÇw {B{†/¸_èëµêíüYÿç“•/Ö^’¼Tv™r¹ðòꕼ+‹WÓ¯Î_‹»6Õ·¹ïéõëû}û‡nxܸuÓùæõîÀ•[Ö·.Þ¶¼}áçN÷]³»]ƒ¦ƒ¿˜þÒ9d6ÔuÏü^Ï}‹û½Ãë†/ØŽ\{àøàæC·‡wG׎=>Š~4û8ùñÛ'ÙO–ŸîœÀO?{Vù\þyã¯Ú¿vÍ„—&'_ø¿x:Å›zý[æo+Ó…/é/+g”fZfg/Î9ÏݵáÕôëô×ËóE¿‹ÿ^÷FëÍù?ìþ\Y˜~Ë»úgé;™w'ß›¼ï[ôY|þ!åÃòRñG™§>q> |þ<³œ³B\©ú¢ý¥÷«Ç׉ՔÕÕÿB,¾;E^ cHRMz&€„ú€èu0ê`:˜pœºQ<bKGDÿÿÿ ½§“ oFFss0ˆÚÿR pHYsNNÆÊ/¥tIMEã$:.$¶­ vpAg’Zó!%Õ€IDATxÚìý{|#w}/þ¿66›‹’Ù¤¹iCÂ8´!ì˜÷”všÀׇ1œ²4î!HOB/HœíáRº‰þZhL·X…RNñÐm·6áR"ã!)—Èx€dµ¹ìdµÙÍ.K¢ßãÏh$Ë’lKšÑèõ|<üصF—ù­>ïÏuSµZ­‚ˆˆˆˆˆˆ(`NðûˆˆˆˆˆˆˆšaÂJDDDDDDÄ„•ˆˆˆˆˆˆ‰ +Ñ€³m†aø}DDD]Ç„•ˆˆhÀ™¦‰D"á÷iÐËçó°,ËïÓ ê9Æz1a%"""¢ Óu•x Œõþ:ñýïÿûý> r†sÝtÓMøâ¿Ó4qùå—cË–-îñ|>ï~8$I‚®ëPÅ=nòù< À$I¸ð Ýc™LŠ¢¸ÏoÛ6.¿ür÷9MÓÄË_þò5ß—h-ZÅøjÇòùðßDÕ*f¿øÅ/âèѣزe dY^§ù|že6 ŒÄº,Ë-Ë~ÆöÚ°‡5lÛÆÈȈ;ÿH×õº¡]™L¹\Î=6>>]×Ýã¹\ãããîsŽŽ"ŸÏ¯8nÛ6lÛÆøø8‰LÓtg2™5ß—¨S­b¼Ý±Æxóþ¾Öxe|S¿õ2öS©TÓV~Û¶‘H$`Ûv]Ã&ÑFµ«¯4jŒS–Ù4(6ëíÏØ^£*ù®P(T½ŠTUU­.--U—––ªªKKKîqY–«ªªV«Õª{|aaÁ=>33S•$Éý@uffÆý]Q”j2™tO§Óîó­å¾Djãk‰ÿ………*€êªÕêÚã•ñMýÖËØO§Ó+^çÀ+⚨[ZÅlµZ­ªªZ- îñÆ8e™Mƒb£±ÞîñŒíµakˆ!_©TÊÒ[( Ë2t]‡ªªuÃÂ4Msÿo†;ìÀ0ŒºßE+÷5@’$H’Ôö|:¹/Q'ZÅx»cŠ¢¸# t]G2™¬‹ÉµÆ+ã›ú©—±¯ªêŠ×-ôÞï ¢ni³«iŒS–Ù46ë<ž±Ý9&¬ Ë2 …`||›6mB*•à IhE ;Èåru?Í*2D~iã­ŽN·ÒÎØ¦AÒïØWétºîyˆº¥]Ì…ÅFcŸ•îbÂb!¥™™8p Ðuù|’$µLZEq[mÄÏÜÜÒé4ç.Q`´ŠñVǧÒnš&r¹lÛfÏ ”~ÇþÌÌ Òé4pþu]»˜% ‹Æ:?+ÝÅ„5ÄBJ"1•eÙ *,bÒ¶mÛuÁ®ªêŠÛÄÄo¢ hã­Ž‰ß5MC.—C2™ôûRˆÖÄØ—$ Ùl¹\ŽÛ.PWµ‹Y ýÈ0¢A°ÑXïäñÔ9&¬ æ%ŒŒ ‘H`ddÄ­¨È²Œ™™$ $ ŒŽŽÖ “L&ƒÑÑQw…๹9¿/‹ÈÕ*Æ[Dà {WiÐøûš¦AÓ46^RWµ‹YI’ÉdØ‹Do£±ÞIùNÛT­V«~Ÿ9D/ª$Iîp^±x’,˰, ²,»CɼI©w‘%1L˜(hšÅx'Çòù‘ƒC‚Î;$xÓ¦Mu‡’…išØºu+dYfÌÓPaì9ØÃJDDDDDDÄV"""""" ¤“ü>nùò—¿Œú§¹çžë÷©ôÅáÇqøða^ïž/‰`zzÚïKëØÄÄN=õT¿O£o|ðA\tÑE~ŸÆÀ^ïƒ>ˆ/|á ~_VÇX†‡[/Êðg?ûÙøà?è÷¥u„åw¸õ¢üþð‡?ŒX,æ÷¥u„åw¸¡üMÂzöÙgãꫯÆÔԔߧÒÅbóóó¼Þ >ß 9õÔS±gÏ¿O£o&''y½|¾AÂ2<܆½ gùn½(¿%YX~‡]ÊïÐ$¬ÃfÛ¶m~Ÿ¯—zÊ»ßð0¶ëvÃV¦ Ûõ»a+φíz‡Ý°•gA¸^&¬*"ú}¼^ê™±±1¿O×K=3leÚ°]ï°¶òlØ®wØ [y„ëå¢KDDDDDDHLX‰ˆˆˆˆˆ(˜°Q q+u…išPeÍ3 £åb¦i¶íºÛTU…eY0M¦i²,¨ª MÓ IÒªÏeÛ6LÓ,..âÈ‘#~¿mä#Ó4!IdYnzܲ,X–åþ.Ëòª÷]a«>Ö¶m†áÆdãç@¼¾øl©ªÚô³"^£Ñ/~ñ Ÿßa"""¢cÂ@¦iB–åU“/QÉ ¢¢(-µÕžh^‘Öu†aÔUÖE¦iP–e!ŸÏC×u÷±"©L&“e¦iÖU¤“Y‘hʲŒ\.ç>^Q÷5t]‡ªªu×fš&r¹\Ý}UU…a­»–Õ’hEQ°ÿþ5'Ô¹\–e¹É¢,Ën ›¦‰|>¿"QL§Óÿ½LÓ„®ën|5Ƹx ïmÞûÎçCœ—`$I‚¦in")γٹ‰†q]â6I’ IlÛ†ªªPeÅçE 1âšÆÇÇWÄôjI7V""" &¬}f Ãp;¯òm·¡ô®waÇÏŽož>þ÷É'ãìK/…¢(¸2Á#¿ü%núô§ÝJ°¨àf2$“I$“IضíVÖú^Ñ#išæŠŠ´—HNÅc-Ë‚aÈårîýÓé4ê’I‘ȆEQ033Y’`Ùv]"ß,Éï$I0 g ÎY°,çߪª"ëí}RÀ{mŠx^¯X,âÀÌŒßá:º®#•J¹1äíõÎçóÈårîí¢ÇÛ²,7¶D‚¦išûœù|‰Dªªº!¢Q§±Q¶mȲ\×ÙØø"ËòŠØÄgjf•Ø1.ËòŠÏ°xìz¶7ð^o3âgÖ³ƒ¶+ owôKc#V#1òàÖ[oÅ9çœã÷eÐk72L×uXÑpî}¼¸ˆWoã«®ën\{›}GˆÑdâ‰ê1aí‡|Ç?óüç±c(=ø ~ç/À—^ùJ|ó¥/­ë¡Ü>7‡üÁ ò·‹×çóx}>cÑ(žùÔ§PÞ¼_G¡P¨U’MÇñãÇq×G?Š¿ç=8ó™g 8é×~ GŽÁÌÑ£øÖ~ä¢ïݹÏO&kç&I@Ã[$“N‚¸L–e$- IUuŽ ¦YûQÈé4²Ùlíx&˜&äåÞ+—aªê¼öÜ\ÝK«¶ UˆŠ¼e¹\ÓÇÀ4×’$ç¼-˹&ñ»su +ÜÕU~GF ‰ž|Ñû-*‘Í¾àŸøéO‘ÎfaYpÂÁƒøîÔ{ñ/öïXxnlÝ„hôùxûÛ‹¸çŽ‘Ï›H¾´ŒìuM* ¶íþýLå$’Ðõò\*I¸´ñ$XZÂÉ^ax…a8·-Wâ#–…÷5©$#Ÿ¯%t’T«XÛöÊʯ÷µDrjYµdP’€tºi¯'V©Ø»e –ÈJRóç\íÜDO,mˆw¸·ø²ööT>òÏÿŒÌ³ž{¹×\’$¼óØ1}ôÀ©WA;~*¤ÿñ§ü>>~Ñ?c—`×o|Õ™ÈçÐIgÛV‘ïeȽë ðé4¯=öûaa9õÌd(¿òÖ'däèE(¼ú¯LÆYo¨fÎ}Œ$ÊÙ?ƒyý?À|dìÃÏÎ: Ù7ß X2…ßFþð[±ð¹ŸA¾öù0 ÏGb×$ì_἟ õŒ"ä—ž¼©@¿ïihªä¿¾º^û(¡\†ôËGœ“=ù²w˰m •r>:†.ÇÞ ydr÷ò‰?ÇÌköŠ‚Dö·ãÇQXþe2ËyðÓC:6óï¶Â>ºê%÷£ðÎg<ó‰Ka…ìóAáh÷¡$Io¥ Fbh¼þ.*áÜJ{ôØ1œyæ™xhË+L‘(†Ÿ~õ«°s9ŒÛ6’É$LÓÄñGÅwßô&lÝ´Éù^j,ÓÅ9Іï£GâS²ìžãÂÂ$Ór9+•pëïýžßo9­ƒhøh–Œæóyäóy(ŠâÆ£7Ù£°Òé4ç{)•J¹É¡ˆc]×ÝÆE‘$ŠÏ†¢(˜››«kHiüÌ4Žf£×R©LÓD2™D¡Pèx:–¸†NP9B†¨Ö5², ©T ³?ü!¤|Ú±cΗlcï£m»=„¯—e¼¾És©ÌÉë´wHUWÞ·ÙóËrûD²Më¨7kMšôÞšúJô†ˆáÞù÷޲…,ªa‡·Þêþí H½ù h“§@}Ù)0MÀN’ 4F™÷㪺­Ö>"Ç…"DÜû¸¡šÀºó ìeçEË7: ãŸÎ: "jD§cîÇQ(/zsL¬ùÇ€g’„윲|~Ïw_KÔUÌȵºµ” I8?BýG"ºü#\`'$PMÏs-·ïØ6NK óìpÞ‡†š¦‰÷âĆ׹tùÈ6|l"‘Çz(ä1·ß[¹nœG-’ÊÆ¹Ûº®cddétÚŠŸL&1#>˜Ë³mÛZ?>lÞ =êü¨ª¸†QûY~Œªª°î>ü0þàÛŸÆ×æçñšÃ‡qñÏ+Èã7aŸrû1HZmp€®ÖígBÛÿw¹ãì7#ÿл`?y2”çV ÿ1¬“öS—@Qœòò€Ü_iûvüæ_݇Gççýþ“ %«qÔ”‡H¸½Ÿbš†·‘DS™DºªªuɤwêˆèumL&³Ù¬;up¦Xx§}´›r ®qvµãbêõÖ5sð¾tň^wðÎw®~gQ3%bx“;ä<“t[väb¤>q ìM[±°ÓÜÇäóÎÏÜíg¹ ÙZÛ4Ö²î•|õEMoÏ~ü¬ºßk»“xŽ©çh^!iÖÞÓ ÍÚ_Ö±˜öºCÁ#z@½CjÏÿáñ“_üÿñØc$ ~:ÞwÊ)¸òé§`^ \.]×ñ±ÓOÇ™W]…?þýßÇû÷׆!XV-=Ag€š*Ëxê‚ PþЇð†3ÎÀyçär°Î{ ògü)p‰“ƒJ’]—`>÷k˜ùØ60úÂãPÿó~X‡Ïƒ…ȬqoC z÷™P”ÝÈî~;^“Ë!÷øõÈã5Ð^|BmIÏhygI‚Ka½y² (6¶ÄH÷­0ŒK Ëµå €å=Ï;šv ~ò¿ÿšÃ)‘H¸š¦Õ5Œd2¨ªê&‹¢7T ñI¡H8EJÌý¬›ò´¬]")ˆdr½;ô”hEmXK€3ÕIŒ6ëtØ6^}÷Ý~Ÿ5Q øš°‹ElÛ¶ Ñh´éñR©„H$²êñ~½ª’$áîO|‘ë¯þïÿõõœ(ø‚ßãããîÂDÜVkïð&ëÿü dÛFòî4 IHHÄ+°ÒNEÕkf†ÉÔ0 bŒûζ±ø€or î¿ä˜¦‰ ~ô#üïÇq褓`¼ãjC/ýÙÏpÉ©§O? ¨*ŽÝr Þ}ÂâËOlEömïÃw¯3Ü-˜^þòoáÖ‡FvóÇ/|ùÊ[`œw'ÌÅӜƑƒ?ƒ<:LÝùlÚ¶“ÏÚ²Y` €žS€G€äêG@XÞíŒt$`é“a17l¦6+C†•žþ­V?olÌ’åú6]ï,YnÞ€$I+GjôʰÆv&“qÍk”J¥ Ë2fffê¶åß#Ùl¶.¹\m+.¡=–M“U±®…8fÛN JÃ4*—i:1ª@ W-ÍT¬¥ašÍ¿¥éZ°mç¹ £6ÌGUñÀ½÷võ}ifXcœ“/ ëÞ½{1==J¥ˆÇãÈf³ˆDœ/Èr¹Œt:R©À)ôÄDö^ºó%/Á–{ïŇ®º Ož|2N?~ÛÀ7Î;étÚ)xGGšÀ·‘¡áÔø‹Ld—GUQù­y$“¯$‰¹’oÁÂÂ[꫼*è¯,rdÔð jŒûIÌÿÞùÑâñ«®Âï<ˆ3¾÷=l~éKqä±§‘‰~æÃQ$åÚg'•ÌûUgà‚m#sÃAè'ÿ¨¯>®ü—oÇóï)á­o} &&Þ°( Ï·¸woÏÞÆaŽq\'ôû+• ¦§§155Ó4qÇw¸· »wïF4u—J¥ºã=aY8ûî»qŻޅ{ðA²YüÛ“OâÿÑ¡P(ÔZ gf8Ç’VØøð•Ï|ýÑ /¯ªª*òWýÌcÏw+­šÖü;WUë×ãj¶^ ‡ Çx¯™¦‰T*…T*…G>ö1`d€SÁÇùçÇð¯­à_þŽ}ñ^ü¹²€šÄhåkP®bnΩ‹ÏªzFÙKpÉ%(|õÌÌ8Ií¾}›qå•W╯|çóéýúÑ´ú…ГI§þÛéP{nE]/ì±-V±m¶HVgff°°”###Áøø8$IZÓ¶Z®&¯ÀI$Å1à §C ‘p~òyNn¸œ+;÷Cßçæjõ1ñ¡h¶hd2é|©‰Ÿ¥%çßlÖIB›µ¬x?LÙlm1HEq~_Cbêý®Ìçk§iÎïÞŸTʹü_üâÙÝù£7{ŒSxõ½‡µT*¡R©`ll ‰DÇÝ–œr¹Œb±ˆ[n¹Å=>66†½{÷bjjªgçõÙY|OUñü÷¿¸æ§ÄX^©·NÇ?†3¥ÁK¬málñ±¶Î]Q9j6u‚º/¨ñmš&®~ôQl¹öZç[QU¡›2òÇ®CáîÚpŸÕ»±áZŒ^Ô^Z¿ Æx¯Ø¶Þx#6ßvŽnÙ‚®¼¿öÀ¸ó–/á/¤Ûjá²Ëž…B¡€\NÂë^çY€},ÓÜ…OÔÊ_o¿±c§Ù牟±þ {lg2™ºEŒÄ¢Dbå\oBšÍf›îß”XdR oœ/ ]¯õf.²·WßþàÇ }ãó0žóèÌÂD–ï¾\õòæ»v2ñq`.½üyòn]·JG‚3òÀù¿81ºW|ß-ïZæþžH8ÿW”úÑÃbζm×êiâó™H`U"¿m¼ÚÐwEvíz '1ö§ðê{ÂÇW´îíÛ·gœq†ûˆÅbîñX,†r¹ÜÓóúàw¾SÛ_QQ€6ô|ºîr [š®Ê¶k-ožÅëXœÂz®Vè6öt‰ïˆBÁy]1zF–ko?Gð › Æw>Ÿ‡òÎwº 0Vz™ù1î>g] Þé@4\‚ã]! â™wÇ?ùILžtŽýëxæÁ“!+Á´$¤?þ[øß¸ÿß Tê]¤•Ée/W§Þ slçóyX–…Âz;JVgñ®'¶Ͼ²aÀ>ºúã¯G^Ê6° æJ9u…É$RFe+~'0Ó$yó~¦ÄÖÛ‰Dmd‚wzª¨ãN"(¦•Šï*±»H\ÅG"¡÷ËfëGkZmN¸8Y®ÿlwò¶6~g¶šÞ+aŽq›Ëel>rdMñuÑ¥ÉÉI÷Ã!ZsZ}(*•Š;ƾ›¼{s­—®;…YÒÓ*(IµŽZ1§HìõhµÝ’ÉZïi«7•‘Œz_OU/Bcq"Á T¿%¾ÅâÞÖóÌOSÈ~bm_–â‹^Ó8•A‰ñõC$ ÀmÛ¸éØ1<±u+Þ;2EQœm9þìÿá/K¯ÀÌU›¡ß$2χ$Ÿû (c~_õȠǶ—ØNf-Éê "Û³m§ÕÜ+›E>˜w€³þ¢s¨ÿŽqV¡®ýÞø4Û-`†aÔêMb×%Q•ëdZi³ùÖ"™m6µÕ{ƒ.L1N>Cî¼-F^žÂ)û÷ã”§žZÓËô}«×u×]‡‰‰ ÀÍ7ß î$ðf:´ê±x·ß~ûº6[ÎårZ©Î»5 ¦G,,8Ç·nu¦gx‡¦x‡YŠ9ýkábQ(8…»Ë‹s ³½{÷⦛nj:§›ºßðàƒbrr{׸ƒ®ëu c†“ëÙ‚¦ÇouÉää${þ:A)Ã×Ã0 ü/|! P(`)™DbtçýíßbaasssH&“Hé*’S›8Ÿ™¥%§\çÿLOO㦛nÂOz¸·MPÊïõÊd2H$îÏÌÌŒ;¸#ù¼3¤+‘¶n…ý?þù#;aeç–Ÿß™Â-ê4¢"~šÍ¥îÖ´$ñÜŠâ|E=J$ŸƒÞ(/Êo1L·W¹ü¦•<Ñ@%攋9æÞÌïâdssµ„Ä[xìÝ»üÎwðÝÇ_Û¹U P(T·oß^­V«Õ»îºËý¿Ðì¶FwÝuWõ¦›nZóküÚת²,¯ë¼p~I:]­ÎÌø}þ[o¼¬G7â»Z­Vo¸á†5¿öÝ_ûZõªK.©.--¹·8P­z~]ÇõT«Éd_Þ:Ú€õÄËzùY†¯×¿îØQ=rÁÕª¢8£¢ ^>Äú/~–ßë•Íf«š¦­ïÁssÎg!™¬öü¤šNW«šV­Ê²ó1áG¤?X~Ó†8àTÖÄÏÜœóVUçÃ,IÕêÂÂÊlj»,W«ÙìÆ*‹-¬'^ú>$xzz¥R {öìqocç`Û¶mœa bï'ïÿ»é‰Ÿþ‡çw¾é¦5?Ö¶‡tz°ZóTµy uGâÛ4M,Œá o{¢ž¦n± ÌúŸ—½KÃ,H1¾^¶mc÷ÏÏÁü[îDòºc¿ûÙÛ•‰‘(\Iwx„!¶ÅÜëuÿUèt'2< *jCcYæ‡CbœP¿˜e­_ïœ-(Š“´´ª®gœ~Ÿô}HðŽ;P,ë†:†á~¢Ñ(âñxݰÃ0hµÛ:ض=¯z~ñ›¿¹®áÀb"ÿ %«@m!ê Ä·išxǛބ‰ÓNCôà”oË»p¬[.çŒcåex%Æ7"ŸÏãeãã.8‰7‰q# Kªj±Ý" AmÛ¶‘J¥:þ+Vq4 äóÎwƒ®e¨o8 p·WbyƒãCIì$†æŽŒ8ÿйˆÍæŠy£ÞMèíB|Y%xll ;wîD<Ǿ}ûpèСºÖž©©)LNN¢X,º“¼¯»îº®ƒmÛH$øwçx^WTNÚ%¡b²ÿz¶$ 1‘_BÝ„øœ=õ¾|õÕØ|þùnÕ¢%‰+» Äøšd2uóhòù< IÎw}.çüxËtïb.42¶—Ù¶ññqhš¶ú’¦é´8ŠŠîòƾš]¿þÅ×i©AŽñÐÛ‰x{‘š­¾ê]ôÆ»ÿÒñe•à]»vabbÂ],×Åbøüç?ï¶5ß‘¬þ¯×¼çÜwŸ;ÞK,ÔöÊj$¶Œ»"Ó¸Ru—Ÿñ 8‹m¨ªŠóu½¶ö?VŠŽÕicüŽñµ8òÑbÓßý6=ŠS>úQ†mÛ&`š’ûyH§ëGضóÃáÀÃgb[0M©T Édrõcù<ËÁLÎÀHÎ8» ä…$ëÃfc<42™Z‚*–£n·Ù¶ûõˆ±pÄ꺖åÔ¿šlbËÄÆ7ÄV¡·É² Y–!Iöïßßù>ÏË|݇µWħqQ×92âv“J’“ ŠeÒ½s—r9'Þ$)\=K #äÜ÷ ènE­ —XVó­xDC9Äü¥¹¹9äS&¬ç¿âOœJ9áÎÆ ™L†aàíòÿðâ ðwýGüëGc¸úW¿ÀsÿìÈò¹u÷÷–‡Ý>OÔm¦iºAÑ8©ªêòðöU¾ % Æh©™íH§ÃU!ò•iÖö&jÿ&“ƒ= s™eYÐu¶mömXžŠ¸(‡TU…¢(MËI’VžP,1??¿¦ó eºÃ0077W7Ó¶¤Ç[‘ "–å$²aLŠlÛùœ¥ÓµáÐâ=ÈdœÏZ«ÖWÓ\¹ ‰hdÑ4çó*žWì1+>Û¢"èm”ÃUÅc¼£$R)çÜÿ™LmÄk>ïü½Äc¼£.¼ Ãù›zÅ ±ßª¢(Pìq¤6'1>^{¿™¬Ò°H-/4P(Ü/RI:ïùë;ñåc¯ÄÉyEËÇsþ*‘˜£ ²,cÁ3å£QmaH€Â›ø@ÔuÉä@Ç1M¦iºI¨è% ¦eY°, š¦A]¾¾ÕÓ~ eÂ*IÍ“7Ó÷Œ_½ç)Ì…»·2¦(µ!ЀSY¯%²\K³Yçv±ðŽ7v—¾o|^1 I$ºÞÇ‹÷ºñ1ÀÊß›iòÚnåîbÑï¿@÷Y–å,eÌÌÔö~_ïDE×ñÍ÷½c›7ã5ÿú¯Èå%w ‡Óˆv þ`fõ‡»åQˆÞÔlÁiÝ}¦y¦ÇúK´Ëó¿Ý¡˜B€?X¦iÂ0 ·'Ô;l×4M¨ª Y–Ý:£Út·êõK(ÖæÓ8ŒZË€¦šæ.ªæÄt=TÕé¹4ÍÚ{Óø¹Þ¥^Íl<¿0öŠ·cY$Irz²¥æàTÒ9Œ†EùÆQzþó‘L§a|ÿ\FýšÙló邪:õ&¬4"am+Ÿ‡lY(ÄDë"ö7µíÚ‚ «XŠR‘ŒŠa»–eAQw¸.à$¤•Ê„ðô°ærnvÕ8ÁW’8ìk5’4£†šmÛPÅݱ€h˜Tî¸ÿuè´åEd«yCV«3Iª[X›(0 Ã@ºÙŠÞJµ$Áú«Ï@ºóV«jM4 ÃÉ€Ú<µvÃõ|Ïç‘ÏçÝEŒÄàÿ°Ý^ mÂêVJ–[I ¬LX»µr*‘oÄdâlÖ‹ÐíkˆͽøŽ¾üåî—5Ëv 1¬¯iETÌßI¥ÓDêÌy¤—΂ú¿ÏšhÀ躓 ú\2Mº®»óL‡æ*Š‚¹¹¹5¯²;èB›°Ë *Y–óŸåñÚBã"=Diyõ¬'R©¡+¼ˆ¼¢ÿùŸøGi:uwö”RXèºÞ|8ŸaÀ¬<:²€çÇô½¾M4˜ú<äR¬ú-†ñÚ¶ Ó4ݹ¥ÌW&¡MXÝEf–+ñû¿õ-(é4ÄxI]—9˜žyK ù+‹ø½ÿú/§ζ1rÅ©XÚ·ÙïS#ê#•ÂæK/Å+$©é–]DƒÌ4Mwuà:²Œ ²Ð–×â0Í•Û>Q±w¥Ó4‘ÏçÝÄ´q(o6› íÞZSÂZ,ë6.‹0 ‘H;vìÞ&Ãb2_6‹oŽ:A ë°^þûd£gÝóðeP½`þË}PÎØàŠ =/Ñ )ßv^ýá#ŸwFG²‡‰ÂÄ0 Ì4ka—e$ÿ¬¶uãžhbú”˜ïÝÇVM±Ÿ©®ëeš¦5ÿT*…‘‘är9X–MÓ°´´„¤H>¨«Úö°–J%Äãq71œ@ݪuÞãA Iµø4 œr  ëP®|)TÆ…„¹i’ØvÒ'_l¾1h[†õŒè]œžU&¬&¢®åö°&NK¼,sl¢v’É®AÈçóÈårÐ4 Éd’=©}Ô¶‡5‰ R©ÔÝV*•‹Å—¤6Êdjÿ¿òÊ+|ʵQ£ÐXøÞ °m/zÑÙ_ûëPdÛïS"ê Û¶±ÿSŸ‚hTU¦pÉd2µ­-–WÓ¥Úðw"j¡‹­÷º®#‘HÀ4M d³Ù–sË©ûÚ&¬±X ¥R ¥R €3Ø0Œ+‹¡ÀÛ¶móûš¦ #o-ÿ×ÄE/x2W–Ì&x g+gytå#;1s÷¿O‰¨/t]Çw I0MgäQXäóy(ŠR«çr0^þ~x–!"Á4ë{©º@×uwدwn*NòGÛ!Á±X ñx“““C±XD¥Rq‡W*ÌÏÏc÷î݈ÇãîªÁ¾³mHgž ÛvZâeY†þ Œ,ãŒBÂ0°ÜÒn;[6q,0 ‘\.‡ÅãÇMC>ÅáÀ¶m#—Ë¡ 6”ÏçUEêý`nŽE=QÃR©®,oÛ6R©LÓ„ªªPU•Ã~¢£U‚³Ù,¦§§Q(‰Dê`ºùæ›1;;‹x<^º†ù¢ëàY ˜ÛP¨Ÿ{ÊoŸÓ494…†ŠišÐd'/×Ü… ÐPxˆ9rnON.‡üÛ‹Ð4'Ö‰€e9‰*à,¬´ÁžOÃ0J¥N§1Ç„!p:JXE’ÚÌØØÆÆÆ‚Ó³*Ø6¤ ·à¡‡rzŸÀ‚žÂ%ùíë }èó0 Ûq¢a ë:Þrâ‰n·*e¤°°mº®cA¬ª´¼pî“ç@t¸ =Ñ«:3Ó•á5bïÔ¹¹9vTÛ9¬íD£Ñà%«`Y®ºßøÆa(ŠÒí¡íD¾“7—!Ip·õ º®ãŠGþË7°l§P½«n#¤$Áxñ_@Q¸¨‘+“qzU7X÷1 ###°m…BÉj€uÔà 8‹*ÍÏÏvìØ±bÑ¥À±,( ð•¯<†³Ïæ‚2–…ü‘HÂIX‰†…išxåWà“÷ì@~öžyûí°ßv#ÌO¯©C‰hMüŠñ5³,g8ðÌLGwÏçó0MKKKý?Wê¹¶=¬Û¶mÃÄÄb±XÝÏÄÄâñøŠÛ;199‰x<Ó4qÇw #íéݽ{7¢Ñ¨{¼T*azzzÍÇá’ä‡~Ä7÷ä#?õ« ÷², ²,CÿêVØç3Y¥Þð#¶'aE>ý¬w€BÔK~Åøš‰ÞÕäóyäóyÌqÒwhµíaF£]ÝoµX,¢R©¸Ï‰D011½{÷¢T*!‰ X,â–[nqaïÞ½k>Û¶¹0õU?ãpe’Ì^©úã‚išxÉe—á4É€ªŽùý6PùÛ¶mãMgŒŽÂøÏS9‰zƯ_³5ô®š¦‰\.‡……nób ŠÅ"æççÝßwìØx<Þñãc±öìÙS·Òð¾}û8 ñoom,ó=QüˆonkCýäWnYÞ~ñÅxîXÀW©§åWl›¦‰ß}ê)Ø/yÌr80õÎÀÔÁ3™ŽzWMÓÄøø8æææ˜¬†\Ç‹.†k¯½“““˜u&''qíµ×v¼'k$©KpËå2¦§§166†h4ÚòCQ©TV=väÈìß¿ßÝ7Vœ3˜•Ëe,..âñÇïús÷*¾àðáÃ(‹l¼¡¶ŠÅ"<Ø“çîgîeYNü¯C0޽¢Oï"U©TÂââ":ÔÕçõ³ü¾gÇè¿|‡“[~·‹©õð«ü^˪۞r5Þd•£)‡¨ƒ¯µüî(a-‹H§Óضmr¹LÓtr¹¶mÛ†;w®)P+• ¦§§qíµ×"c×®]îí«iuqGŽÁC=T×û €AL+ìÛ·¯g «Ðíøœ Ïüü¼Û pž657??ߓʎW¿ÊðLȼäNü¯Ÿÿùÿ¸Ö©Ïïã;IAÔ«„UèWù-†Í/})$ LXÉ-¿{ß@ÿÊïu‘e ›my&«ƒKÔÁ×ß Þ½{÷ª«„©ª UU‘N§±{÷nÜvÛmmŸ¯T*a÷î݈D"¸å–[V =XM4]õØ9çœEQú;Æž’h]ìJÁÚD/âÎ=÷ÜñÍ‚šš™ššêxÔËzô³ O§~v1¾rï—pnå$hc÷ñ¤ ½A½(ÃûY~{ɲÌ=ã @­ünSë5èupÛ¶‘J¥033Ã:ÐZo¼m«Ârã7¶¼ßÄÄÊårG•¤t:펣oüplÛ¶ ê†%”Ëåu}pMÓä`ê»~Å7‘_úã’üÖoÝŽç¼ê>`ûvÎò£ü6M‹‹WÀ¶ý¾zƒ^GÉd2ng ¶ «håi¬"èÛ C3 årªª¢X,ÖýN N<ÇÞ½{ë“H$Öul}¡~êg|s80ù¡¯e¸m#3ñ0,ËÂýÑy(ü¾z ³~×OºŽ¶cvö<¿/Ÿ†€/1Þ ±*pù|–e!ÛfÈ0…OÛ!Á‘H¤«ãèEìäääŠc¢>55…ÉÉIwùíH$‚ë®»Îï÷Ѝ­~Æ7·m"?ô3Æ­/Þ ÓØ ĸ}õž/õ“LKŸ‰¯~5£^ l<—k»<¶eYîö54|Ú&¬±X •J¥íÑ:ã]*»™©©©¶cÜc±>ÿùÏ»¬µl›ãÅ(ê·~Æ7‘úãòO¡°ófŒè·o¢žë{ùm€¢àE¶Í¡îÔ¬£ØvG{®¦R)d³YNõR%¬±X étzÅÞM‚Xm,·œ°½Ko¯{Ÿ(¨ºß6'Ÿ‡$IиŒöÐêh[›]»v¡\.cçÎØ»w¯;»\.cï޽عs'Êår VèeežÂÎ4MVä)Ôò÷ìÀ‡pãœBɾóû¸ð¼ÃŒonù|Ë=WmÛF.—ÃL›X ·Ž¶µ«‰MOOc÷îÝ+ŽÇãqLMMu­wµX™§aÀ§0³9 'ð#HÛ8ŒÂÇøùsqdÓc¸”CiX-¢A‹ºL*•B2™äPà!×Q ԒV±uM©Tr‡ G£QT*‹Å@ÍÇcp .û¿ÂÁ߈àzõ~Ÿ Q÷=ü0NºêqN_¢á•Ë9›m¯B×uضt‹ûÐpè8aÄ7û•J%LNNf¡# ¦°3M“ó9(Ô¬C¿<þQ(ʜߧBÔuæ#Ûð¬cß‚$§¡Ÿ¨oÄ66«ì§jY2™ W&ÎaDLÀ-ófö¯ÎÀÑ2Nö¦­øå/YŽÓp’¤–+sU`òZsë aÂJD4¸lI†mY~ŸQOHÏfTQßµh¨Éåre™£ÈÈê„•(Ì,Vä)ääØfØ6[×)œ Å ö®y™¦‰|>Ï¡ÀT'ÔC‚9̆ŒÃd(ì²YÆ9…‰VJ¥R˜™™aÙOuÚö°–J%LOO·}¢J¥â÷µ¬À`§0c|SØI+ôN¹ððÃÇØ°NÃÇ0œáÀMê0™Lªª®XØ•¨kC‚#‘H ¶´aË%…WÁ¦°3Mà«_}‚z %Û.¸à)8à÷™õY*,-­¸Ù4MèºÎ¡ÀÔTÛ„Uì¿:hØûDaÆU°)ìôëÿ[/? lóûLˆº/k&×4&¬4\LsÕÅ–òù÷Uq80Ñ`S7}ÿ1+ô>¶Ì3ÿiÈÐ$)ÕuÉ*µ´®Ö›o¾“““~ŸûªØjIag†ß§@ÔSæÃQ¬ÐSøX_¼&6®Óp±,g¡¥&e:{W©Ð & ;®¢Ga6~àã\\ŒBÉúÞPÎ/öm–ã4ãüË!Á2Ö#§A}阦é÷©õW“Î$&¬Ô‰P&¬DaÇž' 3ãKÇ Ÿu€z %ë¡-~{;Ëp.MöW[ôqT$µÓvVÁ»ÈR¥RYq›0ˆ{¶ "ö¢îË~: Ã0ØèHCMì½:33ã÷©Ðh›°F£QLMMù}žDäÁá3f² ;VGS)г%Ëqfù|žsW©c &¢à˜››óûˆzFÓÃ(sŽ…GÉÐÐpZgV,¸”Ïç±Ðd^+Q3'¬¥R ³³³˜˜˜@,[µ"ÁE2ˆˆˆˆV'›! ½|H§ënÒuªªrX¢ a|SØ1ƃMìqØéœI˲êöE”$ 333C9ç²—±Í!Á=/¿MsEÂÊÞUZ¶=¬¥R ÑhÑh´îv1 XÇ÷í۷⾫)—˘œœ\Ñâ[.—‘N§Q*• iï.QÐ1¾)ìzã–eù}y˲¬CUUu{Q[½Ú###Ð4 ªªeOw?Êo&¬ä§¾ÔQL³éüU.¶DkÕ6aD"8tèЊÛ÷ìÙ³î-—Ëî"NÍìÞ½Ñh·Ür *• vî܉ééi7¦Àø¦°ëGŒÒàÕæ…öK'Ie'ɪ°°°Ó4¡ë:2™ ,ËB¡PŠ!|ý*¿Ù C~ékŲÏÂJ\l‰Ö«m‹ÅP©TP,ÇW½ŸVàíumußÕ¾<Ëå2ŠÅ"n¹å÷ùÆÆÆ°wï^Vèi 0¾)ìãõüN¬{êdYF6›u×u½ãaxâ着ª› f2äóyÌÌÌøzýЯØf…üÒ·òÛ¶Wlec†ïå% ¦ŽÖX,†ééiÄb±¦ i¥RÁôô4âñ8b±XÛÃØØŠÅ"&''ëŽíÛ·Ï}]ï9p Æ7…]?b|V zl-ó%mÛF>Ÿ_qMÃ’`õ«ü–÷“‚§ouÓ¬KXmÛ†aCÑðEÝ×Ѷ6»víB¹\ÆÎ;1;;‹b±èþLOOã oxÊårWZÏ[}(*•ʪǎ9‚ýû÷·œ@N81¶¸¸ˆÇÜ—×^M«ø€Ã‡£X,2¹¥¶ŠÅ"<èËkw« †á§½b6mÚäþ˜¦‰ôò<²ÆcÞíl@Ó4ȲŒ‘‘w[Ã0ÜÇA©TÂââbÓéJ½Ô­ò{c¨ÿDùÝ.¦z¡«upU<É©®ëÐ4­ï×DÁ"êàk-¿;ÚÖ&‹á–[nÁìì,¦§§WÃÄÄDÇ‹-µÒêqèСU‡9r=ôæçç[]&Ú·oñä“Oöýµ×߀SᙟŸ€®|Ö(¼æçç}©ì,Ãý¦ª*ªÕêšyoŸ™™eY°, ’$®ñ@$¬ýÖ­òûСC{O)8DùÝ.¦z¡—å·auSh8‰:øZu”°Ny×®]˜ššrW°ê0áõj5¤¸U%ýœs΢(¡#EÝ# SQyè§õÆ7œ{oêHc9ÝOÝ(ÃÙå?ïÖ6A366†h4Ú÷2¼[å÷ZÀ¢á#Êo?¦{YçVN¬¿ÞÑ`¯H$‚x<îþt»õgÛ¶mê‡%”Ëeö(Q(0¾)ìºãÜTž‚¨[å7d(¨zUGábK´QkNX{-"cïÞ½îm†a¬˜gC4ˆßvŒq «nÅö mÙDÃ¥«å·§aÆ0 6BÒ†t<$¸Ÿ¦¦¦099‰b±ˆJ¥‚H$‚ë®»ÎïÓ"ê Æ7…ÝFcœ=PT,¿)ìºã†躻è’išm«E´_Öx<Þ´b‹ÅðùÏÞƒÅ8h1¾)ìzã’$±Š|ÕËòÛ4M®–J¾ëiŲÏÖM–eqþ*mHà† Þ¹²DaÃø¦°ÛHŒ'“IÛÛ¶‘J¥°uëVlÚ´ ããã]ïµ6MÓÝöFüd2™ºãÞßY–…D"]×ën×u£££Ø´iFFFÏçý~;WèFùÍø¦ ÛpŒ[–³­ œ²€ñNØ„•ˆˆˆÖ.‘H@’$8pÕjÉd‰D¢«I«mÛ€B¡€B¡€™™èºî¾†mÛ-_/ŸÏÃ¶íº„Õ²,¤R)ÌÍÍ¡Z­baa¹\ŽCĉiË=ªœ¿JÝÈ9¬DDD´vº®C’¤ºýUUE6›E.—ƒªªn2iÛ6’ɤ;vddš¦AUÕPÎeæ\> =ÏüUÃ0ØHCÆ„•ˆˆh#ZÌÕàô44ö0†óÓJ2éöR´|-Uuç‹­F’$·§Ò;G8™LÂX>UUaY–û]סª*dYvïß®µ“ýu]‡¢(0 ’$¹ +,,,À4M躎L&˲P(8¤hPx†s±%ê&¬DDDÑ®ÐÓÛà’åõ=®Ùc<BY–›Îù\m™äy Û¶Ý䵓•šeY®,†·{\>Ÿ‡¢(ÈårœJ­øq.QuÏ5“É ŸÏ³‡†hPx†sþ*u V""¢XϰUY^Ù{Ú…×C½½¨¶m»·‰¹¨‚aeÙí h¦]¯q¦i¶íMÑu²,»C •J¹·7Kx¥f‰;“¢8?p£Â8¬Ÿú +QHH’„B¡€ññq7y4MÉdÉd™L¶m»+ [–…l6 I’0::ŠT*å>&›Íº=®Í†M›6¹¿«ªŠ¹¹¹–ÇżU/UU‘Éd°´´Ã0022âž»mÛuÉ-œ§ÑÊ0 w¸?ÑF0a%"" EQ°´´ä®¬(J]/¥ªªno«·÷CÌÏ!îë½7y¬V««žƒªª-{išæ&±333îð`I’8œhÀq„uV""¢j•ìy·éô1ý²Ú¹ÑààüUê&&¬DDDC‚û!Q?0a¥n:Áï ""¢þ`ï%õƒeYLXiÓ¾ûÝ3qäÈæ5=Ž=¬DDDDDÔ5¦i2a 8ÛvH/EqvT[…‹m¾- Èçk÷ó>NUtÚ¹-“qžCìx–H¬|݃/Àë^wʚΕ +u…eYÉÑ#¦é$”²ì$œËÛYp~_Þκ.iqþ]ZrþÍdêNY®mûíý¿øpnóîP¤ªÎmÞ6 Euo¶È{±¸ˆùùƒkºn&¬DDD!cYR©’ÉdÝ62‰†ænI’N§¡( LÓD&“A:®[Ø0 är9d³Y(вâ9EA6›…išÐuÝÝË•ˆ†{WÛ3M'ÁlìÑô&âÿÙ,LÖz05ÍùX¹¥w³-¾E¢*tRD‹žU¡1aí7&¬DDD!“ÏçaÛ6t]¯KX èÛn&ŸÏc||KKK°mÛM:½ «®ëî9ÏaÛ6ÆÇÇ‘Ëåܤ—ˆ†[ÐV‘,Šm¦ÅIMH¥œÄl-ín–UK>§×Ó¶ë“OËr’¾…çw]wþ=š²\KEÛ¨±S’j‰kØ1a%"" ]×Q(0::Úrx^2™D*•ro–t¶ª|нR¹À  ¦i"Nûz–åüˆäO×kÃgÅPVñ¯(¥–PNB›J­ì±4M'Á™q~I®(½CeWK>âf=£TÄ•ˆˆ(DLÓ„$Ieš¦A×õºÊ£!º€Ç@UU·gVô¶6&±Þç0 ƒÛå‘˲,HͲ´=¥¦éüd³N’hµÞMUuLÏ`“ލêÊá´Í4ÎÓdqØ}LX‰ˆˆ6 Ù*ˆ‚¨ÈˆE.De*Ÿ¯ k$æ'uºâ¢w>à$¡Š¢À0 H’Ô2a5MsE²©ir¹4Ms“ÑÆ„5çYé#™L"™LÖ=/ 'Ó4ë¦ô‚®×æ|ʲSF*ŠSŠ^J&á„•ˆˆhš­‚Ø¨qøW2Ù¾BÕ銋òù<Eq“J˲ê†{E *y“V1,XÌim6Ô·ÐɉÑÐéÅô±ýŠ6+IõCr)ü˜°…„®ëe¹.¡L¥RM‡þ¶¢iR©TÏ{Jˆ(\´µŽ»]…HPÅüSËr†èz'¢áq‚ß'@DDDÝaÆŠ £ªªÈ{w|o8f,1Ùk™˜¿ºÖʧaØ´i“û“h5^šˆÈÃ0œi##ÎI¢XJ&Q*LT‡{X‰ˆˆBb¦É9MÓÜÄÓ»¥ n“eÙíQU¥î¾ÞÛfÏ8ÉïjLjˆš1MgN¿aÔöþL§›¯¬KË=¬DDDDDÔsù¼Óƒ*}ˆù¨KKΜTMc²J+±‡•ˆˆˆˆˆzÂ0œ…“ÄŠæÞç¸ÿ(u‚=¬DDDDDÔU¶íÌIÍd˜”ÒÆ>a-•J(—Ë~ŸQO0¾)ìãfŒo ³Ä·iÖö^Xp¶é"Z¯À .—ËH§Ó(•JœÅ¼• 2Æ7…cœÂŒñMa¶ÑøÖu§Wuf†+ûRw¶‡u÷î݈F£0MwÜqJ¥¦§§ý>-¢®`|SØ1Æ)Ìßf‰oËr¶¤)˜¬R÷2a-—Ë(‹˜˜˜D"ŒÕ-«O4¨ßvŒq 3Æ7…ÙFã[–!Àœ³JÝÈ„uß¾}€X,æÞ‹Å8OÄ£T*aïÞ½~Ÿ¯wß¶ÞŠ0]/c¼½0•iÃv½ŒïöÂTž Ûõ2¾Û Sy6(×È9¬­>•J‘HdÅí?þ8~ðƒàæ›oÆe—]æ÷%ôÜââ"Fý>•»ÞÇ{ wß}7üq_®e=ñ-Îûæ›oÆ9眃sÎ9Ç—sï§»îº ;vìðû4òz±ÿ~ß®…ex{,Ã×ïÀüc<õÔS¾\Ëzâ›åw¸õ¢ü.—˾”,¿Ûcù½~¢¾Öò; k¥RYõØ¡C‡š~XN8á8pwÜqGËLJšC‡óóó~ŸÊÀ]ïþýûñóŸÿgžy¦/ײžø€-[¶àŽ;îÀ\€ /¼Ð—sï§­[·M|wûzMÓÄ3Ï<ãÛµ° oeøúýä'?Áã?Žç=ïy¾\Ëzâ›åw¸õ¢ü~øá‡}IˆX~·Çò{ýD|­åw Vï0„F«}x_ûÚ×ⵯ}­ß§NÔÖzân¾ùf¿O¨#,Ã)ÌÖß,¿iP°ü¦ äÖmÛ¶¨–à×Тnc|SØ1Æ)ÌßfŒo ¢@&¬Ñhñx¼n‚¯aHˆˆ‰ã›ÂŽ1NaÆø¦0c|SmªV«U¿O¢™R©„ÉÉID£Qw’÷ž={VßG4HßvŒq 3Æ7…㛂&° +àLü.•J€x<î÷éuã›ÂŽ1NaÆø¦0c|S:a%"""""¢áÈ9¬Ã¦X,®z¬T*¹-\«oµgV»ãýÖîz¼÷ Ãõ’cµ[|wrMâ>a¹^b¾ÚýÂp½´þøÄ¿õFâ{¯—X~¯v¿À]o•|µoß¾êöíÛWÜ~ï½÷V¯¹æšêöíÛ«Û·o¯^sÍ5Õ{ï½·îqo}ë[Ýãï~÷»W)‹uK†7«T*˜ššD"LLL \.»ÝíÅbîñ±±1 h{Ükmu=B¥RA&“ªªu´ë%Çj1¶øîäšÆwذ gfëï;ï¼sàþÖ‰oÆö`bù=xå7VŸŒaÏž=nyÅb±ˇïÛ·€âÿ±X¬î1bÜx»ãýÖîz„Ý»wcllÌÝ´ºñ¾ƒr½äX-ÆÃß\Àø–á,ÃÃl½ñ}øða÷>Þûùo½‘øfl&–߃W~3a  H$R·„x¹\Æôô4ÆÆÆF[A¥Ri{ðÀµ¸ËðpëE‰DfNËïpëEùýš×¼‘HÄïKëËïp Bùš„õ¿þë¿ ëúÀ|ymÔþýûñÐCñz7ð|‡¨„õŸþéŸê|7êöÛoÇ«_ýj¿Oc`¯÷öÛo¨„•ex¸õ¢ 00ïËïpëEùýÒ—¾t`V–ßá„ò;4 ëÙgŸ EQ055å÷©ôE©TB©TÂØØ˜ß§2×[,1??ï÷e­É¹çž;4ñ-ðzׯT*ù}9kÂ2<܆½ gù~Ý.¿£Ñ¨ß—Ô1–ßá„ò;4 ë°‰ÅbˆÅb~Ÿ¯—zfX¾ø†õz‡Ý°•iÃv½ÃnØÊ³a»Þa7låY®—«Q 1a%"""""¢@bÂJDDDDDDÄ„•ˆˆˆˆˆˆ‰ +V"""""" $&¬DDDDDDH܇•zƶÓTµùqËr~†óU­=‡,;?âwÀù×¶k“e ™¬=P{í|¾þµöï¿‘ÈC~¿EDDDDDÔÖ50M@QœS)ç¶B¤ÕcÛ@&ã$Kª hš“X ƒLÆùW$™ŒóÞe³ÎûhYµÄr5¶]K`EÂê}Œ7ö&¤¹œsq\Qêß÷ÅÅ {¬â÷[DDDDDD-0aí®;IЂ“ü,,8½v‰Dó¤U$·’ä$©ŠâÜ|ܹ-™tn8™L}Wf †,-Õ~Ïfë‹^ÔVd¹þq¿¯¦PXþe‰Uu¸ü‡:㌃˜Ÿ?è÷»ID,wcrô´ô`´BZ0:ê|÷ÌÌø}6홦ó=’N;ßÁ²ì|—Ñpaºssõ¿‹œmtÔùò—$º®ãرëðÍoÆÜDV$eé4 ( …%|þÏ.F©ð\ìÌl±‰ |4ƒ$IH&“[tÁš¦ó²,#Ù"i4MöòxYI’ lô[Þ¶nåVÝÉù|‡ ¹aÔ2{Ûvj%†áüf¦yw´aÔ?ÎKŒöþ¾´ä´6ŒŽ:YÆiåòÆÞ!¤ë:LÓ„eY˜™™ÔðÞÛ¶ ]×a$IÂ#¼ÏyÎYؼù›0—Çq+ŠUU¡6i©°m¦iÂ0 X–…d2Ùô~@}|Xõ~k%*ÈÉdÇ¡î+ËrÚ4m@À˜mù?œ´ê€Ä‹,ÙXˆN 7¿ ©ÔŽ5%­†±²xòùú-ígÛµQ0âkLŒÈñÒ?õfö< àtȲó47ç<îÖ[ÏÅæÍgúý–­›·Ó8Eê¿x¶ß§G(¾'¬ÅbñxÜ—×_šÙl­Ò×,¯³mšÖ¼6¢i6þó?oÁß8‚‹.:މ Ÿüä4^÷ºó IïX–]בÏç¡( F·nEº’Á›:Šo¦€Ý‡á§žŠÛ$ ãããe¹.iµm–eÁ²,·ÂoYFFFÜÄÁ²,˜¦é&²,»Iê_þ2þ£RÁ‰7ÜPw_HŒŒ úðÃøÁe—¹·Àö°ýÀœþÆ7âꫯÆéõWΔN¯þ†ŠÚ¾mCÿ×?DöOôŸ;·7¾¹¶í$Šâüß²jÙýrRÙÔȈsIªŸÌ*ž[Œn”N;5£\°,\ôµ¯á¢;zc~Æw§ ÀišH&“+’P˲Ëå`†›hJ’„ÑÑQÌÍÍAQ˜¦‰|>Ã0 i²Ù,,ËÂï½åEHýPÃ{6ÏâÿÞòK\rÉ™0 º®#—ËpbÛûšŠ¢¸±›Éd ( 4MscÛ4MH’T÷1M©T ªªB–e7ñ5MÓ}>I’êâ[eét²,Ã0œ ±¦­>rb£,«Ö&#†©¯²b¾¶>oYµ÷ÎñN&k‰ÂòÛ Eé_…gb¼rÿýh—?éY‡‘ûï2²ÿ~¥/çÑ8Ï_ÜfÛõóþí}‡¡},y*‰ó“ÈÜþSŒ^õ&ho9ªZ‹³TÊù¿É2:êüëCIrž[4âŠÛ× Ðu@•aþä ©û ‘e@>÷I ÿ@–¡>ëYÀO~R»°'ŸDú¼Û ½àNwG6‰Ìöê< ?½â´ž¾·ÃÛ½fY$IZñ}#ˆI§#¹±,êATUuËFQ¸õÖ'qèÐ!¼ím,?gýš^Í’FUuþŸÏ{Ï»öÞÏH"áùݶ‘P«Í¯û¡-XúÔ·EA&'Á²j¿¬Ï}zá,à±Ç òNztk_þŒq›ªÕjuãO³>år×^{튊äôô4fggën‹ÇãØ³gϪÏU,1??©©©Ž__tf³µy© µã¶mãu¯û>î¿ÿvD"ÿ‚d2‰d2 ˲`Û¶[ùÖ4 étÚ-|mÛF&“qï=v ï9ûl<ï}ïCäU¯ªÕ’Iär@:¹œ¼-,Ëk»¡dUÅy~O úX$‚øÿÀéÇãeO=…+ï»O_y%¶|ë[õjY¨ìÚ…#ßü&~|ÑE¸øâ‹qþùçãä;ïÄáÇñ+®À‰7ÜPŸ(çó8°´„|ãX\\ÄiW\òë_EQÜ„W|q(®¿ÿ~œ}é¥TÖ…/Çø{F°°ó£âäqçÉ'ãøé§¯¼žŒåɪ |3Þ/2‘°È²ì&1>ö±áðáÃH·JÀ7¨›ñ “““mï³¶m#—˹‰®ën‚Ô* "î½D’(*š¦Aótñe2î¼ÙGÿr} øßÁzÞj‘‹†šf#Ä0{M3êî+âë½ïý: o|ãé¸úê‹8i§’Ÿ‡®ë¸ï¾WáÑGÿW\ñAD"÷¡\~=N:éÎ;ïj‰´“ éÌg`¼öÿµ¸»ãoËWæ-?ƒùÓ­P^q§ŽxŸÒ4â_QUµÈÔç? ³|>J¥c8ùäQùÅØzÁpÕU·ãÊ+ÇP©¼Š™wzá—?Ëß|ÛÛpD·ð™ÈžzÑÙÐ&N[Ž%²mâ©?þc8pÇG$Á–-[püøqüêW¿ÂI‡á¤ÉIœúÎw6¼)#€¢ ÿôÛÇ‘¼ïÏÝ,Ö¾ý»°>øÏPvÆj÷oÌ»b›uÙ.g‹‹‹øÆáÃHö¨ zùÝoÞqñ!ض{î9>ø$N?ýtœqÆøÉO~‚sÎy àÒK?°,GŽÄ02òUlÙòî¹gžy濞zê)À–-[/zÑÏðôÓÿ€RéT<úèŸ }—^ú \~ùËñÙÏ^'žØŠóÏ/ã—‡ãä£GñË_þ¿~Î=xã•ÿ[~?ÿùÿ‰'žƒÓNûȲŒò›xâXÔ=çg=ó NûÕ¯€óÏÇ+e¿ñÂ3pÿ™ÿ ßûÞV.¹ä~¼ü«ßÃÏÅ–SOÅI'„O<ÑMO@9öŸµ8uç¹o”ÓâƒkY+[$“É•·‰!’( nºé&ÜxÛm=ý›sùMþZO¼ø’°–Ëe”J%ÌÎ΢T*­ø°¤ÓiD"‘ºa~‘H±XlÕç\ëÅëºS¦4–5ÜdôOÿôïqèÐ^XÖVµÊ=P_­K¼Ä AðTJ §€ò®2´<¹Sä©î$Y Ö´gšõ“@ÚsȲó¯( ;™ê]b×¹ˆŽ+X¢N$ÒÞaâKÌ0œ„áœs^ƒC‡~ÇŽM×Uȼ_p"õ>‡x︕9I’`†û^‹Þfñš­´â5dY®»ŸmÛ°mÛ}½jµŠíÛ·ãÃþpG׿½ˆo {ñw-YϤ`ï߸]C÷oU;0úÂãX81髟s2J1ޝø^÷gÍçk½Žâcàé¼wë´ÞŽx]¯=‡wh¡®×:äZ‹x&ã„¿xÌø8ðž÷ü çþï?¹wÞ‰_ýéŸbËû߸ñÆ2>÷¹­xå+ÿßýî‡pÁ/C¥ò\Üw_gŸ})N>ùI\~ùCضí—8å”§pÊ)O¹qçmðÆ®7NEK2™t{¬Åmb´„àMr¶=Š ¾õ-üÎ÷¿ãÇã}±ŽFÝçýñŒ¯ý뎗f‚P†û*Ÿ‡uÇÏ!ÿ¿ÝÎﺎol>§EOuÿ¶¦é$ Vy3.¾è8ÎùõððÁŸá¡ïž‰?Pt|ò¡oãŠ+¾„o|ã2,,Ñ¿œ€eYøÑOGùà ¸ïéWá_žÃÖmßÁi[ÂÕ}xÎoÿ6n¿ý|ûÛ_Ä©§–Så2^}ð ,—žp~yžÿÜ žuë­n£”!!¦‡äóyȲŒ÷üábÓç>‡]p¾±o_}C¤¢à§žŠsO>wŸ}vÝw°² åEä¾ûðøg?‹§N9?¸ì2|ëG?‚¦i«Nai,sDYí}Î~ÆKÐËï^S>¼gEQð¥/=Œÿ÷Ÿ@’T\|ñÓø³?‹,¿ÛñÀ'aÏžÿX¹¥Ö¯úÿÄž~ ˜xÛë7ãô«¯†nH"sÊdQX‹QVÍ4VÒ2çËÀû½³ÜåÿÄOà‰'žÀ%ÿð+ë6MÆœ=z?ü0Àpÿ%—¸ÇD£º·1\Ô%¼·‰ølר^ß°h6½Ýë®»îbùM¡µžxñeHp±Xt¿ìš9tèâñxO‡)d2+ËÁ|>\.‡cÇnÂïþîOqÁ·áoþ&²\îIµŠ}&S[9ÉK,¼ü!w ¢Æ¤ÓÓ{šN;¿J¢ÛŲù“_gmî|(uçH’ UK:S>µnˆ XAWl%#ò^·]r+r^É®Uæ› !_,Îó««Î_l¢‡­V!gË¿¨”€¦i-çÙŠ$KœK»¹¾íˆK/!¾›±, ‰DÂí©, +ÞõÌu®(¨ÅP&³âon€ý@ûΟ4 ÑS*I€vî¾òço6Údâ‰E°{ïÔ‚´±BbN ‹™¯Èf5­õ’Ób†hõñ{ã&&õy‰Ç´k×åm}jVyó^{úÑ£ãWÞ+ù|™L𦹉ž>{æÌ®¼æÛØõÉ žyæz¼úÕäÝJ_6›­ÿ\5Nêlóšbúš¤Rµ½Ò€eYîµ6e_Ësˆi½Ž— •ß‘ÏçÝD5™L¶mÜ{ïCxÞó.Àùç¿ïzW´Vš&Œ[†R]€´ÿGµžOoͳ“¥úiCX~S¿4.ø%ˆjˆ¨~‰tÇ4ú¾m×¾âD›½hCVn*â ÝòœŸÇÁ³†w¾ÿ;>ÏÀ&¬Ñh‰D•J{÷îÅ®]»066¶ês}éK_rçàµûÀˆ‘·bê‹mÛu‹ÈN]µnïÎf•hÑU)*´lõÒL>_{¨¨éû@$ă° f'ŠÅ"n½õV<ù䓘žžîéët+¾àMoz®¾úêŽ+H^b.è\ãR×R)è?¸ ê—ÞåöšŠ¿{* TÂÌæÝV]4ɨX{ef±à–w€,&‡6žgãpv ¾ÕLcó°zr2ÓÓÓ¸ýöÛñ…/|¡§¯ãWÞmÞu®>å}øÁü}8ò¬gaËy/Áã?,ãw"Žûþ¿º t‘¿öîÝ‹ï~÷»€}èC=y •ßjì±#“EA2™„i*î(,M²é&`ÞÚi»2–zB”ßÿøÇF7þ„«KùMo§yã /ïQÓ¬õ'ˆß›}ÌEç˜hSws"‘¨¬Æ²VÖá<=_Ä='žˆù+¯ÄŸÿÃ?t|}¾¯ܨ\.cbb×]w"g®D4ÅôôtËË©§žŠ .¸;:Xùõá‡K°m¹Üw>˜?&Ô5Z‹nÉÆ?À’T¯\®ö4¢ã'HÂ’¨ Û¶mÃe—]†Ÿþô§}íõÆ7œvÚiرc¶mÛÖöuDkº˜÷›Ëå°à]Q¬mæG¾Õ² Ý’®m¸Ø,!ðîÕ©f÷’Ê׎;p×]wùòÚý(ûɻʴrö?âÁ¯~ïØy.¾ðøém8öÜ{qåG>‚?ëÒÖI´q±X ‡r{€ú¥_å÷zèºîŽ ˆªªø‹¿ø:¾ò•Ó1>¾¼Ð¿b@‘tÀ0¨ëÛ zJ”ßgœqFß_{ÐÊï0òöxŠ$T¬P-FKŠüÏ;ðK×ë«^êÅ÷‡-?Ñ@QÍÖ×ͲæòÐH³É‰Œ:#×ÔfyN«2¢YNQÜ,ùÉr?3 _cù¸„5®hÃôôtËå·O=õT\xá…-[. Ãp·Ó«ýŠ=MW¬›h˜ÑÃ]ÖÅhEYVÏjXE£Q\vÙe¨T*¾¼özâp*<´Ìçr9·¥3³Ü¢ÕlËšºÇ|à(ps ªY¿÷íÜÜòÚwMC9òM`¦Ð»VwV’º&ãÌ3ýÙ£²—ex·Í¤Óøðç>玮±žý›ÿýoEú‘×Ã0 |˜q8±X •J¥ïex?Êïµ²m©åõ3êÊy1{IS,ÌhùÚ*tªÚÓ: mŒ(¿EÂØOƒT~1PÌ;|VQjS÷²Yçwq ¶ý—tñ½Pž[Yžê$CI&ëg]åó˜±œŽ 7¡°<£ÉŒå'k¬Š'i72Îkƒuë­ƒ.a-‹(—Ëu-9‡–[6úáM¥RøÜ羊3ϼ¤õßD4iôi2¦PŽ4 ¿^Æ7w«™B¡àV\· ê÷[ãŸÁB扦A(I€òÒÍ@r®ÝËõ<Æ×ʶmäóùº­ÂLÓÄ›ðÚ“NÂÇ·=ŒTêDg­€û›ºÆ˜5Ï+¥P Zl†T*…d2é6ºçóÎÏ :æÌ €å…-z¸…CÐb|Ј­è¼Cp½ëƈy¡êåA~ð'€}ɤZ—jfšiÖ¯š*ËÀÏ¥Õ; ’É%’íFÆ@àÖH$‚ÉÉIÄb1w íÙÙÙºß×ömȲŒû¦éú,u2™•Ã{H$¬†á´¸°Ž^½Šon¥¼qžj³ÅMr9@9ûgP÷~8ã $ã! ý©ÕŸ¼ Cßi8ô2Æ×ʶm$‰ºUÌà¿¿ü÷±ç­ßGêoÁÝÞ ÉqZŸ Ä¶w»"ïÚÎ1OõEQ˜¤Òš%ƃÊ;DWl»g€X HÌõ¿d‘CÖ;ÍÏ›ˆŠRq¨eSKXc±&&&°sçNÄãqìÛ·Ü¡¼ë%ð®jÕ”˜}ÜÇîNU­íÎd5Üz߀³àF²ÃÄ2™å{œÂ3à-k48zãk!’UMÓVLùHœÿ¤ÿøB¿ß*0~Çv*•r÷%[“éºänu-¶ÿrqØ­‘ß1$bMUQ­3Ýí/¾éS¾ IyÈH&‘Lz>sbGïçP¬dbßlïb„¶m×mŸå½]̯߿ÿš0ô5aÇã+V'€©©)Œ¹”nŒ‰Ã"Û.h¤(}ŸÛ!I·‚ ¡áÒÏøàî¯Ø‰ºŽ¤žÔ_ýŽñNˆ•Q?ó™»ðßþÛN¿@­-Òøð÷€ã€ú—¯ôûí£ Zl‹õ¼ûsºÃ?÷3HÿS™`ï u(h1î'ÑcêMPÅn!ÓDAYïk¢¶Mž¢/_îijÖð°ÑiÞ¤Ql˦(Š»×µØ—Ùjµ °ûžÕö¤·,k¹SÐI`ÅtšÆç‘$ Š¢`qq‡^Ó¹®‡UˆF£]]ÎÛ4Íæ½OkØ/¯—ø3\º߀S0HmzJ Ã)„¹ÞõZ/b¼±øŒ¢(8óÌ`óæÍî±ÌJûИÉÚëz~" ÿ±-a¼+½‹ýä ‰Czӌӵ°Ê1 .?Êï~³íÚ& bô¥¢ÀÝÖ©®ž$˵}¯0uÄ»h¬w½oBÚì1btà$²,»{\kš¶býñ¼²,¯Ú3jš¦ûœíœqƘŸŸ_Ó56aí6gÃqÙ:ã9PÛsÌGAÛʆK³…•<Ý ¹ô ½õYØ»DábY Ãpz òy$w~´n|da_ Æ»¾ë±”^á÷éuD¬ì]›À0€Ô;žÁÜö,äêÏ9<‹hÆÇ=û_W‚òÛ—÷ Fó­Ö³µÞ‰ï0˲V$ÞDÐ0 ·§Ò{?I’ ª*4M[½>Ø„ÖA"ž»•µ¼æz EÂ*ZšnŽÛA·7QеLXÅf]f4Éî| Ÿ|>þê3¿þO+î£~äõ~Ÿ&Ñš¤R)¤Ói·|·, óçOcnË”çF,‡Ëµ£ëN>*zM³;Y¾Å9`-/~T(ôt=Ó4a†û¯è­”eÙž«ª*TUE2™¬nëZ›N§Ûަ £¡HXÅ‚K¢5¥Ž‡N4ÀLÓ\½•̲ú¶E‘Ä" ȿ훰Î~²œ›MÎ0 ض]7I–l,œ˜Þ¹Ám,ˆBλ+LÝÌ?Ó„|Kιaa¡ëIªH>ÅP[Ñcª( EA:vGLˆûxÔF­†á“¡HX-Ë‹_ü;øÓ?]eîÞ¶TP¸˜¦‰™Õ&¦.t££=o@$ò…®ëÐ4 ’$!¯K(|ç"¿O‰hÃr¹\Ýþª”Œï¹Hb–åÌï6 §Î#K6ÒiOÅGQ6´u¥H2k¯gÕõšŠá»b­¾ÛL¯‡Ñ†ÉP$¬¦iâá‡?м|oÚíJ.¢¥‘É*…Q.—C¡P@þmß„;éª×ø}JD¢ëº[áµ,'a-H¬¯5cÛN¢ªë@úíaF™fmϧ ‹‰…ŽDgmmõNꊡHXô£ lÆìì*w`  01佩å!ïºîûºbD=ñwï?öD" ä+_ÃÜçNðû”ˆ6,“É °<•C–‘‹DÔ\>ï$«š,ià“ËÛ!¬±âcÛ6òËÃE©[IÓ4ÌÍÍqx®OBŸ°š¦‰Ë/¿põmclno@ƒM,5Þ”,Ù,ôQNc¥ðI¥RxôÇ?Æ;®»ÖµïÆùj¿ÏŠhcr¹4Mƒ,ËÈåê»&¢¶í –,¼ëË?2åd­kœ›jÛ6r¹œ;½¨ÍEõ.zFþ }ÂjTUZ½• + 8Ñò·úq¦ð{®þÛ׿ÐsœÝAƒOôð,,, “ð³ŸãïÞМ;¢0#Ç$ÛÂŒ•,,OZ][¨®ëÈd2Ð4 C¹ï XSÂZ,Çë~7 ‘H;vì¨;ÿò/¯Â_ÿueõ;pÿ2p-\8˜B'“É@]Ü«*ehð‰ÞUÛ– ö,` øÜ?ú}ZD’Ï;?ª §ã)ӸEŒ®ë°, …BC}®£„µT*!N£\.»›Ô†t:h4 ˜Å®]»066æ÷5¹l°, ²|Žß§BäÛæ‚’†aÀ0 ,4Lêãˆ-tb¾\¡P@*¤ãVH¯z3ƒ›¨¦yê5|> À®ë0 Ñ&L*p¾Ô@è(aM§ÓˆÅbÈårîm³³³ˆÅbسg"‘fgg1==¨„U’€Ë.ûdyß§BÔbõUe2ȦÓìz¢P°m©TÊÝÃN-íl §A–ËåL&ašì¥Hnú?@š«-µU€“ÉÎËzñaÛ6Òé4Wò`m—S,‹(—ËØµkb± R© T*all ‘H066†J¥‚b±è÷5Õyì±ÿ¨ý2:Ê9«:-VÓ„e3Y¥pH¥RH&“õ `$î•DƒJô®&“Ig¡¥‡Þ¹ÊÆñDÃÇ4DÀÃCNŒ´­Ë‹¹à£££n/ªÊ¹Q­mÂZ*•ÇÝĨ­œåýã{E*…úÉÓªêD½`YL`)4 +*îfù|,O÷#x¦i"ÝdÉÔl–½«4ؼC•'ï„úûr(0œzÍø8ÿ²ß|™³Ù*£Æ2™ FFF0>>˲°°°Ðô;ƒOÛ!Á‘H•Jý¢E¥R ±X,Iª –¹®KX%ɹQ$Úb[]h@†áƸaö}Éú9Û o ˲š&0MÆ8 <˲ÜN€ì£ÿƒC‰Pkˆ_¸ææ¾°ê*À¶m#‘H@UU,q1ÕPjÛËÅP*•P*•8à ÃX±"° ¼mÛ6¿¯ €äÏþÃõ7* {T)tÄðÈl°¾þ@ý±èÃ\p‰BÁ²¬¦{áÏy<‹> $Ó4qöÙ—ÂøôCNaÎuhÈÙ6zÇ3˜9ò6H§<åì­Ú$Y5M£££H&“Èf³~Ÿ6õHÛÖX,†x<ŽÉÉIŒ¡X,¢R©¸-•Jóóóؽ{7âñ¸»j°ßLxö³óÏ÷Tpd¹~H°irGn ëЯÕ~q†ø}JD]ašfÓýñŒÛ¡ZLƒÍ²,|÷»—À²5Ë …‰ ûÂÿ岨ӈӄØCunn®iƒ&…GÛVÈf³PUÕ]úÙ»ÓÍ7ßì®"¤– ÃdÙÓìn-×h›âY¡§æÝO,5b@>ã°î|йÁ¶‘øîÿaï…‚mÛ++$¦ ë© ü>5¢ ÃÝ9"†È!™´}Y5YÍçóÈår( LV‡@GÛÚD"ìÚµ«é±±±1Œ¦g¨ú]\üNmÎS*嬸çm†÷ö¶ Û¶¡ªª³çð[¡üú!XE@¾ú"À¶a±ç‰BÁ4M$kó¶ {Ë%œÃJMlOÆd•È©Ã'ÀBAqXª;fC×uäóyH’„B¡Ðtä …OG=¬­D£Ñ@%«@ýºJnÂjÛN²ª(µD•-2’i`æÕÿŠìüêåÞ4Í›ý>5¢®°m–Õd±£[ü>5¢ ±, -ý6ìŸ>á÷©ù.Ÿ_i IuL†a`tt–eannŽÉê騇pUšŸŸìرcÅ¢KA"6Ïåš,° aËDeŠÆÛ†|ñÓuó´ítPˆ$@µê¹Á¶Ù(Cϲ,Üs×» æ8&˜†^³¥e,ËB*•â\Õ!ÖQÂ:==ÙÙY÷÷ÙÙYLLL`jjÊïó_•3]uyUIËZ9WÕ08•ž(¸óŸ<Ê«T(ªŠÌ;GNÞÊrÂÀ4MȲìîLæÆµ¦AÊo詉|÷oœ‡WÃ4.¶DÃK×<ò´?:¯îvÛ¶1>>Žl6Ëduˆu4$xvvccc0M¦ibll ³³³+ög "I’œ„µ1È…-™úcÀò¾ÈúÎè.¶DaaÛ6dY†òä°¿ú=÷vËbŸßþ_„×¼àQ6¢ÓP˼û(~óŠÊK*•‚¦iÐXص¶ «Ø_ubb½Mô¬Š½YƒÊ]AµÙâJ’®ÔAƒJ×=Ã؇N‚rÃÀÒüãœ2Ÿ!Na`.xð\w³ø+÷vYf»# ¾'+; ½á—~Ÿ‘o2@;å ÿçïÔÍ[Íår€4· z/ºä]X)²Ü“X¶ ,¯ºçþî­¹g2~Ÿ!цäóÀ½÷­ 9v¬vpù¶¬f2a¥ÐxÖ©QH[7ÁÞÿ”{›eq$ ¶\ΫN¾“ChhÙ6 ê)¤Ï›­›ÀjYòùE € ¯H¶ãõWµßM³~¨i²–CMUyOÀòí NqåóËsAØ0C!aš&ÞðœH_òYà‰'ÜÛó“÷°(§öµÿÔÍß÷£a•ûÀQ$MCú§¿©»=•J!›Ír%`€„U 9n¦T*¡\.¯ýIeOíßçœãü®iõsXÅBLD=Ö“ø†Ò_ùÊé–§h¿ùR÷˜,æWŸÀøþ·ß—OC W1îeY.¬üjfÙmsoW¿ÿ·¬çSÏô#¶ÕcÓ¸úêGý¾TRýˆñV, Ðo>‚ô;Ô5Úd2(ŠÂy«äêx[›ÉÉÉ·MOOãæ›o®»mÏž=¿x¹\ÆäädÝ\l¹Ðï·€B®—1î%Ë2ôÅ+ \~!¤û‡wõÂ{&¬ÔýŠí—?x+*oû_~_. ¡~Åx+æ—AvëGê¶œÌd20 …BÁï·ˆ¤më¶mÛ011X,V÷311x<¾âöN”Ëe†±ê$êÝ»w#Â4MÜqÇ(•J˜žž^Ó…Í_|1®X\l~ÐÙó¦Ïo5 ‹~Ä7, jä?ðoœM«o“QÀþ¯0÷†öû­ êKŒ/3–×#ÈßõÀxå°—·Ø6OÜá÷[A!ÓÏØÎç¿>ï%Øqà ~_6 ‘~Æx;ÚÞ -]kuL¥R°m…BC©NÛÖh4ÚõýV‹Å" Ãhz¬\.£X,â–[nà,ð466†½{÷®éÓ@’€¹¹®¾‘DB_â[–ñÓsŸÄîç}™×Þ³òðÅOÃŒ^ë÷[A!Õ¯2p\RÖSÒ{”—n, Jôa¿ß ™~Æö 7T‹ñû’iÈô3Æ[Éd¼ÁIVmÛ†®ëÈz†yuœ°†k¯½“““˜u&''qíµ×vmOÖVŠJ¥²ê±#GŽ`ÿþýnmYNܱÃúÛlVï"L4TÊå2ñøãûòÚ«ißpøða‹E÷9þåâ‹¡ýà½0¾¾r Dòo/ƒôÒΆèSø‹E÷|(Êé~_* ™nĶaÊáoàþK.Á%~_Qƒn—ß^– R|Ãk8 kÒ;™•hmÖX,†J¥ÒvH€Xp)‰tüâñx¼iOQ,Ãç?ÿywx±ïÜ)˲X™'ßõ*¾‰‚¢×1n$IBþŸOƒš8¢“U~NøÉOl÷û- êel›ß> å¢G‘7MVÖÉ7~ÔQô™Ð.ü6 ]˲`š&Tïð¢Ut”°Æb1¤ÓiìÙ³§iBZ©T0==x<ÞrÂöZD"Vä)´6ßLA×­2\–e¨'Üé‚Ôn;óq$ÒW£ún¿¯’†Ñ†Ëï¯Dò¥›%N_¢`êU\ÿç_bî­O;ÿgï*­AGÛÚìÚµ år;wîÄÞ½{ÝÉØår{÷îÅÎ;Q.—;Z¬dYf‹ …šmÛŒq -Ër~Äâyê3·Cynm}„äÛŸ†²ù‡~ŸÔ% ä€IDAT&Ѻd·ÏAþíçpqH*–À¶!§œù°ù|ž +u¬£mmb±öìÙƒééiìÞ½{Åñx<Ž©©©®õ®n”,Ëlµ$"P¦)¶²1!Ë2¬oí‡ìm ‘$,¼â] ~Ÿ*Ñš)åÛuv&ã÷©õ,Ù˜“3€üy†áì¯Í­l¨C%¬@-i[×”J%w¸p4E¥RA±Xä0^¢>`Ë<…™ØkUUÈÄ÷®Á’÷Šhšß§I´>Ù, IlX§áb_ïtl‰Õ‰:ÕqÂ*ˆ-n­T*arr’sëˆú€ ‹Q˜‰F÷£G·dX.¨¿‡’Ñ R6:ÒÐɘ²Y ¶mÃ0 ÌÌÌø}J4@:šÃJDÁá4fª |ík'8½P[¶ø}:D]eš&{Xih˜æòV8½«GÈÐ1a%@Ük˜BͲ ¾øI8°–%C:ùI¿Ïˆ¨ëØèHÃB–‘ð€³]VZ«5 &"ÿq( …šiB5 <úè_ä‰Wú}FD]Å!Á4L$Éù±m¦irJ­{X‰+ PÓ4À0ð¼_û'°^OaÄ!Á4L2¯½‡Óúµía-•J˜žžnûD•J¥í}ˆˆˆ:’Nã=úlû}`c<…V–˜ß8 ÀœN§ý>%@]ëaD"ÜÒ†ˆˆºâg/z^ùÈ#À‘#ÜÁ†ˆh@™_~Êyû8˜6¤m«Ø•ˆˆ¨_îüqœüÂ"÷£H^w¬¶× Q˜¦‰$·f¢!`~ñ!(/üt]gÌÓºq+Rñ…/Dú‰÷8{"… ‡Ó00¸êÄ6®LÒ6a-‹+ºï+• ŠÅ¢ßçNDD!eš&œu’3 8‰•†«Ó°°‹@zãÕ\hŒ6d]ÛÚÜ|ó͘…ÉVo""êÛ¶Õ°¹"6…VÆ­OB=ç˜æÃœ»JÂ}X‰ˆˆˆúˆ=M4 ”'¾ ùw Ó:˜§ áV"" ˲ü>¢ž`ï* iñ;û9\˜6Œ +Ž;$˜(d8—†EY@Ó˜°Ò†1a%"""ê#‰Û4QÈY–óãüßb# mHÇsX'''ÝÿW*•· ܳ•ˆˆ6Š‹úQXqH0 I²Y'Þ™¬ÒFµMX·mÛ†‰‰‰·Çãq¿ÏˆˆBŠÃÇ(¬8$˜†$9?†ÁáÀ´qmÖh4Š©©)¿Ï“ˆˆˆ(˜°RØeÞ¸ˆìÿ=†a0ÞiÃ8‡•ˆˆÅ0 Îñ#"P–˜wTIâ`ꊎ簖J%ÌÎÎbbb±XlÕî}Î;""¢b‡ÂÊ4M$“I¿Oƒ¨gŒÛŽ@9µ`LÓÄÌ̌ߧD®£„Õ0 ¤ÓiD£QD"÷ö©©)D"†R©„Ïþó~_ 8.JCaÇ 3ë®G¡^}ÜïÓ éhHðîÝ»¡ª*n»í6D£Q÷öX,†±±1ìÙ³;vìÀÍ7ßì÷õÑ€ã¢4DDƒË¸ód(/>†apÁ%ꊶ k±XD¥RÁ7ÞØò~7Þx#fggQ.—ý¾&""`Édš¦ù}D=Q(ü>¢ž±mGŽ@ºö°,‹ëPW´\*•FëzVg[ïð`q|ß¾}+î»ÓÓÓ˜]ñšÜç•€ñMa·‘gï*Ëp ³Ä·aê _ä,Ë‚ªª~_…@Û„5‰àСC+nïu¡¼oß>ŒÕº7A&dŒo ;Æ8…ã›Âl#ñ­œû ”Ë¿ Ó4‘N§ý¾ ¶ k,C¥RA±XD<_õ~Åb@÷ ìC‡!·|M¢AÅø¦°cŒS˜1¾)Ì6ßò¿¼üBà`êš¶sXc±b±¦§§Q©TšÞ§R©`zzñx±X¬+'&àééiLOO»¿…ã›ÂŽ1NaÆø¦0ÛP|'“Àr¯*“Uê–ŽV ÞµkÊå2vî܉ÙÙY‹E÷gzzoxÃP.—155ÕÕ“ãç+• &''±wïÞUï{äÈìß¿Ÿ_ÔV¹\Æââ"üq_Ïc-ñ ‡F±XäÂfÔV±XÄÁƒý> –áÔ¥R ‹‹‹M§+õÓZâ›å7uJ”ß«uõˆÊoIbï*5%êàk-¿;Ú‡5‹á–[nÁìì,¦§§WÃÄÄDW[311ë®»ÎbF1==±±±¦9räzè!ÌÏÏsˆµ´oß>,..âÉ'Ÿôåõ×߀SᙟŸwïO´šùùy_+;,é—DÂê—õÄ7Ëoê”(¿:ä˼èn•ß–eqKZAÔÁ׬ºF¬Þu×]îÏÁƒ×úërðàÁêöíÛ«wÝuWÓãwÝuWõ¦›nê˹Ðà Z¼´‹ïjµZ½á†ü>M A‹–áÔMA‹—vñ´Ï#[Ðâe=åw6›­f³Y¿Oh=åwGC‚½"‘ˆ;»qk›n)‹+†ˆ®c®ÂGƒŽñMaǧ0c|S˜u+¾mÛf+uÍšÖ~ˆD"ؽ{7J¥’{Ûì쬻Ñ c|SØ1Æ)ÌßfÝŠoÓ49‡•º¦£9¬ý‹Å011;w"cß¾}€\.ç÷©mã›ÂŽ1NaÆø¦0ëf|³‡•º% +LMMallÌý p Æ7…cœÂŒñMaÖø¶,ËïË  l 8«’q5= +Æ7…cœÂŒñMa¶‘ø¶m²,û} "œÃJDDDDDƒÇ4M¦®bÂJDDDDD]ÁáÀÔmLX‰ˆˆˆˆ¨+,Ëb+uV"""""ê Û¶¹¥ uV"""""ê ˲ ªªß§A!„•ˆˆˆˆˆº‚sX©Û˜°QWpKê6&¬DDDDD´a†apþ*uV"""""ê ö°R·1a%""""¢®à‚KÔm'ù}DDDDD4ø˜¬R/°‡•ˆˆˆˆˆˆ‰ +V"""""" $&¬DDDDDDHLX‰ˆˆˆˆˆ(˜°Q 1a%"""""¢@bÂJDDDDDDÄ„•ˆˆˆˆˆˆ‰ +V"""""" $&¬DDDDDDHLX‰ˆˆˆˆˆ(˜°Q >a-•J(—Ë~ŸQO0¾)ìãfŒo 3Æ7ÅI~ŸÀjÊå2Òé4J¥@UUär9¿O‹¨+ßvŒq 3Æ7…㛂&°=¬»wïF4…iš¸ãŽ;P*•0==í÷iuã›ÂŽ1NaÆø¦0c|SÐ2a-—Ë(‹˜˜˜D"Œ¡P(ø}jDÆø¦°cŒS˜1¾)ÌßDLX÷íÛˆÅbîm±XŒãè=D2,Ât½ŒïÎìÝ»×ïSàõ®c¼½0•iÃv½ŒïöÂTž Ûõ2¾Û Sy6(×È„µÕ‡¢R©ø}z°oß>ÌÏÏû}¼Þu`|wÆ0 ¿O×»NŒñöÂT¦ Ûõ2¾Û Sy6l×Ëøn/LåÙ \o ]jõ8tè"‘ÈŠÛðƒ೟ý,þíßþ —]v™ß—Ðs‡ÆáÃ‡Ý ña×Íë}ôÑGñ‹_ügžy&¦¦¦ú~-ë‰o°, ¿õ[¿…­[·âÜsÏíûy÷Ûƒ>ˆÉÉI¿Oc ¯wqqGõíZX†·Ç2|ý|ðAT*\rÉ%¾\Ëzâ›åw¸õ¢üþò—¿Œ×½îu}¿–ßí±ü^?Q_kùÈ„Õ; ¡Q4mzûõ×_믿ÞïS'jk=ñ ÿþïÿî÷©u„e8…Ùzâ›å7 –ßD¼mÛ6õÃÊårËÊ<Ñ `|SØ1Æ)ÌßfŒo ¢@&¬Ñhñx¼n»aH$~Ÿц1¾)ìãfŒo 3Æ7ѦjµZõû$š)•J˜œœD4E¥RA$Áž={VßG4HßvŒq 3Æ7…㛂&° +àLü|ãñ¸ß§CÔUŒo ;Æ8…ã›ÂŒñMAè„•ˆˆˆˆˆˆ†W ç°1a €b±¸ê±R©ÔrߣR©Ôr“çvÇû­Ýõxï†ë%Çj1¶øîäšÄ}Âr½Ä2|µû…áziýñ=ˆëÄ÷ ^/±ü^í~»Þ*ùjß¾}ÕíÛ·¯¸ýÞ{ï­^sÍ5ÕíÛ·W·oß^½æškª÷Þ{oÝãÞúÖ·ºÇßýîw¯xÞVÇû­ÝõxÝtÓMÕn¸aM״륚f1¶øîäšÆw¸° _‰1ë‰ïAü[o$¾ñzÉÁò{¥ –ßìaõI¹\†aH§ÓMONN"Ã4MÜqLjÇãu÷ݽ{7¢Ñ¨{¼T*azzºããýÖîz„b±ˆÙÙÙ·ÚõRë[|wrMã;LX†³ ³Ä÷ þ­7߃x½ÃŽå÷à•ßLX}R,ëö¸jÞ={ÜòŠÅb+ö»Ú·o'Äÿc±XÝcĸñvÇû­Ýõ»wïÆØØ¶mÛV÷øA»^r¬ãa‹ïN® `|‡ Ëp–áa¶Þø>|ø°{ïýƒü·ÞH|3¶ËïÁ+¿™°P$©Ûóª\.czzcccˆF£-ƒ R©´=´ë€½{÷¢\.7-<íz©µ°Åw'×Äø.a‹q–áäÕ*Ž=ºêã‚ú·ÞH|3¶Ã‡åw½ \/Ö«T*˜žžÆµ×^‹x<Ž]»v¹·¯æÐ¡CmízÊå2fggÝß›=n¯—Z [|¯vMŒïá¶gN^ÍâaÿÖë‰ïA¾^jåwíqA¸Þ“|zߨR©„Ý»w#‰à–[nYÑÕ¾šh4ÚöxЮgïÞ½ˆD"0 †a T*aß¾}n Ð ^/µ¶ønuMŒïá¶gN^«Åàþ­×ß###y½ÔËïà•ßìa ¨t:íŽ;o 1¾ÜÛ _.—ÝÀhwï¼óòz©5–ßÁ»^ö°a(—ËPUuņÆñxÑhñx{÷îuÇ›†D"mízÄ –ÂöŽ¥¤ë¥ÖÂß\ã{¸„-ÆY†“W'ñ0HëÆ÷ ]/µÆò;˜å7ÖËLONN®8fš&'&''Ýåª#‘®»î:÷~íŽízÚ¤ë¥ÖÂß^S+ƒv½ÔZØbœe8yµ‹‡Aû[³ü&/–ß+áz7U«Õª/ï mX¥Rq±Yw~»ãƒfØ®wØ Ûß{Ø®—†ïo>l×;̆ío=l×KÃ÷7÷ûz™°Q qÑ%"""""" $&¬DDDDDDHLX‰ˆˆˆˆˆ(˜°Q 1a%"""""¢@bÂJDDDDDDÄ„•ˆˆˆˆˆˆ‰ +V"""""" $&¬DDDDDDHLX‰ˆˆˆˆˆ(˜°Q 1a%"""""¢@bÂJDDDDDDÄ„•ˆˆˆˆˆˆ‰ +ùÊ0 ضí÷iõ]·cß¶m†á÷euV"òU"‘€iš~ŸQßu;öMÓD"‘ðû²hHåóyX–å÷iõ㽿˜°цèºÎ < Æ{ä÷ P·µ&™LB–åÇdY†ªª0 ÉdÒ=n†;LÓ4(ŠâËd2H§ÓÈçó°mŠ¢@Ó4÷9%IB:^ó}‰Ö¢U|@.—ƒmÛMc¬[ñ½žûmT/c?›Í"—ËÕÝ.ض\.·âqDÑ,žÅmº®TU]Ÿâ6–×4H6ï¶m»±+I’É$$IÀØ^+ö°D*•B.—X–…ÑÑQ÷’ÉdÜcº®c||ÜýNeg||€SAE>Ÿ_qܶmضñññº¡h¹\™LfÍ÷%êT«øÇÅ\¾Æëf|¯çþDÑëØO¥RM[úmÛF"‘p+BDÝÐ.ž½šÅ'Ëk$‰wÛ¶122â68êº^7eƒ±½FUòÝÂÂB@uiiɽMUÕj:®.--­8&ËrUUÕjµZu/,,¸Çgffª’$¹¿¨ÎÌ̸¿+ŠRM&“îïétÚ}¾µÜ—¨­â»ZubNü¿Zuâ·Wñ½žû­W?bßûøB¡PP=pàÀЏ&Ú¨vñ¬ªjµP(¸ÇãSÜÆòšÁFã]”ǪªªºÏÇØ^ ]סªjÝ0±B¡Àiai<¦išÛcdY®[Rünš¦Û²î}¼$Iî„fÖr_¢vZÅ· ªªûïýzßë¹?Ñzô#ö½D+}6›õû- é$ž5‹O–×46ïâq©T š¦AUÕglwŽ kÀµÛò@ ;C„f_Dƒ†ñMÃj#±/æO¥R),--ù})DDCG–e w*ŸmÛH&“˜™™ñûÔÖ€hLL Ãp']·JZE$Iu­6-ðD~[-¾½ ‡5Ãø¦AçGìÏÌÌÀ¶mèºî.BÔ ëg¢A´‘xuø™™ÌÌ̸ێ)ŠÂÏË:pÑ¥H&“0MÓöeÛ¶»‡þë=æ]tû ™ &~A«øn‡ñMƒÌÏØ—$É]±’[/P7tÏÄ6Ñ Øh¼{{V§Ç•C~×=¬ Ë2fffH$ ªªÛ*#–¿n<&*2@­R’ÉdÜŠeYmÇÙõK«øn‡ñMƒÌïØ×4 š¦!•Jñ3CÖ.ž%IB&“q‡> ²Æ{2™„®ë¢(îèMÓü¾´´©Z­Vý> rX–å¶„‹yJb˜,Ëî>¬b¦¹¹9÷±â~@m(Q4‹ïN1¾i1ö)LV‹go}¥q¯a¢AµÑx=´’$q*Ó0a 8˲022‚……(Š˲H$N§Ù‚IDDDDD¡Æ!Áç’`Û¶;É*…{X‰ˆˆˆˆˆ(¸J0Rh†뺎O}êS¸è¢‹ü>•¾8xð *• ¯wÏwòÉ'cvvÖïKëØ5×\34oX\\Äe—]æ÷i ìõ...âk_ûšß—Õ1–ááÖ‹2\’$|ìcóûÒ:Âò;ÜzQ~ÿýßÿ=b±˜ß—Ö–ßá„ò;4 볟ýl¼úÕ¯ÆÔԔߧÒÅbóóó¼Þ >ß ¹è¢‹°gÏ¿O£o&''y½|¾AÂ2<܆½ gùn½(¿%YX~‡]ÊïÐ$¬Ã&#û}¼^ê™aªì ãõ»a+Ó†íz‡Ý°•gÃv½ÃnØÊ³ \/ç°Q 1a%"""""¢@bÂJDDDDDDÄ„•šeY0 ÃïÓ jʶí =Þ4Mäóy†±áç""""D\tiÙ¶ ]×aÛ6E¨ªZwÓ4a†{\–eȲìo¬DK’Y–¡ª*dY†a°, ¦iºÏÀ=&Ë2,ËrŸ[–eH’䞃¸mÛu¯/žCÜ–Ëå`šfÝk¬víâœþçÿüŸ~ÿ)BÉûwYÛ¶a†Š¢¸ÿïôñº®Ã²,Nl*ŠRã"¾Åg@’$÷~âñI¢,ËPÅGŸ^âsàoïkŠøTÅ}¼¸M<§8O˲Ü׳, ¹\nÅ{kÛvÓÏ<þøã=þKõÖ>Ëd2°, ÉdrE’(*¹¢,*ÒÞ ¬H%I‚eYn%[QhšæVÄ+ÒâùÄkhšn¥<“Ép*å¢Ò,I’Û{iš&,Ë‚ªª0 ªª"›ÍºeqÞ"Q B2™t/qÞ¼½¥étzM‰Š—išnòÐÌ m‰0lÛF.—ƒ®ëœFG"³, –e¹I–÷o$:¼ñéMMÓܘ±/ˆDN$˜š¦¹ŸÃ0 ë:2™Œû¹ŸI’ÜÏŠ8/˲ iÒét]Œ†áþˆä5™LÖŘˆßÕâ[¼ŽeYŠïN Ú¶6DDacš&lÛ^Qß#¢µaºF¢²Ú, ›ÐXiÍd2PUš¦!—Ë!—ËÕ%‘¢¬ªª{›èY=)Éd…B¡®¢+^w||Ü}ŽÆÊ°(4[U¤{xV»þl6»¢¢-€fÖÒÛÖ­B½]O+5§ëº›Àyÿ"Qq$xßg]סi–þÿíÝœõ}'þ— $Ø`Á ­S2‰Õ$ ñ8«4¥¤£æšhÕÊäŠ9o[ª-{Yš^ûˆt·—¤¿ö*Ý·wíY×mVM.ë‹Û†U²Ú¤m4BZZäzr¤¹ ð@ÂÊvøá1Z†@öûÇø3ýþ±’f4z=¯~Í|¤·>;ïÏÏcÇê^ €Ýï|]‘à9“¸FŸaö¨€fiÆy<ñèEí¹·;V3Íê¢QÓìb\|Ÿ›ý^ûˆïI,³RuJ¡PÀ¯ÿú¯»ýKÚ5J‹éB®MÄ(K"ÖÄèhÔø*ž/âQ4”ŠFX稘\.g7jGȈk¿fS=8B†¨Ö.d³Y¤Óéª^EQ:{Åý¢7Fü¡^\\´‹Åìûb±Ø†¬VÉ¢ó1í8{s›a+¡iš†t:T*U57Xü1 !Θ±mòù|ÕÅC,³{J›é4ždYF"‘ØpÙ£IäE"©¬Zo’ÉdÕs£@\Ô·šr‘N§ënsNï¿7J.TU­;7çûd2i7†©ªj7Ær”ŒwmdZˆh¤Éž¸¾1"þNÕ+W›žž®ºÎrN×]ªªVþßÑ9päÈH’T×ø X×T©Tªê6ñZ¢cC<¿Q 8¦½p„ Q5&¬•h£ È9Ó‰É Ã00==åååŽOØSHÔ;ç|zç¿Åôq»s>6Ð8¬Ë\û»¢(˜žžF<G"‘°‡È' Äãñª×®íñ©ö> ¢ñ”#½G$d"™tj4-Dô8ŠžH±>€H>Åg,^KÓ4Äãq,..ÚÇIªHN‰DUlˆÆ—l6 EQ iZ]j+íV;i|:[þí$êÖíÝ»·áPX€½64úD|s(5QoD/Œø9KñÿÚïWínqŸL&í üÚ àV ¤˜ƒÝè{œH$L&±sçNȲÜð‚žßÓ“]׈Qf±XÌ^OÃ9 VÜ'¦…8G™‰!¼ªªÖMkr6Ø8§3u2z °¾;ËËËö0ßÚ×'¢ÑÇ„µFíÜöbC´°y™h¥?â‚•ñMÔž*/IRÕ÷%›Í"›ÍBUÕºEóº]\K¼n/Ã*[­Q I7¼Š7ù—HHE¬8{ðÅ‚‘µ£Ìœ‹EÖŽÐé´—¼“éH`¯<‘¹š° LLL  6¼¿X,"4½¿ß¦§§íE‡ÄņU;W¨/Æ7P½‚.ÑFx-ÆAôœŠVÄC]בJ¥ ëzÓé"1¨¤’ÉjgüÛ¦iÚÃfkçMŠF—#GŽÀ0 {ÔˆýX,†|>_÷šÎűh´ø1ÆÉ¿\IXWVVÉdP.—áp©T @P*•H$P,X­fuè'q1äÈ‘ºûXS7¼ߦibzzÚn5'Ú(¯Åx¿‰yvbŽØÆËizz{÷îµ{–8ÑüÛâï@í¾Îâ61”VQ,//#NCUÕ¾7Æ»üãä_ç û€år™L³³³Ðu÷Þ{¯}›0??`0hß_,«îï7‘¬òbž6Êkñm"‘Ea|S_x-Æ7B¬&ºgÏD"ûG$ªÇŽÃââbÃFËÅÅE¨ªÚÕBeäm~ŠíZbêÅÅE,.."ŸÏãØ±cÈçó ·ËIk<g²ê#~Žqò·¡'¬ÅbårÑh‡Q*•X-;…BSSSöýÑh´áP”=O@ëdU,Ðh@2 d³•û4­þ§É¶Z4¼ß¹\‘H‰D¢/[ÂÞŠñ^e³YìܹӞwzäÈäóyû§Y’Z+3Yõ‘Qít:H$‚d2i`/Ôì:ǹÇ(ùÛ¨Ç8¯¡ ‡ÃuûY­®®bëÖ­ö¿  Ù÷‡B!ûËÔ/bŽF£¡^‚iÓÓ€,© I€ªV'¤gÿ8^·òx?^ˆoçþŠÊEýæ…ï•®ëØ»w¯=ó9Éi”c°Óååe{;1¿0ú1NãËÕE—fffì/Ç¡C‡ å—¢\.Ûcìk}ÿûßÇñãÇQ(‡[7N#›ÍÚCºj ëVoj<ˆÎ)‘°:Õ&¦¦ ìÙÄÕËJ¥Ž=Šgžyf Çég|ÀóÏ?ßr‘±žØÇι¿"—B¡€gŸ}vàÇq«ï…išØ»w/‡ðú@±XÄÑ£G±¶¶6°c »þÞ¨l6‹X,ÖñV0ä]¢þnS5Jõ7y“Øq¢ç–UÂÚÚ¾óï`×®]]ËÕ„uÿþý(•JXZZÂÁƒ1;;kOodmm­å—åĉ8|øpÓ/‹®ëöþvzž’I«ÇT’E–—­ÿwC’€³[‘G­®®âèÑ£xî¹çzœ~Æ7`]ð>|^ðär¹ª…3úÅ0*#Ø!5>Ü2ÖúeØuøFˆáñ¼˜}"a¤a×ß•N§Ù‹ê¢þnS5Jõ7õ—s;ªft]‡a0M³áßM±h[£ûœûŽ×®H~ôèQ?~Ï?ÿ|WçìjÂ*‚: ‘H`vv¶jB­V•ü¥—^ EQ0;;Ûô1ÓÓÓH¥RM·ô`¯èxq'.}œ~Ä7\vÙe-ãÛ0Œ /‘͹œó5­$UQ¬Ñ²l=&³gÈ›fggñµ¯u÷Ç îÃ{5== UU9êÀ'¢Ñ(‚Áà@ëða×ß¡iEáwŸ˜E±Xøv2£RS=±E•Y³hŽ¢(UÉhm z<Åö"™óÝ{yÇãñÔ)ªªâío{×õ÷ÐÖL&ƒb±ˆ……û61v&&&XÃÄ—Ãùï~¼QNº¤ÓVoj?MO[ù®DÐ Ó´ž×Mç€aXe“$+7 «YQ*¯ãœƒë|kt½ò˜dÒú¿HèuÝ:Iª,4%iDo2iÝ–JUŸ³¦Y øŽÅbÕï‘8®iZç^K ˯9=m=¶›Ïozøâ¯A"Ñÿ‹7ã[×õžWJ&­÷3«ÿ<q啞^¾OµÏ7ŒúáþNÙ¬õ˜xÜ:–ˆ{Àš2P›¼‹ûUµúuMÓz-ñ\QG8_SünÖcu½2êC44#^?›.ºh÷@Þo·ëðnˆU€c±÷Ò¦¶F)¶²Ù,c¨#£ããÄ0 är¹ºd€½•¦iˆÅbU ¦HR%Iêz4‘ÚêÂÂ#†ž°NNNbii ÅbÑnÉÑ4Íþ2ƒA„Ãa¬¬¬Ø-5š¦!‰l踢²–if˜c"QYMX̉‰$U.‰J¯U6k]¬ÆãVB .N³Yëw‘$./W.fe¹’`lÛVé ³Êl½¾¸_¨OXMÓJ\L³>)¬cçź,WÊá¼h¯½6L§«/ðUµ2üZ¼G{öX÷9kÖcÄãÄû(W'Ä‘Hõsœ‰·H¦ àW~åA ¢qÞ­ø¶ÞC£ëÞUñ™ˆÏ¸“§'•8êE.×x>¸h\iÔ{«i•c:ïD¬‹_nÛVù¼eÙúüM³2Ĩ4¦ˆx (¢‘IÔÎLjÛÅqEÜëzeκˆéX¬r¿x­\®ò½‰Å¬sPÎ×”åJcŽh ï·¦Y¯“LZ·Åb•äWU­ï‚xŽææîð3½PM¸ãÝØ»w/LÓäâJÔ1¯Ç¶¸PCõĪ¢Ç„¨¯Çø8Ð4ÍžÂUË0 »ç³ö;-zGc±Xÿý^¸²Jp4ž}û‡±ººŠµµµªÖžÙÙYÌÌÌ P(Ø“¼÷ïß¿¡ã6»˜¯íéçJÁ"aUÕÊ…5P°‰ N!³. ÷îµþÏW'Öâ‚ßY¤S§*¯ TK<§6‘ì¤Ó¡öýI$* QuC$ª^W–+çï,_»s©mƒèd ,O=Õýùw­ø6M³«‹ò\Ί«^â_ôö5"Ëf# "‘J¢‹UÇ‘HÀD£I2i§HäœIj>_‰g繈‰j£]j¿kÎï€xP}nµå礪Öy'“Ö÷U¼Ví|_‘d‹ÕÆÅûè|Œ³ñIœ§óøÞs‘‹×iö¸~r+Æ»‘N§!I–û=t†|Í뱉D‹Å‹Å ª*4MƒišmÁDx?Æý@$–ÊårPÅ^ ­ÛÆÔqþ®oZ___wãÀ¥RÉ^¬Ñír¹Œb±ØôþZ…B‡n:~>™LBUUß·@PgÚÅËFõ;¾kE?ç'±ç^»aé´•Ö6žôbïÞJ/¸®WF ˆ$N×+½–µÇröèý’O­ã¥†]‡wJl]Ã-ümuø°ëïNär9èºÎ¡ícb\ëïQ$’SÓ4ík1‘Xʲ\•”Ö.@4®z‰×] ƒ-Çċ͌û¥Ùü¾tºzø+Q? ;¾5MkY jš•<ÆbÖpÑ~Ô—‰„Õ*†­Ö¾¦¢XÇjD’¬$6›åwoT ;Æ;aš&¦§§±¼¼Ì‹ê™c;—Ëõ´FQ#^ŒñQ i²ÙlÝ4CçBE‹í  †\]%x˜š sʈF™išMGˆ9›½lÓÔJ?†ŸrꑬŠÕ‰üB -d\ sX¯sxo"‘àtŒEÂ*'h†ëqШ3 £iÂjšÍí%Uº®Û«³Šü&—ËõÜ5¢aÉårHŸÝ¢Â9œWUU{Þ)¹clÖfA¶‘ÕN‰¼ÂhÈB~¦i’É$y1A¾¤ibˆHÓ´ªÅú¸²¼÷ŒEªiZÓàcLÒ¨k5‚À¹­‘e³Y¤R)&«äKL48Ùl¹\€5Ô— ³z×9nŸÀ04ëam°'/ÑÈiv1“ËUö&ò#Ã0Z‡'uLÔ?Éd›6mB$A$®ëX\\D>Ÿçß‹Öf +{ŸÈš%¬’ÄEÈß²Ù,â rò±l6ËUG‰6H,Ê'IN:ÅUäGÐX$¬Íp;òÃ0¶À³±üNÓ4ä¹¢ù”Ø?žÃ‰z£ë:4M³G*p.øèò}ÂZ»WR-6²Ð¨k4‚ —³VÆ7ùU6›å&ìä[š¦±A†¨¹\š¦A×uȲ EQ¸’t•° …ª„ …4MC Àää¤'7n¶ÿ*`ÍïëÇ^’D^bš@:Íý…Éßr¹R©”Û§AÔwbøâòò2dˆ:dš&"‘EªªJï3%¬Åb‰D¥RÉÞ8W,³ KKK˜››C4u»LUZ-È¡ë\%˜F›hAtJ§9w•üÍ0 ˜¦É¡’äKÉdñxœñMÔ!‘¬Æãq®kàS­œH$ …pèÐ!û¶¥¥%û¶{î¹³³³Èd2n—§N£ z!gï*6Ó4«âÛ4McÂJþÆÅ–ȯ¦§§€síˆ:Ädu<´MX …J¥æææ …årÅbÑh@FQ.—Q(Ü.Sf «¢pŽ6Ã0ª~gï*ùišÈår¼0!ßÉf³0 ƒC‰:”N§±gÏ&«c mÂZ,‡í݆¨jë¼ßKÄæF¸G%:çwÓ´[bM~Æ})Ét]G6›Åòò²Û§Bäyš¦açÎ0 GŽa²:ÚÎa (—ËU·‹E„B!Ï&©N­æ€ðâžü$—ãBKäétš+§’ïhšUU¹ÈQ †aØÃæóù¬@sss ï‹F£ˆF£žêYZ ±á¬äbaÜüÌ9üÈoZ5°3Ã0ÍfqäÈ·O…\ÔQ XsT> ˜œœ´ç°z1QŒ6U™°Ò(Ó4ÍBÆ]ÈïZí©M4êØCÔX2™D*•âù1×QšÉd°´´dÿ¾´´„©©)ÌÎκ}þ 麵bj«VUeÂJ£ð4.œ[8ù‰¦i¬Ë‰j˜¦‰H$UU¹•u–°.--!ÚÂççç±´´„ýû÷{rkE±öX=rä›>¦ï×=g÷¦…$Õ¯ædí—%Vë¹^³ÓÇwz¬Ú›¦•å·"Ëõ¾®×O®=çÚyÍb³ÐVç×+™l~µ‹±hZÓ÷pÇñãøöˆ_ ˆ!d{÷ZÃ]o oGÄx£8kv¬f­­b¼7ß§fÇnãµù}rjU·èzÝ}¯}ê©öïãÑu Ž{'2M“½GDº®cïÞ½H¥RLV @ «Ø®fjjʾmvv+++(‹uÛÛxE*|ö³ïA6Ûx¯UMk’´Š @ñ€Ú%“ÖÅ¡H¸œ²l]46º¨ìäb¹Ó lq1¬(õ a£cÕ^Ü7ºÀnw~º¤ïC£Ç7bšÖs]| þp·kahôY¶ž§iuÇ+=Š3Ï?Qfš&ÞñŽŸE.×C²êlØhãB£/Kí>˜º^iTht2ºnÅjí}θ±áÔ(ƳY«Ñ£•FÇÊf«BIªŽéncÜù<§A|Ÿ€Jýâäü¾×Óo «oWQ­m¨h×°Ó(¶ý­jÔ`'êAñý¯ùniŸ9Üy'pâDÕíÊÖ‡!÷Ì\ým·Až}?dÙÑ6óÉOÅ\Ð?õ ðíoW=Îy,ã…í0nù(ä÷^m+†u~^|ñEÈí:\àpw¢Š\.‡d2‰ååe•'[ÇsXsU½Ø«ZË4 ¼ímA:ýûPtÜišum}$uö¹®W~ÄEa³žž^VBnt1щaK–{;V/ÛKôz¬^Þ?ñ6xî³[·âųs²G•išxøá­hÛø((gœ‹†•Fïk£îv¥>‰íD¯q×Kì-/÷v¬n óûÔâûþ33ø¥î_Ñ“ Ãp÷‚Þ0꿹œ•žM8µÿw¤§®$i/½ úû>j/†–ÍÆÊƒÀ·¿]÷òñûGÈo¹Ù'‘{î|¤þGe¤P.àÑ«`žÙ ýd€õy'n~©Û…þHÉßy ­v‘€~xa·} sí\˜O½ŒcÓÿ<:=RiÛÉfÜ_^ iýßB¾úè«—›7ÿó~ðm˜ß¿Ú?½êÙ·Ãn›¹ê6àªê2É2 œ i- ÀÑîe𮹏æ˜Ö]•çÅIŒ³ùvÌt<€úç7îºë øIDî¼ pÃŽk·ß•áÊåröjÀlÀÙ FS“jGÜ4›~×njWŸF½]ôÌ3]É· «y¶9V’ê; ìϧ—"0M'OniÝù|ì˜Û§I´aNXÏŽ00Oœ~ýoA¹îBH’èUÜ]ÿ}È;~å§¶@ŠXO‘b@6eTÚyTU|­Z¯_û7í¡ÔŒo‡»wõÔψp&"!L¥¬g3/Â8a5Èè \]¶Ÿ ò­?‰lÖz^*¨²ìÔ?!÷­kxüØå_CüÃ[`ªqhšcF$íÑÛê/†®CÛ¨ª=0O’˜&dCƒŠmP¯Ô«­~²ª’E®˜¤ÞvÖo³’ŠÔâߌ‘éL.—Ãâââè'«"YltqÖh=g‚(Z/jŸã|Œ˜Vç¬3jG¸5›šäœrÒlúª6_'§‘G½=¹cGWï8a™™©»-“ÉààÁƒU·-,tÞ$T,¡P¨éý@ §­s¸g¹mñ X «®÷6’”¨ã‚®ëˆwèbþ¦¦Á|%¼õ­BW }r?ðÕs!ÿ¸õ·¸Ò«ç5|©1Ï#ÆÖ°b€o’U±þ›þùÇíÛôÂË€ø[ ˆý÷Ÿ¨ëUÔÃ3H>zðòËa@Ú¶É~®¼ù”O©Tõ¨|Àb!ŸA ^í8‰' é?nýÉêëhSBücW ŽSâM¯iE²†Ï˨ilÊçÑɪ—’dÈŸøºN» ÎwWVþy 3ÆÛ1 Ã{×í­S½Š†a%‡µ÷‹çÔ~·%±íÄ^¦ súÝ´MX'&&ª\šx'ŠÅ"‰J¥k~l:¶_³T*!‘HØ_&UU‘N§»>NÝFóˆúlXñ-ËrݺAMW#ê£aŸÐñÖ\Îj>ÛJlN'‰]ŒÄû­ äþ|Ó˜q#¶½ž°jw=í³OgÎ@ÿƹÈßüI •²;~R)@ãú?€~é!_ò,äןc½?a@}ÏíîÇÚ^E¥°€Ê¯“MÏ¡êÚ[U¡t{aÝh¸Ý˜vŒw"—Ëu×(ÙOét¥‹ßÙ{).°-xØëZŒÁžµMXƒÁ`ß÷[™™ªª˜››C¹\F&“A"‘À=÷ÜÀÚ6' âСC(—ËØ·o2™LWçQ7'Ä4­ý?96‹jñ­i$IªÕžLV&Ñ Ð0b\èfÁ%MŠa1$ ¦Z‹Åãh¿0ÑYÃŒmÀŠo/ô*¥ÓÖeR*@Óüèy0~°úÑ  ¾ê^(?ñjÈŸBâã?LXÝÕ8 Ôµ/€—ãÞ7ìïD.—Ãò ¦é‰'Å0ÝFCnEBÊdÒÓÎö …Êå²ø@SSS(•J(‹(•J( v¯n @4E¾ËHëö5Û»× Rüa ÿV|5«JNO[òâ¢ÛoùÜ0chqAv$±`]oäóV»Íν7‚ÓxvlVãú°{Xsÿó{˜?ˆ½;þ¹jN}½.ËÖÂ@¯ÿ ŽÝ·ŠÅg?ˆøßE¡~ö6HS7ñÂ~„¹ãíˆmú2w5›µþ ìÙcýˆÅ€TÕº>jô!cL€®]* 8ìØdrr²«½XC¡ª¶ÆY]]`}1Ä¿CŽC¡=t¡S¦s_»éi«…W.4`Êo]×qôè[üð¤^ø ëF&«4ÊqAÓ´ú ðºOS)ä4¹ªULÝéeú·aÇ6`]«¨ƒ¼X6 $ÿÃKпq.ðƒÀxòB¨—ý+âѧ¡ì3 X_”ªEŠeÊÒàzÓÈ=nÄx;¹\®ßðP^ùNÇ «¦i8pà@]Ð.--Õo%T%¸¥R ™LÑhÁ`…B¡ésËårÓ=`Ÿ~úièºn[°/pDÓ;ƒ—Î* ¸ë®»ðÜsÏõýµßðä“O"“É`rr¦iâÂW>ù®ÿ|PâÕ9UÉd2xâ‰'òÚêÃÃ0«Ó›N[Wر9Üw쬬¬à_þå_úþºÃª¿ÇÄV1;dy@6 õü×#öKÛ ¼;p¶'©»Õ9i¸Dý]*•ú¾àѰëïNär9ëtGÓ´zMµ³;×vDñZÈóÄ5x·:\(H$011t: ]×íŸt:‰‰ ìÛ·¯e ×ãæo¼ñF„ÃaÌÍÍÙ·7³¶¶Öô¾-[¶`ûö혜œ„¦ixw ` $&«Tebb»víÂ%—\2°cô;¾à‚ .Àää$&&& ë:þ\ þÉIVÐTgrr²åÅs? ²w2M³zH°aX+ñ8œih|„B!ìÚµ [·nÈëºþvª‹ï™¶†CÂe`_ö¤RP?{”ù(‡=ŽQ*¾áÕßítÜ»j•¡¾†a5XrÔäH×àÝÆwG=¬óóóMW SUªª"‘H`~~Þž´ÝJ±XÄüü<:T7ô ™V-M[¶lÁ•W^‰p8ŒÃögøõ¯|Åj…aM5‚Á víÚÕ²bÞˆAÄ7`]ðˆ–Ñs/}ñ‹Øü¶·¹ð’×…Ãa\tÑE{ýA×áNzí&æg{W ÃZšàÈ‘¿™ä9¡Påry uø0êo'£vóÑäÒ’ Žüú Hàuü¨õ÷ ‡Y·“Íf‘jÕènV¯iV’ʨ‘×ë5xÛÖB¡€R©„;å㜓¶ÛI$ö8úÚ/‡h}t=îvXÄÕü Ê_ù “UrÅ ã>qÑEøÈ'˜¬’;†ãBUï“Ø =G:Í sê¿aÆ6€žš1M }G Éë@äŠo"ýñï#¿lBú“»ýöÑvŒ7cFëé´µV¢ÇޱÂsmÖb±ˆ`0Ø6XEз˘5MC©T‚ªª( U?€•y‡Ãa¬86MÖ4 ‘H¤ãBI’„«ØóD.F|Àµ×Þ€>4ÌumX14è}J§aÎ~ Ù¬·õÍ0c[<·Û„UŸ[Áží%˜ù#P¯þ–ÿê9ófÈ7¾Ùí·FÀ°c¼•l6ÛzïÕXŒ‰*ÙÚ mçftCôÀÎÌÌÔÝ'†~ÍÎÎbffÆ^~;`ÿþýn¿WDm +¾?ðãüóÝ.-£aÖáµ[Ú$_‡Ü¶ýˆÅ¬íkˆúÉë“n\’Kÿ€#ÿ¼ÒÛnrûí¢ä¥kð\.‡#­ætôc›ò¶ «˜+ÒnH€hi7æ~vv¶í b¡Pwß}·ýÅêvL<‘[†ߺn­'F4lìÃÍšU•Ì÷üŽ|’±Oƒ1ìë“N÷`ÕõÊ|miéÝ~›h„yå<›ÍBUÕJüëzež*Q%¬¡P‰D¢nï&A¬6‡;ÚÚ¦µKoùÉFãÛ49E›¼­u¸ØP^Xüü¥n‹¨o×'îÁšËY[Ô°¡††eÐ×à¹\®²Ø’h‘Y^v»Øäamk377‡R©„}ûöaeeÅžŒ]*•°²²‚}ûö¡T*u½÷õF×9Z†ÆƒHX9g›ü¦í Á¦ ¤ÓH¥¬ugˆü j±%g²Ê §:ÚÖF¬&–Éd0??_w8ÆììlßzW‰¨5Ã`ÂJþg$I²÷‰çŽä'ízXÓ?ÿä‹'sûD‰ú(—Ë!‹Y 2LV©C%¬@%i[׋E{¸p0D¹\F¡Pà0^¢!àÞ“4D+¼~¨ˆXŒ ¢ä/­zXÍÿû8²ÿôfùÞ·O“¨¯r¹–——­d5‘`²Jé8aÄ7µ­‚Åb333õ›¼Qßq.Ã0Ã@ünþ˜­4ä/­\JÿÒ7{ÏB’˜°’†Y–!g³V¢Ê-k¨C]'¬DDDà Ë2ŒÅ<¤Ü ¶ÑŸ˜¦Ù4a5>s?rߙıâv·O“¨¯²Ù,öƒÖ£.t´èÑ0‰-möþŸ„ùî¨Û§CÔWº®Wí1lßžÖ°÷×.Bêã/¸}ŠD}—Ëåð“wÜÁ©kìa%""ÏÑu¯ô=øaèû¯{³Û§C4xÉ$¦3û‘úì¨?w¡ÛgCÔW¢‘æâ×½ÎíS¡Ä„•ˆˆ<ç¼çžÃß}÷ßâÿ¬p00ù¦iU{ GžçâbäO¹\®£}‡‰i›°‹Ed2™¶/T.—Ý. ùÄ_ÿÖ·qÍ寂ü¶Ü>¢ ëô´X†Øår9;vÌíÓ Õ·9¬@€[ÚÑÆ>ÿøÍˆ¦·¹}&D¡ë:$I‚aX«¾s±Tò»O?ÿ¼Û§@#¬m«Ø•ˆˆh²™qéåbûöÍnŸ ÑÀ(² ˜R)yã/FäaßüØÇ°i ©w\%˜ˆˆ<%þÇ!\ð†ÿÅùNä[º®#}Ë¿ÂXÌ»}*DwîW¿Šoÿø»}4ÂÚ&¬…B¡néõr¹ŒB¡àö¹‘O=÷ÜnŸÑÀ(Š‚ìW^y:âö© –iâòo~WÝv›ÛgB#¬§ÖƒbffÆís'""")†aà¹Ç"ˆI s80ù\.‡üÅׯŠMÔ &""Ï‘$ngCþdÎ+O"ÆEid³ø³W^aÂJÂ}X‰ˆÈSîQIä««Ïã;§®òá׺}*Dƒexå•WpÞßèö™Ðˆc+y{Xɯ–?ñCüòEwr80ù_6‹‡¯¿ž ´aLX‰ˆÈSt]wûˆæäïÅu‘ÓnŸÑàÉ2¾|ÑELXiÃ:ì\d©\.×Ý&pÏV""ÚEQxC¾õÉM?ƒ¹}ÅíÓ ¼x'’I¨×^ëö™Ðˆk›°NLL`jjªîöp8ìö¹‘qÿUò³ÄîÝÈ_wÛ§A4º®#‘H¸}4âÚ&¬Á`³³³nŸ'ÑÈK¥RnŸÑІÁ5 hÃ8‡•ˆˆˆhHEqûˆ†Â4MNï ¾èxk±XÄÒÒ¦¦¦ …šV¸\,ƒˆˆˆˆhŒE"Ð 6ÐP_t”°jš†D"`0ˆ@ `ß>;;‹@ MÓP,q÷Ýw»]"""""r“iB×u¦¾èhHðüü‰L&Óv´Q&“ÁO<áʱY‡Ó ­¬¬à®»îÂñãLJz\Öß4 ¢þv£!¤oõ7W¦&Ä5x·õwGû°†B!:tKKK /&¢Ñ(¦¦¦êfêE«/ÄÚÚZÓ!Ç[¶lÁöíÛ199¹ás ›˜˜À®]»ðØc ýؽÆ7\pÁ˜œœÄÄÄÄÐÏ›FËää$xàWŽÍ:œ- ammmèô¬¿iDý½uëÖ¡»/õw8 0r9Äb±¡—¼M\ƒw[w”°Ö*Àsss˜E±X´o…BÍ[íT«!Å­â-[¶àÊ+¯Døì…¨™`0ˆ]»vµm„^ã°.xßÔ‰p8Œ‹.ºÈ•c³§Akk »gýMà êï~^[wªŸõ·išìa¥:½^ƒw4$Ø) Û?ýþB‰ÖGgæ]*•úÒ{Kä6Æ7ùcœüбM~×Ï7 Ãíât°Z0D8®ZÁLÓ4D"·OhÃßäwŒqò+Æ6ù]¿bÜ0 ®L}ÕñàašÅÌÌ …Êå2öïßïöiõã›üŽ1N~ÅØ&¿ëGŒsÁ%ê7WÖp8 ]×ën…B¸ûî»í¹²œ÷A£ˆñM~Ç'¿bl“ß 2Æu]ç–6ÔWžìa*se‰üˆñM~Ç'¿bl“ßm4ÆMÓ„ªªnƒ|ÄssX‰ˆˆˆˆh4éºÎ9¬ÔWLX‰ˆˆˆˆ¨/¸èõV"""""ê Î_¥~cÂJDDDDDÆáÀ4LX‰ˆˆˆˆhÃLÓdÂJ}Ç„•ˆˆˆˆˆú‚+S¿yv["""""LViØÃJDDDDDDžÄ„•ˆˆˆˆˆˆ<‰ +yç°‘oè: ËÀF·„Õ´Æ·K (Ö¿“Iëÿ©”õÿl0ŒÆÏ«}L_ý{³óS”Êù4:v-Y¶#Ê%Ë€˜Ê¬ëÖù½NqfÂJDDDDDž#’/ ’ìˆ$MÜo•DJ$e¹\ã$Í0¬dS$²¦i%iªÚ8IK§­ÇÖîÔ#ËÕÉ[m"&ËõÏqR”ê„:¯$}­ž#Ê#ÔþÞˆHn›ýÞHíùÈ2H4~¬³QÀ0¬gÂj•Ï0ž}v®¿þñö'áÀ„•ˆˆˆˆˆ†NÓ*I©Hv€JÂdÖcœÉßâbëdèO’Ö(AìäXíOñÚ£D’:ëíä½(Žâðá'»:>V"""""(M³~TÕúÑ4«GS ¯Åê9E©¿­]²JþÄ•ˆˆˆˆˆú®vˆ¨ªVN‘¸µÃU‚‰ˆˆˆˆ¨¯Òik¾©˜ã(TöR·ØÃJDDDDD}#†û;æö™°‡•ˆˆˆˆˆúÂ4­UyÝ>ò &¬DDDDDÔÓÓP"êV"""""Ú0]·zX›íÙIÔ &¬DDDDD´aî]JÔ &¬DDDDDDäILX‰ˆˆˆˆˆÈ“˜°‘'1a%""""""Oò|ÂZ,Q*•Ü> ¢`|“ß1ÆÉÏßägŒoòŠsÝ>fJ¥‰ŠÅ"@UU¤Ói·O‹¨/ßäwŒqò3Æ7ù㛼Ƴ=¬óóóƒÐu÷Þ{/ŠÅ"2™ŒÛ§EÔŒoò;Æ8ùã›üŒñM^ãÉ„µT*¡P(`jj F‘çÆNäŒoò;Æ8ùã›üŒñM^äÉ„uuu …ìÛB¡ÇÑ; …±jíòSyß™™™qûXÞ1ÆÛóS6nåe|·ç§úlÜÊËønÏOõÙ¨”דsX[})Êå2@Ýí‡Æ_ýÕ_á _øvíÚåvîÙgŸE¹\¶çø]?Ëûä“OâÉ'ŸÄ–-[0;;;ô²ôßð­o} ïyÏ{°mÛ6\vÙeC?ïa;zô¨¯.†YÞ£GâùçŸw­,¬ÃÛcÞ»'žxÏ>û,.¿üò‘©ÃYûÛ êï/}éKxßûÞ7ô²°þnõwïÄ5x·õ·'Ör¹Üô¾µµµ†_–ýû÷#" º}úCQ.—±¶¶ÆònðõÜ*K3Íâ>ñ‰OTµxú]±Xdy7øznaÞëðþ¼ž[ei¦Y|³þö·AÔßn½¬¿ÛcýÝŸ×ë†'ÖV_ÒfoV hz¡ïG,¯·^¯½Äw»çùËë­×ë×±Y‡³¼^|½nô߬Ïüõ7ë3?óBýíÉ9¬ª‡%”J¥±iÉ c|“ß1ÆÉÏßägŒoò"O&¬Á`áp+++ömš¦!‰¸}jDÆø&¿cŒ“Ÿ1¾ÉÏßäE›Ö×××Ý>‰FŠÅ"fff íIÞ cÕOþÅø&¿cŒ“Ÿ1¾ÉÏßä5žMXT­H‡Ý>¢¾b|“ß1ÆÉÏßägŒoòO'¬DDDDDD4¾<9‡uÜ …¦÷‹Å–ÛS‹Å–{fµ»ØÚ•Çù8?”—,ÍbÜoñÝI™ÄcüR^bÞìq~(/õߣøYo$¾G±¼Äú»Ùãëq+/ßgîvy™°‘'qÑ%""""""ò$&¬DDDDDDäILX‰ˆˆˆˆˆÈ“˜°‘'1a%""""""ObÂJDDDDDDžÄ„•ˆˆˆˆˆˆ<‰ +yV""""""ò$&¬DDDDDDäILX‰ˆˆˆˆˆÈ“˜°‘'1a%""""""ObÂJDDDDDDžÄ„•ˆˆˆˆˆˆ<‰ +yV"r•¦i0MÓíÓ º~ǾišÐ4ÍíbõV"rU$®ënŸÑÐõ;öu]G$q»X4ƲÙ, Ãpû4ˆޱ>\LX‰ˆˆˆhÃr¹/âi,0Ö‡ë\·O€Ã0ÍfënÇãe@¥%G–e¨ª MÓÇíÇjšf‹ÅbPž/™L"‘H ›ÍÂ4M(Š‚X,f¿¦$IH$]?–¨Ä7¤Ói˜¦Ù0Æúß½<ž¨WÈýT*…t:]u»`š&ÒétÝóˆzÕ*¦5MƒaÈårUUëbTÓ4Ö×46몪Â4M;v%IB<‡$IÛÝb«˜¦ ]×íMÓì À êt: ÀjÑÙ»w¯ý%¬‹½{÷Ú¯µgÏžª/™¸ß4M˜¦‰½{÷V EK§ÓH&“]?–¨í⦧§íßkc¬ŸñÝËã‰z5ŒØŸžžnØÒoš&"‘ˆ}!DÔÄ´SmŒ²¾¦Q±ÑX7M;wî´s¹\Õ” Æv—ÖÉSN:µ®(Êz"‘X____?vìØ:€õcÇŽÙ‘ey]UÕªû9bß¿¸¸¸.I’ý;€õÅÅEûwEQÖãñ¸ý{"‘°_¯›Çu«6¾××­˜sþ¾¸¸8°øîåñDý0¨Øw>?ŸÏ¯°åŒk¢~kÓªª®çóyû÷Úe}M£¨—Xõ±ó5TUµ¯çÛÝa«ÇLOOC–e¤R)V‹ŒªªUÃÇb±˜ýoMÓ Ë²½:¤ówçbÎçK’dIh¤›Çu£6¾UUí;ãoñÝËã‰6jP±ï|¾ Zé+ˆú­YLתQÖ×4jz‰u·ÓÓÓÐ4 ’$!ŸÏWÅ3c»sœÃê!Éd†a ŸÏÛ·µÛò@ ;C†…F1Dnjßí0¾É†ûbþÔôô4Ž;ævñɇz‰i¢QÔk¬Ë²Œ|>oOå3Mñx‹‹‹ni$1aõˆl6‹l6‹|>_ÕÂ"IRˤUQ»ÕF-ðœ·D^Ñ,¾Ûa|Ó¨s#öaš&r¹œ½Q¿ôÓD£f#±.NZ\\Äâ⢽혢(U‹¦Rg8$Øt]Çôô4–——ë.Db±˜=Ù€½â˜à\…L¿‰¼ U|·Ãø¦QæfìK’d¯XÉ­¨_:‰év#ÈFÁFcÝÙ³ X=®làéV+þF"lÚ´ÉþI&“e‹‹‹ˆD"ˆD"سgOÕ0qQ’L&±gÏ{Éååe·‹E u|·Ãø¦QævìÇb1Äb16ðPß´‹iI’L&nB4J6ëb ›;w"‰`çÎe™k ôhÓúúúºÛ'A͉!`²,Ûû°Š=šœ.Î…8ÄP2"¿`|Ó¸bìÓ(q^³8”!ò›Nc]Œ”$‰S™6€ «Ç†;wâÈ‘#P†a ‰ ‘Hp <ù]ò8ç`Ó4!Iâñ8“U"""""ò=ö°‘'ù¦‡õ¾ûîÃç>÷9¼á opûT†â™gžÁ3Ï<Ãònàõ^yåüþïÿ¾ÛEëØ‡>ô!¼ñotû4†fܶ®éwyu]ÇÒÒ’ÛÅêëpD¾uëVüÖoý–ÛEëëoDý=??`0èvÑ:ÂúÛß¼Pû&aýሠ/¼“““nŸÊP=z/¾ø"Ë»×{ì±ÇÜ.VWÖÖÖÆæó€x€åÝàëÖáþ6ˆ:¼T*¹]¬Ž±þö·AÔß[·nu»Xcýío^¨¿}“°nÙ²W^y%Âá°Û§2صkË»årÙíbuå‚ .›Ï~á~åÝ€‹.ºÈí"u…u¸¿{ÎúÛßQ·‹Õ1Ößþæ…úÛ7 ë¸ ƒ#3T„å¥^D£Q·O奷:mÜÊ;îÆ­>·òŽ»q«Ï¼PÞsÜ~ˆˆˆˆˆˆˆaÂJDDDDDDžÄ„•ˆˆˆˆˆˆ<‰ +yV""""""ò$&¬DDDDDDäILX‰ˆˆˆˆˆÈ“˜°‘'1a%""""""ObÂJDDDDDDžt®Û'0Nr¹4MƒišˆÇãPU`²ÙlÕcMÓ„aEQ ª*dY†¦iÐu’$!‹AQ·‹EDDDDD4®'¬…BápØíÓhÊ4tH¥*·‰ÄÓ0 ;™4Mš¦Ù ©3‘4M¦iBUU¨ª I’Ëå0== I’ìäS–åªc+Šb¿n.—³‹Å`Òé4t]¯zž¸Ÿ‰¬7x=¾ûM|D ¦iB×õªÇ†QÓ4šÆ-Æi|0¶Éïã4*\MXK¥fffê.d3™ –––ªn ‡ÃXXXêùår@2 ¼ð 8yò“(•îaˆÅbPUŠ¢ØÉ$¨ªŠÅÅEûù"™”$©îµUUµ{PkU'I’ÇÞW{»aÐ4 ôG+øÖ·¾„mÛ¾ŽóÎ{†aT%Ë€•XȲŒÍ›oÀ·¾µª Ȳ•@8“ EQìç|ñ‹A:D ð n¼ñ$Þÿþ’}\Ã0 ˲]–/~ñEÜu×qæÌf¼ím".¼ðÐu¦iB’$;©·8ð˜œ|ïxÇ}ueçñÈ#œ8±/½ô8sf3yäi¼ôÒQH’Ôð}|ðÁIÜwßÏâ½ï]Á®]ß´o?~üxË÷½¼ß­ˆÄS–e»w?›ÍV#Ähgâ{‘L&!ËrÝçí$I4MC:†¢(U±äläœ1Fîå'j…±M~ǧQâJÂZ*•P,ë¾Âêê*¢ÑhÕ…j øy麎\.‡œÄ7¾Æúú)¼úÕ³¸üòÿˆW^¹‹‹ï¯»Xn–LhÛËÙé…w6 È2 ª€aXÿv2 ë¡ëq> Äb@"ˆ\ùÏþì0t}†aàÉ'çŸÿAÜyç…(—Oàœsþ'x.¿|7ßüqæÌf<ÿüÛðº×­C×uœ>½ ÿ÷Q\|ñ)üÂ/|ðÕ¯^Ï~6„›nú \|ñ)˜f Ÿþôsxë[ ¸øâSxì±·àÖ[ãê«_…O}ê5øå_~.¾ø€«ðçþ84MÃG?zNž bïÞcˆD¼÷½ßÃâbKKïÂ5×<‚§žz-`ÇŽ',áäÉ î»ïgo{›„M›"X^á o8ÇŽ­áرÊ{ò®w}ï ozÓfüöoßàr—㓟|=y$€ï~÷\üÜÏýí@âÈ«ñÝ̽÷–qôèQ|ç;V|èºn'ž†a`ïÞ½vCÍòò²Ljšv2Ú¨aFÓ´ªr¶"†º‹ï…išöhçë°_LÓ€ªÄZüä@>?¯Å·`š&’ÉdUR¨iòùŸÆ®]»ðË¿,w<œ\ co§Ódt]aTZ.Ð4àSŸ*#øLóA¼úÕ·`÷îSxà¿Å¯üÊoáøñíxî¹ç°}ûvlÛöu†þð¿àå—_‹]»>f÷Þ*Š‚3g6㓟|'NœÀí·?޵µ7`jÊúÜî¾ûœ9³ 7ßüIÀ}÷ý,àôéÓ8sæN<õÔõxË[Žâ­o-@ÓNáôém¸óÎÛ°k×7qÝuVCÈ¡Cûñ _Ç /lÇ[ßú0~ã7Ç?üÃøÔ§~ˆw¼ã>œ<Äý÷ߌ;Oø,þàþ‡/àoü.Þõ®oà²ËÞûî»_ÿúf¼ÿý%\qÅ=8t¨ˆ»ïþ5\wÝ“øÐ‡Vñ7s?Þó«éßãÁïÀ+¯¼‚ÅÅspå•ßX,y5ÆÇ‰zߨ¡ˆz7α-íÓ4DÃa.—«jäk÷wÂÙ¨éLLE+G[õu³TNñx¼ê1ÙlÖn€t6ªŠón”H þÝjT¾F÷·zLmyECë sŒÓèÚ´¾¾¾îÖÁ …BÃኢ`nn¥’5ätrr²íÇJ@cvv¶ëó8t¨ˆÿôŸnǾðß<1÷sçNë¢]ôªÖ2 qAïö™Ž®ÄK7ÇèW|ÀÌÌLÏCrLÓD$±RMÓpúô6üÚ¯ý´k1¯iVÈ¢ñxe¾x.g5~Vc„¦¢–Êf­¸÷§Ó•Û$ÉúΈwî® ‘HåÄãÅk6»žÈ媿oŠ2¼ï_£QØH¼tÊ+uø0‰5 :éÅÎ `‘Õ±. õ¢¡E$¢·¨¿À `}b‚3Á­½`¯M~#š é¯}\³ò7z¾è¥sNï…óõœ †˜²"IÖ××qíµ×âw~çwò9{©þî7Wβ‰DUÄ•HN5MC,«K‡¥Ubé,O6›µã,—ËAUUÄb±ªç7êé­mðiw¬Z²,7gL7z]Ã0ìuLœÉ¹iš8~ü8¾õ­Á5:ãY“7ô/žMXƒÁ "‘Êå2VVV077‡h4Úôµr¹þ÷ÿþߨ±cGG"àMo:ƒóÏÿär9,//·¼pD€|~ðï‰aÓÓÃ9Ö¸ZYYÁç?ÿyœwÞyM‡ÄôC?ãn¸áìØ±ªª¶}l-±À—,§ìöX¬z1±a .¢‡½¶QÆ4­$TQ†›úÉÌÌ Ž=Н|å+=Ž›u¸²Ù,Òé4 ‹!uö ¤i²Ù¬=LR\€Šhºê»Ð¨Æ™è9Cg‚Ú(at¾–H>D’â\;¡Q‚èšï\g ÚÇŠ‹o1µ@$âqâ>g¢,Þq[mÙÄí™L_úÒ—°cÇŽºöûÅKõ÷F9…kÔ¾÷µ ÎÏkTzñÅ. ñx|dιQÿéŸþ)B¡ÐÆ_°‰q«¿ÉÄ5ø¶mÛÉd:⺋xàõÝ»wWݶººº~àÀõgŸ}Ö¾íÓŸþôúõ×_ßöµ8ÐÑq[_¿êªGÖeY^O$ë§NjûUµžGþÐM¼läýŠïõõõõÛo¿½ësÈçóë±Xl=_W”õõDb}ýÈ‘úÇÅão„XlxÇg½ÄK·ÜªÃiqqq=•J­çóùõ|>¿¾¸¸¸žH$ÖeY^Çãë§NZ?uêÔz"‘XWžýØÙ?ÇŽ[ÏçónÃ÷/^¨¿7âÔ©Së‹‹‹ë±X̾ÖY^^ê9PïX“Ÿõ/®okS+ ÖuG£Qd2™¾-¿ý‡x'Î?ÿ|üÓ?鸎=žÔÈoH&“ö·rù?á駯Áâbeá¡Z’$æþ=°æþ8äŽaÅx¿†á‰PÝû©ªjÝÈT*U·PÀ•¬ýÌë±-©sO$ž˜êD£Áë1NãËs k¡P@©Tªz°¶¶ ?«”†Ï}î4>þñ[!I[Ü.n½{­•ÈŸß@eKšåå#åÎæ@*Je˜ð ™foó1it #Æ7J,$ãnšËåJ¥ºÚ˜‰Àxñrl§Ói;†ÛëuÃË1Nãí·O V Àüü<ŠÅ¢}ÛÒÒB¡P_ÆòOOOcÏžÞüæî’UðVä´.çûÓˆt|›¦‰ééi¼ùÍÑAÔI‚(ÖAÓ4ö®úÝ c|#ÄJÙ{öì©ÚŸZUU9r¤«d•Æc[Ôùº®#ŸÏwµ2;Q-/Æ8àÁÖP(„©©)ìÛ·áp«««`/t±étúì l2º­ÓeÙZ)tЋÔ8÷%ÿd|‹×±.º¯è*ÆEOì q8°ÿ :Æ{¥ë:öîÝ‹x<Ž#G:ŸB$x)¶³Ù¬=ü7‹±W•úÂK1Nääj‡®>8;;‹h4jQú5f>—Ë!ŸÏ£×E9”‘º1ìø/ù'\˲5dw×ñºnmaCþ0ìÓÝn5x"Á«±-¶(S…óSiC¼ãDx®‡Uƒƒ}{=±Ç˜$IH$z{ Y¶†4jÄM2i]Ì31ö¿~Ç7`µ¸'Îw/{wŠaÁƒQ&ËŒïq1ˆï–؆&‹!ŸÏ³W•ú­ØÖ4 ÓÓÓH$ˆ³åÈ õ7‘“gÖ~­†Õ‹ÔK£¤,ö‚~CŽÉŸÄ‹ªªBÓ¬Xêv„Ø0b£ÖhÐLÓD6›µ)óù<û쳸þúë»:ÖX$¬ÙlÖ@Uí=1TÀ9ï<¶n±­ëVï-`]”wów…‹ÑÐFhšfÏ]5ŒÞGLO®4¶¶Íá"–4†a —ËqA%ò± ðââ"“U¢.‰dM×uär¹º$Ñ™ø%‰®þvtº"·H4u]¯JVkI‘ü5ûž;ÏU×uûuMÓ´_§ÕsÅcu]¯{Ĺu›DÇb1;®MÚk÷.w* øêW¿Úñq€1IX5M³{Ÿ6r±,IõóÎ9­šVIXÅÐc‘ˆŠup²Yë¾X̺=›­$ÁL½Èf³UÃQ6²Ÿê ·¶‘$&«48étñxœÉ*ùŠXÙšÛÕµ'Sg&®ÜuSé0ëßw¸ßõÁF_¯—Æ´-[ºÛ^Ô÷ «hM¨´Jl¬'Ó뵋7u²˜“¢T/<sÕTÚ±Y¼ÐëmX^¶þï-àlÑ´JÃJ6[IB%©zȯx¬ø¾Åãl¡Á1 ÞöAä¹\’$q%¢6ĺ€ÕëתwF“ïÖ\.gooÖJ¼=îúÑÑCý$æNôk¨˜¨ßuÝú¾Fe@íÜoIª$¤"Is¼ÅcE²ËN/¤t:m¢!òÓ4‘L&qäÈ·O…È“r¹œ½Ÿ¢(X\\d’êc¾OXŦڀuñÍ„‘üÄ0Œª¡™¿êÔIƒ~,V=ô˜£È bá ö®’ŸLOOsˆ;Ql6k×ùªªBUUÖýcÂ÷ «ó‚^Ó¸/ùKíJo²Ì¡·4>Ä‚4Ëb,;‘är9˜¦ÉQDÓÓÓö÷‚ Ÿ®ÖB¡€p8\õ»¦i˜œœ¬ºÏ+œ+p™&VòÓ4¹%Ó4‰DxñB¾“L&íU߉Æ€“cìœNT,qã7bffƾMÓ4ÌÌÌ P( ŸÏcff+++n—§ŽÏ®ëÖü:^Û“Ÿˆ½­„½{»Ò/‘W$“I¨ªÊiÈWÄ6|œ‹Gdå‘H’$qèï˜ë¨‡5‘H  !íØ„tii ¡P XZZB&“A4u»L6MÓÎîudí/ÉKò›F .±³‰üNÓ4˜¦É òt:ÍÞU{†a NÃ0 ¤R)Ž$£ö=¬…B¥R sss…B€r¹Œb±ˆh4Š@ ˆF£(—Ë( n—Éfš&$I‚,GŽðBžüÇ9ä¨lKCägÙl–=«ä;ì]%²m"‘b±òù<“UÐAk±XD8¶SÀjݪ7šuÞﺮcuõ·Oƒh LÓä… Ã0êVÇ&òƒ\.ÇQ4¶Ä"zpäÈ®MUÚö°”ËåªÛŠÅ"B¡'“T§“'_ÄáÃ?êöi „®ëU k.gí3Lägì]%?õ9!i\MOOCQ,//3Y¥:mÖP(„b±ˆb±À¬iZÝŠÀb(ðÄÄ„Ûe²=þøã˜Ÿ÷vRMÔ+1äÝú·•¬:÷E%òÓ4‘Ëåì½µ‰ü"—Ëqµk[b]nåDÍ´ …‡133ƒh4ŠB¡€r¹lÇ*—Ë8|ø0æçç‡ Ý.“í‰'þ•ðä[º®Û8é´•¬òz‡üL$«l}'¿1 ƒ 14¶¸Ÿ6µÓÑ*Á©T ™Lù|@ j¦ƒbii áp©TÊíòT¹à‚)·Oh`D«®šf-,FägÙl–5äKÎH¢q’N§‹ÅÿÔRG «HR‰F£ˆF£žêY¬áßùÎínŸÑÀˆ…göì<ÖVDÔw¦içø‘ïp=W¦i"›Íâ[Ü©ŽVÀš£zøðaÀää¤=‡Õk‰ªðµ¯½²l¸ÔíS!]סiÖ0`.˜J~§ë:W&_Ò4½K4–¦§§Ç9̓Úê(aÍd2XZZ²_ZZÂÔÔfggÝ>ÿ¦òùuLN¾ÊíÓ EQ (æihšÆ^(ò%¦q”Ëå¸Ðu¬í*Á€• F£Qèº]×F±´´T·Ý—<ñÄe¸öÚ3nŸÑ@èºI’ ILXi<†Á‹zò%&¬4nLÓD:æ¾ÃÔ±¶=¬b»š©©)û¶ÙÙY¬¬¬ X,Ömoã§N]Œ[o îºní%¢(@'Ct½ó%\»yl#¦Yy qn†Ñ8³•åÊý¢l@뱦†aýÔr¾V£c5S{,çã%É*Oí1Û½ÿÊçbÎS2Éù«4xQO~eGÐX -1î©SÏauÎU ¼½·©¦çw€¶~Píï"9J¥êÆH¤úwI²~Òië÷X ¨ÝÌ>™¬OÐt½ò\Iòùúû“ÉÊï¦YŸur~µ¥>³Éf\®ñãeÙ:nmY{~µ]|†a=§Ù{á|¼iVéFÇ2ÍÊçä|ÅãkÿÝÍ{ñó?Q&†Gf³M`šÖx¯5­ãŠb}>ÎÏÍù¹Ö>W|n±X} MO[1$âQÓª?ÇFq—ËYßç1jÅøÎÖyFýñtÝ*S»oô}jôÜ»·rœÚÇ›¦u¬N¾ïÎã5z/zý¾oÛÖ¸QK¼>Kì†vAoV¼È²õ>ŠÏB|wb±ú†¯lÖz¬¸=—«Ä²óöÚãˆúM¼øâ‹?ðüàcbÀ˜¬Ò¸1 º®#_û·—¨…ŽÖQ¢(Àë_ÿÑ0a5 +¡qîw&zJk/âzùbõÒõ¥(½«—ç4ºèÔùõò^ˆÄeïÅÙ‘£ì²ËÞˆ†£i4ÍJ$±,ËÕÁµqÞë纸t;¤'CO$;Öýszñ^Ž5Ìïû©Sí33ÓýëzTϽ«¦i5Žd³Ö{‹YßtÚʘήL)Ú4Ôû?iûù0ïÚì× ·@=ý9@Uan¾æý' Ë2 ö‚gæ¿\íãÿýûOCzåi¨»_D|VñCöÿxëKHݵ €uXÃŒÏÎ{5°õf(ÊÍ0þy3–ß·höú0 I8òMëœD;ˆñà!¿öe'6C:çYHç=‡Ôu_‡²OEöÅýÈ}*ˆ”b“ÝNSžÖB_S‚tþ…Ð_ŠÂ¸õ—ÿ©"Ìþ´¿X‡øQæÖó ]øą̀ú IÐ_TaèÔ[­çȲõ<ãíÿ¸øbàäI¨?v ½ý?ï¾ægN÷o®jŸÒ4@zûë¡L|Ϻqû }k; ßl}Û¶Â9†GUž¹ô^·CsÃ8r j;"€Ö#·šSպ癿ó? ÿõñ†‡•Î]ƒòîJYq}¶í ¹´Týê·æ.„ñÂv$®ºH¥ C±ÛGeÐ6Ep…¤ n¿¡ƒ!zWÉ{ 0þþ¨“e@Qª“šŒûOÀ8±¹ás•7¬AºîÇaBªê0ïºúÃ[až|æS/C~Ëx≓xå’vun¾LXu]ÃÎ5¾S–­ D¶hÒÓu‰D¢ñhhE±.ĹêùDGõ5S)Òi@ú£?Bìßo‡tê”u6 ýS"¹ö1Ä7ˆØÙ§‰‹Ìì·>㯭çǦ€Ø;KÀi»#<öc@•Ž~ëy7Cù] ®::Èe@RõëÿÔÄb€’Úm¿†=[C¶z(Ô´{TÚAœ#›Äƒµða\µÎK¨´ÓÎþÔ®æ¯@V€Ô‡늳?µ¬©mþ©\Û_|ö–úç«·n·\ÀÙ¬:7µæ_µ¹†õû…®ÆÖB‡?‹Q组µ6 l4(‡nÊU³ªŒkÿŒ¬^{óÂ|y+äÍ'¬Ç?ü0ÔÿFñ²Y+~âqÙ,"ÿqã…·çlÞ åŠR×ý- ªˆD¬S:vÌ:ŸäGσ~2à*àÜŸ£S·= E¾ÔnôÌÝ? íè…ÀùçWTÇ·,ÊÙ/†¦UÚ‡‹A7bö «:©Ûz¶zàòy|åþsû³Ó4¡iÚØÍ]Õa m}Ê{/dÙncQUÙ,²+—Âxö’†¯kò'>bÇf*(Б½õûÞ»ªkžÙ ã…íHíZBüwƒÐå’IÇ@¯d‘?ßÛô|Õ?´þžjZe0œd0¾ø8´ï\Ýð9ò[ ~|LHö`/YÌ¿+@ûFeú¨ñèž[{^÷Óݽ‡'¬3 Zë3™ ýu«§^«ždL§­vñ5UÓT@2«Gê#Ç¢Úì;ôz×YÇtb‘e¤þ¹Õ—nR¼tÕàùÆ7#ucû·¬¶^èdÜÚ_U••ðKþÛFŒ;år9oö®ŠFG¯¢ªÐ4dÿ¨l%‘g§-ˆrH]þÇPìGRS¡i•¸ÑÃ3H>z[Ýa”7¬A¾è(W—ëVEòÊ+×§fÒÂöc+³MÄRмù°u\Ô|R)ä[þ Û  &~eÕ:vÓçXß7ÕßùAí¡¬­RC7Ú&¬U . ¡ÐÆ4*•J˜™™^ÓúV*•H$P,ªª"-æŠv@UU+aMàD.T|@*•B2 Äå•Îþ" À cÜÉ0ŒÊ>}ÓÓVÝ~ê”=¶Ô|ÓµØûümÈêòk§sÖN­f’Hí 3¶‡2‡U\…̇N@ûÊ9пùjફ~ò¿»YÄ‘N[Râq@ßòSH>ñ‹P"Ûª^ÊÞNílàò²#‰TUä[^‡Z_ĺ$íÖíh·Ër£F ~—{7¬wJ§ÓCŸ»jbI&1}è§ìd/¿ ã…í6Ÿ´ùÕÈÿÞ?Û «xŽ,ËPoÃ`·Û·Û·W†}ã3€TM\*…tRʪ޳[¶3®1ß6a ƒ}ßoµT*¡X,Vííê4??`0ˆC‡¡\.cß¾}Èd2]‡,ËV+¼[rÈ׆ߪª¯¼²ñ¥‰z0ŒœC&·m~©·ÿâ_³ºD³9 ñx)ÇÅo£*_mw%LtÖ0c[¬ö>(b(ªdÖ°Á>ãônkÈê{¶@ùèùÖúÊÍ€d ÷v&’ʾòûÚ‡ƒzFË0cÜIÓ4(ŠÒߘ7 Ÿ= ã_Ÿ³ŽQØ ù¹E|þG¡+ñêa°±bïx#ÔŸ»°É‹½@mcŠ Y–1¦9¢§t=‡ÕêÆ=lÿ>99ÙõÖ6…BZ“žÏR©„B¡€C‡°V$ŽF£XYYéþË’ËYMDC4ŒøÖ4@Ùú0ð^6ÈÐð ­GuÂz졉íƒqö"$—ë~M-¢VÜŠí 1 ˜>ƒÜ_¼„ø5‡T Éœb_)ŠŒØýFœ‰%a¸1î”Ëåú3üÝ4aþü¯ ýí‡ï¶üÔë~ö_军¥Á0XEÊöý‘Õqªi8€R©TuûÒÒ‚Á ÒétÇÄ£Ñ(¢Ñ( …BÝÜØÕÕUÕCŽC¡PÝqÛ“þǵïœ\3ŒøÖu@>ýu^­“+†R‡Ÿ¥ëº=çIzÝÅÈç­é«ÓÓö"¿D}3ÌØÞ³Û'释ÈmýäžþMÄny5Ì[½¦)…KPcnŸ®ëÝ/¶dÖ6^¦d-¤'©”ów@þö,«¼Ìçtò B¡€D"‰‰ ¤Óièºnÿ¤ÓiLLL`ß¾}(ôa«V_Šr¹Üô¾ï~÷»øò—¿\ùò‰å݈j¬¬¬àÀuó6†¡×ø€'žx333XYYñ`Ê™ûYSSC3338zô¨+Çî[~Öôç>UU±çìb ’d-’tìÃ\e28p?üðPÛ¯ú[Ð4­27» úÄMˆüæ›±sé£HïÉAþÍ›päáRr>Sõ·˜C:Lý®¿]×» œÍBÿ±[‘‹TöŸVÕJ#Œ|ÝŽ–;Q’w‰kðnëïŽzXççç›NºVUªª"‘H`~~÷Üsφ Òê ±¶¶†@ Ðð¾×¾öµø™Ÿù™Ê¦&¢Ñ(‚Á`ÕÐöaé5¾`ÇŽö*Üÿ厓XœýÑ¡Ÿ?†………¦ƒÖ·:L/¼ð‚½ç©/ÌÇ×ìì,&''‡^‡÷«þvêiHðÂßäźO‰ú»‹›v«¯õ·CG ëÙ}³³ŸzÒ/ÿ”wÞ‚øo^(g·gf¼ûB¯×àm{X …J¥î¸ãŽ–›šš²'roD«/hÇKks80yT_â@üÜÿÅäIýŠq€®cõòË¡ª­¶ž!޾Æ6¬E—Ú2 ˜¦5~zÚºI¹‘É* F¿c\ÐuÝZ,²™l¹Ðǰsñ#Ðßÿ1äõmXþâ\0lmÖb±ˆ`0Ø6PE·ÓÎÄÄ€êa ¥R©»/ŠirnyR_â@ü““l!OêWŒÀ÷\ÖLÔH?c°¶´iw½{´Û/˜¨?úãBË„5™ÄôŸ„Ýõߑ׷aqé5¼¼¡:mÖ@ €µµµ¡P0D8®›ç‰D:EaÂJžÔ—ø¸OyVßbÀ ÿøøîö ™t»TDým M«®#™X‡þÿ}’ÄKŽ~Ç8ÐÁH‚T ©û ù¯žÇD•šj;‡5 ¡\.·ma .µšÃÑ©ÙÙYÌÌÌ P( \.#`ÿþýn¿WD}Áø&¿ëWŒŸ>}_9ýKøy^ÄGô³þnz!¯ëÈþ›èoH õî_Su£ß×(ÍzWs9k‹¾ÅE®I@íu”°†B!$ ,,,4LHËå22™ ÂápW“ÄÃápÕZC¡î¾ûn{>l·û¼yã›ünÐ1þø7__ºÉéÚ4dè¿.B“Í"÷±o"û#iäÿn‹Ûoùذ®Q4M«ŽuÃdš$n¿ 4*:Z%xnn333Ø·o¦¦¦‡ í †—––°¶¶†¹¹¹¾X à…<ùã›ün£1nšÀ~êð›ð($i·ÛÅ!²õ£þÖu½nKóÿ‹ôWAÛþ'Xþü«ØëD®éç5Š®ëˆ‹1íºnÍËÎ籸ȡ3Ô¹ŽÖP(„……d2ÌÏÏ×݇1;;ëÊÜDDä?é4ðÖW ¿ök·¸}*D}gšfU¯“ñ_>‹È§ÿ=b·_Š#)·Ïލ ðbÝ4¡ßô{˜|GdŽ ît”°•¤Ul]S,íáÂ]=ŒˆˆHÈ嬆xs×$éCnŸQßbû½³äÛß‹üÏžùmnŸQÿèºnï5¬ÿäØûâg°ü&«Ô½ŽVAlqS;º\.£X,r˜#mˆªZ?X˜’ÈÓ Ã°/ä’™C€Égt]·zW5 Ó'ËùœaOÔ©¶ÛÚtªX,bffÆíòш³æî™usüˆüDÄ·i‚[7‘/‰½†õ?; ù-0Y¥žõ-a%""êçP2"¿±{ž` 'ò#]×ñöK.Aî+—@½år·O‡FX×C‚‰ˆˆMÊå°mÓ&·Oƒh`dY ±Ëžb×¹}:D}gš&.ºóNh|ynOFÀV""òœWÆ;.»ÌíÓ {ÿË\Ò·à6ä_ªŠå¿Þ̧ aÂJDDž³íôi¼ô®w¹}Da¯œzðÿ!ûʯº}:D}gšg×!PUÈo»ÈíÓ¡×vHp±XD&“iûBårÙí²‘O\ð½ïUíSIä¦iZÿ0 äLÊÕ—º}JD}'æi'“@Š{ Óõ­‡5pK""ê‹Ó›61a%_²›žFnÓ^ÔìHä ¦ibóæ+¡inŸ ùAÛÖP(„……·Ï“ˆˆÆ…iâÔúºÛgA40o9zÉÕA¹–sûÈŸºÿ~¼ã²Ëpë¢ÛgB~懵P(Ôm-P.—Q(Ü>w""ò#]ÇêåÜüIûüWpç—oƒyÍ»±È‹yò©ë ¼õ©§¸÷*õEOC‚<ˆ™™·Ïˆˆ|è›_û.¾øb·Oƒh Z™Ä]]Æâ_Ø»J¾U>ú2Oþ·Oƒ|‚«‘§l}øa<ÏVò©wïü¯Pÿ·l"+<ÿ>üèïpû4È'ÚÎa%""¦O\u\"ßúÒà7¹Òù™¦áÏ_ùU»}"äLX‰ˆÈS‰„Û§@DD=Ò>ù8^{ñiHÒUnŸ ùV""ò‰ûÈÇòù¼Û§@4Pñw[qù5ßsû4ÈG:NX‹,•ËåºÛnCDDDD4~ÌÇNã«ß'n~ÇŸº}*ä#mÖ‰‰ LMMÕ݇Ý>w"""""ò-SÄ;äQŽ”¡¾j›°ƒAÌÎκ}žDDDDDäa±îÂcß?ˆÝÊ/º}*ä#ÜÖ†ˆˆˆˆˆ6N’?vŒ=¬ÔWÏa-‹XZZÂÔÔB¡Eiø8]×Ý.¹¤Yž@Ô‹ŽVMÓH$ ìÛggg iŠÅ"î¾ûn·ËCDDDDD.1 ÃíS ŸéhHðüü|+++öãú¥P(@UUd2Àää$¿8äŒoò;Æ8ùã›üŒñM^ÓѶ6¡P‡B8F&“ÁÌÌŒý³´´UUqèС¾õ® bü|¹\ÆÌÌŒ7òôÓOC×uûËEÔL¡PÀ]wÝ…‡~ØÕóè&¾àÉ'ŸD&“±‡ß5“ÉdðÄO¸}¬Ãi VVVp×]wáøñ㮞G7ñÍú›:%êo·wÝ`ýMƒ ®Á»­¿;êa¬U€çææ0;;‹b±hßÞl˜ðF”J%LMMaÿþýökƒAd2D£Ñ†ÏÙ²e ¶oߎÉÉɾž ùÏÄÄvíÚ…Ç{Ì•ã÷ßpÁ`rr®œ7ŽÉÉI<ðÀ®Ÿu8 R(ÂÚÚškô½Ä7ëoꔨ¿·nÝêÊñYÓ ‰kðnëïŽzX€=®½vk›~ ƒ˜­zíh4j/þÔÈ–-[på•Wrȵ ±k×.\rÉ%®¿Ûø¬ žp8\·ÅQ­p8Œ‹.ºÈµã³§A …Bصk—kô½Ä7ëoꔨ¿ÝZÄ‹õ7 ’¸ï¶þî:a†B$êZ• IDAT¡P7ô@l­ÃUøhÔ1¾ÉïãägŒoò3Æ7y‘'Ö@ €ùùùª¡ÇKKKöŠÅD£ŒñM~Ç'?c|“Ÿ1¾É‹:žÃ:L¡PSSSØ·oÂá0VWWétÚíS#Ú0Æ7ùcœüŒñM~Æø&/òd ³³³ˆF£ö…ãâÉOßäwŒqò3Æ7ù㛼Ƴ +`MÌåäWŒoò;Æ8ùã›üŒñM^âÉ9¬DDDDDDDLX‰ˆˆˆˆˆÈ“˜°‘'1a%""""""ObÂJDDDDDDžÄ„•ˆˆˆˆˆˆ<‰ +yV""""""ò$&¬DDDDDDäILX‰ˆˆˆˆˆÈ“˜°‘'1a%""""""ObÂJDDDDDDžÄ„•ˆˆˆˆˆˆ<‰ +yV""""""ò$&¬DDDDDDäILX‰ˆˆˆˆˆÈ“˜°‘'1a%""""""ObÂJDDDDDDžÄ„•ˆˆˆˆˆˆ<‰ +yV""""""ò$&¬DDDDDDäIžOX‹Å"J¥’Û§A4Œoò;Æ8ùã›üŒñM^q®Û'ÐL©TB"‘@±X¨ªŠt:íöiõã›üŽ1N~Æø&?c|“×x¶‡u~~Á`º®ãÞ{ïE±XD&“qû´ˆú‚ñM~Ç'?c|“Ÿ1¾Ék<™°–J% LMM¢Ñ(òù¼Û§F´aŒoò;Æ8ùã›üŒñM^äÉ„uuu …ìÛB¡ÇÑ;‹E¬¬¬¸},oß·Ö\?•—1ÞžŸê´q+/ã»=?ÕgãV^Æw{~ªÏF¥¼žœÃÚêKQ.—ênôÑGñÅ/~º®CQ·‹0pÇlj'Ʀégy?ŽGy›6mÂìììÐËÒK|À±cÇ055…íÛ·ãÊ+¯úyÛ—¿üe·OadË«ë:{ì1×ÊÂ:¼=Öá½{øá‡qâÄ lÛ¶Í•²ô߬¿ýmõ·[u!ëïöXoìµyä‘®ëoO&¬år¹é}kkk ¿,¡P×^{-vìØ]»v¹]„{úé§ñôÓOEYû]Þ§Ÿ~Û·oǦM›\)K/ñ ï|ç;qÕUWáÒK/Å¥—^êʹÓK/½„ÉÉI·Oc$Ëð#?ò#®•…ux{¬Ã{wÅWàĉ¸ä’K\)K/ñÍúÛßQ_qÅ®”…õw{¬¿7öZÛ·oïºþödÂê†P+ 6¼}÷îÝØ½{·Û§NÔV/ñ ÿøÇÝ>õ¡ ‡ÃnŸÂÈ–×í÷Žu8 Ò(Æ7ëocýÍú›Ë“sX'&&TK(•J-/æ‰Fã›üŽ1N~Æø&?c|“y2a ƒ‡ÃU|5MC$qûÔˆ6ŒñM~Ç'?c|“Ÿ1¾É‹6­¯¯¯»}‹EÌÌÌ  Ú“¼šÎï#%Œoò;Æ8ùã›üŒñM^ãÙ„°&~‹Eîé'ê7Æ7ùcœüŒñM~Æø&/ñtÂJDDDDDDãË“sXÇM¡Phz_±X´[¸šÝßj_¤v÷[»ò8ç‡ò’¥YŒû-¾;)“xŒ_ÊK¬Ã›=Îå¥Þã{?ëÄ÷(–—X7{œçÊ»N®Z]]]ß½{wÝí=ôÐú 7ܰ¾{÷îõÝ»w¯ßpà ë=ôPÕón¹åûþ|ä#u¯ÛêþakW§¬ß~ûí]•Çk奊F1î·øî¤LãÛ_X‡×cŒûG/ñ=ŠŸõFâ{ËKÖßõ¼Z³‡Õ%¥R š¦!‘H4¼ffápº®ãÞ{ïE8®zìüü<‚Á }±XD&“éøþakW¡P(`ii©îöQ+/µŽq¿Åw'eß~Â:œu¸Ÿm$¾Gñ³ÞH|byÇëïÑ«¿™°º¤P(T-^{_¹\Æìì, `jj ¥RÉîn/ ˜šš²ïF£ÈçóÐö~7ÊÚªïq+/ßg>någãöY[yiü>s·ËË„•ˆˆˆˆˆˆ<‰‹.‘'1a%""""""ObÂJDDDDDDžÄ„•ˆˆˆˆˆˆ<‰ +yV""""""ò$&¬ÔWbÓ`"¿bŒ“Ÿ1¾ÉÏßäg~Žo&¬ÔW333öÆÁD~Ä'?c|“Ÿ1¾ÉÏüßLX‰ˆˆˆˆˆÈ“˜°‘èª/•JXYY¦iö}ÅbKKKkÇ.—ËÐ4 š¦ eØ@©TòõªæVŒ»ßc|œ°'?cýM~Æú{´ëö Œ“™™D£Qhš†P(„B¡€p8Œ`0ˆB¡€@ €L&ƒ©©)ÌÎÎöýس³³8xð B¡ý¥ """"""¢Z\%˜ˆˆˆˆˆˆ<‰ +yV""""""ò$&¬DDDDDDäILX‰ˆˆˆˆˆÈ“˜°‘'1a%""""""OúÿHøŸaº}àò%tEXtdate:create2019-03-28T17:36:52-05:00ši$%tEXtdate:modify2019-03-28T17:36:52-05:00ëNј-tEXticc:copyrightCopyright Artifex Software 2011ºÅ´1tEXticc:descriptionArtifex Software sRGB ICC Profile †2tEXticc:manufacturerArtifex Software sRGB ICC Profile\~=Ÿ+tEXticc:modelArtifex Software sRGB ICC Profile1(‚¡!tEXtpdf:HiResBoundingBox1080x792+0+0_Ýx+tEXtpdf:VersionPDF-1.4 G:xIEND®B`‚blis-0.9.0/docs/graphs/large/l3_perf_zen2_jc4ic4jr4_nt64.pdf000066400000000000000000000652351422157504600234160ustar00rootroot00000000000000%PDF-1.7 %Çì¢ %%Invocation: path/gs -dQUIET -dNOPAUSE -dBATCH -dSAFER -dAutoRotatePages=/None -sDEVICE=pdfwrite -dLanguageLevel=2 -dEmbedAllFonts=true -dOptimize=true -dDEVICEWIDTHPOINTS=1396 -dDEVICEHEIGHTPOINTS=1123 -dNORANGEPAGESIZE -dFIXEDMEDIA -sOutputFile=? ? 5 0 obj <> stream xœÍM%9vž÷ý+rÙm`RÁorá…È‚m¶”³h5ÒȆԲ52`Ø¿Þç=äyoweÖ”‚=šI/o܈x‚äááÿòr½¦— ÿÏÿû÷?ÿ^ðÿþø?\/¿IízIeuù¿©•ëåÿÃ~±|¤ôºzz™}•×–^~þ!÷º^©äŸvtµÕåï?<Ô9ŸŠ:Ÿi/ÿû9âºÖ•_ÿÇßüå©´ñ:+µºKFʯ Çò¶Ë¬åŸùïÑ_»ÖÉ×U^Gáã‹j)Ê¢%ú{·„ã›+÷—Çÿ!gû_~Hz!^ü¿~ÿóËŸÿö‡?û›ñ’¯—ßþá»>r’4ŒßQÖk)ùå·?ÿð»óOýÇkÿç7éÊåµ¶ë­¸õ¿ýíüá/~ûÃ_?¹T£¤×’ ]ª·§—¦\¯¹ÝjE[KnŠ×Y¨­(á¶N­h‹kí¶ú5_Sã¶¼äÖÖ®µÛ¢Zç¶¹z{å¶¢„Û:µ¢-®E·`ίóÖ–•ÜÛŠZ§­Së£ZÎJ¾f–s^§œk½Ðq“ÒKmr‡É ðwû°»nÿRÿ¥Nû§þøOW²šïï˜ß½¤Žãú[ùÏß}õ·wà>‚ýöì>|ûó»ð};¿rN3Î)ÎçopbKñ“ºúk>õ¤þåOí5Ëi©?þûŸòõz­«ÿøW?¥ëµÕ¾~ü/û_ÿëOr5{õÇ7a¬¾Î4Ò¶ÿù÷ÿcæ?Å?ÿ½”%añœI;ÂÏ_ÆkRk¤×kÚ!ÿë?Èú{ùÏÏ?•¢ÿ§Ð¥²‹4ñ”Ô6ä8ävBÆò`šJÃ\¯µ£¤õW\°™çkNëeN¹WûBIï¯ Oº%›Z¥d]r—ä!%S/”Ô*grÆIÐÓ’)'ôË›ñ!yÉE/+çnJW—éR"%+YòKJæx­xȃnâóR2_[×|O©òlJ)'9˜f%z¼)·*ĮРË-ƒÇB‘Cšú5òÈ|•›|µëz-Z§ 9”Ž’þZ´Ýz-Üh«IûzüµÊ‘ÈW·1äîÐ9Jéi¤$¡Ã’–å`¤NG¢]Ž.¹YF)ér곜†qÉá5-©r4¨3ók³:SŽuJÅE—’‘ähä4Œ¼^—~ùhr8rªÆÐß’%‡ƒ:ò鬿s–&‡±¦à4ôlÎ!‡#§bâ8Q°¤#‘¯žrõµÂjr,r¦ü4=1Ò—â¤I¾5_òýrÖ¬ OyJÁ…cÈr¾^r–Pô4æ4åPCÎ8¾!g馊ÃjvLrdÜâKŽÒ Ê¥}ÃZ}XEîư~mrþ-5éE’Ç7Ôi~j?²ºªj¬WœõÜä‹>òåGXÉȯÚ+à®FA¶§~H~¿Ûé9ägØsèw/õ:ÿß0LÊí)W‹”oÓÛh38ää¯|c÷AfñKœrç¿æN ^—žrb0áòfð’Û¨Wfð’_–ÁkÈ/ÌÁKî™ëŽ  sB0MôZÌ`®ÃoÅ`0á!œ™Áœñ0e‹|ª†°Èeíƒ!Ìòi{ˆ„e¶W½+7…Uî^{…eÚÅßù‘^Å!,ròbu4×ÂÚ–\U†°Ê—÷BVÐ{a¯ 7þ¡°Êg×` ÛìþåN±v7Š=W;ë›Å&uõé¹qlrrôZm[ZÖCo Ûʯe1‘½9^AdOÝîÇdšô‡o&ÛX8×%žkW'*e€V_Sf*»Œ¢K>X®&ws©„¥<ú¦=0ŒJ}ÆöNTÊ™˜þ™36ô îTJ'›õÿòÿ>„¦;¡¸­çÐ*÷j¿*™ö‰›P|JŸ•›Ð!³ßò“V;„N|ƒ¡å„ʇ*®å!tNùò±ˆPy`¿¥Qy\t®íòŠAžuríNŸ”$£â™©z’¬À»Í¢ƒ¼p¡ã‡bDyɦ¦~RÇ»ÑA^`?ßøÃ…žÜA^ÂGª7þ¤ëuF¿µbüâö/·RU6'ß âV\ÜCÊTÛÏy0xÕ#ƒÒÙo•õ³Â⃵è 1´ÉŒà%S…+qÿx hoQgMî1óšƒÄ“È@‰ÃÂÂ^rb¯wNïû‚@D´78JÝ~#LMNàUm¾¶ÄèlrÿxÉ1­Êýã%×ɺæ7wµþqGüJ‘G.ž9{ªÝ²Üò9Ó´>êP4î]ó©¨óø™˜£~9’W1$¯Zß%‹²5Ðß;þ&½xÔR”pK^¶[:ãHn‚ßñÅH^úåHÞã%+eêÔ#1Ï.‘<€ñh¦ZÑÖ‰ÑE[£‹¶N­h‹kí¶vŒn·E1ºÝÖ®µÛ¢Zçö‰]´Å1ºsÓE­h‹kÑ­è1ºÓÖ‰ÑÑ ìµN[ŸäéR_ße$ï#È¿½øð·§÷áúçwáûv>«ðÄ4|äû×ÿóÑÀX©ˆe Œ%=ð*@^:zo5’IèÀ-Cæj½xiÒ5t€Ï-‘Ú¥X§Ý´@×x¤'DÐ{”^t줜èdªtéYÚ¢‰oòÄ.›6÷,Cgã›VEºõ‰µLµÆD\ sååÇ;å~/(‘cÒÁ®Ìd+~̃õ¹ˆéaZÅ|ºj‰ÌÙ{¶H˜Î¹+†Dù­U¹PèÃd’Ölt+ãã²™À¨Iº÷Ž¢ôKmi‰ôóH¢èÀ©Joûªa} Zš–H·>ÕZ4š'Sö„#“Yä´³^ :YÔ‘q³Nvj‘Þ1aŠ(cN¬Ô*O~T‘Ö¨U§ìRàýqŽ"vÙéª —¡/wjŸX[×aY\ÝÚeNÐQE»‰Úë…ÐÅ’A§^‚ÚåñÛ’K¬_;¤CÇÓnÉ¢M"ÌÚ5>fÝHr£TĶp¥Q0‹žÁµº7eø–qsÉåYˆ$,D²´Iº °ÕmÜS•Mû’§'Ž»a '#Œ…‚ÈpY¥r\øÖ†YIµØ—±–0¸Ñ¸VÕf[’iüÒ税þä ˜0õG¥wBÉߵطœg1¼/_Œ ¥¿“AS(§Xï¢CáåäC¡œlLo eZ§?/(œKjØxSˆ3 7Ú¦kk8(¼d «cò ð’ûÌÐ 1´ÔY]`ˆèغc(O€Ê¦¹¹t ³|¨&¦0_Éé 3–„n, 4¦Ñ1}l óðaò¦PŽËi #»²úëê !Bjý¡^²Á6Ð B¡Àæ·›Â*“O…U®††Â6…ˆ=­…M†gý†!¾)g&±–áxŠ]n%ónñ©~ƒæÞ˜Féèm0½qDtltæ±ËÓº5²-Æo&…«×> JùöËø &;¦^‡I™Hû Á¤ÆÆ:1i]fR—óu”«Éxõb,õDhpl·š\Ôõ±àØžSG© F¯Æˆ×¡èKÇ­Ÿ2ñ“òÐÒ§z *O×ôÊ„Z|¡ ÓÙš*Ï‹îý™:g²ð¡:§œDísÐ9qi&*_?É ºj‘™ÐKnƒÉýäœÅ£nA¨ü‚}©:1ÃÕ‡Lª‘¢Ä„ÊLÂß(‚@Œ'² ìF<ñ\Ò8Fà9Ñ5åIxÊ÷tûާFÇnxÊSrxWkxj4DãH§Žo¬•ÀçA£ÏË—k‚Ný¦Ipʸ©ÚÌ7à”vA´åÀ9Ñ­-î*5HqcóJÝÞlb’½nlb"Þ;±i±£JlN¬@é}pÊåöeF§S”$ßtbŽ©×-èDIŸˆ›N]I¹á©S~ÆS¾»ú7Åø«]—§¨ÄÜ\NmÂO¦¥ò%c§Éõ¨sæÙïëœOEÇÏ||nÞˆ¿:µ¾KhFe1y ¿÷ŒZæ+²à„/¡–¢,Z¢¿¿ñܼË@fàwü)sóÇKÖ%j÷,›g—(/<4¸V´ufÝÑÖ-ÆÛ¢\o‹kí¶ö¬{·Åù3ÑÖÉʼn¶¨Ö¹}bÖmÝògöM·sq¼-®E·¢ÏºO[gÖM7päâì¶¾"ËFžüšöôýMÍ?BüÛ;~ù~{zÞ™~¾oçÓSóŽü¬Ü§ævÆÿøÓ¯OÌ;žKYYèéqØ2ìLÈ3Z» 銎tÐÓ“<­-‰¥ÙªDÏÒ¥ãA2婺¬ÄF¤òÅ–žåymtm¤ÈÃ:[¤U‡é]Æ(:dKÒ–cºŒôyžt8Ö1üÄX+¡¿ÔC«C?¼Ðèzu—nB;…¬³¦ŽÚÀ@?yø¶c¤Yu ïÑùÞeú„[–ñ¸ý{ÇäpÚŠ»öj}`ØT, F'×}`Ñuz±ÉŽAÖ)°¢m‡‡PÆZ6¨VÒµ^UÆXúÀíº„¥kÜÓÏ“ü£.b-Ú¾kÍ KÞ¾J4/õŽ=üòl¶lD«­Ä~Œô{¾n?’ /¯££ Šeåè€pä¤ 2ºè¬O±‘eh˜‡­>iŸ;²ü¶ËŸWzÂÏ©ëøOq-[@sÍW¡G•1;ä,ÚÔeTa‹}ø"óÑ–_e82lÅ{à9£99réô²È%YNNñ Âè2\¾tñÚ×6F—¡ R{ÐßW-¯ÀbÇ/×ùÄXåH¨3ñ(‘‘ V;Æô…ã1–&3-½¦úåv"Ö:åpª•Èx¹ >{ %T‘#·/Çû”;WÇs_˜¢oåúá40,÷óÚ<Ê%´µ£Í#Jth¹yDbŒ JœG èeq$¥ Úše )=û°“HÚŠi%*'~«ï6•X!Ò±[P91ª¯Ì%æþÐÚ\^Ícr›Ké¾Ê„ƒœ %‚e1”iù=¾¡DŒÎG6”y]@)ƒŸ¾€ik' Ì#¾]¡D( 1“^¦ÁL"»fÞ˜,X—oÌd‘ïÑ,Í$#5°±,ËËK¬-_±,òíö]%Òô4f·¹¬QݸD}m.«œk{²—ˆ2ðÁe•§Ý¸Äóh2–Hîë•°l5p ,[<ö6–M¾1ݰDJà`*;&ƒ©l˜.N¦²ãÊ4ÆRúXk†]y¾|j†N=fÃ…&B»¥7 r‹èù8|^ÅrLŸàüÖ_âqgýÉá3ÙE=|zÞÁæsÈÃ×îÊàsà„/æs´ÄŸZÒO<#k'>ç@W›ˆÏ‰ôG½¦Á§ÔA¬!*³oï˜Qý”^@TCv8ލfé,Ft"œ¬!ƒ@tN,üBtbÚj½¶#ª!I)¢ÉÔøN0:‚n„蜩GCtbî;3!j »ƒ3x¨~J#™¨ÔÉö( DõË5Òˆj‰æ¢ò©å8¢R§Û˜"3ÒžQù”gÎßµ–;1*#¶yë:åCñåÎèœÈãÈĨ|(ûOwF-ºÃ]çˆF¶C*u¦õ‚©3Cª'UG{{´ŒXŽBCõÙ»åFœ­'2„ž¯•†íQçLºß×9ŸŠ:ŸùøD]Ó:¯Îíš^GYL%èï=½^Ⱦh¼¿K¸%/Û-¿¿ñD}a°‡ßñ¥‰zY¿e²·¼0Ï7Ó¬;M “ž^{Lù_‘œ¹la\ž(––òe—Nþ—'g¢“Ð|BLó5S!päËs3“gº®\-1 yïÅJ¦e†á¿uN  ƒÈ ÓX.Ís3}ó‚ ›-1¬ììÆZ,1¬`ÉPUšVVµÁ… n-3¬F¨Œe53¬V_8ÐLq]þÇv MQîÙ2Ãj¤f®Ž¬9Ô‘ÑžŽòä„j¯½š­K ¤ê"ˆLÝ/OuÆÈHÓš/,½ŒÃvËhÜf¡“ÆÂcC‚¸žœ…ÑuÙG i—]SŠM[ÖBÚœNÄ}v‰eì¡:,8XŽæ……©¹ïk‘K®gÃYˈ¾’îHÑ,K‚”Vôô`ôšíS9]Ú ¦|žž-ãùC}xÆèÔçîÀ> ûTÉØ?"c»ßUº–ž,ÿóªˆ!¡ÄÓð¥¤KHðR"çí`µY³ 剩Ç3#ÃY~¦Îä´ëP@K{¿4'05käæ°è€)7Ë(70—gßn0‡ \7—ÉSÿ‰Ëi7yp9±‰Ç6‘m.åÞ.‰¹Dž¢Ž×—Ò©é$ñp)÷—N6—×Ô6˜H ¿q‰äN»ñƒË$7‘Ñ\b8mЗiyïln0±Š§ó² ?&–ë&q‰_Ûn\^2ËYŒå…p2–Hó4PË«ÅÉ ,3¢#™±ÌÅ 6–Y®²>e7–¹5[›ÝXæáº 2˼Q•7•%åØïçTæ¹S©Ê¼<¥jc™q×Ʋ¤ËwÔ– ª,Æò¼"1–éò©ùƲØÞ¢`²ôéYÜŽd‰@ÂF9²#YV üÉš#÷;L-Ù“o3™ä«æ Ê4}iÿÓy"´½ï:å¹®?öš}?c*¶w„"@t OÜ߈âIæ%Ž(&µ·®Ó:éBˆÎ¾ D¥tGTÚéþèwDå°ZGtêVÄLŒNÜ}Æ–3ª{Þôg£2O6Æ FucËlĨÌÜ.?gtbåߎÇ•ç—op FåË=ðåêPc1¤ Oe¥š±`{€œRlQñ§ŠS*%ö„H'’*C:‘5V¸ï” Ò¼tHåL\u HuÍZcA©~ÕèD©œÀw½Q:W¬?¥ò³ZtMFéDÒÚ$H§ôåvºR]¿õ»8û"H5«Â;nƒTV"Nuø¶Tùò T½;m3€ƒªÑÛqƒ>Ô¨ÖÝ0¨r<3ŽÐGÕ«ú0†fô)á‘t—Iä:ip5h>«Ÿˆ¬ÿñ¹|JK·ìRÛQÂj /Û“ó÷ž§Ü‘ÊÃ-E ·äe»¥ó÷7W[àþ-Xtÿ•¹ü“‹%ç^¯6Ïå/"^÷:ÞÍѽ¥ÛL^[¢:ÞÒ­N´tfèÑÏã­¥S'Zâ:ûÆÙósoé6‹÷›m×ñ–nuÎ-³óÝÍáã¶:»¥ÏÏàSJÖûgð_Füí´ï‘~{~çÝ0zßÝÚø¼ÑzÍÅýÒÌý_?8c—ƒ®ÔÒµýSóۧ¡Õ”jÖ¤(äÜÙƒ8aIX£à>ÇKæ*g¶‡¾ŒÁ³>ˆÑ­›ã‹#šæË¦IfÔz‘êeUz[ú<Çs¯²4»7³Í©F;X ‹1=¶áiziм¸”fÒ$-tW62LˆSë~ØPVJGÆÈÕœ G†t|é͇µŒôìl ðÓöø]–íŠ.Íö¬ed¨«ÂÒ ¥YÌ–°ëÛSÖÃ)‘z(%W—é;SFð@fëôFr½ToQ<ÃQJ†K±å<$ö`̶ö"H0,ƒ¶z] Z 38= ¹Ë-Å|ݾjÝë~ÙlI¤Ém›|—ÓCѸ¼JÓýô¶µÝ¾»ÛÂú@÷4×”ǥǂÕb/ÀÞoÌÕ‹o…Ì33Ûh#OÍ$”’b«JRÒõP0¶3;‘0‚‚Ç¿Šº0b÷b–I¼Ú1dœc»¨å9¡G‚¿•‚½êǰÜ)Xþ§ý{*z a5+z¸…L,’/=ÍC´<ß±šP^¾8?¿a(㡆ÇpCl%[7 1‚n7 Df µdÝ0”Kc£¨ƒa‹–ƒÃZ}êµ9ÄŠÉCù‡›Ñôysè³Í!JlãêæðŠäæðŠMŸÁ!¦Vs˜äŒùî[ç„·ˆhÇ·ß:ˆˆÜÙ1ˆ9ÍM™ˆVÌE$â›Ìã$"™§¥Cbƃm1ŠºÕ§2Š˜íŒŠ˜Ù3Šrø;£¨ù ÅÜG|ÆQD>€ßðŠ"žŽ…I¼Po1‰H0‹@ ˆ5 3SŠr›»Æ#PĸݿØQ,¥Ä;‹xúOTK‹Y°XF Õ€³X†¯Onsù£*<*ÓˆíM93Žê;¹ñ˜šï`w 1[ùìÜœèl8…L§<»Ì‡°éÜÆ’ S…éÄÒó½“=6<#¶Wl:‘យΉè¤÷eF§”L¿€N§~ªV¢súÆìC§>?Æ$:ç TÐ)Ï`Èé”’bAô Sã•éœHRZ§®^ÛüÓ᜚’4 NaäÓKêl½‚sêcwœº¤Ë½äÄfóU7›ºvlODgS×—g&6ù‹ŒMÏצ<2{chj0ÅަmL„æ(~´]×ÐážYĦ~]~gSCµ›ò“+³©ÛüáclNLúÖ"65;gbSϓכ!˜„¦~$wBSûIÍç·g£¢©)öㆦÎâ[#4õ'¶ÓWNtÍç+1C\ÇýteòÁEÉQFáàKÿðPë|îÔzö¹OÌÌ]y¾á”dWéd|Ç©5æºlÄr„’t´»ä´e§­]Bm}[ñ$„B}–?M4¯ÿåä¯aÿöð3Èߞ݅à?¿ Ûú´z²#:-£–/©'ëø¼zR>󨞬Šz²k€ùlÅùïä:}­}RŸ]¶/ÅÍ>=aa€õ“=§¾³¤ÔìÓKµMÄ!öé5ûÞØûô:-°å^ŸŽ¯GÍë£I‚ü5­Oï2À÷€µy}zo®l ¯OÇð·nø–€4{}dv»|Îb^Ÿ>–í¢­OÇ:‡Mè]ëÓ^7µ›k}ú²A“;}:âø6¦p§Ï€Ê†~îô8“6p§Ï@NCbõä¸0ƒ7_–9}†ôÍ>}r§ÏÀjª.¨„ÓGF«ár§”øúe8}F qM8}¤j¾yµænö»Ýé3°9È«5r,Ë„Óg`‹óM¬5à×Él½˜è˜FË­>Râ§°úÈMⱌ°úHIµ™AX}d °ú Ý*Íb-) _k}F¶D§£õÑ:VŬ>k¥™]”ZEïÆ°úè!›çˬ>Ò®'L‡ÖGKÌ:dZŸ;j²ÖGJÂ1O&ÞEyÃ_’Qvä™^ãF$"8¬ºëiøôy™‘Ü;É|XPs$±²K>XMÞ DŠd-W,ì8“Ha±˜M0Y#¥~3Y‘P³][Ò‹w—½:’HäöA¼! @Öd&[ce‡qÐ|–$´‹‘옫B²c÷¶¶ÉŽ`ØbeGœ×Hw$¥ÄçàNdï3¦‹NdÇ^gãØ‰ì;;ˆìÁºwˈì˜ÛY0ljìÈ€¹ˆÈŽ-Ó¶,íDv›Gl õovlÉá&oÃyìÓÚýïo@‡ÏÅPäåOöÄÊó$bmA(]\<鄿ìk ›PØÚÜsØ¥7¡U.ƒ¹[Ñ·ÄF´åâXG;²µ«Øˆb*a¶Ê@áÁÆòf}:~Ž(¶.Z@t¬z3Qvø(.6Qö¹BŒéˆÖþÙ@4cœØQìòÍö&Ê~Me‚¸Kû A5³ªYw¨LÖ¥Ë=í«-AÈ>êmÄZf$ňUÎA¿ Y±ýÑ¡Œ!köõˆ=bE`8‚{Öß°©¹cñ ©¹—&nþtëÍ`þðÜ-·þqFâËæû9¼ÄùC0§°-½#ýcÝøÃ]\oäB:ÎbþHšÄß@âŠaŒY±(aób4ܘ¿¡ˆD ¢€C·ü±‡r¨’°A´1fÅ=2 @)¸Þ Y±uǬŽ1dE¦”¹ cÈŠÉšP}ȪŸâNr`ûñ$>œXÔ< áŸ à@fól ÖY·!+f©€#ÅBƲ&iÏÐñ!kJžåµ‡¬˜^d²bvgß²êÏdSóÐ[ùL”gîrŒ3Û:¬{_ë|îÔzö¹Ïû(Ï7œ’˜‹²‡Ø%˜ ·$µµK¨-/£¶¢ä›ùÂIùå ßœ”çg…c‘C5Ï.•9¹Önk‡ïv[¾ÛmíZ»-ªµÛÚá»Ý…ïv[»Ön‹jí›h‡ï¢-ßí›o׊¶¸Ön+x»©ÀÛ-EÝÐçƒ|á£üþ‚|Áþíàg¿=½ ߃ÿü.|lë+¬”Yž½é³‘[äìóbÊ®š©F¾-w›u0t[ºe·™îÎ|[2PÌn¡4ÝVÇZ¤Yé\·ÕÛå¾éÐm鸥˜€Ë|[RG½ã÷ÕáR覡ÔÐ]›91Ý·Õ±ð¨xnÉø!£·?Â-ÌYné,ÍDš.Ü’…½h$|[ËhêzrÝVG¬þ‚ÐmI‰jܵՑñ©ð‡kkàdÞ\[],Û’.ÞsI÷¥=ñM‡7nnJ:÷m$¿ÕDvîÛp¹grRìµ®f×2ßÖ@2’ŽIÜ·5°6Ø·5rñý¬áÛ¹†;Ë}[éµöÝ.ÜúN Sp™qKJL¥eº­ä³÷¹nKãaÁ ÝÖÀ#¦°okè»xôSîÛ92ŒÃ·%%ÅO–û¶öØw¹oKw'öm駺•èè Ï…oK¿j‘oK#dö·é¶4B¦ãýÐmYM[qÝÖP¼­ŽƒŽo¶Êø!I¥í³L$R;«befiÏM$¶]Ï’‹ø¬Šíxù‘ÿF²Tw m$‘âp#RŸj$/yÄ]ChÁclŒÍcC˜E±YðéÆ#yF~‰Q|aE¥LG’_û kQ¦| ({÷ü‹€Rê¸l/ ”GÈZXƒ²cÏ—&”½K£&µÀ¸p&»çN&u¶£Ý®3Ùõ5‰˜ìHÎ01)ÍͶÎdGnÆd&ûÀ^vàÉ4jùÏt&;ÖîÌèLÊìeØä=°ìxoÇÅXvÀ˜Ø‚×±£ÂRÚñ®*°ìØ‘K ÓÙÅr,»*aÙ±KㆥÆÁið:¾R'øeÇv‹AXvÍ¢ ,»æ2$ÂR#ee–ytš—°{dÝÙöɼœ[§Ynˆ^áÅ܈"ÛÄÌ­Á(žáwF÷F²Ãhò¥…Ãhq•Áa4yÐzCŠ÷!µN”"ݬ²HVÓ{_Ǧ:•ߘ–¸†ÓouÙ˜ÊÇnŒvßB»ÍË£ù›Ñ‚ ÄŒ–ÑCÝìŒÖØ™·­ÝwnmFñÎ"ï&ƒÑâц)^)3RÄü͸"}u$‚!…ÎŒ¶Z,¹>m%\œ›Qd ´£ÉÞܵEÔ7³ÏYîˆÖ悉(¾Š=•y?Öס=°›P ÷Üm¡ð @¡—ÊìuÖÊrY÷‰ù* 8[ÄÑ6œxÌLp"ûֺȠ[^ƒM'Â_ëFgC|˜ÍÎ]7%ØèøÁQIëênÊ8Ã÷¨Ã³ï÷µÎçN­gŸû¼©ò|Ã)93í(;‹]B3í°NrK”œ¶¢ì´µK¾ù¬=l•Ò¬ýñâ…}ñ–`ñäR™}‘kí¶ö||·ÅI7ÑÖIà‰¶¨ÖnkÏÇw[œtmžh‹jí›hÏÇ£­[ÒMÜ|'ÇÛâZ»­˜‘ï¦ÎŒ|·´Ów¢¡¯HÍ1Så÷7iÿõoü>cüíéMøžûç7ác[_å«ÌP?NÚ?§¬ìúš&VVvÌ)M>é.k,VVv䤫QÊ \Ëûf×r—Œõ³û£ÜÀ%½g~%A^Wã ¸zŤH¡.àê-ÖƒBÀ¥+à7meÇí¶Ì~g®ÞãõeaàÒq{fse‡®$³K:(ý"×ouèÊMÚåú­Ž7ëé!ô[ªCd†~ËuõS®ßÒA§9Ä\¿Õ±u£˜lËô[:¤¼i+;Þöe½ ô[òdð°|è·´/4µû·Qpy”û·º¾•K?åþ­ÛÐtsîßWñô×ðo¥…ðoý–¦ðo ¼®Ê¤yîßÒØøbuåÀ†Üм‘äú°~k`ÈfòH×o Ý‹¨_îú­Ñ€‰4]¿5°/Ûd›®ßHÓµ/7ý–\;†~KJÜšú­™¡5ìú­eBeý–”øV®ÐoÉYrí™Û·öQ˜ Ðí[‹˜ÖL°ŽEgýCæJëžË ËX ÜX^±õkc‰eø‘˜Ë«xÒæò²D9â%v«9˜(04ÌWeƒY"yaƒ‰w¼Af‰œè f‰›vƒYÐ}ƒl³Ð˜x#ªF°6›ètíÛƒÍ:Blb·¼1l¶ël6±”g'5ØÄljf³mÅ^°Ù¦ÏdŒMü©?a³Ù¦«?7›x=ÂêÌ&<Š•²]Ó-Ù§Ëî“­²RâAÁ`Ó➬¯”` äljJe›;›ZÇ€q6{îä 8u”ß ÁÙ¡0[žÃÙ1Ó0?¤Ãi©;‹àÔ:út85±ÎŽ(:Ñ 85a*‡³ÃcÞ[‡³c~:&ÁÙG¨}‚N©“íN :;æB…½²šTèÕ/Ÿ1XvxýǽM¤fÏ9¤æáŽÈM*öóµ©Í7*Ry ‡e¿Bý¿IÅ+ØÇT,˜ê´p“Š€ŸžÛMjʾ›d“оÜHMÍWL7©º§ŒAE¢Ý:QýªÅ "ûrÝ:QÕN3§ˆ,_¬°Ô“4nœ" dÞúЛs6§¿˜óZ9E9ƒSì¥)¬~–4‹ÿoN Bj¬™•GŸ§›lNKˆC7§x<–ΜâåUÆ`pZâm¤›Ó»7§%»Kts ¿¶u~Á)ª‰–Ž1ïfpZJ»;,µNeý³ÀiZáÀ´d¥îÆÇpÇ¿»Ð^kµØÕ¦ÛòêRœŠÁ}¨þL}zoJs¼FuSZy·Ã&¤s´Åõg@ux:þ¾ÖùÜ©õìsŸ÷Xžo8%gêegª±KhêNJjk—P[^FmEÉ7ŸÆ‡Ëò‹Óø¸,ÏÏ 7#ÏÆž^*u3r­ÝÖž ï¶h‚¾ÛÚµv[Tk·µ'è»-š ï¶v­ÝÕÚ7Ñž G[å”"8Y;«8­qÕ×›S ”XhÙá9wÃmpÚÂxœbÉÃ…ÑÎ)¤¥Ü8•»Á?åœbw^aLûÞ(¸1¾=è‰Ï’=Ðmœa~Ô¸Íîouâ3§Æ³Ï|ÞjIíïrgxM>¢„fãa¨¤¶v µåeÔV”üpg˜ÙòË ô0[ò)2cãmfÿx™ÔØx«-{´ÄózkéÔ‰–¸N´tæëÑÏê­¥S'Zâ:qûœÙº·t›ÓÛMwêxK·:ÑÒž­GC4£·vvhæóóù°Z~óù/cþöí#ÖoÏï»w¨?½ïÞµóunËœ>6ÿ¬Þ²Cew¬š»ú~Yo˜»4C0³WOWn^=,Ôp^™¹«ÃžnÖÜÜ¥)wÍ]:/˜ì·ÔM¥îÃ3s—f½Y3&îÒ……›VOzðe‘õwi–®ë¾LÜÕ›ôÛö!óviê–{öÌÛ¥ ù‰­zÒ×ÇüÓ½]a±ÌvËçxxöT¿¡›Ð]*iâ.é0sX2!îÒMÝ6´tqWŸùŠÝù&î’N¿øùssWÇn<›ª¹Kgô™Í]2£í‡nî’qîvó™¹KÎjliVu×À"“þLÝ¥Râ%ªîX v9™©»tQÃ]|]•³ºÌÌ]2(Zqøfî²m{îÙÓ÷2Qïn ºEϿԬ]2ü.>qk×ÀÀÖm`fí ÛsCj€Ï`o³ý\Óv X†+¹’ÇŒ[Õµ]r㢪¶Kþîñ·i»TÚa3×v¼/˜k»´Ž‰ z]˜ÿ@B=±ˆ·è1Š‘â¼QÄ›7ã}ܛČ}‹I,WXʃD¤º²gÖV«˜Cô$>rËÌ>ÑÚ ê@“8DŠýuã°–\ç™:å"–lÌô "}Ù‚ƒˆ±¿Í×ÄJþ "ÒÝ·è îèÀ¯VLý€(ÅgÄjëª"VMü®s‘LíÞ:S \ˆšKÌzË®éÖ¬·Ô »ë\«¦¬á÷¥ƒ¨%8ì¥o]­q¨ã~wÞ‚CyއúllÌ¡ÌÕS¨7Cy6n½ßÐÍês„3ÖX”’¹}yÊ¢nho•XÔÙN=vKVèéZ®ï 6e{ÅŽÜfbQ7¦[„ÍYÔí Û--¥9‹ræ²?ÿ­CnxÈ'çéÄe±,úfv½Ñî"场ÒÁÄ»9œ…è"–¼©)JƒÁLÛúdê³i0šØPµnhî-VMèUG(šµç5ØÔ·°ºCÙcù`öšÆrKµ3Ô;›¥îÐØÌûuÁ&LDùÆæÞ¾µÙD€ß;"cóÚŽUg«ÆÑm›ÈþnlÂÉSŽzVƒ‘冿UBôèh²*£ Î2¡‰nbv4ËAÆÙ¬xS"÷‘òM3Ê&ô¯Þó:œp@ŒÁpV¹I2³‰}LÑZ¤¤Å ÀÙÄu±ºcò|q?©!ÅLlâɸØ­)MÖÛ›[Ÿh⇖EhFPd£Y×V$8š5D`›ÌV<2à+\WË¿—[¬Ý·Bι(9’栆 ýùx¨u>wj=ûÜçå–çNIñ$Å#·Œïø™J"éh+éhwÉi+ÊN[§ä´õmå–X|»bªñµrËó³ÂÖx.ÞÛÓKe¾F®µÛæO§¶FÕ©­]k·Eµ¢­ŠW?¥AmE ·ujE[\k·…õ¼º¸-/¹µµkí¶¨Ö¾!å.³WE[QÂmZÑ×ú¬àë°€}»—PÈàê—^B‘?ôаÿö@ñ3Òߞ݊ô?¿Ûú´áYsit6\æR —m~†K]eÀ¬y.zÈ¿ÿZ½e)M3_.¨ ƒv°.HºÜnÝZè‚ ^@mAw×ì ´÷¯¹.¨,¼šÙVš5LPð&›.¨^©Ç;ÑLT¯Þü•gf ªx¥¥»ÉMTbñA|MÍ-Âî ªÈÝK$¸¬Hq+,ìª%2OCTkŽ/U¹Ø>ŒvaPE0Ãj. ªm«æ]T±Ü–YTè¶ ˆ ƒª¾TÒd@& ’¯2hø‚*rñÜàe¾ ŠàÂF½Ú±³N›q_PÅ›,Ü d¾ Š¸ý _PÅk'µ×ÉHÈß%ŠD».¨bÈn:÷UͯUŽû‚¤¤}á ªx‹ºû¹Ì$%>Ð_PÅëYXT‡Ë¡BTõÍVbº ŠQ³¸-¨â¬3ǰI‰é„L¤ÇfjMWU5H™ïÒTAvlú)Séá›;ÏLAú5æ?2SPEª#Ëô*^W§œìÎdÄ&•º-K™jKc‘ç¹ÇÖ|­oãØåƬlï*t%¶w]Ãb·ÐÓ¸VdUÈ¿áˆDã‹}³;,Z¼ÀFþ\Åetc©%ÞAa8"¥s¿YÁp ¡WЈmDãcò×Ò‹úæšÎ,"{ÈÂÁ"¦ v,Á"†Öâ±%ØôÁbmÃïcEÎLcëŒOŒº;€å]µ´@8`DÊ­¦Æv]w{^ÅÄÄΦӈ€ÅXƒÆa¥€Û¼û-+nÈ•FD :Ë»*¶÷Þä] ‚c02ñ³êÆQwÆ;LñKˆr7Ÿ˜:jw³ù„ º³ºàÝ!‹Ý³“{ ³ŠŒ¹ÔPùPºÛõä›vj€¼`¤rYð"¥µõzÚ¬O PûìдZªe8@ ² دW° vó[€Ù‰Ð‚mî·Þ²ÔH¡B îîÊJh8]wBåq¤;¡E{fÐl·å„ê(Æe–FhAøÊz1'´Ôи¡{ý:Z7o]µZÆrïœZ0Ó¾X ]ð"akÅ•këÁá@TÎÎr[«#ZpÇ^ì •ˆ¯z¢¥W¿¢r€þ¢Ž@´ÀLéÎKCT†x)äy†hÙ·¼£ƹˆÑ‚74Ý$´E³‚:1Zôµ'$¡-=¬,Á¨ž ³Û£2š,·n³´âó¾=¸ú—u›‚Ë‚„”Æ‚ËÒbmå6bµ<¸@_žoÂ<`oa q@…³r;ÁìcFÊ…#ˆÎÓ2Adt6\Œ±ÚÜbÓÕ­,:*#ÅeÁÖ‹Ê}¤V™7;ÞJÈŽË2B¿±!ÄÈ€Ðr‡ûØÍ ¶w%v@ŒÊX…® ʬK1Þ°AyØW÷w,€¸én~K9Þx)ê0¿¡¶zã¯x²qð‡Ñiç² û­Ä†•¬·,ªeÖ[j»,d×*‰G«ãH»Qƒ> sgúPÇl²AŸêKÛ>Çáôì7øªï7ÝðifO[aöt˜»˜=T™d—•‚Âäá:ôÂäxQß³å™s‡RãÌò£GêÞ×:Ÿ;µž}îófËó §äDå¢ìÄNɉʅ¡’ÚÚ%Ô–—Q[»ä[GøÂlùåßÌ–çg…ª‘C4Ï.•ɹÖnkÇîv[»ÛmíZ»-ªmØ]´Å±»hëÔŠ¶¸ÖnkÇîv[»ÛmíZ»-ªµoÈ»‹¶8v·oä]+Úúš_Ø-¿ÃßGØ{ øéoOoÅ÷ô?¿Ûú*½e). ›ý·O†ÍBÖ%£õfƒuÙ€NíX.ë*è«ù+MÖU4³TõX.ë*0Fj°"d]e•x¤º¬«¬x«`Ⱥ*#ÚŒ»º*:1s~™«K:ipÂÕ%¼$ë.ÜÕUU|oŽ=suU +õ*¶uºdÏ\]2U÷WU„®«ê®|–\êœúbÉ¥ >ü-¡ëªØ_¬ëÐuÕV|Óp躤£ó7 †®«¶#ð2]—б;õ4tfR*×uÕžMw¶.œ±­ËgæØ3]—<ÕÝÝ K¹ÏC×U±S>™øÒt]U}X&µ4_WÅpK—ÝÂ×¥a$kÇ}]uTß)¾.=™ŒË…]Û×ÍæÂ.”Mvi`L£5aìÒï²ÓåÆ.­cÂ]øÒQd»¬"”]@»¬D×B+öà_lº¬Ø•I©§G\ÙÚ¥UØtYá4 ŸK»êèî!ßk a®3™Èu`0±GB—³7˜ MvÏlAר³#ëë&Þ¦1Ó Ìî;Ø6˜‡7V]V8üÚ$2¡gÏ,»¬Ø>_+‘¹¥%›Ì/_ÜdbOû¼“Y/o&ÈÌnÒ?`bÜWL$ ÐjÊÜv¦ÜÌ~ï˜xÑ‚YaLžX@[+\—“ÁDž‡öØÌ.–M&´7“q™Í\‡Llè,Ò«=2Ñ7™Ø6ØL$À4öÏÊ¿xòÙ¹éé&RÔ3›ôjÕˆ &ž?7“^ŶÄ\bïÌ9—=Â|›ËØž´±D„Ìweß<DzÇû%fîÎ3,{ömŽKŒ_u-ds‰è\Ìe]øg…,ÙEÑT—3ØÄŒ"VÚQ„º&‹. vuXÿˆâ ¥Êˆ"/Âd“(‚3Ú9¢ú߉•f|å„ì\3´œÐ‚—•›ÒÖ-Ø\ÔZ%dÏ 'Tã ‹=—E_Ñ4‰Ð‚%N“7:¢›”&«.KÀFˆêZ¬º,-ÖãÑ‚ëcwª#Z0ųûÛ-PÖ.V]tE•}´¥ÅÆ@´`FëQ=ûƒ;Ï‚»¹PçY`—LŒ¨&ÌëˆjðÂՖƨ^î;õ”r×YÀ£ý&'´ «w"TC)%Ñ:_ûÝN¨<ík0kˆˆ-Zô…îìº,@?/B´À~ÙXF[`¥Ž³ôØî„–íÛqB ¶ÈX÷ë„–‘]{„ÚuêDhA¾qÏYÀ7AwI‹ì®Õ8Ãù¨ÃSò÷µÎçN­gŸû¼îò|Ã)9Óï(;Sr¦ß¡­ä¬–(9mEÙië”|ë©|è.ÿ¤©üãÅ ã-ÛâÉ¥2ƒ#×ÚmíIún‹Óp¢­“ÒmQ­hëLÒ£­[Ž·E)=Þ×ÚmíIún‹Óp¢­“ÒmQ­}CîIz´Å“ô}#Ÿ”oë«’uLyùÎä?‚þÛÄÏ@{z'¾‡ÿùøØÖW8/åYxÌÓ™üç´—ú<¸Ø¯WTJÄÖ.]7§¥[»J×¼Ò#í*șȬ½,#Æý!í*3û*¨K»t,¡ !í*ˆq›àÎ¥]/)7ážK»Êjî” iW½’'À†´K‡ÕJLÚU±åÃTZ.íªHäÕ1MX»t0a‡ìÖ®Š0·=ÛÝÚ¥É7fÝtk—À[nÖ®Šôa=9.íªØ7¬ÝWH»ta^×§CÚ¥&siWźjÚâK‡ÜÊ¥]UW M·gÒ.™r,—â¹´«bîgŸriWÅk2K»ª¾|SX.íªFºnϤ]ºÞ™ØË¤]¿°°»´«âÍr®Û3i—–˜ðÎ¥]ò]×M|Ya_ìì’áPs[¦;»¤d¼š Ó”]U÷d²Z¯bó½9¼TÙU1PjlÖÓezš¹²Ë^޲«bÿ´[½LÙUueøå»tÔoçÁ]:Õ2%¨»*‡fã‹§´*?`Ã8TbÞ™JL®ÅTêv´ÌTâÙF«Ém&• ,KuÛâÆR&vÿ:•%vl*1—p¹žS‰uA·•=âmAeÑmd,½,Ø6ÖÊ‚Ñgg( p0±ŸCY€ƒ‰;ÊákfmÕ¨u†2aa§1• ·ûh5ÊpséUxLÌXbU«³¶bÇRÝT"†hú× 2G‚Цs‹›Ž¶æé›6•%&ì›JläqÁ¥S á›ôtŠbîÊ€R÷L†R“C‰kXnPbh€ ²†HgS©×ùF¥>~ØxYkŸX"݈±ÔùQg,Ñng“^­‘H¹¹DÂJgᥔø¾¬ ¦ªJ ƒ‰,œ—ã Æ²öòÑD˜Ýe-ãFhö­Š‡P\ ¶]*ÅéÖq–ˆªB…SÃnBW?´!ŠX~gB±F:ný&öŽMöE=÷™ Å‹(ÌÆ„"fåZG¡ì´Ql¤H7D‘6ÙvY ó^ÒÕ€A]„¨NôwœÛÁôáˆØ.ìiåˆÊ#®ºÖÓ--/Qyè¹êðTü}­ó¹SëÙç>¯º<ßpJδ;ÊΠ㔜iw(+©­]BmyµµK¾õ>T—_œÂDuy~V¸yöôR©½‘kí¶öä|·E“óÝÖ®µÛ¢ZÑÖ™œG[<9¶N­h‹kí¶öä|·E“óÝÖ®µÛ¢Zû†Ü“óh‹'çûFÞµ¢­¯™Â‡îò;œÃ„ý·ŠŸ‘þöôV|Oÿ/ÜŠm}•ïr s›ÃKÙeÁrX›$ì’¡àåþ<v|ý"£žp/–]jæë2§×²t³léÃ×Uàwl캴¬È—ãë*½§å盯K7ǘÜÍ}]2¯÷ìûðuU}%‡¼ldY¡[æâ2_W½¢k _W½–ëû\×¥s6]ÊLº¹jÎm]ae+0Y—nªé,ºÔI¼ïïQYW•»ÙMa.ëªx0»bOe]¯uסRȺdðÜ{ç².×[¹ºtìÙÕ%C[[± U—Ždûôju€PuUlýõtjSuU°O¯"/Öíy¦ê²É·é¼ÌÕ¥Iñ¾)Â\]:·ö,lsuɈÝsÂÕUñÖsÓ$¸«K“ô»—X®:&×5¶C]š…r˜¹TÕ¥y ®á3W—.%fö\Ê ¾†ÃÒ\]U“_­suÙz#»º*–¢Ü g®® ø»ºªæº²S¯ê>ûöxzwÚE—‚¥æá2–ÙÓ–‰$zš¥Ý33‰r"ËeÁ†ª|ƒKüãe×}wL%–ŠœA§/7¬“©œÍÝAe™Ã§ßAeÁK^ÍIçTÊ}sjT W. ,-«'3—º˜˜K¼A ÜÀÄàf ­xׇÕq0¯â¯Ü`bSÝœæ[ü6˜W¼aoƒ©o=gÕ¥Æ]/ëd¦ês¾& .nÚ34åÙçk²¦œÓi3ç@S&xÃzéfö¨Ì&fS–èi˜Ñ5±fks©Ñö\j(b²èRC.Ìs, üü‰±„ i-æ=QîÌ%"îÔt.!°ÍÁ%â;ô´¤1–%V&7–©nŸcY†w7–x͸a‰¬“9_>5µ?ˆb«.K ™ÿF¯k¹*QZf o´SZ#=(EÄdÞ(­±ãlSŠ´O¦´Æ¬xSŠ f Ja?°O¥êwdMtAz™2ƒR¸ULŽ”âYê†Z§TÓDRÝWÒ‰QÇÛóÀÕM-,º,ЫÚímˆèBTg™D—ºzk+GTW­­{uDuø’XtYðêÌk¢:¿6g¬#ª‹Ö¢ˆO]ê†É„jÖD&BmÔQù*ïA‚Q}.–D g†i7™;O[3gI´n˜°§T\jì̸´hSÙ]0s±‘VÓ›.õŠß,ÑímLiÁKzÍêá˜Ú~¶D떉½gWìÎuLõ·ÖD뉭Ý{Õ%[+ ß8#ü¨q›ÝßêÄgNgŸù¼ê’Úß%dÒð2šwì’3e%µµK¨-/£¶vÉ·7i˜êòË‹óP]ò)2‡ãmfÿx™Ôâx«-{´ÄózkéÔ‰–¸Ž·Dóuoé6«×–¨Ž·t«-Ùz´ÄszkéÔ‰–¸N܈g®î-Ýfôvûž:ÞÒ×ÌçCwùÎç¿ÌúÛ¹l¿=¿ùÞñþôæ{×Î×ù.Çû¬úo!»´¶•D^6¥Á&/é÷ý…]aòÒÔ¸Á²Ë÷™m w“WAÆPw·—š¼ 2“mŸ»›¼t&Ðݺ§&/æ'–]–AÞ0y$ŽÌØj«Çƒ„¶åÛM^e­è)ÜäUõÍ‹îöR“—ŒÏ{(;ÍäUUúauÌäUÓô\³0yUˆ·&[ö„à±KÔ0!ç- ‹nòÒwóÁäUq{,Ö]VŒtÜ0g&/‚²É«"k¢“—Nëm½«¼tÍÊý—jòª¸xìØÓÝð~´yÉßËžd!òªm¿÷ÁE^UǾqRE^º¿‘WÅõ_þ·eÉâõ ®ÔSWÅÒÎbÙ%rmíOP°á> ]º“@d3Û.±vnªÂK7ί£ðªÒøA˜Â«bsˆ »ÔàU5EÒ¬•¦ð’;ºGM±kÔ ^uÊÂàU;Öt­Ž)¼Ôæá¦{8ñ!#Åá°iâqX[X΂CLÈÛC,°TÆÛ'Âkib=åæœ-xó·ïTw ǪQ'0̾„º1c;4ÃTƒúRÕ;ƒ-|ˆÎ ÌØc·ª3¨3v7îƒeÅ,c3ˆKçªUg%~¡A¼yÓm4ΠŒ+Íqb¶6ŽL¯Œ˜2o!½!(£Ë8 Þï×ÁT}Ï~¨¯T-Œ fë31ƒxùÀè‡AxR ge²9Â%é b¸ÝY¦'%.53L×,ºÔFn×s…œøÍÎ 4¢þ)Å»g]QéBBèçÀ1Ää=ôzF"\T¨$¢[¹“ˆ¼æ¾ELn{eq¾Ü¤,²ÐYtiqÌÅ,Ö+îø`Û/j>,b±z‘tö3¢Ë¢Ñ„rëw¨ ¸Äöº^˜K<¹Gg0 Ü·þÓVëÌ*ÿå}–ƒ‰D¦u³&ß`¿Á„RÉ™f=Çãlb·Ie mÁôi2šxè»rÖÑìÛâh⾫DfÁÏÜ;ê*½ß·FfÁ›# {. ¶ú$4K«G­sÜ#d64 ö\äšx’_…Ð,ºC%o4 &„Þ›ò=ËÕΦ΋+Ë uA{ÑeÁ»S¼66 òä³)óÒtïõîQ7S4î ö×ø#ÌØÔ³kWÀÙ,èóF³ôx1o ©Çæ£C³ e?ê(šÚGlÍÈ´ÅîÄhêì<ìÏÉÎJŠûÅÑ,H=½dÁn–?+™:5÷ÐÈ,ÒS`9ZÍìOïvÁ‡N#e‘y.Jޝ2ã Ã:áùÃC­ó¹SëÙç>ï¹<ß°KädÔS*+‹ïø™J’?Á’Ž6J¨­(;m’ÓÖ7ö\"¹O.Οä¹O[QÂmZÑ×Úm!DØ'·å%·¶v­ÝÕÚ7ÑuñAéŸÜŠÿ{4±ÿ}ya%s^rke×Ú Q­Ïº- Äùý~^EñÜßÀ}÷Û³»ïøçwßc[_R[ž™9òŽæ ÞË»±ùÙ<”3ÿøbŽË9ü·?ýFž÷rON*üg×]~±â?þO²Ô´üN«¹¤éfnZMùk5SÚZÍìZMü«k5{ÙZM9Þ?ÛÿZÍ6C«)ÿZÍö'k5UYÜú¿V«Ùuµ—%EHí¯=aÈQ±>?$E2rÚë&)ÂøÀÃ÷.)JX±²(»IŠä¸C×í’¢„¿;Ê$E:²ó¥'“%ämÇ‹“tOkÒ®u‹ü4R>^2IQÂÊ$)Jº7›%E:ªëìÕ”Q]˜¹\R”ôYæÌ4IQšÝ_(–¢4g¼¢É-E2ô‹a–[ŠÒJ5¼Ef)JKîy2¹¨(é5Ìf¢¢´äÛm†ì¢¢„Ä û.*’1dóð‹‹ŠÒî#tO‘V±yŠÞÔ‘Y–°¨in6¥%š‹ÅšRR}Êæ¢"ùïfãó0ÉãÙ§ýa*’:ÓE”®*’:Õõb®*’’ä:KWé0XýFn*ÊX\ÖR˜Š2ÞqgþJ7eìê1Ç«Š´Ž~“›Š2^Ib’27i=¡*’ïöìxWeXúÍ¿éª"ý&VI6áª"üé^¥ÓyæƒnÍa÷ÍAÛAKcoØÄ›Cj!$qsŒ´É…\cÖ†ÉEˆŒ'ˉþÂB'‰Ê6w "ñª_v"s›~¿‘XTîñòù³‡°=ˆÔíÓ“ˆ¬gúîDb㻿€Á‰DÉ`¹¦Ìé"ÜDb—¸}s©Sö†%쟮lºMwÙ¤0ˆûÅ2A$":Æz‰ÉY%ˆDúsb»fBÒż9G§#‰Uf“¬’ûõDI™û,&òŠxm9÷Ë~6‘Í|H}7Èf‹ÄÁcÒéK#vm•J<&ÄÓÈËß@ÚC…Õaò©dsÀR¿k4"R~¥¯Û‘zÒË5VhÛRV¾¿&€”®é3õáÚ!©ßc¿)Ƨsøþ‹¯Pk"ÿh^‰ù”»¼\ÜeÂxçÄ:Ÿˆ‘Mm >ñ¶Ð~1 Øa½X­ ]f5¼-u°ú‚ëËîeç ê%³YB2â¥:/´% ŸÈë^þîå¿u]7>¡À¶x”ó‰.ô² ç®f±1çsênvkbCxg<‘ƒXíÞv<‡j:á9ÃtbÏRíì¾]°°Øoà­Ø‹EÔKw:-¢¡œâ=¨Ó‰Ä%ê/±õ©Ú© 8aúÎ$ÖÔ¸­îXª²_étNuFÃsh¶X#<6åsw‰£«fˆv<6,¤ExμîZMlñ¿ k5gõ” çU\ópÎH¾Ølbæb¯F:ÝûOg3áÔç§4Yª™ròA Ó‰qŽ]‚ o$›•é\xsʲ üƒUs`MbútÈÃø„Lf¯-¾µßÆ«Hk5$>$Ç5Ë1ø–¾+¬@ªz¾‡Á‡‡åÕXk CöÝ| ?*o SÄ:#ƒ¿SÄ«oB…(üçý:œ/T¼Å¿.˜¶OìV?Ѽ¯µ}Be= ùÊð²ë?CX&C‘…° ‹§w§`Ê*x:¾2¬?Ý•‚ öÂÂJÁ„üâÂJÁ„d«I²Ï¤&s+0aY²TÉí+KȾÈì+KH—µÏ¸¯,aþ’ÙW–J¨6ו¥¯F]™ô×¾7;tei6ïºCW&sjß׺2™ªû *te Q•ɺ2™oúì=te »*´·•éÔܬgn+KËí!+Ó \3™.kAgŸ`Z‘Ìë²²¤9[*AsY™Nùíx]V–0¸pY ÉÊ’µa·•iäN×—CW†Ç¢Û ]W¦uXô©¡¼lþ2³•eŒÌô[™†Ó 5–WXô™!…1ý¢ëÊ,º§‡ìº²ŒQVcѧFát^é¾2 »]f'3_™êÌ`¦·³~÷²ó•`øÊôh3Æþ™‚öìô!Ó§.mWV}"Ö|i¸)°ÄMÔØô)cP÷il*/xpoXâw˜7°Ìr;ÅXT½ñ7–9^¨XBÑ™Ø#˜ÔXшKHn컃Kl›lúÔh¾“6—xaB½‰·N]•ÁìÉÍ7L5?²ê3hyƒ©ÓŒÊ`Býš ƒ9â]áÌy¹êu“©±ÖÅdÎlΆM&΀ñâdÎx¿æ&)—ö«œL„tfsÈL¾_d“‰m½AæD&Sž-Éå¾N¦Æç¬Ž“©Ó ûᎦ|ª½†¦¶cH9š ³C]Ó 4¢#&kt4¥N¶h\ ‰%âRk°ÔÕÓâ– sÙYK]g1¨a©:Ó…:–RÒí9XêÙ3¡c)Gën±ð’¾Rô‰L˜Å¢OðÖdBqÇÙ<8Å6$ €¢Ø†tõNˆ¨d¢]Gt6ßR„"¦SYô gqºС#ÄL€"]¬4@ÑáÝL¼V¹˜OônÙ‰5>±¹Ù-ÁçÒS">oI«ŸÒU3Ý:ŸP.î8±ÇîvÇsªÃ'ž¸%gcï†m:51‰N ·n"Þ‰ dy<'ž€èœ+{'dpêÝÍl¢»ÎÜiâþÓ4¢M&:;Ó‚:™X­žˆL`TKx‘f‘Ÿ W¢dx,³ò:˜¸4 0ѧ—Æ`Êé£SG.ö)gs껵Á©òŽI}&†2­±{Ucã¾ôÌ…=ˆ7¿§Ì Jä™ÛT@‰•顼·'e¸FäÌ.¢Þ×:Ÿ;µž}îónÏó »„Qvæ=§äÂÑÉ™<^BmEÙië”|ë`Âv{þ)Á„Ç‹®Ê[ºÉ“Ke®J®m0A´uK=ò¶(ÉÛâZ»­&ØmqêQ´uÒ˜¢-ªµo" DC')n;O`ò&ö¿ïÏï0Án‚»•“Æ }M‚’ù<¿¿XÂGh{àöÛoOo¾÷¼?¿ùÛúh,AEÈO# #}O‘„°>$|Î6Š]µ6c k[.ó^º5 ë%ýbkšt"á>tkšz¹ÌÏ­i)ūچ,lËqkZ’ÛßFé¡MKˆœ_¬MKèý ëFSÙr3צ%¨ÕLRêÚ´ÕÜ`Ýh‚³\û§Ð¦% åLùéÚ´Ô∡MKx3œ‰Ë\›&%Ëh®MKê g³a¬Ù]›&³Ð¨º6-éë¾X›–Æðý¡MK'Τ¤óÂ䣸ŒËµi þF]mZB¾ˆ!B›–fM‘Òkæ´4cB˜Ó†’&%uuZšÃ'B¦%zÍC–°‹E'C¡N“‘¹¿"ÔiZg°ÛPêXªs˜Ót8_Í¥fæ4™KøÎ…0§¥…³q4a¸°q4A‡EjCy §Q»nNK«øÜ–të¸YIÍœ– 0+š›Ó4‡Ël§nNÓ| “:º9-­æ@ìžhUÚ£j¬‹£HaÏMÀšÔ^ØŒ¸Z5kº³‰$úK§ÐÁ&JJe0^ÊÈ9Úõ]74eDé š©Û ßdæìñºMf–i†iIƒÌ2¢™ ³f»í&ï»]ƒÉ¬E'&³ÅüMfÓ¢0™H¢Ÿ f÷pçæR­¹ìñÞ‚Í%ä5ƒu† ïä´ç–r‰L‡‹u†òUhp‰Û+±Î0AuÐs‰©Bf,Gän,‘ŠaVÒÀwòd卯>ÖJ€q£µß¨Ì¾qé`‰7 Æá-MåÚX/q,‘8™Xh(O÷L—xØÌÁ\"ÿ2³Ñв«ˉ}² XK* f§¦N ,÷qc‰”¬‹…†Ins{ª~…s·F*,ëÆûçM ŒM’Åzž@•¥¢ÃŒÂÒQ}yÑ„èØyÎè@ƪ8£¸_,rŒâBÛÊ{@ ŸÆ¼AŠNdNî>'²h+[GTo¹¤zŠíg9¤˜){Ë)TE–Xêuu·AŠ’Ë;T£Ö‚ )&½s°uMÖž&0EÖʺ‰ÑÑX&ŽbŠ É:0ÇtOÒƒRÌã-p”¢ß™ƒ{OԱߘb®nK/霢Jq¸Þ¿¤˜@[EPŠseA)ÎCšéÔ7%‚U¬·wFaº1y¯#Š/šn!5D[51¯#Št$‹28¢êø/rDWŽ\ñ@u&÷œ ü¬ówDq­|’#ª]©# “¥Ñ¢¶ZÑûÙž8Gi‡‘+LÎd#êpˆà}­ó¹SëÙç>ï=ß°K(egtJN8 Ü¡ÔV”p[^Fmí’oZØÎÑ/…>â=?+š]è«?FúúRÅo]ê=ºð-=¨]\™ln˜ùêà"dns5ïÌ]æ†ôÀ+±r1ÁQÒHƒš’MÝf2·”²%ʇË-ÁØå–ôåæ`4—›eb²Ë-iö{PS™Ó½ˆîrÓíí•‹©ƒv¸Ü’šÕtㆻÜv>›.Íen /´×HØÜR¿\67ÍÅ̶Ëtnº3ªÎM#Ú®ÛÜ^Øe9¯fs“I‹)GBæ¦á%†ÌMç#ìrÓ™Å0s›¹Üdð¼\Üê.7Ý)QX·˜”®®rK¶ýú¨ÜÒŒ%ÊP¹¥Ke¡rÓ{g•›n¦p—¢šÜtïIJ¹iAxQ}SA ±‹ÜFo“-¨Ypw¡‰ÜtK¿i*\䦀0¥ªÈMã¾ÃÆDn £oÇDnZÇå©&rKªz汉Ü4’p±ÈM3H:ûu˜U1›®£Ú>®è›V»nk¤_² â¿C ÔÕ?½A¥Ž—u¸T¶G*[ƒÊËý‡Jç˜â8°LÉÁAe*¦ÉÜP¦æïØP¦xSë†RnO†”ªZ %2±¯ÅPæâª eF2Ód(ñN‘|ƒÙlX„AÀÝÃÁ$–63‰Ö*+u‚±âPâC…‹R&× Q{–xc*ë‰^Oq±a1•á"ŽM%^êaÂÀ²žMcÎ¥ú8 s Æ`,V‘Ø‚*á²í‰Æ%^‚t –ÍÁÔ„\gÛæ`âµH¶•%À„%É6~˜˜‹&öëÆ±Ê†Å¤ÍÅ`båÛSÌ>·.ÙÁĆ“§˜ØJæeS߀<ÌQÚv.™™xqSK/ŸŠ7lJåræÄ®b}qäb…8~‹í†qJ‘S“]{j”°—CéÐýH…(EÔ8¡êVÖD”"§Z¿è˜"¦ÝìnuL6u ¶CcvÙ=î˜b€¥"¦):;L1ÿ´ÈF`ŠMf»N?rÍDéTßí"LmÍ$LÕ¦¼È"Ž cƒ)]Øe¥·‚SªY…%âHQ±õõ tb׉9ÃRìͱ,ˆÀ½žM˜SÝcÌ”ê;5NéîBRU@™Ù!ņ>ðfNxÁn7ÿWoàük|ú„ ¢.X§N4ó¡…Pž~¡…/ãýöë#ÎoÏï·wˆ?½ßÞµóaJ²Õáï?¤JÖ/‡>«dEò&v†å†EÓe®œ›éRì?m圦Ã%7?ªrÅ0 œçÒ5ýÝlaœÓð‚mPtãœþ,{”›pNfñfÎé´À7‰šp.éüà ©Â¹„Ëg–Aê¾ÎåêG5Î¥Z·èÑŒs©¥¶3Î¥V|bÊ9/×ÉYF3Þ&ãzESÎ% /—Щr.ámß¾#Ü”sI­K¾“ƒ~œäå‚9UÎé¾ ·šr.!Õô®œÃÓ?á›Ó̅ʾ9 ¸Ñ|s C&×¾™o.Í#Ćæ$Øvq÷Í™-Áýê›Óœ„Ì.H ¸£¢«’劫﹄‘Ä2Ȥ›†í›M8—l×°•¨!ÞÆÆ9Êûi²‡æt»VÓŒsZ⮾¥»Nڼ綻„5Ù¡`ýÔtÍ%^G¼û[¤ç²~]9ìHF¼ÖÁsI·ÿº¨µNkäú„–uø~çÃ"ÞªáC;gQå7Q¢,&ìÌps¢±˜t%u1ŒºôÆ^Ö“èEìÛuc±Ã¨¶?b0š.¶#'Ý‚!;œìo8Ú0^‘4¼aÄàk0Œ¸çGeñbç9ŒHÅuÿ Ã…jg3«>.Üóë0â£)3Œ%ù[ˆÆ’»•ÆodÜ0"‚é÷³Ã¡¨kY”Gì-ÏŒ#fLþ¤pkªw5«\ÔíCU±ÄÜXœj7ŽhìjŒ#²=J98j®GcëJ¡rvѼÞÀͧ#€Lx¯c»áˆaª 8G¨>ýt;Ž^ÎãfMÐ.º~Óqìy„½ÆyÄ«wgb1¿ÆáëÆ#üë Èq…€3€„Á\¤J7>8Ø%43‹É]_pÓ Î®áî(á„cs¹v®Î”¡©v­‹ûId··ð°*›3’ìÍÑLâwÐTare4'nåAdN„¢ST2Ace/+®¡-ø˜úbb¶–Ã0YË:õ ÜG"d°³érÕ;D£rïì(}Ä¡@"!¤ä²ý ‡G¤þ§:‰G8¡àSÓ̲òu4†#æö‹iÄO~+*ÜbkRÍsb¯Ød4Ntn#\ÎU÷;-`ÔE}·ÀŒˆ|×ÀSc59~±ˆ½Š×­g¼r~e^X7ޝ\§­™@„ Èq¢ªËsˆÝ„#¯#­àðê˦Á!ÒÜÜ£lâHÒÁ–6löñEsß$_t&¨ãß?ÿÉǼ%Ó“ÿ°ÇÂo?Á¸'ÿ `ôN˜ðÿö¯~øí¿ùÝÿe×úŸžìûÏòŸ[Cÿ.þ¸µƒwé¡#övþ"*ý÷Ÿ¼½ØíÙ4 {!¡ðüç=@ÿOçËnªóرU¬ évlJÄcg!ª„D8/ùòÂÄn"éž_n"ù.àO8¢¹…Õ”I­yE|.O. Ø°…œF[qŸEë°ÿôÞ×Á‡ò½ÎÓÝêð7 ÓÕÿê7iŸéxíCõáC_<¼ëáôi¤’/h”àþõÿêÌDendstream endobj 6 0 obj 24655 endobj 4 0 obj <> /Contents 5 0 R >> endobj 3 0 obj << /Type /Pages /Kids [ 4 0 R ] /Count 1 >> endobj 1 0 obj <> endobj 8 0 obj <> endobj 7 0 obj <> endobj 9 0 obj <>stream 2020-10-09T14:37:22-05:00 2020-10-09T14:37:22-05:00 GL2PS 1.3.9, (C) 1999-2015 C. Geuzaine gl2ps_renderer figureOctave endstream endobj 2 0 obj <>endobj xref 0 10 0000000000 65535 f 0000025206 00000 n 0000026719 00000 n 0000025147 00000 n 0000025013 00000 n 0000000267 00000 n 0000024992 00000 n 0000025299 00000 n 0000025270 00000 n 0000025363 00000 n trailer << /Size 10 /Root 1 0 R /Info 2 0 R /ID [<391568A5F5BC68BE8246DE3BB64C11CF><391568A5F5BC68BE8246DE3BB64C11CF>] >> startxref 26939 %%EOF blis-0.9.0/docs/graphs/large/l3_perf_zen2_jc4ic4jr4_nt64.png000066400000000000000000007463341422157504600234370ustar00rootroot00000000000000‰PNG  IHDR¬øSzgAMA± üa cHRMz&€„ú€èu0ê`:˜pœºQ<bKGDÿÿÿ ½§“ pHYsNNÆÊ/¥tIMEä &VeÃh>zTXtRaw profile type xmpH‰ÍVK’Ü0Ýë9‚ìã¸-i—ª,sü<»Û=Ý=“©Ê"vù'!xÀ9ýþù+ýÀQhɉw¶XÖ¢¬­&”•´ªéªY—Ëea|Uñ‘j\¥q–fY²‹®IÛ +Û&½Šâ …ÌXDƃ{ÞÜ ‰7AÍ-–©©Bõnó”Œa &°´ W’]”èªÂÞ°¶µ9^-”ý[wíÆ>絤«ÞæÄM<œ¹«ÁØ%ÜZ¤ÕLþ=pî@¿z8u^qj\˜iB…³%Tš¼_(c¾³ÂÙ‰“@y~~L'sÒ.&83oÀ5,ê!ê¡ØhÀèê'Þ2À £M%x²!Wîš-& `Ú£¢k]žÍ¥î§œtÐ`h£á Ü2\ʱG§DfŠð½z8´Ãæ!•ø¸gÇcŽòk÷µ§wxæ’9ÌGˆÝìP± ipÈ'|eA¦6€„aåÙòŒVÄÑü‰s ýžsÁªoû(„‡p;ÓCÑ&͵؊#ª gÄ”~‡KUð.¼1³á4Á8j÷Ì{˜º)Mg­S鬰CÄ#PçÌ]â•Ùô »/•^ͦ"(€z”#wÄrgªIË ¼.‘cZ„iõÑ£PZ ˜Ý-ŠzР"cž; l¾Æô`ÐeÒ;ÊOR|^g⤿bh ÍõEi\É“¾b¶k“»)tlȪ÷,íhj´ö È!Á†Ö‹í rˆàñ‚WOvyÓû6æU«»†PCÐ݃ÌW5õ®¤Ò»È@ˆ_tË yÒýÞ)]w Úõæ)7cs´þP¶aÓñEÍÓ>w ó†²aºuž(ɹÔ'qíQw‹ïaçWvõ#Ågõ,‚î1Š‚ðc¡À® †×”웢_¾ç“¥ðyò÷dg²õËŒÉGÌ>戈†^½‘–ΠC^¶z‡^c¸«¸bx6wB GÓ»ú:)Ýô6úô/à3زÑþÉùåíCEóìéç/Hµùß–þðXuçÑ0´caNvͱ¸ª€IDATxÚìetW€Ÿ•¸{  @€@pwwJ)PJ?Z¬P¼iâZ k±Rеxqw· $ wݬ}?¦Y®ÙîsNNvgfgîÌÞ™}ý•éõz=@ @ ä2䯀@ @ ÏB(¬@ @ È•…U ‚>ž„„ÌÌÌpvv6̱¬{">>Ã=‘5ï-,,P(¨ÕjT*–––¨Õjt:z½žˆˆt:ÝSÇLKKÃÄÄ333c_@ Þ¡°æ’’’8qâ)R„jÕªt­VËùóç ÄÏÏB… ‘ššJ¾|ùËåh4._¾ÌÅ‹ñôô¤fÍšXYY‘ššJ\\666ìß¿ŸŒŒ 4h€££#‡âÁƒT©R…%J —ˉˆˆ@©TÍéÓ§)X° ÕªU#::š“'O¢ÕjiÕªÖÖÖÆ¾\‚<ÈÉ“'™5kW¯^ÅÚÚš&Mš0räHlll`úôé`jjJƒ øá‡HKKcΜ9üïÿÃÏÏ€+W®0wî\ÈŸþIáÂ…Y»v-ÑÑÑ4jÔˆ:uê°`Áîß¿OÉ’%™:u*¥J•bóæÍܾ}›ÐÐP:„½½=½zõ"((ˆ={ö––Æ'Ÿ|¸qã0111öå|èt:<È/¿üÂÍ›7±··§yóæŒ1sssN:ŬY³¸rå VVV4iÒ„#FÃܹséÓ§Å‹àÌ™3¬ZµŠŸþ™Í›7Cxx87ndÞ¼y†cêõzŽ?ÎÚµkùöÛoñõõ5öeà­ «‘ ã›o¾!11kkkîÝ»Gûöí3f K—.å—_~ÁÛÛ›ßÿWWWt:«V­ÂÌÌŒádzÿ~ (@LL 666,\¸»wï2bÄ *„Z­æáÇÌ;—Â… “@jj*£GfýúõT­Z•Ñ£GŽF£A.—sõêUêÔ©Cll,÷îÝcýúõ,]º{{{c_6A£_¿~ÔªU‹9sæpùòeFŒA¥J•h×®ÇÇÍÍÝ»wJÿþýñõõ¥[·n\¹r…;vPªT) kÖ¬!::šŒŒ 6oÞL­ZµøóÏ?¹{÷.;w& €yóæannN§NX¶l3gÎäÚµk,\¸™3g2~üxÆG¿~ý9r$6l`÷îÝÌš5‹V­ZQ­Z5c_.Á@jj*¤]»v,\¸“'O2nÜ8êÔ©C½zõ0`UªTaöìÙ\¿~ï¿ÿž *жm[Nœ8AñâÅñññA«Õò×_‘––†……×®]cÙ²etìØ‘Y³f¼¨:Ž#GŽ0dÈúõëG±bÅŒ} !¬Y³†áÇãèèhìáï­VËßÿMLL  0öp> D«‘9pà7nÜ`Íš5lÙ²…~øÀÀ@ùä>ù䢢¢8yò$T®\Ù°ï²eËbkkkxŸ™™ÉàÁƒIJJ"<<½^oìÓ|À>žßÿ^½zqáÂLMM bÇŽìÙ³‡cÇŽq÷î]Y·nÎÎÎôìÙ“˜˜Ö¯_O\\]ºt¡{÷î>|˜¨¨(>|È–-[ððð W¯^„„„°iÓ&’’’èÞ½;]ºtÏpÁ;E§ÓÀâÅ‹¹té ¤}ûö|úé§ìÝ»—Ó§O“””Ä’%KhÑ¢ÿþû/¥K—fÓ¦M(•J¦L™Âõë×Y¶l™ÁaÔ®];:uꄉ‰ ÿý7æææœ;wŽP¬X1z÷îÍ™3gضmz½ž#FäøqŒL£FèÛ·/óçϧk×®tèеk×’™™Ihh(¶¶¶«ºL&3ìHMM%""‚ .ðÕW_þÖ¯_‰‰ jµSSSCa›,²öõ,ìììžZö¢í‚WA§Ó1dÈÖ¬YÃW_}Ett4ýúõã?þ@¯×Ó£Gþþûoz÷îJ¥bРAÌ™3|8+W®ä‹/¾àîÝ»ôéÓ‡uëÖ¡Óé8p k׮嫯¾"66–þýû³téR@2z{{³}ûv¶lÙBåÊ•qss3ìÛÔÔ4Û³Y¡P0aÂ&MšÄš5k8þ¼±O_ð3{öl¶mÛF÷îÝiÛ¶-³fÍbóæÍØÛÛãíí™™¾¾¾XYYñï¿ÿòÃ?pðàAêÖ­ ÀñãÇ:t(AAA|÷ÝwdddгgOvìØÁgŸ}F¹rå˜2e W¯^åÀ 2„ˆˆ†JTT”A‘ýüóÏ)Y²$“&MâÆƾ,‚ŒØØX†Jzz:ß}÷ŽŽŽ|ÿý÷Ü»wOOO\]]±··§D‰¤¥¥±dÉFMdd$UªTA¥R1bÄîܹàAƒ(^¼8cÆŒ! €uëÖ1dÈ,--éß¿?tïÞ   zôè““cÆŒáþýûƾ¹áa5"YÕQ?ùä†Ê7Ø·o#GŽÄÕÕGGGÒÓÓ³}&뽕•tîÜ™™3gÖ?|øÔÔT‚ƒƒ}zááá 0€qãÆÑ»wozôèÁ¨Q£Ø°aŸ}öß}÷ýúõ£GtïÞY³f±lÙ2~úé'œiÞ¼9óçÏG&“±dÉê(Èܺu‹Ñ£G3mÚ4úôéCÏž=éß¿?7n¤Aƒ 8Ñ£G~ú‰õë×3hÐ òçÏOãÆ™5kZ­–5kÖ ñ= …BA“&MHOOg×®]Lœ8‘5kÖààà`ìË øÙ¶m]ºt¡sçÎÈåròçϹ¹9øûûciiI­Zµprr¤ðø5kÖ`iiiØGÑ¢E5j®®®XYYѰaC&MšDáÂ…©\¹2§OŸ&<<€’%K2jÔ(ìììÐjµtìØ‘©S§ŽwîÜ9"##)Uª”±/à">>ž#GŽpòäI*UªD½zõ¨Zµ**•Š’%KR¸pa”J%5kÖ4(•~~~üüóÏ(•J’’’صk6l uëÖ4mÚ??¿l‘UªTaäÈ‘€N¿lÙ2Æ““… ¦{÷î$&&ûRä „‡Õˆèt:þþûo†JZZE‹å³Ï>C«Õ’””D¥J•HMMåÈ‘#¤¥¥ÊÑ£G Ÿ¯U«Ççòåˤ§§Έ#X·n±OM 0àääÄÅ‹™2e Û·ogÕªUìÛ·ÚµkcooÏÍ›7™offf0ôØØØˆ(ÇÇw¹Q(Ô¨Qƒ?ÿü“Ž;âááÁõëשS§ÕªUÃÁÁO?ý”^½zQ¾|y011Á¹\Î'Ÿ|ÂßÿÍçŸN•*U¸{÷.)))üøãܹsÇØ§'’ðñ×_±|ùr&Nœˆƒƒ]ºt¡gÏž˜™™ñû￳lÙ2&Nœˆ mÚ´¡gÏž†Ï—/_wwwÚ¶mkpòåËÇ×_̓ԯ_?C~ L&£~ýú¨T*@úIJJ2ü-Z”áÇ>kkkË—_~I¡B…Œ}¹...üñÇüùçŸLœ8gggzõêE=055eùòå†uööötîÜ9Û¼¯V­ŽŽŽ|öÙgÙ„÷:uê’’b˜Ëžžž|ûí·†zcÇŽ%** µZ-„yÁ;gÊ”)4oÞÜ`€üé§Ÿøî»ï8pà3·wppxJðV*•¯,Œ¿Î¶Á»ÂÕÕ•µkײk×.Ž=Ê?þˆJ¥bÅŠYãI¯Œ%ûìß¿Ÿ}ûö1mÚ4âââ˜;w.M›6c¯ø%32U«VeóæÍìÞ½›¸¸8š7oNݺuqqq!==.]ºP¹re®\¹B­ZµX·nLMMYºt)‡æÂ… T«VæÍ›ãîîN¾|ùX±b…!ïÉÄÄ„+W®rKKK¦M›f°zN›6-ÛÓµkWZ´hax_¸paÖ¯_Oþüù}Éy5jP¾|y133ÃÖÖÖS¾|y|}}ILLD©Tbgg—­ñ… P*•4kÖÌ ´xyyѯ_¿lÇ1b„áµL&£yóæ†÷5ʶmVÞSöööôéÓÇØ—Ið!—Ë©W¯•+W&99ssslll ó¾zõêøûû“˜˜ˆ©©)vvv†uZ­–S§Náàà@Æ ³í·qãÆÙÞ,X0›ñ mÛ¶Æ>}ÁJBBK—.¥Q£FüüóÏ$''³`ÁæÏŸÿ\…U È‹²yófúôéCÇŽ‰ŒŒä›o¾aÕªUÏUXçþýû,_¾œ¯¿þšÖ­[ËðáÃùã? «àÕ «‘Q*•øøøàããóÔº   ̯¿þJÛ¶m áìÙ³|ùå—åÒÑÑ‘víÚZ}daccƒá½\.§téÒÙÞ{yyÞ?YmÕÉÉÉ–R˜Â“¡ Áë`aañTXæææO…Œ,_¾œ+VàããC¹rå„•]ç°²²ÂÊÊê™ëžwO,X°€Õ«WS¥JJ”(aìS (•Jþúë/nܸÁ!CÐét\»v-›1[­V“žžŽZ­6öp‚7&--éÓ§ãììLݺu %""‚zõê¶Q©T¤¥¥=·ƒÆ¬Y³P*•´oßž¨¨(BCCEjÓ"Ö\Œ7¦G¸¹¹¿¿¿¡Ð@ð¡caaAãÆéÚµ+ÖÖÖÆŽ@#XXXЦM¾úê«l…jccmmÍ”)S˜={6]ºtA©TR´hQæÏŸ@¹råpsscÀ€̘1ƒ%J<Õ @¨ÕjCDƒƒuëÖ5$ÍÌÌð÷÷ÇÑё… ãàà`y\\\²åËš››S¡BQ`LðÎñõõe̘1,_¾œ… bnnNݺuéß¿¿¡_öáÇLÇŽÉ—/_Ž766–þù‡#GŽ™™I… øâ‹/(P ìܹ“õë×£Õj©X±"ݺu3<ãŸÅƒØ»woŽÞ§oK\\W¯^¥víÚÆÊ+“ÀÅ‹³µeÈí$''sðàA¾ûî»=nhh(Ë—/çòå˘ššd•¬voׯ_gåʕܸqOOOºvíJ… ž+«¤¦¦²mÛ6jÕªeìKúÊÜ¿Ÿˆˆˆ<õÛNHHU«V5öP^™¨¨(®_¿N×®]sô¸gÏžeÆ âèèHûöíiР–––h4N:ÅŠ+ˆ‰‰¡L™2téÒå™-³ ââÅ‹/Ü&·ñàÁbbb([¶¬±‡òÊܸq Oµ<»{÷.±±±OõrTaMNNföìÙ¤¤¤0tèPbccùí·ßÈÌ̤W¯^h4ÆŽ‹‡‡£GæèÑ£Lš4‰™3gR¬X±çî×ÆÆ†*Uªä¨Àö¶)R{{û<#ƒÔfÇÒÒò©õ¹œ¶œ>|˜¹sçÒ¯_?¼½½ù믿˜>žñãÇÓ¼ysjժşþÉ„ Xºt)fffÏݧ““uêÔ1ö¥|eÔj5%J”ÀËË+ÏX.µZ-Å‹ÇÃÃ#Ï(Ùjµšøøøµ´ªÕjV®\É‘#GèÛ·/J¥’%K–0oÞGŤI“(S¦ “&MâÒ¥K̘1sss5jDpp0ãǧU«VÔ¨Qƒ?þøƒI“&±hÑ¢çÊ*J¥???ªT©bìKúÊ$%%‘–––§œG¥J•x¡8·akkKbbâ[í#GÖ._¾Ì”)S –ôÛ·osæÌºvíÊùóçIMM¥OŸ>/^Ž;ÆÁƒ_¨°æEòÒÃ4 c!O°gÏ*UªD›6mP*•(•JFŒÁ7¸té...|õÕWØÚÚbaaAÿþý¹xñbž²¿ “<%ƒdØÈKʇ±HMMåàÁƒ|òÉ'4hмÓsçÎåáÇüûï¿T©R…Ï>û » pïÞ½ê9naa‘çæ‹¹¹yž»/ÁÝ»w¹víS¦L1xoݺÅéÓ§éÚµ+§OŸ&==o¾ùŠ+ƱcÇ8tèÐsÖ¼ˆ­­-¶¶¶ÆÆkamm§ÆâÌ™3Èd2ºwïNáÂ…)Q¢‡âôéÓ4jÔˆ={öàîîN·nݰ±±ÁÌÌŒAƒ§Ò—‘çx^RTß%9mmm ·oß&33“äädbcc±³³C¡Pˆ««+^^^€ôãêïïÏÅ‹}‚WÆÃÇ’˜˜ˆV«%22½^­­-W¯^¥L™2†œÚ|ùòáååE@@€±‡-¼J¥WWWîÝ»GZZéééDFFbaa™™×®]Ë&Ðøùù¡R© 1öЂW"KéyRV±··7È*îîîÙd•råÊ YEgpvvF­VŠN§#..ŽäädCjÝÕ«Wñóó3È*ùóç'þü\ºtÉØC|¤ä¨‡ÕÓÓ“ž={2wî\Ο?OJJ >düøñXZZ…©©©áQ*•äË—ãÇ¿p¿*•Šàââ’ã…G¹NGLL QQQ9nmíС7oÞdĈ¸¸¸@ãÆñõõ%<<???CÑ;;;ìíí }á>ÓÒÒ ÃÝÝ]Ìq å¯>xð€ÄÄÄ-raiiIÏž=™6m#FŒ@¡PpåÊ†Ž»»;‘‘‘Ùê xxx V«_ÖGxx8nnnyª˜„àýj(à•S(P€îÝ»3þ|Î;GJJ áááŒ?sss"##133ÃÂÂ"JòåËÇÙ³g_¸ßØØXbcc y°Aff&aaadffæèqýýý©W¯³gÏfï޽ܿkkkÚ´iH¹À×±··ÇÖÖ–°°°çîS«ÕNjj*VVVÆ»¨‚\ERRááᘛ›¿Õ~rT*HKKãÂ… ØÙÙQ¸paòçÏ\.çêÕ«h4šç~îEë@Ê˹sçjµ:'OG‹Ñëõ>„ÿÀÀÀªˆàÃ&&&†„„üýýQ(Èd2ÜÝÝ)Z´(÷îÝÃÇLJ‡Â¢¢¢ÇÛÛÛØC^‰û÷ï#—Ëñõõ¤^pÞÞÞØÙÙAñâųY郂‚P(¸¹¹{èÁ+qûömœœœ ª²dFCBBÅ‹'99Ù5£R©¸qã†Uy‚ŒŒ ‚ƒƒñññ1ô~555¥\¹rÄÆÆ’žžNÉ’%yðà!r122’¨¨¨ï‡,d‘£ k‘"Eˆ7„?dddpäÈ,,,pttÄßߟ˜˜nÞ¼‰V«%!! .䩾e‚lmm¹xñ"©©©dffróæM)Z´(Õ«WçòåËÄÆÆ¢ÑhæáÇԨQÃØC^ ///´Z-W¯^%##Ãп6%%…‚ R¹reŽ;FFFjµš3gÎ`kk›§zó >nŠ)Bll,·nÝzJVqpp |ùòDFFd0¸YE'077§H‘"ñàÁ233IIIáàÁƒxxx`iiIåÊ•¹téqqqh4nݺExx8Õ«W7öð)9\¡Bš5kÆ·ß~KùòåÉÌÌäÊ•+|ýõ×888àââB:u˜2e uêÔ! €’%KŠDg011¡oß¾L:•   ÜÝݹxñ"nnn4oÞ¹\ÎÞ½{ùñÇñõõåÈ‘#4mÚT´šä\\\èÑ£³fÍbÏž=˜™™qáÂZ¶l‰ŸŸÎÎÎŒ5Š‘#GbggÇÉ“'éÓ§Á’/äv*UªDãÆéÛ·/åË—G¥RqõêUzôèNNNÔªU‹É“'S»vm.^¼ˆ¯¯o® iW«Õ\¸pû÷ïg[îääDÅŠ±¶¶F£ÑpáÂLLLð÷÷æ~Î;‡^¯ÇßߥR‰Z­æêÕ«œ9s†´´4ìíí©Zµª{ÎåÈårÚ·oÏ™3gèÛ·/åÊ•#""‚F @ýúõÙ·o?üð%K–äðáÃ4kÖ,ϵò|8ä¨ÂjccCÿþý©Zµ*—/_ÆÄÄ„¯¿þšbÅŠª¦öë×råÊqùòeÚµkGíÚµqpp0öu^™ZµjáééɱcÇˆŽŽæÛo¿¥B… 8::¢×ë7n»wïæþýû :”òåË{ÈÁ+cbbBÇŽ)]º4gΜ!33“Ÿ~ú ¬¬¬(R¤S§Ne÷îÝddd0iÒ$üüüŒ=là•±µµeÀ€T«V+W®`jjJ=²É*äèÑ£\¹r…öíÛS«V-ìíí=ôg¢R©øí·ß8pà®®®†åÉÉÉÔªU‹9sæ ×ëùý÷ß±±±y®ÂºtéRôz=³gÏF.—3yòdÖ¯_——vvv¬¬¬ ½3³Xµj{öì1¼¥k×®+V N÷Zû/P ¿ÿþ; .ä›o¾!99™š5kÒ°aCš6mŠ———ð² ‚w†PX@ r –––tèÐáï·N: 0Àðþúõë,\¸??¿×>žL&£uëÖÔ¯_Ÿk×®q÷î]¶nÝʈ#ذa+W®•ÁÁ;C(¬@ 8žžžÙŠH5hЀ¸¸8þúë/êÕ«÷Zû:{ö,)))Ô«W*UªP¥J:uêÄÅ‹iÕª[·nå믿6ö) ‚¹± @ ÈY´Z-*• …B\þzâà¡C‡3f QQQÙ–{xxàîîNzzº±OO |@«@ ÁÎÝ»wÙ¼y³áýõë×Y¹r%ƒ 2ô»ròUŸìÞªU+~ÿýwÆŒC¯^½ptt$))‰þù‡¸¸8š6mjìÓo­°¦¦¦’˜˜È;w°··§hÑ¢¨T*lll^Ûb'@ xwÈår\]]¹téãÇ7,755¥oß¾ôìÙ…B››/^̶ @ëÖ­)_¾<...èõzd2%J”`Ö¬YÌœ9“ž={bjjŠN§ÃÄÄ„™3gR°`AcŸ¶@ ø€x+…5""‚™3grèÐ!’’’hÖ¬Ÿ}öË—/§cÇŽÔ©S¥R8q@ Œ••¿þúëK·›={6³gÏ~îúéÓ§g{ߺukš6mÊ¥K—HHHÀÉÉ ___ÌÍÍ}ÊàãµÉôôt~ûí7n߾͸qã8wîqqq”(Q‚âÅ‹3}út (@±bÅŒ}Ž@ ‚wŒ©©)•*U2ö0ÁÎÇìÆÅÅqúôi¾ûî;š7onÈptt¤gÏž8;;sìØ1cŸŸ@ @ ò(oìaÕh4dddàååõÔ:ÜÜÜHJJ2öù @ |ôܹs‡U«V±eËRRRP(T¬X‘âçç÷ÞS¸´Z- ,`Ó¦MÙ–»¸¸Ð©S'Ú´iƒ^¯ç·ß~#,,Œ©S§¾pgΜaĈT¨P©S§¢P( ëbbbX²d ;vì 66™LF­ZµøöÛo)]º´ñ¾@ðF¼±‡ÕÌÌ {{{8ðÔº„„Ο?OŒ}~@ 5aaatïÞ 6зo_~ýõWFŽI||<:tàìÙ³ï} z½žàà`âââøòË/ }úô1Œ!88˜€€€—îoãÆœ:uŠ7bX®Ñh˜7oK–,¡K—.üú믌?žððp¾ûî;îß¿oœ/A ¼1olNsqqá믿fÖ¬Y\¸p•JEBB‹-býúõ”(Q‚Úµkûü@ >ZRSS7nZ­–ÿý///d2z½žvíÚ1pà@† ÂŽ;°¶¶&99KKKBBBˆ‹‹ÃËË OOOÃþt:ܽ{KKKJ–,i(´”ššŠF£A.—„N§ÃÛÛGGGÃç===éÖ­›á}ãÆéܹ3»ví¢bÅŠ¯tN!!!ìß¿Ÿ¾}û²{÷nþý÷_ €\.'44”­[·2lØ0zöìi8×jÕªñÉ'ŸpêÔ)>ýôSc-à5xc…U&“Q»vmÌÌÌØ´içÎC¯×“””DíÚµéÖ­[¶”@  g‰ŒŒdÿþýüøãÙ"ßd2VVVtïÞîÝ»sòäIC»š‚ òÏ?ÿ˜˜ˆ‡‡“'O¦ZµjÈd2víÚÅôéÓ ÇÄÄ„:uê0jÔ(<<>ž^½z‘ÀÑ£GéÞ½;666Èd2d2!!!¤¦¦bii‰\.ÇÃÃùóçãááaì¯D ¼&o¬°FDD0räHúõëÇÂ… }@ ‚''<<œfÍš=s}Ù²e111áêÕ«(P€;vP¼xqV­Z…'N¤OŸ>lݺ•ÔÔT†NçÎùþûï¹sçŸ}öÓ¦Mã—_~áþýûÌ›7yóæ1sæLΟ?O×®]ÙµkíÚµ$ïèo¿ýf8þ¾}ûÐëõtéÒå•ÎG§Ó±~ýzJ—.Ÿ|ò _~ù%aaaøúúâååÅ_|ÁèÑ£9xð Mš4¡R¥J”*UŠråÊ!—¿q6œ@ 0o|×*•J4 çÎC­Vû<@ ò> >>¸¹¹1lØ0"##¹qã{öìÁ‚®]»’’’‚««+_}õ[·n5ì¯D‰4kÖ Š-JÁ‚Q=6®ÈÈH¶nÝjø»uëiiiÜ¿½^ÿÒË“––Æž={hÖ¬ñññ,X'''vïÞ HòiïÞ½Ù´iµk×fÇŽ <˜¶mÛ2zôhý ‚×ä=¬ööö|úé§,]º”ÄÄDJ•*…L&˶MíÚµ±µµ5ö9 @ ä ÒÒ`ÍšGJé?€µ5ܾ k×J˪V…Ö­A­†½{áêUiù·ßBþüÙvW¸pa"""HHHÀÍÍí©Ã%&&¢Óé°¶¶6,{¼‰ƒƒÅ‹'$$„;wîpÿþ}¾øâ Ãú„„RRR oÑ¢E±²²¤°ã'=š•+WfÛ¶m†÷III|ÿý÷ 6Œ¿þú륗gÏž=ÄÇdzhÑ"V¯^V«%>>ž­[·Ò»wo,--±°° aÆ4lØ€ÀÀ@¶lÙœ9sppp`ðàÁÙª ‚ÜÍ+¬)))œ={NÇ8qâÄSÛ”.]Z(¬@ ¯Š­- úôr??éïqÌÌàóÏ_¸;777Ê”)ÃæÍ›:th6EM¯×säÈT*þþþ†åqqqùM§Ó‘––†¹¹9¶¶¶T¬X‘É“'¶MOOG¥Rökbbò”ãŧkK­Zµ8uêÑÑÑ/Ü6--¿ÿþ›ÚµkóÕW_”áëׯ³víZÐjµ 4ˆãÇŠA•,Y’¢E‹ÄÑ£GùöÛoŸ›S+ro¬°ÚÙÙ1xð`233Ÿ»«««±ÏO à£ÅÅÅ…:°bÅ ªU«F­Zµ å½{÷˜ŒƒƒÃK /ݹs‡«W¯òÓO?ѱcGÃòèèhV­ZÅîÝ»i×®ÉÉɬ[·ŽÏ?ÿÜ H§¥¥qçΪT©‚‰‰‰±¿@ð¼±ÂªP(pqq!))‰°°0ÂÃÉÇÛÛ77·l%ÐG£Ñpúôi:Ddd$5¢~ýú†ð‘ððpvìØÁåË—)P íÚµ£P¡B"I^gÐëõDFF²eË®\¹BñâÅiÑ¢ÞÞÞèt:î޽˺u눌Œ¤lÙ²4kÖì™aZAnE§ÓqóæMvíÚÅíÛ·©P¡mÚ´ÁÑѵZÍåË—Ù°aZ­–*UªÐ¸qãlá†An'KV9xð ÑÑÑ4nܘºuëf“U¶mÛÆÕ«W)T¨mÛ¶¥`Á‚¹RV155åÛo¿%44”®]»Ò¨Q#Š/΃8xð … bÖ¬Yo$ÀÒ¥K ÆÞÞžµk×Ò¡CJ•*EéÒ¥Y½z5]ºt¡mÛ¶DDD°~ýzfΜùÊã9}ú476¼ŒŒD¥R±`Áœ8wî\¶m*T¨€““qqqOrqq¡aÆlß¾¡C‡Ò·o_ÆǶmÛ¨\¹2:t­VK×®]E80R¤ä±cÇ8pà2™ŒöíÛS®\9LMMÑétܹs‡uëÖE¹råhÚ´©UFãV€ÐÐP~ýõWNœ8All, =‹/ÎÀ©Q£ÆSïóçÏ3qâDêÔ©CÉ’%ùõ×_IIIá³Ï>C¡P0yòdÂÃÃiݺ5gΜaüøñL›6MÜ$‚-Z°}ûvƒ—tРA4iÒ„|ùòeÛ~üøñlÙ²…;wîн{wºtébž;w.+W®dß¾}8::²hÑ"jÕª@‹-¨Q£fffXYY1xð`Š+†\.§S§N”)S&Û±ÌÌÌ(]º4åÊ•C¯×Ó±cGJ•*õÔ9xzzbnnÎ’%Kž™nÖ¯_?Ο?™™ß~û-ÅŠcß¾}ìÛ·7nLóæÍŸ¹ï‘¿ÿþ›M›6Ñ®];bcc6l3fÌ R¥JDEE1bÄòåËGÅŠÙ²e L:ÕØÃ|¤¼±ÂšššÊüùó¹{÷.?üð 4@&“qÿþ}Ö®]˘1cX¸p!%J”0|&..Ž ðé§ŸòÕW_P @vîÜI‹-¸zõ*AAAL:•råÊѺuk:wîÌž={èÚµ«±¯•@ðJìÙ³‡Û·oóÏ?ÿ`aaAݺu™:u*çÎãÖ­[èt:ÆŽ‹““¥J•bðàÁP®\9c] x)*•Š+V?~&Mš„\.§jÕªüüóÏܹs‡¿þú‹âÅ‹3zôhd2...¬\¹’ºuëR°`Ac_ x)±±±,\¸Ï>ûÌ`hñòòbÏž=4oÞœK—.qûöm¦OŸŽŸŸ-[¶¤K—.ìÝ»—Ï_’OjLlmmiժ͛7G§Ó!“ÉP(ÏÌ7­Q£7F¯×£P(²9 *Ä?ü€V«E&“e«>üä¹y6ohµjÕ¨V­ÚsÇ(“ɨZµ*U«V}íó+S¦L6e¸yóæ4mÚÔp®r¹¤aÆY¥^½z 2 ‚‚‚ððð páÂÈd2¬¬¬ð÷÷Ï3²ŠB¡ÀÄÄ¥RùLe5K‰U*•˜˜˜5 W¯^%**Êh×SûˆˆˆàòåËÃÈ›òÆ «¹¹9NNNlß¾ÔÔTôz=z½Þ`I¿téÅ‹ês†þù‡† ÒµkW8Àܹs_(ˆ¿¨1HM¢íííE½À€L&ÃÖÖÖàÉÌi6mÚdèõ&—Ë™4iÏÝ>«Ýó055ÅÑÑQÌq:ŽÔÔT233±³³ÃÒÒÒ(s|íÚµ”.]š>}úðàÁ¦L™ò\¥T§Ó½ôÇÊÊÊ {{{£œ‹ ÷âää”­PN¡V«Y¿~=7¦k×®ìÛ·ùóç¿Ð0þ"YE&“ammm´âc©©©ÄÄÄ<ó/55NGbb"¶¶¶ôêÕK(¬9„R©ÄÉÉÉ(žêÛ·osòäIzôèA“&M˜?>6lxág^$«Èd2ìììŒr¿ r/æææïä·ýï'''ºvíÊôéÓ9{ö,U«V5ä°;vŒ%JP½zõ§¨T2räHCÒ»««+ýû÷çÛo¿}î±^Ö+ËÜÜœB… ¼V‚›ÔÔT4 ùòå#_¾|F jܸ1ýû÷G¡PP¶lYúöíËž»ýËðÖÖÖÏŒf|<èt:ÂÂÂØ¹s'ÈårJ—.J¥2Êx¾úê+>ýôSüýýiÕªÕs=L …â¥Ïg (`”sä^Š)Âõë×sü¸&&&Œ9___@’y ôV²Š«««Ñ H.X°€E‹=s]÷îÝéÑ£}ûö¥OŸ>Ô«WÏ(cü133ÃÛÛ›øøø?v5jùóçG§Ó‘’’ÂÆ_X ïE²ŠB¡ÀËËë™±/ööö(P੨Û×åV¥RIóæÍ±²²bÛ¶mlܸ­V‹½½=­[·¦K—.†Ð‚,,--±²²ÂÇÇǰÌÃÃ¥RIbb"ùòåãÞ½{¤¤¤`mmZ­&44T11‰‰‰†0,B}#""ÈÌÌÄÉÉ kkk´Z- „„„pòäIŽ?ŽZ­ÆÎÎ:tè£cvvv6TD°±±ÁÓÓ“èèh<<<ˆG­VcbbB||>ÞPŒ)..Ž„„üýý=tÁGÊ[Å ˜˜˜Ð°aC*W®Œ©©)èõzC¦'quuÅÕÕ•óçÏ*Àݸq4ð *°iÓ&BBB(Uªœ;wŽN:û: r˜””¶mÛÆ–-[(_¾<;wÆÅÅ…åË—sàÀlllP(-Z”ððpRSS111¡jÕªL›6 www‚‚‚8vìXŽ{Xýüü¸pá;vD©TMpp0M›6¥X±blÙ²…ÔÔTìíí¹ÿ>¡¡¡T©RÅØ—\ðž¹páaaaT¬X®\¹Â_ýEzz:*• T*jµšR¥JñÏ?ÿ°zõjJ—.ÍÉ“'©Q£óçÏÇÁÁÁ°Ï2eʰeË– '377ÇÇLJ³gÏRºti@Ê?MHH þüT®\™ãÇÓºuk°°° hÑ¢Æþ ‚WÂÝÝ'''.\¸`x6"—˱··7´ù Á××—ôôtΟ?Ï_|aì¡¿++«çV£×jµ´lÙÒð|IMMåâÅ‹„……Q­Z5¬¬¬ËåÃSff&G%,, J–,‰©©©Á¨lkk˃ÀÎÎŽúõë‹0ã\DñâÅÙ¹s'÷îÝ£H‘"hµZpppÀÒÒ’ªU«²cÇÒÒÒ°µµ%,,Œû÷ïS©R%c]ð‘òVRÎýû÷™5kñññ,^¼-ZÄÎ;ùꫯhÙ²¥!a pá´mÛ–É“'ʪïܹ“/¿ü)V¬³fÍ¢}ûöœ8qkkkj×®mìë$x¨T*N:Å®]»(X° z½ž .àääĨQ£¸|ù2ƒF«ÕR¶lY¦M›†ƒƒ±±±œqqqØÛÛ³gÏ5jDÙ²e133cÊ”),X°Ö­[GãÆ³br3ÞÞÞ´jÕŠI“&Ñ¢E 4 »víâÿûvvv”-[–"EŠ0{ölÚµkDZcǰµµ5ô"Í‹ÄÅÅÑ»wo D5øî»ï8uêÎÎÎÌŸ?;;;*UªÄرc¹ÿ>Ç'88;;;fΜI:u˜>}:*•Š>}úP¤HîܹCZZ÷ïß§Y³fŒ?Þh9¼‚ìT«VM›61zôhZ´hÁƒ8pàC†  ~ýúlß¾Ù³gS¡BÖ¯_O™2e(Y²¤±‡.øHycé'--… rÿþ}ºuë†\.G&“Q¿~}™={6>>>ÙB•J%_~ù%ÖÖÖœ8q€ž={Ò¨Q#C~ÓÈ‘#ùçŸX¿~=E‹å§Ÿ~!*))),\¸:uꄵµ5³gÏ& €N:!—ˉ§gÏžT¨P…B¯¯/uêÔ!<<œ²eË„v;;»\™×Y¢D &L˜À¦M›Ø¿?~~~´iÓôz=cÇŽeõêÕlܸ‘ªU«Ò²eKQLé!99™%K–päÈt:}úôÁÃÃ9sæ0fÌüüü Ѝ———¡":`ÍÊÂÊÊ ???üüüŒ}ZÙËå4jÔöìÙCpp07æÓO?ÅÎÎŽŠ+2tèP6lØ€J¥¢C‡´jÕJ´”ä”J%ݺuÃÎÎŽãÇ#—ËéÝ»7 40áøáƒ¬R¬X1ÆŒóÔ=œÛ¸uëß|óM¶efffôèÑWWWâããQ©T8p€£G2oÞùä.\¸@pp0Ó§OÇÅÅ…èèhRSSñõõ ÒAžA£ÑðÔrôz= µô©Y³&ÿý7ÁÁÁxyyqûöm._¾lèîP¡B¶oßN“&M°²²âÖ­[ >œ>}ú¶7z½Fcøÿ¶¼±Â*—Ë©W¯EŠaß¾}\½z•ˆˆ¼½½éÚµ+õë×!açÏŸgæÌ™Ì˜1ƒC‡ѽ{wCQ¤.]º`aaAÁ‚iܸ±±‡*¼6:Žƒrüøq–.]JXXÿþû/¶¶¶LŸ>ÝÐîAD‚¼ÈÅ‹ŸÙB­I“& 4Èð¾K—.lܸ‘®]»R²dIîß¿‹‹‹!,xÀ€|ñÅtèÐbÅŠqüøqŠ+FݺuŸ› &>ÒÒÒØ¶m7oÞD¥Rq÷î]:wîüVû|-…õþýûœ>}šbÅŠáéé‰ à믿&-- N‡©©é ãáy‡´´4bc¥J‘‘‘Ìœ9“ž={R¹reüýý9zô(ÁÁÁeU ÈKèõzGÁcèõz’““ùùçŸINNfòäÉ-ZTä¦ò4†äädd2 …‚dziÓ&ÆŒchM#Œ‹Z­F­V£ÓéHHH`êÔ©Èd2L\\7oÞÄÓÓ“.]º?~är9qqqÆvž'!!Q£Fȯ¿þJ›6m =½^Ï©S§èÛ·/%K–䯿þ"**Š~ýú1wî\jÖ¬ HßÝ¢E‹X¹r%¿üò J¥’þýûóË/¿P»vmcŸâ{G¯×ÅŠ+8þ<*•   ¢vÌœ9“)S¦P®\¹\§¼–ÂzûömN:E¿~ýhÓ¦ œ:uŠúõëÓ A _~ù%‡æäÉ“BaÍhµZ®^½ÊíÛ·‰ˆˆàäÉ“”+WŽÑ£Gçº )¼.†¿ÿþ›Å‹ãåå…N§ÃÜÜœ9sæ=„E HÂ~hh(K–,!==„„bccùâ‹/hÙ²¥!Ÿ¼AƒÆêKjj*™™™ìرƒ–-[¢©Ôj5Û·oçáÇäË—½^V«%..ÎP 433“3fð÷ß3{ölªV­JPPñññ†m>tnß¾ÍèÑ£©Y³&³fÍÂÝÝ]ÔùäinÞ¼É;wpvvF¡P0eʺwïNÅŠseˆúk)¬ Èd²l} ### £wïÞ “\.ÇÜÜœ¨¨(cŸŸ8|ø0K–,¡FØÚÚ2tèPJ”(!”UÁÁŋٺu+ .ÄÍÍääd¬­­…²*ä0Ü¿ŸƒrìØ1Š+FãÆ‰ŒŒäï¿ÿ¦nݺ4lع\ŽR©ÄÃÃ#W F:FCõêÕ9yò$ééé†0¿””Nž E-##ƒ¸¸8T*AAAüñÇ´oßžÖ­[‹‚}‚ÛÃêÒ¥K¤¦¦R¾|ycŸ‹à³`ÁFŽI… Œ=àrïÞ=~ùå¾ýö[J”(L&û(ó©cÁœ9sˆˆˆÀßߟÁƒÊš5kP«ÕüôÓO+VÌØÃÌh4ðð¡ôÀÞý°±‘ÖËdÒ_VO{{HLWW°²Ê¾ß"EŠ*/7iÒ€+W®P¸pa‚‚‚²m¯×ë™9s&‹/féÒ¥²š””ÄÌ™3 ÅÌÌ www† BåÊ•=4àˆŽŽ&99 .\¸ÀŸþÉÈ‘#ñ÷÷7öÐ^™×RX=<<011áÌ™3(P€ÌÌLöíÛGÙ²e±¶¶6lÉÝ»wùüóÏ}~QQQceeEjj*¿þú+½zõ¢\¹rÆš@ðÖèt:Nž<ÉÑ£G‰åáÇ´jÕŠêÕ«çZ« @ð¡‘””Dtt4fffèõzn޼ɟþI:u2dNNNÈårÊ•+GÓ¦MÑjµ¢èÙk–6@Vún­Zpôè£ÿ~~’bji r9\»öhÛãÇá³Ïà±`8\\\¨S§›7o¦AƒÈårvìØaøŽWX5 ¿ÿþ;.\@¥R}° ~}||Ðétüþû︹¹1uêTlmm177¿/‚<‰V«åâÅ‹Œ?…BB¡ÀÁÁ™3g’?~cïµx­'——ÕªUcáÂ…’””ÄÕ«W4h …‚ääd.]ºÄü››+V4öù}Tddd0gΰ´´$))‰¦M›B°‚¼Frrr¶ u·oßfÊ”) 8+++òçÏO¾|ùDÁ Èjƒ¶lÙ2ôz=ÎÎÎÄÄÄ`ffFß¾}©V­ÚSŸ1555ö°ó¶¶0xpöegÿÿ"ž·\.§E‹ôë×{÷îaeeÅéÓ§7nû÷ï϶mBB—.]bÕªU,_¾œŸ~ú‰5kÖàááaìËóVÄÆÆÒEÂÃÃ7n–––888°eËbbbh×®;v¡¿‚ÌöÀÐétDFF‰½½=^^^ÂÒõ†Y³fQ±bEš4iÂ’%K˜;w.'NÄÓÓÓØÃ{7dd€¹ù‹·¹sGª*ѯ¬X‘+V½^O`` ùóçÇÎΔ±{÷î‘’’‚»»;...®ü âÔ©SÌ;gggŽ?αcÇ:tè› Ëz=¨Õ`b"U(É+Ü¿^^ %­åÂy’žžNPP¥K—6<«U*wîÜA§Ó‘/_>ìííEX.G§Ó‘˜˜È½{÷ˆçÖ­[\¿~{÷îQ·n]V®\‰µµõGù=&$$NÉ’%³]¯,YÅÁÁOOÏ<#«´jÕŠ®]»âààÀܹs_º½B¡à‹/¾àêÕ«|÷Ýwx{{RKœK—.e;o¥R‰¯¯¯Qááá 2„ôôt5jdhE3lØ0Ê—/L&£páÂF_n$<<œŒŒŒl×EÈ*¹­VË‘#GÈÌ̤@DEE±ÿ~æÌ™ƒ åË—Çßßÿƒz^¿–ª×ëÙ¹s'Ó¦MÃÓÓggg6oÞÌ•+WX¶lY¶\³—¡V«Y¹r%§NbåÊ•†å‡â?þ ::kkk:uêDëÖ­?|oá Ðét¨T*är9 …‚½{÷ËÈ‘#±··gÊ”)„††âååõæÑj%aØØ“[¯‡ÈHX¶ † y±Ò%KBéÒðí·Æ÷3OEÏíÛ·éß¿?Ó¦M£bÅŠ¨T*6nÜȺuëHOOÇÍÍîÝ»S«V-c7× ÕjY±b­ZµÂÙÙ¹\N5¨R¥Ê›þHO‡' zõÜá±Ü¼j׆— u BH,] Ó§C. »Ôëõìß¿Ÿ3f°k×.,,,HLLdÉ’%8p™LFøþûï…€˜KÑh4ÄÄİvíZÎ;‡••îîîx{{óùçŸãé鉻»{žQÆÞ5™™™¬X±‚óçÏó矖µl¤¥¥ñ믿¢P(èׯVVVŒ7ޤ¤$,--?Z£ËËX±b»ví¢]»v†eçÎcÁ‚Œ7Ž5j°`ÁÆϺuë>jYÅØh4V¯^Íž={˜7onnnÆRŽñZ¾ý´´4är9µjÕ2X(^¼8ÞÞÞÜ»wï•ö¡×ë¹{÷.+V¬ÀÏÏ/Ûº³gÏbooO»ví°°° fÍš”(Q‚£YuÜ?B´Z-»wï¦I“&tïÞV­Z1lذwú{ð ¤$¾ÂÃáߥðÆyó >þÙÛéõðÏ?RºÎáÔ)I }ö…‘„øÇQ©àÏ?aΈŽ~?çòŠhµZV­ZõTNÌÑ£G)[¶,5kÖÄ‚6mÚ`iiÉÙ³g:^c’u­Ž?NJJ ÎÎÎ >üÝz*ÒÓ!3S ~_¨ÕÏŸ¯OÒ®´ícBäS$&Jý)lm¡jÕ\a„yœøøx.\H‰% ˲”š4i‚¯¯/ÎÎÎtêÔ‰°°0nß¾mì! <';vì ÿþìÛ·† 2sæLzôè!”ÕÇÐëõܹs‡U«VQºtélëΜ9ƒ““mÛ¶Å‚ZµjQ¬X1Ž;fìatèõz"""ظq#ýúõãîÝ» 4«ÿšÐÊd2ìììDÞõ3Ðëõœ?žÓ§Ogs$«øûûS½zu,,,h×®fffœ;wÎØÃþègÔ¨QôêÕ‹N:qáÂ&OžüÑ=¯_[’ËåÙ*Ä™ššbnnŽJ¥z¥Ïët:/^LÉ’%qpp`Æ †u8::ò`MMM)UªƾNF#))‰³gÏòóÏ?ãåå•-‡æâä$5r{×e¯5øåðõ•:šÇÇÃøñ0j”tÌÇyøPÊÕëÛ¬­¡R%xžEôÆ ˆ‰:u-³´„#`ölXµ  z?×ê8wîgÏžeìØ±ìڵ˰üêÕ«øûû >nnnäË—Ë—/Ó°aC£×˜Ü»w}ûö±bÅŠ÷g¹U*¡J•÷ë]ýë/I íØQR2ŸEZšÍP¿>Œ))¹ÏãØ1é~¨Qºv}ã~Cþý÷_233éСƒ¡Â¨N§ãÚµk|ùå—†íJ”(AFFaaa”)SÆØÃþ¨ILLdñâÅ3jÔ¨÷÷{ò¦h4RDA.È“Ójµ,Z´ˆÒ¥KceeÅÖ­[ ë®_¿Ž³³³Á»annN©R¥¸té’±‡ýÑqéÒ%&MšDÅŠ0`¥K—þ`{ƾk"##™;w.ݺucóæÍÙÖ]½z•Ê•+cþ_ZVVš«W¯Ò Acý£!22’ï¿ÿž6mÚàïïµµ5®®®e.qŽžqVYñèèh:wîüÔúääd …Á³’Õà6**ê…ûMIIáòåËdddääé¼wt:7n¤|ùòOY¿Þ9µkCBÂË·S«%oÕŸÂ… /÷(]¼(}æ³Ï$%ô»ï¤Ý;wžÞÖÜ\ óupdêÔ©ôêÕ‹¡C‡zOæ%ÒÒÒ¸páiii9z\µZÍ¢E‹ðòò¢Îã†ÿÿHLLÄÜÜ<›¬baañÂ9®Ñh¸~ý:±±±9{?PRRR˜:u*+V¤}ûö-Zww÷<§¬FFFrõêU4Y²ÍòÚw¶V«åúõë)==¤¤$BBB8|øp¶m+T¨-$200+V0aÂCbð«ð2aL&“abbòÁ%ÇÄİgÏfΜùf¹Z­fû²x|<˜™=Ý©<%ERÿë·HÂvT”´lìXèÞÚ´yþ¾óç—ý5Çõyssd¦¦(ÿ3€ä$jµš?þøƒ"EŠP·nÝWV$²”·ç!—Ë?ˆ9~ÿþ}ˆ cÇŽÅÌÌŒ3gÎ0uêÔ÷{nr¹dY² u$0›˜HÞÿ,®]“¶½{WR0GŽ„ç…'‡„H¡îÕ«KóóÇáúõgo ;vÀÌ™O{~üQRŽ“æ»R ÞÞVµ¦N…1c`ÍP*‘éõx<ˆÏ‰˜|úiN}…ÄÅűpáBZ·nM™2e8sæÌK?£×ë_:Ç Å1ÇM||<ë×¯çØ±c899ѰaC¬­­ÑëõX[[ãëëküž©™™RJ@€ß®d0-\Xª[%7Ü»Gþ{÷¸’Ã}?¯_¿ÎÊ•+™8qâk‹_ô¼—Éd(Š<§PåVRSS™1c 4 nݺy6?Õò«N§ãÀܸqƒiÓ¦½VúÍËžãJ¥2Ï)T¹‘ððpæÌ™ƒµµ5Ý»wÏÓ×ô]ɯ¯õäÌzà®\¹ÒðpÐëõdffòðáçbÛ—.]šMaýçŸÈÌÌdݺu¬_¿ž7n͘1cøâ‹/055E§Ó¡ÕjQ(èt:222^§meeEÉ’%ód3ë' åÞ½{XYYqæÌ|||Þ<_õÜ9Ii}Y¦C‡¤pÜâÅ%A"ëáuàìÝ 3f<ªÖ»{·6\­šT4&Ëþ,23yžG¾|°h‘TuØ0©uÇã+–]aNJ’„ýnÝÀ¹„ä]M$»ÂŠtƒx{{–£7ú¥K—8vì¥K—füøñoÑòåË E&“¡ÕjÑëõÈd2Ôj5jµú¥{{û§ò¨òjµšßÿ¦M›RªT)ÆŒƒJ¥¢}ûöoA ÑÀ­[RÞ— àóçÃ'Ÿ@Ñ¢på ”*%-_°@š_ŸþhÛ˜IQ,THªâÛ½;ôî OVGÔj%Ol–™™¿¿´.&/ˆ`i ß/µ©y’¬{¼páGaðmÚ>>888û²æIÔj5×®]cïÞ½œ={–êÕ«Ó³gOC>v^ÅÅÅ…âÅ‹¿4Êêe¼–ÂjooÏСC_9táÉêU*TÈ*fjjŠL&3To+Q¢W®\!&&777Ôj57oÞ¤P¡B9tYK\\?þø#èõzbbbøæñJ¸¯KX˜äªZõÅ9A÷îIaº’0Ÿåì, ÝÉɒš’"…(Uî-Uê‘àÿ𡤠7o.y‡ÂÂ`Ý:©5Í‹(VLòݹóȪþ"ö퓼®]»Â=à6p È%©XŽŽŽ´jÕŠÌÿBB³V333ÌÌÌ(]º4¡¡¡¨T*ÌÍÍ‰ŽŽ&22’ºuë{èï“'Orûöm €‹‹ 666¬^½š-Z¼™å-) ~þYª´û"!0-M2¾|ù%4m*E€Ú¾gÏÓ•±Û¶•æ¾…ôï/y\Ÿõ|挴Ɵ®d™ “&ÁO?=ÊÕ¶²’ò²_„B!µuŠŠ‚'ó=}|$oî?BÁ‚è--ÉpsËÑvT… ¢yóæ†÷Y9NYm3|}} ¦víÚ£P(pqqɱ1~lèt:~ûí7nܸÁøñã)Z´¨ñ=NHi¶¶RÎvx¸ö›fj*(³Œ”2ÙÓ5 ”J£«T©R¶6}&&&†Ö0r¹œ’%KHll,®®®¨T*‚‚‚>Y%§ÉÌÌdÛ¶mlÞ¼kkk ,H‡¨\¹r®l#”Û155¥~ýú„‡‡–eyÿ-,,ÉdOÉ*QQQDEE}´µ6Þ7,\¸ÐÐP4hÀœ9sððð0ö°r¯õK`ffFÅŠ ï“““ '-- 333 “žE«V­hÕª•áý²eˈ‹‹cذaÅuñâÅÐ!!’gÇÆFšçY!M’"û¤@ü¤Ð™e”iþ›šJF//Iy|V¡(ssiýöí’÷vß>¨\ùå}WA25m*y·Ï2^9¤°R¥JÙ~Ξ=ËÎ;yRzý®ñò‚–-áÒ%ðÿ¯hHùw˜7åÉfÍYUµ r¹œòåËS§NÆ‹‹ >䫯¾ú ûšéõzRRR8xð ‹-¢Y³f”/ÿèËÊJ1xcT*)÷ùÈIi|Fá@ ;ÿöÛ¬ƒ>j‰¤TJ÷…N'-S($å6=žW¦jU)w»X1éØÏC&ƒF`Ó&©7ðòåð˜’÷B¼½¥(†'½Æ¹$÷íÉ9®P( …Ä ­[·æâÅ‹ < âââøá‡DÖ·@¯×“œœÌÞ½{¹qãwïÞE«ÕR´hQÔj5wîÜaæÌ™ÆóbëtÒœ—ɤù[¬˜¤ ¾JÔL.äUd•N:±lÙ2öìÙCDD-Z´È}U—ó z½NGDD&L@¡P0nÜ8J”(aü¨„'Ÿá y]³" @2(׬Y“±cÇf“UÞkqÄ­VË;w˜>}:^^^̘1ƒ"EŠ{X¹™þeÔOÀرc9uêþþþT­ZwwwÒÓÓ¹téÄÜÜœŸþ™R¥J½‘• 44”ÀÀ@¼½½)öÏ›F£aË–-T«VíýWÒ}ODFF2qâDjÔ¨A§NÞÍNOž” ¼L˜ðêŸÑë¥ü¸”)L·Þoâ¯CáüRØ®‡ÇÓ!”“”$YÔ³þ¿²Œ‡&ð+` Œ{ö¦‡ÆÆÆ&›¢”¸rå >¤|ùò/2ãããÙ²e ݺu3ö°_™¨¨(¶lÙ‘#GðõõåÛo¿}?tÛ¶IÅÀF~5¥îï¿%/ФIRñ¥Ã‡%¥²{w˜;WR~kËò—.I¡ó_|ñjã›9Sòîöìùê¡»ͳC$Ÿ@­V³eËjÖ¬ùÂè–œF­VsîÜ9T**TÈ^ù,BCC9{ö,íÛ·7öÐs)))¬_¿ž­[·R®\9Ê–-KÙ²eIMM%,,ŒØØX5j”óʪ^/=磢¤{°uk)µäÇÖ­[ùßÿþ—³ç÷ „„„pãÆ Š)BÑ¢E_¸mRRÛ¶mãóÇóåÙHOOçܹsüûï¿„††ÒµkW7nüÁ‡ý†„„pþüy>ùäcå)._¾Lxx8*Txaþ*@@@*•Š*/2æ~ädddpîÜ9öíÛÇ¥K—èÚµk®üÞß5/^$11ñ­Òß^Ëd¯Ó騴içÎcĈ4lØ+++ƒRÚ²eKZµjÅÏ?ÿÌìÙ³™1cޝ÷ xªȇBZZ‰‰‰„††rýúu®_¿ÎíÛ·)S¦ -Z´xwºqãQhcFÆósnÜ”Û/¿”„ãâÅá×_¥ÂŽp X· T„Í›¥bG/Œ³”’÷i…ËêÓè<iX¦L™2DR£Ñ°wï^þüóOÊ—/ϸqã(P À»¯Œ©ÓIóÚÒRòtêõB}ŸÜîî]iÎf.ðö–>—åÁtu…+ }{¸yzõzñ±Ë–}TeøUhÙRÊc}ã].ñ¦¾)&&&T{×=?2t:ׯ_ç—_~ÁÕÕ•±cÇâëë›ÍËäëëkÌÂÆÒïG±bÏÎóþÀ)X° ÿË'¼9Y“&M"==æÍ›ãçç—g~~~ø=Y SðF$&&2wî\>|HýúõéÕ«W®24çv^K*ŠŽŽfË–-tîÜ™–-[>%„*•JÊ—/ϨQ£øßÿþÇ­[·„¥å .\È¡C‡([¶,ùóç§mÛ¶”.]ú݇„šš>j‰‘ŽX±¢ä™LK{”ïwã†T½ñqaº`AhØÉ hâ+U¾_ª²j 2$àq_` r®«‡àDGG³bÅ FŽIÙ²eßß""¤|ÒQ£¤0õÇrãIHxÔ¦&=]2Àôë÷(OºR%É›µMþüÒý#…ñ¾Já”× MËjÇ$¼"*•аbÅ :wîœ-ŸÒè\¹"Í__øê+éO x ®]»Æ„ hÚ´):u2~Û%à£Ñh˜7o)))Ìš5ËP¬Pðê¼–ÂúðáC4 •*Uz¡ÇÄÓÓoooÎ;'ÖÇÈ “›4iÒû·X}ú©Ô_$oÒ‘#’Âúï¿R¨ð¤I’g)*J¨ÏÙÉ*ô¢\>+«GН± 2’þÎ;lذèèhÆŽûÒPÓ÷‚N'pôz陟¥@= sæ¼^ª‰@ð±±±lß¾’““‰ŠŠ¢K—.4oÞ\ô©|¤§§f(Ò¶uëV"""˜rôz=ÇŽÃÑÑ‘â9Û²eö÷R该¥- ÑH}íì¤bG/³hffJőʔyzßÁ{ ==U«V±gÏ*UªDÁ‚iÒ¤ ^^^ÙjC…`ÌÉóxuçQ£$c¨h¹ xEÒÓÓ A­V“‘‘Á¯¿þJ•*UèÑ£‡ð4 >8ÒÒÒX´hQQQüòË/ØÚÚ¢R©055ÅêÉH/ÁkñZ «··7...†ª¼Ï«úyøða)—•C) &&†°°0*W®üþvü¸$´g)ÆJeö‚Y9z©©pëÖ£\×'IêñHA4&wt$OkV·ÿ^ï*^ÆäÇ‹Z­fÏž=4mÚôíúãétpèTmôEÅLže¥|¼…†R =zHÕ®5z¹€­ÑH^%ÑcNC,_¾œ#GŽäÎñ^^Òß“ˆÜBÁkòÛo¿qüøq¼¼¼puu¥C‡4kÖìýGá9€N§cß¾}lÙ²­VKRR–––üüóφ¡¨¾^Ka577§oß¾ 2„Q£Fñå—_âåå…‰‰ :Ž„„vïÞÍš5køòË/ñöö6öùÔÔT~ûí7Ú·oO¡B…¸u뎎Žo ÓÁ‰’üy•”“’ V­ïG«•òý‚‚ž­°ª€À>à“½èS )Êz$ï*Hy«Y ëÀhˆ(‹çرc,Y²___ *DhhèÛ·ºq~û ~þùùÛh4pá‚êû¢|'??øå—§óWŸ…¥¥T[„: Þ3éééüõ×_œ9s†3fä¼²š‘!Õ4Ðé iSiÙúõR~jx¸”Ÿ* … Þ’„„–,YBDD .ÄÎι\nøû¨¸tIrT«&¢>0n޼ɲeË9r$z½ÞÐû£êW›’"9ÈÞ³Aóµ³Ûýýýùᇘ={6ƒ&þü(•Jôz=ñññDEEÑ®];ºté‚Ùãy”gÏžeÅŠܼy“)S¦pæÌªT©òæVEµ>”Ús„…Á¢E0y²²õäð“OÀÍíåûŒŠz”Û—ÕäqÅp6Pí¿×9ÉQ :ÂõH‚íªgÕ«Jl‘ZïX¯}$ÇÑëõ¬_¿žzõêaeeÅ™3ghРÁµ±2 ³fI!ëžžRUêÌL)"@&“þôz)*`ɘ?ÿÅû“Ë_Ü‚éIÚ¶}~>·@ðÐét,\¸S§Ndz-q¢£¥”‘,Ê–ggÉ$š× Þ½^F£áÖ­[,]ºKKK~øá‡·û]È«dµY“ɤ>ßR ¶÷&È1RSS™?>-[¶¤téÒï?Ý/·¡×KE-gÌ þU«f/àúŽym…U©TÒ¬Y3ªV­Ê‰'8wîiii( êÖ­KÆ )ü¢¼È€ÄÄD/^ÌÒ¥K dРAÄÄÄðûï¿¿Y^’V+U÷=xPªîÛ¹³äeZ»† y¤°jµ’õüU<Û …Tt)-Mz¿)4KV±¾L¼9É$å3KaÕ€–HU‹³(ùß{Rø² Ç8pàééétìØsss>ýôô²²’Š{•,)½ON–r¯}}¡S'ÉûyçÌž-=ßuHÙ«y‚WD¯×N@@fffXXX°mÛ6ôz=‹-zÿ•<ÒCll¤¼Óúõ¥×:<US¬Ø£¶OÁ ÑhX±bGŽà“O>ùøBõzÉtã†Ôþ©R%¨\YúM;p@’Ñ>6¥æ%##ƒ àææÆ_|aìá‡ädøþ{IFËÌ”ô“Ñ£ßÛáÞ¸~¸ƒƒ-Z´ E‹O­KJJbþüùtïÞWלŒ%5>z½ž£Gbccƒ¿¿?eÊ”!55•[·náééùf; •Ö1c¤"2 ññ’²ªVK!^H•Sûö•úJ¾ŒÇô•@o)¬ÁÀ~ ’™©·Òâþ;æãQi.H^Ö‹@VÔé$ÏjrGžíGB\\«V­bРAï®hFf¦4g³”U^O™"ýøk4Ò2WW6ìùáðA. «…Ùüùó)V¬r¹œøøx¼¼¼øúë¯ß}ßí¨(IxP«¥¿2e$%51QúýȪLonþüšÁ¢V«Y»v-'Nœ`ðàÁ/^üÃ/¨¤ÓI}¾³<©––’>Þ0Ï322P*•L›6ÍØÃz¿$'Kó\.—Zœ=®[h4Ь™ÔáömI'y¼—»'--åË—óÉ'Ÿ|t «N§ã¯¿þ¢ÿþ(  ß|ó ÉÉÉož·aa!…I>ªenYádII°u«”·ÚªÕ«)«O’ <>¼ ¤–19]ÈH…‚4ûo™ (ƒÔsõþcÛæCòë€ë@­W?ŒàÍ9xð ¶¶¶”|\¹|Ôj)¼÷Ë/áÉÖEŠdŸ÷66"lW« cùòå\¿~áÇS¦L™÷*–’"õJ-XPÊ=7Oê;üÍ7Òzgg©B¶@ðHOO'&&½^ϦM›xøð!3fÌÀáñ2IIðçŸÒ½0t¨tÏ5i"ý=Ž¥¥ˆ`Èã¨ÕjæÍ›‡Z­fìØ±äË—‹¡ÝŽ’Ã,3†Ôâ ÀÑQJA)ýê=·2æžw@ÖƒàÂ… ØÛÛãïïŸm›[JN~”ßð,eÓÝýŹxŽŽRKŽ·ŠÌ€kHU³ÞER ‘Âqs ’·ôñß<-pðýïàýßz'À>‡Æ÷¢Óé8vìgÏž%$$„ððp¾ÿþû×kð®ÕJÿŸ5GCB¤6L}úûT‚7"«†Ã¿ÿþËÞ½{©Q£³fÍz·9ª*•/“IÊêüùÒë¡C¥c¿þ*mc¬Þ­‚NÇ‘#GX¸p!éééèõz*UªÄðáÃ?e5&F2šÚÚB—.RHï_DB‚ähøÐ=Ï)))DFFbii‰©©)+W®$99™‘#G~¸óüÐ! ”æøçŸK΂Ï>“Zýedd/`™™)Eð¸ü—§çì,E¾G„ÂúX´hxxx˜˜HŸ>}^¯Œu@tïÓ§K…_'1Q*¶ô"o–LövÊj&ð©mL©€5’2ñ/Þ}àñHiÍÇ |l™)ì׈Bª"ãQŠÿÆ/x/DGG3cÆ ¾øâ 5jDAssì||^o'—/ÃéÓðé§ÒƒíÉu%JH!ŒAäöíÛL˜0¢E‹2eÊ ¼ëõÔTX¼Xº\\`éR)Gõ§Ÿ=û-,DÛÁ{çüùó,X°€aÆQ¡Bãö Îi4©ñÈ‘RdÓ¿e/båJ©¾HóæÆ> ÁKÐh4,X°€'NàææFjj*æææÌœ9óݧsƒŒ ©CÈÇ’‘³IÉ)ý†4oþ¨­™L&)ªOê4ׯêURÁ%B†ßs¡°¾:Ž;wrõêUÆo˜È¯»!“IÊj•*O¯Û¶MòÀ¾«ðËgƒTy÷ñð_`˜")‘ï px<_=)Ö É³ª@ÊU=´C*ƤC a~Üiùþ.ÏÇLff&Ë–-£]»v´oß^òªNž,åI¿Ž'ÇÛN’>7r$<P¯Ô©cìS^­VË… ˜={6:t E‹˜¾IJÆ“$$H¹qööR®Ü²eRžª‹‹äeýâ ÉÀ#Âã9„N§ãòåËÌŸ?Ÿ‘#GR®\¹Ü­¬fy>_EKK“ úyy=ªò,>”ä±7©Gâî.™¹•J…©©©a>_¹r…sçÎÔ´´4¬­­óf«š´4é·ãáCÉÈ’?¿ôzÉ(\X*˜”•®Ø±ã‹÷õ×_’žâã#U¾~28–‚€IDAT‚èâEIá}Oí_KaÕh4DDD™™ùÂí²Âc?t¢££Y±b#GŽ|»Ð¯š5³¿?~\*Œ¡Tž=RÜøû$©ÏjøcËTHVÀP#U ~—$ …!?N&àøßÿØÿÆ•‚TtÉ(€¤°ZY:Žâ¿mïœ3gÎpýúuú÷ïÿ(øúõGÂÀ«bg½{C… O[ê>ÔðÁ‹N§ãÆlÛ¶ãÇ3hÐ êÕ«÷ö;©pÅðá’Wuùr©àÅ­[ðâ^dz#¼%jµšþù‡M›6Ñ­[7üüür·²š™)õóŽˆ:)¼¨–ÊÖ­°y³ôúûïáæMIà~–r’š*…ß¿ID[‘"’ÑV«P©T,\¸ZµjeÈU2dEòb‹/½^ʯ¶´”Œ›+WJ)WNNУ‡´··”BòºètRذt/<éd»xQJkÌ k`` ßÿ=‘‘/vg鳪¦}`èõz‚‚‚HLL`Íš54kÖŒ2eÊH¨ÕÒC²ÿWßi|¼dÝxܪwü¸ô8Pê÷ž¾|·‘³¢ÉôÀ  6Ò 94^£¥å+ä‘'•ÿÆPØ…曥°VARTÃþë-¤ÂPUBÀ;èª"Jµßºu‹ôôt´Z-óçϧoß¾X[[KÜ¿/=´^µ˜šV+…´m+ •+7}ð ò^«ÖÓÅ–‚\ˆ^¯çòåËÌ;µZMÆ ùý÷ßßmqÁíÛ%#fëÖ’ÑÒÚZŠÀ!ó‚$33“pëÖ-¶mÛ†‰‰ 3gÎÄËËëÍ Hær¹¤XZYI2Ù˜1’gtõj)ÒÜ\j¿an.Uœ2Dâ•JiÛ |ù§÷ëã#Uû}üü$o– ×Õš&$$„ääd¾þúkœœœðññ¡råœjñŽ9}ZRFçΕäª/¾òQÍÌÞ¾`R[AFj¯ù¤áÆË Μ‘dÄ÷ðŒx-…ÕÓÓ“ï¾ûŽôôôWÚ>Ç›¢¿gbcc V—"EŠàããçŸ~ú¨d|<=*…ïÖ¨ñò|"­Vr±—+µk?ZÞ»·ÔºãòeéAú.Ñ!…â>µ–¤ôÝþï½IYÌš‹Mx?½Xm€¶ÿ?ËévAò¨¦þ·, ©”É˵H¡ÁYÐ` RCÞš={ö°víZJ•*Åýû÷©R¥ •*Uz´Al¬d@¹zUj•ñ2KsX˜$€öÙÓë.\ Ç<(VAž 22’Ÿ~ú‰Î;Ó¶m[ÌÞV‰ÌÈ€iÓ$ïKõêRû‹$Á"ë_&…Z9ÊÍ›7™8q":///6lH“&MÞ~¾çJ¥Ôw¸NÉÒýT €åckûHx/[6ûg=<¤ÏRXŠ7¯ò6Ÿ¼s233ùã? bܸq899ÈÎ;éÚµkî7Ê<Û·¥yŸ%SYZ¾»}- ½zI^Üg¥¾”)#E7¼'§åk)¬J¥ ,øáVÉzIIIŒ3†Þ½{Óºuëgo-…7þóäòó{ñN32àÒ%©×ãØÙI’÷ñ¥§'Æ-óDj3IY•#yTóÿ·þRNiõ·8nRˆñãs<ø© R£ÿ–¹"W2åQåß$UÜE ÿÝ‚ÔÆ¦REá®HНëÞ˜ëׯ³bÅ ¦M›öüP˜²e¥üAƒ$K[Vhbjª”+‘U1.‹ýû¡jÕg ÜýúAµj/®€-ä;v,ƒ¦Î»Ê¹V( xñG­É¾þZä¥ Œ†F£a×®]üþûïŒ3&»±ÒØ$%IÓÛ·%ù¨m[ÉÐS¸°T,fìXI¦rw—^›™I÷WVh¯••Ô3òeT­*fŸ¾8°k—ÔÖãM³þýWR˜óç³Ï Þ ééé,\¸[·n1cÆ C2eÊ<Š˜ÌM¨Õ’—tÜ8IiLO~®µ©)¼Ïû¶lYé>°±‘sãî-ZüŸ½óªjâð»I6½'ôÞ{—Þ¤w)"M±ƒ(b¡HPTDäEE¥ˆÒD¤(H¯!Ô$„ž@ éÉn¶Ýïa7YBKMð¾ÏãÙr÷ìÝsÏ9ó›™ûöѹÚB¸rå sçÎåÌ™3¶ÇbbbX´h&ÓýªÌS8X»v-Z­–žwªðV®<û¬ì’‡‡g=~ù2ìÜ)aò줧Ë"z³‘²ØÞ]u#pqî¬ì@¢”~HÕ^#"¶Ò‹#2áüp8vÓc%€·°—EòWÏ Ž5HeàRÈöJqDl*ÜxÞØtãq•þøc"##™6mÚ[NÞOŒFñ¬-ÿîDd¤ø*À¥Kðå—·ííäìEJŠÔV¸•‚TQ¤êð;N‘«kff&IIIvÎéõë×ùé§Ÿ5jÔý;AÀb±˜˜Hbb"/^dõêÕ|òÉ'wî=éë+»sþþR•KNš´ 8xPú¥Ö­›õúâÅó–øœ ˆ3úYÑÈrˆ$¸ïçž§7Ò©Cþ#—בHiöŸ?o|ÞJ$ ’›Z ‰žF Žé!à©Ï·B¢Ä¥ö7V*"†UrÅÅ‹9|ø0¿ýö7¦ÍÍÀ²c2ÁêÕÐ¥‹´×ˆ»Ñ7- Ο—\»¸¸¬rè »**E“ÉDLL %K–ÄÙÙ™øøxÞ~ûm:tèÀ [IÛï•ÌL‰øXï!©©bˆ4lè诬òFQ._¾Ì¼yó0Ìž=›àÂTÔëÜ9iß4`T«&µm+ÿ¬8;‹Óz?Çm2eõ`Í+%KÊ1T8Š¢püøq¾ùæ|}}™3gNVmŽûMt´8§•+Ë\Ý»W¢í •w‹Ø'&Ê&——ø ˆã航ũ©2Žì¾Œ•Œ øì3Ik¼×âok£( ™™™¤ßÈ+ðöö¶Ë‹PN‡N§ÃÕÕ///‡hÉ>ÌÔ©S©V­îîî¼ñÆTªTéÎoJH½xÍšY…’4ÉOíÜ+«G‘Å’%.ˆ¹A‡8ŸÆg ’ß¾€µâz q<Io~¸ŠDo³“4þ « ±æÆç'Ûë&¯5:‰Â:c¯¨vã»Ìf3©©©F<<<ðôô´ÍcEQìžóððxàEaýúõüøã4jÔˆ±cÇR¯^=´wÚ™ÎÈ qmÛÚçýx{Ko:WWÙÙ6™à—_dîÜÙg_åA`4IKKÃl6ãééi7Íf3)))(Š‚———]ˀŒÙlfÛ¶mÌž=›ºuëÒ§O¶mÛF­Zµòî¬*ŠìŠóDS­…WŽi•ê°JŠŠ­’ßï¸ÿ~,X@—.]èׯ_áè3©(ÒÚ) @Ä1c$ð øðC>ܾ}««(èó~Üîݳ6¬ ‹½^Ozz:ÎÎÎøúúÚe, iiiF<==qww/ëøÍ„„„ðã?’@×®]éÕ«Þžžb«Üé÷0™²ìz''‰*j4¢.‹•(iË–2'Ìfy}vŘNóçKõÜ'žeš³³Ôºyä‘ÔÞJay3MšÈç‚8©µjIàæüëcÇ$8f­|?(Y^xáÖùØ..¢(MK{8ÖK—.±hÑ"Μ9ƒÅb¡Y³f<óÌ3”½±0œ»·À`0ðý÷ßóöÛoß»ô+#C6[¬ ²^/¹CÁÁY;}¬]+Ò©™3èwRypÄÇÇóý÷ß³oß>ÒÒÒ¨^½:Ï?ÿ<µk×F§Ó±aÃV¯^Åb¡qãÆŒ=šb÷rcv Š¢pøða–-[Æüù󉋋cýúõ/^œ±cÇæ½¿jh¨\ ýûK•Q+;wÞßþÚ*ùâÂ… |õÕW6[¥yóæ<óÌ3”¹‘xâÄ –-[Fxx8¥K—fĈ4oÞüÚ*ùåÊ•+Ì›7‰'Ò¸qã»;Üf3œ9#m–üþ ,)Iªõ.X ¥‚¬Â}/¤¦JŸÉ›ÖŽów\k„¸°gÏV¯^MXX^^^tëÖAƒáçç‡Édb×®]|ÿý÷$$$P»vmFŒAÍûݵ¢€ eòäÉ >œ¾}ûÊ:.j1­ž{.«§¼¢ˆÃ•‘!A§„Y»õzQ‹½öšÌƒøx‰š^¿.µje¾üðôí+¿³¿¿øÁÁYóØÊ[oåîKÜ|ï?>g{@zO¨³óísdÝÜäwõª8çÌÝLHH`öìÙÄÄÄðöÛo3qâDΜ9ÃܹsIKK#==)S¦ðá‡Ò¨Q#fΜÉÙ³gØÍf3k×®¥J•*4¿¹ÇÐݸr%k:%ím"#ÅQ³:kë×ËîʬYŽI¼/†8§±Ö/ŒD1]‘<ÕȬ¨‰Tñ‰ÈF÷<ÖÌïC¢ªVÜ9rƒ¯‰Gr]A*—b€ã7ïõ;ݢ.<øÓy+6mÚÄ—_~Iß¾}Y°`åÊ•ã“O>áСCœ={–éÓ§Ó´iSfΜ‰ÑhdÚ´ièsÛ×4X,~ýõWêÕ«Gý»Ëޝ¯ì¬YÓþ‘ÖçÎe½Æšo4~<”.ýÀ¾“ʃÃ`0°dɶoßÎsÏ=ǬY³prrbúôé\¸p­[·òõ×_3dÈ&L˜À©S§X´hF£1ÿ~±æq=šúõëÓ©S'æÌ™Ão¼×­ŒƒÛa6‹y£ìzP)ëß_v ×¬‘ ÍâÅsö±S)Xm•ØØX&MšÄ[o½Å©S§˜;w.éé餧§3yòdœùðé_¿>3gÎä\öµ°a±X8xð Mù`í7Ù½{wqVA"D·#) fÏ–ªÖÖ×EGKô¨ 9{V¢WŽ¢zu‰eçúõü;ƒô†½ '“é¾UV½—.]bÆŒ¸»»óÉ'ŸðÌ3ϰjÕ*¾ûî;ÂÃÙ1c-Z´`æÌ™èõz¦OŸþ@m•üÂôéÓ™gÒZ§'(HÚMœC‡fEc;w†gž7ÞÈJ*_^ŽùÕW²a¯(âÈŽ}û —ðpX²äÎ_":/¶,88g©¢Èko%Õ}Œ Ù+=ýÎkË=’««³³3†øøxΟ?@tt4f³™ .ä–)SÆnWúòåË„……ñÅ_Pû†,ÊÝÝÑ£G“’’™3gÈÌÌä¹çž£zõêT¬X‘¿ÿþ›þù‡5jœG}Ôö\žÚx> ;vHŸ:(MöHÍß‹áóì³Y2/•BÅÅ‹9{ö,_|ñ…Mýâêêʘ1cHKKãĉFFMµjÕ(_¾<ÿý7;vì Z!‹¢Y aüøñÔ¯_Ÿ‰ãÆ~ü8‰‰‰ôïß_"«[¶H®\ÿþYr¿ÌLy¬dI‘D¶n-ÕÝ­²á„)†4uª½‘š_’“ïo¥Ó»Ñ³gN‡ù›o¤ˆ`~6™àƒ²Šæèt°g?ÿŒÛÞ¼:|ø0ÞÞÞ¼úê«”.]š5jêU«xíµ×زe eʔᩧžÂÇLJѣGóúë¯B‹)ÏÎ#IIIÌ;—ÒØÉ Í„ ¢€0 +jß¶mÖïl2ÉFŨQY-ar“íá!¶}·n÷>H­öì‘(ï툎¶ €lœ8 ×cöâ¬}ûÞ¾zðƒâf߯l–>âuêä[)‘+‡U£ÑàääÄçŸn“½˜Íf, cÇŽÍ¡m_¼x1•+W¶ýíééIÏž=í$Z­ÖVÄéÔ©S/^œr7v,ÜÜÜhذ!GŽy ç9##ƒ%K–зo_»qß3Ó§gízxyÉ¢T¹2üDVÅ]«ôàA‰È³·£¹ŠD.ÇÕº‘X )¶dBY«/ã…Hzïuð7à²ú¸¦;‘¨i$"¾ ´‘>¯nÀ%$¢ "CöA"ÓÙŽ]‘ ޶•L`3ð¤ýPÊüQÓð[ÁºN:4oÞÜ&¯rvvÆb±Ø’þëÕ«‡çÞX¥K—¦lÙ²Ôa]¿~=7¦ìÅ‹²fï|'ââd·æðÔ­+ ‘Ê Ú¶mK«VY ‹««+&“ ‹Å‰'lÎ*H«½^ÏÅ‹ •ÚÀæÍ›Ù¸q#åË—çƒ> zõêùÏCܹÞ|óöFÎÈ‘ðÅRþ¿ÉGÿKXm•ìåÙm•“'ORªT)[*“»»ûµUrKrr2_~ù%S¦LÁl0ð{çÎÔÖjywëVü==Epì˜Ì[''Qˆ}ò‰8ŽíÚI©¯/dÛÌ${Êøùgɧ+¨ÞvíxÄÑŽ› k£Qú†‘¿ãúùIMZš8+Ÿññ$uïŽá>UV½<ñÄ”*%B4ÍV8~ü8õë×·Ù*eÊ”¡L™2EÂa=²éÓéùØc<ñÄ8+Žj÷î9_l LU¬x_d¬w¤LÙ¼Œ½½3%½³£×êU,°:¬̓ÿ­ÈÈ'¼sgqV¿ûN6¾Ê”É·j"Wkùòåyÿý÷1 ÷ôúÖ"C7¨V­&L°ý˜˜È?ü@³fÍðññ!>>WWW¯,íÌîV$˹LCòGÉšA@ ì#¦·# )¢ÔïÆ1@œIÃ϶J£#n|޽½„DU­§Ð*K>Ž}„؉7Dœ\+n|ŽY^c49¸ã W“®RÉ»åyp¹Âc³EEaÓ¦MDGGóÒK/±cÇ6lh+làë닟ŸW®\¹ã1/]ºÄêÕ«éܹ3þùØôˆŠŠâ¯¿þbÆôé°}»Ü„ïÕaýí7‘ùZû»¹©-iHFF›6m"44ômvøøø0qâDÛß:ŽeË–Q¦L*UªD\\œÝ-Y²$F£‘ë·êm˜C‡áááA×®]ï\½8uê}ô~~~Lš4‰Zµj\Áœ1cî\I´vmÙÅW£«÷ÄÊ•+¹v åý¤FvΪÕViÞ¼9^^^ÄÅÅÙÙ*Z­–’%K²ÿþÛSQ8@åÊ•¸ÁèÐ!¼½½iݺ5ǎѦys¢G¢B… b`úúʆ»Õ0®^]Qÿ;Ïe''QÝtñÈ]Œòft:‘…Ö­+¶\jªH?óÛ3ÜÃC ÷K—D…÷Ê+$êtüüí·äïØ¹äÑ›6._¾Ìï¿ÿN§NQ6kÖÌœòóóÃÇLJ¨¨¨ÛÓ`0ðçŸ|çöx÷ ‹ÅÂîÝ»ÙóöÛ¼X¾'¡ß†cÇŽ±råJ<ÈË/¿|Çœhó]zq•+WŽ~ýúåÙ¨6™LlÞ¼™/¿ü’ &P»N¹ù^¸ ݽÈH.\Ȫpªâp<<<èÝ»7‹Å!…^2339|ø0‹/&!!3fܶ’º¢(¶ûÛѸqcºwï~_«P [¯É7ß|“¦M›ܹËÌC÷nJÖþÃ*÷Ä€ذaƒC>;%%…;w²xñbJ—.Í”)Sî˜Ï|'[E£ÑдiÓ±¡rÃõë×Y¼x1ï¾û.îîîP¶,^Ÿ~J5«sêá‘3rèâbßžìndÞœÁ qú÷w܆hZš(äæÎ•JÅ’»[¼óŽtŒÐhÀÓú÷ïï°è|ll,¿ýökÖ¬¡}ûöŒ3掯¿“­¢ÕjéÚµkÞŠÀÞ½{Yüæ›|äåE‰©SÑÜÉ,,ÜͦªP!çc®®Òæ&û½òØ1ñCí°ÉFVT”ŒýÓO©¦ÑÐÝË‹Ô|æ€çyÛd2Ù$™™™·\¨³·ò1ZRRR˜9s&aaa 4ˆ.]ºPüÆÕPQFƒ¢((ŠrWÒ:޼:{÷îeéÒ¥,\¸ÐV“IrêÕ»û®š¢HþGŸ>9ŸÓ#Žb…ÿÿ ¹d¯©“ˆ´–ñBÈÊ-…D.¤Òuĉ´t$+ k%íÆ¿ì§GƒôTý‰‚Tõ-Tþi—S,ç½6âpž@dÂVJ"-l†Üô¹MÈ) ©Ä\ ð“9¡¹¤AWVǃÆh4²yóf–,YBÕªUùüóÏ©R¥ŠmžBÎ9~·Í«\'/˜L&V­ZÅÖ­[yï½÷hÑ¢…\+ÁÁÒŽ&7½Èò»Ã¬R`äwÝË+Š¢ ×ëùæ›oØ´i]ºtáñǧB… FÛ¼¶b±XÐjµ¶hÔíprrº¯mAL&?ÿü3»víbÖ¬Yù«‹`ý~ä¥mÙ"m$ªR`8jŽ'%%1kÖ,"""xòÉ'éÚµ«­Òuöµ;/¶Êƒ¿^¯çêÕ«|ûõ×Ô-_ž:iihôzû|jTþ?ðâEqònµaŸ[ΞY}~zçoo©ˆoU¤<ù¦{¨#×ñÓ§O3þ|ÒÓÓyíµ×hß¾½mC&/¶Š#¿KTT‹-âõqã(Q©šT÷&ߘÍâlÖ©“sƒÆb‘¨iµjöíw4¸¹ƒÉ‰öUè…F#µz<=åÿq‚Y÷rí°Z,Ξ=Ëš5khذ!-Z´à7Þ°“íj4ùñÇívZ™2e Z­–E‹Qú¦*¢Õ«W'""‚„„‚‚‚0 œ>}ú¾K V®\É믿nË•3ã";æ| •ñît#²¶÷¸U‹ "umKÞ«ìæ•âˆôÖˆÈgõ@s$òYq6-H.«æÆøŽ"‘Ïì›4z`О¬¼VBRÿ¯d{ì8Rì) ›<—  *â(׺ñYËq7Þ£–!‘Ôìi_Ͱ¯Vlå:ÉÍŽ‘![‹IYä_jíT<¸³¡\Ь[·Ž¯¾úŠÉ“'Ó²eK;G³V­ZDEEa0pss#66–k×®Ý×]÷¸¸8þüóOfÏžmËW!2Ræwn"¦³f=Ðó¨R81 |þù焆†òñÇS³fM›¢Ñh¨Y³&çÏŸ·å¸†‡‡ãââbÛ˜tf³™ púôiæÎ›?ùÙ,•Q S'12|}¡F‚-<£â0˜^6IE|s_VGqŸúÀæÚå={ö,ãÆcëÖ­vFŸxâ æÎKÇŽ)]º4S§NÍŠVÞàÌ™3:tˆ¡C‡R­ÔúÏd2Ѹqcâãã9uêF£‘øøxŽ9BûöíïÛyÍÌÌäâÅ‹¶ªÅ€”`~÷] ­ûùÁ¦MwÞasr’B·’‚YÓ}“‚CŠËˆ¸YŽò%²¤¾Î7^¤g{_Ù¯ÉÌö˜Õß»YÑ…Tή)¼€D•ão<H}­QÔTD–lM+-†8´7·ÎñBro¾o %Gq%k~­y½\ãÑ`8 ¦À[pÉb±°zõjÚ´iCÅŠ‰‰‰±ÍñäädZ´hÁ±cLj‰‰Áh4ræÌ¢££s×ï7—œ?žàà`³7<_»Vvî¬IñÇŽÝí‹ÉkUþó$''³aÃúö틟ŸW¯^µÍqƒÁ@óæÍù÷ßIOO'33“={öàççç°þ}Š¢pèÐ!8À{ï½—?gUQDyóÅâ¨j4R» Gèׯp½PÉ7§OŸæèÑ£ :EQìl³ÙL“&MˆåôéÓFâââ ¹¯¶Ê½rùòe.\È믿Î 2xÚ4<>ýT¤¨÷K"Y±¢ð+ˆV4 HÁG3p Øtï¿Ë—;¶T£( Û¶mÃÉɉ޽{“`›ß11Rù²E‹„„„‹ÑhäÔ©SÄÄÄ:‡UÙ»—ÄQ£(Ï“ŽŒÊç''‰è'%å|îøq „ÝnófáBÙL¯^½²?(»ÇÖHӣʚ––5߯_o®T)Ù”Ù´)giõ"Nf¦lœ—*%²‚Àb‘Âxß/m8ï¥}ÛÝ0àêUék~ö¬}ÿrGP«V­ÛÁ)Y²$ÞÞÞ|ôÑGlݺ½^ÏàÁƒ]µX,|ýõ×4mÚ”ºy‘󥤈ìJQäÇôõgµ(óPÉ3?þ¸í’ëÆË«¯¾J³fÍ8~ü8ǧU«Vø9¸âáÇ9Âǯ¼"à  fºnáÜß3™™²ÈiµòÏév”(!†ÈC†››ãÇçùçŸÏñœµB»¿¿?Ó§OgëÖ­DEE1yòä¼­¡Mf&=ÊÊ'X±iÝŸ~š7»w—Š×EFäçŠ"²ú„Qv¦§K¥Ý;Õ.5J6íÍQäÊì‰Çl6S­Z5[­››íÛ··õ#ðòò"((ˆcÇŽÙ-úö²Ä[àååEÇŽéøv bbb¸ténÎ;êÜ9§¼×d‚ÿ…?õÅ%géù祒Ñ(!ù݈shÝ„rB¢–ˆ<ØLÁ;¬&`-Л¬BF鈃Èv-À`ðç›ÝxüàœÕÌ­`„Ð#ðË/ðÒK0c&þøã¼àÏ?¥A{@ôì)9ªy¬F¯Rt º«"ÀËË‹N:ÙÚ€8ƒÁÀþýûùì³Ïx§fMJÍ›'»»w±· “ÉVh‹E Áœ:%‹Øðá"‡Í›¥EšÅ" Zb¢¤¦ìÝ ÝºÁøñŽ>¥5NNN9ò²oF£ÑÀÀ=Ü,RR`ñb.ýöÛýý™3¾­ e‘Æ*ñÊí¦On f>äÊìqwwG£Ñ‘‘a÷ØSO=•£°Ùl¾kGI‰%r$›sS1(@þI“Äp·îXººÂ#ˆÅ«(`ÑHŽæ²ÖPDŠ[ qóp]™Lb¸Þ¼¾lÚ$~uã:àöRa×qNOATx5=…­ÑfX:^ì»ÁTNÄÁºõR…zRkp†c—dƒ¶iSq× .Ñ0uª|ízµE…pè*¼¤€O5ЄçAJ?h_ê]m ¼Qv—VX Ë@ò·p²LùB¾S—.ð¿Ùp>Œƒ¦Í¡CÙpý|24¯'cqu•͵½{eC©Q£¬vm¶¿êÀ9Ï.Mà% 7·ÿ¦i±XسgMš4±":Zæpö^wVäÊX±^x!Kšåí-ì=èfE檿Á¶Òûå8t>ú(ÿΚÙ,ö’³³Ô3øày,?ÝMEl‘”¯¼"‘П†7ßÌÛñŒFé½½h óçËœ ˆªF½;Û¶mcáÂ…Ìš5‹à{‰2;'köûAïÞaqqqì.ŠÊ-0|úé§<Ú :o€òÂõž!Çÿîè¢ÿ ðé1x~¬texó+ÔCCoqV%zé7 ‚¦ƒûŸÚ%º\ƒ.Ó€‰H!%=”,%«#åäû»U„Nõ m[8rv§CÿÖP¡ÿIî-­ZAŸºpîC¨ÿ¼}Ä©Lm¤ˆÓ¤¢ï )Ò:g"u>t¸ñ† ¤xSÄç‘»E+hÖ4ÄYµâá-ržk¯Ü*šœ‘ËÀ[™V…†¸¸8Ìf³}A±Í›å‡(Q¢À?Ï*³½zU6Öók{˜Ír9†‡Ãôé² îÝ+iy!::+BùÅ¢òÔhÄ þé'Qùçfl—.‰œýÊQµÕ©“%W.YR6|.^ÆÝHN†íÛåz¿~]T³få4lêÔ{°sgYTr²ÿ~æÍ›ÇôéÓ©]»ö½5—.ÉŽCPPÖûí·~WQ)„èt:¾ûî;ž~ôQ*~ú©l¶8ÚaûÌ®K‰Šc‰ˆ´=½^”p-[ÞŸÏÉÕ%£Ñhàg‚ÀP¼øÁ/—aåBê[w@3#l<"]pš4G÷×_ÅÐ={æÌƒuêTQØìÛ'ÿ_©’D@?xÜŒðÆä¬–MḬ́èø{³ll¦FÀÛM¡^pñ…еaéj˜Òê5Ïj\>ªæúö ¿:ÐhY|m?>Г¬8žH®®3†´ìÙäÑZ__‰vÞäÿ;ǾH ›‚(èzã8•ò{ ¢¢(ìØ±ƒªU«âmÍs0dBUà[`Š"9—/KªkzzþŽg±HÊø‰2ÿ}}Ee’{‡UQäšúè#yï¤Iö_¿}{ù“éîF„µ»ÏÒ¥ðÏ?’ÎþòË9í3F¡¡âdÞJn¬(ò™—/KÐÛÝ]Ú—Õ­{{%Ÿõ¸11ªÃz+, ß}÷Æ »wgdW¡vmùÌfIº/¤÷/ƒ‰‰‰4=tH¤µ={:v@løa,–¬4\E‘ûA^UÕŠ"йzõà±ÇdiéÕKÊE”)íÚL=†‡‹åÈ.Ã'>>uêÄ”)SVq^%'Š"Á¶nÝdÏwùrñ‡îGú|®÷xÊ–-ËâÅ‹ùõ×_Ù²e þù'‰‰‰¸»»SªT)7nÌСC©u+él!!%%…¹sç2tèP»¶;”-›¥Ý¸»vIžç§Ÿf¥¹V¯.ÿ­RØ NZG &ÌIíÁXªï…Šu`ÄĬcöí+…_~ûM"*%JÈ¿/¿”o¾yãØ7>cÙào¤Ú.€4 Xwä WÀÕ£ÐÈ€­…M©ŠðnqàlŸ4žP±!R8;Z²ªߌ©t\qNûÞx¼°óÆwÏn¸÷›í>k®mvœÈê÷š4@¤Jò˜ãdzeË>ûì³,É»«+L™r_>/:Z=y²8—+WæïxëÖ‰#7wn–3دŸ\:ݽÅ3åúÚ¶M¢´AA9 ëxk×¾sTØ`Šó;wÊâ<`Àí³À@‰æêõöiYéé"sNI§·reqzï% ²>üøcáëþàhEaÆ ¸¸¸Ð£G{wVããeXeïii²;8i’£¿’ŠÊ-1èõ|³d O?ý4-ZÈüý–&›ü ˆŠEQd]ŽŒû(?ùsññ¢´±Ö IKƒråÄF»×ÌE‘ûVh¨lRnÜ(™Ö¥¥T)˜8QªÈ·hñPuʹ?œ;Ç‘·ßf[ݺLùì³üõÐ."ØÚI‘ü™3¬xóMw©RðÙgÒ ª ƒày:%>>> >œž={Gzz:Z­J–,‰G!.±l2™øæ›o ʪDl±ÈJ“­UOL ¬]+-SŠ—p÷š5R5÷V5™8€8mA@ EÔu@ ÅAr=o¢Oi¡”=J,;q9ˆEœ==àHtwC(u Ji‘v6Ö_÷àg û¸ÝäõÜ[j¢ÐäÆç§!9ªÖÉX©@<Ь>¯ QN·ãÌNKrFp ’úHë½^ÏâÅ‹4h­]z½DŽîCA £Q"Ž f{öˆì)·y¡f³( Ο—]雋à:$¹ÐÖMœ;)5UªênÞ,¹ ·kèî.㌉Éé°šÍòø¶m²aÕ£‡¯XñîEšJ•ç2*JÆ›š*ëÈGÉBþä“"C Ê]±¿š5Ev}ú4„‡k ¢E‹W »°’œœÌªU«xíµ×rÔU°¡(29´Z oÄÆÊ®È;ïdm {yIŽ÷}Í«¨äÅd°p!•RSiß¾ýÆëIO—váJ}€Þ½Å©¼|Yj'<õTÞZΦ§Ëæá_ˆ“ð⋲¢î UËÍû_ׯ‹ è‘Gä5z=œ<)Å÷jÔû×»ïæ,–Y·®D]CC³º'ªÜ„"\„ÁÀ'¾¾Ìœ6í?ᬂlÖ»ºJÚÏýP=ëõ"U·âáqûÏQqngë(Ф1Y[ó:9ÉuøÖ[r-4lX°*‚<ûðÎÎÎ/^<Ë .Ä„†BÕªàá¡ð×_¼y󲪟<)g½o_Û{–/Cõ—_$Šº~½ÈõîØÍ!h€8rÎ@R!Øj;µBªç8—·Ù ½€8ÀVÉ®ø ‰FžBª+dE:k ­s<€ì©,ˆ£|³”²ÉcÞ+î7>¿ YUAR-°ÈÞÒÖçÆ˜n¶ï·Òî?^'eóæÍ899Ñ¥KyÀh”äèråìÛÙŠ"×—§§8rÖ…oȹ¡çÆaÕëå:[½ZŠŒÝª&Tw—_¹"êþ;åë.XpçqXoIIöïß/Æ‘Ñ(¯™<9w2\¹,^,ÆÕŠbøŒ“¿j‘Å‹‹Qµb”-«P½z2ÎÎ…»"ûƒ`Ïž=S»víÛ¿èøq “)IÌÓ¦É]6ûn¡‹ËCYüE¥èc6›¹¶a)ß~Ë€eËìb9çÎÉzâœgç‰[¼Þhq·ƒª$»ví¢~åÊT®œm§$%^}5ǶïÑ£roÛ6oŸ•˜˜µ«|óhåÊbôí{wG/!AŠ5i"•€ïÔA§reqH³“‘!»|‰‰â“̘qÙþm(]Zõ?Eè£J‹šüú1+JÎRA£ÑÈzd4ü±‹‹…•+WR«V-êÔ©sû&'‹%½/Öm 쩨6víÚÅÚ ˜þÕWxÖ¬éèáÜ“IÒ(¾ûNŒÞ=ä~Ñ£têtï‘—ÄDÙÄlØðöëzp°<¿m[ÎN:Š"ª›ðp)Ú—–&KÀˆwÏqs“%âùçŨ¿pA"»Ã‡KtT«ÍÊ$ÈbÕÍMdÁ¯¼"ѫڵÓpq‰Ð?Qá$=ó«V±ÎLJ 3gþg¤Àbƒ<óŒlžtè óëúu±¡¦L•g‹\ØÔW®ˆ¨("B|!™kYÏIý‘O?ÛËjïddˆ’¡cG©Õ±f˜Õ«KðÎÙY‚nn·v }|$`0ožä²æ&åéN<Ô«Á‹ɉ=wNaÉÒ£L«S —7ÞKúñÇÅ3us³­ž/ÊŸÙ7un¹°†K‘ˆ£+ FòD}k@ ²ä¼ ânĹ˞נ ÑÚìÑÉ]@—ïÉ@"¹«Ñ7Ž‹ô $«"®'"Õ½€Tèµâvc\!Å­8®Õò{ •ûÁöíÛ©×Ëê2l˜4ñìÔI<œlÉz=|ò‰Ü4óâ°&&Šš²X1 XÝŒµ_°År{‡5=]v˜CCe!­Yóîí^«V• ¨´4YÈ7n”ÝúðpéÿõÄy“и»KðÍšæ«6w/:\»v={ö0mÚ´Û¿H£ÉûÎŒŠŠƒ‰:wŽÓ¦ñáâÅT¸WÙJ.1™$7ÞÍMîy74ÃÂ$e¡J‘5V«&ÇmÜ8«øíöŠEö–Ο—¨jƒbÀgËØº%uêˆCœ–&ã¶JW®)qçÎâhººJÄê^s늓"˜ûöIô¶W/ÙˆÌo~aƒrmÐ =‡›òwÀ‡€¤¤$¾š?ŸbõëóîûïSö?”šqäH– D‰emU¬(ÒóìÙ¬ ·C¯—M•}ûä}R/ÃËëÖ4mÛJÐàØ1±Ûœœäÿ«V{ÊÙY®=E[«cÇ{«ž(ïùçY[ò£sçdòÃCí°îÚ%†h:жm2{ö¸RcútÙnؽ[<Úl+²N'Ñ›ÀÀ{¨Bz8ômvã¿»~ˆö8âÌ>zÓû¼DìÖ$à "ŸuAòPc÷Éï.DÜŒ,§³’3{¬bJ®@»ÇÈ>~'²ò\ó‹PqZU ñññ$&&RçË/eò/Y"¥[”“ݳGæûþýâ8榓Ñ(F@ùòÒ!çV(ŠHMÚ´¹½Ñ3c†&¯¼r ¹ýmðöËôéRl£iSéY:lXþÏŸÚ:°h²lÙ2Z´hA¥lEór`­2ñÊù+*$%‰?7ù‡ÿ5ÎÏË8ƒ·Jì/ BC¥ïu›6rû(QB¢#¹½d±MiÝ’]¥âë+FñØ;¬‰‰â@úû˽éÛo%£kW¹}=ùäÝ?·R%1¢×­“HЦM²aúÈ#r(™Åm©RR¥¾ qs“p YË“ôz^ú쳬v|…½^¼ãÇ¥ØVF†Ì¹ÜtÞ‰‹óÙgo­êÒhÄüüs©aqsq1“IœÔ˗ŵ‰ˆ Û Aw¿~]]%ê:k–ÈÚK•ûnîÜ,ÇØÕ5÷åO¬Ž®õZ¯Z57snÍCë°fdHÔeÜ8pwWpa;¾éU¸xÞÚ @ýúXК,~ëöí’߯ŸHVî¸{`¢‘Hi4½ˆ#qëßÏÞôÞvä”âþ| TEr^¯!NêÐÇù)¾”½ÏiàUà1ì#³n7Æw3 ðä¾€DyU ›û|}ñóó“&ò}úܲ¼[B‚ä|ò‰Ü(£¢²Ú3ÝôtxûmÙeîÒåöÕãe‘Òé²VE‘¿O’V3?.ÆKn£™]ºH$ Q#Y\óÚ'O¥è³{÷nBBBXºtiVû¦[ñÓO2Ñ bgCÅ‹%«Õ”““_/Š´eK¹Ÿº»Ë:³q£8BÁÁb˜…‡‹³b6Kžà#äl÷ïBllÁW7/ X,N®]KÙ³gñ_²Í}ðèEŒí3g¤½V­Z0p ÈùnU9ýV$$ˆÍµj•¤‚Lž,÷”›£˜NNrkZ´H~wE'¹D ‘ó’Õ¡AƒÜ§d<ú¨HûôÕNÙ²wWí¨ÂÉڶ ýO?ñÎ'Ÿà}º(Šä¯^-ÑËòåÅù«R%÷•l-©Òÿ믲Öõë'*)ø¸m›¤9YoI+VÈãÆ‰S«ÕŠ‚ "B®½={dƒæN©LîîâÐ~ýµØVÎβɴgOÖ÷«__®a??YCïÕ6ªQCdïׯKĵ[·‚¹nZ´T/WW É$9Ö‡×a=tH¢7U«J+›¨];`2rþ\o’4„„h(QBì˜áÃ%Aøw²ôÙvXë™X'µÉ}ø)¦ä…½L¶÷×Ô»éX&$¯ÕúÚtÄámü¼‹Tô} ‰fZ_·¨IV+™H[šF7¿.9{«BÁ¶‘©ÿC¨,III¤üù'5ªUCãæ&+ðm¶ÖV­’]ÁÊ•e'üÔ)Ylï´h+Š,Ìü!ÆL³fwnëâê*AÇŽ‰+=]6…Ö®…rŸ>²å%G´I“Ü¿GåáC§Ó±dÉ ”U`ìv„…Iu•{BQl%prÊjo`E£‘ÇNœƒé‰Ž5o.ѱzõd³8.N6¸22DFÙ±£üw÷nYZµÇÂ×WòÐ-’ã·ßÕGh(ÌœéA@À£ÏèÍ\½z•…Ë—3ñƒp/À¼Õì¿g\œDWFÊ*f§ÕÊo¸ÿV³YîS§ÂÓO‹#0{vV›‹[Q¼¸Ìƒ>µŽ‹‹d°Œ%÷¥òÞ}­V-éðàãS°í4TîÖF£!1.Žåß|ÃèQ£ð¹9«VguÖ,±]Š—õçÌÉÝÌMŸ]NÖ¨ãÇe¾=óŒý5R½:|ólâÊú¨×‹³¹|¹ØEU«fù'?.¹©Ö\è;Ѩ‘¨¾úJæxT”ØnmÚˆ=—W\\¤@dAãäT°¢¦‡ÖaMLÌê•‘žNü_ñòÀá|vГId&;Ëd¹k„ç(¹´ÖóˆGªîBªŸöã³½Ç |AN)n#àDÒëlBùïKÀIÄqm8ÈHÓY@ÿlÇñCdÂ7;^@WGŸ}•Í…ÈHʇ†âòÞ{wÜV;{VÍ!CäïfÍ$™øðÛWn´XÄÀüòKYtÛ´¹·»J•Äà,YR"+‰‰R€¨ššÿ¬’O’’’˜5k­[·¦ïÝ’ÛÌf¹4jto/‚(ŠHåCC¥øKÍš¢l°VEõðÈ)Q³XDi.B` =‡K´³bE1èzõ£ëØ1y>6V¢_§OKÎÕ /ˆ³a•£½újV»Ž*UĘKH°—€V®,kNvÚ·—ÇŽ‰ÁwꔌéÙgS‰¿êèSü`QtgÎðÁôét4ˆ ¹©´r„†ÂÏ?‹cyö¬lt¼I…U½ºDŠn…Ù,ÝgÏéá·ßæ®òoýúÒv¬zu{,¿Q­V­?Pd8|’’0´kÇÜ (ýôÓø=÷\UlOLç0#C$³Ó¦ÉFyß¾bÕ¯/U§££ï^ÉÖÚþÐ!QwùùÉ{oåèÉš8t¨öZ¾\åÚµecgûv™£íÛç~®º»KÔòâE±ÝrÛ羨óP:¬ÖJ¿o¿-Ÿ8yKÕª<3wˉÇÏ»o:`+p˜ƒ6 E ,!U‚÷"mö¼ÑÊ@KÄ)ÍN$/u9"ùÝŠ8¢^ˆÃz)šôr¶÷¸!Õ›óüž¼1•ÿ<{÷í#xøpÙ¿ ááðþûR„ÌšØ_¬XVÍÍ(Š°Ø²EŒÞ—^‰ß½ÊL¬9ÖøbÅÔB•üc4ùüóÏqrrbÈ!¸ÜÍÀÑh¤–LRNM•]ôr岌ñ¤$ »ºŠsZ¬˜ä®]+Ë5kä½M›Š ­F ɪPAœ __± wí’‚]»Ê©Ù·O”gÏŠì¾qc‘Üëtb ½ø¢#3SþÕ­+›RÖ€H•*·ncUºtîªv7h Îò… r|“IÚügP̧N5z4]œÞ}ûÞYîž ,‰ }ú©H«V•õÜË+§b¦R%ia—u¿HO—:Î΢N2Dd¸¹M7ôóé®Ê½fÏÆüÜs¬[·Ž„„Þzë­»¯å÷ÈõëðÁ²îÙ#ëRŸ>RñÖ:Ï}|$²–SlU˜X‹;®Z%jk½Œ»åCûúJq±yódÝ´¦\¹¹IŠD~¨QCþýy(ÖcÇda.Y k×®¥ïĉ8U«J®7ðÎ"”:ˆÓøð&í,@œÊì ¾)t«3ü,⬖BZÖXkâTfÞø;û ¾>0†œ¹¯QõW¥È“ššÊC‡˜8q"šÛ,ø:,ºŠ¤ÄŠ»»DQJ—¶ïö}ùë/1˜ß|3÷2­*U$_ÄbÉ»ÄKE%;F£‘%K–˜˜ÈŒ3î.±ÈK½¤û+W¤p̵kâœÆÇ‹:!>^ Ÿà`‰€ùù‰a6eŠÜó†GÃÓSª<úû‹áuèkgÏŠR»¶DÖünT²7›Å8ËÞõÍZǪe˜㻟<ýüÄq‰Îþ—°\ºDôK/q®}{z¾ò n¸Ëwé’»›8Qò…ï„»»l¬['ôK—¤Wö•+Ré§Ÿ}¦TŠ,?ý„¹];Ö¥¥±råJæÌ™S`ík23E V¬˜DïoW°K£¥ÇgŸI*CppV>wX˜tŒŽÎÊ»~å•{(Æš–-¥NH~¤º*ö°lûáúdfRõ6Û~ññbÌ>óŒÈ`²ï$º¸È®¡Á혖¬"ÃÏ='p^¥Z¹YàUTîÆÞ½{Ù¿?~øá½9« Ò3(4ÉÏ™™² dͳ3›Å¡Ü·OœÓ:u$2zò¤ÈØÊ–•ÈÖ±cò¾Q£Dvæì,Å>ÄÉÌ.O»ÙHòöι!u3ÎÎöΪʃGQ¶>ÌþÒ¥y}Ò$f Žëë@S¤×ª•òH¡£›•—5§5·eÔUgõ?‰ÑhäàÁƒÄÅÅQ³fMªV­ŠózÄ܆ӧOsÈË‹¹C‡âtã1™¤ÂçñãRÍs„»GuqYŒ¯¯ä7Y l¨¨ä•ôôtvïÞÙl¦nݺ”-[6wNæM,[¶ ‹ÅBÿþýs_˜£GÙ•¹N‚… ¥`Ñž=r=Õ«'»ü˵²r¥DÇ‹ãªÕJlgg äêtòÿ½z‰euDûôÉùyjÈ¢‹ÙlæÌ™3„‡‡S¶lY6l˜+[ÅŽƒù{Ý:b:vdâ°avs<1Qê„„HË—nÝÄÈÎN“&bÔÏ™#óÌZÉtüx‰’æFªªjµê\ý/b49pàñññÔªU‹*UªäÉVÄ(ùå¾/S†zõêѪU+»§/_ÛåôiQšÌ˜‘U U§“·ò‰DB½½%u""Bêkøøä½:´ä§–-›³’ºJá¢Ð9¬_~ù%›6m¢lÙ²ÄÅÅѰaCƇï=êžþúÃHÛ‹?²&ó ]‹w%°B­œ/Ò«‘j¿ƒê¬ÿ_¨ˆôG=…½sªAªß,§)tgQ¥°’’’¬Y³ £X±b,Y²„Ç{ŒçŸþÞFÒŒ|b42xÔ(‚‚‚ÈÈžªÈÂݶ­Ú÷º[Ø­Û½ËÄTTîÄ… øàƒHOOÇËË‹… 2a½[å-0›Í,_¾œS§N1gΜ{Ï[ÍNûö( 2%zj±HdóìYùçã#Ô´41ÎÇŽ•ê©ýûK~ ÕX·^={ÊkgÌ× ²Q:kV–sÚºµ£•ûÍ_|Á_ýE™2eˆ‹‹£Q£FŒ7Ÿ\V£6Z¿ž­mÚ0qÖ,´Z-f³TI>yR kU­*UG+T¸}„tÐ qV]\ä5NNÓâE5âÿ›$''3kÖ,ÂÃÃm¶Êã?ÎèÑ£ót¼”XéãÃegg>3µóÚ5øå‘ô 9Ò®®ööˆ‡‡l"V¬(Žm… ²n;9eÍ÷ü`-ð¦R¸)T®Ö¹sçX³f Ï?ÿ< àäÉ“¼øâ‹´k׎:Üõýéé¾å O] %°ì@êTl‰f¥FŠ&eßeÜŽôB >F $=†8£NÀ@ û¶4šÂvÆTŠ{÷îeïÞ½|úé§Ô«WU«V±hÑ"{ì1JÞ­V:È ÿÅüKéfÍhÛ¶-™™"e‰Š‚1cdaÏín¸ê¬ª‹…5kÖ””ÄÂ… ñññá“O>á»ï¾£aÆøç²qÜøõ×_™3gÎ=oZÚ‘’™h~ûMƒ´èHJ’ë£cGÉë®\Y i4öí nw ¹ºJÐw߇bÕ*1²ÔcÿÎ;Ço¿ýÆ‹/¾H¿~ý å•W^áÑG¥]ö2ì÷ÀÑ£G™sò$ü1eÊ”%2R6¯^µËˆúånF¹³sîÛ˨¨ÜŽ={ö°oß>æÏŸO:uøå—_øúë¯éÝ»÷½Ù*Ù¸rå 3ŽAãåÅÄ  $-MÚ+99‰B`È(Sæöó\£‘¢pja¸ÿ.…Êý:tè¥K—¦K—.hµZjÕªEëÖ­ùûï¿ïÉaõÒ˜f>Czà@j®l€{Uw¸„´Š1-€T¤ÌçHA¤@À靈¡½ñ˜ŠJ²{÷nZ·nM:uÐjµtìØ‘uëÖ±{÷nú÷ï×÷+™™l=q‚m~åxµÏD>û̘7îþ¶™PQ¹, »ví¢_¿~¶ÂHƒ b„ „‡‡Ó¬Y³»Ä`À|ý:ûW¯æûŸ~â£e˨^¥Šèn÷ï—Ï£Bƒ/E“¸àGâã2ýJ`zr‡C]ñOºÀ¦o¢Iµxñø¨ Ú¶+KÓ¦›ƒ$…Êr韨<8p€²eËÒ©S'´Z-uêÔ¡eË–üý÷ß÷ì°šââHøôS¾¾*?þ(¹ÏOEQ0 d˜LütŠo5B[^‹Éd’ÂGs€ËˆÌ7‰¦º"N,ˆ˜l?öïßO… r½SåHŽ=Jpp0åÊþRÆŠ¢ ( F£ÑÑC±#<<œÖ­[Ûr "<<üŽï³X,dff¢3ix?q(Æ”v¬^íÎÀ&Ê•“ÅßôçïÝÐétìß¿ŸV­ZáZDª öïßOãÆó&=}ÀX×=³ÙŒ¢(Ž óôìÙ³vm *T¨@ff&W¯^½ã{M&ƒã‰S\›ø>¦«1¼7°?e«šN¥*á£år¼'бcµ®œêKšÅ“2¾´Œ³P¥Š‰ªå‚iØÆ_W=Åjû£q7ÝøŒ‚û® œl{ìĉ¸ººRö{¡ª¨v7nL\\œMš§×ë Um•‡†¦M›rêÔ)ÛæcTTÑÑѪ­¢â0 •ÃÚ¤IL&¿ýöñññlß¾sçÎѹsgGME¥@h×®gÏžeÇŽÄÅűfÍL&SŽ&Ú**Eggg:vìÈÎ; áÂ… ¬X±‚ªU«Þqg^E¥(Ñ´iS233ùý÷߉gëÖ­\¸pN:9zh**B»víçßÿµÙ*‹…–-[:zh*ÿQ4Ja)/yƒðÕW_‘€——ƒ ¢GvE à RQ*::šbÅŠQ¢D GGE¥À¹rå IIIT¨P¡ÐUÀTQÉ/f³™ .`2™¨P¡B‘¨º¬¢’[®_¿ÎÕ«W)^¼x‘)𣢒T[E¥°P(V•B•ꢢ¢¢¢¢¢¢¢¢¢¢¢bEuXUTTTTTTTTTTTT %ªÃª¢¢¢¢¢¢¢¢¢¢¢¢R(qž:uêTG¢¨Ç‘#GÇÙÙÛsŠ¢ÅáÇILL$ Ûóf³™3gÎpüøqŒF#þþþ89eí#dffrðàA.\¸€««+^^^h4š{ZZ»wï¦lÙ²8;;ÛÆ|íÚ5>L||<þþþv•Íf3gÏžåØ±cèt:ìÆl49tè‘‘‘¸¸¸àíí] cVy°X,._¾Ìáǹpá>>>xzzÚž7›ÍDDDŠ^¯¿å|8xð ‘‘‘hµÚó!!!ƒríÚ5¼¼¼ððð(ÐñÇÆÆrìØ1»*µf³™óçÏsôèQÒÓÓ ²³ÉdâÈ‘#„……áââ‚ݘ“““9tèQQQxxxàáá¡Îñ"ŒÑh$22’ƒK@@®®®¶ç­óÁºÆßi>xzzÚ]Ùï ÚÝ ‚óçÏséÒ%J–,i7æÐÐPNŸ>F£ÁÇÇÇnާ¥¥qðàA._¾Œ»»;žžž¶ïtó=ÀÏÏÏî|¨=¬½bCBBÐëõøûûÛÍÃÔÔT:Ä•+Wî:rkGŽÁh4âççg{L§ÓqðàA.^¼˜Ã>R…¸¸8:D\\¾¾¾¸¹¹ÙÞk±X8þüðC¥ÿþJbb¢’žž®Lœ8Qyá…”«W¯*ÑÑÑʳÏ>«L›6MÑét2þ 6(õêÕSzôèa{ìòåËJ‡”o¾ùFÑëõÊž={”V­Z)ÿþû¯¢(в~ýz¥mÛ¶Ê‘#G½^¯ÌŸ?_éÞ½»¯èõzåƒ>P†®\¹rE‰U^|ñEå­·ÞRÒÓÓýs©ä}ûö)mÚ´QV­Z¥F%,,L}”¯¾úJ1™LŽþ¹TòÀÒ¥K•N:)‡VL&“²}ûv¥k×®ÊÏ?ÿ¬ eΜ9Ê“O>©\ºtI‰W^{í5åµ×^SÒÒÒòmä—ÄÄDåÅ_TjÔ¨¡üòË/Š¢(ŠÙlV,X ôéÓG9þ¼’˜˜¨Lš4I=z´’’’¢$%%)cÇŽUÞzë-%..N¹xñ¢2`ÀeþüùŠÁ`P._¾¬têÔIY¼x±¢×ë•ýû÷+­ZµRvìØáèŸJ%FeüøñÊСC•Ë—/+ÊÊ•+•Ž;*{öìQ’’’”1cÆ(o¿ý¶¯\¸pAyâ‰'” (F£1_6AA©ôíÛW©^½ºræÌEQ%55U7nœòꫯ*111Ê•+W”¡C‡*³gÏVôz½­ôìÙSY°`’‘‘¡?~\iÙ²¥òÇ(Š¢(;vìPÚ´i£ìܹSÑëõÊÒ¥K•6mÚ(±±±Žþ¹òLÑ ÒÓÓ¹víÏ>û,%J”ÀÇLJ!C†G|||8>>>+VŒþýû†ÉdbÏž=T©R…Ž;âææF‹-¨U«ÿþû/ s¸k×®T«V ///úõëg“*^¿~ÐÐPLÉ’%)Uªƒ¶I¸òƒ¢(„††²bÅ }ôQ»çLZZ‡bÀ€”)S†bÅŠ1lØ0BCC‰ŠŠrôÏ¥’Μ9CÆ éÑ£...T«V.]ºpüøq@Ö´öíÛS§NÜÝÝyì±ÇpuuåÈ‘#¤¦¦røðaÛ|(^¼8ÇçèÑ£\½z•ððpRSS8p ¾¾¾¶coß¾%Ÿå, [·n%,,ŒêÕ«Û=·k×.š5kFãÆqss£{÷î±wï^ôz=ûöíãñǧ|ùò1dÈ"##¹pá.\ ::š§žzŠ€€*UªD¯^½Ø¹s'™™™Žþ¹TòÀ™3gèÓ§õë×ÇÙÙÙ6ŸOœ8N§cß¾}ôë×råÊÄСC çâÅ‹ù¶ òƒÉdâ§Ÿ~ÂËËË®¨Åba×®]ôîÝ›Š+âïïÏ“O>ɵk׈ˆˆ **Šððp† Fpp0åË—çñÇg÷îݤ¥¥qøðaéÝ»7nnn4hЀ¦M›òÏ?ÿ8ú§RÉf³™sçÎ1bÄÊ–-‹‡‡ýúõC£Ñpùòe._¾Ldd$C‡%((ˆ *зo_víÚEzzz¾l‚ü’‘‘Á‚ hذ¡Ýã±±±œ8q‚¡C‡R¼xqÊ”)ÃÀÙ¿?‰‰‰6ÕZß¾}ñðð víÚ´mÛ–¿ÿþ€Ý»wóÈ#ФIÜÜÜèÖ­%J”`ïÞ½Žþ¹òŒê°æ???&NœHµjÕl]¿~ggg\]]¹rå &“ÉNÞX·n]›žüôéÓ”*UʶûúúR¾|yN:e{>»!R©R%›f=¿üöÛoøùùѵkW»Ç¯]»Fjj*•*U²=V§NÂÃÃ1™Lœ9s†bÅŠ€‡‡•+W¶söóQ¦LÜÝÝ9þ¼£.•úôé|;¬W¯^eéÒ¥Œ92‡„þôéÓT¨PÁ– U¬X1J”(ÁéÓ§1œ={ÖnW¯^””bbbˆ‰‰!99ÙNâ^§NΞ=‹Á`pôÏ¥’ ÄOðòò¢]»v¸»»c6›Ùµk¯¿þ:ýúõ£V­Zèõz,‹]± ___›a›žžŽV«µBZ­ÖvqYŸÏž|íåå…Åb!555Ïc¶X,lÚ´‰={öðòË/ÛIü6™LvŸëççGbb"‹…ôôt[Ž ÈBáåå•cÌÖdt«c“””äèŸK%”,YÒ–3‘‘Á† ˜?>/¼ðîîî·œÞÞÞ·ÃÖù`½™dffÚå9ùùù‘–––¯HŽÑhä믿ÆÉÉé–ù8;;ÛÆìää„··7ׯ_·Ùšb€¹¸¸€ÅbA¯×ç¸>222ÐétŽþ¹Tò@õêÕ©S§Š¢pýúu¾ûî;6mÚĘ1c€ÛÏ뚨×ësÌáôôtt:™™™9î~~~¶¹–Wôz=óæÍ£I“&¶\òìXï-Önnn¶œrEQÐétvsØ××—ÌÌLÒÓÓïzP)z4iÒ„råÊa±X¸rå 3gÎäÚµk :ô¶óA¯×ßÓ|¸›MW®^½ÊÇÌ!CìŒv+vcòööÆh4’––†ÑhÄ`0ä¸.“““1™Lèt:œœœlu;¬õò{]ª8gggÚµk‡¿¿?f³™cÇŽ1aÂêÕ«G«V­lóáæ9œ””„ÉdÊ—MöîÝË?üÀ„  ²{Îd2Ýr§¤¤`0Ðëõh4ÛÖh4øúúÚùæ{€»»{‘ÞXW‹.åEQˆç‡~`ëÖ­4nܘW^yooï<ó~VgéÒ¥ 6Œ2eÊÈÅ‘cD­úð¢( ‘‘‘|ýõׄ„„ðä“O2hÐ »jt7ãÈùºuëøä“OðõõµÍk“ÉT¤+ä©Ü?Ìf3GŽáË/¿$11‘‰'ÞÒ, ˜Ífþøãâââxã7¹F- &“éŽ×åÝÐh4ùŽüª>EÁl6³víZV­Z…‡‡S¦L¡L™2wL¿ÈÏ:žŸ÷F~øáÊ•+GÛ¶m1›Í¶9®ÎQ•›Q…ôôt~øáþüóO*W®Ì¸qã ¬¸]A£×ëùꫯèܹ3UªTáÚµk€¬ïÖù®bê°æEQ8uê|ðÅ‹gÞ¼yÔªUËö¼»»;NNN Û{JJ ¥J•$bj41›Í8;;c4ÉÈȰ{>{¤Éº“™Ÿ pëÖ­DEEñû￳~ýzRRR7n}ûöÅÕÕ233m»QÉÉÉ”(Q'''¼¼¼l»”...˜L&ÒÓÓsŒYQ4 ¶j‚*E ³ÙÌöíÛùä“OhÛ¶-K—.¥téÒ¶ç½¼¼Ðétvó!--í¶s8##FCpp0ÎÎθ¹¹¡×ëmÏ'''ãïÖ6«V­"33“>úЍ111¼ð ¼úê«xzzb6›mc¶X,9Æl0lsØúý¬×€µfö1ûøøäk“JÅq˜L&¾úê+þøã D¿~ýlUáÖóÁl6S¼xqÛ|¸yûúúâíí››[Ž{@rr²m®å…ÄÄDV¯^^¯gÊ”)€È¿œyã7xçwl÷‹Å‚““™™™dffR¡B4 vs8%%|}}Ñét·¼/^<_ΰŠãHLLdÞ¼yDFF2xð`úôécû-o7<==ñññAQ”|Ùy!<<œ­[·R¬X1ÆoûË—/çâÅ‹<÷ÜsxzzÚ9-- 777[ËWWW;õCrr2ÁÁÁhµZ<<<°X,F´Z­M¹–Ÿ1«8EQ8þ<³fÍÂÉɉI“&Ùm8ZçÃÍsØ:òcä•={öpæÌEáСC¶¹<}útzôèAÍš5msØj%''ˆ»»;îîî(Šb›ÃŠ¢ÜÒ¿È~ÐëõEº›nÈIIIÌŸ?Ÿzõê1}út[ x+•*UB«ÕrîÜ9ÛcGޱå]4lØË—/Ûòõ’’’ìrI5jĉ'l@Q;‡!·4nܘ±cÇÒ±cGÚ·ooKônݺ5•*U¢lÙ²øùùn{ÏÑ£G©T©...4lØ«W¯Údv¹$5âäÉ“¶Ћ/’žžn—Ã¥RtˆŒŒä«¯¾bèСŒ7.ÇÜkذ!ÑÑÑ6iLzz:·ÃÖ¢òåËãïïO¥J•ìž?zô(%K–´srKŸ>}xúé§iß¾=íÛ·§J•*xzzÒ¾}{‚‚‚¨[·.III¶ÍÌÌLNžø€Ç{ÌnãÁÝÝZµjÙ͇ãÇÛrúòkä…%Jð /н{wÛwss£zõê4jÔ777êׯo7æ3gÎàââBÉ’%)Q¢¥J•Êq]ZsúêÖ­Krr²í`49qâD¾Æ¬â8L& .ÄËË‹Y³fѼys»ç­sâæù`ÍóÏMWªV­ÊË/¿LçÎiß¾½ÍÁ~ä‘G¨^½º­XØÍöQéÒ¥ñòò¢fÍš ®\¹ˆÓbç_DFFÚR•bcc‰ŠŠº¥¼¾¨ FXóÁÕ«WÙ·oUªTaõêÕvÏuïÞZµjÌš5k=z4W¯^åßÿåõ×_ ]»vüðÃìØ±ƒG}”mÛ¶mëYÚ¥K–-[FïÞ½ `õêÕ”,Y’úõëçyÌ5kÖ´s¬>̲eËìÞ½›ÈÈHÞ~ûm:uêļyó8qâ¥J•â·ß~ÃÓÓ“¦M›:úçRÉ%ÖðâÅ‹¤¥¥±|ùr»çGŒAÛ¶mY´h[¶l¡gÏžüûᅵ;wŽwß}ùðÙgŸqâÄ Š/Îo¿ý†<ò†-Z°fÍjÔ¨ÑhdõêÕ´k×ÎVH /´mÛ–¶mÛÚþ6 œ?žáÇb -\¸7òä“OrôèQNž>>4oÞ<Ï6A^)_¾<Æ ³ý}íÚ5>ÿüsz÷îM5Ðëõ4mÚ”•+WR±bEt:¿ÿþ;:t ((ˆ† âââÂÚµk1b‘‘‘:tˆY³frøã?Ø·o7fÓ¦M$%%ѱcGGÿ\yF£¨ÉyfÏž=Ìœ9ó–ÏMŸ>ÆÂG}d“Ÿ´lÙ’çŸÌf3«V­bÍš5¶ÏðøããììLJJ _~ù%‡ÂÅÅwwwÆ—£êi~8uêo¾ù&«V­²` gúôé6¹rƒ xùå—m•`ÿýw~þùgœ1›Í<öØc 8WWWÒÓÓùúë¯ù÷ßqqqÁÕÕ•±cÇÚ ÷¨, ßÿ=«V­ºåóÖ\¨ßÿ_~ùÅ6üq €V«%--Í6´Z-nnn¼øâ‹¶ÐØØX¦Nj+P¢D Þÿ}Š/^`ßcÍš5lÙ²…E‹ÙÛ¼y3ß~û-NNN˜L&zôèÁSO=…»»;:Žï¾ûŽmÛ¶¡ÕjqqqaäÈ‘tèÐ<ð?üË—/RaÚ´iùR>¨8†ôôtæÍ›ÇþýûsüðC<<>ž·ß~›«W¯æx®K—.¼þúë$$$ðÑGqöìY[¢÷Þ{Š+ù³ ЧŸ~š§žzʶY“œœÌüùó ÅÙÙ///Þ|óM[ZVTT“&M²>«V­&L°)a¶lÙÂ7ß|ƒ““F£‘=z0dÈuS¦É«¯¾zËç^yåºwïÎ¥K—xï½÷ló¡FŒ?Þ6òcñññ<ýôÓ|ñŶuøÚµk¼÷Þ{¤¦¦¢( åÊ•cÒ¤I¶jÆÿþû/_~ù% *Î;3bÄ<==1 ,_¾œ?þøÃv2d½zõrôÏ•gT‡õ@dd$T®\9Gá—K—.MåÊ•sê‹…Ó§O£×ë©Y³¦­õÂý&99™³gÏâããc×ÒÁJtt4—.]¢|ùò·4ÔOŸ>Mjj*µjղ럦òpÅåË—©P¡Â-ó€N:Ezz:µjÕʑ뙑‘Axx¸­föJ~÷“˜˜Ο?O™2er´1Ò¨]»vçB¯×Û$rÕ«WWœÿaaa$%%Q»víkš^¯',, FsËù˜˜Hdd¤­åƒ*þI\\5jÔ°kM¢< Ãl6S£FyãÙïÙ[:¨<œ [N]õêÕï8òbܬmu 5kÖÌÑõ 55•ˆˆ<==©R¥JI{ll,çλí=@åá"%%…³gÏâééIÕªUs¬iù± îéé鄇‡ãææFÕªUslÅÅÅqþüyŠ/nÛ`ÊÎîE ÕaUQQQQQQQQQQQQ)”¨E—TTTTTTTTTTTTT %ªÃª¢¢¢¢¢¢¢¢¢¢¢¢R(QV•B‰ê°ª¨¨¨¨¨¨¨¨¨¨¨¨JT‡UEEEEEEEEEEEE¥P¢:¬*************…ÕaUQQQQQQQQQQQQ)”¨«ŠŠŠŠŠŠŠŠŠŠŠŠJ¡DuXUTTTTTTTTTTTT %ªÃª¢¢¢¢¢¢¢¢¢¢¢¢R(QV•B‰ê°ª¨¨¨¨¨¨¨¨¨¨¨¨JT‡UEEåsþüyN:åèa¨¨Ób±ÁåË—iÓ¦ îîîŽ> *9ûöícçμõÖ[ ÒÓÓñõõU핇’7Þxƒ—_~™âÅ‹c±XrØí*÷Õ2s0.\à­·Þ¢k×®<ñÄ|ÿý÷˜L&Ûó§OŸæé§Ÿ¦S§N<ÿüó,_¾œÏ>û ½^ÀÎ;yî¹çxôÑG0`ß~û-:€_~ù…¥K—2~üx:uêÄ Aƒøý÷ß™1c½zõ¢[·n|õÕW˜L&¾ýö[–-[Æ+¯¼BçÎyòÉ'Y¿~=S§N¥GtïÞï¿ÿ³ÙìèS¦RÄ8qâ}ûöeíÚµhµZ,XÀ¯¿þj{þã?æÝwßE«Õň#øçŸ0™L¼ùæ›lÙ²ÅöÚµk×2~üxœœœøí·ßm*Eˆk×®Â3Ï¡M›6üïÿcÅŠÄÇÇS¶lYÞzë-zôèÁÂ… qssãßÿ%$$„R¥Jñâ‹/²sçNvìØÀ«¯¾ÊÈ‘#U§UìP88˜ÀÀ@\\\¨R¥ ;œgΜ!66– &0jÔ(^xáJƒ ˜0aÞÞÞ\½z•o¾ù†uëÖ1mÚ46lȶmÛX¸p!“'OfË–-´hÑ‚ùóçsåÊöíÛǼyó3f ýõ~~~¼þúëÔ®]›72pà@-ZĹsç}* ªËî@œqrr²s³7&“)‡m}­ÅbÁl6S¹reÚ¶mk{¾mÛ¶vÜèªCªRÐøûûd—k§Óé8þ<®®®¤¥¥Ê“O>ÉÈ‘#9þ<Ÿ|ò ³gϦG+VŒæÍ›³bÅ 222èÝ»·-’ª¢R˜©Zµ* vª”ˆˆŒF#©©©œ8q‚‘#G2fÌΞ=ËìÙ³ùôÓOi×®eË–¥aÆüøã\ºt‰‘#GâååuÇÏkß¾=Æ ÃÍÍ™3grðàAZµjåèÓ ò‘™™É_ýEýúõ™0aT¬X‘uëÖƒ›››­ØR@@€M)ЧO^xá›MR¿~}žxâ ‚ƒƒéÞ½;ü1/¿ü2%K–`É’%¤§§ÛÞ?pà@yä@6×µZ-={öÄÍÍ=zðõ×_« •åÔ©S\¼x‘¥K—R»vm@äÁcÇŽÅËË \]]mA ///^~ùe:vìˆF£!::½^OãÆ)Q¢ãÇ'<<ÜV¨©C‡têÔ •cDDO?ý4ÞÞÞ<öØc¬^½Ú®Hå5Üà@š6mÊåË—m9v‹…¿þúËfà4mÚ”ØØXâââ©úkmïêêJÆ èß¿?Ï<ó C‡%33“¨¨(µ:ŸJ¡ÀZõ»ï¾cóæÍDGG³nÝ:¶lÙ‚F£!33“W^y…¥K—’žžŽ¿¿¿]ÔÔÍÍ>}úð÷ßsøðaž|òIG%•{¢qãÆøúúòùçŸIXXsçÎÅh4¢×ë5j¿üò :ÎfÜ[罇‡O<ñ«W¯æÜ¹s<þøãwý<777ÜÜÜ4hmÛ¶å½÷Þ³åA©¨iiiœúèßS²dIªU«f µoßž&MšÐªU+úõëÇ·ß~‹¯¯¯-ãæšZ­Ööœªl´G°:òåËÓªU+¦OŸNZZ&“‰ àéé @£F(Uªï½÷äÈ‘#9r„š5k¢Ñh4h_}õS§NeÀ€„††2{ölæÌ™ã详¢HÔþÙgŸåŸþáå—_¦T©R z÷AAA<ûì³,]º”Í›7c2™0 vs¸eË–øùùѤI›<dÓ&û‚îì쌷··ío'''<<«uëÖ´nÝÚöw±bÅxçw€œ²„N:Ùtõ 2‡÷Þ{ÏѧK¥ˆâîîNË–-oû|éÒ¥íZÝX¹té?ÿü3žžž4kÖLÝeW)r”(Q‚Þ½{ßò¹ *P¡B…Ÿ?žeË–Q®\9êÕ«ç诠¢ˆ\±ÿþüñÇL˜0ž={²ÿ~»v`Z­½^Odd¤]nŸŠJQ£F´iÓ†·ß~›gŸ}–””–/_NPPWWW‰ŒŒ¤|ùò9ÞoU$üúë¯T¨PŠ+rðàA‚‚‚¨Zµª£¿^‘ÃyêÔ©S=ˆÿ:Z­¼¼¼ì òŒŒ -Zľ}û0›ÍüüóÏ?~œ·Þz‹²eËÚ^çîîN@@À]‹r¨¨5¦NÊÆyã7ì6[TTfÞxã víÚÅ»ï¾KãÆ=eË–¥zõêìܹ“íÛ·ãëëË;ï¼c“»püøqþý÷_›šF«ÕÒ¼ys[†Ùl¦lÙ²Ô­[gggEÁËË‹N:áää„¢(8;;Ó¨Q#‚‚‚prr¢I“&¢º©U«–­ŽÙl&00&MšØ®TQɶBH6l !!—^z‰úõëÓ¸qcJ—.ÍîÝ»‰ˆˆ ]»v6[¾qãÆ¸¹¹¡Ñh¨R¥ þþþlذíÛ·c±X˜}:ׯ_·sX?üðCöîÝKýúõÙ¸q#7näý÷ßÇßßÿ–DZX,”-[6GôÂÌ•+W¸ví<òˆ£‡rÏ\½z•‹/ÚZƒ.^¼ÈáÇöùaaa¼ÿþû<òÈ#6‡511‘I“&‘@¥J•øùçŸéÒ¥ o¼ñÆmc0h֬͛7wØwÉ-QQQÄÇÇÓ AGåž9sæ 5kÖtôPG’œœœ¯c8Äa5™L¬^½š£GRªT)Ûã§OŸæŸþaܸqtïÞsçÎñÜsϱwï^zöì鈡Þ7š4iRädªõêÕ+rcv$§NbÙ²evíØ±ƒÈÈH>ÿüsªU«ÆüÁG}Ä Aƒ¨P¡‚£‡\`¸»»Óºuë"©‘Ö¶hÑBmÃpX,þþûo¶lÙb÷تU«pwwç“O>ÁÃÃÿýïüôÓO4kÖŒbÅŠ9z؆¿¿‘2Š|}}Õ~ƹÀdú?{gVåÝÆñÏ9t·ˆ¢ˆ-v·³{›1síæÞu:çzSçÂØf.¬éæìYsnsvw£ŠˆJ÷9œxÿ¸9„„€À}>×Å¥œxÎï<köù… ؽ{7&L oß¾ó¿ÿýÇÓ¯_?s/»ÔðññÁÛÛÛÜË(UªTÁÓÓÓÜ˨4hµZ~úé'ÂÃÃs&víÚÅÕ«W™;w.µk×fË–-|ûí·<öØc÷•­RµjÕJ•]¨[·®¹—`ÊÝû08p€ÿþûGy$×s§NÂÇLJN:aii‰ŸŸ:tàÀæÞO¥Ž••U¥)•¬Ìk6éééÌ›7>}úäzüèÑ£´oßžÚµkciiIûöíñõõåðáÃæ^r©¢R©°¶¶®T}•¦5+A™¢Ê¢E‹reôz=ÇŽcÀ€¸»»cggÇÀ‰'$$ÄÜK.UÔju¥©¨Ìk6F£‘}ûö±{÷nœë¹“'OR½zõ¬W­Zµh×®Ý}g«XXXTª ce]³¹Ðét¬^½½^OÓ¦Ms=wäÈ:tè@­Zµ°´´¤C‡øøøpôèQs/»T©ŒÇ‹¥¥åX/wË,>>žÅ‹3räÈ<¥¥!!!888d•ÔX[[S§N¬ôwA ÒÓÓÁ…,ŒF#Æ,BE¬Zµ † –ë¹   |||²ŒF<==¹téR¡ÛÔëõ¤¥¥)ǸB¦#NWî"©©©,]º4OOŠÑhäòå˹"ðþþþhµZnÞ¼Yè6322HOOW;r‘žžn¡¢ØØX–.]ʨQ£òô)‡„„àèè˜ËV©]»ö]m•ŒŒ EÍæÍ›yõÕWó´ÝQ­Zµ,gÎÓÓ‚‚‚ ÜžÉîÒétåþ]*.:FsÏ÷öruXÓÓÓY°`þþþôîÝ;ß/¥R©²2¦ŒGRRR¡ÛgïÞ½¤¦¦–ç×Q¨ÀèõzNž<ɉ'ÊýâyìØ1þøã^~ùå<ýL¨Õê¬Ì£)R–œœ\è6£¢¢Øµk—¢†­Ezz:{÷î%88¸\<½^ÏüATTO<ñDžè´N§ËU‰ammN§#==½ÐírèÐ!EEU!Û·o'""¢\?Ód«Ô©S‡ž={æyÞt7Ù*¦Ìua¶ŠÑhäܹs–ïT¨Ð$%%±}ûö»Ú¹eñ¹óæÍcàÀÔ©S'ÏóùÙ*…Ú*𥔠"^‘˜˜˜ï{Ôjõ]Û 4h@»ví”¶…\tïÞ½ÜÅ ·mÛÆ:t(qqq$&&’‘‘qO¶ŠJ¥" ÀlŠõ GGGºwï^®B†… biiIÇŽ¹yó&iii¤¤¤póæÍB‹Âl+++ÚµkWéúžÊ__ßRÑ)×"è={öÀG}ˆ4s||<¯¾ú*}ô...„‡‡£Õj±¶¶F¯×“K˜)?,,,pppPzϲP©TØÙÙaggW®ŸÈÕ«WIHHà¿ÿþË*ó™={6ØÙÙe•¸YXX’’BJJJ¾ΜXZZVåZ…òA­VãààPî½ÂGŽ!::š dÃo¿ý6#FŒÀÅÅ%W%@ll,VVVª§š°±±Q‚Ž yptt,÷~­Ý»wç²U¢££ILLäÕW_å“O>ÁÅÅ…¨¨¨,[E§Ó{W[ÅÆÆ¦RßS({,,,ptt,×@]BB‡"&&†‰'pýúu,--‰ŽŽæë¯¿ÆÍÍ-« I­V“’’Bjjj¡Ê´*• {{ûJתP¶X[[cooÏÓ Êõ.ðꫯòøãgý¾eËvîÜɧŸ~J:u²f>]»vzõꑞžÎñãÇ+ÕØ…›¦M›òã?f•5fddðä“OòÔSOѵkWœ9tè)))8;;sãÆ ÂÂÂxæ™g̽t…"1`Àš5k–õ{`` Ÿþ9|ð5jÔàèÑ£û¬b«(T ÒÓÓ™6m§NÂÁÁ­VKíÚµ™0aÞÞÞ$''³`Á8e«Œ=šáÇ›{é (%VDÒétüñÇ|öÙg¤¥¥1lØ0ÆŒCóæÍÙ´iŸ|ò ñññ¹ÞsíÚ5V¬XÁã?Î’%Køþûï±±±aÕªUhµZÂÃÃY¸p!ƒféÒ¥L˜0•+WrâÄ sï'…"³zõjŒF#ßÿ=K—.eèС¬Y³†ððpŽ=ÊÆ™0aK–,¡_¿~Ì›7èèhs/[A¡H¤¤¤ðË/¿Ð¼ys~úé'~øáÚµkÇ’%Kˆeݺu\ºt‰Y³fñÃ?àïïÏ?ü@RR’¹—® P$BCCY¹r%O<ñD–­baaÁêÕ«ÉÈÈàúõë,Z´ˆGy„%K–ðÖ[o±bÅ NŸ>mî¥+(‰#GŽpôèQ^{í5–/_žå¼îÚµ €Ã‡³iÓ&&NœÈ’%KèÓ§b«(˜•;¬111¬_¿ž§Ÿ~šÙ³góüóÏóÜsÏ1qâDæÍ›ÇÅ‹9pà@®÷$$$àääÄÈ‘#±··ÇÇLJFŠF£áèÑ£xyy1pà@lllhÙ²%­[·f÷îÝæÞO EæöíÛŒ=šjÕªammM‹-°´´$,,Œ}ûöÑ®];Zµj… ýû÷ÇÃÚ{Ù E"##FØ1cpuuÅÕÕ•V­ZÃíÛ·Ù·oƒ¦V­Z¸ºº2jÔ("##¹|ù²¹—® P$âããqqqaĈØÙÙeÙ*W¯^E«ÕräȪV­Ê€°±±¡uëÖ´lÙR±U* 7oÞ¤M›6ôìÙKKKj×®MÍš5³®Óûöí£C‡´lÙ €››‡6÷ÒPJì°¦§§àAƒppp@¥R¡R©°²²¢fÍš4oÞœK—.åzOãÆùþûï³ú<âãã ¢nݺØÚÚrùòeœñôôÀÚÚšúõësáÂsï'…"óÉ'ŸÐ£GT*F£‘ÀÀ@ þþþâçç‡ ^^^x{{hîe+( ¾ÿþ{üüüi 9{ö,UªTÁÝÝK—.Q¿~ý¬×שSFÃ7̽t…"Ñ´iS¾ýöÛ,[%..Ž   êÕ«‡µµ5AAA¸ººâáርR¯^=ÅVQ¨4 4ˆ·ß~;«'5""‚ððp5je«X[[b«xzzrñâEs/]á¥Ä«……ÖÖÖ\¹r%Ïséé鄇‡ãââ’ëq[[[ªT©B||<Ÿ~ú)}úô!,,Œ±cÇbeeEjj*Y7 µZ££#111…®%::š 6`îý©PAÈÈÈ`ÇŽìܹ“ŒŒŒrýl///ìììØ²e 䫯¾bĈT«V””¬¬¬²˜lll°±±¹ë1~íÚ5V¯^M\\œÙö©BÅ"%%… 6pêÔ)ôz}¹}®……ÞÞÞèõz~úé'úôéÃÊ•+yá…pqq!555+ àèèHFFÉÉÉ…n÷èÑ£lÙ²Ng¶}ªPñX¹re¾vFYb²UâââøøãéÓ§Œ3&_[ÅÂÂGGÇBË%F#‡ÊSy¦ð`ÇÊ•+‰-×ÏurrÂÍÍ›7oòøãóè£R¯^=ºwï¥Áa²Ulmmïj«hµZþúë/‚ƒƒÍ¶?*/^dË–-h4š{ÚN‰V777Z´hÁìٳٲe iii¤¥¥ȼyó¸}û6;wÎ÷½öööŒ5Š©S§âììÌÒ¥KIKK+ñ—ðôôdÈ!yd…+++zöìI=r©Þ•'­ZµâÓO?eذalÞ¼™sçΕx[~~~Œ9R¥…ƒƒC† ¡E‹fQn´²²¢wïÞL:•N:±dÉnÞ¼YâíµmÛ–Áƒ+J« ¹=zt¡ãóÊFÍÔ©Sqpp`éÒ¥¤§§øú”°U*:t S§Nfù. 777F»»»Ù>ÿ­·Þâ£>"88˜7–x[ÖÖÖ 0€ºuëšå»(TL6lÈàÁƒs²KB‰->øà¾üòK¾þúkÞyç@Ø 0yòä\ea·nÝ"%%ÀÝÝñãÇóòË/coo^¯G§Óaii‰Á` 99sïo…"¡Ñh¸víÕªUËúiÚ´)ãÇgçÎ888‘‘Á`ÈRWÕh4Yå• ¤¤$"""ð÷÷§víÚÔ®]›-Zлwo.]º„½½}®Hjrr2666¸ººš{é E"**ŠÔÔTüýýiܸ17ÆÕÕ•_|‘W_}{{{nß¾e«èõzÅVQ¨4èõznܸ ÞÞÞ´iÓ†V­ZÍÚµk7n\–r°ÉVIOOG«Õ*Ǹ‚Ù(q†¤—éÃ?dÁ‚üðÃÌœ9“… òí·ßÒµk׬R{÷îeÚ´i¹Ê×rfš4iB||<‘‘‘€ÿçÏŸÏãø*(TT’““™:u*§NÂh4rŒ›"ï-Z´ 888+JÅÍ›7©W¯ž¹—® P$®]»Æ'Ÿ|’u†ì븅…Íš5ËUMpñâE,--©Zµª¹—® P$vïÞÍ×_] ­Ò´iSbcc‰ŠŠÄV¹pá‚b«(T t:+V¬à÷ßÇ`0R³ºÅd«˜‚‘‘‘DFF*ÙS³qO«N§ãرc9r„nݺ1pà@bccù÷ß¹~ýzž×ûùùqáÂÖ®]KXX—.]báÂ…<ôÐC8;;Ó¾}{RSSùóÏ?‰çСCœ?ž˜{?)( ,,,X²d AAA„‡‡³jÕ*nß¾M÷îÝéÑ£.\àðáÃÄÆÆò矒œœL=̽t…"Q­Z5n߾ͯ¿þÊÕ«W¹rå óçϧN:4lØÞ½{óßÿqéÒ%nܸÁš5k²ªj*µjÕâܹs¬[·.ËVY´h=zôÀÑÑ‘Ž;’””Ä_ýE||< 00þýû›{é wÅÆÆ†š5k²uëV¶oßÎ78yò$ëÖ­cðàÁôèуsçÎqôèÑ,[%55•‡zÈÜËWx@)qI°^¯gõêÕ,^¼˜æÍ›c4Q©T¤¤¤°~ýzöïßÏ_|‘+ªÞ´iS^ýu~ûí7Ö®] €··7¯¿þ:ööö888ðú믳dÉvïÞN§ãÙgŸ¥aÆæÞO N—«(%%½^V«ÍzÌÎÎÎl=!&LàÛo¿åÃ?D¥RaaaÁøñãiܸ1:ޱcÇ2þ|,--Q«Õ¼óÎ;ʰùJŠÁ`Àh4©‡499µZ}׿µÑhD£Ñ––†F£Éº¶š¢ß \¾|///³”’›*k~üñǬÙVVVLœ8‘êÕ«óÈ#põêU>üðC,,,pppàÝwß½çþ…ò¢Y³f¼òÊ+üú믬Y³€ªU«òÚk¯agg‡½½=¯¿þ:K—.eÇŽèt:ž{î94h`î¥+(‰Gy$+ØhÒùèÔ©#GŽ$Ã:zôhæÌ™ƒ¥¥%Š­¢`VJì°Þ¾}›Õ«W3vìXžxâ‰,cê±Ç£eË–¼ôÒK8p€aÆe½ÇÆÆ†‘#GÒ­[7nܸ]–L¼‰~ýúÑ¢E ®^½JõêÕ©Q£†¹÷‘B ‰ŽŽ&>>E://¯\eâZ­–¨¨¨bý¯^½Ê²e˸xñ"µjÕÂÒÒ’ˆˆ²> Ä€öððÀËË+Kõ®¼hܸ1sæÌ!88˜ÔÔTêׯŸ%–daaÁ¸qãx衇¸}û6 4P„”*ƒëׯg)NkµZ‚ƒƒ9~ü8)))T­Z5k<—^¯ÏU.«ÑhˆˆˆàæÍ›XYYáëëK­Zµ²Æwå$11‘Ë—/sãÆ T*ƒ;;;ÒÓÓ1 Yýržžž$&&’€:t(·}aaaAÏž=iÙ²%¡¡¡Ô¯_@Ú>ø€‹/¢Õjiذ¡bä(T*lmm=z4Ý»wϲUêׯŸKÀoÀ€Y瀯¯/¾¾¾æ^¶‚B‘qttdÒ¤IܸqƒÈÈH<<|KKKlmm©Zµ*IIIØØØP½zujÖ¬I‡°²²Êr½¼¼ðõõÍUCdd$IIIXZZR«V-<<<¸uëׯ_ÏR]4agg‡­­- ܾ}???ž}öÙ"3¼½½³œ^…üÐétìܹ“… R½zu:wîLµjÕ°µµ%55•„„¬¬¬xúé§ ­Ñ²eË"fÍš5Keíööö4kÖŒ«W¯*£`î[Jlåxyy1xð`¾øâ Ž?N×®]±³³#44”õë×зo_s?…bžžNHH—.]âøñãYò~ýúñå—_âîîŽZ­F­V£R©²²›…͞ˉ‡‡yW2ê åAbb"!!!œ;wŽ3gΜœŒV«ÅÅÅ…©S§R«V-%¸¡       PÁ¸§ ë¨Q£°°°`õêÕ¬Y³;;;èСï¼óŽR*S 0•0nÞ¼™uëÖaiiI½zõèÖ­5kÖ¤V­ZØÙÙ™{™ %Ât|9r„9sæàââBƒ xä‘GpqqÁÃÃOOOEHA¡‚`00 DDDV«ÍUy£    P10èõz.\¸À­[·hܸ1žžžY-|QQQ¸ºº’ššŠ——×=}V±ÖÄÄD¢££ñññÁÎÎ777ÆÏøñã C«ÕâáᡈÈT"Ž?Îòå˱²²â½÷ÞSʸî+Ο?ÏÂ… IHH`âĉ4mÚ4Ï|hó Õj !44”ØØX222 Êêí¶±±A£ÑàââÂsÏ=gîå*((((d’ššÊÑ£Gùí·ßHII¡nݺ,]º”””lllhÚ´)5jÔàôéÓ\¸pQ£FÝÓçËaMHHà×_%..ŽöíÛÓ©S'<<<°µµ-µ¾,…²E§Ó‘˜˜È™3gØ¿?'Ožä±ÇãÑGU2© ÷ F£‘£G2kÖ,~øa ¤(*(”&1­V‹^¯'::šððplllðõõ%**Š˜˜®_¿ÎþýûQ©T4oÞkkkz÷_–Bll,›7o6÷×RP¸g4 Z­–””‚ƒƒ9wî\–º¼RE P‘1Û»~ý:ÿüóÁÁÁ„……áîîÎСCéܹ3...èõz’’’°··Ï%È{òäIîi ÅrXkÔ¨ÁG}Ä•+Wسg³gÏF­VS³fM:uêDݺuqvv6÷~U(€Û·oóû￳gÏüüüèÒ¥ /¼ðÂ=§é*§NbêÔ©¼÷Þ{tîÜÙÜËQP¸ï9{ö,GŽáÌ™3¸¸¸pûöm,--ILLÌ3Û××WWWÞ~ûm6l¨ˆ†)Ü·$%%qôèQ¹|ù2z½Fƒ››µjÕâСCœ={–N:™{© ¹Ðh4DFFrõêU®]»Æ©S§HLL¤[·n<þøã4lØGGÇ\ï±°°(³ä@±ïjµšºuëR»vmRRR¸uëgΜaÓ¦Mܺu‹æÍ›ÓºuküüüpqqÉ3òF¡üÑjµ\¸pY³fQ¯^=fÏž··7æ^š‚Â=“––Fbb"111\»v‹/rèÐ!>üðCÚ´icîå)(Üw¤¥¥uÎíÙ³‡¨¨(zöìÉã?Žƒƒ¶¶¶8::âìì¬Tï(<0èõú,¿={öpøðaüýýiÞ¼9Ï>û,®®®¸¹¹áèè˜ÕžÌÉ“'ͽt…ƒÁ@JJ ÉÉÉÄÆÆrâÄ BBB¸xñ"¶¶¶øøøP«V-ÆŽKýúõqqq1Ë:KÖT«Õ899áääD:u:t(7oÞäèÑ£lÙ²…¤¤$zõêÅÀÍòÅ„øøxæÌ™Ã™3gxå•Wèܹ³¢„ªp_ ÕjÙ¸q#»ví"###ëÂZ§N&OžLƒ ̽D…JORRz½WWWôz=çÎcÑ¢E¤¦¦booOݺu0`;wVS…ûšôôtvíÚELL ¨Õj´Z-ÑÑÑ€d¤®\¹Â­[·°··§[·nÌœ9“êÕ«:MÁÊÊJI (”;¡¡¡œ8q‚óçφ *•ŠúõëÓ¾}{^|ñEªT©Rat?Jì°jµZT*U–ó“žžŽV«¥Y³ftèСÂ|Á £ÑÈ­[·8räQQQ öíÛGçΙ3gŽ¢Ú¬p_`4¹yó&?ýô±±±<ýôÓÔªU ggglmmͽ<…JORRçÎcïÞ½;v ƒÁ€½½=–––¤¦¦òÄOйsg”**…‚›7o2cÆ ŒF#~~~ÄÇÇr?ÊÈÈÀÞÞ___üýý©[·.>>>ØÚÚy쟂BYA||</^äâÅ‹a0hذ!­[·æ©§žÂÉÉ ;;» {ÜÛaÕét=z”íÛ·3hÐ ZµjEFFß}÷;wîD¯×Ó A^}õU5jdîï÷@qåÊ>üðCêׯ——L˜0&Mš(…û†sçÎñÕW_ѪU+Þ}÷Ý<= %çìÙ³,X°£ÑH×®]yâ‰'ðôô$22’[·nQ·n]EÀLá¾D¯×sãÆ âãã¹~ýz–RRR›7o¦W¯^Œ;V¹ç(TnݺÅüÁ®]»¨R¥ 5jÔ I“& 6ŒÚµkWªŠËb;¬þù'_~ù%5Â`0°iÓ&Ö®]ËÃ?Œ¿¿?ÿüó|ð ,P²zå@zz:ÿý7+W®äù矧G¢¼Ä`€ädHO‡ØXHKƒÛ·áàA¨S4ðóµΜKKpvpq‘ÇÏž…-ÀË ÜÜ 1._OO¨YSÞ²­¸8°³GG¨__¡1Íe\²d AAA¼øâ‹tìØQkQP(%Nž<ÉæÍ›¹|ù2O<ñÝ»wÇÚÚ:+Ò^³fMe€Â}Ãõë׉ˆˆd<ÇÉ“'9uê†zõê¡R©¨Y³& &MšD³fÍ*„m¥ Pz½žk×®̱cÇ8{ö,:t`îܹY1•5U,k/::š+VпÞ|óM\]]IJJbÇŽ4oÞœ7ÞxWWWÚ·oÏK/½DPPâ°–!†7²eˬ­­yýõ×騱c™î¹sP¯ØØÈï·nÁÿ““8VV`k 'OÊ¿Z­8™5kBß¾0|8X[Ãþýpä´m ½z½½8®ë×C•*Ц8 û÷Ö-⤶l)ŸW­„†Â€ò¿ÿ.íÍ›­[Cƒ°s§#GÍý§R(!GåèÑ£œë±jÕªQ­Z5Ž;F·nÝÌýï+222¸xñ"›7oæÀtìØ‘?ü°ÔfôzÇ22ŒFˆŠ‡ÒÖV²¥×¯KF´iSù·^=8~\ïÔ Þ~[2¥Q¿~ÞÇêÔ¡Có>>j”¬£^½ìÇví‚_….]àý÷ÅÉ5!"’’ÄQ¾pA[i£I2†Ù³gsþüyzõêÅ;ï¼C:u*UùŠ‚BEÂÔû½hÑ".]ºD=¸té7n¤mÛ¶¬Y³F9¿î[RSS 毿þâðáÃL›6† š{Y %"55•½{÷’ššŠ‡‡:Ž™3gÒ¡C~ýõ×û2èR,‡5%%½^ŸkÖê•+WˆˆˆPÆG”1F£‘ôôt–.]ÊÞ½{>^f(EΟ?ÏÌ™3©S§?üðC® AAhµâhΜ)ÙÒ€q05¨ZnÜG¶S'qL«UƒmÛàÂxøaÉjZXHï8:BEÐÔR*+?ƒ={öðã?âââ‚Ñh¤FÌš5 s/OA¡R‘˜˜È¶mÛ8vì)))F´Z-]»våÇÄÃÃÃÜKTP(t:lܸ‘“'OâååE:u¨W¯cÇŽU‚Ÿ •šŒŒ 6mÚĆ èÝ»7£G¾oÓü(–Ãêç燷·7K—.ÅÉɉèèhöìÙC¯^½P«Õèõz’““Ù¸q#ñññåÒOy?c0ˆgëÖ­lذ‘#GòðÃ8ë.#vìžÏfÍàÏ?% Ùµ+¼ü2¸ºJÒ`€”@²¶__é…Ü%· eN§cåÊ•lÚ´‰wÞyWWWìììðôôÄÞtP*((Ü­VKPPsæÌÁÓÓ“Ç{ ðððPf¤*Ü·˜l¥~øË—/3pà@ÆŽ‹ŸŸŸ"’¤P©1 hµZÂÂÂøå—_ˆçÝwß} §Ëauttäå—_æÃ?dèСF5jĈ#°°°àèÑ£Ì;— .ðâ‹/R»vms¿J‹V«eõêÕüóÏ?øûû3kÖ¬B££áÊX³Æ“ìg¯^"D”ŽŽ TÄ(˜“””~ýõW<ÈÌ™3©Q£†¹—¤ P)IOOgΜ9;vŒ—^z‰Î;+ý¨  {÷îeîܹtëÖï¾û—ÂÄ3*ÑÑÑìß¿ŸãÇ“˜˜Hll,½{÷f̘1ìµ½Ø3!š5kÆ’%K¸páƒFe)vFêÖ­ËsÏ=G»ví¨Tui¡Óé8qâË—/ÇÁÁ‰'R¯^½÷å­[2êå믡wo˜5Kz=+àÌ_@"†aaaüüóϤ§§óÕW_)jâ % %%…‹/òã?R»vmfÍš¥”=*Ü÷Fâãã¹pá¿ýöz½ž7ß|“víÚ=°Æ¼ÂýAPP[¶láàÁƒ4nܘ.]ºP»vmœñððx +Ší°ªÕjÔj5ƒ˜˜nݺ…——íÚµ£]»væþN•–ääd–,Y±cÇxøá‡>|x‚J2Jfñb)û}ÿýÜsI**ä»ï¾£OŸ><ñÄJ鯂B1¹yó&Û·ogÏž=X[[Ó§OFŒaîe)(”9Z­–}ûö±xñbÜÝÝ2d]»vUJÞ*5ƒƒ2{ölzõêÅwß}§ï ØîÍ™3gxï½÷HJJÂÊÊŠ””† »ï¾[¤ÈVll,›6mâĉèõzºuëF¿~ý²šnÞ¼ÉæÍ›9sæ ~~~ 6ŒÚµkß×µÚƒ   ¾ÿþ{œ™5knnnù:«:ÌA={ÂÃaÚ4qTñ¡ŠƒV«åøñãlݺ•7nÀ€hܸ1ƒV¯^Mdd$-Z´`àÀøøø˜{ÙeŽF£aÍš5lݺ•I“&Ѽys,•K¥$%%…;v°{÷niÑ¢Æ £jÕªdddpòäIÖ­[‡^¯§}ûö 0GGGs/»Ò£×ëÙ³gsçÎ¥ÿþLœ8‘êÕ«+ÆzÃæÍ›9~ü8ƒ‡zˆ~ýúe•›Þ¸qƒÍ›7söìYjժŰaÃð÷÷¿¯msÇáÇٴi–––¼ûî»4hÐ[[[s/­ÒÌßÿÍ©S§pvvfðàÁtìØ[[[ôz}–­EË–-8p R UhµZ6lØÀÆyÿý÷iÚ´éI-ˆb]Yu:‹-ÂÊÊŠ?üo¾ù†þýû³fÍ.^¼x×÷§¥¥1þ|–-[F@@7æÇdÑ¢Eh4¾øâ ¶oßNçÎ gòäÉܾ}ÛÜû©LÙ½{7“&M¢sçÎ|öÙgxxxä{ÓKIÍ›aÃ-óþûP·®â¬V4Ž=Ê;ï¼@ÿþý9uê}ôaaaܾ}›÷ߟ¨¨(:vìȶmÛ˜9s¦¹—\椧§³hÑ"vîÜÉçŸNëÖ­gµ’¢×ëY¿~=_ý5U«V¥S§Nlݺ•o¾ù†ØØXNŸ>ͧŸ~Š££#õë×gñâŬ]»ÖÜË®ôèt:V­ZÅ?üÀ{ï½Ç¸qã¨_¿>Š“Tʤ¥¥1oÞ<–/_N“&M`Á‚,^¼­V À”)Sرc;wæÚµkLž<™èèhs/ý¾C§Ó±gÏÞzë-öïßÏ‹/¾ÈÌ™3iÞ¼¹â¬Þ |ôÑGìØ±ƒž={âááÁG}ĶmÛ²l•èèh:vìÈÖ­[™5k–¹—}ßa0øã?øã?˜2e Íš5SœÕ(–ÅMxx8Ï<ó ýû÷G¥Ráããùsç8{ö,M›6-ôý!!!ìÚµ‹iӦѾ}{š4iÂÛo¿Íرc¹rå ÁÁÁLŸ>¦M›2hÐ ÆŒÃßÿÍSO=eî}UêÄÅÅñóÏ?sêÔ)¾øâ òͪ¦§‹âïï¿CÏžâ¨*NjÅeíÚµtêÔ‰O>ùKKKúôéÃË/¿Ì¦M›²z‘?ûì3ÜÜÜà7ÞàäÉ“´lÙÒÜK/5ÒÓÓÙ±c7nD¯×E›6m˜;w®bdTr’’’X¿~=Ï?ÿʼnvµhÑ‚%K–dýž’’ÂÆiܸ1„††bgg‡³³3ÖÖÖÔ­[—uëֺ݌Œ bccñöö®ð©ôS§N±hÑ"ŒF#O<ñ:u*𵩩’Y=r>úÊ]©ý(°øŠR8RÊ£ÑHbb" ånàMŸ>=×:8@dd$cÆŒaþüùôë×ë̹§§'^^^ºMFCtt4®®®º”699™‰'Ò´iS.\¨ôÖÝ#qq0e ¼õ–ôªçD¯×KJJ F£±ÜÖäææÆÒ¥K³~×jµlݺOOO|}}¹zõ*ÕªUËz¾víÚhµZ""" Ýnrr2qqq¸ºº>ð”mÛ¶±eËbbbhÓ¦ ‹/ÆÉÉÉÜË2 ÑÑÑY-CåE«V­X´hQÖï&[¥iÓ¦ØÛÛŠƒƒC–­bccC:uؼys¡ÛMJJ"))éý[Fll,kÖ¬áôéÓ¤¦¦0nÜ8ºuëv_—¼ët:¢££Ñétåú¹Ã‡gøðáY¿ÇÄÄðÏ?ÿdU?†„„döòòÂÃÃ˗/¸MƒÁ@\\éééJ%U!$$$0wî\®_¿ÎôéÓïû‘~©©©ÄÅÅÝó}½Ø–¯Ñh$--ÄÄD@Œ ½^F£ÉzÌ„ƒƒC¾dFFaaaüðÃ1qâĬ ~˜zF "))‰ãÇS«V­ }ÖjµÌ›7nݺ1|øpò}]F„„À¢EТ…™œU€$ê¥Ò9¬z½žÀÀ@Í&ÃöíÛYºt)]»v¥[·nÌŸ??ß×fddÜu[G¥K—.ÚØ9sæ :Ž'Ÿ|RqVKÐP8sbbò:¬&q¯°°°ruXMèõzn߾ͲeËø÷ßy饗¨W¯^¾¯5 w5È®\¹ÂéÓ§éÒ¥K…Ê”%:Ž­[·²fÍž}öYš7oŽ››Û}m°ßC‡qëÖ-³|vFF¡¡¡üøã3qâÄBmŒÂl£ÑHpp0W®\¡yóæfù> £ÑHjj*û÷ïç—_~¡U«VŒ?///ÜÜÜ ´‘î'RRR8tèÙÔòÓÓÓ9qâK–,A§ÓñüóÏúúÂlNÇéÓ§iÒ¤ ¾¾JiÞ˜Ú£¾úê+\]]ùâ‹/ððð0÷²ÊœÈÈHNž}úššZîɱZ¸p!µk×fêÔ©´mÛ¶@§ÔÂÂ"«ª  š5kF÷îÝËõ{T46lØÀêÕ«ùæ›o”òéL|×ÌeYžžÎÂ… Ùºu+:t`ƌԭ[·Ð÷f«¨T*Z¶l©8«™èt:vïÞÍüÑhd„ ¹J°\\\ýôS¬¬¬˜3g5kÖÌe³›lN‡¥¥%±±±ÄÅÅÝZåÁ` >>ž«W¯²oß>8@«V­˜>}:þþþ¾}±"R,‡ÕÕÕ• &”øÃ.]ºÄæÍ›Y°`yžoݺ5ëׯ'44”&MšžžÎ±cÇ;v¬¹÷Ó=ó矀¿¿¾ÏÂÂ…ðöÛàï¢Ìð¦˜ÃÊ  !R¶ìÌý9{VRÒfŒb/]º”V­ZñÌ3Ïä¹(µoßž7’’’‚««+ááá„……eõTV222øóÏ?6lØ]3i E@§Ã°e+ÛÞO ÎgO ×Cú”Ø$„¯/¼ø"Ôª…êÀ®\AUŽA‚¤¤$~ùå^xáyä‘\Ï©ÕjÚ¶mËþýûyôÑGéÛ·µµ½kvêA#&&†É“'cggG‡èÞ½; 6¬ð•B/^dëÖ­,X°€Fåy¾M›6lذ°°0HKKãøñã÷å4ƒ²`ýúõF¾üòKÅQ5Û·o'::š9sæä›tjß¾=þù'©©©8;;sýúuÂÃÃi×®¹—^)Ø·o‹/ÆÁÁV­ZñÕW_áçç÷@·wÜ+%ÊG ÂÃÃ9yò$ÇçöíÛ8;;S»vmºtéB:uò-¸xñ"QQQ¼ð yÊ>V¯^M³fÍhР3gÎdèС½½=ééétïÞ‡z¨Ô>#$DÆÿev (+++:vìXèkT* 4à“O>©ô¶JYÇ–-[ذaäÝwßUZ;Ê€b9¬iii,Y²„fÍš1iÒ$¼îȸººòâ‹/âêêÊ?þȨQ£ ìÙ,ŒûáÄ0œ?žµk×2mÚ´\ª©z=LŸ.ÉÀ©S¡Â …EÒà²Æ`€„ض üüÀTZ –zx*D ð¿ÿIIäY`p;Ÿí5h ³@bb*dص2bLÁ©yóæqìØ1¦M›F:u*å9»s'4lx‡Ãj0È1giy÷“S¯—Œ~Q²µkáèQøðÃìÇ:w–¾Ô¸8ñž3Ñéä0wpøË¦Mкµ¹÷XÑP©TŒba "##ùöÛoÉÈÈàwÞ¡M›6•úüWÈæ~°UʃÁ@XX_ý5L˜0—ÌÙ|...¥zmˆŠ’ËuJй¿õý‰r­*£ÑHll,Ÿ}öNNNL™2…† *ׄ2¢XWÐÐP"""xóÍ7ó8«&¬­­yøá‡Y¹r%(‘ÃZÙÑëõœ;wŽo¾ù†'Ÿ|2ØÈòår}ö٠쬄#ÂF€’Ì5¤ôÑÕõÇÃ7ßÈàÙ.]ä1gg4Hþø+󵦾’]­™ÏöÜÝá…PED˜{/ÞWÄÆÆ²gÏ~ÿýwúôéÃÒ¥K+mRF†9yªi÷ì÷ß¹îÿýO^‘‘r|šÔn““%ÛÿÄPÔþÌÁƒaøðÜ烣#4nLzºœ2¦øPR’d  Q# r¥¤dþ ›ÐÐPÖ®]Ë1bÆ SzUî{bccY½z5;vìàé§Ÿ¦ÿþeêô$%I1ÖÕ«§67z½Ä/ŸåþÆh4röìY¾úê+ ÀèÑ£ó´A*”.År—bbbÐétyf«æÙ¨¥%îîîDEE™ûû•+)))ÄÄÄðóÏ?ÅèÑ£éÓ§OÖóz=lÝ*NêG‰Za‰FŽŽÑ@ζDF®Ä9OLƒA®Ðwf™22Ä —FÁo¾‘LÒ°w/tè %{{Q›š>jÔ×ÞIpíŽÇ€^À|Ö¯VC§Nwï6÷ž¬ô˜.Ì7näÔ©SÔ«WW_}•Î;WêHâÙ³Ï{»z^{M2Ÿ Ñ¥#G¤~ãF˜6Mê‰gÎÇÓÍ BC¥¬·V-©á4H^“ž.Žî‰0dˆa (H*Ýû÷—ߟä# PÖÊ€F£áçŸf×®]têÔ‰¯¾úꮳÆ*;z½žC‡ñÃ?P¯^=¾øâ‹2¯¼1ÅìèÜY ´Ì^Ÿ] s3Y¡’¢ÑhgÏž=üóÏ?Œ;–*™èr X«¤Ü¥öÂ`0 Ñh ¢}?aª_ß¿?))) 0€I“&åÊ<%&¡C°¿ØÂnnæ^õìê’­´þCÊp!Îêܹе+´l »v‰³=&ƒc¯^•+µ……ó3gÊöÒÒ²\++iâýüshÖ ÞzKÊv +ÝM@2¾99 ¤g>®¥bΊ½HMMå»ï¾£gÏž¼ñÆY37+3¦¤é˜1;80Ç“Ï>›ûÅÙ……I¤éÒ%yüõ×å8÷ñ‘Rö°°ì‘J))0¾8»ýûßµløæMX³zökkù˜œ~Ž…œ> 9b` ŒÄÄDfÍšEll,ß}÷¾¾¾æ^’‚B™£ÕjÙ¸q#«V­bÒ¤I´¹S®ŒÐé`ß>q+‚yF†Ý|òIn‡Õ`Ÿ ]Q§pWnß¾ÍìÙ³ ¦K—.̘1CQ¿/GŠuúÔ¬Y[[[vìØA@@@ê†×¯_'$$„7ÞxÃÜ߯Ì1 Ìž=›´´4^{í5¼½½ñÌáxi4"œ2{¶”õUØÌê>À]îib'ÚÁ) *’Ýйp^xAŒï¨(qZGŽ”,iR|÷¼¿IQŠ1‘3xQ¥ŠÌðIH‰ä¢àèïx¬`ÇUqXË„ .àèèȰað·/†æRF§Ã°~šT=6OŽ@”ȵ3)lúæ¼{u›Y¯#1QJØ Ê ˜¬ºuá7ij°±a‡ûcÔm—ÃP±³xÐ ñ< É4 "U§Žœ^^RñÊ+Ù¯ñó“„­)« P±HNNfÆŒ$$$ðÅ_äÒ-P(­6û2‘ AÐóçᡇ̢ö®P4 ‰‰‰,^¼˜   fÍšE5ÊíóõzhÕJlª“'%ÓjÎk£I†à? qãìî‘¿þq¨W^É¿€L¡bc4‰‰‰aÚ´iøøø0wî\ÜÜÜ*u…Ye¤X{ÛËˋ޽{³víZþý÷_twÌþ3„„„0cÆ Z´hQégK…‹/Ì„ hܸq–³š–&âŸ3gJ¥`·nÒgg5-M2Ÿ…ÉŒîö‡ÃøñÒ¿/™Õ*ˆC²W^Õ]KKéÝ[¸úö£ÂÉ Þ{OBÝ»ß}]..’™* ·G¤TÙÄ_@0p¸e†ýú ÓéX¶lYÅtVõz©› *ü57’ôûf¾?Ûƒ3gÕpêg¦l¤¡g –ž.,_Ãï¿Ã’%òž»aa‘ÇоySâ5ii9^S£†X.w1º“’äôJKƒÿþ“äld¤¼Ý„¿¿¿ÊqäªB¹yó&ü1iii|úé§Š³z'F#ܺ%Q™cDz…Í>ûL¬ùœÌ›''RzºæM)ƒÁ@HH?þø#o½õÑÑÑL™2…š5k–«"xZlß.¾5ä03'.ˆ×¨‘8¨ 1y“0|F†y×§P2®]»ÆÛo¿M»víxíµ×ðððPœU3Pì…1cÆpãÆ ¾þúk6mÚD»ví°··G¯×såÊvî܉››Ÿ}ön®îµtIMMåÇäñÇÇÓÓ“ÔT‘Wß»W|·fÍDc¥~}±mËíøÖëáúõlƒùömq,oß!“/ˆ±Q=ÀÖ¾úJR;Ëw@µa¢œ”ùÚgŸÍ ¿“jÕàÍ7K÷ËÑ¥( ÈY9쎔/+ ¥ŽÑhäðáÃdddÐÙÔÏYQÐé`ófX¶ ž^N²äd1~OŸ–cÿóϳ²¦šw?&ru>ý^¹3ú'Û3¤¹.ÍÄ&?ïÆ’5-AÝVXüû¯JÔ¿8¤¤ˆZq÷î°jôê%É¥œÕ×jµøÕ:’tª(¤¤¤pàÀ.\È Aƒ6lØý=Î 9YJàs€))-çMAåq'OŠFA­ZrSy}ÿþ°bœ;'ÁP{{±øml¤ä^¥’ö… ƒ^¯gË–-¬X±‚ðÑGQ½zulmmË}-ÉÉì³µ…‹eŠ]yÅ8nÞ”ØËÀr(gdˆý÷æ›2Ü`Ú4Y×¶m2 B­†9s¤%Ì »J¡˜¤¤¤pöìY¶oßÎ… xì±Çxä‘Gõ{3Rì=ïââ„ hÒ¤ Û¶mcΜ9¤¥¥¡V«ñóócðàÁ 2„:uê˜û»•9ÇŽ#))‰N:¡ÕJ³}x8<ù¤¨Õ™¥Õ/!AŒø]»$[Z£†Ô(N™"uxf#hjª\I—/‡G‘ìeœµÔ>÷üi€@@«ƒ]Að°ÑïeQó¢A2¾q€_æc-€ê@àþŽ˜£ÑÈ?ÿüC=*žúV gÎH CíÚò˜J%õXíÛgƒ66ðì³Ä‰‘ðÖ[påŠÿþkÅÜAò–aÃÀºch?Wú¨K!Ðë¡Gùè?ÿ”Šø»Åvr’’"UÆM›JÕ”m͉££$©Š’V([’““ùûï¿ù믿Ðét¼õÖ[tèÐÁÜË*;RRdnðöíâHNž,÷–3gàûïå|ëÝ[ÚCnÜ g§N’ImÚTNˆåËóƒºuñ½¨¨l+ÞTG©P!9}ú4«V­âã?¦qãÆf±l4ÊõÛÎN®™Mù9¬©©rûiÓFâôááb÷Õ¬)Ϋ³³h¸ºŠÖ¤…ÄEi¹9u9µŸï%Á… IFFsçÎ%00Aƒñ /P%ÇÈ9…Bˆ‹“ûB«V’¹+EJ*pqqaĈ 2N‡ÑhD¥R¡V«±¶¶F¯×sòäI6lxß /%$$ðÛo¿1nÜ8ÒÓX´H Ô×^»û—‘ž.J£ –k@@þ™ ðp‰RÿðCî¿Z-¥»¦š•J „?†úÍá? 0é$X[‹h¼k–AlS°mdÞÞ8”·È|l"uéqUTùJ•Ο?Ï‹/¾X~j4Šq|gÇ„V+Ç®|ðAî×88HZ2RSÅ–nÙRNWW™|!S• ¨Zâeÿõ—”5lÿü#ó]ûô)¸Ð $D*âMíîW¯Šmïî.ÿþòKöt'nnR ‘PAûàŒF#ûöícÆŒ´nÝš7ß|“zõê¨çPi1åĸtI"166rn!'“©zÊßfÌ{‰é\ôðóóÝw%kÚ´iáÑkëܵï ƒÁ@LL çÎcΜ9|öÙgfwVA®µvvbòøùÝûöŠÃ‰½xQþ=t([ÕÝÊ žžÊÜ׃øà¡¿°ùÉÕë¯óø3VÌz±3ëÂFqX+$éééÌ›7ëׯ3}út<==Í~œW¢¢¤Í#4Tþmß¾T7_âܶZ­ÆÆÆ&ß¹r111¼òÊ+,[¶,Ï ÒûF“Ùt펕U;>ø@ÅãKÙÙ-))¡öñK·n]qXãâäCmmÅ:nÜX~ò#çè;»liÔ0à:° èžùZ`yn%ƒmïòU20dþ«Îñû^dŒMÎê°êHIpOrÞQ¸gnܸÁäÉ“yî¹çðöö.Û3¥$°n]9–×®kàñÇ%|ma!¯IM…¯¿•ê>}ŠUûï¿rZ˜’°Ã†e?pïEçÎIBI¥ÇxéR ®šœ˜(mâ?,Õ ¾i}Ý»Këñ(KKÙ-MÅPÄ|Ð0 ‰Ÿ9s&/½ôýMó‡î7âãaåJaè×OVKËì!—9[}ò‹ ÛÚŠ¾A¿~J¶´’c4³JÞ©R¥ ¯½öZ…pVA®¯Õª‰ÃZÚ1ôt1¯ ’Ù¸qÆŽ…_•Ú³gôëk{E­¦®Ý >n· »FþЮuꪰhXŸ]g¢é«ˆçUŒF#§N"11>LHH“'OÎ% ªP¦D˜‡‡´~„†BØeRŒmŠÆéïÃÚµôôt~ùå""b4èsf̰棲'Y܃4Ã98d‡4Ͳõö† ò¾gåJ±nÝÝaâD1ú‹K0)¹5‘´l϶‡WŠ¿É’ïàK sM* 3¢Xœ³W5°Gú[íû¿ ½\ˆŠŠb„ 8”þÄÄd‡ÅA”*Þ{OJíì$X¯,^,)È:u$Œ=q¢8±Ýºû#ÅAÌWW©`éÑ£d_'=]bE¦.ˆ*U¤lÉqLïäÒ%1T¬¬ä½¶¶2ù¦uky¾F ‰Ô癋|‡Û·KÿO¢pwn޼ɤI“xã7èQÒƒ¥¢¢ÓIS^ÍšâœÖ¯/çÚ½”tåw+T û÷ïgÖ¬YLš4‰ö¥œ-¹Wôz1}>ø@ìå‹¥*ÝÕµ4¾»ä®]ƒI“ò¯h±·»O¯‡E?éhd ¤åú•ÛZ"¢õêáñͤ\ï±µ…7'Zóãâ>tS4Å*GeÚ´i´k×KKKùä“Ogµ8¤¥ÉŒúþý% Ù¤I™|Œ"sU t:[¶láСcxx¼ÇÍ›N|÷ˆ+Sé£éÿQQ¢ŒøÎ;"`’Qš1Ξ-x;ãÇËÌœ_,šâ®Éžæä"p X‘ã5i€¢<–¼#eÊŠt èŽ5ê»ÌuÕà™y×Êi}÷)F£‘´´4N:Å„ x衇>|xéÐÍ›ðöÛ2ß)*JŽýÅ‹%#“ÓÒèÜfÏÆàW‹˜øñÏê,n4ýc£Š]s¯ÓI²Çß?ÿç­¬$CZ…ÉÔÔì×?.Û7Ùö2–8$DœÓ;·{û¶”&ïÝ+QzS$ß”5U«¥òÒ=Ÿª£QbTæVÃ|Ðëõ\¾|™O>ù„6mÚЭ“ ^/_ttvƒ´Á J^~(Úééb÷ìYêýG •‹sçα`Á¦L™BÛ¶mͽœ#5Uâ6jµhÜy½ML”î«ÚµE ÏÍËË)8è"÷®Bð«kEpô¨¹÷àƒÑhäÆÌ;—§Ÿ~šI“&1qâD^~ùeªV-y{Ð}‡Ñ(÷ƒ¡àפ§K”é¾b €öž 8¬EÄ”Yýý÷m4hð1uëz3r¤™%*ë¸uK²J ľ}Rê»p¡4Ãüü³üÁ{÷.x;––RÓª•dfïF °ÿŽÇR‘¾PS¾]œGœG€eÀÍòÚÑ@<Ò—jˆ8§ÞHϪ6ó{˜øî(%Á÷€N§ãßÿå­·ÞbþüùŒ1‚^x¡XclRRòŠå‹““ô¶µh!‹¢:rdÞÉÆ†»,xùeˆÑ:s2­!cñO¶“'E8¸ ?·Z51~ÒÓ‹¾ÍO>‘ž%ƒA®Ów&“¼½åô>x0÷4)“áÓ»·$³Ž•„s÷îÙ•–j5 "I®;©WO^_ìÝ P’““ùñÇ™4iÇç•W^Á¢²R¼|Y")“&ÉŒ ƒþÇ%U4i’"_ªÈ¸¾Ï>ûŒçŸž&MšTÈÑÑR¥na!?çÏK%Mi°r¥8¥cÇÊÿãâr?Ÿ­™ä惞©BŸ:À€w-…T«Œ´ö¼ÆÅcÉʘ3ÃÔ©S™¯{4óyo ¼œÖwŸ¡ÑhX¾|9'Ožä¹çž£aÆ%š!¹{·\³L‡qgÎÀ©S²6Lêe›4‘ÆQ£QNº|Ê+ ÉzÆÅIÑAÓ¦"D¤×¤‹Z]xÐÛÁ *z0pÿ~)Ù £ÉÓS2¦wâé)ß!*JœSëÿ¾}ðÔSÒ†{옔ßéL{²¶ƒ´´Ü­„ ¥‹Á`àêÕ«LŸ>š5k2sæLüüü*Dß^’“áðaI÷8:\Šëë+³†³¤ííeæF™(*T6ôz={÷îå§Ÿ~âÕW_5k5ÁR½f*Ç5¥íØ!ñyN¦Møúʈ›»¡Ó>¹,*JݧN§tÐ 8wÖH§¦IX&ÇCJ §ë¢VgÞˆÒÒhÙH…ÁºˆÁ£‘V×ÖóïöÖìlÒ¾}Ͷ‹H .\à矦N:<\P¯Ðƒ†V+ÆUÎ{܉°h‘TÀrRæœÂ`ÂÙÆË6\ÜÜD2#£Tï-ÅrXoܸÁ²eˈ»3ÜtiEJµTÖ®•þ³6mò>Â÷ßÑèJ‹ßàææÆSO•‡†…I¡‰ü® Ý»—þ—Õ'dÀ4vg2oõ626ÆqMUF”Ïè˜X é«Õ!GèuÀq°#ìêyD5¸Oæï§€Qå°¾ûˆ””~þùgÎ;Ç”)Sð)JIy:$7úvíîZ¹R¼µ–-s7Ý%š™œ óç‹(Q¦^çÏKà®aâ¯Ë`³iÓ‚_£ÓɨÎï^¤ ×Ëk ëöøñ⃿ðBÞ׺¹‰÷¬YÒgec#×| »¹É؃¡@qã|qr’R¸jÕd{.Môz={öìaéÒ¥ôíÛ—#FT,`­V"¦u:©?_³F²ï¿—×íߟ-©UK"(ù5ã)Ϊ ÕjY·n[·ne„ ´lÙÒlæÎ•Öˆ‡óÈÔ5åà ¢vîg¢qã»ÓÒÄÞ3&“K§“Šœ#²å@žÞyS˲¥4·<ÁÞ@‡ÏhÓ#Óa]½‹5°èÙ³h_N­Æº¦}k³hm7:u2Ë.~ Ñét¬]»–•+WòüóÏÓ¯_¿Š7²Ï\¬^-'TN¹í5àÓOå(3³[´ÈN¶™ppÈ=ru•×%%•êHƒb9¬©©©\¿~˜˜˜»¾¶yóæf$]ŒF7w®\[¶Ì¤¦¦²qãF¶ný‹=†±}{?F²£}ûâgxòeìXó HymÙks >Ò³šØ #cröM§–ÁZîTÉ¢ö¬GÔÉ ;Vd;Ñ È.®´+ÿ]Y™ÑëõüüóÏDDD0sæLœïah°^/*·õëKdúÉ'sø£Ÿ^ì&)IœÕW^ɮއlí¥â8¬Z­8¹…Ù¶¶bÀ¸¸Ü}{iiâL·h! •?ü ¿d×9:Bd¤A:ÈøšÐÐìÏjÚTZx‡½ûg›ðò’„5@r²š;ýèØ±b_k+F£‘›7o²|ùr‚ƒƒyýõ×iÞ¼yù Š×éä«R‰`:‰RSåÄjÕJÒH‹Ks´F#½§Õ«Kä$99w]¾³³”s­['e ŠˆˆB>hµZΜ9Ê+HOOgêÔ©Ô¬YÓ¬Õ¡¡r] “ùö?,ZuêHuÊõëÒNatr )<Îë–WSRàÙg³M°ØØìñfÇÃ'ÓàŸ½òà“Oòè0 B‚ž ùcj´F⿱“ª™Œ IùNœX¼/ظ1Í¡Ê9©Nª©Œä+st:‹/&88˜¹sçR­Zµ« ØÔ˜mm-‘7DÓàôii‰Š½œœkÎ$†‹‹Ü›ò+ó½yS‚M'”……Ìø,e°Xwâúõë³ ?¥ÚJJ` Ë—KÄîäIɲ&&&òí·ßI§NŸpûv]ÞzKì…Rk_2— EÙΟ‰Ö€’ͬ t\3Ÿ/«þóÀ*`BŽÇ¢2×ÔBÊ•c«V€I8'³‹¶Hùòßd« +Ü•ƒräȾûî;\Šâ©BD„œãÆI;Ü™3Т‘F¼ÅbçƒØ×11â¬æôúö-~囹ʥ°òY£Q„5<< žeB£ÇÜ4CünãeLÏ'NHFöôi1ºL÷Éäûǧ¯Q#»Wkï^ðòŠÅÞ^™ss¯>|˜3fЮ];¾úê«òU‰LIo¿•ÅÛ¾ùFÎíÛ¥JÁÑ1»Ô`ÌسGÓ¨RÉësžoM›^Z ðÀ£ÓéX¶l»wïfèС 4(ßQ…åMR’t4j$׸åË%X9uªØÛuëæˆàá!ŽlAèõ¢ÜÞ«—ܣΓ®«Õ«l]—Ž/ጙäÇ ž:<~þFÄÈ^}ŒFš6UóÎRwº“{RݪaIrñ®W¯x_°iSìš6åcd|7o¶å¡‡ 穜Ñét¬^½šðÕW_=X¢Jz½ôÍŸ/¥a£G‹Ó¹l™Djš5“c¸fMÑ9Èù¾ë×åce%kïÞù+_}%ÁÓœýÛe0,¾XkHH?þø#?þ8Í3縤¥¥qõêU6lXi¢·nÉßiþ|øßÿ$ ððÃâ°ÚÛ_eÆŒ)´ I“÷8pÀ†÷ß— g©““¥FpâDó\hEÝ$C™#GB2âD6#e ãbÊBg$øxq–A‚­€1HvD¸væÿCç:0Ý#lÈòß•••ÀÀ@fΜÉ7ß|ƒW)Œž ÃÆF²Ÿ?ü3ºnÃ1â2¼õV±¢<:\#Ÿy&oÉ–••DÛ‹SBe0H5daã -,dÛEé:qB’XÅ9uyDÚ@RSEÈ£K—ìç\]Eoª8ã ŒFiY>N2R½zåÒ ¨hèõz-Zľ}û˜ÿüó uœ—Z­(TžÌ4 ÛµƒéÓå_Ó±ªR‰bc“}¯qwÏ–¾‰ö§¥egJU*P«ÑT„†æèOI‘€ê Kgg©¿/B iQ)–Ãj00ÜÑÕ®Óéˆ-ý_z„‡‹áh[šsn—……—#DGÂÓóEÚ¶µå‰'¤e¨È¤¤H„|ß>ù==]B…ã§Á¾Ì™«gÏJZÞ\GD–ŽeþžŽÌ2U€†ˆóÚƒl§¶12õ^8ŒdGsrÉòæ¼Þûm2?ïâ4 ãlTˆã|³c*¯·ö ™b…IOOgÚ´iøûûóÄO”Ê6FÉzêS * g=ãF&‘^§qv c18qBzCóË8::ÂæÍbxÆÅ‹RâûÓOrÍ?þî~³ƒCþådÑÑ’A)}^µJÖW,-áË/åRpç5ÝÂBª8‹Sœâç'—ßW*>KŠ^¯çÂ… Lš4‰Ý»w³`Ájå¼Y—II0gŽôr›nüU«ŠJתURÞ« PNÄÆÆ²bŠƇ½½=Ó¦M«p§«Wå:o*2°¶–kÞÝâHNNbß¾ù€©?/<t:þùÛHÀµ­ØSáÈœ“nˆܹs‘ú»½½%–4y2h2,P¿ò’Ø|¦1ÅE­† ­·²2`iYº3+t¢¢¢˜2e aaaÌž=»l®ïë׏z5»<7gÅÎݸp!;Ë#ÁÒœú&çÎqa臼ñFÖ¡+å§œÿöÜÜÄp*%ÊIM"/)))lÛ¶¾}û棑––ƱcÇ8wî5kÖ¤[·n8::–J&hÃÉUÉÇùJMMåôé%<ñÄ;<ù¤”—› $ºÑª•„6l€ÿþƒ>ïÀ™L¯¬W¯’G䊋!ó'ç_YƒdTL;éHDœÙÖ™™Œè(D)¸#â4–„ëÈ8:9»ôÊžÊüLÞÔ‡'ù,’M]˜•«W’àœF~Wr÷åVŒF#;wî¤Zµj4ÌT 2$''óßÿEÓ¦MiÙ²%vÅ© -!;wîäܹsÌ›7¯Ô²HF#Ä^ŒÂ3ð °ºÇsÕðW?OÃb–h4!?¾à×T©’»j%?~ûM2´NNÒ«”ßÈ™;±°ìnN ñ)öìãÚ5‰ú—´5ãæÍ»÷ÈKK¹¬ØÛËzîæÀ—%ƒM›6Ñ®];ªU«–õØíÛ·ùçŸÐëõ´nÝšF•ŸxQ!FbbbX±b‡æá‡¦ÿþ%åT$’“åõí·Ùý¦vvÅSS0+IIIüóÏ?ôë×Ç'ZZGåüùóøùùѵk×R±UÊ£ÑHDDŸ~ú)îîî|ôÑGY÷¤ò@¯ÿ¬(»fÿ~iû(É-±ÿÌà_jª¨i^¿^^è_y ½Á—Î߂ŋf¢VK€pÆL]š:u䧤ԩ“]uaf®\¹Â¥K—#™b²U¶oßέ[·hÖ¬-Z´([¥¤èõz®^½ÊÖ­[Ù¿?­Zµâÿûßý©l0HRL¯£Àôwyâ ©{/‰àκurµm+Õ=Ï=—ûùêÕIˆÎàÅwÓ™<Ù–/¾0R¯¶¡à“ûÕW%@k0d¡¿ÌbAèõzþùç~ÿýwºté’ËXøúë¯9|ø0mÚ´a÷îÝüóÏ?YÙ{áömÙ§9Ëñr²téRêÕ«Á{ïù—\XéömQž19¤ƒ‰üçvq´’(~zæ^¸D#ÂD&j¾Hé/d—ÙZ~@S@OnU`'$Ûi ä½¬d—›ÈÜv`æ¶Õ™ÕË\ߤ„¹ÙYØF™k¸…¨›HEFÝøQa eÞ¼yŒ?>Ë8ˆ‹‹ã½÷Þ#))‰zõê±qãFºuëÆ¤I“Ê|-K—.å³Ï>Ãí^x:$QëÖ­ÑUó§IS>½ÍëNGë`ˆˆ(¾pGPdG s}}¥¶ nݒұLJµ¨ ,›““èhÑ*˜7OJÒNœ6‚’òä“%3Âòãí·¥/לBìƒ'N°hÑ"üýý³ÖK—.ñÑGáî‹ ¿ýö¯½ö”öLépá¦M›FûöíY°`Á=©c Ÿ¼7}…Jƒ^¯çï¿ÿfõêÕYÁsÓ¦Mãøñã´nÝš]»veÙ*÷|}-˜2e ýúõã±Ç+×ÏŽŒ”êww‰å–èÒëE¦¤ã_‘ë¿G{Œ|@šÞ{{8}B®•u•ÜqQ©düØúõ¹ÕëKL§N"p¥ÓéXºt)‰‰‰¹ÖØØXÞ{ï=RRR¨[·.7n¤{÷îL,®"r9¡×ëY·n¿ýö=ö³gÏÆ;§ÐýÆ©SRú''ÌóÏ‹_%ߦôF¶m+ÓÆX¤Æ9o2»NÑÛòÍ—~~d³¼>?ÊFÄYýõW,L‚"÷@±V•J…J¥"##ƒôtúÐjµFÒÓÓó” [[[çb:tèk×®åðáÃy¦sçαoß>&L˜@ïÞ½¹víÏ=÷û÷￧ᾃ”-úøäŸ å¿ÿþcÞ¼yXÜ‹ ð MŽø¤du0â •§rYñÀ 3RR ÒŸzq& gg$j2®=‘’Ü’¢GœõcÀ«dÐ'+;€IDATgFÃÇ:q@ÿ@úQS1¥ g_Šع½GsÈÿùõë×Óºuëø@.Î?ü ªsù\œÝ’ˆ¶îÁŽ*^zIlúçž“@gEm½Ô×,,H3CF°K挵œAGAAAôë×/˦öôôÄÃà  ·g0ˆŠŠ"999Wù|Y‘––ÆÖ­[Y±bS¦L)×¾ìb¡ÕJ'¿sÐh”hMÿþRBkzMÇŽâ¼hµ³yæ‘,OŸ–Ìg)’œ,z°Íšƒuܺ…ÁË› ë%èÔ¸±ää||À͇.C»v¸º©yæ»–ÐÚ&WI«…ãÇá‹å5˜ðö+,4DFFÞ³ Z,‡ÕÏÏ JS–:•J•e¬¨T*¬¬¬HNN.ô}†°°05j”¯ÃúÇÒËv§­’ššÊ¬Y³7n\ɲ[:(¼ìÙ#½«ù9Ä1LGœ¶ò<Ÿj IÉHXÄØ”ãžDÊoÕˆcëˆdYsVk[Qt‡Uü†”ëšÄH6Õ)En‰”«2?¯sæs×R_GÛ q²sî3{à\æwÈhV™e—F£‘ÈÈH\W¸âX³ì/œEE§Ó¡V«³ÊU,,,°°°¸«A–’’µk×puu-–Ãú÷ßceeEûöíï­DæÚ5I_Ž—õPD„ù9ˆ))’ -JBíÈi‹}ñÅÜ‚tù‘œ,Ë6LDŒ'sÕ*©”;¶dZ Á¿Õ«åÿý%³S+rrL§ÓF\\\¹;¬w[WÎÖ +++ôz}VIAÄÄÄ^*³A²`5jÔ Y³f÷ÖêQ›6ÁÞ½R;n`©QCRF÷SJ½”HHoqZËBCCïj”7ùÙ*–––…®Óh4ÍíÛ·ËÔa aúôéLš4‰–-[–mé{ÒÓaëVé!=tHþÿöÛ¹EhßÖÀÁÍ1ÔyÖšØ æ|›Áô˜/©öÂÌüo¾¾ðé§Ù£""ä~”ÃÚàц½eÍÞ½2ÿZþ6¥W1YhµZ®^½Š¾¤jÃeDIl½^Ï7HJJ*s‡5::š3fššÊäÉ“i\ІeAz:|÷œ¯¼’½ UÈaà ÇèØ€S‡å–Ò¿f¾nnERµ.*AA0¾dEgNI¡É‘%0v,iOŽ'ìˆøN^^bÓÕ¨ê[Q2_ÕËKîy™k̉µµ$V®´dÁB>ü6ááá÷¬Ôl~ÙÆ"p7…/gggÚ·o}>BB‚èòÛOÛ·oÇh4Ò«W¯â-(6V,Y©u1BÂ…ù9VH «⸖ÀvD¤hâZ’íüUG„¼GÕD<"v”³ÇD œž.ÂçÞ–Mrl# q2»‘]¶{_£BJ‚£‘LkÎûÕÿ²æ;wkw¤Ç6ç}8虹-åâÚ´^S®{^'Á£‚4·ÂÝŽq///:wî\¬mÆÇdzfÍÞ}÷Ý{Sh‰™3ó4˜FF,bV£FÁ½¦&22düÌš5bØÔ×”oïl5ßþ‘ò¬7Þj1 ‹{Sá1BÖ&÷Ò¯ZØÚÚÒ¾}{"##K%#Y–¨Õ껃uëÖ¥M›6¥ö™›7o¦ÿþe»o† “´þsR+²…lFV¯;gÈ¢¿§K—.ÄÅÅ™{éE¢°ë¸J¥¢~ýúešJHHàóÏ?gìØ±´oß¾àþô“Ú/Î ´ R¥ââr÷2ùv%ƒÈ >üP• {TSâ Tç²ïßïÎ~ Ác½ MwaÌ“–x¬#‘Ç;V½^9³ ä?ƒ pnêÇ/OI2¶²èí8::Ò¥KŽ?nŽq+++ZµjUòöº"Ëûï¿O³fÍxî¹çòµý‰Ž–ëry\‹““Å'ÈoÖÖRy³j•/¦c|ûö"5CgÜŽãÆekúõs ½F=øâ‹R©Ü1Äþ ƒ‡–qMïM°eìŽãt6‚Ÿ´ n])éÏu 5¸Š¡Q¨J¶••œ‡›6Á‘#Õ9s¦/þþ÷6Ò ÄVlPPVVVx{{³råÊ|Kóëa- WWWÂÃÃÑh4ØØØ ×뉎ŽÎ#xP¢¢dõßääd~ÿýwÞxã‚ ©3gÄò6©þ"%:c†dšºu“æ·œ\@œ'éHÓ8C¶nibDœÊœÙöÄlM¶Ã—BvÖs8’ÝlD×®¶y«ÌªT¨÷soo/ŽŠ‚èhý9?Å~wbb"Ÿ|ò cÇŽåÈ‘#hµZöïßϹsç¸}û6`ûöí¸¹¹»^¹]»vDEEeõ¶¦§§sôèQÚ¶m[¬íäääɼ}¾z½ž_~ù…¶mÛ\*i0À•+2G(8XîªÒ°7~|Áò.Ä1ÌÚ’ 4"YYT}èuݤÅý‘’ÚÐÌÇ4dg0O"½µäΰ^~ÌñÒÜáäÎh’ù}Öæ³–¶À²3ÊÈ Wpq⯑íûlþÑG­–½ãaÓï”°ét5iHúøã¬†T­Vz“üü îñtu½€‚TlµZ™mÚ¾}ñD,¬¬$›úÆ’ ¨LF……;vdÿþýYûlöûêÔÁ¢jÞž fÞ‘X3Ò¹sgnÝºÅÆ æ×_ÅÑÑ‘–-[–êç\¼x‘„„Z´h‘o@Ft…Ý']8zÝGҦᦃ0S§fËíªÕ¹Ž÷Ó§eØðá_³L‚ùÝôz3b„8¬Å„7n,×ÌâVò+”=jµšÞ½{sôèQvìØÁ©S§øý÷ßiÖ¬Ù=÷¯•ˆˆ®^½šgLC©pà€8¬={–Ëw¹W’“ÅV +•¹íùb4æÝvL |ô‘Ä|MìÝ+Eÿþ›;ˆü÷ßòXp°¹÷VÑiÑ¢666¬X±"ËVIHH k׮庎˗/sðàA^ýu–/_ΧŸ~š»dÓÒR”ì~XŒn½^œÔœgBF{{8öeøÓN|ýš„È4ÍKÃ`Èÿ 1nÝŠ~Çn)ºzôQ®=õ {"룶Èܦ££^NNù^àmläØ=:ÇÓ‡çŽp¦¦Ê¼ïü‚ÁÁÙŽˆ•®ÓQµ +ÙÕÒ K—.DFF²yóf‚ƒƒY¾|9ÎÎδhÑÂ,ë1®¹|ù2¯¿þzvP&%EÆ Œ‘] Ù¶­Œh4HÒ|ׯ‹»rev$æÄ Q2º3Rvì˜Ìb:t(ûÂfa!ÞÜ_ˆŠXά®Ñ(YÔ;ËÍ®\‘5€*•\ø ¹(wî|WÁ ƒ~Ýæ‰sb8~×vsꯈB{ƒŒfýî;¹þ†…Iléôiñ÷î•Sçûï¥õôΑ­––ðÌ Ö<[?ü I4Å* ŽŠŠbãÆ<ýôÓ<óÌ3XYYŸõ¼““;vÄÉɉ7ÞxƒöíÛX>РA´Zm.™u¾øâ ~üñGÞ~ûm|||øüóÏ©—g(WÑ©_?û˜1±}ûv5jDüì&'÷ߊœ³…<ù¤DS,-%¥SXÄ^ƒ8a!ñ+±H™mOJ6ænd ÎdÎY#’qTe®ÉìCz?MïÙ€”íæ, š!ãfL8cÈ]lDѳˆú¯i·„"}³½‘‘9d~çj™ÿþ ø€W2Ÿ¯´ »××DUľS¥¼>û@…”6ïÉÜV2° ]ͶwqqaàÀ¹Ž³úõëóÉ'Ÿ°xñbÖ­[GãÆùꫯJUÃ`0°k×.zöìYàvCN$°ÞëÓáÃáñÇÅ{¼~]"ò=zd«Vä =]â7O<‘g¦t.|} .+;uJDTçÌ)Y+ÆÐ¡r­/EÝ…âããÃÀ³DdT*ýû÷'==Ÿþ™ŒŒ Ú´iÃÿþ÷¿{ë£.F£‘«W¯òå—_Ò¬Y3Kµ¶–§ÎÑšúÛfcóÉ{¤2‚ ¤H"?.\dÀÒ¥ܲED*ýýe9ׯË5¹qcI燳3¼5, jö.§¿lÑ)–^¯§S§NYQ<µZ³³s®²Ãš5kâééÉÑ£G tX;vìHÇ|Ô¥êÕ«ÇgŸ}F||Íû￟ý ^/;ñbÙ±wÝŽÑ(Éͨ¨ìRZëÚ¾tkBhPµ|Ö nÙxÄÕ¯ÃY½:ßøfñèÖM„ zöÌÎlaiÚTlµAƒä>ej–»×Ñm(£FÊó˜Z­¦K—.ššŠ§§gé+¦‰?üðã{ö¤FHHv•@QiÓF~râå%?â° y)JTﯿ fM9èãâäÂwë–\p³oß¼ïkÚT"ögÎÀóÏsKëJr²´Àz{Ë8Ö„)ìÌÈkÿÈ‘`c«‚~ýhëY‡üV£Qª£‡•dBýú’A}òÉ\SMNu£Xwßôôt 9îžŽŽŽ¼ÿþû ><ë1Ó8šhSxµ˜8::fÍø»ÂÃåmúcF6lØ@µjÕ Vê«][®À%±ôH¯§Ù¥¿UŒ£;âì•E†õ"®t*ó÷DàɈ8’‘ŒjÄÁq« nNa¾ªˆzð_¿!2CÕ„É®>‚¨ ›ø/sÛm2÷ÁMr«üö@œØÞä>úê!™Q—|>·¨½HÐà|æúÚ‘]î\ÁpwwÇ××·L¹c0ð+À«ÛùóeNœÿ4:FÅeÿ¾ ¼vM.´žžùÖT%&ŠâÛ›oÞÝ.pqã3GÉÉâ¬&*¡\ØVáP«ÕT©RŸ2wVΞ=ËìÙ³yçw3fL®{T‰‰ŽÎ–6Ì,lb¢}ú¼'IIùߢ¢¤›1gÙή„@GÇ i kEÎÎΨT*²æþ™ “œ éééDGGãVÒJ)±aCnQ–„„þþûoFŽ™÷ÅF£”}Õ¬™·¡¿¨„ ¢B{ÈβDJf-,eYŒ“³AÊd5™¿§!YKk$+: q䎓ýw@²ª;ÉgÏ ;ÙÓµ!§RÄÁÝô¹gnË-sM3?7gI¯°o“óÞâŒdeï¬à­_Àz Â5ó{ÎüŽeo+W(ôz=›6mbàÀyv£vïæŸ%76DvtíÚ ÃJOïÒc.FeQojµˆG^¸ ¿§¤HðÑ`Èwl—‚B‰ÑjµüòË/Œ=šæÍ›ßÛƒ!;Êâê*Ê`ãÆ^ÿ^†\»&}GÿýWøëŒF ]½š-¶ñï¿b¬xxˆÓšœœ­£v7nÜRÝœm‚:$åó22$#P¯ž öí“ »_~‡ÕÒRÊоûN¶7`€´XY‰n¡V+þI÷î²ýÑ£¥”ø.ãzëüæÍ›Ò«vûöÉ+#CŽÓéÓ%[Y—.I,fÙ2É®îÙ“WÀΩe=®Ú7áVNÑCŽKû£9V¿¿´}T¯.š7E™¹](ŽŽâhïÞ ¿ÿ^øýÈÕU^!Å‹Íø×P(´ZŒ‹‘Èÿ÷ßK641Q†ËÏš%É £QÖа¡8ÃÒµ~=Ô­›-æQ½º8«?ü»§Ýh”lÂÿe¿Öô¾ððÜëÓjÕ¤¦>`‘Ç»påÊn^ºD׿ÿ–e7·ìŒˆ³ó]3kÖHV¼ysÉj›ÆƒåÄÞ^x*ë³md,?þ“§Çê°´”záѼ±(ê1£Q¼é)SòÌýÎ…J%¥¯¿–rÎâ4Ð*TÒÒÞ¿ŸiNNôš4©ìÆ¢9#³ÄDéa* ..’Y5ÐwïEx8hõ™A“ÞMŽsð—_àw`Ë_–Ю‡Z¾D³f’p-N|ÕÑQüãÈHÑIK“ØTh¨T¸ŒQ!£¥F±š|ìììxöÙgyï½÷xï½÷xæ™g¨Y³&vvvh4¢££ùã?øë¯¿3fL¹1ÈÔT‰ÜæŒúmß¾–-[æ-ÃŒ‹“0Ÿq÷ö¡.ˆÃ´q𼿱%€nÅÝãùp8<ƒd'³"®tq¯]~l8µ¡d;±NHë#ð&ðÙUs¼þ ’Iuú!ÎçN²}k âJGÉ­Þë„Ì\M"·ÃZƒüåÎ/Kê‡(/–!ýµ'Ož¤aÆù—¨ed°Õu >žYN§««T"Œ[ð°xƒAš÷­¬òªÊFãÆõûòKùý™g̽wî7bccY´h¯¼òJñ ½>¯…½j•”y½û®YÔœìÞ-AžŸ~‘Êfͤürút©d “ çêÕRBÖ­›d:§NŸ;gÜêÅåq[[‰æ§¤H‚jéRÉžþïÒµb…8—?.¾ÐêÕlª][*è"#aæL¹&|÷]v÷LíÚòy9+(¬­¥2õܹÜQÓ¦Ò«õä“Ùkkqpwî”댩í`ófG¶o÷㥗Ìý×0?!!!;vŒ?ÿü“þ?Œ]«VÒ¬VŒ €¨(1p;t냹þî |¶TËÀþ>T¯eEÔ™(ö§µf° ïØÚÊZ”óÏËK²«ÎÎ¥ä-+˜›7¥Ç³woÒ¬­ù,9™Ño¾‰¿¿Ù}fzº\ôLÇBˆŒÌnc¨[ÇGßçø{‘:ƒŽÞÞuãz ç.]²Öøx¹¾¾þºý.\VŠ?.þaka!kxýu)þéÐAì¶¶m¥´ÿ~§ØîS»víøøã™?>¯¾ú*µjÕÂÙÙ™ÔÔTÂÃÃIKKcäÈ‘<ýôÓf«y‡lS###ƒ#GŽðÙgŸåó±k—¤ƒîU’þ8’ÅtGÉD¤T6s4vˆÓؼ$Ïd5’1…8r·Ì­Ò7žùyíÈvô ý§9+´ÕÀ9òöxªÉÎÂÞ‰©O¶9â8¿ŠA{§¹.’M&Çzö ŽnN|ÈÛ«jŸ¹ý;)®Ý¨BˆS3ÿ‡.°²!ŵ:«ç:̽½¥Ÿ)9¹à9ÐÉÉ’)=º`§6?üüÄY9R´1*ˆðöî;<ÊbmàðoKzï@„’„UŠ bA)ÒD±p°û¡bWŽ"êQDQ‘® ½C B!@zï=Ùö~¼f!tÌ&0÷uqãÖÙÍìî<3Ï<#ÜF¶lÙ‚««ëÍŸùçŸò¨}ܸ ?0PŽÿRºõ°¿œÖª•œ6–”$¬iiòBÀÃË“MkÖÈ…•î»O¾ßÀr€©V×-Å`e%¯¨mÜ(/(ääÈÁÊ;ïȽc‡œ‰9`€üXææ0j”üX]»Ê)j*•¼ÅÝÚZÞ=sñi\J¥<Ã1…Bþü×9¾yQ,<\n÷Å·2D^¥]·N~}iiðë¯5 Îîĉ¼ÿæ›ôHIáùùóéyÝö•äçË{šk»ýµÂÂÏÃ6ýé?¤¬¬Ä`(ŽŽÿâ^Ñý¡¨=R¸=TTÈ2£7X¹r%mÚÔ9>ófÄÆÊYò;Ëÿ-Irqß ä- ÆDK__ùË®;Àùûoù¦#GBe¥‚ädK-?GQ‘Œ¾¹úƓ芃^®Ûáë+ß½ý¶üü/½tÑóߥRžLlÕêB°Z{ù¹vÓ«™™ƒ¦wïÞDGGsøðaÒÒÒðööfذaôîÝT&žñ*.®[Q:66++«+¯ú.ÿk(3äj¸ý÷xêS_kße{ä•ÅU‚<ָѭ«ïÿóxi\Økv!ï-à k ò>Ó‹·î*‘Weoæl>[ä`y8rÜ9@ä+€O/¹ýA.O;È…ó`kY"¯J7”ù?¯3¾¡ÔüÔÔÔÏÓO?]÷в2ˆŠâ¬]/Μ±¨³Òáèxí®_R"g¾Œuá‹ÿFÙÙÉéb}ûÞÞi*‚iÔÔÔ°iÓ¦ºUR¯G§“å{÷†ÄDyªúùçå)ê› zÿEåår þ‹/ÊAbÛ¶r!ŽÜ\¹Úï×_ËŸ©±cå ˆ‹nmmáµ×äÚÅ—×?\÷xA¥RÞŽÕ¥‹| NÏžuïW»Eëbò éF\é ù8ÛK·Ù[YÉAì‹/ÊqRL™RCõ¾±5''‡¯Þ~›¹ee=ôÊ»îªW¡Úd²¯¾º±Û+” ÞxSI\A"mGï Ýn«¸©‰KA¸!›6É_tO?ÍÒ¥KÙ¶mß|óMHn”N'oؽ[Þö4c†}ý ìuúô…?¬$I9r„.]ºÈY¨/½Ö¦†ÝŠ¿~*ò*jíê¥uW0}¸PÉ÷F¬@N'® äÒ÷gNG>’¦òŠjË®olùçù/Lø"§â^:£Ó‡Ë‹]‹/r„ˆ>ðÏåjà{ä`ýâÉÑäÝKƒÓ®\^-ùV}øÈ«½¦Û>m2QQQøøøàååU÷Š]»`ëV¢Z÷$  î`Ô` BB._a5ä윞=/|–n†Bq¡ Š ÜJ’$±gÏ\]]o|ëIy¹|øï#È&_xAΉmGaH’Ü”ÌLù³˜”$_V[yÕÅEäö¹Ú ¥òÊ“AW›/V(®¾ˆ`aqsIF ùÉT(®¾8æí-âóçË)ÊO=u킱·;I’X·ní$‰ÖcÆ 7®Þo~E…<1q£Gi* ìîïO@>íRÌ< ÿ’0XZ²gï^¶nÝÊ{ï½WïjïiirÑÇÿþWž„[´Hêô‘ž^/ǹ˖É_òb‹Ð””””°xñbæÎ‹Åœ,^,O›]¸üÒÉIO—«¶zyÉ«—'NÈÙÊ—cÆÈAÞ•Vyy;ÅÅG½€<î™4IÞ1s&¼ùfÝŸ‚¤$yÑ«}{ùº~ýä¢Fóæ]?`T*åI¡²29“á·ßLýß>nÛX]§»0«QYYI~~>žžžrméÏ>“{Ó©Sò·y}¦®@n±ØØXœœœ®\ñýJ´Z¹úè¿q4ÂM’$¹hGMüY+)‘÷”(ï'}ä¹R·nušå½SwJ:fÛ¶õÛçuÛ$tQQ$<ó S'OÆç&ƒUçg¶m“ úê+ùxÓŸ—*·JM<?{NǪU«xüñÇo:X½èrrä>ß¿ÿõƒËž=åÏÃ'Ÿ@AÜœü|¹ú!rí>WZ‡½¹-Ó½zÉY"­s[þô¥¤Ôí\û÷ï'ÌÛ÷´4ùtìÚ×YYõ«Ç.!ŸóÙ¹ ­rŠîCÈ©rÚìQä³Jk©ÏK½4 W‡|üËÅéÃG9È«¸µAo109ŒC^ÅõEÞ‹ r°Øù<Ø‹Óp]þ¹Îå¼¹=«{_ry[ä`öâØßœÚ<"á_GPPJ¥\áäí·aÎyܾ=ùûå3¯ÄÛ[>ëä/þ]»äªžï¾[ÏC§á_öË/¿0bĈ?sÕÂB.ÑØdfÊÁƒV+WÃ-.–g÷§L¹ÐT—+|W+be쎒@êŒTõêÅ+Sö˜yÕÔÁáòëvì ¾Œ%ÿwa¡\ðJš„„9½¤m[¢¢¢())áž{³´««aÕ*¹¨QHˆœºÛªÕ•?—²°÷”FGËGx9;_8ºöHÌÖ­åZPW*,-ffrÕsáÖ¹-Ö„yä¶ÿÞ²…Q••NÖ6M-ètr…Š›]aÕ ¯ž†kÿùßl ðŸëÕÈéºç‘ƒÚ‹DÞÛyñ‡)9ý÷ä`´Ø ¼¼‚»¹PQ6þbm€¿æg/z^5rÚðņ9·nOgmzé±?V›…FwüøqzX[£øúk¹ÂÀœ9ò!ŽffddÈçªÏ{åûvì(¢µZ9•&5U^åÁªÐÅÅÅQRRBäÅç§ÜBÕÕr†A×®u··ÖÖä¸ÑŸ I’‹Ü9"€jÏA={V>ÎE’ä# ÌÌä꽂PË`0pbÇvxy1~æL̯ö^S#Ï»ýµÜŸÆ¯»¢”™)ïÓûðà —‰`UhR²³aÒ$j¬­Y¿~=cÇŽ½ìØIIºp,ö•¾{÷ï—«ŠWTÈYa™™ra¤ee%¯†Ê™/GŽÈ…"/ff&& ›‚Û2`­®¾0HJJ¢03“¥–/¼Ò•7C¼G4y?gr{qPØ ùLÔKϾîÅ…³PkmE>¯ur ›‡|&©ò~Ì·‘÷‰s!Õ79õ7€º{Sݸr¢÷UV×êeò~Ö‹µB>KUhtÄŸ8ÁcZ-ŠiÓä ml kWÊÊä™Ã«ŸÖáá!¯°–”Èë;ïÈÕî¡©Ñh4,]º”Q£F]ù¬á«9tHþLtèpÝ›¦¤Èû¶gΔ¨õÓOrÖÎСWk›äUÖ‹ú÷«^Ü#§ûþ³ØËià>äÀóÀ)ä`¸rÀjŽ|üÌÛÀ¨‹§ö˜ÿKß럶]ê¶-¯ugÓjµlݺ•áãÇ£ìСNE–íÛå²í³g_ÿ|ùéÓå¶««©_‘ \Ý_ýE§N°»™|õÊJ¹ÀÞË/_÷¦ÈŸƒä¬Ï>“÷~;,¯hmÚ?þ=&®¬¬äÉžÈHy?TJмW04TpAþXÞ)Å’„00¬]‹{|<ƒ?øà²óìóò`Ö,¹NŸ~áò¾}å@vþ|9˲G¹˜ÌÕ²jÁ¤†ŸFÿÑGlÞ¾´´4^zé¥:{Wkj䬖֭嬯;`Å xè!yju5”–Ê%;Äwëá¶û3ëtò9HVj-Õk6rOj*íê“P+¹ðQ_ ùlÕ \H±mlzS÷H3à,r {±AÈ+¶‰È{M×÷"ÿ%ü€ÅÈç”vþçöµçŠ"qSK‰ä^z¡š[S XhÒÓÓ©ÉÊ¢KD„ñ UƒV®”ÿwÖ¬ ƒæk±´¼~P+¦”œœÌÁƒ™?þMå@¡sÆ.)ñ¨×ËgŸ=+§ùz{ÃùóòêªZ-ª™3¶l‘ƒSwwù¡|î¹GNùýáù²wß•÷*Îé„›e¨¨àìâÅ„~ð–—|!×ÔÈÕLƒƒå>x©ÈH9%½W/yÿµ™™È MP~>|ù%š—_æuëØ°aï¿ÿ¾quµª Ö¯‡_•«õúúÊÅŽúõ“O¡\½Z^œÍÍ•'eüÄV´;Æm÷uVT$¯°ªcŽ6kºÇÇñŸü ‘¨[éVŒF07#¯Š¾úÏõ‘W[/f†d^:®²ÆO!¯šzsáÕžÀÈ)Æã/ºO0òŠì¥EoS¿Û‚©åÄÇs×޽؃£#’$¤ûMDÛÚ6ø)Áä 7ndРAòñd7ÃÊ ©ÿô:9 T©0~N–.•'8_yEÎ>{&N”ïfo¯¾*§ ]ëªTòçjà@yU]->g­uì'ƒ‚Qçòœyõôä•û+¢žž7WlFL¢ºiÐ Ö$&²zõj>ùäüüü$yì¾l™|Úäë¯C‹ -™™Ég§VUÉ3’$³73w)4o·]ÀZP Ï@Öœ9ÍÌêj>½™s÷ôÈçšöàÂy¢ßaÀä•ÕL䊸g¤¹"“g﨑‹0]i ãL¾DN®},žïÒsZ-‘ƒfA¸˜N‡ê«¯þøã(ÿ©¬‘”$¯}ð´iÓÀÇ„&"%%…¿ÿþ›¯¾úêæïœ—GLœoÎsÄÇÞzKÞ:rô¨¼båî.­±±0v¬\²ÖõbcµZ«Â­QZZÊß~ËôW^Áꢒ¤$¹ºt¯^ò*j}Ž„&Ã×—˜ðp~}ç>ÿüs|}}Ñjåê¼Ë—ÃäÉò_Wêç¶¶ò?‘ê~gºíÖädy2Þ­¶}úàîî~cw”Ï9]Žœúû0òñ2!Ȫ-rŠïQäJ¿냜æ{qÀjŽ\á÷j…nºKKS{œ¹PÜI®!5!b¥åsÏ!©Í(*”S_zI«ÂíC¯×³nÝ: pãßç)úu3 µeÆ»ba!£ùûo¹PGíy§}úÈÿÁTö­\I£#;Ëû ù<ì÷߇©S/?jCš•š8q‚d''>øàÞxã |||IKƒÅ‹å³¨_}U^5“2•ÜvëîmZ"ƒKÙ¸7w ˆâF{¾ø9ø\¼ª|nê£ÿÜæ)ä‚F£.¹oàNÝTbrJðÕ¸_p劻‚pz½ž »va>bfnn$%ÉÕ±§Og: ·—#GŽpäȾüòKÌêqÞé#t{¨ƒþ©;àå%ÏÐ?úèM?” ü+Š÷í£å¼y ùðC”*ÕÕ'ŸŸ=eмº*ÍÚï¿£ýûoXYѯ_?:tèLjª\ oèP¹N€8ëT¸–&°J’Dee%XXX`ggwÃ6ÊÊÀ,9ûE 8Z’Ç¿úêê«öŸµiJ‹ ݃\ðh;p9H­åûÏ_š&Ö‚ú:ÁêÉ`0PZZŠV«ÅÚÚkkëŸX¨©¡hÃíßϬ·ß&#æÎ•ÏÜëÜùÆFþ-z½žââb$IÂÖÖ ‹›ëãÿ¨¬¬ä»ï¾cܸq—ypåç•ÏŸÜ¿_>ãÔÓ~<ß›7f\ø ’ÿ BCH’DEE•••XZZbkk{sÅÀþ‘CÒË/0o ¹‡ÒRøö[ù\ß™3Å9ª‚é4x¬R+!êÕ«ù¥m[UU<úèc|õ•¼gõ£ä½ª¢@˜p=M®‹œWÕ’ ‘@^5}ö ïZ“{…¦J§Ó±wï^–.]J~~>íÚµc„ ´oßþÆ@’`ófN¿õ'L ¬Ì?þ€#`Ø0‘J#˜^UUk×®eõêÕèõzÂÃÃyê©§ê•λwï^lllèÝûú檫å"J––òI6ë×ËG"Ü÷B[ü:šú]n7'NœàÇ$11///&NœH=.;Šæz>[±¿G!bØ0¢£åÊÓ£GÿsÚ•©_¥p§ÒétìÙ³‡ü‘ÂÂBBBB˜8qb½NÝÐ:9ñ¥‹ ç ™ùäÞ~ûmªªªnì*+Éûúk–Ø8ã4™ÿýÏœ{ï•V1C)˜š$IlÙ²…~ø‰'2sæLùßÿþ‡F£¹©Ç:|ø0 .dÚ´iØØØ\ñ699ªýþö›|å°aò)6sçÂøñ0ô~•\ÚWn‘òòrfÍš…¥¥%óæÍ£K—.¼÷Þ{œ;wî†C**bݼy€{šÂæÍ0ož|œRD„VÓ:}ú4ï¾û.}úôá“O>A¯×3wî\ª««oüAÊË)IMåÓ~ ËÖ±cßå‹/<ðô„»îÁªpsšTÀzøða´Z-O<ñÁÁÁŒ;{{{vîÜyc`cCµÇ,Æ8<‡ãsŽrÀj¼€\L) ˆC.žôr€úòþÕ‡©{ŽªÕ?÷+VÂ-´}ûv|}}5jÁÁÁ<þøãsìØ±º¿øVïÄ)þœwÞ~Ú·+«BÓ ×ëÙ´i={ödèСtéÒ…ñãÇMrrò ?NAA~ø!=öÿ6Ÿ/W¡Ù²…ÜÃÉÌ›ü\ŪנYµ–Ž1ë¥ œ¤$Ô®G½x!ªØã¦~[„ÛÌÁƒ1 Lž<Ù8V±µµe×®]7ü%óçS¶jÆNç7ì07‡?„Þ½Å^>Áô¶mÛ†ŸŸŸq¬2yòd ox¬‚V òËO_­íLŽwæ™gÆ£Ãáf4©5™¸¸8ÜÝÝñûç$` ÂÃÃ‰ŽŽ¾¡ûk4•‰tÿ±»¼UÜø›Èg©ÎF>ÛTqá¶('';;;¬­­þ`$//+++lÅ9õvâÄ :tè`\1òööÆÏÏcǎѳgÏëÞ¿¨BÏo¹Ï3iRO>Y÷ަD§Ó‘““ƒ§§çM§È™Š^¯'''77·z÷ä=O'OžäÁ/”?ïØ±#555$''ÓæÊWWž>ÍÁ§žâ3ss|¡tÐC@Õ–SÄ~„Óº@‚î«ÆÖ&=PƒÊ' ³òbyIÊ`¤¦òòäÓåÿ¥iüêêjŠŠŠðòò2õÛ~ÃjjjÈÏÏÇGlŒl¸¸8<==ñõ•‹WXZZvÃc•âµ³ñ‡$VÏI^¼ñ†|_Sûª,//§²²²^éü¦RYYIYY¦nJ³vâÄ :uê„Õ?Ký>>>x{{süøq"##¯{ÿâ¿v±fözþêð»Þ——9Ç˓1Mi‚½¢¢‚êêj\\šOQ™¢¢"œî°%ê&°`fffü€¨Õj<==Ù½{÷5ïWVVÆáÇ Æi”Ú  .Ü@܇¼wÕy_k¢i_ëŽ;hÓ¦M³8ìß¿OOÏ +M˜$IO—.]LÝ£ÜÜ\ÂÃÃAœ½½=öööddd\ó~ìÝ»{{'ÞxÃ’öíÏ‘’bêWsu•••ìØ±ƒ»ï¾ó¦U_¢¦¦†;vЫW/ìììþ€ÿ2ƒÁ@NN©©©jµ& ??¿N$´Z-………×¼_RR 0¹†ŸòÇÖ Uµ+ªÏ‹HJRÖ‚Ìþ>x{ëiÙÜÜÎZ „^´ÿ;+Kþ§TÊKU ¯gÎÜò×™——Gtt4C† 1õ[~ÃŠŠŠØ¿?C‡5uSnØ™3gÈÍÍ5u3êÈÏÏÇÜÜKKKÌÌÌðððàÀW½$Iœ={–#GŽpôŠõ-_¡ÿ=ætꔈZ 7‘MÜh’““IOO¿¡=äMEzz:gÏžå®»î2uSnˆN§ãäÉ“7—jÛrsséÞ½{±Š™™™×|-111XYY±æ›v²©IMM%;;›ˆˆS7å†8q€N:™º)7¤²²’ãÇ'øê«I¬W£×ë¯zJ¥"$$„¨¨( jµúº#ÊLýŠÀÝݲ²2M9ßGGGy»´Y’$òòò077§eË–¦nÎu]«ÛÛÛÓ¦MNž<‰§§'ÖÖf$%™ºÅ×&Iþþþ$''ׯª ‰ÚìççGVVÙÙÙ¦nÎuéõz²²²ðóó»¡ º¦$IÒ5ƒj///œœœˆ‹‹Ãή%ý¦wC­®B©LÁݽÐXý:ðŸ£ÂŠ‹å¦d0ðõõm߇·Ùßß¿Yµ9))‰ÐfrV×µ¾ÇÍÍÍqssãÔ©SøöráÙ^©\cüorz½ggçfÕ_ nnnͦ͆¬¬,ú÷ïoê¦Ükõq777t:§OŸ¦ËT{º4ïëk½›fÓ_cXsisii)ÕÕÕ„„„4èqšTÀªP($ I’Œÿß`0\s0¦P(ˆˆˆhV³#ÂK©TÖéãƒI’°··¿ê}T*Ç7uÓá†Ô~w×Òëõ˜™™]sûƒ™™O<ñ„©›.7¤>c+++ž}öYS7]nH}Æ*þþþL:ÕÔMnSMªèR›6m(//7®j4NŸ>Ý,RPáF„„„™™i¬˜š——Gvv¶èãÂmA¡Pжm[’.JHLLD­V7«}p‚p-ÁÁÁ”••÷’ÕÔÔ ¾Ç…ÛFHHhµZ@®»’››K«V­LÝ4áÕ¤Ö.]ºPPP@ll,Z­–ÜÜ\¢££›Í^A¸žÈÈHbbbÈÎÎF£ÑGff&}úôiøƒ ‚‰©T*"##ÙµkåååTWW³wï^ 6uóá–èÖ­¹¹¹œbïÞ½DDD‡¯¯¯±ß BsW\\̬Y³(**¢uëÖ:tˆòâ‹/šºiªɬ•••9r„'Nкukzôè½½}³)Ü"×"I¥¥¥ìرƒôôtºwïNûöí›ÕñF‚p-’$‘••ŶmÛ¨®®¦W¯^´nÝZ$ÜV*++‰ŠŠ"66–6mÚн{w1Vn’$QRRÂŽ;ÈÈÈ G„„„ˆ±Š`2M.`AAAhb{XAAA¡–XAAA„&I¬‚ ‚ ‚ B“¤6unz½N‡$I¨ÕjÔê okíâ:…B™™Y¢ ’$¡Óé0 ¨T*T*Õe×מ٩V«Q*•·´¨ƒÁ`@«Õbnnn|ÜKÛ\û¼—¶Y¯×£R©P«Õ—µY«Õß[Ýf¡qI’dìãµýA¥RÕ¹¾!ý¡¶^©¯Ý µm·°°¸âkº^›¯ô¹¬m3ü;ŸK¡q]ÚÇÍÌÌ.ûλ™þpéçãZ¿·BíïÏÅ…­Ò‡¯÷ 4?µý¡v¬qéw^CúÃõ~nFƒR©¼l|uµñÑ´ùZ¿BóSÛ‡kÇç5´?\ïû´¡jûò¥¿=—޽®Öf¥RyÅøâßlsckðË/¿pàÀ*** eòäÉ´hÑ€ììl–/_Α#GpvvfÔ¨QôêÕ 333 ±±±üôÓO$''Ó¦MÆŽK»víP(h4vïÞÍO?ý„F£!""‚±cÇâæævËÚüøq>úè#¾ÿþ{lll(,,déÒ¥:txàˆ¹¹9ñññ¬X±‚„„ZµjŸqãèСJ¥­VË¡C‡øá‡¨¬¬¤k×®Œ=Sÿ©„zJNNfùòåœ8q…BÁ€9r$®®®H’Ä©S§X±bgΜ!00Ç{ŒöíÛ£T*Ñh4ÆþPUUE×®];v,^^^€\ió×_eëÖ­XZZÒ¯_?FU'¸l½^ÏúõëÙ¾}; ,0^~öìYV¬XÁÉ“'ñóócܸq„††¢R©ÐétDEEñã?RTTDçÎ=z4þþþTUU±víZ6n܈J¥¢gÏžŒ?+++Sÿ©„z:xð ëÖ­#..ggg† Æ}÷݇µµ5Z­ÖØŠ‹‹éÒ¥ £G6~ÇWUUñǰiÓ&ÌÌÌŒýÁÒÒ€ÜÜ\–.]Ê‘#GprrâÑG¥OŸ>·¬jruu5‹-B§Óñ /r¿ŽŽféÒ¥äääÊèÑ£ 4ÞçÏ?ÿä?þä3{ì1ìíí(**béÒ¥œAƒrظq#k×®E¡PУGÆ­­-а1Á­PVVÆ[o½Å!C¸÷Þ{¯iÛ¶m¬\¹½^ODD=öÎÎΔ——³dÉöïß­­-÷Þ{/Æ 3¶ùܹs¬X±‚'NàëëËøñã «3Ù$4%%%¬[·Ž­[·R\\LûöícûÐ’%K8pàvvvÜwß}Üwß}ÆþÐ1Á­’’Âo¼Á»ï¾K«V­¨¨¨à§Ÿ~bçÎX[[3pà@zè!ãø(%%…Ÿ~ú‰ãÇãááÁøñãéÒ¥ jµ½^ϱcÇXºt)ÙÙÙtìØ‘1cÆdê?U½©æÌ™3ÇÔh®ª««ùæ›oزe cÇŽ¥OŸ>ìÚµ‹C‡¹¹9}ô <þøãXXX°dÉÚ¶m‹EEE̘1ÆG||<7ndàÀXZZ²ÿ~>øàî½÷^úõëÇúõëÉÈÈ 22ò–ü”––2wî\¢¢¢xê©§077G§ÓñÅ_Å„ ppp`éÒ¥øûûÓ¢E 4 ÿùϰ²²âñÇ'--Õ«WÓ§Oìì숉‰áÍ7ßdàÀ 2„M›6qúôiîºë.1Cß 1wî\ÒÓÓyâ‰'æ×_%33“ž={ûƒ­­-“&M"99™?þøƒ~ýúakk˱cǘ5kƒæî»ïfÓ¦Mœ9s†~ýú!I+W®dÕªUŒ5Š€€~þùglllhÛ¶í-™ LIIaÖ¬Y”””ðØcò@祗^¢¦¦†)S¦'zôè““§OŸfæÌ™tïÞx€-[¶ÍÝwß ÀúõëùñÇy衇èС¿þú+ …â–ЄƓ™™ÉôéÓqttä™gžÁÒÒ’ï¿ÿ;;;:tè@||<3gΤgÏžÜÿýlÞ¼™ãÇûk×®eÙ²eŒ9’~ùåÔj5íÛ·G§ÓññÇÏã?Ž••?þø#mÚ´ÁÇÇç–ôñ;w²`ÁÜÝÝ8p ÷ûW^y…:ðÈ#°wï^víÚÅ}÷݇R©dË–-|ýõ×<ðÀtéÒ…U«VQ]]Mxx8ƒ¯¾úŠƒ2qâDY¶l~~~øûû7ëú;Õ˜5k}úôá±Ç#55•Ÿþ™N:áééÉ_ýÅ·ß~ˈ#gÕªUÔÔÔ†Á`hИ ¡´Z-+V¬à矦{÷îtèÐI’صkŸ}öC‡%22’5kÖPPP@DDƒÅ‹³}ûvƇ‡‡Ë—/ÇÝÝÀÀ@´Z-/¿ü2•••<õÔS³bÅ """Œ¯Ð| ~úé'–.]Ê#<ÂàÁƒ‰ŠŠbÛ¶mtéÒ[[[¾ýö[víÚÅøñãqsscùòåxzz€F£©÷˜àVüæWTT0þ|¶mÛÆ£>Š««+z½žåË—³~ýzÆŒC‹-X±bŽŽŽ´nÝ­VË[o½E^^O>ù$:Ž%K–йsgÜÜÜHKKã•W^¡]»v<úè£8p€mÛ¶1tèÐf;)#VX ¸¸˜;wòÜsÏ1tèP:uêÄ!C8þ<–––œ8q‚ÿû¿ÿ£W¯^;vŒ5kÖЭ[7¶mÛ†R©äùçŸÇÛÛ›–-[2eÊ8À½÷ÞËï¿ÿN‡xòÉ'P*•ÌŸ?ŸsçÎÜ ¶×ÔÔðÝwßQPPPçò³gϲÿ~f̘aü$$$°fÍzôèÁ®]»¨®®fÚ´iЮ];üqvíÚÅèÑ£Y»v--[¶äé§ŸF©TbaaÁ;ï¼C||<;v4õŸL¸I œ?žùóçÓ®];lmmyíµ×xñÅÙ³g†çŸžV­ZÌäɓٽ{7<òkÖ¬¡U«V<ýôÓ˜››óÞ{ïqúôiÜÜÜØ°a<ò<ò ¦Ö¬YC¿~ýpuumPÛ‹‹‹ùâ‹/.»üÀ0sæLÚµkGxx8&L`Û¶m<ùä“lܸOOOžy欬¬°±±áõ×_çĉ²víZî¹çÆŽ ÈW«W¯fàÀx{{›úO&ܤ={öàääÄë¯¿Ž——Ý»w§¢¢‚ßÿÑ£G³aü½½yæ™g°°°ÀÚÚš™3gKË–-Y·nC‡e̘1À…×þýû“——ÇñãÇyýõ×éÝ»7111Æß€†YYY,Z´è²Ëÿúë/™:u*8;;3mÚ4Ž;FÇŽùã?èÛ·/ãÇä”âeË–qÏ=÷P]]Íž={˜>}º1(OLL4þÔ® ÍÇæÍ›éÑ£‡ñ;­S§N¼ôÒKlذ6mÚ°fÍîºë.cÐjµüôÓO 2„ÊÊÊ êðáÃlÞ¼¹Îeƒßÿ.]ºðøã/ÿæ›o¸ÿþûQ©TlÞ¼™gžyÆ86KKKcÍš5ôêÕ‹èèhòóóùä“O ¡K—.>|˜­[·³„æC§ÓñçŸ2fÌãÄthh(#GŽäرc ¶nÝÊÔ©S+ô)))¬Y³†ž={Uï1AçÎÔvƒÁÀÊ•+IHH¨syvv67ndüøñ<üðÃäåå±fÍúôéCBB)))¼û‡‡Ó¯_?öïßÏŸþIHH›7oÆÞÞž©S§âää„««+ÿùÏ8zô(=zô0õŸ¬^Är@(•JBCC‰ˆˆ0^fgggÜ'’––†$IÆ”S¯Ž?@\\­[·ÆÅÅggg‚ƒƒë\qÇjß¾= …‚óçÏ7¸í‡"::ºÎ—=È òòrÂÃ×õèу¸¸8´Z-qqqøûûS:mmm騱c6wïÞÝ8 ÂÆÆæ²£Ð<˜››Ó§OÚ´ic¼ÌÖÖÖ¸o(..Ž–-[âéé €½½=:t¸jnݺ5VVVœ9s†²²2RSSë\IJJ ……… j·Á`à·ß~C’$FŒQ纄„<<<Œ)„‡‡×isçΩBþþþ¸ººGUUçÏŸ¯Óæ=z••ENNŽ©ÿ\B=XYYqï½÷âáá€B¡ÀÊÊʸŸ/..Ž.]ºSx[¶l‰³³3ñññTVV^Ö"##ÉÌÌ$77—´´4ôz=:t¨s}LL =½¼¼œ¯¿þš¾}ûZ纓'OÒ±cGã6üüüˆ‰‰A£ÑpæÌ™:mîÒ¥ ÅÅÅdff’MiiiX=ˆ7~î…æÅÃÃ{ï½×8Ù`nnnLuÔh4$&&Öé]»v¥¨¨ˆ¬¬¬ "''‡¥K—2~üxŒ— âããë´¹cÇŽÔÔÔššJ~~>yyytïÞ½N›Ïœ9Cee% ¸ººS:ÍÍÍéܹó-i³`ÁÁÁÜu×]Æÿ¶±±Á`0 ×ëÉËË£  €nݺ¯ïÑ£ TUU5hLÐP‰‰‰lÞ¼™§žzªÎåEEEddd\6Ö8þ<¥¥¥œ;w[[[cНB¡ {÷îÆ6Ÿ­Zµ"99€ŒŒ ìììŒùè666xxx””@zzzU&/// CƒÆiii,Y²„1cÆ\¶·´¸¸˜ªªª:i1¤¥¥¡ÓéÈÈÈÀÆÆÆ¸_ÏÒÒooï:mvqq1¬îî›“™™iê?—P;wæÍ7ß4¦±råJ"##133###[[Ûkö‡‹û°‡‡fffdeeQUUEaaaëÈËË£¼¼¼Aí>yò$›7o6¦a^,++ ã`ÞÌÌ ??¿:mvrr2¾flllHKKC£Ñ——W§Í­Zµ¢¸¸˜’’Sÿ¹„z¸ÿþûyüñÇ©]ÉÉÉlÙ²…¾}ûrpvv6^ïêꊵµµ±?äçç_Ö‡ )--¥°°­V{Ùo@JJJƒÛ½aÃRRR7nÜe{K322ptt4¨qttÄÉɉäädôz=999uÚÜ¢E ***((( ¤¤„ÊÊÊ«þÍÏóÏ?Ï AƒŒ¿Ë{÷îåôéÓôîÝNwYð÷÷§¬¬ŒÂ ê«6 ÌÛÛ›Áƒ_Vl&33³N›}}}ÑjµäååQVVFIIÉeŸË¬¬,jjjÈÎÎÆÜÜÜø V«iÑ¢EƒÛ,˜†¹¹9ï¿ÿ¾qb]£Ñ°zõj,-- ¦´´”ÒÒÒËúCff&¦Ac‚†ÈËËcÁ‚Üÿýu¶@Ž'Š‹‹/ksNN•••äææ¢T*i÷ …‚V­ZÛœ‘‘ƒƒƒq¢ÕÁÁ—fÝÇEJð- ÑhˆgáÂ…¤¥¥1{ölüüü®zûëýè_ëúÚª`õUYYÉ×_MÛ¶m>ž>ú膋ðÕ®¨]«Í×úm2Í›^¯'!!eË–qüøqf̘AHHÙÙÙW½}CúCC¾õz=?þø#Œ9ò†³Ê®7>jH|ÑÔ‰€µ´Z-ßÿ½qÏÒŒ3ê¤O^Ií,N}®W«Õ ÚCÅ¡C‡˜4iÛ·o7¦oÛ¶í²ž‹Y[[_s¿ÕµÚ¬T*EÕf¬¤¤„yóæ͈#1b„1}òj®×®Õ‡-,,ê]p³þøã P*•lݺ•3gÎPQQÁæÍ›¯¹ß¤6uæJ ÖÖÖ×ló­ªú*4¾ÄÄD>ÿüs²²²˜0awß}÷5 Æ\¯?˜››_³?\ï7àZ***øî»ïpqq!??Ÿ-[¶““CII Û·o¿æþ¤k=¯™™ÔÔÔ\ñz+++Qp©™2 >|˜O?ýkkkfÏžMxxø5¿gÍÍÍ177¿jxCÆד••Å’%K !66–“'ORSSéS§8tèÐUÇ*×YZZ^³Hε~„¦M§Ó±fÍ/^Lhh(Ÿ|ò íÚµ»f!++«z÷‡ëý\OBB›6mâ‘GaÇŽ°ÿ~ãQ—WbiiyÍ×t½>ÜÏ¥©‰€µª««Y°`111|üñÇtèСNGòññÁÜÜœììlã¿ØØX9ç>--ŠŠ lll())!%%ÅXÜ&88˜ÔÔTãã?ƒÁ`|¬ú¨¬¬ÄÓÓ“-[¶r©o€_ý•‡zoooìììÈÈÈ0¦ ÇÆÆÒ¢E T*ÁÁÁœššJuu5>>>ØÚÚâííMjjª1Ý,66ww÷ $IÂÎÎŽ_~ù?ÅÅÅ,_¾9wîÅÅÅ8::¢ÑhHHH¨ó¹ÌÈÈ@§Ó¡V«÷oÑ¢–––´hÑ‚ÔÔTcéùØØXœœœê¤} ÍGzz:/¾ø"={öä£>ºl ^ÛjϘÌÌ̤´´???¬¬¬ðóó#55Õ¸ÿ)66ðööÆÂÂâ²ß€V­ZÕ;øÓétØÚÚ’››ËŠ+¹€ˆJ¥â·ß~#$$„àà`²³³Ñh4˜››“››KNN;wÆÌÌŒV­Z‘ššj,„ ÎÎÎèõzìíí¯øЉ$ÁtöìÙÃûï¿ÏSO=ÅСC±°°0ö?333Z¶lIjj*!!!œ:u [[[œ±±±iИ >ª««qss#11‘ÄÄD@ž¨9xð jµš   Z·nMjj*‘‘‘€<é¤V«qssÃÎÎWW×Ë>—>>>XXX@BBEEE899¡Õj9}ú´ñ7@h^ ?üð7ndöìÙuj€œÂëââBZZš1û±¶?˜››7hLP_åååøøø°ÿ~öïßoœÚ°aƒîÝ»ãááAjjª±Èjll,žžžX[[ãïïÏŒ[R$IâäÉ“uÚœ““CMM äåå‘••ÅàÁƒMýçª7±‡µòóóÙ¸q£ñ¸­VKuu5ÕÕÕèõz‚‚‚P«ÕÄÄÄ,Þ¿¿±bp·nÝ8sæ 999 rssIHH gÏžDDD°ÿ~cºá‰'P«ÕÆ€¶>ú÷ïÏ‚ ˜?>óçÏgúôé|øá‡Üwß}´hÑGGG¢¢¢ŒmÞ·oݺu®]»’’’BZZƒââbbccmîÖ­0žŠ§ººú²¢ BÓ'I111ÄÇÇóÜsÏáêêŠF£1öqI’èÚµ+ÉÉɤ§§c0(**âäÉ“—õáÚÃS§N¡ÑhèÔ©NNN´nÝš½{÷¢×ëÑëõìÝ»—6mÚ4è¬áǼN1bžžžÌŸ?ŸÂÂÂÈÍÍåܹs ***ˆŽŽ®Ó‡=JUUƒ³gÏRPP@×®]±±±¡}ûöuÚ¼oß>üýýñõõ5õŸL¸I’$ñçŸbooϤI“P©TÔÔÔP]]m\iìÖ­QQQTWWc0HLL4žÇjkkKHHHþ°gÏZµj…··7XXX+UÖþôìÙ³Þ«½½=/½ôŸþ¹±‡……Ñ£GÞ{ï=ÜÜÜèÖ­'Nœ ¤¤ƒÁ@jj*iiiDFFbnnNhh(ûöí3¶ùðáø¹¹ÑªU+üüüpqqáСCu~ºví**7C’$ñûï¿ÓµkWã`µ¶kµZ,--éÔ©SþpèÐ!<==G×4dLPþþþÌ;ר¿çÏŸ££#£FbÚ´i888Ð¥Kc› ÑÑÑØØØÐºuk¼¼¼ðóócß¾}Æ4á}ûöŠaaaäçç*++9zôhƒÚ,˜ŽF£aåÊ•Œ9’°°0ôz}±¸··7ÞÞÞìß¿¿N ÃÖÖ¶Ac‚ú «Ó¿kO}íµ×5j^^^\6> ÁÙÙ™öíÛSYYÉéÓ§1 hµZ{Ùu‹/¦wïÞÜÿý|þùçœ:uŠóçÏ£P(ŒUK»wïNpp0³fÍ"22’Ý»wA§NxôÑGyã7xýõ×qwwgÛ¶m<öØc ::ÃÒҲΠ£vÿ“³³3ÖÖÖX[[3zôh¾þúkÉÌ̤°°3f V« §sçÎÌ™3‡þýûsàÀÚ·oo¬”Ôjõeß§J¥cß3f o¾ù&3gÎÄÉɉ;vðä“O3üq>þøcRRR(((àìٳ̙3KKKÚ·oOïÞ½yçw2dG¥eË–ôë×ÏÔ.¡222HMMåwÞáwÞ©sÝܹs5j'Nä¿ÿý/IIIpþüyæÌ™ƒ……EƒÇõannn“ƪôÆ1ÌäÉ“yï½÷ÈÎΦ¼¼œØØXæÌ™ƒ ÁÁÁ 8>úˆÁƒsòäI<<<ŒçÅ÷ïߟ¿þú‹™3gƶmÛ0`­[·6õŸ«ÞRCkëßÁ Œé*—jÛ¶-ŽŽŽTUU±cÇŽ9‚‡‡ƒÆßߥR‰$Iäççó×_‘˜˜HXX}ûö5VÙ5 œ?žuëÖQQQAß¾}‰ˆˆ¸¥ûAËÊʈ‹‹£k×®Æt/FÃÎ;9tèÎÎÎ 4ˆÖ­[SA غu+qqq„„„пÜÝÝQ(H’DZZüñEEEÆ6‹½!Í$I¤¦¦’••uÅë»víŠJ¥¢°°-[¶Oûöíéß¿?nnnÆ>œžžÎêÕ«)))¡oß¾tëÖÍØ ‡b×®]˜››Ó·o_ÂÃÃoéÁÖµî‹Wù‹‹‹Ù¶m111´nÝšAƒáééiìÙ™™¬]»–ììlc® ¢ ÇgëÖ­( z÷îMDDD³=ŒûN¦Óé8{ö¬qÿÐŬ¬¬ E’$222X»v-999WìÑÑÑlß¾…BAŸ>}èÖ­›±?TUU±sçN¢¢¢pwwgðàÁ´lÙò–8_ëÌ™3¨T*c¦$Idgg³~ýzÒÓÓ‰ŒŒ¤GÆ À`0ÇæÍ›ÑétÆ6×RÓh4ìÚµ‹C‡áääÄÀiÓ¦Í-m³Ð8jjjŒ™N—rss#00ƒÁ`¬¬n0Œý¡v‚¢!c‚[%::___ÜÝݹŸ9s†7R]]müm©×ëõìÚµ‹`ggÇ€ 1¶¹¸¸˜íÛ·süøq‚‚‚¸ûBóR^^ÎÉ“'¯x]@@îîîèt:víÚÅÁƒ±··gÀ€´k×®N¨ï˜àV¨©©áرctêÔɸ7V¯×³ÿ~öîÝ‹••wÝu:u2¶¹¬¬Œ;vpôèQZ´hÁ=÷܃···±Íµg¹ÖÙ¬'ÖEÀ*‚ ‚ ‚ 4IbºTAAAh’DÀ*‚ ‚ ‚ 4I"`AAAš$° ‚ ‚ ‚ M’XAAA„&I¬‚ ‚ ‚ B“$VAAA¡I« ‚ ‚ ‚Ð$‰€UAAAh’DÀ*‚ ‚ ‚ 4I"`AAAš$° ‚ ‚ ‚ M’XAAA„&I¬‚ ‚ ‚ B“$VAAA¡I« ‚ ‚ ‚Ð$©æÌ™3ÇÔ¸ÓUVV²mÛ6–-[FRR-[¶ÄÒÒ…BAuu56là×_¥ªª sssÒÒÒpuuE©TR^^ÎßÿÍÒ¥KIJJÂËË Š‹‹IHH ¦¦†~ø;vàêêŠJ¥âçŸfÍš5øúú¢R©HHH ´´”'Nðã?’žžŽ ,_¾œ½{÷ˆ­­- …ÂÔo™p›ˆ‹‹cÕªUcaaaêæB£8~ü8k×®¥mÛ¶˜››7øñþþûo¢££iß¾½©_šp‡ÓëõÔÔÔ R©ÄXA¸mI’„V«E§Ó¡V«MÝœ;‚B’$ÉÔ¸“3sæLvíÚEïÞ½9þýôÓ[Ò·¡)Òét|óÍ7äææ2wî\S7çŽ ¦LH’$¶oßÎÎ;Y¼x1ݺu£¨¨ˆáÇsðàAÚ´iÃo¿ýÆwß}GÏž=ÉÌÌäÀÚÚû |ýõ×ôìÙ“ôôtž~úi/^ÌСCQ*•L™2…|¬¬,|}}yüñÇyõÕW),,dìØ±ÄÄÄ0xð`,,,øî»ï°··ÇÃÃE‹±aÃ:uêÄßÿÍ«¯¾Jff¦X…›f0(++£ªª kkkìííë\/Iùùùèt:ììì°¶¶6ÎÎ JJJ¨®®ÆÖÖ”J%’$¡ÑhP©TTWWS^^޵µ5vvvTUUQVV†Z­ÆÉÉ …BAMM jµšªª****Œí¨¨¨ ¼¼333Q*ÅN áÖ¨í»555ØØØ`ggwÙõùùùèõzììì°²²ªÓŠÐh4ÆÏDm¿¿¸/kµÚËž·v•ËÒÒRôgá_¡×ë)**B¯×coo••z½žôôtöîÝKII ÎÎÎèõz z½žÒÒRÜÝÝÑjµH’„$I£V«qpp@’$JKKÑét8::baaa¼mígÉÌÌ {{{ ¥¥¥èõzœœœnI¦‚ \Iuu5%%%¨T*033C£ÑpòäIÒÓÓ©©©1^fffFee%:'''$I¢¢¢‚ŠŠ Ôj5vvvƾªÑhP(h4ÊÊʰ´´ÄÞÞFCii)...¨T*S¿M‚XMH¯×sðàABBBˆŒŒÀÍÍ… bmmÍŸþ‰¹¹9ýúõÀßߟ»îº‹˜˜¶oߎ——UUUlÛ¶ €6mÚ°k×.†Š««+ááá(•J\]]èÙ³'ØÙÙáåå…Á`0¶'""'''œœœ°³³£sçδjÕ •J…XêcõêÕ|ÿý÷$''Ó®];^xácŸ¯©©á×_å÷ß§¸¸˜ž={òæ›oâïïOMM ëׯgáÂ…¤¤¤Ð±cG&NœÈý÷ßOUU ,ÀÓÓ“Í›7CPPÓ¦McõêÕìÝ»fΜIdd$_~ù%~~~lܸ‘“'OÒ¶m[ž{î9V¬XÁ¡C‡pssã7Þ ÿþb/4˜N§cåÊ•üðÃdeeÑ©S'f̘A×®]yôÃ?ðÇPYYIß¾}yë­·ðôô¤ªªŠÕ«Wóí·ß’MXXS¦LaРA”––²`ÁÂÂÂXµj666u&u:?þø#¹¹¹L›6 S¿Âm¦¢¢‚eË–ñã?RQQAïÞ½™6m,Y²„üü|>úè#^}õUöìÙƒ……111ìÚµ‹C‡ñ÷ßsêÔ) Ø´iL™2…ÌÌLÖ¯_OII >ø o½õëÖ­#==””þþûo\]]yúé§ILLdÓ¦MTVV2fÌ^zé%ÌÌÌLýÖ·™ÌÌLæÍ›ÇÖ­[±³³ãî»ïæ•W^aݺuìܹ“ÊÊJæÍ›Çøñãùá‡èÒ¥ ¿þú+ÎÎÎÌŸ?Ÿýû÷óå—_‹³³3Æ cÚ´iXZZ²hÑ",,,Ø·o‡ÆÏÏ©S§²wï^ã˜þ…^`̘1"hE]2)I’¨¬¬ÄÓÓ³Îå¡¡¡´nÝšÜÜÜ˵33äææ’˜˜ÈÇlüwìØ1Ú´iƒV«ÅÌÌì¦fÅÀFø7ìÞ½›W^y…°råJÚ¶mËÔ©SÉÌÌàìÙ³>|˜¯¾úН¿þšýû÷óóÏ?òÞ¼·Þz‹|õë×À‹/¾ÈñãÇÑjµüõ×_|õÕWŒ?ž… ’™™ÉóÏ?OÇŽYºt)þþþ|úé§ddd°iÓ&-ZÄ“O>É—_~Ibb"Ó§O§W¯^,]ºGGGæÏŸOYY™©ß2á6°iÓ&Þzë-~øa~þùg\]]yæ™g()) 66–3gΰhÑ">ùä¶nÝÊÚµky‚çÝwßå‰'žà?þÀÍÍ^xS§NQYYÉÆùàƒhÙ²%ãÆ3>guu5_|ñË–-£oß¾XYY™úmnCß~û-Ÿ}ö¯¿þ:Ë—/'++‹3fÄðáÃqttdâĉøøø°wï^fÍšEuu5/¿ü2 ÷ý?üV®\IHHÏ=÷999|þùçLž<™åË—Ett4ï¿ÿ>AAA¬Zµ ¦NJee%_}õcÆŒá‡~0Nä ­RRRÂ+¯¼B||<ß|ó 3gÎdÆ |ýõ×ôë×®]»ÒºukÆÁ``Æ |øá‡2vìXªªªxñÅqssãçŸfâĉüðÃûì3’’’LýV4 b…Õ„ 666œ:uªÎå?ÿü3¶¶¶xzzR^^^çºÚÿ¶±±Á××___,X`¼þìÙ³”””››kê—'h4~üñG Àþ󬬬xá…8þ|8÷Ýw;w&%%…‰'bmmÍ£>ʻヒF£`äÈ‘ÆøöíÛ£Óé=z4VVV<ôÐC,\¸Ngê·MhæjjjX¶lÇçñÇÇ‚—_~™ììlŠ‹‹ððð`Ú´itêÔ‰   ºwïnì÷_ý5#GŽdܸq(•JæÎ˃>ÈÆj=˜5k*•Š-[¶ ×ëY²d ß}÷_|ñ½zõ2õÛ Ü†*++ùùçŸyúé§6l*•Š7ÞxƒÏ>û I’ðòòÂÌÌ ãö%'''>þøc,--Ó¾}{&Nœˆ››<ò .䥗^ÂÇÇggg~ýõWãäNhh(ãÆÃÞÞž‡~˜ß~û—_~lmmùý÷ß)”‚p«$%%±cÇÖ¯_O—.]((( 11;;;)++£E‹¤§§ЧOÞzë-T*¥¥¥;vŒW^y…Ž;D«V­ðññ1>Gß¾}9r$ƒ "==©S§boo^¯góæÍTUU™ú­hDÀjB*•вaÃ6mÚD—.]ÈÊÊâý÷ßçÕW_¥gÏžüïÿcÅŠ 8””¶lÙ‚ŸŸ Ô_xá6mÚD÷îÝÉÌÌdúôéÜsÏ=tìØÑÔ/O(++#%%…1cÆW{\\\X¼x1æææ¤¤¤àáá¿¿? O☙™a0¨ªª"99™²²2ž}öYãc¦§§ãíímLg¨óœÖÖÖÆÒ¥+L—ÞÖÆÆÆx±%Ü*EEEäääððë_ûúú²dÉ,,,ˆŠŠÂÏÏÏXhL¡P+MVTTššÊÁƒ™2eŠñ1srrÈÍÍ5nËèÕ«W4±¿þú‹„„ÊÊÊDuVá_“V«%<<ÜØÿÂÃÃY´hQ€ôb=zô¸,ÛËÛÛû²ïÜÚ­Kfffu*¯úùù]v@®½!Ò%…CRRÞÞÞ´hÑÂxÙ˜1cÐétWís/[ZZòä“O2{öl–,YB¯^½èÛ·oÇ ¬sÿÚ=Ú@Z‚XMJ¡PЫW/î¹çž}öYÈÌ̤sçÎ <GGGžxâ þïÿþϸ‡Ô××T*ýû÷'22’矞ÀÀ@rrrpwwgôèÑÄÅÅ™úå ‚±°ÆÅƒ…Ba (”Jå¿”u: …‚öíÛÓ­[7ãå}úô!((¨Îýo”Ø›*4†Ú òâAR©¬Óï Åû½^¯G­VÓ©S§:}úô!$$Äøß—náðóócÁ‚|üñÇ|òÉ'DDDˆmÂ-'I …¢Îw©J¥ªÓ·/u¥÷Í ÄÅ ]0ƒÁpY`jff†™™Ù‹ÝAÝïesss>üðCŽ?ÎÞ½{Ùµkß|ó ü1£FDß¾bôfb666|ôÑGlÚ´‰gžy†%K–°téRÜÝÝ©ªª¢gÏžlÚ´‰©S§²xñb‚ƒƒiÙ²¥qráÂ…¬[·Ž &ðÅ_ð×_áççÇ!Cعs§1õÀÜÜFCÿþýÏ»lÙ2ãž’¥K—òöÛoÛ5mÚ´:Aopp0GŽ!,,ÌÔo™ÐŒØÙÙáïïÏ®]»¨©©0NÊlÙ²åº÷ ÆÉɉqãÆ1iÒ$zè!Ο?OEE…>…&ËÑÑwwwöïßoLG?sæ íÛ·'**êš÷µ··' www&L˜À¤I“1b TUU]u€Ó©S'ºuëÆìÙ³ÉÌÌdñâÅ"½]¸å<<}úðûï¿£T*i׮ǿæýÇÇ /¼€——;wfÍš5¬ZµŠÑ£G›ú¥ ÂUYYY1vìX^~ùeüüüèÒ¥ Ë–-ÃÞÞžÀÀÀëÑ?~¦OŸŽ……lݺ•'NЧOôz}~hmmMÇŽÙ¹s'Ë—/'66–#FðòË/£V«)..¦mÛ¶´nÝ?ŽŽŽÆ£,u:555ôìÙó²³ëïD I¬Ù¤ ÒÓÓ)//ÇÆÆOOOãGš ƒÁ@QQååå899Ýô—onn.¸¸¸ˆ/n¡Ù0 PYY‰³³3vvv7uÿììlª««qqq¹éû ¿I¯×“““ƒN§ÃÝÝÝXp©¶ÏWWWãáá!&ÿ„f¯ººš¼¼<ÌÌÌpqq1f+êt:rrrP«Õ¸¹¹]u›RII ………X[[ãââ"²ëI¬‚ ‚ ‚ B“$ª–‚ ‚ ‚ M’XAAA„&©Ñ©%I¢´´”‚‚”J%žžžu›®ÝëVTT„­­-îîî×<¾Â`0OFFF³:<º²²ssóf•Ë^UU…Z­®Sm¸©S(„……áììܨϫÕjëì?srr2œ0 dggSUU…““ŽŽŽ×ìãZ­–¨¨(ªªªLú^Þ ƒÁ@UUU³:øZ’$*++±²²j6GæH’„¥¥%]ºtÁÊʪQŸ»²²’ÜÜ\ôz=îîîØÚÚÿÖZ­–ÌÌL$IÂÅÅ¥ÎuWR]]Íž={šÍûò¾êêêfuÖisl³Á`ÀÑѱÎYÌ¡v¬’ŸŸJ¥ÂËË«Nýˆ›«ÔÔÔ°sçÎfõ›¯ÕjÑétþÝÒ:FsÍsa›NG@@€±øNc©íÃ………XZZâíí]gm0ÈÊÊ¢ººggg®ÙÇsrrˆ‰‰iVcq­V‹^¯¯‡4uµG6§z6ƒN:‹^ÖG£s&&&2þ|Î;‡J¥"22’'žxoooŽ9¢E‹HNNÆÕÕ•I“&1pàÀ«~É Ž;†··w³ª·{÷n‚‚‚šUÙ÷ƒâééiü[5'NœÀÞÞ¾QÖÒÒR~þùgþüóOÊÊÊhÕª£GfРAhµZ6oÞÌÒ¥KUj§L™Bçίúxååå=zÔX9®9¨¬¬äرc 0 Ùݨ©©!&&†ÈÈHlmmMÝœ¢×ë9xð :¨ÌÊÊbáÂ…DEE¡ÓéhÓ¦ ÿùÏhÛ¶-¬X±‚µk×b0èС3f̸æ÷Fnn.gΜ¡OŸ>¦~KoX~~>gÏžeРA¦nÊ +**"&&†!C†˜º)7¬´´”4zÀšÀ‚ 8wîjµÚ8Vñòò **ŠE‹‘’’‚››“&MbÀ€W«ÔÔÔpòäIî¾ûnS¿¥7,%%…ŒŒ zöìiê¦Ü°ŒŒ RSS›ÕwIvv6QQQ°nݺ•_~ù…””ììì6l>ú(öööhµZþúë/–.]JII AAAL™2…ððð«>^zz:………„„„˜ú-½aiiiäææÒ¥KS7å†)HË–-“î¾ûnéðáÃRjjªôôÓOK/¼ð‚TUUuÕÇLII‘V­Zeê·ó¦TTTHQED€IDATÉÉɦnÆM©ªª’Ο?oêfÜ”‚‚iÉ’%úœùùùÒøñã¥7ß|SÊÎΖNž<)9Rz÷Ýw¥šš©°°P8p ôá‡J………ÒªU«¤~ýúI111W}Ì’’é§Ÿ~2õÛySJJJ¤ôôtS7㦔––Jiii¦nÆMINN–~ÿý÷FÎJ_~ù¥TVV&íÙ³GêÝ»·ôÛo¿I’$I‡–zõê%­Y³F*,,”æÎ+ :ôšc•cÇŽI4é{y³Š‹‹›]ü››+åå噺7%::ZÚ±cGƒ£Qó¯ÒÓÓIKKcäÈ‘xxxBŸ>}HLL¤¦¦†¨¨(¬¬¬5jNNN 2„-Z°gÏžÆlf£ðõõm6«8µ¼½½qpp0u3š¼ýû÷Ó£GBCCqppà¾ûîÃÜÜœäädvïÞMpp0ƒ ÂÉɉG}…BÁÑ£GMÝì[ÊÌÌŒV­Z5«Ô µZMË–-›Íа©TUUqìØ1î¹çhÑ¢Æ #++‹ÜÜ\vîÜÉ€èÖ­~~~Œ;–³gÏ’””dê¦ßRÖÖÖøûû›º7ÅÒÒ’V­Z™ºM^ZZ<üðÃxxxо}{z÷îÍ™3g¨©©áðáÃØÚÚòè£Ç*¾¾¾ìÝ»×ÔM¿¥ìííg\7vvvøúúšºMÞñãDZ··gذaØÚÚÒ½{wÚµkG||< g†„„Ç*£F2f4ÞNšUÖ €››[³Ê(½U5`uuuÅÝÝPYYI^^çÎÃËË 333âââpuu5~AZXXJtt´©ß'A¸aµ_úÙÙÙhµZâããÑétxzzCHHˆq——>>>?~ÜÔÍ„baaA`` G¥¸¸˜ÒÒRâââpttÄÖÖ–ØØXºvíj¼}ûöí©®®&99ÙÔM„R; nee%gΜÁÅÅ¥YmBþ=ƒ´´4RRR}?ň#8qâÓ§OÇÁÁ¤¤${ì1)**ÂÊÊʸòhccƒ­­íuûxII ñññ´jÕªYþ=Z­–3gΛ›‹ÔˆÇi[ZZ2yòdæÌ™Ã³Ï>‹R©$-->úWWWŠ‹‹ëõqqqA§ÓQRRrÍÇÍÌÌäìÙ³4«âK¿ëÔ©S7êszzzòôÓOóî»ïràÀ***0 |ôÑGXXXP\\Œ™™™1C­VßÐX%##ƒÌÌÌf·¢#ü{ªªª8uêÕÕÕú¼mÛ¶eøðá|ùå—¬_¿žÜÜ\üüü:t(€q¬Rû]lkk‹ 999W}L½^ϹsçÆÑÑÑdï©Ð´pöìÙ×’iÔQAQQëׯ§]»v<øàƒ :þúë/4ÍUïg0®ù¸z½žŠŠŠF´ M›$ITUUQUUÕèýâàÁƒdff2|øpxàºtéž={HOO¿ê}®×Çu:qÐ$ ÷ñŠŠ jjjµk46oÞŒ••>ø ǧmÛ¶¬_¿þª…$I×í»555&ù¼ M[yy9:®QŸ³¨¨ˆ7b«XZZ²yóf´ZíUïw­>.I555˜M›Á` ¼¼½^ߨϛ––ÆÞ½{éÑ£>ø ƒ&33“ƒ^·½W#ýSi¿±?¯BÓ¦ÑhnIŒÖ¨+¬‡âðáÃüþû︹¹a0hÛ¶-/¾ø"?ü0jµÚ8°Q*•H’„V«ÅÅÅåškggGxx¸XyŒT*mÛ¶%''§Q÷QVTT°dÉxà&L˜€B¡ _¿~L›6 6 V«1 H’„B¡@¯×£×ë¯;óäââR'ÍRÌÍÍ '55µQW$322øý÷ßùôÓO‰ŒŒD’$ ÀÃ?Lß¾}Q«Õu_ssóëîÙoÕª;v4Ùû)4M×\Õù7ìß¿Ÿ£GòÛo¿Ç*mÚ´á•W^aäÈ‘õ«( 0õ[*4!666DDD4j NǪU«°±±áÕW_ÅÎÎN‡™™?üð÷ÝwfffuÆ*:½^““ÓUW­VÓ±cÇ;r¥pu^^^„††^7Ëêzu…5//ãQ.J¥oooôz=UUUSVVFAA tNŸ>-ŠDÍFyy9555´lÙ¥R‰B¡ÀÁÁwwwòóói×®éééÆs´rssÉÎÎ}\h6 1333îßS(¸»»ceeEYYíÚµãܹsÆÛŸ={•JÕ¬Žðîlyyy8::^u¬Ò¶m[JJJ(,,ä쀄„ñ=.4 Z­–¼¼<|||°³³ä`³E‹”••¡Õj !--͘ý˜››K^^-[¶4uó…;T£¬!!!”––²sçN ÉÏÏgåÊ•xxxàììLDD………ÆBçÏŸçèÑ£ÍêÌ8áÎæææ†ÿý7™™™”””°{÷nNžË»ï¾ËŒ3prr"))‰ÐÐPú÷ïB¡ ,,Œ7ß|“-ZpúôiF%VŸ„fÃÉɉ©S§ò¿ÿýíÛ·cffFrr2=öíÚµÃÍÍèèh^xálmm9þ<¯¿þ:ööö¦nº ÜÐÐPFŽɬY³@«Õ’ŸŸÏ´iÓ°³³ÃÑÑ‘áÇóÅ_°uëVΟ?OŸ>} 5uÓẠC‡åðáüöÚkPTT„^¯ç¹çž 22’mÛ¶ñÆoàççG||<£F龂É4jÀjmmÍSO=Å=÷ÜCll,ææætïÞGGGã¬)S¦Ð¯_?Nž<Éøñã騱#ju£6S¤k×®,_¾œ£G’ŸŸOÇŽ ÄÌÌ I’˜;w.‡&##ƒéÓ§ËÈ Bs V«¹ÿþû‰ŒŒäرch4:w·7*• ¾üòKöíÛGuu5=zô2B³bmmÍ3Ï<ý÷ÞËÉ“'¯8Vyæ™gèß¿?qqqL˜0:ˆ±ŠÐl899ññÇsîÜ9N:…««+‘‘‘Æ“6lmmyçw8|ø0™™™Ì˜1Cœo+˜T£»ªÕêkP«Õ„„„4úQ$‚p«(•Jìíí¯˜:£P(033£W¯^¦n¦ Ô›J¥ÂÓÓ“{ï½÷²ë ¶¶¶b+‡Ð¬©Õj ¼êõíÛ·©îB³eiiyÕ>¬P(077§wïÞ¦n¦ ¼‡UAAAn”XAAA„&I¬‚ ‚ ‚ B“$VAAA¡I« ‚ ‚ ‚Ð$‰€UAAAh’DÀ*‚ ‚ ‚ 4I >‡577—¤¤$Μ9ƒ]ºt¡¨¨???T*•©_Ÿ ‚ ‚ ‚ÐL5(`MIIaΜ9;vŒªª*î½÷^ÌÍÍùâ‹/xøá‡yðÁ1333õkAAAš¡z§———3oÞ<”J%?ÿü3ÿùÏèÚµ+=ô_~ù%qqq¦~}‚ ‚ ‚ B3U¨¨ˆ„„ž{î9Úµk‡B¡ÀÒÒ’¡C‡Ä¡C‡LýúAAA„fªÞ«Á`@«Õâèèxùƒ*•ØÚÚRSScê×'‚ ‚ ‚ 4SõXmllðóóã·ß~£¸¸ƒÁ€F£!11‘èèhÚ¶mkê×'‚ ‚ ‚ 4Sõ.ºäììÌäÉ“y÷Ýw9qâ:ŽòòrÞ{ï=vîÜIdd$Ý»w7õëAAAš©z¯°êõzZ¶lÉÇL§NÐétXXX——Ç”)Sxë­·°··7õëAAAš©z¯°æææòÚk¯1cÆ ^}õUS¿AAAá6SïVkkk<<<رc¦~‚ ‚ ‚ Âm¦Þ+¬ÖÖÖôë×~øììl:vìh<Ú¦ÖC=„³³³©_£ ‚ ‚ ‚Ð Õ;`­¬¬$66'''ŠŠŠØ½{÷e·2dˆXAAA„z©wÀêààÀ‹/¾ˆN§@’$ *•Êx›«]2 èt: fffuî#Iz½N‡J¥B­V_¶r+—2 ÔÔÔ IJ¥…B™™™IÛ¤Ó鮨%IB«Õ"I*• •J%ú¸pM’$QRRBbb":…BA‹-°··G’$“µI§Ó¡×ëQ«Õuú±$Ih4Ôjµñ3)ÍÉÅcsss”Ê »¨ÄXE¸ ´Z-æææuú°«MI½V¥R‰½½=¹¹¹œ8q‚äädŠ‹‹  M›6tèÐáŠ÷Óh4¬[·ŽmÛ¶‘——Ç Aƒ5jNNNœ={–+VpòäIüüü7n¡¡¡u‚ZA¸Xnn.+W®äÀH’„³³3z½,,,¸ë®»µ=ƒ³gϲlÙ2âââ bÔ¨QtéÒ½^Ott4K—.%''‡ÐÐPFM`` ©ßFá:ŽÂÂB\]]Q*•TWWSXXˆÁ`ÀÉÉ ›õù%I"'' œœœÐjµìÙ³‡åË—c0°´´ÄÎÎŽôôtlmm177§gÏžúéõzöïßÏüArr2aaaLž<___jjjضm+W®D¯×Ác=&²m„f¥¦¦Æ8V)((`РA<úè£Æ±Jbb"?ýô§N¢E‹Œ7ŽN:‰±ŠÐläçç³víZ¶oߎR©ä‘Gáî»ïÆÊÊ Ng«äååÇ*¦n¶p‡ªwÀ*I±±±|òÉ'¤¥¥Õ¹ÜÚÚšI“&ñÐCÕYå2 lݺ•eË–1fÌX´h:ާŸ~ƒÁÀܹs±±±aÚ´iìÝ»—wß}—ÿþ÷¿´jÕÊÔïÕK«Õ’ŸŸOrr2ååå$%%‘‘‘AVVeee´iÓoooÂÂÂð÷÷ÇÚÚÚ8ó¬Ó錳ÒÕÕÕ$&&ræÌ´Z-¾¾¾XYY‘——ÇùóçÑëõ888`ee…B¡ ¨¨ˆššT*~~~(•JòòòˆÇÜÜœððp\]]Y·nÌ;×ø\µíÜ»wo£¯@effòþûïÄK/½Ä† xï½÷X´h¥¥¥Ìž=›>}úðè£òÓO?ñþûïóÍ7ߘ|EøN%I¥¥¥¤§§sôèQŽ9BRRvvv( t:ÕÕÕøûûSPP@÷îÝéÙ³'ÄÆÆ`kk‹‡‡z½žŒŒ ŠŠŠ°±±ÁÆÆ??¿Ë±:ޤ¤$ª««ÉÌÌÄÝÝKKKª««9qâUUU( œ±±±!''‡éÓ§Š™™™qÅ555•?ÿü³Qg½%Iâøñã,X°€0|øpV¬XÁçŸÎìÙ³9tè ,`Ô¨Qxzzòý÷ߣÕj™>}ºÌ Í‚Á`àï¿ÿæ§Ÿ~b̘1ØÙÙ±hÑ" S¦LA¯×3gΙ6m»wïæÝwßåÓO?ÅßßßÔÍ„ë2 ,^¼˜'N0yòdòòòøì³Ï°¶¶fРA¤¤¤0gÎúõëǨQ£X¶l~ø!_}õ•«&Q¬¬ŒE‹¡R©øðɈˆ@¡P››ËÚµkùâ‹/hÛ¶-¡¡¡Æûäåå±lÙ2ÆŽ˨Q£°±±aýúõTUUMAA3gΤ]»v„‡‡3a¶mÛÆ“O>iê÷êŽc08wî¿üò qqqøûûãíí‹‹ =zô 00KKKÒÓÓ9uê¿ýöåååXYYQUU…J¥ÂÂÂÊËË©¨¨ÀÛÛ›N:!IyyyäääH¯^½pss#''‡ÂÂBÔj5øùù‘““Cnn.ÕÕÕtîÜ™áÇSUUEbb"qqq<÷ÜsDDD\ÖþŽ;âàà€Z]ïn^/›7o¦¢¢‚W_}sssÚ´iÃüùó9uê'OžÄÑÑ‘©S§âàà€³³3Ó¦MãØ±cW| ¿G’$ÒÓÓÙ²e {öìÁ‚ˆˆ&MšDHH–––—Ý'==íÛ·óã?âáá¿¿?nnn¤¥¥…¹¹9^^^„……¡ÕjÉÍÍ%55õŠÏoii‰¯¯/ÁÁÁTTT`aaÁ!CèС•••œ:uŠÂÂB"##±³³3ÞW¡Pàèèˆ gΜ©“ªøo«©©á—_~!$$„gŸ}€V­Zñé§Ÿ’‘‘Áï¿ÿN—.]xüñÇ÷ùæ›o¸ÿþû j´v B}åææ²|ùr{ì1yä@.4¹iÓ&ªªª8räÅÅÅÌž=›àà`BCC™8q"Û·o¯Óï¡©JLLdçμýöÛDDD ×ë“°ƒ âÏ?ÿÄÙÙ™©S§bgg‡££#3fÌàøñãtëÖÍÔÍî@õÉÏ'Ÿ|Bxx¸ñrFÍØ·o_€5--ôôtúöíK~~>555„††Ò¡ClmmIHHÀÃÃ-Z`aaAxx8Ç7õûtG‘$‰ÂÂBÖ®]˦M›¸÷Þ{yúé§qss»âJN‹-èÙ³':Ž’’***P(XZZbee`\iµµµ½éÁuûöí¯xyçÎMýV]ÑÞ½{¹ë®»¨¬¬$//+++^~ùe,--ùå—_èØ±£1­ÔÇÇ???bbbDÀÚˆ4 QQQüïÿ#,,Œ×^{-Z\7Ý×××— &0zôhÌÍÍÿÕ6Z[[ÓµkWS¿U—©¬¬äرc¼õÖ[QYY‰““sæÌÁÒÒ’øøx^|ñEãí;vìHMM ©©©"`š…ÔÔT²²²èÝ»7ùùùh4ÂÃÃéÔ©666ÄÇÇãåå…¯¯/VVV„……‰±ŠÐl=zÈÎÎ`äÈ‘ÆëOž|8tèÐÁ¸êëè舓“ÉÉÉ×|ÌÌÌLþüóOzõêuÕbf©¨¨`áÂ…DEEñúë¯Ó¡C‡›NUý·ƒÕQUUÅ®]»8}ú4‘‘‘ö¼†´´4bbbX²d YYY´jÕŠgžy†víÚ‘™™‰«««ñö¾¾¾hµZòòò®ù¸±±±¸¸¸Ð»wïFÏŠš®M›6ÕÙvÔ ),,dãÆlÛ¶’’ºtéRg¬biiYg¬âëëËÑ£G¯ú˜’$cÌ€’’6mÚtÅŒžSZZ%%%,Y²„={ö P(4hãÆ ##ƒÎ;¿‹œœptt$%%媩ÕjÙ½{7^^^Æ…'áΓ‘‘Aee%vvvTVV²sçΫ.>ݨz lmmñóóãûï¿ç©§žÂÛÛS…;ƱcÇxøá‡/»ŸN§ãèÑ£¼úꫨÕj>ÿüs>øà>ùä“«>Wm%⫱··'44Ô8$Ü­VKyy9ÕÕÕ”––rîÜ96mÚDyy9Ó§O§S§NXXX˜º™õ¢R©èر#………&Ù7·uëV^yåºuëÆš5kX°`îîîW½ýõú¸››½zõú× þÜn$I¢¼¼œÜÜ\ÒÓÓÙ³g'Ož¤k׮̛7ï†'c…Fz=Üà÷Xm sAAA£¦×Ú¹s'3fÌÀÇLJ¥K—òÎ;ïðÞ{ï]ñ¶ƒ½^ÍÇ ¢k×®bŸ«PGïÞ½/›ün Z­–cÇŽñú믣R©øì³ÏøðÃë=VQ(´iÓÆ¸@¸³èõzÎ;ÇÑ£GÑëõTVVbiiIëÖ­ñ÷÷§¨¨¨ÑÛ”ššJii)_|ñéééÌ;—êêj^~ùå«ÞçZ}\­VÓ¹sg<==ýµ¯¸¸˜‚‚@þ‹‹cãÆTWWÈ©S§0 ( T*­[·nÐóÕ;`uttä‰'žàÍ7ß$66–¶mÛ¢P(ÈÏÏçÔ©SôîÝûгˆjµš—_~ÙXilêÔ©<ùä“”——_õ¹®·jªR©°³³¤Õj9xð «W¯&77[[[***hÙ²%£F¢sçÎÍ>0R(Æ¢7¦(Ã~ÿý÷3|øpT*“'O&**ŠC‡]õö×{¿k³„S\\̾}û8rägΜÁÜÜGGGzõêÅ„ ðóókzåùw쀘˜>n`¢H©Tbgg‡………I^Ë“O>Iß¾}x饗2dIIIW¼­Z­¾î ‚•••È.cooo’"/fff¼üòËÆ‚Ï>û,O?ý4W½Ïõú¯••ÖÖÖþZÓŠgÕªUÄÆÆÒµkW:vìˆJ¥"??ŸßÿóçÏ›dûG@@Ï?ÿ¨³š^;ƺ˜™™­[·¦¼¼œ’’’µ«Á…ZµjŨQ£pvvF«ÕRZZj<–äÒ¡‡‡îîîìÚµ‹ò~I+++œ cùòåœ;wŽððp***ˆŽŽæ™gži´?ÔíB’$ |÷ÝwìÝ»—Ž;Æ<@@@À¿? &IPY ÇËÁf‹r0©TÞ\0™› sçÂ;ïÀž=pÏ=àæ))°x±´Î™ööPQ_~ ÷ßíÚ™ä½ eß¾}Œ9sssÒÓÓ9sæ #GŽÄ‚Ÿ~ú‰’’\\\HMM%--­Q÷ 6wµ}»öÿgff²hÑ"èܹ3=öÁÁÁ7vî§Á ÷ÓúNÔètpâ„Ü'M‚nÝä@³¶_KddÈÏçåuá2€~ý MÈÊ’ÿûÇå€õå—å`U’ä>¿t)¼òŠ|ÙŠҨ¥¥%ÁÁÁlß¾víÚ¡P(ˆ‹‹£¢¢ºtébìÿ …‚èèhlllœ$4_µŸÙêêjt:öööM/Ãá"žžž¸ºº²k×. ÀáDZ±±ÁÉɉððpV¬XARR¡¡¡”——sìØ1ž{î9S7]øÔni$ ­VKjj*Ç'##ƒªª*”J%111˜™™„­­-6661xð`‚‚‚®˜a¢P(P«Õ˜™™5ú¶Žàà`V¯^Í©S§hß¾=:Žýû÷ãííµµ5ݺuã×_¥¬¬ '''RRRÈÌ̤G¦þs T;Q¢Óé$ÉØ÷222رc[¶l¡¼¼???ÌḬ̀°°@­VÌ„ hÙ²%...þÞ €5>>ž9sæ ÕjY¹r%–––|÷Ýw¬X±‚I“&1iÒ¤:ûJ[µjÅäÉ“ùðÃÙ¹s'ƒèèhž{î9œœœpss£gÏž¼óÎ; <˜#GŽ@Ÿ>}õMi® IIIÄÆÆ’••Ebb"ÉÉÉôêÕ‹… 6þ G\¼ñÓOÊÁêòåò ÑèÑàèxù}t:ˆ339à,/—ƒÑ ä 77>ýT¾,8V¯–ö™™PUo¿ rpl"ãÆãÕW_å?ÿù­[·æðáÃøúú2lØ0 [¶laæÌ™„††ò÷ß3pà@Q=õåææ²mÛ6RSSQ«Õ“’’BÿþýyóÍ7o~ÏõÁƒ°u+ÜwtìxC©¸u¬] 6Èý»v ÄwßA~>̘EÈÁêsÏÉýù¡‡äÉœÜ\¹o‡„ÈAlm Ûµ«|»Ú‰¥#G`Ö,xõU9Óà‰'P¼ý6ÿTxl,¶¶¶<óÌ3Ì™3‡óçÏãèèÈ5jaaa899ñæ›o2sæLœœœØ±cO>ù¤Ø×t›ª¬¬¤¤¤¯Ú~ûãÇWgJKKY·n‰‰‰ØÛÛóÆoжmÛk>n^^&yMLœ8‘>ø€;v ×ë9vìÏ?ÿ<ŽŽŽ¸¸¸Ð½{wæÎËÝwßMTT­[·¦W¯^&i¯pëét:8þ<111äååQ]]Maa!^^^ЪU+,--ñóócâĉƪÑÍAdd$¼úê«ôíÛ—¬¬,’’’˜3gƒ bëÖ­Ìœ9“Ž;²eË D`` ©›.ܤêêj¢¢¢Œ[/ 9xð 999TUUáîîNEEjµš>}úðÅ_\³æŠ©($©vzÿæ”––òæ›o¢Õjyê©§  ;;›­[·òí·ßòé§Ÿ^VþZ§ÓqðàAöïß@ÿþý 5®ö³mÛ6bbbhݺ5ƒ ÂÓÓ󪑼N§cíÚµDFF ?ÝIjg­SRRøý÷ß9}ú4áááøùùáåå…··7­ZµªßìÝêÕàî={ÊÁ`q1=*¯^J’€‚¼Šjk+Ñéäÿpì””È÷77—ï“•%§2Þw rù Ôñãòõöö0q¢”þý7<ú¨¼*UZ ï¾ Ã‡Ã¥çÎɃú#äU.KKvíß]£¦ÜÖžï¹uëV’’’§OŸ>¸ºº"IÙÙÙ¬_¿žôôt"##éÑ£‡1-çJŠŠŠX»v-“&Mj´×Ðèt: ENŸ>Í÷ß§§'cÆŒA¥R¡T*ñññ©eêÂBؽ[^ɼë.5J6¿ý|| W/ ’ûî™3š ®®òevvògB¥ª˜ffÊ)¼³fÁÅ?îÕÕðÞ{r`úÐCrpøàÎ;Ço¼A»ví¨¬¬déÒ¥DGGãââBii)DDDйsg¢¢¢øý÷ß™1cöööìÙ³‡3gÎ`mm³³3EEE¤§§“ŸŸOË–-0`¹¹¹<ýôÓúÚ´Z-‡bß¾}(•J @ÇŽc•ÚÓ Nœ8A›6m4hW«”––²aÃÆŽkê?ÛM’$t:1KçÒË´Z-ûöícË–-èõz ÃÃÃGGGììì®ù{])))=z”‡z¨Qß‹ÒÒR:ÄÞ½{quueèСøûû£R©$‰¬¬,Ö¯_OFF={ö¤G8^i¡áǧ¦¦F¤ 7NgÜÎWK’$4 555h4<ÈÚµkQ(8;;cii‰§§';wÆÛÛ[[[ª««©¨¨ÀÃÃã_«#qìØ1JJJtjG½Ö””&MšÄW_}EÈ%)i•••¼òÊ+´mÛ–çŸþ_yñµîä€5;;›¿þú‹ƒR]]ÍàÁƒyà.u0äõÙWWQÏ<³gËûC¿ýV.Ó©¼ôÔÔ\XIR(äËNž„ᅦ^Í«¥ 9eer€pémòóå ·eK9H¸RÛKKåÚÃãêíÿà8]UU°ÞjwbÀªÑhX¾|9ëׯÇ××—¼¼<œ™9HýôS¹/?[¶È}´yÒåJôzøãy¢æÒï¤ÔÔº«ÿ••pö¬œMPÂ2Z­–µk×Ò»wïf½‚)ÖæG§ÓñÉ'ŸPZZJ¿~ýX²d ÷ÜsÇG©TòÞ{ï]µrÿîÝ»Y¸p!vvvDDDн{wrss©ªªÂÜÜœ¶mÛâææFtt4Ë—/G£Ñ°hÑ"S¿ä«é”––’@ZZçÏŸ'33[[[cFNmpfaaAee%nnnŒ1‚ðððF©ëaª€õVkãÐëõÄÇdzråJ aaa8;;“——GZZ©©©TTT ×ëqsscìØ±tèÐÁ$§ Ôºk½S‚k£ú+½µ¹Ñ­USSCaa!±±±ìÚµ‹³gÏÒ§O¦L™BPPÐåû‚bbäÀ³w¸8hÝZN¯•$3ƇÚ}ffо½|»Gkk9%rÈ9x]¼¸n!¤‹uî,?æÅm­]©ru•ÿ]‹½½üïZœœä Ãß¿ÑÿNBýI’Dqq1K–,áÔ©SÌ›7ã@ö†ö]—•Éý³vEÏ`€%KÀÏOþL¼ü²|Ý‚ò*¾››|ûÚ€ÑÌLNîØQž˜¹¯†‡_Hû½Ö-*<ðÀåû´ †ËSÕ­­åI Ah¢ôz=ÕÕÕH’DUUz½½^ÏæÍ›ÉÈÈà7ÞÀÃÖ-[2oÞ<ºvíÊøñã¯yÌ\¯^½ ÁÖÖÖ¸ò~¥3ú"##iÕªëÖ­3õÛ 4ƒ²²2Ο?Ïž={HNN&;;N‡§§'AAA3hÐ ¬­­/ F-,,033ÃÙÙÙ$•©ájjûvJJ üñgΜaذa¸»»“˜˜HLL ÎÎÎøûûs÷Ýw«îßN}¹AÇÚ´k׎/¾ø‚gŸ}–öíÛ£P((++cÍš5ÄÅÅÝQ+Bÿ¦òòrvïÞÍæÍ›Ñh4ØÚÚ2xð`^yå•k¦gðå—rú`}ÁSO]t_²? ¥R^!½x¶ÄÜ\NÇ »öêç•fy¾ùFÞ³7hЭyÓºv•WÄ„fA£ÑpàÀŽ=Jtt4þþþ|úé§Øý“jkwé^Ы?¼º>fŒp‚œ¢{ø0Œ'g¬]+_wô¨¼^ËÕö´^oÖýJ™K–È“;âè¡™(..æÇ$::wwwŠ‹‹EËÊÊxÿý÷+ûmÛ¶å믿6V¿•J…ëõ&&ÿannÞlÏ×úõëÙ°a’$ѳgO&L˜€³³3-LXÓBªªªŠE‹qüøqlllˆŒŒdúôéÆñmÛÛ]½V;;;¦L™Â¼yóxî¹çpvvÆÙÙ™ÄÄDÌÍÍ=z´q_«P?µE”>úè#œ=z4mÚ´1žsuÍAÁ™3ò`ûÒŽ¬×ÃúõòÊéµVvn¤ÂꕨTòc_Ï?Êé™< 110uê­{óÂÃåàÇoÝc ·œ^¯'&&†ï¾û+++"""ŒUǯµBsEZ­œ¦ne%ïMM•'N’“å‰WWxøaøùgy?é­š¹šéÓåýÖvvòçqß>yEWn±Ú”Æ#GŽpÿý÷×ë1t:¹¹¹TVVRUUÅÑ£Gùûï¿éÕ«o¾ù&vvvƪ¦J¥33³Ëö;Ý.3ùBó¡ÓéˆgÉ’%hµZ¦NJëÖ­Mv» ÜJéééÌŸ?Þxã <==±¶¶¾#ûvƒR‚;uêļy󈎎æäÉ“ÔÔÔ +„……¡nÈ™„ýõ?üð#FŒà¡‡º¹Ç=<äÔÜKSg•J9åqÁùß•sûvypÿo¦*Áš5rÀš•%ï÷»^šïÍP©êžÙúÿìwxSe‡ï¦»¥ŒRÚ²÷eï½QÙ²D?œ8Td(Š ‘©²‡Ì²i™--ÐI÷ži’óýñ4]”Ò=àÜו z’œ¼INÎyæïQ)uÄÆÆòóÏ?sþüy† Æðáà 6j)1Qno¾)Áš•+áé§EœËØSÓ¸±dUãâŠ>Óib"ý©mÚH¶¿}ûüÏQQÉÄÄD>þøc.]ºD‹-9411ÿ4¡öîÝKHH5jÔ@«ÕR·n]>øà\\\Júí©¨dKHH?þø#ׯ_gøðá :´ÈDcTTŠ›ððpfÏžMÇŽyã7žø€`ž<Ê»wï²wï^jÖ¬I³fͨY³&ŽŽŽ <˜âÈ–dcïãÀ­[·Ø²e þþþ,X°€úõëçý3­PAŒöíÛEÕ×x ¯Y-ZHê±c Ç„…ÁO?If¨(éÜY²¬ááRB\Îñ¶mhäýª”<<<øë¯¿8wîíÛ·gùòåT¨P¡àC;;ÉjÂaäԼU«t±%sséo.d•ÇliÞ\Tˆ\\dnªŠJ!À¼yóèÖ­#FŒ`éÒ¥,Z´Û,Ç›N§ãòåË9rwww´ZmšEÆ yþùçiÑ¢EZ ¹$fCª¨äDrr2ÞÞÞøøøpüøqüýý2dS¦L¡R¥JOdÖIåñ"%%OOOŽ;Ʊcǘ0aÇ/ñ¯ÒNžVGGGÚ¶m˹sçØ·o_Z-u·nÝpppÀÄÄD=aNÇ‘#GX»v-ýû÷gÆŒ¹ïÝ3¢(°oŸd0kÔµÒÞ½¡råt¥ÓÎE8)éÁçnØ ½E=kËÔTÆ~”+'™¨¢ˆSîî]Õa-(ŠÂÕ«WùòË/éÝ»7K–,yd&(Wèõpó¦óG§tè‡ÃíÛ’Ý,nFNï×nܸø__å±D§ÓqáÂŽ;Fbb"—.]¢GLš4‰„„6nÜÈíÛ·ÓZrE!::šµk×âîîÎàÁƒ3f µjÕR« TJ=Æãwß¾}ìÛ·­VKÆ éÓ§mÚ´)þùò**…ˆ¢(¤¤¤àîîιsç8{ö,)))ôîÝ›?þ˜–-[ªÃTòtµ²µµ¥sçÎtîÜN‡··7Çç“O>¡J•*Ô­[—:P¯^=µ,#„‡‡³jÕ*îxz²lÙ²†°ç ­VfJ®Y#åÖÖâ|º¹Aß¾¢žj0H¶$ë.· Äq|î¹âËÕ¨!cB¤4¸°iÑ›³g‰/žw£’z½žC‡ñÃ?ðÑGåMö>9‚ƒEa71Q*œå8ÖhàÆ Zúá‡Ì«¹9|òIɽicxLŒdZk×~ø¨'•G ( ¬^½šû÷ï3xð`êÖ­Ë‹/¾HÍš5133£|ùò¼ñƬ_¿ž%K–ÇÙ³gÙ°amÛ¶å·ß~+é·¡¢’'>̪U«èС3gΤY³fjbDå±!99™Ï?ÿœz÷îͧŸ~Z8üÇ|‡WÍÌÌhܸ15b̘1øùùáîîΦM›HHH uëÖôéÓ‡ºuë–ô{,µ(ŠBrr2üøãÔ¬Y“%Ï=Gåø,.–Á ÙPãLÕŒFyLŒˆ5i"ëÝ»’=5:¼#G¦÷êÙØÀ‡fÞ÷ýûbìO*Y¨œÔ} ›ˆؼ^y¥höß¼9ѽzåÿ W)Š¢ÃÍ›7Ù³gÞÞÞ,Z´ˆÆuêHÂÒ2sO§V ¡¡â”6h 9}vì!¯÷ß56VÊÖ_}–û‡-Üè ) \]E ê˜5KuXUò…Á`àâÅ‹,[¶Œ=zðî»ïbÿa¼Î;³yóffÍšE`` ŽŽŽL:•:Þ‚t:9ž +K«(òÛ65UËçU0 œ:uŠ]»v±hÑ"êÕ«§fšT+âããYµjZ­–… æZ9ýI¥ÀW*V¬HÅŠi™:FÂßßWWWîÝ»§:¬A¯×sáÂ~ÿýw¢¢¢˜4i½zõÂ|ýzQ7mÐ ýÁþþ°p¡ä..2²#) ÜÝaùrÙÖ¤‰8¦¯½–ù…ÚµKÿ¿™dý>Z´'vÑ"1¨£@Š­Vz »u+šý;8Ø y,ªV)ŒÆÆŠ+pttä©§žbæÌ™”/_æÏ??qB'N„êÕEEwÍÉö¿ô’ÿ¢òd•*0cFñ¾¦J‘c08~ü8+V¬`öìÙ´hÑ"óÅñãåøÕjÓg 4H¸Œv0gNö/R¯^úø¤Ò:ƒÌÊJœñ[· Q£’^JÄØ¯ºjÕ*Þ{ï½G:«F4h@ƒŒAÏü’’"¿SNœÒråD˜oÓ&ù»¸H–U«ÕykkòkÝZHÛ¶‰|Ë–<µ¶G÷§Ÿ$€úôÓ0nœTýý·TQ´i#¯úzººuI *é¯B¥IJJ"11‘¤¤$®]»ÆÆ©R¥ ³gϦzõê%½<•B!((ˆuëÖqõêUêÕ«GçÎéß¿¿ê¬æ’<;¬¾¾¾|öÙg\¿~Ï?ÿœÁƒãááÁ[o½…öööìÝ»—k×®ñÎ;ï< Tø¤cåqýúuæÍ›—9rh0H&)k–³reÉ"e¤BxýõܽèâÅR>ùË/½Î.ZY¦¦Ù¯E¥Ìb08yò$?üð~ø!mÛ¶}°ß(;A¯:uäö8ab"%˃¥á**¹$$$„7rêÔ©\eV Œ^/Á•À@èØQ®1gΈpY\œ¨mOœ(׊+2—íZXH¿øÞ½¢£P¿¾TU¨ Hÿ¶‘>}d_ÑÑéÛêÔeúŒU¶¶ðÌ3è""HÚµ«¤¿•" ""‚ýû÷súôi´Z-æææ(ŠÂÛo¿‹‹Ë?ÆCåñáÎ;|þùç4kÖŒŸ~ú)*ysX“““ùî»ïHHHàûï¿§U«V¤¤¤°uëVªT©Âüùó©Y³&Gå믿fذa4oÞ¼¤ßc©býúõ°dñbÊoÙ/¿œ~‘¶´„áÃ¥$X§“‹¾Á å“Õ«ç_I7%‚‚Ä€vt,é@å1&""‚uëÖ1kÖ,Úµk‡IX˜\4)÷=rD¶žC¤MµoU%OèõzþøãvîÜÉÀùöÛo©Y³fÑ¿ð–-°{7 (× ãט©µµM¿Veˆ¶±elNgb"ûÊŽÊ•åfDU+~¢¸ÿ>[·nÅÕÕ•V­ZñÚk¯Q¹re¬¬¬°±±Q«óTʾüòKš4iR|ЍuëJiƪ;;¹åÕùTyŠ¢pãÆ –.]JãÆùú믩V­ZI/KE¥ÐY³f §N¢M›6ÔªU‹>ø€fÍš=~óTãâ¤$2Rl=++øî;Ñ-HN†™3¡aC4))hôú½Tž®,QQQ4iÒ$m[@@÷îÝãƒ>HSpÓh4XXX¤=^Eؽ{7 4 N:’ijÖ,³²éš5P³¦l?tH²«çÎÉ Ç òÿ¯½&†³ñ¦¢R¤¤¤°{÷nFŽ)Ä;¤ÔÏÁA²«ʉM5hUT²åÒ¥K,_¾œÅ‹S·nÝ¢wVcc!$DªyRƒÐ**EAdd$ÿþû/;wîdòäÉôíÛ÷Éœ|ìté"u*±±±,_¾œèèh–-[†££ãã¥n}ô(üù§¾ššÂÆÒòÅéÇtß¾2¹¡rå4mÛ{÷P ø9äélajjЉ‰ ú ^²››ƒ¦M›–ôÇXªIHH`×®]¼ýöÛrðÖ®-BJ¿À{÷¤ËÙYD+LL$¥Þ¥KÁ²Rê‰Q¥ððð **ŠÎ;‹¡Ý¨tè Ê¡±±0mZæ2@•4¢¢¢øæ›o˜8q"uêÔ)zgÕ`2à˜=»¤ß¾ÊcŒ··7óæÍ£|ùòÌŸ?Ÿ† >^F|^¸xQªåZ·.镨2÷ïßgñâÅèt:æÏŸ/S'ö탵káÿgU£?ÆÜÚ¶#úI («9±±±lÛ¶ƒ2f̆úøôªFDˆ(fÓ¦éöšÁ 6ß­[bcuè ‰†÷ß±ÁŒÙä˜qÔü2¢(ܾ}›¥K—Ò½{wž{î¹²;†ÉÍM÷@J|‡ ƒ=äVŠÈóYÄÒÒ’aÆѹsgRRR¨\¹ršy=hÞ¼9UªTyrç¯:8ÀgŸ¡tîL¤ §OŸæŸßg’­-µöì'')™:Uß¶­¨28 ƒÕ3öø5kVx©öçŸ/éOFåqàìY‘0¿~”€n'&òõ×_Ó²vmžµ³C³i“_îßpž°ŠŠ ÁÁÁ,]º”ÈÈHzôèÁ„ Š&û¤ÕÊoµ|y¹® .í&%ý¨<† .\¸Àš5kpvvæ³Ï>£Aƒe«ü7%EZ¨*W–*9­öï—i /¼ • wîHY䫯B¿~pó&Ì›MšÈó;t$‹KzE’Ñ‘¹qNœåT•2‡Á` ** ???._¾ÌáÇ7n,;Îjh(\¸ ÇwË–¢1Ò (ûZYI@¥”’g‡5::š_ý•3gÎIÆ yþùç騱#åË—ÏSÝvpp0·oߦ{†,Œ^¯çîݻܽ{'''š5kVv¢s^^M›øÏ?ÌÕÓGØØ€½=lß.jÀÖ7ß”ƒ©0¨W¯¤?'ƒÁÀ©S§hÒ¤ UªT@§ÓáîîNdd$uëÖ¥víÚeCê<%E*Ƈ+W8¶`«#"xï•Wè4hš°0Q¿ gž)˜²µJ™!66–sçÎÑ«W¯´suBB—.]Â`0аaòY&U¤¤¤ðí·ßR¡B¾úê«‚ó"œ ýû‹@ŸNþþð×_⬾ü²”t©=äù&((//¯l•;wîpïÞ=œiÚ´iÙ±UŠ€“'Oòí·ßòÆo0hР’^NÞ‰ŽG4(HÊyíìdrÙ3ðõ×ò˜Ê•ÅQíÝ[bìÿòKöí/žžRÝðôÓò·——<îêUqf]\Jú]§áååE\\­3ˆAét:ÜÜÜˆŠŠ¢^½zÔªU«lØ*E„§§'óçÏÇÖÖ–Ö­[3kÖ,š5kVúƒ2aa¢Öke%½ÕÇKE¯£|ùÌKJ)y:» 6mÚĦM›èر#-Z´à¿ÿþã£>bÓ¦M8æaÆgBBË—/çæÍ›™.›6mbÇŽØÚÚ’@Ïž=yíµ×ÊFÆvï^|ÇãËùó3x0CBC±jØPz^{MW»væçÅʼn3õ=–¢“™JÞQ…sçÎñî»ï²bÅ ªT©B||<+V¬ÀÕÕ[[[3f ãÇ/éå>SSxóMRœœØëåŶ>}ýuZýû/të&Õ&ˆÁœaô•Êã‹Á``Ë–-¬\¹’“'ObffF`` K–,Á××KKKôz=ï¿ÿþ/ÂÎÚµk±²²bÆŒy7r.]‚Ó§eôYèôó“¾£Þ½%à â¼.[&ÿÿðÃ’~Ûežøøx¾ÿþûÖ 6ð÷ß§Ù*½{÷æÕW_Í$@ù$ ×ëÙ°a'Nœà‹/¾H–,íܼ »wK¶S§g5>^~3©£8°·‡Å‹erƒFÄ15’¿sšÂœ ÿþ+™X++¹†º¸H éܹRcãðÅ_P¿~ý4‡5..ŽåË—sîܹ4[eüøñŒ3¦¤—["DDDðùçŸ3räH† &z4¥¤$)[¯VM|Šÿ…={$«:¾Tm¶k'·ÒîdgCžÖ˜˜:ÄÈ‘#™>}:––– 8÷ߟ‹/2dÈ\ïëÈ‘#üóÏ?ÔÈ0¤ÜÏÏŸþ™^xçž{ŽË—/óÞ{ïÑ®];z”²Zêl¹s‡äV­ørÅ :ôëÇH++9PŒŽ¨12•5B¥ÑHipÖG< TÒ `Ù²eÄÄÄ`08wî{öìaáÂ…´k׎7²jÕ*úõë—–-µh4РÇdÝæÍ,ž?ŸÆü!ãŒÙT33uÖêÂÕ«Wùå—_ˆ‹‹Äݾ};wîÜáûï¿§bÅŠ,Y²„ü‘Æ—}åÄ}pxÂÚ "##™;w. `Ô¨Q¥#Ë-üäx÷ð ‹••8§ôZ7huë¦W”a¿"O+OJJÂÌÌŒÎ;§EêÕ«GíÚµ¹{÷n®ö¡( W®\áÏ?ÿ¤oß¾™î;þ<ŽŽŽ 2KKKZ·nMûöíùï¿ÿJúsÊ‘èèhŽ?ÎÆ  ælÚDË–-ùß³ÏÂÿÉIðQT®œ>ËHå± %%…•+W> ”}òäI:vìH›6m°´´dРAT©R…3gΔô’ŠQññàï¿óåk¯ñ矲páBYZBB‚ ˆVyâ¸ÿ>ßÿ}¦ó¸Á`àäÉ“<óÌ3Ô®]› *0vìX‚‚‚¸}ûvI/¹X‰ˆˆàÃ?$66–^x~øÏ?ÿœrÆìMF 1®u:ùûömIš>]Œ,êsÏÁÛo˼îœÐhTgµ€(ŠÂåË—Ù¶m}²Œ–;wîU«VeРAXZZÒ¦MÚ¶m[êm•Â"11‘;w2mÚ4Eaåʕԭ[·ä”0Kã»ïd¤ŒÁ ·ØXÉ8eÄ`Öµ{{ûŸY_¹²ô¾fͺׯ/¢„%Œ^¯gß¾}ܽ{—FÆŒq*'Ož¤sçθ¸¸`iiÉ!C¨\¹2®OÐxDEQð÷÷ç“O>¡~ýú<÷Üs¥ÃY½u Þ{O ‰±mÛD?Ä(èej*UÍ›?6Óòìj›˜˜d*e255ÅÜܽ^Ÿ«çëõzÖ¯_O÷îÝi™E”åöíÛ”/_>-zcaaAÆ ¹yófIN9²|ùr~ùåL†eÌ‹/2yòd¬Ê——FÆ9”9an.'KµÇë±áøñãò|±«›7oR«V­´€ƒƒŽŽŽÜºu«¤—üPöïßÏ;ï¼CØÚµ¼\¿>K—.¥iÓ¦˜T­ 3f¨†ñÊöíÛ©R¥ ýúõKÛf0ððð a†ó^½zõÐjµ–ô’‹¸¸8¾ûî;Z´hÁo¼AÛ¶mqrrÂÚÚ:û^Þ[·à‹/Dܤ”ëþ}xãtýãóLL¬ÒQ)tt:ëÖ­£W¯^´hÑ"Ó}žžžT¨PÊ©šeÅV),~þùgþùçfϞ͌3°µµ-Ùõ9s`Á)éhÕJTOŸ~Z~+ëÖI/iFŒJ¨E‰TÏ™›‹Ó¼zµl·´„§ž*¹Ï+•ÀÀ@~ùå^{íµ„ßnÞ¼IíÚµÓæªW©R‡Rm«6×®]cÊ”)´k׎ɓ'—\ðýû°|yzûàªUе«è‰€”¬Ï+ÇsvÑÇ„bÍ §¤¤°fÍÌÍÍ7nÜ÷'&&¢ÑhÒ„ 4 åÊ•#,,,ÇýFGGsòäIŠóí ÓéX³f ¡¡¡¬úðC&ŒG—.]°²²’Tóæ…±SÉz½žË—/sùòå\S wwwV¬XÁŒ3¨šE4+!!ssó´ ¥¥%–––„‡‡ç¸Ïàà`Ž;–VzY3eÊöìÙÃòåËß´)ÕúôI/ë,WNí[‚$''sêÔ)¼½½ÓJ΋ƒÁÀ®]»8þÁÇLJ¥K—Ò¼yó’Ï8…†ÊíƒÒ3I€QSÅÌLÔ}ýý3?ÏÆ¦xì³)=¾q#³Óœ’þþÄÆÄpäÈ‘Gž ›¤¤$/^L—.]è˜ [v¶Š……ÝgJJ gÏž-ößka£Ó騴iŸ~ú)Ÿþ9/¾øbñéè„…Iˇñ:¸{·è߸¸H¹¯™,] /½Tfü ___Μ9CJÖ*‡<’ç+¡N§ãôéÓidrr2aaaܸqƒ-[¶dzìÀ©hœË\ºt‰={ö°téRlllÐëõ(Š‚V«ÍQ]ïQ‘;+++êÔ©Sì²Òžžž:tˆ/gÏÆråJ™=ùG7Ê&&&T«VjÕª«‚[RRk×®¥k×®4jÔ(íªÓéÐËý²Þœ°³³£^½ziÑ΢&>>ž¥K—Ò°aC^zé%*T¨-Z¨£jJ¦¦¦Ô®]//¯bÍnñË/¿ðÒK/áè舯¯/Z­ö¡Ç§‰‰É#×èèèHÍš5ˬš°¢(x{{óå—_Ò¤IÞzë­œÏ=ƒ”îššŠðKÆ^Ô2ÜgTØÔ¯_Ÿb}Í .°oß>–.]еµu¡Ø*&&&899åIœ²4 ( ÉÉÉ\»v_ý;;;>úè£ÒÓnk ³f=<°cb" Yƒ ý%bE­áæ&êÀ•*e®¸‹Ž†å˱üðC4h@€±Ÿ¶ÐëõüóÏ?ÄÄÄðì³Ï¢Óé0 èõz´Zm޶tNǸF£¡V­Zا`”Aôz=[¶laß¾}|öÙg´jÕªx^XQ$ðòÉ'rl¬\)•—Z­lËx}(é Q©X±b¡LÃȓêÑh°µµeÏž=ÜÉõë×3mk×®]&‡uûöí$''³(u@m@@ÁÁÁ¼ñÆLŸ>=͉MIIÁÜ܃Á@llìYª¬XZZR£FbuXÃÃÃùúë¯yóÍ7idc#©ú2v=Îh4œœœprr*VøÒ¥K\¾|™ˆˆ¦L™‚¢(|÷Ýw\»v 333´Z-ƒFCRRIIIÔΪ›L‚EÍo¿ýF|TÓßz+]4lÊ”b{}•GcffF5¨X±b±ã‡æþýûlݺ•;vÀ´iÓxæ™g°±±!)))íñ±±±XXXdºd‡½½}ÑÌ#-"##ù÷ßù믿˜²ˆˆvìØV«å“O>¤ØÜÜœ™3gòÑGakkû€­’œœœ©Ý#+¦¦¦T­Z5û>ýRŽ^¯Çßߟ?ÿü“›7o²lÙ2*UªT| P8xzö„‰Ó·—‚^ç‚R¾|yªU«Ftttö“'‡µR¥JÌ›7­V›«ÇgT1bm2ˆEœ>}šøøx €ƒƒ-[¶äܹsQ³fM’““¹~ý:rý¥EQ8rð 5+Wõâ«WE«ÜU)êÖ­Ë;3–M5V$´mÛ–V­Z——‰‰‰ØÚÚÌýû÷ZJ„‹EáÚµk>|˜…sæÀG‰zõСЧ”¤¨<ÑtèÐ!S–éÞ½{\½z•>}úРAZ·nö7H©¯™™Ù#ù²HBB‡bçÎ4hЀE‹eR“%9bbĨ¶µ•R¯… E\)£Q¢Rª5jíÛ·OûÛØr4`À*W®L«V­¸téÁÁÁT¯^äädnܸQêl•‚ ( ¬\¹’7ß|“®]»–Α=11’,È©d3k6Ø`$CqÌ ¯SG®›5j@Æökk™™Pì¢8åÊ•ãå—_ÎÔŠŽ ½zõÂÚÚš¶mÛrûöm’““±¶¶&((ˆ   FŽY¬k-jôz=.\`Û¶møúúÒ¹sgæÍ›W<ÎjR’ô]E¿†/3e¾%AžVssóLãððp¼¼¼ˆŠŠÂÖÖggg4hðÐçwíÚ5“ä{BBÞÞÞLH•ú¶²²â‡~`Ïž=Œ7ŽK—.qãÆ Þxã’þœ2×–-¼Þ¦nÍšI©‡ša}â©Zµj¦ž'­VË—_~Iß¾}Óú›gÍšÅÙ³giݺ5»wï&..ŽÞ½{—ôÒ‰¼.]º”™3gÒ m[«¸|YJš´ZÕaU¡I“&4É0g÷ܹsüòË/Œ;+++úõëǶmÛ0`vvvlÙ²…ºuëÒ´iÓ’^z¡bÔ0¸zõ*o¿ý6íÚµËüX±BŒ’±cE$ÃÉIÔë×â{SK3ݺu£[·niÇÆÆâëë›f«tîÜ™+V°gÏÆŒÃ… ¸uëS§N-é¥~~~Ì›7™3gÒ¹sç’^Nö(Š”N¶n ƒ?üqññr 3Î=Õéàÿ+GÑÒR î߇ڵӳ¬ðÙgòŸbýج­­8p`¦m'OžÄÞÞžQ©½Þ½{3gÎΞ=K«V­ØµkIIIôìÙ³X×ZÔ\½z• 0}út:uêT|A™û÷áÛoenjß¾¢_3ÓÅIž¯˜Š¢ÄüÁÁƒIIIIëOÒëõ4iÒ„W^y…Ö­[?²w°råÊ™ævÙÛÛ3mÚ4Ö¯_ϱcÇP…×^{­Ô:n—.añß8#ä––jTD%[LLLhÒ¤IZÃ~Ë–-yá…X½z5sss>øàƒR¹¾uëvvv´mÖLú)ªTÎ妢’ 6664iÒ$í:0lØ0|}}ùä“O055ÅÎÎŽ™3g–ÎAëùD¯×ó÷ßsûöm/^œ}™§ï $ýk Y Ç( ÷¤P¹råLc[*W®ÌôéÓùå—_8r䊢0yòäFƒ”U’’’X²d ƒ ÊV§È0Ä7¶XY[Cõê¼V 0dHÎûކ%Kà÷ßåo ‹ô‘6ÅA` lØ jÆYíâR"2W£FL}É...Lœ8‘~øSSS,,,˜9sf©±U ƒ˜˜V®\ÉäÉ“éÕ«WÑê$'Ëñjn.þ‚F#£Ê\\оú1!Ïkxx8}ôžžži'³J•*¡Õjñðð`ÇŽ¼ÿþû|ùå—tîÜ9Ç`ĈŒ1"Ó¶àââ½{÷¨V­ÚeÅ%MRR[~ûw{ô@ó¨Yx*O<æææüý÷ßi[XX0iÒ$zôèAXX5zdo_qrêÔ)zôèÙ•+pü¸”«¨ä@‹-2ãåË—çƒ>ÀÃÔ”5jôX9 ã~ûí7-Z”ÙYÕëÅ0±±A— Y:•²ËèÑ£=zt¦mƒ ¢uëÖøøøP½zuªçäX•1vî܉µµ5ãÇ/>ÑÂà`صKúø&O–òykkÈ2.ƒ”Ú>êZ¹²ü.å·FÇ¡¸zÿïÜÈÈì_oýzèСxÖ‘³ó;S±´´ä¥—^¢gÏž„‡‡Ó¸qc_|LHJJâÛo¿¥E‹ 4¨hó›7%›ýû‹Â¯“S©mT–È“ÃjœKæïïÏ·ß~KëÖ­133KüèÚµ+ƒfÉ’%|ýõ׬Zµ ''§$>þøÑ¥X**1z½žÓ§O3eÊêԩÜ9srîç‹—lONƵŠJ)C¯×søða&MšÄÚµk™5kÝ»w/Ü ”>SŸôÙÖ–ðì³9;‰‰ðõ×ððÇܾ-ý¹!:ÜÜäÿժ徔¸° Â26¶¤—ñØÌÊ•+™>}zöÊîùÅÓ3ýØ2be¥–y2yêa­]»6uêÔaûöítìØ‘jÕªeŠP#u;wîÄÔÔãÌ«²È;Я†¿þbÿáÃ4ëÜ™¾}ûJ/BÕª%½:•‚{÷˜1ÄMÊîeËS»6fŸ½z©3…UžX¢££Y³f L˜0^½zannžó“._˜·ßV;*eEQ8vì¿üò ï¾û.Í›7/5ï”8{VæK&B3sæˆc™±QΚ¹ÊH§N²ÿÜP§ܸ11pú´Ì¾´°(ÒÏ8·”¿z•^^%½ŒÇšØØX>ýôSÚ¶m›ßD¯¬¬™ÙÈHðö–YÛF4A¥ÐÈ“ÃjnnΔ)S˜:u*|ðÏ=÷M›6ÅÒÒƒÁ@PPÿý7äwÞ¡fn#_¥‘Æ¡MN†…a{þ<3§MÃÒÆZ¶,é•©¨œS§ÀφõÿýGí† é7r$”//Ñg•'ˆˆæÏŸ……ß|óMîÇ8\º$c TgU¥ŒpéÒ%~øá>ÿüóÂë勌„uëàúu Þ€Œ¦ÉOY¤¹¹<7.îáÉËhÁ döjh¨k{ö,5k\“&$FD”ô2[¢££™?>...¼ôÒKyïϾw®^§tÂ9×g¤R%)OψF#•*…Fžµ•5jÄÂ… Y¹r%K—.} ÃjeeÅÔ©S5jÔ££Ò¥åùç¹åéÉÊ;øøûï±PG|¨%½•Â¥"jÕâû¹syóÍ7©­:«*O0Z­–µk×Í'Ÿ|’7gDU[E¥“’’ºuë¸pá|ôÑG´ÌmÅØ¾}âÖ®-ÙR''pp’\EÃÄI}öÙÂ[tNc}}%›;~îö¥ÕJ†¬B7®ÔdWUŠŽ¸¸8¾þúkEaΜ9vVEÄÁþû† gS£/¿LÌ¡CÒÿÜ¥‹ü’"UÆŠ#GŽ@qŒ†z‚È÷ôZ;;;ºtéBã—–ÈÈHfÍšÅܹse¦cYB§CùæÖ]½JÇNèÑ£GI¯HE¥Ð‰kÕŠ¯, I“&ôêÕ«¤—£¢R¢œ~üQFtï^ª2¬*…Orr2?ÿü3 Ì;÷áçõK—ÀË F–cÂÊJfiש“}ÏuT”ôB}Ÿ˜qrgÍ’ì«ììJúcx¬È·ÃšÉÉÉü÷ßÄçÔ,_ZIL$âÒ%üââøüùç1Ë‹H€ŠJ ÙÕë×£S&Ož¬ã*O<¿þú+ãÇÏŸ³zæŒDá;u*é·¡¢’-÷îÝcëÖ­,X° ÷ÓüýáàAxé%h×NnÅ¿?üô|ûíƒ÷étÙ;²ÃÂB²aIIò{Uyì0 àêêÊ¡C‡0 |þùç?¯ÈììçžgU£^ÈùEj×NrL%'KFµmÛôE/½$“T õW›…ÄèhŽ_¾Ì[sæî,2•R@BBžS¦P3)‰ùóçS±bÅ’^’ŠJ‰a0ذaNNNôÏϸ2vîÌ[¦GE¥IHH`õêÕL˜0†9õYAB‚üßÝæÍË›ªoQPµª8zýƒ÷uí*½²¹ÅÒRzXwì€Ã‡Kö}© {öìá­·Þ"88˜7ÞxƒåË—§·(*Šô\¿û.¸ºÊŒß}û`ìXxê©Ü1š7‡×_OÿÛÄš5“ñMûX[·.U£“T‡5EQ0 lÙ»—ð1c¨ß¶mI/IE¥PIHH`Ù²eØDG3rêÔ2-Ц¢RPE! €}ûö1eÊ”¼•H‰‹“ñµj•ôÛQQyNÇöíÛINNæé§ŸF“Q®(p÷®Œž¹{W¶ÅʼnŠîÈ‘%û*U’Y–FG:ãš5š¼9Ôffâh$$dï«”YEÁÓÓ“õë׳téRÞ~ûmÚ¸¸`en.Ž©¢ÈœÔÕ«E8©n]9~ÆÁ°¼¨ÛØ@FUm''é_mÐ@Ê×Ef•ôÇòء֦r÷î]V­ZEbb" .Ä"c-ºJéE˜j;JŽèt:Ö®]‹@ÝI“ШÊu*O0ááá8p€]»v1dȼ`Óë¥çÉÌL2@3fä,£¢RÌ(ŠB`` «W¯Æßߟŋcý0›ÆßfΔleóæ²­k×Ì3%K’™3Ü–œ ü!ý´VVyÛŸFSpc•REbb"_|ñ“&M’*‚”øê+53dˆ'..ðë¯2ºÏH~õ îÞѱŒ=ª={ÊøEDàëÝwKú£y¬È“Ú””Ä­[·HJJÊñqelžÔ¡C‡øé§Ÿ6t(Ϙ™QNQJzI*¹å<ÐPÿJJJ ›6mâÚµk|öÙghJzI**%‚¢(x{{óÅ_PµjUÞÿ}š5k–}æ)ûHYÙÆé%‰F#_E¥”pûöm>ýôS:vìÈŒ3°··Ïü)elÔHŒö?.½3æµZYkÆŠ ãÇe.æ£ú ³rõª8ê˜ÂÇNǯ¿þJýúõ8p lLN–ïùÝwEL£‘c(£³Z~úIÔ°Û¶…¿þ‚š5¥ÇÛø; Rƒ˜E@žÖ[·nñÎ;ï\Òë.4X±bü1í¤,fÔ¨’^–Jn9´DuXsÀ××—¿þú‹Õ+Vàäà Êù«<±$&&òý÷ß3|øpFåç›þãøKK9F3‹2©y²\ƒ‚‚XµjÞÞÞiÛüüü˜={v®³®¥‰¿þú‹þýûS¡B9‰uì(êa*B$â–Ö–Þ`+p¦¤R:Ñëõüù矴oß'''Ï_TZE¥Œ“œœÌwß}ÇàÁƒiWÁ1­Ö¬GU ö¨”R’’’X¾|9£F¢Ivåê±±RNÛªUÙRµ®_Þy']ÉõäI™¥šìì¤ Z¥L“’’ÂÏ?ÿÌ+¯¼BCGGðógñÒ%)Ç-N]víÀÚZ® ]ºÀíÛ°j•¨«*yºú¦¤¤˜˜ˆ!ÃËÉ“'QʘPÑÝ»w9}ú4#GŽÁ{÷Ä0QI§ â&–ôBRIÎò·Qé^UÏ–ððpþûï?†.fÍq•'ŒíÛ·ÇСCóþä;w¤ouøp5;£R*ÑjµüôÓOøøø0räÈÌÙÕ”س>ø®]+饿[[é<{,²Ë¬cnòB%ýŽT È… HHH oß¾˜üû/üý·'o¿ Ÿ~Z´åÀ ý«Û¶I(,,}û˜1а!\¿^ÒÑcI±µQ…¨¨(BBB0 T«VM2œ© ÂÃà £|ùò8;;?¼´%ŸhµZÖ®]ˈ#d¨px¸ˆ-­^­–{eä"â°æ3˜Y¨ç€a¶™#€">7å­VK@@qqqT®\GGGÌR"ôz=ÄÇÇãàà€½½}îUJs‰^¯ç?þ K—.é½ä5j”ôÇ¢òÏýû÷INNÆÑÑLR:­V‹ŸŸƒGGGÊ—/Ÿv_q³{÷n¶oßÎúõë3]krMíÚ°reÙ)¡T)Œ¶Jpp0Š¢P½zuÊg0„ aaa„‡‡™­’|}}Y¶l+Vä믿Æ*㘃A´9NŸ†7ß,Ûê¸uêˆ3лwÁD¢Ú´)éwRjÐëõ„‡‡Š……5kÖÌtüèõzHHH J•*TªT©Ðm•¼’ÀÆyùå—¥oõÔ)xî¹â]„Á6ÈH¥Û·ÓžÌͥ纨æ'”bwXoݺŢE‹ð÷÷Ç`0мys¦M›–V¦uîÜ9~üñG|||¨\¹2/½ôL3ö ???®_¿ÎôéÓňºqC¢3êA–™nH¾4$σW2;¬w€¦À1 (%Â111¬[·ŽÃ‡““£Gf„ ¤¤¤ðï¿ÿò믿Mݺuyýõ×éСC¡®ÁËË‹“'O²lÙ2ÌbceÇðáRº¢¢R@X¶lnnn$%%Q½zu¦M›F§Nˆç×_e×®] š5kÆûï¿OõêÕ‹}¡¡¡¬\¹’Ù³gçÝY½_ú¢êÔQ7O 7nÜ`ñâÅøûû£( -Z´`Ú´iÔ¯_WWWÖ¬Yƒ¯¯/¼ôÒK 0 Pm•GqïÞ=æÌ™CÇŽ™ûì3œœœØ¸q#¿ÿþ;¦¦¦|ôÑGDEEÎG}DóæÍÙ½{7/½ô_}õnnn…ºŽ 60lØ0*W®,"#áÿ+΢ôqɦ ~z!%½8à>p:Ë6K P—Ò‘NeóæÍlß¾O?ý”#GŽ0|øpÖ¬YáC‡¸rå ‹-â•W^a×®]4nܘ9sæSh¯Ÿ’’ÂÚµkyöÙg©V­šÌ;yRôTT Hbb"K—.ÅÏÏ~øþù‡öíÛ3wî\nܸÁÖ­[ù믿X´h6l %%…E‹‘˜X<½gΜa̘1¼ð ¼òÊ+̘1ƒy) ”ëÁŒò•'Žû÷ïóÙgŸQ­Z5þøã6lØ€¢(|üñÇÄÄĤÙ*...ìÞ½›^x p­˜Jnõz=‡æwÞaÒ¤ILŸ>=³³ª×Ñ#bÛX[—}gU¥Ð¹yó&‹/¦sçÎìß¿Ÿ¥K—rîÜ9–.] ÀÅ‹Y²d ¯¿þ:»ví¢~ýúÌ™3‡ØØØ’Yph(†3ÐMœÈ¤Aƒ°3V¼L›&Bbʼn©©¨×®-³X3âî.ëQÖB'O«™™&&&ܽ{—óçÏsþüynܸAJJ /^LÛf¼%dé3 ",,Œ7Þx'''ªU«Æ+¯¼Â­[·HHHàüùó”/_žÑ£GcccCïÞ½©_¿>'Ož,´7ìïïÏ;wxúé§ÓKžyºu+éï¢d9‰8…Fâg0 qf‹=™³ºJê¶°Ô›£:°5™íæÊ•+ >œ¶mÛbnnÎØ±c©S§nnnœ8q‚-ZЫW/lll5j\¼x±Ð^ßÝÝ   çÖyy‰˜XÆR1•|’””„‡‡“&M¢AƒT¨P×_¨¨(|}}9~ü8ýû÷§U«V8::2~üxîÝ»ÇÝ»w‹|m ¬Y³†Ñ£G³xñbþøãú÷XXÀر"´”_5R•2Íýû÷‰ŠŠâõ×_ÇÑÑ‘êÕ«óÊ+¯pãÆ 9wî+VdÔ¨QØØØÐ·o_êÕ«W¨¶ÊÃP…cÇŽ±~ýzæÍ›—ýñ}îlÚ¤ ¿¨<”7nP£F ž{î9¬¬¬hÖ¬cÆŒáüùóœ8q‚V­ZÑ£GlllxöÙg133+T[%7ÄÅÆ2eÊ^üßÿøæÄ Ž5oNåØNL,¹@|‹¢œU¸jU ©:y »™˜˜`mmͺuë2m·´´äÃ?|àñëׯO+Ÿ¨\¹2¯¼ò u3(ñ&''cbb‚‰‰ 7nÜ råÊi¥c–––´jÕŠ+W®Ê›ÕétlÞ¼™Áƒ‹j*@LŒô&=éÑ+@ƪŠD %’a-nQ£@;ÀØ2¦ YÞI@4àºý,ÐGæ±–ñ¿þýûÓ²eË´~&½^Orrršcêââ‚uj‰¡³³3Õ«WÇÍÍ>}úøµ£££Yºt)ï¾û.ööö²±Aé]RNU  ÆO§NÒ¶ét:ôz=&&&\»vç2ô5kÖŒ¤¤$îÝ»G³fÍŠl]ƒ?ÿü“êÕ«3~üøüïÈÁA‚˜*O,F[¥N:iÛ2Ú*ׯ_ÇÑÑQ40[¥E‹…f«äDRR6là“O>É^ d¼ÇàÁ`¬"SQÉB:uxùå—qpƒJQÓJÚÝÝÝéСCš­RµjUªV­Š»»;½{÷.ú†‡ÃÅ‹œýçªU«Æøwß%%%¬d6ïÚµðÅ%SA#‚KõêeÞ^¿¾(«:yú–ëׯÏ×_.—_F,"/5kÖL3dôz=·oßfÕªU 2„ *ƒ™™©ÂG¦¦¦ØÛÛ”³ÇÆ_ýÅĉsìSŠŠŠâúõëŒ7N6$%‰êÜÔ©2GéI&ð:¦þ‚8оÀ¤Ÿµ8Pl/@ïÔ ÀeÄ=‡Ì^É; ™à,%Á)))œ8q‚ãÇ3dÈbý(G%oEQˆå·ß~#::š~ýúqøða¬¬¬ÒœY[[[lmm ÎqŸ>>>lÙ²…P)Á‰ .ààà@ëÖ­Ó7–e¡ •‡Ï¿ÿþ‹››]Šræ\lmmyþùçqX³f -Z´ I“&DGGgšsjooN§{dÙûùóç±´´dðàÁùê æàÁƒÌ;7ïoÊ`€; \91ôUJ ›7o~äù±°©]»všXN§ãöíÛ¬^½š§žz ;;;¢££3Ù*fff´UEÁÕÕ•:uêе™û£GR±bÅLÎôôé#•ROdd$›7oNoQ+&2ö¢&%%qåÊvìØÁرc±—­¬¬Ò*mmm±±±!$äá=bZ­–½{÷R¹rå¼ËHb",^LP\ûÏžeÆ®]iÁ¡4Ö®•Ù§%ˆ÷÷ÿaùòÌ"`Íš©}Y¸uë»wï¦cÇŽÚOž¬++«œO’¹$,,Œ¿ÿþ›­[·Ò¦Mf̘ñ X@ (kqpp K—.Õ¸wïåË—OϮ޹#=JŽŽ~Oež]@ã +€3P égÍ@LŒhTeÔ.ˆ—3Ø©(Šœwrøj$qœ3¶I(HÆw,âX“úoG *âL§¶šétpæ (Š9=zôÅÔÔssóùH=Ê–-[ áý÷ßÏ1»ô¨c¼víÚi’œ¸rå ;wNW«ŒŒ”±ê1þØakkˈ#011)uÒÄÄDöíÛÇÆ±±±áÓO?}ШHEQ”Gã:tà™d6wîÜI§NhذaÞŸ|ÿ>lÞ,FJ©büøñìÚµ«D^Û ß¶míÚµcúôéi§ìÈé711¡sçÎrV#""øí·ß˜3gNf5à¬çJ•Q©R%Æ_쥶F|||øå—_8yò$cÆŒIOè<„œŽq † R0gÄx1‚M§OS­aÃì¯+]»J¯hI9¬U«J 3ëë÷è¡–âg¡I“&<óÌ3DGGh?ùÎ£ÇÆÆ¢Ñh°´´Äßß?ÛFì† f:©*ŠÂÝ»wùüóÏ133ã£>¢mÛ¶iÑxsssEA¯×cjjŠ¢(hµÚ´’…‚ræÌ:uê”åÞ=èÛ÷É$PRoc^@e cÙ}8¸zñË0Â&Cl¢ŒžÚ¹úõƒqãDXùðai—éÓGTç[µ±ÿ*V{{˜0œÓÛ‰‰àë ;·C^’´²‚È@Øä öÑ0ÀEߺØéÞ;`HÔi–!pî$ „š P?c!$DfG›šŠÖVkA“&Å{B‹eÆ 9r„ž={òå—_¦eE-,,Ðëõ(Š‚‰‰ :N÷PC?¯xxxdîiÚ¿_f…½öZ±~…Á ~·…EáUïkµpá‚\óòãã<Œ„ÙoëÖ…+<,、õE!$$„ï¾ûŽ»wï2qâDúôéC… HIIÁÜÜ`«´oßž.]º°nÝ:NŸ>Í€¸}û6—/_fáÂ…E²žË—/³~ýz:vìøè™ÝçÏC›6%ý—.Á§ŸJ@¯qã‚ï¯(Ø¿þü&N”BŽ’nq4 ¡zõêxyyñÜsÏ¥+ú€sçÎ1¹iSLjשõÝ»åìQŒ=QQr\}ÿ}áœXƒƒá÷ß%[¹j•D 2#<)I~'Z-ÌŸ/Õ 6Ht¾ _ÁþýúôS êœ9#¿Õü&ÎSRä7/¿œ>êmçNÙ·qbQIàççGLL K–,yà¾eË–1bÄ.^¼È´iÓ°±±Áßߟ>úˆrEp®ŽŽfåÊ•¼òÊ+ùû éõ6L-¡TIãÎ;ÄÄÄðÎ;ï}úzPF¯×sèÐ!V¯^ͳÏ>ËØ±c­Éàà ¥O‰‰Ôsq‘j¬Òè°º»K0óÿƒõëEVbàÀÂmÉ+IIIܽ{OOOÞzë­L÷999qüøq:vìHÛ¶mùøã©Zµ*ÞÞÞ…f«<” `Ô(vÿ÷ýû÷ϹO»¤11)¶,ïñãpó¦;¥ÑaŒ”„Óˆ’\hÓ† ‘DVa’'‡ÕËË‹û÷ï3sæLªU«–íc,--=z4ÿý7çÏŸÏõ~饗˜4iR¶Ï3–M¾úê«ôë×k׮ѰaCš4i’Vn–_t:çÏŸ§{÷îò©.^,†|F… ‡™.D–ïߎàJZ0.N¢m¯¾ ¿ý&>s£FðÕWðÆв%üø£ýgÎÈ¿Uª@ûöb¼ûøÀûïËzLL$Ãéä$û¸sŽ“£½½Üß´©æ:Óm0ÑÀÈnÐïYÐè Üv0é6«áÍ€®`2WþÅqïí ð%œÊ!5ÇF‚Q@T†m'R_§ 2V<€g¾ÛrHÏ­=` "[ ŠÂÑdrXK‚ªU«râĉlï311A£ÑðùçŸsùòeüýýùøãqvv.ðëÞ¿_æªuëuêÈ´l™xhq$[YXÙ:½^²–Ï>+ŽkA‰Œ„Ï>“6ófÍÄqË2Ú9ODDÀ¡Câ¾òJºÁЮT$äGï' @IgÏJ¹²QÛª}{)7öó“$wnÑj%°ôÕW”úðÃÌ¡_„kײ×z(.:tèÀõë׳½O£Ñ`bbªU«puu%))‰Ž;R±ˆzCwíÚE5è–ß9ÚÞÞðï¿a ŠÊ«¯¾ÊË/¿œí}F[eòäÉôïߟëׯӨQ#7n\`[%+žžžüüóϬ^½GGÇÜíÿÍ7Ÿ˜j­[%«3y²$çôú‚ùÉÉbsY[‹£éàP°ŽšÈH±Çž{Nªãzô€¿ÿ–йlò6ņµµ5‹/fÑ¢E}L¹råøòË/¹tétìØ1]°´¨øòKîFEq{×.¾ùæ›Bÿ=•EîÜ‘V£ÎåßÒVœ?ý$—Õª‰}õÏ?²ÖÂ.î˓Å^¯§Zµji’µµ5£FÊt ›™™Q¡B<==39¬&çÞ‹ÔÇÔ¯_?ÓüÖ‚¢ÓéˆŠŠ’}††ŠÕ׺u¶'uƒANZ§N‰3!3ä†ñã%‚W¹²8åË‹±o‚Qy®™YzÙ¢¢€ÞJÐ%ÊãNœc³cG9‰ýó½ù¦d²©Õ€IDATRLMÅP?p@&,`)¥Õë³\XY‰aŸ&Fk›dqø“ ¨Ð)§=<8‚‰/ÐTL}N%ÄT€üœ?àfêketXcÁÀNDé× ™©Z°Fœ\­¬‹š©¯]™«GU#ÕÇ6ÎAQ`bbòÈ‘&&&´k×.“¬|A ÀÙÙÍ{ï¥{2³fI´å!\¿.½È…1RMQäè8˜§O¬*-)I~ƒ HòK£‘ã~óæüUáËoªA˜>=³QÓ¹³8ŠŠ’;;OQd}‡KiÒ$©–Èÿ²´#E¯ÏÝúRRäÔôÅbÔ ½zAVáó5¤w¼ukùI›ó¸¥¥%½zõ*Òuèt:¶oßÎG}”ÃæÀ‰Xäð;QyòÈ­­Ò Aƒ‚+¢>EQ8pà½{÷¦J•*¹;Æõz9‰=¦†¾N'·;w$p—/½ÑÑrý=:Wyˆ0N48{VÌnÝäZ±b…Øi¹z¨(p÷®Ø‘qq"RÙ¤‰$!Œ ¹=`ß¾‚;×!7ÊòÆ™ÃíÛ·§}û‚d+Á _`ÅŠèììØ´r%C‡-ÚLn)Æh3¿ž½{ŶoØPŽ­‚öj}œ+WĆ7NFÉæöXŒ—Š=Äòö–ÀŒQ ²J ÒïÚ%¶VaÖóä°–+WSSÓ´2`Ãäé§ŸÎòˆb^i‰Ž„‡‡Š£££œ…‚V+_â?ˆ¨êüùéÙ‘þýådlQ©WO¾ˆðpéKÐëÅðô”èÜÔ©’ØŠ‰¥Û¡á)8sÍäøþû²++9`zõ’×Êøåøà5š< £Ýx˜ í³ÄñÓwÄ9ý‘ôŒj/dªÈÍAƒÌL5~ý:$›š‚Œ­1¾öm mêë#ÙÑNH©o ’•î„dUÏ1ݳ¬¥Rêþ³`d…e 6üׯ_§yÖF¸¢È±êéY8kr²8oÏ?/5kò¿/­V7GG9áýù%&Êo,7 ’å\½ZÞçèÑž˜Û¶…o¾#åQå6:œ<)¥ÉU|XÕÜ6n”,éÃ.:ô¡oØ YÙW_•÷ù°˜‡™™\¸®_/9‡µ´°qãF\\\2Ï~Š"D… r{ñEùrJ*]­¢òîݻlj'X¶lÙ#ç4Ž•“c~+Šèh)ktr‚ühS%'Kµ™­­œ{ÍÍ%³jo/o¹];9Ÿæ‡ðp©j±³“N1#¡¡RES­Ú£cz=ܺ%m­Z‰ð^¹rbßeüúìíáÆ qŽ 0áèñáÚ5©züñG®{yáåå•mÛà“Â_‰]ö¿ÿI ÄÓSZÿRRàêÕÂÙÿ‰¢‹Ñ²¥´[-]*SzrÃÙ³r [ÍצLÉ\©W¯ž$ü´ÚÂMΓÃZµjU,--quuÅÅÅ%Û^ ãèoooÞ|óÍÂ[i8}Ú6mÚaçï/k65ƒDÃŒ=xµje6ЫWË¿8°÷ïÃȉxèP9^¼(¿?ˆ …ÖZè:ºõ‡øÊ––¢°[è¸#ÙÍžˆ£—ˆôѶ][$›jÔÖ¤þ[0ÎO<ÉÃj@²¸oîd&"cs.#YÐVH™q$›Úq¬Ã€«ÀDÒç«Æ¤>ßHíÔÇ…gYK5à 鎲;bóøÏĺ~íî\ÁdÔ¨\L:”²6mZð×VQ‚îÑC¢ƒdYSRòÞÔ$eÅ]ºH'ãoÐÒRœ».]$jý¨5%'Ë{ܸQNøM›fï—˜›‹a‘˜øp‡U¯—,íÒ¯:q¢T\ä”LoÝZÎCf‡Õ`¹««D+·na²=D„íQ†QŸ>"èô$sçÎþþûoV¯^ýÈŠ†4’“å@ýí7øà±*‹CÃ@E% þùçz÷îIÜ2GEÖ|6¸Ï™…¿Q™´³r¥·åËÂyÏ.úùɹqÂÈ*nj*%Á Jà/wŸ±œÓ/]’[íÚâ$d¤m[)ßmß>ûó²N'×33É„íØ!í\9]÷4¹6;¦:¬$'KÿÚ¸qè,-Ù¼y3ýû÷ÇÆÆ¦àû.!NœG³^½¼?71QZþ´ZÉî·i#­JuêÈ5ÿÀ3&ë2¤nÓ&i_êÚUŽ_//9md×£ÓÉï×Ü<]ö×_%qgm-_™™¡2R«–¬=(HÖ^Xäé´äääDÿþýÙ¼y3{öì!999ËbàÂ… ÌŸ?Ÿ-ZŠXRA‰‰?ÿlŽs…˜|ö™ÔøfÃåËâ°*ÚÃl ŒÎråä9w®8­Ï='YáÃåš±s'Ô«#‡ƒ“3Ô-œ¢c•ÆnDØÈu¼‹8†u‡ÔíÞÀYÄÉ3œRÓšô£Ã¨Eî´‹âR_Ó5öÀ Hºóy qNm‘L®Oêv£X®âàî%s±=’uõ#s¸¥.’QÎ8—Ø ¢«GU9ª˜>ð’!!!¿‹if0äºv)4Tœ¿½{ þú‰‰â´i#N¥µµ8Š7nä}??ý$e*]ºdï©v»{Wì ï¿— NÕª²Îwߕʄ¬eøâmÚT¸ŸqžDŒ;–»wïòí·ßòÏ?ÿйsgœ‰ˆˆÀÍÍ‹/âèèÈÔ©Só?¯0௿¢ðó;= «Ò‡lnBC¥&û³Ï ¯Ì®[71àm"€/‘Và)òך âdÚ¹ ·`Eº£™„d.í‡Ï ¨€iRg…8—[ˆ“©kϘœÖ§¾^ÆsËM¤„7ɶj€ `âønBœá+€ñºj‘ú÷Õ,¯Ûøq¢³R7ËZ4H¶6é½Uä}’ÿ쪛›5+T RN^Y.^”,á‘#âæ6ˆŸƒAŒœAƒ2'vóÚ¾¨ÕÊZ‚‚$úþ0žs~‹11â(¯^-s€ûôytO“F#ƃ««8¶FBBDh9(HJØ–/Ï}Ù ¤´Îž•ÌqD„DßÛµ“ƒ ò§¢go/AµÉ“ås«ZÕä‰2~BCC9sæ óæÍË[ÛIË–ò«YÕb!9Y -c`Ç`ß’•Uº"·^/×ß­[å|ô„¶­=Àž={hÚ´©´1= E‘›••ô姉é½}[²‰ÇމÃÚ£‡ÞòŠÁ ŽéÿIVgâDÉ´èõb€ÇÇ?zÉÉÒza0HB kלâûô‘òɜ錥 ÄF{õÕœO66"Vùý÷â0[XÈ>ŽuêT±óìì C‡3M£F ¹æîßýúAHˆzýt7bm o¼Apx8¿ýöÓ§O/Re`iù›9SlŒÂò‹SR$}ð ¶ÝÝó.Œ+Ç[¿~ò·££Èd,5VÆ úèý%'KæôØ1 rk4ÏzŽ­^]ìŸþ‘–.ã%50PÚ¼FŽÇÕÃCÚªºwÏÝûiØP>ƒ°°ì'Šä‡<;¬ööö|úé§;vŒýû÷³yófîß¿uëÖeìØ± :”ÚERãš7†o¾ñ£E‹xÆ?O¢õÿx#Ëc""¤Onʔ ºk4©'ÂûˆcÕøq$ Yê™`30št¡¤k€ ’5½dH½ÒYMê<€Äù3Aœ¼`ÄÁl–aÿ¶©÷gõý®§Þ&dØvéKý鉭 ìz ެ/’…uDTˆš#ÂO‘ˆ“‘¶©kÍDxé‘Íx20Æ ssÄØ¶±”ãñ6P/]ºDûaÃ0é×/WaÛ„qê¦N•“vA"éׯ‹óûâ‹™·k4²½U«G/I«•¬c` $¿rº^9;‹c›ÝìòÐPé;o×N¢Þ¹=™˜Hwß>ù;6Vú\ŽEùÍŠ=ôî»ÀÒj¥Õ¸V­ÜëZ[‹Ó}á‚©öí³§I“‚˜Ì³Ã `ccÃ!CèÓ§III¤¤¤ Ñh°´´ÄÚÚ:÷=EEÈ;’ñÅ«˜™Õå™§-™7¯>£CÅH´¢Hú=?" Ö!"EÆ“¼0hˆ8­EaW€ˆƒgTf=ƒ|»¶À Ä黈8{ ÙË $#ig‚d)½2¬$sÛ!ËÚõÀ.à )’55î£pqšíÇøÔý4@Ä–ŽÆj§ H‰p}¤×ÕHÔçg•ñî”Íg`‚(ÿžºß@ù ”aÅ7ƒµ$HHHàÊ•+Ì™3'×zç÷ï§GóEÊáó_2Žgš:õÁ2w''‰î¥¤<ÜÕëÅ)üóOq ŸþÑ úåÊ=÷ö–ÒÛèèt#+·¢LFºtƒúØ1éyut”É@5k¬t«S'1xEÖ^X™PcYYJJÁ÷U–ˆ‰‰ÁÕÕ•¹sçæí‰wïJÝÞ”)%ýŠE‘Š€˜9&ìì$’+†Á ½ƒYýŸ”yž­­Ѷ¶òwPümn.ûJJ48X®•ææò»^¶L~Ç]»JÐiÜ8ؾ]îå9·üü³ü¶t:1èâãáë¯EójÐ ¾89I©Ú?ÿ<8£2<Ü”ðð<þ Ë(Š¢päÈ7nühõáèhI ž‘âî.ßá AéÛjÔ€d^VwwiYøðÃ…$AËÓ§®’ Ï0AJ€MLrW‰bm-Zññr=Rùˆþþ[ŒïÉ“Å1èÐA®3yÉ~½úª8«'Nˆ£óã*¸ç•æÍ%]½: …——¶`;,KÄÅÁüù(K—rÜ̓²|ùr,Š0ZeÌú¿‘šµ:zTL&£€j^1B–/—ý,X çJ½^Jɯ^}xü()I„Ž*TýlØ 6̺u9¯¥m[9§&$<è€&&Šß£Ñˆ†Îĉ"&ikûh»£zu©^˜5Kœbss ¨2VV¹ï ÏHƒ°aO=¶¶‰yßIòíYš˜˜`mmu^-Ãbâöm¹`8pþýûS·ž oO•¯E 9a::ÊH gçB2$#?‘rØ™©ÛžaÝ !]Œ¨°¸Š8kˆÃªE2Ÿ¯#å¿ÛÞФ,ÄÁ<Æ2G“Ôçÿ@fÅ]K$+êNºâp2┾“º_2O5q`G#%Èq©ÿ7V‡÷CèÞ¤}¦H68gcDtDœþÜPé“=ŠdŽ!ïcLDDæææTvw—æž\Ì»¼};]D²fÍÜõ„fÇêÕr’ËN8ÂÑQ Cš£G¥œxÒ$)ƒÉM%PíÚò[ —‹ÃÅ‹b<´l)͇Œ‡~$rñ©YS¢é…0¾ZZxÜ¿33³Ü•JfäÖ-ñæ¤ÌêÈù ´j%QwWWÉZÞ¸!Žh×®’…ïÐA›’"Î`ݺòÛŒŽç2<\úvï‡eÏq»w—H{ÅŠb_úûKð%0P;]ºHÖkà@qZ·†óç¥`ð`1”7–r_ù}¿¶… %³Ú²eúoöÝwå±,A°ªUÅù¹|Ùš7žŒZa­VËÑ£G7n܃åîÉÉòåÔª%ÖcJŠ|áO?ýhyóÐë¥4µY³ÌŽáSOIf%/Ëm'M‡7;ã»eK©~ó÷0Pšœ,Çñ!ò¶òÚ2‘’"=³cÆH0ôêUùé/X ¯•ßÐÁƒÓ?“ÂÂÆ&}Z„æñ®gâï¿¡K|ôz¾ÿþ{¦L™’7=‚|àå%Ž¢ñ8/_^:£:t^¹pAΟC†Hðؘy45•ãßÛûá«««ØakÖȹÓÏOû¨ÀÖVì¤èèÌ«qº‰‰ Œ!ÇU£F¹ÿý˜šÊ5 Cqˆ '‰×®è6k^^ÑDG,Â^ò©Ð"ââEIsûúúR믿 !¦½ŸÆÇGÎõƉ1Y¨½Ý‰ÀÿÇ4ÉnVGJn€ñˆWÈ\"â;“^{™z xq&û#K+$Û: Q 6^ LR·ÛgØR²l‚d73Ò-uÿR÷ E͇ÜQ)=þ qPÃ3ì§ ðIê:3~ö/"¥ÃY–A¤;Ù¹¡%ð90xqÜcpòôÄ&99û9HÙð×_rB‰.<('òܶŽ$%I…­m†ù¾Ypr’‹@v寒uiÚTÊkÕÊ[ÀH«•Ò®›7ÅøY¹2ïóì˜:5½ŸU¥træÌ\\\ò( “HeB§“l¿­­\Ïš5“2Ê¿þ’+UÕÕk×Ä ;V®iCúLáÑ£å˜=Z)ŽÂ¥K’}úi¹ZXÈoÙÔž}Vþ55}0àd̈{É3ŽülÙRÖ˜ñ7dj*YWEÉüû¬REÄ>2ba!Ûºv‡xǨ_¦M‹ÃÆ&'›7oÿ`idR’ÔØzyIê$8n:½I 9Éôd½|T¨ s]º|<^FŒ•-ÑÑhJN–^ê®]¥R¥I“‚Mi«X1ûv«üR¡‚T™¥Ã-D[Û tžžÔpr‚–-±µ• w‘qQâíCz†rð6â^A2‘‰Òý œ–!qlê>Ÿ>FÉX$ËØq k!%·{‘l'ˆÓ윺=ã­!0—…¡:#=¸ˆ“ºé—uD²§7U_£ÊoõÔç8!¥ÊFê"ÝšY^£&<Ð`l|ݼ¥ÕR÷»[€Ï¹ŒpÏÝŽ·naº`A®ê`ýýÅv7ŠW˜˜H¹^llîVƒAJxGñaý ¦¦RN^Rf0È6w÷t1‹ü(f»¸HÔ´ira(,cD5jJ7Š¢pöìY^z饼«HöêUjzX%Ý©4ÞbbDX¦^=q&Ä8‰‰‡ÒÉI¢èîîé¥ê;^³Ûnf–þ›˜a4ä2Fåö1?¬ë'»×ÎèÔfÝžõo33ù êÕgº|y)u{²OƒmÛ¶1lØ0Êg¬‰±N+U’”Pªu­`Bx¸”e¿ývî@Ž9N!?ü £3²~wÎÎbŒ?¬tÄ`>tH‚Ò’aeõè _ÇŽriÚ-’syóæ4ɧf “… åX>F|}强paú¶òå%«˜0ã9;,LF¹4o.•X«Ú¯PAu±±Raõûïòû ’ ;»üµa™›§O&i£êÚUzÎ ò»)+<–?çsçäÀpu=F¿*U°|þù\÷÷7¤ÔöâvDÔx%·õ‘þÍÜ’ˆˆ#eü–®"#`î"½§7[HærâÌ6FXã<É~N"]Y× )åÍêÀW’5£°#õ}Ø!VkDté\êû1õ±fˆ3;ø;Ã>L‘Lo\~y=B­‘Ìn$™U„SÜ®]cÒ_`’ ±äd)Ùûì³tGÑÒRÊ?rÓ ©×KýÄ 9YçÔ|of&‘r£Tzx¸Œ¸tI î‰óÿž‡ +¶W¥qóæM’““iÓ¦MÞŸ\çÿ\rü¸ô®ÙÛ‹ª(RÆem­‹£¨Y³tã¿G’^yñbtÀ ÖöTfpssÃËË+ûþl£zUEdÎÏOJ§LÉ}fåÚ5ÉÞ÷è!BWÙ©ï–+'·­[̆ƒô3ýµœãçÏÏ›0]‹’E?wV­*¼ ;»üõÚ©IIàå…›NGhh(ÃV¢•Ë—ÅÑÌ(Þ•[’“å%wï~p’F#¥¼?ü =Ÿ9¬]]%£Ú¼¹8£¹±ABB¤æÖ-±wŒmXZmþ¦iÙR~o9‰–=®<–«›´nmàÈ‘³L˜9³psÒF‘ŒcF‡¯%¢Pk‡8f1H)­ÑqlGÞ&ß®Fz2£6n }™m‡¸9p)Ç5:˜ú¸Ú^+)“ý<þ5H65$ëéLúüÔKÀó©Û;ß#YÛŒYºîH qÖ’ÞÑ©ŸOQQ‡Ü;Äe˜¨ÈHîãÚYMùýw ¸˜›‹xWT”´‘<ÿüÃK"…¥eá ©”BBà矹>f wÿøƒ¯¿þú‘O9yRͪUó&yñ"üô“TÐg­®Ïˆ1Xxäˆ(L÷ÉÉb­]+AÅÌy?ÙѸ±ôUüõãÊcwÙ ’(¶ý‰ý °²Â¤PU•R1 âIížNGD!·2–Å$u»’‰5b(è&“ÙaF²–Æ~MR:< ØdT+ ª¼ÆQ0ÖHvõ0¢¸ ’Ù”º-c¹@Ä9­Ÿå}´Ff¯æ…6H–·w–í£RßwÆL9é#sT %&ÝŸÒé…rõø7DÚß8&ÀˆQ%;UE¥»” ÐÔ©Î ggqû÷Ͻ “ŠJvxyyannN¥¼¦r@,ì¨ÙëtR»r¥8¬¯¿.טž=%{êë+«ŸŸ8 11’Ôuq¥E£sZ˜b*çΣU¥J˜N*,,Dýêå—夛ÁŽIL”ó²Ñá´·—@ÉÕ«?Æôzq:wìÀÉ3Ï+4Quu•òÆZµ¤JÆÉ©`e*O :ŒË¡;wèׯ_ŽUqPwìá/++éñ0àÑŽcT”L0?>w ýuëÊë –>CúÔ)q6'M’*€üØ/•*IPG¥ðxìVƒAÒïAßl¢â3C”†/ ‘q5#Rÿm‡ˆÙ Ë*H6ó2ƒ5#&ˆ£™Qlæð°h†”éþü˜ú¸+H–µ’aQýýqrû2E—2;ÄDø)ë·Ÿñ:ŽH©rVTÁšâåÎκ¹ÑaùòG>T«•9_cÆd/räë+yÆÞ½^ú‹ÜÝ%S:aBÞ &÷†‘ŠÊÃÐétüöÛo <»ṵ̈µM(— ¤¢ÀÞ^¢äˆúùçÀèåË™×é$03fŒ4(HœÈÙ³Ó[ˆlläœÛ«×ß—œ,ÇùÓOçzhµkËó~ÿ=}dÞôé⨦àå¿*™yìÖƒ¡ºu87NÙ ˆÌ7ÞLãõ#Rª‹8p‘À2—áŽÞDËŒh¢©‡¦>w.p"uŸAȼS¤÷ÃÔûZ’Þ#ZÉʶ!³³Øqœ³ò6h?΄˜›ãÖ­}1Ò`RÅví2…ÏHƒ½4-ÎêÎ2À½zuUAW¥ä¸rå III<•ßÂ&M²W•ÉBr²d©ví’ã½Z5É–š™I¢Ë­oÔHnz½DüML ”ÀUy¹ãåEP@-ú÷ä‰öÜ9øç)wÌXVÞ­›h DD¤WÁ 2o~åJïÒ«—ÿy):31I\Rq•|‘œ W®`hÑ‚?ÿü“V­ZQ;‡Fý˜jÙ2ói»gOécÍê°æM˜75•,錹_ž³³rNž”c½jUÕÞ)­^ƒÅ#3F32 µ÷I$ ÷ƒé;rdŽFŽÑùœ=;{¡#F?`Ý:)ž0A„aÔr•’ÆÇǦ{ûòæM’‚ª]­VÔ#½¼dDSãÆ]·³“^&µäQ¥øÐjµ˜üñgÎÌñqáá¢înk›^zž•Ž¥÷ÎÌLŽíØXcrv~´ ¼ŠJ‘±s'ôîÍ/ýEß¾}©™CÏÄ?Š6Óž»§OcÞµ+6Ö6ÒWú°·’z3Þ‹”ð¾‡dU£‡µ&’áx¸EæLj~© |†:“ô CQbbb8tèAAA´jÕŠvíÚaó°³tÖç''s4)‰:27/ët2êÀÕUM‡•Œ©ŠJqc0 bÿþýèõzÚµkG‹-0Ïc­í¶mÛ0`@®zW éÁ>zTþè7•+û›;Qµ•)Öj¿©J!Ϲsç¸víuêÔ¡gÏž¹·U€;ÞÞDÆÅѨ{÷LÛu:QIýæÉ’.Y"%¢\9hÞ¼¤?•ÇEQˆŽŽæàÁƒ„††ÒªU+Ú¶m›k[%$„ã—.СC‡ û–¬êáÃòo£FÒšñ¨]7h =Ü*O&¥Îa]¸p!.\ cÇŽœ9s†ƒ2oÞ<ìs·µeÿˆÔ«S‹{RÞ;šL="œtÉhÚ"™ÕzHIn5àƒÔO'ã˜ËÊHia¡:«O‘‘‘|ðÁ$$$ШQ#.\H·nݘ3gN®žŸhcÃùví˜Ñºuú¶Dp½oŸ¨Aöî]ÒïRåIæÖ­[|üñÇT©R…J•*ñçŸ2eÊFŒ‘ë}øùùqáÂ^}õÕ/3†OÔÛ·E|#³ °SI$*! ,àÊ•+tèÐÓ§OsèÐ!>ûì³\Ï ö]·Žç;tÀ:C†—lÙ"¥¼Ï<#s}U-•’ <<œ>ø€ääd6lÈ‚ èÕ«³fÍÊÝ‚‚zí5þ47磯¿¦\ªÌº¯/ìÝ+Çu|<Œ«×UrG©rX¯^½ÊéÓ§ùàƒèׯ¾¾¾¼üòËœ™­:y²Œ¡ÉªŽª¢R\ºt‰N:Q£F LMMi×®U«VåâÅ‹¹rXÝ®]#¤k_: çï¿å”___<==é¯* OOO ”¦=ààà€ƒƒ¹zþ>‡q\ôjLʱò<ÿ¼T”/_úëwïÞ%((ˆ.Qê.\¾|€6mÚ”ôRŠ•ReêêõzLLLÒ!MLL033#>>þ¡Ï111!66–µk×R«V-ÌìÌÀ¹e%qXw•ô;•>¯›7oæºß¥4àååE… ¨R¥JI/å‘îß¿ÏèÑ£Kz9ièt:4Mš0‡©©)¦¦¦$$$<ô9æææðí·ßR¾|%ê×7£F ¸|Yn¥‘ääd<<<ˆŒŒÌqVli"%%‚‚‚°*i½^Oxx8‘‘‘t/ED½^Ÿit¹¹9z½žäää‡>ÇÚÚš3g΀NW›“'pÿ~VV¡´k…X—“ÛÕkr+ibccñññ!22²¤—’kâããñöö&66¶¤—’k|||Jz [EQNœ8ATTÑÑå±v‚¶M¥§Ï×·¤ßQö„……‰¿¿I/%×DFFBPPPI/%Wèt:îܹC£FJz)¬+«­¢Ñhr´U´Z-;vìàêÕ«Ä%[Ѿý=477¹•FÂÃɉ‰ÁÛÛ»¤—’küüü011áúõë%½”\‘€ (Ð~Ê„%i‘ƒê€F£aüøñhµÚL?®ÒŽ¢(ef½eq̓ “¨Ei%'U[[[f̘ñÀ¤´£(J™YkY\³¢( 4Mî•KF“càÂÁÁO?ýS^yÅ F‰‰RÒËÏ–²v≯f½^_f‚^9Ù*vvv,Z´(“£[Ú)‹ÇxY[³ñ<^V*‘r²UÚ¶mK“&MÊœeçx)‹k6ãµÅKÕU bÅŠøûû“œœŒ¥¥%:ŽÐÐÐlg7111ÁÊʪLdDTTìííILLLËBÅÅÅ—c™µ‰‰I©wHTTŒTªT‰¸¸¸´¿ÃÂÂ077OkõÈìììJzé**¹¢bÅŠg²UÂÂÂr´U4Új Rf°··'!!!“­OÓ¦Mú333õW)2JU˜¯S§NsïÞ=@Ê ÏŸ?OÇŽKzi**…B÷îݹ|ùrZ阿¿?÷îÝË4£LE¥¬bjjJ—.]8yòdÚ¶Ë—/cee•+Q1•²@—.] L+WNLLLǧ¢ò8н{w.]º”Vìë닟ŸíÛ·/饩<¡”*‡ÕÅÅ[[[6lØÀíÛ·Ù¼y3111ôìÙ³¤—¦¢R(tëÖ°°0vìØ‡‡¿ýö*T u†¹ª**eFÀ¸xñ"àÂ… lÚ´ j×®]ÒËSQ)\\\°±±á÷ßO³UbccéÑ£GI/ME¥PèÞ½;¡¡¡ìܹ3ÍV©T©...%½4•'ÅX ]Jðòòâ§Ÿ~ÂÓÓ“êÕ«ó /СC‡2Óó¡¢’ƒ³gÏòóÏ?JË–-yá…hذaI/ME¥PÐétüóÏ?ìØ±­VK‡xõÕWË”ÀœŠÊ£¸}û6?ýô·oߦF¼ð ´oß^µUT ®®®üüóÏ„……ѪU+^xáuJ„J‰QêV%ÃèèhÊ•+§Öë<–DFF’˜˜ˆ½½½Ú­òØa0Ç`0`ooŸ£P‡ŠJYÅh«ØÙÙ©=Ø*%ª­¢RZ(•«ŠŠŠŠŠŠŠŠŠŠŠŠŠŠZ»¢¢¢¢¢¢¢¢¢¢¢¢¢R*QV•R‰ê°ª¨¨¨¨¨¨¨¨¨¨¨¨”JL?ûì³ÏJze€€Ž9Â… 055ÅÑÑ1í>ƒÁ€——‡&((ggçL$:ŽsçÎqêÔ)´Z-UªTɤ2˜À¸~ý:VVVT¨P“B[{tt4»ví¢aƘšš ( ÷îÝãðáÃâàà€¥¥e¦5_¹r…ãÇ““SÚs´Z-ÀÝÝ *T¨ *'–a žžž:tˆ7nP±bÅLbh:ŽË—/sâÄ ptt|àxØ¿ÚñP±bÅLÇpPPäÞ½{”/_žråÊêúýüü8~ü87NÛ¦×ë¹víG%::šªU«>°æ£GrñâEÌĮ̀T©R¦c8<<œƒâííM¹rå(W®\¡þ.UŠ­V‹››Àßß''§L#Z­–#GŽpéÒ%ÌÍÍ©X±b¦ã!,,Œ¤x ÞÞÞi×''',,, uý×®]ãÖ­[™F¥¤¤pâÄ Î;€½½}¦5GEEqàÀ<==±±±¡|ùòiǰ¢(øøøpèÐ!¨R¥J¦k€JÙ#!!'NpìØ1âãã©R¥J&[$22’ƒâé鉭­-vvv™Ž‡‚Ø…Á‘#GHNNÆÁÁ!m[\\àæÍ›X[[?p ûûûsèÐ!üýý±··ÇÚÚ:í¹z½ž7npäÈ¢¢¢pvv.ô5«/ááá>|˜³gÏb0pttL;ç)Š‚ŸŸ_ŽÇCAl‚‚’œœÌ®]»prrÊ´®ÀÀ@<ˆ+VÄÆÆ&Óš=<<8räaaaT«V-ÓšSRR8uêgÏžEQ”®e Õa-z½ž½{÷2}útBCC dýúõ$''Ó¢E ÌÍÍÙ¼y3_|ñÑÑÑœ:uŠcÇŽÑ®];ìììHNNfîܹlÛ¶ØØXvî܉;wÆÔÔ”{÷îñî»ïråÊüýýÙ°a+VÌdxtý?üðß|ó ¯¼òJšõï¿ÿ2{öl"##quuåÀ´mÛ–Š+0oÞ<6lØ@\\»wïÆÃÃŽ;baaA`` ï½÷gÏž%$$„ 6`ffF«V­JúëRÉZ­–Õ«W3þ|ñðð`ýúõTªT‰F¡( óæÍcãÆÄÅűk×.nß¾M§N077' €wß}— .Ć °°° E‹\¸piÓ¦áïïÏõë×Ù¼y3...™‚>!66–?þ˜#GŽ0qâÄ´í_ý5«W¯&!!}ûöáææFÇŽ±²²"44”Y³fñßÿÁ† Ðjµ´k×www¦OŸÎ;wÒæÓµhÑ‚ªU«–ô×¥’™>}:þù':Ž3gΰiÓ&š7o޳³3!!!Ìœ9“'NΆ Ðëõ´iÓ777¦OŸÎÝ»wÓŽ‡V­Záìì ÀÖ­[™7oQQQœ:uŠ£GÒ®]»BSÀ÷ööæƒ> &&†~ýúâŒÎž=›ÅüAdd$;wàæÍ›Ì˜1¼½½Ù°aõêÕ£V­ZìÛ·?üˆˆÎ;ÇÞ½{3]TÊwïÞåõ×_çÂ… $$$ð×_qàÀz÷î 7nÜ`ÆŒxzzâííÍo¿ýFÆ ©Y³&P0›  (Š‚««+ï½÷ 4 yóæ€Œ@œ1c×®]ÃÇLJ 6àììLýúõ8qâÓ§O',,ŒK—.ñÏ?ÿЦMìííøöÛoY¹r% ìß¿777:tè *á–AEáäÉ“L™2___ÂÂÂØ°aþþþ´k× Ž;Æ»ï¾Kxx8.\`×®]™Ž‡‚ØÅ`0°uëVæÎ˰aÃÒ‚2®®®¼óÎ;áîîζmÛhݺuÚý?þø#K—.%..Ž#GŽpîÜ9Ú·o 111Ì™3‡½{÷ÅŸþIxx8]ºt)é¯+ÿ(*ù&<<\™8q¢2oÞ<%22RIHHPvíÚ¥tïÞ]¹zõªâçç§Œ5JY½zµ’ *ƒ RÖ®]«(Š¢¸ºº*={öTþûï?E«Õ*‡Vºu릸»»+Š¢(ß~û­2|øp%((HIHHP–.]ªŒ;V -ðÚ ƒròäI¥{÷îJ£F”ØØXEQåþýûÊ„ ”¥K—*qqqJPP2jÔ(eÙ²eŠN§Snܸ¡tëÖMù÷ß­V«œ;wNéÖ­›rêÔ)EQeݺuÊ€%))IY½zµòÌ3Ï(AAA%ýu©äƒ7n(O=õ”²aÃ%!!A‰ŽŽV-Z¤ 8zô¨Ò·o_åСCŠN§Süýý•É“'+Ó¦MSEQ6mÚ¤ôë×OñööV´Z­òóÏ?+T•øøxåƒ>P¦L™¢„‡‡+QQQÊÌ™3•iÓ¦)111Š¿¿¿2zôheåÊ•i×€!C†(kÖ¬Q C×®Óé”Ù³g+Íš5SfÏž¶}÷îÝJŸ>}777E«Õ*[·nUºwï®øùù)ÉÉÉÊgŸ}¦Lš4I Ubbb”O?ýTyíµ×”ÈÈH%((H™8q¢òõ×_+±±±Jpp°òì³Ï*ß~û­’’’RÒ_—J>X±b…2tèPÅÓÓSÑëõÊ¥K—”aÆ)ëÖ­S’’’”¹sç*/¿ürÚñðÉ'Ÿ(¯¿þºU`›  )/¾ø¢Ò¸qceóæÍŠ¢È¹}áÂ…ÊØ±c•àà`%..NY¸p¡òüóÏ+áááJXX˜òÒK/)óçÏWbbb”ÐÐPå…^P,X $''+žžžJ¿~ý”-[¶(Z­V¹yó¦Ò½{weïÞ½%ýU©ä­V«¼ùæ›Ê[o½¥„……)ÉÉÉÊáÇ•>}ú(GUBCC•I“&)_}õ•£„„„('NT.\˜v<ä×&((ƒAqssSžzê)¥Q£FÊ­[·EQ”ÈÈHå7ÞP>þøc%**J W&Ož¬Ì;WIHHPîܹ£ 2DÙ°aƒ’œœ¬øøø(Ý»wW¶mÛ¦(Š¢ìÝ»WéÓ§rùòeE«Õ*;vìPºvíªøùù•ôוoÊnn¸˜˜Hll,'N¤bÅŠX[[3dÈ"##‰ŠŠâöíÛhµZžy欭­©Zµ*C† áèÑ£€DOZ¶lIÛ¶m177§mÛ¶4mÚ”S§Npúôiž~úé´gžy†ÄÄDnÞ¼YàµûùùñÃ?0jÔ¨LÛ}||gÔ¨QØÚÚâääÄСC9uêÉÉÉœ={– Ð¥KÌÍÍiÖ¬mÛ¶åĉœ9s†AƒQ­Z5,--WWWºtéBãÆ177§GT¯^3gΜœÌ… 1bØÙÙñì³Ïâëë˽{÷ðõõ%$$„Ñ£GS®\93]Tʾ¾¾ 6Œúõë£ÑhhÓ¦ 4H;>/^¼˜éx3f wïÞÅÇǧÀ6AAÐjµ¬]»– dÊîëõz\]]:t(ŽŽŽØÚÚ2|øp"""¸}û6ܹs‡qãÆagg‡ƒƒ#FŒàܹsÄÆÆrùòeéÓ§æææÔ«Wnݺ¥]Tʃàà`ž{î9*W®Œ……}ûöE£ÑL@@¾¾¾Œ;;;;ªT©ÂðáÃ9{ö,ñññ² Jll,ß}÷Ì´=44ÆŽK… °··gôèÑ\¼x‘ÈÈH®]»†­­- À‚5jЯ_?þûï?@®:u¢I“&˜››Ó­[7jÕªÅéÓ§KúëÊ7ªÃZX²dIZ•±'ÂØÃHJJ NNNiÏiܸ1xzzâààV“nggGõêÕ3ÝŸ±'©V­Z †ÆÉÉÉlܸ‘–-[Ò©S§L÷…„„GõêÕ3­ÙÛÛN‡§§'•*UJ+g³¶¶¦N:™Ölü<€4GåÞ½{%ýu©äƒV­Z1þü´cT§ÓqãÆ œÑh4iǃ±gÏÚÚšÚµk?ô®V­æææøøøG```¦ã¥I“&Ü¿Ÿ˜˜˜­;..ŽŸþ™#FP§NL÷ݹs[[Û4ÈÜÜœúõëgZsõêÕÓzA)_¾<ÞÞÞ$%%áëë›iÍ7&,,Œˆˆˆ’þºTòÁ!C˜6mZZùb|üÿÙ»ï訪µÃ¿™É¤÷^€@B轄^l(Š¢\@® JóbADQA¤ª¥ ÒD@zM轄@HHï}úÌ÷Çù2CK™ö³Vdê>“=çìòîwpõêU©>˜×þxyyáèèȵk×P©Tܼy³DNKK#++‹¤¤$´Z­9<¤úUîëåË—Y¿~=ï¼óN±u}Eeöõõ5“»»;ÕªU#** ½^OLLL±2×®]›¼¼>>æµæîîîxyyqùòeKÿ¹ÊLtXËÁÆÆ†ÐÐP”J%z½žM›61~üxHhh(:“É„•••ù9vvvæÆ¸V«E¡P˜/" …kkkrrr©cyûsmll0”¹ÌF£‘7Í!CJ$ÒÐëõ †eÎËËÃd2•(³\.¿c™‹ÜÞªóš œœ–,YÂâÅ‹yï½÷°µµ½c¶±±¹k¾½>Fôz}±Ävvv¨Tªr5Œ5 óæÍ3Ïfý›V«E.—›/>r¹üŽe.ªÃJ¥¹\nþètºeV«Õbö©ŠòööÆÏÏÏœ¤eæÌ™=z”aÆw>§Éåròóóï[t:F£ñ®×€²*((`Ö¬YtëÖͼ¦ïv…BQ¬+•JrssïXæ¢ï²Z­¾ë5 ??£Ñhé?—P5jÔÀÝÝ£ÑÈåË—ùì³ÏÐét 0à®uX£Ñܳ>ÈåòreÜݳg{öìáûï¿§°°Ð|QJMMÅÅÅ¥Le†{är¹¨ãUX~~>Û·ogåÊ•xyyñí·ßÒ°aÃ{>ç~çé{Õ‡òœÃu:¿ýö:Ž®]»’žžnnœ¤¥¥™“ˆ”ö}‹êðÝ:¥"ƒjÕe2™ÈÊÊbéÒ¥ìß¿Ÿ&Mš0aÂ<<<îºüâ~ç´ò´ î'??ŸyóæQ¿~}‚ƒƒIMMÅh4’——GVVÖ]ÛW·w:îvÿ½®-å)³`YF£‘¸¸8,XÀÕ«WéÚµ+¯½öZ±Œíÿv¿kvyÚ÷“™™ÉܹséÓ§ÖÖÖ¤¦¦šo/ º[™ËS‡«òy\|;ËÁh4É·ß~K³fÍøàƒŠMß;88 P(P«ÕæÌséééæl¢...h4ôz=VVVh4rssñóó3ß_XXh~½ììl Å=$÷säÈRSSY¼x1Ë–-3Ï|Ž3†—_~WWW”J%*•Ê|QHOO7oUâââBZZšyDV§Ó™S€ß^f“É„L&#//ƒÁ€§§§¥ÿ\B þüóO–,YÂóÏ?o^çTÄÅÅ…œœœbõ!;;»D}(’››‹Ñh¤Zµj(•Jìíí),,4×é´´4ózð²Úµkùùù%@OKK#33“wß}— &àääD||}ú´ùKzz:õë×ÇÑÑ‘ +sdd$¾¾¾m+¡bíØ±ƒ'N0iÒ$zõêU¬³ R}8uꔹ>ܸqƒÌÌLêÖ­‹““õë×/Q‡ýýýñôô$$$[[[.\¸PìþF•9ŠÀÙÙ™ &ðÙgŸ™ëxÑvÇÇÕÕ•6mÚpáÂó€dbb"7oÞ¤qãÆØØØÐ¤I“be>yò$...øûû„‡‡§OŸ6ßäÈêÖ­ûÐ÷*ÆÒ¥KQ©T|õÕWtèСØÌ’­­m‰úpâÄ ÜÝÝñõõ-w› ,ªW¯ÎÔ©S?~¼¹Ž;::Ò­[7s✖-[+ó¹sç°¶¶&((???9vìX±2…6kÖŒÌÌLâââ)¼øäÉ“å*³`9:ŽéÓ§S¯^=>ÿüsêÕ«Wìþ€€üüüŠ%I*ªvvvåj”UÓ¦MùñÇ3f £FbÈ!¼þúëtïÞ‚ƒƒ‹ÕለjÖ¬‰‹‹ 6D¥Rqýúu@ê´GFF+óí×€¤¤$nܸQ"A_U"fXË!))‰K—.áããCLLL±ûLHH~~~¬^½OOO®_¿ÎÉ“'Í£âáááÌŸ?Ÿ¿þú‹gžy†7’››KûöíèÖ­sæÌáèÑ£xyy±jÕ*ªW¯^®}XýüüÌ3¸€yä&<<GGGsgbÕªUøøø˜˜ÈáÇ>|8ÖÖÖ´jÕŠo¿ý– 60`ÀþùçRSS騱#;wfòäÉ>|˜5j°jÕ*<<<Ä>¬UÉdââÅ‹$$$°cÇvíÚUìþÏ>ûŒV­Z1}út6mÚÄ‹/¾È¶mÛHKK3ׇ.]ºðÕW_qøðaYµjžžž4hЙLFxx86l nݺh46lØ@ÇŽKtŒK£N:ž#W®\áĉæïU³fÍ0™L¬[·Ž·Þz‹ÇG}@ÇŽÙ¶mûöí£Q£F¬Zµ ;;;š5k†B¡ }ûölÛ¶-Z —ËYµjmÚ´)ö½ªNÇ‘#GÈÉÉaÅŠÅò^^^Œ5ŠN:ñÉ'Ÿ°ÿ~êׯϪU«ptt¤iÓ¦( ÚµkÇÖ­[iÖ¬«W¯¦]»vøúúâááA@@«W¯ÆËË‹˜˜Ž?ÎØ±cËÜaµ¶¶.q>]³f ŽŽŽæ}VÛ·oÏüÁ®]»gíÚµ˜L&óÞ˜:ubýúõ´oß{{{V¯^M“&M B¯×S·n]V­Z…¯¯/ÉÉÉ}šAƒÑ»wo NNNÔªU‹ 6°jÕ* =z4!!!Èd2‚ƒƒ±²²â—_~aëÖ­øúú2zôhsf»‡A¥R‘ššJÏž=͉9š5kÆ¡C‡X¹r¥yûƒçŸ+++lmm©W¯[·neÅŠ¤¦¦2jÔ(5j„\.'00WWW~þùg6mÚ„‡‡cÆŒ!ÁUÉd2g‚Ôjµ%êx=prr",,Œ-[¶°bÅ 2225j 6D&“ˆ‹‹ ‹-bóæÍxzz2f̪U«†B¡ qãÆDEEñûï¿sðàAš7oΈ#êLNVVr¹ÜÜ€²±±¡~ýúìØ±ƒßÿ¸¸8Þÿ}Z¶l‰\.ÇÇÇ///–.]ʺuëprrbìØ±æÌÈõë×'))‰eË–±gÏê֭ˇ~(óUF£16þ»ŽÛØØÐ±cG|}}©V­K—.eýúõ¸¸¸0fÌs}hРñññ,[¶Œ½{÷šëƒ J¥’¦M›²ÿ~ó5`àÀ<ýôÓu½\bb"~~~æŽlµjÕðóócåÊ•¬]»¥Rɸqã@&“FNNK—.åŸþ¡V­Z|øá‡888 T*iÞ¼9‡6_ž}öY^|ñE±Æ¯ ÊËË3gý÷9ÜÇLJÆS·n]ó×]»vQ»vmF½½}¹ÛËõë×iÖ¬AAAÈd2j×®Á`à×_eÛ¶m2zôhœ±²²¢eË–DDD°råJ"##éÞ½;¯¿þ:J¥4hÀÎ;ùí·ß¸qãï¾û.­Zµ¹ª ´´4P*•%êx½zõ¦E‹æúpôèQžzê)h®em<,:ŽØØXºu놳³3 …‚æÍ›sæÌV¬XÁáÇiÛ¶-C† ÁÚÚkkk6lÈž={øý÷ß¹té#FŒ0GP¸»»`¾( ÆW,SrU#3•7·¾p_ùùù$''ãè舷·w‰‘õ¢-¼½½K$…1ÄÇÇ£Óéð÷÷¯°FqAAÉÉÉØÙÙ™f·ËÌÌ4¯ ¹Søf||<*•Š€€€r­Gª†¢úàééyÇ•›7o¢Ñh(Q‡5 ‰‰‰( |}}‹eÅ{”²³³IMM5oùño‰‰‰äççX¢ët:ÉdŶ_ ܱ>hµZ‘Édæ­›nWt (ÚDz¢ÅÉÉÉäææâïï_"ÔY¯×“€ÑhÄßß¿D.,,$)) ;;;¼½½ÅúÕÇ\Q}0™Løùù•¨åm< ƒ„„ôz=þþþ%v=P©T$%%amm¯¯o‰:œ““CJJÊ]¯Â㥨>ØØØàããS¢>”§Mð¨¨Õj’’’°²²Â××·Ä aÑö7...w\–Tt ðóó«òy6D‡UAAA¨”Dìƒ ‚ ‚ ‚P)‰« ‚ ‚ ‚P)‰« ‚ ‚ ‚P)‰« ‚ ‚ ‚P)‰« ‚ ‚ ‚P)‰« ‚ ‚ ‚P)‰« ‚ ‚ ‚P)‰« ‚ ‚ ‚P)‰« ‚ ‚ ‚P)‰« ‚ ‚ ‚P)‰« ‚ ‚ ‚P)‰« ‚ ‚ ‚P)‰« ‚ ‚ ‚P)‰« ‚ ‚ ‚P)‰« ‚ ‚ ‚P)YYºO:FC~~>&“É|›B¡ÀÉÉ +++ŒF#‰‰‰¤¥¥áíí››Z­gggd2F£‘ääd’’’pvv¦zõêX[[£ÕjQ©TØØØpíÚ5ôz=ÁÁÁØÛÛsýúuòòòÀÓÓ™LF^^ …‚‚‚nÞ¼‰««+‡Éd",, kkkKdÂc$++‹¤¤$j×®-ê–ðÄÈÈÈ 55•Úµk£T*Ëýz h4‚ƒƒ-}h‚ ‚ðЉ«…mß¾Y³fë°úøøðÅ_‰'9r$‰‰‰ÔªU‹Þ½{“’’¤I“°··gãÆÌœ9“k×®áîîÎK/½Ä‡~ÈÅ‹ùå—_¨V­üñ:Ž~ýúÀÒ¥KÉÊÊ¢nݺüúë¯øûû3gÎöïßÏÅ‹ñððà¿ÿý/û÷ïçÈ‘#FþóŸÿ0nÜ8¬¬DµŽcÇŽ1wî\,X€···¥‹#âàÁƒüöÛo,X°r¿ÞÊ•+IHHà‡~°ô¡ O¸„„Nž}šüü|:vìhéâ<DH°…uîÜ™Y³fñã?2uêTlmm)((ÀÕÕ•èèh†NŸ>}8þ<|ðÓ§OçäÉ“èõzNŸ>͇~ÈóÏ?O||<³fÍbÉ’%,Z´ˆŒŒ þüóOL&.\à×_å‡~ ""‚={ö°mÛ6nÞ¼ÉÚµk8þ<³gÏfêÔ©\¹r…† 2f̺wïΙ3g3f Ë—/çÒ¥K–þȄLjF£!33ƒÁ`é¢B…)ª÷F£ñ¡¼^~~>999–>,AàøñãŒ5ŠŒŒ KEƒÁÀ¯¿þÊôéÓ-]”'†˜*³0gggêÕ«‡Á``þüù$&&²lÙ2<==9pàùùùŒ5 GGGžyæºwïNbb"k×®¥nݺ 8ÂÂBš7o΀ظq#aaaøùùñÊ+¯`eeExx8¯½öîîî(•JêׯF£1—¥G4mÚ€¦M›rèÐ!^|ñEìííéС ,@¯×[ú#ª˜˜˜nÞ¼Yì6êÕ«€Éd"33“uëÖ‘žžN§Nh×®666˜L&²³³Ù°aW¯^¥M›6tèÐ777ôz=/^ÄÕÕ•óçÏI£FèÕ«'OždïÞ½xxx0pà@ìíí¹téîîîœ:uŠãÇÓ¬Y3žzê)Ž9¡C‡ðóóãå—_ÆÉÉ ™LféM¨â®^½JRRR±ÛÜÜÜŠÕûääd–/_Nnn.]ºt¡M›6(•JŒF#YYYüñÇÄÅÅѾ}{Ú¶m‹‹‹ Z­–‹/âããÃÉ“'Kt L&‰‰‰Ü¼y“¦M›bcccéBxÌœ={–ìììb·ùøøàîîΕ+WP«Õœ>}RRRP(ddd°sçN&L˜@||qqq¨ÕjrssÙ¶m¾¾¾<óÌ3äää°cÇòòòx饗 çmá¡*ªÇZ­¶ØíuëÖ%++‹ÄÄD2339sæ µjÕ"::___Ž;FNN$??ŸpìØ1¼½½éÒ¥ ¡¡¡Èd2.]º„ ±±±ìÛ·z÷îMLL »víàÍ7ßÄËËKÔmD‡µR0 ¬_¿žùóç3sæL4hÀÉ“'©V­ŽŽŽ€´¶ÕßߟÄÄD4 ÑÑÑ\½z•š_+%%¹\Ž^¯ÇÑÑww÷bïUôZ2™¬ÄÚ©ÀÀÀb¿+ sHR©_¡L¶lÙb>ù9r„ƳjÕ*n޼ɻï¾KXXjµš… 2sæL @tt4C† A©TR¯^=&Nœˆ§§'«W¯F¡P0räHL&þþþXYY1wî\Z·nB¡ÀÇLJåË—Á_|Áˆ#°³³Ã×דÉÄO?ýDûöíQ(T«V¥K—rüøq~øáììì,ý± UÜüAdd¤ù÷}ûöѱcGV®\ @tt4ï¿ÿ>aaaäää0þ|~ýõWzõêÅùóç:t(Ô¬Y“1cÆP¯^=~þùgT*ï¼ó$%%ñÌ3ϘßÃd2qæÌÞÿ}z÷îM“&M,ý1¡… oþý¯¿þbøðá 6Œ£GRPPÀÎ;©W¯_ý5 äææÀòåËùå—_ £zõê¬X±‚Å‹ãââBõêÕ¹ví¿þú+»wïæçŸæÏ?ÿ$$$„   –-[ÆâÅ‹qtt¤zõê\¾|™+V°mÛ¶mA(ÌÌL¾ûî;sXZZlÞ¼µZMtt4ùùùìÚµ †Jpp0 ôë×NÇøñ㉌Œ¤uëÖ9r„~øÍ›7ÊgŸ}F\\AAA¸»»³hÑ"/^Œ ?~œþù‡•+WR­Z5K':¬•À™3g˜4iï¼ó;v4w ­­­K„Jýnee…­­-íÛ·gøðáæûÕj5J¥R„‡ •ÆÐ¡Cyã70ìÝ»—ëׯóöÛoãââHuvðàÁ¼ñƨÕjÞ~ûm"""0`‹-ÂÎÎŽE‹ÄÑ£G>|8›6m¢ÿþ3kÖ,”J%o¿ý6W¯^eÅŠ³hÑ"–,YBnn.õêÕã›o¾A&“ñÊ+¯••ŲeË`ÆŒüõ×_Š«Pn|ðZ­ƒÁÀöíÛÍõÞÖÖ•JÅ{ï½GÿþýÉÎÎfðàÁ;vŒ^½z1{öl|}}Y´hÕªUãàÁƒ¼ûî»üóÏ?´oß­VË’%Kðõõå»ï¾Ãd2qéÒ%Þ{ï=žzê)Fe~/Ax˜¦M›†^¯G§Ó±zõj®]»Æk¯½F£F4h'OždìØ±æäŋٲe AAAæ×°²²â«¯¾¢aƬY³†ðÏ?ÿйsgN:Åþó¢¢¢iÀ|úôéÔ®]›Ÿþ™#F°gÏÚ´iCdd$ÿýï¹víšè° •‹/Æd2QXXȇ~ˆƒƒ:tÀÖÖ–Ý»wsóæMFmÀ1 ,]º___4 ¿ÿþ;¿üò /¾ø"qqq|÷ÝwÄÆÆ H“H?ÿü3ŽŽŽ|öÙg,_¾œM›6Ñ A¶mÛÆ„ HNNVÄV‹»qã}ô}ûöå­·Þ*6ëÙ¢E ÒÓÓ‰‹‹¤ΩS§iö³Y³f¤¤¤Jxx8Íš5ãÈ‘#9r¹\üi…ÊÁÖÖÖ6eÊ Ä+¯¼‚B¡ ((ˆŽ;¢P(°±±ÁÇÇÇz¾k×.¸zõ*»ví"//>l~ý¶mÛâää„­­-ŽŽŽ‚B¡ V­ZFsR³öíÛãàà€½½=öööÔ¬Y“5j`eee~¬ < vvv¸¸¸píÚ5¦M›Æ{ï½ÇsÏ=g>7‡„„˜£ìííñôôD§Ó°{÷nêׯÏÙ³gÙ½{7Z­777Ž?n~ý¾}ûR»vm¸|ù2o½õiii 4È|» ç¹çž£V­ZØÛÛ#—Ëñ÷÷gåÊ•¬[·µZÍ?þH=ÌoÕª®®®XYYáêꊫ«+Mš41·Id2Y±¤¬O21ÃjAz½žÅ‹süøqjÕªÅĉÍ÷½òÊ+´lÙ’¦M›2bÄž~úi._¾Lll,5kÖD&“ñÚk¯±dɆ Fß¾}¹pá7ndþüùÅÖ¦ ‚¥ÅÅÅ1~üxÂÃÃ:th±ûlmmï8£™––F~~>{÷îåòåËæÛ iÙ²¥9Ú 4 sш*ŠÉdâÚµk|üñÇ<õÔSÅ–n€Ô¡½Ó hrr2*•ŠmÛ¶ë  ¼½½Í ó¢|‘˜˜ÆÏòåË™?>_}õ•Èè.<&“‰³gÏ2iÒ$† B—.]îùx??¿KŠlmm̓–÷cgg'á‹0¬\¹’•+WòË/¿P»ví{>þöó²Ë—/gùòå̘1Fƒ¿¿?Ó¦M3ç2m’'®f$“Éèܹ3®®®%î+qŸ>}:³fÍbË–-tëÖ^½z‘——‡R©ÄÉɉ%K–°téR~ûí7˜7o:t >>ž÷ßßüÚ …‚3f€ ƒ 2‡¼þúëæMFDo/———cÇŽÅßßßÒ›P}ñŨT*&NœxÇú~'žžžx{{3xð`Þ~ûmóíÇÇÍÍí;‚` †Ï>û ggg>úè#sþ€ûñññÁÓÓ“?þ˜^xÁ|{DD¾¾¾æ†û¿ð]»veĈ¸ººòý÷ßóâ‹/Ò²eKK Âc(99™qãÆÑ¹sg† vßΤÈ!TU‘‘‘üøãŒ;–V­ZÝ·.ßþ]ÈÉÉ!33“Ï?ÿ½^ÏÙ³g™2e 3gÎdáÂ…–>´*GtX-H¡PÐ¥K—»ŽN^¸piÓ¦ñõ×_ãêêŠJ¥â•W^¡K—.æÐáÆóÍ7ß ÕjÍëZjÖ¬IÍš5ͯeeeŇ~hþ]©TÒ»woóï·ÿ Y³f4kÖÌü»»»;¯¿þº¥?2¡ŠÑëõÌž=›C‡ñÝwß‘““c^_]½zõû>ÿé§ŸféÒ¥´hÑŽ=Ê'Ÿ|Â×_-Öt•–N§cêÔ©œ?žéÓ§“™™Iff&@±óòÝôêÕ‹ ШQ#ÜÜÜ8pà_}õÓ§O7¯}ú·¢H…°gÏ&MšÄÒ¥KK$Þ„òP«ÕŒ;–‚‚^{í5RRRÌÉkÕªH³Rz½^lW&Ti×®]cøðátîÜ™6mÚpýúuœœœÌaìƒNwǰ݌Œ Þ|óMfÍšE—.]ÆÝݽDÖaáÁˆk%æééI~~>o½õáááœ9s†ÜÜ\ú÷ï_lvÉÚÚkkkKWJÈÍÍeëÖ­¤¤¤ðÉ'Ÿ»oóæÍ÷}þ믿ξ}ûxíµ×ðõõ%::š®]»Ò©S'ö.TZYYYìØ±ƒÄÄDÆŒSì¾}ûöÝ÷ùC‡eèС¼ôÒKxzzÅK/½D›6mÌß»qppàÃ?ä…^`ûöí¼úê«–þ8„ÇHrr2{÷îÅd2ñÖ[o™owvvæÐ¡C’••ÅçŸ΄ ,]\A(³óçÏsîÜ94 {öì1ßþÌ3Ï0uêTùóÏ?™|˜ãÇóÖ[o•HÞSÖ:ž’’Â(((¨àOR¨¬ŠÖÜ^»v­B;y:Ž5kÖ`eeEß¾}ï8Ò{û,µ\.Ç`0 ÓéîùºW®\áØ±cbPF(fÏž=$''Wè{æçç3þ|:tèpǵme9›L&.]ºtßÁIáÉ’ŸŸÏÞ½{ÉÏϯ°÷4™Lddd°téR^yå•;®».K×ëõ=z´Â¿¯BåOddä}Û÷S¡Öõë×sêÔ):tè@TTÉÉÉh4Ξ=K^^Þ]ŸgccsÏ×õðð wïÞU&QŠðèYYYÑ®]» _“˜””Ä?þH·nÝHKKãüùó€”I5..î®éÞïWÇèÛ·o•ßÚAxxìììèÕ«õëׯÐå§OŸfõêÕôèу7npýúu@ !KII¹ãs Å}CQ›6mJ·nݪ\x–ðhõïߟ    }ϵk×röìYÚµkÇ•+WHNNF­V—«­"“ÉhÞ¼y•Jî"ÿüs~ûí7,X@óæÍyþùçź=¡Ê `ôèÑXYY!“Éhß¾=Z­–uëÖ¡ÕjéÞ½;/¿üò™†_x<´jÕ 777óï666Lœ8ÑÜV©Y³&_|ñÅcµÏ°ðdyöÙg‹%‰¬^½:'Nä·ß~ãäÉ“´hÑB´U‹²hÍkܸ17.v[PPcÇŽE­Vcmm]"˪ T% …‚áÇ›—Ëå4nܘÐÐPt:vvvb_D¡Jóóó+VÇ Ý»w§mÛ¶FìííEgU¨Òš4iB“&MŠÝV½zuƇZ­ÆÆÆæ¾‰ó¡2ëÙ³g±ßår9Mš4¡N:èt:ìííEgU°¨JYû¬­­ËMJ*3;;;ììì,] Ax$d2–.† /^ÄÛÛÛÒÇ'‚ ‚ ‚ TQeNºäááA·nÝX¸p!äää Óé¸páË–-C§ÓѺukKŸ ‚ ‚ ‚PE•¹ÃjkkËСCQ*•,[¶ŒèèhŽ;Fݺu™2e ÁÁÁ–>>AAA¡Š*s‡5##ƒÅ‹óôÓOӿ󬶶¶xxxàééiécAAAª°2wXÕj5»wï&((ˆ—_~™ÀÀ@K‹ ‚ ‚ ‚ð)s‡ÕÓÓ“×^{õë×ãîîN­ZµJ<ÆßßkkkK£ ‚ ‚ ‚P•¹ÃšŸŸÏ¹s爉‰aäÈ‘xyy•xÌ/¿ürÇŽ¬ ‚ ‚ ‚ ÜO™;¬ŽŽŽ¼þúëôë×ï®ñõõµôñ ‚ ‚ ‚ UT™;¬ÖÖÖ4hÐÀü{~~>YYY÷]Ëj2™8þ¼÷Þ{–.ºð„*s‡U§Ó±zõj–/_NûöíùðÑÉd$$$°aÃ>ÿüs¾ÿþ{¼½½ÍϹqã;wîä“O>¡S§N2yòd6nÜHÓ¦M‰gÛ¶m¼÷Þ{ôíÛ—¨¨(†ÎÑ£GéÑ£‡¥?+Ax 6l ^½z|ñŸ¸¸ð×_1oÞ<®_¿NTTçÏŸgæÌ™Ô­[—7òã?ò /`é¢ Â}°~ýz^~ùe À’%Kذa:t`ݺuFfÏžƒƒsæÌá·ß~£E‹Å¢i¡²Š‰‰a÷îÝ|úé§têÔ‰‚‚¾üòK6mÚDÓ¦M‰‹‹cÇŽŒ5Šgžy†K—.ñßÿþ—îݻӭ[7K_î+22’ŒŒ &OžLÓ¦MIJJbĈìÝ»—ÁƒsàÀ.^¼È¬Y³ eýúõÌ;—þýûãïïoéâ O 2Çh¥¥¥±eËFÅ×_m>Q¿ñÆÌ›7ôôtöíÛWì9Z­–ÐÐPžzê)lllpss£zõê$%%¡Óé8qâ¾¾¾têÔ ¥RIíÚµiÛ¶-û÷ï·ôç$T!ƒÁ`±÷·²²âå—_ÆÃÃ+++‚ƒƒQ($''Axx8uêÔA©TÒ¡Cüýý9r䈥?6á!Q«ÕÄÇÇ“™™ùP_7))‰Ë—/IDDW®\A«ÕVøñF<==yî¹çpppÀÁÁrrrÈÊÊ"""‚¾}ûâåå…ƒƒÏ=÷™™™\½zµÂË*e¡Õj £GX[[ãææFPP¹­rüøqèØ±#J¥’ÐÐPÚ´iÃ,]tAx ………tíÚ•-Z P(ðööÆËË‹›7oAÛ¶m A©TÒ©S'|||ˆˆˆ°tÑ…'T¹fX hÓ¦M‰ûœ©W¯ñññÅn¯[·.S¦LÁh4’››KBB§N¢uëÖØÙÙqýúupuu@©TR«V-víÚuϲèõzrrrðööñõ˜^¯G§Ó!“ÉÌë.U*Z­½^o^ÿ`4Ñh4dff’Kú™3äWrr̯U½zu z½žŒŒ L&^^^¸»»“——‡V«%%%üýýqqq!33“ŒŒ T*•¹ž¤¦¦rãÆ Ôj52™ ƒÁ€\.§Aƒ8::Ò¶mÛ ýŒÆ ………äää°wï^ìíí©W¯sæÌ)¶NÄÝÝjÕªuÏ×Ôétdggãää$êøCb2™ÐjµFómFƒN§ÃÆÆ :½^o)znzz:©©©dee‘‘‘Áµk×HNNF.—£Ñhprr" €¤¤$²³³±³³#((T*×®]#??OOOjÖ¬‰££#yyy¤§§#“É0™LÄÄÄ “ÉðõõE¥RáììLjj*)))Ýñ<ü¨8;;3uêTìííÉËË#55•½{÷R·n]|||ˆŽŽ¦zõêæÇרQ­VKRRÒ=_·°°ÜÜ\œœœŠ-%žlÙÙÙ>0S¿~}&Mš„Á`0·UΜ9C›6m°³³ãÚµk8::š—*Y[[|ßkaa!888Xìó*½^Ovv6z½¾Bß·gÏžæöWVVÑÑÑ$$$ðꫯE·nÝÌë²=<<ððð¸çÀ£Ñh$//Fƒå>T¡RQ«Õäææb2™Êõ:eî°ZYYaggÇ™3gJ„2põêUš6mZìv¥R‰R©$++‹ï¿ÿž¿ÿþOOOzôèR©D«Õ"—ËÍ r¹\Ž 9·urî$//“'Ohnð ec0¸téiiiF233Í'Ò¤¤$’’’Édäçç›–EŸüü|¼¼¼ÈÍÍÅÑѵZMt4íΟ§WûöÄ?õ~Íš{¯¬¬,ªU«†½½=vvv$''“ššŠ££#îîî4jÔˆüü|bcc¹|ù2AAAKnÆ€¨Y³¦¹#ǶmÛ8uêÍn{ÏŠàääÀ¶mÛøé§ŸHHHàý÷ßÇÃÃFƒB¡07È‹¾¹¹¹÷|Íôôt"## k¤ÊÁh4rùòe¶oߎJ¥"..N‡½½=®®®äåå¡R©©!áì쌭­-ùùùhµZ4 ¾¾¾FÒÒÒðòòÂÉÉ hÞ¼9!!!T«V ½^Orr2jµ…BÉd"55•ììllmm0`NNNddd˜˜X¢Ñbee…¿¿?T«V­Xâ"•JŶmÛ*|v^.—ãììŒZ­æ÷ßç·ß~£°°Ÿ~ú ´Zm±$b¶¶¶èõz ïùº111œ>}š¶mÛŠ$d‚YDD©©©úžEçåÌÌL¾ûî;¶mۆݻwÇÊʪLm“ÉDtt4ÑÑÑ4nÜØ¢Ÿ©PyYá »lmmHHH`ôèÑ\ºt‰ððpš4ipÇ¶Š••Õ=Û*ƒ3gÎP§Nû&`žIIIœ>}šºuë–ëuÊÜ*ððð {÷îÌš5‹ëׯ›×mܸqƒM›6!—Ë騱ãŸëììÌÈ‘#yíµ×X°`Ó§Oç»ï¾»{!ïÓxqss#<<\tVï¢htÃÑÑ;;;d2jµšÌÌLL&NNNØí":?€IDATÛÛ“œœÌôéÓÉÎÎÆ×××Üè6øúúR«V-:¶o‹‹ z£ƒÁ€L&ÃÖÖ{{{ó‰M«ÕbccƒöññX©TP»6õœ©'“Á¹spþ<\¸o¿ ÁÁ”24owÊ&ZXiiàåvvÒmF#ä烣c‰ç1lØ0öíÛ‡½½½E>÷Î;Ó¤IöìÙÚ5k¨W¯Þ]{¿YS___zöìi‘ã¨jL&¹¹¹¤¦¦rúôi”J%uêÔÁÎÎŽµk×rôèQž~úiZµjež!±²²ÂÆÆ¥R‰666æNªÑhÄÊÊ +++är¹ù;tûÿ1@­¥þÐÄÊÊêŽë’ƒƒƒKÜæíí}Ïúq'vvvôéÓƒÁ`‘žµµ5  GüùçŸæzwr{ãþnêׯ×k†ðäêÕ«›7o¶È{»¸¸ðÁ0hÐ æÍ›W®¶ŠL&£Q£F¢³*ãììLÏž=9qâ„EÞßËË‹éÓ§“œœÌÔ©SùùçŸùßÿþw×Çßë<®T*iß¾½è¬>A ééé\½z[[[<<<Ì×hµZ<==iÛ¶-åz¯2·rlmm>|8&“‰M›61gÎ@jDµhÑ‚I“&•h¬ÅÅÅ‘M£FðööÆÛÛ›ÁƒóÆo˜gìâããÑjµX[[›gàÄ~®¥—žžÎ78þ<äååaooOhh(~~~DDDH3 ÿß0÷ðð 66–¾}ûÒ¯_¿;geŽŽ†õë¡KhÙRºM¯‡ˆ ƒjÕ 'Gú÷Ø1hÒîÔß¾T*xñE(:±EDÀŸ¨QR§õß23á§Ÿ¤ç½ò ´k'½×Ô©0`´haéf½.\¸@íÚµquuÅÙÙ™°cÇNœ8‹‹ jµ£Ñˆ\.§°°ÂÂÂ;vb„;3™L$%%qåÊRSS‹Íj@zz:öööÔ¨Q™LÆîÝ»)(( qãÆÌ™3§X2¸»)ÕXF,XÉÉÏ?w(ÑëáÒ%é;s§Qu“ "#ÁÁ6,y¿V  üÿL~EËÌÌäúõë4lØwwwÜÝÝ1b«V­"..ggçb³©YYY(•Js¿ Tv±±±äææÒ°aCs[åÍ7ßäí·ß¦°°Ð’_ÔV) «máA¨Õj®_¿Nrrr‰HÄŠ ×뉊Š2_#ð÷÷ç™gžaÍš5üïÿ»c[E¥R™3à 7“ÉDzz:$%%™#ÏŠhµZ222¸yó& 8::"“ÉÐétèt:@êªT*4 ýû÷/W™Ê5,ïàà`ž)U«Õàì쌳³ó; .¤K—.8;;Ó¬Y3L&ëÖ­ã­·ÞâÀÄÅÅñÑGUäßµJÐjµ=z”­[·ƒ££#AAAtìØ‘zõêáååUbÑ»§§çgò\]]¥$)¹¹wÇèØz÷–ÂoAê°úøÀÓOK3JEë*ßyGꨶm{ë±ÿvÛÆÔfVVСÔ¯wÚúB&“f”žzJú©ñÞ¢…Ô°ÏÊ’:¬©©ðÝwÒíTøßÅÍÍ ~ýõW<==ÍÛÚdddйsg4 üñ»ví"<<œµk×b2™Ä Ì¿FΟ?Ï¢E‹HMM¥[·n¼õÖ[¸¹¹aoo››[©^¯Taá§NÁòåÒlþÛoX)’—“'C­ZRÝT(¤N«‡‡YP¤iSiàäÄ ©#ëë ­[KQ¿ýÙÙwî°¦§KZÞÉi (0/†÷ÞƒmÛ¤ïa'áòõõÅÊÊŠ… òæ›ob2™X¾|9µkצnݺtíÚ•Å‹süøqÜÜÜXµj¡¡¡Ô®]»BË)T*•ŠØØX¢¢¢ÈÎÎF&“ѪU+‚ƒƒÍƒ¥GŽáäɓԨQƒàà`Nœ8Arr2ƒ¸¸8\]]:th…•9$$„ÔÔT~ùåºvíJ~~>‹-¢[·n899Ѽysôz=ëÖ­ãÍ7ßdß¾}$$$йsgKÜÂCV”´h–(==S§N¡R©°··'''|||ÈÈÈ 667nL×®]yûí·ñôô$;;“ÉTìæM›î»Æÿa²¶¶¦~ýúÌ™3‡õë×Ó¼ysn޼Ɇ ÌÒ:ð矲{÷nZµjÅÚµk‘Ë墭RŲuëVÖ­[gNzÇIÅjÕª™'ÝÝÝñóó+õûYß¡}okkKãÆï›è~d¦2¦mÒjµüôÓOüõ×_ôîÝ›>ø™LÆÞ½{ùí·ßHKKcΜ9Ô¨QÃü£ÑÈ‘#GX°`999(•JZ´hÁ°aÃpssC&“qöìYæÎKBBîîî 4ˆ.]ºÜ5n^¯×³qãFÂÃÃËôáVƒ„„RSS9vì¤Zµj<ýôÓ´hÑ'''ó»RIM•Ö”†‡Ã_@ðÖ[·f– ÐéàÿèW•JZÓZÔ¹Öé`Âx÷]¨Y³ä㋪ðÅ‹ÒlkðÜsààÀ¾}ûprrªÐÄK)))ÌŸ?Ÿ³gÏ¢Õj ä7Þ uëÖFvíÚŲeËÈÉÉ!88˜·ß~ûžëš²²²Ø¸q£yÏËÇ‘^¯'&&†œœÒÓÓùûï¿),,dÈ!4kÖ ¥Rùè3ǪÕR=7¤:xàtï.Õ¿k×àôihÔ7–f`·o—f9ä»a2I?·?F©³ûïã2¤5ÞI÷™LÒ{?.ÍúFF ApáºI“ØÒ·/áO=en0=j&“‰Ë—/3oÞ<âââÉdÔ¬Y“Ñ£GãïïN§cùòålÙ²ƒÁ@½zõ5jÔ=ðãââ8vì/¼ðB…ƒð`L& hµZªW¯n¾çää––F`` y`4&&†ãÇÒ ¨ÉdâØ±cœ9sj×®MµjÕÈÎÎæÌ™3$%%áêêJÍš5iÓ¦ íÚµÃÕÕµØL•Ñh$##ƒ­[·òöÛoWØqF:Ä¢E‹ÈÎÎÆÚÚšV­Z1tèP\]]‘Édœ9s†yóæ‘€‡‡ƒ ¢sçÎwm«äææ²eËhÉ?©pƒŒŒ âââ8þ}FCëÖ­+ì8)AV\\{÷îåàÁƒdggãêꊻ»;1114nܘÿüç?x{{›ëdEgâ?uê999åÔ+s‡5!!aÆñÖ[oѯ_¿bÓËñññ¼ûî» 0 ÄÉÙd2‘Mff&ÖÖÖæÑúÛegg“ššjÞòã^ç«ÉdB£ÑpðàAÖ¬YCzz:µjÕ",,ŒöíÛ—È–[jz=üïàí ~(­Ã›4I _9Rj(9"5ž‡ «¸OK“BŒüQšU«¥úüùÒ ÖÝääH³ÄRÙõzö:„ÓÿÏÞW¤¢m<´Z-¾¾¾%ÖC&''“››‹¿¿ÿ}·8xœ;¬F£‘«W¯òË/¿‡··7žžž4jÔˆN:Ýy-uYdgK3’}úÜyæ?+K ÓýßÿJFlÛ&…þ6j={JkO5©^–·|z½jß©Ük§Á‰‰·Ö|èt&Mb§•‡¯°k‘üü|RSSÍÛíØÞÖq/`Óëõøûûßw‹Ñaµ<“Édþ‘Ëå þúë/V­ZEAA¡¡¡ôêÕ‹´´4Ö­[H#çmÛ¶%//£GÒ´iS<==ÉÊÊ"55•-ZЮ];Šuä 999899Ý÷–™™ÉæÍ›yóÍ7+üóÈÎÎ&##›{¶Uжü¸Ña­8ƒƒÁ€ÑhäÚµk\¹r…üü|óýYYY\¹r…¬¬,BBB°²²"66ÖÜÐoРÍ›7§Fx{{?ò-Zbcc9qâÏ?ÿ|…N™™™deeáìì|ÇkHRRyyyÔVÖGËh4¢×ë͉%£¢¢8zô(‡ÆÚÚšFѽ{wÉÈÈ 77777jÕªeñíF‡µÌ!ÁEÛ´k×®ÄI¼Zµj„††’œœ\ây2™ 77·{†ô¹ºº>± :n_ŒéÒ%"##ñññáƒ>(uÑ;ÊË»•¬eÝ:)ñƒ¤°Cooi-h\Ü­Çþú«Y‘<=¥Y­ ¤Ê„)yÓ}¸¸Üê@ 0s&v¶\Á¬­­‹íEùo>>>ÞÁ¨Lôz=çÎcË–-\¼x‘¾}û2mÚ´G3êg0Ha´™™p·Eÿ‡K3žw WïÕKú¹ôS^VV 7›oJá3gàßaW EñÎ*€R‰qâDò6n|øŸÙptt¼kb*…B!Ö¬VRjµšóçÏSPP@íÚµñõõE«ÕràÀ:Daa!DGGc4™4iAAAÿ\êd¦§K}G–Bß )±Qx¸e>˜ví¤õ AÒàÌ/¿”ì° Â0™L¨ÕjòòòŠíéO~~>‘‘‘\¼x777¸qãžžžäååáîîNÛ¶mÍÉV­ZQ¿~}ó¾Òݺu3'Ò*R£F jètÒr NЏ[R³ädؼYJ .%!û7£ñÖã ¸wÔ ÜF¥RñÃ?ššÊK/½dvtt¼ïìÒ½Â\¡" T*YYYœ¾*A§Ó±cÇ~ÿýwúöíËË/¿üpöU¼zUZó©ÓII[œœ¤PÛ¢‘íûp‡„À”)wÞzãQ+Ê R'£,£EÍ›“ýÔS(þ?‹¬`Y Ìš5‹ääd^ýu:wî\¾˜*%H*Z^P­šÔ‰=tHZ£*“ÁÀ%“U”æÍ¥p|­VŠn¸_$ ÜAff&;wîäÈ‘#dffâîî^ì:âããCÍš5yíµ×̳߅……œ8qÂÂÂ<BÑ9U¡9OŸ†Õ«¥óvïÞ·ÖekµR'ÖÞ^ªãŽŽRr½¢Ù÷œ©ƒëà ½æÎR2²6m¤×>}³¥>BùDEE‘’’Âõë×ñõõ¥C‡Èd2f̘Á`à›o¾)Ý–d‚`AF£‘Ó§O³k×.bbb((( ^½ztìØ‘1cÆ<¼eQ2÷Ь¬¬èß¿?¬[·Ž¥K—¢P(0´oßžAƒÝwMÇ“¬( åàÁƒìÙ³£ÑÈ„ ¨_¿~ùcÍ غUÚRcòd©±ðî»÷Þ¢ãNäò»g ~ÔL&((Žeß¾;Æ?€Œ6mp²Àö6‚t"NLL$>>žˆˆŽ;F÷îÝ?~ü}צ?*JÀ¿ßk¯Iõª{w©Žß#|»Be¾6¤u²‚pE#òZ­–cÇŽñûï¿ÈÀ .¶ÕÆÝØÛÛÓ¡C‡Ò½q^,[& d&e¾þä)"§hp3/OZÒ±v­ÉÓ«—”¾~ý⯵fñ0nœÔAõõ•¶/«UKºìØ!-UžXƒ¬¬,"##Ù±ciiiÔ¯_///víÚŪU«pvvF¯×óå—_ŠÎªP©åçç“——‡V«%&&†Í›7“žžN¯^½èß¿?ÕªUË î¢TÖ¢Mbk×®££#vvvôìÙ“ž={’’’‚N§ÃÅÅÅB$ÜÝ®]»X²d 6dèС4mÚôá­ˆŠ’Â ¿þúÖ^¤¥í¬Zš^óæIáÈ[¶”¹Ã*X†ÑhäŸþaÉ’%Ѽys¾ùæÿ½óaÑ餜¢uÁ&¬X!5œ?ø äã;v„fÍn%=êÞ]šå±•JúÞvî\áÛÔU˹sçøçŸˆ')) 777 ÿûßÿ {´É5ÒÓ¥ëŠ]ñeVVÅ×XÇÇK× =à^K2úõƒ?†¿ÿ–öþwh櫯b5r$V"Z뉔••źuë8xð >>>ôíÛ—®]»Ë$}ùòe>LŸ>}Ä$‰P©?žùóçc0°··Çd2ѹsgz÷îýD­.«RuXu:{÷îeÑ¢EÔªU‹–-[R£F ¼¼¼î¹ep‹N§3§Ëÿä“OhÔ¨ÑÃo`8;çŸJÙ~«*++©ÓñÇÒV;B•¡Ñhؾ};«V­bÒ¤IÔ¨Qãឌ““¥me”J)üP¥‚Ÿ~’B|ûôÁƒ!&þùG i¿{{éçâEX¿^zže?4˜9SZ_.\ÿ/77—¸¸8âââ¸víçÏŸG§Óѽ{wúõë‡B¡ÀÖÖgggìÊ;(/Íx>õ”F¿u«¾{{'ÀÚZŠN¨WïÞÛ9Õ©#ey·µ½w”ާ§!EüûZˆüÅQÄÇ[úO!T€äädÒÓÓÉÊÊ"::šƒÂĉ (±„D.—S¯^½‡“R2FCvv6YYY8p€={ö0hÐ Z¶l‰ 666³,ê1Qª«#GŽ$99™3gÎpäÈÖ¯_­­-Ý»w§I“&b„ë>Ö¬YßþÉäÉ“‹e®{¨üý¥ŸªL&“ÏìÛ'm±#T :Ž+VpìØ1¦L™BÍš5~æß ¤í‹ŠÂhml`Äxé%i¿R£QJ^ôöÛP»öÝ_Çd‚ýû¥0EKÏjººBÆðçŸðßÿZ¶,‚ÅiµZ>Ì’%KP(æíÌÚµkGýúõË—lC¯‡“'¥ïMÑþÏ™™RXoÓ¦·Ö—îÛ' žÜ~Mwv–"îG.¿Ýs?>>ÒLëÝ>‹Þ½ÑlÞüh?pÁ¢RRRX¿~=ÄßߥRIõêÕ7n!!!ß’CJëĉüúë¯äååáàà@`` S§N-‘ÍWxp¥^Ã*—ËñóóÃ××—=z ÑhˆŠŠbÿþý¬Y³___6lH½zõ ë þŸZ­fÅŠìÝ»—ï¿ÿ¾ü•6+Kjd;;K¿ÇÅÁW_ÁðáÖ ¨ :t€ºuË–pI¨pÌŸ?Ÿøøx&MštÏTùÌ`Â}oŸÍéÑš4¹Õ –Ë¥p^øÏ¤ÁŽ]—×¥Kå —ïÓGÊ *<±²³³9xð «V­ÂÇLJqãÆQ»vm”JeÉõ¨99RˆnÍšROM•¢ ï=£RÝ —¯UK ™7¤„I]»JÏ5™¤L¾{ö@ëÖÒý+WBÛ¶léI¨â233Ù³gW¯^%..ެ¬,Ú´iÃ?þˆ³³3 …¹\þh¶9„G(--5kÖ°oß>Þ}÷]Z´hB¡@©TŠ—r*sÒ%™L†••VVV4mÚ”¦M›’™™Itt4§NbÑ¢E´k×î‰ß¾h#ö… rúôisˆd™åäHa²»wKkˆÚ¶•B¹þû_iç㔞]¡ 7ªˆÌÌL¾üòKœ™4ôÖì–ðD(º>¨Õj:Äš5kP*•Œ3† Ü9”^£‘fâÿüSZ.1eŠ´„âèQ©#Z³¦4ps{ÇÒd‚]»¤ûjÕ’ÂÏU*iàÓÆFüéÑãÖã‹}Š"²³aÛ6©C+ed2™¸rå _ý5>>>tíÚ•ž={X1‰øá!3™LäååAdd$§N¢~ýú̘1ƒ€€Kï±RækAAyý H6_»v “ÉDß¾}>|8Z­ÖÒÇgq±±±Ìš5 ¥RÉÌ™3q.š-«'¤Fü?Üšyôóƒ¹s¥0`1‚#T°ŒŒ >ùäÚµkÇË/¿\þ½ÁÔj˜1Cúÿ!RïÖMÚf)"BŠ x\×}Ük] ðXIMM5g>MNN¦^½zŒ9’† Þû‰*•4ã9o^ñ­Éúö•²ñîß_²¥¤H¡ô¿ürë6;»{GøúÞZO]´ÝÒý¶B„»HMMå÷ßçĉ >œŽ;ZºH‚Pnñññ|üñÇÔ¨QƒN:ñᇊÈÒG¤ÔV•JÅßÿÍŽ;xã7hÛ¶-ùùù|òÉ'œ={™L†§§'#Gޤí½fBsF£‘£Gòã?Ò©S'XþÎ*HYD;t(¾7ª\.ff‹ÐëõüðÃT¯^”?€Ñ(%AJHfŽ\]¥ ¾GJ³®‹KáÀ‚PEååå±}ûvV¯^M­Zµx饗 Á÷öd[&“ôs{pF†4Pãê*%>º¥òVV^­V ö÷‡Ã‡¥üÒ^ƒ´Zi»šÀ@5Jš„RÐh4œ9s†3fP¯^=¦OŸŽ×“¶ÌÇ`¾Ï ŃEÿ•žÉd"99™¯¿þšvíÚñÖ[o•°þqSX(-[yH3ͥ^½š¹sçÒ½{wÜÜÜøã?ˆŒŒä­·Þ¢víÚlÞ¼™/¾ø‚%K–<±SâGå›o¾áÓO?¥E‹åÁÓ§¥Ñð:u,·7ª ÜÆ`0°nÝ:²³³;vìÃËv׸±4Sôÿçú÷—.òŸ.Í"‰YH¡ŠŠ‹‹còäɸ¹¹1oÞ¼;‡AêtR¶ÞÀ@ipR&“2cö *%£{7o—_J¹ 5’Ö¢–Vz:|ñ|÷X»*”Úõë×Y¸p! Œ;öá´…ªΜ;¥ïm·nRÇ5/¯ôƒGB¥““Ctt47oÞdýúõtìØ‘ÿüç?–.Vå£ÓÁ´iÒdÃÚµå%KÕaMHH`Ó¦M 4ˆÿüç?ØÙÙ™Ó5‡‡‡3hÐ ¨S§Æ ãìÙ³O\‡Õd2‘˜˜Èœ9s;v,Í›7/ß ªT°aƒôóÕW–>ýú«”ت +€ÜÜÀÉ ._†öí-ýQ U€^¯'==Ý»w³aÞ}öYƇû“N®VÃæÍRž8~\ZW^”(Pú€¤œ#aaðê«bÛ¾*äÒ¥KL›6 777üüüxóÍ7i/΋NªÛEËLNž”n›?Rˆt©®`ÉÉÉèt:ºuëfÞó---˜˜Þÿ}óØÕÕ._¾ÌÓO?mé±B™L&æÎKxxxÙ*ra!DFJ3©~~R²‹¨(˜8ñÞ[tB:uêË—/gÒ¤I¥O–‘Ÿ_üvô¨Ôa]¶ìîϱµ•¶©„*$''‡õë׳ÿ~<<<=z4Mš4)™ñ×h„cǤs~` ¼÷ôì)­èØQš¡)m§óùç¥uß&SÙÀÎNj|ët–þ(…JÎh4réÒ%Ö¬YÃÕ«W æ›o¾y4[›UFüþ;œ?/-ch×Nú¹••±ð÷ß°q£5!TzqqqLœ8‘gžy†Áƒ[º8•KA|ÿ=ÄÆJ›J=M›>Ô|#¥ºú©T* ö·í¯vñâEÒÒÒh]–p£ÇˆJ¥"))‰ˆˆ²³³=zté_D§“²7¦¤HûJúùI{Ô}üqñ5«‚`!F£‘ˆˆf̘Á7ß|C­ZµJû0y²ôÿ·Þ’F™qãDBá±Ë—_~Ipp0Ÿ}ö~~~æ$…%dfJçþ)SnÝ"ý@ñ ¾¥áê*…חdzϊëpO ¬ZµŠS§Nѯ_?Þyç<<<Þ2‘ªàÚ5©³:y²•p72™”Ìì­·¤6ŸR)}ÿ…JëâÅ‹Lš4‰W^y…gŸ}ÖÒÅ©rs¥Poï[‘@¯¼"Ͳ%}ÈßÿRuX=<ùäFÉd¢Y³f<ûì³Èår"##ùþûïIJJâ£>ÂÏϯBƶlÙ‚——:t¸ó&ï¥!—‹‹Péäçç3cÆ ž}öYúöí[ö0¯kפm6Š.ð"Ûµð˜Ù½{7³gÏfæÌ™Ô¾=ç@F†”€eàÀ[IņS§`üøÒ%S„J **Šo¾ù†!C†¯ëOЧŸ–Â!Ë“íW§“ˆE‡µRÑëõüüóÏ\¿~)S¦ød¬Ã¾›´4)‰RÏžR¶ø#,RŒR‡…„„°fÍnܸÉd"((È<êàééÉË/¿L‡¨^½ºE¨"]½z•5kÖ˜ÃËL¯‡éÓomç!•„Á``Ù²e„……ñì³Ï–½ž«TÒ¢ü,}H‚ðШÕjNž#<<ÜÒÅ©F£”­°PÚÓ¸h}yyÃ_YúÈ„Ûh4–/_NTT_ýuùv@x= _ /½dé’”¾Ãj4‰‰‰!""‚ÔÔT6lHxx8öööÔ­[—ºuëÞóù&“ ƒÁ€V«ÀÚÚºX‰ÉdB¯×£ÓéP(X[[Wº‘ “É„F£aÓ¦MtëÖ­ø†ïeñçŸpö,¼þº¥MxHŒF#Z­ƒÁ€R©D©Tšë±Éd*vŸ••U¥«ãEå¼xñ"`Ö¬Yå”9uJJùß¶­¥KxHŠÎã&“©D=6h4”J% …¢RÖñò0,_¾œíÛ·Ó¶m[øöÛo .Ú¯47WÚõƒ©££´þçï¿ËžÅWxd‡¶ÊÃf49qâ3fÌ`Ĉ´zÐ=«ºØX˜1CšijÔF*Û6Qÿæçï¼c±Ã*ªÃZ­¹\ŽM±¥>U¥­ò° vîÜÉáÇ™ ([µ´4©Ñ^«I{AŠ$…ÌÌLÖ¬YÃÁƒÉËË£~ýú¼õÖ[„„„ ÑhøçŸX³f ƒV­Z1hРÇnƳgϲmÛ6fÍšUrÐR­–fNCC¥ÙÕ»qs“„…J'>>žÅ‹sîÜ9ŒF#íÛ·gàÀx{{påÊ–/_ÎÅ‹ âõ×_§I“&•¢­ò(èõzþþûo/^Ìÿþ÷¿'§³ ÒZ½GÑF³±‘α±9¬ãdz~ýz.\¸€““Ï<ó }ûöÅÉÉ ½^on«¤¥¥Ñ¨Q#XúªˆÌÌL~ûí7Ξ=ËØ±cË?U•íß/%Äôò‚²ìxòˆ”j™F£aÉ’%„……1oÞ<.\ÈÈ‘#9xð gΜ¹ïósrr˜>}:çÏŸgÈ! 2„Ç3sæL Ðh4Lš4‰ôôtÆŽ‹¿¿?_}õ±ú2ß©ü“'O&''‡÷Þ{É“'ãââR¶ûí7¸zUúӦа¡XÓ÷˜Ø½{7ß}÷mÛ¶å‹/¾ÀÆÆ†iÓ¦qîÜ9bccùâ‹/¨^½:£G&99™¯¾ú ]%ÚçP¥RqâÄ Æ‡½½==ʲ¥†Á m˜~ì˜ô{@€ØGø1¡ÓéX¶lþù'ýû÷gôèѤ§§3uêTâããÙ¿?sæÌ¡G¼ùæ›:tˆ_ý½^oé¢?4ùùùÌŸ?Ÿ·ÞzëÎ µúÖÖ"Ë{•SÔV¹xñ"C‡eÈ!8p€™3g¢R©P«Õ|ñÅdee1vìX¼½½™2e 7oÞ´tÑ:½^O\\Ÿ|ò ÿý7'N¤E‹–.Ö£•™)u"øAʽ`cóè&nÜ Ô›¤¤$&MšD^^ü1Ï<ó ?ÿü3«V­ &&Ƽ-×èÑ£IHH`êÔ©•ª­ò0F.^¼È„ ÈÍÍå›o¾¡N:–.–¥> Ø»æÏ—Bß+™RM fee‘ÍàÁƒiܸ1Ï>û,»víâÒ¥K÷q‹åôéÓÌœ9“FP­Z5†ΨQ£¸rå ÙÙÙ|öÙg„……ѰaC"""صk×­0+ ÑjµÌž=›Ö­[óßÿþ·|£¨Z-œ9#B€SÛ·o§[·n¼ùæ›XYYQ·n]FŒÁîÝ»Q*•¸»»3|øp\\\pqqáý÷ßçäÉ“•b/㬬,fΜɵk×èÓ§Ï?ÿ|Ù’,%%IëóæÏ·ô! YAA»víbÈ!¼ð 4lØÞ½{sñâE6lØ@‹-4h …YÍŸ?Ÿ~ýúUÊH‚²Ø²e îîîtéÒ¥ø‰‰RâúÈ·“'áÐ!h×®B122kkk>úè#iÕªùùù¬_¿ž¡C‡²mÛ6<<<>|8NNN899ñÁpêÔ©Çjv=&&†I“&1räHZ·nýØFH<ädøùgøôSøÿ­K+“RDzZYY›U´³³ÃÉɉÜÜÜû>×ÚÚšöíÛS¿(K"ààà€N§Ãd2qùòe¼¼¼üÿ*š6mÊéÓ§-ý9Att4óæÍ+…6¤Ì÷ ª¬5jжm[s=±±±A&“¡×ë¹rå 64_ôýüü äÌ™3ï°êõz.\ˆ••³fÍÂÍÍ­|ëU^žô5 !¹\N“&Mhw[ËÞÞ½^^¯çâÅ‹Œ;Ö|_£FÐh4ÄÆÆVékÑ1,^¼˜ëׯ3gÎìŠ%ÅÇÃöíÒzŸ‘#¥«PeY[[Ó¡CêÕ«g¾ÍÁÁÁ¼žõÒ¥Køøø˜Û*vvv4iÒ¤R´UFÃÆù믿øä“O¨[·nÙ¶2«J²²ÀÅEºv $%L{Ôk6CB°]±YÏZÛÛÛÓ«W/üÿïg™L†yõÂ… 4nÜØ|Ž Àßߟ³gÏ>6V•JÅÂ… éÕ«mÚ´y<ëwn®4sêâ"ý{¯þ‹‡‡”°’&ͭпNXX“&M27äsrrX¹r%Í›7ÇÑÑ‘äädlllÌy¥RI@@7nܸçëj4’’’YÈ™V«eñâżúê«÷ßþAØÙÁË/—~Ï.áFÒÒÒHKKÃTÁ MÆŒCxx82™ “ÉÄ?ÿüCRR­[·&11óºgWWWÜÜÜîö^XXHBBÂ# Ç9xð /^äwÞÁÝݽ|Õ€è×ïá$¦îÈ`0””DNNN…Öqggg&Ožlnè¨ÕjV®\‰¯¯/5jÔ )) óãýýýÑét¤§§ßóu³²²HNNÆh4Z潇üü|¦NÊG}DXX³gÏÆÓÓóÖΜ¼<˜:UZâ!<4ñññVpxZ½zõøâ‹/Ìm•ììlV­ZE‹-ppp 99[[[s{@©Tâïïß¶Jff&™™™ùKkõêÕ¬ZµŠiÓ¦Q¿~ýdz1»¤$øö[ÐhÀÉIJŠV †t^^¤Ô©SáK&žzê)†jþ»&&&²iÓ&:wî @BBB‰¶Š‹‹ qqqw}M£ÑHJJ z,e¡×ëY¹r%:Ž—_~ùñ¬ßW®ÀGI3øYY°p¡T¿ïÆÆFšY}Èõ>//ï¡\ÛKÝš4™L¤¥¥™OÌùùùh4rrrJœ¬ýüüîNXPPÀñãÇͳ9ü1NNNw}Ïû}‘U*W¯^%,,ì¡o\­ÑhX¼x15kÖ4‘ËD­–6ŠÏÈ:¬bvõ‘2™LÄÅÅGPPEÊÅŸþÉîÝ»4hÐ=Óÿ߯ŽçææråÊ\\\Ê¿ßï\¾|™Y³fñÍ7ßoˆ?(£QZ“—'­Ù«][NÇÕ«WIMM­ðA™¢÷¿xñ¢y¿ºO?ýô®K7ŒF#ƒáž¯—œœLLLLÙêß#tìØ1fÏžMûöí9rä­ÁRR¤„b={J[’‰AȇîÒ¥Kdgg[ä½ 8vì .ÄÆÆ†?þøž!±÷:›L&INN®Ô ÈòòòX¶l§OŸæÛo¿5Ï"?ÖŒFX·Nš…²µ­Ð·VÛÙq¼zu¨ËÊÊbÛ¶m¬^½šzõê1lذ{>þ^uÜ`0pýúuóÀNe¥ÑhØ¿¿9ßÈC™ˆªlÒÒ`Ú4xåèÔIš<ÐëáÇ¥,×·'ÉML”BÇŒy$í¶ÌÌL®]»VîµÁ¥îÝ©T*æÎ‹íÿ©M&ÉÉÉ\¿~ˆˆˆb3g5þ­R©øöÛo9zô(Ï=÷}ûö5Ôߣ£ã=ïwuu%<<ü‘|AþüóOΟ?ϤI“ÌÇ\&§OKë"ÒÓáÕWE‡õS(4oÞœüüü‡>ˆq?ƒðÃ?àããÃ7ß|CýúõïJ~¿ºëããC×®]Iy¯]»ÆäÉ“éÓ§OÙ3šLÒhÞ¾}Ҡ̤I¢ÃúˆÙÚÚÒ±cG²²²*|tX§Óñû￳jÕ*Ú·oÏ{ï½Ghhè]#¬¬¬î{þ¬[·n¥ÛÓ1""‚Ù³góòË/Ó§OŸ[ßa“ þùGÚ®é³ÏD$Á#Ô£G6oÞ\áï[XXÈ´iÓ8vìýúõ£oß¾øùùÝó9÷j«Èd24hP,̸²Ñjµ|ûí·deeñÍ7ß‹”¨ ©óYÚA]µ.\¶ï¨àm[œœéÖ³''Nœ¨Ð÷¸qã3fÌ >>žÒ«W/œïùœ{µU”J%ááá÷ýžX’Z­föìÙœ:uŠñãÇ›w(yì89I;3Ô¨qk uð`6Lj«ý!@j· l‡êÕ«Ó®];rrrÊõ:¥ºÊ:::òꫯ>pHË¿gM³³³™ï¾ûnåî¬J…–2Ð×®}kc£QŠzxûmÐé`ùrhÛVša²±‘&vî„={¤mµjÒõJ£‘êœH0ÚÚâVk›M&»wïF&“1xð`L&“¹ŽËårìííiÕª+V¬ 77www®_¿NRRR•í°F~ûí7ùðÃ+¿ƒAŠÜ “¢Ù.^„ï¿—þ5kv÷çÙØHߟü|)ÁÆFÚkÕ˫ҷßÊÔ6 œ;wŽýû÷sæÌ222ptt¤FtêÔ‰ððð;†Æ\ºt‰ôôtú÷ï_â¾Ý»wS¿~}ÚµkÇ”)SèÞ½;'Nœ $$„öíÛWø³}ûvúõëWöFÖ‰°x±T„'FZZÑÑÑDFF²lÙ²b÷½ýöÛ 6Œþù‡?þ˜† ²{÷nºwï^á#óz½ž­[·òÞ{ï•}]Á±cÒ…ÿ>!ýÂã%66–ÄÄD>úè£÷ýøã¼òÊ+|úé§|üñǸºº²ÿ~† †···¥‹þ@ŒF#Ë—/'''‡‰'„U©¤Ù˜à`éGx,]ºt‰ÔÔTúõëWâ¾}ûöÑ AÂÃÙ2e ]»våøñㄆ†Ò¶m[K½ÔÔj5Ÿþ9®®®¼÷Þ{$GÂC'—KFŸO?-e£OH–Zµn-5¼Ã¤Œ§ÕªIÉÐ )äÑÓ,’ѨTRcýƒ A‹NaÍšä'&VØûi4Î;ǹsçJì³îííÍþýûéÖ­ÿüó&L AƒìÚµ‹§žzÊâ[L–ÕåË—9~ü8³gÏ®úU~ùEêg|óÔa-(êôƒ´çŒFX´H긎ùè·nzHJÝaU«Õ¬Y³†åË—SPP@Æ iÚ´)*•ŠS§N±{÷nÚ¶mË'Ÿ|‚««k±‘é=zÛÒævÕªU`äÈ‘ìÝ»—Ó§OÓ³gOºvíZá çÏŸçý÷ß/û‹ØÛÄ •r/#áÑqvvfîܹwLLàíí««+_|ñ[·nåæÍ›¼ûî»IŸ‘‘A^^ÕË“¾|èP©ž O”Úµk³|ùò;ÞW«V-\\\˜:u*[·n57†-ò^VW¯^eÇŽLœ8±xã=%¦O—B§*ñ:D¡üzõêeÞ+þߊÚ#|ð{öìáìÙ³ôîÝ›.]º”mé%•”ÉdŒ9²òvV ¥Ù¤£G¥¤7ÞBŸ{NšMðñ‘’ÆCx¸´N/9YšER( kWiÖµ(cùÏ?K | GÖ¨ÁÍŒ ZVÐû)•J†ÎË/¿\⾢Μ››“&M⯿þ">>ž÷ß¿Êng“››ËôéÓ6lX¥KêW&GJŸ. À€´gðƒR(àµ×¤5®ü!%fªJÝaÝ¿?³gÏæ…^àÍ7ßÄÇÇÇÜ)U«ÕlذE‹ñý÷ß3a„b3­~~~÷]ŒíââÂsÏ=ÇsÏ=g±åòåËèõúòe´ºKÇ\x¼ÙÚÚÒ¤I“{>ÆÇÇÇâ›ËïØ±ƒ–-[šŠJ¥°Pá«b3áápqq¡Å}ö aÔ¨Q–.j©%%%1yòd†ZüüŸœ,­W Õ'Àƒ´U\]]éß¿ÿ#ƪ£ÑÈâÅ‹¹páS§N½o²‹ºx¶l&M Ké6++0àÖc”ÊâÉ–d2i}ë¿Ãömm¥mײ³¥h‰!CY²™ÊJ¡PÜ7ªK&“áããÃ!C,]Ür[¹r%tïÞÝÒE)óç¥YІ ‹ßÞ¦ô]¸Çî*÷åå%uxo[ÒSÙ•jÑZNNË–-£{÷î¼ûî»øúú›Aµµµå¥—^büøñìܹ“›7oZúøJÍd2IÓ¦MK?Úh0Àï¿Cd¤¥C €;wòÌ3Ï”þÉz½æ~ô¨¥CªÂÂB¦NJÇŽ騱cñ;år)!Jy¢n¡’0 ìÝ»—½{÷2fÌ\\\,]¤{kÒ¾üRÚ¿þß3dùùÒþ’+W–î5]]¥(¡'¬³ú$ÑétlÙ²…]»vUþŽ·Á íü÷ßRò0­Vtùúk)º¤A–ôti`¦<Õ".(RuXãããÉÉÉ¡gÏžwÝ7U¡Pкuk¼½½KlsS¨ÕjNœ8Q¶$8×®Á† ÒÚ A¨¤ÎŸ?­­mÙÖ¢;&eHmÝÚÒ‡!J¥bñâÅØÛÛóꫯÞJ@–œ,5¼¼ wï ߣQ…}ûö1kÖ,¦NZ¹×$ffÂîÝÒlêÝ&’’¤õ|eIŽYɳ¢ å³yóf.\È”)Sʽè#—--#Ü·O wW(¤HÍÚµaÓ&i²`Æ éþ'T©¾­™™™èõúûfÍU(8;;“••eéã+µœœÔjuÙ2:$mëQÙG+…'ÚáÇ˖Äh”:«£FI£Ó‚ðP«Õ̘1ƒ´´4¦Nzkù«W¥¤-ß_rVGª ½^ÏáÇ™?>Ÿ}öYåî¬ðçŸRÈâ½ö ¯UKúžŠATáÿ Ž;Ɔ Ì» T*ii°q£ùì³Ò–€®®RŽ'§â³þï¿/uV÷î•fWûô±té-¦TVärù};¢F£•JuÏM´+«Ë—/ãååU¶DO}úH‹û¡;vìŸ|òIéŸX”™QE{‚§¤¤0qâÄ[UæÎ…víÄZmá±qäȾÿþ{&OžLãÆ-]œâòò`Û6é:ó R¨od¤4@z/r9ü+Ó­ðd;sæ óçÏç£>ºk¢W‹Š‰‘:­£FÝ ÉU(Àãäc==¥u¬gÏÂ[o=Ñ}ŒRuXCBBpvvfãÆÔ¯_;;»;>îܹs\¿~ý¾‰9*£Ý»wÓ©S§{î'[‚Á ŠQx¡’[»v-¾¾¾„…™4hð`ÛsÄÇKøš5-}‚PnÙÙÙ9r„uëÖáææÆ·ß~‹ííá¾о=ôëgÑýáa0™Lœ:uŠY³f1eÊþ;‰‹% ÒuÅÁAÚzææMiYUjª4“ôúëÒšU±×±ð€ŒF#‡fÙ²e|òÉ'Ô®,u§hÏT¹š6…-¤™ìÁö>•ɤA™J¾Oê£Vª«““}ûöeæÌ™„††ò /`ccƒL&Ãd2a49wî3gΤC‡¾·dyݼy“‹/2f̘RÑÈǾ}ðî»w_g!–’’Âúõëùì³ÏPÊdÒhvõêR¾×‰0/¾øBÚB@tX…*Ìd2qóæM¾üòKìííyíµ×hÞ¼yñÎ*HáY/¼`éâ ÂC‘ššÊìÙ³ùïÿ{×íz*TN|û-\¿.µ›Ú·—²o׫' ŒæçKÙª–ÕU°¨èèh-ZÄèÑ£-\Ô®ŠŠ’¶OŠŽ–öI©ãZZeyÎc¦Ô+Î_xárrr˜;w.«W¯¦yóæØÙÙa0¸qãÇŽ£yóæŒ7®ògž»Édbç΄‡‡?x¹ )[êwßI›O‹üB%¶qãFêÔ©CXX˜”¨"'~û ÆŽ•ö°»ƒ~úIJ$Ö³§¥AÊE«Õ2sæLžyæžþù;?èàAiû//KWÊ-//É“'Ó®];:tè`éâH΃  ˜8±dˆ£R)Âð…R+((`ÆŒ¼þúë– w×ëáÌéÿÍ›KƒŸƒK“–þ˜ª´R÷°lll«X¨²*ÓÙËÎÎŽ:Üu´N­Vó÷ßÓ¾}û»nSÙœ:u ½^Ohh(¨Õðé§Ršé¯¿–ö»ã§g/½dé¢ Â= ~ýõW:wî|käÑÅEú¹rE:ÉÞIv¶4:X“B)ååå±páB|ç¤z&lÝ*­-ù„ÇÀßÿ͹sçøöÛoq°ÔìŽR) ú_¼(5ä?úH o!ŽÂC’ÍêÕ«™þøcÖ¬YS%:¬Z­–U«Vñúë¯KY"##¥†z‡pøpÉ«Z «WKûò‰‘¡’‹‹‹ãèÑ£|ÿý÷Ò ))PX(­GíÙ4š’OŠŽ–BÝ,°tñ¡ÜL&{öìÁÖÖöÞa‘M›J3A‚P…™L&öïßÏÚµk™4in:Ķ vìþ}õÕâ‰Ê\]ÅÀ¾ðÈ$''³`Ázöì)-wzŒFi?%EÚFÉÚZÔ,Úâ¯h€³F éGx$É—Éd¢°°£Ñhéã{ .\ --N:I7Ha={Bݺ%ŸpêìÙóD§—ªŽmÛ¶Ñ´iÓ[aú{öÀºuÒÿïœJ}Õª;×}A¨‚òóóYºt)/¿ü2Öw m—É U+i­‘ TaÑÑÑ|÷ÝwŒ1‚àà`d{¹’Ñ(­Õ)$ò‹/¤Ù¦víJfÕ¾qCÊú+QJJ K–,áÝwßE­VóÆo<š÷ÂB˜=Æ“ÚM*•t{ûöRÉ×W䯩 Oü§l0Xµj=oO(S4¯TJ£)·3aË4œ-]|A¸§øøxöîÝËwß}wëd~øð­ ¨F£”8,$¤xÇU­†ÿüÇÒÅ„r+,,äÛo¿¥W¯^wßj-+KÚ¯Y3KWÊÌ`0°gÏæÏŸÏ¸qãhÓ¦ÍÃ}µ.\€åË¡aCxã ©±Þ­„‡CB‚Ôq½½=µt)tíz«]%å¤Óéøúë¯qqqaÖ¬YT«V ›‡=”“#ýëè-[J“Xþþb¢Ê‚žøE[¶l!##ƒ>}úܺQ©¼• @§»5¢RŒúo@§N"É’P© Ö®]KÛ¶m ºuGHÈ­ÙS“I å:q¢ø“§L¹{"&A¨B¶lÙB||<¯¿þúÝGà7n”Ö$ Be0ذaK–,áý÷ß§S§N(öÂqq0w®´ÝÌK/I³©r9ôê%åDÈΆݻ‹?'3SJJ#ɱcÇP©TŒ3ÿ‡ßYiÛ¿={¤:Þ¶­´_½è¬ZT©fXF#yyy †{>.;;ÛÒÇõ@öîÝËÒ¥KY´hÑ­$sçJQŸ}VúýÏ?¥“ðСRè‹BuêXºè#H,¼•P6‰‰‰=z”ï¾û®ø#FÜ ÛR( Ai–õ©§¤tìµk‹ôëÂc!&&†?ÿü“Ï?ÿ;;»;?(/OjœL™béâ B™-]º”;w2{öì;'+‹¤$X¼ºt‘fPkÕ’ÚHÖÖw° „ÄÄâ·Õ¨!ma#Aff& ,`Ĉ8?ª(Gƒ._–"„J£TÖ7nðã?’‘‘qÏÇiµZK×}¥§§³páBÞyç['wŽ/¿¼õÀà`X±BZ¯±|¹´eÛ¶–.~Å(®R¹;¬—þ¿|O|p{q&“‰íÛ·Ó¸qc|ŠfJõzéDüïÆFÆ`g'OJ[zLŸnéâ B¹i4fÏžÍË/¿,e¿“IÊêlé" B©™L&Ž9ÂŽ;øê«¯pww/ýšU“Iú1nÍš^¿.í–P¿þ­¥Q EÉ5ª·óô„¢­‹¼óŽØMxhŽ9‚««+Mî¶{ÇÕmNj뤥IÒ)ÉÞ¿¿/ $'ß9¿‡`1¥jæ[YYáíí­­í}[³fÍG7úQN†9sæÐ£Gžzê©[w$$H#„·7\üü¤“ðްs'¼öš¥‹_q²ãÀÓ–.È=ì‚Ö¹yó&;vì`öìÙ·Â 7lNÒ\ü"­Ó1BÚ;ÌÕÕÒÅ„r;qâéééôíÛWÚ{ønœ¡GKWÊäСC̘1ƒiÓ¦Qëß97ÔùóðË/Òg~;Jß‹I“¤ˆ›ek+%£¹ÝÝ"¡ŒF#7nÜà—_~aÊ”)Ô1Û°AJ$ùúëÒZT½^ ÷Ý´ ¾úªä€Š½=Ì›géCþ¥TÍü   >þøcK—¹Ü¢££¹|ù2ï¾ûnñ;||¤4Õ·óò’Fù† {²bØ3t@ TÆR ¼ˆV3£ÑÈ?ÿüC£Fð.Ú¢Ã`€]»à•WîÊeoãÇC£F–.¾ ”›ÑhdÇŽ¼ôÒKw_Ç——›7C¿~bP%ý_{çŹ6à{—Ž€"‚€¨¨`Á^±÷kª)¶4Oz×4ã19‰æ˜âIùrÒsbªI4Ñ$öÞcA±!`¥Jï,Ë–ù~<îÂÊ‚4ÌÜ×Å•83;óîÎ;ï<ý),,äóÏ?稚²ª×Kå^//°´¼ùf‰¶±´ÀiÖLþª>(ñкºJÔNjªä¸ª¨T³ÙLDD«V­ââÅ‹Œ7ŽUMËÛ´ î»Or¯A*ûÞ¿D”© „*)¬ÙÙÙœ¯¿þ:îîîtïÞ½ü„…ÁÛoK}•H\\ÙÙÙtéÒ¥üƒE 3_~ §Nɶñã%ÏûYz»u“wÉ$UVÃÂêú§Ri $$$°sçN¦L™Rq‚ŠØ»WŠ,ÙãÌqT]ÉÅ‹%…ÆTê ufZÎÊÊâÛo¿eæÌ™4)Uä%55•7rìØ1Z·nÍäÉ“ ªþd-Ell,...t³—§'Þ'?¿ºúIê‹ ¢tºW:àèëzpÀ%à0ùŠñuÚÔõàìc2™X±b:t ÷åгÙL||<¿þú+—.]¢{÷îŒ=ßZœ<ˆ;w.Ù¸c‡X y¤â **UÄh4òé§Ÿ2aÂÚ´icÝvêÔ)~ûí7L&ýúõcĈÕ·Ž_³ÙÌêÕ«éÔ©3fÌÀÃÃþwÕl–ÜUÕ€£R)222øþûï™5k7¶nOMMeýúõœ8q‚àà`&OžL‹-jEV¹f³™U«VqÓM7ÙŒ €œÉÉvr‚Ï?—¾¨áá×ÏÓéï< ïš>}®Ï5UjÄÑ£G9vì³fͲn3›ÍÄÅűjÕ*RSSéÑ££G¾>é€ÉÉœLäÎtéÒ¥ú×4aùrxùeûû¤uå¤Iò¼XèÛWªc«Ô+®ýÊj£ÑÈêÕ«Ù±cz½­6´xñbV­ZEhh(ÇgÑ¢E¤§§×Êu7oÞÌ Aƒì÷ãsq‘^«×|¦SÀ•ÝŠú]ªq®kA*pøŠmÑH8ð:ÄÓZψ‰‰áûï¿'­”u/##ƒçŸžèèhÚµkÇ/¿ü»ï¾[k×Ü´icÆŒ±šví‚Ö­UeU¥V1›ÍìÞ½›?ÿü“ÜÜ’ð‡ãÇóÒK/¡×ëñööæƒ>`ÕªU×lEEEûŒˆˆœKùL&ß~û-mÛ¶eÑ¢EhµZüýýùé§Ÿ:th™5¿6øùçŸiß¾=m+ÓGuÓ&)´¤¶nR¹ 7ndùòåDGG[£,ìÛ·Ó§O³dÉzõêÅÔ©S™9s&[¶laúôé×lLGåèÑ£lß¾½¬wõ?ÿ³gáÅ¥=ÔMõkƒAÂ,[¶”4«þSž9•zǧŸ~ÊÆ‰eĈ6ûþøã ¯¾ú*Íš5£K—.¼ð œ8q¢â0ôšÒº5üßÿ±óÐ!.éttíÜYò­ûõ“óªàê*­lJ{O¯äÑGmSC ¤Òµš.R晴‡ÕÑÑ­VKjj*111ÄÄćÑh$66ÖºÍòw¥÷ C‡<òÈ#Lœ8±Ì¾˜˜üýý E£ÑàååE¯^½8zôh¿èÑ£G ÆÛ^Þ†Ñh?ñúïÄI ¿Ô¿]pÛDY¬k2€ýH¡% Í€ŽHÖº` ^^^L™2…G}´L¨ï©S§èÞ½;ÞÞÞh4Ú¶mKPPÇj!Áÿ·ß~cذaøûûÛîxâ ÓRQ©%™9s&³fÍÂ¥T«/³ÙÌéÓ§]îùL&qqqtêÔ //¯Ê ¢¸X”Õóç)œ:•_}Åo¿ýÆ‹/¾HKt·n%EêBF†ô®hI ›ví$<øèÑ¿w´å5 ;;›‹/âiéù\Mª¤°¶iÓ†%K–`¨d,y```­|Ùâ«Tî-..&%%Ŧzqi ‰‹‹+¿Ùpr²*ԟƶ}M2RèȈ䎎»NãPo¯% « Xd#J´å6Ž@Ù¿.ÿ»W©Ó( ™™™dddr-J÷×2W{¦t:ÉÉÉ4oÞÜ®ÂzäÈm ˜‘Ÿ7ÂØ±j™“ÉDJJ yyy×]a­*f³ùª­ÏrrrHKK£E‹W=Ÿ¢(:tˆ?ÿü“7ÞxãêP Utr²ß‡X¥Þ’œœLaa= ¡©€ŠdEQÈÊÊ";;»Ê «n×.GFÒ£W/™Ãå¥6ÕÆ“pÌ–-UëU0 $''—+¿Ö7*’UÌf3iiiètºÊ+¬gΈ2úÚkìiiixÔP­’ÂÚ¨Q#:uêtÝ׫ôŽôòò"<<Ü~1%௿þ¢M›6å+Ð: |Ý¿W½!Š^ºùò¶  · ºŽc1"³²t  %ʨÅÐüL†QÆ ìàà@×®]ÉÌÌÄ¡¼0¯6Ç}}}4hP¹û7oÞ,¥ß‹Šdåðò’¦í6@y‘* ÂÃùtéÒu©LZ¬–úò µVÓ¾GŽaéÒ¥¼ù曕{' ðÁ0{vù8Tê%C† !;;»®‡Q)*ZÇ5 :t }ûöU;iV‹Óô…ph(E!íubP±‹‡‡ƒæðáÃ5?Ùu t È•899Ñ»woš7o^ù†…I!}ú““S£ëT9$XQòóó9pà>>>„„„ðþûïÛänh4œY¼x±MhØÕð÷÷çâÅ‹ШQ#  U:‡½ñnذI“&•¯¸Œ÷÷±Zú™6-µm2,ú¼%×h|yÿ4 ’³‘Îã/o3¿ÿ̈Ç5éòøœÏë6®Ÿ¸´hÑ‚œœŒF#ŽŽŽdgg“••e Í©F£‘sçÎIŠ%$í–[¤àEÏžjÁ •ë†F£! À¦ØXbb"ŽŽŽøÔRÕÅ .ðÖ[o1gÎ:vìX¹™LRFE¥ ))©Ve•òˆ¾x‘?}}ypÂû•¯ë#F£T':TõV5PZ´hAvv¶UVÉÊÊ"''§âþÖU¥ @BÛ==‰‰‰!??Ÿ^½zÙ?6=¾ûNZ&UF¦9{V䟫Øsr‚ Dëªgèt’ ƒI¨ ì×E‘ŒÊ $DœÙÒE1* z÷–(ëڢʧÊÌÌäùçŸgÞ¼yœ={£ÑÈÙ³g­ù¦999\¼x‘‘#G–ívúôéCJJ /^$¶ÿСCôïß¿Ú_0++‹¸¸8úöí[þAòÐ\+tHxm} X(’ÅÔ’~cþ¼|,ˆ‚˜QÙ Ô|$ø"%^Ö$Àð"ýWÀðËû› ×À€8zô(ùùRá*!!¸¸8úÕ Šott4ÞÞÞfväˆä99ÁâÅâQªçÞ7•­VK¿~ýسguÛÑ£Gqss«\žéU0›Í|÷ÝwLž<™‰'V^€7›%õ£>½íU,}ûö%99ÙZHL§ÓQ#YÅz½žÏ¿ûŽvsæàÙ´iÍOx½ÐéàÇ¡ò2Uj‡päÈk8~||< ËÒU!?–,¼<Ìf3[¶laĈåFJ¢ÕŠ&tµ–dEEb ìÞž|²rciÝ*kü¼NètRraÉ麳`$&Öõ¨JÈÍ•¶›7KúüÍ7‹èéè(¯ÙíÛk¿–m•$Y“ÉÄ_|a-ç>aÂë¾ððp^yåþûßÿÒ·o_.]º„c+1vëÖàà`Þÿ}¶lÙ²eËpvvfèСÕþ‚qqq4mÚW×r,2;wJžßµ$¸Æ—¨4À.l<¤m;ryÛPÈ÷ÏÔ«òš›+)¥Qf³¿®¬‹QX(Ç—;i“ÁðØ*ÏF(òã¤À@˜z‚NÂð)P\ä…M€%mßâãáÄ É·¯o-à† †Édâ£>bÓ¦M|ðÁ„††Ö¨L|lllÉ祤¥ƒÃµ5Ĩ¨\V«eêÔ©DEEñÅ_ð믿ò¿ÿý#FÔŠ÷)==Ó§O3jÔ¨ª}ÐÅEšÇ«Ñ*µ@÷îÝiÙ²%|ðUVquueÈ!µz3Ÿ}†&)©LË‘z§§¸ZªªR¯>|8F£ÑFVéС;w® ìÜ)¢‡yyy>|˜Á¥æyzB@@IáҘͰv-,Z$Õ²d»½® €œ)Þ»·þ~î9¸í¶Ú-n_T±±â­j ŒØXií|ð ¤Ošd»¿E ¹%W)?Teªôõ“’’سg3gÎdÔ¨Q8::Úpqq¡mÛ¶<ñÄ<üðÃLš4©ÜÞ’}ûö¥Y³f6U£œy饗øñÇY¾|9mÛ¶åŸÿü'AAÕO¢LH0;œC‡ <ÜÎ[¶\û• @ £Ñ22lCøM&ÉSwp€ìG4çäȤ,ýÎÈ;ç#!,›!Êâi8êAC¡™ÐCÚ¯ðÖ÷o†‡»BÓdÈÌ–â„ò[úúŠQê÷ßÅðÕ¯Ÿì;öî…?þ±edÀ­·Êÿ»»ËØÏœs¿Â©¡¥Œ»Kö?ûãá\Œr‡÷À™HˆK‡?ž†~Y0º- i¹ðãKž ~QÐK{#`øpغU”êþýìß÷ë@³f͘;w®MØb‹-X´hß~û-ß~û-ýúõcêÔ©5ʳ=uêÝ,9CÏ?ýÄ_GŠŠÄºhéó][ÄÇKmµåZõhÛ¶-sçεÖÐh4ôïߟ§žzŠ•+WR\\ÌäÉ“¹ùæ›k%Ï6>>ooï*Gïàè–Š“**U <<•2v8;;³`Á~øák7„þóŸµVhàü©S¸~÷Ͼûnå ØÔ'úô¹!ßE7"·ÜrK™h•–-[òÏþÓ*«„‡‡3eʔګ ²¿¤.98€³³3åïä$ʨ½gAQÄ8?|¸„ ×âsx½ÉÍ…uëÄkÙ¿¿|-EÇò¶m4WSòòàwäµ/iÄ•©‡”–+WŠ<6g `¿s“&0~<\º$¡ÂµE•VK%Þ¾}ûZ½§ŽŽŽÛT½kÞ¼9Í›7gïÞ½å*¬;w¶k© âÉ'ŸÄ`0àèèh·"jeÉχÏ?w§S§Q|ô‘(W6ëgNŽÄ¹ÏŸ_{¿¨= C¶›RSá㥧qË–rÓSSáÏ?¥ü¬Y"œ›Íðé§°fXX&O– üÁ2ô!C$Ù¹C‰€ CÔo¿Aú%غnš£F‰R™±þt ¥pï\0çÁ™S°á4’`V*4 û"!d6¼p7ý–üf·‡‚.]dâ®X!qêZ­ôwpê`ß~+žÙûîƒNàÜ9ˆÝÿ÷<¤¹ÉX[·†àb˜|3üü ¬Ý/ï·ä ðø›þ„wˆY³Ÿ†nwÁÖÃpä ~^xA®Ÿû3xtñÓäa™| *cPtpp`øðá 0EQpqq©µ¢PÛ·o'<<¼ÂÂvIOK™êñQ©"]ºt±Ó²eKž~úi NNNW-*V’’’X7>wôì‰O]Y\kÊÍ7×üWAQÄ ~ü¸tø©ÏÿÅÅ"Û­X!?Mm9*k{|­VK—.]xõÕWkEV)ÃóÏ[oØÆéׯŸQÈ.í'3S]»DØk×Z˜Í-ŠäС"“XÔFdæµkkvâb‘Ùßzõ‚Ûo—üØÔÔòå ³RRľœ,޳‰%X©¢Œœ€É X° ö~£*)¬–²Û¥C}ÝÝÝyüñÇmkFƒF£¡   ZƒªÅ?3S\êp÷Ý£ùùg_""®˜ÓÎÎâ×¾Öa“Q@Ä›é$i¿ýþþrCÅZñÖ[R½»Y3QÄzHÜõ;ÊwIO‡_”…ÎÇG*Û7k&Fª”X¾\&bß¾¢˜mƒáçñ8ÆÄÀýz˜~'ìÏw~Ô˜Ñ nY iGàøføß7ðôÝ<´ž0r„w·±%ÊB£F²Þ\Éœ9b}qq)™ÌÝ»C÷H¸eäÜ%€0è /‚äÞ¢h:™Á±øëa˜¸©< p„vS“pH«¿\ÃÏ HEúÆ"–#77ˆŽ®Ÿí>ª,p—CNNŠ¢ÐØÍMªÜÍšU§9«99y¹dIíµ2‹Œ”úµâ/vªéÓkïœEEpø0|ô‘´u[¾¼æÝ²rrä·ÌÉ‘g.,Lž±úÞÚP£Ñ\µòuU)..æèÑ£,\¸°êÅg¶m“ tË-uýÓ¨Ü@Ô¶¢jaÕªU8ãóÔShêh=ß´©†æ¯C_Ø£GE6rw‡®]kOaÍΖ%Ãl–è°Ú8ß»ïŠÈéå%¹õIa­ˆÚ’UÊpY9-,,äàÁƒ¼þúë•_×óòäus“b50›%¬¾Þ¾t ¾ùFÂk'O.5|õúQ‘-Î-'')†Ü£‡l/(GÀ[oÙÿÜ–-Ò&·cGxøáÊÛ|{ô€ äüµ•‰S%…ÕÛÛFCLL :t@£Ñ Õjm{?"=w˜8qb팲X,Ã!‚‚îॗ`çÅQq8‡\.JãæVëabùùWX*Œ óBÀoë_~)ŠiÓJ\ó³g‹%¢];Qô† 㑯/L*ÛE¼“99ÒVÊòóò’¿W_£Sjª„ðh¼aÞ¼ËcÑfh¦Â¨ly(ƒ@û h!°'¬†Ñ¯‚ögи_þ\4ÚL RYÏ®@é5Î ÿÖîïû‹›Ìþ½=°x)(ª(™©}‘ðjÒ“Õ‚'Ò¿uŠíXóÑ6ºq‹åææâææ†sjª¼agάôg-­ ÝÝ+ý‘ ÉËemÒ¤’s×”¤$ñÚ¿÷žxX mÛ꟯¸XBn^~Y‘Q£àþûE0«IOëØX‰2˜1CªâˆÒZ…uÿ~ Áÿ׿ÄÀ“—/½$Öù¿cg–¿þú‹fÍšU¯¯òéÓR1RE¥žÏž={øôÓOÑÔA8…^/¯’Ï?—¿ÚÂöí°zµ(jƒ{î%  j?µ‡:$Šnm©YUºÓÁÁÁ´iÓ†_ý•´´´2ÍêEA§ÓñÃ?`4éS‡9CÉÉrFJÐ7iG÷ë8pïQNŸ–ƒDüE‘ÅæÒ%Yl¾ûNÂo-}E,3:mA¡ìlYˆ~øA¶+ \<_þ'»Bš£x`&N,I öö–æÕWE×je²ví*ÔÙ³K&¯F#^ÙìO­VÞäXMp ´fÙ§MMS hA«‡"Ðx\ž ® ¹gAc,“Úb©L_k3ð1¶…”òê¾iˆRi9×h¤ÏëðËÛbfˆ"Ú)•m -°¸ Û6;­%·ô”4CËŸ[â™]M¤ž“––FãÆqÎÈ€  Šc4J¡(bÞ¹³vÆa2I´@b¢Ø‚Ö¯¯ÙùE 3ÿþ·D tè –½]»ª>½Þ|S¬…O? S¦È «C‰d¨ÅÅbüñGñØÞt“<ÇÎÎ_Aõ2%­ãÞzK""žxBŒV"Ü̘!ùáU-’ÐÐ1™LìÞ½›ÁƒW¯µGË–7WQ©˜Íf¶lÚĈFðtv®ôz^›<(n£FöëÛTý;‰2ùüEGW¿‹¢Èº¸s§¬‡wÞ)ÂpHˆD™U·*©Ñ(ÂõÓOË;æÙg¥˜L÷îáSÙõVQJ ’ïØŸ|"KÏ¢Eâqrr¹/0ðoÚeËd’$ÈË­q.]ºÄ¦M›˜2eJÕÖuF^ŠUzFEŒÉ?ü ÿß³gíU²µè z}‰®p522¤¨’É$sÄÍ­ü¯£ÑHädF%;vèõ"C½ò œ<)´{—UÎ]\$}/%Eþ>ýTŠ<éõRdyÐ )¢T@¶måy-*‚„WŠŠjæÎ®’‡ÕÙÙ™üã<þøã<ôÐCÌš5‹N:Ѹqcòó󉋋ãçŸ&""‚‡~˜àÚŠ ¬â-9Ä Aƒ¬!;O>ÎÿÖslS¡— ÃÇo“tóc´¹s²°4m*eš %$¦sg˜.åqìXñt¼ý¶(´­[Ëâæê*ÖˆÆeAzýuñr~ùÌq†qÁáŒ~ªìXÝÝí[ð*]LAÚ¼”ŽL*B*þ D‰3#±´Í€#H»`2ÌHë˜ H5^ Í€Êzµ²ãÀVJú¨¦#y¼£…µ7¢tžîA”×ýHïWKÚKà¾Ëß¡t O³ËçÙ”.Ý »ÎE”]€S@2ä5¹¢|ñ Ä©S§hß¾=ŽíÛË®äªb2‰PÒ¸±$Ç×”ôt±L/X ‹ÓæÍ5;_D„<wÜ! &Èbûì³"¤T%JÉhÁ–-­Ð£‡mÀ¤Ib7›+¿(§¥É‹ãÓOÅPõæ›¶p:ˆ÷61±rÖùsçàûïÅ€uö¬aãÆ•í•Þ±£x'úõãÕß…œœbcc™1cFõNPͰ1•ÚÅÒå¤ôók2‰RУ‡Ú«¨°ìÏ?gNP,\•XèòóEªÈÍøxQ(Ÿöí«¹0o4Jý³gÅcëí-÷;5Uì«UA§“†ß|ÿø‡(”‚‚dÎήzôID„¼üü䜥»¶LŸ.‘=Šru½È`î§O‹tà@‰ º2äT«}ÍÒ§òoʼnâ0€¼¼<^ýuyäB¯“111Q¸G9âÅåTTë©2äæŠ7}íZ¹Æ?þ!Ž£Šˆ‹#wŸ>•;>6l¹UÞZ™’"¾¸Õ«EÎyè¡«‡Ÿ·k'²Û™3¢û|ôQíÔK>\ŒТ…mÛÖl‘ªr‘äŽ;òÎ;ïðÙgŸñŸÿüwww0âááÁ“O>É”)S®InGeHKƒC‡üýO1vìpëv¯^¡Œþ¤ã܈ݛ†ëEØs± 7¥ÉͽtI^šz}IÈ®Åâ,^£uëD°mÛV¢/?üPbF„Éá^ ½ìr?s¸FŸm(°Q,k±45\>ç/À$$4DIl ü…(MD‰( €sˆ§Rƒx/‡û€Òµ²D¹¼Úks]]©k‚„ë6AòvÇ^>g0D^>#0îòu€H¯Ú¥Î• ü˜uÅ÷M:c pâò5_óqÈêš…Y[ÏzÛÔ"ÉÉÉ 6¬Ê+nQQõ^îöHJOè“OŠe4–„®WuÑS …ýðCy¾J× óegW>B¯—gvíZQôìYÛ·å}àÀ² â•ääÈ éý÷%lÆ 1ZÙ«uåæ&^Ö^(k|2ÅË—'Qùùrž[nãWy!JM›Êxcbþ^ kff&®®®xW§M%$¦¾'þÖ³Y”ëý532ä™èÚµD¨7d^·o_òl˜Í’f#G–¤¹:ÿùxþNsÚQ»w3±¸¯*´`Z³F X5­Æ™™)ùòãÆ‰|sæŒÊ©›yUŠŠÄ˸¿D‘5i"at´¤JTVaµ}Ù·OŒ¢o¾Y6-ÄÕUŒ¦çÏWîf0ˆ‘ð§Ÿ [7 ¾˜2¥ìq~~°g(öRFÌfyÉo§×˱ Tü.éÔI®=ujÍRQ;ÊÍwtdýå0¬*·(«Š"rʪUšÝ«—Ü»)Sjf$3›¥Ö¿þwß-5r\\D/ïÓ§ìZ¬(2÷>ùDJ],\\d½¼ûn[ÙÊh”ó®X!zÊ„ ÊÛ¢EåBú›5“ÔÁ€q ÕVˆtçε ×Ã¥KÔÌyTeÕÉÁÁž={òÞ{ï͉'¸té´iÓ†=zàs5©ï·ÝVÀ_gÞ¼’ÆÁŽ~t „nG mo†Ì”;³tiÅçlÝZÔÙ³e2,Z$Ûÿõ/yaDEI½Ï×ßRµ=b…¬-ˆx1kð.¢dZŠž@ Yr>½ìeo£.ÅQl-D!‡•ÚÖñŠ^9‰ŸRâÝM&"á¿)—¿ûÆËÛœ€•@àG`áåÏ„ÛÅ·´¡­×å϶»âºÁ@1¶íà Qfu€rúçàA=*«ZËœ9s†cÇŠ »]»JnÍY¬·o—…®ºB®¢È9†-"œœd!?yR”ÀÊb2‰ôüyQòì JcÇŠ€\…õìYÉíÕKžÓò>ãæ&?]Ea<&“„â~õ•,Âo¼quå¶{w‰~ÊÏ/ÉU²TQ^³F„¡M›äDxß¾}tíÚê$Ôåå‰ÅâÎ;ëúkT™‚ÒÛ·/Pt: [tqo»»+WJ%ø9säøëå­\¶L´/¿åÔd’hï¿—è…Ç—ã23ÅÒ+϶Ÿ_IõÉÛnAËž#\§s #£–íë1ÅÅÅ|ýË/Ì[¼íåÉ«qñ¢´•óö®¹Âºw¯Ü“qãäß-Z”í­^YòóÅ»$éN–ˆGG ÃÜ·OÞW£¨H¼•6Ⱥ[^ÅQggy""l=¤öHL”uwï^*Âï¹s2·«Š¢ˆ‚¹{wYƒOX˜(• ¥yqìÛ'ŠÜ«¯–¯ æçË‹ ,Ìþ~£QrsÿüSàaÃ$¤¸¢ÂR..ò‰ˆ° .,”q}õ•…÷_¿Ê9?š7——Rn®ü))" xzJ^ê„ 0z´¼xªR©°ys)‚àé ?üà@NŽ?&ÔvØFýÁl6sàÀ™˜(1êu ° 2g-UËóóå™[¿^æ]ëÖ%¹‚gÏJ¡‹öíÅR¿oŸÌM›ÄHsçJÙª•ÌÅü|™³..¢\º$Výýûŋշ¯œóèQy^:v”c½½m-èz½ÌÏÒsÐleÙÃÃöù-mÜRw‹rý'DhKJqÉñ†Ýq‡<ï¾+…Ý»¥.Ä£JdC^ž¶ž}VÆ¥Háξ} ·¯be9vàGGFެÔñf³ØaEÖÄÊ®µöγfÜ7KzÈ=Û±£jUr-ÞÐeËd³DŒ”fÈ1jT”‚a6KhíÈyžxâêžÓ)SÄÃT\l;—EÖàK—DùÝ»W¢m&O–gáj†>}äwiß^æªN'6ƒÀ{ñE[UC²§M“ˆ''ˆŽöÆh¼›ëõ"$Ìž ­Zqúôi¼¼¼èPÁ£ŠäæJ­[o•wnéûÝ®|ýuåÓL&™ßqq=¥ÑÈÜ,Ñìî.µl–/e“&²–þñ‡Œã¡‡ä¨ŽA±Q#ÉE5™äÙ_¹RŒýûËnô•NÊÑéÄÛ9n\ÉÉÍ$‘Ûl–@êæÍ%†d¶T±í‚Fc?ŒÅÑñrÈß9$ä5è‡x$‹Ÿ;âz-Ú‚þ(Œ›._7ÉOm‡„ûþQš‹E %â©ü«Ô6 âýÉ--°°¼¼ ˆ‚øRÙwÀåÏC<ª±—ñGWL[€Ž”xH/9ž’ –íý/ÿv¥ Å¶à’…Öˆb¾ðCŠ:Õ“’åׂsçÎÑ! ǽ{%ɺ’DDˆð$Å!Ìæê)¬gÏŠ@ñï— ;iÓF”³Aƒ®ž‹/ç !·¢©ðpÈíQP Å8¾þZ^N'V®²F#VÀ}ûDa5™Døþâ y ‹’ZÕŽ(nn²ä¼ù¦üÞ11r®Ûn»ºw¶"š5“°¦½{aÒ$:]ÎÎ-«ÂzNZZiiit¯¤×© Fãu/«¬×ËýÞ¿_ž7ƒAæ£Ep2™dXâqlÜXè¬,Q>$üüöÛKÚ–H4C·nr.£Q®³b…*OMf¦—.‰Rëã#ÛV®”ÏÜ~»¤»[XºTž“‡Èâ­Ý²Er-–÷ÈHÑûûôï˜Ñ(ŠÉ˜1âûÔSò,­]+¡Ž½zI¤Ä–-%JCHˆ(鯽&‘›7Ëõ¤ïàÎò¬XÖŒ„غUÇ!( º1ÉY¼˜›¦O·iX¹¹2¯^xAæŒÉT…º¥HI›Îðá¶koóæò~(Óù Ìf1®lÝ*áˆ:Ù7Äy{‹ðn¿ŠzB‚„áž:% Ƹq•S=<௿ä¼£‡¥âñвÎQ«†Û¬™ˆ‹7JzÉ=÷ˆá²gÏšå wë&ÏÑ©Sзo.ÉÉ™Õ?Y}g×.ÑöÅðôÃ?pÛm·áv[Jæç‹L1z´}%±S'±õët•3BÇÆJýšÛn¯l·nöóñкuâMß³Gd¬š¶ûsp¨Š}ûdÜÏ<ÓpÚ#Õ7œÂj0H±“¬¬hBCCEaÕëÅ䈂}e µ[‘0Þ›/kâA½ÉŸÍŽ"ÞM7Ä£¼ Í-])u0° X‚mˆñt ëòçJ3ªÔ˜-4¢ü"P÷»/§‘üÙ”èèh-IUÈaýñGZA»ƒ«v]³Yî­[EXêØ±ì1Z­„¾—/Deg‹GéÿþOžÙ)S®®`jµ"äκœ×¬×‹µ3!AlRwß-ù!žžU³`öè!¡AŸ./›Õ«å¥4lXÍrŒúöÁÏRÀ¹¶òCú÷%Úd‚5knÜ(Âb:t¨^80ˆÄ0aBµ¯_T$ÊÚ… "OŸ.¶ÎfÍäÞŠñÍ7­Ð¯Ÿ(„û÷K^ÐäÉrWW™¾¾%‚®¥ªhé9ѧÜ×Q£Jæ°År^:ˆÂb(½ï>Ûñ6m*a¸&“( Z­\§¨H¾Ãoȹ{ô¢a“'ËX-ÞÐcÇäù¾õVùÞ§O‹²¼r¥J¾ûNÎëá!!•C†Èw›7OŒEC‰ ×­›t±8vLòT-·ðÁ¥÷ß믗(-Ã‡ËøÖ®•Ûe6‹À×¹³'§kaé­GüñE.ÐÆÒ±¬X!Þ9__YûÆŽ!¶²(Фm¼õ–x»¯ 8sw—œÿ“'¯žg—˜(÷¹m[ñ T”÷êâ"EorsK¶ ò íß/Ì=¤Ré•þ«qÿýb¨qw—÷ÚñãòŽ›7¯$š¡:<òˆŒ{ìØ’°Ìšâè(Z€„éé•,-ÛÐ(*’°Š™3ÁÑ‘øøxNž<ÉË/¿\©ÇÇKHø­·ÚF7^ “I.Û­›DpØ3ž¸¹‰[Ò—Ô ’sl2‰­qã«¿Çï¹G ±N˜ FÇnÝj§è÷ĉ%Fê²O]pÃ)¬ññåêšÀðáJJewëfkV¾œG¼šžˆ'1QP[! b’÷Y“(ˆ/‘Šº÷ ŠÜyÄsÛɑ݄×n,M¿ÝPÙÆ”(„î—··ÃVqôAªõ^ù`uF¼²‘ˆ×sR¥×ýò¢€|¤ˆ·Óñþ–ªæG0¾œÅ5üïð•‹ÊPl«cgl¥ñÖ"ÞÚ®—«ƒÁÀÉ“'¹ãŽ;.7Ý­éé"`[ZRví*J_U*䦤ˆ€4xpù•ð¼½E)¯ÊdAxgš7—àÀJFüµl)ŸMJ’q¿ÿ¾XG'O幺=Z%\ñ¯¿Ä:?qbí4÷ð(?|¹&Xªú›oÜzb€„GDDÔ¬Šd‹%© •$>^ÂoD Û¿_z÷†„ˆ£`Å Ù&ÿnÔHY??™7‰€u庲ï¢å>^IM''Û¼tF„³N¤ÆË/ËZÐ¥‹,J~Õ7߈â¸p¡¬§O˳îâ"Šnûöâ9ýúkà–.-1è´n-û.1<9:ŠçÕh´}ƃƒ%+§uë’uÇÉIB¡7n”óšÍ¢Ï™SÒWý†D§ƒ+ØÑ®/WÒý’”$†»wÞ‘9Õ¯_Õ•¨¬,¹ÏÓ§Ëçí1r¤xú+âÀQz–ûW»’££Ì«Îå>ò‰DLœ(Êau+”êtRàiÊùN< !ô5Íç¾Z^luù[(..b¹¼øY:8Wâ{ò¤ÔŸ¹¥² kq±ÿ]䌊¹žžI`OaMJ’è…¯¿–µî\ûíѹ³D¨´jU»?çö[7œÂj2‰ì›obiÕjºltqi´6«PÄ!9—S(ñ˜º Þ̳ˆ× Kµ{ A<¤•åÿ¥EàÍFÓæHUÝ H  ¡ˆWóD¡µ,=v2ƒKë ¤ì hAùÞËNˆÇ¸¢ØŽ@Ì'€0d‹Â꼈(¬=¯8Ï—”íìCÙ0dËyª‚+ð:’›[ eþë+yyyЪ &ãü| –.-YøŋѧÏÕ ™L²÷ÅRt¬¢”Y??±´gg—XýE,ñþ)—ùóÅóX•ÇÒÅE¼«Ë–‰²<~|‰‡§¦w÷îòW­UÊ¡¸¸˜¸¸8&ÔÀCJNŽÜÔ«¸ŸEÂw¿ýV»ÂB1€tì(yJîî%•m–ç!;[-Ú1p\Ú·‡?–õ ´0߯_ISy˶J² ,µ¯¯äÓúûÛÎqt”‡+Ÿ?¿²cpw·í1n!$D~óèhQˆ'Múõ®®ü4`­Ìf¼*á"5™$íéá‡KlðÑÑ2|xå.yäˆ(š –Ör¯¿ùÆÖÛ¢dÆÇK¡-K¨£¥|ehÕJ<¡o½%ï„{ï•uÝË«fëo¿~R ¶ys™êZ^Ðhd"]fãÆŒ½J´£Ù,ùÓQQbtÈÈâVO=ÅU?wá‚„ÌîÜ)éJWK¿ —cÆ£Or²D1ïÜ)é | ²GUd '§ÚWVÿîÜp ëÎàNWH«V­¤ÇÅ^›ìGB[[ Š›‚!ê‹„ÀžBò63)ñöC5…н„ ¡½ JoX©ó»su—¹€TÓQX Hꥮá(Ñ¥«j€Û)éÑZzûÄrÆÔ #^uùß«•’»z7®k¡1R|éÊkØSB5v³5GIDAT”­B\,mrjØW«¾SPP€g|<ù¥Ò}Å+Ù¬YÉ‹¼Q#) tµtn³Yr>úH,ØW«H©ÑˆRš-‹v^žx/EàÙge{uŠvíäå2fLí¶P…›úGQQ4«IêO?IÜéèÑ6›M&Jrs%»S'ñØß¿xìËS@5š’pÜʶWªOh4²\ù“j4e«…—ç *)Qšªtå«Õʽøç?åß™7pjÈÿcÿ~^~ùå’ˆ° ÐéÄàðÖ[%kVË–Ž~5…ÕdOúñãrÿ¯ܺµxáóòÄëi6—¤_øøHÊDÿþ•«P//18vé"ï?¿ÚYÝÝ«>•kˆ¢Èd½õVðó#;;›óçÏ_µAR’×—-“(—´4É…//ÌÒ¹,9YŒésçJ®ieäFd“»î’ÿ?|XÚê võš*×—Na=v ÌæôéÕ —S§¤ºÃܹ5Êa*ƒñäý ½Œä_NF¼“~ÀD+­K4AÚÀt§¤ˆâyQL-ã_À<$¤8QT·³‘ðÙSH…^wÀ’_Ò©Kñâµàwy¼W*qå…I—³Ýñ ¿Žä –>Ï-H›œÒ3ª1’GÚ¤ö~záôÉ“ìÛ‡{%뱉²ùÈ#¶¡cò"hÜX $ÙC¯—ÜÎfÍ$ß´²é²–¦ë«WK•ÜÜ*Õ†*—.]ÊVU¹1‰ˆˆ 88?{nºÊ’]FÊÉÊ¡$1Q^F£ØZ±BPT®#ééÄô¦RS )ܵh‘mñ–°0©)P©©¢ÄÆJÅæÊڀΞ•üÒÆ%<òã%'ÏÒ§¾:¸»Ã?þq~_•º%)I¬‚÷ßÙlæÇ¤ÿþøW×j4Š7õùçKÂ_}}¥È`Ë–eå“IR–-ÛýGU.,Ý‚ŸŸ¾ÿ^䤌 ‰`®JT•ëà ¥°fe§§Bqñ:7i"U^z©$a¯ºEÒbi.~Gªáº!•#á¹SåòRˆèJCRiϧ…sÀˈ¢Ù QPÞ¾¾|îîˆBjñ’Þ„$G— ÐXÏÛ ÉcµàŽ´“© AlR|éÊž‘· íkJãˆä¾ªÔ:±GŽ0|Ð 4}ú\õXKõF'§²ꜜěqáBÙÙ,¡fHúÉ€Uªí„““X9 »‘jùV© Š¢°wï^z÷î]³étè=9sRºNž¡ÈËK*ãúúJ(¬ŠÊugûvÎlÛF»#*uøÁƒ’ã{Ûm¶Û;w½ +«l0™É$zæM%í…*[¥\£‘(œÍ›å=ðÈšÞ²åõëó«Ò€‰kг3ɉ‰lÙ²…·Þz«ÜÃÍf1¼œ;'¡À¥½îƒI¨¯¥ß)H®ê©SR}Ò$ ¢©jm>É鎖¨¯ÎNzÇßJaõö†7Þ(â±ÇŽqÛóÏKÌRUËÌÙcR@È’¯sQJCï¼ÒÀÅëã„äm~üïŠsABt‡]þw.°ñ’~ ,FÚÃôC̹ˆG3QZ-ކæˆÂú,%a¸`%­gJsG-ýÈÎÀBl=ÄPÒGåšc49ËØ·ÞªTµ¢œ)DöðÃöËð‡…É¢_šÂBÉZ»V*‡N›Võq6o.½È®EÑ!•Ÿ¬¬,Ž;Æc=V£ó$=°ÿû?i33w® ©ZI•ZG§ƒ‰ `àÀ•úÈÏ?Kèâ•)®®6™’b«°K¸ãªU"UÕö£ÑHMü|©F}eÑ0• éÐÁZ qýúõôíÛ— {½!/“–&5.ž~ºl¤Ë˜1ST$†“Ir¨¤pcu uiµR§À^·•úÅ ¥°dedà^T„Ÿ_íÄv#a¹[€nHxkâQt&!Õ;!á²&"•t¯ »éŒx(!ÛóHõÝY—@¼·ƒ¯®âÅ]‰„[Då+ª)ª­k~ •ê“pþ<&Á¡¡W5sëtÒ®bÂû=ï@Þ';w–:‚¼4´Z±Æ×$SUVUªKLL 4©¢”œ•%]Üܤpˆ >ož*p«Ô#œœ(œ1ƒÈ÷ßçnK³Ûr°ôƽýöò£ÆC#ˆ§êÈÉ5 –ðÊê®ãýú‰âªzTUªÌå¬ääd6nÜÈ’%KÊí3œ‘!5îºË~¯ÒFä˜ãÇå¿›7‹1åÎ;«¯¬ª4,n8…Õ)#ƒ©§NQkч‘@’zQLWó/ï۶Dz”ZðF¼‘Wý» ¸„䟶F¼«"ùž­€¥HH°%5ÑQ~“°­òë<€´ Qù[átð ·89]µÁ¼^oéc(UMË8š4%5!ABnâ㥠ÈÔ©W/Ƥ¢r­Ø»w/=«˜Îqò¤TÁiû׸1ô>ñ?Z>;½ú w**×GGþLI¡sR ²Ž‘(˜ñãË_“ÓÒ`Ï ÷MK“jîãÇKQ=§²oø*Í*×½Nž¤8,Œ/¿ü’ñãÇÓ¶œ¾sçÎI4× AÒ±Àž¬ââ"áÀ?þ(ÿž>]Ž­ž¸* ƒïVÿü3a£G£­n‡èll‹¥£€ àà #%!±žˆÛ[ï¦+B|å/ìô%} ï5PR ©0)àT:'½ Ò:æJ*h+¢rc¢èõ8þù'ÇŒ©ð8KqŽÝ»áõ×+^Ô]]ÅúÜsÒ"fÆ )È¡ZÔUê’ãÇóÜsÏ]õ8E‘°÷?þéÁ¥l»;hÌ&ørÕø_•úEá¾}lþóOžzþùr).†5k$Ràµ×*ŽhÛVŽû÷¿¥ê¿ÿ-Qê:®R'ìÞ rÞÝÓ§Oóàƒ–9Äd’Ã>ûLZYqßðᢤ:;‹Ü¢Vöÿ{qc)¬ñGŽ`¸ï>'(BÇÊ’Œä‹>€xNS5Hû'DA\xOK[Ç]>¶ô6W$oÔ^¨‚#𢸾EIµ^G` eÛÞ8W/ ¨òw ;›˜ýûiSRQï?`ñâÊ…Ë ,E Z¶T_*uÏùóçÑëõ´iSqIn®ôiiRDiòä+BEjWKÿªÔ'’’ˆ{äL:кuù96?ÿ,K–\½3_PŒª¡ï*õ€={ {w~[½šÁƒ—iMVP Õ}ÿæÌ‘^¿WÃÁA ÿý;SïV³ÙLzz:iiixyyˆCecRù< €G:t€7EðY*—×YŒ´i |„x4÷½/ŸGƒ´± ¼}Åg‡!­iJ úˆW¶ùäëçL&i•ôÇÒßwñâš…¬«ü}¨w ë¾}ûøôÓOILLÄÛÛ›™3g2aœ*1£³²³É+Òb ‘ÜÎXà¤rnéE\ArH“‘°]-¢¬F‹.oiÓò¯RŸu^@òUKãIõZÆ4À¦ó*5£¸¸˜ßÿï¾û޼¼Hÿþý+õùܼƒAÚ¼û.Üs„»·m[AÈ{óæµÛƒ[Eå2{öìá³Ï>#))‰¦M›2kÖ,ÆW)Y¥H«e£VËü¬†E‘öåËå˜îÝ%g¯²ÙMª¬ªÔÅÅŬY³†ï¾ûŽüü|Z·nÍܹséׯ_¥>o|è!V¾þ:&L ñe·¨É$ý¯wïc£¿¿ÚBF¥òÔ«ì†ôôt.\H÷îÝùý÷ß¹ÿþûyë­·ˆŒŒ¬Ôç½½½ùfá7¸¾î*žÐç‘¶2û®8ð,ð„徤]>¾Ä‹/¾h-¸TT$Å’ÞxCª ¶n O>)ÿUQ¹Þ(ŠÂÏ?ÿÌüÁÒ¥KY¾|9f³™¥K—¢Óé*uŽ˜˜š4iB`©–M&“´fzàéùá‡BÖ¾ýUŠnäçK©l•ZÄ"«ôêÕ‹ßÿÙ³góïÿ›'NTêó¿kµø j-B“œ,i³fAzºT¾í¶Ê+«**µÍáÇY¶l=ôkÖ¬¡}ûö¼òÊ+•–Uââ∎Žfüøñ¤§KUߥK¥ŠûÇK×µžJU¨W ë¡C‡ðòòâ–[nÁÍÍ¡C‡ÊîÝ»+w©º;hTè}éazÈvï#yªw E”tˆbZ:·põЭÒÙµkݺucÈ!¸¹¹qË-·àêêÊ¡C‡*}³Yò?RS%œæ»ïĉôßÿJ“½^«**דÉÄÎ;3f ]ºtÁ××—;3‹/rîܹJC_PÀ¨=`ï^”»ÈÌ”ê¿ÿž—Î-ÆL¿ôÜí—ƒ““Åݺ`¼õdfÊöÇŊóôÓP…gKE¥28pooon¾ùfÜÜÜ>|8íÚµ«´¬Ò¸qcn¹åRR¤Pҳϊmåµ×¤ÍÕòUUT®5YeðàÁVYÅÉɉÇWêókÖüNxø(Žóå×_¥ÁwÀË/KøºŠJU©WêØ©S§ðññ±ZÖ]\\èÒ¥ G­Ü ŒˆWt0%F!}O¿F<§–4.ïï¼bç\ØQªeΞ=K³fͬ¡ .àé鉺ÚT›ãÇÓ½{wknž¿¿?DFF2räÈ«~Þ`€Ÿ~keëÖp÷ÝЮ]ýË)..æìÙ³„††^µýN}Áh4röìYZ·n«ÚϧZ˜ÍfNœ8ÁŒ3¬ÛÂÂÂ(**ââÅ‹tîÜùªçèHÿ~ ~÷EÎûôfõjiÍ´ü?™8sÚYûûѨ‘”ÎÏ“½%¾];qS)Ê5 7ÈÏÏ'11‘NE¼ÂÂBâââèØ±c]¥AsòäI|}} ¸<«*«tè0–~!þÑGáÿþ¯~*©™™™äää\µøY}";;›ŒŒ ÚµSÛ(Ô„ãÇÓ·o_kŽu@@þþþ?~œ#F\õóÎ΃ټ¹3ÉÉZ{L :ÖG²²²ÈÏϯtÊJ} 99Àºþü]¨W’dnn.ŽŽŽ8_jwpp iÓ¦¤¤¤Tø9“ÉDRRšŽH¿â€aH®ª©þÛÉS­CöîÝK‡ÔCràÀ ©ë¡T £ÑHFFžõ(™3;;WWWkwww5jDjjj¹ŸÑh4èõzâââ0›IIÑpÇéî.!dõ‚‚vìØ››. Äå«×ëÙ¹s'C‡ÅËË«æ'¼èt:òóóëz6äææÚKòööÆh4’““Sîg´Z-999ÄÅÅ‘‘éÆç 8•¤aP…»oNÆ×Ò<¡iŸ’]~iSZù*ý0Xžû¬¬kò=SSS9xð`ƒ™+ ÈîÝ»”¡4--¢¢¢º† WÊ*ŽŽŽx{{_UVÉÎÎ&!!3ghÜ^|Zµ’ÔŽä:–IìqîÜ9âãã”/>>ž˜˜˜r ¶Õ7E!)) “ÉT×C±áJY¥Q£F¸»»W8ÇÍf3©©©$&&ÈCe*iõq~ƒ8b’““ŒaàÈ‘#U*bX×XæEMeÁq‡Ìfs¹ûhÛ¶-ÇŽ#..®òUúê777­–’†€ƒƒééédZÂîê1Š¢ŸŸF£iV¨Šæx£FfëÖ­xyyÑ®ÅÅPÉt©:AQ|||*^_hÒ¤ QQQ âe`6›ÉÉÉÁËË ºN…(Š‚¢(åîoÖ¬nnnlß¾77ú kÎè& hµF$O»¾¡( 7æÀu=”*¹iÓ¦ jÌééé×õ0*EE븳³3îîîìܹ“F))òW_1›Í8::6¨ùb6›quum0c6™LdffÒ»wïºJ¥¨h÷óó#22’={öàââ‚NÇŽÕõˆ+Æl6£(Jƒ™/€Õ¸ÑPÆ\TT„N§«”g¾"ê•Âêää„ÙlÆd2áàà€ÙlF¯×—éßTFCŸ>}èÓ§O®¤¢R78;;c2™PFƒÑhÄh4Ú˜¹'''ÆW×CWQ©NNNFë¿õz=ÎÎÎF:¸ººr×]w]±µ{]»TGVquueΜ9u=t•Jq¥¬b00™L¦„qï½÷ÖõÐUnPêUÑ¥Ž;’——GFFƒèèè•?¡¢R;w&>>½^H¸[JJJƒñ ¨¨T„V«%,,Œ3gÎX·ÅÆÆâàà€¯¯o]OE¥VèÔ©999Öh£ââbbbbTYE冡sçÎÄÅÅQ\\ H Djjª*«¨ÔõJaíß¿?ÙÙÙìÚµ‹ÂÂB¢££9|ø07ÝtS]ME¥V>|8GåôéÓ°{÷nRSS=zt]ME¥ÆhµZFŒÁ¦M›HNN&++‹?þøƒ€€ºvíZ×ÃSQ© @FF»w聆°¨¨("""TYEå†aĈDDDCAA»ví"##£RÅ!UT®õ*$¸E‹Üzë­|üñÇlÚ´‰øøxFŒ¡ :*7 }úô!<<œW^y…€€.\¸À=÷܃w},©¢RE´Z-S§NåСC<ù䓸¹¹‘œœÌ‚ h¤6•T¹A âÖ[oå£>bÆ ÄÇÇ3zôèJUÁVQiôíÛ—¾}ûòòË/ãïïÏùóçUYE¥NÑ(eP×/^äĉ„„„4¨–**•åèÑ£$&&Ò·o_üüüêz8**µŠÁ`௿þB¯×Ó·oßUIWE¥²\¸p“'OJûöíëz8**µÎ‘#GHJJ¢_¿~jZ‡JR/V•z•ꢢ¢¢¢¢¢¢¢¢¢¢¢bAUXUTTTTTTTTTTTTê%ªÂª¢¢¢¢¢¢¢¢¢¢¢¢R/qX´hÑ¢ºDCG§Ó‘––FVVë>EQ((( 55•¢¢"\\\ÐjKìf³™¬¬,2220›Í8;;£Ñh¬ûM&)))äææâàà€“““Íþšb0HNNÆÃÃÃz^EQ(,,$55N‡‹‹ 6cÎÎÎ&==“É„‹‹‹Í˜Ìf3)))äää Õjk}Ì*×EQÈÏÏ'55•¼¼<œœœprr²î¯é|(**"%%…ÂÂBqt¬Ýâå………¤§§ãééiórssIKKÃh4âêêZfÌ¥Ÿé+ŸK½^Ojj*ùùùÖ1«s¼áb6›ÉÉÉ!%%N‡««k™5/55•ìììJ͇ÒÏÇÕÞµANNùùù¸»»ÛŒ9==¬¬,€2c6 ¤¤¤ŸŸƒƒƒÍ¾Ú;@¥áa4IOO·®yWÎÃââbë|¸rM«©LP¤¦¦b6›mä+£ÑHJJ yyyvç°N§³ŽÙÙÙÙf̥߃¡Ì;@¥á¡×ëIKK³öG.=«2ª#Ô“ÉDrrr™weÌ………899ÙÈGŠ¢——Gjj*ÅÅŸ¹¹•³å (J­ùzS¯ÚÚ4D’’’øïÿKdd$EEE´k׎'žx‚N:REð£>âäÉ“xyyqûí·3yòdœ1›ÍìÞ½›¯¿þš¤¤$Z·nͽ÷ÞKß¾}Ñjµèt:~ûí7~þùgŒF#]»våá‡&((¨ÖÆÿ×_±dÉ~úé'kÛ‰K—.ñÞ{ïqüøq5jÄäÉ“¹ãŽ;¬/Šð¿ÿý‹/Èœ9s8p èõzÖ­[Ç·ß~KQQ;wfîܹ´k×®®o•J59qâü1çÎC£ÑÎ<@‹-P…¿þú‹ÿýïÄÅÅÑ¢E æÌ™Ã€¬óaíÚµ|ûí·èõzºtéÂܹsiÛ¶-¹¹¹|ôÑGìÙ³ggg À#­[·æ¾ûîcàÀ€Ì¡wß}—ÈÈHÜÜÜ7n3f̰·šÈµAll,óçÏgÙ²eVy9''‡÷ߟàââÂСCyðÁqss **ŠO?ý”èèh¼½½™5k£FÂÉÉ £ÑȶmÛX¾|9„††rï½÷Ò£Gº¾UÕGQ©6ùùùʼyó”;ï¼S9t諼ð Êm·Ý¦\¼xQÉÏÏWæÎ«<þøãJLLŒ²~ýzeôèÑÊÆEQ”øøxeøðáÊ| ÄÇÇ+ï¾û®2~üx%99YQEùí·ß”‘#G*›7oVbbb”üãÊSO=¥ètºZbb¢2uêT¥}ûöJ^^ž¢(ŠRXX¨<óÌ3Êܹs•S§N)[¶lQƯüöÛoŠÉdR²²²”#F(K–,Qâãã•Ï>ûL;v¬ræÌEQeË–-Ê!C”µk×*çÏŸWžxâ åþûïW ëúv©Tƒ¤¤$eúôéÊÓO?­ÄÄÄ(GŽQî¹çå‘GQôz½’‘‘¡Œ1BYºt©¯|üñÇÊØ±c•sçÎ)Š¢(›6mR† ¢lذA9wîœòØc)sçÎUt:R\\¬¼óÎ;ÊwÜ¡Rn¾ùfeß¾}JDD„rÇw(Ë–-SŠ‹‹•üü|塇R{ì1%::ZÙ°aƒ2fÌeýúõŠÙl®•ñ÷ÝwJ=”_|Ѻ-22R6l˜òí·ß*ñññÊ+¯¼¢L:U)((PL&“òõ×_+'NTvíÚ¥?~\™9s¦òÚk¯)z½^),,Tž{î9åÁTNž<©lݺU™0a‚²jÕ*Åd2ÕõíR©«W¯V  ¬\¹RIIIQ>ýôSeذaÊ–-[£Ñ¨|õÕWʤI“”Ý»w+ÇŽSî¹çå7ް·šÈ5¥°°Pyã7”N:)?þø£¢(Šb6›•Ÿ~úI;v¬²mÛ6%**J¹ÿþû•^xA)**Rt:²páBeöìÙJdd¤²sçNeòäÉÊ÷߯F%''G™2eв`Á%>>^ùᇔQ£F)G­ë[¥R ŒF£²dÉeüøñÊž={”‹/*¯¿þº2iÒ$åĉŠN§S^~ùeeΜ9ʱcÇ”;v(“&MR~üñGÅd2ÕH&¨ ÒÒÒ”x@iß¾½rúôiEQE¯×+‹/Vî¾ûnåðáÃÊÞ½{•iÓ¦)_~ù¥b0”ÜÜ\eúôéÊüùó•óçÏ+«W¯V†®ìß¿_QE9qâ„2lØ0å믿Vâãã•E‹)“&MRòóóëúvU5‡µäææÉ<@ïÞ½ aþüùÄÆÆ’˜˜Htt4IIIÌš5‹ÐÐPÆG—.]ظq#»víÂ××—Ûo¿   ¦OŸŽ³³3ýõ›6m¢ÿþŒ5ŠÐÐPf̘Á™3g8{ölÇ®ÓéøüóÏ­– çÎ#::šY³fÑ©S'FŽIxx8›7oÆ`0°wï^<==¹ë®» â–[nÁËË‹={ö°e˺wïθqãfæÌ™$''U×·K¥\¸p¬¬,{ì1BCCéÑ£>ø {ö졸¸˜={öàååÅwÞIPP·ÝvžžžìÝ»€Í›7Ó³gOÆŽK›6m˜5k‰‰‰œ>}šŒŒ öîÝË­·ÞJŸ>}èÛ·/Ó¦McûöíÖžš––Æ§Ÿ~Z¦ÏíÐjµÌœ9“   ¦M›†ŸŸ;wî`Û¶mtìØ‘›nº‰   fÍšEVVÇ'??Ÿ;w2qâD @=¸ë®»Ø½{7—.]ªëÛ¥R :DË–-™3gþþþŒ9’©S§²}ûv¶nÝJXX7Ýt-[¶dÖ¬YdddpüøqrssÙ¹s'“'O¦ÿþôìÙ“;3;w’’’BLL Ìš5‹öíÛ3vìXºuëÆ¦M›Pj¡£Üùóçùõ×_mÂݶoßN›6m˜2e AAA̘1ƒ¢¢""""(**bëÖ­Œ=šÁƒÓ¥Kî¾ûn>LBB.\ **Š™3gƈ#0`›7o¦¸¸¸®o—J5Ø·oÇgâĉøùù1kÖ,ºvíÊÎ;)**bÛ¶mŒ;–AƒѵkWî¾ûn|€£GÒ¯_?ëg;uê„¢(œ9s¦Æcß°a/^äÁ´Ùž˜˜H^^Ý»w·óñãÇ1 DFFÒªU+ððð K—.eÆl‰“ ÁÝÝ]UX(Mš4á®»î¢M›6ÖmŠ¢X…íÈÈHZ·nMóæÍðôô$,,¬Ü9‚««+§OŸ&''‡óçÏnÝß¿.\¸@FFFÆm6›ùì³ÏhÞ¼9S¦L±ÙwòäIüüühÙ²% ÏqÏž=mÆÜ³gOkÈfëÖ­i֬ǧ°°˜˜›ïÔ¯_?’’’T…µÈÌ™3iÖ¬ k¸Éd²®aG¥W¯^V988oooNœ8AAAgΜ±™ýû÷'!!ÔÔT.^¼ˆÁ`°û¨©Âš™™ÉÒ¥K™>}ºÍz ò\véÒÅZHPPe3æž={’••EBBIIIdggÓ³gO›1Ÿ8q½^_×·K¥ôèуÛn»Í& Ý`0ààà@QQQ™ùлwoÒÓÓILL¬±LPÎ;ÇòåËyòÉ'iÒ¤‰u»ÙlæØ±c6cîÒ¥ z½žóçÏ“ššÊ¥K—ld³ððpNŸ>MAA'OžÄÇLJV­Z’ß]ú Ò°ÐjµŒ;–Q£FY·•–Å/]ºDjj*}úô±î'**ŠÂÂÂÉ5åСCìÙ³‡'žxÂf{ff&ñññeä£3gΓ“CLL 5²¦Wi4úõëg£_„……YS•üýýiݺuƒžãªÂZš6mÊ#<‚——Š¢‘‘ÁÿýßÿѵkWZ·nM^^&“É&/ €¤¤$222pss³èpuuÅÛÛ›äädëþÒ–sE©‘÷IQNŸ>ͪU«˜={6^^^6û Ðëõ6ùx¤¤¤`2™ÈÈÈÀÅÅÅúà:;;ãããc3æÒœš4i‚““éééu}»TªA§N˜3g³ÙL||<Ë—/g̘1¸¸¸‘‘«««Í|hÖ¬Y¹sØÛÛÒÓÓ)..&??ßf@@YYYe¬UAQ«Uþž{î)Sd ++ GGGkþ•££#¾¾¾6cnÔ¨‘µ ‰——®®®¤¤¤`4ÉÍÍ-3æ¼¼<òóóëúv©TƒáÇ3aÂ@¬Ý‘‘‘¬]»ÖºíÊùиqc\\\HMM-w>äææ’ŸŸO^^F£ÑšÏjÙo™kÕÅl6óÓO?¡Õj™0aB™9ž‘‘»»»5‡ÐÃÃOOO’““­rJ¹yóæ‘››[î; 55“ÉT×·K¥LŸ>^½z¢¨þùçŸDGG3fÌkÁ±+çƒN§#//¯Æ2Au)((à“O>¡W¯^Ö±—&++Ëf̾¾¾ ²³³Ñét–y.-ïììl­ù‹øùùÕxÌ*uƒ““<òˆµ®F^^_}õMš4¡k×®èt:t:Ýù`0j$Ô„¸¸8>ùä«g·4z½ž‚‚‚2cÎÌÌD¯×“““ƒF£±FIj4üýýmô‹+ß^^^ zŽ«Ùåµ@aa!»víâ³Ï>ÃÑÑ‘%K–X­ö0›Íž¯"¡@Q”«~¾"òòòøÏþÃСC:th¥­-u9f•º'##ƒ?ÿü“ï¿ÿžž={òôÓOÛTB½’šÌ‡ÒÜêpöìYÞ{ï=ž{î9BCC+æu5a¼¢1›ÍæZ ñT©;øî»ïزe Ó¦Mã®»îªðøšÌᚬ‡f³™ýû÷³uëVÞxã e¸2Ÿ­hßÕö«4lŽ=ÊŠ+8zô(>ú(ýû÷'--Íî±551n˜L&~ûí7222xá…*|×”æjï–k9f•ºÇ`0°{÷n–/_Nvv6 .$$$„óçÏÛ=¾¦ó¡&k¢Ñhä£>"88˜‰'V:Bëjï–«¹!ÏqUa­Š¢Í{ï½Gdd$·Þz+cÆŒ±†G:88X=SËŒÑh´†¶888X]Ëq&“ɺßÑÑÑæ08::Ö¨éîÝ»‰ŽŽ&$$„Ï>ûŒÄÄD¾þúkú÷ïV«µ;f///4 Fë˜EÁd2Y« ZÆlÙo2™Ðjµer¬TŠ¢pñâEÞ|óM xâ‰'X¼ðZ­Öf5 ¸»»×¨‚ê/¿ü‚^¯çرcœ8q‚ƒ’ÍgŸ}Æøñãqpp° 6Z­¶Rs°~g­Vkó nnnjÕŠ¢(ìÙ³‡O>ù„&Mšð¯ý‹=zXïgEóÁ2‡íÍKëŠÞÕ!//o¾ùOOO¶mÛÆöíÛ9þ<ÎÎÎ,_¾œ©S§Zçxé1›Ífëu¯³¥Í‰››z½Þºß2fƒÁ€——W­·ãQ¹>èõzþøã~øá:tèÀ‡~HëÖ­­ûíÍaWWWÜÜܬa•Õ• ªC\\+W®$$$„ŸþFCAA»wïÆÝÝ¡C‡Zß=ŒF#NNNVO˜åÝbñ0 <<xzz–;ª"T‡ÈÈHöíÛǘ1cøì³ÏÈËË`åÊ• 2'''»òQ£F¬û€rçð•ï‹~áããS×·«Ú¨oŸPXXÈ;ï¼CRRï¾û.÷ÜsUY ÂÉÉÉê¢8vì˜5æ<,,ÌÚ»¤„õ… löŸ;wÎúÙsçÎa6›­eÛ«ƒ‡‡={ö$))‰¨¨(.\¸@tt4©©©øûûãååE\\œõ3–ýôSyä^{í5BBB¬^KgggBBBlæ°¥SÓ¦Mk,TzôèÑh´Îq£ÑHrr2.\Àl6Ó±cG›9‹££#~~~øøøàççg#‹;vŒ-ZàêêJhh(ÖZ ƒÁæ Ò°0›Í|úé§ìÙ³‡7ß|ÓlQêš5kF³fͬò.”ÌggçÉÕÅÑÑ‘¾}û’™™ITT”µ6ÍùóçINN¦qãÆ–‘üýýqww§mÛ¶FRSSQÚ?n3æÄÄDkÝ´´4’““ôWÖ’’ÂæÍ›7nEEEÖ…5**Šüü|:v숻»;;vì@§Ó‘‘‘ÁŽ;3f ƒ "66–˜˜ôz=ÑÑÑœ9s†‘#G0dÈvìØAVV………ìܹºvíZí10€×_Ýúg)º´`ÁFM›6mhÞ¼9›7o¦°°ÌÌL¶mÛÆ°aÃpqqaàÀÄÇÇsüøqkƒ'NXÇ~üxüüüxýõ×éС}ûö%##ƒˆˆôz= DDDX 6 <˜péÒ%ŠŠŠ8p๹¹ 0OOOz÷îÍæÍ›ÉÍÍ%77—uëÖf-à¡Òp0›Í¬]»///z÷îÍ™3g¬óÛ"( <˜¿þú‹ÔÔTŠŠŠøë¯¿((( ÿþxyyÑ«W/6mÚdk×®¥k×®Ѿ}{<==mÞÛ·ogôèÑÕVX===ùÇ?þa3Ç»téBïÞ½y饗ðññaРADFF‡^¯çèÑ£\ºt‰aÆáêêJxx8[¶l!''‡üü|6mÚD«V­ !88˜ÀÀÀ2C‡ªQ “ÉĪU«èÚµ+~~~ÄÄÄXçxrr2nnnôë×­[·’““C^^7n¤M›6´mÛ¶Æ2Au bÞ¼y6sÜËË‹©S§òàƒâååÅ AƒØ¶mÙÙÙ°mÛ6|||èÔ©-Z´ $$„uëÖQPP@VV›7ofàÀxzzÒ§Orrr8|ø0z½ž¤¤$:dS´G¥áPTTį¿þʈ#PÅj¬ŽŠŠ"++‹–-[Ò¶m[Ö¯_o[¶laРAxzzÖH&¨.;wæµ×^³ÎïyóæðØc1mÚ4 cýúõäçç“ÍÆéÛ·/>>>tïÞââböïßOQQiiiìÝ»—Ñ£G[Ç|ìØ1.^¼ˆ^¯'22’ÄÄDFŒQ×·«Ú¨æÒpñâE²²²x饗Êìûâ‹/ 0oÞ<\\\ˆ‰‰aÁ‚Öè‰Ù³g³xñb¢¢¢ÈÈÈÀl63eÊÕÃÚÉÌÌ$..ŽÝ»wóûï¿Ûì»õÖ[Y¼x1wÞy'/¿ü2óæÍÃÙÙ™ØØXþùÏâåå…——Wd‚ê Õj˼4 ÎÎÎÖ¹Ûm·qôèQž}öY<==‰ŠŠâ™gž±Fº<ðÀ¼üòËœ9sÆZ<êÙgŸÅÙÙ™6mÚpÓM7ñŸÿü‡;wKïÞ½UÃz%11‘´´4–-[ƲeËlö½öÚkLŸ>ûî»… KNNEEEÜrË-899ÕX&¨ŽŽŽ6ë©e¾[ŠX:;;sß}÷ñâ‹/o5x.^¼WWWZµjÅ´iÓøøãÙ¿?çÏŸ§sçÎ <*È]ºtá•W^¡]»veÞ ¢V ©6EEEÖPÈ+iÒ¤ ...Ö–#GŽÐ¼ysÂÃí¹Š¢PTTÄÁƒ9{ö,Ý»w',, ëþœœ¶mÛFaa! ¨õ°¬ââb²²²ðõõµ†O˜L&bcc9|ø0M›6%<<ooo«€UTTÄÑ£G‰ŠŠ¢S§NtïÞWWWë˜ Øºu+YYY 4ˆÖ­[Wºh‚JýÁ’RXXhw¿¯¯/½^Ï‘#G8}ú4aaatëÖ­Ì|°xsh3E!..Žýû÷ãììLxx8ÕæíQXXˆN§³ÉÝÐëõ?~œãÇJ¯^½pss³Ž¹°°;v’’ Aƒ¶æÕ*ŠBrr2{öìA£Ñn~¤Òp0›ÍäææÚm×âèèh­Ì^PPÀŽ;HMMµ;’’’Ø»w¯u>Yç°Ñh$::šˆˆüüü¬žÙڜ㖊‘…SQt:{öì!!!~ýúb5æ(ŠBZZ»víÂh4Ò¿‚‚‚¬ù]¥ßÞÞÞ„‡‡Ó´iÓZ³ÊõÁd2‘••e·ØŠ›››µËAjj*»víÂl6[çCmȵEzz:5² ö–Ž ;vì ¨¨È*Yæ°ÙlæìÙ³;}ûpvvfèСŒ9òšÉ*YYY¬Y³†ÀÀ@ÆŒs=êkŽª°^#øðÃiݺ5ýúõÃl6óþûï³~ýzš4iBïÞ½9tè .䫯¾¢}ûö5¾¦ÉdbÛ¶mœ={–¦M›Ò¹sgrrrX¶l¹¹¹<ôÐCµþ=õz=ß~û-+W®äùçŸWËÿ8|ø0+W®$88˜nݺqúôi^}õUZ·nMûöí å÷ßgïÞ½lÚ´©V®YXXȯ¿þŠ““¾¾¾„††ÍÂ… ñôô´6Í®M²²²xï½÷8q⯿þúõþ™UêƒÁÀ¦M›8sæ íÚµ£]»vìÙ³‡gžyÂÃà ä×_%33“·Þz«V®›Íÿþ÷?Ö­[Gûöí­×]°`Ÿ|ò ÁÁÁ×äûnܸ‘·ß~›G}ôš7Uêùùù¬X±€®]»Ò¦MV®\ÉÎ;qwwgÀ€˜Íf¾þúk5jÄìÙ³kåº.\à³Ï>£E‹tîÜ™–-[²qãFâããyã7lzf×z½žåË—ó믿ò /XûµªÜØdeeñßÿþ—€€ˆ³³3Ÿþ9›7oÆÃÃ~ýúË’%KðóócàÀµrÝÂÂBV­Z…³³3~~~„††Zsª½¼¼jí:W~×eË–qúôéRVQµ‹kHNN÷Þ{/#GŽ$??ŸÔÔTxñÅiÓ¦ S§NeìØ±œ«ÓéÈÌÌ´;÷´Z->>>v-ú¹¹¹ 6Œçž{gggúõëÇÂ… ‰‹‹³«°æää”[tÃÑÑ???»k³V«Åh4²aÃÞ{ï=î»ï>¦M›¦ÿF˜L&ºvíʼyópss£iÓ¦,Z´ˆÿþ÷¿ 6 “ÉÄ¥K—ˆˆˆà¶Ûn+³&çææ–[œ®¢¹—””Ä#<ÂäÉ“Ñjµ„„„ðÑG‘••eWaMKKC¯×Û½Ž›››ÝÏ”–U¾úê+~ûí7.\Hxx¸*«ü(((`Ê”)Ü}÷ÝFòòòضmÿú׿èÔ©:ŽÑ£GaW‘LOO§¨¨Èî¹]]]iÖ¬™Ý}&“ 777æÍ›‡¯¯/‰‰‰$$$[æ:&“‰´´4ŒF£Ýs5nÜOOÏ2Û-ó8''‡?üK—.±téÒRVQßJ×Úµk‡V«ÅËË‹€€ ƒUp÷ôô$00°Ü ºdÉ.\¸`wßĉyðÁíî !44'''Ú¶mKll¬Ýc“’’xíµ×ÈÈÈ(³ÏÅÅ…‡~˜áÇÛl·3?ÿü3kÖ¬aìØ±ôéÓGµXþ iÙ²¥5²E‹xxxбcG«1¥yóæ4iÒÄ®á%55•þóŸv‹¾899ñüƒÑ£G—Ù§ÑhèÕ«—U9ðòòÂß߿ܲîGŽáƒ>°ûÂñööæå—_&$$Äf»³³3|øá‡üù矼øâ‹×̳¥R¿ µ ÃÃbŸ>}¬ë`«V­ptt´kx‰ŒŒäý÷ß·[ô¥qãÆ¼øâ‹tìØ±Ì>‹wË¢ÌT޹víZ«§ìJZ´hÁ;#«««Ív­V‹““{öìaûöípÓM7©Êêß GGGÂÂÂpwwJæx¿~ýpppÀÁÁàà`í®±7näÛo¿µ{îÀÀ@Þzë-»†Ç¦M›Úù„ƒÚÝ×·o_^~ùe»û´Z-½zõ²¦WT$«äçç³hÑ".]ºTfŸF£aöìÙL›6­Ì>gggòòòøàƒX·n ,¸aeõÍTy衇Ðétv÷U”_t¥Å¾"ÄÏϧŸ~Ú®B¡ÕjiÙ²e™íf³™¢¢"öîÝËÔ©SY·n]¹–)•òðññáé§Ÿ¶[ÝN«Õd÷sÆfŽ[¼\åÆK/½dW¡prr"00°Ìv³ÙÌÅ‹qrrbêÔ©|ÿý÷Œ;Öî±**åѱcG^xá»sÏÑÑÑîú âù/_§Õj+ô >Ü®â â°—/¥( f³™-[¶0qâDÖ­[Çš5k¸÷Þ{ëúgSi@ <˜víÚÙÝçââRÆPbÁÉÉÉfN_ÍP2cÆ ¦L™bw_yÑff³™ÂÂBöïßÏ´iÓX·nS§N%<<¼®6•Ä]wÝÅM7Ýdw_Eéöd•òÖñFñÄO”EPžìa6›¹páÎÎÎLž<™ï¾ûŽÑ£GP×?[­£*¬õggçr›º×–Üò@•.Vž"àììÌüùóéÞ½;/^ä‹/¾ K—.xyyÕõϦÒ@Ðh48;;Û-°QÑÜ«*¸¸¸”«4Ø»¾¢(´lÙ’… âêêʳÏ>Ë7ß|ÃSO=UkETn|ª3÷ªƒ££c¹óòjÅ=æÌ™ÃÌ™31 |ùå—Lž<¹Ü7•+©ÉÜ« NNNå^§¢âI®®®ÌŸ?Ÿ®]»rþüy¾øâ ÂÂÂì†Wª¨Ø£ºs¯ª”÷¼h4šre~EQhÕª .ÄÙÙ™gŸ}–ï¾ûŽÇü†“UT…µóõ×_owßèÑ£¹ûî»k|ŒŒ >þøc²²²ÊìsvvfÖ¬Yvcí5 mÛ¶Å××—G}”ùóç³bÅ î½÷^5¤L¥RdeeñÉ'Ÿ™™YfŸ““3fÌ`È!5¾Ntt4_}õ•ÝàÆóä“O– ¡1 xzzÒ¢E |}}yàXºt)áááeBäUTÊ#66–/¾øÂn¤Œ——?þx¹Þ©ª°wï^V¯^mw_@@ .,#¼(Š‚Á` mÛ¶¸¹¹qß}÷qüøqÞÿ}žþy»aœ**Wò×_±råJ»ûš7oÎ+¯¼b 7® ¿üò 'Nœ°»¯oß¾<üðÃe¶—–Uüüüxì±Ç˜?>?ýôsæÌQCƒU*ů¿þÊÑ£GíîëÑ£O<ñD¯¡ÓéøüóÏIMM-³O£Ñpûí·3~üø2û 7¦E‹4kÖŒû￟·ß~›~ýú1tèкþéjU³¨Ç<÷Üsv-óP{–K.\XnÞHe^4Ý»wgäÈ‘|ûí·Œ?¾Ü07•Òøúú²páÂr£ÜÜÜjå:Ý»wgÉ’%vç¸F£©”`>jÔ(V¯^ÍçŸNß¾}Ua^¥RtíÚ•Å‹×hîU†qãÆ1lØ0»û´Zm¥Þ-Z´`ÆŒ¼ù曌1‚#FÔí§Ò 5jƒ ²»O«ÕÖÚ:>wîÜrs +ëåêÑ£ÇgùòåL˜0AMñP©÷ß¹PkËÃÚ¨Q#^zé¥rå¡òBë¯dôèѬY³†/¾ø‚Þ½{ßP²ŠÃ¢E‹Õõ nDL&ŽŽŽôéÓǪôéõzéÒ¥ n½^O·nÝð÷÷/sKþ‡½¿òƒÁ@Ë–-mò™ôz=~~~têÔ©ÌñZ­¶Ük¸ººÚµ@šL&œœœèÝ»7îîîhµZÂÂÂ0¸¸¸Ü° ß*¶ãããC¯^½¬Û éܹ³µBÉdB«ÕÚUò´Zm…sÜž§ÞâêÔ©“MßK‹§È^Þ«ƒƒC…sÜ^8|qq1Mš4¡[·n8;;ãââBûöí)**ÂÇÇGíQù7À2ׂƒƒ­Eì@Šc 0ooo ÄߣG2^ÌêÌ=³ÙŒÙl¦G4mÚÔ:£ÑHçέÛJãèèXî5,}¹í]Çh4Ò³gO|||ÐjµtêÔ ƒÁ€Ùl¶¾§Tn\JÏ+KΛÅ+9xð`ë¬×ë  S§NeÖåêÌ=“É„‹‹ }úô± âf³EQèÑ£‡]!ÛÙÙ¹Üë”g±'«têÔ £Ñˆ««+­[·®ë[ r±Ì«Þ½{[óM ÞÞÞôîÝÛz\aa!;v´+¿VgîYÖ×Ò²ŠåÒ®]»2}»-éyU‘‡@doooºvíjgûöíÑétøúúÞPé¥<×šŠŠŠŠŠŠŠŠŠŠŠŠŠJ¢6¢RQQQQQQQQQQQQ©—¨ «ŠŠŠŠŠŠŠŠŠŠŠŠJ½DUXUTTTTTTTTTTTTê%ªÂª¢¢¢¢¢¢¢¢¢¢¢¢R/QV•zÉÿ¦öqÙäiî%tEXtdate:create2020-10-09T19:38:14+00:00ʺŒ%tEXtdate:modify2020-10-09T19:38:14+00:00m—0"tEXtpdf:HiResBoundingBox1396x1123+0+0x{JXtEXtpdf:VersionPDF-1.7½8;í(tEXtxmp:CreateDate2020-10-09T14:37:22-05:00o jÜ6tEXtxmp:CreatorToolGL2PS 1.3.9, (C) 1999-2015 C. GeuzaineÛ©AJ(tEXtxmp:ModifyDate2020-10-09T14:37:22-05:00ÛòVåIEND®B`‚blis-0.9.0/docs/graphs/large/l3_perf_zen2_jc8ic4jr4_nt128.pdf000066400000000000000000000651011422157504600234730ustar00rootroot00000000000000%PDF-1.7 %Çì¢ %%Invocation: path/gs -dQUIET -dNOPAUSE -dBATCH -dSAFER -dAutoRotatePages=/None -sDEVICE=pdfwrite -dLanguageLevel=2 -dEmbedAllFonts=true -dOptimize=true -dDEVICEWIDTHPOINTS=1396 -dDEVICEHEIGHTPOINTS=1123 -dNORANGEPAGESIZE -dFIXEDMEDIA -sOutputFile=? ? 5 0 obj <> stream xœÍ½O-9rŸ½ïOQËnSJþ'^X€,Ø–a[5»V#lhZ¶F ûÓ;~¿ #ëœî[uç..ÞWî)^ž<™ù$É`ðÉy¹^ÓË…ÿÿýýÏ?¤üúÇ®—ߤv½¤²ºü¿©•ëåOÿðÃ~±|¤ôºzz™}•×–^~þ!÷º^CÉwtµÕåï?<Ô9Ÿò:Ÿi/ÿç9âºÖ•_ÿÇßþõ©–ùÚfhu—Œ”_Žåm—YË?Ç¿GíZ'§Þ^s<<„vXäÍœ?w+8¶¹ryür¦ÿ凤á…ÿùýÏ/ùÛþâoÇK¾^~û‡ìÚÈÈéuâ7”õZJ~ùíÏ?üîÇòSÿñÚÿ÷›Tóx½ÖýVÜúßýö?þðW¿ýá¿=¹L£¤×’J¸LoO/K¹^åxc-okÉ ñ:KhËKb[§–·kí¶ú5_S‹m±äÖÖ®µÛ µÎ-sÉ¥ˆmyIlëÔò¶b­pûåü:omYɽ-¯uÚ:µ>z¡å¬äkâ®ÃOv¡ý*þ&¥—Ú^n€¿—ò®ðuû—úø/uÚ?õǺ’ýÓ|Çüî%u×ßÉÿýý‡0{í#ÔoÏîÃw ?¿ ß·ó+ç4ãœâ|þ'¶žÔÕ_ë(vRÿú'AUNKýñßÿ”/çê?þÍOézmµ¯ÿËþ×ÿú“\Í^Fýñ Œ½Î4Ò±ÿù÷ÿsæO?ù?ÿƒ”¥×Τágˆ/sRm¤×kÚ1ÿë?Êúù¿Ÿ*EÿŸ®•]¥‰G¤6"OÃ!÷Ó4ä4®×¥·ð\¯µKÉÈKUüaæùšÓ’‚•^ûBIï¯KNÓœ]­R².¹MòØòkŧV­r*ÇËºŠœ p¼fÁÿX×FÐLºä¡%ß¹R•‡aÓipT)™ò EKä¸êzYùJJJò ÎRE z]UKð5EŽvü™“KC…ÊïÉ­ ±«ûw¹a²üY¯K®Jäù*·ø’ë¦Q2ä8äÁQåÒ.üœT¯…ÛlÕ%¿K¤V9ùæ&çGO‹<µå’d)‘#(Z§e9Ôù5iTÃs+Éáj•~ÉáL<£úkÒfz•ÃA&'J¿¼O9©3P÷¶ÜCr8rú¨ÖÕ¤ÑäpäD´Kî)‘3e§wʵ@3rëØOùx“s‹žôì¬T^å»§œÎ¤ß+zÉ©˜5ñKO*w1J.û¦|Ií†:cèŸ}ÊSðe¡-´‘å}½ä4ÌÙô4ä$áMjdÖ˜r RCθÕÈYŽCD.¼v”9÷ŒÛ|-yÄâåri±–|›~¤Hß×´†Erÿ^_µ &tR 7—¶P[Ãí»–ü·h\\ùr‚ô^ËM EN…>ò³]Gù{ÙWvA{â3[“§ß¸d  O¡ß½ÔëüÿÆ`zà—í*7þ„ ;c¼ê ÞüÉŽðMœ³à›SXk¾9ëÀø¤J1†¾)%Þe„o¢½+ú¦Ÿ"ƒïºäß[„ï’û³ôßÄU°žüÉ£B.dü]òL4êÉŸ~ªGþ¤dx ùC<[äïêŒuç?ö*À«é=¼äöI=ˆÛ:•à%ß¾n&¹z^r Øïr¥›ç1@4cd;€—ܵq1®Ô~Ž^2ˆÔf6€—Ü"sE¥Û’¤ƒC'2á¤Ïˆ$îÔ™”’ËŽ†LJ›õÿÿûð™î|Êý'ç:ò™–ý¨<¼ô$@åÈKDtÈãìŽè3RW@tÈ}]#¡#WÜèPýêØ=Î)7qý£4“•Fäá‘¢¾Ü¹5 :äʦ¢Oøk®È'N†u-Îç»URΧœƒùšžs빉§<Ù²]ÇS¾ù]ÿ8§SxÊÓ/;°†§üùI3à)Ç[ïxʱ=â)ß^x~‰gjƒÏ!â9ÑùõÐ?Ê÷ÇãYFÃ9;xÊW;{ާ^%kxÚ/tÊg–}·ã)Oõd½é”ïnvÇl:/¹™Ò tJG{ÙCÑ锳¥Çél…„N=Ç5Ò)gKî½é,~¿’N™©.íéN¹¾—=¨Î&Ž=*çDyE8å Ëã$+œ×#|©ã2DøäÚá›2:Í7ødLøzë—Ü‘zÿžþQˆÕŽk÷ò_»®NŸùÖï|ò·ÅŸœñ:|Sz1»-¾‰Çà >´šoýãÄÈ¥Gþð‹¬÷qþðóó  Ÿª à”‘oTù”ܼ#¸ä·q8J16+-(ƒ-Ž|7€rÖìQåâ²Xí®d2ògc…ùÕӛÎù[¸:7þ®Ä;~ó·Š£äü¡$â'=ü¸÷Žú ÚŠüÉàÝ*»{¼Ç)@œã€:"¼Sñ©|ë1HºfpM ó'C~ö ÎŸnZäO>£Oö à’Q€ àÕ80<Êgm°î®±pÖ4øåq¾RzÒGΞd·¼ôV>z¯bpïêœOyÇÏøäôËñ»z͉‡Ýi}—„¸›—y!ü½#o·ô‚ØŽíföŸß8~WdP6ñ¾¿k¿¿{¼\¥LÀÆøË³Ëƒkßy['2çmÅÈœ·ujy[±ÖnkGæv[!2·ÛÚµv[¡Ö¹u<2çmÅÈܹ἖·k…Û‘¹Ó։̅›—µN[ŸßéR_ßeüî#¸¿½ƒ÷î·§÷áøçwáûv>«ÒU]øùÄÄþõÿ~4V*ˆàã¿8î*<^:ˆÍ6,uèÔCÇr:Þ+ £“i]¸Î›KC·¬#n]xiò¼½tr˜­Ã.Ý`µi§v«¥„®GzÃdcù2äiY“ô!6G/'DÃú&HŸ>íjŒT•™ñh’^¶±Š-¤$£sÖVй˭¶Šô: .KŽ ¤UéÈ.+™ #¡U=BOQ/t÷Bq­ oIe­&|®¦%Ò¥O¼Š…ëj’SÐ ¢dÅfÎÒ³éÇW“RgKUºÚW æÖk–“‘Úê‰sûš|DÀKF:è¯ENJAÀëâD§–¾ð˜X¸¥tœT«ôêv÷Öj¡Æ…™Âµ´£i+Ð S›L·ä¤]6Ĭ­k gdÚ8¶v9ÿ/ù™:Z¨]¦J5[É¥íô¡1µ5»Í*ŽÏ<œ}=º!£®Ž£jgRÇjˆhà ªN9#ICZKŸY2‚Ëz,¹Þ:è®2ÆÈCjXà¬.DÔ—þ‰Èþ1)hò,Ä´äG-ñ2"oòäÃW4Lã«V°±HKˆ’+È…[ôZz”òLh`mjA×Q Ž|´{œì Q±Ã¡œñ•o ÊaëU Ž×uã07ý’ᬜp:†2ü¾ì3¤Pª4F eÌžmìÚð; eTzÙ8Ë)Ôáš})¼ä)¡·Ì¦Eå3áD<²×¡tZøi‰¨§NÞBýnËn/L-R¤ð’£7 ¯lÑÑ á%?ªÝ ¼dú¦ƒï áU¼ŽCˆNUã:ÂT8p/û„ˆ1©ý$xɃæ‘@eÙbÂ&ð’G£ýF'0íÃuÎÒ¡í&ðÂÔ|Dq†Úˆ ^rv¸á5ÍÙ&†ž7…IŠþØ&¹ÞCÙbà©“Ãb™®‘Å”ø³Æ$3Ol“°Gœ_½ù6‰Ï„Í#ÂxmE q¶´Ó:7™?ëïþrPlÏËC7©½YÄóâÊÆsÈÕ× àæAíl@Gm‘NĪôÌo<ÓÁäÆs%ι7žÑÐðÄ¥µÚñDH}:'qÚ·9SÆàv:6žc^¶Œ´ñÄzŠvAާMöJÄ£éœ×;:¥aù%9Ð)“²bó§S†\Ns<5dw.ñ”–“×q<“÷Äsbá%G<-ò±žò˳âC¨<|õ–#¡sa‰ªB¥Y^J'T× ÖPy¯i„Ú ÕuÄ+ö‘sb¼µn€f®?9 ÒŒ?Þ¨´³,ìâ„jXIã9›PLºípH¨ÆôÙï„êéJ±·ÔxÚªÐK~g/ЩKW¡Ã”V¦=ˆœPie’sG‘‰U¢ÒL²@Ø!#*÷~f.'7éO>KäÝŠCu¯sfÙïëœOyÇÏ||fÞíqf¾KÂŒÚË|úþÞsê!· âQá8½$´äeÞRøûÏα;Æfç)ýòìüñ’uíGïÙ5Ï.‘Ü#uÜjy[gÞímÝòfØVÈÁa[±ÖnkÏ»w[1oÆÛ:98ÞV¨unŸw{[·¼™}Óí¶k…[‘óîÓÖ™w‡Øspv[_‘]#{Mwúþ&ç!þí¿|¿=½ ïÌ?¿ ß·óéÉy—>­öõ09ÿ“°3~ü§Ÿ~}jÞ/[‘Cê8¶<_ûäÒ9žÍ= ‚•KhXí©w Ní{F`£y„u›–`ÙNÃø6gíݹ®P_|’y\gë;š~FÆ*:rCo ý.ƒ{¢#‡dõ*6tI·©Û^å¹”“ Ãìh²5PGFKÖN“qñ³ž¾ÒÛÊÆìàšGï2Åà-ËÀÁ~yïš¾#·~ã·Kûõë8»Œã§­àØÙSGkÈŒ±^¨Ï¬kV«øÐ±Ï®+¶« .Ðtä %G;ÖGwôY–RÓ° €’yÉŸ™ÓîqÙÌyU™‘è¸v`l¯ù4…£ƒ‡d==Iø¢‘Š#ä2Tûá2:(š—ƒ AŒ,ýACBã##ÈŽøÖƒ­d]–”ƒg8Ε`:u1çUÏÌQ%ŸwÕ"8£b‹gbñvõÀb~ǧ­ŽL‚¸RúðÀ±¬œ¢ÊcƒýE]FÂXÒf»ü~Íì™^E®²¦äÈhS«_X¬Àò²ýè!ãf¬yŒÌ‘¨tN:FÐ\]WA!æŠÁ°Nd¬ùD e ª ¹55%`øäg?ågâõÿÂL}c9,±ô„¦ƒåÅuÀƒåÅ%ÖÙõêo,uå½G.Q¢c`r©1s.µD¯¶s©%:Šr.'&ªq.µŽ ƒÈ¥.M±Ä¸”ÁØe13çRŸ$:$q.ç”ÛÔ~:¹”¡ —´œKL_$Œ\êxÖŽ‡\Êw5 Á8–š^GP K‹*m©l*åCÝÆ®JåD ‡ •2ï°´¬ å%GÒS„òJL5ÙP^H{kÊ«2$±¡DîŸNÉ6—)‘Ë ƒ¶—ˆ‘Ö—#M‘K„6Œ9ç¡ëÆåJfäò’y‚açh^e:ˆDq <9šzRJDÉ::àÙhj†OhâdŒÑľ޿5Øh^7éFŸRB6š'™/Ÿš±‡Þ³â® ˜¢D“k6¦]n‡R#¦}ñA0½pn˜f‹7L‡…±¦Ó.ÚÁTº¢Ôn˜&Nɦ2¥Î7Jå¶5rœRMU‘Ò!ü•#¥*X?è”,—Þ(ÅT$ÇÞSJ*ÛqJµ$BŠu‹Ê<„:¤ˆ;Ì¥c¶)òfÊî:çhŒGnHå^³µ§TÚ6ùvJ5ÿÅz4Rª¹"9@ªQÖJ‰…KQý…z´ÎèÄOÕ3îŒJI?‡Q gÌØwα.»œQÍØ±Û›ŒjË=öšŸc=Õ±›ŽŸœÑ ¤ìÛQý„œQ]ž±AFåC¼”ÎèœŦÀ¨|ªÛ-áŒJIåCŒj¦±NF¥»Ÿ=nÖhMcö”}önIg㉠¦‘\rð^çL¿ß×9Ÿò:Ÿùø”}•9n{A˜f³ÈgçÏ=ÉN2¸¡þ·ÓhÉÞLã}ãi::kàöçìy¼JÉ-©Þ¦YO¯ÊШc¨åmù··çßÞÖ©åmÅZ»­=ÿÞm…ù÷nk×Úm…ZçŽñù··çßç>óZÞV¬î>οO[gþîYÖ:m}~–ŽÅš ÁÆïpšþÊßÞ1ûÈôÛÓûðÎù/Ü…ïÚùô4kÖ1y®ïYúÿþé7r•®+ÿ¨³uý_?ÿ$ȵ¦.¬ëÿúõ¼n1iÕfð]iÐÔÐżf¶ãáª=…%¯IÉLš†0¼F°e¸ÍœÌÒì«RQ'ËiŠÙÕ-oÝru%2Ù˜>“døÍ”éi[tĦc9é25ßKþ—eL'™féL—X4 &÷ÿ²’Δid·iI¾˜2-]¤.Н\-eËøV0-%,wFeNn)aØ´¢=› ý-c:Ëáh´Ê²Œé‚er-©Ås2¹œ%“gÍ˜ÆøJ§x«%˘ƒ.ìËDXsŠédlÓµøÞž-cºÊäB»C™ãN]½¬ƒ H £»¤b86™f³µÒh ba”€åË&'ÀN…nQ@æ-c‰#qî­?£9¹EF?„Õï®U–]ε/§SoÏô¿.ä‘K‰\3˜JIÃzØB‚›×±|rZI*EWÿ ãRb)suk'§K“ª­nK´ˆY³ œ÷RÌiIÃ~gºŠô3˜kãÖ´ôÑÒõp¦€Ä†«þd™k[B¾T=š)Ÿ–„Zõî\S®§å{·¬ƒ‘% šÌì¶ø·{€¹>´Ô¨ÔÅÖ•“9¶›JäZÞ¨ìÜû´©Ä(ëªJ ©4þ°©ÄÚ˜®‘:•?O#IN¥®ä̰œxØ·ˆ¥®Ùˆ¥.jºÄRKF RžÜ åTêRSŠXj£›XjJ3KS¥Kµ„ ÇRëÌ°Ô ^»_ K9f9–RÂXêB“m—#–RbùßN¥&ýê)v*u™ÐvJ)áLשÔ3šf R£vŽIåÄ×È%•·Ð8Šc)u–-[:–ºZV•RÐí‘åTjhµµ@¥n2JJ©Ò,¾èPjâòÊʩɿ%@)%Í.žS9±ÎW”ÂAå7“RÀÔ\gRó‚G LjjÇŠPÚºÜPZïR•–`Þ–ò£¸¤»ûj¤§ôò©é{€T¬Ò‹Ë…Ò‹ú iîö89>}Ò¡·Ü&Tæ†{Ü„j÷{#sÍ|#tTfœmBqvÏmBeª+½‡Py>ØRGtØ2^@Ï뀢Þ{mD‘™[#¢˜‘j¸a#:z·óA©Ò+"Z;WGYêúrDÁO=§n¥©wF+7°Fñ/7F‡'ËoF1‚ÉwD™`r-v{B¥µÚ"¡Ø›g]ý!4{WêˆÊý=bÇ)çoxOåˆæ}ïnF· 8£a®ˆ¨nî‰ý¦&AòCDOƒ[Ç©©“ì éD`l6¤X9ÎRœ/þBŠN‚ ;¤Å7+nHåÀ1!Ȳð÷ž¿§TÒum—\g×{0{¿ÕðOø¿?ÖÿøÌ= -1ÖÇ9·–ì†ÿufíY7ßÚ`É­+;íì¿¿µÂ"MäÌ|yöþ+kìO®QÂÎðûêù“«‚°Ö½[ ³r¶t›»kK¡[ºÕñ–ΜÜ[Š3wkéÔñ–b}¿ì9[ºÍÛyí:léVçÜy>ß-…Y»ß­^g·ôù9{ÂFYÄî¾Ã9û—É~{Çê{’ßžßy7ºŸÞw·6>ï€@8¾¬LÖÿõƒ“t9èÊ0Ö@×­?cj‚˜. Ù.·Š4RtïÍb¬RÒ5C ¬í³NX¢ÍìVX‚Y  ;uÞ.%F<km@–ºfÇÊ iÒÝ 3í¥Kï‚}G¶lÏcáôb)YÓ{°d1í…Ä:>iu##Öâ}'^BîÚ²]Ö$toÒNN—·ƒÅ¾jÉõÓ~„eEK׸¸E-_–Þšå+m»ž\=ž‚ÌGÛ˜B³’f;lSÖãÁÙö˜âl¨Õ?‘âFäÙnÜ‘êŠUõÅ ûûP4E¿²÷̉ø 0uÐo[™•DÝÚ<"‰:§!ÇHœ HÔOuóóAÔ99°¨uìÉLçRÒQÜ|ˆVªw ĉ -Ž‚¨‰~@´ýÝ)€¨Cû6‰:ÿ®3 ¨3{; Ö¯Z^>5T6üò[™øðÛT^±ØTæú®‹ÄÊ´ýv§ÁÇY#•ÊûˆTl…è‘Jdú¬±ÄC²÷ˆ¥®íºÂŽÇŸUN嘙w¬c©FŠ±Äš7ëK$eÛ“Ô±”ûÅŸüÄrïÝÙXߘ|°Äý}ÃËÈìcKèlFç\¢]/!—¹ÑK±¹”) ïlåR)r ÃûH} Ì;—‰©)ÑΙ"˜8{ìÐ7™—ÆÉÄ:åq ÁÄ~…v³r ü€¹ïu#S¡s$kF)'QA¶K2§ÜÞ%ꆃ´;Q’9/N…7™˜¯™ˆ¢¤uÈÄé¿J$ ôvÃ8™p"ÌØIj•u"F&xê»I¸‹à:n©+í›—+¤Ü8˾ôµÎçN­gŸûÄ„œ†Èó §DžÕÜ^æßqj¹.»ÄÛÖ NK,: yAhçÛº%z¡Yþ<·äùMîJ<îíée2Wb¬µÛÂÀ·ÔØKnmíZ»­Pk·…] ½Ç¶Xrkk×Úm…Zû‚ÎaE¤—ĶN-o+ÖÚmШÏdÁ­%¯³:u>ë•lH­¹ò¯ÏÏÓ/ÎÏyæ^>4§ÿ«ä¯!ÿöï3Àߞ݅Ð?¿ Ûú´]²ë²^ý¢]²ŽÏÛ%å3vÉúçØ%±„#]òÕ ùïåB}­`²#í&ÐêHìÑáÓ‘¤¦±.wøôŒQŽF®)ñée2TìŸ^1JÑ…7“øô¶U0”øtXmÊ6‹Oo³ø•Y|: k”ÜuMdÙ–»Ž Ç-wã½Äé/,>3ÌZ]Å\֚ŧ›äæ[âÓá²A%>;ÇR”Lv ~k9|ºLú9  Ã§CRw2ôLœVPá3°·×FTø ö-ôB…ÏHî5p…ÏÀ šQá3 ÆifÕ2…ÏÀ–·>#unt‡ÏHÓ¿Ü>RÐy¡Ãg¤±­“æð‘Cà.wøh3âPâ3°n¤³F—øèW™^Ši‡¹ž.ñØb9¢Ägh¶ktM¬Q™õŽ)áJ«K|ä—s‰K|†F”Ì'iŸ¡.:sfY^çH¾N‹ÏÐ}ÌzÈ´øè‡ìpÌâ£ÇgÊ“øèÁØ©ðÇ“.ª} ²p¨DPðegüæ@™¹ô·¡Ä€À˜J\ eB†o P¦-u(e–â‹>„áÌÍ“=ã©™”‘¡]cÜù,Þ˜”‹ÇY»!™å¾áŒ•HbU1ÝDU‹8“ؽZReqâHæé3g2Ÿë;“˜|”èÕ’Où&”ZR£W«çÅÉ=™”®ñ9“[}[ô¾JÏŸy&Ȥ”0–hHvd õ¨Õê2òæ™0$µ€ž;C²ãÕ@¤Té48’ÈŽMÆ©"5½;µ@d/¾lj”W8’È^|ÖãDvDCÍ—G";S“¿Â:Ù±ÉböŸòœÐ£Ú|bUGŸ´›O$û[é|^ƒD-³Í$‚VÁ¿™a;v]äŸxZØüÑù„SóÖgê~÷µù¼*E5‡Ïâò9 t»Š-3šïôrY,ËÅe‘'[ñ,üᄸÆn”„¦æ!#'aërœPì¸èwBSì3;öóÕèeÖ‘ŒÍeOd%X¸ÁùÔ35"Ÿ× ÒI´pïÁ¦S=@‘Îä[†6«éÏ´¸Ñqã™`£NO`c)·iO†M'ì9ö—}ïkÆçîÉï/Æ÷äßà}øÛÓ»ð=ôÏïÂǶ¾Â@)#d¤¬jØ'ÄÍ>/¡ÔˆÙjÁ®ÕÕœ-”NUº]K§œÉtZf×’! ×k\°%#úã]°ÕfÄ3Á– R¸´å‚-ÝI»‚`KÆ î©£`«#·#ÃVÇúg³3lulǬf˜4Öbo†­WùeJ<3lud˜h‘†­®;êÍ9iŠ­Ž%íz]±Õ5¯;*¶:¾!G^‡!ÞLSTl ýµHQ±5._GuÅÖ¸<-Ç[r’êÝ€70ö5¤)¶4T¤“!Wli m žpFÔPdE–¨Ø2̱+¶4JfÖ9*¶¤dx‰9¶4nV¢o`4k*M:¶ck`ðaHÇÖH¸bk`Ù©˜zÒ[û3é–)¶d8ÍPŸ+¶FÊË…Z¦ØÉe©Tläª3Wl hñª9(U±5°3«›sË[o†¨ÑJ©¡¶bÎ;SlIIôkäY'´RÊØtf·(Éá2¹Û¹LWv É¥ŽÚKä2aWO´ÃꬱݸDÔ¬EñÌJl·c‰(šÞCËì[SKl3»ÉaµÊ¸a‰¥ôyÃ2#ÿ%Šï4*¶jÄ27ædo,õ=L3b‰ÈYvØŽä¹ÍwRBµc©ŸÊ-`Ù1g¹¢V#g%bÙËʼn¬cÙ‘•9‚˜RãbÖ0±´0XÀÒ‚^9`©A/“ÆK­Cä K™ Ó[ãXJ Ÿ˜Ž¥–Ø$–2_¼¨Ý#–½xD±´9åXª?¶Jã²#‰aE9eÇïÕhsÙ+–+pÙ‘·¢í8—2aç;„ÈeÇM?£úNc\:É —oÒ¢­Ò¸ìµrÓ„s)4þNçR?U¢/Vêd‹G~…²CmZïý'6-´ÈéÅ´œî3Scp0…ä2GL/ßN±1EÇÜ¢ŸÒâ¼ë†éàcÆ9EÄâ&qîX{)-pªçrã41Ƽ9Õ§Ñ«’KN¡d0×äæ4»§Ø9Õ8Lœ¦N?ÂæTƒ­åÆi¥ñpz¹7usz1'nsŠ %*¥:SjCÚ· Hó´‡î†´ÐRôDOÖÙ©Æ8ãy¯§âïkÏZÏ>÷yIåù†Sr&Þ^vf»$L½]8Žv—œ¶¼ì´µK¾ù4ÞE•_œÆDTNÅ‹·„‹'—ÊÄ‹±ÖnkOÐw[1 ÇÛ: =ÞV¨µÛÚôÝVLÂñ¶NB·jí›hOн­[Žß|'¡‡mÅZ»-Ÿ¢ï¦Î}·´Óy¼¡¯HÕ1Iå÷7‹ÿõoü>cüíéMøžûç7ác[_¡ªDW½žÍâ?g«ìP1·|[º€7ÍMi¾-û3p™oKºâEë}[:ˆ6ñ}[úÔ½Ì_i¾-émSu[Òð}®ÛêHAQ·Õë|gÅëò ·y¢û¶¤ƒd*‡û¶z³]ÁÇ·Õ[çZ¡û¶:<‰ÍÜ”æÛêˆàçh«ì8Ïæ£oKþB÷méMFáVÇnY;·ô_ÌXFãVÇÆsѸձÃ,}TnuäÔšXÊ­ŽÙm•}¿À•[‰ë€qå–4Fõ†+·:ÞxÅ|Rsnu8úr´UøügVŽ‹¯sçÖP¿žYð̹5°¥‹5îÜX]Õ‰¶;·T÷QW©É;&î£rkàzj\¹%³hËrãÖØÂ7n´UYfܬúåè¶t‚_M®eº- m˜µ‹º-©ãNê¶4’aî?ê¶,'È$y¦ÛÒ:ÅÜ”¦ÛÉ_ƒ¶YOëòýª²Uvìy^å†ev¡ÝÆ2Ó«¾±„¼0͈¥.×Õˆ¥ÖYKUæÀ% ìw.!¿Rä%v;—(1zœË˶„.ÓîŒ%—{0¾¹ÌÅ„s‰uŸ‘Kü˜rãÓz{Ú8—i9ÍÎeò÷cl.a*ф׳oÛ\âÛu괹̙–8ã3Œ›¯ÒÒuJä2wî Ü\fúP6–yp5jc™'g­Ž¥XbXJê —:±3ç*¹ÔñyÔUvlj7=±Ôµ®:—)K)¡(ŹԆWÔUj’O‹ºJdè…!˜ÞˆhJA·X£)÷!_LéhJ¾ÚÛÑ´{µ4-(Rš]·3F[¥FEÌæës)ÉMxŸ¶UöËvkFL¯ÝW:¦nª=˜¦þúŽÒ|wÊjhÀD›RÉɦ´òµ,‡ÒÊõêCéÈävSÚ9É?”ÞT•ýZù.”Õ ÓC;¢ØÈj~[G%#šŒž@¨fZÔ¡WâÏÞ„f5À&Oú MþnÙM(’fòД¹cÅEÒŒˆN(¢«FBSõîÌ ÕŒÇ(«ì6_·ž±;¢H®ìQW)aZÊÕFAt wnD‘˜¢!¾Í(^l3ŠlÊ~cíÄ®SÓS´Uvlˆ7—²#ŠÆ-ŠØÉd•r[2“f#ŠvíG9¢HÚ™Ñõ,ŸbºáF4U—^:¢¸ö´rDÑokàr#Šïºnˆâ0×»}6.› »YèÆ8Cy¯'âïkÏZÏ>÷ieåù‚]p¦Ü,:3 /n“PÆã´¿Ã^- ;uìïo>i§¶òÏÚ^óx½\ç^O¯Žjc­ÝÖžï¶Âl|·µkí¶B­ÝÖžï¶Âl|·µkí¶B­}ßìÙ¸·gãû~Ûµ¼­Xk·åóñÝԙÎnèósvWV~“öþöÀì3®ßžÞ…ïYÿ…»ð¡­¯W6]Dv\œ³Kwe‡ýŠ®…®)¸€«_¾zM—.Ùé8Î\ò0Ÿ7w¥æjsâO¼fâ–;¸4mpDw¥åRš•Ë\ºÌb&H:¸zÛÒD:¸d(âžG:¸dÎ?hy£ƒ«#\nÂ-SpÉ”Ÿ’7¸d~ß L7puÍÿEW×èÑÐÀÕõ=š– i®­¢éµÌÀÕ‘²×Í·e.™Ì3«€®>];ᮎÝüæú¢KÆ3zpÔoi>Ý0·–é·tx£Ó×oõeOÊ·4-îf­ì0k™G‹ö­¾|ÁÑí[:‘7žÉ·Æš)Z+Ò¨/:*U¾%‡´¸«ò­ÿXJ%å[C½¤– mò­A±m³¥}k ³·Eû–޶.Ûçdö­¡c‹†<ÝÔ¢}k`ùÚE–:‘ÒuõB×–Ú·4jà>.µo Ü`ƒ%jß’‘]öo7û–´ÓÝýeö-͘tYÚScÅôé| râjܨ¤ûâP9“ÝyN¥nkºQ EQMJ%&º+;ö¤ëHmS‰‘š9îœJ,¸¤¨”EÆxDYŸw$QR£¸R‡‘¦×s$qt9š+í«k„)) eõ€KÔâéÄÉî{‡R“ r„R·ÿs¥îÞ1û¦C‰Ñg‰P"»%Zñl¤9"“˜IØ™q,5!¿G,‘‘£OÖòàk$Ó³f:™Éíø›Ì´]–$SKJ4Wê„cD45ŸªG4»æßD/^OÈ„oM)InÁS2;r¸™ÂÈìÀ1Õ@¦èWTWj(„)ÞF¦L/®»O×/mó=Éì¹çÇÈÔO `v,ÄZ>4Á´TøÀ”:t#:˜=¹ëX‡hH ™2ŸqWj(\ÕYÒÌö^‰f¬oHñZN}N;¤—¿òfCŠlÝÜs -ZHáøuºø¾"§¸º&qtNAžN»7§XÒ506§Å;ÜÍi™ì$6§ÝÕµÎiô[oNóÅœ˜Ã©€`{êœÓŠ%‘ ¯Ôkf¢Zç4ælN£STl©Õ'áµx`vƒŠ—F娸7ç TÜ~7N1Ù¾é+5zvÝzP,ÑÛ3Á9Å¿qã´úa6§™¯LÞ˜fÏ8Ù˜ê2犘bM¼Å´#>Ðkä‘0Û¦ãœBâT§±µ§ÅS_!Ù˜–±|Ã11­nGÝœ–ÌwÏNGå^ç)ú·´—Êm Žiñ— =±W†A·Z6Î ßkܦó·:þ™SãÙg>ë° ­óï0×’0é°¿ã4ž>ÊØŠ—Äv¬,¶Ä’o¯Ë0å—§óðX†_E?ãm:ÿxuÔÏx«ã-iº·'óÖÒ©ã-Å:ÞÒ™¤{Kq*o-:ÞR¬ãwÍ™¢³¥ÛDÞîµS‡-ÝêxK{Šî …i¼µ³kx3ŸŸÄ»Ãòû›Ä™î·Vi~{~ß½#üé}÷®¯1YêžÏÍÞ?+³ÔY{¢.Mts¥Šº:ÞÞ©îRQ—†Æi°3Q—FµéÓSO—%ÍZ2¯ËôÑ×±éjD‘e/n¶wK—t›é5Š,53²ú>>=–êiØnéê•z—téÞ¾Am—Geqï¼9ºz÷„wtõî/tG—LâipGW×Wz[*ºúp!€+ºdïcdUtõ±{-*ºt‚{MÑ¥ëñfÊ0CW‡Ÿ{aèêÓ—ÜÐÕ'ºqºôÔÐ¥Ûú(½2C—.QÐ. C—îá㡘¡KNzå웆. N繡k`ÅÈ•\º¬ŽeKûÓrÓ/Kmüã6t ¬Y™Å†®Õ! ÷`è’¿‹û@ÍÐ¥Ó~ÊÂÌÐ%Sñær@3tIÉt‹ ]¶|Oňº¦ŠÜm†®¡3PsŒ˜¡k`ÒwÔyö§mê4A—–T–¨ K%ªóTòq¥ÎÓã»ã¿ä±Ô•¹Rn V¿7‡>(Ú^ÙÎ!r%¢Æ²c7ANÙŽxïu¢˜|ép£ˆýÔ©FQb1 gQÑJd=®‹º‹3E?¡ä0b®îÚJ£QµZQ*«Ëj¼H#–fJ4æé/-Qd©iÄë†#æ6åóºî€ˆVY]»ã¨‹|#ò(ç–w„ñ£Çˆ&K]£‡<&_þÜîp"'&Ýà„æ8²‰•óëÆ&’r>klkÝÐ,\dÞhâùY£cVuü Žæ•_£bVoÞÀ„ F0/½`³:¼Ìä]™¶QÊÁ¼¶ƒÖÁ,㮲x³Ã``ÖáÝ—ƒ™:6Ìj/y<\VNÄ˲Þs ´=«-¡GÛ³p8¹ÿ\VŸm.a*7.}óááÛjàn®ØQ*ÿéÆå•yOm.w‡K4³D.Û+±Ÿºù.–Ãeæ»uœËìeç2ánY7.çÅë¼¹”Û=²qyM» Ÿ˜, òjZ ’9/9Fʆ”(‹þá¡ÖùÜ©õìsŸ7Yžo8%…/,;&KÿŽŸCÉUüçRJÖ NK,: í‚Óη5Y"êòYÆ×š,Ïor5ã¹poO/“Éc­Ý ³Å¶Xrkk×Úm…ZÞV•§z¤Ó–—ĶN-o+ÖÚmõ¥ÏÐKnmíZ»­Pkߌxäè¶IoËKb[§–·k}Öf‰L·ÖÊ7|Û„ŒK~émùC/›ø÷o?£üíÙ­ø@þó[ñ±­Oë,Uò%½xÐYʨæQgÙæ÷ ³ÄúÂxªd/zÌ¿ÿZ—e)5Ù[´Ý T`³õFªJó®å*èÿ®¨*PYçè²,ØÕnËu¦*kkݨ*˜­Þ´y«&|£‘©*–?m¨df šöûž ªs¢K¶5­ ±¬yñý?®ª0еèÌ«E~–M*èªØwiS%zjݦ,zªšÌd^ ù¾)˽@µaZf=óÕÖ¸Êî^ )q_<½@µ-_ ¨ö+ß­y 66¥H·ü™ÚÒ´@—Zì@;}œL„k,1ÌÑÄC¹¡‰òå†fõ,¥&V¨-ìæhbçŸõ²ŽfÝï„t4UfD–¥ïP–³Y« úÈ&4Ñ2[ðÆ] m9šØ>Q¢GO‡XÑ2«ßl‹“‰ÌÆÁ„»â¦}–-vjfs‡ÉgÞÌËÎ&®Ž}•³Ù‹’ÙR}\°Ù¬Þ-l8‡¿²ÆáÄìÉápB;;[„ó²·†o6!7È76k]|×óƒÅRï}7áF¯eÞ˜½îó^¾Ídï«g:{P¨ßØkÃל½æ’¦Í^“‘çºõŒ­ïu6²×ª¯N(|H|`°—ðµz±ákm¾ë±ƒ/ rúäªZÈÈéÓ÷‰G‡¬Liè Úôõé‘|ð¼ÑÌÄÐÓ"Ø`·Ÿèôõæc\§¯ËsË>âôáµ½vÀN_Ÿù}¯‚Þðaý.‡ájÁ¸nÝàëû/„‡@É:éæ“-²j1Yq¸ª?á6\-º 8"~g(êüu47~x×Q‰Ë«~£UùÝõîxÖOÑèLü†¿Ioㇷ*F‡e»cÖ}‰z%§¯Ïh\×kc¿ˆ8ó•ëú-+, l¨å]² çÎŒÛegŽïubŒî}­ó¹SëÙç>o°<ßpJNDÎËNôᔜ˜e”¡)/-YQhÈ ¾ulÏ –_Ží}À`y~“+cpæÙe2)c¬µÛÚQ»ÝVˆÚí¶v­ÝV¨åm¨·£vÞÖ©åmÅZ»­µÛm…¨Ýnk×Úm…ZûfÜQ;o+FíöM¼ky[_Ûs‹åwÛû÷o?£üíé­øžüç·âc[_¥±¼.`ºB¼ì¿2^æ&®S¸ŽAÜÄ%ÿåfb7q¨¨u~á*.yêó= ®â*x\Ž&ËÉw&K™e ¼¨âªH<Ö¾ÖU\õ*´’SÅU±Kõ2Ù¥©¸ª&¿lWÅ Dn"ËŠ'˜Ö ˆ«ê¶o=ЏäG2uÔE\Uk£ˆKíV- ó*¤l9Џd,rY¯ã".5^Ù§(âªÐ;™Í‘"®Ú|#‹¸j«\wuWmÖ,-\ ¤¦£¢†«¶­–4 Wížg䮊±Œ‹y¸¤€KoîáªÈ"ÎQbY1žhQbY1V°fèáÒÔŒËÚ;-rîáªÝß%ï.ùßë".ùt£à"® ÍH”åUŒ9LRHWŸÄ™.[™=Ï4\ÛwGÔpéÑhØŠ.­2£ÃRÇ%¸ò*F:jr W…E“Æ\Ã%íÒ?è.ý•—ÙóüA HÂýKKjæy§’/qó”•#žÅûŽ'VnZÔWJ #£O†_6žˆKŒ ¯,ûÅ;O„¬%ž&ŠHg“.M§šáÄT¼F÷sÑnà'â<¦t8¡m% OáN<ѯél…j” (ÂNvC9  Ôˆ€"!Ö4“(Ö§Lyé„ba¡Ô@(L¦)v›Å–j¡Mν™P¼ÈÎ$“ލnó‰úÊ‚®%dIV:kÝ"âc½›CªñÀ!ÅtÞDió½:ÒVø6Ž )–TÖ RÌÌÍ3í"¨bWÂ!Å8保”~ƶ;£ð†«“bCŠ`Í îg N®ÈhóÇñfëJ=ªŸ•­oHõÚ½<µW†euº2Î0ÞëÄiøûZçs§Ö³Ï}Þ^y¾á”œI·— Æ)9Ón·P†£Ý%§-/;m’o=…w{å§ð±W†SDã-¿âÉ¥2!c¬µÛÚ“óÝVL¼ñ¶N·jy[grîmÝoØVHâa[±ÖnkOÎw[1ñÆÛ:I<ÞV¨µoÈ=9÷¶âä|ßÈ'‰‡m}UzŽ,¿ÃüGÐ{€øèoOïÄ÷ð?¿Ûú*…eÅ»>žÎà?g±,ºÛ¦WÁCw»‡Kz&¾Ð=\º°2¢ˆK—†tç". =_&Ð3—ÎgqÉøÅîá’¯v&=\:ˆÖy{¸d¨È!¹‡«¬ÁþÃU\búóLÅU‘Ük¿*®Š=%Úòt|‘£‹«ê‹:µ„.®ŠLSÓ癊K†œF¹Š«¢‹2UU\;‰£+OÆÜgî&®Š½mÓìyfâª2\¢< &®ŠUË]yRâ‚*š¸*2‚gtåÕʬiqUDgFqÕê‹z.âªúö1ýE\2®á’¨‹¸jÂ@tåU ¼«Š".­Ó£Ã²âúÜD\~ŒÑÄU›¿ÞM\µ5:@ÝÄU›nð<&.©ÂÔtš¸´À,[4qÕ†ÔwáÙXÛ]f¶4—†Dj”åɧlôâ"®Š!˜ÞÄ.⪺²ôr<\›±LÌééæë¸´Xêâw.7,}çÇÆ²”ñK”˜]αD U²Ä²ø\wcY ßàX–åxúï+2)ÿÎ;Ó™,eÞ –ZR£ÁRG˜ö\!“ÿm‘I]ÚӻʙԑóŒKëäȤ.Ò•h°Ä"Ÿ„²ôíÝ%”ò|¢OÇ©”qr¡yTJI£“T–Q˜5®TÊ„‰â§²Œî™Ú¤RF œ¦9•eèÒæ¡R†ŒARYtŸÝTjÎÎíœJ­sE³¬”ä×(–-¸±uÁÍ¡”ãã>‡RJxjJy 3^ãP}IOÔãIɲ‚C)%´8•27œô^•RÀmENeAÒÿˆ Ë{Àˆ Ki¸SXI*í«•: ­Q.[`Ò,ÇR¦D¹¬æ'¥òò©YüA4k3"š3û¡hæÜ5 Z¼WtDkôW¼5$Ýðl\ÝxÊI4¦7¡rm¯[·Yfr Q³ÅAÖ¡­‰ï!܈֋³úhMÜv³­2Y0õ´#Š`cïQ謮ØojСÆ~³àرÛ,Úë´H(Þ”Yn„"ë´µHhmÌx2BP1ó¤Z×r4 Åúÿè‘Ð:í]™›Ð†ü„ E.k¾Z·½Ø ­PE@±§ÞÅôØ:@'ï»ÍÑ—ý'´1X·ŇRTÌؾ­¿s@k§œhŠT§ÜÏš€Bb (ºuªl@¨¸R]v‰Km˜²gZ]’± mLÚ€V¼ ;E@뺶£à½¿2ìa¡ãŒã½NœŠ¿¯u>wj=ûܧý•ç vÁ™t³èL/vÁ™r›2§ývèhI؟ÿ¿õ´þÊ?kSÍãõr!cœw=½:ªdŒµv[{>¾Û óñÝÖ®µÛ µ¼­3÷¶â|ÜÛ:µ¼­Xk·µçã»­0ßmíZ»­Pk߃{>îmÅùø¾ww-oëkfíî°ü§íÁýíÜgp¿=½ßÿ ·âC[_!±T7ð}Öþ- –:—Ÿ9h¸t “×pIÇÆw>SÃUšeŠ Wé\ÑÂU°§KGInáÒQå´“!Ì‹g®‚·;›ŠŽ®¢ïp´œßÉlëÎwþ¹„«¬ÅuA—pU8 t^쮊—¸×(Ë«—¿ÞÊ%\›‚LWi®š·r»ƒ«âE渢ƒ«ªØ) ,kž ÛÓÁU1&³MtpU ×Ìh© .¦O³t™‚«ÝÄz \/ïhÑÀ%%“Æ2¸*=¢€Kfà|Å“¸t¿þ" ¸tº}pU„ÍÍsäwºm†qNAS¿õžèLÒêœÈ~gä´L/6§º6ÚŸuÆgúGç)Ô·ÞS³¬ÛpN‘NŸb÷©kʦÂtN«¿7ysŠnͬ¬ÎiOAþ¬O¬åÏÉÛ-ø+uÌQt%zf f·=zfõÉh{Òê{[¤|foH[çF© )æšÖ:¤XØ/Ñ_©ùëWì> L\7Ϭ^ÍrÃ´Ž´Kˆ©ï!Û˜âfÓæIÓŠT (°Ô, ¶CL‘ŽuEeiþ¦ì)ÚY‘Rlsí7Jû5ýAJ1ÇïRLßgôW°t‡´aoq6¼ ô/ÃEtaÀ­r3À÷·ùü­ŽæÔxö™Ï ,Cëü;ÌÁµ$L8øw˜ÇSD[ñ’ØŽ•Å–¼ä›[2L`ùåùü–áWÑÌx›Ï?^u3ÞêxKgžî-ÅÙ¼µtêxK±[ ³t¶t›ËkK¡[ºÕñ–ÎÝ[Š3ykéÔñ–b¿ÿÎ -Ýæñvמ:lékfñ.±ügñ_FüíØG¤ßžß|ï0zó½kçk,–zþòôý³ K¶è°Ôxþ¤ŒKõ\šòf8©ç’ǯû˜¨çÒ¤.>-MÏU°©±ÄÀïsú^uÓsÉ(ŽAa×sɸbºFËü\º4¸e¶X¢eÚŸ2?—ækZósiΤ©žèçÒUùÕyõj>Û£Ÿ«Båg{Ú(èªI7%¢„†®Š|"Kx¸xÊ ]¦ië+iè’¹líÙ ]”ԨΫXb]ÑÐ%ƒÿá4tÙäÝêÀÐU±@R)ÊSCW…âófèªGÐWeŠ.™»óUW¦èªçóXLÑUqyi¡4EWmÅÍSTtU¼ÞzQÉ¥«ëõò3eŠ®ŠÑ¥]¦èªx›§K»TÑU5¤üo¨?âò«DE—®Š_ÑeY‘CZ££KJ¶ÒŽ.µSüeŽ.7ß]ïµ-™ttUÜ“´\š»_˜ÏêŽ.ûèè’z7ÿ]³-Sýñ)]x?Ðe©k×ãÆãätüðÈ—ËoqÕË G¬•è”Õê%‰#²@ 1qÔÑc‹8b¹*G•¥ÎÇ (qlþÒõcÃþ”yÄ Æ£”,i¥m7yÔý¸%òhəј§ëøÜÅk<ê¨ØU³Ê£”0§ÄyÔ]AÁ˜§î ZöŒGÛ²[ZB©­ñXdjGe©3vjcG™CŒ×h²Ôý î­TezÀ^Ûp´½·GM§NÆ‚‹3£0O3 Èg×Á›÷@£”4Ø6ªùŒFôÓÏ3tìU¶ OiÔ]©9ótÒoÓnÒ¨¿é˜,mon4YêcߦϤ±`'ò0ûa^Á‹wS„QzŠ‹•0–™¸í4 :~“Y§ŒéÔVZdY•Ò Í½ÛÚÑÔ’h²ÔÙ4u¬d³Œ[?i¾«fi”*:—X‹®Q1[àv¦w‰\–•œr‰}8ýÆeõ—ƒn.kË︴9XÀRŽÝ¤îÇ/‘ÊÚ쥨JèØuJ¬&'‡²¹Û¡Ä\½žNÒ¦ù7(1¹ow(=¥aC©3Äu ¬òÛÙ ÊꯪÝTbÆxE¿¬÷y‡åù†]Ò`Þ弊eþ?‡³?e8X„–XtÚ§oì°,2” óg9,Ïor'ã¹poO/“9c-o+]K#X§-/‰mZÞV¬µÛjöºØÐVóȆ¶v­ÝV¨µo ëŠ¥ÆVøïÞÄþ÷ýùЉ96Á’[+»Ön(Ôú¬·Ïiœßïç AýíÚg`¿=»û`~÷=¶õ%måÁFó%¥€ÍÏæ˜œùÇóWÎùã¿ýé72¢‘{r†Â¦Êò‹ÿé'ˆ–¥¦àwÊLH÷¤‹¹)3åCTf¦´•™™ÊLü+•™½le¦ï_ìvef›®Ì”vefûó•™x‘z*Ô|þ¿¯UfbÄzÕ¨!š2/­–d@ Qº\dí"4ù²5D2Dê\Ф†(é;7‚†(a¦óÅj:÷MX}°Q65D©î·5PC”煉Üò”“ö€“ã2!ïɪiˆr9@ª®ŒðÒî­ÕB”Fõw³ÑB$-¹yŸ¢„µ®`I}¦ã3 QB­~%DiN®ìº„(a=¢G QÂfã+Z3Óº<ÒNQÂ+5lîLQ‚QÁçôI sÝC”ðΤEDZ§A_š~å\D”pQ­ÄDD y¾vr("Òª¦6¥ˆHÕEDr*®×è!JÈá5k=Dr0™²Mzˆ¤™å"Mé œ¦2QÂòÍ=`i%N>]Dd%f3QBZ¢˜‡(açÉŒ"¢;àŒŽ>½vÈ&"J0òå¨KŒEQZµºŠH 4ø³»Ã…×­}à}J,Åä(ÍØôªÃ‡rޱ³•É ÿ¹-Ñ‘Iäa®ž"“xÃiLNÝJ5¶ØH>JÔØbuŠaGgòÒ™W@¯Gm#©o>II}ÇJf¦«M–“I}j‹LbKOŠ^¾1ÒÌ„åS›>;“irdžïø°™’C‰—YÚá8”ú–ù(Ó’Õ| ÁÌ(ÍLxq…M„œIØíKtƒ%¼ÌÂ&BÎ$äü+˜ùd†Ä ä›IÕ9˜TIœ8“¬™DÕnMgR_S9"”Ø=mfM‡W(•%6<™Ö¡D<Ö\›ent·l(³1êDâ‹ZDâÂ_Q –ôåÑš©?ÓØq$‘ÅU‘¹ºdωD»ö !‘úÊÁHdvMñ&­¤õò‘8ƃ4v)Å.Sƒ:ö–hÒ©Ûçrì2w¨e<ÕÇ8ZÀS·åÛú¾á©2¢gxªŒãŠJ[N·)/ñ˜Yì‡|Ârܯ­ÍDàªy @ùÄqÙKµw/É¡D>ÕpÜ¢¹O†2Ë'°Æ'öà$ o‘OÕßøÔwO[ˆ‡|d,XØŒ|"$cOÝ0ooA%žæ6ÈÏ¡ÏøTáòMÓè¤Z‹R[Í•!±Æ'¾<ÏÐg.£ÔvÈÍo¯Ñ903§Wšt¦ÆWØÎ1ÓÝh‹S5®È&NyÊ+°©ñ8sÆ’M¤·¬Þ›C×{V`»iZ÷Á$0f÷ d¨¬HçÊ4.8œØžÔk„s螇œø-&Û4:'–¦Sì/z ó’N¼‚×,‚ÄS÷´èÍÔð¦õ—ÞLDunŠwDmæ’sUô´íñêu¹Ð}÷ãõÆF"¼©ïk2i$(1ÃÀC㎢‡±UÆÌÙ<ØÁÖPÏ"vÃã¸FÝt5¢C‡Ì¤™CæJã+‹Œ¹ëE‰ãTtê„skø‹\ˆÜ*xÁrDnºaÊ‘ƒåƒGKä¬v•t·eâC3Z¤u‘%,/Æ y[¹ú„¼i„+à–æ4·û’»Ë:^·DA‘¸U}<äÈé0âÖòƒsâð"ù:£CZ›é·ÞðB‚[$N·0ÇÎp©·%§*Ñ"í¢êÝÓ㈦څ}°Ö2‘S÷JPeâ€‹Õ qøn¶Kâô毸5à ʸ…Éd}—Ùã^»3Ñw9Ç -x |_ë|îÔzö¹ÏÛ2Ï7ì’ûó²ô8%'úGñehб%+ yÁ·Ž"n[棈°ežßäöÇzv™Ìþky['>èmÅø ·ujy[±ÖnkÇw[!>¸ÛÚµv[¡Ö¾,Jè í(á¾åìß½‰ýïûó;>¸›ñÁÝÊ®µúŠ(¢2¿¿(âGP{€öØoOï¾÷°?¿ûÛúhë‰è5ŠˆÙ<QøÏûå6_¨x‹"~]øÎ ž›åwøîk žØÏ9‚LmxQF–°€Hõ˜ÉÈdpjÆvw‘%ôl:wYÊÚó»ˆ,qš‹Èö 7ÓŽ™ˆ,!ÿ·yg–üQD–Ô¤õ²=d2ÃvsEd ‹÷#ŠÈ&W:uY 8Y‰™ÈÒØ/šÈdŠÍݼn"KHB/Q˜fg>‚›È4~6£‰,á¸L‘G™±ìS4‘ɧšMcÝD¦Ñ»Ë¼cf"KÓ·4¸‰LJ¨4§‰L—‹o&²„Î2ǧšÈôˆí34‘%ì­žÑD¦%QD¦q¸nn@‘i3&n£ˆ,á%"Šœ‹Ètä5£ˆLJiq™~•‰L)"Ó#îQà©Ñ»d’1‘%¼Ôä&ðLxGHO-¹Ì;f"2 Ö]Á˜tì©4‘I¾ž”&²t„‚f"K^æ3™†æ²¹ÉÌD–ðZ í~h5n°ø À³ölÒeB©»ì–%•;nfTâþ´±žc©.…±ÄàׯúN&n›Ù;™K_q»™æNsä’Ìëj.Ýd^hGórëF/5§§£yaŸÛ M¼8yÜÐÔÈ`hâ¼¹F4Ã3¬£©o£mM ÐkTxÊS¬VGY·é†&Þ•Y#™xï¨à&S.f$Û õñçdb·aŽÏ„ÉÁˆdæÂ÷"m2“‹ 6™9om.ÑÌɱs4sa~ÖFoº\Qä©!1û™ŽfòÌ‚¦Œým–½ÑD‡£Äf|IÁFïÌÍј0Ú‰Š@)ÈÖð&3>FL„3ky"¯ÂWœL„èZŽhfSl41—JÑ­«?j¶ˆ&“ùcq¼“§FÛZì;±uf™¤–˜b§—M¦6¦ÐÕ˜‹—˜"^ÔÌ™MLqézŽ¢]¼ŽËb'Ž)ÔX—˜"TR(»VLVJ7“'rÅJêS}ÂYIL±ŽU4&ã˜ê»MÌ4JL‡¦{Ö€©JSõøS„r,¬â˜b â"ʆ©¾þ!v h†©Œ¾äTGH±§¬ö Åïn%öŸ:§¦Ý©ÎÐ ‹s¡û„•'Û‚ªRÄ0Hüë:[sH±ÄgÓ}‡tô(ÚÅ´øæÙE<ƦèΧfÑåÈ'Œ<ƒVOãsaîžc× )Îͳ;¯Êñ érÈsŽ@'b6æ(&œðèû=¤7EÕØé„™}W¥v@›é;Sí°ùЉ³moàp:õ<ÕH'âl†tN½"+Ð9‘oÑÞ @\µr è 93 ¯ƒïkÏZÏ>÷y‡çù†]B^væ@§äÜÅŽÖKB[^vÚ:%ß:°°ž_ ,|ÄáN”·d“'—Êœ”±–·uBÞÖ-ñˆm…$&¶kí¶vÈ`·¼­“Ääm…Zû&²À7tÒü¶cú›Øÿ¾?¿C»‰2Ø­œ$&oèkÒ“l7é÷WøíoÜ>cûíéÍ÷ž÷ç7ßc[+t¬b>*Œô=EÜ*ú<ªð9«(Þ‘WÔ¼bR'îF›Ý£âîF“9Åe çîFK}vnGKx٭ɽ¨GÓÁw6šêÑdü˱¹MW£SÔ£é˜T’]–ð­“U×£¥ây8®GKÕÓ„\–ªç°¸-énd“¡™-!»ÖälÔ£%Ø+í©GK,hô£%†Ù-aK´£%,Mæè/LxI— iGK^™O‘v´„¡œéaGK*TeíhiL¾†ÖíhZb&G³UõtÑŽ–fâÛÜŽ–ö¯çÓíh ëaÙl…fGK%˜ˆz4©ãRAêѤ}¦4¥-aÅË„dÔ£iÚ¼)DÍŽ–ö¢˜ëѤ™A¯õh+1gõhšèÔ¢-a\cí˜Mƒ¬bz4Ü,sšM³¬š M¦_ešQ³£iÞÅnGKû]nGÓ¨G´Š&LºùÒØ aœWÂÔåKVQÝ)ÕWÀR§+-Ê~±š³ú XbStLëX¢ÄX&–(˜¦ $–º«k¡*0Z´¢¤(ñw/Q+ªC‡Pj‰ŽEJ,ãÙR»C‰X‹ FJ¹ÓI)™\³y‘¼2ß¼½‘Ô’“ÈÁ7W£3 BT±¡Dô" ¥ QìLê cF&/ŒÛf©O–'ïL"Ñ£é7%em(òlW„2a{`TjU¿XTæíëPî}ÇJ¬D›fÔ¡DÆmTʇ¸au3‰ð†‰ÊÔªG7”iñE&Jä>õ(MÈU50Jla×ËëP"Àìˆ%B)f=u(ai6¥±C™supI%JZtjU+‘ÊìÏåeN~µËŒ½±{îƒUcŽ;Ný-JEAq¹yñz¥kE7‚ú#EïoÇ›#H1EE ˆÝ„{N¬À'½f)fÚbtHGñü?‡¹-–žã"öPGôqcï~oRd‹ØìÛ)½1Zà˜ÂÎQ1Ý“^§t¸ƒÓ!UU‹õÈ„ÿIv|¤¡Tž.R:õU­9P:ª‡I•Ò©9JÇZÌ¢rJ§¾ïdJ‘Ãc)\N©nc‰Qªïù®5PЉ|O#P:À>¯œR¬VpW)Õô›1…žÇÂ8ŽéÀΣ›{Hk“KÇi3‹úmÃTÏ#݆)Fü1Åå°T$bJ¦¥cz¿â”â[—S:5§JqUí28¥X¹±¨SªIO9vž¸+,UÊ)EÐ%/:Þ«EÃÖ"zKÎ\ÃëÄÁûZçs§Ö³Ï}Z-z¾À B,€Eg ´ N$ÀD¡ñ8õï¸qJK¶)þý­£ ®ýsö:=^/WeƹáÓ«£ªÌXËÛ:ao+† ¼­SËÛŠµv[;L°Û a‚ÝÖ®µÛ µö}cÁoh öfÿîMìߟßa‚ÝDìVv­ÝÐW\'úýE>BøÛ«Ïx~{z÷½gü¶>M€w}ôGã }õÇxB__ªø â ÔÞà ßRwÚÑɶ¨lƒŒ?é •mˆo[Ô™Ê6,/XJ¢+Û4Õžì¦lÓuBíO\Ù†]á–Mêʶ”/nãve›.»™"Ê6l(¶G¦+ÛRÉævwc[*¾ÇmòÈãÛÅÜØf ˜Ñ¬˜ðæF%»±M÷±ÏhlKð›å(³)Œƒ9em†ƒ‰ûÌF妾jÔ¤‚ëkƒâDQ°zSžNusjbT:`â>äR_ÇÁåca[Av.5ׯHärj®õ \êf?a9—H(7Q"±Äö:[Öu,‘«dÄŽ%¢b¶ëı\¶b~¨œpfØI'•K¯w€yé·¢A¹ô½N)@ vËg®—skX¢àº‰ˆ‘]¢ïtéJlô"ÜSóJ$…÷›HQ¾±ÒsáTb.ØoT^•½À¦ò’9õŤò|'ËÆRsg"•Ð;ðÑB*a韩lBevÖ®ՀݭïÔ ^ˇPMˆ«9ŠÂÌõŠ©ÍΜPÕÚÖn“Ú€BÌÌ­À$T.¼¥-9¢2/gXÒÅÖØujÁäÆ$tdº=P¤I¬+öœ¥˜9˜|Brc3Nç™¶"î|bão»2>‘Zf¿ÒùÄe¼ÙNuòm2qtX\áð‰MB| 9Ÿ*æˆý&›–+à|j¢Ç |‚&»Ý7Ÿrµ-bä|j@Æ:Iò‰×e³ŸP£ŽÀ§¾ÈxtâÝ%7U8ÞuľŒ|Â{`›ɧFô¹aÔEœd•À'Ž»pW·Ê‘;ŸðËob•OÏÀ§¥£8›ø=‰Çfl"R?olNÝ4¹›P׻̥°¦§® ”Øeb­ÃbÐO4§a& þ•3óð·ØÂ­ŽæÔxö™ÏjNCëöwŒhI˜ ñïS ®4¶Â’[;V[ò’o.R¡æô‹±…hNó[x¼:ªï¼ÕaK!fÀ–n‘m)ÔaK·:ÞÒ‰xK1®`-:ÞR¬ãw £læDì.㿲ó¯þé-ðbLÁÚ8u¼™¯ˆ(¸Úôû‹(|™ê·F)~{~¿½#ûéýö®[S˜…|Ñï>’àêÕ/‡>«^…÷z9ê“ÃÈcÑÆf>¹±…|ÔÉéø—%¦“[°yç¨zLXÎq;«>‹VFT=ª¥ÓŪ{}!s£L”J9Mf ?Nrpƒ¹ÒÕŒròSÆöÇ©Q.á­/ÔUšQ.!;•rV5Êiš‚ii”K –̨”KÍìÜ)§!„Iõ£:åRÇ"-sê”Kº½<:å¤éfeP§\‚gú4sÊiÁ-sê”K:ª±Ï˜S. UEžÜ€nN¹4·œN¹„õ":×Ì)—tÒfß§œœ±î–å0eendstream endobj 6 0 obj 24563 endobj 4 0 obj <> /Contents 5 0 R >> endobj 3 0 obj << /Type /Pages /Kids [ 4 0 R ] /Count 1 >> endobj 1 0 obj <> endobj 8 0 obj <> endobj 7 0 obj <> endobj 9 0 obj <>stream 2020-10-09T14:37:31-05:00 2020-10-09T14:37:31-05:00 GL2PS 1.3.9, (C) 1999-2015 C. Geuzaine gl2ps_renderer figureOctave endstream endobj 2 0 obj <>endobj xref 0 10 0000000000 65535 f 0000025114 00000 n 0000026627 00000 n 0000025055 00000 n 0000024921 00000 n 0000000267 00000 n 0000024900 00000 n 0000025207 00000 n 0000025178 00000 n 0000025271 00000 n trailer << /Size 10 /Root 1 0 R /Info 2 0 R /ID [<6440BBA5DA31B15440C01B4B7AEBB4CA><6440BBA5DA31B15440C01B4B7AEBB4CA>] >> startxref 26847 %%EOF blis-0.9.0/docs/graphs/large/l3_perf_zen2_jc8ic4jr4_nt128.png000066400000000000000000007412771422157504600235250ustar00rootroot00000000000000‰PNG  IHDR¬øSzgAMA± üa cHRMz&€„ú€èu0ê`:˜pœºQ<bKGDÿÿÿ ½§“ pHYsNNÆÊ/¥tIMEä &VeÃh9zTXtRaw profile type xmpH‰ÍVI’Û0 ¼ãy €ôY$o©Ê1ÏO”mylOfªrˆTÚHÝX)úýóýÀ‘yI$» [,iVÑ‹V+œ”µªéª][—Ëe°a|Õâ#Õ¤–&©4KE »èJe±Í°°Šm¥×¢xB¡±Éž6PÑáÜlÑl‰›*TïVÏd$@`ic.R¹ìE™¯*l‘ ­Íùjæäߺk7ñ9稙®8²Í‰›xsWƒ±K˜µ”Vû÷À¹ƒýêî aî²âÊÜ$‹ð† cs¨4x¿pÂ|…±“'ƒ€ÊþüH'’sÒ‰.Vp&ÙÀkXÜ BÜC±ñèê'ÞÈ 0£M%xŠ!Vnš-p&0m^ѵ.ÏpÂý“Ž4ÚxøG†IÉ=öhT)3Dø^݃„íÀ< ’A÷(âxŒQzm¾vzÇg.9ÉÃt¸Øa‡«F¹bÂW*ˆT˜PN„-h…ÝÁŸGpì÷Œ‹¬ú–³Bxp·gz(ÚJsã@Bm·ìŒ*سâž”~‡Iµà½È&"÷ã¨Ü“ìuSJg­S鬰CÄ=PçÌ]â,}÷¥Ò+,}AÔ£¥Ã—»pMZ:ÒÀë1楯>zJ£ ™Ñ=Т¸GTDÌc‡bækN€.CïR~&ÅçeqNúRæ JCs}Q×ä¡¿e¶k“»)tn̪÷,ï=;Ú9ØÔhí› Àð¬’Ð|‹·¿ËG{°3,Јkœþ9V&YbÙæ}¡¦Þ•½ó „äE·LgÝïÒåp¯„…7Ká¸é›£õ‡² ›Ž/jö¹c˜7”Ì$R!Ò­óDIÎ¥>‰kr¸›˜};¸²«Ÿ©gátïÔð Xd¸ ».2<¤ŽHÉ®±)úå{8…Í3O83[Ÿ¹LŸ|äìcÎè!ñÏÔ«7ÒüÑÔ ç—­Þ)ÐkwWÏp'Æ0”ÞÕ×Ii즷ѧŸÁ––ðOΤ(mÿ#(šÿcO?‘t‘¢6ÿÛèjXh8x÷caNvͱ¸ª€IDATxÚìÝut×ÛÀñïîfãîJH à!¸;ÅKi ”BÑR´Ph‘ÅÝ¥P Å)V¬PÜݤB°$D‰Û¬ÌûG~ìÛ—f¸Ÿs8°3“Ùg†ÙÍÕçÊ$I’AAA„FnèAAAáYD…UAAA(D…UA ©ððp† fè0Aá?#*¬‚ ‚PHÅÅÅñûï¿: AAøÏ:AÞ:ŽÔÔT’’’066ÆÑÑ333²³³yôè*• ‘$‰ÌÌLŒŒŒ011ÑŸ'==¥R‰‘‘ÙÙÙ(•J=zDVVÎÎÎXYYKzz:vvvØÛÛ£ÕjQ©T(•JâããÉÉÉÁÅÅsssbccÉÈÈÀÞÞ;;;d2™¡o•ðÑét$''“’’‚‰‰ ŽŽŽ˜ššê÷¥¦¦’œœŒR©ÄÑѲ²²P*• I#—ËQ©T˜˜˜‹¥¥å3ß333¥R™ç³#‚ …•¨°˜Z­æÚµk„„„àèèH•*UprrÒäÔ©SXZZR»vmRSSqrrÒö###9}ú4Z­–Úµkãåå@FFIIIXYYqèÐ!²³³iذ!ööö=z”‡RµjUJ–,Iff&ÉÉÉXZZ²ÿ~êׯ••ÇŽ#66–5jàçç' ôÂ9sæ ³gÏ&$$KKKš6mʈ#ËåŒ7Ž£G’’’BñâÅ™0a¥K—fñâÅ8;;Ó¥Kýy¾ÿþ{>ûì3¼¼¼X¼x1>>>lذ„„7nLݺuùùçŸ‰ŠŠ" €©S§"“Éøõ×_ñôôä÷ß'55•V­ZQ±bE~þùgbcc)S¦ 3gΤxñ↾UÂ{B§ÓqäÈæÎË­[·°µµ¥yóæ >SSSΞ=ËìÙ³¹~ý:4mÚ”þýû³råJøä“OÈÉÉáÛo¿¥wïÞXXX°jÕ*Ê—/Ï‚ 8p ÞÞÞú÷”$‰S§N±aÃúõëG©R¥ }Aá­ÉIJ6†£V«™0aþù'îîî$&&bddĦM›pwwçÔ©S 4kkkd2&&&ÄÇÇ3oÞ<ªV­ÊÁƒùî»ïpssC’$bbb˜4i­ZµâÈ‘# >œ¢E‹¢V«‰ŽŽÆÈÈRRRÈÈÈàîÝ»lÙ²…G1f̼½½ÑjµDFFbee…««+éé餦¦Áž={(S¦Œ¡o›PR»vm~øá®]»ÆðáÃ7n üüóÏ,X°WWW¦M›Fvv6óçÏgýúõlÙ²…Ý»wcaaÁ… èܹ3ëׯG­VÓ±cGj×®ÍèÑ£¹wï;v¤D‰,\¸SSS:tè@£FhÓ¦ _~ù%}ô?þø#ÿý7Ÿþ9•+WfáÂ…äääðå—_òùçŸóÓO?úV ï‰ÇS½zuÚ¶mKïÞ½9sæ ãÆcÁ‚Ô¯_ŸJ•*QµjU†Î7øþûï=z4·oßæÌ™3lÚ´ 333>LÿþýÙ¶m111téÒ…råÊñÅ_P¯^=ý³ÿþ}Ž?Îwß}Gÿþýéܹ3J¥ÒзAø€$%%±páB6lHÍš5 Ž üg´Z-7näÑ£G 8ÐÐá|ÄVÊÈÈ`Ñ¢E|ÿý÷ìØ±ƒ_~ùKKK®\¹ÀìÙ³)Y²$[·neãÆØÛÛ…F£!::š‰'òù石uëVþøãZ·nÍŒ3xôè†øøxš4iÂöíÛY»v-çÎÃÙÙ™-[¶°zõj<==9uêjµšØØXÚ¶mËÎ;ùå—_8qâþþþlÙ²…ß~û GGGΜ9cè[&R7nÜ lÙ²xzzÒ¨Q#–/_N¹råÇÒÒ’²eËâççÇO?ýD¿~ý033£jÕª¤¦¦rõêUvïÞM©R¥(Y²$tíÚ•âŋӸqcLMMùøã)_¾<þþþÔ®]›Ç`ccÃW_}…··7Í›7G.—Ó¾}{J—.M©R¥¨ZµªþXAx4 ·oߦ|ùòxzzÒªU+–/_ޝ¯/¡¡¡”)S///4hÀòåËõ ;‘‘‘ܼy€?ÿü“*Uªè{RMLLèÞ½;;vÄÝÝ]ÿ~gΜaÈ!tìØ‘/¾øBTV…|—‘‘ÁŽ;7t(‚ðŸÒétœ>}šC‡:”†l@r¹ Nž]ÿŒÚÚÚR¦L™<Ó3rrr\_ŽÿЉ;`@Ì›7ðÕW_Ñ¡C†ΣGˆŠŠÂØØX_H‘Édú¤<@«Õòõ×_Ó­[7ºuëÆ!C066ÖW,õs]ŸxÞT“§ íOŽóV…·¡Óéøî»ïøý÷ßéÖ­ ôïߟ+VP¾|yV­ZÅܹsñðð`åÊ• 0€˜˜d2 6äèÑ£\ºt‰‡R»vmC_Ž ¼¥RɰaÃX»v-_~ù%÷îÝ£OŸ>lÞ¼NÇ·ß~ˆ èÖ­‰‰‰ 0€_ýUÿÜïÛ·‹/’ššJµjÕôç•Ëåú„LO( &L˜À¤I“øý÷ß¹té’¡/_xO?~œ)S¦P±bE¾ùæÂÃÃ?~<”,Ysss|||pss`çÎŒ9’#GŽP¯^=¢¢¢˜5kK–,¡M›64nܘ‰'2pà@jÔ¨A¯^½Ø¸q#k×®àðáÃ|÷ÝwÄÆÆ2tèPâããéѣǎã‹/¾ €I“&éG$»’˜˜ÈСCÉÊÊbÈ!ØÛÛóý÷ßsÿþ}<==qvvÆÖÖVŸ fùòåŒ=š¸¸8ªV­ŠJ¥bøðáܽ{—AƒQ¢D ÆŒCpp0›7oæ»ï¾ÃÜÜœL= £gÏž8880fÌ¢¢¢ }+ ÑÃj@™™™x{{³iÓ&RSS9qâ3fÌ`èСh4}(ä¶lêt:Š-Š»»;çÎÓ^T*7nÜ @ßË*†ÃÀ7n½{÷¦gÏžŒ5еk×òøñc}OTË–-‰‰‰¡hÑ¢DFFâááA‹-˜;w. .¤uëÖX[[úrá•ܾ}›Ñ£G3mÚ4úôéC¯^½0`[·n¥aÆ|ûí·Œ=Zÿ™øé§ŸØ²e ƒ ¢M›6¬X±‚ÌÌL>ýôSý¨‚çQ(4mÚ”¬¬,öîÝËĉùý÷ß±³³3ômÞ3§OŸÆÄÄ„biiIåÊ•9þ<Õ«WÇÖÖ–ÀÀ@J”(¡ÿFÃï¿ÿ޹¹9gÏžÅÌÌŒo¿ý–ưxñbZ¶lI¯^½Ðétœ9s†û÷ïë> €Q£FaccƒV«¥}ûöL:777¹xñ"qqq”.]ÚзGx$''süøqΜ9CåÊ•©_¿>ÕªUC¥R€FFFÔªUK_©,W®3gÎÄÈȈ´´4öîÝ«Ÿ²÷ÑGQ®\¹<#ªV­Êˆ#€Üލß~ûñãÇãàà€=zô 55Õз¢@=¬I—.]¸zõ*vvv4mÚ”Ò¥Kƒ»»;Å‹g÷îݤ§§“’’‘#GHKKÀÝÝ+++víÚEzz:ééé¬[·ŽÑ£G‹‡[(P¸rå S¦La÷îݬ[·ŽƒÒ¸qc$Ibùòåüúë¯ìܹ“)S¦P¾|yœpvv¦|ùò\¿~&Mšˆa1B¡akkËùóçõÏýÊ•+9sæ uêÔÁÞÞž«W¯2yòdvïÞÍúõëÙ¿?uëÖÀËË nÞ¼I£F^ù=MMM4h±±±¬_¿>Oƒ§ ¼ •*U"33“Ž;2wî\’’’øøã_Ø8R½zõ<#¸LLLô+<áææ†\.G&“=µ\S‘"EòŒ*Édú\333ŒŒDß‹ðîÙÚÚR»vm İaÃ8sæ 4ÀÏÏï¹?S»vmýóhllLãÆ?~÷åÊ•cìØ±ÄÇÇ£V«Ea^x§š7oŽ››ûöíãøñãÌ™3‡ 0eÊ”çþ̿׸–Éd¯õ\‰‚»ïœÙ°a{÷îåĉüøã¨T*V¯^­/kü›½½½þßOÊ>‡âàÁƒL›6¤¤$,XÀG} ʯAü&3 333V¯^ÍñãÇ ¦råÊÔ©SGŸµtéÒ¬ZµŠýû÷ãé鉥¥%3fÌÀÕÕ…BÁ_|A‰%8zô( …‚aÆQ¾|yý…Õ«Wãââä~(®_¿NÑ¢EÜ„ Ó¦MÃÔÔ*T¨€££#ûËåúõë+V KKKæÏŸÿÌEêáUÔ¬Y“Š+’ššŠ‰‰ ÖÖÖúa1Æ ã›o¾A«Õbee¥Ÿw­ÓéHLLäÂ… ´hÑBßë ¹=Pýû÷ÏóÇ×ÿ[&“Ѽysýë¾}ûæ9öŸË×( Ú´icè[$¼gär9õë×§J•*<~üSSS¬¬¬ôÏ}5 $55ccclllP(èt:bbbæÓO?ÍÓéëëûÔ³ìííͰaÃòlûøã }ùÂ{H­V³cÇ4 ?üð?æáÇT©R….]ºˆu¬…÷Jhh(Û·o§OŸ>´oßž¸¸8¾ùæÖ­[÷Ü ë?EEE±råJºwïNëÖ­ILLdذa¬X±B_a^¨°L&ÃÉɉvíÚÑ®]»§ö=šŠ+2zôh²³³6lŽŽŽúJ¨±±1Õ«W§zõêOý¬••VVVú×r¹<Ϫr¹<ϜΠ422Ês¬B¡ H‘"†¾]B!gfföT0È}Þž5*àÒ¥K,Y²„k×®1}út1X(”,,,°°°xæ¾g}&NŸ>ÍâÅ‹¹{÷.mÚ´=KB!“Éf÷îÝxxxàääÄ¥K—°¶¶Ö7hK’DVVÙÙÙ"ûºP¨eff2}út©W¯ÄÆÆR¿~}ý1*•ŠÌÌL}~™›={6FFF´k׎øøx""" 2ô¥J¢ÂZ€}õÕWL:•ƒ¢V«‘$‰É“'‹_ÂÁÄÄV¯^¿¿¿¡Ã„|ñdÊG¿~ýžZŠI ÉÈȈ޽{Åwß}‡$I˜šš²xñb‘ÉdT®\™E‹abbB·nÝ(Y²dž!ìÖÖÖTªT)OCMÍš5õsR!w^ß“%É|||°³³Ó7X:99Q¯^=ý±¦¦¦‰cÂ;WªT)ÆŒÃÊ•+Y¼x1¦¦¦Ô«W`ddD½zõ8vìƒfèСé—˃ܩS§NeݺulÚ´ ùñÇ(S¦Œ~Ô#äNù¨\¹²þµ¹¹9•+W~nƒç‡F&‰Û ´ÈÈHnß¾R©ÄÏÏgggÑÓ$‚ ‚AäääNvv6úQ_)))„……áãビ““¡C„·ILL ŽŽŽxyyéçæääpëÖ-LMMñõõ}î:À±±±DDD`gg‡··÷SË’ ¯FTXAAA„ItÕ ‚ ‚ ‚ ’¨° ‚ ‚ ‚ R¾']’$ µZMvv62™ ssó<ã¾%IB¥R¡R©P*•˜™™½0K¢$IDGG[è³)J’„V«}/ÖÍ{’1ÍÐóm•J%ÅŠÃÜÜ<߯?33­V‹©©)ÆÆÆúçS’$ý>“<ûžw®ððpÒÓÓ z/ßÕ}‘$é¹s= FS >«øúúæûzn†¬¬,$IÂÌÌ,ÏZ‰:ŽŒŒ 7)ÊËÖQÔjµ„„„ Õj w#ß­V‹\./ô¿ à<ãvvvøøøäë{¾ë²ŠF£!$$ä¹ÙD FƒB¡Ïø;"IEŠÉ÷9¿ÿ|† yþO_·¬’––Æ;wxf¾/ϸ$Ièt:ƒ—¹d2Å‹ϳzÉëÊ÷OiTT¿ýöׯ_ÇÈȈ† Ò¶m[ý 7oÞdÍš5„††âîîN—.]¨T©Òso¶V«åÀØØØäY°·0JNNæï¿ÿ¦Zµjÿ}[·nÝB©TâëëkÐ8nÞ¼IvvvžÌkÿµÌÌLöîÝËÎ;IJJ¢L™2|òÉ'TªT FùsçX½z5 ”)S†N:Q¢D‰çž/55•?ÿü“J•*ô^¾ wîÜ!33“²eË:”·vôèQªT©’ï!ÿ¤Ñh8vìíÛ·Ï׌²‰‰‰lÚ´‰ãÇ“““CPP_~ù%EŠ!;;›={ö°eË´Z-•*U¢k×®úïøgyøð!È×ÏéåÂ… ¸»»ãááaèPÞÚž={hÖ¬™Acxüø1GŽaÈ!ùú¾¬\¹’k×®all¬/«>žI“&Q¶lY&MšÄÕ«W™1c¦¦¦4nܘððpÆO«V­¨Y³&+V¬`Ò¤I,]ºô¹e###Ê•+GÕªU z?ß–N§ÃßßGGÇBÿŒ?~ü˜ôôô<ËF‚µµ5©©©ouŽ|­°>xð€k×®1eÊ}Kú;w8þ<;wæÒ¥KdddЧOJ”(¿¿?'OžäÈ‘#ÿBÉfffxyy:ŒwâE½)ï»ýû÷S¹reÚ´iƒ‘‘FFF >œ›7orõêUœœœèÖ­ÖÖÖ˜™™1`À®\¹BµjÕ ú® 4`¼+ù=D± ÈÈÈàÈ‘#|òÉ'4lØÈ]<}Á‚DGG³sçNªV­ÊçŸä6ÄýüóÏÜ¿ÿƒø/ì §ÿô!ü=˽{÷øûï¿™2eŠ~dËíÛ·9wî;wæÜ¹sdeeñÍ7ßàï'Ožäèѣϭ°¾O¼½½ Â;ó¡>ãçÏŸG&“Ñ£G|||(Y²$Gåܹs4nܘýû÷ãêêJ×®]±²²ÂÄÄ„Aƒ\è+¤/#—Ëß›²øûÒx ùœtÉÒÒ+++îܹCNN?&11 ¡¡¡8;;ëSSS¹råŠ¡ï“ ¼2777¢££IMME«Õ‡$IX[[BÙ²eõÃHÝÝÝñòò"88ØÐa Â+122ÂÙÙ™û÷ï“™™IVVqqq˜™™abbÂßÿ§@S®\9T*<0tè‚ðJ,--±´´|ª¬bkk«/«¸ººæ)«T¨PA”U„BÃÑѵZMDD:ޤ¤$?~¬oT ¡\¹rú²Š‡‡\½zÕС ¨|íaõôô¤W¯^,X°€K—.‘žžNtt4ãÇÇÜÜœøøxŒõ###ÜÝÝ9uêÔ Ï«R©xøð!NNNž':ŽG¥¥e¾¾÷gŸ}Æ­[·>|8NNNÓ¤IJ•*ELL åÊ•ÓÏQ¶±±ÁÖÖ–ˆˆˆž333“ÈÈH\]]Å3.¹ól>|Hjjj¾&¹077§W¯^L›6áÇ£P(¸~ý:Æ ÃÕÕ•¸¸¸<=énnn¨Õê—ëLJJ"&&—B?%Bxw"""ô ¼òK‘"EèÑ£‹-ââÅ‹¤§§Ãøñã155%..ýpA¥R‰»»;.\xáyILLÔσ„œœ"##ÉÉÉÉ×÷ ¤~ýúÌ™3‡…¥¥%mÚ´rç>þ3Œ­­-ÖÖÖDFF>÷œZ­–˜˜222°°°0ÜM ”´´4bbb055}«óäk© 33“Ë—/cccƒ~®fHHæ¹?÷¢}ÙÙÙܽ{µZŸ—#`’$ñðáC>|˜ïYÃÃÃIHH hÑ¢x{{ãàà@XX)))Ïý™—eG}üø1wîÜA¥Råëµ—F£áÞ½{$$$äk…U«ÕríÚ5t:>>>xyyakkËÕ«WÉÌÌ|æÏètº—>ãñññ}ô-ù‚PÐU®\™&MšÐ·o_*V¬ˆJ¥"$$„ž={bccƒƒƒµk×fòäÉÔ©S‡+W®PªT©;¤]­Vsùòe¢¢¢òlwpp R¥JXZZ¢Ñh¸|ù2J¥’ÀÀÀgžçâÅ‹H’D`` FFF¨ÕjBBB8þ<™™™ØÚÚR­Z51ì¹€“Ëå´k׎óçÏÓ·o_*T¨@ll,<`ôèÑ4hЀƒ2räH8vìÍš5{¯–4 —|­°ZYY1`ÀªU«Æµk×P*•tïÞ???}ÖÔþýûS¡B®]»FÛ¶m©S§vvv†¾O‚ðÊj×®§§''Ož$!!~ýú„½½=’$1nÜ8öíÛGTTC‡¥bÅŠ†Y^™R©¤}ûö”)S†óçÏ“““ÃO?ýD`` +VŒ©S§²oß>²³³™4iåÊ•3tØ‚ðʬ­­8p Õ«WçúõëÓ³gÏdñâÅŒ5Š-Zäkþáõ¸¸¸0eÊ.]º¤_ŠlÔ¨Qúù§¶¶¶Œ?ž}ûöñðáC~øá‡ç>‚òµÂ ¹•Ö РAƒçîo͚֬53ô½„7¢T*ñ÷÷æH™L†££#:u2t˜‚ðÆÌĮ̀T©Ò3“,Éår|||øæ›o ¦ ¼1kkk6lHÆ Ÿ¹ßÊÊŠæÍ›Ó¼ysC‡úR’$‘••EË–-Y´h›xç÷ßgÔ¨QìÞ½›fÍš‘••õÂeÓ²³³ÑétH’Ľ{÷X±bC‡¥ÿþ@nvå3f0vìXªT©‚«««¡/]x777Z¶lIË–-ŸÚ'“ÉprrâË/¿4t˜‚ Â*‚ ‚ Ž\.§V­Z8::¾Ñ2$·oßF©TR¡Bý6 zöìIll¬>ˬ » *¬‚ ‚ DVV'Ož|«å|\\\ zn©N§ãÀdff>s¤ÄËžžÎ´iÓP«ÕT®\KKK<==Y²d‰¡o¡ ïQaAA( $I"%%…ôôô7>‡………~íÌ'Ö­[Çþýûõ¯éܹ3~~~ètº×:‘"Eøå—_X¼x1ß|ó ?¦V­Z4jÔˆ>ú///ÑË*Â;#*¬‚ ‚ „¹¹9Ÿ}öÙ;?oݺu8p þõ7X¼x1åÊ•{í÷“Éd´nÝš ð÷ßsïÞ=þüóO†ÎüÁÚµkEfpAÞQaAAxÏyzzæI"Õ°aC’’’X³f õë×­s]¸pôôtêׯOÕªU©Zµ*:tàÊ•+´jÕŠ?ÿü“îÝ»ú’AxOÈ € ‚ ‚¿´Z-*• …B\þzÅÁ£G2fÌâããólwssÃÕÕ•¬¬,C_ž ïÑÃ*‚ ‚ðž»wïÛ·o׿¾qãk×®eРAúõîÿ} äÎWý÷zá­Zµâ—_~a̘1|ýõרÛÛ“––ƦM›HJJâ£>2ôå ‚ðyë kFF©©©Ü½{[[[Š/ŽJ¥ÂÊÊêµ[ìAA„wG.—ãììÌÕ«W?~¼~»±±1}ûö¥W¯^( \\\¸råJžcZ·nMÅŠqrrB’$d2%K–döìÙÌš5‹^½zallŒN§C©T2kÖ,¼½½ }Ù‚ ¼GÞªÂˬY³8zô(iii4kÖŒÏ?ÿœ•+WÒ¾}{êÖ­‹‘‘èÄAA0 æÏŸÿÒãæÌ™Ãœ9sž»úôéy^·nÝš>úˆ«W¯’’’‚ƒƒ¥J•ÂÔÔÔЗ,Â{æk“YYY,Y²„;wî0nÜ8.^¼HRR%K–¤D‰LŸ>"EŠàççgèkAAÞ1ccc*W®lè0AxϽñ˜Ý¤¤$Î;Ç!ChÞ¼¹~þƒ½½=½zõÂÑÑ‘“'OúúAAA„Bê{X5 ÙÙÙxyy=µO©TâââBZZš¡¯OAáƒw÷î]Ö­[ÇŽ;HOOG¡PP©R%¾ýö[Ê•+÷ŸOáÒjµüüóÏlÛ¶-Ïv''':tè@›6m$‰%K–ÉÔ©S_x¾óçÏ3|øp‚‚‚˜:u* …B¿ïÑ£G,_¾œ¿þú‹ÄÄDd2µkצ_¿~”)SÆpÿ ‚ ¼‘7îa511ÁÖ֖Ç?µ/%%…K—.Q¤HC_Ÿ ‚ Â-22’=zðÇзo_æÏŸÏˆ#HNNæ³Ï>ãÂ… ÿy ’$NRR]ºtÑÿèÓ§>†ððp‚ƒƒ_z¾­[·röìY¶nÝʃôÛ5 .dùòåtêÔ‰ùóç3~üxbbb2dQQQ†ùOá½qsš““Ý»wgöìÙ\¾|•JEJJ K—.eË–-”,Y’:uêúúAA>XŒ7­VËÎ;ñòòB&“!ImÛ¶åÛo¿å»ï¾ã¯¿þÂÒÒ’Çcnn΃HJJÂËË OOOýùt:±±±Ü»wsssô‰–222Ðh4ÈårÂÂÂÐétøúúboo¯ÿyOOOºvíªݤI:vìÈÞ½{©T©Ò+]Óƒ8tè}ûöeß¾}ìܹ“"—ˉˆˆàÏ?ÿä‡~ W¯^úk­^½:Ÿ|ò gÏžåÓO?5ô‹ ¯á+¬2™Œ:uê`bb¶mÛ¸xñ"’$‘––F:uèÚµkž/(AA!ÅÅÅqèÐ!~üñÇ<#ßd2ôèу=zpæÌýr5ÞÞÞlÚ´‰ÔÔTÜÜܘÿüs¦M›ÆÜ¹s‰ŠŠbáÂ…,\¸Y³fqéÒ%:wîÌÞ½{iÛ¶-Û;ºdÉýûùäºtéBdd$¥J•ÂËË‹/¿ü’Ñ£GsäÈš6mJåÊ•)]º4*T@.ãÙp‚ ÈjŒŒÐh4\¼xµZmèëAA(ü4xø<Èý£ÕænÏÈøÿmII¹Ût:HHøÿí*ÕS§‹ÅÑÑñ¹I•žô@>)ËåääЯ_?üýýqqqá‡~ ..Ž›7o²ÿ~ÌÌÌèܹ3ééé8;;Ó­[7þüóOýùJ–,I³fÍP*•/^oooTÿˆ+..Ž?ÿüSÿçöíÛdff…$I/½=™™™ìß¿ŸfÍš‘œœŒ··7ìÛ·È-ŸöîÝ›mÛ¶Q§Nþúë/ÌÇÌèÑ£IMM5ôÿ° ¯é{XmmmùôÓOùõ×_IMM¥téÒÈd²<ÇÔ©SkkkC_£ ‚ Bá™ ¿ÿþÿ•Ò‘#ÁÒîÜ r·U«­[ƒZ @HHîö~ýÀÃ#Ïé|||ˆ%%%—§Þ.55N‡¥¥¥~Û?sØÙÙQ¢D cõêÕT¯^Úµkë+”÷ïßgòäÉP¥JÂÃÃسg}úô 88˜àçç‡R©äðáÃØÚÚê3Ï™3‡ÈÈHjÕªõFñ¥¦¦rìØ1ììì^šxéîÝ»„„„ðÓO?Ѿ}{ýö„„Ö­[Ǿ}ûhÛ¶-?fóæÍ|ñÅúŠtff&wïÞ¥jÕª(•JCÿ·‚ð޸ªP(prr"--ÈÈHbbbHNNÆ××—<)ÐÿI£ÑpîÜ9Ž=J\\7¦Aƒúá#111üõ×_\»v"EŠÐ¶m[Š-*&É …†$IÄÅűcÇ®_¿N‰%hÑ¢¾¾¾èt:îÝ»ÇæÍ›‰‹‹£|ùò4kÖì™Ã´¡ Òétܺu‹½{÷rç΂‚‚hÓ¦ ööö¨Õj®]»ÆüV«¥jÕª4iÒ$ÏpCA(èž”UŽ9BBBMš4¡^½zyÊ*»ví"$$„¢E‹òñÇãíí] Ë*ÆÆÆôë׈ˆ:wîLãÆ)Q¢>äÈ‘#-Z”Ù³gë{#~ýõWÂÃñµµeÆ |öÙg”.]š2eʰ~ýz:uêÄÇLll,[¶laÖ¬Y¯ϹsçhÒ¤‰þu\\*•ŠŸþGGG.^¼˜ç€   HJJz*”““5b÷îÝ :”¾}û2nÜ8víÚE•*UÈÎÎæèÑ£hµZ:wî,†“;RòäÉ“>|™LF»ví¨P¡ÆÆÆèt:îÞ½ËæÍ›‰§B… |ôÑG¢¬"ÌWX"""˜?>§OŸ&11Èýb,Q¢ß~û-5kÖ|êËûÒ¥KLœ8‘ºuëÀüùóIOOçóÏ?G¡P0yòdbbbhݺ5çÏŸgüøñL›6M|H„B#))‰)S¦ R©¨U«äܹs,]º”ôôt†Ž‹‹ UªTáÏ?ÿäï¿ÿfÆŒ†[^ÙÝ»w?~<ÞÞÞT¬X‘íÛ·ÃСC¹~ý:£G¦J•*¸¸¸°lÙ2?~ÌW_}eè°á•]¸p‰'R¿~}J”(ÁܹsIOOç³Ï>C.—3aÂhÕªçÎcüøñLŸ>'''C‡þL666LŸ>-Z°{÷n}/é AƒhÚ´)îîîyŽ?~<;vìàîÝ»ôèуN:é‡/X°€µk×rðàAìííYºt)µk× E‹Ô¬Y,,,Po\aÍÈÈ`Ñ¢EÜ»w‘#GÒ°aCd2QQQlذ1cưxñbJ–,©ÿ™¤¤$~þùg>ýôSºuë@‘"Eسg-Z´ $$„°°0¦NJ… hݺ5;vdÿþýtîÜÙÐ÷J^Éþýû¹sç›6mÂÌÌŒzõê1uêT.^¼ÈíÛ·ÑétŒ;J—.ÍàÁƒ ¦B… †]^J¥R±zõj<<<˜4ir¹œjÕª1sæLî޽˚5k(Q¢£GF&“áääÄÚµk©W¯ÞÞÞ†_^*11‘Å‹óùçŸëZ¼¼¼Ø¿?Í›7çêիܹs‡éÓ§S®\9Z¶lI§N8pà_¼d>©!Y[[ÓªU+š7oŽN§C&“¡P(ž9ß´fÍš4iÒI’P(y:Š-ÊÈ‘#ÑjµÈd²<Ù‡ÿý{ÌÔÔ4OohõêÕ©^½úsc”ÉdT«VjÕª½öõ•-[6Oe¸yóæ|ôÑGúk•Ëå²Ü|8uëÖE£Ñ`ddÄáÇ©\¹2;wî`ìØ±ØÙÙÀ÷ßÏÕ«W)_¾¼¡Ã>@oüÉMNN&88˜Ò²eKÌÌÌ055¥xñâôë×'''N:•çg"##‰ŒŒ¤qãÆèt:´Z-õêÕcÈ!˜››†‹‹ ¾¾¾Èd2ÌÍÍ âêÕ«†¾O‚ðÊNž>>Èd2,,, ,4e…BR©ÄÈÈ處Õ'•X###”Jå3+yr¹\Ž‚êI…üIœ¢²úÿ._¾Œ½½=eÊ”A£ÑðÕW_é× ¥B… XYY!“É(Z´(îîî„<ÉF-ùì?½Z­–œœ|}}ŸÚgjjЧ§çSk]ÅÇÇGpp0ß~û-:uâ·ß~ÃÂÂ###îß¿¹¹9666@îðââÅ‹sëÖ­Æ’žžNpp0YYY†¾ŸB¡Õj¹yó&7oÞDûd »|rýúut:'N¤C‡Œ9’ÈÈHlmm ÇÉÉ cccqvv~é3ž””ÄÅ‹ÉÌÌ4Ø= •JEpp0‘‘‘ètº|}ßÛ·oLj#èС“&Mr¿ûïÞ½‹Ç?–Õ(V¬*•Š˜˜˜ž÷þýû\»v-ß?¯BÁvþüù—fŽ}×ââ∋‹ãòåË 8N:±råJ}YåÞ½{XXX臥š˜˜P¬X±~K’ÄÝ»w¹sçŽAïç˸ººòã?ê‡ô ÿ­ŒŒ .\¸@FFF¾¾oXXÙÙÙüõ×_tëÖ=z臉„‡‡ãìì¬ONåää„££#aaaÏ=§F£!$$„øøxƒÝO¡à‰åÚµkú†‘7õÆVSSSؽ{7H’„$Iú–ô«W¯R¢D‰§~N£Ñ°iÓ&5jDçÎ9|ø0 ,xaAüE™ˆ!w‘h[[[1‰^ГÉdX[[ë{2óÛ¶mÛôk½Éår&MšDhhès²~Ýócoo/žqAO.—ckk‹¹¹¹Ažñ 6P¦LúôéÃÇ™2eÊs+¥:¬,,,°µµ5ȵ—ƒƒCžd@ùE­V³eËš4iBçÎ9xð ‹-zaÃø‹Ê*2™ KKKƒ%ËÈÈàÑ£GÏü“‘‘N§#55kkk¾þúkQaÍ'FFF888¤§úÎ;œ9s†ž={Ò´iS-ZÄüñŸyQYE&“acccÏ«Pp™šš¾“ßíoü qpp sçÎLŸ> .P­Z5ýÖ“'OR²dIjÔ¨ñô1bÄý¤wggg @¿~ýžû^/[+ËÔÔ”¢E‹ê{­A.—ãî»»A†5iÒ„ P((_¾<}ûöåðáÃÏ=þe_ð–––ÏÍ |¸”J%E‹ÅÁÁÁ •¼nݺñé§ŸH«V­žÛäP(^úýìääD‘"Eòý:„‚­X±bܸq#ßßW©T2bÄJ•*ä–y ôVegggƒ%üùçŸYºté3÷õèуž={Ò·o_úôéCýúõ ã‡ÈÄÄ___’““óý½‹)¨Q£ððð@§Ó‘žžÎÖ­[_˜ ïEe…B——×3b .[[[Š)òÔ¨Û×õÆV###š7oŽ……»víbëÖ­hµZlmmiݺ5:uÒ-xÂÜÜ üýýõÛÜÜÜ022"55wwwîß¿Ozz:–––¨Õj"""D!F(Tõ¬¬¬ðôô$!!777’““Q«Õ(•J’““IJJY …BC¡P`kk›'¡žƒƒ666$&&âáá‘ggdd¤¾A sss,--ñóóÓoswwG¡P––†‡‡>$## rrrˆŒŒ,Ðe•GaccÃòåËŸÚçää„©©) 4x*[°ð~²³³ÃÁÁWWW ·‘¿hÑ¢dee‘™™‰——ÉÉÉúdLIII¤¤¤hèÐ…Ô[AP*•4jÔˆ*Uª`llLvv6’$é0ý›³³3ÎÎÎ\ºtIŸîæÍ›@n <((ˆmÛ¶ñàÁJ—.Mvv6/^¤C‡†¾OB!õ²¡¶ÿ…råÊqùòeÚ·o‘‘ „‡‡óÑGáççÇŽ;ÈÈÈÀÖÖ–¨¨("""¨Zµª¡o• ¼SSSüýý¹páeÊ”r矦¤¤àááA•*U8uê­[· 88333Š/nèÐᕸººâààÀåË—õßÍ¡¡¡úaøO–ùxðà¥J•"++‹K—.ñå—_:ô²°°xn6z­VKË–-±³³r‡_¹r…ÈÈHªW¯Ž……r¹\ß𔓓É'ˆŒŒ$00€€ŒÑjµÄÆÆbmmÍÇ ÆÆÆ† ˆaÆH‰%سg÷ïß§X±bhµZ‚ƒƒ±³³ÃÜÜœjÕªñ×_‘™™‰µµ5‘‘‘DEEQ¹reC‡.| ÞªÂÅìÙ³INNfÙ²eXYY±téRöìÙC·nÝhÙ²¥~Â6€ü1“'OÖ§Uß³g]ºtÁÎÎ{{{üüü˜={6íÚµãôéÓXZZR§NCß'Á@=z„­­í3çw$$$píÚ5nÞ¼ILL iiiT®\™úõë£R©Ø¿?àûï¿Ïט?ÿüsFŽÉøñã)Y²$GÅÔÔTÿÌÿùçŸÌ™3‡Ê•+³uëVJ—.­v&ÿ”‘‘ADDr¹ccc,--qtt4èÌwß}@ƒ ؽ{7sæÌ!((ˆ-[¶P¶lY ºðzã kff&‹/&**Š®]»"—Ë‘Éd4hЀÔÔTæÌ™ƒ¿¿ž¡ŽFFFtéÒKKKNŸ> @¯^½hܸ±~~Óˆ#Ø´i[¶l¡xñâüôÓObˆÊ(33“={ö°bÅ ºtéÂ矮ߧR©Ø·oëׯÇÝÝ*Uªè{zŽ=ÊÞ½{III¡zõê´mÛ6ß[uK–,É„ ضm‡¢\¹r´iÓ777$IbìØ±¬_¿ž­[·R­Z5Z¶l)’)} BBB¸xñ"eÊ”¡|ùòú>FÃÑ£GÙºu«¾…[.—M½zõhݺ5fffœûŒV­Z‰%%„BÃÈȈ®]»bccéS§ËåôîÝ›† ê?£#GŽÔ—Uüüü3fŒ~xeAuûöm¾ùæ›<ÛLLLèÙ³'ÎÎÎ$''£R©8|ø0'Nœ`áÂ…Ô¬Y“;wòÅ_è++«W¯æöíÛ¬X±‚Ò¥KóÇ0|øpš7oNÕªUINNæÜ¹s¬_¿6oÞÌ”)SèÝ»÷3“q ùÏØØ˜#F°{÷nŽ9‚ƒƒ&LÐùuwwÏSV©Y³¦(«õÆÖGqæÌf̘AÅŠõ-þ%J” oß¾„‡‡süøñ§ææÓ¾}{Úµk—À¿Össs£ÿþhµZäry^ãKx;aaaüñÇ|ñÅxyy!—ËQ©T=z”µk×âááÁĉY¸p!÷îÝ£M›6œÏ6ccã<#áÔj5»ví¢víÚÔ­[¹\N“&M¨T©’þ˜M›6ѲeKd27nÜ D‰øùù±oß>ýê6mÚP´hQ wšŒ$Iùºü–ðr...tíÚ•/¿ü™L–ç9ËåðÓO?‰²ŠP ¼qmðÉ26...O OS*•XZZ’ýÌŸý÷ãßÞù—¿`O~A=é}ÿçö¸¸8Fމ··7ÇgÈ!”.]š… råÊúöíKÕªUQ*•LŸ>éÓ§3pà@ªV­Ê€(W®Ü3Ÿ…B£££¡/à…-¢!æý I’þßÿ~Æ8ÀâÅ‹iß¾=gΜaÕªU˜˜˜ T*quu¥aÆT­Z[[[´Z-ÑÑÑúL‘yÖë}ÂÍÍM¿.¤‘‘æææìØ±Ã ‰}¿ì;^ ƒ•UÔÀßÀ“¤š2àò?þN&@qr( ÿDZWÈ­Èþ«ÂêããÃäÉ“Ÿù–qqq@î4„øøxÊ”)£ÿ^‘Ëåú Èqqq¤¤¤°víZvìØ¡ÿù„„|||ôë(ûøøä¹BÁôdºÉ󈲊PP¼ñ“hmmŸŸ?ÿü3½{÷¦H‘"Èd2²²²8rä/^¤M›6†¾>Á@T*{öìaݺu´oßž&Mš`mmF£áÂ… ̘1ƒ¾}ûÒ°aC‚ƒƒ™0a™™™4nܘåË—cnn®?—½½=&L@­VçÙ.†¤Ñhصkׯ_§fÍšT¨Psss¢¢¢8tèÇŽcáÂ…xyyCNNÞÞÞOëÉrOŽ}™'‰O ‘TL„ÿ˜Ðù_Ûªÿëïy•cžÃØØ ‹<’$¡R©€Ü^9ggg¾ûî»< 1ÃÃñ¶¶ÖWàE§ƒ ïÒWXmllèØ±#Ó¦McàÀ/^{{{BCCyøð!5kÖ$((ÈÐ×'ü‡t:&Oëœ$Idgg3oÞ<ÂÂÂèׯ{öìáàÁƒ”,Y’«W¯¢R©øâ‹/hР2™ŒÀÀ@fÍšÅÇ©\¹ò3çœ*•JÑc#’$Ë/¿üBRRUªTáÏ?ÿdñâÅèt:ýR?ýôSž ¨›››¡Cá¦ÑhHIIyj»R©Ô177§V­Zlܸ‘ððp¼¼¼¸sç×®]ÓÏ• b÷îÝ4mÚ n߾ͰaÃèÓ§O¾Î§áÃñÆV¹\Nýúõ)V¬$$$„ØØX|}}éܹ3 4Œ÷˜F£aëÖ­\¸p^½zQ¼xqär9¡¡¡Ì›7"EŠ0sæLìíí©U«gΜ!22’~ø%J<5„ÑÇÇ'Ï"A(RSSILLÄ××Èm¤¹tésçÎ¥N:Œ9ccc¾üòK=z„B¡Ð/ !‚P\¹rå™K¨5mÚ”Aƒé_wêÔ‰­[·Ò¹sgˆŠŠÂÉÉI?,xàÀ|ùå—|öÙgøùùqêÔ)üüü¨W¯Þs§‚ ‚ ¼×ª°FEEqîÜ9üüüðôôÄÆÆ†"EŠÐ½{w233Ñét¿p<¼Pøåää°}ûv¶oßNýúõ;v,íÛ·'''‡­[·òé§ŸÒ¢E ýZ¼FFF…:Ý¿ða eÚ´idffÒ«W/êÖ­Ëõë×™>}:  Fyæ÷”¹Ó‚ ÿ6`À>ûì³gî³³³ÃÝÝ_ý777 ³fÍâìÙ³ÄÅÅѵkWF¥oTö÷÷gëÖ­lÛ¶¨¨(FEýúõ±°°ÀÄÄ„eË–áââ¢?¿¯¯/6lÐ'aþŸN§#..ŽŒŒ C‡"ÿ µZMTTÔ[χ~­Ÿ¶²²ÂÈȈ7’™™‰··7+V¤|ùòØØØúžùä—_~áĉÌš5 êÖ­Ë´iÓ022bܸqøûû:DAx+Œ3†-ZÀ²eË8tè·oßfðàÁÔ¨QCdL¡ÐðôôÄÓÓó…Çouîת°ÚØØÐºukš4iBRR7oÞäôéÓüþûï”*UŠR¥JQ²dIó}íKá¿—™™Éòå˹ÿ>³fÍÒÏÏó÷÷gÞ¼yÈd2‘I(Ôt:çÏŸgΜ9tìØ‘V­Zadd„¯¯/K–,aРA¢²*Â{­nݺ¬_¿žöíÛãääDLL ½{÷¦|ùò†­PJOO'**ŠŒŒ T*áááÈd2nݺEzz:$--ÍÐa Â{üø1`Ó¦MT­Z•ÈÈHzõê…V«¥N: 2D?êòM½vÿ¬L&ÃÌÌ <<<¨_¿>qqq„„„pñâEþüóO,,,¨V­U«VÅÙÙÙÐ÷QxG/^Lhh(³gÏÆÚÚ:Ï>KKKC‡'oE­V³gÏ6lØ@Ÿ>}¨S§Ž¾bêääÄèÑ£ ¢ ÂÎÞÞž_ý•RRRððð T©R"/ÉHIIa„ ¤¥¥agg‡–––ØÙÙQ§NªT©Bjj*—.]2t¨‚ðFbbb˜:u*999üøã”.]¹\Ntt4‰‰‰”-[–+W®ššúVïóÖ ,ÉårÜÜÜpss£~ýúúÖ£S§N!—ËiÑ¢…¡ï¥ðt:\ºt‰Ë—/óèÑ#rrrHKK£R¥JL:õ©Êª F=âäÉ“$$$ P( #%%…É“'ãíí-ÖáƒemmM5 F¡¥Õj fêÔ©´iÓ†O>ù¥R‰B¡xj„ÎÛä!¿èt:ÒÓÓõõ‚3gÎès×´jÕ*Oç•»»;îîîïì½ß¸Âš””„R©ÄÊÊ €øøx8€F£¡bÅŠôíÛFcÀÛ*¼.I’8{ö, .¤dÉ’4lØwww²³³‘$‰€€€·îÒ„‚à—_~áСC„B¡ÀÅÅ…*UªàäädèðA„Bâüù󄆆âç燗—·nÝb×®]Ü¿Ÿ=zЬY³·N8#†´}ûvN:Ett4ÉÉÉ8;;£Óé°²²bذaT©Rå?áµ?AqqqLŸ>S§N1vìX>úè#îß¿OçΑ$ KKK,X@÷îÝéÞ½»ø:Ž3gÎ0eʦL™BÙ²e ’ ¼s?fÞ¼yH’Ä‚ òd²¡`Ñh4;vŒË—/óÕW_:œBK¥RqíÚ5²³³)S¦ÌSKo¥¥¥qíÚ5ÌÌÌ(W®999SªT©<Çfggsùòeììì(R¤ÁÁÁ`oooèK4ˆ´´4~ýõWΜ9CãÆÙ±cQQQx{{Ó¾}{‚‚‚ĪB¡Ë´iÓÐéttíÚ—wÚkú:^«6©ÕjY¶l×®]cðàÁ¡Ó騶mJ¥’áÇãëëËž={X·nM›6¥X±b¹0áõœ>}š™3g2yòdJ—.mèpáËÉÉaéÒ¥˜››Ó¯_?‘N I’P«Õ¤¤¤°råJ.\¸@ñâÅ V¡–’’¨Q£ eþüù´iÓF?åáÉȪ¾}ûÀš5kˆ§ÿþ,X°@Ÿ½V­V³téRÖ®]Ëܹs122bÀ€ú5©?$:ލ¨(¦L™‚½½=óçÏÇÅÅEL#Þ Z­–¬¬,þþûo~þùg‚‚‚èÖ­›~D­¡¼V…õÎ;œ={–þýûÓ¦M ·ö}öìY4h@Æ Q(téÒ…cÇŽqæÌQa-"""˜7o£F¢\¹r†GÞ¹–/_Ž¿¿?½zõÉC¡€Ñétܺu‹'NJVVÅ‹gÑ¢EìÙ³ÇÐázäääð×_ѲeKýè7µZÍîÝ»‰ŽŽÆÝÝI’Ðjµ$%%¡V«Üƾ3f°qãFæÌ™CµjÕ #99YÌûìîÝ»$%%Q¬X1ÌÌÌØ°a¤U«V´k×NŒ$ µ¬¬,öíÛGdd$;§úþýûѹsg5jdè׬°¦¤¤ “ÉòôÀÅÅÅIïÞ½Q(@n"&SSSâãã }}¿¤¦¦rõêU*T¨€µµ5ÉÉÉL›6:hèðá­eddN§#''‡M›6JãÆéСƒ¨¬ ‚åääpùòe<<<°··G&“±ÿ~~ÿýw6lH—.]pvvÆÙÙ™Ç:ÜBO§Ó¡Ñh¨Q£gΜ!++Kß[’žžÎ™3g¨^½ú3+ŸÙÙÙ,]º”72yòdêׯÿÁ,ë•ÍñãÇùí·ß°··'::SSS¼¼¼øé§Ÿ(V¬Øs/„÷$I$$$°xñb¢¢¢¨T© …www:v숧§g‰öÚC‚%IÊó½zõ*T¬XÑÐ×"¼„J¥bîܹ?~œ’%K2hÐ öìÙƒ££#mÚ´Ñ78Ba•““Ãĉ¹qãVVVQ½zuú÷ƒ¡ÃX·nÀÄÄd2’$1eÊ|}} žÁi4û7€­-¤¤üÿßVV¹ûe²Ü?ÿlj*8;ƒ…EÞó+VŒ¤¤$NŸ>MÓ¦M¸~ý:>>>„……å9^’$f͚ŲeËøõ×_?¨Êjjj*?ÿü3·oßfâĉ/^œŒŒ bcc)R¤ˆhø -I’HJJâòåˬ\¹’J•*1gΜ¿<åkUXÝÜÜP*•œ?ž"EŠ““ÃÁƒ)_¾|ž ‹‹ãÞ½{|ñņ¾>át:6l ))‰ 6pôèQ¾ÿþ{¬­­™9s¦Ò"zÙÙÙÌ›7–/_޹¹92™ SSÓ¦%†–““Ã… ˜9s&æææ@¶mÛRµjU>¬OðgiiILL ÑÑÑT«VM,™ö?™™ðÇ””ûºvm8qâÿÿ(W.·bjnr9üý÷ÿ{ê|þ9ü;…““uëÖeûöí4lع\Î_ýÅG}„V«ÍSaÕh4üòË/\¾|•JõÞ–233¹rå vvv¸»»cnnÎåË—Y´h5kÖdÚ´i8::`aa!¦¹ …Γ9×ÑÑÑ?~œˆˆâããñðð sçÎ4hРP${­o ///ªW¯ÎâÅ‹ %-- „B¡àñãÇ\½z•+VàââB¥J• }}Âÿ\½z•Ý»w3yòdœœœh×®+VD¡Pàììlèðá­­X±‚{÷î1{öl}AY„ÿ–N§C«Õê{œ¶oßΦM›øé§Ÿ¨P¡/^dýúõ,_¾;;;¦L™B‘"Eppp L™2†¾ŒÅÚλ­I“¼¿ÈóŽ‘Ëå´hÑ‚þýûsÿþ},,,8wîãÆãСCyŽMIIáêÕ«¬[·Ž•+WòÓO?ñûï¿ãææfèÛóÎ$&&2uêT¢¢¢°¶¶&++ ;;;²²²èÑ£µk×#Ï„BM¥R±mÛ6¶nÝŠ+V¤Q£F`fffèð^ËkUX ß|ó &&&œ:u NG—.]hÕª2™Œ“'O2kÖ,<<<˜0a‚¾UJÈ?)))$%%áíí­ÿ¢=qâ3gÎdܸqúáVr¹\´ …Ò£GHIIÁÅÅsssn޼Ɋ+ÐjµŒ;¶Ð} Ba•žžÎ´iÓÆÃÃ¥R‰N§cÚ´iy†öQ¶lYâââ055kГÕΜ9ƒ½½= …‚š5k>Uaµ±±aÚ´iT©RWWWš7oΤI“˜5kVš×ö¦Ž9ÂüùóéÚµ+õë×ÇÈȈèèh®_¿NíÚµqppY…BK’$"""˜3g …‚Y³fáêêZ¨‡²¿ökkk¾ýö[¾üòKìììôÃí™2e ÅŠû`×å2$FÊ+صkß|ó mÛ¶%22’iӦѻwo}k· VLœ8‘ÔÔT²²²pwwçÁƒ´nÝšO?ý‹OÚá?¡ÑhX¸p! üòË/$%%ñèÑ#Ê–-ûÔ|q™L†‰‰‰¾WU0…BA“&Mؽ{7îîî=s¸¯R©ÔÑöððà‡~`̘1´hÑ‚fÍšú2ÞŠJ¥báÂ…ôìÙ“-Zè·/^\,¡$¼>|È÷ßOË–-i×®Ý{Q6zí kff&»víâØ±cÄÅÅQ®\9Ú·o¿¿?®®®¸ºº¾ò¹RRRˆŽŽ¦T©Rúm:ޏ¸8âââ°µµÅËËK ÉxEG%$$„ùóç³dÉ:Drr2cÆŒ¡råʆïƒ$I¡¡¡xxx`ccä&/»ÿ>éé鸺ºâää$æX¾Føqãppp`Ö¬Y¤¦¦réÒ%*Uª„­­­h 7¬¬,ÂÂÂ(S¦Œþ»Z¥Rq÷î]t:îîîâÿç=™™ÉƒÈÉÉr‡ùÞ½{—©S§booo°ÅäóCJJ 111è·ý³¬bgg‡§§g¡)«´jÕŠÎ;cggÇ‚ ^z¼B¡àË/¿$$$„!C†è{ÏÕj5W¯^ÍsÝFFF”*UÊà’$ÍŽ;ضm7fÀ€Èår¦M›FÓ¦MiÞ¼¹Ac,HbbbÈÎÎÆÇÇG¿M”U ‡Gqüøq<<<(V¬7oÞdÞ¼y <˜ªU«šï¥—y­ «$IìÙ³‡iÓ¦áé鉣£#Û·oçúõëüöÛo¯µ¨¬Z­fíÚµœ={–µk×ê·=z”+V€¥¥%:t uëÖ…bB°¡H’ÄíÛ·ùõ×_9r$¥K—fÒ¤Ilذ*Uª$ ‹ IwîÜaÀ€L›6J•*¡R©Øºu+›7o&++ ý\áùrrrX³f ™™™üøã( ìííiܸ±¡Cû I’Ä¡C‡˜1c{÷îÅÌÌŒÔÔT–/_ÎáÇ‘Éd)R„ï¿ÿ>OAH(t:×®]cëÖ­\¿~kkk$IÀÄÄ„ñãǼbò_ËÉÉaõêÕ\ºt‰U«Vé·9r„+V˜˜ˆ¥¥%;v¤eË–²¬"—Ë177×Çæïï¿¿?*• /// ÷ÿóI¢:¹\Ž¥¥ežžW¹\NïÞ½9tèK—.¥GH’Äœ9sò 3´¶¶fÁ‚ý&I.\`Ö¬YT¨P™3g²|ùr–-[F¥J•¸víýúõå¢ÿIIIaÖ¬Y8880bÄ ·ÑqË–-lÙ²•J¥/«ÔªUËÐá ÿ#IéééŒ3Fÿ¹ŠŠB£Ñ0xð`jÔ¨aèßù¿²ÔÔT©]»vÒ˜1c¤ÌÌLI’$éøñãRµjÕ¤}ûö½Î©¤£GJåË——š5k¦ß/5hÐ@š;w®”™™)íß¿_ªY³¦tþüùçžG­VK[¶l‘>|øZïÿ>ÉÈȺuë&­Y³ÆÐ¡8G•.]ºd÷Ž‹‹“ºwï.ùûûK§OŸ–$I’Μ9#Õ¨QCÚ»w¯”™™)Í™3GjР”’’òÜó$%%I+V¬0È5kÖ¬‘ºví*¥§§:”%''GÚ¼y³c÷¿}û¶T¿~}Éßß_ÊÌÌ”t:´|ùr©iÓ¦Òßÿ-%$$Hß~û­Ô·o_)##ã¹çyðà´eËCÝFá4´gÏéã?–¶oß.%&&$ŽÄÄDiåÊ•»‡’Ê—//µlÙR¿-..Nª[·®4þ|)33SÚ³gT«V-éâÅ‹Ï=Ojjª´nÝ:ƒ]LJ$<<\jÖ¬™tóæMý¶ÔÔT©_¿~R:u¤#GŽ:Ä<îß¿/ýñÇ{ÿyóæI¥K—–F¥ßvòäI©FÒ¤ÌÌLiæÌ™RãÆ_XV¹råŠtöìYƒ]LJæöíÛR×®]¥ß~ûMR«Õ’$å~_Þ¹sÇС=åòåËoý¹{­¾ýÌÌLär9µk×Ö'6)Q¢¾¾¾Ü¿ÿU+ÈÜ»wÕ«WS®\¹<û.\¸€­­-mÛ¶ÅÌÌŒZµjQ²dIN<Éã.<%33“ùóçãííM»ví Žð?Z­–uëÖ=µ®Õ‰'(_¾<µjÕÂÌÌŒ6mÚ`nnÎ…  r I!!!“™™‰V«e÷îÝìß¿ŸaƉì¿Hrr2‹/¦dÉ’úmZ­–ãÇÓ´iSJ•*…££#:t 22’;wî:dáÂÃÙ4i¿ýö×®]cãÆlÞ¼™É“'ÓªU«÷¾'õß$IâîÝ»¬[·î©,ÆçÏŸÇÁÁ?þ333j×®ŸŸ'Ož4tØ<µZÍÒ¥Kùøã)Q¢„~»µµ5ãÆcàÀT¯^ÝÐa’$qéÒ%Î;÷Ôþ'NH5033£mÛ¶˜˜˜pñâEC‡ýÁÓjµ\¼x‘ &ФI:uê¤ aooÿÞ®eýÚƒÑåryž qÆÆÆ˜šš¢R©^éçu:Ë–-# €ºuëæÙн½½~¬±±1¥K—æêÕ«†¾OF\\{÷î%ã«„¯\¹’èèhFŒ!²£ /^äÂ… ôë×/ÏöüýýõÿW...¸»»síÚ5C‡\ ÄÄÄ0tèPÆŽË!Cøí·ßXµjcÇŽ¥dÉ’bW²sçNrrrøì³ÏôÛt:ÿýwžÆÈ’%K’Mdd¤¡Cž#,,Œ‘#Gbii‰L&cÉ’%œ:uŠÑ£GðAÎ[Ójµ,]º”2eÊP§N<ûnܸ££#...˜ššŠ²ŠÄÇdzwï^‚ƒƒÉÉÉaëÖ­dffÒ±cǧŽupp ]»vïE–ãw!..Ž еkWüüüòì{RV155Ðç¨ 1tØI’ˆŠŠâÞ½{Ü»wU«V1kÖ,zõêEÇŽ ä4„ÿB¾®­ÕjÙ¾}; ôë×½{÷æÙÿøñc …þæ+ ìììˆáyÓÓÓ¹víöööú×û(--qãÆ‘ššÊš5kðññ!22’‰'~0ì«ÒjµÜ¹s‡Û·oç{vä»wï²páBºwïþTVÌÔÔTLLLô@sssÌÍÍ_úŒ'%%qåÊJ–,ùÞ6L¤¥¥1sæL:uêD³f͸té»víbРA-ZÔÐá8999\¿~‡¢Óéòí}%IâÌ™3:tˆï¿ÿžÌÌÌ<û?~œ§'ÜÖÖFCjjê ÏûàÁþþûoJ–,ùÞ$‰(È´Z-III„††òóÏ?Ó»wojÕª…‰‰ _|ñ999O1„K—.‘˜˜˜ï÷fÛ¶m$''3pà@víÚ•gÿãÇ122ÊSV±µµ}á÷¸$IÜ¿Ÿû÷ï‹ï³·$I7nÜ`ç΄„„àççGTT™™™¨Õjf̘ñZ9U )33“Ë—/?õ=ú_{ÒíååEݺuÙ¾}{žý©©©˜ššæ)«˜™™½ð×h4ܸqƒâÅ‹?•)\x3ÉÉÉlÙ²…;vè{Q˜1cF¡ItGHHÈ[¯áüÚV­VË7ô¤¬¬,ÒÒÒxðàÇŽËslPPPž_x¡¡¡¬^½š &àááñÊïù²Â˜L&C©T¾×½/ÙÙÙÌœ9“¢E‹òÝwߏsçèÑ£‡>i‚ðÿd2FFFù^ðU«Õ¬X±‚bÅŠQ¯^½W®HHÿKdò5ê}rþüyŽ?Δ)S õÂÖùI©T@XXX¾>ã‡âÁƒ\¸pëׯë[Ü'L˜@½zõ066F­VëÏÎÎÆØØX¿¦ãóxzzâïïo˜›ù çǤU«V|óÍ7úž“‚ÚPP®\9ø²J~øý÷ßQ«Õ|öÙg¢·ú Ó AbbbôÛžôþ?i¼úwY%>>žøøx5jdèðßk:Žýû÷óÛo¿Ñ«W/5j$z¬ÿçµ>í&&&TªTIÿúñãÇÄÄÄ™™‰‰‰ vvvú„IÏÒªU+Zµj¥ýÛo¿‘””Ä?ü ¯¸.[¶Œ#GŽÐ²eK¸xñ"3gÎ4ô}2˜G1}út†*Zf  ¤ýd ¿:P­Z57nÿý7%J”àèÑ£$$$|Ðë‰þþûïT©R…   C‡"¼‚Ê•+çù=páÂöìÙÃàÁƒ155%,,Œ}ûöѤIÌÌÌØ¾};”-[ÖСp¢££ùûï¿ F«ÕJÍš5iݺuíQ-Z·nMëÖ­õ¯—-[ÆãÇõe333–-[ƱcÇhÖ¬¡¡¡\¾|™9sæ:ô÷Fff&éééH’¤ŸvÂåË—™8q¢hly –––tîÜ9϶ˆˆìíí0`2™Œ 0qâDBCC)^¼8GŽ!))ITXÿ#’$Çúõë¹~ý:³fÍÂÓÓS|OÿÃk7OI’„J¥â¯¿þ⯿þâáÇdeeabb‚ UªT¡S§N¸ºº>u£ÿÝJ T*166Öowss£cÇŽ¬ZµŠC‡K³fÍ(]º´¡ïS¾$ ­V‹N§Ó·®Y³†råÊå{â BG L̵ “Éò<÷O²j+ är9+V¤nݺŒ?'''¢££éÖ­[¡›ð:$I";;›;v R©hÕª÷ïßçÂ… Ìœ9S´"ÿ~Æ …>‘˜B¡ uëÖ\¹r…ÁƒcffFRR#GŽKåé‹Éïܹ“íÛ·S¡BJ”(™™7¦T©R¢ô¯RVéС¿ýöû÷ï'66–-Z`èÐ =I’HIIaÊ”)$''caaJ¥ÂÚÚš²eË2~üøB5Gµ ú÷w8äöºþs¾xPPµjÕbìØ±yÊ*/›Ú!¼I’P«Õú9Á×®]cæÌ™”+WŽ)S¦àââ"¾§ÿåµ+¬©©©Œ;–³gÏH‡puu%++‹«W¯²k×.<ÈÌ™3)]ºô oøW_}ÅW_}•g[—.]¨W¯¡¡¡øúú>•jû}ÏøñãÉÊÊÂÇÇgggΟ?ÏÊ•+ßÛù¹ïŒœ:¼Œó,YcnnΨQ£¸~ý:ÑÑÑT¬Xñƒ*ÆÌ™3qvvÆÁÁ>}ú––ÆÄ‰ß:{œ`8•*UÊ󌻺º2þ|.^¼ˆJ¥"((¨Ðdì,ì4 'Nœ`Ù²e/^œùóç‹ÏÖ;н{wºwïžg[·nÝhР7oÞ¤X±b/^ÜÐa¾T*'NÄÃÃéÓ§:œÆÜ¹só¼¶°°`̘1\»v˜˜‚‚‚^8Uxu:޳gϲ`ÁÜÝÝÑh4ddd0jÔ(1é^«ÂªÓ騶m/^døðá4jÔ }¥´eË–´jÕŠ™3g2gÎf̘ñF‹)RäƒjA“$‰ˆˆ¦NJ±bÅhÖ¬7oÞääÉ“ 0@TV_Å ë Á4ß²eË~P_L—.]bÖ¬Y|òÉ'´lÙR?'&99¹P&Ê^L©TR½zuC‡ñÞS©T\»väädn߾͑#Gèß¿?5kÖÃ&ÿcÞÞÞbÞý;ôd R©¤G†G 7éÙ?×ÕÞ^hh(‹/fÈ!øúú¹¹ Ä(¤{­ kBB;vì cÇŽ´lÙò© ïFFFT¬X‘Q£FñÕW_qûömªV­jèk,𢢢6lŸ~ú)Ÿ~ú)¥K—¦]»v†­ð0"w(pº¡þ-''‡)S¦Ð«W¯<ËÔ8;;¿4«¦ ÏÇ’%K¸qㆾ×ËË‹åË—ckkkèðáµdff²`ÁBCCY¸paXXÞµ[·n1aÂúõëGPPöû^«ÂF£¡råÊ/ÌÎæé鉯¯//^Ö—P«Õ,_¾œ† Ò¦MC‡Sx¥wÉía ­VË–-[(]ºô YÞNÇ7X¸p!%K–dñâÅo4’I E«ÕONN&&&DDDð믿âççÇÔ©SEeUx/…„„0qâDºuëFõêÕEeõ5½V…5##N‡ƒƒÃ {²²J¥2ôõ8OÖà|Rá?uê >\ ßzJ  …b8ðûL­VsðàAœ âÞ½{lÙ²…_~ùE m„w 88˜iӦѳgOêׯ/–ö óçÏ3kÖ,lmmqtt$55•V­ZѼys‘|Ox/ÄÄİk×.Ê—/Oùòå¹ÿ>'N¤S§N4jÔ…Baè ×úMgoo\.'<<__ß綨T*âããE²‡Q«Õú´øÄÚÚšåË—Ó§OÌÌÌ ^áö7ðÐøp¦?8ׯ_ç·ß~C¡PàææFzz:Ÿ|òÉ“XJÞ­VË¡C‡ØµkÔ®]›ˆˆÖ®]ËСC …{¡P‘$‰3gÎ0wî\¾ûî;}Ve###,,,Äó,z:ޏ¸8~øáŠ+ÆÕ«WIMMÅ‚P­Z5QY}C¯UaõõõÅÉɉ;vP½zõ禷>vì©©©b)–9tè?¦Zµj 4¼¼¼Äú“ï‚ ¨ˆ)‘“––Æ‚ èÝ»7+VäôéÓ„„„мysC‡&…JFF+W®äôéÓtèÐû÷ï3oÞ<"##;v,•+W6tˆ‚ðÚ¢¢¢X´hß|ó 5jÔ0t8‚ðÎݼy“)S¦Ð´iS>ûì3d2·oßF¡Pàïï/eÞÂkUXMMMéÛ·/ß}÷£F¢K—.xyy¡T*Ñét¤¤¤°oß>~ÿýwºté¢Ï~%ÀÕ«WY´h¿üò ®®®Ô©S‡ßÿþýûcjjjèð ?„ÎJH†F£á·ß~#00  —ËiÙ²%Íš5­‰‚ðŠÒÓÓ9uê›6mÂÍÍeË–aff†$Iäää ÓéÄh¡PÚ¿?Ë—/§ÿþÔªUËÐáÂ;ËÈ‘#éß¿¿¾¹IT…·÷Ú“_9r$sæÌaðàÁxxx`dd„$I$''OÛ¶méÔ©“˜³ö?:Ž5kÖЮ];\]]‘ËåøûûóÓO?:´÷‡ àÜ3t I’¸}û6'OždΜ9yZEeUžO«ÕM\\÷îÝcÿþý¨ÕjzõêE¥J•ô¿Ce2™hØ I’Ðjµú×gÏžeîܹ <˜:uê:>>†¾®C§Ó±råJLLLèÔ©“xˆÿ+ò€H–™ïbbb˜1cÇÇËËËÐáB¡pëÖ-–/_ÎÝ»wñ÷÷ÇÙÙ™®]»R³fMC‡&oìÉÜëyóæáëëK\\Z­–+VàââbèðáÈÊÊââÅ‹899áááÁÒ¥Kqqq¡}ûö¢¡þ?òÆéíììhÑ¢-Z´xj_ZZ‹-¢Gü:‹>äàÁƒŒ7®ðeÖüïOahØ·&·‡5ÙÐ|X4 K–,¡L™2:A(ð4 `ñâÅ´nݚѣG?7„ &’$ÌÒ¥K=z4¾¾¾¤¥¥aeeõÁ—…÷GFF , ,, ¹\NBBöööÌœ9cccC‡÷ÞúOòágff²råJ>ùä“úKJ£Ñ°xñbêÕ«W8çóžÎƒ€‚Þ`´ŸÜemb ȇåÀDGGóí·ßŠVEAx µZͯ¿þÊñãÇ™7ož$¼7$IâÚµkÌž=›±cÇR¦L€º (¼Ôj5ãÇG’$–,Y‚±±1‰‰‰˜˜˜ˆõƒÿcb·ÿˆ$Iœ>}šÄÄDFŽY8 ó©ÿû#:—þ÷§"nè`>ׯ_gåʕ̜9ó¥k3 ‡H§Ó¡R©ÈÉÉ!33“7ÅôéÓñðð0tx‚ð΄……1qâDºwﮯ¬ ÂûD¥R±råJ”J%ß}÷¾7U”ò‡¨°¾ÉÉɤ§§ç™¿—••ŪU«èܹsámu1â€l  _‚øP€î†èý—““ÃÂ… ùøãżUAx­VËعs'fff¤¥¥áââÂèÑ£±±±1tx‚ðÆRRR8zô(AAAxyyŤI“øæ›o¨_¿¾¡Ã„ÿÄòå˹|ù2‹/C @TXß’N§cÉ’%ܸqƒ¥K—ê—øë¯¿pss£zõê†ñÍÝÌ™¡ù5ð¬iÀ©À zŠõ=òdh»F£¡{÷›³lÙ2<<<øä“O ž 8aaaìØ±ƒ›7oÒ½{w|||022ÂÊÊJdû µœœ-ZÄ;wøý÷ß)V¬4mÚTdGÞKjµšµk×rãÆ Æ'*«òZVFCll,999/<îÑ£G†¾®|ó÷ßsþüyŒ9uê5">>ž72iҤ½´%¹•A`aàXÇÎÏØg 4l ç{(!!Ó§Oãìì̈#hÙ²%`É’%…ûù„w,<<œmÛ¶qìØ1š6mÊܹs±²²2tX‚ðNèt:vïÞMdd$3fÌ@«ÕrôèQ*T¨@›6mDeUxoܹs‡C‡‘““ÃˆŠŠböìÙ¸¹¹:´ÖkUXCCCùþû‹{áq’TÐ'=¾ééé,]º”Þ½{ãççLj#àÏ?ÿ¤lÙ²øùù:Ä·s‘Ü!¶Ù†Žòì ë#àð)° hAÁOUH<é]mÓ¦ ü1`Á‚üðÃb‰áƒwåÊÖ¬Y@RRYYY4hЀõë×caaQ8sÂsœ?ž72qâDý¼½Ï?ÿN'*«Â{!''‡#GްtéR:t耧§'AAA-ZWWWC‡÷A{­ «§§'C† !++땎ß["Ο?J¥¢víÚXXXP±bEV¯^ÍÉ“'™5k2Y!ŸªJQ0*¹•ÒgÉ"þ÷ïúÿ‹ÛÜпnݺEXXC‡ÅÔÔ”V­ZQºti¼¼¼ ÿó-o!33“Ù³gÓ¸qcÊ–- €¶¶¶†MÞ©œœV¯^Í_ýÅ€žZõ@TV…÷$IüòË/œ>}š‰'R¢D ñl ¯Ua522ÂÉÉ oooììì »AÅÇdzxñbÆŒƒ…EîxÙN:Ñ¥K>ùäJ–,ièß^ ¹ë°„™Î¶ä.[“Fîš«ÿ¤žtfG‘@ C\øiµZÖ¬YC›6mò¬Y(—h„wèÉúÃåÊ•£K—.†GÞµZÍÞ½{Y½z5...˜››‹¯¯/ .ÄÝÝÝÐ! Â;—œœÌÒ¥K‰ŠŠbÑ¢EØÛÛ:$á_^«*ò$ÿ€ôÉ„âââØºu+½zõÂȨ Ôlþ{999,_¾œŠ+RªT)ýv&Mš”g[¡vžÜžÍ:€¡³v‡k€ÏxºÂªž,g˜$ *¬oI’$îܹCxx84t8‚P Ü¹s‡ .0}útC‡"ïŒN§ãÀ¬ZµŠaÆannNbb"¶¶¶”.]Z qÞ :Ž‹/rüøq6lˆ¯¯/Ó¦MC&“1aÂ1J¦€z­¦J¥"%%F£ß–˜˜ÈúõëéÑ£‡¡¯%ßœ>}š{÷î1}úô<_àr¹œ5j:¼wÇÜÌ»†Î«#ÎäöøÆðte4–ܹ¶_öä^Khh(ŽŽŽ899¹S£FâÇ-ê‚ð‰‰‰L:•îÝ»‹%„÷†F£a÷îÝlذ)S¦þ‚ð ’$qîÜ9æÎKýúõY¾|9ÑÑÑT©R…êGL O¾w‰J’„J¥"##KKË<™F%I"++‹¬¬,Œ±°°(0cÈ%I"22’eË–1hР÷»&¸KîPÜDþ¿Ó$à àϳ{zÝÿ÷ïò@HÊ©Õjyüø1jµ333ÌÍÍõϱ$Iyö™™™t>hZZ£GÆÊÊŠ~ø///fÏžMÆ 4ô­ (µZMzz:Z­ssó<ϱV«%-- I’°°°ÀØØø½˜ó,I7nÄÁÁzõê:á?T˜Ë*¯ëIÓÆ3fŒ¨¬~ t:ÙÙÙddd P(°¶¶Î3RR§Ó‘žžŽZ­ÆÜÜSSÓBý=.I¡¡¡,X°€!C†P¥JÔj5 ØÙÙé—¥ ¦|¯°FDD°xñbnÞ¼‰N§£J•*tíÚOOO w™˜U«VqëÖ-ÜÜÜèÒ¥ ÕªU+CQ"""˜4iõë×§råʆç¿•Cnv`Kr+®†$‘›HI „eÿµÿ¹=¬u0@ T2\¸lß¾={ö€mÛ¶¥iÓ¦h4NŸ>ͪU«HLL$ €.]º`Xu:›6m¢bÅŠ”-[–Ÿ~ú œÅÜ<á¹=zÄêÕ«9{ö,éééøûûóõ×_SªT)²²²Øµk[¶lA§ÓQ±bEzöì©ï½/Ìn޼ɘ;w.J¥òíO(X÷ïßç—_~Ñ—UªV­J×®]ñðð $$„U«V†»»;]ºt¡jÕª¢¬òºÂÃÙ?>ƒ 2Øï"!ÿ>}š-[¶pëÖ-,,,hÚ´)Ÿþ9666h4Nž<ÉêÕ«IJJ¢T©RtéÒ¥Pçg¹sç&L W¯^Tª”[HT*•bY!‘¯ÍIIIL:•¸¸8†ΰaøyó&Ó§O'==ŒŒ ~úé'¦L™B`` “&M"<<Ü 7)11‘yóæ1jÔ(êÖ­KÇŽ Ï;“ èž³O#7KpA˜Z‚ÜJ¨í3ö©þñïú@ƺgÏ~þùgÚ´i ô=–/^$<<œ &P¹re&Mš„Z­fܸqdgfí ‡rðàAÚ·oO‹-=z4%J”`øðᢵQx¦œœ–-[ÆáÇéÕ«“'OF.—3aÂîß¿ÏÁƒY¾|9_|ñC‡åÆ,^¼µZmèÐßJbb"3gΤW¯^b(ð{îIY%>>ž#FðÃ?pãÆ ¦OŸNFFŒ3…BÁ”)S(W®“&Mâî]C·î¾¾ÈÈH&MšD‡ô…xáýÁĉ155eöìÙtíÚ•Í›7³råJ˜8q"ÕªUcÒ¤Idgg3aƒ•UÞVNNóçϧqãÆÔ«W¯Ðކø½V«B¡@&“ñèÑ#îÝ»@tt4Z­–û÷ï?Õâìáá±±±þudd$·nÝbáÂ…úÄD¦¦¦ôìÙ“´´4nÞ¼‰J¥¢W¯^øûûS´hQŽ9ÂÑ£G)QÂ0µ¦øøx~üñG|}}™:uª¾uõ½ ¸EŸ³ßH.ýDZ¨È†ìýŒ}¹½¼~ä® Ûì_û]€Úÿûw p0àTâ£GÒ¤I>ùä ƒ&,,Œ“'Obdd„››_|ñÖÖÖôìÙ“råÊ}"³ü´yófjÕªEÑ¢E‘Ëå”-[V¿D‡ xRVùgCù?Ë*ÿý7nnnú©L¦¦¦-«¼Š¸¸8–.]Š%K–äîÝ»>|˜o¾ù†š5k¾åá…ìììøä“OpsË-<Éd2}Yàúõë”+WN_VñððÀÃãPVXCBBX±bóæÍ˳DŸP¸¼V…µH‘"Œ=šœœœW:ÞÅÅ%Ïk???†ªœœÌš5k¨R¥ VVV}úèÿ-I{öì!::š~ýúqìØ1*T¨ Ol`mm QQQ/÷œ999ìÝ»GGGŠ+–¿7ò9T*sçÎå£>ÂÕ5?z_„»uëýõ×[O9x­Rµµ5UªTyëàÓÒÒ8qâK—.ÅÕÕ•Ÿ~ú KKËçÿÏetžÅÁÁjÕª½Ó‚÷ªU«ðöö¦W¯^ïger“Eúè#ƒd¡ aæÌ™4nܘŽ;ê+Ìbx¼á}úé§ìÚµË ï––ÆñãÇYºt)îîîú¤tÏ󢲊L&£råÊï¤ õ:’““™6múò̧Ÿ~ †F¶¶¶´k×Î`½óñññlÛ¶­[·R·n]z÷îýÂã_TVQ*•4iÒ$ÏÈÊüúìwxÕ×€ßÝì¦W¡Ð{‡Ð;¢JS,X>ý!¨HµcAivÅ(•& ½„NHHiÞ“M¶Ì÷Ça7Ù4Dƒ 8ïóäQvfg§Ü¹÷ôsž•+Wòè£Ò A²²²X°`í۷稔sRgåСCÉÊúgáÛŒm2™l!Âùùù¥NÔE[y€-™™™¼ùæ›\¸p±cÇ2hÐ üüül‚Š¢(h4EAQ”ëZ¶­çQ‚޵ìõX¸pá­­¬šL Ñ@Yáž—)» R:ðÇïУ(Œ©Hû˜¿ŠÁË–Á}÷—WÙûY,PP `·§„W·@n.$%ANø4Fpï]ðžôN77Q8vðT_9ž£FuC\ ’ƒö/FT$F£‘ß~ûe˖Ѹqc–,YB£FlãJŽñë[¬á:ERRyyy·¾Å11¶n…I“d¬ß \¼ òý¿cð2`ùrÈ˃‰¡U«²Ï#?ŒFñè:9É{™š ³f‰Âݬ™œÃ‹/ÂþýPÔë®(ððÃШ\«¶«ñôÄðŒˆ@{e°"QƒÁÀ—_~ÉÖ­[4h#GŽ$ £Ñh×…·Ù‚^¯¿n/­Vû¯ Ћ…óçÏóÚk¯1räHÆŽ[)Þ]•²©¨µýFP…ôôtÞzë-ÂÃÃ7nƒ¶Uº.:wÿYåß";;›wÞyNǃ>h“gTEµêP‘òë`•u/^LNNÏ=÷}úô±dþެR™×’ššÊ’%KP…3f0mÚ48@zz:/¼ð­-ËßâTÔÚ~Ã+³ÅbáâÅ‹¬[·ŽvíÚÑ­[7¦M›f¶«Ñh¨V­ß}÷¥%--yóæ¡×ëùä“OJ”’nÒ¤ ááᤦ¦âëëKAAçÏŸÿWC òóóY¾|¹]lÿ-‰É~(Þ§Ò<{F 3ð0’^ÍܨQ ^ò¯…Ü:ñ—Ñéà™gàZq-rsa×.ðñÁ¼Z5ù|Çñ úûÅÓzõ*Ìž-ž¯ `ø0Ê:¶€û€ŽuÅÛk6‹²Û½´õ–ãi4 ó†V] :¢ÐþËlÚ´‰Ï>ûŒ¹sçÒ½{w;E³yóæÄÅÅQPP€““‰‰‰\½zõ_·ºoÚ´‰>}úàUž1¡ª£ÓÁý÷‹wôž{lŠÜ_ÆÁ¾ü²ü}¬•m‹/vbLñö†7Þ€?þ€¯¿†ùóeßK—d,õ8~ù%üù§D<ý´¼#FÀÀ…aÉ..p-,Ëvžýû—<·êÕ±<ô ^^ý‹J–µÚâ©S§X°`Íš5³ (†fÍšqéÒ%[ŽkXX:Îf˜¬ ¤¥¥qñâEŽ9ÂÏ?ÿÌ+¯¼ò¯¿ƒ*U—ÔÔTæÎ‹³³3Ÿ|òI Y iÓ¦\ºt‰´´4ªU«F~~>¡¡¡U& dŒÏŸ?GGG^~ùår=Ã*ÿ=¢££™9s&=zôàÙgŸÅÙÙ>„®yóæÄÆÆb4qtt$!!ÄÄD‚ƒƒ+ûÔK`6›ùàƒhÔ¨Ó§OçØ±c¼÷Þ{¸ººòÎ;ï”Á©rëpÃRÎÅ‹™:u*ùùùv ü=÷ÜC·nÝøõ×_¹pá3fÌ(QQ744”£Gòá‡RaØŠŸŸ:t`ÅŠœ;wŽnݺ‘œœÌñãÇ™öwÃõþÇŽ#55ÕVýò–$?V¬€¸¸B…±8ÙH‘£ÖHkQ…UŒîð÷ˆðýU(D§À3ÝÅ;d6CV–x§RS¡wopvo“Ù,¶££ýo[,âÉÚµKö™9SŒ&MॗàÛxmßš5aéRñ¢¢0¿õR½¸6ò;ƒKs¦EÎý*Â\ X,Ö¬Yc«¼›`ÛæææF·nÝøüóÏIHH víÚ„††OÏž=ÿµs4 ìß¿Ÿ7ß|³rnÒ?EQàäIQX[µ‚9s ÇÊ_¿ 2­ß3ÅKZÔC’”$ãðÒ%4zH~;3SÆñ¹s0}ºŒõ¾}¡Gù‹.\€o¿ƒËäÉ2|ÿý0nœl·þNµjp‹UÍÈÈàçŸfÊ”)xyyqåÊÛ6///ºvíÊÞ½{9r$:Žýû÷ãååU%ú÷ ¶lÙÂO?ý„¿¿?Mš4á½÷Þ³U­WQ - áÃ?DQ;Y¥fÍštìØ‘o¾ù†óçÏÓ¥K’’’8qâD¥¦X˜Ífrrr0¶¼=NÇK/½¤*«*v(ŠÂŽ;ÐjµÜy礦¦Ú¶988P³fMºuëÆòåËILL¤fÍšœ;wŽ„„„*§°šL&Ö¬YCZZS§N$½dÉ’%hµZªW¯^Ù§¨RAÜÂZPPÀ‡~ˆ«««-Ì1==j§wß}7ƒæã?æ§Ÿ~¢sçÎ89zåÂÂÂHMMåþûï/qì;wÒ´iSú÷ïÏ;ï¼Cpp°­¢jy¹I||<Ÿ}öÏ?ÿü¿ž_¡$'CL ̘!!†11¢µ  ­d ©®kÅT÷Ö×>å+@WxkÓÓáãÅÚµ«à ^¦-[Ä›:s&Ícpw‡GK)p­McD8Ø+ @+@(ªñ@‡"ÇXÔ¸¶M˜r%””ÄåË—9~ü8ßÿ½Ý¶G}”'Ÿ|’mÛ¶1kÖ,š5kÆ>|8õÿNæß$<<½^O@@À??Xe`4Â’%" &{£,[uëŠg$´xÞ<ñl6jVc\êkUÊ ñ¤†„ÀË/Ûk²þ¿V Ɖ!g÷îÂü (–UˆŽŽ&11‘9sæ”Ø¶xñbÆŽËìÙ³y饗ðòòâèÑ£<óÌ3øZsÎ+‰´´4>ûì3¢££yõÕW«tÅâÿ±±.Ñ7íÚUöÙR$$%%¥Ôžë»wï¦Y³fôíÛ—·ß~›îÝ»Û*ªV¦—þüùó|ôÑGèõz, <ñÄÿí¢z*¥b08þ|vî„÷Þ+ü~­ZâAÍÌ”üR#µÂ´Õøâä>< vy¸¹ÝrÞÓ¿BóæÍË,‚S«V-ÜÝÝyï½÷ؾ};ƒñãÇWºw555•Y³fQ»vmÞzë­[;þï’’"ùÖC†HôKYaäƒDÏÄÄHH{ãÆeï Ñ“™)뇇¬%yy…ëOÑÜ{E‘PzE)4¦.\(ï¬V[¨°îÝ+‘ îîöaõÿ#GŽ´“]Šb5¼<ûì³téÒ…Ó§OóàƒÒ£GJWYYY|üñÇôíÛ—>}úàää„››ŽU¥ú¹J•ÂÉɉ矞I“&•ØfÍá÷ööæõ×_gûöíÄÅÅ1wî\ZµjUÙ§nÃb±Â×_ÍŒ3Tõ?À )¬ÉÉɘÍf‚‚‚l ´NNNôéÓÇ®4º››¾¾¾œþþþLœ8±²Où}ñâÅ2eÊ”¹Z·ŠgÏÊ߸q¥ï!óûÀ”)б£|n6‹r˜ž:ÉûñóÏÉpäˆÓéd»‡‡½&Ñ ©©0v¬(ÃiiðÑGò™^/ÆS8q~üQÖ°aÃd}«SG GÅ ÊÕªQQòþ^§KÀÍÀ××÷ºnnn 0ÀÖ¤²0™L|ýõ×x{{3jÔ(UIU¹.Z­öº5Z4 >>>•/+”Axx8o½õ3gΤ£u.S¹­¹!…ÕÙÙFCnn®Ýg÷Ýw_‰jÀf³ùºm ª k×®%&&†ùóç_·’åMÅÁyŠ*3yy¢|fdˆ€Þ „ã®Y#ž¢ DXùáøýwxë­’ÇíØQ>·öÅ €ÿ½?:Âh §M»–ƒç så ’çZŒÜ\9­²æ½íÛ¥Øé–-p¯\¢°SXøŽÓE˜R Zö‡À#ÅÆ–Ÿ înHû›"\„?7øq<ÚnáˆîŠ&%%…éÓ§“••…Á` qãÆ×U8nâÉÈ8?p6o–ñÞ¶­ŒñÔTñžîÜ)¡æ>*Ÿ½ñfw/”Ðõë]z^víÚ°h‘xw¬ÒZµÄ¨"”[ùùéŠ"r¸«kéE±XDGvu-»@·«sªzõ/r¬r}Ìf3_~ù%éééÌœ9Ó.Eå¶!/¾øB&[kM~¾L®žžònT«&ë@ûö2q[ïÃöí’km6K¥l??ÉÍÖjEYtt”ã}ù¥T]\¤h˜ŸŸ¼wÞ -[Š7Ä[úôÓ…Ñ ÖTQhkÖ”œn(û ’?9àܹʾËU–ƒrèÐ!>øàUYU¹í1›Íœ={– ððÃÓ¡C‡~P•[‚RX«W¯ŽV«µåkXËW/’’ÂÅ‹™`«0ùùù¬Y³†9sæüse5+Kráþn¥@F¤á¢ñÂ…)BÆoHh¢üßÿîSP E^^|Q„‚â88z—¬ÿNu€ ¤}Í/H~ªÕsdºS˜×ê‹x9$GôrzÓ¦‰¼R”Œ ÑMV¬®#_¯‚Ç| k;ee‰¾òÞ{ „Ï?‚þg`X2hs"Î3åœÔZúq?Ìyj¦ÙÿVª$fÀÔÿÁ§ŸBÖð®¨ýи|ù2ÎÎÎ,^¼˜ÜÜ\¯éP&—.‰¡¤_?Xo³YD§N…¡¶ o¾)l\œŒõ'Ÿ„æÍe»Ÿ¼þ: ?ýÉå­)të«P¦^W^®V‚qv¶lºÞ«o6‹¥ÿ²ë˜YÉÍ•}G.l\ ðÉ'4q½B†çÏ‹ñgÊ”ë;¦U„}ûöqäÈæÏŸ{(«¹¹’ó™›+ƒ×Z¬­S§’aêÑÑ’Cœ,ãkÖ”Á^4lµ{w™¼½½ _¦0Ø:МœD =zTdë`mÚTþŠâà ¿øà¯^úô©ì;x[a4Y¾|9=ô­åŽŠÊíLHH¯¿þ:Ï?ÿ<={ö¬”¾Ý*•à ž֫WÞ½{óÍ7ß°oß>ŒFûÊ6Š¢Æë¯¿N@@‹æ˜UQ6mÚD—.]þ™•&) Þ~{LÂË#),Tœ´4xê)ÑôŠ2mš„TÍ+ÞÔÒÐëá•W eK D¤¨RNé_!ÈDÂp{s­mM‘ïmƒðS"xÌ@PÄI•Ÿ/ çý÷‹Lôý÷’údåìY‰I•+ES§DÁ-þªÇh”¿uëþÚ¾>>r®·ohha±cë»SÞ£˜eŠHÃV²³EÈX'rÅS)ÛL&©Êø ñäç‹ó«zuQî²×—ËØ¹%Щ¸›Š÷”l¸´KçŽo–‡±k³kWaÈcÆ¢l6m*úJLŒë¶êçyP+>xÆ4ƒÓ§%íÉÖè4”ÛØ i$iŒ3fÀšõP'\ês88@מ0s,„ì9îîI0tpa­^/Þ ÷ˆ×êÛokc0Ü¡€“mÛ¶Ñ¢E »¢h™ü|É ]¿žß‡èüZòÀ­ Åž=°j•hh/bZùÇúO'¥ÀCòÎΞ•Pß¼jZÁ–¿µ’{xxðàƒ²páB–-[ÆŠ+X¾|9}ô³fÍ¢¹5ÿ¬ c2™Ø¶m÷ÜsÏ 4 ¦»é–ëºu%¼÷Í7E"ظQ\$ºöã,Ee^{Mâü¬Å–ŠçÝ QQRËæÉ'ųôw8w”’V°ì†ÃÛà« Ô Š(£F¾;m»JÊQ‡!p$¿ÐÁ%úú!…ßñîê*áŠÏ?/Qc¶¦@]'à/M—BÆ Òó5[6µâ#Fˆ~sh7ô(ætJ€±]¤ðñ¬¡U±(j½ëaÜ><GÇJjÊZÉ vïÞMß¾}oüË™™ðþûpå J÷œ;'2¶~~R´eÚ4¸|jÔ súk¼ú]c¶nEÙY³ä])%–66VôÙ;®:‘‘’¶íì\¾'Òb‘ðô¡C¥æŒ-<¾L&)È›+¹¡åyCCBDwhÕ Ö®-ßÃyì˜DXöí+ vYÇÍË“ãÖ¯/ vVVÙÇ={VRã=<$ŠsãÆ¤ÿ øþûï1bÄß3FÞlöï—µaêTq±ƒ ê”X¹R¬ =€_xA¢kTTŠ`6›ùþûï2dnnnÿü€·00gÎ_3PV) ‹}äåUöÙTYÌf3+V¬ÀÅÅ…Ñ£GW=¤Ê¿Æ ]*Šƒƒ~~~·dï£ôtØ´)”„„:tîÜùÆC Ö¯—œ¡Ñ£KöBµ,ñ©Ö\ŸzõDûûÆUÂkÇŒ‘ê¨~~¢ôþÃðé¬,éÜñ쳎إ $wßþ€˜Ðg€}Zài'øã øÖ†_B |.Œ}LN)1ÂÛÀ¤&"x¶…Ÿ~†6Š´R ‘ÏíÒ˜ö‚Þ$úɾ}…QX#!Èç¢NÖ5Ö ¬ýÖkQPÍUnј@q…¦#è]ijÛ0(îñjøƒSøù Õþ7=¬ééédffÒâzU‚JCQd ÷éC¾A¦èhñŒÛhÑB*‡?.ƒÁÛsoüüÄùúÀm%Ÿµ Ο—N2¿þ ÷Þ[~››t²™1Cþ[V‘ã„Qê¬k¬ÝsJ#,L #wß-a¶IIeבÒhÄ£×K˜|JJaÑí¢äæŠ'¸Oñľþº´bõô,ý÷­ûk4ðî»bëêÖ­ä¾™™Òš$ÍùnYÓÏ™#GŽÎÔ©S+ûT£QÞkÛ¯=dý ) 39tH Ô®-ïŠJ9œ8qƒÁÀwÞùŸ¼rEæÒ”׫R ÒY,²Pj4RÄÒºø<(‚§¢È»ïí-‹äæÍb,Ÿ©” $$„cÇŽñþûïß…óþ ˆÀÕUBÞ*ä°[a½1¤Èʯ¿pòdb4:_·M •"U?ø ü·³JÔE-:H„ZZ¥\X´hcÇŽ-ѡῆ¢È<:j”û¤§_¿x}vöõ+²[÷Û±£œcÖ>ßW¯²õ|vv§ù8yNÒÍ9„V/( åß¹ôz”†üú»–&Á¹Ngª?× 'WX$Ïœ©ìÛYåHIIañâÅLž+@QO S±ã5¶÷Q@iaŸ]€ï®ýîøøx¶nÝʼyóÊÌ%?rD"ï¾ûÚgÏJ˜úô颰^Ã`ÛÌðáù[–b âH ÷ĉòE©©Vn±ˆذaé½Hà?¿÷^I÷.‹ƒE¡´¸W¬JÖÅ1›eß—_–wfð`©oSšÂ-×cU:ÇŒÃxÛ¶%÷½tI®DÈ™8Q¦:uì§ ³Y椢ÑÚýúÉÚ°}»\§“I®©¨ öÈ#’u`U‘ø÷ߟîÝ»3èoôÚµa±H¸ÊêÕò‚<ü°ÿÞIÉàêÖ­üw÷¿&E«ü§IIIaÞ¼y <˜!Esrþ£2Ž!sfhhù kl¬¬ Ó¦•ÑOÛl†«W1åùìÇÚì9äÄéÓ0ó%Ú° ¢ Z»_Ì›ÑуZ°+n2£þÏÆ;qôh'ÎfAÓ~…­ì­þ+ñðÑ$xÂþüÓ‹nݼÄ.ìtŠ{ÿQV¬XA³fÍèÑ£GeŸÊíƒÉ$/Nië‘Õš/Öó”ÉE²*¬¾¾b\Õj ÇX,ò2Hø—5R sçÂw «Úÿþ «É$]bb$mhñâMôìÙ“† ÝY·N„Á¢ÎÒìl‰ÖøåèÛG!á|*~Ûÿ¤úðnx—ç\§ŽÅjÖ¼ƒxd4…Ñ}70Æ~³¢ˆàžš*žœ† K[½tI¢,G’±¡×KúÕ+ÅZ°†õ€úà ÷='²ÓÙ³ » -‹; ŽCaâqmu¥X¨¡#pHǺvºŒ Ü‹„ó&QRaý˜ŠÌÞÉÀ  ¶õá'«gX‡´Û±Îß‘×þŠÒúÚ1²¯ý–w)÷º9¢üÝQskrå ìÚe&>þºvíJP®HE‘±tüø5…59Yª>ý´LHE¸|YRmüý%?³<…U§“ÝìlQ¾¥t%Ôb㉋‹ÌoÛ¶‰L_Ú¾))…m„}}%µvøð’á°‹x­ç×¼¹(çΕ욕%ó°ußä|’BLEß;£±°m,È;Ÿ”$ïRóæ…s‡Å"Þ墩è-ZÈ<òý÷’A`uÔåå‰AÝÚFÓʰa¢D·j%^d­VÎëôéÂ`9çÝwaÍ-qqžÿù(R‹Å–-[ÈÌÌdÜ_éiT ´I“Ä=_^ߢ\½*Ö†ƒå¥4HÀß ÉWQ)†Á``öìÙÔ«Wûî»îößòòd=)ωœŸ/ò]½z2g¿öšÌåv¶£’’Pò œ9á‡ÉäÎÿ=fá™ÿ˧CÃTôZ‹ÀhO@x8é^äxÌàý÷øìcÄZ'q}ìþÂ0£k)gcªQï°3]»ÊǃK*ˆƒƒÌÙEeË H6L æoÛ&óøTöÝ®ZX,Î;ÇÁƒYPAÞ¹Û£Q¢xÜÜÊ-¿zU¢}ŽÓ²eòùÏ?K@f¦„¼/Êèÿþ'ŠHÑ0ìÖ­K×ÕUô¿À"{yãF™Øž|rr28xð ƒ "(HËùóö…NRR$Ôö÷ßEÀìÐA¡‡Çiê?1Œèšøê+yÎ'OJ{»ï¾ƒ÷ޓБÜ\ ¼> ¼¾ÖJ‰þHN–‰nëViM3ož}/ÇŒ ù¼}{éhàTÚl£³žÜïd=ИE9èÔ Ú5}ÑúNõ8‘Ó\\ Hä™Å8EéA¼¦™ˆrZ”,96ÖðÉžØ÷|Í‚) vš žS®·¸\ />\BZóGì]Äí½¨çàA˜:ÕÀþýû1bD™ ,‰>lÙ0—‚dÒ™2EB<ŠYIΟeµgOfsÙ¿Ÿ’"2~Ë–ªUV¤ðp‘ã==E1+Ϲd0HÚˆõ¼OŸkïZ)¿}õj¡÷_§“BM»w‹¨(Ö\Wë¥êõò-ZTrßâ}OÝÝåV½÷^aÍ5cãF{¥[§“º9µkK+e«‘QQDÙ-iêë+­hýµ°-Od¤Ü÷¢ï·U§êØQÃ… ^˜ÍU»"ûÍDQ8À÷ßÏË/¿ŒOÑ~¤F,íÚÉâo4Ê‚^¬ïx NŸ–sÄhüoç"å×_åå—_fòäÉÔ¯ÿÎëú+œ;'/Êôé¢|®_/ÂÛ¡Cò™··„f-_^¨¬‚¬s“'‹r1æšÍÚÍÙ¹t/ÂuصKŒúÍm¯°ÆÆJ’{ïww…-[¶Ð­[7©__<Ý¡Ï,EY¸ˆØKÌšµ«x·ËúÕ Qc-žíI· yx¢–÷߇ùóE®Ÿ9S éM›JXî÷ßÁìI°cµ„1-üf1­0è^p쟃¼b¡¬'Nˆ'gÊOwÜ!í.Neõ»ïdLöîx5Þž‡*ˆ’—†xë }Vc‹lOÒ‹ü» 0”B%Õ€(»E¹¸ZÊo)ˆ2Û‰3Þ‡(®VrO§5²ðc‘ãœFzÂ%Xuí:Ü<Åi„XGSº‡Õ˜ŽÚÿV>XHˆB»èÝû¬‰î&“¸S …V“ÁÈñ/Žqz]8û÷# këÖEbÊ ©QCBeÝÜÄ—ž^úoggË‚\»¶îäI·¥qþ|aWQn‹+† y°‡†ã:8ˆgtêT{cHú„Éd?¿¶l)Êù¶möúFrrɼÒfÍÄBÿå—ö×èéY2mÀÏO”áùóåÜ­4o.rLQt:1@J‡’ü|QØOŸ.=,­aC9þ”)b ½zUôŸÒ"»Û´1sÏ=±88”cE¸±X,ìÛ· 0gÎêÙziý޳—’u:jú©ð³#GD¢~òÉÂÛ¿¿T½ëÕ«üð_•$44”+V0cÆ <Êòøgg‹†t½æÏÌÕ«"ï˜ÿ´fú¯W7&F;Cºg0ó‘x¶ƒåÌYÙXP_ cư»Ï\b/›%ÇôØ1}5›ùO\&fáÙ×ÁAðô„±:ÜÛ+D?°’‘!×>x°ýºÓ¢…Èo.»§N‰ŒW´¦‚«+¼ø"´k§çÊ•¿™'ÍË/¿ÌÏ?ÿÌüùó¥…¢ÜÞdz³E :~¼ðÅHH€?ÿkÏ23aí×™ä¾ñ´á˜1£PðptÖ§Ÿ†‚9;Ë{òÆ¢œäæÊgþþ%­äþþâ5ð÷/]ȸÆáÃâÈ[°@ ûeu`¸rEä­/¿¬øö{·½Âzò¤¢îîÍŽ;èÛ·/­µM䇳íˆ<“ù?ŸàSŸâ¸ë·ÂP044NNò‘““x9FŒÏèý#á0®—±óÌ3"÷( ÄÇÂ’ì ƒî€aõ¦E&³o¾ÁÔÉIä=$|dóf '¿|Y„Y­Qò\‘°ßâÞP3âÉôFòAïÆ>ø;¨[äßÀZ •ØfHA£¢t2‚QE1{jM`,ö=]¨•Ú×¾cUR£ßbÇ쌄òžFÚÞ”R°†Nˆ½{­  ‡Úëkãðò>9;_!/Ï‚^?¼Ð»+‚ôܹ"]( ÚU+ ö<Ä™õqw/_ÆùñGYt==e¼·[¹|Y”5­VŒyË\‘‘…žPFdýM›J®Kùùb\ÔÛ£‡{Á{®UV+êTÖé¤FZb¢DAX¯óÒ¥’5Ï´ZIÃÈÈwÑ*€:TRÿÐj%?÷ÙgEÛ¹S¼­§N•î-Öé$çôÁe®Ø¼Y ]¥…»iµ0v¬§ví*=¤ÙŠFÊß1‚Þœ9s†… 2gΜŠëG¹aƒ½yX§ƒ `Ý:$@VåV­$lªå5‹šƒCù…øTTþŠ¢°víZXzá™+WÄ‹øØc2±(ŠL^GŠ|XEÙäÿ“4ª2w²XHOWHK 7(rÍ(ÖI6/O¬ó3f`yèa¬ŒbØ0Ô&‘9·pùKlû!Y.E§“P±÷ßÇkþKÜu÷µw®uk‚–½@ÿ9Á¼S0UjF&uWWw¢m; îî qÐR­†ƒ‡;r与ääÂÛtႬs-‹Ê]\Äèèâ"QÃ!!²ÿÈÚX¼¬‰N'»w‹n-kÔ)%ç|OOèÐÁˆ—W)aCÿ!, ~ø!^^^¼óÎ;´jÕJdƒAÒ3–/—Åù_6ÈÜ0Ö÷Ïd²·âœ9#/Ë›oz=ãã%¤êÝwÅ jhÂÃEa=u ÅÛ›;àõ…îüRc¢X8ž¾Ð2Þ¸±(^^RØKEï(ð‹/D(µj˜´õ³–j(ìløøc‘måÙ¶­ä£0E÷ ½è¥—äR+ê‘Ýö«kB‚x»:„³³3ÍŠôµ èì‡Ò³OÅÎâÞûœèZ/^¬ ^¿Ü\1Ü2¡ÃÿÁP¼$ÂéÆÒ·ñóÏ 8늒»p<¤Ÿ“JŸ_}Ÿ.ZìŒW¡w'wÖâ[6a8胄Ûn)~ÑH+«Õ0ØZdûyÄ{Y” *~{(=÷3+öY–œ'Ö0÷lăj=V.PÔ‹¤úñ×ö©/^£^Î^»Î²º¶oYÅ–›€ÆOƒWªÿL&«WcÒ$ONÿiÀxê¼lhР°JÐo¿¢pÜo(6z˜fÝ|øè£²­eYY¢L¶l)‹òðáe‡z\ºT¨pjµ²Æ %÷3e޵æñƒ_ª[WR‹’˜(VꢞƒƒDn  Õ‹«(òw{zЇø‹/äòA¬…¥åž;:Êü-ç&euêÜYò”Ž>åº,#¥³³ì?p xpË‹up0è dN¨[•b ^}õU¦OŸN‡*¦?_n®$'·fJ~·up!VífÍÔª¾*7•“'OræÌzè¡Â6éé…Þ˜´4),ñá‡2jµ¢q­Z%ÂÏ—_æPÄÄHÁ±c%CTŠq½xùêÈxë 3§ö¦siOŒHAÂc~þÞz Þ~›Ã;²¸|îo}Š˜Ï~áÙz83íkÙ×ÁA&Ǥ`Þ›l¿Ø@ šAA´Zø8£öfKNNž ZhÕ ƒ_}>þÚj¾×#.µ}xòI‰lüä´Aþ«×ãÚÛ”%únÊ)ºwæŒ\ÏŒ%_k ç}åQÎ?ùDnñ}÷•>ç;;KÄNÛ¶ò»[¶”]±¾Zµ¼¼þ»½XÍf3_}õ&“‰iÓ¦áa6ËMVñàÌš%òƒ …•ØØÒsƒn6Ö÷ÎbÏèï¿ËŸ5?èêU@=$Ê¥¢‚‚D Ñ1Þ}W”€ùó óO{ö”cÌœIFý6äæÂW_kùq{5bMµä{e¬;11¢„ÆÄ@¾Ö¥ÔÁ©(â`8~\d¨ùóåV–¦Xr¼™3ÅYpÏ=…©S›7Ûï&Žƒ>}ÄÈþÒKReíZˆÿçi ·µÂ%®«+dddðÝwß1qâDiw`6‹¤k±Ð¿¿x?zô@¬q/¼ð÷*6ž@ÈÚ ½"@'NCgC <Ю=³ºÁðÄ© êç'Bl‰þ‹¯‡E¸Ÿ5KB'm„"a±ƒ€Cžç‚A²UkeU#¢ÀO 8Œ„t@*ú§3R·¨2k@< V c0Ò–D!AB|‹ÒøúÚq.QzµdàODù.«(s¤ÅM9£8öÞX²½²oðAÞzX,~þùO‚ñX7ŸzÓÏ¿Úï4~¼h@Z-3ýèÐAæO'§’y›V"" Ó"@äø}ûJNlŠ"E–Š*VÞÞ’‹^Ì+Ÿ-Ç(*99IXÕêÕ2‰Zß+WÄXi’jÛ*‹ÈÈHvïÞÍSO=%••?ýTÜÓÖ©F$ÇÚ2ÄZ0q¢hOV#‰Ñ( ­Ápýu‹Eùôtù¯¢È_F†¼‰‰…Êil¬( &ˆ0²ï… ò^¹bSžs]}É{ü”×^ÍJóæ:5v,4nLf&¬ø^Ç–Ýnåz8Ïœ‘®¶m¥ØêîÝe_šÑ(2Q|¼¼¦S¦ÈþÅOyy"ƒ (úrŸ>ò8 ·Â"këVû(3''1ÎÇÄHj—Ù,‰‰RûÇêÐm×–.•GöùçuHNþgõ%nÛÌ}£Q&«×^WW Ë–­¢Y³ftêÔIžÈ·ßŠ9`þ|† )" kµ?¬ë,’¯Ù©–‹L´o¿x&RXçÜ.g íË¥·Ç  Áýè[ÊD @Â~!žL«‚ºÉµz° J,ˆÙ‘’í^žz#Ò¾¥œ“ßµ¿5€µUH$p…9¯5€·¥µphXì8€áÀfDy.mqðÞ–q¿#Ež<)ƒŸ½ãíß«îòåË,Zô+÷ {ÏßVq¨Õã4`Ÿþ[ÄÒ–—'77)âUÖ„™`_}: @”ÉÄDû>¤f³ü»hs77™Û—.•Î Ö>>…m=âãEÂlÙòš…½t:ô5*ülÈù+ŠV+“ܵÄ}“YÂX}jè8íÚô 5êÖ-êãã!2’_-]è¬GÛ£õ¶õâžõðÚ&X<¼½=¤)6bP l)Êîî¸6u禢WìÙ#¹——.œ=+!ÆÅ_ë ¤•ñ«¯ŠþРAa›Ó⸻˾HùZµD·) ­8lmëÓøñ×.žž¶"Á×ÅÁAÒÚUJ'++‹E‹q÷Ýw(Æøxqe]øµZ{Ëõôébi?p 0òåÂq};;‹¡dÔ(Yœ/\£KZš< ??b,+wçÎ"Dhµb´9wNŽyß}Ð¥ ¦j50O{§†u ÏÉÁA¢lFŽ´’ÑÓf8Ò¸q:¿•¨¹aƒ¨ 'NHä׋/–.“üö›„£kµ¢ ¾óŽD ÷éc¿Ÿ¢HzR\œÜ³YŒ4+VÈíìÛWæÝ”‰ü½Œf\e`þ@ÚªÔ(e[k  ¢¬þ„x?­œF<…ÖYQæJCAzˆŽ¹ö_ÁE¾4EòWÅð[àÿ®í“ˆ}¡"ÿkÿþQ.C€âÞÜzÀ«ÀÄ«Y–!äAà“kÇñFñ"ë!H/Ö7€—®_ñˆ\‡kßÿR-y^¿å}íÚÊ{D5ùÏ£dfrnútò2ïų^º§_¤ûvWÉã-…ôt±N?ü°ÌÉ­[‹ÐP´ Èèèhïùwu9iölñBZ•ÖüüÂ’ýE©[WBH¬U¯›5aãÒ¥Ò1WW9¯~  F#!ñåѹ³XW¯.3UÃFµjrîåÔ°ã¯v4QùwY»v-ýúõ«ØfòŠ"Öùâ¥üU((öLË–FCר!ï‘Å"VöuëD)=vL¼cݺ‰1ÖÙYæœE‹DɨUK„µÖ­EÞ´XD®¬V­0O>;[æ—ž=!5UGJÊ ¬Ó·Š¢pôèQöîÝË[³g㔓#cÒÝ]Ü{Í›ßðÍΖÂ:"ï¸C”4½³³æ×HOy~ÌÓnh4}qÜë#¡ÇhÞÜ ‡±cº/ň "¤ŽQXm}äH9¾ƒƒÈžž%œEpŽ—ÈáS§$ªçÁK¿†Fd]ˆgÛܹe_¯F#kU` ø¥ybU*³ÙÌ·ß~‹§³3Ãûõ“´Žà`ÉCú+ÕÞ«U“<%+‹æ—-V5ëB"y>:ÍÐcöªFÞcÏâæá€ÆÃ½pßÇ·«G`±ÀâOœðð¨GçÎ"'•%güö›^¬ù˧OËO6n,i×^^2.CCÅXóÒKò3?ÿ,Qg©©2z{Ëëž.ýúÉñõzyoãã%D÷$zÌÍMæà5kDι„víä·wìC½D°U«&Ž„¢SH“&2?·i#çóÇr±Ykd¼ôRa Tñª»ÅÑëÅÚØ©ÓõVP ¸ÞêDFF²ÿ~–,YR˜ÓW(Š˜£{ö,lü{ –&ËõÍŠ"ïy:ò^:: ñÉÉbyß·OZRZÓÚ´!æÌqH,\(–û3Äy'Ñp..²¤Þq‡DÍ…†Ê<³nf¹¹RÀrØ0ùÝüüÂcfdÈï:$ÑH'NÈÜÕ«—èe7ꉎþoÔ!°’‘‘Á§Ÿ~ʃmÚàÿÑG"•>÷œL°íÚÝðñ, *KJbjª(¯Í›‹rXTpÝ´Iì6žž"¤Ž)Âë¬YRdÎZ{`ÿ~¡Šz^ôz1DäçËsüå‰HNM½Öï» êÔ‘µäóÏ¥vTy½W}}Eàþä“¿fP¬UK«q½U+ÉÇtw— âýè¯^¹è¹çd.œ0AæÊÝ»mÅ~yì19½¯¿EÔÃC~süx™7lðÛÓ§Egˆ9Èš‰¢ÑˆS E ‰t[¸Pä±ü|yÇï¿¿¤Ìçî.ï^¿~²N”g¬wt”{ñ¿ÿÉñBBä;eÉL:¼ßAA7ct”ò{ÿÎÏü»Xs²ÿïÿàÜÁÔ\½šÑ  MH8¤¿Ûú`#R}÷7¤JmѦtठH˜êj`¢Ä%cŸê…(¶ï#žÆ¢–ÇÈÒêvíï$L÷~ä‰FÂw­ø\;¯—è.¤ZoQªOs‘‚KCK¹> ð<0ù:÷¡Ãµc,GŸ,eŸ.HØñO”=Êê#Šoy¨)cåRpô(Ëú‰ Ï¾gB~ [ø®¯¯¤V<þxÉï$$Ø{SëÕ“Ié÷ßí;rXÓGŠ+¡ŽŽ21ˆÔ³§ÌñçÏ—=±õî-B«““LÂe…îZ±F©ó×#ôK CT¹½ å•W^áñǧnEW¢²XÄT\ÜBS‰¤§Ëûª×‹1F«•`Z­(»vÉ{Û°¡(®AAq-Šf«V"ä˜Í’Oþá‡"H……Éû­Ó‰Pââ")Zîî…^P“Iö •HŠ dE‘°Ìäd~zô¹À×·ð]µF«öé#ž8­V~úÝÉ©0CQD©mÔHÂÇÅ`Õ¥‹ì?qb›7'Vö£øWP…ÔÔT.\H«† é{ù²¸-»t)UÒÌË!·AÑi‹ö-Jr²<ÇéÓ ÅŸÖ­åßuëŠ!ÄÈàì,tÑãôî-ÏoófQzƒ‚$ öŽ;Jþ–V+§Û¦üæÖ­2®®ç0óö–0Û¿2ß[ ›*·.¡¡¡|óÎ;¼ãîN¡CECû‡…óBCÅ›¾aƒü{Ü8qÀúøØ· ‘N¯½&ÿ¿gŒçN$2γÆÄˆ!eÎQP›7cÚŸJ´ÉèÑ2ûøH$³——}ª”ƒƒ\V¢—¼û®ÈOééâI-zN¾¾¢ÐffÊoíÞ-Ç~ì±’×éâ"ßïß_æÏƒÅø7rdÙ ©g9©s¥¡Õ–Œ˜«lªœÂj6›¹pá.\ nݺ´oß½þÆrwìÛÛ~|çF¶nÛ[o]ßUSéH¨îÓ@¦{â©4+€G‹ìß Ó}Qº;æDù]‚x­ŠÁn$Vsí¯¢°ž¹vŒ6âÚ>}‘§ù6â]-þÞk0æ™À ½³ÅqåúMg ’{Z£œcÕC벟†’ÞåÿF£‘#GŽ””D³fÍhܸ15Fµ{M&NF§:Ýùᱞƒ0ÖPŽ a¶)”®«(ÿ©ú#Ñúäµ×~¯[9ûh([Yý’™™É[o½Å… ¨Q£Ë–-cĈLš4é¯Äl†cÇÈõöæ‡ä±ÇÇ××™ûï/œ,]\d;|X¬pE¿«Wå³¢ôè!‚id¤$ÝççKNCddÙžK''b:w–ðÀÒZØ”ÆZúTn-¢¢¢xíµ×ÈÉÉÁÍÍ>úˆéÓ§Ó÷T¥ cöìÙŒ=š{î¹ÝͰdètb¯ üÕ‚ɵ³†ìZ«):;‹puè¼;’W´zµ(¦=zˆÒµ«äõy{‹Ò¦(âõÌÌ”ï"¡aÖ[Q4×¼U+Q`çÍ“”Çuë$ß©´Ð­ìÞvÓÐhJ†ÙUe>üðC~ÿýwêÖ­KRRíÛ·gêÔ©xüÍÄ÷ôeËÈZ¶Œ;3jÏ<ƒãuBF.^á÷7d|ůа½`­^SFôY³Jz_üýň¸i“¤l|ñ…„Ú–…““wÐ Q$n¤ˆÊ­EFFo½õaaa6YeäÈ‘<^ZØÖ_!3eÁN¬YÃ¯ŽŽ<üÎ; 0 \«tv¶OMI‘ñùÁýa-°¨Ó‰2)IZ§Ìœ)s¢Õ–éç'Fš÷Þ%±eK1äyz–,„5r¤ÈL‰‰²ÏæÍ;vlÉSts“¹Ûl–ã$$Èg¥†Æõ: ¨”M•RX###Y·n“&MbôèÑœ={–§žzŠÞ½{Óï/†i9‘N‘u|9¿Åı`è"ôÛܤ­‹#Òš¥Ry¶¨2eAŠDö½Éé´*·9€5 Þñ¦.~@³¦ØW»Õ!^ȆÀ~¤ SiÒ‚¦†Tؽ‡’E\‘¾«Mv0¥)‚ «õ–EE*‘ªØªú8p€°páBZ·nÍO?ýÄ'Ÿ|ˆ#¨õWs7NžÄòÁljÛOOO:uêÄ·ß–\>>ò>œ8! jûö…íîŠ[*­^Ž–-%4ïêUQVﻯ|ù]£‘cª-T@Úͬ[·Žôôt>úè#<<<øàƒøúë¯i×®´æ¸A¬ÊêСC9räÍQVÁö˜L’$ bñqž.ޥ˗%´òСÂhÉÉ¢pK±Šž=EQtw‹½^/Vþ„1$ "¡“nnò[ýú‰€æå%y…e9ÿJ!cFÂמzJ”áïUhU©"##Y¿~=O=õ£FâÔ©SL™2…¾}ûÒû¯¸FŠqüøq¶-YÂð9shu­¨Qb¢xnRRĨѼy¡Òh„?–È1T6h W¯ŠþØ1)b#ž²^=77™çÍf .ÒX:ýr»³ÿ~<ÈâÅ‹iÙ²%«V­â‹/¾àÎ;ïüë²JòsrØΖ–-y`òdú·š—ÂçŸË\»x±ŒÏ =›_-ùóMšHŽè!"»7œdLge‰‘ððañ˜–ao•Ê.úUQRÕŠçÿUjÊ9zô(uêÔaРAèõzš7oNpp0»víúK kA¬[œÈÃ'~àh¸SšO¥Ž¹ŽänZ½:Qˆ×3Ém‚„®.C¼œÖž‡‹€Mˆgô,ºZ4L¦!R0(©èÛÒ=· ®ý•‡©. ¢”–GmTnaöíÛGpp0-[¶D¯×Ó¿6mÚľ}û¸÷Þ{¯€œòÞ|“•µj±ýôiÞ}÷]‰•²åE'ëà`ùÛ¹SB]-!úìYùoY8; ?**7‚ÅbáÏ?ÿdÔ¨QÔ¾æ5vìX¦OŸNXX]n@kÊÏÏçðáüûî»L:õ/ 8¥a2‰àŸ‘!‚ÎÅ‹p%ÞBƒú Q1´ljâØIÜ Rq­íÍù0š5“\ëË—Eè¹óNñ^ (ž¬ºu¥np°(µ—/‹Päà VýÁçZWé„È{k ý­Húö½yí–þË>| €^¯§eË–tïÞ]»výu…ÕbÁÁÏ;wòÕÖ­,X¿ÿƬ\)ѺuEHïØQZE$&J¨îáÃb,qw/½UK­ZòW<”ûz88Ø·0SùoóçŸÒ«W/š7oŽ^¯gàÀüüóÏ8p€Qµõ—ÙŒ%4”ó,X¶ ÿÆyëé8yÒ“ùóenvvãx^žŒÛeü{xH”È[oÉ¡D1,®fdˆA¾E‹²O£GëwR©úT)…5""777|®eçëõzÙ½{w¹ßS…‚‚L&#cRÓqðèÏàÇ;â1Æs³xM×vöGBu‘âFqH¡ûÖ/Öý&!¡·é×>·†R™Šýxm¤P‘Rʶ$--óçÏÓ¥K—›çEø— C§ÓI_­J@QEÁX¼cr¸/ÁÁÁ¶\§jÕªáëëKXXX¹ß³X,äççc4)ÌÊïÏ¡Ã:úôÆéÓ5ùâ 3Š­PJq¬ùéé2éçç‹UÐôÇëß!""‚¼¼W®\)÷»&“‰‚‚HJ!aõB÷ï':ñ*/½õmÚ´ÇðÃOW®Cycÿ¡(11\ú`¹IÙdzà4|'âkPT~;è‰IÑѳi"ÉšÔ¨º¿ã°{'­|2©ùêÓøvlIͨƒ(‹>Æ‚†?¾Ë½ckÚ ÄH¨»§gÙ•FM&ûJ©Vë‹KJyÇ*’ß~û!ÅûvþË`)Úɾ pñâE<<?´K1¶8:Š!ÄÓSþ*k|íÝ»—–-[Rí_Ì÷¾YTö·ÎãUmŒ‡……ѯ_?[Ÿk___ªU«Fxxx¹×b41˜®¦’ùþ‡„î<À—5Ò¬ßx†íÉœ9Î&žyFRW­ËgjªD˜X«S׬)õƼ½Ëçnnâe­ÈwÁd2qøðaš7onÓGnU®\¹Bbb"mÛ¶­´s°X,Æ,§T)­(??­VkKêÖjµ¸¸¸––Væw4 ¹¹¹|þùç´nÝš=вeK®VÏ‚£áG­‘ éHK—²8~íï&’““Cll, Òê&>>jþ•ø¢›€Åb!..Ž+W®0a„ʾ6 :Îö|qtt$ýZÓöÒÐëõ\¹r…÷ߟڵ¸¨øÐ¾S-4špbcOàé©ÃßßÀ™3 gÎTö–OBBDDDTö©ücÎ;GBB‚mAÿ·1™L6À_M™ø7ÈÏÏ·+>ãââ‚Éd"''§Ì︺ºrèÐ!¢££Ñj³q©'Z燩S_Ç™µ|òÉE‚ü«±ûÊlôfšþ’BÈ‚ó4mšJRR7@¡†ÞH£ˆ“( xÔ, k-Š¢¡fí|ê9^êNÅEH¿Hº7°L¢Â3¾çŸ]DDÕªU»å€ 59ý&qüøñ¿z³ø;² H˜eff&i'½Ø¹³™Þƒi_=…ìS‰88$R»¶vír‰‹“–AU•óçσÛmPš½²Ç¸Á` $$„Î;Wö­(q^:ÎVÜÎÑѽ^_®¬b6›Y»v-aaa„¯ÉcWè`Ì>£é”ÎÅ‹ZÖ¯ßO` ™Fr¹|Yáòå²ÿ:¯ÒMÅb±NTTÔ-?ÆÓÒÒÈÈÈ **ªÒÎ!55• .üuÏ|T)…µ,Ê«J¦Õj>|8Ý»wÇÅÅ…>}®S[u±zoueä…×h4_Éó°.BuþIuè‰òž¹››'N$//ggg† ¹uÇÇí4Æ»téòÏ+&þE¡cÇŽ899UyO‡F£)÷™W«VgžyEQppp§ï](Šœœ 0›µ89ÕbìÃŽ88˜qv®…Å¢ÁÉÉ»²/­]»v­ô¹¯¢¨ì1кuë¿\t±²)ï^¹¹¹1}útt:Ê0gÆMwÄÉÙ„^ï]Ù§}èc¼â°X,tîÜ¿ªRýì:”77oÞœ§žz '''úörâa³#®®èt5nàªÝ»w¿-ÆxU¹ŒF#ýúõûDzx•RXÝÝÝ1›ÍFôz=f³™ôôt[.Tih4|}}ñµvÖUQ©Âxzz’ŸŸÅbA«Õ’——G^^ ËÉÚ×h4ßsREå&áááA^^žíß8::–[pI«Õ–“>P9!×**eáîîNbb¢¬’‘‘Q®¬âàà@ãÆ+ûÔUTþ¥É*ƒ&Mš”ù777‚J+E®¢RT)7GûöíIII!îZ,L~~>'Ož¼-òÝTT:wîÌùóçÉÍÍ$¿ 66––-[Vö©©¨üc´Z-;v䨱c¶ÏΜ9ƒ££#þjE•Û„:””D||< Ñ<§NRe•Û†Î;sîÜ9›ñ1..ŽøøxUVQ©4ª”ÂÚ±cGL&ëׯ'99™;wÉÀ+ûÔTT*„Þ½{sñâEvïÞMRRëÖ­Ãd2ÑC-a§rààà@ÿþýÙ³g'Nœ **ŠÕ«WÓ¸qãr-ó**·;w&??Ÿ 6œœÌöíÛ‰ŠŠ’¾’**·½{÷&,,Œ½{÷Úd‹ÅBwµ‘¨J%¡QªJyÉk>|˜Ï>ûŒÔÔTÜÜÜ;v,Æ ³+â¡¢r«b2™øå—_Xµjƒš5k2qâDºuëVÙ§¦¢R!äåå±|ùrvíÚ…¢(0uêTêÕ«WÙ§¦¢Ra‰Û‹ÅBDDG%99mÛÍf3/^ääÉ“äååáããƒV[h?0=z”ˆˆt:îîîh4Ûö´´4Ž=Ê•+WpuuÅÅÅå¦^Ozz:GåÒ¥KÔ¬YÓ®¢ÉdâÌ™3œ;wEQðôô´»–œœŽ=Jtt4NNN¸¹¹Ù®%??Ÿ#GŽpéÒ%ôz½Ý6•ªM~~>¡¡¡„„„••E5ìž»Édâøñã\¸pN‡‡‡‡Ý³ÍÈÈàèÑ£ÄÅÅáââ‚‹‹‹m»¢(ÄÇÇsìØ1RSSñññ¹éÕ7ãââ8zô(éééøúúâàà`Ûf08räQQQ8::–x“’’8zô(‰‰‰xxxàäädÛöo¿«*GNNÇ'44³ÙŒ···ÝÏÎÎæÈ‘#ÄÄÄàì쌫««Ý¾zõ*ÇŽ#99//¯k@DDD™k@E£( ááá?~‹ÅRâZRRR8zô(W¯^ÅÍÍÍnœZ,bbb8vìéééT¯^Ýîý(ºX,¼¼¼n굨T))):tˆèèhôz½Ý<­(ŠmnKJJÂÓÓÓnn³X,\ºt‰ãÇ“““ƒ¯¯o‰5 $$„ .ààà€»»ûMÖ5éäÉ“899áééiÛ¦( qqq;vŒ´´4|||Ðét¶íf³™ÐÐPNŸ>Ñh,ñ~Xeë Ê*·—/_æÈ‘#$&&âîî^bn‹ŽŽæøñãddd”XûM&§OŸæüùó¥Ê·e­7ƒ¬¬,Nž>>v Íf3áááœ:u ƒÁPª^qäÈ"""Ðëõ%ä˜ÔÔTŽ9RêPÐýóC¨Çh4òÍ7ß°~ýzÜÝÝm‚Î /¼@PP†¯¿þš_~ùgggòóóúˆÃ‡ãââ‚Ñhäá‡æÎ;ïd™?>IIIèt:ôz=¯½öüùçŸ,Y²­V‹Éd¢eË–<÷ÜsøúúVøµ˜Íf¶nÝÊ÷ßF£!//æÍ›3kÖ,ÜÜÜHHH`áÂ…„……Ù„µÿýïtíÚ€ÐÐP^yåÌf35kÖdæÌ™Ô©Sç_WU*Žèèh^{í5ÒÒÒprr"//^½zñ¿ÿý­VKll,ï¾û.qqq¶¹möìÙ´hÑ€cÇŽñÎ;ï Ñh°X,4jÔˆiÓ¦ÙªÉ~óÍ7lÞ¼Ù¶ 4ˆ‰'Þ”ŠÊ¹¹¹üðÃlݺGGGrrr¸ë®»xôÑGqpp <<œ×_ÜÜ\´Z-^^^Ì›7¶nÝÊòåËÑëõеkWž|òI¼¼¼0 |úé§ìٳǶÜsÏ=Œ?^UZ«0Š¢pèÐ!-Z„ÙlF§Óa0xôÑG>|8Z­–sçÎñꫯÚö¯[·.3fÌ V­Züøãüøã899QPP@Ÿ>}xì±Çpss#++‹>úˆC‡ÙÖ€|#FÜ”ëIOOgÁ‚„……¡ÑhÈÍÍeúôéôêÕ ­VË®]»øøãÑétFÚ¶mË3Ïù„}ûöáììŒÑh´É· Fî÷Þ{˜˜Û0sæLZµjuS®çÒ¥KÌŸ?ŸÌÌL, ÎÎμôÒK¶5gùòålݺն¦ :”‡z'''RRRXºt)'OžÄÙÙ‹ÅÂOø òÖ[o)F£Q‰ŠŠRºwﮬ\¹R1 ʶmÛ”àà`åøñ㊢(ʪU«”Þ½{+¡¡¡JNNŽòÎ;ï(£FRRSS•œœeæÌ™Ê¤I“”øøxåÊ•+Ê£>ªÌ›7OÉËË«ðkÉËËS}ôQåõ×_W222”„„eܸqʻᆱ(Š¢üùçŸJÏž=•]»v)ƒAY±b…Ò³gOåêÕ«ŠÉdR.\¨Œ5J‰ŠŠRRSS•^xAyòÉ'•ÌÌLåË/¿T ¤\¼xQÉÌÌT^}õUåþûïWÒÓÓ+ûª\‡;v(C† QvíÚ¥˜L&åäɓʀ”7*Š¢(›7oVzõê¥?~\1 ÊâÅ‹•¡C‡*ÉÉÉŠÁ`P^{í5åÁTbcc•ÄÄDå©§žR^|ñE%''GIJJRî»ï>å7ÞPÒÓÓ•ððpeðàÁÊ7ß|£X,– ¿–øøxeðàÁʪU«ƒÁ 9rDÿüsÅ`0(‡Rzôè¡ìÞ½[QEÙ²e‹Ò«W/åÈ‘#ŠÁ`P–.]ª 4HINN®ðk1™LÊòåË•ñãÇ+áááJvv¶òñÇ+ãÆS®^½ª$&&*cÇŽUÞ~ûm%33S Sú÷ï¯üðÊ¢(Ê©S§”=z(›7oV ƒ²nÝ:%88X WEQ>ÿüseÈ!JDD„’™™©Ì›7OyðÁUY¥Š£Ü}÷ÝʲeË”¬¬,%!!A™:uª2mÚ4%;;[‰Wî¸ãeéÒ¥Jnn®rúôi¥{÷îÊ–-[E‘y³gϞʞ={ƒÁ ,_¾\éÙ³§’˜˜¨Fåý÷ßWî½÷^%**JIIIQ¦M›¦<ýôÓJVVV…_‹Á`P^~ùeåùçŸW”””åÙgŸU¦OŸ®(J÷îݕիW+ƒAùí·ß”àà`åĉŠ¢(Ê?ü ôîÝ[ S²³³•ùóç+÷Þ{¯’––¦äää(/½ô’òä“O*W®\Qâãã•GyDyõÕW«”¬¢š?o©©©øùù1jÔ(œ©[·.Mš4!22“ÉÄþýûiذ! ÀÉɉ®]»Ò²eKöìÙÀÞ½{8p Mš4ÁÕÕ•Q£Fa±X8yò$iiiœ8q‚qãÆQ»vmjÕªÅý÷ßϱcÇHLL¬ðk9zô(iiiŒ?OOOüüüì,Hûöí£C‡tîÜ''' DíÚµÙ¿?F£‘ýû÷3bÄðññaüøñÄÄÄÉž={:t(5ÂÃÃѣG“••Źsç*ûª\‡˜˜‚ƒƒéÕ«4nܘ:uꈇ´W¯^´jÕ '''îºë.\\\8vìÙÙÙ=z”Ñ£GS·n]jÔ¨Á<À©S§ˆ‹‹#<<œŒŒ ÆŽ‹——7fðàÁìÚµËæÅ¬H¶mÛF:u ~ýú 4''':wîL›6mlk@E³aÃzõêEÛ¶mqrrbèСLž<Ùfy?}ú4÷ÝwµjÕ¢N:Œ7ŽÃ‡“œœÌ™3gÐjµŒ5 777š5kFŸ>}عs' k@ûöíéÒ¥ NNN 8:uê°ÿþÊ~„*å ( ™™™ÜÿýøúúâîîNûöíÉÍÍ%11‘¸¸8ÂÂÂxà¨^½:õë×gäÈ‘ìÛ·ììlŽ;FµjÕ¸óÎ;qrr¢mÛ¶tîÜ™?þø5 88˜6mÚØÖwwwŽ9Rá×’––ÆÖ­[7n7ÆÍÍx€Q£F¡Óé¸pá¹¹¹Œ=‚‚‚8p ;vì`ÿþý´hÑ‚ž={âääDïÞ½ äÏ?ÿ`Ïž= 6ŒÀÀ@›¬’žžNhhhe?F•rÈÎÎF¯×3~üxÜÝÝñóó£uëÖÄÄÄ››kó6Þ}÷ݸ¸¸Ð¢E zõêÅ®]»™Û:uêDÇŽqrrbÈ!Ô¬Y“PPPÀ¸ûî»  ZµjÜwß}\ºt‰K—.Uøµ\¸pÓ§OóðÃãççGµjÕxöÙgéÑ£†ýû÷Ó¨Q#ú÷ï““ݺu£yóæìÝ»1aaaäääФIŒF£mN·Ò¤I233IHH !!ŒŒ [ˆ;ȳ¿xñ"„††âëëKµjÕY5jtÓŒu!!!´nÝšV­ZÅ™3g2d5"33“¸¸¸ã4..ŽÌÌL._¾ŒV«¥N:¶í­Zµ²[¯üýým!wÕªU£N:ªá±Š£ÓéX´h‘Íø\PPÀÙ³gñðð víÚ¤¤¤””Tb\\ºt‰¼¼<ÂÃÃñðð zõêèõzš4ib7.6lh«=P³fM||| «ðkÉÎÎ&<<œ   8ÀªU«ˆ‰‰aܸqøúú‹Éd² olÕª•-/ñüùóÔ®]@òëׯow-Å×kî£JÕ%00?ü7772339wî 6ÄÍÍÍV;Åâ®ÑhhÑ¢…Ýs¯_¿¾-MÃ×××&ßšL&ÂÃÃK¬ÙÙÙ\½zµÂ¯%&&†¬¬,j֬ɶmÛX³f ...6£Lhh(~~~x{{àêêJÆ ËÃõêÕC¯×séÒ%²²²ˆ-u ÈÈȨìÇhCÍa½ X Ȥ¤¤ðî»ï²cÇ;v,äää Óél¼N§ÃÍÍääd@’¸œœl‚’5‰;==³ÙL~~¾]ž“——ÙÙÙ † ¿–œœ"""˜:u*¾¾¾äææòé§Ÿ2gÎzöìINNŽŽŽ¶\%'''\\\HNNFQòòòìŠ4xxxPPP@vv¶í:­¸¹¹a±XÈÌ̬ìG¨r¬Å,bbb˜6máááôíÛ—=zØÆ…u »¸¸ ÓéHMMÅb±`0ìž½——¹¹¹äå呟ŸÙl¶+PãååEJJÊM¹–ŒŒ Nž<ÉÙ³g©Y³&ñññhµZ.\ˆ¿¿?¹¹¹vçjÍKÏÊÊÂh4RPPPâ}ÌÌÌ´]Ë¿õ®ªT,Ö|éÝ»w³`Ábccyà¨_¿>iii%æ6OOOòóóÉÉÉ$ªøOKKÃb±››k·888Ø­MFFß~û-ÎÎÎT¯^¯¾úŠÖ­[3wî\L&S©ã4++‹üü|òòò슞yzzÚÞÇâk€£££m P©ºh4jÖ¬‰ÉdâÛo¿eùòådffòÖ[oáëë[æÜ–‘‘Éd"//­VkÖ¼·âãº8;;£×ëIMM­ðk1™Läææòúë¯ÛdO>ù„ &ðÐCa0°X,vkЧ§§ÌU´ØŽÕHoÛ^𬒕•UÙQ¥©Y³&™™™|ú駬Y³www>þøc\\\0 h4ÛÖh4%æ6kn*ˆ|ëìì\®|›ŸŸOvvv…_K^^)))L:Õ&ƒ|úé§üïÿãŽ;î°½oEõ ww÷z…«^‘‘‘Q®^‘ŸŸ_Ùцêa½‰¸»»óÀðú믣Õjùæ›o0eî_U+ÎiµZÆŒâE‹X¼x1Í›7gùòåûx¦Ê^«ÊáëëË /¼ÀK/½Äùóçùå—_*û”þ:ŽiÓ¦±hÑ"æÏŸV«eݺu•}Z*U€-Z0{öl&L˜ÀöíÛ9vìX¹ûÿ“¹íf΋NNN|ðÁ,Z´ˆ¹sçröìYöíÛwÓ~OåÖ@«ÕÒ»wo^{í5 À?üpSBÿ š6mjãÓ¦McåÊ•ÿèZT9åöÀÅÅ…#Fðæ›oÀòåËošçðfË·ƒ báÂ…,Z´ˆòÅ_”«TÞNcXUX+åZ+ƒË—/ãääDëÖ­6lO=õëÖ­Ã`0àææ†ÉdÂd2bÌÉÉ¡víÚ¶ª«Š¢Rá F888àäädç¡ÉÈÈÀÛÛÛ’U‘èõz4hÀÈ‘#qttÄËË‹»îº‹‹/’ŸŸ››¶PM«E¾N:h4\\\ì^¦¬¬,œñòò²]§•œœlar*U³ÙLTTIII¸ººÒ¹sgÆŒÃwÜaSò¬ãÂ:†óòò0™LÔ¬Y­Vk«bg%##ÜÝÝqrrÂÁÁ‚‚»íµjÕº)“¯““={ö¤sçÎ888ФIz÷îÍ©S§0¸ººÚ«5/ÆÚjÇÑѱÄûèëë‹««ë¿ú®ªT\¼x‘ÌÌLjÔ¨A×®]yæ™g`Ë–-¥Îm™™™¸¸¸àééi³tã~~~888àêêj·˜Íf»5 ¢qvvæ¾ûî£N:èt:‚ƒƒ©_¿>¡¡¡hµÚRÇ©-Z°3¶fffÚ­WE×€‚‚Û RuÉËËãÂ… @¯^½˜={6111œ8q¢Ì¹­zõêèõz\\\°X,¶qaõ8Ö5À`0`4©Y³f…_‹ÕÓ;qâD|}}qvvføðáäçç³³3Z­ÖnM)>†F£­F‚Ñh$77·„LfÅ%§Ê*U›””"""ppp Y³f 4ˆ—_~™ß~û„„œQÅ6†­yÝÅÇEQùÖ`0”+ßZ×€ŠF¯×ãííÍ<€››ÜyçÄÄÄ““Sª^‘]æÎÍÍE£ÑØZ”•%«T¥Ö6ªÂzضm|ð]˜¢ý¾ÚµkÇ•+Wla¹¹¹\¸pÁ_Þ¾}{Ξ=k›è/_¾LNNõë×ÇËË‹ÀÀ@Μ9c;^HH5kÖ¼)/‰¿¿?Z­ÖæØÂ´Z-íÚµ#22Ò¦T'%%kË×mݺµÝ¹ž;wgggüüühß¾½Ý¶‹/b6›m­Tª&¬X±‚µk×Ú&rFc×»¬}ûö\¸pÁ¶ÄÅÅ‘ššJ`` ®®®4iÒÄîÙŸ8q–Ó€‹‹ /^´m ¡qãÆ7Eamܸ1999¶s5›ÍdffÚBŠÓððp4 uêÔ¡zõêøûû—xýýý©U«Ö¿ú®ªT¹¹¹¼÷Þ{8pÀ6k4»°×-ZØ=Û³gÏâîîNõêÕ©[·.>>>\¸pÁ¶=$$Ä–Ó×®];máZ¹¹¹„††ÚåU$7¶Ë›6¶p74hPbœZsú‚‚‚Jäë…„„ØÎµ]»v¶ú ÉÉÉÄÄÄÜ´kQ©RRR˜5kQQQ¶ÏlslÍš5©]»6gÏžµm ±åôµjÕŠŒŒ [¾žÑhäÌ™3vrLXX˜MIŒ'%%…FUøµ¸¸¸P·n]»1žŸŸO~~>:ÎöÞEFFÚ¶?~Ün ÇÄÄØ¼néééDFFÚ]Kñ5@QÕ(SÅ9v쯾úª¢VTNiÖ¬ÄÆÆ¢°ž8qÂn\DDDØÒ"¬ÅÈ‚‚‚Ðëõ´jÕªÄàââbk]V‘Ô¨Q»”¹ÜÜ\, ´k׎øøx[È}NNŽ]Žmñ1lÍE¯_¿>ÞÞÞ4lذÄP«V­*%«¨ k£ÑhhР!!!lذèèhBCCùꫯ4hÎÎÎôìÙ“ääd~ÿýwÒÓÓÙ»w/ 2€pàÀΜ9CRRëׯ·y²|||èÞ½;ëׯçòåËDDDðã?Ò³gÏ›2yvîÜ£ÑÈ—_~Itt4gΜá믿fðàÁèõzúöíË… 8pàiiiüú믤¥¥Ñ¿ôz=ýû÷ç÷ß',,ŒØØX~üñGš4iBÓ¦M4h{öìáܹs\½z•µk×R£F Ú¶m[ÙQ¥\\\¨_¿>6là?þ ..Ž#Gްyóf†@ÿþý9~ü8!!!¤¦¦²qãFE¡GxxxЫW/6oÞLdd$QQQ¬\¹’®]»@Ó¦M©S§kÖ¬!!!S§N±{÷nî¼óN»Å¦¢8p GeóæÍÄÅűmÛ6vîÜɰaÃppp`РAìÚµËVxÍš5Ô©S‡Ö­[S§N:vìȪU«ˆåÂ… lÞ¼™þýûÓ¨Q£õ]U©8¼½½qwwç›o¾±U¯Þ´igÏžeذa8;;Ó·o_~ýõWÂÃÃ‰ŽŽfõêÕ´jÕŠ   6lHPP«W¯æÊ•+œ={–mÛ¶1tèPœ &55•ß~ûôôtþüóOÂÂÂlk@E3tèPV­ZÅÑ£G‰‰‰áÛo¿%%%…àà`üüüèÚµ+k×®%::šððpÖ®]KïÞ½ñóó£M›6¸¸¸°aÃRRR8~ü8´õTîÛ·/áááìß¿Ÿ´´4~ûí7RRRlýýTª&5kÖ$;;›¯¿þšÈÈH._¾Ì—_~‰‡‡mÛ¶ÅßߟvíÚ±jÕ*âââ8þ<[¶laàÀxzzÒ¹sgòóóùùçŸIOOçàÁƒœ9sÆV±_¿~œ8q‚cÇŽ‘ššÊ¦M›0ôìٳ¯ÅÇLJàà`>þøcΞ=KDD‹/¦Q£F4nܘæÍ›S½zuÖ­[Gbb"'OždïÞ½¶ž°½{÷&::šÝ»w“––ÆŽ;ˆgàÀ€„aþñÇœ?ž«W¯²fÍjÕªE›6m*û1ª”C½zõˆŒŒdÕªU\¾|™ððp>ýôSºv튟ŸíÚµC§Ó±qãFRSS9vìGµÉ1ýúõ#44”ƒÚ*Q§§§Ó¿éׯ¿ýöáááÄÄİzõjš7o~SŒuM›6¥víÚ,]º”ˆˆΟ?ϲeËèÝ»7nnnôêÕ‹ÄÄD¶mÛFZZ»wï&22’Áƒ¢WìÛ·3gΘ˜Èúõëñðð S§NøúúÒ­[7Ö­[ÇåË—¹xñ"kÖ¬¡wïÞ¶‚TUb5«TƒU«V±nÝ:[’s½zõxî¹ç¨_¿>† 6°råJ0›ÍŒ1‚1cÆØšºñÅìÝ»N‡££#“'O¶5©NLLäµ×^³µÆ¨Q£óæÍ»)V6;Ÿ~ú©-ì«uëÖ<ñÄÔ®]›‚‚V®\ÉÏ?ÿŒN§C«Õrß}÷1|øp[¡¨… rîÜ9´Z-îîî̘1ƒ   ²²²øä“O8|ø0:gggž{î9Ú·o_ÙPå:deeñî»ïræÌ[ô@ÇŽyâ‰'ðññ!//¯¿þš;v ×ëÑét<úè£ôë×/Ìüù󉉉$ÁÿÕW_µ)rgΜáí·ß¶…¸tîܙɓ'ßkŸÉdbõêÕ6¥Dä‘Gpuu%33“?üãÇ£Óépqqáù矧uëÖ€´?yùå—ÉËËÃb±È‹/¾ˆ¯¯ï¿þ®ªT—.]âÝwß%11­V‹V«eÈ!<ôÐCèt:ÒÒÒX°`aaa¶¹möìÙ4l؈‘W_}Õjغukž}öY[ÇM›6ñý÷ßÛÖ€»îº‹±cÇÚ†©(²²²øüóÏÙ¿¿íZxà† †N§#!!yóæ‘––†¢(Ô®]›Ù³gS£F 8ÀÒ¥Kmásýúõcâĉ¶¹•+W²yóft:†ñãÇÛUXV©z(ŠÂøøãm(NÇO‹…   ¦OŸn …ݶm_~ù%Z­£ÑȰaøÿþûqvvÆ`0°bÅ ¶mÛ†^¯ÇÁÁGy„Ü”ëILLä­·Þ²yËœœœ˜1c-Z´ÀÁÁ'NðÞ{ïÙ˜»wïΤI“ðððÀl6óÓO?±nÝ:›QtôèÑŒ9233ùøã9zô¨MV™:uªj\¯â°uëV–/_n›W½½½™>}:AAAhµZöîÝËÇ H”ÀÀy衇puu¥  €ï¿ÿž-[¶ØäÛûï¿ß¦Ð¦¥¥ñÁØR+ÜÝÝ™9sæM‰"‰Pœ?>ƒEQ`Ê”)¶Ž 6l`ÕªU¶5eäÈ‘Œ=½^Ovv¶M¯Ðëõ899ñÔSOѵkW@ÞŸW^yÅõS³fMæÌ™S¥dUa½IX,®^½J\\nnn¶Ù¢ÄÇÇMýúõKõ¸œ?ž¬¬,š7on+·nÅš¢Óé ²«þu3ÈÎÎæüù󸹹ѢE‹Û###ILL¤I“&%ò:ŒF#¡¡¡˜L&š6mj—¿g±X8þù¤²OCEå_eÅŠ|óÍ7zÌ .ðÔSOUö¥©¨¨¨¨¨Ü4T…µ òå—_UÙ§¡¢rÓÈËË#;;»²OCEå_%''‡œœœ =¦Éd"--­²/MEEEEE妡«ìPá=++ N‡‡‡‡Ý6EQÈÊÊ"//777œœœ°X,8::¢ÑhP…ììlrrrpttÄËË  0›Ídffâè舧§'&“‰ÌÌLE¡Zµjèt: Ðh4F233qvvÆÓÓ“‚‚²²²P___Û±UTn„sçÎñûï¿MïÞ½ÉÏÏ·mËÈÈà?þ`Ïž=¸ºº2hÐ ºwïNvv6'Nœ uëÖT¯^€¤¤$Ž?NŸ>}ˆ‹‹#99™üü|6mÚ„÷Þ{/yyylÙ²…äädî½÷^zôèAxx8YYYdddðË/¿P«V-FEZZ¿þú+Œ7ŽN:¡Õªv<•ŽÅbáÌ™3üúë¯$%%1`À pvv --íÛ·³ÿ~|||4h;w&##ƒS§NÑ®];|||¸rå gÏž¥gÏžDEE‘——G^^kÖ¬áÎ;ï´ý¦¢(¤¦¦B³fÍð÷÷¯ìÛ òààÁƒìÙ³‡_|‘‚‚rrrðôôTå•ÛŽ/¾ø‚ºuë2tèPrss±X,%äv•›ƒ*™U2QQQ¼øâ‹ <˜{o¾ù“ÉdÛ~þüy~øa À¤I“øþûïY´hƒ€={öðÿ÷ôíÛ—Ñ£GóÕW_‘——ÀªU«X¾|9Ï?ÿ< `ìØ±lذ7ÞxƒáÇ3dÈ>ûì3L&_}õ+V¬`Ê”) 8qãÆ±yóf^yå† ÆÐ¡Cùæ›o0›Í•}ËTn1Μ9ÃÝwßÍÆÑëõ,]º”µk×Ú¶/X°€Y³f¡×뉋‹ã¡‡â?þÀd2ñ /°mÛ6Û¾7näùçŸG«Õ²~ýzÆÏ’%KpuueýúõŒ7ŽY³f‘žžÎÅ‹™0a|ÿý÷Œ?žÏ?ÿwww¾ýö[ÆÏ«¯¾Jvv6çÎ㡇R#T*ŒC‡1räHvíÚ…F£áwÞá·ß~³mŸ;w.óçÏÇÙÙ™ .0aÂŽ;†Ñhäé§Ÿfÿþý€(¾?üðóæÍÃÁÁo¿ý–É“'óòË/k÷›<÷Üs,[¶LUTþ5"""øùçŸ8|ø0O<ñ)))•}Z**ή]»8qâf³™eË–ñæ›oVö)ýgP=¬•Hnn.Ï<ó ééé¼ÿþûäçç³téR233ˆ‹‹cêÔ©Ô«WY³f±gÏæÎKãÆ™ûŒ 6ðé§ŸÒ§OöìÙÞ={xÿý÷yöÙg™1cO?ý4“'OfÙ²e¬^½š%K–УGš6mZÙ·NåÁd2ñÑGÑ´iS>ùäêÔ©CXX£F²íóí·ßòôÓOóüóÏ“››Ë¢E‹HMM¥FtïÞ­[·2räH\\\X³f £FÂÑÑÞxã š5kFçÎ1bK—.%88˜³gÏ2qâD[‘///Þyç4h@Ó¦My衇8|ø0íÚµ#$$„Çœ¨¨(+û¶©ÜâF–.]JçÎY¼x15jÔàøñãŒ?Þ¶Ï7ß|Ãûï¿Ï£>JZZK–,!))‰®]»Ò¡C~ù冊ÉdbÆ Ü{ï½èõzbccY·nÍ›7çäÉ“$$$0{öl xï½÷¨]»veߕۓÉDjj*YYYx{{Û>7ÄÆÆrøðaRSS©V­F£FƒÉd"))‰† ’ŸŸÅbÁb±€££#~~~(ŠBbb"F£‘ZµjáêêjÛ×l6“˜˜ˆ³³35jÔ°ýÛd2Q§N[䂊JEb0HJJÂd2áççgû}Ðh4Lš4 €'NÁÊ•+©V­íÚµcß¾}¶|¥ï¿ÿžZµj1oÞ<||| $,,Œï¾ûŽx€Î;3~üx1bû÷ïç¹çžÃÇǽ^ϦM›l¹„ÁÁÁŒ;€!C†pážyæ¼¼¼Ðh4lݺ•ÜÜÜʾm*·W¯^åĉLœ8‘zõêаaCzõêe‹$ bõêÕxyyѶm[^zé%›B:|øpž~úirrrHJJ"<<œ¹sçڎߨQ#›`îéé @ÇŽqppÀ××777E iÓ¦Ô¨Qö¯F£¡cÇŽøùùÙ•Jtt4ááá<÷ÜsÔªU €æÍ›Ó¹sgÛ>AAA¬X±FCûöí™={¶M!>|8óæÍÃl6I\\ƒ ²}·cÇŽ´hÑwww4 f³™çŸžÍ›7³dÉ*û¨ÜƬ\¹’¯¾úŠØØXéÖ­!!!,[¶Œääd^ýuæÌ™ÃÎ;qrrâøñã8p€ãdzuëVN:ERRÛ·oÇÃÃÇœ˜˜¶nÝJVVÇçí·ßfíÚµDGGÉîÝ»©V­“&M"44”mÛ¶‘——ÇèÑ£™;w®íýQQ©²²²xï½÷زe yyy 2ĦH®]»–;v——Ç[o½ÅK/½DXXëÖ­#((ˆ… òþûïãààÀ¢E‹ ÅÛÛ›aÆ1cÆ \\\øè£prrbïÞ½œ8q‚ÚµkóÔSO±gÏvïÞ À³Ï>Ë£>ª*­¨!Á•Ê‘#Gð÷÷§Aƒ¶ÝíTÖ€IDATϺu놋‹‹m{õêÕ©V­:ŽFbá %11‘éÓ§óØcñä“OräÈl¡» 4° spp°åE9;;ÛåëYmE¯×ãååeÛW£ÑTö-S¹ÅÈËË#77×6Ž©Y³¦íßË—/çÁdõêÕLž<™ž={²uëVZµj…Û·ogõêÕ´lÙ’V­ZÙ¾ëääô—sN‹w•›Enn.ùùùv¹M...øúúÚþýã?r×]wñý÷ßóè£Ú"]:uê„““»víâûï¿§[·nvžÿ5jØ 0‹…úõëóÄO°xñb.^¼XÙ·@å6eÓ¦M¼òÊ+ôë×ßÿ &ðÑGжm[&Nœˆ¯¯//½ô=z”W^yÞyç@*[/^¼˜Ö­[³{÷núôéóÏ>‹¢(üôÓO¼ôÒKlܸ‘ƒröìYÞÿ}z÷îÍÞ½{iÛ¶-Ï<ó ¬]»–)S¦ðã?rìØ±Ê¾5*·o¾ù&«V­böìÙlÚ´ ³Ùlk!6räHúöíKÛ¶m™>}:îîî\¹r…/¿ü’M›6ñꫯҴiSž{î9ZµjÅÎ;y饗X»v­íäý÷ßç‰'žà÷ßÇËË‹ÿýï´hÑ‚_~ù…1cÆðÉ'ŸYÙ·¢J Jo•ˆƒƒZ­ÖN,j!4™L%lë¾Ö™ÀÀ@zõêeû›8q"óæÍ³í#ºªªT4ÞÞÞøúúÚåÚåååqéÒ%²³³9uêãÆcÆ |ýõ×´hÑ‚·ß~Á¼k×®¬^½šíÛ·3hÐ ›'UE¥ªR½zu<<<¸zõªí³¬¬,Û{™™É™3gxôÑGY¿~=_~ù%uëÖeáÂ…€„µk׎ï¾û޽{÷2dÈÜÜÜÊü=NǬY³˜2e F£‘•+WVö-P¹ ÉÏÏç÷ß§M›6LŸ> ðàƒÒ·o_@ ˆÖbK>>>¶H™ºuë2gλ(6mÚpÏ=÷àççÇСCÉÏÏç™gž¡aÆôë×???[EíŽ;2bÄüüü2d&“ɶ¯uMP£¿T*’””víÚÅO<Á]wÝE£F˜2e 7ÀÍÍ ñññ±ÉÚnnn<óÌ3Œ9oooÂÂÂhÛ¶-þþþ >œ/¾øÂv €~ýú1`À4h@pp0ÞÞÞ<üðÃ0bÄL&“]‘Êÿ2ªÂZ‰tîÜ™˜˜[ŽÅbá÷ß·M¼;w&11‘¤¤$@ªþž;w/U»ví¸÷Þ{™8q"&L ??Ÿ¸¸8µà†J• zõêÜyç|ýõ×üöÛoÄÇdziÓ&¶mÛ†F£!??Ÿ)S¦°|ùrrrrðöö¶óš:99q×]w±k×.Ž;Ƹqã*û’TT®K­Zµèß¿?Ë–-c÷îÝÄÇdzzõjöíÛ‡F£Á`0ðØc±jÕ*òòòl½uÜ»¸¸pÏ=÷°fÍ"##9rd¹¿§ÑhpwwÇßߟW^y…o¿ý–;wÚÂáUT*‚ììlΞ=KÇŽm‘` BwytíÚµD¸níÚµKäZ£¿ôz½ ãïïoS~­XsgUyG¥Â¹xñ"¹¹¹´mÛÖ6¾êÕ«W"±8µjÕ"((Fƒ³³3S§Neîܹ3gÎÒÒÒì"ÌŠ×ÌÐëõ¸»»jdcqÔ èJ¤~ýúôèу×_ììlL&K—.ÅÕÕ€öíÛS»vmfϞ͘1c8~ü8ǧY³fh4ÆŽËgŸ}Æ+¯¼ÂèÑ£9uêo¿ý¶-ìFE¥²Ñh4<òÈ#üñÇ<óÌ3Ô®]›‚‚î¼óN¼¼¼ðõõå‘GaùòåüöÛo˜L& ìÆp÷îÝñòò¢cÇŽ¶ðxA¥è„îàà`Ëé‰.pqqA§Óáääd·oñRWWW5OD¥BÐh4¶'Ÿ|’5j ( wÜqnnnøùùñðóxñbÖ¬Yc³ /^¼ØvŒ~ýúáèèÈ€J„ÔôlÞW­VËwÜÁÆùæ›oèÒ¥‹MøQQù§hµZœœœJB®×=ÀÉÉI¼Un)¬†¢c]Q”ëu:MŽÐét¼ôÒKŒ=š#GŽðÇðÔSO1wî\yä‘ʾÄ[U:«D\\\øøã™?>¯¿þ:ÕªUãÑG%;;êׯÏçŸμyóxùå—éÝ»7wÝuÙÙÙèt:6lÈW_}ÅG}ÄSO=EõêÕyóÍ7mÖø^½z¡×ëm …µ2ª///î½÷^üüü0`€­×%@ëÖ­í*Zz{{3zôh»}TTþ >>>üøã„„„žžNçÎíÆÑœ9sxì±Ç8tèÞÞÞtîÜÙNÈ6™Løøøpß}÷ÙYÒŸ}öY»ßéÙ³'YYY¶×®]›ßÿ"bE6l˜­xˆåtÇŽ•}«Tn#êÖ­Ëúõë9zô(¹¹¹tíÚÕ®¢ê‚ ˜2e ǧzõêtèÐÁ.ì·  €5jpß}÷Ù·hÊH݃óçÏÛþíêêÊ·ß~[Ù—¯râîîN›6mØ»w/xyya4Ù¸qceŸšŠJ…Ò¨Q#ÜÝÝùóÏ?éÛ·/z½žÐÐPΜ9cW<¯<"""˜9s&óçÏgòäÉüßÿýÿûßÿX¿~½ª°þ T…µ’©S§ï¼óIII¸¸¸P½zu[XØÅ‹Y¹r%K–,¡  www{ì1Z´ha ¯éÓ§íÚµ#55www[T€ûï¿ßî·‚ƒƒ ¶ý»FÌœ9(–0`À `ûw­Zµ˜={veß.•[gggºwï^æö:uêØµº±ÍÊ•+quu¥K—.ª•^å–ÂÅÅ…^½z•¹=  Ôо—.]bÅŠÔ«WÖ­[Wöe¨¨®xï½÷²e˦OŸÎwÜÁ¡C‡ìÚéõz ¶_•[ OOO&L˜À‚ pvv¦Y³f|ûí·¶î ^Ø´´4"""¨_¿~‰cøøøpôèQÞ~ûmFÅÕ«WÙ·o&L¨ìË»%qxå•W^©ì“ø¯£×ëñööÆÍÍÍN ÏÍÍå“O>áàÁƒ˜ÍfV®\ÉéÓ§yñÅñ÷÷·íçììŒO¹E9TTnE^yå~ùå¦M›fglQQ¹™6mþù'³fÍ¢C‡•}:**6üýýiÒ¤ {öìaçÎxzz2sæL6lH›6mðññáôéÓìÝ»—Î;ãããC“&Mhܸ±M¾1›ÍøûûÓªU+[Ø¥›› @«Õ¢( ´oßooohÞ¼9Z­‹Å‚——ýû÷$LS§Ó•HQQù§´jÕ www~ùå<ÈàÁƒ7nAAA4jÔ777öíÛGxx8½{÷¶Éò:t°¥!µoßžÖ­[Gtt4cÆŒaòäÉèt:ŒF#-Z´ aÆ€¼uêÔ±µ‰R½^¯¦v\C£¨Uª,Š¢Ãwß}G||<5kÖäŽ;î ]»vj‘•ÿÉÉÉàçç§æ—ªügHLLÄl6ãçç§Îõ*U‹ÅBVV–­uSÑLŠ¢™™IAA>>>ê¼­rKc6›IOOGQ¼½½íƳÙl&-- N‡§§g™]9rrrÈÊʲ«¢­r㨠«ŠŠŠŠŠŠŠŠŠŠŠŠJ•Dmk£¢¢¢¢¢¢¢¢¢¢¢¢R%QV•*Ém‘\`0ÈÉÉ©ìÓP©‚888”›[p«••EAAAeŸ†JÄÑÑÑ®ÿì­JZZ‹¥²OC¥ âââbëO~«b±XÈÌ̼nÏR•ÿ&8::Vöiü#ŒF#YYY×íUªòßC£Ñàååõòw+MaU…K—.qìØ1ÆŒcû¼  €'NpæÌèÑ£ÎÎÎe cf³™ß~û„„»fê·"ƒäädêÖ­{Ë Ÿ©©©hµZ»¾ƒ•Avv6  iÓ¦•òû&“‰µk×Ò£GêÕ«‡¢( vïÞÍÕ«Wiݺ5­[·.w¡ÊÎÎfõêÕ·übžžŽÑh´k¿t«M:u*µ¨ˆ¢(äåå1fÌ|}}+å’““ùå—_¸ÿþûÑëõ(ŠBZZÛ·oÇl6Ó¡C7n\îB•œœÌ÷ß[´Á¸rå ·EUÇÈÈÈ-Ïþm Ðjµ<ú裕òûŠ¢IHH£G¶;¯Ξ=Kƒ èÞ½{¹²Jnn.Ÿþ9µjÕª”ë¨Hbbb¨Q£Æ-/sAÕã¹¹¹0lذJù}EQ8vì¶v†VYe×®]$%%ѺukZµjU®ÎŽ;ðòòª”ë¨ÈûGõêÕoù1žMnn.~~~•~]»v¥cÇŽû•&ieeeñÆopõêU;…õwÞáÏ?ÿ¤mÛ¶lÙ²…Ÿþ™¹sç–)È(Š‚ÉdâÎ;ï¤N:•u9BZZçΣk×®·|e½ . ÓéhÔ¨Q¥žÇîÝ»+Íûn±Xزe sçÎå믿¦^½z¤§§óòË/“œœL`` «W¯¦ÿþ¼ð eÇh4¢Óéx衇*ë6VäææÞ½%ÿøãºtéR©ž£ÑÈÆ1•òûf³™O>ù„ï¾ûޱcÇ¢×ë cÖ¬Y¸»»ãééÉ—_~ÉÔ©S>|x™ÇÉÍÍÅßߟ{ï½·²ne…qäÈêÔ©Cݺu+ûTþ1[¶láŽ;î¨ÔsHMMeóæÍ•öû¼þú뤤¤Ø)¬óçÏÿöÎ;®ªúÿãÏ{¹ì)C@‚¨¸÷Þff–f6~-Ûï™M³´Rse¦¶5Ë­•ÛÌ÷Bp‚‚ì wþþøx/ ˆ Èü<Žç>çpî9ï×{ràÀš7oÎÆÙ¸q#&L¸­“V¯×ãããSl>zudÏž=„„„Ôˆ12UᎎæèÑ£fûýL˜06mÚ˜kjj*~ø!)))øûû³lÙ2úöíË»ï¾{Ûý¨ÕjÚµkGûöíÍv,V«åСCW{'êõë׉§eË–f]ÇñãÇIOO¿§}˜EiµZV¯^ÍñãÇñöö6½ή]»øßÿþÇ€¸|ù2£GæÀf¿¡TÎÎδmÛ¶F´¼6·P­ œ;wŽß~û­Èk»wïæÒ¥K|ûí·4jÔˆM›61}útFŒŸŸŸ¹—|ß©IÇØ±cÇõ¾[ôz=;wîäßÿ-òÚªU«°±±aÖ¬YØÚÚòý÷ß³téRÚµkW#"ëw"44´Ú— 1κ|PÑjµ¬ZµŠ“'O™}~îÜ9vïÞ͸qãèׯ/^ä•W^áСCôïßßÜ˾ïtèСÚ;Õ<è׸Z­æÇ$66–6mÚ˜^ßµkW®\á»ï¾# € 60{ölüñõ/ Ú¶m[#®ñÚµkãîînîeT•þT5 ìß¿ŸíÛ·3dÈ"ï8qooo:uê„J¥ÂÏÏ:°ÿ~sŸ§JA©TbeeUíÓT*Uø²ß-yyyÌ›7¾}ûy=,,ŒöíÛ€J¥¢}ûöøøøpèÐ!s/¹R¨I×…µµuø®Þ-QQQüòË/E¢N:Ž#GŽ0pà@\]]±µµeРA¤¥¥qéÒ%s/¹R°´´¬NG Ú§ÃÝ ƒ½{÷²{÷n\ä½ãÇS·n]“p«_¿>íÚµ{`l++«ã”y¯q­VËÊ•+ÑétŲž>L‡¨_¿>*•Š:àííMXX˜¹—}ßQ(5æ·°°ÀÒÒÒÜ˨*ý¯‘––Ư¿þʈ#ðõõ-òÞ¥K—°··7¥ÔXYYÑ AΟ?_ê>õz=yyy²a‡Ä„Á` ??ß,Š4 +V¬ÀÞÞžaÆy/22oooSdÎÍÍ www"""JݧN§#77W^ãÆ#­V[éM.rrrX´hQ±šƒÁÀ… ŠxàýýýQ«Õ\»v­Ô}j4òòòdÃIòòòÌÒ¨(%%…E‹ñÄOP¯^½"ï]ºt ‡"¶J@@ÀmF#›çIŠ`NûõäÉ“¬_¿ž7ß|³Xêkdd$uêÔ1‰wwwÜÜ܈ŒŒ¼íþŒv—V«­ôc‘T]´Z-ùùù÷ül¯TÁš——Ç‚ ð÷÷§OŸ>%”B¡0y5Œ^ŽÌÌÌR÷›––ÆÿýGNNNeޤ £Óé8~ü8ÇŽ«ô›ç‘#Gøë¯¿xýõ׋Õ3i4”J¥)2gŒ8fee•ºÏ„„víÚ%»aKLäååñßÿqñâÅJy:Ž¿þú‹„„ž~úébÞ[­V[$Âhee…V«%//¯Ôý†‡‡sðàAÙEUR„mÛ¶qýúõJýF[¥Aƒ%¦ŒïãF[ŘUš­b08sæ ááá•{%UšÌÌL¶mÛvG;÷~üÞyóæ1hРK¸J²U,,,JµU4  >>¾rO¢¤Jþ}ûîÙ¯TÁºuëVþûï?{ì1RSSIOOG«Õ[ª1s§p¶³³3:uªömï%‡……-Z´ E‹•š‚š’’ÂܹséÝ»7–––ÄÅÅ¢ jrròm…ÅÖX»vmºv튽½}åDI•ÆÚÚšN:P©©É‘‘‘üþûï<òÈ#äå员˜@\\%~F©TÞ1M600víÚÕ˜tZIÅУGJכּeËöïßÏ£>Jjj*h4š{²U ÁÁÁfëX/©š888УGJí*žŸŸÏÏ?ÿŒJ¥¢cÇŽ\»vÜÜ\²³³¹víZ©Â¢4[ÅÒÒ’víÚáééY©çPRµñññ©º÷J-&Û³gééé|òÉ'$''“––Æ›o¾É'Ÿ|‚³³3±±±¨Õj¬¬¬Ðét$''iÌTØÛÛ׈|sIÅ P(°µµÅÖÖ¶Roxx8W®\!==íÛ·›Ò|¾ýö[ÂÃñµµ5¥¸YXXMvvö›T©Tª1&CRq(•Jìíí+½îýðáÃ$%%±`ÁÓ5 0vìX†޳³s‘L€””,--ï8âÊÚÚZ:%Åppp¨ôº÷Ý»w±U’’’ÈÈÈàÍ7ßäÓO?ÅÙÙ™„„“­¢ÕjIII¹£­bmmý@×LJŠcaaƒƒC¥:êÒÓÓ9xð ÉÉÉŒ?£ŠT*IIIL›6Zµj™Ê”J%ÙÙÙäääФI“ÛîW¡P`ggWcj&%ƒ••vvv÷<Í RŸo¾ù&O=õ”éç 6°sçN&NœHƒ L3Ÿ¢££iÔ¨yyy=z”nݺUæ2%’»¦Y³füðæ´FFÃ3Ï<óÏ>K×®]qrrâàÁƒdggãääD\\111<÷Üsæ^ºDR&HóæÍM?‡‡‡óùçŸóÑGQ¯^=ÂÂÂ8pà€©ìãĉX[[ãïïoî¥K$eâwÞ!55ÕôóºuëØ»w¯ÉVÉÊÊbÏž=\½z• ››Ë±cÇøŽ³’êA­Zµ˜Phh(*•Š+Vð /°{÷nâããéÞ½»¹Ï“DR&œœœŠóÆ 6¤~ýútëÖ5kÖ°eË:uêIJe˰´´¼§aÊIeR»ví"CÈ^Ó-Z`ccC¯^½øé§ŸØ¿?µjÕbùòåIÁ*©6Üj«„……±UZµj…B¡`ÅŠ<÷Üsìܹ“7nH纤Z`iiIãÆ‹¼æì쌫««©[pçÎY½z5[¶l¡C‡,[¶ ZµjeîåKPÌ:_¢Q£FEš/9880eÊæÏŸÏË/¿Œ——“&M’5’j‹R©dèС¦ù“Mš4a„ üòË/,^¼˜àà`¦OŸŽµµµ¹—*‘Üîîî :  ƒ&77—Ù³g£ÕjiÕªo¼ñ†L“T[7nLïÞ½M?;880uêT,XÀË/¿Œ··7“&M¢Q£Fæ^ªDrW´oß¾HŒ¦M›šl•E‹Ñ´iS¦M›&m‰Ù0«`íÖ­[1d`` “'O&%%ggçb­¶%’ê„J¥bÚ´i¦Ÿ•J%ݺu#88˜¬¬,j×®-ëö$Õš€€€"׸J¥â‰'ž GhµZ<==Mcœ$’êH=èÑ£G‘ׂ‚‚øâ‹/HIIÁÅÅåŽ5ÚIUæÙgŸ-ò³R©¤{÷î“§§g¥÷‘H cVÁz;œœœprr2÷2$’û†»»;îîîæ^†Dr_P*•wl@#‘Tw¤­"©éxxx˜2Ä$s"ÛêJ$‰D"‘H$‰¤J"«D"‘H$‰D"‘Hª$R°J$‰D"‘H$‰¤J"«D"‘H$‰D"‘Hª$R°J$‰D"‘H$‰¤J"«D"‘H$‰D"‘Hª$&XSSSÉÈÈ0÷ñH$‰D"‘H$‰¤†pOsXµZ-ûöícÓ¦MDGGÓ¾}{zè!N:E¿~ýpttD¡P˜û%‰D"‘H$‰DR ¹ë«N§ãï¿ÿæƒ> ==­VKtt4Z­–U«V1fÌRSSÍ}|‰D"‘H$‰D"©¦Üµ`MMMåÏ?ÿä©§žâ믿¦{÷îòùçŸsíÚ5>lîã“H$‰D"‘H$I5å®kvv6ׯ_gذa899™^·°° ~ýú„„„pîÜ9sŸD"‘H$‰D"‘Hª)w-X•J%–––\¾|¹Ø{yyyÄÆÆâââbîã“H$‰D"‘H$I5å®›.¹ººÒ¡C¾ûî;t:jµ€ëׯ³|ùrâââh×®¹O"‘H$‰D"‘H$Õ”»¬vvv¼þúëÌ™3‡¯¾úŠøøxôz=ǧV­Z|ðÁ4iÒÄÜÇ'‘H$‰D"‘H$’jÊ] ÖÌÌLvíÚÅ‹/¾Èˆ#ˆŠŠÀÑÑ4h`îc“H$‰D"‘H$I5æ®kFF‹-ÂÆÆ†¡C‡Ò²eKs‹D"‘H$‰D"‘Hjw-XÝÝÝyôÑGÙ°a!!!Ô­[·Ø6ÖÖÖ(•wÝ×I"‘H$‰D"‘H$0w-XóòòHJJ"""‚¡C‡âããƒB¡(²Íüùóñ÷÷7÷1J$‰D"‘H$‰¤rׂÕÚÚš¶mÛpÛmjÕªeîã“H$‰D"‘H$I5宫­­-ýúõ3ýœ““CVVµk×.õsƒ+W®péÒ% ÆÉÉÉô¾N§#**Ѝ¨(j×®MPP*Õ]/S"1 ™™™œ8qFƒ¿¿?~~~¦ôx­VË™3gHMMÅßߟzõêaaaaî%K$å"!!³gÏbeeEÆ ñôô4eÙäæærüøqôz}±÷$’ê€Á`àòåË\¾|GGGš6mŠ£££éýÂ¶Š§§'Mš4‘¶Š¤Z¡V«¹xñ"W¯^ÅÝÝæÍ›ciiiz_«ÕrúôiÒÒÒ¤­"1;÷twÍÍÍeÏž=¬_¿žK—.¡V«qss£K—.<õÔS¸ºº1R4 «V­bÉ’%888`0°³³cüøñ¡P(X±b«W¯ÆÚÚµZM=xñű³³3÷¹’HÊÄùóç™2e ÙÙÙXYY‘››ËC=Ä /¼@nn. ,`ß¾}ØÚÚ¢Ñh1bÇ7÷²%’2¡×ëÙµkóçÏG©T¢T*ÉÏÏg̘1tëÖøøxf͚ťK—°²²B¡P0nÜ8Z·nmî¥K$eB£Ñ°bÅ –-[†££#z½{{{ÆO“&MP(,]º”¿þú òóóéÕ«Ï?ÿ¼´U$Õ‚¼¼<¾úê+Nœ8½½=jµš€€Æ‡§§'YYY,X°€ýû÷›l•‘#GòØc™{é’”»îˆ¤Õjù믿øì³ÏÈÍÍeذa<ùä“´hÑ‚uëÖñé§Ÿ’––Vä3ÑÑÑ,]º”§žzŠ… 2gά­­Y±bjµšØØX~þùgÌ¢E‹7nË—/çØ±cæ>OI™Y¹r%ƒ9sæ°hÑ"}ôQV­ZEll,aaa¬]»–qãÆ±páBú÷ïϼyóHJJ2÷²%’2‘Ío¿ýF‹-øñÇùþûïi×® .$%%…5kÖÁ¬Y³øþûïñ÷÷çûï¿'33ÓÜK—HÊDTTË—/çé§Ÿ6Ù*¬\¹FÃÕ«Wùå—_2d .äÿûK—.åäÉ“æ^ºDR&>LXXo½õ¿ÿþ»I¼îÚµ €C‡±nÝ:ÆÏÂ… éÛ·¯´U$få®krr2þù'ÿ÷ÿÇ·ß~ËK/½Ä‹/¾Èøñã™7oçÏŸgÿþýE>“žžŽ££##FŒÀÎÎooo‚‚‚ˆŠŠ"??Ÿ°°0<<<4hÖÖÖ´lÙ’Ö­[³{÷nsŸ'‰¤Ì$&&2räHêÔ©ƒ••¡¡¡¨T*bbbØ»w/íÚµ£U«VX[[3`ÀÜÜÜ8pà€¹—-‘” FC~~>O>ù$...¸¸¸ÐªU+’““ILLdïÞ½ <˜úõëãââÂOùä.^¼ÈÚµkïz_VVV 8† šåX$U“&Mš0xðà"Žì»á®-{{{>úè#¦L™Â´iÓx÷ÝwqÁ2iÒ¤"ia7nÜ ;;‚ƒƒ ÆÕÕ•Ñ£Góúë¯cgg‡N§C«Õ¢R©Ðëõdeeáíímîó-‘”‰üü|¢££©S§Žé_³fÍ=z4;wîÄÞÞFƒ^¯7uWÍÏÏ7¥WJ$UÌÌL®_¿Ž¿¿?JŸ>}ˆˆˆÀÎήˆ'5++ kkk\\\̽t‰¤L$$$““ƒ¿¿?M›6¥iÓ¦¸¸¸ðꫯòæ›obggGbb¢ÉVÑétÒV‘Tt:qqqX[[ãééI›6mhÕªIII¬^½š^xÁÔ9Øh«äåå¡V«å5.1waQËôñdz`Á¾ÿþ{fΜÉÏ?ÿÌìÙ³éÚµ«)•ÀÈÿýÇW_}U$}­pd $$„´´4âããaüŸ={¶˜ð•Hª*YYY|ñÅœ8qƒÁˆkÜèy åâÅ‹&/}BB×®]£Q£Fæ^ºDR&¢££ùôÓOM÷i(¸[XXмyó"ÙçÏŸG¥Ráååeî¥K$eb÷îÝL›6í¶¶J³fÍHII!!!¶Ê¹s礭"©hµZ–.]ʲeËÐëõ€È(œÝb´UŒÎÇøøxâããeôTb6îI°jµZŽ9ÂáÇéÖ­ƒ "%%…ÿý—«W¯ÛÞÏÏsçαzõjbbbˆˆˆà矦{÷î899Ѿ}{rrrظq#iii}ú°}ûv"""ˆ‹‹cÕªU¦¬‰¤:P¿~}Μ9Ú5kL¶Ê/¿üBÏž=qpp cÇŽdff²yófÒÒÒØ¿?ááá 0ÀÜK—Hµ5¾¾¾lÚ´‰mÛ¶ÇñãÇY³f ƒ gÏžœ9s†°°0“­’““C÷îÝͽ|ÉÊ]§ët:V®\ɯ¿þJ‹-0 ( ²³³ùóÏ?Ù·o_~ùe¯z³fÍxûí·Y²d «W¯ÀÓÓ“·ß~;;;ìííyûí·Y¸p!»wïF«ÕòüóÏÓ¤IsŸ'‰¤ÌŒ7ŽÙ³góñÇ£P(°°°`ôèÑ4mÚ­V˨Q£˜?>*• ¥RÉ»ï¾+‡ÍKª ÆÌš~øÁ4#ÛÒÒ’ñãÇS·n]† •+Wøøã±°°ÀÞÞž÷Þ{ïžëW$’Ê¢yóæ¼ñÆüñǬZµ ///Þzë-lmm±³³ãí·ßfÑ¢EìØ±­VË‹/¾H`` ¹—.‘”‰!C†˜œÆ>:ubĈ€ˆ°Ž9’¹sç¢R©°°°¶ŠÄ¬Üµ`MLLdåÊ•Œ5ЧŸ~Ú”JðøãÓ²eK^{í5öïßϰaÃLŸ±¶¶fĈtëÖ¸¸8lmmMmâôïߟÐÐP®\¹Bݺu©W¯ž¹Ï‘DR.š6mÊܹs¹xñ"9994nÜØÔ,É‚^xîÝ»“˜˜H`` l¤$©VXXXЫW/Z¶lITT7ÆÞÞ‚ö£>âüùó¨Õjš4i"IµÂÆÆ†‘#GÒ£G“­Ò¸qã" ühúøøøàããcîeK$eÆÁÁ>ø€¸¸8âããqss+’îkmmÍK/½D=HJJ¢I“&²Ĭܵ`ÍÏÏ'==~ýúœuëÖ¥yóæDGGûœB¡ÀÛÛ»ÔÂmOOO<==Í}n$’»ÆÖÖ–fÍšÝöý РAs/S"¹kjÕªu[g‹J¥"$$ÄÜK”Hîš²Ø*^^^²6[RmQ©Tøùù•Úô±aƲnUR%¸ëVKKKìíí /ö^ff&/^”Þ‰D"‘H$‰D"‘Ü5waõðð`ðàÁ|ùå—=z”®]»bkkKTTþù'ýúõ3÷ñI$‰D"‘H$‰¤šrׂÕÒÒ’'žx V®\ɪU«°µµ%==:ðî»ïÊT‰D"‘H$‰D"‘Ü5å¬$%%áíí­­-µjÕbôèÑŒ=š˜˜Ôj5nnn²‰ŒD"‘H$‰D"‘Hî™r ÖôôtþøãRSSiß¾=:uÂÍÍ |}}Í},’û„Z­&;;•J…J¥’ììlÖ¯_ÏñãÇyá…hÔ¨¨Õjrss±²²ÂÆÆ…BaîåK$%b0ÈÈÈ ??Ÿääd’’’ ÄÕÕ•JEnn.dddЦMÙéV"©$Ôj5aaa899akk‹F£1÷’$‰DbFÊ%XëÕ«Ç'Ÿ|ÂåË—Ù³gß~û-J¥___:uêDÆ qrr2÷1IʉF£áìٳܸqƒ””233ñööÆÅÅ…¼¼<þý÷_®]»†µµ54kÖŒuëÖáììL‹-øüóÏi×®>>>}š:uêP·n]²²²Ø±c¿þú+NNN¸¹¹¡ÑhHLL¤E‹4kÖŒ7’µµ5‹/æé§ŸÆÑÑ‘ÄÄDRSS  yóæòú–Hî’¬¬,NžXYYѧO–,YBDD>ú(~~~\¼x‘-[¶°lÙ2Z´hAûöí©[·n‘9v666(•JœMs|ï–ÜÜ\âââ°²²ÂÊÊ t:ÉÉɦù’ ½^Obb"»víbÓ¦M€pÎ8::¢P(°´´dÆŒx{{cooV«åÚµklÛ¶={ö0bÄZµj………GŽá?þ09mlmmY¶lsæÌ!88˜6lˆ­­-Z­sî\]]e¦DRNGll,Û·ogÛ¶mxzzR¯^=¾þúklllHKKãá‡füøñ8::Í?ÿücîeK$ŠN§#!!GGGs/E"©ܵJP*•8::âèèHƒ xôÑG¹víaaalذÌÌLz÷îÍ AƒÌ}Œ’[ÈÊÊbõêÕ¬Y³†þýû3vìX‚‚‚P*ï<åÈßß¿ØkÞÞÞŒ7®ÈkõêÕ£{÷î\¸p³gϲyófòòòpvv&))‰ôôt¼½½IMMÅÏÏÒªU+bbbˆÅßß¿Ôùw…ILLdÆŒ\¾|™:uê`0°³³#77—øøxÞzë-sŸrI%“‘‘Á’%K ÃÛÛ›·Þz‹6mÚ V«‰ˆˆ ??ŸæÍ›q¨©T*|}}yá…Ší¯gÏžôìÙ³Øë—.]âìÙ³DDD°cÇ @§¦¦biiÉàÁƒéÝ»7ÖÖÖæ>-I¥ʼn'ðõõ%$$+++4 W®\aýúõ=z”Ž;2uêTS9‘F£áÈ‘#8;;lÚ—‹‹‹LÇ—Ô8:Ä矎ŸŸ;v”׸DrîZ°ªÕjS”DÊZ­¦yóætèСLâGR9$&&òÓO?‘““ƒ££#/^¤~ýúÌ›7Ÿûö·R*•È!CÐh4 4) eŒÚ~ÿý÷$%%aeeEݺu‰Å××—^½záââBZZqqq899Q¯^=@Ìüýý÷ßéÖ­~ø¡©ŽÖÈdÊf G¯×süøqfΜI:uÐh4ܸqƒþýû3qâD¼½½MÂÔÊÊŠfÍšUØïnР 4À`0ŸŸ^¯Ç ÒÓÓ‰ŠŠâ·ß~cãÆŒ7ŽÚµk“žžNVV®®®¸ºº–éû§×ë ',, Ù AAA4jÔÈܧ_" %%…cÇŽñÏ?ÿOË–-Ùµk7nÜÀÅÅ…¤¤$ìííéС_ý5^^^E2k,--騱£¹C"©p´Z-z½+++ Ì™3‡‰'beeÅ?þHýúõͽL‰äžÈÏÏ'>>žË—/MJJ ¹¹¹\»v˜˜^|ñÅ{Ú¹«V«%,,ŒmÛ¶ñÐCѪU+4 ß|ó ;wîD§ÓÈ›o¾IPP¹ÏŸX°`Æí4h•š®­R©n›ö;|øp}ôQÒÓÓ©U«J¥’´´4>ÌîÝ»±´´ÄÍÍÍ´}nn. ÄÆÆ’Í믿N»ví°°°(¶ocú§¤ærêÔ)¾øâ ^{í5‚‚‚HNNÆÍÍÍäÔ¨  666E^sssÃÍÍÀÀ@6oÞÌøñã±´´ÄÞÞ½^OVV}úôaÈ!xzzš>———GTTµjÕÂÓÓ“œœ/^ÌhÒ¤ (•J>ûì3ºuëVæL‰ä^IIIáÆ¦Ÿ]\\ðððàСC|ÿý÷¸¸¸0lØ0Zµj…““ƒ+W®žžŽ¯¯¯éþ.‘ÔTÒÒÒ¸~ý:7nÜ 11‘K—.qåÊ,-->|8mÚ´aúôé<üðÃtêÔ WWWŽ?nî¥K$w$11‘ 6]ì½ððp²³³ñññ¡~ýúàì쌫«+ñññ÷œeVnÁºqãF¦L™BPPz½€uëÖ±zõj~øaüýýÙºu+}ô ,³XÍH^^?ýôÙÙÙ|ðÁUzÜJ¥*"J]\\èׯ½{÷(QŒjµZ *•JŠÒ­VKRR™™™DEEñË/¿0nÜ8:vìˆR©¬T¡ZxüñÇéÑ£Z­”J%III¬[·Ž÷Þ{Ï}ÒjµXZZbkk‹N§C£Ñ`aaAãÆ™1cnnn(•J ݺuã×_eåÊ•tîÜÙ܇)©Áäçç³cÇæÍ›‡½½=ÖÖÖXYY‘Z­ÆÝݱcÇŒ¥¥¥é~¬P(0÷ò%’ %''‡ãÇsöìYâââÐëõ$$$ššŠB¡ÀÍÍ OOO¼¼¼hÒ¤ =öIII¬X±‚9sæÐ©S'†nÚŸ………´a$U ½^OLLŒ©Œµµ5äï¿ÿ¦E‹xxxûÌsÏ=GPP666ÅTz½žôôô{ZS¹kRRK—.eÀ€Œ3233Ù±c-Z´àwÞÁÅÅ…öíÛóÚk¯)k%`0ˆåСC8p€øøx°³³#::šŸ~ú©J‹ÕÒ(I¨¹×FM’êÇ7øî»ïˆ‹‹C­VãììÌ«¯¾Zå›B¡(vƒ···7ÕW߸qN‡R©¤V­ZXYY¡Ó鈋‹#''Ç46ªðþ¼¼¼;v,?ÿüs©ß‰¤¼ÄÆÆ²cÇš7oNhh(K–,aݺuL™2¥XJ}vv6 …BÖàIjÉÉÉ;vŒóçÏ޽½=]ºtÁÑÑ‘åË—£Ñhèß¿?5ÂÞÞ{{{jÕªEíÚµK´M6lH›6mˆŠŠÂËËKö4˜ŒŒ bbb¸páùùù4lØÀÀ@ôz=+V¬`ãÆxzz¢T*Ñh4¸»»3a‚‚‚Ìbs”Ë≉!''‡Ç{ ˆŒŒä¥—^2½V§NêԩÑ#GèÖ­[¥ԃƱcÇ?~<ä‘G¡yóæÄÆÆ’™™‰¯¯o‘È¥DRÉÌÌäÏ?ÿdÓ¦MôíÛ—I“&™{IJíÚµ‹½faaqÇùÖxyyÉ4KI…––ÆO?ýÄÞ½{éÖ­?üð111„„„ðÛo¿áìì\ì3² »¤*cŒÕ®]»ˆSeûöíìÝ»bbbP©Tøøø‘‘Á•+WÈÎΦY³fðÚk¯‘––Fxx8Û·oçé§Ÿ¦S§Nåvš«T*6lhîS"y@ÉËË#!!+W®°qãFbbbLŽ;ƹsçLýþøã*Õź\ß¶ììlt:]‘Y«—/_æúõë´iÓÆÜÇò@rýúufΜÉäÉ“‹4»2:$’êŽV«åçŸæÒ¥KL™2E6§Hî.\`Ê”)0kÖ,4h` æääT¬F["©ÄÆÆòÆoÄk¯½†··7k×®eíÚµ 6¬Ä牋‹ õêÕ+Ö°±k×®æ>‰äŽ ÒÒÒØ´i—/_Æ`0••Å¥K—°²²ÂËˋ޽{Ó¦M›bY°™™™dffâééYå2·Ê%X]]]±´´$!!???vïÞO‘H€V«%--MЦJ`öìÙ´oßÞT¼/‘Ô$rssùñǹxñ"_~ù¥¼§H$@ZZ7nÜÀ××+++Ž=ÊŒ3xæ™g>ž>úˆ×_­VË|€½½=vvvüðÃ%f H$Õüü|"""ÈÊÊÂÍÍÈÈHÖ®]‹¿¿?C‡5Ms©S§N‘€cIÇ•VEÊ%XýüüðôôdÑ¢E8::’””Äž={èÝ»7J¥NGVVk×®%--M¶¨¿èt:ÒÓÓÉÈÈ`ÿþý¤§§óÑG™{YI…¢×ëÉÌÌä?þàäÉ“Lžú(ƒ   †Ž……aaa|÷Ýwœ;wŽW_}Uv¼¬[·Ž7¢R©¨S§'N”†¼¤F‘‘‘ÁæÍ›Ùºu+uëÖ嫯¾’ÍÛ$’{@§Óqúôi/^LZZ¯¿þ:Íš5#66–óçÏ3|øp7n,;•Jª5ÉÉÉ:tˆððp.\¸€ Ï<óŒ)µÑÏÏÏ”(‘TG’““ÉÎÎÆ××µZͲeËØ·o“'O¦nݺæ^Þ}¥ÜmV›7oÎÂ… 9wîz½ž   SÊÁ` aƼøâ‹´k×NvA«@´Z-kÖ¬áŸþáÝwߥ^½z¦ñIM!))‰O?ýgggÆŽKƒ díœDRN233‰G¯×›ž‘‘‘Œ9’.]º˜œœ 4 Aƒæ^®DrW 222¸té»víâðáÃÒ±cGzè¡2¥@J$Õììl<ȯ¿þŠF£ÁÚÚš:uꔔĔ)SŠÌr¯©”[°*•J”J%z½žäädnܸa×Ю];Úµkgîcª‘lذ?ÿü“/¾ø‚F™{9I…ÃÔ©SiÔ¨/¿ü²ì>*‘Ü™™™L™2…˜˜puu%00·ß~[fãHj 7nÜ`Æ ìÚµ •JE=˜1c>>>æ^šDR¡ÄÆÆ2}út²²²øßÿþgÊŽ‰' à«p‚õÔ©S¼ÿþûdffbiiIvv6C‡å½÷Þ3ö–FJJ ëÖ­ãØ±cèt:ºuëFÿþýMÒk×®±~ýzN:…ŸŸÆ # à$êõzÖ®]Ë_ýÅôéÓ©W¯ž¹—$¹jµš£G²iÓ&âââfàÀ4mÚ½^Ï¥K—X¹r%ñññ„††2hÐ ¼½½Í½l³Çøñãyä‘GxüñÇËt/‘˜ììlvìØÁîÝ»ÉÈÈ 44”aÆáåå…F£áøñã¬Y³NGûöí8p æ^v'::šO>ù„¶mÛòᇢT*Q©TXZZ>°Ïл%99™õë×sôèQôz=Ý»w§ÿþ¦ÚǸ¸8Ö¯_ÏéÓ§©_¿>Æ Ãßß_žçûÌ… زe  }ûöLš4 ìììdJ{9¹xñ"ÿüó'NœÀÉɉÁƒÓ±cGlllÐét&[%!!–-[2hÐ YžS‰deeñ×_ñ÷ßóÜsÏÑ£GSC¤1;¦\wV­VË/¿ü‚¥¥%ü1_ý5 `ÕªUœ?þŽŸÏÍÍeþüù,^¼˜àà`š6mÊ?üÀ/¿üB~~>_~ù%Û¶m£sçÎÄÆÆ2iÒ$Í}žÌÆÕ«Wùí·ßxóÍ7ñõõ5Û ùàAÈȸýû p劙N`0ÀÍK¨ññ6h4åöËÜaaa¼ûî» 0€'NðÉ'ŸCbb"~ø! tìØ‘-[¶0sæLó¸*@||<~ø!C‡å±Ç“bµŠ£ÓéøóÏ?™6m^^^têÔ‰M›6ñõ×_“’’ÂÉ“'™8q"4nܘ_ý•Õ«W›{Ù5š´´4-ZÄøñãéÑ£/¿ü2ŽŽŽØÛÛcmm-ET9ÉÍÍeÞ¼yüþûï„„„Ì‚ øõ×_Q«ÕLž<™;vйsg¢££™4iIIIæ^zåÒ¥K|ýõ×üïÿ#++‹¯¿þšwÞy‡úõëcoo/Åj9IOOç“O>aÇŽôêÕ 777>ùä¶lÙ`²U’’’èØ±#›6mbÖ¬Yæ^öÑî=z4ÇçóÏ?çᇮ²Ý{+‹rYòIIIÄÆÆòÜsÏ1`À ÞÞÞœ9s†Ó§OÓ¬Y³R?o¬3øê«¯hß¾=!!!Œ;–Q£Fqùòe.^¼ÈôéÓiÖ¬=ôO>ù$ÿüóÏ>û¬¹ÏU¥Åøñã;v,mÛ¶­}êõ Ñ@áòâèh7úô¡N(<;3þú .\€gž)y¿3gB³fP¿>ÜËs#=~ùºt"¸A±ÏB󾉋ƒ¼<ñº…> ëÖÁ¥Kðüóб£8Î @£±¤²Çv®^½šN:ñé§Ÿ¢R©èÛ·/¯¿þ:ëÖ­3ÕuöÙgÔªU‹àà`ÞyçŽ?þ@vèLJJbâĉôéÓ‡#FHú™™ÉŸþÉK/½ÄÿýßÿЯ_?}ôQŽ;Æúõë æã?F¡PàîîÎâÅ‹éÑ£‡œ¡[AäççsöìYŽ9ÂñãÇILL¤sçÎLž<™FIãý¹páÿý÷S¦L1={ƒƒƒyï½÷xê©§ˆˆˆàÊ•+̘1ƒȨQ£ø÷ßyꩧ̽üÅ©S§øõ×_‰gàÀ,]ºGGGyß#ÿý÷yyyÌœ9“€€ôz=ŽŽŽüòË/ :”¿ÿþ¥RÉgŸ}†³³3¼û8q‚ÐÐPs/¿Æ‘››Ë®]»X³f ôë×I“&Påæ¡š‹r‡ž,--ñðð0Ý,ìííqqq!99ùŽŸÕjµÔ«WV­Z™>ïííMNNz½ž .àååEýúõQ(ØÚÚÒªU+N:eîóT) Ôj5àÈ‘#8p€~ýúÑ­[· Ù¿N'O¼yðì³Ð¹3¤¤ÀôéððÃо=L˜?ƒ 1°cxzBr2;­ZÝïÅ‹pêhµ0dÜM·x½._†3g„൳ƒÓ§aãF ‚hÜ~þYlÓ¸±ÖТ…ø÷ê«°f üóX»JmÛfciY¹µ*•Š^½z¡R©P(8;;cccCNNW®\¡yóæ888 P(ðññ¡^½zœ>}ú¬ƒK—.±gÏ,,,Ø·o 6dذaR¬V ÎÎÎtéÒÅt÷òòB«Õ’——GDD£G6ý=CCCùé§Ÿ¸zõª¬÷ˆ^¯'::š¹sç’——GÓ¦MyõÕWñõõ¥V­Zæ^^A«ÕâëëKhhh‰¶Jdd$ÞÞÞøùù¡P(°³³£eË–œ:uJ Ö B¯×sèÐ!æÎËÃ?Ì Aƒä(š $??ŸV­Z™®a¥RIíÚµÉÊÊàüù󄆆š¢×¾¾¾Ô­[—3gÎHÁZ Ο?ϼyóÈÉÉáÙgŸ¥]»vØŽÒH€»¬·¢P(Êìé eáÂ…¦Ÿ³³³Y»v-M›6ÅÞÞž¨¨(lmmM]ݬ¬¬hذ!kÖ¬)u¿†””<==«µ'"--?þ;;;Z·nÍœ9s*¬€^ß/Ää°a°t©š'NÀË/ A¨T·ßÂþýðãðâ‹› +WÂÀõë0güö[Á~u:ˆŠ‚·ßÿ-¿`U«aýzX¶L¬åÿ¯‡„ˆÿææŠµ_¾,"Àï¿/m^\½ âú7Ä:®_7”Áþý© •ûÅŸ>}ºéÿ û÷ï'>>ž'Ÿ|’ùóçÓ¿Ól,www<<<ˆŒŒ,uŸùùù$%%áââ‚JU¹)ÎÉÙ³g™0a:uÂÏÏQ£Fѹsg™|èt:RRRÈÎÎÆ`0TÚï­U«‹-2ý¬V«Ù´iîîîøøøpåÊêÔ©cz? µZÍõë×KÝoVV©©©¸¸¸ÈèI äçç³téR6mÚÄðáÃyôÑGˆïMRR’©d¨²hÕª¿üò‹ég£­Ò¬Y3ìì숊ŠÂÞÞÞd«X[[Ó AÖ¯__ê~333ÉÌÌ|àSûîDvv66l`õêÕ|üñÇ5Z iµZ’’’Ðjµ•ú{{ì1{ì1ÓÏÉÉÉlݺՔýxéÒ%‚ƒƒM÷ÜÜܸpáÂm÷©×ëIMM%//Ov÷/999lذ+Vðä“Oòøã›{I÷í8SSSïù¹^nË×`0››KÆÍ‚Ƭ¬,t:ùùù¦×ŒØÛÛ—( 5 111|ÿý÷DFF2~üøR[kFnGff&G¥~ýúÕ¶±‡V«åǤvíÚ¼ÿþûØÚÚÞõ¾t:Qoš—'é¥KBй¸ˆ¨jýúе«ˆ¶Ö­+"˜Æà–³³ˆV.^,„ ½=´m+¶©_6m‚ C MImÛà½÷ 4fφÏ?/šÂ "Äï+LFìÙ#Äè_@I mmáw„è.¬ÕllŠo¯RAÆP¿¾Ž#G 7[“€ääd¶mÛÆ¢E‹èÚµ+ݺucþüù%n«Ñh°°0ºtéRmÔÔTf͚Š/¼ÀÃ?lîåT{ŒÍ½bbb*U°Ñét$&&²xñbþý÷_^{íµÛv07ŽW)Ë—/sòäIºtéR­2÷ƒ¼¼<~þùgΞ=ˤI“ |`2<È7Ìò»5 QQQüðÃ\¼x‘ñãÇ—jc”f« .^¼ÈåË—iÑ¢…Yާª£Õj‰ŽŽæ›o¾ÁÊÊŠ)S¦`îeÝWŒãJÌQËËËãØ±c,\¸­VËK/½Têö¥Ù*Z­–“'O"»5—‚ÑûÃ?˜˜ÈŒ3jô|àøøxŽ?NóæÍïi?å¶ òòòL“@"—/_&&&†'NÙö«¯¾Â××·ÈkùùùüüóÏlܸ‘öíÛ3}út7n\ê3xsuu¥cÇŽÕV¬êt:Ö­[GDD³fͺ'±šçÏ‹šÎ!öœÁÝ]D'89 ÑZuêÀ'ŸˆHªÁ~(„ ££•_-ê`»ub¸C!†-,D½ë‘#â=#jµˆ&'ízmÉÈÉ7ßk½Je¨. *•Š:ŸŸ_鯝^¯çäÉ“LŸ>ƒÁÀرcéÚµk©Ç;y#ëÔ©ÃÀÂÀjFnn.ß~û-AAAôïßßÜË©ØÚÚÒ·o_rrr*]¼hµZ6mÚÄÏ?ÿL@@_|ñmÛ¶½­(µ°°0eÜŽæÍ›Ó£GJ=Žê€N§cöìÙ\»v©S§>pi‘ƒ¾cäò~`tlÚ´‰:0cÆ 6lXêgJ{v+ Z¶l)ÅêmÐh4üøãlß¾W_}•îÝ»›z>Ôdœúè#Z·n]ä_·n]¢¢¢ÈÊÊÂÁÁFCtttôùäZµjUÄP÷ññ!..Îd«¨Õjbbbj¤­r¿Ñëõ\¼x‘_ýkkkfΜ‰¿¿¿¹—UãIMMeâĉXZZ2wî\|}}‹ØìF[E«Õ¢R©HII!55õèµq¿8wî“'OfÀ€¼ñƸ¹¹Éò—rP.Áêââ¸qãîú—EDD°~ýz,X@ppp±÷[·nÍŸþITT!!!äååqäÈFeîóTá;vŒï¾ûŽúõëʨQ£ŠE£KãêUص  ñZn.:£GýŽõT*Es¥ÐТi¸Ý»‹ëªU"-·pšo·n¢)ÒñãâóyyðÃ0|¸¨o]±BÔ™ZXÀÂ…¢öµBœ¨:`<00sï‘E‹ѪU+ž{î¹b)ñíÛ·gíÚµdggãââBll,111¦º‘šÂ… øôÓOéÙ³'={öÄÅÅÙH ™™Éo¿ýÆË/¿Ì!Cм§T*iÛ¶-ûöíã‘GàĉØØØÜ1:%)@£Ñpøða¾ûî;6lhêÔ)©Ο?ϦM›X°`AAAÅÞoÓ¦ ÿý7111“››ËÑ£GÈiwƒN§ãܹs;vŒóçÏsúôiyä^|ñÅ&ÕÝÜlÛ¶¤¤$æÎ[bЩ}ûölܸ‘œœœœœ¸zõ*±±±´k×ÎÜK¯–ÄÅÅ1uêTFŽÉàÁƒ«u¿sqW¹’z½žØØXŽ?ÎÑ£GILLÄÉɉ€€ºtéBƒ JL8þ< ¼üòËż +W®¤yóæ2sæL}ôQ8€““S…uÉ­*DFF2eÊÞÿ}Ú¶m[æ 7;[Ô{îÚ%„ä¥K°y3<õ”€,FÁT¥¥áZZÂÈ‘¢3paìí…ˆþë/±;;Qû^^#"À/‚¯oñŽÃwÈ ÚˆÝ)))„‡‡sôèQ¶mÛV佑#G2lØ06nÜÈŒ3hÓ¦ ýõ-Z´(ÑSÑét„……1wî\^|ñEzöì)ëk±±±DEEñõ×_3{öì"ïMš4‰Ç{Œ/¿ü’o¿ýWWWÖ¬YÃÀ©{k»¤™™™DGGsòäI>ŒZ­æƒ> I“&DjdU"<<œøøxF]ÌVY³f -Z´ Q£F̘1ƒ¡C‡²oß>\\\èz»:‰‰ôôt/^ÌþýûéÒ¥ d̘1¸¹¹I±ZIäççsâÄ """1bD‘kÜÃÃ?ÿü“Þ½{³yóff̘A«V­øóÏ? -Ñ#)ƒÁ@RR111Ì™3‡>}úðÐCI±z—”Û’ÔjµìÚµ‹ùóçNÆ ñôô$..Žÿý—E‹1|øpÞzë­b)Á-Z´`òäÉ%î×ÉÉ •JÅ|ÀªU«X·n 6dâĉxßk¸° ǧŸ~ÊØ±ci×®]™oÐIIðë¯bŒËÓO‹9¥Z­H§íÒE4HÚ»WˆÂRúWU(J%ܚݩP@óæP»6Lš$Dõœ9BàzzŠÈìÆš cƈm… Ä©€{YZZòÞ{ï•ØÕ²qãÆxyyñÙgŸ±téR6lØ@·nÝ4hPyPÇÆÆ2{öl^ýuºwïnîåHî·½7jÔoooÆÏš5kˆˆˆàÉ'Ÿ¬Q×øýàìٳ̙3…BAPP£F"$${ûÊÉ%´lÙò¶×¸ƒƒ*•Š?üÐd«4nܘ—^z©Hù‡¤8‰‰‰|úé§ÔªU‹Y³fÕ(Û®:¡T*gÞãvtt,–&y+7f„  ”Jey¤¦¦2uêTž~úé—!)ÀËË‹áÇ—ºMÇŽM©c²Nç6\½z•™3grãÆ Þxã Ú´iƒ¥¥e¹'TWš6mJÓ¦MKÝÆÛÛ›7ß|½^_£îã÷ƒëׯ³jÕ*víÚÅóÏ?_d´›¤ò±´´¤ãŒE…BA`` Ÿ~úi³UîÆþ7n45Óúä“O°°°@¥RÉçà=R.Áš››ËÂ… iÞ¼9|ðÆâÉ›¸¸¸ðꫯâââÂ?üÀOûì3y£–HJÀøø Ì 6ocjš5ÑÔ—^‚åËï“-+˜Ø™qeÁðâ̽šOnn.ß|ó O<ñ *jè¯DRCHIIa̘1(•JœIMMeìØ±R¬JjÙÙÙìÚµ‹ÿý—¬¬,<<ù¤¹—"‘ÜÔj5?þø#ƒ â™gž‘c}$5–“'O²nÝ:N:E£F˜8q"UeväÈ]ÅΜ>|8C‡E«Õb0P((•J¬¬¬Ðét?~œ&MšÔh£V¯×Ë’%K¸rå žžž\½z•çž{ŽÚw*ûì3)V«U1®WåÉÎÎfýúõ¼òÊ+w%VóóaõjxûmsÉ8\²¨ÚÍŒ2@(b䞉‹‹ãï¿ÿæ›o¾‘bµŠ?ýsæ@ ‰-’J$33“ï¾ûŽk×®ñí·ßâëëkî%I$Ž^¯'&&†+VpêÔ)üq $S%5FCff&3fÌ sç΄šuD‡¤$¤`½ :„µµ5-[¶,÷g5رCÔ­úû›ûHî@ „ª?ÒÆè 4†™{15ƒ?ÿü“6mÚHC¼ qù2df‚,6iiiìß¿ŸuëÖáááÁ—_~‰“““¹—%‘T8YYY¬_¿žõë×Ó£G.\ˆ•UUï¾(‘”½^Ï… X²d çÏŸgРA & ɪH¹«Á` ??ƒÁPêvyyyæ>®ûFff&K–,áùçŸ/÷¬±¼<‘ ¼mL U¾~;!Vcs/¦òn®1Xô2÷‚ª7IIIìØ±ƒ¯¿þÚÜK‘"9vï÷i7V.z½ž%K–ð÷ßÓ¬Y3† F—.]Ê<ºL"©N$&&2qâDt:S§N¥nݺ²áŒ¤F¡ÓéHHH`éÒ¥:tˆAƒ1zôh9[µ S.ÁÇâÅ‹IMM-u»ÜÜ\s×}Á`0°sçN\\\èÚµk™?—‘§NÁùópð ŒYFÖ܉4 h\ÊL®<’u·’»F§Ó±páBúöí+딪C@ÄÆ%¹¿œ9s†þù‡™3gR¿~}s/G"¹oÓ"[µjÅSO=U£'=H\öíÛÇìÙ³éÙ³'óçÏÇã*Ge$PNÁš““ÃÕ«WINN¾ã¶-Z´¨Q]äØ¿?+V¬àÃ?,óçaýzHM…¡CáÑGÁÙÙÜGSrÚ@OÄ|Ss£FDP]JxÏ Ñ!ØØ <Ègl¹¸zõ*»víâðá䥥1oÞ`æÌ™²†OR#ILLäôéÓìß¿ŸððpÆŒ#›íIj$z½ž 6 P(xì±Ç̽I9)—`ÍÎÎæÜ¹sddd˜^»zõ*~ø!«V­ªQäV¯^Í®]»3f Í›7/“P0DêÞöíbÆjƒPm³ ¼WH8ÐÃÌkqàö3Ví€V7ÿß Häó¶Ì\¹r—N¬‚è¼ko/f›Ve²²@§QÖþQÖjQZPÈÉÉaÊ”)DEE1tèP\\\P«ÕôéÓçünHj>×®]c„ ¸¹¹Ñ¾}{žzê)|}}QÈVä’†N§cöìÙlß¾ùóçãèèhî%IÊI¹¤”^¯G¯×yM«Õ’’’bîã¨0 »wïfÓ¦MÌ;·\…Øz=lÝ ×®ÁOˆ&)Õ–$ З̽à,à‰¨c½5S)‘ `¸¹fI™‰ŠŠ"0ðÁÌ¡>~\\ª¾`MIc°lm!!®_—‚µ¢¸qãkÖ¬aÆ <ù䓼ÿþû888˜{YÉ}åüùó¼÷Þ{<ñÄ<ýôÓæ^ŽDrßX±bK—.¥G,Y²WתИER^ÌûËÎÎfË–-ôëׯˆ§#77—#GŽpæÌ|}}éÖ­•æñKNNæçŸæõ×_/w×°ÈHøé'X´ª…óÆè{()]9 ȼÑMsb@4UÚÄ!Ò” “ ëúj!4UŒ]¥ëÔ©C“&ML¯eee±}ûvhÖ¬-[¶4[ͨÁ` ""‚:uê˜ût™áØ!'G4D+ëö`ž9¨ééЬ™ø‡ªSǪ×ëY·níÚµ3]Cz½žÄÄD¶nÝŠN§£uëÖU¹Æz½žƒ2þ|4hÀ´iÓ 1÷²$UŒÌÌL¶nÝJÿþý‹82rss ãìÙ³øùùѵk×JµUî­VKnn.7ndÅŠ¼ùæ›ôìÙÓÜË’˜™Ë—/ÁÀM¯m•mÛ¶qãÆ š7oNhhhµêo¡×ëÙµkÿý7}ôíÛ·7÷’$÷€Y,NÇÖ­[Y¶l]ºt)"X§M›Æ¡C‡hÓ¦ »wïfëÖ­Lœ8±R<"jµšÙ³gÓ©S':uêTîÏ/^ ?^MÄ*À!„(íQÂ{n@¢+¯—™×iþDÔÔ^¡¸`­ hoþÿ D½k¨¥ŠŠbÞ¼yŒ=Ú$XSSSyÿý÷ÉÌ̤Q£F¬]»–nݺñÁTÚº"##i|3ü¯V«‰¥oß¾æ>]•ŽÁ‡Av6¼ùæ·'§ûÙÌÈ¿ãV®]íÍk|À¨ Øõz=ÇŽã—_~Áßßß$X#""øä“OpuuÅÙÙ™%K–ðÖ[o1dÈs/Ù„V«eÆ ,[¶ŒO>ù„*-4$æA§ÓñÏ?ÿ°råJ“óÜÈW_}ÅÑ£Giݺ5»ví2Ù*µjÕ2÷²MèõzΞ=KDD‰‰‰ÄÄÄpùòe‚‚‚øòË/ –íÆx´Z-‹-"##£ˆ`MIIáý÷ß';;›† ²víZzôèÁøñãͽä2säÈfϞ͜9s0÷r$÷H¹«B¡@¡P ÑhÈËË„Ák0ÈËË+–.leeU¬ÓÁƒY½z5‡ÂÓÓ³È{gΜaïÞ½Œ7Ž>}úÍ‹/¾È¾}ûxøá‡ïë‰0 lÛ¶ôôt>øàƒrEôz8rzô€jåÀ9uó¿=Jx/°GDW›yÀeÕ”ð~Qâz@¬y—›””ÄŠ+ø÷ß¹|ùr‘÷vîÜILL ß}÷þþþlݺ•)S¦0bĈû~CeñâÅœü°šÕ•iÓ·yOØÜüˆ°æ<6W %ÅëW¹¹.cO¬˜½†ÕÒÒ’€€ ÀÒ¥K‹¼wôèQÚµk‡¯¯/*•Š6mÚàããCXXØ}¬z½ž°°0fÏžMhh(îîîœ={///rssÉÌÌ| köôzؼY¤nn·ßV§ƒóç¡uë²í[£÷†²vÏÍ…'`ÿ~xä‘â]‹*¨þþ"•ÙœØÙÙÑ¢E T*;vì(tNEÔõ‰'žÀÅÅ€~ýú±yóf.]ºdvÁš˜˜È?üÀåË—™4iR™G”I<\\\èÒ¥ ƒØØ¢^Г'OâããCÛ¶mQ©TøúúÒ®];’ªIll,ÙÙÙ•þ{ƒƒƒ &%%¥˜`½té8ßôP[YYÑ A¶oß^ê>SRRHNNÆ­¬7†»Ä`0°ÿ~Nœ8Áœ9s¤X­Â¨ÕjâââP«+¿ùF—.]Š8DFFÒ¿“Míî›‘‘‘·ÝŸ^¯'!!¬¬¬Jµ»nܸÁ÷ßÏåË—yæ™ghܸ1¤]SÉÌÌ$>>kkë{ÚO¹îb~~~|ôÑG÷í ´Z- …Âd¬( ,--ÉÊÊ*õsùùùÄÄÄtW‚uÇŽDGGóᇚn슑gÏBÇŽ°l™Qóüó"Âq×èâÌÜÏ ü¢uYÃä’*ATTÔm€Ê¦$[E¥R•ºNƒÁ@RR‰‰‰÷]°jµZ–,Yˆ#ªTM­¤8jµš+W® ÓU­ñwc«èt:âââ*5këÚµk|õÕW2cÆ ÜÝÝÍ}ê$·‘‘All,õK3²Ê@µ°Rï$Bœœhß¾=vvveÜcYYY&CÆÒÒ­6m‚¥Káã¡Q#ðò‚¨[îBåBœ™±þ ¢ÏÑ\)‰¢‚U dFgH÷?Í6ØIÉ‚Ui—`ýˆ~†ë!÷†‹dú‚5ìÜ óW@ÌXnÐlHoRRRª…»Ó5îááAçÎïj߇¢uëÖØÜìÔããヿ¿?»wïæôéÓ<ôÐCæ>|³pù²øN×®-ROõ †*:‰Ð`k§”4iá m[ U —"‘¦ääd,--M¥•ÍôéÓ”ûëš‘‘Á§Ÿ~ʨQ£8|ø0jµš}ûöqæÌÙ¿?Û¶m£V­ZåÎWn×® ¦ÚÖ¼¼<ÂÂÂhÛ¶í}9øÓ§O³~ýzÞyç ëÖ £ô‹/à>8úˆ:Ks£¾ù/â龯fLÆÌ%÷/%8-MÌëP†˜÷¼ú*LŸ.Þ·³ƒ^C›x¸tl-…1¿x1üñØú‰m--¡®; pƒFU³…y—.]8qâ„)­æêÕ«DGGß·küÈ‘#( Z¶,ºnß¾=W®\A­VWhzšN'ü))wÞ6+ þüSïD\œÈ|¸¥ù=‘“M›Š@çÐ¡ÂØ¸ÿü#êL““…QTÚ>÷Oá覘3GXH æ]=þ8,\(^ww'+ T®Î<õ²=XXàà Ή©ÜÓÖ–LçzÜZ6Ô´©hÄTÕ°°° cÇŽìÛ·ÏôÚñãDZ¶¶®ô±ÉÉÉ|üñÇ„„„ðÌ3ϘûÔHj:tàúõë&[%77—£GÞ·ûxihµZÖ¯_ÏæÍ›™9s&£F¢S§N•–yô(¬ZUñû‹+åUVRR„Cñvœðp]°@4Ú[»¶âÖ›–|=&|’%¡×äIð÷ß¾*šÎ;sìØ±"¶Jlll•)©ˆ‹‹còäÉLœ8Qö#x@(—`5 ¬Y³†-[¶ðÊ+¯Ð»woÓ{ `Μ9|ýõ×âååUî‚ç-Z`kkË’%K¸|ù2«W¯&55•nÝ*~¨¦^¯gãÆ<þøãää8òå—âõ¯¾ì}ÉçT…¹ËÎÀÓˆ{Ò-ï)PDg^€ZÜ}„U¯)99B™kínÜ€3ॗ "BÌXÔS]ñÚÓO‹íT*h )…üé áU©Ä?/gW*€4ŠG«;wæÆ¬]»–‹/òÇàààPLPVƒ“'OÒ¶mÛb3&---iÙ²%uêÔ©Ðù“Z­tÉÉwÞ6+Kd3”¥×DzzA@ýÎÇ]p™•ƾ}"mL¯QÑøøÛoÛ¸1têŠÓþsr„ãä‡à?HJcÈèÞ2ƒ!1ä:{ÂÍêˆË–Dꂽ½¸n ŽÇoœ½jo/¢²…³ÃrrDd °¹ysñ¹Rú_˜¥RIŸ>} cÇŽœ8q‚e˖Ѽyó{®_)+ƒŒŒ &Mš„J¥âå—_¾«ÞÉí ÅÚÚš¥K—šl•ôôtºvíZék9wî¿ÿþ;ü1>>>•>O86þû¯lŽGNü»ƒðó-\(̇²Ï<#ž-%íÓÚ^yEØyo¿-žSU:!²ò\DPKÍ))Âô9w®|ÇeºtéB||<ëׯçâÅ‹üþûï899jÖu 233ùñÇiß¾=M›6•3´Ê%XX»v-ÿ÷ÿÇsÏ=W̃çèèHÇŽùè£øý÷ß¹xñâm÷H¿~ý°µ-Poööö|ùå—dgg3vìX<ÈçŸ~_F?~œ .ЬÙ#¼òŠ‚Zµ`ÈÛÔœU$¿[îy/÷N,°¡ø¨˜|`‘àL î.ϵk0q"¼ø"|úiÁSíï¿Áݾÿ^„‹® =`Ð`Þ.œOsG¤ ·¢hÊ0À„HqEÛ"1™ggg D½Bù£7æÓO?e÷îÝŒ7ƒÁÀÔ©SËÝH©,äääpäÈ:–ÐýÇ‚>}ú0lذ ý¢†¨,%gÙÙ¢ënYDhz:ìÞ-š݉³g…~4–8—D~¾0n7FÌàÁ¥GXûM¤ [Xï¼iß*•èÆV»6ƒMË2ÈÈ›&õ9¡jËڂ `îÜ¢û‰]Š ‹ÑþýÅþÑNg k.•JÔÞnÞ\aº»ÂÛÛ›Aƒ™¢ô …‚ðüóÏóÓO?ñÅ_ШQ#ÆŽ[iµä.\`ôèÑ´nÝš &ÈN‘’{¢I“&ôíÛ×Ô„­òÕW_‘‘‘Áرc9räŸþù}-í(‰øøx¦L™Â˜1c 1Ëù±²޶¤¤;o»{·ðSÇÄ”.ØŒÏ[[X¾¼lc¼´ZÑ<¯cG¸¥9? |‹ _·••p@^½ [*À»t ¾ùFÌõvq¢4,¬øvéé¢i_½z"k§àxU$&šon`—.]ŠõÈhÒ¤ &L`ûöíŒ7¥RÉW_}u_l•òpéÒ%ÞyçÜÝÝyçwª|ÿIÅQ. âúõëèt::uêdòX+•JœœœŠÔJøúúâîîNXXØmóÝ;vìX¢!ݨQ#>ûì3ÒÒÒptt4µ¯H²³ lÞ¼‡´´ÿ#,Ì… îS½jI$RÐÌÈœ8ÑÈÝ@GD­*ˆ®¼š[~.éá¢Õ Ë߯¦x‡ƒ”ae{xÀ›oB®ì¬ KžÞe„À¬‡èN|kíG- BŒ^€º·KáFˆzÌ>‹ víÚ¼ùæ›E^S*•têÔ‰&Mš““ƒ››[§ME’ššJ^^ÞmëÈ;tèPá7ûü|ñ§ß»nvÌ¿-66в%lß.¼Ò¥q劸ÄbbÄH©Òøç±ÏÜ\qé•\Óhà…„Xa`œ:%"—& ÈÍ%=EGJ’=JÒ¯gco0ûûœB½¡sgñÐëÀc}Á>† bÓ`Æ’££ðä¦B­Z¢éÓ‘#"5­0‹ÈBbû¼<u-| …8¿_~ uëšïݨQ£bE•JŰaÃèÖ­:ww÷J‹p¦¦¦2{ölyäFŒQ-®Iª6;w.±á]ãÆùüóÏIKKÃÉÉ 'cšD%¡V«Y´híÚµ£C‡f;?Û¶‰zШ¨Òkû qÏóñ;`ÏáÃ.)ñâÒ%!Z‡…É“á»ïD]hiUf×®³3´j%Ä¢NWÔ,ÉÌτ£ Ÿ~Z”Vdeï_ ×‹5ß©4R¯BxØ00–0%ö›Ÿ_tÍGŽGmHˆc–Ÿ/"Ô‹ÙXÎüç ä‰'ž(öšR©¤K—.“““ƒ»»{§Me£Õj9zô(ß~û-?ü0>úè=I‘T/Êeéäåå¡×ë±·/hhãààÀ‡~Èc=fzÍ8Ž&©,.·ppp0Íø«Hòò„·îwòY»VOçÎ! .z•vÝwzßó^î#ÀEÀQ³Z8Ê¥SymwóçÂhµ°hŒ'ž&ÆSzº(â{÷]‘cim-žbéþ .¤2-- ÄjbÖk- ¤Fy)ÃJ„x¾5 ² ` ¢€Ëˆ¨pÆÕÕŸû&VA4$hܸñm›Ý888TxSƒA|Ÿ¼s4ôÀ!ÞJ˜Y^ KK‘Æ~çm/\uBõê‰ÈhIÄÅ­#òõ-!yÙ2xçr~ü`ßL,-Á.â8×wB\,øùÙ<7V¯Ñþ˜Å‹Åyøë/á³µ-XÓÂлUS)• 1ÖŸ;Wò9jÔ† S^¹s†Ë‚R©¤víÚx{{WšXÍÍÍåË/¿$((ˆQ£FI±*¹ïm•Ê« zp„‡‡óì³Ïš-Ê”“#œŽ:ÝùÞœ‘!2B†i»}ûЍdI‘ÖØXqotp€?‘Ð;Œq&!AìÓÝ]”X\½Zô}…BD_ ›• ˆzÓŠïïÌX³æÎç +KDUz¨ ‰“³³è¹pãFÑmu:áˆ46ãûö[u ÌÆÍ­òg —£­bN±šŸŸÏ’%K˜5k¯½ö#GŽ”bõ¤\w9''' 111¦¹Fä°Qœ——GRRR•™ÿe0#vÃqêÝûÍ›Çñê«¶¸ºÞûþËL"Íö\%ý¾\ÄÜÒ’HF¤ÎÖº"j?è€Lc˜!þvj½p‚p+º¹ÁË/‹§•Ñ(=}Z„‡^½ÀÝBpî½ÍZR‚³)%GF“(ˆJ7 x—åKE…ÕSR‚ÍIzz:›7oæÑG­c&%¥l5711*f›ÞÉÀhÒDxÍÓÓEçÄۡ׋z&!„KK!V«…QÒ¨të&¼Ü›6ª9ÍË'[5OŒ¸¹£ h+g¡]õWѾò YƒGÒAˆBÛîípy¼Ç;¿Y¬~àða1&ÇX)áê* ”ÌLqþÚ´Æš““ÇII0`@ñcP*…øÓOBûûÃíJã‚‚”ìÛç‰Zý`‹3ãÜI ž{î9s/GR¤§Ãµk(ããQ–¥à"%%…ùóçóüóÏãZ©FLQââDGÞÐPq/­ALŒÈ2±ýå6LÜÿŽ)ZGª×‹í~Xüìì,üâÿ]úþ™+ ¡·Ö÷Ÿ8!œ‡·úˆû÷)Ä…Ÿ+qq¢‘Tb¢ø½¥õD8vLøï ë9GGá0=¾à5µZ4y2Frûöϵ€èÝÛpÿú¦Tsòòòøì³Ï8yò$Ó§O§S§Næ^’ÄL”Ë’ ÀËË‹µk×Þv@¶V«eÓ¦M$''Ó¾}{s lÔÏ?7Ê/¾€üü0Z¶ ÀÖ¶’=F¹ˆTÖÊ*U8yó_Iè›kúSê›wäŒ 8t¶®… 7[è9æÂå¿`ü{¢cAV–(yôQaY·m[p·îÒEXÚmÛÍ¥¹ì¿ÍZ,‡`ŠÎƒ5R 0N¤ð§x k½BŸS":WÍ©6•‚Á``ëÖ­øúúVØ(õë…³çNÄʼnïYÏž¥×‚ÈvÈÍFÁåË·ß.!A¤ð¶l)îq¥ÔSŸ<)ÒÉœÔÞ½Š1ÚD.?†&û¦Á;w.ŒËù·æsôÐͬîÝqûq*‘}^'¼É£;5 Ú´!.Ç•„Dq-+¬¬¨ßÄ–ì¼¢Q«¾œG)¸ì]\„€=sFV??!V£¢Ä±çå 1z+ …H{V*…!µy³ˆ8”D½zZü**UÈ7#'Nœ`×®]Œ3Æ,Ñ.Émˆ‹m¯o ¿åç‹/¶±CZNNñî7 ÂøñØ~öö¥ôÃxиpáãÇÇ××—=z˜µáLf¦([pr)¹§Oß~[Ñ+Àˆµµp,þôSÑg…N'ž7F©B!|߯†E%¡ÕŠ{­±\¤aÃ’Òo¨Ù±£h£ñçŸâ’LHvâ#ˆ&{‹ GéíÈÍQÓÂ~aKKQ«Z¸ñRX˜Èä1¦$ש#’Ô:w.že#)`ÿþý\»v‰'âëë+kV`Êõ—·µµåùçŸçøñã¼ÿþû>|˜øøxÒÓÓ¹qãçÎcÚ´iüôÓO<ùä“•>Æ $23…wîË/…GK£Ñ°wï^ºtéRù7úhÀ!®*ãù»Qó©× —ãùóÂÍ  Ëå3àÿƒ=ßîfˆòòeøg;Ô‚^=ÅkkP´…W^‡¯¿.D”ö$%×Â^@ÌaµBÔÓÞŠ0ö÷ÊAŒÜ1bÌ¢1ú”ˆY­eèR[SÉÈÈ0EWKC¯/[Ã#µZtþ½]«þÂäçÞÞ3­Ó‰K­^=a,DEÝ~Û´41*À¢£áò¡E[úΟ/RПyÍ‘“tê„øâ§§øXøú²yÛÍ €^€_$©U?jÝ|ÍÑê×gÀP.\(îÅ·²‚^½ ~ "´pÄyß>až»jg' ¨o¿”R)þ  K–ÃåvYMVV"ú#RÛ¼¼JÞÎÂ<<òP*Ëй†¢V«Y¸p!O>ùd¥¬ Q« ¾(yy"¯qçN‘Î`üb,] ãÇ ±j´Èoܳãþïÿ`åÊ‚›Ð¬YðÆbN±1þùçá›oÈùê+²7.ÿk¹¹¹Lž<™É“'3xð`Þ}÷]s/ +«‚¦q={ŠºÔÛ±o_ñÙÜþþ0aüüsÑ’΋ֶZZŠ>Ë——<ê&9YÔÅ…={­ØÐjEoƒààâŸup—cLŒˆª~ô‘ȆiÑB¬oÚ4ñúœ9"EøãŽ^¯ÎÖU«Dß[ ©Æ;wŠm“’Ä4>#*•8FÙÀüö¤¥¥±páBÞzë­ûÒÏFR½(·_§]»vL˜0ùóçóæ›oR¿~}œœœÈÉÉ!66–ÜÜ\FŒÁÿýßÿ™5çÝÈ•+Â6Þ¼.\ˆB«Õ\Òë~˜7ªAŒgiXûÌÈÆyݺâŽÿ÷ßÂ(¨St|GÓ€IDATá‚9ß̹5ýû 7ßekxö9héú;…†BÝP˜3z-”`é#ÄöÝ”<ªbôqDD÷ÖË¢¢é“+¢^6‚(´Qßjì]T(l¼ÇP´¦U ´¤@à>€ìر6,ý‹Œ^ï;MQ«Åe¶c‡hRQZÙëÿ‰HhóæÂˆÐjK~ gg ¡êå%Ò]Ï•”&Ÿ“ׯ³g‹7Þ ì "‚ £a„oWÓ=Ûž|² Ýc—.è\=Øð¯ B|^z ÐÃG¤ƒå䀛¸¹¡; oɤkß^Ø×õë‹ÆFöìïquéÎÿþ+ħB!ާwr…Bœ+++a€ýc¡¡"aÈÒÇgùù CèŸDö½¤dNž0r¤ørþò‹ˆ¦¤ˆgJçÎB¼öšøÎ¶l)zØÙ‰/y` p‹µ…E¯PõÀØ—P—áàPrûpñ=nÑÂÜg³J’››ËªU«;vl¥‹Õü|qK.ÉgàâR EJ°±‡À­üö›Hµ½•  ÷¹q¯n×®xö‰³³ð‘,\(.߯…_„Ï$4´@(ûøˆK6*J<Œ½î”zkg'%§q¨E` øüû¯èb_>>âsŸ~*}‘ä4F(Þ«Wq¸t ¥ñ`$€(/\¼x1ï¼ó޹—")'99â~a©Ð c°‚êìï*s^¡P`ooO×®]Í2(»<Äć.ˆ›~XX£G6Ïbš"¢ªyÀ =¨µB*ŠÕëÅ]80Pä Â`ø÷ß‚v|Æ;^p°È+tr*¨µ²Å ñŸˆH£•]Q—§X<†´¾4-!,ºeíÉÜ}#£ý´°kƒƒK~ðge‰Œ[Pè´de(ÈH5à`w3vûvá8yî9R ͰO.\À{É÷ô¼Ôˆôµµq}e„¸Æ_}ÆŒ!=Ç–“_Ã@'ÀŧŽ.ü5†¼y:ñõQ*…]§Nñµ)âkñ駢鑯¯HG¾Ux+"’zåŠøúÙÛ‹×úôŸ)ŒŸŒ³g ]ðä“%ÛçÆ4à[)ëýÛÑQŸdCŽ’Ù³gööö´nÝÚ¼ 1Ä—J©¼¬£GE„ÓÙYxJüý…}ï=qAõèQpà€­ÞÞ–¶§§ìì\T}<ö˜EYY„Ëll„xÕéÄ…mtðvï^|]· Õ{A^è%rá´Zm…õ$0–_Üét "k&?_tÁ½•£G Òa­­…csï^!Ô ‹³´4áO¹]iC÷îÂé§ÕŠý”0ñ…BD>}}E³¢Ó§…íÕK”h4hPp¯U(„çûï…pU*Å}¼"P*ŹX¶LÔ¨–Ô‡ ðš;v„ÁéÑæ¨±Ð)€›ê_£^]½­—†*ä©  öìÙƒ»»;¡7Ò’êAb¢1ïèÛOÉ3ƒ3°˜ñ5¤¤àâêJnÏž÷´ï]ê­ÑˆÙŠÏÜŒÆ%Üœ QÿN9eA§wÌ«W…˜ìÙ³ô0H–¾×À„t¨UæÄÀé_Eú®µµ(pv.þTP*E1Û­ØÙ•ž›tAtN@4+2r!"¥"m×H4"Ji¬Û³¦ z;ÂÍ“P´ã0Qú0BÿˆCc\º!R¥gbÔH&E#»7×e¬<„ˆÈCW 8[Ž¿e bݺu<õÔCË:ÜŸ9#ê,ûö½ý†)áIŒîŽo=?LÏaÔ('ÜÜnù#ge¾#“g<4H‰ýâôK÷ qb`¬­[WXηb|èF¥*ˆŠ¦¤±Wwx,©4vîÜI÷îÝ+¤áLT”ð:;ßyþµÁ ./kkq_¼5õõüùç›±»ùöíb\ÍÿþWà½|YˆÍÛ™,nnBümÚ$ºO›VòvƺÏ7Þ_‡Ÿ~~{‘õR˜Q£DrÁºuB0?ÿ|ÅþM~¸h ¡Ø‰‹N,??^x(Ýg“Q¾£϶©SÅÉxë-ò¢£1=Z¾Ô`Ö­[Ç÷ßÏ?üPá£÷$ˆ±Ë¦‹ df¢?zŒ³Ëâ讫Íö{Ò¨‘+§L¨(t[¶`¸G‡d¬ÿý'œÇ..Sƒ‚‚*&uL¡s,’“Eçkkq“Úª‡îzPè…õ«Po÷üŸ!¦)äõ‡ºuà oèþ(´BYW4Ù@wD¢<Š VG`d¡Ÿã³KÛÞüÙ¢W†B—6×z.B°~MÁ#‡n~Ö1ÖGMQÁjIAW_Wà_ '"-Ù QûZ˜4DTÖhNñ±‚5žŠ7npãF Þq[NDyvíþ–bQS6ndÏ×iÔ~k$í|nà~á×áÖÇK\óׯÃ'Ÿ@z:îNè?òuÀœúµòÙw ZÜtäÜ´^òò„¾p„³U+Ñ wР¢©`yy *,BmmE:n×®bÝÛ¶‰´C‡JNEaLõï/êˆæÌŽ¬Û‰t??‘º¶jUßѱäm_~YDd`¨r1 ¬_¿ž   Ýî^Ñhµ_cgÛädò±²yŒ¿þ*.ì{Íá^ºT\¬Í›Ã‹/ £ ¤è¦¤Æ£Ñh8zô(ï¿ÿþ=5ŠÔé„Nrt—mJŠhô_Z`O­÷ÔúõE?¬1c œ‡‰‰b_…K,-Åå:i’HèÐA¼UŠSô&/½$ÜÝo¿-ŒƒƒÐ{:¿ÿ­Ág…B8›5~ŸÂSö*hÒP Ù¹âD9:Šû@f¦Ƚs§8~~XùzÃÜéâ¤ß{¯†——ÇæÍ›ùûï¿™4iõêÕ3÷’,ôzq}ZX}Öåå‰kÜÁA¼—˜(Œ°'„§¨ukHL$uû16…5cì‚Ft´Q°d+¨åïOf‡h ·Í¾ j¬`Íχ?þ…ô Œù;v0cÆŒ»¯¯5„no/\/¿\ôýôtXtVîŸxûmá:ôò‚ÆÃ²À‚Ô×­ÖÐÑêßÃAæ f©–ô Ûƒ¨—펌…¹ˆ|FBny3BP£–@·¬yˆÕ7·¹U°ÚÜ\‹B ž^ Gt 6ƒ3€²ÜÜï^ ðî5ÑáSˆ&MM ½ïps çosnj(kÖ¬¡AƒÞ9âaj6q;t:áñ4H³ÜÜŒ„ýûaëVÎÕ~ŸV m°mèór8ÿÙ2B\»‹\'WWÑ6±NvþlC€ññö¦q?8’ZQ*mÄXUØ[ßµ«HXXµ žx¢À(JKÍ7 Ö!C„Ð6¾æí- ©¢Í‘nÅÂBˆÏôtaÀÜ.-·ppé½÷„'ýv· •JŽ$0ñññ,_¾œ¹sçÞÿ~z½x0Ÿ=+"—jµè6óË/b|×Ë/‹/ÏC‰ ¥,‹äç‹gJB‚ðÔ‹ ÛÍMÔqûúV)oHX˜øšqôçÇÿý‡‡‡wvD–Fb¢ð¹¼þº¸g-_.Æ€n0w+«W‹ ¥þýE4óÊ•‚àk× Ê  S»6|õ•°¿.\‘ν{K¿7ƒ¸ä/_Ù0eE¥*9}¸0Å›4•›ìlq³²„ج™¸üþ»È‹Öéàý÷Åâ##EÈ´iEÓcìíK®‘˜øûï¿Ù¶m_~ù%>·6™Ü_öìÿRS…'«Ka€ýõ=ŠÚÎ…ÈÁc‰Ît… I¼àƒ²ßótpô¢¾¬8×ï䥃K ð²Gó„yøùç%w÷./5v Ñµkâ9(¼ñÿþû/!!!wï±9zT„]ÆŽwí’ȱƒ$ð îÒFàïþB _G„à¼~C¤ïÞŠh„h\TXNÑ4[ p¶—°”‘h è¬X[ĬÓÛÕ°&ío¾¿¯„÷÷ Òtm€VZ?Dc'3ÑM˜›Ÿ»õA—ƒ£Dµ¤uõ¿¹ŸrØŽÕ™¤¤$¶oßN«V²xñ·é´îî"Ptö,⎒œ,Šäo>”µ“¿¢I?á½V*ñíׄmMß!±îÍæ(ÖÖ€ÆÂ†¨¨¢ j×_É“‹ŽŠQ*…è,„²²ö‹… #¼ò3cm]TÀzy‰ oBÂ'.9:ŠõÏ>{çsÔ¤‰ˆ*tî\ùOIéìØ±ƒ¦M›Þÿ16z½ð¢Ì˜Q`I'&ŠÜÅÇ+žz;`@ñ‚g#ùùâ³»w‹&z ¾oŸ.”AddÁS½ê¯BbõØ1!v¶n-y•^/ÊmF´"…ôv3…%ÅÉËËcݺu 6 Õ=zÆNœâÔ¸wwñ7½Ýh³ü|áÜkÛVd¯vè DkÎM»%&æösQœÄWÁÉI$øø”­´aذ’K5* FwN8’Þ_8Ãrs‹ßÖ¯é¢{÷Šrƒ[›{ÆÇ 1.l¨[íI†•+WÉG}tÏ3íÓÒÄ-½pð_¡#»Î+Y°þóOÑTZ•J”HìÞ-ÞÛºõÎu©NN"3öúõ² ÑrµÉϞ’¤$Ñ%ÏÍM¬Ñn;rD¨sKKQøêã#<§;vˆ3¦YY‰ÏÜc7SIÙÑjµüöÛoøûûÓç~v/¬nèõBäç›F T–ä]Š%ãz6ž9ÂyZ»¶xùr¸|™”ZwƒÁÓ›5K­±Oð C Šè³´PA~¾-'Oö'=FÏ»0>¢RRDû„M› ž'{öˆ†•!!%/³^=áˆüõ×Û—H9:Bûö餧—’~Sj¬`­][Ô¡iµZ–,Yˆ#Ê×mìÔ)1úÅË>.Ñ•7‘ªz«`µ @˜Õ¦hšny‰B¹TD‡Þ‚ÕQOj‰* Œ‚9«¹¤×T7JN£í€hÌt…¢ œ²oî¯ B„×GÔ•稦ܲ½3ð":ZÑd©p´K‰h²ôÏÍ÷“(.®m€W€y!^’BŒûŸíQ£¦&“••Exx8/½ô_}¥àùçE÷߬¬‚Y¢¤¦ kÀ‚ü|8qÜÀ­Áºë8 Fí wæwçý~E£žW®¿¹¹ÁG‰ 5}ú{!?_¤ƒ”d”88¯Û¢EbçÏ‹F½z•|<ÖÖÅgðI$ééélݺ•/¿üòþEW¯\JÐh=ß |ûí⯕eðî-œ?/¼×Ý»‹ …Âuæyy"¢+šÕwé"¶¹Ño0ˆlG_ß‚`ñ­\»&lú¤$ñ»ŒByûv‘íàã#lùÝ»…þ.LJŠøN·n-²&›5+8uZ­:7k&Žeþ|q¸‹Sò@°qãF¶mÛÆ´iÓ¨U'I¯ÎÂÂ×R)¢&‡—¬Ï ‘\‘3fŒp\”EG{xŸ}[22DtÓÁAdþîíß/"| „åž=¢ŽÜÅEd1<ú¨ð¢´k'rÓ,80QsÒªUÁÃ¥n]ñ “˜•ÇsèÐ!¦OŸ~ÇÙñÕµZx좢ėrÈqçæ ÞÉ“"jì$öí·ÂKO‡/¿dï¶/ÔsaÛ F7ÜI·WƒPŽ.Œ´à`b›r8¾çb¼ÕÆ~hMJ%x\φ¨(áˆêß¿xFœ··ÈŽ9{V›[Ã7×Lqj!D÷ Jް4·‹nä%ÕìBÖõë׌“S]zõ*ÑÛ²åÍ(Gb¢(òts³Mõîøê®PkÙ|Sjã»ïŠT¯#G MñL×ëES§Nŧ¿¿ø~}ø¡H!Ñé„mp»–°3""Dã–{ì"y@‰ˆˆÀÅÅ¯Û t¬ÂÃ…ú«„nZii¢Kw÷îÅÅÛÕ«ð÷ß"Ø»h‘ø??as[Y cÂÓSŒ,6D™íªU¢¶_?!&:v,˜Myñ¢=$ì÷ìl‘jlvlc#œôÏ?/¾£—.‰ßÕºµø~³)üüD4uÀñ³V+:oׯ/Ÿ:ˆ¾mÙ"Œ"•Jì?"BÔŽ{zŠzó£G…À½ß!9¹ôÉm5•¨¨(–/_Î×_G™•^éüû¯Èˆ-Ü I¡R­VØË¶¶âo)ÚuLœXr$ooQYµªŒ‰ÉÉâ"’àî.<œû÷Ôˆ/؃E¨Æ¸¸^"væLñeyä‘‚ïe°‡‚…ØÚŠïnçÎE ­+h~­¤b‰ŠŠbîܹ¼÷Þ{÷¿ÁýÂ(B³³…ÑÔ¾½ø¢íÛ‡æà²¢“IiÓ»¾ñ²ÉA±¿éûÚåa4¸öÇ<7/Ä¢mkÜóætíÚðÉ'ÿÏÞ}‡GQü_î.—Þ{ƒ„„„5tf¡J¬€ П 쀊òUŠ (‚‚"¡÷! „@Hï½]’ËÝíï5'‘*†$༞‡Gseowovo>3Ÿ™¡²Rþ-8eAFÜ3Ë‹|yý•^”($Ú%‚ƒƒ†dc/~'·xiðÅí¬õ IWËl±´”ë€]»ÊÄ—[KþïšbèÔ-°ž8!· Èeæ]ºtùkf`I’›?üPþõöð5U*yàÜK/É9¯¼rq~£„œ‚ª¼Ì™óANUÍDžéµAÑ05µ9¥÷r$äÀðaàYÎv+!Š‘ÉSn¯¾µSœ6{áO'{þ|î r*ò…u¾À| ¹7vëöçq•ñפLéÈÁc}«~rêðä ¶€‹ÎñÀNäÀ¶ãŸçìB à^à#ä@ßíÏíþý5C€ÿqqÊð¯É¼7+›[·ÖSSSÞ={˜>}:ÇŽ)ˆŽ–ç‚iÛV"z·–NáVrZã;ïÀ—_ÂÞ½”†Ž&DyV.ÿNáä$Ÿ È }£Gÿu©\®¿C¹r{ú´<9ÑàÁWNûR©äKkáÂKOÚ"Wsøðazõêõ¯S$¯¨¾ò|ƒåæÊA^žü[$·|K’DìÞ-78µn-GÊ“[œ<)÷pZXÈAj}P÷Úkr[ë©Sòߟ.ÿÚÛËÛLM•;”î¾[îI-,”cC‡ä×L˜ §ã[ZÊÿ­¨÷ñóÏå¿ëg ‘ ÌL9,3S^RêÞ{åë_¥’ƒèÏ?—¡{âîÝåXÅÌL¾w<óŒ8ÛØÈÛT*å÷ ò±¾÷ž-¸_¿Kï»­­üïã/~®¤D>®Ó§åžØ©SŽtr‚”'\KL”{wßÿ¯ø¢M¹×øÜ9øè#¹“bÒ$9°U©äÜ÷Þ“²,°ÁÕõ漤¥¥qæÌ¦NÚð‰ú.P€~¿`*:õ剗]P*åFÆÈH¸ÿ~9˦>Û¥¨Hî9ÿ{rü÷ôÓrNr2„¶Õs{—¬\¬Ai'!ëÖÉÿ5L5f³Í›pøùg9B~â ¹+]’ä‚áê*÷rÖç¦.ÿ»••\»J¥XGéôå—_bkkËô¿/™˜(§_´oÁÁÌ-Ù¹SÎúpw—ËóäÉ—îÑ+,”³h5ùÞUX(g5Èüªª’o8öö`fFõï{8z¸;¥–À»C±î$¿æ­· ¸˜l¥/«]gqð¤-è\ïË™ÓNL}OO{äøáƒ(*’ÇïÿþƒœmÖex;ƾÔΔ+O6Y^.ו֬‘—ºp*†Q£ä×|¹Õ‡&—ZýÀÃã¯þ6¸xÂú[Ñ-°Ë•__8vìN´Y»VÎk´±‘Kü‚r³í?›”‹ø‹â{è8²=DGÓzç7,q\@D‘#m6V˳ê^еµ<Ö©¾µ®ªêòcM/Ô¬K·Þyç-[¶T]uŸnvz½žo¾ù†;î¸CN®«“»Ë”»Ä_|Q®¹CNRF&~)& À…¹ãÓ±ÉLdø³Á|ô?ÿlÏ+¯€Ei§6¤qÀJgVrðyà€|Ò½¼ð<?? ]ãWÊK¹lÒÈ]¬=zȶ®N.pŽŽÿì×Oþ✜þú¢ÌÍåV A¸ƒÁÀž={ˆ‹‹cÁË/ËÚ‘#rCǘ1òM¡¼/F %güsüþ›‘áe´m§dï%›7Z0ùA%6zӺץUj>úDCŸ>ÐγëÚbÞ_hä³EþÌy^‰&ë¼Üho4B¿~TOžJv‰/t¡Ò܉®]áÛ%–„ô„ÛYà:éQªªÍxýW~À†'çN§A¯† ‘û¬JøûË ‚·Ý&7ö_ª¿+<\Îò}óMy8ŧŸ^<†T­–Óqá¯ÿ ¹åÖÚZ¹Ü+u|ÿý÷L­«Cñ×l—›êêZ¬Æ"¯5êÀ_=šðWŠj½NÈi¯·#÷.^ð¼y\i9rx¡"äÒäñ«9È)½Ý‘Àßh8Q‘ òÒ1!p4œè¨~ÌWÉ Ûƒw®p”Çàä^ã¿÷ :ϯüù·ëe¶3øÏã¿sà%®¼üÏM:ì¡1èõzŽìÞÍìš \;_æÁ#¾€uÌ>ùˆQç}Y·Nîqé×ﯺƑ#òØ„Ëqt”ëF¿þ*W¤/·Š“ 4­VË–-[xê©§n܇HìØÎ $ª®®®rÆü¥²ƒ å†ÑåXÂÆFr#÷fîÚ%©³fýµÞð•ÖóU(ä^€Æœ´¢m[9C3'GÞŸ÷ßo¼m÷é#ßWll®ü:gg9 ôJ4y_Až6âï,,Œ˜›¹ÕíØ±ƒÔ”^›7OžP,=]î† ‘gB©ïféÜ:w&?’~³em‹káD æß®bfÛN|ç9‡Ï>ëm‡HM7ãö»5P$°š¹aÆ`+ï¦ãŽñWæ™|ò®…S¯¾µAþ¡£‡³øÃùäóÏñMJ‚Í›å2]ŸêáêjZ+3Þ|>z[‡Í¢áh !j5<Îsϵeîíñ´Ù± £_Ä݉Ãm1xw)äåñj@¢&ðÍ7ÎÜ;Ò «×RçâEZ¶šï?Ú&-hOD„ÜX^.wð.YªB« Âݦ=wñ¤C“&É ‘~~ò0 OOù:¼ÚÜžžòP áú´¸€U’$´Z-UUUh4lmmÿÑlGÊ…¬¬JKKé0r¤œ?ðoå"9‰¼tÍWÈËÉ8"÷’îAN­×¹×59`ëÇÅ“=‰œFürÐZ_1ÚŽÜk¨@ìZßüù¼'rwáò2*äñ§_#’wòW*ò…BÙÈ“2]®¢‚œö{%ÞÀDä^ÔLä%oþÎ 9`­æÒ=¬ ý“®òY·`&˜Ñh¤¼¼œºº:¬¬¬°²²º®ÇcÇŽa.I JFĽìq”{dþLiìë%7z¯^-OØòôÓòß¹¹WŸÓÜ\{&×Ã`0PZZŠ$IØØØ Ñh®;×h4Á` ÕŸc®ÿ­ºº‹ÇèHF#Õ§Sùº`Qûåúx»vr¯©··<‘$ÉõªÂB9˜½÷^ùu¶¶r¯è]wɽ™ƒË7÷Z£&È#`:wþ+pn b&o¹®RUU…V«Å›랹º¼¼œ­}Ä,¥Õ÷?pæ¶é”•øã÷uUj•@[׿ʫÁ §HŸ ŠÎA0oTWc­ØÞþ¯Ï´³“âBCåÀµºúò=*ÕµeŸ §Å¬ñññ¬X±‚¤¤$<<}:n×19s†eË–1oÞ¼½Ä‡^/gœ?/÷„Ž/Oz j¥‚¢Gsçs¡<>LNÏ*/—Ót­¬äœ«õ(‚ÜfÙB†)8;Ëj£G߸5Zÿ«Nž<ÉÊ•+9{ö,žžž<øàƒôìÙó¯ ¯QMM ï¿ý6Ÿ;G§^ jôý|ó h†‡:¼Žµ›Û_kËWUÉëë¯_°!…Â4— 9.C?…ë¥×ëÙ·o+W®¤¸¸˜ÐÐP|ðAÚµkw]Û3¦§“sÿý„އëèÑ|ôØÛ«ÉΖg÷ô”ÇÂûúÊåûàÁ†ãî±²2•osä1›#GÚpâ„ ß}Ÿ|rÁü´¦Y[Ë3炤–—_}š‘’Ûµ¨€µ²²’×^{   >øàöîÝËÛo¿ÍÇLÈ5LK®ÕBIAv§6á¹?C^ûÅJT q­{2i8È*­~FèF!§äÖŸ¡M@ýºsàäܱÈéµ4œüÇìÏ×·¾…Ë.ê†<ÑÑoÀwÈ“)…Ð0ÍV…Øöûs͹tJo}Zrß&úÂT\y¼«p‘¤¤$Þ|óM&L˜@ÿþýùæ›oxýõ×Y¹r%–×RË•$¤²2J–/gpr2½æÍäÌ‚ y¿F#ß|»t‘[mlÄŠÂ!IüñË—/gæÌ™xxx°hÑ">ÿüs^|ñEÌÿa—c~~> ,`Ò¤ItèÐášÞSW'g€\Y±±‘[Êu:yÜejª<¹Xh¨ŒFEÁ† л·½gvcÀMdgwùuMo*•͆ß-Lë{ÚØÈeº¤DPSRä™ncb`î܆kÿƒƒ<çF÷î×6™£FÓ¨sê M¬E¬QQQÔÕÕñè£Ò¶m[|||ˆŒŒd÷îÝ×°š™ÁœÖ?c÷á*Zõz ç]îr@8yy˜8äI|“‘CäžÕÈAæ"äÓO‘DGäàп–gQ O:4 ¹gtroêßV͑ӆ‘{h/ǘ‚Üc{yb£¿¤fȽ¾_å$¨¸|º¯Ðìvî܉ãÇÇÎÎŽ‡~˜™3gCïK-xúw55Ô=÷ ‡ÓaÉ7TÖºõ‡<i¿~WDÍÌ®|ó„Ë`0°uëVz÷îÍð?g2e ‹-"55õUæsrrxï½÷èÒ¥ C† ¹jºe} Yd¤´&%É)¼“'Ã’%òDjµ<ûì…cEþóŠŠŽß»E´”ÞÞ[ÉáÇ1<òÈ#âååÅŽ;سgÏ5—qcu5ëÖ±wÓ&›?ƒ__}$×h×®áÒ––rc£HAšÊŽ;ðõõeüøñØØØðÈ#0kÖ,bbbèÕ«×5o§fï^>ùí7pp`ÈìÙüðƒû÷ÃâÅ ×Yvt„™3ÿúûZGò™™‰•þ+ZTÀš€››¾¾¾h4:wîÌñãǯéýJeŠ?ì±hûNýä^I'þêùìƒ<{îÝÀ.`ÉŸÏ Dfßå¯gßA2·Ç‘Çlþ=l‹¸Ö7ü_®>åÇå—f¹@­}-ÅŠqW»cÆõ…i)JKK133ÃîfNž>žš?—gi)òóóéÑ£GƒºŠ­­-ÙÙÙW<–ØØX,--Ùþæ6ïè…{ÿ± ¼CIee.ææ¹<ô<<ã_Þfo(½^Ï®]»èܹóM_Æ322ÈÊÊ¢gÏk™œæÆÐjµœ8qÂÔÀw½nЍÈ`0\ö9¥RIhh(ÑÑÑ( ZuoEAi¥ÿ z,ÿó_nó§ÑhÄËË‹óçÏ_ÿLl-„R©Äh4röìÙfù|I’(((ÀÜܜ֮ÌÜB]©ŒÛÙÙѶm[âããñðð o_5pžœœkß~KbeeÕlå¢1ùùù‘••ÕlתÁ` ''__ßbK$IÒƒjOOOIHHÀÖ¶5O?V¯"YiÄ©(I²Å¼›’{78aa¡Š§H~ó+•eTäAEžüÇ… Uõå­U+ùÈ ”–•Éÿ_߀r…ÊØµrvv¦ººú–(ãmÛ¶möãHII!<<¼¹OÅ5¹Ò}ÜÜÜWWWN:…g?gžé§C^ÛN¦ÓýUL[:___ŠŠŠ(¹ZI¯¢¹Ë¸N§#''‡7É ä+•qWWWôz=‰‰‰N¶cÞCÕÈk.ÊêênŽÆuI’ðòòº%ʸÁ`ÀÖÖ¶YËxyy9555„††þ«í´¨€U¡P I’$™þßh4^±2¦P(ˆˆˆ ""¢¹w_®ÊÌ̬A7H’tÅÔi¥RÉÈ+-œ*-Hý½»žÁ`@­Vcu…0µZÍ£>z•-_}Ah ×SW±´´ä‰'žhî]„kr=u•V­ZñäŸk¨ BckQ%Û¶mKee¥)uL§Ó‘˜˜H@@@sïš 4ŠÐÐP²³³Ñéäi£ ÈÍÍe\¸%( BBBHII1=vöìYT*Õu/k#-Mpp0¦Þ—ÚÚZΜ9#îãÂ-#44”¬¬,êêêÈËË#??ÿæÞ5á?ªE¬]»v¥¨¨ˆ¸¸8êêêÈÏÏçøñãÜvÛmͽk‚Ð(zõêEll,¹¹¹èt:ÈÎΦ_¿~ÿ~ã‚ÐÌ”J%½zõbÏž=TVVRSSÃþýûqpph¶ñì‚ÐØºwïN~~>ñññÔÕÕ‘——GLLŒ¨«·Œ^½zC^^ž©®’——GŸ>}š{ׄÿ(…taîV P¿¦Y=䱞ž¼òÊ+ÿzÁxAh ÊÊÊxõÕW)**¢mÛ¶DEE1`ÀæÎÛÜ»&âüùó¼üòË888`ggGLL O?ý4#FŒhî]„FóÞ{ï±ÿ~"""HHHÀÇÇÇTîáfWZZÊ«¯¾JII AAA9r„Áƒ3{öìæÞ5á?ªÅ¬Z­–£GròäI‚‚‚èÙ³'vvv7ý$D‚ò`þòòrvíÚEff&=zô ,,ìŠãûáf"I999ìØ±ƒššúôéCPP¼4 Ü"´Z-ÑÑÑÄÅÅѶm[zôè!ê*Â-C’$ÊÊÊØµk—i–ÙÐÐPQWšM‹ XAAAZØVAAAA¨'VAAA¡E« ‚ ‚ ‚Ð"©š{nU’$a0Ðëõ˜™™¡R©033kð¼^¯Ç`0 T*Q©T &k$‰ºº:$I2½÷ÂçF#uuu(Š‹¶}#Ô€¹¹ùEûª×ë1(•J”Jå%÷¸èX$I2­Iz©ãZ® ˰™™jµú²eøzÊ…ÑhD¯×£P(.Úö`0¨««»ì±\©œÖ_ë—º›úZO}4¨TªU†/õP_n.õÐØ.¼^¯t,WÚWƒÁpÉëñj¿BËu#ËðÕ~Û…e\­V£T*>ž‡z+++V®\I`` >>>^ƵZ-o½õeee<üðÃÔÖÖòõ×_Ó¯_?œœœ8pà .dذaôë×Í›7“››KÏž=‘$‰•+Wòûï¿sÿý÷ãååÅwß}‡‹‹ þþþlذ¡É®U¡qmß¾?þ˜‘#G2jÔ(âââøá‡¸ûî»177ç?þà‹/¾`ôèÑtíÚ• 6PSSCçÎ1|öÙg>|˜|¾ýö[|}}iÕª:ާŸ~µZÍ#]š?¾é½›7o–F%?^š={¶4sæLÓs;vì†.>}º¹¿Bá*¾üòK顇’*++%I’¤ÊÊJiÒ¤IÒ§Ÿ~*I’$-\¸PzðÁ%­V+I’$;vL:t¨tìØ1©´´Tš2eŠ´hÑ"ÓöÖ¬Y#7NÊÊÊ’Nž<) >\Ú³géù3fHÏ?ÿ¼¤×ëýXvíÚ%ÝqÇRzzº$I’TQQ!½óÎ;Ò† LŸ=gÎÓë·mÛ&1B:s挔––&Ý}÷ÝÒÏ?ÿlz~áÂ…Ò´iÓ¤sçÎ5éµ*4®3fHï¼óŽTWW'I’$9sFºãŽ;¤]»vIZ­VzôÑG¥·ß~ÛôúŸ~úI3fŒ”šš*%&&J#FŒ¶oßnzþ…^žy橺ºZÚ¾}»t×]wIgÏž•$I’ŠŠŠ¤»ï¾[Z½zõ 9–O>ùDš4i’éïÜÜ\iÞ¼yÒáÇ¥œœiܸq >û³Ï>“¦L™"JQQQÒ°aäèèhÓó“&M2ûòåË¥{ï½W*(($I’’’’¤Áƒ7¸~…–G§ÓI”6oÞlzlçÎÒˆ#¤„„éüùóÒˆ#¤_ýÕôü[o½%=þøãREE…´gÏiذaRBB‚$I’TUU%ÝsÏ=ÒÒ¥K%I’¤?üPš2eŠTUU%I’$ÅÄÄHC† ‘Ž=ÚèÇRQQ!͘1CZ¸p¡é±¤¤$é©§ž’RSS¥˜˜iøðáÒþýûMÏOŸ>]zñÅ%I’¤uëÖI£G–²²²$I’¤ôôtéŽ;î¶nÝ*I’$=óÌ3Ò³Ï>kzïöíÛ¥áÇK‰‰‰Íû% W/õèÑÃôÛ.I’ôÕW_I“&M’ ¤C‡IÆ “Ž?.I’$ é¾ûî“>øàI’äz΄ ¤ââbI’$éÔ©SÒÀ¥C‡IÕÕÕÒ´iÓ¤7ß|Ó´íŸþY=z´”’’ÒèÇ’™™);¶ÁõºeËé…^jjj¤­[·JÆ “Ο?/I’$åååIÇ—Ö­['I’$½ôÒKÒ´iÓLïÝ·oŸtçwJqqqRnn®tß}÷I+W®4=¿téRiòäɦûzK š†n€   ^|ñEœœœÐétÔÖÖbii‰B¡ !!V­Z™ºâmllèС'Nœätâ=z˜Z5±¶¶æÌ™3TTTžžNÏž=MŸ×«W/ÒÓÓ)..nôc‰ÅÚÚšàà`rssÉÉÉaôèÑ<þøãÄÇÇfJuöðð uëÖÄÆÆ¢×ë9sæLƒ}íÔ©UUUdddÐà¹víÚaffFrrrs…ÂUôéÓ‡§žz kkkjkkÑëõ¦”Þ„„ºtébJkÕª...$$$P]]Íùóç|÷={ö$''‡¼¼<²²²¨««3¥+Ö?òäIŒFc£ËÇÚÚšììlª««yüñǹóÎ;MÇrá¾¶oߣÑHJJ ÅÅÅäää\t,çÎ#''§I¯U¡qM˜0qãÆ¡RÉ#gª««‘$ t:III ¾Û®]»RZZJvv6¹¹¹”——›Ò‡A.§OŸF§ÓqêÔ)|}}ñòòÀÚÚºÁo@cÛ¿?C‡¥¬¬Œ¬¬,ÌÍÍyþùç §¬¬ŒÌÌÌ‹ÊiZZ%%%œ? Ú¶mÛàùú}'44ÔÔ3ìîîN@@±±±Íý W T*™;w.½zõä­V‹J¥ÂÜÜœÂÂB L=” —ᤤ$´Z-gΜÁÅÅÅ”>lnnN—.]Ôc:wîlJ)ôóóÃÍÍøøøF?–²²2âãã4hÅÅÅdeeáææÆo¼——H’DXX˜é=–á„„‚‚‚pvvÀÉɉàààÏ_x}„……¡P(8þ|sÂxzzòꫯšêÚuuuÔÔÔ`aaR©$99SНB¡ G îmíÛ·ÇÆÆ///ZµjuÙúmçΩ¨¨ 33³Ñåܹs”——Ó½{w ÈÎΦo߾̛7ssshݺ5ØÙÙѾ}ûË–á   ,--IJJºl\‘––Ö¢ê*b ë àíí··7UUUDFFÍÙ³g™;w.jµš¬¬,¬­­M•{ ¼¼¼Ø·o rvv6¬nnn˜››“Mhh(EEE¦ñsRYYÙèÇ’••EYY«W¯fïÞ½ ÌäÉ“MÏûûû›R¿ìííqqq!%%£ÑHNNNƒ}õõõ¥¦¦†¢¢"233ú(ŽŽŽdeeaccsQ\qøðaàâ2ìîîŽZ­&''‡   Kþ´¨ºŠèa½ôz=999RQQAaaá{ˆôzýeŸ“þœÉìrŒFã é}ÈÉÉ¡  €>úˆW_}•mÛ¶ñùçŸ_õد´¯—;–«§Ð²èt:²²²L7¶«Ý¨¯ôÝ †+–áY.bbbðõõ嫯¾bìØ±¬X±‚­[·^öõW*Ãõûz¹àúF^«Bã«N‹ŠŠ(++£¼¼ü²¯½Úw{µ2|¥ûæ¿õûï¿sÏ=÷°lÙ2:tèÀG}Äñãǯx,Wj ªŸ³9ŽEh<’$QXXHaa!¥¥¥£Õj/ûú+ÝÛàêßû¼ïÛ·iÓ¦±xñblmm™?þ{»®¶¯ÿ¦N&´õÁå…uñ+}·ÿ¦\\­nðoTUU‘˜˜È«¯¾ÊÛo¿Mbb"ï½÷žiö꺯×W܈N‚ë%ÖÈÞޞǜE‹1lØ0>ýôSjjj.ûúú–ÊK1333µœ\ŠF£1¥®56žyæüýýéÖ­S¦La÷îÝW|Ï•ŽE­V_væ1¥RyÅãZwww^yåÓD\Ë–-»ìk …©GéR4Í'i¹Ò{ÿ­ž={2eʼ½½5jýúõc×®]—}½J¥ºâL¿õ)G—;Îu­ ¯sçÎÌŸ?Ÿ>úˆââbSëû¥\éÞ˜†…\N}êÙpï½÷r×]wáëëËôéÓ±µµ%&&沯¿Z9½Ú¾^é7@h9T*wÞy'ï¼óo½õüñÑÑÑ—}½……Å'”¹R¹¸ÚoÀ¿õÄOЧO‚‚‚˜;w.IIIdee]öõW+£Wzþj¿BËammÍý÷ßÏÇÌc=Æ_|ANNÎe_ÿoîmWû ø7lll˜={6aaa„‡‡3mÚ48pÅÆÃ«ÅW*Ã-­®"ÖF&I[·nåË/¿4=fnnNïÞ½Mé`ÁÁÁ”””˜ZêµZ-ÉÉÉ´iÓ€àà`Ó˜ €ŒŒ ´Z-ÞÞÞX[[ãííÝ ­&..WWWSZCcruuÅÁÁ¡Aj›§§'z½žªª*ÓØÖú@¼°°ììlP*•´iÓ¦Á¾ž9sFƒ‹‹ ÁÁÁ ž«O³¨ÏÁZ¦šš¾þúk¶mÛfzÌÞÞžÎ;›R¨‚ƒƒÉÊÊ2µîåääPZZŠŸŸøùù]T†qppÀÓÓKKË?(qqqøûûßÙê¼½½qvv65”¨Õj¼¼¼(//§¶¶–¶mÛ6Ø×ú1Öîîî8::âææFZZZƒ}õôôÄÅÅ¥I¯U¡ñ”••™RÄëàççGJJ jµÚ”6YïôéÓX[[ãää„››vvv *Ëqqqøùù¡R©hÛ¶-eee”••rJã¹sç¸!Çãííéo+++\]])..ÆÚÚOOϋʩ»»;ÖÖÖøùù˜RƒëŸ¯ß×àà`òòòL¿EEEdeeݰcGNN¯¿þ:ÙÙÙ€\yíÚµ+’$QPP€““...• ooo4 TWWSRRÈ=‰ ÊEvv¶é7 77—ââbÓ˜×ÆT_§¸°ŒÛÛÛcccCII ÞÞÞ˜››7nô÷2\XXHUU _ÿiii êdž‡óçÏc4E]¥…;tèï¿ÿ¾) S«ÕôíÛ—¼¼<´Z-­ZµÂ`0PXXÈõ÷øøø‹îmµµµ€|ÌÉÉ! •JE@@@ƒr‘˜˜ˆ¥¥¥i,tcrppÀÞÞ¾A™sssÃÌÌŒŠŠ ‚ƒƒ)..¦¢¢{cÿW\¸¯éééÔÔÔàíí ^^^]ënnn7´õŸë PUUņ (((0-¶~ôèQÚ´iƒJ¥¢[·n¤¥¥‘‘‘Ñh¤´´”¸¸8z÷î @÷îÝ9tèuuuFNŸ>MMM ááá888жm[öïßoÚöþýû 2­7Ö˜©ªª"..δ¸òþýûñððÀÚÚšîÝ»“@ii)F£‘ÌÌLRSSéÝ»7*•ŠÎ;sàÀçÁÁÁ6mÚÁÁƒM‹uÇÅÅaffFhhhs…¨T*233Ù´iååå¦ñzqqqr>vìÕÕÕFÎ;GQQݺuÃÚÚš°°°eøÀ´jÕ °´´$&&Æ´HöÁƒéÕ«W£/‡NBB¹¹¹FŠŠŠ8zô(AAAh4S9­OYŽE£Ñ‚››­ZµºèzìС­ZµjÒkUh<;vŒ;vP[[‹Ñh$++‹¬¬,‚ƒƒ177'<<¼Á½-** WWWüýýñõõÅÙÙ™#GŽ˜ÊðèÖ­tíÚ•ŒŒ ÒÓÓ1”••qòäIÓo@c g÷îݦEåÏŸ?oª»¸¸xQ9 ÆÅÅÅ´Û©S§\õc|»wïΩS§(..6§óçÏ›žZ&+++~ýõWbbbLß{BB*• OOO<==ñõõåÀ¦4Çú êlmméÔ©………$''›~Ž;Ö süøqªªª0$''SPP@÷îÝýXlllhÓ¦ »ví2•ñ'N ×ëñòò"00•JEllìeËpRRyyy¦ù Μ9c:–¿ÿœÌ¯¿þÊôéÓ ÇÎεZÍÒ¥KÉËËcãÆäääðÔSOááᇇ§OŸæ§Ÿ~2ýøøøðÀÜ4ÃÖ­[óóÏ?³cÇâããùúë¯ åá‡6M$òÕW_‘––ÆöíÛ9rä3gÎ$ gggŠ‹‹YµjEEE¬Zµ µZÍôéÓ±··ÇÓÓ“¨¨(¶mÛFvv6+V¬ k×®Ü{ï½bÊÌÜÜœêêjþ÷¿ÿ‘––ÆX¹r% `ܸq888`ggÇ’%KÈÉÉá—_~áìٳ̘1ÜÜÜHMMeíÚµ”––²bÅ œyøá‡M½öûöíc÷îݤ¥¥±bÅ ÈÈ‘#ýX,--qsscéÒ¥œ8q‚ƒ²|ùrxàˆ««+ÕÕÕ|óÍ7ðý÷ßSSSÃO<££#œ8q‚-[¶››ËòåË c„ ¦~ëÖ­DGGsòäIÖ¯_ÏøñãéÛ·osÂØØØÍ²eËHMMeûöílܸ‘iÓ¦››yyy¬^½šââbV®\‰¥¥%Ó¦MÃÖÖOOO:Ddd$¬X±‚ž={2nÜ8”J%üøãÄÅÅÅæÍ›™:u*;wnôcqqqÁ`0°hÑ"’““ùý÷ßÙ¹s'³fÍ"$$OOOâããÙ´i¬X±&OžŒF£ÁÓÓ“ÈÈH:ÄéÓ§Y³f £F2­5ìììÌÿþ÷?RRRˆŒŒäàÁƒ<óÌ3¦Ú–@!µ¤µ·ììlvíÚŹsçppp`àÀ´k×Î4F¯¨¨ˆÈÈH eàÀ¸¹¹¡P($‰ŒŒ 6nÜHII ýû÷'""ÂÔ5o4‰ŠŠb÷îݨÕjú÷ïO—.]nHï@ee%GŽaÿþýØÛÛ3räHZµj…J¥B’$òòòزe iiiDDDлwoQ(FÙºu+uuuôë×îÝ»£Ñh0¤¦¦²iÓ&*++éׯ7tŒ‹ÐxN:Å¡C‡HKKÃÏÏ!C†àëë‹R©D’$²³³Ù´i¹¹¹¦2\?Ó¨ÑhäĉDFF¢P(èÛ·/¦2\SSÃîÝ»M½V·ß~;þþþ7¤\ŸW?ƒ``` ƒÆËËËT†“““ùå—_ÐjµôïߟîÝ»›Rˆ ûöíãàÁƒX[[3pà@Ú·o™™Y“_«Bã©««3U~‹ŠŠèÔ©½{÷6¥dFضmz½Þto«Ÿ-W§Ó±gÏŽ9‚££#ƒ¦mÛ¶¦2\\\Ldd$ñññ´k׎Aƒ™~[}ïÀüAVV]ºt¡_¿~¦™¸ GŽaïÞ½˜››3`À:uêd*§•••ìÚµ‹cÇŽáííÍwÞ‰··7fff¦ß€­[·’ššJ÷îÝéÓ§é7@h¹*++‰ŠŠ"** ½^ODD½zõ2 Y0 ìÙ³‡C‡akkË Aƒ 5•áÒÒRvîÜɉ' dèСxxx˜ê1ÙÙÙlÞ¼™œœÓ﻽½ý 9–úì—½{÷RUUEÏž=éÓ§i}š°°0ScM}ÎÌÌä§Ÿ~¢¬¬ÌT¹0®8rä{öìÁÜÜœþýûÓ¹sçUW« ‚ ‚ ‚Ð"‰|AAA¡E« ‚ ‚ ‚Ð"‰€UAAAh‘DÀ*‚ ‚ ‚ ´H"`AAAZ$° ‚ ‚ ‚ -’XAAA„I¬‚ ‚ ‚ B‹$VAAA¡E« ‚ ‚ ‚Ð"‰€UAAAh‘DÀ*‚ ‚ ‚ ´H"`AAAZ$° ‚ ‚ ‚ -’XAAA„I¬‚ ‚ ‚ B‹¤œ?þüæÞ‰ÿ2ƒÁ@bb"Ë–-ãèÑ£ØØØàââ‚™™ƒ“'O²råJâââðððàüùóXYYaaaÁ` 66–Õ«W³wï^¬­­quuÅÌÌŒ’’Μ9Cmm-Ë—/g×®]¸¸¸ T*Y»v-?ÿü3>>>”––röìYª««Y¶lÀÕÕ½^Ï÷ßÏæÍ›Q*•øøø`f&Ú8„ÆQZZÊ—_~‰‹‹ NNNͽ;‚ÐdNœ8Á¦M› ÁÜÜü_ooûöí?~œ°°°æ>4á?L’$jkkD]A¸¥I’D]]z½•JÕÜ»óŸ î(ÍÈ`0°víZFŽIbb"Ge̘1¦`ò·ß~cܸqÄÅűoß>ÆŽ˽÷ÞKll,z½žµk×2vìXNž˜››ãè舛›ƒ¡¹O™p“úé§Ÿøæ›oHMM¥]»v<ûì³øúúpüøq¾ù梣£ñööæÅ_dРA˜™™ÇÇLtt4666Üwß}<òÈ#888I\\%%%lÙ²;;;¦M›Fnn.›7o¦¬¬Œ»ï¾›ùóçS]]Í¢E‹ðõõeË–-ÄÇÇÂŒ3X³f GŽÁÕÕ•—^z‰ŠJ¾ð¯éõzÖ­[ÇòåËÉÉÉ¡cÇŽÌš5‹nݺr%hùòålܸ­VKÿþýyå•Wððð **Š%K–pìØ1œ™8q"S¦LÁÖÖ–Í›7STTD~~>?üðG޹èsW®\I~~>3gÎÄÚÚº¹O…p‹Ù»w/‹/æôéÓx{{3gÎz÷îͧŸ~Jzz:«V­ÂÍÍQ£F±zõj4 ±±±ìÙ³‡5kÖ°bÅ ZµjÅš5k(((`øðáôíÛ—%K–žžNÇŽyóÍ7 bóæÍdff’––ÆöíÛqqqá±ÇãìÙ³lݺ­VËĉyî¹çP«ÕÍ}j„[Lvv6|ð‘‘‘ØÚÚ2tèPæÎËæÍ›Ù½{7Z­–>ø€)S¦°|ùrºvíÊ?ü€““Ÿ|ò dÉ’%ÄÅÅáääĈ#˜9s&,[¶ FÃˆŠŠÂ××—'Ÿ|’ýû÷³cÇž}öY&Nœ(‚VDJp³ªªª2µ,Öóôô¤{÷î¦–Ä oÀ*•ÊT‘NOOÇh4òᇲpáB.\ÈW_}E»víL¯Q«Õ×ÜêøO^+ÿÄÞ½{™;w.ƒ bݺu„„„˜zî~øáî¹çÖ­[GPP .¤  €ììlž}öY$Iâ»ï¾ã…^àË/¿dÉ’%ÄÇÇóÞ{ïáààÀºuëèØ±#O?ý4ÙÙÙ|úé§L:•5kÖEuu5[·neÙ²eL:•%K–pöìYžyæúôéêU«pppà“O>¡¢¢¢¹O™p غu+¯¼ò cÇŽeíÚµ¸¸¸ðøãSVV@\\III,[¶Œ÷ߟÈÈH6mÚDzz:Ï<ó –––üøã<ùä“|øá‡¬\¹xÞzë-ÒÒÒxþùçÜ·kjjX¼x1ß~û-ýû÷75v Bc‰‰‰aÖ¬Yñý÷ß3zôhž~úi˜8q" >œ>}ú°ÿ~^}õUjjj˜3g¬^½š;w²páB^~ùe–-[Æ»ï¾Ë /¼ÀW_}ʼn'”÷·ß~›ÀÀ@6lØ€··7O>ù$Z­–Ï>ûŒ‰'²|ùrbcc›ûÔ·˜²²2æÎËéÓ§Yºt)/¾ø"¿þú+_|ñ  [·n1eÊŒF#¿þú+ï¾û.mÚ´aÒ¤ITWW3{öl\]]Y»v->ø Ë—/çðáÃìÚµ‹ 0|øpV¯^Á``ÆŒ899ñõ×_3pà@>þøcRRRšûT´¢‡µÙØØPXXˆV«5=–ÀÎ;1b:Ngz®ººÚÔËéïï‹‹ [¶l1UXª««9pàþþþb\ Ð"èt:V®\É Aƒxê©§°´´äÙgŸåüùó¦L€1cÆpÏ=÷0iÒ$fÍšEuu5»ví¢¨¨ˆï¾ûÂÃÃIOOgÉ’%¼üòË´k׎|wwwî»ï>>ÿüsfÏžŸŸÎÎÎ|ÿý÷”––šögܸqÜ~ûí„……¡×ë™0a–––ÜsÏ=|ùå—èõúæ>mÂM®¶¶–o¿ý–‘#GòðãÑh˜3g¹¹¹¦òèîîÎÌ™3騱#ôèу¬¬,~þùgÌÌÌX°`®®®sîÜ9¾ýö[f̘€o¾ù&¦Ï4 ¬X±‚ÿýï,^¼Ø0Bc1 lÚ´ www^zé%lmm騱#QQQ”––†……žžž¦L-GGG.\ˆ……‡ÆÚÚšiӦѭ[7ºuëÆ¬Y³5j À`0pÛm·QTTdzxx8“'OÆÎÎŽ±cDz~ýzæÌ™ƒ³³3666üøã¦JAh,)))ìÚµ‹_~ù…®]»PTTÄÙ³g±µµÅÁÁŠŠ üüüÈÌÌ _¿~¼òÊ+(•JÊËˉ‰‰aîܹtèÐÀÀ@üýýñöö6}Fÿþý7nC† !33“'Ÿ|;;; Û¶mk´¹nv"`mFAAAøøø°víZ{ì1ôz=Ÿ|ò •••LŸ>ž={òõ×_ˆN§cýúõ¦ÖùúB¿xñb&NœÀÒ¥K‰ŽŽfÕªUÍ}h‚Èã´ÓÒÒ˜8q¢©·ÇÙÙ™¯¿þšüü|"""L¯¯Ï(0$''S^^ÎK/½dz>''Ç4æäŒ++«ŸéììlÚÖßgï hð·µµµi¿Do”ÐXJJJÈËËcìØ±h4@ž‘}ÅŠh4¢££ñõõÅËË …BJ¥B¯×“””Dqq1/¼ð‚i{ééé˜Ê}xxxƒqà¿ÿþ;gΜ¡¢¢…BÑܧ@¸ÕÖÖrþüyºvíÚ`<öÒ¥KQ*•äåå]ò}={öl  Ñhðññiðggg  …KKKjjjLÏùúú^”VŸ×h4"]R¸!RRRðòòÂÏÏÏôØÄ‰Ñëõ—-s}úô1=gaaÁÔ©Syíµ×X±b}úô¡ÿþ ¶×¦M›ï¯£ `ee%îåk3²¶¶fîܹ¼øâ‹DFF"I%%%¦JÍœ9s˜9s&÷Ýw*• °²²ÂÛÛ›^x§žzŠ7••ÅÒ¥KÅ!B‹Q?9Ì…£B¡ÀÊÊÊôØ¥nü’$¡×ëñôô¤_¿~ ž›4i’$ÿ|é16Uh õåó²mffÖ q¥¾rþ÷÷éõzüüü.*÷VVV¦íZZZ^T–}}}Y´h .äý÷ß'""BŒ_Õ¥îçpõƾKU¼ÿIE\TÚ…æ`4/ªŸÔÕ«««»ä{.¼çš››óî»ïrâÄ öïßÏž={Xºt) .düøñ€(Ûÿ„X›‘™™÷Üs `ß¾}h4zö쉣£# § ÿüóÏ=z///Š‹‹yë­·ðòòÂÌÌŒ#FУGöïßR©¤_¿~8::¢P(¸ãŽ;:t¨éb377G§Ó™þ¶¶¶æÛo¿ä fäÈ‘¦ç.œÅäô³üQ\XÂ?fkkK«V­Ø³g&L@£Ñ͈#Lé—¢T* cÿþýŒ9ÒÔš¾aÃbccźgB‹æàà€››dÔ¨Q˜››“””Ę1cX±bÅeß§V«éر#çÏŸgôèÑ888`4Y½z5)))W,÷;v¤{÷î¼öÚkL™2…¯¿þš'Ÿ|R\+B£Ñh4pèÐ!´Z-VVVèõz Äĉ1bDsï¢ 4ÒÒÒÈÎÎÆÕÕ£ÑÈ_|Áo¿ýfc}%ÉÉɼñÆÌŸ?Ÿÿû¿ÿcΜ9<û쳬Y³Æ° ×Nt743…B‹‹ cÆŒaذa899™ÃO?ý”¯¾úŠaÆѶm[~üñGZ·nmZÆ@¡PàææÆ=÷ÜèQ£¼×ÌÌ •Jeú[¡P V«M­ò …¥R‰R©¼ìk/ü»þu‚ðOh4¦L™Bdd$|ð{÷îå½÷ÞÃÌÌŒvíÚ]ñ½ƒF¯×3oÞ<öìÙÆ L㦡%³´´dÒ¤IlÚ´‰%K–°gÏ.\ˆÝE)`7räHrrrxñÅ9pàkÖ¬áõ×_75d^‰B¡ 44”x€/¾ø‚ôôôæ>Â-D¥R1räH233yýõ×Ù³gï¿ÿ>………tïÞÝ´$SQQQƒ¹áf@Ïž=yíµ×øõ×_Y»v-Ë–-ãŽ;îÀÖÖ333*++ ׸ Û¶mcÑ¢E>|˜_ý•ÇÓ¹sçæ>´›’rþüùó›{'„K àçŸæ‹/¾`íÚµØÚÚš&â„›…¿¿?®®®üöÛoüôÓO˜››óÆoжm[´Z-¦ :t:F£‘>}úàîîN=Ø·o«W¯&&&†©S§2}útÔj5UUU8;;Ó¹sgT*:Žºº:†ŽJ¥Âh4¢ÕjéÚµ+...TVVÒ­[7ÜÝÝ(--¥M›6têÔ Çg™››_4ÞJ®G`` lÚ´‰Ÿþ'''Þ|óMüýýMk¤FDD˜Æ¸VVVÒ¦MºwïN·nÝØ³g+W®äôéÓ̘1ƒÉ“'£R©¨¬¬ÄÓÓ“Ž;š²b*++qww'<<333BBB¨¬¬ÄÊÊŠÀÀÀæ>Â-ÄËË‹6mÚ°}ûvÖ¯_OQQ¯¿þ:½{÷ÆÁÁììlÖ¯_½½=;w¦¬¬Œ€€ÚµkgZsÒh4Ò»woSúdAA}úô1í«¬¬ÄÇLJ:\TÞkkkQ(¦õæ ÕÕÕ ~G¡1XXXЫW/N:Åš5kˆeذa<óÌ3h44 ‘‘‘œ >L›6mš4`ÍÉÉáË/¿$::½^OÛ¶myê©§ ¡ªªŠ5kÖ°iÓ&ŒF#íÛ·gÖ¬Y¦{ü¥äçç“””D¿~ýší\6–àççwÅã½Yìß¿Ÿ1cÆ4ë>”——sèС&XÏœ9âE‹HNNF¥R™ê*žžžDGG³lÙ2ÒÒÒpuu塇bРA—­«ÔÖÖÏСC›õ|6†'NÐ¥KÓúØ7³–PÆsss‰ŽŽnò€522’ï¿ÿž´´4lmm1b÷ÝwvvvÔÕÕñû￳jÕ*ÊÊÊ dÚ´iWüíÎÌ̤¸¸˜ÐÐÐf=Ÿÿ–Á``Ïž=„‡‡ßôe<++‹ÜÜÜ&¿þÝÙ³g‰¿yÖââb,X€«V­2M‡þõ×_3oÞ<´Z-¯¼ò ·Ýv .d÷îݼóÎ;¸»»›–ž¸KKKBBBnú Buu5mÚ´ÁÇÇç¦ïiððð@©T6ûÅ^RRÒäçrË–-üðüÿþûòÕW_±páB‚ƒƒ)((à½÷ÞcöìÙÜvÛm|ñżôÒK¬_¿þŠ­¼¶¶¶tìØ±YÏecðññ¡®®î_Ý´Z kkk|}}›5‹ ®®Žäää&ÍȨ­­eéÒ¥¤¤¤°xñbT*ü1~ø!ï½÷[·neýúõ,X°,XÀ|ÀÛo¿}ÅV^[¢Œ;;;ckk{K,C`nnNHHH³îCqq1ÉÉÉMú™EEE¼ýöÛ´jÕŠ×^{ÂÂBæÏŸÏ7ß|Ãܹs©ªªâ¥—^bèС¼ÿþûìܹ“·ß~ûªe¸~y–›îîîMžÕq#´„2nooOeee“~fZZ .d̘1,Z´ˆ'Nðÿ÷8880nÜ8Nœ8Á{ï½Çܹséß¿?K–,á•W^áûï¿¿l]E©TâïïÓ—q£Ñˆ³³3®®®7}oݺ5ÍÞyd0(++ûWÛhÒš|ff&Œ7wwwBCCéׯgÏž¥¶¶–èèh,--?~<ŽŽŽÜqÇøùù±oß¾¦ÜÍfcii‰ŸŸßM¬¸¹¹5{°Ú\|˜êêjòóó9þ<^^^¨Õjâããqss3ÕU,,,èØ±£¨«7€€´Z-'NœÀ`0‘‘Ann.¾¾¾ÄÆÆf Ú¼¼¼ðôôu¡Ù4iJ°»»;O<ñ¯¿þ:GŽA«ÕRWWÇÂ… ±°° ¬¬ •JešØ >¥477÷ŠÛÕjµ$%%áììÜ`Rá¿Ëh4’‘‘AZZZ“§5j'Ožä™gžÁÞÞž””î¿ÿ~Ú´iCII –––¦1ÊÖÖÖØØØ\µŒ—••qúôiüýý›}ð¼Ð2ÔÕÕ‘””D~~>M¹œ¶……<òóçÏç‰'žÀÌÌŒŒŒ Þ{ï=\\\(--ÅÚÚÚôzgggôzýUÓ²³³9wî·D–‰Ð8N:Eiii“~¦‡‡=öo½õ‡¢ªª £ÑÈ{gF£¡´´µZmʰP©T×TWÉÊÊ";;û¦¾$4žêêjN:EMMM“~nHH#GŽdÉ’%üòË/äççãëëËðáÃLu•ú{± ÖÖÖäåå]v›ƒääd‚ƒƒqpph¶s*´,EEEœ;wî_Ï%Ó¤µ‚’’~ùåÚµkǘ1c>|8ÖÖÖüþûïètºË¾Ïh4^q»ƒªªª&­´ -[ý,oÕÕÕM^.>Lvv6#GŽdôèÑtíÚ•}ûö‘™™yÙ÷\­ŒëõzS¥I@.ãUUUÔÖÖ6i×étlÛ¶ KKKÆŒÃÈ‘# á—_~¹l`!IÒUËnmmm³\¯BËVYY‰^¯oÒÏ,))aË–-„††šê*lÛ¶ºººË¾ïJe\’$jkk›<0Z6£ÑHee%ƒ¡I?7##ƒýû÷Ó³gOÆŒÃí·ßNvv6‡¾êþ^Ž$IhµÚ&¿^…–M§Ó5JŒÖ¤=¬GŽ!**ŠüWWWŒF#!!!Ìž=›±cÇ¢R©L333$I¢®®îªc!mmméܹ³èyL”J%!!!äåå5éŒËUUU¬X±‚Ñ£GóÀ P(0`3gÎä×_E¥Ra4‘$ …BÁ`À`0\µåÉÙÙ¹Aš¥ ˜››Ó¹sgÒÓÓ›´G2++‹ü‘>úˆ^½z!Iƒ bìØ±ôïß•JÕ ò¥Óé077¿êÒþþþtèСÙΧÐ2EDD\±WçF8xð ÇŽcýúõ¦ºJÛ¶m™;w.ãÆ»®ºŠB¡ €€€€æ>¥B bmmMDDD“Îc¡×ëÙ°aÖÖÖÌ›7[[[ôz=jµšåË—3lØ0ÔjuƒºŠ^¯Ç`0àèèxÙíªT*:tèpÓ¯Ø!4.OOOÂÃÃo®I— °··ÇÕÕUþp33¼¼¼0 TWWLEEEEE€\ÑILLÄßß¿)wS®[ee%µµµ´nÝ333 ööö¸¹¹QXXH»víÈÌ̤¶¶—óÈÍÍe\¸i7X²J¡Pàææ†¥¥%´k×®Á¬®çÎC©Tšîû‚ÐÒàààpÙºJHHeeervÀ™3gÄ}\¸)ÔÕÕQPP€··7¶¶¶€lúùùQQQA]]¡¡¡ddd˜²óóó)(( uëÖͽûÂT“¬¡¡¡”——³{÷nŠ‹‹),,dݺu¸»»ãääDDDÅÅŦ‰Ο?ϱcǸãŽ;šû< Â5quuÅÛÛ›íÛ·“MYY{÷î%>>žN:qÛm·qâÄ ÎŸ?Ouu5QQQäåå1pàÀæÞuA¸&­ZµB£ÑIAAÅÅÅüôÓO éß¿?;vì   €òòr¶mÛ†››aaaͽë‚pMBCC)--eÏž=SPPÀºuëðððÀÑÑ‘ž={RXXÈ‘#G¨®®&99™˜˜n¿ýöæÞuA¸* ÂÃÃ9yò$ǧ¬¬Ì”9Š……ýû÷çøñ㤤¤P]]Í‘#G(((u¡Ù4iJpûöí?~<¯½öèõz ˜1cööö8991jÔ(–,YÂÎ;III¡OŸ>W\ƒUZ333žxâ Þzë-fÍš…££#)))„‡‡3pà@ :uâå—_ÆÏÏÄÄDÆ/zŸ„›†££#O>ù$Ÿþ9;wîD­V“ššÊý÷ßO»vípuuåøñã<ûì³ØØØpþüy^xá…[f©áÖθqãxõÕW  ®®ŽÂÂBfΜ‰­­-Œ9’Å‹Éùóçéׯáááͽë‚pU …‚áÇÅóÏ?O@@%%% f̘@¯^½Ø±c/½ô¾¾¾œ>}šñãÇ‹t_¡Ù4iÀjeeÅôéÓ¹óÎ;‰‹‹ÃÜÜœ=zààà`ƒ5mÚ4 @||}š{7áº)•J<<<¸ë®».zN¡P`cc#†r75•JE›6mhÓ¦ÍeŸ ©îÂMËÂÂâ²eX¡P`nnNß¾}›{7hâ1¬‚ ‚ ‚ ‚p­DÀ*‚ ‚ ‚ ´H"`AAAZ$° ‚ ‚ ‚ -’XAAA„I¬‚ ‚ ‚ B‹$VAAA¡Eú×ë°æçç“’’BRRÞÞÞtíÚ•’’|}}Q*•Í}|‚ ‚ ‚ ÂMê_¬iiiÌŸ?Ÿ˜˜ª««¹ë®»077gñâÅŒ;–1cÆ V«›ûAAA„›Ðu§WVVòÁ`ffÆÚµkyê©§èÖ­÷ÜsK–,!!!¡¹OAAA¸I]wÀZRR™3g˜1cíÚµC¡P`aaÁðáà äÈ‘#Í}|‚ ‚ ‚ ÂMêºV£ÑH]]oÔÌ jkk›ûøgJh–€IDATAAA„›Ôu¬ÖÖÖøúú²~ýzJKK1èt:Ξ=ËñãÇ iîãAAAnR×=é’““<òo½õ'OžD¯×SYYÉ‚ ؽ{7½zõ¢GÍ}|‚ ‚ ‚ ÂMêº{X ­[·fáÂ…tìØ½^F£¡  €iÓ¦ñÊ+¯`gg×ÜÇ'‚ ‚ ‚ ܤ®»‡5??ŸçŸžY³f1oÞ¼æ>AAAásÝ=¬VVV¸»»³k×.ªªªšû8AAA„[Ìu÷°ZYY1`À–/_Nnn.:t0-mSïž{îÁÉÉ©¹QAAA¸ ]wÀªÕj‰‹‹ÃÑÑ‘’’öîÝ{Ñkî¸ã° ‚ ‚ ‚ ×åºV{{{fÏž^¯@’$ŒF#J¥ÒôšËMºd4ÑëõFÔjuƒ÷H’„Á`@¯×£T*Q©TõÜ ÂÍ@¯×_²K’D]]’$¡T*Q*•¢Œ 7I’Ðëõ T*Uƒr,I:•J…™™™(ãÂMçÂºŠ¹¹9ff¢uáV`4©««ÀÜܼAu¡%¹î€ÕÌÌ ;;;òóó9yò$©©©”––@Û¶miß¾ý%ß§Ó騼y3;vì   €!C†0~üx8wîkÖ¬!>>___&OžLxxxƒ VZ2£ÑȹsçøöÛoIHH 00ñãÇÓµkW ÇgÕªUäåå΄ hÓ¦Msï¶ \3ƒÁÀÁƒÙ¸q#©©©têÔ‰GyjkkÙ±cëÖ­Ã`0Áý÷ß/²m„›Jmm­©®RTTÄ!C¸ï¾ûLu•³gÏòÝwßqêÔ)üüü˜Ìœ9'''Þzë-233›{×ášF¾þúkvîÜÉ#<ÂðáÃùøã9pàiiiÌŸ?___f̘Ajj*ï¾û®¨«Íæº{X+**X¶lJ¥’wß}—ˆˆ ùùùlÚ´‰Å‹Bxx¸é=|ûí·Lš4‰ñãÇ`mmÍ/¿üBuu5ǧ¨¨ˆ_|‘víÚѹsgxàvìØÁÔ©S›û\ Â5Ù¶mUUUÌ›7sssÚ¶mË'Ÿ|©S§ˆÇÁÁ'Ÿ|{{{œœœ˜9s&111DDD4÷® ÂUÕÖÖòý÷ßÊO<€¿¿?}ôYYYüøãtíÚ•‡~Øôž¥K—r÷ÝwØÜ»/W•ŸŸÏêÕ«¹ÿþû¹÷Þ{y¢É­[·R]]ÍÑ£G)--åµ×^#88˜ððp|ðAvîÜÙ Ü BKuöìYvïÞÍ믿NDDƒªª*âââ2d¿ýöNNN<ù䓨ÚÚâààÀ¬Y³8qâÝ»woîÝþƒ®;`---åôéÓ¼ÿþûtîÜÙô¸»»;&LàСC8p AÀš‘‘Aff&ýû÷§°°ÚÚZÂÃÃiß¾=666œ9swwwüüüÐh4tîÜ™'N4÷y.¡¢¢‚‚‚œ±³³»hlCUU¹¹¹899áèèˆ$ITUUQPP€™™nnnXZZ6x^¯'77¥R‰««+*ÕµQ£ÑHuu5F£ Ôju³œ—ýû÷sÛm·¡Õj)((ÀÒÒ’9sæ`aaÁ÷ßO‡°¶¶ÀÛÛ___bccEÀÚÕÖÖRYY‰½½ý%Ëbuu5Z­'''Sù/))!//µZööö˜››7x_EE–––ÿ¨|ëõz´Z-¶¶¶Í:ŽH«ÕÃ+¯¼BII Z­GGGæÏŸ……§OŸföìÙ¦×wèÐÚÚZÒÓÓEÀ*ÜÒÓÓÉÉÉ¡oß¾¢Óéèܹ3;vÄÚÚšÓ§Oãé鉖––têÔIÔU„›Æ±cÇpvv& €ÜÜ\Ægz>>>žŽ;šêh>>>x{{sòäI° ÍâºÖú .5.©¾¢VSSÓàñ’’Š‹‹Ùºu+;vì ´´”.]º0mÚ4œœœÈÉÉA£Ñ˜*ójµ___>|Å})))aÇŽŒ3›æ>§ÿ ååå¼þúëddd`eeÅ Aƒ¸í¶ÛðõõE¡PœœÌâÅ‹)..F©TÒ¯_?T*»wïF©T"IÝ»w§{÷î„……QUUÅêÕ«9tèjµšV­Z1~üxBBBTì³²²9ØLãB×®]K~~>:ŽˆˆzõêÅ‘#G¸í¶ÛšôÜ$''ãççÇ‹/¾Èùóçñòòb̘1Œ9’¬¬,Ú·oo:IMM½â6³³³ùí·ßèÓ§Ïe'3Wii)K–,áìÙ³ØÛÛN¯^½  55•Å‹“žžN¯^½èß¿?ééélÚ´ Ó„tNNNŒ=š^½z!I›7ofÓ¦MóÀ˜Êñ•²råJbbbhݺ5!!!ôíÛ—ÄÄDéÕ«W“NGFF±±±¬X±‚œœüýýyüñÇi×®ÙÙÙ¸¸¸˜^ïããC]]WÜn\\ÎÎÎôíÛ÷ò­mëÖ­ddd4égS\\Ì–-[رceeetíÚµA]Å¢A]ÅÇLJcÇŽ]v›’$kÊ€²²2¶nÝŠ……E“~nFFeee¬X±‚}ûö¡P(2d“'OäzV—.]L÷bGGGHKK»ì6ëêêØ»w/žžž¦Ž'A8þ<»wï&,,ì_mçºk666øúúòÍ7ß0}út¼¼¼¹ç &&†˜˜ÆŽ{Ñûôz=ÇŽcÞ¼y¨T*>ýôSÞyçÞÿýË~V}Åïrìì쿨·N¸veeeh4š7M£ÑHii)ééé9r;;;‚ƒƒQ(,_¾œÐÐP^|ñE ˆŒŒdÞ¼yØÚÚâííM||<'NdÈ!äåå‰ÑhdöìÙøúú"I¹¹¹9r„Ï?ÿœââbÌÍÍéׯü1’$±ÿ~>øàÔj5]ºtÁÃÃ={ö››‹B¡ €Aƒ±eËrrrxöÙgM•ão¾ù†•+WÒ¯_¿f™#22’¹sçÒ½{w~þùg-Z„››Ûe_µ2îêêJŸ>}L$៑$‰šš4Mƒ™>ALcbbØ¿?>>> 0FÃë¯¿Ž——ï¿ÿ>éééÄÆÆòî»ï¢ÑhðððàüùóÜu×]Ì;—;v°lÙ2ÜÜÜxöÙg Â`0P[[KBB?üðK—.E­VãççÇsÏ=ÇáÇ™={6íÛ·§wïÞxzz¢×뉎Ž&::¥R‰··7ÎÎÎüñÇÜyç¼óÎ;dgg“˜˜È³Ï>Ë£>Š¿¿ÿEÇÔvïÞͬY³ðööfÕªU¼ùæ›,X°à’¯5WÃH·nÝĤ5B}ûö½¨ñ»)ÔÕÕà /¼€R©äã?æÝw߽B¡ mÛ¶7ù±-—©ñ±©¥§§S^^ÎâÅ‹ÉÌÌä7Þ ¦¦†9sæ\ö=W*ã*•ÊTW„zÞÞÞtëÖíªõÜ«¹î€ÕÁÁG}”—_~™¸¸8BBBP(rêÔ)úöí{ÉVD•JÅœ9sL3=ùä“L:•ÊÊÊË~ÖÕzM•J%¶¶¶¢¢sŠŠŠ˜9s&666L™2…®]»rúôi¶mÛÆÉ“'qvv&,,ŒÂÂBŽ9BJJ ãÆcâĉ¨T*œ ᡇ"))‰””zè!Z·n ÈK µmÛö¢Ïupp $$„É“'“N§£uëÖ¦ïñÞ{ïåî»ïæìÙ³ìß¿Ÿ¸¸8FE×®]©­­%22’~øž={òÒK/áììlÚö /¼À¢E‹øþûïyþùç›üœÞ}÷ÝŒ9¥RÉ#>žwß}† BHHYYY$$$°cÇœ¹ýöÛ9sæ ¯¼ò 999L˜0É“'cee…››ݺucâĉ?~œŒŒ ¦M›fÊ(¸ÿþû¹ÿþû/ùÙ·Ýv}úô!** +++Ó}±C‡Üyç9r„={öPVV†N§#44”'Ÿ|½^Ojj*999¼ýöÛaff†¯¯/¸ºº²lÙ2ºvíÚ,)ÂS§N¥ÿþ<÷ÜsÜqǤ¤¤\òµ*•êª=–––"CF¸ˆ]³ ïP«ÕÌ™3žxâ {ì1ªªª.ûž«•_KKK¬¬¬šüX„–K©Tbgg×,õ×€€ž~úi\]]ñõõeüøñlذáŠë•ê* …›‹†ÀÿmÊÊÊþÕv®;`U*•ôïߟ¯¿þšß~ûÓ§O£ÓépuueÞ¼yÜu×]]€¶¶¶ØÛÛ7HsvvÆÜÜœòòrÚ´iCrr2¥¥¥888 Óé8s挘F»”••amm}QªÝ‰'xÿý÷5j~~~¬]»– кukÌôéÓ±³³3½Ï`0`0P«ÕõêØØØÐ¥KºtéòöM©Tâëë{Éç4 íÛ·',, I’|æ„ ¸÷Þ{/¹6Xý¸ÑK“½Ñ¼½½ñòò2í«¥¥%îîîÓ¦MrssÑét˜››“ŸŸO^^Þ?>gÂÅ*++±´´lpßÑëõìܹ“o¾ù†Y³f¡ÕjÙ³g+V¬ÀËË‹àà`^xáBCCQ*• >­VKee%®®®Ý쬬èÛ·ï?Þ7µZMŸ>}.zÜ××___î¹çSä…ë9véÒI’.*ß …‚»îº ,XФ=P*• 77·×lýXÝÒÒR‚‚‚LiÒ Oî¡R©puum²}„£¾<_XWqqqA­VS^^N`` ;wî4ÕUjkkIJJuá"ƒââbÓ0(çF(++£²²ww÷f™AÝÝÝ{{{Ó2M …OOOêêêÐjµ“““cª«äååQPP@=šû” -”$IäååKZZ%%%”——$IÿºÓå_ò÷÷güøñ899QWWGyy9–––(Š‹*Yîî¹±gÏ @tt4–––899Ñ©S'V¯^Mrr2;w¦ªªŠãÇóøã7ãWpóËÌÌäõ×_Ç`0˜&Ž0dddðÓO?1qâDÆŽ‹R©¤k×®^vÂ#•JÕ,ãË.Už Å÷E©TÐä-—ááá8p€qãÆannNff&IIIŒ7FÃwß}GYYÎÎΤ§§“‘‘Ѥco5’$‘˜˜ÈüùóQ(„††âææ†µµ5Z­–­[·ò /гgO tÙmÕ·7uOŸ™™ÙeÓz/×{ªP( dôèÑM:þÉ‚àà`vîÜI»víP($$$PUUE«V­èÚµ«©ü+ Ž?޵µ5AAAMzNázyxxàââž={L÷‹¨¨(¬­­qtt¤sçάY³†””ÂÃ鬬$&&†3f4÷® MD¯×SWW‡™™ …Âô_…BN§#::šß~ûäädjjjðóó#--ššS]Øh4R\\LEE…)[¥©óÓO?qêÔ)ÂÂÂÐëõ}šùóçSWWǺuë°°°àÿûk֬ᡇ⡇jлåïïÏ#<»ï¾ËîÝ»1?~œ3fàè舫«+½{÷æÍ7ßäöÛoçèÑ£Я_¿æþînZz½ž… Ò­[7 D||çÏŸÇÁÁC‡1~üx:uê„££#/¿ü2/¾ø"ŽŽŽìÚµ‹©S§ŠqMÂ?’””Ôle& €|wÞy‡]»va0ˆ‰‰áé§ŸÆÁÁgggzôèÁo¼ÁСC‰ŽŽ&((è’YÂÍ©¦¦ÆÔ3êææfJK—$‰ääd¾øâ Nž<‰¿¿?jµÚ”ÁfmmMzz:æææŒ5ŠÙ³g7˜„îïôz={÷î%==½I¯W¯^DDD0oÞ<ú÷ïONN)))ÌŸ?€!C†É‹/¾H‡øã?2dmÚ´i¶ïDh\ÉÉÉäää`mm³³3ÞÞÞ(•Jjkkùå—_X¹r%C‡%!!o¾ù333S/i^^ÁÁÁÜvÛmœ;wŽ7ÄÒ¥K/*ïC‡%&&¦ùR‚ËËËYºt)ÎÎÎLŸ>ÝÔÓuß}÷áääÄW_}E·nÝ.šþzذa899qðàA,X@xx¸éýÏ<ó ;vì 66–2dÈc…‹I’„V«¥¦¦†ÊÊJôz=NNNXYY±víZ¬­­¹ÿþû±±±½MÀÛÛ›÷Þ{ÈÈHRRRxàèׯöööH’Ä믿Î/¿üBff&?þ¸h±¼ƒêêjt:F£¥Riº±~úé§Œ3†>}ú R©LÀ 7N—.]L eeeÌ™3‡¾}ûbiiIÛ¶my뭷زe 555¼üòËb¯cI’.›#IÅÅŬ_¿žÍ›7ãïïÏôéÓ¤S6•#FàêêÊ033ãwÞ¡C‡¦ŒgŸ}–;vpòäIÌ!C.¹j‚вÕÕÕ‘žžŽ ¨T*’’’Xºt)F£‘¢¢"Ó0ˆV­ZaggÇîÝ»3f sçÎE’$***¨ªª2Õ¿FM`` 檟¯R©hÓ¦ ¥¥¥M~ì3gΤGìß¿Ÿ¶mÛòì³ÏÒªU+@žÝ¾¾®’••Å“O>)ê*7¡úå$÷ïßOëÖ­ñððÀ`0ðã?²k×.BBB((( ¤¤333:tè@ii)………|öÙgøøø`ffFmm-………QQQaÚ–R©dàÀMr,×°–””ÇgŸ}fZæÀÓÓ“±cÇrøða>|QEE¥RÑ·oßËŽspp`ìØ±—œaX¸´´´4Þyç F£I’¨­­ÅÊÊŠÒÒR–-[&&3iB …__ßK. _?Ndúôéͽ›7•#GްvíZ´Z-µµµX[[cnnNnn.½{÷fÊ”)ͽ‹ÿ)fff´oßžöíÛ_ò¹BBBš{7…fRWWGBB!!!¦tu½^Ïwß}Ç™3gèÒ¥ mÚ´ÁÍÍ WWW ‰‰‰œ8q‚½{÷ÌŠ+Ø¿?óçÏÇÇLJ‡z¨IA­V_±®âèèȸqã¬])Ü\t:Ÿþ9{öìÁÞÞ ª««Q«ÕLš4‰þýû£R©Ðjµ¤¤¤@^^ ,h0^ùfÍJ³³³cèС :ô¢ç ^^^<öØcͽ›Â¿°wï^V­Z…µµµèt:´Z-íÚµã“O>ÁÝÝÝôÚ””Ñjµ :´Á˜SFƒ··÷5-Ãw£\wÀªP(P*•—we0þõôŵÉÎÎæí·ßfèС 0[[[òóóIKKÃÃÃC«ÂM-??Ÿ¯¾úŠÉ“'7h«««C§ÓáããÓÜ»(Ÿ²³³ùúë¯‰ŽŽ¦S§NÌž=333>ýôSôz=C† áĉ8p€´´4Ôj5:///ÂÂÂxî¹ç B£Ñ0zôh<<<øí·ßšû°„›”V«åðáÃh4ÜÝݱ´´¤¶¶–üü|6lØ€µµ5ü1ŽŽŽ”””PUU…———i2"'Û û×ëH ÂPSSCzz:’$¡Ñh0$&&Mrr2“&MbàÀF ¨««Ã××÷¢ÙœýýýMãN[¢µ¬M»víX¼x1O<ñaaa( ***øùçŸIHHhòÑÿNÇÂ… áÞ{ïmð\«V­L©‚p3ÉËËC’$<<<¨ªªâÃ?¤oß¾ 2¤¹wMþÓJKKIHH 11‘üü|üýýñòò2¥áòÉ'ŸÎW_}ÅÚµkyî¹ç°µµÅÜÜœW^y[[ÛŸÕÖÖRQQqÉq~õ½õgÏžmîCnBååå,Y²„sçÎáííMnnnƒe…úöíÛ îdooßÜ»,ÿˆN§ãƒ> 66777ôz=F£OOOºwïάY³”k??¿æÞåëvÝ«­­-Ó¦Mãƒ>`ÆŒ899áääÄÙ³g177g„ têÔ©¹ï–b4Y³f ëÖ­£M›6äääйsg‘²!Ü2***˜7oEEE„……áääDMM ãÇoî]„ÿ¬””~ýõW:D«V­ ¤}ûöäææ²k×.ŒF# §ý>öØcôîÝFÃSO=ÅÖ­[ILLdæÌ™—\ƒT£Ñ\ÓX?A¸š¤¤$<ˆ³³3îîî|ýõ׸»»³xñb,,,ÐjµèõzÔj5æææb½Pá¦P?µººšÊÊJÓã|÷ÝwØÙÙ±téR¬¬¬Ðét( ¬¬¬šeEé_¥wìØ‘>ø€ãÇOmm-téÒ…N:Ýr'«¹%&&Éo¼­­-téÒEÜt…[Æo¿ý†««+ï¼ó'OžäàÁƒ<ýôÓ¦TwAn}š£GÒ©S'Þ}÷ÝÔBonnÎèÑ£›ûp„ÿ€³gÏòâ‹/š–æÛ·oÝ»wg„ X[[ˆßá¦Ãûï¿­­- …GGGt:999ôêÕ‹éÓ§›æ ¸pe–[Í?Š(SRRøí·ßðõõ%44___ÜÜܸóÎ;Mƒ¶ë×£Waa!o½õ=öááá( 1½¸pK‰eݺu|ùå—8;;ãååÅСCÅýDš@qq1ÉÉÉìÛ·“'ORSSC‡gòäɸºº6ùšÖ‚p)’$‘——GII ’$‘™™ÉÒ¥K™={6½zõB¡P`0.;ÏŠ Ü ´Z-+V¬`ïÞ½üßÿý¦5Û%IB’$ÌÍÍÿ3÷å°º¹¹Ñ¥K¢¢¢øý÷ß±¶¶¦W¯^ôéÓÓ¢ÉBã‘$É” Ü®];zöì)αpK©/ã+V¬àî»ïn°ŒÕåF,7š$I`gg×`MÉÔÔT¶lÙÂÞ½{qtt¤_¿~<û쳄„„ˆT]¡Å¨ÿرcûöí#!! $IB¡P0sæLzõêeúͪp3©@W­ZÅöíÛMËU¶iÓ†÷Þ{OÌIÃ? X­­­éÙ³'={öD¯×“œœÌÞ½{yå•WpuuÅßߟîÝ» f¦ýê»úÓÒÒˆŽŽæäÉ“899ñÞ{ï‰ô_á–PQQAqq1YYYÄÇÇ‹ƒƒƒX"BnNÇÆY¶l¸ºº¢V«ÿŸ½ókêzãø7 a/ÙˆŠ8Qq/îmë¶Ö¶ŽÖ¶¶j[«¶ÚÖU못j©úsÔ]µu܈"ˆ‚ eï=Y÷þþxI –¼ŸçáÑ$77ç&çžóî 066†‹‹ ÜÜܸžçu’ììl\ºt gΜ££#†Š•+WrŽCNN~ýõWìÙ³J¥hÙ²%g|)ä“Lµ´´Ð¶m[´iÓS¦LALL üýýqüøqˆD"téÒ®®®uºDr]ƒeYÜ»w{÷îŸÏG‹-Ю];üøãjKPspÔ7är9¶mÛ†‡ÂÌÌ †††èÙ³'æÌ™ƒ6mÚ¨-ÊÂÁÁQy¤R)‚‚‚^½zÁÐÐçÎÃÿý‡£GBOOiii`YFFF°°°à"8ê ,ËB.—#??IIIxøð!®_¿Ž–-[*sT9ž£!À0 žž777…B|ÿý÷011á*V«á­«"ñx<˜ššÂÔÔ;vÄÆÆâñãLjŒŒäÖ*œœŒ?ÿü?üðWa™£Aâåå…çÏŸãØ±cœrÊÁQͤ§§cïÞ½ ­­-> äååaÓ¦M°µµ@mé88êéééðññÁ;w––†aЭ[7¬\¹mÛ¶å +õ†aˆÀÀ@$''#''ñññ‰DèÞ½;>ûì3Î1UUVXY–EVV"##acc0 ???\¹rR©=zôÀ¨Q£tµªšàÆhÓ¦ לš£A’ŸŸ¿ÿþ3gÎä”UŽj$//~~~8tèZµj…7ÂÒÒñññ “““RYå਋deeá§Ÿ~‚®®.†ŽÖ­[ÃÚÚúúú\ÝŽÁëׯ±mÛ6 4&&&èСš4ikkks‘Pe…5::«V­B`` Ö¬Yƒ‘#G"$$_~ù%ŒŒŒ`ff†«W¯âÅ‹X¸p¡²œ8Gù$''ÃÝÝ+W®TÄààhH‹xª¤°ŠÅblß¾"‘;wîD§N •JqæÌXZZâ×_EÓ¦MqçÎlÙ²ãÇç¼…•@&“áï¿ÿF×®]¹V5 ©T ‘H„„„¸¹¹á§Ÿ~âŒXoA`` ¶lÙ¢¬Ìïàà€>ú:t࢚8êŠ(½ÜÜ\ÄÅÅáÎ;hÛ¶-æÎËRâhddd ..:::044Ä©S§`gg‡É“'sÊêR%…5<<aaaøê«¯àìì ˆ‡¿¿?ú÷ï'''ðù| 2'Ož„——§°–CTTüüüÛ·oc÷îÝ\HGƒ!<<[¶lX,˲pqqáÖŽ7„axzzb÷îݘûì3ôéÓZZZÜBÍÁñ†dffâøñãðððÀÊ•+Ѿ}{θÉQ¯Àï¿ÿ,Y²ÐÖÖææ1GƒA.—cÆ xùò%-Z'''0 ¹\@ÀÕîxKª¤° ðx<ÈåråsÏŸ?Ã0h×®¦¯¥^ “ÉpâÄ Üºu «W¯VQþ98¾¾¾Ø²e >ùä >œ áàx âââ°jÕ*˜ššbË–-hܸ±¦‡ÄÁQ%‚‚‚°bÅ Ìœ9Ó¦MÓôp88j„û÷ï#22;wî„™™™¦‡Ó਒ÂÚ¤IèèèàÚµkøôÓO‘——‡K—.¡wïÞ*–ƒW¯^!$$óçÏ×ôõÕ9¶mÛ†¸¹¹q…8qqqX·n~þùg®5Ga±±±8pà222‘‘øðÃ1tèPÎøÃQ¯HIIÁñãÇqãÆ lذAÙúƒ£¡‚;v`ÇŽœ²ZCTIaµ±±Áˆ#pøðax{{#??ñññøøãÁçó‘ššŠ»wïâĉprrâòÕJlݺ•SV9 Ã( XܽÏÁQyär9$ îÝ»‡`ðàÁ˜6mtttШQ#Nâ¨WÈår\ºt ÇŽC·nݰcÇ® $Gƒ„eYH¥R:t£FB“&M4=¤K•V>Ÿ>úfff¸ÿ>ŒŒŒ0yòdŒ1<^^^pssC×®]±páBn“-†H$ÂŽ;0gÎØÙÙiz8ÕŽ¿¿?îß¿;vpÅ`88*L&ÃÍ›7ñìÙ3$&&‚a¬Y³ŽŽŽ\ïIŽz˽{÷pâÄ ¬Y³mÛ¶åæ2GƒƒeY$''ãÙ³g¸zõ*„B!æÌ™ÃEÁÔ Uî꣣ƒñãÇÃÙÙR©æææÊRúýû÷G‡`iiɵ®(rssáââ¢é¡ppT;"‘û÷ïLJ~ M‡ƒ£Î“žžŽ={ö >>£GÆäÉ“akk ###MƒãIMMÅáDZhÑ"®FGƒ%((?ýô:vìˆ1cÆ [·nœ¡¾†©²Âš••…Ã‡ãÑ£GÈÈÈ@ëÖ­ñᇢW¯^066†±±q¥Ï•””„°°0ôë×Oùœ\.GDD"""`mmöíÛCK«ÊìSäççãÈ‘#˜9s& 5=ŽZ„a<|øŽŽŽ°´´@^dddÀÁÁöööõÚ*—––†ãÇ£  @å^æx7ÈÉÉÁ“'O0pà@åZ-‰àëë †aкukØØØp^–bdffbùòå°³³ÃöíÛ¡­­­é!q”Cbb"^½zUJV Gdd$lllЮ]»z/«Tÿþû/ìííÑ­[7M…£ ¼zõ ¹¹¹*µ'd2ž?ŽÌÌL´hÑÍš5«×²Ju‘˜˜ˆ 6`Ù²eèÝ»·¦‡óÎP¥Õ•a?~ÇG¯^½àää„{÷îaÅŠ8~ü8¬¬¬*}.‘H„]»váåË—*›ÀñãÇqîÜ9@$aÀ€øôÓOëÇV$á·ß~CJJ Ñ¥KN˜Ç`YOž<Á·ß~‹Ý»wÃÒÒyyyؽ{7?~ äççcÊ”)˜>}º¦‡[e²²²püøqܽ{:tÀš5k8ïÐ;Ã08}ú4öìÙhii!>>›7oFtt4ttt —˱dÉôìÙSÓíÄÄÄ`Æ pvvÆŒ38eµŽ“——‡;w–RX=ŠÿþûO)« 4óæÍ{çZWäçç#-- õ–¿{÷.6mÚĵ1«GÄÅÅaíÚµhÙ²¥RaÍÍÍÅ®]»ðäÉ¥¬2}útL™2EÓÃÕ(r¹nnnèС·§Õ2URX³³³áîîŽ÷ß‹/†ŽŽ†Ž%K–àéÓ§5jT¥Ïuûöm\¸pA%A9&&ÿûßÿ0kÖ,|ðÁxöì¾ûî;tïÞýû÷×ôwU%üýý‡åË—ÃÜÜ5âú½cÄÅÅaÇŽÈÎÎÃ0€'OžàòåËØ°aºwïŽcÇŽaïÞ½2dˆÒ[_¸víüüü°eË4mÚTÓÃáÐ8tèrss{öìY„‡‡cçÎ055ÅæÍ›ñ矢mÛ¶UŠÀiˆddd`Íš5èÔ©fÏžÍyëîîî¸xñ"š7o®|.::‡œ9s0mÚ4<}úßÿ=zôè¾}ûjzÈ5ŽT*EPP<<<ðìÙ3äçç ܇~ȵ^ªgüïÿƒš5k¦|îñãǸzõ*6oÞŒ.]ºàÈ‘#سg\]]ßé´Ÿ§OŸâõë×øý÷ß9™¾–©Ò·]PP---8;;+­g-Z´€½½="""*u–eáçç‡S§NaðàÁ*¯y{{ÃÊÊ £F‚ŽŽºté‚=zàÞ½{šþžª„L&Ã?ÿüƒY³f¡M›6077ç&ö;†T*Åž={JUËõðð@¯^½ÐµkWèèè`Ĉ°´´Ä£G4=ä*!‘HpëÖ-ÌŸ?ŸSVßQ°sçN•uœaxxx`ìØ±°··‡‰‰ ¦NŠÄÄD„……izÈ%&&K—.Eß¾}ñùçŸsÊj‡eY<{ö ÿüó\]]U^{òä lmm1bÄèèè k×®èÖ­[½“UÞ___¬Zµ X¶lþøãüñÇpssÃèÑ£5=<ŽJ"—ËqíÚ5DDD M›6*¯yxxÀÙÙ;w†ŽŽFsss<~üXÓîu†A||Ç0 BBBкukås-Z´€D"A||¼¦‡¬1233ñ믿¢]»vøðùâõ™L†`àÀprrRy-44&&&J¡µ¾Ê*oʵk×0uêT|üñÇhݺ5LMMajj .DZC‡áÓO?-åùò%ìíí•) –––°°°¨w²ÊÛÀ0 """àææ†ï¾ûùùùؽ{78ƒ£¨U·ŸT*…››„B!¦M›Vêõüü|ðù|eá>ŸCCC¤¦¦–{Þ¬¬,xxx@$տ卅eY\½z½{÷æz­j¹\ŽgÏžáÙ³g•6¦Tþþþؽ{7¾ùæØÚÚª¼&‰  •Fèèè(s€Ê")) wïÞU†^j’ììl¸¹¹aÁ‚Ê áµX,ÆÃ‡ñúõkeÈymÀ0 .^¼ooo|õÕW¥Ö¹üü|•ü5CCCH¥Räää”{Þàà`xyyÕúýZÓ¼xñŸ~ú)œ±xñbNY­"·oßFBBB­~¦T*ÅŸþ ]]]µ9{ùùùJYE ÀÀÀ \Y…eYÕ{¥644ááá?~<'´W999¸}ûv…ëcuSPP€M›6¡OŸ>èÕ«W©×ÕÉ*ÚÚÚHOO/óœR©^^^µ~¿V7,ËÂÓÓ|ð~þùghkkcË–-Xºt)ìíí5=¼zGtt4=z©TúVç©rI;™LOOOå„‹ÅHMMEPPNŸ>­rìðáÃajjª|ìëë‹Ë—/cëÖ­Ð×ׇ\.˲H$åV׫hQÔÕÕEóæÍë„ —ËñäÉ,[¶LÓCy§áñxhܸ17n\«áØØ¿?úöí‹6mÚ(oP™L™LVîxËÃÈÈ-Z´¨ZBCC!“ɸFðF ÀÞÞ¯^½ªUÁ111‡ÂìÙ³aee…èèh&^ÖüäñxŽÑÊÊ M›6­÷B0˲ˆG@@ÂÂÂpûömL:“'OæRCÞ€–-["99¹V?ÓÇÇ×®]ÃÖ­[¡§§W-² ǃµµu•ŠSÖ5¤R)Nœ8aÆջB˜u´jÕ qqqµö™r¹.\@vv6&Ož ™L†a —Ë!‘HÊ•¥Ë›ã|>Íš5«÷ÅE"Ž=ŠO>ùƒ âœOo‰©©iµtè’ÂÊçóa``€Ë—/—z-##*ÏuïÞ]Ea={ö,Äb16nÜ€ŠÒ$%%áóÏ?ÇâÅ‹•J¬T*…P(Ã0ÈÉÉ)å¥*‰ŽŽš4iR'V???¡mÛ¶šÊ; ŸÏ‡µµ5¬­­kUöõõųgÏžžŽ €eYÀöíÛñâÅ hiiA"‘€aðù|    B«¾¾¾JAM™™‰°°0ì߿ӦMãq £¥¥…&MšÀÔÔ´Vçø­[·€3gÎàܹsÈÎÎ,Z´cÇŽ…¾¾> ”Ççää@[[[e/P‡™™Y½/ÖÂ0 3==ç΃D"ÁO?ý€B€…B!¾ÿþ{¬X±¥d±X¬’îQ@[[Ûzß¾ñßÿ…‘‘ÈÉ9Õ€±±17nŒ¬¬¬·:O•ÖFaõêÕH$•:¾x`xï½÷еkWåcOOOäååaذa°°°@ÇŽñäÉ$&&¢iÓ¦‹Å ¬óÊ_DDÜÝÝñêÕ+¼xñ‹-ªž0ŽÚÇÁÁ .TzS ݺuC§N••…W¯^!??HJJBBBƧ顗Ivv6Ž=Šû÷ï£iÓ¦pvv†‹‹‹¦‡Å¡!zöì©âeŠŒŒD@@\]]ѪU+téÒEù P_--­ …ùúŽL&éS§påÊìÞ½mÚ´á<ªõ”‰'¢GÊÇŠ”£aÆÁÜÜ:u‚¯¯/’’’`gg±XŒ   :/«¼ r¹ÙÙÙHIIÁßÿÁƒWh|â¨ÛbΜ9*©HiiiÐ××ÇÀ¡§§‡nݺ!,, b±zzzHLLDbb"Þÿ}M¿Æ`YÁÁÁ8þ}ú@WWË–-ƒ——ºté‚K—.!77ƒ ÒôÐÕ’€õë×ÃØØüñÇ;]Ξƒptt„£££òñ“'OpèÐ!L:ººº2dþùç 6 FFF8}ú4t.‰D‚3gÎàæÍ›Ø°açQ­ç¸¸¸¨årrr­”Uœ±{÷n\¾|S¦L‚ƒƒñõ×_kzèÕ Ë²8}ú4nß¾ èÑ£¦M›ÆVªçèééaøðá*ÏyxxÀÌÌ 'N 4?þø#¼¼¼Ð©S'\¼x0`€¦‡_cH$>|£F‚¦‡ÃQ‚*ç°²,‹ÄÄDœ8q7oÞ„T*Uæ'Éår8::bîܹèÒ¥K…Öesss´hÑBùØÌÌ ‹-ÂÁƒq÷î]°,‹O?ý´Î :ÙÙÙØ²e ú÷ïyóæÕ‰dŽºǃ£££2ß§cÇŽ˜5köíÛ>Ÿ¡Pˆ¥K—ÖÉf󉉉X¼x1FŒéÓ§×É1rh}}}8::*÷ñãÇ#::?ýôŒŒŒðý÷ß«bjHH¥Rœ:u îîîX¿~='è4@ÌÍÍU ÑæææX¼x1:„Û·oƒeY|öÙg¥ZƒÔg¤R).^¼ˆ .`Ù²ehݺ5ôõõë}Ž9‡zš4i¢Ò'»sçΘ9s&þøãhkkãûï¿o°rÀ«W¯pðàAèéé5h/r}¦Ê kZZV¬XÐÐPŒ1½zõB£F ‘H‚sçÎaÉ’%X·nœËUZß{ï=¼÷Þ{*Ï 6 ;wFdd$7n\*¬¸.qüøqÈår|üñÇœ²Ê¡¡PˆÿþûOùX[[ü1ú÷ïÔÔT´iӦΆW={}ûöÅÇÌYÔ9ÊÄÉÉIeŽcéÒ¥ T*E›6m¬#•Jqúôiܺu k×®å”ÕʤI“0iÒ$•çFŒ.]º ** vvv î·¿{÷.N:…Í›7k¼~GÍóÃ?¨<ÖÑÑÁìÙ³1`À¤¥¥¡mÛ¶011Ñô0k„gÏžaãÆ}S¦Láz­r4H®^½ŠöíÛ7ؼŽ7ÁËË Ÿþ9RSS±wï^têÔ‰ë³ÊQïaY±±±pssßþ‰ï¾ûfffšG ‹ñûï¿c̘1èØ±£¦‡ÃQª´ÛÚÛÛ£yóæ8{ö,âããK)­,ËB,ãüùóèܹ³¦¯¯ZaYþþþ044lpׯÁP¸û¥K—¸²îÅÈÊÊÂŽ;0aÂüðÃ\?bŽÃ0pwwÇ÷ß´´4lÚ´ mÛ¶Õô°88j–eqçÎdff–êPÂQ÷©ṘP(Ä‚ ðõ×_céÒ¥øàƒЮ];èèè€a$&&â¿ÿþÃÍ›7±páÂ×<=99'OžÄ€¸Ê© Ь¬,ܹsç΃™™Yí}ÌÁQÛÈd2ìÛ·...˜0a‚¦‡ÃÁQ-(„w777üöÛohÕª•¦‡ÄÁQc(Œ3ûöíÆ ШQ#M‰£ŠT9I¡M›6ذaöìÙƒ­[·ªÄ~³, ]]]|ýõט8qbƒèe$—Ë'N 88ýúõÃ!C4=,ŽjA"‘àñãÇ8r䬬¬ðÝwß¡eË–\þÇ; Ã0ÈÌÌ„‰‰ ^¾|‰gÏžaÏž=šGµÀ²,^¿~Ý»wã‡~à”UŽMbb"Nœ8   ¬X±‚3È×Sª,•òù|tïÞÛ·oÇ‹/±X >ŸôèѶ¶¶š¾®jãêÕ«pssÇ~ˆùóç×ùþ°•%==û÷ï‡>ûì3 :TÓCâàÐ8¾¾¾øõ×_áââ‚)S¦àÿû&L˜ÀYä9 ÏŸ?Ǻuëðí·ß¢W¯^šG!‘H°|ùr´k×;v쀾¾¾¦‡Äñ†¼±ÅÈÈ}úôAŸ>}J½–‘‘eË–áçŸF“&M4}oDAAŽ9ooo¬Y³;wæ*‰q4†Á‰'““777kzH…eYQö ?~üðC®ª{SXÕ‰øøxôèу «òòp>Ÿþ"*—")¢¹¹@F`kKÇñù˾¾À† Àöí€PìÙŒ ´n hi99ÀŽ@p0 ýEŸ%—Ógp¨À²,þûï?Œ5 ºººšNý†aèÇSÛÅaY 1¸|hÔˆ”Ñâ-Áïqvììww@,´µé8†bb}}ÀÚˆ‹£{¡eK`Ü8Mõ–e±ÿ~˜˜˜`Ĉœ0ÏÑ`‰Dظq#œœœ°hÑ"ÎÃÑ aY à 44gΜÇÈ#89¾À)¬%Ëåø÷ß1bÄhz8u›Œ 4èÒ¥´7(*ŠI''ÀÇص‹Ñ9sèø¸8àï¿ÇE‹WW =ؼHM ¾ø‚õíÛuëE>tÇŽÀ¦MäI]µŠùiÓ€6mTÇpú4ÿû/Äß|£éoªNŠàà`¬Y³FÓC©yÒÓƒšóVnÞLž}}}àÛoIá,Ih(°e г' È–H€‹鱕о=м9ýõïOÇ0 pú4pæ  «K÷ƒµ5Íûùó7ÈPÃMyc†Á7Š-[¶pÕ±9OžŸÞOަݻ‹ÑfÍ€­[ØXòÊ€™°v-…+18ÈÌ$EÏ/­¬À„ HÕÒ‚nh¯Tøúú¢[·nšFí°o…‹ù%){ê,­ C ¤ŽŽêë"pè0v,ÍMuôê|ø! “––tž³gɨ’’B†˜–-?þ {M@@÷Ë•+d Ù¼Yõu€æõ¸qäyµ°¯ŽЪýeg“âÊñFãÀؼy3ÌÌÌ4=ŽjC&“á¿ÿþÃÔ©S9¡£A#•Jqþüy\¸p?þø#:uêÄE5@ª¤°cáÂ…HJJÒô¸kŒ€€h® AN ®5¿–“üò ò­[—~=1‘<›¶¶ämÚ”ÂóòHÁeR8ýøßÿ€þ¾ú ÈʶmÞ{}€oSS¼ôê¥Þ3$ª*§††E‚zqtuIà/}}H¬¬ Ã…ƒ(‘J¥¸ví¾úê+MåíÉÊ¢Pò§OssòN–dþ|àèQòð¯\ èéÑó™™ô¾!CÈ@²u+0s&yAº?¶o'ÃÊܹ¤>xDDÐçŽK÷««êçÉdôß|C^WWõ!-- _?ú+ú+ ÅõpT™°°0eÞª½½½¦‡ÃÁQ­xzzB.—síÊ84R©Gއ‡Ö¯_fe—9ê=URXÛ´i777H¥ÒJ_Ÿ„¹\ŽÄÄDœ;wcÇŽ…ަ žÜ½K¡¶³f©÷U™  <<€Ù³É Y†þû02*òœ®Z8:’·³W/RV­"¯‘‚ädRPèÛøä:÷üùä­(ÄqÑ"zm悱R˜àRÐÔcÇŽÁÊÊJ³³†¼— ïxyH$¤Ü?Žeé>ùï?R*“’(4vݺ"O¨\Nss`ÁòúëèÁåÊàΚûC†PH®«+cÔ(`Æ !¼û åC …dLjÓ¦ìÂ^ZZäíÓ‡ÞÏQç`^^^øã?ðÉ'Ÿ`èС\ŽGƒB*•âÌ™3*Ä88"~~~ðððÀ–-[`nn®éápÔ URXóóó ''§U=7&&ÿüóîÝ»‡bÀ€šL—.E9e…áVÄñãTmô‹/HÀNH p\…7ˆaÈÃôé§ä©(g44”žo׎ýâÊ*@ãY³†³L\»FÊ`Ys%>ž”ÒÐPàóÏU½é/_’Çtùrzú8q‚ž›?_U!<˜ƒÏ?'e’c°²¢*§u­Lx&€|ÉšHÝ#)) {÷îÅÊ•+ñé§Ÿj.·#7·¨Ò³®.…‘«#?Ÿ*A'%QhyIO¥X |ý5н;= )_zéRR³²€€Þ½KŸ[W—Œ-ƒ—§-nxáhDFFâ·ß~ÃÂ… Ñ«W/NY}[d2J §¨‰7A"¡sDF=—œL¹Ù‹Q:G…äääàÞ½{X²d Ο?ü‘ËËæhÐx{{#33ý… 94Uò°J¥Räççƒ)Ö*$''`ë©4''!!!Ø»w/¬5é‘J)$qÖ,R&e²ÒÇܽKù¢µkyþ¸y4ˆÐÆÉ[Zªªûú5) @é/êÈ >Ôç‰à‹Ò 6ФI899iΞž”sÚ¾=y ·n%åTOrFïÜ!¦™…÷G,.ÊëîÚµô¹µ´Š")¿ºS'Í]+G#77[¶lÁèÑ£áìì ~EáèEˆÅ@@E<˜šRè<ÃP¥÷›7éÞ›5‹ŒH11ÀŸÒq††dez\ТÝÿQôÏΤ 6i¬^MŸ œ;Gáù\ñ” ÉÈÈÀúõë‘––†  S§Nš]ë98j˜¼¼<:tóæÍƒ±¢ú>Gƒ¦Ökø³,‹ÌÌL$''ƒa4nÜ&&&Ê׆AZZRSSall ›í‹wíÚ5tïÞ]óýÉ<<ÈÊlk[T¤E,¦ðDEŸÒŽ©ª®©iQ~këÖ"ùûïäujÜXýùy<ª*Zò„¡~(¬i eU¬é‰qqqÈÍÍ…¹¹9¬¬¬”-3är9âãã‘—— ˜™™Õ˜ð,•JqáÂLŸ>]óLóæÀ’%”»ª¯¬_OJèñã$œŽQ¶!åÇé>øæõ¡‹Ó³'ð®TAÖ yyyHHH€X,†••,,,”K‰D‚˜˜0 +++kÔ›)‹±uëVØÙÙáÃ?äÚ×TDn.põ*—:tÒÒ¨pãÆE†#>>œ éëÝ»VVñ—WT?e鱯/…ëJuLL¨¨™••ê½ïâBµ´µ)ME(d•¤¤$°, ;;;Á˜a¤¦¦"--­Vd•²xøð!6oÞŒiÓ¦áý÷ß‡ŽŽ9ÀQ)är9ÒÒÒ’’mmm4mÚT%K.—#.."‘–––hÔ¨Q1ô]¹r,Ëraïïµ¾kcãÆˆÃ0èС-Z„V…ÊÔ“'OðçŸ"** æææ˜={6†^#†D"Á7°`ÁÍ.ð åô«ZQtÙ2²L;9Ÿ}¦>/ÎÈøààý÷«ßà•æ¾–*a`€:P45;;À­[·••kkkLš4 3fÌ€T*Å•+WpøðadeeÁÁÁóçÏGOEuÚj&00YYYèÞ½»fæ¸XLÕxûöÚ¶U}M’Û¬)¯­[—]hläHòÈ6jTñg …ôÇQcÄÅÅaÇŽxþü9 `gg‡E‹¡wïÞÈËËÃáÇqñâE0 ƒöíÛcÉ’%«¼.“ÉpäÈÄÆÆbýúõœ²Z®\®_/ŠfhܘªÊ—DTG‡Ú˜G  5 o_ÕçõõÕR‚Ú-Ú§†   lÚ´ ±±±`YNNNX´hZ¶l xüø1ÜÜÜ Ìž=Æ «Õù•——‡={ö`Ñ¢E0`€FfŽúËÕ«WqüøqÄÅÅAWWýû÷Ç_|sssH¥R\ºt GŽAvv6Z´hÏ?ÿÝ©8äÉ“'8qâ~úé'n=¯Ë¤§“ü×¾}µœ®VM%‰‰‰Xµj¬­­qìØ1üý÷ßX±b233‘––†+V C‡¸téfÏžß~û ÏŸ?¯‘ñ„††‚ÇãÁÉÉ©6¿B.§Ð©ØX²"¯]KVçâ´oO¡¾Ÿ}Vþ¹x¼ÊU\­*ÑâPg¼–åâ À M8yò$Ξ=‹_~ù·o߯„ àææwwwøùùaãÆ˜;w..^¼ˆ¶mÛâÇDvvvµC&“áâÅ‹˜0aôj»ýIn.àæFÞ“¿ÿ.?­_?òš–§PFŸ’…À8jüü|lݺ111øã?páÂôèÑ?ÿü3‚‚‚pæÌüûï¿Ø¸q#Ž= ©TŠ7"_QI¼ÉÍÍņ ˆ]»vÁ¢®åÞ×E (|wíÚªGå4°jÕ*4nÜ'NœÀÑ£GÁ²,V®\‰ììl¥¬Ò¹sg\ºt ³fÍÂúõëñâEím@,ËâìÙ³ptt„««+§¬Öu (’èúuzœ› |÷0v,-\­œœZÎË—/±iÓ&8;;ãúõëØºu+ž}ŠÍ›7cþüù¸xñ"Z¶l‰ü9µ<ÎâÈårœÿüsX[[£qãÆ˜;w.‚ƒƒ!‰àíí cccLš4 úúú4hZ¶l ù>ýýýѺuë·qJ‹rJ+Cp0ðÃ@Ïik—V8?û ˜8±F®½R¤È {ÛÕüaaåêÄÏÏ&L@·nÝ  1uêT4oÞÏŸ?ǃàää„B__'N„¶¶6ž>}ZíãÈÈÈ@tt4z©ëw[X–6׊ «I¥”'Í04Ÿûô¡ªÒÛ·syh ˆ‚‚„„„àã?F«V­`bb‚ùóç#33ÑÑѸÿ>†ŠN:ÁÊÊ Ó§OGdd$"""jmŒ à ::«V­‚\.Çš5k4ת¬¾¡«KÌÊJ/yHHH@ff&æÏŸ+++ØÙÙaîܹ B~~>ž€®®.Ú·o)S¦ÀÛÛðàÁtêÔ ýû÷‡¾¾>&Ož --­‘U*Ã0¸qã®]»†uëÖ)£29êyy€·7°aÕ*(•ÄÍꑌS-S%_:ǃžž8 ò¼ŽŽ–+ZLãàÁƒÊð077Çܹsáàà |N,ƒÇãÇã!((æææÊÐ1têÔ ~Õ¤—ÄÓÓ³fÍz;…5)‰*’~ü1Uø­ |>õjìÑ£t¥Òº  µ¦QI˜¸ f¢k+ÍСCѱcG¥Å[.—C,+ÓÎ;+=ž666°³³ÃóçÏáªh;TMÜ¿vvvhü¶‚g` °bõåíÚ•6ßü|šï ëfF KH¶m#ÇŽµýÕsÔÚÚÚ˜>}:z«Â,“É —ËÁãñðâÅ |ðÁÊ×Ú·o‚‚DFF¢}5…•Gnn.Ο?+W®`ðàÁ˜;wnÉ»ªódg“áéo¡Uš7o®|®¸¬+++ØÚÚ YÅÉÉ©ÆduB__m*Êéç¨==îJÝŒϲT™~РҡîFF`LLª?B®š7oŽ9sæ(£NX–E~~¾2ÄÖßß={öTÊ*¶¶¶°µµ…¿¿? Të_mpp0öíÛ‡mÛ¶¡E‹µþù…de‘áE&£T-CCj£éåE‘p]ºÐq†Õß_²J kË–-±eËÈd•s¹5iÒDåqÓ¦M•‚Œ\.GXXöîÝ‹Q£FÁÄÄÙÙÙÐÒÒ‚vañ@333$&&–û9©©©ø÷ß1sæL•Nåм¼¼· RR€Ÿ&ÁÜܜⵡ*½:§ËiKN¦êŠ%{<ÖU¢Ü0@íÿª à)€é…czðàîß¿Q£FÕêp&zÅY–ENNŽ9‚¬¬, 2·nÝ‚®®®R™500€’’’Ê=gTTNŸ>aÆ¡Q%ò8qîÜ9,_¾üír3“*oGÿ2 ÐÅÏ!“Ñþô÷ßÔ‡»yíNž}*­¬ŠÅb}:.^¼¨‘ÏVÃÿùçtïÞ‹/.·@ysœÇãÁÙÙù­•U€ÒND"†–¬{ÁQs0 „ââŠBÏ="Ðûï®®t¯VAùlÔ¨¦OŸ®±PÛ¨¨(:t˜2e ¦M›VÁ×Pö×ÖÖÆ¨Q£ªuí•Édؾ};Z¶l‰I“&iä;zg‰¥½BG‡öÒwÚ´Q-[ìçè舱cÇ"++ë­†óƪHNNø|>ttt«6»uëÖ*%²Y–EDDÖ¬Y---¬X±ݺuSZã…B!X–…\.‡@ ˲H$Õ^(ÃÏÏqqq6lØðæ'IM%AׂþJÒ®fÆNY}g`YÉÉÉØ¾};"""0sæL¸ººÂÄÄR©B¡P% GÿVÆÁJ ‘HpäÈŒ9²~†ŒÉdE¹âææ´Wœ?O‚B·n€¢¥JÏžÀ™3ÔÎÌÒ’îϨŠvIïºè’Ö­)râÅ‹¢ûì3Í·*{Wˆ¥|S±¸(z oª³3å}WÒaRW`·o߯_ý…-Zà÷߇£££2j@¬"—ËkÝ€ÐÐPlß¾]Ó_Ù»…XL=²õõiŸPìéµÖSUVX†¯¯/Ž;WWW 0k×®U)6Àãñиqc"‚Z W¦³NCF,c÷îÝHKKæM›Ð´iSe¥F>ŸvíÚáÕ«WÊ9ýêÕ+XÖp…ç`÷îÝõ/ 83“ŠSddЂøõ×$oÞ\úØÖ­©/qq´µ+o423>ú¨ôóõLà®I’’’ðÛo¿¡U«VøòË/KÉ*ŽŽŽ AZZ,--!‘HR­²JIrssñý÷ßCKK ¿þú+Z·®/&êYY¤ ÆÄ°>`-ú_ ”4„YYiz´oLXXvìØ &à£>R*ª ²ŠD"ŽŽ’““‘œœ\íµ6Ê#;;»víÂ_|QãûG!éé4ßµµ)å±&:¼!U…··7.\ˆääd•¾zsçÎÅ™3g0{öl´hÑ¿üòK©Ö   <{ö ½zõBpp0>|¨ü+((€³³3222ððáCˆD"„††âéÓ§Õ–ƒÈ0 .]ºŒ=ºêå°Y–ò„~ÿ½á·×ˆ2<Ø6€¬ŒüÕ€`åJŠˆQ×±âÚ5`æL*–œ\ºòýûÿÉ'ùV^ç“Ì,àåsRFJ"ÒþÑô,€C‘@J€æ¾6©TŠsçΡsçÎÈÎÎÆãÇ•s<""„ŸŸŸ2‡ÚÓÓIIIÕÚåï̘1ãÍ„v™Œ~0 Ú¨k±˜œD€ÄĢȫŠ üÿÊÀ0•+ð-“ÇŽ‘ÒZH¥¤«Tæºê ééé¸vízõê…˜˜xzz*çxFF www$%%!33W®\M¶‰D8pàfÏž]ë€*ó×_TŒeâDÀ×—žÓÕ¥Årà ¯ç*k”/^Àßß_­¬"‹Ñ§O¤¦¦ÂÓÓ"‘!!!xöìFŽY#ã‘Ëå8pà±yóf´mÛ¶þeê"éé´ËdE!óÏŸS—Ÿ_Ñæd`PZY}C4ÐÝ« ÃàæÍ›x{{+ç·¢JðÀáëë‹°°0äååÁÃÃiiio™X®^½ kkëj £ç(‡¼<’ûæÍ>ýˆŽ&盡aQV*zX pàÀ´iÓ¿þú+ììì™™ ÐÓÓC§Nжm[XXXÀÍÍ :tP ‘ Gnn.-ZTêÜ·oßF“&MðþûïcïÞ½pwwGtt4 „N:UËÅæææâêÕ«øüóÏ߬¨ÃPþдi@5äòÖÁÁäž0A}$g¥ûYÀã °BZÚI,‘ÐznoO‘h“'SOø¦…meòòÈH¹s'íK–Ð} p$zx—/[¶ ! ˜~HŽëâ‘myyÀò}@ø]`г·ªÇvßA ¹øfà3ذøeCQ]m’’’‚äädãìÙ³*¯Í™3 ,@Ïž=ñÓO?ÁÎί^½Â|33³jùü€€tëÖ­”µ´Ò°,åµ}ðÁ‡æå‘ü]QZen.på ¥æUÙ–‘\ºDs£¢[7!ô€â‘[eL²HEÎh–¥(iŠÎ,™ŒîÁÎÉ#[iit]~XqçŸôt '§â±Ö4111ÈÎÎÆf5Þ¿;và½÷ÞÃÓ§O±hÑ"èëë#66+V¬€a T (|óÖ­[‰D4hPÝëËWP@Ö¹>}(*að`ú³²*ŠRÐÕ¥ Üu‚ððpdggcáÂ…¥^»wïš6mŠ÷ßüñnܸ¨¨(¸ººÖ˜Q&..÷î݃›››JšÇ ц#Ò}yò$ýâDÊC0 FµW¯C‡jF>QPPP€ˆˆ„††âË9ëÖÖÖ¸ÿ>zõê…nݺaåÊ•°µµÅëׯ«UV©±XŒ³gÏbÉ’%œqæmÉÉnÝ¢‰§n I€2„º?¼å“’R3>½*im¯^½BBB¾ÿþû2[eèèè`Ò¤Iøï¿ÿàíí­â={6>þøcµïS„MΛ7C† Á‹/кuk8::V›@ÇJÅ ªÏ§PÉ,pO§W´ê*IT ãÆ•žwR)­¿áᔎ4u*¥6•åppw§ó͘Q:õ)ö #V| lÞ ,ëAõ¥?ųgô·v- ¢Ö}[·¶¶À¾}$‹9;Óñ¶¶äM›2…î>ŸjRYZÇ“Bо=u š=›ßaÃè}þþÀÀ¦À¶¿Ý“§é†!åH/pu¢{®{aý?ÿ$Ã)Ÿoбcko±³µµÅƒÔ¾ÆãñÀçó±fÍ<{ö ±±±X¹r%llª/ˆÙÏÏ“'O~ó…oU!”aȳ>`@Å Vn.UCŸ>½â èZZäa•H*VXuui Ë–•,Ë’š“,XPþ9óó‹Ú‹UDJ Õ%غµâ6Ê™™TÈÕÕ•BçË#28|˜¢D5™2ܳgOª}ÏçƒÇãaïÞ½xüø1 ЫW/˜V¤¹¿™™™8|ø0V¯^]·z­J¥À?ÿ7oÒ‚®X +ú¡94μyó0gε¯)d•Ï>û C‡E`` Ú´iƒ¶mÛÖ˜±äüùópqq©ûÑbÇŽJÔýóõ¥ '6X¾œ ÇŒO­9bb€5Ñ6- øšBOO›6mÂÆË<ÆÐÐëÖ­ƒ¯¯/âââЫW/X—%˜VIIIʈËÇ£W¯^èÙSÃ} ë;çÏû÷SŽ 3÷ïSk±¸(Ô½šŒm2Ù}Ö®%¹¦:©’š™™ ¹\ŽÆ+f===Lœ8Qe"kiiÁÄÄ¡¡¡* +ŸÏ¯ÐRÂçóѲeK•þ­Õ…——\\\ª^ža(¦ÕʪFCµX–º DEQ:SÉ\9–¥–¯¾¾ô·x1¥#)öÈ  –W®$#âÁƒ$dý5)¤Å÷Ò¤$ 4å“r9f Ъ)Ëb1°ç 0®)Ы;ð•…YZ[“CÊÃÒ¥ä¨ϪU$¤F)¼C†}f«Vä¸kÒ„ =ýûS·âu¯¨†UÛ¶T$?Ÿ¢F Æé3z~ƤhDDÐu®˜v=Ðv† €æ†4N¨ïMíÀãñ*ôÞóxY8k)X"¡(!–Õì÷[™ÊòŠžÃ=zô@=je\ÇG@@† †¡C‡¢_¿~u/bF°lQ7³ ¿¹œŒ¥ÚÚ4Á¤RR(:w¦Çb1åiFBx5jòó)XÈË 8°zçx•Nehh@  H03fŒÊ„VTÌ«K-??÷ï߇³ÂÊ]Y†,ä?ýD1yo èÏÃHpÕÒzô "%+@§¤‚zú4)'O’±®”ØáÃÉ[eeEö¬YdÉsw/:ON)—6‘Àâ1â¸r%u)¨€d„?Ðv0OÆÈ-[H§Ù´‰”†âŽA--R4ÇŒ!㥽½êëÝ?]»RxpïÞêo<>Ÿ”âaÃÈø¹{70n4¨uMKÀPôëÌK÷àÖ­€¹!€æ…'Èp“dWW`À€ …•ë\ß ƒ®®n™Ñe"Ñɲe†U¸"ärR¨*‘GG¡³çÎUnˆúúÀñã›’BŠâ³gÛ¡Õš©èÚ<=Ɉ"S(|yøù‘®Ò¼yÅç•J©Í­Ž…2—Ç‹ä Øºµry¿ï/_¾Ä•+Wðí·ßÖ ïªL:D ¢@@¬KNYåx#¤R)ÜÜÜ0yòäZ¯|]¬ŽfÝÅ×AS~FøËÄ$éP-€Æ?þ Ï„ EÎ>@Ö°ÉXû—m™2Xqd²ÊS²O•Ó‚WIp0HÇj¨‹M%==ÞÞÞXµjf̘ñãÇ×Zøq]'#(ë¾ÏBrd^Ù±,…#®[¬YS¤¯LJ‚·Bs44¤ç† !cj5ïMwï’îYýrJ•V[[[èèèàñãÇ–1Eëš×¯_¿}Èj$((úúúpppÃÙÙ@nZØ“§HÂ}õJ½&ùâiK—¾eR(¡ˆSWèåΞgÍ"£ß¶m¤\tüùó¤8êë“#¬kWÒ£Ÿ<¡¼ˆŒ Õü:¡ÂÑ?ÿœ¼­ýE æÙ³&<ÚÐò "%´CšëçÏŸ8 X.m€ß~#%°}{ÚÔѯ)ÒUµ €PÖäæèÀ€/€’úg8€ÌÂÿ·U7®GElª‹»wïÂÅÅAó³ÃÂhûôSµÉ¤,KÂKXXŧÊË£E*#£âcE"ŠRéÐ ™™d 14,ª®^¹¹”S›[¾À!“‘býŤ8—Wø(&† 2£FQ°…¢>‡:(:BG‡ïò ãNDµj.o ÙÙä‘'£YäÇ_cù±U&6–~ÌAƒ4=Ž@bb"^¼xAµ<Ÿ h¯ŒbWkܼ ,ZD vp0=gjŠø‘sÐÂ¥1nz­÷úúä5mÖL%…ëõkZ“+2:´Æþûoå†váÕKËÎ.ÿ8mmŠ.sv®Üù®À²,îÝ»‡Ö­[—*ÖúÎ!ÑDRÜ|OŸâõáï“ÄÄÎå/¨‚ïòåv)“‘ðpê  ’wKÄÄguÈ"ý¥º¨’Âjmm¡C‡âäÉ“¸|ù2Äb±Êë ÃÀÇÇ¿þú+œœœª­XÒÛ²,¼½½Ñ½{wܹCÅUG"öú ²|H.ôâé0ƒQHáÁƒ¤,´hQºí—™ðÞ{¤vî\öçëèÐ"¹z5)Æ: æU(=–<б#0u"H1Tü|)*îòV„¸ŽÒÞSŽSRX›(éݺêÓ úÄx§ˆ/,xÓ ·nUâ ,‹ÜˆddG¤Vx(ÃÐÜ+¢®Ž„ª)óñLJƆÒ}acS~»™ŒîY++r—§°FEQÀ„Ž%þ—7æòîÚØ°QVH®LFQ mÚPÕ_cc”iÈÉ¡(„V­È¨ãáQö÷H ­‘¢ÞŸ)u„…‘2ÀååEäw†apòäIŒ=ºÆ T 33ÊéààxKd2ø€<‰íƵÂÌs!Ó5Bv6¬;ÓäzøÖ×— æå¥I(xøÅí#1gZÛž>%¯›[‘”mhˆÌùËÞ¸?›ôDRVÙ‡B±äó©æEy·Ÿ¢Bÿþ´”}“žNNWWú.Ê«/MeFF¹æåUöšo`@)¶Eʼ|Yq$Ò»Àµk×àìì cMöú© †R ørü^½¢çY–„Ž´´¢È6€Â&»v%KIaîun.ÍÅÎɧ–—WþG†„P½™‚JDT¾·ü‰À÷ßSý//õF‘ˆî>Ÿ"⎭8B¡*¼‘F©¯¯Q£FaÆ 8{ö,îÝ»‡+W®`ÿþýøüóÏa¯éFňÖ¯/À„ úصKýúÚZä·6³ÖƲe4—¢âµ?üc¤Gå {ë~_ŒÀT+\¾L¹Ÿ7nT>_±±äálj ™Œ#ë×SèìáÃdmëÒ¥ôû5"o•±q5ó’È)ˆá%^“È…×¢ðÿ/jèR @eè5h¦ $H*ñz/Š)§@@7uCÃÇÇÎÎÎHMå)#Ipâõw)I~>ä¿o‡?¯ üó*®ÆÍãÑÜý⋊Cw³³ÉÛ¾}ù Uv6)‹Íš‘GÖϯl+¶¯o‘ÀЭ[ù ìÝ»Eżڷ§…^݆”YccZ\ (»HS|¼jÅî&M€#GÔoúú”? Ðþ3~9­ËFFôÜ®]À?–ncCß3-rË–©­‡óæˆA!¿F …°8|ݘ>ÖG)/l•A}¸¯‚'Æ ´÷ pdkÂÚ¥•Ñ»(*ØÄ£ï÷]󰆇‡£eË–07çáåK Íû5i9êÚCikƒ™;Ù]ÀÐZ•G|<)\éé;ÌÌÈÓ¥ ý[V¡èhj¤¥EÑ-yyekeEÊ-@ aYB”DBʬB lÖŒ¬ØêBgsr(’FQɺ];RÕ¥±ÇÅ©ê!vvtßúø¨*Ù,KÅò^½è¾Þ»WõØâ¡À „BR†÷ìQÍʼn(Š¢¸Üª«Kùænn@NNÝZskƒëׯcĈµÅòtC8@‹:@çàAªfÇ[â¨rrrZëÅ–RÖ.]¢µ©¢èv‰„ãéÓIv@‘ß|Cž¥b9 óAó÷»bÞ:$ŠLèIZ UÂ=<(edȪspåŠzƒfn.ÙdY–ÖÇ^½Ê®PŸžNÇéëÓžblL{: H©ÕÑ¡š‡‘ÒªwwZ¯mß\\èrJzeƒ‚ÈÁ¦¨3¢¥EÊvttµóÕ+X–Å­[·Ð¡CØÚÚÖêg¿~Mm$+¥”ž^tðÙ³Ô¼}ÇŽ"ÍPá¾ÿ} ¡äóiB˜˜GÊÈH}‘™ ˆŠ"%•ϧy¦ØvÔ!“Q'…Þ½+®ZG÷x÷îGRDF’ÒlkKúµ““úh0Ed†B 8ð.¹LêFÌn !Û·ç@,~Š>Šx:€L‚ £ü&§N¥?77àø†˜ýsSü²šY³È82}:ÏmmÉÂpü8y„ʲ¸Éå´þó÷í£ÉÖÁ¤lÅV4òÒ(B«D:Šr;K ÊíÊ -¾¸"%ЀÞN ¼ ,oP:P(ï5¯w (ºÙ@áþ!ÈÛúU NNNF\\Ú´iƒÀ@àË/Y¤Ü|NÉÍ­ZQoh(-²žž4[µF¿~´±zy•þ/hÝíÙ“ @eÍ{©”¼~ºº¤|]¼XvT‚ž0iýßÖ–BÚËòÞž=[tssjY£NÐHHXPÇS´!ûõ×Ò¡Ì11ªa[ÚÚ´ÿõWiá!6V5ºAK‹â?þPUže2º†’)ïC†’{ï^‘ÐUP@‹{I%½kWR²*zN.§H¡âÑR<Y:§MãÃÏÏ 2Y5î uœÇCWW·vʧ§“Cá"¿s‡\."QQ,»ŽN=hXÉQŸxýú5´´´j]ˆhMrq¡5ëÆ VË"ïÖ#ôɹŽNî[qñ` °íÛÿûy•ÆŒQJ¯i°@?Wm4kFž²ÒK†Öð1cHpv&¥º°ÜgÏh½U ·²"Ç‚º¼9Ej‰¢ûÕ'ŸÐÞ¦.(âêUÕÛú·ß(òåÚ5U!]a$mÓ¦è9Z"vìPõ†1 0{vÑcÅžjelØ`€üüwo ÉÎÎÆ¹sçðþûï×úg¿xQ¢D^#ýý‹&[V°r%¼/Å“¶ ?'Ò&½s'E$ÔtéBVžÆ+Ñ0•¼•_|K&+ªOÓ»7É-eÕ¯ÈÈ ¯¯¾¢2õDZ,Íe¹œºˆøø”m4‘J)X¯¸ü1jùBJ:;üýÉa ¸ôîÝÉØT¼­æÛРïÛ·“pôîm½âý%_¾$é´ð[åóiMÕÑ¡9'Òc… ÝÖÕ•ª kkS˜U«èGVr9Íç5kh½ÎΦ¯kW*ü¥  3Ô|#€”D¨WÞ¢@Œ,AJ`qK‰6€Q(ò°€Ú7UXY/Ü,c,1 0ÞÖ jÀ%¢}ÅÆg U…Ÿ…++~^€”snÀ<þ;w†±±1¤R "‚/Óá´rñx´k._N+”¥%Z„Μ¡ùYQŽAR)löö:[–'T,¦üÎF诸¨$¥sðxt¯©ËyÍϧñ)êðxtŸ>\z‘ÏÈ(Ý*yÄ’Ÿ”ÖÿBÒÓ‹0(ÄÑ‘”ËÿUµæ[[“á´866¤XîÝ[$x±,…y• Ý·´¤qìØQd¥gò”ŒªàñÈxÆ0¤±,)¶bqéu>˜8‘E‹o‘«PÏH$8{ö,&MšíšîmêïOM£Ïž-ry÷íKÞÕ… Õ‡Äp”‹\^quÖw†apåʸººB_ÑC´šPt¿(”2èñY9dÉXȲ´¸»S.^áâ#³E”®#Ú,¹1ð²Zji©í¡¡d¨kÝš”´² ¥2)ŒŠqÚØÀîî^zìÖÖ¤Ø*>¦cG²%EE•>ÖË‹œ]ÅíÜ™ÅÍÉ!a¼xWÆæÍ©æÓ_Qçr995JÃ41¡÷ääйY––‘’câñho±°0FPÐÛ÷¬oxzzÂÞÞ-[VœšTm°, “ÁïqbÃDHM)üQ®\!×®¢2üúúÀ¬YðpY†»®k ×)¼…Bšã «x1äòŠï1€"öï§ú4sçRTº÷½xQbkaAJ :ƒ Ë’#íÅ ºgΤ{Y]Ž´DBvØ=ÈaàêJrTJÇ_'rsIÏ)ÞZ £Ò‰ªçíÖô††Ô‰*, ˆˆx{£zƒUX³²Èåíê„V­T_üì3õ £ÀãÑ4y2 ÌÆQøÞ•+T@eÕ* Sïߟ,isæ“«wïBa3äaeÔFÓèG¼¡>ÌÖ¤<ëÈ-qL€‹=€¼°oêµÌ Rž#Õ¼ZxîÆ:AU™Ïà ò¢ä=m"6¤ð>=j£o` …}­ZUd1ÑÕUÍ~Çð÷/?|19¹lÏ™LFF›C‡¸B3åqÿþ}„††büøñÕz^™ŒRæÊ+ ѯÄ<…`Ýj¸ùãÜ9€ÉÉ¥ö~ÑÂYx0M›cÔçöÐíÚóè *ªìK™ŒÖK¡öžW¯Ôj’É(ªE)£¥E£FJWg?vLõffÔêïÈUϰ\N{Hq½H‘Ëš›«Ú&ÌÏ‘LLT?«];ÒeââhïQ„_Êd¥Ãuu)2tÍ QNN¦kjÞ¼ôõ $£cÇ7½«ÇdeeáÌ™3øòË/¡«ØSS)L©&­ZùùÈß°ooÃo]N#:¼Pø™2…R;þú«(zF(„¬e[dk™C&çU*%pß>JªHi}þœ¶•íÛ)rÓÓS}}ް°¢-GOŒ×aaêÏéçGz€þ½~½H&+N^E´mK{ö$CÏöí$§¬][´ÎÖÂBõ..ädP„‹D9QÒŽÛ¢©[{ö4EZšé[ýt Va}ò„¬ IIah«øUtèðÖ ¡B!ÍéqãHðܾtO?¥EPmû PØk;Ô¼PRŸC}å]²ÚÔ.¦xèp<È ¬ðZê‚zŸ–'dD€ru°zø®ðº‹ßÈ H¹Täø;&ä)V _8.Ek>€?/r^ß¡(33ñññèØ®d¯"ñÈ-]ÂΠK—‚ƒ™™Ê®êåEá(ºº¤•Uy—e)´]_ŸÍQ£Ê®™œ¬6Ò¸1-Ü%™Œ”UÅ 00p`éÙÙôW\ (äêéSÕ¢ qqdT*)<(r±N*RÌ_¾,mè?ÿœ”Ô´4ºþAƒÊ.xÖ·/ûâ}¾…EÙ-8É€»y3)Å%—¥â´jEyëG’PT‡êØiwwwôíÛ·f Ñ0 MÚ3Èœ]GÃ}Y–„„‹É£$•/$)œd©©äù)i¤*( e35•šŒŒ¢{½ €B"¿þšÖƒ²<_}üþ;½·ä1ÏŸÐ9ßÝ ×呟ŸãÇcêÔ©¥#¤RÒ®ÞP˜OH õøòåÂS°,…š¼xAŠh¡¥¡àu<ÚéF‚? ¬»ØÂÇH’¶öÓO´˜.²žžE¿s‡ddSך‹aȰ§˜s­Z‘pîî^Úx‘žNFÊ₯¡!ÍYE6—âœmÛªÖÈ`Ø®J½'$$RÚ¸±ê±::U³{7í3 Cs³CõßaãÆÀ¼y”òü9)Áeq¶µ¥t²ß~£½vÊ”²;9èêÊ¡­ýnÝ<€®®.ZµjE_üóçT†öÆ¢Å!3“~‰¤âÅM"¡…JÑ[ ð¤õëI ûóOzN(DDû1xÜç´Y7 'þÑ.·ÂuD­¯ff´—wû¥¥‘AîÞ½ò;*(r¿'N$™ÅÞžæ’»{éóËdE÷‚@@‘`ÉÉ¥{³,Q``@[ØîÝd*þõyxL§ˆ2³²¢y=j9ÛÚ·§‚Žr9Ý·ººE^^––ÀК’‘A_ýôé¥ =<9$¾ø"zzo×o²nîÄÕ@V…j$$Ä£Y³fô ¿~M3©š*9 ´XΛG!Â}4)kÍa@ù•Îúr.«±?Q)^‚ªîÚ”ÖâÈ@-bƒ¼§¹Põøj(ž&f*O¼àtǼyV[8Õ¢I (,Y~ÓäaUÜ\Y…ß[qlAy¶yW»”x½ €“ ïr'%%úúú0ÊËCøºc°ÐVK>ÂãÇåSŠŠ¢ER_ŸÀ²„Ç”RØLMi¾ë訆DÇÐ&;“a§dò¿HDFžâ6#ŽT² €TJ–ðâJ(GŠaÇŽE‹*@Š·ŽNéÔ>Ÿ‚*Œéü2YQ›u @Ô+W’R|ꔲÂ|)lmÉkt÷.íµíÚ(‰PH×8v,¥¢ 33GçÎÊHîwšÔÔTxzzb̘15[lÉ׷ΔîÌË£ðù‚‚Ò‚Ìë×dÔ¸qƒ†ûí·tìÙ³4Kz£â⨀åÒ¥d`=z”RW‚ƒ)bùrR–/§mrÅ r._¿N÷ÐPJÙ SÍc—Ë)|ÝÃøòKÒñwîT-R“ŸOÖÿÕ«i=Ù³§ôº •’2µcÕ‹‹Š"a±2áu ooo0 ƒ%{}…‡SÒå+€IDAT5ÝÅ‹KU†+^¨´<^…ÈñˬpH"â˜XXåzÓ&äÔ։|tZ= >:M¬Ð¦ žÁSkä *2Rêê’óU]Ñ£ÄD:½"PÁÀ€æŠ",²¸ÂpïyeJ®£'Òý ¸ÖèhºJ¦v”Vñò%y`ÅbŠè)kÉhßžöÀ_¥âš99å·Z33£ûáüyš§Šk*‰@@;¿üBB}XX¥Òߎ=Š3fЃœàôi`Ö,jG ˜k›6QZÆÆE Fr2M’Šb¿e2*B³iUVÚh?ø€þ@(D¸¶#Z9éÂÞA€>}ŠU¸VËd£™5‹æTydž„ÐúÚ­­eåš&$¨xŠú…³+‰hÿ/Ž;z4éð[¶¨*Å C ¢-¹BQTàQ Ýwýú½—Ç+’Oºt¡5úÞ=ºÇ$ZÓKÂç“,ãïOY2'N”ïÎç-ZäA_¿‚¾ˆÐ ËKŠÅôu艌Œ ØY[ÓêB&®Nª5¬K(,¶–å–üó@^Í÷@Êê#@žÀ7%¤Lª¦_ŽÁTÔˆ…ËäA yQòn/=ý@q÷ad)ʲB¸òlf”á⤂àÆ…çÈBQßT€/H‘HÙ¼[ø}L*mJœÏÀÂç“ ÏW=K ¯Q»ð< ”/^ÀÁÁºà}³33t¡¥ÏC—.åoŽ––äñÓÖ.&ÕÕ÷ˆŽ¦iæLzìèH™LU ËI¦*ž·ª­M»vQÑ2…Ò'—“\±¬ E úœŸ¦EßÐ,–¶¶ê-Óƒ‘¬µs'‚¢–%12"ëá¶m¤ì>x@!ýêhÑŸ6¼JíÚ•í5hœL …ÚÈŠbðx´øwíZ9Ç]ãÆ´_Wk…ðz˲¸vízôèAÈšäþ}Õ~C5ÃqÕØXÕ(SP@¸¢ê´"ç»IºÇ="/•«+Ík–%Á;+‹¶9–%ÅáƒÈrŸžNúÎòåôY CÂTP®‰Ž&k|Û¶$ÈÓ $áfØ0zldD÷þ/¿\XP@JåßEN3 m¯’Ô·/7-î%¡òšví¢ÍîÝi-ðô¤5ÂØ˜,ö!!äј2E¾¾VøøãZùI4Fzz:þúë/|ûí·0*™WM_Ö¤IEiJ ²ã²ñõWv5V€EK´ ¥Å#ë"ñmÂÀÒÌx­JÀð¯!±èŠ£Gãûïà/[F?V±6<¼H@åñè·W×JƒaèmŠè--š;Ë—õÌVìAùù´_Çíì€Áƒ©6Óîݤ§èèÐ\-nøT £CsyÇ2&%•ÞCÍ¿|9 Ü¥=± ´´hl©©T÷$:ºtøcIììèZ/\¨xmvt¤qŠDu6X£Öyüø1LMMÑÍɉ,UFFÔ_²¤eø›oh¡’HŠ,ééäŠÌΦ¸Ô¦M•m3Rå¸|C “ -(@ÐÞ¾TxÃÐï¡Uõ"JËLR)íýãÆE_ùù©¦3)È̤|TÅü‰!/»v´¦W9¢£‹úñ*ÐÖ¦[öäI2Dòù´ö¿|YÚx3f Ù­$c¼–ëàPú+tv¦¹·{7½þê]çG•ýûX[Sç’U«èÞ7OýqZZd(%TYÇU Raõñ¡…-:Ú íÛ·‡Q£F”PZÓd€ªï^Ai…URÊ‚o_¼]Èj.€õšøRÍgé RW‚Âf^š¨*¹ýd¾O ¤ð_„uAJxp±s¨|á…ŸÃð'€K¼~ÀÇ ¼Ùé…ß‘Â*É‚”T«bŸ ¤h¦¡¨ø“‚Ž BLA ­ºpÉÆ6ÂN¢s7@B<=1ªIðy<Ü~l##ZèÒÒhS§„æçÓ=~<-\66EJ’‘¡ºy·jEá#))ªçf2•TìÚµ#EÔߟ¬ŽÚÚtÔ>V [Ò¡C”#þÙgEÖzuÊ·Ž)¸[·’u¼eKõ]|X[Ó¼a ;ê,ó ø|RÌÌ*nûІ´hQå~3>¿j‚Ë;œ2©$''<ÀÂ… k¾•MPUX©®_'/ç AÔ–ÏБãÇéþ]·Žî3™Œ”ÇW¯(äÊÞžòŽŠËbŠbŠN(ÿýGÑp¿þJžáÃéþ-NÉÇűµU¿~tïN èÿQèèÑ$ )BÆ};t ãÖwßÑ}ýÙgE½£#mÉ÷Oº?K¦m„‡‹RNÍÂýû÷amm®Å«–¼~M‹Z—.¥C2BC‘~ôºñâñ¿v˜ýi˜™óÈ•niI‚|á’gßg:¢õ‡ãÐQHØ<õzöTM8“J)üP‘kÉãÑÚvù2ýîÅÎÄDú‹Ï[[2ÞíÞM^|Å»?…Þ–ÄÆ†ò<÷ï§h™^½È9¦n^òùr˜@‘ÉÉ¥C|‹ciIé^^t|yë³¶6ëƒHǯL­«!CÈóVž1SAY†Ôw‘¼¼<>|_|ò Ž!넳³zk¯¥eéð"GGrq—¤ysd²€w`z¼äêêIк5>=îÙ“Š'~øaiHV#RÜzt¬ºôòœZÇ,,h> J¡ã§OÓ}Ò©Ío==:vʔҩNÓ¦‘Œ’–F— ~+21¡°ë×ÉùüÑGä“ëÛ·´lÁçÓXzô h×®ê×õ’XYÑwSVº˜==²ïî߯šV48…•aèÇ7ðó|‚9~~Tªº¼•­ºˆy-£AŠVqOc"H±+lå,P[»ª|@1’@½M¯ U/d€{( =ž ÕÂD \Z& –3CØ€¼–½J|^{tå¼*¿pP¸ðP.>)œŠøÂëTV¬-ü×ä] C‘"o`€s~%•d3óA^Ý|§º$F¦Öû¬‘Ó/ ‘‚‚XܹƒÎ3g<š5£E‘ϧ…7 @µb›‘ˆŦܾ½úÚŠê†%óyfÏ&¥oÅŠ¢·¤(Rû€eËHñ;–”ÝÔTõ–i¡,”GŽ@vËÂÜœ,aa"3yrùß™®.Yç•ô*¢sg®@L]ÀßßZZZp¨ ÉoÁÕ>oÃ3àÎ’ÅRRH—°·§ûôÔ)R~þ™Êÿþ#¥IR»u#€Ç#¨gOú*W3päHšã‡“b¸m[õ}E£FQm’Å‹)4_]„¹9y®FŽ,ʯRÀçÓWܺ5°„²#BLMå07/@CçÊ•+˜©e‘É(NûéSJ‚T³X²}úâšoOŒÇ 1U ‘Q<˜™ƒ$ïÄeèÃç%0‰O§êÚ•rwïV5HFF’ǽøïÙ£Í-"Ϻ¢wux¸úpíþýI ¾x‘ä0==ÚCJ¹S`lLž™mÛ(¬¼ œŸZ($§[TEžüôSùß©™yqss+gøãó+ßBP(¬ØËQš'Ož@^P€NÿþK¨S§r/( ÃÃܹå‹ñ2…¦ÎœIµ{÷Èi[2õ‡Ç£ù¨È µ·'ï{rré–t C2‹¢è£ƒÈ?ù„"ŠG?N—¢¸wììh~æçÓ·s']®³3)—êæ®©)Ýg¿ÿNF¿HÙT‡‘)Î::tßœ9S §SÓªÕšåói)©¬üSu6\€Bv6¥ µoŸ‹¾¾°ëÒ¥öÀÒ@žHÒZœ\¥0˜€µòˆ…ýª#ÀûFƒrD‹#(ƒÂJ˜ à|±×³ ª°äUäÁ„¡t ›¶†•8 Ç— ò›ø¤ðZY,¨]b¿µÐTÝ—kꎢpe€) Pé â’ox Pçæö£(d¹ä1ƒœ~9à± 3q$Úã ˜6 ¹‡‘Êã‘Ð[V5Ï’U~[·¦M¡dØË’¿dq¢V­ÈºìéYÔZF,¦PuŒ¶6å?NBLx8…Ô¨Sc_²„6ˆˆ²C¹(½–.­\§õ!ge¡ÕàÌzõS§NaìØ±ÕÞæC-]»¾õ.“‘ëVº·ŒŒH±ëÕ‹ F$¸ŒAs÷“O(ºÍÕ•¢>]]U[p¼ ::E•çÏ/Š$­Z¶$£UI¯[Iø|dÔUGèútui-x—Ã%SSS‘žžŽN áÝË‹,ÅÝÒ%È/à!0T¶º÷¾Žç!3SýùCBT®è޼ׇ«W:4R  Pqò.) '%&ª_G…¢viÿüCJîÇå‡ÎSh¡¥e‘B\B!Í¿]»TsûÊBG‡¼Y—£v8þ<ƾ“Y›+XÓCCÉ€]V˜‚èh:¦S'RnMLÈëW’ôt2x(¼&&E9§%óS=<èósW åõý÷I©ô.¬“’šJ‘1Å pñxtiææ¤h/^L÷áÑ£dÄ++÷ÙޞƯU.«@kï¸q´—|ò‰úB’oƒŽNÝŠðjp¢Xn. Ù¡0 ïСêKcAʘ.J€ÿÌ…£z(îÝJ*|¬Ò;ð/ç³d~àò4–ä<Ès:À&PX¯Â2èWxî÷ w°µðÿr‚[2¯=€5v€”HS5ŸÙ½p,½PTÕ7äåÔ.vž•~…â&ƒëâ …3Pøö-ñº.€ávðkRÇ@PøqY Õ= F‚†—ÄÊ0 îúù¡õ¤IhÚ¤ 2’IÆV,½z•îIª 6VU™Uô~ú”eÅí²E!aÅ Éê¸a " ç§TZvg×®dý¼}›Rá8e¡­M‹öGU.äJK«BC-G=åÑ£G‰D>|x͘¢XG%v~‘ˆÒOΜ¡{¢_¿¢\¨¬,ºÿ–.%Lq@¹Àã=Ïã‘ð]¼*˜š’’Á]ê. ÃàÈ‘#×»7L µAÏä–Л¹][—ãPP@k³•É<]º ®ÎÐÁã‘W\a im=q‚Úp|þ9=¯¥E{@I„Bªý¿ÿÑ{Z¶¤˜²*äSTM~>)óó+6¾Ñš_x¼ÒÞ0Ž:ŽH„¸Ó§QÁcÆ@"Ô‡–¯\¯Ã"úçŸÖ­­MÊ™:¢¢hî*ä…åËIÖps£y¥0ûúÒ|.nhëÕ‹³£GiW´¢|þœŒó%çî¸q™öø1Ý?“ZÞ¶acCF¢?&ãLY^|>|Z¶¤è†Ê(¡-ZÔ|þh] ÁÙ4ýüÈB‘P w°•ï¨ rP*abåfö)|\<í&ä)TL|ëÂçÔU@dAUw[€ò?ƒKUøÞ¶ ðØæ…Ÿ­8æHÑU)-@!ÃA åÒE—t)À¿€Hu¡¶ bF»QäE} м¹M@ùªg Ç~CÍ56° ¤n ®†Šeá1y(*ÐT’ƾBQ8ñ;DvVžî°k:ËRþ„baÈãÎã™]:|cÖ, ¡ùë/ò–*„êôtõ6>Ÿ’ìÛ´!8 €Š¶”¥\òx¤ÌJ¹%å•|W è?Ïñî"“Épùòe 6 ‚ÊÄp¿ > æ¹?äò¢&ê Cÿ—Ëé±\NʦM-°x1)¦C‡R8×ĉ¤ lÜHBµ:åÏ¯Š¡ŠpâwÙ{Y×IMMÅ£‡1. ¼à`H¥À–£6Øuµ²sÊž$IIäµ75¥ß¹kWZ‹ccU×}‰„ö‚’ykZZ”Iž¤Ü\Šš)«m‡ž9|íì¨uAAù!±ZZ¤„~ð) •™ï¦¦å×ਧ°,ØòØóñÇ000ÀððòeùoKL¤ðÙ¨g|D„úžñ2¥ùô-æüÐҢȀ¤$JÇPÜ T[£d“3Ú±ƒŒ-"­ßÅÛï)P(•³fQ(û’%”ŽTÑ··§ÈEòàóK÷•¯èø†Nƒ³»Þ¿ŒtŠÂÑsû1sÞ<*Б¢ž¢oC"Èsê`/T•¾(P~ªBÑr,§{\\ð7…ü”ÉâÛ…ãå•÷:êƒÍE ÜR?cJ\À8—v€¯ËøzƒÐ_@áÏÿX"E\ ä½µyl]Qä-Nsâ»êCzQø}ý…"ï-‘–†äU«`fl ûBÍ3%E5ÌÜœ„æ„„Òyææd¹+Ž­-å{¬YC ðèÑ´X—±cjJ9j¹¹´;:Vz÷Fx8 ÎŽŽäUzÿ}õa×^^äMUxÏ©(Ñ·ßRA«¶m);!¼FŠ<¼â4mJ2¿ýFk¸PH5 ÊBK‹Ÿêbp¼uNa‰Dxòä `ooÂØØ¼J˜çòò€”‰pøÌxèÝ»7` €± ¼Î7µBäøÀfÿ8R… îT•ÄᎃC]P‹•÷нnà;Pè¬HUlJ÷@žÚ¦ å“à2ŠÊ3¾/v.mWó((74¥•D-PîPß ‡ ÷­(´ ¨í'HiWWÅ©ð»z\ÎwnUø”GY–Evv6ÜÝÝ‘˜˜ˆN:¡{÷î•ÏÍ“ËÁž8‡×¯cüþýÐ),kWPPÚº÷ì-ä%­twîÐ"[2¤ÊÐ*Ï¥¦Rޱq‘•¼< ÉÂX^ómŽw†a˜˜ˆëׯC.—£{÷îprr‚°Š©r¹×®]Cÿþýa®NÚ~X–,ç CVy–¥}ãõk =…©¬šö²Å{3¨€…XLBù A”Ï“ŸOÆ!©”<ÞuòòòðäɼxñÍ›7Ç€*-«(`Y<<0pÌ`áBÈ:8ž¢e:w&ïR³f$œ_ÃåršÃÅsHš§ŽŽ´ö¯XA‚zhhùÅjôõ©ðWD½¯2J¨¡¡jGކ˲ÈÊÊÂÍ›7‘’’‚N:¡[·nU®#À²,B££qÀÜ_}õ´´´±?…¡gdPXmß¾êÃÿ%ã PÔ~èâER\_¼ µø›o(5©}{õF##R>ïÝ£÷ùû—ÝIñ9NNä ÍËÓô¯ÀQœ:§°nذ>>>èÕ«=z„›7obõêÕ0+YêK Àú‡ð¿£·1íßa 3 j³BпŽPß–EA>€Kz ´öT¬¨€/@‚AÕnóAáÂÅó9:ªçnålÆ£tÏÕÆ ÏçjÒÛû€ÏA ¤ä=õðmáç·‡ªw—ªÒÛTí7êslM@EšQvoRr_üÂq؃<ºeEêÙC}Ë™’cz‡ÈÈÈÀÒ¥K!‰Ð¦Mlذ...øñÇ+w‚¬,ýý7^tïŽÙ(ŸNL,æâäD}⌌H(éÒ…cGDz‹ Ó߯”‡Z¹ü7•^Äï4ÁÁÁX¹r%,--ѨQ#œ:u ,À{ï½W¥óx{{ãúõë8pàÀ[…+ ŠÉåÔ¾Ïà Y(*U7iB «S·ŒWgÑÖ.ÊÉVÈh††µWãn³~ýzøùù¡gÏžðôô„»»;V­Z…F•©üVÈ£Gð:2_þþ;`b‚¬4ªjÚ¥ ͵e˨5†¯/yˆÚ¶¥5>4”„tuÝúllȃ4lãá¬^]þ8„BJ暴âØ „´´4,]ºb±­[·Æúõë1pà@,[¶¬ò'‘É—–†ínn1{6š5oŽøxzÉÙ™Œ,»vQþé!f«#²²(Õ¨xp…EQ@V) ÇŽQq¥?ÿ,;/´m[ú£ëª\‡#£ÊWŒæ¨ê”ÂOOO,]ºC† Att4æÌ™ŒW×ø¨$ "E1ÈŸ<w!e±Èûøäñ[ õáÁ e5 T(¨(¯S¡Py¡¨%>€‘ ó+<¨i%Ϋ `€GPº*¯[ç3 þªò¬–,$ä Õõ…«Ëí3…é–Q>yc+ºY)„xó¶<ï(·oßFll,vïÞ ¸»»ã×_Å´iÓв¼&¢…Hutp¬m[ 6Måy*Pœ#(Œ&*Šúu…†çΑ T™6“&&Em488*ƒ\.ÇéÓ§abb‚M›6AWWÀ©S§Ð§OXW²Tmvv6víÚ…/¿ü²Ò ËR>^F…tùúRï€d]>œ¼GßO¡bA‰âI¡«Nm‹u<~ü?üð\]]‰yóæÁÓÓcÆŒ©Ô9²==!úî;¬Ü·–…VK—h›ÊffTýóâÅ¢¶]¡¡d4©¨@—–Íý.]*×W”ƒ£8·nÝBBBþøãØÛÛãúõëØ¸q#¦L™‚•©'“Aþ÷ßxpò$̺wǰaTéóìY2˜+¼œsçRÞµ¢í˰a¤˜FDP=€²|U&&.ŸšJ :v¬ÜuUS°‡¨S;s@@lllУGØÙÙ¡wïÞxüøq¥Ö|¹n",h·º;u)—r8ÈSÙ@8€  ^£ eKRVÿúT0i+€ÿz™Ú‚zª*ºy ¼ÓM 0n ïhI“>ÈÙ @*ÊÆ¬ðo¨:°¥ó6ù ì„ ¾”Ê¡q|}}ѳgO4mÚ]»v…|||*¥°fŠDˆeYô(Ô$sr¨°irré…]Ñ ½qc 1“Ë©'W$qpT' ÃÀ××3fÌ€Iá$:t(._¾ŒðððJ)¬"‘k׮ŠAƒàª®d©HHÎÒAZDBKNåUÇÄ»fÁÅ6 “»²hëÜsæÞqqärMP“¶Å}%%Q2ósp”ƒ¿¿?ìììн{w4iÒ={öÄãÇ+¥°¼~ôï¿GË™3a_Ø·"-Š#mÚTtœ@@Âý×…5%Âé]ãÆdŒ¬n­çxS|}}Ñ»wo4iÒÝ»w‡­­-ž>}Z)…U~û6žnØ€—£Gcùòå000€HDËlñ9nlLá¼»v‘á=;›–ã‚ê&PQ1! òÎr4|ê”ÂúúõkÀ´°LœP(D«V­påÊ•J½_[[«´W¡IR`(lµx1 É \Ы ‚GSœ,üW à—ÔÀO ü×\PÕÝ.(í™5…á¶/<Y7V£Â¿ HÉH† !êw|¥ŸŸ´µµÑ^]‰µw˜ÐÐP¸ººB»Ð­cnnKKKWêýzz`nþ;–-3‡PHE_.]¢ÒŠŠ šïEˆÜÜ\Ê/¯ç\¸pƒ†aY½|ÞAX–Å«W¯Ð´X‚´ƒƒÄb1â±`îˆn·üÑó~$R¼¢€uë“àÒ%x¸"Ũš n ìNpí„ü{Þ°O€¾!]·akèÞ÷Žï§DÕÜi€""aß> 0¤ø%K(68 €’œòòŠ¦Þ‚;wî yóæpppxësiš'N`ÆŒšFãÕ«W044Te´µµÑ²eK¸»»WêýW‚pßÃ0z$ZÑ‚\NÓpäÈòÛµÔDë£7áÒ¥KèÕ«¬ª»ñ£àæ¸zBCC1bÄeí XXX $$¤Rï?~.W,wÀ8×—/"<œ"\&O.Ý¥ h—Êaj©T wwwôèÑCýP_‰ŠŠBll,\\\4=”·¦N)¬r¹<*ûàñxÐÒÒB^9™Ï<999Ø¿?š5k­ÖZä}Zø§§Â¿dPj"(Ìöl9ƒ )ü«ArssäääšoáPÃÄÆÆBKK ¾¾¾ù|EÁ€„„Lš4éíOXMÈd2ðù|ea@@‘HTæ{„B!âââ°mÛ67‚,,(¿‚e©'jp0ýÕu ‹¦é¡¼5HIIQ¾ªmär9ÒÒÒ‘‘~u¨Š\.WY¿„B!är9Äbq™ïÑÓÓãGHmpßì7ìÏÖƒeb6Œ~º‹ÄDÖÖ"„Û6½½l#ôlë±àRAR~ôã›E'UDåH¥ÀßÓÿ‹'3={F0¡0tåúõ·¾þÐÐP˜››W[¡(Mâãã¹\®Ñ1DEEiúk(Å›È*,ËâÁƒÈÌÌDZ¦>Ò› Ïý±±´–;8GT1Uë2/^¼@LL Œ@’Ÿ¦ç¸L&Cxx8ÚÔ±bu² ŸÏ/WV‘H$8wî¤ÏƒVódèèþ‹øx Q×Ң̋ãÇ5}uå#—Ë‚¨¨¨zoNOOGff&"""46‘H„¨¨(eXø›R§Ö²ÐÖ.»¯ ŸÏÇôéÓ!‘HTn®ú[Ø(ª>_C]º¦°¡œ^=¨½_^U|óÍ7¥6úH]˜ÕÅ{ï½§Ñë`Y ÀÏçW¹rcmÃçó¡UNõ. üòË/O€æjþŸŸ//ü¿¼Vz—¾-ܯ^äry¹s§.Qž¬bdd„7ª(ºõE5MÏ꺖º°ŽkÊðYUÊ“UºuëGGÇz/§ g¯ ס˜ão+‹×©]ÀÔÔ±±±‹ÅÐÑÑL&CJJ lKv¼.ǃ®®.tuu«ðIšÁÌÌ ùùùJ/Tnn.rssѪU«2ßÃãñê¼BÂÁ¡ Q£FÈÍÍU>NMM…P(T¦z¨ƒÇã•ã­©ßé SSS$%%©È*©©©åÊ*|>Æ\£^Žz‚™™D"‘Ь’——‡víÚ•ù---nŽsÔuÊÌ×»wo$%%!22 ‹áíí^%ËŸrpÔSúõë‡gÏž)CÇbcc‰ž\9^Ž€@ @Ÿ>}àáá¡|îÙ³gÐÕÕ­TQ1Žú@Ÿ>}¯ WÎÏÏW¶ããàhôë×¾¾¾ÊàèèhÄÄÄ GšÇ;JRX;wî =zaaa8yò$²³³1 X¿IŽúŒ‹‹ RSSqîÜ9„„„àÈ‘#011A—.]4=4Ž·†Ïçcذaxúô)nܸ?~;w†½}EM™98ê;w†¾¾>þþûo¥¬’““ƒþýû¿ýÉ98êýúõCJJ Ο?¯”U5j„Î;kzhï(ÌÌ̸ükŽÃ0HKKÃ0033+·PG}E!«5ˆŠ¹%ádŽºBTX98888888888888¸ØŽ: §°rppppppppppppÔI8…•ƒƒƒƒƒƒƒƒƒƒƒƒ£N"XµjÕ*M¢!"—ËáïïwwwÄÅÅÁÊÊJ%a]&“ÁÏÏ÷ïßG^^¬­­!”¯K$ܸqþþþÐÖÖ†‰‰‰JõÁ¤¤$ܼy‘‘‘066†¡¡a^OJJ ÜÝ݈fÍšA[[[ùšT*…§§'¼¼¼À0 ÌÍÍUÆš7n $$zzz066Ç@ýënܸÀÀ@èèèÀÄÄDùGÝ&??ÞÞÞ¸{÷.222`ggWjß¹sOŸ>…––5j¤2/ÒÒÒpóæM¼~ý†††044Tþö à <<·nÝBbb"¬­­Uæ\Mðúõkܼy)))°µµ…–––ò5‘H„ëׯ#((ººº*s ~º7oÞDLL 5j}}}åkµ}¯rTYYY¸}û6||| —Ëaaa¡2‡333qãÆ „††B___e^°,‹¨¨(å`ii å{e2ž?Ž{÷î!77·ÔPݰ,‹gÏžáöíÛËå°´´T¹–ÄÄDܸqQQQ066†ò5†a‚[·n!%%7V¹?¤R)=z„ÇC.——Ú8ê. ¸v킃ƒ¡££SSS•9 wwwÄÆÆÂÌÌ zzzÊ÷ÊåráöíÛÈÌ̄ʖJ¥¸{÷.||| JíÕbOºÿ>ôôô`nn®|a¼zõJ¹§ØØØ¨ƒ“Édxòä >|‰DRêþ‰DJYEWW—“Uê/_¾Ä7•=X.—#$$·oßFjj*7n\j?|ø^^^`Yfff*ó"++ 7oÞDHHH©= &ÈÈÈÀýû÷áëë +++•uZ&“áÙ³gxðàD"¬¬¬JÉdׯ_WêÅïu€ö€º,«p k ‰°qãFìÛ·‰OŸ>ÅÑ£GѶm[ØÚÚ‚ÇãaõêÕ8zô(rssqéÒ%„„„ W¯^ÐÖÖF||<¾ûî;xyy!99G…––:uêxúô)-Z„ØØX*ûZYYÕÈõ¸»»cùòåHNNFpp0:¤ü¼œœüøã¸rå 233qêÔ)¤¤¤ OŸ>àñx ÅâÅ‹ñòåKDDDàèÑ£hÚ´)…o¿ýÏž=C\\Ž= ccc8::jú'䨀¬¬,|öÙg¸yó& pûöm\¸pÎÎÎ066FJJ –-[†{÷î!==G…D"A÷îÝþþþX¼x1ÂÃÕ=Þœœœ`kk 8wî~þùgdffÂÓÓ·nÝB÷îÝk¤j¸L&ð}ûväääàÖ­[¸zõ* ]]]DDDà›o¾¿¿?bbbpôèQ˜››£M›6OOO,\¸ÉÉÉðóóÃùóçÑ¥K˜››×ú½ÊQ}aÞ¼yxõê222púôi<}úÇŸÏÇË—/ñÍ7ß $$¯_¿ÆÑ£GÑ¢E 4kÖ píÚ5,_¾éééxòä ®^½ŠnݺÁÔÔ°nÝ::tyyy¸|ù2^¾|©Üª›¬¬,lܸ§NBNNN:…ˆˆ¸¸¸@ ÀÛÛ‹-B\\púôitîÜ–––€ƒbóæÍÈÉÉÁÝ»wáéé‰=zÀÀÀ¹¹¹X±b.]º„¬¬,œ9s‰‰‰Ê=€£n²,._¾Œï¾ûˆŠŠÂÁƒ!“ÉеkWðx<>K–,‡‡RRR°ÿ~ÀÑÑ|>'OžÄÚµk‘••…‡âîÝ»èÞ½;ŒŒŒ ‹ñóÏ?ãŸþANNΟ?¨¨(8;;C  22ß~û-üüü‹£GÂÔÔmÛ¶ÕôÏÈQb±ýõ~ûí7 DÓ¦MѼysðx<üùçŸØºu+rssqûöm²³³ñã?âêÕ«Jù6-- }úô„„„¨È·G޽½=š7o^#×ãçç‡E‹!""8xð дiS°,‹Õ«WãØ±cÈÍÍÅÅ‹†Þ½{C("..ß~û-|||˜˜ˆ£GB[[NNNYåäÉ“uOVa9ª???väÈ‘ì­[·X±X̦¥¥±óçÏgþùgV"‘°AAA¬‹‹ {åÊV"‘°Ož»víZ–eYöÆì AƒØ§OŸ²‰„ý÷ßÙ¾}û²‘‘‘¬T*e×­[ÇΜ9“MNNfsrrØuëÖ±³gÏfÓÓÓÙ;w²ãÆcX‘HÄnß¾|˜:t(ÏŠD"vùòåì_|Á¦¥¥±YYYì²eËØ¯¿þšÍÊÊbãââØ)S¦°»wïfóòòØ„„v̘1ìÞ½{Y¹\^í×Á<˜½~ýºòþœ8q"{á–eYvË–-ìûï¿Ï&&&²yyyì–-[ØéÓ§³©©©lZZ;oÞ>>¬‹‹ {ÿþý¹–«W¯²C† a#""X‰DÂÞ¾}›0aûìÙ36++‹ýꫯØeË–±lzz:ûå—_²?üð›——ÇFFF²cÇŽeÿ÷¿ÿ±lll,;`Àöĉ,˲ì­[·ØAƒ±ÞÞÞ¬D"a/^¼ÈöíÛ—}ýúµ¦BŽrJ¥ìG}Ä®[·ŽÍÎÎfóóóÙÿýïì¤I“ؘ˜åZö믿²ÙÙÙlJJ ;kÖ,výúõ¬X,fCCCÙ!C†°§OŸf% ûòåK¶_¿~ìÕ«WY–eÙ3gΰC† aƒƒƒY‰DÂ=z”V$±ñññìˆ#Øýû÷³,˲?f ÀÞ»w•H$ì­[·XÖßߟeY–ݶm;aÂ611‘‰DìÖ­[Ù©S§²)))šþ9Ê!22’=z4{þüy6??ŸÍÌÌdþùgö«¯¾b³³³ÙððpvÔ¨QìÑ£GY±XÌFEE±ýúõcÿùç–eiÝtuueŸ={ÆJ$öܹslß¾}Ù˜˜V"‘°kÖ¬agÍš¥”oW¯^ÍÎ;—ÍÈȨökÉËËc.\È®^½šÍÌÌdsrrØŸþ™]¸p!+‹Ù€€¶_¿~ìµk×X‰DÂ>zôˆuqqa=zIJ,˺¹¹±Ã† cãããÙ‚‚vÏž=ìøñãÙ¤¤$6;;[)›(öÅžP—d.f§‹ÅèØ±# mmm˜™™¡iÓ¦ˆ‹‹ƒ\.‡——Zµj…>}ú@(¢}ûöèÖ­wïÞ@{@÷îÝÑ¡C…B8;;£E‹ðôôÔôOÈQFFF˜4iŒŒŒ ««‹–-[¢  éééˆGxx8¦M›###XXXà½÷ÞÓ'O““ƒgÏžÁÊÊ ®®® …hÑ¢\\\pÿþ}4/ €-Z@(bðàÁ077‡··wµ_GFFÜÝÝ1cÆ ØØØ@WWï½÷,XCCC„……A"‘`ìØ±ÐÓÓƒ­­-F…;wî(ÇÚ±cGtëÖ B¡ݺuC»víððáC´Œ3ÖÖÖÐÓÓÃØ±c‘ŸŸ—/_jú'ä(©T {{{Œ5JÆíàà€äädäççãÅ‹000À°aà­­&Mš`È!¸wïš½{÷†££#„B!\\\ЬY3xzzB"‘ÀÛÛ&LPÊ·“&MB\\ÂÃëýZ‚‚‚ðêÕ+Ìœ9SÖ¼`ÁL:^^^hÓ¦RŽqrrB—.]àáá€d²Q£FÁÖÖ:::5jø|>üýý‘žžŽ   L™2E¹L:ÏŸ?GJJЦF%œÂZtéÒ?ýôär9ÒÓÓ€ÀÀ@¥‚ŠF)Ãõôôмys„„„BCC•ae”,22yyyˆ‹‹SyÝÑщ‰‰ÈÊʪökyõêX–EZZöìÙƒ;v@$¡[·nʱZ[[+s³5jkkkC.—#<<öööÊóµhÑ"‘III Uy­iÓ¦(£n3vìX|òÉ'ÉdHNN†··7’’’àìì €æEñœV+++ãõë×(((@tt´ÊnÛ¶-RSS‘žžŽÄÄD(…ÕˆÂ333<þ¿ÿþ;þþûo¡uëÖÊk)>Oííí!—ˇÌÌL$''«¼îèèˆèèh¤¤¤Ôê½ÊQ½|ùå—2d ””¤4˜tíÚ2™ *¿m«ÿ³w×ÑQ\oÇ¿+qw!„@HHp‡àNi¡@©PA*À¥Ô‘R(…â.-Å­@q)î$q#®ëïûfK¤@È&á~Îé)»³;{grgæ>W«V%++‹¤¤$’““ÉÌÌÄËË˰= €ˆˆT*wîÜÁÞÞÞð 077/ô (n7nÜÀÓÓ“Ý»w3mÚ4öìÙC•*Uðôô$++‹øøø"ù4..ެ¬,¢££‘H$8;;¶W«V­Ðóêág€½½=nnn/íX„â!“ɘST*•!¯þûXþý¼zøððóL($‰¡ÂdË–-ôíÛ—?þøƒ®]»bkk‹F£yd¾ÈÉÉA£Ñ T*‘H$†<,‘H077/”/d2Y¡g€L&#++«Ø¥àšš2eŠ¡WØÔ©S™;w.ÙÙÙ¨T*t:ÝcŸ)ÿ.“Éd²G–É ˆ²JÙ —˱µµ%''‡ ðÑGÌo¼™™*• à?çá—oU*ÕcË·ÅM©T’ššÊرc‰ŒŒ$55•¯¾úŠÍ›7®Ççᇟ)ÿÎÃÿ5®(8G¥X_";;;¾ýö[Ö®]‹»»;¿üò ùùùýüÙéß$ÉgדJ¥/m‚ kkk†Î?üÀøñãéܹ3¿ýöÛ¿ó¤Ù.¥Récåá Pú¹»»3gΖ.]JLLÌKËOûî‹òðð`ìØ±|óÍ7Lž<oooþøãÇ~þiùôI×ã˼V…â׸qc–,YÂO?ýıcÇ •uò¢yøIÏ€åïïÏôéÓùöÛo™6mš¡ÕøIÇò¤|ú´´ŠûxÙ —ËéÞ½;«V­bÀ€¬X±‚ëׯ?öó¥9_¼öÚkL˜0‘#G2eÊvíÚõÄî™OKË“¶‹²JÙaeeÅ€X·nÍ›7gÆŒOl}‘<ü´gÀ‹011áÓO?eôèÑüøãôíÛ—ßÿ…Bñ\Çb̸âyˆ€µ˜ét:"""F.—ãîîN5øè£8yò$J¥;;;”J¥¡æB¥R‘‘‘aèiggGnn.:€¬¬,Ã2r¹KKKrss ¿™œœŒ]¡¥4Š‹™™žžž!“É077§yóæ$&&’››‹ùùùh4@_“Ÿ§§'‰›BiMMM5,_Spœ222J¥†…ÒI­VsóæM¢££ ã>š4iBÇŽ ãÚìììÈËË3táÍÎÎF©T¦Y·²²*ô·ðà666X[[cii‰\./TKùàÁÜÝÝ_ÊÍÓÒÒ’:uêàëëk[¿~}""" ×ëÃiMOO7,Ócjjй¹y¡šöäädœœœ°²²*ÑkU(>ùùù\¾|™””¬¬¬¨X±"Ý»w§J•*œ>}©TZäÞ–’’bX¶ËÂÂSSÓ"y¼ ÿÛÚÚ¢R© ϵZMzzz¡nðÅÉÊÊŠN:akk‹T*¥ZµjT¬X‘û÷ï#“É ½ $''coo………aiƒ‡ E<(ô¼zÜ3@(½²³³9þ<¹¹¹888P¥J>ùäÒÓÓ ÃÌÌ ssó"yØÙÙlll -;€aÔ¿óEÁ3 ''…BQ¨[nq)è¡ðú믞 4@&“‘€••2™¬PƒÁ¿ó°B¡@­Vú¼ž™™iÈÃzÈd2QV)åâââ¸rå ‰0`—.]"55kkkt:áÞ¦Óé™/ îm¹¹¹äää<±|[0V¶¸,oÙ¡CLMM133£iÓ¦ddd••õȸâágÊ¿ópff&Z­Öp=?ª¬Rð (-DÀúœuêÔÁÄÄ„ JëÕ«W À¦M›ÚŠF£Á××רBá Ôj56l`íÚµ†¼V«%77×°&XÓ¦M¹zõªáæɃ¨Q£ÖÖÖÔ¬Y³Ðßþܹsxxxàêꊯ¯/–––¶Ÿ={–Úµk¿”šË5j””d¸Y+•J¢££±±±A.—Ó¤I“Bi F*•âã・»;>>>…&9{ö,¾¾¾T¬X±D¯U¡ø(•Jf͚ő#G n¥R‰R©ÄÊÊ 333êÖ­[èo{ùòeììì¨P¡ÞÞÞ899qõêUÃö3gΈ©©)Mš4!&&†øøx@_˜øPܪW¯Îýû÷ ¯³³³ILLÄÎÎüüüŠäSìíí©Q£jµÚÐE¾`ûÃÏ«[·nºÉ%%%A:uŒù'ž"33“‘#Gkœ››kþ<==©X±b¡{Û™3gð÷÷ÇÒÒ’úõ듚šJTT ¿>._¾\(_\»vÍP*˜ˆ¬`ØHq²²²ÂÇǧPOKK#++ üýý111)4¡ã¿ópxx8©©©€>ð 3äáG•Ut:•+W6â_Pxš›7o2fÌCùô÷>sssär9µjÕ"//ÏÐ ¯Óé8wî\¡|l¨Ž7”oMMM©_¿~¡|qåÊÃøçâæé鉵µu¡qÓ hµZ,--iÚ´)‘‘‘$&&ú†®àààBÇòpZïܹC^^ž!®ð÷÷/õe°³‚AÛQQQüöÛoܺu‹óçϳjÕ*^{í5ÌÍÍiܸ1999ìØ±ƒ¤¤$öíÛGRR­Zµ M›6\»v¿ÿþ›˜˜6n܈““µkׯÞÞžfÍš±sçNBBB¸víÛ¶m£eË–/e½¤  •J™?>·nÝâôéÓ¬Y³†7Þx©TJóæÍ‰‰‰á¯¿þ"11‘­[·¢R© B.—Ó¶m[Ž?ÎåË—¹sç›6m¢zõêT®\™víÚqáÂÎ;Gdd$7nÄËËK¬ÃZÊ™››S³fM<ÈÎ; çÈ‘#ìÝ»—7ß|€V­ZqûömŽ?NBB7nÄ‚úõëceeE‹-Ø¿¿aB²7Ò´iS<==ñõõÅÛÛ›7ÅÉ“'¹pá‚aýËâÖ¾}{éááálݺ•S§NѵkW¤R)íÛ·çìÙ³œ?ž{÷î±qãF*W®LµjÕpss£qãÆlܸ‘;wîpñâE8@Û¶mñöö.ÑkU(>¶¶¶TªT‰5kÖð÷ßÎúõë¹u믿þ:fff´nÝš#GŽpåÊn߾ͦM›¨[·.ÞÞÞx{{ÈÆ¹wïgΜáÔ©StèÐsss5jD~~>Û·o7<âããiݺõK9ž.]º°k×.Ã÷‹/&77—æÍ›ãääDÓ¦MÙ¶m·nÝâÊ•+ìÚµ‹V­ZáääD`` ööölÞ¼™¸¸8Ž9BHH;v yóæÄÆÆrðàAÃ3@©TÖ*J'lllX²d ׯ_'$$„… bggGݺuñôô¤~ýúlذððpΟ?ÏáÇiÛ¶-ÖÖÖÔ­[‰DÂüArr2$22’¶mÛúg@XX˜á°iÓ&LMM kq'ZµjÅ’%KøûvíÓ§O§V­ZT©R???<==Ù´iÑÑц2Ék¯½@PP<`ïÞ½$%%±sçN233iÑ¢ Fœ;wŽóçÏsÿþ}6nÜH¥J•Ä:¬¥\åÊ•ÉÍÍeÉ’%„„„påÊ,X@PP®®®Ô¬YÓ0QWBB‡&,,Œ:ТE "##9tèáÞ¦ÕjiÚ´)¦¦¦´nÝšcÇŽqåÊÂÂÂØ¸q#µjÕz)ë°úûûS©R%~ýõW®_¿ÎùóçYºt);v4ÄYYYìÚµ‹¤¤$öìÙCrr²!®hÛ¶-W¯^åï¿ÿ&::š7âââBÍš5qtt$((ˆ;vÊÕ«WÙ±c­Zµ*4Ùž±ItÍxB±Ñjµ=z”ß~ûŒŒ ÌÌÌhÖ¬ü1vvvH$.^¼È’%KHHHÀÕÕ•¾}ûÒ¢E d2jµšÝ»w³~ýz ÕªUãÿûŸ¡å1??ŸY³fqñâE¤R)õë×gĈ/­é><<œ… Ž©©)]»våwÞÁÊʪᦧ§ãããÃÇlXx\©Tòû￳ÿ~´Z-5jÔàË/¿ÄÙÙ•JÅ–-[ An`` C† 1Ì,”^†•+WrôèQ233±³³£[·nôèÑsssÔj5`Íš5äääàççÇ€ ôyxáÂ…†)×k׮ͷß~kh¡MHH`Ú´iDDD`aaÁ›o¾ÉÛo¿m˜( 8iµZCEL\\NNN¼ûî»tîܹ\ŽR©dÓ¦MìܹµZM`` Æ 3tËÍÍe„ ܺu ¹\NË–-8p æææ%~­ Å'--Å‹sùòeòòòðôôä½÷Þ£]»vH$ +V¬àðáÃhµZjÖ¬ÉW_}e˜5555•É“'Ž™™;wæÃ?4Ì8yéÒ%–,YB||<...ôíÛ—–-[¾”qq*•Š;v°mÛ6²³³ñòòbàÀ† #//éÓ§sõêUd27fذa†|Á¯¿þJdd$ÖÖÖôîÝ›.]º`bb‚V«åøñã¬ZµŠ´´4*UªÄÇLýúõKÕø'¡0Nǽ{÷X´háááhµZ|||øüóÏñ÷÷G"‘““Ãøñã ÃÔÔ”6mÚðé§ŸòðÍ›7Y°`1118::òá‡Ò®];är9Æð ÈÎΦjÕª|öÙgÔ¨Qã¥O~~>óçÏçܹs¨T*|}}ùî»ïpuuE"‘Ã/¿ü½{÷°°°à­·Þ¢gÏž˜˜˜ Óé8}ú4+V¬àÁƒT¨PþýûÓ¸qc¤R)*•ŠÍ›7³}ûvÔj5 :´Ð,àBé£Óé¸té .$%%¹\NÍš56lNNNH$˜;w.QQQØØØðÁžý¦PY¾råʆò-軎ÿöÛo111˜™™=2 LLL$##ÃÐmáaK€h4ÃÚ²Ÿ§˜˜”J%*TÀÜÜü¥ÿm„â¡ÑhHII!==;;»GŽMŠ‹‹#;;›Š+ÉÃ*•ŠØØX$ E‚ÑììlÃø#77·—6‘AŒŒ qppÀÅÅ¥Ð6­VKLL *•ê‘ù4??Ÿ¸¸8LMMqww/4ÑAI_«BñQ©T†ñúnnnEÆ&©ÕjbccÑjµT¨P¡HÎÍÍ%>> ÜÜÜŠ<ÒÒÒHNN~ì3 8ét:’’’ÈÌÌÄÍÍÍ0Cl…BA\\r¹"“udff’˜˜ˆ­­­!xXÁ3ÀÃÃð´‚Púåååºzzz¹Oçåå©©é#Ë1÷MGGÇG¶Æ<¼¼¼^úØ}µZMBBJ¥OOÏ"÷é‚gеµ5nnnEòprr2iii¼ÖŸö J¯ŒŒ -“É -X  ®pqq1Tž>,::…B——W‘<üð¾KcYE¬‚ ‚ ‚ B©$ư ‚ ‚ ‚ ¥’XAAA„RI¬‚ ‚ ‚ B©$VAAA¡T« ‚ ‚ ‚P*‰€UAAA(•DÀ*‚ ‚ ‚ ”J"`AAAJ%° ‚ ‚ ‚ ¥’XAAA„RI¬‚ ‚ ‚ B©$VAAA¡T« ‚ ‚ ‚P*‰€UAAA(•DÀ*‚ ‚ ‚ ”Jrc'àU¦ÕjÉÈÈ@£ÑzßÚÚsss222ˆŒŒÄÌÌŒJ•*‘ŸŸ••&&&†íQQQhµZ|||°³³@©T’——‡™™wïÞE­VS¥J,--‰ˆˆ ++ ///\\\P©TäååajjJxx8•+WÆÌÌŒû÷ï“••…··7NNNH$cŸ6¡œP(ܹsooolmmA(1)))$%%QµjUýüEÄÆÆ¢P(¨R¥Š±MAŠX(''‡Þ½{£V« ½?lØ0zôèAbb"cÇŽåСCXXXðî»ïͰaè]»6±±± >œ«W¯¢Õj©_¿>S§N¥jÕª\½z•+VàììÌ–-[P©TôèÑ///~ÿýwÒÒÒ dåʕܿŸ5kÖ`kk˶mÛxçw°±±aãÆ¤§§S³fMÖ®]‹£££±O›PN¤¤¤ðÍ7ßðã?Ò¼ysc'GJÌ©S§X³f K–,ÁÉÉé…÷·aÃbccùõ×_}hÂ+,77—“'Oâçç'*O„rM«ÕrõêU²³³iÕª•±“óJ]‚ÈÒÒ’yóæ1gÎæÌ™C‡ ÅÓÓ€1cÆÊÉ“'Ù³gGe÷îݤ§§óàÁ „­­-'OžääÉ“˜˜˜0dÈRRRHIIaûöíèt:‚ƒƒY¹r%¿þú+gÏžåèÑ£ìß¿Ÿèèhþøã’’’ؼy3666„‡‡3kÖ,¦NJxx8Çgûö턇‡³cÇcŸ2¡Ñjµ¤¤¤ T*A(Q …‚ÔÔT´Zm±ì/;;›ŒŒ c–ðŠKIIaÔ¨Qœ>¾Ð{T¯^NGBBëÖ­#33“¶mÛÒ´iSLLLÈÉÉáï¿ÿæäÉ“¸»»Ó½{w<<ø€ììlNž<É… pss£mÛ¶øûû#‘H ÅÌÌŒÈÈHŽ?ŽŸŸ]ºtáÞ½{>|€~ýúáêê*ò6"`-"""2d:uâóÏ?G.—ŒF£ÁÃÉD‚«««¡ðZ­æóÏ?7dd•JE~~>yyy€~,ì¿»ðZ[[ö÷ðØ)[[[ìíí }ÖÆÆÐÖr¹È*ÂóÙ³gáæ pæÌêÔ©Ã/¿üÀ/¿ü‚““ÎÎÎìÚµ‹óçÏ3kÖ,LMM;v,»wï¦M›6\»vyóæ1þ|^{í56lØÀ’%KÀÇLJ7²jÕ*ðöö&""‚+VpìØ1,--ûì3–.]ÊöíÛñóóÃÛÛ›Õ«W³jÕ*¬­­©T©·nÝbýúõìß¿ŸŠ+ûôåHjj*3fÌ0Ì3“œœÌÙ³gÙ½{7ùùù„‡‡“ÍáÇ133cÀ€T©R…ØØXzôèJ¥â»ï¾ãܹs4iÒ„3gÎð믿²{÷nüýýùñÇ ;ŽŽŽ,[¶ŒU«Vaff†——/^䯿þbÆ 8;;ûtˆBŒ,==Ÿþ///l"MLLÐét†‡è»P¼¶´´ÄÑÑ‘Ÿ~úÉLjµZ233©Zµ*IIIÆ>4A`À€ôíÛ­V˱cLjˆˆà“O>1ô ¨X±"óæÍÃÚÚš-[¶0cÆ ÒÒÒ¸sçà×_¥S§NäääðÅ_0gÎ^{í5är9'N¤N:lݺ•·ß~›?ÿü“:píÚ5>ùänݺEýúõ¨^½:S§NE"‘лwoÒÒÒX½z5^^^Ìš5‹½{÷’››+Vá…}ùå—(•J4 0äû‚ õòòò:t(={ö$==þýûsáÂÔj5çÎcÞ¼y´mÛ–””þ÷¿ÿ±hÑ"Z´hèƒÝõë×S§NC%¦N§#44”¡C‡Ò©S'†nø-A(.=zô sçÎ\¹r…áÇóÉ'ŸàëëËСC9tè}úô¡K—.†ï„„„°gϼ½½¹}û6‰„ž={Ò¿²³³©V­•*U2ŒÁÎÌÌäÊ•+†ï›˜˜0sæLªV­ÊòåË„âdjjŠ©©)ñññL˜0-Z0dÈ'~§U«VÔªU ©T?mŠ¥¥¥¡û»ƒƒ2™Œ&Mš`ii‰F£1¬ˆP fÍš†¹=œœœJ¥†Ê///,,,Ľ[(vR©[[[rssY¾|9‰‰‰,]ºT*Õ#¿Ó½{w|}}ýĪ*T`Æ H$jժŜ9s õXlܸ±¡w£½½=ööö†ž1¾¾¾H$’B W¯2°Qhh(sçÎ¥}ûöÌ›7Ï𾿿?dðàÁÌ;—ììlÔj5;wîþûÚ«W/>ýôSÞÿ}t:k×®¥k×®b‰¡Ô‰ŠŠâ»ï¾#((ˆÚæààPäóJ¥’ØØX™>}ºá}•JUhìµ¹¹92™ì?§Câ…’¢Óé¸{÷.£F¢S§N|ðÁ…¶[XXiÍÏÏ'))‰¨¨¨Bù^©T`KåêêZd9œ{÷îñÝwß±nÝ:/^̤I“ÄPá¥xðà£FÂÙÙÙ0¯Æ“xzzƒ'•JŸ©‹………!Ø„’¤ÕjÙ°a6l`ÅŠT­Zõ‰Ÿ/¨X}¾]·nëÖ­cÖ¬Y( *T¨À´iÓ sˆ2É'žfFäììÌäÉ“ù>è»R:99±qãF*T¨À'Ÿ|ÂÒ¥KqqqÁ‚1cÆàêêÊáÇ‘J¥ôïߟ?þ 6l˜¡æF&“1kÖ,üüü033£OŸ>8;;ãààÀСC µõVVVÌš5ËнÆÜÜœO>ùÄÐ’%Ïjܸqäåå1vìØ"c¥ÅÔÔ6lÈ®]» ïÇÅÅq÷î]1‘ŒPê) ~üñGlmmùþûï ó<‰¹¹9ÞÞÞ´nÝšÕ«WÞŒŒ$>>SSS€GNÀÑ®];Œ½½=¿üò o¿ý652öiÊ¡E‹qýúu6nÜh˜gãIÄ„1BYuîÜ9æÌ™Ã7ß|CãÆŸš—®XÉÈÈ 55•Ÿ~ú µZÍõë×™8q"³gÏféÒ¥Æ>´2G¬FT¡BFŒñØí£G¦uëÖlÙ²Å0IŒ¥¥¥áakkˈ#]B¤V«™7o§OŸfÆŒddd–ßxZËh‹-X³f 6l C‡äååñå—_âææFË–-}h‚ðX*•ŠÉ“'sóæMfΜIjj*©©©…îËÒ±cG†ʶmÛhÕªééé :”zõêÑ´iÓÇ~ÏÜÜ Þ{ï=Ž=ÊÏ?ÿÌï¿ÿ.ÖΊF£aÆ ¬Y³†1cÆ Óé¸sçðOË’N§C¥R¡V«E ¿P¦Ý½{—AƒѦMš6mJDD Ÿ´`ýlFƒJ¥zd·Ý””úõëÇܹsiÛ¶-UªTÁÑÑQ,å÷œÄݤóööfܸqœ?žììl<ÈÈ‘# [’Éd¢KPjeff²oß>=zt¡m‹-zâwëׯO¯^½øá‡¨Zµ*ÙÙÙhµZ~úé'c– ÍÖ­[ ½÷矒͌3pww§nݺŒ9’àà`jÔ¨aì$¿t•+W6ZpUÜZ·n]æ+–^„Z­fóæÍ… Z†uëÖáííÍÏ?ÿŒ\.ÇÃí[·Ò²eËrÄ=Mƒ Ê|™¯½öš±“`Tyyy,^¼˜¨¨¨B•æçÏŸçæÍ›Lœ8‘F‘˜˜H¿~ý8vìo¿ý¶±“ýÒ5oÞ¼\”S@äñÌÌLæÎKZZZ¡÷÷íÛGnn.³fÍÂÕÕ•Úµk3fÌBBB¨^½º±“ýRÉd²rS÷ðð(½óÀ“.ét:Ž?Nhh(=zô(´íÖ­[¸¹¹ˆT*ÅÁÁ pùòecŸ§!•J111)ž\./ûóÊÉÉaåÊ•EZŒnÞ¼I½zõpvvF*•âïï——×®]3v’K„L&+7A^y¹VŸWxx8;vìàƒ>0¼§Õj ¡uëÖ˜››#—ËiÚ´)¹¹¹DFF;É%B.——›€Õ˜ÝÝM§ÓqôèQÂÂÂèÖ­[¡m¡¡¡xzz†ï8::R¯^½W¦¬bbb"òx9 R©X·nnnnÔªU«Ð¶›7oR¿~}‘J¥T«V OOO®_¿nìd¿t‰¤Üäq©TZnÊ\%þ׈‰‰aÅŠ 4¨H7߈ˆ¬¬¬°³³ô7EBCCŸ¸OµZMffæ#ø^M:Žììl²³³K¼E/77—yóæáïï_¤«QXXnnn†EÏquuåÖ­[OܧJ¥"==]äqÁ@«Õ’‘‘A~~~‰çñÔÔTæÏŸO= Õ¶ët:îܹS¨%Õ××¥RI\\Ü÷™››Kfff¹iŠGzz:J¥²Ä722’U«Vñ¿ÿý¯HYåîÝ»X[[Ê*¦¦¦øùù=µ¬’››+&Ï Q«ÕF{¶=z”cÇŽñÕW_accSh[XXîîî†²Š‹‹ ÎÎÎܾ}û±ûÓjµdeeåzJ¯üüüby¶—hÀšÍÂ… iÞ¼ù#ûSLA«…D"A"‘ P(ž¸ßŒŒ NŸ>M^^^IŽPŠi4®]»Æµk×JôA Óéøûxñ"üq‘Yÿž7'&&ròäIrrrJøL ¥•B¡àÌ™3ܽ{·Dƒ<•JÅæÍ›‘ËåtëÖí‘=)ny–J¥h4T*Õ÷{ûöm.\¸ *e„BŽ=JBBB‰þfvv6‹/¦eË–œçyîã:ŽÐÐЧVN ¯–ììlŽ;Fvvv‰ý¦N§#%%…ßÿÞ½{?rÜõóäqµZÍùóçKüzJ·˜˜Î;÷Ô2ÀÓ”hÀºmÛ6®\¹BË–- 3Ìzýúu²²²û=33³'î×Éɉ.]º”ùÙ¼„â#—ËiÞ¼9Í›7/ÑîñññÌ™3‡öíÛ“œœÌÍ›7ýLªQQQîýiyÜËË‹nݺ•ù¥„âcaaÁk¯½F5J´ëÒÕ«WÙ´i;väþýûDDDú.d‰‰‰üŽL&3ÔÔ?N½zõhß¾}¹é¾$ž={âíí]¢¿ùÇpýúuš7oÎíÛ·IHH ??ÿ…Ê*‰„ }FZ¡t±··§G†Öú’——ÇìÙ³±³³ÃÇLJ7n™™Ijj*!!!O JŸ”ÇMMMiß¾}‰_¯BéVµjU:vìøÂÝïK´dŽJ¥b„ €~ ›ôôtÆŽ˘1cpuu%**ŠÜÜ\,--Q«ÕÄÅÅQ±bÅ’L¦ <·¨¨( ûöíãÀ†ZÊU«V‹££#™™™¨Õjär9¤§§`ì¤ ÂŽV«eéÒ¥H$Clj'òöÛoãææFjjªáóñññÈåò2?Û¢ðêG©T*«ddd0vìX~úé'ÜÜ܈7”UT*•(«eFnn.qqqÄÅÅfý‰‰A&“1uêT¦M›†‡‡G¡²Jzz:™™™åb†¡l*Ñ€uذa|òÉ'†×[¶láÀÌž=777t:{÷îåþýûT¯^üü|.\¸@Ïž=}žá?©S§Ë—/7´¤ªT*ºvíÊ!ChÞ¼9ûöícÿþýäää`ggGLL QQQ|ñÅÆNº ü'o¼ñAAA†×ׯ_çÛo¿eÚ´i¸ººrýúuNŸ>Ío¼è§³·°°À××רI„ÿäË/¿,4übóæÍ9rÄPVQ©TìÛ·¨¨(ÈËËãÒ¥KåbÉ¡ü³··gâĉ…ZRÇ_ý5ÎÎÎñ×_‘››‹­­-ÑÑÑDGGÓ¨Q#c'_xE•hÀêââRhòLLLðññ víÚxzz²hÑ"z÷îÍ©S§H$´jÕÊØçIþ ‹BÝa &pssÃÅÅ…6mÚ°sçN–-[F“&Mظq#>>>Efè„ÒÊÖÖ¶P×ô¤¤$*Uª„¹¹9]»veæÌ™¬]»GGGV¯^MË–-Eë“Pfü»¬boo_¨¬R§N<<µjÕ" ™L€J¥âôéÓ$%%Q£F ªU«†\þÜ—¢ Edd$gΜÁÜÜœzõêáííD"ôσcÇŽ¡Ñh¨[·.+VD*}îe¿¡ÄiµZCYÅÑÑ‘    Û5 7oÞ$44ooo5j$Ê*B™’ŸŸÏÕ«W¹sçžžž´lÙ²Ð0>•JÅ©S§HNN¦fÍšT«VÍPŽ„’öB¥ä´´4¶lÙÂŽ;¸wï:kkkZ¶lÉСC©\¹²¡ú‹cþüùìÞ½›5j››Ëœ9søé§Ÿ B"‘0sæL:DµjÕˆ‰‰ÁßߟQ£Fagggìs%ÿɹsç5j^^^ØÚÚ²bÅ š7oÎ?þHVVcÇŽ%::///V®\I—.]>|¸±“-ÿ‰F£aË–-,\¸jÕª0kÖ,† F¯^½ˆˆˆàÇD"‘`mmÍ‚ øæ›oèÔ©“±“.ÿI^^óæÍcïÞ½Ô¬Y“ììlæÎËO?ýDÓ¦M‘H$LŸ>cÇŽáïïÏÆ däÈ‘ØÚÚ;ù‚ðT™™™ >œ„„üýýILLdÉ’%LŸ>ÒÒÒ;v,±±±T¨P•+WÒµkW†jì¤ ¯¨çXU*›6mbݺu´hÑ‚#F ‘HˆeÇŽüôÓOüòË/¸¹¹¾sÿþ}:ÄèÑ£iݺ5¹¹¹L˜0;wR¯^=bbbØ¿?C‡¥[·n„……1hРΟ?OÇŽ}®á?Ù±cÕ«WgܸqØÙÙ±wï^-ZDDDaaaܼy“Ù³gÈÎ;™3g½zõÂËËËØI„§ÊÉÉaÛ¶m¼ûî»ôï߀ß~û;vвeK¶nÝŠV«eÞ¼yXYY1þ|Ö¬YCÆ õ¦„ÒêÞ½{9r„1cÆÐºukrrr?~<»ví¢^½zDEEqðàA†Îo¼Ahh(Ÿþ9:t }ûöÆN¾ <Õ¹sçHIIa„ Ô«Wøøx̱cÇèß¿?'Ož$$$„¹sçâïï϶mÛX¸p!={ö¤B… ÆN¾ð zî>ZÉÉÉìÙ³‡áÇ3eÊúoß¾,Z´ˆpüøñBßQ*•øûûÓ©S'ÌÌÌppp R¥JÄÇÇ£R©¸té´nݪV­J³fÍ8qℱϓ ügr¹œwß}'''är9UªTA&“‘ÀÙ³g ¢Zµj˜˜˜Ð²eK*T¨À™3gŒlAøO´Z-...tïÞ+++¬¬¬ðóó###ƒ´´4Ξ=K·nÝpuuÅÊÊŠîÝ»“ššÊ;wŒtAøO”J%tìØSSSðöö6”U.^¼ˆ——­ZµÂÄÄš6mÊÉ“'tAøOrssi×® 6D&“áææ†««+ÑÑÑœ={–fÍšáç燉‰ ­[·ÆÝݳgÏ;éÂ+ê¹V•JENNM›6-²ÍÖÖ–êÕ«SèýÀÀ@&NœˆV«%==àà`®\¹B“&M°°° ""+++ìíí011Á××—Û·o?1-jµšŒŒ 4±Ï§PJèt:²²²ÈÎÎF§Ó•èo÷Ýw4iÒ„ÜÜ\âãã9vì–––T¯^°°0<<< ãDqvv&,,ì‰ûT©T¤§§‹<.hµZ222ÈËË+ÑïããƒR©$>>þ‰ûÍÍÍ%33³Ä¯W¡tKOOG©T–èoÖ¨QƒŸþFCZZ7oÞäÚµk†²ÊÝ»w±¶¶6 U255¥J•*O-«äææ’““c´s)”>jµšôôtÔju‰þnçÎ0`jµšääd.^¼Hll,AAA„……áééi—íää„““Ó+µZ-YYY( ãP¡ÔÉÏÏ/–gûs¬r¹ ®]»Vd[NNwîÜ)²Ô‰‰ ¶¶¶ddd0cÆ úôéC||<;vÄÄÄ¥R‰T*5 ê–J¥˜™™‘‘‘ñÄ´deeqùòeòòò^Ú ÊFChh(¡¡¡%äÙØØ`jjÊ¡C‡èß¿?K–,¡C‡899¡P(Éd†±Ý&&&˜˜˜™™ùÄ}>xð€sçΉŽ` P(¸|ù2QQQ%äI¥RlmmQ«Õ¬]»–>}ú°oß>zôè••J¥²Ð$bæææ¨ÕjrssŸ¸ß{÷îqõêUQ)#röìY’’’Jô7.«LŸ>>}ú””D‡ËåÏUVÑét„‡‡nÔó)”.¹¹¹Fy¶›››ceeEbb"C‡eРATªT‰ºuë<²¬"—ËŸXVÑh4\»v­Ä¯W¡t‹çêÕ«¨TªÚÏs¬NNNtèйsç2oÞ>>xyyQ¡BÞxã 6oÞÌ?üðȲJ^^žafxA(i/Tâ±²²â‹/¾àÃ?$??Ÿœœlmm±µµ}dmÑùóçY¿~=6lÀÌÌ Ð¯×gii‰L&£Aƒœ>>>†ïÔ®]›É“'³dÉþúë/LLLhذ!ÄÜÜ &L˜ÀÂ… ùä“Opttd̘1áÔ %M©TríÚ5öïßOVVT©R…ªU«R£F ²³³ùùçŸñññaðàÁ…&(MÆÇâÅ‹™2e J¥’Š+2aÂüüüÐjµ|ÿý÷¬^½š+VP¥J¦Nй¹¹±“-”ÌÌL.]ºÄÍ›7‰ˆˆ %%WWWlllÈÍÍåÞ½{T®\™>}úP¯^=äry¡1ªr¹œ *P¡BT*iiiOZœìíí™9s&‹-b̘1H$*W®ÌÔ©SqssãÍ7ß$++‹)S¦ Ñh¨^½:Ç7Ì6)¥]ݺu™8q"Ë–-cÿþý˜ššÒ¸qc €™™æææLš4‰E‹ñÉ'ŸàääĘ1cŠTÒ ¯&µZMHHgÏž%<<œÈÈH nnn¸»»`¨H×h4ܸq£Ä×6íÑ£999ìܹ“µk×bmmÍ'Ÿ|Â[o½@Íš5ùî»ïX½z5K—.Å××—É“'z¯–èèht:*T(TÞÐh4\ºt‰éÓ§#‘H U’J¥dffâåå…V«åõ×_¡4ýôÓR}¼nnnŒ9’øøx”J¥¡ë&è',èÔ©µk×&33“ *ºàe›F£A£Ñ P(ˆˆˆÀÁÁ—BÁæ•+WX°`r¹œ®]»Ò¸qcC š’’‚T*Å××·Ti–H$2yòd’’’H$xxx*]LMMéÛ·/íÛ·G­VS¡BQÈžJ§Ófˆ–H$H¥R£UHJ¥RZ´hAÍš5IIIÁÌ̬HY¥N:†²JÁ’«C£Ñ V« æÂ… äääàêêŠþù'ááá´iÓ†·ß~///ÌÍ͉ŒŒ$11‘œœîß¿ONN^^^xyy•ø=R&“ñá‡Ò¥KÒÒÒ°µµÅÝݽÐöÎ;S»vm²²²DYå¤ÕjÉÍÍeïÞ½üñÇhµZlmm©Y³&¾¾¾Ô¨QƒsçαgÏ>ÿüsZ¶lY¤b:==ØØX.\¸ðÂyü¹KýË4oÞ¼Hðàì쌿¿? E¾'‘Hpppxd7Îöööb‚ôø<*U«Õ¬_¿žÍ›7ãì쌋‹ M›6¥J•*øûû¹©´ÂØØØkóüÓhµZ¢££ åÌ™3DEEabbB¯^½ Í"—žžN||<õë×§Q£F…ºðvíÚ­VËüAll,C‡-Ñ.¾ÏËÔÔ´ÐZ”ÿæîî^èáð*R©T$&&âááQ¤…P£ÑpïÞ=.^¼ˆN§ÃÎÎ *W®L… ŠÜsrrˆˆˆÀÎÎggg,--Kì8’““¹|ù2G%33“–0ÊÍÍÅÃÃÃÚØØ0tèPÃbíe™µµõcgf—ÉdbÌj9tïÞ=lmmqtt|l0ODDÑÑÑT¨PZµjaggGFF \ 33“ÈÈHnÞ¼‰™™‰___š4i‚§§§QŽU”U„GIOOçÂ… œrŸ‘‘‘\ºt©ÄE&“áââ‚‹‹Ëc?ãáá!&+gRRRHOO'-- ­V‹¥¥%ØÛÛcee…B¡ ,,Œ#GŽpþüyj׮͢E‹pqqáÎ;ܾ}›7nð×_aeeÅüùó›‡ î‘J¥ò©K”>Í ÍìääÄÑ£GéÙ³'æææH$4a²›† ÷¯RFÌà6iÒ$j×®ÍçŸ޵µ5jµš””V­ZETT3gÎÄÑÑ‘ÈÈHŽ?Α#GHNN¦jÕªxxxàêêJFFçÎ#??NGÍš5 ¢AƒO\"E£Ñ——‡N§3LŠõ¨tæääðàÁ®\¹‚­­-õêÕÃÊÊŠØØX¶mÛÆåË— ¤Aƒôë×//¯g8¥R)ï½÷ž±ÿ,B1R(¬[·ŽÍ›7ÓµkWz÷ÙÙÙœ9s†}ûö‘––FÍš5qpp@©T’˜˜ÈÊ•+111¡FXYY¡ÑhxðàÁÁÁØÙÙ¡R©ÈÎΦR¥J|óÍ7¸ºº>60Ôjµäåå!‘Hàæçç“mxmfff¨ÊÉÉaíÚµ>|˜ÀÀ@Z´hA@@ÎÎÎØÛÛ£ÑhÈÊÊB«Õ’ŸŸO~~>...ØØØûô *•Ê/ÍḬ̀±±1¡999dggÖjÌÈÈ`ÇŽìÛ·©TJ@@ÕªU#!!Û·o“››khq’J¥TªT OOO.\¸Àܹs ¿çââRhÍà‚–yN‡»»;ï¼ódggÍ”)ShÑ¢…±O•ðŠ(x~¨T*Ôj5÷îÝ#..ޤ¤$8::âêêÊÝ»wñóócÉ’%˜››sâÄ  [·nT«V””RSS‹,¹”““Crrò#{FuB9¡R©8|ø0iiiÔªU ___îÞ½ËöíÛ¹wïæææ†1§xyyHÅŠñòò*Ñžj‚ð,òóó‹ônÍËËãÎ;ìܹOOO.\ˆ««k‘ï*•Jâãã‘Édìùöo‰¤Dç_‘è®î|Fyyyœ8q‚­[·L&C«ÕÒ¢E úôéC… ^ú‚öjµš;wd´®CÅ%;;›%K–Ë€@¥RqôèQN:Eݺuiffl ×èåååqùòeÖ¬YCzz:^^^8::¢ÓéËåÈårjÖ¬I•*UÉd\¾|™S§NO@@+Väøñã4hЀ7ß|www,,,Ðh4$%%‘’’‚››ÎÎÎ/ýïÿ4ÇÇÆÆ†úõë5/"--;wÒ¿c'å…èt:ÂÃÙ6mMš4á½÷Þ3¬•Ì•+WhÕª•*Uzánß:Žëׯóûï¿“››‹µµ5J¥Ò°ÝÁÁ6lˆB¡àï¿ÿæâÅ‹Èår:uꄽ½=¿ýö-[¶ä7Þ0|/33“‹/GË–-iذ¡Qk×U*;wî¤E‹eº‹yTT.\ W¯^ÆNJ¹ P( ÊÎÎæôéÓìÛ·333^{í5ªT©‚¥¥%ááá,[¶ [[[ùðÃiÚ´)999DFFbkkKõêÕ29!!;vð¿ÿýÏØ§õ…dff²gÏ>øàc'å•››ËÝ»w9sæ gÏžÅÆÆ†5jàììÌîÝ» ]aoܸaX[·]»v´nÝ[[[ÌÌÌ ÝÓ_¶‚.Á•UW¯^E¡PФIc'å•¡V«IHH0LòŠN§ÃÛÛÛPq¨ÑhÐjµtéÒ…æÍ›å>~åÊ222^h&õgjaMII!::šªU«bmm……;w¦sçÎ$&&¢R©°³³]ÞžƒJ¥báÂ…DFF2eÊCK¦©©©á š7oþŸ×Œ«R¥ o¿ý6±±±\¿~[·nñÕW_Q¯^½BŸ“Ëåxzz–ùŠáåˆåÇäÍ7ß,Th333£~ýúÅZ© ‘H¨S§³fÍúOŸ¯]»6*•Š«W¯²k×.ÂÃÃùꫯhÔ¨Q¡Ï,—$¥QNN§OŸæÀ¨ÕjºwïN³f͸zõ*¿ÿþ;‰„>ø H7[WWWªU«ÆþýûéÔ©“a<’‹‹K¡‰ÁÔÔT´h Ï$$$„eË–‘››K:uøòË/IOOçÖ­[3pà@7nŒL&C£Ñ[âs“h4qtt,ÔŠ™••ERRÄÆÆrñâEîÞ½KåÊ•iÞ¼9}ûö5ú=ûey¦€U¥RqìØ1–-[†¯¯/5ÂÇÇWWWÜÜÜŒ},eVbb"³gÏÆÍÍiÓ¦•Ú.´KitéÒÅØIʘ .°xñbÞ{ï=ºuëfìä<’‰‰ 5¢nݺ(ŠR{ ÂÔJ%‘‘‘:tˆÓ§OãííÍ[o½…Z­f×®],Y²KKKúõëG“&Mü999ñá‡ûpá©RRR˜1cæææôîÝ___Ôj5qqq¥RIll,±±±ØØØ`jjJJJ §NâÆØÙÙѹsgFM~~>·oß&>>ž¦M›R£FWvnŒgžtI*•âé鉇‡;v4L|âÄ 6oÞŒ‡‡µjÕ¢zõêT¬XQ<$#>>ž“'O²~ýzH§NJõÚ¢‚ð<>ÌìÙ³ùùçŸiР±“#e–V«%%%Å0 ÿéÓ§ÉÎΦoß¾aeeUdι\NµjÕŒtAøOÒÓÓ‰‰‰!))‰„„bbb ëàæççãêêÊùóçyûí·yë­· +œ={???<<<0555úÜ‚ð(LŸ>¸¸8¨R¥ R©”ììlt:Mš4á“O>1´–ŒŸË é=w„$‘H ôÔ«WzõꑚšJxx8W®\aÙ²e4oÞ\L¢ñNÇýû÷Ù¶mÿý7~~~üòË/†L+å…B¡`ïÞ½lܸ‘o¾ù¦ÈXPAž¬`â°¥K—’žžnX– R¥JT­Z•AƒQ­Z5Ñ+G(Ót:*•Š3gΰ|ùrlllpvvÆÇLJêÕ«cgg‡­­-äååѦMêÖ­k¨à/h„ÒJ§ÓÁO?ýD›6mèÕ«××wí¹Öœœd2™a0pVVwïÞE§ÓÑ­[7 ThVÎWV«åÒ¥KüüóÏtïÞõë×e¦.Ax™´Z-·nÝbÖ¬YØÙÙ±lÙ2ìììŒ,A(SRSSY³f ÇŽã‡~³n åŠF£áþýûܹs‡ÐÐP.^¼ˆ™™ß}÷µjÕ2vòá…©T*bcc‰ŠŠâÆ>|˜Aƒ‰Ê•ðÌk^^þù'¤oß¾4kÖŒììlFÍõëבH$¸¸¸ðÅ_ЬY3c_© Ñh8xð ¿ÿþ;£G¦qãÆ¢EU(Wt:¹¹¹lÚ´‰?ÿü“wÞy‡×_] „g Ñh¸wï¿üò îîîÌŸ?Ÿ *;Y‚PlT*{öìaûöíâããÃ×_MµjÕÄDwB™¥T*Q(¤¥¥qîÜ9:Djj*øúú2uêT|}}Ì2í™ÖM›6±páB:tè`hÒÞ²e çÎãã?¦jÕªìÞ½›qãÆñÛo¿=vàû«B«ÕrôèQÖ¬YÄ ðóó3v’¡Ø…††2mÚ4*W®Ì¼yóÊôš ‚` ìÚµ‹-[¶0lØ0Ú´i#æ5ʼ۷osäÈüüü¨X±"{öìáúõëLœ8QÌÎ+”yjµš‹/òÇZ­¦fÍš 8Zµj½ðšòÂ?žéiË®]»èÓ§Ÿ}ö¤¥¥qòäI‚‚‚èÓ§VVVT«VrýúõW>`½wï+W®däÈ‘"XÊNG\\Ó§O§wïÞ´m۶Кa‚ <šJ¥âÎ;¬[·Žøøx222ðóócÖ¬YT®\YôÂÊ4NGBB3gÎ$ €'N†ŸŸ“&MzåˆBÙ§T*9|ø0ëÖ­cÀ€x{{ãââ"z–½$ϰ&$$ R©hß¾½a-·äädîݻǰaà Ý9ìííqrrâÖ­[eb‹—%;;›_~ù…7ß|“êÕ«;9‚Pìt:³gϦY³fb}^Aø”J% .äÌ™3¼ÿþûÔªU ooo±œ’PnÄÄÄ0räH^ýuÞ}÷]är9:µZ-ò¹Pæ©ÕjV­ZÅùóçùñÇÅlì%à™Ö¼¼<4M¡Y CBBHNN“Bü‹Z­fÅŠxyyñÖ[o‰µ¿„rG­V³aÃ4 ½{÷6vr¡TËÏÏ'22’3gÎpòäIjÔ¨Á¬Y³ÄU¡\Ñh4ܽ{—åË—Ó±cGÞyçC×v‰D"‚U¡LËÍÍåÂ… ìÝ»FÃØ±c©T©’±“õJx¦€ÕÉÉ bbbðññàÔ©SøøøàââbøœJ¥")) WWWcŸÑܾ}›Ó§O3sæLч](—.]ºÄ¶mÛX¼x1¶¶¶ÆNŽ ”jëׯgÿþý´lÙ’!C†P¯^=Ã:{‚P¨T*öïßϪU«xÿý÷yóÍ7E€*”aaa,X°€¼¼<ºwïN§NDþ.AϰV©R???fÏžMff&<àĉ¼ÿþûÈd2  ¬Y³­VKË–-}|F‘’’ÂìÙ³6l˜§!”K üòË/|óÍ7¸¹¹;9‚Pji4¶oßÎÙ³g™={6îîîb|ªP®äääpõêUÖ®]‹\.gúôéb}y¡Ü¸uë»víâòåËôïߟ6mÚ`ff&*KØ3¬fff 4ˆÑ£GóÕW_¡Óé¨_¿>o¾ù&R©”sçÎñË/¿Ï÷ß§§§±¯Äét:6n܈‹‹Ë+° å[VV'N¤gÏž4mÚÔØÉ„R-<<œÕ«W3a„Wò™(”ogΜaáÂ…˜˜˜ðÖ[oѲeK±ö¶P.¨Õj:ÄâÅ‹éÔ©óæÍ+Ô›T(YÏ®ÓéŠäc­V‹B¡ÀÄÄ™LVªóxqS©T?~œ¥K—òÞ{ePy,«×y9|ø0kÖ¬áÃ?¤I“&8::;YÂs(ÈÃJ¥©TŠ™™Y¡nÜe­¬R\rrr˜>}:>>>ôïßc'Ià9Ö¿ÿþ›o¾ù©TŠ Ë—/§C‡LŸ>33³§~?..Ž•+WrãÆ 4 Í›7çƒ>0xaaa¬[·Žàà`*V¬ÈG}D½zõJmKNFFcÇŽ¥^½zŒ?žŠ+ŠÅÞ_q¹¹¹8p€={ö€¿¿?=zô uëÖh4.^¼ÈêÕ« >|ðU«V5v²ëÊ•+lÚ´‰ñãÇ‹µ„RSSÙ¼y3§N"++‹5jðñÇãçç‡B¡à¯¿þbóæÍh47nLŸ>}^‰Bmxx8ááá>|˜””~þùgŒ,á9ÄÄİjÕ*nܸV«¥E‹|ðÁ†––Û·o³nÝ:BBBðööæ£>¢nݺ¥¶¬R´Z-—.]bÙ²eLž<c'Ix/^dÛ¶mcccÃo¼A·nݰ±±A­VÊ*ÉÉÉÔ®]›>ø___c'û¥ÊÏÏgéÒ¥˜˜˜0pà@Ãr‚ñ=Óˆx…BÁo¿ýF@@‹-béÒ¥|ñÅœ:uŠk×®=õûÌœ9“›7oòé§Ÿòé§Ÿò÷ß3{ölrrrP(üüóÏýôSNž<ÉìÙ³ÉËË#??ŸqãÆ‘––f˜xnâĉDGG;é/F£áúõëLŸ>#Fˆ`µŒ‹ççŸ&++‹Q£FñÆo°|ùr6nÜÀ½{÷?~|˜O?ý”^½zP«V-ºtéBHH;vì aÆôéÓÐt/^L=JuO‚ç•••ÅÔ©S±´´dÙ²eb³ràÞ½{ܸqƒÙ³gS«V-2d_~ù%ÁÁÁdee1~üxªU«F58þ1vò‹]NNëׯçĉ 2„   c'IxAçÎÃÔÔ”ï¿ÿžŠ+Ò¸qc²³³Ù¶m `ÿþý8991hÐ lll°±±áË/¿äÊ•+O-ë—E†?ÿü“;w2nÜ8Ñ ¸zæ9Çåry¡à,,,°±±!33ó©ß555¥E‹…ç[YY¡R©Ðétܺu WWW*V¬èg%®W¯W¯^5öy*"!!µk×2bÄlllŒ¡ñññáõ×_7t +˜þ\­VsóæMjÕªe¨¹óôô¤bÅŠÿ©‡BI;sæ ·nÝ¢_¿~ÆNŠPŠH¥RêÖ­KóæÍ ïYZZ¢V« Ï=>WW×é’«ÑhØ´imÚ´3?–RZ­–””’““±¶¶.Ñßþúë¯ ÿÖétüõ×_ÄÇÇ3pà@Nž:ލ¨(¢¢¢ðöö6JÂÂÂØ¾};GŽ¡OŸ>OìFõ´<ž™™ÉíÛ·±³³+‘€õÀØÚÚÒ°aÃ?o£R©¸sçIII%°>üû!!!,_¾œˆˆÆŒóØ¡Z­FóÄý%$$pïÞ½2±ÎÝýû÷3f mÚ´¡oß¾¢eõ% %==Ý(¿““Ã… Xºt)fffŒ5ê‰ñ'ÝÇu:qqq$$$”ê€U­VsêÔ)æÍ›G×®]éÝ»7æææÆNV¹•ŸŸOhh¨Ñæ?IKKcÿþýlÚ´‰êÕ«3pàÀ'~þIy\£Ña¨Ø)ÍBCCY±b 4oÞœaÆakkkìd•K©©©Ü½{—jÕª½Ð~žù ÉËËcáÂ…†˜N§#!!ˆˆΞ=[è³óçÏÇÇǧÈ÷§OŸÎùóçéÞ½;ݺu3tIxœ§µÙÛÛTbÈŽ;hܸ±Xº¦“Éd4hЀìììh4Nž<ɯ¿þŠ»»;S§N¥FOœ=òiy×ÝÝvíÚ•Hú [¶lá믿.-]¯*sssZµjEZZZ‰ÿT*k×®eãÆ´hÑ‚¡C‡âïïÿØV¹\þÔBo```™wÿþ}~úé'Z·nÍG}$‚Õ—¬cÇŽìÞ½»Ä777—iÓ¦qáÂzôèA·nÝðôô|âwžTV‘H$Ô¬Y³P7ãÒèìٳ̚5‹ñãÇS»vír=ëqi`kkK‡¸téR‰ÿöýû÷™5k111|ðÁ¼öÚkO ÚžTV111!((è©×‰±edd0eÊÚ·oÏ?þXh˜£Pü*UªDóæÍÉÈÈx¡ý}š^½z!•J¹téÖÖÖe~ ßèèhÆŽK›6mhß¾½¸>ʱÐÐPð%GGÇ"e•úõë³nÝ:îÞ½K½zõÈÌÌäêÕ«|ñÅÆNús‹‰‰aÑ¢E|÷ÝwÔ¬YÓØÉ^"NÇ‘#GH$ôïßNgÈãR©KKK7nÌúõëÉÌÌÄÑÑ‘ˆˆâããËtÀªÕjÙ¹s'yyyôîÝ[ÜÃ˘çê+©Ñh¸qã'NœàÚµk¤¤¤`mm­[·&((è‘]cBCCyðà={ö,²íÈ‘#Ô¨QƒæÍ›3qâDC ???Z´haìó„F£áÈ‘#„††2kÖ,c'G(¥’““ çܹs¬^½ºÐ¶O>ù„ò×_1jÔ(jժő#GèСC©¨™W«Õ,[¶ŒN:áææfìä¥Tdd$qqq|ÿý÷E¶Í™3‡Þ½{3fÌF…½½='Nœ`àÀe6O©T*.\¸ÀŒ3xíµ×0`€±“$¼d¡¡¡$%%Ñ£G"ÛŽ?NÍš5 bâĉ´k׎‹/âïïO³fÍŒôç’››Ë”)SèÕ«W©éí#¼< …‚7npãÆ"KÖ¹¹¹qâÄ Ú·oÏ_ýÅÈ‘#©Y³&‡¦S§N¥r‰ÉÿB§ÓqèÐ!¶lÙÂüùóE7à2è™Öüü|6oÞ̺uëÈÉÉ¡V­ZÔ«W¼¼<®\¹Â‘#GhÖ¬£GÆÞÞ¾P FÇŽ -ió0ggg¾øâ Ž;ÆÕ«Wéܹ3íÚµ+œ?ž•+WòóÏ?—‰IAã°µµeáÂ…œ˜ÀÍÍ {{{ÆǾ}ûˆŽŽfÈ!¥¢ë­V«åèÑ£¤§§Ó»wo1vUx¬ªU«²nݺGnóõõÅÎÎŽÉ“'³oß>òóóùé§ŸÊd!X§Ó‘••Å‚ ¸rå ß|ó˜„ìñÚk¯ÖŠÿ·‚òÈ—_~ÉÑ£G¹~ý:]ºt¡mÛ¶eríÆ‚UèÞ½»¸÷¿LLL4hï¾ûn‘mcòøùçŸÙ»w/111 6¬T”UžWBB«W¯føðáe¶òôU÷Ìë‰'˜7o½zõ¢_¿~¸»»‚Òüü|vìØÁ²eËøå—_9rd¡–VOOϧƶ³³£{÷îtïÞÝØçÆàîݻ̘1ƒ#F”ùnmÂËennNݺuŸøww÷R·¸|RR+V¬`ôèÑb]aá‰ìì잸ùùù1|øpc'õ…$%%1jÔ(|}}Y´hQ¡¥z„òí¿”UìííéÙ³ç#{Œ•%!!!ìß¿Ÿ©S§ŠÙ€_2™ì©½º$ îîî|úé§ÆNî KMMeܸqtïÞ½Ô ¿žÝ3¬¬^½š:0dÈ"[sssÞyç;v,}ôÆ>Æ’œœÌ”)S0`@™íî#O’ÍòåËiÙ²e™¿^áEét:™0a 6äã?y¡\Ñét¤¤¤°sçNþúë/L¥J•Œ,A(vZ­–%K–àêêJ÷îÝÅd©eØ3õýˆ‰‰!##ƒÎ;?¶F&“ѤIÜÜÜŠ,sSýöÛoT©R…N:‰Œ.”;¹¹¹Lž<µZÍG}d´µà¡´HKKcÔ¨QT¯^ˆ`U(w‚ƒƒùú믹{÷.S¦L¡M›6¢+°P.]½z•Û·oóÅ_ˆ%Èʸg*¦¦¦¢V«©X±â?'“ɰµµ%--ÍØÇ÷Ü4 ;wîäÞ½{Lš4I«B¹“žžÎ/¿ü‚¥¥%_|ñ…˜ùZx¥ét:î޽ˬY³ ¢OŸ>¢G(w’““™6m½{÷¦cÇŽ¢/”[111LŸ>1cƈ¹gÊgªR³²²B*•>5Õjµäåå=qíÒîþýûlܸ‘¡C‡–ɉáI´Z-¿ÿþ;jµš#Fˆ`Uxå%$$ðÝwßѨQ#Ñ X(—ÒÓÓ;v,­[·¦S§N"Xʵßÿ† Š¡NåÄ3¬~~~ØÚÚÖ1zœ7nQfgTÌÏÏgÞ¼y¼÷Þ{"£ åRrr2§NbðàÁXYY;9‚`T‡bèС|þùçôë×O´¬ åŽF£aáÂ…¸»»Ó¯_?LLLŒ$Ax)T*[·nåöíÛ|öÙg¢‡d9ñL« ݺuãÀlÙ²…ÜÜ\4 Z­FƒJ¥âòåËÌž=›–-[–е%Ÿ•N§ãðáèT*^{í5±°°Pîèt:¶nÝJPP^^^ÆNŽ V«åðáÃ,^¼˜AƒÑ¡C1–O(wt:GåöíÛ 2D«B¹U0œoýúõ|ûí·ØÛÛ;IB1yæjä^½z‘‘‘ÁÂ… Ù´i 4ÀÂÂFÃýû÷¹pá 4àÛo¿-“ óÆÅű|ùr¦L™"Zž„réÎ;ÆNŠ ¼4/^äâÅ‹b’%¡ÜÒét\ºt‰mÛ¶ñý÷ß‹`µ{)«N§#77­VkìãûÏnܸAFFÍš53vRá¥øë¯¿ÉdôêÕKL,SZ)•ÆNÁ+áÈ‘#øûû‹1NB¹Ï‚ 1b„ÈçB¹ǯ¿þÊ?ü@íÚµá%¥Vô-ÂóæÍãóÏ?ÇÑÑÑØÉG§•ÊØ©(“¢££Ùºu+Á곸pŽyúçrr :ºèûéé°?\ºII…?¯Ñüó:/æÏ‡„”cu¹¥Õj¹sç»víâƒ>ëP å’R©dîܹÑ Ac'G^šíÛ·S»vmêÖ­kì¤/™(¹ÇÇÆÆ†   ±ŒMi”•¥ÿL üú+dg;EeJ~~>‹-¢W¯^Ô¨QCäñÿ*!fÍ'§Ç&/þú †‡9sŠnOKÓ«¿ÿþóþ‚°~=äçë_Ÿ< —/Ãë¯CA×=µNŸ†M›þù^jªþ7…g¦R©Ø¹s'#Gޤk×®Ô¨QÃØI„b§V«Ù¸q#iii¼ÿþû¢‚R(·RRR8räï¾û®È節gštI«Õ’••…æá–GHOO7öqýgjµšíÛ·3xð`c'¥ôILÔ¨ÝÝÁÌì¿}'=–,Ѷk׆nÝôÿ>rDß:úÚk𨉖.Õÿž“ôì úï]»¿ücÇ‚~ÿ'ÂÈ‘`gÿ þ  T©ýûë÷÷Ç`aiZ’êÕ}&êÆ$$$ЩS'c'¥lY³š4Ñçã‡EFÂ;Сƒ>?Þ¿C†@` ~{jª>oÊdú<ûÃúÖÔ‡+ >úH_ù cÆ@۶к5˜šê?“'ƒ•4nüÏ÷öíƒ]»ôŸùøchßÞØg©ÔS(\¿~ àèèÈìÙ³Å6B¹ôàÁfϞ̓˜>}z™šôRžEA/‚÷ߟʕ+;9B x¦€õþýûÌ™3‡”§tYS–¡qXÁÁÁ¯^m»J¥"ƒ‚ÀÖV¦§Ãùóв%ØØè[„vîÔ¢Ö¿¯Óéÿ»r¬­¡bEÖêÍÌ@«ÕÜMMÿ'‘€ƒƒ¾€îáõêéßß¾5Òï£qcýïggÿÐÞº£GÇþ |÷,\úýøù¹¹þ;ÿŸ³3?ŽSx8 ??cŸm£Ñét;vŒöíÛ¿šë ëtÿüûI-Ëú@°bEhÚTŸ§^<=õ){öÀ§Ÿê+pæÎ…‚™e=<`À€ÂûZ²DÔ«§ß‡LV´’ÆÓ~þYŸåòZU xxÀ´iúëða}ᆱ¿VÄŒŸO¤ÓéHOOgöìÙܽ{—>úˆV­Z‰IõJ‚N§¯¤‘Jõÿ=ü¾N§¿%ý¿µÚ^‹ÞÏE§ÓÏèÑ£©^½:_ý5¶¶¶ÆN– ¼4·nÝâÖ­[|óÍ7¢×Ø+â™V¹\Ž››æææOýlåÊ•Ký 3//… òÙgŸ½z…ùk×ô-HM›ê_ ïzûÖ[ÿúôÑÿ—œüO kd$¬X·oäIúÂÆ† p옾ÅÇÙÞ|³ðoÉdúÀtÄ8{V|îÞ è[–5þ fMýø¿‡ÙÛèQÿ¼vqÑÿ§.“ß¶m mÛü86¯ð8µ;wîpùòåWwìªR©¯xiØP‚~Œè•+`i©Ï;•+ë+lÌÍáÐ!8zƇ‚J¬ü|ýXÖêÕõÁeVtíúøßìÛWßE¸sç'§ÍÂâŸßø7™¬h°ZÀÔ Ö¹cº+%%…¡C‡òÆoðÝwß½z÷xcQ«õëO¾ˆ‚^ ÿ5Òjõ=æÌùç»jµ¾ÇŒ““þùQPêí­¿þrsÿùlZš¾7޹¹þÙ#–àz,FæM›Ø³g#GޤAƒ"XÊ-NÇõë×™|8-Z´Áê+æ™úÆÅÅ1gΠ½7yòdÔjµ±å?S*•ܾ}›‹/Ò¦M›Ò•éÏœõµÔÏ#7Wßz:x°>ˆÌÈÐ0ÞyGÿà9RÿÿZµŠŽ›+)2™¾;fqžw pÈ1Î!•&:ޤ¤$Ö®]KPPnnnÆNRa …¾Ååy©TúëdÛ6ýÿ ýû³fÁáÃú`53Sßå¼ øìÚ>ùäù󼉉¾û®~J½èèhfΜÉçŸþêâàúõÂK'=©TŸ÷³³õã]¿^ô3÷ïÃСú1ÙQQÆ>òWFDDK—.å»ï¾{uó¹ðJP«Õ>|˜Y³fñÅ_мyóÒUnJÄ3µ°*•J²³³ ÍœžžÎŸþÉ7ß|cìcy*Fí[·øã? áý÷ß/} jש£ïNØ¢øúÞ¡¯Å}ׯ‚‰ˆæâ¢[ªRÁƒún¾R©¾ûîwßÁ½{úVÒò&P#VàÚµk̘1ƒúõëóÙgŸ!—?Óeþò-_®Ï»íÚ=ß÷srôKÉÈåúVú‚Êöíõ3H{xèÇÆuìøOÏ™¬ø[ô…R'>>ž)S¦P¯^=5jdìäÏôéúe’† ÑWV>+N?vÛÌLÿ,jÑâñŸÍχ7ÞÐ_Ï¥©·R9–””Ä”)Sèׯ5kÖ4vrá¥Ñjµìß¿Ÿ5kÖ0~üxŒ$ÁHŒV’MKKcíÚµôéÓû‡Æz%%%qðàA®_¿N¥J•èÖ­^^^Å2aL\\ãÆãwÞaðàÁ8=i}Å’–›«0½½õ­A{÷ê»2êtúÚm[[ýØž;wôŸ77×úô]mlôhÁÒ%&&ÿL2ó°g™À"¸ ¼Aé_±70C?–µ”(_T­Z5Ã8i­VKtt4Û·o'!!:uêСC\Š© éÕ«W™2e   eË–¥«»{Zµô•2Eóè•+úJ•Ê•õÿ=<T¡Ð_ööúeŽþ­~}øòKýd-]º<¾ë¢PlÔj5K—.¥K—.†¥Ôj5!!!ìØ±FCãÆiÛ¶íKŸ÷þýûŒ7Žf͚ѧOL_áÉÖøòK}ENAwZ…B?YØ¿‡òhµp÷î?]y%ýøîË—õ­¥ß|£çý°ÌLýœè+Uôÿ•S)))¬_¿ž¾}ûš ))‰ýû÷sóæM|||èÖ­*Txé“Û) æÍ›G5èܹó«9™žP¬®^½Êõë×éÛ·¯á=­VKTTÛ¶m#))‰ºuëÒ¡C‡Ί+˜0a‚VË­VÛäå!ÉyñÖ$£ÜéÔj5;wîäøñã( ºóý¿É“'³mÛ6üüü¸qããÆãÁƒÅò».\ víÚôêÕ 77·ÒÓò¤Õê—xY»VÿºW/xûmý¿OŸ†eËô-¦ èk̇ ÑÍ}¶©©~VÆâ7wØ(^p?%!ýøÕR4Ü),,Œõëדœœlx/%%…ï¿ÿžÛ·oãëëË–-[˜õðx­täÈ^ýu:tèPú‚Õ¬,ýÿ›6Õ/‘”–VpRôÝ –»¸{V¯Ö·’‚¾Eõôiý¬£'O>~ÿR)´i£¯´±µÕw;^­VË©S§Ø»w/™™™†÷oܸÁ¨Q£P(8880oÞ<¶mÛöRÓ’œœÌÔ©S ¢oß¾X”§Öôsçô“ÔåçÝ¥öñoÞÞú5€ë×׿¾w¾ý¦NÕ£ ßßo¿é{Þ\¸ðOO…Ë—õ•Ÿ>ú™bk«¯46Lí–cjµš;vpòäÉ"ËõMœ8‘;wâççǵk×?~<©%0ÞöÏ?ÿ$>>ž~ýú•ž2Œðìž0/ÏhÉP©T¬ZµŠË÷…ÿ—œœÌ÷ßOxx8¾¾¾lÚ´‰_ýµDÓ–““Ãܹs0`€èIPݼ©¯ô?Óóç_xw%~·;tè¿ÿþ;·o߯û_³ÿ={–&MšDÆ éÙ³'}ô‡âƒ>x¡ßU©TÀLKƒ~Ðw)¬T韉]Tª&KN†}ûô5uC†ûˆàúõë,[¶ŒË—/jÉÔh4¬]»–*Uª0nÜ8¤R)îîîlÞ¼™V­Z¹çFÃúõëñññá³Ï>+}÷÷ç¡Tê¯KK}p¸m›¾BóóÏõ—J¥þšúýwýb5jè×оqC¿6u›6…÷Wµªþ9rð ~¶ÞúõõHii°x±~⼂ëíóÏŸ>Vû‹/ô]€KS/¥bvðàAV¯^ÍíÛ· ½ œ9s†[·n1eÊêׯO÷îÝéÓ§‡æ½÷Þ{ii:yò$ëׯgþüù8× û‚qlÝ ›6é{ÔéžµtéR<È;wh[°ÄàÿÛ³g*•ŠñãÇãììLÍš5ùᇸyóf‰ûöíÃÚÚšÎO["N(LMõ+ŠT«†24´è Ïè™ZXår9R©”¤¤$ #** µZÍ;w ïü÷ïÖS€jÕªñùçŸóÆoÙ†»»;~~~H$lmm©_¿>W¯^}áóvÿþ}233©]»ö ï«X<‰‰ú»¸À×_íyê”~¶Eoï'OP$•ê»tw× À#vIèg >nì„€­­-o¾ù&C† )ÒÕ7$$„:uêààà€D"¡J•*xyyqýQ“™<£¤Ri‘•Qåçë+dœœôy¼€\®ŸfáB}KP—.ÿäq‰D£+¨¤ññÑWæüú«h5-%<==éÓ§}ûö-Ô’¯Õj¹uë-Z´ÀÄÄ™LFÆ ÉÏÏ'ê%MÈ“žžÎ¡C‡xë­·ÊG°Z0ÁÑÂ…úV˜jÕôc³¿ýöŸgÄÕ«ú^9?þ¨_¯Z§Óëþí7}Àúor¹~­ÓwÞÑ/ÑÿÎÎη¤Óé8xð mÛ¶-¾n’±±0ož¾¶ûí·õµÛ÷ïCOžxbÅ Ø¿_ÿG¬SGÿ^õêþìˆÅ“Öçì¥=Nð: ïŒ¾àO\\~*À½DVVV4hÐ[[[ÌÍÍ m £sçΆ|êââ‚››¡¡¡OÜgvv6xyy=2kµZ¶ný¿öÎ;¼©òíãßÌî½é^ЖB[èbS–( *ʸù9q ¾*n*ˆ•½7(”n -t¤Í<ïw“&m’hi)çs]½”œ“³òœç¹÷½=ôP»sÞ2 yr,,¨O©¡ÅU&£*¢{÷ÒwÞy‡¼C/¼`ø¸ÑÑÜÛ—ï òòòP]] †¹½ÉÛŽŽŽpttDss3vìØ¡ùœa\»vM§˜]@@¤R)JJJŒ³¢¢7T³@*•â£>ÂüùóÑ¿ÿÛú º„âb*¤çïO9¤ùùÀòå”òñä“­FH@7O4<œŠ—©·óx¤¼.YBŠiâÚµkhP§ÜFÔ²ÊåË—ÛÍÏׯ_‡¥¥¥&§ÕÄÄصk—ÑcVTT ¢¢ÎÎÎ7t-*• 7nDXX˜^šåáÊZëüü€@sØõë×õ:xº›Ùó·ß~k·-++ Ó¦Mƒ EÑpvv†““®^½jðxJ¥†µµõM_—D"ÁÚµk1}úô»»xÞ†HDuvΟ""€#Z>!??VÆú×w‚RX}}}±nÝ:ÈåòNíßU¥ÖÛæŽèÛ^^^®S½¸íö+W®àÉ'Ÿì’ëT |û-Y¦ÇŒ¡Ï¼½)´*?Ÿ,ájë§HD¡½Ã‡“À ÄÅÑ„ÕÛ1ð¦ FA3À0 jjjP]]€€€ž¾ºéèjjjBii)\\\ô*¬HOOïÚjÝ ÓšWF¹ÔuuºíaÔûp¹Tàe×.¾;SØÌŒ*ù²ÜJ¥åååhhh¸í ë¢R©:l}VWW‡ÊÊJ¸»»wú¸III(//ïÝB<ÃPxïåË@b"0w.EÄìÚüþ;!S6rs¾þšrHyÐ ú˜² PŠ…äCÉnÆd†aP[[ ‘Htà kaa!Ž9‚~ø¡§o‘åf‹©øöí”û­%ÿÉår”––”_{Æd•J…ÊÊJ455Ý´ÂÊ0 vî܉‚‚¼ñÆ=}»,7BJ ñ  .'¨¬¬„¥¥å-þ†V ëk¥ÒÍtä1²¶¶FLLŒÁBUUU¨©©O×]T\E¹¦àêJá_Mž&€*žnÜH–óáÃi¿oûó»i‚P 7ËAJî|ì0àñx4hjjjîˆp’ŽÆ¸““F´X«ô‘œœŒÀÀ@XXt¡uáúuÊ;7Ž" []œ%/rà®^¥Ba®®ÀÛo÷ô£¼k011ALL ÊÊÊz}¥P§±Ô"00PSM»³|ûí·˜={ö-/„ÝŠTJÆž„j½¤VD£¢È“ª­d …}:/ôf5jD"QO_F§06s8 0à¦"vïÞ˜˜˜.«&Ïr›¹vÖÉï¿o×VÐÒÒ#GŽDbbbO_e§0¥(0tèЛîý®R©pîÜ9üûï¿øøã{÷¼ÎB45Q‡OOrà©xZxxx 22uú Þ7Ì0 ‘à‹/¾ÐÉÝàp8 …xÿý÷o¨Ï©««+òóó!‹aaa¹\Ž¢¢¢[î•zôèQ >\§$}››R_xG7OIÃff¤°¶ÅÞž È$¤œ;GáÂcÆEýN#€€þ·x¬[¥@-}C¡À5³Ñë½Áîî«ƒB¡ŸÏ‡H$Bmm­&4çf9wîbbbº.¯©®øäà‘GZ?³²j-æRU¬[G‘ž{®ëó§YîH8ÜÜÜtŠƒÏçwi1†apòäIðù|£†œÛŽR ?ýDëÄë¯S~è”)À¼yT$O«kO_-ËMâææ†’’’.—UôQ[[‹cÇŽáí·ßfóVïär2äS>ú¨QEzGå|»»»C$id•ÚÚZÔÕÕ!LÊÖ äææâ›o¾Á믿Þ-ïKÓØHF•J·FI7qÃRfMM –/_Ž×^{ ׯ_‡B¡Àõë×5ù¦uuuÈÏÏǸqã +ˆˆŒŒDyy9òóóPlÿÅ‹{Ó7¨T*qäÈŒ?ÞðdŸ•E¡¼Æ¨¨~ýø¿ÿ£0_C¨½&&TÑôž{îLeµÀP¡èJ`CMÄ þ«¶èUmmô1lØ0$''£±±PTT„‚‚DGGßÒq322ÑuÍáÃ4nÕí“ÚâèHañÿüL˜ÀöŸBÙª®}†¨¨(”––j ‰555áÒ¥K·$«èC¥RaëÖ­ˆŒŒÄÀ;):ën&3xÿ}ªW¢Î½ærï(e Y%))IŽ_XXˆ¢¢¢nÍ)ýûï¿1|øðÞS•Å02ðÍ7i÷Øc·å”7$e*•JlÚ´ISÎ}Ô¨Qšœ˜˜,^¼ÅÅÅøôÓOQVVvÃ= |ñÅx衇¡PˆÑ†„æNPQQ‰Db¼ðÎñã–e,dxÍÚ¾`yšn)ÈLp볺—*WA^Ë[ï÷{ë40TœNÀ¤Xç¨ÐK#§ÆŒƒ;v`Æ ˆŠŠÂßÿÀÀÀ[*ŸŸŸ¡PصÉáÃ5 ó,,…ËåbúôéøðñiÓ&ØÛÛã·ß~C\\\—ŽÏ“'OÂÛÛ»K•àF¡ Š¿üB êÛoÓ:²z5«œöqÂÂÂàéé‰/¿ü³fÍÂéÓ§ajjŠQ£FuéyòóóqòäI|öÙg=}Ë,†hjÔåüýéoåJ’ïàb‚cÇŽÅîÝ»±aà :þù' Ðm†“ÒÒR¤¥¥á³Ï>»#Ò¸ú<õõd|é×PוP((rÀÅ…ÒWæÍ£´ÈÛd4¾!kII Μ9ƒùóçcüøñ0oÓbÂÄÄ~~~X²d Ž9‚ëׯ€P(ÄÊ•+áããƒ-[¶€Ãáà­·Þê²B“jöìÙƒáÇßtN K7sù2…B¾õ“CŸ™™QÒ¤¬Îœ93fÌÐùÌÓÓo½õD"¶nÝŠˆˆ¬X±¢[”I•J…Ý»wcèСpttìéÇÁräu)ùá2È-ðÕWÀ‡Òÿs¹$'ÞÆ§rª+ñFEEi@>Ÿªw...pqqA||< ¤÷XÔk©ñððÀÿþ÷?Èårðù|½Qo„’’M¡‚ÔTê¾x1ëEs3•`öó3\uQ"¡ýºJI)T7ï4¾=XÕý|%î¤ß²Q\L5xbc}Eã㩳ɳÏRʯµµnšpBÉtq&M¢B´ç›Ìà­»IY üö7'zCÙ;;»v‹—ËÅÀ±fÍ(•J˜˜˜Üò‘‘//¯[»Ø“'É[TZ üïÔn†…¥<<<Úy<ÆŽ‹aÆa˜˜˜t©b¹wï^ßrÞ÷M#•’¥ÙÂxé¥ë¡Èr{ Õãé鉗_~r¹ Ã¢b7JRRΟ?õë×ßp´K× TjÉ$IIT³ ™1 €æ€gž¡è»;¸@Pœžš,\.¡¡¡xûí·»LV1„H$ÂéÓ§ñÖ[oõô£¸;)+¤š;ææÔŽðùçààÖ”ÆíÛ©vÉÛo÷XaÀ’"Ôe·µ'Osss¼øâ‹˜:uªæ3‡‡±øæbIÌÍÍoYY¨·«¯¯/jjHY4ˆdòº:PîêÚµ¤mêyzâ°{÷-_‡W†7_¾LŠ !22¨ž‡!ÏåÕ«À§ŸÒ¸º%ʬLàí€ë߶߬PÐulÝJiŒGŽP­íí'NîcaA2G¶n¿pÚØ.ZD ëæÍô>ìÛ§{`TÀ™«ÀZ °m+¥k“Ôö§vŸéçå«ÉñÑ›111¹¹ù-/J¥999ˆˆˆ¸µ ²±¦M£å•ÕÜÜV£\o§¹¹ã(€ÞBUUï×j8LMMaff֥ʪT*ÅÑ£G1yòäÛ6vîµ,›?øùgúŒUVïjÔ²JW+«MMMؼy3}ôÑnÃÒ5”%ãÂ× ´H@r2Õv8s¦U‹õö¦tkë>[x°«dc\¾|¶¶¶pssëéÛíûäçÿþÛš_]\Li,UU­µH†† ¡hµ—顇h?GÇŽ Ôv7d¶³³³‡ÃAVV ‡.— [[[ýQTT„)S¦ôÈMiSXXˆðð¡øé'êcûüó” ÿÅÀrånx€„Cá‡3gvÝ0]ÿ¦æfªcSXHÊu[§™RIýxÍÌ€+È+9aBëBÒn%þtzCŸâQÉ‘… [;J´¨jjh]èÈn¡RQÁ!ÔኅúºþòË/xì±Ç:lïÇr‹œ>>ðõõÅ¿ÿþ‹ÊÊÊvÍê†ASS~ÿýw( DFFöôý¡ºº••öpp}”~ûï§HàdI iX…y}ý5…«il$-pàÀ®‘’U pàóú774ýû“RýóϺň† |ÅÅÀ€½y3 °R)ÉTß|CsíнHä+WÚëÄ @~/!§ZRÕ `ºíÚ3À‹3¨îÎÌû€ és•мgŸNÝz)Õñõ×i^»–¶ @ÕÜ9úóòFŽÞ|“Ö¨(RVÕÛù< t ðä“äÀxðA ¼œúˆó¦&`õdÀ£¥È¿˜(¦ßxñbÀÛûqŸÝ$uuuêqi† ét2±qd2àÒ%*×UUÀ+¯P€Ž(+¶mkmkŒúzã…¼µ©®ÖõüB¡~ü‘¼ÇÁ0d€i3=Þ2r9éMꨴ»‘ÂÂB8::ì¹Ýe0 ¢-[€?ÿ¤Ïœ˜’vÙ¢ ,Ý„J¥Â®]»ðÈ#ôhl#%Hnš€;:7764tn?•ŠÒê:UÖܬgQ PMM­FFþÔçàÐßEe-k+‡C¤¡þÌ`ÏžŽ¯·¾žd­o¿í‚(¸>Ã0HHH€T*Edd$Û¶éfQCÒÃJ%íü|²v¤`|ñ‘>œÆòÌ™ÀÔ©wD„À ]¡P(ÄÓO?üü|<óÌ3رc233QVV†k×®áØ±cxå•W°mÛ6<ùä“ð1Vu÷6ÐÔÔ„ü| öìñ@x8)W^{ Híÿê-´Ü†II/¬ÆÒ’–®Ê_-Îù§ Ëܺ•N5v,…ŽoÝÚ*ÌËd4ц‡“Ð:q" о¾”ó¿v-M† WßÙ˜=øí7òZ¾ò …Ò-îÜ ŒV È;š–Fù¦Û·Ï=ð’/’ËbˇZ:ÿ—_’€?n)¨jx<ÿ_|AñŒ¯ ŸOïË¢Eq 375H¡ÏIQ^º”¢žx0áƒz°–<9)À¤(÷àÓr?€@Iµ´œ·a¤õ °µµ5ÚÌÛ(’[¾¼¤„”ÆŽËiÑÎÎîxßòr2øt¼oe%¿ÎèÕ ­:†1†VuGcÈdzüxÇû65Ñû¥Ž¸1†TJïKg³ÿþ£÷ãÛoi-º9þžR£:2¾ÖÕ‘\æéIÏánG*•bÓ¦MxòÉ'»Nï+TTP:£BK¶ýî;òмþz«@³g Ño½Õ:à]]iði+§ që%Üp&PPÖ¯_ï¿ÿŸ}ö™&¶]¡P@"‘ÀÒÒÿûßÿpÿý÷wy^Ç’’ruuÏãÉ'-®µ¡ ƒØQæ†3g€É“ŸO.»òr*K®RÑ_þ˜ªBàój€Ùd9³o M©«#%sìX:åÌ™¤¾þ:ðî»46 `ذÖ㙘GßÊŠÃíCML€¹sÉ»™œL“ª½=ðâ³€_!€ˆÉ«9}:åÐôx-E MÆ û¥Ö”cúÇ’¬2ÞÜðO À?£½E ÔgÕ€€Y›ïªÃO…‚¼ÙwW¯^…‹‹‹æ]S{ö:U££¡~Е+~A&#áÅÙ™r’;:¤µu«7Þ˜ÑN$"Oü¡C‘lì5ËΊŠÈ°cüŠŠ(ò`öl á5„JEÏjäÈV#Œ! Š=uŠÂÚ;j1}ð`«ñÉ¥¥ô.­ZEF*cçÏÊÞ{Þ¯œzßï&”J%._¾ŒÉ“'wÿÉ)ÄÝí1ÌrÛ`çÎCxxx ð×®‘²XS8uÐ".?ŸæÏ§ž2>‡‹D$^…†’ñÓXó¥’ÖíÛåËËb1éœÍÍdÔØn†¬‡r9MØ *®Ô!È^½ŸŠðøûþ˜ò©p‡CÂK‹•½®ŽÒ¥ž}–”aµ(¨†r$ ìÚe¼%eR)Í‹Ñ3Ð)êtrñâE˜››#¬‹R’îXT*â¥RúõK'—Ó¿…B£J%…Gþû/×eË(TqâDR”ÊVÏÜ!$`õë×syL]Ì ¯Ä<øüóÏ‘™™‰ôôt”••ÁÒÒ¾¾¾‡CUÒ¦ª øägŒ§‚NŸc‘ˆ,O?9sÜpø°z2âQŽ@ÒáäÖ™3§ËÆŽ'³'€•;)ŸB_€¿þ¢ WŠÈãQeݪ*Ò'|}éRìíu)Rn®1ÌÌÈÛDy¯••@ €MF¨x$`ŒˆpT įð¡Eé©§ŒŸï¦W¨Ïª@›{D Èkà:€jè–v)³h.]3ÌÑç)//Ghh¨&”¦¤„„½Ñø4€Z ÔVÊa2k>Ì;ˆ„ÉH±êŒ¢©‰òªÿü˜5Ks*½H$´pÿø# FƦ WWJ½¸|¹c…ÕÖ–îûvàñÇ ïWZJsþðáÀÞ½”`H7©ª¢k51!AÆXþÑåË”gÝÜL%ci9 ¶n%㔡u¥ºšÞÝ  ›ÏͽûÖÌÌL(•ÊÛ“¿jcÓ±U‚…¥‹ijjB||<–.]Úé蠟ӼЕveK„’HԱš™Ù:ß›ÃÕóa])¬ùù4çúúÒšblí9y4(pî #ùp °$ÒáÃäv8xá(j Ú¶‹…ØVº2—rSõt²P*)mÉɉ JHu>ôQX;¼ñ¥CÉ冯7=Ö&__Êeuv6|ܾNMM ¾þúk¼ñÆ=úÞ+Èϧœ>±˜„U«èóèÏÕ•^°  ;œ6 8}ºÕ# oM¼…v ½•›Z Å#<‚—^z O>ù$Æß+”UÈÉaýfÍbZ-X*Y& "#áéI‚ßþý-Û}|hÆ}㠚ºl¨ª~Ú„÷,Ãw^ <Ô¥KÉtø0 ¤Úð[Úǧñìçwëaæöötû\ÈsYRµQ¸R@©gŸ®¦Àð–sµ¥@.-׬MZ=ªœ–ëïÛ‘À²³³uªHVWS$ˆ†æf’(T*2í¾ôÅu—” )ϧyc:<‡:w29¹ã¼›´4Rš.$ ¹1®\!årÀ€ŽÃr¥ñ¿{·ñ*Ú½â>H-—êë ï—”DÖñÀ@z×´³Ú’˜HÆOww M6v\‡r¬ÇŽ%+º±p²]»hºï> í×N¡×æâÅÖh __úÞÝÃ0¸pá‚NKµnãôi²¢°°ÜfJJJÀ0 <==;ýýû;—Ö±º3igÏ’¡ûüùŽ÷½x‘ŒÔ—/߯ €l@Ç“íÔ q¥Ã<‹à"¾Ž#ûe­ÿÝwfòùç¥TßÄ¿ðÀÁg± ê\NhÉÃ01!msî\úÐdbƒ«a³aûÎ+˜øŒ?¶þÊ5š|å Õa°° š üa8Œ™Ë~˜"--¢®†ªäLÞX JÓ*,ì²òw{ö쯯¯Þ–Q}©”^Øœ:†,çÏ?OŠªvÇ’ØXj›4t¨n¥0SSò Üeý™{–íMrü¸ søÒ¬[[K#(x⠀χ@@^Ë-[´r0„BšàÞŸ\—7¨!ž?OÞ’cÇ(×L-_¸8Åý<„Öµyüùç4ßsMxmh̾ûn{ïê-ã`HÔ† ?k­ý¸n¥ˆL=¹‘íg\¯g›@$È{:@ÛÜÀf´zS…ü¡_ñícH$# @ó™XLZa·o§d •ŠVÕ·Þ"-Q(DA)¡Áã‘òÒ  %ss£qäˆqeÍÜœºŒO}]\Èžäãc¼µKy9)¡-`lß«WÉrÎç“rm,§¨©‰ŽéáA5?ßð¾ß}G9Ö¡¡T ÄX‹òº£¢Hqýçý¹¯&&­FT// _îL>m_A*•")) Ñ·£?pV N–ÛÌÎ;1|øðò89ÓZSÅUU”Ò‘šj|?¹œÖ‘ûîkßb®-ÍÍ47¿ñFÇ…îd2𻢣i ’H@ÖÇ×^£¿?þT*0J®üs®—ö ¦þ$µ-™yCG¢Š¦$2>vqî‡êí÷àúõJü¸× ¥ŽŽt#GjjHe\øðaàˆƒx8|Øp½”ŠvSGºõëgøþ¶o'¯1—KÆ×âb’ÿôÝÿ/¿´÷ò¢Ÿ>Ý韺O±oß><üðÃ]Úö¬W¡PÀôçŸÀÇ“ã á᫯¨ðÌÁƒô’©…!WW]ÅÔÑ‘„”É“»ÅcšMc½«Ù½»óF´¡O޹hh¨†¿¿ ,T*ªÄáÐì3l˜NŒËÀ$(îÛ×R}ÓÄ„L`-q­r9UµÛµ‹<2W¯Ò¸S÷KÕ¶º:E–9†!G­\NV´øx@Ò,‚@ aÍ¥”Cj,t°£°½4£½r§¦¤ˆšØ ]eR àZ•¾@Á¸µ¼Ðs –>ú¨àèæ¦ªIå­¢å:Úlo ~v €³:Q èNçÚµkpqqµµµæ³ìlŸ ñž=äºãóiü‡„óçCaëˆôôÎ2ÊÊ¢q?|xÇCWWRÔ ¢k1Ôã´¾žÞÊy=uÊðq32H€²±¡¢bÆò¤§Ÿ&¡ÀÃƒŽ«™Œ F£FÑ£™<™¼¨ú¨¬¤aoo Ù}þùö½€Õäæ’ æãC9©“'Þ÷ܹÖV=B!­ÒÒÚ{OhP§ ¤°~öÂîêêêÐØØxCž§›¦ºÚx,; K7P]]sçÎaÆŒþŽXLóØéÓWPOO'¥µ¾Þø®¶í{yQ4¢1ƒ[AÍAAAÀß·´,U(H(¿xQëC ïL1|Îl…í²Å(>˜NY ‡™8‘&LJpqA«"è£'Q$²Â‘# A~Ø0jOÐb¤mnæ ¾ÙV.ð àÃÝݰᱰžŸOÆÿI“(œX|>­céÍÍ$#꣨ˆ¢^š›_xm#Œjjh=PgX[“¢¿mPXÈéòªò½™ôôt…Bôïß¿§/åæ(-%‹±:Ü«¬ŒÚvìÙCP¡ —èâEzéÂÃI€(Tìõ×)Çé‘Gn¢àK× P ññÇëÔ•E²å?RËHu{bm”JÒÁÏŸ'±óìÙV£WCJå­©œ}RaÍÊ22JáãcÎõë4ѵ-Y«~\š¸ªª¨¢nZšîöøx²‚Y[“2š˜Hù¦ß|CEåΣ);›Œ&ƒ‘ò9x0M\o¾IŒ½;€K¾ ¥µeBãph‚ìòB]§`°…²AŠž5€:èz$ …OJ]*ˆÔµÕ *PØ®¡0Æ|© ÜÕ_ôœÇ€º"q0ȃªF `tsXÝ@Jp'//ÞêI°GGr¤ææ‚Œ/¯½f°AÝÈ‘Âd( U™)Sƒ“ò¥o¢hb:}š®ÁË‹¼²†Æ´úµ i7–I•EƇ®åçŸ ï»{7½YòmlôW𬬤÷X­ëlØ{[^NÑêúknnôþëkÝSWGÞRgg*ª¤oßädRªµŸÑ¼y$Àh{YHhÔ6hY[S ÈW_á® ##°ëªŠíÆxè!Ià,,ÝGjj*úõë§°N§¥‘nXP`\±Èã1r$ydFRfjki¾rp€Q ùÎÅp²jÆ£cK‘“ZPþøƒ&j-kÝÅk6€£ððÃxà?òXššRQ‚I“4•÷”Jjpìg®ÈHÒôVù|šç­­i}äº~}á»jÅZ]ccöl²M]¹¢»ŸLFÊ¥vZàܹôÌô)¸¡¡­ûr8¤›Œlܨk°=tˆBÕE‡nù™g€ÿþ³GEÅÝÕ±k×.L›6 æ½9’¥ºšâíÕJ§š½{_¤A©~‘ø|úËϧ*] CŠècQE° Zp>Ÿ¬µ5Éh=T¡W*%™gÚ4Šì2†DBµt®^¥ˆ0àûïÛÏ#õõdpè!ŠlþóO*ØùñÇÀÁƒö‰¬q+ôI…õüy ¹¹®®®à0 YðŒ`kKãïž{(½oÍR2SSI€}ë-*Èòè£ô÷úëÀ'ŸP8ïõëäÑY»X²")Q-„†R‘¢ÿ[Ï U1,êNv‚ÂlõY^Í@— «ª@Ý'Ø ÀƒhU`oqËýfÐW¦>€3HÑ´  SàO´b²ðwË1ÕÏñ<µ‘ŠR`»ùÙö0 à 33³]u½ƒðj*p%CEÚ°v¹œÚ¤45QH“1vì ýÌÍi6&VWGµ5)£ûöÉåpZ«òÚØàe(4¥¸˜Ž %{âDýy¬r9E, Jÿ65%Cü'Ÿ´çâr)²B™íûÃíCrårzÿÕ¸ºRˆþþýºû*•dÐÒ® MsÆÊ••¡*›šhmÓ®ú Ð|ñÞ{¤x«-ôÍÍ$8jG q8tý¯½ÆÅÁƒnP(úv©ÉøøxŒ7îöTž÷ñ¹mMÒËÊ:×ÖÉUU†#º±Øx˜èåË4âƒÈ|»®÷NâèÑ£˜8qâ }'7—¦øã­b”JÒ3fÐY^nx_±˜ tB!?ÐÚ—¸°¬ø-IüL]FælæÎ…_Þ|ø!P+ -ûôS*³Û"¨×),á0ç`Â8z™ã·ßô·ÃQ©HáS× §Ó뫟°s']«:­Ý×—ÖóçÛ ÓžžºuB¬­i^ÿóO]£mE͵ÚS€› öŸ|¢Û·ûÐ!š‹µ÷åñè711iU†årúž¾KÀÈ‘r47wsoé^BYYq×ù~HÝMU¹ß““ÉBÐ@,( éãI(`Ó&šÌÔGG²j<û,µ—éá)jššôÏ J%Tûï§9!>Þp”ÆÉ“d\™6Œ^>H‘oÛ¶µîÓÐ@…Äžx‚wÑÑ”¥Öf̨„½½‘Å¡ô9…U.'EÓÌì*‚‚‚À‰Œ$ ·£Á%¡xýzò$'“Pzï½ôð9œÖ¾Ñ|>GSS²è½ú*y[‡Åœ¿AŠ™|>àèÝ|Qsh<¬Ý Àqè÷Œî)ƒ¶ Q o^ÐrjX`3(ÄØŲ ?Ï•à>K[ΣýR0 ó8²9¤ð«#`Ù²MýÜä¨.H™ÖFòÔöá›ææf´zX¸zõ§S15s=¸P 1âréµ?ž,è†Â‚¦5/ÕښƲ¡5&?ŸŽËá°3nœaKþõëä}è˜11d˜l‹\N€º¶@@JégŸ‘`¥My9 *ÚÅ]£¢h-9qB7 .-­5¥DMl,]ÇßëNÜññº Sä¥ÕîÓ]V¦ë år)Ýêý÷)Wþ§Ÿh?™Œ u˜¯ö±ƒƒéœ‰‰´oU)¶m«os¹$„™˜0`˜;£ÚÍ ‰ššŠpÞdÝDuuû0››„aZÛsìÛGÆÐcÇ(µD"~ý•Œï_~ÙÞSWG†ö˜e˜öEy9L7mê\/ß[½Ÿ­[éÝÕ‡DBÛ¿ûN¿àSSCBÎ_ÑØn{½ê.$MM‡·ö5T*²²²¤¶Ì)4IùQ† mcÆÐòE}/½DFM‘ˆöçrõ†•ÉŽÿ÷ôÎ×ÖÒêç×~_ˆˆ¨‡·wõMŸ;‰¬ÌLDÖÔÀlçÎVËUUM ·cS7>{¶Õ*œ˜HáJüÑÚÐ×ɉ”ÏuëH9U__2ôõ#âpP×Àí¹ÆF2°üóOûǪPÐxŽŒ$yåÙgß§ù;1‘~õÜÐ@ íìÙ­¾¾OÛóòÈÑ'“‘¥~wê®ãîðx 8œ[û}ûœÂ*Ó„lf–‰¶àXY‘€9w.…¤·(Û"’€éåp+¤@WùSSà$Z•µ1hÍ»ìJÜàQ´Ï电\£º˜’kËõ©1Ak_S€FŒ2Úòèê4’@mrÜü†Vï(ZŽ»­#1TxI­è( ms¼h´*áI.¶Ù> Tœ©’É{ õõõP©T­ác*pî\£<áþéRlÛ.0ZÑ÷Ä <ýüh!5TÑW"¡ùyÀëff†‹Dääè.ò!!4¶µð1 èµÓ§LiíÓ§HD¡\ÚJà„ t»¿ü¢»ou5M¤Ú눉 y7«ªtó=32(]¡,ðg·S=a›š¶Oi43£PßK—H aò„š˜´Àæré³W_%êúõdT+.ÖꨟOJLQÂŽÑ‘ýt°±Qa̘2}·,ö¹sç—ÛQ13“VîNRTDïÃŽ4¦Ià­¯'ãÉúõT|ïìYŒmm)õäçŸIÁX¿žÖ'Z©PP{½/¾ EôòåÖËÚ±£µBu}=½G¡ñ}ð`ÇU¼o…‹I8p@¿\™’BÂËåËt­m•í£G)BîwH6¬n#ŸËdd$ž5‹ ;••´žWUqÑÔÔ·{á^¸pÎÎÎðñö&KØ’%ÔB@-¿äåÑ`Óz¨ÍÍô¬==)ª¤ÌH݆!O‡µ5y@®\Ä i‡{öÖ2xì’¡öâup‚‚`:&11@½ÌŒ$Òo¿¥Ð²–IŽcn—1A€§'Ì,ù˜7ÆA[hb"9°Ôó¥%9a/_&aX{¬ÈåT S=s8†ÚÚ ±‘šJžmúõ£BIÜê,‰È@k­'"qÒ$2(?NïÞùóú \r8=óᇭŠèáÆûgPJØ–-t|//¶¥3\ß½r8ô][z'qÚ¯±±}Qذ0ß?LëÓäÉ4E˜v£^ÓçÖª*àС455ÃO§gÍÁçßD¡H€P¿£}¸o#( W-LBao…+Ð ?Ö!bk`t½Mfúš¬ý‚µõ”š‚ÚÊB òxš¡}Ë€¼£÷Pø¶EhúP[IM@ʨZ!­E{OiHn)´mà ¯í× üÜ>Hyy9ø|>¬,-i6áp=b!úÇÚþ¿\]·^¹v„ssò@ª€XP ;Ñ Ô*hÃ04÷«‹O¤ ´·æ‹Å´¯¶'ÔÑ‘<œŸ}¦«àr¹TìQ;–ϧfòÎÎ4ñª÷W(Hxhkø47'èéÓ­–q++ý©½”S¤.°&—Ód¬Oб´¤ô€³gÉ»? ᆢœœÈ¢Y[K Ë´iƘ{ïm=ÿС¸+Q(8wîÜí© uuP8¸ ªJµf5 CúÃ{ïÑɸ³w/-öK—Òï6z4ézç ½Šˆ ™èÉ'©ƒ¯/0}:jé¸yyÀÔ©$H$$×%'“  T’¡$-”Ù†uh8 ÿ¿üBÆ–¼¼Öã©‘JIÿ‘JoÜ‘ÑÔD޵#èÝhk„R((Gòÿ#]«¾¾¥ˆ¡Ö÷¡èˆAƒH8:¾ÕÁ¢R‘ÂI ÁÀôlׯ>ÿÜII}7ÇC¥RaçΘ2e x ìÚ…L«¡ÈèÕÖIòÒ%J Û´Ió` šMLh®=vLëwQ{’Z´»²2 ã\¸çÏÂäâ”—*QX "ëùsd­k™¸E›#êÓ¹ÀÔ©àøø ©I«ò¼ 9µrÇáR˜“C¡²ÚcÌÞž”Pm‚‚Ȩùíaä*)xú ÇNœHi,éé­•Ú h "…xófºžK— ¯qýúQ+š¼<*(“Ýé©77z—³³I26‡Hгƒ9ûjAÜÎÒÐЀc¹¹°Ü°A×5þÀ´à}ñ…qË‹>T*@åå4 ©'î¤$š|ø¡µˆ„©)y£6n$!¢‹‹ë>¤ìõëGÿ/‘pØ0ZÌÕDEu|޶Q$oíÙCÞž÷ß'ÝÄ×—”¿¶XY‘27{6½\.]ã‹/’0³m $nn4~ƒƒIÁýçÚÏɉޟqãè¿j»®Ž”™ŒŒYÚFšŒ z/fÌ ï$%éÞkb"læ©”ÆùGÑüÒÐ@¿kŽßÇÓ6??úlçN²Ø«£šbcé¿55ص«ï–}/++Cff&Þzë-zxÏ?]^¥€·Z^˜9“Ê´ïÙCÑÉ Íå"˜—×ÂúHÌú{¡(?¹¹<dì ‰³ºšBýý‘y•uò Ìâè(<úp=—‡ gžÑ¹¹øaC[jŽq8dtY½š¢lÔË)™LטÈåÒ¼¹mµmófÒÚMsâgŸ‘@.Ð<Þ6ú õæÑGÉ ñôÓ´æònr¹äeõö¦kçñŒ—2 ¢÷úï¿é½ww7¼¯ºÙ„™=/u›C88^kî*êëqlófø‡†ÂaÀÝmff4Æ'M¢%•R‰ssŠc÷òjhd2RLMMi€I¥T17—&”§Ÿ¦IrÀ åhkm¾%µ©‰ŒäãÆµ¯ã*—SÔÚ²eÍuö,yä É -e2ÚïìY’3üý[e¹œ‚ššHÏ–HhM07§÷K$"è½÷ÒNH ãÌ’%ônq¹$¥¥‘,áãC#*ŠYC“|òÊ+$§iuNÔA hMíºô9…õàA.¤âÇ=iboûbt'¹ åªÀaOµÙ¦5±£ ¤¨ éôÑuÉyÕÊvaÁ:P¨ì8v Ù:´*v¦ \Q5n ÅO*~$FûpåQ ÏkHñT£…äŽ)á¯ÈC«Â[RJÕÿ `9€XBµåÜêó Z®ùKoƒ”ë¶Ê‚€Ç¼×ò½yzž€—³ÍfàHûV~ŸJ¥Brr2æÎK1I..€™**(„ϧI&>^¿Q$¢Å^=a ®¿d?ÃÐd¨÷cnN–õ-[(‡A½XËådýk; ŽMûò y†LMi}±°ho31!%ô•Wè;³f‘ðâç§ßŠíäDž«/¾ 9N"ѯt«‰¥sú)­gÚÞ¶…tÍj¯OÛüѶDDФ®Ï Ù Z|Œ)¶jR‚ïV233annWµäÛÔ×û*G@ËÅ7÷ÓïSTD­¢" ¹¹dINM¥0öQ£ºæÜ<@ŽƦv…Ò¶LœHá‘ÖÖºÅ^ø|xžy†ÄúzR"CÐèÑdȪ­%'Æ?’å~øpúÞ$ˆ_¸@Ί{ï%”‹ í;{6oúwX½2½=Ô*SFGÓù7o¦»”àñÇ[eGGG2%$P^ »;mï(§/rõÊš˜@øûïÀܹ¨màC(¤(˜š­ðTWWr´PZÎEþ Î×;3 ÊP{ {{š\\4£¤ ]z/¸S¦Ì2€?7Ðz¡-¿ИÒ6Ð…„PÄÀÙ³ôû«£hjjHnK¿~$ì~ý5ý¶½7ú:R …¤œ&&Òxxî9R Í·#F€\TDc«#„…™oÞ¬«lëÃÔ”¼ÀJeçjæ ¬[u˜Å*d7"eÓ&ÌiÛ·MµõƒÃ¡‘“'QŸS‰o|?Äܧð(ˆ§$y±˜&ÂÅ‹iPª ™™µ ¸û”J’3:³f+d¤Ûµ‹N‘@Æ5mCòÙ³dð[°€æçuëèv ¢[QÏÏû?èõœ;—Þ™ÈHR`—.¥w®¬ŒÂr++IÖòò"9ËÞ¾Õ¨hcC^þ÷Þ£óþóí«]îA]¬8'‡ ÁÁÆeíŸâã;îÅ|;éS «\$$ˆaaQˆð{ž$“ÚíLh0¤PýÔf[#H1TcÊ3½Y΂”µ,ºXk›¤Xª'Ò'@9«ŒÖð\€ÃG‚MgZîC›Xòø%€ZŸ7¼¢Ñ ªÂs¤ƒ¼£œ–{ Gk_kr{”c[ÜrlŽÖµ,ðÈ£›…öÞh(6À»ž6ðŒ|Bެo)¬•••((( sçB ¤ ×PÿϺ:š¸Ô ­£ck.œ¶ Â0$H´íðñØc¤'ÿöý¿ZAöõmï‰È ”—Gym?L“l¬~Ë´:ÌöçŸ)´±¢‚„l}ù›\.Y9_y¥u S÷ÎÓ‡@@¡+´6…7†‹ )ƪžjs#^ÐÎ(«,À±cÇ0zôh˜tFª¸IÄbÊ[.+rsxå•ÖßRÛ >aóŠ Fêºb🛠,\h<ˆË5îèú­¬Ha‹é½R¿Cööd؉‰!a'9¹µòµƒµekh ‚°Û¶‘°¥6&q8ôŽDï¶§g«GT}£G“Òõòˤ¼~ò‰nK;;š¼½É!hìÝíËd?ŽY.ÐÍçãòe 7åóÉ0¢]u\›Ë…Öð¾o øKÈ9Ù£%…ã¾QíæËª*ââxšu6(ˆBÑÿþ›”Dõ|¤PÐ|«¥ÂåÒo[YI¹õk×ÒÜ]]­¿ê-‡Cžök×ȰéïoÜègbBcÞÓ“ §Æô .—Þ•À@ºVí(CûûúÒìLn—Ûù°]udK'ÈÌÄ•-[ ¸÷^x«Ë?C(¤pŽ3píp`)PÙ¬[7‚áÃu÷år5Vª*àßɘèäd|~Þ¿Ÿ¢·ÔÊ 1¶l¡yPÖñÚkäPG~Éå4Þï¿¿UŽŒ¤“ ¨m«“EzSè°\NQ1ê1äåEmí>ü ~ÕÕ”Þ*+ ºÊ(@ÊíóÏÓ5~ò‰þ÷ææ7>¿r8Slo'}Ja•JÑ£+Pœ&‡µ©i×·&`@žJ!È+¨M5€3 °ZµÂ׈V¯j5t‹9C7d¸-"‹ ð2Z>5™¦‚”ãU ÕKYÊáT+ ÅO Î)‘Ú„øn{¤ ¶e¨Òo²Ö÷Ë\Ó:×gtH‘-жHóo‚<Ñb÷·Ù.)àë@ýYgB?Ó`Ä*_>®V},ž2++ t_/¿ ˜›£^D^µµÜÊŠr´Ëø«ilÔµŒ[Z’àñÏ?daVOŽ CÊZÛssš„Ÿ}–Ö•ùó阧N‘BªG¥¾]O?MóàÁ†•6?¿Ö0[cÇÔ¾þ_$»3Š >K¿!„BÝT–ÛGii).^¼ˆÇ{¬KާR‘<9™¼ˆææôOžÄ‡f*ðpþ'0mœXéãpÈÑÕõŸLMI8ÈÏ'ÏeWÁå6¤ðùdý7Tå4$xã Š²Ðv\¤Ø~ø!)íéédìjygjJA†¡yÉÐ{Ô±÷«¯R__ùþý¼l0j†ÆgD)zgÎVX]\H¹TÃáP8àˆºáŠ*ý†m[¯Ü?…a¿÷E¿ô[ê fP× ¡Ô¿°0zoÔ­ÉÚbjJEæ¤RÊÙn>Ù€Ö*OOÃëÛ^OÛ4cô6Áûn£®¤9;ãùóo¨5YCå-ÿðERíÜIFd}F…‚r­i¿óçiLMŸ®kQ¯ÅÅdðøøcš¿\\èQ§7 ¤Tþöå‰j{Tß}—¢åòVƒ}=^ÔŒßZÔ’Ë%ùäƒhÜff’>®m‡åpè;t77:vgÚ´ÆÆÒ<~›º±õ}Jaµ´&+GÆg‡aZUÕ:K¶ c½YÄ %r"€çÚlK)©ê#)SÓZþ ]Ŭèé—rHÛrTèè*€=ÐÍS-yKƒ”»§@E–Ô½" AJ¡ú×õoy[ZŽcÖ¾¦jx ÀJЭ¬ÆΛØr! eu Z•eKlh9F¨¨’6NÖ€r]/˜¯ç\6-ÇIþ>±h¹‡Uho<Ц9¸víBÕMQ[f(&]µÂÖ¯y@D¢öÂBvvûºÏ?Oc>ÿœþ_=1ëOù07§Ü ß§: * ±†&Lkkòöœ8Aç×öÆèC($¥zàÀÎy±ý-Xî\âããÔZ ûP*)oøï¿I(X²„Þ•ÊJ =÷ò8rq àÜ|•È[aäHÊ-êM…YLMõ‡ÙK¡Ådä2ä71ÑŸ»ÈBìݻՓ'ƒ7oÀåB¥¤±A†²ÒR®õÚº•¢KÔós@)«WÓøVçefÒÿ·5(ðù´UåcSZ…±|5ú=ׯ§qjL@61¡¿Õ«ÉËß‘àÍåêÏ]e¹³Q©TØvý:ÌÆÇP­"uu4ÞŒ¥”fd¢ççGFé£G)ŸS߸KM¥´> åuìX×ööd`WËF dˆ[¶ŒBâKKI)U‡Û^¸@ ëo—3%…ŠÉiþÔ= ï»»“a]{î67×϶¶À[oQ¾öܹ­­ú´áñZ£änc†É¾D¯SXU*ªªªPYY kkkôë×¼ÎÆÏ)•àýú+&Ïšާ'µFIyüðä-ܱ À)²šò$ª{‡ª@çÒ®‚7 TŒHR*%Ð-Ä*œtZÃu*J´¤ÔÕøTWm…>RÀÕJb €@ÊrHËõi{¥hUF³@…˜Úæ…ò@y¦CA=LŸ4ðB@žã/[Îñ-(|W› ÏXò²ê«¸×6­€nnoÛ}:Êi ćR©DQQÄb1œœœàààn'¥T™T ñÙ³˜rõ*¹/ZÜYYäœÖb 13£ 1?¿½Âš”Ô¾€å¨ýú+U &áäØ1²hêÃϬí "üÐCÆ…m aŒÛy¡ÜÒ²sû±ô.d2òóó¡R©àêê kkkp:c*Öâ¿ÿþÃ}U‡:ASš¨©!/‡C¡T~ØÒ‚¬eüéèÂb1Iõ†*lu3=tÚ›ÂÙ™"X{“r}»Q©T¨¬¬DUUlllàææÖyY@}a!Žÿþ;VmØ^K\`]V† k5>Lù½Ú¯XÜZPK©)kj¨½Ä³ÏRgFFûžÕjlm©HÒùó4÷+•­kˆ>Ô!¹_|AkKgŒ‰¦¦lèìŠR©Daa!$É Ë*`àÜ9––âСCøä“O4›²²(¬ÖÜœæåÇÓïÙW× (´[  °×éÓI6ðð ãvSÕ]RÖâó)jcõjúüüyŠih ƒù{ïÑ»Âü¿ÿµ¶KzäRZÿ¢¾úJ˜zÿþ­’:ûH|}ɣ˦ݽNa={ö,¾ûî;ÃÎÎóçÏǽ÷ÞÛ©0@~^8¯½†þJ`sˆe *¸UÐïÍÔ9Zó/µ)yQ_,: Ê­4)£¿øDkw‡U òj΂n0Àwp9(/4¼eÛö–k€¼š³@á±ËZŽ+)¹j¬AÊí?€¼œm½šæVƒòBÿðÚÃ0ºÊs[8 9¨åž@ p[<¼ò,*Jp.b2™ »ví¯¿þІ†xyyá©§žBlG.G5Í͈:qîk×êÄØ©ó-µ…šéÓÉÂøâ‹d¡çpèoèPýa‡|>-II$¼äæ¶o)£ §¥?üˆ· ª¯¥ïÒØØˆŸ~ú ûöíÃ0èß¿?–.] ψÅNKK—ËÅÀ\.êJÓ C㪾ž,òŸNÈÔ©T©Úήh>Ÿ\Vݘ/ÛW`ßcàÌ™3øþûïQRR{{{,X°÷ÜsOçB_YpÖ²šˆÅª«6^Üsg9w®µê'‡C^ÓS§ÚW¾åñHÀ "ƒÍÆ4GÏšeøRòîGGS•Óδ¦05½½õ,Yn?2™ ;wîį¿þŠÆÆFx{{cñâÅo1ÖÐågŸá׺:ŒŸ1n-®TuÿàW_¥\äÍ›)òÊ×—dµ2§R‘Vm0çr©pV8:y’”Õ5khþïß¿½baA†›óçéQ+²>>º)Úÿ/RäÁàÁRl(Š€Ã¹ñ9[¤ëVèU kUUV¯^)S¦`ãÆ8qâÖ®]‹~ýú!²må=ˆ›š°ÓǺE€¼›ƒò+-¼àcè!e\hÙ>"«Û³¤<ª{’^k9Þó ÜÐ{ÐÚ× oçG ^ +@Êêt=çÞ²í=‡¶¤/D«Òòǃ<¥ЭŒËå©zƒ”ÝzèWmAJr( {5Mй–;6h­ï|1ên"99ëׯǪU«0vìX|ýõ×X¹r%þùçXëköنƦ&äÜwÂÕfÇví¢pm!rÀÊqJM¥Ê¸d‘ÿýwýÅ2ÔDDÐ_] &¬5¥³0 ƒ¿þú »wïÆúõëáââ‚wÞy~ø!>üðC˜uÔ$(mÚ´ ‹-‚¹éY¥"Å´ºšZ¸p8ÞõÇ$à¬\IÖ÷»VVwo2%Ë ¡–U¦OŸŽo¿ýGÅ|wwwDè‹õkƒêÂÔ8ßo¿…@K‚ýñGºÕãÖÚšŠ·lÚDž¥7ߤ¢_ee† oq¹¤’öìÙÎ…Ú …†ÛİÜ}$&&âÓO?ÅêÕ«1zôh|ùå—Xµjþúë¯NÉ*Êß~Ã/UUGEaéãƒß¢ÝíÞMFñµki¿×_§baï¿Osº‰ ¥]¿NÊ­vŒú}ˆŒ¤ötW®PÈîæÍT¨QŸqÝ‚PCùÖúàpØÚ½‘^ÐsñâEX[[cæÌ™033ÃèÑ£ˆÓ§Owêû&&&X>e9Ìß1'…ìy´ )OI ÂI2’ PHï1çñ=ÇòPȪ–›RöÔL&Ú ŸÍÕó4¼ × Ãƒr>@•z_C{O°€‡|à%è÷N @žÓ…FÎÅ)¼]TÝ’åÆ8uêŒQ£FÁÌÌ 3g΄©©).êëÌ®3Ä-_“6‚yyûâHB!yY'L ¢G|> ;S¦t®}„ ëlb¹1”J%Nž<‰‰'"44NNNxä‘GŸŸœœœN#77"‘ÃÛVƒ…~ååRù€üqã¨èÄ×_“7ÉÛÛ€²*—Sî·LÖ¦&'Çpì$ ‹ °³³Ã<333Œ;þþþ–U²“’p"">CZûÚ‰DäÕv`ñx”×üÙg¤¬òùTX†Ï7ntTcfFïFW céû¨e•‘#Gjd@€ÄÄÄN}?ÍÛlðð£OB¥B,¦põíÛ[Ã|ÕxyQº†·7yN÷ï'cùã>>G•o§N¥H²»!‡ó@n¼“=IDATn§WyX/_¾ ôk‘¦MLLŠäääN}_ À3Í“ȶ ¢)Èsú€ß@9¨Îhõ¶n)ƒþ pÚÁ üRµ"»­½Dò0ª=¦“A  ¾§)h9–±Å…À Ä(™U?O?ðÀӬΔ¦î!eeeàr¹p¾]…ïÒÒÒ¦ñ¹ºº¢_¿~HIIÁ¸N˜ù|3¤¦šá̲::Rh`X µ° œ¨aÃzú Èd2xh÷ ¹C¹zõ*üüü dc|4¨T*¤§§cÞ¼Ö477#??¿Ã_WUásswí!‰ƒâb ¸@ß66@zøVýà~ƒ¬HÙMÒþsJÄæÚ¶VàP*)±O=ø¿ü’’˜¬¬(V80þ½w/•£üö[Š-»rssakk »;))Õ©©©ÜÍè.###NNNš0Ç•UÎüQå=6ð5í7²³I Õç¼25mmgÑÚÿdffÂÃÃ} ,);Æõ“––†¨¨(MTŒ››\]]‘––†¸¸¸¿ÿã¾z43k°qcÆ£P^KKR0õØ"u¼§7—«ÿ¹”J%rrrЯ_¿;~Œ‹D"Ô××ë£Þ=w½Ja­¯¯ŸÏ×€<ööö(//7ú=¥R‰’’çA)§†¾ò€‡5 ÔG´T©Ö­½Q ¢BrPN§ö¶¶¨Ãn¥¯*(ÌèâÅ‹055Õ„OÜ©¤¤¤@("¸cŒ ª««{U[‘HSSSMásssXXX ÂPÓTR©P©ø¸pKKò€òxÔ@]º½ôÇ`w“‘‘±X|CÅIz+'OžŸÏïÑ­©© =ý(t¨¯¯× åµ³³ƒB¡@‘†¶\.uuu(((Oi‹Âœ±X™"ãb E`)Š‹ÉÃê1eD5ú/°ƒ…I)$MMûëèHR¿HDnX€*b¨Tj ~1† !%U  Ä§ÒR*)éïO.[“[~‰Îž= ___øt¦ß`/çðáÃ]R¥ùV¨¬¬DsssO? ÚÊ*|>vvvÊ*"‘EEEè×o ¥²T£°Úڒѱ·ÏáÍ}111=>6º‚žã तJ¥²§…me ˜››ã*• (..Æý÷€Lƃ…q’Q¬¬zÿW(8}ú4"##áØQ³ß^NAAŠŠŠn¨PW£·ÚOýŽÐŠTmC·´àñxðóóCjj* ;7"Û·ùoBÏÞ'Ã0°²²Â¥K—zöBº…B‰D‚„„žy¨ à±±GcïÍãðññÁÑ£GammÐÐÖ1.‘PÞQa!ýõv”J%†é±qÑ•ØÙÙ!==ý†«ßv*• uuu°¶¶†e//§Ì0 u…$=8::ÂÌÌ Ç‡‰‰;T÷€‡P¡° ºc%K ¯ÈËÕ=ˆTJ Mm)*¢¿¶û^¹Ò~ßNzÈŒ! QVVfÔu§àááÑãïjUUÕ£ü›Ç…B!ÌÍÍqòäIXXXhZÕhG¡gg÷ôt[[[äää 77÷ÖÖÃôôW*•¨©©ÑiùÒ›16;;;#%%gΜÑ('"ýÝiXYYáúõëNe魨礞ãÍÍÍhjjê”gÞ½JaP©TP*•àñxP©TJ¥F-‘‘‘*ÊÄÂÒÓ…BÒÆáp P( P(4aðú¸çFº¤³°ô  …Bóo©T ¡Ph4ÒÁÔÔ>ú¨­l¸KïâfdSSS,\¸°§/…¥S´•Uär9”J% ~ÇÃË-êéKgé£ôª¢KAAAhhh@uu5@.—#33¾¾¾=}i,,]ÂÀQXX©T €ÂÝÊËËï ‹1¸\.BBBpíÚ5ÍgÙÙÙàñx}"|…‚ƒƒQWW‡ššTÙ:++‹•UXú DAAd2ª?QQQÁÊ*,=F¯RXccc!‰pêÔ)H$dff"11÷Ýw_O_ K—0vìX$''ãêÕ«‹Å8}ú4***0a„[?8 KÃår‡C‡¡´´µµµØ½{7ÜÜÜ0hР[? K/`ذa¨®®ÆéÓ§!‘HpåÊ\ºt‰•UXú qqq¸té²²² ‹qêÔ)TWWwª8$ KwЫB‚ÝÝÝ1kÖ,lܸ‡Baa!âââXA‡¥Ï‰˜˜¬Zµ nnnÈËËÃܹsûDEQ.—‹éÓ§ãâÅ‹øßÿþ333”––båÊ•w|µE5˜5k6lØ€ °°&LèTl–;¨¨(DEEáÍ7ß„««+rssYY…¥Gá0Æ2¨{ˆüü|¤§§#  èéËaaér’““Q\\Œ¨¨(¶õKŸC.—ãüùóJ¥ˆŠŠêT£y–;¼¼Ÿ¯Ù®T*Q^^Žúúzðx¼v÷ÉÒ{Q*•¨­­Eee%är9ÌÌÌÚáÊÊJÔÖÖ‚Ãá´ê1ÕØØ¨Ãêí Ã@,£¢¢ÍÍÍ011ÑsÝAcc#ÊËË!“É`jjªs>…Bòòr444è}›šš4ïºP(Ôy×o÷»ÊÒuÈårÍf¦Ý<-—ËQ^^ŽÆÆÆvsÃ0H$×õQYY©w èj†H$Bee¥ÞyZ{œ qÊ0 QYY ©TÚîýèh `é½477£¬¬LïÜÆ0ŒÑ¹aÔ××kÖSSÓZºõšTUU¡P¨s­ÆÖ•J…ÚÚZTWWC¥Rµ»VVV¹s©¯¯7:·544 ¢¢2™L¯SUU¥YnD¾íd2ªªª ‰`bb¢s/wš^q£ô®«éCÄÇÇãçŸF~~>¬¬¬0vìXÌ;ööö€„„Íö~ýúaáÂ…>|8x<¤R)öíÛ‡­[·¢¹¹ÄâÅ‹áïï€^¾7âôéÓˆ‰‰Á /¼ssón¹—òòrüüóψ‡R©ÄÔ©S1gÎX[[C¡PàøñãØ²e ªªª€E‹!<<‰üñvîÜ †aŽ^xNNNhnnÆŽ;°mÛ6Èår 4Ï>û,<=={úçcéÛ¶mÃþýûQZZ '''<ðÀ˜:u*ÌÌÌ “ÉpèÐ!üòË/¨¯¯GHHžxâ  åðÇÄ‘#GÀår1dȼüò˰´´⫯¾BFF,--1sæL̘1&&&]~ à 33?þø#ÒÒÒ`kk‹™3gâŸÏGSSþý÷_üõ×_P*•ýôS$&&ÂÌÌ qqqX´hÌÌÌnû»ÊÒu466âçŸƱcÇ ‹áíí‡~ãLjÅbüúë¯Ø»w/ <<K–,ÑÌñåååøüóÏ‘šš L™2³gφ©©)àÂ… øé§Ÿ——777,\¸#FŒÐQº ¥R‰„„üðÃ(**‚§§'-Z„#F 5嫯¾ÂÙ³gabb‚áÇã™gžÑŒÓ¬¬,|ûí·¸zõ*lll0oÞùä$''ÃÌÌ 'NÄ‚ 4c8%%›6mµk×àää„Ç{ cÆŒŸÏ‡\.׬uuuÆO>žIJJbfϞͬ_¿ž‘ÉdŒX,fž{î9æ¹çžc®^½ÊÍÜÿýÌ–-[˜¦¦¦Ûú®²t-¿þú+3aÂæðáÃLii)³~ýzfôèÑLEE£T*™Í›73S¦LaN:Ť¥¥1óçÏgÞyçF*•2‰„Yºt)óÔSO1ÌÑ£G™{ï½—ù知RɈD"f„ ÌÚµk™ÂÂBfÓ¦MÌĉ™ÌÌÌn¹—””fêÔ©ÌŸþÉ2Ÿ|ò sÿý÷3EEEŒT*e>úè#föìÙÌÅ‹™sçÎ13gÎd¾ûî;F.—3 ̼yó˜W_}•ÉÉÉavïÞÍÄÅÅ1§Nb†a233™±cÇ2›6mb ™µk×2S¦LaD"QOÿ„,FP(Ìo¼Á<òÈ#LZZsíÚ5æ•W^a-ZÄÔÕÕ1MMMÌêÕ«™Ç{ŒIIIaNž<ÉL›6ùí·ß…BÁÔÕÕ1÷ß?³råJ¦°°ùý÷ß™ñãÇ3ÉÉÉ Ã0LBB3zôh毿þb ™eË–1?ü0#‹»ü^”J%³gÏæ`:Ä\¿~Y¶lóì³Ï2"‘ˆilld/^̼øâ‹LVV³ÿ~f„ ÌÁƒ†a˜ÂÂBfìØ±Ì—_~©y?&OžÌ”––2 Ã0ÿý÷3nÜ8æðáÃLVVóôÓO3/½ô+«ôrÊËË™ 0Ë—/g®_¿Î\ºt‰™3g³víZ¦¹¹™©¯¯gfÏžÍ,[¶ŒÉÍÍevìØÁŒ;–9wîÃ0 “žžÎŒ3†Ù¼y3SXXȬY³†™:u*ÓØØÈ(•Jæ—_~aî»ï>æäÉ“Lzz:³`ÁfÍš5ŒT*íò{‘ËåÌ_|ÁÌŸ?Ÿ¹t铞žÎÌž=›ùðÃ…BÁTWW3qqq̇~È27nd&MšÄäää0 Ã0‡bFÅ8p€ÉÉÉa^xáfñâÅLSS#“ɘõë×3?ü0sáÂ&!!™9s&³qãÆ^%«°9¬ÝÀµk×PUU…^x^^^ˆETT!—Ë+++<úè£ðððÀÌ™3amm3gÎŽ9‚°°0ÜsÏ=ðññÁüùóQZZŠ+W® ¶¶gΜÁ<€¨¨(DFFbæÌ™8~ü8ªªªºü^233‘ššŠÇˆˆˆÀÓO?ÚÚZÀ‰'àåå…3fÀÃÃsæÌR©ÔÜë‘#G‡Ñ£G#$$sæÌAJJ pèÐ!DGGc„ À¼y󓓃k×®õôOÈÒç΃¯¯/æÎ gggL˜0^^^HLL;v AAA¸ï¾ûàáá  ¶¶iiihllÄÉ“'1eÊ 6 áááxôÑGqúôi”••!;;ùùùX°` €‰'"<<‡‚J¥êò{9þ<±`ÁxxxàÞ{ïÅÃ?Œ¢¢"ÀÁƒ1|øpŒ7ýû÷Ǽyó••…ëׯ£´´ ˜7oÂÃÃ1bÄLœ8GEAAÁm}WYº–'Nàž{îÁرcáêêŠiÓ¦ÁÜÜ©©©hnnÆÑ£G1aÂŒ9¡¡¡˜3gQTT„¼¼<\¹róçÏGHHâââ0lØ0>|2™ gÏž…™™æÌ™£Yììì4k@W³wï^¸ººâ¡‡Ò¼ÑÑÑ(++Cuu5âããñÐCaèСˆ‰‰Á´iÓpüøqÍ;+‰°`ÁøúúbÊ”)ð÷÷Ç‘#G4ÏÉÝÝ]³<úè£P©T¸xñbOÿ„,FP©T8yò$.\ˆÐÐPøûûcÚ´i¨¨¨@AAŠ‹‹qñâE,X°ƒƨQ£‡£GB"‘àâÅ‹`óçχ‡‡¦OŸWWWœ"""0pà@<ûì³J¥P*•8sæ ¬­­ñÈ#ÀÃÃ>ø ¬¬¬8|ø0"""0iÒ$øúúbÁ‚(..ÆÕ«W5kÀ¬Y³‰¨¨(̘1ÇGMMMOÿŒX…µˆŒŒÄwß}+++€D"Amm-œœœÀãñ’’///¸¹¹,--ªö“““­ § €¹¹9®\¹‚ºº:äææ"&&Fs¾ØØXäç磺ººËï%99æææðõõEFFÒÒÒpÏ=÷àÅ_@!A!!!š{uuu…··7¡P(‘‘èèhÍñÂÂÂÐØØˆ‚‚Í}ª ‡ÃAvvvOÿ„,0sæL¬Y³FVWW±X¬ ³INNFDD„&‡ÈÛÛŽŽŽHKKƒD"AVV–Îo’’”••!??2™ ¡¡¡ší111HNNî…õÔ©SñãÇ£¸¸IIIH$X¶l† ‚ÚÚZäçç·§999¨­­Åµk×  ¨s/—.]@k@pp0¬­­ÎÎÎðõõí¶{aéx<¾ÿþ{Œ9åéWTTÀÔÔÖÖÖ¨¨¨@YY¢¢¢4߉‰‰ÁÕ«W!‹‘‘‘xyy„B!"""t䘰°0M‡§§'œ‘’’Òå÷"‰––†1cÆ //IIIX»v-<<<›› ¥R©ŽÜv hÂùíííÑ¿ÿv2™šàà`0 Ã×{9~~~زe œœœPŽfee%ìííabb‚¬¬,XXXhÂb9¢££uÆEHHˆ&UI[¾•ËåíäÛˆˆÔÕÕ¡   ËïåÚµk¨¯¯GDD²²²’’‚ððp¬X±)))ðööÖÈ`VVV 18†`jjŠ«W¯Ô+òòòz•¬Âæ°v¶¶¶°µµE}}=þüóOœ9s‰«V­ŸÏGuu5LLL4¼P(„ƒƒ222ÕÕÕ°´´Ô(¬¶¶¶©¡¡A£ €››D"$I—ßKuu5***°~ýz¤§§C¡P ,, /¼ð<<|8–,Y333ÔÔÔè\«££#T*jjj`kk ‰DÒî^ª««ÑØØx[ßU–®E-Ĥ¥¥á?þ@FFFŒ¢®®"‘Hç·uqqAss3êëë¡R© •J5‚@¿}EE”J%jjjtÖ@GGG$''w˽”””àÒ¥Køï¿ÿ4sòÌ™31{ölÈd2466¶§µµµhjjB]]ÀÌÌLg{II z×ýýý5:´×–Þ —ËEpp0”J%Ž9‚;w";;=ö<<ùä£ß¹Ù{éè>Yz<îîîðòòBAA®^½jtc¿­J¥2:†»s\\¿~“&MÂÎ;ñÚk¯áðáÃøë¯¿ îßÑ85v/Ýù®²t=B¡¾¾¾pppÀåË—Q\\lp_•JÕá¸0†±yóVILLÄo¼]»váÁÄ?þ¨ ÓGGã´£kíÎ{aéZÌÍÍsss\ºtɨ"v«c¸;çñüü|üßÿýþúë/ 6 o¿ý6òòòºå^XYåÎÃáÀÚÚ €R©Ä… Œ*b·2·u´Ü ÍÍÍP©TØ´i6oÞ †aðÞ{ïA&“ÝÔµö¤^q3° kÃ0 š››!‘H4ÕM—/_Ž9sæ`Ó¦MhnnÇÓ Ã@©TÂÎÎÀçóu^¥R .— +++p8p¹\A(—Ëann®S½«àp8ðööÆO< Mžê¥K— R©Àãñt®U¥RA©TÂÖÖ4ÛÕ( …B˜››kîS{ÇÓñJ°ô>˜–vR©öööxüñDZjÕ*„……aË–-ôaš°A.—«óÛ«Ûâ¨Ûep8œvcÃÆÆ¦[î‡ËåbÔ¨Q¸ï¾û ‹¸¸8$$$èŒqíkáóùš(‡Óî}´´´„@ ¸­ï*KסR© ‹!—Ë1`À<ùä“x÷Ýw!ðßÿh?† LLL`ff.—«wŒ[[[ƒËåjÖõö¶k@WÃãñ0wî\„……A(‫«+222:\SÔÞ…¶÷ª¾ÖŽÖ–Þ‰R©Dcc#h*‚¾÷Þ{¸xñ".^¼¨Ãúæ6§w J¥ ÃtÛ<ÎápðÜsÏÁÏÏÖÖÖxâ‰'PYY‰ÒÒRðx<½kJ[9ÅÐÖ'«¨×–Þ‹L&ƒX,†©©)&OžŒW_}/¿ü2~ûí7”••i¼ÿÆÆ°¶¬Þv\Zº£².—Ë… žþy888ÀÅÅóçÏGFF¤R©Þ1¬}/mǰZ¯PË1w‚¬Â*¬ÝÀîÝ»ñÕW_iþÍçó¬é·‚êêjˆD"”ãzíÚ5MZHHˆ& ‹áîîKKKxzz"''G³=55NNN:îü®ÂÕÕ:/ µµ5”J%¤R)BBBPRR‚ææf”çURR???ðx<ôïß_çZ333abbGGG„„„èlS癨ÃMYz'ÍÍÍøî»ï°gÏÍgæææð÷÷GYYÚ °´´µµµðöö†™™|}}u V¤¥¥ÁÎζ¶¶pww‡™™™¦è@cÜ××·[z±zyyÁÜÜ\Æçóamm¦¦&(ŠvãT}Ý...°··‡››[»÷ÑÍÍ ÎÎηõ]eé:êêê°nÝ:M.@¿·““ÊËË!¨óÛ^¾|aÂÆÆùùùší©©©ðòòÒ¬555š5 ©© ÙÙÙš5 «ñôôÔ‹ÀÄċŰ´´„»»{»qêââ øøø€aPÎÔÔTõª¤¤D㱨®®Fqqq·Ý K×PZZŠ7ß|S1Àår éìààgggY$55îîî055E`` Äb±&…G.—ãÊ•+šß}àÀ(,,„B¡”••¡¦¦FÓf¦+155…³³³Ž2lff¡P±X M¨§ú^´Ç°º'8@ï^^žÎví÷#''*• ®®®=ý3²!>>k×®ÕŒA‡ˆD"H¥Røùùir·RXÓÒÒt~÷ââbH¥RÐ@üüüÀçóÛÉ·W®\©©i·´µ±³³ƒµµµŽì 6˜477kô u ‡D"Áõë× Žáüü|477ÃÝÝVVVðððh·8;;÷*£ «°vfffØ·oÒÓÓÑØØˆÚÚZìÝ»C‡ÕäÇ"-- R©¹¹¹HOOǸqã#GŽÄéÓ§Q]]¦¦&œ={*• QQQ°··GXX<ˆ††ÔÕÕaÿþýïE/44b±‡Bcc#jjj°sçN„††ÂÌÌ #GŽDZZòòò •J‘ššŠÂÂBÄÅÅA `ذa8zô(D"qøða¸¹¹aÀ€5jNœ8ÚÚZH$œ:u fff ëéŸÅ&&&P*•øçŸ““±XŒ’’œ:u Æ @c8!!eeehnnFBBêëë1lØ0XYYaèС8|ø0êëëQ__}ûö!$$^^^ „ Ž?‰D‚êêj?~ãÇï…566‰‰‰HKKƒX,Fff&N:…¨¨(…BŒ5JS1U,ãĉ°±±Ahh¨f,ïÛ·‰D8tèbbbàëë{[ßU–®ÃÊÊ %%%رc*** ‹‘’’‚ëׯ#&&¦¦¦ˆ‰‰Á‘#GPWW‡ÆÆF:t^^^€úõë‡Ã‡C"‘ ¦¦ÇŽÃèÑ£ajjŠaÆ¡¤¤©©©J¥ÈËËCjjªf èjFŒ;wj„ò3gΠ¨¨ƒ†³³3 „hÆé0dÈ8;;kŠŸÅÇÇ£¹¹UUU8uê&L˜ 9öåË—‘›› ©TŠôôtäçç#..®§F#ØÛÛãâÅ‹šy¸¡¡‡†©©)àî€ìÛ·b±µµµ8|ø0†+++DFF¢®®‰‰‰J¥())ÁÅ‹5u FŒ‹/j Ú/^Dmm­¦÷oWbmmÁƒãÏ?ÿDMM êêê°{÷nÁ%((æææ8qâšššP]]'N`âĉškÍÎÎFVV¤R)233qíÚ5ÍûØVV9yò$,--1hРžþYŒ`ii‰#GŽ 11Q3·íÞ½AAA°³³CXXd2Î;§)ȯ™ÛFމÔÔTäççkŠå#..&&&ˆÅÑ£G5kÀáÇááá¡S ®«ðóóƒ­­-þý÷_Ô××£¶¶»ví‚¿¿?¬­­1|øpäççk ûåää ##CG¯8uêjjjÐÔÔ¤I:t(0xð`5`ÿþýˆˆˆèUFÓ›”ûUUUøè£˜˜ˆàà`ˆÅbTVVbÅŠˆ‡ÃÁºuëAƒáÊ•+ ÅòåËaii‰òòr¼õÖ[H$puuEJJ ,X€¹sç oÔŠ+àåå…B¢¢"|ðÁÝ6ynÚ´ ¿ýöBBBPWW‡¦¦&¬\¹RSñ÷ÝwßENNššŠ¸¸8¼òÊ+àr¹ÈÉÉÁÊ•+annsssdffbùòå7nŠ‹‹±jÕ*0 {{{¤§§ã™gžÁ<ÐÓ?!Käååáµ×^ƒ\.‡··7***Àãñðî»ïÂ××555X³f ªªªàåå…¤¤$<øàƒxê©§W¯^ÅŠ+àìì .—‹ëׯãý÷ßÇСCP”Â_|Áƒ£¼¼B¡kÖ¬§§g—ßKss3ÞyçM¥ÈÂÂB899á½÷Þƒ““ ±jÕ*MHÎåË—ñâ‹/bêÔ©(7ðõ×_×¼ëuuuX»v- pÛßU–®ãÔ©Sxûí·áîî[[[äääÀßßëÖ­ƒ™™®]»†•+WÂÚÚZSqråÊ•5jjëñþûïcРA¨®®†J¥Â;ï¼___Àÿýßÿi*T_½zÁÁÁxýõ×»Åû®žká‬,ÄÅÅaÉ’%077GJJ Þxã øùùA&“¡¬¬ ëÖ­ÃÀ[·nÅ/¿ü‚ððpÀÁÁ«V­‚‹‹ $ Þ}÷]dgg#00PS­õ•W^Ñ„³ô>T*~ùåüøãšÂ‰YYYxðÁ±hÑ"M[—7ß|DCCÄb1Þ{ï=@þÕW_a÷îÝ2d²³³áããƒ+VÀÎεµµX³f *++áåå…ääd̘1Ï<óL·ÜOjj*Þ|óMØÛÛÃÔÔÙÙÙxñÅ1eÊ…Büûï¿øæ›o†’’XXXà­·Þ‚»»;d2Ö®]‹ÔÔT!##111Xºt)LLLPTT„U«V OWFFž{î9LŸ>½§F#Ô××ã›o¾Á¾}û0pà@Èd2äççcéÒ¥?~|8`ݺu8þ €ÞŸ+VÀÛÛr¹¥¥¥X·nN·†ž†UX» m‹¼ bccáèè¨ñ577#99W®\App0ÂÂÂ`jj ‡†a ‹qôèQEÒÛÛ[²È0 qîÜ9ðù|ÄÄÄ _¿~šªÂ]\.G^^Ξ= ÄÅÅÁÒÒ\. Ãh¼ÀˆŒŒDÿþý! 5÷RUU…“'OB.—#66žžžšÜ€úúz;v 6l¼½½5Õ&Yz7UUU룗—¢££5ùê<×'N ¼¼#FŒ€&‚a”––âÌ™3àp8ˆ‰‰»»»æýP(ÈÌÌÄ¥K—àä䄨ØXØØØtËWç_¾|©©©ð÷÷ÇСCann®¹‘H¤ñø6LÚ©þ~NN`aa˜˜8;;k¾{;ßU–®C¥R¡´´‰‰‰¨®®FXX˜ÆSÐï^YY‰S§NA¡P 66%M©T";;‰‰‰°³³CLL ìíí5¿½T*Err2._¾Œ   „……ÁÌÌ¬ÛÆxcc#Ο?ââb„‡‡#((HÓr„aäççãüùó …ˆ…«««æZär9._¾Œääd¸»»#66š1ÞÔÔ„sçÎ!??C‡EÿþýabbÂŽó^Žzm¿té "##áëë«™§U*®_¿Ž .ÀÊÊJ#Çháôôt¤¦¦" C‡ÕŒaõpòäI”••aøðá:ÇîjÔaë ‹ÅˆŠŠ‚¯¯¯æ}T(¸zõ*’’’àâₘ˜X[[k®µ¹¹.\Àõë׆ÍV‡I;vLïÀÒ{innFzz:233ajjŠèèhôë×O3.d2™fnóòòBLLŒÎÚ¯öF"** :ó¦z Ëå6l˜ÎÐÕ(•Jàüùó5j”F¯`R©III¸zõ*BBB0xðàvz…:*høðáíôŠ‚‚œ;wB¡111pssëUs8«°²°°°°°°°°°°°°ôJØV–^ «°²Ü0êrÙ¬sž¥¯ÂŽq–¾Žº…ÛK’¥¯ÂÎã,}u«»aŒ³ +Ë “™™‰•+Wê´9`aéK;v ü1êëë{úRXXº…ÚÚZ¬\¹©©©=}),,Ý•+W°jÕ*MÛ–¾ÆÑ£GññÇ£¡¡¡§/¥ÛaV–F$!!!‰¤§/……¥[(--Err2d2YO_ K· “ÉpáÂTUUõô¥°°t ¬¬ÂÒ×)))AJJÊ]!«° + K¯„­ÉÝMáôéÓðóóÃþýûÑØØˆ   Üwß}¸páNœ8‡I“&aôèÑšÒÒ·‚B¡ÀñãÇ5¥Ø÷ìÙ¹\Ž!C†`Ê”)°±±é–{mnnÆ ‘H0kÖ¬n+[ÏÒ»¸xñ"ÊÊÊ`nnŽ£GB¡P`ĈˆŽŽÆÎ;‘™™ ̘1]rN‰D‚½{÷"((ÙÙÙ8sæ FñãÇwÛØ‰Dرc\]]qÏ=÷ÜÎÇÌÒCÈår9r–––¨¨¨À¹sç 0cÆ 899aÛ¶m¨¬¬„ƒƒ,Xww÷.9¯H$ÂÞ½{ 77˜:u*†ªiýÔ÷›€¬¬,L:NNN·óq³ôb±{÷îE@@ '''LŸ>b±»wïFCCüüü°`ÁXZZvÉysssqᄆ†b×®]¨¬¬„,Xnk¥ÑÜÜŒýû÷£¹¹³fÍ깋¥wSSSƒ}ûö!44»wï†H$‚ŸŸ¦NŠÌÌL9rr¹#GŽÄ½÷Þ«iYs«¨e•àà`\½zgÏž…P(ÄèÑ£1nܸn“Ujkk±sçNôë×'N¼ºÛaÖn¢¨¨_}õ¼½½ •J…/¾øû÷­-†Š‹/bõêÕøé§ŸÐ¿ÿ[>§R©Ä±cÇpýúuØÛÛcàÀ¨««Ã§Ÿ~ŠúúúniØ-•J±uëVl߾˗/gû’ÝE$&&bûöíðññÁàÁƒqõêU¼ýöÛðööFÿþýˆ]»v!>>‡ê’sJ$üûï¿prrB`` 233±zõjXYYaäÈ‘]~ŸµµµøüóÏ‘žžŽ÷Þ{ïv?f–B.—ãСC¸víüýýáïï3gÎà•W^ƒƒƒ¦§î¿ÿþ‹šš|ôÑG]r^‘H„ŸþûöíCÿþý5ç]¹r%¾ýö[øøøtËýúH¯áÑÞÞ^ç=ò÷÷‡Ã18oذIIIz· >Ë–-Ó{o°mÛ6ìܹ÷Þ{/† ÂÊ*wÖÖÖ ÒŒgoooXYY!$$Í·^^^eño¿ý.\л-** o¾ù¦Þm\.C† ѤW“U±fÍ”••µÛÆápðØcaÆŒí¶ …B444àË/¿Ä¾}û°råÊ>+«°+S/æ™gžASS“ÞmÆò‹ÚZì ÎÎÎxùå—õ*\.žžží>W©ThnnF||<¦OŸŽ}ûö´L±°ÂÁÁ/¿ü²Þêv\.z¿ÇáptƸÚËeˆ¬X±B¯B!Я_¿vŸ«T*äççC `úôéøí·ß0iÒ$½û²°"((¯¿þºÞ±Ççóõίyþµóë¸\®QÐØ±cõ*¾yôåK1 •J…#GŽ`Ê”)Ø·ovî܉E‹õôcc¹ƒ9r$üýýõn311ig(Q#tÆtG†’yóæáþûï×»ÍP´™J¥‚D"Á¹sç0cÆ ìÛ·Ó§OGLLLO?6–;ˆG}÷ÝwŸÞmÆÒ'ôÉ*†æq ,Y²Ä`!ÙC¥R!//B¡Ó¦Mï¿þŠ &ÀÍÍ­§[—Ã*¬½¡Ph°©{WYÁÕ/”¡p1CŠ€P(IJeˆüü|lÚ´ ¡¡¡°¶¶îéÇÆr‡Àáp  õØ06önƒJƒ¾ó3 OOO¬^½¦¦¦xõÕWñË/¿à¥—^ê²¢ ,}Ÿ›{7ŸÏ78.;*î±páBÌŸ?r¹?þø#¦M›f0Ä…¥-·2ön@`ð<ÆŠ'™ššbÙ²e4hrss±iÓ&„„„è ¯daÑÇÍŽ½ÅÐûÂáp Êü ÃÀËË «W¯†P(Ä«¯¾Š_ý/¾øbŸ“UX…µ³yófêÝ6aÂÌ™3ç–ÏQ]]7¢¶¶¶Ý6¡Pˆ èµçp8ðó󃓓žþy,[¶ Û¶mâE‹Ø2–NQ[[‹o¿ý555í¶ Ì›7£Fºåódffâ§Ÿ~ÒlccƒÿýïíBhär9¬¬¬àîî'''<ù䓸ðÃÓ.Dž…ÅÙÙÙØ´i“ÞHkkk¼øâ‹½S7B||ÛîsmYÅÙÙ/¼ð–-[†?ÿü .dCƒY:Å¿ÿþ‹ääd½ÛÂÃñdÉ’[>GSS~øáTTT´ÛÆápðÐCaòäÉí¶ÉårØØØÀÝÝŽŽŽxâ‰'ðñÇ#::£GîéG×¥°šE/féÒ¥z-ó@×Y.]]]±zõjƒy#YhÂÂÂ0nÜ8lݺ“'O6æÆÂ¢““V¯^m0ŠÀÌ̬KΆuëÖéã§S‚ùøñã±cÇüðÃˆŠŠb…y–N1hÐ ¼ÿþû·4ö:Ã=÷܃1cÆèÝÆår;µ^¸»»cÞ¼yøàƒ‡¸¸¸ž}x,wãÇLj#ônãr¹]6/^¼Ø`Žag½\ááá;v,¶lÙ‚{ï½—Mñ`éO<ñ„Á¨]åaµ°°ÀŠ+ ÊC†BëÛ2aÂìܹ›6mÂСCû”¬Â[³fÍšž¾ˆ¾ˆR©ŸÏGdd¤Fé“J¥èׯBCC…[*•bðàÁpuumw uþ‡¾?C/‰\.‡§§§N>“T*…³³3‚ƒƒÛíÏår žÃÔÔT¯R©TB `èС077—ËEHH LLLúlÂ7‹.2™ 2dˆæ3‰D‚j*Ô)•Jp¹\½J—Ë5:ÆõyêÕ^¡àà`¾—jO‘¾¼WgtŒë ‡—Éd°µµÅàÁƒ! abb‚þýû£¹¹lÊ»õXóññѱ¨8ưaÃ`gg ÕÞ΋y3cO¥RA¥R!<<öööškQ(8p æ3mø|¾Ás¨ûrë;B¡@DDÀår ¹\•J¥Y§Xú.ÚãJó¦öJŽ9R3K¥R¸¹¹!88¸Ý¼|3cO©TÂÄÄ‘‘‘A\¥Ra„‡‡ë²…B¡Áó2Èè“U‚ƒƒ¡P(`jj ooïžþ Xºõ¸:t¨&ßT.—ÃÎÎC‡Õì'‘H¤W~½™±§ž_µeõšâïïß®o·:=ïFä!€d;;; 4Hsýû÷GSSœœœúTz‡1äZcaaaaaaaaaaaaaéAØFT,,,,,,,,,,,,,½Vaeaaaaaaaaaaaaé•° + K¯„UXYXXXXXXXXXXXXz%¬ÂÊÂÂÂÂÂÂÂÂÂÂÂÂÒ+ù…‰Õ°óíS%tEXtdate:create2020-10-09T19:38:13+00:00Ùm„%tEXtdate:modify2020-10-09T19:38:13+00:00¨0<¾"tEXtpdf:HiResBoundingBox1396x1123+0+0x{JXtEXtpdf:VersionPDF-1.7½8;í(tEXtxmp:CreateDate2020-10-09T14:37:31-05:00’Npß6tEXtxmp:CreatorToolGL2PS 1.3.9, (C) 1999-2015 C. GeuzaineÛ©AJ(tEXtxmp:ModifyDate2020-10-09T14:37:31-05:00&°LæIEND®B`‚blis-0.9.0/docs/graphs/large/l3_perf_zen2_nt1.pdf000066400000000000000000000716671422157504600215530ustar00rootroot00000000000000%PDF-1.7 %Çì¢ %%Invocation: path/gs -dQUIET -dNOPAUSE -dBATCH -dSAFER -dAutoRotatePages=/None -sDEVICE=pdfwrite -dLanguageLevel=2 -dEmbedAllFonts=true -dOptimize=true -dDEVICEWIDTHPOINTS=1396 -dDEVICEHEIGHTPOINTS=1123 -dNORANGEPAGESIZE -dFIXEDMEDIA -sOutputFile=? ? 5 0 obj <> stream xœÕ½K¯&I’ž·¯_‘Ë*}~Xh!!i„™½p5ÃTÄ‚ôëåfö¾fæç|Õy2»D°Ð]UùyzXÜüñ‹…ùkÿåËõV¾\ò?ü÷ïÿüSù"ÿûçüéúò‡2®/¥=sÿ»Œv}ùçÿðÓŸ~µ|•òöÌòåžO{åËŸª³?o©äÿð:åÏÜ¿ÿô¡NÅ:_þïŸö÷ç¹ê—øwÿæ§2ÊóÖ²U/Y¥¾=r-_½Ì,ÿ9ÿ^ómjÚêþãÊ×Ç’d‰e´”~»%¹¾û©óËÇ?ì§ý_~*ú"¾à?ÿç/ÿê?ý÷ÿn}©×—?þé'{?ûÚêóöÈ}´}©­~ùãŸú»ŸË/óçËÿùC¹ÛõvןëQ<æ¿ÿãÿòÓ¿þãOÿöÅ«Z­ì;oéU}}ùj¶á:ŽZ´õ\½½Õ–l±$ÛŠZ´•k¹­öìGÛ³-”¶¼–ÛJµÜÖêõmÎl %‡-¯å¶R­h‚×>A¾.–d[Q‹¶r­°Õ÷ ÊaËJN[¬¶¢ÖgÍØG^wÝï­¼Ýû½i£a‹øC)_Z{Vy¾üñö_ÔÔ\.üU±¿ê/þ GÍÕ«ýÕþŠg›Ž+¯èß})S.ýßïþáS=Ë×wýÄÇ~äë«fÿ®oyÝèßÛù ½Êc—GþyöµÚsêõÖW³çþo~ouµÞþŸ~Ùå×sÍŸÿæ—r½>ŸŸÿÖÿöÿe¿ðÙVÿùë/uw5==;ï÷tÒ]\÷®¶ÊÛþ¯^É¿üã~îÿaÿóç_ZÓµôìÙßÒת‘Ý­®ÝVÙlÔû‘¶¸àþCŸ»äÖgs×û­îQ®²oí‘’9wKÆ]Ëæ|—<×x[UúÆú\oþÓû~<,‘·ùÜÚ'”«mƒR ‡¿=rý­ý=÷¥tù½ž·[Kž})rêöÜÊZ)m_ÖéåM*z–vÛµ•Zö¥ -™vš:ú›2¶ß‡Ú¨»uû’÷ïÝç¾]Êå>¶iÉÚW2¥äºì,ýz¤éÈ• ½åÒû¾;õ2»}ÿaUR2ìúGÝ³Ž’¹/FŸÂ¹浯æÆ]ëõÌÝ\Zç®:Д¹ïnÝ8—Þæft7.½žnvÖØ×óØëïg_Õhö î&!]ð½öÅ胸ºúÙ/´áY©Õgìk±'qÛ“ØãñÛ­Oë’ßu¿à·¡5vƒ®Z2or{±'Sw}»––[ †>™:÷C»í ngŠ7õ[;š¿ûÒ¯ø¿Y>À8öË5Ãø À8î†ÓËý¼ÇqØfmÔ ÷Óx‡ãþÃ<œhv¤!›plÖÀ‰c|Žã¾þ;ã(ŒÇý6çd{€Ÿ¹ñ;qÜ@¬w8>@6pDëvûîÅÇc¿*às÷áõŽD6pDIÂÏ!áxÙrž@J{i'Ì:×}âXqæ„£=à ¤½Ù ¤™M@Öü¤>ÈÈÝM¾r3ð@öÝîÉ °É}Šy ¹é:œÖ¹& ÷ô¦@jó9€èSÈIüȉƒÈÙ2{¨­úïü瀳p.yýë)ws_ Îç)%‘ù<òà˜Ï³ßü“¸|ž~Œ’»Â˜Ü?í‰ä.@ "÷)PH>2Aq"Å@Âq_ßȃãþ Àã®õ„%¡¸ ¬k!‹»!ZÇHwr¸ÏÒ†û 3ƒ»:G;CP/*ˆ»à’à>¥µUò·MÀføí‚ŽFŸÞùðíßõ`O+ô@ï‘w–‡B}™%¡§&2yzÒ•ÀÓëÌÜíCŒŒ†Ý>¤Q n,k²€n2Q`ÌíëXˆœ¾ñ‘ˆó&@àü5“¸}aÝ®ÀyÃoÚðòø§-wmò;¡¶Ûq=HÛ¿¸XþRÙnö ’Œicd’ .ÀY*sƒÜnTM|‚©ìቦ²¯jÕ T{€*™¨ÝJå $¤vË|+wfªì^c9Sb£ÏŒUÙ¯¦´ÄUéëÍ&™KŒÞw&«ÈR®g´Š¼Œ–ÙÚL .9ùódºÊ>åõdÀöäµ'ƤÎ,²x¤¬Œý¦ŸŒY\39‹['hq.’&TÛD-NEÖÊn$÷“`“*wÉ´…]â&Ït=™7¹âÕ3pòL×ÌÄù;rròr0'uê“¡ ;¤.Ž"vÞpœ;=ÃÊàù;vòâ(¢'uÆ“Ø+}¾ÕšáÛo_€ úâLPÚN+™À21îlm«#»ÀFÝ­¾Ö´üfä¤{W'ŽbÇpÑùmßž ì-[÷’ä–c]é·»åú³ÿ¸w²Ä’l en)~ÿÆ>YÑÜrßrð­þ뾯¬é¢·“W¯HVÓó¨E[ả­ìº£­¨E[¹–Ûr×ÛJ®;·åµÜVªå¶Üuç¶’ëÎmy-·•jES¤ë޶²ë.0kÑV®¶èº [Ạ[¬¶¾ßÁ×d$žÏïÕÁ÷™æë»þâcòõe³?û˜×þ½ïv¯õ=¿¨SV%«†{í_þŸÏ:Öš,Èš8 «vPûÂûæ_Æ¢{Ïít l{ºb«%ñái:dšwc1k‰ôèêm[%O·õR]6jsÏ%t½ÔàrÙ+ö"£É.¹lmÒ–øt̽VQ"c™.ïmÒ¶G«%'-‘ß·|òÐ#¦qïZ³u¸^‰Ì‹­>õ~dúgíý²µç®·o¬š»Hmì•ö¾Ž…uù£%{¾V¬N×ß{q/wóìU뾌ç›QÄ{Æu§–ìaý­`¥Œ’=s¸mnóâ½"-2|ÊÚÔ< ½É2ê1€þžûJtQ¹×.zn¹‘N3­Ò÷¨<ÿj¤ß²bGP{þ_ì)Ù[ícê°#un]Mô¹_ËœÉDZר×[¯ð!XÝ{”•œo}ɾÂAW´dà«”¸®ô¨µR·';÷†·ÜðèQ÷nÕ1×Cß“ñ·‰'aÏO·è²A*îòÐöPùz¶@¥:Ç̦ !ð§=ñE1f>žò$ʇ1óÄSÆÃyŽ™kž#æ]1†OœË§:W<å}×O©3Ïsá™;žmb,veß¼€êtP¿|Ê~€­%÷Q]pi¢½&wfÎ "¨ž»;û ë 0]¸k´7›‚À]å~ky¾ºë,³÷y.sÔ@¯Bþô–lðjwµÄŸ43꿼FâOoû‰¿G€®Ì_<>ò§%#á—.ÆÀ]PÅ-j•z€ZeÜ @µ;ï ”‡ÇtÜ%Å\¥$PKÔgHõÙ”šÔ’;¨%=zòÙ©¦Gõ×<@jÉLÆ£€îi&Z üí‚a^Xò§F6‰'¨-ëNüESKþ¸ýdõ¦0–G„yµÌ:á[{_'ŽbÇ|Þ7ï½¢-Y÷’äEcWðé·{ÑÖ”©Èqw,I–XFKé÷oì›ú} ýuþ¸¯lîµv~`zS/^Ѧ½¯£m…§¶ŽP:ØJay°•k¹-÷´¹­JG[–G[©–ÛrO›ÛÊ¡t´ay´•jES¤§¶ŽP:oÀ–[¹VØ¢§-l…§-lyXžÛú€»=ÖhÊߥ;î3Ì×wÝÅÇîäëËVv1¯Ûü{;ß펛{ò±êGwÜ?oT×Ïÿù—¿ìŒ›W—Û/÷#¬ñÝ·Œs}M鎧Ì$dš»é >Ëdð¸%rAKêž@<òtš‹`ÖMžŒAû-ê”oÖ»ÚìíÚK4MÕuŒÍçžÙ P>êé‰e ­s·¢ §)+@»•Ûü]³Ë4ÔjØ 5÷˜d3@‰ÁÓ£†|“3Õi+¦ÝÍUkíu™3fÎ=*ë°v›Ý̹oä1‡-ýæºtV³Knû4>׮ܵΰ™À\{y q?µÚª`Þ{úð¨O²Ú"}Þ³Yô(‰s½gs½/Ÿõb¼¼O:×§“ãnÐyaL :w³¼O:˃§ó.‰ÍËUbKöÄfEƒ :5Ø$±‰ÒÄæÝO2ëýn¬¬µ 2k³IMYÇ}rYçIeÇ \ÒFp xâ_/™JMd–ùnœlö™ê-K\Ž cœaiœDW\V LL\L<‚Køj—m½÷Ãù<õ~tÆÜݲtÑ 'rwK ¢~§%z· WfbOKFž¨ÞφLJÅ=S5¿Ø{ÔãU{¬®ž'±·Kì{(ÑÛKÐj. ¢÷\ã²@2¢÷ˆã¬? ½GÚ§ÝÐ{®ÝNÔqDô ꪾ]ò˜ ˆð=—Z­ß.™æf!|Ï%óÙ'Á·KŠ—¾]ÒÄðí’ŽõàËu6~,K­¿]²‡úžðÛ%—Bü´ŽáµÄøÈÔ£Þ Á]Ò,êÙ–èd‰î’Ûâ á#Wqµ„¡–Ô’0|ħ¹î„¡ÖY-a¨–Kž®êQ5LÌ€a:90|$âr%µÊÈãc:8T»:"‡»ä¶WNŸRô™‡ZsXx- ¢Š“;îžS#Ó^ÓÝt¥ ŠÕ2ë„kí}8Šu>óywÜÓ7%[÷’äDcWðé·;Ñl=8ŽëDIÞI‹2ßI¿cwœ„KßrßÜÿúëÞ¸oì–èÕÒÿÆË7$ë£m…Ÿ¶²Ÿ¶¢måZnËýln+ùÙÜ–×r[©–Ûr?›ÛJ~6·åµÜVª-‘~6ÚÊ~¶h¿¬E[¹VØ¢Ÿ-l…Ÿ-l±VØú~oœxdv‡ù{uÇ}¦ƒùú®»øØ|}ÙìÏ.æWý;;ßíŽ{vW®3ù= ¸7îÿúå{\Ø«êŸÕ+§úó/»sÞs ™Ó?ýeOݾJ 1¿µ{–ZÍ"̇ñ븵,Âü–€éºï»ØfŽÇ–Ž÷=°‘êÂæÇ=¡²Tº@ d»Ée!Ût´çJØJU±eÏŒ°•ªÂ…µÑÆVªŠm]ú}Ô&xvߕЭT¡]ø»l¢ˆh”Gfý«Tµ# aÛÛˆ%ÌSol¥jˆ5Ù«1l¥âgé§ înÔÏf»»ÀV*ùÒ®5zÃVª†¥ÇÓWGTŸyžQ°•ªaeôŒa[©äêÔîx°•JœDZ2+¶R5Ľ6Ü¥ìS±pìòÝËÐa ˆ#ÚA7Äɹ±ßnÏ|‡F*T„ ÐÝSÒ–GùÆÇú¶O¹`£Y[f¥–Ëb±Ô´E§Þ‚/¬½ô£¤ÕeõjÓ®¦a9Z°1·¤Ñ'Õá °-³£vàºÚTW\Ïä&±1p=ˆ¿ˆ@œ 6TýEw±ÔÆÝKæRšœ~´w.ÇžVëNr¹öm\%¹'ÎëMwÌç^¶)’\ú¹ÀòBb`yÁ XÊZáÄ’ŸuË‚°ŠÀ’nâÀ²ÀeXÒXÒuXVt.eíýÀ²N{ý¥~'ÎXÖ~PV8Êڬà (Å/ÿPФPÒç— 0P'‡²œË¡¬ó=”Ҵ׉å4d`)Žîç–Ø?èXÚZ< ”®fžPvl¾(;Áp(v–ãzåx%ú½åä®èå;$;Pr$”\×; ˉã'Œ«f?ã©s0Å9s ælcÀ|laïf³iÀ,Öù€y­çS¾d™W+È,õý€Y–ù¿ƒÌ‚$‰LtÃiÀÄŽÏ ³"$5È”­Yç€YfdV„o&2á¡IdÖv’YÛ»³–wd„Ÿ'6nÊÙÔµo"ÛKƒLù˜´N2ñ9'‘ o|"1‰L|gKdVÔ 2ù^œÌò\(q2¹ÙÉ”ë¹Ï³Ìs¸„Ï2È”™û ³rç­“Y+‡T’Y±É5ȬøžlÊ}Þ›öŒƒLþ&™µP`„dVW4 ™µ¼,+ÂeƒÎzq&Ÿõ2‡bòØÅ|U6#®ÌŸÀÐ2~WŸo™>ñ aœÄ°(°=yX”è×ëÎ㢻›ˆŸ:Bž–ð{Šìaî ¿\çÆ†HYê? ¿]‡ÛfŸ–ŒDß>¨X\éÓ’‘§«»dš÷‹ôéåè}’¾]ÒÌñFþ´Î³j§ÕàO ÔeFþ4^°?Áß®r›ŒªÝYtV+OXý —'¬zÔÊêÉgž°jIϪe»O¸ë, _$é\ 0#^‘>"½ÓzbPKFfP-Ûž\0¨vl×0ÔW=¨,p½!,s•Äà#Ÿ.KfP댖ÔsÕ'QÏ™Æ#‡úvžž8ÔsÍ–8Ôk®y”ŒèH÷lx]rÙí¥ÝuZå6™IÅzš5’Ãî¨Á#ø÷ëÞYWjÑ¡,ÙfIv±¡Ì×÷ñ;œu{æ4ÞÙ;––¬,,ùïßZ¬N"PÖú–³n/ʯ{ë^¼¬"ßYΨ¸¯GÚgXJ^8X:|uj)Õ¥£-…Ž–²§Î,EZÊuh)ñb¡Yžf×#Km\‘`@û ‹iq½¸k´RäJæ~jG÷‘íß·}LáçåÝ÷WlòèTÊ*æÑð_Õz•ÃFÕ}Rc²ÆÂ• ªfOl \û÷àu`¢]Ûƒ+áòµÊNÍ »¦oÒ—m}qÕ ‚+¼ã1x-´2n\˰'0ñµŸW2¹ïeP¨o]¸’juil@Iò~Ë<¢”ýª·*«å÷Ä•ÜÔû»ŸçÛ‡íÜv*BÓ¨>ÚÚŠîfT+í*¼s:í’kA0å.± A·…¥l´¯ V®Á•›î ×2ñVÁ;£ˆ¾á‡#‹º9¡,Êà»f§øO×~³ëI0>w[¶â Œ{ Ön,>O‡0!P|ž§^”‚r/DÚ‡×B{s ¶Å‡¢r¤PÔjîƒB ™} 6‡…•vÂZÞSX©ôèJí88ô…'8¬‚pÎa­l¹$±ÂS$Ö†Ö¥F9H¬ð¨‰µ×ƒÃŠýùä°Nô`ΡLÝŸƒC *‡âÊË$Êz­$Vz™ƒDD %±ãÅI„û ‘XÙ$‰×89¤ƒ¶ÂÞÊ9,Xz‡å9)¬Ðí"…m%(D´R¢×bŸtPØ1aú´Ή¼4,4©/¸g G/¦èã@Î¥ ȵ8<Ç»#à.€¼zÆQëH@ªª×Jx6é|K®¶˜‡ÊÌkeÔ$û9P»dV13j—ÌVFMbŠL¡Œ¬I V2kšÔFÆMÜßÏʼ¹+Í“øÖ§fâÜsFäÔ‡2{B.y^€\xΈ\ò×9Ýk¯È©—çÊC`ò(:ݹØ3vº»Ñ>h;ßøiÜ%w¸‹­˜äN·†Ö–¸‹ ÆºsfÂ._‰a—ÎkÔe«]5å™®DÝQ2p%7^¨ó½VX‰9}˜«uR%!§s®±¹ØíKäüã-6ÿ’7=éˆ9hR&oz'×JÄž^2§^ïáÌñ´.6M¸¤ÅàT9n>\(&Ÿ¥Ô§´"]øQTŽ%‘ÊaÉ´QñúÓ‡Zq\ÔzuÜwø×Ö!Î%»Ê#ϵÖý\ö”#ÑCºZ/ [, [^’lý¶ !†ÈÜí¯K·Å¤ñò¾¾|U–” ×r[˜Ò$[>ÉI¶¼–ÛJµÜÖ’Ñvd[(9ly-·•jy#ÒÞ~%[,ɶ¢måZnKDeî;ÛBÉaËk¹­TËmIôjÎS‚Ã븡¨ó½É †Ä?]õW|m»MÞ¯Ãk¶›ï¯¹áxTûõ£^xèxÔø\ˆ¿ÔÃ|ýÐW¼êO¾¾jðú˜× þ£­O§ƒyòS¦¤µ3D_ÿÿ¥ƒØËÕëþrK¸SÕüÃ~ü?šbÞ÷”ñ0äy—¦PÐOšç]c×Qµêó.yW»^S@ô£!z×\ÁL w-Y"&Cz×dVèón+Yïzÿ=>VRœwÍ=Í»0çÒs<ö”ê¼kÊ(޹ºLH—HÔœbWYü…:ï>OÃlÖÄy—¨—”,B¿fGJs¿²6ï¶[p&hóî|¢¥6¯e¾hóîG‰M ÔæM÷m^ ¡·ÏUÐæÝWLQz“æ]Z²öšÐË2¯>ìe¦Ì»K&fO¦Ì»?¿ÝA™w¿³Ç•y÷µ sS™w-ÚËI!ØB™wÉçrm Tæ]KöòÍ/¡Ì»ÏU ð eÞ%¿ôK&•y÷¹†õåTæÝ–×›ê@Q™wɶQÝ­Fe^ÝqÐMaÞ”y÷Ù§µ,*ó.!Âd®M™wW¹ÍiFeÞµDS1¥…X2É¿³ ýZ"[©÷à=ÿ|ì£ü'ÓB,LÚ2‘A1"åáÕƒÈý¢®y¹¯zdÉìÝF°—ˆDÎÅc&ÒI É6L*WáT•TJè_yœJùiþ§òÁ'r§’Ó¡”G9(Wát–Tîë·E™S)ßɳd¶ö¶t"–r¹5gjY«@È&°” Þq`)¢}ÏåÝaú}›ø¦ïTJ nYš~I]m¥|«è™ËýöðÈåº.ã’Ë!ËË's¹j±HŠà²T{8‰K¼¹àRüÉ97D®C. fÁ¥øåÖÉå³;—´.e»tVÌN–Ëý¯¬˜­=к3—2—ƒK~Lu.¡3XîÕ¥ ,ûüÞý²N¨®¥³¤ý~ÿYÏ~ÉW,OñÀÜÇ€)Áj£erÜ9mË’8¾–³H¤sM|ަìXîMzŽf½RÖ–x'¦7MÓï‹dËöà&ð$ò¥ä”I:{ZçÐø0†+&«ÍÆzgoɺ;±'Jt üWôÒìèI+:Ñ7`›=F&ðyBë#£W}óÕÙ‹ñÖ‡Æ94>ôEúÐ8¡»3V ¾¹¼Š>4ú C#BôbhAÁ’é›EŽ ë~À*|“f¬ܧyÆzSVŸ÷þú”ÕoôŤ&OYËŸì(¾Î¡ñB”¡ó7¡±àøÉË+#ã7mšIödòdùÒÈžŒí6ôañB`¢³çÑÙ“’•Ñ“¥”åµ zúœgBÏ_AŒŠ>Uæ¨Ø.NbXô9ƒ‹&ìö2D¬¦)sëwÖÉž¾÷µâ¸¨õê¸ïÏ&gˆ’ðê±,< ^’¼zÌ ‘lyI²…²d‹%¿¹‡%¾é!üLF‰¸-f5ÈΗW¯Ê²äZnË}n+ùþÜ–×r[©–ÛrߟÛJ¾?·åµÜVªåÈ}´•}Þø¼måZnË}n+ùþÜ–×r[©–Û¢÷ÏM…÷Ï-±Žú~!³Iüî<„Ÿéa¾~è+^õ'__6ø÷}ÌëÿÑÖ䓨óRàÑ$ûç¾?¥Ä¼eéL*½K‚·,TzטŸ‡H¯zœtMJ‘Þ^(ÒC&Ez—DÄ·¬“ƒEz—ÆÈq^;¦Õ0‘^]^)¥Dª‘^uúè(E‘ÞÝÊ‹™TéÝÃ’Q¥7\3”éÝÃÔ (¯Éô. zÒ-"”éÕáNûcÊôê_²Lv¸·(Ó«kï™SKìs½“é© uz÷vHÚB§7]éô†Ó:½Zå±*ªÓ»ä ¤IùB§WŸNÖÉÖNÁòe@§WΗéUG›N(Ò»+ÔC%[=f¦­ ^=è¶:¦Ñ«Î/ÓÖ…FoÌ ¨Ñ« q £F¯¾^»ihôî’ËëÔèÕÏ…Ho4ˆôê›[¦Po*½º~7ÉkSé]Kâ³Jï’ý7ÓDëM¦7—˜L¯>Šž3K¨w®~Â;G*—ì±÷A¥,§³vö’ÉtÏÚÙk@s<¨ÜSÆë¤²\öâœJÄs*忇tvL«‰¥»—Ë9®XJ@ƒIrKY=Ô–±œ³š¯Æ±ôéºcéuKñe_Y½>áäX^ÔÓ&–îÄw,eÕTsz ½Ou%8–.àéXÒ‹ïTÊ"äÉêÙ>§'”ydɉõDÒ?k’ôÅ“±Îä˜&îåTºÕ©tÿb`ymÇò‚êy`){ÓîK:ÌK¯ãXºÇ’úÀ²!i`ÂC€c)möIJ"žÀ±ÜUVÎ-á~¶ ²3“¡ÄJ;Í„0$ü@r õd¬œ\b›/ÖáŸâänǰÙÚ‘[b£pšŸÎˆóÉO.Á'âˆcФ‹ØGM¾Š5¹ðt<éÀˆQ³ º&ðäâ>ðDË:odÙ :ŸcÄôU±£éVMº¯Íé§„&&»©@SÜ+9óK.!›n‡pNÄr 1ÇÓ» â9EÍ´f<ç¨Þ'ž³ccbðÉ/#Á§ìÒž™Oi&ˆO>åhë ȧeiûèlOùLhœ“O)9S|8t>¥·œ,äsöÉãsJüÿ“ù”¡«'>å˜r ›â*9!“>Ó''dŠgáˆúGËé%–4•kî‡:sú¥%¢@ú ‚ðƒ BrÎ È ŒcŒ”D"ê s%×N}2„}0¹ ìâÀ{2„²AUgt„P|fJC(WŽJÂéÙ2„²SF½ºNá°ò'¢âÁ!1“OFp˜(!¨B{Çè(>¿«e%[Ô}ŒŽòÑfbDP}IOFPònÛÄöÚ¬/r»mƒ å÷c„ìýûhö´?‘?žÇø(Àm<"}.ÌÌÉŸ:-KæOÒµœ{iÉŽSK6AþºœóÎüI†+ç^Zêf[™?‘Ç[9µ„ÞæñëRˆÄOâ&Öñ“ÓÁ|ýÐU¼êN¾¾lïﻘ×íý£­Ê1QëKÝ÷¥™ØóÁ[þò½{-–sL,I Ã2µ{—(yëXHíÞ%:ºv´{u¢ñä,K¾è”¤Ý»[¾ÆS»w‰hB55_ÓîÕ€5ÁP¼wϹMžâ½z” â½ZÇÒJ˜vïšv¡Ý»6ÎQ»×—»”îÝí´_CBî²rï®rY×@åÞ}SÅÆw*÷î£Ü&”{—(€tÅ6å^=·Ùro\÷îµ^µ …{wÉ É[÷î›ÆWt ÷ê èJˆÂ½ËåÎ(Ü»dRjB¹îÝÏê†(/„{}]IÝÞ%S ©‡n¯*èNÓ6ÝÞxsÔí]ò MϺ½»‚¨Û«`ÝIJM·WíèC¶7®ª½º4ê&Ò«ª½ºîXY<[Om9%Lµw/Šyb¨Ú 7ªöÆ¢‚ª½ JÕÞðBSµ7Õ!çå8“'à[y&æèüsDrŠ–z¿œÊK´¥žL¥ÎÎ*=ŠÂ©”¼Ìv©”͉–ÁTŠŽ"0•’&ò½JÙ5¬î§Rrz¶‘©ìP‹t(û6ײ¢ö’¤£óÉTîé¶-=œÊ>+5¶¥,„ìÈ¥LøM«›\ŠeÁ¹ì ªBΥ쵲¼äRrŒöœþe—@¨&¸D¢HpyaNp ­¸ÀòÂΛÀRäc²žö.ylzX +–Þù8–]šKÏ\JÇbšÛäRâììäÒ»,çr ¯;—¢.çR:—šeíSwC0=ÀÚÉ’å&ÉÚïÞ1PN¦î]{4½ãp4+6~šµ Û É”Ý¿ã Str¾‰]§¿`"Cód›˜·èûäìL‹Û˜QYŽ÷ÑÞ™]„qv„ aÈã&½›œœÐù~Ь„xêÊáÀsJË]Ç )9ÎQS¨ÔçsRÇ'FM¹¥z ›ë~ǧL47}È&ŸþáÀùœÔyŒ›þ¹ÁùÙ€;+Þ/ æ™®xÐYŸŒg´6â­xβХOwê¤Q‘Ë1jJ”×<†M´·5}DôQ“•5EJttr–£¦|Ü{7jrdõa³žƒ¦µ·„¦ds:Í‚À@“N¿@“æ@S¼/÷Á¦ä}6éLlBVßÙ”~Ô¦ãRNL™9®œˆiʧÔûIôM™@éã'}SüÚ˜¤~ó¾ ~{¹^í5¿ùhz¿)bh–á‰ø] î'ðZð¼8nW2ª…Ö2êqY™À²§÷6÷&ÂàµàYq5·XÉJ¤—¡DÅuc÷I%rS'‹ l¿´á™z¤©(Íÿî@Q§Ð>ßT]Ç–ôxKgP¢ç1s-7„zAFÆ:‚~uŽ ‡š:‚òø0¹‚zì ÖÂQ‹ Ê^t’È ì?&®E&@%#(%6$‚ëõËN¡lã?H‰µGA Uh´e ã R()Ej†Pf~혺ŠtÇ•¿è\ÐúBB(Zžv)Iñ+'Ò†V¨ÝÅšu²³í}­8.j½:îûóNÄ¢$k,‹Õ½—$ÇsHä«eIÚ¶‹²´m—%¿¹“޹'¾½ÕöÛ¹'⮘ÿ û?^¾)ÕÖ͵ܖ{ßÜVò¾¹-¯å¶R-·åÞ7·•¼onËk¹­TËÛ{ßh+{ß¼íy-Úʵܖ{ßÜVò¾¹-¯å¶R-·Eÿ›› ÿ›[b7ôý>:æøÝ9é>ÓÁ|ýÐU¼êN¾¾lðﻘ_iðlýPæ ™öK\}öÑý–É'öäázSI?Šù. ïYå~‰êTî÷8VlÖK9_ý@g)+LÎw‰¤©Î(ç»D§¶d5mÆL÷r¾îœ¡š¯úÙtúD5ß%øwÎ>7TóÕoµ+‹iï’ËÖE”óÝ%HE9ßøžK9_=Êd®!çÛ(ç”óÝv{9ßø´M9_ýh^’œo¬;(ç«%5KÝët_/j¾é ¨ùêÅØÃšoÚ¤ 5ßtSPóÕ_¶çÊÔ|ã>Õ|ÃãE5_½M{PóMÛ æ›vñBÍW‚î… ý›²×&æob¾ú®õª˜¯nÑèYÌ7‚”(æ«[4JÎ@a óm1ó¨ ŠùêfÀ™åî#èb¾ÐE1_­3l[);eYŠYgþ© Sø¸{bsÞ®I²¹«Ì}Àæ%¯0g X"Oj›À¦hËÙÎ<²éópgS5Ó²Ôöj w6[Çý8›"2f-ŸlÊÇÞ++mÇ×tg³É^·,t¯óäžÑìâüŸÍ^/s8šîCt4û hJ´BÍhÊÔͶ$Í~CЈhŽ ò:Žf—ͪ3£)K0#‘lŽŠµƒ³é>9gsˆºóÙ2Í^™Mñ®Ý3³é>9gÓ“ÎfE6ÇâfA²)AÛE6Å߆|`Ó:§|JÀ0Àé^:‡ÓãZNwá8œþÂᔨ_Î]K²9ekYÏlz¸³)¾\ Ø ¹²é1KΦ ý@BŠ©16Ç*ÂL+¡òdÔåML%z>SÑ)E‰a*ò­+'¤ˆ€ÇT¢+æ1„J\Ï¡ˆ¿›Gµ%ªsÚ'Ò:§}÷§-§ŠI%äTb]ì\Ω[vP…÷c õpšUÌ:@¥O>Š$ˆ*Ýÿªdµª„„ÌçÕÁ ¨îÙwPýÛ£ƒÚÛmÞ5,Ô.ÁBwÕ¡Ô¸Õo‚ ¦€ê_5Ô>!Ýí zì–ƒê‘Bª„€Ùž]‚Ú»ç 0N=öÉ9•““\ãTN>N»vç¼»¤˜×ÑA•ÄæåD¥ä>Q)éwÕEWT J2±3_#Ihë» ;Q2ö\y2;rMûx9bÂâ\7:a‚¸ç#Øþ ç3,|×9¼J?©- —°É1ôtŽa™X|8†âkT©c(;ÌmnF ©úêÆyR¨Y’j¦P{¦°.OU %-™Ù!…’ ú¾3…6§:RØÄÕ82…2s0àп:…î±s E% PBöZNÚ´íL¤É …âM²«!…*›3©åP(9°ÏáRäÂ[N ¾,§°N;…âÐÅ€ ݲS(vfÏÖ9¼Û¿ù”C÷¾sÚ&}[˜•ÃT ¥­?Ç\Vò^aN Ëž´_9›Ú’|U2†r=#'¦Øo±×Ža½±¢q å¨bÔ?$¦HË`UÜ‹e7k~½£‰¯Žùþôɾ—$?Ê’3€%Ù§‡TÙK²-+˶PòÛËç!EÅ7|zŸKQ‘n §ÞÇפ Ž:´Î:ZÊ.=³uh)ס¥pÕÑRv虥¨CK¹›O8ê`épçY£‹:°tÔ¡¥pÓÑRv晥¨CK¹-¹›Ž†’+Ïìx šù~GÓSüîyßîO¾~è>ö__7ðw}ÊËþÎÎ%¨òÏxð¾7GŔޤ'iàùTJ[@xO\‡ ÊÀžMeà%ñ{6h@8Ö©TÖPwVN«7(G@•ÃëEe`]¾M*dÙÖ•=—¬ ¬[ElÆeàä1‚2pZ¾A8iÌAX£¯,G”“e(ï³/Êä™2p¸© œîB¥cM eà´…2pR¡ƒ2p8êLxÉ$tB)xØ¥p"¥ÕáfÎ4hëÕôÐU8pÔŽ­AÔÖ},%7®åÁX®âÀáü£:pxF©{_(œ|t*akNŠ^ÐNb,ÐV•’F‰¥Û|xP}Q‰àdÁ¡ù…à$%¦ Á±›"Á±e"Á!ÖG‘àa¿[†­~?™¥bJ\Ô“•ºç½5®‰£ôÀYI~˜{fµ³ÎªøKôÐAx”¤³d%Ï@Ï©*V“¶Ý3­6æ‡1Eýpì/pgcÙF%lld¡î%w‡›Žâ_¸²Pwx.ÇX|G‰–»KƱ‹ú]ê^ò”FÐèvŽã€œ,Ô­ž8ŠyŽCžÍ eÏÎ:pϱ2Ž÷æ8JI |v=0ÎiŸ .4Žq“,¥ÑCçœF©ho€4zô“Ó(uzäªP—ÜsUìc´x§‘GN£Ô1‘#ÐȘªÀQ‚×cúÀ#w‚Gÿáaö$6ƒ±×¤ ‰ž$;Ë cV»ÓX(©ÏžL]CÚo‡®ÝU è$Š.C×ðe6 “Ñ< “¿û€NâpF‚ޱ/ÒW´fñ‰!õÎ’HC1$¤RúP+Ž‹Z¯Žûþôq†(i® Í2žãÏ©äÂ÷‡HL‘®ÖKÂËÂV”„­ß6}E… .ð4}EÜs(ÄËûúòUY…\ËmiGN_Á’Ö×r[©muI÷õäÜ,ɶ¢måZnKP9}K[^Ëm¥ZnKT5u^ç¶PrØòZn+ÕòÆ}MMV¶X’mE-Úʵ¾7……äq£ý×JË£^¥‹õã>‘.ö3}Í׽ƫžå뫦ÿ¡·yÝô?Úút" ™+èó×ÏÐ#'²¨­ý×Md±â^oËÖÖuãJþþG³Xìá¦kZ>êw A²8è÷û¶|s”îϰQªÀ»ã®üägªÀ»Š9e ÜŸUbªÀã’h~û¤Œ„&°V±I4w 'Ðò¥he½üq1C4wÁ…/„ÐN†MXOmS`ho»µ‡&ðT¥+kï*Ðh£&ðÐZ5÷[Xv—ÔÖ÷Ò³\þ~•øäKQà!uM]¢Àû(DCPxˆÜ‹éÓCxH¤ÚmI+LxÈ*Ü’h@x\:- Yà!_ÓuÆH]àmfX3¡.ð=-Åõõ»ì.À¦"êk‰é ›.ðOœÉ#Cx\¼·)Waoó©,}ìe×ÌùÝwâ:’Ï@L"™BP²L¾–Ì,Õ=(ã½”òi0Kuk‰­ J‰t8¡ÜøG‹]¡0‰¡œtL”Ú0A7(µ5X(u”¼“CcOfr˜jÔÄVLRÏc¾''R¾€—ƒÈØÂ@²#c¹æ{"e”eºÕÌ8‘üNáH.ºÂˆä^?˜WΑÜ'˜I¦{H܇}p$&üp$Ȇ’âñ^’»¤d™n=ê’7>â’ëf¾ "ù {ž#¹[p#‘ _‚HY§öI‰Æ83ó>|gI$åÊkÍHÊn+“ß’ž$Ò‘”äé÷‰díŒCøîýêÃâkO‰È¹s‹.Xµ#ó!Sr5#ìc¦”ÌÜìpÌ”¼³HZaˆvÉMk]Õ’ží¢;`]ížâ„ª]s.‚P½+ët@hº>Ú#¤Ú5Yd4õ ›a¡úâlÙB»gà zÌ“uôõzWÖÑ»TϽrê§\b€ê£9RÌè[²ª–g3õìÈZa„ê%÷–ÔÖ‹E<ëdÇßûZq\ÔzuÜ÷g³ˆ3DI8ùXî…( '³R$[^’l¡,Ùò’ßÚaÈlßt~&›EÜS*dÌ«WeIr-·å®@·•\nËk¹­T‹¶ÂH[ÙH[Q‹¶r-·å®@·•\nËk¹­TËm¹+Ðm%W ÛòZn+ÕòÆí®@ÚÊ®@‡ÂkÑÖ8 ™Ñâwê0üL_óõC¯ñªgùú²é¿ïm^7ý¶~(¯E•Ì"­àîºÿøî:*›JmVî‹C5‚»*X² («»`d•îÝsBÊ• Áý¹‘c Áê@º¬Ä‚ÃûF…`õU™’¯)‡ Á²H‡Ð¾)ëºØ´ø¡¼‚È?‚Õ=£Ë% ‰©YDH@½~9¤F°ú3L2Áz5-Ë«©g¥î!Š -Ëï³SU2ÁᯠL°zªiw›L°Úy²L°žË L%xÈ/ÓÄ7•àðÀP%X«Ô$Ô.*Áñp(®* ëã²ì _*…‚÷Q²¡Ppô3 VWÚ!¤¯R(8Ý„‚õÕÜY(xøþp ‡ŽBÁ㺫½*«ßEuM(8œD g„‚ÕgÐ,ß…)RAH©à]BqoH䦩à]Á¡ŸLoÑE çÊòù]ôjLåždú¾[’©-¿·Df8¨H¦¾]CÊɤŒ“Y®9ff)ØûA0KAÔ›ƒ)Žõ&L)˜O³Täkq2KÁ‹t2ÅÁYïƒL¾'ÓŸoù¬3댾ÒyéJDAæƒåyù ˆÑÉt?’“)sù‘5ôÕrÖïÞÓ:)'óÁJÛÉ,…Ú÷ Sn\ß‚“)Mmf0Åì:¸|˜±ƒ\ÆÅ‘Ky–ò.­÷!–ò^LìœXFbY*2(8–Eî>§Ñ7>,eS™®)KyV;àXÊ.u ’Ki[³g.¥ŠŽ/äÒ}nÁ%ÂdKÞT`9 (°”ÏóËw¹îÑòhÒ„hÝK¸’åõ»ÄâÝ%žkƒÏÖ1Æà)Ss[ÿÑ.áê¼#¢Ûô¹È¨–Ô4x¦SÑ.¡:–ÉÆU»ÐÛ7F“]0ºK uFFµÝœj—ô33T¯ÂÌ"û»„ùPÀè¾s¸öÉè®S˜”Æí²JʈªãˆêZÞ ª÷i9ž€èþ/‚ɨ^rBt_Ì»,ñü€¨”,±ŸîŒvÑÈcgפ–Õ[Z™ÑtO€Tß“sCéõZÞ'@ª'·Ô€TO^£zSÖ ‚Q=¹åâ£éMQ} 33ªïÉ¢”ÑTFõáhG F÷¹áö%£þ.Éh³k&FµùÙ˜ìëª~SÀëCŠ‹&I¬®’lë™gŠ‹ÝøÑãÁ&‘u-“û¨b¯„ jIÎp±Í`@!‚m!i lËÓÎ(€ê$Ôo‰p— SÜz €»·0—€MDÒZÎo¡uZâO«XËê ,9”tgþôŠ{Î̦ÏÓrµ@õYb>kîÕ'r©@=WËcd:;ÜG¡M´ ŸÃn;HQF auR^9÷ŶƒÙ%„õz a 5´›€„°ÞD͹/ö¹†Í&TBx¹N oö»M´Û$„»l™¦»oÂj䲸y“Þ%Ï!!¼¯å²^…Âaw™¤¾ù#PÂZ¢Ÿì(!ì1JTW붦¢‚ðÐH•,!RJëQ¦Š á}ªFQa“Ö°1»+H²š´·J§{€„ðÐ-ñYBXÝÉj Âû Š«„ð¾l±£„ð.yÞ²Œwø—© ¬³-a¦þ·j.¹ìò¶VÍ`Êþ¨’µ½»ÜϬ¬¿ûÒê\.A¤\v¼Éàòfrçþ¾àò¢œ¼sy1I„s9‘K5¸ôfï`®F±o‚9ñí:À\ø0`ÊÃ{&¦Õf‡‹-À™¨û`®i€¹BмKbÔ .Eèx\i´Ï°L2¥ƒëP>è‚ÊÝ6Mß©¼(È *÷QÈ1Tä** sM8–ÞÈKó–…i6ËÚ ÉíXJ¿,¥òKD:–mÚ[ ,{£v>±ô~ù”´²9õ…~ìÐGpy_ÌSC0oäŠ 0oȦ˜O5ïçd¿èÒã•'C*²ïã=E»· ©îJËü]¾ŒÞ¥úö²¿–èc"¥2©(Çè©Ëä–)ŸµoRêÞ§T¶Äy£Ô¡§ËF§ÔuNi£X½S*%6š“Rq\ üá‚tJõfrŠš.ûûïœ#EJu{ò1|ÆQ>åN{ ŸîwsLÅCÕ2¨â7²¶IPý58¨â´± ªo®Ïªú Nå&GæTýe–Øœ†•œÆ S­3s u¡YçNÕÅg£8ÕË1é|pŽ7rª/X8‡LµÀòÓÞ:Bs‰i×MY_ïÓzC`/œ˜v‰?ZyüŒFë*É0 ¶µ±MwÉeÎ ¸Kº}`"€Û"©} »(¦ó"FÚ ]½XQ³Nv½¯ÇE­WÇ} Œ8C”„Ãe±Ö’p¸1•E¾Z–¤­¿(K[½ä·vÞ1Æ··ë~;FÜó0doÈË7¥™r-·å^9·•¼rnËk¹­T‹¶Â+G[Ù+G[Q‹¶r-·å^9·•¼rnËk¹­TËm¹WÎm%¯œÛòZn+Õò¶í^9ÚÊ^9gÂkÑÖøî˜ãwê¼ûLWóõC§ñªcùú²é¿ïl~¥é°õCÉ0>ÄÞý–™0šDÖÝY<¸k`¶vªPîOîKâœLÖÛăû-»xL~_Ń;2ý…zp—n(‹xëÚYw÷A¾&MÃpÔ¡¥ðÏÑRö♥¨CK¹,%ï,><µ”êÀÒQ‡–Â7GKÙƒg–¢-å:´ž9ZÊþ;³uh)×a“¿,Þ;!êÀÒøî˜ùâwê»ûvÏòõC?ñ±'ùúº©¿ë]^6õwv~,ÿ…ì·ú¦Óî{“_4Sî2ER QîO¿\mØöÖ<‚%ŽÐJŠ wyîÐÉ_º´Sžâ»Æ@¢¨ ï’†µ ä…s‰( ‡Ï—Ãáû Æ°ú>®¬1ÜyÜPäZŠà¤Æ°>;Ä$†5lÑ Öó÷Y7þ<ϱ3ï[É/t'F-‰Æ.—mz)~‚œŒFwì! €”]KTÿ¥ð(Ùëƒ 2rHóÉZß]âÇ@Ê÷âJ)-½žé©MÈB7²ºl”¸"²*Ya¿ËÂ%‹}÷%®¦Œ£Ì,©þm8Ê>,õÝ5‹ÐJ4V.$ÆV™2†4vªn:£P?ÞhìÌ´à4ŽA‚IãÎhܽë©o|„ì8i¼†‹w’Fì˜ uVÀX)ç0fUv+߈ÓX)D™›Ùi§!Œs°#ŒTU Œ£²_soJ69Œ3w _‚8€·ƒ8˜þ$jð"ÂÄ $2îóò^4I˹rJš6$df$*ÛX‹úVFe“$M‡.J&ÛªvŒJ]dCIÒ¨ÔÍu+“í–äî™JÑ”MBjïœ!ª=¿3ʦͤ$(›ôê÷ l’±˜”MÀ6 Ê&Ð8&Ú8ѾE®`©:•+c©Ÿ¾.%h9 ’×îûË1HÊ* ,%œC"°ùQ¨h*–× ý R¾·Ü9#M0*¥¸(•—«Ú’J‰ÚÄ *%bèÉPÊ.|ŒfJ¥ìÓ?©,»”¨É䕲Ãþþ.ÛÊï ¥nNÏ i´ä!ey &KõÜ\`²XdNb2 eéœ[—’ÀûàR$õ쫹=°.ËŒ\Âea Ñ™/4"î¹3w’ùêÉ£á&(ç /šC§‘Iy(lò!éÉy 4†êÎsSõ™ÌIÓ§¦êêy$Ü%ºuèÄñÑèd"zç©©:PêÈЩk*3'oq`Nœ7y ÷ˆKÇ€8-y^ª%)ÙL>ÆóÍÀ$.¹{@œo 6àÔµƒfnÄ©«dâtí•ÇÁØ lÄ¥NÄévNŒ5Fœnó­9çEl‘5äô7: C.¶¨¹Ð@$rzu+òÍ$yC0§Vzž–êõßy$Œ­ÂF]¾6£.ÙuGÉÀµ<9ßLl¨%uºÁ×& .¶ü’ºt-¶6•MË÷;÷ã§Æ²>Iž%‘Â¢Ž†ð§µâ¸¨õê¸ïO}gð™°vø;PÆsü9•˜R`Nj‘®–%ÉËÂV”„­ß8õ…ôûåüU©/⶘~!^Þ×—¯ÊÒ/äZ´%_Rw7˜l±$ÛŠZ´•kÑVÑà휮‚%ÙVÔ¢­\Ëm‰O ä{dÉaËk¹­TˤġdS(È–¼ ¥:nG’ÖÏŠ%‡%¯å¦R­ïM{!« yg¿›4´Ÿéa¾~è+^õ'__5ø}ÌëÿÑÖ·^©2Kº¿ˆ~«“úç_dA\6œ_,óÅ}ÿü?üò‡=øö¢+þ“%Á߬øŸ‘¬»¦=a$Û)¿¼uÑ黇ÉÉ6öAH¶Q “mìóü­ÿ-’mÌæÉ6ú_ŸlC2²—†+ù4ÙF¹§~ûåâ*WV.®’ؽ!˜[•‹k›pP¹x“‘s*WÉxURÂ}—žP.®{¾ˆÉ3”‹«ìó€þ¿)Wß Båâ*PÌêxÌL¹¸úf(Wýpc2`àOìö rqÕ ›,›r±ÎŸÌ­ åât”‹«¤ß2g”‹«L•GV.ŽGCåâ*;g,‹(”‹µ#²i”‹·e&÷„rq²åâÚËÄÄÊÅU²™(ïy#âzL¹8Ù…rñ¶KeS.ÞÓDÛñHáâ*J9Y·Ø ([\Ý¿EÝb}· ÷›nq•å&Ä áâ]RNíð}Ôd(\¬víð¸G*§£ \¼ïiXÜ•‹÷Û„/“ÊÅUr¡µœpCŸÄcZÆú9¸Š¨Œ …›r±ÞƒÙ5åâÝ$°Ö¦rñ.¡º¸;sò;ǧòmÔbQ Jɉ£ŸÉJi¯õ”h¥|G>òmÔ.{zZ‚Râ¢(»(§=Ê^™–•PîE,³òJI ß< N•üo#gÁѶzg(»t™t+”}ßö å^Ô·áPò”HÀA"¸1¤Ø0—ìå†3–@Æ=;"82ÒJæQn å8»¤ÁÉCS yôËâÞ²…,Ãæÿò`,>(ˆ¶0t"i%!‰9’þŽ’wæÑÛ‹óØ+öÌ;Rb:ýäуóè­Ìyô;p£„<úót»HHöÌ#Ûƒém“@FOD ãj¤´•ö’}>bJÌÎý$8KckÂY4'W†³H×re8K·˜WY$b¹ƒÌ]pyP‰’¹m< ®42‹t|ˆÑ42‹$åµõ?È,Ò›Ã5*瑞ŸŠŒÌÒô°@f‘Ç>³Ð‘—ެ‘Yº§Í™E¾BÖLf2 8‹0tý«Éê€Î"]ÇÊÃ¥žËRž‚΢I„œEšÿLp¦cg‘¶3›¥WdÊšZÐÓXY4óeOhÊKwJfª2‹t%#‘O“dê“Ê`úíK7B2õ1é$‡djuŠ’Ì"y9{Öø×:w΃ã×O0ã≠%‚©—7s’"¨Ž`Ù i#'À,B].ã7°ÔË]OÂRÛK±’)6J1-ã„äô¹ó˜XDbøÎ9¨$LêÈ Wd·Î ¼‹©ãÀî–È 6ÊÅpnçNv¬ÖŒæÝ;Õgvêd«òÇÃ"žñš©Íb:¬:¹ž™‹+#s~ÃÎÜ5òüT+ŒÌÛåŸ^É[*or%ÇôT/¿äÑ0] ‰S±é œnëÍy5üm8qòafâ4;ÖÈÄ]üêââRH\<["ÇgïÄÙSqÞüN®,…q!ßóÆ+sÜÂ,qócˆŸ€ÓvaÏ”ÃæVÉÚÅïmdÍ!jþHÈ[޳wCÖ.¦k{‘M#ÖëÔî ëd_âûZq\ÔzuÜ÷gÓˆ3xIò²,|Q~CfÅH¶X’m¡,Ùò’ßÚéÙ4¾åƒüL6¸-ftÈîW¯Ê2:äZ´ÞEÚÊÞEÚŠZ´•kÑVxi+{i+jÑV®å¶Ü»è¶’wÑmy-·•jyƒ¤‘¦’Ñ›1ëÐPªãvܻ膒wÑ-y-7õ>HfÒøÝù ?ÓÃ|ýÐW¼êO¾¾lðïû˜× þ£­Ïú Õ¹³­üE¤ä×ýàZ”ÂòD¼ß¨xø ÌMÈ${HnÂMòQä[–)¯¢¾a;$’køÀN‰äêâ4”H®’m~f‰äÚ öÊR#Y>cBðÉáá£H²:ŽšeÐoÕUXîœã£Šô‘Næ¡’lŸC³Lù.©ýC•äpQ%9è¤Jrm&·2É5tÁ!“¬^¡™eÊ«|S7Ù_È$W‰ú×õe’÷Ó€4e’ã&(“¬®Lõ7Q&Yíô¬S.3Ê$«SRà “\EÛ’q@&9ü‚IÞvññœ2É» ¾$S&9™d­cY “Î9Ê$ëÜÇ’¢@&¹ÊÊöP*×7lY “ì>Gª$«£Í’Ž@%9ü‰TIU’ÃÇG•ä}T³¥"U’ãC%9Þ'U’Õ§W’Ry¼Nª$WŠ) ›Jr4Aª$‡k0ˆ…øŸÌò±ç§ê8Hlº~—³)­ÏÚ¾³É­ÁæÄ6 `“$Ø| /l>H—ØìÖÖ‚M|6% ÍÉæ}¦Ø%³ 6Ù†ƒÍ…„`SryÞ›Ôù‚Í…˜`“.û`Óyq6yçÁ¦Œß966k³Á&¯ÇÙ¤¿8Ø\ˆÆp63góîÌü6oä’t6enoœM6ë`“Nñ`“ÞÔ`¾ÿ@ó±àF'Ó=™ÖK9šs’“¤’@ó†Xº£ù ߣ)/îœD ÞŒ£ÉƒM~Kq4ù~M‰:9ȼ¦õ ™lÆN¦;‰ ÑG½Ø,–YÊ9€–q3IÖ®ƒ0oBZDòÓDûi‰píþ iA0KàHwøD iAl—CºOusŒ5H‹ìô³©Z±€´HŒ¥ 瀴H4r¯ Ò"ŸÚÕñIHõT% E–©R R=2i¤»V]„4Ù¤úLïœg H¼´^3!U;Gž=?µ`32ªAhµ'FË4—†3ªç¶3Ñt5Æè.À\‚Œj‰%£ûÔ÷‘Œ§È±3ºkL¤Ú¡»ÁåDt—XX6Ý蔉¨” -’Ò½ÏDh‘ý +§(¢8{eB÷‚Î$T»*в94; tTìË -²=E0-ò¯;ªçÑ¢¥‰ ï-} 6õß¾PnÓúçC6 ÙöbgPýAƒ¢r256Ob‹ÈŠ€J0èÎgŽGðâ&G>D¨ª19ÓNøuH ;ÝœÀ ÁÛ ;"ÀËRl‘>‘/¾r&¬b‹ >)¾K>NäRÍØDøü>)±Yá»ìš|a‡ôyP±Óç^BÒçY§Ïßé£ Ìá‹S¾¸)Ò§EOðñ×ø?¾<&™8BÆ^¼*K2‘kÑVx iëˆX„­ý[¹m…·¶ŽˆEØJѰ•k¹-÷º­±H[ýH[©–7Hú i*Ç,²{ì# ¥:nǽ…n(y ÝRD?ÒÔÄ5ZrßKñ3Ì×]Å«îäëËöþ¾‹yÝÞ?Úú¬KqŠê¥Cq•ÿ–ŠÌ:òÚ¡ø}YG8 Åæ¢ûÒTŠÍ*á0²pz­"–k¢è&Ú¬‘‰Ó¤ÔM´Y?ÎÝY´¹Ö‰ ’Ðm®U”®L¥Ùt›k+ØæLÝæªŠ<:Æ@·¹îùfBΦ„» ôˆ6o«¶í‡šÍÕ…Š¨Ù¬%#k¦W‘ùéVbšÍûj§Mm(Ú\E±Ø.¢ÍµQ‰‚¢ÍûÒ<@´y—¦hsÉhQ´Y¿›¤5D›«4ËžUÓ+S0R³9‚`©Ù\EØÉ$å¡Ù¡³1.ôÛÖ›ŸL:bû±VÆRĵõeK$)5aYd«|ÍZêõšLÁF,u_`ËXJªZ}™ÄR„1êÊX ®Íù j¹±Nt,‹x [æ²LJ‘Ͳ&“ÿMïIœÍ [­Í"; ëÁfe†gSÞÏÁfѸ™Ù¬mA©lÖuAÞÙ¼-hb“‚ïd3z$cSü}í=›#ç3¨.4ælêªë9Ù„ö\°é,8› ¸v6ý³)%5ë©WY¯[æg³v&+ ›ÞôM& 6G;Õ«äiÐep°É,«Á¦'O ›tØ›ÍRyÿ%4÷2°½'3§3¨žë`& Ld$0ñ1è’Ž”*Qu™Qw¸8£c"7©3:|Š#£á"£ê#²\`4œ‚`Tºsf }ܯdt×H F‹0VsΑ2/S§ ¢»Êb‚CTOUrÊ‘]‚×CDwÅ,)@4¼ªDTc6ÚQõªŽœrd—4ô`@4¼„DT‚†:MGQ­ót2NL2ªÎЖ“O;AFÕïj#Ý%Øš@FÃCIFãòȨ:g[f´ˆ¾ËÊÉÒõ€Ñ]dÉh.1FÕŽõ`Tí¬<~¦û£ár&£û($Ë£E¼g–øŒ¦‡Hw $Ðiø»I©z¡-Ã0Ý%اAN5ͺ0pªïC*{)×^dÉ•Õ2ˆ’(ª–œuD$T»5G€¸ÛÅ~É5ƒ(‰Ô,áAB ŸQvß D t³Ømñ*LõCE{åÁRìÎÁ2EEtÚ¦Ô$Q ï•I”’²‰šGkæÁ²H¾(ÎI¢èzÙpN/êb8‰²·æÁ2‹$Šß²´LbÜI”{™¬žè-õÆŸƒDÉ)Wrö‘" â'‰•xœÄ(!‰u†I¢(à–ë Q“{µLbØ!‰º)ù QDÏ-3I ;$1î‚$ÊQå 1Ž"‰r”1ãä$ÑŸ¨“èíËI 3$1.‡$ÆÉA¢¨‡Ì'§‰Vé$JÛYøzŸ~$mL†Àa¬üY'»ß׊ã¢Ö«ã¾?ýHœÁK’;eᓈ’p2H¾Z”äí×(KÛ¯½ä·v-zú‘on™þvú‘¸+¦ÀÈ^›—oJS`äZ´>CÚÊ>CÚŠZ´•kÑVø i+û i+jÑV®å¶Ügè¶’ÏÐmy-·•jy{¤×¦’×Ð[1ëÐPªãvÜg膒ÏÐ-y-7õžE¦ùݹ?ÓÁ|ýÐU¼êN¾¾lðﻘ_iðl}Öµ(’i]‚½?é\œÏüè\œÏ·*þÎEdE9}‹¿eV•£éwÒ–.2gÑM[–®"Ãó˜n´JKW٪ѳ¼{­’k,eE©u@JÒÒÕuÄ)-­Ž£Ërž˜´t RZºzþ=JK§£ -]= #¥¥uÑ}d`¨žŒÒÒU“0šüݲtëQZZ—áȃ2°[–™)-JKGè&¤¥Õ°i_CZZækmÒÒ¾\¦²´®÷Õ„¥u¹¯K Kkl§íŒƒ°t„&RXºJä¯e¹€°tÚ¢aé2£°´:ðth¤²t•Fu(Kk\_Éïa™ÊÒq=T–ŽØD*K«ÿáÎÊÒçEeé}=‹ ê¦,­apGõ1Rþ¶Núx×p;ÛQaisµÝ{P–öCLV:Â)+®MÊJk0oÍiQâ™ÇpÁ'óÉ´(E&óÉTÊçž±,’N›4°,÷ż À²¨dfP¹Ñff"@)_qÆÊPj^ç̤ĂŒœrA÷­œr¡ŠúWÍrïÕÜI]*äœ U¤ºL*LŠCÒvj“Ér#M·3Y vO9“µ"ÔÆ™¬å²Šÿª% +…­HÙkf"ò²Ž -zéLGRö7µ¬õ^å²ËÈHÖ;'*ŠΣ8¬kçQwæÑÚΣ|£¸úÁ£å<Ò…<Òå<òóBð(ûÑ×Á#üÁ#½÷Á#?qyŒ"Y= ‘ܽrŸ’Á©l•G‘ÊýBîœs!¾\%*Æ›¨DÏóiQDK¢<¡²oÓRœÐ±Ê9Š$d­%*ÓLBˆŽ Ÿ2-Cöæ3" i™G¤3HÃHHw&þ¤E´KNŒ²ëpè¤EDͬÁÒ"á^–h–1ß%F)£3= Í%é~•Ê(Æ©Z.OpªÊxêÙ$§»ä2‡68U»5aZ¤Üz'`ºOt#10Õ—†©Þæó$R÷M¡§'©é(Z¤iY²2º/Hj‘+rr½‡‘@ÕƒîÄé.€¦/0-šuça3c”ªo›–?š;šq¤4™1H‹ŠíöiÜ!Íf Ò]âIX R} W:·ŒÈè.€ $-2•G ¬ý¼­½H‹ÂЫ„ Ç—9‚“H¥ FM è;Ÿ‰ „ûÕ'#(‘c#§E)š®ý@Ðr?èº'P‚(mzK=ÚÑ ô@6'ÐÙœÀ«A?À ô=·N _ô§åzœôÀJÐÂßHŸG):~ò`jΈ!~Ž_”?9ñÊ™‰Ò¥¿xÄÏã÷?tü4?Vž¸F|žóçÏÓÌ%F ö__7ðw}ÊËþÎΧÅ%,\âÿ›w%2YË·}‰ß›¬E¤§ß²öžÙ1“ô°‹$„ƒÌ»IbI b¢MÄ.Ï´©<±«|r½¡š­ŠØUóÝZSÄ®—̬ŽIb×R‘’صt*'A»ŠŽxG‰Jb×2õAõ°«lÞ8RµhØD½M»J¦Ú™3ChHJ™ v­9h"]™+“ŠØ™™±Ã]AAl §‚&ŽbWù Þ‘–E#FvÉ`–SÄ®u<ž,bÙµˆ7¢óEC²8݆$¶zlð†$v•- ”œo¶iP¶†}l‹ÄM>Jb‡ï—’ØU¾Á=¡B_%§$$¾M[£Q¡v}áR¸¢€"vDBš"öþÝ]ÿZ±%3)(bWf¼¤ ¶>{A¢‡]#-%ô°k¤o„v\ä°áä1-l5˜èÃ)D)ì¹&!…´;1ÐSóÉ-E˜Öç€ÐWr„P¶ê@Š$‘%Ó „w§8(,’áHÑRöd3MPX4MÍA¡|˜ž9D•ur/ÂHE@ /i('ˆžzÀA”¥G¦¯Òÿ<Ï¢äûÈÊôUojÎQe}…ü ±H‹˜Å"Q¼õ@±0»P”ωQÛíhÄÀ×@Zïq2c¸ƒ(1 3ƒèñÛQü“kfëÊÂôU6(=9AKæÒ(L¿IáíˆC6‡ÀÐû`8=0|§i‘–Üc Sn¶ãˆ$´œÍ,dù¦ìñ[wSª€ÙùÄå^-5ܸT/åÊ #vÉdr'ã²èb±&.Ë(L.÷QÌ&.wŠ9àRµÕÐs—Tfž—û¨Á\ÆåQG¹T;wI\ÑüÁåþýÀk0µ$êì‰KµjëwåRTW wûÌd&^­era)”º½}ä-jÉ-ŒK{#q¹­,‡Rý¿5CN;0ŽS2©¹C£™™IwœÉ|†ä>hæfé#2Ý-ˆ ¯)‰ ÷µ©Îâ»%"Õ÷ ÚŒÈ8€Tßad¼™ùYŠˆÛÕš»ž‹C€+ïž¼ §{2o’a<¸ÒyéN?@À© ù‰‹œ5$®ˆP] K±ÂDœäµ¹rŠ–\ÄQ(\™¸².æµ ®ˆÐaÉÄA02W†6 n/Í,߉“s­œ¥E(qé';åÈ¥cÀœÄΘ”Íëx0'mYŽÀ\:°KV;Éçóä±Pk %°“:Ì`vãZ(©nä¥kyê¥=¹Gô;@/IÑKOè¥`Of0ý`O2]1/ÝOÁ;À'ǔ̞\î^\¿¡gë´Džx)”eÉ(ÈóLH Oö•#ïóN‰Ýp%çÇžã««@Vžÿê—²~þ›_æÏÿ³¬@þúË>‘,7Å}½[çÿæ§?þw÷óßê_þŸØL÷Oû?î”?øaµäÃþµüÝúeú~¨¹d­õþ7Ý÷¿šÉÃ7aƒy —éÒÌ[ÞŠ%î½´£cÉ'>í›…)¢?#[@Éw~†4kⸯ‡5”¼ûbbµkyLèÁk£DjÿÛŸþ?/€Wendstream endobj 6 0 obj 26985 endobj 4 0 obj <> /Contents 5 0 R >> endobj 3 0 obj << /Type /Pages /Kids [ 4 0 R ] /Count 1 >> endobj 1 0 obj <> endobj 8 0 obj <> endobj 7 0 obj <> endobj 9 0 obj <>stream 2020-10-09T14:37:14-05:00 2020-10-09T14:37:14-05:00 GL2PS 1.3.9, (C) 1999-2015 C. Geuzaine gl2ps_renderer figureOctave endstream endobj 2 0 obj <>endobj xref 0 10 0000000000 65535 f 0000027536 00000 n 0000029049 00000 n 0000027477 00000 n 0000027343 00000 n 0000000267 00000 n 0000027322 00000 n 0000027629 00000 n 0000027600 00000 n 0000027693 00000 n trailer << /Size 10 /Root 1 0 R /Info 2 0 R /ID [<6AADBA73AEEB37916689F6B398226B91><6AADBA73AEEB37916689F6B398226B91>] >> startxref 29269 %%EOF blis-0.9.0/docs/graphs/large/l3_perf_zen2_nt1.png000066400000000000000000007104331422157504600215550ustar00rootroot00000000000000‰PNG  IHDR¬øSzgAMA± üa cHRMz&€„ú€èu0ê`:˜pœºQ<bKGDÿÿÿ ½§“ pHYsNNÆÊ/¥tIMEä &VeÃh=zTXtRaw profile type xmpH‰ÍVI’Û0 ¼ãy €ôY$o©Ê1ÏO”mylÏdªrˆTÚHÝX)úýóýÀ‘yI$» [,iVÑ‹V+œ”µªéª][—Ëe°a|Õâ#Õ¤–&©4KE »èJe±Í°°Šm¥×¢xB¡±Éž6PÑáÜlÑl‰›*TïVÏd$@`ic.R¹ìE™¯*l‘ ­Íùjæäߺk7ñ9稙®8²Í‰›xsWƒ±K˜µ”Vû÷À¹ƒýêî aî²âÊÜ$‹ð† cs¨4x¿pÂ|…±“'ƒ€ÊþüH'’sÒ‰.Vp&ÙÀkXÜ BÜC±ñèê'ÞÈ 0£M%xŠ!Vnš-p&0m^ѵ.ÏpÂý“Ž4ÚxøG†IÉ=öhT)3Dø^݃„íÀ< ’A÷(âxŒQzm¾vzÇg.9ÉÃt¸Øa‡«F¹bÂW*ˆT˜PN„-h…ÝÁŸGpì÷Œ‹¬ú–³Bxp·gz(ÚJsã@Bm·ìŒ*سâž”~‡Iµà½È&"†;Þc5€{’= nJé¬u*vˆ¸ꜹK¼‚¥oà¾Tz…¥"(€z”£tør® AKGx]"ƼáÕGBi43ºZ÷HƒŠˆyìP,À|ÍéÐeè]ÊϤø¼,ΉC•9HƒÒÐ\_”Æ5yè«ìÂvmr7…Îm€YõžåÝ¢ gG;›­}sðC ½®Ä[ bʲàÕƒaF\ãôYHUÉ$ ^° Ù+쫚zWRôÎ3Áç¹[&ȳî÷Nér¸W›¥pÜôÍÑúCÙ†MÇ5ûÜ1ÌÊf© éÖy¢$çRŸÄµG9ÜM̾‡G\ÙՊόԳpºwjø,2Ü…€]RG¤dרýò=œŒÂ晿'œ™­Ï\¦O>rö1gôøgêÕiþh jÐsÈËVïè5‡»Š+‡g¸cJïêë¤4vÓÛèÓ¿€Ï`ËFKø'ç?R”¶ÿÍÿ±§Ÿ¿HºHQ›ÿmôˆXo ±†caNvͱ¸ª€IDATxÚìgxTE€ß­É¦÷ÞH!%¡÷" ¨ˆb廊€ ˆ4ùPQQPTDDéU@- ½¥÷^w³íû1ÉB¤·„rßçÙ'É-sçNæÞ=gN“™Íf3wòÚ„„„„„„„„„„„„Ä¥V ‰;Ia•¸‹1 Œ?žcÇŽÕvW$$$$$$n9’Â*!!!!!qc2™X¾|9iiiµÝ ‰[޲¶; !!q`6›)++#77£Ñˆ³³3NNN–ýUûôz=NNN¸¸¸`2™(//G¥R¡V«-í”––¢V«‘Ëåèt:T*YYYTTTàéé‰ ”––âêꊓ“F£ÑrlFFƒooo¬¬¬ÈÈÈ ¬¬ 777‘Édµ=\÷Uó577“É„««+–}UóÞ`0àââ‚““&“‰²²2¬¬¬P©TÕ¶Éd2t:VVV¤¥¥aggwÑ5µZ-&“ [[ÛÚ ‰›BRXïôz=û÷ïçØ±cøøø‹‹‹eÿÙ³gÙ³gnnn´jÕŠüü|<==±¶¶Æl6“ÀîÝ»Q(tèÐoooJJJÈÏÏÇÖÖ–õë×#—Ëéܹ3¶¶¶lß¾ŒŒ Ú¶mKhh(%%%¢V«Ù´ijµšN:¡V«Ù±cYYYtèÐàààÚ.‰»ììlÞ{ï=bbb¨¨¨ iÓ¦L˜0zõêQRRÂèÑ£Ù³g¥¥¥4hЀ‰'R§NæÌ™Cxx8 ¢¢‚7ß|“_|[[[¾ûî;|}}Y²d EEEôïߟÆóÕW_‘••EDD³fÍ¢¨¨ˆE‹áááÁ’%KÐjµ 4ˆÀÀ@,X@vv6‘‘‘|öÙgøøøÔöpIÜ#$%%ñᇲÿ~ŒF#­Zµbܸq‘››Ëرc‰‰‰A«ÕZž >ýôSÚ·oO=(,,äwÞáÝwßE§Óñ믿Æœ9s˜0aBµk¦¥¥ññÇÓ³gOúõëWÛC !!!!!qSH ë@YYãÇgË–-xyy‘™™‰¿ÿþ;ööölÙ²…‘#GâêêŠÉdÂÞÞžôôtæÍ›G£FX½z5ï¿ÿ>þþþèõz¦L™Â´iÓèÑ£[¶la„ b4IJJâË/¿ÄÃÃ’’ 7nëׯ'..ŽO>ùÌf3çÎÃËË ÊËËÉÍÍeܸqìÞ½??¿Ú6‰»ŒÙ³gsúôi.\ˆR©dôèÑÌ›7©S§2oÞ<öîÝËܹsqrrbâĉ|ñÅ̘1™LÆ÷ßOïÞ½Ñh4üóÏ?ìÞ½›Q£F‘žžÎ¯¿þJŸ>}X±bqqq <˜Ö­[óí·ßR^^ΰaÃX²d QQQ,Z´ˆÁƒó矲gφ BïÞ½Y°`¹¹¹<óÌ3¬X±‚×_½¶‡KâaêÔ©dff²téRôz=o¾ù&ß}÷'NdΜ9œ8q‚ `eeÅØ±cùúë¯ùøã©¨¨`áÂ…tèÐkkk6oÞÌ¡C‡°··'11‘… Ò²eKÞÿ}¢££-×;wîo¾ù&AAA´oß¾¶o_â>$''‡9sæÐ¿¢¢¢j»;·C‡±dÉF]ÍÈ$që‘bXï²³³Y°`“'OfõêÕ|þùç(•Jbcc©¨¨`æÌ™´mÛ–ß~ûÅ‹£P(ÈÊÊÂ`0À'Ÿ|Â3Ï<ÃÊ•+Y±bmÛ¶eÆŒ””” ×ëÉÈÈàá‡fõêÕ|ùå—lÛ¶ððp–/_΂ puue÷îÝTTT––ÆðáÃY½z53fÌ`ãÆ´nÝš+Vðõ×_cggÇž={j{È$îBŽ?ޝ¯/õêÕ#""‚O?ý”Ç{ ¹\Ή'pss£aÆԯ_Ÿ)S¦ðÌ3Ï`eeEûöíINNæøñãüñÇ´hÑ‚ÀÀ@œ>|8<ðÀ 2„ аaCZ´hAQQ >úõë‡Á``èС„‡‡I“&M,ÇJHÜ Ž;F`` !!!DFFòÅ_0`ÀË>êׯOÆ ™9s&?þ8*•ŠnݺϹsç1ïÛ·o§§'666¼üòË<üðø»»BQxíµ×°±±a„ 8;;×öíK܇ñÛo¿‘””TÛ]‘¸­$&&²lÙ2JKKk»+÷<’…õ@¡P Ñhغu+NNNñ×_¡P(HMMeß¾}L™2ìííyâ‰',Â{||}€=zðÓO?Q\\ @`` e¥½N:ôïß¼½½ñ÷÷Ç`0 V«©[·.-[¶¬vì€Ðh4øûûãããƒÁ`¨í!“¸ yá…3f ÑÑÑ´lÙ’Ž;Ò½{w Ççõ×_'**ŠV­ZѶm[zõê…Z­¦]»vh4¶oߎ­­-;vì`úôéX[[ Ñh,.ðUT ê2™ +++Ëv{{{‹pÿßcåryµc%$n¯¼ò “'O&::š-ZеkWºtéˆgbÔ¨QDEE]ôLtëÖ ½^ÏÞ½{1 ÄÇÇ3gÎK,·‡‡aaaÕâ­ß{ï=Ë÷„ôž–¸èt:~úé'Ö®]KVVÍ›7gĈ899±páB²²²X²d ¾¾¾–…nooo>ýôSf̘““ÿý7ÞÞÞ,\¸¼¼<† FÆ ùâ‹/HHH C‡Œ1‚‚‚6mÚ„»»; , ¼¼œ§Ÿ~¾ùæéÒ¥ #Gެ–ABâVššÊ÷ßÏæÍ›Q*•ôíÛ—§žzŠ´´4V¬XA~~>óæÍã…^ÀÖÖ–%K–ÍO?ý„/¾ø" ,`óæÍèõzºvíÊ /¼€››ààÁƒÈd2-Z„ Ï=÷F£‘%K–‘‘Aÿþýyûí·Q*ïo•íþ¾û;fϞͷß~ËÊ•+ñòò¢U«V|ðÁ$''cmmmRªð*!åܹs”——óÌ3ÏXÚÓëõ¨Õj***°²²²÷U\.©ŒF£¹Hh—ÐHÜ,f³™Î;óË/¿Ë®]»˜6m6là›o¾!::š%K–pôèQvîÜÉܹsY·nóæÍÃÍÍ®]»²nÝ:ÜÝÝ),,¤U«V7Üi>KÔf³™|FqèÐ!vïÞÍ„ Ø´ióæÍ£cÇŽ,]º”¸¸8víÚÅŒ3ذaóæÍÃÎÎŽ.]º°víZË»¼Y³f–¶ ÅEÌ Aƒù$?ýôo½õÖ}/äHÜÖ¯_ϬY³xæ™gðôôä›o¾aúôéLœ8‘°°04 ¡¡¡¸»»Ä ¨_¿>ÑÑѸ¹¹qêÔ)>þøcš7oÎСC9|ø0£G&""‚áÇS^^ÎäÉ“ Æßߟ‰'Ò¦MžþyþùçÞzë-š6mʰaÃÈÍÍeúôéDDDðè£ÖöÐHÜcÌž=›;wòúë¯SXXÈôéÓqtt¤GceeEƒ °µµ%77—yóæ±zõjüüühÖ¬ßÿ=K–,áÕW_Åd21{öl¬¬¬xûí·9xð £F⡇â­·ÞbéÒ¥¼üòË´nÝš‡~˜øøxf̘A‡,Ƥûé›ì ´´”zõêñÇ››ËæÍ›™>}:ööö 4½^Ñh´¯Õj1›Í€°‚†„„pàÀËþ²²2Nž<‰¿¿?‡ªíÛ“ ¨¨ˆI“&Ñ¢E † ÂàÁƒÙºu+}úôaÊ”)|ûí·ñÜsÏ1`ÀŽ9BTT999¸¹¹Ñ¿¾ÿþ{ÊÊÊxä‘G°±±©í[’¸*ùùùŒ7Ž^½zñøãóøã³råJžxâ ¦OŸnØ{ì1 ÄÎ;éÑ£Ÿ~ú)vvv 8'Ÿ|’””ŒF£¹âõºwïN³fÍ1b“&M¢[·n4iÒ¤¶‡AâdóæÍx{{óꫯbccCdd$GŽA¥RѺukìí퉎Ž&88˜˜˜L&ãÆ£cÇŽœ:u GGGFŽI»ví4h3fÌ`È!<óÌ3”••ñÏ?ÿ˜˜ˆ¿¿?®®®>}ú0kÖ,†ΰaÃ(,,dÇŽ$&&Öö°H܃¬Y³†¡C‡ZB˜|}}±¶¶ÆÛÛ›¦M›bccCûöíquu%77€¶mÛòþûï£T*ùä“Ohß¾=O=õ*•Šàà`JJJ,íðþûïS§N‚‚‚X²d cÆŒ¡E‹¤¤¤°}ûv’““%…µ¶; !bû^|ñE/^Lhh(}ûöå·ß~###ƒ€€|}}ù믿 A§Ó±iÓ&´Z-pÞm÷ï¿ÿ¦}ûö˜ÍfæÏŸÏŽ;øþûïkûÖ$$oWTTÄìÙ³1™Lh4–,YBÛ¶mqttD¯×óÅ_ V«qttdõêÕDEEYÜ»üýý©W¯ÇŽcܸqµ};ׄYYYÌœ9N‡B¡`Á‚–Lí%%%üïÿÃl6cccÃ/¿üB›6m,Šiݺuñõõ%11‘Î;_óuûõëÇüÁìÙ³™;wîEeo$$n–víÚ±fÍüqºwïN‹-èׯ¶¶¶äää\t|``àEªÂ’.¤*C»\.¯¶0éàà€‡‡Ç%U(Ò"¦Äm£gÏž,^¼˜ÔÔTZ¶lI§N®ZI C‡ï–=zðý÷ßSTTD»víh×®o/OOOK©³*ªÚW«ÕËûIa½¨[·.îîî<ýôÓDFF’––Fjj*&LÀÚÚšQ£F1aÂöïßÁ` °°kkk¬¬¬hذ!Ï?ÿ*•Š|ð¢W ‰E­V3mÚ4æÎËgŸ}†R©¤M›6¼üòËXYYñá‡2{öl¾ùæd2Íš5ãã?¶/4lØ???êÖ­ki788¸Ú\V(¼ð àêêjq=ÎËË“¾ $n9?ü0~~~lذuëÖ1}út‹ÇÌ¥Ðh4…&ÉåòkvY—Ëå(ŠÚ¾m‰û©S§Ò§OþüóO/^Ì„ 1bo¾ùæeϹ0áÝÈ‘#iÙ²%ÿý7Ë—/gÒ¤I<óÌ3–Åw…B\.åÀ½’ÂzàââÂÏ?ÿÌæÍ›9zô(mÚ´¡]»vÔ«W³ÙLTT”%`;44ƒÁÀ7ß|ƒ›› …‚矞ÈÈHvìØ••'N¤~ýúÈårºuëFÓ¦MquuÀÍ͸¸8BBB‘„æ‹/¾ÀÞÞ¹\N»ví,ÂPPqqqøûûàääÄ‚ ¤Ì“7„S¦L¡  +æUñÒÎÎÎLœ8‘‚‚Ìf3öööáÆd2‘žžÎ¡C‡xä‘G,s„àþÊ+¯T»Îĉ-¿+•Jzè!ËßõêÕ³ü.—Ëùøã-«Õj\ÛÃ$qÌÔ©S)((@.—ãàà`Y1÷òòbòäÉ—|&L&‰‰‰œ:uŠ_|±Ú¢LXX˜eQ„ÀóÖ[oU»ndddµÅ ‰[…N§cÙ²eØÛÛóÞ{ïQTTÄÑ£GéÕ«Ï?ÿ¼”øHâž¡  € н{wfΜIqq1_~ù%sçν¢ÂZEqq1?üðQQQ|üñdz|ùrÞ{ï=ÆŽ[Û·wW!)¬wr¹OOO{챋öét:FMïÞ½?~<ÅÅżõÖ[øûûãææ€µµ5:t C‡ïààPÍÕ@¥Raù[¡PXʃվh¬¬¬ª«T*-+ø7‚J¥º¬S©TZæô…ìÚµ‹¯¾úгgÏÒ¿)i’Ä]‡Z­¾È±ŠË=›7oæË/¿$77—>}úHó^âŽA&“ñï¿ÿràÀ<<}+++BCC«y$&&RTTD½zõ.›É½¸¸˜Ó§O£P(¨S§Ž%ÿ€Äµ#)¬w$RZ* ‰;Ia•¸#¹ë“.™ÍfÒÒÒÈÈȸgc:F#r¹üž½?³ÙŒÑh¼æzl׃J¥"$$ä®.*n2™8}ú4%%%µÝ•Û†Á`¸-ÿÿ;³ÙŒÉdº-ummm ®–ÐänÃh4Ñh¬í®Ü6îõ9n2™nK=AgggK½ä»ƒÁ@||¼eœîEîõ9n0P(·\3›ÍÜõ‰uŠŠŠ8sæ ÷j¤áíü¿S¸]ϰL,ô¦bwïú7‹ÑhdÆ 8::Þ³ý‡ÆÍÍ­Zí{‰üü|>L§NnyÛÇG«Õ]Û·yÃòÇUÛ]¹müý÷ßôèÑãž-ž––Frr2-[¶¼¥í ¶mÛÆ!Cîê Ê©©©lذá®~N¯Æ_ýEïÞ½k»·#GŽ R©ªÕ:¾³eËFŒQÛ·xS”––²fÍÚ·o_Û]¹-hµZvïÞMçÎk»+·£ÑÈž={ »dùµ›!++‹£G2lذھ͛âäÉ“Yâî'11WW×jî~×"«dgg“““ƒ££#ÞÞÞ’¬"qGb4IHHÀÏÏ+++Ëv“ÉDnn.YYYØÛÛãëë[mF’““)++“d‰Zç¶)¬f³™ãÇóý÷ß3eÊËAff&“'OæäÉ“XYYѹsg^|ñElmmؽ{7ß|ó ©©©8;;3lØ0z÷î}W—l¸71™Lüý÷ߤ¦¦VË`©ÕjY±bK—.E§ÓÌ+¯¼BãÆ©¨¨à?þ`ñâÅÀóÏ?Ïf“¸Ìf¸”rWµ½ªd€Ù ·¹DFEE , Y³fôéÓDz½°°/¿ü’mÛ¶!—Ë ç½÷ÞÃÕÕ•’’¾ÿþ{þúë/Ìf3õêÕcäÈ‘Rü—ćÙl¦¬¬ŒO?ý”§Ÿ~š&MšXö¥§§óñÇ[d•®]»ò /XîüóÏ?|ûí·¤¥¥áââ“O>IÏž=%YEâŽÂl6“••Å'Ÿ|¤I“ðöö¶ì‹‰‰á«¯¾"99žxâ úöí‹Z­¦¢¢‚Õ«W³xñbJJJ ä…^ E‹µ}K÷)·e©$11‘¿þú‹ &››k©ÉTZZÊÔ©S1›Í,\¸iÓ¦±eË~ùåŒF#999Œ?žÈÈHþøãž}öYf̘ÁáÇk{œ$$ªÏŠ+˜={6EEEÕömß¾/¿ü’±cDzråJ<<<˜8q"%%%:tˆY³fñüóϳzõjÂÃÃùàƒ.jCâ>#/~ý.„iÓÎo?rDl[¸ª²Hjµ°|9¼ÿ>Œ‹ê&3ï] ­V˘;w.+V¬@§ÓYö ~øáöîÝËœ9søöÛo)((`öìÙhµZ–-[Æš5k˜>}:?þø#&“‰éÓ§S^^^Û£,!a¡  €Ý»w3qâD<ˆ^¯·ì«’Ud2?üðŸ|ò 7nä×_­&«4kÖŒ?þøƒ§žzŠiÓ¦_Û·%!a!##ƒ 60zôh²³³«Õ¹ÎËËãÃ?$,,Œßÿ7ÞxƒY³f±oß>öïßÏìÙ³y饗X½z5õêÕcܸq’¬"QkÜ…uÿþýüþûïWÛž’’ÂÉ“'yâ‰'ðññ¡AƒôìÙ“;vPVVFLL  8FC‡¨[·.;wî¬íq’¨MÊÊ +KõZmõíEEPXƒØ–š ›7‹Ï‰·Íµ~ýzþúë¯KîÛ¶m-[¶¤E‹ØÚÚ2dÈ***ˆ‹‹cÇŽ4nܘöíÛ£Ñh8p ÖÖÖÄÄÄÔö(KÔ4F#$'‹9j4‚­-øøÀ…õve21Ïœ Ê%W©„Æá‘G`øp •Þ)·’’’Ö¬Yÿÿþ{Ѿ²²2vïÞ̓>HXX¾¾¾<öØcÄÆÆ’””ÄöíÛéÞ½;¸»»ó裒˜˜ÈÙ³gk{Ä%$,¤¥¥±jÕ*N:uѾ¤¤$Μ9ÃСCñöö¦aÆtïÞ;vP^^ÎÞ½{qvv桇B£ÑЩS'BBB$YEâŽâرc¬\¹’ììì‹öÛfφ”±íìYøãñ¹„ r«xçw˜7oí‹‹‹£qãÆ–X€€ìíí9vìqqq–ºº JùøøÜÝ^™™bàèÑÛî¢zK1›!&vï†ÿ,®]Dy9¬_ÿý?< »vAiéùm¥¥'X®tíÝ»á£@§wwxàèÑ.(¬]È¡6mÈlÝSUé'•  ysǬ¼õ‘nnnŒ?žiÓ¦]TsN«ÕròäÉjî“Mš4!''‡´´4âããiÚ´©e_ƒ Ðjµ$&&Þò~JHÜ( 4`úôéŒ=ú¢R™™™äääиqc˶æÍ›süøq´Z-GŽÁÝÝÝâ^)É*w";w櫯¾bøðáí;qâööö–P …BA“&M,s8..Žððp4 ÞÞÞxyyWÛ·%qŸR£uXµZ-Z­¶ZÑewwwrssÑëõ¡T*Q«Õ€x€\\\ÈÌ̼b»ùùùlÙ²…Xbaï$L&f³ùÞNÈ`4B~>8;ƒBóçCP´l),Gr9””KéÞ½ ‚^/”Ð?ÿ__xë-°±C‡Äö·Þ‚ΡMq~åÜà™gD»ŽŽP%p´oíÛc08xð û¶m£C‡5:h4K’{{{T*999`mmmI\`ccƒ­­-YYYWl3== 6ЪU«Ú©çi´å°i£PÒ22„²em °u+$&ÂЧ@ÑMà«BkkÈ©lÇíâ¦Íf3©©©ìÞ½›>}ú\ú.-…•+¡wo‹¥±¼¼œ’’-ºm2‰±6¡ L&LvvèM\|û-88eûÙgÅIo¿ ééЩ "æô7ßÀ±cbnÂ…wÍÑ''hÐvsA£óvØ0qÝ¥K…‚“& ¯€ï¾ƒáÃÑ+•åæRZZJyy9œ9s†äädbbbprr¢´´µZMݺu‰ˆˆ ,, NÇßÿͱcÇj´P»Éd¢¤¤¤ÚÿÉÍͲ²2Š‹‹)**ªöŽwvvÆ`0\µhø‘#Gðôô¤uëÖ÷ö»R⺨ÊP“hµZt:Ý%eƒÁp‘¬¢T*qvv¾¢¬b6›‰¥Q£F4jÔ¨vS⎣¨¨ˆ¿ÿþ»Z2¤š ¸¸¹\n¹®\.ÇÕÕÕ2‡ÿ+«ØÚÚbccsÅ9®×ëÙ¹s'~~~%¢”¸9wîÛ·o§Aƒ7ÕN*¬—£*Æõr˜®bµ±µµ%<<¼Æøk!++‹Õ«W“””DóæÍiÓ¦ÍÝQ`]«JHf& $”ÈK‘ñÈœöïÇúøq˜3ìí!$Dô7ÂÈ‘àæÛ·ÃêÕ M› e¦´vìŠA“&â:¹¹0c ,R™ LFFi)ÖF#. ‰‰‰>|˜ãÇ[âë4 5¢U«V8::VÞ†öªó«¦¸R?®6ÇiÔ¨Qµ,•5Fq,UƒÁJ­XlhÝZXú@,J´l)#ÒÕ°X– †³ 9í{Àî`‚ÎÀôôtÆŒƒ\.çŸþáÃ?ÄÉÉ©ZJt:NìÞMÝÕ«‰ôQö§¦Kii)íÚµãé§Ÿ¶¬Wa0øý÷ß ¤YJ ò¿þÂäîÎ&¶ææ2âõ×q™;·ú"À»ïBE…PÄ+¿¬ÍO>I¡L†Íyå¸U+è×O,ÈTÑ …&°íäIlllð?q‚” B׮罌FxøarÃÂøß¤Idgg£P(°µµÅÎÎ+++6lÈðáÃñôôD¯×“@BBdýúõh4\]]ñóó»#27šÍæËÎñ+í«ÂÏϰ°°;â^$î"##¹›‘Ud2Rò1‰jh4š4iBBBBmw¸º,r¥g@¡P†‹‹Km߆Ä„‡‡ááá7½]£ «B¡@¡P`0PVº±iµZœœœP*•¨T*L&F£…BÉdB§ÓáæævÅvÕj5–6o'F£™LvE¡Êd2‘œœÌÒ¥K‰‹‹³(ªû÷ïgñâÅx{{3`ÀêÖ­‹»»û•í’X»ºtVʨWO(€7*ØétšŠÁÙ™b@¿~=Êõë‘9:r.(ˆîî(óò°Y½»ìl\6n„Q£Ðgea·jV{÷’íèÈ ggTF#”•a’ËÙ%“ñJb"õÃÃQtî -ZK’£#Z­S‹Ø´ovv”•—s&.ޏ¸8¬š4ÁW­Æ15•PÕÆÐ¹3e;³ÿŸØ·o¤¤¤Ä2O4 M›6¥}ûöòØØX<ÈÏ?ÿLYY®®®XYYոªV«1 ˜Ífd2™%™‡³³3jµ£ÑhÙg00 –{¸ÖÖÖxyyݾNëtÂzxá3Tn†Õ©°è<ÙŽÚBÉ hºº:´%%”••QVVFaa!* ÿïýIiç'Ü·¶€_ëCšü—ò).ÊÃûdTŸøA¿x£ùÚr¦OÏFÐë~[þóûÌçå^O`ã· YYÅJ%Ó’HÍ-â%ذ§6mxãá‡q8vŒ¥Ë—3÷èQ†¿;7wøäcL©©ì;{–Ívvä«T kÓ†Î#F°~×.ÿþ;~ÁÁŒŸ<™)S¦àxÂZVVFrq1‡¢¬¬ ›ÌLΜ9Cbb"YYY¸¸¸Ð®];Ú·o¯¯¯EI6 ¤¥¥±víZvïÞ¿¿?J¥’„„JJJÐjµÔ­[—°°0ž ÃÊÕ•ÒN˜ñÑGøúúòòË/ckk‹­­í%ßc*…Šºu©«©KW®hwhQ8+µ“ñǿԨER&“¡R©0TŃÅsÆÖÖö¢}:µZ}UÏGGÇ»c1O¢Fñöö¾h1êvs%YE¡Pܰ¬âäätÑbœÄýJ¥ÂË˫ƽT*f³Ù2‡Íf3:Îòþ¯¬¢×ë1•7»¹\Ž»»{?¯·½^OYY â ""‚ÔÔTÒÓÓ9}ú4™™™èõzBBBpvv&>>µZM`` vvvÄ?Nll,­Zµâ™!C(1ùtÜ8JKKéÞ½;=ôE ¸¡¡¡ 8ââbJJJðööfÛ¶m—u½]4lØsçÎa2™P(¤¦¦RTT„ŸŸ 6$99N‡µµ5ÙÙÙdffÖ¸Ûr5ŠŠ`òd1¿ºuƒˆn°Þv•AÂ2xé1¤#ÛsŒøãQ{«ùÍó7TÖ*1M„Ä„ÐÆØ†Ÿ¬"{G6C‡¥ÓÊNüû/?|òJ@Ut˜úνi²®5ºÒÍ,M]Á€#GèY&G½wÃôrâÙ vΉ¡mŠõër¥'â²×wŒÆñhmlUÂÅÖlftïþlÛœMÑ…äõËÇ·¼  ›9f“Á„éÓÉÓé˜9m&ñ'ËÉ;ǸG>"À3€ñ øðÃyâ‰'(--%##ƒ-[¶`2™ ÂÕÕ•JE³fÍ,óïÌ™3lذiÓ¦!—Ë0`ŽŽŽ¬X±‚üü|êÕ«Çûï¿O½zõ,Ã[\\LAA%%%|ñÅ|ûí·<ýôÓ,Y²­VË3ÏÍþýû™:uj­ ÑhäÔ©SÌŸ?Ÿ´´4BBB˜9s&Ÿ~ú©åŸÏŽ;HJJ";;>þøcêètÈ?ùüý¡Ò:æ’ŸO¯ìlº?ðú¨(r4 õøq¼æÍÃ3?Ÿ >ñ÷'C©¤ÁÙ³øl EÿÁøûûÓ¼];œZ´@OÑ–-dfeá·r%.¹¹äY[³ÙÍz=Míì(—£7›9°i¿:8]TDgkkQÉkáá鉲RI­²^þ·"è…ÖB¥RIð%ÆI¥RѵkWBBBøì³Ï8|ø0¾¾¾xzzÒ·o_ÂÂÂ0›Íœ:uгgÏòòË/••r¹£ÑHQQ¿üò /¼ý6J¥’ÁƒÓ§O¬­­¯k…ÇÞÞ¾vâ<+éÒ¥ _ý5‰‰‰xxx°iÓ& mÛ¶ÅÖÖ–?þ˜ãÇ[2`geeÑí‚D;5‚É99àâ %vè›Göåo&Ø!‡zÀ›z} •’3ÇŽñ믿rôèQž™ú Ý;ÒqVGC(ë)Q”+P„) 74ônÈÙ³gùꫯ˜?>õë×gÒ¤I8;;“››Ë®v‘›¡'zw4o†øÞÌU‚ ÞU#o¤¦¾³žxòý¸Åx­ö¢½_êþP+½lr2 q+(iñÐþIÙa9lÛ¶³»hTô]‡{`Wj‡‡^Æç®ŸSt¬Û޶ØÚÛ";-ãuÕë¬8·‚E¯-ÂÛ׿?^îö2!…!hŠ5țɡ ày~Ø"##iÔ¨å¥åÙs„5ó×’”Â7‡Ð²WKìíí…µS ”J°7ØcïmJ˜6m£Gf̘1”ä—0eèl·…0  @&°³ò÷@ 0P´‡ Œ`nn¦äÛLŠšKvU•QríÚµ´nݹ\Îo¿ýFÆ ©W¯;wfÆ ôêÕ kkkÖ¬Yƒ····w¿™)[KK!8XÄ€——òe")ž½=¼ô’p¥_½6máíÚÁ€â¼åË…wŽÙ,;wî¤gÏžœ8q‚0cÆŒÚý[ŠÙl&;;³ÙŒ§§xF–-[Æ×_ÍäÉ“iÓ¦Í]­´êtºj-T*öööÕîéÌ™3!¾ÊµÛÃãš\RŸOaRÚ”NŸ;ÇÑ¢"еZ|ðAš6mZm±½  €~øõë×cggGii)=zô¨ÑûŽŽŽfþüùlÙ²…~ýú‘’’ž={˜0a 6}òÉ'œ C‡BÛ¶ÂJ ¢Åôé(²¨/àëí-â7Íftj5O•–b0()(ÀÉɉ¦J%ÙÙÙ;vŒu›7SRR‚‡‡Ö±±øúúb;d. žÖÖ„úùáèçWÍí(P«%8#œœœ®{"]««µL&£N:Ìž=û²ÇxyyY,/¢P(pvvæÙgŸ¥]»vØÛÛX•õ.£C‡lß¾#FàææFBBÏ?ÿ<ŽŽŽDEEѲeKƇ··7 :ggçÛ×!#”~€¼~üb3¡ñëð—-‹Ó÷²)o]žèBD-[ îîî9ÈÊ•+-JõsÏ=‡2™ ë!Öð7¤€ P  <<œ3fœœL`` ªÊxW;;»óÿ×ðÛU™¶ à È@† /žœù$‡·Æ#Ú+ßÊ—zÂê˜ ØË„bÝäx*<Ül0YC³P¨°/µ‡•@h†kЄhà‚Bå)%Cò‡0¤Ñèè¤Nô$`&àŽP(mÈËäØn¶¥Ex Z¸¶'DR©Ïĵ8œFä`ï ÄMÅøÛ¹Û1¡Ç–Í[FÇðŽxïöñ¼YÀfàÐØÔžªìÓ¥P€ÙÙLQXfy͹½«T*† ˜1cxóÍ7Q(dgg3}útlllèß¿?111¼ùæ›h4ÒÓÓùàƒîÈ„x׈N'Ê„;'Hoo±íÓOE<¶•¼ð‚H€·f ÄÆŠ„zÏ?/V™ \\DÙ&77q<@‹˜|}9rä ¢¢P€hãwÎ_ûJÙ¶oŽŽŽ<÷ÜsŒ5Š£GZ’Œ=øàƒ( üüüxøá‡ùòË/Y·nÉÉÉtëÖÍâqp7b2™(,,ÄÁÁÁb™™É›o¾Iii)Ÿ|ò ìß¿Ÿ5kÖðÚk¯ñé§Ÿâàà@ãÆÉÊÊbΜ9Èd2HãÆk$LëFIHHàË/¿äÌ™3X[[ãææ†Éd"77—ðÐC!—ËÙºu+Ÿþ9-[¶ÄÆÆ†ŒŒ ÒŽåÕfÍhbcÃY†ßŠŠ8ºw/$%á[R‚·ƒ6/¾HªFê‰ ·³ÃÎÓ~˜ÒæÍ™0ašÔTôí‹[E‡<<8SÃJ¿··7ƒfÁ‚lݺ•ÔÔTÚµkGóæÍ¡ÐFGGóþûïãååŹsçn¿¬rqöìY>úè#¢¢¢2dnnn”––rôèQT*5º®PŸòòrÆŒƒ“““¥îyRRjµš.]ºàååEaa!iiiäççc41 tìØ‘·ß~û²á :u¢S§NdïÞ½üóÏ?–œ;vÄÖÖ¶nÝÊèÑ£4h¥‚†ÙlæôéÓÄÄÄжmÛ›3™¹2ÒäååqàÀhÒ¤ÉE.›‰‰‰ÄÇÇjq¾U‰UZ·n}Õ8ÀëA§Ó±fÍ–-[Ƈ¯¿Nýノˆ¦N%C­æí×^ãÝ-°_¸ý´i4èÑCdM=wN$êׯ¦‡UâlÛ¶ {{{š5kVã×Þ»w/999´jÕê¢$‡"55•èèh<<<®ØN~~>¿ÿþû%SÓ_p X¢…òLÈöƒ2Èÿ}`…Y¦`½l=Ë6-cäÈ‘üûï¿ìÞ½Û²âìííMÿþý/¹Èpß þA(ÕÖTÏxl@(¸ÖÅÖñ?m»ʽ‚4㦊‹éõz~ÿýwÚµkw{cœ/Ayy9ûöíÃd2UmUV¯×óï¿ÿ¢ÓéˆŽŽÆÁÁáŠm%%%±oß>~øá½‡ûƒAÔ­.)€aùÌÉÿýO„ DG‹„{ÖðÉ 0%‹× «Ñ(2gƒH–P=¾ŠsÀ 'Õ¼ ›6mbñâÅàhçÈ„^j„ÒW •¯Ì]»vñÛo¿1sæÌ¢ÜÜ\<ˆ££#Mš4±,¼U‘À‘#G¨[·nµ0€KQTTÄš5kxüñÇkü>®DBB«W¯æðá䥥áììLÏž=±··gÁ‚Œ5 &OžLãÆÙ¿?S¦L¡Q£FìÞ½›)S¦ÐµkW¶nÝÊc=†­­-üñeeexzzZ²š‡‡‡ßQÊΨ_¤±·7¾ý¶HÒ˜˜{ö•–ÆÌõëÉpwÇÃÑ‘òù¨[7\<<ÄŒ—å›6qnÉdd`ǹ];:vìxÉøäŠŠ –ÌŸOÎæÍè Ø"“ñôÓOóˆ^º ÂÂH dÿ±c 8°ÆÇ!99™¸¸8‚‚‚.™ÅõàÁƒ¤¥¥Ñ¢E‹«º/:tNW£YëkƒÔÔTNœ8ANN!!!„‡‡£ÕjÙ¿?þù'>>>tîÜ™zõêY€V¡ÓéX¶lË–-㥗^"++‹•+Wbgg‡V«ÅÇLJ²²2JJJðóó#22ÒbdJOOG¯×c2™ˆˆˆ N:”––²oß>öîÝKïÞ½yôÑGk5Ë~FF³gÏ&%%L&4ééô()ÁÏ×—âW^¡gÏž7Üv­(¬·’[­°jµZNœ8Áwß}GaF£ßŸðÆEÆ}ûÀÏSh({æÏÇjÎlGޤîO P©Äÿºu¢¼Exxmµ«°Þ*nHa5;Ͱ¿–~Cœáõ@®†Ä$ðõk5ÅÅżùæ›<óÌ3´k×®¶oUâ:©M…õV")¬µÀر"vh=è÷8¤„ÁñXµ†:@ ?Øå¶ øGUÐ á$G,ˆUéo& oÝh(Ž1—˜É™Ç¹ŒsÔëR»v˜ë˜IONgàlOÚÎS/=EÓȦœ\y’²ÊÈ È£›_7lß¶å¤é$ ?Xˆ²¾’ÉßN®í»)î4…µªÌÎìÙ³iÙ²%íÚµ# €S§NñÇÀ3Ï222°··§qãÆDFFqÞ«ÁdáÙÙ’‘‘Â{åv¡× ¯›ÒRÊáåII0u*DFHžFC§Nnøw®¿F-––ÆÌ™3):y’‡ê×§‡\ŽÊh;ííE¦^Äwu›^ ¡G‚‚‚Î7`g’À%QÛ˜€_€_ÊÁ}¼,\Ó+_ÐÙ\T À¿ÿþ‹££#M›6­í^KHHÜn´Z‘]^­†?®¹kPài'ˆè›ñÔuní=Tð9ÂU>h‹p}÷B€,ÐÔw&Ž€¯pŸæNyÃrô“ô¬?¸ž¸qÈ6Êè6½ {%á% ðÀ“žDqRÛ!Ú'ŽÁ_»þâ ÿ‡×/ Œh5‚ÍN›k{äî9bcc7nï¾ûn5š¨¨(¢¢¢ª+“É bÒ¤IÕ¶«T*zöìy‘ÕD¥R@@@mÚ´ ´´”ÇsäÈ-ZDVVNNNÈd2Z¶lIïÞ½¯šeù¦(+tVVLÏË£Õ—_bÛ«×ùý⃈é" áeP(ו+C­VßÞû“¸"f³™uëÖ±bÅ ¨[·.*•ŠƒR\\Œ &“ kkkrss ¡~ýú,[¶Œ¬¬,d2õë×§}ûö|ðÁ–ØS“ÉDBBjµ???Ëõ†Jff&ñññœøà¥w$' eQ§ƒyóÄ¢¤L&Â1EŽ…B„f\yÀ„NR’ø;,LÔœ/,„={D»f³ÈG°aƒÈ= ×ÓOŠ>ÀW_`cÇŽ¥E %µ²µµ¥M›6´iÓÆ/[TTDnn.«V­bÛ¶mŒ;–    :ÎRV¥¢¢ƒÁ€^¯·üm6›qtt´”Y1™L?~œm۶ѲQ#¼ÑØÙac6c•™ óçÃk¯qª´”åå¼Y©HKÜý˜Íf INNæÈ‘#DFFâî­-VVVFÖ¯_Ï¢E‹,%äŽ=JYYÏ>û¬EÑ¬Êæïáá··7 …‚Áƒ[ꤻ¹¹]”F.—|É~yzzâééI×®]kbDÙËo¾™3ÁÁÞzK(§zìÝ ?þ(¾\$Æ3„%öäIÈʆ7³Y(¦±±bßsÏ …U&Ö[• r„Œ>â瞣^eR¤Lhw#Ç€Exö4 µ·eןþÉ?þÈìÙ³9~ü8sçÎ¥qãÆ4nܸ¶{-!q÷abVG;D&ç;õU«…éÓ¡N±R^ÕÿUÀ#@=áÆ™™™IEE…å´ÂÓ…äååYjEzzz’`Àñ=Ç9~ü8ÙÙÙTTTàêêʆЪU+”J%ºu¿7¢«D(rT¸¹¹UûëݳòS‰L&ÃÍÍ ÷ȼZHºt·c4Yºt)k×®ÅÞÞžââbéСë×¯ÇÆÆ†1cÆÐ¤I“ZéŸ\.ÇÙÙgggiÔ¨›7oæwÞ¡~ýúØÚÚ’––†ÙlÆÍÍììl¬­­©¨¨ÀÍÍÌÌLÊrr0Éd¼>r$Íš5cóæÍ,š=›Ö¹¹Ä§¥±¢kW :s†.IIèºv¥¾“¯XaÉö,q÷“ŸŸÏš5kزe r¹œ6n܈B¡ÀÚÚ;;;”J%ñññÌš5ËbhªJ.u!—Ê'¢T*ñöö¾Z7jŸ’á~ûôÓç]/•SàÁ¡eKøç¡¨À‚"wAT”PJårxäñ¹èÝûâvkÀ{àNýz½­F~üñG8@][[†ÄÄàóÊ+x ‚¼ƒ•%$n #p°ýÿDièrõz´Z-±±±,_¾œ>øÀ?Ô©S§Z Η¸0š1äЗ鑩eh¬5"£ô´Z ¡Uµ»Ï^°Ûm7¿ùŒŒ üýýÉÏÏÇd2áàà€­­­e·¤¤"##éÒ¥ ØØØàèèX-y¢UK+‘Y»öª‹Ý—èõzöîÝËÏ?ÿŒµµ5#Gޤ~ýúhµZöîÝËxúé§iÚ´éíWØtºóÙ ¯B•kqDD%%%bî<ˆ¼n]¬‘ÉdXYY¡T*…+¦ÙŒùë¯I\µŠ…#F°0, £BÁ$oo‚»w‡)sq¡°¼}eß}§N1ûÅ‘Ëå|ñÅwu) at:|ø0óæÍ#001cÆàíí½½=¥¥¥QVVFFFÅÅÅ<ûì³Ôv·oÅÅÂjm mÚˆ÷üSOÁµ$5òð€‡:ÿ·‹‹ÈÌ®RYBÇîDîK…533“Í›73kÖ,üE‘òúõk»[7ÇàïT¨ø>ÍÊM›Ø¸q#GGGÆW­ì‚´Â,qßSŽH¤¼ÄöÈÏÊG±LÁ¡Ã‡H°N CŸÁ+½^ÁÎËBa·BÖl[Æ‚ t èÂÁƒÑý«ã9ùsXí·‚©ˆ¬ÑW£ ø pæÆV#°‘øè4`•Ó?Ȧàý ô.]²ÊüʘóõúöíËo¼§§ç­[ÄrºEÿ#‰k"''‡¹sçrîÜ9HïÞ½-‰e4Í%cMo˜ÔTáèï/S¨®œ&'Ã×_ —à ª»$^___‘´eêT!—EE‰88±q§N»»ø¼ú* [´`òo¿±¹aCš÷ï‡ÈXpz°N ¤¤„ììl)–ô.'55•Ï>ûŒÔÔT^y墣£«eð¶µµµ„9…„„Ôvw¯ ƒv‚‚àÑG/Ÿ$)/&LÊeUE;;èßÿÆ®-—[ž›;™ûRaýcõjš»ºâmk+ÌÛW)¹ !qÇ“| <¯ÓÓ¤ººòçŸ2kÖ,‹õãN®‰'!Q£d!’ m‚*·u#ž¥`(2• Þ•‰ò/;´ðB|áÃëÀ¸ °ð¬²û' êg‹Áìofq 4à±Ç“¼-îRÌf3 L:•FñÎ;ï\sæÚj r(@)"^Ym §B!’¦üü³¬_](¬™™0r¤ˆ…{àhÕJĺµn-{M™õê‰ä-›7‹Œ¥O? ¾¾¢ò¾}B1 n… bßÈ‘B`7™à·ß`Ù2á1ð BaÕh }{¬Z¶¤·Ry¾Öý°³³“jïbòòòX¶l[·nåÁdüøñØØØÔ\†ék!7W,ÞØÚž_¨)/^ŽŽÕÝtóó…•´S'a)õôሠbÑÇÑNŸ ΞÏÖËc_xBC-Y«ïî; 6;;›-+W2ÃhDYX(Láw;鈒<1áΟóçqKkKHÜõ˜uuG(~c?„Uò "ëm -Y„R®ä¡çBS)ôî×ww–,YBëÖ­üè`êÔ©ciÞÝÝ7Þxƒ]ÞÞÌXøÖ><¾Ô›æ@]èÞ¾Iý>ØÖ ’M ; sä`=Ú¾ ú–PP «V ¡¥D_M‚û–ø. ¶Þ…uáV¤ƒz<|aƒÂWJèþ"©R"0è ü Ôâ¾Å¬š¼Š·ß~[RVïbNœ8Áûï¿Ï£>ʃ>ˆu•Ë÷õŽ'9 „…À7@O3˜W+i£F‘!jõ~ô‘P0AX@gÍ5yóóE²èÓGì«Jè·t©°Æ>ðÀy¹ËÍMlûþ{áÎhï… ¡uC‘µZ†ú[µ‚ví„¢zá\•ɪ[vT/·$qÏ••ÅØ±cñòòâã?&00ðÎrëÖë…utþ|¡P~ôÔ­+Ê%Í™#âC;v„W^ñ¦óæ‰H^^о½˜Ëáá—ÄT«… oHˆXÈñ|5jt}ýÛÓ¸‹×kî+…Õh4²xñbz~:À)¨%$îZtÀ<´t” ìØ±ƒñãÇ×vÏ$$î Ì@6pø˜xQ)#j‡FŠßM&¿ýö`ƌՙLF” ÍóòmÝŠ,0P$2ªâÈT>>txì1Z<ô³fÍbö¡94z¶8ÿA÷úÝT6Ùl³¬'Ê@Ïé`ðÂ5ëÀ&gxþ5Øl†•2øAVЦfNOØ|©Y¾Ð~q¥% ‘P)x‘ØÈáš¼¡¤×‡#ÿÁÎÎŽzõêÕöGâ0ìØ±ƒ¹sç2jÔ(¢££¯.Àg{Êà¦ÊmÍ€ÍÀ@à#Î?&øê_øÆÞóÊ`r=xè}8&!(õÙ¥ýýÏËSF¬ÎÉátc1ÏÝþ#ÀUžô±N‘É´Âëäð˜¿k×¢üà$Ð áaD$ðj\Ù6•ÛFVîo <8 žýbD­šË)²G ûI B¸è€XÌjG,jWö#®r{bå±õ+ÇÍRPTÙ§úˆgPVyÎ: àÖ윹1™LlÞ¼™o¿ý–¡C‡Ò§OŸÛç-f6 ©É$Uª®c0 §R)j22`ñbá¯V oWW¡|~ù¥x;9‰sýýá“O„µ´Êâjm-J¿¼ñ†X€¹ÒspÞ-þFHB,>D$ìP\­^eˆ¹}¡Ìž@ÌßÁˆÅζœO*x-öªïÄów ¹¯Ö‚‚<ȇÆ!kÕêŽ.–¸fʀ橰ê3xp›6mÂÃÃãÞJ0 !q£˜€³ˆxÒAÀLÀóâÃ̘1è lÙ²…_~ù…÷Þ{—KxàȬ­‘=ýôy„à²jlßÓ§#svF£Ñ0zôh 1l66;ŒÜ•¹dÍɳªÀÀöÐÏþü·q_„"›$E¿g"„]<Öç;Ó ðRC€ºº0> zŸ&#æ3¼Ø‚ÙhféÒ¥ôêÕ ›» vI¢:&“‰ƒ2gÎFŽIË–-/°È!Î3Àc•¿ cuAÄO_(7—æÀ™ŸáÝIPä,<Ì2PÉ„°›€Pæl "eBŽb+Ûì°Ökp x !Ȇ"W*dð—B$ ›Š¨ë+GÍ%ˆç·áºoƒP¸ •ûÿDÖMµ„Û"”Ø/e˜þA(«û€îÀT·2¥ ‰^FòÞWh*ÇİFxbÔ¯ÜæXÙOkÀµòX„¢›YÙ¦¹ò:ñ•ãä‰X4‹B(Õs+ûWÖ¥Ö¨mÔHTÇd2±}ûvæÎË[o½EÇŽoíŒF¡¤*•"dãÿƒƒ…BùÙgbfûva5Õëáùç…Âêä$âE‹‹EvvBýOýb zªñ]ä®7wñ^¿ZÄsëÎ¥ZŒˆE%bžÉ.qþJÄ"É``⹃P>7WŽX$jŒx'D#ž?_Ä÷ˆEÞeˆg§b.Ë*ïGVÙYe~D&ŒóÉÁÎ!”²9o™œÅyËgí+û´XXù{/„Òù<ð5ÕËiþÓWÿÊŸÞî‰Êó×ùˆçܾòçï•ÛêUöµ"FwÐa¹X 4G(½U\hIº\E“KY›".slB±¿PììŒP^vƒ:]ÚKRXÿËÆ™;w.³fÍ"44ôÖ6~℈‹ „aÃDýÐ7Þ¨^[ Cñ¹kk?z½¤# 3Šc4çÍ„ñábf Bñë†ð<¸PœËB,@Éu¬ßF,„TyËçKst$"ÏAsŠêƒ/£+Q¥kO¨l3áÔ´òï“•m´R qðâÙC,ø©À„Yf¾©Ù}£°êõz6ÿú+ÏvïŽJJ>#q¯†×‡¦žÄÄÄàééyë_îw:Ä*ò6„e±Þù¤ëÖ­ÃÊÊ ¹\ŽN§ÃÎÎ{{{ºvíJ—.]p¸0_q1œ9kÖˆ8ºN.¾–·7¼ûî•]»:Ct»h~9ò k×®eðàÁÈd2L&yyylÞ¼™C‡a4Q”+p÷rÇêkQÊ£{÷º¢R©ÈÈÈ`Æ œ={™L†^¯')) OOO\]] ÂÞÞ¾š‡EÆ ±µµµdÒÔëõ8;;Wˬ)qw——Ç×_Í믿^]Y5"„Æ8„@ë€H¶õbþ×EH|Z-,YYYb>GG ·Æ„غþýWX’š5»¶Õ©üä"”R/.VV«P Üa;!bÉÝ‹3ÎÜXÜiXå¹sQœ·œÚ ¬ÈYùY…öG"|‹ž·§Kl³F$·jE‰E”ì/¹Í¸{0™Lœ aqm‚pñ}°r¿"Jäâ{¯ÊÅ¿7¦˜^*χÿVÜ©I+¬%%%lݺ•ýû÷£R©èÖ­7¶$¶ÈÍÍeóæÍÄÆÆHŸ>}ðòòº©l`ƒ#ýE£QøßI™Å$î9 §Nâï¿ÿ&;;›f͚Ѿ}{<==1™L¤§§³zõj222ˆŒŒ¤S§N7.lî5ƒ"dn rŽ=ÊСCk{$îq´Z-û÷ïgûöíTTTЪU+Ú´iƒ½½½eþ¯^½£ÑH‹-hÛ¶­Åõ¶Sårø"ÞÆ Î=ÇôéÓyþùç騱ãÕ3©šLPP b•ºu+«[²Ð˜1cHOO'++ …BÁèÑ£©[·.jõÅnf³™¢¢"²²²((( ((WW×;+Cæ=Hqq1Û¶mcÿþý¨ÕjºwïNDD„eîäää°iÓ&âãã ¢wïÞ7-«\ü•JÅC=T=³sÂ%w4"¶òB´Zá| âí† ¹¸ñä¾À!ôD(ÍïÖv‡j´´4vìØÁáÇqww§_¿~¢T*1™L¤¥¥±zõj233iÒ¤ ;v¼í cƒ¯¿þš.]ºÐ¢E‹›o°¨æÎ…“'E"¥‘#…G̵*«„+¬ B¬ú È@ÄhF¸ëª‹¥jDŒç*„úoˆE‘vWô*<É\] sÆ#\mE(¨ÿ=Gpko~ ÿw 5ú§×ëùöÛoùòË/qpp@§Ó1fÌþúë/L&S§NeñâÅxyyñï¿ÿ2aÂrssoêºEEEÄÅÇã;eÊù$·‰¸¸8Þzë-²³³ñóócÑ¢EŒ?žòòròòò5jÀÃß~ú‰O?ýôÆ/–¨…ï?ü<>Œ““·{ÕPâ¾Æd2±víZ&Mš„ÙlF£Ñ0}út¾ûî;***8rä£F"77¥RÉŒ3XµjU t Ø…p­š†H°b%’í}úé§<ûì³ôìÙóÒÊê’%"Ùˆ’‡ÁôéÂâdm->·È+G©TM¿~ýxî¹çxõÕWiذá%•U™‰©[·.ÑÑѸ»»KÊêm¦¢¢‚o¾ù†¯¾ú GGG´Z-£FbݺuYeÊ”),]º///víÚŇ~H^^ÞmëÓáÇٰao¼ñFõ¹R¬@ÄþWYÕëᇄ‡À‹/ eUBĵ>€ˆcõ¨íÎÔåååŒ?žß~û€€’““y饗ˆĄ̆Q£8tèüðÃÌ™3ç¶÷kûöíðä“OÞx}Õ¢"8p@d÷up€6m`Ì‘­×ÛûÊç±ßg®¸«Ù³G#ÜzA(ª£*ñGx4TeÏ@(°"Üß—",©s±¢y­&C;Ä<õ¹ŽsîAjôÖÏ;gyávïÞ£ÑÈŒ3X»v-ݺuãøñãÄÆÆ2qâDZ¶lIvv6Æ cóæÍ ¹ÔŠà5²bŠºuÃájòv%îSV®\IPPï¿ÿ>†¦M›2iÒ$âââ8qâ%%%̘1///š4iÂØ±c9rä 6¼¾ %ñiÐÌŒÉÖ–ß~û‡zHŠK“¸­”––²bÅ z÷îÍ«¯¾ŠLX˜Å‹Ó·o_/^L@@“&MB©TâííÍŠ+hß¾=~·³”ØYD6ÃwE+ùþûïqqq¡{÷ ³g‹ÂîíÛ‹m¿ý?ý“& EUâ¾ãܹslÚ´‰·Þz‹®]»b4™6mšEV9räñññLž<™èèh233yꩧغu+<òÈ-ïÏ‘#G7nÓ¦M;ÿ n‚?!â0_âD…Z¶„no|ÞÝÈÓˆE®û”={ö‘‘ÁäÉ“‰ŒŒ¤¤¤„—^z‰7Ò¤IÖ®]KYYŸ~ú)4nܘ>ø€£GÒ AƒÛÒ§ãÇóÙgŸ1kÖ,o¬‘Ü\˜2EÔ@­ á¸Zvá«*Äl†sçDÖßîÝEAöaê+¦66v«2ÂHÜ,ñññäçç×è5CCCyà,²JNNëÖ­ãÕW_ÅÆÆ†3gÎ`ggg‘UÔj5uëÖåÏ?ÿ¼b»)))$''ãïï-Ý@§Ó1{ölüýý6l²"üŠ”‡#ê‚ʹØô`6Cl¬ðhÕªFÇNâú(//'>>žòò›«Qy½´k׎?ÿü“3fЯ_?bccIMMåõ×_àäÉ“ôíÛ×"«¸»»ãææÆ‰'.Û¦ÑhäÔ©SÔ­[÷ºb]F#?ÿü3:ŽáÇWϾ”Jxûm±Ps¹6ŒÏ„SWDÙOÄsu¥5ÊDÞ«'QœœNž$$®™L†‡‡¥¥¥¬Y³Êf:u,Šæ…óP.—[¬¯·œ D—¥2*/k4™3g<ð5ý1›áèQøè#xøáª›©íᔸ©’Uøý÷ßÉÏÏÇ`0ÜVYåR¤¤¤ÏìÙ³Q›Ôð!¢\Ó„€}9ôz˜7úô©í¡”¸CQ©Txxx°nÝ:ôz= øùùáì,RÕÖÔHNNfýúõ¼ÿþûWOˆw!&“˜ë%%"AçΗ·ªñÞß#¾7šO!¬¦×šPÆ}CZÛ\vèu:z½»Ê }£ÑHll,%%%xzz|i«+pèÐ!>ÿüs>ÿüs¢££1 ,]º”±cDzhѢ˞geeuÅvmll¨_¿þ%'z~v6gCB¨/Õ^½¯P(Ô©S‡¤¤¤u¯ŠË bòäÉ( N:Å»ï¾K:u.{ÞÕæ¸££cõ×R`U¤m‚7!>>ž‘#GJ ë}„Z­¦~ýúœ8q¢Fçxnn.S¦Laذa 6 £ÑHLL cÆŒÁÉÉé’ç(Š«ÆVûúúR¯^½ëëÌ7@ ¢,@%:Ž/¾øWWWž}öÙócc0ÀÊ•b>:ºÆÆKâæˆˆˆàܹs5zÍðÕW_ñÅ_…Á``ñâÅŒ;–Å‹_ö¼«½Çýüü®Ùº °sçN¢¢¢pµwõÛ#’]ê2ùùbQÆÅEï*ÕÕc÷$jFCDDû÷ﯱkšL&V­ZÅ¡C‡X´huêÔ¡¼¼œ &0yòd¾úê«Ëž{¥9®P(®ÛºZ^^Îÿþ÷?úöí{ýïÿ´4‘L)?^{íòÇF”9KGÔ7½=!¸—ÁÍÍzõêQXXxSí\$åFþùçÞ~ûm~ýõW@øºÏŸ?Ÿ#F0nÜ8Þzë-.\HEEÅu],>>kkkšU¤V*•´k׎¢¢"rrrððð ¢¢‚²²2@殮¥]× þ¿)-%¯K—[;ú—!;;›³gÏÒ¹sg 2™ŒÐÐPêׯϑ#Gpww§¨¨ƒÁWß‚‚|}}¯ïBJ@¹ìM”––RTTD@@@mß¾Ä}@BBEEE–xi…BATTÖÖÖ$$$àééY-[jzz:J¥òÖ—CÈ\±DpøðabbbÎÇ­BYU©à­·D)ŸÄˆ‹‹³$̃ó²JAA¹¹¹xzz¢Óé,²Š^¯¿iYå¿èõzvîÜI‡Ÿ”ÃÄÂÌ¥ôfÎnÀ¡¡0v,H¡P—@§Ó±ÿ~ÂÃÃ-U¬­­éܹ3çΣ¬¬ ooïj²JAAEEE×/«\³ÙÌËåôë×ïÚ^SSaùrQ®ÉÃC$ÇûòKèÝÌ ‘É÷_à ð"cü*Dêx$eõ.æ¢Ù±ÿ~ÆŒƒ^¯·L䨨X~üñGÚµkÇøñãéÞ½; .dË–-×u±*7²¢¢"˶sçÎa4qtt´dÛKHH„¢¼oß¾›*|øðaBk ¢­„ªV«ÉÊʲ¸ÔœœŒ»»;íÛ·çСC”––Âå+))éúë˜a“¢[qúôi\]]±µµ­íÛ—¸pssÃ`0T+7–žžNQQ´lÙ’þùDzïàÁƒh4BBBnär—g)báæ?aÛ‹/fèСxxTÖ«X¹~ÿ]ü.•õ¸<<<(++£¸¸Ø²íܹs˜L&iÑ¢iii$%%ÂJ´ÿþ›’UþËîÝ»Åh3‘•ôM.7Wåþ+—ŸWuu•JøI\•J…››¹¹¹–ØY³Ù̉'Ðh4ØØØÐºuk8`Y”INN&99™è[èb4Y·n]»v½¶:ÝII¢–pNŽ˜ïj5Ÿ¯©z ‘Œì·ÊßË<ï %ݧ%ŒîªùÉ–••±|ùr4hÀôéÓqppD]$¥RÉ›o¾‰««+mÚ´!))‰]»vѹsçËÖû/M›6%$$„±cÇÒ­[7´Z-Ë—/§W¯^8::âììŒ_}õ>ú(;wîD&“Ñ¡C‡»»Š ܲÏÁƒk{œ%î4  `ñâÅ”••áëëËæÍ›)**¢[·n¨ÕjV­ZÅ·ß~KË–-Yºt)AAA4ªJ¿~­hÖ!Оĭ‡“’ÄHÔ^^^tîÜ™™3gÒ·o_¬­­Y³f 4lØ…BÁ¬Y³X´h...üøã´oßþ–ZŸÈAdÉžU}ó(//§k×®"¾iãFøõW!äHH\#Í›7'00±cÇÒµkW´Z-Ë–-£OŸ>ØÛÛ‰··7_}õƒfÇŽ( ÚW•FºIôz=7n¤W÷^°(êpi…Õd__2D*Ã$qM(•JúôéÃØ±c™4iíÛ·'55•U«VñüóÏЩS'þøãæÏŸOtt4?ÿü3ÁÁÁ×_~ï sâÄ ž{l2ÁöíЯôí{q¬êa`ð%`‹”餚ªÓéHHH`ðàÁÕj íÛ·èèhK†'kkk|||ˆ‹‹£¢¢âšV>üðC–.]ÊÚµkQ*• 4ˆ>}úXVWÆÇ¢E‹øê«¯ âÃ?¼qWǃQ«TX{HË*5Çã?އ‡7ndÇŽ4hЀáÇS·n]L&&Là§Ÿ~bÞ¼y4oÞœ^w<8f<è "›_pppmß¶Ä}‚F£aĈ¬ZµŠíÛ·£×ëiÖ¬<òžžž¸¹¹QQQÁŠ+¨¨¨ [·n <øÆ3?^Š\ ÕVÌ+**X¾|9ݺuß'z=œ8,\$%$®___‹¬ò矢R©xôÑGéÝ»·%WÆøñã-²J:uøðÃoYáÜÜ\xõWE‰¯¸| +«óIÄ$$®‘F1~üxþúë/–.]Š‹‹ |ðmÛ¶ 00ñãÇóÓO?qàÀ¢¢¢nLV¹{÷î%<<Ÿ«,—ÃO\z_°HN4÷,ÕfžÑh¤´´´škazz:ÇgÈ!·ä‚þþþ¼ýöÛhµZd2666ÕüÖ9r$Z­µZ}}ÃþCùáÃ÷ö&RRX%j[[[úõëG÷îÝ1 X[[[uär9‘‘‘Ô«W½^F£¹j2šK’byF-‰‰‰tïÞ½¶o[â>ÂÍͧŸ~šG}³ÙŒF£±2 …‚nݺѦML&666·VY“Ô’j«è)))¤§§óÖ[o‰ *¼ð‚p“¸Nxçw.+«òî»ï¢Õj±²²ºjÂ¥ëa÷îÝ„„„àšá ï"bµÿ‹Ù ‡··äþ+qCDGGÓ¤I´Z-J¥²ZY<¹\N“&M C¯×cccsK•Õòòr~ùåÞyç+·[QÛ¶A³fÂսнˆ÷°QûÖyäKÜT‹aU«ÕxzzröìY˶ݻwãààpQüQjj*®®®×=e2*• {{{ììì.d­V«qpp¸)e ÖͳÁÁ×l–¸UT 8—œ‡SV’K`ã_”ääPZZzËVö%$®•ª¢óööö}Èd2lmm±··¿õÊj&à4©¾yÓ¦M4oÞW[[á \^.¬ORæl‰àzd•[©¬‚pmïÔ¢Ê_•àÎ¥­«%%ðùçž^ÛC%q—"“É,sør5Ü«d•[©¬=z¹\NDDÄ•\º~þY$Ï»Í@>Bim E*9sSíßkggG·nݘ?¾EY°` 4 00Ð’hcýúõ:tˆ1cÆÜòõ­äpN ¢¢j»·žÄb°Ï£°¼¥Ry㊯„ÄÝ„X8NðÓO?C~~>z½ž9sæ Ø¼þøÚ´©íÞJH\7™™™;zŒw½ #±«—".N”°‘jÌKÜ…lذž={^ù #GDæëÏ>«ž0o#"ëo7.‘:Vâ^¥šÂ*—Ëyà8~ü8³fÍB¯×ãââÂ{g““§OŸfæÌ™ìÛ·‡zˆvíÚݹuHüåšLzùcÌü”ýç'œw7»Ú-š¯ñ8‰[ƒù‚ße—Øgº`ŸùšZ¼û8l½#ÑšL899I «ÄýAÂýkŠÈj¹zõjžyæ|||pwwÇÃÝþú .c1¸“9}ú4¡î¡8¬w^—“+ÜÝá©§àZ²«JHÜaœ:uŠþýû_ù :uDÕ Ë3é€?‘”ÕûŒ‹ 莎ŽLš4‰×_ââb¼¼¼,®ööötéÒ…—_~™ˆˆˆ[ïêu+Ù¾œþ±Ô|­F~å'ˆœ€àÐØŠˆ \+?ˆÌ¬ŠÊ}*„b”^y¼'ÐŒ‹cML@p¦j€YzåèûÆ›gUžs©”2DvÌR„¿þýêþ°1†r °ê'ÿ³ªrÀý´;æî1­µÀ í@æÈårIa•¸?Hz^ƒ‡‡Ý»w?ï®VQÏ='â$$î2Ìf3‡"Ê%d‰À+\·nmwWBâ†ÈÏϧ°°ÐR:ó"öì€ðñ¹xá1 QÊì:+JÜý\¤ò˜Íf²²²Øµk§OŸÆÓÓ“>}úàââ‚§§'ƒï’1Ú¼<<ÂÃ…Ø#ê2åë€`„’Ó¡l:"2NVÅ‹8öˆÕü£ˆ”ÙñÅóÉʶ‚_€¨ÊóG!\x¼=b%hb…T¤"”߆@rå9Ÿ#’*ÔG<ž‰ˆÑê ô¯¼T9¦òÊk´¾`†Üí2æ#''x÷]pv®í®JHÜ©©©øûû_ºÂˆZ-j ÏAx2þ)™©„…K¾]\ª›±<<<(..®í¾^;F#îŸÁáA[áN{熒¸.Ì@¦éNbj*6668K‹ĽŽá <:t^aQÂæ£D «„Ä]HEE¾{}QR O¦ 1™@§)Ù’Ä]͉' «¾17WdÎÈ–Ô8`8’²*Qkò¿cK×\ŽŒ 2uéœò=+Mx‰{ 3à ƒAõHII!00ð’í%$î) âÙÕ"ÏBii)õ«êOÊdàí žžµÝK ‰&'>‡ÔòTl±½X2KO‡ùó…7„Ä]Ì©S§ˆˆøkÞ¦MbnË` "yéÕ¼%î;.™Z´°°³gÏZþ.**B§ÓUÛÂëääTÛ÷P°Ìd»“È­oº9 ‰;  ÓCE xJBºÄý@>"y°mÛ6ºv튵µµ°ª¶i]»Öv%$n ‡Ó8Û:_:Ä’%âçÝf<¸€ŠŠ Nž<ÉSO=U}Çñã0|8ÄY‹ !µÝS‰;‘K*¬k×®åŸþ±ü]XXHII ¯½öZµãž{î9XÛ÷P`¶çh´5-ílk»7·°3”Idde]Û=’¸ý$Š< 111<÷ÜsÂEòÀø¯ð#!qr®äÍ+.ÞQ\ Â'ŸH «Ä]͉'P©Tøøü'kÒ;ï@™ÌÞG$û”øÕV¥RI¯^½¾¦“CBnlD«Õ’””DII !!!8:žÏþc2™ÈÈÈ ##'''Q(®#õP .ºKuKHÔ©©©¤§§ãáᯯ¯eFÎ;Gqq1ÞÞÞxxx\»[¯ È<„ÑÖ†ÂÂBüü$¿‰ÚÁ`0’’BNNþþþxxxXÂGt:§NÂl6ãë닳³ó‡–œŽn“žƒN§‰ÆbcE’¥€€Ú ‰{”òòr’““)))!44ô|Vj„¬’žžNff&ÎÎÎ\Ÿ¬òd¿Éˆ|5òâöö°`XߊÕ)..æÜ¹sÈd2êÕ«WMn6œ={–’’’ë—U.ÁhÕªªª\f3TT€Â¦#*XH• $.ÃE kçÎéܹ3 ^Èz½£Ñ€B¡@­VßTLkQQ3fÌàÈ‘#”——ÄÈ‘# F&“±iÓ&.\HAA†Aƒ1`À€kW>wÿPœ(ÅöIÔ z½žM›6ñÃ?PXXˆ <òƒF¯×ó믿²råJ***puuåé§Ÿ¶då¾*f8ëCEYëWÜ}ñå÷Z­–~ø 6PZZŠƒƒ#GŽ$**ŠÂÂB¾ùæ¶oߎL&Ã××—‘#GzcËGÔ¼FÔ_µµµß BU«„Ä-¦  €™3gräÈ´Z-ÁÁÁŒ1‚:uê “ÉØ°a?þø#ØØØ0xð`ú÷ïZ}c桲„2*¬ÿca5…P/)«·ãÇóõ×_sæÌÌf3-Z´àÕW_ÅÕÕ­Vk‘Uôz=®®®<ûì³tèÐᆯwæÌ™êçÀW_ÁCoɤÒÂWà’Éd"11‘ü‘·ß~›aÆñä“Oòî»ïòóÏ?“––vC3 |÷Ýw¤¤¤0kÖ,-Z„µµ5sçÎE«Õ’••Å'Ÿ|BË–-Y¾|9/½ôŸþ9‡¾¶ hT þr™ß'Q+9r„Y³fñì³Ï²råJ† ‚ 8yò$à믿æå—_fÙ²e4kÖŒ>úˆ‚‚‚kk¼@Û`÷ÃÛÛ[ÄñIHÔ &“‰¿þú‹¿ÿþ›>ø€_ý•¶mÛ2sæL222X¾|9[¶laÆŒ|ÿý÷h4>ýôSJKKoì‚ Òó=..Ž¡°ÚØë“„Ä-F¯×³`ÁÒÓÓ™={6?ýô …‚/¿üNGff&S§N¥M›6,_¾œçŸž9sæ{Ã×Lפ£uÔV߸f ìÞ]ÛÃ!q¢Óé˜1cööö,^¼˜Ï>ûŒ}ûö±råJbbb˜7o¯½öË–-#22òúd•ÿ ×ëIKK£î…Y®W®„ ü`£¹8;¶„Ä\¤°šÍf¶mÛÆˆ#X°`………4kÖŒÈÈH²³³ùòË/yûí·‰‹‹Ã|ë’““Ù²e ǧN:¸ººòÒK/†Édbß¾}8991`À4 mÛ¶%<<œ;v\Û”Àë¥ Ïe_jjm­Ä}ÊßÿMXX;vÄÊÊŠ>}úðÄO Ó騱cMš4¡M›6h4ú÷ï­­-ûöí»¶ÆmÌðDFùùù’…U¢Æ)++ãÏ?ÿ¤gÏž4iÒ{{{† F‡Ðétlß¾ž={Ž››>ú(ÉÉÉ%í»&ŒÀ,‰hŽ?NDD²~€˜˜Ú ‰{”ääd¶oßÎSO=EPPnnn¼òÊ+Ô­[“ÉÄÞ½{qss£_¿~Y¥~ýúìܹóÆ.x ¬ì¬P:]àô¦×ÃH‹2·…››ËO<ƒƒAAA¼ýöÛ–½;vЬY3Z·nF£±Èå17øÞ---Å`0œ,/‡ýû¡E_ð\k{D$ît.RXÏœ9ÃôéÓqvvæ›o¾áÇäý÷ßgܸq,Z´ˆO?ý…BÁ‡~HJJÊu]¬*¦¯AƒÄÄİaÃxñűµµåøñ㸸¸àåå€Z­¦aÆ׾j©¼åг'h4ØK/z‰Zàßÿ%**Š„„Ö­[ǹsçxì±ÇˆŒŒ$>>žºuë¢Ñ ÜÓÓoooâââ®­q{-œ[Œ1?nü5Iyy9±±±4kÖŒøøxÖ­[Gnn.¯¼ò >>>=z”Æ[Ž C§Ó‘””tý3!2F‹X«øøxƒ‚`ãFêKÜ&RRRÈÌÌ$<<œ}ûö±aÜœœxñű±±áرc¸ººZdkkkÂÃÃoÜš)Ö)8:ÏçAl,ØÙÁK€HHÜbccqppÀÑÑ‘­[·²cÇ¢££4hñññÔ«WÏâÅååå…§§'ñññ7t½’’¬¬¬ÎË,*¼3 ŽÔ…®\&¬„ÄyªM½^ÏŠ+°±±a„ øúúV³à( Z´hÁĉyã7زe O<ñÄ5ÇŠ–——S\\ÌäÉ“ÉÍÍÅ`0PQQÁ«¯¾J§N(..¶ÄÉV]ÏÉɉ¬¬¬+¶›““êU«:t(ŽhûõÃzíZIa½ÑëõìØ±ƒíÛ·Ó»wÍFäææ²qãFÖ­[‡B¡ °°æÍ›3jÔ(ŠŠŠ°²²²<3›«ÎñÄÄD~ýõWºGGã¼q#¦öí«¿ü%î;JKKY»v-‡¦uëÖ5v]£ÑHaa!ß}÷EEE€ˆ÷{â‰'èׯÅÅÅ–''' ƒåØË±oß>¬¬¬èÕ«×ùy­Öí„€åëë‹{j*‰Ä=ÏÒ¥KÉÌ̬Ñk–••QTTÄG}D^^ƒ½^Ïk¯½FÇŽ)..F©TZ’Ç\‹¬b6›Ù³gAAA´iÓ¦Ú¾ŠÃ$»&WK@Iýú0nHïø{šüü|–.]Š«kÍš HHHàƒ> ¢¢‚òòrlll3f áááÉ*666h4²³³/ÛfEEýõ®®®å,(//ÇÊÊê|b2¥œ!x´Fo]¢†9~ü8kÖ¬¡E‹7ÕN5M³¬¬ŒcÇŽÑ¡Cüüü.én(“ɨ[·.Íš5cïÞ½ètºëº ÙlÆÇLJÏ>ûŒyóæÍ_|qEaÆd2]±M777  ^ö2‰éé †[>èw*•Š.]ºÐ¹sçóéjÜÜ\ÆÇ?üÀ[o½ÅîݻٲeËe¿š{}`` ƒÆY¡kkô*9995~_w¶¶¶ 0€&MšÜTvÒ›aúôé,X°€§žzŠï¾ûŽ'N\ò8³Ù|Õ9Mß¾}«/Âä#bXÅŠ£Fש/½µtÏ5Ë£>zÍ• n%f³???>ÿüsæÍ›G³fÍøüóÏ)..¾ì9W’Ud2­ZµºHY¥Ô›ÔØÚVŽmm¡†•‰šÇÙÙ™G}—šO[^^N‡˜?>sæÌA&“1þü+žs¥÷¸Z­¦wïÞ—L°W\\\]aýñG8^ Mï¿u‰¤~ýúôíÛ÷¦+·TSX+**ÈÊʺ¦lŽNNNY2_ …+++^}õU\\\pttdðàÁ$''SXXˆ••&“ÉÒ¦ÉdB«Õâááqíwtæ ê… ¿ÑŒ”7‰J¥bРA„‡‡£P(èܹ3aaaÄÆÆ¢V«1 –—¾^¯G¯×ãîî~m;:Â+¯€JE@@@5K–„DM “ÉP*•<ÿüóøùù¡Ñhxä‘G0 $%%aee…^¯·_^^ŽZ­®Väš)zA¹Y¸!GGGƒHåœ$n# …kkk^yåœqttdРA$%%Y,O7-«T‘éÚtÜBÜÎo;pöì©ía¸‡Q*•Ô«WÁƒ£V«ñööfÀ€ÄÅÅ¡×ë±¶¶¾HV1 ×.«ü‡¼¼<ÜÝÝÅ‚ä™3°n3ìRÃ3HîÀ×D5…U©TbooU÷Dþè666×U:ÆÑѱºË —Ë1˜L&ÂÂÂ(..¶XŽôz='Nœ N:×~Gyy¤ÄÄ`–JÚHÔÕþ–Ëå˜ÍfŒF# 6$)) ­VdƒÌÎÎ&33SÔ•¼¡ys***ÈËË“’.IÔ8*• oïêKâ …ÂòçÔ©S–}§OŸF©TÞ˜  BIi ƒ/½®5k¼„Ä âää„££ãE!QÎñÂÂBrss‘qõäÉ“×'«Ta†íÿµÄÃðÛop×K ‰›ÅÇÇ•Je™ã2™ ¹\nQR«d•*/ʬ¬,²²².’o®•ôôt<==…ΰ~=Ôë‰*)Ù’Ä5SM«³³³£yóæ¬^½šŒŒŒËž”’’®]»hÞ¼ùu•Õ ",,Œ9sæ’’Brr2 , 22777Ú´iCAA›6m¢¤¤„¸¸8bbbxðÁ¯ýŽÎ£ÀÖ§Zp¯èѣ˗/'>>žììlV¯^Í©S§èСÝ»wçСCÄÇÇS\\ÌæÍ›ÉÎΦG×u*ÁIŠa•¨ilmméСß|ó gÏž%==ùóçãììL£FèÞ½;ëÖ­#99™œœV®\‰¯¯oµDL×L6à%ÂU4 kÖÀʰ„Äí N:„††òÙgŸ‘ššJrr2óçϧI“&¸¸¸Ð¶m[rssÙ²e %%%ÄÆÆràÀúöí{ý;‡ÿ<|¾ÜGj*œ< ×Z›[BâhÕª999,]º”ììlNž<ÉÏ?ÿLçÎQ«ÕtíÚ•ýû÷säÈŠ‹‹Ù¸q#yyytïÞý†®—pÞ¡qc#YW%®™jSE¥RѳgOÖ­[ÇìÙ³1bÎÎÎ+ªÉd²ÔJµ±±¡K—.×eauuuå7Þ`ôèÑ>|³ÙŒL&c̘1ØÙÙáààÀO<Á¢E‹Ø´iÙÙÙôíÛ— \ûu°GÉÂ*QKôêÕ‹¸¸8Þ{ï=ÉÍÍ¥oß¾´hÑ“ÉD—.]˜2e ...deeñì³Ï^·»dYY7 !q½XYYñôÓO3~üxFމZ­¦  €wÞy‡:uêàèèÈ¡C‡xçw°¶¶¦°°÷Þ{ïúÝ×Ë€, ô2ñ€IDATdÇdc¥Vcuæ ^ÛC qãææÆk¯½Æ{ï½Ç¡C‡0™LÈårÆŒƒ­­-ÿgï¾Ã£¨öŽ·¥÷^!@B!@½Š4é¨HAE¯ ÅŽð*W, *X_»*¢¢REªôPH'½'›lŸ÷1 +-HȆp>Ï“'ÉÌîì9;ggÏïÌ)îîîL™2…/¾ø‚ßÿ¢¢"ÆŒC»ví.ûµt^:އ§E‹òWWxðA±œpUµjÕŠ©S§òé§Ÿ²aôZ-!!!L›6 €.]ºpà 7ðßÿþ×ZW¹çž{þõd¦xyyÉÿôé_blá2œÓ¶Ñ©S'ž{î9.\È­·ÞJ÷îÝñññA’$ Ù»w/¾¾¾<ûì³´iÓæ²_0..Žï¿ÿžC‡oS‘™2e ýû÷'99ÙÚÊyYüýÉ1EE^°///^yåNœ8AVVíÛ·'44ÔºÿÙgŸåèÑ£äååѹsçÕU2==]Ü]ì&<<œ?ü£GRYYIÇŽñþ{™™ÀÀ@/^ÌÐëõÄÇÇÿ»JNð÷rÚiii´ôñAÕ£ü›n—‚p™:wîÌwß}Ç¡C‡P*•ÄÇÇÛô(›6m7Üp'Nœ uëÖÿª>`þÆL¸Wø™:‹— `ïì ׉'2lØ0öíÛ‡]ºt±îsuuå¹çžãÈ‘#äç矟߿~­ââb #p†¼@SÍ—á¼5ÞºY‚úé'öìÙÃþýûQ(qûí·3vìX› øårqq9w¦¼³„‡‡þïžœŒT[K˶m÷„ˆŽŽ&::ú¼û:tè@‡+X_ï|ã¡1i4âãã/¸¯GWö•€—üg^^-¢£áæ›ímá:âêêJŸ>}.¸¿E‹gîŒþK••xDþÝÃÆh„ÂBÑKLh^^^ <ø‚ûãâ∋‹»¢×¨©©A«ÕÊ]‚.÷!ðX x^Ña…ëÌyÖºÙÃfÏž}Á'nݺ•ðððݪxÕ¼ñ… ºvµwJáª)((°®W,Í’ðw¬–F¿ˆ0›År6B³RìZŒÅÿïåp„Ï?‡Å‹A\ß…f";;oooÍf8|L3¡¿½S%\kþuÞÛo¿ÍŽ;ì~[F#TTPñ÷lÇ‚Ð\UTTàââbïdÂÕ“ÊŒ9B»  ¦ÆÞ©„†sòŽæ¡ôú»*¶c $‚U¡YÉÉÉ‘»—”@\/˜ì*áZó¯VNg³Ö^“P]):Rùï» Â5Àb±œ™À@š#7 ½<öɳ¬ GGë ͉JÝJiÑòïnÅ‹1??ßÞi?/£ÑˆJ¥«Ð¬ ÜÜÜì A¸zT 9KXNŸ&¦¨ÈÞ©„†×ö­ÛÇï1°?ôS§ Í‹N§C£ÑàTPþ0R {§J¸Ù¬J¥’€€jkk/ùÄV­Z]pI{²X,¸»»‹€Uh¶êzˆ.ÁB³V FɈ&5•H1vUhn,Àw 2©ä ô ¸Â5]¡©Ñëõ˜L&ú„?=!JD«Â¿cS prrbòäɨÕjœ¯ÑÙõz=•••(âC!4O%%% {'C®®L0;™!7Ï#ìAhXhûj©È«ÀÉÉ ž}D¯¡™ÑétH’„ƒCH®`ï ×*›ÛZ­–—^z‰ï¿ÿÞæAÛ·o§°°ÐÞi­‹ÅB@@€˜tIh¶$I¢U«VöN† \=Z L&;:R3`€½S$ «¸8ü½žv›6 z† ÍŒÉdÂÁ`@³m/´Äÿdsu4›ÍäææRQQaó wß}—¤¤${§µ^ĤKBs—ŸŸ/î° Í[&…‰Sj5ŠÐP{§HV +„‡…ÂöíöN \•••øææâ°n+Ä"Vá_;'ª“$éœÕÖÖ6ÙYÿÉh4ˆ.ÁB³e4ñôô´w2áêQƒ¡8?ŸÎ¸‹‚…æF™>™(*ŠáÍ7íA¸*NŸ>sn.˜;…Én3YX,vìØÁŸþÉœ9s¬Û X¿~=‰‰‰´lÙ’±cÇÒ¢E‹zß1Õét£“tM@UU¯½ö·ß~;111X,233YµjùùùtîÜ™¡C‡PÿF£QÌ,4)))|øá‡¼òÊ+8::b2™8rä«W¯Æl6Ó£G „ëå ;ÆCf3J‹ÅÞÙ®S‹…íÛ·³sçNžyæëöüü|Ö¯_Ï‘#Gˆˆˆ`ìØ±„‡‡×¿w—J(!ÄÍ \ÂíMá:f4Y½z5z½ž©S§r¹ÏÈÈ`ÕªUÏСCñ÷÷¿¬c›Ífbb ]'ègïœ ×2»õ›-++ã­·Þbû?ºÂ,X°€uëÖlj'˜?>ÅÅÅõ>nff&*•JÜaìÎl6³jÕ*¾ýö[ÊËË(..æ™gž!==ØØXÖ¬YÛ—Ùº^VV†N§³wö£ÑÈûï¿Ïºuë°üT&&&òüóÏ̲eËøá‡.ïÀ¡@{°ìÝ‹9 D?2Á>JJJx뭷رc‡Íö—_~™Ÿþ™¸¸8’’’˜?>%%%õ?p Ô¤Ö rq…aÃìMá:väÈ–-[FJJŠu[QQÏ<ó ™™™ÄÆÆ²jÕ*/^|ÙÇNOOG9r$¤¶¶cÄ!4ç܆T*• JKK­ÛÌf3ÕÕÕ6Û\\\äÙí.“V«åwÞ!??ߦkã®]»HNNfÁ‚téÒ…±cÇ2eÊ6lØÀ”)Sêul±Ü‡Ð$lÙ²…µk×Úlûé§Ÿ0Ì›7???:tèÀã?Nbb"ë¹`¼Åb¡]»vöΞp3|ñÅ$&&Z·™Íf¾úê+¢¢¢xñÅ­K¥-_¾œТ¾Ëv¬î…Ò‚*Ft€ìá캊¯¯¯uûÎ;IIIaáÂ…tîܙѣGsÇw°iÓ&&MšT¿ƒ›!Ã=¿¸ö0|¸½³*\§ÊÊÊX´h•••6Û×­[‡ÙlfþüùøøøÐ¾}{ž~úiŽ9B\\\½¯Q*i‘çN„ˆI¿wN{‡B¡à×_eÖ¬YÖŸÜÜ\>úè#›m³fÍbóæÍ—ý‚’$±eË2227nœÍ¾””‰ŒŒD¡PàææF—.]8tèP½_RR‚£££½ßWá:WUUÅ_|ÁäÉ“m¶'%%Ñ©S'<==Q(DDDnSé¿”’’ôz½½³(\çRRRøõ×_­]È@nLINN¦OŸ>¨Õj”J% èõz²²²êw` ()Lb­Ñˆ¦ŸèG&4>I’Ø´i999Œ3Æf߉' ¡uëÖ( ÜÝ݉¿¬º ‡@—¬£Ex˜¼« 42ƒÁÀ—_~IëÖ­Ïi0?~ü8;wÆÃÃ…BA«V­ áÈ‘#—õú´4:&‚IÅ\¸6«““&L`„ 0ÀúóÀ0vìX›m ,,ì²_0##ƒO?ý”x›}éé鸸¸Xïº:88ErròEY]]Mbb"µµµ”––þ«»¾Bób6›III!%%¥Ñ' Ójµ,Z´ˆ¸¸8FücýÈÔÔTpø»‹£¿¿?—,㥥¥8p€ššt:Mk¿p}2 $&&rúôikwÜÆRTTÄÛo¿Í„ ˆŽŽ¶n—$‰S§NÙ|7´iÓ½^OnnîE™™™ÉÑ£G1—›! ª•Õ”ÖÔܲeã¾±B“²ÿþËÔPN:ÅçŸ~ÞºJZZ®®®ÖºŠ££#‘‘‘½ŽK’DFFiiiòdÔfÐâ­·à½×„ëGMM û÷罹¦¦Ñ_{Æ ìܹ“Ç{ìœ9RSS D£Ñ€ŸŸ'Nœ¸àñL&ÇŽ£¨¨ÈºÍ¯ ÏÕjЈٖ®W=z“ÉtEDZéìääÄèÑ£¯Z¢+**Xºt)C† ¡S§Nõn©¹Ô*• 777T*jµ«–áÚ P(pqqÁÅÅ¥QÇ3K’ÄÖ­[IJJâí·ß¶¦—R7»õ…h4ÜÝÝQ*•ÔÖÖ^öÄBóS× ÅÑѱQ˸Á`à믿ÆËË‹#FpìØ±K>Çb±\òËÊÙÙ777Õ Ð€!;›!ÿXbM¸þxxxÔû:ÚPÊËËY¶lÆ £cÇŽ8p ^Ï»X]E¡Pàì쌳³3Rk‰€hp«®Qg¹n)•J<<<u^ I’ÈÏÏç믿fÚ´ixyyÕû¹««Ô}'ýyu*)Ç0,§ØFËžÐÄ888ÈßíWXOiÔ!Ð?üðƒµ›Á‘#GÈÉÉA§Ó±oß¾sÖ~=Û¥î˜:;;ÓºukêßíLhÖ”J%aaa„……5êš¼§OŸæý÷ß§_¿~deeY+:)))¤¥¥]ðNإʸ»»;QQQ¨T*NŸ>-&Ðh4´nÝ??¿F-àǤwïÞ$%%Y[Ü|ø¢CŽ.–N•JEË–-mæ¦ÙjñA©'º_Ǽ½½‰ˆˆ@¥º²»ìç]ûE§ÓqìØ1òòò5jË—/çûï¿·yŒF£aÚ´içty¼˜œœ$Iâõ×_äSËÊÊøßÿþÇœ9s&33­V‹««+F£‘ìììúOÔ¼Šî’‚½Ôu{ܸq#›7o¶®k¼|ùrŠ‹‹ñ÷÷§¼¼“É„Z­¦¼¼œ²²2bcë×ü(I¾¾¾—·Dˆ 4 ¬¬,Ôj5Ÿþ9 …­V Àë¯¿Îøñ㠱間“ƒZ­>§[åéPÔÖ¢å\°ƒœœÌf³µ®RTTDyy9ÿûßÿxþùç !77×ZW1 —]WÑ·Ó“r‚yæL{gW¸ÎÔÖÖRVVÆéÓ§yíµ×ùº®R©xë­·X°`aaa”••Yë*eee”——Ó¹sçz¿NII Åå¢ÝÀÙÞ¹®uç¬&“‰wß}—åË—3lØ0FEAA%%% >œÄÄDŽ9¤I“ˆ‰‰¹¬{à˜>}ºõÿï¾ûŽõë×óÖ[oY»8®]»–ŒŒ bccÑëõìÛ· &Ôû5ÊÊÊDe^°›Ž;òþûï[ï¤F†Î<@Ÿ>}øå—_øé§Ÿ¨®®ÆËË‹œœ233™={v½Žo6›)((¸â–*Aø·†N¯^½¬ÿ'&&2{öl^{í5üüüHLLdÇŽÖ‰j:„³³3‘‘‘õ{\ ²#8Ü®CìaáºóðÃ3cÆ ëÿ+V¬`Ó¦MÖºŠÉdâÇ$++‹˜˜t:àöÛo¯÷k˜7›q ôC)†wÌÛÛ›yóæÙtaŸ;w.žžž<ñÄøûûÓ³gOÖ¯_OMM dgg“““C·nÝêý:µee PJÐSËWÈ&`•$‰ßÿuëÖ1sæLn»í6ë¾   üq***øê«¯8|øðewaðõõµ¹ûééé‰F£!<\^4»cÇŽ´nÝš%K–0~üxvìØ³³3ýû÷¯÷k”””4úxA¨ãääDhh¨õÿº/|}}8p ?ýôï¼óݺuãûï¿'&&æ²î°j41¶`7îî»[ÿ¯ë†““ãÆãÕW_åƒ>ÀÇLJ•+W2xðàúOÒ§Ü!O’Pµmkïì סKÕU:wîLDDo½õ·Þz+Û·oÇÕÕ•~õѺª³*ðð>Žº‘'L•JuÎòusÔÕ_ÈÏ?ÿÌ;ï¼CBBß~û-íÛ·§}ûöõ~Sv6·šÝ¡# ÚØ…+d3¸¯¶¶– 6ÏwÞyN.µZ¯¯/3fÌÀb±ð믿^Ñ씽zõâ?ÿùõFóÏ>K»víX¾|9jµš¹sçÚ—âêêJPP½ßWAä/†^xV­ZÊܹsÑëõ¬\¹’„„ž{î¹zß1•$ÉÚEGš‚–-[ò / ÑhP(tïÞÇœãdziÓ&ÆÇ´iÓê?–<!Oº$å…¦ OŸ>Üwß}Öÿ5 Ï=÷mÛ¶eùòå8::2wî\ëøÔK*u˜ž›²Òq«ÐL˜0‘#GZÿ cîܹhµZV®\I=˜3gÎeõîR¡«m?É·Ð ÙÔzu:ÙÙÙL˜0ÁæîiPPmÚ´±þïææFLL »víbâĉ¸¸¸ü«?_kMhh(<ò&“ •JeR»>²³³EE^hRT*wÜq‡õ…BAûöí™;w.f³FsY_‹…ªªªFHJ.&00ЦŒ«T*úõëG=$ ‡Ë+¯­å_‘®&ò¬!$‚`/±±±çô‚ cÖ¬YÖÄ˪{T‚º} µGLX”JqóI°»Øü¯T*‰eÞ¼yX,–Ë®«h- ÁnÐÉÞ¹šƒs®°‹åœB9zôh† f³M©T¢Óé®Êú—}ñÿ›ŸŸ?þøÕ~ÏáŠi4šËjŒ9›¯¯ï¿n$„Æ P(®¸ÛzÑ©Sø‰r.4aÿ¶®BèNBFD=T*° MÖ• ±Krp ÀÒ‰Y¡²iöÖh4øûû“˜˜ˆÙl¶nwuuÅÛÛÛú¿Ñh$55•€€€&uGÓÙÙ™Ž;Ú;‚pÕ˜L&rrrĤKB³§usC:kyAh6| t¤’S½z˜@hŽ$ ]u5Þ%Þ æ€MÀêêêJïÞ½Ùµk‡² Zë ~ûí7’““éÓ§˜üE‘$I¸¸¸4êšm‚`›ãâ¨ëS ÍÑ>¨=RMeY™½S"W‡Á@Û?w`é™ öNŒÐØÜU*•Œ3†;vðÐCq×]wѵkW‚ƒƒ1dee±mÛ6Ö¬YÀ2dH£.X/×»’’ÜÝÝEC‘ÐìéÜÜpõð°w2¡á†°S‡¸­g‹&ÕKMŠd0xÌ€§w¤˜!Xhç\)½½½yñÅùæ›oX¹r%ßÿ=‹Å‚^¯`òäÉLš4 777{§_®+îîîLž<ÙÞÉ„«kçNÜD×w¡¹êUíÂEÓM4ú Í’d6“_XˆÓ`1A¤Ð0ÎÛ´ÆSO=Åĉ9~ü8ééé( ZµjEtt´u‰AWPPX¶Ihþví"R’læN„fc8(_˦Öõ{§D® ³ƒ†Îãpp×p¡a\´/JË–-iÙ²¥½Ó(‚ \ONž$Åd]ß…fk×ðá¢AFh¶ ’D®Á‹®b¦w¡aˆ{õ‚ B“RÒ·/%¸»»Û;)‚pUœÒj1‹îÀB3¥8}¯2-ªbX‡Ð0®›Ñþ&dgÛoÂCAË–àì µµ–àã2UU55 ÕÂPVƒ›¸ºBf&¤¦Bd$´j..`6CQèõàï/¿¦BååPQ!ÿ_P Ïlïäàé :ü£ÑÈwvƒáÌ6µúÌlø’¥¥òÿyyòã}|ÀË ”W¡I¢¦æLššI’ÏiM|~òòpu½~Úeôz¹|úøØ;%‚ðïåwîŒóž=öN† \%% øùùÙ;%‚pU¨×¬m%Úp-žˆåÉ„+w]¬F#,[&z¦M•C†@N= !!PY ãÇËèo¿É_Q‘üx{ËÁ¨‡Cq1Á®]°e ôî ÇŽÉA\Zš|Ü„8rNž„¨(9`-(ƒÙM›äÇÞtäçCx8<(?7$áðaèÖ þøCNÓ!pâtê$¿nY™œžŽá‡àÎ;á×_å@¹S'ÈÍwwpp€ýûå€xüx9ØîÑÖ­“ÝŽ¡E 8uJþ½~½ü¾-ïÆå@þäI9­;ÃÖ­póͰv­üØ>}äýÝ»ËS~¾”ÇÆÂöíÐ¥‹¼ÍÑQÞVS#§K’ä@\£°0¹QÁÉ RRäí-ZÈA·V+ç5/O~ßÛ·—ƒfooù}°Xäc&&Ê?ÑÑòo‹Å›-Ìÿ®à\ƒ¾þvì€çž“Ë”XD¸egglïdÂÕ±iÁ»w£=ÚÞ)„«ãøI|J‡áll‚w6„«"5UŽUþüS¾Ièã#×ëÓÒ ¦Æoï+«6û€µ°,›‡–ßÀÚZ9ÀÛ¼f΄©Så€gÍ9°íÓG;w–ƒ¡Œ 9H6M¾³©PÈ? \·Ü"ßI­»{ r`zú´Ȇ…Ùž-®wß-o«»ªPÈ $ù_’äß>(oS*åmJ%Œ+ËÙYàî¼S*Ç?“÷êj()‘ƒ>‹Ž— SA¼íŽ;äãyzÊÏmÓFNÛ€àë+¿NÏžr xô¨hNš$ßž:UH#"ä×òñ‘óêâéér¬TÊlj‹“ƒÿòrùõäàU­–Ó•‘!×NNòÿááòOa¡ü` è*òæâb98NM•}ø°Ü($§áÖ[å@`Û¶œœš·ÂýûáË/aÆ 9/–ƒûÛn“/ÜÜä;ú{÷ÊQ£äs#I°zµÜ1`€ÜH0b„üÛb‘ **ä† wwùýws“Ïóúõrùøö[ù\µn-n åÏΡCòyìÑãLYÙ¸Q.‡žžry;rúö…Ÿ~??¹Çb‘?¯ÙÙg^7 @¾Þ|3ÔÝx —?Ÿu=JJäí11œ,7 åäÈy ’Óàä$¿ÎÉ“ryjÕJ.‹mÚÈû ùx&“\&á—_䲜 7¤´k'¿‡r:»t‘ó,—}T¶n•ß½^>–‹ „†ÊåõÆå÷"/On”JO—‚‚䆫à`y{F†ü;;[~ϼ½ås}ò¤|]9zTImm=z4£nWôÖ[øÜ|³½S"WÇéÓd8:%–mº*êÍäkêÅnõz¹®¦RÉß UUòïºú‰Nw¦W™¯ï¿KÁ —99Éõ/N>¾§§üz••ÔÖ6¯ê¸1¢‰ñ9DpÀ¡Ñ_¿¦Fþíârîö¢"9ðò’É7¬ŒFù\•—ËåáôiHJ’Ÿ— ×ýöõ•ËIa¡\_Ðëå¿äúoNŽ\WHJ’ë>>òy/,”Ï{NŽ|Ü®]aß>¹gæÑ£rý6 @®‹ïÙ#×¥¶l‘ó'ÏÇGþ?#CÎÏŒ°m›\GÿñG¹œ……ÉeÍb‘oàìÙ#§sð`ùÆW›6r½£²R®·µh!×a÷n¹®1~¼œÞ€€3uB½^~ŒN'×–ѹ³ü¾ôî}&VÉÈ?‹òçKÍ•ÙoôOˆ$IX,L&’$¡Ñhl–.$ ³ÙŒÉdB¥R¡V«/kÚwƒAþ­ÑÈ‚¯¿–+ÁžéBëì S¦Ø>O¥’+÷·Ýf»=<\.|r¡®±ÁÁòÏ?Õxçs¡îÈçÛîè(ð‹=ÆÓSþ©Ó¹³üûìçí|ók…†Ê¿£¢ÎM“¿¿üóOÿœDºî-ZœÙsæï¨·¶mÏÝ6tè…5ºDׇ$IF,Ë9å¸nŸ$I¨T*T*Õ¿^Ú@’ä Øÿ+7&´k'—ý¹så`03Snˆ9|Xnˆ)(ßûS§àÅaÜ8ù\þïr`¸k—|qÙ¾]²BCå Ÿ³³|Q:|Xnéß_ÆBCáž{ä´¸¹É´ª*ùËX­–Ê’ùN|¿~òk)—ww9˜öò’/ŽZ­Üµþ‡äò¦ÕÊå×ÑQ>v›6ò1ë>o|aÖhäÀ/#CÞ"çÛÍM¾ ;:ÊŸã°0ùËÉb‘·KҙǸ¹Éù®ûS©äcGFÊ3u_8;ÊiŠ‹“ß“É6uiS«å/€¿L ’¿ÈÜÜä ~]/ˆäk‚^/¿¦B!?¯¼\¾~hµr0~ü¸üEÖ¢…Àví*¿÷£FYظ±µºu£—q‹Åb-ÇjµÚ¦K’„áZ­F©TÖ¿Œ—–’ž›‹——W£çIh|’$—q‹Eþ[¥’ÿ×häßrE©ñÇz^ÕºJx8xz6LWI‹Eþ©­•¯3òµÄb9SÑT©äëXÝßæ¿;ÕU.ë~êÎ…£ã™Êéß+¢VŸyœV+7ÜI’ܨ\Z*_;OœÔ äkœ³³|½W*ϤíèQù±IIòñCCåë»Ñ(o¯Ú"_÷¼½åïžS§ÎÔ}L&¹Î²w¯üØ.]äŠ}«Vr¹ª*ùu££åÇöí+7¢‚ü˜-çgëV9€iÑBî!öÞ{r¥>ó#jµü=’˜(Lœ(ç³o_¹òîç'¿*•DX,ro¶“'!>^Îs—.ràP\,_÷ããå†w//t:'»”ñº2¬P(Ðh4(Ϫ4]I]Eóàãt¸é0ý•ÝU«+“f³|žM&ùïºå‹ë’[S#—ƒA>§¾¾ràÕ±£\ÿ/.–Ïó¾}rÝ&*JnXNL”ËÞO?Éß×ÑÑò9ŒŽ–ËjT”ü}"»¦F.sÕÕò÷ºÁ ŸKOOùõår™š*§aÛ6¹\´m+¿¢BÞ^]-FÚµ“Ÿçå%×QZ´ÿvq‘o„†ÊåÎÉI®3µk'\\ä´ÔÖÊå¼Kùuo¿]ÞW¨›Ír>¢£åÏW‹rýÅÕU~ŽÑ(ÏÙYÞîë ÷Ý'×÷äz‘‹‹œÖºàÞÝ]>®‡‡ü™©ûŒ_l¥ÓƒµTT¯¨,4zÀš——ÇgŸ}ÆáÇ1›ÍôíÛ—É“'ÀÉ“'ùæ›o8zô(áááÜqÇtêÔ©Þëñ½û®|ò;t FD„Ü¢ ÖæKmm-6l`ݺuäååÍÍ7ßLß¾}1›Í8p€/¾ø‚‚‚:uêĤI“hӦͿz­}ûä/ÀùóåÊAggùBÒ½û…Ÿ;p üepv#ÿرòïo<ÿsÆ«ÚÎn”è×ïâýûãÈŸÝói×Nþvé×®{½#ο¿[·úçãrÄÇŸ?ÿçËGûöçßvþêsöqÏ&1™hì¹[ÊÊÊøþûïÙ¶mUUUÄÅÅqçw‰^¯gÓ¦M|ûí·˜ÍfºwïΔ)Sð©ïÀjI"ÙÙ™ÎnáTU•üãë{¦!÷lz½\Éòó;swÊd:ÓëÅÃC¾vèõò÷l]¥ÉßÿLðTRr¦»»üüêjù§. Ú¿_.ÃÉÉgz=tè _×n½U\þû¦›`çN¹Ì;9É×–.c?i’ü{ÆŒKç©î†I×®çß?lØ™¿»t‘_¨>ӣǙ¿Ï®»ÏÙ7“ÂÃÏÿ˜ºÕCBοÿBÏ»º›Q—û¼«©QøÊÊJ-ZDFFwÝu‹…O>ù„ÂÂBžþyT*/½ô®®®<òÈ#lß¾—_~™7ß|³Þk¿Nœ(ô´4ùŽRlìÅ'R„†¶eË^}õUî¼óN:uêĪU«X°`¯¿þ:...Ì;—~ýú1a¾þúk,XÀûï¿_¯Ê‹$É-b55ò—öW_ɽ.Ö àBĬ¿a4ùòË/ùé§Ÿ˜1c~~~|óÍ7üïÿ㥗^"99™·ß~›‰'Ä'Ÿ|‚ÑhdÖ¬Yõ«ÌwïÎÉV­Û@wŸì¥.ÐhäŠ;È×Ý¡ªë^rk·N'qiiòggù3š‘!¾³²ä†×À@¹Âæç'¿ @>n‹òó:u’DZ›Ír«n¬¿J%Wò³²äÊôîÝr¥|Ó&9ð©»“ VË•ò#Gä;I={Ê•ÄîÝåR«•+àu½."#åÊd^ž\aÛ³G0’“Ï §éØQN[B‚ܾnøFZôê%O^اD8;Ë•=9øª¬Ô±o_Y£ž»ŠŠ -ZDNNÓ§OÇd2Yë*Ï=÷J¥’yóæáååÅ#<¶mÛxùå—Y´hQ½–4™L¸¸¸œwÒ%I’+àuw›œä€è‡ä÷uß>ùš¿y³0Ýs\úõ“ëzüõ—\)îÞ]"U*¹Ìõî-¿·mÛÊçÛÝýÌ~Ï¿««|êþzõ’Ëj]Ã]’Ë1fÌ¿;u¨ÿTPž$œ¯¯\¾À¶‡Ö¿ùÎù.RÝsgΔ_¨÷rz5¶üü|æÏŸOhh(O>ù$iii|ðÁhµZf̘Aff&óæÍcÀ€Lœ8‘/¿ü’W_}•¥K—Ö«®’ž•ÐÙ¥óy÷ rãÈ‘#ðÍ7òµoÀ¹ŒÖÍeb4Ê×¥>}äFfOÏ3Ðus X,ò5©®Aâì^užžçï9(\›5`ÍÈÈàÀ,^¼˜N7)ðŸÿü‡‡~˜'NPRRœ9sˆ‰‰!>>žiÓ¦±iÓ&î©ëwx ¡¡òO]ë† 4¶õë×sã72cÆ Ôj5:tà?ÿù7nÄÁÁ///xà<==ñññá‘GáàÁƒt¿Øíп òøÔÓ§åÖñçž;ÓíTƒV«eãÆÌ˜1ƒ‰'йsgFŒÁ±cÇX³f ÜuÖ-±÷ߟ1cÆy¡ñg1»¹¡Z\wXÍf¹ñhÿþ3c½óòäà14¾ûNôùçòãccÏtÑR*å ä;B[·ÊÁá±cò„ÐP9ˆuu•ƒN~lÝŒör…N¡ƒŽŽåÊ™««||³Ydê£TÊ•º#äÇÝ}·|¼›n’ïÕÍT¾auêsâÞ{Ï¿}útù÷wÖÿý ‚ÒR3'Oêõ¼¦§§søða/^LÇ¿£???zè!~øaŽ?Nyy9sçÎ%::šN:qçw²yóf›r!¹¹¹ Ôÿèú%Iòö… åJza¡|®ÓÓáùçå€ëÞ{ån·#FÀ³ÏÚö33Ä_è.ÐÙïm}ÝÅPhöìÙƒF£aΜ9„‡‡Ó»wot:«V­bÆŒ¬_¿xàÜÝÝñòòâÑGåСCt«G%Ç4Gœ=á B½=õÔSÖ¿%IbÓ¦Mäççsï½÷òçŸÒ¡Ck˺——ÞÞÞdÔÍt *Õ…ÇF BcðôôdÁ‚Öÿu:+W®$((ˆ–-[’››kÓÕ1,, £ÑHQQQ½Žo4 ºœÛ?WÀl–»ÔîÞ-·Òó|w²[7¹ëlp°Üâïç'ß‘ “ÇzyÉ GçkÙ?_`YŸÞÍŸ Ëÿû_ëÿuu•„„\\\ÈËËÃÉÉɦ®ÆþýûëuüÊÊJësëdeÉ]|P.Cu½ ÂÕ0ì}©óòòX·nýÿîk}úôiºtéb­«x{{ãååEfff½ŽïRégMÖYP 7üååÉ2×@¡‰±ËTD5558p€?üI’˜3gîPg2™.z¼ââbÖ¬YÔ)SlÖ=áÚf4ùóÏ?Ù¶mÇ·KNž<ÉÚµkùý÷ß™|ѲuµF’““ùä“O8qâsæÌ¹àäa‹sÝ´¤°wï^iݺ5RÝú^ @§“'{©­•'æ$y"={ä;’uã¦:u‚W_•ï:;ËÛ@n$:{èí¿]ÚBøwV¬XAAA]^[«ÕZë*J¥’gŸ}ö¢wþ/v—$‰Ý»wV«µÏ]P_|!ß5íÝÛ.Y줬¬Œ+Vàk§ Kyy9¿ÿþ;+V¬ **Š™us/àbeÜ`0°~ýz|}}ñÍó¥´c)‹Üµ}Ñ"y û“OÊ=M„ëGrr2?ýôS½z^L£¬µµµ¼ñÆìÚµ‹Q£F1vìØóv9Û¥º†ùùùÑ«W/¬ V†o¼•JuY316³ÙÌŽ;X´hþþþ,X°€¸¸¸sÆ+Íõ}{[¶lÉ„ 5BÓæêêʸqãP(õžE½¡˜L&¾ùæ–/_N¯^½xóÍ7i×®Fãù§­W«Õ8]¢–Ò­[7FűcǤòV[+Ïÿúërð9p Ü=74Tž„eæLùΩ˜”¯i›4iëÖ­kô×­©©á7Þ`÷îÝŒ=š±cÇZ»O^ÈÅê* …‚ž={Ò»wo6lØ`íEpú4Ì™O?}þeÛ„æÍÛÛ›I“&Õûî|CÊÌÌdñâÅdff2qâDFŒÇ%„^¬®âààÀðáÉŒŒÄ`4PYCA¼ð‚<<¢];q½½µk׎Q£FQQQqEÇiÔ€µ¢¢‚W^y…ªª*–.]JDD„ÍšOmÚ´áÔ©S”——ãåå…Á`àĉõžF[š‚_ý•%K–0{ölˆãYëFDGG“ŸŸÁ`ÀÁÁÂÂB è"f ®ƒ÷ߟíÛ·óÊ+¯Ð©S'kcŒB¡ **Ь¬,ë]ßÔÔTÔj5þ›Íç,Z­ö’=Î''Gž•6/OîÆûûïr7ÞÿþW[ªVËÝ,{ áÚS^^ÎË/¿Lmm-Ë–-£eË–6u•ÈÈH6oÞl­«èõzRRRê]WÉËËÃ`0 ×ÃãËÝËÛµ³ßºáÂõ'77—'žx‚ØØX^zé%ÜÝÝmÖXŽŽ¶–S (**¢ÇÙë±\Ä,ŸY<ø(ëÖÉ€µo/®½Â•iÔËcJJ ;wîäÑG%$$ƒÁ€N§C§Ó!I;w¦°°S§Na±X¬Ýqz‹>2Â5B’$¾ýö[n¸áú÷ï$IÖ2n4éÖ­‰‰‰TTT`±XÈÊÊ";;Û.]:áߨªªbÍš5ÜqÇÄÆÆb2™¬e !!;v`6›±X,8pWWW¢¢¢êu|½^_ïàä.¿+VÈË~üú«>žüü|ÒÓÓ±X,TWWsðàÁz×U, aaá=*O¼uë­"X$IlÞ¼€{ï½ôz=:ýßkmuëÖÇSUU…Åb!33“ÜÜ\zÖgö7 Z_¯¯ÕÕò²?âÚ+\©F½ÃzüøqŠŠŠsž¹6oÞL\\½{÷æ¿ÿý/C‡eß¾}´nÝš~u‹ BWTTDjj*»wïæóºµ,þv÷Ýw3sæL~ÿýwæÌ™C§Nذaƒ ª×ì©‚Ðdffrúôiž|òIž|òI›}K–,aòäÉ<ÿüóÌ™3ooo¶lÙÂ=÷ÜSªªªlZúÿÉd’—~É͕烙—ËcTï»O^oT®ÔñãÇ),,|˜2xð`» F„ËåááÁ;ï¼sÞ±|ÁÁÁxyy1þ|Ö­[GNN÷ß½[,¡)hݺõ91u¢¢¢ðööæå—_æçŸF§ÓñüóÏ×k„:ƒá‚wcËÊ䉑ºv•ƒUI’—ÿhÝZŒÎСCiß¾ýy÷ÕMz÷Øc±iÓ&4hƒƧžÓú–——c0¸r×]bïÜ ×Fý÷ÞË-·ÜrÎ>‡¿[O|||¬u•Ó§OóÀ\V]%88”;AŒvJ£¬¡¡¡—œ´ÀËË‹[o½•[o½Õ®oŒ üNNN$$$\ô1ÁÁÁ—œ‰Oš*//¯KV\ÚµkG»¹Pä¸qã.¸ïÀhÕJó'îJ WKXXØ%'ƒôööfüøñŒ?þ²ïáÀ?¶fÌÑÐ"4>•JETTÔE‡i( BBB¸ï¾ûþÕk””È3±Ï™cïÜ Í…]–µA„KÉË£Q^ïtófy½ÔùóE°*\ÛÂÂî`Ø0W.ÐáL®yþ)¯?}‰I‡¡ÞDÀ*‚ 49ë×Ãñãr7à°0زæÎ•×H„kYëÖ^  î® ÍWr2Œ#ÏÎ. A%A¡ÉÐjåY·o—ï¦úú‚Ù &€——½S'W®{w{§@®®‡‚K,//—E¬‚ B“‘™ iiòäJöN ‚p¹DW`¡¡‰€UAh2Úµƒyó@£±wJAAh DÀ*‚ 4J¥ü#‚ ‚ ª‚ ‚ ‚ B“$VAAA¡I« ‚ ‚ ‚Ð$‰€UAAAh’DÀ*‚ ‚ ‚ 4I"`AAAš¤&·¬ÙlæÄ‰œ8q‚ÐÐPâããшù„fÄh4²wï^ŠŠŠh×®‘‘‘¨T*{'KŒV«eÇŽ˜Íf:tè@XX …ÂÞÉ„c6›INN&%%…°°0:wî,ê*B³b4ù믿(..&&&†6mÚˆºŠ`7M.`]¶lëׯ',,Œ¢¢":wîÌc=†‡‡‡½“&W¬²²’ pâÄ üýýùè£3f 3gδwÒ¡AdddðÒK/¡ÕjquueéÒ¥<ñÄÜpà öNš 4˜wß}—ßÿÐÐPŠŠŠˆç±ÇÃÝÝÝÞI„+VQQÁ‚ HII±ÖUÆÇ=÷Ücï¤ ×©&Õ%8--~ø©S§²téRæÎËo¿ýÆþýûí4Ah»víb×®]¼ð ,]º”Ûo¿/¿ü’üü|{'M®˜Åbá‡~ ¼¼œ·Þz‹·ß~›îÝ»óÙgŸQ^^nïä BƒHKKcõêÕÜyç,]º”矞_ý•ƒÚ;i‚Ð vîÜÉîÝ»™;w.K—.eâĉ¢®"ØU“ X÷íÛGHHC† A£ÑCŸ>}زe‹½“& bÇŽôéÓ‡ØØX4 7Þx#¡¡¡ìرÃÞI„+f±Xؾ};7ß|3ÁÁÁ¸¹¹1aŠ‹‹III±wò¡Aüõ×_„……1hÐ 4 ±±±ôêÕKÔU„fcûöíôëט˜4 ƒ&((ˆ]»vÙ;iÂuªIu >uê®®®x{{ Ñhhݺ5üñÇEŸ'Iƒ£ÑØ,ÇI%&&âççGHHˆ½“rU”——“˜˜Hÿþý옒$!IF£ÑÞÙ³‘’’BŸ>}¬c|||ðõõ½deÞb± ×ëQ*•ͲŒÿþûï <¥²Iµ¡5˜¼¼>>¤¦¦^4/F£±ÙÖÅóóóÉÌ̤GöNÊU¡ÕjÙ³g7ÜpCƒ^£, F£ñŠë)M*`­«× êV*•8;;SVVvÁç( jjjøðÉ‹‹³~¸š“ÌÌLÜÝÝñññ±wR® ­VKffæEÏóå²X,œ>}š¼¼<¦L™bï,Zét:Ôjµõbààà€ƒƒÃE»Kj4òòòxóÍ7‰ˆˆÀÑÑÑÞÙhp‡¢¦¦¦Y~É”••QRRBnnnƒÓd2qêÔ)jkk8p ½³h¥×ëm&ŸqvvÆd2¡Õj/øöìÙCVVͲBðàAt:½“qÕäää R©8~üxƒ÷ÀMn\è¿©«€ÜͲ²²’àà`{g¡ÁFRRR¨¨¨°wR®ŠºÆ¸S§N5hyÔét>><ôÐCH’„³³³½“{U\ehð喝¸¸kfÒÅ‹_WWWžxâ Ôju³lXèÓ§O³.ã½zõjðº˜Åb¡[·nØ;{õr±ëxLL <ðŽŽŽ¨Õ×DxqY®V]µ)éß¿ƒçÏh42pàÀ+®‹7©åææ†ÙlÆh4¢Ñh0›Í”——_´5R¡PàëëÛ ]4ájñðð@¯×c±XP*•ÔÖÖR[[K«V­.ø…BAhh¨½“.õâîîNmm­õÿŠŠ ¬Ý'ÏG©TÒºuk{']êÅÍÍÂÂB›ºJEEÅEë**•ŠÈÈH{']êå|uNGÛ¶m/øWW× ušT3A||<%%%œ>}oO>|˜:Ø;i‚Ð ºuëFRR555À™±±±±öNš \1¥RIBB‚ÍÌîGÅÁÁ°°0{'OD—.](**²vñ×ét$&&ŠºŠÐltëÖãÇ[OŸ>Mnn®¨«vÓ¤Ö„„L&«W¯¦¸¸˜Í›7“––ÆàÁƒí4Ahýû÷çäÉ“üñÇñÃ?`2™èÝ»·½“&WL¥Rqã7²mÛ6:DFF+W®$22ò¢-ó‚p-éÖ­z½ž5kÖP\\ÌÆÉÈÈ`РAöNš 4ˆþýû“’’Ÿþi­«X,zõêeï¤ ×)…ÔT¦—üÛ_ýÅ|@ii)®®®L˜0áÇÛLâ!×*“ÉÄÏ?ÿÌŠ+Ðét2}útzöìiï¤ Bƒ¨­­å“O>aË–-H’DË–-yì±Ç·wÒ¡ÁìÞ½›?ü²²2ÜÜܘ8q"Æ u¡Y0üôÓO|ûí·èt:‚‚‚¸ë®»èÞ½»½“&\§š\À òŒR¹¹¹øûûhïäBƒËÉÉ¡¼¼œ–-[6¹0áJ™Íf2220™L´lÙ'''{'I\II yyy\3“æÂåu¡©h’« ‚ ‚ ‚ 4©1¬‚ ‚ ‚ ‚PG¬‚ ‚ ‚ B“$VAAA¡IRÍ›7ož½q=*,,$--íœI¥L&äĉ¨T*ÜÜÜP*Ï´+TVV²wï^rrrpvvÆÙÙ…B@MM {÷î%33GGG\]]­û‹Éd"--½{÷’ŸŸ··7ŽŽŽ6û:Drr2J¥www›üUUUYóçää„‹‹‹5’$‘——Çþýû)..ÆËËKÌÈØ„‘‘‘äååñÆožžŽƒƒ …‚§žzŠøøøFË—ÑhäwÞaóæÍ¸»»£×ëñööæé§Ÿ¦mÛ¶TUU±lÙ2vïÞmÍß”)S7nYYY,\¸üü|kþæÎk]¿q÷îÝ,Z´¥R‰Ùl¦mÛ¶Ìž=???{ŸR᪪ªøàƒèÖ­-[¶´n?}ú4¯¿þ:ÙÙÙh4”J%sæÌ¡C‡Ì‚ ¬ùkÙ²%O=õ”µáê›o¾aõêÕÖüÝxãÜu×]¸¸¸Øû” g©kxxë­·¸ï¾ûð÷÷·îKJJbîܹÔÍg̳Ï>Kpp0ßÿ=+V¬ÀÑѽ^Oÿþý¹çž{pss»ä5²1$''³páBªªªP«ÕTUU1räHî¾ûnœœœHNNfÞ¼y˜Íf™3g!!!üðÃ,_¾ôz=ýúõãÞ{ïÅÍÍêêjÞ{ï=vîÜiÍߤI“¸õÖ[í}J…$‰“'O²hÑ"^{í5ÜÜܬû~þùg>ûì34 ƒ^½zqß}÷áááAmm-ï¿ÿ>þù'NNN ÆÏĉQ(—¼F^m‹…]»vñÚk¯YëJ:Žû￟¡C‡¢V«Y¿~=Ÿ|ò‰5=zôàþûïÇÓÓNÇûï¿Ï¶mÛ¬ù»å–[˜4iJ¥²IÔÅ„ú±X,lÞ¼™7²hÑ"k£„Á`àÃ?dóæÍÖsúˆ7Zó7jÔ(î¸ãÔj5………,^¼˜'Nàèèˆ$IÌš5˺ï‰'˜?>F£žþù«Ÿ?IhTÛ¶m“Þzë-©K—.Ò“O>i³ï—_~‘úõë'íÝ»WÒétÒ;ï¼# 2D*..–ôz½ôòË/KS¦L‘²³³¥ÂÂB顇’žxâ ©ªªJZ²d‰4vìX)==]*++“ž~úiiæÌ™Reee£åmß¾}Ò€¤¯¿þZ2 RZZštÇwH=ö˜$I’ôÛo¿Iýúõ“öìÙ#ét:iÙ²eÒ Aƒ¬ù[°`4yòd)++K***’yäiöìÙRuuµT\\,M:Uš?¾TVV&|¸ôÉ'ŸHf³ÙÞ§Uø[MMô믿JÏ<óŒÔ±cGé믿¶î3Ò›o¾)Ýzë­RFF†TRR"=þøãÒƒ>(UUUI¥¥¥ÒŒ3¤çž{N*))‘ÒÓÓ¥±cÇJï½÷žd4¥ÌÌL©_¿~Ò_|!ét:é?þz÷î-íÞ½»Ñò·|ùriàÀÒ®]»$“É$ýùçŸÒM7Ý$}öÙg’Éd’/^,Ý|óÍRFF†TZZ*=ùä“Òý÷ß/UVVJeeeÒ½÷Þ+Í™3Çš¿qãÆIK—.•ŒF£”••% 0@úôÓO%N'ýùçŸRïÞ½¥;wÚû´ g),,”~øáéî»ï–zõê%íØ±Ãº¯¢¢BzðÁ¥'žxB***’²²²¤ &H‹-’ ƒ”““# 2Dzÿý÷¥ÚÚZiïÞ½RïÞ½¥Í›7K’tñkdcyúé§¥ñãÇK™™™’N§“V­Z% 4HÚºu«TYY)=üðÃÒìÙ³¥ÂÂB)++Kš4i’ôÆoHz½^:}ú´4lØ0é½÷Þ“jkk¥H½{÷–6lØ I’$mܸQêÛ·¯´sçNI§ÓI|ð4pà@©¨¨ÈÞ§U8KZZšôé§ŸJ·Ür‹4räH)==ݺ///O5j”´dÉI«ÕJÇ—zõê%­[·N’$IÚ¾}»Ô·o_iË–-’N§“>ÿüs©oß¾R~~þ%¯‘¡¨¨Hš2eŠ4gΩ°°P*//—Þ}÷]iÈ!Rzzº”——'3FZ¼x±T]]-%%%I}úô‘Ö®]+I’$íÚµKêÓ§´iÓ&I§ÓI_~ù¥Ô·o_éôéÓ’Ùlnu1áÒöïß/-]ºTêß¿¿t×]wI:κïàÁƒRŸ>}¤ŸþYÒétÒwß}'õéÓG:uê”$I’ôþûïKÇ—N:%UTTH/¼ð‚tçwJ—¼F6†¤¤$馛n’Þ{ï=©ººZÊÏÏ—~øai„ ’$IRbb¢Ô»woiݺu’N§“~øá©OŸ>Rjjª$I’ôá‡JÆ “N:%UVVJsçΕ¦N*•——K•••Ò¬Y³¤G}T*((²³³¥É“'K¯½öÚUÏŸè‡ÓÈrrr¨®®>§›$ÀöíÛéÓ§;vÄÑёѣGãææÆÞ½{­Ý(o½õVÂÂÂð÷÷gÊ”);vŒŒŒ vìØÁèÑ£‰ˆˆÀËË‹‰'rúôiNž<ÙhyKMM¥]»vŒ3FCDD#FŒàÈ‘#ÖüõêÕ‹N:áèèÈÈ‘#ñðð௿þ¢¶¶–¿þú‹[n¹…ððpüüü¸ýöÛIJJ";;›´´4ŠŠŠ˜8q"^^^´iÓ†ádzuëVk+`&“‰ŒŒ €sî  víÚÅØ±ciÙ²%>>>Lž<™ôôtÒÓÓÉÊÊ";;›Ûo¿"""5jþù':Ž={öÊСCqtt¤k×®têÔ‰mÛ¶5Zþ’’’¸é¦›HHH@¥RÑ»woâããILLÄh4²sçNÆŒCË–-ñööfÒ¤IÖò›MFF†MþÆŒÃöíÛ©©©á¯¿þ"((ˆáÇãèèHBBñññüñÇö>­ÂY´Z-ÙÙÙ¸ººž3$!77—¤¤$¦NŠŸŸáááÜ|óÍìÚµ‹ÊÊJ8€§§'£GÆÉɉN:ѽ{w¶nÝ \üÙXRSS™:u*-Z´ÀÑÑ‘±cÇâììLff&yyy?~œ©S§âïïOxx8·Ür »w零²’ƒâææfÍ_\\={ö´É_Ïž=‰ÇÑÑ‘áÇãííÍž={ì}Z…³”––RPPpÞzJbb"†qãÆáââBLL ýû÷gË–-ìØ±ƒ.]ºÐ­[72dÁÁÁìܹó’×ÈÆPQQAII 3fÌÀßßOOO&MšD^^=z¥RÉÍ7ߌ««+íÚµcÀ€lÞ¼Ùš¿øøxºw£#ƒ&$$„;wb2™šD]L¸´¼¼<ÊËËmº‚×Ù¹s'±±±ôéÓGGGn¸á"""رcüñ#FŒ uëÖxxxpÛm·QRRBrrò%¯‘!;;///&Mš„««+ÜrË-;vÌš¿öíÛÓ·o_éß¿?­[·fûöílÛ¶áÇӺukÜÝÝ?~<ååå$''SPPÀ±cǸãŽ; ,,Œñãdz{÷nÊË˯j¾DÀÚÈ&OžÌsÏ=GTTÔ9û’’’hÕª•µˆ··7)))èt:ÒÓÓ­ÝcÚ·oOqq1¤¤¤Øì‹ŒŒ¤¶¶–¼¼¼FË[·nÝxðÁ­]‡$I²ö߯Ë_DD„5øúú’œœŒ^¯'--Í&111”––RXXH~~>555DDDX÷ÇÆÆ’’’‚Édj´< çîîÎ}÷ÝÇÃ?LPPÍ>“ÉDjjªÍ9nÛ¶-ÕÕÕäççSXXHyy9mÚ´±îåÔ©S Nœ8¾¾¾8::ÉñãÇ-ãÆc„ Ö2¬Óé¬_zf³ùœÏaTTZ­–¼¼<ŠŠŠ(--%22òœüéõzRRRðòò²æÏÁÁ¨¨¨FÍŸpi<òÈ#ÜyççŒ]­«èŸ]bccÉÈÈ ¦¦†“'OâêêjíB¬R©h×®õ_ìÙXfÍšEß¾}­ÿWTT`0pqq¡¬¬Œ‚‚›ï¯ºüiµZN:…‹‹‹µ ¿J¥"&&Æ&-[¶´Ž‡ô÷÷ÇÏϯQó'\ZBBO?ý4cÇŽ=g_FFjµÚÚÅ C‡6ç8<<Ü:LÃÇLJ   Ž?~Ékdcð÷÷çÙgŸ%<<ܺ­¤¤FƒF£!33¥RiÓ½ñŸù ³6ÈúøørÁüÙ£.&\ÚÈ‘#™3g]»v=g_RR!!!Öº¬§§'ááá6eàìsܪU+Ìf3999—¼F6†˜˜fÏžmÓàTXXhý¾JJJ"88ØZ7÷ðð E‹Í_ݸõ²²2òóóÏÉ_VVÕÕÕW5_b k¢Õj­cœœœÐh4”––b±XÐét6·ëÆ‹hµZjjjlö¹»»c4©ªªj´ôŸh”––òóÏ?³zõjž{î9›üÕ ìvrrÂÁÁá¢ùÓétÔÔÔ ×ë1™L6û===)--µŽš6I’¨­­=§œêõzª««qppÀh4žsŽËÊÊ0›ÍÔÔÔ R©¬ÕMJV\\Ühy¨‡$ý=؇~ÈÉ“'yúé§/˜?ƒÁ@uu5nnnçÍ_yyy“ÉŸpeŒF#F£Ñf OOO***0™LÔÖÖ¢T*­iݤJ%%%Àů‘¥ÿþ€<¾+))‰·Þz‹ˆˆHRRƒáœüUVVb4©­­E¡PXóW7©ÒÅòçèèhÝ/4}:À¦w‡‡Çϱ££#ÎÎÎ_òÙ<<<¬eÜl6óÇðî»ï2aÂ"""¬wRë›?kþ€&Q®ŒV«%88Ø:¦U£ÑàââBVVpî9®'ZUU…Ñh¼è5²1„……Èó‰lÚ´‰>ø€GyÄš¿³'ëË_nn®uÿÙùsuuÅb±PUU…Éd²[þDÀÚ \hö9…BÑè3ÓY,y÷Ýw)((àÉ'Ÿ´~9Âù\i9mÌ2.I‹…_~ù…åË—£V«™7o-Z´¸`ëéµ”?A$ NÇ—_~Éúõë gÖ¬YÖ;ÿ‚Ðл®"Iùùù|õÕWlÚ´‰¾}ûrß}÷]µÉíìQÞµt- )))|øá‡?~œ3f\rò¾¦ž?°6!®®® $I²Î\g4 D©TZg­SYY‰››îî¸Øì«ªªÂÑÑñ¼ýó¯“ÉÄgŸ}ƪU«?~<·Þz«M—„ºüY,”J%:ƒÁ@PPÐóçêêjm¡T«ÕèõzkËOEE…õ½š>…B³³ó9åÔÙÙÌf3æœs€Z­ÆÅÅÅz§J­Vc6›©®®¶éšvµUUUñæ›o’””Äĉ­ãµ/–?'''ë²çËŸ¿¿¿5EEEvÍŸpeêºêt:k tEE¾¾¾Ö;1‹£ÑˆF£±¶Z×ã‹]#KVVÿûßÿ0Ìž=›~ýúÙäÏÁÁNgí^öÏüI’dÍŸ$IõÊŸ(ã׎ºr]wŽAþ®¾Ð9ÖëõÔÖÖ~Ékdc°X,9r„yóæÁÒ¥Kmz‡Õue®oþ µµµÖ.ÄM¡.&\WWWŒF#f³•J…Ñh¤¦¦ÆZþyŽ«««Ñh4x{{_òÙÌf3?ÿü3ï½÷ƒæé§Ÿ¶YBóRùsuuµÉŸV«E­VãããƒZ­¶æ¯.?øøø\õ¥{DM¿ ‰'%%ƒÁÈx”””ЦMœ‰ŽŽæèÑ£ÖÇ>|oooüýý‰‹‹³Ù—œœŒƒƒC£VtöïßÏš5kxä‘G˜>}ú96ÄÇÇ“ššjÍ_ݸ¾6mÚàääDLLŒMñòò²N^âîîNjjªuÿÁƒiÓ¦ÍúhBÓ¥ÑhèСƒÍ9>vìÎÎÎrÎx½ƒZÇôuêÔ‰¢¢" ¹kZrr²ÍX‹«mݺu9r„_|‘›o¾Ù¦Û˜Z­>çsxüøqœœœ ((’’’lòײeK‰‹‹³Žy´ãÇ7jþ„+@hh¨M8xð uL_ûöí©®®¶Žg3™L9rÄzŽ/vl,Ë–-àÕW_µË àççGXXØ9ù«ÓƒV«µv-3™L$&&Zó×¹sgNžû§¦¦¢P( ¹ä5²1$''óÙgŸq×]wñÐCÙ«uùËÎΦ¢¢€òòr›9dΗ?I’¬ù ·KþDÀÚ„ 8C‡±ÿ~JKKùñÇ1ôíÛ777ú÷ïÏO?ýÄ©S§ÈÈÈ`ùòåtíÚ•ÈÈH ÄÆIIIáôéÓ|ûí·´iÓ†víÚ5JÚÍf3[·nÅ`0••ŧŸ~ÊÇÌÇÌŠ+¬ùKLLdß¾}”––²nÝ:ë:„...ôïߟ_~ù…S§N‘™™ÉŠ+ˆ§U«V´iÓ†–-[òÝwß‘ŸŸÏÑ£GÙ¼y3#FŒh´V+áÊ8880pà@~ûí7RSSÉÎÎfåÊ•ÄÄÄжm["""ˆŽŽfåÊ•äååqìØ1~ÿýw† †‹‹ ½zõ¢¢¢‚_ý•òòrvìØArr27ÝtS£¤ß`0ð믿âêêÊ®]»øä“O¬e|óæÍh4n¼ñF~ÿýwRRRÈÉÉáÛo¿¥mÛ¶DGGÓ²eKÚ·oÏŠ+ÈÍÍåøñãüúë¯ :WWWzõêEUUëׯ§¼¼œ;wZg%® !!!$$$°|ùrrrrHNNæ§Ÿ~bРAxzzÒ­[7ŒF#ëÖ­£¬¬Œ¿þú‹Ã‡3bÄàâ×ÈÆP[[Ëï¿ÿŽ»»;k×®åÿþïÿ¬eüèÑ£Öü­X±‚œœNœ8Áºuë¸ñÆñöö&!!I’¬ùÛ»w/´ÉßÑ£GÙ»w¯užƒšš `ïS'ÔSçÎqttdÍš5”””pàÀöìÙÃÈ‘#¸á†8qâ»ví¢¬¬Œ_ý•²²2n¼ñÆK^#Cff&û÷ïG¡PðÝwßYË÷ÇLaa!;vÄÙÙÙ&»wïfÔ¨QÖü¥¦¦²sçNÊÊÊøí·ß())áÆoD­VÛ½.&\¹‘‘Á¶mÛ(++cãÆäåå1xð`† –-[¬³ÿý÷„„„wÉkäÕf±XØ»w/ùùù”––òå—_Ú”qç)ÈÊÊâ?þ ¬¬ŒM›6‘››k“¿­[·’””D~~>ßÿ=AAAtìØ‘   ºvíÊÊ•+ÉÎÎæÄ‰¬]»–^õa# IÌXcóçÏÇÝÝÙ³g[·ét:>ÿüs6lØ€F£A¥Rq×]w1hÐ @žÉîÕW_%33…B‡‡sçÎ%,,ŒòòrÞzë-Ž;†R©ÄÕÕ•§Ÿ~ºÑ¾jkkY²d þùç9ûùä“OÐét|ñÅlذµZJ¥âÎ;ïdÈ!Öü½öÚk¤¥¥Y'#yñÅiÑ¢ ·½üò˘L&Ìf3ñññ<øàƒ¢«MTXXÈ+¯¼ÂСC­[*-ZDrr2J¥777æÌ™cmåNKKcîܹÖî*±±±Ìš5Ëz¡ÿé§ŸøòË/Q©T˜L&FÅĉ¯zWËçóÏ?oÓò^§ÿþ<ýôÓ”——³xñbŽ?nÍß3ÏB©Tb4¹é¦›¸ýöÛqvv¾ä5òjËÉÉá¾ûî;ï¾™3g2vìXòòòxöÙg©­­Åb±Ðºukžzê)kþ¶lÙÂ|`ÍßСC¹ãŽ;¬]A¿üòK~ûí7kþ¦NʰaÃì{2…óÚ²e ß}÷Ï=÷¡¡¡Öí;vìàÝwß䮳ƒ bÚ´iÖî²Ë—/ç§Ÿ~B­V£T*™}ºµ+åòåËY·njµ…BÁ¤I“=z´5ö¬‹ —çý÷ßçôéÓ¼ð ֛&“‰ï¾ûŽÕ«W[{ðÝvÛmŒ;•JEee%ï¾û.@­VãììÌìÙ³‰‹‹¸ä5òj2™L|üñǬ[·î¼ûþùgÌf3ß}÷?üðƒ5ãÇgܸqÖü-[¶Œ}ûö¡V«qrrâ±Ç£S§N€Ü3fΜ9hµZ, <ýôÓøùù]Õ¼‰€µ JII¡´´”öíÛãááa³O¯×sâÄ $I"::Úf¦.“ÉDrr2F£‘èèèFë~p¹RSS)))!&&æœ`óìüµmÛÖ:ž¤Nyy9'OžÄÃÃCt¾FF’““1›ÍDGGŸsŽ+**8yò$nnn´iÓÆ:kn¼¼<233 ·©D5uù3™LçýVVVZ—79_þòóóÉÈȰ™éO¸¶TUU‘ššŠ³³3‘‘‘ç¬×ZXXHzz:ÁÁÁÖ¹³]ìÙTWW“ššŠ““ÓEóDË–-ÏyþÉ“')..¦]»vç]ëShúŠ‹‹IKKÃßߟV­Z³?--ÂÂBÚ¶m‹Í¾K]#›‚ºüùùùѪU«s&¤IOO·._òÏ@äZ©‹ W·öt›6m¬K‘Õ1›Í$%%¡×ëi×®Ý9Kœ]êÙdee‘››KëÖ­Ïé’_7K¼N§»hþê–lŒžŽ"`AAAš$1†UAAAh’DÀ*‚ ‚ ‚ 4I"`AAAš$° ‚ ‚ ‚ M’XAAA„&I¬‚ ‚ ‚ B“$VAAA¡I« ‚ ‚ ‚Ð$‰€UAAAh’DÀ*‚ ‚ ‚ 4I"`AAAš$° ‚ ‚ ‚ M’XA°›””RSSí AhTÇ'==½AYRRÂîÝ»í5AAhp"`m¢V®\ɦM›ì A¸ª>ÿüs¾øâ {'CÕÒ¥Kùá‡ô˜‡âñÇ·wÖA¡Á‰€µ‰úå—_صk—½“!W•V«E«ÕÚ;‚Шª««©­­mÐcFÊËËí5AAhpj{'@F*++1›Íxxxœ³¿¶¶–ªª*4 îîî˜L&P*•H’„^¯§²²///0›Í˜L&”J%eee( <==Q©TTTT`0ðôôÄÉÉ ³ÙŒÙlF¡PP^^ŽR©ÄÓÓ…BAee¥õ±ÎÎÎö~»„kÅbáèÑ£üúë¯1hÐ ƒµìíܹ“­[·RVVF·nÝ3f jµš}ûöD›6m¹LoÞ¼™˜˜œ9zô(þþþ¬^½š’’n¾ùf¢¢¢X¾|9iiiôíÛ—Ñ£G£ÕjIJJÂÇLJï¾û­VËm·ÝFHHß~û-™™™ 0€‘#Gâäädï·Kh&Ìf3‡fýúõTVVrÓM7a4$‰’’~ûí7öîÝK@@C‡%&&†ýû÷A‹-Ðëõlݺ•Î;£P(8qâaaa|úé§Œ;Öæ5%I¢¨¨ˆÃ‡GPP½ß¡™ÓjµÌŸ?ŸÇ{Œ€€ªªªpvvÆÑÑÑÞI„÷î»ïË 7Ü`mtwss³w²š5°6Z­–eË–ñã?¢Õj>|8%%%DEEPTTÄk¯½ÆÆñõõåöÛo'--3fЪU+rssyå•WصkJ¥’aÆñÈ#Ä¡C‡X·n|ýõ×( ¦NŠ»»;_~ù%………ôéÓ‡7ß|“£G²aÃ4 ß}÷†éÓ§°bÅ JJJèׯK–,±Ä‚P_{öìaÊ”)DGGÇÂ… ÉÊÊbìØ±üùçŸÜ}÷ÝÜx㸹¹1oÞ<ÒÓÓy衇øì³ÏÐh4,[¶ €ììlîºë.V®\‰Ñhäî»ï&::šN:‘““äI“h×®±±±˜L&þóŸÿ`2™ðóócæÌ™´oßž.]ºpêÔ)ÆOtt4:t ¦¦†{/¾ø‚Ñ£GÛû횉72sæLºtéB›6m˜7oiii´oߣÑÈSO=ERR7Üpû÷ïç“O>aùòå,]º”ÈÈH^yå’’’¸çž{X¿~=ÙÙÙ<ú裴jÕ '''Feóš<ôÐCxzzÒ©S'{¿Âu@¯×³|ùrîºë.$Iâé§ŸfÆŒÜpà öNš 4¸ 6лwoÞ~ûmæÌ™cïd5k"`mÞ~ûm>úè#ž{î9:uêć~ȶmÛèÙ³'F£‘ÿýïìÙ³‡%K–PVVÆÿû_JKK;v,žžž<õÔSÔÔÔ°téRª««™?>ååå¼ùæ›dffòöÛo3mÚ4¾ùæ~üñGæÌ™Ã¨Q£xõÕWIKKãÉ'ŸdذaÔÖÖ²hÑ"þóŸÿ°|ùr–/_ΓO>Éøñãyã78zô(sæÌá–[naÈ!ö~Û„kˆÑhäwÞ¡[·n,Y²8À¤I“yÌvûöíY¼x1NNNôêÕ‹ôôt Æ ã7Þ ==V­Z±fÍ:tè@tt4GE£Ñ0cÆ n¹å´Z-ôìÙ“yóæQ[[K^^Gå†nÀÑÑ‘|‘#GR^^Ž=ô³gϦ¼¼œœœŽ=*V¡A –,YÂàÁƒyíµ×ðòòâÏ?ÿdêÔ©èt:V¬XÁW_}ŸqãÈÏÏ·^ÇGŽÉG}DNNaaa¬^½š=zNvv6UUUŒ=š)S¦àææÆÆ‘$‰ÜÜ\üq\\\X°`ö~„fª¬¬ŒÒÒRÜÜÜP(€Ü“¦´´”½{÷2lØ0 ÔÔÔ R©Ðëõ”••Š^¯G£ÑPPP€Ñh$((gggòóóÑjµøúúâåå…B¡@§Óògª¨¨üýý­ÿ[,BCCEcºpUèt: ±X,Z·kµZŽ=ŠR©¤¦¦GGGjkkqrr¢¬¬ÌúøºÏEEEÎÎÎøúúâèèˆÁ`Àd2¡P(ÈÏÏG¥RˆB¡ ¨¨NG`` ¸{‹Xí®¬¬ŒuëÖqÏ=÷pçw¢V«ñòòbÏž=€Üjùý÷ßóÞ{ïÑ¿, ÙÙÙÖC‡±eËvîÜIDD wA»ûî»yñÅç¾ûî#::š;§žzŠ{=zЦMbcc)))ÁÅÅ…V­ZqÏ=÷ЦM&OžÌüùóùÏþC·nÝçÓO?¥¤¤ÄÞo›pÉÊÊ"55•Y³fY»'ÆÄÄЭ[7"##ùùçŸyýõ×8p C† ÁÇÇ€ðâ‹/rôèQ¼½½ùý÷ß1b~~~¸»»‡R©ÄÝÝ…BA||<ÆæËÀÛÛ›˜˜ îîîÖÇÖU€ê+WêÔ©Säæærï½÷âëë @çΉ‹‹@­VÓºuk>øà*++IHH`Þ¼yh4òóóyþùç9yò$ÎÎÎlÛ¶iÓ¦áéé @PP7Üp^^^Ö×Ójµ<òÈ#lÞ¼™?üЦb% éÀ¼ôÒK?~œkãcyy9~ø!¹¹¹,]º___†λï¾K`` Û·o'%%…¥K—òé§ŸÂòåË©®®fܸq´oßž>ø€ÂÂBâââX´h|ñÅTWWsðàAöìÙC@@÷ß?û÷ïgóæÍF¦OŸÎìÙ³Q«EÕVh8%%%¼þúëüöÛo˜L&ÆŽKYY_ý5;vì@¡Pðúë¯3mÚ4Þ~ûm ÀÇL§Nx饗øý÷ßyûí·9yò$~~~Œ=š§Ÿ~šíÛ·³qãF, ?þø#ŽŽŽLŸ>ÚÚZ~øáÊËËéÛ·/ï¿ÿþuß#&]²³´´4ª««éÒ¥‹õ"fí|ìØ1Ìf³u“R©$""FÈ€^¯ç¿ÿý/3fÌ`ÆŒ|òÉ'TVV¢×ëyL«···ÍëÖUöÕjµÍ‡ÀÏÏÏZ!:ßcë^W.GMM z½Þ$ÖVF€|ÿþ÷¿$''óÌ3ÏЧO/^Lmm-þþþôìÙ“5kÖ°ÿ~RSS¹õÖ[­ÇQ©Tõ'¥V«Å˜*¡ÑTUUa6›mZÇÝÜܬA¦³³3«V­¢OŸ>|þùçL™2…AƒqàÀ‚‚‚HHH`íÚµìܹ“ÒÒR†n=޳³ó9×jƒÁ@ÇŽ¹í¶Ûxã7ÈË˳÷[ 4CuC’<==Y³f Ï>û,_}õžžžÌš5‹àà`fΜɀصk/½ôaaa¼ôÒK²råJNž<ÉêÕ«yã7X²d _}õ}ô_ý5III¬X±€ƒòÚk¯1~üxþøãZ´hÁÃ?Lhh(k×®eÆŒ|þùç=zÔÞoÐÌ<÷Üsüøã¼öÚk¬^½š¼¼<:ÀĉéÙ³'½zõbÖ¬Y 6nÜÈ’%K1bÓ¦M£¸¸˜Ç{Œ²uëVî¿ÿ~¾úê+8@zz:Ë–-ÃÇLJ­[·2qâDžzê)NŸ>ÍòåËyùå—Ù¸q#[¶l±÷Û`w"`µ3¥R‰R©D¥RÙl«û¿n¤ºî6€ÍßF£///úõëgý9r$K—.µVŠþùü‹¹œÇ B}ùùùáîîN~~¾u[UU999 þúë/ºvíÊW_}Å×_ͬY³X¸p¡µÂ=bĶnÝÊÆ‰ŠŠ"44ÔÞY„K ÂÑÑ‘ÂÂBë¶²²2ëç ´´”””yäV¯^ÍG}„››ï¾û. —ûßÿM›63yÒù®Ó^^^<þøãÌš5‹òòrV­Zeï·@h†:DQQ , }ûö 6Œ3fr¢——jµOOO\\\¬ÏkÓ¦ Ï=÷œ5ˆõññaúô鄇‡3jÔ(, “'O¦}ûöÄÅÅÑ­[7ªªª¬ÏïÕ«#FŒ 88˜ÁƒãààÀÌ™3‰ˆˆ`øðá8::Z» BC(,,äÏ?ÿäÑGeРADFFòØcÈ NNN899Y»¯Œ=šû￟èèht:iiitîÜ™ÐÐPn»í6>þøcBBBhÛ¶-“&M" €#F`0˜9s&mÚ´¡oß¾´lÙÒæsp½«µnÝwwwvíÚe9255ÕÚJØ¡C$I².2o6›9q⃀¨¨(ëDKÓ§OgúôéDGGsèÐ!”Jqz…¦!((ˆo¼‘>úˆ?þøƒÜÜ\V®\ÉŽ;°X,|ðÁÌ;—œœ\\\ððð°©ÇÇÇãîîÎûï¿oÿ'M]xx8={öä½÷ÞcÏž=œ>}šÏ?ÿœÃ‡r÷ÉéÓ§óã?¢ÓéðööF£ÑX¯Ý½zõÂl6óÅ_0eÊ”K¾žR©ÄÕÕ•èèhž}öY–.]Ê®]»$ÉÞo…ÐŒüõ×_´k×ΦçV}&WêÕ«—Mw]—sf°>»¡ýŸ] #""lê5J¥Òºª‚ƒƒƒhl\RR …‚ØØXkÙkÓ¦5`½Þ½{[ïëë˃>ÈC=Dÿþýyå•W¨®®Æßß›Þg€õ³¥V«E÷¿‰wÁÎ<==¹å–[x÷Ýwñóó#66–?þ˜ŠŠ @îö5zôh^{í5T*eee,_¾ÜzçµcÇŽÄÆÆòðÃsï½÷¢×ëY¸p! ¢û®Ðd( î¿ÿ~öîÝËý÷ß¿¿?’$YÇ¢N˜0{ï½—É“'ãèèHII /¼ð‚õNjXX;wÆl6Ó¥KëqU*...6777› ¼““ŽŽŽ|l]o…B““Óu?NDh8 …‚Y³f1sæLf̘*•ŠaÆáèèHxx8'Nä•W^á“O>¡¦¦''',XÈ£˜˜ÜÝÝiß¾½õ¸jµ›Ê{]ù®û{üøñ¬ZµŠ/¿ü’„„Q®…ãìì|N#H}Æþ‹å„k£££uùÈ:’$]²ðì²îââÂóÏ?ÏĉÙ¿?6là›o¾aÑ¢EöÎÞ5E¬MÀý÷ßÀ7ß|ƒÙlføðáŒ1///4 ÿýïY²d sçÎ¥eË–Lœ8‘ï¾û|||xï½÷˜7o/¼ð†AƒñøããääD«V­3fŒuíTî»ï>ëØA†NLL Œ9Ò:ÆÏËË‹ûî»ÏÚ‚éääÄèÑ£‰ŒŒ´÷[&\ƒBCCY½z5ûöí£¦¦†=zØL³ÿ~öìÙƒÉd"..ް°0ë>‹Å‚B¡`èСÖõXúõëwÎØŽ‚‚ëßŽŽŽ,Y²ÄúÿàÁƒ­«Õj›n6...|ôÑGö~›„f&**ŠŸþ™Ý»wc2™èÝ»·Í˜ÖeË–qòäIŽ9BPP:u²žf³µZͨQ£l>C† 9g¦önsuuåÇ´wö…f¨{÷î¼÷Þ{äääжm[Ìf3?üðƒ½“% ®]»v( vïÞM¯^½P©T>ž.]ºðè£rÇwŸŸomD¹1Ðb±‘‘AQQ‘µë£ \k¼¼¼˜4i~ø!jµš-ZðÑGY{j) ë¬îiiiçíiàååÅ®]»xõÕW:t(YYYN£Ñàé鉇‡‡»*4+?ÿü3/½ô£Fbúôé¢| ×…ï¾ûŽ… 2qâD&Ožlïä‚•››}ûöåàÁƒ¬_¿žššyäbccéܹ3!!!äççóÓO?Att4&“‰ØØXëò{‹www¬=À  °®l±XhÛ¶-mÚ´Ád2ETT …³ÙŒŸŸŸµT’$Ôj5]»v=gölA¸uKß­Y³†}ûö1~üxÆŒCtt4­ZµÂÉɉ-[¶Í€pvv¦GÖq©uKïíÚµ‹µk×’ŸŸÏÔ©S™1c’$@§NÐh4H’„ƒƒ7Þx#NNNH’„R©¤S§N×ý2e IÌÆÐ¤I’DEEkÖ¬áÀ¸¸¸Ð·o_ d½È BsV]]Myy9>>>8;;‹‰5„ëBUUøúúŠk½Ð$ÕÔÔPUU…‹‹ nnn6׿ÚÚZ***ðòòcW…kžÉd¢¬¬ …BMùÙl¦´´‡s&Œ<[uu5ÕÕÕ8;;ÛÌŸ!ÔXAAA„&Iô­AAAš$° ‚ ‚ ‚ MR³˜nS§Ó¡Õjí ¡ R©TÍb"ªªª* ƒ½“!4A猻•••Õk-Gáúãììl]êçZe±X¨¬¬Äl6Û;)Bäîî~ͯ•l4©ªªºä¥ÂõG¡PàééyEãv¯ù€Õl6óÛo¿QPPÐlöZ'5hŽt:………´hÑ¢Á]]]Í AƒˆŽŽ¶w6¯(+W®¼æ¿Ì.&==ˆˆˆk>èºêêjªªªnÐãJ’Dmm-·Ýv›u™«kQqq1_ý5ÞÞÞöNÊU“––Fë֭팫¦¸¸•JÕàçÐ`0 T*¹ûî»íÅ+RSSÇ~HPP½“rU˜L&rss¯Ê÷xS I¹¹¹ÖÉÿRMM -[¶døðáöÎæIMMeÓ¦MÍv–f­VKEE!!!öNÊUa4ÉÍÍ¥eË– ~ìêêjzôèABB¿>Æ5°J’„ÉdbÔ¨QͶ>|???BCC픫¢¬¬ŒÄÄD ÐàÇþã?®ù»ïF£µZÍ´iÓ씫æ×_eèС×üð ÉÍÍ%''‡îÝ»7èqF#k×®Åh4Ú;‹W¤¦¦†°°0n½õV{'åªùå—_1b„½“qÕ;v FCÛ¶mô¸¥¥¥¬[·ÎÞÙ»b‹…°°0n¿ýv{'åªÐétìܹó¢ë _ËÌf3{öì¡mÛ¶øùù5è±333Ù¿¿½³xÅ Ý»w§GöNÊU‘ŸŸOFF†Í’’ÍIuu5{öìaàÀ ^;xð WtŒk>`½´oß¾ÙVä<==éÕ«—½“!ØÑÀ›íÝU€ÀÀ@üýýí ÁŽškE¾ÎµÜ‹E¸rŽŽŽôéÓÇÞɸj”J%]»vE­Õæë•¿¿ÿ5Ý“éR\]]éׯ_“­‹‰OÞ5@£ÑØ; W•R©lÖÝ]…Kstt´w®*•J%Ö\»Î5×!+uDEþú¦P(šõu\¡PˆzÊu®¹7õ2Þ|oÛ ‚ ‚ ‚ ×4° ‚ ‚ ‚ MR£÷áÙ¹s'6l°Ùψ#P«Õ°~ýziÙ²%cÇŽ¥E‹Íz §Ð¼±|ùrÊÊʬۜ¹çž{ðòò"33“U«V‘ŸŸOçÎ:t(öN¶ Ô[rr2k×®E§ÓY·µhÑ‚ &àèèÈ‘#GX½z5f³™=z0hÐ \]]ílA¨·íÛ·³iÓ&›m]ºtaøðá¨ÕjòóóY¿~=GŽ!""‚±cÇ.ê*Â5cåÊ•$''Ûl1bݺuÃb±‘‘ÁªU«((( >>ž¡C‡Š¹»iô€uÛ¶mlÛ¶ÍfÚä-ZX×ß[°`999Œ5н{÷2þ|.\(*ôÂ5£  €o¿ý–ÈÈHkåÅÍÍ £ÑHqq1Ï<ó ~~~tíÚ•5kÖpäÈ.\hïd B½;vŒŸþ™ÈÈHë6Ìf3‰‰‰¼ð $$$̲e˨¨¨`êÔ©öN¶ ÔÛüqN]%""ºÆäË/¿L~~>#GŽä¯¿þâСC,\¸PTè…kÆêÕ«©­­µ™H¨ººÞŸyæHHH`ÕªU;vŒ Ø;ÙÂuªQV£ÑHNNwÜqS¦L±nW*•¨T*víÚErr2 , K—.Œ;–)S¦°aÃ›Ç BSVZZŠï¾û®ÍvFçŸ~ŠÑhdÞ¼yøùùÑ¡Cüq騱£½“.4A&“©IMhc±XÈËË£gÏž¼üòËÖí ……BÁW_}ETT/¾ø"J¥’€€–/_΀šíBób49}ú4Ó¦McòäÉÖíuu•;w’’’ÂÂ… éܹ3£GæŽ;î`Ó¦MLš4ÉÞÉ„KÒétTWWóä“OÚ¬ÒP7©Ðºuë0›ÍÌŸ?Ú·oÏÓO?Í‘#Gˆ‹‹³wò…ëP£Ö‚ª««©ªª²¶@êt:\]]Q*•( RRR $22…B››]ºtáСCW5`µX@’@©„óÍæüwƒ*Mt¦çë’$IÔÔÔ°uëV>ŒN§£¼¼œ¡C‡rÓM7¡P($‰¼¼<ÜÝÝ5m§OŸÆÇÇ•JEMM îîîÖ2ž””D§NðôôD¡PAxx¸X+‹ÅÂÁƒÙ¹s''Nœ ¨¨È°ñÄOÈkêõúFMŸÉd¢°°???”J%ÕÕÕÖ2n2™HNN殻9!!Ï>ûŒ¬¬,° ׄªª*ª««­ëmþ³®râÄ BBBhݺ5 …wwwâãã9tèX…kBaa!*• L& Ïd^·¤ÉñãÇéܹ3( ZµjEHHˆX»iÔ€µ¬¬Œ’’>ÿüsÞ{ï=ª««‰ŠŠâÉ'Ÿ¤mÛ¶¤§§ãââ‚§§' w1‹ŠŠbÕªU=nmm-iiiøùùý«)™?úþú î¾bbÀÇÇvÿÎ`6C¯^ÐÌW˜i²êRwww4 ;wîäÿþïÿhÑ¢={ö¤E‹TWWóÓO?ñÙgŸ@RRƒ×^{­QÓš––F^^ãÇÇl6c2™¸ë®»˜4i©©© 6ÌZNýýý 8gÉ?UUUqòäIÂÃÛÌÒƒÚÚZëçµNMM ŽŽŽMjúw£ÑH~~>ÅÅÅTUUa2™pww'88˜€€›ë†^¯§´´”ÀÀÀFVPPÀ§Ÿ~Ê‘#G1b÷ß?QQQ8::b6›Ù²e 3fÌছnÂ××—_ý•ììlúöíÛhi4 dggSVVÆüN§ÃÅÅ…çž{ŽÎ;sêÔ)¬oÓ¦ z½žÜÜÜKæ=33SŒl¤¦¦RYYÙ¨¯YZZJii)Ÿ}öË–-£ªªŠvíÚñÄOEZZ®®®ÖkŸ££#‘‘‘¬[·î¢ÇÍÏϧ  €ÀÀ@»½ŸBÓ¢ÓéHMMmô†ÇììlÊËËy饗ÐëõTVV2xð`xàHMMeôèÑÖeðóóãĉ<¦Ùl&33“˜˜<<<ìú¾ MGYYW\&5`­­­E­V3jÔ(úôéCUUï¼óo¿ýöEÇ𠆋·nl Ùl¾¬ôHìÝ ÇŽÁãCf&<ñ<òtê$ßQ­¨€Ã‡Á`€#G`äH‡&T·;I’¨®®F§ÓQ\\L^^½zõÂÙÙù¢Ï«­­Å`0`4±X,h4<<ûŒ¶mÛ^ð9F£ñ¢ÇÔëõÒ i5›Í”––òÛo¿A÷îÝ/Øè#IZ­–dzÿ~öîÝKee%7ÝtC‡ÅÁÁß~ûŸþ™Ûo¿qãÆY¿ìŒF#&“ •J…F£i…©%IB¯×ãàà`àFjjj(((`×®]9r„Ó§O£V«ñôôÄÓÓWWWrss)//ÇÙÙ™>}úлwoùå—_(**"::š#FÙlÆb±’’®]»HOOç?ÿù±±±Ö×6 èt:jkkÉÈÈ ¶¶–ÐÐP<==Ñëõdfd_p°M_“É„V«åĉüßÿýááá,Y²?//8q~û ÆŒAe21Øb¡•»;yï¼Ã[naРAäçç7êZÍf³ƒÁ@×®]¹í¶Û0›Í¬X±‚E‹Ùt>›Åb±¶â_HUU%%%6Á® ÚLîÕêê*£G¦wïÞTUU±dÉÞyç^}õÕ >ïbuI’¨¬¬¤²²R¬×“É„$I¨ÕjëwŸ$IFŒF#………—]½Røùù1}útbccÉÍÍeþüùxzzòØc]ðy««X,JJJÐét"`¬jjj())¹âÞŽ°ÆÆÆ²fÍ›m=öÓ¦M£´´ô‚ϻԂëtïÞý’Ò?•–›o /@ûöò‡¼ö,^,ßi7à¶Û`ófxôQ¸ýv˜0¡1ß¹¦«²²’õë×óË/¿ ×ë ¤ººš 6ðì³ÏžsÑ2TlÞŒñäIvìØÁaòmy9^ùùÄÝz+“ÄÄDÞ}÷]ÆŒÃÔ©S‰ŠŠ:so¾Í›±¬û™TckÊÂ;bÌ—H|W¢Uk]okIëØXpp`WQ–Ë,WꟚ3fpàÀ¶lÙb°ãŸ.UÆýüülÆ™\)I’ÈÉÉaíÚµlܸ‘nݺ±qãF~ùåfΜIË–-m‚J½^Ï–-[øæ›oððð oß¾,X°OOO¾úê+^zé%, Ý»wçÉ'Ÿä³Ï>#33“‡~˜S§N±råJ***ppp 00Ò©S§u¶ªªŠÝ»w“œœÌÑ£GéÑ£ãÇÇÂ>þøcRSSqtt$>>ž›o¾™èèhk÷¾³™L&RSSÙ¼y3 .$::šÇœ¨¨(¶lÙºuëøù矩¨¨ ²²’6mÚЭ[7"""X°`·ü4îÙ³‡?þøƒÊÊJ´Z-çŒ;u(-¥Ã¾} 7—®]ÉiÕŠ“'Orjÿ~´‡£-(àΠûw¢®¬„·ß†}û`Ú´3qw§Í#ЦU+ú†„`4Y»vm£Þ‘ôôôä믿¶ÙöÏ~ôx€IDATÌ3Ï0hÐ ’’’Îû•JuÉÞ/‘‘‘téÒ¥Ñò!\úôésÑúÁÕwÞºÊôéÓ)//¿àó.vW(´mÛÖö»Lhö²³³ùòË/©¨¨à¡‡"<<³Ù̾}ûøì³ÏèׯmÛ¶%++«QÓ5bÄFŒaý¿U«VLŸ>Ï?ÿœ‡~ø‚Ï»X×h4téÒEL’zÒjµTVVâïïNÝ'44”„„***®è55`ÕjµÔÔÔØÌ¢çåå…««+F£‘àà`233ÑjµÖmÙÙÙWmÜSn.Œ+w®Óµ«‰'ŸT³z588ÈwYo¾$nêQF«¢TNåzóË/Q ¤ÀQi”o¿j4òÏ%î™LòÝKÞ1™ä[º-Z€¯¯üf3\íàK’ÀhĨPPQQB¡ÀÛË eUxxPœ™É—÷>HÒ瘪ˆˆlÍÓÁÁ„éõ¸·nað`¬XÁ¢×_gî 7 ß¿ŸâÜ\6¶iÃöÇéXVF|‹ 6Œ!Ý»£ E¥Õ¢ê)N|ðŸ®[GbP<ð7ÜpJƒŠŠÀÓS>)íÛCäÖúòÛ&œÊ *ÊçÙÿáDäaçrCCZZ,ã‚ïkÝKwwwë…ÝÑÑ‘ÀÀ@ ¡¡¡”——['Ò)//§¬¬ŒØØØFIŸÅb!++‹7ò믿’À¢E‹§º¬šWüÈ‹¿ˆ¹Ö ®€Ã™|EGGóÈÃë‹sˆ3¸ ¸ÿþû­“xzz¢T*iÕª .ä ²²’›o¾™øøxô55ä²xñbȸqãP«ÕÔÖÖb6›quuÅÝ݃Á@II G%88˜”J%[·neõêÕ´nÝšvíÚqï½÷òÓO?ñÈ#ЫW/¶lÙBß¾}™?>AAAgºOK’'OBZšœØ-âã9}ìŠåËY¤ÓY/V/<ðQ¿üBþwñâ³ß“P9œäŠ8´IßÒŠ‘#;âU“„¹P^Ž£‹ ³fÍbáK/ñÂðá8u숇ŸBÁƒ>JPP §N©øâ0”|·Ü*•‘Ÿ|IÏ£‰HLdÚàÁø‡†ÊyÙ½ŒF¹¿vd$tîLAÌ™3fÀ€rv<“µQ£ä:ÿæÍåh4w‡Õh4òøã3vìXn¹å ÅÅÅœx{ÃÑ£ðÿìwxSÛ‡ï¤mº7ÐA¡ìÒR62D¶ ˆ€(ðº·8?y¼Nq¡2d¨ Ù{ÉÞPF¡“î=³¿?ž6m¡--£eœûºrA““³rròÌß³hhµX5kFÈ#ðÙûï“=g))¨Ö¯‡ÒÕU¾¯óæÉ6K"bj{{Ôaa4 £1ЯºË݆½î×Ä•œœÌ³Ï>Ë|` ‹%''‡† Ò©S'vìØÁ=%7¹C‡aoo_aŽ‚ÂÌÎ;™={6?üðƒÅV9yò$ggg:tèÀ²eˈ‹‹³»8Àƒ>Xß»®pHJJ¢°°Ðò·NNN\¸pÜÜ\V¬XÁîÝ»¹ë®» !-- +++>øà‚ƒƒèÚµ+ß}÷|òÉ'– Þþýû9qâD‹ÉdbÞ¼yÄÅÅñÎ;ï`ooÑhäСCx{{ckkK—.]Xµj………¸¸¸OBB;v¬ïBá*ÈËËãüùóøûûWZu¢'‘ŸŸOnn.666´iÓ¦Â뉉‰lÚ´‰;w¢ÓéhÑ¢|ð!!!¨Õj’’’0 –͹sçØ»wïUë¯Ô©ÃŠ‹‹ ¯¿þ:=zô ;;›µk×òàƒâææ†››!!!|ùå—ÜÿýìØ±{{û«öÊÍfÈΆýûaÃ8}ZËùó»±³[ÍéÓ­ º“óçÏ3sæLúôéÃþMëÐüû1ý|ü9ü¤‰_0èõø:8€ƒýú5gRûjøbm+²O¿Ê˜ûŠpv$´9ìX_ÄÊSðq-¦÷#Á º×• ¢£aÿþ¶l±¥];/Äž>ybb (Z·ë£GáÐ!²ßžŠÑÑ7#Xµn wÞ ß}ÅÅtìÎûïÚà–O4ûÀ'’çÚ…s]Èßw÷v<Ž13 §ãÇ oßuBú]ûHÚMÊ£È,ÐS°d!.GblÀQ§öìc5ѧOðßì œüna8sæS_ŸÂ[®.ÌHß͹Ì~Lü¹-÷¸«ÑéÄ×]µ ÖæµÄã%§Oƒ×qqƒ›OÁüÅC~ØÚºbcãÀ’%jœœÄ†÷÷—cÎÌ„%K m[ع³ùùí¸#ú÷ï&¨Æ†“mã…œ3!/ONC¯^Э[åŸyiEН¯këÚ q])vvvtîÜ™ï¾ûŽŒŒ \]]Y¿~=†þýûS\\ÌòåË™9s&;vdñâÅ´lÙòšgX ™:u* ôéÓ‡V­ZñÓO?a6›™9s&ÞÞX´‚=Àrà93âÄê€0à8sànî`Öÿ k$zÃ`gÅäc~¤<Ð u`sìýÝáï_(ÊL!ºS'\5"ÈÓ×iÓÐÙÚ’о¼ƒ‚°]¿Þx´Z0«þýéN§½{±Z¶ þü6„õ르ChÞ\N޽½dXcc%‹ ²®yó¤Ö_¥’ Ï A²''Y¦Y3xñE¹¡”d]<ÇmÛÓ®¬›’”ƒqxôòcÖ7ñó»´qÚh”Œòùó’ÁnÐ@ôb||dßAþR™YÅÅpú´$™½½!.Nü hÜX*¥ïºK—ó¶lÙ‚³³söưeËV¯^M~~>:t`ðàÁa6›9yò$óæÍ#11‘N:qÏ=÷аaÃ*×—••ÅßÿÍ„ j´}“ÉÄܹsÙºu+O=õ[·nåàÁƒôë×ûï¿'³ÌöÏj!~¥IvþÉ'åƒ|óMÉh7Ž„i@c è´JïM@ZädƒoC8 Øé@ÐØÍ…b'°SË:œÌ°*6¬÷áÐØš§Àï@çLxó98ï Q§!'²2àÁ^`v‚”$p1€àå.eq±\z½8¤Í›Ë…V ;—¥å†o¿…)ßÀ9$³\òo}“x–û; P) Ðó÷š¿éÞ½»eÔM]žžÎ?ÿüÃÎ;Q©TtéÒ…áÇãêêŠÑhdÇŽ,Y²­VK÷îÝ6lXµ‚ qqqìÝ»—#FÔ×YV¨CŒF#III?~œøøx>LFFNNNèt:T*†¼¼<œœœpvvfÚ´iuº111,]º”“'OâèèÈÝwßMïÞ½-¶JBB .䨱c4mÚ”#FЬY³*m•Ò,Ü…]·ngÏžÄY*U¡OKK£ÿþôïßgggÌf3‡ÆÙÙ™&MšÔ˾pèСKt *•ªJ„Ò̧››[…{£V«eþüù¬[·Ž:°gÏÜÜÜpuu%''‡¤¤$4h€½½½¥õa„ ´iÓæº‰ÛÅÆÆ²ÿ~î»ï¾:=·{÷îeÍš5DGGãççÇ}÷ÝGxx8666˜L&Nž<Éï¿ÿn™»=tèÐj…:„V«¥sçÎuzWKff&—Õ¹Ñét,^¼˜íÛ·ceeE£F. ~äççsæÌt:O=õ:tÀÊÊŠäädNž<É¿ÿþK\\®®®ôéÓ‡^½zYÖ¡×ë9qâÇ·´P5mÚ´ÖšA$''‡;ï¼óеÎV³ÙŒÉdB¯×[~”.Žæ † Š¢Õq9‡µ @œÔ—^«VýÍ_ýŧŸ~Н¯/†¤$ò_z V‹ãÛoK&¦šÁ«¥J©ýõ+W®¤cÇŽôïߟ]»v±oßžþyZ´h‰•ÚŒY¯'>AÍ'Ó¬qrŠ'vÏ—|6ØŸŒƒûùôpîw¾JÁ…Þ ÿ‹@‡tòSòù3ìbc¡G©.Ô餺÷Ày¸»‹ î½÷&rúôvΜ9Cll itèЖAƒî¦U«V¨ÕölÝjM~~1K—Æ}ú(M›Eñü C‰ˆhƒJeɤB­–ªH++q4õz0ääcU\€ÑÓ++ÐéÌäääãáa“SÝ$åÍfqRF 4XYÉC¥’¿/çô–Rkéu¢Óé0›ÍØØØ\ò£ª×ë1•¾v1µuXwíÚÅ—_~ÉÔO¦à€1ň.A‡m#[Ô›ÔâèEàk°)€æÈEÖ»·\tVV2çiÆ ˜=̶ðîˆ> ZItÅÛ[JÊ¿ü$Ý=q¢|h¿ü"‘ WW1š„‚0¶HÆULPlsÉ9ÀZd$Á!pÕ@Àd#YÝhÄYn l@Ê–Ï"N²GÉúK“1ç÷’eâæ@∶.††Vàd™f˜¶NÙ@ßp((YÏ^`4R]zÙ§kçý0¦d{}@ÊùòÂ’÷ä•ì§WÉy¨ pøH@Àæ’c¬c¤‘[wÐâ­x7¬[¡‹Òû8ˆØFyC½üõ±Šse(ëÍKff&xxxàééYá5NÇòåË9pà‰‰‰¸:º’u: ­^‹*NEøðp"hݺ5 °M¶Å¬2cld$99///ôz=kÖ¬©ñýïZQ[ÅÚÚú¡‘‹©o‡µ¸¸˜~ø;vàëë+šZ-jµ;;;‚‚‚ðôôdÙ²eìÛ·RRR0™LÆÐ¡C±¶¶æøñãÄÄÄàêêŠN§#<<œfÍš]±Š½Ñh$!!µk×’ššJDD5âÀüóÏ?4hЀŒŒ ¼¼¼ðõõ%%%…øøx¬¬¬,ãÉ\\\pssÃÊÊŠŸŸoÉét:¼¼¼ð÷÷'##À¢ˆ[XXHtt4yyy4nÜØÒw‡££#!!!•~ö×’úrXÍf³eôžZ­®T¯´±&¶Êâ°–NHMM%77—V­ZY²à¥e©f³™ÔÔT–,YºuëÐh4¸ººâïïÏ!Ch×®%+¸ÿ~‹2~Ue´&“‰””,X@Æ éÓ§eÙ¬¬,Ë$“ââb‰ŽŽ&99™ððpzôèÉÉÉDGG³oß>âââHJJB¯×Ó AhÙ²%;wÆÖÖ–´´4:Äž={桇Âl6“žžN||<þþþŽÕÖÖ–fÍšU86 hµZlllj>Ôdm™¬,©8 ¬Ðbu1×Âa­Ó’`À«î¯ÉÍ¿¦?.e«M›Bll"?ÿü3ï¾û®%em£Õâ>h(+•özVscR©T899ñÐC1|øpœJÊ›7o޽½=o¿ýO>ù$Ý»wÇÉɉ"}4çÎàôi/~úéaü»‡á”›KÊýÿa@ç}ÜÕ±~Ç!ǀ˃£ßP¢!111ìߟC\\âKhh Nœ8Ã{ï-¢uëÖôë×Aƒ\hܸ±Eð¦”Áƒ6¬1QQZ7îÉÌÌò”:…Ø9!Þ`o¯ÂÕõêä¨k‹JusWSªTªjëõ/. ºVÄÅÅñÅô/x{èÛ8/ @§M¼öNö0ðºVKálcèØQÊ\/¦CéŸÖhĹk‚³6‘&å´ÞÞàç'3 üüÊÊfml¤–;5Uj½œ$XY0ÎZ NånpÎÀ#ÖPú’¿«c8â Æ#1€"eä"Ž®+r§3G]À ;ùÛ8 ØFÂË@gÄé4 ¥Í#Îb â”NG2ÌO÷#Žè)¤Lú^À tAMCɾœAú„ÛûJÖ7¦äßáˆó‹8ì¯^,°xx¨äØ ç99§=Áœi¦è|fUÆP«ÕU^ã—»þ*!H:]áûõHi¾û¾¿–FV­ZÅ®Ÿv¡ÑkØkÚKÆ 4h}úôA­VóóÏ?³oÕ>&„LÀ%ݯ^8žrÄñ G4›4Œ 4E‚Q“kûMpï&’™™Y/%ªum«\OL&K–,áäÉ“Lš4‰–-[VD %::šóçÏL“&MÈÌÌdõêÕL™2///š6mJDD&“‰¬¬,–-[ƹsçèÒ¥ wÜq‡EÓ //øøxL%£åT*Í›7§U«VÃ8..ŽE‹±mÛ6ºwïN›6mرc‡e^í›o¾Ixx8ÙÙÙDGGSTT„»»;AAA¤¥¥‘Mff&ÉÉÉFžzê)KY·Ùl&++‹øøx˾ôìÙÓ"6äääDxxø%çáº(ÝÆÄHùYZøúJ5P|<®óæá\²?u‰J¥ºì5\c¦ŽIJJ"!!ÐÐPËgY:«ü›o¾¡yóætëÖ gggΞ=Ëüùóqrr²´f?žƒÎçŸNƒ ˆg÷îÝLŸ>ððpK{—F£ÁÓÓ“ü‘ž={òðÃ_bKïÚµ‹éÓ§Ó¦MX¼x1;v$!!èèh\\\$If0àííMÓ¦Miݺ5[¶lá·ß~£Q£F¤§§ãïïOdd$}úô!88ƒÁ@^^III:tˆ¯¾ú £Ñˆ‡‡íÛ·çõ×_§M›6W5) F÷±¿þ‚;DdÀÉþø£h{„„HÂ⢀e…m`u•£›ê<Ãz­¹\†õ知µW¯Bþïÿþ>}úpoïÞRsÚ®] äzkÇþýûY¹r%‡ÆÊÊ [[[LïÞðñq³,wäÈ>þøcK$Q£Ñ°{÷nâãã-ÏÒ/¢——ÎÎΜ?žS§NáââÂÓO?}}Kcb$[fe))pÇ×o[בúʰ^Kj“a÷æVýîGA[/T3¯¿¤£swMÅ Ìš5Rþº`(ÏÞ®ü¾|;@G_•ªŠàR삈M]Œéõ]Ü,!eÑ­'¢ü­&XŠ”úþ„8Õƒ‘,ª Q`ö rG¿¥cmêº$øZS'V= …dË¢©[S dø#纮|¢ )—/½&N‘ëç>`²oÉÀNäú)!ªê/$¨â8»o#A—Ê[8qâóžÏÀÈt1tAí©–€Ð è ‡NâìÙ³$&&’M“&M %44´‚²snn.gvŸ!-!Q'H<–HÓSM1z޼Ѭ'ZÍŸþÉîÝ»±RYiÉëþOas: îÐÀÓmÁÕVÚôzØ“¶Á0Ûž5B›<0k`N»ÂjŠvÌeóý üòË:ú€®×;úuëV~ÿýw&Ož|I¿øž={˜6m_~ùåu»Oäåå±dÉ’’’*<_:ÊL«Õ’’’BBB©©©‘™™Iqq1ÇgРAW=§±^0™Ä?|X$ýýeâ‚’-1B9U* GGK©Ü«¯Bp0ÄÇ“þ÷ßì±·gУÖ÷Ñ\u‘a5 lÙ²…Ù³gãîîNff&YYYXYYYtpžxâ ‹ÐU)f³™;wòï¿ÿbooŸŸÝ»w¯ ^ŠV«eÖ¬YDEEñÔSOŽZ­æÂ… ,]º”7âåå…e¶²^¯çí·ß¦y‰VFi–·aÆ„……U[nœššJtt4íÛ·¿1û÷ËõüàƒâPUUI¡ÓIÕÝÉ“¢ù1a‚föï'õÓO¹0r$÷ßÅ»q㇯‚ôt8qî½×ÌæÍ›ÑiµÜí寽&'³’¨ÚÕÒ¾}{Ú·oO^^éééøøøàPI/]›6m˜qIqt ëÂà»ã¸Æ‘ƒâžàŽ«•+½zã=Л†ãÂ@` Øìµ¡Åøüßÿý™I™$ý“DÓåÁØäMƒp´Ž›’/Ɔ °zµT`<õ|ãêtxe¢8²M ïë°ÆÓ¾æfÔ÷UtÃb4Ù¸q#?üð5bÒ¤I¼ÿþûÍ„¬¬,fÏžÍØ±c¯ë|LggçUõz=.\ -- WWWoîjŒC‡`Ú4,Í’ví*: z½dTKyÿýKß@ÁСïß_ßGrÃSê¬Îš5‹wÞy‡6mÚ`4ÉÍ͵”‡We;«T*î¸ãî¨-kkkË /¼€^¯¯àhúûûóÜsÏ1nÜ8HII±ôØûúúZ2½ *ÒǯÑqy{{×ÏìZ­VœLF’w¥YÚÌL °h4Rк5¼óNY%]Uh4"xyà€” —.Nâk¯‘“ŸU»{K;¬ÇŽÉÈN•*9sæ0ù•WpܽFŞ눳³sµÑBµZm™ÿxC 3gŠêé+¯Ô÷Þ(\†‚3?½CLJ5t~Ä++ˆh§"y|Œ~›°Ú²¥Lˆè¿ÿ­ïݽ1èÞ]ä¦7o†Ñ£ëgÆ©=’iS¸>ÿS¢‰%-–0?f>Ͼò,:ŽW¼Âç>ÇCãvƒ–Üɹxµö’Õ†¢´=gÎìvÛ1L5Œ4c-;¶Äêe«ª·•‹”¶Æ#YòµHð¢RR8¢#eã? åìo#O€Ÿ©Höu*P™3¸ÜÿÛA ³ÕqìØ1¶è·`wÐŽˆ Œ~d46½lèàÒ>ü€U3WѬ™lèàþƒtîÎÞÀ~µ½ôx÷»fßC  ¦€ìÍÙÄœˆ!®Q_ëŒ_w?TV•¤¢' U¿:\MƒŸÐàŽð«ÎYøòÛ‡’G|¤ÄÌÆÆ¢ÂÍ`“Ýçè¼ú¾’n8rrr8uê;vì`Ïž=|øá‡„„„ðý÷ßóÚk¯ñÌ3Ïpþüy¶nÝJdd¤eÌT}cccCPP¥¤÷¦'/Þ~[¿—V2Ùۋ¼Â5¡täÎÊ•+9~ü8|ð-Z´Ä–ö¬¦õJ©®ÀÅÅåÆULNK“±zËãâRß3g$Cêè(É‹_-£×«—8­O?-×r×®2³63ÔÝÜ OŸŠÏY[—Þ¼ nY‡õÂøûo hýñÇ"ºtéBëŽE´¾³—7ÞÞ0fŒ4’†„Ô÷Þ(\† ™˜»/‰Í?µÃêôIرóÀqÄd¹R4axÅÀØMÐsU'´i#Në²e Q¸50 Îã<À ôzV5]ÅŠÍ+xÿý÷iÓ¦ ÅÅÅìÛ· 0bĦþ‚žÖ«[ÓoE?üžócïï{±>hͽÁ÷’ugK¢—ÐpYCî»û>\[ºŠ1£GJÆ€™ˆ#ºS¶Kà-¤œ·²j°.Hæ4é-GÊÖŠTE¤Lå|ÒyN-=EVV­Zµ¢uëÖx{{ãäädéWÒétÄÛdz{ùnÖ­[‡ Ý»w§Ëô.bc'5Ç^x1eÊNž<ɹsçÈÏÏgÂ#èÔ©v;„8Õj¤Ì8ÇŒc¾=ŽSñòwCe(ÀÆÊ òÊ´–/çÒÎ:u‚0-~,‚€CÒrãì'†|M¹XyÒ ž( é駱¯ã'// °nÝ:üýýiÛ¶-Ÿ|ò <üðÃØÛÛ³|ùrZ´hÁOù$Mš4ÁÕÕÕ¢Ž;`ÀòóóIMMeÍš5¼óÎ;h4î¿ÿ~^zé%ÜÝÝ/¯i6‹!ïá!Qù)SÄ@jØPzÚ½½¥æ³Ïä;q÷Ýò¾˜4In$åçûõí+ 'Õzw”Gio”Â5áܹs¼ÿþû´oßžGyä’Y‹·>žÙ³g“››Ë{ï½GhhèU©àÞpdfJ /8X®é­[¥zÏøðCy~ýz3|xYÀÄlÇÓÎN|™ž=%Kêáqét+«ŠŽçÔ÷Q_5·¬Ãêå%Ÿybb"íÒÒ$q‘Á¢ p³S|füc¦Ðk!!ƒ 8Pn\j5ööФIÙXa…JP«k6ÐWáÆÄ€8ª d\PÄ$Ç0cò 233ùàƒ©¢­áâçU*¾¾¾U+©jÀõ W^þéeˆÝpVç¬X½z5/ûkkk|||èÓ§ÉÉÉÌ;[[[lll(((@­V£V«ÉÉÉ!,,ŒçŸ¾Ò‘£V«qqqÁÅÅ…¦M›2nÜ8lllj7è>'>ùDúd432¤¯tDƒ^/c®Ú´)3’ì쮬OqV¯ÉÉɼ÷Þ{Œ3†¾}û^—‘h7,9"eƒI™cÛ¶ðŸÿÀ¾}Ö„)' €‹wUªŠ—êP©”²¤zâøñãüïÿ£C‡Lž<ùÆTÍ­)ZmÅê­ÂBX¹RJs[·†×_—k­¸XîÁS¦Èµ RšþÓOH,-;×éDàkøp©s¯£f7·¬ÃºiŒ'OžÄÛß_²«JÙŸÂ-FöyP¹žænï|4¹¹ U* Ð×÷^*(\'þ™§û "fÔvìØÁÔ©Sy衇8p`¥*íWŒ é;ô†Žži×®ù% ˆh4Ìf3:½^È,L•JeyØÛÛ_qÖÀD¨ÁÇGŒð³gE@,?_J‹ÆŒ‘ѽz•Þ‹‹1Tú;èêZ樖Ү]]|j µ 99™·Þz‹ž={r÷ÝwßZ™&“IJml¤4÷×_e¼C¯^’½·µ…>’1{#F@©P“¿? &ê÷¥ÂÿþÏ?¯TÒݤ¬_¿žÙ³góä“OÒ³gÏ›#0c6C|<ÄÆJ©y@€8™'OÂÇËsJ`¥¨²³¥d·aC –«T¯ãRÚ´ÁÓÒû8È÷ )IúNoCnY‡µm[©öûñÇhÂyD. …[Œ>ƒ]©[yÝpBn†å°¶–ï@ZÚõ×ÍJL”ûhxxÕ£FصKZ.ÜÜä^›+öut´hÜyg}ŸQ…›†4à 0‹’nZZ_}õ'N¤gÏž×Ǹ×PQ¥¼îv‘‘¬R©°µµ½ö#;æÏ—þ:??1Î7–rÇ~ý¤¬m[1¢–-“|·nbÌoÛ&YUU] œU¸ZrssùøãéÖ­cÇŽ½uœÕœÉ4ýû¯he”öU7i"?" ”U¾¼ø¢e.îë³¶®XÚ»c‡|BCëû讀C‡1gÎÞxã """nükÝ è߃C‡Dœ«¸† £iS˜66ž‚z™µžê ­ÏëDà·ªçÀGFŠÂz)yy¸©jï-Ä-é°ÆÄHù÷˜1 =q‚†ÿùO}ï’‚Â5§(ÖêæsÇ–a"|rñ2Er/½Žs¼‰‹ƒçžÇsëV±•;u’PR’ÿüSì={ä~Þ½»¼¯¸Xvv0w®,s›U¹(\ &`0 ™a 1uêT @¯^½,ýŸ7çÎID>:î½W¢ô»w÷ߊzÇ2Ž Ä˜ÿ䓲=\*œa6ËòË–‰Ãjo/#cnt#P¡{öìA«Õ2vìØÚ•ßHüï°¿ü(<òˆTüò‹”ú>÷œö %÷Ýwéû]\ª^·V ¿ý&,­V87s émÊáÇyÿý÷yûí·i×®]ýÞ»3ãˆò»â%iö“ÈoOÂZØßî÷ƒX¸w(¼6DF”©T°ØdÖžàÜ <‘™ÛHõŽ’ÍÀ d¼]›’mä€d ˆ´ƒø>žvånN×ÂV©ŽÕ«WãââBÏÚªÒG²4¹Hf(8‹8›-€ƒˆ¡» ˆA ëd ”òÝR‘%Ï?[òïNàw H€­Ó!´%4»šƒ›¢ö²•pX Ã^„Þ&MשH†*ð´c6 ø hR²ownLWb”û!ŽE&27¸Ø îßM“q45=ÿÙˆ£îJÕå˜U¡G ó[Œ¸¸8ŠŠŠh^®?Ò`0púôirss ÀÏÏïš–êšL&-ZDDD÷Þ{oݰV+?ôn>pT§€8`|18ÿ#•ÈðÇR)_ÏÈ2°  Ç(xú~1<\áþ’u^É!8*y¾iéTrí¿ö°ÌV ‡q1°ùÎø ß«"`=Ð؈|WZ!ß—†È= pDîíö’ç/ ×x>rÈ:!Yã`$âl[÷ Nõo%î%ïi|^r\C€c`kGNÓœ«úÈêÍaÕjµÌ™3‡ƒ²`ÁËó+V¬à÷ßG§Ó¡V«:t(£G®U„ñðaèÑr–$¥C‚±%…zÀl6süøq&NœÈôéÓ騱#EEEÌ;—5kÖ23ïá‡fàÀµZ·^ Æ0ÄãåèX¥’ž££”áN˜pékÅÅôÎÈÞÒ¢"®ÛµKÚ†Ê劋EÈlÕ*±{SSáèQqDæšÐ±£¬37·ê*0£Qì­VþmÔH*Éj"èX:–¬¸X²¸åm³Y'çÌ‘Š²À@™€àã#6~©^‚F#Uk‹ÁÒ¥’»\Gi"âZb6K81²³ëÏz2›Í¬\¹’/¾ø‚ 6`ooOzz:_ý5ÀÊÊ 777^}õUZµjum6jþ€äÞÉlܸ‘É“'ãáá­­-þþþµ_ŸÁ e¥cXÄÙ¾].01R¬­¥Oî?Dæá‡¥t 'G¾dƒ\ˆíÛË:–-“/M»v"´ ë>\J¼¼®ÿd2‰±•ž®”J^!ÅÅÅ|ÿý÷;vŒßÿÝòü²e˘?>:+++†ʨQ£®I6433“?þøƒ—_~¹ò´ˆSYþ#f Ža_¤¬0ØŽ‘ÒÄÖˆë‹dF<ïTb¬ÞUòœØ|ìCØ'ó#w8û ¤¦Ãf½d[¶©àˆ+èÁ3-@í&ÆóVÄ1ìƒdòc» bL§–ËbDDÍ1’W›g·kÉþY{‡±/âD6‡ÜG`¶ZœXg$3$"F¹=ÒBеäïsˆž‡d‚† κuɺ‹J¶w®äy•¬+qºû•O ÇeÞ褥¥ññÇÓ°aC&MšH‹Å/¿üš5k,"qãÆ£ù9žWINN;wîdòäÉ×÷³ì翈#v'| ¾ùœ_‡xÃF›á³/D@iÒ$©Vª l<Œ|Oâ€ÕÀnàq`4ê‚|@>ª’c/D®sO 9r­oGœÚ6Èõ_ê7(ù»â7¢Dñ¯Àë@,r?òF¾w?¿¶`rºúùŠõæ°nݺ•yóæÑ°\ßMRR_|ñ#GŽä?ÿù»wïfÒ¤I4oÞœ®]»ÖxÝnnРAŸ$'3³ä˧ P×”–º¤¦¦b0Ècÿþýüúë¯L™2…®]»òã?òé§ŸÒ¹sgúˆ3fðÙgŸát-FEcž‘Ÿṵ̈aÃhß¾ýÕ­oãF)),.–z¿~ò…HJ‚+¤þûå—Å8ññ‘Ÿ²¨ŠJ%™Ósç$BÔ¤‰\,Ç_:û®Aƒ JÞ×½¶l‘(SM‡Ñ+T`óæÍ,X°€Àre"¥¶Êƒ>ȸqãØ¹s'ÿýïiÙ²%J„®‚ÿýš5kVù[€£ˆ:¶=b¸.A2<]¨¾ ¯i%ÏY!N™›6lMˆô–©EƸ#Un<÷Ü_9ÁžŽe¢1ÃÕpª¥¬åïqC,i$Púuè‚8íJöÙX²ý·K–Ë/ÙÏ7ã»ü-®ü´šá@‘5´í.†¸sɲ1ˆW²­>%Ëj‘ì7â êGæGÄYwBþÂÎÀÄé(Y>¢ä>A²Pƒ®ú£¾!øå—_زe ÷•ë!Þ³g¿ýö~ø!:uâûï¿gêÔ©têÔÉR-vµ,[¶ŒæÍ›z=…²NŸMŽƒ—ôð“€Æö0bäï…ð y—<ïâ"ãeJïÓÎÎ×W¤&h4p×]—>ï‚8™m.óþªb£¥ßÓ«½eY!ß›òÂÙ‡å'4<ޱ£…öꂦuné˜ÍfN:Åï¿ÿNçÎIHH°¼¶wï^<==¹çž{°³³£S§N„……±uëÖ;¬pæ „·ŒÅjå((\+ ?þø#~~~žß¾};‘‘‘tîÜ;;;† ÂÚµkÙ³g*“6¯‚âbˆK2Ó³ð8ÅczU»ll¬¨®7.×K#ëø¿ÿ»Ôáš0AZŒll$9ô÷ßb‹?úèõ·µGŒï®»dÙáÃp÷ݲÿ ˆ“ú¿ÿI&¸o_q¦=<àƒDÞÉIþ>yRÄT›4" @œÅ~ý$»:eŠ8“¥ñ²ÂBɜִbÒÞyFJ˜‡¿ÔÈË-ôtèä;wJEÏOˆ{%•UCYuÒóσ··™Í›‹j¿¢k@ZZ_ý5íÛ·gÅŠ€8¬Û¶mcàÀ#dÔ¨Q¼÷Þ{DGG×hæhµÄQ;8–}ó÷ñãįþ@"#Å8×hÄ9É~>ö˜ôÅ eåM+±ö]\$Ûz17BFÓÖÞxCÊj…Ùl&**Š бcGRRR,¯íÙ³ooo† ‚]ºt¡uëÖlݺõªV£ÑȪU«9r$ö•Ý HYŸ°ɘ®GÊù:Q³ž1N¢–¥ÕgF£^ŒF‰Λ'?/¾ƒ=DMïõež½8oÛÏöˆCw1%ò4¤bù¤0h F2¡>Ô¬¯Õ),Og ¸ä\T÷5Ô rs$Ûj¦¬w×ÉJš’çMÀ$`ð'Ðq–)ëA¬ fÄ.›d¬‹ë>ðh2™Ø¹s'G%88¸ÂkÛ·o§C‡tìØ;;;†ʆ سgÏ5ɲÆÇdzbÅ >ÿüó+/¥/í«^‹œÿæˆãd‡d÷§Ãš|x<’ÏÁ‚ .ž~Þ÷œAÓK¾ *•<žy¦Î?‡› ­Ö­+-M‚ÿ»w‹­eo/íêžž²ÜäÉ’ öö;;&ÓÕµÕù7Äd21gÎ"##qtt¬à°ž:u 777¼K,hFC‹-Ø·o_ן—'Zžö3ÌËëÆßP¸eù÷ß9yò$ï¼óþù§åùãÇÓ¡CKÙ˜··7¾¾¾;v¬V«6ô ЧÚ`W®¼*Ê;¬ÙÙ"2:fLåÙAkkq²æÎ•±w§NIuL]$†BCÅ&úé' lNŸ.ÿnÙ"vÒCU§lk+I±ÐP)‘]°@ú×7o–,m‡•ÏŠïÓG²£¥ë† µ+ÛU«å½Ÿ~ ]ºÈ¶ÓÓ%›ëí-A‚âbq*KcmÚH6xóf ”VŠÊ>–$áéÕ«ò}ÑjeÜæ–-2oÜ×WhõÅ_ý…F£aèСÖ“'OòÈ#X–kÖ¬Z­–øøø«wXZÁ¦ÌM´oßç+íñÌÏ—úö«Ïzj47†ãy5”WV¨1ƒ9sæÐ¡C4 Ë—/·¼…»»;^%eݶ¶¶´hтÇ_õvcbbHOO¯ÚñÕ"ŽêûˆHÌHਹE7gŽ4ç÷è!ÆúæÍrƒíÙSŒùÇ“›XiEÄ… ðÚk2bãz)Í©gãZ`«Me¶#U+ZSñ¼ª‘=€Ù”ò'Þ É\e#Ž,HntÉ¿)%g¤DÕœ‹qjP÷²¯ÉÉÉ|ûí·<þøãüñÇ^;~ü8]»vµŒåòññÁÛÛ›'N\‡uåÊ•´k׎F•‰^Ô„b`!"XÔÉâE‚#ÉFèvþWwúHŸ¶z4 …½{å× R*OjÃwßIŒ¶S'ñï6{ÑÙ¾ÿ^nÿ÷ÒZ6~¼$ ¬¬@§Ë''G{UÛ®S‡Õ`00þ|ŠŠŠ=zt…ñ+++˰`+++\]]IKK«v½éééüõ×_Œ;Î??0G%¢eKÅa½MÑëõlÛ¶­[·Öº?ôj‰ŠŠâ«¯¾âùçŸ'  bh9//Fc.°³³³ôýUGll,üñýúõÃÝÝM´sg¾‹_]FѨtÖz)›6‰Õ½{Õï4H°Çƒwß­™hÒµÀÚZ¢sjµÜìJm£ÊªaJQ«¥\Ùd’”VVÒ[Zڢئ$Nž¼´zórxxˆØÔ”)âtÞ¿1ùùÉ>”Žë)OX˜D"×­“*Ò£G%À!û¾t©ìOïÞeï5àĉ2'þw¤|º  €þù‡Ã‡תeâj1™LlÚ´‰íÛ·3iÒ$²³³+¼žŸŸ_!3äââ‚Á` //¯ÚõîÝ»[[[ piĽ˜ ‚ÂV…l}a+¯¼òÊ•ÄÚµb¤ºEjúna,XP!»Y æÍ›‡N§cÔ¨Q‚Ž ×¸µµu[ÅÅÅ¥Z[Ål6óï¿ÿL·nݪ\fÛ¶m– œJ9ŽôŸ %ÁÝñ5±»‹‹ÅY=wNnxƒÜŒ~ø>ü°l9›ŠÕ#G*%åÓééé‰,@Ê„!=“ˆ…‡8¹ÛJþÝNYOï³UÅœ¹sðp¨Ûj@NÇÌ™3iÕªwÜqÇ%k^^¶¶¶[ÅÞÞ;;»jmNǪU«ðôô¤ieÕ(å8{ö,=ôPíwü,Òß|¾ä¾Š”r«€Ô,°w‡ZøË:À`UbH´h!…Z£×K…[a!üç?•ë>ý4¬^-íJ~~R§V‹M¼bÅŠ«®>©S‡õøñã,\¸©S§Z²¨5Á\*Í_ 4 k×®¸ºº+õÒ™ßÅ6BqXoWlllèÓ§O…H] ×ëùé§Ÿ £K—.ƽïr×xPP”󨎂žáž{›^Vµ¯qc±S@œÐcÇà…ª·?ìíEtÑÎNÊoë •J2¦*UíùjuÅìku„†Šsâèúû_YÕd` ”P·m[±Çµºãst”2bÍžòLœ(ðÞ½’MNL”ìø¹s`èׯ¬uÒÑÑ‘áÇ£R©,ê¼uAff&ßÿ=£G¦Y³fìÙ³ç²ï1›Í—½Æ;vìÈ!C*1é+›;÷îÄÇLJ–WŒ—î÷߯<ý®pCQYpûzsôèQ/^ÌÔ©S-YÔšPÝ5®R©èÒ¥K•Î*ˆåøOu³ã‹Á«’GÇZX~¾Ü(ß~["n:ÌézüñÊËÝKQœÕK)/z¥¡Lm¸ª8Ú€‹þ-ÁÝËÆ?Àþýûël×M&k×®%>>ž©S§Öª$·ºk\£Ñ0pàÀË:«YYYµ(+UŒžƒˆ‚½HÅlüéÓðõ×Ò4Ð z]¾$\Š¿þ‚æÍe4¡««$:JEÑ ¥²kþ|øê«ªÅëmmeŠU¿~r›Q[â-2d99u¬l2™ˆ‹‹ãàÁƒ„……Ñ´iSŒF#Ë–-㯿þÂ`0бcGÆŒƒO…÷.X°½^Ï·ß~ ÀùóçINNæÅ_äÉ'ŸÄÎΓɄÁ`ÀÚÚ“ÉDaa!¾µ°$£¢Ä(<Þý|==Qb) uÉø÷ß åå—_Æde´¯¿þš¨¨(Ôj5ƒ“É„Z­F§Ó¡Óé.ÉÄ^Ï6;º—æ­.?F¥’›É$}”aa5›uêä$­yu=k´.l£  ²¬qADkC³àî.%Á× GGñ£¾þÖ¬GÚÓS’!7Ê͵k×’˜˜ÈÚµkÙ´i™™™¼öÚkÜ}÷ÝØÙÙ¡Óé,Ëbkk{uãfÎý È¦ˆ?ÿü“GyäÊQ ŠŠX]Š)ÜTÌŸ?½^Ï7ß|À¹sç¸pá/¾ø"O?ý4vvvÆ«²U*###ƒŒŒŒKú -äß_ÖrÅ&“dS==E¡®ôF¢ÑHŸviÿžÂmAff&óçÏÇ`0ðñÇ’&>rä†I“&ñÒK/aoo^¯¯`«èõúKìú«¡Æ-¹H¿ðàMÄa-o—$%Áÿ+©¿Ò ä5]|#“š*ÙÏæÍeÚHþ̱㼼äëú´¼—.•аíÛ¥-iÐ I<ûùIÅWr²ès9"U`mÛJýÕWk6i­&Áû+¡ÖkTTo¼ñééé¼ûî»4mÚ”ýû÷óÁ„¯¯/‹/&11‘·ß~WWWË{{÷î]A8??Ÿ´´4BCCqpp eË–™JëD27‡56VJ_Ÿ{®f›¹•mooщ‹“¾w›Ë§©+4xé¥úÞ‹ªiÕª£F²ü˜˜Èž={hÚ´)^^^´nÝš¨¨(zõ1°3gÎ`eeU«LܰFHIM¡¸¸¸vª’:¤ªwí’ž½€€º)£pÓÒ§OŸ ªÀ¹¹¹dddXl•Ö­[sôèQÒÓÓñõõE«ÕrêÔ©ZÙ*•±cÇ"##+ØM”&´THiüýȸ‰š`6‹Òòå2/졇.ÖuDR¡Þ±··gøðáJíOŸ>½½=!!!ØØØFLL :;;;RRRHMM­•ÖFu¤¥¥Yúc«ÄŒŒ[™„¨MOBœÕ‹Ñé`È饹U–ŒF‰?|¥×¬¿gǯ?~\œÒ† er‚Á ÚgÎÈ߈`¥$/JE)K“ì-[–œz³8¯wÞ)ÓÝÆ«ï#¯¥ÃšŸŸÏ'Ÿ|B£FøöÛoñ÷÷§¸¸˜?þøƒÐÐP¦OŸŽŸŸ»wïfâĉœ9s†Ê&âÞ}÷ÝÜ}÷Ý–¿øá’’’x®Ä‚vttä»ï¾cíÚµÜ{ï½;vŒƒòÅ_ÔxW¬€§ÊÇ#3—ª†9*(\'yâ‰',ët:f͚ŰaÃèÚµ+îîîLš4‰ƒÒºukÖ®]Kff&wUפy1éCAÆèÕÀêõ°¿”[[×\ ÷VF­–¾Ø„©ˆ»óN¥ê­¦DDDaù{Ïž=,]ºÔR%SÚ¯r÷ÝwãààÀâÅ‹ $,,ìÊ6˜ ÆÁÞ¿÷Ò´iSkSÊûÙg©éÜùÒ¦b…J¸Ø(Ÿ={6ééé[ÅÎÎŽo¿ý–uëÖ1lØ0Ž9ÂáÇyì±Ç®x›ÅÅŬX±‚·Þz«¬Í£X‡¨æz#â>é—YQ|¼(´5m*å#ï¿/ÿ¾ñ†r“SÄÖ9rd…çNž<‰‡‡>*sƒúöíËÿû_:DË–-Y³f 999µ³Uª@¯×£Ñh.o£_@2ªÃé‹/ߢ"¹§]*Öq‹²|¹aº¹I¿hÇŽÒâUÚfT™®aÏž•¯«T¿2T*y½ºeêšZ9¬111dddðè£Z´§¥¥qæÌî¾ûnK©@Ë–- fß¾}Ö‹qppÀ³ÜÙðòòâÑGå×_eãÆäææòÀвÔå¿ F£¤·S÷Òäða¬Ç¯ïó« €··7š¥Ñ¶mÛ2tèPËLÊ‚‚ž}öÙZͧ4Å€»Ášü;›£«Ãjk+ѲíÛEf\ ¨ 2×5!Al9…+ÃÆÆÆ¢I R©¸çž{8yò$¯¿þ:ƒÁÀo¼Q»~¥òœz‚ÉÚÄæÍ›;vlõ=»ÅÅ¢³_*ý ·†Ú¯B½áèèXaDž··7>ú(¿ÿþ;ëׯ'//Q£FѼyó+ÞFtt4vvv«3€]ˆ¸Ì.é´PT$bb¿þ*𥣚î¿BBê¤Þdºµ+sne\]]+”è¶k׎Áƒóé§ŸZl•gžy¦vÁÂ*ˆÅÑÑÑbUJ:°Q¿î hK$—¤Z&!AÆ-½óNµwJ©lß¾µ›*Pf³¬óÀI$8 ú r˜îî25 ôçÎlòî»e¹Ñ£¥D÷v±éjuÊsrr0›Í•‹dÄÅÅCÏž=-QÁRÂÂÂj×7fÌÆŒSá¹#FÐ¥KΞ=K`` ˼ pÇàQœD¡­íµR¯ ph4¶mÛfùÛÞÞž_|‘þýû“’’B›6m*mjBz<My©0Ö bîì,ÄèÑ•GßnWš7ûÎÍMT†®ŒvíÚU¸Æ===ùðÃ9räZ­–°°°+¿›€@ˆ”¬eeeÑ®Ýeú¶üQzZ´‡UùP¸JÆŽËØ±c+<7räHºuëÆÙ³g ªºï´†DGGÓ¤I“²`L,2²c¢:;0B•Â.HÓÙ—_–2ÒhdþDPX(cÅzõ’¶,…›‹Ë«D#¶ÊK/½Ä€HMM%,,¬BÐæjÈÌ̼|ùü"doOàB<|ñ…\\÷Ü#÷õcÇäïk´OÕa0Hoè©S¢Ҩѕ‰QšL2ÒN­–-[[Qÿ7›¥µ¼Q#9œœé#ݵK&”êk–T‘>u{þ¬ÕÊauppÀÊÊŠüü|Ës»wïÆÉÉ©‚*˜ÉdB§Ó]¾>½ 6lX¡×µ¦¸¸ÀOë]‰Òh¸ãJgô)(\gZ´hA‹+‘W7C¡lì²ÐÕHV£‡µ†… · jµ”Ót¬Ê¦B°¶¶&²ó/‹8¦Á&Ö­[GïÞ½+ŒÌ¹„cÇD%⃔>U…ëΕÚ*•‘˜˜X– Ð €@ 1Ðx’ñ«bÁÁ2ñ:5ãkµ-}råc¬……òü÷ßK’7(HqX«¢¨H4JT]\®M¦îzÒ²eËW9Ö”¸¸¸êƒ˜qÈX ÇƒV¤ó»v-›o×¶­xrfóuO/ɵ}ð ¨øo¾ ï½W½PcQ‘T|:;‹£ZT¿ý&±ÔÇ“ljß¾ðÌ3ò}):J ý%3âKózÅÅ‘qûŠÛ×ê«€½½=Ë–-#$$„¬¬,Ö­[g¬]ÊáÇ9þ<¯¾új­-0x0û¿ÿžç¯—T•‚B}a‚¼|sÇŽ»üoJ‹0uêí~V¸©¹pámÚ´‘?¶ ³:ï-yÑè\Å÷îk¸GëÖ£zô¨ØJu±³³úrsáŸ$¡ûØcâ¬~ðø7Šùe4J {ppýÝŒFÑJX¸²²¤Ô3*J²i=ééj‹Îí@aaaõž3@6¢lVËì¸*¶u\GÕl†õëåoÒDÔwÿþ[6õé§e1PظQªÖ.¦¸X–.•õõè!߆ åïiÓÄÑ-Ñ$¬–ÈHén1å«­ÓIeXM¦<ÜŠÔÊaõôôdܸq|ú駬^½ƒÁ€F£á¾ûîC­VsîÜ9.\ÈÚµkéß¿ÿ5ÊÔ“‰œŒ ìíì**í)(Ü áÔ!ˆ=™Šc[óeg°‚Ül[µRúŠ*#4´l®©Â È6 òÌy¨ÕêÊ•†Íf±, ± gõ¦Ä`l‚ŸŸÄn·–㬬,ý”ü¼ÎåGs¤¥I ð+¯\výW‚Ù ¿ü"J¤'J;lq1üü³L3FÊÝÝ%ëc2I©ä™3õÓ~’ ÎBX˜\?©©â8ØÙI›cD„ø=ÉÉR’Yúó$ÕÔGŽˆ£âë ݺI$/æÌ'Åh”²POO5J~S*èt2Fd×.‰)˜Íò1ùúÊv dKJ |÷'={Þ>i³äädš5kVõ§€î@~¸8ˇq).–ìç¾}0w®Œ”3™$¨=~|Åûш°nT˜Ír½§§‹Bozº8¼<"AFÄ‹åzªMF=0>ùDôáßÅ–»Q&Ô5µrXU*wß}7nnnìܹ³ÙL—.]èܹ3*•ŠÓ§O³oß>†ÎC=TóK×’ÌL ~ù³ùʆÊ+(ÜȘ 5\5)ƒ‚j\v»4åוJŒE8óÆ ,â~vvv• ~èõò«Þ£Ü{o­7¡pc zA!!¢ôàƒ7~¹äµ$++KTS·!@ÄeÞ`2ÁâÅ’†¹\_÷b6K âÿ[ÖRâè(c·ž{®¬Ý¤µZtDæÏ—LPMuÖÒÓk®›“-†ûîÝâ4–﬉17WÖÙ¸±Ì˜ìÙS‘Çá?äõ=äZ‹‰'ä8»w‡ò·ßÊ*oþüSœÀ@q²²dLÈÙ³âØ¼ø¢ô^<‚÷Èɨ(ç&M**ô»¸Hp qãt(¸.ŸáHvvv-œKpÄÀôŸ¥þ¶FTîÙ#óÏþY®éäd‰}Vv]†‡K0¢T´ñða™Yߣ‡\ª½WÈÅE¶(ñ©ëôU¿)¨õÏ 4hЀÂÂB|||,e‰wÝuwÞy'6665ê­».dd`Þ¶¦µÍîjel«Â ŽI -SAý¿øqé‡üG Ê\·k/ÈMø øÎn>K@@À¥%ðLŸ.VÂ5š¨PwèõâdÌŸ/£9sÄ!yûm8òòT·ö}N«ÕRPP@ë Ô$aªRÁ}÷]5ŒdsrÄÓé$“hm-§÷Þƒ~ý*:… ŽiU>„‡‡|¦))—Ÿ4 ß~[¶íÈHÉ‚ÚÛ‹³|á‚dHÏž…—_†o¾‘@Ʊcâ,Ÿ;Wqߢ¢$#öàƒ’ µ¶.S-îÜYʘãâävak+Ça2ɲjuYðòí·E@jûvÙnëÖeŽyƒR™c4Šs¾aƒ”‹>ü0 *ËâðÜ{oÍ’ƒjµù¶ª€Š‹‹«ZÀé°:TïÀS^÷R‹ôt rÄÅÁ¬YeA…ê4Ô¬¬äzš9†×^“àÌõø »t‘K^ž|OÛ·¿®§ã†¦ÖkZZÓ¦MãðáÃàççÇ„ 0`ÖÖÖX×wH´° éé˜Ê§”L% Ð "ˆåqÀ PÜÈCf>•*Ô«(` ´*Y¾>n0¥}ª+ܾ¹Üÿëjÿ‹¥@Й­Õ 8X²?þˆ¸„3àYɱ™Ë=Ê¿vÝàKÑÂò3fzaM/¯+6SP¸áÉBú˜@JJ •/×·¯ÔI݆Í没ð&“FåG…\Íȳ¹ìQºŽë5‚Ä\îw¦²õÁ?ˆ`V+ÎÊ3ψÑçë ÿûŸ”¡._±±jBCoí2ˆ¸¸8üýýq<åIH†©:J?È‹S9µD§#}Å èß_²Œ-Zˆó•–&F{·nµ»F\]Å¡‹—rÙ%K$ÛxÿýeŽ_j*lÚ$ŽÂ¸q’Q?sV­’l’N'Ëôî-W_•þÁîÝeƒKùæÎ·"]VV—VΨTòÜŃ'JÊãà ûõÀUwXYÉrC‡JöyÊèÓG‚ yyâìNœxUÏ-‰V«¥¨¨¨ò «HzÄB¬¯|à×øe2ÉWgÿ~ÈÌ”À„³³dÑk3°!(Þ}÷ú·µh!£tbcå;r;WËÕÊ»4Ìš5‹;wrß}÷áëëËÊ•+™  äßÀX tôY"xðÐq²z!»½™ÀûHÙN]aBæR}Œ8Òd˜xs.uÜ2J^ÏAk7äF_rÌ€=ò£è8й%çär áE%ëõ(ÙÆÅD—œ3k$(ìEœÔ1”9újDHÂXr\G‘€‚kÉþ´@‚%ËÍEß.åöµ5аŠý(A“®Aítk}ÃÛÈÀáè:ë?@¤ p½0"÷[àüùó•«[[ß2Ï……Ÿ/FxÓ¦â˜Ès›6I¿Ta¡ôºåå‰1ô÷ß2ø‡ÄXoÕJœ»ï¾TtC§cF«Æ×÷Rƒ½¨H2Tññµ?qB µ®]e½_¾ýW«•(¿—W™YXX¦~j2‰ÀÍáÃ’8}Z2t Èø¨Rrrä£{æ™Ê·éë+}c™™F–/7Ô÷Gx]9vì-[Âf͍³Y_ÊNÒ ÓI@Àhá$F®Ç;àñÇ¥ôõõ×k^Ö[Š••0}ð\ 11RByò$Ìž-YÔèh¹†Þ~»ÌçîÔ©vx<=åÊ3gŽ8×k뚷×–°ïØ!ßÏ'ä;QWn:òòòª~±øx¹-´l{ͶYT$÷Þƒåáã#™áÃ¥øJ(Uy¾Þ8:J…Aƒº©•µ›Í‘#G=z4O<ñÖÖÖ„……ñÒK/qäÈ‘Ãaõð ÝÃC²§»€¯€çÉÈL'{Äi5#Ty¼€û{LëÀh <†8H¸8…%ë2 ÎX©dFJˆT½ 8RòÿùÀHdΔmɲÅåÞcUòÿ\`p‚8×k€w§M_²Ùˆ³0 8 4A²Èž%Çîƒ8}Ç=ˆãéŽd;[;Gü.Äi´+Yö(’a¶CâÛ”<‡HpÀxÁÀ~àÑ’ÿ—þð•:úå{îÍ%ï;ƒ ¶"¥QÛ%Ÿ™GÉöâÇù³’c÷)ù\Žƒ‡W¤€ïb_ Ÿ¯~ð̈́Πˆ£oü>\z(sjnaò/“–’’R1"o6üy’Ê©£9“µÁl–jåÓ§%{uà€]nÚ$«­[Åq¼óN)‡ts‡¯Méu J[[é]Òje¹•+%󨥋8­©©R–Ö¯Ÿ”&j4².ñã{õ*s,wì‡äùçe½AA’aÈÍ•}ôö–ÓÙª•ü¿´,S¥ãnÕ*1Ð,ìÓ¶mr ¡¡Ò‹—–&NoB‚dBBä¹ÿ§åí·ËÎOt´8­·@RüšpþüySÅž¸99be?þx­·c4ʵd4JvZšô£–V]:9I–ÐËK‚W:™ÊÉI]»JðÁÚZ‚}ûÊÿ¯…Êi@€ìJŠ8 R‚[_F½½½Äúö•Òä>}n?á°šPPP ½Ú•‘j–>®U Ñ(Á“V­äÞÔ¥‹\×WYœPgøùI@3+KÄžngjå°êõzlll ³dvüüüð÷÷'66¶¾E8{]F‡zˆÓ÷-âÀ”G…8ƒÕEÏ4ˆ“WZ"мÜkíKÞ?é}, Ž–+2+M”µ…ÿ"ÎjÄ)< ÌFœÝ@Ä@û£d¹{KÞë‡d}€g(›ÁöXÉ ±ä_§’m_̈³Û©Ü1_\?q#Žn0hŠ”hý§ÖqO YÑF%çËxˆ2g ÙïJQ!™ÔV%êÞ_zî@2·&¤¬Ø€8Ì ‘Á#÷TÎv·Î<^½.l?‡v”u助 · ¹@ddd`4ñ÷÷/{-%ER³g×ë.æåÁÚµR†xú´8x¥BÅk׊QÔ¸1<ú¨DÈÃÚÃC ¨ê„fJ³;åFœÓ¬™do^]œÎ{ï•$[›6eýs å’ŠÃ`k+÷Å‹ÅÇ)oÕ¨QÙòƒI/ײeðᇲýúI`óæ"†Ô¢…”uÞ¿8¹Í›‹s\á׸±8Õ/¼ 窴Ýòßå¸Á3áôéÓŒô)US—cÛ6ñŠî¸£ÖÛùé'Éâ{zÊHË .uªllÄ ¿š1Ê660rdÅçÔêk?ÙÚZ¾>>:vLÚz냞=å°l™8ÒùD‚…·3W]O¨V«ëO`©2~ú‰Ä§’3F2 ×ÃWQí€%ÿw@œ9#âD•–»Z!Sℹ Žç}È™7Ÿ ÛÏ€'Ôq — ™ÊwJþ­JÊúrsË•§ñÂÃEN´( øê+¨iß¾îZiÕêË.Á,Z$뉒Q«‰ƒâà k¹¿÷Ý›7‹ãZªHV7çëF'33[¬×YW_‘tþ¼4_¦1Òh„/¾Òßçž“ Ff¦$fÿïÿnžRȚЫ—”Èëõâ¿wèP¿ûÓ¹³\ãÆÕ÷™¹qÑéte Á`%e6ðŽ 0fì5‰¤èõ"(Ö·ïµ½ŸÕÍšÉÏÝí>b¼Ö«N§cÑ¢ElݺƒÁ@ll,ùùùäææVXöñǯ[£:5•B/îI}—a.ʘ…[£RRHˆ‰¡yóúHk+(Ô @gHLL¼T!¸¦C¯!©©’-…tü¸ô„Þ¨Ž× A¢Âšš*ûZ]võzãâ"åÅyy’õ­­Ï­Lnn.ÁÖÁRaUU8&ÞzK/ã°nß.Š¢>*ýÍO=%b[cÆ\û’ÜúÆÞ^i’“¥ú¨|×@} ÑH¹¾"¶T5¹¹¹¨,ŠmH%b—’_~ùªÛ ©&9z¥¢cèÐ룄^—ØØHæþfÎ_ jå°ZYYáååÅéÓ§9}útÙJ¬­ÉÉÉaÛ¶m–ðÁëöh¼½1ý÷rÛ‹¹©ùê×§ p£QT3f ÎÉQ2¬ ·6ÁØÔHÜ¿qt/g¡×ßJº°­ÂèhÉV%} ™Â¡Co\aWW9MkÖˆWŸÙ'wwéMO—Da¯^õ}vn²²²>, ª2¬¿úJ’[µºìúbcáÙg%Óçì,×m@€dÚoµ‘’y*(ïc};&*UY¸Båètº2ýmHß¶g1è­®z0úÊ•¤‹ˆQ¹;î¸ùËÞA®«[-Øt%ÔÊaõôôä‹/¾ÀT:(î2ØW)ILLdéÒ¥>|úôéCÏž=-5í ,[¶ŒÃ‡ÄÈ‘#iÒ¤ êÞiíOØ{.–övíÑpƒZ ·4………lß¾•+W¢Õj gРAa49{ö, , 99™ˆˆ†ZQP¦:ôzHH Y§Ãñ*oî WJff&«W¯fË–-ØÛÛÓ¡CŒ»»;z½ž}ûö±xñbŒF#]ºtaðàÁ8;×RP`-}Œ–8ééâõëwÝŽÍd’J•J‚ýgΈŠîèÑbð'%IÆpýzßq#Ó´©¨ßqGý*òZ[˹ûûoQP½óÎú>3—'!!?ÿü“C‡áééÉ]wÝE÷îÝ+Ø*ýõG%88˜ûï¿¿V¶J)éq鸞uAƪ3FœÕËxdsçÊW¤];ù»U+ÉÌ4o~kfg¬¬DÍØh”RçÛ½d²¶:tˆÕ«WsêÔ)5jÄ}÷ÝGëÖ­Ñh4FΜ9 HII!22’!C†àççwUÛúHåê;x¡pí©ÕU­Vcoo££#ŽŽŽäää°yóf-ZÄš5k8sæŒå5GGÇKnÜ999LŸ> 6лwoüýýùôÓOY»v­Å þàƒؼy3}úô!55•÷ߟÔÔÔï£~£ž\¯\)3PP¨6nÜÈÿû_‚ƒƒéÛ·/›6mâý÷ßG¯×“žžÎ[o½EVVwÞy'6là³Ï>«ùÊsrÀɉ\ƒAqXêNÇܹs™3g:u¢M›6üúë¯üüóÏF:Ä{g‡‡aaaüòË/,Z´¨öêwÅÅÅe×z|¼X¥×¡))9YÔkß{O²RO=%‚ß|#¶Ô¸q¢Šûå—Rè`o/YÌ™fÍÄi<¸~ 8•J2|k×J@àF¿uegg3mÚ46nÜHß¾}ñóóãã?fýúõ˜ÍR½5eʶmÛFŸ>}HJJbÊ”)¤§§×z[) )4øOƒ²‰•Ѿýe#))r]Ž_öY[YI6Û×·¾ÏèõÁÚZ‚2ÿ-Ç#éÞè\¸pÉ“'söìY†Š••¯¼ò §N 55•·Þz‹ÜÜ\î¼óNÖ®]ËôéÓ¯z»¸¹¹Á^ÀË»ÿZÞÒ(Ë#­¯¾*ÕгzkRëV“ÉDTT_}õ[¶lÁÃÃgggôz½(ÝùùñÜsÏ1xðàKÔƒOŸ>ÍîÝ»Y¼x1¾%wP½^ÏÊ•+¹ë®»8xð çÏŸç³Ï>£M›6 4ˆÑ£G³zõj&”ÖaU‡2e’’Zë(§‚µbÑ¢EŒ;–gŸ}µZMhh(o½õäСC¨ÕjÞ}÷]ÜÜÜhÙ²%Ï?ÿ< ²&s‚ƒ)˜6 Õþcù)(Ô%yyy,[¶ŒwÞy‡^%µ¾¾¾Ì™3‡{¹sçƤI“©Ìùé§ŸèÝ»77®ù†–‚¾ƒž¬¬¬2‡ÕË žyæš§‹vîƈxòɪ{ᆠ‘¾Õ?1Ýaµ¶çûF(Slß^œ)?¿zw¾,§Nbÿþý,Z´È"ø¥ÕjY±b}ûöeÿþýÄÄÄ0}útZ·nÍ€3f kÖ¬áᇮնlØÒ>´ý¥/œ8ß}')£h¾ùFÔªo·þÉŽ¥K uë[¯äùz²iÓ&œ™6m®®® 2„sçαzõjÂÂÂøë¯¿°¶¶æwÞÁÕÕ•æÍ›3qâDë ýõÐÁzÔ.ÀSʷߊ³:r$ôïk©_+TN­VNÇW_}…J¥bÖ¬YWx½Y³ftíÚ•/¾ø‚3fI£rÓɃ‚‚˜0aZ­–°ÿ~vîÜÉ“O>‰““±±±ØÛÛãR~Õh44iÒ„Å‹W»_yyyìÝ»—~ýúalh$ ›[¡ÓZáŠ1œúˆþýû[®OOOO¼¼¼8sæLµëLOOg×®]´mÛ£ÑH‹-êçÄ*Ü0hµZöïßOll,ݺu«³í:::òÈ#`08zô({÷îeÍš5ÜsÏ=S¡Ï©qãÆèt:’K&VAtt4 <<«+hÇN£aÆb4ÅÇK³ÚE¿;5ÅhÕ”òÞ `õjرþ÷?1|/‡J%Ú7_]ÿФ7##GJõ_mعsg­Ú‚®ÁÁÁS\\Ì8pàÿþû/Ï<ó ÄÄÄààà` ¤h4BBBX¶lY•ë4›Íœ9s†Ó§OÓ¬ÜÚ.©]àbA•„èÝ[T³.CQ‘TLœx{^“’±¿ÑËÌ«"??Ÿ;w¢×ëët»¥vQ~~>[¶láøñãäåå1¬d&ϹsçhݺµÅViРžžžœ={¶Êu :DPPP•`=Ö÷ ñ³ó%h{·Zï{LŒ¹=ý´´i(ÜØ\¸p\ªö_KjçLLL$**ŠÑ£GW¹aƇN§«2ÚX\\Ì®]»Ø°a999ØÚÚVˆÒ_Ìå¾Èlll(**";;ûZœc…›•J…——^^^õ–mŽŽfݺu;vÌR…P—»Æhذ!666¤¥¥QXXX/Ǥpã`ee…ŸŸ®®®õrFŽ9Âúõë‰ÅÑÑ£ÑXé²&“©ÚëÀÝÝ___9–d âããiÒ¤‰¤F/†“'¯h_ÍfyëºuÒ£Ú§ˆÑ ,Îjm«ëÛ·¯Ýò ‚¯¯¢Ô†FY²þøc²²²ª\Ÿýe.j[[[‹1o2™,ΫÂíKéÓÛÛ»Þú™ïºë.¾ûî;¾üòKvïÞÍ?ÿüSå²—»Æ D£Ñ ×ë+= ·'ÖÖÖ4jÔ77·zqXmmm;v,sçÎåÝwßå›o¾áرcUîëå 2üýýåûš å7'((HÄÆŽ»b«äää™™I@@)))–·¶¶®`¨_#ÐUzÅ£ìÛ<=k¾Žr\¸ }NŠN™BMصkóçÏ·ümkkKß¾}‰‰‰A§Ó@aa!ùùù€´KÅÆÆÖÊV0§›9á|¢ì‰Ã‡aölñF«zYªãß~.”Êáöí• ‹BÍÑét,[¶Œ-[¶Xžsvv¦Gœ>}¾ŒŒ KeLFFYYY\ÙFÓAW¤C`‡óœ9WÔtZX(-M›Þšcšª§VkiJ÷СCÕÎbÍÏÏçܹs4mÚ´Âó)))|÷Ýw"”QQQøùù¡ÑhˆŒŒ$%%…ØØX@J‡÷íÛG×®]k~@j5žWhÔ((\-ÖÖÖ,Z´ˆ;vXJÇ’““)((ÀßߟÎ;sèÐ! 1‹‹‹£s-BÄÅÅÅ–>o…ºF¯×3g΢££-Ï9sggg<<<èØ±#;vì°¼vøðaìíí/ù=¨–µ@¦”«JôÁ¯¨Q­°¦N•JœG¡&$''3{öìKl•Òê­öíÛ“””D\\EEEìß¿¿V¶ €ê˜ ]‰áž› ³fÁCU›.ÍÉ3`ÄÿêÙ³F•à Ôj5GŽaáÂ…–ö"“ÉÄéÓ§-A—Î;sðàAËëñññ$$$ЩS§+ÞnJë¼]Q_Á,WƒAÆŒÙÚ^ñ¸V…›œZý|Éo¿ýF«V­hÛ¶m…¯Ùl&++‹Y³fáççGÄEÓ‘‘‘4iÒ„gŸ}–ž={’ŸŸÏúõë™0annn¸»»ÓªU+>ýôSî½÷^vî܉»»;={ö¬ñ>ÆÇÇRßçUá6ÅÑÑ‘{ï¿ÿžÔÔT\]]Ùºu+®®® 0­VËÊ•+ùä“OèСýõíÚµ£eË–5ÞFqq1^^^5^^AáZâççG¯^½xçw4hf³™õë×3`ÀÚ¶m‹ S¦LaúôéxxxðçŸ2tèPükª£Ò Å1…¬¬,)AË˵Ô+è9xPÕ«V¸ˆŒŒ$88˜çž{Žž={’——ÇúõëùÏþƒ‹‹ ´hÑ‚O?ý”aƱcÇ<==éÑ£G­¶“a“ÁÙ ³„ÅÅp÷Ý2§¥ Š‹E$¬Cy(sG®kkkÈäÉ“yóÍ7‰ˆˆ !!Ý»wóßÿþ€¾}û²jÕ*>ùä"##Yºt)íÛ·¿rÁÇf\~û‹öýkýÖÜ\øõW©=Z <Þ®X½ûî»ïÖta•JEãÆY¿~=ëׯ§¨¨kkkrssIKKcß¾}̘1ƒ]»vñâ‹/Ò®]» ­««+dggsòäIt:cÆŒaРAh4Ôj5äåå±}ûvyê©§¨²Ä×d2qêÔ)pvvfëÖ­4nÜXqZ)G´µµ­ Zz½iÕª~~~=z”sçÎѵkWüq‹AÛ¶m9uê W¯^L˜0¡òžŠ‹‹9uê”%´iÓ&lmm ¯ïÓ«PÏ”Þÿê²ÏO£Ñµµ5G%##ƒþýûóÐCáää„!!!ìÙ³‡øøx† ƽ÷Þ‹m55\999\¸pV­ZI¯Säµõ÷aÆIj›65ñq1GŽÈh—i¼‹BÍ)**âôéÓ—À¯'nnn[åĉèõzÆŽË€*Ø*999lß¾   ËÚ*Z­–Ó§O[ÆA8,q À¦€ ÞAR=ЦMµµ½›6ÁæÍ¢|£R¨9999$%%Õ*p}µøûûJjj*ÇŽÃÙÙ™gŸ}–ÈÈHÔj5NNN´mÛ–“'OrðàAz÷îÍøñ㫵U’““1¦ƒX8›‹iã7œ¹£)Ý»×x?õzظQb–ƒ]qWˆB=“œœŒV«½dºLm¨uœ"00Y³f1gΖ,YÂŒ3Ðëõ¨ÕjÜÜÜhݺ5Ÿþ9]»v­ôÆÈK/½d)—T©T–óññáé§Ÿ¶¼^Û&]­V‹]­Þ£ p-qttdÈ! <¨x«T*BCC™4iÒ%¯Õ³ÙŒN§«]y¥‚Â5ÆËË‹ñãÇ3nÜ8 âuleeEçÎ-¥cµ½ÆIö@vléÕ>{Ž¿"K¥¸–/‡?¬ï3¦p³T­­âëëË3Ï<ƒÙl®ý5`—Œa%ÊÚçÎÉ à*ÒG99ðý÷2/XAáZбcG:tè`ù»¼½­R©hÖ¬“'O¶ü}5Ú0¦™yl.*Ä¡aÿG§ƒ¯¾’ûø«¯^V‡Lá§Ö«J¥ÂÏÏ×^{øøx’’’,«««+!!!¸ººR\\Œ­­í%gyýºm\é#++«jIm…:âr×𕪥F.\¸ ˆŠ)Ô;Õ]ãWeÜh€nRYàææ&3)[¶¬µªŒ^/~nË–7ïÈ …úãzÛ*á˜Ã1œZ9‰*ØçŸÃgŸUê°šL"´ôàƒJ¥€Âµ£&×ïÕ*»šÍfŠЉ=“ÆÆg^îÓ§Æïݲ’¯†â¬*\q%¸¡¡¡„††^òZZZãÆcÖ¬Y4®ãÆ¡¢¢¢:]2 9r„ÄÄDËs*• wwwÂÃÃ-³7=ŠZ­®²„óðáØL&ÂÂÂ,ê¯EEElÙ²…„„ AAAtîÜYgr›c6›qvv®·¹„ × Gªe¬­­EµM›¿Ý`#ç·ßÄÇ:UéyR¸É…ücùhîÑÈ€à6mª”>Š‚7Þ€¿ÿVúVn.bbb˜7iCᾩ¶¤¸ÿüsL&ß~û-¶¶¶Ì˜1£ÒõüðÃhµZ>ÿüs¬­­IHHàÍ7ß䨱cx{{£ÑhHHH iÓ¦LŸ>ýÊeÅnzŒF#999Êœa…[— _‚­¬¬ÀÙY5$5Uzžîº zôP |…³ÉL¼1žÞ!½aÕb?¾ÒåL&ÈΖ’H¥oUáfÁl6sþüy>ùøº§v¥E?{lkx/,„o¿¥:”Q¸Á¹¥nÅÅÅØÙÙáíí]'Û3›Í2xð`>ÌáÇ9tè“&MâŸþaùòå–eJ¥Á+£ôõÒ^™åË—³yóf.\Èš5kX¾|9‹/&99¹J§WáöÀd2¡×ë‡UáÖE4—*?OOQ™)*ªñÛ¿ùFT‡ ‘R`¥z^áFĘi$=:{{øè#¨B}5*J¦Ý\FIAá†âèÑ£¼òÊ+ôïÓ‡›wÇÖ&§Æï]¹ºv…ZLûS¸ ¸¥Ö¬¬¬:Uƒ­ •JE¯^½ðõõ%++ëŠÖqôèQ7n\¡œºqãÆ¼ð u¦ªpã¢ÑhÐ(  ·*=A››‹!5U†ïU3÷»Zß;­p#R+‡5&&†éÓ§“’’Rßû}EØÚÚ2dÈk¾Þ.]ºðüóÏâPœ}š}ûö±víZæÌ™Ã›o¾É[o½Uß§R¡ž0$''+V…[gggœ»uƒvíj´¼V !!òPP¸ÑqØî@[B°Ò‚&M.y½ \\D8L¹Ý+Ü´¨~TëmäçÃÂ…ž}ú€½}}ï´ÂH­Ö¶mÛ²nݺg o—>»ÀÀ@hù{À€äçç3wî\z÷î]ëõ­X±‚°°0‚‚‚ ¢oß¾¼øâ‹|ùå—üúë¯Üwß}´¨B AáÖÆl6ãêêªô2+Üòœ=}š^íÛ×xù  8ÜÜê{Ï.OªO*'Ï2ì¹·¡’1ekÖÀéÓ¢”ª pÓòùNm =+C½p^{ zõ‚çŸgUS¨ŒZÅíRRRX´hÉÉÉØÙÙagg‡F£ÁÊÊ [[[Ës¥% te¼÷Þ{üüóÏ–ÒcµZ½½=áááX[[W«8¬pk“€½½½ŒûPP¸…i¤×ã»dIµË˜L’Y=}¢£!4T1vnlÖÛìß«J´. aíZèׯ¾÷RAá*чFI•¾d6Cl,tê$eÀÊý[¡jj•aÍÈÈ`áÂ… Àùóçy÷ÝwùñÇoÛQqqq¬Zµ (+ þñÇyæ™g,óYããã-Ë”âïïOxxø%ë;v,S§N¥yóæ´k×{{{øüóÏiÕªaŠ|ÚmKÓ¦Myã7ê{7®;¦”œ/Sß»l,Z$†Î /@ëÖõ½× 5#ëP9ꃨ †ÃEÕh99)£lnjrº‚‹{¥/ °¿ˆŠ)1x…ËQ+‡Õ`0`¼H~]«ÕsEâB7;*• wwwvíÚÅk¯½fyÞÚÚšñãÇóÔSOaccƒ››Û·o¯° ÀСC ÇÍÍ ­V‹ª$´4nÜ8Š‹‹™ÖÆl6“””ÄÙ³g1™L´lÙËë&“‰ØØXbccñòò¢yóæX[ߘÓwùúë¯/»ÜÌ™3™9sf•¯öÙgþöððà7Þà‘GáØ±c ‚‚‚hÞ¼y}²B )..æØ±cdddH“&M,=݃'N••Epp05RJ|n:²²²ˆŠŠ¢  €&Mšl ºqøðaL&Mš4ÁÛÛÛòZM‰õò¢häHªÒß8~΃fÍ”è¼ÂµÇl6sáÂΞ=‹Ùl¾ÄV1ÄÆÆ‡··7Íš5«¹­ö-AV*TÍ`2¤Ô½Y³ú> ·:ƒ¸¸8Î;‡ƒƒmÛ¶­ a08~ü8ÙÙÙWn«4·…ÀÊ_:sFDòêûL(Ü Ô©'h4Ù´i_|ñööö˜L&¬¬¬xî¹çèÞ½;jµšE‹ñÇ`mmÁ` oß¾L˜0á¶Ì*y{{Ó§OŸúÞ …Z’À'Ÿ|Bbb"ÖÖÖÑ­[7&NœˆÙlæ»ï¾cÛ¶mh4L&£Gæ¾ûî«ïÝVP¨f³™Ã‡3uêTŠ‹‹Q©T3a† Fff&Ÿþ9§NB£Ñ`mmÍ«¯¾J»ªý–’QT„uIKÅÅRJ6q¢â¬*\{ŒF#6l`ÆŒ[ÅÚښ矞nݺ¡V«ùã?X¼x±ÅVéׯãÇǾ&§yPhÌÅ©cG¸¨bêôiéë ¼üj®ƒÁÀ·ß~Ëš5k°··G¯×Ó A^ýuBCC)((°Ø*¶¶¶˜L&|ðA†^óKcØ\Z)c2ÁªUвe}Ÿ …›…:UEJJJbÖ¬YtïÞÙ³g3{ölÚ´iôiÓÈÎÎ&11‘ï¾ûŽ2wî\^~ùe~ÿýw€IDATž=™={6ß}÷-[¶ä³Ï>#77—„„¾ûî;† Âܹs™8q"¿þú+‡®ÙÒ!Í rž^­–ãÈððPFÙ(\_Ž=Ê’%Kxàøí·ßøüóÏ)..¶T îÞ½›?ÿü“×^{_~ù…>}ú0cÆ 222j¾‘ãÉp¼ò1˜¹¹r­+9…šR«[¢µµ5f³™íÛ·3þ|æÏŸÏêÕ«)**báÂ…–çJÙÙÙÞŸššJQQ=öîîîxzz2jÔ(Î;GQQ{÷îÅËË‹ÁƒckkKûö퉌ŒdË–-õ}žª%>>žiӦѣGÂÃÃiß¾=O<ñGÅ`0\÷íFfÏžÍàÁƒ+<ÆÏÊ•+1™L˜L&æÌ™Ã¤I“.»¾C‡1xð`Þzë-‹Rq)ÙÙÙ̘1ƒ»ï¾›víÚÉĉ9yòd½ÿ¨¨(FŽi)0`œs…Û—‚‚þùç>\'A±RìììèÝ»7 A¬ƒ2cÆ z÷îMxx8………–û€³³3z½žüüüj×»wï^lmm0`ÑÑÑ4ðlFºÞƒ­[áÊ–+*‚Ÿ~‚©S‡õv`Á‚¤¤¤\ýŠj··7ÞÞÞ€OJm• &àêêj±UJ3¤VVV—µUÌf3ÿþû/ÁÁÁt{¼v[öã¨oQa™ìlHKS²N·YYY,X°OOÏ:ÝnÓ¦M-ÿÏÎÎfõêÕ,^¼Ø2Í¢  à[ÅÖÖ¶Ú’`NǪU«ðôô”õ:CÓÊ¥®==¡ŽM3…z"**Š+VЩS§«ZO­VµZ]Á¹Ìf3 üüóÏlÛ¶Aƒ1~üxKçJhР]»v­Sg --Õ«W[²¥¨T*\\\xòÉ'yôÑGÙ¹s'ƒ bÕªUDEEqáÂÖ­[‡J¥¢OŸ>¼ûî»xyy±eË>øà¢££±³³cÀ€¼ùæ›x{{ó÷ßsâÄ ŠŠŠX¹r%ƒöíÛóý÷ßW)HemmmqúkúÙ=z”””žyæŠŠŠØºu+<òÎÎΘÍfÌf3©©© lllP©Tðå—_âïï_§ç¿:lllèÓ§O…H]Qzž.\ÈŸþ‰³³3“&MºªóÄå­v…ÛGGG†ŽJ¥ªs•i³ÙLnn.¿ýöÿüó-Z´à¥—^ªPQS[:vìh©20™L,òîIN¼3‡ÃÈ‘eÎij*ŒsiÖUáÖdôèÑ,_¾¼Î·[j«üøãìØ±ƒ!C†0nܸjm•ê‚ù*•Š.]ºXšîÖT÷î…”R÷Û wwwFÍþýûë|Ûf³™ãÇ3sæLâââ˜8qâU }j4(ÎªÉ í€¦—.wô(¬Y#FÔù!+Ô-Z´`È!äää\Õz®X%8%%+++\\\Ø»w/©©©—,Ó§OŸ N¤ÉdbïÞ½¼ûî»DFF2gÎËIᕪñ ¬­­1™LäççãççWçø²$%%Ï=÷ÜSéëáááØÙÙqøða Ä… øüóÏyøá‡9r䇿ñÇçwÞaâĉLœ8‘û+WrîÜ9FÑhdÆŒÄÅÅñùçŸ3}út>úè#öïßÏÃ?ÌÊ•+-YÍÄÄD~þùgËö×­[GQQãǯÑñ˜Íf-ZD«V­hÙ²%÷ß?=ôqqq´nÝš€€ÆŽËäɓٸq#C† ¡C‡4oÞœ:X"q·;iiiL:•ÄÄDÆW¡Ô×ÁÁ½^ÉdB­V£ÕjÑjµU3oRAáFÂl6sæÌ¦L™‚££#ÿûßÿ, À:{{{´åÄ’òóó±µµ­•3›ž€MÞ~[Æ×äåIÖÉ`€™3•Aó דÉÄîÝ»yÿý÷éСC¥¶ŠÑh´Ø*F£‘‚‚‚Z%WzzòHË–”º¬Z-ÌŸ\ßG¯p;`4ùí·ß˜?>÷Þ{/}ôåTÙ+³Ut:¾5æëàíCðU;ð/ ò˜L°`Œ5ÔVP(¥Ö«N§cÍš5Ì›7û￟¾}ûòã?²ÿ~lll(**Âl6Ó¦M:vìXÁaMHHàóÏ?gøðáŒ;¶Â¼'€6mÚ°ÿ~RRRhذ!:Ž'NT(]¸*L&ÈÉ‘Fš++™^œ›+¯k4àæ&ÿÏË“_ Þ}»’’’ðòòª2ƒçàà€••úÒí!e»Ï<óŒE¨áÉ'ŸdÖ¬YbccÃã?Ž^¯' €ÇœiÓ¦1cÆ BCC2d666„††Ò¸qã †abb"sçεü}áÂIMM­p#ªî³]½z5o¿ý6ùùù4iÒOOOÖ®]KëÖ­±¶¶æ©§ž¢Y³f¬[·Žùóç3gÎÜÝÝ2d/¿ür³¹·2óæÍ#..Ž©S§Ò¨Q£ ¯EDDX„;HII!))©æ=! õLaa!3gΤaƼöÚkî-jµš¶mÛrüøqî¼óNN:…µµu…–—£ER›vö¤p¸Dãï¸CÖ´4ÈÌ„rí³ ×œ¸¸8¾üòKî»ï>ÆŒs‰­Æ¡C‡HMMÅßß­V[k[e¿NÇ“åjÏŸ—̪»T¨ <ÈâÅ‹yöÙg8pà%`œ={­V‹½½=ÉÉɤ¤¤0tèКmÀh»ƒàÜ(sX ,Lîé µ¡ÖëÆùïÿKß¾}+ˆn<ú裌9’õë׳xñbžxâ‰K2£'NœàäÉ“ôíÛ—Å‹Wxíþûï§sçÎÌš5‹þù‡‘#GrøðaŽ;Æã?~m޶¸~ÿ¢£åï÷Þ+(>~þòó¡E xòIqjÿþJEF†Î+¬®qãÆ$''“••Ui877£Ñˆc9Ùú€€ËšZ­¦M›6XYY±ÿ~.\¸ÀÃ?lY6;;›¼¼<‹ÃjqU*Õ%ÍN:±zõjËß999¼öÚk–ñ@—cíÚµdffòóÏ?³dÉŒF#999üý÷ß<ùä“888`oooQ!8~ü8K—.eÖ¬Y888ðòË/×yyâ„V«eÕªU4mÚ”7Vx­uëÖôîÝ›7ß|“½{÷Ò¶m[V­ZEnn®¥'PAáF'==­[·òÀ\RªÙ«W/îºë.þüóOúõ뇓“‹-"88˜Ö­[×xÁéé¨\ƒ ‘lja¡<ŸŸ:IüPAázqüøq¢¢¢*µUFŽI×®]™5k«W¯æ¾ûîãÀœ8q‚gžy¦Fë×¥¥Ñ\£±ôÉ‚(_UßG®p;`4Ù¼y3Z­–ÔÔT~ûí7Ëk<ðÀôéÓ‡I“&±oß>Ú´iÃÊ•+)((¨¹­b°ìΠ®ØF¸u«Œ³=º¾Ï‚ÂÍF­Öœœ~ûí7úõëÇ›o¾‰»»{…Ñ5¾¾¾Œ=777fΜI³fͰ¼ž››‹ŸŸK–,¹dÝÄÇLJgŸ}–Ÿþ™Í›7£Óé7n-¯Õdaxî¹KŸoÒ¦L©øœ­-Œ'*ðòò¢uëÖ¬\¹’æÍ›WpÔÌf3»ví¢°°ˆˆËóZ­–¢¢"ËpqN‡ÙlÆÑÑ‘ððp¦”ÛÒrÑRÇÔÚÚU-TF\]]¹óÎ;ùøã/+ZQ\\ÌüA§N?~¼åX¢¢¢Xºt)‡B­V3qâD¶lÙbÔjݺ5¡¡¡ÄÄİmÛ6ž}öÙ*{jo²²²pss#::šèÒÀH #FŒ`ܸq<ðÀÌœ9FƒÙlæå—_®ÔPP¸‘) ÐmÛ¶í’ך4iÂ=÷ÜCtt4“&MÂÊÊ [[[^ýõKDøªÃÑ`Gß»T4j$ñÄ  2R”%Û¶…:nKW¸ÍÈÍÍÅ××·R[eðàÁxyyñì³Ï2wî\6lØ€N§c„ 4kÖ¬Fë×nÞLÇrý\°x1|ôQ}¹Âí€N§C¯×£V«Y´hQ…×JG8…‡‡3räH¾üòK‹­òÒK/ÕܾSÛ@ó–àZñf­V‹‚Bm©•ÃGNNÏ>ûl•J¥ÖÖÖtïÞ~ø}ûöUpXxàË Ç 4ˆÈÈHÎ;G£F*ôÜh4hЀQ£FYF×ÜqLJ2!!>ø€&MšXDΟ?OTTíÚµC¯×³nÝ:ììì¸óÎ;™={6~~~–Ñ0_ý5ÑÑÑWÜŸ——ÇöíÛquu½lIð¹sç8xð o½õcÇŽµ<ŸššÊ’%KX½z5#FŒ ##ƒE‹1fÌ‹S«Õj‰‹‹#,,¬ÎŽn4|}}Y¸paµË<ñÄôîÝ›´´4Z¶l©¨þ*ÜTDDDT¨ä¨ŒÉ“'sâÄ t:-[¶¬U@¦°°wòûѧ±7ÖÖ ß}'E/f3„†*êÀ ×—1cÆ0æ2Võ!Chß¾=çÏŸ'  ‚­s9lãã±*i—*.†_•XúE$ ×{{{Þ|óMÞ|óÍ*—±³³ãÉ'Ÿ¤OŸ>¤¥¥ÑªU«Ú‰ê©TÐØÊù·990g|ûm}Ÿ…›‘ZgXF#^^^–çyþùçq)׋aee…££#111W´S¾¾¾5oì®G4 O?ý4çÎcܸq 8–-[’˜˜ÈúõëñôôdÚ´i–l*ˆ Ï믿ΰaÈ‹‹cÞ¼y|ðÁ >œ%K–0~üxFŒAJJ ¿þú+|ðA÷çÀ 6ÌòwRRYYY|ñÅ–ÏìСC–1@===III±”ú–âííMŸ>}X½úÿÙ»ï¸(ŽþãŸkôÞ›€  ¨Å`-ÖDÓŒÍc“˜Mcz5͘<æÓ5Õ’Ä{VPAD"½×~lØx±&"‡8ï׋—r{wÌÜîíÎwvæ;«yæ™gx衇xõÕWY»v-Ý»wG«Õ²yófªªª?~üyó „ kß¾½YfiAhMÔjµÙ”‘¢ººŽSÚ 3àûûK³1-’’.]—ááëëû¯’BÖdýÙfÚµ ö탦šù$Mé_·UäBˆ+XýÕY¹r%$$ˆõW…çE(•JJKKåÇ4ÙW2ìÕ××ßwÛ\]]ùðÃY»v-«V­béÒ¥8;;3iÒ$†~^¯kLL &LàçŸÆÁÁ?þ˜!C†`ggÇœ9søöÛoùý÷ßquueΜ9 0€#«³³³cÊ”)´oß…BÁèÑ£ 1û[666DGG‡B¡à¶Ûn»`6ÚÀÀ@ìììø¿ÿû¿ ö M™2…;wbkkË“O>I»víX¿~=¿ÿþ;ÄÇÇ3bĈóŽA„ªôŒÊÓh<)•Rj3àùç¥ßáz¶':ZÎM±`´¼Ç œúAh~= þ]¿V…FŒ#d„ç¬mÛ¶ÅÙÙ™U«VuÁ5YF#ÉÉÉdeeñßÿþ×ÒõkNNNÜqÇŒ9½^R©4[pù\ŽŽŽŒ7Ž;Bµµµ<Œ8$$„—^z NwÞ¶®]»š½Ùr:½zõ¢W¯^—,gÏž=éÙ³ç?®_tt4ÑÑÑòï·Þz+Æ “ç@h4š:Ñ’ M§¼@…óÙÓf›\åºã‚Ð"TUUaooO]Üz+\ÅÒ—‚Ð2UŸ†n²9q„‹¬)—õúª:t(+V¬`Á‚ÔÕÕ™m7¬_¿ž>úˆ„„„nÈ£••vvvØØØ\rMR¥R‰­­-666ç%QR«ÕÝÖR( 4\W¬ ‚ÐT*jmq¨6{,$¾ùþÁÊ8‚ÐbUUUaggG^,_èû„ë›z(hþÊ‚m2Ad¤´r¤ üÿxÂáwÜAUU ,à‡~ [·nx{{SZZÊ¡C‡8uê={öä¿ÿýï?› }èÑ£Çu17WÁRº²†ìŽ[äÇÔjøS¡Eª««#88…ÎÉq(­‡.Ιöã0p t.„ã:ÖÖÖLš4‰îÝ»³aÃ’““Ù¶mNNNtèÐx€ÄÄD|­VKII /¿ü2]ºtᥗ^B­Vóþûïóꫯòå—_RTTÄ©S§øé§Ÿ dáÂ…¼óÎ;üç?ÿ!""ÂÒƒ ÂUÓh4–.‚ \s Ц ˆÃ]hÍ’ål„«õÖa½îécÀ¾?Jþü·HùóÿGÿ|ÎaàÄ9Ï= úó¹W@¡PÈwIÕÔÔ°nÝ:&OžŒ‡‡...Lœ8QΨœ››ËŽ;¸óÎ;)++£¸¸˜‘#GrìØ1NŸ> Àðáà E£ÑHëß ‚ ‚p}(*‚]»¤;­‚ÐZ¥§C»v–.…ÐXìk}}=[·n%11{{{ùqƒÁ@ZZééé´iÓ†nݺ5]»)èÌýów;`+ÐHê_@T>HÁ+@' è ümñú¶mÛòÑG]ðOËÿo :œœ)¨µµµEýçÂT999444ðÐC¡R©)ÕjµòÚvç|óŰ¹–/99BBBäÇt:Û·o§¨¨ˆŽ;.‚p½Ù¸q#:uÂËë¯Eâ«««Ù¼y3ƒ˜˜Ú´iƒRycõ ­C]]III$&&bgg'?n0HMMåÈ‘#ÿÚ*µµÒ`qê,-//'NЫW/³Çu:IIIÓ©S'ÂÃÃå¶é•jß^Ê,WË"§J£ÑÈæÍ›ùꫯˆŽŽ6 X?øàÖ¯_Oxx8¹¹¹„……ñ /àìì|õظh¼ñ©Âÿü7æœÇÎuË9›.°ýprrÂh4¢×ëåÇt:ƒ€6mÚàëëË–-[ä$MF£‘cÇŽáîîΜ9sD`sÉÍÍåÃ?ä¾ûî“Öòòr^zé%NŸ>M@@_ý5C† áÉ'Ÿ´tqá1™L¤¥¥1gÎ^{í59`=~ü83gÎD¡PàààÀÿþ÷?¦M›Æ Aƒ,]dAøGŒF#7ndþüùÄÄʬ³fÍbóæÍ„……ñóÏ?ÁóÏ?/wH_ŽÜ}·XË2 ÌŸ?Ÿ¢¢"³€µ¬¬Œ—^z‰¼¼<üýýùúë¯>|8=öØ¿wa!üò jéZ ­A³Ÿ*8À²eËØ¼y3îîîfÛ233Y½z5=ö#FŒ ##ƒ‡zˆäädxõ\ñ·/öØ…^s‰çFjkkÏ{\¥R™ öóó#88˜ 6Я_?L&{ö졬¬ 777œœœHJJbذa( 6mÚÄÇÌÛo¿}Íö‰Ð´JKKY¾|9«W¯&==ÝlÛöíÛIMMeöìÙDDD°téR>þøcn¿ýv,]tA¸"'Nœ`ùòå¬_¿žêêjùù{{{>ýôS,X@\\œÈþ+\7öíÛÇòåËÙ¼y³Ù而Œ Ö®]Ë“O>ɰaÃ8räS¦LaÀ€ôïßÿŠÞÿðaiþj|¼¥k*ܨþøã¶nÝʺuëèÝ»·Ù¶mÛ¶‘žžÎœ9s ã×_eîܹŒ5 ÿ+z¥ÆŒóW…¦Ñìc´”J%ÁÁÁtìØñ¼mûöíÃ××—>}ú Ñhh×®7Ýt[·nµôçtI¤k×®çý<ûì³ÔÔÔ˜=wúôéüúë¯Lš4‰É“'³téRlmm±¶¶&00§Ÿ~š©S§rÿý÷óÐCñÐCqë­·âççgéj WH¡P`ggG\\Üy½í»ví¢G„‡‡£ÑhèÕ«þþþìܹÓÒÅ„+¦P(ðôô¤K—.fà »víbĈxyyaooÏ­·ÞJii)™™™–.¶ \1¥RIÛ¶m‰ŒŒ}úàããî]»®øýׯ‡ìlK×Rh-šýktt4ÑÑјL&V¬Xa¶íĉØÛÛËÃa5 ¡¡¡lذÁÒŸÓE=øàƒÜrË-ÜæîîŽsçΕïžuéÒ…ï¾ûŽ%K–àååÅÈ‘#yóÍ7ñõõE¥RqÏ=÷ЦMÖ­[‡ÉdâóÏ?§oß¾¨Õj>ýôS|}}å÷æÛo¿%88ØÒƒpWWWî¼óN233Ï;v322èÕ«Vv9º¹¹áááAFF†¥‹-W¬mÛ¶´mÛ–­[·²gÏùq“ÉÄñãÇ :gqÉàà`8s挥‹-W,66–ØØXôz=kÖ¬1Û–••…ƒƒƒm6l\®W*•Šøøx’““åÇ>Œ••–.ž 4‰¸¸8 ÉËˤáù¼â¶JQü¹´º ´H >|˜º?ÔÜÜ\òòòΛšv199Ч4’@šB‹Š”ºté‚ÉdbÉ’%³zõjN:E¿~ý,]4Ah={ö$;;› 6PXXÈ¢E‹0™LtëÖÍÒE„«¦T*¹ùæ›IJJbïÞ½deeñóÏ?vÕóW¡¥èÚµ+z½Þ¬­’——Gß¾}¯èõ55pN^2Ahqzõêʼn'ظq£ÜVQ*•WÜVIJ’†· Á?ÂuÎbchƒ‚‚èÞ½»Ùœ<'''^ýuæÎˤI“pssãÅ_¤C‡–þœ.¨¡¡ôôtêëëéСÃyCÞª««IOOÇÚÚšÈÈH4 ¹¹¹Ñåo©ÓŠŠŠÈÎÎ&44”úúzŠŠŠˆmQCý„ÆÁÁÄÄD³¡¼‘‘‘ü÷¿ÿeþüù|õÕW„„„ðÎ;ï`cccéâ Â?æîîNbb¢œ-U¡P0räHªªªxûí·1 DFFòä“Oš-#׋àà`ºuë&gv©­òæ›oòÙgŸ1iÒ$ÜÝÝyñÅ »¢÷LI?¿2‚`q111çôëÔ©Ï=÷óçÏgÞ¼y„††òÖ[o]qcÇ`ÀK×LhM,°öë×ï‚wN£¢¢xçw(**’—üh©***xá…8rä³gÏfäÈ‘r€i2™Ø³g<òíÛ·ç»ï¾ÃÍÍßÿE‹±eËù}JJJxöÙgÑjµÌž=›åË—óÓO?±iÓ¦ë"apa¾¾¾Ì˜1Ãì1•JÅ AƒˆŠŠ¢²²ÿfÏl-M¥cÇŽç­©meeÅ„ èß¿?z½‘,L¸n],ktt´ÜVi\òãJ‰5X…–ãþûï?ï1•JÅàÁƒ‰ŠŠ¢ªªê·Uî½Ú¶µẗ֤́Ef)rqq¹l‚Ž–¢¦¦†ššV¬XÁСCå»z½ž?þøƒœœ<==1™LÔÖÖRRR"¿>??Ÿ§žzŠÊÊJ¾úê+|||¨««3{ŽÐúøøøàããcébÂ5¡R©ÄœU¡Õû·m•Ñ£Å`áúàëë{Ùdb"f9 M­EÍa½ÞFt:=zô`×®]f™1kkkÙ¾}; }}II S§N¥¼¼œ¹sçâççgé* ‚ ‚p uìb9mA„+×"ï°^+F£4§¾^úÝÃΞ•ﮨƒ¬­A©½¬¬¤ä ­%U[ NNçÏ= ¥²²’;wrË-·žžNCC:uâèÑ£ç•åÌ™3L:•üü|¾ûî;‚ƒƒ-ýñ‚ ‚ ‚ ´(7TÀªÕ²epò¤ôû]wÁÂ…0llÙ"e4 •J `àÐ!é¹]»BFôê={š¿¯‡‡½zõbéÒ¥ 8…BÁªU«8p VVVç¬Z­–'Ÿ|’äädÚ·oo–ÌAAAAÜP«­-LžlþXã²i‰‰~͘1—_•JÅðáÃyüñÇÉÎÎÆÑÑ‘mÛ¶1sæL’’’Î{þñãÇéÓ§¿üò 'NdÞ¼y¼òÊ+–þxAAAZ1‡µ‰téÒ£ÑÈÎ;IIIÁh4Òóï·bÿÄìÙ³‰gúôé|ÿý÷¬X±£Ñhéj‚ ‚ ‚ ´"`m"jµšÁƒ³bÅ 6lØ@—.].:Ô×ÁÁ”J%wÜq={öä7ÞàìÙ³–®† ‚ ‚ B‹!Ö&4lØ0öïßÏæÍ›5jÔ½ÆÁÁ7ß|“††^}õU9Óp]];wîdÇŽòÏáÇihh°t5AAAšÅ 5‡µ©) T*J¥÷‡……LMMœõW©T¢R©ä×(•JÔjóÝÇLJ'Ÿ|’W_}•Aƒ¡P(ÈÏÏgÌß&ÐvéÒ…¯¾ú OOOKW]AAášëUðòòbÛ¶mòïîîî¬[·Îì9/¾ø"/¾ø¢üû´iÓ˜6mšÙsT*'NdâĉòcO?ý´¥«'‚ ‚ ‚`QbH° ‚ ‚ ‚Ð"‰€UAAAh‘ZÜ`“ÉDmm-555X[[ãèè(Ï„ÖÀh4RYY‰N§ÃÎÎ;;; …¥‹%MÆ`0P^^ŽÉdÂÁÁkkkqŒ ­ŠÉd¢¦¦†ÚÚZllläÌÿ‚ÐZˆ¶ŠÐ’´¸€555•o¿ý–ŒŒ |||˜0a=zô8/Q‘ \ôz=IIIÌŸ?Ÿ³gÏÁ„ èØ±£¥‹&M¢®®Ž¥K—ò믿b0ˆeòäÉxyyYºh‚Ðd:Äwß}Gff&¾¾¾Lœ8‘„„³$‹‚p½ÒëõlÛ¶ï¾ûŽÒÒR"##™8q"–.špƒjQÝÕÕÕ¼üò˨ÕjÞÿ}ºuëÆ[o½ÅñãÇ-]4Ah¼þúëôèу÷Þ{€W_}•ºº:KM®šÉdbíÚµ|óÍ7Lœ8‘^xÌÌLæÎ+–äZêêj^zé%lllxÿý÷éÚµ+o¾ù&YYY–.š 4‰£GòÆoЫW/Þ{ï= ¯½öõõõ–.špƒjQkrr2:Žû￟ððpÆŽ‹““›7o¶tÑ¡Ilܸ‘€€î¾ûnÂÃÃùÏþCyy9°tÑ᪠V®\ÉM7ÝİaÃèÚµ+÷Þ{/û÷ïçäÉ“–.ž 4‰]»va4™4i’ÜVqpp`Ë–-–.š 4‰ 6ЦM¹­2iÒ$JKKE[E°˜°¦¥¥áååE›6m°¶¶&66–ýû÷[ºhURRBMM¥‹qÍhµZòóó-]ŒfqèÐ!:uꄽ½=~~~´iÓæ†¿œ>}“Édéb\3555YºלÑh$55•îÝ»ËuîÜ­V{ì§N²t®©ÒÒRÊËË-]Œf‘––†ØØØsC·Uôz=yyy–.Æ5c2™(((¸aî0:tˆ¨¨(lmmð÷÷ÇÏσZºhS[[Kaa¡¥‹qÍèt:rss[l[¬EM -))A£ÑÈ_µZ[·n½ä몪ªHNN&<<¼UÎINNÆÇLJÀÀ@Kåš())!99™!C†4Ù{šL&ÊËË9rä]»vµteEEEÄÆÆÊÇ©““NNN—½Ð—””””„››[«œÏ½dÉFÕj“–œ>}š'NЧOŸ&{O£ÑHaa!§NÂh4ZºŠ²³gÏâìì,ÿîííN§£´´ô’¯ËÎÎfçθ¹¹µÊÄ‹/æŽ;î°t1®™`eeÕäóñ322Z\gÏÙ³g±²²ÂÆÆFƒ··7;wî¼èkL&ÇgïÞ½899Yº M®®®Ž72lØ0Kåš0lÚ´‰Î;7é||½^Ojjj‹ „‹ŠŠèÞ½»Y[ÅÑÑñ’7ôz=)))ØÚÚÊßÖ$//ŒŒ úõëgé¢\UUUlÚ´‰#F4é5¸¶¶–ƒÊ|ÿÖuÑò5 ݦR©ˆŒŒdÏž=(ŠVÙ˜···§¶¶–ÌÌLKåš0´iÓ¦Iëg2™(..ÆÊÊŠàà`KWñ².uŒ;99Fjj*>>>h4K·É………µêù_ƒ&=Æ gΜ¡M›6fbKd2™.Tûúúâêê*ß¹jkXXX«=‡rµ©ë˜Mtt´¥«wE.u·²²ÂÓÓ“ôôtÜÝÝ-]Ô&g2™ lÕǸeeeTTT4Ù{644pæÌ™ë&ºÔ1îéé‰^¯çèÑ£ò(²ÖÄ`0àååÕjq“ÉDHHH“ç ª¬¬¤¾¾žÈÈÈ«zŸÝ) L&&“Iþ¿Ñh¼dcL¡PЭ[7ºuëféâ Âe)•J³cÜh4b2™.Ùã®R©1b„¥‹.W¤ñÜÝÈ`0 Ñh°³³»èk4 ÷ß¿¥‹.Wäß´Ulmmyä‘G,]tA¸"ÿ¦­Ä”)S,]t¡•jQã郞®–‡Ž544pôèQBBB,]4Ah‘‘‘äççËS‹‹‹)((ǸÐ*( :tè@vv¶üXff&jµZ,k#´áááTUUQVVHyŽ;&ÎãB«I^^:€ÂÂBŠŠŠhÛ¶­¥‹&Ü ZTÀÚµkWJJJ8|ø0:Ž¢¢"öïßOß¾}-]4Ah=zô %%…‚‚HKK#??Ÿ^½zYºh‚pÕT*=zô`Ë–-TWWS__ORR...„‡‡[ºx‚Ð$âãã)**"55NGaa!m¡ÕèÑ£ °°Pn«’˜˜hé¢ 7(…©…¥ƒzÿý÷Ù¼y3Ý»w'==___fΜ‰«««¥‹&W­¢¢‚—^z‰’’ÂÂÂHNN¦OŸ><ûì³–.š 4‰'Nðâ‹/âââ‚““àñÇgøðá–.š 4™wß}—¤¤$ºuëFZZòq/×»òòr^zé%ÊÊÊhß¾=»wï¦ÿþ<óÌ3–.špƒjqkmm-{÷îåСC´oßž„„œœœZeáÆc2™¨¬¬dÓ¦MäææÒ½{w:vìxÉù}‚p=1™Lœ9s† 6P__Obb"íÛ·o•É„Wmm-{öìáðáÄ……ѽ{wÑVZ “ÉDEE›6m"//„„"##E[E°˜° ‚ ‚ ‚ ´°9¬‚ ‚ ‚ ‚ÐH¬‚ ‚ ‚ B‹$VAAA¡ER[º7*ƒÁ€Ñh¾Ü9²94Ãeø{¯÷ú W¦q_]l ù:ÿ÷}¬×ë1ÿø:ß\Q“É„Z­6»Nµ†ú W¦ñzüO÷±Éd¢¡¡¸ð>¾Ô9²9\I[üz«ŸX-dóæÍ>|˜§žzJ~L¯×³wï^¾ûî;JKK‰e̘1PWWÇòåËY¾|¹¼Þá½÷Þ‹Z­–uëÖ±hÑ"ŒF#Ý»wgܸq;о}ûøí·ßHMMÅÉɉáÇ3|øpìííÑëõìÛ·ùóçsöìYbbb3fŒ¼u]]+V¬`Ù²e(•J¹~ööö”””0þ|’““qvvfôèÑÜ|óÍ"ûh d0øæ›oðóócذaòãõõõ¬Y³†%K–À¸qãpvv¤e¾ûî;vî܉““#FŒ`ðàÁXYYpìØ1~üñGŽ9BPPãǧsçÎç ׊N§cÓ¦M,[¶Œœœ‚‚‚>|8ƒF¡PP__ϺuëX¼x1&“Iþ6.uQYY)×ÏÑÑ‘áÇsË-·ÈõËÌÌä‡~ ==ÀÀ@ÆOTTT³ÕO¸r Ìš5‹aÆ+?^]]Í·ß~ËöíÛqpp`ðàÁŒ9RÞÇ'NœàÇäСCøùùqï½÷‹J¥ºì9²9TUU±bÅ Ö¬YCii)‘‘‘Œ3†˜˜¹~óçÏ')) {{{ ÄÈ‘#±¶¶ ;;›ü‘””|}}¹÷Þ{éÒ¥‹\¿ýû÷3þ|Š‹‹‰ŽŽf̘1„„„Xzw PWWÇÌ™3yúé§ ?}ú4ßÿ=ÄÓÓ“{ï½—¸¸8Ôj5ƒƒ²`ÁòóóéÔ©÷ÜsíÚµ»¢sds(..æûï¿gïÞ½ÔÕÕÇ„ ä:æææòý÷ßsàÀ<<<¸÷Þ{‰—ë—’’‚ ÈËË£cÇŽÜsÏ=´oß…BÑbÚb•9|ø0¿ÿþ;Ï?ÿ¼|Ž6>|˜ pêÔ)ÂÃÃ;v,:t÷ñ–-[øñÇÑëõtëÖ±cÇâáá\þÙ222øé§Ÿ8|ø0†Aƒ1jÔ(\]]åúýðÜþøcFŒABB¿ýöåååÄÇÇ7[ÏΙ3g˜:u*ÖÖÖ<òÈ#8;;óÕW_¡Ñhˆ‰‰!++‹ÿþ÷¿ÄÆÆ2zôh6mÚÄÎ;åÆþªU«øòË/5j111,Z´½^OTTF£‘Ù³g³ÿ~&Nœˆ““óçϧmÛ¶´iÓFô^¶F£‘ŠŠ RRRøôÓO‰ˆˆ sç΀Ôc·~ýzþ÷¿ÿqë­·Ç’%K¨©©¡K—.FæÎËŽ;˜0annn,X°€€€‚ƒƒihhàÉ'ŸD©Trÿý÷SPPÀ¢E‹HLL”Þkmß¾}¼ð ÄÇÇsï½÷RPPÀ‚ èØ±#~~~lܸ‘O>ù„#FЭ[7~ýõW*++‰‹‹Ãh4òù石mÛ6î½÷^<<%%%ôìÙ“²²2žzê)¼½½?~}X¾|9yyyôèÑ“ÉÄüùóY¹r%cÇŽ% €~ø777¹SêZwX›Ù¼yóزe §N:¯×ü?þÀÓÓ“Gy;;;yöÙgå5i—.]ÊÀ7nZ­–E‹ѧO~ýõWºuëÆ}÷ÝHÁÁ¼yó1bD³õ^ïÚµ ^xáèÑ£uuu,Y²„û+WâááÁ#<‚ƒƒNNNL:•””:tèÀï¿ÿNÿþý?~< ]þùgHUU»wïæ™gž¡_¿~9r„ßÿîÝ»‹»¬-DEEï½÷»w聆°Ðl›V«å·ß~#11‘ &RÿÛo¿eèСèt:¶lÙÂã?ΠAƒÈÊÊâ÷ß'!!;vPUUÅ믿NXX;wæ¾ûîcÓ¦Mòû]këÖ­#66–G}¢££)--eéÒ¥ÄÄÄð믿’Àĉ)€ÿꫯ>|8ƒ7òØc1xð`@ºõûï¿Ó£GvïÞMyy9/¿ü2áááDGG3qâD6nÜÈþóKïZáOYYY|úé§ù„Q£FaccsÉsdst®>|˜ââbfÏžMûöíP©T¼ñÆLŸ> 6 T*yüñÇñóó#88˜|;w2dÈ–,YB§NxàP*•Ìž=›¬¬,ìííY¹r%'NdôèÑòûï¿Ó³gÏkÚ¹.º{šÙĉù¿ÿû?³!dÒÒÒˆ•o«âååEjj*õõõdee‘ ?¿[·n‘ŸŸÏ‘#G̶EGGS__Ï©S§š­n666 4???@úÛÙÙÉãàSSS‰ŽŽÆÖÖ€6mÚàëëËáÇå‹Ä¹uˆçìÙ³pæÌjkkåai 'MMM•çJ –çääÄO<Á{ï½'eo¤×ë9vì˜Ù>Ž¥ªªŠÜÜ\ )//§k×®òö„„Ž9‚V«åÈ‘#øûûËöìììˆŽŽæàÁƒÍV?†*S·²²B­V£Óé.X¿˜˜jjj8}ú4EEE”••™ =z”úúzŽ9‚¯¯¯\?[[[bbbšµ~Âå3cÆ ^|ñÅóç«s„„Ž?Nuu5¸¹¹Éß FC\\œ¼/uŽl.íÛ·§ÿþòïvvvò|¨ÒÒRΜ9sÑúeffâââ"7ÌU*ñññfõ‹ŠŠ’뀿¿?‡j¶ú —Ç{ï½ÇÃ?|Þ¶'N`ggG»víäÇzôèa¶;v숣£#>>>“’’rÙsdsP©TtéÒ….]ºÈ9::ÒÐЀÉdâĉØØØvÑúEFFâä䀷·7!!!¤¤¤`0ZD[L¸¼‘#Gòé§Ÿ2`À€ó¶¥¦¦†››îîî„……ÉÇ@ZZšÙ>îÔ©F£‘ìììËž#›ƒµµ5}ûö5ë qppÛâiii´oß^îŒrss#<<ü¢õëØ±# …‚'NPZZJ~~þyõËÊÊ¢ªªêšÖK¬ÍÌÓÓlllÎÛ–››‹«««<4ÊÍÍ GGGN:…N§£¨¨H#жm[***ä/ȹÛÐjµœ={¶Ùê6dÈ&Ož,{ÉËËã?þ wïÞòﯟ““§NB¯×ŸW¿àà`*++)++£¬¬Œúúz³y !!!œ:uê¼»‚å¨T*|||ðññ9ï®·Á`   ÀlR[[Kii)ÔÔÔ˜õ臄„››‹N§#??[[[ììì)Xô÷÷';;»Ùê÷ÐC1dÈyØËîÝ»9xð }úôÁh4ž÷=lÓ¦ õõõ”””PYYIUUÕyõËËË£¡¡3gÎ`cc#Æ€€€f­Ÿpy666øúúâééyÞ¿êêj***ÌŽΜ9ƒV«¥°°Fƒƒƒ }_å}|©sdsyóÍ7éÔ© ^¶l&“‰Ž;^´~Ô××SXXˆZ­6«_PPYý\\\ä¡w®®®¸¸¸““Ó¬ûP¸4üýý/8ﲸ¸…B!l µEþ¾ÏÿÎÎÎxxx}ÙsdshÓ¦ ï¼óŽPWWWóã?Ò¡C<==)..8¯~'Ož”ëçìì,Ïwtrr’ëg2™ZD[L¸<777üýýåëí¹òòòprr’o988àååevŒŸ»ýüü0]öÙzôèÁ³Ï>+_GJJJX¼x±Y[ÜÑÑQ®Ÿ½½=ÞÞÞrýrssÍÊïëë‹Ñh¤°°ššÊËË/X¿ºººkZ/1$ø:p©€¬1Ûð…F‹seee¬]»–_~ù…°°0|ðÁK>ÿRwHFãEëw¹ÏF¸>4§›Ãv¹}l‰;ì§OŸfÅŠ,_¾œ¡C‡2hÐ ´Zí%ëw1-±~BÓ2 ˜L¦‹n¿Ü>nîcÀh4rìØ1~þùg’““™2e QQQìܹ³UÔOhzW³-ÑViÕòÉ'ŸPQQÁÌ™3ñöö¾èó³þ^/õšÞÕìãË#¯…ÊÊJ¶oßηß~‹‡‡Ï>ûì¿®_ã(›KÕÿZ×O¬-\ã°Ú‹±²²’{úþN£Ñ4kV2æäÍž=›S§N1f̆ bÖSÙ”õi¸šH¸t}kn¼›ÓŒF#ûöíã£>B¥R1}útâããÑh4 X/÷=´µµ½d2Žæ¬ŸpmØØØüë}|¹sdSÓëõ¬ZµŠÏ>ûŒˆˆÞ}÷]"##/™ÉÆÆæ’Û/w _è.‡p}¹š}ÜÜmNÇgŸ}ƪU«2d#GŽ$44´ÕÔO¸6.µÕjõGN6ºÜ9²©óᇒššÊ¨Q£9r¤Ù]Ñë±~bHp N~~¾ÜËQPP@ii)AAAX[[d64,55ÜÝÝi×®Ù¶ŒŒ 4œ†º94ftsscþüùÜu×]fÁjxx8gΜ‘{* 9{ö,ÁÁÁXYYlV‡´´4œœœpuuÅÛÛòóóåí‡&((HdÞ»N¨Õjyw££Gbkk‹»»;žžž¸¸¸››+o?|ø0mÚ´A£Ñо}{*++©¨¨¤òÌÌÌfMd±gÏ^|ñE†μyóèÕ«—<O¥RjV¿cÇŽamm‡‡¸ººšÍÕ:|ø0h4ÚµkGuu5åå倔¤*##C$긎¸ººâééi6ÄõðáÃøùùaccCÛ¶m©¯¯§´´‚Ã#GŽÈûøRçÈæòÃ?ðùçŸ3cÆ 9yÒ¹Cx½¼¼Î«Ÿ¯¯¯\¿††¹~ƒôôôóê×8—ª°°âââf­Ÿpu1fC\>l¶ÏþxöìYòóó ¹ì9²9ÔÔÔðÎ;ï’’ÂG}Ä“O>i¬ÈCƒ/T¿ÂÂB¹~%%%äåå‚R©lm1áꄇ‡S\\Lmm-åååœ:uJ>NÂÂÂÌöqVV Íg¾Ü9²9óüóÏ£×ëùâ‹/¸ï¾û̾_áááœ={–šš@J–™““#×/<<ܬ~'NœÀh4âãニ‹ ÞÞÞ¬_c[èZ-ý$>>žýû÷SSSƒÑh$++‹ââbâãã±³³£S§Nlß¾]^ÐzÇŽ´iÓ†àà`ºté"ok¼ äääd–áZ2™Llذ•JÅ< ßqª¯¯—ï<ÅÇÇsàÀª««1œ8q‚‚‚ºw­íyõÛµk~~~Œ££#{÷î•zÞ¾};ݺu‚¯Ë»÷ìÙƒ»»;!!!àééÉîÝ»Íöq×®]±µµ¥K—.äççsòäIŒF#•••¤¤¤pÓM75KùM&¿þú+QQQ :T^­¾¾N‡Z­&66Ö¬~{÷îÅÅÅ…ÐÐPüýýññña×®]fõëÒ¥ vvvÄÆÆRPP Ïõª®®æÀÍV?áêùøøHRR’¾Ô9²9˜L&~üñGn½õVºvíŠÑh¤¾¾žúúzôz=^^^‘””$ãIIItîÜggg:wîLEEòk“““ILL”ë—’’BUUF£‘œœœóx-[dd$Z­–ôôtù<¶cdz}œ––Fyy9F£‘ÜÜ\Nž<ÉM7ÝtÙsdsÈÏÏgÍš5<òÈ#„††ÒÐÐ ãF£‘ˆˆ.Y¿ôôtJKK1äååqâÄ å„N–l‹ W/>>žcÇŽQTT$ÏÝÌÌÌ”ÏÓݺucÇŽò>NIIÁÚÚš:\öy­™L&öìÙC^^S¦LÁÅÅÅìo¬_FF………òÜÛcÇŽ]´~‡B­V§§'ÁÁÁçÕ¯cÇŽ×|­a1$¸=ôVVVDGGÓ­[7^{í5ú÷ïÏîÝ» k¶€®¬¬Œôôt222X¶l™Ù¶¡C‡òÑG1vìX^zé%^|ñEÙ²e <ò^^^€tŒüñÇœ8q‚ââbN:Å«¯¾Šµµ5QQQtïÞ×^{²gÏÚ·o/7”„–ÏËË‹x€·Þz‹S§NQVVFFF¯¼ò ¶¶¶DFFÒ»woÞxã ÌhÓ¦¼T×åΑ×Ú™3g8yò$ï¿ÿ>ï¿ÿ¾Ù¶çŸžûî»û￟·Þz‹ÜÜ\***8r䯾ú*vvvDDDЧOÞzë-ÌÁƒ ë7`ÀÖ¯_Ï /¼@çÎY»v- h¶`E¸zaaa 8Y³f‘’’Bzz:^^^òRd}úôaÕªU̘1ƒØØX6nÜHŸ>} C©T^öy­effR\\|Á¥Ð~ùåbbbfÏuìØ1ºwïNxx8/½ô=zô`ëÖ­tëÖ¨¨(îºë.f̘ÁôéÓñòòbÆ òš²“&Mâ­·Þ"??Ÿªª*ÒÒÒxå•W®yý¦æž,ÒA£V«Í.Ô&“‰üü|–-[Æ™3gèÕ«ݺu“{e{rÖ­[@¯^½ˆG­VËI2V®\‰V«•_Û\ó&ôz½œòúשּׂ­‰•3è-[¶Œüü|éÞ½»¼nScOκuë0rR­VËæÍ›INNÆÝÝЮ];1$¸jÎêååev¡6¤§§³zõjt:¼ç)7®Åºk×.\\\èß¿?áááò>.++cýúõ>|˜:póÍ7ãííÝ,ó˜µZ-G½`&™™™xzzrüøq±²²B§Ó±oß>,XÀŽ;ä×*•JJJJÈÌ̤¶¶–/¾ø‚;vàåå…N§ã§Ÿ~bùòå¨Õjüýý)))!++‹òòr¾üòKöìÙƒ··7555üüóϬX±[[[üýýQ(–þÈ„V¢¸¸˜ÿû¿ÿ#(('''KGšE~~>_|ñ!!!888\õû;vŒï¾ûŽ›nºÉÒUnpF£­V €R)î‹­—Á`@«Õ¢R©D»øg’@§ÓñÍ7ßpûí·süøq¶mÛÆ°aÃØ´iF£‘%K–pÏ=÷päÈV­ZÅ]wÝ%ÿ®ÓéøòË/3f Geÿþý >œü½^Ï–-[1b>ú(§OŸfÙ²eŒ1‚‰'²sçN8À°aÃØ¿?kÖ¬aذa<ýôÓäååñóÏ?së­·rÿý÷³{÷nvïÞÍ AƒÈÈȰôG&´"eee|ûí·[º(‚ÐlŠ‹‹ùî»ï(--m’÷ËÎÎæë¯¿¶tµ¢¢"{ì1vîÜié¢Â5•œœÌäÉ“)))±tQZ=µ¥ @AA|ðÏ=÷÷Ýw:Ž3f°páBâããùøã™4iS§N¥¾¾žéÓ§³víZŽ9ÂܹsyóÍ7=z4z½ž>ø€O>ù„áÇ R©xâ‰'2d©©©tîÜ™Ç{ŒÉ“'“——Ç=÷ÜCJJ 666¨T*ž{î9úöíËŽ;HLLdÚ´iŒ;–¬¬,ù¹ááá–þØ„ëŒÉd¢¶¶–ªª*¬¬¬pvvF¥R™m¯ªª¢ººœåÞùs_«Ñhpqq‘_«Óé0™LF***Ðh4899a4©¬¬Ä`0àêꊕ• €Ô+ZYY‰••NNNèõz*++1™L¸ºº¢Ñh,ýq ­„Éd¢¦¦†êêj¬­­ÍŽëÆíÔÖÖbgg‡£££Ùq_]]MMMÍyß™Æc¹ñ¸ÿ»Æ»\µZ\ê…¦g4©®®¦¶¶[[[œ1™L”••±}ûvú÷ï^¯G¡P ×ëQ©T”––ÊçoN‡Z­¦¢¢½^‹‹ VVV”——£ÕjqttÄÎΣÑ(?·¬¬ “É„‹‹‹üÚsŸ+îr ׂÁ` ¬¬ ƒÁ€““¶¶¶ rssIJJ¢¢¢BÙÐЀF£¡¦¦“É„““Z­–ªª*L&ØÙÙÒèJƒÁ€B¡ ¼¼¥R‰³³3 …‚ÊÊJt:ÎÎÎØØØXú#°8qkŽ;†ÑhdøðáX[[cmmͳÏ>KAAyyydddð¿ÿýlll¸å–[غu+YYYâååERR9r„ÚÚZüüüèÔ©îîî$&&bee…««+žžžF‚‚‚èСƒÙs{öì‰F£ÁÃÃ777ù¹‚ðO¤§§óÖ[oqðàA¼¼¼¸ï¾û¸ûî»åí;vìàí·ß&%%…^xáQ*•$''óé§Ÿ²oß>ÜÝݹçž{¸÷Þ{qttdÙ²eäææ’““úuëðððࡇ"33“•+WR[[Ë=÷ÜÃÔ©SY¸p!•••¤¥¥±eË|||xøá‡9tèkÖ¬A«Õ2iÒ$¦L™"ùB“Ø·oï½÷©©©øøøðÈ#0bÄ@jðoÚ´‰µk×rôèQ"""xá…ˆG¡P°uëV>ûì3<ˆŸŸcÇŽeܸqØÚÚòóÏ?pôèQV¯^Í[o½%ÿM£ÑÈöíÛY±b“'O&44Ô҃Р­^½šÏ?ÿœŒŒ BCC™:u*;wæã?æÌ™3Ì›7OOOœœœX¿~=~~~Ì™3‡yóæaooÏO?ý„ŸŸßÿ=•••ÜqÇtìØ‘Ï>ûŒüü|ºvíÊÛo¿MYY‹/ÆÓÓ“  Õj;v,|õÕWЭ[7fÍš…§§§¥?¡•©©©aÁ‚|÷ÝwÔÔÔгgOžxâ jjjøöÛo9{ö,ï¾û.Ï=÷ŽŽŽ|úé§ôìÙ“¯¾úŠˆˆ~øaÞ~ûmvíÚ…^¯§gÏž<÷Üs´iÓ†;w²eËL&¿þú+666üç?ÿA«Õ²xñbJJJ¸ùæ›yÿý÷±²²²ôGaQbHp PSSƒ›››Ù]€€âââ(++ÃÚÚÚ¬ñ¬Ñhä^Ä“'OÒÐÐÀ¬Y³äŸï¿ÿžŽ;Ê¥F£¹âÝÚÚZÜ]š\VV=öööö,X°€ÿüç?¼÷Þ{¬^½Z~Î/¿üÂĉùå—_puuåÃ?¤²²’S§Nñä“ObkkË’%K˜2e |ðß}÷û÷ïç­·Þ¢]»v,^¼¦L™Bmm-ÿûßÿ¸çž{øæ›oHIIa÷îݼþúëÄÅűhÑ"™2e ÿ÷ÿǨQ£øüóÏIOO·ôG&´GŽáñÇÇÛÛ›~ø{™3g²mÛ6´Z-¿ýö=ö?ýôƒ?þ˜ºº:²³³yì±ÇðññaéÒ¥ÜsÏ=¼õÖ[,Y²€;wòòË/SQQÁsÏ='ÿM£ÑÈ–-[˜:u*áááXúcZ¡]»vñÌ3ÏÐ¥K/^LÏž=yôÑGÉÏÏçž{îÁÃÃѣGÓµkWNž<ÉG}ÄòåËyâ‰'æÌ™3|ýõ×ìÞ½›¹sçòì³Ï2kÖ,>ûì3^}õUfÏžÍÎ;Y¸p!¹¹¹|þùç>|˜o¾ù†)S¦ðòË/óã?òÆoðÖ[o±yóf–.]jéEh…æÍ›ÇG}ÄôéÓùþûï9sæ O=õíÚµcĈ¸¸¸0qâDüýý©¬¬déҥ̚5‹ØØXFÅG}Djj*~ø!³gÏfÿþý|ýõ×F222øàƒÐétüüóÏôëשS§rèÐ!>øàž|òI–,Y"ߺ‘‰[-€ƒƒr’€ƒ²cÇzõê…V«E¯×ËÛjkkå`444???Ö¬Y#o¯¬¬dïÞ½x{{[ºj‚À¶mÛ(((`É’%¸¹¹Ñ¥KŽ;Fii©|,ßsÏ= 6 €;3÷Þ{­VËï¿ÿŽR©äÍ7ßÄÓÓ“ððpŽ?΂ xì±ÇˆŽŽfüøñ899qûí·³hÑ"¦M›†»»;,Y²„ÊÊJâââ;v,ÖÖÖÜvÛmlݺ•§Ÿ~Z6¼téRª««-ý‘ ×9£ÑȺuë0¼öÚk¸¸¸ÃáÇ)))ÁÓÓµZÍĉ8p £Fâûï¿G¯×óÃ?àããÃË/¿Œ««+!!!dddðý÷ß3~üx\]]y÷Ýwqpp`õêÕ˜L&¶oßδiÓ7nãÇ¿á{å…¦§ÓéX¸p!;wfÚ´iØÛÛÓ¶m[RSS©ªª¢M›6X[[ãïï««+¶¶¶L:Õ,)˜««+“'O&**Ѝ¨(xàÆŒCbb"µµµ$$$Ès½¼¼x衇ˆŒŒ$44”‡zˆ &УG*++éÒ¥‹˜G(4¹ÚÚZ~úé'zè!†ŽJ¥bÆŒ|ôÑG˜L&|}}Ñh4ÉÃ|n¹å¦NŠJ¥bêÔ©tèÐnݺammÍœ9s¨««“ŸÊý÷ßOPPcÆŒáí·ßæÑG%&&__ß&Íup=k бcGÜÜÜøå—_¸çž{¨¯¯gÖ¬Y8::rï½÷ÅW_}ÅóÏ?OMM .¤¾¾€ˆˆøì³Ï¸í¶Û0 ¼ÿþûäääoéª ™™™òqÞhæÌ™( rrrèÖ­›¼­ñ.¿Á` ##ƒÒÒR¦OŸ.o?uêÅÅÅ Ú´is^üqH»µµµÙ\Ùàà`³ß•J¥Ü¨²±±Y-…&a08~ü8QQQ¸¸¸È¿ûî»( Ž=ŠZ­¦K—.ò¶Æã^¯×sôèQŠŠŠ˜6mš¼=++‹ŠŠ ù¸7›ÛÔø=9{ö,Z­VÌ箉ÚÚZ²³³ILLÄÞÞÒyóæ¡Ñh8}úôy¯ $88Øì1;;;|||Ìk×ÚÚÚÒ‹Ð  Óéˆ•Û ±±±|ñÅ—œWš˜˜(?„ ¼÷Þ{ 0€„„úöíKBB‚|~öòòÂÑÑÑìõ€tM£%"`m<<}pttD¡PpÛm·1räH9ðññ¡¡¡A¾Ð8;;óÛo¿É_Æ1cÆÈÏ 3{®»»;kÖ¬ ~ákß¾½<,×ÉÉ ƒÁÀƒ>ˆ‡‡÷ÝwßE_§ÑhˆŠŠâĉÜvÛm¸¸¸`4ùþûïÉÎΉ‘„K¥RÑ®];~øáª««qpp@¯×s×]wÑ¥K9‹û…XYYî]»¸ýöÛqttD§Óñõ×_“——wÁΦ— :”òòr¶nÝÊ믿Îÿýßÿ5É:¯‚ÐÈÖÖ–àà`’’’x衇°µµ¥¢¢‚ÁƒóôÓO‹Ñ]B«áííR©äÀôêÕ ¥RÉÖ­[™2e «V­ºìëËÊÊxë­·èׯ?ü0=ôË–-cüøñ¼ÿþû–®ÞuED-„B¡À××—Ûo¿Aƒáââ‚B¡@§Ó1kÖ,.\ÈðáÃñ÷÷ç×_¥C‡òðJ…BŸŸwÜq#FŒÀÉÉIî­Q*•¨Õjùw…Ba–´I¡P V«Q*•ÿ蹂ðOôîÝWWW¦OŸÎúõë™;w.ÉÉÉôîÝû²Açˆ#8sæ /¼ðÛ·oçÇäÕW_•‡ñ BK¤T*8p z½ž_|‘72gÎŽ;Fbbâe{Ôïºë.RRRxå•Wعs'_ý5ï¼óÎe³ * \\\xúé§INNfåÊ•òHAh VVVÜyç áºg0(,,D¯×ãåå%ç"0”””P__··÷E³²×××STT„R©ÄÃÃã’ ›„ « ‚ ‚ ‚Ð"‰Ô‚ ‚ ‚ B‹$VAAA¡Eºîׄ09rä’©þ¯wõõõ¨TªV»xpc¢›k1ÏE¡Ps]'ÐÑétìÙ³‡ºº:Kåš©®®ÆÞÞ¾ÕÎËÖétèõzlmm›ô}M&666tíÚµÉß»9Õ×׳mÛ¶V5±qi›ÖJ«ÕÈIušŠÑhÄÅÅåº_*E«Õ²yóæV»—Ñh¤®®®ÕÎWmLheeÕäûP¯×Bûöí-]Í«RXXHJJJ«m‹ëõz.»ëõÊh4R[[{MÚbF£‘¨¨(¼½½ÿõ{\÷gN£ÑÈðóóÃÃÃÃÒŹ&öíÛ‡——~~~–.Ê5QZZÊ¡C‡äL­MéСC899]×kuu5ûöí£OŸ>–.Ê5³cÇFŽÙjÖÜÜ\N:EÏž=›ô} »ví"44ôºX‹ŠŠÈÈÈ W¯^–.Ê5“””ĨQ£,]Œk&%%+++šô}+++Ù¹sg«XSSS8p ¥‹rMÔ××sàÀn¹åKåš0lÙ²…N:5yò³‚‚öìÙsݬ¹¹¹”––ié¢\ùùùäääлwoK嚨®®fïÞ½ :´ÉÛb™™™¤¦¦ÞØ+H‹XwèСÕtØÛÛËK~´6uuuÜäï]VVÖ*îÚ8::eéb\3ÖÖÖ„……µÚ€µmÛ¶DEE5yc^§Ó‘••Õ*>7ŸV}Œ[YYÑ¡CKãšñññA¥RáîîÞ¤ï[ZZJVV–¥«×$—ßjt:nnn­vY£Ñˆ››M~‡ÍÙÙ™êêjKWñª©T*ùZ×…„„ЩS§&¿Ž· øøøÐ¶mÛ&oS ***®ê=ZEÀÚÚµÖ@¼‘­­í5 V…ëGxx¸¥‹pM9::âèèhébÔšƒUÖœn\¦Õ«J¥’ÀÀ@KC° ‡V=­ÃÊÊŠK㢮ÿ[O‚ ‚ ‚ B«$VA„ëII :€B§ÃåèQTz½¥K%‚ ‚pM\Ó!Á555dddЩS'9íÉd¢¸¸˜cÇŽaggGxx¸Ù-v£ÑHNN999xzzÞj³ê ׿‚‚ÊÊʈˆˆ0{\¯×“’’BMM ¡¡¡øúúÊsiõz=éé锕•L@@@«ÍªwÃ0 ¸ììÀÉ©iÞ³¶„‚:ll ;^}¢¢ * “RI½»;Æk8O;33[[ÛóæíTUU‘ššŠB¡ ]»v¸»»Ëó^êêêHIIÁh4Š——W«˜g+´N‡" À,9ŸÉd’“]¨­b0ÈÉÉáÔ©Sxyy&Ú*B‹¤×ë9xð ‘‘‘fóoF#§OŸ&;;www"""ÌŽa½^OZZåå墭"XÜ5;»FvîÜÉ¢E‹xÿý÷å€5==×_ýŸw‚ƒƒyî¹çäù/‹-báÂ…¨Õjôz=ýû÷ç¾ûîkµi¤…&P^7Ba!<òèt°hœ9ƒ÷‰Ç޽&V¯×³hÑ"ª««ÍÖŠŠ æÎKrr²¼ÄÃý÷ßÏÀ©­­åóÏ?gÛ¶mXYYa43f £G¶ÌgW_ÕÕ`e%ZÕÕ°};”•JwÞ)=/;Ö¬šˆŽ†@¯‡3gÀÑœ¡¥$&“ìÙÚ¹œNF#\é²µµÒ±eo/Õ¯¼V® ’~ÔjXµ ~úIúÿ„ з/œ=+ƒàí ÷Ý'³&TTHŸoÛ¶ÒßII‘Ê¥ÑHÏõô„¼<˜5 £RI]t4µååèkjP~ü1C† 9­^O± ÆkôÙ7Ë7ß|³YÀš››Ë¬Y³ÈÍÍE­VcmmÍË/¿L»ví(,,ä£>âØ±còÓ¦M#66¶ÙA¸“ÉDAA}ô?þ¸YÀšššÊ›o¾)·UBBB˜6mšÜVY¸p!‹/–Û*dâĉ×u¶n¡õ1™L;vŒÙ³g3kÖ,³¶ôÒ¥Kùá‡P©Tèt:úöíˤI“ppp ¦¦Fn«X[[c4;v,·Ýv›¥«$Ü ®IÀšššÊÎ;Y¸p¡Y ㊊ >ýôS‚‚‚xöÙg©®®fêÔ©,Z´ˆ‡zˆÂÂB>ÿüsÆŽ˽÷ÞËÞ½{yî¹çˆŽŽ&11ÑÒŸ•ÐTNww)¸œÂBpu•ªÚZHO—~¢¢ &F "ž}VzÎþ#½F£‘ÞßÑ‘3z=n×`ýÚ­[·²oß>¾ÿþ{†n¶mÓ¦M¬ZµŠO?ý”öíÛó¿ÿýO>ù„¸¸8:į¿þÊÛo¿M||<óçÏgΜ9ôîÝ»y—e2™ ) ~þY à îâéõ›+}îçÞ-ÐëÁÅüý¡1p©«ƒ„ÇaØ0¸ývi?]ŒÑ™™pú4të&ÈååRçãs~ ©ÓIÏõõ•‚ÏÇaÿ~psƒðp “ž—š ¡¡Òs@:NæÎ•^ߣôì)›7Ão¿IáðáиLÆéÓÒ1uæ Œ-•kçN˜?`Ò$HLü+ØÝ¼YªçãKld¤t×3 @ú; Ý ‚¤çXYIõüí7éõnnðá‡ÒsKK¥N‚ÂB<†GïáAúÝw³~×.²÷í£.) J‹‹ IO§·§'•••lØ°ŠŠŠ&_*£¦¦†íÛ·³aÃ6lØ`–Æ¿¡¡ï¿ÿžââbfÏž­­-¯½öÿ÷ÿÇ+¯¼ÂâÅ‹IKKãã?ÆÍÍwß}—Ï>ûŒ>ø@$žZŒ¢¢"’’’X±bÇÇ`0ÈÛÊËËùôÓOiÛ¶-Ó¦M£²²’gžy†%K–ðàƒRPPÀçŸÎĉ;v,ÉÉÉLŸ>˜˜,]5Aàĉlݺ•¥K—b2™0ò¶üü|>ÿüsFŽɤI“HKKã‰'ž cÇŽôïߟݻwóÛo¿ñî»ïÒµkW¾ùææÌ™C¯^½š<¸ \‰k°æççSPPp^ã$77—ãÇóá‡âáᇇ#GŽdõêÕŒ?ž={öàééɰa𶶦k×®téÒ…-[¶X.`Íχ¬,© Bz=ìÛ'5t;t~ZÓP òr©}äDDÀ ARC<5Uª»››t'ÈÚZº#—•%ýëâ"}*•4XY™.»wÃ'ŸHÏ?^ pï ÕÖJÿo :6o–‚¡À@xòIé½Ö¬M›¤¡q4xì1)€±±Á`0°sçN6%'“™™IUUÏ]ƒ5³Nœ8AEEÅàÛ¶m£oß¾tìØ•JÅm·ÝFRR×ìÚµ+ÖÖÖ 2„Õ«W³k×®óß&WSiiЩ“ô9·i#]u¸¸Àý÷ŸÿÚöí¥Ÿs98ÀOHûïÞ¿öõ÷ßÃ/¿HïùÀR0\\ o¼!íçnÝþ 33á³Ï ªJ:ÆŒ‘þÿÕWRÐ*uHØÚJßÁ†é{gk+¬55°p¡Ô Ò¥‹Tv[[éŽfRlÛ;KuLH€éõ®®Òß?s>þX:¦;wþ+àôõ…§Ÿ–wq‘ss“Ê8j” 7çAAç^RÀ9 xy¡zù忎_€~ý o_tµµäœ>ÍžŸ~bÓ¦Mèõz ĨQ£°³³ÃÊÊŠ††öîÝËï¿ÿŽwÝuÙÙÙM>L«¡¡AnÄÿýŽQ]]ÉÉÉŒ3FΚ9nÜ8^{í5rrrHJJbøðár¶Á»ï¾›™3g’™™I—.]š´œB+¡×K:%%ÒwÃÕUý‘™‰Õ‰8åä4ùŸ¬¬¬$;;kkëó†ò6“|üñÇqwwÇÝÝ#F°aÃÆGrr2>>> 2kkkââ∉‰aË–-"`ZŒââbrssqpp ªªÊlÛppp`äÈ‘ØØØM÷îÝÙ¼y3ýû÷'))‰îݻӥK¬­­:t(k×®e÷îÝ ýÛµMšÃ5‰² Ä AƒøðÃÙ¿¿üøÙ³g)))1[¹S§NÌ;—úúz222prr’ï4YYYÆîÝ»›÷SÑ餠K©„'`ñb©!;`Ür‹ÔhÞµKºÈ¦§ÃSO5ݼµÃ`€;¤»Ž—[«µ¨HºƒÖØp\±rr¤¡‹÷Þ+ÅÅRóW °u«T_;;˜<Úµ“üóçKõ‰‘^¯RÁœ9pü8øqÒðÇvíàµ× q™…BJ3w.TVJ@ãÔ”9kkôz=§cb¨o\¢²Rú‚ðµ±A¯×óûï¿3þ|î½÷^n¿ývΜ9#ËmJ÷Ýw:ŽÓ§OŸ·íÈ‘#Œ3Fž³êç燃ƒÇ'==nݺÉeòððÀËË‹#GŽ\Û€õðaøßÿ¤ïã¥}xµK 5v0tê$ý41ú÷—:wƒ:77˜9S Ï/ýÔÕIß;øëŽïÝwƒ—×_Ç_P<ø ùëííᥗ¤c-/OzL©”½£FI?ÁÑ‘RWWjkk )0}ÿýóëv©ÏF©¼òaÅÊÈÈàÛo¿¥¸¸˜ ýûi×®AAAÄÆÆbccÃæ-[X±b„‡‡óÈ#Íyï5lØ0† Hk6ùüPWWW¦L™BNNÇŽ3Û¦Õj9qâ„ÙRD”••QPPÀÑ£G™ðéG²ö£8uêEEE(•J\]]ñ÷÷—ƒÁªª*233ñ÷÷G«ÕbkkËW_}…‹‹ ÉÉÉìÞ½›4Í|…ª««±¶¶–ƒ;;;T*eeeÔÔÔ`ee%—߯Æ›Ëã¹¹¹¬X±‚Þ½{ãt%#UUÒÝÔèhé8ÌÉ‘:zö¼ô°Ý 0™LrPÔxqÓëõ$%%‘œœLtt4~~~xzzÊwúܼ¼Ìïú©Tç« œ>}šššª««ÑëõxyyˆÝ9pCCgÏž¥¶¶–   ùü S«ÿépN™sss9uêœ:uŠÊÊJŽ?ŽV«E©TâááÁ]wÝEhh(ŽŽŽ¨ÕjÒÒÒX¸p!‡¢C‡hµZ ŽŽŽÔÕÕQ__¯¯/¾¾¾$$$Ž““F£‘òòr²²²Ø»w/YYYXYY¡P((--¥²²’{Ž;’••Enn.?ýô³fÍ’[:t(Ý»wÇÆÆæŠî˜ÖÕÕ±~ýzÒÓӹ馛šâн"F£‘ºººóÎãuuuÔÔÔP[[k¶ÍÑÑNGuuõ%ß÷àÁƒ¸ººÒ»wo‘¼æF ÕJç•Jêœ?^êj}ú°k×. P«Õr`®P(èÚµ+:u",,LÎk2™Ðjµ¬_¿žU«VQQQ!_àkjj(,,¤¬¬LêÌpu¥¾¾žôôt4 1xð`"##ÉÈÈàĉX[[£R©prr¢²²’ÚÚZRSS)(( M›6ò««+wÜqmÛ¶¥¡¡ðý÷ߣÕj)))ÁÚÚ{{{n»í6¦L™‚­­-555 ¹“ ´´”òòr²³³ùæ›o(++£C‡=z­V‹ÑÑÑÜ}÷ݨT**++±±±!22R~¶&[ºï¾ûä`6 à7謭­éÑ£ååå­"oXX]»vmß×–Ìd2QSSCMM (•Jù{úôi***éºÚx\*Š+;Æþ<§ PHÿ7™þšöÑøïÆÒpÿü|LcÆ`JLÄôç}“É„ÂdBùçëêØ•œléì}¶£P(èСasï[Æã¦²²’ÜÜ\ !!!888 P(¨¯¯çË/¿dÛ¶m 0€ž={ŽB¡»s¯CWrŒ5þÍ3gΠÑhðôô”_g4ÍÞ³QII óæÍ#55•»ï¾›úúz¶mÛ†Z­ÆÝÝ6mÚÈ#Gptt$((ˆ®]»âé鉷·7.¶×;'óòò(//ÇÑÑQ¾¶UWWSVVFee%‡B£ÑàììLPP¿ýö£FÂæÏÑ9›6mâ–[naÊ”)¤¥¥‘™™iéÝyÕÔj5qqqf¹k! €nݺ™Í¡þ7š5`Õh4h4´Z­<$²²²4 ¶¶¶Fôz=jµ£ÑHuu5¾¾¾—®„Z³³óÕ7tôziHÒ;ïHC‘E}ôÑG:tˆ^½z1jÔ(222xä‘Gä^´Æ%x^ýuœ_xÁü=o¾ùü¿ãåo¾ ¯¿.ý½FUUÒ°Åši.ϤIб£´ÍÊJÊ@zÏ=Ò¼6m¤Çï¸Ãì­ †ví°zõUó¿éì,õb_„Ñh$??Ÿ½{÷’‘‘ATT!!!„„„È é¬¬,¾øâ ²³³qtt”ùôïߟGyç?‡$:”Í›7³dÉú÷ïÏ«¯¾zÞšúúzΞ=k–}´oß¾ìØ±;;;âââ®h·ùùùá×8ÌøO …GGGùbÒœìííihh_ uuuF<==±³³C§ÓÉA¡V«E«Õt¡yç°²²ÂµqÞååüþ;Üz«t§ÿ" §ÊËË™?>:ŽqãÆáãã#g=þñǹãŽ;9r$uuuLŸ>»îº‹„„¾úê+xàºwïÎW_}uþÝÎ?eeeqðàA6oÞÌwß}Gee%nnnœ:u WWW¢¢¢xøá‡/x§¡´´”3gÎÈ¿{{{ËCï¶oßÎÊ•+Y´hmÛ¶%88…BAaa!yyy8::âîîÎèÑ£éÓ§ÏE?";;;úõëG¿~ýäÇ*++/{÷ÚÇÇ€›nº‰qãÆ‘••Evv6'NüWA§›››YfÒB©Tâì쌭­m³ã …´Z­Ùggoo““¶¶¶fÛG¸\¬ƒîOvvvòùC¸vŠŠŠ˜>}:ÅÅŸ»»Š^¯';;}}=^žO³²²(//§]»vÜzë­tïÞý¯79qBºFuî,]ÃÊË¥%˜’¦Ü|³ôØ_HShœœ¤N\{{ô®®d*•døú’•œLþÒ¥¨Õj ©#&66–¶mÛòÅ_0räH9Sos¹X[ÅÓÓµZ­­-ƒAn« jjjλý½½ý•u:^êëëY»v-‹/Æh4ÊÁY~~>AAA´oßž 6Ç[o½ÅæÍ›yï½÷©Û¹sgªªª8zô(ƒÈÈHl6‚ê\å®]»Ø¿?§OŸF¥RáççGtt´<‚Æd2‘ŸŸZ­–Û)&“‰1cÆ0}úô«Ê«T*ÿñy»¡¡ÔÔT¶oßNÿ>}àµ×Э^ͨÿüN‡««k³wÔÙØØ`2™Ðéth4L&UUUr{ûBm•††ùx±ÏÆÉÉéšLî_666899É¡ÿV³¬>>>x{{säÈbbbiX`` ÖÖÖtêÔ‰}ûöQXXˆ¿¿? ¤§§›Í#¹*&“t§R¥’z{õzip]tÑut”²„þI«Õ2{öljkkùúë¯åWŸ>}=z4gΜÁæÏD?+V¬à³Ï>ãñÇ¿üiäHX¾Ž•.øåå°v­4ä÷…¤Œ©÷Þ+?½q8]ãpi…ŸºúztUUf'ö´´4–-[Æ©S§ #""‚˜˜¼½½å’Á`À`0 Ñh°²²B§ÓqèÐ!–,YÂéÓ§å†Brr2 ,@£Ñжm[|}}Y·nƒ âÅ_ÄÎÎNâæævÁ“mß¾}éÛ·ïE?›óÖvT«ÕfI¯GÑÑÑòEX­Vsúôi*++ &&&†¬¬,êëë±³³£°°3gÎ\ýœsíI“.:ìW¯×³oß>>ÿüs:ü9„vÚ´iLž<™äädŽ;ÆóÏ?ϲeËHJJÂh4Ò³gO†ŽJ¥â¿ÿý/EEE¸»»_4XiÞbhh(·ß~;€Ù0"{{û ÎÍlt©Æ@bbâ5KÀvEC­/Rω­­-:t --¨¨(>Œ³³3DEE‘––&÷;†Z­½î—c0Hßã3tÒd‚º:LZ-åÀâÅ‹9yò$cÆŒ!$$FƒR©¤¼¤„^Øöíûꫜ­­%óða4üÁ¤¬,ü}|ÐL è ÈûñGޝ_ÏŽíÛÉ}â F €æ³Ï¨MN¦! €’ñã9^ZŠ6) ›Í›Ù˜›KèøñŒˆˆÀÃÙý!hÓÒ¨­¬$eíZN°gÏôz=;v$2,ŒÄž=åﻕ•eeelݺ• pÛm·qË-·ðÇ4ë®ðõõÅÓÓ“£GÊÃØÛ*VVVtîÜ™ƒRTT„ŸŸZ­¶iÛ*ÍÀh4ÊCŸ *•ʬãK¡P Óé(**¢¬¬LRTT$'´¶¶fòäÉôèÑCn‘’’šOœÌ€IDAT¾}ûxâ‰'èÞ½;jµšvíÚ1~üxrssÉÉÉaÿþýøùù1zôhÔj5III<ûì³DDDp÷Ýw€Á` ;;›mÛ¶±k×.lllˆŠŠb„ DDD Õj9zô(iii1`À<==±²²ÂÖÖ;;;*++1™L8::^0nRz½ô=¶¶–¦äüü3<ÿûŒåË—3vìXŽ;Æþýû™5k7ß|33fÌ`ïÞ½têÔ‰?þøƒššš«o«­^QQõõõf^õè†k°ºººâëë+÷jÙÛÛóØcñ /ðôÓOc0hß¾=·Þz«œåÑGåÛo¿eóæÍ444È=iW­¡¾ùFš“joÏÑôt2³³òè£X99I, 3gÖÖÖ<ýôÓWœÈéùçŸgîܹ<üðÃòÊÚÚZ>Lvv¶<¯¢}ûötïÞg{{ôNN”=ð&¦ÒR(-ÅÊÊJÎ÷ÕW_a4yóÍ7±²²¢ººN‡³³3¨T*yò¼«««|ç*00>}ú Õj)//§ººFƒ †êêj***°±±Áßßÿ‚óU*•<ÿO¸0ŸóÖO½é¦›1b„¼Ï O>ù$¶¶¶DEEq×]wñÉ'Ÿ`ee…Édâ™gž¹ºabF#|ù¥YO­V«å×_娱ctéÒ…€€>ûì3|}}ùøãåÎ¥RI·nÝøßÿþ‡|¨T*Ä 78Fƒ¿¿¿Ù9P­Vs÷Ýw“ÍôéÓQ(ØÙÙ1mÚ4¬­­9r$YYY̘1•J…µµ5Ï=÷Ü 3L¬¡¡²²2\]]Ï»@F6lØÀìÙ³:t(÷ß¿tήª’†ÓÖÖJË1  H–¸¸¸àìì,]Këë¥lﵵСºúzN­]Ë×99TòèÃÕòåŒtv¦èàAJŸ~C§N8¨Õ„¸ºJAiã(FJ´÷wÒà|ËâÅ‹±··çé±cqwwÇÙÙù¼ýAqq1éééøøøàææ&]o‰Gúœ;꣱­2sæL¹­Áˆ#ÌÚ*óçÏgÆ 444pß}÷µ¸ù©s=³²²8zô(™™™dggÓ¥K¢££4hNNNfA§V«•‡:;88àâ₵µ5:Žúúz¬­­¯ºáy1...Œ=šræÌlmmñôôl¾cçï£ð¶o—¾gmÛJI)mm¥eù ¤N%éG¡’nÖ×KKªôÜ[o•2Ø÷éJ%Ó]\È^º”ŒÌL&MšÔùäúÅÄ0ñ©§0äææRY^N‡°0Ô66è6ofß/¿°nýz¢£‰¼ývuîŒÃwß‘¿{7‡üý)ºùfŽ9B~~>£FbÈ!ÍwG©™”––²|ùr&NœØì»¢¢‚ÌÌLìííiß¾ýyçÎ3gÎ}E»•••¬X±‚±cÇ6KÙµZ-K—.å§Ÿ~"<<œ:о}{bccoì ãÌiÝîÚZi)@ww)HMI‘–ó³²’r…X[K#ðÒÒþÊdÝ®´>ýÿþ'½W×®RvkFZ|øð‹'Óʆ ãÑ‚Ú Ào¼!·ërrrØ·o£Ï™’Ö\ŠŠŠÈÊÊÂ××—à ,çÖØV‰ŒŒ¼l‚ƒ¢ÕjÍç» 7”-}„í‘#t›>]êä±¶†-[8=>ù·ßN÷«˜þf‘–«““Ó%êøøø4}ã«m[Œ¯½ÆáìlÞ{ï=&OžLHH¯½ö†ððp-ZDii)3fÌ ::ú_5ì  DGGSVV†­­­¼dF£!C†púôi¶mÛF¿~ý ”³êô644ÈÙIE°z}ºÔÈ€öíÛ›­G|U\\àÃÁݽ^ÏÆY³f ¯¼ò aaa 2„úúzlll®ýá†amm}Ñ4õjµZžßÚ¢íÛööèBCÉß·ê)S0iµd´mËRl=<èuì i„íŒÔuéBEa!^Û¶aò÷gONdfr"'‡€€n¹å:tèÀÒ¥K™}š$‹Ÿ­­íE‡±XYY]6YKkÉ$(4µZÒ~äȾøâ Þxã yxšR©¼±{ÔáBjjàÃ)7Ž//&çäIºg‡´gN` ÎÎÎÛ¿Ÿ9óæaçèHÐÁƒ$Ï›‡µÉÄ­UUtps£­‹ C‡ !(2?¥E^ìÛÇãFαõëñîÚ•ò1cè'ÍçÞ°ŸU«Ð?÷û·n¥W¯^<üðÃ899qäÈvîÜIà”)t<¥RI8>|¸4’BþT[[Ëš5k(**ÂËË‹ÚÚZ6lØÀàÁƒåü ­Fuµ4t>9Yê¨mu´p¡´Æ|D„‡KéõÒs‚‚ 0ð¯Ü?|þûvè 幘sçé*`g'ý\‰ÂB)[öÓO£|æ†f #ÜØª««IÙ¶v¥¥xçæJ«ŒŒ+Ë……°zµÔŽ|í5ªŒFÎ~û-'ORïåEŽ¿?kÏžåøÎ ÎÉA‘•…I«¥Ó‚8º¸6o»¦L!±S'Žt놧^K¦Š½=¥}ûR{=e ¶ˆãÇáí·1̛Ǘ_~IÏž=0`€¼ÙßߟùóçˆF½pýY³FšKÓ³'óçÏgôèÑ„7^´A ªªŠ¥K—RVVFqq1 “‰‡S]VÆÏ_}Ũѣyä‘Gpqq9/‰LXl,ÌžÍÒ¥K1 ¼þú븹¹¡V«Q«Th |ÔjéâÿúëPY AA¨ºu£ÿþúö=/+ÁÁðÉ'ø»¸0ûÏ,©Û£¢¢èܹ3@«X_WhzëŸÏž=›àà`BCC)**¢¦¦†çž{ŽÀÀÀf_îêªTVJCíϤ×Czº´nï°aо½4<÷?¤¥“Î]àÑG¥×j4Ý! ÿ+xµ$//i¨ÌLèÒ‘Dø·jkkÉÉÌ$##ƒii”ÈÛn£mÛ¶”••‘••Eqq16668::²k×.öìÙC?ool²²X¦ÕRE}n.!!!ØyzBß¾T—•±{æLNæäÐ5 €¶: ‡Qwêþ}ûrÛ;ïàïêŠÚdBàâ‚ nÛ–¦N¥*1‘ß“’˜ôøã×,_EëX€ví8zô(ÇçñÇ?oX¤T…ëRCƒÔ³üä“äææ’™™ÉTqFdEEE¼÷Þ{èõzn¾ùfi.–“={RæäÄÇøùù]´q߸îìÝ—XÇZ6s¦ùkáÂC1ÿ]£4¦ÝB³Óét|òÉ'ìß¿Ÿû}û^ß ÍŽ‡éÓ¥`32Rºž99ÁwßIkŠßv4æyèÞ]úù»K,“fq*$$H«RÄÆ^tÈ¥ \Hee%999œœÈÈH¼½½¯è¤@JðúijÏòøãILLÌ5»~µþ€µ ÝàÁ|õÕWŒ5겓Æằk—4ï * ­VË|Àƒ>(† `ª©!7-'Þ~››ûöåñÄDiÞ™ƒƒ4ÐÖ±2¬p=Ù¼y3óçÏ'""‚Ï>û¬e÷­¬”–tÙ¿_ZWÞÏV®”–ôö––6L®»`t‡4?ÿ¯¡¶Ã‡K¯»F‰›ÕèÑÒÔ4¬ `0ÈÍÍ%++‹”={pNOçÌÞ½dŸ8AÝ­·¢T«™äæÆà€¬–/'1,ì¯aê¢OJ¢fÿ~îú3S?ÇŽI#¼¼¤yÙ&â³±±¡k×®tíÚµIËÇsÏ=Gxxø5Ë 7BÀúŸÿšžÎÙ³gå…ì¡UˆŒ”Þ ¹ùæ›-]*A°,ÓæÍTþßÿ±¡ €)/¿LïÄD)KüÙ³RƒØÏOJÀ"דÉÄöíÛùì³Ïxà¸ùæ›/ºŽm³3¤å\t:Ðj¥| jµ”I÷Ä øÏÀÍMzîÍ7K™y«ªþʶ}n·mÛ¿þïÝŠº“¼¼¤á†f2™ÐëõÀ_£hŠ‹‹ùüóÏ9vì¡¡¡t‰ˆ Ÿ›.;¢°¶†)S¤Ñz½Ôáñ÷ï½£#ê!Cp2ä¯Çšy8¼R©däÈ‘×üœÔêVƒ­-_/XÀ£>*î® ­Ë9YA׬YÃ!CÌÖ„‘>?Ÿ­3g²ÎÙ™Q}D||¼Ô8xöYKMþ•œœ>øàÞzë­¦Y—¾):ï¾+¡‰‰R€ªVÃäÉr2@™ ü=!‹ ´Byyyœ>}£ÑˆÉd¢ªªŠÌÌLŠŠŠÌ×£G2lØ0žî×çà`)IØ…´ð,ßÍ‘õºeW£¨æÌ¡à¡‡(--µÈ:œ‚pÍÔÔÀÁƒ^©dïÞ½¼óÎ;bî›pãjhÀ¨P°æÐ!~ ä¥×^#,,L|'„ëZCCóæÍcðàÁtøsDÅTVJI"#¥SWWðõ…ÿþWvèâò× ¿«‚Ð ™L&ª««©¬¬äìÙ³¤§§³ÿ~N:ExH®®˜L&Ôj5^nn܉J§£ÎÁ••>©©®[›7KIû„‹j½kf&TWs2'‡   ³æ• 4‰³g¥¤QQ¤feáìì|Ù…ë¡ÕÒj᫯HqsãÇåËyùõ×E¦láºg4Yºt)•••Œ7îÚv¾4®jgwþ°ÃF&dgÃòåRÐúøãÒ]Ós‡ò  ¢¾¾žÍ›7³xñbT*666tèС¡t÷ôÄ:/O?p 4áÿû+÷ÈãK>¡¡Ð§Ôäìlé*µh­7`ÍÊ‚„RÓÒÄ¢ÇB듟/Íñ±·'--MŒ n\&üñ§¶oçêjöYqÎZ…cÇŽñÛo¿1kÖ¬kŸ`©²Þxºv•2óÚÚJß­ª*)@ýöÎ;>ªb{àßÝÍnzï¤Ó›PEDEE@{y<Ôg÷§Ï.úìýÙ…§ ""ððQ„ÐBo $!Ò{Ù~Ìlóý|òÙì-sçÜ;wöœ™3ç\{­P¨~X¶&“X['‘\À˜Íf Ù³g{÷îe×®]Œ9’I“&áïïOAAkÖ¬¡ªªŠ¡C‡H]];vì`ýúõxTVr÷°atÓéð¹òJ´11pð ìÛ'‹Ù#x{z ã52RªÞÞb{p°ôFh"í×`7´Zö=÷·Ür‹«k#‘œ_üü`ôhÌV+Û¶mãÖ[ouu$—p,7—²ä³ìl®œ1ƒ”””SR—I$"³gÏfìØ±tèСå/æç'f}ž^£Ó¦ Oµ·ß__˜0¡áX»²-‘\À=z”Ÿ~ú‰íÛ·Ó¥KRRR¸êª«øá‡xøá‡éÞ½;;vì %%…àà`¾øâ jkkñôô¤S§NÜsÏ=\²r%î99зoC ¿=Äßɸ¹ÁÀ®ù‚¦ý¬aaFòó󥫤¤ýÑ£tïNEy9ÕÕÕÄÇÇ»ºFI«óðÃsøðaFÄM3g20%åôyO%’ «ÕÊÏ?ÿŒÑhdòäÉ-3sì,]*¢×jµpÕU"àËÛo‹ß*œ8!RË$'·í\§I°Z­±ÿ~~ÿýw222¸òÊ+yë­· süvtéÒ…M›6‘‘‘Á;ï¼C‡Ðh4LMNÆPY‰vï^ÇÃgŸ±>9™ñãÇËwI«¢×ëÙ´i¿üò ÅÅÅôïߟñãÇÓ½{w, `îܹЯ_?n¸ábcc›~’xë-xí5òòò É¢%’V¢ªªŠß~ûÕ«Wc42d×^{-áááFRSS™?>‹…Áƒsà 78úøóÁ`૯¾â~77‚.„{îqõ-‘´3 ùé§ŸHKKC§Ó9t???²³³ù駟سg ÜtÓMtïÞý¼Ì†~óÍ7 :”Þ½{Ÿ_¡jjÄ ê­·Š@I“&5ªrvè¢ãÀ,^¼˜Ý»wÊ”)Sèß¿?X,öïßÏܹs),,$))‰n¸á‚óXÌÏÏçÞ{ïeРA\{íµôïßoooT*•³¡j4ŠOöì’n¼NŽòùçâS­–ï‹ hÕ…>z½ž?þ˜õë×3aÂÈ'Ÿ|¯¿þŠÅbÁb±0kÖ,öìÙÃÔ©SQ…—_~™'N4ïBÙÙ胃IKKcÀ€­)¢DBZZ/ÙRjLŸ>½{÷òòË/SUUEAAÏ<ó nnnLž<™;wòúë¯cµZ›~£G¡²€íÛ·Ó£G¶“D^Òî±X,,\¸o¿ý–áÇsÅW°téR>ÿüsôz=Û¶mãµ×^£{÷îŒ=šE‹ñý÷ß7¯Ÿ…C‡QœžÎ°º:TrHrž©¯¯ç£>â?þ`„ 0€ÿûß,^¼Ø¡«¼ôÒKìß¿Ÿ©S§b2™xùå—)((8çk×ÔÔ°mÛ6®¹æšó߯/YùùѰM¥’Ê÷EHUU/¾ø"999Ü~ûíÄÄÄðôÓO³sçNŽ?Î3Ï<ƒ»»;“'O&--7ß|ó¼öã-Mii)/¾ø"÷ÝwÏ>û,#GŽÄ××µZÝ`¬ ãtÚ4ÁÄ’«wÞ3©'{h4âO¾/.¡U§>ÌÆy饗€ÀÀ@þýï“››Ë¼yóHLL䡇ÀÛÛ›/¿ü’+®¸‚Ž;ž—:Ì›7ñ11hÆŒXrž9|ø0[¶lᥗ^"%%€êêjV¯^Íu×]ÇöíÛ)((àwÞ¡G >œiÓ¦±råJn»í¶sºöÖ­[‰ŒŒ$¡%RÅìÝ O?ÝFrѲaÃôz==ö;wfÔ¨QtêDxx¸L/iu|||¨©©A¯×cµZ©««ÀÝÝЧO¼mQ£¢¢ˆm^ï×&O¦°°ÚÚZ×'“—\T¨Õj¼¼¼¨ªªÂd2a2™ÐëõhµZ4 éééŽI€>}ú`49zôèy¹~aa!999\úÌ3¨Æwõí´C´Z-:ŽŠŠ ']ÅÃÕJEFF‘‘‘÷HOOOúõë×|]åO˜ÍfÖ¯_ϨQ£Î ¥¥0¾HYðÔS2gª///, UUU(ŠB}}=‹OÛ`ÆHLLt¬¡ŽŽŽ&::š}ûö¹ºêg¥´´”O?ý”¢¢"f̘!<E¼«VÁ#@n®8xâD˜9³ÁX•´YZu†5>>žiÓ¦ñé§ŸràÀ***صkO=õÞÞÞäççãáááÈ7¦Õj‰gÁ‚–[YYÉÆ¹êª«†@~~>;v”ëEŠÙlväÔ:Yyn ¦NÊK/½ÄË/¿LTT¿ÿþ;$11‘Y³fѽ{w´¶üuAAAsøðáFË,**bíÚµ 0ÛªôuëèÚµ« ¸t‘¢×ëÙ¼y3‡fÈ!­v]oooî¼óN>øàjjjpsscíÚµÜsÏ=DEE‘——çè...£ÑHaaa£åfdd°yóf’““u…\üÃLêߟ°¨¨V“Yâ:~ÿý÷æ/ :GìkR?þøcöíÛGEE»wïvAÊËËÃÓÓ@ ÆÇÅűxñâ3–©( dÿþýôêÕë´ÇÔ×ד““ÃwÜqîBмª"Š)ˆô4’6Euu5¿ÿþ{«ëªƒ "))‰7ß|“aÆ‘™™‰Á``âÄ‰äææÒ§OG ˜àà`ÕUL&[·n%::š¨VìŸ GeöìÙÄÆÆòâÌ™ž8!òž* |ÿ½ˆqsã"*4¼’#//Í›7Ó¹sçs*§UŸ”Éd¢¼¼³ÙLEEååå€xaó‹7™L–ëååE×®]Eà™òrøôSJ4Bâã¥Áz‘¢V«‰‹‹#..®Õ×wVUU¡×ë©­­¥´´£Ñˆ^¯Ç`0œñ³ÙÜh™~~~ôèÑw77HKƒnÝØ·oßIûG«ÕÒµkWrrrZµŸ³Z­TTT`6›©®®FQE¡ººúŒ}µÕjÅb±4Zndd$;wnT–ò²2|V¯ær™ÏgÏž·ê5íºŠÅb¡²²Ò¡«TUUýe]E¥RÑ¡C‡FùƒâëëKÄÉkL›JMpo¼ôRáò»z5tí wÝ%#™¶a<<<èÙ³'ÙÙÙ­z]½^OUUF£‘²²2*++ýxc4¦«h4:uêD```«È`4ùïÿëHe4ñ÷÷ç®›ofи¿ð‚HÉÔ½»X{z×]àî.þ—´AAAtîÜùœuñ3¬õõõèõzGóX,üþûï”——“@Ÿ>}Ð5ÓÇ{çÎÌŸ?ŸO>ù„ž={b±XX¼x1o¾ùf£>ñg ë®Õj #AÕÕŸOu` Î÷}—\ ¨Õj‚‚‚ lUeÞd2ñᇒ””ÄSO=…Z­&//‡~¸ÑÑ÷³µq1kUSß|ƒõ‰'(((hÕ™5IÛB£ÑŠO«¶ñ’’>úè#î¿ÿ~&NœˆÕjåàÁƒÌ˜1ƒ.gXOêæævÖHÖ~~~„„„4zLev61ûöáûÆ­&¯Äµ„‡‡;Ü[‹íÛ·³`Á>ùäzôèÅbaÑ¢E¼ñÆ$''Ÿñ¼³õãþþþ4¢—,^¼˜«¯¾ú¯E}_´–-QM½½aòdÍ´%r¸JÎZ­–ððpòóó[íšV«•_~ù…'Nðá‡Ò¡C ¯½öï¾û.³gÏ>ã¹½‹jµšààà–KÅt555|ùå—¤§§óÔSO9ÞWUÁ ¢aŸ4IܸoooBBB¨´ ý«œÒ“FæÏŸÏ¤I“øöÛo1ªøÂ /ðì³ÏòùçŸóÈ#ðÊ+¯Pe_ÑDÒÓÓñõõ¥G€P¸ú÷ï^¯§¬¬Œ¸¸8êëëåF>ܼàF#„…Qk29\‹%’Ö¢¤¤„‚‚RRR‘èbbbèÚµ+™™™ÄÅÅQ\\ŒÑB½´´”ââb⚺~B¯‡ÊJ ;\Ò$’ÖâèÑ£˜L&’láþÕj5={öÄÇLJüü|âãã9~ü¸ãøììlÜÜÜÎjŒ6…¿ÿNà5×ÈõF’%==G|FCRRõõõ”••Omm­CW1 9räœ%9r„Ç3zôèæŸ\_©©ðì³`wÇws“ƪä´ 8@÷îÝIu:)))?~œºº::uêDqq±Ãk ¤¤„ÒÒÒ¦ë*-ˆÅbá­·Þ"//7Þxƒž={ŠÀI{÷ /K??˜0ÁÙX•\ðœÒ›mܸ‘>úˆÄÄD.½ôRöíÛÇÊ•+™LTTƒf÷îÝÔÖÖb­õÑ£G›ÞÆ-=³‡ÞÞÞ2ÿª¤Õ‰ˆˆÀh4:ÍdffRUUE‡0`©©©Ž}»víÂÓÓ󌳯MÅh4²|Ït3g¢’ë¶%-HLL ååå§è*jµš€€’’’8qâ„#˜^¯gÇŽÍÓUþDNN={ötÄ7hZ-üóŸ"‡\%9 :ŽÈÈHòòò.ÀV«•íÛ·ãïï——ÉÉÉìܹӱ64//üü| äêꓚšJ~~>ÿüç?ñóóFÀk¯5“´;œ\‚kjjX°`C† áå—_v„^¾|9þþþ̘1úôéáC‡X¿~=cÆŒirЗ2lØ0î¾ûn†Ž^¯gýúõL›6ÀÀ@BCCéׯ/¿ü2&L`Ó¦MDFF: ç&áí :a²XÎˈ¾DÒÜÝݹçž{xÿý÷FêÆÑh4Œ?FÃÿþ÷?^xáú÷ïÏÒ¥K2dݺukÚÂÂàÖ[1–—;ÞH$­IDD7ß|3/½ôÆ ÃÃõk×2räH àùçŸçå—_&((ˆÿþ÷¿ÜtÓMçœblߺutðò:çÀ ÉÙ4h)))ÜsÏ= 6 ½^Ϻuë˜>}:þþþ9‚è]}õÕlÚ´‰¨¨(FŒñ—¯™‘‘áˆ:Ü, !$d2IÑh4Lž<™G}”¿ýío <˜cÇŽ±eËžzê)ÆŒÊ+xá…èׯ‹/fذatíÚÕ¥uÏËËãƒ>à•W^!((Hl4àÕWáo[–IûÃIÛµGrœ>}ºcq¬¢(ìÞ½›8 SµZŸŸ¹¹¹g s2<ú裬X±‚Ý»w£Óéxê©§8p c6ôÑGeÉ’%lÛ¶ž={2~üxš.Ñ¡CСÇ—3¬—pÅWƪU«8|ø0W^y%#GŽ$""EQxá…X°`Û·oç†n`Ô¨QM_ƒhKònµZñòòúk£ñÉ9 Óé¸ýöÛéܹ3©©©TWWsçwrÙe—áïïOïÞ½yî¹çøå—_8zô(÷ß?#GŽ<§u¶ƒÐ%K¸½_?HOÒâñØc±bÅ öìÙƒN§ã™gž!99ÙÑç>þøã,Y²„´´4z÷îÍÕW_}Nƒäyyy\uÕUÍ;éÄ xågW`‰¤ ÄÄÄ0kÖ,Ö­[Çþýû åý÷ßw¸Á‡††:é*S¦Lá²Ë.siÿkµZùÏþÀ„û½Õ*t"77áaе«ô0hÇ8¬V«Õ‘OÏNNN‡æÞ{ï=/ å–[ná–[n9íþs éþÎ;ÔL›†——×9èK$wwwRRRNë¦R©ˆç±Ç;§k˜L&êêêZ=²D"@ÒUW]uZ[­VÓ¯_?úõëwÞ®g.,¤`Õ*z=ü°«E—\$„……1mÚ´3î åÎ;ï+eeeçœóO"iË;vLzH. ”Ý»)ݳ‡žm a½Dr¾1›Íìܹ“)S¦œýàª*øøc¸õVá,‘´Cjjjxæ™g0›Í 0€{õ"¨GáìååêêI\Ä)ëáÇù¿ÿû?ŠŠŠèܹ3[¶laóæÍ¼ùæ›\rÉ%®®o“8~ü8}úôqu5$’£¾¾žÐÐPWWC"iY,ؽ›}Z-7˸’vHII õõõM‹»a±Àõ×CsrÓK$Ë—/Çl6óÁ V©àÆÁÓÔês/\rÁâôôÍf3 .ÄÍÍùóçóÍ7ßð믿b2™X´h‘«ëÚ$Ìf3•••Ž\RI{¤¤¤___WWC"iYÔj¶÷îzäHW×D"iJJJojZšÀ@;ÖÕU–HZŒ‚‚-ZÄÌ™3Q7DÖÆêEÏ)kYY)))têÔ www¢££2dGŽqu]›D}}=ÕÕÕ¸¹¹{aIÅb±4]É‘H.TT*r-":vtuM$’¡¼¼üìñ ˜3¬VP©\]e‰¤E0|ñÅ >œ®]º zí58|ØÕÕ’´N;dñç™›àà`êëë]]×&a0 ’«¤]“žžŽ««!‘´(Jf&¹6'ׯJÚ)GŽ9{ÌeË 5ÕÕU•HZ”­[·ràÀn¹é&4ß~ >>ÐÔ`d’vO»›c×ëõ˜ÍfÔÒ}@ÒN±X,hµZ"""\]‰¤E±|ÿ=–ýûe^mI»%''‡:œùƒ~ù¦O—³«’v‹ÅbaÑ¢EL™2/77`læL“O§m ………¤¥¥9¾S[[ë´ ::ºÍ)Í&“ 777i°JÚ-ÇÇ`08ÒMI$í‹ÓöíœÇÏÏÏÕµ‘HZ„ŠŠŠÆ VwwxöY™$í˜M›6QVVÆW\ÊÓ~ØÕU’´1N1Xu:kÖ¬aÓ¦MŽmõõõ þïÿþÏéØûî»o¼ÑÕ28a0ðôô”.Á’v‹Éd"66ÖÕÕHZƒã%—PYP VI»%;;›àààÓשׂ«4V%혺º:æÏŸÏM7Ý„'@y¹LÛ$9'«N«Õ2qâD Ф“{õêõ—.ZSSÃ(//'))É)=‡ÅbáÈ‘#9r„ððpz÷îÝ,ã³¾¾£Ñ(gX%.çСCdeeG·nÝíØl6³k×.ÊÊÊèÔ©ñññh4š&—[PP€V«uµx’‹£ÑHzz:ùùùôèуøøxT6—źº:ÒÒÒ°Z­tëÖˆˆǾ&ãåʼnéÓQÞxC¬—PSSÃþýû©¨¨ ÿþ„„„8öY,>Lvv6ôêÕë/ ”»»»ŸÞ`­¯‡wÞ{î`OÒB”––²{÷nT*)))xzz:öÙs———Ó¹sgââ⚥«4•ýû÷SWWÇ AƒàçŸÁl†Ûowõ­‘´1œzWFCRRIII€˜É)//w\òòò"((èœì±cÇxþùç©­­E¥RñÅ_ðÄOœœŒJ¥bîܹ,Z´???jjj:t(÷Ýw_“ÌÔÖÖ,gX%.£¾¾žï¿ÿžeË–áííMEEÇçá‡F¯×óþûï“––†¯¯/555Lš4‰›o¾¹Éå›L¦³G•”HZòòrÞ}÷]<ˆ»»;eee̘1ƒ«®ºŠ‚‚^ýuŽ?Ž»»;F£‘Ç{L(#ÍÁdâО=ôë×Nçj‘%yyy¼ð ÔÕÕ¡R©øòË/yòÉ'éß¿?*•Šo¾ù†%K–8t•áÇsï½÷âííÝäk9rFsjû6›á?ÿÿ˾^ÒBlذO>ùµZÑhäûï¿çÙgŸ%66–êêjÞÿ}¶oßîÐU&OžÌÔ©SÏkÌf3Ë–-cÒ¤IøÖÖÂâÅðî»®¾5’6Èi­:«ÕJzz: .dß¾}”——£R©¦OŸ>Lš4‰N:5ûbF£‘Ù³gãááÁ¬Y³ðòòâ­·Þâ›o¾¡W¯^”––2gÎn»í6nºé&víÚÅÃ?Lrr2#FŒhÒ5rrrðññ‘3¬—±wï^¾ûî;Þxã Y½z5ï½÷cÆŒ¡¬¬ŒåË—óÆo””Äwß}ÇgŸ}Æå—_NXXX“Ê///— ¼ÄeX­V–-[ÆÁƒù׿þETT?þø#ß|ó }úôá×_%77—?üÞzë->ÿüszôèѼ™Ò¨ýå:Lšäj‘%v]ÅÛÛ›W^yOOOÞ|óM¾ùæzöìIqq1sçÎå®»îbÊ”)lß¾Ç{Œ2tèÐf]'**êÔÕÕ‘ÿøHoI PWWÇÇLÿþý™1c<üðÃ,Z´ˆ|Í›7³bÅ Þzë-úöíËܹsùì³Ï=z´“Wä¹’••E~~>O>ù$ªãÇaøp8åKÚ§XuV«•ùóç3cÆ ÒÒÒèÔ©·ÝvÓ§O'66–µk×r×]w±jÕ*¬Vk³.–ÍÆ¹ûˆˆÀÏÏ3fpå•W¢ÑhضmaaaŒ7NGŸ>}HNNfݺuM¾†Ùl&::ÚÕ÷Uró믿2xð`úöí‹V«eÔ¨Q<öØcøøø°aà Dbb":Ž+®¸‚°°0§5ãg£ººZæ`•¸Œšš–.]Êõ×_OçÎñôôdòäÉÜzë­hµZ6lØÀ„ ˆÅßߟɓ'SXXÈ¡C‡šw¡Œ ŽnÜHïÞ½]-²ä"ãðáÃlÞ¼™»îº‹ˆˆüýýùûßÿÎW\Z­fëÖ­DFFrÅW ÓéèÛ·/ h–®pôèQ¼¼¼NÝáï³fÁéŒY‰ä<ššŠÑhäÆoÄËË‹ÈÈHžyæúôéˆÙ×ÁƒÓ§Ot:ãÆ#88˜Í›7Ÿ·:X­VV­ZÅàÁƒEÉøxøÛßä ä´œ2ÃzàÀ¾þúkȃ>HTT”c¶Òb±pèÐ!Þÿ}Þ{ï=âââΞ?ì$ )**"**ŠU«VQTTÄàÁƒ¹æšk1ÒâçççXÏ¡ÓéèÒ¥ 7nlò5òóó/œDâ vïÞÍ”)SØ»w/ûöí£sçÎ 6 ÒÓÓIIIÁÝÝ9ŽCCCIOOçÚk¯mRùÒ`•¸ ½^OFF]ºt!55•ÇÓ§O®¹æÌf3‡âïÿ»ãøŽ;b49qâDó.TZJFuµ€”´:ÉÊ•+)..fÈ!]%33ÇÒ www:uêĶmÛšuúúz§u±ÔjQà%-Hzz:^^^h4~þùgT*—]v—\r‰cÿˆ#Þ\!!!„„„‘‘áx΃ÁÀ¾}ûøÇý÷CQ‘p—ƪä 8Ͱ æÍ›G‡xî¹çˆ‰‰qr­Õh4ôèуW_}777V®\Ù¬YVƒÁ@mm-÷ß??þø#ëׯç¶ÛncÞ¼y˜ÍfêëëQ«ÕŽõ§jµoooJKK-·¤¤„E‹QYY‰Ùl–ëû$˜L&Ö¬YÃï¿ÿŽÉdjÕkWUUñÝwßñÚk¯±cÇ^|ñEî¿ÿ~ÊËË©««C«Õ:Þ+wwwÇÀÆÈÍÍåǤ´´”’’%XBmm-‹-b×®]X,–V»®Õj¥¶¶–W^y…O?ý”­[·òÀðöÛoS[[K}}½c@ÀÛÛ“ÉDuuu£ånÛ¶¥K—b6›¨=𲤤f­ ”´?æÏŸÏ‘#GZõšƒššxà~úé'Ö¯_Ï­·ÞÊüùóºŠF£i–®¢( ›7o&55Õ±­¢¢Ây†U¯3L{ö´îM–¸ŒòòræÏŸVà|S[[ËÁƒyàX¿~=‹/fÒ¤IŽöy:]E§Ó5ZO£ÑÈo¿ýFVVV“ê‘‘Á` ®¬ ž~jjZõHZ‡ôôt–.]ŠÁ`8§rœfXëëëÉÍÍeèСøúúžñ¤   úöíËîÝ»Ñëõ§wi9*•бcÇ2eÊÔj5ÿùϘ3gcÇŽmôœÆ aðàÁøûûSQQÑäM’ö‹ÝW£Ñ¸$¢®ŸŸo½õQQQìÚµ‹çŸžÕ«WŸñø³µñ¸¸8&OžŒÉdÂl6Ÿ9«0UÀ.àRÀÓ8ÿVÀbÛgwRlnÀ™b«Ùíu#ÇœŒÝ–2ÛʶÚþt€ö¤ï†“ÊTŸôwò­QN:Vc«§Å¶ÝbûÓØÊ5ôi±•c=I>`ˆh²}7Ú®i߯9éúÖ?]»Î¶]cû³Ëd¿?gát(¶kc+ÿà DÙêîñ§rÌà­ñæún×´+-­ßÆ{ôèápuÿã?˜5kÇ?í±*•ê¬m<99™ñãÇ;¾×ùúsþ+no+'?Û¶†½-œüŽÙÛþÙêmoãfD{<2*4´{+÷'×Üòz  ~M(Ã7M¸‰%+—œßûÛT*ãÆcòäɨT*æÌ™Ãœ9s¸âŠ+=§±}))) 2ı­ªªŠøøø†ƒöîFk\\«Ë+q L:•íÛ··úµu:wß}7cÇŽ¥ªªŠ—^z‰9sæ8µÑ?ÓX×ét\yå•tîÜù¬×V…åË—3öÒKñZ°®ºJ¸ÂKÚÝ»wgüøñTVVžS9N«Éd¢¬¬Œ¸&t–ÞÞÞÔ××7k†ÕÍÍ wwwÇZ'€+®¸‚/¿üÒ1Òh±X0™LhµZ, ÕÕÕ'Õþr†UâR<<<˜0aÑÑѨT*’’’èÖ­ÄÓӣшÕjE­V£×ëÑëõÎJK#X,ªªªœf°¡œîÀ øp'p²—|6p¡ ï€m€Â@*ümçè€PÛ¾l ø ¨ØŽsCW¥C9Èâl×)²]£¡<»Û`4°î,lçÛ£`´mßF X†0âzÛ®«E(ùÛlÇŽãÕã²»íBYÞ z?#µE»ŸMV?›üÙ@Ðø¡t‡P¼;Ûd*¶]wµíØÝ@2pÌVž›­Î¶órJ „‡m2Cl2'!Œ†6¹×ÙîýP´ Ê9·Û¦¢R©ÐétÜ|óÍŽ¾vôèÑüë_ÿ"//oooôz½ãøêêjt:ͺŽuëV‚š:ØdÞˆ6è t´Ý+€r`+pÑ> Úƒ/¢mFÐÐæ,ˆ6[h{^F  ƒg¢Úvî™Ä,A<Ã`N@*´]'ñþrmq<°ñެº ÚlP‹hÙ¶c#€6™6#ÚôÛu+}„Ѧ†d ÓV^âÝÕÛÊΰ•;ÑÞ‡Ûî£ñ.Ùîw8°×öÿPD»~·ÝË+€N¶{¼XŽè_nµÝ×Ó¥!Ýü´9Z´[w@ÆÍÍ OOO¦M›æ¤«|ýõ×TVVâííMqqñ9é*ÅÅÅôëׯaÃ0c†TÜ%-ŽN§£S§NŒ;777‚‚‚;v,ï¾û.ƒŸStƒÁЬe€QPPÀ¶mÛ˜ùæ› ÑÀõ×»ú–HÚ8N«N§#88˜¬¬,E9ãHŠ¢(ج7AAASZZJDD x˜Íf´Z-}úôaëÖ­ƒÑhdïÞ½tïÞ½Iå[,jkk¥Á*q)]»v¥¬¬ÌñF*++ gÀ€dffR__··7?~¼ÉëW­V+nnn 3¬ B!\„0캷ñEs ððÂè\‚0ʺ“ª—íx„fA(Í»†e0Ìö}0ÑvLí¸ZÛg¡íü(Û>í{o„òª³ýy× h5p™íú½mò¨¦ ¡äïG(ò=leöB{z[U¶OOàÛòF,!@"b–9à¤:T#ó?l²LµÝ»¶rÝÊ·}–È®PwB ¡£ÕÃv¬½¾:„‘Yg«C 3¯ýF«]÷¶Ð0³0 lrxØd5 Þ*à¿ÀAàrÛµ#Áêc¥bYЦõ VNG\\%%%ŽmõõõÔÕÕáééIß¾}Ù³g—]vD«Õ6[™×þ9ÚÆ"g[=£H¡apeâÐØî“ÝàÏA´Í„qfF è|`;î D[þaÐF <¶ Ú¾Ðaä³]/bÐÇ\bû´íx5bÐ& ñîémÏ/ØvÌ*àjÄ`‰1x‚xgÆÚêRƒ0(Ýlu÷F§¹#ó¨íº«mç] t³Õ3ñ¾ áý‰A "Yíj ¢¿˜k«c/„qï‡h“>ˆv Ü…hÏ]µÝsÁþi7„ÃÆhbP ÄVÎÉÏí2ÛsÚ ü<€‰AîÙÀ< '˜®1aÚÒºË:‚ƒƒ tÒUª««ºJbb"iiiÁ``ÿþýMÖUì”——;ë+7ÞŒl*D{1!žy  íN…xOìžyZÛŸÊvžÑÎÏ68#¹à‰gûöíÔÖÖâïï¢(TTT V«).:äð¢ù„AƒÄÀùè£X²d 7Ýtiii¤§§3sæÌ&•_VV†···t –¸”+®¸‚>ø€ÄÄDX³f ¹¹¹Üwß}¨Õj~ûí76mÚD¿~ýXºt)uuuMNÛdµZ©®®n(ªæ#”Äq~£ÕãR|ŠP˜¯ÞG(¤'ÿ§ïqˆYÆÛOÚ6ú/ÜŒ¾gØÞœ „‘Í86ð¤ÿíFæél_„áÙó/Èt:N^q²²g÷¬ö§ãSlŸÎR®;ÂØD"¦uõx@üN\vÙe|ùå—øûûãëëËÂ… éС½{÷¦²²’Ÿ~ú‰1cÆàëëË?þHBBB³•ùúð;S½„Ñô€…0ì¦Ø>k3ˆ= §ËÕ13žŠxÌÀUÀC4 ,ŒC| ƒ' <¢ý¤ Ú˜½Õ K|mÐ ç÷Í>;Èv΄¡×±'}ž®«8 D!œF;—Û>6áØå‹@¶&ù¤ÿ‹“¥¶Ý»xÛ÷‘ˆ±÷muî†0üŸ|A)SPÔ­7 "PX÷îÝyçw¸óÎ;±Z­|úé§ <˜€€ ć~ÈÒ¥K™2e [·nåСC<øàƒM¾†^¯§ªªÊaДåUVÄÀG ¢Ý”"úøÅˆ²n¶ívo™4Ä eGÄ@NoÛ¶RÄàƒ7¢­W!¼;¼)µˆg½ÔvÝîˆ6`@ b¨3ë~Ô³áõR‹xÎÊ\B- fâ7옭îa6™ÝþrɧbÍq 5­d+%%…Ù³góÕW_1iÒ$ ™7oãÆÃÍÍ‘#GòÔSO±yófY¼x1ƒáŒË>šË¶õëo0€É$-Iš„Ók§Ñh¸öÚkY·nÏ=÷=ôñññŽ(az½ž¬¬,Þ~ûm¢££;vl³òúùùñä“Oò /ðÌ3Ï ( qqq<øàƒCó‘G᫯¾bݺu¨T*þö·¿5YÑ äõ×_wõ=•\ä\~ùåœ8q‚>ú«ÕŠ»»;3gΤoß¾X­Vn¿ýv>ÿüs<==ù¿ÿû¿&¯·Z­èt:qüqàU`Ba?ÓèÕˆ»X„2Ót§‰ä´Z-wÞy'ï¼ó¯¼ò Š¢àííͳÏ>KLL &L ??Ÿçž{µZM`` =öX³7©¬¤¸cGêNöò±"”ì:àc„Áó.bVútÎ@ÞœÞÈÿ3¡Àµ…ÝÝö÷gâ€G›Xw„1z&ìá!þô½%ÐÐögË‚ƒa}³ÎÝÏÃ…±¶üýýyòÉ'yñźJ||<>ø ^^^x{{óÈ#0{öl~ÿýw‡®Ò­[SœÀ`0 (Jƒõ 0}:œœãÞˆ˜¡ÑîKFTÂs$Ķ0ÝöÝïO÷n‚­bÐR‡pí¶¯ñ·¯ïW#lª†æ^Ä»1ÈöŒ,¶rjnÝ;³ñ×Úêt/bШá½ò%bp%aäîFÌôÆÙÎ=€0¢ÇÛêˆxwN~—ÍÏb[ýìž á4ÌÛg”»ÚþרÊó³í¯BüV"J!fòÿc;~(b`±ᩱ±œæ:Ûw ¾ñ¾º#~WUöá­1Æ&g'[¹Þˆ~k£ÀÑγ]û- JP¡ŠjÝõ‘‘‘<þøã|ùå—lܸ•Jň#¸õÖ[HLLäÖ[oåÓO?ÀËË‹'Ÿ|²Y1k΄Édºr%ýûõîÀI8EÅMHHàé§Ÿæµ×^ãïÿ;ݺus`ª¨¨p¤3xôÑGG›HTT~ø!‡ sçÎNŠÌ¨Q£èÝ»7G%22òôIµÏ$Œ››L÷!q9žžžÜ{ï½\yå•町`Ú´i :”ÒÒRºté‚3Ö+Y,ÊËËÑZ´BYïKãÆ*¥dœ«ïФ=ÈóÏ?Ovv6uuutìØÑñ;áëëË£>Jff&&“‰Î;7_Éñ÷ÇúôÓÄÚ£MÖŸ#ÝDà&„1z>1¿s/BòQ#Œ[\]‘bbbøè£ÈÊÊB¥RÑ¥KÇà=ˆÉ>}úpôèQ:tèÐl—wƒÁ€¯¯¯ð–©®‘ƒÿ´˜wb¹Ç„¡§E,_ˆ‡fÅY³/…°² ’DÚ>Ñ4LCpð¢íûdà)ÄL¬:„'ƒ ájÂÜ‹0Ü"†e¤í¼"Ûy¹ƒ5aàæ ÂUˆß½a£Ð„X·}ahÇ#f¢»"ŒúHÄïe$Â`}ÕvÎ ÄZí*„7Æ@„ñ}²z{ÉIÿ—َ߀piGÝSž>ˆøÿµÕõ„§ÅxD‚hë¡¶¿€ÙÛLý®úf<ÐóÃðáÃéׯøùù9­OÕétÜzë­ 6Œ²²²fë*qàÀ&TTàý·¿‰NI8­šÛ¿¾üòKÖ®]Ë–-[(,,D¥RËÔ©S¹ì²ËÎi”ÅÃÃ^½zqXXa­]’H.bbbˆ9C”Ó„„þº ƒÁ@`` ¾&_ñC<‰óëž$‘477·3àpss£GçT~QQuuuBÝŒPXß@ÌĸÓv#üJÚ ôîÝûŒûÏEW±ÜS©T":ð°a Á–ʳ–ÕÀ‡ã©­öóZ„ñi@Ìú ²?Ô^4¸ ŸL2bØŠ0\MˆÝHÛg(Αã-¶c¯¶m÷Fã Â6ÑÕújâ)Ø#¿ÿ™X[šj7!Ö›@ œÙã Ø‰C¸?›³¶œ­Û×ÔÞ}æ¶üc:ö¥€g¢cÇŽtìØñ¼^sùòå {â T}ûºNpÉÇi»@»×ĉ™8qâiO\°`]»v¥Ï™ÖI$’óŽÙl¦OŸ>¨©…àêI$-ÀÒ¥Xwì *9Yú±Æ1äË•HÚ&“ oooáܽ;tî *•0¸–"ÖM>ˆK]£›…;»¹¸Ñ ‰¦4ñx8ջž¦ì¯x]ü•I>{Àª3•gŸÕ–8QWWÇÖ­[¹ã“Oþz€1ÉEÉ_ž‹Ÿ={6iii®®¿DrQŽ×Ý+~”¯8çâ$’¶ÉêÕ••á£õQzÿ‰4V%í {Ê•J*\dïGÌ.>‰s07‰¤Pµ{7IŠBhèÙ"ÍI$Îüe'EQP”ÖÜ'‘\쨪¥*1ÔÔ’ÁZ$W¡(PV†1&ïõÞ"ЋLÑ'igFüýýÑäåAYĦÀ,Äí!œÃt‚DÒvñZ¶Œk»vuu5$ ²K”H.$jîbÃε ‰¤b2Á=÷`Vyâ»ÌWÌ4ÉLe’vF}}=‹õÚµ°qü‚HMöw.7`‰¤9TTûÓOXÎSjÉÅ…4X%íä ½cFzˆwuE$’B§ƒaè=^‹ï¾ 9H%’vDuu5‘‘‘h2s¡8I¤FiÊN‰äÅl6³´cG|›™“["?¹+ŠBEEµµµg=Ñl¾¬`âÌÑì$§Çì~B¤oiϳÀWWB"iAªªàÄ âÊ∮Švum$’!??OOOTÅã!¥܉ Ò#i×ìËÏ'76–˜X9 )i>Nkuu5/¾ø"»wï>ë‰EEEg=¦Í ·ýY ±A¸˜U"~ æ!‹âÌI蛊9®¹s×uˆ„Ö[9¼&!¢î…#‚èhéþçès&D°{u"ws~ü¬ˆ$àÇIÁ“¡×½mez f1«#Á^¶{ØØ*hûñµ¶{ZQïiÛgOfn¤ÁåÏã¤ûoE$ûö@äy;Ý=-–ÛêÌGäS bÀ#ÇMO™˜Z"¹`8tV¬àX•žê˪ñ<¯ÉV%’¶Z­&Ä'Ê‹Vi¬JÚ3õõì\º”AâæÖVs4IÎ akÕù{ë¿@D­‹Â|ë¹Mt:µNÇå—_ÞhÞ±“8p «oÏÙ)B1 Œž?lR'#få®:Û7x8ÂØKG‘¾ˆ„ò•£ªapuG†žˆ‡sȶSLGgQo»æQÄú+0‘“ì8bư‘óë­ž» ¢'ÐÛVOo aÌG$´N®µÉ| Ø„0 m]Á*mò­C$ðN±ÉV,³ôòý&„Q>‘¬ÂÈ ¶ÕŶ»Òv“É»m2T! â àˆ­>ÛhÈava/·É›l“9Âv½ÀjD¾º à6››,û#øìñAé*ƒƒI$ åå`µ2¼p8~¾~®®DÒ"äääÐß­ ÑC¼‡««#‘´,»vQ÷úë\¾i“«k"i.&`7Âæé†˜ Ò;“Flß÷"ôý={æàn  {R«9»÷nc8¬nnnôîÝ›Aƒ]ø!§K¹ƒî@”MZ{ZY-b4À1sw Âxü‘üºÊ¶=a¨@KûlÛ‹ˆ‡· a¦ Wg lŸáˆ5X[Þ¯#/C\#Áú!Œ.aíû ˆ}vR‹H„]‡0œˆµŒ}Æ©Æ&ÏU6¹¶•ÕÅvíp„±W‰˜ù,A4°dÛµ®G4þøc233ÛŒF#/½ôGeÆŒ0kÖ,òóó›^ðD€5[âbôz=³gÏfÓ¦MÔ× å;//矞ÐÐPî»ï>Ž9¿þõ/™×XrAR]]Í¿ÿýovîÜéðÄIMMå½÷ÞcÈ!Üxã¬^½šo¿ý‹ÅÒ´BO@I^‰‰—´ Ž=Ê'Ÿ|BVV–c›ÑhäÅ_䨱c̘1___f͚űcÇšTfAAþnuÐuÏ1³!ißlذï¿ÿžââbǶÜÜ\žþy"""¸ï¾ûÈÌÌäõ×_o¾®RY‰’žÎñ‚¢¢¢šwî…ŠAw=ðð"@é¿€wmû÷!fKn¾þ€u$"v‹´ï8™uv·–úúz§Ž×d2QVVvJgìïïOÓ®t|ðÁX,'¥dÓ¦M”””ðöÛoÓ£G’““™>}:+W®äî»ï>{Áz„;ðãHƒUâr–-[ÆÖ­[¶ýöÛoøúúòÀàïïOXX<ð;vì¸0ÒDI$6ì£ò'+9V«• ””Ä=÷Ü—àÏ>ûŒk®¹†NšD©24NÌI»åd]åd6nÜHYYÏ<ó Ý»w§ÿþÜzë­¬^½Ú)`å™0 ÜmžµFW‹(¹È9qâŸþ9V«Õiû²eËàþûïÇÏÏzè!vîÜIrrrÓ/PUEeu5µ*ñññ®÷üc¥!sG®íS¤"\r£quòëJ»ÑÌTÒ,N1ë´Z-Ë–-ã?þpl+))á³Ï>cΜ9NÇÞqÇLœ8ñìW9 «ÕÊÂ… 1›Í\{íµüöÛoŽ}„‡‡;wwwúõëÇîÝ»›.Ísˆ"‘¸üü|,XÀ}÷ÝÇßÿþwÇöýû÷Ó§O¼½EØç:Þ={¤Á*¹ Øºu+;vìàŽ;îà©§žDÿ~ðàAzè!Çq}úôÁ`0››Û4ƒ5 :D¼[¼«E”\ÄØ_T*×\s «W¯vìKOO'22’˜˜<<<èÛ·o“u•â#Åxxo†È‘®SrSSSÃ'Ÿ|Â¥—^Ê®]»œöÙu///¢££‰ŠŠbïÞ½Í3X£¢Øyå•Äì܉Dž¾^»á—ºaWKCŠÈ^ƒ5 ‘rq<"¯ä¼ád°zzzr×]wQ^^Þ¤“{ôèÑì îß¿ŸeË–ñÜsϱmÛ6§}ÇÇÝÝÝ¡ÌkµZbccÙ²eK£e–——óûï¿síµ×â×ü_IûÃl6³cǶmÛÆˆ#ZõÚ¼ÿþûŒ1‚””§}ùùùôêÕËØ 00   ²³³-óĉ,_¾œÁƒãçç‡DR__ÏüAFFC† iÕkçåå1{öln¾ùf‚‚Òr(ŠÂ±cÇœòxGGGc2™œfbOÇþýû eÈ!˜¼Lc@rqó¿ÿý¯yË‚Î{öìaùòå<ÿü󤦦:í;~ü8]E§ÓÃŽ;ÎXž¢(ìÙ³‡^½zx,¯k!QF¾Ø©ªªbùòå.I÷²dÉrssyüñÇ9pà€Ó¾üü|úõë礫““sÆòL&6lp ÄàîÎáúzzôìÙêòê€ý€˜ˆ¢›ŽHÁØ ‘µB¦Xl”ììlÖ¯_ÿ—lÆ“q2Xu:C‡m±JŸ8q‚÷Þ{iӦѫW¯S Ö3q6Ÿy___úô郧§Î4 =zô ¸¸¸U×ÂY­V~ùå*++™6mZ“„ÎÖÆCBB4hCA’HÜÝÝIJJ¢°°°UYÔÖÖòé§ŸÒ³gOÆŒÃÎ;ÏzŽ=Êjc$$$зo_4 ‡âšk®i5™$m—”””SRíµ4Ççƒ>`úôéôèÑãƒõL4Ö«T*:wîLçÎÑÿOÏá·‰‰–î`;^^^ 4ˆŒŒŒV»¦¢(þøc¾üòK§c<==yøá‡™4iR“/f6›ñõõå»ï¾D¤¼ŠŠ ¾ýö[BCC騱#‡¦¢¢‚€€ŒF#‡’)?$ 555„……‘––FZZš#ñŠ+P…„„ 1èt:Š‹‹),,lT ’HÚµµµ„……9âTWWðÝwßqÝu×ѹsgòòò}¨­­eçÎNö#ÐXO—ήSr‘Àã?îäÞûÔSOÀÿýßÿ@rr2?þø#555pôèQŽ?Þ<ƒUQ¨II¡®²ò¬6-Ž‚0R‹ˆ I%À@o صՓœ'ƒÕjµòÓO?‘ššÊ+¯¼ÂW\áØÈM7ÝÄ7ÞÈÂ… ™?>cÆŒ!<<¼ÉóõõÅ×·!ž³——†±b¹OŸ>¤¤¤ðâ‹/2nÜ8¶nÝJ|||«Í‘Hþ*:Žàà†žÏhi üýýñõõåòË/gåÊ•<ýôÓôíÛ—åË—3jÔ¨&+ó‰«ñôôtŠàïï@pp0žžžÜ|óÍ<óÌ3<óÌ3²jÕ*îºë."""šT¾Á`pü&H$®àlºJbb"äÅ_äŠ+®`Ë–-tìØ‘aÆ5©üøðp°y H$­Z­>e‰‘N§ÃÃÃῌ3†•+WòÔSO‘˜˜Èÿþ÷?FEçÎÍh ¡àÚk‰_¿¾QWâÇŠH7ó Ä—‰@À_/VÒº8¬uuu¤¦¦2bÄ.¿üòÓ® ussc„ ¬Y³†+Vð—׎Ž7«=ô+W®d×®] >œ±cÇ:É…„››_ýµ#:Z`` /¼ð‹/&//»îº«EI$-M·nÝøú믳¢Ýºuãå—_fÉ’%Ô××óÔSO5˃ ººÚáf,‘´®ºêªSRy<üðì\¹’Ý»ws饗2f̘¦»±O ¾2£¤ípÿý÷;‰ ⥗^â×_%//{ï½·ùÑèFriò`åyÊH7c¶»3«· È<¨(N«Á`àØ±c\~ùåN.Y;wvŠîäááA§NHKKã¶ÛnûË‘K£¢¢ˆŠŠrÚÈäÉ“™Š€—€»¤±ÚÎp2X½¼¼=z4iiiü÷¿ÿ=e¦ ²²’o¾ù†ÜÜ\F-£9J$‰ä¼Q^^.gX%‰äBÆÛ›òÇCÔr9X-ÀDÔ߉À@wd:švÊ).Á£GfÆ ¼üòËìܹ“aÆѱcG ééé¬]»–72a† Òª ë%‰DÒ¾±X,MÎÙ*‘H$’6ˆFCÖ2ž˜zà xðsµÀ’–æ”VäëëËóÏ?Ï AƒøùçŸùã?¨¬¬ÀÏϰ°0þùÏ2vìX§Ô‰D"‘œ+Z­–®]»ºº‰D"ù«=JÁ–-çvµ8dÛ×fÌ‘´§öðõõåÆoäÒK/%//ÂÂBT*aaaDGG7+÷ªD"‘H$MeÈ!¨ÕÒ§K"‘H.X/¦<5•€AƒÎ_™™ˆÀ¿÷#r©Jcõ¢¡Ñyú°°° Ö5«¬ ôzñH4¶ÔÖh„º:ÈË«bc!0Ðù˜ãÇáØ1ض z÷Ûbb 4||N-Ój…òrð÷‡³yCÔÔ@u5@E…Øæáf³HÕæáÑp¬É%%àçµµ r*Š('.JKű>>PX(޵tÖj!, Š‹!(ŠŠD]ÝÝA­†ˆQçòrñçæ&ê¦Õ ùEܵZçé)®§("R]¸ßö%hPU%î±]VçnÙÀÖ­b[X˜¸Ÿ:¨‡} µ¿?dd@d¤×`Çx{‹:Azº¸/11â~øøÀáðcG0%ë€DÒF#h4âOr~ù«iÒ$‰DÒFÈÊ☇ÇùËÁšŠ˜M}øÚÕÂI\A» ñûÕWÂÀY¾\(—ãÇCŸ>й3¨T¨).†ü|øæ¸öZX»V:ÁÁâܤ$ؼYV:ŒÝ» oõja\öéÛ·Ãõ×Ã÷ßC}½0xÃÂ`ÿ~èß_”a6ÃW1.*+!'GƒC†ÀÀm·Á+¯ˆcÇúù ƒíÄ aMš_~ &À† b_ǎг'ìÞ-dZµ ÂáW/Q‡ØXQת*!_Ϟ☡CEÝu:HH€ìlQ^a!9"Œ¿…¡ »vA‡âzÙÙàå%ŒÕÌLq_ãâ`çNèÒ~þY±ƒ‰ûíç' ËÜ\ñ|†urs°Ù,ê—“#dèÐöîÇÞ|3|ø!Lœ(Î//ƽ»»¸·S§ŠcEÈWY)ÊìÜjkëÑhÚ_`0E†»F#Ng8Ù)¬Vñ Ôjñ×z½8Þ^žZ-Î5ij²—ißn±ˆÁ “Il×jųÔhÄ>Ei(Ïhö2ÜÜÄy8ÆlûÔj1Ø`µÂ¾}¢Ýtï.Ú }É|a¡hw ÞánÝD›5EûT«Eyz½xbb >^\Ó>¢(âÚ……pð ¸^v¶¸^¿~☈Ñþ¡a€dÙ2èÛ/ÛLJ•+aÔ(Q†‡\r‰¸žÁ Úif¦x£¢Ä;¦R‰{µ¿ĹôRX¿^¼o{öˆ~Ä>xSU%Þç¬,QþˆbàÆÃ–/×°sg,ƒµÛ®\"‘HZ «UüîØ?Uª†üÆ8ù·í\P°XTX­®¾çs§Nœ8r„¾çšS[A¸ÿ~ <$žÿºÚõŽó’ÇÞFìÏÖlÛT*ñg25èLjµ³Nd46lwwÿkµ “AömövjµŠÿu:qîÉÇjµâzf³8Ïdßuº†2ŒÆÝÌãAw±Oü¹» ½¤¼\ì+(vI·nbÂ(1Ql·X„màå%ì ƒvì€Í›IN6žÓýlwZŽÕ*fì„3mš¸Á99ðÛob»¢C6>&O†×^Šä¤I¢Œº:X²Dh¾¾pï½B=¹9²áÿoeÆÇ‹ë‡†:çÿÛß„¡åë+Œ)ooÑ8 aX…‡Ã-·ˆc—.=UžãÇ…Rëå% 9{=ÿœÏùê«Åçõ×7l³ûg®¼òÔcA4Þ²2ÑÐþÌÔ©g¿ÿöcî¾ûìÇ^~¹øLH8û±ß|súíû›ø7îôûÆ:4íp¬¦žzJF%%ÂàéÓG X­–ëÖ £½ @´³º:±/*J .¬^ cÇš5ÂHóôÉ$ŒÃŒ q­Q£à×_aôháaPW'A"#!5U¼ ©©¢='®Û«—xçêêĠƸqbPæ²Ë„a¦RÁðáb ¡{w!ÏîÝâØ D7r¤x¯†dQ‘0ö,Q·ÄDaàEG‹wS¯u÷ñß-!We¥0ËÊÄÍ A¢¾v9{ôïcR’8¯ºZ ¦¤§‹û»c‡¸>>âû´i¢Î7Ý$Ê´X„§€··¨×¡CðË/¨=fÌ}OÏžâÞ¹SÈ(ŒÑà`ñc$~(ʼnø®V‹²ÅýÉÉ÷89-@«uu“”H$’s¢¼\ôÅöÁD»²ìí-”eooÑw*ŠèíƒzæÈÑ/çå‰>ÖËKôÙùùb@=3SüÞùû‹ß?»7×öíâØÉ“EÉÉ £¡¡Â«­®Nèr;wŠÿ¯¿^\#>^”o6‹ßaOOñ[Ø0è$úo»'˜Á ÎÍÍ  ºº…s•¶2æ{î¡þŸÿ$ àÜ Ú¬^"?Ôd:EMhGáápô¨ÐßsrÄ1AAâ9yx4Ø……B_³FL¦lÛ&Œ¼Î…Îd0ˆòŽeôï/ž[HˆÐ¿ôzñœƒ‚ÄÿjµÐÁjj<„ŽSY)ÕããÅàtB7 :ÍîÝЩ8 B¡{­_/&½~ýUlKImÓÇG´³âbÑ.GŽ“oC†ý#$Dè"vý.)Iè?µµpÕUBLLƒç……âøqãÊX·NÈ>§ŽX­¢ƒµ¹¹úîzúûÕ¿ÃÿörÏ4Ó¥KÃÿ—^*>‡ 9ó³ Ÿ¡¡â3:Zü¸€¸#Fyìƒ3 îÙé°¿ç:]ޱcŧÉ¿þjjf ’´7E(Êuu ƒ5öަŽ×Ùg™Ìæ†>Á®|âSq¬‡GÃH¾¢ˆwÄo¢4öYOOapxy‰Ïúú†þÚZq#G„rÙ³§87!Aôs[¶¸SPÜ4!$MBQúçÚZñÜÝܼqì32 ¶WU etî\¡ä_r‰PZÕjÑÒÒÄ3ž4IL ,~‹jkE¿æí-Ú“Å"ž­››Ô¸Ù¯_ÃR¥¾}…—ˆû¶oŸ/;[´ï= gÏZ²³«]Ý,Î+f³£Ñˆ—×_\dªå`.ÓÕP¯ý1a nÜ(~'ÿøCèÔƒ '<\<‹Eè‹hCâúIv¶x†:Ѓ †Zÿþ¢­zxˆwÄî9fïíqfOž‘4™)g©«ƒ ¢½õè!Ú}ÖqÐ ñ¿¯¯hGW_-®c×5¼¼ÄÿbÐÄþNº¹ ]/0PL6¬û˜L žq ö ">GŽejµbŸ½¾W^)êêå%ô_ßo=//ñ9a‚8çLºÒÉôê%>OÖsN®ŸV ;wVSYi8{aЮ V“ >úH¸÷Ÿæ÷Íþ0$’ ™½{Å ÌÇ‹´S'Ñ©â¸îºSÏ‹‹³»t×]§¿Îé–žüy°4ä4ƒÂvãíÏØ×bûû7_fµZtªøQ’HZ‚‚¡tlÝ*f’ÂÃÅ(yLŒðè)+ÊÙ€Âà !ˆc**Äû[P ί« ujªY´¨ayŠ}V¨¬L(òîîBÙúõWñ¹p¡èºuƨ^/¿#GÄèÿ5×Àÿ+¥M›Ä,Cl¬(óÐ!1[-Þ//!Sq±0޼¼¬Ô»úv_0âyæäeÜÇG(Ûyy ±)‚‚„ÈWˆçâã#ÕõzÑo¹»‹ÙµZ<ÿ+ij»ûna€ý™Ã‡Å±âw%2R,q2™ÄsT©2ìƒ ÞÞ°óõqABB×Ïx@|žì½e±ˆzyz‚=°¸¿?ÜyçéÝ;Ÿ'þLTTÃÿöC»ûgNX´Çúó@ëWˆO»A Þm'“›k¤¸øÜ”ù¶†ÅbÁjµ6É`Í̃¢?8~zﵿBäpdèÃĽ íU«m8¹æ1àüç‰#û38Ó€öÉØu—“®[ƒ¦è gJÊ¢Õ6¤vìºÖÉño !Gƒ.w®àgãÏu;Ú•ÁªÑˆŽªG³¯?H.Dêë…±zË-§v`:ð"H$­‹Õ*ÞME† ¢ˆQqû숑~£Q(ÍÕÕB骨h®§Ó 70³Y¸Šˆ‘òýû…BŸ-fp‚‚„ayèØ_Y)~ó #Ü:]è{y¹ñ/)iˆ…âz%% Ç&$ˆ2‚ƒEÙ~~ÂØñðhpÃwsu«©iXÎ+¶.¹D(&:]ƒa"Öæ ÃÁ×W>ÞÞ0l˜8ÎÝÝ9 áÉË:N,ZVfbÉ’:W?b—S[+ž§¯¯h?ÂÍÌlðY»V, Y¾\<ËE;ò÷ a¡x®C‡ŠÏˆa4ÚŸ4<·zÛ¯¯˜= >ólýÉÆÛÉ °V+®s&ÎÕ›K£i(ÿLn×`4©¬¬<­Áj±ˆ8'»v‰>%>^´í¤$ÈÙñ•Sׂoà §}@Ë>q&o$Iû¤Õ VEQÈÍÍeß¾}X,ú÷ïOôI>¯‹…C‡‘™™I‡HLLDÛD]­np7”H\I]]Û¶m£°°Î;Ó«W/ÜmÉd"--’’ºuëF§NšµÎvôè¦J$-Iqq1;wºšž={Ò½{wT6M¢¶¶–M›6a±XèÕ«QQQŽ}í…òráê—Ÿ/”æ~Þ=?ÿ,¾wí*ŒU£QÌÜÚï[C´ùÇõùúŠ}Ý» WrF]ºˆ™ÈK/…éÓ–mœ-ú<C4)©áûɱ΄Ý;Éîî~¦ýÐ0#Ñ”ûhÿ…âå¤( 999ìß¿«ÕJRRÒ)ºJFFYYYÍÖUšŠÙ,1 à»ïÄ÷k¯‰‰¢íùøˆ5qö¥ƒ‰%MgûI±Ï&žé9KÚ?&“‰ÌÌL<ˆ)))øŸäe2™Ø¶m¥¥¥tïÞŽ;6YW9qâ§D}ÿã1g±]Æî> €®Ü „ÿçê»#ik´ªÁj6›Y´h}ôqqqX­V>ýôSþþ÷¿sÕUW¡Ñhøì³ÏX¶l”••‘””Ä?þñ|/4@ÉEKVVÏ>û,f³™€€fÏžM¯^½xþùçxíµ×8pàÁÁÁqíµ×r×™ürÿ„‡‡X-=$®Âjµ’ššÊ«¯¾J@@îîî|üñÇL™2…[o½•ÂÂBfÍšEUUžžž”••ñØc1bÄWW½Q쳇ååâ“Ia‰Žkߊ‹Åîœa b31Q ÉÉbû¨Q˜tsk0þlÇ &>ÇŒqµÔ’Óa6›Y¸p!Ÿ|ò ±±±X­V>ùäî¿ÿ~ƇF£á“O>áÿû”––2`ÀþñàsºøàbccÙ°aÿú׿X±b¾¾¾lذ·ß~›>}úðã?òÙgŸ1~üx›‘ËÄH"qõõõÌ™3‡.]ºðÌ3ÏàããÃÿþ÷?Þÿ}ú÷ïÏúõë)))á£>ÂÏÏwÞy‡Ù³g“˜˜è4zï ,¡8éõÂÕhÄÌÔw߉™C“IÌhyx4ĈkÂu:±6¯°P£ÝºþgZk$¹pÈËËã»ï¾ã†nà¶ÛnÃb±ðÅ_ðïÿ›!C†PQQÁ‚ øÛßþÆõ×_Ïž={xðÁ1bÇÿË×­­…Y .¹fÎË?Ë#/‘üvïÞÍúõë™9s&&L ¸¸˜^xÏ?ÿœO>ù„M›6±qãFÞ{ï=zõêżyóøú믹ꪫš¤«äççe›ÆÏΆW_®¿?~šölæé€LÅ-9 ­:OSZZŠÙlæŽ;îÀÏÏ®»î:Ž=Š^¯'--ÈÈHÆŒƒN§£gÏž 2„ßÿÝÕ÷I"i2GŽaêÔ©ÄÇÇ£Ñh1b111dee±qãF† BïÞ½Ñét\~ùåtèÐövIÇ`0PXXÈí·ßNhh(žžž\wÝuÔÖÖrâÄ 6lØÀu×]GTT¾¾¾Üxã“aÏ“ÔÊèõ"ГOÂÀK/‰YÒÌLÅóøq¸á¸ç¡L}ý5|ò‰ˆ’8}ºX'Õ¿¿0 BBDDÄ3«’öAII Š¢pÛm·áëëK@@×^{-¹¹¹ ¶nÝJTT—_~9:ŽÞ½{“’’ò—u•ÂBáRþÐCb]ò×_ÃóÏŸ9m‹Dr®dggÓ³gO®¾új´Z-‘‘‘Œ;–ôôt6lØÀ°aÃèÙ³':ޱcÇΦM›šT~^^¡¡¡=*–IL*Rñâ5ovÇ€W¹YrZu†µcÇŽÌš5ËáÞkµZÉÉÉÁÏÏ777²²²ðññ!жz^«ÕÒ±cGÖ¯_ßh¹V«£ÑˆÕju¸H.nEÁd2a2µ~Ê™3gJ¥BQJJJ¨¬¬$88˜]»v1dÈt6-$((ˆ:Ôh™V«ƒÁ€V«•m\ˆ6n00›Í(ö|#­€/¼ðÝ»wwÔ#//777¼¼¼ÈÊÊ">>Þq|||<ƒöˆ?gÀžA«ÕžÓzW“I¸UÚÓ|ù¥btûí"©˜Yµ§’´m {FûV¢K—.¼üò˧è*þþþ]ÅÏÏÏ¡«èt::vìxVeÞl6c2™k]E¸›õüãðò˧Î.i¿ØÛ­ÖsËQÙ\† Fÿþýñ°-.·X,äææb ýèÐ!FŽéÐU‚ƒƒ nTWQ£ÑˆÅbáĉ„†Fñï‹H˧ío`5° ˜ÈÁ™v‰ý·ý\õ”VÕ|èk‹‰^__ÏÏ?ÿÌo¼Á½÷ÞKPPƒµZ›-š„Z­ÆËË‹òòòFË-//gÕªUÔÚ“ÁI.z, [¶laË–-­n´öîÝ›¬V+<õÔSèt:&NœH}}=nnn£S§Ó¡ÓéÎÚÆ?Îo¿ýFuuûÊÕ&ùëÔ×׳zõjÒÓÓ[UÙÑétôë×OOOÌf3k×®åÿøW^y%}ûöE¯×;”///ÌfóYûç½{÷²víÚ¿lœ °t)<ý´Pü?ùD¸TÞt|ú©Zäïßô¼¤’¶Á²eËÈÏÏoÕkh ¹^WWÇ‚ xë­·¸ï¾û@¯×£V«hÔj5žžžö㊢°{÷nvíÚ娖 o¿ ÿü§X-Õ‹ªª*–-[FUUU«^7**ŠÎ;PTTÄ_|ÁÒ¥K¹ÿþûºŠ}ðP§Ó¡Õj©¨¨8c™&“‰õë×sôèQ&N¼žãÇ;2x°sp'v‡€ ÕvLvv6k×®Åh4žS9­%Øjµ²wï^¾ýö[rrr˜>}:×_}£ÑõÎ6£ÌàÁƒe`&‰777†ŽÕj=ï‘φ¢(ÔÔÔðÍ7ß°víZºvíÊwÞIðé’Û8[ŽŽæºÓ%W•\´xyyqÕUWa2™šeú| ( ùùùÌž=›]»v‘’’½÷Þ{JDH;*•ê¬m¼_¿~Œ;¶™õ.¿‹‹µ©:ÈÇ/"OjµÎIÖ%'NdÉ’%­~]«ÕÊž={øöÛo9zô(·Ýv'Nt ¨ŸŽÆÚ¸J¥¢ÿþ$''b=uV<÷œp3—\œ0qâD¶oßÞê×6¤¦¦òÕW_a±XxñÅIIIiôœÆÚ¸}™SBBÞÞ <ô<ûì>¼ <D!iÇtéÒ…±cÇRYYyNå´ªÁj±XX·no¾ù&—]v=öNJÒåããƒÅbq¸ÌX,*++Ž‘HÚ:ÇçÕW_Åh4rÿý÷sÙI™Ç}}}î?jµšúúzêëëIHHpuµ%’&¡( {÷îåÕW_%&&†W^y…=zBòññ¡ÞžÄ¨¬¬D§Ópž3”×ÖŠ¨“û÷‹¢×]'£¤J΋…ßÿ·ß~›Q£FñÄOéØïããCQQÑ9é*yyÂ]ý«¯\-­äbÄl6óùçŸó¿ÿýiÓ¦qå•W:Å;®¢×ëéÚµk“Êÿö[ ýŒëýÿ\$5©8‰¤u Öììl>øàî¼óN®¹æ‡ï¼¾}û’ššê‡m0سg½äð£äböìÙÔ××óÆoœ2«šœœÌ¨««ÃÇLJ'NpìØ1&MšäêjK$M¢¦¦†÷Þ{ÄÄDxà§YUµZMRR;wîdÔ¨Qìß¿­Vë”Ãò¯¢("åǾ}°r¥˜A4I¤”‘HÎGŽá£>âî»ïfüøñŽÚvúõëÇÖ­[9qâ±±±èõzöîÝëXòÔ†¿ÿýÂÉK+i_¤¦¦²bÅ ž|òI† rŠ—Nrr2D¯×ãååÅñãÇ9qâS§NmRù×\#R‚2!kæ# Õk\}$­j°fddpøða233ùàƒœöÝwß} 0“Éį¿þÊ´iÓØ²e YYYüãÿpõ}’HšD}}=ëÖ­#22’¯¿þÚi_rr2#FŒà×_å?þ`À€,Z´£ÑÈСC]]u‰¤I”””––FPPü±Ó¾ &0zôh¾ÿþ{ÆŒƒ¿¿??þø#;wnòÈ|c”—‹H¿ýû WJ™æIrþ9xð ÙÙÙådf̘ÁÀyÿý÷ùõ×_¹ùæ›IMMåÈ‘#<öØcM*¿®NÌ®¾ø¢\S-i}Ìf3›6m¢ªªŠ 68 óõõeÆŒŒ1‚¥K—òÇ””Ä/¿ü‚ÅbaðàÁMº†-&ß©!Ö­>‚\·*i­j°Z­Vúõëç›}2&“‰ž~úi>ÿüsÖ¯_‡‡=ôÃÝL"iëTWWÓµkWª««Ù·oŸÓ¾˜˜† ÆÌ™3™3g_|ñ!!!<ÿüóxÊä’ „ÚÚZúöíKQQEEENûFŽÉ„ (**⥗^BQ¢££yøá‡15EjÞ}·!Ú¯Tô%-…Õj%11ñŒºJPPO?ý4_|ñk×®ÅÓÓ“Gy¤Éƒ2¿ý&Ò$ÙbÞH$­ŠÙlÆÇÇ‡ØØX<è´ÏùºOŸ>̘1ƒÙ³góÙgŸʳÏ>{nºJðp#àê» ¹ÐhUƒõšk®ášk÷âãã1b„ÔU$íEQ¨¬¬dåʕӧO’’’¤®"qmÎ%øµ×^ã7Þ ´´”ùóçóÌ3ÏP^^îêjI$ç…òòr}ôQ~þùgŠ‹‹yíµ×xï½÷\]-‰ä¼‘žžÎý÷ßÏæÍ›ÉÊÊâ‰'žà¿ÿý¯««%‘œW^}õUÞzë-JKKùþûïyî¹ç¨¨¨puµ$’óBii)<ò‹-¢¨¨ˆW_}•?üÐÕÕ’\Ä´©Ö½{÷’ššÊO<ÁèÑ£9zô(wÞy'6l`„ ®®žDrάY³†üü|>úè#Xµj¯¼ò S¦L¡S§N®®žDrNX,~üñGüýýyã7ððð૯¾â‡~`ðàÁ„‡‡»ºŠÉ9³gÏ6oÞÌSO=Åe—]FNNwß}7©©©\}õÕ®®žDrά^½š'Nðïÿ›¸¸8–/_Î믿Î7ÞHÇŽ]]=ÉEH›šaÝ»w/ 0FCTTƒ bóæÍ®®šDr^رcÉÉÉÄÄÄ ÑhèׯQQQ¤¥¥¹ºjÉ9cµZÙ±ccÇŽÅßßwww.¿ürªªª8r䈫«'‘œöìÙCTTýû÷G£ÑMrr²ÔU$í†;v0hÐ ¢££Ñh4ôïߟÈÈH¶oßîêªI.RÚ”Ázøða¼½½ @«ÕÒ¹sgÒÓÓ]]5—²iÓ&²³³]]£¤¤„%K–¸º­Â¡C‡ˆˆˆ@§ÓLhhèE߯øá¬V«««Ñbäææ²fÍWW£ÅQ…¬¬,bbbÛ0 ?~ÜÕÕs)óæÍsuZ”´´4öìÙãêj´ YYYøøøàïï€N§£S§Nu?^WWÇ¢E‹\]Ãb±°|ùr \]•VÁ®«Øc„„„BFF†««æ2òòòXµj•««ÑbTUU±páÂ6«‹µ)—`‹Å‚J¥B­v´J¥ÂÍÍÚÚÚ3ž£R©¨®®æË/¿$667·6%Òy!;;???‚ƒƒ]]•¡¦¦†ììl*++Ï[™ö€'Nœà†npµˆÌf3jµÚ˜C£Ñ Ñh¨««;ã9Z­–cÇŽñî»ïØ.ÛøöíÛ1í6`IYYÅÅÅçÕh³X,”––R^^ΰaÃ\-¢S½4ã»V«Åb±`0Îxާ§'›6mâØ±c¶Ëv––†Åbqu5ZŒ£G¢Ñhλњ››ëjÑNá¯è*Š¢ðÇPQQŸŸŸ«E8ïF`ß¾}Œ3Ʊ½´´”'žx‚µk×R^^Îwß}G}}½#Qó¾}ûøÇ?þÁáÇÉÌÌdΜ9ôìÙ“:™™ÉÃ?ÌþýûÉÍÍeîܹtèÐŽ;¶š\õõõ<ùä“Ì™3³ÙLZZsæÌ¡[·nDEEQVVÆ“O>éPÔ¾ûî;jjjHNN`ÿþý<ôÐCdee9äëÖ­ÑÑÑ,Y²„þóŸ”——³yófV¬XARRþþþ®~¤’?Q\\Ì+¯¼‚§§'—\r‰c{FF=ô$;;›9sæG||<+W®äñǧ¬¬Œ­[·²lÙ2’’’)Qþõ¯ñõ×_S[[˲eËØ¿?lµ‹üü|î»ï>RSS©¯¯géÒ¥,]º”‘#GâííÍ¡C‡œä›;w.111$$$°fÍ}ôQJKKIKKã¿ÿý/ýúõsÈ÷úë¯óÅ_PWWÇo¿ýƾ}ûZU>IÓP…¬¬,fÍšE¯^½ˆ‰‰qìÛ¸q#>ø %%%ìØ±ƒE‹ѯ_?‚ƒƒxÿý÷ù裨««cåÊ•ìØ±ƒääd<==ÏÚG¶›7oæïÿ;999”••ñý÷ß“••åh‡©©©<øàƒ±k×.~ùåúöíëï£>âƒ>pÈ·}ûv‡|åååüßÿý«V­¢¼¼œyóæQUUÅÀ]ýH%Âjµ²mÛ6Þ~ûm.»ì2û¾øâ Þ~ûmª««Y»v-›6mbÀ€x{{S]]ÍÓO?Ͳe˨¨¨à‡~ ¸¸˜Áƒ£R©ÎÚG¶4f³™_ý•Gy„²²2òóóùꫯèÙ³'nnn|ýõ×¼ùæ›ùRSSòÕÔÔðÏþ“¥K—RYYÉO?ýDAAC¾¶ ‹Iš†Åbáûï¿ç·ß~ãÊ+¯t Jèõzž}öY.\HUU?ÿü3ùùù¤¤¤ ÑhÈÎÎæá‡fÏž=äåå1wî\‚ƒƒéÚµ+ÀYûÈ–Æ`0ðÎ;ïðÎ;ï`08pà_ý5ááátî܃ÁÀsÏ=Ç‚ ¨®®æ—_~!77×!_NN<ò»ví"??Ÿ¹sç@·nÝØ´i>ø ………ìÚµ‹… Ò·o_§AŸA‘´*¿þú«òøã+‰‰‰Êã?î´ï§Ÿ~RF­¤§§+F£Q™;w®2jÔ(娱cJ}}½òôÓO+÷ÝwŸRRR¢TVV*O=õ”2sæL¥¬¬LyõÕW•©S§*EEEJMMòꫯ*·Ýv›RZZÚj²mذA=z´²lÙ2Åd2)ÊÌ™3•{ï½WQEY¸p¡2jÔ(åÀŠÑhT¾ÿþ{eäÈ‘J~~¾¢×ë•gžyF¹û’’¥ªªJùç?ÿ©Ì˜1C©¨¨PŽ?®L:Uyï½÷”šš¥  @¹îºë”?üP1›Í®~¬555ÊþóåŽ;îPz÷î­|÷ÝwŽ}F£Qy饗”éÓ§+EEEJuuµòâ‹/*wÝu—R^^®*Ó¦MSÞxã ¥ººZ),,T&Ož¬¼ýöÛŠÑhTÒÓÓ•#F(¿þú«b4•;w*C‡U~ÿý÷V“﫯¾R®ºê*eß¾}ŠÅbQöìÙ£Lœ8Qù÷¿ÿ­˜L&eÖ¬YÊ-·ÜâoÖ¬YÊwÜ¡”••)EEEÊ­·Þª¼þúëJuuµRTT¤ÜtÓMÊ›o¾©F%##C9r¤òË/¿(F£QÙ½{·2tèPeÕªU®~¬’“ÈÏÏW>ùäåºë®SRRR”7:ö•””(wÞy§òòË/+•••Jqq±rÛm·)³fÍRôz½’™™©\~ùåÊüùóÏ|ذaÊÒ¥KEi¼l-|ðAåÎ;ïTŠ‹‹£Ñ¨¬]»V¹üòË•åË—+¥¥¥ÊÝwß­¼øâ‹Jee¥RRR¢ÜqÇÊK/½¤Ô××+YYYÊØ±c•yóæ)ƒAÉÊÊR† ¦,^¼XQñû7jÔ(eß¾}ŠÑhTæÏŸ¯Œ1¢U哜ýû÷+¯¾úª2fÌåꫯV²³³û²³³•«®ºJùöÛo½^¯äåå)Æ S~øáEQeÅŠÊÈ‘#•íÛ·+F£QY´h‘2dÈ%''ç¬}dkPPP ÜxãÊ›o¾©TVV*µµµÊüùó•K/½TÉÊÊRrrr”ñãÇ+³gÏVôz½’ŸŸ¯Œ1B™7ož¢(вzõjeäȑʶmۣѨ,Y²D2dˆrøðaÅl6· ]Lrv~ÿýwåé§ŸV ¤ÜqÇŠ^¯wìÛ¸q£2bÄeÆ ŠÑhTV¬X¡ 2DÙ¿¿¢(ŠòÖ[o)'NT ”ÚÚZå­·ÞR¦Nª”””œµl vïÞ­Œ7Nùᇽ^¯”——+Ï?ÿ¼rõÕW+Š¢(›7oVFŒ¡¬[·N1ÊêÕ«•¡C‡*{öìQEQÞ}÷]åÚk¯U ”ºº:åwÞQ&Ož¬+eeeʽ÷Þ«<÷ÜsJEE…RRR¢Üu×]Ê /¼ÐâòI?œVF§ÓÑ«W/ǬáÉlÞ¼™#FбcG´Z-£F"88˜mÛ¶Q[[ËÎ;™8q"ÁÁÁøùù1eÊ:DNN[¶la„ „††âííÍu×]Gqq1YYY­&[nn.—\r £FÂÍÍððpFŒá¨ÃæÍ›>|8:uB«Õ2räHÂÂÂØºu+uuuìØ±Ã!Ÿ¯¯/“'OæðáÃäåå‘““Cyy9'NÄÛÛ›ððpÆφ 0™L®~¬’“ðôô¤_¿~9m7lÛ¶k¯½–ÐÐP|||¸á†8vìGŽ!//'N0iÒ$||| c„ ¤¦¦¢×ëÙ¶mqqq 6 ­VK·nÝ8p üñG«É–››ËUW]E÷îÝQ«Õ\rÉ%ôìÙ“ÌÌLL&[·nu¼‡>>>Lœ8‘‚‚>L~~>ùùùÜxãøøøÊ„ Ø´iuuu¤¥¥͈#ÐjµtíÚ•”””V•OrvT* 0ÀÉÕ   €¬¬,¦NŠŸŸ!!!Lœ8‘mÛ¶QUUÅ®]» aÔ¨QhµZ>|8ëׯï#[‹cÇŽqóÍ7‚V«åÒK/ÅÃÃãÇSXXHff&S¦LÁÏÏàà`®¿þzÒÒÒ¨ªªb÷îÝ0zôht:qqq\z饬[·Î!ß!CèÒ¥‹£ìˆˆ6oÞìêÇ*9 •JEtt4}ûö=eßþýûñôôdìØ±¸»»͘1cœžñÀéÑ£Z­–!C†ïp­l¬l jjj¨¯¯ç–[nÁÏÏ///ÆGqq1ÕÕÕ8p­V˸qãpww'**бcDzvíZ‡|ýû÷§W¯^hµZRRRèØ±#©©©7RWëb’³ãææF×®]éÔ©Ó)û6oÞLbb"‰‰‰hµZ @÷îÝÙ¸q# fPÇOxx8^^^\sÍ5ÔÔÔžž~Ö>²5((( <<œk®¹wwwGŸlÇ6oÞÌ%—\BRRZ­–¤¤$zôèá$ßÕW_Mxx8žžžŒ?žúúzL\\œc_BBõõõ´šl—_~9>ú¨Ã}Q¯×“žžîõСCtèÐÁ±Þ/$$„€€2331äææ:É×¥KÊËË)))¡°°ÚÚZ:tèàØß­[7²²²°X,­&£¤q¼½½¹þúë¹á†N1XÍf3GŽqj§:u¢¦¦†¢¢"JJJ¨¬¬tz7ºwïNvv6F£‘¬¬,üüü.àîîî$$$‘‘ÑjòÝu×]L™2ű^«¨¨ˆüü|bcc±X,§È×±cGêêê(,,¤´´”òòòSäËÉÉÁ`0pøða|||òét::vìØªòIÎN‡˜:u*ãÆsZ×bígqq±SèÞ½;G¥¾¾žììl<<<›;wv<ãÆúÈÖâÕW_%%%®ÏGŽq¬áª¨¨ ¨¨è´òÕÕÕ‘““ƒ»»»C>FC—.]Î(_pp0ÁÁÁ­*ŸäìôèуéÓ§3lذSö=zµZí› [·nNÏ8<<Ü¡NzzúYûÈÖ C‡¼ýöÛ„…… kÊýýýñòò"//•JåäÞØ˜|„‡‡“‘‘Õjmº˜äì 6ŒÛn»Íáæz2™™™„††:ÖeúúúÒ¡C§6pò3Ž‹‹Ãb±pìØ±³ö‘­Arr2Ï?ÿ¼c@Õl6sàÀ¢¢¢õ q’/**êŒòÅÆÆbµZ9vì•••ž"_~~>µµµ-*—Û¹!9_ 4ca³V«E£ÑP]]¢(˜L&§à.žžžèõzôz=F£Ñ)(€‡‡f³™úúúV«¿ýàøñã|÷Ýw¬_¿žY³fQ>77·Få3 èõzÌf3V«ÕIFOOOǹ’ “ÉtJ;5™LÔ××£Óé°X,§´šš¬V+F£µZí0Õj5îîîTVV¶Zýí*V«•¬¬,Þÿ}***¸å–[NûÚåÓh4m^>ɹa±XNûŒkkk±X,˜L&T*•ã«T*<<<ϸ±>²µ°¯Ã²X,lÚ´‰÷Þ{>}ú0|øpöìÙsZùêêê0›ÍY¾Öšyœ;v¦“ƒ,yzz:=c777G777´Z­ã7ÖG¶žžžŽ6n2™øù矙={6·ÝvqqqFG½›*ŸN§sìo º˜äܰ÷S~ÆöA‡??cwww, uuugü °÷‘­A`` #.FYY?ýô?þø#<òˆ£þ'˧ÑhœÚ°½Ÿ,ŸÕjuü޹J>i°^4%T­VŸ1ÂbcûZŠºº:V­ZÅܹs ä7Þ OŸ>-"ßÙΕ\œíŸ­ ŸÜ±¶4Š¢PYYÉwß}ÇêÕ«éÕ«=ô¡¡¡g]¼ä“´ jµºÑ(¡g{Æ­ÙÏ)ŠÂ±cÇøä“OÈÈÈ`èСL›6í”HȪ|’–á\žqkë*V«•]»vñÍ7ßPTTÄôéӹᆠnw!É'i{Æ'ÔŽ³õ‘çƒÁÀúõë™;w.Ï=÷ƒ¾ å“šPÂßß½^ÕjE­VS[[‹Á` <<Fƒ“KAII >>>øúúâççç´¯¼¼NçÙ¯¥1™L|ôÑGlذ{Ë.»Ì)ŒöéäÓëõDDD V«O‘¯´´Ô‘ÚÆ>ûZ__ïps())!<<\þ\ ¨T*|}}žqYY™#dºÅbÁÝݺº:‡«JII aaaŽÔ!åå厶`6›©¨¨ 22²Õd(++ãÅ_¤¦¦†|aÆ9™3Éçî¿?æ´ò…††¢Õjñó󣨨£ÑˆN§Ãl6;ÒžH. ÜÝÝñðð ¶¶ooo@<ãt:¾¾¾ŽÙtN‡Õju¤~ÆûÈÖ"==W^y…:ðì³Ï’˜˜èاÓéòÙ Øââb‚ƒƒÑétøøø`µZ1 ŽQùÒÒÒ3ÊWWWG}}ýiÝò$m{»¶?cmüÏÏØb± Ñh¨¯¯§¦¦†N:µl ¬V+6làÍ7ßdÈ!üßÿýŸÓR#»ÎÒ\ùbbbP©TmB“œþþþ Ìf3nnn ªªªíÄßßßéWTTàææF``àYûÈÖÀl63oÞ<,XÀ”)S?~¼cÆõ¯Ê§Ñh r’Ï.Oqq1AAA-žÍ@júmˆ””vïÞÁ`ÄZ‘¢¢"z÷î———\r‰Sð­[·FTT pÚ·{÷n<==Ò-´4¿ÿþ;6làÅ_äꫯv2VíòíÙ³½^à²c—¯OŸ>N2lÛ¶"""HHHÀÏÏ={ö8öoÞ¼™^½zɨ NGRR’Ó3Þ¹s§cýDll,¡¡¡ìܹӱÓ¦MôèÑwww’““9qâÇŽÄlþîÝ»O¤¥øþû難¨`Ö¬Y\zé¥NmO«ÕÒ¿'ùvíÚ…··7111DGGÁŽ;œäëÞ½; 0€ÂÂB‡|z½ž]»vµª|’s#22’¸¸8¶m󾯦iÓ&:w·7}ûö¥¢¢‚ÜÜ\@ ò¥¥¥9žqc}dkñöÛoÇ‹/¾xŠwLDDñññNòmÞ¼™N:áããCß¾}©®®&''nÅ–oïÞ½÷Èüü|Ž;vV/IÛ¡wïÞ § B›7ovzÆ ¦¦`rrrlë#[ƒãÇóî»ïróÍ7óè£:«½zõÂl6;­«þ³|ééé碢"Ž9Bbb"¦Mèb’s#%%…ÌÌLÊËË1`‘™™é¼4hÓ3Þ¿?jµšøøø³ö‘­ÁöíÛùùçŸyòÉ'¹ù曌U»|YYY”••bÐèСCùRRRœä;x𠊢@xx8;v<­|¾¾¾-*—ÔôÛ#FŒà¿ÿý/ëÖ­£oß¾üðÃèt:ú÷ï››ÇçÿûÄÍÍ~øAƒÇe—]ÆÜ¹s=z4þþþÌŸ?ŸîÝ»Ÿ6ZK`OB\^^Î?þÈ‚ ûxüñÇùöÎ;,ŠëkÀïzï]Ø»ÑMµ%éÝ_ŒŸ1Ñ5ÑôÓŒ)‰ÆX’{/ vQ:HgeÛ÷ÇÝ]$V,€xßçÙvÊ;³wfι§õìÙ“•+W²iÓ&¢££Y¼x1666ÄÄÄ V«­çߥKlmmùõ×_‰ŽŽ&$$NG³fÍøõ×_ñ÷÷'--]»vñì³ÏVó¥—Ô_lmméÝ»7K–,¡wïÞ899ñ믿ҦM7nŒÁ` U«V,Z´ˆ€€²³³Ùºu+?ü0öööÄÄÄPYYÉüÁ˜1cؼy3ôîÝ»Vú_QQÁÎ;Ñh4Ìž=»šûK›6m9r$}ûöå—_~¡oß¾¸¸¸ðÛo¿I“&M0 ´iÓ†E‹HNN›7ofìØ±888бcGôz=K—.eܸqlÙ²…ôôtúôéS×?ä ñ÷÷'&&†_~ù…   Y·nC‡ÅÅÅ…víÚ¡R©X²d ?þ8»wïæÔ©SL˜0à’ÏÈÚ ´´”ØØXÚ·ooÍ=`aðàÁDGGÓ©S'~ýõW5jDQQkÖ¬áž{îÁÍͨ¨(lmmY²d O<ñûöíãäÉ“<ÿüóÖó[¶l7n¤S§N,Y²¥R)ë°ÞD´jÕ WWW/^ÌÓO?ͱcLjçᇠ{÷î,Z´ˆuëÖѳgO–.]ŠN§£k×®¨ÕêK>#kƒÔÔTÙ³gGŽ©¶î©§ž¢eË–¸»»³xñb<==IHHàØ±cÖ<Ý»wgÁ‚¬]»–>}ú°téR*++«_]Êb’k§k×®|÷ÝwüóÏ?Ü~ûí¬X±FC÷îÝèß¿?ß~û-±±±øøøð믿ҤIš7oŽÑh¼ä3òFc49tèYYYüý÷߬^½ºÚúY³fѵkW¾ùæþþûo† Š+(..¶&Yëß¿?³g϶Å~ýõWBCC­ž0:uâ·ß~£qãÆ”””ðÏ?ÿpçwÞðóSMŸ>}ú ¿‚’óHKK#88¸š»•ŸŸ¾¾¾ÌŸ?Ÿ¥K—âääĤI“@©TÒªU+²³³™7o7n¤yóæ¼øâ‹888Nee%?üðk×®%44”‰'Þð •••$''[ÿ×jµÖå!îëë‹¿¿? ,à÷ßÇÁÁ—^z‰ÀÀ@”J%‘‘‘œ={Öz~áááÖó³¤ÞÞ¾};¿üò ûöícذaÜ{ï½ÒÂZÑétVïK69…BAóæÍÑh4üøã¬[·Ž&Mš0qâDœQ«ÕDGG³sçN-ZÄÞ½{2d#GŽÄÆÆ;;;"##Y³f .$##ƒñãÇÓ¡C‡Zq ·XŽT*Uµñ­Õjñññ¡C‡DDDP^^Î?þÈÚµkiܸ±õ>´œß®]»X´h±±±ÜqÇ<ðÀÖókÕªk×®eÁ‚¤¥¥1~üx:vì(ÝÞë!åååmÍ(ªV«‰‰‰a÷îÝ,Z´ˆÿý—~ýú1vìXëoܦMkœrr2Ï=÷]ºtA©T^òYäååqæÌìììÎãÍ›7§Y³fDGG³wï^-ZÄ®]»èÝ»7ãÆ³ž_ëÖ­Ù¸q# ,àĉ<ûì³tíÚÕšY6 €… ²dÉììì˜4i’5{¥¤~Q\\ŒN§£sçÎVW`[[[¢¢¢Ø¼y3 ,àèÑ£<óÌ3ôêÕËê6Ìo¿ýÆâÅ‹Q(¼ôÒK„„„ T*/ùŒ¬ ÒÒÒ())Á`0œ7Æ»t邟ŸmÛ¶eÓ¦M,\¸#GŽðä“OÒ§OT*4jԈŋ³xñbL&“&M"44…BQ粘¤fäääàææFtt´5FÓÅÅ…°°0þøã~ûí7***˜8q"ááá( ÂÂÂP*•üðÃüóÏ?1qâDÜÝÝ­ïù‹=#o4–L܃áPQQAFFÆ%Ï/''ww÷Kž_PPU’Ü\“««+~~~ç­ÏÎΦ¨¨ˆÀÀÀó\!/÷Œ¬œ{~¾¾¾ç%”±œ_@@ÀyÊèÍ"‹I.Mnn.øùùg=4¤¥¥¡Óé :¯ÄÙåž‘õk=¿ÌÌLÔj5µr~Ra•H$‰D"‘H$I½Dš§$‰D"‘H$‰DR/‘ «D"‘H$‰D"‘Hê%Ra•H$‰D"‘H$I½D*¬‰D"‘H$‰D"©—H…U"‘H$‰D"‘H$õ©°J$‰D"‘H$‰¤^"V‰D"‘H$‰D"‘ÔK¤Â*‘H$‰D"‘H$’z‰TX%‰D"‘H$‰DR/‘ «D"‘H$‰D"‘Hê%Ra•H$‰D"‘H$I½D*¬‰D"‘H$‰D"©—H…U"‘H$‰D"‘H$õ©°J$‰D"‘H$‰¤^"V‰D"‘H$‰D"‘ÔKÔuÝ  ŠŠŠ0Õ–»¸¸`gg@~~>©©©899LEEÎÎΨÕjL&………¤¦¦¢P(hܸ1...TVVR^^Ž­­-III„……akkË©S§(--%44OOO*++©¨¨@­VsòäIT*Mš4A¥Rqúôi4u[‰äzQ^^NRRaaa899Õuw$’ZA£ÑœœL³fÍppp¸æö,ï€6mÚÔõ©I$‰Dr]‘ k= ''‡qãÆa0ª-Ÿ:u*ýû÷'==W^y…;vàææÆÈ‘#9yò$/½ôÍ›7'99™ &pìØ1 ]»veæÌ™„††²{÷n.\ˆ³³3Ë—/G¡P0räHX¼x1………´nÝš_~ù…}ûö±téRT*«V­B­V3zôhôz=Ë—/§¸¸˜¨¨(–,Y‚½½}]_6I!33“ñãÇ3{ölZ·n]×Ý‘Hj…””^xá¾ýö[ÂÃï¹½¸¸8¦OŸÎ–-[êúÔ$·8†-[¶Ð¦MBBBêº;É #==ýû÷Ó¿ëº; é\ðööæ‹/¾à³Ï>ã³Ï>£sçÎ$$$Lee%“&M¢  €]»vñË/¿°råJÖ¯_Oqq1<ñÄ4jÔˆØØX6lØ@AA&L ´´”ÜÜ\~ûí7<==IJJâý÷ßçí·ßæôéÓlݺ•ßÿÄÄDV¬XAff& , <<œ“'O2uêT¦OŸNii);vì`þüù>|˜þù§®/™¤¡×ëÉËËC¯××uW$’Zãz{­VËÙ³gëú´$²³³y饗سgO]wE"¹¡ìÝ»—^x¼¼¼ºîJƒGZXë6664oÞ£ÑHll,kÖ¬aÆŒDDDPTTÄ–-[X°`~~~øúúòøãóþûïpøðaŽ=ÊO?ý„ƒƒüïÿcôèÑФI†@—.];v,îîî4mÚ”ððp´Z-ŽŽŽ4oÞœ»ï¾»Ú¶ãÆÃÕÕ•-Zиqc´Zm]_2ÉMF~~> Õ„s;;;Z¶liý®ÑhøóÏ?Ùµk-Z´àÞ{ïÅÅÅ…BF£açÎlÛ¶ î¹çP*•œ>}šŠŠ Š‹‹Y½z5 2„¢¢"Ö®]KII #FŒ <<œäädŒF#¹¹¹¬[·ŽÐÐPî¸ãë÷òòrFEãÆQ(u}Ù$79999œ8q¢š÷ŒƒƒƒuÜ›L&JJJøý÷߉‹‹#**Š!C†àää„B¡ ´´”-[¶°k×.š4iÂàÁƒñóóC©T’””„B¡ ¨¨ˆU«Vm=†¥ÝøøxÂÂÂðññ©ëK!i`¤¦¦’’’‚Éd².sqq¡iÓ¦:tˆ²²2Ž;F—.]°µµ%##///,XÀÈ‘#ñôô$99///V®\IAA÷Þ{/¡¡¡,]º”””zôèAïÞ½Ñh4œ>}þøãÊË˹ï¾ûðóócùòåœ>}š>}úУGlllêúÒH‡¢°°°Ú2<==9~ü88p777lllˆ'$$„­[·¢P(¸ë®»ˆ‹‹cÛ¶mèt:zôèA—.]P«Õdgg“““ƒZ­fùòå899q×]w¡R©øçŸÈÊÊbÈ!tìØñ–—I¤ÂZ8zô(Ï=÷cÆŒáá‡F¡PpìØ1”J%¾¾¾( üýýQ«ÅO—’’‚V«å±Ç³¶S^^NYY™U±tuuÅÍÍ­Ú±,1®*•ÊÚ€‡‡‡uÝ…¶U©Tu}™$7!Gå“O>±Æi'%%Q\\̲eˬãkúôéxzzâîîÎÛo¿M\\o¿ý6 …‚_|‘;vЧOâââøüóÏ™;w.=zô`Μ9,[¶Œððp5jÄüùóùñÇqvv&44”„„~ùåV¯^ͧŸ~ÊÖ­[ #((ˆü‘~ø'''BBB8räüñ+W®$00°®/›ä&gÿþý|ûí·V¡>>>…BÁÒ¥KÐétL:???œœœ˜:u*‡æ7ÞÀ`0ðØc‘@¯^½øí·ßøôÓO™?>íÛ·ç£>âĉ”••áëë[Ma={ö,/¾ø"|ðA]_Idýúõ¬X±Âú}ïÞ½4nܘ¹sç²uëVŠŠŠØ¹s'={ö$;;›iӦѨQ#î¾ûnöíÛÇOçyöÙgiÞ¼9M›6åøñãÌ;—ððp)--å³Ï>cñâÅ 8°®/¤1gÎÒÒÒ¬ßÿþûožzê)ž|òIbccÑh4¬_¿žÈÈH ãÆ£M›6¤¥¥1zôh~ÿýw^{í5ºwïŽÉdâÛo¿eÆŒŒ;–¿þú‹·Þz‹V­ZÆ®]»øá‡ðóó#$$„´´4>ÿüsvíÚEDDD]_Š:E*¬õ„üü|Þxã "##yøá‡­J¤­­-&“©Ú,¦Á`°~wrrÂßߟ7ß|³Úú’’«’+‘Ô5]ºtá§Ÿ~Âd2‘ššÊ3Ï<àAƒˆŒŒ$55€-ZðöÛoãààÀܹsY¸p!%%%ÄÆÆ²{÷n¾øâ úöíK^^O?ý4_ý5=zô„—ÂG}D³f͘;w.Ï<ó ›6m¢K—.ìÞ½›gŸ}–“'O V«™={6„……1}útÖ­[GÇŽÙ¶m/¼ð§OŸ– «äšéß¿?]»v 11‘矞;3fÍš‘€Ñh¤S§N¼úê«ØÙÙñÁ°iÓ&´Z-ÿüóÇç믿¦[·n¤¥¥ñÔSOñý÷ß3{ölX¾|9aaaÄÆÆb2™ÈËËcêÔ©”——óÉ'ŸP×—AÒ=z4C‡`çÎ$''óØcÑ´iSžþyÖ¬YÃã?NïÞ½Y¼x1ÙÙÙLœ8‘ûî»www233Q*•Œ3†x€ÂÂB¹ÿþûyë­·Ðh4<øàƒ8p€nݺ¡T*yâ‰'¸ï¾ûÈÌÌ$88˜Gy„É“'“ŸŸÏèÑ£9xð TX%×÷Þ{½^N§ã·ß~ãäÉ“<øàƒDEE1vìXöïßϤI“ !11{{{æÍ›‡¿¿?C‡eÀ€|òÉ'|òÉ'deeY'ðU*S§N¥{÷îlÚ´‰~ýú±hÑ"† Fbb">ø GŽ‘ k]w@"\!§M›†Á`àÝwßÅÃÃú®E‹ØØØpôèQÚ´iƒ^¯çСCTVVÂÝ×h4âããC³fÍøçŸX¼x1Ý»w¯ëS“H¡PÚØØŸŸÏ|@PP¯½öZµì¨Ã† ³Z[ƒƒƒ­3;vìÀÕÕ“ÉÄÆq_,Z´ÈºoëÖ­­ ¦——J¥ÒªÌãàà`}9´oß___ ^^^ØÙÙѹsg5jd$’H®ÜÜÜÈÍÍåwÞ!22’I“&Y³¿ÛÚÚr÷Ýw[³c£×ë­c= €òòr6lØ@DDDµ¤JÝ»w§mÛ¶V7Ȳ²2^xáV¯^Íœ9s¬-‰äzcgg‡éééL›6»îº‹Gyä¢Û7iÒ„þýûãíím]æîîNtt4*• ///ºvíŠ&“‰   ësÛÛÛ›öíÛ£T*­mtëÖ ;;;\\\8¯Ò‚Dr=°<Ÿ—-[ÆìÙ³™={¶u"òb 6Œ&MšB®Ø¹s'óæÍ£C‡L˜0¡Z‚¦&MšXïYî‹{»rl#ÖzÁÞ½{ùî»ï¸óÎ;­30íÚµãàÑGåÝwß%33“’’þúë/ *•ŠvíÚqÛm·1nÜ8î¿ÿ~´Z-?ÿü3>øàu)• ‘\/***x÷Ýw9}ú4?üðÃynêîîîÜ'33“3gÎXã¶A”kjÑ¢…uâÆÁÁ¥òÊrÈYâ%’Ú ¤¤„7ß|­VËŒ3ªeXW*•çÝ &1-ñ¯çŽ{­VKDD„uÜ[â¸-TTTàïïÏ Aƒ˜={6=zôž6’Fff&'N¤uëÖL˜0á’Ûºººâìì\m™J¥ºâŠ666ØÚÚÖõ)KnAL&‡âÍ7ßä±Ç£oß¾—Ýç\­éÓ§3oÞ<~ûí7¾ÿþ{ììì˜0a‚ÕCÁÎÎNÆ^_Ra­óÎ;ÜÓÓµZÍÿþ÷?|||X±bááá<òÈ#ÌŸ?OOOœœœxë­·øæ›oX½z5¶¶¶Œ?žÑ£GcccC›6mxî¹ç¬–+WWW>þøc‚‚‚!è?þøã„……¡V«qtt´ÎüøúúòñÇ[g|œœœxæ™gd?ÉU±lÙ2þüóO¾þúk®h{{{5jDïÞ½™?¾uùéÓ§ÉÌÌ”Œ¤ÞóóÏ?³eË~øá‡+¶xZêmóùçŸ[—'%%QTTd÷ÿxqwwgÚ´iœ:uŠ¡C‡²|ùrž|òɺ¾’Ê|@JJ Ë—/¿lb/…B!' %7%YYY¼ôÒKôéÓ‡'Ÿ|òŠ&Ç-c½¢¢‚¤¤$FÍøñãIJJbþüùLž<ÙšàTreH…µдiSk‚Œÿ¢Õjyå•W¸ï¾ûXºt)F£‘÷ß///ë ÂËË‹W^y…ŠŠ  öööÖ*<<¼Z?''§jDz³³ãž{î±~?7k«‡‡Gµm¬Ù†%’š°nÝ:^ýuÆ¿¿?'Nœ¨æv1 ÀóÏ?ÏüA¯^½(,,äù矧}ûöÖLÖI}Ãd2±bÅ >ùä&Mš„‹‹‹uÜûùù]vÿ»îº‹_|‘U«Vѹsg222xá…4h;v¼à>*• "##™8q"_~ù%ÑÑÑ´oß^* ’ë†^¯çûï¿·&Œ)--µŽíàà`@ŒN'Ë•Inj***˜4i’5¦:;;›ììl”J%M›6Àh4¢×ë«eƒ·`ñ¬éر#'N$00ÐZ²RR3¤ÂZÏQ©Tøûû3eÊ Dnn.7näƒ>°úÕ[¶;÷»DRŸØºu«5 äܹs­Ë'Ožl½]»veÀ€Lœ8‘ððpòóóqpp¸d¼”DR×èõz6oÞÌ™3g¬qOfÍšEhhè%÷ïÛ·/]»veüøñ4mÚ”ììl|}}yà.{lµZ͘1cøý÷ßùæ›o˜={¶ôF\7ÊÊÊX»v-™™™Ìœ9³Úº X=¶>ÿüs\]]뺻ÉU“••ÅæÍ›1™LÕdWWWvìØAHHL›6)S¦œWIÃÍÍ#Fðæ›o²{÷nT*©©©L›6­Z…ÉåQ˜dv‘z%Cð®]»ˆÅÅÅ…=zqÅ1{I]c0.˜4@¥R¡P(0 ÖÿAÌXFë2£ÑHRR±±±øûûÓ·o_”J¥u_ÀúÝh4b0¬1!&“ ƒÁ€R©´&S:w[£Ñh}qX¶=·/ÉÕ`2™¬ãë¿ÔdÜÇÇÇG£FèÞ½û%Çý¹cª2ÊËñ,¹ž\jl«Õj IIIüûï¿ôìÙ“jãÎë Ê<©T*ë³ÚÒ¾e|[¶5™Lèõú n+KïI®'™àBª’ z½žÝ»w“““Cß¾}qss»às=++‹;v`ccCçÎñ÷÷¯öÜþïØ¶ÜGçÊ/·ºÌ/V‰D"‘H$‰D"‘ÔKnmu]"‘H$‰D"‘H$õ©°J$‰D"‘H$‰¤^Ò "~KKK),,¬ënHê!666x{{ßôq-ùùù”••Õu7$õ<<Í«¦¸¸˜_~ùåŠJaܬÄÅÅÑ®]»›¦  €³gÏV+1u=°$sxànêñ‘™™ÉÂ… /›9÷ffÿþýtèС®»qÃHMME¥Rx]Û-//§¸¸˜çŸ¾®OñšÐh4Ì;—æÍ›×uWn:Ž„„„[§Ýh4’˜˜HPPµ®ýõ¢¨¨† V×§yM$$$°uëVüýýëº+7„ÂÂBrrrˆˆˆ¨ë®Ü***HLL¤M›6×];{ö,QQQtïÞýªÛ¸éVV´^½z]÷e}aÿþýøúúZë›54 8pà}ûö½îmoٲ妟Ñ6 8;;3bĈºîÊ ÃÁÁÁƒßôV‹‘žžNjjêu¯«ÓéX±b7{îÇËËËÙ¶m¬ë®Ü »ví¢E‹WT?¼&œ>}š}ûöÕõ)^3&“‰N:]¶TÝÍJff&§N¢[·nuÝ•Bii)»ví¢ÿþ×]‹‹‹£¨¨èšÚh kC'**ªÁZž@Ô©êÑ£G]wCR‡ 8°Añ€€€›Ú*¹v T×]¸¡´hÑ¢AßÃ’KcooOŸ>}êº7 ¥RIçÎoúð"ÉÕãçç‡O]wã†áääDŸ>}êís\*¬7 ½¸°¬/%±µµ­ë.ÜPä—4ô1ÞÐßS’K£P(ôW(ÖÚÞ’[“†þ¯ïc¼á^y‰D"‘H$‰D"‘ÜÔÔú”¨Ñhø }ûöÅ`0ÇüùóÉÉÉ¡]»vÜÿý4iÒ¤®»-¹E©u—à}ûö‘——G`` õãîî@ee%o¾ù&gΜá™gžÁÝÝ™3g’––vã;¶|9<ü0¼ó$&Še¥¥°y3|ò ¬_ù6L&¡ôZ¬kZ-¤¥ÁÎp5àŒFцFÁÐd‚ÊJñ÷BÇ/-µßXQâcQžL&Ðé ¸X,«¨À|ñ!+ ö{«·[Y)¶¯i&ÒÊJøá˜3~ùJJªúP^^ýøZ-lÙ">‚%³oi©8ÿsgºFÑŸ¸8ص«jÑ(¶/(ÿ;:r¶o_tµW“——ÇŽ;ðóó³ŽqÔj5©©©L›6 žzê)’““yçwnúLÆ “ òóÅøªO˜L(/ö<¸$%%qüøñjÏqooo”J%;wîäÓO?¥[·nŒ1‚ 60oÞ¼ zH$õ•½{÷’ŸŸ_mŒ»¹¹¡P(¨¬¬dÆŒ¤§§óÌ3ÏàââÂÌ™3IOO¯ënK$WÌÖ­[1ÕÆ¸““ 2O›6 žzê)Nœ8Á{ï½'eIQ«V­VKzz:#FŒ`ôèÑç­ß²e gÏžå£>¢eË–ÄÄÄ0vìXÖ­[Çã?~ý;t⃃4j~(¾[ؾ](D­[CÓ¦bYV–P”|| , ,µQ³³…²µcLž AAsçŠmZ¶„Ž…¢vô(DEÁå©`Þ^ÿ~xé%JXòÞ{ø-[ƃ¡lÖ žyF(« Š~ªÕðôÓЮ°,öØÙ‰¾FG‹m÷ïʼɄvÊN¤¦âºe \]Eš7‡Ktwq''q-3Ï˗úuB©|öYq-t:8~\¬m«ÕðÛo¢-[Âý÷ƒš“'±{ë-TNN(† «RÔ?ýΜfÍD»ÎÎTcSË3Þ¹¹¹x{{3mÚ´ó’P,^¼Æ››¾¾¾Œ?žýû÷Ó©S§Zíç-…ÑeeàèW“4áàAxã ðö†‰Å3¡®)/Gµj–-C]‹Y¶ ÄÄÄðæ›ož·î÷ß§C‡<ñÄ€p þöÛo¹ë®»hjyŽJ$õ­VKff&#GŽä8oý¦M›ÈÏÏçµ×^£E‹tìØ‘‡zˆ 6ðH-{ôH$WƒF£¡¼¼œÿû¿ÿ»`¹µU«VáîîÎóÏ?««+ÞÞÞL˜0¸¸8bbbêºû’[ZUXKJJ())A¥R‘˜˜HEEþþþÖ™ùãÇãççG£FQ·®}ûöç¹,\3 |÷Ƥ$”¯¾*”© tï׬.à pò$üó8;ÃÛo KââÅB 6+UDFÂûï‹ö-èt°q£°:>ñÄĈ6ÖXËüü¨ DÿÀØ{z¢¶(Æп?üü3¬]+”l…B(¬j5LžÌ‰òr>Ÿ:{{{þ‰Œ¤¼kWî¾ûnŒìÛ³‡ ;v0üž{hƒÊ\O¬ÄË‹‚çžãø™3?~ÃgŸa[^NË;Hµ·'+8˜}O>‰‹«+­ôzÜfhëÖ¸±}{ ±ýã´ÇŽ¡µµÅsölìáB5ç5‚ǃÆÁl]ÇÙž|òüm‡ ÃÔ£¥›6QœœÌ¦5køgùr”ééDÞv·{z©Óaok+”Ü{ï…ÐP¡$×éé鸹¹‘’’‚F£ÁËË ___ìíí9zô(QQQÖYÌÀÀ@BBB8tèPí(¬F£˜t)-Ê—§'TVb<}“·7ªšºmêõbÜ]ˆÒÒK+ˆƒ˜ÀÑéÄvs¯“É„N§C­V_>sß®]ðÑGàë+<),uâ´ZqÌŠ 1U*áa°~=&ooÊ££)ö÷;;Œ“'S˜œÌ¡ß'{ÃFöè¿BÂÝ“³3…66èõz\ ìml0••QáèH©Ñˆ).Û_Å!4»#ÄX5ÄÄÑáÃpûíbL­0ZmÕõstש°PôU­¿V‹1?Ÿœ=©Å ­z½žììlœ9yò$ÅÅÅøúúâïïÑh$>>ž &X·ŠŠB«Õrúôi©°Jn Š‹‹)))A©TZe•€€¼¼¼P*•$$$@HH Jº´k×îúË*É "++ ¥R‰F£áèÑ£(•JquuE¡PXeGGG‚ƒƒ âðáÃRa•Ô µª°QPPÀÂ… ùã?(((ÀÃÃɓ'Ó¡C222°³³³ ó6664jԈݻw_²ÝÒÒR<ˆ§§'öW{jܼ™ú‰ã?ÌHWW.ªÚ\ÈÏ?þvãÇŸ¿­øœ‹««°Àþý·°ˆÆÄT¹È–”{ö,»““I¨¬$!!²²2|}} æÉ'ŸÄÕÕÚ¶ÅЬÿΛGÞ_„GÛ¶œ9s†¸•+ÙµkwÝu£F"++‹‰'’™™Izz:999tèÐY¿þJçS§ˆ‰‰aÿþýÄÅÅ¡R©ðññ¡cÇŽV7mSçÎÁÀðÆiÔ¨•••Ì™3‡WOœà9GGÖ~ñ)û÷ÓA«åŒNG†Ñˆí«¯2zôè ?Ø:v´þk2™ÈHOgçÎhµZ†j}@j4~Z¸´´4233q8xÈÈHÞùøcX·n_~ù%M›6å©§žÂkøpk»ƒÁê¶Ø¾}ûë=”/É™3g8uê“'OÆÖÖ–ììl† Æ3Ͼù¦L¡$ëõBìÑC(\))ðÁâþ …_ õž=B9+)^ÿQ¢M&lß¾-[¶pÿý÷Ó»wïªõ«Wî](t:11Ò´)´iŸ.L``à5µS« «Ñh¤I“& >œvíÚQQQÁgŸ}Ƈ~È×_}Ñý.ç3¯T*±³³»pö2£Q¸šž=‹Ñߟ4;;¾]»–¶m±MI!ùÝwù¿ÿû?ÜÜÜ8yò$ 55•œœŒF#?ü0Í›7¯Qí%£ÑHzz:ÿþû/………èõz«òíàà€££#!11xöéCAn.©©©Ä<ÈÑ£GÉÍÍ¥U«V4oÞœ»ï¾;;;þøã^ýuk➥ÿÍòíÛi×®›·n%##ƒf͚Ѻuk>üðCBBBP©T4jÔˆY³fñþûïÓ½{w^~ùeÜÜܸ÷Þ{ùé§Ÿøõ×_i×®“'OÆÇÇ—ËÖÓsppàÉ'ŸäÛo¿åõ×_§oß¾ü߬Y¸ººZ³&ÆÆÆòÓO?ñÍ7ß`ccƒ““J¥’ôôtŠŠŠðööÆÅÅFCEEíÚµãìÙ³8p€çŸž¼¼<¾üòK"##=z4888àîînfGÅ]wÝÅW_}ÅË/¿Ì‹/¾ˆ££#:ŽòòrΜ9ÃéÓ§‰ŠŠªÍa޽½=ƒ â±ÇÃÖÖ–íÛ·óÙgŸU)sW1ÆU*öööWœ¡¯´´”÷ßßêÒcuMöò‚iÓ 0ìí9sæ ¯¿ó=Ÿ{õ‰,zúizÌœIãÆ/~,ƒAÜWööwïξ7ÞÀ¯ €/ðÐC vvÆöÇaäH«Ë¼æë¯©Ø²¯aìVÔ|GGR† !5+‹“©©¸þð#‡ÅõðaÈ̤ÔÎŽ/FíëKk½ž0“‰m§O³õôiNѱI^:p㎜h׎&_|ANi)KæÎ%ÿÔ)|bbh{êʬ,8@rr2¤§§cooOYY‘j5¥ååèrs±›>ŠÊJòòòpww§û˜1¼Ð­^^^Ö{ÂÞÞôz=…†2å·ßhf0”œÌSãÇÓ¢E ”ÅÅœIJ¢µ¿?íÝÝQÛÙaccƒR©déÒ¥¼{ü8“‹‹ñôôDóÐCœÍË£$7Cr2Å%%ث՘n»Ý°ûË/©T(òóãÑ‘#iÖ¤ ù¥¥ä;Æ©”víÚEff&Æ «µñm2™ðööæ¶ÛncÈ! –-[Æ_|qÑ’Ñh¼l «ÍÅŸã’úÉ$B2«¼Œ®µ^ãÕ`0дiS†NÛ¶m©¨¨à“O>áÃ?ä›o¾¹è~—zŽ[j6äZ¥WKii)eeeh4šóÖ999YkCªT*\\\.úŒ(--åôéÓ8::¢R©°±±¡Âœ'£¼¼Üú 2”””PTTDrr2ÙÙÙ„„„лwoš4ib•»n$F£‘üÔT ™™8%&bôòªÕk®×ëéÔ©=ôMš4!??Ÿ—^z‰o¾ù†Y³f]r¿Kagg''%ÕP«Õ×åÝ^«oððpfÏž]mÙC=ă>HaaáE÷sºŒ{§££#-Z´¸ðC&- ^{   ° €éË—Ó½{wFމ^¯ç³Ï>cÊ”)4iÒ„íÛ·Ó©S':vìHçÎIJJâ7ÞàÁäî»ï¾¨ÒZVVÆéÓ§‰ˆˆ@©T²páBþùç«¥R¡P ×ëINN¶*R™™™899Q^^ŽŸŸ­[·æ¡‡¢U«VÕ-bfžyæ>úè#>üðCºwïÎüÁôéÓiÞ¼ùeAóæÍ™={v5Ë\pp0¯½öÚUÿ–<ûì³<þøã8;;Ÿ·~РAôéÓ‡#GŽ`4ñòò:ï÷ÉÏÏG¯×Ó²eK(++cáÂ…Lœ8¥RɨQ£¸ï¾û.zÝ ...L˜0 60sæLBCC)++C«ÕJvvöËoÜH&MšTíûí·ßÎ_ýž}ûÎK!oárcÜÍÍV­Z]|ƒ’«åP¯×óÕW_q6-ˆ (³µÅö¶Û <\X2Ídff2}útbbbóøã¨µZŒ¿ýÆ‹/¾È‹/¾H÷îÝQ«ÕTTTðÓO?Ñêôi"õzÔ:'ƒ‚ø×ɉ;wÒ¨];ž~øaž7øàƒÈpuå±W^Á®M@dMž™–F®“5º;Æ™3gXµj4kÖŒFQQlݺ•ãÇ3kÖ,*++™5k¹'NM~RhµDët·j…ßÃãâàÏ?Ï‘C‡x÷Ãé:>[¶n¥oÿþ ïуC‡±dåJ mÚ´áž{î¡Q£F8;;ãææF~~>%%%äçç[KSxxxàíí§Åÿ"¨Õjî½÷^ ÇŽãýO?Åßß_¬ôòÂã"”Q£F1mÚ4>ûì3BBBرcvvv(•J|||(**ÂÕÕü›4aÚØ±ð×_ñöW_¡P(¬7þþþDEEáééY«‚‹‹ ~øaµecÇŽeÞ¼y$''_ôz]N "<<¼ÖÎCr}Ðét:tˆÔ3gPþñM&ì§Nž×aò¡uëÖ—õ@¹Þ4oÞœ/¾ø¢Ú²±cÇòÐCQTTtÑý.÷·¸UÞêèt:vïÞÍþýû9uêYYY8;;cccƒ««+åååäååa0ðòòÂÁÁììlJJJhܸ1­Zµ¢cÇŽ´lÙÒêUWXXÈG}DBBAAAacÓðõõ¥  Àú¿««+999øûûF›6m8tèï½÷J¥’–-[Z•dŠrDD}úô±N8‘‘‘EÙÓÓó¼‡ŠŠ ëØõ÷÷¯–)}ýúõü9s&ƒÎžE_Qñ¡‡jõ7èÓ§}úô±~wuueĈÌ;NwÑý.$ŸZP«Õ„‡‡ËŒðÁÙ³ð÷ßx»ºqÉgç•P« knn.¹¹¹DFFZ—999áàà€Éd",,Œ“'ORXXˆ»»;•••$&&^[Éoox÷]'nü½½;v¬õ¡óÚk¯ñÓO?¡T*Y´höööVá¯K—.ôêÕ‹wÞy‡={ö0`ÀºvíZMð*((`òäÉäää T*qrr"88˜·ß~›F§lYêj4Μ9Cpp°õA})ÅÓÞÞž—_~™O?ý”yóæñùçŸ|Å3WêFZlmm/9[looOttôEן›à ñ |ôÑGéÔ©~~~øúú^‘eÛÎÎŽ;¾}ûVÛ^¥R±uëÖ+r¿^èt:Nœ8Q-ûµ îîî˜L&ÂÃÃÉÎΦ²²[[[rssÉÎΦÅb¨¯„´4X´’“á7¨ôòbåÊ•œNNfƻ{7K§McøÚµ¸}þ¹ˆNœ8Á´iÓèß¿??ü°óööŒ}üqºöéCÙ /p0;…—ß«Õ4î×}d$ñ§N¡ËÉ!ÝÖž{î9bbb¬>ø€O>ù„Gß}—°°0<<<ؼy3Ï>û,111lÚ´‰ßÿfÍšE`` uì2„o¿ý–gŸ}–ÊÊJbbbxíµ×prrB¯×£”&Í,qœ¾¾´êߟ—ýüøúë¯y饗èС*•ŠÖ­[3räH@¼Hÿ{¯øùùáççwM¿÷}÷Ýǽ÷Þ{Åööö̘1ƒ?þƒÁÀË/¿LhhèkÜ[×ñþûïçöÛo§°°___lllP«Õ V¬XQ#k¥´´”S§Nn½·ìííE¸¢¼Mjj*]»vDFaµZ¯¯o­õQr”•‰dwþþ"‰Ý–-ðÓO0fŒépwÇd0ºcþôJ Q«V¸tïÎô9s¸Ô(ÚíÙƒV¯G¿s'Îee¢Ý0´e eŸ|B£V­pk×õÏÅ‹aýz*=<˜}êgBBP¤¤¦T¸qµvú999äååUóŠqvv¶Ê*M›6åÌ™3áææ†V«åĉuZž,55•””<<<ðòò"  Nú¡ÓéX¿~=K—.ÅÕÕ•°°0š5k†»»;ÄÇdzqãF‰‰‰¡_¿~„„„Xs(•JkÛs1˜L&’““9räß|ó eeeôêÕ‹–-[2gÎzõêÅäÉ“±±±±îo©káÜïçÖíÕ«eee$''SRRBjj*eæq«P(ؼy3?ÿü35¢´´”ŒŒ ÂÃÃqttÄd2‘`õ¤Ójµ¤&&Bi)FLh4zõêÅÀÙ¾y3ûãâxíûï àLZŽ©µßÈh4’šš @¨y[¡PàîîŽ &“‰ˆˆ²²²ÐétØØØ““Cnn.-ù$’K¡×믊p«‡†kTV¡–ÖÇóÁðóÏ?[-ûöíÃÅÅWWWÚµkÇÂ… III¡mÛ¶”——³ÿ~ž¼P2žËa2‰ƒ„‡c2™Ø´i={ö¬¦d©Õê‹f V*•4nܘ>ø€uëÖñ믿òûï¿óôÓO‰N§ã«¯¾"00Ï>û “ÉDiii5Âÿbq rww·*4Wüc©Õ<õÔSŒ3??¿é:§R©hÛ¶m÷³Xž.Ô^mb2™xóÍ7ø …‚ŒŒ Nœ8Á¨Q£hÖ¬¿üò %%%xzz’ššJjjê³ô] Šq>e ptÿ~ÖΙÃôŽñquÅíöÛùaË–7o΃AA( öíÛÇ{ï½Ç¸qã4hPµk¤T*‰ˆˆ@óý÷Û¸‘ÃGòôðá´9'îøRxyy1cÆ RRRHNNæøñã|úé§VAnøðá ?'Öø\xúé§™;w.<ðÀÖ¾]Ê%ÐbAýøã«MNXîµIMEË8}õÕWk¼Ÿ‡‡Çy3×uQ*¦¨¨ˆ‰'2kÖ,ë„T||<åååÓ¡CvîÜÉðáÃQ(8pGGÇ:µžžëÙP[ÏM“Édý( ëçJ÷³ôµ&ý½è1ƪò_J¥ø”—‹€ „„`ЉñÔ[·bš3\]Q<ý4 ÀÔ¾=¦²2Œ+WbrqöíÙ»mÚqãk4Òá±ÇP=ó 8:²·C¾˜1ƒf|À©“'iŸœL°RÉêC‡èñÿG¶½=vìà…AƒØ˜È?Ó§Óª°±cÆàÔ·/ÚfÍøá›oPµhÁä瞣´¨ˆ-›7×ÊofáСC|òÉ'Ì›7Ï*«ìÝ»WWW\\\hß¾=‹-"%%…¨¨(4 qqq<ûì³µÚO“ÉDQQK—.寿þ¢Y³fTTT••…¯¯/]ºtáöÛo'##ƒ7’@TT÷Üs~~~lÚ´‰={öPYYIdd$]»v% À:yfK™™™œ8q‚ÜÜ\:vìHÓ¦M­Ï¾sÇœN§cÞ¼ylܸ‘§Ÿ~NŸ>ÍÑ£G9{ö¬5<ê‰'ž mÛ¶Wåݶm[Ú¶mËÈ‘#9qâüñk×®µ¾s/Ú¦ÉTu(Usˆ‹²¼g;;Btî¶J%F“‰SIIœHHÀ«²’¦:à&&w’“©<}š”]»HêÒ'''yx²f j• ãØ±¤¶iÃüÁÔÉ“–ÍÛŸ}†¿ù™¨vp@Q‹“Žýõ ¼ýöÛ8;;£×ëÙµk5ÂÖÖ–˜˜/^Lii)îîîœ9s†ŒŒ ©°6D**¬y3ð÷I!A”Ä,/†Ë{£¬LTPÉÍ!_wÜ!¶=zT¬¯ª2t(tï.ZÆÅ]s7kUaŠŠ¢uëÖ<úè£tîÜ™¢¢"<ȳÏ>‹»»;^^^téÒ…3f0hÐ bcciܸ1½zõªùÁΞ5@_z  k²ƒ7Þx£ÆM¹ºº2lØ0†ÊÎ;yûí·iܸ1vvv0kÖ,«›Äå\‚®\®4)ޤֱµµeøðáÌž=›ãÇãêêÊŽ; eðàÁTTT°víZ¦NJ»víX³f ýúõ»zaþå—«}ÝóÉ'¼ššJàË/ƒ½=¶À /¼À¤I“رgjµš‚‚^}õÕKZu‰3†«É¨R©hÚ´)M›6eÀ€5Ú×ÞÞžçÿ›Ô¬ûJn<ÞÞÞ 4ˆ×^{=z`0صk—5ÞÏÙÙ™×^{×^{ Ö¯_Ïc=Vå2]²dÉš5kFtt´Õ|£ÈÏÏ'>>žuëÖQXXˆJ¥Â××—Ю]» zÞdeeOü‘#;† @X-Z¶´z€È`»sçNòóóñððÀÇLJÒÒR²²²HJLÄÃ`@sæ -ƒƒ >œðÖ­Qýù'üú«Ðï¹x“NGÑÑ£§¦’‘‘ÁñÉ.*¹¸³3¹..´?vŒ–f¥hËž=œ*.&oæL***ðõõeæ¶m4vuíšßÑ:ñõðË/¿pßС´lÙ£ÑHdr2 ,ÀÓɉo~þÙ:Áا¬Œ÷Þ{&Làµ×^cß™3P«ùhʜɷ·Çönˆ7‚¶mÛÒ¢E {ì1:wîLAA‡æ¹çžÃÍͶmÛÒ©S'f̘Áí·ßÎîÝ» £G-——Ú½{7~ø!]ºtáÇ´N‚F<È–-[xöÙgñðð oß¾ôêÕ‹ÄÄD¦NJqq1­[·¦[·nØÙÙqðàAÞ{ï=233qqq±Æ"æääàììLãÆñööæ•W^¡E‹ <˜‚‚ÈËËC£ÑPVVF£Føá‡¬²ÐUOÆ^"##«yìUÃdV;;a¸8qBTmððÆŒI1¿ûÖ¬•þïÿ }{QæïãEû  xå”&M÷ì¡éÊ•VC ޱ`¶ŽŽDÄÄ1x°XÞ»7¼ò J xqÐ ^ÿá*õzZùûã¹oA ©¾¾èo¿@wwBV¬À­°|>4ˆèØ‘±wÞ‰§ÑˆÚɉƒE+WräÈ45Ù^‹-·*ó%%%ûL(w]»ÂèÑÂJº~½pO´µ…èh1Þ‹‹…5§°P”|öY¡¼fe‰u–ZãõœºRX¯7Ra½0:Ž}ûö±zõjŽ;fMöA`` ¨T*ª¼4õz*32øuÓ&6nÚ„‹‹ ÑQQÜ£Ñà—‡ÎÝœÉ.-Åm×.lÖ¬!aÿ~N¶oÏ>??üÝÜèïà€³J…Z«å׊ ÒrsI/??œúõ^#Kvv6éééÄÇÇ“ŸŸN§C¯×£Õjqss£M›6xyyY'´¼½½qww¯6Q\\Lyy9)))lÛ¶1cÆ0xð`‰‹‹£¨¨¨Z¢¯šR»¹âk“±c­YS-îR²ö™¤Áðï¿Ð¹³u¦w÷îÝ888Ȃޒ[‹U`Ë–-3eÊk-fKÐiÓ¦±sçNfÏžMii)öööFBCCiݺ5#FŒ ooïj±ñeeeäååqæÌ,XÀâÅ‹ñññáøñãŒ5Šž={ åÏ? ×ÂÖ­ÅŽz=ÄÆÒþŸ˜üÜs|ùÃ:91ô—_hS=ÌÜÍ‚B¡À»KômÛâ™›‹­%™N·nâs \]]yä‘G9r$”––âëë{Ù,ØuB¡“mÿA¯×“““ˆp£¼¼<æÎ‹J¥âí·ß¾¹dšÄDñÞ²³ƒ!C„•ó¯¿à·ßDÌœ¯¯PX}|àé§…âéî^eͼí¶óÛtu…Ù³…õÔÁ¡Ê¥Ñß_|$’ZÆâo0Ðh4lÙ²…;v V«¹ó¶ÛxÌ×ÿà`l""ªâ=O‚ƒaåJèÒE<×KK±ýæÆh4Ü=d‰¡¡Û»—¿W¬`Ca!6¾¾¸edP^YI„^}û9e m7末y]t¨¬äôéÓüý÷ß|êÇ'OÄs%((“É„¿¿?={ö$88GGG\\\Ðét¤¥¥±ÿ~òòòpvvF­V£Óé8zôèyž^^^„……q÷ÝwÓ¬Y³ëêÎÜpÖsfŽÿý÷_ÂÃÃe–JIÃA¯Ù:Íüøã<óÌ3µ^¯P"©KJKK«e+ÏÍÍåõ×_§iÓ¦|zn©¡ÿ`ooO¿~ýèÚµ+™™™4nÜøŠ\äEí:vìÈ–-[HMMeüøñÕ“èéõðæ›"Z«V°|9,[O=Eç=hÞ¡nnn5z™«P7jtU×ÉÉÉé†çW\öïßÏ[o½…¶¶¶¤§§sûí·óÔSOÝð„rWÁII°o4i: ¡ü»ï„i.w èôéVårëäTCw%ØØˆDR‡ddd°~ýzbccÑëõØÙÙQQ^NLh(  Íˆ8ϵk…;îš5ÂCÎÑQxäæ —vK˜…»;LŸŽrÛ6Ü·m£ÓˆtêÔ ž}–¯¢¶¶¶„‡‡3a„ïëããcô­K¦t›’"~¡¡ìÚµ‹ùóç3eʳ'i8<ù¤˜Q6mÚ„¯¯¯x˜I$·<÷Üsxxx0iÒ$\]]yï½÷èС?þøe뾂ÈL}µ¥Hìíí«âq ‘èO¯BùC ëjF†Ð[·†ž=EÜÔ8C¼äÖ###ƒ/¿ü’ÿýï´k×ŽŠŠ @Ôó¬7ʪ^/bHwî„„•ôÐ!øðC‘ ÅݽJ6M¼³Îµ½A ™$’ëÑh¤  ÀZê(((rss9räǧ¨¨{{{r³³‰ ã™±cñnÜuF¶ ârø°ð¡ŒZ§m‰õîÐáÂI¸lm¡¸7Ú†DÃTX׬öçå1sæLž|òI‘ª\"i(˜gáJJJX¸p!>úèU•HnF4 o¿ý6íÛ·'00—_~ÙšLìᇾ"eõº‘ß~+ÖAƒàÁ…P~®{þÅ2™J$@£ÑðÎ;ïЯ_¿gZ¿!°w¯ðhÖLÝîîð矢ÃàÁUC[¶ÙBÿkÑ¿N º$’Á` !!]»v±yóf¼¼¼puu¥¸¸˜²²2Ôj5QQQ 4{{{ ÜvîÄuÏ1yéç'”ÑÞÿMV¤TZ WD-—g¬¯4<…U«…¸8öõêÅ[o¾É'Ÿ|ró'%H,èõ">®W/hÚ”øøxÔjõUÕ®•HnF ßÿ=z½ž^xµZM=ذa#G޼þ®¯z½BììªþW«ERaQ}òI†R!D"¹óæÍÃÍÍ‘#GÖmGJJ„•ÇÆFͽzÁáÞ.ÖÈH‘ ©I“*Kª,/&¹‰(**"--¤¤$ÈÈÈ ==ÚµkÇÌ™3 @­VSYXˆaÃÔ[·b·{7ŠGï…-[ÄÍÛo[½hpsÉÁ$׆§° þ¬,Hxxx­Š—Hn8••¢sÏž¬Y³†^½zYëK$ ýû÷[³íZ¼ BCCyôÑG¯ï*+ោ顇„°~ú´pmôô‰bžzJîÒÅWrHKKcãÆ|ôÑGÕ~Õ:gÏÂ[o‰É˜V­ªr& TµMMbM%’:"..oooBBB¬Ëöïßφ ؽ{·µ¬W µš»ÚµÃ÷õ×ñ./IÁŽ“nn8¨Tâ½0|8DDeDÍÝÞ½ëú4< Oaut„Ç£ü³Ïhy3TI$uNq±øøú’˜˜HRRÿ÷ÿ'ǹ䖠¤¤„o¿ý–^x   š7PVóæ‰ØÒ¨(¸ûî*¡ã¿¬X!fΧO‡à`±,, fÎõ ®Z’ëŠÑh䯿þ¢oß¾„††Ö]GNž„©SEü\«Vu}Y$’£ÕjY³f Ë–-D[;;;\]]ÉÎÎÆÝÝðÄOˆœÿ _|,’••‰çý¿ÿ† â=àîcÆÔõ©Ý²4<…µ² Ξ=k-€.‘4\\`ÊLÎάZµŠþýûKëªä–áèÑ£ """j¶£ÑXåÊ%¬£yyb9Ô`‚z—.½wÐ Q~ãÜûK¡egþSzF"¹”––²mÛ6^}õÕÚ=°N'j{ÛÙ 7F‘áZÆ^Kn"L&•••$$$ðÃ? V«y衇èÒ¥ “‰¤ädÎfgìäDhëÖØ8:ŠgºV+JÊœ;æáöÛÅG«½øÄ¦¤Öhx ëÏ?C³fÈ4þ’†‡9å¿®²’äädî¸ãŽºî‘DRküòË/ >¼æ“4±± ÷ÜÝ»Ÿ¿>- –. e,ëÿ›(C"¹Á¬_¿ž°°0ÂÃÃkï ¥¥Â²tø°°"py¯‡µz%’ a2™HKK#66–íÛ·SYYÉ#ÁK/‰»v…#„\õí·?€TVë Oa=v ¢£)))ÁÃã®{#‘Üt:*•Jf–Ü28p€ŠŠ úöí[³õz¡Œrñm ¥dÂIQXXÈÊ•+™>}ú/[SR"þº¸€F#2ø~ð\›½DR‹hµZÒÓÓùûï¿9sæ …£ÑHZZ‘‘‘ 6ŒvíÚáìì,‚á¾ûD ‹0/‘ÔcNœ8Á÷ßONNÑÑÑ 0[[[hÒ¤ÉùøƒPLß~[„€pöô”5€oB–Âêà~HªÙXÆöI*z½ þ—Hn yyydggÓûj21À»ïÊ™tI½æÐ¡CtíÚõú5xâ,Z‡Á½÷Šd1))â^:Tf5•ÜT$''óÆo0bÄúô郇‡ÇÅ“Mêõb¢ÆÉ ~Xä.Üô(ëòà¬[·®Ú2ƒÁ@||<+W®dïÞ½ètº+oP­??222ê6ÞDbÆh4²nÝ:²²²¬Ët:»víâÏ?ÿ$11ƒÁPãvõz=666Ò%XRçóçŸZ'Q4 ëׯgÍš5¤¥¥a2™®éÉÉÉøøø\™×ŒÅÝÑ‚­-øøÔõe’ÜĤ§§³~ýújË ÇŽ»:Yåœ>}úúÆ®ªÕ«`ölaIðõ ëwa^"1Olllµe:Ž;wòçŸrâĉ«’U®YYYÌš5‹ûî»»ï¾OOÏ‹+«ùù0g|÷HÂjcSU#XrSSgÓ†>ø€ääd `]þí·ß²jÕ*üýýÉÏϧC‡¼ð ¸Ô FNNÎÕ•ÍÌ™3)..ÆÁÁüü|&MšD¯^½®ú8 C‡¨/5S®×‹ºy«W‹Ò……š ¹¹pçu}©$7)%%%|ðÁœ9s†Ûn»Íºü믿fõêÕøûû“——Gtt4/¼ð‚ˆ«!•••¤¥¥xmÍχmÛ`ð`hÒD|ÎÅѱzÖk‰HIIaÚ´iDFFÒ©S'ŠŠŠxï½÷ˆÇËË‹9sæ0tèPyä‘ZéSyy9ÉÉÉœ:uŠß~ûîÝ»3lØ0‘DÉÂÙ³B1 †±c¡¨&O5ƒzHzÕ40ê̺fÍÖ­[WmVòÔ©S,Y²„Ñ£GóÕW_ñú믳jÕ*öíÛW£¶eII} 55•/¿ü­Vkµ0íÚµ‹íÛ·óꫯòÕW_1räH~úé'²³³kÔvqq1ÞÞÞ2†UR§ÄÅÅñ믿RYY ˆIš?þøƒ³gÏòñÇóÅ_бcG~üñGŠŠŠ®ú8ÇŽ£ÕåêAnÝ sçÂO¡<%&N1LÉU²zõjÖ¯_ž¬òûï¿3f̾úê+^}õUþþûoâââ®ê'NœÀÃÃãÚònÀ´i"Fõ=$·?üðGŽ©fAݵk;vìà7Þ૯¾bøðáW%«\ ååå|øá‡|òÉ'ÄÅÅñè£2nܸêÊjv6¼úªH¬4p Xæà –=ù$xyIËj£ÖV“ÉDll,¿ÿþ;wþgÖ{ïÞ½X©###éÖ­›6mªÑ1Nžgtè ¾wí ß|£FÕõ¥’Ü„˜L&þý÷_–/_ÎàÁƒ«­‹%((ˆÛn» [[[Z·nM—.]j,«Xرcýúõ»´ÁåXµ ÂÃá…¤eIrE –-[Fvvöy‚Û·o§GDFFbkkËÀñóóc×®]7¼_ß~û-ÅÅÅ|óÍ7¼öÚkôíۇ깸À¤IðÊ+"qˆqߤIU‚1Iƒ¢Ö¥]­VË?þÈí·ß~^¼FRRÎÎÎÖr4666„……]VÐ1™Lèt:kÑàüü|5jTÛ§&©G˜L&ôz}µ¸ºÚÂh4²fÍ4 #Gެ¶.11‘ÀÀ@«+¯§§'ÞÞÞ$^Æ d4­c„ïïï_ëç&©?Xž{uWd0X¼x1M›6¥û9uMF#IIIÕ26nÜ­VKffæeÛ}¬1gÏžÅÍÍ­ÖÎKRÿ°³³£gÏž4kÖìâo©©©ÌŸ?ŸáÇãääDYY ⪵Zí÷Q(—ã-[¶¤K—.Õâ”t:‰‰‰Ž_U*…Kp òIn>,aµÉöíÛÙ¸q#=ô&“éºÈ* …‚Ö­[ŸçÚžžž^so™ÌLxí5¡´Zâ÷$7%...ÜvÛm5J,z­èt:/^ŒV«åŽ;î ´´½^Oee%%%%—œ½Ô·±±¡K—.\…W‹Å£aôèÑž 4™àï¿ÅsÔ(ñWrSШQ#ºuëvÍek,É Ž9¶mÛèÝ»7mÚ´A§Ó1wî\V¯^^¯'**Š'Ÿ|ò¼A÷÷ßSVVƬY³áÖ˜››Ë³Ï>ˤI“pvv¶º…ÙØØ`0(**ºìËJ¥Ráää„R©D«ÕâààP=8[rË¡P(ppp8?îásèÐ!Ž=JAAû÷ï·>ø?ûì3Ž=Š­­­UøQ*•”——S^^~áô9¨Õêj^YYYWõR4”J%NNNØÚÚ֪ºe˲³³Y°`‹-²NÊL˜0{ï½ggçj“–EEEØÚÚâîî~ÉvíììΫ­Óé(((8ÏS®`!!µvÞ’ºÁÙÙ¹Ö' -²ÊÌ™3ÈÌÌ$//gŸ}–É“'ãììLNNNe;;;ìíí«-;|øðeŸÿçááS§Šì¨’›šså×Ú¢°°Õ«W£ÑhxõÕW‘øËÆÆ†É“'3}út\\\ΓU***ˆˆˆ¸h» …GGÇ+&z½ž¹sçâééÉ}÷Ýwák¡×ƒ››ˆÑ–“”7¶¶¶8::^s鯿¶mÛÆŒ3ððð }ûölܸ‘ï¿ÿžîÝ»ÂöíÛ™>}:~ø!>çÔ¿5jTµÂï›7of÷îÝŒ5ŠÀÀ@ÚµkÇÎ;IOO·Æ=:tèòÙ!Ï¡¢¢GGGia•Ô ááá¼þúëÖYx½^Ͼ}ûèׯ=zô@¯×“@YYÎÎÎdff’žžÎðáïø:Ž’’’ ñÉ ¦gÏžÕÜÑOž<ÉñãÇ9r$-[¶¤C‡ÄÅÅѯ_?Ž=ŠÍU%Â+..¦¢¢ooïê+ŒFQ¾¦woYORrÝyðÁ­ã„Œ³oß>FE@@íÛ·'66–ÌÌL5jDEE‡¦]»v5>ÖÉ“'ÏK@yAŒF‘ »Y3¡¨JeUr•¸¸¸ð¿ÿý¯š û?þˆ““C‡ÅÙÙ™˜˜âãã­2uFF™™™<ðÀ×½?‡âßÿåÝwß½°ìn4ŠØléMpKS#­®  €9sæÐ©S'^zé%¼½½Ñh4¬ZµŠV­Zñúë¯ãííÍÀyþùç9qâD5…µ}ûöV%„•èèÑ£ 2€èèht:+V¬`̘1ìÞ½›¤¤$^xá…+î£Å=MZX%u·ß~»õ{ee%“'O¦sçÎtèÐ¥RÉßÿͶmÛˆŽŽfùòåTVVVK\s9rss12N[R'4iÒ¤šE(66–/¿ü’AƒaooOÿþýùå—_0`nnn,^¼˜fÍš]rfþbìÝ»—ðððóÇzQüðôí[×—CÒé`É4m&==ÄÄD«¬Ò©S'>ûì3V¬XÁèÑ£Ù¹s'ÉÉÉLš4©ÆÇ:uê!Wâ)°?|þ9|òI]_ÉM޽½=ݺu«¶lÕªUxzz2`ÀzõêÅ_ýŶmÛèСË–-Ã`0еk×ëÚ—ÂÂB¾üòKF}a…òrX¾\ÔV½Šwˆ¤áP#…õôéÓ”””0bÄëŒwNN‰‰‰<ðÀÖY÷ÆÂÞ½{Ï»)Î% €¨¨(ëwwww¦NÊœ9sغu+öööL˜0áÂå .BFFÒÂ*©( :wîl­ ܪU+ž{î9æÏŸÏwß}‡··7Ó¦M«‘ërQQAAAu}j ®®®tîÜ¥R‰B¡àî»ï&''‡7ß|“ÉDpp0/¾øbµDLWJ\\Ü…³§fg ·0™dFR Ò¦Mëw‹¬òÝwß±yóf˜8qb'e  …âò1º%%ðã"ጬ€ ¹DDDT‹£ŠŠâ™gžáÇäÛo¿ÅÇLJ×_ýº†Y™L&6nÜHPP<ßxáBX¹¼½¡gϺ¾D’:¦FZ]II ƒ¡šÕôôéÓ¤¥¥Ñ¹sgk•B¡@¡P\6;ëàÁƒÏ«oÖµkW"""HOOÇ××·ÆÉ ñññ©Õ˜.‰äbØØØ0þüj߇JLL 4nÜØªÌ^)5ÞG"¹Q´hÑ¢Úwttä¹çžcðàÁèt:7n|ÕBNbb">úèù+œœàÞ{eâ I­pçwžç¶Û½{wš7oNFF~~~W¢‘™™‰R©¼pɦs±³ƒ „;°”m$7€ÿz2ÚØØ0|øp:uêDaa!Mš4¹î‰¡*++Ù´i÷ß•‘éäIÐh * †…ûï—¥š$@ VwwwlllÈËË#44 8|}} ³ng0(--½j—EK½§«!55õ‚)º%’úDHHÈ•¹]€‚‚é,©×¨TªójWÖ”ÒÒRÊÊÊ.ìM ÒË@RÇx{{Ÿ_]®$Q%%b‚æ?uë%’Ú Q£F4ºAVýøøx4M•§åÎðÁ`q­¯å¤™’úM4èae€IDAT¦§CBBpqqañâÅäååqüøq¶lÙBÇŽQ©TÖ¢ÁÛ¶m###ƒÎ;×ú ^6¥Dr3£Ñhj^A"¹É())ÁÙÙùÂÞ2ïim’ÜÄddd\Ú[¦¨Þ}W(­IÂh4òûï¿s÷ÝwWÝK—ÂØ±pãd% ƒ)¬îîîŒ?ž={öЭ[7î¾ûnìíí=z4*•ŠÃ‡ó¿ÿý7ß|“1cÆÐ¼yóZ?¡ÒÒR)ÌK4ÙÙÙÒÂ*ið”””àt± À/¿ ÉÉuÝE‰äš(++»´¼’’ÅÅ2V[Òà8xð IIIÕÃ_îºK†zH.H㣣ùæ›oˆ‹‹Ãh4Ò®];š6m ë¦J¥bÊ”) 8ð¼zc7ƒÁ@nn.µz\‰¤¶Ðëõ¤§§S×]‘Hn(¥¥¥¸¹¹¿B£ÔT¸Ê°‰¤¾““séddÇŽ‰X¾ËŸJ$7[¶l¡_¿~büUuV¥×Œä"ÔXaU©TøøøÐ¸qc Q*•ÖÌ^½zõ¢W¯^uv2yyy4mÚOOÏ:ëƒDr#1€Hl#‘4d4 &“éüii rbRr“SZZJëÖ­/¾Á°a ÕJ‹“¤ÁqðàA¦L™"¾ÄÇÃÞ½ðàƒ2Á’ä¢Ôxd$%%1}útÒÓÓ1™L¨T*î¿ÿ~}ôÑ:/%ãééÉäÉ“ë´ÉÄ`0PTTtU%B$’›‰ŠŠ |}}Ï_ 5¨Í-‘ÔWRSSéҥ˅W`c#Ý% ޤ¤$ ƒH<©×ÃüùÐ¥ ¨TuÝ5I=¦FÓvz½ž9s曛˓O>É믿NTTß|ó IIIu}.¨Õji]•4h &“IZX% ž‚‚‚ªº|F#ÄÅÁÑ£`oò9/¹É1”——_8[¼Á êO¦¤Ôu7%’ëÎßÿÍ€D¹³' ' ’îÀ’KR#…5??Ÿ“'O2vìXî¿ÿ~ú÷ïÏøñã âðáÃu}.IƒÇh4b4k=>\"©m4MU¹´„˜9S(®I ´´”üüü '+*‚åË¥/ip±}ûv  „…ÁÇË6’ËR#…Õh4bccChh¨uæÛÃÃooo²²²êú\$’Á` ¬¬LÌLJ$ ˜ÔÔTlllÄ—Ÿ†ááU«ºî–Dr]Ðëõx{{£ºdZšH´äãS×Ý”H®+iii8;;WeǶ³“ù$WÄ5*Š*·-‰DrC)++#88X–µ‘4xÔj5^–LÀ&ˆ¬Àò]#i ”––RVVvá:ÃAAbÌËÐI#66–¶mÛŠ/ lßýûËdK’ËrUo“ÉduM´dq¹¹¹´nݚѣGQ×Ý–H®˜ôôt-ZÄÎ;±³³£mÛ¶Œ7Ž€€***X»v-‹/Æh4͸q㪄”+%;Ï–-AzéHê€øøxæÏŸO||<îîîôíÛ—ûî»777@È2 , >>žÆŒC‡®XV)))¡´´´*Èí·C£Fu}Ú’[ˆõë×ó×_‘œœŒ¿¿?Æ £OŸ>ØÛÛ£×ë‰eþüùœ={–6mÚ0zôhÂÃïúx{÷î¥[·nU  ªëK ¹‰¸ªV£ÑH~~>;wîdöìÙL›6>úˆeË–‘‘‘N§»à~999|ôÑG”––òòË/3lØ0þøãþøã«EjÆŒñÊ+¯Ð¸qcfÍšEЬE&¹‰X±bóæÍãþûïgêÔ©”””0sæLJJJHIIaÆŒ„‡‡3yòdòòò˜5k•••uÝm‰äЍ¨¨àÛo¿%66–矞'žx‚ÇóÕW_QQQÁ–-[øòË/]»v ¼¼œ9sæššÊòåËéÔ©£G ²²’¯¿þšaÆѬY³+:Fvv6®¾¾8_áöÉõääÉ“$&&²råJ«¬’˜˜ÈöíÛ>|8±±±h4ž{î9"""hÑ¢»víbÓ¦M4iÒ䊎qêÔ)œ…‹åáÃФ Èìï’ZbçÎxyy1iÒ$œœœhÕª›6mbÛ¶mtïÞ5kÖàããÃc=†‹‹ ŽŽŽL˜0Ðé*Üx qppu‡÷íƒO?…Y³¤W䊩±ÂzôèQ^{í57nÌœ9sˆˆˆÀÖÖÖju7oóçÏÇ`0ððÃcgggÝ7,,ŒY³fY_•••”••áää„R©$!!___™°íÛ·'..®®¯“DrÅ<÷Üs4nÜ¥R‰Éd¢´´…B££#GŽ¡M›6ÖbñAAA„„„pðàA©°Jn œ™1cmÚ´D=ÉÒÒRìììP«Õ;vŒÉ“'[·ŠŠB«Õrúôé+VXsss‰ª¨€¢"0»`J$µE³f͘9sæEe•øøx¬I%hÛ¶me///È˃wß —$’Z¢GDEEYe‘ŠŠ *++qqqàÈ‘#DEEYk¾ÄÁƒ¯Ja-**ÂÞÞ›S§àÃaêTî!©5RXµZ-ß}÷Ìœ9“ÀÀÀjë===yõÕW `áÂ…ÜqÇVåÀÇLJ¾}ûRVVÆúõëÙ±cIIILš4 GGG²³³±³³ÃÑ\{ÌÆÆ†   vîÜyÉ~åçç³zõjFŒa½Ù$·6z½žÝ»w³sçNúõëW«ÇîÞ½;‡fíÚµÖ¸ÈÈH222hÓ¦ÕûÀÍÍ ww÷˺’¥§§óçŸÒ«W/k •äÖ¦¬¬Œ 6pôèQ«¥³6°··§_¿~èt:¶mÛÆ† ˆ‹‹³Æ°feeY}€ÀÀ@t:gÏž½d»°æ5ÈÈÈ`xn®æåx¿¥Y±biiiµzL___|}})++cݺuìܹ““'OòÒK/áàà@VVÖe•½{÷^´M“ÉÄþýû‰ˆˆ ::šÔÔTQÞãäIpu³â ¹µ(,,dåÊ•Vű¶°L²dÉŽ=Š C†  ##ƒŽ;ZewwwÜÜÜ.)«TVV²qãFüüühܸqµu™™™øûûcëå%”U󄧤ᓔ”Äúõë«êï^%5Ša=}ú4§OŸæÁ$à"™ììíí1bvvvìÞ½û‚ÛFŠŠŠÐjµ”––’––vÉø¦ËÅ>¹»»Ó§OŸZ¿á%õ•JEtt4;vÄÆÆ¦Nú Ñh(//§´´”¬¬,ŠŠŠ.ºí寏¿¿?ýû÷—2+öööôîÝ›ˆˆˆªÄ-µˆÉd¢¸¸­VKYYiiiÖÌÀÿÅh4b0.Ù^dd$=zô@¥R¡ÉÊ"ÔÃCÆôI8pày“ãµ…Á` °°­VKII ©©©—Ç—zŽ+ Z·nmõL0 ây^^÷ÜS'ç'©{\]]0`®®®ur|ƒÁ@QQeee’™™yÙí/† ݺu»`9Ëøøxš4i‚2(H*«·¡¡¡ôèÑãšeñYXsrrÐét„……]2µµ½½=~~~¤¦¦^p½³³3cÇŽå`áÂ…|óÍ7ôéÓç¢í9_&®C©Tboo_'B›¤~¢P(°³³«æ’^ÛtéÒ…Î;“ÀäÉ“Y{‰Ù—ã*•Ê:›/‘€xî988ÔYY$[[[†  Aƒø÷ßyå•WèС÷µ±±ÁÞÞþ²íY¶)ÊÌ$¡CZ˘¾[‡óòaÔ...Œ7ŽÑ£G3þ|¾ùæ›Kzì\î9nkkk}'åçç‹gzûöurn’úå9^Wò«%ŽU£ÑðÆo0gΜKzì\Ê0¤P(°··¿àýšyì½”J¸÷^0»Kn ,ïí5&ÙªÑbooJ¥ºìAM&:î>^&\’Ü4äåå1cÆ âããñoÞ¼9¤¥¥Ñ²eK233­÷Pvv6YYY„……Õ^' š%lÍûîþ í@6 þÝ?~œ7Þxƒ¼¼<@L¦tîÜ™ÒÒRŠ‹‹iÞ¼yµÌîÇG¥Rá[kije%ÅÔõ©ÖL€æ*÷= ÄYÿi£’+¿_Kbó>ÿ¥ 8j>Æiàg>î…ŒíÙçl¿ Ø ,Þ¾4ÿÿpŽ3ŠÝ;¼âkXéY½z5}ô‘õ»EVIOO§²²’ˆˆJJJ¬²JEE 5’Ut:ÞîîPRR«ç&‘hµZ¾ÿþ{–-[f]æèèHÇŽ­Ïî–-[Zes€¬¬,rrr®JVÑëõ”ìÝK¤ÑÒ°$¹Jj4mˆ ÿþû/­Zµºh½±³gÏ’””Ä“O>Ym¹ÑhdùòåŒ5 ???L&;vì Y³f888о}{~þùg‰ŽŽ¦¸¸˜¸¸8žþùº¾NÉáììLll,¾¾¾„……¡T*IJJ¢°°ððpL&?ýôøøøœœLzzzõÚdׂ Ð!„ÑB„r…P0S ðú¹À)  °x°ŽÀ@oÀ¡ æ˜÷ËÂÂì* 'ð+ð0¸¶€ ¡ „æFævuæõ•ˆi3µy[б0˜û`(ÌËM@‰yƒù£2/\€ ó~jó~ ó~–cÉwæUcooÏš5kèׯŸ5^{÷îÝxzzâïïOtt4;vì`ذa(•JöîÝ‹‹‹Ë•×6ÉJI±Öæ®Fª~{Äï^ãÍÒ'½ù¯1FÌý´1/3"@šù»;ðÐXbÞ§º™—Û£Ìíu1·(’Gʦbb©Ð¡Þü ø1æýò€¦@¢¹ÏáÀó±RŠd0ÐX Œ–™ûÖ¡´†‡Ï `´¹¿6Àróú(Àp2Ÿ“/àxë€Ì}Rƒj¡ …KíþƒåË—sÿý÷W“UÂÃñ··§C‡,X°€¤¤$:tè@QQ`„ W|ŒÌÌLl“’`ãFxì±Z=?É­Z­¦  €m۶ѳgOÜÝÝÑjµìÙ³‡Ö­[ЩS',X@aa!^^^œ—}æí Š´=B Ö˜ÿÆ#”áp„Òhþ~‹áççÇðáÙ1c†ÕulÏž=<ðÀ´nÝggg^{í5¦L™‚»»;Û·oç©§žºb «)={­™gM9bòä„¢´z!”©ĽÒÄü±¿ò¦/ŠØo>nB<“ ÄØ7™ûvؼl b ?|Pè¼3ˆ±½×üýÄRB!ý/ 3âþrB(¯ùˆ‰©³òIÄæcî@Ü7½÷Á ó¶ÎˆûK‹¸OÊÌû´5_Ó E#Üoþ{ûE®Oâùb2÷+Ê|—“:A(Ò/‹s/{»Œ³«ÏR›ÄÄÄÃO}úàããsÑ-½^ÏŠ+èÚµk%fÔ_¶lÙ‚‹‹ËEcënZ­–#GްsçNJJJˆ‰‰!::L&¹¹¹¬^½šÔÔTºvíJttô%.°bÅ ~øáª…iÀ'åª1B]°–x"„u„rZ,ª«µNYÜóÌm•!”ƒFAµÂÜ®!”—!,@&ª¬¥žæåJ„yÈüý„R:a)¶PfÞÏÆÜ®ƒyYUV\‹¥÷,B ODÆæ6J€áKòi„BjÞ' a­¶EñÛŠOB1Ä……úŒN§cÅŠôèÑÿZ;nii)±±±8p€Î;Ó±cGìíí1œ:uŠÕ«WSQQA=h×®Ý%ãÉÏœ9Þ={6lº]»øû¾û¸7+ëü ˆß*¡„&ÑÀÇJ˜lñ¾@ü^ …î6„ÅQ°"z"Æ—°ðCXöüŽæc9›Û<а€öEŒã&ˆûO˜€9ƒ˜À8ŒP@£ãÞdÞ^—îæeŽ%Ncn×Ùü©K«p}ˆPv]!_—ÏŸþɸqãjµ gÏžeëÖ­$%%áììL¯^½hÞ¼¹UV)**bëÖ­:tˆæÍ›Ó»wo¼½½/*«ó×_1zôhNž<É›o¾É¼ÈHèÖ zö¼úŽZ¼N,Ïzƒùúijª«lWRkœ>}š}ûö1tèÐZ=nrr2ÿþû/§N"((ˆþýûˆJ¥²Ê*«V­²zuìØñ’²ÊÐjµtîܹÚò9sæàææÆý÷ß¹.I(qqq]2_Ñå¨q&___Þzë-~ÿýw6lØÀŠ+Ðjµ(•JèÞ½;<ð­Zµºàþ^^^Üwß}mßÕÕ•;3;ï¼³ö¯¨Dr°³³£cÇŽtìØñ¼u …___zè¡k;H2‚y/ª¸a }Œ*7Ú«Aɵ)^ ª„ï aɵ`Î_ÏË´ÙÃüwàEÖŸÛ_K»¶åà¿!Î7Ög‹ÂzÊÜþæÏ…|Îÿ–ÇÓN„Ût"0ëc¹» pvv¦_¿~L@£T*iÚ´)Ï=÷ÜÕ5~ö,É^‰Yü˜‡¹ˆß3a­tÿ϶ÓÍO ,®*à>„»¡ì–!\O;"î§žˆ 5b"Å!ü» Q°1†:wS5¦ú×à<=¹üØ¿UQ"~[Š}àíí}IÂÍͻ»îº«Æmˆ ö‡‚«q}1.O"&×Öc^ÿ"˜UWPs‹ê­Ê „Õ¬%âÚý…p½¬)Ý.–ûJð£T¹IK®Š3¡¡Šª¾°¡¨†!,ã1\¹å(üœÿ•ˆxì{/²­'ÂàRDÓ–Œ…–\888ÀEÊZIGx–d#&f† U„Bºx ЏG⨚€é·ø¡ Þ»Åï€À$ÄÄ‹å½aQdµˆÉ?jÿbBxâS5dñt(@L"]Mif‹wFÂ{Æ ñÎ,CxÕx Bf¤]©,( íÞ½4?¾®»ÒðÐ"ÞA—»GõTåN¸˜Ög¤*ßÇ…( êÞt@xpX<Ú<¨>q{ƒ¸ê\ñjµ///¼.0ž››Ë#<Â÷ß/3üJ$×BpïE•%U…tûª)ŽÀ„ p9Âb=âÚê†xà§"ÜMåÄÁU£U«ñ ª¾p)BÀM•U¼®¨› +’DQQn8QQΜš |J•«{«`‚LCLÈXv¿Pî¾w€M¥ìgóöw"ÌCˆd\½–ÙxÄó+a¹uC(pÑ%¹ á2oñj)G$ÉR îËNT·äbîw2b¢h;B™nNUHÈfĤaB öF(êg öF„ÂÚßü+óõ膈¿Ø³V‹Èó`™È]ƒxF3÷i´ù0ok‰}¿Û|^鈂6ŽÄû7ÎÜ÷h„ç…%„Âcn«±ù7 3÷ùbÞFp‹uÃ;Õ›†ˆFƒMEz''ùè¼^ãö{D¨‹bòý0"Æ1õs ⻡hvGÜg–{u)bR Ä=ß1~Uˆ1¿áÅר…˜¤ßƒxîD"¼’Ú žJÄó#‹{Ú]%7dü 233/YD["‘\¹T½¼%WOSÄl{!•z8"^õjQ!•çñÍêúo^4 F£Q|1!Õà5ê^Y•H®¯´4X¹Ú´©¾ÒˆP$cY×#©š4!”B‹5äJBÔ¡¶/â^²djW â½×›Ûïh=°!ˆ®4Z#”^ó¾Bn20ñbâ¯!(gR¥È 5·y xáòÝ ¡Ô݇”ãÍç8ßaÞÏÉ|„uù„àü("@‡pó?‚P}‚º a™2_»q%3¡”Ž0Ÿ“a}ýǼosŸN#”ù­Ïœ`óuÜ…PˆCJx°¹ŸæG—5‰Ù_æklB(*óukŠðÆY•*)õ,½C­ÎÑèt$EDÐⱯuJBð¢úä‡1Î+cOøÝŠãûbÌõAä´è€˜¸ÈCŒëæö!îŸDÒ9ËÄÏ6Ä8lOURº½æÿÛ"Ƹ“ùX•æ¶îEŒqWÄDÑ(„¼±ÒÜ¿cˆ1ÕÂÜ·ÄU;óquˆ²ÃˆìïŽY% èg¾‡¯“J%ˆñšüñì¸ËÜ—‘TKrÍ×&1ñ䈸ßÖ˜·Ÿ!Ú  ×ôSÉ ‰äf"xé¶t­¸ \éN ^ –dÑ}Ì-5Ì-ÊlBYqžr§r*TÐ9Y\L\Ó¦ u¬…¬„:„rÊ¥óq!&ö!&bV!&>J¿m6ð&"ú/ˆ‰‹ÖTÕ¯Ž4ÿ DXécÜRé á9PŽPÛ!Æä.„¥ÒÕ¼ß(ĤS<ÂÚˆPV#Æ£ù8•ˆ1c‡˜dioJÅÛúR÷²…Í-y Ìý¶¸[ªe"ÂÏZ˜ÏÁ2ßp!×ßFæOÌ–߃Ph{AæÑLÊTe\ Ra•Hn&”HeõzÑ!päúX¬UAjUµaÿ‹%‹ò*D|XWÎw¡»Å)..®²°þ‹˜Un~ J$õŒ’’œ;v„sKÿ¥+ψo¨.DÖ'g~ç*ÓJ„µçJ¡º¢z5¸!B[„…I‹˜Ür¦þ]7%Õ]‚½©þL;]×¼qœ=uŠ`_ßó*†\5F„B¹q]½ Ýi„kk0bå#„ò™†pß@Lh” ”17„k|„ ,DXŸAT h‰°þ'"”6K¤åT,ãÌŠ†HÜb²5 aá´Ä††R=VÔ²¿%Fô%ÎÛ%s½Þ…N\Z–´ÄÌ_ –XsgÐgë1¯©¹)¬&“©J¸õ™}%‰ä†ã‡xY­§ª¦äµpõÙkn»!|vB¼üv#fY»!܇֛ׅ îæ~]¡À¥Ð+pLsDa¬oÚÕ£T*iß¾½xáÌGN­JwÜqMZ¶¬ž!x-ÂÊ÷T]÷î PP?ò&¨ B{„õIæ¨wmØ€mtôµ5b){—p÷^Žpãîb^v ¡\õ *iÞB„ûîNó§½yâ=mOõ÷l3DâÄÄä¹céÂEO.Œ¥M'ÎW.ëË}s“R#1 ''‡%K–PTTtÉí4M]Ÿ—D"‘\b¦´Ëµ6t*„»Ðv`â¥ØñÂk>ÞKTÍÈnAXUì1MqÀ[\Y¬f(*ñÞçjhÃy 4Hü“‚Pà¥ZÒÀè••U Ò‚ò¤ºîÙMÊuNî"¹Nhµ'&¢¹–2•z„›¼ÂÓ +}9Tˆ÷è®ÜR¨@LKê%5RXÏž=Ë–-[ÈÍͽ춨ÕrZ\"‘ÔSˆ„×;{b8ájän>–%~ëÜÇboóÇÂ6„[Û.]×ü †½RïL¥‘íåj±Ü„T"ŸH$ ½{aÏ?^äßRU+X"i(­VcºX]íËaþDx"M@¸úÊ Ì[–i”­ZµbÉ’%uÝg‰D"¹>܈äHÎ+©Õc¼®äiÛ‘‰s:ð:UIþKð0Lñ¦ÚºZµK!"^N"ih$'ƒ³Ù,x¿ú²®¯¤aáíÍ·þþüÏ’D¯¦¤#Þu3¨Šá”ܲÔHaÕjµäççãîî.Š^ßì”#²…ýŽpÉ«D¼<^äêÜLˆÔÕŽaõ\ÿø‹%aágoBºçncI~½ÃÓŒæ¶-žÝ.Te,E¸^xrýf²Œw'"hýR©øMˆ x="+YMF¨Ñ¼:"[œ=¨JT(¤ ©E”\½ÕÖx ø‘˜É‘yï\k«1ÆßA$qˆ¯ë¾Ad!žÑIC#;,q}€G–#IƒCg2‘¡Õâëë{é ˱©Krp"âÇT•$’ÜòÔHaMIIá½÷Þãé§Ÿ¦S§N°mÛ6† ‚Juù³œ>G–·!T¢0õˆÒ!5:S€÷V›.À|D†±Íˆä*½¨ºêz„Pú"éŠU.ùˆ›7‘yô¿¤#ê;• Ò`§ ‚Êÿû\¨DÔÛPFû"Ü+z™«C<Bi³EÆ]'‚ò…\•,µâRÌýmÈÀfpáðBd<ó@Ôi;AUñðÇÌ×ßÛÜF "îOHDó…ù·èe>~B¡Ö#ÙX^ìg.”ó5øÛÜÖ_A¿)8;bã%31Hn"±l{ãûB µ¤•OE<~FÜ¿ • Äý.‘44FŒos¦Ã\{6N‰¤¾a2Q¶};êÂBœ/dœÌFÈ€÷ dÆÅˆº¾÷SJ#¹å©‘ÂZ^^Nvv6Z­Öº,++‹O?ý”AƒÝ< ë D”hċ…*+f8"Ê:óº+=¥B„p9¡\}‹(ð{ ¡ðµG$WYg>†a=8EX#Ï!3!ŠfïC(pî%ì>Dí&à!ó¶ÿßÞy‡GUtü»5»é4Bz£HH#Ò›€ü¤E@}}Å‚E”,¯ ;"ŠðbGQ¤(½„ÒC !¤÷¾Ù¾{Œ{“%H²!Ìçyò$¹s÷Μ{gçž3sæÃlZ#~Núçó2•c0Ûº§ð +±¶ ƤˆQøý??Þ J¬'ÈlTÛ§7Ä`õqõµø§}"•™Žl¶¶²ÙÞt\÷0È ÂýG~O}vh™ï¾6w¶2bõOÛu„XñÏ= IRÜöqǵù{È VþO{qGÊ-`Ðÿ{üZZZpþüy”——ÃÏÏ02"~×*• .\@UUàëë{÷LöPúÈw< dâfÈøô3H¤DSYY‰Ë—/£©© £FB@@›kO"‘àÌ™3Ðh4 „‹‹Ë­çá«Í9L1 à ??©©©Ðjµ …«kkp3Fƒ¬¬,dggcèС º5]E’Êf ^ÞPÊ=J¥Bvv6ÒÒÒ`ff†‰'²Mª%•J…óçÏ£¦¦ðññé¹®¢V£©º–ÎøóÊAôñ‘‚¾K¼}_‚rWÓ¯a|U*~úé'|þùç€V«Å¶mÛ°zõjÌ›7|>[·nÅÑ£Gáé鉲²2øûû㥗^‚……ÅíUª°Ä­N bؽb(vö’pY|ĨbPÕì7q1(@6„ïÙ£ùv›kØB?ú§înwÌSˆV£Óæ3ËAVui8:k7½—TX‡ˆ«òü^¾îÍr Ñ}DPˆQê2+=@_òÙÙÙx饗 ‰`gg‡={öÀËË ÿýïÁáp°iÓ&ÀÉÉ ß|ó f̘'Ÿ|ÒÐͦ TÆ‚xUè²…eLò­V‹“'Oâ­·Þ‚‹‹ Äb1¾üòKÌŸ?>ú(***°aÃh4˜ššâ³Ï>à /¼€É“'ßZE÷Œ¿J?£R©ðý÷ßcûöíð÷÷‡V«Å_|'žxsçΟÏÇ–-[pâÄ xzz¢´´#FŒÀÚµkaÞÕŠR[jTƒLÔR(ýŒ\.dž ˜˜444`Û¶mظq#BBBÐÐЀ7¢°°NNNرcæÌ™ƒÇ¼gðx(vt„Qg‚y—½lŒÒ#úÕ`-))ÁÏ?ÿŒ‡zK—.Ã0صk¶oߎèèh444ààÁƒX½z5æÎ‹ììl<þøãˆ½ue‡12?YÑ[²Ò舞íMuð@ö’d…s ZÄ@¬1ŒE=¸nwp:9F3µ2@ U¿ÿþ;x<6oÞ '''$$$à7ÞÀ‘#G`jjŠäädlݺØ·o>ùäÜÿýpv¦‘(`ŽÖ½èQ +­.†kŽT*Å÷ß   ¬[·ÆÆÆ8qâÞ}÷]„‡‡ãôéÓP(øôÓOajjŠ>ú»wïFPP¬¬z’`döýHÚ! ¥Ÿ)..ÆÞ½{±bÅ ,Y²ß~û-¶oߎ˜˜ÔÖÖâСCxúé§1{öldeeá‰'žÀ¤I“Ó³J” “áÔ‹€b’““qåÊ<÷Üs˜6mjkkñÆo૯¾BHHâã㑚šŠ?þ~~~Ø»w/¶mÛ†¹sçÂÉ©áÛE"dޱV«œ 3e ¨±Jé1·ÔU¸\.8šššPYY‰ÊÊJÔÕÕA«Õ¢ªªŠ=¦û¹ÙU¸®®°lÙ2˜ššÂÌÌ Ó§OGii) ’’’àè舘˜øøø ""§OŸ¾uÉnøÄ5wˆ¼zH‰ 2»¿ÀÿüL¾±ªÃdå7¤(ýCaa!-Zðx<„‡‡ÃÉÉ ¸pá"""àçç@€¨¨(8;;ãÂ… †n6e ÂÙO_2ç ƒN`)•JÔÖÖbÙ²e°¶¶†H$ÂŒ3 •JQUU… .`Μ92dLLL0þ|ÔÕÕ!77·ç•”‚l ñÒ( ¶¶<K–,‰‰ ÌÍÍ1mÚ4C©T"11...ˆŠŠ‚@ €¯¯/ÂÂÂnMWÑÅg “ÑPXXˆ€€Üwß}àóù2dbbb——8þ<"##áãã@€˜˜888àâÅ‹=«@*Emee{ïÈ*45A¼÷(”rKC%‡ÃZ­ÆçŸcc’gA.—C*•â™gž‡£o±mÞ¼YoªÞ{ï=˜˜)EFƒììlX[[C  ??&&&¬½@ €‡‡Nœ8Ñe»4 š››¡ÑhZýë÷‚¬¦>jHÞƒ0 ©TŠ–––®#ÔõÏ?ÿ>¾ËëÊd2H¥R‹Œ‰²iˆ;JHh4455A£Ñôk½111ˆˆˆ`ck( äää°ž^¹¹¹ˆeuØØØt©«0 ‰D¥R þýù'\¶lisH‡± ™(÷ …‰äŽõ”[2XñÄO@&ëYr¼›gVÌÌÌàç瀸•ýöÛoؽ{7{ì1X[[C©T‚Ëå² 9—Ë…H$Bccc—õ455!!!ÎÎÎÄ8‘¸à-PcõE£Ñ ==°µµ½ó Þ^^^l®^½Š÷ßfff˜={6öíÛÇNî‚nûxuu5Î;‡ñãÇ÷|ep’’êŸù…B„„@{³ÛU"àïïP«Õ8vì>ûì3Ìž=£F‚R©Ô >#‰ V«!•J»¼îµkט˜ˆÈÈHð ød åž'>>ýZ§¹¹9;ζ´´èé*·¥«0 ƒÜÜ\äää`Œé’5`vOZCÌH$ÄÇÇC$ê=e=gÈ!ìßøñÇqüøqlÚ´ y¿ðù|=]…Ï磩©ó™DµZ+W®ÀÛÛN©©à™šB,nãÖ˜buü»_E¥˜ÒÒR$&&bøðáwt[2Xmmm1gΜ;ªP£ÑàòåËØµkðØcaæÌ™àó;oJw+JVVVo]I«qÊ= ŸÏGXX;èö' ྾_}õ.]º„±cÇbùòå°¶¶îô3Ýõq'''LŸ>½_å  0BA¶üc ŠÅbLš4 ‰¤ßWݵZ-®_¿Ž;v ??S§NE\\\§J‡Ãé6JðÈ‘#Mfáå +0cÆ üùçŸý^¯F£ABBvíÚ…ÆÆF¬^½Ó§O¿m]…Ãá 00cÆŒ~ Ù¿6 ebaa3f ))©ßë–Éd8yò$vïÞ ccc¼ýöÛ;¶ëä×]õq@€‰'ÂÕÕ²Š Ô›™±+´Ð82ñJçÜï)<<<ÝíÂLwܶ&ãÆ ðù|ØÚÚâСC(((hwN\\ììZÔ5 Ž;Ææm}ðÁõfyÌÌÌPZZ ¥R ¡PFƒúúúžmðÖ¡ Œš¿‰bJJJðÆo@ àùçŸÇøñ­™¯-,, P( ÕjÁår!•J!•JáááaèfS:Ã0 &á†AJJ Þyçøøøà­·Þ‚²¿ÕÌÌLo5µ¡¡B¡°ç—$ÿüö7´¤”{Fƒ¿ÿþŸ|ò f̘E‹µÓUªªªôt•†††žë*æ +…b T*¾øâ œ>%%%ððð€B¡@JJ ‚‚n!î»d‡*;±}ûvp8¼õÖ[íÜâCCC‘œœ ©T SSS”••¡¤¤‹/6t³)”ÑÜÜŒ>øaaaxüñÇõVUy<Ƈ˗/cÒ¤I€ôôt…B ÚÃ5 ¨ëŠÈËËÃ矎'Ÿ|S¦Li—_588.\@YYÜÜÜ “ÉššŠÐÐОU0tBbPΜ9ƒS§NaÆ  j犌Œ Èd2˜˜˜ ´´eeeX¾|y®¯qwŸÏgãÝàh1ÊqË]çàÁƒØ¹s'|ðADD´N•,X°K—.EBB¾úê+DDD´sÌËËCaa!.\¸€Ë—/ë•=ûì³ ‚F£Á¯¿þŠ+Vàܹs(,,Ä‹/¾ØóžÉoÖÓhÀJ/"•JqáÂØÚÚâÃ?Ô+‹ˆˆ@dd$~ýõWœ8q¡¡¡øõ×_¡Õjfè¦S(=¢¦¦©©©°°°À;ï¼£W¶hÑ"ÄÆÆb×®]HJJ‚••~üñGx{{ÃÛ»‡>¾2 ˆ•dʽKNNŠŠŠpþüy$$$è•=÷Üs ‚J¥Âo¿ý†åË—ãìÙ³(**ÂË/¿Ü³ ¨ÒN1 jµ ¨¯¯ÇþýûqàÀ¶ÌÜÜÏ?ÿ<&L˜€ßÿ'OžÄ¸qãðË/¿€Ãá $$¤Guè‚¡² S§üèD å¶¹¥a³ºº?ýô|ðA<ýôÓ‰Dhhh`Ë­­­1uêTØØØ`ýúõ5j€ ³ï‘‘‘lz›¶h4XZZbÓ¦MضmyäXXX`ݺul ¦nÑ8 `>hn'ŠAhiiÁ˜1c ‘HPUU¥W&‘H0|øp¼ð سgvìØWWW¼õÖ[ýpB¹]är9"##ÙtfmQ(˜3gñßÿþZ­¾¾¾X³fM»UªN)pÍÐRRîeø|>Æß¡®¢Õjaee…×_ÕU,--ñÊ+¯°®ñÊ@F­VÃÖÖ#FŒ@MM^™R©Œ1Ï?ÿ<öìÙƒíÛ·cذaxóÍ7{¬«TUUÁÒÒ’DÚ.0@Ïl] ¥CnÉ`-//‡R©DLL ÛiuÁ4tî>>>°°°ÀåË—õ ÖéÓ§w8f̘1xçwPYY ½=°Ý¢IeCÃeS „Þÿý.Ï™>}:FÆÆF¸¸¸ô{Ú åNÀ_|Ñå9+W®ÄäÉ“¡V«1tèP6uBh .E¡ˆ™3gbæÌ™]ž3vìX¼û¬¬„­­m¿G£§Pn‘H„G}´Ësø|>f̘ѣG£©© C‡eÓ<õ„êêjØÚÚ‚ ¶Äp ¯ åfnÉ`Õå:m<ÃÔÔ›6mÒSH¸\.ŒŒŒºÍ»×VVV=ÐÑ1€[ð¦P …££# Ý ¥Oàñxpss»½»ƒÆ  Üܶ®B¡Ü%899ÝZàÓ((( Ê$ 9‡§ZÊÝÎ-9Κ™™Ë墼¼œ ¨Äãñàääö<•J…¦¦¦[š¡P( ¾ {X) å.F¡P¯ƒrº5”ÁÀ-¬^^^°³³Ãï¿ÿÞix]êš’’½ L …B¡P( epSZZJ¯f €î|¢Ü!·älllŒÿû¿ÿæM›ðî»ï²yV…B!T*$ 8€ü³gϦ¹%) …B¡P(”{ˆŠŠ âJÌàuÇ—»«Q©­Ðh†„B §1;B«%×>àÝFäe][”JÒ>P(ȨՀXÜZG·|^WK ‘G¡ ÿ‘sŒŒÈ瀲2!„Â; ~ËŸŽ…D"ÁŽ;pìØ1øûûÃÚÚMMMÈÏÏG]]fÍš…Õ«WS—` …B¡P( åÂÍÍ ...À»þcèÖc«®(/† #Æÿ& ¨®ŽX ù-®®­åUU@~>`eC¯´¨­LL{{rŽH\¹TTÀä355€\N>7kiƒH?NÎ #çzzEE@Aàà™™€pâ1&-,Èo¡¯¯'mŒŠ._&Ç.\ r;:™sr77àØ1@"ÆŒ€qã€ÆF #ƒœMއ†û÷yøpÒv†Ô𠏏“&¤>­°µ%²™›MM@n.ÐÜl”ÝÑ3¼eƒU(âþûïGDD.\¸€„„ÃÜܳfÍBTT|}}[“÷#--À—_+V7¥€¥P( …B¡P(}Ìš5k`,5FèaÌ&­–aY¡k‹DÈdäxm-YÌÏ'cCpÿýÄH²´ ‰Áåç\¼øû'O%%ÀرÄ>HMFŽ õM›$%¾¾@^1<í쀠 bLÜQ““‰ ¬‡16ÃÉ{*GŒY.—ü­Û»É0d¥qÆ bt._N K.—¬Jv„Î ³°èZ ‹îÏ¡ôƒÎ`õò";3“,ÛS(ƒ ssârqü8°p¡¡[C¡P( …r¬AäßÄDà“O€E‹ˆA:u*Y œ2…¬8ÚÚ¶~ÔÙ™ìñì)YIå:‹†Ò–A÷xŒˆËÀÎä÷íDÏ¢P*B!ðØcÀgŸ÷S*žB¡P(Ê@B À к‡?þ¼ü2 Þ3{¶¡G¹¹¥<¬w ÞÞÄßûÈâO¡ &||€¹smÛhÿ¦P( …2À8ìÝK¢ÝnÙBömÒØ2”ÛeP¬ ½oðÚk$ŠX[T*²AûûïÉI*í½z[£d ¥(.&‘Ë(ƒ“à`²ºzü8ÐÜÜñ9õõÀùó$š…B¡P.ÀÙ³úúCy9ð¿ÿ¿ü\»ÖõX®V“HŸº\‰ŠA©jcëõÀ¼yÀ!†nånÇ`.ÁZ­ÍÍÍ055¯ß.Ã0ÉdÉd …011—{ëvµ—ðþû@z:É”ŸOò••‘p×ÁÁÄßýÊà·ßȪìøñ$¤µ±1q%–ËI^¢k×€´4šZÊÚË ¨®&_B.—„½..&ÿ§¤Ïׯ“J®®$˜.‰nv6iXLò!=ø pæ ™yòó#u:9‘kååyÆ'a¸ccÉ&uccòcnN"œ À_Ùfξý– :s†l\;–È(—C'=´aäHQÍߟÈàèH^xÆùLM‰ÑpØ……$äv}=1”<<ÈfùÊJ"k|<9×Õ•„Ò¶³#íËÊH{G&m°³®^%¡¶ÃÂȹ––Ä௯'纸™î»üæpÈó±³#׋ɽ02"ફɳHN&à´Z@.7ÇøñBCusH$ðù|ˆt1ÈÿéãÍÍÍP©T‹Å‹ÅàÜâ´£™ ,ðÁÀ¡CÀš5äž $ôû/¿g¢V“~ÓÔDîý#MMä^Þ¸AB« üþ; e^_O>çâB¾'r9¹vBùx{“¾=t( t`kKúËС¤›š’6Èdä;¦V“>ªRµî5‹Égyû aaaˆŠŠ¨Õjœ?»víBmm-üýýÿ[º¶®/¼ø"I$ýãD9àñHßU*^ *™ ¨©!϶¦†©%%dÂ$<œô‰iÓÈ3­ª"}Z"!JRr2Id}íé[aa¤ï¨Tä©©¤ aa$¬|` I ÍáþWWG’U''“¾bdDêÌÈ $ééäÜ1cH½~~$Š`y9)wu%ÞÞdE™Ç#jkÉ÷®¬Œ( ù^¥§“ïôáÃDOÏÖÉ" ‹Ö0ùÓ¦ÿMdÿë/ro,-É÷2-Œû÷“~4gpé™ ‘J‰ñ®Õ’À´þ62"“@ éË"ÉËfaAÆ…}ûˆ2™›Kžƒ@@¢êŒë¾GcǶ&ô./'ÏT ÷£¤„Üãìl ´”Ç 3g¤‹C.—ã­·ÞÂÊ•+Ù>,“ÉpàÀìÝ»Z­cÇŽÅ#<»›ãæS(w¥¥¥øè£°nÝ:ØØØ°Ç322°k×.äææÂÉÉ qqq í‘®’‘A Óª*2^ØÙ‹“÷ð¾}ä]––FÆð¥K[?HÆä÷ß'cßðádjn&ãç¿þEÞÉIIdÜárÉ»^$"cJy9‹är2î1 °};yO”•cÏÆ†Ô“›KÞÝÙÙ­©-.^$uææ]ÆÍ|63“¼óããÉ»'2’ŒÉ£F‘ñV.'Ÿ $ïݨ™Ïž%åååDG03#cßO?‘չݻ‰¼!!äalLÞIIDž)SÈÂÄ”)äºeeäºb1‹‡ NŸ&÷jút2ÞO ü†ò>su%möõ%ç äÙdd{ÕÔDÞ2ike%³ssÉ;!,ŒÔëáAd,*"×ò𠺓YÌÈ;¦¬Œ¼oòóÂB ›¬ÇÇÇ#!!/¿ü2{L­V#>>»wïF]]¿Îr¦ÜÄù³@yæJoÀa˜þu illDYY¾ùæà³Ï>Ã|ZZZ¬X±gÏžÅþýûñá‡Â××·Ãë©ÕjüñLJ“S³wnO DB`këÞ<¦›»EãNaòÓÝ5ÕêÖ•#¯wÛ0P9}ú4ÌÌÌ0vìØ~«S©T¢ªª çÎÃ'Ÿ|‚W_}ÓþI€•§žz ,À„ °sçN”””àÛo¿Õ[…mK}}=þøã¬X±¢Ó:››É µ¶–üïéI^èÁ0­3Ò=Iÿ¤›9îlrU©$ß–ò¿BA®kfÖê¢&“µÎÄ‘—¼@кb¨›=×­|êVdu3Ö"9ndD”†!åryëù&&äï¶+¢\.iFC¾º-DA37'×àrÉ@ÐÚ~Ý¹ÆÆäþêBåëÜötç´=W7£Îå¶®øêäÓ²ºUS†!çèfÿu+¬FF­ÇÚ®`èV t+Ôjµ ‡ïGtôx888ôW‡T*EEEþüóOÁ0 8€O?ý«W¯†ƒƒ>ýôSx{{cݺuz«°m)**ÂåË—û,¯·VK }ssrïÍ͉¢ª{é»Qb++ɤGUYÉ*-%çFFꯅ³¾žLª9:¶ö ‹Ög/ÅV$j5 D"rŽî\]Èõ,,Èo†!ýA!Ü¢µßs¹d²Ãؘ”)¤ØÚ¶zè`"CeeëwÐȈܱ¸µÿš˜ïªHÔú½áó[¿Ëj5¹@®¯Psuž<^빺ï‚îýÔÒÒê¡T’c&&D›Öw­VÛ:aš›Û„ÄÄÃxî¹ÿë·þ ´ê*;vì@qq1>ûì3vÒ¥¥¥Ë–-ƒâââpúôi>½«½üð1'O&«åÓ§“ÕKKâúnfFÚ}û€_þýoâ.K¶$ÔÖ’U"±˜x ,^LÑqãZ·>¨ÕDNI!+ÿ7’ºe2àí·‰·€ZMVT®\!ÊoSYÅ¿x±5Ù}u5QÔóó‰÷ÃU—¼<ò½½p¼bcɱˆòù’r oo²Êß}DV…‚¬ügd•¬úzÒ†êjâ=pô(ðßÿ¶Ãã6#ƒô{r¼±‘ü½oQȧM#†—YQºvÀ#G#Ò‚Ü##bÀçæ’ªÌLbà …dÂ,3“x)$'“ëúù‘Õ:ggr߯]#òϘAþøcö8Ã0ÈÈÈ`U9r$är9 oÛ`Õœqt$†`Cq¬©!Fª›[k>?•ЏäݸѺ'?#øüs2aBŒÙ³[÷âÄè41![2tÊ£—ùBò&%LŒ«$ÛKÆŽml0‡a€ ëöÃq¹$–кâ¯Ñsï¿_ßãÏ'›n¥ŠÃ![= :šüojJŒV>¿uÏ´ZMê±´$.•žžÄ(ÍÌV¯&.¦<ùÑÕ­3”ÖUW]¹nuH÷¿n_ ‡CÚCêŸ0¡ÕƒˆÃ!í ÉsZ÷øñùä·îZFFÄ5)‰¸´šš<¼ñ1 ¢¢¤8|¸¦ßûø”)S…={öàÔ©Sze™™™ptt„‹‹ @$Q]…r×ñ¯ý «V­ÂK/½Ô®,==£Fbuggg8;;÷Ø`¥Pz›~7XŒŒØŸ›©©©P(„øŸé4>ŸGGGÄë"ùtBMM öïßÏ®ZQ(*• çÎÃéÓ§YwÜþ‚ÇãÁÌ̬à •••=z4øÿh¸æææ°°°@III—×,**ÂÞ½{1yòdXê¦Ö)÷4R©‡FZZZ¿OvV™ÑÁ0 ª««õú¨ƒƒT*juþꘘ±XŒ)S¦€ÏçC­&«lºýÔ ä¼À@²çméR²Â§[‰Òy¸º’ØååäóAA$ΨÞf 6€¬d^ºD"Ì_¼Hö%·õZ¹yU¬«ºtF£î3­"ñùúÞºÛÝÙªUÛú££Éjñ;ïÕæµkÛ{#´=ÿN½Šn–µ'+km?CVy<}O‘}û~F…Bw¥«TWWëé*¸téR§×c ððð  ?…¥¾¾¿üò ¬:[~íCtã7¿×»ÊÊJ„„„°4033CéÍi7Ú T*ñ×_ÁÖÖžžžý.e`’““ƒC‡!¸mð Ûà®pU릘;ÁÆÆaaa0»U?;Ê …Ïçcâĉ`¦Ó}s MÛЇ0tèPÜÿý·1›28‹Å˜5k´Zím¥ëO†V·üÖ cÇŽÅ´iÓÀáp V?ÿLÜyx€¸=ê"/WTÕ@—®·B8:’; ÷rÿ‰Å¤=ï½Gò ô¹£ûî#÷Jçf:árÉdÃÍ,\¸0tózDWº ‡ÃÁ¸qãbèfR–––X°`Á]³:ß•®"0eÊxxxº™”„··7¦M›Ön‹Ü­2  V]¸l†aÀápÀ0 †évÕ”Ãá€ËåÒ´ ‡Ãö‹„®=7÷ñî&[8΀7J(ýË@÷týZ‡V«…@ `W£:ƒËå‚ËåB¡ i¹RS×_oN®£§û´I[z[6b<¿þºþž¸Š.ÎÝÌ@îã·««P(:ê8~;ºÊ@•…bXtïö;¾Ž¡i‹$ êêê÷‚«W¯R×Ê Áßߥ¥¥PþV¥ÎHR~~~(((`åææ‚ÏçÃÞÞ¾G×ÈÍ%‰>ü°½±:P¸ŒUJßáëë‹ææfÔ×× ²³³©®B4øûû£¤¤ª6æWVV¢ªªª]p& ¥¿PëØ±cQSSƒ¬¬,¨T*ÔÔÔàÊ•+lK ån',, ©©©¨¬¬„J¥Bvv6ÊÊÊiè¦Q(w ÇChh(Ξ=‹––( œ?=ÎßçëK"ñöU¤v åN BUU®^½ •J…êêj¤¤¤P]…2h CJJ ªªª R©••…ÊÊJŒ?ÞÐM£Ü£ (g!___ÄÆÆâÝwßÅøñãÙˆª¡¡¡†n…Ò+Lœ8GÅúõëáçç‡ .`æÌ™píhó…r—Áår±hÑ"¼úê«x饗`aaÄÄD<ùä“°é*Qt)’(”ŠŸŸ¢££ñÎ;ï <<œ¨J÷§R QQQ8vìÖ¯_œ?³fÍj—â‰Bé/ f°Î;±±±í”˜'žxÁÁÁHKKÃÒ¥KA£¢RîJ\]]ñÅ_ÀºMQssslÚ´ ÇGII ^}õUŒ9ÒÐM¥Pn‹   |ñÅ2d{ÌÃÃï¿ÿ>Ž;¹\Ž|°Ç««Ê@cþüù˜2eJ»(®O?ý4BBBžžŽåË—#""%t¦P0¯¼òJ»c–––xã7pìØ1”––bÆ 1b„¡›J¹‡1˜ÁjeeÕaoÄÆÆ"V—ŽB¹K122°aÃôŽq8XYYaáÂ…†n…rǘ˜˜Àä¦ü%...X±b…¡›G¡Ü1]é*“&MÂ$]b] å.ÅÑѱÝ1®ò€.™4…b`ÔV …B¡P( …B¡PtPƒ•B¡P( …B¡P(j°R( …B¡P( e@B V …B¡P( …B¡ H¨ÁJ¡P( …B¡P(” 5X) …B¡P( …2 ¡+…B¡P( …B¡P$Ô`¥P( …B¡P(Ê€„¬ …B¡P( …BPƒ•B¡P( …B¡P(j°R( …B¡P( e@Â7tnF«Õ¢¦¦ÕÕÕ077‡““x<ž¡›E¡ô%%%hiilllÀåÒ¹#ÊàA©T¢°°Z­077‡Ã1t³(”^C«Õ¢ºº555°°°€££#ÕU(ƒ FƒââbH¥Rª«P ΀3X/\¸€íÛ·£´´VVVX¾|9¦OŸ@`è¦Q(wŒR©ÄŸþ‰ï¾ûÍÍÍpuuÅ£>а°0C7Bé$ vî܉ǃaøøøà…^ÀСC Ý4 ¥×8wî¾úê+”••ÁÚÚqqq˜:u*ÕU(ƒ¥R‰ýû÷ã»ï¾ƒD"Á°aÃð¯ý !!!†nåe@M•ÔÔÔ`Æ  ÄŸþ‰‡~ï¿ÿ>RSS Ý4 ¥WHIIÁ–-[ðè£bÿþýð÷÷Ç«¯¾Š¦¦&C7B¹c†Á/¿ü‚à½÷ÞÃîÝ»¡ÕjñÞ{ïA&“ºyJ¯ ÓUÆŽ‹?ÿü=ôÞ}÷]dddºiJ¯””„?üÿþ÷¿±ÿ~øøøàµ×^£º Å` (ƒ511æææ˜?>Äb1&NœoooÄÇǺiJ¯pöìYŒ5 &L€X,Æüùó!‰˜˜hè¦Q(wŒF£Á™3gpß}÷aĈ°³³Ãƒ>ˆÂÂB\¿~ÝÐÍ£Pz…„„XYYáþûï‡X,Ftt4<==©®B4èt•ÈÈHVWHJJ2tÓ(÷(Ê`ÍÊÊ‚ œœœFFF1bRRR Ý4ƒR\\ŒúúzC7£ÏhiiAvv¶¡›Ñ/¤§§Ã××ÆÆÆ899Ýó^ééé`ÆÐÍè3î ƒM«Õ"##cÆŒa@.—£°°ÐÐÍ3(iii†nBŸRZZŠŠŠ C7£_ÈÌÌ„P]T*®^½jèfôZ­yyyH$†nJ¿žžˆÅb€££#žžnè¦ŒÆÆFäççº}†\.GVVÖ€ÕÅÔÖ¦¦&ðù|…Bǃµµ5*++»üœF£AYY ÊÀ—/_†££#ÜÜÜ Ý”>¡¦¦.\€……E¯^W­V£¶¶fff†‘¥¡¡"‘ˆ \`ll TUUuú‡…B¢¢"ðùüAÙÇ?kkëAС°°ùùùìË¿·ÉdNjjjb'dÀÊÊ jµ~†Ë墱±EEEƒvà±cÇ`gggèfôW®\‘‘Q¯+;ÕÕÕËå†O›u>Ÿ++«nu•††””” ÊàL2™ §OŸ†¥¥¥¡›Ò'h4œ;w£GÆ!Czíº Ã ¬¬ ÆÐ"êq³®bbbccã.û¸V«EUUJKK廼¸¸999zï·ÁDSSNž< KKË^Õ3uýÂÈÈ莮3  Ö®„í ¤¥¥¡¨¨hP¾†AEEE—FÍÝ Ã0°²²BBBB¯^S"‘€Ãá°³à™®ú¸‰‰ ÜÜÜpâÄ ˜››Ê>îää4¨Ý¢µZ-ŒŒŒzµkµZ466ÂÜܦ¦¦†±K†éÒ±µµ…X,Æ©S§z}âj àââÒ«Ï ¡V«¡R©z]Æššš»f²¶«q\(ÂØØgΜ‰‰‰¡›Ú'ØØØ ê>njjŠ7nôª·ˆF£A]]‚‚‚ -^èj···Gjj*Î;wÇÆÉ@D«ÕB,Ú>Î0 ìííqùòå^½®\.‡L&CLLÌ]g@¬Z­<Z­ …¶¶¶~†Ãá 88ÁÁÁ†n>…Ò-B¡ ÀÃá@­VC­V³nð!0uêTC7Béjµšý_¡P@(véé ‰°xñbC7Bé·£«ˆD"¬X±ÂÐM§PzÄͺŠJ¥‚F£M§ŸqqqÁÊ•+ ÝtÊ e@­Ùûùù¡¹¹µµµÈžˆœœ¸»»ºiJ¯0|øpC¡P în•••wÍ …Ò\.¸ví{,//<oP»ÃRî-üýýÑØØˆºº:$Hnn.ÕU(ƒ†áÇ£¨¨J¥PUU…ªª*ª«P Æ€2XÃÂÂÐÐЀ³gÏB*•"''III˜1c†¡›F¡ô ÑÑÑHIIAvv6ZZZªª*Lž<ÙÐM£Pî.—‹˜˜=zåå娯¯Çàè舑#GºyJ¯ŽÚÚZÄÇÇC*•âêÕ«¸rå ÕU(ƒ†˜˜\¹r¹¹¹hiiÁÙ³gQ[[‹ØØXC7r2 \‚±`ÁlÛ¶ GEqq1bbb¨¢C4#44¯½öqãÆ ,]ºVVV†n…rÇp¹\Ì;‰‰‰X³f Äb1ÊËËñꫯÚ}{”{,X°Ÿþ9þþûocòäÉ>|¸¡›F¡ô ãÆÃ¸qã°~ýz888   €ê*ƒÂa`üâÂÂBdddÀËË ¾¾¾†n…Ò뤤¤ ´´ãƃ½½½¡›C¡ô**• —.]‚B¡À¸qã`nnnè&Q(½Î7™™ oooøøøº9J¯“œœŒ²²2„„„Ðmƒ2 V …B¡P( …B¡PÔV …B¡P( …B¡PtPƒ•B¡P( …B¡P(j°R( …B¡P( e@ÂÛ¸qãFC7â^D*•¢©© ÆÆÆzǵZ-ª««Q__‡¡P‡Ã–+•JTVVB"‘€ÏçƒÏç³å*• UUUhnnÇÓ+ë/´Z-QYY ©T ###ðx¼åpKò1 ©TŠªª*Èår…B½kS P*•022Ò;ÞU?mûŒe2Y»þÃ0 Q]] µZ ‘HÔï}\£Ñ ¶¶ÕÕÕP©T022—Û:÷×|2™¬Kùššš *¥çÔÔÔ€Ãá@ èoÛ‡o§†Ass3ªªª R©Ú=ãîÆÈþ@©T¢ªª uuu`FFFzmhÛ‡oG¾ššƒÊGé ಲ²Ãqª¹¹ÕÕÕP(‹Åížqmm-Ûn~ÆAWÑ}GÀårõÞS Ã@"‘°ò‰D"½1þnÒ3 êêê`llÜ®×ÕÕ¡®®Z­¶Ý3V«Õ¨¬¬Dss3¸\.AÇÈþ í8ÜÜÜ ¡P>¿51ŒV«E}}=jkk;”O£Ñ ²²MMMàñx]Ê'ô®ÝW ¨´6÷'OžDff&Ö®]ËS©T8zô(þ÷¿ÿ¡±±þþþxøá‡H$øöÛoqôèQp¹\Œ3Ï<ó ÌÍÍ!•JñóÏ?ã?þ€V«E`` ž|òÉ~@{üøqüüóÏ(((€‰‰ &Mš„¸¸8XZZB¥RáøñãØ½{7àçç‡U«VaĈ¬|»wïÆßÿÍÊ·fÍXXXÊÊÊðÉ'Ÿ ==¦¦¦˜3g.\ØÎ ¢µZÝ»wcذa˜;w.{¼¥¥?üð8 ÄÓO? @uu5¶nÝŠ´´4cÆŒxðÁ!‰‰‰‰Ø¹s' ààà€+V 22²ß^ …{÷îÅÁƒQYY‰!C†`úôéX¶l8¤R)~üñGìß¿ Ã`ôèÑxòÉ'ÙèŠ555غu+RSSallŒiÓ¦aÉ’%¬|W®\Á7ß|ƒëׯcÈ!x衇0a„~yPn ¹\Ž>ø ,@PP{¼¡¡[¶lArr2Äb1&Mš„‡zb±žžŽ;v //¶¶¶x衇 >ŸßíÙÔÕÕa÷îÝ8}ú4š››1lØ0ÄÅÅ!**Š•ïÃ?DRRÄb1bbb°råJV¾ŒŒ ìØ±¹¹¹°±±ÁC=„˜˜V¾'N`÷îݨ¯¯‡¯¯/V­ZES× P$ 6mÚ„W^yC‡eçääàË/¿Dvv6,--‡É“'C @­VãÔ©Sؽ{7jjjàåå…•+WbôèÑ=#ûƒ’’|üñǸzõ*”J%üüüðÄO°‘žsssYù,,,°lÙ2L™2§OŸÆ®]»P]] OOO¬\¹cÆŒa庥g¤¥¥á·ß~æM›  cîìٳصk***àææ†+V 88\.2™ ûöíÃ/¿üFƒQ£FáñLJ³³3€îÇÈþ )) _ý5 Àãñ‰•+WÂÁÁZ­ñññصkÊÊÊ0lØ0¬\¹ãÆcåûý÷ßñË/¿@­VcäÈ‘xüñÇáââhllÄÖ­[‘˜˜###DGGãá‡î{ùJ¿rãÆ æìÙ³Lll,óâ‹/ê•%$$0'Nd~ù妸¸˜Y»v-³hÑ"¦¥¥…Q«ÕÌöíÛ™9sæ0çÎcRRR˜Å‹3ï½÷£P(˜~ø™:u*sêÔ)&++‹Y¹r%³~ýzF.—÷›lyyyLLL óæ›o2¥¥¥Ì©S§˜iÓ¦1ï¾û.Ã0 “˜˜ÈDEE1?þø#S\\̼üòËÌÂ… YùvìØÁÌž=›‰gRSS™%K–0ï¼ó£P(˜––fÍš5Ìc=Ædee1ÇŽc¦NÊìß¿ŸÑjµ†~¬”P*•L^^óÃ?0aaaÌwß}Ç–i4æÿû3cÆ æÌ™3LFFÇlܸ‘Q(ŒT*eÖ®]Ë<üðÃLFFsòäIfÆŒÌÞ½{FÃ4440S¦LaÞxã ¦¸¸˜Ù¹s'3yòdæêÕ«ý&ß‘#G˜ððpæ‡~`***˜o¿ý–™8q"søðaF£Ñ0ß}÷3mÚ4æôéÓLff&³bÅ æµ×^cär9#“ɘuëÖ1«V­bÒÓÓ™S§N13gÎd~þùgV¾éÓ§37ndŠ‹‹™Ý»w3“'Of233 ýX)mH$LVV³yóffâĉ̹sçØ2¹\Îlܸ‘Y¾|9“’’œ={–™={6³gÏF­V3̼yó˜W^y…)**b~úé'&66–¹rå Ã0]‘ýÅ–-[˜I“&1gÏžeŠŠŠ˜·ß~›™>}:“’’ÂÈåræõ×_g–-[Æ$''3ñññÌœ9s˜Ý»w3jµšijjbæÏŸÏ¬[·Ž),,döîÝËÄÆÆ2‰‰‰ Ã0Lrr2Å|ÿý÷Lqq1³~ýzæþûïïWù(ÝSWWÇ$%%1/¾ø"3sæL¦  €-knnf–,Y¼øâ‹LAAóçŸ2ÑÑÑì÷ ++‹‰ŠŠbvîÜÉ3¯¿þ:3sæL¦©©©Û1²?hlldžzê)&..ŽINNf²³³™gŸ}–Y¼x1S^^Î4773Ë–-cžþyæúõë̘˜˜æìÙ³ Ã0LNNÍ|ýõ×Lqq1óÖ[o13gÎd­V; t1J÷”••1.\`.\Ȭ\¹Rïùܸqƒ‰ŽŽf>ÿüs¦¸¸˜Ù¼y33}út¦²²’a†ùí·ß˜I“&1Çgrrr˜G}”yþùç¹\ÞíÙ3óæÍc^zé%&??ŸILLd,XÀ¬Y³†-ŽŽf>ù䦸¸˜ùàƒ˜iÓ¦1ååå Ã0Ìï¿ÿÎÄÆÆ2ÇŽcrss™Ç{Œyæ™g™LÆÈåræÍ7ßd–.]Ê\¹r…9wî3wî\æÛo¿ísùèÖ~æçŸƇ~ȺCµåäÉ“ðõõÅÌ™3áâ₸¸8455!-- ‰§OŸÆŒ3ÀÀ@,^¼çÏŸGqq1Ž?ލ¨(DEEÁßßK—.Ezz: ûM¶””ØÙÙá‘G““&L˜€… âÔ©S€S§NÁËË ³fÍbå“H$HMM…T*ÅéÓ§1mÚ4Œ?£FÂâÅ‹qñâE”••áúõë¸víâââàïïI“&aܸq8vìT*•¡+å$ vìØÝ»w£¥¥E¯L©TâĉˆÅ„ 0|øp,Y²ÉÉÉ(..Faa!233‡áÇ#::ãÇÇñãÇ!—ËqñâEaéÒ¥pqqÁüùóaccƒøøø~“ïÂ… Çœ9s0dÈ,^¼ãÆÃ©S§ØÕ±˜˜Lœ8X²d RSSQTT„¢¢"¤¥¥!..#FŒ@TT&L˜€ãÇC&“!!!|>Ë–-ƒ‹‹ î¿ÿ~ØÚÚâìÙ³†~¬”6á³Ï>áC‡ T*õÊÊÊÊ€¸¸8"22“'OƉ' ‘H””Fƒ¸¸8 :sçÎ…““NŸ>  ë1²¿8wî-Z„ÈÈH :O=õ¸\.222P^^Ž„„,[¶ £GÆøñãqß}÷áĉhnnÆ•+W R©°|ùr¸ººböìÙpvvfß'Ož„§§'fÏž ,[¶ R©ÉÉɆ~¬”6$''ãÃ?Ä¥K—Ú•¥¥¥¡©© Ë—/‡››fÍšwwwœ8qpúôi¸ººbÞ¼ypqqÁ’%K Ñh””ÔíÙÔÖÖ"++ «W¯ÆèÑ£áëë‹gŸ}YYY¨ªªBzz:wwwÌœ9žžž8~ü8+Ÿ³³3+ßâÅ‹¡Õj‘˜˜µZ= t1J÷>|[¶lé°ß={C† Á‚ àââ‚ÿû¿ÿŸÏGBBàÈ‘#ˆˆˆ@ll,|||°lÙ2äææ"??¿Û1²?ÈË˃J¥Âã?aÕªUì{æìÙ³°³³Ã<ÀÊ' ÙïûÑ£G†I“&ÁÛÛË–-õkןŸÊÊJ\ºt K–,Á˜1c©S§âäÉ“hjjêS¹¨ÁÚÏ<÷ÜsøùçŸ1nܸve))) d]\‡ {{{¤¦¦B&“!77!!!ìùãÆCee%JJJžž®W6jÔ(H¥Ò~$°téR=×­VËú½ëäÓ¹ ¸¸¸`È!HII\.Gvv¶ž ÁÁÁ¨®®Fyy9Š‹‹ÑÒÒ‚ÀÀ@¶<44©©©P«Õý&#¥k,--ñÖ[oaûöíðôôÔ+S©TÈÌÌÔ{ÆcÆŒAcc#ŠŠŠP^^Žºº:Œ;–- Eff& ÒÓÓáää'''€X,ƨQ£””Ôoò >‹-Òs}Q«Õàr¹P«Õíä „D"AQQ***PSS£ç>Ь¬,Èår¤§§ÃÁÁu»‰D ìWù(Ýãçç‡>úï¼ó¬¬¬ôʪªªPVV†ÐÐPöXhh(rrr ‘HpõêUXYYaذa>Ÿ±cDzϸ«1²¿˜4i¦NÊþÏáp R©ÀårQSSƒ’’=ù——‡ææfÖ…ÒÝÝ•/88˜•/55#GŽdåsvv†““S¿ÊGéžèèh|ûí·xöÙgÛ•åææB,ÃËË‹=Š+W® Ï8 fffˆ^0lØ0$%%u;Föb±óçÏ×Ó%84 8®]»¡PooïNåó÷÷‡¹¹9ÀÞÞîîîìdÔ@ÐÅ(ݳbÅ üøã˜1cF»²ÔÔTx{{³ã» ¼¼¼ôÆé¶Ï8 jµׯ_ïvŒì¬­­±dɸºº²Ç´Z-†aåóòò‚µµ5{¾O§òùûûƒa\»v µµµÊG ÖAÇÇëp~mm-LLLØÍýæææ‹Å¨¬¬„F£Acc#ûÈ‹@"‘ ¹¹õõõzevvvP*•hhhè7Ù"##1gÎvðÏÎÎÆï¿ÿŽéÓ§³ò³ò™™™ÁÄÄÊ×ÒÒ‚ææf´´´@©TÂÄÄ„-wttDee%´Zm¿ÉH釧 B‡V«ECCƒÞ3¶··‡B¡@SS¤R)är9LMMÙrGGGTUUA­V£®®B¡Ð°µµEyyy¿É·`Áv V©T8räRRR0mÚ40 Óî{¨“¯±±R©2™¬|ºàMõõõ¬||>vvvý*¥{ºêãr¹R©T¯8::¢¶¶–y<»g™ÇãaÈ!ì3îjŒì/V¯^aƱgvïÞ ¡Pˆ1cÆôH>.—ËÊÇår;”O·çÜÌÌ ¦¦¦´0¸\n§}\§”¶´sttDYY€öÏØÄÄ(//ïvŒì°zõjˆD"0 ƒªª*lÛ¶ AAApttdÛÑ|º¸ÝÉg]ŒÒ=º>Þ™..‹Ù`zb±VVVì8UWW§÷ŒmmmÙ MÝ‘ýA`` –,Y‡­V‹ÂÂB|÷Ýw¬q~³|"‘HO¾ÚÚZ½öÛØØ€aV¾–––åS(}*äqЕA¦Õj;-gÆ Æ\YY¾ÿþ{üý÷ߘ5kzè¡>‘¯»ÏRîîôk4š~oszz:~úé'$%%á±ÇÄ Ú¹@ëèî{8å£ô.wúŒû{œÓh4ˆÇwß}‡ÊÊJ¼òÊ+ðóóëÔý¾íìýÝ ¥÷éîwUn]E"‘àÌ™3ضmlllðúë¯ÃÖÖvÐÈGé}îäw7FöÕÕÕlð¤ñãÇãÉ'Ÿì3ù†ésù¨Á:€àñxl§Ö­R2 ÃFÉår¹zF¥RA,C$±ŸÕ¡V«! Û¥ÍéK†ABB>ÿüs˜˜˜à?ÿù‚‚‚Ø™JÇvêžÊ'‰ ‹!•JÙÙ"ݬ¯Z­†…… qó3V«Õ022‚±±1ûl5 ;;¯R©`nnÎΆêM.— †a ÑhÚ¹eö%J¥‡Æwß}lݺlìê{Èår;”ÏÌÌŒõ¼0´|”;ƒËå²c[Ûgljj >ŸÏ>×¶ÏX­V³Ï¸»1²?H$سgþúë/DEEaÆ ptt@V—»“À-ɧÕjûU>Êqó3Ðî·Õc´Z-4 ,--õÊuô·®¢[}÷Ýw‘——ÇFÀÖE)Öõë»U>Ês;ϘÏçÃÔÔ´Û1²?`¹¹¹Ø²e T*^xáDDD°Þ]ÝÉÇçó{$Ÿ•J“>—º †ŽââbvOfEEêêê0lØ0ˆD"xxx ??Ÿ=?##°µµ…¯¯/®_¿Î–åææB ôk¨øüü|¼ùæ›ÆÖ­[©çV3|øp±A’*++Q]] 777ÁÓÓSO¾ÌÌL˜››ÃÊÊ ŽŽŽ055Eqq1[žššŠaÆÑ\¬w |>>>>zýôêÕ«‰D°±±½½=¬¬¬ôöú¤¥¥ÁÅÅ~~~hhh`]«är9rssáááÑo2œ={Ÿ}öV­Z…7ß|~~~l(|×N¾œœÁÖÖvvv°¶¶Æ7:”Ï××MMMl@6…Bììì~•rgX[[ÃÁÁA¯¤¥¥ÁÉÉ "‘ÞÞÞÉd¨­­@¬¬,öw5Föß|ó Ž9‚·Þz kÖ¬‹‹ ;ÆZ[[ÃÑѱ|ŽŽŽì¾F¹\ŽššdÆ>33SO¾ââbÖ5®ªª UUUìžWÊÀÇÝÝÍѨ#--}Æ(++ƒ\.@Ry•••ÁÃãÛ1²?hnnÆÛo¿ ©TŠ­[·báÂ…zz’›››¶+ùd2â>YZZ p¹Ü¡‹Q€TVV²^S (,,ÔëmŸ±No2dH·cdPZZŠ×_nnnغu+¦L™¢·) UUUH$Hšš7nt*ßõëסÕjáàà+++899u(__OÊPƒu1~üx$&&²ƒ}bb"êëë1~üx˜˜˜ 88ÇŽCSSš››ñ×_Á×מžžˆˆˆÀÉ“'ÑÐЀ––?~öööðóóë—¶kµZ=z|>áááÈÏÏÇÕ«WqõêU\»v•ïÊ•+(--…\.GRRêêê cccŒ7ÇGcc#š››ñ÷ßÃËË îîîðôô„Ž?©TŠºº:œ:u ÑÑѬ>e`cdd„°°0œ8qH$8vì\\\àííaÆÁÅÅGEKK êêêpâÄ L˜0ÆÆÆ EEERRR P(PTT„””Lš4©_Ú¯Ñh°oß>øùùÁÉÉ yyyl/--…@ @xx8Nœ8††V>GGGøúúÂÕÕÆ Ñ#GÐÒÒ‚úúz?~‘‘‘011AHHª««‘œœ …Bâââ~•rç899ÁÇLJ‚D"A}}=Ž;†°°0XXX`ìØ±hnnÆåË—¡P(P^^ŽË—/³Ï¸«1²?P«ÕØ»w/&Nœ.—‹œœ¶×ÕÕ±}ùðáÃH$hhhÀÑ£G KKKŒ3---HHH€B¡@EE.]º„É“'³ò%''£¤¤ …W®\Auu5&NœhèGGé!£F‚F£ÁÅ‹!—ËQ]]øøxöGFF"==7nÜ€B¡@ZZŠ‹‹ÓíÙ±ZZZØþ}õêUÈd26çñùóçÙÉ—³gÏêõᬬ,@¡P ##………l®aCëb”;güøñÈÍÍE^^;q|ýúuÄÆÆ&L˜€S§N¡¾¾---8}ú4,,,0bĈnÇȾ†a\ºt •••ˆEYY™^×É———‡ÜÜ\( äääàÚµkzò>}õõõJ¥8sæ LMM1räH888Àßß_O¾#GŽ $$„ âÔWP—àDTTNž<‰uëÖÁÕÕ)))X¸p!† X²d Ö¯_µkׂÇãáÚµkxóÍ7aaax¯¾ú*^xᘘ˜ ;;/¾øb¿|A²Ú•——‡¬¬,,]ºT¯ÌÉÉ 'OžÄ„ pâÄ ¼òÊ+pssCrr2æÏŸÀâÅ‹Yùø|>®]»†M›6ÁÌÌ fffX¶l6oÞŒÌÌLTWWC(bÖ¬Yt…õ.ÏçcÑ¢El?‹ÅÈÉÉÁ+¯¼Âº®X±o¾ù&²³³Q__µZyóæÏçÃËË S§NÅ–-[pìØ1äää <<\/Úc_ÒÐЀ7n //ÿý·^ÙŒ3ðá‡ê}‘““ƒ—^z‰•oÕªUظq#rrrÐÐÐ¥R‰û￞žž˜6m>øàœ8q999 Á˜1c ýè(=ÄÊÊ ÿú׿ðòË/ãúõëhnn†D"Áš5k  áîîŽY³fáã?F||<òòò0fÌ6Wwcd_S^^ŽÊÊJ|ñÅøâ‹/ôÊÖ­[‡+VàÑGÅË/¿Œ‚‚´´´ ±±O>ù$ŒŒŒàææ†Ù³gãÓO?Źs矟ÀÀ@„……›¦jýúõpwwGJJJ¿ÊG¹s†Šûï¿Û¶mÃ¥K—pãÆ °“ãÆÃ¨Q£°aÃxyy!--MßÄår»#ûš‚‚466â™gžiWöÓO?aôèј?>¶oߎ„„ÁÇÇÑÑѬ|£GÆþóx{{#==sæÌa= ­‹QîœÀÀ@„„„à7Þ€¯¯/2331uêTÖdþüùHNNÆóÏ? deeá©§žbÝÆ»#ûFƒÜÜ\w?&''#GŽDxx8ë%–™™‰)S¦°™æÍ›‡¤¤$<÷Üs°²²Bff&V¯^ͤ?ü0^~ùeA*•¢¾¾?þxŸËÇaú{0ØhŠºÐè™ÑÍfTTT ""îîî¬Ë!Ã0¨¨¨À¹sçÀ0 BCCáââÂ­Å™3g P(Ž¡C‡ö›1§ÕjÑÜÜ̺µ…ÇãÁÖÖ–•/>>eee ƒ‡‡ÛÉun8ñññÐjµ cåZ¿ˆIII°±±AXX,--éÖˆ.ê³H$ÒsaÕÕÕ8{ö,T*ÂÃÃõ\µZ-òòò˜˜KKK„……ÁÚÚš}Æ …©©©ÈÌÌ„¯¯/F ±XÜ/}@£Ñ ¡¡¡Ã4J"‘`5558sæ T*ÂÂÂô¾‡Z­×®]Cbb",,, =ùÒÒÒ‘‘Œ3¦ßä£ÜJ¥ÍÍÍ033cÇh€ôñüü|\¾|¦¦¦ …û •J%222šš ÃØØ§Û1²¯Q«Õ¬»ò͘™™ÁØØ ÃàúõëHHH€‰‰ BCCaoo¯'_ff&RRRàîîŽqãÆµ“ïܹs(--Ehh(<==ûM>Ê­¡‹jaa¡·?M¥R!++ )))pqqAXX˜Þ3–Éd¸páŠŠŠ …B¶¼«1²¯‘Éd¦ß°¶¶†@ ГÏÙÙaaa011Ñ“ïâÅ‹(,,DPP|||`ddÄ–R£ÜÍÍÍP«Õzº$Ã0ËåHHHÀõë×1zôhøûûë=ㆆœ:u R©ááápuue¿#Ý‘}‰.º»T*í°|È!¬|—/_f'ôäkllÄÉ“';•¯   ‹Å ëù¨ÁJ¡P( …B¡P(” ÝÃJ¡P( …B¡P(” 5X)·ŒV«…Z­î÷œRJAû8e°£K9CóCR+t§ vt)iî…>N VÊ-“““ƒW_}U/ì;…2˜8yò$6oÞÜé^' ån§¾¾¯¾ú*ÒÒÒ Ý ¥O¸zõ*^{í5TUUº)JŸpâÄ lÞ¼ÍÍ͆nJŸC VÊ-ÓÐЀ„„„N7uS(w;åååHIIaóER(ƒ ¥R‰Ë—/³9S)”ÁÕU(ƒ²²2¤¦¦Þº 5X) …B¡P( …2 ¡yXûˆ’’ÄÇÇÃÃÃýõ$ üüü0cÆ \¾|§OŸÇÔ)S0qâD‚;®S­VãÔ©SlhêƒB¥RaìØ±˜9sfŸå9“Ëåøûï¿!•J±`Á½”ÁKbb"***`llŒ'N@­Vcüøñ Áþýû‘““Ì›7¯×r‰J¥R:t~~~ÈËËùsç 0qâDLš4©Ïú^CCþøã888`êÔ©ýy›)B¥Ráøñã055EUU.^¼@€yóæÁÎÎ?ýôª««accƒ¸¸88;;÷J½ 8tèBBBð÷ߣ  &&&˜5k‚‚‚Ø4_}!oBBrss1kÖ,ØÙÙõçí¦€––:t^^^HHH@^^ììì0wî\´´´àÀhnn†‡‡âââ`jjÚ+õàòåË1bþüóOTWWÃÊÊ qqqpqqé³ôr¹ýõär9,XÐ+ze`SWW‡Ã‡cĈ8pààááY³f!''LJJ¥Bdd$¦OŸÞk)¶tºŠ¿¿?²³³qáÂ…BLœ8±±±}¦«Ô××cÿþýprrÂ}÷Ýן·ºÏ¡kQRR‚O?ýÆ CHH´Z->þøcüõ×_°´´DPP±aÃìܹ>>>w\§F£ÁÉ“'‘ŸŸkkk >øðÃÑÔÔ„ÿûß½.§B¡Àž={ð믿⥗^ÒËÕFÜ$%%á×_…››F…ììllÚ´ Æ ƒ¼½½ñçŸâüùó8zôh¯Ô)•J±oß>ØÙÙÁÛÛ999ذaÌÌÌÙërÖ××ã£>BFFÞ|óÍþ¾Í¡R©pôèQ\»v žžžðôôĹsçðÜsÏÁÆÆ¡¡¡prr¾}ûPWW‡÷ß¿WêmhhÀ·ß~‹Ã‡ÃÇLJ­÷ÕW_Å—_~ 77·>‘÷È‘#ؼy3žxâ‰>›Ü¤ ,$ ~úé'ÀÈ‘#áîîŽ_ýgΜ±±1ÂÃáÕj±k×.˜˜˜à¡‡ê•zoܸ¯¾ú ÎÎÎ>|8†Š#GŽ ¸¸o½õlllz]V…BÝ»wcß¾}xùå—i^Ô{„úúz|ñÅpttDDD„B!vìØcÇŽÁÔÔ!!!ÈËËÃÛo¿ {{{DDDôJ½R©¿ýö„B!ìííáííÍî©677ïµzn–õÃ?Dvvö ÔU¨uч466båÊ•ˆ…D"AUUJJccáe ZIDATJ°nÝ:¸»»cîܹ˜2e 233;4X+++¡R©:¼¶©©),--;,«¯¯Ço¼///¨ÕjTUUáêÕ«ž«R©PSSFÓ®ŒÃáÀÒÒ&&&íŽs8Èd2ìÚµ ¿þú+^{í5„‡‡÷Ùì?e`RSSƒ;wÂÑÑåååXµjñÒK/ÁÒÒxæ™gPPPwww½ÏÞNßHT<###¼øâ‹°··GYYJJJ››Û¡Á*•JQ__ßa=›v³º~ÜÜÜŒO?ý¥¥¥Ø¼y3\]] }Ë)ýŒ±±1Ö¯_kkkÄÆÆbÞ¼yX°`ž|òIp8ðx<;v UUU°··×û¬L&C]]]‡}ËåÂÆÆ¦Ãý¦¦&DEEá…^€P(DHH6lØ€¢¢¢ ÖÆÆÆNƒnðù|ØÛÛw86s¹\¨Õjüý÷ßøè£°jÕ*Ì›7N<ÞCh4Œ9/¾ø"Äb1¬­­±qãF|ñÅˆŠŠ‚F£AEE®\¹‚… ¶“›šš: N×Uß+++ÃêÕ«1{ölp¹\xyyáóÏ?G}}}‡kuu5 E‡õˆÅâ?ÓVWÙ¹s'~ÿýwlذ¡¡¡TW¹‡hiiÁœ9s°dɨÕj477ãäÉ“xã7àïï™L†É“'ãÊ•+’555Ëå^[$ÁÖÖ¶Ã2F±XŒ_|vvv(--EII òòòÚÕ£ÑhP]] µZÝáµ,,,`ffÖ766âÓO?EEEÞ{ï½A©«Ð·RbccOOOp¹\˜››ÃÑÑ*•ŠUÜÍÌÌàääÔi}ûí·qãÆËfΜ‰G}´Ã2///x{{<<<——×á¹eeexýõ×Q[[Û®ÌÈÈ?þ8¢££õŽë”™_~ùû÷ïÇ”)SLg,ïA†ʺB:;;ÃÔÔ~~~ìdÊ!C`iiÙáÄKUUþóŸÿtôE à±ÇÃäɓەq8Œ;–5ÌÍÍáààÐiX÷ääd|òÉ'¾p¬¬¬°~ýzxyyé …hiiÁ§Ÿ~Šƒbݺu}¶²EØx{{³Ê°nb188˜]]]Áçó;œxIMMÅÇÜaÐ ¬[·~~~íÊt«[:cÖÑѱKwÌC‡±+e7ãììŒ-[¶@$éçr¹8wîN:GGG̘1ƒ«÷|>066ÐÚÇCBBÀãñÀãñàææ†ÒÒÒÇØ#GŽ`Ïž=^ÛÉÉ ï¿ÿ~‡ÖÖÖzß#OOOp8œNÇñÏ?ÿÉÉÉ–EDD`íÚµÊ?ýôöïßéÓ§cìØ±TW¹Ç077‡ŸŸÛŸ‡ 333 ã­««k§ºø—_~‰Ë—/wX6nÜ8¬_¿¾Ã2.—‹±cDzÛ+ºÒU$ 6nÜˆŠŠŠve=ôæÍ›×®L(¢¹¹Ÿ|ò >ŒW_}uÐê*ôÍ4€ù÷¿ÿ ™LÖaYWû‹nž±ïJ±··Ç³Ï>Û¡AÁår1tèÐvǵZ-är9Ο?¹sçâðáÃÎLQ(accƒgŸ}¶Ãèv\....~ŽÃáèõqÝ*Wgà•W^éРprrjw\«Õ¢°°sçÎÅ÷ß)S¦tx.…Ò~~~xùå—;ì{|>¿Ãñ +ÿm÷×q¹Ü.W„¢££;4|²ÐÑ~)†a ÕjqüøqÌœ9‡Æþýû±råJCß6Ê]Ddd$<==;,322j7Q¢C èõéî&J–-[†9sætXÖ™·™V«…T*ÅÅ‹1oÞ<>|sçÎEhh¨¡oå.bñâŘ1cF‡e]mŸèHWél711ÁÓO?Ý©Agº‡V«Å7  1{öl|÷Ýw˜Ÿàà`ÖèS(prrˆ#n…BQ£FÁÁÁ¡Ý5tû?:úéìK¢R©0tèP½ýL …öööð÷÷ow>—Ëí´‘HÔá ¤F£@ @PPŒÁårµZ ##£A»á›¢R©„ ÆŽË“J¥>|8¡N£Ñ€Ëåvhäq¹Ü.ûxG+õºU!½¼—º•¢Žö½òx¼.ûxGîðJ¥–––5j„B!ŒŒŒàãã¹\š£ò@××ÜÜÜØ v Ž+++­«ñ£Gn·Šy;}O«ÕB«ÕbôèѰ¶¶fÛ¢V«1|øpöX[ø|~§uèòrwTZ­Æ˜1c`cc.— ¨T*hµZö=E¼´íWº=oºUÉÈÈHv V(ptt„¿¿»qùvúžF£‘‘‚ƒƒYE\«Õ‚aŒ=ºC%[(vZOg2é*þþþP«Õ‰D6l˜¡¥Ñõ«   v¿©J¥‚••‚‚‚Øó¤R)üüü:Ô_o§ïéÆ×¶ºŠîâééÙ.o·n{Þ­èCÑU¬¬¬0räH¶>>>Éd°³³TÛ;8LgKk …B¡P( …B¡šˆŠB¡P( …B¡P(j°R( …B¡P( e@B V …B¡P( …B¡ H¨ÁJ¡P( …B¡P(” 5X) …B¡P( …2 ù/P1~¸© X%tEXtdate:create2020-10-09T19:38:13+00:00Ùm„%tEXtdate:modify2020-10-09T19:38:13+00:00¨0<¾"tEXtpdf:HiResBoundingBox1396x1123+0+0x{JXtEXtpdf:VersionPDF-1.7½8;í(tEXtxmp:CreateDate2020-10-09T14:37:14-05:00‚SX6tEXtxmp:CreatorToolGL2PS 1.3.9, (C) 1999-2015 C. GeuzaineÛ©AJ(tEXtxmp:ModifyDate2020-10-09T14:37:14-05:006­d<IEND®B`‚blis-0.9.0/docs/graphs/large/l3_perf_zen_jc1ic8jr4_nt32.pdf000066400000000000000000001047331422157504600233250ustar00rootroot00000000000000%PDF-1.4 %ª«¬­ 1 0 obj << /Producer (Apache FOP Version 2.3.0-SNAPSHOT: PDFDocumentGraphics2D) /CreationDate (D:20190328152847-05'00') >> endobj 2 0 obj << /Length 3 0 R /Filter /FlateDecode >> stream xœÌ½K¯fKrž7ï_QC{Лy¿ <°‘°L´IÀA#ªÙ²¥CZM†ýëý¾k­ŒÈÜ眮j®>ÕU_Ö÷­Ì\‘OfÆõ¿ý&~ ø¿åÿô™¾ýÃO¿ 1Uùtý ÿ·ß´8ñAêC>ã_ë(µ‹¥|ËM¾‹ÏúMÌeâÿUÿCŒøsX`ÓþÍÿñ›ÂÓ¿ÿ•|¶þñ~÷íó¿ýqOü×û…Øë·”+úŸK’?ýWùSo åÿù7ôcúÐví÷¿ùÿÿè?ý&}ûwxÞÿ…¦VêÈùÛÿó›¾ýûOŸýw/=Ãøi 짤ŒOð__ÃÚ>Ê9‡âÈoua4<"ç’k¼»à?z¿ vÈ2éþ“Ž?Ï9Gì_1Ú÷ÉÑ¿øËø-¶ràïÿÝÑgýþºU{úˆ±¶ž:¾ZÓø¹ç‘ŠäßüýÂËoSü¨øõoÿÓ·ÿð?$Ìüÿøí?~ûû÷›û÷2ô_Öd×ZŠaÌò=Ï*dzÞZ»$Þx›7^^»v4m È»Hг}„4Kóx²k{± µ„:FJ-]°m/v!Ž€§äüÉ,ض÷†‰åÜñyj{lÓû>rÂs[}SôøÀMôÜ“¿@ô¤ ^ô|Þ=é‚=ß…÷EOˆæDÏõà3Ñûõý"N?pè)Îù )î!rHwHùmøò_êß~»hzbÿE 8‹•QRDg¾q¥æšs:§´áªöä¯þò¯ÿæoÿî/þáŸÿð»£KöÜô‹3Ðk”CX­|+çÐØ{kõœ‚ÌcÌo‹>û_~ÿ»Ÿ~úþsŒ_€ágÙ?Ð'LCËEÎÆ˜£ Ö v?ZG[jã[J‰çæ¯rqTüKÌhÁ”¦0p>k=àX&møÉÆén˜‰Ó'V Û&~ròq“›â.ÊfmÃo²+XþxÑ /¦áïEÛð›ƒÏméc⥵N,¥?:»‚•ñWeÎXš´á'+~²×†UŠŸì¡¶:¤ ¿Èžd< ÇÆÐk…ìKSÄ/òðXy«LõçÜšJ“_ŒøÅq]À¦ì#‚WÒéŒÏ¾Ý>jh˜Í,ßÃ#:{RpÇ"þH“‰¡KqÏW†8|a ~‘=Ix¯x·¡å\K‘§AH:ßÎ@§c® ó\GÓ6ü"{R#æ$㨎¹lA~2ã'ùvØ"~JPâdž%B¨•**o üäš°Ä·S!5]Ú¸,ù¸že×Èœp¼¶Aè_OÏÜmÐMÌVÖÑUü$»’1µœÌN(3ÈOÖÁ“<ˆ‡s*\žø°á·naåoÕÚ2z!_hø±[XcÀ«ÆÇ&*Üðcâ˜c¦´V¼Š&_ëøIüe@žÐT?&fâ$’ÕëÇ%XüZ׈1GiÃOòÍŒZÈ”\ˆ t:d¬›ñkàмyiÃoÞÒJød¼ãy} ?ù+¾Ö@(ü–| ëfÜ“Á͵4–Mâ¤`—“@Fj–kBª©ýÞÍÑÉ[‹¹sà˜èHÄðþ]€ìÇÒ„_ä{™_Ãþ!ÿ ´gm£)—Þ{¡ËX6óV»…VÀiÃOÞÂ: ä‹hˆV(C^Ú#«øI®¶>±j&§„Ël —¾1äiX4I~°Ïo³sŽ;¶m¿DGð¥ú '¹‚ùMSœ±f&Þ äJ¾„õ™„Hš*Ηœ¢ ïï·fiÂïÝrŠßÃ¥·uéRa88%AjêwÝç•öÿûEiÀ¸-R§Ô'¨I@¬Ü’Ç jÒˆÞçƒÔ86Ðݼ“Z¨‡ßàûNêÄʼnM'¾“:Q@€¶¢ô¤ÆDb¿ë¤t ó†;<`©Èr¨fÇðI‰ù`5úU°¶»BСzŽ+Hý@uÅÙ)ÌVæ…q‹êš?&6£ô7ªkA&Ÿº‡ Õx\¢@ë=ųzžØNK•£³guÇÀ1«(;X=2N_w|°š‡áPS˜ú8Çj|-u¼æ¤`u¬†p óp²:øâÅqÇêÂß,øk9a1tt‹¤-XãC¬'íh¬ù…PñÒj<` ˜XªAW¯‡5k L„>ÈÑ:ËqS™ÚAk,‘p§ähÍ Î8mh_­±éÍQF˜cì´– /© $=­³;¢.kt`Äõ€56ô\°kÍ­ñ ÑÁªšskL:úˆ•öÑÓ_+¥å2_ŽÖ¥LÜPZWr9Zî矬Gk>Žj>îÀ5ÆMµ;zÜw\£¯ÒŠ÷Sv^ó`ÂޭóÀŽ ð „R˜[dã¤òÑ9ž"g8Çl¬!Pëtä´C›‡8ÜϰÐEäâ‹· Õ¾ÛñÁöø–¿¥où;ÈÑå0¹µäÆš<Þ“Ü9$¬—žãIn µbÒçgäÎØÿ*~´glb¨ÀBˆå3rcFñt‘xrcQ¶ ]'iGn¼õ‰—¦§^ c÷1ÛAîŽË\ÇÞ^äÝyr7–A_ÈS=ÈÕ5pÂÊAnÌ&ðpô¸“¢BÝ J:È­àËvîÉ=¸(Û³˜=¹Ï€hŠŸ wVF¼ºéÐÝæ/GxÈyÌ&±`±Lå¥{t¯è'zuè«KÃYjê9Ö¡ÿ(Ä"ѱ+º nXa¸ä•ÏÐ]°­†¨[™G7¯ñ@7$‡‚\SšºÑ†õX¨Å?ÐÍ‹i´ƒÝ7ùÜ1>=ûƒv€@`×÷ºx™¿·ÇîJIÏç´³{?~¯4ăÝ«{ö+v±yyŽ<{ã)¥ª[ Öù¼†µ}ôº¯L ‡»ÎöÑë]pC–I÷Ÿ¼î®ã¬o=ü¢»ÎanK“×ï‰ãÝ/ûçdb~pOâŽøçãž³Öê…WÞ^K ïy™ÑP}mIï"h÷‘°Oþ ‰y¸çø.|Ä<Üs|¾ÀGbîî9®ï»çX ªIóEÑã7ÑsOþÑ“.xÑó]x_ô¤ ^ô|Þ=!š=׃rÏÁ…&á¢Ç;J{Í=Ç?ä-÷ÿ”·ÜsÜSÞrÏqù!÷œ_ñ~É¢X¸Y¥ñ+Î/Á:¿üËÿûžóKž»óK‹ ÷i9§™ÏtòI³Ë=¿Pkrß•©&™4P¥Ñ¥ ¿ùÜ•'îé•¡&ªBµÉsWæàÄdW¨5y®Ê¸ÿâBš.‡šó ú¥÷o‚§$«ÜÉ¢À#‹Z¡$«ÜÁÂÅÅ.R!mF¹# Ä8°¥Èã¨5y®Ê‰ë½åÚÅGÒð\•ñ¦Âˆ…v6iå¹*ÓCTk})øÍçªLCî÷%Šf¤£Ü¡6'A¸»Ü Kqþ/m“š@AÝü_JE'‡¡KµÊ4?FŒaѰCh뺮ÊiŠûLb) ¿ù\•é#þ;â|R¨oùÂlÜN¼¯Nn¼Ä„U"Ú'ÏmLr™½]Z+Çmê·AíÌÕÛ‰Î^2TFÛÁMuzÎŒMå÷ìâ¶Ò nì}$|O¹àÀ-^-=MŸ7¹“ˆšÞpóM…Ž÷3nãìZ°àüšnWžÇ°xFk·i×¢ ½+Ù,·ñ Üíwà¹] â.3šç6Nfx#WY<žÛ8ˆ^ûõï¹Í•”#eŸã6¾‡Ï³)wnZMËí{ãÁMåuÔc;Á-N4ãvžðàî̤¯§nò nšu î¤'n|»%ºjŠûI †z©zpÓ‹aô†ÕÜÉÄy)¸±õãËáÁ™C'[Uè9nC0 XY Ò°T#Á=eþ=·yEˆ8Øt±G:nWºàòdSOnWž•FhaƃÛ4hcN Šùà6·âN«ÃÕf¹ YëáÞŸnÚ§$\^·ç6ýað›i”ƒÛ… ÉÎI9¹Mw„ú(å=·éÔg¥?íÁíLLÑÀ4ËÁmѦ6©ÜÆX±øqK¬7Ú°…pCN¸Ée¸q‰óòyÑ º¡›ÖÁ©þ¶ºNXIQH9tãPÚ1©QÀžÜ‰Þ ØßûqâNQβ@›ØEü‘'õ†—ÑÕÍÛ‘'UF.„ŽÜƒ¯‡&{цxrÓ‡"Š=·ï䞸anè_<ÈM÷t’æþÝRÔjÑm›á<Dݲ¸GûàᘞÆ;¸iÒÂf€y;Á=ä€ y·±aA û}!ò܆TâÜCn<¸ÍÛKÅšNâ»¶q¿YÑa5…{nctrC9°-n˜‰^2óÄ6§oc¦z`m&àt¦…m0•¶?z¯ØFNü@‚¾‡m¾Ü…¸Ø¼ A^Õ'Âcエ@2ÅÐê±=x†ÇŒ =L8lÓä†ÏmzÈÎ>.˧çöä÷Ç©ôrܦÛ@rŽ;·'áÈ‘ønyn³-ã)Cl·žÛŒð€˜1(zlC‚BÆ™õXxåýd ðÞj5£ÑHwÙ“Þ…ÐfÑrOþ‹–tÁ[´|Þ·hI¼EËwá}‹–H¯³h¹¼oLµþ%ÆT>p=÷ä/=é‚=ß…÷EOºàEÏwá}Ñ¢9Ñs=ø!c*NŸ;„Ü_3¦ú‡¼eLõOy˘êžò–1Õ=ä c*c±èŸBÃ…ì­©)ykêþË[ÖÔF Î!¸c5ð¬ÐÃ9*²Ó¤M+ßb*]=œ[R_ùÈJ­<ÆÑqѯҶiåCÅÝ«ŠN»e§•/Œöi1ˆ‚¶eõ•ïTü±MÿÜ’ZvZyÜÌ&ÄlŠºQmi½ër7Çe·?¡k•ò¸7Lš:%7ªMôªNÐXÇ¡‰} U«Úi ïĬ5‰hU]å•@¥}P}^5B«ê*¯c¡A¸´®~έ9­î¸çÆ ê¾ê°Í`&p抰½°Íéå±¥Û ÐÀ×3nwŒ ½ %ØîYÖwÒèYí–@Ç ¤çy`[‚˜0™ê@â±ÍÓdéƒi„l ”ð/‡èÝ·¨1ŠYw Çm|­wBO"‡<·Å<Ûâ m²/Ûí<¨ ‘ŸtkÚG‡í"G6Ð%ÔÆ™?3͵¹{Oy'µ ðÛªÆ nÔÆÓ%„jÓÆ: dI۵цW²êø=µy Àîžf< ]$ '2ÐÆY! \üò8¡ÍPÓÎg•=í"Sfèâ\ŽèKªß©cýnCêÁí)£#ÜÎÌŠRrC‹ç6}gÊchñÜο9™œ«ÜNÌø…ݸå“ÛL³5θ%ܦ%V7î¨uç67á…ò×q;NZL›ncâŃÛ¬¤Övêâ¸M÷ŸÆF=¬:nӳޗ¸.ÊÏmzÏaÜ#¦¼s›® è@¸Ü·Å0MËbš;·ÝŠ%’ZI·¹ 2Â4å:vn³-50ãqÞæã°Awn³­ktíŽmŽnÒõLŸf©Íµãídu.sØæ/ªç¬(ÖÛ?œÒÔé°›žSæevvØNLÞ… 'ª/‘ã6û‡3§ë\f¹Íça¼]¥Û|³CµÏ:nóy³í(ïÜæ 13cèAÃr›]¡™Òqp[Ú*h©‹mÊzƒ?˽ˑ›_ÃÉ%2³ÆNnŽ.plž ¹9,ÛêNnI:¹hö GnyA»ª]±äæ„ñÅż·ù0¼ÕV5@Ö[<èò•É›m‘~Y·@ î$ÙÎè"\pä–ðuõi<Èèʇuݪ¹™yfº¾VKnÑ$Œüô“:Y¦`¨¦ÍúnSêIßÂmJˆªeŸØü¢1õÓ§¿¡Ä¼Æñ“Ú+¡ïƒ7§n½nËœ¥îæÔí£×»à†,³î?yÝœê,ðŸüˆ9•¹4±s°dƒ¨þß4§2Ë#öÄÎä5ßeº}ÛœºÖë†W2{‡gù¼¼^ÍxêWT‡8d9«–{òXµ¤ Þªå»ð¾UKºà­Z¾ ï[µD~UËõà}ƒª‘q è+,ªòÄMøÜ£¿¢rôÁKŸïÔ.>xñó}ø‚Ú‚5'® ?dUÅGt0µ2×ì[fÕí)oÙU·Ç¼eXõy˲êŸò†iÂÅ\P¸+Î_IÒžºµ¬þ÷?¼§:×é,«Ì9••¶%ì–Õ‚[› f _Wg…˜à7vmëÞ²Š3Þ/¬£oY–Øä–8j±–ÕÀ|O¥iØåsœe5Vf{â}u´à «“‹)KfÀÑŠ5¬2*6ÜAr´ «•%èf)…=B•á,˜â*mÅZVÇG§v¥Ê97NcYeª,…¤Y©pÑ·–UÚ†1™AnºckYmâÌß5Q;cž˜Oª2œ\ýèãýh=™ûíÉý;˜ {™VûÇ­öYµ­}™xy¼gK7'/«KëÉ4âL1./o†bM«å£2²¾¼º5­Ò‡¼…^%¾gRùð\ž)qwîxµkZ-2Ö2D1cÓ*#$iÝÉ›)XÓ*Ë ¤r%埴>:z±ƒâÛU”Q“‹êQÒ3jx5hR!¹l«‰jG}f»1$±íà ×"÷SâÏn%=3ÐÍTkSÎÄêYJzæð£Ç½¼Ò‰©{tôôJ‘6mêFG3^Æ"Êã y2¦UF40†8h[1ZzÑM²&˜(è0×FK) ë[ñM†n?Kw5< F‰ ˜b=¸–Ý$¹Äé|¶n´ô‘ìT¸«õ`´ôÔ2Ï`Ö¹ÄÚY¶UÚB ò Ä0uË+v’B aP-=-A‚S“}w2/ß#¯“™ª-]ÝF©RyÌàDÑüO’â‘× ©¸s‚ |Û†©RgZÇÔì«´QÓ3ñ}¦JÞ‚žZÄÙrlùû®Dßi\ÝÀM…ÁÀy¨ÔÜLˆ¼’ãnàÔ1'šGuã63RÆõœÜf,îŒÜ)ËÉmV™@_T‰í¸M}Û,™_͸™ê½‚NMsÇ:pÓFð#©ÌƒÛ“Rê+à¹ÍøŠqMÊÎm¾át©Âs›‰2ƒD•ØC´÷WÉm†y5FÉñØf|E™+;¶X"`â±=%:¬È_vl3LJs ŸØÆ©’МážÚô<ÊÌBhS”Ó8æ¡Íˆ¦Ô3sÐfêâBócŽ ÚCc–‡6C§˜÷[íÚܤsd¿x@›!)“¾ý„6 ·ð,®!öÚ8©W¬Þdö=´Ù–€ì*ÚhíŽu:c'Óï¨ÝYÖ"±6ÁíÎt­¯LŽžÚ´±Ô 0k/µ;­M|I"®žÚL»˜J¼úAí.¦'ü±×ƒÚޱF5ÿxlwJs2ÆÛ…Œ:ÃÁ6h·ù¡RrþðÐf¦mì~CÏ4ÚT»'yžÌnô•Ñ(ôƒÙœ¼&ó ̦{mýE ØžÙ˜œñÂ%ׇgv£KãÃæƒìÆ mäl¼£z·+ý´ú8©lIOmêYLF6Û¸·`ó Ê'm¶ôg {hs­3ÝöíÈ Ø].®YhG)i1ù€6NÀyÃb¯;µ%s| ‹šœ¾µiêL_Nj‹m¥qŸP{Ò@ Ö++-¶¹¹4ÜOX1àÄ6~ä*£pbr!ß;Åv’4аvž¶ù5Œi=NlóRöÔfþn¼»¢ëÇc›ù0èµ£Ç=Çmf Æo^K· Z1Ô|¶™ï5ë{ýŠR-8©†®+Õs›·ˆ¤×ÃÛxm™‘Óã<â’èÁͼyÞ~“ÜCSâw]ܤÙÀå·¤Ü,äRèÖsµYps çqÆô༟à绘r=¸ÙO¬%Ü•æŽnºpážQËyÜ&ªq¯E_ž#77r%ÊuÃrèFOh¾Žš[Ý£m²ø“JžC7¶ºŽ=ijån¦Ê÷¨/Ý¡{HXý¼bR•ÝŒ2Çi"‡G)+¥óxzíDé<¦õ×Ì6Ü?+Ï9ø<ÐunÓÊ„o—Bæßüõÿòw¯yº':”ˆhËÓfâL —Àµˆ3fÆ6=ÊÇ?~œâ™ÁwA‹Ÿçßüß¿û§ó×ÿó÷õ{ýDí˜yÝÊ¡íƒvm?0j\ „L_å3êûþþwÿôCCþN/+7jºUñ pÙGmÛ~`ÔƒHï,ãP~Ôÿþýëé?mÌgèÎâuqc¶m?à2Iy¼äð£>üc×›z}Õiâóç¿c¥¨·ÛÄ3ºWž#yßð_bHÄ5´í³×½¢”­aÙ7ŸNøÏ¾ vÔ:õþ£×'ü˜¯.¸Ž.õdÍÒ}3ý‹›î›Î=WÖrÍ4/´?'g »Žd¼òFoJ¼¾ŽÝˆª${.wð¹µý³¿Äª]ŸŠ­_aÖ®‡WÅÖ‰¯°k×ݯÂ÷á +¬´Ç)UÙk ¯ ¡&ÆõBèžýB(Ø„Ðwâ „ð1d!ôø!Èy!t}ø!ïŠÖ2íM—ãR_ó®Øžò–wÅö˜·¼+ücÞò®ðOyû¢SVÊ,¥´ø+îÅ:WüËkÎÀj—”„R.‰ê^œÝdnÿ!ˆ½˜V:t7õi@£Sø²ÞWè#&uýn»ƒÅ q¨þ<¦EÅN¼‚.¨ .@%•$&¤¾]c[Är»¬—½ûœ²©IÁoýæ0^Œ¸.¬°*ö?´1ZÐbŒ/j]ÑnµÁŒBï!kr€HKš‰k  -]½é]*À]+v8º¾Ô¡ßbߺ~bCKOF©8¸ü/ÄÛ&÷ÑuêÆæÁ¤t§Fñ‚º…X¢‚˜žPËûJjÁ'SøüÉIA9­VX" êU0Ò!k>BL®0¼ŽƒŽ\ù‘ajé&ƒÅ—Š‰Ï­F1áKQø´¼0* Ðb%ÍKù‘b jf¸NÖÆþÑ)Lûñ>FºõOË)fë3ÆcÉÑÑ*+m6ÆGª<pØ?a<1/j'ñŒ×Àt©œq0ž6³žsÆÁx:r$ÖóÆÏ‰FÚÆb;ÏB À O98ÁΪË'ãeGǼ– Žñ<éeúB¤t2žî‚ŒYV§‡ñ“ MWõ€¼dö¬·;ÚùYYØ“›xB^Ù“?dƒ=cÁ¥vEúô zŸ,?\>ýø I½Vˆýñvùžl ŸU*æb.-è§8ÍŽ¯Ì‘ž_ÁÆÐ®o8ÐóY,Ã2æ'çyú.ªgì'çy©$ˆùÈJOúÁ:Â Š®'è!F8Ͷy½ ÏyæÓXýäü¤"xØ/ÑpœçžËòNZàbýd ¼Ã\>= SHûýÐ3‹ öÞ¦¹±6Ð3'=ŽW`ö' ç_FõštËyæ‘oývAß8Ïí<ë9Ñs^ŽL ¥ðœgЇÀÊRŸqž.F‰I…ó'¤"ñX“%Ÿ¤§3s‡õòÉ‘žµÊqøÂ­#ýdI—'û×÷[…M¶ü$Å¢µ¨ÿtMZõO/Ù„?yú+ªÕk?™±½ñœ”5ÿv_Û>ª¢Î•ê/ua˜bÆWüGïwÁY§}ûh¬‚ª_0 WüGŸtáW5¶ô²–vrm¢’€¥w° û©KÿSí¿ø¸‰cà6óÏzÝþûˆö¢Ã+…x/"¼½fíxÚrxF8óö‘Yåx²m{¯ ™%XÚÀ‘3ä½ ®íÅ.°JSe‘É>.ض» GàžxÐ=º`ÛÞò°¸üžðɽðù'¿/|ìÂ&|® _ |Ò/|¾ ï ŸtÁ ŸïÂgÂ÷뻆¦T©‚ÍŒ0¨8’Üãþ½þ!MêËv–>;üfÍCêŸô<"£°¨Þ¿¢AÙ?EC‰™¦ù— ½ñO ])#Á<çëçŒÖâªFKQô®j¿ ô 祭û­1-¯®ØC¦iÔD[Ãâ]8•ÙOóyÃÿTíÊ_ýå_ÿÍßþÝ_üÃ?ÿáwGŸ¬ûÜ/Îóñø•ï‹»nbµÉÉÌãÑÙ&QÿO¿ÿÝ{¡þ¢@½+Ž•ÊR£ô·Ë²!“Ö‘eáZ7Å랇:Æ0°Bp•ºäl•ˆ<Þh™Å¹Hb²U%#Ã(Yä«á*Œû<^âÒÌLÍê8¦ŸYç.õR.›ç4Y3ƒ0hÒl’°í.8–Kµy7iÌx¢2kÊå^~Sô;WÁ1ˆcéBÔUZO:‘Ì#š++)¦z£Ù…ÁGâLJb¡µ+¦!S >ÒÍ“ÑM³†¡¹O™p²³+§ï\!6Ì‚©Zdfd¼+äef›dÀèèú5“ÔQºÙj»Ê‚2EòS"/3é,1iÆ”MVG¶UùPÓ9\C€xºSã.ÐDû‘˜±”}Èç’Æô»pb¿g®²«–ŠæsœÚ¥ú™j:âµ2ðìX5Åñ2I`%àAMژБ_H¸øCæ(;©™âx™C/évJÍ$tÌ©³ _Ÿš)­âx™¹Î3'9[S7 3Ñ1ך²8u“Ï13‘(å»^m¦6ž|-OÈ…èŸÓ0ùs‚å%hª×4Lm<¶Å¸Du˜„ŽlTˆˆ1ÍUÇ>BGÎ"Ôó­!:)ÝL“€¼.3èú.åÈdªeùæ`Ò9f¦æ§v+‹A#3»ã-§¬ƒºN9šlŽüÅÚž_dfÌGL©îÌ’‘µJ›IçÈ—£¹#Äš™¢õ®äÈïij Ìɤs¤DÆÂ je¦[•™¸Òx9ðqúæ]Ê‘0°€\¬#¾Î»zúÈRõ‘V¬^\èS’ð'9ÈPÑÎ3ÛwyÇ}¯aÙã:ñ¨®+~ÇuÉDÃ=lëL%÷#°ž×R3±'êF³U¿áãX]Ûϳ ”¶šÞŘãa]™€þ™FëÊD÷8hŽéÖ,ʽXgi]°'²~nÚžÖ•W‹È­´¸Æ÷b{ÖµÇ5볯=Øãšö¢u¶ó¸få™5û×[ÖÛ‰êñåq]•¹ò\·Ñz\3…;Cû•1‚kt!¨Cuú^\§}Ø›3v¿…ƒØ´ãÿÌ›«¹?PðÄÎL#oðÄΙ°*SSŒxb'÷ö6bÙˆk“ì*±-0±ñf¯Î}Ìý„ÍÄ+©Ü/ïÀ¶=Aùö`!‰{¯õ'ì*‰'ÎÃufíÝ8Õ]Þ®ÿݳݸÃ5HkW߈ݘbëٱ韭ߟ±çÉ€5ÍUáÏØtMîØ>ÔÞéÏØ´‚-Q߈ͪ"ëÜèˆ ‰J8~ßÇ[Ol)ÉñlÃJìž~þŒÝ èZÖ9ÚSŸJ_¤·ÄÆü§¶íˆÍÜh*¬'±ó² _žØÌ鵰片»L9pì.ŽÜt;Jφܒ“emVŽÜœ²¥ ô䯮ˆ_|åÈM—Ž^h·dÅÀA›pù¡Ômz¬'yh9+_g ÚÕ¾¸ ÚÉ‘¶36},žÃŸ‡6^ÎLÏ$ogì&•ï[ævÆ.ÖÍÚC[|\ž›µ@»1¯Þ3So:õxhs±_'¹C+‚mu­ýí˜=ívµA›5ò Ê Ú¸C—yŸ¬h›‹‡6® ̾õÀ×B3ݧº…6Sâ­Sƒ;fóBfÁl ]RvKÄB»Ð}ϾUþ¬Ý˜êA›?kó&Š>;jÛv¹µY‚i¬{‚wµ¢¹{°Ñó›þ¨›DZŠ wÔ—„çŽäÚ,bN¤Ü¹îVÙü4+OŽC6o@\~÷%B-7„µ¢²ÙÆTR×}Ý!›m8Ç>·‹ì"/}ét,²ÙftÙr3·‹ì"yðêÒod³Í¬‡l¶9Ôdó4Æ|¶ƒl^r†™G‹lj!/×Vk‘Í!TœZOG‡l~Ïh’·ÙfÞ›å¶V݉]$?Ͻ%6Ûzê…8bó¶h.9ŽØïhÛ ±‹ä/\GwKì"ÈŸ›ßÃs—æÃ›“\ÓºFXb³-ñÆ¥IWÄÎ&=üønß:L©q°P› ÿ¤¶pñ |Ñ7ç³§¿b›·“ÈÛÏ)U]PdÐm½îSÃᛳ}ôzÜuÚ·^÷ÍqC¾Þ|ø“}sód¡ ûøxÙ5'ôƒA@ôÛýóñÌY+v±á•Ø’!Ë@fºNbtÙKK3ÅLyåë¦^š)f*×aÓ—&93/]'ó&¬Ý¡ôÍû¥-•XéÎûeÚ›zéêý¢šòË×§ çý’¨»¹­keXͼ¸à<¦Š2œ÷KÁ» ,y/R9÷Kc¤ð}W/Ó¹¿8ÓH™›û‹yq58÷—D½Î=‘58÷—ø—Q Îý%[ÃzÖÿ¥Z‡­fžùR+m¦œ)}‚ŒÕª&SÎTÜ9°\‚v$Yå|r¶æ {â±²j.ŸždçÃþëqyÕ3eS^šÌš7˜±Ôpµ˜z¦ô0™K W‹UÎÓƒg­ÇZ6@êVÕjê™rËO§V«›N^k5åLùµ¶ümä¸ .›Ï[þ/·%ÖÎmI‹ò(Ã7nOÙJ/Íç6%}™G<·©ƒ^ }ÇmþCK¶è¬©ÅꋸE3™¥™·ÄÓ? [n1B<ÞÜ4k-Ùóàî ìÒÑypwÚ·Jn:L,Á´à=èrrpàæÔÚÝÓƒ{Z‡n¾Êx+dvpOçiåÁ=¦ÉNâ¹M_ŒZô9n·rYæ<²X¾<;<²צªÈfšêÚn¯IlþòrMòÈnžÿÙ•«ÇeñĦgÌÏãK¦ŽØx{u?<±1æ²L€žØh kÝxb‹ë°Á²õ‚ÉÖºï‰ÍšPË<ã‘MwÝo§lÖ ZnjžÙâ$ûØÀ=³!It¹¼.OžÙ5Ђõl:–Ù,‡eö#Çlve>~žÙ8¸cÏlM‡Çjí™Ã‰ÙȲi9\§9ÏìÒ@²GÆ=³%Fû± ³éO³|a_´§žÇí[4lcí±'ylguÚzÚ,¶½¿²Çv.Ö×ÇcÛÛS=¶éF¼lùÛôbýÖa[¦éÆžÊMuùñ8lÓhäÁa»D.¡Ç¬ç°M³¯ñbpØæÎÓÍn¶a{.ÿ=mnJåq%wØæÑ÷õ9S;ßÅŽYyXe©Í$ó5Km¶]ëõÀ62-0‡mŽÎÎJwVÕä¾×7«ªñQvS,ârqì‹ëòäwì–‹Þx‘c7Û¢‘J oÎ1^ù³ÅMgUí6ÀÁ›Ö9cuðæ÷X(û´ƒ7Çg¬¸Þ|ö”kà-Þ^ó‘ oÙùãc9uðcs}<ϼi¯7n‘Þj}îÍÞ|^\žÞb©]ÞlÞ|œÝ²³­Ž¦Õ¹Þl³W†âl«Ã¼y½ŸË>ïè-¶m³ÇTg[mn–Þ³6•pã^òݶÕoÛB·u“Rk[ß´­~öô7T™÷8~2c{å9]Mˆº Û>zݰ‰£´\,I€{nýG¯wÁ Y§}ûèuÛªòõæýG?b[Å•‘åéÀ—ßÎ{P@ÀË\ús²®®5»èðÊ+ɰáÅ5kÆÓV ùwa´¸ü“ß7p± ›Ëuá \Òoàò]xßÀ%]ð.ß…÷­«Vȿĺ*ôÂçŸü¾ð± ›ð¹.|ðI¼ðù.¼/|Ò/|¾ ?d]Í,ãÇDá¬ö–uÕ?ä%ëªÈ[ÖUÿ”—¬«î!¯XW™õ‘‰K`þŠyW6c\ýÃy­\µ(w}H9uÞæ`69m/¨OTuKu%Ĥ֯x·ä”ôÉjmZvJúnµ=-×UÑ”º‹ jËVÛªUñ5ªQ®‚Të¶ü\¹1X££§ÒaY^Õ(áÊ He»Ñè´ê¬«¸”ÆG·Üj]Måy+æ®Õ±*š2ˆ‡þ¾×å²5g]mÖ¢ÖZ]Y0­ËÝš5¯öhó)4üõÎI#ðxò[·ÆÕælU­UДjV£)nÃêè1Tf„¸l‰m8%}úhK! Åg•|ŒÏó¦ÕÔã•-EÃB‹Kñ)ìoMD›¢©/ÙNq§å–X‰ \»PVSÏø±ñ¨œ:µ(·Ä2É‚ 3ìѪê)jKÒãö´Œ;Õ(·ÄæÜ[p‹^OVUŸ]8d§å–XV•˜®'«©§‘z¹×wjQ‰-$Ô³ûõìTõ«e /[U=~s® å^œªž•Ó¥t/NUÏÜO4X/VUŸ¹BÒ(€ÙS–ª>G7†jTõ™µ»Ÿ5Þ«SÕG›ñ¢7«ªÇLs —±­7ûÔ­©7§ª/àÆc0éÝéê“=Lônuõ“‘²nuõ¹Ø€žY²Ôæ¼fñ-ûê†î¶’›ìèÆë0Vn&(Oè–G7^ÑõztÓ´a8äЩ4nºO,é³è–€¢ðÄ98tSÕhBƒºU“úX¿ºÕ€ðÄR9ts÷ÉOÞGnêéÍštäíøRý9rK,ÕJâÈ-I–Ø’›ZOâÐͶ9o!‡nÙ—Õá[‘V  C·$ó1ûµE7s¹xr3ÓþRƒ{rÓʼ<%÷,ÖüëÉ6³‘yr3ïn~tñžÜà ¥'÷¸by<³ñ ³yfa_˜g6Ú8¹—\9fj}±<³™1w<³G´ <³Y0kQzf³ÞòIkžg å­™ûs- Ok,É­yZÁFŽÖÌ‘´–µ§5ÉæéiͲžÖmÚ£Ž§uköèiÝ™¥ûѱ{Z÷`­§žÖ|øŠeZs6êc÷}ѲzûñÙ9€]¬U»:ó¢v¤¯hTlœ¢ªmsÀæ!ö±7y`çösgmûMpµ6ö€´ =°™žl9½x`Ó[n¾{`c¬˜„Ï]m¶ìÔ¬H{`'¹‘=$tÀf©•¤Ë›;Üxü&=°1+&wжd´{NØò¶ò:‡[`3!ñ:ëy`çøq!¥ìÄf[hÏ•À»H§çL£À–i\ÁèØìƒ¥¶üØò®uÀæŽoòL8`K^‹å–ç°M~6KÜb[^ÛòàrØæošðX‹m¦ØX{›£6…d„ö)µ‹Ô}[,µÔ¦s}š¥¶änZÜŽÝòFŸô_ÝrDZñæÝ”Is¥tè–IIñ³ƒ6›–Š#7`.ÅŽÜE”F‹À–Ür?_þSŽÜ<½¼Ó¹y"3}Gn¶F9rëd>«Q4¤²šiýn«êI¤ÂmK?ªƒíoÚU?}þZÌ{ ?Ùѽò 1wËêöÑëfÍYênYÝ>z½ nÈ:ïÛG¯[Vݵ ÛG?bY­­2A¾4Ã|ٲʺXð½bù.+îÛ–ÕµjÞ©òü¬¡·W­Qý Ûª<Л·ü“ß7o qóuæ-×…/0oI¼yËwá}ó–tÁ›·|Þ·­1ÇÑâ+Œ«úD/~þÑ_PÒ€}ØäÏõá+jH¼ú>|AQ郗@߇2°ÒÒÉœ³›ìù÷ÅÃ1›‰W&Ïl*KV6ÏlÚ^ ncv±VYÇìä 5mÌnZ³éÀû\.<²YÝ Ô!;6·¦²îº*ÒxdKýñ…‡lF“® \ŠlöýçÎÙRwe¥×öÈf|¬é G6“;>ëË#;f›ƒÛ#›{ßÒqmÈîÖ5Ç!›mÉ Ú"›Q«†?ٜǕ…Ä![CEM›A6·a‹I‹lα¹º:dKØê2:;dË–Ò!›mÆñË!›2´"¦-±%¼s]°±åõºÃïŒæ¿´WËhù••‘‘ZŽæè]|˜ªí˜¥µœŒwáK)mÜñ÷—çõ±hŠ©E•¼*tó¼Z¢ûÓ¼£¹¬Qu ð•'Å ÆC¾È{pÛg¯Û4±ÌÔ|ÈäkO'üg_Ð ;êkò·Ï^7­úQßðŸýˆqµîQ©Õ‘zÙ¸Ú¥ZEÏ̹ÐþœŒ«vý.V¼òo<¼¿~ݘªˆF¹³¿ùÈ­j·öWظêacõø#W=¬¬['¾ÂÊU;ëÖ‰/0´Z‹(-¼*†w—Cÿì/C-0çÅÐuâ+Äð²bè;ñb(ØÄÐw⇬­ ÷ñÍ롼WÇ{{ÊKÖÖí)oY[·Ç¼dmõOyÅÚÚ#+£ÜK‹¿fnuÆÖy¯Nv Ž…Y’ëÐséãÜNî6–7¡f–*Mu_øØ©î›uŽF£3µº€É¤úo{QÍÃx2†¢±H³<ÃuÉ_:T4Zk«z‰aXs«»É£ ¿Š«¤h ¨a5A“h´W±,ÅËÖä é6‘Žh,’Çì¢b4ùÑÖ%ÙµqW›Âgpgt¥÷÷*gƒµºŽd­µhÄÏ¢?¢£IÖXSbŒÖîÚíímÎðÚm94vIgÖ0"Ñd3vŒÔ»è¤g)ßi¼çÑhm¯b³}¢=2e¯Ì%ømc¤ê*-iÙÌn;Ä(ALPƬhãRáQ­°Ýžj—[ˆ™þÏ¡‘ºˆKˆ%årµßt†Ød×c¬Ö[øÞžÜÄhdU’K”IiôÐhì’ÚLDYì´+" «×§†íP3ÖX±Žšþp·¸E™fÎ¥Ê@'œ9ÖEa£ÑÙc]$uR5êÚZ³ÕuÅHEÌ#Ê|3ËZ‹Fg’-®&gV½/£O°,„?ûˆ2Õ°Kë‹Fo–51êh³~Ñß>jtS*H©$çhC•ÐH;Ï-ÉìŽa~Àšg}ÁÒ–ЧQ ©¼Þ’ ±6iaÑØ¥Œ”Jr6ËÛ•š¹°ÃòkÕµÈ?å(OÈ3³íbΆz—ÚsC=Äj,ýÙ†ú\l‚È õ4½'ÛØ·l•+ZΡžH_FÉ õ©8 9ÔKlÈ2‹yԋ꿚aZÔK¸«QZÔK½'tÄ“^’,›ýÌ‘^âd°:ÒÓ iBIé5ÃáêI/ºð”éI/ÅûSp#½™»Ý$<è¥ÜʽéA/¦`ÛhAÏoö`¶ z©Æ·ò¿Þ ÇK³eÛ襠۲5zÐK•¸•ÔƒžÇSuу^¬¾FèiöѰʂžÕ ¹9c@»*»;ÄKFèÎìOcvŽŸ#žC0¥Œ7ÄÏ¢>Éü7Ä7gÃÙ7?óaGxÆÄ­<á§+þ°~6“ìÙ~2%v\/Ñž¦ØåÞ±~fë´že™lxÂû Åá'N]}mržðµY¶ðÓe¤WÂÓæ½Fðfm×ó$ÅÌŒgéÊY»1^’'?¦Ûñ\aÙÊã‡-Þ°1ž™4VxûÆxn¦Ô·c|6™óÆx&°0‹À3^ì{ëÌáÏjà Ó3¾Ù|ä%ëâú¦§| 6ÿÊNùá~ÖSž9†£%¹5òV[3x£<]¿Î“< ÃÆçÅó]61{âr€¶TËÆwF+¶;¬xÃ;v8ãu´á=V|Ñ»°)®°Ñ9¥—9y£»¨Üè.Ƶ¼=Ý™Gi%tßèŽí´šÓ§;S¯üëÞY h¹xÆ'çñ°13jqã!7T[ÈsJ§½ŽYÈK†l»×ZÈKÖ]s+w”s7§¥¼48ÊËÔÚýxz³o_y«=楄y¤Ã<;kœà<æÅ{Îì:óbôþ¹ƒ¼XË´:ÌK"C+‡yñ [~ÁO s,ø~kp¯ßZ'ªY^–ÒB³à)VýÓK–àOžþŠRõÇOflo<'eÍÍÛ×À¶ÚŠšy© ÃÔ=½ºà?z¿ vÈ:íþ#Ý«Ô ä fáê‚ûè³.üªªT–CxëÔã‚Hh7Ü»OúŸjüÅÇÜð@Ž!{êû¨×m¿`/6¼R®óâÁÛ+ÖŽGóÕÎýø]5jÉÒR„¸'Û¶»€çõ½Ú»`Û^r‹âãYÛ({\Û‹]H\ϽõzŠ€k{_ÈÃòËyOøä^øü“ß>é‚>ß…÷…Oˆâ…Ïuá „Oºà…Ïwá3áûõMƒ§â6ûÎ;ͼ1öÓÌ÷ã&^÷†ù ×ì(æê_ÑöêŸÒ+Žâ¸˜·ñ™Åòç¢ß÷”%u^Âõà—Æ’ÿ´§0¸ŒŠ;É/¥¸§üÅ_Òn‹ëpüö÷ÿhžù[,ù/õo¿56åÕû/bd<¸¡7I.~ÁèPlgOþ§jWþê/ÿúoþöïþâþù¿;úÄôéêÓ/γ ñø…{ŠTs¤F‚> §/›+Zû¿ÿÝ{¿±›*ZíŠÕ‘ìÃäzkT7Ì’ ƒrgšë-à\`EñÒ‹Y5Åc0tGkBU&N LÆ¢ŠðEk…ƒöœ%[Ì´ìÉÝsj®· €@wÄÜ/MÈ4©Þjíxa¡•BD§`ŠhIeœ”F⮟‚Éõƶ´”.—ÇV-H"óíáJ î鉵¾xŽÄçhc¨Nn%]mšê ÷÷,mèHÄý¹H›æzÓݳP™Y2NÝœ±¤¥=qËåá»0¾ãÌ—Ò*¢U ƒØ(:.Œe#°ÎP¬xïY”Q)›"ZlK¥Hy–6“ëmq*CÈšë-à2¢ßü•Ù,QtUX'xAâ_€ ½h9K}=3†&–¯ µÉЦz›Og[¤Á¥éK¨&Õ«(á`ÏC2¼jŠhÕœ™-ñ–Ì÷ûP讟.!šV-ù1æeT%Vj&׿—/{º´™"Z•Qìo½ˆ "u“ë­Šl)úJ»ÉõÆïõˆ%2$pꦈ–|=C,Íi˜\oü^ÄÚI)I?‡)¢U%Ô6•<´ŸÃd{c[+9_Qi®"Z5÷†ï`òd§IöÆùÇBB'õ'™3ï.û&SVZ Ú†¥)º)ñÖááb8¯6“íMÞÍ£™ÌŒ¸–ñ½¦kRr4¹Þä%”ÒZ•——£˜?oe°g*"¡l3ÙÞä{¡Q†8a,;ï²oÒ6Ê€ÐJ/“ÉöÆ :BÕV¤Íd{«Ì‰Ý™Üžïœ6êyW}ã×JÆÔ5Q‚K=æ%°‰Á«6¥mˆ:êX<°à‰ùÖ1*Ìó›¿¶'—"^¡¶kƒØg¼5Õä:lS„ËÔfb±M,ÎijŲØf.O¼\ªØ– ³—x†,·Nt¯òÇmæŶƒŸ;¶ó—Š%žvl³ Lk¹ö²c[Fh—ªøµØnTÆ|%Ñk:l3ã(¸ŒW8ÒŽm:óa¡£¢¶ØnL瘟³ÃvcòŠ6'±†8l·0ÑgLsËÃvã\í±ÍE±†fn;¶y¨P¹ë¸]¡_©UÏ·'.e̤GnÏm‰ÉéØÿÛm©]ˆ6-v}a{Ðì˜C)åÄö`}õÖ1]ãÀ6SaD쨲¢<µ%çcj˜ÊqP»ÓAn âUâ©£DÕYj7 OmŒÇ C§ÊQ›©o!ËiˆöÌS»RÞÇñ 6ý?’ìÑå v¥‡"PÕUµñ8¦MÔ@žÚøžž¡b>¨ÍâE~¿ìØflŽP±Ô¦Ñš.ä9jãÄÓ¨ÇOm–´Åk‰Q1ê¨ÉÄp[qðЦÙ3l²R=´ ù…cÒÝØS»p LEÌ;µYï K™kà 6×f S¿©]2ކC6£ïÅöwšŠ¹!ÂdÃÊι;ÝK ¶1Ÿn¦£ÆûéŽ7vEÞŒc rcAœÆìº8rWVw–ƒóqâf>ʼn…ŒóT9È­‘ÖøV9Ñie˜2ÖsÜÑÍ*£Ð1!žèffìô, ‡îÄsH ÷ãºi•£Ü ¶èŒ¡ô(kÜ“9Ÿ Q·ø÷˜x{8”êÞãÈÍ3<–Y¼¶3GnÑ"=Ù¹uäò®|Gn9eá~ÒÛqâæ¬$ìL÷ÉÙ’›»OÀÚºV¬#7g,Ëõ墺A7–®õTtsΖèPßÑݘ9I™âÝœbüC\(®ïvã”úùC£8<»§.xHÌ8Ø=y‡Öë¤nÙ-iôã >Ïî!6`\¯õ bÙÍ3JÇ ­•ËnNVÞÏut^ìæ.DõëìØÍãKÄ/-»Y‡œ´FßÙÝÜZ1¡5ìn¬q› ±Õ³›3ni‡w£g˜Ûëo^Ô±KÆú9à>G,¥Ö?9r3´}Tˆj?à=™ä'àÔveå¡:¶ƒÝƒ ¢\½‹{vVp,ëÑÁ±›²Yq;]ö]Q¥ÒcºDòM7Çî*ŽÞ8&¶yžºé„ L+'»™›wÏÑÔÁϱ›‰²p¼¡ÆÁn3¡±äÆi¶v|_o÷žÜâˆp‚ý 7½˜—Ç…'·d⮚ž},¹q.„jh‡®„_y[ê¹EÚû2Or³žr~.äŽÜ<ÿ§òuD³‡nÖ1ÉT$ª’&~¸øˆ_«·„3‚µGnú’à©3”ãÈ ±cÚo.êÜ‘Çø{Î'¸ ŽðxÓlàr¬NŸ¨Jø›x·¼pÄÜ—çõ|³ÀàÙŠ=¸±p¨†£àFðkýpóNÐUÕ3Xps"q£ ¯ïàn"±à,9vpó7é>ÔT€,·I6^ÃÔýÅq›nªó¯<ñÜ–â:õÙŒ-·±õ ü!…yb»âõbÙ6½ÏíØQNlg*°óu@Ù°]èÂŽ½S|Í=¶qÉÅæx).µéàDójGV»…`Ù©-² ø–^ÛNm^-±_‰êlÇvSd\_ÂÁmÊV ô!Liç6‡00|¼´¼s›ï ³Ž|‡ ÏmìJ¸×DI,~q›¯¬‹Öõ‡²8P£¡¦Czõ«ÅRK9[ßôÛùìé¯˜Éæí@²ÆöÆs€sqOwNØöÑëN35~;ÛG¯wÁ Y§Ýô¾ßŽòõæÃŸì·CKÛ°wÝv2Q?¾ Þ¼.^;k½.2¼òúZ2\xÑ;ÈŒ§­4ï‚hwœpOþljyxíø.|ãÄ<¼v\¾Âqb^;¾ ï{íX!7U¦ß>y >ÿä÷…Oºà…Ïwá}á¢xás]øá“.xáó]ø!¯D=u¯ðš×Ž{Èk^;þ)oyíø§¼åµãŸòC^;¿âƒ;îÛ1¤žÆ÷¸Äüç]bÀç\bðò*î„ÔÐ3dйÄ$&€,ňÁ°®ÍhÃz ¹&i3åéƒ/ъ»ã:ž U2ùÅ£è´.¬±Uá²%His>14·Õ’äæÏ$çƒ{´hœ¤Í¹Äàx† o{Òf\bpîÅm¿ •²©ªheÄ{t,Òø˜ªDõñØV%»ôcª*¸7ãæ8Šþ˜ªô ßwÜìku'ë¸/—Œ àÊš%A!ÃäŒK @å²·Kxõˆ©ubJł°<ã3©ßªEoþ…E—ƒT Îc[3ÕéZAg1ŽVÚLõCq‰éMŒíÒFuÅãa …¨—wÞKÌÖ¶¹ÄÄÇìZúí3x UzÎ!†v€4Z«JÎ!†/¾^ví2œ?ŒdXÍC´Ðe:wªAZ¹üLÊtî0™‘åa4Ö¹¹ÃT¬è2DXÃæÓëí#Qƒó†Áx!+øÅ&mÎ&ðûtza[ôÞ0=1tJTs5:o˜bk¡×hJrN@ ˆ8ÔdJJ/KåÕOšœ3 ͱ#FM›Q“)}Hi¬"[ò¸ìÜað#ŒâO¢°”¿^AZò ÒL¹ÊÞM4Þ0Ôë5I–"—Ó S¾ÇÖݶyÃ@¨R«b<¥ÕxÃdêºÆ¥×¿¹;>KÜZ°ŸŒ"š™Z7w˜Ù"+Kk›©}(ß›Œq)2†ž5¾/qÖwúÃlÌžx‹I”³YzM¸@§ƒÙR+¼c7ý•c6kÔÒè0ÏÙ¢G/ê °3›ÊòNÂ^ Ò2›úÝ”{‚¨×ÚÌÍJÅ|Òç9hS"Ä_mn-Ë!ÆC»I-¼UÝ,´›Ô>è"š;´©Ó‡t…©¸±Ìæ0€ÌèÂÙ8Fuòȳ±ët¦^R£ž‡6Í*øœNK´ë¬}ÀA[ÂEãĉ¢Ðf ãRn'íÊô8àÆ¬'´ñ=ì©è®(B=´ùð6Úe(ôÐÆ€bx\/j3_pH²žlS}ƒ–&‹ðÔ®âÆ4£º˜yl3c•B é¹Í¨s, Rñà6s¦ãÒâ'Ün ^àØæAßûÁmæ'Ê8é–‘nÓë@ž–n«ÓkëöƒÛx\˜ŠJ‰ç6“(WÖöÜn¬”TÙö=¸éUŒ/5ïxpãõ‘®­Ös›¹Ø!%SÝC·™^ {'&"Ü®|šÚn³j8ƒZÕRæ¹wP¹Š®í¥l1s)ü=·ivÌŒOLÏí"æ]œ:e©zncx¥%:pÇ›ÛÌÕ¤†©ïKxøÝFUî.^¦\T'º¥Ø‘Ø\ÊnÉ€…ÑõOÐ]èÕŽCºª'<ºKuÇ@‡îÂDgüÕØtÓeG·”:Ç>”ÜtªJĹx7!›Ðt¹ó9pÓÕ€ã4¤07cÍ^cֽǃ›gÕu?qäfžU7Ä’›F±~yûì䦙ªÒOãj³ä–L‡Xý:øWgVeš!USRYr7IÿÛå`ëÈÍçµe*t䦫Æ,‰^xy'·”°‡ü§)ÎØŽÜœ²,¾éâÁæÈ;àÄË ‹Ü4@C’nH9rËÀÆõ¢6tóAØlgº¶@‹n¶1];ºùnèÔž³NÈtfU¬KÀ¦%ݦ3«zi…©§6‹nΣ&e(ºé–[É¥‘wr³—ØÂ±ïδ‘›35 ™³ˆÁÛ‘›d®Å¦"Gn±5ã0ž¯MÄ’[Žij¿väf]èå´“[< n˜mè‡d,ók[tË袜•tó')uqèéߢ›óŒ Á7ÅåÐ͡ό9º1gW‡^ó}¬6è¦14èI#ïè–sbÇ·5¿C7×x /¦¾¼¦ ×ó;]Õ¬ŠtévY»\™É?©)ƒ­ošU?{úzÌ{?™±½òœVAmØöÑë6ÍžÚ*¨}Í­ÿèõ.¸!ë´ûÞ7«º!_oÞ}ôCfU:\2z ÜË/§C(.Í8¡1ùꟑau­ØÅ†W^àH† /®X3ž¶Dâ]m¶-ÿä÷m[ÒoÛò]xß¶%Âãm[® _`Û’.xÛ–ïÂû†U+ä_bX•záóO~_ø¤ ^ø|Þ>!Š>×…/>é‚>ß…2¬fVûY®„¯VÝC^3¬ú§¼eXõOy˰êŸò†a•a®¬‘‰›¢ØnÁ²Šk´³¬þῼeY•[ù]I®õÄä’£Ó£¤MÎ>ò6ÔiLã¥#Õ•$SÌ[ƒ/Ú–çæ$gÎtb£Ò~©zpç-=ELH–¶ºj2ˆýÈ%‹†²ekYe6SQÛêˆZ”+¹ ƒLB/ýÊFGeÒRÒÉžq“ÇQ‹®Ô‚µÏàp”¨"Žvié! ¹·V4D‹‘OíCæKȵÜ@ŒØzj²­ª}‚çWFz-Ój“"‰=«¬±4ø£õl kýÒ'Rɶôôø‡8m†´Ÿ=>i1%Q´½rwnݪéõòzÇ#`óZµ%wµÔÒ†SÓÓ¾‡­FM´áÔôŒ\Á[WÓ–ýJŒIõåìµò¤/Ó©é¹¶fšój««ø!uœTø^¾÷mªšž*­ûÕt*Qn‰eSñî{VM_¨¸òõ½±rbJÈ$~äþÍhÕô´zc®/·ü­š¾0ƒÁ)Ò©’x$¶0žª¤Ëà ¹6zzQæ•Û׺§ú¤Ã”¯uÄ”&«¦gáЊաº½N-Ê#±ÌÎ/¡.¢aéÙêé‹fH-EdÏVOOÝæ.jÈD/VO_˜a¹ÅË÷ «§gUø>SÓK›3°fûEgˬ*KQϘ¼ü„‹õjõë¿c”Ÿ¬.p’¨Ð)ƒmÍ*êñ“+犠ïÍE®F–lˆCisŠz®ê|‡võnõ¬ÃŠÃÄØÝ»3°2ê#Š _Úœu|hÕ×ò¨eäVx;ß3°nèn|ⱓ»Ñ2®’r»JòÎ0ŠèÆ<¹ÕI…)]òAnÆù‚Ex§c'7qœÕø:wr_a˜lÛÈÝ$!G¼UŽÜŒÁì8ò^–DGn‰L¬'®C°ä6¬¡¾žÜØDÐozåƒÜS\ €“Úr3©r·FÔ‘›¡ „KêŠâÈÍP«yZhKLŽFÐ×Ú2KIQœW´ÛU‹;©íÈA[‚¢2öÎ>çmj–šÆLÐÆ~u•sª´€Ä(™Ûí&»ƒù/hóE{`)ðÔ¦¢I²¹ˆxjs1c ^]žÚR«E3Ôn™%ÚïƒÚÕsçíÝå©ïAÈÛ•¢ÚS»GëÝ⨮ÌÐî*-žÚ=s#ˆ—¢ÚS›ŽØÜgVÂ:jcZ°àÒCGm¶­’žÚÁ†³\a¢žÚ\üåÉå©Ý˜ô»àT§¿é¨Ý°.%Z¦ÇQ?9ݤ‡v£%43È/Ц¡ˆA·9ŽÚ|Ä®+2<´ÙKœ ¯ÐSm±ÊNÉ¿t@[Šú¶ .ÅÚuREx³FïšÌ[TîÃÚ‹ÖÕÛ4êv¾Ët€›ž#8N$M-åÁMÑL˜é ²܉0:]Ën¼“íƒAÙ Â,¸i7—$Ïí7Ë™cƒ/jôàf9s¬á¦é'<¸X¹”ÜÜ<×áå?nþˆúy)Š,¸ùð*ò–p³Ÿ5ô;7…w6…w•S ­¡û‘+‹¡Ïx}á8rÓ­ è½Ü?=¼Ñ„…!ìðì.jäº,¯ŽÝ~³INûÝì Þâ*±›“R–¥×±»I ûÜ/ß1e·üÎÍ! л©ò¸äoqg7ÛÐÓØçn ÌÄ+ YWœE7³/PŽñ>7À0ªù ß [Rµuê´è¦`ŠäÕMƒn&‰HëŽáÐÍ6œm°ZõœnÑÍCÈ O\°C·¬Lו/Á¡»I9‡D°”Ý:¨.9wè–ia‰œÊŽî&~­OܪC7×ûXŽÝM*hÑó2Ý4[B‹ˆáÆnw‰ûVíØMƒ hô »ˆe7ýpôDoÓÁnÚ¸±Ñ%&>ÚÙÍï%v¨ …c7§bU|±[ÒwDt'‡ï|Aуâ.€®_Qõ@úà%Ð÷á‡L­,ò›Å¨•&É·l­þ)¯[·Ç¼emÝó–¹u{ÌöVXd( (ö+¹ÝqzŒ­ÿýï…±b{c+­†™„pqw6!QãCr»i„É(¦"¡zÏÎŒCP—6Sÿû¡5îDO>¨™Yiû$µðí8<¨™y” ƒ~âyÒ?[ÚL5BIý6x™”ˆ›ÑV1BQ c55M>Z±QT…§„ܤ͔"¤¯â¾elHTä•q0Á¨´£²¯Ì(UÒåpŒë§QÙ³Mº%Xc˜2„´bÆ¡aºÒfªÒYfXƒõµûËtÕ$>ˆ9#Ù6W B6±W]cLÆ4%%d2Aº<Õ—åŠeÜi¸’<ù“Å—å K-¦ivg05ÙT[/%ýš©A(F­ùÔàœ1­=m„e5·ÐÅaií™{ÂpU½›±hBîžlö“U­=$cºmE“EW +‹$>y­f2õi!Ãeã®0s°¡¬ôͦ¾_nîSãBïPÖÁ¥V® ÚÉ{ÿ#°Ìêá3K°‘¬® ò,«ò DÏñçd•ÄÉ*¥YMÝAÈj›ÒVl(+«Lv¬sCÞV$+ƒ s¸ȧ(¤ŸHÖÁ2~Xä"ʳÊ:rÎf*Êã° bMpéL‰MBY9)c¨²eöb"Y¥jôUmpönYUe¯†ð9‚cåte†KH™¿Ó]ÓÖÝ49>´q¬,ðNÚh™æ 6Ž•:æ'ñ3^„5³R×—â­2%½õ#­XoX=¬Øø(g(-Mtüßu0ùN;ëAíZd¦ Û©Ýš©Oì¡Í:âK]ï MÝsjØ¡Í8ÖÑÚ²ÏA[ò¢æ‡%Út’ÄzWòS m†X0¥õ•ÚA[¬‘š¡y;´™‚¯òv™pЦ•?x¹‰8hÓð¯g}‡6óšÚS¬ŸãŠVwÐÖôè§Ö¹tÐf¸GÅóèæ³A›CÇ^p*³%â©ä;µ³‡öÈ©H•Ýy@›C]Y~µ9›õŠDÚ©-Iû®H—Úb¿y^i<µ;óâJ¢Fù‹ÚCó"¦z0{rcÇÿ?E}î™-5G‹X˜fO)Ý~UñÈ–bÚCnyG6ßg®å¶Ó{dS1ŒïÜÄsÌžñLš©Ó!›Éê‚t ›Élq†d½ÕÙøÅ2Ð)¶lF-ÆÔTñç‘ͺÇëÔâ‘Íœõ­b‹ˆGöä=-Üùö=²'S·‡Ûî‘=h™¾ãÞ²+7ˆ&vƒƒÙƒ¥„ÙU¼&©•r0»O>òÔÊ8žÙhã‘e¨Ï€g6˜‡ƒ#+ ǃٽ|\>Où`63ݯz(ÊìNg³ÇiìE3ë†mÍQÜ.5“Ãvg¾Îc½Òî+·y•+ Ë_+8r7É·\°óëé×’[‚9qªšqÛ‘[v~,ùû`fÑÍAÇ^ð½è–¦~ÕÛqè–ì³…Írrè–c‘¬3,»9ý˜úûÕ8v‹ãèÇi[vià ×µã´-ñ»­âGuk´ìæè2 }e2rì–CA–¼Â}g·Ç ¼µÝ<@€èWwtKšè’ï\ð–Ý\sº|»y(˜ÏÁ̱›S™€-ºùìì–²:m0‹ÍqÞ–4äx^UßÙ-µl°ËÔp ›M_¹RÊ8tKòoôñª ¢zJt!%Íý}Çí«¨w¨™S$NͬrÕÓºÞü¯öþ´ï(4ëci]|åI1¨E1á`vnûìuCgÄLlŠgÉ»þ³/è„õ5ùþ³÷í­~Ôw'Üg?dqÅ14`‚üÔû»מyôì¹à.ÔþŒ,®võ.R¼òo8¼¿zݘªdŒ-wá7¹ÕúöÏþ ÃW= ¯['¾ÂòUÓ«ïÄ—˜¾êa|Ý:ñÖW+ðQr’‰ø›b¨Þ}^ ý³¿@ UiáÅÐwâ ÄP]Ô½ºN|…J'61ôø!lãU‘æ‰Ê{Õ¿ýS^3ÁnyË»=æ-ìö˜7L°˜œ,i‡JiñWl°ÅÚ`ÿå½êÚú¦O®ØŸyWÁË}¸ÅQ×%J\HSÒFÌ=kc^©øÒ¬‡h±z!ܤS‘’Dzwb´‹Üþ¢ÞÇX9éʞŊ.’ÞŒÅ?¥´Ý”pŒKaÖv~Ä©›ÔËÒ0†XÑì=j´S}ˆ¾zTõ!<¨ØÑGkŠŒ¬Âã¯òƒaZ[lgÇÆä›Q‹¤9S0*¶ŠX‡IÍKz6ÎÉÀŒšôŒc¸Õì7–Xì˜^ñàEcñÁ¯ƒº2m¡‘Y ©âeoYs3?̈VþÝ[𺚶Y“,ÓM2ƒ³ Gc—lgê &àt«7b¤Fg]6·{htvÙþÑY4Pë‰Óöc ³¸P31´†SĘÅs~Jü Á¸ËßÕ-™_WRžI"* ÑÄøYRYEËÏÊí?¥æd)Ø9ðѸ¦)ooA–¨U\Šª*ÐhUý¬³Y(œz 5øXXŽ€F–,¹dY ÖqŒKá‚Æ.™ÏT– ^òMM¦¸9-|fÑãh£QøK渋Ԣ­Ss«¢L 'ܯì¹è„Uù³ð{ÅÚÒˆQ4Z?ûªÞû*íG”1W qY‘Z™G”%œ‘E*uQÆaõþŒDM èÊW£³Õ2¹ØãÀJ_óeI §Æy5‹—^“ºÆ£Í*ÿ%ˆu„©†jkúR*Êø&µëWù/®tþe÷Ð5u˜)8£íä.s'k¥–Ç[m)Wõx4Rev‹2ssϬá—hêRbJ™)½§Ô6Ž®‡fýYùÍôÃ'ç1IL€žNÎCĘ5–yeOÎ3qì2¸m¨gœuìCœ˜ÔÓü_Ônr ž´ƒßˆ%½ìË]ŠŸÆô ôZºˆì@ÏÒi+˪½››ýεàAOhÂmÿJgçAOõ"MWZjzêÊÓ Rñ §ŸUÓá9/¦€Ë’yp^úSŸÜÇŽóT âLÔ¯"âžó¢]½ìªç¥0Úú½CXÎ3¸#ZÛƒóRæ.îãà<Ñ&.KçiË-¹b“Ôé8ÏF,+ZLçâ¼TÅB»ªÜy΋…ûµÚz=楪^M|:0/5H±Çõ«Z¥Ã| ™·†ñÄós²¤`` ø‰ùYmÑÃó“èÄXG:8ß膠è<9/š²Žçqdy°up‰“réå‰ã<ó†DM¸r~&l š¦_Ý8OS3Ç”®#‹ãüÀ&Ð4Êöä<ÿe/ã^óC«Ðæxí‘óƒ±Y¹q$'æ#CñõÛ0ßéOÒïpº ó’–ë<”ïÕ4ãþNÊ‹}£ßU 7ÎwFœÇ;ÀU6ƒl©Vñ}—Öï¶ôî¨g`Lý$6;ê©–M7Ÿ¨g¬tØ=¯S´C}ÅV–¸2ú'¨gtìxRmo¨çÁ´ÐoŽ“õ,/ FM·]ÇúÂ`à0¦Îàû"µgoÇ öô ó6wm°Ï4Ðvæ=ï'ì<8Ä~žêÅi>YwØ3Ÿ/w¡Ÿ´gnãðDWï´—"wŒ§§}–Å£Y8OõY¹Ê×n´O bÅN¡ñæí¥·„ž§zÎî}5:pÃHp©¹ž´OôéÍñA·£}"×± ådNõÜÐ{•ÄJŸÐža«xÿ˜ÂvâžµhÁ»gëu¸gb[¬å¤^:îY”}Œð¸—"«å.Bái/Õe±Æ¯Â­žö4_bs¹KM8ÚóeàÿÆåêi/Ç„™ÄÌzОVÇŽ‹vKŸœêÕ×ëQŒyÚs¾ã¨w2O{6VÐà2¯{Ús p ¿*xÚKclñxàNw9»9ÜK*åîq/Foüíªàìq¯õk¹ÜË7ï´ã^’ƒkXr9xσ ~><Ô¶¼§Kst=š8ÜKâg §ŽøëEàÐÔTþýÖa„ñÒY9¯$ù“–¤í…b«þé%Ëð'OEÍzã'3¶7ž“²¦òík`î£!þ_5Ǧa*¤^]°}EìuÚ·âÛö`7ä« þ£Oºð«ª[æîÂÎWq•¡zG*ètzµuk0>¦c<À1fùŽGíÖà¿øËøååÑß¿ÿÇ?êÁ %Ï¬Ú §É ¾ûÔ3ìOfÑüº>ùÿûéÛÿôíŸð?8ñG¨±øôJyÑ‹IoSÃŽG“ìâRÛ_Æ¡ø8bƒÚþd×öbä00´vÞÞÛöâ¦0è9pdÏqï‚k{s_’x=Àï]°mï y³£TSyOøøÀMøÜ“¿@ø¤ ^ø|Þ>!Š>×…/>…š>ß…Sød7a^ˆôÇî&<¦·‘xY ŠŠIáϽäÇ­Ðþ¹ÍºA3òíRÿ¤‡D:[ãüûFý×´t»§ðšñA›} ñ—ò' Ej)dzï–ϬÃ?cMÿ¹SÅoqA‘ÿRÇé`™¼WWì¿`:]Fu¥Ø¤Ž]¨gâÒ|5ð?U»òWù×ó·÷ÿðÏøÝÑ'+›¿|Ê©QNƒyàò[xëÊ»Oœí\¹Ýÿï÷/–ÛÝÔÿ¢s?C­¨Åå¶0L†ºÁê’×Ë+*oh†º€kã·A5öÊXÇ`ÂJ­gÕñ^å7Ñ6£èÒ&£Gû 1.<öÈ©ê&pð ÷q:•+f5N“¡®wºãƒDüàVý/&žÂb¿û’‚IQÇ„U(¯V°Îè†ÕðˆÄè8žkYZQÚž`¿5Aú•Ñ$wù§IóÓé>Ú˜CLLbò‹âä¶Â«@£ÙçñwJiÕÿêTÂh²~ͤ§c¢®ó­IÙÔÿb[&:œ)›ôtì‰FÑ+ƒ!¬’NÔåt•p=á°ãsÑSlˆñÎy™¤ªð3Uú”x…h¤¢¹éfíYzg‹AµX©šÜtüMš€f¥Hª¦òÛpÉy¦ŸõCíw3E¿øŒº$#5“–ŽmF3™š)úÅ~c‘Ô+’0u“—Žmx¸'ŠôÔM^:¶…9BJEÛLÑ/‹gÖ‡IKÇŒk]bc$œ- Sô‹#«Z¡Rº2L^:iëênÁ¶¹ª~Qî1IlL“–މÚĕ鉥mˆzLwUÎ<£Ô¤‰혔©c[YbšƒIKÇÑ™u±^žeÍwÓâ=ºMVº.IJŸdFû­ H¤&ÈˬMvW©ÓÉ|h9™¬t’ÚnäÛo/'“•Žm6+þòT•³Ø µJÛV oÎ&)›êr̬M¶Du0ïä3)Eÿyîs^³s;VcC$r°º³Þ\,àH9XÍä wV²ÕŒkRÕ³¬f¬œa§c5^ HRê‡ëX=“ÖÒ£ïXÍ6*ŠŸ6Ãj¶E#φÕàJkKq¬ÌÿgS¢ø¬9¼šÔ­êÔ,­Ó9õ›†Ö#PÙÍRñÔò´ž`èŒ÷L;Z£Kö-8\PÝoZf3ÏIÁ¯\GtÏìÎú¼b=˜=Rg„ßÃLËìÁJŽí)Fé˜=$ЊV±w:fZÖÞ'È4ÉÏZtÜŒ»Îáy£–Ûƒfеö·‡èª×«ñÜfá¾5Ç–ÛàüJ~·qÛƒ½g8póÝLFýëMÌ{:—<ÕÌ=¸niöL îÙ@\ÈP '¸gqÓïÀ=™Ôö9èxp3‹ñÏãQ¬¸GûZ ¸;ÓßÖûm{p㬶޶7Ž%Ìg nž‚BMYâÁÝ’Å÷ mÜ›FõAƒ'wovÑyró°¶“œ¸…Íù<§ ·QX Ó0™Û¸´An£Üb¶uî³:fnc“ÞâŸÛÉÜî Ö¬¹÷nÛœ³Ã\ ·»{5îòC+¸ñvGÛîÏÝp÷Ó[?;27ÞO0¸ñ Ù´™ãdpc!UË|öÜXIñ¸} +¥"»Ä¸ùÙAí´ ¸aè9"HWÝ•“˜–U÷ÉwSÁ]Ñþf®SÜxEž3*¬àÆ^;Í_AÁŒxg¸\Á]l=ÕTî kpp@À}Áå=÷¥+¸i£¸€û’¡¸½Âü\B ·ík¼ŸenÃÆ~Å_nþLLnã5»:¥÷u{TŸ ×E·,”ÞO³ÒÛ]êA¥7L:m^ƒÒ»²ðÞ6̹þл£FǤ¢Ð¶õTz£>=í¿„Þ¨kO! ¡7làuÌ¿)ô†ž-ôFñvúM…Þ€ÁÔ ½í¿Ã…ޗÞö5*·Ð;ÉP„Þî×OÏji¡÷0ÄšUèß›0Ìô†å>î´ÒÛ‹ÿÏÕ‹ÒÛ+÷¥gŸ¢ôöõñÃx‰Wĉw¡ÒÛk¶Í©§ôFŸ…x/+½1N^Z3½½¹HÄg”Þù댅ÑMo{ŽôËy®ƒ¶®[@DÏõ[7ÄÝz9Žîtýèì[IJñXYâÚvœ'—Û(ÇÇçÂä£ì;åøæ ’^‚\ò}Û—¶;ˆä’?¿üñ?;ˆŠÿØ1[—ô½¢ ´7LØR£¼éºN”Ñ;½Pÿkú‡‚A§-S¨&bÓFŸ]OõþzÜ ÃÕÂÁg~ÃÂ1¾ù‡t/X8Æ7ÿ á ÇøæÒ!ì÷ñ$§&Ýû&N¸L>9ó “χ “O‡°ò9QtòÉ^˜|7ÔdòéþÿPB1KôCïµMþ!=Ç&ÿžd—HβË?¤'ù-ÿиslKæ`SKýWÌ9ÿØhιÆbΙ[›bÎ9ÑúóÙîe„tæFÞþ!)¢ù ö‘0çØ:éÙäç“ÚGâi¦xOFLgÚ˜g!ú|Š9§ð9'1ç¼³Îi1ç=#'6ç4T À’/jéª[ºwFÆFtÊgh„S%#¨òYçˆpÎÔ>Ò ?¡æLöœªWžÅž“qûq0±ç@å‹;]ÄŸƒÎÌ3|“Ñå2ô³Ìq¢\©$´5 æJ $}œ•ŽAiô3Wgf¨576é@ň bnlÒAP1æÜܤSVus§Îõ!û6{ä.F{ÚBHÍ]Œ: ÿ3góÁQŽ©ýçñͨ3CVy°Q§Œ/;ñ#b”ƒ:ÞwþÜå`§šÿžS¨/ ¾ö½3Bëå$ÁWÅ rŠSçàÈf9©¤;nÂeQ5ôKð«ó«¤Å©C¾§’¨$¾—PøåVÎÊÅŠ¯;"²V®h 鯠ˆl–k±êÐS€:³´©[n"çNت3BüC%±êx°îQ 5ız62›Å«CV ÓžµMñôdºeõcí sÒ.¯Ž¢{h÷qËÿ+ºQ+=$>E7rãÒÝŸÅt#¸yÐÄèFDq„ƒDÐHi¬Šî’¾ÓS¤èF›Y[ú>``t£*}š“OÑ=¼®Ò|^Ýxk…±RÈ Q´ÑK„Éí ò9miLî%ª.ävsë=ö"‚AþÏ?O±@j#©›íŽÊ¡Š ´¡ãñßh7qd ´¡ñ…ÿB™Ý³¼9›˜tNe½ëp¿ŒépfC£#kª@ÇÈm#І~—®éàhwïsU ~ÓA)̆‡Ê)³ñ÷{O˜=$à¬ÌŠQ?ïZa6ÌñJZ˜}±?U™Ò>y×Þhi†õ\ö*®»˜éרaM“¯ÐºÖÄ”Ö yæs(­+Ò̧åBiÝà(¹×’ÒMr£(¶íÇÉálCZ%ÓŒ`?­>Û.­Æj‡±í—vYÁv·IãµðîÝŒ`¿wêÄgb7þ&½ …Ý8FZ…Ýþ».ž×³çëQ]á»B?·ÀW~E‘D7ŽÙ%>¿ÀÛî˜oüB¤µ ½ýÑ Xèí>ƒXy ½ýV‡ØîáÊ,«ý_VyQ'çó¢óûÝÅݪŽîTytö!Íç:þI×¶å<íˆÍÄ}aòÑ kK5ÙŸ{˽0¹äû¶/mWyå’?¿¼~ô;*/Ú’¡æïÚ\'Âã¯èž†½Û›:oÆËµ)¹þ5eÞ€FàiËê‰à´t=5få^.J›œù¥Í‡ J›a¿Òæ“G•6 JÛ=EiÓ!ì—yy’¿"óâ„Ëä“3¿0ù|:ùtû'ŸE'Ÿ á…ÉwCM&ŸáOyQ8eÌ’÷*Ü#óê96ɼz’]2¯œe—Ì«'Ù!ófì³íï%Ûx×ÿ®ó¦KuÞýÆÊáÿ§óz‡¼§`ïHôø“Ý$bÁñ•ËLãôþðOHì‡uÅ&#ø„Rš±µFÕË>!à¦z•è_‰,¹Í½¿d¤Û ÁPQÁô©fj¡í{ãkY´‚“ãËè–µõè_‰X+m­kg·¥¯¯ÚE2¨_è¸ñ)¸P{ú¥ Ù{V¨ƒ5ƒvqÒS…‚ªYc¢×yQW£Ì$φ¨Î3eñ…Šh¼Ó¸¬ó¢‰väc4už{K÷Ç£[´“u^;É íWÒý¢:ÏŒuY?‚ø-‰ÎÛYÂjˆê<3¶"²17-‰ÌëgA,gNT#9%+µK¤‚ÆÁœv‰¼[¾úŒßc£r2™#ŒØ2ËM2Zf¹ VV¼PcF 1cßþ½è”†é5BÝm¤sÉõ‚»èý›UÉçÕ¿YY/@îm(øyI00è§©üº„Òk<_—Õ]JªòE ßYˆAymÇÌÑ\yîÍ‘¤¼F/âÐו׈Ð3í^y_1T1å5¨†å5r´B–a^#R´„×=%&óYûi~t_áõ] øÉ¼îpDá5.Rœ…×í3w™×ÃSнð—~Ñ;€x%õ|^{nWŸjð鑤¡¯B=b® ¯‘÷r§àÚE†°¯(®Q”~L‰Wpí*5ïN ³ç&´;Áµ'íFHYyÂãñ ^÷Ó¥ç~¯1M(SVxï‘FxtQJ8^{á‡o3¯‘JEú…×ýôþ/ î†úã³Â€õ"(sMÀ u{ö˜ÜPÓQ–ÉÅUú¹GâW¾’{ Ü£G‡r#Hj¿’Û¦o ¯Ÿ’Ûÿd ¥.J/ÕPrÛ\#ÃŒ’J»›ŸÚCßWí!Ê‘CÛ›Lj£Êû ÜSÔ[Á=.®—¢à¶G„i)àöî±äp7TИ¾pËZ ·›Lgáv;Ø(§Ü¶% ùƒ”ÛXkÐBT¸]½®ý¼rá6Þ®apTn£*Wd*·a2À/üY× ·«$T*·uU&ÜöõaüÂí:¸˜—rÔ©”ÛW@E¹]û7^cùµ¥„׸SµÆ[Lx]ÙñòÁu•%¾âé¼á&\ãH©ÉŠk´’4H¶Šë"U`×%qaŵK)ø)¸.™£c‚k\B8½×X/ÇK]píZ>aPpí›ÖEÅ5.X'¸v·çÔo×eÈíd\ãm×·ílþÜŒkÜ~¡2®±fùÙBÛmQåNp )™Ù×8FKNÁ5äiÚ~0²ñµ+*”²qå”Gí!Jܨ Ë/K»¶fyÊOÇ£'øÞZŽïwxþ‘ÌçBþÉW·åD}¬ò®|ô‚¶:rYå]ùè…!È%ß÷}ùh»¼+—|aùèwäÝRQ ¨œ—-Æ^y­HŒÈ­èàó¢¼[P1(tmgòMã n¡ö´ ŸOñnnЕ7^œpÙäÌ/ˆl>ÙtûE6Ÿ>*²É^Ùî,"›a¿ÂKÓÜÖ6oH¼~ÆeúÉ©ßèCácÐù§cx¡…SE' ŒáN7Ùdêþ™· Ù¹íaŠ7nݤó.'Ù$ô.gÙ¥ôêivI½ËYvh½·PЀöõöSc©÷ßÿÚ—Òë…™XêúŒÑ×îAD  §®«/I½(-?µ8ß»qeEÚ¡cgJRïÁU¨|k:…34L ѧ”^$q…¬àˆ|„³^¸Þb"!õ"€Åà{m,õ&Ží",C)½Þ†êyì{Ë,õVNÄA=¾zíÈoŒ„ézQ:=’.Ã#©÷’± ½fHhÝÓ¼Žâ½ïìGêE)¶@ÝÖ“Sn"}­£³f(½—ôHr ­³bkýÃMã N•Ð#)‰p ’ jQÆù`ÍÞ÷}æGôX¼?Œàfš¡ôVÎè¥)½ˆJ ã¸÷Ò‰zTâ{Ô•a\§ôŽt Z‘H½”53PW3¤Þú >|°Ê‹XíÌŸ9“Ê+•¤2>B彨ž?ÊÁroæ4ùQ²f†Õ(„?о!äÞΡ¦üéÐ{Ń?jæô0©j=jc½¨§p?Ð@3&ëÅ"ëh™ôÞ›âÏPZc½›)û°,ô&ËšfÆ4MÌû…ÞÄOŇ ½ô–YèMœÀ6Ð13¦ibéâ^7à3›’†×_L.ø%©Wy=RTÎ\y JÅ/¸öI<(Å5äÎö\#[)6‚k$QÁ=Áµ‹'žqÓõz×~,R*מû53Í„ÖþµYÃS`Øô„oÖw6Ó,Y!°vQ6 ë;mgú$Öøž+ÑŒiÈ£äºL{ÚT¨–Âi¤™ÓžxÑRá4oHNß3fV!N{!Ë;”ÓÈ%% 8§15ÉÙ$œ¾«bÎd6á4j<ÒëN8>TG@8$i¦ sÚûD¢½pÏ”Q$°ÆùZÔ&`X#‰úèÓI%°vsAÈlkcçŒ ¬at¨QÓD` ù—Vk7HD ^`äæòXcœüîXÛ̥⫠k$m‘Š(°öN tyÌlïx ¶2Û+OM™=7sQf£'@&ž³!ÐÓó-ÌöúÑñ ˜ím¬}oýËBï‚íÜVj÷ÎåUÛp† G± ù1ž/Ŷol¦Â­Øö–Ó–¡Ø†ºZŠmÒžÛÍ^âO ¶KåñÊí'ýBŠïò_ð-eõ|6#,ø–LfÅ·O«¹|{ýâø‰>øÎ²QS|£ÙN5R|ç“»_(¾ û¼ž|£þE˜®ߨ¨† Å7’>i,‚o¢=ŒàÛNG`Å7~›¨k¢ø¶?I "Å7 xOå\éáØ*½1»Î™…­ôÆŸŒÔ{¥7Š!G»-¡·gÓKéüçð‡(½í:Ût©)½¯!/<¦÷R ]èíåªi"1½ýòè$ôFÉsÚ“ ½Q´=ÊÝK䑇=â×Û¾ÛøM“î#úú6ïîüްµõûG°'´Y¦î¸åLçqë›x×>'Ÿ½ »Úc~+œvi‚?{e|ÕŸ›¿|¶]ýÕ«~¡ŸýŽþkÏ¡á Õb+æ¶Wÿm*xµËøuÕ7õßv"ÿ£m¤~ý5õ_&HÐjËDzµŸ rMÅ+ùæ§¾óÆS®ÝàåܯÈpå› ¼ â ®|‚u¯q囼 â-˜'ü9¼'x±5ÏÎièkßeʹߘ†>ˆeê ^˜†OÅWž†2ˆ7¦áÍ9†:ˆ?A¶ HkGÞÖ~9É&Ax9Ë.AXO³K^βC¶í¾mÍò@ýóáÌzðÿíë¿~ „²Ö¶ÚA[,0e]m[Y.´¡òR}O–¥ãX•m¯s”·µƒ¬Bó׈ÙNøðcÈ!»árš½êÜ5Žê‘D ¢ÚÁ¦™¿=D¹óè¤úÕ#:aÇ ‹Øt‡6ÒH쇪‰¨Ùºa$ G·7;˜½ö܇L…ýñv°yñ¹ùö¤SÛˆ(<¾ì:fßâóU¸yã¼OdÀÚŸµùU»œÜ=丙õy"*tbe†‡dm <½Ì^†îÊç0KUåìà­kÃСg{ŽsXì nÔgã(hY"FñÓH€µË94¸ñ}+hió™Â¢ŽÔ?;ؼÏdOް—íÅͦL8;Èbqc×»Õ}f²g<‡µÁF!rqç,L˜8X/®ÜsÑ6ïfrŽdÕ:—=yÜÏÀÙJÄäQBÛä9•+êõÍÕ‚´“Ì©Œ3F=R;(ú±t µ÷¿ÈWX·ƒôçTNÒ7Í›}¦2òˆcêÝæ‚Ä•"·µm_F²ó7Ä£Ð#µTÆ#£+2;Æ{_¿ó'ŒG !IQoOeE½Gßcr0ê½ÅhÁ]A½‡Êgdxa½=÷dWQÖ÷{RâqÅ$F<’N£ˆ÷HzD¶ñЋÉó¡ˆ_B®Âxo\õÈ•ñÐB£4®"ÞûÆ3#„G¸™Úh+á!µQÖ·~0Z+á½%{$p+áûѹ6ü‡ðÐ2¨{ Þ/!ÊÀ*á¡»‘:¯„Ç7yÝ „_Ôì…ðXrFþ˜ã7c…âbuV9JÍN•ð.(d*7èHtÛš¨ƒ ’*á1XªHª„÷h=V?Ä „w!†1!¼/èÅA„wÇ7-d†ˆ•óß•ðÞh•¦•š8&UÂ÷Cª¼(á=Wèê…÷U²bÞãG.ôS1ïái¸øÅ,¼GÿjfðöÃHLUÞ{ÙnBºðÞwðöCxï=ÆzÜpá=ra£2ÕÂ{\ 퇕÷v+e.3ïñge«(¼/]oó·–l§Êû7\‰ý°ßf$u_€yÕã5«ÀGöèÌ ðÑÔ&òñàÛ= Õ’ò¾ ñ ï½múA5ÝÓ‘Lµàýßÿö±rX‚ endstream endobj 3 0 obj 34154 endobj 4 0 obj [2 0 R] endobj 5 0 obj << /Resources 6 0 R /Type /Page /MediaBox [0 0 1080 792] /CropBox [0 0 1080 792] /BleedBox [0 0 1080 792] /TrimBox [0 0 1080 792] /Parent 7 0 R /Contents 4 0 R >> endobj 8 0 obj << /Type /Font /Subtype /Type1 /BaseFont /Helvetica /Encoding /WinAnsiEncoding >> endobj 7 0 obj << /Type /Pages /Count 1 /Kids [5 0 R ] >> endobj 9 0 obj << /Type /Catalog /Pages 7 0 R /Lang (x-unknown) >> endobj 6 0 obj << /Font << /F1 8 0 R >> /ProcSet [/PDF /ImageB /ImageC /Text] >> endobj xref 0 10 0000000000 65535 f 0000000015 00000 n 0000000145 00000 n 0000034373 00000 n 0000034394 00000 n 0000034417 00000 n 0000034847 00000 n 0000034716 00000 n 0000034611 00000 n 0000034774 00000 n trailer << /Root 9 0 R /Info 1 0 R /ID [<8F68A573F4AADBEDE04259C4443355D4> <8F68A573F4AADBEDE04259C4443355D4>] /Size 10 >> startxref 34928 %%EOF blis-0.9.0/docs/graphs/large/l3_perf_zen_jc1ic8jr4_nt32.png000066400000000000000000003275531422157504600233470ustar00rootroot00000000000000‰PNG  IHDR¬öEYa )iCCPiccxÚ•‘gP”‡†Ï÷}Û m—¥ÃÒ›T) HYz•^E–ÞY–"bCÄDiŠ AF¥H¬ˆb!((`A³HPb0Ѝ Ü¹3qîüÈóë™wÞ9çÌŠ*’*àû¹Ø³CBÃØð ‘¼Ìt®'ü#Æx ÿJtL&V Ÿ—Î ¹ •#H Ç€•”.@Γ€ÜfÜ_>̨¿|˜ü?@¢Å}ãQßø÷¨pù‚„ؘ\¶Z¬ '’ÃÎôs±g»98°}øi± É1ßü¯Êÿ€ &Wà–¾…Ÿ/`ÿßPcC##øûï|„5ø¿ÿ€oziœEìÀßYT5@÷é'gjÇD ºîñ²øÙe8‡ÏÁá+ñÍøNü ü(~ÿ@ °šs‚+!”HØJ(%%t®† S„E"‘(CÔ%Z½‰‘D±ˆXMK)Hq¥b¤öIµKH-IËIÛIÇHKwHJ–aË8É$É”é–y&‹“Õ‘õ•Í‘=&{Cv^Ž)g%Ç“+–;+÷D•ב÷“ß*B~P~QAQÁE!]¡ZáºÂ¼"KÑN1Q±Bñ²âœCÉF)A©BéŠÒ+¶$›ËNfW±ûÙ ÊòÊ®ÊYÊ ÊCÊË*š****ÏT)ªÕXÕ Õ>Õ5%5/µ|µ6µ'êduŽz¼úõõ% M`½Ý³šÒšnšyšmšZt-[­ ­F­‡ÚmŽv’öQíû:¨Ž©N¼N­Î=]T×L7A÷¨îðü‹5©k׌ëÑô¸zÙzmz“ú,}Oýýný7ja  ¾š&6>5’0r7*0ê5úÓXǘg\küp-}­óÚk{Ö¾5Ñ5‰19fòÈ”aêeº×´Ïô‹™¹߬ÝlÎ\Í<¼Î|œÃäøpJ9·,ðö;,.Z|²4³XžµüÃJÏ*ɪÕjv溘uM리U¬#­¬…6l››ã6B[eÛHÛFÛvªvÑvÍv3\mn"÷4÷½¡=ß¾Ó~ÉÁÒa›ÃUGÌÑűØqÈIÂ)ЩÆé¹³Šsœs›ó‚‹©ËV—«®xW׃®ãn n<··ws÷mîý4ž:ž|Ï^/ÔËÝë×Äzõõ©ë»½ÁÛÍû÷3MŸ ŸŸ} ¾>¾µ¾/ýŒüòýüþ›ý[ý?Ø”< Ô Ì ì  j Z v .†„l ¹*šÚF k[Üà´áð†épÓð¢ð±šs7ÞÞ$»)yӥ͢›#7Ÿ‹ÀGG´F¬DzG6F.F¹EÕE-ðxGx¯£í¢+¢çb¬cÊcfb­cËcgã¬ãÅÍÅÛÆWÆÏ'8$Ô$¼MtM¬O\JòN:™´šœÜ‘BJ‰H¹*‘š”ÚŸ¦˜–›6œ®›^”.̰Ì8œ±À÷à7g"™3{LAº`0K+kOÖd¶MvmöÇœ œs¹â¹©¹ƒ[t¶ìÛ2“çœ÷ÃVÜVÞÖ¾|åü]ù“Û¸Û¶#Û£¶÷íPÝQ¸cz§ËÎS»(»’výR`XP^ð~wðîÞB…Â…S{\ö´‰ñ‹Æ÷Zí­ÿ÷]ÂwCûÖî«Þ÷µ8ºøN‰aIeÉJ)¯ôÎ÷FßW}¿º?vÿP™YÙ±„©ÆÚuÈëPW»¢¸âýá͇oWšTÖ¡É:"¬ò¬ê©V«>P½R_3Zk_ÛQ'_·¯néhôÑ‘cvÇÚëêKê?O8þ¨Á¥¡«Q£±òáDö‰—MAM?p~hi–m.iþr2õ¤ð”ß©þó––VùÖ²6´-«mîtøéû?:þØÓ®×ÞÐÁê(9g²Î¼ú)â§±³gûÎqεŸW?_×Éè,îBº¶t-tÇw {B{†/¸_èëµêíüYÿç“•/Ö^’¼Tv™r¹ðòꕼ+‹WÓ¯Î_‹»6Õ·¹ïéõëû}û‡nxܸuÓùæõîÀ•[Ö·.Þ¶¼}áçN÷]³»]ƒ¦ƒ¿˜þÒ9d6ÔuÏü^Ï}‹û½Ãë†/ØŽ\{àøàæC·‡wG׎=>Š~4û8ùñÛ'ÙO–ŸîœÀO?{Vù\þyã¯Ú¿vÍ„—&'_ø¿x:Å›zý[æo+Ó…/é/+g”fZfg/Î9ÏݵáÕôëô×ËóE¿‹ÿ^÷FëÍù?ìþ\Y˜~Ë»úgé;™w'ß›¼ï[ôY|þ!åÃòRñG™§>q> |þ<³œ³B\©ú¢ý¥÷«Ç׉ՔÕÕÿB,¾;E^ cHRMz&€„ú€èu0ê`:˜pœºQ<bKGDÿÿÿ ½§“ oFFss0ˆÚÿR pHYsNNÆÊ/¥tIMEã$9·-ç vpAg’Zó!%Õ€IDATxÚìý”+ù]ß ¿¯ùa36MjlLlÝ™Mª ŒÀgƒ§ä«À!±Jâ37¤÷”’/Ì}’])îMO~=¸*¹ylÜ»*ÎÉs;4Qe=á†%]ÐÇãŠ3 0º2dkèzÂÌ•MŒÝ÷Å^²ÑóGõ§T*•¤*©JU¥þ¼Îéso«¤ÒWêO}ëóûsm4À0 Ã0 Ã0 Ã0ãuy/€a†a†a†a¢`ƒ•a†a†a†)$l°2 Ã0 Ã0 Ã0…„ V†a†)1®ë²¬¼—Á0 Ã0™À+Ã0 ÔÛ¶Ñh4ò^sÅ1 Žãä½ †É–õõÃ+Ã0 Ã0 ³¦i²Ï\ XÖ×Ï}ï÷~ï÷潈«Žëº¸{÷.~ê§~ ¶mãë¿þëñe_öeþqÃ0ü‹C˜¦ I’üã–eÁ0 X–Aðö·¿ i$IòÏíº.¾þë¿Þ?ŸmÛøæoþfÿÃÄažŒ/:–·Uä•å›Y7YÊ~»ÝŽôò»®‹F£×u'› ³*‹ô•0a9å=›) «Êú¢×³l/ÁˆÉ•^¯7 þÎÏÏG²,ÎÎÎFggg#£³³3ÿ¸(Š#Y–G£ÑÈ?~zzêïv»#AF£Ñh`Ôívýc’$Z­–ÿ»ªªþ¹–y>ÃÄažŒ'‘ÿÓÓÓ€Ñùùùh4bùfŠO–²¯ªêÔûœŸŸOÉ5äÅ<™F#Y–G½^Ï?–SÞ³™²°ª¬/z=Ëvr8š3”òÕn·ý”Þ^¯Qaš&dYžH SÅÿ¿eY~ÚeY¿“—&øZA B¬õÄ}>Ã,bžŒ/:&I’ŸQ`š&Z­Ö„L²|3E&KÙ—eyêýÈC¼O0LZÌ“ÙY„å”÷l¦ ¬*ëq^ϲ 6XsFEôz=@³Ùĵk×Ðn·x) ó ´]×'~¢†É‹y2>ïà9h‚J;Ë6S&Ö-û’$AUÕ‰ó0LZ,’Y†ÙV•u¾VÒ‡ Öœ¡FJÝnççç8==…iš0 ‚ Ì5Z%Iò½6ôs|| UU¹v‰) ód|Þ1ÀSÚmÛ†®ëp]—#GL©X·ìw»]¨ª \ÿĤÎ"™e˜MaUYçk%}Ø`Íj¤D†©(Š~Z),T´íºî„°Ë²<õ~3LQ˜'ãóŽÑ@×u´Z­¼? Ã$"ÙNº®óØ&UÉ,°83ŒaÊÀª²çõL2Ø`ͪKÚÞÞF£ÑÀöö¶¯¨ˆ¢ˆn·‹F£F£Z­6‘FЉ¦i¨Õj~‡àããã¼?ÃøÌ“ñyÇrÌpt•)yɾ¢(P…—Lª,’YA iG‘˜Ò³ª¬ÇÙß™d\F£¼ÁÀ¢ ‚à§óRó$Qá8DQôSÉ‚Fi°É¥ 3Lш’ñ8Ç Ã€®ë8;;Ëû#0ÌR°ì3›Ä,™ ê,óšÓ0LYXUÖçíïL2Ø`-0Žã`{{§§§$ Žã Ñh@UUNd6J¥©ÕjhµZ~mÃl:,û Ã0 3¦)ÁƒÁ`æãÃá0ïååF0%øÚµk¨Õj~*SX¾—öm<üðÃE‘e¾à°Œ§ Ë~q`Ùf6–q¦ äa=88À`0Àáá¡ÿØp8„ªªþE$Ë2t]Ï÷›b˜%`ùf6–qfSaÙf6–q¦,äaí÷û8::šz|•J¶mã¹çžÃ`0ÀÁÁAžKe˜Ä°|3›Ë8³©°l3›Ë8S&¾8¯7¾¸¸€¦ie<ð‡è÷û¸wï`kk ;;;899ÁÞÞÞÌóýÌÏü ~ø‡o}ë[óúHKóéOo|ãñÆ7¾1ï¥$æÕW_Å#<’÷2óùÏ[[[™mÂiË7ܾ}=ôPÞ_ÝR”YN>ÿùÏ—r_yõÕWñ¯ÿõ¿Îìü¼‡á=|ý|þóŸÇ£>Šøÿaêçæý{’2ËH™÷ïïÿþïGµZÍäü¼áý{ý,³çf°îïïcggÀdþüýû÷`â"­V« óèßüæ7ãÝï~÷›F988À7P¯×ó^Jbvww'RIÊB¿ßÇ /¼ÙùÓ–ox衇Jù]å—“2î+»»»™žŸ÷ð1¼‡¯Ÿ,÷pÞ¿')»Œ”qOÙÝÝÍÌXxÿÂû÷úYfÿÎ%%øääÃá0R°ç]y,7snܸëׯ罌¥Î…e ïßå`íëp8ÄÑÑîܹy|ÞL[óÊ+¯àÙgŸÍ<ªõz•J%ïe,yèÊÄÉÉ îÞ½ëÏ®M“¬äðR?vwwqrr²Þ/,Ê('P©TJëu}饗297ïáÓð¾^p÷î]¼üòË©ž—÷ïhÊ(#@ù÷ïYÝ{W÷ïixÿ^/¤ƒ'ݿמ|rr‚­­-X–˲0 pÿþ}`gggn ÄÞívá8Ç \»Ê0 Ã0pJ0Sh¨¦+M ÃÀ;wòþh Ã0Eq¢Ž•a†a˜I8ÂÊÃ0 Ë2LÓ„ªªsk»\×…išpÇÈ@۶ẮoüùC±†a†a†)&l°2kǶíXÑÓ4Ñív!LÓœê¼éº®?¶m?JA¹®ë?W?’ÑjµÐï÷óþ†a†a†Y¬ÌZqF­VkbDù Š"Z­šÍ¦o°Ú¶v» À«“eyb „¢(yL†a†a†aR€kX™¥Ðu?ü0šÍæD$sš¦¡ÓéÀ²¬¹µ©Áˆª(ŠE–eÁq4›Mt»]œžž¢ÓéÌ7PµËŸøKd†a†a¦ ,e°àÖ­[$ 899ÁÁÁAÞŸ…Y¯}ä54›Mض³³3H’„Z­Ó4¾Ö²,¸®‹V«…^¯]×aÛöÔóÇeY†¨¢(0 ÍfN'^ƒ€ÏXµ?a7²½½v» Ó4}ù»víZ,y_ÕT'i*æ8NÞ_ Àu]´Ûm<üðøvíš¿7¦‰mÛh4?š¦ùÇèÿQPFK”¼š¦‰Z­†k×®a{{;õæv Ã0 “‰ V2Pëõ:*• `kk '''ØÝÝÍûó0áº.¾ïo~>û¡Ïú³A€ªªèõzÐ4m¡¢Ön·ý4`Ap||Œf³9¡ˆÕj5ß( ¢( lÛF«ÕŠ—òë0t¨¸'×u¡i4MÃññ1ÎÎΠ˲ÝWUgggÐ4-Vfã8SÏ#÷V«Áqèº{mÛÛÛ‰2˜li4çççFhµZh4©­ô÷îõzèõzèv»~Ý>ÕñÏÂ0 ¿!]ÇqÐn·q||ŒÑh„ÓÓÓ™D†a†I“_þå_Æg?ûÙD¯ITÃ:qtt„ÃÃCÔëu¿Ëª,˨T*¸u냪ÕjÞß“ŽãÀ0 ˜¦‰ïzâ»ð•»_‰–<ÙüHEt»]hš9ôžŒEQ&"£’$áììlâ½æÍ[ >w!mxƪpùÃ0 °,Ë—ÓÓÓSÿqEQ¦œ$­VËWøg¡ë: Ãð»[‹¢è7ët:¾¬Û¶½PöøFG¸.²,çý^)LÓ„ Î5úÛêºY–}ƒ’2KHŽ(bÀܶm_¨1]T?•HÄq\˜¦‰^¯ç;GHÆèÿô» èv»ì a˜1 ÃÏ¢yñÅó^äÙ?÷s?‡'žx"Ñk¬÷ïßÔëõ©cÕjÕjyÌŠPª")È­V §§§žâ­Á‹\†ô(?£ë:TUà)Ò†aøé½ôø,)ì±±hQ3~g˜”Öéº.ŽcÉ¡ªªh6›~t4h˜Ê² Û¶!ÂøºgK’45ž‰:[/z_˲Ðív§¢`†aÀ¶í #{#qïg’„Ç_YÖü׈¢÷Ķ(ã-pþYÝÎE¦iE†a ×ëA4›M¿[yй×h4|T×uCUUÔj5ßÀug*õ—"ÿ³ EŠ¢øãÁèµ°½½ EQüæu ÃdM2<½Çq˜¦é_‹ð‰O|"ïe2L,lÛö³Ð€q3T×uýÇIoq­V å¯ü¼ð ‰Þ'‘Áºµµ¸¸¸ðÿO\\\ð\Ëá8A˜PžIq·mŠ¢L*ï”b+cl†èt:¨ÕjeÙW¢UUèà»txiÀþƒWÃÊú¶m¿õ"‡J˜n·‹f³ I’Ðëõ|£Ã4MH’4•eÁº(Õ6úZ­æ?F7AbEiKãÄ3>“¬²m°FÇQç!‚©lµZ¾QÛjµ|S–剛»išeyb~ô¢(ªµàs‘’| V8==õgMÓà8z½^¼þ Ã,„ÿ‚ øóკ®ëúûvй '''y/ŸaB倲,CQ?«ˆœ¶’$ùã$ƒúÉ2£%¬EÝÝÝÅ;wüLJÃ!îÞ½‹J¥}eŠG»Ý†ã88>>öfªLsŒÑc†jZ:Îú UB¤qÊ)ÁLRÔMÓô¯¤‚0•/ÂÔ¼àEȲ¼°Ž•ŒÀ3pÉoEñ¡y£¢J,{?IYæ;‰ñ7¤ï0Iv’Á)ÂÂè¦(Š[J)ž'k†a@’$_¶Çñ•ã áLkÕ4 †aä·o3̆@N ¹GJ<9ñ9›ÙÈAv¶(Š’‰.’xëáá!4Mí[·xVòÑѪÕjìæ!L¾P#˜ããc´Ûmß`«¸›ŽáEZçÐjµ+쩳Á:;³<”VI©œ’$Mm´y@ïïºî̵X–å+9” J+¥œÖjµÍ6X ¥þ£¨TŸÓjµ&Ò ïo(Š¢¥¿Õ¼.¿³X”Bnš&DQœp¨P·kUUý²°âœ÷µÀ0e†š™‘33xræ³ihšUU×vßHl°nmmáððƒÁÀ¯WÝÚÚâFK…Rsƒ^sŠÎP*#Eff @¼ü¡11Eľ\›<ãse faT3jYLÓœA3T÷:ËóNõ«ÀØP¢H)EäxbÅh=RÚl6'h‘ÓŽ:IS'aÇqü}¶V«¡Ýnû¯¡ÙÔ³°, ×®]ó§NíT;>Fu«AdYö EQüÑM´v×u#›æ1 ³Ã0 ëúâÙð S(‚J÷” T›ºÎŒœDk¿ßÇîî.ž{î96PK€eY~3˜`„Æ0 ¿A ¥ñÎ…jW±ÑZ4\MxÃÈðêZ™+uçmµZ~„K„d]¦× ¥iF¬Q†¬,Ëc¢€ñ¬b{ò?ñ8<<Ìû£m4Ôéœ:‡›jQíŽã8Cª¥sÐsƒÏ £Ñ(òýeYžy,L¸Ûu·ÛõÓ„©ÆŽa˜äÐ<í"dì0̪P@ n5‰4_ªQ]wùHâÖ­­-X–…•ß¼ßïãúõëþ<×0ƒÁ[[[3—‰uG>lÛöÇnðQ'ªSéLxM–H.EEt z—ë+WI¾ó¶mèºî7§q]7²EÑ!”0MŽãøõªá½#˜LPä•¢¯I[Æ/˸Ǽ½=8>&îkÖŬµ J³VUu­keÙfâ@÷ *Í(,ãLª¿VUÕ×£TU…®ëØÞÞàÝ»TU]û=,q—ཽ=`8F>goooáyNNNpppà§×ëut:¿óðp8„ªªs^Ë\KÍ,ÎÏÏ'¸È¤!eY¾±J¥ë:,˚ř‰ÉŽ»s‰ê&¼ï±…ùÆj²°+qÕä;/4Mƒišèv»~×UŠr• mŒ½õd” ‚0•bF–ÂP+ù^¯7Ñ/mXÆ“{-ÿ†@5FcâžöàÁ¼öÚk©¿Ë65J£ò’Cj^YtÇO–q& EMÃãøøóÆsï‘1JÈã?>÷gŸûÜçFïyÏ{F?ù“?éÿþ|`ôáØÎ?øÁч>ô!ÿøO<1º{÷îÜó>ÿüó Ÿ“½^o$IÒH’¤éƒÇ£ÑHMï½ÎÏÏGªªŽ$IžžN;;;‰¢8Eqõ7:]ý©!ŽF£³ä/ËJ^²’ozãÑjµF­Vkt~~ž÷RRÿL’$¥ò¹²’—«¶‡3ù¡ªê¨ÕjF£Ñèôôt$ŠâHUÕ‘¢(£J¥2úîïþîTß÷ïÍ£ÛíŽDQɲ<’eÙ—¡¸^E¯;>>^˺yÿf¢PUuÔív';??ŸÒùç¡(ÊH–呪ª¾l+в6Ù–“—×-c…ÏûY5k¢”â­­-Ôëu?b;Ñï÷qûömÿøÎÎN)›APÇ8ò¾M}?)FW©¹àÕG…£L¢(&?«Vµÿ™bÁ«OãØŒ1–' ®’|çyº»ÝnéR°æAM“ŠžZÆ2Î$a{{{áÌØ( Øh6ìê­ª*~ò'<òHªkeÙÞLÓD£Ñ€eYèõzþõïh4~VKŽã@×õ ½j*±Œ—˲ü‘|ívÛïö^«ÕÐh4æÎí&h>j§Óñm‚ÓÓS^¶w ^•z½>e¸Ý¿_þå_îÿÀDS§jµ:3¹¨;ÆQ/L.¼&@)â²mÛŸ}:/ -Q8ß×Äè4âØÓkç¢'X‹µÔÞ^ùÎj°ib$T XÆÇ2„:°SÇà« 5ý£N“q ž dh 6 \fðü"X¶Ë ™Tú5ó”ÒÉ ¥NëtÍ’C”œüeK÷]Ëx9q]w¢ÔjJeYö§}˜¦9÷žCÆnÙz|K¬'''°,Ë¿aÔëuȲœ¸Óîî®qÜ»wæ^~Ž}˜Ï|æ3°m±êh³‚ UEQ&æpMt5Ò{?Û¶Ñl6ÑëõÖî%P³Á"Œz$‡}\£?`ßôû}|ô£ÅïýÞïeºÄ4å>ýéOãàà7nÜ@½^ÏtíEÆ0ŒBަ)xõÕW3ŸMÜÓ`YVd—Þy3u‹9VÓX?5£¡hÝiìTx†5 $¯ÿ,NNNðË¿üË™~¼›`c:úݲ,¨ª«{)uÍfRpaÝÝOÃÐþ=3mxtÕ÷ï2AvÉ»ªª>E®ës Vêì›÷½‰tð¤$N >88Àþþ>*• nß¾Û·o£R©`ûûû‰Îõä“OúiO?ý4øEàQêõz‘´?þøèþýû‰‹o{½žß°‰Îuî´ xÓ¦ÓéÌ,æ?;;ɲzp4É‹Ï; I’¦Š¯Sáx4Íëù"–jt”*q{&t»£‘ ŒFm}â3­S^ÒïÑ(ߦNgê1UUG‚ dÚøˆÞƒÞ¿Õj­µ1@™Y§¼lÊž~ã ú9;;õz½‘ªª~Ó½óóóQ¯×õz=¿ ÞÙÙ™ÿÿÓÓÓQ¯×óÿ~~îÿœŸŸû÷I’Fgg«mòôùèÜÔðïøøx¤(Êh4ßEQL|/[—¼lÂþ½IPó­Mj¸ïßWEQF­VË¿¯Ä¹t: ]örI’FªªêšYF^¥Sê@”…^¯×Q­Vqÿþý¹)  íƒV6yƒ©Y§E,yø‚ Rhpt~ ë6€3zÀ’QJ›J½FÊ Ö…tù¼u¹¨?‚ˆxiɶ è:pz H=àÛ~øŽ7eºÄM‘ï Žã@Ó´©Q*T/‘ÕiJñ:;;ó£/Á&,L>ä&ãÆ¥aäË^É…ˆqVż %í#Æåkÿ‡Y4>+¼dËB«Õò=Û” C!jú"˲_çIõt&{¤Œã8h4þ5íºîDµa‰ú¸® Û¶á8lÛö? 4“®ë÷IQ ÕÌe÷ïM"XÇ—wZcYa/>”’T×QÍfªªÂ4M†Qø&ŽIHœ D§ \\\Ä*ʾqãúý¾?ß ðnêt1T*ÔëuœœœLjn‘”ú+I’Ÿ²E È<ÁØùÌÎtÍeÂzPÚ°]×Íf&RÔÜÕ"àh`vçâ©ç»@» t»€(=|äç3_æ&Èwš9Gi‹€—º(I:N&©Á4Œ6[RP®z›"›Œ‹¦á2"…Ë߃Ž@yÎ!Íø=ü±½S +ý„ÓÕƒ¿ïÁ”¯u§jQ9I§ÓA¯×C§ÓA·Ûõ¯¯V«Ó4cËdüZ–Çq (ÊÔý‰œ[áºÕ"±‰û÷&Ñn·'êø˜ä°Œj¶Œcžî5¦iBÓ´sì$аÖëuT*hš†;wîLx_îÞ½ë?gÑ9vvvpëÖ-ÔëuÜ¿<˜ðöìííawwý~ß/ò~òÉ'óþ®|t]‡,Ëèt:h6›¾×x‘§øÛ|†ï¢‚åö1ôû}¼ð °T›öJ¥27'ž†p½ž èõz‹S§  ÿ'ûøMû7'…ÑžýJÛ¢Ùs™ÝìãÞ\×ë¸û×Î÷/Ð˲LÓ´àu.N™S,Ê*ßa‚‘Tª³#¥;¸!v:4 †±TÚnPÖSŸfš^Ä}]Z×4 Ȳ6϶fÓsQ6Ášk{7EÆWa1Ò† Õããcü97àôôÔ7"ÉØ ++Ië;ɱI)º®ëNÔÄã9”‹ nܵZ ­Vk*²µ‰³ –í|¡¨½¢(~*9§§ Ëx± žóÆyÅA„J²ÔÖápˆ­­-ÖR¿ß¿REÙQƒ¨ ˆ ¼ù½/<ÿÂäãç³_Bu²™¦BÚˆŸþ&ÀÙÙ¸ù‰¢x׬ V@ñUÇ™í0×9ÀDCÑUÀSPkµš½ s||ŒF£á7X‰ Ò6|IùC¬÷K[‡g“EdD8q‹»™uÓl6!Ë2,ËšR¸ÓTÀÇ™ÈþIƒN§³Ñ SLH÷±mÛÛÛ~`€a6jlÉ2>ŸÄëÉÉ ö÷÷Q¯×ýà§Ÿ~ý~wîÜÁÎÎNÞŸ©x¸TàM¼ ÎÅS,iŽ_¦lÂ3<“fü†%R¶Š²/ 8Žþßn{õ,ã^BjuiW ÄxŽI’ ëzdj¥R)Ž’kÛ6ÚívvÆ*±NƒÎ¶³?Û«ÀzŒd&1¢(úV Û”X*×I{ý ³NH÷!Ç ];ì4a6Ê.ëv»¼ß. Q—à‹‹ àöíÛõª‡‡‡ØÛÛÃþþ~¬NÁeeéú"@Ëó¦O¥Ï赡ëº?!3\ŒG?,‹,g£œ;ð ê8ú ¹_‰æž=‰ š»  ’Â=+2DÑ×`s–0¶m£Ñh`{{š¦ùÛ3C½4Ýu¡iÙ‹jd]Oýë½¾ÏÌÌDÅ•ë’AJ>wÑfÊŽaŽJMg˜Möm¿ä¢ õýy“(Â: pqqá§¹}û6NNNÎa-;K¥pÒn°q‘­H 22Ÿ7Iº ¥õFÇ”NüÜ6å­ý(¾úÅó^éF“fô©ÝnCQ6V vÄ‚´d<<ŽéJ’±n’¨†5Uµ, ý~GGG¨V«~ôu“q'™o#²Ó­ªª0 c¢)ÇÒž]÷%kû€qÇzIòä?|/³m ÝÆoîïã =”÷j7rZš+ÖZÒœàÌçÊ—rÀÈ2¬9t.&²†-ÆÃã˜.¡’¥ŒHd°öûý©ß)5øÆ~Ú0³EQ ë:>þãÇ·ÜXídtC§úÓ(¥6‹}qVŽ"­³ÒlÛ3 ÌîÜë\ŽÜi·½=¨×®Î$QM£¶CtÏÎðG‡ÃÙO"™Íšd8_8V„ðjTppp01º¦R©$NÞÝÝE½^‡mÛxî¹çP¯×'êö÷÷Q©TüãƒÁ 3^c ª Ï`´íx¸´Ó²K&$Ìî‚Ü„g,_Ac(¯|ã´àX^Ĥ#Y¢®…¬7ÿàùã¤_Æô¨¥¸¬«yT(³ŒÏcQJ0à)úÁHS0K!˜v†Ò† ®gëD*8›"ÛŽã Õjáøø8vº®$IÐu=òaB¾MÓ,‡<…eºègDÙd|Q©Å¬×„ïä”Ê‚‰a-]Ã%Y^„U3Ëš‹e°RíêÑÑŽŽŽüzÖeè÷û¸¸¸ÀÞÞ/z{ûöm ‡C?ý ßïãöíÛþñr Ÿvüçï)¾ºî¥ÌóN-«F´0®#²åTuÔÍÜ×’P6ùv¿¦Ñ6qÆð6¦$Þõ¼7zËZì@2Œè¹“q¸"ã Ê&ãI Qó_'AO~TP¢h)†EgÄ&É69Q$IòÇ2-‚/Í’SJ &/U´)o¢22ŒFÍ¢¬2žÔh : ’o×u'"¬²,ÇŽ°>C&H»½>ù ö(ÉÈáË`=::ÂÎÎŽŸ.¸³³ƒ£££©q7q¨V«8<<œ‰sÿþ}Þ…Aÿ§ÔúÞyô‰jXÇ-/ |ì LŸ§/+O¦96ÈXÌ žñ]„nÀ9QFù&E†FÛ¬M É:"Þ¨aþæMpUŸ¦5ëWdÎje<q¢«„ªª~Š\X‰™Õœ¦U†¨¥®od=j\6E¶c;CPs¥YJ9uÊ6 #^Ù3&ªÇAÿ¦Èø99ÁÝ»wµ2KVò ¯¾ú*vwwqrr’É÷2¯~Ég•ïL' AÚLm{r\FZ„ÇÌ,º~ Ë’R{ö(¥Ï¶½®¨F¡S€wwwñÒK/erî²îá‹HRŸŒ²†ëYÃ×EW 2 ï-AáààwïÞÅË/¿œêy˼Y%uQUÕ¹¯¥´àR8`ŠÄ¬”àˆ{*íßËèØ‹(ÛþMzZƒr^$4j/¦ý|–e¡Ýn—+ضÇYpY“Q#ýæðñú!¼õÏý¹ÄûwìÖ`jÐ3³,888ÀÍ›7Q¯×ý¦Nó.ˆÌ<öè£â}ï{W^Û,b§s=ò‡Ó^êy›»„墬Á ,Ȧ{¹î²étœ;;;xê©§2Ý|Ò–oxä‘GpxxˆÔÖÕ-/ò{Ѵũ틈º~!ŸNvQt»ã´ÞNgÚûMó&OO½çÕj¹4̈Ãáá!{ì±LߣŒ{ø<5\ £ª*Úíö”ò£(Ê„3¬pµ~¶íl¡ì‚°··‡§žz _ó5_“Éù˲Ïb•h‘¢(suV«ÅÆjR¢.÷[Ú¿ƒQδ)ËþM#–’ÂNÄ ’$EÊwÔ5cÛ6¶··ašfdWíBCM E1{çzBýí[ONð…ïû¾Äûw¬.Ái3 °¿¿­­-Ü»wo*õ`¥˜ñjøÆ¯J6ÎeÙk€.:^“§uCAÇ9½A)“|‡k9"£@”îqzZ®-³"¤Ëàº^=H·ë)ôSà(k–”IÆãbÛv"ÃR–eTHº†OA*TtµÑð¨aå«Lу ÙÙβ›©$IåŠ4E —¢:ÌgHÙd<‰,“~^vœóѲãããrÊ;ÉœãxÿÏ2sÆq&Ïoc)Ìe)ãçÞõ.à…½M.«ªª ׯ_à¥)ÐÅü^ÄöîHȾC/!^ݨàtÕ“-A‰œM뤌òMD*#¦9N•]…°‚¼¦²ˆ°:ΤW[–'#Äí¶÷œããÅŸ­Ùô”üà¦\Æ›XJ”YÆg§áR˜ãããÈ×':Ï?¤wR'à"ÒaSd»PNf¶ÁCÔ®L2'[Àu]?;/º x×EÔµ!\×õ÷óF£±0=¾ð‚§§ä‘ fšÓ:’ax÷ž^øÝßM|ÊØkT^úÁÁž~úé‰Ç¥X–…ápY–'Æã@½^G¥RA½^ÇÉɉ_+kY–ï­Î‹L…VƒWšÄâºÀ¾É{-Ž…¡lòN nµZÓ ¸izÑÕ´¡ôÛ¬"•²<[!wï§Ûgˆ° h^”MÆã¤áRÒ4÷X=‡ Ëõ›"ÛË6]b2b^tkÍQÙdœöæyA#]×ý‰áyÃq‘$ µZÍ¿Ȳ\îÔwÛ—xd}Ÿ ¾½_pÒ4O”e/@ ŠÙ¬×¯_Ÿh¸D,›[OEäQ0 äÞÞvwwýöÛ[[[xòÉ'Sý~3cÀYÄã”V™Ö`ÛÀoý/À?Àú›-13)›|‡S1ªnS’²IW¢¹€Y¥BE) tÓ£Ke38 @Ùd<¥¿*²ì]šæ]ßÜñÀæÈv¸Ôƒ)Ž3Vê34bË(ã4Žf¶mãøøx¥=¼Óé ÓéøÓPJm¬ž<‘n•uºyTJ;¬)–”-4X+•ŠïeIƒ½½½…ç«V«xæ™gü +ØÑ,b70p|á§¼?ê$ Fj ™áù‘*ð•ÃRtå½J”M¾¦@Ò tS TMÓÎÎV;×¥l2‡¤ — K’N¿Ž×H-‹ì‰’²)²½q#:®í¶g¨6›ãûT”UÆçe P:plLö:ïgáï>X~%Iñ3ÙK k­·ódÞ í  xÿÇi°JÒì«"’uÙÕ¼å-ÀÝ/äýÕ0KR$ù^HšÑ—­ý3"KQÊœ2ÉxÒ†K…Å0â+»¢ŒFy¯¸”]¶Ù`-!”ž¯(@³‰‡Þóž\—S§5³tð+——é úžt0¤ô÷Il°öû}¼èìtãÆBuÖ,¼ èþ0˰gð&5X%òë/Rfy¨æc.i7„h4€óóéÇ×™~cšëÝ̙³LÃ¥ÂA BÔ½Êq¸fõ Á |H:ßør¼ÔSÿïç½òÂÀk Éà~{«eY¸yó&vwwqttäÿìîîâæÍ›™ 8.:€úæÿ‘ÒŠ")H66'c,˳˜ò±öž¢«Ž3Ù¹.‹N‰Íæôcó”zæJ²lÃ¥ÂAݼéÿš6>¦iœUpEH2¯’ÉÛö²ê #¹òÞjáÇÞýî¼?AሒmŠÀ2sдt;;Îäý%м Ö~¿UUqýúuèºî%Û¶ ]×qýúuܺukªãئ«ãž à‘çç˯ªµ/ß§`Ð~Ì÷I&6aƒ5 ¢R8ºÊL`YÖf¬¶=6JeÙ3Z]×Ëj„õf10¹áºîfÈsq]O‘¯ÕÆ%`4»;!¯|åWæýi éß’$E¦º³ÁQL®oéúì2F]_ìô—¤Ô‚Xëþþ>dYÆááá”`ßßßOuqEÁqœù‘(^Ôó“¿çdÓÉX<šÆ—vœ““|–ÍNÓA¨WÀº¡F—LrrñÄ ‚·q¦õÞ®;[ð¢®YAàè*3ã8åWð]wrî° xFëö¶gIJ“æÊÀõ«9Ñhx†*à¥Þ{£>ʾ·ä̼R –õFüRÇñ ÐZÍûi4¼×vrZ–÷šEÐN'uÙ_h°öû} ‡C<õÔSsŸwûöm ‡ÃM žk°êðºõºîây[ËÎGëš×8«Ýžíœ¡ùó‚àéEëÿFï‡àgøÁ|¿ñ¬w±cîèƒ8)Ë@×Ñ¢k%.íöfu1fÖÎFxèƒéÀ„ªz†*GV¯\Ó—1í¶g„éõ¼ÎóNöcD®Aƒ5ìd߈½; LsÒHÅè A³9Ö󎽎ñ½ž÷–czž®OÎ\]# ÖÁ`€J¥‚J¥2÷y4—õââ"—’¼©ˆÕ¬µy¶EWsÀu=C/Jç ëtÖ¼2 ÏVEïúl·§ŸcÛcÇgðó-ßrޝýÚW×ûe–‰uG_Ék—M›êH#b2+ó¥ ¬#»š)8Qã§D‘ëV¯(l°f)íìZ;²,OET-ËbY"¬K‰¢§°‡9>g,l,뎕윜 »ommáÁƒ¹,®(Ì­a5P¶Õ"¯Ã¼Æ2óìƒöå{vk2(Â}<‚YQÑÍuö´ÑõÉNð¦995Ŷ=R·;}}=öØçhv}%™›N3kü̪PJpË{â`šÞk¢fHÒ¦³‘|ejBs¹ÙÑœœ©_•eN=dÄì¹Á,ƲöîaýH–ÇúU­æÕâ5ãæ|9Õ„PfïÝÑ„ÓÛƒìÆw¦”C`< AQ¢ƒA²|%êß6]"Èh¥Ñ5ƒÁÀO®T*¸¸¸@¿ßG½^Ïû3¥†ui\FzqTLF> ðE†¤¦Mí[ дqæ‰ýq ùk þ[ŠhgÖíQÓ&³‚Šï²:õ'ˆ[)IÑåˆÝ®w¢4ãf“Çš¥ÉÚëWç!Ó#ýÑ©ÈT½Ÿëõ‚ý4ʪ4´ZãyÈlÇÄÇ0Œå<ôôegÕ˜,ÝJžÊŬÛ¶¯ŽÁJuCtßèõàÛ^éÒ‚à]G9_K4]üN–åÙΑkf&î×–e¡[ææ‹„±Mq©óÐ-çªêÀ± V‚FÜ„=ƒÁ»»»sCøeC×u¨³”ã°b5V ŠˆÜsí­?ŒÖï{X»}92©ÿ¿á¤Ó4/$)ÅT<)ä© ž*­L3EñløUî b è,I¼¡¯´f¤&!¼†çzvÒÊ€ Í!Šå3ú(ÎöL24MƒmÛ8^¦ã¡ëŽ7¸¬&Aà†JLl–Î(#sôDäw¹Äõ_Ñ462XiïÎq¼e©p]÷jÉy˺ºÆ*3%ø*BÑÕ©”À¬l°8P¨ªý™ÿÖïý)ˆ_æ â© Hoûœ~å·C:Ú$ î?úáÉÜØ” VMËNßR”xƯmsÿ<Ðu}ö†OEÄ+BÒ).;չ=XC×,Ë_¶’T¾(+§“%§ÑhÀu]ôz½å¢Q޳T­ôLh.Q¬Á2 ¸R —B÷¯¬G¤¶Û³/Sº×E•·ÓØ4z\Q¦ŒªÊÍó¢wqE¶moÎ8² ®»°–ŽÆ×mo§÷¶eŠ1²ÁëºÐ4-:ºªˆÒåãþÕC›¬ôÁ8~æõÞ/P?õ]¾õ Ëp] ñáw/B1Œñ&Y«MÖª¶ÛÙ–BQoÊž›…i–+¢µ †Ó4ÑÉ0,gžŒQæä¦é{šOÙЫGÞ/³:áe@°œÒ³Ê­Ÿ?ñ 4à•RÉeœ^¸M›ÝÐ…ièº÷³½Í´˜•بF4s×õ.—ímï ;FÓ¸ŒÂ͸eÙ{Ÿ¨s»®— $“÷¾vۻăk”/˜"®eíTŸ%Aƒ•ŒQ¿ê8ž°×j ½ÏÅOë£[–÷¶eq”$N Þt\×E£Ñ@«ÕŠŽ®Z¢t$7‰K¡¤ôCQ ÀËg9àŒ 5)=)†w^*}==4$)³²Ø ,Ë3J;ï=-kÒ(0MžÃ½NlÛ†aËG—b"Š^_%ÈHc‘$À4¡vßY¡ª@³YøÿÊ»ÙÓ¸ÊÜxU’Ø`ƒ®ëè­:Kq– Ðü;*ˆÖuo“r|jÚxc nÄ.gVÀ4ÍÙeLEƒ"Jtƒ îq„®Oö, F’&.-Ò'‚þ#jØ¸ŠŽ®ò¢Q¬ÆXw£d‹àó:Ïþ fÞq}cÎØ·eYÀ‹/¾/Ÿ¿KÁq]·¸õ«?ìý!)’'¡Š©èSY\Üîºã>QŒëzúeEµš·Î4U9ް«‘gÍDMS¿Ì;œj4Ù×uXÀÔ_8éu©iãÆwÁý?xÚVk=c_hîv¸ü–6øð=ŠÉ×uÑl6Ñív31Vu}l4Ѭ(ÓQKç?? ÷í_?±‰Ò¨"íÙ?;3 rf´v–)a, áfÎ\Ç:a“zí“m{¡P §ôzÓuv®ëi¼®ëyêÂ5§›0KbdY.~Ó%Óô,3 íÐÆ“v:pÿé¿Bû¿¿ð"@ã4R’î1á½O–£³e4mÅ4 ï² F5 c|év§/OAð.[òIÍúª½Ë?©ÁLºž$_ù•¯¬÷ïR@¬ÐQEX–UÌúUšoYóÇ$¹î¸£5y;2rÐÏ›/OýÊVÕ4ͳӃ¾V2„ÓþX #¬ƒÁ Otqq‘îÊr@Ó4(Šm¬Î‹®ºîÌ¿ yâ¨L©% ptÚWýÐûÅ7ŽŸ˜ÒõGÓŠµô#ÊØøÜ…Ã4M(Š2?eŒn ÿ8äÉ ÛšÔ7ˆö‹7¡>Þ›š %Š€üoƒaŽ”A!EçicTÕÕ³Â_E¸kv‘ 7ˆÚ”LÀ¬˜ÛDo¨;\\C¡ÕZOz s¥0M³˜Q'‚Ràeî·ÿeÁµFl^–- ýû?ÖéÿAÿ-86LKBK\ì×Q”錓à}_†”¶Kóãã$`dÄàúõ—²}“ÎrEº®{YXEÃ0<ëO=áÛÞ7s ¬aÄwašž±ÙëyòÐn{/ êBótlj–5,¬Ú•² h­Š2¾ÅQ…W¤aÝÚÚ*õHÇq`YÖl…†¢«Qî ÓŒTVjµq½ƒß¾üÃïF³ú«è¼1‘3½V‹÷ ˜&µå70Šƒ,{÷2\£º© Âxt«mn¦¸8ŽSÌúU²&OЂ©…áçŨ?"ƒ’ ‚ ")6J]Ÿe,†3–TýÐjM:Â&’ ¤W®´0ÂJóW³bÞìÖÁ`€­­-T*•ÌÞŸXè}—À·å JÁŒÑÁümÚ-ëKà8_²”Îâºó7SR¶‹ìd½jE¾©«^”BCuÆÝ–½P€¨‘•™R U\™3  µ÷ú™\Òç cœöõÔ W/*› œ #ÓÍ-k܌Ȫדeyk¥Ï”áyl¶=ùyž}öHÿƒDPŸGj^ù¸ó¶™  ² xÑÕ…ÎÈY8ÎxÈyZÎÊ7 l¸T¶­ªÞ>V¸ÁÓñ§nQÝ.àºþøI¤Û´Zã,ÍE#BW¢Ê¸á¦ì°B¬Qå+8,Ë«Ym·½k'8Ö‘ê§g¡i“MUãŒ\¢¸[ܯ–²ÝhÛQUï}ÃNùNgì„RÕ3+G9rÿþýÑã?ùø>ðÑã?>züñÇGúЇžëùçŸݽ{w©uœžžŽ$IZüDQÎÎF£ÓÓçKÿ»RÕÑèøx4êõF#EÎÏÇïÕëŸwv–þ{o"«ÈK\Ò”ïÑh4úà?¸ôZEõ‚‚BUG£‘,O SˆããѨÕòþUïr¤±,ÎC½ã<ÿü<Þ9iÝQ2~>ùx¯ç}ÎFg*;iËKEÞ¿{½ÞHUÕ©Ç£[;1ì€U8?ºÝñïQo%˳_+Šãk~¢ªc]!øtk;;óþÔ•Z­ÑHÆkY .NA:˜$yÿ.#/ S‚ûýþTÍÛÅÅúýþÒFòp8œ›~»¿¿J¥Û¶ñÜsÏÅ®£]MÓføph»êDq¦«‚æJfÑš\’ŽœÊò¸;Ê£NiÈ”Ú2Ë‹é8ãt3Ó\œêKA¹n7Ú ™×õ®ùp„B’Æçµ¬lk Š&ãQ†Z­QqšVQW5SjÊ Û¶m£Ùl²,ض½\í*Ím¡æ/«Ö,8θvéôt"íF–gg¯˜f¹fAneñY¬4Ž:mmo{ÊBÒ99‰<6Ñï÷qûöm^mìÎÎÎê£f@µ3S tx ‘ cn.Ÿ®÷ê,RrÅK 8>žn¡nDÉäK‘äð÷Y7&×½lh§i0¾á0ò8 D“$ãåøØÛL³Cô<Ì4އŒYjèJK¶=ÝšÍqýÕ­Ó¾`ýMi7Ä BfƒSœg¬‚0ùØöö¿Ïì».šŒG¡ë:NOOÓm´´¨.ƒ)=emÃ0ÐétüŸ¥R$Iƒ$ TQf+ð4‚&ŠàÀQU:´5Á×åÃÊwª!eÖGd<Z-O‘>;óþoYñæ_“ü2ÇÇ“yº+`“zFœ9ÂÔ©šh·ÇMÃÂ×5#•>Éò¸ ·×‹î˜‡ß6—±6;;;8<<ÄÞÞÞÔ±û÷ïðjg‰jµŠáp˜ÉZÖ®ªmÜN+„뎻³ŸžÎn<“¬'•ƒ"É75›U¿gÛ€üÿ|PX¿ò–)C‰˜ÂQtÙ0wOŸÂq¼¹Q£6‚ׇ,ÏN)™•nrm2^»…mœùZ­ª¦¦Ë3P_iÿÖ´ùº(ìßë³¢Ò#ÉU–â}…²¹È±7ã |¹v:ã&Åa¨[ðª*ófaÓ¥u3¸¸ÀÖÖVjïeDQœï1wN …ßÙCÈÄaò xéî­VkæÆoý“— ~ÑoszXº(¦'Ûelj¡ªã()yït|^ƒàãaÇ5uÝ#('Ž3=îfݬ[Æ£0M3ýÆ]½òA¶ ÃHÖ@¬ÝžNÍŠ"8 =ÍЈÐ,¹Íê@zhò0g|•—"È8!-ãá&Ïò,yC`š¡&¡§FK:Îdj.0ޤ’Ú|HÔ\©Ýž¾ÿÏ‚>ž¦M¿O:F#ËJ.ÖyÌ›çúàÁƒ™Ç^yå<û쳉R•çEWÍhïôöi÷ôÌÿ‹“0’\Ÿž²±Z6NNNp÷î]Ø9Î,+ßðꫯbwwwf*O˲àºîÜî‘Η>©ë'/œiz›à¼´Õ«ÕjPDuÝ$±»TÕ»Wïîî⥗ò™ã·Î=|ój¶W8i¹ïöÄÁÁîÞ½‹—_~y­ï»Îý{‰¢«º~9à:ùµà8€ýÜÅÔ EÊŽÜÞ¾ì.ßÍ®»úU…öïÁ`°ö÷.Âþ½¶íÉj­¶\;þpã "¦±JåSÁ,¬Zm²gEЙLÏ¡K«Û·È‰kÓÀ8×^¨¬Š÷½ï}‘)Q†Y–gÎ-Óÿ Ðzr\;FQÊ Z8Þ¤ËÇÎÎ*• ^xá…µ¿÷²ò <òH¢Sš¦-lÆî!£ªãÇÒ¿Rv’´zÏI¢”ãÃ܇uíáó°m{9ïü<8ÂZöööpãÆµïáëÜ¿£pŽãÄ“mÇñ,Ë%ŽµÛ€àü&Ži†Yà´”Éþ›l8<ôöïyò–EØ¿o嘡\WrÌäd•QcÊà’[­É,ã N58i»…²Ë–ÕÁc¬Aå‡<0Q Ѫòõë×xi tqÿŸÔ# ÇðÐúÇÓÇX‰gVa]òM™yŠMTzHY7@Æ£#B×%ã³°,+›9}eϧ*)”‘Z„{oÞ²mšfüèj»¸ÞÎ0¼öZÝCÏÑ/ë & €"ì1Lvä-ãÀ¸~u¡cƶ=c5AËZ]÷ŒÊfÓ³m½eURš/õ­ðÖé=N¥BáÛƒ d»o]5ÿé”àëׯãöíÛ¨V«þO½^ŸzŒ~V¥R© ^¯O¤ÍX–…F£‘Ú‡¦ú¦Èº>Û†U?¼~ÇsX‡|žÁ• Üh΋Ÿ®[žÈ!SÖ%ã³°,+ýè*¿¸ˆI1¥ëÑ]±ó OÙv]wæ¾>EœÔ08Î¥2ÿÇ~yBív'º‹ºn¹›¶0‹É{ÿ€v»o|$ysFö…1 ïÒèvçOµ1ÍÉßn×{« Qê83û±2°0ÂZ©TR ñÇeoo»»»è÷û~‘÷“O>™Úùgzà/g|ˆý,俸ÖÌ\!²–oçR£§»Síu»é¢÷?˜U5q ÃÄ!kŸ‡eY›1‚áŠáºž‚Is©9‰,Ö b8|=^|ñ«×¾Î¼d»ÝnÏm 7A cÕ0¼ïšF±êúe@ö;Þ |Ç»ýç™æ¸¶ŽJbÙo³Ùä¹Ï-×KÐQjJƒÝªMs|Y,Êoÿ ?'(û|¬—\kXëõzdã›jµŠgžyÆ/8¯×멾¯eYѵ}†È2dó+€¿žç7ÃlyÉ÷¬´1˺¬Qm}Îûþs7Y¦üä%ã³ g ³)Át_š/ÕxDQ¼ × ƒ­RùÞùÎßÊlmE’mMÓ ¸I$uÆÆ…ëA'| MZ×=e^=Å~–K3ƒãZ™Í H2Nèº>ípÔ´±µ3Ç6hœ ;é/Õ~_¢=ˆ³ÏŠGlƒu0àèèÈOž•r•VçÕ­­­L.’¹ã, Îßø8ÿ`Ye²$+ù<?>>?Ðn¢ËRÑ•M(ͼ³ímž•ÇdG–2…eYËׯڶ§ÍPxºê1™@†ªe{¤D5!!ÂQ=×^zé¹­²mšædÖ€ãx Eq¶-@Ê>t&+&FMš¦·Y¨jâæaT^ IcÙŠ¸ÞcÁZÖ8³Ö™|ˆaÝß߇,ËЃý™¿ÓÎÎTUÅÓO?½özפÌL6M@–!~§¼0å%2XQ *€ú!0G¾b^”™\ ³ †aL*ôóÐ4ÏkV€H+/‘‡j:‹®Q–½(é²ëuO ¥yÑïÿ9挌Ü À$IcÙÖuï \QIÑõd#4dyl'3LPö£(ŠžGË0–ž4NEÑ Î†K Ú› ÃÛŸXÿ/. #¬TtýÔSOÍ}ÞSO=…££# ‡Ã¼?ÓL¥ã›n¡õñb+ 3Ó4##L¶ oçæ.KÌA)d±ŒUÓç –Ø…nÀö¶g{Ï‹zÑćfs<À~\wlï»®·Ëšý|ŠjP0{UãZÆ3 mxì±Ïg󈉈à}¡+zg~wÔ(…Ó$™lñ;`›æJÆ*àíKAÃS¼Æb³²9(u˜“hŠÍÂë`0@¥R™šÁDiÀ¿ÿþZç5%!˜lc-à…ÿ7ðÛï@»~1%Åqˆ¢8¥¼Û¶§èËZ¦ìИXÉz›W¬Ê(^·'Þ0ÆÍoH—k·Çcƒø#J.ÙK’÷Üv{y{‡ŒEÒ!½ó‘ض½ï…F"¦/2+µoÓˆì–:cvü<¨Ä5ØTf™Dž½Êd…uéù’(½}ÅY1Ô¸-Éó9PU|¬[[[xðàÁÔ㇇‡y¯=1”L^b«çmä7ò^ì„iš“ÍÐ.5“<”k†É]×ãEWm{l©-é±wݱžšw$UŠAMˆTu¬<MQc`»Ýq³ÝÏÅiU·ë·®›L9£Ia” grú’aœ%­–÷9¯Â~Ù-u 4Í“)ê)F2Æ0EÁ0Œq&Á’–#e{ÌkÞ6Î (> ÖjµŠ‹‹ ôûý¹Ãúý>LD]‹„mÛ¾2?6RèxgJŒmÛãMÿRÓu%¹Ley  ×uaš&NçEœ\׳ö(rÉ Á4½ÓÈòdcÖ4²ŠƒK¤ udU”xµ†¤ßIÒâèiP‘«Õ&_4f%ilˆÚöleŽê¿Ö…㌳º/UŽ„²ÁÒH\§ÒlIòzØ-eòÇ4Mªˆã8ËuwAÙ%®ø`æË`­V«888@µZ4H/..ppp€z½Žjµš÷gŠÄ²,|úÓ Âíñü2[Ò™ÆÃ0¹tÊØ»ÿÚùW ö¦3›‡¦iPe~t•B)Ìn:>žT‚Há§·ˆ î•¤›QT 8±¡Õò"¹Š’,?éû°­¯ªÞÚèG‹Wö9ÞDÚí6ìFÃ+@^" 8H0pÕëyF?Ãä‰eYÐu­V ïÿØÇð·nß^ê<”ûÙŠ^¯åíäŽ3΃jh©äÞ0LNøÑUMƒsñ¸oþj6V™Ãqhš6?8xKYŽî¸Jõ¨d<´ZãT5'ÅÌÂu]ü?øƒøî/ú"à—~)ö먾:h®£¦˜a–Á²,t[­ÄTžA}™‚™)ÌæË`¼.ÀwîÜÁÞÞƒÿø¬4á"ñÜs¿‚w½ë«=Á¶T´8X`JŽmÛøs_ú¥ÀÏü Œoþ´Þ›÷Š&}Úí6:Nt*0iìKzj( –F Ä©ƒ’¤i£ÀuÇ3+ T&>š¦á_¾éMxÝÝ»sŸçºÞ(Ž}ðqe–aòÄ0 |×Ox›äñql‹Ó¶=Yg9¿ºÄ6X‰­­­¹Í—І¦¿ò+À{ß+y $]æfÁ‹®r:³ضïýú¯T¦öœ~OÞ+b˜tq.‹ï”(ƒÔ²Æ³ûbž×^’¼Ô^š¬—p+]á & ¶mãú/ý’—©6'/Ûu½ UGšŠžÆÍ0„eY¸ûÐCãN`  ý4NS9f³Il°– ê(øŽw< Izÿ¸:ð ÖN™a6ÇqðÇýçÿg( §É0›‡eY“c›꼑À[ïÏshçš.Õ¤ëNÙXe’bš&þÞ§>|ô£sŸ'ž±Ê2Æ” ×uñ†_øüÑ·¿8:Zøüà(1Öi˜6XuÝ«Òõáèès´¯f•Ó ˜ €F @U!‰[8˜Ù@lÛžŽ®jÚ¸óF‚‚=ïÑí®^ç'Ë^)‘´[/ÃÀÖÿ8¾ô˜é9 6ïbc•)#ÿâ~w¿ð…Ø¡R’u6Vx]Þ È Š®Êr {ª¢x‘ÕæJ§f˜BaÛ6DQ„+°†Ù\|Ç à¹Ýk5ïÿ§§±¬NJÝ<ße¯—NSº½¸®wß ¾ÃÄÁu]œ¼å-xÃG>2ó9†1ƒÄ0eä™gžÁïä#37^Ëò¶õvÛûz 0 °Ák»í9q¦ÒÈ4\ïÁl¶mC–ehÚxÌÃlc› cÜé=˜53²o/çÔ§Þ=U–Ç)Æ<ç’IŠišcgÌ ƒ£÷Lyq_ôExÛw~gäqªìèv¹V•‰f#S‚I)‘e Ý¶Ñ îò|!0†?Ò¬Ð0›É„ãq !—¤lG HÒ¸Ë0a’bÛ!=%„—-ÆÝQ™òbšftÃï¥0LfLÔ¯.À¶=HQ<%h¬0þ•¹âضÿùoœyÜqÆÍ–¦ŒüÇ_ÄŸãÇe4Í“mÎc±‘)Á„¯äü¿Þü¿ŒGØ0‡išý§_„õ7~7ï¥0L&8ŽÅó@.´ i¦j©e]e–á§~ôGñ?]\Lö”zŽB1ë$ ùÖ4 ÿšÛÀÙYÞŸŠa<Òoøìÿú¿âµ÷¾®íª­Öúz 0›Ea#¬ûûû¨T*°mÏ=÷ƒb¿þùû1|ûG?ê¹qØ=ÉŒUåû;¾ã%ü¥kÿò¿ø.–o¦¬*ãÐn·ñ·y$²ã wNeòdUùþ·ý(þúÏý~óýÿÀéÁ0E!ýû·ïÜÁ›_|¯Ý>@³É¥ÌjÒ`‡è÷û¸}û6`kk ;;;èõâEJÿã‹/âŸ}îsxÝ?ûg|…0…cUù€×ÿÒ/¡ýmÿ[G2…$ ×4 ÿûÖÞxýºo™ZÖxÎv§Ã+“+Ë·ëâÍé/áãÛš?¿Çó'™B‘ÆþýÚG>‚ÿèáß}øyüÕ¿ùv–qfe i°Þ¿P­VýǪÕjì<ú/º¸Àü¿QeþääÄO»(I=nÌêò 7¿ñüÉ“ž÷G‰MYåd0àää$ïe”ŽUeü?¾ø"v~è‡ð'ÿ䟄)w¡iÀö¶U-"¼‡_-V•ïñ§þ'|àM¿„ϼãf)š„•UFxÿ^Ž•uÇÁ/ü½ÿ ¥ú«ø‰CáUÞ¿ËA!kXç]ØÚÚšzü³Ÿý,~õWO?ý4{ì1àýïG¿ßÏû£Äâ—ù—ñàÁ\„ZÛ—çŸ7nÜÈ{‰øÌg>ƒ_|Ÿýìgsyÿeä›ÖýôÓOã-oy ¾úïþÝÒÈ7PN9€—^z /½ô*•JÞKI¼îO~ò“¹½ÿª{ø¾ø9ÜûŠã·¬wâ]Ÿû4Þõ®ÏáÇ~ìð_þ P4Ñç=|½¼òÊ+øßø üþïç3_}ùîß?ôpø«#¼ûÝ}¼\‚že” üû÷p8Ìeí«îß¿û»_ŽÎC?…ïý«€w½«_È=;ïßë…tð¤ûw! ÖyBóàÁƒÈ‹åu¯{ÎÏÏñÜsÏ•Rè†Ãa)×ýðÃã…^È{‰øä'?‰ßþí߯W|ÅWäòþËÈ7|Ù—}ž{î9¼ímoÃÛßþö\Ö¾,e”Àû{(ÝÚmÛÆý¯ÿ5·÷_u¯V¿ 7þÒoã¿{ä—ýãEÿð¾>^~ùe|ö³ŸÅ×}Ý×åòþËÈwpÿþËÙÛ¿Ëòµ—QF€òïß¿ó;¿“‹Áºêþ-I¾ç{†Ê#㼯ÒÁ“îß…4Xƒiaf]¼ßöm߆o Ì2c˜¢²Œ|ÀÓO?÷Ò&¼‡3›Ì2òÍû7SxÿfŠH!kX¯_¿`2-!¯Ô†I–ofÓag6–of“aùfŠH! ÖJ¥‚z½>Q,oYFÞKc˜•aùf6–qf“aùf6–o¦ˆ\F£¼Å`0Àîî.*•Š_ä}xx8³¾aÊË7³é°Œ3› Ë7³É°|3E£°+à~S«éz½ž÷r&UX¾™M‡eœÙdX¾™M†å›)…6X†a†a†a˜«K!kXËÊ`0˜;|x0Ìo5ïø¢×¦ùÒ\÷:×ÎdK–òçxZŸ!íµ±|o«Èø¦Ê÷ºÖÎd ïß,ß›ïßù­}-Œ˜•ùÄ'>1zâ‰'F?þøèñÇ=ñÄ£O|âþñû÷ï>ðøÇ?ô¡M¼~ÞñE¯M“»wïŽ>øÁ¦²îu¯ÉŽ,å;Îñ´Ë÷ªkcùÞV‘ñM•ïu®ÉÞ¿ó_;“-¼_ ùæk ìîî¢^¯Ã¶m<÷Üs¨×ëPUÕ?¾¿¿J¥â 888ˆu|ÑkÓ¢ßïãèèhâ±Uֽε3Ù’¥|Ç9žQò½êÚX¾7‡Ud|Så{]kg²…÷o–ïM‡÷ï+"ßy[ÌeçùçŸ=þøã£Ï}îsþc÷ïß=þøã£O|âÿ'~äG~dôÄOL=7||ÑkÓâsŸûÜè=ïyÏèCúïáYeÝqŽ3å KùŽs< ¢ä{Õµ±|o«Èø¦Ê÷ºÖÎd ïß,ß›ïßWG¾9º"ÕjuªÕ÷ýû÷[[[þÿ«ÕêÄk(Ÿ|ÞñE¯M‹ýý}ìììøÃ¢­+ãL9ÈR¾ãOƒ(ù^um,ß›Ã*2¾©ò½®µ3ÙÂû7Ë÷¦Ãû÷Õ‘o6XWdkkk¢Ý÷p8ÄÁÁvvvP©Tæ ÇÅÅÅÜãgggs_›'''‡ØÛÛ›x|•uÇ9Δƒ,å{r2K¾é³,»¶u\›ÌzXEÆÉAYå›÷ðÍ€÷ïüÖάÞ¿óY{°Áš888ÀÍ›7Q¯×qçÎÿñYxÿfùÞtxÿ^ïÚó‚ Ö±, Ãá²,£ßïOüž'£^¯ãäädâ5FcáñE¯]•z½Ž½½=ÿ§Z­âúõëØÛÛƒ$IK¯;Îq¦d)ßqޝÂ<ù®T*…¾6™õ±ŠŒoª|g½vf=ðþÍò½éðþ}uäûÚh4彈2spp9? lÛ0NW¨T*¸¸¸ÀÖÖÖDW³yǽ6íÏ2 pxx¸òºãgŠOÖòçxšŸ%(ß«®å{3XUÆ7U¾×¹v&xÿ.ÆÚ™ìàý;ÿµ¯ 6X×ÄÅŃ€è¼ùyǽ¶¨ëÎ{íÌú(³œ”õÚdÖË*rPVùÎ{íÌz(³Œ”yíÌúàý»üòÍ+Ã0 Ã0 Ã0 SH¸†•a†a†a†)$l°2 Ã0 Ã0 Ã0…„ V†a†a†a¦°ÁÊ0 Ã0 Ã0 Ã6X†a†a†a˜BÂ+Ã0 Ã0 Ã0 SHØ`e†a†a†a ¬ Ã0 Ã0 Ã0L!aƒ•a†a†a†)$l°2 Ã0 Ã0 Ã0…„ V†a†a†a¦°ÁÊ0 Ã0 Ã0 Ã6X†a†a†a˜BÂ+Ã0 Ã0 Ã0 SHØ`e†a†a†a ¬ Ã0 Ã0 Ã0L!aƒµ`¸® ˲ò^ÃdË8s•ÉBþùšbò€å޹*°¬ç¬öm4¼—Á0™Á2Î\e²¾¦˜<Ëap'ïe1Lê°¬ç¬ Ã0 Ã0ÌJ˜¦ÉJÃ,b‘Œ÷z½Qp:??ɲ<:;;›’ÿÓÓÓ€Ñùùùh4bùfŠOÖò¯ªêÄyÎÏϧäšaÒ`‘,F£‘,Ë£^¯çÿ”Qú÷l¦è¤!ëóövz>Ëv28š#Žã@–eˆ¢è?Lõ5Ms긢(þÿ-Ë‚(Š~÷²àïä¥ ¾V?aIŸÏ0óX$ãôx»Ý†eY½^¢(BEH’äg˜¦9‘R|=Àòͬå?˜. À÷Ðï “‹dyaå=›):iÈú¼½=ü€e;l°æÕ¥ÎÂuÝ…¯§Z¥àOøÁ0y±HÆEQD¯×4›M\»v ívÛ?®(Ê„Âβ͔‰uË¿$IPUuâ “‹d™a6…4d}ÑÞÎ$‡ ÖEÑ„A#U„¹F«$I¾×†~Ž¡ª*×.1…`‘ŒSsn·‹óósœžžÂ4M¿[Qض ]×áº.GŽ˜R±nùïv»~£®bÒd‘,3̦†¬/ÚÛ™ä°Áš#Š¢À²,߃NÑÒàqÛ¶ý¢mê8F»TøÍ0E`‘ŒS#1ºˆ¢8•ò«( t]•’Ã0E"ùÁïVÉc˜´X$˱LÙICÖííLrØ`ÍJßj6›¨ÕjØÞÞžÊïv»h4h4¨ÕjÇI1Ñ4 µZÍï|||œ÷Gc‹eœjò¶··Ñh4°½½í+é9f8ºÊ”¼ä_Q(ŠÂÎK&5É2àé$š¦q‰)5iÈzœ½IƵÑh4Ê{WÇq"g=Qó$QýœzšÑ4JƒM–(M˜aŠÄ,'(‹ ê¸aÐugggy †Y –fS˜'ËA…ë]™²“†¬ÏÛÛ™d°ÁZ`ÇÁöö6NOO!IÇA£Ñ€ªªœÉl<”JS«ÕÐjµxˆ6s¥`ùg†a\S‚ƒƒÁÜãÃá0Ï%æJ0%øÚµk¨ÕjP…Õ’Àò½¶mãᇆ(Š,ó…e<;Xþó…e›ÙtXÆ™2‘K„u0@UUÿB¨T*ÐuÕj0¡ªª!ɲYðÌ0E„å›ÙtXÆ™M…e›ÙtXÆ™2’‹ÁúÞ÷¾²,ãÎ;¸¸¸ÀÁÁúý>>ö±vwwñå_þåÐu¸uëöööfžs8âW~åWð–·¼%¿osI>ó™ÏࡇÂC=”÷RóÊ+¯àÑGÍ{‰yíµ×ðº×½ï~÷»S?wò ?ó3?ƒ7¿ùÍyuKQf9yíµ×J¹¯¼òÊ+™5xà=|ÞÃ×Ïk¯½†­­­ÔëÂxÿž¦Ì2Ræýû[¿õ[±µµ•ú¹yÿž„÷ïõ³ÌþýÅë^d¿ßÇÅÅ…/ø[[[¸}û6NNN0 °µµ…~¿{÷îùÇwvvprr2÷bùÿá?À4ÍR5Û¶·½ímxûÛßž÷Róì³Ïâ}ï{_ÞËHÌ'?ùI ïáëåààwïÞÅË/¿œêyyÿަŒ2”ÿÎÂéÈû÷4¼¯ÒÁ“îß¹u ¦¼ù›7o¢^¯ãÎ;þã³xðàÁÌc>ú(Þ÷¾÷áðð0¯Ä”„<õÔS™¦®¤-ßðÈ#àðð°”7`f½â±ÇËô=xgòbooO=õ¾æk¾&“óóþÍä íßYQ¼3yA:xÒý{í)Á€—ê°¿¿­­-Ü»wo*õ`Y¤G0LÚ°|3›Ë8³©°l3›Ë8SFr‰°ªªêçч/ŽëׯÀDZÂp8ä …) ,ß̦Ã2Îl*,Û̦Ã2Δ‘µGX-ËÂp8„,Ëè÷ûÇêõ:*• êõúDG2˲Ðh4òþ®f!,ß̦Ã2Îl*,Û̦Ã2Δ•µ¬TDU˜MMpööö°»»ë·ßÞÚÚ“O>™óWÅ0‹aùf6–qfSaÙf6–q¦¬¬Ý`ÝÛÛ[ØÕªZ­â™gžñ/¬`G3†)2,ß̦Ã2Îl*,Û̦Ã2Δ•\š.Å!Üz›a6 –ofÓag6–mfÓagŠFncm†a†a†afl°2 Ã0 Ã0 Ã0…„ V†a†a†a¦°ÁÊ0 Ã0 Ã0 Ã6X†a†a†a˜BÂ+Ã0 Ã0 Ã0 SHØ`e†a†a†a ¬ Ã0 Ã0 Ã0L!aƒ•I†ÀÎ{ ÃŽãÀ¶ù¢d†af3aƒ•IÄK/½„|ÏGÐh4píÚ54 hš˲ò^Z$®ëÂ4ͩLJÃ!^}õÕ¼—Ç0‘8Ž×uç>Çu]hš†F£v»v» ×uáº. ÃÀ¿ý·ÿ6ïÁ0 Ã0 ³2_œ÷˜ò`^ß=þÌßú3ø›ú›<¥Ù²,´Ûmœåº>×uaÛ6Çñ£N®ëB8ŽUUýçþèþ(Þð†7äº^¦˜˜¦ ˲|'L§Ó¢(+ŸW×uH’Y–ç>Ïu]4 ‚€^¯A&ŽY–Û¶aš&Eñ¯;]×Q«ÕŠ¢àï|gÞ_%Ã0 Ã0ÌÊ,e° ßïc0àöíÛ¨T*‡ØÛÛËûó0a>ó¿|÷þ.®®ù ‚EQ`Y–¯@ç…®ë¾*IZ­DQ„뺨ÕjhµZ–ea8â;¿ó;óþZ™áº.šÍ¦/ÓÝnŽã ÝnÃ4Mt»Ý ã1 ý¤ó©ª QÀ—WB×u(ŠQÑh4ÐëõüÇé“$ ªªN¬GUÕ §ÌîînÞ_)Ã0 Ã0ÌÊ$6Xprr‚\\\¶¶¶ppp€Á`€ÃÃü?³$†aÀ²,?­Ðq_‘v]¿ð¿€ko¸Dd*ʲ ˲b¬†a ÕjMEeTô»ëº’t½8Žƒf³ Y–'2*É ‰D·ÛE¿ßOÜø4‘ÁÚï÷±»»‹çž{Ž ÔU±±tжm?j'‘6jÓ4 ‘w€Wk¼Ì Z)Š×uF¶ÂZ—½ÐÅéZÄúD¤ÍfÖ5×êv»så–ä`{{’$-|þ²P+ý›UMìMÓ|gæ,Âòæaš¦_޲ ”ŠÖjµ2¹Ž™Í"<:l¤@Sf ÍiF„¨A$)ãI{0LVPö"Éd0ÒO“:–5X Àišþuìù!z½ž?僲Ü(˜`¢OM˜´öðÄ5¬[[[°, ;;;©, ßï_ͺW^åŒôÚY¸®‹f³9wÇ,–övSÇÝÄ­¥ÆK’$ÁuÝ¥Ó&<ªT^kŽúΕ•ï cuQ—]"ØT++dYö=™Ýn—ëUÁ2^f‚žñE]°Æ\¥„0 ’$ùQ€¤ÎHR‚dYF»Ýžj–F%0Ï?ÿ<þÄŸø™~?,ÛÅǶmèºÛyHi€'KÁûż̰M…e¼<ÌKy§=7JŸNê ñ‘Ácº®ûY³tA¦šëΠIÜ%xoo‡‘ÏÙÛÛ‹}¾ápˆÝÝÝ©åÁÁŽŽŽ&«×ë8<<\ë—“)¼.¶V²—5È3kY+q ÀhµSRj%]d+^g਄\ŒÖ+!jtp€IDAT-ß+’ÔX%²nªEò:U7}Ea//Ô †ŒPª-Š’kJ›Õ%;u…·m{bôX4MƒeY~†9héý)=SE|Ë·| F£oDs`Ù.TJœ¿Nüeœ‡W}g/º®û3ÙgAHƒ>j Ùív!Š¢ßÇ&HYzp$®aÝß߀)a&â¬ÃáƒÁ`æ9îß¿‰?LÒnR…g Ç¥§Õõ46aÇe {|Pñ_¦CðÆÆj²ÇX¾—ƒ”UÀSH’«ëb™ì†Mƒe¼ÜDeêPmRÔ^LF¨¦is3bÈ  &Ô5~á2‚RÑ(j¼î–©ŠËvqi6›àgÒèºÎûñ°Œ— ª³^”EN ¦Ô÷`éàÚí‡Il°.JŠC¿ßŸ²ðƒãÒ« ¯nu‘±š0õzX¾“Cé*e¨ eåˆe¼LÐŒ``œ6•©C)¸Q¯§¨§ã80 cfÚ¤®ëó¶%Iš;»˜¼ýtþY÷u*Y,ÛÅ„œÝn–eÁ0 6V—„e¼ø‘jYÇA§ÓYèÀ¦obSÈ×åñ¦;;;8<<œí÷û¼´„ƒƒÿ÷ÁA¬®µ¶m£V«ùÍ0Öj¬^ÔruÿD$4¯ Xn¤Ï]tÏZc îÊËwBHIææ 1 â2°ŒêMMh,ËB­VàE¥šÍ&¶··#3u¨L#Œa¾Á©(Š?â  Áó¶Z-¿Ù_øœµZÍOñ=;;+Lz&ËvþPmu°³¨®ë¾£„êíØX]–ñbìÊÛívqvv»^”&u›§S-e°žœœ`ww×OÑÙÝÝÅÉÉIª £T…‹‹‹Xçå•Wðì³Ïbwww=ßÜ*è‚3lµ`mF§ÓÉ'¿\Âìô߯Ä'héÏFkˆcŒj[ONNp÷îÝT²–%©|À«¯¾šÉµ–RJÓ‚¼€›¶±f‚ëáX„1»»»x饗r]îFïáÄ4M4›MH’ä7Ù :ðN§ƒV«…ÓÓÓ¹ÎOY–§®oÃ0|#”F‰÷N2’i BznÐÈ¥úôÓÓÓXMœ¢888ÀÝ»wñòË/çò]—uÿ. ”@N kV†:»4 ý{0ä¶Þ¿ó!8RfÝ¿ÕjA–åBëT¤ƒ'Þ¿G ¹{÷îèñÇ}øÃݽ{wt÷îÝч?üaÿ±$<ÿüó£Ç|â±û÷ïîÞ½;úÜç>ç?ö#?ò#£÷¼ç= Ïu÷îݤ':ÿ Þ?ggg£ÓÓÓÑh4žžŽDQô/Êh4ê­~Y–GÇÇÇ#UU—;8Îb4Mƒ,ËÅ X˜ÄsX©µøÍ›7'¯T*8<êõºQÝÝÝÅÝ»wqçΉBí²CáúV«åw5ít:ÐuÝO_Ij°>½÷ôdó ñe? <‹gŸS)êõœfÓS¶£¢CÍ&°u<ó6@zfÆZB)À‚ྺxÉðŒqf!š¦Á²,_îÉ`%c5Ztžn·[åW=#4 ƒÕ¶=' yN›MÏÑ2Ëqïðd6x^Iò®E”á;ff¢ëúDz$Ô×u¡išßI:\ŸÇõzféGL) ò¾Y3¥ƒöÕo«ªZ½¨`$2X/..ppp€Û·oc/Pÿwxxˆ££#ßݯŒmÛ0MÓ׫ªŠZ­æ§±R˜?öX–KCðÞOß›ldá µ11+#ˆ¡ùü™§ÛÛ¶§¤»®§¼‡¡”ápT•Ð4ψè-)KáH„Œµ4’*;ív€×”ê´iÃ¥ú:аÎC×u‚0Þ¬)RX0/²,{‘ù$Ï·Žã–åÉîññ؈”¤qÆÑhL:uÂÿ2WN c6 ×uQ«Õ ªj>¤ÕóÇ^/GÚJ EVã6N-}£ÉœId°\\\L«ÄíÛ·qrr²òX›¢`šæÄì/A (ÊDz‹$I‰F||ê‰OÁý·˜^t2œã8}øéÍ3¡è¦ Œ£GÁcÆü¨ÓKÿ øÇÿ8ïoåJAMHÉEqÂ!ãº.AXè§ZŽ œj>‹H»íy¸cD}Â7ÓôŒR×Îe/âOFüÈ)³±¸® ]×aš&Ï#f6ÊÈe„‘ëzCÞ[™5@‘ÕBêôÈRcmfñ §Q!YÕ¸Óé@UÕ‰Çã¦GB~à× ˜sè $ÏhE8š$ËÞcD³éuë÷]|é½?’îçLò¯–eùN‚Æa0W橳iiR^Ç“Qê¶» TG•Ú>¯eÍ—}fã1 µZ €—ÍÀ ³ и¿ÜÆ!Ѽê²Ö•˜Ò@%ƒ5]‰ VJ÷Ýßߟ˜Åzqqýý}ب9MQ‘¤pÓ‹XiÁ6kܬiŠLp0ŒÍÔ³àxx*ì¦éý¾Haá5wJ“‚øòÆq¿¹Ø"#“®‰YQÖv» A¦›ÃP®"Bëšg°jÚü”aQô2f}Ás¯½›/S4Mó3‚Y< S6ÈÑIЉ\)ÓÞJºR£‘÷J˜P¹Ï©^/‰#¬º®£ßïã½ï}/nݺ…[·ná½ï}/,ËÂáá!¶¶ 6¦eIbEM1…ŠD~ú§Š¢L+'ò7X;ˆ— —p·Õ ²®(ñê³Øxo‰Ä0Œ©Ì"X¯Œ°;Ýã.§ÀŒÎw”^4\w¬àÌ2Xgq§ÞEP+s¥i·Ûp]·øcž&4¶¬ÑhÀ4MF0Ç;÷‹êÐe&0MÓÕǬ—ÄkµZÅÇ>ö1躎z½Žz½Ž;wîà™gžÙ¨èj\e"V„µ|ä×>½‘ç™ âÈb´,Oz9%i?‚ùŒµ±¸–­O»ÎÜ…g@g¹/§on4secƒ5ìp‘$É7`iVëBçM’MÞu';ëf5\šEÑU‚SåJ‹mÛ‰ï €WãGs»s¯ícL:WÁ0Œb6œ±íò”_нGÊeh_A¨Ï«K`¤-Zh°V*躎{÷î¡Z­âää·nÝÂþþ~ü¤%ÃqœDB9Ó`5Hž²3scwàëF°Šþ–­=r4.דµñÎ÷„ ¬”¬_¼+)ð¦i.ö¬kZ|%‚j —Œh%"a >nšÞZÒ24Ù`--4Ò)É3`œy°hì˲üîÔ«@{áäZç; ‹J’²)fíPGàÜ3ÊŠ®§’a–¨†U–eܹs÷îÝC½^G¿ßßxã5î÷ùùmÀ•Ü)e‚4 ָʔo†ê*×^ð­LÓ3H–ŒÕ²O–.ßÓЄ§”ÂN#¬¶m/>OEßu½x8…Ø0RóÔùÐ8›0ŽÃÝj&“$:å8,Ëb%‡) ”Ön¬¸.rtæF«U®.ÁLá¡}œ3d–IJÆúÔŠ,=‡5h¼îìì`0àÖ­[‘2œÔ‹NÆè„2ãclì"Ò‹*6›‹½¼Èïª×Ù§4¨{Ùf d–% eóJ… ¬” ûZ1Œxu©‚0iÜRzîÙ7.bÖ«IÓMÓdƒ•) ddR¿e³â ›L”¡Ôq&g¯Šâ¤ƒ–)º®CÅb;gŠNptàŠÄ2XƒnÞ¼‰ÝÝ]ÿ1˲°»»‹~¿^¯‡ÝÝ]œœœäýÕä†,Ë“‘Y €³6½uV-ÞÔBá5LR”qÔjod€yi|,s1Û)}î$ˆ9¼gA±,+v¶,Ë3»\†ß`Åx²¦(“«(z]¦ VfíÐ옽º.Ø+Ï… EUÕÄ]¯ Ã@³ÙD£ÑÈ|Í<Êœ¿J°s«Pض Ã0Š-ëe€F¦õË`UUÕj÷îÝó;::òûØÇ>†½½=äýÕ¤‚mÛ‰)ƒÕ,7¦Q°üx¿Àû9³7jÛö"[Á÷‘¤±P«%˜“ªÛÛžwp•¿6Öí\µnwÈë!'ŽŠ°Æ­ƒMÍÐ\ÅSGéëi×Á2eY~T*ŽÁjš&t]çš§epœù{…iz#¯j5¼ýG¯íµ¼W\ gr´õ݈ÛùºÝnûu|…_3‹ut–OËâZÛãº.Úí6ŽÙ防¼ž¦Ký~ÃáwîÜñÓ}/..0 &æ¯îììàââb*m¸¬,ÓºZűBs ˜NLe> f ƒm{µ­•›ÑÑEUõ"ZqÓƒZ-/5Sê­ãxQÝ(T¬ßxsxÏ‚’¤yŒ 3•ïØQ¤´6}Q\ndeyŽú»í)7EOcr'¨èÏ»/´Ûmlooò¬«ÙXÓÆ×Xà˜Ûöžu¿²mÏÚlFŸŸF]žúó’ßðû¿Ÿ÷§.QõÔq¢¬®ë¢V«A„rÌŸ$gdÑkXSL“dÒƒ,QWàÂË{šÍ|Æ=¹njúßBƒu0 ^¯û†)¿ö!hŒ—eç”ÇÛØ¶»F0•Hcpžd£1îÊÕlz5¦ï¯Îžq*IñyÕM–샼JØ> QÒ%Qi1²,Ç¯í  kUQU“§|QdõøØ»Ž/-š–ž!Íl,Žãø÷ºY—LÓ„ëº8;;C·Û½z5OTg.I“ ®ë݃ û/Qƒ¾à}Ä0Æ÷ªãcï>Õu^×½c¢ˆ">ù߉ϽùÍyòÂCÍ–Â29sºÁ%Žã Ñh Õj•'-’ÆÚ½»û¢ùßÌZ±, ÛÛÛ~&(Šå‘ù¸¸n>ŽÊþL!8ðÅ‹ž°µµ…‹‹‹‰ÇƒªÕêF©A–5XEA»ÝÆÍÊMüìßøY?{ï…iQÁ5˲ws·,O –n®(Ë¥±‘,bÙ¾ü7Ï{‰ ¼ãö;pþç9.$VMuI”=@u©qR¶æu^Æa"^T&H§Ã#MÓ IR¤¡L›aêþàº.4MÃiXÆ®í¶g$ˆâdô´ÝöœLóêóLÓÛè^%IÞë‚X–÷s•¿ã%p]×7:Ãû=ÍØŽÂ4Mhš†N§sõœ/ë ê{7Œ±ü3kCÓ4X–UŽ ‚U  Öº¯g ¤ðÝ.Œ°V«U \ÍÅÅ,ËB½^Ÿx¥_¿~}½_F,›ÊE7€{ë¾ë‰ïŠ/üi8Ú\wì±SO @Çb£X–g{@¢ ø$3Mmx³V|UZ7€—^Âo½ó·r^L~Ä­]Zˆiz‘‘°‚&IC‰U=qq?« ¼T^Û¶#Ó#ÙQ—Úív¤Ape (E?é>dšÞ½cѵ|ìõSÞ/Ã2Û^~tÚ%h¬ÎêVeÕ4 º®£×ë­ÇX}øátz= ˜pœè{ã”ç3lº®Ãu]œžžn¶± xFc½è¾Øë­|ª…ÖjµŠz½ŽÝÝ]ììì ßïãââ®\\\à…^Àþþ>êõ:*•Êú¿Y6ºJ´Z-ü©¯ýSø£ïþ£ë]øq š+ŠÀùeôÐ…7wu‘œªêìM´ÑðêVƒÄÑÍ\xƲ ÏP-BÌ¥Îó_¾ü¿ä½’\YftÓ4¢F–½M0­ô&ËZ-MWÓ8ÃÌÄu]èºîwýÕ/#þ½^ÛÛÛSϧ‘6„ ÎJ¾Ò –ÚíÉûO8©™‚°øš¿Êßï’4›Í¹Æ*=šÌ4Mœ…ï÷YâºÞýdU‡u#-:³dÒ8N^ Ó4!Šb,Ô²,t‹ž>žqÆ^œX]‚;dYFïÒB6`zúé§ý.ÂËä|ÏkÒ4 0×ú…DÍ›L‚ªªx÷w¼;žAGdåØqáE6U,^ϬÏlË+ ”e|†b«9P4ù^ÇñºD;Žç1ëvÓ¿Á.{ýY–·.6V×J™dÜ0 ¸® Û¶Ñn·!‚¯°(Š2e GXiÄ¡iÚÕQxf1«®\QJ¯ •I¶ƒPÔtÑàðtƒØ]ß‹JZ½²&ê;–¤\"¬e•ñYhš†f³«£{Ø!¹±ØöF¤š/Œ°^ë;w"íìì`ggg©Èêp8Äîîî”` ‡C¨ªê§!˲ì{Â×ÁÊ©]üH^,²Èt²áÕŒ¶°8º: ×­àuÝÍ|½¢U¾Äž'9…izÕe‹ÒB⤆5㺈 ºÎ‘˜5SdÂ0 ôz½H%…¢MÁ4HÇq¦Ò")ÂJ³V¯„Â3 Y6Ùbšf¬¨¸Ž5mÍʨIÛPÓ´TR3¡@2Ëx$¿­V F½^of¤uí²ž'yÕFS£§”"¬€ç…988ÀÁÁÁ„G¦R©$6V‡Ã¡?Ó+Šýý}T*ضçž{ƒÁ`m3^W®ís'Z@ž!¼Š.A)ŸQH1Î}EÕ"Ë7±t½†aD+¨®;Û«mÛñgŸÎ›'Lˆâô{ëè˜Ì)ƒŒ‡!e–©(ÊT=_T7mQýÔâ+— lY³ÇÎle”í 4š#®2Œ²Æžl&­ÖÕªaEÔ}-#Ê.ã³  I’ÐétМ³W])ƒ5/‚ºŸë®|Ç2X°»»‹££#awww%áí÷û899‰<6Ñï÷qûöm^twggÇOGÎÇqV+¾v<Å·`•ñH–5¹YÛX~Ω®{ÞIMó¢iË(dÆéÀW"Ë7°bv·;»ÞlV§iJÕË¢ A˜>ß²²Ê,EÑe< Ã0*ãÁ&4ív;òù’$ùsú®\tU×76¢J”Q¶ƒ$u¤Ð¨¦Ò§KÒ¤l=-8Ì÷’²Ëø,‚—V«Ù$/øÜRËû2ÐÈËu1a—$\Ì –Áztt„ض Û¶±³³ƒ£££©q7qÙÙÙÁáá!ööö¦ŽÝ¿üYúÿ:óèWJ ¶°8U6̪‘z˚ܜe,Y•¤q”ªÓ™o<Ìr^¸²5«@ñå{¥:íYü<9 v°^¼¸Å«,OnºÔ®ýªÝ|r¤è2Æqœ‰yª³ ƒÕ0 8Ž3³/ƒaW3º lüuVÙÖ"„4suQíjаæ¢ÀSJpÆåå|^¹Õƒ®ÌšÖ\OB”Ã…Ê<ÂÓþÊuv—¤õ¬áFh+Ê÷Bƒ•ÒÉÛÀrÊoO“yÅ<ù•W^Á³Ï>‹ÝÝÝ•Þå”` ɵί TòÍÎxʈ,{Æê¢Ô Y²w¼âçɘ““ܽ{wù:ÎXV¾àÕW_ÅîîîLÏh2Ù¨ãlFq¢­‹2ÂÖ+õIÊîî.^zé¥\Þ;ï=< Ã0b)ñ²,Ã4M躎ãoEªªW#ºjY㌚©Zp÷î]¼üòËk}ߢìß¶mC×õ)}E×õDÆ*0Õ”K:°·€h‹EQ¦Ëû2íßYèØ‹(âþ‡(ù 7 >÷JEWƒ2·nGÝ'ÒÁ“îß±š.˜¨SÝÚÚÊì³Í» ™Ùû¥ÂãŸþ¢²\ó˵ùÍ-àWžÉá3wÁFêä-ß®ëÎv̘f¼†[Q¬ê±L2dú*ÝpJHÞ2„#¬s &0–å]Sþ¢È¶ eÙÙÒÆVÌסœ;Ž—‰nÐF݃ד®Ç»oÙ6 iøæ7½i=ß[E‘qïë°¡iE‰4J5ÔEÑÏH°m;v?ƒ!Ü©w]‚Ã]ö)¨±¤3i¡ÁZ©T2+¢®×ë‘)¸ÕjÏ<óŒß!­^¯gòþaÈK™˜ýp~:ýÇÉÀßûj`÷ÿ„õ¾7ÀÆêŠ&ßÄÜ9¬«x¦[­h£5ÜHiÖû›¦·™®û:b–¦¨2d¥Fz›Œax?ªêÍWf&(ƒl^:¯išS gJ®§×y:ȤiŽÇ ÓöeÊ[Ð0²¬xMeÙ{Þ_ø ™/¿ 2n†ot† Ö¸ãÊ(u^Ó´r^'«ÔËÖÙé=ìHP”•I±»ý~¢³Ó72æ­­­\.’¥RjÞöëÀO¾e½ uàÍA}ú÷?ýÞõ¾7³2yÉ7°À`]e3‹síH’§¤Dá8ÅKãb–&ObÛöÕJ‹«½ש.AÞ²mÛ¶UjµZåtÈ8ŽgÄ©ªgðQvϲä‘mšÀééä{#©dF²Æe‚€_øº¯Ã_^ÿ'òÉ[Æq÷_UU#GÑÄã$I4Mó³®a‡Dž™+~÷± V˲p÷îÝ©MGGG¨T*Ðu=—Üiâ.ã¡s°~%Û…g¬vÜ,n!dYÆáááT8=øøþþ~ÞŸg%¬¼fIá—lo'{cÉêA%°±Ê,Eì¬i6‚ï¯i^WbºùóMI™®º®§”·ÛžRrvæyñ)²åÑEïq6VKÍF8aŸa•Ïn,x÷”e L…E„ V×õË+’¶a†I’ü¾2aƒ5NíjÜîyÏÞ]u<Ùe0lo{?q® `œí“" Ö~¿ápˆ§žzjîónß¾ápèi—‘¨¢î¹ð"a–QºãÈ€…Éñ5Eˆ–1›ƒe-“'­ïi³›Õu»|£gR‡Fl,’ä]?’òÅÄc#œ0áTÅU>“(NG;—9Ÿëz÷0Ëò”s˰š6VÀ£ÒÁëÌΠT è*ìöKÇKqmö®mÏî#Æu½ìIò¢ggñ'48ÎìÌËÂëCå¥qXh°T*•…Cƒ©~õââbÅo3Ïês˜$;Úã´6Ž`b2u¸Ýf£•IÄ\Ï|©+‹¼‹W©½<“ ¥isíZü=ëâÆ#­¹«Žã9Niþ¸iŽõ,I¨‚ÝY»H†IÉ ß“$i*ÊZн=ÎìÝu"ñu=Jq©áÏì‹ iÞO³é];QŸûòýÿx§ƒ·¾új¢¥/lº´µµ…¬ý;]7‰Ó-xi¹¶=­`,3k(Ns¼ðþè8œBÉ$báˆU7ÖMHUc6†REX-Ë3@Ã륪¤”—åó0™°éÀÀ´ÞDŠtšÙ®;}Os]ïš²íi§5+¼ëlVCŸðŒU&uÂÆ©(Š~§àÒDWi®<¥‹çá` _qïŽã­9NP!hSIʬ¿Ïe“—ú}|:0q& #¬ÕjSÝÃPÃ¥­­­¤_g!H¬ØXdDâXFéŸwí9˜nìT´4¦ü¤!Sq^ßh°aˬR¬Q×O»í)ŽÃ5ÌTä©´„S‚Ó¾N£:»®×3ìMø7¨ŒGQýI¥1XI§„øµŸiâ8^´3j]Ô?äᇽç„ï-šoÌ”,{Ï£ŸyÆêŠÄ2X«Õ*TU™î{qqƒƒÔëõÒŽ¶IÜŒF‚g°’—.LÒ”`}Á±°~?K¹a˜9ض=;&ʽ*Q ¶$å3ä¹rض]ƒ5*+G×½ÇZ-OàZUfSèõ&_µ9L˜¨sQŠc§3nPÆލŒÇ`§à\šG.÷AòMŽŽ Òíz÷zÀùyt#>U_¯º&bu ¾sç†Ã!nݺ…““?Ú:qrr‚[·na8boo/ïϳ4‰/ŠìGÕè-3SlV_ ^„5œI0Kf3å<-#2(û³ÒÖ©™ÃdHâÞy¾V¨Ù 7#clLJp˜UÆoÆâû ¥Ölj1¹2kü=¾ÔÊU¡ò¿$z’¢ŒÓ€%)ÿ7ÁuÑø%Z[Ø`- }Ë`­V«8<<Äõë×±¿¿›7oB’$ܼyûûû¸~ý:K]MŒ¯éÒ,–Qf9ÎuDw"N»Öƒ¹¸³6[ªµX•¨èiÔyãv©c˜pËÉ·¬Io¶eyiZN±v0¹³°ÁU$*]>|ßÑ´Ù5©L¡˜@E¦iæ]m6=ÇH’I Á¬eY«2«ñQIYØt‰ £•F× ?]xQᢓ8ÞgcÏî‚•†òßð™ñ-˜Ôš–qÁ\)œyè¨9vYA +X†™ )Ut5\âAc: –’Å0…ͧÚ7 ï¾Ã†~)˜5cU’¤|éQ-ª,/?úO’V˜ËòÖ½ANšXÖ •J²,coo²,ûÆêÅÅ…ßx©l$®s’.fì¤Õ»µ ‡À[îLk¨~5h5^u^“qÑõÉ^?ýè[ñê«oÍ{Ykþô‰¹fS¤á‰£ŽxDTšÕä1L†”ª~5<–C9˜‰¤4Yó?Äê%!ÔÅ”˜w­+ÊF)î›Î¬,QaÆú3 Hç–ååÓze9y„uÞ5B3ƒ£Î麞2¾a2ŸØ`Å`0ÀîînÞŸg)ׯªþ ³3%ï87˜8–‚A¼$–5¶G û^èšêõ¼åjÚòçOê$xº_¯7þs}Çw|<òé¼—¸6lÛ†mÛ³ Vêô¶*­ÖdT(ª‘FŽò»)Ðdf6®ë–cNà]eY+“+¥i83{Æüúðc®ë)ÛÛÓu^m·× __%bV69 ×n°âIRöý7lÛëàÛnÏî.Ün{ki6§å¿Ý^­&¼ ÄN Þdf¥DbÃËήÒýû¿¸8‚g¬¶Ô,o€u˜5G ËP’íAeU’œžNÞdÙ{<ï©;ÔÍ›í"MÓÐáfƒ¦yΣðõnjɥ1ìÒ8bf1ËÀ$Eð68š]5 RÿEèüÈ¥-lY°ßñ$,=?G ¥Á'‹â´Z^OZض- îSª:¹‡lèõ™ ]®øš–^ftVÆ8²JPfgLbYÔ¢z™5ͼ¨’†™Cé V]÷~‚*IŠö&_‘MÌ4={FU½m›ëDáJ9Â=c(…pQÀ¢>WШã1§tß²ôgH‘+o°êº_©Ñ1=u¦9Þ˜ÐþÞ·AÞyü_ÿjßøÕèÞ{#dË‚ûumا1Þ+#,kù4øVköÎEPy ]Û¦é«Áu”!V4Mƒ,Ë‹£«iæp5µÚ¤uU ¨ô©×;9Óž¶³ì5užvÛû?9V‰N‡ÓßÃR©øP«ÿ¬7šÛÖD-Ëûá9³™53MOf;åÇæ‘&ˆªfîu§ ­ãx—vÙ]®ëÝÈ6 ï»ó uDm?ä$¥ó ÂØYZ$;-/ÖVÊA Nè5ë=£"¥qêÞÒºù‡)¨>µ¬ƒÁ Otqq‘÷gIŒaE1^ª¤ oþjcí±Û-Qó(#Ð4@xì« v¿ °þ#dýÂq½´ùC#k»Œzп½í}$j ´,áû“¦yç¥TS ¦Át|®Ó[Ó4aYNãlpÁ“UÑuïô:(gLZze'A<ïy¶=΂“eïÇqƽ(‹¨Ó‰¾?R)3Ʋ¬è}æèeÕ¤ÑP‚0»Kc0m…aŠ)Áòä-zºdä¦*œå÷! cì#¥¦«Ú ¶í]¦Š’|o¥ò$Ú¯éë&TÒW›–½)¬-ÂjÞ‰<³ödE™¦¨Ô^ªY¥?öŒ€fMjÖ­­-Ôëõ¼?Ol\×…®ëèÅÝtxÝu},è)¤¢”PY†ÔnC’Z€2V¨²l`ÔhL‘i:ý)“‚¢WÍæt zà~ÁÔÕpš¦Å“oËJws¥î†‘»%E† (Ž?"]O³®)òÖ/kÓ˜¦§´´Zc˜løà=βƞuÀû7\*C¿ÏsY9tËÈLƒU×=™Lû‹²mo3¥óº®÷ǧ?šãxÇI¡çfPÌX–•®2OʺeMÖÙмÉyi¤ Ѽà˜Véôq"ŠTDî6Íñm†Î•¤„‰ú:)ʤ£pVÏ›ZÍ;x¶=ÎênL†õ1‰š .ÿ&“c)É»%8Q{uÔýƒ芦ëÞWHã_ÃN›4üX ÖjµŠÃÃü¿‡ÔÑuŠ¢ÄO¯ùçÀ›Þ¼ï]ñB~‚0Ù {S×y|4›É Izù¢%¶ÛÙŽÄ´,oó§ þôÔ{ÏFcü¹)¢Äe\éB©î±äÛ¶Ó„^¬Ößÿ?aéoJýoK …¢DË.%@Ðýˆ²?©™Þ¢àuŠ_´n .Ð(H• žÜS°›:ÑG)?À¤ä{™—Åp•°, ݰmÓ^`õyu¤UÓÜ, ›‡çª*Š÷8‡Ã™H%%Ø4Ç©é­Öô†¨(c/[˜ §-Aú9Ô‚#¹æ)±ÁÞ´§‡/ÒÂ{í<¨i]§3­žÑ½BU£ÏÓjM7ˆ%_Ô¬Ë:î^NŠ>ûw÷ÑXßë¦a¯c^9ZEYì YÄ27íœ fr­bg“ß‹ô2I𼆂ì*,4Xûý>vww'„èââƒÁ ÓˆêÁÁŽŽŽ&«×ë©Ï®ëÂ4MœÅ±i8¯ü­ÀþOÄÿ‹Rûêh ŒÎ¡êOˆØÁiVq\§u†§¨f°ie-¸®÷“e*J„ín×ܲõH›,嘡°GAÃ)ÕEØ6àîBþKoè¾ Î-_†Æ+‘ƒ#83ž ^6Île¨Û]¬ÔÄÙ(`þ=Jqiµ&Ÿþ= Z­ñløÄ'¾9Ý7HHÖ2> Çqþÿìý}”ëøyß ~[‘,GTÐV$[¼’mTì\&;9»åË$vv$”'Nº-‡œŒusúÆã%*.e¼ÙqrO29™SsÈO2ÓLjClæ¸Ú¹'ä²»x²"’žÄyiÞbïÄiÞh]°­.J½\¸y§;’³6÷Ô‚  @¬çsN{‹/à¬?<ïϪRoYáÿM\À¢¸\dTË^¹"/ùÞ˜V˖Ѱ¨hXcÚ`cl`ÎrYC”w‰©S”u¯(«ÝôûËÍWéx­Ö %ܧ±®´ÝkÏíT®I²EŽÐw¾ófîß[«_uë<¤,S)eÈì(n“²›I'òšÃê±é«T{; ò_¹›oB¢”à_|§§§™zB®®®ppp°”P©TR9¶¦iÑf9‘±Ún§¶0ÿ醟è¬7‚ã¬ä4¥k±×[Qævmc_ˆšaqÓÈR¾}v/tí’ ;F„ÕÛ±yñ¹ôÜ· ‹ý?Hv©ÞG£ˆ¼K!¶wC ªç 36“‰îæ†îŸþu¯þÏ8ûMøGÑ"¶²¼ðâ­ÃÝ@ XÝØ¹V¢d-ß+^JoÚ#YŠ”ÆJéò¾šuyå-¨ y“G£…÷œR«¼)^Ae‡ ¦Ji:E[-û˜tüu™œE°YÜ{Äááã\×’¥Œ‡á»¿{=ên„” öÑÆzÏs#ÈC¾-ËÚÚýZ¼õÖ;bGa Öñx Y–ÅwïÞMå±, ¦i®*ôÔ$Æ­Ôp%1<ŽÎ#I°þãïB§e?8ú?uüq4þç;þ_ªb¤`Rô)LŸ"ω,³.U²’oÀöÂ/e(Êê®ss¦ùŸgg«Þ=÷9?ù¤q1Þ{„» ‘»‰6W÷æVošÕý­Ù´Ï9‹=7,e< ß±Íføµ×³µ¿ u’¸¼\hÔi…j˜Ls‘)äVÌŠVú›—|oÃZÿßAï×þ4Ä;þ3å© <v’TšáG熲ŽÝzMX]ÁVøÓ6oB“ï<ä[×õì VJåÊ Î4my§Ìj¿®Ñ¶e-·? cQÒŽßµeB!°xïþþ¢j…®‡0H¶©Ç Ýæè}’”|/Å…Aüæ›·ñ쳿ëý¿#ÙÇnÊŸŸÍf8<<ÄùùùÆÇôM6ŒE÷H/1KûE nÿÿø“ÿÈ[8³ÿ??ƒÞ¯þç¸xãÛ Å^75í#,kñ9š¶hâ²Ãi÷;Gò ø¤Dn8ƃ|9´ÏEJƒh·—•OM³ÿïgˆ’Je$Qî]îf¬iB%^l¬&'+wcE®ë0 Ã?µNþ©øXU»wóº[³W03:ûÞÖíÚ_5}ÝîÒ–¢° ùvc%iþ@¡ÌPªk«œ}êw yÑ…bú«ª~\\¬¿L¨‰ýmÓv¸‹bq"–edÛò­ëz´r½$xòÒIíO22IÖ(UÖ¯ÏAéònýÅ0ìÑ’ë2ÿÝÍ’è}†ý^÷ì`À6@ã:Xt=|¢GR¨‹öhœžþ2>øÁ/Ä;À| ¯¾úêüÎ;K½ð +¥ÉÕÕÕü…^˜¿ñÆÎc?þã?>ÿð‡?øž³³³ùŸøbþñ<ôØ’$Í///oÝ——óy·ëóÄ“˜ 8öphÿÿâÂ^òÙÙÆ‡½‘üôOÿôüðçÏ?ÿ|.ŸŸD¾çó¹#ß?ýÓ?øšËË˹,Ë‹Î΄2Ãá|.I«"|q1Ÿ·Ûóùh4Ÿ»?.ˆ‹ ûí¶ý“Â%Á„ðñ|þ‘|$·ÏÏr÷"Ëò¼ÛíÎÛíö\„ù6ʤt»óy³¹ü; lfŒFö‡^xaþƒ?øƒóù‘ÉeÍIä;Êþ½Y–çO¢Ê¢,/~Úíù“'¶(_^®Šs»mÿ šMû5nu¨Û]èóyð=! ¤~‰¢½.Ɔöï×^{-—ÏßæþM\^^Î¥¸AøCŸn·çó^/ùáIŸ ûø Ó!½iÕ̹ƒL˜"C:xÜý;²ÁúñÜùùØÇ>¶òýdÅo¼1¿sçÎüÕW_ \ç /¼zŒ• âÉû¯î§àHóùœ7Ð%мl“uò=ŸÏ#]_ÃápÞuï‚dU&`bŠF±Ér?NB{¸—áp8o‡i Láéõ’í!eÛÓ^ÝnwÞëõV‘aøxeÙÞÓ{½xŠú“'‹¿OšÆêâüߢvš›°»éõzóÞ&¤›v{EþÉaã'kqäùÉ; Šþ¦ƒ›fsõó./ýËÅÅÂ(ÞÔG›Iäem ë­[·pÿþý•dzÌeǘN§888p{úô)€Íº”-¥‡u6í7Ñ¢f§¸;2LYÉ7àS¿ªë‰j6LÓN- ëþF#ŠXæ/YÊ8aYTUÅÙM((Ûa¢–±ìï§6}kc¶!߀Ýñ]Ó4t»]'í=Þa¡XÔ°Y–ý]FýÞi¤…¢,júÓläÊÓžŠÇ¶äÛMäQ|~P;]*Šn6—JüÜݪýÈá׃®/:芢ÂVŸMÐxW5GMPÓ¸eÑÈïn÷æ´SXk°V«Uů¹Ü„J¥‚ÃÃCÔj5Ôj5v.½û÷$,]!ãj¬åó€Ð‰~ƒ¤2'VÞ™ud%߀GÆi§Lõ&SLŠÔÑ)YÊ8Ñï÷!Ërx“Ž Ù720ŠbäùgümÖÓ.â° ùlïv»h·ÛhG­G]«®ïTöêîJ $É®{‹2wš:íéïÀdö䛰, –e%k¸D]¯¨„»ç·{i·ƒ8ÔŒšÅ­¯n6íÏ^ŒüK·F;­q1e¡]‚kµîß¿{÷î¡^¯ãêê €½yoÂÒ|Ê·DÿE ù<€wF'sƒu"&[‘o úð^Ö Pg˜0²’q²,hš†‹uÖu½¸aÂlY‹.­ÛüLÓŒ®QÄ"ªÂU¤.ÁYË7`ïçQ'Ó´»SQÈÆÝr]U—´ojrçVÈiôp%<åQôLÙ†|»Ñ4-Ù¸&÷l¼O uð rÊÇ«.u:‹Ù¸›™‹î×Ü«o3 i°ÀÑÑœ eÓä•ΩAwIпý×ö¯ë®Ï~¹ƒ*ÃD!mù|æ¯F€M]I¡¡™` ³ YÈ8Aåk‡ÌSzX¨ª½ÿqÂM¿¿˜“øÏMŽuoø Q&——áQ8Êj jÌ_²”oPUÕ^¼ýäbŽ˜·¥¨'õE×W£GÍæbf;gÔ3~d-ßn|ggG!BZc§³>èäNÝ%D1½©d3›Ù`L&8==Åýû÷Q«ÕVçÜ]c¬ëǃjµŠjµšÊ±V”ù 4àâÀõ —n²$Ъº˜»VçÇ0A¤)߀ϦA‹¦ñ$ç$Ó “iË8YÁ1ŒÄÞDw9”÷üy¢^(ºê>w:0¡¸aPê“'ËŸI Àv„‹^½^¼½Æ4íõÉÀÊJ¾×f¸‹I½‘)ÏïAÎ Š²rä” "+ùöâ;;Û‹{`/±f!‡Ûºý™84Š[’xDd‰d°’rP­V— ®ŽŽP©T ë:&“ ^z饼Ï'Ã0¢Õ€´áÛiÉk°¦‘*À0iiÓwAƪ;›¦Ù,–òÍ0~D’õ$3+¯ÑuÛà"[—”Íæb–!þºTZ(ÊByŠâ¥èªûµggÉæ˜’Q³®º ß÷â¹ÿD›FSý‚‰»J¿ßÎ Ð4û‹ a5ÂÝîF—ÃlŒišèt:Á³WÉkhö&tv)¢J3Dilv¨gëôÅ%’Áz|| Y–Wò×kµêõ:Ðívñâ‹/n½ASTœ‚î;/ÕÔø9ä½)¬Ô3E"N H£±¨5ã&LÙˆ,놑¨v•9vÛ>”Ÿ®DF]ÝNUÕ6*¨KeåË4WïaTêØ°_Ã4Ó\t„uŸ› ,š–}ž_3ò,ʆE1[ç@X]Õ´ÈaÑ0Gƒ÷oÍ0ÛDQhš†áp¸¼Ÿ[–½ác†ÚòFÜ`“–çݰ6¥äw¬{Áx<Æl6Ã'>ñ‰Ð×}âŸÀéé)¦ÓiÞç´‚a¶±J³:ü°£Ï-Ö™rb¾ïÿa»ÝÝšPÊÙ™]gFc¦L†Í`ÕõØ–a, C¯§=èPTJ˜ÔÙ’¤ÔCÊ 5<Ö_ײ¼zl45¹„¢,^O_§~ÑÕ¬ æ(»Lht ª)ã™gì¿YqšZ1̶Ðu¦iâòòry/×4[‡욆³³ÈMh² ³»¬5X'“‰o{½^_J¦ç©@»H8õ«Ô¨À…s£Wa“x¦œhš†þÚ¯‡°P@YÆ™2)ÂJa¿ù]–eX7ÎÉ‹ „¼ü ¬¨©˜4RXÔËzßk¶ŽUY“eû˜düR £Û]¬•ê`‰nwñ;}µd Ëòöê ižá®­] «Ï6Î.ÙªºØ×WÅQ#¦˜¨ªê_¢g¶`÷zè«Å–ï°æ§†aïMŠ²Û™LƒµR©8ƒÝœœœd2) ¼OAuùEGW™bš&$IÂ×ýó¨9fÔža¶ ÉúÚîÀ†{pž¦%›µGøE»HáÚÛ[<¶¿oÆî×t:v”ÓýC‚¦—ìïÛÏ“¡BÿâDÒz½Åû›Mûwªß¢óp77’åEª®/¬ÛŒàIÒbLÅ.¢ªêÚîׂ°(壑nYqôœ1Æ Ó4ƒ³dh#¢Ÿ9©¼û«ªÚûª¢ØÏsÆØî³¶†µV«a6›a<‡¶µǰu- †a@¢Ö„.‰&Oñèÿ•÷ &9š¦á;ÿïþþßt169{€Ù4M‹ÖX,ÀŠR”E§÷zØ4JØïÛ-OÓìû‹·Ñû;émî>:–å…ívé·d0&¹®Eq‘ìæu»¶1Ýnîyv•„EïµÊ±Shš†ÑšBeï?.Ë õ©ñ¨; S£«XôW¢æv„(ÚN:z̲¥U½9¬°Öj5Ôj5 Ìf3ß×Ìf3 ÔëõÂE]n’>éaý>Ð~/ üTÞ«d˜ä躎ýÎߘÿeY¬¼0»®ëÁ%Cß·ˆrJ’­ü’O€7Åíá3‚…¢îë“ü«alª¨õzö=Ð]òNûDPš)“”ê¾]½i›æb4÷[¨‹5+òLÑ4-Ð`ítüuä`sGY»]–ñ›F¤.Á<Àáá!îÝ»‡ƒƒƒ%£ôÑ£G8??w^W4œ†Kžîºÿ¾à'ó^%Ã$ò,˜¦‰÷ ‚oçŠ(iv!Ã$d]ôÓR¨€Ó',¨i¶aæîú+‹žLš–ÎõáþèV«øFƒ ,ÏM%z½d#p˜ÍXÕdš OÊuq؈†)+NJC¹Néʆ ðµp‰d°Öj5<|ø§§§ +Ïàþýû[0Ã0l¼{¨l¦÷;ü ybJŠ#ߤØ\cY¶7^–ÙXevMÓü£«Ô-É#è–µPl¼os;ø7êG„q…ÅÖÌlšwðå¹Ûµóǯµô.ÿM˜’£iþÜþ íI×´•ô’°}‡ŒU±Å{ÔÍ#’Á Ø]€ìÎÀ SbLÓÄúS øƒÀBQ÷è; Szt]ÇÐ=>Ä3Cið¬ä3eÀ0 ´¨}´Ï潿ŸŸó…aÒàå_Äÿöo¯2¥¹¼\ êÍÜLb¬eâÇ~ì×ñ­ßúKìTåF㺫˜ÛXåÍŸ)9¦iâ?ý“Òù]UÙXev]×—Ç D¢ Ãþ•뛘2¡ë:þø›o¯ˆOUW›r1LÙøêÇøÍïÿþAV”¥j=† d§ VUð?ðïxê˜8]‹ÙLOwÞø™]D×õåq6ªº’¬ªöwl ÃÃ0Ð\rš5Kc>x_gÊŒeYøgŸûÚžð¨ª.æ­2Ì:vÖ`Õuà½ïýuü©?ugù GŸ˜Àé€Ð&© Sz4MÃY¢–µ2àÔ0ìfl¬2eÄÛýºÓ±÷ò°y¸ S4MÃøó~©¸Ÿf©rŠ/•µsXËŠ¦ïz×CÔÞzk1ØÉкþ—aJŽišxîº3·¢øÏ/c˜²Cʼ3 Á²–ºn¸³ƒ9m’)+éîXÌRec•ÙüægS·_nPÇDe'#¬¦i;àO¡:ø×@µjïü€6¸v•Ù ÃÀ_ú‡ÿ€îÎi5Ì.B³ûDqIËQVî™òâΔ!¸›Ù‚æg·Ûl¬2ñØÙë_ù+ŸÇw~Ó7ÙÞxÒdDpg`fgøúù/ñ¾ó;ðøfw œ¿ Û1iY¬à3ååêŸþS<=*Ð4íÈÃì ÞýÛ²ì6V™¸ì¤Á*ŠÀ7}Ó¿Åù[¿µÐd”¼WÅ0éò¾ÿõÅ/}臠ªy¯„a²šŠ‰ÚeqC¦Ü|ðÕWñµÛXeEžÙ%.‡C|ü—~Éù½Õ¢ H†‰ÇN¬0Êÿ£‚;ÿß/Ù¡§¾ýÃìßýÛ¿þ/~”fgYòÎûxfšMVð™ò¢ë:þØÛßî8Ö»]Î`vÓ4ñû?÷9T,²aXÆ™$ì¦Á*OßøE¼ë+ÿ P@À^xf‡ø'?û³ø÷_ómÀÛßε«ÌÎâ4ëд%·¼aص« Sf^ùÿG|s¥K9M’Ù9~î'~ßÿ›¿ 4›0M»)—/1I)¼Á:™L0Nc¿ï‹_þ$¾æo¾jGV‡àFKL!I*ß¿ñ©O᯿ó¿fO%Sx’ʸeY°, ¢ ¬L—ïtØKσ¤òmš&¾ï¥—ð[ñ¯¡Ñà4I¦˜$•oøÝÃ!ÐlBUÙÁÈlNa»O§St»]L®›ȲŒ~Ôn–eZ½ÿýÀý¼Ï„aVÙH¾¼õÚWpñ•ïÂϰ·’)(›Ê¸“ÜéØm€]3kxÞ*“7›Ê÷ëûÞq÷.”ùýevÀ0ÅbSù6 ÿÙÓ§8»ýסªÀh”÷1e§°ÖããcT«U†W^y“ɃÁ Ò{ýOÿLέa Ì&ò ÿËkß…¿ðÿ­¼OƒaÙTÆu]ÇÿõÉû—f–ÅT™â°‘|~ï/þ"†ø9¶?†aŠÄ¦û÷¯?x€¿ù-ÿ-Ô‡ïÂhÄ3²™Í)¤Á:N1qÿþ}@¥RÁÁÁF]4ïýÞïÅ×üµ¿–÷i0Œ/›Ê7üó÷߯óoÞ§Â0¾l*ã–eá¿üËxæSŸ†C¨*ÐhØM;&o6•ïÉþ(šïÿYüÎw¿›»\3…# åÿè7ð÷û‡ÙXeR£ëÕÕ vÝêþ5^ÅåAóg<'®È›óóó¼—P:6•oøå_ÿÏJu(«œÐ›‰Ç¦2®iz–½£¡Ñ`ÀÙYq#Q¼‡ß,6•ïƒ/þ|óù#¥1VË*#¼'cSùþ…?÷ßá‡ß¦áïüÝw•BOáý»Ò` œÙl–÷òRçÑ£GÎQ6tî››&ß@yåäêê =Ê{¥cS—óî¿ó ]ÞÁph÷[*r•ïá7‹Måûoÿí;øÉŸ¬ä}‘)«ŒðþŒMåûwýðà/ý_$å}&Ñàý»²éRØñôéST*«ý¿ù7ÿ?õS?…Ÿù™ŸÁíÛ·ó>…X|á _ÀÅÅ^|ñż—›×_‡‡‡y/#_øÂðÅ/~ïyÏ{ptt´õÏO"߀ÝUò»¿û»ñÌ3Ïà}ï{ßÖ×½ e”xóÍ7ñæ›o:'ÊÂãÇñ•¯|%·ÏßtÿÖo½ƒ÷ç«øš¯ù~ìÇr;Èð¾ý5Ïf3|Ë·|K.ŸŸD¾½û÷OýT.KODe(ÿþýó?ÿóø¾ïû¾­~Z:xYD†÷ïíB:xÜý»«; ÁKµZõ}ü‡ø‡ñÃ?üÃy/aÖ’D¾àþØ÷Ò&¼‡3»Lùæý›) ¼3E¤)Á·nݰœ–0NC•y†) ,ßÌ®Ã2Îì2,ßÌ.ÃòÍ‘B¬Õjõz}©˜X×u4¼—Æ0ÃòÍì:,ãÌ.ÃòÍì2,ßLyÛ|>Ÿç½?&“ Q­V1›ÍP©TprrXßÇ0e‚å›ÙuXÆ™]†å›ÙeX¾™¢QXƒ° ¿©X¾^¯ç½†I–of×agv–of—aùfŠD¡ V†a†a†aææRÈV†a†a†a†aƒ5E&“I輯Éd:9ìùuïMóÒ\÷6×ÎdK–òåù´Î!íµ±|ï›Èø®Ê÷¶ÖÎd ïß,ß»ïßù­}+Ì™yíµ×æÏ>ûìüÎ;ó;wîÌŸ}öÙùk¯½æ<uu5ÿØÇ>æ<ÿÉO~réýaϯ{oš¼ð óü㩬{Ûkg²#KùŽò|Zxå{Óµ±|ï›Èø®Ê÷6×Îdïßù¯ÉÞ¿o†|s„5Q¯×a^yåÔëut»]çùããcT«UçùÉd‚Á`éùuïM‹ñxŒÓÓÓ¥Ç6Y÷6×ÎdK–òåù4ð“ïMׯò½;l"ã»*ßÛZ;“-¼³|ï:¼ßùÎÛb.;¯¾úêüÎ;ó7ÞxÃyìêêj~çÎùk¯½¶ôâÇüÇçÏ>ûìÊk½Ï¯{oZ¼ñÆóøÃóO~ò“އg“uGyž)YÊw”çÓÀO¾7]Ë÷î°‰Œïª|okíL¶ðþÍò½ëðþ}sä›#¬R«ÕVfS]]]*•ŠóÿZ­¶ôÊ'{~Ý{Óâøø¸uëÖÊ9$Yw”ç™r¥|Gy> üä{Óµ±|ï›Èø®Ê÷¶ÖÎd ïß,ß»ïß7G¾Ù`ÝJ¥²4Ÿj:b0àààÕj5T8f³Yèó———¡ïMƒóósL§S-=¾Éº£<Ï”ƒ,å{r$ßt.I×¶k“Ù›Èø:9(«|ó¾ðþßÚ™íÀûw>kÏ6XSb6›a0à¹çžC½^ǃœÇƒxúôièó_úÒ—Bß»)Óé§§§ÎZ½ç“tÝQžgÊEòµœ„É÷¦kÏúÚd¶O_'e•oÞÃw Þ¿·»vfûðþ½½µç¬)0™LpxxˆÉd‚‡.yKÜáx/Õj5ôy·×Èï½›r~~ŽJ¥]×1 0™Lpuu…Á`€÷½ï}‰×åy¦Ï{ef0øÎOÃ0,ÒªÕ*f³*•ÊRW³°ç×½7ís™L&899ÙxÝQžgŠOÖòåù4ÏÅ-ß›®å{7ØTÆwU¾·¹v&xÿ.ÆÚ™ìàý;ÿµo 6X·Äl6Ãd2àŸ7öüº÷uÝy¯Ùe–“²^›ÌvÙDÊ*ßy¯Ùe–‘2¯Ù¼—_¾Ù`e†a†a†a ×°2 Ã0 Ã0 Ã0…„ V†a†a†a¦°ÁÊ0 Ã0 Ã0 Ã6X†a†a†a˜BÂ+Ã0 Ã0 Ã0 SHØ`e†a†a†a ¬ Ã0 Ã0 Ã0L!aƒ•a†a†a†)$l°2 Ã0 Ã0 Ã0…„ V†a†a†a¦°ÁÊ0 Ã0 Ã0 Ã6X†a†a†a˜BÂ+Ã0 Ã0 Ã0 SHØ`e†a†a†a ¬ Ã0 Ã0 Ã0L!aƒ•a˜ÜÐu–eå½ †Ù:i˾eYÐu=ïÓb†a˜Ôaƒ•a˜Üh40 #ïe0ÌÖI[ö Ã@£ÑÈû´˜Šªª0M3ïe0ÌV`yß>l°2 Ã0 Ã0‰Ñ4xæÆÀò¾}¾6ï06noM»Ý†(Š+ω¢Y–¡ë:Úí¶ó¼®ëN*X³Ù„$IEQÐív¡ª*,Ë‚$Ih6›ÎñA@·ÛuŽ÷õ •0ù€~¿˲|e,H¾–q¦ød)û½^ý~éq²,ôûý•÷1Ì&øÉ3=¦i@–åù¤Çx¿fÊÄ&ònY–#»‚  ÝnC,ÛIàkèt:è÷ûÓ4±¿¿ï\ Š¢8Ïiš†V«å\$€­ì´Z-¶‚²¿¿UU—ž³, –e¡Õj-¥¡õû}(вr¬¨¯g˜(„É7=Oµ|A2 ¬Ê·ûy–q¦ˆd-ûNÇ×ÓoY†£1L¬“g7~òÉû5S&6‘w˲°··ç85M[*Ù`ÙNÀœÉ•‹‹‹9€ùåå¥ó˜,Ëón·;¿¼¼\yNŹ,Ëóù|î<qqá·eŽþ?ŸÛòU¾éý,ãLÙ†ì»ß?ææOžûl)å(·œÌf³R~ï?Æ?þÇÿ8³ãó¾€÷ðíóÆo@üÍ¿ù7S?6ïßË”YFʼÿ­¿õ·P«Õ29>ïß xÿÞ>IöïÜ ÖããcXΟ¿ºº€¥‹´V«­Í£ÿЇ>„~ô£koEd0àîÝ»¨×ëy/%6‡‡‡K©$ea<ãÑ£G™?mù€~ðƒ¥ü®òËI÷•ÃÃÃLÏ{øÞ÷O–{8ïßË”]Fʸ§ff¬¼»áý{û$Ù¿sI >??Çt:õì°‹b6›>÷¥/} †a”2máè訔 €Ò^(?û³?‹Ï|æ3™? ù€/|á  ÇÛýÂR Œrõz½´7à×_=³ãó¾ ïáÛåüü?û³?‹Ï}îs™›÷ïeÊ(#@ù÷ï¬ñþ½ ïßÛ…tð¸û÷Ö ÖétŠÓÓSDQD³ÙÜxý†aÀ4Í•c)ŠÃ0œs 5Ó¹ýèþ(æóyÞ_?“’;·,¦qL]×cK’´ô¼$I‘>®“v»½ñšEªª$ ívÍfséZକ®YÀ–óõ¯þUjß Ã0 Ã0L^°Áºƒ†UUC’ŒN7¦iBUUhšæ(Á–eÁ4MH’ä¼G×uÇHm·Û+J<ÑétÐï÷ÑívC×ÖétØ µ¢(KŸå^#)ådL˲¼d0X–UU×ʲìPDŸnêTgL²A7mMÓR‰úojFš‹¹k¦£¬‹Î€S_Í0Lt4MsÒü‡Ã!>ô¡å½$&c¨¤‰Ê'Â$)4sFUU4 œ9e!Íf­V ’$9÷Ê £þT†BNFMӜƑ’$­í¡À0Yãî?³É1t]ßX‡¢r,w‰Ÿ·—Ž®ëx饗ð=ßó=±ŽÍkôû}§žÎ+䭢׉²ju»ÝH£šÊH,ƒu:âôô'''¨×ëN‡'Y–Q­VqïÞ=L&Ôjµ¼ÏkkP>8oØÐïÛÍ’LÓþX³]·_cšö{DÑþ¿ûï"NJ0|ßT¨nÁÛD‰ÉEY–éÞõÕ¯æ½Z&#úý¾Ó\#Ngö8sªyDØÍ†Æ·¸e‹¢ú–eA–eœí¤bÌ0Q¡@ªÏö‹’Òì^EQœZî¬öÖ´gŸ‰XëÕÕ ^¯¯`aˆº¡ÚTÀ6h% Ð4Û€å®Có´XÆ €e-œ8a,5.>ôÅ/æ½b&!Ôi8®(î&6 “¦iBQ”•z7ÀVÐi$ ÃÜ4,ËB«ÕZªý *¯pÓëõ°¿¿ïŒŸaâË`­T*€ÙlæüŸ˜Íf±gê”ò>²àeˆÛàìõlÃôìl¹žUQì×¹•õv›Õ0 ƒe¼H†m¨ªê"S°¯ð9.Cöñ­[y¯˜I¥Z6›M´Z­•1ý~Ÿ3z˜Ì …<¨)Ö.Gp& ê@i·q¡,5¾~’ñ;⼘¢¨‡‡‡KÆét:Åññ1ªÕªoôu×PÅQäYðR²쨨kñUºî@èpv¶Yb6‡êVý"Ö²,¨ªÊ³'ÝèújÄ”jZ‡CÛ0Ñu»Ì .,/ƒ|@§ÓÉN¾MÓv^DŒmöë»Ýð¾ªÆX‹¥é†9¿è¼-kõ; ùˆSóš!e‘ñm¢ëºS:Bu§ô{–s÷˜t¹I²Ýétœì¦HÒb¯Ï›$ãAèºî;²¯Ûíboouÿ$±šÑ~»éÒññ1f³NOO}Ö1›Í0 pttÃ0ðÊ+¯8¹?£Z­:ÏO&“¥ç·yĹ£×5–eÿx¿2žyÆþ÷ââF«e‘oEQ²­ÇŽÓPHU7éýýES/U]ŽÎZ–mÔ¬ýþ¢6ºßßüÆ·‹o¦ÍЖåEC%7–U˜Œ„²Èø6Ñ4Í/Ë2Úí6F£TUÍÖ1ĤʮË65ü¢®§¢(¢['ÛQéÊÌÈ‚]—ñ¨PtÕ‹(Џ¸¸H/Óì&!Ëé6eõÛ`5 #ôgÔ¬éàà€µ­×ëNÄv:b<ãþýûÎó+³è²Ä݈†¹FÓ‚½&Ã!ðä ×Ï¡<ò­iZvò7m·Ý¶ÓÄ{=ûßVË6½ÑTAXÃëF–íQ2TuÝßø‹ m¾ªºxŒ"Áqi6£yƒ6ü5R*ƒŒo]×W¢T¢(b4áâ₟iaY™*D»,Û¦i:ãøF£F£wN÷ý! 2Þ+vYÆ£BeA™œŸŒSÚcw ìt]×1Øé²,;@õz}Ű½ººÂ»ßýnçÿ–š:Õjµ­æÑ¾Ø:ã°»/ÔÍ— ¥ òMÍ_2“ï°èª_º«I²RUµS˽¯ »‘HÒr r³i¿‘åd¨É@Þß_|n«e?æ&jwß(Ñí…>£”AƳ„œ³îú&]×WRË6Vct-Y–½¯³(£ôê]–mªU-¬^SFhâAe*º¾0V3tÊ첌G%(ºÊ›Øë`0Àéé)Ìl6Ãññ1&“ ýéOc2™àää$ñ¢ë: ÃT> ®o?Ú²®þ®DœŸŸã§ú§ñö·¿=ÓÏIS¾àõ×_Çááadç4÷1Ótš êÅ4mr]]«$­ÖJ'A#`ÜFf‡­4ßôìlõÚ£(¬iÚ†ú¦Ê‹$-GTDWñøñãͿßS´= ÃpJF4Mã@7ëœRA†}ù|"ÇÓÅÐïÃhµðÂûÞ‡g¨%Џ'EQ”À¦_Ìø•I%E×1e½^¿üeL&“L'rÜ”ý›š‹v¦×mgˆ(®ÕYH»ÇJ žN§8==E¿ßǃptt„££#÷¡}ýèG7¾PJ3˜}Û^Ò26º àààŸøÄ'2OûHS¾àƒü NNN6Rvúý~öΘ Y¡qF4¾%íT*?ºÝÕÌA°£5­Ör½ªú§û’íg¬öñG#ûÇ4í.ÙŠ’¼‰¾#Â0b+E'''¸}ûvæ_o÷ð,1M¦i¢×ë¡s ÷K¾ÑìïÇ¿¶5m‘½à—epqa— ÐíB2MüßþìŸÅ·û·gvEÜ¿“@% ¥ÐkÊFšõ¦”]ÐnCÑ4ܾ};óñ‘7eÿ¦£Ñ———|-d‰(®½.H»Çа’'Æïæ\¯×Q«Õpuu…jµéxõz€#ßívqttzF=nR4M+Ç›´sÄUÕ²¢ŸwÉ(¢|K’”oŠb³i+§i¥ÐFýL7’d—ªjGnÚm[öûýàTÃ(׆(ÚJu·»PÀ-+~ÔµÝ^þnL³°×fÑdÏÆ»½éM’Ièf[TÏŠ®¢(¢×ëå3þÀ²lCq³NØIÑõÅ*¯±I4›¶á9ÚÎÏNgU)—ådÝ忚ÖÈ)»&ÛªªB’$n´‡8rm*‹¦¹µ=~×d|ªªî<+A$(]ŠKì¦KÔ]ë¹çž[z¼Z­FÊ]¯×ë888À½{÷P¯×quu…§OŸ.½÷è臇‡ÇN‘÷óÏ?ŸéQˆèST¨yMmÆÅV,¼ŠDÆh” –oØ2¦„rýHt ¨hUƳIJ,hš† OÊxn÷ŒNÇN5w×{nK)SUûg8Œv ü~ß~_³˜vM¶¹v5!qö]AØ<:ê5’3ìï°k2†eYÅo¢šüä åÈÞ†Ó%¶ÁZ«ÕðòË/c<ãÑ£GlͺȪ›àþýûNM¬÷½µZ /½ô’ãŠsì¤hšVž÷4•XðS©Ñ E[ÙXMLå[UÕe;2ž“ȃ"Êx–ôû}4›Íì#UýþBù½n0´‚®Û¯!c9Ìq™´co†a;¤./ã·À†ª›²É6eÏx£H¦i²¬bdÕ?ç*éDQ š½M˧ cùzÒ4àÛ¾-³Ó.›Œ'e§;¸o!¢‹-¬%ÑÖétŠJ¥‚££#Àx<Žã^­VC_OÃŒ·AérÜÛm{CKð$¯ˆÛ`ÍclÎŽQ$ùÖu}ó´°°Ùªn¼7^fg)’Œg‰®ëÐu={‡7RJµÞÞÈ©wL“вœ.FuE~Ê›×3nYþi‘4vÆo>òŽQ&ÙÖ4 ªªB×ug¾¶eYP¥Š§¢(Ù§”Q Üp¸0,{½Õ}¸ß·[§ôzvm)5þ’$ÛøÝÛ³ ^wÍÛ¸µ,»Üį6Ê0Ö7Cb¶Ž®ëFF­V ûûû$鿬š–ÌhÅUY§‘kq2…6½çy¯iAÀ»¾úÕ쾯¦Ñh ñ>;;+O *.d$nc<à:¼éÉ–•I}m¬ël6Ã`0Àýû÷è*`Ïü;==Åññ±Ó˜©Lhš†ËË˼—±}ÜZ÷ì¤-6`²EÓ´tj8X˜FÓ4 ‡C4¥¡ò4c5Ó´JUµoîQ"IÒj¯ÇÀ8½ (“†h·m£õâÂ6f›MÿϹ)ÆO‰°, –e9 Àôk%±ðxj––c\’’é-~õ§¤ YVtçŒ l–ñæ}Ÿ$áCŸþt:ßÍ ‚ä¿4å}›"ŠÉ³ ÒD×—¯=ï,ù”ˆaL&˜ÍfKÆ*qÿþ}T«U''¾ X–…V«UÎb~£hââ ã7›¶ðýfÇD‚ÒÂnÌæÍ0   Y–qyy A ë:4MƒišÙ:„í¥Ù’ñêþ,Y¶ŒýýàºY¦C… 9.<†‘~¯ƒ¤Vï:¨‹}œ 6QŒ÷zjœ¤Ã%Õ³d”f4eƒdÓtô4ð¦ÿJR&½LÕ°ñ4ƒ¹hYaš¦c¬–RÀÓð`˜æ²‡³×ãèêÑjµÐív“§Ä¸›¿D….1%ÃÛA{ë÷ƒ"8L»];êUÆ{á F×õâ8ÜÅŽôD¹ß¤9C˜æ¦Æ5ÔMÓÿÞÖnÛÇ[gPTI„¨kè÷m®ß·ßçmü$IøÐ¿˜Î÷sC0Mº®ïfG`?šÍ…ìåw„L éDsX1›ÍœÇg³™3‡µV«åðmŧÑh ×ë•ÏX[[†i®n°¢ÈÖ@UUˆ¢˜¬†É4måµÕZžñÅA'Šar†Æ”"*•%¢ÈÆj )Œìš¦m|ÅURÓ0Z½éˆQQÕà®öQ"¬n£–¢²Q¿+2RG#ÿ1o‚€÷ºtlf=4róÆ@º]c•²@m'VŠó²c7]ê÷ûÇøÈG>‚{÷îáÞ½{øÈG>]×qrr‚J¥’÷×´ªù(ÄFª­ ÏÞ&p$ugñs ?§¦,ÔÚŸ6Å8Fh<~ T’1LÐtƒB iñ÷ýf3½(L³ß‘oá†éºãy{€DÕ'#Î"þR té¢`Yt]¿9MÆÜd”~›Êº€UYß  ñV]×Me¹Æ*`oô¥ŸM&Š›ZߔԉˆišÑ24®¢Ý¶¯lbpòz¦D¨ªšOw¿¿¨e˜xëWs…Ê‹È\Gš£Fh¼G’(ôó#ʵ÷^iY¶qaDÖ Ï>‹“ô¾¥¦ßïßLc•(b„5LlµðÁïüN<úŽïˆuȵÖétê¦ndYÆÑÑŽŽŽpppPc°½1¥¥h™BbÆñ\kšm¬v»en Ƶ—7—(UÒ4F†¹¦Pëp¸èB½mhfpÜϦ(Ûq¯(‹¨/uþ]÷þ8¨êjÓ3f-zH9’iš7«Ù’—¼#¬ý~¼Ï—$Çaó{ñc}T¤ëéé)¦Ó)êõ:dY.Mj¥°²¢ @À üÅRÂÛíõ7PŽœ2;‚išè÷ûù7è`¥•Iˆiš0M³8)Á€-Ïy­GìÁqðÓÝu΀$:$«±±, FOž<àóÝݸÚUÀv|PgÞ<åɲ"§¸/!xýÏý9üÊ£G±Þ¶6ÂZ­VÑï÷ñðáCÔj5œŸŸãÞ½{8>>õz˲|¿¤áÁ,b¾{XTèü½-t]'ßEé4Ç0£ª*$IÂååe~ª"Œ"`JK«ÕB¯hNDIÊg$é3q HïH?ï±û\‚Žé§CybZ–=*Ê ßkc£]7~4|¾sÓ4aÆÍK¦^6€-£yõa Œ-«†Õ=ãK×uŒÇcœžž¢V«9Ñ×2`šfy#¬nƒUQla‰s.ªjÿD¨¡(5d¬¶a«&€9£³&7Ïû&ÃÓ&CEa¸¸¸ÈßaY¤ÈS*:dY.o³0ËZ4ޤN»›Iî7ôùIå× ŸÆäÐãN1FV•j¦äWæÔétŠç¸ÙÔX–¹MÐ4;½7Žm°e["v—`B–eÄÁÁ&“ îÝ»ç[ïZ4LÓÌ_aIŠw“q%cu“†&lc°èè°Õ67ÊXÕu=?ƒ5Åæ “N–ea4å¿÷Ewf ªªÂ4Íâ(éIÆìÑìQ`1¿t’(ëî5'Éã÷ZI²¿E±›<*jC,Ë‚išh6›++E\Ë(K´u< ~õûÑ^¯ªvÚüïe±"¬ãñõz}éw]×Q©Tp÷î]mm᛻² I=)nc5éù°£–g°À"ãvl}­ºÁjY‹æaÜ”ts¦4PÚØEQ²J‚¢; ³†~¿_9’7¤÷¤Ñ0&‰ñî®%%£™j£àg$шœ¨5°ÌZTUE³Ù„(Š+)Á…j:¶m²*)éõì4ö(}M4më½M"EX'“ ž{î9:麎ÃÃCŒÇcŒF#âüü|«‹OB©£«À²€¬óN6‹Á½›«€€!€"g|6`GW½k¿A%c±›Š=óÌúטf´è)§3CUÕbÕ8qý*“Ú× ¥¿x˜ªºþ=Þ¬0QLçš0 [牂»–T–kÝ(®ê‚`+ú²ÌÆjJМlQW¦{”º´oSÖ9‰úýdýnÁÎ ètÂ_×鄄ʈHk·ÛE­VÃÇǨvõáÇxùå—qtt„Á`°ÕÅ'a§„|Ýy¸ ÔMçk6taG. t¿\€mLË>G¸î ±›ŠE¹våšan¤ôŠ¢­‡)<º®Ow¡¨„¦­W”½Fn³ÍÐ]GØw³nô°ñ× ˜íC)ÀAÙb†aÜÌ«ßH4E±eUQìç-+Zª½a¬^í¶ýþFÃŽ¶zWº&rè°¿Ö`ǘN§xðà3Îf6›a2™,Í_=88Àl6Ãx<ÞúIÄ!Ö|Ê] ÛÝâÕVR xÂï‚Õõô=‚ngŠˆbE,)[¡@%jyÛ!¥‘±n4Mn&Ã䊪ªP\Æ¥®ë›G¥:Ü<Ê 4X×ýÀuŽK¿{D»,ʪªËkð‹ˆjÚ²RNéŽQÖMµïŽÝëAU·Þhæ&A#l.//qvv¶d”Š¢èËn´ÁÚí®Ž¢:p÷¨ 8=ß²ì4ù’u±^k°Öj5L&g\Íl6ƒ®ëKÝ‚8©À·nÝÊûœB)L„Õ@üñ0^ƒÕ>¡Õפu~ V jÅ1û°¿Ã(ºdÄ^ e'Ó”™(‘ª¢8ƒ˜‰¦i0MFªªnžLNòXs“…4XUãS’¯‘ š"œIp_ߢ¸ú^ƒÕoV¸,û¯[mu4ž<±ÿ½©†Òk鎰š¦y3ëWƒ 9uËfP”ղ쌡f³t²É`­×ë8<<Ä`0Àáá!f³™#,dÀ*Š‚z½ŽjµùÃ݆pÐóÓé4Õ.L—` všjgßü¾ËËåßu=†”úë'ÏE(#Pa‡|ä!ß–eÅÛÈÓTÀ%i³ðLéÈCÆÃ°, gggh6›èt:É”j^¡(vd…"*T#´)i—l0™P$Ù.dƒ?ã3Šn¡Líñ»yg¬ ÅœšÒD=Ÿ§H2„§½Ë²ìô ‰= á&à½~¼u¬šfg4öuZÂLHsX{½ƒF£*•ÊR¦_|§§§¨×둇YO&t»]çB¨V«è÷ûÎ1§Ó)ºÝ®s!ɲŒ~Ôa¶k(„±J$ÑíÃ.RÚpÓ8Gö¼U?ždûÕ„B]Gˆ×±˜ÇÉD€IDATºgLžò¨†5­_8ÂzCÈSƃp§‰µÛmH’”L©Q”E 0 Sì£t^ _¤­8°c§°Q¶ Y¿Úlú;ÇÜ iׯy¿oT‰êúܯ÷Kñ¿a£hŠ(ã–e­•qÊ +Lài›Ä-¹’e;í×ýþá°tQU7‘ÆÚ‘úòË/ãáÇ888pž;88ÀË/¿Œ“““È5­‡‡‡¨×ë0 ¯¼ò êõ:º.ïÀññ1ªÕªóüd2IedN¡„œlû4{yèz:›.Ýo‚ä:oÇ– ;²çO)!~ vBò’oÀÞôc)é²](Z‡J&7ò”ñ ¼i“‰=ð Ö}Œ4:†ZV!›Y0 Š&Ûº®/º„,o/Ré÷9Þ&2ÞŒ3ú‰•ö4(šŒÑ¢¦’$7=>K:ø™9‚°,çÝnéå>’Á Ø5ªƒÁƒÁ`itMµZ•<1›ÍpttÀ6†ïß¿étꤌÇcÜ¿ßyþàà£Ñhã“-Lýª;«,Žþ¦,õû‹–Ö›`¢øõžM$3š·pÍS¾c›d9ú&ÆQ!ùËx©íïANMIÚ\çØBSDÙ.‚žÆwÑj­wùÕ¢z Vož ”>Ê´)E”qÀ6X×”$I‚¦iÅË6Èj"˜$…÷ì,þ{ L¤”àÁ`€ÓÓSç÷ÓÓSÜ¿ßø8Ôjµ•hìÕÕû ÿSjý?<úBÌ`µ`GUÉéG×Ý´aó(˜qM[J¯u°`Ò=Ø3aã"^¯9ã ažò%¥†a6%OC×u ³î曆ÁZ&ãã†Q4Ùî÷ûÐ4-sc¡pt»Ë£¤Ls‘õGÇñs²ÞpÇkÑdœˆÚCÓ4œí˜!ˆªÚYy¯¤Dаžžžâàà†aÀ0 àôôteÜM*•ÊR‡áétŠÁ`€ƒƒT«ÕЋ"Éç¹)D„ÕÛÕ6­åt»›^ t÷u÷ƒ-¦×:˜°k~“fFmÉŽËS¾soõÖЂÙò”ñ ¶æ¬¡ñ›P”²f…¢È¶aØß߇iš¸¸¸È^¶5-¾3&I²F#ZZ½$Ù‘Zú¹¼´UM³Ó#í/‰¯¥EƽDI –e9~ÙSYQUûç¦9«BXk°Rú/¥p"«aÝÅÖ1›Í0 ðÜsÏ¡^¯ãÁƒÎãA<}ú4ð¹Ï~ö³øô§?ÃÃÃÀ×b«ˆe£+,-Ý­ÍŸ(ª(Ñk#È ”R·‹“'''‰‡(䵇‘ʘM‹–²»i„•¯‘9::ÂÝ»w3ÙÃóڿ݆fÖMî,ËŽV ‚rG13nM3¸c|eY;j¤º¡ý;LÞ6¡hûwTÝ\Åò¥«ª}5›‹”ö°kÍ4íî³³4Vä:xä¦KiÒívÏk(5ŸšÆ.Á¡‘?#¤ÞÕWQ¼sÑäóèè6¾ïûþ]ê_i^ò Y©¸Jz˜g’Až2NX–…ýý}H’I’ÐÞ´|Bד“aõz†Á# JFd{+Ñ&?EYUík êutïê¤ôcR¥2îÅ4Íâ§ú®ëÑA}gè5Ý.g¤ÌZƒµZ­&*¢Þoëí4È-ÂjÁŽf94io×õ%GUmC«ÝÎHîÏ®³o÷í … úý…ÎÕïÛz˜,²¹|’Î(Šöëb¬€u;jú)Ë×÷g€ˆð'ÿäð+¿ò{2øR£‘…|g^ó$Ëö6xÙ~>S*²q‚šÒôÒòPÓFõµ¤”4öÿýR};ö ï(YÊvæÙ`A2IFf”}Ü0Âk¹½)Á”iõœd&5²”q/™§ÀoŠ®/ºö¤`ºË>HY7Íì²vJ‚iÚ?”`”Fà-rJ01—:;ݽ{wkB½ ¹æÈS:°MØ-uìs]dôÅÑ¥"aÂŽ`Š€¡-jÁý²x€ec¶Û]¨^•:Í’3ØÖÌoÔY:ú®ÛQ^]·÷绣óð=ßóï~÷¯¤ø¥æK¢ ?íQIl°¦möA×=õjèõnæ=1u'hóóCÓì?Œ¢Ø¢ŸÜ{2e&*©t¼&ÈpŒ²IÈr¼9ÚAú”$­:6wxÍ&­s“ËMÓ,~:°_ªc«e_dÝÔ? –eûré–J·ÌM·µÈ«®ëxá…V† Ÿžž¢Z­¢ßïgÖ‚;-r»(Âô úZ°½×kTÕEd0‰BjÂahÁI»%²,[Ç’¤Å}((ÛM’Iº!ýCÈh]+ &ÿ"`ulÁ^§7R£5'r à™g#%É>†¯3·à޼¤$Ù”¦‘Yâh’®Ûò_”±g¤ÈÝ)»NÓ¶×L¼H¤>¢,¬ë©dú}ùŠbÿ¸Á“T"¬¤5v»Ñœ1QºÀa{}h¿o¬,£-úìjwv©e¥3í§¬¨ªZìt`J!ô®1§ý=’^3ÞIY”`±ƒu<£Ûí¢^¯ãŸøÄ’p麎óósÜ»w'''…¶ne®Yaû·uý# K`Mj¬6¶À,mÞlcõ €¸l ‚mà‘W„Òz“*ð’´F@¯ Uˆ°,ÁßÀÔ´åhm¯g¯Í[öäIg²Û`ßA¬muü-‚5—24AªÝŽ6†3k(›ˆ²¼_9)779`‘zÚdgK³¹o{¡Ô°¢x>˜Òaº›tï¥yºÝXߨ¯ ?‰-~_‹,}Ê<ÉËW¤ªöýD’aýÖÛjÙ™k7½ïŽeYÐ4 Eªó§k€Ò5mÑÑ7gÅ^ÎpXÜ€®ª®–16›áÕdQ‰4Öæøø²,ãäädÅâ~üøø8ïï*”ÌküüPh$Y |Pþ¸ý;Ͷ¬ecÓoTSš¶0ì–hÀî|ý5׃e{£—eûZõ=ÆÒ ?Õl†d©×k¹Þö÷—ϯ߷ÏyyÂ,‡A½O/ˆþ–DMÅz½ø»^ŒÛ²¢oRdœmŠd ‚½Éæm¬öz,˾†4ŸQL4}E‹MȃԛtÄ9Í®ô£Ý¾¹yÚL*$Ѥi¶Ç°7ËËüÒ/¶h1RYR¯gÿkYùÜK܉ggþ~2V½·QËŠ—½+ôû}4›ÍüGNº1 [§?ˆ+ó1ÈØ2ÞíWVTÕ_gÅtÊ×׬ãñÓéŸøÄ'B_wÿþ}L§S§«XÑê j«cREÃ"í×eëànÇ~Œæ {‘?R[áéÀ®£m/>߯l‹2z½5ŽY¡ÑÊ FЭÇþ^(uƽ_‘2>ÙBNv•,o¨ ‹5àï~¿÷ï+E«¡ba¨ª=C»ß¦d†ýÚVËc zOPà€¼nÈi䆊ßY¶¯½v{y„§û|ܵ!71¬ðM:&!‰”wEY¤DmROG#i‚ˆªˆlÉóç·Ërô{C%x¯%£ÂkÛ¸÷o·±êýz¨$릡iZòl7Þy×qÞç•÷fÓ¾ŽÈ:ÌÙ‹Ýj­êÇEÈ ŠÙ£×¬“ÉÕjÕj5ôuT¿:›Í¶û E$(ººnÞŸLJÙm·Þt±¿(ÏRã 5Pq3E0>;Ú[4Lê÷7L)ˆpO]é}ºýo'E¼ñ‚±¼ºþxäjµlçM» ûÃÿòiè!¨Y(]8;„ï0\D‡È®Ø8[(b”ioh|@^†?i¯ëâ§Î6k®ëEÞøŽ7¶ø¡Û!Ë”wð7¦@}…ukR‚Ý\^g¿v:²çϰõ@Ij³ÀH²Äx5åjKZüÍÕ· Î=Àýwõ‹FRWG¯'ÜïþE,¼Pê¬w-´V·1®* ªê•®7ÃX])Dä¢÷Åõ ¶Z‹‘”ÕçþîÚíå5ŠâòÍ!è& ªÀlöÞx‹) –e¥aít ïegn¹§º·Û°º=ìï_×õ×~úýRªMÄȆ»œ)(V§ª« }§ã Î ‡«¶Œ·y ÕË}5t/ô;–—›d°Òè¦ØŽGšÿ;… ¯»_?¯ W˜ï\ÓÁ,ÒÓƒˆÒG-JI–7C‹úgøáÖ×!~†¦ l^ÚÉ`­Õjèv»é¾³Ù ƒÁõz½£mÂ:¨Ò4¶¾BI=hÚõµ m¤k‡:Â-éZº|{´éBQ<*NäÇÀRc£ÔiÉVâj8%ü,œúY&}yåcXWŽ'[Ó ûg}7y£ò§1åòÚV/ËòW6ünê~i»„»\ËZ+ù8FÜ÷F]÷ïTO¸•‡f3ø!Ë‹kn¥nÜs¾Þ›{Îj¯çß¡Xe î>Þ5øE÷öþ5v‘ÔgjÇiÃ0¹™XÆÝ.г:ßýEÿåI*Æ*e¾´Zþ¥ƒn:…I½Ï/U׋ ,ï‰Ô#ÁÏèvÇ£Wí¶½¿Ó:hzY”í…¶´4º©ijW›Íhá¼°.V×Þ ³;t:Lç 5§¤t’•0™‰2â;ŠÁêu¦˜¦¿ü…•_%e:}Þzë±Þ©Kðƒ0NqïÞ=œŸŸ;ÑÖétꌴ™N§8::J÷ŒR"l7)­ŽMjÝë%àMý> ¼€ ¹š>¸½ÿ½_³ö$iQá…”áá¼_“ $ô¬fN"¯<¥D`ooùwùΓY³þýWÑù·}ëxüš`„e°y7L÷<¯0D1ÜCM5´¦uLº™…}½Þ›Æp¸P޼¯½ÇñFK©Ó¥4[8è9÷yÓç¾ão­ÿÒJJªkÞQ-†¹&R kX$hê¶ÎÓüɃÔ|9­Öb$  ºô¨ô‚eûwJ•\·&w¦'u. ŠÆÒ¾JÆôº³î(kœ©AQèõnF…B˜Nž 4WqõƒËåe°’ì“®·ÝO×Ñ´Ez/eRÒã^¹òóyQb¯c]ÓÒñéšæâ~ðàÛðå/¿'Öû#…öjµNNN0 |G×Ôëu2ºJÝÚí‘”*Ǧ×ǦtúîW\ob¡dÊIŒà¡£è ÕºQªI»m ˜­±`×Ífm(Z°ÒžÏãìñ9ÌVHT÷ÔéDÊÏðÖD€øMÿ€KôMý—nCîT|å]–—=Ø$¿Ahš-×tü¨Îýu)W”ÆB]´Ã ¨p¿oÞ)9ÀööÓO¼†)áOë #è;k·íÏ£ãÑ߬ ýï6Æ0 ´Óª;²¬›;ˆ)–e­ßË)“ýþõöë·"¢]ªj+ÀNoTêÞKI÷r?¨.•^O{äºý›îTŸ·.£yxÝã#Šs”’ëüJZ6%Jäl0MÍ´¿<7n¥ƒ¸î|¥þé CçzþJ÷,Þ ý`š¶|­˜¦-Ã~[eP  ÈOãýúýÅšÈÉ”¤5›À¿øËxôè ±Þ- £•F×L&']x]á¼ Spür aûK‘V{}ç>Ò€owà%(wðâÂ6X ¬52ÛmûÇ4—•Ý¥”Å}ØÆb†{€¥1 ì1>—ñÇ$ÇŠë’U”k­d½&B]§—0 Ȳ ]¿–»~Ú×þ5\lºä×!‡Ëºf²¼èó‘bé€x7†‹‹ÕÆQ?#èst}1–&¢Ï nï,íi¯¼’Þ÷V$R­a5 Nf ÃÚlòŠgädQÕk£Ò¥/‘Q鷻裑­„{U-M³÷$¯*åµW(úiŠcãPÅÙÙú{HœqIê÷˜e2°úµÒ5M ×ƒ¡³oˆ´"ˆTÂD2ç'{¦¹yÿ2÷gPê Þ4ôZÒ?€`y'8Uʤ=±ƒœV_übü÷FJ vS­V!Ë2ŽŽŽ Ë²c¬Îf3§ñR Rp(,¾”@Æê:‰rµvî#ìy§ëþÀäÊÛPas—bå”hÖjÖÆ*A½ÛPÖêLê†]§üŽaC*YR$ °¬EÝäõ8›Ë/†7[£×û5?òB)WmêLIâù ƒRûi¿H ÷÷´ò7c‚átàÂAÊ×3Ï\w˜o¬¯YÜÖîãqS>bâ§ÄjZxÚ¤,/jïÈÙè†~Pàu w$i¹&)‰ŽA5qAxºX™‚]Wã-[Š:ÚR×ÃKލþ™œ;AÍ"ii›ÞÿÉÐu»ÔÉÛ Ñï3©¡S”Œж‰Øk“ɇ‡‡yŸ/ëÆÚ×…öîjþ5ƪiý_ù˜¿ú6Àïìͧw·i®i(tCOYÁE‚Ý\ªuý¹½΃IDä@§y‚oêìõûhŒùóaý¥¿¾öXôú(Êyõ2ÔËrƒÒÈÒ6XûïE…]e£9•þäpIÎPdº‰ ‚}í?yrÝaþl}-ù. ëz¸lg]ü÷çk¥/^¥Ö=¦ŒSŽMÓÞ³h.}ÚŽ¶¼žÌ*‰›æy[è¯ÃÕíQÓ‚Ç 4v7Ž«¡ªd:и— c,¥E¿o¯‰>7-ÖõøÈ‹Ô Ö"tqPpýÇn431| ÅÀuÄøÔÿ÷7°7jQ„Ý”|>¨ÕZv»wqŸq/±PawÞöˆ4ê†|;²ËäBä¹”A³dB^¶ öz@ç¥ïƒqëû×+nmNZc‹Ý ÓöüS£¨]Ž($žS|ÀÝ´’ Š‹ „ûOL)˜iÍ,2¡Š|†ÑUÃVÆýº¤ÓŽÕõ/ö¡(Qq2†›ÍâEs˜lˆ•Fx>DÁµi(Êf—Îp¸•çe%‡‹wßò}QÇSÆ9Å‹‹Ý¾ç»Ùyƒ5L™w÷ÛèõÚ¦“6`ÚThÿWïBïWÿs×ÊxçDÓ Û6A½þÉ#ªÒ„m¬²¾—;‘”ø°ÁuLÓ–uß{ÄõŽK5 ŠOVÞË´š#•Dó†Ãå›s·/ Q•·(Q²yÚBíjØ¡½—®‡ïaëœn..v3›†ñ'Rc1/ºŸ¾ötE¹tüœ/î©5rÓé,w¥öB×9pÒ¼÷ß´[×άa :¼7KÁ¯£p €èîöKEeAž|v´2 €ò1oØÅRT"+ñ2HuDnD1@‰ |]ø{&K,ËŠ6§2*»n ýýÝOõC ÁšaŽM»¼‘!ê~D¨®ÄÜh5\r57ƒÕí-‰…½ÎG¢!n$iÑôÔýØ:ç ÍöÝ´ÑÒMgç Ö0eÞÝRÚŸ{Ñuÿpÿ "üëGI²ÓN;#ãXG8o8›¦H*Š­8’Bb!éwQ Q&R¯ae¶‚¦-ÆU¶Ñ·±ZÚétE#T‘jÓ›Q2©0lv*ÃD!ö~ÝØ1‰ÁÚïGKLð›ïLôzË×À:Ÿ'Ùl¬nÎÚ±6“ɃÁ`ífúæ‘-Ò7~#»Ó±w#V{“îõ"\+AD”¡2âÕ€Rp^‘U¦0„ŽAÐõµ&Ý z½ÅHMë=&+¥“1©´s·e-ÏëeÌh -¥`Κ-MÝx5-Ú˜Q´ßgYœUÃ$Ç4Íxõ«îöÑ11ŒÅäÈu¸—ä;Á]+Ž«wM7e¶î6H-ÂZ©TP¯×ó>Ÿè˜&Úz Ò}[ ¼ÞÛn׾Ɇ ›eÿÅ,x,M3&d°±ÊiBC“Ü×@é2Ô¡Ñ0ìÿóË‘µs*£b»®Ë€°N›^hˆ½eÙÑåå²b7ÚŠdûl×÷¥Ôf ¯:¶öß(Š-@VŽ1›»i5މ¡CÓ-B’ì}'êCêR«µþÖ iË=p˜í°6ÂZ«Õprr’ÙÆãq ¡;™LP©TœY¯I0 ]¿pym\ÒLÙñ<Éÿ+À§?wüŸÅhR°~$ÛX勤4d-ß¾=‚F(Š‹”Žª2IØ–ŒÇöÎ/Þhô”åÅÜV‹ íbrq±(¶­X–­±ÎŠû§ÌC9Ü–l6‡L¹Ù’$-Dž¢¥Q-Iö˜!f÷ئŽ{¤_‹êh GÜÌ `ÑLÉ­¥´,&%ÖFXÇãñŠGd6›a<oüáÓéÔwvët:Ž{÷pïÞ=<÷Üsþg VnŠÈ2ê²ÄQAµªÆðüþÄ7ïøïƒŸê’\×7Ç@òÆLL.lC¾}k´;ÿ¢ ¸ç ³ ÛÚà FÚôûöõÐíÚZI£ÁÆja5ì4C8 rø†õLJ„¤‘ÔØ¦lû6‡´¬õí{#BóÝĘpÆì(Û”q ÁS@M3y€(rAÑI”üâ‹/ú yT¦Ó)t]¼ŽQ­Va^yå•Èu´~¬(ôt7öùlQ´>lÐõtSÿŸOü]D; -Ø£k8 ¸ðlS¾Wj´¯1ërçÒ`ÍÜ,¶)ãD¢ó–µœç>Ú¡"6VQÕÕ”¸½=ûßv;Ü`Õõõ#O6ê˲¤0²MÑÕ ÑuÛOÃ4 ‘‡ŒÌÑöÐl&¿dz½åYÐLñÈ¥Kðx<Æùù¹ïsÓéãñ÷ïß`ׯ`Db²tqP÷uôÉ{HI² ÕÈ:Q@öèNÝj­-‹BÐMØm¬²ŽU ¶)ßKP¥š 5Ð`˜$ä!ãa#Ê„ÝNwŠb• à™gÖ¿O–—4o°ou²|‹£äެ ZÊ,Ékÿö5X7L¡ùñn˜Bn:Ê:(&Ô½zS<éÿLqÉÅ`=88ÀÉÉ ŽŽŽVž»ºº`×εZ Óétó¦iÖžµ£kÜ)ÖòNgqƒIâAòz…,Ø)Àl¬–ŽmÊ÷RíuPŠ˜ Ìw&)yìá¦i¦;ƒu‡étlU×m#s8´3‡¨1Ìèk6mßÍ„åÈÃp¸0UuÑäd“Û_T$ÉþÛ—ðúëïKý3òmÃ0– V]·Ovƒt`ÓäRmÆŸ÷¹¥r]×—ëW Ãé­¯ëö¯‰•vy’©Íjš]!ÈÉtNN™étŠÇãË_þr.ŸD˜|À›o¾‰ñxŒ[·n-5AXº DTè¹»Ýn3ñÆoäòÙiîánRë¼!–UÜ‘¦¹0PÃPUÛˆñ*yÔ5–ÎÍ0‚ËŠ70 $ɾ…õ«ÌòA:øÓ§Oc½/—kaó\ÃNî­·ÞÂç?ÿyò.Yìß@ÀˆI˲…6fŸÓd=¦Ì$ÕÁ׬·nÝrНý>0mnݺÀÓÅáþVêB<$ÚÔ³ê¬*ÁŽª²±ºÓ¤)ßbuÜSöJ2Ù“¶Œ>åA±š‘ÆNÑÕ<ºIR÷^·n×ë-¢¬I:óºGèúJ7ëñ…lû:c„F)Í›a6! R‚iV„MÆ0ìý2;˜›ÇZƒµZ­zL² Z­¢^¯ãüüÜù\]×Ñ 1I4h>Œ6²3*Y1ØyÒ”o+FN»ªÚ é m˜Êl‘´÷pÀg|“4$C­]Ó¢ÕwfAаúMnqÍæbò_¿6vn-“…l/5Îb«$‡žÊ ¸ÁÒͤpM—;âððãñØ)ò~þùçcgI¡÷´ˆ§Ñ|Ñvýom0å"-ùv2LÓ–ï·£ªÚ?ÛèJÏ0@z2NDJ VÕÌCŸ†±°'Z-àòrócÒ\Qj…ÐïÛH³iŸÝ«²0Žé˜l˜F'mÙŽäŒ €äƒU&MÒ–qÃ0V÷oÓ\Ûwƒ&õ‘|³s³‰l°N&œžžâþýû¨ÕjÊCœšºz½îûúZ­†—^zÉ©ÁJš~¼¤äÐH‘=Ó€ìFKÜÄ€‰HÖò \7ëÐõÐ×PslNícÒf2øD¡¼P±eŠ54aÁý±nå‰F»HÒb wÄ©RcÁÉP¥¯Q–d»½A¿f#¶)Ûí!#˲ÕV♤lKÆu]_°JÒZ/œ¢°3†YÉ`ÕuÝnÕju©¥õÑÑ*• t]Çd2ÁK/½”ÚÂ*•J*u²‚ ,zý»ˆµÉ·`§³±Ê¤DòíŒùðI %—SŘ¼Hk_]Mظ# ðÉÑh1ÂÆ›L†*ÍívmB¢7év×G79úY<Ò’m ]2äƒ/âx%¦üä-㺾¨Ye âX›ããcȲŒ—_~y©ðºV«9ˆïÞ½‹_|1ïóYÂñmRl¤Á®-åœy¦`8Šñ‰Oàôôt냼Ãp”—ÁjY¶Â¹_‚ôGØ0LJ|ó—¾äëŒáÑÌ®°6¸ÝN­m¤¢,ŒUº~z=û~ašË&•»SA°_ßjÙÇêtìÑ3Q÷ÊìKS#æ~Ó,mΜaJ‰¦…>mY‹T`vè1nÖ¬4 ÊÛÒº^¯/¥Óó~C±sÇ•¬i1êŒú°Ó€9å†) ¦iâë>ÿyßœ0Ïì –eÅß´ú~[ sRš&°¿oÿÿâbÙÙCF(E\Ý´ÛvDÕ ÍE•eûÿîòv"1n–²(÷| š–éä&†I•¥ñ’в(Ö@V÷`†"Ô°V*<}útåñ“““¼×ÊÒÜ>W„5Vo]e ‹eYøO~ó7—vvM³õnûÎì ¾ç#bYv„S’ìÝÍÇ¼× ™qZG˜(,e¬i÷Kj Ï dÊÄ’ÁÒk Ó±å›u&ˆµÖZ­†Ùl†ñxú:zÞuÍç"¨êÚL„U†àÙ¨L±±¬¥tj–Ê0»ÂÊÀyÓ´}íûì¨i»mÛí¶m´ÒÜQÛ Ø-¾n˜m5{€R̦l˜¦iׯR¦£Oz#udgc• #’ÁZ«Õ0 0›Í|_3›Í0 P¯×Q«Õò>'®¬ºõ]ÿÕ’r²ãú‡a ŒI»üµ`“Œs×HfWðí.I®ø5ˆ¢Q%%¨Ý^DD%É~ޝ&Oœ«®‡ ãpÈãk˜râDXCšŸŠ"g0ë‰Ô%øÁƒ˜N§¸wïNOO1ŸÁ`€ïÿþïÇt:ÅÑÑQÞçã@‰jÊPߺoeöìU†)0¢g—7M®]ev‹•óŠbk7!‚n‹2)¯ b3a†II’|Gï¶“_’aʈiškÄd†qk­VÃÇqzzŠÁ`°òüÁÁîß¿¿Ò˜)O~ã7žÁpø§°·‡xÆ*tpzS2x̳k˜î¼æ­šæ¢Ë/ÃG¾½-¨¯á¬¦ì82>ó⹄‰‰C$ƒ°»?xðGGG˜L&ÎãµZ­Pu«€½÷ÿäOþþüŸŸâ¯þÕg‣TLÁYj*†ETöÄ3»„SÿDš·JiÀ¬à3Eg%ÝÝ']R×y| S^t]_ȸ'‹@×¹A$È+Q©TP¯×ó^w(¢ܽû_àG4†›ÝÐpcÔ·²à g˜RcڤѨjhè”2ÎØXeÊÀRº»OŸ¦ñžÎ”§ažgd“eÙ­¸.›‰ClƒµL–m¶«m°±Ê”˲ðŸ<~ìx-%‰ç–1»ÇRý“ îåTÅ×S–ÒÝ} ™ñ SVœ AX²Nû};Y†‹L"5]*#¦iÚù5CŠ—ŒUNM`J‚aøðg>Ã9ÀÌN#¸‡¦4ZRU;½Œ»L2eb)ÝÝ^b Sf–æ _cšìŒa’±³«(ж³.§¦»f•U¦d<ó¿á¬ûûy¯†aÒeià|·ë[ì¤ë¶ÁÊ©eLÙX™/ì"Ä?Ã0¥Áoΰ ØuÙìkgⲓ«eYø]ÿñ?Ú¿„]ýëÙÓÔŒ¯þûÿðMßÀVÚÙÏìN:0ໆ]ÅÊSFe^Q]ó®‘$Ž@1»‰kt<ÃÄb' VÃ0ðÇÞþöõW…€;ð1%äwþ›ƒwýÑ? Àsî$Éì+3X]XÖb| ;k˜2âÔ°êºãq¡¶’ÄN¦Ü82×9À–Å™`Ìfì¤Á ¿ïÿß×k2mØF+ÔŒo›ÍðÎw¾3ïe0LfX–˜2I=<ØXeʈ3ÒÆYmµlû•aÊÎRÃ<Ãà®×ÌÆì¤Á*~ï¯ýšÿÕaØ`Æ<(È7¯®ùn4ò^ äišIáñ;L2eʼn>õûÎ>N£É¸v•Ùœ ™ëîaí67Æc6c' VIQ­Výsjtðø¦ôüÙ?øQtg“1ÌNÔé½Õ²•{†)+¦iâ_÷uKíRE‘ëV™Ý"¬ÖO}ÚÿöÎ{9̰›sX #8÷€½—ÌPùÒ—QD§ÁR™ÝÃI'Óõ%7Íh£µ¦È˜¦‰û¿ök@» Z¼3;†ištÊ7þ àêý¬z3³“VÈ2ðGŽ–k0aŠÇå%…‡o3»‰išø®?ðì_\)¢ÈŠ=S~¾æ×ßüèÐí¢ÓáÚ>f÷¨üÖoÁü è_ù.NfR¡ðëd2Át:÷&À_­ ìšÕìæJÜ ƒ)‰äv”‰‡o3e ‰Œ†?ôúëKš<7£aŠHùþ#¿ð øº¿òWп­Çû8ST’îßþ+_òöÿ½¿ö5yŸ³#6%x:¢Ûíb2™dYFŸv÷uˆ.`¬{dgyŸÃ,ØH¾aîëv¹~•).›Èx·ÛÅWïßw Vðe~4b™gŠÁ&òýÕ矇.¶¡)œ1À“Mäûû—ÿÿîsÂG>ÄÙLj6Âz||Œjµ Ã0ðÊ+¯`2™`0Ä;H¶áÊ3*™‚±©|KÐnç} ̦2þŽ_ø@–™«Ã!«LqØD¾¿ùàŽ=G˜eš)"›È÷·<³‡¿û»?‰Þ_ÿyŸ³CÒ`N§Ǹÿ> R©ààà£$®Hð]¸úº×ð½ß«â—~ (ºèð¾]^ýu¼ñÆxÿûß_š=œ÷ïíSöýûçþçñ}ß÷}[ÿ|ÖÁËC¯MÒÁãîß…4Xg³YàsOŸ>õ½Xžþy Z­æ½üØL§S¼ûÝï4TŠÌd2Yò•…Ùl†§OŸæöÙAÉ7üí¿ý·Kù]å—“2î+y*iéíá?˜Û9Ä÷ðíS¶=œ÷ïíSöý;¯ïœuðòPök3…4Xþü ‹¡R©”RØÂΩ ”ñBò•—$ò½î}E§¬k/ó¾’çwÎ{xyàk3>I们ßs™×^æ=…÷ïíÁû÷öI"/…¬a½uë€å´„étZj¡b‚å›ÙuXÆ™]†å›ÙeX¾™"RHƒµZ­¢^¯ãüüÜyL×u4¼—Æ0ÃòÍì:,ãÌ.ÃòÍì2,ßLyÛ|>Ÿç½?&“ Q­V"ï“““Ò¦0Œ–of×agv–of—aùfŠFa VKÝÝêõzÞËa˜Taùfv–qf—aùfv–o¦HÚ`e†a†a†an.…¬a-+“É$t”Äd2 oöüº÷¦yi®{›kg²%KùŽò|ZçöÚX¾w‡Md|Wå{[kg²…÷o–ï]‡÷ïüÖ¾æÌƼöÚkógŸ}v~çÎù;wæÏ>ûìüµ×^sž¿ººšìcsžÿä'?¹ôþ°ç×½7M^xá…ùÇ?þñTÖ½íµ3Ù‘¥|Gy>-¼ò½éÚX¾w‡Md|Wå{›kg²ƒ÷ïü×Îd ïß7C¾9š‡‡‡¨×ë0 ¯¼ò êõ:ºÝ®óüññ1ªÕªóüd2Á`0ˆôüº÷¦Åx<ÆéééÒc›¬{›kg²%KùŽò|øÉ÷¦kcùÞ6‘ñ]•ïm­ÉÞ¿Y¾wÞ¿oˆ|çm1—W_}u~çÎùo¼á }þK_úRè{7e:âôôÔY«÷|’®;ÊóL¹ÈB¾³–“0ùÞtíY_›ÌöI"ãëä ¬òÍ{ønÁû÷v×ÎlÞ¿··ö¼`ƒ5&“ 1™LððáÃ%o‰;ï¥Z­†>6¨¹Z­n¼îóósT*躎Á`€Éd‚««+ ¼ï}ïK¼î(Ï3å!+ùÎZNÂä{:úÚd¶KR_'e•oÞÃwÞ¿·¿vf»ðþ½Ýµç¬)Ðív¿¼¼œ˜_^^:¯Eq.ËòÒóÎóÃáp.Â|>ŸÏ̇áóœ$Ióv»íüÞívc%y=ÃÄÁ+ßó¹-sî߇Ãadù¦÷³Œ3E'+Ùw¿4Í8Ÿå–k†I?™–ey>œß½2Êû5SF’È:íÇîcȲìèó,Ûñákèt:E½^€í‘‘ey)}¬Ùl:ÿ×u¢(:Ý!Ý¿“—Æý^Aœt„ ⾞a¢â•oB–eçÿnù‹"ßÞ÷°Œ3E$+Ùw¿Ÿ /½û^Á0i$Ó^¼2Êû5S6’È:Ém§Ó®ë£ÑhIžY¶ãÁ5¬AQ˜¦‰Ñhä<¶nä¥PÊ0á§Ä0LžøÉ÷:X¾™]`Û²OõSN———yŸ>³ƒ$‘i†)#Ie]EŒF#§”ϲ,´Ûm ‡Ã¼O©´°ÁZTU…ªªFKABVI’¯ Ax®[bŠB|¯ƒå›);yÈþp8„eYÐ4ÍiÂ0i‘T¦¦ll"ëÔ8i8b8:cÇ$IZjšÊD‡S‚sÆ0 t:œ­("ÍfÓ)öàt#Ü]È*üf˜"&ßë`ùfÊLž²/‚Ó±’G/0iE¦×e†1LØTÖÝ‘UÀޏ²ƒg3Ø`ÍêøÛh4ð¶·½ÍùQ¢(b8¢Ñh Ñh`)%Œ”EQ°¿¿ït‘<;;Ëû´@¸|¯ƒå›)3yË~³ÙD³Ùd“ëdZ(Šâ;„aÊĦ²N#löööÐh4°··Q¹·À¼m>ŸÏó^㥀‰¢èÌa¥MnÅÅ݈ƒRÉfW`ùfn*,ûL™pë,î†2 ³kD•uÊK™6$Wƒu2™jµZàó•JÕj5¯%æŠišØÛÛÃÅÅ$I‚išh4èv»œ_X¾™]‡eœÙUX¶™]‡eœ)¹4]šL&èv»˜N§€jµŠ~¿ï\4ÓéÝn×¹˜dY^é–xp§[–AÐn·ÙX-8,ßÌ®Ã2Îì*,ÛÌ®Ã2Δ‘\jXQ¯×a^yåÔëut»]çùããcT«UçùÉd‚Á`÷w• ívOž<Á|>Ç“'O¸ãc `ùfv–qfWaÙfv–q¦Œl=Â:1›Íptt¨T*¸ÿ>ÎÏÏôƒñxŒ‡:ÏàüüÜyÿäŸü|êSŸÂ·û·çôU&ç3Ÿù ¾á¾ßð ß÷RbSÖ#_þò—ñ[¿õ[øoþ›ÿ&Õãf%ßð#?ò#ø}¿ï÷åýÕ%¢Ìròå/¹”ûŠa8==Mý¸¼‡¯Â{øöùò—¿Œw¿ûÝø á/¤vLÞ¿ý)³Œ”yÿ&Ã1Mxÿ^…÷ïí“dÿÞºÁZ«Õprr‚J¥â¥ùÜç>‡oýÖoÅíÛ·ó^Jl^}õÕR~ç?Ưþꯦ~ܬäž>}ZÊï(·œ|õ«_-åÚ_}õÕLŽË{ø*¼‡oŸÇGÚ7ãÀû·?e–‘2ïßï~÷»S?.ïß«ðþ½}’ìß[7X+• êõºóût:Å`0ÀÁÁªÕ*Æãqà{g³ÙÒEææ]ïz>ð,»Lܺu«”…í?ð?PÚï|6›¥~̬ä¾þ뿾´ßuYåäÖ­[¸}ûv)×þž÷¼'“ãòîïáÛ'í=œ÷oÊ*#eß¿Ãä))¼ûÃû÷ö‰»ç6‡u6›a0à¹çžC½^ǃÖžÀÓ§OŸûìg?‹OúÓ8<<Ìë”S¯×Ky¡ÀÁÁAÞKˆÍùù9^xág\D¤-ßðúë¯ãððçççù|qPF9ìfe¼âñãÇ™~ïá xß.ƒÁ/¼ð>ó™Ïdr|Þ¿—)£Œåß¿©éQðþ½€÷ïíB:xÜý;·.ÁÇÇǨT*xøðáJêAaõ¡}ýèG×Ö‘0 y=z”Éñ³oøà?ˆ“““|¾4¦Tœœœdª8ðÎäÉÑÑîÞ½›ÉÎû7“7´‡ÉÛ&ðþÍäIR<—k·Ûuòè½Ç­[·`)·y:–ÖûÁÜ@’¤%CP„µ ³Ût¿Þ²,hšAÐl6W·>^Ûï÷¡ª*A€(ŠÎÚdY†išKÊ»išÎšÝk}ç;ßé¼—a²Æ²,¨ªê\—†a82*ËòÒµ¤ëúÒk[ŽAXrr¹å_Q\^^.}Þ§>õ)œœœä}ê Ã0 Ã0Áëé÷ûh·Ûèv»hµZPUív;Ò{;t]wŒ1úE†a@UUèºî<îU€÷÷÷qvvæk¤†±¤ëºÓ4È ŽáØëõ t]w"<€9v+Ì^,’†a@E˜¦‰f³ MÓ Ëò’RÞjµ ˲c꺎f³‰ËËË"Ôãñ=ÊôïÍdÉ [Þ£¾ŒB’Y–ëÇë8é÷û°, ívÛ¹†LÓt®úݲ,çwº>-Ë‚®ëh·ÛÎ:é_Ó4¡i:Žãp€n·ëœÈ ¦ý¤ßïãÖ­[yÿy†a†a6† Ö-AÞÅÅ`8¢Ñh,)¹²,¯DB-ËB£Ñ€,˸¼¼t”_2R)¢Øl6#¶²,CÓ44%EÜm4º££tº‡¼3yaY–S¸îuî>3‚ 8^t}Qi”»ÔP’$ܽ{o¾ùf¬u±Áš"º®CQgSŒ«(H=-²,;‘0‚—Ò £@õ½‘E‘ñÌ3yŸ>ãÁÝ˺K7fÀŽ\’gšnÚ­V ÝnÍfÓ‰˜FRŠ¢¸”ÅRŒií´án•Fh·u×€e­ÐlB¸.)ànÁL\ȹšFs>/nï:A=hO ¾d¸3Úí6†ÃáR$K–eüÐý÷!(9dTFuú5Ÿs?G÷wóE·ã›J³ÜePNǹoŒÑý‡tÒm6Ù_Ýz!7•?1Ì6ñfCº8äð§kŒ®Owö™¦iεHוZ¶³îZIÒG&‘Á: 01™Lpÿþ}T«UL§Såø'Èò¸Ñ4JÝ®BžKtJg^¹¹(Š­ˆûÜtÜÐÈ‘,I²#Rë¾w]·_±Ñ·§Í4M§þØÝ‹6Ãýý}þ›š,Ëh4N®¨MÉÒ¦Ûí¢Óé@„ð5´Z¶,'5 Ã>ÆÅÅòõÐnÛÏ­£Ó±?ÿ:Š×÷Å”Ã0Ðjµœ ?%ZUUÇÛn·Ñl6WöuºîÉ8¥è¨$I0 ÃqD)ŠK=,ËÂp8 ½wÒgãñ8﯎I€Û‘IPßr^ȲìÈ d„Z–µ¤g†á”BP H޼:¦éìt:Žœš¦¹ä„OsªÃÚì1†IÚ[ÝQN2,½û7íÛ~6 9‚hÊI^ŽñØë`0Àùù90›Í•JƒÁ“ÉäFŒQpw!$I ¬Ó¼)Pª–;‚æ]UU@–íb{ù£¬šø™Ì*”ξUUÑï÷—ùmzTÓæU£Ñh©†4ÜÊPàw iöÏ&ë4 ;JÚïîï¥ÛööÂß«iö{»]ûšbvw£/7îÈc±Ji÷ûûûKݦé^'Š¢³—«ªŠýýý•®ðî®Û€}-SI tSívÛÙüF™1»‰®ëŽaêWêä6N½ãóÜ2¢ë:†SB¥i†ÃaâR³³3ìïïÃ0Œ%y‡Žs…#¡LžPäÒ}ÍPʹߨHÊ6 ¨ªªŽ.wPœÌÏXët:Åéé)NNNP¯×1™LØ^«jµŠ{÷îa2™ V«å}^™@7]Ó4ýÑwò¤¨q°,;"ðý­õÜÆrDKCç ë@³ow D7oò¸ÑßÑ]OÀy]ÚµÖEˆöz½¥qO+†-{†‘ÜbšÀÙ™uà•aY—k·Ó‡j¹9x'è÷ûÐ4 –e9Ê2—t½…Aõß”¶åí^ ,Ò+Ý5â£ÑûûûŽÂ#IÒÊ½Ž® ŠJº®fQ]u³Ç™ì Q|ëöv2FMÓt"5’$9ïít:°, £Ñ(4úE§’eggghµZh6›ß{A@¯×C§ÓYq°¡ÊÄ…öFŠnX먃®-Ê.pÓ}-¹³U¬ÍX)#± Ö««+@½^_y®V«¡V«9Q×]ƒ„†êivËÚHù¦º?À6l|#¥¤€ob´Z€ûÆ"INJd îìÞð÷þ^–ßd© zSr2¸Ó=TUu:W»ÇÁpš$Áó–‘R^šMûº ¢ß·å3ìš’$Û‘$×Aïu+i½^´MLá!cñòòÒ‰xJ’äDB©ë|D£Ð(åž(`yd™dÀRÓ™0ãÂMCJÒ®)H7EQœ2o"`QEÑP·¼Ìu:g]šNHI’Bç¾Ç¥($7ßõÚkÑ2ǘܡîh÷Üõ½½½D+5‹Òxò&Ë`­T*€ÙlæüŸ˜ÍfNÄu×pwÛé²aØÍ^æóøïUU×3 Ãf²°ñ¤ß£ß.Ië›Ó¸ÓE_ûôi¶ße‰èt:$É×SMòV«…v»½ä„¸ñÔ:¬ÖtM6“,I¶ÇýZY¶kT£°ËûÒ ÃmŒŽF#4 §nÒê÷÷÷fFÔ½X”eÐ& ~ÆB”qLîZT޳‹Ù H§òŒýý}ôz=Ç€%=ˆ¢¨^cd®™2…į ÄÃËKÞ× ŒÛÑO{fP@«Ùl.•Z„A½¨$ËÏYtS‰e°Rõððîqbdx’c$íQ{7ÈÖT)îéQ¯‡f³é¤×{ñ›ßn·ÙPõ!vÓ¥““(Š‚{÷î°;õžž¢V«­4"*;d¬îl pa)Ž~¸ŒP*ð/Òl®7XÅ~(®¾6ižû}’„¯ÿ¹Ÿ¾ã;¶ðeªÉ.¤3æmoKéß&dL†•‚ÿzrã×ÈÍ4ícrŠPi0MÓ10Ý#5ÈKoDQtÒ'Ýøñ$É©u?·Í(§$IK]€9e­ÜPT•"ôî¿'É“öïw}õ«y¯’¹Æ[6%Ër,»€öHww^j.F)ÄIÆ`Þ4b¬•J'''˜L&K]‚w©Ñ)òÀ 3V7‰~^{ÿ©2Ð3D›´eÙ?Þ”ª£¥×z£îHiœóò4³yÏ_þË7Þ`¥þìÅKÉ­uµ¨Q>êÚ{ËZº~?ú‹¿˜÷7Ä`±êõzE­VËñž7 Gù1MsÅP#o±Ùlb?r³¦¸ìïï;Žn(¹"8ÞÙ`ͪ±¦Næ’$-éünCuÓ_ívÛéüN ôºÝîͲ16äwÄyñx<†$I˜Íf¨Õj¨×ë¨×ë«E›¥fš&†ÓÕ°0¸ ¹,¡1qp½>r74Ëò¯Ï£œºžú}VІ¶n÷ x‹ZÑä›6`š…ZØ£¢GkÜÎuÊ]PS0W `,4mÕ‘CÇs}Îíë&yYS4/–e¡Óé8tÚ[­†3âEEȲœ»êÛï÷£¯;©ÌçÄ®É6EPÝШ™³³36V·É=äKž>1Y±k2w¹ßh4r2ÍèqÃ0°¿¿ïteïõz9÷izeÛœWÿ*(± ÖZ­†J¥²²á%e:âððpåñÁ`à1ÓßëÒÆ0 4 t»Ýâµ37ŒíÜ쓬‚°¾S¯› ú<]·Ÿ“e[1÷~AŠ‘Û¦è-!Ë+ þßñøà¿ûw™~•E“oÓ4±¿¿ï4p)tŠWÑ£¾¢¸© ˆ?նʲ¿óÅ+ßQ ¦c~ß ,]S/<ûlæ_CÑd< Œƒ¦iBQ'rå®ï$ãµ°MiL3ò^î½½¿²!M+¤!»+²M]£÷÷÷±dÔ´‹çŒæDAF튌Ç%¨Ü~o4ŽQ™V•oP¶M™œ“E!v—ࣣ# L§Sß×­=Ît:Åd2Áéé©ïóWWW888XòôU¶àmrP/$YwŒó¤Æ~oÜ´G2ZÝçešv#AX}žæ^úáVÖû}û÷Ôá¯V«ø`Fµ›E•oê>ZšJIÓh·(†_ngŒŸs&®Â¢(öq,+|.kJÎÄuUÆ7…œ–ùŒTÏ)ËràèB7(¢†0®½f³¹T—µö¸4·Ø-û Ð|ðoý-<ùÚØUMkÙ5Ù¦¸[ž À¢(°,«˜= v‰FÃÖE¼×SØ5cYøìïù=¸Ñ’vMÆ£bš¦3Ó4(ƒr8:ØÓ.—j·ÛKMõ˜xÄÞí PУ¬ãñ84JûôéS'Ýx[¨ªZü”¬¬£N¦iGâFX©®t]Ó-]·Ü£<¼F¨ûwJ¥¤(„,‡¢h×÷é:°æ&üä{¾ÿöï@í"Ê··ûhá)òu¯Rî5\œ/~´Ûv·aËòoÄ,Œ-PDߪ+:;;s:{³S‡HQW €~¿ápXì{H´/"²y¿‡P,˾¿øÕ^'àŸûfwî¤~ú»$Û4Ó×k”J’„QÐ>¤WæG#Û )ËþŽ!AÀÏþ¡?„f´œ]’ñ¨(ŠMÓ0צ½g•_ý+K6È.ˆ•l–ú…ƒƒœœœ·”S? 0 2ϱ·,Ë)†.,ÛPD›M{óL"L²¼^ñð>ï­SõF[½©”A©îãu:@„Úãÿß»ß7¾á2ù‹&߀Sª´¯v»ÜFëºMÙ4ãg#ŒF‹îÙA¯Ù’ÁZDß÷(Y–Ñëõ–æŒRÝ·išèv»N‡G÷{wÂXÍ*÷ðbš@‚ò„wL§øÂ?˜ú2wI¶ißçÆz9bÁzË&ä7`—d|ÔG€² ¸F;GL3| àb¬p~~ŽÃÃÃ¥ÜöóóóTÏ‹"¸³Ù,“㻡ùbb‘‡4ocŒE»½\›•¨žZoTÉ›ÂèUòƒjÿ‚e;z[¥q›ò­(ÊÖf3¦EÉˤdykðÖ¥T&ñ2 Bè yö1 R¸MßêØH×¥ºªªêt’¤ÆÔI’¢­ý~¿\××:,+~'ö¨¬eºÖQÙ¦ÛÕÉ™ }a‹Æ$”AÆ×AõÛÔD•79C% ‰< pzzŠƒƒÜ¿€-ÐÇÇǘL&xðàÁFç3Nqÿþ}<ÿüóNÎ|µZÅ`0ÀÁÁAàû>ûÙÏâÓŸþ4&“ NNN"¥y•¢Ž£èÍœ\—¶ë~½ ØJ»í¯ÄûÕ<”^ãáüü?ýÓ?·¿ýí[ÿŠ’Ê7¼þúë8<<„,Ëk_K”J¾ o¤½ˆ4ËŽ¯âá§„[–-ëªjËs×óõqñøñã\¾šmïᛢiAXi€4±··ç;z€ š­Zªëkq£ÿQ I–àZÿ©O~ßòÖ[øÌg>³Õ¯fÛûwR¨¡§ýæLXyUPãIÀÙ¿'“ÉÖGF–mÿ‚ŒÕÂ6·»‰\gþÌ3ÏÄ{ÿ<WWWó;wîÌG£ÑÊs¯¾úêüÎ;ó«««ÈÇ£÷¬ã7ޘ߹sgþꫯ†ë…^ˆs:óù|>o·Ûóápû}[§ÛÏ%)ïU¬_£l8Èò|þäÉòcOžÌ碸ú8qyüÜ$•—¸Ÿ‘–|ÏçóùÇ?þñØkèv»ón·›éy¦Î:9*²¼ü»(.þ?Íçí¶ÿûz½LäÙ$ò—"ìá›ðäÉ“¹(ŠóËËËDïFó‹‹‹­®¹ôx÷£$ßßÙÙ|úgþL¦òR„ý; Ãáp.IËeüåýÉÿ爳³ù_úØÇ2_^Ù÷ï ...æ¢(–C·"L>ÊŠK·K"/±R‚¯®çúùå€Ó<Ö« gÿÇã•Ôƒ§OŸH¿K™®ëΰöÂÓë­Œ­($aëó‹¾ ‚Ý&(Ú´®nµdlS¾©áF©jWÃ0 ;:™7~2îŽiZpF@·»SòìÇ6e|SúýþJs¥8äÚ¨O׋?ðÛ@ß_œkÛ0ðæí¬z¨STÙ¦ÔôV«MÓ0Š¢®(ÉÆz•÷ŒlM[Ôµ¥Þ;›å²Ô¢ÊxTÜÍóJ¡Û‡ŸLÞ+Hÿ|6ÈžKTÃ:ó¹f³Yਛ8T*'½˜8==E­VK=5BQ”b7Zò’B²1–µ¨}‹SgY‹5%™ázÃØ¦|÷ûýrÉ·¿¹Ãº^Œ Ü4W R÷bAبN£ìlSÆ7A×uèº^Þk$KƒÕ;Ë:M‚õu]æÝ˜&¾Z­f³¾Š(ÛªªB½6ö»Ý.F£×ê šn@2O%NëšòåDe<…O•Íô)‚’JSÁß²–ñ¤PmwéUM?jþÆä¦ôû‹9ßîÒ–½=»‡°ˆ°–` KQd[UÕòŽ­)Â^¾ qF“Qÿotµh.Š"ãQQív»\z}yöo¡½8MÜ¥R²Œ¯ÿ;'¶Áš¨†u:¢R©àèèÈ<œFýê¶Ðu½xžõut:ÙÖˆúåˆú¾²ßxv Ó4Ëçqw³îÚÌÓicÁM•ÊêLºat:òÏ䳬læ8’ §}lwV‚[rïSYöhØQt]/c™²A²7Ã2 ¢èžEèÕP" Ã(w??Úíü‚£ÑT.òb#ù¦á潞m¬åýwÛöuªiËJH f-ªªbTj‡ÖÉe­dáÀLzÝ™¦íèÙß_^uöž§_„Õ›VßïÛï§ñ\»¢¼% ßïc4AÅݨ[-óßR¢õZp¿FWçsSƒ³¼ïµ%¦”A¨(ä9F¨ÕJ¿ÄÉã zóömüÊlë±"¬4‡õøø3×Íf3@á —Ö“u ÍÙÙ²ÁEr·©v¯Ó²ì÷1™­¨~Õ²l%..‚o š–ý ˜¦íð–e0í´r˲kUÝñ5mU¡`J 9pJQ"IÑ»þRÏ´:n¥¢ÙŒ×|¯Ù´÷ÿ^où}A#Í¢Œ:ëví×QÖG§S¼,£- ª*dY.‡G¥lƒ,î.¿˲°··øœaåÈž‰KžkÚÙ)eÅÄnºÔï÷1ñ‘|÷îÝý{÷ð‘|º®ãää•J%ÝMêžZêîEÂݦš$;ªZF§À¨~UÓ¢¥›ëúÂ˜Ì ÓôW’-+]§ß·eW׆øpÈ–ƒýR@3JóÄ­¨Äɲ¤ÅþÑl.¿O×ý®Qaòôw»7öÞ¢iÚnu@-3ÆÓ Q”t6Ú×ÒétÃÔKiPQ ÙÈ«Lšºž_–MÖ¦O§SÌf3'rJsXu]Çd2@–åB«@ÝSèµaƒ´ÝJDVÝ!™ QJ°7u)ˆnז鼣вY”Å4m#õòrùÚÊÛX`RG×u )´,D1äÚíl²n²0Š‚2m¢~Emo(º®C„݉®º’IoåIœõ&ù›¥¤ÜÁ²,´Ûm˜¦¹¢ÛìÜ(/YÌCõâµ)èóh|_öFTs ‘jXOOO1NQ¯×!Ë2jµdY.gcë©qj44ÍÞ¼ýnÌ’´ØÀ%ß‚|M³7a6š GâZŽ¨Ê¯(ÚÑ ª»Ù&ÞÎÓažut:‹š8V vŠ~¿Ó4!Ë2,Ë*_ª˜,GKËÊxÉ´ּ_%š†í 4ÒHì½¼Lz¤ÛÀVUû\‚œ)QÓ*ý&-”é;É˲ ( F£ ÃXÑß)êZºž4ÑNÞþwúI§c—‚¹?›¾Ó´RƒM3•ž kS‚«Õ*úý>>|ˆZ­†óósÜ»wÇÇÇÐK–{OŠL!ðÖ¶Ûöc~F. Yâõâø¥X–m0·Z<ª¦€†‘,Ý=ÎŒßn7Û´`·üëú¢¾g“9ÁnhíEÙ˜Ô°,ËIÖuý~¿|k\¨«7³³ì̘2/Ehìw4jݪ(ãod¹ÜÝ’3DQ´Ûmˆ¢Qazîù;;ÊXîÖž%Û²áRŠ°Æªa•e<ÀÇQ¯×1Ke¼šÛîJ´kÚªÒOiOîAÓÛ‚ Qï½Fi¿o{IÎÎl£uo7ÛaYVöŠMœ9‘IðFNi_i·—7¼M®å²¥ˆ2‘PÝnÍfÃá———åò¾Ó©8×— d×m•š­#h4“ ;“ LО^†î¸Š²œñà¾6×9N“¦±³NåDO)ÝW’¤ý}g£«„(n'›1 ±ÓÙŠÜÆnº´8Ç…ñzpp€Éd‚{÷î9u­E$·ß½á‘à§4S—Űn¬Yt•óóæHÒ²RÝ_¯g?GÝd‹žRi(Ø8Qf ~ש; ,ËÉä2zõ™µ˜¦ ]×w#u2Î9x÷é4¡;ëPUV²3B×õÝ3Xòd¸øÕ÷Ñ߃Rš7Å{/Û¤ÜeGˆÒLiç VÀ–ƒmG‘I¦ãØ‚ìÜL1í?±Áê¦V«áèèÈI."ƶSX½mýUÕ6\ Ûè Úz½p¯vVٺ㊢m¤š,ØZ†HUöšo@`kx¢)ëdr • óƒÙEQÐ+{c’é(k£±ú¾MQÕUÜ{­Ó\Tïkv]qÌ Ã0vÓ`- ~£—Ü4äþòrõ±þ7÷«ÛEqI§©Ìøu²¦Tö8²M÷^¿ Qwù ‰e°ŽÇã•ß1 Vž+–em×㾉·Û¶òl¶Ñæ1¡4·RGš0ÃÒï°;jY.4q# VÉjX[AFôc~Ʊ7Âj¶²MõÕ{{ö5e¸;Szt]/gƒ%/IAi6ÆðË»Ÿˆ¢½_Ðõ¶¿_žhY ÙºÞÂ,°¬UeÞaìÿ³S4U¨‡×u×±î|t5ʘÁ´ðÊx»lO§V†=N"¬“ÉÏ=÷Çt]Çáá!Æã1F£q~~žÙB7ÅÊ3e‰RhÏ΢¥Ðzk#¼ŠLÚçâ}ö®Á‚­”¯ÿ_d:rœ¹œ‰j´“È’ŸG8a©&ÍæÂÈ kHAçj¶‘Jžðn×^ßhdÿ¿è)ëÌÆ¨ªº£ ¢*`Þk"­(ƒWV¯ŸfÓ¾¶(mq4ºÑ#g²f'sÚ»)󬍸”¤åkDüïQÔ 9éçÞ`4Móu>J’äDX9ó %Èá’–Ó…fÛgD$ƒµÛí¢V«ááÇÎc§§§Îc/¿ü2ŽŽŽ0 2[è¦l}ã÷sq…½6­º 7î6ÖîÏ1ÍÅg5´¯Šl˜×ësë¯"€àM´û)©Ù/48šäá䯦š¦ÙŽ ^/~ SzLÓ,V÷÷màwÍ®»'DUJü Vo6„(Ú×[V³`Ó4“eÍêøîžÇZDüÒ%½Î™ 9™†‘\q¿á÷0MÓ|{¸#¬¥Øó÷÷Ó9N–]à©§‡Ÿ¬JR´úY÷ú2ž»Ö`ǘN§xðàSŸ:›Í0™Lppp€J¥888Àl6+tjðV7~IJ>gÎ’w @»Íü:¿ï†„Ø„VÛ†a-ò>!ð:ü‹¾æH<ÒÈGéÜô3Iq &`̤ßïïF£%w”FU×+»îë'Jã%EYßÉÑOÑÅbGÁv˜­Ñ£9òY8ßÓļ·çÿIòOŸŒãö¦â—½´aTU ,ípw Öu½ø™ieBf}ÉiÔ’*ïúdÙe;liàÃZƒu2™ ^¯;†)g„ÛÃá~¾ˆl¤Ðç[h¼‘Û¬eàÉ“ë,"–ŠYÚ䈱ó«eYÉ”›<<Ü­VteÅ0Ší…grò¬Ýé ìîÔîWKƺñ tý4›áµã~ʉ,Û ÌÖ1M³øJù&ýÜÜÆhPV(®¬–egþD5<½ÍÎva?KȺ٪îÒ¾Âëó›èéÛväx¦›¬U’FªßxÌ Xk°V*Ìf³¥Ç&“ jµZáT/;½ùo‚»nРåyÌ„]#Z$´ëŸ°2¶;rÓ ñŒá$>ã*Ô^(=Ê1¨^ޝ]ÆÃÎDW[¹¡sY7NÆÏ£¦©ª}ì^Ï?5XQì”{?ÓìscgGÚ¿Žòî½%Nªc¿?]¾È‘æ-²®tOEôûýòèòIÿ®î4Û,FYºñö« «ô~7t¯üË 7`­ÁZ«Õ0™Lœùª³Ù º®£^¯/½ŽRoݺ•ÚâÒ$±BŸ%êõÏÖ>ﺳ£×PªTaG'—^{ýS Ø‘Õ3„×ÖfXP6òÆÇõTú¿ˆ¾ÐÅgúmÂÞZղܘ˜­TëTJÜ‘šuF ÕFÅí9;[½¦šM»Ã#GR ÅÎGXâÌïÕ´ðkJ–mÝi2Oµ«qšÀ…5¼AD™½*IR19–Þ2ŽS~Yž«ª®êi:ORœÁ D4Xëõ:1 pxxˆÙlæ°Š¢ ^¯£Z­ÆZ@XÍëd2Át:MåD·.઺>•±àôZ ˧%<–µHÛßæ±ébµå;|†Uú lK¾„)2I9›¬’Ï-¢³‰qئŒä‰/|ZX¬‹¨z¹¸X(%¢¸ª x;Ÿ2yÈ6±³«ûÞQ„½Ým¬éE… Ûo4Í®Û5›œ·9EYó”q7†a¬5XEQ,Fýj¿\^¡( ¹.²#Â4÷uèþn×<Ôõðk"åóÔ%¸×ëA–eŒ®‹åÝ ˜^|ñE§‹pÜÁíÓétiTŽûñ{÷îáÞ½{xî¹ç6YËHM WÖEÝݘ÷"nµÂßë—²Ii*½žíIËS·PüZ·±eïm‰Û’o`ƒ6ï²ß¶‰G˜Þ'ÅŠS‚ Ë6eÜMâšm?žyÆvâ)-/L‘k°ÞD£>ò’íÇÛUt¨jptT×÷À ì¡( h(ó!îýT’l½¬Õ² Þ-69+’ŒG‰°ÒžŸ{‡à°×4i“޹^ÇI6Œ[¯Úät/Ê`E$ƒµR©àÁƒxùå—ñðáC8Ïàå—_ÆÉÉIäšÖét ]×/‚ããcT«U†W^y“Éd£‘9…œÙÔ„© ’CQ\¤x¿§°‹À²ìÏýð7k:Ž$…§u>fÓekD5V·Ì¶å›H$ãÛN©¤Í\Ý"ÝÏÁJw¡ÈKÆ ]×Ó‹®>y²ÜÙ0M,+þX‚$¡,GÜ0ò–m  :KäQ¥FH~èú"e^–í×ù]OggáÆ¨»v/.²lß·4f®2î&jÆŒ,ËÅp5árGë7¹?¹ål]Oƒ4[kØg‡]ϪšÁ ØiƒÁƒÁ`)… Z­&J>??÷}n:b<ãþýûlcùààÀ‰î&¥©c‚SYú¨†‹¢¬zùú}»F) äÜ+Àžà‹ ÛÈ[K«`k³Xóo£HÑ¡uɯ_>)»¨¼•˜ç[@nYÖöú°?”ŽEt0H—‰;T›j4ü"©Q7ßì4åu¶½„üŒÆM,]Óé?Æ—¿üå­/?©|À›o¾‰ñx¼rŒ­GW7Ù„’(9ŠÍx<Æo¼‘Ëgg±‡ûË`U”EmX¿ï_'–E„•j™Ö­^GN˜‚â×C–må¡Ñ°•¦V+úÈ2™Lðøñc<}út«Ÿ›ÅþíG!Ëì^ƒÕ4— ÷ër6žhÿÎBÇ^Ƕöo‚zÌ”.£Àk°šf:ŽŽ ïwÿ^k°’ðQzÇ+C£nÒ$ì‚;¹·Þz ŸÿüçñèÑ£•çriºÆ¥ëÿAõ t³ÒueÇ[£ÚïÛaý¤‘d¶¡ZDGC²4`72#ûêê*7ƒ5©|¶ÂóèÑ#ÇJ$vÈÜl·"nYË™~rÎ-ÿñèÑ£\” ›=ÜKì1eÔÄnoo¹žŸˆbT&AlŽrìM•vÛþiµüÇ×ìy¬YìßA²ŒiSòì L×­AýS’›Íxci2€öïmË7°ýÛM¿ßG³ŒÎµ^o9‚ªëé칂°ùó»%iùœ2šK:x\ùþÚ¨/tשFm®”wBؼ¼÷½ï…$I¾)…næÈ£™^Þ”Hwº°a,”Mnp&¢¥»_¿ hVmŠOš!wcMƒ¤ò ï{ßû|å;±C&l–Ø:ÒHQqË7`ËxQ¯Ó’qtt”‰C1 Yìá^byã-ËÞ‡ÃE:°w¯ÌÚ8Ø–¢NFëŽspp€jµºõ=<‹ýÛËNGW½Q(·ñ˜Õç©êâ~Õn/ÿ^ШíßqûäÁ6öoÂ4Mhš†ËËËÈïÉMóÏ3Œt²ZÒª}]‡;%˜tAïØ3IÊÄ`MªƒGnº´-nݺ`9-a:n|ánÕ[4›ÈÄjD5ÌHŒrÓ2Ít¼éQRua;k¶±:б¶ DbTOòMöb³Iä2 …ÊÛö]–ýËÖR‘ÕNÄO©ðñY5óh·×+ Q Ú"Ì­¼Ád-ÛÀެÀòµ iÙŽqÑ´e]¬Œ‘¼-³ ':N1š(Å!H^‡ÃÕTò~?ß,Ò„Ýß»aøŸ—(†§ÇoqP@ƒµZ­¢^¯/u0ÓuulCˆ>¶)AEÒq#…á“·¤ÙÜÌxб~&¬É“%Ô˜* cH^÷š2YÈ7Ð!³¥ú!‹ŽÞ†) YÉ8aYV¶‘ü¼ï߃ݜãÀLx>Ç·G91x zLpm, ËØqb£µ(Œ[§jÉõ§?2§B× hoˆ,PhUˆè ޱ²¬M·@#¶Bv#A4íÕƒœö4.’¢ÇMì´èMœõ—k¯ ;ûÇç…ó>Crfô|aWâËü8|æ™çù=o+'i7“©‘››ÁFwØ?S)‘ÇÚÆ ±HÙbdÌdeërsv˜EË8 ¢«GGi2>bÖɪ*ô±×ýȾi…Eë|I ßÏd_‡ummÍÒp‰ðÊsJ­VsìpZ©TpóæÍY å;G!5ó)U§Ô.w«ì¸ '.Šíׯb¢¬:D7c›nN,C¾‰Hü²SmŒpê†ÍFE&Y¦Œ›É„Ã÷†Î©ð+e²kg5*ª*F6ù?·Ý6²¢d6\0V¥¿5MC¹\Ξ¬“ƒJP}§[“$I _ÚïÝå‰emRnnŠ „ åˆKþþ|ÖR©ªˆ:) …B"ÉJFÚ8ÑG4'lÑFKÌ1‰1€H—.ÇX“-„k,µ@’’o FÊ{…Ój…oÿï´ÎzݘY­rºVŽHRÆÍ¨ª yÅ]<æú²Gaid‚=]n 0˜ð,R¶3±“N³,íT«â>Ónûßêu¾‡$Ä¢dÈpÚ;5&"¨)Ñ`\}ôªÊ>(pâï%t ëéé)ºÝîì'ìÌ¥e³ôúU7DsXµþÂ×®šIÒñ@4XZ9´÷b8QwÎiPu½.Œõ“64˜@„®a êäQt&)̺»Ý×8Ã횦19L.QUÒEú~ƒÞ»dÙMåEŠmÆ tã¼´@eM9¬né´A6dì¸ÙüIf‹*Š(0'ÜêgÝšË.À5¬Š¢à•W^™*|xxˆR©„N§“HšpÒ¬d'§Ý¶ÖÞi¼J U¸7cZĈª³!”¤®‘¦?‹–ý”DW“$ֆ̲7sÒ²yÄ\, àÍ7—\{„5‰l™,D–™È¨ªŠ^/‡7*¢ÕÍ$ÃBc© ±±IÎëÑ7!Ë º®§Ûau‹rÚ#¬Å¢ø›[t5j©–Ýg1²L‚0ïåe·-Ù· a===…,ËX[[C§Óªª³ŸN§ƒµµ5\½z5µÑÖ•à.p³3$x×°&uÒ!"«@|ç­óõô:„£Ê}D"kC&îì³ ¨®‹ÝGînÊ$@èè*tÊ-­•jµÃÀ<ŠÈ󴳄SWÑ Ÿ»Z5"­’$jZùž’I4MKw&A§ã<²EÓæ3\üæÇGÑã‹öYœ&D¸Ý£Ví?™ä°îííA’$Ì ™ùï{{{«þ\úÂ’"ñº ÛüžIª*ä ýþiÔR£5'XJEK‰¸QÙn‹kƒü"ó$“ò%±fjÖn‹ÿÓõ "²'p¯çâT:@ƒúÌ3†.i6­¥¾4¶ °e9T§çc¸ôk—ð¶o¼-¡“¼:"e4É~ï‘ö´&s„®a côJR²©½ÿo.1¤z¤,‹mÞdÔœyô“TUq ™"<Ì-‡^ã–5M|ôN‚Ó 4ÍH®¸H·ÊÔv¶wÎ¥ª–t€„ €'ž†ªý½ƒØs^;v:« Îé¼nÍ£¨^¼×3.„áë°V*ŒÇã¹îÀv¨áR¡PXÙ‡q"²Ãº±áì9ÝÙPà;6¦Õ¶TùøÝì°öû (G Ðÿð̸ÛJªjÈŸªŠMú¡zvær )B†c"Äþ¾¸Í]KûŽ”½3ãèæ`>Göó Ë¢_P¯'þo^5tmDX wºwðàbžà B_vÜFµêýšfì0 ¥Ó¹8§:R³Ž´¤Yº9ζaΩõzìMµte&î;€îT·}t*‚CÎgåu:ÂÎhµ¼'Yiš±”r9ÜÀ† S¬hÝ››±Nk¦H­œÓt3²,¾œ¤n°º.„ªß†u±8ïgi´*IÁGr&̱,;×âú y¹lø+Âw¬M¥RA¥R,Ë888ptHÇã1ºÝ.jµZêFÛDº0Hp¾˜ Jô=S4:qJ¿/Þª^‡è"lzÛrÙØ\¤4”(Cû= üDöm«%dÔn»™72«Ug9vD b»m¼¶Xœ¾§ qÎÄß)…·Z¿&)Â|r2?æÊ¼æØSè¸élh½Xh1ð—ìA±è­X%tÊÈæf2K»hÈr¢åe©&t «ª†»Á.2Í©Z5"¾æð À3ˆ™ôCòU…þÏÿ ÿï'ÿBÜ>:SÆuZít,Ϊ¢ˆËÄ/Øjž"HKtº”é²#_AQ„Ýo÷Sȯ°÷¡q»Lu]ØXf[ªÑ0Žc_r‚Íï×n_ 5ÊÁöQ”D³)¾´8†'MJ ]_¯ïõ —$÷ˆÚt¯‘åyÃ?mç? º_»v £ÑW¯^Åñññ,Ú:p||Œ«W¯b4awwwÕŸ'>rtÐ ã ¾üËP?<±1_ãIt:&Yõ°‘t=Úî[«ôÿ7Éð½Þçä$¢VÅ,Ý™]û5¡ü[@ýyqƒ ÝLY6>·y§•jMíŽy³É}¼Ô¨ƒ¶Š;ùÅ-,”R ÒQÆGÒ2‰´ MÖ ®Y'ôdØÆ‹´ÉúÕ4¡ŒigÒnÕ2MÓÒÛpÉ ¥I†¥\Fûoýê?û}³Ë‘aÏh6g e{u:ÞûMN„í},Ìhš¸ éTK’s6ù/N¶‡“¾î÷­j¦^ë¶æÈI·ÕT.y’-R×!ØÏæOböµ$ Ù>;KæýÜ6tÝØùxóMqÌFD“&ÃZ©Tppp€µµ5ìííáÊ•+¨V«¸rå ööö°¶¶†ƒƒƒÔEW#5¤i·…s»y”ËÞZ¥ J%4þ³·zT‹âa ÓÆ£Ó{PúûƆmI- |ßj{5›âš¡t_Rè‘„"DdØ Jmþ‡@ûº¸I4›ÖÔbrbésxrÆ›ªß °ÍMCa.Ë+¤Yyé÷ÅÓ½œEJ=•ˆ„¹7v:Fö²p2¸Ì¨ªø”EdÆœvÕŽÌ‘jŸVÕÜ£ßw߉(—EMC³™Ž]f天 õÖh4¦"¬ª†á²{LÝøeú‹M ”"´Ñã›D’œ/ºeÕëâ–EÏsrL;yûŸt¡“™ææ„ÚËtÝ}ïÊiÒ”y#Þü7Àvî•ÔLŸ>c» |ö³ÿ8ú—˜RRÙ!ØÏæ u*Múýnúý¾ð”è’¤ ä°†ÓzëÖ-t:loo£ÓéàÖ­[©tV]÷¡‰ªUoC»\ö´ } s߈\özÆÛ‘³Ød×'2ÒlÎѤ؊E!Ÿ³Ç§N ü_çßg_¬+±M»s1mhD§ŽÓx§fÓV;eb0 `ÎkJh—-P£HMÊeG#ÃíéTïïå,Ò?ˆCÅ?¯×ŦJœÌ·°ç’2àÌçè÷Å×wr"ŒjBŽ+eûÐÚóî°f& ¸[Ì ã@Zº½Ó-£\º¥Z…ðàÌ!IÛÍšz$Õë@ÿîÌÍÜÖ4Ã'0ã4ÊÛí–U­ ÍüüvÛ°#ìÔëó|~÷sƦW ²ù½ÍΨ½^ð~$Ô<’ÔÆýØo„ÿSNš6f@ùÙ_Gûþ?˦êä°Êr2Ü”Øa%J¥$IÂîî.$Iš»dzÆK™ƒŠýëuÿ”0/ ¸tÆÀÉw~ÚÑ‘‡,yØ6æÚ óNÝ(D½4nú²ê ¶ÿoB¤ <~¯g5º™ðø¦×Èr¢9ÕdPp‡* :ßþ´ZÁ"œý¾aœ¸]~ªjÔF÷ûÞï«ëâ¹t_ôJµ2GúéšuJ¯¥ˆCÈ@ósÖíéaÔoÄl‘M›_˜æSËòžœÊÚ'7t=›F³V6/Þé¤fsš½þ? óàç|_wô«cÈjÚùwAû/Ÿ·ìP·Zî™ùö(+¥;í¯Þ½k$¸ÑÆ¿›íÐlZoOŠâ½¡G‚´&/ÈaÝÜœíͺR,Šumx\,í!üQ°eˆD:GI)¦TYÛûh¿ñ‡À‡>´êÓiUÆâ÷SíLIÚauc8bggg±g $;S[Ù †½Wø¥ œºGþ)3`þˆEP ª›AÚk› ü±%¦ÖÖ!íDTõ ‘Çç0É¢i€ŽbbÎj§c4ÿ𽥋06:U¨“uœœøß¨u]¼Ù sBU Í+rê”ÒKŽ“:PÕy'Ù­¤5šk¯vÌéžHÆ”y#¹Ñ°¾'u‡4\¦®Ùïa®e{Çì¼±”±I̘PÕ‹5§‚‰ÍB²BFmIÏ™uRñþú÷·\Ÿ¯ë@U ú3ïªU4÷ËèüÊ÷š>—©¹¤ö„5¿d sº°ë$Ì—R•ËþϺqN òe™K™Â»C°¦-žÃx\ÔœÂ\T¬iè¼å±ÿKoXŒnßéúâ³È:;¬i$PCš°¸Ì?Òu@/Púá»¶¸~ëuQCíÒ©È;€üÉd?®'DTµÑ™÷ÒqSþöÑ[q°Þ²ÜØmQþã=è÷¾‰£Ï¾;Ðœê› 2šì˜wÝé#ÛïW´‹n¿FèµäHšÓš û}`0¿ÓqIІ-Í"6Úß·¾G³i=U^élQ)—óm<…®ò+v"®ÃJƒ¢½¬cÆÂ``Ü2©Ùe3ƒ’÷±M¡Ê—‚b+|§:S7(ºYTÎsÅ;¿£öçŸÿÃ×Ñ®+ž;­[ ^„½®sO‹ ÷+jš¤ÂŬsËådËÅŽò½9¸(bgÉÐ.o¹,CP¯K™Î`4yjjQBõ'¿gÕ§$Ó—UB”ô5’k‡Àbòå´eçý}ºl«Q ò+K>tbfÎhÅž54-¸.ßÜô¶ë)e×,[ŠÇÂþÁç.AîY-¯‘+N)áö襛ÿ°±aýŒÔ¼Ë JqkµÄçõSÖæ59uªìõ CŒÖGõÚN× $YŸv®_P(U-õ¬¡wæ5-ü“f]„…<+Uõ\Í8aHç)3£\¿kZ¾ƒÖ‰wN%Åh’eêÄï¶3++—-óÕ¦³ ¥_yòùî\Ê k ²É@ÑWwçG˜~fˤƒØrN:ÂÛAk`(EË42IU…؆ÝÓÌ:”õ£°aš#¯IDAT°Èk„©†È½Ãꊹó]@¨~OoÚ,lÀ2ÚQ¼Æ8ùäf#f–Nzêç/®:¦8ˆxw:þ“š(Âh¦Õôo~÷Üs{=@úÄ%ËߪUçµ8¥ÕÒ¥c~¾Ûö^ϰÇÚmÿæx46I–ƒ9‹ƒ¡x½|%ºõ§ü¢qh6ÇCeEQ–Óp)ê]–BæGGùs' u÷“×<×gÇN“t¢ßJÆdçPóÃzÝù\ÎÄ–ògÏÎfòìdÔ{%˜ûøA›|ÙäUUãÌžPµìFJž© ò}#¸©$è^•w-rN¹[)VTrí°ºÖ°Z:LJjP¾„}FaZXÍ+!|:­­#/sñpL#›¦4RT U†E¯çžYBÓiì"]¯Êÿùë– ÁíxN6¼W §^N÷9r)e9HvL˜Tí¶XGÖÆ˜%þ–Bõ”[¾¬Ž”GG<0ÚD»,Âæ4–Ä ·(y ´!Oõ^¥GÔD²^Ç ­ZT²c@¿åCÿÊÙ25Ý0gÊ·Ûþ÷j¨”¼é+fžDz8 ±õc0p Ë“SåmôÊK š¼l‚.ëEFYiúGÒÇx«ß†Ã!ºÝ®ïÇãÅ|òØ[holLwòܦ7{ ªâä“ñÚj‰m«%6"¡*F;¼°FR”ì1"ªÊ6cÆ´µíWFgžë–få¢ëEC‹WõÎϪ EÚG¿¼¢W Rrdÿû½ç¢Æ¨Q#6¦VOh£¾ÕŠ^$œ³ÜSE±Ë€ô†Wš~Ðè*°¼QS« tš$)ìv[œ<'MJS–ÑùÛѦÀ`´Z¾õQ >ó =Õ‡òÁÏAþ„÷!)*$ã„aœH¤Ë{”šM%cîðìÌÊ‹ ë¤ tP[- 4Ù éûMbÖB¡€Z­¶¸3sY½¡ÇLÑ4kh²ƒ67Þè(âæu—]‡ˆ˜A>¿ vV+ÓB¯¾&Íl/Ì#(9ÀŽÙq4S¯ê£Ê,ÌiïxkǼKI݆ÝÖ'Ió ý‚~Ž$i6Ù0K ¡.Qä)ªq$‡)ù©ý¾Ø¤¥±NF°yIW’¬›Hð&C¶Ã|E1¦8¤OC^Uç?49¬GGîÝR§–¢¢Qþ¡·=Fƒ±ÏÎPÿÚ§¡>õè'gØÿ¥·ù–’dŒ¼áºP& ‰¤GÁÅa%ÝC%ÛNØ›B:®pi¯‹H?¦}«´Ü–åäûFX+• VýùA–ýç_A1dt•:ÓÍ^¢ëèé-ôŽŽ€¥>ÆŒ 1ÇÔ¯±¤  îÈËp¨ë››RmF¿ï½ËeÖádPÚí¦³3÷ã—+cPÝG½èoÄP„„ª×óiÞ*÷­aˆÀç©e³—àÆ[ˆp,óÒ‰}ž%e5‹Ý]7o^™GAQ”—~w›ÍéF^/»FXUÕûË¢Îm­–ësf›ºn„»§'îAŒËjUL)`˜¨ÝD!ü0™1ý~¤/æ©n—`»m\n·ŸFÃØ óƒÊŒÂÞžhÏÊÍ&¢Ò-êåáuªÈŸDÐíäÄûØ”:ô+¡sIº}c#¹Û±o„õôôtÎPÇ8==Mf.t»]T«UËOØ9¯æ¦4º.†`oüÊÏ„vÿ%É&4×¢@Fü\«2ü›‘³z„@cp˜t“„|¶.ØS‹p_ˆ¤¦9ïæQÆ€õ}‹°[óçuÊ:È=;«Ù') Xœüp³õBaAEÿßÜ4:[¥ºÎìÐFТýlêÈm†Ñuß—¤ä[×õù«ÙYõR̲ŒÁçÐ~ÿgçŠK鿳·¶ jSÏÏ\<’Ôß¾ÑUšgEˆ ÓÕjèТÙ6òаR) ["=Ôv2;–a(—½³cèýü¢¬öÆùA¢½F¸õöûÖóiž‡ß«ׯ_Çáá¡{—Ò8??ÇÖÖ–E‘ …Pïa¾@@û÷¯Aºü(¥PWœgŸJÂq”H1ãßexwù5;«Ü•7$!ßsöœâVÂçÖ‹ÆQU¡ ½"1Óž ¦)‹Œì0é")Õ¬#‰YwïŠÉX2oÁŸ¥¦©Sglgåµ)äwÍRÍkÔ´®En6mn¦§sRòía¥.¿,áÎ[~úÿýš?òV”M'Æmqˆ@‹é8L:IÒFñÔáŠbÚvåQ.}9èš°Cé[Ôú–<¦jÕucÑܿퟕ.F9‚]wRVZÛ9‡ûûá҂͵¶æÿ›O© ·u߃u­~‘Oú|tzƒê ³Ú"‡5‰ûB$‡u<|øµZ-±ºXM¤?ÿOÐñ×\ëòìÐÛ‘{ÿø' à=É|`ÎΨ vVsFÒòmÖd´1ïvp3DIÖIÁ$¹û^­²³zÑHJÆ=ëWÍB›4~s’VL½. /óHâ³r2´ƒÐmfx5YJ²MÓ‘”|;ʶª:‘ª Ÿ| š/~7:Ÿûqô¦Í“ȸÌZ‡s&=$i£xÖi“#êôx½.rJý6,ëuÑ(ƒÒ!}®{ã0·KЀ¿ñ§À·ÿ(¹ì6e§ vVsH\ùl»–º>«_5ïÞõCŒ=¢ñ0§‹1ñIBÆŸt2*ÊY)uV©”ºÖSs²0Yqdü8AÁ¸ ºcÚç Àræ’]«ªÀë¯/=z|±ô ùvœ/ì27Ò "5›ÖÑ3Åbª³Ö™ ”þ÷Ñ£GøÒ—¾4»¨ìM:tþÝGf;~6Žg‘sÀ‡~+Ù>ûn¡ö3°³š0£ÑwîÜÁW¾ò••®#Œ|À׿þuœžžb4Íþ6sX§Ö«]yÙ•a«å^O@Š%gS=.$§§§xðàÁª—K‡®Vjm}ÁvVÌ×°¹c}‡µ\vOÛß7 3ºn”ò¶Û"ðÑhX›l,ËIúÍß¼‡ßþí¿Ä_üÅ_.ç€.„‘o'ý 8DXÍ!“ÐËONŒ ÊEo0‹…ô÷ªÇE&¡¿†K¦1|®È2êõëPüæ?ÌWu²Èo¶®ÙÛ,—­YcÅ¢QMB˜ur³9ï°žœøß¾ÌÇpêb«›ECé3<óŒá\:©•^Ïðõ›M÷zÕrYœ'³MÙh¿+ÓÉžN¸,‹{1ððáà;ß¹è;#R™<°½½^xa–3_*•Ðív±µµåøšGáÞ½{¸}û¶c ƒÙ§§è©ù¤º†¿%øqñm%Õ¿Ù|­µ œâŒÌÊççç¸sç¾öµ¯­äøQäÏíÛ·gÏw¼+è„¢¸•´‘ÓhXÓ ™ìqûöí•;Iêp]×wçƒ;1¡yÛ«o¤iFÍ¡½fj?üˆÂ^—DÇ©Vè)*âØô¸,[_»L}ñÜs¿o~óõåÐFùvÒߎõ« ˆíiÝÔ<¦ÓáTà¬CúûáÇñ{[D Iýí›!ãWÃP,¢z$‹ôÙ˜Ÿk0pn"o×eÓÃZLêít/‰ÒsëucÉIGÒßœêóí)¼”QC×·SН9JNµ¢zÛŽùõäXÒ,ûz67sR­ŠóHM™(mÙÉo6諪ŸúÔ_óÏÞ ÿN|xíµ×&ëëë“_|qöóñ|îoô³(ŽBXN8Éùd2™LªÕÉäÍ7]c¯'~èmONÄýáèhuçM–ÅG]ÄšMëûV«†¾°ŸÚ³³Õ'²¦Ã®GY–''f…=™x#²l|Nâÿæ›m&õäE÷z=‹-n{Ðó˜d³¼ù¦÷8œ…°õxóMöº{7˜DöW¯ço{õzÆ5}t$^ëôóúïÞµÚ{Ip÷n2çÛz]|Qô·o„umm ÛÛÛsO¬YŒ”6cÞÉyøð!€à]Ê̵!N!ss15¥ÒøÒfY 4-I¨ñæÎ5IÈ7àܬÃÞŽ"%år°F*q'‚0 œŒp®†×点+n¹,~§È£$‰û¥¾.j : Ž¡ëÖ€C¿mn_PhGvÅ%ɸÒ©%ý‘Ò’Þ•¤|ÏábŒØ»7;Éwþe’ Iùvj¸DwïzÛЃuÚANµÎüØ,ŸmCl[ãüÈ;æˆ+Ý~ü (kµêŸúKvÛOˆÿ»5 §õӌؤÐÑû/êžC)ÎQJ¢}ÖR©„Ý0mœ P(`gg•J•J€È¥7ÿ2tªº‚jQ…SŽm¨›ð"ësªÍœ¸QBîIJ¾g5!ý¾Ð2’äXXO˜Üj̬:õ‘ÉIɸæVP=kY胮 C†n¢’ä“0qä˜îZRN!ŒÖåfE_.N+Ã,›¸2îØaÒcç¥ÑðŸAÙn‹]ù^/üuA‡¦¬… ©^Šbu8¨VÖ«.Ô­£ã¢Øßç ­($¢Ã šGãðÅœ–Í,Ÿ¸ò Ødœž‹(ÂêÌQÉ„W4´ß7:•7áSh½×iŒt¹ˆÑË,hëÞÞ$I­[·,Â[©T°µµ…ƒƒ\¾|ׯ__õç±P,MÃþæ‹¶S¬hƒëJ™ôbÚ‘w›Ãè4´™a²B1 ò6Ïž³Ï‚3Ï®×E$1Î&ަ‰÷™Þb°±a´íï÷EµÑÏušOZ¯§¯‰QÚÖ“w,Ù$8á]çÚU&›(Šb8¬º ÐÛÙøH³³I#`¼äœRãi´K’Y¤ÿ8"š^|#¬§§§Çx饗<Ÿ÷ÒK/áÊ•+ØÚÚŠ½#“(qêW;‘UnD䌙±c¼jî¦g†¢;l2Y#LS]7ÃÍM£|§#n´kžÄu`Ïbh6…Ó ©¿t‰r#3Æ Kö O5eËP'Ò¤ s†Y&³ Çi# õî÷Yt0•KÉ"0_I_UM?¾ëp8tL ¨Õj–ô`züüü<«¢(íó_Eëõ—qV5 €€ùï ³LTU5R‚§¡"7Øu0Y&HSÀjpôzbþìl9ƒhC¨\æHUÖº©€˜êй”ƒÉ2–^Óæ’­¹ 9pÛp7C·ÞÀ¹˜ø¦ …Ùü%3¡Û[/šû¤½þTâíáß`ѹ—&¥”ËeK_ø¨M†&­Xv ŽBN£WÌT«Ë¯ùKh,,sA˜ó³)¸ï“ª4 Þ¥¡uöåT\Æ_‡µR©`<ãÔgÊ+={hv¨o­¡xémá_(ƒ-1éÇÒ±í “u,ÑUUK#P”dG0Ì2ùàÓOÏ p§#Da²Ž¦ibSÆ4W¯Õ²>G’¸l‚ F ‡µR© Ûíb<;>g<£Ûí¢V«¥"êJ»òº¨?¸®fI‡Ñ˜aRʬ†uº3wÔ0ä K:™øÃœg*IœòÎd]×QøÂædšR$&ëèº."¬&‡•7c˜¨ksíÚ5ìììàêÕ«ØÚÚ²8¥·o߯ñññìyià÷~ï4mšÍ´ps&åXÆ6Á2݆arÃ,ÂJ©Á¦¦4Ô©—a²ˆ¦ixÎÖu00Æv0LÖ™•tLgy) 7d¢Èa­T*¸qãÑívçßÚÚÂööv*š-À¥KßÀOüÄçqxáʨƒS™L`Ž>™z/1L.PÍ[ñ¶è*Íãc˜¬¢;ä²;$0Lf™m8š¢«œ=ÀD%à ˆ.À×®]Ãîî.†Ãáìï•J%uu«ðÔS£p/Ð!,±³Êdް2yC×õYó<¨êÌèÑuñ+§3YF· ÇÖuá°²\3y@uÈýå¬&¾5¬v …jµÚì'Îj¹\†Mn÷C°1ʆa2€¢("Ì45z\ð1Lf±ô¦Ð¥M2L–±k2•ù1Læ™Õ¯šPUÖÝLtB;¬Y \.CªVÉí^èu«=œªÀd„Éd",œiX•‡^3yCÓ4±ñ¨i–<²~Ÿçð1ÙFUUkC1cžåšÉ š¦á‰¯~Õ²©Î0qȥà À2ŸÒ“D0ïú0YÃtà]K&oXf°N‡ô©ªØ£á:(&Ë躎ÇbÓqJ¯ÇrÍäMÓÐøêWgóöÊååÏÆfòE¾V¿¢>šAÏ‹™¬aŠ:iÏ`eòÇ,U.Ïvd…Ó&™ì£iÖþüÏg6 GŸ˜¼¡ë:žøüçy7IŒü:¬~E}€>D*0Ãd “|<یɺ®Ï¥L"ÐÊi“LÖÑ4 ?øïÌŒùÍÍU¯ˆa’åËôG¢ÇÍT³Œ3qɯÃêWÝ­B8«ÜY•É"¦ ‚j•£NL¾PUu®aG– “ ÷ï°4Àf˜Ü°vçŽ%3†›B2q <Ö&wð ‚É2¦~œqÃ\67£#®óc²ÏøÕWñWï{aȳ1ÏäÇ› ¶$±ÂÄ'ŸV¯éĵ« “UL2Îõ«LÞPEŒýhµU…¦ ƒ‡U&\úÆ7ð=Ï=]çúU&躎€6×~3)"®|+ŠhÌ3)™´[‡+ :ßü—Ül‰I%qä[Q„L³\3i%®þn·¹;0“,©­aÝÛÛC©T‚ªªxõÕW1ÑívÿÑ>¸É“:âÊw§#v.&­Ä’q]‡ú¨åsoãfKL*‰#ßý>o62é&Ž|S*0—q0I’J‡u4áôôÛÛÛ€B¡€­­-œœœ¬zi ›$äûä„wç™ô[Æ-}ŸU&•Ä•oYæÈ“^âÊw±(lNf’$•ëùù9 R©ÌþV©T0V½´…p||»êŠB¡€'Ÿ|O>ù䪗šo}ë[¸|ùòª—Šû÷ïãÒ¥Kxì±ÇVrü(ò øÀðÞ÷¾7“²’E9„¬Ü¿?“:å]ïz×ÊŽÏ:<;dñÚ|ê©§pïÞ=¼óï\Éñ£È7ëïå“uýýÔSO­äø¬¿³C¯M²ÁÃêïT:¬æ4;n­µ×××±¾¾¾ê¥G¢V«­z rí«"Š|À'?ùÉU/=2,'ËeÕç›uxvÈâÚW½æ(òÍú› ʪÏ7ëïì嵇%•5¬kkk¬i £Ñ(Ò¬J†I,ßLÞagò Ë7“gX¾™4’J‡µT*¡V«YŠåEÁæææª—Æ0±aùfòË8“gX¾™<Ãòͤ‘Ç&“ÉdÕ‹pb8bgg¥RiVä}ppàZßÇ0Y‚å›É;,ãLžaùfò Ë7“6Rë°¢ð›ZM_¤<=ç[y=î÷Ú$?C’ë^æÚ™Å²HùòxRŸ!éµ±|ç‡82žWù^ÖÚ™ÅÂú›å;ï°þ^Ýڗ„‰Ío¼1yþùç'ëëë“õõõÉóÏ??yã7fŸŸŸO>þñÏùå—-¯÷zÜïµIòÊ+¯L^|ñÅDÖ½ìµ3‹c‘òäñ¤°Ëwܵ±|ç‡82žWù^æÚ™ÅÁú{õkg ëï‹!ßaM€Ôj5¨ªŠW_}µZ ²,ÏßÛÛC©Tš=>Ñív=î÷Ú¤8==Åáá¡åoq̵ֽ3‹e‘òäñ$p’ï¸kcùÎqd<¯ò½¬µ3‹…õ7ËwÞaý}Aä{ÕsÖyíµ×&ëëë“Ìþv~~>Y__Ÿ¼ñÆ–ÿŸþô§'Ï?ÿüÜsíû½6)KÔµ-ãÚd–C÷“ƒ¬Ê7ëð|Àú{ukg–ëïÕ¬}°ÃšãñÝnW®\A­Võk×fwãáÇžß¿ßóµqF8<<œ­Õþy¢®;ÈãL¶X„|/ZN¼ä;îÚ}m2Ë'ŠŒûÉAVå›ux¾`ý½Üµ3ˇõ÷òÖ¾*ØaM€ápˆ ‡Cܸqò[bÇÛ)•Jž{ j.•J±×}||ŒB¡EQÐív1q~~Žn·‹ïÿþï¼î 3ÙaQò½h9ñ’ïÑh”êk“Y.QeÜO²*߬Ãóëïå¯Y.¬¿—»öUÁkȲ<Ë£· 奛Ãó£Ñh&0^û½6.—/_v½`ßýîwG^wÇ™ì°(ùòx¼ä;îÚX¾óETÏ«|/zíÌò`ýÍòwX/wí«‚Ö˜(Š‚ÑhI’pzzjùÄNF­VÃññ±å5›››¾û½6.µZ »»»³ŸJ¥‚µµ5ìîî¢Z­F^wÇ™l°Hùòx¼ä»T*¥úÚd–GÏ«|/zíÌr`ýÍòwX_ù~l2™LV½ˆ,Óívç'€ªªŒt…R©„ñxŒB¡`éjæõ¸ßk“þ,Ãá±×äq&ý,Z¾ƒ<žäg1Ëwܵ±|烸2žWù^æÚ™ÅÀú;kgëïÕ¯}Y°Ãº$Æã1†Ã!ç¼y¯Çý^›Öu¯zíÌòȲœdõÚd–K9Ȫ|¯zíÌrȲŒdyíÌò`ý}ùf‡•a†a†a†I%\ÃÊ0 Ã0 Ã0 ävX†a†a†a˜TÂ+Ã0 Ã0 Ã0 “JØae†a†a†aR ;¬ Ã0 Ã0 Ã0L*a‡•a†a†a†I%ì°2‰rzzŠñx¼êe0ÌÂ`gò Ë7“gX¾™<“gùf‡•I”Ùb†É#,ãLžaùfò Ë7“gò,ßì°2 Ã0 Ã0 Ã0©„Ö%B¡úÑh„ããc(Š2{l8âððpa;#tìñx EQ (ÊRÒF£Q®S+«’ñUÉ7À2~‘`ÎäÖßLžaýmÞºê\$vvv°µµEQP©TpzzŠZ­†R©„ÓÓS t»]loocww7ñcïîîâúõë¨T*³‹òÆ(•J ù¼Ãá;;;$ µZmáç—Y=«’ñUÈ7À2~Ñ`ÎäÖßLžaým8ºdNOOqóæM`ww§§§€[·náÆ$ia;<ׯ_ÇÁÁpóæM¼ãïÀñññBŽe¾P®]»¶°óɤUÉø2å`¿¨°gò ëo&ϰþÎ.a]2›››( €J¥$iöøÚÚšçÅB© nlmm¹îÖlmmÍŽY(°¶¶¶ã ‡C\¿~—/_ÎÍ…Â'ŽŒgA¾–ñ‹Ìªä›gÎ,ÖßLža<»p„•Iœn·‹w¼ã¸}ûv.òæÆË8“gX¾™<ÃòÍ䙼Ê7GX3F©TJ<·>éãlmmawwýèGÑívsµÃÃ,–,È7À2ÎDcYò÷X,ßLX3y' 2žWùf‡5c ‡Ct»]×Çwwwg)«:Ž$I( ¸vídYÎMÁ7³x² ßË8eÉwÜc±|3Q`ýÍä,Èx^å›ÖŒQ*•ð /x>ž–ãÐE²··‡[·n-ÿd1™#Kò °Œ3áX–|'u,–o& ¬¿™¼“%Ï›|³Ãš1 …ÂRvJ’:εk×påÊt»Ý¥¥Â1Ù%kò °Œ3ÁY–|'y,–o&(¬¿™¼“5Ï“|?6™L&«^Ã0 Ã0 Ã0 ÃØá.Á Ã0 Ã0 Ã0L*a‡•a†a†a†I%ì°2 Ã0 Ã0 Ã0©„V†a†a†a&•°ÃÊ0 Ã0 Ã0 ävX†a†a†a˜TÂ+Ã0 Ã0 Ã0 “Jþ?wcÒóù#ól%tEXtdate:create2019-03-28T17:36:48-05:00òÉ6ô%tEXtdate:modify2019-03-28T17:36:48-05:00ƒ”ŽH-tEXticc:copyrightCopyright Artifex Software 2011ºÅ´1tEXticc:descriptionArtifex Software sRGB ICC Profile †2tEXticc:manufacturerArtifex Software sRGB ICC Profile\~=Ÿ+tEXticc:modelArtifex Software sRGB ICC Profile1(‚¡!tEXtpdf:HiResBoundingBox1080x792+0+0_Ýx+tEXtpdf:VersionPDF-1.4 G:xIEND®B`‚blis-0.9.0/docs/graphs/large/l3_perf_zen_jc2ic8jr4_nt64.pdf000066400000000000000000001057641422157504600233400ustar00rootroot00000000000000%PDF-1.4 %ª«¬­ 1 0 obj << /Producer (Apache FOP Version 2.3.0-SNAPSHOT: PDFDocumentGraphics2D) /CreationDate (D:20190328152855-05'00') >> endobj 2 0 obj << /Length 3 0 R /Filter /FlateDecode >> stream xœÌ½KÏ%É‘%¶¯_‘KÍ¢.Ãßî -¦!¡ÝÐb0+›-õT·¦Ø€0úõ:Ç,"ÜÌýV%¿,ƲѨ¼éá0?nnÇÿã»ðåÀÿ}Ïÿ´¿üá‡ïŽWˆEþvþ ý?¾«¯0ð±uù;þ,=—ö%äü%UyÿÃw!å?üwýC8BÀŸù6ýÓwÿçwÿ‚Þÿ„ß¿‘¿›ÿøÇ?~ùÇïþ¿¬Ç¿ÞB+_b*ÊQþôßåO­r&h”?üÓwñ‹±|‡ö§ïþËÅ?úoßÅ/ÿýýßhª¹ô”¾ü¿ß…ãËzÛ÷ïêÓøaNì‰^bj¯¯Í_é•Òq¡§‡:ÆÛ_w¿÷Ç»½f(+{ÿÀ꣇öìlõ{žÞ:ýկ×P_ÜÛ¿ÿG Aßÿ§ŸJ ?jΡãÑû«§–zÌ‚÷û ßÇð*xàËïøò_þ®ñ¿ûò_¿üþ?~÷~/Óýj_ñ8âkÄTs å#}Õ­¯§öã½ñù‚çfx?ÚÙÔ) Ï DèuÄ)[Ï®íÁ!”ö:Jï1Ö´ Á¶=8„Ð_zIéÍ*ضñ~¼úÍ%Öu¶éy ?^)¢ßZž=v¸ˆžëùDO†àEÏáyÑ“!xÑóCx^ôќ蹼½¯ŸMa ›1rl­<">%ϋ޶ãJàyV|ôPòÄr¼JíG ãÍ™¯NÂ/ëå8¸1¦#§Ÿé%þ¢^Z…vPpÖÖ~¦“ô‹:Á÷|áXo1Œñ3d׉()ý-À+)߯CþÛ—ïg‡f$ö_„#¯Üs Ì@Ü+—TRŠû’Vü§èH~óëßþý?üîWø×ÿ¸ ÉêM?»-W=ˆªq|Égh­Ö²/A¢ó}Ö¾ÿü§?þðÃÇõ¿ŸÄþÅcª)‹Œÿö2^µ¡)Öþ%Æöj¹`[ŽÌ›N/ØUXÑŒ%ÅW|¥ž–¡H^IÝë¨mØÎ¸lµ6:ÛÞ9Ø %åÕ¡pC‰ŒÒ†wr(Øþ_(-¥ŽÞ¤/ìì¬w¬âñj˜y ‰Å#¼‚}ñ…“iµP)Ò†¼°•Š6üè­ô’‹´áHB_Ò˜K‰CâðÊŒW^?oË1kwo9ï ¡¦×H­¡¿,mÎpÛ2‡>±xPL‡’K¶ÚÑYÏÒ_„*}.W(K$‰²\ºnæP"¾k(á…‹É2;Iãçé‚ñŽˆã¶á'‡R°²!÷W ¸ö¦¤mx'?OÅF _¼„†o-SÈáÅÙa:qBŽ S`÷’¥ÖdD™Aæ¶dw-IS]½HwuçjXÀ€qqù¯äPR­ÚÐO¼Q°­S•O@Qæ\ñ²KZ1£WÂ:´KpŠk8Ú+H!VHÚð2¬GÇd€Öõ•q̤*âÞ‰OÓÚV >±œ8Bs Ÿ‹¯ôÅø“´áü6(´áÛÔ– *ò¶N¿%rmPc®2lxKl<(Úý*â…­Sn‰ …ž ÷4š°súµú˜]®o|i¹*8çðT…PÈ·JöNi÷ž Ù“Z9JìK|D ¢¶ö* oÆa+müåhMúlŒe {çÚß|%À“•ÅLØ;ãX´áÚ&b(mxå-°!¾BÁeY0|tÈè%°"3pœÊþÀÇ . RÚ0sˆ²¬JÂÞ‰òJ|ç¬Á¿‰bÈ6¼cÁc<< /ø=w6:8àXÞYZkG‘ ’ ˆé–X̵ã8¬G‘±`óÔ[bÑÖ€!¶|šä¯BÍ8£?¤µ)ôÿç²ÌuÂv\`û-j7l9LeEmL3âÀmM¾€G혰½±àãÈ;js‹,@ØQ_nP^Ye‡Ú„NºÎiîˆ[|jÐF·n9†Á#¥¸ñ±‰–Üyn".Ð ¥Èf›HM<‚½âvÄÆÂT0ƒ²â6ßQBõÐÍjq€BÕh`…Ò‚ÛlÂêÄŽÁ¬¸Íc×@5aÁm.f‹=qEmªÄ‘;VÔŽGæ9]°7ûŠÚJb9ZÈ!ì¨Ý1ÊU‹»Â6G (1¤²®ÈMýÈùaCn(7X¾N¡X‘ ñ¬÷Må–ëD:a¹7è>äª( ›ÊÝÎêwÐÿâˆ+t¨‰ÐÌüNåΣ*rFzè>°ÒØ i„º©Üø\C४ƒ¼±b¸[½GÝTn dkwðˆB;ÃGW´òà-Uœhª:»Co8a Æì:7>C®9•R¦Î=¨AbU‡ñàÝ îA$Ñ{ÚÑ;w«ê½;%¨ÀE¯Nå.Ø LÐOêTîÁ´çT7ôÆçNPz¢ž#¼ñé¡2ˆ8oàÝ©jàĪŠÂ¼+ƒv‚°Ån D‡¾û®q£ëi‰C¯ˆ»K…zŒµ;ä ôØÍ½‰‘@u vca1¹Œ«+vS¡ÈV½_yìæqÐSãp6ì.bÍÃg}Ãn Ê6ÐM¦ç±»q(PQô²á±›ß(6òر›²$ιoØwoI1Ý[ò…±• »I]aœMnKjB@(l‡¬Æ_n£ü…ЙÐ9¨¹±¿´›!šàb(©ÄÜ ßJpÇÂ(©” ¸5¢„.v•m? Ü© %±)d¬ÀðB›7àær ‡IÝTnœÖØÈøæan| Ú ƒ¢‰×¹Ð‡üyéö:w¤Né´‡XàŽ´Öa›CÙÝtnî䆅Ým%œ]2ÞèÜPÇšÎÜkÝ™ GdzÜøp—žYNëæmc@»c½Ãm=\gòaÃm,C‚Y’ÞñÒ•†ä‘¨œÒ¡àJO¤Gä©t ¯u-nSº ®èÐf+‘+ÎTˆB\›ƒ(ÐìpMí&Œ0è%ÄiÝ<ÂiïÀ†]q[æE;UÓ ƒnï +ƒSµ­À-¼ˆGNpã⌦9.È-WRœoøÚrs(Kˆó}¬È-³‹È&¦*‡Ü2”4Ðu³•ðhÁS#/ÈÍ¡p‹ãþµiÝ”ó­KmCnŒ«7¨t]¤Ë!·Lƒ wY‘[àÕ¢c›r^i}niSº)”_cCm¾/Ws+js©&šWÐæja!+öú…ÚÒ=Ö2%YÀ(Üê…CBJ CÚÍ”'äŸÔ–4õÂy×÷#ÔØ8½6î‰=Ñ 4^8ó×ãî0%/œûÇãÝ^3”•½<î…sNP¿gü /œ¿Ä`ÀiR{Øï›3¿xFàŽö!Ÿ§ýnæ¼·ú#߬F³ÑŸsï1³©8¯3æQ`YlÏŸáü06¿?„Op~›ßÂ'8?ŒÕïÆày¿+ᇠohÇxPôØá"z®çO=‚=?„çEO†àEÏáyÑDs¢çFðM~7¸¡Dhè¼sÔÇün|'OùÝø^žò»q½<åwã:ù&¿›¯¸µ$¡d{¸ð•¯¸µÖ­åÏÿó9·–4‚w–Í–•vïœ1K™9Í ·Ù’vhÚiòA[Æ;­ÙO¥Út(Ù{¶ä€ë°Þ‹s¶fö ±LXÖ &ê\¬gKI¼xg2 Òæ<[*nÐ #– HÀ+ßfKLwp2þlèÛm¶Ìr«ÅÖ"7Ór›-1W #>¶ø åÚÉœfË|¼ŽAc´Ør[\[* “jÒ¶˜Ù ¶DÈb£ËM][ ´é¨Øðò@w®-xR‡;¹HW·®-x.@ÊP‰í‹k ®Ôô4“Åε%¿úÀ¼‚\Ãóp®-¸½·v™‡òp®-‡˜ø0g.V9œk ÎëBØÅ>_khÙB±Ü•ÃÚkè.@Å=Fž ÆÒÈâàËE12”à|[|Ä(6ÒBú¿ß‡&6rÍX9· !A\í‚xÒ´ŒíÚ…Ò,ÑZÚiíÀ6¦5ZÚðNeÑwеyˆ}¨$kj'œI\$ ½—0–8’ø½ðø¬‡^JZ|[®|ÜLl£$b(ä&mX•š8;•ì|[ðe6P»LÉη%³ Û_X*Hõkp'cÓ¨OLÇÈRÒ6çÛBó>˜ÎK!ˇ™§Å…lÍÈ"œ¢±þ.”˜ŸrmÙ»]þb+r“m!ªï‡îˆÇÈ)Å ¶±Œuà»`7l°M÷ŽJ/ݶiÞÂ<±äbûu°MHN Y~Ûc¼èšƒ¯šVÜ&_Ö;EO4zÇ–‘E0âŠÛbœ/8ÔÀá6íjR¢ÞX·Õo ”†Ûb£†¤÷žØÇ–^èWØ–3‡R:?AqFv®N»s¡‹3²‹ÖRN÷5Û\Œˆä}^a›<Äy?ËÛˆI“ªc±°Íqb $Òé+l“>†TÏC°-ž-˜[©A¿kS#;-Í7ûæQ»Xœ’S.mEm!G4Q6Ô·— Lz çÛÉìvœUuCíI”~Ÿ µ‡HÉ gá†ÚƒúIV¿ƒµyÅw©ml = ¡bëÐníF/9š²Ê†ÙPë‘°!l˜;ÂcãÄ ³0›Þˆ õ²ñJžÁª°A6=[OÀÚ7È”rHBí »Óµ =¤P6Èt\kx£â¤ƒl¶åȳe‡ìžy£J„ô ²ñ\Ŷ…âY7ÈÆç)Äë Þ(²ÛA| J‡yÌTÌpvâêxa6.r8…ãc6„³£»Âõ˜n¨ ­Ú ]sÆÛãUß<¼îB"À†P’ p *ôÑð¸±÷?wEKÜìuà-wnÁ!HN¸”jÜ*i«êbç€[üZ nÇcn²¸ègLÜ€Ävˆo~Ô ¸yLFE¾Wà&$ UªZ§En((ôdÆR ¹ÀÐÒqºˆ…aCn\Br [€`”eBn:¢Am>µK§nw|ƒ†Kn‡Ûây”QÙq›îÊeízx:Ü&ƒynÚ¶p¸µMMürjIGÌêåÊâ¶P}XÝÔ¦mó´MX4Œ6n¸ij¦vuìöÚ6£]*¥.nÚ¶(!oHú±‡cGq‘`ªçYÜ–=0°Ë¢\¡n“v„,G("iî(而¤ª±nub R;pË Þ"nliS¶Å!K×F +p‹$4©eCnŽ lºsrëJãS‡cCn¡;()”äÏ®Žo®w@‡Ü"æøBаêŠÜ\”#ñ¦ÑÚŠÜrñ§[wÐkM^ØQèsM½ÅpË÷áNps5ùU£ÚpŸ¯¤Ç~>[žq"©cÀ‡ R|ÒÓ²ÛúERòOÂb°ñA‚ô]ßOØ0Ïiü0'öH/ͤó×ãL%îÜ“ ½<Þí5CYÙûÇãé9AýžùÛ Rœ¡ôÅå;ü0A È¡»f¦'Û‡ÈØ§ Ò¹ï­þÈ7ëÑlôçv ™†¥ë9ó(°,,•ëùX*‚g©üžg©dž¥òCxž¥éu,•Áó©•ðO!HÙá"z®çO=‚=?„çEO†àEÏáyÑDs¢çFðM)ÔÞŒB.v¤¾“§RßËS©ëå)‚ÔuòAšqcÆ%+ÓDñ‚”Æ– ýñŸŸ"H+ !¸Óàš† bʯÄðË„)d£3³/ ÞijTwöÀk&cR‹½ ñâ¯ÑÚk¨ð๨NÖ59{ îIüz-«IÝÙ±ÁÒé®Û.ú­&ËÒÆ„õÃe‹·ÕJC¾S;ÔfÆ Ü;e˜Ùò£¸Š…Æb¨4„è½2H︩ WP‹%H[gT®„r‘­EÝÙ=òPÔ½ug?ÕñÆMTº«–å+#ƒÄŠëZ.!%¸ãæ*óZ-AJŸlæ.ÐXðÚH"–K¼³,Ì{ M–­ô‚OD­.mêÍ®–K¼2Öp$‰4ªÝÚkj¢5åž\·vö’É—Óµ[¬«7».ÅVD×}ý>ÃÒ£…1kø²š1 2°ç6\fÜîi¹â^‡lr{ÎX…¤ÑrÉ«d4è˜E•‹v;,=šók†ÎÈò7B.e6Ü!0‡>¬Á† JÒEe›5´g†tdÆ¿kÞy lHLêÁô²X@chOØ¡_qGØh ¹VÌå¢2[tÿŒu…ª£\Fã?½6ò³ñŽ¡Ë’¬©A)‰|«XüZ²¦vü8-UÅÀݲ5µ3Æ‚~Mtø–­­ "Ú`ðŸ,Y¶¶vL=2SECu+ÖÖH‰jJËþ½¡G ^72½bmíøBØ[4‹K[µ¶v¼²1v•ý0=º¡ö Õð 6Ô†~5jIÑס6¹­º ÿãQmX‚4²xìyÔ²(-¸¢v r«ÊêÁåQ;1D,eÅíH¿H¢ºxÜF>\Ììíqc†B—Ou¸&’[ã`UÛ‘¸R™(m¸ɺà$8zÙ€›g2Žý¢>v¸¹³Ëɋׅnöw‹´îÈÌP^”ôÀ6\M˜ÚdS·¥7&.Ðc¸ñ\ÂñÑ•ôÀÍ·ÆÛQ<ÛP¯ ÜtöS¯‘¸7C ùM»KŠÜ\EÈjÐ jfŸØü Cú¶÷'¬˜ç<~0S{¤:Ý\åüõ8Y9ʘéýãñn¯ÊÒÞ?çHÏ J¯×Ÿ¿…#-U‚à#­ÏñaŽ´Ô±hç`>Œ¿!ŽtîÁ{³?’[ûÚàïA3Ÿò,);\¨*×ó'PU2OUù!š_²lSæ—H:æh†1¥ÊëðÈ_1˜uö6f¦0‹%EY–Á|Œ“2mü íPö`HÔÝeÌ̃þä‘,-Û$›æeÌÌõ… = [ÆI7…I™–$gKÕ\²ƒiºð@DG%C¸åeñ°”i¤}ûVlLèÑF”B)¯¤Ü²¶5K™¶$¡FÍ(ˆ;¿±¾' D‹T¿›1Mt︢‹ p¤fSà hò²Á|ñ3s#ótâ_f‘t|÷É˜Š›FâÇÖ¦fãII´b¯i@ï(‡eLq?c,͵-[Æ”œ{ÃhÅâ=ø¥n‰$‹¹ÄBŒzXÆ4Ð2ZšFæ¼%62´§&fE—¶fJÅÕ¿Ö,†EÌËXßñ\¬­kôáÀž¸ï’\=‡ O5OZ—²š¨ U6ž ì<3kBŒlî—˜ïÅôÜ>Ë!➤®ïýëq—ˆkŽg¿í'œ">\ßWñcª‰WÓg]$³¶0CR>ê‡Ü1¯ooöæ |Åkç?¾7ÝŒäâ{ä+÷ƒ]®eî]ߟÂU—ÍSbÄgÕeó•XñluY½%ü>Á]ÂJ»$ɤõñ¨j1-/„®ïÏBÄ"„~Ÿ „2ˆEý >A伺1|“ÏD­ ÂÁ˜ü\áû¥—§|&–nžò™ðÝ<å3á{yÂg¢ING1WƯ¸Ldë0ñçç Ë‹ŬãE’hÐ|Ëx«¬g”@—x¯ vØBßÍvŠFǽá*bÓ´ÑhsÜ[|r©DŽv¼´Üt8s¡ÏJ“º[Ì`*iïÄ´b³øqÒ:ÅG³&\2©e)½ÆÆnÜ&†ÔÑ’âhÚÆ÷`]rO²8e<øZm´Ž,cGôÉá<'h,Ç'…Æ,¹º(„¸Õ½‘ÑF¯#“‘R Î×Bg!ÖyB¨ÓÏm´Þôº8²&ý“F¼–Ì{7ˆŽxV ÁºO4_'Ö6ë?/ >,ÂÒÌRé’WrÆ•×À\Ñb4 Œ;>]ãØ9Ý#è[£ó `4€,sÕFëBQÈýÓ,]t´˜b<¹ŠæÎ"mé.HÍb& L i”3Í#èë@à,/õµÉ:wšK/9fäyì‰fád]N9ÖlëÔ JBØoGŠŒÎò8t$ÅyRŒ—†¥ž}¼öd‰"§Ö–âOr ²„´×†¥=T7ƒ*ðëÐ¥©Æ‚Ž¬Û²~)ÚMoIN,ê ±Ñ°èÀÏêBÐk/^ÝÚè<*耣õȂ仿%9JÒFì´¤Ó¤õô–ä( Û+ÀG¿FwNä@ãJušÝzU0&ž;š[/hØK’™à¿l`]¼aý*˜@‘ù„OaÖ±BÜ?_%‘W´›Je5•d)=Ø ¡kcf–ÈS’yIczÝèd#¦k=ÀÓÌŠkU8àé[1¨ƒ‡Æ 1Àß’Ì.ëÁP$µÐ‚¾%™±AèŸJN€1qþ‡Ô˜V¢ß`È0èYöæ±.)˜'<É5GåŠó sÏ|ûŽó¬cŸkêõ„d‡óô²H#žœÂôlŒ´þ â€^bœðŠ&]õ@/Nø½ŸqCèéùÀ§°uú(1p±ÊËô’õ;°JÅyÖY 'K@¦ï Wô@/%ûXC÷‚ˆÃ±vÄ‹,zÒå‰ÎEZÞ!½µ<?-Œ éÕ=7zÛ^¨Í½#½x:6@a yƒzÉnÞ™£ùÜËꙦÜÌ’‡zy-£õÎ ë ^˜K Z±O¨¯‹!Ž ê£¦©À@O<²P/œ ðfäÔfo1õ¼!½3šœûŽôÛ[-ÒóI&žÅ†ÎÒ“ ¢§gç`«çñX”™\7¤‚ ÿ RÔ7¤§pdœÖ=ŸÇRsTÙ.,Ïñé…qì*ÄØ^ê`Væ.iCzaÊèYÎÑvç‰Á2«G%†lH/y÷Z½á}1PŽ êe@ó/»B½Ô×=Ä£$mP/±¤¤žLëÙ' +gõ(óXÏFàÀ!— ë%+/.ƒ±œGˆÅzÉSÝŠE7ÖæýOÇYäôÉ*ÈÞc›·ƒ5`w¼g“8Nªïg p‰êâ¶à=ö5=ÇZy‹÷ «Žê]µ¢}£—õzÊ´§Û+êqG{ì‚”Rkzž/hÉŸþc;ØCI¨i(®x°ç1‘´Ôð°,.tôÒã°g#ˆë¥^¢vq4Åôé釭siIéñNì+(;ç®sHO9`D~ƒó$@©˜êq¶à¼@ ù=Î7ÜrqŽfÅyh™kÞUz9ÎÎM¶ã<=1pLötì*½Y-¤®©6nœoL¾\Z}‹ó•7(|‰üæééS˜™»l0/é@ðW)œ£Üp>bÝFMopžH…˰֣yƒóA€â Ì'*L0v˜ot×ýT˜¼`ÄVO‰r0/Ã!ozŽÕÃ<Ý>XåùT<ÌW| f¿ºÜÁ>iûñ9ŽéÌð²§[~"ÌZ¥DÊ1«bˆVýÓCTï›Þ±®žóøÁÌí‰~bÒäØ:§ù«ˆ÷ü¨Ô =$?ö¹–×Ç»½f¨k;õY²ôÑùžßôúñ¦Û¯b¹ŒQ¨@=\P#½Á‚ñXmZðÂëeªrÿ@_Óº÷>œ;þ‘Ïvîò§÷¡OÌÿ³“¥’ENGP×׳m{n‰…Mj¯)i‚k{pL¶Ï¬:ж!ض‡<€–GÊM\ÛóB~L~Nø¤C/|¾çç…CX„Ï á„O†à…Ïáyá“!xáóCx'|_?¡Ä³ºG&áûP föTû_‘ÃõÐ×QÝâ‚ÿÓ”_ÔIêuöpNUžØ÷"Å[/Ü?Ç߆_4M/V¬ÃEf_¯Ÿâ¢Å÷à=о?lÁ›Xûò½aŒçPì¿£1¿PÅúŠX¸@åÑvV¼â?E‡ò›_ÿöïÿáw¿úÿþøÇmLÖ+îg× e&:âϰø"©ZSçÙ¦1ÿoúãsaùä)ï²s¸»1ÏzÃ}NŽ‚nò*fÆ*Gú««å°k^E’F_X¥­G B‘ë]gNàCÓ%f2^?ÔLÃ<ã¬En8Ó,ɨWõ¡yqo_p•S5%^ÚL^ÅÄÜGfØÁI"Ö®:^‰7èÖ.à’L¥WÐEb²Aõµ®m³î\jòÇÑÄ„)q4R±Fsˆ4\*q$tiÓÄŠâÊWÆžŽ®Æ-¹"‡[‡h,G­Ë‰¶(±¬5ðÎ!ízgœuçp?}QÃnMŒb®»b.R%W{Œë±dêÎñ¹Æ©kFS|i„J6}Lµ˜4³âQ1[¬2“æ]§MÌALPcrø%«f¡œ"ËãÝK†k9«ý:fM­8 öRb–ót¢±˜ÔЉû Ñì¤ýSz.I .øš6¦V„`½2“E'a¯c5¥çR¦5m~›jR+&É ©°e€Õ”žKmì’d“mͤVĤ^ô_*j΋ͤVDO/†EÍœ›)=Ç6Ú’Î+v“Z1IÌPÏ]ÓÆÆnJϱ¿Pqìiaì&»"IæåOX9ynÌÒs<¢™‹ýú6Ã$WL‰©÷™r]l*¼ì•fŽv,x9wVNLNräú‡RjB¯¥Ã$WäsX‹kê‰Ñ™—Èl-¦24“[1 pÌÇh³¹E–2 ÄéZ54“\118kîÈÄyW±ÄÄ,ç$£Ôlš¢I®˜p¯½ëÑ$WLL{¤ë«§$e̵X"ß9éj‰ñé¾E6±Ji¿€Š«[o‘%øÑ%lÕ«˜(—ù0û‡4È2Ǻ³È‰@Û Ýø¨äuÎ=â¡;3f óÐôº#J;nÛ‘›Q¡í=rç8˜ #ž8ä›m¤öÏç;KöÑto‹ÜY+e\f‘›å(>À†Ü¬2{`ÞJƒCn¶ÙÃß"w–̼äó·È-•kçÆ!·¼“U©5fÜ!7«è6àîÕŸEîÒó9ƒÜ 0òV6 rg2PdÎÃÇ"7—¥åJrs˜E¸[Ù¬¹©K‘µ9• ‡Ü&=mÎ¥¶È…׿\‡Üù` ä-é¹óÁÄñ-Ÿâì‘{´×!u„(ôÈùt3L‹Ü¬sŒ×¥s5rgÚ9Õ³ÝäWÅØYdólè^ÇÔ=z+ÂzÐî?­o g|Ë–Gm*RL®ØåQ;Ó¿4Ôwú6±Êã™:Àƒ¶hî«é£éÜtjË«^£¿pÕc5‰pœjÕnÕÜL&§ÔÕ‡QÖ,T)¦æ±(ÙŒ“ŸÓuPÍüëmîxÕGVæ[ÿsPÍ !@›’-c1z£S²;Þ©®<¦#ÿþ$'W˜fL~-·¾ììNfx5 ÓÄn¨ê×Qèl:ì2Íyq0Íìðéþö¥]T®=éõk:à³^ÈïPkq´pMN¿k_A½~-Àó{z”ÎLƒpMN¿–Ì2VýšC‰íŽèXP'vÈJ¨®ú5k(Hù”\6”¦g@×¼~=˜Hý¸Nz§_7§«l(ml¯_÷8ý”æPÒTÓ6”>¨­èÄë×tBfõ*½˜/(Ý"ŸÎ3Ï£t—dZ×…Þë׬¦n¶qGéÀ0ŒÈ»Ì…Ò¸ãç RûIo‡ÒؘåZ•¥Y5+Þò·èØ‘ Ãy©òpMEz^̸&1_/õÎÃ5o\ó–³Àu`U@tÛÑšw¸{1¸æ!î­`q›#1 ‹Ãmªító<•ÂUÇŽI½ŽÍ ÝÑY€;¾XÁãB§cw{Ny›©ÄÈ÷Ÿ*žnL!bÀç%ÛëØœÏœž×±€L$3ïÀ]_ÝÜJœŽÍëdÕ+øÞôVoS¥tàèr4mT^Çf¥£:ë_V§™ÜëØtíiaêѼ;7çy»óàűj»W±Ëë¬/V6ðNuÓ¬y3Öi$rš5ÝÎÓ-óy‹¿4¢U³¦ÃˆQGf“TŸ·,‡Ù‰‰´æª;Íš ÆÜ¢³¹Ç{›H½ûvšµäŒº5ÙŽ3·Û®Y'š`nDð˜ÍzÙÓç0›ïdj7fŠß4k:—N…ƒl~„0.+žƒl¾2N‹¢W¬¥ÖmÜô%È'_ÇNVà¡¿÷ .ö¼¡?”Ò„<9•䟔o©=oÞõþ%6./9·'úÁƒÆófþzܦDãysÿx¼Ûk†º¶ó×ãž7çÏoç ÷!“¦a+¦ö°ç “½½xLÐ:ó·äy3÷áÜñ|¶Í~ÐÃÇ̧N¡x`Vç×ó'8?ŒÍóÆ á3œÆæyã‡ð Îcó¼ñCxÞóÆ ¹©ÌþœðI‡^ø|ÏÏ ‡°ŸÂ'Ÿ Á ŸÂóÂ'CðÂç‡ðMž7¸ªD¦ïc\Àcž7¾“‡{@ “x^Ã_K 7‘Á+ÝôkI–¡ÊÉ ¥3‰aæyÏ=n#&³ L«›X]n'­í™æ¦;¸ »ÝšRh2³~-@—ëòJ¢Â™Ü{¼Í¾ä<¦_Kq^¦_ ÔÔ•YÖô¶a–$%O¯[MÁP૵™äj †&f`˜n¹JþÊÓ†YhöM§e-7ëÕRhjíw“sjaYàÙ$>-âóqS·¹[“{©´"ÜbЭO s,x²¹;—í^‹áJ´…8¬þ)—–µ3vÔMŠ.¨=ð‰ËDf‹Ú9YW+ÚÚ®OàP›†7ÌøZf‡Újy¥¹Z>Cm¡§Í¡6­Îør§ãP›? vÐæ¹cØ%Ú|c˜a´i4àÜàkA[ÜV¦)Þ¶˜Û§{“í,‰LâåËä@[}n›žmŽYJ*Àl­íŒï›;Ù¶z­Üœ›m’džzu -Î$½\d–my®Ü.NµÉñöñ¼Â6‰5ÈÓ8Ý·Åö<˜n³ zŸ‹·IÖvïEܴζ4o‘›RØ“$t‹+r烹믬ý¸Ù”§sn®6(k››¬¤c¶9³{µÇ¾n6NÜ´ƒèàÆ{ÜÜ·†buÀͽ§–îáìà¸épÜòí-ê€[ú3l€›È8í9àf›=²,pSJB9.%Ê·He ýuG•VNiúñnÓ•'ó•Åù³Dë“ãqj§á¹åº‘Ç©s=È”.ÐÍu†rX|§p÷ry.ÈMåñvóðÈMÂ.÷[!uÈ-ëílà‘›¬ÙŹÅKöö{X›ŽSvÈšåLzäf‹[™Z›Þb÷'÷ÈMFúæþvä¦Ò§R´ wÁ(o7ÝÌ7nòÕC7ãYS½ÕtÝx§ñÄöМ'އîDô»½·[f¿?¸Í|ê,Ðþ,À,Œ•ïùyÆŠCX+7„O`¬dž±òCxž±’!xÆÊáyºÔ ù§Ð¥Ò¡>ßóóÂÇ!,Âç†ð Â'CðÂç‡ð¼ðɼðù!|]š†Ôc–kÞct©ïä!ºÔwò]ê{yˆ.uZt†Ý;v„[` öž9--Y”wc½,‘-Y”9h')Ú²%L1ƒÉ*´lÍî¥Y:7×&ó¼UV,_Z" ÷^$F+†/-Œº¿#›Z±|)ÛòÍC¶jùÒBcQ¼xÖV-_J*¾ÎîªåK ÏϨ¯l–.ͬtɰ¢‡-dèRŸ ÓiÍšÝsuÏQ[ âLºð)ºtÁí:SM‡|·™u5Å36ÀÃ6k²—¶™˜B³6{È&ßÞî8pÙ,¤WoöÕA6ív3RÅA6_i¼5d/iifKD„‡Ùl›Ñ¦³%äg’˳Ųl€Òb6mÿFfó9‰g1["jŽ;pÃa¶ÐÓ–ê0›–Ï:c fÓv;f0ˆÃl‰Î€\œVQ‡ÙìkrÅÈ8Ì–@¯É%9Ìæs±ßƒŠÙUï˜W‡Ùl«ýŽïq˜ÍØQ#&³eÒÇ­î;Ìf›1Û:Ì& \ÒKç0[XÉÛ:Ì–q¼ø:[ fóþã„®è¸ÒnÞh3ð²Ns¯maþËíúã@›\µa!h“4;Õ£v£ŸÁ½#jg‰JškQ[xâÉÓ[ÔæcÙ>¶Dÿ›dµS`ÝrÚP¾¢9UëWZ›fÇ–òzg"p°MÍ̈¥‡mŽe: Émÿ|L^æA¶tCî~%RÚ¨>n׌¹™´þr Y;^aã jC™hñ <óÈM´wÆÜÌÛÍàÐSýµÈé½pÇõzä–R@SûuÈY™;½S¶I—™@Â7“,q è®óÀM‹ñE;¯À™ùûæˆ=pó,›~`¸Å›Èh͸¹ËÂâé›LìŒ÷÷Àe˜¾1·IMúØãvv±†·³ã‹jÒ•?*—Áö'ùÒ·ý?aɼ&òƒÝ#jÓùëqêr”1ÓûÇãÝ^3ÔÅ¿gLÏ)j¿÷oaLK•`ùÈ’§ñaÆ´=2r€É‚;Œé܉sÏ?SEùÜçÏïD3£òœi?=a må{~ž¶âÚÊ áh+‚§­üž§­dž¶òCxž35b>XÛõyÒT{ôâç»þ„ÚÃ"n ŸQ\@ÆàÐ᪠ȼú1|qJ“ù”JÊ÷sºôòuºôòwºtóyê{y„=-@.1zòæû5ö´Û`Óûñ¹`ÓθÇŸ^‘€\&Ñü)“íÜ·çž³åOYâüæA{n–?6{Ng åOÓ4ÙvÒ>“? ÖZÚ‹)çǶp'nìõpô©¹µu–¼/ÈÌÑ™ïTÜ|“>ehëL/ÙÛaùS?sV¼Ù(¦sŸÙœ»Dº^‡T'w{X÷n ù¥6ljÜÞM%?áHÕÖYopš›^µYá«i2}dŸ?hu‘Ûµo£&éÇp“iƒIío£fÖ¨IEwr§•þ踫Í`Ír§Ãr®ƒo.Jnæw®*z,îtX*t°öœ0zqFÄ Ú‘'wY2ùZûÁè²kZ_y¦±yîÔ¤ÒÉ”î“`ÞÖ+^"ƒ`¨áäN™×Ë<×,wš,m?òa£M«$œ>ßGΆ;UkáÉyš*'yÊh‚z™áF9êaÈSšÒm¹ÕTìc[Éã2bj ö‘0œ›q°¸à-±´rÍÐËÑfµ>]”Û AÓ ïmšƒen‰+×ü¬+xK,aÈHl7•úŸk"éÆ8,{§›mÙ³§ašï‹ NöÔÅÑ«ÎÀ€é€ú}ºÀvž„lãÐ)wòá¶»ZÛ2ï[RÒS–25?'/PèeznŸÅšÞ“ݘx³°Ýo´åª•ÃK£5ò0’uÆÜ„cXNuøÊ€n…L(¦€À^“ @c“”bªC0µ¡)ßK«öjsB¡1û¸T“ mÆ511°©Ò }Þ°«h3{h³ô*Vò°]†&‰Å*¦¤é†M=Ù@›Š®º¾Ö¾ Ñ2¬ø´Æ8BKº¡X[bÞnÙ!Ь‚åµÈYŸV2«–ìb)‡®„ïŒA£°¬,¼4©˜ß!ùÅD–…fÍw%4ò§,Kê̈ƅh5¡{!Ë´ªùñ †@£dnUYfcì7KÆ&iÆD–…üœño¸yY²•Ѩ“$G£e[I-Ü‘»hk3*k`²McŽoeÂà;áÊÀ”;—Em¥:“Ê2=Úc›âAKË%ˤNk¾k…¡Ñq®,Ö«íèÖf‹ÄCñÂ[Ši« (-ãŠKq¿k—£m¡\g%h:;Hu&b’¿ÓnŒÆL3ì)Äå $A£#]³`<­q8öëš±«o3%ìáâm…]46©Ñ¤BŒÆ2Êo5§Í‚s®Þaþ"Óv˜gD–GóÍ,-0Ï0bÓÁ<­ø³¾áóh„8›b1äCäϬ~ås² Ê“=n—åÉÙ;iºGyúÅ;ã·yÉ8ŽäÉÖOÎÁƒ<{¾ƒ‚<È+±kö¿y•ýÎî0^Hß™cØc<_zL]Ýc¼Æ=Í2ˆã%å^½"Ò=Ä +Xðž kËý5=Þ3´Òáõx/çèt4óxÏÔÏÃèç'ÞÓqòv]YðžïK·ÃÂ÷4 L_¿ï‡?˜=ÞsQ®ëðžß±µ[‹ôxF“`ÁûÌÌÍwäç‚÷Ã&‘~øvÁàSHÅ`º|úbL¿Ø𥌯|JäÌ˽>ÕsE÷€/Àfn|ðéše' øŒ©«kãøº™b`|:n™Ë’|VW=Œ îŸáêñfÀÀç3×ÓðSÏø˜&3ÄŸ.·“x¤†„ç|q‰‚ÖË*uØÎü“–u-AæŒVýÓC|ï›Þ1³žóøÁÌí‰~bÒŒº:§ù«ÎИ‡ª’R÷\ËëÇãÝ^3Ôµ½ôï`´Gç{~ÓóÇ»n¿j 50-^¥"ªcb=ÜvCù/¥x.¸·ãhÉ-”tõ8Ã{ï¹ßùhçzÚùh*Y©Kÿ,¼T&Ç¿â-ÖžmÛƒCÀ>¸íëlÛƒ [Ãëè8§kÏë\ÛƒC`Ò'tÜÊ.®íy!?¦ŸÍsÂ'záó=?/|2/|~Ï Ÿ Š>7„O>‚>?„wÂ÷õó‰šní‘c§¶WqKK¸Ÿ¶Íûv"×u­šb(Öê¯È°ú^Z¡ó=NÞþŽ˜üiêóc½@˧ Båÿ¹¹¤_Ö ãcqi(¸þÜ\²ëåW¿f&b\r×ßÿ£éó{&²äÿbûò½aŽçPì¿ á.Ž[ù6ñéÅ€BÝGRñŸ¢Cùͯû÷ÿð»_ýá_üã6&Ö“‹ç˜~v çhnè$%¢\Oè©°{¬¹ú°øÓŸ Ù Í”«ª´áÒ•pÕçYÐM¶ªôRNQ³]°Ð˾¤Ï£´¨‘‡¡ãõ,¿TYû+Ò«X­¨#ˆI ŠÎ¦È‹tÒUSÄÐ,lðƒ´iéÂ0YØ ³¦L»R+mš†¥„Ð–è’}Ô&dG š†í<ÁÛ+TL_Šm´­p(¹„/,|Óñvü[m›« c0.ÆEìP1š,l…iðRÌÇ{}L¦`ÛFë55m2YØŠ“ÔŽòʤYØ0jŽDb$ä‡m tãHÖ–m´ªÔµ­°@Ϲb¤:ðñ²Ü½cÖ4l¬ -9¸HµV¥­˜4l¬¹õS±S¯ªH¶2|»”e5 C×Yv¨µ£­Sb5õªØV?CX¡XM6>7rø¢² Õ¬b™#ÈD±@[3iØ C­ã8“ºÆf²°q|r!“îš)XUÈlõB»ª´u“…m-å]ÿn VñG¨µFm2YؤP$_@f>fÁ*6á ás‡$M& †4 LlëòSOU<§TŒ"ébnGßB»*¤£»Æa’°Q‚0ËÈê˜ÒÆŠ±§¼Ò3Ð rÐL6%àóˆ)‡mRçð”W `ˆ=«á^7-M&ö0FÚÍvX+¸7Ó +Ù“¢IÂÆ…ÆÊ_œMŠ& Kbá»Õ˜…”gñÚqXc›þY>+ÆÞql‹'g-m]lL*°üQ”`lÑh„€Y@•y”:ö°^0¶¦cl°]ù#A;Q¢ƒmîRü=¿¾Á¶8 ôTƒŸ-l3#fÅviy‡mfÒÄ¡zÍßÁvÕЩLVh…mfíèy”¾¢v•ª¬¹Ó‚Úَ̈€E—Ù9Ô®À'Šuê'2Ô®„XHZ:wEm¶ebFŽjWæè/ÔÅCƒÚ\0©$á^jsÁ$½½žµ«d³ ‡¼Áv¥í³§24JÆÁv•ÔŠ½T,ã Û¼Ã$ ¥äºÁ63®FÌ€VØæs{ç8áÍÂ6ËÌ`¡+³-®° ÁúԕVØ®g)A¬i^a»Jl¨%‡¶™§ß h¦“¶°]#30­ da›Œ9áÜ–¶À¸2qIq¸ÍÁù‡5ÑÁ[ܮIJ€=BÒaÁíÊ8·ŽO¤÷Ü•åt;&¬˜nÚϰ“2ä°®ÀÍî2Ë<ŽVà®w£¡£´¸!Ť΀ '¨à®Ø.<$0¯´weHx>ƒ¸™`·•GqY›» Þ%[ns:*Yh‡ÛœÁȇÞ6Ü®RÂ÷¨UoÝ·Ù‰Xé¾â6§ GHê+nsæ¸Ëô8³¸Mß[ìÈÊü9'ró¯°+4³=„sÁ+x3Ô”¬x Ä»¥„zðF[ÇÞ Øbx7Òœh-cï2˜M•ËY7ðfðlLÌh½éÜ•ž€¸€ÊI硽c82ä»+ —N²nt‡Ýdâð–\vì®,ßÑn5×a7S»8zN%Þa7k¡¢¿|Ä´aw oÅ»úªq3é2äŸà„|‹ÝÌÐKŠŠë»%´›2Y¶`÷!¥½awÅ^Æñ)¼ÙŠÝ…–—Â+iÙ°›ãøø1×»¡ý‡$nÌcÃnªÿØU¿¹Çîƒî?X°0‘zmî¸Ä¹±Á!l§Û“Gn¦™µ=r3\ Ÿ &Q¢ä¦óA„° ¹qgÆ!W®û•Cn ^ðºJ‰Ó¸N¼ø6ä ©~ì‘›9˜ôãTWäÆPÊ ;F.r'^õ2”õ16ä>X]Y*܇ ¹bMïl¸é±šùl37&—é_Úò†ÛRt¶_×tÛ<ú¡bCøvÜÙdÃ^›Y·¢žï;p‹³?ëÜäu!åºáÜš@–Ê9§o÷Á:ÏÊçØp[ŠWú­ä ·qøáh¸T÷'}xn«-’v¥›™ Bgín«DÃÎ(ï”î™õÅö$ݧ—¼Ávf¥šq0ôrƒmÆh êαmÀ-ÉÒI·ÍTÂçJƒsÞXà¦qCîp3 ö#Žùº7Xh¥Cïã¸#­î¸uÝ?¸%ýV¡ E߀›H† ·]çf‰.¨‚Q=1tC¹û½<Þí5C]Ûû×ó®8çÏo+Nd–Hì”Ú³®8‰¡^<,èÁ÷7äŠ3wáÜï|´ÍnÐåÇ̧ΠÏÂËê ázþoˆ±¹âø!|‚7ÄØ\qÜ>Ãbl®8~Ï»âX!7UŸ>éÐ Ÿïùyá“!xáóCx^øQ¼ð¹!|‚ðɼðù!|“+î+Q8$\@sÅq<æŠã{yÊÇ÷ò”+Žïå›\q¾âè‚›Mxá>;®Áqtù§]˜À9ºà+£TÿŽÅÑ¥µ|yÌ’\cXrñ¾ªŒ%Џ–v¹„2­ü-³Òì‚›w=Ä"Ó,rû ô„Y1¢\ýõ3]p§.¸Wâî+c‰ÎÑ…ƒ¦-X”d©:] ¡´[t}Ìû¹hêe2å0Ìýx1”¶"1W§C /…¸ÜÅ¡m]B®Î㑉Hy1Ó3CHR¥ÀQ>/½6|Y1ËxUHGT¢•™,ŒŸ id|&ÖF½9? ñ2ûJÛo@l$1Ž˜õ¹.ÁVê7ÀPzàÒɶjê Ò'Õ£¢¹šrƒEvûÌ!³(âí6PxÅÆL ˆÉÍù¹ˆŒ•V«tלŸKgÎy’w6õsa¹Ý™ÔÝ­Ÿ }Yj8NÛYîÎÏ¥0·;dOŽÉÜŸ ÍK5Õ&:kÖÏ…>0±×¬_t,~.´lª LÎÍ…†bÆs‰ñ¼«› Ä1¡ÇËáÜ\¢I [çæ’^Êʼn1¢ëæ_šVì‰%87zÝ„o ¦Ö xÎ\q]h‹¦Ö ÛÂÍ=—è¼\HÆãë5'DSj®,‰&¦&‰DJrn.ÕI[É’µ¡¤YjÞ*œZTg q¹¥•acX°$v[ó•7Sÿ]½l³\uãäœ853Ó¿´-N.™Ž?JýS@ïP*eDÝÒæœ\ØîwSiPÆÂŒ©Â<‹²ÀœÛ÷Àãø íæC^. fSéö³2€ì#«ùØc6ý@>³R—³I¶aŽ=„²a6CP+T%Üf“îÁ²—kËçåR2SV’P;ÌW¬ÛÑ…»t˜M£4ôÌVÕhA›MôÊj­s -öjÆF… ÚÂX`v,umÚÇ{a=Naêhs˜Ì´p ŸmqÕ ï°‚6]RèÖŠ8ã9Ц=5L÷ÚÂÍT ´õøxJž9ÐæJ)ëµ9lßzeµe¥ñÒ:ʆÚü²¦ä€Cmz‘à*lÀQÔ&sWUœeEmª {(žG€Em©`œR9èî¼\(€…CŒç´5S) Ò8Ô¦Á7•ÂWØæ0¡Mf|í¶Âv•Ì81K*+lWÖ.ÏQ”€I‡ÛÐ^x/î&=,¸ÍÇÔ‘X¤Ëáv•ØÔqm‡ÛÂpOöÛá6Wóˆü?…/ Üâw2ýþpÓG„¥’F ps,%ÞŠ™n ôëL7Và¦K NjÜÐõ,°È-+¦áÏaEnÒž#\t¯îÊôe§;­n¾rè7+p“]†tÆëè±ÀÍM‡=X2[.»‘Q÷¸Í¦¦iü0[º€7ô9Zéó‚7‰Æ;+åæÁ»fê6—÷’oê/¬†ÞÄÙÃ7uÄzÓà x‹à\Þ¼YqåôþÛÁ›©¢°èY¨:Þdu¡DZA74x|€˜„òÐ N£ÅÖtKàü‘kþiî‘¢Ê×óÝÖ‚“wóÈM'±"\؆ÜLÔ šqÚ[ê 7UwäÆyÆ"ê°¶ ·$è%¿¼#73…‰²¹©{Šºt>ç{ˆOS¶Ô#7SRå[óÈ-Õºé;WûDnQö°Ý‹^…r31î5èQæ[RpÜѺ)?êvèN<ÓlÐMg(hð)é…ÀA73É·*òÝtÐo(õóÐw•"V7èf±…&¾D«ÊM})9(ÂݼBA(ùÒ ºÉ´j¯´A7"$AFlt“*†vYÎa:è,¦q(ùì» ŠWUð-psÞ€šª@šVº4¦6ôtq°Mö„“ ¶²À4êLäq›ËEïE/ÛE’KEÒØp›ž‹‚%ruô¸Íç$ž\í/Ü>}.¾)q”²Ó¸ËBájÓ埔Ë`ë“lé»ÞŸ0d^óøÁÌí‘~šeKç¯ÇiË– [zÿx¼Ûk†º¶÷¯çÙÒsŠç7Í¿€-Í’ž8·*Q\²¥8gp¼µL§³O³¥sÎýþÈGëÑìöw¡™O"ñ,¼,„•ïùyÂJ†à +?„ç +OX¹!|a%Cð„•Âól©òOaK¥C/|¾çç…O†à…ÏáyáDñÂç†ð Â'CðÂç‡ðMlibM-ܤ¢‘{†-u<Æ–ú^žbK}/O±¥¾—'ØÒœY“Œ·–¯°¥¬!gÙÒÿù)¶”µwmA†i¬d¤K|)šZÖhn1]^ùýäj¤´`6k¼aÆÞ¤ÐÐYš.§ñ†ñ©=m+³¶ Ø`ã‘“Öü{ìŒÖK³vÆŠTÚEN ˆÈ”Z ½4Y²tDf ˆ –¶>“TP«¼´k¾afÜM™QÚʬ.ˆw3$7Ó„ m}Vdö‚Â'r'[Ê à•ŸL¬äŒžºÓS)¹ù.i³ticì£|"y®…;9% ß8¯Þ4ÄM¶´2È—ŽûBgãìšKeD^ +-¯[¶”m gžvµ[º´EÖÎh'5„]?óR²-ãp8-.uXº”Nç…z²\Ûë0ñ(õ¢ÁÙ2½!t)Ó:hÙz h4‹\ËD1ævF¥´ÃÒ¥x®hâ…(m}f¤,Ì#YÏä‚h Ž.mdÎËéÂÜ‚åK‹äѾ¢`í"—Ä^æG¸‚ø[´„i1ƒf[¹“QÒK#5|¦ª-–/%£ugal4‹ÜòZ˜¸\„tK–/-Ìî‘ÆI´dùRa3OgË–/•&Ô+rË–0eÔ;cê[¶„)Í"yˆÀ¶b Snf(UŸvüûI˜J^‰$¹¤É¦bÒ ÔóäT˘⹂ñªS~«–0¥uM²¹ Ha3´ÐÑ?\Q¢­YÂ4K.ÙËÝ£5K˜fI–ÏøËÖ,aJïzòxJL‰ÂEÌúé?ñcºà¶¤¦aÝɶ§“J‘îa›‘M44%(Û…3ã×Vu°M“œ˜A lS.¡˜õäa›Î )ô±°MœÆÆW‚Ü¡6¹MÀH¶±Cmö¨E™"Úlƒzxr¢µÅÒŠŽ w¨½E:ØfMÝgðœƒm‰Þ8î”¶ÅÝ%ƒjX`›Vðx‡!9Ôæѹªk` Cm~ƒiùƒØ‚j mÐ¥NçXQ[ ëédÅœêP[(Q`FÚßpt)n]8O·‡Ú€p´7jK”uº³¤8ÔfpvÔ83Ã8Ô®š~÷:j O²4 GéP[R´„ÞÄòïP[8Ñ¢¦G^Q[(p¬1p¨¬¨Í9@zÊogQ›¤ažIxlCo|YMÀá6Ÿ+Çõ¹l3aÀ!ëÆ Û´7€/þ]^a[rà#ž0êP›)É!®“ËÎäžlCm鎅e“È«EmrÁ*ÀrnÙ«'ÞlÐ]%f¸D ¬uÐ-t/w|RY©Kt)†ˆC$ìÐÍÎ'{î¡›¤ØN×ÔvW– š3áÂn:¹·ÛYèÃ|i§­·w\œ‚üQù ¶?ɘ¾íÿ kæ5‘ììéhTÙÎ_“—£ŒÉ™Þ?ïöš¡.îýëyÎôœ¢ö{ýø&δT —Ç&J->Ë™â!8‘¤Âäß g:÷áÜñÏX>wùóûÐ̨|k*zâÊ÷ü¸’!xâÊáyÖÔˆ9”…Ï MµG/~¾ëO¨6 cðòçÇð åU¼º1|F½ƒ—@?†o¢NY0WÒ^XžâN}/‘§K7O±§K7OѧK7Oð§Ø%þý¼÷~…?í“=ý·Ÿ‹5Å>öì)Þ€wÉÉÇb`6l)ãJ‹~¹åzΞ< ¸×5ûõÜ,yJKîíZÝåºu5Ž›YkÚ–-yÊ¢Õ©œ%½˜" iˆ£^iÀqû¼Í9’n.öËC·ób{sQI¶µ*©´™ ¥» e½™L²]ù¹‘v#¼É¨¦n³=ŠWJCž²|6&Ô†Äõônªû‘ê< ËsÝ÷#½˜ö«\•'{ÊÜ]š#•mc–ö#(JÐb”@>²eOV¨Ã­ZW“U'{J‡|…½!´±¦øC¯jI‡)ëÇpYü±ô*zú8LU?%'#sÑÊ;ÃaƒM 9×C’Óga’§DHR×,bƒik…Ãò©Èõx°îàMž {Â’~ÚD]ä) Kîà&ñ#6Kž2XBYW¶%SÍ$(@}œ´=þkƒM£[®À·!Öü‹<%7™Rûˇ6dçbÔ‘g%? —-¸<¨ e0:cF›6&UÆÖ÷(¦ŽŸ;Ãóä¹’m¸)#Ã$hLºãטᦅ»Ø#ÄȆ›2”¹Œi’¶lãM™á ¡Ê¦µÙxÓÌ"ò§ý~9g¸i¦MíÊ)6ë÷IS•ª…ÚÔlRõÄRUmý0ìifÅrÌà”V´ñ¦X†~Ò§øKc‰ÏLôv›÷Æ8,}*q*W@3zµôid‰m¦f“é±Ìà¤O#Ùt|ä”o«‹ßSüé‚ÜPŽO.d‡nä¦AZqÏAweu[¿ktã>ø=ªòÀº‹ð$=U‘LÝÄêrÛk=t³ðƒ÷M+tó± Ñëu…n}L‚ã Ý´¶¥‰º…ËÅ “6tÓò½•Wè–*!G¸bÑtK.Á (vü£¶9ä® û»StzäfÞqˆÊ¡q‰¹©^âPKiô ¹Å#Kª¿Cn`£lJ·$õ %¨&¸wÇ×)º¿Ö£7 •x%ÙöðÍì¬3/ÏßéÅ Õ‡™òð-îL€0ŠCovט®èT¬-zº23ìè-„*ÝZwô–Ô6W¦–¼qŽ ó"¸€waéç«òÃÞƒQãt‘zÞ̲ƒ?½58ð†tá 9µ Ý úí·ÃœÃnIôTÐ:S»™¾.Z»Êc7ëá#§ónã°›ÙšÍQè±»¿N`vKõ±#† »¿ÞÕ7aÇnÆ;ã£kòª»=Þ°õƒ.‹g­ì£Ü¦:šhuïx±ò­—ývÏX6ËM£Î >ÒS–G5?g4ó†I¿>¡ã`¹Ôùóy2õšåÕsût*Ô»Fe@ÁÚõOÒ©™€Ž8_êG˜ÛÇkg›9wÿ#îÚðÏïH7§"9[ó•É÷É.—Ú¾ïÏ`µÊƪ.ƒø Z«l¼ªħðZecV—A|µjWFR– Š¡Fky1ô}‚j‚M/†~Ÿ †1‹ºA|†Ê 1ôƒø&~µjÒ±Œ>?WTÛ÷ò¿ºtó¿ºtó¿ºtó¿ÚX‡¨Ia±øz5[zõÏÏÕ¬=*Iàe~·/V7“¢ÕGe¥qMÀv&†l±$¹A²x—¥X z¥C2ÐhÍ=b´ÍíÌÈÖÆ–[]Ð0,ˆTbÓÆ,ùÅ×$qÜ!ù&‹6Z‹Ýò¡†v^º1ù„Æ 8Æ5m£1fÂñÄNӳΤ;£¥ ધ··a­>D¿  ¢YÒŒ) t–^« ×>¥ZhP‰×¡5Xb°M3Âa¹V:¡‡Ü%ÑhÉVìÝŽÕTãÚðÒt–òfºã @:¹4šPUQÃPõ[…àÈV.*ÝÜ›¾kÅTcR»‡ä.Éð¦VšhYÑ×X¼bhÑY´9ºU‚ òeIl÷2ú3´|*m+á eèlžÉçИ%ÝkÎ Ã[{½ŒbhlgÀ*><^©%u +—³q(…¨ïËxß%Å|_a*8-Æ…FG»ö—}hÈWÅñ®G_KM³õ¢1¿Â%ÅgÔêY5 mM’މK`goµ§ KZ-óÊ ‡ˆ/œ†Ž§ê•a˜Gª‡ÂBYëSˆ•>¾£„h7´±«‡ØýÎêg¡YòU죟Û,qM"X‹7žòF+Ë-Ĥtñµšf:C£å_ñÚÃåÛFGÀn¿tšò!ŠL’w‰±¼ö.‡‹FËÁ¶ÃsO;Ã:, Ë*I!Ž*F9ˆê!%›T5¥áe¡E#£I.A¦©/¶BÒFÇÃâIŒì¬Ô΢n–ˆe{.g\#Yfý’d²Øµ$}-vV½%™¶X&_V&çN]¤æòÇ î}´ÄõŽòU‡v”oL{“Ð ÊWf­1ivÓåñcœCw”Çkúà  %V=Ê×ÄœpWq¶å¹›qècUÓ†ò¸ä3èmGyFG ñîÒ¡<73d÷,ù¼À<ý…䣜‡™…yZþS‘\ˆqƒy¡Ï¦zìq^â(€7]½<ΫåóŽ(÷@¯¦bIÔ>V¤Ë4æxh¼‡z1µÖÎ$ƒê•ðm¹ô²!=S¨“(óP/D+ÙjïÔ‹õ½¨¥yƒzÑ4?nÞ ^èXÀTjcL¨f±H|{Ú ^iÇÐÏø]õ$1Œ€‡zv†¯Y=‰røÌÀyV_õP/•%¡%Œ|ž‚ë…ßiáâ:=ÖKÂç;ñ¼ƒzÉ É,Çõœz2'LnØG¨Ô+Í4ñ;Ô30ǪúÜ õŒ”döõí¡žOF{ Y¨gm;4IÆõ’5U¬òç b¡^> ÞuV‹tP/±Ø@l:ÇmPOŽå`Þ¹º=ŸcBÕ¦Á­è¥|;öÐŒåè9(ãLK잯Ç]½Ö½P>ú]ÇôB$ÏÌä'GD èù ãz²²ê‚õ€Ñ0»ò;¬]*wä륮‡DÆ7XÏIJ©*Í‚õÊÛŸÛ+ÖÓOóò\¡žŽIQìPÏk‚ºÃ¼zVoS}ð ÔG\»B=žwÌ3*ÍC= Á0/êIí Wx¤7PŸXò'Ljo >ñ:žR8AÐA½ÀÝuÄC=Ñ*Ý™_c‡zS¦az&ÁÆÃÌ;Ö'I3sæ+X¡ž'>ä«åé™AZdÔš÷+Ò3MtèglâŠô¬WI¶ì„Ez¦ µÇÇŽôšw¤¥|ª—é Ùq|–#îHÏ'q;I—ú]·æqšzAz©îSÃYNfEz|SàÝ#==ðÔ%­ê)(ø_¬;ÒI~vùx,HáÊÚu¶8¨ç%£Þ1¤ Ôû’Ú Ôó"qnûêéˆÊͪQë Ô‹raÌù Ô“ùÖ+ø¨’û·°±C½T¿+Á/`/E}Õm{º£Æ˜…'ßÀ¾ˆ‹ñ­ ,`?õzŸ¢ì™çw¤Ž:+Ø××™aàÖêEê8ÎÕ{çãl/ôr|uÖ­ÃõÒ2¯Ð¬ÙZõO1½ozÄÄzÎã3·'ú‰ISìꜮ_]Rê?Jµ&13]k©?>¡Ûk†º¶óWxšß=§x~ÓëÇ›n¿jŠ Ô0Ëò@¹§e‰=¸ÇÔúWgwéÌ,L• ‰>ÐÕÊîþê×á «°ã0øý?þEsl8ÁX;ÐÒV˜ö’xÓ©â®=CgBÏ]{þÂÿýðåýò/øÿoÈZø-H01çÁ9qæi$°óÑ ·£ã˜âıç„-_מ]ÛƒC ä2 F*q‚m{è;­& ŠJa‚k{ò¬IL…©!TëlÛóB~(ÅIž>v¸Ÿëù„O†à…ÏáyáDñÂç†ð § æ„Ïa>9M$ãà_zšP÷ÆÕ‰¬8ùq†€ð¶¶Ÿ%ßÎ*û>Y¤^î;}9;)¿¨“é×ãàáüWd®]/¼;ЄŠKOø¹N~ÑT²˜¾X#.¿£{‚ÿ)­â{Þ­ø¿Ø L {Åþ‹pàfž{fÝÌ|†«mQ›ªÿÊo~ýÛ¿ÿ‡ßýêÿúã·1YÙüŠ–3^•¦N?=&£Ý£¾qžsõkÿ¿?=X¿64SN‹®ôM‹5ЧI79â:˪Æ;R&tÍwàùE!æ® I¶ÎúP߬¥pyä“õçI3*nØWKÀšV±Â$$¾aÐFOršÅÙ: “#®óphÔ¾ã$fñÍ7ÍÄìŠz]-dÏŸ+m9Ö¬>è`6¢¶­dfËe˃ßÏÌìN{f¶f4ï9{0·ú7r…=jÁ 8ß¶ëùwõ\i7ÌcêÿîÜ<]î$·|që²Ñ6h]ôGtD÷ʬ†¿ODfuþˆ†àõÊa)¯º›¬®öÏjçÇ@ÈËZb!–/ÿµ´q}3èW£¿"ŒÍ-â×öÆ8ò‹!hÿô…TxظÏ_v_ặþÓë@Ï%>Ï4ýFPšú­“tÎýÝ Y­Ézu¬ÿ$Ùè·3€ò}5MèLòý{f9 œ9¯Lœ–q^Ì4 ×ÓÔR@¿nï"îLˆ## c~dñ)|! c~dÑ)|# c~dñ)¼Ÿ'yèqýÞäÀÇ䣑¿0ùôxòñ)¼?ù”(<ùè¾0ùÔhòñ)ü@©jµ‚L¼•Äc¼”ă¼•D£¼•ăü©  “_#;ªõñSv{õ'ù5ÿõb~Mž6j¶á—Åè£FMMjŸ\A@ƶá9Ç¿å ò—\°/wèÀˆc³Xè´ "cÛp9vy`¾Ü1p$a›'^e×”˜ÒRe׌º+)f×Àu4m¥¦äбϕ݂F‘–«€ìšj¶ËU€çuk[s+¡c5†]áZæÙ5}Ý»Çg)1»f”èZ*e×̸-•²kFT’ EZ®‚éyîlžÒBFÅ­<'©´ÐY2!Ѥ Q¤å* ƒ&™EhéGvÌý‡+=f× ŽYü®ô•]sÇä†2bvM—©?,¾PFÌ®äà2Žìšî‘ù2cv Æ{”=FÙ5ò7g¶©7)»fjwÙçáÔ+f× ›ç6Q¨^”]õ×¢zõ¢ìš‰`êýÌ¡z‡ì„]®Šú¹ª‡Žìš4¯…Œ8&ÿ+W¨ö5…Œ.Ø×Ókƒî­¾×z0êåuùÈ­)Þú·f￈G=‡½U5©5áÉÁßÜCqŠyEšaÒài5°;ñЯ¶0i5Ú]Q¿Ø0¿°b2½‹)×G­ÐÞížU3c˜VÝM¶q¨fã„ÚVN÷D›·²jØÊ˜¹³j˜ØsáÍqB6Ê|s5 ²Bd&à0²[FãåHÅÈFµ°§Ú-#+¨õÔ×èMÚúV( ×8ÒK"®!´<-’Z–ÇÈ?ß$‘ñàu›Îµ†Ào“{ÔC_ê{¿Ôª–Ë-Føá >üþFP#bb¢ꡆږÄJ ÆýM™&Pã÷æR ÒÐéÊmiU€o‹f¤ñ÷‚ BÆs‰×­¨ÍMþÝ”N“Ð+c‹…iÍÛ–úBÆ@! ­‰#–oBŒÆ5ã+ÿ„‰ÑH= Ï… ùZ–0;O…ìzDŒFŒ[{¬g=V{‡­£q*hÝúà‚ ¡7è¤ÄhM@ò<@b4’Q¦‹GÄè¡&*NëÝ ÜœÆ¯µi9Äé¡Íìå NÕ€~ëØÄê¡=#,׆X;V[küMyMw¬Ÿ`Û Öïʲ„XËÝçB÷N–~ó¢.{ð%úu¥á¼Fv‚§Å1¯±(|L¹>y=…ev)Ìk-÷Å$óþ7i'·3¯±`ôÉy0†+6™ÙhÓ}¼Èlì@]dpÃåÈ«ÜX غã“Ü>§™Ü(ë÷¼~"·,yåWöGŸÉ u\Nr/k‰ÜX,ÜÍ6,Dnt‡©–Áä–Ë“UÄžLnøxn5Ó¹6éÚ¹eLïCB_½5¹ÝgÑ[þf^|†Óë]dez#Ó4lˆÞPÓ`!ù|ò‰ÞêoÉíLoÎög|÷õvÆ7>ž¤Ãø†pëîcŒï>£û ã[OU#|#§wXâ ãMº=O‡ñÖwÃ’(ß²j+(Æ·<ÄÛç ã»Qׯ·¬ÊBê á[7–¡ÀøÆÎ/üáÕ4—ÉÙŒoÌCO;e|cêù"ñ;]·w ÓYOÚ®iÝ1¢wï1uYéݯ¸|ý±d û­ÝEÏôÔÅ-1Gß”l5ú‘Ì}ÿ×öÊ8=J¶û§/h§rI.Ù>?|aØ}…ëÞúO¯K¶Ï%>Ï´ü†d w.ôHiÚ›ëUɶtØÓõ"ïlú‰:üÛ’m)Z«…†‡íï©Ø:9¯Ì›‘p^A¸žæ³ò]¢üÑLOE3>…÷E3<,šÑ)|A4[ó—D3>…÷Û8É¿¢ØbÀcòÑÈ_˜|z <ùøÞŸ|Jž|t _˜| j4ùøþÅ6£ÍÙȺó|K±å1^Rly·[å-Å–yC±-UùËÆxÿR±M™Ûþ‰•ÃÿO±…¬u|Ôbªv,ÐMP{\»¥êŽ¡º[ž¶«W{~Û£¬Ðã®0ý÷€òÊSÚ04¶Ž MØeÃ\ÖJ2xH †aëv EE…ì/·,«f”¶9—­ÓÛ´ÜõX,BêNu?´Ý9:¾{œöÒÖòÇ.¯luxËG7äûÚ;w˜œz@éJ¸[æn­ºM¨ümXSjßz=F¢íˆ•¦òF›I¨š,˜¨Ž¾Ë.ÙN˜ZÝsëÃ;>Ê?wïF96H²…4²ÝäÛˆŠí¼Ñ\o6†Ûƒâ·BÑZ›Q°•(œx¶ímVo÷;»ܦêµ~³}?—Ž Íž®]N5yt·_䆠ÎÉõ‰Zuiöt…(îWÕï(×b8O[ïw”kûˆ5óAš=[õÜ“ÐzŠrí@©=²Ž Í3[!³‡²ÿž¢Z+[Áž­@¶#F³g+NeIV=G¥u^nÞsTjQZæñìô\©EoØ7­Rjk”V{!¥V8•mQÒ+©µ2­ÔMUß_ù÷®Öâ×d:>Õ½’Z‹0’…Šz‹j-ÊÒd–>Bto¤ØR”L (\±Åif{p$[(Xõ®Ö%[üMO XÏOV9—ÚMêÕUC¿caß[’íAìáä=‰r[Og`bã}õ.ªLlYî #‡Q9[ Š,0ÍÄÖººôkbÃØ£X؈=ÐÖî$æ0—©”Ll­³å(€ó*]&vG5±ÉLl9â¢LìzÅWœ‰ Ü“ˆˆØ¸-Ããü‘ØZVdÍ:ˆØú[a´Hlh‹Í«‰Ø§j—䥰²Ucž¦°³q,ËÔÜߣIú-êšû®»#h#´›³É± ÚPݦœÐÆFfx"Aù楸mÖ7³ jãXصUôâR¢¶Ö²ºHÔ†”2Ü‘)R2ót[¢6–;A!jCK®nÖBèÆ3 Î>„nèÿÍemB7*”›;“ºqé²mÙÊ„nœg¨>#t«ÎïoOD÷X µ·DèVÓƒ“ÙZeœý;™­ná£ÙÈ ¡Ñ‡82³xy21âs¨@$f비i‰ýnFnÙ=~¼­þ±r{`{ú¢øÛòç®%flÏDìblOâaÙ;^3ÈØúHö#elË^«yý;c[î 2ÔÖZãÛO+Œòmýº8LÛØÚ]¾®'l²-8°=ÿ˜Õ ƒÛpykÕ¾<'¶«ÏfÆöÀÌ0ÿÂö rIæöh´Ý!nܘÛò7Cž sÉ‘îÚÂÜ–/ÖåŠ/sÈ@æ6’#«Ÿçâ¶Ü«éuÌí~ –ÙÉÜ3ºÐ1·Y0·¡»Å swdz™ÛròòDíBÜÆr­íˆÛr?z ¸ÜX®Zr!sÓT|æ6V!^´ÍÜf‡æö@›º²Ëš™Ûø†{ ¹-Ï{${}˜Û(¾÷lâv'çæ6îXÿ$÷€¥ñ0¹Q»<¶…ƒ;¨Òv–/ƒõñX·v˜+ö1 pc›ä¹Ö n5S³{ûcÑóGh|V`Wÿs)8þ¦lûËñ߈gî ùG¼ºWš-·û§/(¨³NnŸ¾0ì¾Âusý§×…Ûç׸ößnkS‡€$ ëé]á¶]HÑÖe*#~O¸­²Ø“^仑ÿ¦µ¶Î§Î;¶ҼςpEõÚíÐÌ`’Ïhä/Ègz ,Ÿñ)¼/ŸéôaùŒNá òÙšÁ$Ÿñ)¼¯Ý†i.ë•oˆ·:â1ýhèo´{ÐsàùÇçð…~Jž€tßhø°ÈF3Ïá/pkZ%_¡æ[ î1ÈKî1Ê[.ó–ˆ{Œò†Š+뉩†TØ‚ÿ·G÷þù^Ý-"i!¸T6\)øUoPSqu½ÍQþáÁ¥–ÿнØÊÄE=FPq¯¨æh:¼íÔ3EmÔ ×UÜ¢1ADSƒ|›ÿÐý¦bÑ„Ûn÷æuÕìÍy¢ õssá6íb0M öBÛ‡½gÔ½iaVni$é>Ý´° qÊ6æÊrSðôì”—Éô–Á`´Yû‹Ç”°!µÀ!ÃÒ§;!…‚­G`d³y&#ïëmΦ„meñ4ÏfÂö [¥a[å:ϵ!lã÷‚ <±[ËVÒe¶Ènuݬ¦¥Fv¯z$ û»q,¸"»q,”u»UðÆÄn„}Ãw›Ø=›–õAìÆ¥ßͺ»Õó.ö7•ݸ¡€‰Ø­'èõÕÄîUölÉ;ÄnMóB+b÷È3JÄn­²öW•Øw"è¬Än-@sƒŠo­(òl‚7N3£åñš²oH¢òYÝ">Á[%pïN@ðÖB+—* Þêp á­UQžŸAðÆû¯!Â…ƒ¡ÝI„÷ê'`oÁ¤¸ÃÒ Â[ME=³†à­ªõêç{ŸðVï|7< xk…V2C‚7ˆ–\°#xk“ˆî-”Ö¾f'¢½¨àøžÐòï;êõ¾§¼_¾¼$|«éŠ-Þ>ð™IøF®[ÄþïqÛ;ËøNQÑ;ð ßms’e|ãõrúÀwAU©­Ô ß0®õu+ã[^õˆZÆwŠJìotœß鄽s|½˜ÞZ“íJ߃ÞW\íô†%„™¹0½›v·¥Ó;Å×Ao2b8è}‡þì¼)uå·®¥œ6 oÙ ¯ÕåÉíP ÎÜFNGk˜ÛºÒõMÈÉíiëŒmâ4¤±¿1 õ$ŽiÈ'ñ…i¸¢é< é$¾1 çxòIüê®\@Rû¯~•×zªƒ¼¤î£¼¥îò0o©»Ç(o¨»¨döÈÎ+ýq·Di÷¿ßkY®Ë:øHW¤½N¹³Õ[(^ ^©×Us_Mÿj±hœ$u‰âÖg[’¼+»C3Sº¯®ý!UïÕê“àÞ&‹Ú¾e$ò¡)Zh%cì >‡·µÛ»¯qq®oå˜üÕöÄïµö×ÛnÊÁ~‚ѳ‡˜àØKuÑáϬxå`Qó·EɻȖӺÊAí ö|Éá}[Øñ¾¯‚B vwB¾},×MÑŸXv·äìzé”ÍE€áßçƒr,*À˜ˆþ]‘ƒ]=àš\’*Î('ßwïF¤gÝõ¬¿™<^&c( ¦}½Õ¢ eì0Ä}#âsc…¦*©—Gœä`Q#¸\î±Jj›i rP…`¨ÑÞÎP®ïR+8ʱí‰ëATp>S+ûË•?øG-X÷ Öáù®‡çùŽ{.Cü ¶Ãr°«œÎåuÐ,;å´£Œ¦nî)&ƒ",'{{.º“¿º¯¬£ sZλœiÂ-ZzÂ?•«y»W¼ÉAíËý|çPâî´÷­ÞŒ{-¦ö´¶ƒ¤ £òÜjˆä`†¡z¸XfãåÅá¸ïÃ{sÉÁ #_ß½åXç¢ÞàÜ,³õÒÎ]k.#zÝÍ—PT­=s]ºª•°ÉA’‡™wéŽú°þÙ¶ Óå`JóÌeõw6yEvíêµæ2RºÙæ>µßåψ ?íq~°>XÈ~²¾ Ç6D`½4…! öxÄÙÒ ØãÕš¦“°G <[ã¶öˆò{ô€=Šj"\#ìUQæI°4ƒ˜õë*[7zFÖã`pS`ÖkT?ž+±^õëÊ«^ìåðLyܶ`ãÈ”×êOüÊ]ç™ò8Øgy ¼6½lÇÀ”WoÑb¹4Lyüfs]›)¯v“Ýßn¢¼Ž¹’¸˜ðиB ž¯ÃÙ/º¯ó°2Z¦»Öp{æÓ}ÅÙý5$º/Îð…‹tWñVƒ„cØ5˜žÃtÇRŽF¤»ê®î%Jt׊gÖ3Ý¡9?÷†À¾4J?Oûòw7U™Á®EÔÞW‘ÁŽ7PX½Õ};V¹ñE`×Ö"a‰·¶Õ²péß°n>á3>àŽ[ïnÃÜ¡._Öšã„»\o¶RÑîdÂpÂ=ÓÚï€{©) whò9|Oîãö—åî2$¸r&?àŽ®½Þ‹ù€{CåØp—?["¢ îjƒlÅ•Üõôf¸Þ#1ÝqCÜØü »ìÖû€;Òí<ƒâ€ûP3)_çⱌsc¥ñ…Œx9Ÿxº?à@`¹„'â^]ßâñÍkç <®/~¼ˆðr}Áté ¼¦¹† œ¶UDy,îÜê†)‹ S2é‘[1‘ç^»ƒô-öÙ9H¯Mq¬jÿ =îAí~ƒ˜ôäp ûm'ÐË_½â÷?‚^ïU¸=z8y»GÈA{$šTÓ¢Úã7=qô =çÒ´ÇnÅ`NÚËgÒR´zÂÎ{us(¡5`ÿŸÿñ¿ýÿ°Ç endstream endobj 3 0 obj 34691 endobj 4 0 obj [2 0 R] endobj 5 0 obj << /Resources 6 0 R /Type /Page /MediaBox [0 0 1080 792] /CropBox [0 0 1080 792] /BleedBox [0 0 1080 792] /TrimBox [0 0 1080 792] /Parent 7 0 R /Contents 4 0 R >> endobj 8 0 obj << /Type /Font /Subtype /Type1 /BaseFont /Helvetica /Encoding /WinAnsiEncoding >> endobj 7 0 obj << /Type /Pages /Count 1 /Kids [5 0 R ] >> endobj 9 0 obj << /Type /Catalog /Pages 7 0 R /Lang (x-unknown) >> endobj 6 0 obj << /Font << /F1 8 0 R >> /ProcSet [/PDF /ImageB /ImageC /Text] >> endobj xref 0 10 0000000000 65535 f 0000000015 00000 n 0000000145 00000 n 0000034910 00000 n 0000034931 00000 n 0000034954 00000 n 0000035384 00000 n 0000035253 00000 n 0000035148 00000 n 0000035311 00000 n trailer << /Root 9 0 R /Info 1 0 R /ID [<8B8D6CDBD5BC7A8365A3E5CD763CFD41> <8B8D6CDBD5BC7A8365A3E5CD763CFD41>] /Size 10 >> startxref 35465 %%EOF blis-0.9.0/docs/graphs/large/l3_perf_zen_jc2ic8jr4_nt64.png000066400000000000000000003465771422157504600233640ustar00rootroot00000000000000‰PNG  IHDR¬öEYa )iCCPiccxÚ•‘gP”‡†Ï÷}Û m—¥ÃÒ›T) HYz•^E–ÞY–"bCÄDiŠ AF¥H¬ˆb!((`A³HPb0Ѝ Ü¹3qîüÈóë™wÞ9çÌŠ*’*àû¹Ø³CBÃØð ‘¼Ìt®'ü#Æx ÿJtL&V Ÿ—Î ¹ •#H Ç€•”.@Γ€ÜfÜ_>̨¿|˜ü?@¢Å}ãQßø÷¨pù‚„ؘ\¶Z¬ '’ÃÎôs±g»98°}øi± É1ßü¯Êÿ€ &Wà–¾…Ÿ/`ÿßPcC##øûï|„5ø¿ÿ€oziœEìÀßYT5@÷é'gjÇD ºîñ²øÙe8‡ÏÁá+ñÍøNü ü(~ÿ@ °šs‚+!”HØJ(%%t®† S„E"‘(CÔ%Z½‰‘D±ˆXMK)Hq¥b¤öIµKH-IËIÛIÇHKwHJ–aË8É$É”é–y&‹“Õ‘õ•Í‘=&{Cv^Ž)g%Ç“+–;+÷D•ב÷“ß*B~P~QAQÁE!]¡ZáºÂ¼"KÑN1Q±Bñ²âœCÉF)A©BéŠÒ+¶$›ËNfW±ûÙ ÊòÊ®ÊYÊ ÊCÊË*š****ÏT)ªÕXÕ Õ>Õ5%5/µ|µ6µ'êduŽz¼úõõ% M`½Ý³šÒšnšyšmšZt-[­ ­F­‡ÚmŽv’öQíû:¨Ž©N¼N­Î=]T×L7A÷¨îðü‹5©k׌ëÑô¸zÙzmz“ú,}Oýýný7ja  ¾š&6>5’0r7*0ê5úÓXǘg\küp-}­óÚk{Ö¾5Ñ5‰19fòÈ”aêeº×´Ïô‹™¹߬ÝlÎ\Í<¼Î|œÃäøpJ9·,ðö;,.Z|²4³XžµüÃJÏ*ɪÕjv溘uM리U¬#­¬…6l››ã6B[eÛHÛFÛvªvÑvÍv3\mn"÷4÷½¡=ß¾Ó~ÉÁÒa›ÃUGÌÑűØqÈIÂ)ЩÆé¹³Šsœs›ó‚‹©ËV—«®xW׃®ãn n<··ws÷mîý4ž:ž|Ï^/ÔËÝë×Äzõõ©ë»½ÁÛÍû÷3MŸ ŸŸ} ¾>¾µ¾/ýŒüòýüþ›ý[ý?Ø”< Ô Ì ì  j Z v .†„l ¹*šÚF k[Üà´áð†épÓð¢ð±šs7ÞÞ$»)yӥ͢›#7Ÿ‹ÀGG´F¬DzG6F.F¹EÕE-ðxGx¯£í¢+¢çb¬cÊcfb­cËcgã¬ãÅÍÅÛÆWÆÏ'8$Ô$¼MtM¬O\JòN:™´šœÜ‘BJ‰H¹*‘š”ÚŸ¦˜–›6œ®›^”.̰Ì8œ±À÷à7g"™3{LAº`0K+kOÖd¶MvmöÇœ œs¹â¹©¹ƒ[t¶ìÛ2“çœ÷ÃVÜVÞÖ¾|åü]ù“Û¸Û¶#Û£¶÷íPÝQ¸cz§ËÎS»(»’výR`XP^ð~wðîÞB…Â…S{\ö´‰ñ‹Æ÷Zí­ÿ÷]ÂwCûÖî«Þ÷µ8ºøN‰aIeÉJ)¯ôÎ÷FßW}¿º?vÿP™YÙ±„©ÆÚuÈëPW»¢¸âýá͇oWšTÖ¡É:"¬ò¬ê©V«>P½R_3Zk_ÛQ'_·¯néhôÑ‘cvÇÚëêKê?O8þ¨Á¥¡«Q£±òáDö‰—MAM?p~hi–m.iþr2õ¤ð”ß©þó––VùÖ²6´-«mîtøéû?:þØÓ®×ÞÐÁê(9g²Î¼ú)â§±³gûÎqεŸW?_×Éè,îBº¶t-tÇw {B{†/¸_èëµêíüYÿç“•/Ö^’¼Tv™r¹ðòꕼ+‹WÓ¯Î_‹»6Õ·¹ïéõëû}û‡nxܸuÓùæõîÀ•[Ö·.Þ¶¼}áçN÷]³»]ƒ¦ƒ¿˜þÒ9d6ÔuÏü^Ï}‹û½Ãë†/ØŽ\{àøàæC·‡wG׎=>Š~4û8ùñÛ'ÙO–ŸîœÀO?{Vù\þyã¯Ú¿vÍ„—&'_ø¿x:Å›zý[æo+Ó…/é/+g”fZfg/Î9ÏݵáÕôëô×ËóE¿‹ÿ^÷FëÍù?ìþ\Y˜~Ë»úgé;™w'ß›¼ï[ôY|þ!åÃòRñG™§>q> |þ<³œ³B\©ú¢ý¥÷«Ç׉ՔÕÕÿB,¾;E^ cHRMz&€„ú€èu0ê`:˜pœºQ<bKGDÿÿÿ ½§“ oFFss0ˆÚÿR pHYsNNÆÊ/¥tIMEã$9·-ç vpAg’Zó!%Õ€IDATxÚìý}¼äø]߉~Úlqaµ kSÝÑáa ŒÊ],ë€U!ñ˜×IT°—ÞLo²/ÕõÉžÉÃîEÚíd/Ih¶”åÞÝt…¥½30ìæU Ϙ%›)… `j(³&TÛp˜é2ޱ˜jfððT÷¯J¥’TÏGªªïûõ:¯îS*I?é|õÓ÷ûû>]‡C0 Ã0 Ã0 Ã0LÎx]Ö`†a†a†a˜8Ø`e†a†a†ar ¬ Ã0 Ã0 Ã0L.aƒ•a†a6Ïó`ÛvÖÃ`†a˜µÀ+Ã0 Ãl0Žã R©d= f‡1M®ëf= †¹XÞ/6X†a†a˜…±,‹xfg`y¿|^ÿ½ßû½ß›õ vÏóp÷î]üôOÿ4ÇÁW|ÅWàMozS°Ý4Íàá–eA’$€mÛ0M¶mC|á~a°Ÿ®ë$)8¶çyøŠ¯øŠàxŽãà¿ñþ>ÃÌJšŒ'm3MžçAÅà8–eáñ!IË7³¬KöeY†aøÌg>øñÿqÐëÜó<üƒð&Þ ³ iòúÓ?ýÓøÌg>ƒ7½éMEqBFé3ž³™May!qÞg¹^ ö°fŒçyØÛÛ ò,Ë íÒu†aÛªÕ*,ˆjµ§T*Á4Í`_Úîy<ÏCµZE¥Rã8Áv]×þ>ÃÌBšŒOÛ•·eä•囹lÖ)ûµZ-v•ßó˾,×óÃkƈ¢ˆv» ¨V«¸rå jµ?$! ×uáy Ãû‰{A0L–¤ÉxÚ6À_  +í,ßÌ&qÙ²/I4M;ì‚iòÊ0ÛÄ2òÎÏÊz`ƒ5c¨R³ÙÄùù9ºÝ.,Ë‚iš!Ñh•$)Xµ¡ŸV«MÓ8o‰Éi2ž¶ ð•vÇq`<ÏcϳQ\¶ì7›MhšœŬ”iòÊ0ÛÄ2òÎÏÊz`ƒ5c¨¦¢(¡¤°Pâ¶çyÀ˲<ö;0Júf˜<‘&ãiÛèwEQ`TUÍúRf.²}AP¯×a·]`VÆ4yÒ£Âf“XFÞgÙ—™6X3†ò’öööP©T°··(*¢(¢Ùl¢R© R© T*aa¤”躎R©TnµZY_ÃŒ‘&ãiÛZœaï*³id%ûŠ¢@Q^ÀdVÆ4yº®³‰Ù –‘÷Yævf~® ‡ÃaÖƒ`xQABz©€’(Šp]¢(¡dd˜†‹,Q˜0Ãä‘8Ÿe›iš0 gggY_Ã,Ë>³-$ÉkX_I+LÃ0›Ä2òž6·3óÃkŽq]{{{èv»$ ®ë¢R©@Ó4d¶ §)•JPU5ÈÍc˜m‡eŸa†aFä"$¸×ë%~Þï÷³^f„C‚¯\¹‚R©„’1›Ë÷b8Žƒ«W¯BE–ùœÃ2¾ZXöóË6³í°Œ3›@æÖF£^¯‡ãããà³~¿MÓ‚‡H–e†‘íb˜`ùf¶–qf[aÙf¶–qfSÈÔÃÚétprr2ñù;wP,á8ž{î9ôz=4,‡Ê0sÃòÍl;,ã̶²Íl;,ãÌ&ñYYx0@×uȲŒŸ÷û}t:<õÔS€B¡€ƒƒœžžâèè(ñx?ó3?ƒù‘Á|ÁduI+祗^Âõë׳ÆÊxå•WðÊ+¯äâoôÊ+¯ P(¬m^µ|À­[·ðÐCe}ëVFžäaUäé™}饗ð¡}hmÇç9|:y’‡U§gö•W^Á»Þõ.ü£ôV~lž¿§“'YXyz^_zé%üãü±¿¿¿–ãóü=<ÉÃ*ÈÓ3»Èü™ÁzçΟ¿ÿ>Œ=¤ûûûSãèßö¶·á=ïyÏÔ—Æ&qxx8¦±ét:¼ð ¹øÑXÖŪåzè!–‡œ“§göððp­Çç9|:y’‡U§gvs8ÏßÓÉ“,¬Š<=¯‡‡‡k3Vž¿g!Oò° òôÌ.2g|zzŠ~¿{ÓÒŠÁ`Åp3ƒz®n ×®]Ã7²ÆÚaùžm”‡m{f“`Ÿm“‡m|f£°lÏÆ6ʶ=¯I°ŒÏƶÉæ?³—n°öû}œœœàöíÛ±ÛÓˆpØB”_|Ï>ûìÚ½ — ­~m Åbår9ëaàôôwïÞ ú×®’uÉ7à‡§âôôôroؚȋ<¬’¼<³‡‡‡¸wïÞZŽÍsøìäEVE^žÙF£»wïâcûØJËó÷ìäEVI^žWš¿“ª÷.Ïß³“yXyyfIŸwþ¾ôàÓÓS ض Û¶Ñëõpÿþ}4 ¤†@‹ÅÄmïz×»ðè£æÂÕÍ䛃ƒ‹Åµ„“­K¾àúõë[žÂ¬ãããµ)<‡3Ystt„7n¬|çù›É4¯#$˜ço&kÕÁ/Ý`掾v툎ðÿ&ϰ|3ÛË8³­°l3ÛË8³©\ºÁZ.—Ç\ÒT¥5¼*S.—Ç*’Ù¶J¥’õ½b˜©°|3ÛË8³­°l3ÛË8³©dV%8££#¢Óé`0 P(àñÇÏzX ³X¾™mgdÜqèº>ö™$I¨×ëp–e¡^¯OìW©TÐn·–eÁ0 8ŽQ¡iTUÍúÒ˜vA¶™Ý†eœÉ#™¬qñîûûûxú駃„ó<$ 3Ì"°|3ÛήʸçyŸ®ë¢R©@Qxž—XÔͶíàûµZ Ýn¢(Âó<”J%H’I’²¾<»+ÛÌîÀ2Îl ™¬I ~H˜­…å›ÙvvMÆEQ ÏYp]7ØA@³Ùœy&;vM¶™ÝƒeœÉ¹5X†a&ϸ®;,ËràEMƒzüíííAQȲ¼u}ÿ†af°ÁÊ0 ÃäÓ4aYV¦c¨×ëSÃug1V‰n·ä»êº×uÑn·9$˜a†aB°ÁÊ0 ÃäUUsWHűÂJ–eÁ4Í™ÆI†­,˪ë:LÓD³ÙÌúÒ†a&7¼.ë0 Ã0Ì6@Õ~gÁó<†1ñ¹ Y_Ã0 Ãä ö°2 Ã0Ìض+W®¿Ë²ŒV«Çqb·QEaP¶mcoo/0r=ÏûÃ0 Ã0l°2 Ã0ÌÜȲŒáp8÷¶ðçÍf®ëÂu]‚À¹« Ã0 ¬ Ã0 “áÖ6 Ã0 ÃLÂ9¬ Ã0 Ã0 Ã0L.aƒ•a†a†a†É%l°2 Ã0 Ã0 Ã0¹„ V†a†a†a&—,d°6 ܼy’$¡ÑhàôôF#ëka†a˜KÃó<Ôj5\½zW®\AµZ…ã8+=‡ã8¨T*c?º®Ûèÿq¸®‹J¥˲&¶Y–…R©„+W®`oo¦if};†a&–¹ V2PËå2ŠÅ" P(àôô‡‡‡Y_Ã0 Ã\ •J‚ àüüÃ᪪¢R©¬Ôhõ<Ðn·Ñn·Ñl6aYÇçy©ç2MžçM¬®ë¢V«¡Õja8¢ÛíÂ0Œ•Û Ã0 ³ æjkÓï÷qrr‚ããc”Ëeôz=~Ϲb±ˆ›7o¢×ëa?ëëb†a˜µaYA@½^>“eõz†a@–åÀ ô<ªªBQ”`_òhÒçŽãÀq¸® Çq IÒØ± jƒC†ì´1¶Ûm”J%¸®´Ï¡ÿÓï‚  ÙlÎtL†a†¹læ2Xïß¿(—ËÛö÷÷±¿¿Á`õ51;Œçy!ëa0ÌZØÛÛC·ÛÝMw]ÿ' I¢÷ƶÓ÷Eÿ'ŒãqÆ[èødTFQº®CE˜¦‰v» AP­V!DQ„®ëh·Û|/- †a ÕjAÓ4”J¥ÀÀu]w"ôW–eØ)׿8Np>EQ`Y4M ö|yR²,Ÿ1 Ã0LÞ˜Ë`- €Á`üŸ Ç•a² V«šÍfÖCa˜•cÛv`ÔÄyÞ¶×Íøœ×`•åxƒ5Î8Ž;~AO¥ªªQ«ªj``ʲ ÷âø²,ò,Ȳ QƒïOó¢ÚS®Ë²,H’Û¶!˜Á ÝnŽãÀ²,èº×uÑn·cp†a†É’¹ Vò¢âöíÛÁçý~wïÞE±XŒõ¾2ùÃ¶í±°Uáy\×Yé ‡©-{=äQ°m›½ÌÖaÛ64MƒišÐ4-ð²RØéÖ˼,û?ó²ˆq¯ªS¿"ŠblΧmÛ±ó_Ø+îy^`p ‚0õo'ŠâØ"…«)ã4M’$Á0 þ\KómØp¦±êºÓ4yÁa†És¬p|| ]×qóæM@§ÓÁÉÉ ö÷÷ƒ#“LÓ„,Ë© Ï¢Ç5MgggS¿ëº.öööpvv¶´Ñªëz ÐQþA9daîÝ»‡W_}u¥×Î0ëĶm´Ûí1/«çyAH©®ëcrÿüóÏg=ä­†BÃ^TÏó‚Ï(• EBòÀÒ|•Vå7 ÇqRçL˲ Šbv ø(äeõ%þÿééiÖ—ºõH’„³³³ ŠC’¤±¿'E±¸®;¶hFù£t únø;aãq8Æž_–åÄmQE3b›Íf&,ç®2 Ã0¹eîÖB¡Û¶qpp°ôÉ;®]»ôsÒëõP(·3‹#ŠâÊVÓ4Ñjµ *•JêwéÜ”›U«Õ&V÷© }7^G.µ~ˆ*‰ä­È2‹å›‰B2ÝívašfÐ Óu]˜¦9æe£)€/ûacƒ¼dY,ã>i‡¤ZYÿí񮮡l3ÛË8³IÌ]%øèèFý~?ö;GGGSszzŠF£„—ËeÔëõ òp¿ß‡¦ic}^9?vu„Û¬Šh'ªN™TLIJ¬@‡î ‚ô#$%Ž¡ªêÌcβŠ*Ë7“…dRho­V Â2E‹(•JÁ3dÛöØâKÖ1–ñ鬺>s9°l3ÛË8³‰¼nÞîܹƒÁ`€“““ØŸi 4 Áq<÷ÜsÁgás‹Å`{¯×ÛÎ,‡çyq9­5¬D+VR«À7÷öö‚œ-`Ü`T?¥ñhš†³³3Ôëõ Tn<,ß …YÆ}nÛöØsÒl6Ñn·Ñn·' œf³‰Z­–Xu6+XÆgƒ½—›Ëöv±ŽÔ§uAí¥*• öööðì³Ï®å<,ã̦2·Áö~ÅýLƒŠ5QHq¡P@¹\<¶ý~N·nÝ ¶p1ˆB§¤¶ óBý!ÃÞT*êá8ªÕ*Z­VPÝ”r¦ÂÊœ,Ëh·Û¨×ëÐ4-W ú<°|o>‹(9ŽãÞÒZ­†J¥2ölQõØ8Ï’Q#IEA­VËUË–qf¨–À&À²½=†‘K¯`ø]Q*•påÊìíí…*[­ÎÎÎð裮åü,ãLxðàÁÜ:殼,åryÂHºÿ>Þò–·ÿ0VÔi?1™™Ÿ°q¹ «®ë±¹¢²,…e$IB³ÙD¥RmÛ,·–ï͆zQ’ÌκeYh6›Ás@ 5ô’¯V«eyn¹§ê±y2XYÆGÄåêSn1U ÞuLÓœ©×l`ÙÞ.{¡„ZúÅÒ£Úu¦iZfõ5XÆ™¬±m·nÝš{Qf!ƒõôô¶m£ÓéðY–ç.Ätxx<O=õ¤>ƒÁ ˆ±ò©O} Žã¡L2äA 7•Ÿ•hõRêy§Ükš6Ö£Ú@ÔjµL ÖN§ƒ~ðƒøƒ?øƒµžg•ò Ÿüä'Ñh4pãÆ ”Ëå îÜvã8ÎXåêV«+׺®/|×uƒÜÓ°’"I4MCµZ zn.*óá¼ÖYi4x饗Ö~Ïv}·m;¶J¯çyÜÓô i_¥ÁzzzŠ_ù•_Yë¸yþÞ\ÂzÊe,ø¹® Ã0 ª**• šÍfPÇÃ4Í G½^Ÿi!”æï~¿¿Ö‚G»>3— EY>ýôÓxßûÞ‡·¾õ­sí?·ÁÚh4prr‚ƒƒƒ d`0àÎ;èõz¸}ûöÌÇzüñÇÑï÷qrr‚'Ÿ|GGGAx/•JÁâ‰ã83{8WMؤBzq…e2ng1@Ép Š©ËBϰªªk+Hò½¹~&.$=­M˜MòœÎËønašf=øsx»ÝN ]§ÅUú×¶íÄ® D½^R¬ÖõÜÌm°îïïã™gžA§ÓÁ /¼ •i/‹©1ñÔ̘Y-®ëN(®ë+ü”s•¨ˆ˜ÿ^NáÊ…å;?8ŽÈ7Uce–‡e±-mÊQmµZAd åÿ~»"òV’" ËòØÜ{žœ°á©ª*ªÕjªÁJ•§…øÚ¶=f°.L«üš¦Á4M|ä#Áw~çw®åž°loTY;n1RQÔjµ@)ït[ ÒY`ß~,Ë BtÃ*…ðƽ_hž%=‰" fyVÖ­[-Ô‡µßï£P(½–:'eoqa\­V+ø\’¤t¡s°²p9†Y7®ëƶ§a˜Ë¢Z­B–å ç-LêØ¶¨¾›VP=©%OÔÒ† 0èEŒ„pä,ËPU§§§øÍßüͬo“ÈóE/¸®x—vÙXe¶Ïó ëz¢'•æïhD}6Í›šs¬§§§¸sçÊårüä“O¢ÓéàöíÛ888Èúš˜â<¬s ¦ 6X™Àó¼ ï‚U& DQ <¬r'‡´PVÞEAµZ LEQ¥†rR©òê´c‡¯wZEú0õCãs]w,Ôð=DëìÃÊl®ë¶íÔT¼={ ³º®CUÕÄp^òªªšú<4›M”J%¨ª Ïó`\×XÍ!s¬ƒÁF·nÝ ¼«p||Œ“““ÀeOk~Yuw†É+TÑŽC€™,!¯e¡V:aE žŠP ƒ5ìyvMŽãŒ­ÞÏZx‰ÂØâ |0Lq¹« ³mèºÔˆël@‹ô³xHAj)~í…¼×ö˜«­M¯×Ã`03V‰[·n¡X,IÜL>ÉëÊ Ã,‚ã8¨T*á‰Ô;o–^‘ ³«Lóx†‹tÐ÷I!5/5\d ð=¬ÓLu]‡ah·Ûl¬2S¡Vžçñ\Ïl5ÔJ©ÕjŶi¢©š¦Í5IFêÙÙÙFõÔSxæ™gptt„F£‘õõlŽãàêÕ«AX¤ëº0Ms¶Uïâg•„CŒWÙ7õ¢ª1³{¸®‹J¥A–ʯc˜]#œ¿š’$A–eŽ„`‚Ò›ºÝ.Úí6Úívæ2Í0—«ó3Õ`ít:è÷ûc¹©ƒÁ½^AïÕƒƒ t:¬¯i#Ñu=0L ªŒjYjµZÐgo&¥ÞÄjJ‚ /­Úàç°ZˈY¥Ri¢mÅ*±,+è3Æ /ÃÌŽçy+-Þ´(´ÐÄ0‹f˜ËÆó<6V`ªÁÚëõP.—ÃÀX~ ÞÎÌ•o×u=¹Öu²,CQ´Ûí±ÖSq°£rm7àâ_ë1²™¹¡‚-ˬÕjuâ3𬩰+, 3;á¶œ3Êl Ô~/ŒmÛ<ÿ3[®ë¸zõj û4sõëù™šÃZ(0 Æ>£>¬l¤®òœŠ¢8VŒ#œE9O3³‡Õº `£V9ësè1s`YDQ ZÊ,‚išAp%S]×!Š"{Uf žçÁ0 xž,`Òbæ®4‹g6jSøŽŠs]—•vfk¡xív;pH…ûr3ó1Õú¿¿^¯‡^¯À¶m{¬Z0€ øÚµkY_ÓFaÛ6<Ï š­·Z­ ¯jîòù6ÅcË, µËð¼ÅÿèTí1¼ªN9Kl¬2L2Tˆ¬T*ð•|Û¶qõêUÜæ‰ÙÂmjE W˲ØXe¶šZ­xRÉÅÆêâÌd°–Ëe¢ÑhàððƒÁ ðº«ë:ÊårP5˜™ Ã0Ƽ§’$áüü|¹‰¼¿ˆ‘¾âÁRôY#è*pBÇf£8sȨT%QŸÇqÆúSõˆd&ž°¡ÚívQ¯×¡( šÍ&ÎÏϹõ³18Ž3Ö¦FÓ4X–Ïó‚þÀ ³˜¦9‘ÆW¯×ÙX]‚™ÚÚÔëu4 ´Ûm …±LO>ù$NNNP.—ç^õ%¯-+n{¡PØZ#øŸ|ï?Á·ßXý¤-a=Uw×Õ^o° Œ5#6U¾)¯HÅ…sXMÓ &jUUƒÕt˲¦öªd6‡M•ñ<âyJ¥EA·ÛÍ_„ÍŽÁ²½<¦iBÓ´@–I7 c¢‡0sù°Œ¯Çq‚ڬ묞™ V2Rã888ÀÁÁÁ\îë Åb†aM¿ß‡¦iÁÃ$ËrF²-X–…·6ߊÚwÖVp‹021½×ªsñ³ª…":Î"ú™ ß8ÏÑ¢Õ¦Ëwxå{‘¢.´zNÊåÝéºEQXß6]ÆóâàølaÙ^ Ñ÷¡iööö8Ò&CXÆWµ©Q²,-Ô0«a¦>¬€Ÿ£Úh4Ðh4ÆZ׋ŹW_Q.—á8ž{î9”Ëå±°Ø;wî X,Û{½ÞVõxuº®ãýï?ÞøÆ7®þÙMj+ã`bìaµÅ‘†õ¼^\wÅcY›.ß ø+âÎ;+q­ (lîâaL.ÙtϵZm3 )¹.P©d=Š•Â²½ÂQ6aAÂÜ™l`_-á65õz}¬°³:f2X)wõää'''A>ë"t: ð½··nÝB¿ßG¯×C¿ßG§ÓÁ­[·‚ícs7×uÁ~ë[ߺÚ\PbÑ÷@šG6œ[*aµÍermmŒò_“Xƒ;‰M—oÇqƼª¢(Î]x)Z𽬭V‹'ñ-`Óe<†J¥ô×öÿÁ ÿ‡cê÷÷÷ƒÐ…M§V«¡^¯û‚½®C‹“ižÓ°‘*`º‘8+Ô3–XÄxMÓ—lø^ãÈw®ÿàu\ÿèõ]ĈM—o˲Æ I’æ*¼D9¯ÑPâp&f³ÙtÏ–e¡Õj!ò›Ë'ŠÀ)i,Û«Þ#¼@™?XÆW‹®ëaó¢c6©+…ÿÒj €`e†âÛç¡P(ŒµÄé÷ûh4AlÚC‘f ¿øâ‹xöÙgqxxxùwqF(´2…‚»(a£sƒ8)Ä6j¤šs×@¼a)a¼g켋õ¦¬Æîóéé)ÎÛçøðï|x”κä^zé%âôôtåã&¢}ñA˜«ðW~̇‡‡¸wïÞZ޽Ësø* d´ˆ³¹N g[”F£»wïâcûØJ»éówVض½½=ìíí¡V«q5ø%¡ù{{<¯ Þè蘌8==]hþž9‡5œ§^™Y”Á`€F£Ç{ år9(ê”ö@>^zlëB×õqÁ®cõù—FÆä¼Êlâ½§6Æ+Ïkhۘ̀^$‡5maËŸCß988Àõë×ñ¶Gß6çÉfgÕò ׯ_Çññ1Ö6î¨Á*Ëò\!ÁTa˜É–ããc<üðÃk=Ç.Îá« .Ç{£‘¤K7XŽŽðÄOàK¿ôK×rüM¿³€ êµZ-œAQ” ð ³4'Uï]</Žã8¨T*eÍfsó/™ƒƒƒ…æï™ª¯š^¯‡;wî P(à©§žš=HbÓJkS/JQaš&$IšŒq_õÂ̲aÆIïËåÛº ÇÐ/>K:¶y±-)YDºÁêb<äø‚7~| Å®.Ø6ùžÇÃê8çqìÛ&ã—õ8Þ:e~Î<÷<ò=;”M}V‘sëä{Ë`_r>±œ_.™¬š¦­è„¹ví?LŽðÿ7˲`ÆXHåDO¦«ÎW|b£ö0:æ3ˆeø^4¯t̪Ϙç¦ócJºŽöÅv“mqÂrø^xÀg¾ð3+¾À›*ßÑ‚K^ ¯"Rx»(ŠÁ>[ç9bÙT¿ ¨Ÿj\/Õ¸‚d®ûy¬Žlɳϲ=¶mömî5¹°Œ/é>l¬^>3¬qqéFO>ùäØgÓÂlÛF¿ß‡,Ëcíq \.£X,¢\.ãôô4È•µm• *OmkÚívzK ³õ=2ÍëHÆÞ¼ù òű-L7XçK2ÌŒW5v#×5‹d#Þ¨¥üUú蜯_›ófc“åÛuÝXy¥ÂK²,ò,èºÔ æØÔþ†'ñíg“eü2¨Õj!¶JªišÛ¥à[Ðín‡•e{vjµZ­VÖÃ`æ„e|9 Ãàö|1Õ`½víÚXÁ%bÑØzJ"3€©éÑуòÛ…B?þxÖ÷j&Âý˜RUÀ÷V0¿ÁJ…‘¦Uê7ÜØ¹8fœ1ºÎ¥¨qÖ}ÈˆŽƒÂ‰“ƾ~£{&¯<üÊZ.e“å;)œW„`[t!FET«U´Ûm8޳¹ÕN™™Ùd_7¶mÃó<´Z-T*•1ÅÆ¶í ØÒÖ £Ÿ-€e{6t]‡¢(œþ±°ŒÏGX/bïj¶L5X‹Åb°Ê² ŽŽŽ¦oO?ýtð`…+šå]סªêz'rªz;í™™wUIö†9ßžxâ‰Ôïݺu ý~?¨*¶éèºÓŒOž´,+¨Lqîs«aæ5Xmø†ZÒ"g8*mž…аáwÙÑKSCŸ¹ðD3á¸bäw‚ Ý(æÅç´ŸŽÉ¼]ÉhÒB¿yqÿfɉÝ1–_†ÙA(<²^Ÿ·wØQ¯<¬¢èab¶Ïó`Y+ðÌÖî!_¯×ÑívÙ»šC¦¬½^ÅbÅb1õ{”¿: ²¾¦•àºn¬Áê8AÂ'eYŠj,¤ð'y&Ó_ÀhÂy¨&¾4½,-÷5ì •1n ÖŸûj\|bÌx¢Ö°Që ÞXw᫜Ã:‡o8µÚòÇ`f‚òV9<2Ï[‹aPU•eÙZlÛ‹„áÅû|2Õ`- xðàAÖãÌê£Ʋ¬1Á¦ïÌ•¿ ø9—|ãjß´0ÙJèw㡃Q¥Ü44L÷Ά DÒUâÆ–æ MB½8¦ú=®køÚÂáÏI4…1óÂÙl¬n8ìݺ4Hg¥&„ .¯nä9­ÕjØÛÛƒ®OæÑ¸®ËÞUfëpCsUØ»Ê䛩ëþþ>ƒÁDuà(Tp©P(d}MKã8DQ úè4Á‡ VEQ`Ûöü9€F¡½óØ dp˜4>£á·Qƒ5ÎsÞ7ì ÇÆdNh¸ênûbŸ¤V!f >Ïð f 3N"z.#lÔ˜%ÈÃË ÅcL«Ì䜫W}—Ü_;´8É |Iš]þXNsa>ÓívaYÖDÝ]×w;ìÙ:LÓD©T ŒV6X7‡™ Öýý}hš–î; Ðh4P.—·¢µ …Gʲ Çq‚L•Jš¦M„ÆÈ²<ÿj;ÙÁ᪸³@…š<ÄŸQc,š3š4L ã9©³TóéfbdæI C‹ïÍf²,C(ŠÃ0‚ïËEØmÂqœ Ý=l°n3U ¾}û6úý>nÞ¼‰ÓÓÓÀÛÚï÷qzzŠ›7o¢ßïãèè(ëëY á4š¦Á4MT«U¨ª[RUÕù'õ9ÞÙッoxÖá{"ç9O’繆)§é!&F¡Áqß‹.Ά½ I†ãû{ÀÙùd8s˜¸}+˜‚¼ãQkqyÙTõšÙ@Ç7V Ö% c´T*í ¢†EQxqðeÍŠT›Å묪~øú,†¨i¥Ëõ‚ضX8’d9¼ø®iZ`¤º® ]×c{ 3Ì&CÅòTUE©T‚$IœŸ½!|Ö,_ÚßßÇññ1Flëšr¹Œ£££­ð®¾Ç‰xEQ°··EQÛ$zW+ðÃeãÐfü^=å»qÆXØqìazÒè³›f膷Åé+Ñ[£„öK╟ŒˆK5¬ß˜ˆ¯®Lä4È9všZ­D£\VÂ瀌Ä<à8¾±*IœÇºÔ4¾ÛíÂ0Œ ϔ뺰mÝn7ë¡æ—´ö>¶=ZXQUÀ0ü*ÃIxžÿn×ß'ü9+—3Cù§a…œ¼JQY{YÇA½^gEžÙ*ÂῤϳŒo3¬ÀÈh¥Ö5½^/.‹ èt:(—ËY_ÓÒ„óQA@»Ý^¬À†}ñgì-šEÃpà{6Ãï|“FédÌ%-l§Í’ÖUŒ \5f¿è¾|£5ÉÃêyÀ[ß:ù¹_é‘eÿi<ÿÄB®Ã!0Ñœlfj5 ÕÊGeTÏóŸ Iò|f!Ç ø¸b{®ërØXÛž]þ=ÏfÎ.VJUÕ÷œjZ²ñiY€¢Ln/•&XfêZ@ó}x±=λJhš,Ðó{Ù6¢ùªÓzh3ùbfƒ• 7Ñ—w¯×Ãááal(Õ¦³–jáÐÕy#d Æµz¡ÏãÎãøãçùƒ˜ˆÓucŽáD¶G+„¾þ^¸Gl\ËëbŸ¤âG¶ ¼ãþ÷$ÏWPøÅ÷·Oýíõz|¡*¾škDÄâyTU…eYAÞªišÛå5ºz8¿7zŒUÀ÷°ª*Wi]*²Gˆ¢8ñãÂd1¤ÝÓÉ£ëús8!þï¦é/´¸î¤wÖ0€vÌ ªªúÆ/ç§.Y©TÅÜqœXï*!B×Ê0ÛW¼ÞlfÊaÝ%¢ÊËRhˆ÷hÚð«ü‹¼⌽¸¾¦”Ã*øºÆç‰÷®F/?n¡Uº8_8EÆÄ¸¡+Åì«øWÿ<ÙÃê8ÀÞÕ ÃW)2ªÜ9ö V'¡€ùZí¤tS^6åjoMHŒçÍW¤e‘Å5 mÌ ®;2Ø#²Ñ¢¢(N]ò< Ö0I‹#¶ ìíùÏ–,~¢J"å²Úöä±è‹»ßšæ^*áúþ Þðê«Y߉\ây$I Ò?,Ë‚eY3õNò¾2Ì&C‘“,Û›ËÜÖmg¥SÓ<}‹œÂPÅȸœ§€¢ _‰øÊ»ó÷FMº¾'”Ç%Œ{T…˜óȪ‡ÀÉ7Bqò˜Ž4ÕÑý!E‡ ï¿÷o€ÃÃQeÔè=eïj*¢(B’$”J%ÈïJ:…Ï ³î[«ùÞúyÎ㺫 Gô<ÿ˜‹ÁṊÛO,DšÇ‰ààŠÆuýPÞv{z‚(Æ{Pÿi¡zõºÿ^ø[ _ðÒKY߉\n½DQ)½‰^˜]IJ,î½á°‡5B¸BðRØUÏ]Ùààe†áÿD Ö´ÊÃ:€þ;€ýýÉq™XÌ3¹‡qÃ;Ü 5i<ü9à[?ýb»³0*´%."P¼ØOuGð Ìyì·´ðam´-ЩÚpÒ~¿ú«Àÿõø1$)à4 £ÂN³@VtÌ$õæ{÷v.œ,¬°ˆ¢ˆz^CH=o~Cš…$Oþ¬û­¢ŒçùÏr«•|¬ZÍ?×<÷ò|cüÃ^n|;€eY±½&EQ *J®ì°-¬Ó Åü4Û <Ï æ÷•ÖáØ0\ן2Û³¶ d6]׃¼ìJ¥ÌÙ•J%è·Êl+ó° …­hi³2D¤çT¦éÕâóSÆ®(úÇOJ8jsl'f<•‹ÏgìÙ*Š1/tÌèx<(¼¼íuñ…¦!9L‚ï•M*ÔT©Œ<©–T«þÿÃʺŽ?ŸWcmM„½«y%ˆè!¯ã¼ãgŸEóFI\…ÁjÛ~H¯$M¥FòJjfñÂêúbù¿;HZâ°‡•+3yÆ4MTé}‡ÝηvÝÅjé1›‰®ëe9(0V¯×Q©TP­VÑjµØXÝ2¦zX©ÿêºHëÝÚëõP(P,ç<êb¬teÒ„ïeÓ‰%Œˆ:|ŽÞ1*|ƒ/Ö¨ÃÈ0 Û½ø‰îC-j< ¨_(ÙÝG\Sô÷i™mÔËÝq9l°Fç òü80ìxE=‰¤¹‡~ʤPϸ¢ ýÿ~ýäŸ|á…ÙϽ y‘ïMð™f¨nкǚ¥0 Zº'Ø„l;} ¦9’aAðçåà¶v‰V^d|VÇiš°m;1Ê@–e}mw²Bð¢[Æ&ȶã8p'ˆpggu×?“d×ÙÃu]ضvÈ®( Ç¢(¹×w˜ùÉ4‡µßïãðð0öó›7oâæÍ›xì±Ç.­oÒJ Vj[—æ¦`Ò@Œ¶ƒIšt_?åÐýÐoŽBkMć٪7Ž% xÝo'î\uŒÂp“hûǶ,ÿÇ çÂÆåÅR«ÀÕ½ùs=$·’e¿1ýÙ™ïU[a–$`8¼´jªy’oÇqrïaUÕ ‘ <ÑÅ/6Qk EñÏáºþ³´²<ßr~t\q•®Ã˜æÈ •¤QEa"®ÈDZ”ÂÈ“ŒOömT*èºI’pvv–Z„ƒŠ.íœÇÊ0&e«VÛ¹Z›"ÛŽã ÛíEgv9WÏu9z6EÆã°,+¶S½^gcuK™j°v:‰?þ`0@§ÓYø¤ý~¶m'>wîÜA±X„ã8xî¹çfΣ]–•*&ô¾°0iFßûuøù €ïm3öè{úÂ(þöç>{dPzHn•ö¼ Pø¯GÛœ)ûEm]ŸMEßÁé†ç¸ù‚¼ž*€?ÿÖ‘Á̦ø+X¬gí%“Gù¦¾|yF–/Ä¡^Ÿß` ÷`µ¬Dy2Œ‹MdŠââÅ“Dq¶°`ÏóþZÍ q&æk;#ïjø>EoYÉ„ª.æ9ž“<Êx¥R –e¡^¯£ÝnÏä’$ žçí^…`׌|¡0ý`“d›rW©]™®ë;k¬þ«#îÑæ}ÀfÉx–eíl$Á®²‡õÉ'ŸŒ]•™•N§ƒÓÓÓØmý~N·nÝàçÆŒ¹ý×ÅÊZÚ„ T É SKÙ—B“žC Aà­­‘a˜BlÃ÷ö† Ï/~Ûèÿ€¸Iò®†I}ö"«ïc¸î7~º·á°OÛö•ïYòó6ÀXò)ßy/ÄaÛ¾BáºÉÉÕ«³ÀqÆ=¥ FFlWš {Ndy4ð´qU*þóÚíŽòQ“W©Œ…¢/cEU–e¿XSܘ.áïœGOÂ4MH’„f³9×ü.ILÓÌõs³l{Üó¿c9Ñ›$Û¶m2­i ÃÈýÂ亡ˆ¯0³–Ø6IÆã (‚¼G1«%“àƒƒãèèhbÛýû÷ø¹³Äþþ>úýþÚǵ²Â4a¯eÜáâÂÉÉÓF¼‘ ø}OaT¨å­ç³qNÈ‹ôÚãÀ?þÕÑïqcôb>7Måu:ôE§,øÄ'€ŸüÿöEñ—4”,ûÇtÝK Ó½ ò(ßyÏÃ#ΘÝ8âö®ÚIb?¦…“pÈ®eM±Q‡*šÆ¬¦éŸµš/Û$ߪšœ‡*Š~Ž,ýD¯_üÏ›Í鹬k&2ž„a …´ ‚0fìq¹«QvËÙ$Ù/²‹¢MÓvK^#T«£za¨~ã³I2‡i𻕦ÁÈaÖ´‡b­s¨`ÁÊ{q!ÀaÍó|òÛÝ)ïŒÇAŠÍ"‹5’$ížÁgœR5k&W² Lê-õz=5/{Û¡õqSòŽMà “7ƒòW™Íåó~åWð•¿ôKsí“;ƒ5íxðàAâ¶_|Ï>ûì¡Ê+ ™´12X%Lï{Jß±áªIû…#2Dxùeÿûi+à{bÃ×ö]¯ÞñL¼7<¦°aíº£·@$Ñó8Œÿö“þç÷¾Ê÷Ć=KI4›‹WY]ÓÓSܽ{7(ªr™,*ßðÒK/áðð01”'‰¼{Wß”$@úò?}(3…êš&à=ÿÑñ–31kðçþ­ß?®,ûáÄá>®$ëº>ŠUžçjZ¦9‡‡‡¸wï^&çÎjcQï*0jw“÷gg ×]<'Æ#hÑ&g¡wFwïÞÅÇ>ö±K=oó÷48,rD»í‹jø‘u]ÿ³Ö J„æï^¯wéçÎÓüE°Üo.§§§øø?ù'ø¿ÿûsí—;ƒ5†%­´ö»Þõ.<úè£ ·àqguV#ïdÜ3õð½RCŸÕ_¸(Ìë£ó¥MÆú¿W8¾êpÞMï%©W$à+ÿÕ*”¿s ¤äüÛœppp€'žx"ÏÉ¢ò ׯ_Çññ1æ:çÊr³×)â+Máêäùœ‚®ÎÇß9®¥Äº´úÞ~Ý·Ž?‚à/´Då»ÙUä®V7*,òøø?üp&çÎj²ŒwªyvÆ š‹FTDóU©wÎ8::ÂOª+³(áv»€mãåw¿{îݦzX¯]»†[·na?ø)—ËŸÑϲ‹E”Ëå±°ꟷ.Rû–Å_™ÆXÆ 8ñF©‹ñv66Æ« [þà¥ñ¥CIþäOâ{½†¡ÊÂa~é›üã[°·”J¾'iNãÆq¼éM€ L´‰\†±]Õý²’ïÔI]ÏtéỷJnP µxRío}n4&>!,¶ ýSÿÝ\©±Ì|d!ãq¬¢åFyWßXP”ùr¿ÃD•&Qdƒ5D^dXqTØ* Šnß^ëT@}­éÞOlŒ‡ÕugŸý¯—?ÐäIÆ‘œ7›M´Z-hš–¯p`ËZ|¾%jµÝª æy ¬S=¬Åb1¶’Ø:9::Âáá!:ƒ …üñµ/Ñ»ªë‹•ô¯/Ùy]Ó¼¨acV‚ߎ&¼í?:þýz}Ô~&aqÆó÷ï‡TœT„‚,I~a*ªT­†JþbT•Éǧ[G7VYð×uýcnÓªèeËwbõk*,Dm’2BGÍÞþ¶ú{O™ÄE¨ÿå óÞkãÂù¨=Z«ºˆú×| xã;'Rõ˜ÕrÙ2ŶíÝ-ÊA¡ôq •ÌÒd-Û€?§¯bAf!HA‹^ÈpR £ôßû!ˆÿɶ16ë…§2;dœGH’´ÚEDÛöçÈeŽéºË-ÔPF#!…zÒ¯cnˆÖúXEÁy§¼ðÂ\»Í¼Êårlá›ýý}<ýôÓAÂy¹\^ë8b Vò:-z•¹€³‹ÿÛˆÏ7maÜ£*`Tt‰ Þ¤‡bJ$Aõ×þ{t!LFÿŠ_’Ô4ÿÇq.*Ùxñ/¥ð0c ¬’°í¼iäA¾]×—oÏóËå*Jæ«a{YüÚÏ_ HZý¸Hzu\’(Býï"‚JÛLÞ¯½ù¯ÃþL/ykȃŒÇ±òê¾4'.b¼áJíÓP”ÅÂù”m×ualÛF=«VpŽ3¹˜ƒÖGÑÛdÀßû‡Ðˆ÷~.É×T©çç™^!ËÀ×}Ý<ºÖóäQÆ£¸®»¾ÅGòŒ.*»Ž3Ò™—ƒ¢¬Ny6Mî_uØ4õº÷¼ÌÚPÎ\t©×ëAÓ´@€i¥#ú³* …Êåò¥<(± ½eÅ+'áÜ$¢»Eí¸Å‰¸|Òpx°„ɘÌk¥‰—+ͯú§“çÓlèJ’í­ÖÔ•”p yY^mdé&V÷›•Ë’o]×ãË òÝ’B¹«Õå ŽÎ„ëÂþàøç·m_öãsaœÂM2^*¡vë5@áŠr²ì) Ðn£ýéG€vÂ/É2ríÒ8;{$Óó_æe¥i¨å‘mgò85e#¬4%…›¦ŸþQ©W®W¯úÿŸå½Æd%Û•J’$áìì,»‚p¿j‚^Ö~4Âí±­Ö0h¡'¾}¼³(®.ÿh“*<%…Œ»®;Ñ‚o­E#5m¹p^Iò·eÞ ®‹êýÿ¯ßé`PWƒUËŸ$ggþ3’Ñ{p&ƒÕ¶mܼy½^…B!øüèè·oßF¹\F¡PÀsÏ=—ÉE,ËDheÁùš¿ÿ÷&á6Ÿ;êa²*éÜÆ 2¾—5Ì›ÿxâÉÑ~qBRÇȰ¥Þ ŸÂieǘ|—ÈHo…³ « ¹Eßf&Ç3¶mÃó¼xÅ&”äO‘ïÁç†ÃðõÓ\³ÑZ©Àø_ñŸµ‹ÆÔwÓEEj´Z@»|×4gïHÒÆë3ñüóß‘õ2ž•ä9™¦oÐQ¿Ý¬&"×õÏ´²mYãj´ª»mûµ 'xv0ú¥v;³sfv¨:ªšµ×œÎÃnÜbú%VáÂÿWÿöC¾|Ë2ÄÏÿžP‘~Ï·eùsF¥2®³ÍQ£ú—^Á£¿ökÙÜÈ 1 zhñlíaï«Zdiµß·Ù„ôþkÀþèjÆB-(×Q¨Cüg)Ü£þ™É`½sçdYÆ3Ï<3V)l8>>Æ7ðä“OfrËðOÿéÏàÚµ[ã¶ eÁzË__t–¤‹•vø!¼QÅ×Áxî)à×ÃdoÓ06&+ÿÇ_>ùÇ£bLq-Ú74Ðná á®;æx]äxßžu`ËcרÕjñUR©:…(Âóü¿_ ‰"¼Þ'`šþ¼Ônûr´–ÜÃÊóŸørs‘ÑX»ƒÂ˜5Í4QDóä |}#íÝCĪWQwaÕ¼ç=ÿ{ÖCÈ„•yWiµ†æTU½¼•Çñ•*Ã7@ÃÛèûÑ7¡ÉXüë VMÌÆ‘›66­–/[á —òï2ò,FßOáÎÁ»MU!?^Lÿ‚/‡ RIQ|O”¦ùï+z–ãžQÛö¿Štð¾ö[àýÛWßð†K¿Yã8ìмv)-ùH§_öK i€ðçߺšë¡çsÞk"9öü’džÅ×õßa{{Ky@¦¬”týÄO¤~ï‰'žÀÉÉ úýþƒ¹L\¸uë5üÝ¿ûUØß?B­æßKëäÀqP?yG|­!¾ç4ªÈÇÍu&ÒÛÙàâXá‰Ôó€ßzø¶ÿb”ÿ7‘†/d–å+$¡Ù˜BãÑÇ«Vª£6´ ¬Î¸©V/JÒ§×}bbÐuТĝNšfpC-ktok5À† ûÿú“ ›… ø©4W«£w00*´•2øÏ=χ¦Š‹°­ Á¶ý—JþÌ~±C´ÈFš.=æ2:;=nÑˤN:yáÚµ{Y!Vªä„ƒÕååè åÅAÉû¦é¿˜ÆV•0ÊQ%E€Bü“¸Xàa6—ܣśð3FÕ¤/<ý—]Ü(\¸~''SøS”)ª.¬PëzÄ) (¾ñ@FS¬\7xâüÜß.ËpþîO@úÀ üÛ/ÿò˽‰ã8DQ„,˰.^°c°.5"YY$Û¢•âuÝ—Oê’F³éøÊ•ôóxÞøƒÑn/UWaªÁÚëõP,'z0Q0AÛïß¿¿ð`. ×õÿ&/¼ðCø‰Ÿx?üÃoE»í/Š)ôûþVáàçªF¿×¶F€o°–"Ÿ‡µýhˆ®aãO[o}7ÓÒÃÜnM†–5¹JžüU*Õíöøï«\W ÞÆ<ÖubY´ÈM£÷#€@ÆÃí¿4í–ýª{PäxEºÕòHÇ—5J‹›»(ù?i¡EQàA)7¡~c»PˆËÙÙØÊ…aŒŸ/mÞ ·<&åv¢5BöÿZ¢Á²€ÁàíY#Væ‰ZE5D‚Vzöö|Á%a¤'ª Ð*…ïÆM´”[ LÌÿÌv‘U Z4žÊ…µh_© òÃÕêlΚU-þŒÔ«èøS¯'MѾpÿÝ ”åÈb¦$ùÆh\¤å<…;2È2ìÿÎ\[ ‡¼_ŠÁJ‚@s鼌)T‹CSœ¬.ÅÙÙ|߯×ýŸn׿¶½=_¶u}r…^Gi%Ñy‰r©^EÓ–^4Z%¸P(àÁƒŸ¯ðÎ^.þê›ïùQ”¿=¾1bý[–ÿ„¨KðK¯_Ÿpp“Å“$ø^Ö¨•rñ&Žq§Ùí:ü0b×;HXñ{Wƒa\ä‡W«‹ë7¤ø'í»Êôš°ŽF·$ Ìy‡&þhÍ954¡¹£®4‡Ðûº”z³Ã‡ ÿ½mÛŸ| ãBÖ,cÂë`””Üíoø}MJ**ÐGèzza¼U(T›ƒ;Ïó¯·ÛÙô,1 à«¿úÕl‘ 篚¦/´ó*G¤aD“©£óz½/´ú‘vÞ$aZuH&·Ðœ~™Ðòïÿ þ¾áG!(F}ÑûRzý‡!_ù×AwJË {fÉKJ¿·Z#çM˜¸º’¸¿õgÃýëÒŸ†z?ƽ0êõÉg²ÛšMx­6ìŠã¿ïoþ=ÿ…§(ëVËxÊ’|Û ¦´Ð¨( t]_801¯7­’Ð5|ã_Cõ¯þÙ\¶¯ý~ò·¾þâšû§,–°l?Ø8huh¥†öYVŠa&ƒuFƒA|IðÁ`€F£r¹ŒýýýÕÞ°%1Íñ‚V¦ üõ¿þÉÙ+í¹€ö†HÄÖç}-ð¦_ôÿïs³l¬†'°‹ŠòÿôÞñ‰—*9zIEµ Èêü“_8Ì3Žz}±Ê»–5^ùÝuãüK˜—htE´HàOâ‹ñËSná:ñ[­ùÃV¨«)ûq+”ï=¯½S«/ P"z˜fÓ¿µó(ôT gWª ›¦9é]µ,Xsâï8±Î"“¶âašcñ]c1d9P.HQI’ï´¿YœìÉòì²î<+”¾MI¡õ³æoQáãEsµÃág4½ìªÁªë:dYžn°RÒ5…,¢Å­ç¡‚+³u¬Ë»J‹~•Êä\¿$ h©6Úµ9š[¨ÂbTéM[𠇺$„Ä„/UUºæAôFÇ„‘×—Šïs¹mƒVBÝÿEˆoù½É1ˆ"ÜoükÐ…fv¤ëñ^äðýPU=ŠœGª:*Šž·© ^“‹ûQC7¼`¿‹‘þ–eé-T|imQq+ÞIßKZÕ‰¬_þNˆÿþCA²©Ø6œ×ß“wå½ç°þÅ•ÔÝÌïÿ¼¯ý–1aê›~ƽ÷Oœ#(ÌJá ÀÈHذ»™ Öýý}<õÔS(—Ëh48<< ~NNN Ë2žzê©ÜyWQ;: QU_ÿõoðWnhÆH›!êT@{0¾/tЋÒú#@|ýE§›7ý"`\ÌþѰ°;/ŒzúI GªœÂ}QɱZuî ÂÊ{©4ªµ±,ó–4¦f3݉Q“=wѨŒè1âZ@¥ÙMTôŒÂºÃŽqE:¦ו Z´™e‘Ä0ücÒŸLUg™Õ´qûiCʨwßÔ4rë/Y­a.Ã0ÖV8lxEÖØú(ѰyÊõŒZyik´šõDÁ‚²_«Uõ#¯¯¢„æ:Êó¸(Œéý؇ —'믠݆ð¡ƒ[©¡*vÕFmihq üT(9©–Œ,TK è {ºTŸ§“lÿ]€êD½©ív{6ƒÕqæ÷HÌò2§Ð§^¦¶ ˜½oÛ ´áPÞÛÇþÿΆÃá7¼:l~åÿ1Tßñ³þIg@ýÏÏýaÝîp¨ª“ßWUÈáßëõÉï…5 ’4ž]\¢6 Âè÷©·D‹]ÝŠvÛ¿^M‹ÿ®$ù×F–“ÿ4ák§ûGçð}Åäc¼ûÝ¿?ü¯þ«Ÿ™ïfeÌ>ðÔíÝnw¨(Êp8ôe¥ûøÝ@ÆIÞ–"ü‡œõ¹Y!$—ççɧÊÙÙÙ¤láçÉ¿þ¾IßO“§(ççþ÷Óž¥³³øcv»ãÓH»Þ¤?ý­§ÉKÞˆ›Ãg¡Ýn%IžOû㜟'OBÌÆ±¨¼dżϣªªCEQ¦Ëu¢89É]}_6›þ;7áë>š6©ßHÒ¤ÂÒíúÊVQ«ÙL~&ëõqå Ýö øƒ]õzüÝn§¿ ¡Ûõ‡=ëësWæoMÓ†õ$ErÂÊqXÏÏý§“‹bðŽ¦¯[­ñ?¸$%?W”‹]/ö©ÕSCõ›~còï¬(þ,Ï¿èk‡­ú¤ðuëÂ'ËÀDåFÓüK=ÿ©3¯ÿјÙ¯¸VËŽÒdúüÜoøY[D^æ6XóJÜÅkÚøÄ\¯‡"i‘Ó´Éáp8 +ùgÃáÙ7 ‡gw†ÃáżÝlý|ö‹Ã¡|6”æPhçVÕÉH”óóñ}ÈP ?‹IÆn­ÖèZè~Eß)çç“ïz`’ìsŸ¦ÆgL7›ãcV”‘]”v/ÂeÔ€Ñ4ÿèˆ~¯×‡Ã÷¾÷Ó¥ì ‡Ó_`š¦ [‚$ÑoÏÿÛÁ™u"šmdyµoð5A²@ BÒ»ðâ½1”e_^Å—GÚ¿ÙÝ·³³ùu¤VËß'lh‡ÇBç‹rv6ZH¢ñ…Ÿ‘¤¿e·ëŸæ’]QxDQž-%àÌ&²Í«¦iCuÞ—y²@c^¤ÑwîÌÄ­"«j¼†}Oœ&Ä0Ñûè>,Œæ…]™¿gZlL#,㤔žŸ¥‡~cxö=?<”¾æOÆÅñÂmµFï_M•ÿì¥áÙ·ÿ7þñÈB A6äðìl8TÕ¡ôŽûŽˆ°ªú?Ýn ‡ú޲‹÷öÙÙ°ù?üöL‹!aÝ îõÖ펫ð¥EÁÏÎÒõ¿v{\/¡ãN#nüq:VtmŠ ÖÈÅGç»V«å¿¢îÊ8ZÃá0:©KÃá°;/ ¦ÖûŸò%õÛÿ`8¼PŒÉ^ð™ö,Ò8§­QÈ‹< +¢^7PëõÉwR³é{cÓÊ­ÖôÕžèØÛ¡Å¥y ߸{NïVQÛíîF);Ãáô˜Z.?ûÅáðü|bÑpnüUžéÏËBú--r dyô2#»Ÿi2NûEŸ/ I"üîÞ…§Ùl.§Ø3˶¬çç磹|QhA^Ó&&®VkN}BšâÆ4«QIÊ@ÜËH’æ ÛxþžéãJæÅ‹µý%Ö:Ãá0&ÚNQbW±[­ óý¯ [ÿÿöXeüÐggà |ðÜõ†ªêëÁiºA·;¾NFæ4½,i-háÈGZ·"=¢^÷§ÇQ'£5iyPÛíqý<.@•î5ݤűnw8,?3ü›ó§æº¶­6X£(Š2ü·?öcãïÙp8Œ6y8F±úÅ‘ qáH‚hä1…F¡?ô¼´ZþϪ"§=,ò;ïyÉ;šfœ·Û‹­O[I:;󣉺ÝÍSv†ÃôX°3Ûßù¿ Õ¯Ÿ¬&<Ó2+"Òd5)ìyZ8Yø˜Û®ðbŸ¸:?m¢Ù!V±ÞN¹Ìqм=÷¦Íá³>Ífs¨-×Ò»?ûr œND鞟ë0I«r´¿ƒ‹–Y²íó÷p¸‚蘸¨¯‡jZ8:22ÊÂVit»›¥"Qdý¬ªÙ,ô3í¾„£+ÓÒ¨~ò'mX¯Ï7§|Ö%¤Éfµ– ºžçÁq|ƒ(Ž„1˜ðÛÑPÎwЂ#rP@ íž°Üj’ð©’\¥âÿNY’ö›—uùª×Ó+®Ríy„ÑO³4cÚ>¢ ‡þÿ§´Þ¨Ja¸•ý¯þÒÿû+ø"ºH‹±.L³rHöÓž¤mÓj ­« @1 Š¢L¶û Ê&²¼qU ª#2ë;ªŒÆÉ‡çùÇ¢9{‘î(ÔÃyù¢1JÒ|µ>DÑ/^³+²mÚíöÂûÛ?ðaXÒÿ {¤DqT(PŒl{T)•ZGËÝ‚ÀïfåβPëσ÷ôÏÃí¿#èÕJó‹(5'Ä•ê ‘ø§Í?q-’ÒØ´‡‹\ß<×xÑ섚¡$¾oŠÅ×Ðï¿6ר·Ú` \AõÔð„ì°´.þ%!7Cÿ#˜á=}þêuÿ!I’¼ ½ ¬oL³´îØådYLÓ/(÷Ê+ŸƒfÓWÎR êcYŒaև뺰, Ýp…w²ÌlÛSæmRª(*IþåL›/u}´0zÑârâxÍæ¨Ÿå"¶)-Täu£— Ïyp]×.`Û6$IZªÿ¤ýåO@>( ùÄlt.£h†¹d À6o7 èîQ:{â—~3¼‹†´Þ’4¿qױ˃ZO­š­5Xm{Üè1Ms\¹|ïª ßsJ¸ð׿ÔSÌ?,̺e¿ð £>GžÇ?³ÝÔj5Ôëõ‘wÕ²FMi7¼‘¡aø—¡i~û‹4Ï&©õúdë&BG?•Êbý‡ÉHuœÅŒ^Óô¯ƒy4GyÞ¨3J\K§ju´ö`Yþw)úçÞ½7góZ#mÉÂÐò¼Q;Ë‚û#ÿ濼Iòïqýƒ'Ÿ`^÷ ìjC&SótêYŲüù\‚^¶ŠªªŠ®·ØÂ³¹ÌÔ‡u ÷¸¢Ðƒ‰Ð1ãžT ^±±Ê0ëÂ4q~þHðÙÑd “{ À £Þ”•Š¯Ø´ÛÓc¦/e|ñý)Ì·Zõûé%õÒö<ÿ2azÏkÓy`)ÕÂqFm0)y*ÓÚ^Æ%|-ªß÷šúœÓu†±m;]‡ãŒzi×j#û+zÏ¢áÃá–µÐïoWm×uá8ÎdïIjÀH—8Oõ༺t»°?z=5ÕˆaòD­VƒçyhµZþCN“(Ž7h§F¶‡iúsÍ3l¬î[ëauœÑ‹Î²¬øÆÛQž  ‹ÉÜU†É!.gÛ6Þÿþ7á€<‘3ÛŠã8°,k<ǯ^¿ÔðFjÎv„Q^={a›£Vm§\BʧF^Rêåö”Òq(íPQF—êyþ~q9êÕª¯ë™æ¸×RUýÏ¢6Í%a<Ï»¦®‹¼¢áïSÓxzÅ’]%I#3&Ë#£>¼_øOhšþwÂfJS)•üßûÞs¼ðÂ¥ýÙ×Nlˆ¤wáF ý‘Çÿû¶Z8½”Ù jÆi“&¹ oiºX5Å\¬E2³•k8$Òó<ض¦ëŽ¿¥]ŒŠ,*ü¼VVø™ À4ϳ¡( ¤Ïùœö§pœ¯‰ ­c˜m`"X‹±jÛ#I×}Ã°Õ GíøŸQn¨iúÛa2çTQâÃuGï¨ñßã ç}§Vó Á¸uX2Š+ÿØaƒV–ý})ïUýÿÛöx±@×õ¢8}RQF!¾’4©H¶Z£Ðá°±FÓFF5Aá”—r®Œí§ëþ9?ö±•ÿÙ3öm8Ž3RäC7Å–48aâ”ß–E†Ù,Ë‚ëºS Š‘ŒSÎ;/À3ÄV¬aïªaøþoùàå—G_0à¦Ñ›ò¿&+øÄ'xúéÿb­ãw~ÞoòJ$³Ôj5ü?¿ø‹!¯QS·mß³ŒŒÌz}ÜUÿǶGa½ív²b5-ep–*Œ”ƒJÔë¾a—ä]£"Lqt»þÜAãÎ{{£ë»ªW¯ŽÆžtMiÈ2p~>ù¹aøãNºŸ¢¸žbYcþ?ïï\í¡?¶(ŽÂ¨Ç¿7l¬2›„çyÐuÝ7V½øäSÊQ5ŒTÇ+³ÃäÞ`íõz( (‹3ï3 ™ò`YþÁ7}Ó¸ô»˜4V&‘oâßÿû?Ä7~ã ^¸hÔÿ®ÀŠ “;–‘qÂ0 üç¿üËøîÏùœD…g‹š”;I¹—š6i¨ÅŽR¬² Γ%iájZK²n7½p› øÆæ:<›¸Ø¶¬|›¦‰o.ðžïû>ÿs!˜aÛUÓf«®Ï0«fU󷪪g®¡Vóå}ƒ ¼3k&·k¿ß‡¦ièõzüjb-}O^Ⱥn ùÎÿoø?ŸþÇК‹*1³Œ|¾wç­oíú%/\-*Ý`rIJ2NX–…/ùÀ_þ†o~ôGg¶”ÂEUEÑ_³ ·h óÀ¡ôLë“MßÙuV!ßžçáµøñÿzÝ뀟ú©@(ÉÓÏô˜¬XÕümÛ6lÛFWQüÉ÷B¨)j€RXÖ™iä¶Jð;wP,á8ž{î9ôz=4™÷éç^Âûî¾òŸ€w?êT*Áf˜ŒYV¾ÿÅ¿ø}üÞïý_aT…arIJ2~î9ìÿ—ÿ%¾å¯ü|Î?˜j)yÞHÑßÛuJåÑãA^Ѱ' R²±ÊÌÃ*äÛ)•ðMÅ">ûßý;¸‚Ȭ$¥‡™3̺Y…|{ž‡Æ­[øùW_õc~»Ý`¢¥v\<ï2³’Kƒµßï£ÓéàÖ­[€B¡€ƒƒƒ©ÉÚðÆ¿ô9xøú¿®ÿ ðÿ©_ý· .¨ÄdÎÒò àç~î%üÓoüL¨\$Ãä‡Uȸçy¸÷ß·×wá­?üÃ1Ûý{ éuÝQþi·ë‡–Qx/+þÌ*Y…|¸\|M§ÃP©Œät/7ì‹UÍßO}ÕWáŸ}Ögáµïÿ!èB¥Š´Åª×¹%03¹4Xïß¿Øßß>ÛßßG¿ßŸiÿ_ï?ƒÁënàmý-£Òȼ«Yy§×ëáôô4ëadβò Ÿÿ‰OàÀs|Í|C>¶Q¶í™]”eeÜó<<÷¥_Нþê¯Æ;NNŒúË“ÂC¡¾”ÛG^©¤Ê´Y°mò°Ïì",+ß¿ý]ß…_þÍ?Åý¿ÿ£RñÃ#»ÝÍ ”ÙFYضçuQ–ÖQ<N©„ÏýœoÇ|Ç=”þÛ÷ðççM’ñm“‡Mfs™ÃšöP  …‰Ï?ýéOã#ùž|òI<üðÃè:>õÈ#@§“õå,ÌóÏ?7nd=Œ•qïÞ=Ü»wo©äýUð©O} ¿ök¿†OúÓ™œù¦q?ùä“xûÛߎãÿõSøÕ‡îíyX%yyfïÝ»‡üã™Ù9üµŸýmü<êxÝýEÜ»ñ2>þñ7â ¿ð3xøáWðÞ÷ž£ÓyðÕ_ïG /ò°*òò̾øâ‹øèG?Š?üÃ?Ìäü‹Èwxþþþî_ÅË_ø xäg_ÆûßÿÞýî—s-ÇqäEVI^žWš¿ûý~&÷wÙùûÕ{„xÿçðußþ9xøM¿‹fóoyËŸlœŒçEVE^žYÒÁç¿si°ƒÄm<ˆ}X^÷º×áüüÏ=÷Ühÿ ï*~õêU¼°á׿Áƒù5}üãÇïüÎïàó>ïó29ÿ"ò ozÓ›ðÜsÏáï|'Ü/ü—ï¼ÈÃ*ÉË3ë8þìÏþ,³ó/;‡ÑŸÿ|Îû>=ôþÂ_x ׯ2tìÍý¼ÈêÈË3û±} Ÿþô§ñå_þ噜ùÏßßõ·¾À¿ ‡›#ÏÑë²—…U’—ç•æïO|â™ËÎß’$áøŸ ¶]ÔmÚ8ò"«"/Ï,éàóÎß¹4XÃaQ’Þoû¶o÷}Û·e=t†™Ê"ò O>ùdÖCg˜™à9œÙf‘ož¿™Mço&ä2‡õÚµkÆÃ² `˜UÃòÍl;,ãÌ6ÃòÍl3,ßLÉ¥ÁZ,Q.—Ç’ƒmÛF¥RÉzh ³4,ß̶Ã2Îl3,ßÌ6ÃòÍä‘+Ãáp˜õ âèõz8<õ©ÄmÊ€k×®½é÷û(‹©Û¦í».Ò …ÂÒcÎ⚘ÅYF¾W±}¤Éø}ÑmÜõ0Ë‘&ãÛ&ß<‡ï»6O“ï<^³<çÿšæ… Ö5qãÆ t:À¶müb±ˆr¹ŒÓÓÓ±í•J%uÛ´}×ÅþþþD íF£¬Ì,;æ,®‰Yœeä{Û×AšŒ¿ç=ïÙ¸ëa–#MÆ·M¾yß-vmþž&ßy¼f9xþÎÿ5ÍË•áp8ÌzÛÊ;wpzzŠr¹Œû÷ï%H~Lúáá!ŠÅbÔ|||ŒB¡ºmÚ¾ë‚ÎI«Tó\Ï*¶3ùbù^Åöu&ã›x=Ìr¤Éø&ÊÏá ±kó÷´1åñz˜åàù;ÿ×4l°®™pÉô¸<‰Á`¬E·§m›eû:XvLy¼&fq–‘ïUl_ë|&Y¾74ßDyà9œ!vmþž¶=×Ã,Ïßù¿¦Yaƒ•a†a†a†É%œÃÊ0 Ã0 Ã0 Ãä6X†a†a†a˜\Â+Ã0 Ã0 Ã0 “KØ`e†a†a†ar ¬ Ã0 Ã0 Ã0L.aƒ•a†a†a†É%l°2 Ã0 Ã0 Ã0¹„ V†a†a†a&—°ÁÊ0 Ã0 Ã0 Ãä6X†a†a†a˜\Â+Ã0 Ã0 Ã0 “KØ`e†a†a†ar ¬ Ã0 Ã0 Ã0L.aƒ•a†a†a†É%l°2 Ã0 Ã0 Ã0¹„ V†a†a†a&—°Áš3<σmÛYƒaÖË8³Ë¬Cþù™b²€åŽÙXÖ³‡ Öœá8*•JÖÃ`˜µÁ2Îì2ë~¦˜,Ëišp]7ë!1ÌZˆÎ±,ï—¬ Ã0 Ã0ÌÂX–Å <³3°¼_>Ÿ•õ˜ÑJ $)q»(Še¶mCUU€mÛA˜‚¢(cûëºMÓ`š&<σ$IPeì|š¦-ü}†™•4÷³, Ëò„ŒÒgSeH–³³³!€±í¢(eY¶u»Ý‰ã†Íf3ø]’¤¡ªªÁ eY^øû 3i2Þn·‡áièüü<ï¨üw»Ý!€áùùùp8dùfòOšü/+ûš¦ûÒ±ÎÏÏ'äšaVÁ´¹\–åa»Ý¶Ee”>ã9›É;Ód}8L—÷´¹¾Ër=?ìaÍ×u!Ë2DQ >£P_À_•‰nW€¿â#ŠbP¹,ü;­ÒÛW„ $!‰y¿Ï0iL“qú¼V«Á¶m‚€v» Q!Š"$I " ,Ë « ï°|3ù#Mþ—•ýp¸0A«ôôž`˜U1m.#NFyÎfòÎ"²Œä=mn'X®ç‡ Ö ¡¼Ô$<ÏKÝ—ò”Â?q/†ÉŠi2.Š"Úí6 Z­âÊ•+¨ÕjÁvEQÆ”v–of“H“ÿuȾ$IÐ4mì8 ³ ¦Íå ³-,+ëÓævf1Ø`ÍQǼ¡À¸‘*B¢Ñ*IR°jC?­V š¦qÞ“¦É8h6›8??G·Û…eYA.¶¢(p†aÀó<ö1Ešü¯Cö›ÍfP¬ƒs ˜U2m.g˜maYYŸ6·3‹Ák†(ŠÛ¶ƒUtò˜†·;Ž$nSEIÀ=ÿŒ’¾&/L“q*$F/Q'B~Ea3…ä0LžH“ÿuɾ AµJn»À¬Šis9}Æ0›Î,²NŸÇ1mngƒ Ö ¡ð­jµŠR©„½½½±°/QÑl6Q©TP©TP*•‚í¤”èºŽR©TnµZY_ÃL“qÊËÛÛÛC¥RÁÞÞ^ ¨´8ÃÞUfÓH“ÿuʾ¢(P…0™•1m.º®³‰Ùx¦É:.ï³ÌíÌü\‡Ã¬±ë¸®›Ø£Ïqˆ¢ÄÔSŸ&2LÃE–(L˜aòF’ŒE·Ý4M†³³³¬/ƒa"MþYö™Mb}…s]™m mÞžEÞÓævf~Ø`Í1®ëbooÝn’$Áu]T*hšÆá‘ÌÖCá4¥R ªªr#mfg`Ùg†a˜™†÷z=ôz½Ôíý~?Ë!fJ8$øÊ•+(•JP…Õ å{9ÇÁÕ«W!Š"Ë|Na_,ûÙòÍl;,ãÌ&‘‰‡µ×ëAÓ´àA(‹0 ûûû€~¿MÓ‚I–娄g†É#,ß̶Ã2Îl+,Û̶Ã2Îl"™¬ßüÍß Y–qûöm 4 t:<óÌ3€ÃÃC¼å-oa ¸yó&*• ŽŽŽÙï÷ñáoûÛ³»›+æÅ_Ä»Þõ®¬‡±2^}õU¼ú꫹ø½úê«xÝë^‡÷¼ç=+?ö:ä~æg~o{ÛÛ²¾u+#Oò°*òô̾øâ‹k+òÀsøläIVAžžÙW_}…Baå¹a<ÏFždaUäéy}ñÅñ­ßú­( +?6Ïß³‘'yXyzf™¿?ë²Ùét0 Á/ ¸uëNOOÑëõP(ÐétðÔSOÛpzzšú°ü»÷ï`YÖV%6?ûì³xôÑG³ÆÊøøÇ?ŽßýÝßÍÅßèãÿ8»ƒ•çðÙÉ“<¬‚<=³ÿøÇ`¥cáù{vò$ «"OÏë³Ï>‹¯ÿú¯_¹ÁÊó÷ìäIVAžžÙEæïK7X÷÷÷q||<öÞ¿€ÿ`Ðÿ)4þ?-Žþmo{$IšúÒØ4¶éz(_âàà ë¡ Óéà…^Xùq×%ßð_ð,@^þFi¹IËÀsø|lÓõäé™]ÇÎó÷ìäIVI^þF½^ÅbqåÇåù{>¶ézòôÌ.2_zÑ¥B¡€r¹üÞï÷Ñh4ppp€b±˜úP ƒÄm/¾ø"ž}öY^ö%­mzPÒËÃrzzŠ»wïí€Vɺä^zé%âôô4»›·Bò"«$/Ïìáá!îÝ»·–có>;y‘‡U‘—g¶ÑhàîÝ»øØÇ>¶Òãòü=;y‘…U’—ç•æïu,:òü=;y‘‡U‘—g–tðyçï̪SÜüc=†r¹ŒÛ·oŸ'ñàÁƒÄmïz×»ðè£âøø8«Kb6„ƒƒ<ñÄk ‹Xµ|Àõë×q||œ‹ ‡É7ÇÇÇxøá‡×zžÃ™¬8::ÂOdYF§ÓÛV.—Q,Q.—Ç*’Ù¶J¥’õ½b˜©°|3ÛË8³­°l3ÛË8³©\ºÁJIäq‰ÙTçè臇‡AùíB¡€Ç<ã[Å0Óaùf¶–qf[aÙf¶–qfS¹tƒõèèhjå­ýý}<ýôÓÁƒ®hÆ0y†å›ÙvXÆ™m…e›ÙvXÆ™M%“¢K³-½Í0ÛË7³í°Œ3Û Ë6³í°Œ3y#³¶6 Ã0 Ã0 Ã0 “¬ Ã0 Ã0 Ã0L.aƒ•a†a†a†É%l°2 Ã0 Ã0 Ã0¹„ V†a†a†a&—°ÁÊ0 Ã0 Ã0 Ãä6X†a†a†a˜\Â+Ã0 Ã0 Ã0 “KØ`e†a†a†ar ¬ Ã0 Ã0 Ã0L.aƒ•a†a†a†É%ŸµÈNFN½^·nÝB±XD¿ßÇÑÑQÖ×Ã0 Ã0 Ã0 Ãl s{XNOOQ.—Q,…B§§§8<<Ìúz†a†a†a˜-a.k¿ßÇÉÉ ŽQ.—Ñëõ²,£X,âæÍ›èõzØßßÏúº†a†a†a˜ g.ëýû÷årybÛþþ>ö÷÷1 ²¾&†a†a†af ˜Ë`- k”ƒÀãÊ0 Ã0 Ã0 Ã0Ë2—ÁJ^ÔÃÃÃ1ã´ßïãÎ;(‹±ÞW†aærù½ßû½¬‡À0 Ã0 ³4s]:>>F¡PÀÍ›7Ñétprr‚Ç{ ý~†ad}= Ã0;mÛø¹Ÿû¹¬‡Á0 Ã0 ³4s·µ) 8>>F¯× Bƒ …Zb6×uá8>ô¡!î sÙèºI’ Ë2AXËñßóž÷d}™ Ã0 Ã0K3—ÁÚétpxxˆçž{Ž T&3LÓ„mÛhµZ‰ßq]®ë¶m¸® Ïóàº.DQ„$Ixøá‡ñGôGY_ ³ƒ˜¦ Çq‚ÿ{ž‡v»½2ÃU×uȲÌð†a†Ù æÎa- °m{eèt:YßfCp]•J¶mCEèº>¶ÝqÔj5ìíí¡V«ßÓ4 ívgggh·Û¨×ëxï{ß‹·½ímk3Ë7Æó<†f³‰z½Žv» UUQ©Tày^ð=Zd™Çq`Y4M»´kbg¶–mfÛag6…¹<¬…BGGGh4è÷û±ß9::šùxý~‡‡‡·h4899û¬\.ãøø8ëû• H‘]G(aÞ œI4Mƒ¢(ð<¥R š¦Axž‡jµŠz½Žf³™õ°°|3“†EQ Šb𙪪p]º®CÓ4†˲ Ërjã8A´AøxÍfóÒæ–qf[aÙf¶–qf“˜;‡õÎ;0!ÌÄ,k¿ßG¯×K<Æýû÷qppY–ƒÏ8ßp·ª×ëYe¥„=÷¤ŒSž_4dRhš]×Ñl6Q©Tc6kX¾™8\×…eYèv»Ûêõ:jµZ ÇÍfÕj†aÞRÇq ë:Ç$IŠ¢d²@Ã2Îl+,Û̶Ã2Îl"s¬Ñ•˜Eèt:©aÅ<@¹\æ9)¸®›õVyGEQ ŒRAÐn·Çûlì÷m,RŒå2ÇF¡’$^#*–¥Z­¢Ùl.ì•eyîÈÓÓSܽ{w%Ñ‹2¯|ÀK/½´–g™×uQ«ÕP­Váº.EÁÙÙšÍæX{½^+®4/’$¡ÝnÏ]Eøðð÷îÝËôñά‹F£»wïâcûX&ççù›Y'4÷z½ÌÆÀó7³.NOOñýßÿýøÈG>2×~s{X)ûàà·nÝà ô;wÐëõpûöí¥.¤ßïãÖ­[xüñǃ˜ùb±ˆF£ƒƒƒÄýÞõ®wáÑG«èÓ¦âº.$I rÙ.Ê+;/yKIy'4Mƒ(ŠA!²,(Šré×ppp€b±ˆ^xáRÏ ,.ßpýúu.z°B¨ õ楰òiòHE‘TUºX² Ù^äÇÇÇ™)<‡3ëæèè7nܸô9œçofQ\×…iš3é<4gÑ>’çofÝü¹?÷çà8¾ã;¾c®ýæò°öû}œœœÀ0 ܾ}GGG8::ÂíÛ·q||ŒÓÓÓÄêÁ³R,qtt4–à}pp€Á`Àå·/E¢(^ª‡0ÜR¦Z­NœÛ²¬ Jo\K EQ&<¬¶mç"ï2aùÎá¼iMÓpvvI’`öööRó{LÓ\Øcº °Œ3Û Ë63/žçA×uT*‚€jµ ]×s)Ç2άÓ4Q­VqçÎ|Ù—}Ù\ûÎe°Þ¿ƼdD¹\Æþþ~ðEét:¡<ÀUÊß+$dY^k«çy°mº®“­ªªhµZhµZÑjÛ6*•J ÄÇÉA^a¶í\Tõ½LX¾óµ— {TÃòm*•ÊÄ3æºîXq0f–qf[aÙf’¨Õj(•Jc†¨çy¨T*€³³3hšT‰öÞÎ ,ãLŽã R©Ì½Øbš&*• ®^½8½ºÝ.~øá¹Ç°PÑ¥Á`0!¸ƒÁ`iï*à? Aá'''c¿ï2žç­ÕÃjÛvÐ÷” %‰¢UUƒ¢I’$Å`$I‚¦i©†*!Ë2,Ë ×YöÙ6X¾WO­VC½^ŸÙˆôšõ0˜ „ZÉlcqÈ…ÚÚܹsGGGA/V À}šÖˆëº/tQS+în‚›ŸÙ](ŒŒÑhž¨ëºÁêø4ÈËJ ñªä^–å`Å’a. iœ•p˜ü<•RMÓ Þ‚  ÕjÁ0 Ôjµ ½dC’ªE*Šœ›£ÈX¥”º.êãÍ0‹B2–wêªëú˜nDú² {g˜4h±t"c‹³¤ÒQdÙ6²p[›ÓÓÓÀ8íõz( 8>>ŒXfõÄ•‘eyç+î2›‰eY‚ èã6XçñjJ’Ó4aÛ6ÎÎÎV6NQÇ^ ³nÇA­V›«Ú¨®ëA«½½½™*7š¦ Y–ÇÞ”G ð€Nó~š¦ ×u'Úw•aÖå=Ç)èTÇ#ü Ђ />2y¤R©@Q” ý€@÷ :Íf3Qß'a[å{¡¶6Ï<ó lÛF¯×@–e6VWLt2Ž+À«ÓÌ&`YjµZPñ“òØÂ .N C¨gA–åDåeYEaÅ›¹4Ç z<΢|PH=­ÀkšÓ4§z’ ÃHí'ËrP&Éh¥– ëîÁÇìT«@’¤ÔÐtÃ0‚Eû(I¥·U™g6ŠhIÒéeY†aAT¥@‘NŒÒ-¶•©k¿ßÇ`0˜õåòòë‡øš¦ UUáy^ÖCb˜¹!ã´Ùl¢Z­BÓ´ @FXy  9Ì<ý½DQD³Ù\Ë„Í CÌeB‹“áB2iDsøEA©T š¿ÇAÞÕiÏW¸r©¢(Áâ …bš¦¹uÅ=˜l¡b\®ë¢V«9Ïa,Ë‚ã8¼PÂl$$¿À¨¿û´FMÓ‚t'ª€^øßæp``Æ*Á'''¸yó&FàUeÖ …´Ûí@‰Ïcv†™F­V š£SK%ÏóbÀpØû"ÅÂòZù‘aæ" féǨëúD‘$jV«Õ‚BLÑϨ‘›†$IA¡3Ó4ƒÞ~Àø ?ÃÌ‚ëº0MÕjW¯^«LíºnúØl6qvvD›¦i‹  ³iضDP€Ye™R”é–e‹ûÛA0ÕÃZ,ƒ“mÛ8==E¯×Ãþþ>Êå2PkB×õ Ø…,ËAŽÃl–e§”C”ynÂÿ2Ì®AÕ°§µ¨¡‚Fq^&MÓà8<σã8¨T*A/îY½«aDQä!fiÇ ¼õš¦¡ÙlEí(­£^¯yì):‡ ÒP¡0öê3›F8ÕoúM½^r_·Ý›+‡5lÛ6:NNNØx]1áj€¯xPÜ:Ãl qyªÓE10TmÛf™gvŽp<=qïÖ°â÷œ‚ìGÆ/}Zî*ìÓ4aÆ„²N)¥sÄ¥uaKí—øÝÀl"”µªÅxQƒùýüü<ëË[+3…Ç!Ë2nß¾§žz èõz¸yó&‡ σ @ŸüX×õ±P-Zyä šÙ$(x/Ž,ËA$çyìaevŽpdA¸iô;•Jõz}æg„òYK¥ÒÜÞU†!Ç™êùƒò»Ýî„ÌRž´iš‰¡‘ÃÆ*³)ТýÕ«WQ©T‚׫ŽT¡H…m.æò°v:”Ëå±ßmÛF¡PÀ7ptt”õõl1¾µZ ‚ L45Yg˜M  <+äa|ňs”˜]#l°*Š‚J¥2¶]×õ ÇoÞ¨¦f³‰Z­ÆEĘ…¡œé½½=hš6³òM½“”jI’¶ÞCÄl7”‚A=á©òïºå:ÎfØFfò°öz=<öØc8<< >³m‡‡‡èt:h·Û8<<ÄééiÖ׳YD V**§¤S &‚ ²ôQ˜B«Š‹T«E‘sµ™&l°’rOi"{{{€n·»p N³Ùdï*³´hÞl6Ñn·ƒ*¥³îÇ3̶âº.ªÕ*,ËB¥R Š‚M«üËÌÎLVMÓ°¿¿?B¹«ÇÇÇ( 899A£ÑÀÁÁAÖ×”k<Ï î£â)xýï¼ÿ\ÿçAYkö(Í ¿ÿ.ÏóÆÊ°'É©çyA¨â¢á)¢(²,Vª™$ÚÊI–eT«U‚°²B ³áʼ¢(¢Õj¡T*M-gYÖNx€˜ÝÅ4͹"˜ù™êaít:è÷û¸}ûvЋu0 ×ëáàà…Bppp€Á`€N§“õ5åRæI‘ÿ¥×~ ŸûÑÏ»¬5Â\þL:žç¡T*Áu]¨ªôÇ‹ûU«[&@’$6X™A×õÀ×wXUU¨ªÊíc˜L1M’$MÈ`½^k9ãº.t]ÞÀb̶B ú,ãëeª‡µ×ë¡\.†)0 ï‡$…·ï†aÀó¼T×?)ó¤|ðÃYûÀË_œõ%l..üûȬ ê×HrKé ,±ò½ ¢(rSfg°m–e¡ÛíÆzª¸ “5ŽãÀ4ÍØ4ê¡ëzÐr†r¯ëõ:Çáœif«!™ßö¢GY3Õ`-  cŸQÖ]6RÃPÓkªÂG¬2¯`ù^~µef-ÐÊa¸wªªªØÛÛ ¼A«4VQž{X™]AUÕ@ág/*“,ËÓo’ædMÓP*• IRÐUUUÔj58ŽÃÅ”˜­†ª_3ëeªÁº¿¿^¯©ƒÁ¶mOäªR(ðµkײ¾¦K…VÄ)ï.Na·m’$Å+óó×¥aˆ`£†»r¨iLÓ ÂÁVe¬¾Á*¬ÌÖã8Azm»®ËaeL.÷Ñž6 ‚€³³³±ÏDQD»Ýê0Ì6`ÛvUIQ¦Üvòr˜É`-—Ë8<<ÄÁÁ:ƒAð‡ xá…pçΔËe‹Å¬¯éR±,+‰!/S ©œ€çñå¡V¾ñʬŒ8ï*A^VÏóÖRRWä™MÆ0 ¨ª:U‰ ÷n6›¨T*ìaerišs÷ÑŽƒå™É3žç‹*i•×)uÃqœ ÿ5ýÎ!ï—ÃLmmêõ:dYrʘž|òÉ Šð"å›ÓŠ4õz=ôûý¬ïQ*äUE²,ò¬±í®ëŽ­ÄŒ!(e}Ž Ü«›,ßIÞUBQî•Êl´Œ¯Ã0`*• <ÏKý®mÛA Šâ„—ŠÉ–]–m."³첌뺎J¥Ã0`šæD‹&JwÚÛÛƒeYAÈ;yT©X*Gƒ]3µµ) ¸}ûv춃ƒ,äYí÷û8<<œé÷ûÐ4 ½^€¿ên©“È»JPRx’§•öX8‚`yrcU‡oL#Ã*ìH‹¥qÏ3^Ú'éV:…÷FuÆ:|ƒ3ް•—rÜ7ß{3>ùW>¹òÛ7 YÊ·mÛ¨ÕjP…«à1k#sø<èºI’Rç{Ã0àylÛ†$I +û’$Áqœ‰7I» `šÀŽ´€Ø4Ù6V7~±„Y›,ãi8Žè?Ìæ1Õ`-‹kK¢.—˱•Z÷÷÷ñôÓOÒÊåò¥ÞÛ¶áºîå„KjXO»—Ep0=§v‘E)º¾°=¯ßèt0n H6èÕÈ÷¢Øz"/ëÅ÷Þøñ7ⵇ^[Ï}¼ oòMùج¬0«"o2¾T5­™išAð²$)ukVø% °·¯Ôý¦Ëv¥R(ŠÃÆ*eÓe| ÃZSrdÁf2wÑ¥N§3VÙéÆkæB¡ÙC¢ëúå5 Þ–å2‘^µ˜Š'Íû®sáœÄV¢íÀx‹£à¸ù%j‡ R¸¿·TxIö¿÷™/üÌ¥ÜÒ$²ojÏÊ sd9‡ÏƒišP%5$˜U<;dìòs¸¹l‚lSQ¯R©„z½Î‹•Ì\l‚ŒÏ -JÎSÑÉ3¬¶mãîÝ»=šNNNP,aF&%¸WišK…{ÍŒ?¤ÕŸÁ6 bû‹Ž¡OÙxIžPé^Ò¤÷ ym©R°³¯ºáýh-æzÜÈg"FáÊâóWÞÞ‚ªE²Ã0>žçMDÔD=¬FÆ¡d)¯Ý^î8•Êrû3œþÁì´È¨ª* c2„/œÏÍl6S Öýý} ƒ‰êÀQ¨àR¡PÈúšâÒ+¨.c4Õ1ªŽG@óç±ê÷ˆ†àW5&óJ«SŽé„Ž5´Û7<ÃE¨ÂžÙè|mÁãEΣ—FùUUÎKßÛK²,c˜TH)¼ˆ#IÒ˜‡•Ã*/oÇ&æ5Á :³KP¸¯¢(°m{ÂËÊÏÃö0“Áº¿¿MÓÃ}ƒÊåòF¶¶ñ<ïò“²„ÿO,Ò[ȬbŽŽŽ²¾ž…°,ëò:lpÍóÎwà‡Íšˆ ¦j¸áª¸„‡äPb#±’pÜðØÃi]Ý‹ãŽ)FÏ0ÂÅýWý¥k®V}'.¹>ì¥ýת:©Ñqàm?û³¸þÑÎqã7Ïóàº.+Þ»‚¾cñî ç]&«³â?óÎ+W¯ú2êy€iôÞE?'–Y.0ÃìáHUU'¼¬ìaÝf2X÷÷÷q||Œk×®áÎ;xì±Ç I{ì1ܹs×®]ÃñññFzWŒó  ö—}¨^]Ã/¼ |õ[üßÏÎÆKŪ<¯<ü0^{è¡þ›¬⺾7iÙ‚4³â8£"8L,Tõ7©Y¸R0+9S¨‡&vÇñ=¤õ”Rì¢èoE@QÆCŠç ÞÛ›œÛì]ev‹¸cªª¢T*ñ<¾…Ìäa S,!Ë2ŽŽŽ Ër`¬ƒ ðÒ&‘‰B.,ÌŸJG!e{Üq¤·vBÿ†Ç§`Ò uBÿÒÂx\rºîDJÊÅ•RÎø†ìÉ;|CÀóü “®ëï÷‰"ðŸ_K¾¾:ËÂËï~÷œ7}3ኑK@Jø¢Ø¶¯ˆ_VT:¸.žøÐ‡.缂뺩ÞUÀWn¨ ={W§~oÎbp ¸m$гå_s¾k"–e±‚Îì Ió4U æy|»˜Û`M¢×ëáðð0ëë™›pÂöÊ)Íø½yúƒº¡ãté° 㦠ˆ‘Ó §QØ3‚5ªµsà¡oºP^Ž-ÄŒ=.5O€fs´jOãI³Ï4¶O~ÇwÌp‘› OÖKbšþÏ¢PdZ~^­æ‡G.¢€»î¸‚ïº#ƒUqïÚµù¹Å†‘j¬~á%Ïó¸àÒ¼¬" }VCT–'+À3°mŽãpß`fgHÒqEeY)º@–tqÍÓæ§n»@&ÅÄVEÖX<ÏÃ2ž2X%)þzj5ÿßnw2”—‰é‡ö÷¼ð©ñ}Ò¼Ò+ ‡õº°íx¨7¹bÞ{ p'/Öu/¢I—$_1?;çˆzt£è˜Ì}M ÇÜr6:xÖj·iW×]®·£$Mï1I¿$ÉëÕ´‘g8z aãÒ0Ò=IIÈò¤‘Kù|’42h™ =M½^ŸÙX|%g뽫¦¹š91š·*ÉÇ]vʲÆ÷W|Þ¯üÊúïUÎq]¦i¦*î ³-P2X·za‘™`j[›^¯‡F£1õ@ƒÁ ëk™›µ+&2â½IŸÔÖebÀ ŒúFa ¾Ñ.žDßùâŸ>ú+ÀWñ…ÁúöÑ~"&{¨Ò(g68‡å+ê²ê‡1‡ÇÖ_^ú9à[Ÿ›lsðuÿQ»Q÷yU "*UUÂy84!ÉðÏçÀûCÁ¤÷X–aþÀª`ùFÄŽ¼Ø]×Ýlƒ5Í[à8¾ÒMFiô¥Eʱ,/Zœæý$(l˜Æ³ãŒQ/ëªþ6²ìWQ¸ÿj˲®M IÒv+BÝ®°êޤ{æyÓ˜æÈ{K G¶=þ| ^+ñyŸþôåÞ»œQ«ÕP¯×Û41̶`š&dYfYßaVæa- (—ËY_Ï̬=¿O†oÌ© ÛÂïo¾!þÝK9.}nm$‡èÞÿyà¾øO¯ÿñ?N¸mMئ§p2M~û·'sféz?ú<ð5…Éãþ÷ß髯ŠgŒE4Æ)7Fxšw9ú'•$ÿ¦ì{‡B¦6ÚKD†hòÅyl±pG 9—µTò=¤•Šz>o˜dT‰F¿×ëã$¬ž·ZCA–w2‚`ËÓEqsŸÙ.Ðÿw™ïè3Œ*bG™7\]–ýøVËÿ¿ëŽBäC¼xxˆÏ¼éMÝÄì¡ðHî³Íì³Tyg¶›©Öýý}g=Ε³Öv6À(\6\E—ˆË %ݼˆ6|a)²_ÔþR#Û©š0<ó@•€ÒUà{À{FßÓ/¾ÖÈ)„ÆOaŽÍ&ðÁŸª¯žé'¿+hñÆ:õm/kY”t§“ùwVâë~cT@gGp]7¿+‘÷÷‡ÒV*¾¬E¿çº¾ò*ñmgÂÞM2è¢JiúÛfñ¸“½Ÿi9£s U@]õœCãšfäïžçÁó¼…½¤;Qi•BÉ—YÄ‹3X ÓôCßIîç97œÇÃkÅ"^ë÷3ºÙà8NÐvɲ,´ÛíåÊ09‡¼«[ùÂLeª‡µÓéLvƒÁNg­k4$iìg•}^×ÞÎæ¢cEl™´(E Áeñ;ªH ßñüö»}EàÏ¿(6¦¯®Ó±Âº[8è;Þüñu ÿjüu)Çç¾6›€®Ãyþá8Sê#I˜ ]ž‚mîÕL1_¡Àë”o×uó=±§åÐ…=7I}Éc“æa ZÅÃó|ezÖÕÚhû˜E¸}_ 9ÍÓ^÷žÄFço_в\á¥i…ìTÕ¯? i©Fç&“…|S!1QÑjµò=Ï3MVów–e±w•™îaãÉ'ŸÄÉÉ œ5¶ ¹ÿ>ÆB¡°Ä'Y«ŠìÁ¸÷Iš“ÅodÆÙÒQO(…Ç ÿ+HäÀÏ'ý–_ð þg”÷F÷–ÎƼCô…üéKÆ·»¡m„mB8¯ˆ@‘—N~^¯ ×}G²£è*€9‹¾y ÿ¥7,íLX5ë”ïÜ÷$i$cdlÆ-,ѳKß¡ëzeyÔÇ— ¢G³>ÿ’”レ¶\x皸Œ9<Û¶wC¹¡(yŒzV–Yäˆ@JƒÎµ…\¶|ÓB Xb.ƒ¬æï(öÅ<Å‹3ÌBëeðàÁ”ËåµäÅ®=8LœG0î}î—šäøu"ÛLW¶ýÜ8ƒU ýKà±ÐÃþ3Àÿ2R:¢Õ~é\öÅç4Þè‹2nœá¶;Á±.6 ãT#çÓ4Ôí ìgÂÑ%ßË NÒÏòd¬ë—ï\Oîikø%I“žÍh>\¸J.0Y7Î(uœôpÞ(Ëoº â•sÀ:e<Ü/ج ]÷çäY'7×õ÷¡0Ò¤g€r­“žÑU´Ú.[¾×ÚÕ`,²~’{tÝŸ[/k¬RñŸËÌçYÍßQ,Ëâ–M €·µ¡ãF£F£±Òäµç÷Åå­¦®æëÂ7öö¾m[óî/öß¿ñ™øv/€Ÿy3ðeqôÙõÏÚCÿÿI}VLVž À?þUà×^}FFyâæžfò?y_úbü ËT 2oúëºå;× û¬ÞÀp+"Zì…¢ˆ¸Õ‰èwÚíùA{G{ûÎË:e<‰µöÖÎTxl9Œ.öÄÝ'Çñ+)9‚°X[¦-ã²å;ï¡îÔ^z« ¢_—ÕKÈYÌßQ(_› ‹åÏ»´g$·+œœœðsfqzzº’㮽凃‘Q‡ï© Ík OòjÌgÁÀ#¿«¾¹à+Ï~:Þð¬Ãï{ú¹×GŸýŸoœ …ÄFrˆ²‚™ Ö@¿¡ŠÇ¿Êm•$_ IÛj†(ÊÒýì£4›£º;y³1Ö)ß¹UÚÃç,^ËhjTŽ¢Fm\››z}ù Iò+ W*þ¥"ï¬KÆ“0Ms7”ªP=Oxè´P|2V[­ôÉ’CR.K¾©.An éa¾ •á2«°ç°pÞeÏßQ Ã`ïjÞq V[þ83Ëà~¿[·náñÇbæ‹Å"b÷yñÅñì³Ï¢×ëM­jìüÿÙûû8Éñ«¾ÿ,k{íµ·×Z?»fÍZf H £fš¢ZîµãÅ·‰ÊäzÌNˆS•íÐ ¾$«Â“ æa’Ò/ÈtèP"ŽgÍB‰mì%6±Kñâ¹Óã’íÄfkbÒ¼S¶ã‡Sߪ£’TR•êYUuÞ¯WÏt—ž¾RïWç|ÏùžcY³_ã|¯¤q(Q²¿`ߌ†ê&eª üÂ_Ä{u/ÿÛÉF)Õ5*áÏø8ðÎcÀþ]Ï ¤ð‹0>qŠr+D Àñ)àÍ‘}¨ž^Ü£ D4#ÖÒ`Ûé’¯ZV/yìÁÁ~øa<ýéOO¡)2Ž|Àã?ŽȲ“”ôž³,|àþC\}îsÑjµÏçç~Ë‹¿ã0M“3agYö Öúé࣎ߩ=¬;;;þ…?£ŸiËå°»»Zཽ½=0;ñË^ö2ÜsÏ=©:ÊTB‚mxkH“¶‘m&¢WÓ”¶ :'m—"ûF^Ã~ò¿zYym¸ósñ™LMOÞþÌ ´½Þý`s³§´ À{/7ôp˜ÛS–Qý›¿¼ï}Àïÿ ÄÜd­–¨üHRÏÕ ªë^s“šHNŠe ¥Os|wbÿž¯ùÜ}÷Ý 1VÅŒßQt]‡$I™Ž*X *•áQŠ2R$é࣎ßC Ö'NàìÙ³ÈçóþÏÖÖVßgô3 ûBnܸ`ò,e“Ôç aHJZBrho\‚#(Â3"ÍȾ„9N×½p`»»­pÒ,M3,8BÌõœÈu$ h6=Åß0<£ÀЀ³'¼ß‡„dèOžó{ÿâÇß|÷7¥˜ÅT³/ã|5ªŸÄ5X&gÞKQ1KùμÁJ‹ŠÞ gÛ½Y‡hÛxæ™ì2Kcí¼«£“£Ãýn ó–o˲²»Ì½¡Û¶Ñ3î2˜¹|䛼K£Œ‹âdåϨvõ¤[Ÿzja·>oùŽâ8Næ& 5-aS¥²:“3QlÛ»ñaUÒNêLÈÐ`ši™'ØÙÙ Á/^œŠQ<µßDØs:ˆà¸5<ƒç«Îó­¨ß—ÛmÝ;X{!*ßó-À?‡ç•Ÿ üíjo`%ÅMB²"Þ:ÓJw»o,•ÂÆiÚ䓟½ò¥=ÝÄ’£NˆãÑ»!­ÞY­z}ªXìß&Šá(ά¬³”Ϟ”¨çF–= ÅÆQH.™¥b–2GÖ”›™"Iლæõ`¿ ¨Žã…lM2.8Ž…st´è»Ïó”oÓ4³=¦Ã{·*J×h½òoÒt²Ijc±Ø‹:Hc°Ré¾q&”è!Ò$‘,ãÔåË£ŸcJÌ{üâ8 …TUÍÔä;•oï[-Û¸h(Üa‹Ê)ÆØ»5®|à ÈäÖ|>³gÏâÌ™3ØÚÚµk×xJɤŒUò#.“n ýÉ”ˆzkRÉ8$’ÊÖ4¼kè]'©øPz=ï“,÷н›fO€(«0ˆJØ­€øõ«d¼MÁ ¥Qšæuêqì 2rƒÉXÓB_g4gA´ÚÍ/z œ¥|[–•í$’]$­ÕÝ"fÌRÆ£¬•w5AgvOÙn6{ƒ ªNffÜ+—ý­Ýs¢W™ÃŸ´± ’×Ò‚ê¬N¨A8 Á±>xïi°¬Þ{&nÍ7yòˆ¬å™¶|½>»Pè%ÜŠB~]ŸZLuµ:ÙRŸU²¼Ç»ªÌb bÛ6ÇɆÊ4ãÀry47M¯?‹é×Î)Š×‹Åé†ÑŸ<éµ¥TâRN1ÌZ¾);ð"ÏP¤c_ÄSĘ *ð´ZiVƔ޶íÝ`Ðm½ÇacŠãxƒw°v„ùkŸ­õá9yrv2%³–ï(†adÖX­TzÁ,>Ô"Š%ÉèÜ—¶’…LñùÑ¥Aà ^òq×À/ÿòxüñŽt{© VÓ4qæÌ´Z­Ð‚ëÝÝ]œ;w[[[ØØØÀ£>:Æž/ö¨J÷ï? üùG€ø›át´ï]×'D¨Ý‚P订:­Ë”kèúŒÓ¿eôy‚mÛËF?Ê 'Z,œô¦´D'2%)½®Ú‰¾_¢I1G1†—‘±.ÑÚ¶F£op*ÿÀ`¿æ‡{k›§TŽš8¯òvY&ZF– š‘Ÿ+¶Ýÿâ¯T’ë 7ñ/‰¸óÞJ ¬¦õ&”è'N`TÕ Íj4¦fOk3ªD®:¦i.¬®09jú^)‘°¿`pŽ,!*ä¥LÁÔr»èzÏ+ i$†¬d¬Fó~t‚ö/þzâ¨Ìwû·OáF—‡ENÎ ƒ†ê>‡GBmk²çþn§ptú ¶sˆ@R ]膃÷F ˜‚× ŽMqJxÒ…|øÃ·ãyÏ»>Òí¥2XÏŸ?Y–ñÈ# —ËùŸçóylooc§OŸÆC=4Å'?}FVèÐ àµO?ñFO$Ï3©À3øº³.¾,Kƕ޾ÁmäQ—exO¡·A‘l˜ÿÛ;ŸãxÛL3f\o ~Mì0Tô­m%=iC"j¦ÍO|ÄiÆ']ëƒQÏ,ÐÿÞˆûª+•Õõî,ß´è8&Üɶýàù0Þð¼+Ë“k å2ô·¶üIŽUH¬wÇ“݇ Ì·6ý*aÛ6LÓœïŒ<)ª•J/ò Xô>o6ãC8¡g´V*Þ$Q¡àýÄ)굚×çÅ;ŽkY/«Ý$(ÊRÕ^%ÇYèúUÊGŠü#c5°NN–Ã"âwhÈ`†‘:a‹(öæc&òägÆ£}j؉)ê(ÎXEü´ßã1}D²ì] ®Ñ½ïÂöÅÛ”¨PhÕ´…$ÆSÀë_ª:0ÄŠŒøç‰.¡,Øôîg½ª®{ÉûºÜzëh™°‡¬‡‡‡èt:xàî÷ÀàâÅ‹h·Ûc<åù`Ûvú°eRLøéï{1xwk¬†fR‚µTC‡gè.Oz€îúTôfØ6Žþ³7ïêU«I»æ}˜mý³?†1\7‰F·•Jác‚•JÒ¶3*óÑIrN¨jo26)¯A¥’¸Þo¯míö-X5RÉw¥âYY…‚÷…'xcÈ©b¶ºTÓ°ªlf;ïi“z†±øª ”`¬Xÿ^*•Õ1ÞçÍB2 ‚·¨<™4í>Ì«IF+%ϫ׽ó¤1FÈ"X„ÁJ†33w ÃX˜w5¸&5†t3Å Z¶ ý­-ïø´ñ»)_†Ñ_¶{l/fÒs5ÍäŒÚår/âaP¹?I‚úÚ÷^™¶Ý ­'åDÓ¼-ÅYôËlÁضéÒM–ÕË_`¹ÆÀwHûÇêÁšæÉ%Q&qa¹þžb2À²MŠ3FÞO7£ÍÙöhs3•ªiÞÎÍ&L¸ûî'F¾½¡k«ÕB.— yVøaÀm¿¶à…âƒHÕ!hæ£Xô¾à§r°À~½5Ÿfïwý›½ÿe¹;xÆ•­)Á3Tkð Öà !´ÍÜÑ€Ùê]=EUÓƒš–Ü,Ë»½ ñKçT”ÁúÉIž,§Õ©ªÕþ~$I½çCQ:§®÷î-É™Aï…¸íTê&—[\³Y‘j}vµ {”²ˆ¢ÀÅð@UNôµç×þÚ×ÿ»ÞÚ Ûö¿·a¡]IÑ•Þ}öÖ“,Aðg½>žÑŒº™…Áú[¿U™ü$…¼O3‘·¬Á‚Hîž´F3ÍÔÌÛèd–]׿qrœžÒbðPÑuØ­§¼MÁù háë} c²h®TPFíAI–šÍJ’aŽZíµO{™VOžì)^ä#ëfY¤¬§!¨O&6³RLÓ×O€^’¦Ð>–åé_¥Ò|²O’wuÕjŠË#–œi!$É“yUõŒóÍÍÞ} Âì Ö ¿`pýýý™×cš6Á ª Ù‡$õfJ%Øÿ ë*ßGoÝj×0µm@{Äû(¤tF¿S½p_:…3‰G3{Ô#,@ú%@ú>ïOÊ¥1ÌËJ“7I†w{AãWze›l;Þ(¦)â%Žœt"FYïMï Š˜ ØU¾E_UUíöëöy}6zåCaíè% M>”JþóЙmÛFùGžñïmy'Ò4Øw¿6ô%%è  ‡$(“z\”À LÓÓÒ(9iÔ©,f¹<Ú³'ƒ7ñNã}Z, ØØøÂh Z"fî}"{™`YAXXJš°Œþî¬÷Qè]à8¿÷¯=½vÈÀfÛ@åÿø˜§‹½êõfš(æx™ºÁ]û¤Vóì!Š+!g öÇÇÞË‚JpÈ=€l‡áHÀÄH÷î EpMw½±ñL3~Íô¬ Ä}Ág39DŽ3y^« È]#ËžO3ûÝû¶,àÛ¾m´õ«@ ƒ5ŸÏ£Óéàððpà~´=èuÍ–eùVËê…b;ýÓÚ±qs÷x=ƒõ×þèN’×Ê쀇Õ@ßÚPûC€u¡z¬¦ (7ôâÁ)®;:xYe"¦¸øAÞS*â4îRtÕN¼{¡ŽE+A(BèEÐçqÐ2 79P.÷ä ÝdT1‘vôÞHz—Sÿ:隉ÑI³]hRð唯èÒ*Ë5L2,Â÷†ò3»»Z‡ùý{} ¶¢rL¹’ÞáÔFYöړư¤({MóÆÌANh]÷ŒZËêÝoœRDÛ‚÷2(´—È·kªBc==;Më…ÕË^{£ýÈ0€'®8KÊÔ“ÑÐL Å–•¼&•af̬&d‚Þ‚ÞÍÁ±4:Žù Y‚ëÖºxhì²mÈžòvIˆ‰$@ùü‚§o|ö¾Ög4¿ áë]éê\’PE©i&ë^e²œl‰æLñ#Ý£²Ýµö¢‰H}t½7Ù3‹Æéy¥R¿MkÆ)‰R¡£ C{ÍïBªF6XS-ñŠ(]¶=^”c*ƒ5ŸÏcooN'vŸN§ƒ½½=lmmeÖëZ.—Që~qT~«T6·žë{n?È„[º™ÏôB‚¿ú-€ey_”  ªRû'ðŒÕ®KzžD’¬’ŒZ þM“ GGýKwîÚí6Μ9ƒ‹/âððÐÿÙÛÛÃ÷ÿ÷£Ýncwww¼V̘J¥Y–ýõ}ä+Iê/´aü÷[â%U€Òww…óÙ€sžÑúÒÏÀ¼ôYoP–à²òŸÁ÷†RXãÑÐ0:ño›?ø¦™m©÷Dò7¡4XI#â¼™GGñ‚UƃQActÎØh„ßÔWƒJ8×¢Ÿ‰ëW#SÓš–<Æ—J½IÀ ®DáÂÑñÖqç3_†ôЀ¢øãçæf¸l#-ÕHR:ª›K×–¤^Ø/yìƒaVÑšæ)Á~,·¤»Ü$tlp­4!нPù ¢˜._[–éî£Ú¸woìÚôBôh÷5JHvË-O¦kà’aFúäqk¢PB$6P™ @Ñ2yœ¢5»sQ4-5£DÖ–Õïͤ\cò>ß7r QøßÛÓn(¿¬wÌ¢8Ûî¶!9±^*_ø'pýúv6M˜¿ó%È0ûfæ†æ­¡0”ÍÍ„=i¾Þ0B¥Ž].HpX×{ùÖ<Ç’®ëey¼ÐwRVæ€ ÓAûúQ\I›föŸÝ Y+ørê‹ë °@ÀŒ¸p$a)ýkí ê/¼(ý y?Ý>a¶r<ˆâHkÃNã¹èònJ®]»æþÜÏýœ{êÔ©¾ŸŸû¹Ÿs¯]»–öT3áòåËî… ú>o4®$Iñ©ªëžù¯®«º®[wÝzÝuŽz›Ê½¿UÕuë/r]·áºîÿÄUĦÛlº®{亮Ü;¦VóŽE×=>\뛿ìºF·M®w씩×]·TêýÝlº®¢„·ÇqtikàñȲëJRø¼®ëºÕªwîàóJÃñ±ë ÂèÇM›$yÉ2÷ßâ6Y–Ý£ÀCm4\ïadÿø¸÷Q½î}‡ÕªÚ.Šýç>:òäZU]ïŸZ­·Q’»ÉßmœŒ‘\5›Þµ›´dQQz¿ÑæÍfïÞK%ï'®}Ñcˆ¤¾}¦4Di4ºÏ3@t?Yö‡Œ‘(•¼ö ’—,’¶O–J%·žôDQÕþ½èÁ‡™ Ë6†§íÕjÕ­Å Z£ ªn³Ú:¦MÄñ±Û8õ`ïAíèȇå»þØ­—1YõÅêÿù{néôG{Û›Mוe·ñÆ_uKßrØëË²ì –]¤Ztéãco¿®ârüÎw»†×¼h×o6½Ïé‚ï:úÅðØ?Hw‹ë£ÃO­z-'²ªãwQCzˈÇ|O£#×mœz°÷Å+ŠÛüµÇ¯/Š®÷Åþ/ͦ'ÕjO k5OÞ‰ãco?RZ\O~i—z}¸åø8|‰££ðßÃŽUõnayIm°ׯ_w/_¾ìÿ\¿~}ôÏ€¤›WÅmF˜f3ð%Éû£îº®ê}ÙÁ/*¨ìÖ뮫Þåíwü£®+Þ0ÐrK2ì÷ÁãcO°$ÉuUÕ¿ä´ ëÐEÓ¤>=ë³1¼çÁ²);®;ø&F¾hQt]õû>êÿèÛCŸ¹nψê›Tq=™øþh4¼Iie@ŽAQ&—¡R)üŽšT׋ƒŒùf³"()jô¨$©ßè¤÷M´Áç| ¥¥^Ûg«ªðHƒ´½¨ðF¿8Yž€¬1ãL\ÆA“ii¿žeÃÓöGI’ÆWâ»ÝùjW]Wú–¿r›¿öØHJèHû¢?«Ù£ñÿ~ÈUîþþë"Dôƒãc·ùžxÇG¬ÎP掽1³Vsý÷’üê¯ø¯ª ­+G ÁwÙܤûŹÁci8¡c¢ûIDçÑŽŽz“ 4y{ò¤5ƒ/lvŒÚUUuÕqõ‡¨w†çÅ9¬oü·úu¿º†¼q˜¨ø·t|œ<³M¶P‡‰ ͦçñ \;8±7?›æQN¨Æ¹®Ö}ACÆ\ Ö¬’tóQEÞWëu×½ïÇ<é±ë{I}¥±ûò¤ÁêèÈuk?æºnÍukç]W}ñÅž É®ç¥}×§Ýú÷_꟞ ¼«ÕééK¤¹n¼ÇÆu½>-Ë£÷›4Ly"k®,›²ãºÉ ÏÑÑ‘+éãcï»Qï~·[Ýõ€ GÑu“å%ã¸ý˜¥`ÚŽ4R$¢rõzxüR«y“=qÛè=,Š£?樇| Öf³é*IoEš!ˆûœ^þS”Ý,rt4åc’tÇqÎS­¦ó>¹îòáiúãÑÑÑà ™úÆòîŒÚÑ‘ë6?xÝŸþ©ô4›FúK½Þ³Ú† ¨ªÚß¿ŽŽúg$É9@hHue §æÎ“f3lÜŽò>£ÇBΆhÛWqü&†+Š¢{<®@aDQ"aIU6 Gßõf÷è]¾|î?¹7þjªãIFâÇ# ‰ŒÚçI62é„qÎqûM\÷ÅA6Îøj ë²â8N_l¼_–Å4¿úa/«¯ +…Ä;ÿÀg{!碔~@ 0?(ß× ¤R xÕ³ üÈ‹z ©þV`þ zÓ£B‰…§W[>Š,÷²O›y”b†M@C¥äÔ/ÿ4ô÷zõ‘%)ü}%ÉK*Ò.ÞLÁ¬– šf ÙÁ” ò5±%©"(Jr6eÊ`·þ˜iÙ*C%cÑ´äA°Vó¾)Êî,±ítËoûŸÏ€’m3 PðúE\6÷QQ”^µ4Ù¿W‘q’-ÑyÂzè€$yºÎ÷l ùÚŸ„üÍŸ ëq ?+ï‡ôJãnšýi„ã ]A¢uð€^öÇ}1š= Õêü+HR¯–ü¨å•é±Ðú¿u¨j`Û6ŠÅ"4MC½^v07ÉSwáeÅ”ý|¦9 $œiöÉ´e¡—`¢›5Uü¦gA|ów…öþÎwÁ|îßMÕTJP—;IJÂzJ¹ìý=´j÷¹ézX¯£¼Ád_”_iPU…¸®HÕzß÷N*¼\!q$é•Êtô±§M~ŠìWê£ZEO¸åZ¯/o7ÑKååÿŠžÀ•n†ßê‹{YdT5Âs—ÏW!¦(¬[y—uÄ4ÍÐÄŒe’m@¸çÛ £—áyrÊq9‹óOvŽ`Íã(\’o0†a ÙlöoÐõÁ™°Æ0Tu=>cú¸P’RÛþ=›O„æD3rÏŠ`•Ê¡3êó*—½ãÈ *•<åfK‚X–…êƒ)”r Ù£õP~·¿ð¦×¢jþ`*=Ý'.ÅzÜuGUÒ|ùq™KcàŠR«G¡P€ªªc×\µ,ÀøÙ«D¾d ‚?¸Ú?ôvàz¢¬XˆÏï øÝÿ/Ô»~òø™?ì•E߸SOWn¾Õ=ỼÙMóTü ê¿x®Ÿ|,8±œï R«yû’ÁhY½òŒÑýlÛ5­gŒKàIÊãD6w¹ÜKÝÆë¤á†&ç%Ék·¦yíÖu)Ñ%•à,—½c¦¡­´Á§È‹" X–7¥U„gh¡l¼ŠhOÒë¢çŒŸ”C¯$ÐWw•aæ‰mÛ¡Yùb8’½X{Õ ÖÉ#ž4À3Ë‹¦iñõúhêxŠ3•J/2EÓÂ5©îú(Þz‰7›^ fsBÊÍVW*éJ89Ž÷Ž›•—½\öÚA K4ë7eµuÒÅqÂÆ)Í;ЄA¹ì]«ÞŸÇI.O øÜu=üìJo¼áý@ü`ïCzˆô §ág˜ÑuŠ¢Œm¬Þ8,7aÞ"£r’¼Úäü.¤¿øÄ7BÃOµ @ã£×¡ÿëD¹ýc@7*±Yóþ§Ò@7[ue›ÆOAü#º·OTwoœ#ï%ENªœÑhx×–Q—ªgËS •¢¯' ¢8¸›“·7X./Š$õî…²‰§™¢’„'Oz§1rÓ²Òk0$˜Ò¬aøUšD R¼‡ÏU¡™lŒ$°¬î Ó­DL7 amÛÐu=Ù»êÇKxÁ—©ãôŒS:yü‚¥ò§WÃ8 ¤`žRD¡´qM&CP”î$ÔCÔ/2L³Wq!h°•³jÕSR‚Ï. qó ¤ Rä¨$…=«ˆ¦i‰áÀŽãÉL£áÙžT&Ø4Ê©x×_ÿî_öŸ`Ò°†™]×QcRÑ4½¾O¥ÛJ¿˜$ÑßfÛ€ùçgïz#’ì"ñ[oGõâí}Ÿ“ñ¯(´œüQƒÆ²hã Û ªi ¿¸èHŠD™tònÔIÅQö§wm{¿O3²o¥ V˲ (5lnz/½®c¢ß3Z†çû7Ñó¼ʼnëN3ÌÔ ÎÈG•H`µ•0œ™BÔÈyY)̓mǯ튮¿LóœUÕSnk5à•¯|W®Œÿ½eÃ0à8ŽL ÿó[ ÿù?Aí׿ 2k°¶Ûm¨ªŠV«eÚ(àìpå7íùÞßÔITpè/³P&•o˲pÓ—¾?|øº‘3¤2Ì<˜TÆCÞUÓô\†’ä[Q–å©d°-«!4Ža-Iûý,Ãq3/ëwǤòýÐ/ý~ø¯þ Oÿí߆íкõfÙ»ÊdIåÛq¼¼VÃóî»(•`YÞ0ÎU ˜qÉl–àóçÏ#—ËÁ²,<úè£hµZØÛÛKu¬eYøGîßþã6ðîgxj^˜¼NªÄ,œIäôõ{ø÷È‹9ÌŠ+‰aL*ã~fÉB¡W+%P…¼\æxfqL*ß/øgÿ ÿýÌ/¢PüÈ6V™¬0©|_zë[¡xæOý”¿`•&¬˜ù“IƒµÝnãððgÏžlll`{{ÛKL‚gýÏ¿Äßÿÿ7ðï:À÷lxžÕ&ØPe2Á¤ò _øÀí¸ç;žàØ&“L*ãŽãÀ²,HºÞK™*IpœÞšÊf“ f1L*ßï}ë[ñä³ÿJÿù‡ýõ¼£dLf˜Y2 E6 <ã ~ò6VW˜IȤÁzíÚ5@>Ÿ÷?Ëçóh·Û©ŽÿÆo!nþõOgòá K6{ypp°è&L×Iå>öŒ7áÿ6Š‹¾•‰XEyXµ>;.“ʸaønÍZ –åEonö×Í2«&«ØgÇaRùþô»þ?þ´ƒ¥VâWQV­¿ŽË¤òý{?}ïxñOâ•?þØöòN.®š<,{ŸÍ¤Á:¨St:á'Å•ˆ3—I3KÁµk×pe çMÈÄò àèÓÏZúHàU”‡Uë³ã2©Œ+/ü|ìEÿ/ʨasÓ‹¦ú¦Ë4´¯š<¬bŸ‡Iåûè~÷¹ÏáóŸÿö1ïg™ÈŠ“È÷4¶Ï‚A2¾Œ÷ÃLÆ _Fyà1œ!ÖmüÖ¦,Þ3<~gÿžFC‚gD§ÓÁÞÞvwwaY}ôQÿ3âüùóÈårþöV«åo´-ÍöY°··‡v»G}–e!—ËáâÅ‹©Û”Å{bÆcRùžÆöY0HÆ—ñ~˜ñ&ãË(<†3ÀzŽßÃÚ”ÅûaƇÇï帧‘X´Å¼ª\¾|Ù=uêTè³ .¸÷ß¿ëºÞLÆ©S§B³#ï|ç;Ý׿þõ· ;vV\¿~½ïš×®]s/\¸ªMY¼'f|&‘ïilŸƒd|ŒA2¾ŒòÀc8C¬Ûø=¬MY¼f2xüÎþ=ÊÓm0¯*[[[°,+ôÙµk×pÛm·ù¿@>Ÿ÷·çóy´ÛíÛ†;+(µy>ŸG«ÕB§ÓA>ŸÇîînª6eñž˜ñ™D¾§±} ’ñÃÃÃ¥»f2ÉøªÉ÷4ÚÌ2¾<¬Ûø=¬MY¼f2xüÎþ= ¬s`ggdžK—.À@!8::JÜÖétKž§Í7úî寨ßß*ÔiÚ¼ˆ{b¦Ã¨òUy$ãËx?ÌôˆÊ¸iš‰ûfUx gâX‡ñ{˜|gQçb¦ßÙ¼§Qá5¬sà¾ûîÃÙ³g=ôO’øÂ¾¸íÆ%¡ž6ÁÙGy<ò¶··±³³3ô~Ò´y÷ÄL‡Qå;«ò0HÆ—ñ~˜é•ñe”Ù8ÖaüvOYÔ¹˜éÁãw6ïiTØ`[[[ØÞÞÆ<à/ºÝãöO"—Ë <6—ËÍäNŸ> ~øà N‡‡‡CÛ4év&»Œ*ßY•‡A2~ÓM7-Ýý0Ó#*ã«&ß<†¯/ë0~“ï,ê\Ìôàñ;›÷4*l°Îˆ½½=惠õ!pâÄ áЛv»\.7pÛ°cgÅ p€‰Û¼ˆ{bÆgùžÆöY0HÆïºë®¥»f2ÉøªÉ7áëźßÃä;‹÷ÃLßÙ¿§QaƒuFœ>}‡‡‡¾LÓô¿ü\.‡­­-„¶ …Û†;+òù|_ í½½=ffÒ6/➘ñ™D¾§±} ’ñW¿úÕKw?Ìd ’ñU“oÃ׋u¿‡Éw ¿³O£r“ëºî¢±ªœ?ØÚÚµk×B ¤/&}gg¹\Î_Ô¼¿¿Û†;+èš4K5ÊýLc;“-&‘ïilŸƒd|ŒA2¾ŒòÀc8C¬Ûø=¬MY¼f2xüÎþ=¬3&˜2=nD§Óñg€¢ÛmK³}LÚ¦,Þ3>“È÷4¶Ï‚YöI–ïåcŒ/£<ðÎë6~ÛžÅûa&ƒÇïìßSZØ`e†a†a†a2 ¯ae†a†a†a2 ¬ Ã0 Ã0 Ã0L&aƒ•a†a†a†É$l°2 Ã0 Ã0 Ã0™„ V†a†a†a&“°ÁÊ0 Ã0 Ã0 Ãd6X†a†a†a˜LÂ+Ã0 Ã0 Ã0 “IØ`e†a†a†a2 ¬ Ã0 Ã0 Ã0L&aƒ•a†a†a†É$l°2 Ã0 Ã0 Ã0™„ V†a†a†a&“°ÁÊ0 Ã0 Ã0 Ãd6X†a†a†a˜LÂ+Ã0 Ã4M8޳èf0ÌÜ™¦ì;ŽÓ4}K Ã0 3Ø`efa X–µèf0ÌÜ™¦ì[–…B¡°è[bÖ]×aÛö¢›Á0så}þ°ÁÊ0 Ã0 ÃŒa¬À3kËûüyÚ¢ÀxgkJ¥DQìÛ&Š"dY†iš(•J¼°2 S’$ùÇU*¨ª ]×á8$I‚¢(þùA€ªªcïÏ0i$ß ilj•±iÉ8Ë7³f)ûÕjš¦á¦›n ç84Më;†a&%Nžé3Ã0²,‡äS’$ÿ3¯™eb\y—$É—]AP*• –íqak(—ËÐ4 `Û6677ýR©Tüm†a X,úDÓ4‹Ež‚²¹¹ ]×ýóÒvÇqà8ŠÅb( MÓ4T*•±÷g˜4 ’oÚNkù’d˜\ÆY¾™y3kÙ/—Ë0 ŸùÌgüÏÇA¡Pð!†™Ãä9HP>i¯™eb\yÿÄ'>“'Oú“†a„–l°l‰Ë,”f³épŽŽüÏdYvUUuŽŽú¶‰¢èʲìok6›þ¶Z­æ ‚àÿ À­Õjþß’$¹¥RÉÿ[UUW–å±÷g˜a ’o×õdŽ~w]O†IƦ-ã,ßÌ<™‡ìÓñFÃà÷É5ÃLƒaò,˲Ûh4ümQù¦Ïx¼f–IäÆcâøøØ×Ûi_–íÑáàcdY…‰5 Þ,Kt›¢(°, ¦iBÅPvHúÛ²,f=x¬ ~HB£îÏ0ƒ$ß„,ËþïÁýf!ã,ß̼˜‡ìz‰œªÕê¢oŸY1ÒÈs”¨|<^3ËÁ$òNÇ”Ëe(ŠY–ûŽeÙ6X3Ì ’¶mû딂Ľ fagÖ•qeŸÖ –Ëe-ú6†aÖQÑh4üe|Žã T*¡V«-ºiK ¬ j˜š¦é/¼N2Z%I‚ ¡Y›èì;Ãd$ù¦ÄaI°Œ3Ëμe¿V«Áq†á'a˜i1®<3Ì22®¼“þ^«ÕP«Õü²c’$q_™Nº´`J¥’â x„qÃi%Ýe9ô7Ð[ôÍ0Ya|ƒeœYf%û‚ øÙ*¹ì3-ÒÈsÙf˜e`yzVÏãÊ!¿“ÃÖ#Š"jµ …dYögf(vt)2¤”T*_©±m{hŒ=ÃÌ“Aò= –qf™Y¤ì+ŠEQP.—¹¿0Sa˜< ‚€J¥â‡?2Ì23‰¼—J%†“'OB’$?2FQ”EßÖRs“ëºî¢ÁxÊ͆Ó:% EѯÃJušêõzh FÆ0Y#N¾ÓÂ2Î,3,ûÌ*‘$ÏA}%Zk˜a–•Iä¼³‚ ð2¦)Àk†±m'OžD³Ù„$I°m…Bªªò &Ã0 Ã0 Ã0+O&Ö°¶Z­ÄÏÛíö¢›·0‚! 7Ýt677¡( «KË7³ê°Œ3« Ë6³ê°Œ3ËÀÂ=¬{{{hµZØßß÷?k·ÛPUÕïD²,÷¥÷g˜e€å›YuXÆ™U…e›YuXÆ™ea¡ÖÃÃC\¼x±ïóóçÏ#—ËÁ²,<úè£hµZØÛÛ[dSfdX¾™U‡eœYUX¶™U‡eœY&–%¸Óé R©@–eܸqÃÿ¼Ýnãðð—.]lll`{{ØÝÝM<Ÿax×»Þ…;ï¼sQ·4u®^½Š»ï¾{Ñ͘ׯ_G§ÓÉÄwtýúu<ýéO¬§Á´å^ÿú×gâÙM‹,ÉôÈRŸ½zõ*>øÁÎìü<†'Kò0 ²Ôg¯_¿AðoþÍ¿™ú¹yüN–daZd©¿^½z¿üË¿Œ|>?“óóø=œ,ÉÃ4ÈRŸgü^˜ÁzþüylooÇÏ_»v B4ŸÏ£ÙË^†{î¹gèKc™ØÙÙ …i,;‡‡‡¸råJ&¾#jˬ˜¶|ÀwÞÉòq²Ôgwvvfz~Ç“%y˜Yê³³ÃyüN–daZd©¿îììÌÌXxüNC–äad©ÏŽ3~/$$øààív;ö¡ êN'qÛ¾ðX–µRa «ÔQ`kk+3åÝï~7>ùÉOÎäü³oøÜç>‡½½=Î÷͈¬ÈÃ4ÉJŸÝÛÛÃã?>³ó󞎬ÈôÈJŸ=88À»ßýn|úÓŸžÉ¹yüNVdašd¥¿Òø=«„G<~§#+ò0-²ÒgIuüž»ÁÚn·qñâEœ;w.vû  [ˆrë­·â%/y NŸ>=ï[b–Œ'Nàî»ïÆóž÷¼©Ÿ{Vò Ï~ö³qúôiœ8qb¾ŒY:NŸ>™œ›ÇpfÑäóyÜ}÷ݸí¶Û¦z^¿™,@ã÷´åàñ›Y<¤ƒ*ßs >88ÀÆÆLÓ„išhµZ¸víööö°½½=0"—Ë%n»õÖ[ñÒ—¾[[[ó¾%fÉÈår¸ûΈìäð–o& [[[¸ýöÛgrnÙE“ÏçÑét¦>†óøÍd¿g1éÈã7³hÆÕÁçn°›}¡ÙÇv»íwŽàï “eX¾™U‡eœYUX¶™U‡eœYVæn°nmm…f`(Þ=W½µµÊHfš& …¢Ÿà …å›YuXÆ™U…e›YuXÆ™eeaY‚±»»‹¢Óé`cc÷Ýwߢ›Å0Så›YuXÆ™U…e›YuXÆ™,²pƒ5.cU>ŸÇ{Þó?Õ6ÇÄ3Ë Ë7³ê°Œ3« Ë6³ê°Œ3Ë Ö$666¸“0+ Ë7³ê°Œ3« Ë6³ê°Œ3Yc!uX†a†a†afl°2 Ã0 Ã0 Ã0™„ V†a†a†a&“°ÁÊ0 Ã0 Ã0 Ãd6X™LclÛ^t3†a†a†Yl°2™E×uT*”Ëå¾m–e-ºy 31Žã@×õ±Ž3MÓÿ‰›Ôùüç?¿èÛc†a†™˜Ì–µaÖ˲ išÍ&Êå24Mƒªª€r¹ Ã0P¯×!ËrèÃ0úÎcY$IH’˲ÐjµpÏ=÷,ú6™5Æq ‚Ã0P«Õ Š"lÛ†®ëPÅ—[Ú¿\.ò,ˆ¢ÚfYlÛ†$Ip¶mãöÛo_ô-2 Ã0 ÃL ¬Ì\1 †a@UÕÂMJzp¿z½AP«Õ°¹¹ EQ`ÇA£Ñ@¹\F³ÙÐSæUU… þy‚[–Çq ª*>ùÉOâÊ•+‹~Ìá8Ž/‹d¬–J%”J%†á¯ ( ŠÅ"šÍ¦ÿY±X„¢(¨×ë‰×°, ‚ @Eììì,ú–†a†a&† Vfj8Žã{4éDQ„ ¾ˆ”ñz½î{<‹Å"TU…ã8pÇß‚  Z­ú }£Ñ€ $É÷¼–Ëe(ŠEQÛ4fÜ ‚’E’q¾UUU”J%ž*Ë2Ç(Šþ~…BÍf•J¢(úû'Á2Î0 ³XÇ€Ðäù¨<õÔS‹¾ †Él°f 'fÐuš¦ùaŠ‚ ôyPMÓô·ž2N#ò¦R¶EmÛ(•Jþ9ªÕ*677ý—… 3̤8Žã'üІæÒv õm;’+Š",Ë‚iš¨V«0 š¦ù2N!»Ñs ‚ê÷Š¢À², ?ª€a†É.š¦A×ubR’$H’Y–uŠþ<]É0 ÜtÓM‹¾†Él°fÍÍM4 ßÓ²H‚Š;€Ñ)*• A….Æ\kJç©×ëþ:Õ4zÔ ¥R º®û¡Á 3 Žã@Ó4†EQ Š"4Mó×R@p ©,Ë(•J}ýµR©`ssÓ  í†jµŠJ¥š¨a†a²%ÁÓu½O¢ÉËà{„°mÛÿ›Þ ¢(¢Ùlâܹs‹¾-†Éc¬{{{8<KeYPe"ƒUÓ4ضr¹œÊ $oR´pttä6®aÊ0óF×u†á‡è’w4ÆKÑä5UµZ-ö|ãœYˆ’`†a’!hÇqü0^AXÿa˜.¶mûÉSƒP™= W¹€&s(z ðô¢\.‡ç>÷¹#]w$ƒµÝnãâÅ‹ØßßÇÖÖZ­ÏÉår8sæ Z­òùü¢Ÿgf †ÆAk¥Rûü†aÄ–ƒ‰£\.C×u¸®Û·C™eÄ0 躎z½îG+Ðì¸(бkRfUÐu}ìÉN†YELÓô Р^CÑhŽã„–]Ð$'Ã0d€êºÇq I677Q¯×!Š¢‘I•9†éY‡‡‡#WêÉ`½ví`kk«o[>ŸG>Ÿ÷½®L<¦i¢R©„<—Ñí”°(X?4-š¦AQ”P9˜¸ÅþŽã X,ú ¼iš¡DÓ4Ù`e–˲P©TüATEžgÖÃ0ü5ÏË­÷Kz]½zO>ù䢛Éd˜ çT’$?Û:Ðs³µ3̪C^Ðh ÈèvвŒ®³†½Ëñɲ<ó\2#¬€N§ãÿNt:ßãÊ$C3}qÆhpœ$I~fÝ´½«tžz½Žb±è'†Á—¤:É›Ë^(&‹PVjÀ‹î r04ÈË8Í0«ŠišEq©½¬Áü @o ½i¦ÿå/9^õªW-º¹Ì‚pÇ×eèoò ’ŽE HÁ®V«°m{â¼ ³lèºî'“$ …BÁŸØ¼$‘†aø®¸D’Q(¿M\ÕƒY0’ÁJ^ÔP³v» . —ËÅz_™¦i¢V«A×õ¾õr–eù«,Ë}k*â „‚ øáÄÁX’$ù3ïúÍÌ›”P€a²) 𦅲îR¢$QûJ)1̺aš¦Ÿ}}«®ëþ û¬£‚ºUUõß–eÁ0 ¿ ¤HRƬŽã P(@Q”ÒM“–²,'æ#àP_fU¡1”b²,ûSJrJò¯ë: …TU…®ëe91òs£T=˜”‘“.íïï£R©àÌ™3¼8ä‹/"ŸÏ§2°Ö"Z£­·JŠ7àšÃŒHš1¡Çq“,)ŠÒ—X‰ ðãh[—u†žY¢5~K¥RHŽÉ5ìÁÙñàDf”`ˆd°LYêw´‰JsPmái-%Lå,«ë‡a!„&*ˆr¹ EQúòsPÄ Ã¬¶mCÓ4?YkµZõÇlh4}ã|©TòÃä«ÕêRô›‘ Ö ìïï£Õj…²s¢¥áBxжa¡A8j$RXpœ •Ëeض+ˆ£’t<ÏD2‹‚’aH]§—aÖ™à»"îýB™ãÉH¥õ}¶mû¡”¶mûª`í`EQà8677ÇJZF%Ñ(“B|ÉŽ3T™Õ†–0Ñ2)‚ä1˜ I×uX–…Z­Ã0üµ§ ³Î Õ`T nIŸ$Ih4‹¾ÔŒd°bgg>ú(¨c@áZ€7»Q.—ûŠ ‘5Xƒk6H¡˜Qo.‡3³†”Y–C^RRŒK¥+% “Rèþ÷ - ©V«± ”I{1̉Ƹ¤Œ’ÁòRTÏ;x½¤ÐMf5¡‰ZsJK9(J,NþdYF¹\F¹\†išK¥d3Ì4¡É óþ¾jŒ¼†ucc¦ib{{{â‹âĉÈår±Û[­666·/4ƒH)Õ…$#5¸~•e…BÁÈéŒCŸqëey¦{rÖI¾“ˆfú$#• U I!…ŠÅ"gn\XƳõ3"XwXÓ48Žò˜FIFaù”‰˜Œ‹ Jï+±ù–!ô `Ùžš¦A×õ؉“a:M­Vó']8úk:°Œ/Ta„–®‹‘dä,Á»»»ØÛÛC»ÝŽÝgwwwèy°··ç‡omm¡Z­ú™‡Ûí6TU Õy]öõ±Áp`BUU‹E?<*:³(Š"jµÚ\5l°ŽÏ:ÊwÁõ§ä±§P¯à`+‚ﵡ²l¬f–ñl÷~QÅOª1ÍHUU¡išNL!œ¤H%­‹]X¶§½ ¨ôŸò1íõÓë Ëx6©T*ÐuÝŸä'݉òÔjµõ^ÏïŽÈ©S§þ ãúõëîk^ó÷á‡öÿ~Ó›ÞäþÜÏýœ¿Ïý÷ßï>øàƒþö׿þõî… ž÷òåËC÷Y$Š¢¸Íf3v[£ÑpUUuŽŽÖ>Qýߛͦ+ËòÂÚ2f%/³’o:nY¨×ë®$IîññqªýUUueYéf0³’—uóÊññ±+Šb_¿9>>^è;eÖÌB^xüž.GGG®(Šn©TZiYœ<~¯ÍfÓ•$ÉUUÕÿìèèÈm4+«#/_3ªKÉ’~†AÉš(¤xcc[[[¾Ç¶ÝnãððgÏžõ·ooo/ýš…¸º«„,Ë s ^;i 3œu•ï –e¡R© ^¯§žI¯V«þ â2{gÖ–ñì`Y677c‹ÀÓ =“–íñ°m•J¥O,‹¨Õj¨Õj,‹e|ö8Žƒb±˜hѸ½¹¹‰B¡MÓP«ÕB´æŸõ¡#g ¼pÓ4qxxÀ 'e9ÕºÖ­­­¾/ñÚµk¸í¶Ûüß„’:åóùÄäe€JÏdhÒ'ftÖQ¾ƒX–…b±8Ö:뤒LL¶XwÏ Á¾ÆŒÓe{8ôÖ.;ŽEQBòX©T¸ÌLaŸ=T/¾\.û‰Å‚¯É@å¾1#¬{{{¸xñ"¶··ý˜N§ƒóçÏ£Õjáܹs©Ïµ³³ãwŽK—.ÀÀNÑétüû(ŸúÔ§ð|­V ûûû { q†‘ùµ”¥OE˜¦¹Ò³:xøá‡ñô§?}¦×™¦|Àã?ŽÔ“Có†èì°³³ƒ«W¯Îå:ë0†/‚J¥â—™!TÂlÝûÚÞÞ._¾Œ;î¸cf×X·ñ{¦iúJƒ “TUõoY–Q,¡( ,Ëb¯Ü˜ÐøÝjµfZ‘ƒÇïÙ`†¿V»R© X,úIð¸„WOuüÉ`m·Û¸xñ¢¿x>ˆ,ËØÙÙÁÙ³gSg»ï¾ûüs>ôÐCØÝÝõÇqãÆÄÎò²—½ ÷ÜsOª¤OódPªö,³lí…íímär9\¹re¦×™¦|ÀwÞ™ÙÁº+ÐYc;;;3¿Î:Œá‹@×u¿Ö¤$IÐu…BF¶m¯}_ÛÝÝÅéÓ§g:†¯Óø= ZæQ­Vz…$IB½^÷—„0ãAã÷¬ËGòø=9ÑJQIgÝYµÆÕÁG2Xi&&nÀÚÚÚB>ŸÇµk×R¬[[[¼yUU±»»;°ƒ.Cjí8á]–Œ§q¥u˜ñYFù&oÎ(Ἆã \.¯µ½®,£Œ/š¦…ÊÐÐ;¤P(Àqîks€e»‡išP%•~ I{V—–ññpº®û}ø2¿ •ËÊÈI—ÄÎÀt:T1î{{{}3ÿ;'NœKh·Û™é(•J%q›®ë(‹¾RxÂW¨=kȲì·9ZÓIϲËw±X9}}¹\öËY0«Ï²ËxÖ¡úè\*• ª*ªÕ*÷µÁ²Of¯,ã“S©Tà8šÍ¦?±X.—ýµÁ<>φ‘ Ö­­-är9T*•>a>þ¼¿Ï NŸ>ÃÃC¿¾àÍÞQgÈårØÚÚÂÁÁAh{¡PXô³‚išÐ4 ¦iöm£úIÍf¥R …BÁO:°Œ±êl°ŽÇ²Ë·$I~8,ËB¹\öû·Ó¬óÈd›e–ñe@Ó´Äþ¤(ÊRL€.+,Ûñ ªrÀ,,ã“á8LÓô+ðëÊ ŸgÈÈI—èezï½÷†>Ïår©Öglmma{{gΜÁÖÖ®]»†7n„ŽÝÝÝÅÎÎýEÞ÷ÝwߢŸLÓD©Tê[Ümzá[årÙÿ,눢èÏQ@ft–Y¾)|ݲ,hšÖÖBÙíTU…®ë}rϬË,ãóÀ², ¨ª:òDŽiš±ÞUf>°l÷ÃÞÕÕ‚e|24M‹5J©tÓ²,\FF6Xóù<yäú fOŸ>=Ô³äܹs8{ö¬¿&6zl>ŸÇ{Þóh”sÏÊüU,}Ų,†£££Ð¾¥Ri©7¨ -£G8K,£|S6RY–!IR_mÇr¹ Û¶ýìv¥RÉŸØ`yY?–QÆç­ç®Õj0 år94?Œ¸‰"f¾¬»l“BN:aì]]1Ö]ÆÓ—4•ì€88Òl¶ŒU‡µÝncccÃÏvxx8rŒ{.—¸?3Î TòE¨ª Ã0 ˲¯œ¬l€Le“o]×ýÁV(Š]×ýÚz²,÷%Ò`/Ðz³l2>h…îjš†ÍÍM¿¯H’”h–Ëeˆ¢ÈÆAXGÙv•J–eÁ¶m_¯±,k©&ß™t¬£Œ§essÓ׃mÛ†ªª(•J}€™ù2rÒ¥ƒƒÜ{ï½ØÛÛó?{衇pï½÷†bÞW 2P/A‘iš~QàU —¡¯ 4³D“ƒ©ª MÓüÐFöú0Ì`t]‡mÛ¡¾¢ª*ŽŽŽÐh4Ðh4à8N()_ôØU™üd– ’KAÐl6aš¦?M“õ ³èºîgºn4h6›~F`Ã0xòfŒäaít:ØÛÛÃÙ³gCµ–ö÷÷qñâEœ?ÞOÌ´jX–Õ§ˆhš¶Rë÷AXÊš±ÌdT*(Šš5µZg&¶m§zÔj5"ˆÞ'´¬„K0ó„äŽ<ªäE<9-—ËPUue&ä& Ѳ4‚  Ñh X,à À‹d$ƒµÕj¡ÓéÄ>{ö,FªÃº,8ŽÓWêeÙÖ¨¦…=¬ë…®ë0M3VYælw “ŽQÖªªª QCÙæëõ:O 1sÁqhšæ+æÁ\„,ËÐ4 𦭤žÃ0qPTAÔ(%£•Y,c­aMâÆ‹¾Ÿ™@E³W*iÂ3ªëišÐuFƒ•e†MÓüußiY™ò4Ž‹+sKmÛ~éh¢È(ªª¢P( ^¯/ºÙ 3’23Ù`¬:¬çÏŸG§Óñ?ït:~Ö|>¿è{š:ëdÄqHðz`Û¶Ÿ0ŒU†Û¶¡ëúú®=µ,Ïhe–J®—&',Ë~Vx†Yu¨¾*Gd—±ë°øÆi«ÕÂÆÆö÷÷±±±±è{š*¼ I°+³Úâ“ 3:d¨RXåÚ*õ’Äë’à8ÎÀ’qðûY¨*“]Æ®Ãjš¦_£i{{²,¯œ± xúºxWi.g\mÆQ\†ñ0 •Jªª²J~_,¤¯µ¼2L´<ŠÉ.C Öv»N§Óê»Jå\’XWÅž ÖÕ†JذâÂ0£S©TÐh4xœ â8žñÊd]××N—a˜4P¥Ó³M*ëÅ‹Ñn·±µµY–Wrj´{]{ÿY4Mã™D†ªÇÍŠMQôÖ²®øö²AOEQ„®ë\¢ŒabXWÇÔ22Ô`ÍårÐ4 €—|èàà­V ù|Þ7`W‘ubAØh]q(+Ü 3:º®§JX³V( ‡gB¡QaÛ6ÇY+]†aÒ²nŽ©ef¤5¬Á0`Ó4qxxˆ‹/®œñjYÖÚ®÷à—Új£ë:gÁc˜”PJAüº©<© Rñ<«l°f Š d‘¶mó$%ÃDXGÇÔ23RY› ²,ãܹs¸té¶··ÑjµpæÌ?Ó2bNž< MÓ Š"TU]t“fªØ¶½2K 3kt]Çææ&*•ŠŸ!Ÿ `Yl¬fÊS@°±Ê¬  ŸÓ×Í1µ¬Œd°öý}þüy˜¦‰Ó§OãÒ¥KK½¾Õ4MÔj5Ôëubfå°,‹†I …ÏÓì»(Š<Ù)™Â¶mX–Ųʬ%år†aô}®ëzßgÜO–‹Tk«Õ½÷Þ‹ÿ3Ó4±³³ƒÃÃC4 ìììààà`Ñ÷3¤ 0Ì*Â+ä‡ú‹ ¨V«kQ‹›Y~¨Æ6ì#–eùË7Ã0P.—ájF;ŽÃ¡òKF*ƒUUUäóy\ºtÉÿŒÖ®^ºt <òvww±···èû\fÕáp`†ImÛ¼^u–å•´©Tݦ‹iš¡p`†YhÌŽ¬äŒ z^¹Ÿ,C ÖÃÃC´Ûmœ;wÎ÷ít:hµZØÞÞÆÆÆ`{{N§/lxY0M“•f¥a+ä‡ÃÅR Š^ýUËZtKxÞUI’x9³–4NÇeY¨V«!CÖ²,Öù—Œ¡k«ÕÂÖÖ–o˜ð¿ôàË<¸}aåd…),ºÙ€£&Žã°ÒŸzFP;f18ŽÃ‰Á˜µ†¢ÈdYöíʘ-I¬ÀÄ/\>†¬èt:¡Ï¨ë²©AXxW»û³Æ8ŽÃÆ*ä„gßS4RÙ`]8Åbªªò8Ϭ-4n+Šâ§ÁÐ_ò¼Ú¶ AxRrÉj°æóy´Z-¿\M§ÓišØÚÚ íG¡À'NœXô= {žV±û³Æ°Î0é1M“ß Ã°m€Æ~V ¥R©@E®±Í¬5dˆ^VwÓ4Cºy^y àr’Ê`ÝÚÚÂÎÎööö°³³ƒN§ã{#É€­T*ØÚÚB.—K}ñ !œ´½ÝnÏü!°2?&fã­tÌbÔ'þ³"ß+àÌlÈ’Œ§Á²,Üqǡа88áR $ ¨V{OÃËZ©1%)Á²È6eE­¿ †IÁ²Èx¢Q’²,£\.‡+‘çÕ²,N¸´„¤Ê\­V!Ë2„0=ôÐC~á´&•É9sæ Μ9ƒ{ï½7ÔiÚívhÛ¬×dðúÕÐ1ƒÕ0‹D“<#{Ž:PÖäà`fºdQÆÓ ë:J¥ŠÅbl]>‚'1GD'O¼T.¦¹ðNË&Û†a T*qx#“še“ñ4D“J*ŠÛ¶û Sò¼òø¾|¤2X766pîÜ9<òÈ#¸té¶··ýmÛÛÛxä‘G°¿¿ŸzMëÎζ¶¶`Y}ôQlmm…:Äùóç‘Ëåüí­Vk¦%sXxG`VK³ Û”0×5¬Y“o€KÚ0Ó%‹2> Û¶}OT³Ù„a¨Ä”cáÉ1˜ÔX¢ï¡^_¸Áºl²ÍÑ̨,›Œ§!ÚA@£Ñè딀‰Y>R¬€·Fuoo{{{¡Ò5¹\n¤0àÃÃCt:ìîîðŒá³gÏ¢Ýnûᇇ‡8{ö¬¿}{{Û÷îN*$̳“#`N~Š>,³CD5sš Ìš|¶½æY§˜©‘U†®ë¾R&êõz_½>€½«cAåm†¡iÉÛªUï< «–Q¶Y^™QXFOC\âÔ¸IúR©ÄáóKÊÓÒì´··‡‹/ú_¼xgÏžõ~òù|Ÿ7öÚµk¼ŽA¿SÈ1ý>«8zMÓØó4 u,t]èÈØ„îÏÈš|¬Ð0Ó%‹2> Çq`ŽŽŽüÏA€$I~˜0Áë½Sbšž)Š@šd?ŽãyR¥?ISPEoßL"/›ls43*Ë&ãiµpŸYNRyX/^¼ˆíím±òöö6.^¼ØWî& ¡ Ãív{{{ØÞÞF.—’üv€IDATØ)Æ¹Þ H‰Y†øüÌ `6¡»€ò Ϋwf±>6†,É7ÁY°™i’E†¦i±I6J¥’_`žàg)1ÍѼ¡ŽȲwÜ …«ÀòÉ6OF2£²l2žîëÁPƒ•Â)<€ïY”]lN{{{¸÷Þ{±µµ…sçÎùŸ'qãÆÄmŸúÔ§ð|;;;©Û@J ‡@³I`4«°]€ŒP⃃\¸pah¦ÐI˜¶|Àã?ŽŒÔÌ×\½zu¦×Èž–¤‰II’à8Ž2_©T Ë2Oð¤Á²F3,EPÕ©„üîííáÂ… øä'?9“[ËÒø=ο±šÐø=‰Ž=Œe¿ƒ”Ëýž ŽŠY.HuüN ´N5mr¥$Z­Ο? \ºt©/ô M¢¼ìe/Ã=÷Ü“:L™¼«Ífs¢{Y+lx†Ÿ`Ág±¬ Ʀ™Ä+W®Ìà‚³‘o¸óÎ;±¿¿?R[Hι>ßz±¿¿?SÅ! cxZ( ib²T*A×u(ŠÂï„QÕX’¤^‚¥ ØÝÝÅéÓ§g2†giü†eY<¶¯ 4~’·IX¦ñ;ÕUƒ Öåa\š9ÙÝÝÅÎÎŽŸ~{cc÷ÝwßÔnš2Š­ìLºƒÐšÍ©4&§“¤ñ#™ÝŸ¤pb!òÿŒÉ‚|ÓµªÕ*âÌÔÉŠŒ§%Ín.s0Ñ÷§3 }¼®{ÿ—J^–`ÚײâÊ5Í[ï:ç „e’mÎMÀŒÃ2Éx\û’â±®³ú 5XOœ8J¸DŒ[¿»»;4Æ=ŸÏã=ïyß±‚ͦÁÊô³šœ6áyX5³Xæ%t¯1Š1l¸_ s3T‰,È7àMʬ´Œ3 #+2žöB¥Ä¶=#±VKLÔ`ôœm»çI¥qɶ“Ådcv†,“l¯¼ÃÌ„e’ñ8AàLîkÊPƒ5—ËÍtuÑÔÛÌÈð ËY0‹š¦V÷GÂè!ÁUw$lsÐ+Á“±š×³–o^ç±F8Ž÷“1Ã, c8gQM‰iz^Ðju²’2IõS-Ëó˜F?KúnÒ”¿Y Ym˲x¹33² ãAh,‹Œd}g=y ëáá!öööüŠ{_&Ö"öåsAGrâ#ã'EràåÇñÊ E¨•˃ÃÕVVҗǯ䇮g.qMVBÆ ãq#±™$¯hq†lÒúÕà¹h2†éöíÕ]ÖÄ0­Se}g=Hm°š¦‰{ï½;;;¸xñ¢ÿ³³³ƒ{ï½w¦õ¢fÁJ¬:f k¡ç±uBë×ÿ}Vi±èe–tÐ N«¯;ŽWA¬ÇÇÀ¿ùÀæfXq·¼øIO¡ÿ™ÏÎ.T:c¬Å„Ì*¢i½µ~£à8Þº@¦ö°¦Ä4=è$žŠ$ãÉ4ã=©IŸžÁjÛÞdc0ûpÀx}Ú¸åÉ'ýäB¥R˜HŒaV Û¶}«™áè fv¤2X¡ª*Nœ8MÓüÔÒ–eAÓ4œ8qgΜYo«eY«=3ic°GsDx¡»£NzÃÿ¾ë÷{ ‡aô+ÚiÏ[.{Æ©((÷|ð#ïêõ°‡@ðÔóö»ü¹µ1XÇYmù^&L3½×Ô0Æ3°Öoà5~)¡prYö’"Mz®(–Õ®N}bÐ8%ŠÞö`›67½>U©à›ÏžÅí_ü⢟Þܱ,kõ«0LŠ–‰Žé¼>¤2XÏŸ?Y–±¿¿ß^üüüù󋾟ÔdB‘©`¼Ì¸Ã ÷û€~¬ëcèÆ€BøÐ‡Fo“"¯|¥w¼m{ÞQJðAÉ‘¤[kZ«GGž"³ySÏ›,Šá0µÁöö»ã·¦ŸÙ8£pŠ÷`Ûã…&êz:¯)ãxMl{²u‡+ {WS"Þ¸)“­ƒŽ vo"&ú+Š@sHæ¾F£? T­æEæøÄÅ‹øÜw.úéÍr¹ŒZ­Æ“’ N0¹N 5XÑn·ñÀ ÜïìÙ³h·ÛKl³Nl™è:%^¢Éë‘øº?õþÿ_žlÞ·\îýî0l|‹g<ž<éýOÊÑ—¾4^’(;á÷ ¥’êvõ}½pæ5€ Ö)S©Œ—ƲÒGJý¨®A™V×Î$9CâÞ¡ŠÒ/¿››ÞçÓR(eÙ[R­â¯n»mÑOaîT*ȲÌrͬÑÉÇ•×á™X†¬­V ¹\¹\nà~Tæ¦Óé,úž†’)e~ïžq6à6e9AÏ-'ƒ/þC/‹äù¯Þû3Éû•Ëak˜&Ýx Íñq8cdó¸ç½Jº¾iö{¸lx†n=¯r`ë·îyFs—g_}6îüŸ«9;Ï¡3À²Æó~ÒÌmŽh0Œñ½«ô]×ú­1Žã X,BEî“Ò ¿íC×û'bâ<´GGýÙ™±°m›C™µ$5&Ë2œ€.ÈÆëú0Ô`ÝØØÀ7ÝΩ‘©x÷i× ¥{£õ«;årÌ$¹ཟõ”¨’bÀÆ÷xÊqÐ;Å0¼W«áσ÷uí¾áw{ÊOÒØ5‚í|¾Äk_ë=—.wü—;pË“·LþÌ3gœ2“¬m4¼Ù!Ã@¥’†OFç8ß™iöú¢e­½Ñê8 …DQDm”š¢LRJzÄÞ¼L ë:TUå±Y;(áÒ¨Û˜Tf±.q6 5Xóù<:ÚíÁ! ”picccÑ÷4ÌÅ»OS¿ì®íϘpîØ¥uÿé3ÀÓ?ä)(Q%åáëÀ—ÔûÝàÄÌòRæÞ¨¢hÂóö&ÍüÀí=%©³=)ì‘<¬ÂkuÝkËqà³ÈáÏüô3Ñy~ö£Æa-š8Ϭ”Í4 ² XVò2XQô†{nê«’4Y–×@Ó4(Š‚jµ:ùÉÖÓìïG´œ£XôÆò8ƒuÍålÞ8ŽÓ4Qš4)Ã,!ÑåQ¯êZè<³À²–ª$^*ƒ5ŸÏCUÕÄpßN§ƒ½½=lmmù¡ÁY%SáUL7s-u”ÉwÈ­ö=Š|Ä;PŒ1Xÿù[€·>{ð Ëådï+µ©¯Ú¯ë)MqûÄ%í¼0`=£5xc¦9°#ÞܹŸ»ós>ðì±6ÞUØŸ71v;’4šAzòdú}ƒ±ý²£X–Åå>F!®ɲ·ö4nâÒq¼Äy´34Mãu«ÌZbÛvß2¾µÐq¦ ÕµB/I­ëTY‚Ï;‡v»3gÎàààÀ÷¶¶ÛmàÌ™3h·ÛØÝÝ]ôý Ŷíì ü´þrXVw­\÷ïýÙ¶=]£OFïiÀS¹xCWDo½­Üßî;žóï„qëkl$g¶|öVïwÇñ¼±Áë\`^ Üg°=’ä…6ÿ|d‚%`Ô>óÓϜ҃Ïk3©9 ¦Ù“¿qê¤vQÕ”ïªA9*‚ௗ]Wâ”&Ç Ë6Aý*ÎKMëT×|bdž8ŽÃkW™µ@Ó4hGƒa}:{Ð`åª)‰[“dšÞ˜¾$3© Ö|>ýý}œ8qçϟǽ÷Þ I’pï½÷âüùó8qâö÷÷3ï]Z¬½ptŒ—èWœ)l–Âd¨ëÿéŸoV²'4áÑ9ïþœ'žÑ ìïèVBŸ C˜¼CQƒÕpå[â n–eàáÏ?Þÿ¦x7o_~é—Ç|ðÙ&Sk´ƒ˜fÏ33 Dqòš‘iˆ†£§ Ÿ¡rJ¥”y•$i|£³Tòžó†õ²ÂÉÆF¤R‰HE\rFU¹ŒÒ¡0wö*eœyFý¬(¦iB¼»’¢f‚º<¬) Èà ¤GeÉ.@*ƒè­<ò4MÃÙ³g¡iyä‘¥1VŒy  „¥FÓúJSqö÷¾øó?ï~6ø4V4ŒV´=ã1Gθ¼õœW{“ôIƒ†ÒÕ¿bÚDkpý]PWw ßWðÝ|Ž‚Üþ½À‹^Þcû† Ï(#pÝÕHJŽ—Qô2½3sÁ4Mö®.åÆŒ…ã8¾~NïŽãÄzPEQ íä n¼TòÞ3^F3-?Jjƒ•Èåre»»»eÙ/wÓétüÄKYÆqœÅÌTF=žÑ5j3Œ~£ãxŠÄ—þxÖzŸ%èn$·¡1À¶ÂMÞïitåÈ>õÄnŸ¾Š~ƒ•<·äa}ªÕ3XM'þ?ൠÆepY`ô9¾êõÀ?øÚðþ÷\ïf|:§W3áRf×°Ž«ÇA²>!,Ü’”Θ fïíb½ï£¸xihZü}¤õ°ê:`Y0ŒˆÝ+Š@­†ÿã¯ß?Ÿg”25™e’’ã1™ƒrndrLg¬ñRŒi`š&E,Ë0ºžjú,J°?°Áš’jua¡¿…Âtü#¬I´Z-ììì,äad*D€—4hPöÜ8È“õÂPœïß=ÜòûÞg “&²ìM¬„q² ÈÕär8q%pºPsbÇkÇ»?ÛŒ1mÒº÷/žgèuOý£œø p~;þF‚ºiô9Þ~ð’—„÷Wï™Y&·<ùä~9È\lb’Ò0Qf¹~Õ²¼ì¨I£k7ãï¨m”e ñ¡gÀùã/ô²X›f|XsZ/®a‚›Kœ¿xálžQF±,+›Ñ“â8ÓU†Ëe/¬—Ãè2O4;*“a‡=¬@K:J¥RÈ`M’2T98% óK¥éØÊS3X—…yWIÙj•TzfÔæØ6ðÒoêO®Bá(Ïû6àýW¼Ï–ø‘Ùçðª Ù€vÐKº„ÊĈ"€÷',›³ÝeußàšÛèwóÕ¯~öÕñaÓQÃ:z^+Ò^jô«^ü|W®à™_úÒˆ?ûdv «mOïe®ª½–Je¸ÇÓ²Ò×+—=ÞÜŒaɘ¤r I†Dœ.hüé×÷Bú­ÁÅÈxÑ¿&6¸¾6®·Ü²z2I¬ô,»®O¯Vžãx²ÉåQ–Îz½DØö|Ë­­A㔼¬Ik0$˜FÕLcÎu­ Ö…eó"Ã1^ VËþôÀŸþ£ðù¨lƯÜå6:»×Ô¨1JÆákùÇ7›ÂÃÏñÝ8Ã7úŒ¢áÔÑ6'—~V……¼CQz†]Ú²0i!¡*€;îðä>ÎÐ,•‡jU*Ó)×!^I 2íÒÔç®V½UõâJ¥.̲€Ç{Õðr°ÒVÊâ8j¨¡eeÛ#À $®þä²AzðZ8c•& qãwµZM ‡aþ!ÁYOMsp^¸’‚AG kk+Š7÷>¡ìiÃvhµZØÛÛz¢Ng9²®Žd°:Ž÷E˲g´6# Häh‘ê1î> ž'Q@ÌZËP‡±ˆIF°ì­ÅKðºøuá«·æÂé*â Öè¹Οês¼cN¾8útd¿à|¿÷« æïn×B|&c³Û£{]ò°Ç.ýI—èÄ•÷1κá%!Ó3òÔohm渆!i?ÁûT3’ l¿º P­ÎMÙ˜fþ):Ÿ®{ÝžnÁ4Nçùs¹Ÿ,`ÛöjzXÇQ‚uÝû!oO½>»$eḬ̀, ¥%_klYkNYá%iú“²k€iš¨EÖWZ»MzÎ\VZÿŸEl;]iŠ$£q…ô°Ä¬©“C¯¯i eSó°nll`kkk&7<-F.ùa½ð¿jupöÐ$iÈî†Öðîü›@¡{lœ¢^@Ï(ˆ  îýèÿü ž!N…ãŽÂ ‚áëACíàâ-ñ›­kÞ³E¯ˆyQ*‘ëÇ|eÚF>>G#þ˜Nb´ì%"Ó+1iÈ”¿t T5y-ëŒêŠCÇ„1P”þˆU¾õ[?0Ó{Ê +k¬F‰›øŒƒÖIÓEM;Ÿ™ŽãÀqœ¥—kÛö&Ò²ø32ƒÖ‘W«ž®M†É e½e®uçm»·d(k š–ØÅÞÒ’à1‡%C¯¹d ÎçóØßßOý3*ƒj·¶Z-´Ûí©=¸‘ëô•J½iEñ~Rư[V¯6»O’Âö‹EàŸývÏÈ£sǹû›MÀÃIŽû2ðÎÁø¹ÿ ”J°ª hV·³Ça*·C˜èO–Ô5~a…?ïî߉Êîß‚Ðõ=+p-ñ¥wJÝÏÉ«YÃj¨Ä%ø¥}’ô:znsÔæ-ßc)8”Ew’%mÜ— ¿…á'mW‰£ã’2ÏYê4LE‡¶ye ž§ŒÇ¡iÚÒ‡NŽEÒº%Eé œ$yFk¡ÀŠô,J¶çRÎfÆ“¤s»øèúôÖdÏ Jx7Œ%›dXôø=n2Ôy‡Ûϸ†”ÁdA(î™D#Úè=\ª˜F/2™¦‘@{¨ÁzxxØgäu:Bž–v»[»µÝnãÌ™38sæ î½÷^¨S˜Õ˜JÙòФº^Œ—=èÝ >ÒŠ÷¥¦Ò'è6‚I†|°¿aºsÃpÏ·Šâ…è’Ùèy(m ÷° ý6ˆ€ôŒýIò&e¹k°~ÂY€ã(Å\+`ØZ]ïj_ÿ"»=iN‚úìœÞ'ó”ïI¼LVëV˜_üVï…|ò¤§Üž<é­ M«äF¼òõôËòpöXLo¡)û1)çþÌõßç"½Ýi¾ȳJ *‰y冘§ŒÇQîÖ·žÕù'†¾ˆi‹–Õ‹IóEK’7™Õg”Q)Ûs‰–1Œx}fJƒ•Œwœ˜We¾^ãfÜV”ôm¡¿ÇôsbÑã·wÿöX“3’$ ×ë§(cæ÷ïÍ'Ú»PM>ƒžÒJ%^áŽ%¤'FÃf4Þ¸“FZŒüÐCÅ yZÚí6LÓLìçÏŸG.—ƒeYxôÑGS¯£DªKÇ.()dH Ü 8Ö ÇR NÔHÉïŽ>hÝg=“0XÓ´{^ßðTà%ßüÓ7@¼û¡Ã¼{>,„kŸÊè_Ã*(æGá%½Cã´…¾Ð\ëuÝv9ˆ/qC÷QŽ|0bí'"ªÝ¶zWÌa‚lò=QXÍ‹óЯ¿ÑóÄy2~tä¹íÒ¾x“^æÑYéHHp_ed°N€üº[ ¿á9c(S{}h܈*=³Ö!ãQ4Mƒã8}kŸ2})¦9úº6]÷"âpÏøl6{µ‡Ñ`É‚lÏÅ`Ë :Åuz4·» ¶ǺÎT8•ËãÍHŸD­6R_[„íž'&‘õ¡Q“››S,œKŠ$6ƒ ùSŒ£VQôÞQAâ¥`Sâ¢ÀFe!Y‚qpp»­ÝnãððgÏžà­ÝÞÞFc•ûC;%XŠûÂîüžò‰ Pz?`?z#ü­“&ÑG¨ãt'üSó1v?ÊÈûÞ¤ûÞ#†{!»õUq ÿV÷°öGú¯|?TöÐóÎ&ÍÄ•ã1{mTE϶ê»íR÷ØA/´982)ß]â\YŽaV®ž…ùÞ§Ò5 imj4„7vP.ômªkW£EÓBµGÇ%u›"”ï ðþŸfÊ?å8a›hÖ Ð"d<ˆmÛÐu=»Æ*àɲ¢¤WtmÛ“q YOZ³Já*€·õe ±Ì(‹–m`Në²kµþñ”¼1cxY£cEVy÷º9ïºÝg¦iéE—D}lÈí;Îä µ˜£F¾(´„Ôcð ùÙY‘'FÎ-3ʱªšÞÊ2©X*—¬}dF]O|ÄѨ4ZgÕgPC8šsÒÓ/Ä`ÝÞÞÆþþ>vwwû¶]»v €·v–ÈçóÇÑô°Z–§$DÆî3Úõô_ Õïz¨7ÐÉrwÖ@ o^3ôýdY=«…î:ÒÀLÉ 6:^{Ìw“áS¨Âa¹q’v÷úÜûHøF@øjäšB¸ÿ(ßïþ% 6£cѽ¿îuE1&2ÔFræá9²ùNc°š¦ék¾ô‡B"95£c¤øÚ»aÞòºôˆSÌ-«ÿ‹ê º®Ê÷u ]{×ÿ4-YI§²4LÑѤþ¼ë’“ è•ê›þ ƒh‰ç÷EÈx˲ (J6Ë8¦Ù“ýAJyS‹Å^½Ý8c"AðöÕ4Î<%-ÛÀœjKÒ` Í„‘µrÇé áñ÷°!Š4Ÿ™V?§±tlÅ×0&«¯‘ôŽ‹XÜ£,Ñ•åù{Y³ ãÀd3’$ÁfŒŽâ5©Bó,ÖÏýîÔŸC¨ ã¬Akô™tÿöÓ”øeB"Ž*Ÿ6E¢MIJM’–ÌÕaÔ)•ÎyòÉ'ñéO:vm-ŹÇ*7¶í=Åz=ÞõÑÍ€;RÖ\Ư©óhO@hfƒJÙtCrÌŸô䤯¿×*‹Óm˜è¥R'¢cqÐ U¼¾··Ù?4iòÌA¼!,0óm{ü-€ú}ïšGG½J§ò–&Õ½ïšöã@á¸÷xBèHµ>µÝnãêÕ«øâ¿8|ç)3®|ÀO<ÃÃÃØs¤øíŸ?€ðÌ/ÁúÑw…Ò‚ã:̓TS†P›& }á„O’ô2éÎÔê: Þþ+PþÆU¯ÿ5›¢„ä>šÓôZW5 “$ ˆ*XÓÌsœ( æR¸~ý:®_¿>½ À,Æð(™ÏˆìX@r˜×É“ÞFò?N-`Y\wé’½LB«ÕÂÕ«WqãÆ¹^wVãw±êÅK4«-¹DF KàøØÛ(mAP9 éÑ~Q(¤Ï÷BÆm©4AåòŒ é^qÆDÌ{βÒÛ´_ðqâúõë )9ñ›9j„¡ý$íË>8¹‡®£\îú´þê7Ænï‡ÑSPÆ=Ž“Ï®¼ûçsÌduîÒeIuüΜÁ:¨C º¹'Ÿ|ŸùÌgpåÊ•¾m½«ºî) IƆçm±OÙŸòŽÕ/ÿcØNW¡Ø=ò`V*@±ùö¯BêNjZ<Ñq¼xIr½RQW2,ÉC¬È«¢ß`¥vweX>ˆ3Å Ç%õc^xt2†ŒÖ“€óí6줢?ñR÷Üö_R·m±‰ªR|O×®][˜Á:®|žÂsåÊ”H5KiY(ýñ?Eã}™ºü<¸,"|­˜üJ…dÐ?ü­°ÿ PˆWÓ L:¿ø+”T˜¶˜¸Ÿ6aaöàšªQg³Çp:ø(Jxx™väf°”Ýçí·ÿ¯…ÕÆžÅ%ó¥l¢ŠqRÜ}³9×À«Â¢ ÖYŒßQ& ‘™èÂ22&S*µÁ¥‚à‰¼¦õ"oƒøâ_*²ìO¶QàY¨zÌXó–”•ž­m§³|ƒëmã<¬­œašâíÐüïO‡øåÇüØzïgQ4K‰c;½Ð!ÙˆÓõéE©—/ú¾Q”ôÞæ(~ â.Ó\×3Ås’H¸óÎ;§w¡˜Å%óÖèŒ}Ò,I–Cš3Ìöö6Þð†7à¥/}é\¯;‹ñ;ʸYSG‚2åF#´È¨KiEV*a¦B ²/CŠkwE ¦x nýœÞUc/«ˆ†Sò™aÊ{p)J0!9Þ4é¿üÿREÓ;):<ìîîâÎ;ï*S³`ã71‰‡uèq£¼äiéR±+÷ⓟðåYïü œÇÿb¬6‡ØÜ +>i"r"‹q•9âß5T¯@ºä±››žÞ˜v6‰úÓÉ“žÒhÛ}æ é^[[[(ø[ÿûôȆ¬'NœÀÙ³g‘ÏçýŸ­­­¾ÏègRNœ8 –Ðn·'급Vî SæÝ A7ä 4M@Ü [P6ÿ}x|EàǾ ¼íƒ€ªÂVT8ÏóîM–»vÚŸßÈ1ÓˆV¤Q#sP|8-sýBëg½„LA‚žÙ¤7Nÿ"ùë®SKDh¿#{¬átï/p¡Tм¸â ÝŒ1 ùª¼W*€,£lx_d0J&8™@cXð½.å}0tog;0©R­zcYùþ¯Aé»[º²¤(°¿ c÷¿¢øÄ;ßäézsõzoütRÖ Äf­@ÈË;Ñ÷Î4—‰gñi-Ø´;Ê,d<ˆã8Ùö®ÒLsô3ɬ9“ f-ÛÀøu)G"jiáy)ÃPT5<Ö‚÷Yt¼Œæœð«uwìÓÏcjÄÿ¤´‘ˆ Ž]‹!×MôÙ®ª€zªû£×‡v÷`RI¬s½%` b2NL2ñ(Br$‚ãô„0Í"izq&%- ôG"Ì‹ƒ£$Rܸ×Y¢™ƒÖýOüý‡`ÿ~$„;¦ïÒr¨‘¢›Mï\åro:%ûêU<þ ß0Òcj°ær9ìîî¦þ™”\.‡­­­P3Ó4QHáÕŒcàúÕaÞUB€—ô‡ï8€ð”÷‹ôí_ ¿h°û¯ÿ(•P.Î7oúk:­÷Ã3ÏÄ$»‰ÖGz¥âä›2îvsÙ”¡õ£†X âRZ»›ôbäkiüíî/]og4ÒB’û}Ý`½¶#ãÄ¢J¹Ë´åÛ{C}ÃTÕVÁñ,8^kOûIçî~ðä“þ‹• $JL'<õY(?ò"ÿ¶¢bóì7CûíW ñÁ›Q*yãE© ñŠF´FË·Frô–¦ 7@ƒïœQC‚)|ÙOZ0"ÑvO3$8øÜhõÀ„‘Ó3 ’)ïj_]&x¿Ùìß—B˜¥eÖ² Ì)Ü=Nk *Ì)4Ûhx¢o"ÙN½ßýÌÀ]KµO?'ƒ5ð¡™h·¬MÔõþH¸¸±TÞ'‡%û‹k„(ŸøÄЈãSíÅm˜µ»/ÖÅE^ÌCƉIBßEQD)I>Øjuø÷GrY`Û(^û_•ïÿ Ä›ÿl²×õ^’×`Ô%µC‡Ïl—˨~÷{!Ý™HP”¾c©ïiÂ¥•?¢É’qs[}çrþê¶Þ.?øõ^2Մ˦¼ùžŒC£‚$ãÝð‚̓·õzßRXÿ>"§’åäɤÛëÔ†×æ” ”R¾£çu•¤PBãqxZÚ[­.^¼è‡' š5‚…°µµ»>ŸÇ{Þó´Z-¿q±,+V¨)s'% „!ÎÖèC0ûX*—»¿üÁÐÿudfã…/~ñ €î lÂ7ˆ% p €`¢ßë) \î%̨ðB€»É£êux •ºžSUœ3è/1#`xéhFflô®G·$¨öw$I´¯ÃX¡»Öƒ€™Ø"gw°ÿض׎z}âJ(1ù:ß·µÞ@A²M¬$I½Êþó(Ç5ljoìl"¡2Áó$1¨©4M¹Æ‚}†Â …pž±˜ÉÄD‚ÃÀ(v½KhÉû¨DŸÇ´ôQJÒFн¸ÒŽLƒyÈx”‘C‚I»®Õ¦M³*õ:¯C]Q!ÛsÉ {¢7beÚwlzóÖÝ-ô.§2,qAƒ(•”˨85T«‚×m$)yP•e¯mÝÔh×í{Lä¶ífÔ´”åú[[p^'õÚò» B÷Yª*rÓº’@É„¢i·7 Wç»fu2Þ»ÿ†¾Ûvú±ÞqzÊA\dãÀ~¢EA€þ±Ó±éRHªÕˆM7Ëé9²Œ¡IŸºÌÏÒe}÷Aüž¯õO Nò<õ°„ÈÓÄïÝ Zþ•†TVÓ4qæÌ´Z-llløŸïîîâܹsØÚÚÂÆÆ}ôÑ4§KÅÆÆ¶¶¶&î(ÁNA³_'O†Ë—RTH¬ Œ‚ ãkHBQ„_ò~^õt8Ÿ‹ìðô§B °´ Ï“ @z`!¾öiÜ::+°-n®@@X¯ß@L@<‘p#cxiÄö#ð=¨q5‹Çõþ˜Öß§ã&ÄÈ™2(SßOÿxûx ™Ó’ïAI ‚"À£ªÑçIÕ5‚H§oFõÁãþAŽj†MšxдÞ$^Eñ¶iš÷bˆ:Íhb=Ž`míQ˜Vâ¾Y|ÏR[IIËÓ’ñ(I“±ÐzÒQµëa‹ƒ³Ë3+ͬd{‚µ_¿åOìbs³« }öÞÐKÙ¶½Ï—?H’ØlúŽ’±æiJ%ÀüƒgÂУ(X×aþÚgús¨* i‰Þ\Óʧí þ–å5°›˜t¼XŸ) ì?é"‰tlÛ›=•$ÿ}íˆÌâF×ôÚ‚SP< æ('@éõŸé…5›ÕoFÌJÆ Çqf·´#ªxBU&ȳÿàÓ}z’yó÷ÅzS޼¯±X÷Ba¾êí^)@ «W¤PèyÖ /Þ MÚ›HÊm¥2Ÿ¬¸ü5ĸe©R¬çÏŸ‡,Ëxä‘GB ¯óù¼_€øôéÓx衇fÿF„fãu½;öÜýŽŽ¼78©2¨$Ï#MJ3ÚM£ý2ú„£{h_8«ˆí®RÜ5´B_xTY–Ñ3* ćÙZÝãä@ò¡×û ?wÏ€¢œÓúë/œÏ"9QF÷0Ñúù8‡^ÜWíûq!˜ï~÷ ñÑ~Ýh É I…³77ÃKx¢^h2ø¢ï‹Ø÷‡$AÝü/áÏhÔK“»?%¤ ’ ‹‹º¤DPq]3úýëzºDJQ£>iù:ÕŒnKJ ; ×Â| [^dÂ¥LAõ—H¨¦aÉÓBl*É0Sd‚…ÏýO(oü¼µ'/üh(GM£?´Séšqì çOþå?×âí2]‡øÍ·ö—Ýg¡ëĦ²Yùû·Àþ¡·‡¬hºkOžìé¤OlJëUËùs¿  üwK*asÓû3M=îà{)häÒïôŽE@þ ­y7Œží½êÌ4mûú©ã`´¬‘$M¶ H¯zVhé­«ÏH$UL–¦ùç°Ç0.>Ñ~Y†ö®—„"Å‚Ä}÷F©K­û1½Á|±Árvqøå2»„²Ç?º‘ØÜŒ?&²½ï¿üË£W1j°¢Óéà¸ß<€‹/-н‚z‹òÞ0pÄé³üã²?ÒŒÒU.w–$¿„ž(âs"}EŠ)×ÑõŠÙÝ·ä3UŽŽˆÕ²€›nêÞf\àÀYá2`Ä h·ŒLè#§çÞ{ùu€µÑ[Û÷Ò‹ ÇÔ4àŽ;ÂL–Gé±£ïòPAò.ÑzÑyó›? Y^þ·Â '8QpT”BCâÜØÕª7È.(2Zß‹šY¯÷¯úÓ8¹‰#úÜ’²Í—ËžŒnn†¯Ì”N¬ü뮿õöØjö?û÷Ÿó¹ø›©V¡þËçCûƒïêíÉÏ@‘9–åÉ'9 BÏÀäÝRE`X¢ùxÝ>éë1Œø÷ å¢wï–ïÄk+ÊTç€3‹ã8³‹&°,Tžñ (¥v’]T*Þ»;ôÎDPš?ô®Ø\]ÁSêwýsh…®G¨P€ K¨½â_¡²Óó­ß2,Håþïº\ö^1Áq” ï`RLšœ&yY£“îqAäУ6å˜&yâ Š¢Ø­QîMÌD—œ©Õ€7¼ás•¡k«ÕB.—ëKiMaÀmV{žP‡åîl›Véϯ!š„È4»GQ”pr˜Nú;nT¥W¢g$ €øÜH_iÄdX·¼}å·t÷uékQ"BkV ò¨JðKÈ’ä Æ’Ô=Fî ‘@¥_d Ü“ð ô%PÒ´åÙd úp¯&=jÓì‡^$AcƒÊÔ’'-IG¤0Í`¢µhg¤¨£QgŽ–$k³¤CþêûýA,úìFÒ¹£…¨3 ­ô²òžQ¿sö¼¾‘4‡Õ]:.)½ZõÎ|TC†ÊÝS*ym¾ ’^qI©ýª’J¡·¬ÞúÒq”ÿ8Řf3;1×$X·™q ֘ĦþÒ +Ñe;ˆ1¿áéÿà]É 6‹Þ•º u q“HÕj/ÜR–!¾ç¡þÞÿÙ¿Ÿ¢ôM*Q„Ðæ&Pøá;¡üÄ×%F4”J½á…B|äŒ$õæXc—œ"&‚<–Õ+­Fç z´ÈH%nÜX¯(ÞyšÍžÁKºcȹ4S*• 677QU´m£ôêÿéGR`=™ïu„îd¦ý÷ÎùÆ\h9QÔD|d_­Ö3òœû߆ÒOç¼/¯þ-þÆyTz ðÁ†,SË ª¾Ñ½t³®HŒp¯ODå¬Tê-÷Ž7iÔ)hB…¾ŽF#üŠ3Mïšqý*XŸ¾ZíµÏ¶Ãý&Ž\î©Ñ¿[w?ü°ûš×¼fØn®ëºî©S§ÜË—/§ÚwÚ\¾|Ù½páBè³F£áþè¾½÷$ =O£áº²Üý£æºrÞûL’\÷ø8¼ïÑ‘ëV«Ýß_û#®ø¢¿ðþ]×¥}]W½Ë;Gð8QLnCµêºnÃuÝ’÷·ªºn½äº®êý^«¹n©8g©»÷ÜAšMo?QìµÕ»ÑîqÍÁm >—èã«V½öÄ!ËÞ1µZüöz½÷œ%©w/Ífò1ƒÚFÇW«‘ûŒik©äº?üÑ>yÉ:÷ßßg²/¬TÕuEÑ=þÈŸ¤ùt(Ê¢o$j5O¾ÉÒÑ‘w[¢èýŒ*w„(ö÷;×õd.:fÐuƒ×ŠŽ/µZïqW«Þ¶¸¶ Bÿg²Ü“ó8yÉ2qcxUUÝFp0ãøØH¡(ýƒ þq}Š™)Íf|DyÉÃúãññqüx>#‚”JÞ˜Ñlz¢Nc]ì€äº^_Hz™G!¥bQ”ÞX[¯'?Ö$޽㱊ã·$I®ªªîñˆLQÒ=ãfÓu~ïS¡Á¤Ñp]éë¯{')•¼ÎR¯‡öi6½ïS’Òw×Mßmêu¯Iú@´Û“N÷K'é<Ñí²Ü]Qì½êDqøëòøØ»OIê§gÂ8ã÷Pƒõ±ÇKeˆ^¾|Ù=uê”ûØcMvS¼ùZ­æ>÷¹_ôþ¨×=aM$u¿tÕuËuKÛê®g˜ÒFYö…÷èÎðùûñ]uÝê[¾ìèÖ=ÿÑ‘ëŠÏöÎC/¦££î9ë®ë ΨòLŠ{Ÿ@J½ó“BLJ1Cêñq¿P×ëÞ½&½·H÷Ô™k5¯­£ ÃP”øÎw|Ü{v¢¸|ÊŽëÆ¿ÀÄàlCw&Dýößs›¼îºnï{×[e‚v ÉGPvT5¾Ÿ‡å>Iñ¨ÕRÍ‘ùçLC³ÙÛ7N·]uƒU–å‘•XŽ{Ê ½i–m4Õ„eâø8<ÆøR HÕV[¶1|Xl4®:ÆË0ª¤›åèht«‹™)«6~5!Ólz“³QõtÐ IC¸ªºîÑ7ßëÿâÅŽ”èuK¥ÁiÇÇ鯹Z­Û†„sŽ È15)qcÙãvù££Ñ'£Œ3~ ÎçóÈçóØÛÛC§Ó‰Ý§Óé`oo[[[Èçó£»ygÄûoOáû¾¯Ûær9“{ Ÿê}fþn/qœöËðBq%Tµ»näéáóÉ÷.múûc¢Ê*ðÊÏ¡µ <(ìôÂ8ýPC~øq\wÊð×çš—á¯Ï¥0_jc©vçwKy†Î1,ÓEF zäTj‘!ÁR6qa‚ÐË IÖ·ÔˆÑòÕ*¬ç¼â·xáú²<¿¬pËÉý^«yaZÁìvqQh´VBd’"DK¥ää´FF×I»”‡’r†‘¤ù¥¬Ÿ7¶mOoÝ}á”y†~æôð¨Ǫ\–ô‡%¨¡q‰¢BW9œ}ã”´¡ZÌ´jƒ"×ýwjÚJI"fF†1VB1ªTÕa(™öWü&©@µ ˆœ{ïë••`Ô…!]‰¼`ÉÕ¤kÅ3nªËê­™Ž»&ÙãvyQœ^y¾QHU‡õܹsØÙÙÁ™3g°½½2J¯\¹‚ƒƒ¿,ñä“¿R)à®øBÒ ”Jž2©}  ©Þã ¢ê_øÑŸözQW+Ô~þcä„:`Qý¡:P‹" ýY~Eôê¥~Pþº_°+7ò?ôboD*FbœÁ¬Å7ÔjžÒ=h9×<…Z{kl“®I åWe šišaå½+ãv¥÷ÝѽrBÓáHR/%0ŠC'ϹC F}aÛ·¬8c•¦Š®ë(Å r¡àÝø‚~<™n2ŒŒŒq&‘ºU62×Ÿãæƒ»IÎP†~ÀëSô~Ö/ØÝ½o~ó•EßúÔ0 G#Φßg”œ¥ÙìþQ¬°ÊdÓ4QãÅi@óÍÿ%ñ3€ÞS*k à\z/ ¿½ùGî†„á «FudmœM ½#¢ëe—Tk>ŸÇ¥K—pñâEìííõmßÞÞÆÙ³gû3-Çq¼hÊ4€ðáÏ”w¢H"¼ú¬¿ôS}Ç)ß šwÊ ?Ôþ} PpJ†„ꥊ€ð­ñUkð-Þ P´ÄŬ!j–’ÐÂô$&-ZœE^úÒoòÄÛ6üúsÑ2,«4`Íšyõ¡i\g3œ‹Ä4M4¢iD)}â ;6%CÕuÏ c(áJšW Uƒ¢£Ø#Ì»NÛOdk—,÷¤‘wš$ÚÜìEÊPrE +†Ü}÷ÃOº$ ô>QjÙ˜d0æû¾õû>˜ÈJ’çì%Ÿø}ï-«ÆÍ¬”xÔ?#î½Þ+Uó[öo7 nýÄ£IBíƒ_rÙSWÅ1 V±ë§2X/ ð¹sç°»»‹V«åžÏçCÙ‚³Ä‡>ôï½_F&DÀÍ‘)Ûe ¶á…ñ_Ô”¹7ˆ«ðÂw%ô¦PŠù\€W_ÕDÈ#d‘•¬ë¨ÀßtÓw£PŽ~è1]ƒ5kß ÃLŠ®ë$)Q@éÅS‡•Œ…îV«ž37îr”ÑœJ R‚%\Gé¯IYH§ UŠÎ èz|ùÙAFú0/kÔ+MKZŠÅ^)2Vibðþå+Ç•q°š¦Ùo°ÒL ÌÖ´¾/Å>r!}ìÀ£ Š( ðjËÉ¿¸è[bÃ0 ŒaMö²ù{žUA’ þÊizû ]T³ü¤6X‰ lmm-ºÝC±,àŽ;þÀ㹘"edxëLxÆ*½[Ìç’»ç3hxBNø¬ Ϙe˜þâ/¾Á[ûõ’Ÿ‚ªfeý wfõ1 £¿ B¹<³ZÀŽÓ3Bƒ…]F›Bë¬hü ÈÀuœæ]+ïøYyÈøŒÎó–Jž!m7ÙSq ò²&-Ï$Ï.‹.)¡ù‰Uó¢8Ž˲Âá’TšIQNÈ4?~ Â3æ “=,ËË`B©¢pÙz04éÒ²ò+¿ò¿ðµ_û…á;ð Ñ8¢Æeœ^]r— Åç]µ¿Jð#­Ø š™–eáå/.ªÕ^bö°2«Õ–¢Yß’2lLB!¾kµÚ3œˆ ‡qX¾a„“xŒRÞ˜jwKRòqår¯h{ÁA§—HŒB–‰“'Ãõ'ƒ4‰¤( A†nܤ›ªzí£ðìU!6¸Rñ4óU^”ά ±C°¬^S†VØ`ýä'oC>ß¾£‰øÅ¡BÂ瀄‚ϱ‰“/t¸’°mâ efíqo{Ûó¡(žÂ˜¦X3Ã,š¦…gçmÛ³üf8­Þh$Ÿ>ÚÇâBu“ *AwIÆ#eÀŒ»†¢Ä·2ÄRôh’ä)‚ѤOÁcd¹—*hRhnUÕ‘”¹š ð´PfKš«XLÓ Ë7Í6to²\öî9:Qpòä¢[Î0Ãf¬R4Kä r R§³6¬°ÁúWøÎï¼eøŽ4mÄ|Å–»Ÿ H ½r4â£s¤î1ì)efÄ ”é ³Ì˜¦Î\.{?a(0•Â"hí&0øÔ‚Ð+Û,Ë=÷æf¿‘u SI±Þ½zÞݨÁ)IÃísÊrMÉŠ‚ç-{^aJüW‰DQé…àßšæ>W”þç´dÁë•Ëã…öªj¯Ú*@áÀ¡è@jOMó¾KQôä‚äuC£™ÕÄ4Ͱ|pO®+o¼ÜüÖ¯¢ò*TÍM”ÞöüE7ŸÉ#¯a]lxæ3¿„oxá ½?éMo£—)²K‰•¢/Fa£Tìî[Â`Oèñ¢Ÿ ³Jضg>óQø›ÿ_ø8 Ë0MOáå(2fUˆÍ,I!@uteÙóT‘!–¦¦¡ëÞ»&nMUµÚ«™«ª=ã–Bz ²ÃƒùuªÕžQKFu´O“A}µÑ£"OhµÚ«Ó|d”@JÓz÷÷˜É³GÛÁk5t®4XÖxÇEïoQY’gAl2šî—Jß}³é=÷R)l>õ‡}u©f2ëam·ÛPU­V Ë2´hnÿ$øîŸîû%âJÖ0Ì™H¾Ø7^ù-w-ú6&‘Idܶmœ}ö³ïøŽØ‰GÇñ’wpfQL"ß–eág®^EùÖ_¾ôL-ún&Ì$òM‚  ò†«0ÿìÑøè³x™3™õ°ž?¹\–eáÑGE«ÕÂÞÞ^ºƒ ¸åu@ÀIxá¿•ÀÃ,˜‰ä€õüïãÁŸÉ4“ȸišxÃ_þeÈ»ê8žGÕ¶=¶Vã|Ìâ˜D¾¿íúu¼çóÿì[òÆÎd’IäûýÿößâO<òíÿNóÍÞÌú 31™4XÛí6qöìYÀÆÆ¶··ÑV4Žá…ö6Á+QCÕ 3Ì,˜X¾á)íü`²Ê¤2~Ï·}¾éË_öã|uÝËM°‘Ê,žIåû®¿øvè(ù%—&KL*ß?ø¶·áß|ãï?øƒ¨]{++ÌTȤÁzíÚ5@>Ÿ÷?ËçócÅÑð Xž»DÊÎÎÎ΢›0UGò"®*ÓïU![EyXµ>;.“Êø]þ0þ´X¦'OzY€ëu/x™ ÖU“‡Uì³ã0©|›ßüc¨ýÚ­K%ËQVQV­¿ŽË¤òmÛ€ðõÏ_úèU“‡eï³™\Ã:¨St:lllô}~åÊüÆoü~û·wß}÷¢oa*\½zu¥:Ìõë×Ñétü5‹âsŸû>÷¹ÏáÖ[oÅîîîܯ?Ž|ÀýÑá{¿÷{qÇwà…/|áÜÛ=m²"Ó$+}öêÕ«xâ‰'výIÇðç<ç ¸|ù 8yòÝxÍkþ7ßü$~þçv;c“y˜Yé³?þ8®_¿Ž½èEK3†GÇïw¼xÇ;æÞô©‘Y˜&Yé¯4~¿ï}ïÃk_ûÚ¹_Z:xåDdE¦EVú,é࣎ߙ4X;Nâ¶7nÄv–ûî»ÛÛÛÈår‹nþÔhµZ¡®e§ÓéàÆ™øŽ¨-‹ºvIò ¿ò+¿Âòq²ÔgùRšÞþ2oXØ}LJ–äad©Ï.ÛÎãwöÉR]d[X÷È’öØcSkó"Iä{ÛgÁ _Æûa&cŒ/£<ðÎë6~kS ¿³O£É,Á«@§ÓÁÞÞvwwaY}ôQÿ3âüùóÈårþöV«åo´-ÍöY°··‡v»G}–e!—ËáâÅ‹©Û”Å{bÆcRùžÆöY0HÆ—ñ~˜ñ&ãË(<†3ÀzŽßÃÚ”ÅûaƇÇï帧‘X´Å¼ª\¾|Ù=uêTè³ .¸÷ß¿ëºÞLÆ©S§B³#ï|ç;Ý׿þõ· ;vV\¿~½ïš×®]s/\¸ªMY¼'f|&‘ïilŸƒd|ŒA2¾ŒòÀc8C¬Ûø=¬MY¼f2xüÎþ=ÊÓm0¯*[[[°,+ôÙµk×pÛm·ù¿@>Ÿ÷·çóy´ÛíÛ†;+(S\>ŸG«ÕB§ÓA>ŸÇîînª6eñž˜ñ™D¾§±} ’ñÃÃÃ¥»f2ÉøªÉ÷4ÚÌ2¾<¬Ûø=¬MY¼f2xüÎþ= ¬s`ggdžK—.À@!8::JÜÖétKõ²¦Í7úî寨ßß*ÔiÚ¼ˆ{b¦Ã¨òUy$ãËx?ÌôˆÊ¸iš‰ûfUx gâX‡ñ{˜|gQçb¦ßÙ¼§Qá5¬sà¾ûîÃÙ³g=ôO’øÂ¾¸íÆ%¡ž6ÁÙGy<ò¶··±³³3ô~Ò´y÷ÄL‡Qå;«ò0HÆ—ñ~˜é•ñe”Ù8ÖaüvOYÔ¹˜éÁãw6ïiTØ`[[[ØÞÞÆ<à/ºÝãöO"—Ë <6—ËÍäNŸ> ~øà N‡‡‡CÛ4év&»Œ*ßY•‡A2~ÓM7-Ýý0Ó#*ã«&ß<†¯/ë0~“ï,ê\Ìôàñ;›÷4*l°Îˆ½½=惠õ!pâÄ áЛv»\.7pÛ°cgÅ p€‰Û¼ˆ{bÆgùžÆöY0HÆïºë®¥»f2ÉøªÉ7áëźßÃä;‹÷ÃLßÙ¿§QaƒuFœ>}‡‡‡¾LÓô¿ü\.‡­­-„¶ …Û†;+òù|_ í½½=ffÒ6/➘ñ™D¾§±} ’ñW¿úÕKw?Ìd ’ñU“oÃ׋u¿‡Éw ¿³O£r“ëºî¢±ªœ?ØÚÚµk×B ¤/&}gg¹\Î_Ô¼¿¿Û†;+èš4K5ÊýLc;“-&‘ïilŸƒd|ŒA2¾ŒòÀc8C¬Ûø=¬MY¼f2xüÎþ=¬3&˜2=nD§Óñg€¢ÛmK³}LÚ¦,Þ3>“È÷4¶Ï‚YöI–ïåcŒ/£<ðÎë6~ÛžÅûa&ƒÇïìßSZØ`e†a†a†a2 ¯ae†a†a†a2 ¬ Ã0 Ã0 Ã0L&aƒ•a†a†a†É$l°2 Ã0 Ã0 Ã0™„ V†a†a†a&“°ÁÊ0 Ã0 Ã0 Ãd6X†a†a†a˜LÂ+Ã0 Ã0 Ã0 “IØ`e†a†a†a2 ¬ Ã0 Ã0 Ã0L&aƒ•a†a†a†É$l°2 Ã0 Ã0 Ã0™„ V†a†a†a&“°ÁÊ0 Ã0 Ã0 Ãd6X†a†a†a˜LÂ+Ã0 Ã0 Ã0 “IØ`efa˜¦ ÇqÝ †™;Ó”}Çq`šæ¢o‰a†af¬ Ã,ŒB¡Ë²Ý †™;Ó”}˲P(}KÌ£ë:lÛ^t3f.°¼Ï6X†a†a˜±1 ƒxfm`yŸ?O[tÖÛ¶¡ëzßç¥R ¢(èÍ䈢Y–aš&J¥/¬ŒBÁE$Iþ9*• TU…®ëp’$AQÿ|‚ @UÕ±÷g˜a¤‘oÐ4 ŽãÄÊØ´dœå›™'óýjµ MÓpÓM7…Žsš¦õÃ0ã2HžMÓ„mÛ0  ËrH>%Iò?c„Y&•wI’|¹¥R ‚ `¹ö°.Çq`Y–ÿcš¦¯Àž`kšÀ›Ñ)‹~'Ñ4 ÅbÑ?Ïææf¨ƒÑvÇqà8ŠÅb( MÓ4T*•±÷g˜a “o(—ËþßI2IçšDÆY¾™y2Ù/—Ë0 ŸùÌgB×- ¾"Ä0Ó < Ê'y¢X'a–…IäýŸøNž<éO6†Z²Ár=&.“Ž]I’\UU]×uÝ££#€{ttäï#Š¢+˲¿­ÙlúÛjµš+‚ÿ7·V«ùK’ä–J%ÿoUU]Y–ÇÞŸaF!*ß®ëÉ\ðïZ­æËØ´eœå›Y³’}:¾Ñh¸üëåša¦Mœ<˲ì6 ÿï¨|Óg¬“0ËÆ¨òNãqðxÒÛi_–ëÑak†(—ËEÕj€7+#Ër(|LQ^¨˜(Š~vÈàßÁDÁcAðC’u†IKT¾ Y–ý߃ò7 gùfÁ¬d?x<ÐKäDï †™Iò%*Ÿë$Ìò1ª¼“Ì–Ëe˜¦ AÐh4B²Ìr=:¼†5#T*ضF£á6¨ämÛþ:¥ q/†Y4qò= –qf˜§ìÓZÁr¹Œ£££Eß:³‚Œ#Ï ³¬Œ#ï¢(¢ÑhøËøÇA©TB­V[ôí,5l°f]סë:Fh–E„D£U’$Ö† Ùw^·Äd‰$ùË8³ìÌ[ökµÇa~†™ãÊ3Ã,#ãÊ;%NªÕj¨Õj~Ù1I’ü„©ÌèpHð‚±, årõz½OQÅ_ì x %Ýe9ô7Ð[ôÍ0Ya|ƒeœYf%û‚ øÙ*¹ì3-ÒÈó ¨0†Y&&‘÷ gð<®<Á39l°.Êø[(pÓM7ù?•J¢(¢V«¡P( P(`ssÓ #¥¤R©`ssÓÏ Y¯×}K ã3H¾‡Á2Î,3‹”}EQ ( Oî0Sc˜< ‚€J¥[ „a–IäJØœô!üÖoý^ñŠW,èQNŸU+ßñÅ/~_üâ3ñ}ñ‹_ÄW¿úUüìÏþìTÏ;+ù€ù‘Á7|Ã7,úÑM,ÉôÈRŸµ, /^œúyy OO–äad©Ï~ñ‹_Äm·Ý†ÿñŸÚ9yüNO–daZd©¿Z–åŽÓ„ÇïôdI¦A–úì8ã÷Ü Ö|>ýý}llløŸ]»v €×1è÷`L}>Ÿ÷C’øë¿þk<ç9ÏÁéÓ§ç}K3ãòåË+u?W¯^ÅSO=•‰{ºzõ*þäOþdêç•|À72ñì¦E–äaZd©Ï^¾|y&çå1<=Y’‡i¥>{õêÕTãæ(ðøž,É´ÈR½|ù2n»í¶©Ÿ—ÇïôdI¦A–úì8ã÷Ü Ö lmmù·Ûmìíía{{¹\‡‡‡‰Çv:P' rë­·â¥/}ièÜËÎüÀ¬Ôýœ8qwß}wfî©ÓéLýœ³’oxö³Ÿ™g7 ²&Ó K}ööÛoŸÉyy OO–äad­ÏN{ çñ;=Y“…i¥þzûí·”§qáñ;=Y’‡iµ>;êø½°:¬N{{{¸÷Þ{±µµ…sçÎ ½7n$nûÔ§>…|àØÙÙYÔ-MíííE7aªär¹Lt”ƒƒ\¸pÁ/1 ¦-ßðøãcgg‹ypS&+ò0M²ÒgwvvpõêÕ™^ƒÇðádE¦EVúìÞÞ.\¸€O~ò“39?ßÃÉŠ,L“¬ôW¿)éÑ,àñ{8Y‘‡i‘•>K:ø¨ã÷²Ÿ?¸téR_èAƒbù_ö²—áž{„ah&ñÊ•+39ÿ,äî¼óNìïï/æ¡1KÅþþþLÙE²»»‹Ó§OÏd çñ›Y44~’·Iàñ›Y$ãêà ñ°ªªêÇÑG;lj' ÛÜn·¹³4°|3«Ë8³ª°l3«Ë8³ŒÌÝÃjš&Úí6dYî‹•ßÚÚò]ÖÁŒd¦i¢P(,úY1ÌPX¾™U‡eœYUX¶™U‡eœYVæn°RL~\¸­)ÜÝÝÅÎÎŽŸ~{cc÷Ýwß‚à ‡å›YuXÆ™U…e›YuXÆ™eeîëîîîÐ÷|>÷¼ç=~ÇÊÂ"a†IË7³ê°Œ3« Ë6³ê°Œ3ËÊB’.¥!šz›aV –ofÕagV–mfÕag²ÆÂÊÚ0 Ã0 Ã0 Ã0Ì Ø`e†a†a†a2 ¬ Ã0 Ã0 Ã0L&aƒ•a†a†a†É$l°2 Ã0 Ã0 Ã0™„ V†a†a†a&“°ÁÊ0 Ã0 Ã0 Ãd6X†a†a†a˜LÂ+Ã0 Ã0 Ã0 “IØ`e†a†a†a2 ¬Dz¬E7a†a†af!°Áša,ËB¡PXt3†a†a†aÂÓÆ9hoo‡‡‡hµZ8{ö,r¹Úí6vww}?+…ap¶mCÅE7‡a†a†af®Œl°îííáààÛÛÛèt:€ ìíí¡ÕjaÑ÷´2†UUaYV¦ V˲P©T $I‚$Iþ6Û¶ašfèlÛÆÑÑÑ\Úæ8t]‡¢(þõÇÁ¹sçð‚¼€'Y˜•åóŸÿü¢›À0 Ã0 31#…·Ûm\¼xÕj»»»8qâ@–eìïïû^Wfr,Ëò¿qÖ±–Ë剮ï8*• …Nž<‰“'O¢P( X,†Úã8Êå2TU…ªªÓ4aš&4MƒmÛPUGGGh4h4Eq.ks ÃÀææ&ÇA¡P@¹\†a( ¸ûî»ñßù3o³ض Û¶CŸiš†;î¸Ãï•J%kÎMÓD¡PÀc=¶è¦0 Ã0 ÃLÌHÖk×®¶¶¶ú¶åóyäóyßëÊLy%I‚®ë#kš&*• ªÕêX×·, Žã V«…¼»¦i¢X,BUU”J%T*Ȳ Y– ä]MB’$8Ž3V› ÀeY‰^Z2–MÓ„ ¾\­V¡ë: Ã@½^Çç?ÿy\¹re¢ïˆÉ.Žã@Ó4H’Y–!BìvÛ¶}Y¤ "EQBû QQ!I À,Ë8::‚ °, –eùç¬V«~Ÿ§Ýº®C’$ÔëõPÛMÓ íK².Š"LÓ„$Iªªâàà`Ñ_Ã0 Ã0ÌÄŒd°nll:Žÿ;ÑétØ»:ELÓD­V€>ÏÎ04MC£Ñ@±X„išg]סiZŸñgÛ6Aè E–eÍf…B!dÔŽJZƒÕq†2>J¥ÊårßÚ^MÓ`YdYF½^ïk{©TB©TÀá’«DÜo Q'#ðd—"LÓD©Tò'…Ï#O=‚ @?B€dœ&MjµZhr†ŒÝR©˲P,ûúÔææ¦6¼.aš&Êå2EÁÑÑ‘!P¯×ýûˆß²,'ö?6X™UæÝï~7n¹å–E7ƒaf;&ÌH+yQwvvpîÜ9ÿóv» . —ËÅz_™Ñ ï !ŠbêÄKº®C–eˆ¢ˆZ­†b±ˆf³Ùça"Åœö¥d¶íDo)y.u]÷ ÀQ ëE=Yä"Ú,I’ï)%$IòŽà=E=ÂÌêS(P*•ütZ74ƒÞHI’Ðl6ûΣ(JH&㈮ÑNÚG–åPÿ ©ªª~”BÔ 5 ÕjÕoC©T‚$I(‹e¹¯0Ì<±,+vsžÐ{Â4MÜyçøöoÿöE?fÉ ˆ”yÉq¥RA©TJ¼ébFÃ×yt]Ç>ðE?*f±m›››~tج¡eƒÕjuâ>7rÒ¥ýý}T*œ9spxxˆ‹/"ŸÏûž f2¢^Ñ8ã, ò®Òq¶õÂèºî{‰*•J¬Çs0SØá8„¼µªª¦ +–e†a„>ãlÊËG4¤|T(™MòH’MÓúdS„Té´PUÕ7¤Iɦ‰£R©Û¶aF¨=Á¨ B’¤¹%(c˜$(j€ÆnI’úŠ> °t ·ö›²ÝÓ¸Oç‘eÙ6 ÈÚ—¢e臖t(Š‚F£O~ò“¼¬ƒ€¾±4n;-'’eŽãø¿ÇéF´¬cRHf-Ëòõ²(d@ 4 ض MÓðú׿~Ñ•Y1ÇñÇqÃ0Fv8iš†R©4’¡KùtÊårbHËÈëÆÆö÷÷ÑjµBY‚óùüÄ“ñ8˲Bƒ¨,Ë¡µkI¡T"HqŽâ8ŽoRèdÐh°,klƒ4 Qƒ•BÓ«ôL‚‰¥†…>3ÙÃ4M†á+®ãžƒ2@—ËeÔjµ¾þ³DQô•lÛ¶¡(Jh§I(R²x²…É*d¬ÖëõPø|¡P@­Vƒ,˨T*þ¤*M>ðÇtAbû8´äƒ<_t ÁårÙ_Ž2¯“hb:É %%üøø86’LÓ4‚=ª_‹Å¾H1ÚRhG³Ùô>ÆÝ-;±, ›››€z½Žw¼ã‹}ðÌB¡±Eq¬ˆÆ ´äH–eßøL Õ”&¾BNÌz½Žr¹ì;ÇAµZÅ3ŸùÌÑ*u¸#pùòe÷Ô©Sîõë×G9lè9§už .L­]‹ Ùlº¢(ºÇÇÇ¡Ï]Y–ûö¯Õj®(Š®(Š®,Ë®(Šn£ÑèÛOžÏAðo4®ªª¡í’$Íô^£÷£ªª[¯×G>ÇÑÑ‘|­VK}ì¼äeZòíº®{ÿý÷ϼ½óDÅD™WUÕUUÕ•eÙÿ‘$)VNƒ2 BlXGGG®(Š®$I}÷G÷OT«U·Z­Nõúó’ÃWêŸÍf3v›$I®$In©TŠ•ñY2yáñ{±Ôj5_ÆâdöÐ7î×ëuW’¤ï£ƒç*•JõŸZ­æÊ²ãñ{}9>>vEQtëõºÛh4ÜF£á–J%WÅTznT憫(Š[*•üÏ’äqP{ŽŽŽÜz½î·­V«¹Š¢„ô4EQÜjµê÷?ºõ zo¼ùÍoY^F^ú±±Ó4±½½=‘¥xk_wvvúJAìííáâÅ‹¡Ï¶¶¶V®Æ+…¥Ðï•J¥/+(?ù A3Þi×µÅmÎ4FÏOí™õ½GÿuV3*mšæÄáÓfÝå{•JÅT%žB^ÉR©ä‡ù’lP™¢ Ì’|W«ÕDOÎ"EÑ¿Ç8Ù¦0Hú– ³‚e|18Žã'äJ•2êùi­hÒ5(·À |Ë Ëö|¡ðYò´S.’±Aù8(7@\”Ø ÷A0¦T*ùKªHö£ç+—Ë~Ž‚¸¥Vä£céxòŽiš60ÔxÞQ6,ãÙ¤\.ûI! Y–aÛ¶_µ )ŠŒ’7R®Ò‰(a)Õ»Ò´‡"`DQD¥RñórDóß'–t2À³3ªÕ* …ªÕ*^ùÊW޼¤cä,Á»»»ØÛÛC»ÝŽÝ'{·Ýn£ÕjõuâÚµkØÞÞ ѬÄË À’$ùŠ÷ å#X5ž5 ­¢ýiÍDðÜQrÞç8J…JÃϲË÷`(˜•J%‹Eà$¥!Nƒ/ý¸«¬}ƒ”šp¡1`™”~–ñÅB™¬IÁÃq8Ž3t,7MÓ_ŠôÖ—ÒZÑa¹ –InÓÀ²=?hb„Æòjµê'È£äŽ$cqù8hÒ¿Z­öÕž'Cv¤D;Žã/©¢±9øSâúìäÉ“!½Š*(Š2©ª*Nž< UUý>Eãÿ¼aÏ´ä/XÆ2NvEQD½^G±XŒÍÕA碲“ƒPehXp0¯@ðZ4Y‡(ЉýN–eðòÊÈkXÏŸ?‰‚žÆ`=<<¸&óÆØÚÚZÙŒÃä! f-’¦øñQ9Qû Ò¨œa‹´³ ®.æ¨'ÍrÒŒgVXwùNB×uèºîºô}“¬ÑŒztvR©ä{YIQYVEñgì—Még_´î»Ñh`ss3±P™¯A‘'”ß ê‰g<^X¶gOÔPzNãÞç”#8QÌaŒe›Ê‘û¬óýŽã¼`Å娯ޯàÔ`ñFiòrqÕÈÄô®–LÖ —•HŸÛærØt™sIÎîHÀÅ}·¹]wYz`Î%Û"M2à½KºÀyaƒ5tq³—uä¼tåÅ-;—G;¶CV÷ÒSõ«RU©$•T¥Òó9§ÇUR½éù=õ{~Ï[µêju#F´ƒ­Ø…k¨àX””$:.]3yug ËxòSHŽ¢––– ÖQŠXú…W*H’äÛú/i¾aœ/íïïcccÃö lllÄÞ¤ž<¸Ýnw*ÇO R°£NP©wä8m9ü&õÞm¤üé§=aÏ?Éj>埤É`BVåÛêÖ#—ŒPZ-£\.mc0/üfá^¼,’ŒÏÓ4íüqbímïÀ«V«íæšÍfêBèç–í`¨ÏôÍ7ߌµµ5¬­­¡R©ØQ1+++¨V«®ü¶¨P.(…ÿŠ‹1¢WtÔ(1?O•èµ zßìììØÑQîÅÛŽO )N,ãÓƒÚù3òø{=åÞz4aÇŸg¨~HZ<ª^Fö°R2öêê*Ö××X}á´Ûmœ?~¢ êt:X__Ç}÷ÝgÇÌçóylmm…zú⿈}èCh·Û©N ·…Ç$¹B´âHèºî«œEf¡Di`M¢´)x”A¿¿¿÷¿ÿý¸þúë§~^Æ•oxì±Ç°±±EQb)z6 ¨i´_11j;ufüÎô‰{hcc>úh"÷”už4É'Î¥R kkk®qC¡õ4éð+ C“œyC[[[xøá‡qóÍ7Ïô¼‹¦¿G¼ÿ”ª!†56 WË–IæL­Žqòî7ÇokÐÂÿ°ðMI’\ž` »ôBú»Ýnϼe$ëïéB…¹âð`z£ FK“Ó‘"ÖÈs;mh>²þ¥¤ðññqïôéÓ¾e©åÍññqäãÑw†qõêÕÞéÓ§CËoÏKIíaåЧ…X:ݯd{½^·[†”J¥Àòq±··gŸOü÷8PøQ˜UK„¸ä»×›Ï¶Š¢ŒÔnhG~£0 yYDžårÙÕ’@DlíÔëYú[lvpp0ÐFLQ”Ô´—iË ëoÊårO’$—ŒQ«‹0]ÿÔSOŦ뎎Ž®Alÿç×ÊoT¨ÝßÎÎN¬-Çè˜GGG¾í Ößó‡ßÜ™ÆKµZí mµ4 ‡‡‡½R©dÿÿ¤séY2޼Œ||| À?!~yy…BÁþ̸´Z­Ðƒk×®ÈF•² µ¤WeLÓœº‡U|“†ÅÌ“— ëòMPøbÍ®³Î<ÉoEƧ µÐXYY±=SAaZÖE.Ó4Ú!N9E¶Ì[EXtÙVU¦iâð𪪢R©`mmÍö…ézò.Æ,Ë888pÉ9µ:‹«¦yX㮑Q*• ëzjÃ]ÆÇ…*·¯­­ÙF†aàèè²,Ûy«qÉ“7×:­2cå°v»]ßmA­nF!—ËÙáÅÄîî. …ÂÌC#â&Ia"ed0SëºÎY\xž4ñÓ «ò½¶¶†¥¥%{R¼²²‚R©”Ú\fzdUÆgå*Š‚½½=†Ž#ʃ&ÃÖ/¤‹Bòiœf1gz,²l뺎F£a§cØ}´‡¥|L¿¹BŠcžE÷÷¼ á´‹,ããÒl6íÞ¨Ôv¦V«Ù]=(Gúèè(öÎb¿|Yb¤ÖååeäóyÔj5œ?ù|€óþÀØŸ™„B¡€õõuœ;wËË˶Ç6¨pDÚ ƒÐOy'YÕTì÷ÔÞïßÓ¼ñ¹,ŠnÞå|†]×qxxhç*Õëõ…ùM7Yñ¨„éûq 6£äùQR¹\üŽ˜#žõIÍ4Y$Ù&ÈkÙh4 Ó´éxY–¡ªjl ¥Åbq*†8KKãÂÑ"Êø$†aWn¬ßvooÏî'?í…Z)•Js×Ï}TF.ºDÕÏž=ëÚžÏçGN´^^^öõæmnnbuuÕ(óTN{mm ¥RÉ·x̸—â‚’ªÃöRalRè\QûFÍY”oUUí~u$Kªª¢\.C’$Ôëõ¹îÊŒFe|†-÷Ã0MÓÕ†ƒÐuªªÚ¡‡ãLrF™ gQ×NƒE—mê/˲= Oûd¸X,ºÚÓLJµZªÁšôó\tƒZ­f·E"h¼Ìo«¤,3²ÁZ(pùòe´Z-\¹rÀtz4åóyÛƒ;/†a÷Uô3Xu]O¬UÐ ëûE^ØY)QàΰHÌ£|ŽqÚh4ìIzÔtÌb1¯2> Ôx=ŠÁº²²À #“ªª–ËeŸŸ#².Ûd¬Îƒ‘*¢(J¬ãhZ‹;”wžf².ãqašf¢‘ÅbªªÎ}_ú(Œ•ÃÚétËå°¹¹‰ÍÍM{Û¢#6àõóT&Yp‰rXÃŒCI’|{úM›¬²y¥R©¸V_©ßm½^G³Ù„aö*ñ¢ä 3 AooE?¨%Íáá!ŠÅ"–––°´´d÷×N[h%“]†Õ¨˜Wc•˜‡bb”̤ï1 ÃN×öÙYC9¬l°ú°¿¿³gÏbkkËÞvñâEœ={6ó…MÓÄ©S§” ÖR©4 ØI'Ø‹E˜¦–L}Áféa­Õj™dó…+Þ©ªjGT«U4 ÛãÊ0‹†¦ivîh˜ÁJ}÷ısppÀ†*3sTUÅÊÊ VVV\‹ê”£º²²2ׯ*ÃL ¤EÅ¥¥%¬­­Á4M¨ª:ðù4ŒY–í÷Q–É`ív»ØÚÚÂúúº+_u{{›››¸páB¦=­ÍfŠ¢ R© x*iuC’$_ƒ5 Â$¶4ðƒ„~VÞ2:{çÒ‡ªªvó÷µµ54 (ŠbÿVårÙöØ'-× “Ô°rˆü¢WLÓD¥RÁÎÎŽKÏÑ»‚afM¸Q­VíŠÑKKKh6›$ ;;;8::bÎ,~Q‡”îtxxˆÃÃC»R{½^÷÷§Y–S‘=mFÊam·Ûèv»v°Èúú:ö÷÷q||œÙ¸wUU±··MÓ°²²â*ŽAÆ,à„¸ŠÕ ÃH<)z˜'“öÏRèÉ0bÒ-l¬ûûû¶qÚn·‘Ëå°½½m±Yƒš¹‹(Šb·‹ñ¾$IB¹\†išØÙÙI…QV*•††pÎ2LˆžIž cá kdfjE#B=ˆ©¸]Bņ è-„–a¢B)~€eì­­­EZ`£%ÃjÂ0ñ3Ô`ít:èv»¶qJ}X5MC»Ý¬®®BQ”̫Ԏ&Ȱ ZaIÛêzÚ&P\x$]˜¦ MÓ8·‰aB0M34•"n&i¨è·Pa]׿ô^‡”ä "Òäa]"yXwwwÑét°¼¼ EQP(lïâ" ªj⓲ ¿HÓC­VKÝ" ä ]×íâ5 “vÖÖÖP­V9Љa¼)~Q‘$É•·š–ÖEa¨ÁšÏçÑh4X¡%ûûûh·Û( ¶›ušÍ&{¦{"Òç®2L0¦ibmm ì^Û “f†šÄ0ŒC³Ùèzï|•篳e¤VÑ«ªiZ­vww3m¼ªªêê?É0YdXu<†YdÈ«Êc„™4M‹æÈ0‹ÍéÇ…òVÙ»:{F.ºDˆÆk»Ý†¦iØÝÝÅùóç3U)XLÌf˜,ÂÞUf–‹JPKqVä&)¨öÃ0¦iN<§—eÙ~w°‡u¶Œm°Š  lnn&}?±¢išÝd›a² {W™E¤ÑhÀ0Œ¡“Ì<ÂÆ*ø¡H™IæôÅbº®³‡5F2X[­–——]ÿ¯ir¹Μ9ãÚ—x¢ÂdR¼ì]e MÓì•ò É=G0óH˜L3Ì"bšflõh Ãà Á ð Q>Ôn·qöìYlllØÛ4MÃÆÆZ­°±±ýýý¤ï'6(N’É2µZ õz=éË`˜™¢ª*ŠÅ"J¥šÍfàçx|0óˆ®ë®È0F¥Riâ…EQ`÷`M€HÖjµŠB¡`W `[ÚÞÞF.—Ãîî.¶¶¶°ººšô=ÅB­VãJL¦¡~b¼(Ã,ÍfÓöšV*ßJªäå÷3o˜¦™ô%0Ljˆ³$IìaMˆ¡ÖV«…N§ã*¦ÔívÑn·±ººŠ\.X]]E·ÛE«ÕJúž&† s.ÏdygÊ=¢ú¦iú®–³w•™WØÃÊ0ªªÆ6×)‹ï fº 5XÛí6–——mÃð÷̈ûç]×]«ï “EšÍ&$IâBfáPUÕµéÜh4P,yÒÏÌ-œÃÊ0Nîjœ(Ã0¸k 5Xs¹ºÝ®k[»ÝF¡PÈŒ‘J˜¦‰J¥‚VöLf1MµZe˜…Ã4Mhšæ óõ¬Ôú€½«Ì¼¢ë:O¨NîjœÈ²Ì6B Ía- h·Û¶‘Úív¡iÚ@®*…Ÿ˜¹† Vfщ³2°¬É0ÔÃZ(°¼¼Œ lmmaccÝn×%$¶V«ayyù|~¤ Ëym·Ûèt:S}µZ š¦¡Z­âèèˆóV™XIZ¾½4›M.$ÃÄJÚd< ¯w•¨V«v#ør¹Ì¹Ý €ù’mίc¢2¯2î‡aX[[C­VC³ÙD³ÙŒ¥2°I’Ø`M€HU‚ëõ:¶¶¶ppp€\.ç*ÀtñâEìîîbyyyäªN§ƒ¼NÕjív€•++V(Ž UU¡ë:¦òp™Å&IùÖu†aØŠ•ú­jšÆòÎÄFÒ:|È{êçyâ|UÆË<ɶö®2Q˜g1MFÍfÓ¶C4M›Ú|‡4“!’ÁJFª«««X]]ɳÚétÐn·±»»ë»ÿÂ… Èçó¸téºÝ.Î;‡­­-lnnÆv㺮£ÑhÄ*À0iïF£aOZ¨bd©Tâ¼U&Ò ã£B«í Æ<ʶˆ¦il°2¡Ì»ŒNt$y:‹Å"íÿŸ¦®gïj2D2X+làÊ•+€3gÎ`yyF¦cQ¥a/N­V —.]`Ë«««Øßßu°pq%fZ¤A¾u]ÇÞÞ^Ò‚É(iñQQU•Ç3”y”m/<¯a˜w½§,ë‹ÃÐVvîêîî.vwwí|ÖqY]]Åöö¶¯ð€rLÿŽ3ŽÞ4MnéÁL¤åà0fº¤AÆGrúx\0Ø7Ùö"zÆy–qÃ0P©T°··Çr¾`D2Xwww±ººjçÁ­®®bwww ÝM„ аó=ûì³xüñÇCÈ nª½Øt:<úè£øò—¿œÈ¹ƒ6žžyæ´Z­¡/MÓX¾œV«…«W¯&rîYèð èå…óE»ÝÆ£>Šk×®Íô¼³ÐߣBÞ&Öÿó éïi̱‡‘¤þUª×ë¼ø8ÇÐ|Tý=Ô`%á[__··Ñª %dÇIØ€»¹gŸ}O<ñ„¶†®ë¼2³Hxæ¯ÇÇlj¬ãÊ7`Mx®\¹b¯€Þ.Ë÷ÂsåÊ•D&;ÀltxÍf•J¦ilgƒ5;$e°ÎBB£Ñ@­VC¥R±·±þŸHÏZ¾dõwÍfKKKX[[CµZe]>çÐ|TùŽœÃ*æªær¹©Ýˆ†v ^n¹å‹ÅH1ö¦ir8ð"Qp ÿ§üëi(ÖaŒ+ßpÛm·E’oÃ0X¡/8›››SYPŒÂ,txº®CQ;d °ê‹E^‘ÏTèqÖ:|ú; š¦AUUÀÁÁ*•Š+rŒ=¬ó éïqjÄLJ’ú;ˆZ­†ƒƒÖáaÜ9x¤àYròäIî°„N§ëÀÕu‘Ð1àeMŠYÉ7/È0I1 Â0 ÔëuH’„Z­†¥¥%H’ÄÕ±™XHR¶`mm §NB³Ù„¢(vŸ¢(¶Ë=X™IHZƽP+2ž³3©3Xóù<–——±¿¿ooÓ4 +++±#¨“ALXžÕ”DHÍB¾&I’’qÓ4m½^¯×¡iÊåòÈýÁ&ˆ$õ7S:::ÂÎÎÊå²½¯\.Ûy¬<·a&!msÃ08b€0BHðÆÆÆÀ¶­­-\¼xѵm{{{â‹ÚÜÜÄÆÆZ­ºÝ.r¹î»ï¾Ønz!ò;Tå‰2H @ @ÜúCÐ÷ÜÒPÂõNÀ4å› .1i`Ú:Ü1$R’$î±ÍL…$d€íU ¢T*¡V«-Æü†™*IɸÜW˜!†¬'Ožt\"ÂâÜ£²¼¼ì[ѱP(àƒü ƒEñÎq°0áÀMLÇ`U0o¥‰é„푘±ÊòÍd$d<¿ë`˜qI“l›¦ ]×CCÛK¥VVV\žW† #M2„9Ã,6C Ö|>ŸH³à\.7•A²0áÀÓª¹3­ÔHsòC¢õÿR8Mùæ‚KL˜–ŒÁÅô˜Y1kÙæ]À…ŘX™µŒ1l¡†Y"‡­VËUÙéÌ™3©ê¨,ŒJÃt<¬+vÄýK°ªùÆM­ÿ_2ˆ À4qçããS”VîÁ0I²þ‚ökÀÞ]×Ù»ÄdUUíª×aT«ÕŘß0 3¿ŒY.rÑ%MÓpöìYlll`ww×þÛØØÀÙ³gk¡0* ^`ÂÊÝÇkÙ¯4ˆ+?6]ÖÖs„“›&ðs¿¼â³Ã¯m”ãÒ³(Á2²uÝšä+ ºgÎ๗¾tŒÄ03 V ‹š6¶ÒÏ* =Ã,Tõ7Šl—J%®aÀd†…q0-šfÍoÆ ’ÁÚjµP­VqòäI4 èºnÿ5 œó¾{êŸÔk–¾²â„IúgŽÁšQ Ãà ‘ÃgÑcŠEÿ…ša‘ ’<^k/NØp%I&«èºÎu ˜… Ùl¢)¼ŸÂÁ´h˜&0æo:Ô`mµZèt:¸ÿþûC?·¾¾ŽN§“êÐà…î£wÇø’$²-ÔÐ4­?ï¤Úo"]­oøðà—‚wàÕÿÜñÞÜn­Êx¯Mðo;Öu˲uM¢1@­Ã¾úUëº2lбr€®‡‚q£(Á‘a×qx<›Í±~VáÅš £i¾‘?/ºv-é+› ,ÛÌ"@mÉE±Vö°f ]Ÿh>Ô`m·ÛÈçóÈçó¡Ÿ£67Ýî8–Òlûô¥‚€1¢‡ß(°öF .-ogÐDZƒÕÒF‡c˜z'ÕT,ÆK;üý§ÃÏÿìfÀ$Ý0 ~âŒ5‘ùäs@çcÖu–Õö Ÿ{éK-Ï/ÃŒeÑlN–3ê ï•eÿh‘bÑ,öó°‡ïþ?ù“xž×À‹5F×­ñâá¶|ÅachÎIÝœ…a¦UÂVZ\s]‚ŒašE† 5Xs¹®ed%3uáÀ¦ÒÎÅü ½jÌcûyX ÃÙF}M)‡NœP†ïÄpâfà…Gkš–!\pϧ€W=xiMS´Þ÷à箺dEéh‚“¿*Á:O†áÉMDY]Æë…rqü¼¬A¡Â"å²ÿxóWOòÿ®¦á‹·ÞÿóK)¼Ÿa Ã/žñ÷òGÅcßömI_Ý”o'ìÌbÐl6Q*•P*• iË~µhª‡¡k¡P@·ÛE§Ó ý\ÊårI?’@Ò¶ ¯~P/Û7ñIè×€â[1^ßÑbÑ áu]¨ÚO”†c°–ËÖßÁpâ¼:À§¾æÞV«õ‹4Á2(_Ý ð •ËØùÜÛy«ªÀW_b…‹‰®TêWQ¶-€Þ3M“CdžQ*9ÞøQ¿7Š¡KùÔÀ 7µR±ŒØaÞ!EŒVðŽ± ~]_(ƒ•'7sŒ7¯Ü›c®ëÖXð/{ù£âïî¼3髟*¼É,$ç4)•Jh4,ûY# Z&*‘ ÖB¡€jµîÛív±µµ…ååe;48¤mÞ¼0¾ÚÿŸJeøvÆu$AÅ ÑIUeX†e–Ðy'Ó²ìªHmv^øWn£\L¾.ø¸ý—ƒ/MNiÖF–ªÈ…RþÅç›ÿ7ßôß¡}>¶G›Z̘<2M½>^þgPxnbØ®èM«ÿRεˆi†ëYvWØ ~ôäÉé?Ï”&½ÎŒˆ7Ä=¨å¸8cxæî»“¾ò©Ã«nç•I(˜(—ËPU•à³È4 V8þ<:Î;‡ýý}ÛÛÚét°¿¿sçΡÓé`ss3éGJÚVá‹{Vø®MLÅ`ÌZ_¯ÿÒˆ_TÕÁ°Yqrý+O¹¡¢¿1 Ãª.|÷‹Ý/{ò˾ëÀƒþ­fºå¬­ïý}à–ëú×éùB½|êï`>üÌ«ßÜ̇§I¶3‰Ÿy…·Q)zH‹ÅAã”=Ir1?ƒµÏÞpCÒOl&hšÆ›yÁ+Ûôð¦t—UÓÜã…d]ÓÂ`MÛœ%q4môÔ &õP80!Ë2EáÅš¬Q.O7‡°¼¬ÛÛÛ8yò$.\¸€³gÏ¢X,âìÙ³¸páNž<‰íííT{W¤nR£|0(ÒZÓb ¬¨^ùx„/P;o]"Ó´Â!‹EàÂÖ¶F3þŠ°Â‰?ü}ްŠù®”kòó˜¦5§±ç;;;Ào²¾'c°ÀT©ÜrÒï¾Õ*`~Oÿ2Jj'íc6ˆN]·EDü Ì ¼^# ³÷¬^cSÓF[ :FŠR¦ {¡æðډcÈOVÅœï ƒU×qõõ¯Oúަü¸ØX`–Þ™™à &R•—yüº~Ä_dæD2XÇh½|ù2Ö××Ñh4pùòå¹0V5MKݤf倛ûÿ£(ñ„ºh@I³Œòoð=²u¸½•²lM¶Ëeà=XÛrO_ùŠpÎ!“x ƒ9¤THpçšúÀùÑ¿…, ã©X´zÍÖœŸz`»XôG‘ù<Ö©NnÆ WoL£ ö”!cÕ›Ë5,Ø/—›Âx½¡Â~}ŒÅïÖjÃC„½zcÁz´zWç™)Gº õÁ=db1BÌïÇÂyX ÃHÝœ%ŒSƒ€I-Þp`&!tÝZPLñ¢Pdƒ•ÈçóP›››PÅnwÓívíÂKi$µ½Ì¾µÿ߃ƒx±',ûÓåvuøÄOú„%¸"² ¼û´õïîoßø°³o˜M…e”®xÎG¿‡hg}÷×Üžæ€õ ô+_žƒS«¿S«Â|>ÑDú4•ŒiÊChÒ™¨ªŽlÝ®[ùä;;ƒF_TƒUUr¹M·÷T–ÝEËèüÞ¢J”·´ å5ZÈÃJ•ßÙ5E*•ÁBHã ªÖ¸ÒuW.êÀ8£÷Õ8 ý$çaÕè3„¦i,×^‚tà8ï'&hšÆk ÅÃGÅl°Ñn·±±±‘ôý’¶ ÁЀƒD?êjª†àÜ"P9²æµµ°cø4c¿é&Ëø»ãŸÖ6Â9½•¾ŠEË#”[Ò„îKó}±“8gÿ‚k×€›nt&Õú×å÷ØLk?_6ŒþudÓ4§'ßãzWÈ8LK1¨fÓ™ {å»V³ZÄ4–gÕïYúó> ­/ûÄŸ‹áAÏË;A¥¼ÙF#øwðÒ¥ÒDa7óD³ÙD¹œáXÿ¤¡ÉËÎÎdÇ¡…IŽŽ,¹n6ƒÇå±zÛbÑ ÐS›=¬>éµ8‹1‰Þ〺!ŒÈÃßß5¤*É 3)¡T\DO±¬i'm‚XžƒHóAÃIDATE îØëþA“ EÀz§—Ë€ù¹s{Ûjè:ð¥|¿Ç* ̈ë#w §(,÷®Ë`-¸ô s>¿Ï¿ä«ÀƒÏ;ÿ_Ð}Æ¿Ë>•sÍp¼³Þ÷z?´™lÓ Dž½ºþjÜù©ì´D˜j…`ú­F}‰›¦õðã|ùO‚8¡W?ÈÈ<<´&Âaá¥b˜°¦Y+ûÞÉ Éý°P]UÜOãTÓü`úLÐ5fUU9xZ˜¦e4Šò\©Œ1ÑlÊ©X˜Ì‹_ïbv^È,Èpn¶~s’“¸ Öf3ÞÂNÍfø¢m€||œíw€½«©bÚ©Dr< c°¦­€ù ö ò/í‚?gÿ¾’ä„eQ‘"?j@]œ¿…Ù1¢gÆ0€¯\oå…Ò¾µ5!g–qhšÖ ÏqDéÀy„ÿùßXçª×–4¢çó§¿|µŸ+kÀ 6 —ÓË~/Õ-=¿¶†Áž³EXÆ.„ÈKa¾ÿòG_ŽÇ¾í±É~Ä1Õ‚ êÏÃ(—­ÉnZr޼Q¢ÁZ­Ž> ®T,ÁW÷ÅF?‚žã©SÖ1üŒ/I 7B%ÜÈÎ(AÅ:RGŠC¬B¡œS¿…«(=Äëuoi˜Áê·ÐåwœŒ’¦ùJjØÛ\È Þñq-ŒÚ!Y1+¨ÝÑlúÖz¸çžÿ+¦‡–^Ø`M†1Ý…À0!" a°š¦™:å¯#`~7 }€O=äûWá`Yv¼žAa°€e ö¿£?Ol£aý‰íÄçcÂ)Éëʧ°´¼ùUîã) PÜñvNî¨ àåß?XpIüÚé§€Þ‘³ï‰ç€§›öÇ]vEq°Ë‡M¿Ð“ë½Cï³”D¨ÆÉT=¬¥’qŸ´Ðl÷úx½2âÄ{œÞ¬†õ\ÅòÌFÑ/õzð áèÈ?o°¶/È$}æ¢X‡ªzúq͘IôB£1(w¥’Uê••ÑÏ5,týèh¶Ï*Epþj~éqêÓŒ/eXÏçýuë­_ŒïžRŠ®ëé×á‹Â´õM cj! Ö‰Ck¦´@.I@ý}€ò៵6hšk5žlTÛN ¨ (?ÕVþMÿãw}ÆpV·)òÅw[Fž‚¾AìYý¦k¤¾á,>`rÀ„Z¾+xÅ+Ü/›*ÜÆwQùjÿy8ñ9à¾ÙŽÐQ”þ§¢LáϨÀ×Û´>Cc°Vƒå­Õ­¿«¯¿:5«P¥èïç>¬(Œ_Á£q¨iZ†È¬Bo9,З™V6Œñ<¥”*‘T÷ÒÒxߣÂ]~9ÕÞÉu¹lýc´2¾¤2…)-ø=—¨ñ¢°³ßm”0KZLΧëÙ fOÞH¸Z-ÞÐø 4Àj°R1¥a[[[Sy†ñ<'}²°1ªr;"F°Î3›¾Ëð»ãMÖFÏd@–­Ehûä"ƒ-ˆëOø>÷dD–Ÿü%Çp,ÂÚ/&_›°ŒYŠÍõ¬fÀ5yç//ºÕýÿÜVÀ#o¾k7?íDC›}{·ÿg‡Å{£ÚÿëÜ¢®æwô©ÏçŸGV0M3ñ°H±ï̉2YñT­fMÐÓŠšah²33¹—åñ^ÞÔÇ:©JÙA¹ ^¼}ÀU58Ì\ŒÌ!Èh]Zrž“a¤§BøœÁž§!xu·$…‹¡@‡Èˆ)#Q¯gÍÇ‹à5Xý^’4Ñ.°ÙžþeS~ˆÉ’ÆV“±rêTÒW0ÞßÂ#“‘¨ÕÂI§m°F%—Ëayy9®ÃÅÊÄÕö‚Œ±!ÔjÁ:Oÿ çý×¾õè­ž•x]·dƾtR¢eÑRÚ#ÎТŠ×˜Œ c”á™ai"Þâc•ŠÿØ‚É0ü'ó;;¾ã톞ÁCMMÓ²]0oÞ´iœ¢Ã©ò»_4R  C ÖB¡€íííÈidâ‚4cÌM)u!ÐŽ¸ß ˜O>í™»|?R«Yß—šª#ºî*4À7òcÖÖPý@ñ¬g¿wÅ/¨¸…—°Ç§ÃªÀ4>ÅíôæÐ4ÿ…€"€ïü¸ú\­ßû ”ÔÚMaÒ0ã9wj¯óðaç·ŠNdûZÍlyX­Ç:%å8BH¡Ë%zWTÕõro6‡è.r›Spb˜æ09ö;Ö¸F'O$'‘¿Qg½bÁ•YÇËkšS™w˜—“ò±½EÉ‚ðó°²lMÀ÷ö¬ÜnöŽ ¢  Ñ°Æ”÷]áåZÓô)p42å²ÓÊtB©$„€a°ÈÌ@Ž—€8Y5d³œÃjšfê ¡ÆŽ'Ì{.)•œð9ï½xÛb’×bgÇÞˆ$?§Áˆ 5X[­ÖÀJ_·ÛE«ÕöÕ‰ØÚÚB±XtýÛçÕ˜ThúÒ¨ø¥ÙÜÞÿLþ?Áüú‹í‚SñÝfŽ’¾ãMNõ\¿¹Ó‹CLS݆¦@õäòQ…ÑœM+,ÖäõºŠÑ7,#ÚoŽ£{¶¯ÀYMÔ¾S._¹Ízî’ó®—ÀèWR–å~*¥è/qÞúe8ÞÚþqEO^³ 4_ÜÿGÿ-ã&NùÖ4m:«we-`’J)8.ý$æ+x*‹M”$ëGæ¢<;À„0cbooPYr!£©§Œ{I¤Þ¨¹¨â˜õÄELû;7EBŒRÉ[’†£²<ÿ†!LK¾3*9 dô‰‹0äL×…¡ö^‰ZŒ¡X´Æ€ªZw?¦é¼Ü$i°_pÄ\[ÓLÞÃ:Mýyï*0zXy)•¬ñR«ùq›ØWûàÀY`"bˆ¶yÑ8_ºxñ"vww¡O1?åøø«««®•Æ\.7òq&^Å¡[ [ÔfKœÿjZ?T5 ç¾ô, hO× ? ¹,£^·þ©^yJÊkÿ›ßÉõAû± I÷¥;¡½ñס}¨ïöwÖ|ö.àÿôL4Å2€iÎRôŸ*û=Fq»×8¥ýÞ÷ )wÐ^ìã¼­(–QÙoÿ×xŸv˺…ˆ7I´?…ã­Õ”FÅ=Ó? ”îŠô«O¸ä›˜ÊÇÛ'QU­É‚ç\´

Ÿy‚à¾Áa°A55ùÖ4 !ù˜ Í7ű$¾L¨º¯g¬Q‘aÀ½ˆäç­ *6æåÍŠ•€ÃŽ 8ëkÓÔ߉G¬­ .&Ä ­â‡õšN§NùWeÇw.FÆ,ɲ¸_’çSýׯÀ§>uçH—™Ú*Á×®]C¡PÀòò²ýW(F>ÎĹ b•ÛH.½Èr°'©Øîë3]‡ñü‹&Ë@I‹PT@‰äû.@þÎîÚÏÃnYc;0¾oXûÅü_IpìbMI—|1DAù¡¹ü>æz‹+5ª2m>ôñr»r¾%iøj´xÑ(6M§%ÇÚ˜dˆSƽLMæƒX[Ýè SGTŒtn1ú`eÅúÓõð\U&”iÈ7µ'Kºˆ^*ç-bÿx»EžèŽ,[b.Ë€ñgŸq·ðF刭®Ã0†8É$iÐø KOñîó†MF ­;k¦©¿÷°N[×jó¥TönÛÛóÀ!YŽzž‚+WF_üH­ÁJ!Ç[[[ØÚÚ;ybƒUeè­„ÒvÜç —×Æç…ï_wÂùŸþ—ì7š†ò}ÁÙO¡·á·u¡Guñw~å¯þGgÀ7=3º6G„Õ:†Záâ Ó?mÙcE‚e÷ŸÝÀ3|`lº»ó˜b>l\x#>§úÇNs .ù¶žïj¥aX/RÊóîóP¯[ÏZ×…ÝâÊ·°3¬²¹ë=–+çõN5VÊÉ£¾§qä,1#§Œ‹$e%è{€%‹£¼‡ì\1ð†õx«=V«ÖŠQ½>žž´2 ùž‹ÞÂIàZÜ‚IC·TÌOÿ½óÞ¨VýóðH·4Ð~÷ ƒÅÁ‡½O VïÜK‹Ç|`PMÜòCFh80àïÄ)9¨Õ‡4¿Üÿw½|“§u$92¤ëÐox£ÿ‰éغÞ_-„Û,ËÀÚßô“¦ûû^ÿ­ƒù©ܽfuÀøA‹,ôTîÿ †å@»¿¢J*l/§ñ­!ã¤;”Ø0E˜»¿0^æž“À1ª)¯U¸OÛ¨=:Ïvðè£âË_þ2’dù€gžy­V Nǵ},oű‹hpâ„%Іa­ˆyóCÎEu^ Z¥ýË0œ÷¹w1¼x÷3Ðÿüig…œˆPTZÁ!£@¬â»³cc^•Êxm?‰V«…«W“¯„‡÷2ó M>$i´\Ïa•FÃh6qè½–a-¯Áê½î Dív>ú(®]»–èuŒ"ßAú[dæíl&Q2q¡ëÃ'½Þ•΢ð’¢ èÐå2Pì\v§ªx¡Ä ‰,£ôúÏ® [H¢\Ð=‰Þ÷«®C–ïùKw»£Mèãfú;ñmU~Ä‹OêÔX×¹²2Ù1¢àF™1 ÖN§ƒoláÅ/>é{©4X;Ö××qéÒ%lnnâüùóØÜÜ íõúì³Ïâ‰'žÀ•+W\Û'Îu"ƒ, ¥„Ò*÷Ü¢^·¾'ßäÿ½ªÞ[,âàs‚¼ôãWìs†ÆýagÁî,…ùÊÏ;Æ ÀP{Î}žSÿ÷ÿn]X–G´_@ÊU©Õkƒ˜@ó}Â⟟B^Wò²–¡(~¶‰ÁPbÀ.Šd|»SÄÒµÐég ±?a1ßÔ«þâ9Úü8>>NÔ`G¾kÂsåÊ»ùHÞ&ð” Ÿ’Q ×s¼/~ ×g²L 6vDߊ]¿Âj©/ýðã?üÙŸYHסþBúoÿ%ô>ãþU^$¨¹ñÎNpÑ$qEP’ÆËÑK±+Ð8\¹r%ÑÉNœ:ÜËÌÃŰÃYM´TÕZ…óŽíµ5+·»V 6\ý¢2`¤Š$m°Ž#ßAú[d¦k£1zŸÅ¸¡jòQ”]Ð궸ÝÇ«å²É½áòbÇ(6o/@Û=v;nÅ|Õ0 îÁJ…N|ɇ?ü_ÑívçJ¾£êïDÃ)¡yšÞOñwä}1«±éMýò°²r)’Ô¯0Ù¦h=ÇÇÇxßûr#ËwdƒuccÃþ£qýÅA>ŸÇææ¦+Á{uu5´:ñ-·Ü‚b±ˆÍÍMÏóšpr#d>Ž+XÛ %@¾ÃÿÇ.ÞrNCˆ¨Ô4Èoø¦þa‰º|ö¯“Q¿ è¸%]½Þ2>LX†  @³ Dûá}D ÐüB¬™ðÏM5a£âx”€æ®Ð/Y wZvöéGÎBÔ@(¼ðÎÖuX 2(~}ð™Öj€q ¶÷ØoшôÓòò2î½÷^¼öµ¯ ñ3Ž|Àm·Ý†ÍÍMW¿c3jX‹ÖÿÑWVœ~‰£FøxX©Î oô{øýœbn¿Å/þ1ô¯¿Î®@g<üwP¾í1ÏçÝߣ°^ñÿG ¯ô­åææ›G{Ó„Æþ$ÝP677qç£4ˆ“8uøàó™qÁ¥$*üÊò ‘Y«YÛ(|i)xÒ•†$¸)²ººŠ{ッzÕ«9ÿ8òí§¿EfÞO›Šè%}B‘>ÃÆXÐ5z=¬ž<,og™•§=†±.ïyoé/|ô/Üâne<,§…(—ƒãzK%k¿ß{²X„ú3£xb ÿôÚ5äóùáçšÓÒ߉·³¡‹iç—Òý‘#BóúY_‹àa U^§‚÷9И0Æ———ñå/ÿÀÈú{¨ÁzòäI¬¯¯£P(ØËËËÛè/Z­Ö@èYâ£V)›x`Ðï9C‹ïbç]ÿ€H>N<ãMØ®þ0 þ‚ðAÑöCuÝ:ž¢\ê—Œ^²VÜib£õ_rŸK¢zN,#PÔç­CØE½hݲ àú9Ò­g ÊaÇc(ÆhÉÿ»‚,¶þ£b®ª ÜüPûßœ»Æ¼H+îögöaÿ ìüU?'_Z /Æ)ß¡á‘TrÿÔ)ëߊb=hÏ‹´ÑÁ›ç™XˆL»î‘¢ *êrÆmßg-¶ÕëÖçñ7Y_>8@ý¯îò¾ŸimçN–28ÃdÔÎl^ÛÔÅ)ã^f>±=¬“5tJU'»ä‘¡œzÝË~×5Íê— €éÈ÷LC%i’:¬íÑ,®ƒ&Pa×áš°x¶{Âxʼn˞Õ4˜ßðJ÷÷)Á•Æ—¨W^ûZ(ßðîp¯„¢Žz®ú…3—ËÀóÏC6’õ|OKë]½ùæ˜ìKzæÓ\¨ⱌ„X}wÚ y¿U«Cž½ß|Ï»_U]ã{ÜG?´­ ­´Ì’\.‡ —¼»»;²Q<’wU×a<;OvõY÷9Üé@_€(¯<•!Ú¶ ·² ù&«»M 0hò\.CÑ…)Á)³J³lì&PôeÒõ€ö€bçÈZÇ£û=©Ù”¾NÒŠ?êÞO! {fÿØïìæzÇžl…£ÀòØš@ÙGÆËeëoiÉ© _.÷Ÿ¿]üOåÀý3yÇ‹_bñóÎ xì±Û¢JG¬Ä%ßÀ§Z!$–ê(‰ïxZüФ}<7¢ntìÈò@ÅE?é½¶Y@Ã^Óf[ìBUýç`b¤3½(æÍa§Œ{™ù ý8e;IØE%Dº:ìX´²î c¯T¢¢óºÊ1GLC¾ Ø]¨¤8×I²Í Uª¦ë’]ïvqÇû9a6ìZ¸Vþ½Ï±),˜ IÚ|ï7¿øG€ÜpÞ[t½#@kÅ·æ÷Ò-Qÿ+¸¿±ñyüÔŒ~/ÓÒßãÖ ñ˜8°†žù´j&ÕÁb˾i3¤èÒĶ=åL Óî¾û™‘•ÊÖB¡€õõuœ;w8{ö,Z­Ο??Òq È68N²ÜL~¹b!ùö ß+ò¯¨Ê—} ­þé%OÛBRü ü+ 䱥L–·S PÊŽ°ù„‹Ë¯ð7Î÷ 0>a]c­ÖD‡U–r?¬wí}¨\­öçN þ޾¾ò3€Ñ—ÉæOµqó×ÂõE¹ìô¶?×ω•åá­~©&bTÂ>p[bk\ò ,•\ÂG¹Â^å³³^ØpàÞ…³¡©!ŠGÎè7¡<#ߪÑCð«M3Ú3t*ÇEÐõ4›Ö_µmŽ8’÷;EÄ)ã^fÞòC\•ô«æ‡w`άË4­cøÔð«Ì X 7éÊšS‚j¨ÍÓï¸{S†¶d¡IjÒVš@…„Ö¦¸ú¹}<ljA.ÔrÙõa]‡ý2²[Jm">x{µšõޏ܀‹Kòç ¦¥¿Çõ°R­“‰½ÚÓZ¤‰6-ZÆ ï5-¼.Ä;êêa<.ôœ=sÑqêa%Úí6vwwíPà CPÉ;¹¹‰ÕÕU»@APÞG‘óûH™¦»äoÿGRÕÁ@Àà™ëG%y- ²×ŸìÏï øËE;7– PÚH@]H?³sš‹ôX’×W´“ŽÞu=‡ÏÁÍÕ4 ÔsΫýÉ`Ô®¢À®æ[’¬ð_Yr‡ÿÖ1w~ XúYÇ£)÷ïCùP{¨8'´ÏZÏ%h¬”J–—•Þ?õ:Óg`U«Îu†õÏçŸÇ«^õß¼5šŒÄLò XkÔ <Í…½5YÄ<â¡ó%ϸ÷ί«Õà÷¹÷Ø’äèf‘Qtu¿fÓ@-Q(—}Æà†¥F¼‹*Ôvo/ø|T£€ÆE”"|”Gœ6ÇZ\2.9˜r¶ã0ôÄ<êb1z›$¿ë¤ëòD>؆ÿÊIFUÀ_ÌqÊ÷4Z5Ñ;ѷ潰ÊMoŸâEGý¹]Ñ7AãÐSÛäÐhQ["¶Eê|¯VhU•,¦Ça£Ñ/!Ò_£ŠRÿ¯RIGúÒ4ô÷8ÄÚ!Fcãæ—£^wõòE³9Ú¹üB½––¬¨Jª&Z,FòÀ’±4¯3  ¦•±°XOe™HÒ€@›¦ÕÖ¦×íP‘<¬š¦áܹsh·Û®øuª¶¼¼Œ\.‡‡zh‚»$ŸÏÛ ‹Çaäð±r`ƒ}o¶öy xXeÙ-‡´X¹²'çµÜ_=®Õõ•¢{²ªj?¬+l!ÌV|§QOVÀ2æ^ëSëæ€þØ^Òr¨þcëXå2PýyØyŸÖ3ë y¿Êqý>ç˜Þ¹: ½ÕzFü¬Y×"]ÔÍš¸¯¬XNl{•tox*E³ÖjÂ=…ôPõ¤®øÎùİœ{ïý»èr1%&•oÀšèD•qêö"þ†” <î ¦m(š&°´Z áäPHï< RAd ÇC<.´¸VYzÔãQ_Zª™#>¯“Í»êÕ1~ˆê´‡Œ»ïuH80Í kµÁþ£ãâme‚ï7¹¥ë¡Fì~÷´=¥˜æäØ«“扸ä;îVMTËh ˜¡sÂØåŒÕ"#®2xziÂ<Ðá,luQxxiTû܎Тpe+ï¼}äg¦(Î{—:²ÙPñ4ÏyÓ4üãÔßš¦µ(£ªÑÕ®=oW…çY<\o° åÔ¢ŒzȋȲ5™¦ÅN]·&CœrºèOÙ=~½-þ†©JÑ›T5é’{‚6îY$ƒõÂ… P—/_vU-+ X]]Åöö6Μ9ƒ‹/NvWS€¼Oô€ô‡º0ÞüÏ‚¿ *Î" }Gßzþí]¨ ¾ : ©vx‹0½Å;M@¥Ï@M4OGŠrÀÜ« §‚±àôà5•Wú»¬Ë±~Ýúž$ÁiOÓÇnÏÙoƒ~¨3MJ\‚+DVôz}ÁWú÷^²¶X;;ÂĦ^D¨V=¡šu „';¿³»Z­ŸCÆ‚ª×®E.H5 }ëÅ/””<©¢² ¯{ûh›¦Uè`ØD–á¬Ò”Ë0‹Š¯~xY»îÁ-W¤‡A÷A=vÇ ½EþÈÔjÖu”ËŽ 꺵@êׯ“äQ¼w¿…S¿çAï1ÒTäøøîÉn&… ØS„ÌáatA•a“š%y'ÕT{ CÞR{sB’tô¥q'ó|•_³ÙïtçÓÊZÓ€¥ýtS0#Œšø½[¨N˜ªŽ0äü¿Ï9ëu ü—ÿlð]D-qB°õmß5ÏöÌ ¡Zųy¨²[‡. xnig'xÎ#¶œ·zQ·öE®ª6)˜ÅÖOSX¤‰xãþÛWV¢¯ÎW«N…øRÉZô¤¼9/”nrꤿý(ŒO}ÍRO|=… K$ñZ‚· ½¢¯ýè}⇬­V Ýn÷ßèçî¿ÿ~ìîî†6Åž5>F‹†˜—?†•GþmðäV\‘¬‚B;;€þØàG{ú> ÇüõÏcçùßuÅ‚7xŸ˜Wáö Þ»E‹u/~9pƺ_ÛÅ2€’:éú.€ÚÜÂ*Ë}¥JÛë>mê0ªȉ,µ&­¬ºîeˆ2{‡Q>l£Üxã?Œv1)Ä×»Ú_’ö* GÜùªb!q{£á„£ú½Œiò"=sl Hµj¯,x½}‚=;…{‰ïaQ;”FÃ-ãx½²ú¢ªÑ boˆt£aÙPÔÇKµêž… {ótÉLÏÍ;15Mà#IªdÇô0M38žÜ1ô ©dܸŧÕjNEîYµ#HôÆÌnXtƒu¢þ«†%{ÂÊéP1¥@×(úwüÖÖúÕÊw†‡Í«ª»#•ü ÊekØííäk лC;èÙçÕ4`I«»ZÒ}È0 ¿ô‰AÝ,Ë0>ùuF8§½øN7ßl,ÌáWÃ[ç Ù´žI³é´G¦gB"¢n_ZrÏ)dm-Ûë82N²”JB ý•6ãi¸[¸`ðûºT~¬é¥p ÏïþFà7܉ê¥3¥Tä—Â2PûSy\]UtÅù·ªö÷{Âl}õw¬ÁÊQmx. ”ÖpÎOm–"ëšþ}„1¾—Ô'h`‘§k–-§‰o>_¿éÁû9ˆ A«Ìä©$H¿Ó" ®•ÚVV`üð*?ÖAñ‹l)ǾåHõ3ÄózìÙËı@Ç”¤å×}ð¾‚æm®^|P5Hql—ËÖ¢hÌQ1šsÝdØŠ×#æÈz£_ àÛ¿ý/Ç{°)fh‘1ï¬vyJ~³^Šo§p’4ÅõMª3J¿ß÷ƒªƒSÄ©Sƒüßý»;ññgÒ &ª|­i–’±'Žó¦;Ø‹“zÃÕηVsô‹iZ¿'=o:ìá¡%æTtÑÛÎ[­:ÀùýDoަÍ¥–Öd;”X6K…gÐxÍ¿·.¤Ÿ³7 ›K%4þÓw¹ê˜‰¤ñžg™Ò4—€‰ÍfÓÎd8†5QUë9ô;³¹‚'jµð5z–Dµjm;<Œ·ø_š·ýN¡EÄ|PŠ&ÊõÓÐ/‡8Ñ¢®rSÃ8}÷ÈEé½) !¤JŒSÊ‹ ~PÉ„ Y#ðÆ­Qå·ø3ö­ö†ðþ÷¿¿÷–·¼eØÇz½^¯wúôéÞÃ?é³qóðÃ÷xà×6Y–Ý:<ìõJ¥^¯×ëU«½^½>ä Õ^¯ú#\DµÚz½êÒ×z½׿ÞÁð9eð«Êͽ^ýž^oç\Þu~bçéõëd¹×+{½ßrkà<½^¯wä>N¯×ëõžêï¨×;øý^¯\îõvv<Ïã©^¯wØ?Ä‘uÞHõ\÷î}üår¯÷ÔS½ž¢D<Þ”ËÖßÑQðgë:üä%í¼ë]ïrýÿÞÞ^¯Z~Ü£#K0„çA¿[µjýÆô±ÃCKVÊåáçUë;¥Rt9ØÛ³äTQ¿³³c]›Y¶äd‚eàðpøqIFÅÇúÔSÖ5…ÉÖ°ýã°ã=Oñ™ííõz?ó3¿8þÅ$À°1¹³³Ó+ ò=ü”j½n)’I~ìŒ@z|g'þÇQ­Z2M:«'òùçzõúÎxO¯þ&ŽŽŽzʸ/ľί×{½Ã¿¸ÚëÕë½jÕ­#èù…ý>;;‚î)•z;ç>j¿öö‚uæÎŽÿ»üà`|ýÝ+—{OÝs¯u?ÖxëßPµj½âüî¥\vdä©§z½§^÷ÖžëKý ªVÝ:þàÀýn«×‡¿#χ& H^ÒÊ0ý=0€=W,•z{õ#ß¹Bßÿ¯z½jµ'ßôåà‰ï“0 š¨xñ{_øNÌ{=I²ZŒÐiŸzÊ_^ŽÂçáQç‡Ã ù#ëðÐÚ6Î|¨‡µP( Ûí¢Õj…~ŽöOÚ>Nî¸ãMî¡!{”ê›Úó€ùaCØbLI²úóÏ/z‘;×ôi14Å?tW  ­b”àòè– ûá6{{}ï 9½ûÞVß^_2<ÃvQ'Ù y¦¼×ÊžPàh¤üþ%•áT¢©b÷B¶ˆ':Ðç|¾¾wµÙt É‘WP¬ O¿§_J‡_ ÊÍ¥àj©d^<8ÿ…’ùm÷óÚ4–G Ê]¡^¾÷z"½x£t(Ä­\|6j}êÔpÙưÖ:Õªu-AzK .•€nxvü‹Iš¦AUUÌ:ÔÖÇe¯Ρù _/jäñkGå×áÇïØj6-BEk OÄÑë_/{ÙóI?‚‰Ñ4mì‚Kæïÿ V®þXûÙÌrÕvT8%JqÔj€$¡œÐNá k”ê3Q?íbÒ‡ÿÅ·æ¬ 9"Õªó>òBu2¨Htæ5ÖKÀ0\á(õºõYº>Eq¿Û‚"-=—ÈŒÈ8ÞU]Š×}0M/ýðÜs‘¾§ýä¿GóïßÔë(®ÜìÑ£j*1'Î÷<ÞŠ ^ŠEà©§bo³Có;Iò¿-o·6¯Žö¶·¾‡˜òEaÜ[d° lmm¡Ûíú~¦Ûíbkk ËËË7… MÓÐíþóÀ)á¸ÿ¤ÄVA¨þ²õoÃj¿íêÔ7à ©[áìì/y ”à ‰-~\d ¨=5x®ê«½»ùlðõPhe±(äwê€zÞ*Ôäk°!r©ÕÆ´9:Ú§xl¢ô𜨽õ/åaÞý†XO=H§y Ó«S‚úõ‰á¦^Ä.r^¹;x[+4›À;ßùxÒ ÆÍí€æÃw¢øƒ7Ù¡¸§Nù§ Po0jÁQ™É2 K>cp’„äU»aíÇ\ïêC>â䯝%3ãÓu_ø°³ùG ¨¿ä½áî{_´\bÙRN¡­†©ú.`~åˆýr}|0?÷4–´ú@E\Ûs0iEÇv‚ŠÒ0¨qý>j(/E>NÝ(¿tܨD*•zþüylllàܹsX]]u¥W®\Áþþ¾ý¹4ñØcÿÈy0>³óaM2IðJ5_i9+›M $8ßjKÎ0úP‚«8ô¤óoã£@ñ}Nvè³­†þ ó¿« "E@~€“#>áúF-†4)#åÃŽÀ¢9<&:}KUœk”Ëþ=:©Ø’w¥x’šq³³ãTו$g±=*4VVVÜÊp ù­”ÓbõУïɲ“ÿKÿõšâx&APjå¼¶ ¢V«aooÏß EÃ~„Z-Új`M*ÄjV>Õ~ãÈ1SÕxÚÌïÆÛÏ’€ÄqÖúðí•ì]kˆ2ŽÄ^àùüóHQDZÑuÕˆJdiÉzN´èVþÏ«ö¾rÙw}Å‚É$ÉùQDhÕDt=º/ÒQ.bãçbÑú®xQt¦rÙòðU«Î˜£ÏÕªÿ¢YPåÈ•ÿ1Oã®^†d)Í £Læ÷öœªÊAm|ûuªfÓ €¸a ¬´=H É •CÚF+/Þãíí9=_(çˆ^8 T”Œ±7Š@Ô7 ¾é"”ý«PþîSƒú\øã”#b^ýJ"Y¯c¸ËîM¡¾†ó ?ÔwP’€Ú)‘†$0¾ÁJÇöÚ£1ï‚¢·<éX¿–~^u@·ö3’ƒŽëýVÀ½÷~ÍÙP¯ûÎ H§ºôm±½iÀüœê`å2$Оè¿,þòð/^ ä^ç> U×è—öÉo¨À2tÅ1¸˨Ôúÿöc\Ã/Á÷Ulf&C–e{â¬&‡b©d¨¤0iî5b¼“Í´R*MžÚá÷ýjÕRÐAÆyY½ W|¤qÑ%Êûwž­žJžša(Љg¿%ä!Ç#£zNŽc°Š­¤±ËÁ$PÅÓ¸-(ÊŽÞÖJÞñCaó46L3xüjZ°Ç5¬¯e–"4MóÈÓsS:(2©^·¢©Ïª¯ ö½>v9q1bÀïásÁø)»aÂOJ4æÜL÷V*N§ rÔj°«‘ͦeŒ³à84‡ÕK.—Ãòò²ý—FcÕ4Ï|æ[ðö·¿àl ‘’Ú;=?D±­uòíÿàj–¥_*U ü6ï}©å¥ô¶ïuQz@ù,¬pa?ª>û$Xy²aï…5>Ça^< iFÓ4H’dçè×e@¡Pˈy0Ng‰$Y)+a²–Ê•Fc5‹¤¡äã(#5®Õ`¾åÇQ¹uK/océ{¿ÚªHÓ€'ü´qºˆÇõÞ’¸ú> d,R;˜ ÏDíEI†Ðo '' ÇÓtÙ)BÞË0½K‘"ôÿ•г=jïhº4¿BbÔ°_' UuÏÃj5ç8ͦÕ×Wì}ì‡$9σ"©‚&¼á¿ÀðTуT’"ö'ÝŒjzˆúˆŠ^zçž“.8fÒ`-«WßíÃM x HßëÔh6ÃÿᯠŸ–Ý“¢"P¬62Ä ,Ã’P0h”*ýÏŒú2¦Ö2)Ì•c’…ªî‘¢¤pºÀ¢ 3‡ ´nò8†P,Bƒý3¹¯9yþD‘ÂÆÄVCbµéþ!‡VÕÖõÁ‰‘ßd‚V·éQŒJ/Þ0´çÿUÕ1‚­Ïú‡Í¦Ó:ɯ%•a8FpPô…K ÁI6õúðŸÍÏs›Ut]Xi6-ªÜl ¬W€•×ú-7tÝzˆ‡‡¬ç™¹ÀW‡Nì(Y†ãä÷Ãü£?·d< ?âðÐÑ/¢&Ýxõk¹ì,Ò>qñÍ0¬Ë8u*¸˜o¹l-ÕjNM±ZÍÿóÞµTïÂÞÚ{tdéÚ¥%·1+"¦ͦõ¯¡éçÅ-•¬g¶´Cßk4ü¯A|'”JÁ­ƒR“¨.ɸDÎa7ì"VÇó¢Ãe\’wêà@ímƒ†§ËðlÂñ°ûÇQúÿ51h`a¹:FßÍP&^dY¶•)¿I Á0LÚð-HãkäúŽõ_Yvç†Öjþ¹Ôc˜ ”Zâ÷z¤÷JPôŽX×$èý“tjY& VC\:®T‚ËiipŒÒ5 ´'üÐ2üKVî*!þ»+Õ¿Pa†]×ñ?ñ¿ZŠ­±‚ÒÞ«#ÃÌ;¡+ó ŒjãQ‘ 1uoiÉz„{OcnCÎ4­•i¿P/ £ò+ò±¶æ´€\YqVу(•¬×•˜ç5U—BâN(ÄÇG‹£V˜¦þÆ^¯÷y3>ƒ¼Y*FP~¶$ÅséèiÏ0“`š¦Z‡0/'ëmÝ8L_Q¼v^ýO‘it^:žW÷nÕKèm¥?}”cDiwãç©õ’Ö…Ã̬EjÖöËèp L Ù%öKR`ž~‡Ô„Ïø1œa¼†Ï~öÐüI² 2²ÁÊd…ÀBž7x­æ¬*—Ëî ‡8‰jÌù­èS/?ïëį] àTB¤?­Ž‡MüZ•H’eÄ!§µß…RÉé7‹äL ’וּ¥bÓ4Ñl6ñÞçž lM`Öâž×X$tÔ Ú}ôÞðc’âL‹¤ËfE& VI’¬Á°¦AbHp–ÑY†ºë·Òëç%]ƒeðrqfFìííA’ù}ÿø!KÆ‹Ežì0Ù!Jï>Ê ëI‡Ç.hòD“ ÊER'÷U„æiÔ¶2o˜,y*)”^iä¹?ÎäJ왿 “Ì膭¦ôcôtSëÝ`˜Qi6›øõ×¼/yä_c•r%½Æê¬àŽKóEF‹.­žOa…9 ¸sT)°z¢á7¨dá 3ŠÅ"dÉDñ¿ëÒô‹NÇdŸÀ`¯G5)Èy6þ¨ðѨÔë–aypôzî"P•ÊdEŠÆÕì=˜»k?~Üì^·P§˜ìóüê¯âmŸü¤k%ŽªËŽ^ã6qL2i°,Ã]ÐHåa5`¥£¼ÈËR0ib‹Æ?ÌK„Lfñ-¸Ô‡*3¦ÉU­†¿rÆ5®½aÄ”ç)IÖýïqa¾¹Ã4M+ Œ*¾ìíÁü–×ñÄÉ š¦áo¼×ÿÔO¹VÆVVxa쬣¶=ÂóW‡}/áêYÌâÑ|øNn²ÊdÛûD˜¦U= Nw†=óŠ=P«¡öš÷Å"d™Õ9“TUÅÛž{n@¨Ù£ÊŒK6 Vj°¶ÜíÓ#ÎÎce˜”£Ÿß‡œž—*™L2PFUm}ž–0`†MÓpæºë þÙ·Àü–×%}9 +†aà5=„Ü[ßj·¬©Õ¬}]×ñÐC¡Ýnckk+Ú—M5X«+ü·ÒßÖLúÎfBù`<{;¯X2©fRè:Ôó_€öoaO“*&‘ï„æ3?Â9«Lj™H—Ë0k 6V™XI¥ÁÚétÐjµ°¾¾ÈårX]]ÅAÔæo€X!¾uG°ú§šðf˜2±|Êzç—“Vâqè:jÊ!Ô[Ïãà£7°'ŠI “ÊwãîßCé§®g™fRIú{¥tªUž§0ñ‘JƒõøøP(ìm…Ba¬\?Vë™9òJìH9ívûûûI_FâÄ!ßY胘EyÈÚ˜—‰e\×QùÏÀüŒƒÿò²¹ØgM²8fÇ!>ïÞÕ,ÊBÖÆë¸L*߆aÍQæ½pÖäaÞÇl*sXÃE·ÛE.—ØþÙÏ~>ø`¤fóó‡>ô¡¤/!Vüq<ñÄ“-<ÄtŸùÌgpâÄ lnnÎüüãÈ7a}}wÜqòùWaÞuiZä!NÒ2fu]Çç>÷¹ÄÎ?©—®ÿGè|×IüÐ[þ—.%v“yˆ‹´ŒÙOúÓxâ‰'póÍ7'rþqäÛ«¿çY®ôÈBœ¤e¼’þNj>Ç<ŸÇÜÏQÒ"q‘–1KsðQõw* Ön·¸ïÚµk¾ƒ¥P(àÍo~3î¼óNÜ}÷ÝIßB,¼ð 8sæLÒ—O>ù$ž|òÉÄŸ'Ÿ|wÜqNœ8‘ÈùÇ‘oxã߈»îº ·Ür n¹å–D®=NÒ"q’–1›Ëåpë­·&vþÉuø]ý­É?ËIH‹<ÄEZÆìí·ßŽ'žx¯|å+9ÿ8òÍú;ý¤e¼’þ¾ýöÛ9?ÏÁ-Ò"q‘–1KsðQõw* V1 ÁK>Ÿ÷Ý~úôiœ>}:éK•ååå¤/™ãÈ7¼ç=ïIúÒ™!¤eÌ&}¬Ã-’þ²JÒÏuùfý~’–«´\ëo‹¤ÆM*sXOž< À–ÐétB'ó 3/°|3Y‡eœÉ2,ßL–aùfÒH* Ö|>ååeWr°¦iXYYIúÒfbX¾™¬Ã2Îd–o&˰|3iäD¯×ë%}~´Ûmlll ŸÏÛIÞÛÛÛù} 3O°|3Y‡eœÉ2,ßL–aùfÒFj VÀJün·Û8–œÉ,ßLÖag² Ë7“eX¾™4‘jƒ•a†a†a†Y\®{ï{ßûÞ¤/"ë´Z-œ8q"0”¢Ýnã…^ðݶ/ÊþiÐívaF`ÛŒI¯9‰{bÆgùŽcÿ4“ñy¼f2Âd|åu8C,šþvMi¼f2X§ÿž"Ñc¦ÆûßÿþÞ[Þò–ÞéÓ§{§OŸî½ë]ïê]½zÕÞ||Ü{Ç;Þaï÷»ßi_”ýÓàêÕ«½w¿ûÝö9ßñŽwô>ùÉOÆvÍIÜ3>“Èwû§A˜ŒÏãý0“&ãó(¬ÃbÑô÷°kJãý0“Áú;ý÷4 ©¬œºÝ.¶¶¶°¹¹ ]×ñÐCÙÛˆ . ŸÏÛûÛí¶½?l_”ýÓ`kk N=ôt]G>ŸÇîînäkJã=1ã1©|DZ„Éø<Þ3>Ãd|åu8,¦þvMi¼f|XÏÇ=DÒsVyøá‡{§OŸvm{àzïz×»z½žµ’qúôi×êÈïýÞïõÞö¶·…îöÝiqõêÕs÷xàH×”Æ{bÆgùŽcÿ4“ñy¼f2Âd|åu8C,šþvMi¼f2X§ÿžFåEIÌYeyyº®»¶ãÆo´ÿ …BÁÞ_(ÐétB÷ ûî´ Jq…BívÝn…B›››‘®)÷ÄŒÏ$òÇþi&ã­VkîŒ0Ïš|ÇqÍ,ãóâéïa×”Æûa&ƒõwúïiTØ`¶0\ºt B…àèè(p_·Û ý.õËŠ›k×® Ü˵k×°½½=T¨£\s÷ÄÄèòVy“ñy¼&>¼2®iZàgÓ*¬Ã?A“ï4ι˜ø`ýÎ{Îa÷ÝwÖ××/^` @O>ùdà¾k×®…~—„:nÄÕË—/ãòåËX]]ÅÆÆÆÐû‰rÍIÜ£ÊwZå!LÆçñ~˜øðÊø<ÊëpÆEÐßÃî)s.&>X§óžF… Ö°¼¼ŒÕÕUÜÿýv‚´èv÷û|ù|>ô»ù|~*÷pæÌ°ÃK t»]´Z­¡×4é~&½Œ*ßi•‡0?qâÄÜÝ^Ïš|³_\A“ï4ι˜ø`ýÎ{6X§ÄÖÖ–½òAP~œååeìïï»ö¯¬¬„îöÝiQ(JhommÙ+3“^s÷ÄŒÏ$òÇþi&ã÷ÜsÏÜÝ3a2ž5ùf¾X,šþ&ßi¼f2X§ÿžFåD¯×ë%}YåÂ… ØßßÇòò2Ž] Ò€“¾±±|>o'5ooo#—Ë…îöÝiAç¤UªQî'ŽýLº˜D¾ãØ? Âd|Œ0ŸGy`΋¦¿‡]S Ößé¿§Q`ƒuʈ%Óýò$ºÝ®½äݶ/Êþi0é5¥ñž˜ñ™D¾ãØ? ¦9&Y¾ç0ŸGy`΋¦¿‡íOãý0“Áú;ý÷6X†a†a†a˜TÂ9¬ Ã0 Ã0 Ã0L*aƒ•a†a†a†I%l°2 Ã0 Ã0 Ã0©„ V†a†a†a&•°ÁÊ0 Ã0 Ã0 ä6X†a†a†a˜TÂ++­V Ýn7éË`˜©Á2Îd–o&˰|3Y&ËòÍ++vÓa†É",ãL–aùf² Ë7“e²,ßl°2 Ã0 Ã0 Ã0©„ ÖB®úN§ƒýý}hšfïk·ÛØÝÝÚÊ»ÛíBÓ4hš6“°N§“éÆMR2ž”|,ã‹ëp&˰þf² ëïùæEI_À"±±±ÕÕUhš†B¡€V«…ååeäóy´Z-är9lmma}}›››±Ÿ{ss/^D¡P°å¥K—Ïç§r¿ívPËËËS¾Lò$%ãIÈ7À2¾h°g² ëo&˰þžoØÃ:cZ­>øÁb{{›››hµZ€Ë—/ãÒ¥KPej+</^Äöö6¶··ñÁ~7Þx#ö÷÷§r.q œ?~jÏ“IIÉø,å`_TX‡3Y†õ7“eXÏ/ìa1+++Èår€B¡PÅÞòäÉÐÁB¡ A¬®®®Ö¬®®ÚçÌår8yòäTÎÓn·qñâEœ9s&3…‰Î$2>ò °Œ/2IÉ7ígÎLÖßL–á9øüÂV&v¶¶¶pã7âÊ•+™ˆ›g/,ãL–aùf² Ë7“e²*ßìa3òù|ì±õqŸguu›››xûÛߎ­­­L­ð0Óeä`gÆcVò=é¹X¾™q`ýÍdyñ¬Ê7¬sF»ÝÆÖÖVàþÍÍM;ä ©ó(Š‚\.‡óçÏ£Z­f&á›™>ó ßË83³’ïIÏÅòÍŒëo&ë̃ŒgU¾Ù`3òù<î»ï¾Ðýi9 ’ .àòå˳XÌÜ1Oò °Œ3£1+ùŽë\,ßÌ(°þf²Î<ÉxÖä› Ö9#—ËÍd¥$®óœ?gÏžÅÖÖÖÌBá˜ùeÞä`g¢3+ùŽó\,ßLTX3YgÞd> endobj 2 0 obj << /Length 3 0 R /Filter /FlateDecode >> stream xœÌ½M.9’¥·Ï_q—Ò"ßq~“ -ÔÀTC£tkª-³š©®–º²¡©j@ýzÙ!¤óˆÈŠ›Å@– é›/ÃN>n4;nüï?¸o—ü?âÿ”æ¿ýן~¸^Χþëþ—üüßÈ/×ä_jÿ ÿ™jL囋ñ[ÈýZùý§\ˆMþñ§ñw9'ÿ¾ö?PôÏ?üŸ?ü«ÔþGùï¿ï¿í?þó¾ýÓÿÇ_Wãßo>$iˆ¾ÿëOý_%£'RØÿñÏ?üÕ7–á“ö iüá?ÿù£ÿöƒÿö¤¾ÿ[ŠrL5„oÿïîúö߬ûw‡ê‘nü´;v¢ã ÿí«ŸÝ2?…W×u¹5!¸ør9ç”åŠ{dù§ãM .÷Aç_Ê+çÖZuå+Æ`v’üÝï7^~ôî•ä‚o¿ÿéÛþŸœŒüÿüí¿|ûýøáßÿ¾wýgëòWm¯«&W“<ÎOÔåuZ» Gžæ †ÃkW÷&ï rIþr¯Zž•Þ?Ÿ«ØåúzÖ{ÿz°Ú^Ù?ë½>Xñå_Ïjûçgíõ ^jÌéätê®éÄ•N¨xM'ª÷ètêÕ®éÄõN½â{:qµ4~þâšÜºúŠ—¢ü­]\¯åu1ìn¦öåÁ•ø*/¹šCº\z¾;ü·õ’úEµ\UÞB±¶ìÞzC­Zü/ª¥ÊBÎ¥âŸÃµë¿¨Ž\Üë*Q,¥V?¨$R%Ý–¨¯XÛ?^¯«ÿOüã®PµDÿ…»ÂõŠ5zYCþ›ðêåí/Tx4$d™u?¦Ñ–¿ÿÍoÿá÷h¶m>ì~Éî•‹Ï>J—c[Ñ•âZx>ÈSãÇ8ªýËÿðÓOŸ·5xÁ]ïò»ŠÉ*cC”®HwÃ% <¯h¯”ù\åá‰iÔr­}»%ö’¬(ÎèÇÚÌM BßÕT¹eÆXg÷­•—XÅN_EQ“;6ÔÖÒ7Y”9»Zdáô"¹#"Kþ›Ì“xµPäö½HnXQY­ßäæ¹J3ü…"з N¦L-¯1º¹õ"¹a’–”¿ÉÚL9×ârìErC4Cº)%U^X>Ž‹œÜ/Êý’Ì+s?'÷«·q.zŸ.ïúý0'Ýýâ“"_¥í)` ¼X­ˆÉõ«RÊ^¶”½(½Ü=LRâ’ô«´ÚKä~h…Øöh…<\ç[íE25 žI-},d·¼ü^mH®DMò{ƒäïð@dÍ¡H¶ %úQS”·Ú®Ô‹Z”‡3)Ê ß¥ˆ5ˆºJèu5iDö½®$7Ä)¡7#à —Øo˜ä†hFÈÙÞP,þÔ òç5cBxY-uÎL)’IXbêÂg¹Óœ˜2[‘1l£Dn$£PÛåPR¯„ û“àTyÝÒ—¢„¾ÆU%½îIÔ¯ŠWI}F¡¨Ž¿¬)¢H°Ûh„¬Žºfe|‡'1î'è׬Œ²ˆ¤éíê.Ï,­Y±ó|´²8êo¾HÖ†ÇPÈK EÑ…2g¥¬Tî—¤]N&ìx¶AÖF“VÈlWE,œÖKä~x­ô‹daF‘¬¯9)ƒ hÐ!/„W[“2H« cY~MJiDÅ¢é³Hžç+¯i)WÉÿMchƒ,†¡p1£È-cY¾ß¯4É„MhJä~Ò ¹&õöù%˜y5y ²m”‹¼Ü[š>&LÅÖ¬ô2Ìø÷h»,޼f¥¿mØ!ò²‚02í3ÖΠøºé+Í›ÀÞøàÐú²W‘Øa˜ŒCì³Å8`…ç{91˜K. pƒ R˜,`Ë á†cU3Û&%p“ÎaÈÆ´%3û4ëëjR•ŒäÖ1öCÝXßÌ`Ô./y¬ñ^–ÀÞãmäüƒÀg™sÇ,så¦a°®Ë0ØeéÖXs–Á²:d(üÖ‚™©ÁòÆ.÷êY–«Ò5FÎ8döM8"°,é¥ël± ç¶,€c‘ÊÇd¶–éQbév8Ê^K–ÀÝdC`*ÒfØ… %†iMh£ƒ2_ï#›"&p1ÜïqK`…t‹`Y]²Ôz ÁRâä~Í?e˜å™û”ß °¾H8ÊüLy €ù˯Ãß&–ò=ý-€sc(-€…V2µÚxŠ à€î9É–—&ÙD0½K>…`·\¿…oþ[ø…åø,“SV°`QìÕ{ª‚±›o àA`yùʲe„`ÙÅûµÁk5ß„cË›¹ÊU÷Œ&ËÓªËàfë)˜ÞtL`Ùv 0ã*"0™L`y›ËÕóA–«Üz‹e2 ©°÷°–­R…õ>A&ë…eÞ®ñcËZµos’Ì7$˺ŠÒô0Ö=XVÅ‹jìˆÀL "pB³Ûœ›ÀlI‚eð#^y£i„`6 ‰Á L¾û•G–º ¶é a!a1Æ‹ LC˜g‹1ƒ#î0¶Æ ÞV«µ‚'(,€ሿ´f˜¿lÍ2Õ팬֙åo †Áj `©DFxøc8É ÇD¶Ö-7ŽUÆû X.ªqî®™¿Ò ì(ÇŒ¸­à ÞŽIÿ×ûü~!‚K~µ|/Ckg±i6ÈØ–õtÇb g/v¡t.Œ2aY’¡8m<â0Êd;(;ÜÕ#»$ûí01 F‘Löe_i£Ì¹e^k»$&*Öÿ ´f± äÅ^n¶kã2L±»ãDc\°b'sŽQ&t÷ðŠÇ(Êï&_,‘{SÀÂûe¢‘Ü{\Í2`–ɶ)Ê(»€ˆ›”šÊ(ó°O†¥AXFˆÝÂÃ7aŠ4–mmšËèAJXÁÅ-0÷–‰¸ð«ÈŒ²ŒÅv¿ð4šûuXnÉ’¹7ïÂ.&4ÛÚ4›ík8÷¦1·OAÓÙ¶RãeêW²|î÷¬À°oÐv¤4¢e Ó¦™j”y8×rˆÔ¦™Õ( 0:ðà ¬{Ï^-YZ›Ñ$^Û2 l”• ïM_DlÛ=lóˆÙfȈÚýºÙ0ƒm[½}hŸ°‡p%´²•.Þ¡5ü«ÇˆQxP¸òVÝG¢MíÖP¬Ž¨%æ!ЈAx;ºe~:®IaH4°‰›#Ë?ou¹:ÿr\¸BO~y£?Ñ bxt„ˆÝˆ8*U òºÆ+JÞ5ÿš¤*{µ.,y~Ù+(œSĨÞd1:ï—ÒY)mUzV[ДT…ê=«-hZªÂõžÕ´-UájJUô¬½:c]¹ÚÁéÔ+\Ó‰+=:PñšNTïÑéÔ«]Ó‰ë=:zÅ÷tâj?'U‘ÜoØKäcR®ä”T…k9%U¡ZIU¨Žï’ªüŒž#Ùx7Ùd¹ø3bK‹Aþò?ΉAB# pD2æ”(ì×Ý-Ý΃Sµ\ûVce¸Š¯Åú® <6vïXYlìW€Ø´qsÌÀÞtøvȦ‹=à;¾‘.í§€XrÊ.%ð1Œ‘HN{À)(’dU¤z¿¤èB¬}ļ Ù¦˜ÈLòìWj ì/FûR3ná´ÜË`J3FR†ô奾…G ûÁ·o:ɺhÒïZ1º ™0Ê .EV ŸŠ¼Y”œ«’…Ѱ:¯Ø{uy?% )!bo#îàî”™ÆëW=ar{?"<§Ô L`20§;¬–IÓu½I`)8Á‡7ˆŒXd€S÷¾Î ¸bÜ ##xR25‚¡Õ‹~ôÁíåÚý0™Án—çƒIàÇ &aC ªîöæ2„ šé/1…)hK–w&âZ¢p~U„&Fd›)L"¦0WE&…s¸¼"x7f“8¿¤ ñ޽[gˆ.G˜‰I,æbw]…õ ²-™1‰›ÄÜ×Ê‚˜¥þAF±¬„€‡;F¼M^¾Þj, )VØxÍ7–„„ Owܰq4r¿ÅÝdk] £XÞ£²ÞüˆŠé Ë(¦æ1б.1q\| 8¾¤ÓÌ(Žp•‡[SÉ(¦`)£˜†B“˜bÊLâGeS—9lŠ8©‚û–ÃúM–ÞÕƒ0‡õë¹c˜ÞÊ!Lb]Æ­6$n9·¤©bÙËÉÔ™š)ÃaaÖb£æ°“ÛË*X¬ WyKÀ¶°,­âf$AL’*±Ìgä€@̘¦ƒ˜Ô• b20Ä:Ðo¬a²“5‡i%0‡I7Ä&É’5‡u]Æ–-¹”ä'‡ec0 eÍ`¶Õ5¬c­aý 'ƒ•òÎ2¸‡`‡hÀ2¸ä4ÜL`Æ<X ù,€Õî‡øK[&°X@Ømj€eÑÈžý$ãæmm4š·­La¹ÜˆÏf Mû5¡ûp8<üf¸ˆÑæi¤mS4¥mS4¦{}îÞF´æ´m§µeBuŸÇ°ç†…­QÝg>hjbµí†µyà„k³J Øv45³ÍLjÂ§Õ Ùͨh©S‘õ0, ªAÞªûD@çîÆO»cGj©Cõ 3eæ1?—bˆ}bÕ æ§ãM .÷Aç_Ž«A¨Ãã©§_ª¥&ïX©¥u‰ÛI5ˆ¼mèäµêMj½ZŽ<¿êέVÕ›‘Ü¢¿“ÎBh‡ï¹Ò£á{T¼Â÷TïÑð}¯v…ï¹Þ£áû^ñ¾çjªAô¬ý5H¯pM'®ôètBÅk:Q½G§S¯vM'®÷ètêßÓ‰«ýœ$ÈÆGHÞwjÇÔ \É)5×rJ BµRƒP'Ô Äêsìœ|¨ñžÕ þ—Sj džìSdÏš…dê#´%ÄôÚ“2GL~öラ’¾øºöÎ.{퀑¾d8ÙÆ-í€AR9ÔÜFÑøGVäzíå÷çŠ9hÿË.K+’áØÝ[¹J÷ª×µå“®nïKkÒ¨é÷ÌðjŒ}¢ƒ3òjë{Þœ”ï¥åWC$m}rãô5ßðé÷r,!]œ»Yøïáœ•ã¥a ·Oä,7œ{YÖÍä¬ü.Üv™›åÞÈš¦åsAûÂúZ1—ñNßÇ6¸W,FÜv¹H‘X¸ó µ\•Ç¥!ž¶‚㹎Opú&7 3ÔŸ›r¸4$îY3¾zÎòŸnî`q?Ä”G|!Ãñ­É“­n¦H)xšsr6…Æ»¬\ÊÓÒð¡[ßÅ81æ¼ÄC8v¸­‹S~ä¥A”1½ŠSná˳áÕ)paÌYÙà X(¯ýàNŠW(p`ÜsRJ.„<ǯÝà²Sî´ïÅš”²¯ñ*+A;Á¯æÏ¤——†r‚SΆµ¼½Œñ!W‰ÚÎ%Ú.“.¶ùèJÒ.pÙˆ Î7<’ò×Û.mpK•P’öS¦äIÚ>pÊWS²öSnƒ’µœ‹Šv‚YØåõ)ÓVyÁ)eC)Ú.ˆ ˜c*Uo‚§!a×÷öµYg|â”§Ó‡!ÅŒ€|8DÂè¶=Ý at KrÃvíwp“)ìä:(öF(ìd’îÐaØ]E91‰Ãªï ÄH~ð±ò@Œ1Š<쿉ñ>¸âÒ…Š¡’&Ì™@,6_󌻺fŽ‚Áqƒúk á¸A®uMÚŽåßm…$ÇÈ»´’1ŽeÍ„=Æ„ã"KkI˜ÇüÖ"ËšÙ©gnËŠ(KÆ<²Ç¥žb$#¤%Ãp¯>Bò^Œ‘Þ0³¶0‘!ûÝ$""3ý‰È$g""óýˆÈß(æ7‰d~ø©…a(ËR€m40AP–¢€ åxLeó6ÑTn˜§åŽ$•ñA3,’a[•¥H¦Ð44•¥Ä!IÖXDe¼gdõŒ Œ—¢o@/!|õ|ÝW)(K^¹CIL–’ •ûm¬™,EÎÍÅMH6¨ÞœŠC˜Ê¹É{·‹h,“CFjÁ!¯a"Ã'ç­N6@Æ<ˆãÛó³4d¥Mc cgP–œÑ˜Ålûn,‘UL1u6‹³,Õ]™ÅÛc›ù`æ‡òl1ªü²±I,›¿‘~-âðвoæ“A …ëúìžìÇ×»ãÎöì,› íkÊËìÕÆ£q·~š Œ0p›‘{&0M[&0â–ym)4Ùxº ÌÖ#˜VXŠ®60DàŠ¬ešÝ„àž&»›ÿ–ÀP/B_›nn+ËEoÊñ(ˆÀzÖ9!5€Q&d¹¯ÑÚ<r€‘?ñþ `Tîøµ5ŠÅšÂ^ñFÅ2÷aÜÜCKV1ec³˜2j±Y\d‚-ÀÌb­°`«˜Ä—lS>K¶Š¹}Æ*¾ð½{EV±ê‚Í=­bR2±UÌuÝVñ’T‡çD|ÝÚƒáæÌnM¦° N}YÂÆ+Éy†Êƒ1Ü…ÈK|ÍîÏsó‡0ÜÅqÛQ¢íâ ÍXî YºBKì¡»|‚ ã‚¤Û $ø`«³±e\º€h&Ca˸à#lÆ=É2.Ö- [Æß,Æ“a\ Ð‡ZxT§¨ì ò°Ô)µ",÷²¼ß…šË(Ã5wÆ3$Ax?Ý‘sB3Ê"æóHçBlÆ«C~kmÎ(Ëq?{yý >ä?šÊ¾CÿU…Ç÷.×5õýŸ]z⃠°7k?Žûñ“êÚ‰jÚ¬Ìüt\€%/«3?o‚îruþ希:<@¿üò£¬,8[ýÜñRß¡ËÝÞô6Ÿ:6ë´"l¯Þ…‰#']k&Ÿ]½º?é+4a½Â%âáJŠxjW²ß"ª÷¨ˆ§W»D<\ïQO¯øñpµ5ajÞ6óÏ‹ÂFkBq­gOGëR 9£¨â³Ç£õz×”âŠÏžv]nÍ)®÷sÂ0ù 1ÉšR­í˜2ÌÔrJfª9¥ ãj‰Ã¸’ê0ùá(t­bcþ±:¬huØ¿ýù\® ±-T¬!NJ.ag¼T¬;cVÖ⣃d ˜¿‹rÀ:ÿŠË1^Ó¥?Fü©L}AMQ«Ã\[óü¥Š¬°+ì OÚüþ±â š£xVÍQEÁ;¦ÍðFÍEEÁàî„:¢Çj÷9Î(ÅokwšÎ@:Rfp¾Š•¹#a”J£ÖK} Çä2T|à¬Ä8xÝÍ€ˆeÅÂ.é×ýyEÅ3F¦Ú¢Š„qóº(`G}Ëðªbd4*æÖaD¹Û)®0?#oWQ¡0÷[îäÍ]*&7„;|P,ëÉC¡tƒ‰XìdbÃ…>æ<³XV´KK#K,†ØËãyÞ Q4†ØË¹%˜$CÑuá<†Ž'C}•ÊÒ 2e©»0e W¤šñ'rS}RWò+¿R´YÌ@ÎøŽ<ð(™´Ldœ)Tçòc"G|Ý~‹¤È8‰c=1²ØЉ¦'IÆÄ<Öß0Žå5ÝÖ7ŽIþÀ8v¯­R$K ÷›–hÜ׿ÊO4f,јßrLcyâä½ Ö‹²Vèjk=,Ã*šéc#v›î'Î0&-؄ƺݩô,Œâ[[Ç0æ"‚1eÎ20V‡\2ŒIoÁ0æÁ˜N_cË¿—ÜŸYL‡¥1‹ùE0Ö÷,Ö¿Ô†}‚Æîuk;Ó“ÆIH½^iÆ0–žlÉž¡14€w"c}‰aqÒ‹0‹ucXL¹ä ‹³>á„Y\»ZãžÂÌbĆ¥¶»ÛÄâŒøèÔ-YO•q½Öd âòºvS"qé¹µ¡LbˆdVòD&1TFaÚçŒbS¤QŒ¸îú’…Yœ^+o!³˜oH0Fz·•ùñ†1¤ëuJÇÆ4@Lc®Ÿh ™Ó<~‡aÌ%šÅ¤&›ö‹ù*Åb–Œñ”ÊJ3E0æöiC—,o·ùÆÒ0æÍ!Á·\÷Ì##U¦ÚM:b ìµ2\ŠMM Å TÛÚXhË]f³å@(Fò²’ÊyÇK,Æ6oÔûݨYÜú¨L1±uáe;ÞÃÆ$ì<(#÷oØâ†ÆÂß™ìä< 㞸l©‚Æ¥î…ia\ð¨'˜ƈ3m9,ø ‰@ž‚‚qAޏðH0F¤’ô€1|«m ÉÁØõì8iêãˆÆ]Q„³w35Ž!Õ‰x`#õ ñ¸+ŠöŽ–˜Œ24ä–_”ûÉ^û¼WMe£ð!,wYÍÌuFTF‰ÛÙÉË]p³%Äe#Ž!0w1ÎVy™eQkÄHŒ3ØÜ¼–OŠàŒ2ᛌll–Î(‹35¬Á3Ê”º-=íúÉT~žÛEˆîe×­¢4ŒFÙ:Í@Zè"¹>\Ô”îE;!aeu§0#NÛë4©×­CÎÏ5šÕ(Êp€6Ñeµ)%$\÷²}ê"ñº—afa¦6Š"FsçˆØ½Øb ¡!Ûô@#»÷`§^#fÛÞihÛÞijÛÞil›ÞݱêÖ§u$bi.)æÜ-$Á?Ëx9¤£J’·ë?øISK²zw¤žž‹¿"™Õ5“KØßŽK9 †ê 1<ëjÿöнCÏ?W”pŸï&ÐOß“W¨ŒÏ ñ"®‡E$pÈÀ]ÀܯGD¢îbÄ‘G8±p|áRR?Ž(ÎÓ§NV¹ÿ¦ÚÑÿ¤´$\óáÐÒjSóáØÚzSñIA‰žÁ®ÉË^ÌŽ|X½Ê=±¸Ú³k~ÞðFÍg'V¯xO,®ùìÄAð{bqÅŸS•È–ªŸ,ÖsLÇT%¦–SªSÍ)U WsHU•œP•áyÙ¿Öúsª’¨5%9¦)F–žó9§þé6 ÷»(2³Êö*-[I/ò}˜÷•É{.ÛÇ6A É}.&a¸ò}D»dG—ûÎ Ge_YXµ>F–ÂØ?‡vå¾¶<{Ãý%…¬-QQDTR—l¯£” #’t£Âˆhr™!)cyINi·³iº×š)‹=wBGÇѤ¬ôÄÏý½Ãê×ó\,Ÿ%i(R)mO:}4ìLûÉôŒ=WÁUÜ»ß!æ«>¸N) LOé´¼–”LÁ!¦´ÏYzòmøv¦<À!ú|r0© @yÓáºÊ3i‡”iw:´ƒSDÚevu7©K3˜å\?Vž¹¬7“)BʺG]fžõ=½\Š”>kùÌ)“›ÍI‹²íÙs˜ÃÛ©î±?šÊE‰®¶’ŸHY|¹9c)„ë§>ÏùÊ禹žNXå$òePí°¯WI‰v„Öu_Þš®¤Êqð9nß:}îð¡¨ÎL„/MÃ5*“u“ÖlÕI!œƒ/DMV}UÕþuõ@ÅAɉԧòÎ4c®"P p»ïÙ¢NO”0 fßZ¡üDêw×És¶"¨‰ƒ¡†¦!ÖW˜³•O‚Ç"žê‹py‹_ô5¶L’;»!)É=Yù£p)+ýð>Yù(¡H¢ÓN)PÜ,éÚJSdÀ]ý“×ðûâ{ꑟÈðç¬ï”n†× ¹ø÷üa^ËÚ‹×:õy- Ô)¢Ø=oH2œŒläçðº=šÙ`NÚI…Ú€UÊëĦv?ÐkgÆal.Væ689Ã#Gƒ` jipËÚ–U¤VƒB7`íw²†·ÉïÄôFÚïs—ߨâJ+âÈü–¡Äá SöÀwý3è±b‚£[*×;#Ü(n†÷5&νXâˆûê§K›)Žñ]d°ïƒï—H’9Ž`z„–aö^ƒ¼ŸÚÖ–Ž“QÞÍú¼D‡Ìrʸ5&ÄrNüÂ0ïÇ ]ëÜ1¦9fXv+Ã8G¡sB tAlZaCôöºsÜ“"€qŽ´ˆÐ“Üë‚pÎ9 眽†qŽ?Ô¹#šÊ8g™ã†^šC5Ä8gmãœT_Œsù2Î9 â£Cg¦úç ŠÅšâi¿SD縄A{l}ÌnY¡A{?@YeŠ{¢]­Î5hHºM)F;gIb´Ü am í2úuk• Úå±å­y2h"º}©A;rÞÅ¥j1h¿@ï•làýÊý íÅBû…ù±”w†ígúÍ}vH(GT©>ÑÐÙж7È.eÓ R"û…Ðe¸7c]„Xå4—É.oˆ>OûÄØå”ÏØå”,uÚå85Ç/[˜ÌrS¤­r:RÍXåbøµ­ée«œª2V¹i:™åú+c•ó&’¬rÓ2Ë!Ô›çø«œòý«ÜГ(N)b Å•êÅp¯á¥w6—µ­^z‹ã”°ÐrÜC—17ŠÄqR;=8¾• Œ«·ãPÉ!~½q$?ñó]j1Þò:ö×`Ü´r¨¡VÄæÔ¿XŒcä~îåÓ.ãÚð7)^º~t³˜(Žìn˜c(ŽL?c«œž/HK¸>“1ßiõ,Ñ”¦"›áýN!†gìöž‹.W¶-v5 ×2Cpdj Øß"8ÇÄ Á¥0ÄõÁ€!xÆÈÁ›ü“àR]žÇš1Â34Ü×T$„gä¹[ë“.Exü~¶†.…ž£û92Äù`3c›Ë•©Ö½å&ÛÜÞ–lsÜèºö¶Í‘q vòP›Û<#òJèelsœÛ†§Ý•‘mÎÇÛbì¹ç[‘ls>>ÉØæ|L“±Íùœ&6ÎeÚ:WÇvÓœË2¦9. Û/JP7£1ÕÍq` ö~¦œOD“Ý¥&­[j6F; µGU³ýYF*:PŽéÞÛs¥í=Ñ|··%À£°àÉIMxæxçÖf£(••1œß ¡IºgVÏÈo}¯TF=J~ú!ÈÿúSÿ—oýÙIéø×!¡Ìµ eÝýøIõíD=òhº»ú»cæ§ÔƒhýèÄ3Mn0•²\q-ÿt¼ Ôå1ìæ§º“|Á(ÜOžz£ ?.sH`èK‘ÕŒ¬s—d–7¢r¿P#㯞 5¹þÞøD]Ç52kÍn:y„7N¯YÝŸ¼uSga}ªîÉhkÖeçšm“ÿÉ{ÜÙ&PÙÁ&<‡=öðÁ°‡óî§ôµ)|nªõ ¹Ï\ó×ôÙL5jÂLµÞ„ç°Ÿ›j½Â†ýÍ©öóoX¼¹úÚß¡øô"‰±YŘþŠh¸’Œ‰lƒl¨?¨$ý¢J¢ì`ÒfÙ3þ-…:\‹lÿeœe#Ü>”ý²¾\Ñu mv×#Eç»j žð ù'|û»üOLû•hg7Eÿ…“á+Öèe796N–e%û“GÖÌCF—4ó÷¿ùí?üãï Òè>$ŸÍã Y|á„]z‘¿-µ=ëÕÇŠý·?þá\âø’Ö¹î¡ìƒÎ…úU%îéÂ>§Ž|Ý}Ë*fÖúkɵÓà€­\ß÷#³ÈÈ!¯–K¶§àXƒ¦>e‘²þ“JÒ?_ßÄüé¨×î(‹ÇC×^¤’t£h{%üµûœ{]H*xu‹Öãœyx¤Šeë‹$”Ý]%ÿ()ºÇ+QÊ›=ΙO÷§hÉ%ï÷ùí£·Þ«ÄÜÂ>8²VzYPǶ‡8…t=÷"•˜»©A #1÷…Á‚»þè¶wEjüp´ü%sÕÈÊÝ}ЍL]•TRn\¥›ŸÔ¡í(KR&³¶!'·©%«#Û{‘Ò¬RrKÛõ’Ÿö‘í(+¸°À/à‹ÊÈm/+*#7ÊTKŠ:±Eê%ä«JÈ2õLª:³E˜gé·¬*!·-kûÌví•ã›JÇéÞs‹2_”8hoõ:\®;’œŒ^/Úk4øv#õ«ö”ˆ}­¹Õx`~·=Gƒ~2 €ßs”/S™¸QTsÏæ‰"œ)áp±GÿIåßî}݃.ûáí32• ›9¾8»Z3C‚ʾm¯ªÝ_tOM¢8þX= cB‚oìß¼Žt«–¾òÊÚ‹‡)ì/â)c¸¼n~¹‡]Öd;šŸ ä.Ø\ë˜x,Ej1ƒÈAOkæq|b8hú0…½ša ad/ÛWiÓ›Šaì‚ù–d?Ñ˦6[¿zNë7“aLÖ/iãWWeHL–‘A±Þáã—V›µ~umÖ VÏÊ 8= L{&ƒàüD¯ÞjL³wOÄ“BMÞ(Š5Ç yãÅL$ò¶FF±okàB_¥mZMÞ!¹"à6âñ¶{ˆ·N) Xñ–K·¦HÓ¶ëf÷‚$Ür ·­¼gîr]„[ Æm{ß÷Ð>ð=ô`c¶™ˆ²1B”5µnù–„[ˆAÛö¤l{Úµ¹Etm eÂkWº­ÉAt5E®\¤á/cÃj¸šË4[¹H³µÑkšk.ÒŒåñ`ÈÚ2MÙö.eùq3f[&«0kË4gMq–[Bœ5E³æŽÄ[[¦yK3¹ÛèuÍþ´8®ú/KyÊCð¯ îéŠSÞªýH´¨M•ÄîÛ‰zbŒþ3?W†¤÷É7÷ØòOÇ›@]Ãn~:.N¡.ßOžúqJ§6"Èõ)ÁÈwˆS‚¼ñ6’w2ÞýzÄ){Ín:y„Ù+6Á¨þäžØ£¿™ÎÂÈ*¨æ/P ´‡8…šðŠ6Å)\óÑa·Šªùü°ë)}ídÎMµ^!÷™kþš>›©FMø‚©Ö›ðösS­WøÁ°Ÿ8E¶'^6j]?LœÂ•§p%§Ä)\Ë)q ×ò]┟Qà›©¾ÊI É?V8­þøËÿ8§þÀž_©?v¸FŒ½K;À=E"|;ÊCÄx©cÛ9L:µ}¨"¼ÛÅXõ&»ícTŽÓèÉ^úOäøÖ~Žèµã»jŸZ êˆvvSG$¿}Œäæpsl'#yibT'´³'6Fö|ëEr}g}U"Ï7‘ç›Ü·§Èk/£.ËJÍÂŽÀ˜ÕñìÝE«|OO¬ÜÊc‹Q‚èIQÈ®ÝݱLøöåÅJ.p-͈ÕAÔk'V#Qî¬ØŒ\u¸‘ œ4±ø¾,]ä×ê‚t‘\« ÒEp*rÚ®… ɈêXrêTv)ÃO^ƹÆíäþcOwd—\…Û'{¯ä¡$È~V)ì“ØmӂѨg•¢:‰eêŽÑ¸ÀÕ˜GÖ৤Ž_· Hä§Hêôu{Yý}.™O)@À±½ à@Qn°¿Îàò.€-C±£¸ƒ˜äÌa’†0·v4æÌa’0‡Ç’%ü:¯«%úŽj5uYÆÇÔ…àcã?½‡.2zU=A—dÌÜžkŸY‹øïYB­s LZÖ32i¹þò”y0iÍ­ªÑy¨ÙRÌCÏ–ftª¶fdê!7–yÐz$Ò"¡Í†ÖeåËˤ¥viY‰Â¨e£¶Ë4µÔ#F-É-µ\ŒîCuH“vÔ¬Úc ñÕi¾ŽE#òР$¾Rƒ’Ñxè7ó•"ä Æƒö*¶€uI/>櫎32^½ù2^½~q;WGÓŒ™«#ÆÊ¥À½1wù2mîRà̘»Ç2ö.½8Œ¹û´r«þk²rß0n+YmlÝš22oõœ1Ö-ïOغmï[·ôdÙ¸¥h¨1nI“nŒÛF¤Æm{߸­TDÆ-)£ŒqËelÜ6â*·Üp6nqÐ2WÉŒyÛÈ(&ó¶½kÞ6 $6o¹lÞRûÛèÁ†n}¸í#êêZÈÀ}îmOs¶=ÍØª'¨á-—1pë»Àe¨ÞnÎ~†¯ŸWr_Í QÃWü‡ZÄצßÌצ5…Ì×F+‡øj®"YGÕu_ïð‰¯š¯R¢èBxmìÎ ¼6æñÕ\G åê4hY¾ÁÄå±"àšÊ¸\×ÔFÀíjm+ôî"Òr-Úq'â+?‰r+:èî•¥d·’Ä£¼kÒŽŠ «üׄUSDÂ]DPÅŠÐÖ*é:ž®î#ÁÔ‘¢ƒê'˜r±tÔO5•Ké™0KÍeš¥\?1Õ\Epµe¤ã0e$äà2¢,7…(KK‡)kî˜ ÿ´#»Æ,uJ)ð¯8EéI!Ç[µŸˆ¬Ì~ü¤úv¤ž:ô ÝÃ::f~:®¢(é!ä0?ouy »ù鸃º|?ùô‹…8G\ÞšROCç¨CÞ)ù˜R+=ÉÆ¯Fȱ×ì¦Ã‘GX½bÃÁ5«ú“÷¤8 #]çšÏG×Ñ]§&|At½7á9ìç¢ë½Â†ý „zJ‰£WÈ}æš¿¦ÏfªQ¾`ªõ&<‡ýÜTë~0ìß'ä8N´†¾k;&äàJ 9¸’SB®å”ƒk9!äˆØCVŸG:Ì…²S2Ž?ÿË)G†‹cT«=-UOIH9x¯ã\HV·RF0uïesÖ¾¯5gðî‰Jr¦¨bï2ï®à ‰*r¡h"é4r©ûüd„LÕ U 'Ãr¥¸¢ŽØÊ²Þ©bQ¤[Ò(°è•"·´O-]Émõ—ô®Ž9%ûGêûa”‹‹t,ý`‰9)ù‹ØâLdQM½âLhQ9µ ÜkZrœªxRqhÇaÿcÎÏîG-ž½Ûø ÞŽ5Ù]ùµµ#¡rk“®Drk›2vk+O¿Ì íÞÖ’Ƚ­£Oò×Ê»­¿(+‰¼ÜE·>“·›>Ó-™ÜÞ}*™ÜÞ\VÈí­US¥Pœ‘‹ÈíM=«ÞJ”N©8 •ø´wœªF&pÒ2:&pLðF­U`‡x}»Åä ZÏÁä „""o ‚2xwÉ!nÀKŸm3y½Ž|2x½Î.DöZúÂü•"Õ1¯×/Ưz.3~=I©˜¿R¦¯#þz-kaþzÏ—uþzÊÂö:úÂüõð×kEŠÁ/¡’é« _Ç€$ø:Ši}íe¤ì¨º!„cÇì$;b'áØÑTd;Š{0ŽÅ†ÙS‘qìH!ÊŒa¶\Ù&Ë•má ë`[˜­S¶…=ÛÉd ó¶ÀÃD\²†u ¦i ?Lö°ÕÒ³&°^±Ö&3ךÀ{ÉZ X[¹&™’F1˜nh,a2mE¬‹ŒÐCÝ |=í`º›Áo˜¿üÂ`û·’iLêÍ2¶iƒg `˜ÞNù}Ù‡±¹ýlÓF‚ `z©UoõT… l§Szq£×£LÀl±iàBª¡ZÅ[Á•&‘Æmtå=ÜFÊ^ªqïìw“š»ñ鄈š·‘’ºn#)R »‘Õ]„ÝH뀰ibv#©4~#ëÜ¿‘¿k!þÆ.$îFNDÜœˆ¸)}a7Rþ*¢n¤l;ƒºi3WÑ7R®!¢¯V-úFúö„à‹¢÷àéC‚o¼SúÌݲ'EHyÇý9&Ñ7ÒÇDßHß—}#ŽAøEÙ{þˆÈßEˆãõ0|m5Ä‘>ÈÐ F‰zXĶ~ â^¦`«8é›â0ŠÔ i £H·ŠÂ¦ñšÂñòö:þzOˆOËB*´ui»~Í`hÿçÄ¢ü¤0äÍúO„jfG~Ò½;QQÃ|`iˆùé¸.C&‹•†˜ŸÎ7AwyŒ»ùé¸4„º|7úiHϤòZøÜ¡0ß! É8Ïù çœ}ê°›ÓÒ½j7Žr­ |xÕꥯ‡ô 9tÌ5ŸØ×.b¥ˆ=5á "ö½ Ïa?±ï~0ì_ Q“Z^å_¡5r¯¹ê/êµ™mÔ†¯8ð¨·á9òO<ê5~0òß§‘ŸpJjM©ÖvL"bj9¤1µœ‰˜jN©DL5'd"òÿ£àd³XÂÏÉDªÎ÷ño>—¢Üâm;°ñ¢Ó^Ôv©Æ¨…"zoVcÑB½[®éÒBŠÖW™?Ê'Þ÷0©h_¸v.×|)_8>Qq.òvŠS4 N9Åu4­–Ë8Åw³q$òvDjO¶lè´oœ¤µ^Ú7N!¿Z£vŽsp òöŽë]jm—ö’÷_";Çõö„“Ë;N.ð¦CÒÃ5 3UyÅ)Ø®¢½â¤Áhø\¹·Î^m§8ù©dÞ¿’ù˜­á´ã5MQÔßAR¯yu†ðø°¯…Kþ¨?Fi!êÏI©ÐpºñvŠWÝ•xqzk}YŒJbŠŠöŠëp`K—öŠóe)j·8yÑÎ6ÞBú`·õÛA^úOQ;Æ)²ØrÑrítk8ÑX'ŸQ#X¢rë`»TÁ®u³q–ñvk·nÃIÆÛ?NR(ù¿”ášf^»´ƒ\G𛬠åמ¾†,É{RRmã½O>ÃS ^6牼YO_&o"W-£7iñ£7V*ÒäºïLàx1g‚ƒŽJ3Ý´ÃŒ»Z¸ÀæœT `>”ìõºdþzê™æ¯Ïú h±'O0ƒ˜4#Ìa¯„y̲æ±×®DƱgê=Js™%#Lä›¶šÄ$€d³xƒ‰L*M&²£Ùé8™ï¨ìˆþÄã®Ãd;½4ÃÎ Zc˜ÕŒa§…rŒcÒe0ƒpì˜Ô ÇNkvÇ|ј¯";šåLc—vïC˜•LaÒ' ³.á 0„A\·-û°€„@õ:`¶ Ù¦5Â$öôÖg{Ò,ŠYåÌ,ö:ù³˜×=ÃØëÏ’ÆÌCcHSúCc÷¾9lʈÇN¿MÇDAƒc¯—ãXfp¬_®†Æz´4Ö &+£Ø€Ù0ø]«ØS+†±×y˜Å^§qbóArÌb¾#±˜§ Áx¼BÂæC4f%"ã˜sœ1ŽùµD4ödÅ“¤ƒyìõþ×àXGÙÇí]ëØ_dk{Þ_ùi1ŽiëEXæ‡ÅX櫈Êõi{T–» cëõˆË‘r|–#k]ˆË¬1 ,G:•¨)ù A]ò5l(³h˜l"ëeÙ&(G:˜‡ Ì1~b²)ÒHŽœæ’lz­‰y¥‰Ì2"r¤<“d#l "í!9^lW-'IÅÜ6B1+<’m£4’yL ÉfL ɦÉ‘R}’#ëJD6 ‰ß÷W˜j2›j0›«4—Íph,›~i,Û¢H&vÑb’dilZ­hlHÓØ>_cÓ4MãÇeE‹H⻾ 3FšÇFDD@æ®èÝéÓ2w¥¥ãèÓkèH¼Ÿ1Ûþ'…$o·àLL'-)Éîà‘šÙ?”xÍÊíoÇ•ÂÚ!šð©ÕÕþí ¡{}¾ùí¸ „{=Á¿}¤¤È ìQ"dÍ:«()H¡äÄ,­ á©_¢D/ߊ#OqÒáüò¥>¥~”HœÇÉœ¬’ãͦî¯õ§‡°„ñ%±þ4¥%¦î³ƒ>ü¯P—èéÏåÌ)_G']¯Òô›ëþ¢~ÛIGøŠI×ñÆàœt3Y»ƒÿ}“œ´ÆQ ILL-‡$&¦–SSÍ)‰‰©æ„ĤxÈä«ìtkýY‰ LþrL`"$-=lN]öNŸÂ»KfN–ýY 8öÞ×d—Ð6J Ë{ɶÝ%ûÀÜwtnøa·‹AÊbO+4É&$e$4_/óµ¥ü„ó ¤­õþ¢QQI IZ¢?;pW#mIæ e÷‡$°cÍÓá RVzØñ¢ï“ŒO%/¹#Y‰öìI™ÜK®n„¹úoNëIîŸHPrÿVzž×,m5Ÿ‹1½î¡ sìœ'% E¤¤$ô¼ òÇ1ûfóžHaìI_Ct#9ûöHIYwœóǩҕ«§}í3O2¹Ûšx÷]"Å/½r°9—(~IB)Œ/·&.¼Vn),=ûë=ót¸ÁI8§¶naÖALíö—"¹åž‰ŽÆ°P8“bRù,.,ýtß{&^tWxDöL¼xœ+9ÑÍ]ká“ hààY“’>I“²Hßaêak…?ÄÔJËú¿c¶’èHÊdÕ®Ùú¸¤&ú3My3_œ‚›Ê°›³–TCRVú1¿cÒšë¼³IåO‰MÂòÚÙ•> œ© ãDYœxñ1Œ“öÑG:õÊÐ8ÒÄ'*‡ÊEšÎ”»ÊÀ9Їò†Î”ÅÄÀ9xz£œŸJÏtæ0¯Á´§n0¦=#_ãÚ—'®GÃ×,E1¼ö‘GܦÓ* ¶=½ßÛÞà°í=uh`›#ÝÛvìˆÛžN0÷L°d(z€7¾øÝx8³¡èá$€ëOÛ-À+]VŒE4ó›gã»D¿ UX$…¸_8g‰^©Lo¬0¾9Ɉá·ÓGÌ|;-/4ø&ÕŠ¡·1²߯"a~SÎ ÃoÎÒ¶ÎÌÚè LÅ ¼mñò“àù‚3O‰à1<ÁHÄiÈøfnF›ävÜžÎè3äöÁ˜ÎV¥¢£Õ„n–Ïv{c”0»-\F·1u˜Ý]Ȧ6-jcrs™Þ<›Þí”sSØoXà\“üÒ†w5&ûҋ„ oî-à\Æüfd2¾«a»á7=뿚ßd~›w¼ÑëÎcÏgc˜ùÝ>²¿ù¡1ÀÍû’Άñ»¾o~»ú¶Ùfl×°MÐ0Ô®éDmšc†ÚæÂ[eºWÄA‹ñ~¨Ó÷,µYÂÔæTLmÎHÀôFÞ5,o““€éÝO"Ñ…U‹YÝTãî݉Jj6‘‰Þä²ôFỆwã5KìnÙÝ× ±»5¶e4¼ïÖØ’%z·7¨ÝêûÔn¼‰Ú¶"Âv«Üzâvko8NLU„ïfÙ®ùm/Ôü¦sR ¿›®Äo[¦ñ͇$1¾1£iP4¿j€Ói5†ßÍÒðƯ68Ÿ‡dþ(ÔoõInÛ~"wc{^“Ûir›F0ÂÛèæ³l »m!Á››Áì6ŒáÝÊÓäæß>/z)é[.H…¢ïÿúSÿWNT)ÿ:$xy£ö#¦»?©¾¨GVIWsøêgÇÌOy6}¦ ý›Ì9ƒî±åŸŽ7º<†êšÞ£2êòýäé§·šð³Q+‡X1B ÏzǯÑ‹ü_þQïüù`Å1½žÕöÏOÛk ÏM§^ášN\éÑéÔ+žÓ‰ë=9: Öt¢zÏN§^ñ=¸ZšN?ÿµš«¯xFüòRKõå©Jø~I WryC`ë…¬”C­Õ"]Ãâªbîå ÇçjA®Ô«ˆ],”j ¿¬ä8Oå-±Èª%R-ÿî7îü9²üý?©:¼^WÿŸ/ß~T˜Ýýî’ík¬Qzˆ géŸ'_àŸ·-‘É“¾ý˜Fcþþ7¿ý‡üÝ£A6ø»ArEæâ³ Í û!±t°IyTëTB–ÿúÇ?œKÈâŠ:>ë»&iO8ŸÞU•5g™¶ReÀcßpÕ‘6÷ÃéÎNõûÐØ7\Uî9ý28qõ“Ðù±¥j®;ŒÄÒ’—Bœ]ìÒFÎÜ~¤ÄÇW*±ïQ¦’æ¦þÍ}-yØÖþRç'£,c ºš{™J››ä‘»,jî:^¯ò£(Jó"z)E`+¼H©±MVœl[e#.¢ßR¤JSà}@ÙH ;^€ˆ98X–W/C°M‰²F™¼­Jq£)~¡œd7׿dô½HeÐÅa¸Õ‡®>Æ>¨3”QÖj ³™AåÐEY–ÉâGæsÌ:|ütåâFY’gêÇhF×}E²>R/ >·«‡i<z^#fŠF*݆dŒã["”É-÷„E´8@{™J°kºÐ?Ož§~÷Q‘ñéíB™Ê°Û»×£Å}ô Ó[dÛ‰Åóøo;,A%Ù•Ùø*—,:L”Õî+º§,ß3ަ;y´©ô‰pL^C̆V^Ú¥…·-5å{yd‹½^…ô×Ä–é,1įxúžÜò"½rË€¹àpTÜô"nËÓðB¯9Õ™ÛRy’wôh s[.ÕâÍ_Ím[¦¹ íÌüÆÍrÕùk­râ¶¼¬®„”®ãžšÛx_{y…ÜÔ#nãSšÎ¼ðÀ¶©°à¿sv1¶ñ2kYªoÆvPTw?ÃmÄ„n±¯:wÀâiøÒ-¸ñ†ªÉØ>Á›Ú\É7¸MãÜÜ·\wµ\ïÙeÀÍo~7ß“Á-× ½ºa°-W5±3î¹ÅØÖW´%ÁÐæ6´ù¹0´Åp&¹Éz m Ð{½Álº¥a6âÀò„‡÷™­ºÆÄF]Ajkã%ÀÄ–Á’÷QsÕ»IgdRy» Ì£˜IãÝÁÀn;âð6ÔÄ%ù¾j ¯å2ô亙L¼–²œkëÞðš&Éà5ÒI9 !»™xn¼q,³áG %Í1[nÒ¼¼øÓ“Ù¥+¹Ãmp2³KÏÂ&¼¸y®™-Õ%ÙìÝ(afKÙš£–ٲĪLùû!0³¥LÀ;žˆavéaæì§=­™]ÇCÏè93»x±èúûÊ=˜ëdþ–ú†­ƒ&„i·¥ª‘mj#dä‘Éwㄘ²+.[˜]ª®Òía¯³ vÕ~Z.Ìl[¦™-e2QÖ«…˜mzN̶ešÙ¦ƒÙø±ì—1¸ÒŒh0³m™f6:Ö'^z2Û 1» h½v€LíÒ?þY¯v¢v6]ÈÇô"n›GÜ6mÑÜFÑ•rº7•Äm4³¬W;a[ç°Ü¦ËÛö2…m(-J|ÛÔ.=AIJРܸîªË²'póäbrÛ2MnK&7%£›Ÿ£Û–itó|JêòIMFwîÙ:î®ZtCÿáe¶ß&µ&wË‚Yq¹Ï"F·”µkÙ£Œn) qDŒnùRÇ2~ [Êbod&·åºÞÈLns™7æ½ØáÓ‹@àn²•Wî Yâ6\ÅD¹wéÄm”É/é¶*‰Û8hgxÖ Ú¨)õ1~BÛÜŽ Ý°AvŽmC[ʤïµÝöA[ÊRªn2‘ -e²Òc¹žÌÆ-ë'Å2—µkºÃ˜Ù¨N^‹ËšÙ(“É=7BƒÙ¦}Äl)“i\拃˜mË4³Í=‰Ù¦ÄlsObvO9’ýä+1ÛÜ“˜ëds1&ÛÔ¦‰m*#b£¬É O]#[WÆÀÆÒºÖΉݔ”Æ›ÂÄæ†0±1E¼¬Ðö±ùé0±m™&6Æ« wÞ"6%Û´“ˆm¯ÓÄ6eÑÛ[}ZG!Óü îxþ5"×(=©£y«ö#A°6»o'ê‰yÈEºÂktÌüt\Ä’BÜÇìÜcË?ouy ;ÿt^GC]¾Ÿ<ýô]:šp!áŸìo]nŸ·|‡Ž&È ï)yE =Ù¯FG³Wìfј½"ÃA½ŽêOîÉBúËé,Š”ð*=+|hJGÃõ>4­£¡z ÚÖÑpµu4zÚ^›³ç¦S¯pM'®ôètêÏéÄõžœNk:Q½g§S¯øžN\íçt4²ÿð2<]šLGÕœÒÑP-Çt4\Ë) ×ò]:šŸª¤Ìƒ·E6œñ3B•>(TŸ$,:rV÷ïƒTı:#)øéZ[鯀LÏÓ»ö´p´ênA¾™Z™y—>¥ŸÈ¼v³=yêò¨Egô);‚3£•<…ô"ÑkÇ >_½ÖÖ-ª¯YQt•µ‹ŒAîl¤$R›íGBão·R„_cGŽÊK6á£kQî ùFLa–°2ŧîÀJŒ¤LɯËËC¾[‘Œ2eéI”"Ë<ÜΚˆÃ§wÈ(a[Êð•Ŭ¾ 3J‹˜Õ Ïýž²Ýžã‹Ä;fÄÍ/F–²DO(3²%ž‰eÊR”¼$V#KYS eF–â}™.ùX,åòuƹc3²yõöÄfd)òûôÒÆfd)ª,]F–’ ’.#K¡²÷e)ɱ,¥ä0¿ÉYŠ— ÍÈ.—œ:ëÙ(O’Wg=÷²¹ºµ;J•²e"X&+˜hä%ˆ³+Y N=‘)4\’Xþóë¥Çeï«RRTÇ>ÛA‰V•²Õ%d¨ 'Né’WôÐ7¥¤N~NãÜ–ÐKɨRª¼_nÅZJêìg£‚é¶wë”*…„ƒñØ= ­¾ {@ç÷„é06¤–áºnšXLçzåkŒ•µ¹tMÚ…'LkHfŒÖÒZʼL˜[¦G´fÓJM1S¦5þðþxК%0Ìk–J±¥(øTdbã²¶‚'Llô@hSJ+0¶¥L¦Ì c0¶!«‘‚6ÄFŒm¼1›»—?SÛ¼L‰Ú¨._s}0µQ] Î Á S×ÝŽÜÙ,,adãiʬº#îŒlV¾0²MëÙ¬)ed›)BÈF[ZÊ)>‰Íâ ClR²0±ùy±y3±YæÂÈæ0²Í= ÙÜ;"6? &¶-SÄæ;#JÑcBÀæGÎÀ¶eØfPضÌÈRt[Ø$ð鼿'vP•blj±»díµž˜”‰ É~G3±K“I*í¿­"6ö¹Ê|"h|V›o‹œ ¢p²¾…lÖ«0²¥lÝxÝÉmj—ˆ×Âñ`Æ'^K;d„Ób¹æµ”ë„[ʤíÖ:2°¥¬ çç="Ø(’~O¢°¥lJ¶˜Öæ~Dk\$¯·Id¢u÷ÒÞGJXZyÊêšÆ2áZ®ƒ5vÏrƵyn„k[Fr/ïêmŸÜÄ6#b›Ž±MLjئDl󰉨(k=ëD{[ÊÜ ú3±KÄg&ã=ᅥ0¯¹ãÄk\æÅ¸í>âµ”5Áà[6rÜ!Ö®¥¬Åµûe\ã!¹07¬Ìë‚|Õy~Á¼–å&Ës¾4‰×¥ê­ ÕÉ„º÷„ lD𣼯Se`›¦°¥)B«õÒ$`—¢÷$ÄëåŸcTubKNăÕZž2Çö  …Xf–@ÿÄÀ:Ëà‰Þ" †5Ò—(l¬‘ªC-{‚uOK1utLkäS ‡ÚiÝÊ+,¥ÃZŠÜ–31¯[lÓUóZŠ.ù›{Gȼ6·$^£,. ”pÝdº–m¸®Í-5®!éqÛÄ#\Ã‰ï” MZ’û0±»ó››Dl4Óms“ˆÍò"&¶i ÷ŒÓP&%J†ö¶«˜ÖRËÞü Z›Á Zã^¥Îo(˜Öh\ܶ0ÑÚ4œhmA´6÷$Zã:·4Â5×ÇÀ¦ñ`^C¢5ïaxÍ­d^£,. ?›U_ lsO¶”ÉýíئŒ€mFE››šÍF¼6= ^›êˆ×fÄئDmnJööNŸV¢ˆ‰v‡ÎJZükÄ~QzR‰òVí'ÂH³?©¾©§ÁEOó9:f~:.)é¡D1?ouy ;ÿt^‰B]¾Ÿ|úÅJ¨„áCÛÿuR‰"¯ÙYùb"ÿŠ”({Ån6y€Õ+2\±ª?yO‰³(ÚÒ®ô¨t W<¥\ïIé@Ÿ&K:@õž•ôŠoéW{P‰¢§í—(Qz…k:q¥G§S¯xN'®÷ätê4XÓ‰ê=;zÅ÷tâj?§D 81µ†¾e;¦DáJN)Q¨–cJ®å”…k9¡D‰Ø-Ê ÅþŎJœò¨•(þ—SJ” Ç<Ž7;sWœ4=¹ÍéÃìÓα‹-Š—]ØýHöÚ›Ü$ÌψsО˜ˆ ™+â—CÚ§EË6.u»és X'ü1ÜŸ¹ä¸ã IYãJd աβی²º3ìöëê 5çD±N¤÷]1çœÒ>0©äYÌt‘ñ/îð‘Xp2”·«>g v"Iïòçœvz]\'ÛFw{Gr¦hgx!xzo3¾ Uñ#EÌÅ;w|O^GûÔhÚäJÊB“« vªpb®uçØ5XçF­*Êø8ŠÂG;,˜ÛP¨ WÏ5?¸9æ„E™TØnõJ¹H¡Rå?Rº3‹ø9Ö„õp®/:Š#…Jy´)£ˆ*” §ô£°æ|EŽá˜ç-ž*E;V üs¾J‘«nzÏ‹'}ŠÌW—ýí@(ps¬ùŠó°ãZ%@Þ5©nxqJ …ŠE•Hú*!uŠ´Ñ¥2(‘Ô)ùÕdÝ ‡DI$N!-’ü¹§ÀÀ¸c¢X'—e§À­Õ½Z}3‰S²,õ4…²î´8…r •Bâ¾®P¬3ã?ò-Á+…Ä)ÒN ‡Z‡úª¤2ÝǧÄ)ÄlxuóüDõÁì¢õ3†ÙÒµp™ \ý0ÌFŠ07Ó:fË0ï/Û™ÙH‚'Oêöª2³ñÙÒ™fÃãÖkÇ2Ûß_V`Ë4ñ~†¨À–¾ÏÌ ØPÖ-Å¥6ß“cÎ…‘ó:v‚©Ø+|g¢HçÆ1Àæ÷;lZbH¦òD”!62ú¬X.Û”±¥¾\¤wÙH*´B7²ñâïÈf}#[ÊjYQF¶”%—FO,²q:ä=¨ÙR…¯B„l4ÅÅEB6ä˜ïÇFÈ–¢PWˆ‘ …V SïÉÈÆu‚ó[@ÀÈžâ\†µ©‰pÍZ06g÷a`c1וV€‰ëÄй£–Dl[¤‰¤«3‡es‘2¯¥¤º68æ5ÊÒJøÀ¼&uãš5pŒkÜß[nu\ÓJS °Ûž/ØÈe¿S=1°±\·š]“ZÌëtN#æu‘-[é ™×¹"náѺ4©+άYLkœuQä¥RÞ µ”]2™')ØŸ+o€°K÷O[mÊØ(Ãt³’újš:3°¡ti}K ØÐ%È+îIЍàõ67lVÃ0°Q&oÌ;ÍÛ^§ ÑŽ<¤ax1¯!ãh~ÚÌk[6ô)^ÞÛïð¤•$y-eø«ÛÌg^Cgâ×KƒymËÞ×§0°M›…Jl*æ5®¡JujÁ×(ÛFC›UE msO‚6«°Ú,–ah+9›7N¶Š÷F‹‰Í3„™ÍÃEÈf­#Û–‘<…²(1³I4<ò×u™7%*ì‰b˜Ô;‘•a¶ìV_Ý>ÛglÀÖ_‚¼›Ù²ž´X‰˜û—in;ˆÙRÞíS!DÌF›Û•æk@A%r·i´³ëß…,††vG5oø*hg¨Êš”íÜóCÔ™à• ²°ßÄíìàTX‚¶l^qç<#h£ÌÏU ‘ q’¹¤éøPÈΗ<‚kf=!b£(vËüvn(bç ‰mÛÄFYÞÛy"6ʼzqjd#OÙ›^Bv/ÛÍìž»ggÐ%dçžg}tDÈÎ>lY)c Ù(K[ÐFÈFYØyZ Ù(sû“B¶Øù¯º· „l”µýŠF6Š’ äýæ#f£,î/MÚ(ó²ý™o m”][nKÐΗ¼‹›*‚6ÊêVÜ´Q& ™I÷Ú¶LCeñª3ß‘æ6ŠdœgN#â6ʼ»ç¨á6Êœ»n¿aE—s~NÍm(ìš“žß#­¹²â–ÉIÜ~”)n£L†vîy{¤? ‡èîÓ*• à8wãºft¶ÿsD†Q~R§òfý'¢L³#?éÞ¨¨a…±RÅüt\&Ò`i°RÅüt¾ ºËcÜù§óJêòÝúé»”* x pÔOôJ•ì2ĶÒ¡昣ÓJ•½f7Žœs­é{xÍꥯЪô —¸€+=*.èOq×{R\Pïs#†¸€ê=+.èßâ®ö VEM܆=Ï‹UFkBq­g³ê5ÏÅ=ϪaM)ªøðV½æ{Nq½Ÿ¬ÈO8Á¶¦$;ƒcŠSË)É WsL³bª9%Z1ÕœP­Èÿ CßÉ6°„ŸQ­Ô­Yù·?ŸËžR¡Ç؛݂T»¥Ç3žñRîôœ_Ý¡Ö7ø5Fþ z3.ûu-YÁ‘Ñ+fTӥß8a…òkŠÊŽ“ƒÆ>Ýõ²¢%+ˆ®çÇþYfœ â”<ÓYVœ^½ãI²}¾ÖÇu5þÄ~öÎ|RË¥ãŸ:V»ÏL…”TØH¶‡:üIá“Z/þ¼ð±ÕüV©Ö¨ÃŸNo¥•®8¹Zï¬ÎʨmŸmrß×uNMgºöŠc«·€Nhúøk;✠(S‡B㺫\3•{»Š¬ˆµ\VšÒæ.-X)/™;áNuØv§Ã‹‡LJיּò )œŸt6iÅJÑQ†t[±‚ïºVˆ¼ù¢+|]¸X±rÅ6Ýé-D-YÑúŒ•“V¬¨¤:-^Z±’u§Å¨+²¨jš'£4œ[½+ß<…{–·tiÅJÖßV·Y±’<¶i8·Z+V”¤áˆ­YªNÁAËQ«VH»ÑrѪÒƒ4©Üˆ8Z‰J¶BŠ©EËVè|§†#«÷Œ•ëf¢m”E-[¡<ò£ƒ’® µKËV(CPëùyU *+Z¶BgM +i©ÛÒÓÒ­n+oœå6‡ç ¸… ×=ß,¸“ß Íà–×2¸áß©öÜ1èoÍÜðîLÜ nÈ}›á(n8²«›àct㘣5 »‘áyUfÐ-ÿQWRƒnR®tgùMbȵ•6ž/®„¼>¦frcÎæêæË€È 2…#erCðr­X'“[ÞtéZa3&7Þ‚8ŽqÔÇäæCœ˜ÜµD7Åu7¹QQ\q=&7 P˜ÜhDŒÓGÃä6×¹Qv§©°àf “›åLnj¹YÁäFüiKx™Ü,arsB&7Êjžñ&7l†ºNV`rC3’Ö)Lnäº[ö 7ç$"r³iÃäæD@Ln>ü‰Éͦ!7–ž‡§1¹m™&·©ÈM‰‡¸ùø¯ƒ–‡Í}¹~Ø_~°»Šu–V–fw•ÆÈ»µàÌn¢äfF7NŸØKÑ]P›F7>çÞ¯dB·©—<£[&‡ÊËÇètûÓ rK‘:ÉÉmË4º‘F¢Å[…ÄäÆeÛÎ䆶sçbctË-ÕûœÐmnIèæ–¹©ˆÁÍ'21¸—‡ƒ™þïC™ÙÜ@f6N/YguÞÈæÃ¢ÙXæû„EF¶½N#é|Â574ŒìRtBAf6†bŽ‹e6Ú²ÏÇdf£¾m˜G™Ýb/1Ût˜Ýãqë4Tf6Of¶ÎdÄÄ6-!b—ªS`2±éŽÄk.Q´6ãO´FUʶ%ZóÊeZ›1&Z£kû¬T¦5æãN<É´`v i-eHv —o? ´//ÁAõ ã»)4¸6RµŒ¹Ìß·}$†Tej^wñGUþÅk<ü~ù¯¡Õ;ÎÇ¡мÆ§D÷¦ºŠåѰî²½¦-­h „¼¦Þr‘‰Á—Ý5iPã’¸Ô%P£ÌïÉL îª MãK Wèrñ‚@mDjì«ÂNXD¨6ª BuW+ìﴈ׸.ï£`‰×]qùe=i^ãžbNû¹­ïÀ6R ¶m vo`¼Sf®»˜bç=#\÷;ÊÞ`úb4®{óv‚eÂ5צaÝå em§4¬Q´f˜5Ë3ˆÕh£ÛÇ$«ícѬ¶ešÖvL4­Š„hÝǤÄùÅñÚÈ:4±Qtm!.eyçÂ"b£ÌWK°Ø(’Mò<ËŠ€Ýs§É"`Ûžk`m »÷N.¼wó#`„æÅ6Ý‚Ÿ–­ ö ÷7t+ÝVèQâþ'…+o·àL¼)-éÊîà‘šÒ?`ºÍΙߎ+GÆC¤!t««üÛ4B÷ú|þí¼€…{=A¿}—„¥È„ #ÓØQK^…,°éÎ_‹‚E/Þ Š#Ïp²áüâ¥>¥~>LœÇ¬r©Lµ‡eI YLÍguIKY¸æÓƒ´Å,¦â“j=…eç"½n‘ŸœX½Ê=±¸Ú³kn´ÞªùèÄŽŽ5±¨æÃkÄqî‰ÅNÒ’3"ä².WLÇ$-¦–S’®æ˜¤ÅTsJÒbª9!i)þÂ7w²­õç$-QKZþrLÒ"˜,=#nNË÷±ï3&_LËó,cG"åȽ±~žîì¤d;Úq¾²óû.)Óžv¸àÚJ"…¥'ÇÍÒ›^èÂJˆ=½îññá—\ijuœ*–åÇÄÿÕR|ƒµü·ÎÁM" ŠÙÐòóìG?³Sž¾ H-»´m?üðb׵峷€ÇÉ›ðжeÆS2$ y|X;?5Œçƒ--ãÙªò)ds\‰ƒÊCza§XvSÖhŒwD}ÂD1é‘c`Kñô¹Ty~¢Ï Ï=AÞžúŒSe›vƒ^Ì}©r)€ ôȘ[ÓŠù1èñéÝY¦ôp?Ìuf9ïô€-çäub6Ýߊ3çyMû`Næ|ÿÊ|‹a˜ó& Ĩçï’‰ôrs,w-×HFš2ñˆô­Š=º„v†ôÒ+™ÿÛ°"Òã@¸r8Ò·åõ^±Dú†ô u~mHßp ¦ÛïÁAz ~[ÂvCú†\++xnH?¼ûS'iHß<ÂøS’eHßðQüRzÒ7§®†ô QÄ0rÔ7J²EÍ„ú†ÞŠÍÔ7DŸ—šÇ ^®”G±–+£žôj†ô“ceÔ0¨— URƒz) jÕ1ê+2/Õe3ê¥6dõ(Ûyí êk}Á[toÓ™ôþ‡1_ëó2>˜„á³á­_Šyì!fž‰æÊ¯ðÀ<²¦¨'siLÄ(ÉËfל‡ê²´0õŸ„yÎ-b0¿D+Lx@R^I×tá‘HCÖéÚwá9{…E¼‡zf5´ˆ§€ºE|oÜæ#þÒ­ZÄ_ï™ò|H›ò:Û[€—·ø•|“ɲtð8(på¾±€—B™ÄÓv2€¯:¦|}•6µâ–ïöÂÁw1€ƒr 0ß±ÔâLºiù.‹ôZsËwY‡WØ^&æ{!Çð½ ]oX<Îÿ^®4Æ»iá6Áï]7…¦ï¶ðnÞÒÄw:€Ëâõ²x—Âk;hï¨2n§ ã]nÅlç#¸ ÛÑÐkHkànl †;$fÏGtÀóñYðB x>ƒé­°>¯À‘“'.ŒÑ÷ý©ÿK6¨BJÇ¿©oÞ¨ýHdìîÇOªo'êñqœâã©wÇè§ÚÏõ;*y nœâ„αÕ?}A¨ËcØÍOî´æ†º|?yþé&ülìÍ!O›/Âà ‚o¹‘ ,æ’óß\rã/±I¯Š/7ðÖø««²’›÷÷Íá›_÷í÷ÿôWõQ,6˜Q ˆȆ';fy/>k–½¼Ô\GÍß𿟾ý/ßþUþÿï8á{¨±ùtdÝL:M ÝŸq ì+ËaÖŒªîJ¦f*;Ø„«uê©ÿï8—‘Çužw )ô¬ÁxT•+Y6¢{¿+Û¯:’%_Ñ%ëä*éIwÀ‰ˆ}3Χ.b‰¡ìºÆð7T',õGÑÈ•ÜÏØBÑúÚe*WréAe(Ô±…õ—:λô0M±e×ËT²d”©[úkç]‰ÞÌñPaÂe–â(Ûôn¤J¾œì´‘3V׿FªäñÆ޳ÆÑ€˜d(b¡Zü>ÅEËG‡"• ej}P§x?ÊTŽd±ÉY‘Ñö¾—$ÉW.®—­oˤ h4%\©—©§é¡½Ú•õ`Ä‘#¹!¿ÔýSR©‘Ñ:õ ’:¾E¶<òÄ{2#ÛÞdu|·íMV™‘K÷ÖÉ¿ö©Ý¶ƒE%Dîe÷,G‘ʇlúWÔ™Ý(ÒÓ§ªtÈ(S‹ÃWuf·Ϊò!£LBÛ‡v÷–¨ÑT:d{K¤•ž'Ì#Ç1Æ ß_Áa‚Áóˆys]¸T:d”)S#\8ØgNΤ{œÊ†ÜËä2aQ/’;î¹™Ô0§’!÷±\#à`ñy¾¼m‡WÉÍ#-ûvlÙ¾Av5Ï—·×• Ù<‚€ö$Mz}­–îÔ1 CùÚ3áAe§G‹©œŠn=S9QÏ •£ê¢¡r|Â8¨ ``uã Œ“e0ô¨ê¯‰Á)0h5„S …B†pIWÓXZ§–º†1ßjyŒû0ƒÑ€}#Bp š4D`Ó%"ð¨„Àkÿ\“—k!ãé(0‚¹ÝƒÀ¦"ðh7 &°{"°¹ŽlFŸ<š@èå^yy\¼(R¯ ^Ó6¯½Lƒ—˼¶Lƒ—ZIÜ¥¥ÅØ57$îòÀ3xM‘—“—ç“×´…ÈË#ðšê¼Üóø˜È'EAš½õR/vÃÞz%‹Üz=ìß •Êê ¶â#IoMZ”éË4q¤DÜÆ†·±¢ÑÛôKœÉkŠ4x›~O0wå*2g5wù2Í],µm.vq‘ZxÄ_(dv‰¿ß@`){À6;Lb®Ž@l.#Û2MâŸ$æjĈ!îq" ãNjà È|ñØŒñØ\¦qÌm$,›"åÙÖ\6ešËß Äåf˜­¹Líg,Cß l?²-S\æÑb07z2˜m™scˆ˜¹ç æ<æÁ`Û2 d[¦lÊ¢¿k>)Û!‡ø®\ƒö0}aûX“§kƒF3N­QøÕd6EŠÌ¨M¡M“Wi€i2÷;¾Mf‘q«ÐŒÚÈi¡Øü¸NÁe³ŠÍ(ÒPp¶µi:÷;ªU«éŒ2½ÅÕx–2KeTCäUTF[QùQ¦°Œ2í:ÐXîõmNi*£å8Ëö^šË2fÛ/ f{&ó£L‘¹O7íãPh¶õi6Û{j8Û{j8ÛëœmuÎö–ΦŒèü(St6õi:ÛË4yœm‘b3ÏB³¹J“Ù¶C#ÚŒ$!ÚÜRÚLr"´½eôö§O p ‰¹”§ÿáf”žà¼Uû‘xT›JÝ·õĨw!D×+i½ 1ešÒg¨9N”n…i«( uŒ&„¦4$0zY;£!ƒ—D0åAç–ߥsËïÓy܉ Ü´v˜™Ü ÓUC¹Úh(·ü>”YÜÄäFæ3¹QÔ›™ÜèuJHn•q­ÙÜ*ÏšÍíi ·ò.’1Wôc ;ëmh"ãïõØi$Ëb£QÐL®ŽŸ‡f2æ•é°ê¥­;BrÅÜÝŒÔD®ŽÔDdD’‰Ö:¨´ÀJY€aS Ô~"2¤7 Æ­ÈvÖ¡ÔîPV$Æ™B cÄ• H âÊû31îøˆ«±ð5ˆ«Ù¢hWÒó‡ëýEÁ4þ5ˆ+o²ˆÈ¶ >ºø©V?¯wa‡ü>ˆqNä{ ô ש5FÆÁ†Ê—¡1HbN†„F/?a\§ yÜ[¢–´âq Ž«pŒ"ý"Ñ\F¨L­Ô-Ñ`–ë mŸ" ]Ú»F2ÊÈ&¡K#Ž+£H7\Ù6Eùq²½®à¥ä‰Ì¦{e(^´Ü”ÉìM "3w™ÀlšN`öô .û¦gqçƒ+˜©ý†Ë-l»0Ï5˜yÌ<ô fsK"4õ›mª#@›2"4ßRÚ”Ö¥½Ïg[Fjº%áÙ\F|6í'>ó4a>›{foG÷Ój—ìf¤µÔ©7Á¿Fl¥'Õ.oÕ~"ø3ûñ“êÛ‘zêuô4:F?}Ô¤{XíB?}A¨ËcØÍOÇÕ.Ôåûɧ_¬vA"0yÁJ=ÈivTí"oÙKYú%ú¯T»D¼SS»¢üã×)vÙÐØx:2‡ªWp: ÕŸ¼gåYÕü „ÞV pÎ+zžÃ~NÐgëÃþb=¥¿Dì‚ ÍT£š¿`ªõ&ðTã&œŸj½ Ïa?7Õ:°>ö¿…Ø%àäÜú~󔨅ë8$váJN‰]¨–cb®å„Ø%b¿[½$ø,èC± ŽõÔb—?‡Yð׉]Àx^¯¦H8÷kG\‹ÖWà,ñ•ç¸dŠ #Iývækÿ„” ¹V}ËöÙá=ˆ»÷r9PÄ•²3d¸gî ±(Ú[~驸’;GõÁ.S IpMý§´ ‡9¬b H¤uk{1r¦8«–ÿdœÂµXä Ë™â¬äËÅ­¤Æ(R›á\(ÌJß\ê>7ª!ýL*…Y/ºg¥x+%Äɵî|Æœc'7 ·^zt[Ú§†KQÿiY©æŸÌœ˜Ð+)/I¹Hû¢G>™51#íú‹#íËø‰$/U=¡WÌš‘üÅ“â… ¾˜9cå"R¼`8 <0kF½ J ¥ ÅSJ ¥ }Ü„šRºÐ7=q(¥ ß3’Ò…– ¯Rºhñòpl¡ …­°À•Ò…¾o”Ò…Â?Š’¼pK2i^tpª’¼p)^(ÐS )^Œ4>\kþ‘JU‘ÊŸ¿?—‘%|)"R© í¶¨HE¿sã·c"R'!~è%y /h¡8ãNpÿ´ˆZhàI†Û«†FÁhe‘Ø(B0-J†³ÌE+Uc¢ÈÐêÂtzRQ'\h­'U+e*ÂÆÖêTä˸µíV¨Ò¢R¸ U´]_î„*­oÕ_’µIŠœ]_D¶2«,£õE o_lRwÛ”$=-š¥"„~yuU„­Ît-*éQüT¬4½É= ƒŸŠ„gúZU²‚LÏ‹JV0œºÆ¦Ðäãéá{<¥+ìq[ ]™‡6(VôÚ…´D+¸ûr']éûF銨 zTWéŠ,î>HWtâeSéŠ&½í¥R¹¢w*ꀫrå|`{Ý \‘ù×JáŠvßO*\‘fQ\u+jª”­ÈÝê‹ÉVäúGêxÕ­ÈSÛã7Óª[‘I¾¾nt˜§t+8¿/°³¹%ðp®ê1$› VÙ\6ðWÑ\TmG4U"ˆåHäYš¡¹_‰¬Â2DNd(Q Ȉ…5e¿)Šg"ØNN Ì$,$ðëß+ó²Ü9-Â*+z‘â†äµf@/½nªÌÌr³3öÑÀ^·)|m8À—ýެ21‹ w°—ÿÿU0iÙ?2”X`/Ìá';1û³:˜¯gðL@hÿ(aÎ|d¤ÈÕÆïßÂóØQxÍǺ÷ö™„û‘IèY¿.¾{\ó~O‚Çþ"¦¦¨2ÛZ‰e bjdŸJƒ¡ã–õŸÄÔÔÊx,µ¯-ÿ?1 V¬£7ŸžÎiŸµj¶w½¢‡4¡Çþ¥Â~ÑÅØ$~Bª°¿•16öï¦ï.þOˆcty§>6%cwT–GÝÜÔÚycìŸXtom¹.:NâÝáf¹^üÝúæâÿ ™±_ïäml2¶ý)…Œ òBÆFyJ!ÃaSÈØ0O(dꮡ6>¿[û;…̦ú˜?ÓÇ ªÖ™ ¸ìóGòó’@îø>-ã‰Ûs=œžòÔ£†a~¬9Œˆ­¨c½ŒOÔ2?5Syä‹m·™8÷%"¨¯cˆÁN£i4V#‰ÃîÑ1ý¤²q†Mñš´t Ì–šQ¯½~˜°2zŽœõó–‚Û;Åù ÎÔO‹gÇ…×!S8sÆ|¶ôJu .Š4¬Ÿe¥ñ” U¥Å°Õ™¸Œòó Òòëë’9 ÔÍ™VÄhõ×}2ÑŒŽ;æõûbÄYuÜù-ù¯ï‡í¤Õ[˜Â§ó^»ÁÆÑÝ{íâ¨q ÚÌÞvFhc£“ÏRE¥…a«3-ð±R}M©,·%4†Qc³n½~ÖìÎG.UDg¹òRExV}§ÃVg%ìcÉî‰CÆWÌgÉî‰C6hîJC€Ö–l¸xÎ%k½v Ñ.˜jGŒòб(—YûµdÕ©9lÛ¯ù\±pÊ#â´êzïxÄi1›u> endobj 8 0 obj << /Type /Font /Subtype /Type1 /BaseFont /Helvetica /Encoding /WinAnsiEncoding >> endobj 7 0 obj << /Type /Pages /Count 1 /Kids [5 0 R ] >> endobj 9 0 obj << /Type /Catalog /Pages 7 0 R /Lang (x-unknown) >> endobj 6 0 obj << /Font << /F1 8 0 R >> /ProcSet [/PDF /ImageB /ImageC /Text] >> endobj xref 0 10 0000000000 65535 f 0000000015 00000 n 0000000145 00000 n 0000031791 00000 n 0000031812 00000 n 0000031835 00000 n 0000032265 00000 n 0000032134 00000 n 0000032029 00000 n 0000032192 00000 n trailer << /Root 9 0 R /Info 1 0 R /ID [ ] /Size 10 >> startxref 32346 %%EOF blis-0.9.0/docs/graphs/large/l3_perf_zen_nt1.png000066400000000000000000002327351422157504600214770ustar00rootroot00000000000000‰PNG  IHDR¬öEYa )iCCPiccxÚ•‘gP”‡†Ï÷}Û m—¥ÃÒ›T) HYz•^E–ÞY–"bCÄDiŠ AF¥H¬ˆb!((`A³HPb0Ѝ Ü¹3qîüÈóë™wÞ9çÌŠ*’*àû¹Ø³CBÃØð ‘¼Ìt®'ü#Æx ÿJtL&V Ÿ—Î ¹ •#H Ç€•”.@Γ€ÜfÜ_>̨¿|˜ü?@¢Å}ãQßø÷¨pù‚„ؘ\¶Z¬ '’ÃÎôs±g»98°}øi± É1ßü¯Êÿ€ &Wà–¾…Ÿ/`ÿßPcC##øûï|„5ø¿ÿ€oziœEìÀßYT5@÷é'gjÇD ºîñ²øÙe8‡ÏÁá+ñÍøNü ü(~ÿ@ °šs‚+!”HØJ(%%t®† S„E"‘(CÔ%Z½‰‘D±ˆXMK)Hq¥b¤öIµKH-IËIÛIÇHKwHJ–aË8É$É”é–y&‹“Õ‘õ•Í‘=&{Cv^Ž)g%Ç“+–;+÷D•ב÷“ß*B~P~QAQÁE!]¡ZáºÂ¼"KÑN1Q±Bñ²âœCÉF)A©BéŠÒ+¶$›ËNfW±ûÙ ÊòÊ®ÊYÊ ÊCÊË*š****ÏT)ªÕXÕ Õ>Õ5%5/µ|µ6µ'êduŽz¼úõõ% M`½Ý³šÒšnšyšmšZt-[­ ­F­‡ÚmŽv’öQíû:¨Ž©N¼N­Î=]T×L7A÷¨îðü‹5©k׌ëÑô¸zÙzmz“ú,}Oýýný7ja  ¾š&6>5’0r7*0ê5úÓXǘg\küp-}­óÚk{Ö¾5Ñ5‰19fòÈ”aêeº×´Ïô‹™¹߬ÝlÎ\Í<¼Î|œÃäøpJ9·,ðö;,.Z|²4³XžµüÃJÏ*ɪÕjv溘uM리U¬#­¬…6l››ã6B[eÛHÛFÛvªvÑvÍv3\mn"÷4÷½¡=ß¾Ó~ÉÁÒa›ÃUGÌÑűØqÈIÂ)ЩÆé¹³Šsœs›ó‚‹©ËV—«®xW׃®ãn n<··ws÷mîý4ž:ž|Ï^/ÔËÝë×Äzõõ©ë»½ÁÛÍû÷3MŸ ŸŸ} ¾>¾µ¾/ýŒüòýüþ›ý[ý?Ø”< Ô Ì ì  j Z v .†„l ¹*šÚF k[Üà´áð†épÓð¢ð±šs7ÞÞ$»)yӥ͢›#7Ÿ‹ÀGG´F¬DzG6F.F¹EÕE-ðxGx¯£í¢+¢çb¬cÊcfb­cËcgã¬ãÅÍÅÛÆWÆÏ'8$Ô$¼MtM¬O\JòN:™´šœÜ‘BJ‰H¹*‘š”ÚŸ¦˜–›6œ®›^”.̰Ì8œ±À÷à7g"™3{LAº`0K+kOÖd¶MvmöÇœ œs¹â¹©¹ƒ[t¶ìÛ2“çœ÷ÃVÜVÞÖ¾|åü]ù“Û¸Û¶#Û£¶÷íPÝQ¸cz§ËÎS»(»’výR`XP^ð~wðîÞB…Â…S{\ö´‰ñ‹Æ÷Zí­ÿ÷]ÂwCûÖî«Þ÷µ8ºøN‰aIeÉJ)¯ôÎ÷FßW}¿º?vÿP™YÙ±„©ÆÚuÈëPW»¢¸âýá͇oWšTÖ¡É:"¬ò¬ê©V«>P½R_3Zk_ÛQ'_·¯néhôÑ‘cvÇÚëêKê?O8þ¨Á¥¡«Q£±òáDö‰—MAM?p~hi–m.iþr2õ¤ð”ß©þó––VùÖ²6´-«mîtøéû?:þØÓ®×ÞÐÁê(9g²Î¼ú)â§±³gûÎqεŸW?_×Éè,îBº¶t-tÇw {B{†/¸_èëµêíüYÿç“•/Ö^’¼Tv™r¹ðòꕼ+‹WÓ¯Î_‹»6Õ·¹ïéõëû}û‡nxܸuÓùæõîÀ•[Ö·.Þ¶¼}áçN÷]³»]ƒ¦ƒ¿˜þÒ9d6ÔuÏü^Ï}‹û½Ãë†/ØŽ\{àøàæC·‡wG׎=>Š~4û8ùñÛ'ÙO–ŸîœÀO?{Vù\þyã¯Ú¿vÍ„—&'_ø¿x:Å›zý[æo+Ó…/é/+g”fZfg/Î9ÏݵáÕôëô×ËóE¿‹ÿ^÷FëÍù?ìþ\Y˜~Ë»úgé;™w'ß›¼ï[ôY|þ!åÃòRñG™§>q> |þ<³œ³B\©ú¢ý¥÷«Ç׉ՔÕÕÿB,¾;E^ cHRMz&€„ú€èu0ê`:˜pœºQ<bKGDÿÿÿ ½§“ oFFss0ˆÚÿR pHYsNNÆÊ/¥tIMEã$9·-ç vpAg’Zó!%Õ€IDATxÚìý{œ#å}'ú3†á"¨ÁÍ`\ 2¶“LuF»Žcœl ß9«µšœxr˜Ý8ÒÏ4{6ç¼,%s6o2ÙÖ&¿“,´·o<“dã–iâà„® ‰×Þ»°c4€§À̈ SŒz`Öù£ô”J¥ûµJ¥Ï›W¿˜VéRÕúêÑó}®[*•JDDDDDDD>s×'@DDDDDDÔ V""""""ò%&¬DDDDDDäKLX‰ˆˆ&œišÐ4ÍëÓ "":&¬DDDN×uÄb1¯Oƒ¦\.—ƒa^ŸÑÈ1ÖÇ‹ + ,ŸÏ³OS±>^oúÍßüÍßôú$ÈÎuÏ=÷àK_út]Ç-·Ü‚mÛ¶ÙÇs¹œýá$ ù|Š¢ØÇ5MC.—ƒ¦i$ ×]w},“É@QûùMÓÄ-·Üb?§®ëxï{ßÛ÷ý‰ºÑ.ÆÛËår0M²,ÛÏ•Ïçñµ¯} Š¢ô¯ŒmòJ?ñßM쫪Šl6‹gŸ}š¦A|¥›¦‰O}êS ßDƒj¯_úÒ—pþüylÛ¶ ²,×ÅèùóçíÛXfÓ$4ÖÛ•ûŒíÞ°‡ÕLÓÄÌÌŒ=ÿ(ŸÏ× íÊd2Èf³ö±¹¹9äóyûx6›ÅÜÜœý\³³³Èår ÇMÓ„iš˜››C,ƒ®ëöñL&Ó÷ý‰:iãâß4͆xë7^Ûä…~ã¿›ØO¥RÈçó8uêTÝëÅb1˜¦Y×°I4¨Nåµ›3FEoËlšƒÆz§Ç3¶{T!Ï­¯¯WœoÅéÓ§+ªªVŽ?^9~üx@åøñãöqY–+ªªV*•Š}|ccÃ>¾²²R‘$Éþ@eeeÅþ]Q”J2™´O§Óöóõs¢NÚÅx»c•J¥á3°±±QP9}út¥Ré-^Ûä…~ã¿›ØO§Óu¯qúô醸&–N嵪ª•õõuû¸3F·±Ì&¿4Ö;=ž±Ýö°ú€î•J¥ì!½ëëëeù|ªªÖ K$ö¿5M³‡hšV÷»h¥q¾H’I’º:§nïOÔN»owLŸG2™¬‹É^╱MãÖoüwûªªÖ½–h¡w~O K§òºwŒ:Ÿ`™Mþ4h¬wóxÆv÷˜°ú€,ËX__ÌÍÍaË–-H¥R¬! íˆaÙl¶î§Ù‘WÚÅx»cB"‘¨«´3¾i’ ÿ½Æ¾¢(H§Ó Ÿ!¢a覼& ‚AcŸ•ábÂêb!¥••œ>}ÈçóÈår$©mÒª(ŠÝj#~VWW‘N§9w‰|£]Œ·;&$ 躎l6 Ó4Ù{Deøï5öWVVN§€óŸhèº)¯‰‚`ÐXçge¸˜°ú€XHI$¦²,ÛÃDeELÚ6M³.ØUUm¸MLü&ò‹v1Þî˜ Ë2‰²Ù,’ɤחCÔ“A⿟ؗ$ ‹‹‹Èf³Üv†ª›òºÓÈ0¢I0h¬wóxêVs’fff‹Å033cWRdYÆÊÊ b±b±fgg놄‰ŠI&“Áì쬽Bðêêª×—EdkãíŽ9‰Æö®Ò¤4þû‰ýD"D"ÁÆKªNñ*I2™ {‘hâ ëÝÖm¨;[*•JÅë“ ‹èE•$ÉÎ+O’e†a@–e{™3)u.²$† ùM³ïæ`íÇšÍfqüøq¯/ƒ¨/ýÆ?cŸü¦U¼:ë,í§!šƒÆz§º u‡ «Ï†™™lll@Q†X,†t:Í¡‘4ÄpšÙÙY$“I{~QÐ1ö‰ˆˆ8$Ø÷œC‚·lÙ‚ÙÙY{Ñ4ÐuÛ·o‡,ËŒ{š*Œ}"""ö°‘O±‡•ˆˆˆˆˆˆ|éB¯O`XxàüÉŸü ®¾új¯OeäNœ8]»vy}#÷üóÏãÒK/Å¥—^:ôç~ùå— …°´´äõevmß¾}¸ä’K¼>‘{ùå—ñòË/ó³<„çþË¿üK¯/±k,ÃgÔeøõ×_ßú­ßòú2»Âò;xF]~ÿÇÿø‰D¼¾Ì®°ü¿•ßIX¯ºê*Üzë­XXXðúTFn~~ËËË^ŸÆÈ---aÏž=ˆF£CîB¡€£Gz}‰=¹ä’K¦â}ï ?˃?÷$a<,ÃkX~ϨËïIIV–ßAä·ò;0 ë4qîÃd{öìÁÎ;½> ³izϧå³Lõ¦å}g>}¦éýž–Ï1Õ›–÷Ýoå7Ö ǽ>…±E«ù_8F8öú4ÆbZ>ËToZÞw–áÓ‡å7Ý´¼ï~+¿¹èù{XaЫÿ–«?ä[†aÀ0 @¹\öútˆ†N×u˜¦ øÞ÷¾çõé Œ k7L¥úûlõÿRõG Uÿ½^=–•ÌŠßõêó¸ÿ ‹^_`€¾¯;þ&½p_¿˜² ]×ëî&Ë2dÙjøöý߯e~ ¯¿þºp~嚯àñËÿ~°e7—÷àñËÇ¡' ë:¾öƒßÁspîÂ(Þôƒ _A¹\ƯÏü:Þÿþ÷{ý&€|õǨÞ&i’è>ŒêÔÃcÆDÓ´†Ûœ `+î¸mÇ4M˜¦iÇ5`5¤ˆX—$ º®×5®õŸq®2€ß¸öZ\|ñÅ8µmÞ¾§¶m³Ÿ‡ +ÖV2Ò°*Ös°*×¢‚½Ñâ1†ãßjõñBÞu_µÉc2Õÿ'a%¹êñfõáÅêùˆÄ8íxNçùè¨%™"Á0ª“QK–3hîÛ%àÿ,â›oz®ÿ¿_þ8¾¨}ð¡¿ÿn|êFÀ¹‹ÏÕ=ìË·~÷—îÇGJÁ¿|ì_âw~ôwðù—>ßÛü ÞsöçqúÍà²×_Ç–W_Å¥܈ +WâÝ¡¿Eùòÿ†/ßú«øØ}Ãú•ëHݘÂ?;u>ùèo¢|ùáÕËžÇÖk¿·¾õrlݺ7–Ëxýõ×qîS¿ŒðW¢–@ÀÝ%Džÿ ðÒKÀùSÀ3 „>\`â<ó*¾8Ìx™t"‘tÆHõOµ¸D« o*¬Ïˆ3ÑÐ!çø¿H̜ɚÐëÂ΄Ó|š¦Y—ŠÛLÓÄÞò\þúëxrf¦.)tç"XEQ I ‘H@Q牺¸]]Te ™¬?–ËáôÊ àÒï†u_§õõúß ÈçE©½¦ãä(""Ï™¦Õ ¯iE,ËP¥¡aÒù½õo|ÃëÓ&ò&¬­h¨%së]>ÆY×u×µ»éEMªØKŽç0$к7jõI¯+Á=¿JõßpöŸœÅ㶞݊ozGß8 d€Ÿz ÿì^‚×_z ¡×nEèõ¿ÆÉmÛpîÜ9œ• œø¥ïã«ïx.½ ’$AU¬‹{×ú¯×Y/~x 6oÚxíò>öpÇ?ˆ·ø?ÙêÐ4çp n¬^cíu9nÅÕøˆEÑï4ïÄÒöñ+ñ» —rþò3®ƒ÷8~øQ²ûf¡€ç'hK„¡3daÅ›HTÔ6$؉§¦iö©ž±J‘dÚrÀŽs;ð‘ÒGðÒK/ágþ’$á¦òMx"ô„¿†a@2%+Ù‹7•o¿}äßâ+×|Ÿ¹ñ3$ ¿|â—‡~ᮼòJÜrþÀ?^üøÃˆ›Êe¨ßü9¼¼óRü©\k ’$É>'I’ê’Èí?Œ7¡Ü<ûWÀÖ³À³a`ûÏ; àæk€EׇÔ0€\ÎJ«‰´­â¶õu+atúÌS®>^½ý37OT#uÀk¯Y‰¾¡8þQlÿ…½À]—XûLõýj±êï¢Ñ@“-mÝQµž/»à’W¿êu”Ñ´3a5|©ènD…sôø°i°âÚ1’CÓ4<óÕgðüÀë+$`%¥š¦Ù®âÿâ»R|麎|>oÜQ\ߢqôÑGõú’ˆ†N4ú;v ¯¼òJOeÂÚŒ²èÏç튻¨+ŠEQpÛ7âŠ+®°zNºz~£®'ÄNÚ\ó` 8qö[¸üáÇÿnUºŸ}öY\úÜs€‹ï¾7}â€\mÁÓt¼å÷~?tÑ? l<‹'^aóaë-žyé%¿òJHW^‰|"a½\u˜áÖ³gaî~W~ô£¸F–ükÜä:å;›]‡k(äå®ÃÛ›=¦—^3©û»R4XÃÔÅœ®ëвšÝòkTUµ[…“ÉdË^HV¯¢®#¥'¬›&Hw|ßïĸӼ͊©Ï= lnâÖ7ŸÂ©·_Œÿú¦5ìþèn\ŠK±®®™ ðú³ÀéÝøð>wßù8ðÜN`ËvàÍ׳ۭkIáGe/o>õàÖ]µOðrõïáŒ9I²Î[ü´cVd7|ܺMo¶‘$©qäMÖÖÖ¼¾,¢ŽZlsO• 4bdÚ™3gðḧך®„5‹úaº­hÀù[ÎãOsjãPUªªbEQÃÀK/½„³_ù .YYÁc?ø^{í5ÜxÁøîM7aí¨{ºw;†è?üÂÏ>‹Òµ×þñâ‹qþüy\uÁˆ¼ò ¾ú3?ƒo\u•=tÑ0 ä_z áPÈ~ÌSW\×nº 7}øÃxêÌ<ô¥/áßû=µäSúÑ…ò‹¿h`%ÖWHv‹ß½~È{ì¡ç¢!&ŸÏCUUȲŒD"¿ê*\ñâ‹V¯¸hdɪ{H«®©”õo‘Ü©ª•°ærV’¹ºZߨ£ëÖí"±•e«·òF©Úkyv¨*>é>÷ÅEG2wgýyµ$£á‰œÃüs°z0×Q«˜‹„µYÔ†O7K4;-Êæ<—AÞÓéØŽ:ÑQŸlº‰8Nbz‰hÄÒPõ3[½]4Ê(¨5°ˆQ‰êè%uÍSÏf³øò}[x+¤'$ÈoȈÜÁÕۮƿõÇqÉ]—àb\ ]×ñžÃæ0të»Ð4M(?­`ãÓLëZø^åFT?ä¶aôƒsäxŒ¨séºn7Ì:ëO¢çÔùœ—½ö.üqÜüæ7ãª3gð¡›oÆoÞ~;.j ùâûÌ)“ih课ˆõ}#Ë@uj‘Ÿär9hšf'žîµ7Ñ`#:7DëžâU(p´ÇQŽÓ“°f`}‹a-˜¦‰'>ý>WúÜðá7#±w/Vœˆ¦²Œ+\ùK¿( öT麎²¦AuR¦iBðÈÍ7×½a—x_uCÑ4ñj(ËrÃ{c“óÜ `Éë¿+M$]ÒíHô nllXO.g%Ÿâ W–k a“…‰X÷Ûh1¹;‘hžT*Jã¼Ì~t;²¡‘»“Öniè~êQ'Î…Í:ÝOŒ¬„1‰Zã…⸟è1Eõ¸XLpµõ œ£ DËjý˜¯\ô ÂJØþ̆C3ìÊŒ¨ü‹ï2Y–‘Ëå ( ¾ð_¨«Ü¸Iê¾ÿ‰D³;Y¸¦ØÐ‰Î=¥Â«s±ä$0D¬‰óɦ3~¶:…m§NÙÿ.>ô4ÇÚ²,ã'‹ED¬'Àk¯½üùŸãÜŽxýòÚ˜±•ãÇá: ë{Òz’æßAÍn[œ”6iÚ4[tÒî<«vf,..¶a×D¯k‘´3 «úçžïé’Íf‘Ëåð¿Îüwüîåÿ ¼ç×{XÚüñEilQC‹/]çc0Ü7•¨Ó4ñÇ¿öÇxö ‡ÍIkÄ€»E7™lìAúÓa$•£–DãJØÝe ‡°S¯ÄOçibNyºúç1µúïŒãñ 4 íoèÑs›WÑ0À4LèùÆD¥Yï˜KfCK©HÜ ƒ½±¸¸Øø—q¬ôgšµi2âßÉdc?Ÿ·{¨nÚØÀS»wƒºgr"ÑBý*è¢!A,Ô,)t® îë|\»ÆATŒEeع ž3ÎÄk©’„í[¶`ëÙ³¸üñÇ .À @óï©LÆŠ±³—ó¢‹ùÅ_DÜ]3 «wS’°µzÓVt ËL>}LÄ–3¾ vlUGN‰{gñ»¸~1•Q×u»QHô’¶JF×××{NTG!ø « 닺Eƒ¡aH¥RPüêoá’ÿë,ð7Ÿoš|M*]×177‡Ï\óoñS¯¿øì?cŒ»u3eÀM‡âR½V1!Vß®öZÚÃgU´^\Ow=Ÿ‚žzó À¡T+o¹Úp.÷HUUëX¬†ÔºÞ61t±þ¬Þ&M³Žg³ö}Uª$Y£,ÜÜEEi|n7Y¶ïóüÎx¾RêÛD¦i"ŸÏ#—ËÙs+Eå³ãš."6ìEøª•`Ó4‘ï;êO¡YÅ8þÖ·âÂíÛñ¶ÅÅúdWLI†x®ñ/ìä²éwW¢ºvB:Ý9–TÄi0bضsÑ€"R1’L’$†aOƒJ¥RH$H§Ó]5¸ŒŠsÅh÷¿E*‘ÄNÎǺ’œTUE:®Kä»Z“Äg‚Ÿ°Š/zñþ‰†‡j\jš†T*…•dªiŸù °ú_%Üûky©Í0B1zàKŸú"Ÿ|øì'å^Ÿ±?õÚ˪¡¿D—&›ˆÑËiÀj=¤b"ñy\DãþÃ"qm§Ã}Dëy³ý{Ý+”M’PçK9·H¬DTôxŠdquµþAιÞÝ$µéýoî8ç3—_LóJïmˆ$U¬F›H$°ºº:påÔYùïÖŸþ4núîw­¸ëärÖ{éŒ+§~§‹°vªˆbÁ+UUë§ðµ ’5 Ö؋Š( ’ÉäЇËrÙ=ìÖÙà Ô'šÎ Ã꽫íF}úYðV±„…UaHXúÛÿê_áÑü‰=ÿ¶‡–9"?IÁª»ê“óc?†Ÿ:…_½ùflýwÿøËU&«í˜°’.ïïÜc–&“˜š€•VW³­[ý°’Ñ4jÃÇ5Ç1CsÅ>Øâ;HBý÷Q—œI©sx—3!½gvåF Ÿ­®Ü];'½–dº‡TŠ^2gâÙ©²ÔËâd4Rî üÊÊÊèzPœ‹ñ‰8k2Åä¦| 6ì– ewtà¶oÜæõYø–ˆqÓ4‘L&qÜ=Ǹ’$a±:¼;ŸÏ#›ÍZÛï¹õDëâN&E/o³dTL›&­‡ÓkÁOXÝ[UˆU ¤R)|âÀE·ÝV²”Aw{¦ù‰ØŠÉ¹B'¬žUý¦›°*6!pjM¬xÚ ‘ÀÐd‰¤¨{¸·  9ëÛb¡"¸nsj±ú³¨µ‚æ\p&ŸÏ×%¥ñ·¾ÿfçN\sò¤•èºõýåNt½¶ Œ;¡I«çåM$Ã0Íf¡iÒétm½aËf­† Ö¨!>ZU¼[-Jä5çpü~i°ÊQVˆÅ=ÅŸ^ìiîÜBn®z›˜£®¡¶h`5”)°8#›è 1‹‹‹Cï M$vï£s.¨sñ/‘Ȋň2™Œ=ÄÖ9ßë!Æžs6€ºùâýðEÂZ,‰DšÞ …÷9Ÿó1€½[]rçÞF¬­U§VŸGGmÛ1¡šÚç¢ÃJ$¨-ΙEóE:ÅH ñ<κw³ý³5Ô�Z½Íù8çñêžÇ_ÿ*~??ØûÙ%¿Ç¸hŒI$£kŒqñz•ì‘ûc+è¼ ½ó1"Ö“¾ñpä5ছêïwìà/þØv øú‹Àe¿¬|xòÿØ|;põ‡€°kÇ.<&?ÖÓ©{ž°.--¡X,byyÙ¾­T*!N£X,°ºÝú»f¢eëvCE^Xíø¬D]i| ι«IX_ÖI`nn+++õ…»†új-Æé9XC…MX.QÁ™bc‰ña‰*€³¿|þüŸ#7kÕ¶Åb¢•\Q{[–n8÷?b˜èý×·Ü‚_ýª=w陵ü÷¾…kÞüf|êïÄE¥RãÜ=Ó´æNsk½GüÛº®#•JAUU¬w3ßS$a¬2L°ïYàÁ+€®¯þO`í-À[ö×¼xÓ͵„¨&„Šõ¸ËP«ìº÷nõý¢¢>I§,’\õ ‚â5£ädÇk‰µI¤&¯ã¬Ú)°’@çÈ¢4Fç¨R1ʦSïk7ߥj‡Û<MïçkÌ$“Éæõõ égj‘h¼QÏáA'>_bQ?‘°ÊŽçÐ\÷7_vný2ðP8½xõ0ß œÛ\8üWÂúÕŸÞùà?_é¸ñ#²µ}Á«çPþ_eœù|O—ëiÂZ(pðàAD£ÑºÛ8€p8ŒÃ‡£\.cïÞ½XZZÂÂÂBo/ÐbXßß~àoñÅúÅêž“¨µ´YI˜¨W#o!…Úð¢jÉdçWˆí3|8:Ë—Ü­ù2j= VÇè暑bl1>(1/Y¾òá¯àÏžû3hÿ—Ör11)•JÙ«2:ïãLjÃvo¹î:¤ffÙ±Û‰Æ9¢†aõ\©*`š¸R×qkuoï¦Cw&ªñslçr9är¹æÛ5#FÞ¤QK²bÕ.Îÿ£Zé¹#¬tñ\î-“Ü k+­îÓîñîú˜ûµ»ÕO½n ¦eû9Æ3™ 4MÃêêªÿ{;Eý@Bm¿kV‚s2·êvCªÝiæÜºÌYÏp®S"yD¬æÛ¼ŽÝÀ¤ª h:7—¶Wÿà}ï«5©r‡ªóÒU !柼Ãb[õ§ çW¡œyý ^=újOfÏÖr¹lWª777íÛK¥ …> …BˆÇãX[[ʇ%ŸÏã;7|øçXoÌ*¸‡" ÕØâ[ÌÁq|¹šIÛoücÜý ¿P»1« ícáÅ©µë @ÌUlVFLqòïUÞ—,ðJäì3÷ǬÅ.Ú Ÿl·?ŸXô¨tÿýxêßÀ­Ï>‹_¹æ\*ž¹øâÖ Ì8çó‰ù\°ÈwüÛ"Y]__o)Ö2P[ éÞ3À·>w ëìg^ ?Çx*•ÿ÷ªæaÕ­Dâ)¡¶‡¶(þ»Ý†Ì=ºSE})8{CÝÓ‘ZöŠÅ€ŒcEnñ$¾{äu™¤ÿæ:y–°8pñxìapòäI¨O‰DP*•z{ÖœG ˆù_ÿèGoç¯Ý5ÕN‘Ç· op8òÏÿ9’¯ÿ+\|÷'¬Ä"ë`ÃL/8×·­±Åx¿­Ïšª!“É ™LÚÛt¤iÖö†a}±Wç„Ú{û‰Rú§­äÔï½Ô5¿Æ¶èujš¬Šy˜2€DÎZ )‘žø$ð;oöòÏI>ä×ÉêÀó±‡É9\W$¨bQ¡uÔçÃÊ)Ô.n+À;Wì^\ll HãÔ^¼èÚÚJ¥RÓÖšvŠr¹ÜòØ /¼]×±´´dÝÐdØJ‡&†c[,Œ“H8ºuR¨ÍŸ€[w·ºVmû 3a%¿Æx2™ýjÀbWEt¿Ò òy«Õ=%™ôåÂF~6ö„5ÖµÀˆñîαôÑh´nE2MӋź÷^^¾÷××äGÆ}¹4eÆßNŽåη:…Ÿø™ŸñúO@7öï‘®ëxä÷Á§>ö©æw¨Î“ BK5 —ßbÛ0 äóy?~¼¶VXh¯Óܹ$˜¬R¿Å¸Ø»zdóVuÔVïU` ûÕ¼S1œW ïÕ4®?DžîÃÚÊÂÂæççQ(P.— …p×]wuÿ͆Áè:®®®ˆFä¥ãÛÉQðþ?o;pñò¡ÆxLÓD*•ÂçÿÙçqñÏ\ì>Èd•6ÎØÎf³H‹¡êYT·¸Ð­ÅVœÃ›áWõiÜ1>²d5 «WU >Õg"›µ†øÊrýðÞ žgêGž'¬ÍV)‹D"¸ï¾û쥶{ßdÌøÁðñ,‡‡Ñx$¾ÑrXõ7/¼€e¦1iŒ÷(›ÍBUUÜ ßPߊnšÖ^tŽíiˆ:ñ2¶ À¦iVe>êºy`.¬®¶OV‰ºäeŒkšY–!;–5XÃæ60œ5=L³6¼×½ÞA2É5ÆÀ󄵕P(4´‰aÃÿ@ `hñ]iÂ'¿fÞ ±ˆÈÆÆ0ƒZªiVÏ*ç ÑŒ#¶3™ ­iŸ?üR¶sÏ*ÑŒ#Ƈ޻ª¡¶Ͱ¶œÉç­ï]·<M–fGÁXø6a&]×G?™›hÜ# Ã`ŒÓÔ2M™L««Õ±_¬–p±]ÍÊ ÷J¥‰¡iLÓ´ZŠÁZ$æëŸ³*ÌLV)FÒ»ªÁšß=è”QÓ´†øærµ9¨Þë9&¬DP<|ò{Þãõiy"•J!‘HX•VËz>oä~ª4aòù<’ɤ5X‚5´q6g & €¡õ®f`5Ü'0œ=‡5 H¥¬žTŽfð•©HX;r¿vç^ŸÑpÍÁÞ?lîóŸÇÉ&sQˆ‚NôFÙ‹ÓH°VHU9ü—&“=wuV%Ü0¬a‡¬ ¢á˴뺵‡ÜE€&”®ëPÅ6«°â9—k>wŽhiš6œúŠ `ƒ-ªdõ¿K“UŸ |ªë:~øê«9‰‚G 1 lþÐy}6Dcgšf}°†QM¨|>÷DÞS·Ç6… †Q`hšfÍÏî‡`ÖÔ~éº5ìwfÆL¡§„µP(4ü~àÀ,--5ó ]×qËùóLX)°žº÷^œ¹ñF¯Oƒhìr¹œ5×Ïéß¿êõiõ-ŸÏãΧî´öØ»Jaš&LÓìo8°k²$zßSU,Â73cý_UãÇÙ4AºJX‹Å"î¸ãÌÏÏÛ·išfo,¼¾¾Žùùy¬­­y}= Ã@øÕWÙÅOÁ¢Ã*¸@×qQ$âõ]CªiÀ–Ï{}ZD} D^|ñÅÖúD“ÏçëGÄtËDmNw/9¦èMµ~__·/c#ÐÄé*aM§ÓˆD"8|ø°}ÛÁƒíÛî¿ÿ~,,,`iiÉëëiðܱc8·c‡×§A4\&ìÆÐ / |Ç^ŸÑX‰yP’hŒ“ÏÞìõ©õEÓ4«2¯ä|nð'$ò™†)Ýšƒ•¨öšgF­75æÂe¬cÂZ(P*•°ÿ~Dª½8årÅbñx¡PÇQ.—}74øê'°=ü‰ˆüÄ1ã© .à‚K4uø|>_›¥ëÀÜð™{‰ŸšLù|ñâµ!‹Dc7Êô"kñ±~Fï&ìM ˆŽ k±XD4µSÀ 8uAç<î'7•ËLÁ#–r×4<þúëµ^&¢ ËЭyPö†a%«««Àßü¨µÕÑ„1 {Ê{ð–.µn`OŒòÞ3±p'¹\mÿm œŽû°†B!”ËåºÛŠÅ""‘ˆo“T§­gÏrÁ% žê ’ß|Ó›ðoÄÏy}>Dã4űÊd.g õ2+Y]÷ú$‰z§ë:ö]ºxËða.CÁÓ÷üÕn:HS)«ñruÕëˤéØÃ‰DP,Q,XÃ5MC4­»Ÿ ¼sçN¯¯©ÎÚ›ÞÄ„•‚§ÚÃúÂo` ‡¼Ó4ÐQUàV¦iÀµ2°ö­ä`š@Oþ÷'qË©[€G~ƒC)t]ïm;›9tÞ¦Ì4­•$ÉZP‰£Í«ck$A4Åüü<âñ8 …Êå²]Y(—Ë8zô(8€h4Šp8ìõ5Õy%aSð ²Ñ$ÊÀÞ$þ±/?u¥š°¾þMØJV9Š’&Ôu^‡ò<ŽK¯PXg¡@2 £ûéKbâvù­i±˜µ5 ·§ ¼®V ^\\„ªªX_·ÆZ9`:t轊ðââ¢××C4N{}Dc¦R¤„_ºò—j·_÷—ýíËGä#[OlÅIçbKH=ï½*Ãj„lE×­žU&«S£c+`ÍcÝ¿ÓcñxñxÜw=«€5ü€(Èã45ªûRþÙ÷ÿ }óGk·¿ëRîYIoçs;Çþ-ðé{½>¢¡ëiÁ¥<¬ÊV±¦Y[hSþ¦FW=¬í„ÃᾓU±eN+Åb±íñNÎ?ú(·û ÏŒ:¾‘ÍâÝ_þr‹ ÁÈc\0`ÍÛ°º±ZßòÎ=4c‹mX½Oö®?~ýLc3Î×u½»áÀ&¬é,.2Y2]õ°V`=z°gÏž†E—z±¶¶†¥¥%{õáh4ŠÅÅE{ÕáR©„t:m/ô¤ª*²Ùlϯó®ßú-üe<>¾¿&Æß0 ”®½7x}Á4uÆãB@0dkb“,Ëömœ·JÃ4ö؆U™ýTˆ‹-ÑXxã¦iv׸ž5b¦]n+Iü¬L¡®zX—––0??ƒâàÁƒ˜ŸŸÇÒÒR_/X.—±´´„……躎‡zȾM8pàÂá°}¼X,öýzDã4Öø6 |熼¾dš2ž”áÕ±:°@3ÉôúÏAâUýäÅϽˆŸºÑë˧)àUŒëºÞy««¬ç”Tj¢«„õàÁƒˆÇãÐuº®#ãàÁƒ û³v£X,¢\.#^íù …BˆF£ö°ƒR©„B¡€}ûöÙÇãñ¸½àS×4 Ç.½´ûɈ†`lñ †Ñý0¢!kŒÖ±j=GÓªû¯Ê¤ê¾{DC2öØ®ºöÛ×b÷îÝ^_>M¯bÜ0ŒÎ kœâA-uLXÅþª"x`aaìὈF£ ÅœD"‘ºŸ}ûö!6ÜÞÉž={P(êlÒ4Íþ0„ÃaD£Q¬­­ÕÅbÝ_•¢p~yb,ñ °ÂNž[Œ ÕiÚ†aà­O‰à¾ûî³[€z}~Ae/+y`\ñÍ9Úä•qÅ8 Ø q˜¦ $9l’Fkl± :pîÜ3¸ò'Òë˦)2ÖZ6HÕ'.°DMt°jš†{î¹§aÉëƒ"#›Íö´¢Y8n;&^lfL4‰ßtc‰qÅúéjÓy¢![ùmg^;‚·ýÄOx}É4eÆãm\ÊÀÚʆíîÔ…®¶µ) H§Óعs'²Ù,t]·²Ù,vî܉½{÷¢P(x}=6®žJD M@$Æ5pè#VËáÀ&Z¯LÔDW ë ª*–——†Ù:o?pà€××cëj£b¢ ¦ëº×§@4Zšë\ñ‚Æ€O¿ýinÑDÕ²±1úù«¦iýµÐ1a- (•J¸ûî»ÛÞoß¾}(•Ju+y 2Ó49O›‚­Z1Mw<û¬µÕQ@œúÚ)¼÷–÷z}D#Ó²‡5{Ë2ÖBKšæõé’uLX‹ÅbDZîìù«årÙëk""¢ 0(VëŽsçØOrÃçn@øÙöp%ò9Ó4ë{X5s°Z ÃJV‰Þ_€¦FÇE—B¡677½>Ïžq¸$QHV+ý•çúQ ”o*£T) þDD>ÖÐÃê^h)›åveÔQÇÖH$‚r¹Ü°:°›Xp) y}M8\’‚óú(ðªí޲,[­ðŒw §ŸþpãSßðú4ˆFÏ€5 XE}²jšÖTnYFt•°F"¤Óé–Ã}Ëå2–––F{ÚÚ†ˆÕS)ÐGà “U ˜z"„È{ÞãõiŒ&æ¥ê° ëd³;—¨ ]­¼ÿ~”J%ìÝ»kkkvok©TÂÚÚöîÝ‹R©„……¯¯‡ˆˆ‚À°þgš&f·ogÂJóvƒ½JlöHG õ«Ö¨™|X\ôú4itœÃ X½¬ËËËXZZjºuM4Å‚¯zWu]G’C (À¸×0š `Ð2~rÛ6Î_¥`1 ~ðœÞ½Ûë3!½f¨œ»J=è*ajI«Øº¦X,ÚÃ…Ãá0Êå2 …¢Ñ¨××dã>¬dLXi˜¦ ù’K¼> ¢áÒ¼ö$éG¼>¢‘¨«£è¨Ÿ»*°c‰ºÔuÂ*ˆ-nÜ ‹EÌÏÏsu^дÖSĺ%½Œ®sâÝtÝzÑñ!¦*ˆ×Öõú](œ[l%“Ö^éšfýˆß Ãú¥ñ\ÅùHRãk7ã>Ÿ tÔ°A†-{…à·Ýr ç9Qàl^¸Éu(°ìõ4X .­¸î°²ÒdzҴê9a£JœÅûdÒJ˜2ë¶ÅE+áÊd€\®–9ÿ¯ªÖcD’¦ªÖ¦Yœ š,[ŸiÓææ¬çÃýc1çõÖ^G–ku»LÆ:¶¸hÓ4ëü›I$¬ëÒuëqâwÓlêzû„Õ™|:Lç5:“R±—ø·3áçcÖH’D¢÷„Õ0¬¿ùœ{ÙÅð^Ÿ Ñp}õœ×g@4r²,[½«¬wÑ€›°£÷)—³!Ó¬ï™tîm¼¸Xëí¿‹„RôF-±“¤ZB)NQUÚsšfc¯¢$ëëõ·¹oÆ=—=™ì<CQêŸ[–»›ßìµ:qwšˆ$¾—óköÚÍ8Ïç{ßë|?3œ-# z±íÔbõm€9úX'òıçð—üO܆íõ™–€#}Å=šÑÉÝÉ#:Ûš=ÆYWTUëx.Wÿ{*ÕøgÎÜŒ÷¿ÿ©žÎ9° k³ý)uݪ<‹Cšfý!76¬Ûææ¬ûˆß¥öÓN«ã²Ü¼²ÞêöÚ¹{ý×#¿3 c(2bÄ€(ˆœ½Øù¼õãµ#zÜE¯¾»`rŽH¥jÏ«ªµaÙ²\k@#D#D&Së1wö¢Fí1¹\íwY¶~wŽ CÎósp¤Î‘bظ¸n1úA\“µÐŒs$ƒs¨»¦YçØlÚ±s$ƒ{¨»säE³×÷qŽò›G}ïÀñá9 Ük˜‚if ¾ó7/â6¯ÏƒhDìÆF õÛõÊL!wÇ€øînÆ]×õM³F6ëu1Q÷q×Íœù“;amšÖúüÄkKR}‡œ$Õ¯«%ê7…Â1=ú|O/OÖb±-W.‹…B‡Ã¿–aX ©xsÄÿ××kÿ^]­ §–Ð FßÝVäóy«sùÉS"QK ÅS:6ÀzŒøü8sœ‰¡$Õ6a}½–à:‡Œ;O½Uo¹Hš› ÷CßÅó¸G8#ÎO–­Ï¸xŒ,w7JÁÝËœHXp»?¿Eá|-çù9“RAüd¹v¬Sã–ø{‰Æ8q¾†?þtç‹ÐHc<`‘ +ycäõ“oÅŽnÁ¼×JSkÔ1n"×Fꇋ/õ š¿*ÚÝ=Œ¢1\$žâûºU¯"PŸ4ÎÍÕOáÏÙL«ºN¿£»©û¸GIv3jR$¬­~DÇ„µX,bii©ã•Ëå®_´X,"NÛû¹†Ãad³YûCS*•N§í“ªªÈf³]?¿¦i •Q9•åZà1!¥Qu|·¢ëÖw(45Í*EB*8“Ñn;i8~¼ý}š%aâv÷9tC–[¯xßé³Û¬€ì7ïq?W7å†;Ñì&ñl6ô¾Ûç$^kmmt ëXb<`¸ìµ×8¶œÆÆ«ò›h\Æã»Oï®_¸Ýª c$z EêA%ßÅÔ@ñõÓj!PqѺ²Òù+Ë4rÁäö.Ö…B¡®·´™ŸŸG4…®ëx衇F‘vÔL8€p8lï6ivj6\ÒÙÄd•FeñÝlQ±L¦Öº§iíc¼›Ѝ•qÄ8«ñqw¥bÕˆÆ`,± àµë_óúR˽CøNk’èzíw‘°¸§ºÖwj³gq”ÍÖOÝp>·óGL½j m:˜t¿Æ(§tŒ+ÆàµË^Dcµøã÷ÚzÝ'ñ·tþ¾}»5 I¼bAT/‹‹V")êOɤ52K¬O#¦79{6Ec³3ádýjø:ö°ŠýW‡¥P( \.caa€•èîÛ·kkköðƒB¡€Ã‡ÛÇãñ8ÖÖÖìÇôjf¦6/•h”ÆߦiÖm‡ ¾øØBG£6–w »zß÷¿ÏÂ;àÜ P_¦9·@ÅRé"¼øâC=qÖOÎ]|.0[Ú42éž:"Ž9‡MºÛ¡ÄÎîÝZíŽà&z¬òùú^2‘°:“Q1¥DÌ·k6%£ÓðLqçóºwGprNõpÏós¿Ö¨¦tŒ3ÆMÓÄiõt­‡5ŸYïªafµé}î—r.ŠJ“gìsXE …ìÛNž< Àú`ˆ;ÇÔG"{èB7$I²{X5Íja}‡Æañ-8‡½›fëá³DÃ4–7P?Œ, {¿s®†/V·o¶À˜úæ^ÈLüî$4k–tˆ£U%ß9OÝ]É…ÞÀ¶mç‡zýã,¿Kùw.êùƒ{¨$Pû·HÚ½"Q â=I£x[ÍmsþÆîÝÌók6%£›Üʽ0g7Æîklö·Õ”ŽqƸaØó¦=µ4­ïŠŠiÖò]çß.—³z¹UÕzœOÇ4DÖB¡€ùùùº!ˆårÅb±ë!ÀNî¡Ã¥R KKKˆÇã‡Ã( -[.—ë>d­(Šb·\vSP Ë8â»™1°!kŒëºŽñì³_Õ†è‰t¯.í\èkfÆ:.Vèv®Ší\ÛÝ+%¾öÝÓhœ ™9çj5[Ü£™~æn¹+ù—_þ:.¹äÕ¡þ-ÇÛ×|å+í» ‡HĈ‘©(ÖwF³ÕCÅ}Ýsõœõ¨nÞ¿N[Ö s1êÞ¸ë(¡NWq<=«ì‹˜Ìdj ¬XŸ†‚­¯ÖC‡áàÁƒMçÑu«\.Ûϳoß>{¨A»Å›677[~Xž~úi<øàƒ(‹öf1Ĉ½«½ÑuW3¹¢(X\\„®ëÈçóXl2®"‹a½úM–Ïç‘Íf¡ë:dYF:FÒ'ãU×ÖÖpï½÷bëÖ­#{aÇ7œ8qóóóPUº®C­~Ûçr LõæççqìØ±‘¾ÆHËðÐ2 YCʮ޺u*j#"™ûÞ9‡Áº{4Do•{(£ó{¯Ó‚i@½R¢7vÜ–––päÈlß¾}$Ï?êò;þJ•“0ºy¬Î­¾œ«¹;ã¤ß=Íi´Dù],[®à;¨qÔÁÔö_íqcw÷è wÇl:]›.@“EÔÁ{-¿=ÙÖ¦X,âÀ…B8|øpÃЃVÚ-­}ýõ×ã¶Ûn«cŸÍ6n'A™ÕL_$Ÿ†a ‹!‘HÀ4Í– ZµiÖ0 ¤R)lll@–e˜¦‰ÙÙÙºžo/‰–Ä£GŽäùGß°k×.û‹àÓŸþ4TUµ·~aŒ“Óòò2æçG·aÆÈËp€ @‹¯Šy~¢ç*›­Í«sÎms&îa°Ýö`½çjaa{öìI>Žò¿ñ^¹ðíPÕŸ¯˜**øªZ«Ìó{a2‰ò{TÉê¸êຮ¢¼r.µÛ†aXe£íÑn1;£&S¿upOÖt:h4Šýû÷7Û¹s'k˜‚øp8ÿÝ MëîËÚ“eÙN<»a†ýÀšk¹²²Òõã'ݸâ»öz^_1M›‘Ǹ˜§øÄ8·cú(?>¢áȽ2©iÖ¾ƒÄ ¥")=öóeÂx¥ü>úÎ]ü €þV±×£HP»mÌ W¥®ƒ¢Ãb2box1Íu‚¶i¥1{ªiJ¥TUm+F‡FëV$Ó4 ±çzˆVG¶ÀôÇ0Œ†aÁªªÚ½¨íˆ¡ª333H$PUÕ¾-èÆß"ùg…–Æm\1o<ñ.zÏ{¼¾ä&ƒÚ>Ç@m`³y{‚»a‰Ÿ[ÿ[lŸ9ƒ×¾Òóù9WBÕu«R?%_­4$ã,¿wŸÞ d,¢i—ÍÖíD/.²ÞNÍ=a7®&†š.,,`~~Þ^~; á®»îêéuF¸zöH¸“Ãqë&©ì&Y666ìù®™L†a`}}ÝC‚Gi\ñ ÔVÍã°/§qÆø¡®üä'=½^Ñêoµ¤SÓê+UbõTšlc‹í—¶ãÉ7¾‡zxH6[+ï .œMýgù½ûôn{´Œ[*ÕzQ/¢fºNXÁ-&e7 øN{¶.,,tÜË)‰à¾ûî³?Xý¬FœÏOÖð¯{ eWë—,Ëu +åóyär¹®N‰­ªªv‚šÉdËå°ðqãŠïºÈ‰Æe\1§¶m{Wd.WÛÖC|¾Ä– ¦ ¦±Åöó¯á¯Þõ(¾ v¿Ç½¢tBNÔɸb\Ó4\|ñÅ-Ö€Wi:&¬;wîľ}ûnï·Ò-÷ÒÛ½pî%7)¼NX;«ývÃ4Mär¹†k’&é ±Aâ[{ ùÑ0b|•èû%VéØêOÍ #¶Ïv±J½iZ (é4c‘Æk1.C¶ÏsôPÂÔ«Ž k8îØãG\ˆf0š¦aË–-ö着buuº®7=¶îèÎN$Ð4 333v’kšfÝ}hpšÆVJ ¶qL!Èd¬¤`cêS±÷”Fî?mƒù!œ›c¢J“kÛùm€ –VV`J2R©ÉýHþáÉ*Á£Æ…h£ª**•JÏÇœ·¯¬¬À0 †I’?wuÜØ›hªi𕤮®ÖT&©4V{#0îî<Ÿcuu²FŠ ¦ib÷K»­_ª=¬s1«¬eýœúÑuÂZ,í †#‘HËÄ‹!\äOέmh¸&mQ1¢^=ñéOããßùÎОϽ¿‹&òR«:”aX=þ\-•&™®ëPflןù¼u;§1Q¿.èæNš¦aïÞ½(‹…j;â-,,`ÿþýˆF£…Bx衇¼¾¢© iLX)ض<ü0Bo}ëÀÏcšVj,fJØØàg‡ü‹Ã€)(ŒEê¬( 2Na¢Át•°8pªªâþûï¯Û<8‰ cyy{öìÁ¡C‡¼¾¢©À" º 77QºöÚŸgvÖúÿÆ·€"0Z,ïžJYÉ*V Ã@æw"‘`…ÓqH°Ø‡éî»ïn{¿»ï¾wÜqâñx]RKDÃÇ ÝÖo} ¥Ûnë뱺nUŽ$ 8~Üë+!ªgFÃt±¤¡ ¸öÛ×â†ož2å.„JëØÃZ,‡’P1 XÇOž<éõ5Ñ„Ûþ䓨ñŽwôü8M³†Uša%òŒs›7]·ÖÕU¯ÏŠh8.{ì2+/0 ÎǦ¡è˜°†B!lnn6ܾ¼¼ŒH$âõùÓˆ˜¦‰T*…íÛ·cË–-˜››ú‚Zº®#‹Õýd2™ºãÎßÝ Ã@,C^Ìæ¯Êçó˜Å–-[033ƒ\.çõŸ“ˆzTºöÚ¾m“$«—ŠÃÏhR¤¬]?X©§ÀøÜ ŸÃ¶ÿã²üš×§BÑ1aD"(—Ë( mï'Ž;{]irÅb1H’„Ó§O£R© ™L"‹ 5i5«] ëëëX__ÇÊÊ òù¼ý¦i¶}½\.Ó4ëVÃ0J¥°ººŠJ¥‚ d³Y®^M4I4 §¯¼²ë»†U鬅•˜¬’Ÿ¹¿66¸M¹e;´ís^ŸDÇ9¬‘H‘HKKKˆD"MÒr¹Œ¥¥%D£Qöº@>Ÿ‡$IXtlN¨ª*‘Íf¡ªªLš¦‰d2‰Du­ò|>o÷hŠÛu]‡®ë0 ÃZê\Qêž[Ûà˜]ŽåËçóX__Çìì¬='Hü_ôÌH’„•••®Ÿ“ˆ|À0ðäK/áÆ.ºœr9k»î¥J“Â4M(ŠÓ´†®³…‚æg¾ú30+W"}Àë3¡ èjÖýû÷c~~{÷îE<¯KJ=еµ5û~4ùDRé–H$Éd Ë2r¹Ö××!Iæææ IdYF&“ÁzuÕˆX,f' Ùl«««H§Ó˜µ\Ã0†ýª]¬(¤ëºýš‰Dù|étÚ~ìÌÌ ‰TUíêùˆÈGdãO;t;årÖÏÆ‡SÒd‘$ ¹œ·\½š‚æÃoþ0d™14<]%¬‘H‡ÆÁƒ±´´Ôp<cß¾}\x±XûãŠÒØ…Ë®ù› ÜK꺵)¡["Ññ[S’$»§2™LÚIm2™„¦i¬dS,Ù¯ª*òùL&Ã0°¾¾Þr£v"òUÅ©l¶í]D²º¾Îd•&¿–(ˆ.{í2äóVÕ’hºJXkàýû÷caaÅbѾ½Õ0aêQ?kÙ'“½7Í*JÇ×’e¹éœOMÓš&}ÎÕMÓ´“WI’:&ž²,× CŠ;=.—ËAQd«•ZÃ0ìÀJ–Źf2är9¬p×j¢‰ÑnÞ¹XU•É*M"]סª*·ú Àzìâç‘Íî`ÂJCÓqÑ%·P(„h4jÿ0Y 1ÄÖYa4M™LÉj‚ì<&z9eY¶ç¾.ö9¡L×õŽ+ƒæóyȲl/Ö´¾¾nŸ³~ì&±VK4QÚˆ$®ªJ“MQTTÛW‰åè§â(.‚úâç¼> ®{XizH’„õõuÌÍÍÙÉ£®ëH&“H&“Èd20MÓ^IØ0 ,..B’$ÌÎÎ"U]®S×u,..Ú=®Íhš†-[¶Ø¿«ªŠUÇftÍŽ‹y«Nªª"“ÉàøñãÐ4 333ö¹›¦iÏ«%¢ÉÇyQ4éÄnkìe¥ ¹póB»àB|èG^÷úT(@Ö"Oñxœs}Ľ—~Æø¦ ó"Æ;íàE4 ãˆmMcÂJÞuŒä#Á¾m_òú2)`ŸoØÿ+èßtÈqU66˜¬’¿°ü¦ cŒ“_ùnH0` ÷™ŸŸG¡P@¹\F(Â]wÝåõiV»²@ÌßÊÐ,Pä´Úê! Y½¦Éï­îßMÓL&!ITU…R³Ëå ªªØªªŠ|>UU!˲}?Y–aš¦—uOLe|ÓTaŒSP1¶)èãäGž&¬Ñh´i[$Á}÷݇b±hß/ðºYTĽJf“LÅõÜîßÛ½\“e9E*8÷cuÎm5MÓ:,ÚiÃø¦ cŒSP1¶)èã4I|Ùà X›óCâo’$AÓ4¨ª Ó4í‚OôœŠ„wçªvÂø¦ cŒSP1¶)èãä7¾›ÃJþ±eË–ºwâ™L&¡iR©æææìÖd2 ]בJ¥J¥ì¤–ˆˆˆˆˆ¨¾ía%o5ÛÒFɧišX]]…aP±XÌ>¶±±a÷¸Š9«ªªÖ%®ëÜ\‘ˆˆˆˆˆÚ`ÂJ™››ƒªªÐ4ÍNL…Gј°RßdY¶{XpØ/ Vˆ,Ëu+ ]"""""""_bÂJ t]G,³÷Q4MC,ƒ®ëÐu½aÕàL&ƒ\.×ôQ¯˜°R±§j>Ÿ¯»=ŸÏC×u˜¦Y·ï*¤R)˜¦‰d2ÙpŒˆˆˆˆˆ¨LX©)EQ’N]×›®ü›J¥+++^Ÿ6VjIUU»—5ŸÏ7]8•J!ŸÏcqqÑëÓ%""""¢€á*Á>áš.ZG䉺˜& (€$†aý4#ËÖiZsÿÞêþN‰DÙl‰Dš¦!™LÖõºŠÛ’É$R©VWW½þ3Q€0aõ‰nVðK‘°¶zœªÖTMkü½Õýİ`1'Õ=XQ{ðìì,òù<‰„×J""""" &¬>Ñ͈Úd²þwU­%³­Èrýs»ï$‘H •J5,I’ýï••Äb±¦÷#"""""êç°R[‰D¢«žSEQN§177À.¼eËû'‹y})DDDDD4aØÃJ TUµ{JEA¥R±­¯¯×ÝÏ)N#N@ÝcˆˆˆˆˆˆúáûÖb±ˆR©äõi㛂Ž1NAÆø¦ c|“_ø¶‡µT*!N£X,°zó²Ù¬×§E4Œo :Æ8㛂ŒñM~ãÛÖ C×u<ôÐC(‹XZZòú´ˆ†‚ñMAǧ c|S1¾Éo|™°–J% ìÛ· …ÇëæOM*Æ7cœ‚ŒñMAÆø&?òeÂzòäI@$±o‹D"G_5-­\kkköp” a|·W,±¶¶æõiŒEP?ËŒñö‚ú¾»± Ÿ>,¿'㻽 ¾ïn~+¿}9‡µÝ‡¢\.# 5Üþâ‹/â‘GÁ¡C‡póÍ7{} #uäÈìÙ³ÇëÓ¹¯ýëØÜÜD¹\êó¾ð øÆ7¾_|Ñ“ëê'¾Åy:toyË[𖷼œs‡cÇŽáØ±c‡Ã^ŸÊÈê³|ìØ1<óÌ3ž]ËðöX†æé§ŸÆc=†sçÎyr]ýÄ7Ëïàuù]*•<ù;²ünå÷`D¼×òÛ— k»?ÎææfÓË\€Ó§O㡇ú×o¶oߎ£Gz}cQ*•†þ~>óÌ3øîw¿‹+®¸Â“kê'¾`Û¶mx衇°cÇ\wÝužœû8lnnÀTÄø¨>˺®ã?øg×Å2¼=–áƒyüñÇñâ‹/âïx‡'×ÔO|³üžQ—ßÏ>û¬' +ËïöX~FÔÁ{-¿}™°:‡!¸µúð~ðƒÄ?øA¯O¨£~â:äõ©u…e8Y?ñÍò›&Ëoò#_Îaݹs'€úa ^ 6Æ7cœ‚ŒñMAÆø&?òe‡Fë&îkš†X,æõ© ŒñMAǧ c|S1¾É¶T*•Š×'ÑL±XÄüü<Âá°=É{yy¹åü>¢IÂø¦ cŒS1¾)Èßä7¾MXkâ·XR9z}:DCÅø¦ cŒS1¾)Èßä'¾NX‰ˆˆˆˆˆhzùrë4) Mo/‹m÷Âôø8‹Å¶›r-~ºNjÔ*¾à¼ï£Œo¿]+ÕU|ws|œ‰ñIºNª7 ñÍò{zMC|‹s Dù]!Ïœö±UvïÞ]Ù½{w哟üäPÓ£>Z¹ýöÛís¹ýöÛ+>úèP®ÅO×IÍ5‹oq{Þ÷QÆ·ß®•"¾»9>NƒÄø$]'5 z|³üžnAïJ%xå7{X=P*• iÒétñ C×u<ôÐC(‹XZZÚñqšŸŸG4µÏ%Ö]ó ×â§ë¤zíâÎû>ÊøöÛµRÍ(ã»›ãã4HŒOÒuRÍ´Ä7Ëïé4-ñ °üö,õŸb÷Þ{oåŸø„Ý:!ˆg Èg?ûÙÊí·ß>”ããtäÈ‘ÊîÝ»+gΜiz}ƒ\‹Ÿ®“µŠïJe°öÓû>Êøîæ8ygTñÝÍñq$Æ'é:©Þ4Ä7Ëïé5 ñ]©³üf«âñ8–——±°°PwûÉ“'‘Hľ-‰ØãÃ=>N‘H¤a tq~¡Ph kñÓuR£Vñ Ã~zßGßÝ'ïŒ*¾»9>NƒÄø$]'Õ›†øfù=½¦!¾Åë­üfÂê#íÞìr¹<ðñq …BuË —J%,--!#t-Ç÷ÍuRo‚ò¾2¾ýöY¦îé}$Æ;}VýtÔ½ Ä7Ëoj&Hï{Ëo&¬>ÒîÞÜÜø¸W×´´´„;î¸Ñhû÷ïøZ_xáß]'u'hïû(âÛ¯Ÿeê,ˆï{?1Þé³êÇë¤Î‚ß,¿É)ˆï{Êï Çð÷¢.9»×ÝÂáðÀÇÇ­X,âÀ…B8|øpÃð~¯%âСC¾¹Nê^Þ÷QÅ·?ËÔ ½ïýÆx§Ïªß®“º¤øfùMnA{߃V~³‡ÕGvîÜ  ~XB©T²`Ðãã–N§íqôîäZüvÔ½ ½ï£ŠïnŽ“?í}ï7Æ'í:©;AŠo–ßä´÷=hå7V ‡ÃˆF£X[[³oÓ4 ±Xl(ÇÇIÓ4”J%¨ªŠB¡P÷3èµøé:©7AyßGßÝ' Òû>HŒOÒuR÷‚ß,¿©™ ½ïA,¿·T*•ÊØÿ’( ˜ŸŸ‡®ëömÅbóóó‡Ã(—Ë…Bu+} z|\–––pðàÁ¦ÇÄõr-~¹Nj­Y|ÁxßGßÝ'o"¾»9>.ƒÆø¤\'5äøfùMAŽo ˜å7V*—Ë(‹P·Ê×°ŽûÉ ×2I×Iõ¦å}Ÿ¦Ï2ÕLÓû>Ègu’®“j¦%¾§å:©Þ4½ï“T~3a%""""""_âV""""""ò%&¬DDDDDDäKLX‰ˆˆˆˆˆÈ—˜°‘/1a%""""""_bÂJDDDDDD¾Ä„•ˆˆˆˆˆˆ|‰ +ùV""""""ò%&¬DDDDDDäKLX‰ˆˆˆˆˆÈ—˜°‘/1a%""""""_bÂJDDDDDD¾Ä„•ˆˆˆˆˆˆ|‰ +ùV2Mš¦y}D#Å8§i5ªØçgŠÆ1GÓ„ñî&¬>¤ë:b±˜×§A4RŒsšV£Š}~¦hÜÜ1—Ëå`†×§E4Îxg¬V""""X>Ÿg%ž¦c}¼.ôúÈ"Zj$I‚¢(-˲ UU¡i’ɤ}\Ó4{˜B"‘¨{ŽL&ƒt:\.Ó4¡( ‰DÝk¦Óé¾ïOÔ­Vqnš¦o’$!™LB’$är9;æ…|>Ó4íøï%^Ûä•ve|¿ñŸÉd°¸¸ˆl6Ûô{Ã4Md³Ù†ï¢A´Šeq{>Ÿ¨ªÚ£â6–Ù4)šÅ{·±ÞªlÛ½b«ÌÎÎ"“ɰϹ¹¹ºã™LÙl€UY™››³?$Ífíǘ¦‰ÙÙYär¹†ã¦iÂ4MÌÍÍ!‹A×uû¸xý~îOÔVqnš&fffì—|>o¹1M³!ÖÜ¿÷¯ŒmòB»2~øÏf³H¥RM[úMÓD,³+BDÃЩ¾âÖ,FYfÓ¤è%Þݱޮl÷gl÷ BžZYY©H’T9~ü¸}["‘¨ˆ·æøñãuÇeY®¨ªZw|cc£á9•••ûwEQ*ÉdÒþ=NÛÏ×Ïý‰:içëëëgQtúô銪ª•ãÇ7ÄÿÆÆF@åôéÓöý{‰WÆ6[§2~øPI§ÓöcÅs>}º!¶‰Õ)–+•JEUÕÊúúºý»;FÅm,³Éï:Å{§XoW¶‹û3¶»ÇV†UU!˲}›s¨o>Ÿo8žH$ìkšY–í•Ëœ¿‹Vu—$É’ÐJ¯÷'j§]œ‹ÛR©4Mƒ$IX__‡,ËeŠ¢Ø# òù|Ý¡—xelÓ8u*ãçpaA´Ò;¿+ˆÕ)–[i£,³Éïú‰wg¬·+ÛÝ÷Û0aõ˜˜—ÚŠiš/æ)9š}Ay¥]œË²ŒõõuÀÜܶlÙ‚T*eO$uvÆ6M’Neü(â_Q¤Óéºç!T§X& ’Aã½SÙN½aÂê1Y–ëzBú$U’¤¶I«¢(v«øY]]E:æ¼%òvq.XYYÁéÓ§±±±|>oÏÃN$ÐuÙl¦i²×ˆ&J§2~ñ¿²²R·h Ñ0tŠe¢ 4Þ;•íÔ&¬K$Ð4ÍnA½¥Î㺮ۓ¶ÅŠc‚s2ALü&ò‹vq._²,× ‹‘e‰DÙl¶«ágD~Ò©ŒUüK’d¯XÉ­h:ŲÀ$–‚ ›xoëÊvê V‰¡[sss˜ÅÌÌLÃø••Äb1Äb1ÌÎÎÖ•’L&ƒÙÙY{…àÕÕU¯/ÈÖ.ÎÅœ¼™™Äb1ÌÌÌØ•tA4̰w•&M§2~”ñŸH$H$Ø€ICÑ)–«N’ÉdØ‹D¯S¼wŠõnÊvêÞ–J¥Rñú$È:ÐjJ]×!˲=ž^ìÑäLJ‹,‰aÂD~Ó*ÎØ£šËårÈf³8~ü¸×—@Ô—v±0þir´‹eg…ó])º©Ÿ·‹õve;u «Ï†™™lll@Q†X,†t:Íá‘xb(Íìì,’É$7Ѧ©Âø'""â`ßs Þ²e fgg‘H$˜¬ÒTÐuÛ·o‡,ËŒyš:Œ"""ö°‘O]èõ K©TÂ7¿ùM¼å-oñúTFîé§ŸÆõ×_ïõiŒÜ /¼€K.¹—\rÉПû•W^Á\€[o½ÕëËìÚ<€«®ºÊëÓ¹W^y¯¼ò ?ËCxîIZÜexðŒº …B3'ŒåwðŒºüþÀ>€P(äõev…åwðø­üLÂúÿðÈçóóå5ˆ|·Ýv›×§1rº®cÇŽ¸îºë†þÜÏ<ó 677'*aý“?ù“‰:ß~=óÌ38uê?ËCxîIJXY†ϨËp/,¿ƒgÔå÷{Þóž‰IXY~ßÊïÀ$¬W]uEÁ‚ק2ÓpkkkˆD"ˆD"CîB¡€£Gz}‰=¹úê«§â}/‹(‹ˆÇã^ŸÊXŒê=-‹^_ZOX†Ëð–ßÁ4Êò;{}y]cù<~+¿“°N“iø ˜š/<ª7ªÒ¦å³Lõ¦å}g>}X~SÐMËûî·ò›«‘/1a%""""""_â`ò|>]בÏ窪BUÕ¡.cš&t]ÇÑ£GñýïßëK¦ e À®ë0M³é}$I²÷3M†aØ÷Q¥î~€÷@-Vï–išøú׿îõŸ‰ˆˆˆh`LX©)MÓì+ŠbW´ÅO'y ;íÄ¥—^Ь‘…¢(0 £®b®ë:E®ëø™wü >öòǰï­û°˜X$à¾kîÃÚÈår0 ²,ÛÝqn>Rú¶žÝŠk^¾Û¶mÃÙ­gñøåã+×|§¶j8'ñ˜+¯¼?ûÜÏâoüo½þ3¬8ÉŸ,ËP¥§•㜱êÔ.VE"²,C’$û<œqÖŽ8G‘t6{ qn’$Ù‰¨ø¿8?MÓìû†l6Ûðâ<ʉërŸ«óü_ýõ!¾KDD4†aà{ßûž×§Aä+LX[1ähÕ€ @°Xý=W=– Uÿí®«ýŸ‚³"»íü6l;¿ §¯ šâ{ÂÝ*Ênç1w£|³FPñ|íÊþ_|ÑëË&ò&¬­ä`UÚW`%Y@cB*Ê%µ„ÕÙÙcÂJ˜Ò°’5TkÖm&L<ú¥GQü«"N:…‡·<Œ³[ÏZ5ÍZ…]Wð¶Õ·áË·~•·Updzw`ëØŠ³¿roÞòfœÝzß}ÓwQ¼¤ˆG¯{[b[pãS7âý…÷ã±ÿí1Ü Þ€íoGø¯Â=d`Û-Û¬ë2`%„ÉÚu¼ïĸ³þïa;r;pkîV`£zÿdõoð $‡p#n´’O á±vr/V µÖs:©°D®£ÔnWÛµ8IÕç•kïå«…W§6aýû/þ=Âÿ& :>sãg ë:n¸âüóçþ9Þ}ß»1ûïf~5ÜØ@3 ëoºnýzZ9 Àïz÷^p¯»€•P& ¤ÓéžzKÿ ð“ÞQ%wΞO"êŸ%!*éâ;ÌÍ=T¾×áîâµ®ºê*|øÃöú²É#¢QÓ­Õˆ'«ù|¾iƒ§s‹H8Ý#jÄèÀŠéD"aß_¤t~~Þë?1‘¯0aup~qÊI¹±×Æ‘ð¨õH *{T YؽY?ü0.øæø/{ÿ 8ö~íÇ ³/ÍâÚ·]‹k¿}míy´ês‹Dwø>V{Þ߯3ì‘÷`¾§áoĵçü¤ã¼D™® Ö›Ö®\•`%Þé&·w*%×ãdÔ’ NœçÖk^!zp§œøb~æ«Ï`×c»ðBü(¿¦@UUÜ)ßÙpߥüòù<Š•<ê±Z+ñÎKwâÍ©7CÓ4¨ªŠŸú?…÷~ë½Øûõ½ÖßZ^¾ùe\ºïRë ç`5:¬‹@×ï‰,ËH§ÓVï¯ëýCn¢±(ÙÝswM4²tKsYû°R#ç(2Á—îdO×õ†SÄ¥øŽrŽ3M³á9ÄmÉd+++¶n§”ù•ȃœŸ1úMt¤I’Ó4íq͈†KAŒˆ3 Åb?ÿó?ßÓyM}ªë:r¹œýFüò‰_Æ×®û²ålÝ}œ-y‰DÉdw5cS2‘•²ÐRš]ÐÊ?%cŸºKÊR“Àú‚Ãg;¨kaì%¡kv_ÓÜ'ËÖO÷Pqbõ·†õÓî¶d²ñµR)@’¬÷sj ªÖS&Óxn¿ýÛ=ü±&W.—C.—C2™Ä¿ÙùopÍÉkÚ6ˆÂ(N#—ËA–e{ø,`U0$IjþE_­X^ª_Z»mÕu V+zoÃñêïsÕûmTï·^½O¾zL¢àºó×áš­×àcw~ÌŠÖwÞÁúÝQ6܈q+ªk<‰úÞMç4™VÜí¹ÝŒ¨q`êe$yÊ0 är¹†ÛDO|?ÓCˆ¨‘H8Ýy‡{ŒØuC$Šî5?Ä1ñ"ñ\]]É(w‚Ü©LXMÓD,ƒªªØØØ¨½éɶ²YÈºŽ•Dæâ¢=¿Î¹ª§ ‚â¾ßø „/¹ÄªÔŠÞDè%OÍzçæ¬$ËY¸;ÿ-Ë ¡iZ·9“¾f‰£“¢ëëèY:Ý<¹l§Ùuvû8çÿû1…s’U Ösߊ®¹œõÞ.v¨)ŠDRô’;04­šDºž#—³~€Z¬þ´ ȻۿŽh¨pÇ7Ðú½M§­câ<»)Pˆ}øóÇ€;¯”ÿÔ9Î¥ýg¬çywŸ¬ìM.1dÝ@m˜·xÛSÕÛ×­JÇU¿{¶ÿ÷íxþ²çQº¶„“לķN| ïxæX[ZÃE‘‹ðsåŸÃíÏÜŽwâÝØó‰=u/eO©²OøÇ~¦fˆÇ‘¯‰E}Úõ| J =2b§ÀžR¢Á‰Ï—¦iÈçóögºYÞá¤( ’Éd >ƒS—°Šd5™L¶Ökš•UQ‘Ïå e³HŠJ±èlÖë™ÉÔnoVánL««èÙ8“²}Òp躎l6[ß´žiÖÐkÀ–­ëÀÌ †ý6Köœ…¥ª6Îí&î× Yîœ<·z-ÀŠÕ^>?õ£ÖQ·œóªER*Â\Ì¿–§®z çvœÃ™?:ƒW_}A–el{ï6<üêÃøƒ™?¨-îò‹µÑ ×à¤ä”57wÕ½ô5¸Æë«'™¦i·œs93™LÓÑ]ÎÕÑš-€%zIÅk¨ªZ7pee…ó6i¬œñ;)‹&ŠÆ1òÀ½KP[“¦n÷Žjç—$Iuº)3U «a˜››kž¬êþëyàâß´zCWVê+º’dõÚÖ1ðz‹Dï’$5&šýö`õI×uÌÍÍauuµ1YÝõûlcÒ(bDãI"aýd³Ö±D¢1í'‰d¥†¼"±«¹wZ,Nƒ5\VlÇ%†ÏŠùÖîÅ÷«3 ë»×ñy|Þš¯'«.’€R½¯áXô=26~º+#Ô=Ó4‘Édì­QÄp[wüär9ÌÎÎbuuµnË0÷âDÎÞØf À¤$L"nEÉhØ‹?.öS1çç|m1•z7U k*•jLVMÓJ<ÿàZ࢒µèÆFç^Ä~{~ˆ†É±:®hY]]­ ñ3W"V‹{ô@³9ÑŠÒ_O?‘߈ÄV:ê·Ùrî³-ØR`Í· 1„7¦óÀEO— †fÀÌ[½Rb%Rö@ =—€ib×_þ%›Â¿k>ŸG&“A:î¸Ê­˜J¥ìÅô‚4DÐ÷œÓ¿œš­bšµic‰¦˜r'’RY–‘H$êb^4ܤR),..Ž´ÁÏ™, Î}xI5{¾©+ÿåtíÕpŸ›ðÔûßßÓS{š°‹E@$iy< !åõD€='šf3sÀŸnãüš±Åw@ÒjM·+$†Q‹ïdø“_víb|ÓP» ïZxîÒçðÈÍju>,F ýÂ`@ã–Xm¶ÕÒ4 ©T ‰D®À c‰‰¥iÍÁœ«Â;ÿíšêé!Ä ¨9޽ áü¶m¿Å¶išH¥R0M³§¡Š¢`cc£«ûR•¨t;+ß²Ü8:)—«-º'î뮜7‹éV=lÎÛǰ«ßb\£ìQ[;ˆ…PEf"‘ZòšÏçíÅÄöI€õyóHÅ|í‰oÒ´Úš!¢séÙb•ÎÏ€ Ëõ"îx—e|çw~ÏWã¯[ž$¬Åbét¥’µša8F6›µ?4¥R étÚþ0©ªÚq‚q7ê*âùÖ×HV¥Jë4\coÑkd8dtÝZ¸+®ÍC%"¯ÊðŽ ) øj¿¼ùËØókA"17(Ne8–sF]×ëG5L"‘@6Û~¬ÝÖabzgåD, Ø,aÍçk÷k:tZ°Å´šg ¼:‚}XýÛbí ±Ú.U5[k¨íJЬQDQšÇt*U»¿sçznÉdïë28ŸÓ#~Œq 6JLì¬Ñ­t:t:mï9?;;k÷pŠ$¶Ùke³Y;ÝqnvœÛ‡·?l oˆý¥+×0QÛCÝ@mšJ¯_!b Š;wq6¶8cßÙ‹/Öà©{>׎² ˜rm*ÌWÏY#–€ÚŽÉ$ $ÛïïP P%¼©ü\ñâ=]®' ëüü|år{÷îÅÒÒ†wÎV‚<:·¸ui¬ñ-ö)Ô`ÏMB&c çuV³°†8 /Êð&Îßs”À_¼õ/pï}÷Öµ²‹Ý3™LÝRþétº«Öx‘¤ŠÖvÑ’ßiXæX‰í¿œ-ãíz05Í*/œ=¢ÎÅ[ígÝÍ"kný®?f~‹í®Š "QávW¾CmWVêcѹإˆ7¯¢÷¨Yì:?Ç&j+z;÷sÙó°’„n¶xÄcÓh>>S}^HŽvm¿Å8P©²¸¸ˆDŸC¢ÅB`‹‹‹0 ù|ù|ÞNLÅÜW±Õ‹˜²ÀZ ィ­G vˆi$@cr(¶Ëœë~"VœûHWëköb}bZW³¢6@Ê¿÷PZ>ô-kƒ‡·ÿá`ûÃÀËo.}_mo{€l_úPx?ðγóDX¿¸ür`ëV«N¨9Î7 ëûa¦z^Žk2ªÏ›ØVûlè¨åMε$Çu6‹óêßïÐ8¿í|oopeÌŽ9RÙ½{wåÌ™3öm'Ož¬ìÞ½»òè£Öý[øìg?[¹ýöÛ;>ï=÷ÜÓòøúúz%‘H4?˜®T*«ãþK—:ÅË Ï;Šø®T*•O|â7Ê•Je½Rù^ü{­ãût¥RQGý%¿i/CàUÞÉéÓ§+ëÒzåž»ºŽt:]Q¥²±±Ñplee¥¢ªjEUÕ €Š¢(•t:]9~üøHþ®[\¬T‰J%®TVW+•õuëGœ¯_Ï»O£(ÃÇ^~wAQ”ÊÊÊʈþŠ>·²bÅs:]©üéW+•?}Æú>«T*•ã•Je½bÕÝ+•ÊF“ÇŸnr›xÜz¥RY©Xõ?µRÿ)WŸSÜ_­T*JõöÇíâùÓÕcâÖ«·-VÏ/Q}|ºú¸Jõ˜ìøÝyÎéJå»?ôÝ‘üIýX~¯¬¬´,‡ûv¼R©H•ººýéÓ§+÷…¿«œºëTí}oçt¥ö^6‹q»°Qý=Y½ßJ¥y º¥Ó•ŠªV*Éd“ë8^©llXñÿÉÿlÝç_ÿf¥òû­Û×»^©ÅàñJ}¼¹­;~†øgïV?ñ2öÖH$‚ååe„B!û¶“'OB¡ýoç˜úH$b]DË9E&ZÎO"êÅØã;@.¼óB(Ÿl1žD ?!/ËðVÄP²û®½êÁî óÅÅEhš†¹¹9»U_–eär9o·ìCsÅœ"]¯õ|ŠÞ%÷¹NCE§uNmüÛ™Lªª¶îYÕaõàˆŽãâÕÛ×QëéqŽôÑsâì Z„Õ;¢˜C­·È9»ÝGLG­Æùš ¥×•<¼|Њík¨¼ øÙŸ­Ýß %UÔz¥4?úž)![}mçâibµoñ»^ýÛ8¿*U4özwü[®þÝ«ƒ;ÿ½ˆú=Eo—³Îý7+»{¡$ë¹Ë‹XÆ2†Ío1žÍf‘Ïç›n¿Ô5ѳéü˜ˆ÷Íñ>Iš„[3·Ö/¬×ŽˆùVñî^wUAïÃzE9¿¾Þ|ع(·À þܽ¿öÙžÀœgì k(B4µ/•JXZZB<G8F¡PhùØr¹\÷!ëI>}ë[ÍùhDM¶±Çwµ@Z}Ûjë9Íæ8õɳ2¼Ã0‹Å°¸¸ˆp¦÷ÅATUÅÆÆ†½Â£aX]]O¢*¶pÏáÌçk·§ÓÜûzLüÛbUÒ¦sùD2)†&Ñ>RÇÝóËDh%Q_áWPKÜÄþÂâÿb¯aÖÐIVróeàÇ~\ye}büG_¶þ¿VLspåOÿï?µ*ä"ÉusÖÍ܉C«DB ßXsžg¯z)Äwn»‘­My÷SŒ‹ÕÕûÞ_4ƒú-ËfPû<8“G³z_ IìHärÖ:9Ýì8’ËYCÖYÆwäÙ*Áår‡ÂÁƒ±oß>{l|¹\nù˜ÍÍÍ––§Ÿ~>ø ŠÅ"–—[¥BGâŸú©Ú ¬9ÑšHScmm ÷Þ{/¶nÝ:²×v|À‰'ì¹'ñx¼îØŸ?ÿÛHJ×ø V«9{X§Êüü<Ž;6Ò×wÞJ*•ÂÊÊŠÕ`ÓgE¤Õþ“C‘Ï7_øBô”6[tˆ ë´µ´´„#GŽ`ûöí#yþq—ßͤR©æó«MXɪèy솻G±WÍcš€©ÉêœéX5¦Ø­6.F”ü€u>¿A >'Êïb±ØrßAù¡ünãÝ’`% âáiÔæ»‰9ǃó¨Å‚^"ÞÝëˆØŸ›k¹hœ-Ÿ·Û)"êབߞ­|àÀ„B!>|¸aèA+í–Ö¾þúëqÛm·5Ÿnš?û,Šþ°ã6Ôï³GSC´$Á “ÀhâvíÚUÿE°覎O^¼ø/ß8ŸÂDý Á,//c~„Û"Œ½ oA«.¢b'›^–ç¦iý¸{fÅJºÎ¤Ô¹°õlaa{öìI>¶ò»|>I’Z/>ãuC{,VÛÂE¬*: jM Q~*YõCùÏçašfo ‰i°ê4°’Tw»ž„æóÍîÛ-±"º˜–¡(­’I+±Íf[7@æóÖçfʾ ú­ƒ{’°¦ÓiD£Qìß¿¿áØÎ;XÃćÃùﮘ¨mù<6®¼;%©6«ÓˆŒ<¾…j,kY ÿ¿^øYà@õXÖ‚0a¥¡[ŒwJ¥jC&ÅPÅQÇ»®×ö½¥¢2Ólõ\ö–N?Äv6›ÅêêjóƒÆ[q®È+ô°åùb<“Éô´u «~ÍWŸ”è1m¶n¿VV€ÙYë9›%·šf%¾Ô•±'¬š¦¡T*AUÕ†±òÑhápÑhkkkvK¦iˆ97ïD,D°b¿(þ&²¬³ÏvšJc‰o nSÓðE”7Y7ˆy¢’hˆÆãd³Y$‰Ú\S±%Ä(Ö™™ZåýO#ML’dm187g%¯Íö=õÓ¶h>7ö„UlDÜl¸šØÜ}aaóóó( ö$ï»îº«ûQa ì1çG%Éš÷‘“U™±Ä7P·°DäÛ߆ô©OYzÖè‚éšAc4¶oùX‡mX Õ¢ÒÞlßÐãÇû{Nš~ˆmQ™ojµ·çêJ>_›g-c: w¤‰å‡Ïçóí÷¯6aMyêfñª^8W]S8Ôê|ëQ5<*Š•´¦RÖë8“b~Ÿôdì ëÂÂBÇ1î‘H÷ÝwŸýÁr®hÖ5{Iññ¹c²J¾1p|W÷v;õµ¯ášk®©¾LVÉ'Žñ6òù|}ï*`ÍÛî§Œ7 kÈÖâ"‡gQWFÛù|¾¾w5«LåˆÜaƒ¤@UŒ·A0¬dÕ0¬H÷üS/ç‹JÒÔ-®4lx}#“€5/†!IxßsïãBK=ñJ×^ëõÙM.—ƒªª[!dûx2Ó¬Í/ââä±\.W[55S½qXÉj&cÍÁ&òˆAÐveà4úOVEyžJqÄ@ù¶‡u`¢.#)xáoŽbÛ[·a‡´Ãë³"Žê\¦7ŽÅÉk®ñúlˆÆ¦åü§~Fd³ÍçªYÝbKyX îƒ,°$’«X'S·ß#ùKÃ'ƒ­€ËYåùâ"*¸ +`Ïù8·ãþîֿûð.¯Ïˆh¨þâG [iJˆ}Wæ?éè¼"vuîT]Ë;—!ŸÐ4­¶ŸpV²ÚÏBQqWU+¾Ý{y$—Ë5ß®)«¦×EÅÄ©bÿë » °`'¬Õ²ÿ˹/Czƒ˜‚IbMS"ŸÏ#Ýl‹ ç¾ÛÍèº5TÌ]YbEž|Â0 «÷)«îÒψ±ÍúzãÞ©D>Ðt±%µm({!Vøe¬O…àÎaòÀžoîa/’ÉUçhŠÔõB9µêaÍç­ùL"Yå÷ù”®ëVlèÞª$YC"Y'ŸÑ4­u=|ý&PUÆú vÂ:3˜À±Ky}&D#ach*èºÞ:ÖMØû[¿›Àìlm›šãÇ™¬ÒdXD÷½«b˜;‘φÑ8Ì€5_»“\Î*Ïiªõ”° …†ß8€¥¥¥†cžcÚ“ÀCå‡X©§à1 \öÚkLÁV]-Õ0ŒÖ{÷)¨¯äg2V¢ÊÕihš†Ÿ|çOZû•ËY£8ʆ&€a£c²°ÛI¥¬‘2냬@FAÐUÂZ,qÇw`~~Þ¾MÓ4ÌÏÏ£P(`}}óóóX[[óúzjt½®E•z œ\—?þ¸×gA4ZÖ:Kí{X¨%¬ù¼U‰wïÁGäSº®ãƒ›´zœº¡iVº¾ÎEfh"4”߬²½Ý6©”õÆ9¡Ë„5N#‰àðáÃöm´o»ÿþû±°°€¥¥%¯¯§FÓì±í†Ñí·ÑÑuniCÁ· Ó!auŽŒL$¬žU¢ a$UênÿIÓ´*ò++¬ÄÓÄhœCû¹Ú"YeYNUÖB¡€R©„ýû÷#‰Êå2ŠÅ"âñ8B¡ £\.ûgh°aØ=¬2'eSÞô–·x}D£¥Ð: θ~gEž&ˆ®ëØó‰=ÝÍ]Íf¹M”†ÆFÖÜÕV 4šfÕᙬ’CÇmmŠÅ"¢Ñ¨˜µ½ðœãÑÇ}¡š°rU $ÃÀk»vy}D£¥[?o¼ñFëdÕ@ý‚KD&üjØ©v¸£®[•ù ¯O™¨kº®×—ßyXÓ8ZI¥· £©×1a …B(—Ëu·‹ED"ÿ%©NÕö† QJ×^ ùŠ+¼>¢Ñ1À³ágqçew6¿O> ȺOIä/š¦aþÂù΋Ï8‡M†—òh½ïªaé4GPƒŽC‚#‘ŠÅ"ŠÅ"k8°¦iˆF£u÷CwîÜéõ5ÕÍ_¸à¦áÜŽŒm 6 €|ëì·ðî×ÞÝx\°ô?­‰&®ëø‘ïýHçÞÕ\ŽyšH Gëh=ü]–$©QÇÖH$‚h4ŠùùyÄãq ”Ëe»µ¤\.ãèÑ£8pà¢Ñ(Âá°××d|u+û”QJŠÂ- (øà±ÿñ¯ºÆ™>XÞåæñ4±Êß,ãÍ×¼èÔö˜Nwõ|D~Óvý¢.uµJðââ"TUÅzu$çL‡²W^ôË6²l·¸›¦Ù¸÷Ѥ3 h¦É/ 6€~ö0ÂEWch À•«Àïþœ×gIÔ·kÿǵØ>·ÝëÓ ‰†duÆë3¢IÕU …°ÿ~Üÿý8|ø0âñ¸},ãþûïÇòòr_sZ}³ª0ÑŒ,¾«CLXÉk#-ÃMÔTrîŸðÜsÀ Ÿcï*Ì8ê'‘W"͇GÐÐÈ:ÆëVÖÑë¦ ÌÎZ еÑUÂÚN8î{p©TÂüü|ÃíKKKP¥î§ÙýºÁE—È+#oŽ y®;ÊpQŒ›°¶±¹ì·9L’FfõÓ4qËù[W¹6M ³’V¢WÜNXÔ/¶$â<™äÜlê¨ãV¡P(àèÑ£€={ö4,ºÔ‹R©„b±ˆƒ6=~òäIÄãñ¡m›Ã„•Æi\ñ­ë:’\œ€<0¶2|Ý‘°V·¸ ö°ñ¿uÉë?Ì8ë'º®ã臎â×ñëõR).°D#3ÎoX!ØinÎZo†õêBW ëÒÒR]`M«Å9!)HtàÊ+¯´†º³2OúÅ€K³A†ÖUÂzàÀ¨ªŠååå†EŒœ·8pÀëë±qQ :6ÈP`ɰê°öñ38˜‚Eþþê¿·V¾fYNuÍW¾ÂŠŽ k¡P@©TÂÝwßÝö~ûöíC©TB±XôúšX=P¬ÐM õC‚M“• ]Òqùë&«h7üù¯²ì¦¡è8‡µX,v5ùZÌ_-—Ë^_“C&‰ˆ&—=RFQX±§@yãèx÷®]9@¥ë:Þôýòû½> €Ž=¬¡P››“·ô:·ý  [__÷úˆFŽkPPÝø™±ó¹çØCõ#§ß†-Wu5󨣎‘‰DP.—Vv .…B!¯¯ÉÆ„•ˆh²q¤ Ñk¯½†mçÏŒo ¨Ë^¿xÿõ^ŸDW k$A:n9Ü·\.cii ÑhÔ7[Ûp["""ò£ßÿðïãê³g¹UÖŽ§ßüØ ^ŸDW}õû÷ïG©TÂÞ½{±¶¶f÷¶–J%¬­­aïÞ½(•JXXXðúzlì]%"šlº®[ .år^Ÿ ÑÐ=ÿ«¿êõ)ÌÅ_ pÄ; IÇE—«—uyyKKKM·®‰F£XXXðMïjÝÞ}DD4‘E±¶ýàˆ  øÐßåßzÍë3!™w}ÿ]«â4$]%¬@-i[׋E{¸p8F¹\F¡P@4õú𰇕ˆ(tóü(pΟ?7áM^ŸÑȤw§±®pHŽ®VAlq£ºæ]‹EÌÏÏ[C¸<&ËrÃùÑä°×!0MÎó£`Ñ€â«EÜ¥Üåõ™Äßñ‹È>ü°×§AÈõ¦™°M6{K]çÖ8§¶âÔ% ¬Ë?tñx} LX‰ˆ( 8$˜‚Æ>þÄœ›Muíß]T®ôú4(@˜°‘±w•‚ÆÊ›_¸ÖÔË[ÆÿÜÍù«4<ž'¬…B¡å±b±ho¡C4‰ßt£ŠqMÓðc/¾ÈJ=yf”åw(òúòˆFã[ýΫ,»ix:.ºT,±´´Ôñ‰ÊårÏ/^*•š.ÔT*•N§Q,ªª"›Ízý·"ê 㛂nÔ1þîË..ºÈëˤ)4ÒØ^Ôqê#Ûp“×ISm”1~}é=xîª÷ú)@†Öà …ºÞÒ¦T*AÓ4¤Óé¦Ç8€p8 ]×ñÐCu4ù㛂n\1^úÈG€ÅE¯/—¦È8bûì‰8µm›×—JSjä1nxýÂy¯/“¦c«Øu˜ …4Mkz¬T*¡P(àðáìD8cmm ^ÿ½ˆ:b|SÐ#ÆMÓôú2i #¶_ø‹¿Àk»vy}©4¥Fã†×·„qn§<Ñðx2‡5cyy¹iðŸ9Óòò²gwÃ*ÃÏþýß¹]¢ سgÏØËða•ß™£G9\’Zåw»x•¡”ßyàÙgŸû¹Ódè·îù>¬n;wîP?,¡T*uü2 šŒo ºaÅøÇo¸{°’¯ ³üæpIò£¡Ä¸<öîǼ¾ ß%¬ápÑh´nØ£¦iˆÅb^ŸÑÀßtÊñË^{ +ù Ëo º¡Ä¸Ì!Á4|¾ XÃ}æççQ(P.— …p×]wy}ZDCÁø¦ 4Æ ÃÀŽsçUõúRˆê £üÖu*c›|jÐç–d4 ]'¬ÎùPbRv³9R½Ì±‹F£M¾‰D"¸ï¾ûì çÑhÔë¿ÓÈé: IV‡‚iÖ~Ó\Zl™ V§Óuë±Îß Ãú¿[2i½–¦Y?ªjý†5mÌMQ€D¢þ¶lÖz='Ó´žc}Ýú=—³~w¿žûšÅu¨ªu{&c½^2Yû½E©Mq €Î×÷ñ·øíßý{Êø¦ UŒ†}ýu¯/¦Ø¨Ëo&¬äµQŸ®ë9:††¬cºsçNìÛ·¯áöQW²C¡ÐX+ò"!2Œú„1‘he2É H××­ä+—òùÆäË0jɨ®[ÿIiZI,wNX%©1Auÿ®(Öýܬ×PÕZÒè|>§TÊzgäL¨[q¿Pÿ:ÎÄWQjãf¿›¦õã.÷Ëç­E±~Òië\F´+Sׯ߈˜—eë§YÃ…x¿ï»øÜˆÏˆh ß_ ¢Ñ¢Y#Pû *JcCŠ,[s¾¶¸¿“ó3 Ô^K|Ý$ XY©ÿœèzí¾â3*®ee¥öüºÞøzÎçs^o.g]—»AÆýyr_¯a««õ¯åþ¼K’?Ö)$Æ·ž=‹—¶oÇ[¼¾¢&üV~ Û 1Î9Ú½ë¦cÊIä€õÝ/êÿêLÍ8ëpšfÕ•¥VgjV×uñZîN'QïV”Z‡‘ó|Nœ¸º§¿OÇ„5få]ðþXº^KÀDÅSC»$ÌuS)L&koPŸ|‰d·Y%ÕýÜݾV»ß› ŠÐ*a]_¯UæÅß±›çovmƒ6¼IRcÞêµ§q!FQpÖ{™Ï[…‡³0?é´õ£ëµžvÑÀàŒñœî†w¬ˆ¤TÜ×4kï•xŒh´hÖˆáænHq¾ïÎXjõ¹M$êÏÁýyš%±¢nõ™?—âõçãœ×+ zñwY_oþeå¼^÷9$µ÷MÜ×= bR]þøã(]{-nôúDˆˆ(4­V7õÑ"êssµN' ¾cÊYgÇΤ.™´¾ƒ5ÍÔêË‚»óÊ9J°—„5—«ÕQšiVgêfP‡¨Ã9ÚÅß©Ùk8_ËY§Y]µ®G×­óõqç9ìÚõ|OïŸ/ç°“¦Y$ztD«ÁÆFýý¼3IÉ”D]·>ÐÇ{}Fä”ËÕQ(‹˜N$¬Ÿ|¾¾…ËYˆŠdVh—¤95KX;q7ZtÓˆÑì|úi0iE$zÎäV4fõ¢Ÿë:ý½›ý­'© éÅs<€K¼> ¢Yw·~È(ö¸£‡$©±1¨kÖË×,!ÔõZR™H4&hB¿S‹‹í¿ŸÝ#»y­|¾–„Š‘]­:ošÕ™ºMX»¹­Ók‰úè0Ñ»NX‹Å"<ˆ}ûö!‰´ÜClÚ/Ñ‘N÷Wù¤FÎ!‰ä=Ñ€ ªVœ­¹aA”ÍZ_jî-¯3·Ý†ÿôŸz}DDԣĀ Ó¬%g²\û^vNÛi–j8§­õ“Ãé¼êfº\¿—TʪƒOcNÓUªiÒé4Âá0B¡}ûÂÂB¡4MC±XÄ}÷ÝçõõØD²Ú®‚zÇ„Ç?LÓJVŰ\:Í÷ƒŸûõ_÷úȧĜ÷HäR¯OÅ3bqC–ûäG½,¸$†ÓŠxvNguw1uIp›ÝŒ* ²®Ö@UUdEÿyU$A4E<G:Æ¡C‡|1ßUŒ™f²JA67WâNÃ1ª–Q¢I!æ«‹¡ëb¨XàÃÙ³!æc‰UØsŸÚmÛ(z>Ä|11|ν(šs ˜&^ã•W¼þKygv¶6OÌI$óâýkÕ£äœ÷î,Ĺ9×FÜIƒ¦MVÚî|ÛszMžœqÝ깿÷½ë½þóŒ„iZ=¦’dÕ_œÃiÝ;GP£iNZ;&¬b¦»ï¾»íýî¾ûnÜqLjÇã‡Ãž^T³9ªDA’Ét¿ðM.÷ Õ"‘¤Zá\-RpÏårN¬ä0›­UEÒèœï\µ^<§sþ»3ç ε›išî„«Õ¢hN"‘.^ÆÑ£^¿;ã!ŠðÎ5$Äû.V‰½s‚X̺M #tn-Ô(U­õre³V¼ˆ…*Å|@çëf³s33µÇ;nQÕÚcfg­×v.r#bÐ,º6ĵ6û>s[íÔÐŒ¸iÖ´q6Àˆów/$(V±@Ïêjýk7ã¼±à¡hüÉf_Üí]Àˆ9gY$LJCy£cÂZ,‡’Ðh4Z7][§÷J$¹\-Öºi€p?o³ÅE£‹àî\èg‘›tºÖ£ŸLZ±½W»Z‘¤ÆÆ”~®¿›Ñ0$Êq~óó_p[çõ9±è©iZÓiÎKƒë˜°†B!lnn6ܾ¼¼ìõ¹M-&«Dþ%zZÜ[õÛš9Wóvïs ÔövþÞÏ\.çðC‘àpÊŒ?9.Ä{뎧Q-‚8ªÑ;£2,zhc1ëo7I (ÃØêϯDoöÊ “T\Ç„5‰ \.£P(´ÝD¸P(@]¯+QPˆ¹œb¸¢Øw7kÜ×Û½u”›;!×p8÷¶ ä=1ìZ IåTÞ‰¤Uì AÞ+Ú2Y¥a¹ Ó"‘"‘–––P.—›Þ§\.cii Ñh‘HÄëk"""ê‹sÈ¢˜ÿ·}»5/›­%«Îùlîmœ›¨û “Uÿ™m¾MõF,äCÞóæ™¬Ò°tµJðþýû1??½{÷"×%¥GÅÚÚš}?""¢IašÖ,[½\™ŒÕÓ%Vàîfîš_“Sš ÍæM*1 ¥›²“¨[]%¬‘H‡ÆÁƒ±´´Ôp<cß¾}\l‰ˆˆ|M,T¤ëµUMÅð]Uå ó4>šÖ¸XѤ붡¨]%¬€µ ðþýû±°°€b±h߉D8o•ˆˆ|Í4k‹!‰9¦ÍVU%—TŠ $DDÝè:aB¡PÛÅ—ˆˆˆüBìqÔ/ŒDä%ö®u¯ã¢KDDD“HlsX‰W_%¿Èç¹=Q·˜°Q ˆ­Ä*¿ëëìQ%ÛØQg= —¥¥%áõiÒñ[¼ « ?~Üë+!?˜´2ÜoŸGò7¿Å ëà4LýÄ‹/‡ …†¡›››¸JM>Æ7Ý(bÜ0¬áÀì]%¯± § c|“ù2a …B8pàŠÅ¢}ÛÁƒ‰D<A4LŒo ºaǸ®±˜•´ye8ã›üÈ—sX#‘öíÛ‡½{÷"âäÉ“€l6ëõ© ŒñMA7Ì×4kŸÕÕU®®JþÀ2œ‚ŒñM~äË„Çí —Ó¦ a|SÐ #Æ3+ae²J~Ã2œ‚ŒñM~ãÛ„°V% ‡Ã^ŸÑH0¾)èúqÓææ¬ùªëë€$y}%DX†S1¾ÉO|°Ñô1M ™ ¯Ï„ˆˆˆ¼Æ„•ˆˆ|E–¹0Y|¹J0V""""""ò%&¬DDDDDDäKLX‰ˆˆˆˆˆÈ—˜°‘/1a%""""""_bÂJDDDDDD¾Ä„•ˆˆˆˆˆˆ|‰ +ùV""""""ò%&¬DDDDDDäKLX‰ˆˆˆˆˆÈ—˜°‘/ù>a-‹(•J^ŸÑH0¾)èãdŒo 2Æ7ùÅ…^Ÿ@+¥R étÅb ª*²Ù¬×§E4Œo :Æ8㛂ŒñM~ãÛÖ C×u<ôÐC(‹XZZòú´ˆ†‚ñMAǧ c|S1¾Éo|™°–J% ìÛ· …DZ¾¾îõ© ŒñMAǧ c|S1¾É|™°ž…±8zô¨]p 㻽“'OâèÑ£^ŸÆXõ³Ìo/¨ï»ËðéÃò{ò1¾Û êûîæ·òÛ—‹.µû@lnn" 5ÜþÈ#àsŸû¾ð…/àæ›oöúFêĉ˜ŸŸ÷ú4FîùçŸÇÆÆ:4ôçýÞ÷¾‡+®¸ c¿®~â ÃÀOÿôOcûöí¸úê«Ç~ÞãòòË/ãå—_¶{²Q}–;†óçÏ{v],ÃÛc>˜'N \.ã†nðäºú‰o–ßÁ3êòûÀ‡?üá±_ËïöX~þ¼ßûÞ÷z.¿}™°:‡!¸…ÃᦷüãÇÇ?þq¯O¨£~âþú¯ÿÚëS'ê Ëp ²~â›å7M –ßäG¾¼sçNõÃJ¥RÛÊ<Ѥ`|SÐ1Æ)ÈßdŒoò#_&¬ápÑh´nb³¦iˆÅb^ŸÑÀßtŒq 2Æ7ã›ühK¥R©x}Í‹EÌÏÏ#£\.# ayy¹åü>¢IÂø¦ cŒS1¾)Èßä7¾MXkâ·˜¸F½>¢¡b|SÐ1Æ)ÈßdŒoò_'¬DDDDDD4½|9‡•ˆˆˆˆˆˆˆ «Ç …BÓÛ‹ÅbÛÍ›=>NÅb±ížlƒ\‹Ÿ®“µŠo 8ïû(ãÛo×JõFßݧAb|’®“êMC|³üž^Óßâ\Q~WÈ3'Ož¬ìÞ½»á¶}ìc•Ý»wWvïÞ]ùä'?9Ôããôè£Vn¿ývû\n¿ýöÊ£>:”kñÓuRsÍâ[Ü„÷}”ñí·k¥F£ˆïnŽÓ 1>I×I‚ß,¿§[Ðã»R ^ùÍV”J%hš†t:ÝpìÀ‡ÃÐu=ôŠÅ"–––†v|œæççFís‰F£u×<ȵøé:©^»ø‚ó¾2¾ýv­T3Êøîæø8 ã“tT3-ñÍò{:MK|,¿=Ký§Ø½÷Þ[ùÄ'>a·N¢ÅÇÙòÙÏ~¶rûí·åø89r¤²{÷îÊ™3gš^ß ×â§ë¤F­â»R,†ýô¾2¾»9NÞU|ws|œ‰ñIºNª7 ñÍò{zMC|W*Á,¿ÙÃêx<Žååe,,,ÔÝ~òäI@$±o‹D"öøðAS$iسKœ_(èZütÔ¨U|ƒÅ°ŸÞ÷QÆw7ÇÉ;£ŠïnŽÓ 1>I×Iõ¦!¾Y~O¯iˆoñºA+¿™°úH»7»\.||œB¡Pݾ]¥R KKKˆÇã‡Ã]ËñãÇ}sÔ› ¼ï£Œo¿}–©{Az߉ñNŸU?]'u/(ñÍò›š ÒûÄò› «´{£777>îÕ5---áŽ;î@4Åþýû¾Ö^xÁw×IÝ Úû>Šøöëg™: âûÞOŒwú¬úñ:©³ Å7Ëor âû¤òûÂ1ü½¨KÎîu·p8<ðñq+‹8pàB¡>Ü0| ßk‰F£8tèo®“º¤÷}TñíÇÏ2u'hï{¿1Þé³ê·ë¤î)¾Y~“[ÐÞ÷ •ßìaõ‘;w¨–P*•ìôø¸¥Ói{½;À¹¿]'u/Hïû¨â»›ãäOA{ßûñI»NêNâ›å7¹í}ZùÍ„ÕGÂá0¢Ñ(ÖÖÖìÛ4MC,ÊñqÒ4 ¥R ªª¢P(Ôý z-~ºNêMPÞ÷QÆw7ÇÉŸ‚ô¾ã“tÔ½ Ä7Ëoj&Hï{Ëï-•J¥2ö¿$ …æçç¡ëº}[±XÄüü<Âá0Êå2B¡PÝJ_ƒ—¥¥%)×IÍ9¾Y~Sãfù̈́ՇÊå2ŠÅ"Ô­ò5¬ã~2ȵLÒuR½iyß§é³L5Óô¾òY¤ë¤ši‰ïi¹Nª7Mïû$•ßLX‰ˆˆˆˆˆÈ—8‡•ˆˆˆˆˆˆ|‰ +ùV""""""ò%&¬DDDDDDäKLX‰ˆˆˆˆˆÈ—˜°‘/1a%""""""_bÂJDDDDDD¾Ä„•ˆˆˆˆˆˆ|‰ +ùV""""""ò%&¬DDDDDDäKLX‰ˆˆˆˆˆÈ—˜°‘/1a%""""""_bÂJDžÓ4 ¦iz}Dc7ÌØ7Mš¦y}IDDDCÅ„•ˆ<‹Å ëº×§A4vÃŒ}]׋ż¾$šb¹\†ax}D#ÇX/&¬DDDD4°|>ÏJŸ¯›²ÁØîQ…<·±±QP9~ü¸}›ªª•t:]9~üxÃ1Y–+ªªV*•Š}|ccÃ>¾²²R‘$Éþ@eeeÅþ]Q”J2™´O§Óöóõs¢NÚÅx¥bÅœøw¥bŰªªŒošxýÆ~¥Ò¹|w?v}}½ rúô醸&†Nñ¬ªje}}Ý>æŽQ–×4)uQ §OŸ¶ë5âþŒíîqH°äóy¨ªZ7Dl}}€ÕÂâ>–H$ìMÓ ËrÝêâw]×í–uçã%I²‡$´Òëý‰Úiオªö¿Åýß4éú} sü»+ˆVúÅÅE¯/Ÿ¦›xvsÇ(ËkšƒÆºx\*•B"‘€ªª glw «ÏuÚî@ ;C„f•¢IÃø¦iÖoü‹ùS©T Ç÷ú2ˆˆ¦Ž,ËX__·§ò™¦‰d2‰••¯Om"1aõ wbªiš=éº]Òª( $Iªkµq÷>ùA«w.æÆø¦ è'öþãee¦i"ŸÏÛ  K¿ñL4i‰uQ‡_YYÁÊÊŠ½í˜¢(ü¬ô‹.ù@2™„®ëö/Ó4íE8Äð_ç1ç‚3ÎUÈ1ñ›È/ÚÅx;ŒoštýÆ>0XüK’d¯XÉ­hXº‰çnb›ÈïugÏ*`õ¸rÈoÿØÃê²,cee±X ªªÚ­2bùk÷1Q‰j•’L&cWj Ãè8ΞhœÚÅx;ŒoštýÆ>0xü' $ ¤R)~fh(:ų$IÈd2öðG¢I5h¬'“IäóyÌÌÌ@Q{dL"‘ðúÒ&Ò–J¥Rñú$Èb†Ý.æ(‰á_²,Ûû°Š=šVWWíÇ:áÃȈü¦YŒwƒñM“®ßØÿä?­âÙYgqï5L4‰uÑC+I§2 € «Ï†™™lll@Q†X,†t:ÍÖK""""" 4 ö9çÓ4íáLV‰ˆˆˆˆ(èØÃJDDDDDD¾ÄU‚‰ˆˆˆˆˆÈ—3$8ŸÏãOÿôO±k×.¯OeäŽ;†›o¾ÙëÓ¹'N  áŠ+®úsŸ9s[·nÅÁƒ½¾Ì®Ý~ûíSßgΜA¹\žŠkågùرcøÛ¿ý[¯/±k,ÃgÔe¸$IøÃ?üC¯/³+,¿ƒgÔå÷ýÑ!‰x}™]aù<~+¿“°^ýõ¸í¶Û°°°àõ©ŒÜüü<–——½>‘[ZZž={F‡þÜ…BGõú{²k×®©xßÅ{ÃÏòàÏ=IX†Ëð–ßÁ3êò{R’U€åwù­üLÂ:M¦áƒ`* >jFGR@úÑ´|–©Þ´¼ï,çËo ºiyßýV~s+ù{X©+º®Ã4Í®ïïÜèÞÉ0 ˜¦ Y–!IRÓcÍ8ï/6i›1·;gÃ0 ˲ý¼â9Μ9ƒ÷¿ÿý^ÿYÉ'zo±‘x»˜unîü,èºEQìÿ7»¿¢(0MÓÞ¬\<^Ó4¨ª I’ Ë2t]‡®ë$ɾ °>/¾ø¢×V"""¢1aõP³J²¨7»¯“,ËPU‰D¾M$p­ž£ÓsjšEQIÁY¡nGì+K7I’ZVòUUmú|â\Å¿ À$ImÏ)™L6¼¾¸ÆÇ|¢æ?M"g:D"&Þ»f ²,CQ¨ªj'w☻¡Â™Ø¹o#Ýè6¾g¬º?7îÏ`"‘hûüÎëI¨ó5ܱ,îŸN§ë^WÜ®( öïß?Œ·‘¨g"[}8µjÜÐòûHÓ4=zßÿþ÷½¾TšîÕ4­.¶ÝßIªªÖ}¸ËoÓ4177×ð:⻞|òI¯/›ÈW˜°Ž‘išÐ4 º®#ŸÏCQ”¦_æÍ¾¤Ý^>Ÿ‡¦iÈf³uw/d;Í:?’$©.9p&é½j–Sÿ4M³cÚˆµžñv ÍâP×õºø{ ÝŸ?½·Ý|þœœ×ÖÍu´ú[öštÓtsW´ŸSççºYB)%ñªiZÝw›ûqîF$ç(wì¶Jbëóuîܹ‰øþ¢Î:–êD$zf÷œ£Sº‰#÷¨0gBêü܈ï.çyåóy¤Óiû±â3²¸¸h?Fœ·hÜœ´EóˆF ë†a'”‚(ŒD‘(¨ú•øÿÚûû ÇÎû>ðýÒ"MQÒ€IQ¤Ð´ŒhN²–“íØ^ÛAÛ÷Z&íB‚Éæz¼ÓYû¢-Ø 7ñ]µSYgíªÆn­w—(·Ý(W©gwÊÙjD‘çnÔgCÛëd‰ÖÙ¾Y£—>”ÅÆŒLqx4h’%S}ÿ8ý/çßOU× ^Ï9Àïí Ë_’Uu•*îÝ?lÔÕ°FoyýujC¢Ó~¤Óƒu¾zÝê(ˆÇñw>ð\ý7ÿøàñö¿ù7ø;—/[ñ­6°ªÛJ§ñÄÑ‘÷Ÿ!-5áÌf³}£{ìW=6Ç~ŸŒ^˜¤auš)KŸ°V*4  üËÿþ¿Çc¿ÿûVAvýºcå0#þK¿ä\ÐŒ"?ØRÉÕ›ÔÛØèmÌ3ù¤HÒu;ù~õ¾ûðß~÷ÄãÀ½÷ùÈèFIXÕç¨.Ãâš {Ödrðunzƒ§é]÷¾Ã>ÇY*m³ö‚e³øÒÞÞlïA®¬¯¯Ã0 ìïï»þ±žºBoïIz  €óˆµ²­&«R1Ñuàä¤ÿ5šf½.ïUò¥KÞÔè{å^~ïœâZ 3øA9ßoš¸·Ýæ4¤QDþµ÷æO“ˆN±ý·‡•¥ê(0‰I<%fíõy¾ú~j#½4’ªÔXNû7MªPèþF½À§¿ö5T««XÿÿÇá¯;ý ýd±ˆŸ×÷@‘§®% iZßüqûZ24]F۩댺RHЖ6a5M•J?Üja3· 1ù1WˆOS™Ìç­?'œ_IÐ4 ëëëx¶^LJ~ø‡gŸK,qÊ¡^´êõúÀº–h¶»¯6Ô˜¦Õ»¢öÚ+¼j#¥üß>tÜ)!Õ8"=˜v››½ÆR·e@6;8êÂi*öN=Zã$“xù—w–h”Ì8².ºB­zy¹¹÷æ;õÔË4&yÌsºî<¢^ïM­P{äÓéáñ¡$„®uåµ|>ÕÕվŖˆœŒºäå°^P§«„xÞ å³¥LXMÓÄêê*òù<.Eì ¥%&ó: Ô5­»áßàœ5¢‰T*hšÖ]ñV*÷ݺ…¯=ú(¥—T*ØÉ¤uþ5V¥|\¦ö>ÉsǽfÔã£Îs–‘dêõ:Fw- OV¿Õu+^ £¿ÓÞ¨’LN7ÊÆžDF°QT¦ðêËK]Û@z@eÔƒjØ¥–²ÙìÈKútֿɤót]·FúØ©£ƒt}ªud–+aÕ4tÞñ¬þÿ … Ó E$ «ÓU”Ÿýã?F½^Ÿhˆ"Ïîìàÿ÷±áÇ:lþäOvçU§e­‚Fê«• i(’¹lC¦“ô °§‡Ÿ çÓ4 år‡Ó¬ ¡rZ8Qs“ñÒi«!†üScïêr‘¹¡24×¾jvàW`„S]/@M@ÖÖ1ŒþõFÜ&Ïj#T¡€_ùÊÄëÈ,UÂúæÓOã—þóÿœÉ*E¦áÿ.•ðÿÑ?b²JtJ. £¶nôÂüƒãcü_?ò#xí½ïí¶vÿäããçãq<ñS?ÕÿC, k9%£Éäà¢@DkŽ6 ”Ëåé‡ü™fo¨$«öžvQE¢%¥.h¦iZ÷—årÙû^Q™Ö(£!€þ醅Âà´D™#®Îç·@ä4S8äuª)VÁ^ž„U×ñï¿üe\ÞÝårëIßüìgñ3ÿèaww—×x£¥f*• t]ÇráÖ¾ö5|àÖ-ÄN˜¿ñè£øìOþ$ÎýÈt_³¹¹9¼‘‡¿0Y“ P(LÞ£*•Yù?`U^Ëe'rAmøtš_Ç»ÃugZÐLmLrZ=Š/£ÒéáW;p²`w¡HX[­R©”ãý±X ‰Dbæm¼¶»‹/>ø ~‘ò™ñFÿ>‘@ùþC^g‘|çKŒ»Ôh4P©Tð[ÿäŸ`W®]-—>€lßàožþ†Ø–Ë&íîîŽ/ßMÓy€Ô}&©ÐÒRCŒ‡‘ô–Ê%ËF]ªl$v+‹‰©—´tº®ºaLÖ˜”L.ÅPýÀÖZ­†V«…­­­î}ívår­V €5Ѹj¿Fã„:{{x;— úpiÉøßÐuü‹—^ÂorAò™o1î‚z‰™d2 |ãKñCNÞClËà‘Ó<¤W¦Ñ°þo_á™W" !Âãa¡ë:Fw¥Ýd2Ù]|o(¹´˜=Á¬×{+`Ë<ðq FÓ¹]ß䯛Í&vvvîߨØ@"‘€®ëxþùçÑjµP«ÕfÚÖ=/¿ŒÕõõ —–ŒŸñýÍßÿ}¼þýßÏy«ä+?c|œõÓò½›¬ 7ä‰Â# ±­iÚèdUÓ¬ËÈœ?oU˜··§»-¥0ÄxPdá²ÕÕU¬®®â@µZí&¨ûûûØÞÞv^u[×­Dt}8{¸xÑùZÒÙ¬Õƒº¿o ãÍçÙp4ƒÀÖN§ƒJ¥20Ÿ´Ýn£Ùlbmm ‹ÅËåú¯s7¡7vvÐ^{í5ìîî¢P(87U*Ö9·ºj­’kVzxh%¤N—r™äÚ×4V`C‚766;¢+ÃàèèúÆÓ§R)´Ûí©·õùÿõÅ×þößêPi ù߈ÇñOî¹ÿ5‡“|ñdW*TaˆíõõuçÕEåZ¨öË+M 1î5Ã0Ðh4 iLÓD:F2™¾j¯ ­ÇWÔÝÜä¥ÈHëÞÞÚí6J¥ÒÀc£NŠN§3ô±/}éKøä'?‰b±8ðØ_üÅ_à¯ÿê¯q¨B{{{xæ™g ËÐ=xÿyÇ7¼üòË(‹ØÛÛë»ß0M´Þõ.Ž  ®b±ˆ7nxöþ~—áØ¦‰J¥‚ÝÝ]Äåz¨œúyµZ Ï<ó >÷¹ÏÍý½ý.¿ÔO¯©íxù=Y`…å}dIù­&’ó–ò{ž4MC½^G¥RÁêê*Ξ=Û&²½½ëׯw‡ø$«†5¬W†ÖóÜò”ÔÁ'-¿}ïam·ÛØÙÙ:{Ô q||ŒX,æøØw|Çwà'~â'N@Ó4ñ¿ñ þØù}¨R¹\‰D^´Ø ¯â{ì±¾…D£Ñ@ž½«¤ØÚÚò¬âàw>J¥RÁoýÀ ¹ºjU2œ.tN‘S*•páÂ…¹—áA”ßNªÕ*G ,1)¿VîU˜ÊïY©×%Îf³ˆÇãÈf³( £ðëu+1¬d5›µÖ;àbG¾˜¶î{º··‡X,MÓ iZ­ŽŽŽP«ÕËåFž Ó,­­i+óä¿ã°V¶Ûd%|DŒ;Ñ4 Ÿ?8ÀÏt:Is†Ø–Kht+ÜëëÖðDV¦iÂãóP©TºõcWñµK§{¿¼ÌÓÂð=a½páÂÈÇWVVX­@rr¨ÿŸ”®ë¼.%ùÆïøþêK/A×u&ßøãÃT*ü«ïý^à‘GXá ¹Cl7^dµjÍ«c²Js†ŸE½^GµZu—¨ÖëÖê½»»ý÷3'XH¾'¬™L™L¦{[–ÊV‡d2ìííuïÓ4­»¢×¤t]wžBä¿ãûÛ~ò'ñŸŒù"š'¿cÜI£ÑÀO>þ8ù?ÿOk•F¢9:¶e]…t:m-¬ÔhX£ˆæ$蟖¬W`šfÿ¥ËŸh7ÕªÕÐÃÑg‘Ø*Á£”J%‹E4›Mt:Äb1\¾|yò7Òuüâ¾ÀÞ' •¹Å·iÞþÎï úˆúÌ-Ƈh4øyÄZ|†ÈG^Æv½^·ØMÓZfw——Å ßy]~OJ×u¬¯¯#ŸÏ£ìtùÓ´zRå/Ÿ·®GÌs'ROX&h§R)<ûì³ÝÒÔÖ ‰4xá•Wð÷ƒ>HZZ^Ç÷‹øÀds7ˆæÌÓw`t]G‚=«ä1?cÛ0 hšf]Kx}Ýš[Ç¡‹ä1¿ËïI5 T*loo\3€5áâE+IÍçÙˆa'¬ÃÄb±ÙO]Çíïû¾ …hÀ¼âûSü çhS(Í%Æt{¡ˆâEl7 +® Ãê%bƒ È«ò{õzõz}ôàtšçÊ’ä:¬¾0M¼ÕjáÖ}÷½'DÞÐ4´y$è½ òU·bO!º®[=Hõ:à4ì‘h‰È*À#“UZ*ÑMX5 ·~è‡ØûDѤë@6ËU°i©´ú§»×Û#Š’nYžLZC‰–T½^‡¦iØßßï/ëu8>èÝ£€D7aÕu|áþûƒÞ "o4ÝùM¬¼Ó²èüÙŸ9Ïc"Z`} …‹¡¥¥ë:ªÕ*öí«cË\UÎQ]ZÑMX hñ8{Ÿ(šNWÂ“Ë Ež¦á¥¯~yö>QÄhšÆº -=Ó4±¾¾ŽÝÝÝþ†xuÕlž'K+š «at/$ÏÞ'ФÍM€ 2´DþÃÿ1ÞñøãAïÑÜuç¯-±J¥‚|>ß_¯‘aÀå2“Õ%7Ñ*ÁÍf³oÕ°f³ MÓ‹ÅpáÂ…ÀWë2M«÷‰‹sPTe³0 #è½ òÍkûûxÇ… AïÑÜq-Zvš¦Á0 ë²N¢R±¦?±g•ಇµÕjá©§žB±XìÞ§iZ÷ÂÂûûû(‹ØÛÛ úx,é´5àêbY†a°’CKã®—^Bê# z7ˆæª›¬®®Z£Ãˆ–P¥RÁææfïŽõu«óéúu&«ÀeÂZ.—‘J¥píÚµî};;;Ýûž{î9”J%Ôjµ §{ ˆˆ¢á¯~‰§ž z7ˆæª;U™ÊD´L*• ²Ùl|¹l-°Äi}tjlÂÚl6Ñn·qåʤR)@§ÓA«ÕB.—C,är9t:4›Í ©‹½«eš¦1Æi)hš†3gνDs§ë:žJ$Ø‹DKÉ0 4 ”í×f݆lÆ&¬­V ™L¦›˜Vå@ß"êãa ë:\¢ÈcÂJË uíî~ßû‚Þ ¢¹Óu©v› +-¥z½Žr¹Ìú:56aÅbèt:}÷µZ-¤R©Ð%©*Ó4Y™§HãwZϵÛxë_ý« wƒh®ºõ]¸J0-Ó4ÑÅQ ú\ÑcÖT*…V«…V«À¬iÚÀŠÀ2xee%ècÀÊ_.…[±¿›¶çȶë§ÛO*û,’Êg¡+·Ó×9QöçþÛ÷Oñe…VZÝUT‰"Æ4M|è‹_dï*-F£l6‹d<T«Àþ~лD!ç*a•$ÕI.—C.—›ªgµÙlbeeeèk[­b±ØTï­ëúàªc^ÄL. VÂ$IÚ*¬dJ~ ô’S9?uôSIXÕ„Ó°ý_’²Êéûl*Ûƾ-IþLåý$•Ä/®ÜV÷Q?ݶú(Ï•Ä;k{ÜMãYýÉxáôýtÛg"ï' «¦ÜŽØ–²?_¿ïë.vhz^Æ7À—(x^Ç8`•åµù‘ •–Œ_±}!~á‚>\ZB~Äø0õzÝêäª×|ž£ h,W +`öÁÁàÂ… Ý9¬ÓòÞÞjµZw1'é•EœÚí6ÊårwÞl6›EµZx;ž¯:¦ÁJÜò¶ûÔͺi4*Øng1>¹SÞY¶Upñš$5÷wÚ¶“ì˜ÛÃŽËé¾Q ÐIô’v`tªxë]o¹Ø¡Éùß¾¯‚]E/ê°>ciœz öQö^p'&¬sHpñôÿ›Ê¶œ~Çd;Àਹ¯“‰¹­žËò>Ãzò—˜_e8|ó•WðþgŸ~åW‚>ìù‘Xr:/dtIVüçOB•œ‡ö‘,êm§†>Mù?N·c TͰõOä÷IF² Û–zŽBÙNC9&u4Œý¼RGùÈÏØ€Øý+ëä+¿cÜÎ0 ˜¦iœ¹x‘½«äÊØE— V«¡X,bgg;;;(‹¨ÕjSm°Óé V«¡T*A×u<ÿüóÝûÄÆÆ‰D÷ñV«5ñö<]tI°«b°þdnÓv›–Š_ñ=Ó*Øõ Ÿ¿Žþ^þ8¬ÊsV¯þêéÿ«Êó¤Â«m¯*÷«" àý†Ãó°[!{¡Ùކ^"«Ž(cÒœ=}ï³ÊþÊ1˜¶Û:€ó§Ï]=}]Ŷò+ÆÅ£7oú3dR þ$Ned‹oÑ꟨ØnWÑ›Ž!ÓäO’¼4¬ß—‚r»|ú·úWFod‰°'‰ösg½©PÞ[ݶ}ŸÔ¿¤²µqÕ´mëüég#ÇŠÓc)+¯‘÷Hcð\WÏÏlŸß*ðá¿ûa<üòÃóŒßc›ÈoaˆñF£a-¶¤iVÙÎrÁUëÎÎr¹\wXðÆÆvvvpùòå‰/mÓjµÐétËåXÃ3™L·%§Ýn£ÙlâÚµkÝÇs¹öööP*•\og.Ã%í½DÒ”†õû=û&(ZüŠï‰ç¯ê°ÏëÊÿ·Ç<_zoìÏË£¿'Ò‰½çÞm¯¼›iñöç¸5`Å?=Néñrê¡·÷ä§a}žêg¦&Ëòܳ§ÏÝuyÌga•;'§·%9²'&ñ+ÆÅoß¶äpCšœ¦lvš'¯>8Ou(c|Oàæ˜Û£¶©²ïŸÓví ¦n¶e7£ì#Yâ¶mmÂ:>5D}QeÊk¶ÛûÀŸ5ÿ ¯¼ââàÜó;¶u]ï­’Jä¿c܉®ëÖpàjÕLäÂØ„U.W³¶¶Ö½¯T*aoo­Vkàò6ãd2èzÿ¨££#œ9s¦ûÝEäÿívÛõ6ú†KÊ*§úŽ É’JªÌ/U‡`IåU~À¯côbG´ÔüˆoÀŠq× Ñ˜°Z$aÚF¯÷B’§ÎS¬Šo$_¹NîhØÐõCÛí³§ÛÈŸþkÂê=Ú…õy:¼oV/®lG]ÍG~ŸøÎXÌ]«ôðMÚ0²ŽÞw1i’2luaŒ›Î2~Ç6€è,(¦þvPhã*Ó4{—sÊf™°’k®ç°ªsU'íU¦X,vOiÍuRt:WÛî—4aUÆ è Ñ“dSæÒÈo…TÕß{OUš€Wñ-âñ¸UIˆcxƒŒ+Öí½@òµ.ó×È[‡°Êžz=‚£ì•~ù^+pßkë¯cÜ4M<Þé¸KXenä$1,•-C6^Ç6üý/~¨T€Y¯° 5ÒÈ®N}8„UÎKƒ×&¬òD’¡6`&ÑßhßÀà¼e•:ÿƒsýuX r2§Y]Í?«ì“çпˆ¤t(È9­¡d‹Ó¾ív\yyº-9n ÿwS~#e;ò[šµí«4l”Û"m{®ºè&”ý“¹âêgU¶§<ç¡ÎC³Å„ ~ĸ¦i½QLVi®V/\¾|ív;;;¸zõ*J¥Rw¸“ããã¡'Ë—¾ô%|ò“ŸD«ÕÂ/üÂ/X k½B@ænÂ*Lä–ÎÞÞ>þñãž{îñt;óŒoxùå—Q,‘Íf{CÉ*°~ð°~p¥â½ŠÞ¢%û^‰Ÿ¥G‘¦'aR™š¤“Å©×JzmO¿ÿb±ˆ7nx~^•á[[[¬‘þ«¿r7$¸Ž^¿ŽÞ ã£ÄÑ?¬›B­Và /¼€xÀ³mxY~ËpÌ7ŽŽ¦»öäyX±+‰¬‡#Ó•œÊ{{N¬&KÃ^#ϱ‰WÙÇ’+'Hr—FoH·$ÓöKÕ©ÏnFJ jï´Ð˜¤v½ÄV½ì§ýÊÛÊçTöÏTžoïe¶CÚö¸ÌÛ¶MCyæÅgðç_ýs´Z­¾žÎyóºüvÒ—°ÒR’:ø¤åw  « 'ŽÅb(—Ë(•J#OÎQ+Çw|~â'~¢;Æ>N[•8©Œ¸™wGKA.Ã$«^{ežñ =öX÷‡àw~çwާ{ÉNÖ±\ˆ‹î-†y­„zˆ¾JÚVl ϼçÏwßË2îyýu|õ0¶¯AzL¤2˜‡•Ànï®-S÷PÓtJ¥.\¸àiîeù->ôàƒîwH½^º½‘ešÚiç)˯ÕdÎNÊ:¯IG½¿Sâž´½Î))Öff_|l7e}xºð4noxš¬Þ—ßN4MÃö6‡´,³iëà®Öb±8p_­VÃÕ«WûîÕ²"¯±·ÀÈØyXYY` K“Cý¿k£æ®yįø6 £7Ü]Ì8ªŒœZaJO|ò O6ã[à®OíGÁ‡Æ=QGÿ¹ V 7Ñ»,‘¬Ì›GØÐ?cýÚ×Ü÷°Êh¢øãªîÚ‡ÓÄÆ^ÖfeekkkH¥R}kkkÈd2÷sáÂ4›ÍîŠd€Õâ"'C"‘@&“ÁÞÞ^ßã«««cß»O¬ïüŠïíííÞœ="»<ð‰ïÿ„'oí[àùN7~äG\ïÐsAÎ(säZ°ŠÂÍÏØÖuÝJXݨbô*ÖD.ùãvF—  >éµõˆ\ô°&‰¹-e XCr¹.]º„L&ƒ££#÷µö”J%‹E4›Íî$ïË—/»ßˆ:÷€ÈG¾Ä7€¬‘¼¼‘üŠqøÚ;߉³ãz ¤q’çÍÈÏØ6MÜ¿‹'ÂMùÖ4~Ƹ¦iøÍ• Ì¡4¹@æ°^¹rkkkÝÕÉì—ÆI¥RxöÙg»-@“^:Çõ|"x߀ջÊ!À_büTâV¼;M{ZUš+¿bûž×_Ç×ÞùÎñO¬€ 24W~–ߪÄ[oáÛßxcº…ÆhéMœ°6›Í¾‰².\˜*˜‰ÄÈ1ñr1c¢Eäy|»Y•ÈC~”Ắ#¿™·zQ«èÍá“Õ8¹vyÀØþòü ÎÏ–Kž¨ ‘²ò,ãœæÌï:¸¦iøÿ¼ý6ç®ÒÔ\'¬š¦á™gž¸FÓÎΉªÕªç+šÑ)–ù´þö+ÿÒZÚª°Ÿ‡ÕHS=ý—# h½òÍoâ?úþï·nÔOÿdq0éMÕÀ8§H0 1M ÀÅe–Ú饭þ?Æý÷º˜¡p•°6›M”Ëed2<ýôÓÈ*Ýùš¦aoo—.]ÂÖÖ{E‰ˆhvš†Ÿélï’»°®/,×Ò&Z`íGA;›EJƒÕsƒÃ~™¬RD|Û¿ý·@šÃÂ#—~›tjýZñ•ÓuÛóÔOO_·¯¼F}~¸÷潯3ä*aÝØØ@6›EµZx,›Í"›Í¢\.cccÏ=÷Ü|>\""Z^†õÍ_ïN/©–ðZÐ;E4†aàž×ï~ VcŒZ‘¬ÀŠwޤ¡ˆ8Ól"þ«¿ôn,±¡¡w)Ĭ$Ô8}Îi¯'ôÓ?iÖa•Erýr ÿZÅi8'Àöë›;4¼½Ü|wîLt(cÖf³‰v»ßùßù¼µµ5\ºt ­V‹Cƒ‰ˆh6†›ßó=Aï‘'LÓÄüžÿØJJíOÃ*‚D ê«_ý*ÞõÔSAïÆâ°ÊµŒd3yúW‡µ0a½^Kýô9eô’Ô‚í=4åý³§ÏUË4z½¤"Àõ²Æ&¬­VkìälÝ$µÓéw4DD r?üÊ?z/ˆ¼3ìò{ìY¥ÑuÿÇê*Ö“¼ÖäXÓ?VÂh*mžÞ'‹±Iù!ɨ$ ÆéíQ÷^Mel‹Åp||ô~ÑùÆ‹÷áí÷¿'èÝ òÄß»~zaUÖá)ât]Gr™“Ué픡·çwn£W”1ú*ÃÖpX°tRcÖT*…N§ƒv»=²—µÙl°ÜeaÖŸiZÉdïòRºnÝg¿-¯I§øi×»ü_Ó¬¿lÖúÓu Ré=G•Lö[«T¬÷ÞÞîÝÖuç}ÞßïÎæ¦õÞõ:Ðh8¿&Ÿ·¶%û“N[¯€ÕÕáŸ}[ÛÛÖ~ ]·^¿»k¯ìC¡`mSÓ¬ûLsþûôÛ¿ýy䋞ÅÍæ[ßþxý»_z7ˆ<ñ}ßú–ua^²†"Î0Œ¾ÅZ#IÂ+‡zþô_Ò›Æàð^ûüNŽ®ÊUšJ¥P.—±µµå˜v:Ôj5d2™…›¿jšVÒ# ¥$zn"5‘4ŒþU½mOÕ„2™ì%¯Ùl/©K&rŽâÊ8s{9Ï÷î‹ÇfÛ´$…ÂøÕÆÓé^Â'ì·l:L¸6MàâEëõ²ö}°W2ÙŸðβO¿üË/ãàà•ñO$Bï|u:—¤ÑÊþ˜¦ >WbÚ4ûÏa²Ñ4Üõö‡ñ…>ôžÍŸ®ãî»ï\i“(‚t]GyXev‘Õa%ªrhúGL\z£ÅÕ*ÁW®\A±XÄ¥K—°¶¶†L&ƒD"v»f³‰ãÊ•+AÏHÒÓ'=x†Õƒ'=œÙ¬õ˜šM›Ù“¿MËÓÛ4Ù§I_æ•Ã+k++·¯Qo” š½WßÞ€£’ç†uÞ½¸–‘jÃ40Ø{Úí·UòÚë×û{þí HöçV<Ù•FmKÌkÔÄò°-ù  ZÿYûþ û,Ta.\1 œ§ðÎGßôžÍÝ­_Äçc1œcï*-¿wý:â‹ÞB«¡ލ«7Têúqr*µ)õ-©©u#a™©Þ®V{u>û뤞R¯[Û’<Émi}ÝÊgä}VW;wžÀþè':VW k*•ÂÖÖjµ666Ïd2(•J¡ï]µ'ù¼õGþÉf­žU7=º4Ó´’Q)|âñÞÐsµ±@M¶ «@rj,‘†yLmØ‘ç–ËÃ{í矛F{œ85 9±?ÇͶ‚uàÅgQ,ŽÏÐzûÃølÒ@zá3o¢A_ýô§ñÈ#Œž§F·þ—ÿ+ï~wл195)¬…Ò€q`< Ð?µÏñ-Œ^=Im\–JÃõî®õ¾ö†ly?ðž“N[ÿ—NIXÕÑ]ê(KûÈLõ¶úS;¬—N÷u[GºnëiÞßšÍrt•°½¤µÝn£Õju/_“J¥H$ÐétÐl6‘Éd&Ú¯I €›J$y/›íLóc/¸$ù”dRÓ¬ÂLMVíI©›F§d–=á4W ¸ùðÿ÷àž ÷„hîî»u ïø«ÿ¬wi ¢ˆºóñã­¿ñ7‚Þ GjO¤iø2`¼iý³¤sƒk«˜: }0V¯¤jÔTBµŽ$£Õì¦iȶ¿W29݈N7u¸ ëí®V!—¸±O nµZ(‹ÐõðLÊ0M+ ®sy¨ôQÕhôãµ'ŸL*ia”éC†AÑó­Û·ñÄáßa²ÒHLÎîþó?Ç;í×|ݦ¦õ••ºÐꪕL¾öšu[×ãÓþH¿ÄˆÛ¦ª08²i\Öiôcdv'¬‹¤ZµmчÎ £ë½!¾Q\Ó€–—išÑ_Y2âdhš:,MVæEÙ©s¼¥—CÏý{¿7ù¨°øÖ¾€»ÞÃK6ùE®Ð0ic¹Äª ýÔõÞœ=éÅjœö´©óóìÛœ×H².„,Ö_ýê/ý±ÍÅ»ÿò/ñþøOÞ[]¼°Rü¾d«è&‘: (h°M’ë˜R¨E6a5 « 9< zOˆ¼S¯s6ÍÆ~¶QI¤š4V«Vù³¹9|0™B0,aœç‚©åš}®T¡|ï÷N>*,îýÆßÄ_}è$èݘ™Ú»(‹õIÒ•LZßk>ßûn ë5…B/†4­÷\I u½7uEâls³ÿrw’ØÉÎlÖzM6Û[PS†hÊh;õ’‚ö+BhZoQHIFe ý”XVcsÛ¶p–Óô3u!B`p?Ù/5¡-ÀVÐ_ñÌ^¿çž¹­E Îá¼x±ÿ»’ïßUUÖ"IêµO)ô"›°®¯$DQ"sVçEaš^Fê*²B¤ôÔØ‡ÁIò)•a©øIåÚ~¶a+Ô«‹­M» šÓâfËæSs çÞûµ w@ÿ>IÄœ$Öä;^_·þµ_ºO.«'+ÐËåëd[ù|ÿ¥ì$a“DUa—»Æ_aÀ¾ f2i-RôLìÉM6;8}ÌÍ\@7ìç“ý}#;D×ñù·ßÆãS¾\ê8²x¤4Ž%“ƒßÕÈϰ ë4»°: `5_š]  k«Õ€¡« ·Z-Äb1$‰‰ÞW ÖÈ´¼ŠoQ­r0ËË_¶‚eΕ}ø¡ýºÞ¿êc2ÙK$¥b¬Vħ¹ GmxÛßüì7qïoÞëËq˜f¯gSíåK&­ÆNYUÔiÕw•ý>{C©SæfQ?™è6æf­×±^Øãu¦‰¯œ93ñ˪Õþ7—@Üöé¿qô.?Ãé mlÂÚjµP«ÕƾQ§Óq½ÑV«…r¹Œv» ÀZÈ©Z­vOšv»r¹Ü=™²Ù,ªöå¸FpÛÒKä¯ãèU2Ø»JAð#Æ£D¶ô†4JÏ–iö†EJâišýCeÝ\BÀíµ»i8?bûñÎãxô§û¾Û{Øåˆö^K•Óª¢Œ¡hó­üÖ4˜.ÆèÊ"Ijù¶»ë<ßw,Voª  +Yå°ßHø¶y½Q,s}I›b±ˆL&]×ñüóÏ#“É ¬tmll ‘Htw›4…ñÍÞU ’×1¾¨Ã5Íê¨Tú‡U^¼ØõtÚJ ¶·­¡m‡‡V#« wzså¸h ¿ü(¿ïC¿7—Þð~ Ô\B/,×@”¹’D€up-›Å¿sIi|W˹ryÊdµ`V‚z½k¨R$Œía•ë¯ÎK³ÙD§ÓA©T`%ºkkkØÛÛë?h6›¸víZ÷ñ\.‡½½½îkˆÂʯøVçùÉ7M3´C‚í+Ž[rÔ°ÜÚÒó«üÞjN_§’!¾õºu[¯)s™‰†ñ»ž•JoºÃÌs…°’Õ<¬D•|‘äûVI€c±X÷¾££#Ö‰!ÿWÇÔ§R©îТ0ó+¾9˜‚²Œe¸,RdšÖ"FêÂ1²x{B_Øc{}ÝjÉçg2IKÍÏ7œ–‡•¬Ê4ˆ¹ÐìƒC#nìàf³9ÐÒÝétÐl6§Ú }èp»ÝF­VC.—C"‘yRŒš'ûæ›oâæÍ›Sï-v»7nàöíÛso¯âÞxã 4›Í…®ø“?šÍ&îܹãÉ{ûQ†9$X†¨U«V‚pöl¯7+·†XªÃñy­oÿµZ-ܸqÇÇÇs}ß0–ßrOÀî{xØ?tœ¢GÊïIÖ†qËÏ:¸aùƒ\ovæF÷:¬žUÀZõ—çÃÂ:ø¤å÷TsX¯^½Šb±8Ów:Ôj5<õÔSÈd2¸råJ÷þaFÜ›o¾‰[·náàà`¦ý¢è;::ò,aóŽoÀªðt[@‰†988𤲣ò² ÇãȰòËú:pþ|oˆo>ßK(<¼JXEXÊo]·âQ:ª8 d9HùíU|>ÔÁ ‰/q¥5O®¡+—šš+aåâ` Iêà“Æw —µiµZØØØ@,õk׆ 3jií‡zétšó\i,i]ôªqËø€‡~˜ñM®”J¥î ^ˆJ.×ø“„´PàpûE ½A^”áa*¿ ƒC—‘”ßS_Nf _Êo]ÇÃôGHþWÿk¤ÀúºÏ3HÉš«J iÚ:øÜV žD¹\·Ÿ+++Ð7,¡Ýn{vâÍ㛢n‘c\bÙhô/€ÄÅ( ±-#âÕ¹ÒDóâKŒë:>wæLwÑ¥jÕjœ:žMça]¶†–’ï=¬š¦¡Ýn#›ÍÌ7Íd2H$Èd2}+’iš†ÕÕÕ ?+¢±ßu‹㕊•¤Z·Ù›Jª0Ķ®[—A’%š'ßbÜ4ñùW_íÞœiZ…à"¬ëªr´ÁÒò=a•ajNs`e¡R©„b±Ø]~;‹áòåËTDã1¾)ê1ÆMÓJ’IkÑ$"'AǶ ›dC yÅ·7 Üúëýô}gèY•duG,5× «Ü2)Û)àÇ]³µT*Ç‘J¥ðì³ÏvO,uE3¢0c|SÔ-JŒ›foEJ]·Vö-ùÈhAÛÕªµpëÑ’ð-ÆO¯V©X7§JX™¬’blº²²‚µµµû½®€Ø—Þ&ŠÆ7E]Ð1.sUËeΤùò"¶e0Ž 0˜5Æ_{ï{‘L&‘LN¹ºµ&«ÔglšH$¸2)-YH)™ì¿^*Q˜U* L¡iøÚ£"O?ª% `œ³J]¬LDD4o†5¬ræË&ùH×­aÀ @‘`øÊ_ý¾üåDߪ쮘§ÿg²J ×sX[­vvv°¶¶†T*…ô’U&mùIæÿ1a¥E’N3Y¥ÉfñÉOÿáS?Óœ°<^‡“#W «¦i(—ËH$ˆÅbÝûK¥b±4MC«Õ³Ï>ôñÑ’‘vRVúiÑ4ld¡ˆI&qóâÖ­ûœ´—´€‹Ž‘WC‚766ÍfñÜsÏõ]<8•J!—Ëakk .\ÀÕ«Wƒ>""Z"šf]²†hј&º«¨EÉ'?y?žzê-÷/¡ÃLViˆ± «\‡éé§Ÿù¼§Ÿ~;;;h·ÛAEœTö+`w—½«´˜67Ù»JÑÓé<Ž¿÷÷ÞëîÉ&€UX+ 16amµZH$}=«€uYux°<~ttô1Q„™&pþ¼õÿë×™¬ÒbŠÇ§¼äQÈݺõ×Ý_O¸ «g•‹,ÑcÖX,†ãããû·¶¶J¥‚Þ""Z2Õ*P(X½SD‹ª^zˆæOÓ€GýŒË'а,§1Æ&¬©T NÍfsäóäqµ×•ˆˆhÞâqL}?¢Ðu«bO5>xïÿ»{r¯—M.¸JXS©jµ:Žãs:jµ2™ {]‰ˆÈSå2çýÑb“Õ‰¢æöíOáüù¯Ž¢4Øð< \]ÖæÊ•+(‹¸tér¹\_Rzpp€½½½î󈈈¼R¯³w•Ÿ¦ûûAï‘7ânZë`ï*¹æ*aM¥R¸vívvvP«ÕÏårX[[X˜‰ˆˆh^êõÞ5W‰•aX#8J€¢Hw[Ho‚ -‘k®VÀZøÊ•+(•JhµZÝûS©ç­‘çÒi£¤ÅÇáÀeå²ËnS&«4× «ˆÅbÈd2Aï7-^¾†¢@×¹Â5-1 @ÀvÐ;B‹dì¢KDDDAª×õõ ÷‚h>Êe ÉÞ%ZV pî*M,ð„uÔårZ­ÚívлH45Æ7E×1®ëÖuWÙ#E~ó*¶9R€Â":Ê68˜&hÂÚn·Q,ï¿té.]º„§žzÊýxx¢a|SÔyãº\¼ìîròËoŠº@bœ×¦)’°¶Ûmhš6ô$ØØØ@"‘€®ëxþùçÑjµW'& #Æ7E1®&«ì‘"¿°ü¦¨ ,Æë°†M!„µÙlv¯Ýj×n·Ñl6±¶¶ÀZä)—ËaŸ,£Áø¦¨ó:ÆMÓš³º¹Éd•üÅò›¢.°¯‚sWij$¬¹\[[[(•J°.—#R©çúÑÂ`|SÔyã†a-L“Ï}¤´lX~SÔã:€48w•¦ø¢Kv£NŠN§3ô±W_}º®shÕl6ñ‰O|ŸûÜç|ßö´ñ ¯¼ò jµÚÈEˆ V«áå—_dÛó(ÃÓi&«4ÜÞÞ>ñ‰OàæÍ›¾n—å7ùAÊï B<«ƒ×°L'ôêà“–ß¡KXGÇÇÇC{×»Þ…G}.\ú(äVVVðÄOàÁô}ÛÓÆ7¼ûÝïÆ… °²²âû~Ób¹páb±X ÛfN^K¥Rxâ‰'pæÌ_·Ëò›ü å·ßñ xX~k`ÂJzuðIãûî wÜN†`—H$†>ö®w½ øÀÉd‚> ¹D"'žxbl‹¸¦oÀªð0¾ÉL&ƒûï¿?m³ '¯¥R)t:ßËp–ßä)¿ƒhtô¤üfï*)¦­ƒ‡®‡UZÕa ív{ìÑ"`|SÔ1Æ)ªÛužÄx\l‰fº„5‘H “Éô­`¦iVWWƒÞ5¢™1¾)êãUŒmŠ:Ob< €×Ѧ…nH0”J%‹E4›Mt:Äb1\¾|9èÝ"š Æ7Ecœ¢Š±MQ7ׯÂZ8ôQÑ¢ 4aÍd2Ðu}àþT*…gŸ}­V«û<¢EÃø¦¨cŒST1¶)ê|‰ñ€BÐGJQÊVÀºX1(ªßuŒqŠ*Æ6EÝÜb|Lsº9¬DDDDD´àÒAïEV"""""šŸ #è ¨`ÂJDDDDDóÓ€µB0Ñ0a%""""¢ùÐÁ•i®˜°Ñ|4Àù«4WLX‰ˆˆˆˆh>4°‡•æŠ +ÍÎ<ý—óWiŽ˜°Ñì`ï*ÍÝÝAïE@!è (b+…V"""""" %&¬DDDDDDJLX‰ˆˆˆˆˆ(”˜°Q(1a%"""""¢P }ÂÚjµÐn·ƒÞ "O0¾)êãeŒoŠ2Æ7…Eh¯ÃÚn·Q.—ÑjµÙlÕj5èÝ"š Æ7Ecœ¢ŒñMQÆø¦° mëÆÆ‰t]ÇóÏ?V«…Z­ônÍ㛢Ž1NQÆø¦(c|SØ„2am·Ûh6›X[[Äb1är9ìïï½kD3c|SÔ1Æ)ÊßeŒo £P&¬GGG€T*Õ½/•Jqý©b±ô.ø¢V«¡Ùl½sÇø­Ùl.MKnTÏeÆøhQýÞíX†/–ß‹ñ=ZT¿w»°•ß¡œÃ:ê¤èt:ˆÅb÷àŸÿóŽù/ÿ%žx≠ÁS7nÜXŠæå—_Æ /¼€ûï¿®ïûÊ+¯à•W^Á»Þõ.”J%ßkšø€Ï|æ3øñÿq<ðÀxøá‡}ßo¿Ü¹sN§;w&ʼ:—oܸ7Þx#°ãb>ËðÙß÷Î;xÿûß¿0e8Ëïèñºüþ×ÿú_ã§~ê§|?.–ߣ±üžÔÁ'-¿C™°v:¡;ž,—/_F.—C"‘z÷=×jµúZ¾¢ªÝnãÌ™3C¸Yt:r\ÓÄ7üîïþîR|ïòÝð\žý½ƒÂ2|4–á³[´2œåwôx]~/,¿Gcù=»iÊïP&¬£aØÉ‹Å<ùPÃhNž|AÆË4ñ=îuQÂs9üï=˶Y†/ϹÌ2ÜÝk¢„çqøß{–m³ü^žs9låw(ç°®¬¬è–Ðn·—¢å†¢ñMQǧ(c|S”1¾)ŒB™°& d2ìííuïÓ4 «««AïÑÌßuŒqŠ2Æ7Eã›Â讓“““ wÂI«ÕB±XD"‘èNòÞÚÚZš!mŒoŠ:Æ8E㛢ŒñMaÚ„@ßJs™L&èÝ!š+Æ7Ecœ¢ŒñMQÆø¦0 uÂJDDDDDDË+”sX—ɰ‹ò¶Z­‘ךõq?µZ­‘—ؘåXÂtœ4hÔE§£ò½{ßa;VêçU|»yÜO³Äø"'õ[†øfù½¼–!¾e_"Q~ŸP`ŽŽŽNÎ;7pßÏýÜÏœ;wîäܹs'¿þë¿>×Çýôâ‹/ž<ùä“Ý}yòÉ'O^|ñŹK˜Ž“œ9Å·Ü…ïÝËøÛ±Ò /âÛÍã~š%Æé8iPÔã›å÷r‹z|ŸœD¯üfkÚí64MC¹\xlcc‰Dº®ãùçŸG«ÕB­V›Ûã~*‹Èd2Ý}Éd2}Ç<˱„é8©ß¨ø¢ó½{ßa;Vêñ2¾Ý<î§Yb|‘Ž“z–%¾Y~/§e‰o ‚åw`©ÿûøÇ?~òÑ~´Û:!¤ÅGmùØÇ>vòä“OÎåq?½ð 'çÎ;¹sçŽãñÍr,a:N4,¾ONf‹á0}ï^Æ·›Ç)8^Å·›Çý4KŒ/ÒqR¿eˆo–ßËkâûä$šå7{XËå°µµ…R©ÔwÿÑÑ •JuïK¥RÝñá³>î§T*5°ºì_,›éXÂtœ4hX|³Åp˜¾w/ãÛÍã¯âÛÍã~š%Æé8©ß2Ä7Ëïåµ ñ-ÛZùÍ„5DF}ÙNgæÇý‹Åú–Ao·Û¨ÕjÈårH$3ËááahŽ“&•ïÝËøÛ¹LîEé{Ÿ%ÆÇ«a:Nr/*ñÍò›œDé{bùÍ„5DF}ÑÇÇÇ3?Ô1Õj5<õÔSÈd2¸råÊÌÇúꫯ†î8ɨ}ï^ÄwXÏe/Šßû41>î\ ãqÒxQ‹o–ߤŠâ÷¥òûn>/rIí^·K$3?î·V«… Äb1\»vm`øÀ´Ç’ÉdpõêÕÐ'¹¥ïÝ«øã¹LîDí{Ÿ6ÆÇ«a;Nr'JñÍò›ì¢ö½G­üfkˆ¬¬¬è–Ðn·»0ëã~+—ËÝqôöŸåXÂvœä^”¾w¯âÛÍãNQûÞ§ñE;Nr'JñÍò›ì¢ö½G­üfÂ"‰D™L{{{Ýû4MÃêêê\÷“¦ih·ÛÈf³h6›}³K˜Ž“&•ïÝËøvó8…S”¾÷Yb|‘ޓ܋J|³ü&'QúÞ£X~ßurrrâû'I€f³‰b±]×»÷µZ-‹E$ t:Äb±¾•¾f}Ü/µZ ;;;ŽÉñÎr,a9NÎ)¾h|ï^Ç·›Ç)X^Ä·›Çý2kŒ/Êq’³(Ç7ËoŠr|Ñ,¿™°†P§ÓA«Õ€¾U¾æõx˜Ìr,‹tœÔoY¾÷e:—©g™¾÷YÎÕE:NêY–ø^–ã¤~Ëô½/RùÍ„•ˆˆˆˆˆˆB‰sX‰ˆˆˆˆˆ(”˜°Q(1a%"""""¢PbÂJDDDDDD¡Ä„•ˆˆˆˆˆˆB‰ +…V"""""" %&¬DDDDDDJLX‰ˆˆˆˆˆ(”˜°Q(1a%"""""¢PbÂJDDDDDD¡Ä„•ˆˆˆˆˆˆB‰ +…V"""""" %&¬DDDDDDJLX‰(pš¦Á4Í wƒÈwóŒ}Ó4¡iZЇDDD4WLX‰(p«««Ðu=èÝ òÝp¡P@2™ÐkÉI&“Èf³Ð4 …B¡û\MÓºCÁòù<Òét÷±J¥‚r¹Œz½Ó4‘N§‘Ïç»ïÇQ.—§~>Ñ8nbªÕ*LÓˆ1Æ7-ªYcÿ•J›››¨V«}ç„0MÕjuàœ!šÖ¨xÖ4 †a Ñh²Ùì@ŒÊ}nË`–×”yĺišÝØÇã( ˆÇãÛ“bk˜¦ ]×»š¦u+/€ÔÕj€Õ¢sñâÅîIX‹/vßëüùó}'™) ÝÛår¹û~Ó<Ÿhö?9±bN½½½½}’Ífß)“ÄþÉÉøòÝþÚýýýÝí¨qM4oNñœÍfOö÷÷»·í1*÷¹-ƒY^SLëR«ï!õy>cÛ=ö°†Ìúú:’É$677X-2Ùl¶oèX>Ÿïþ_Ó4$“Éîêêmu!õõñx¼;$a˜IŸOä–=ÆE6›íþ_âñMQ2Iìîâ_}­Vzõ·‚hކųSŒNR³¼¦ Më·ëëëÐ4 ñxûûû}ñÌØvsXC¤R©À0 ìïïwïw¹v C†…ÓQМb|Æ7EŤ±Lÿ2j}}‡‡‡A:EÐ4ñL´ˆ¦õd2‰ýýýîT>Ó4Q(°½½ô!-$&¬!Q¯×Q¯×±¿¿ß×ÂÇG&­étºÛj#¤õó–(L†Åø(ŒoŠ‚ib˜>þ···aš&Fw!¢y™6ž‰Í,±. 'mooc{{»{Ù±t:Ý·h*¹Ã!Á! ë:Ö××±»»;P ÉçóÝÉÞº+Ž u2!¿‰ÂbTŒÂø¦E7mì³Å<ï®XÉK/м¸‰çq#ÈÁ¬±®ö¬V+x¦Ç„5dÅßÕÕUÜu×]Ý¿J¥‚d2‰íím¬®®buuçÏŸï&•’J¥‚óçÏwWÜÝÝ ú°ˆºFÅø(ŒoZtÓÆ>0{üçóyäóy6ðÐÜŒ‹çx<ŽJ¥âx9¢E2k¬Ë%lΞ=‹ÕÕUœ={Éd’k L鮓“““ w‚†“á_Éd²{V¹F“ZiQáadDQÁø¦eÆø§E¡ÖYÔeˆ¢Æm¬ËÉx<ΩL3`Âr†aàìÙ³¸~ý:Òé4 ÃÀêê*Êå2ÇÀQ¤qÑ¥S‡›¦‰x<ŽB¡Àd•ˆˆˆˆˆ"=¬DDDDDDJ‘éaý£?ú#ü‹ñ/ð]ßõ]AïŠç–å’ŸûÜçðàƒâÁœû{ß¾}o¿ý6þÙ?ûgA¦k¿ò+¿‚ïþîïz7LWX~GOØÊïÈ$¬ßúÖ·ðž÷¼.\zW<÷ /,ÅqÞ¼yí¯ý5<ñÄsï7nॗ^ ú'r||¼ßû7ðÖ[o-űzy.¿ð AÞDX†G×ex»Ýú]cù=^—ßgΜ ú]cù=a+¿#“°¾ë]ïÂ>ðd2™ wÅs÷ïþÝ¥8NXYYñ¬…±Óé}xy÷»ß½ßûÊÊ žx≥8V/Ïåûï¿?èÛËðhbnaù=^—ß±X,èCtåw4…©üŽLºLr¹\лà‹e)¨_"‘X˜aP³Z–s™ú-Ë÷Î2|ù°ü¦¨[–ï=lå7V""èºÓ4»·yM6"""¢ñ˜°.]סë: Ãè^ Øë‹rË…Žåÿöʵa0 càurQ{µrnšf÷¹ê{Äãñîsu]ïÞ§w2™ìÛ¶zÜö`Ã0ºÏ¿sç~ôGÔ³ÏúÉw%ña¿ßé»,—Ë}Ï–Ë@ì:%ò|‰IU<ï;ïä9êûÉ>Kì†Ñ]¤A^«žrÜÙlñx¼{Ûiû㨯_´9ÚDDDDN˜°ú@­ K䜞/É™T’³Ù,4Mƒah4Èf³(—ËÝ÷• î°Š®iš0M³¯ÂmF_%[¨s©˶åùöäC‘Íf»ÿO§ÓÇ«iLÓD>ŸÇöööÐÏOÞW’võ=&í¥’Ï´ÙlâààÀÛ/>Âä;Q¿i°Ç¯H§Ó¨V«ï%q¤Æ‹a8þ<òù< …4MënOÐ}MÓú^ï´ •ì›®ëÝ÷–çHLåóù×ÙëB¡àØp¤ž nbÔ4M4 †Ñ=§í»ùNäØŠÅâ¿qZfãyÔòy˜t:t:Ý÷ûoÐûݰÿnÊo¡øìg?‹Ç<è†"Êmƒ¸üÖ©LÓìÆê°Æ};9¯äœøÓ?ýÓ ?¢PaÂ:g†a@Ó´n%X 2õÞžÈIBè¦7I^»¹¹‰z½ŽJ¥Òí¹’÷R+ºNIª—òùüÐÇì½S£ ûë²Ù¬ëçÓü¨?ÚÒ`!q-1¦6\Ìó;Êçó¨V«X__ï&óŽIßÏmiOÀÝ<¿P(Ìt,“n“¢ÉM£ž®ëh4}œ¦iv{ù¥1GÎ}õ=ÔS©²Ùl·QuØ>麎z½ ÿCmÀ·7ˆû± ÙãûÏþìÏ‚Þ%¢™É9no8ýÔ§>…7ß|s¢÷bÂ:„|ÈêŸÚ³¤‚^Ï'%š…¦iÝÞ”aBuî£4¸„éÇœ(Ììo{r©—añ2ü;›Ív_ÔÞu¾³¼Ö~þzQéf/=©ÔÆyµG^M@Óé´ãôymXb*,ûA$µq@·ÁIFcªëÄH²i½J¥ìÔN<ù“÷zì±Çð½ßû½í7Vô U©d4!~ö,ÍC½^G£Ñ`õÆš'LDã©?ìê‚[êï…P“Éaçž4$ɰWþÆP$¦ÕžJ‰kµñD*³ÃæîÛ1A$òž}úÐÿ[¥ršs­6<©kÈC!#„ÔóÔ‚š£~ϦYGféÖF£z½Þ—œn €añ80IBÓz¯‹Ç·…µ®Té´õZ·LÓÚ¦}? £wÿ¼ZàuÝz¯yö&«Ç.’ÉáÛ!=š6øù;ÖÓySê{Þãîp8Â"0MõzõzÙlÛÛÛHš¦õ7½˜˜g\Œ¢i“oKbwÔùg½xL§­Ûö8rÚ®ÄúÞrŸ´ž.d6°?£ØcÑ4{ïg[¥¸+Ÿ<¾z}ô¶’IÀ>  ^·¾[Û{ýç@ÍLJ©ÈËèûö´òùüÈyÿDó¤öüË¢‡š¦uãZ†íÍ#¶#K-Ïê*Nu•Ó üV~ÇW¾ô‘R@ÔEìd}Y˜ÑÞ»iFߤ4NcssÓõ”bÔï‘Óë‡%¥^4¾2am4°•Ëáñ¿ø‹^¡¡V‚uÝúÿîîà‹% ¨×{‰œZA¶¹ºT*ý·¥À“BÏþ°ºÚ+*á’€¨ ÃÚ7uUVMëßÖþ¾óþ©I·}? …ÁºRéUΤӀ}.¢T²åqû~Ökœ v§ÿKÂ’ÏVèãqë=•D vó&Þ±äF£J¥‚|>ýýý^…£Ñèÿ~4ÍŠ ð¾K§ïG.ùÜÔ$Jâc{{ðûY]µ^kšÎNßÄÚ‘N÷ï³=VÞãã꾘æðŠúZ!ç•Sn½×I‘}{N «ŸöÇå3´K§G79U„ ësµÓ—A“Q×(•؇Íõ\HšÖ+ϳYw IöóXC’SÃŽÚp[±jßfµ:øÛf½I×ñØoÿ6>±2Ü­aë¨ÃùÔaæj©ºº4jBâeT‚7I}CÊÔBaøoŒú\‰91¬>äDêiÙ¬sÂ*çÓï…üæÚßO^{Š ëâ’E휮¤ôÿ’^PMÓú†ÕªÓå9r¾NÛ˜…ÑK°J¡ÿx¡<þø`¥]8ކU˜åóV2ë&€’I빓V|œ*ëãd³î{xE:=ݶ¦YÇéGÅ«måóÖŸâåfw"¶`GµZíOTG—Z1´ß/7ù¼ûXò+~’Éé^7Ík¦9—¦Ý¿i[%’í/ííM÷^KÄ0ŒîÐyõ2^Ùlׯ_w—¤Ú{Ð園ʬÓoøF¾x|°‘tXZKuݹ‘ouU¶—¤êz¯7?ŸŒÕ‹ûUÔ†TiÄujärM Ç/I‚ý3•Æ-ûçao̵}oÇbøú}÷¹ø–£AQ¤rëÔƒaObeñ¡™zLí ¥Ów"ñ,!NêöxQ‡Âqº/›u2Ê´eñ4¿gÓÔk~/þ¤XÄÿkòw¢H.!ç¨$œ2\ÖéJ2d–ÓµÜ[¾„U~laõHåÝTÆ ÆQIÀ0Qh¡§P’JLR*£ṅõ*N›p¬Ñhô RW&•Vfµç©P( &§öQò7j˜¹*ïõf:*pê9gXZ¶?ì=§©t;(r³Ó4¸LÙày³ÙÄ[ktt¢iZw¡®¹Vn~'4ÍJ>NáÔ«èWC ¼ŽÈ'2·Z­v‡æ½¹¢r[†îºnè\$ÃFA8ý• œ¦5¹´\ «´no§]íeûP#¢ôÛÿ̓ß=9±zS&m}&ZpÒó$ótì ɵå_ÇKé:°¾ný_’/©ËúN½GÓŽ˜Và#«R©@Ó4looÏ6'Lz3eê…Lù±7fd³ÀõëA6Q ¤·T~3¦Y…•}ÚŸ¶6†ŒÈ7müí3 ë5ÃFF +¯fHæ—'a•ŠÈi-]ø\•‘ÝÿýÜsøoÿôOñþÿò¿œëEa¦ibuuµ{]ƾÞ'Y“ Ñ@6™ì-8¦® J&­ß‡aÉ|b.^¼Øš>•zÝú“!×é´Õ˜Éá‡D0MÕjµoÕ\™ë-Cé~S¼¦ödjšó0zÉeä¶ýwÌi¤Í°‘t£:7üœ¶çR  k«Õ¤R©¡Çb1$‰Ù6$_°xÝáÀDñ%¾ üüÏãó¿ð xœÉ*ùÌ·2Ü$«…Bû«aX•õ|ÞjÄQç_jZoa059Ú0.šI±}ñâEç¸fXÅuÊ¡w´‚Œñ ÕëuT«Uäóù¾slî«cKêÔã(=˜ö¡ùòÿa=—åòä ¨ÉuIX[­Êå2Úí6 ‘H Z­vOšv»r¹Ü=™²ÙlwÇÄd<µ­•¤Ñhp¢3yÂÏø¾õïþžû¶oÃúoýVЇMKÄ×2ÜÁÈdè-pg7ílZ"¾—á6•ÓQ3ÝJ½ ý%šQ±mšæðº‰iZ•åtÚª/q/ Í&èòÛ+š¦auuÉdÛÛÛ(—ËØÜÜÄáá¡ûëh›¦•˜ž?oý­¯÷VaÏf­äÓé·FV¼æ´Où>$8•Jakk ±X¬{ßÑÑëÄÿ«cêS©Tw褮%¸z:t,›Íb}}»»»Ñ[všBÁïø¾úƒ?È…ÃÈW~ǸJ†vu+OrÝGŽ–¡9:¶‡Î¡‹Ç­^¢ãÓ0 F¦iÂ0ŒîedäR~º—›ÙÝÝí»o*£ߣ@ùÞËÅQ†0¶ÛmÔj5är9$‰‘'E§ÓúØ›o¾‰›7o¢ÙlöÝõÞ{±½½ MÓðÀ P(°‚¿äÚí6nܸ۷oÏý½½Šoxã7Ðl6ûÞÃ4M6¾Ð€f³‰;wîxòÞ~—áªjµŠýýý^̳wu)µZ-ܸqÇÇÇs}_¿Ëo•$¬DR~‹©iY~O¢R©àìÙ³Ý52dûûû899Áááaw˜ïõëׇ'©¦i å­T¬!õ««Ö_½Þÿ¼xܾË:•§¤>iùØ*ÁNW¯^ÅÎÎÖÖÖºÃFÇÇÇ}­Bª7ß|·nÝÂÁÁAßÉ(KVooos‘%`µ&Þ¸q¯¿þºgÛ˜w|V…çàຫöÉìDªƒƒO*;*¿ÊpÑh4Íf{ɪiö®«MKEV¯øU~ ¹Ä^_lËe˜héHù=.¦fáwùí–ÌCÇã³-ŒdšÖÜSuH¯\Ú‰çU ¤>©ÀV ÞØØ@,õk׆ 3jií‡zétº{Ò軾‘ÂT*óæE|ÀÃ?Ü߀ãìa%»R©Ô]áÑ ~•á*MÓUçî5œË·¤¤7È‹2ÜÏò[HcL×úz¯‚MKGÊo¯.'Dù톮ëX__G>Ÿï[j*ñ8‡÷†Ô´uð@Ör¹ŒL&ƒ+W® <¶²²Àê2–“Cýÿ$¤Õ’ÈO~Å7 ßéQë+Ñ(¾Å¸B×õþQ2õºó¥kˆfDl7 \¿~]nX½CL "ÆÇ1M/^Äöövã»÷_JFðŠßç°jš†v»l6‹f³Ù÷X-8™L{{{}¯Y]]x[ÿÖo1a%_ùßo”Jø[ßÈ•©h‰ùãB×õþÑ2õºÕÅ44GAÄvßPwÆÈaîä‘ b|¹®v¹\ž,Y5ŒÞª¾N—›¡Hñ½‡U†©‹ÅÇt]` ‡(‹Ýå·c±._¾<Ù†t¼ôÞà ùÈ·øðöç?»r¹ ™–ŒŸ1.†L²åœ<Dl÷ u¯VÙCž "ÆÇ¹xñ" …‚ûEÇ4Íj´4 ë·àúuû]¾'¬¥Riì÷T*…gŸ}¶{bM5Û0ðé»îÂeö°’|‹oßøÆ7‚>\ZB~Ƹè2Iä‘ b»;ÔÝ0¬Š8ãœ<DŒR©TL&Ý%«šÖ›ß](p ƒ%Ø*ÁãØ—Þž˜®£õ®w}DŽæß·î»oò¹D>™9ÆOÉJØ\\ŒÂb^±­ëz/®«U`Ö…fˆæd^1>Šišî#uÝþ»»ËÅÈ–Td'À™rAy¢(2 Ü|ç;ƒÞ "Ï5 k-‚JŪ´E„išVl›¦Õ{Äk Ó©T*(—Ëî#Óikô“Õ¥Ù„õíÏžMÑ¥ë8xûmö°Räiš†|>o-ªÁ2"Ä4ÍÞ ®xMKDÓ4èºî~Þ*-½È&¬o½õ+ó]†ë¯½ô^ù"išLV)rº«_ÇãŒoZ*Õj›››Î꺵ò/‘"´sXg¢iø³w¼) ¦¨2 ¼9âßDQa†Õ»ÊHŠ $ë)´d4MC2™tîTÒuàâEŽ8 ÑìaÇñïßz‹?Y·~õWƒÞ"_$“Ik~VŠ˜¾!ÁDKbà2eÂ4{É*GM$V3™ÄÁ‡?ônyæ3>j-ÖAa¦iâ=ßü¦uƒ 1†a€Í0´LLÓì­K`wñ¢µR6ë6ä`¢!ÁÍf³o™ëf³ MÓ‹ÅpáÂÏ—Àv«;/„(¢ Ãzˆ<§ë:~þï¾ÿûƒÞ¢¹;÷ÚkîNK¥^¯;'«Õª5—›‹0Ñ®zX[­žzê)‹Åî}š¦¡X,¢ÙlbÅb{{{AkYžËÃS„†ÁEÅh)<þÁË}P$½òÙÏZ•t¢%Q¯×W6  ^¶·ƒÞ= 1W k¹\F*•µk׺÷íììtï{î¹çP*•P«Õ‚>>™›("8÷‰–¦i¸ù=ßÃ!bIÿ÷½CÝiihš†t:=8²Z67ÙxC#MX›Í&Úí6®\¹‚Ô骤N­V ¹\±X ËåÐétÐl6ƒ>&¢Èc+-‹w|ô£AïÑÜu§u0a¥%Ñh4œG?–ËECcMX[­2™L71¬V}fõq"òç°Ò2àHŠ*Ã0˜°ÒÒºØÏral‹ÅÐétúîkµZH¥RLR‰²¿¿ô.yÎ0 ®†M‘uß׿ÎÊ:-–å4«± k*•B«ÕB«Õ` Ö4m`E` ¼²²ô1EWÁ¦eç¼&Š MÓðŽw¼#èÝ ò…¦iýõ–Ó‘šDn¹JX3™ ŠÅ"jµŠÅ":Nw8°$°•J™L‰D"èc""¢xûàÀZ=’(bîûú×ñíïлA䋾u74ͺœÑ\­¼¹¹‰l6Û†¨.ÀtõêÕî*›››AEÄS‰„uÉ¢úÂ/þbл@ä Y!¯=LS¹ÛÍ“b±®\¹âøX.—C.—›ºgµÙl /¦bœþ “`Ð$Oÿä¶* ~ú^2ÍA;}®ÌѯŸ>îTÎ¥O_¯þeOÿŒÓ×Ù<|×ø÷½÷zþñ0¾)꼊qÃ0ðè׾Ɗ ÆËòûO>ó<ý¿ô!Ò’ó³ŽÇÓ´zXyÍUš«„°‚úààpáÂ…n€Ï2¸Ýn£X,B×û³—Z­†¾û2™ ¶¶¶‚þ¼†Óa%JP>ýWƒ•DIV9½<}¾‰^²·¯ýlL‡×èÊkÔ„è%¬öûU’ð&OßC¦JÄ1˜àêÀ½Ÿ¹ï¼÷ðR¤â›È—1nyä‘ ‘–”å7çgSüª£ ô®ò64WÃMf3*-IDAT «=xwvv°¶¶†R©4ÕFÛí6Z­ÖÀ !ŽŽŽËåÂsÙé¥ËÃJštÑKŠ€^R˜U^£>G­ìékÕÞFéöQÕiåo˜ÂéŸú7‹Èî¹íÄÞ(&=™£$ìÚn»=>ì³·-û÷bß¿,ðróeÜ9¸ãb'&·pñ=O XñF¯¡Á€Õ€’EœÒÂò+Æ_þrøWQ•߇qe¡ ª¼F+§·w•ÛN#P Xeâ¨FJ'“4Rªå«ð@ ûNá'åw§Ó læU7 £7š@×™°R·>iùíÍ$dmm­o¸q"‘@­VC.—úº7ß|·nÝÂÁÁ»– ii—y¥2ôH†;IÏEÎÑÑnܸ×_Ý÷mO߀Uá‘…ÏF.v¦& X/êjÍ@oѬE›SZF/A•}ßÄðáŒv¬d$â=´UvæU††3gÎ8?Y惺‰ß*úçR /ȬØtFËß“¹‘„Õoó*¿ï»u ÷Üsÿ-)¿}_ßbÞuðnï*ì»™·@Q'uðI¹îaõK"‘@©Tê;Is¹:ÎÈÞÓ‡zétzøBP&zócd®ž´„ËüŸ×` ‰d²i™L?û³?‹ïÖ{ã¡iã~øa”J¥á 2êªÓ¢+É“E®£·ºô¢Ú†•HOk½ÄE.…4LÃWÃŽR©„Ç{,mϳ ¿çÿÐùÉÜ ×•žX¿¦Lå1¸ª;пú9Í,—Ëágögñ|À×íΫü>úã?F;Œ+`Ëô · €²âVÙ*Ãîž£Žˆ¨ W¯Âj„¬ ÿÜ©ŸÞ¯¾F}o£/©çvÿCHÊïY®Â1­y×ÁûÖE¢Æö(2UIbZwñ|‰}{L/ ©ƒOZ~»îauç^«ÕpõêÕ¾ûf½4‡ ™Q[r¤Ûxê–&VpH¥ÖíDsæI|½FûŠÑ€óœºE‡5×Õ©—T~ ¤Ù® «RTÁ|†BÓ€yŸýR }$a×c.±âYXH]lHÃàjð´æÛ÷¼ü2¾ó;¿ÓÝ“×a•YNåÙ°U£e‘.CyLæmožþ¿+67a5¨H¢ª.À'×M—ß)_e;êeíd±½‹Êm)cå€òNßC¶gœþ+¿WöyÐIôÕ¨aÓZÔEöóO>Ÿ:z£uò§û IlÞáù8}¾L'p» áòyЇ:Mö‚9™wE×u !Ê%±¡Ž²Q“Mu1¸¸í9@ÿ*ë²(«ü+—”¼®<èå2’3ú§Žx³_Þ²‚þ†y(ïe «ê ÒIgØ^+SƆ0RÏuñÍü~MXWVVú\©TÊ“ŠÅb(‹H¥RÝmìììôÝžˆ«uªÈùlîñ X? UXøe™'7ìÇ_z“/žþß~ÎËP«¾@Íd^1>´UÞ¾ª¯ÓyßùüdÑŸ`ÈáüàÓlæÛÞ¹ƒ×~üÇñA7OÞÆøÑöú4ÊÉȹ„’\LòÜÔ‘ìýöõœ~œàÊ:¼¯z)4`°l·j#Ð[PPM(ä·R~äßúéóåõjBº~ú¹Ég˜>ý|5ôVðú/ßWE¯1@.%½ÇêªâÃÊ…Uà'nþ‚àEÅó±¥—R?ì ì µAGýŽ€Þú£vÕ·N_yô÷ÜÛ×í— , ÿ¼T÷E”a­Gb?ߤñHHO¯44ÉZ!öÆ5Y—Û~%õ’²Zþ¡r{Xϰڈf?^åòkOÜy_üÑ/bcVà—T*…µµ5\ºtÉ:st¨VÇõËÛ°R‡õe³bJ!0·ø–8î.³´L²°>óè/,Õyë»èýp…ý¹šGŒ¼F¥º€‘T6^%èÍÙ–KÔø©à,zófc‘1¯òû®—^£>:úI똾¡cXråÍ z—jÀ:ÿí£+œ>—øé놕ô7 »¼: DޏòöíVa5œ^Goà.º+ñÿ~ñ÷ñCø!ß?ƹÕQN†È%t²s@ ½ßñ$z#$Ù”ÞËQ›rºÚ›]s»ûñ!ÿwû¾öÛqX1¸Žþ+9ØaV,™þ›3¬ñhÔ±ÙÏ#7ÓqòèuÖùqÝ+AÜhÞÀ+¯¸ü@-/ºÔl6» ³-wÉd‡}•J%är¹î‰2ñû°Nþ²Ë–ÈžÅ70¾%pÙI«ºSoœ<¾‰ÞðšŠW1nžJ$Ó´®Û§R[Œ¥—Bz”$Il`øedüp¨üßï„™æÂËòû=ßü&ýùŸþÉ ØéÞ&z•õ æ7íËíô„¯Q¯É¬!ßtOë(§’É$ÐhÌ–¬ªCÛ¥üÖ ö F‰ô–®ŸÞöÛ6颒^}VqôƒV’Õi¹NX5MÃ3Ï<3pI$ T«Õ¹N$ÓO8O¢¿Â@23Å7À$Ë Š%?fyôäuá©YcüÿùGäü@zÈ}ê(~·ä¡Ycû‹ëoáܨ'°‘crR.ÈZ‹ð©^¶-df®£Àº4«‡u{ŠÖÃz7²hä27âlÂJü-!o`ædp™°6›M”Ëed2<ýôÓÈ*-%š¦aoo—.]ÂÖÖÖL-1DDsSFÿ\’a…¥z‰ MÓðKwß=Ø»ªëV-Bå”èTîÿ߃ޅè*ƒåAH躎‹Å·«KOª¬Kà4sÙù¹ˆà¼ÌiKW—µÙØØ@6›ÅÖÖV_²  ïþ ?""‹ z?„Nd B¡€ï|õÕÁœ.›A%U /«h<&«¡ò}·o»OXeR4“U:56a•%®Ÿ~úé‘Ï[[[C»ÝF«Õ ú˜ˆˆ,2—qÔ5ûä2Édw??øÀ¨åø‰¢@]TŒh麎•¿üËÑóWMôæeʪ¹LRÉÁØ!Á­VËÕXv™¿Úét‚>&""‹ !•Ë8YÀkšGÞ°U‚C8׋hnÔK¤-8Ó4ño¿=¼‡UVGæ”ralk,ë^4˜ˆh¡Èáí×è³3л(8Ï0ú+9j+o5 ¬ƒŠ&µl2ÀÞ&Š]×à¥äh ®®ÃšJ¥°µµ…Z­æxéšL&ƒR©ÄÞU" ·=qXIkV¯(i-Æ‘/OÑ¥¡7g5 ö®R¤¤‡-¶ÄHš‚«„è%­réšV«Õ.&"¢éH/ë¸EšÈ[q°"OѦƒ1N‘¥ë:.¿õÖàgÁQ34WsXÝhµZ(‹AÑl6Ád•ˆ¼ÅKØP„=ðéOã»ì—Ä4` {g²JS˜[ÂJD¼¼ yEFp°âNõ•fߺÿþþ;“vƒÞ3ZTLX‰ˆì*°†ìÍ{W)âÞyó&¾ý§~ªw‡ ®ÀO3aÂJDd—V"òç¯RÄ%¾üe|íÑG{w¬ÃZdŒhJ'¬Ífsèc­V«{Í×e¥»¬4›¦õç–aLö|·LÓý>€6A¦i“=? ß *^'Î%Æ8E•g±/aC¡àUŒ¿û/ÿßóÓ?mÝÐ`õ®æƒ>ZZdcW nµZ¨ÕjcߨÓéL¼ñv»b±8pqáv»r¹ŒV«Èf³¨V«3¨aÉ$P©ñ8P>½l…®÷'nšfÝgÀþ¾õyN:m½VMœä¹ñÓ¹(ÛÛÖóä9Ù¬õ§ëÖ¶e?ä_ÈçBÁºo}Ýzýæ¦õX¥ÒÛÿx¼·]^{­÷]·^“N÷n;½Nž£i@£ÑÛ¶ìŸuVW­÷÷û·ídw×Ún½nmK¶-·…úÕÚ÷Gݶ¦YÇã öýQo«Ï—ïðÎ'ð£?úÅ™bj?ã›< åç™ Å§¨ò4¶Yq§ð2ÆoÝwÎIų ^*Žf6ñem†‰Åb®/i#×rÝÙÙq||cc‰D×®]C§ÓÁ¥K—P«ÕP*•¦Ú7].^­DµZí%Œ’pŠdÒJ˜’Ê*¡’\%“½ÄOŸr¹wŸšø&“V¢*ï“Lö8ašÖ¶åÚÊÉd/ÑöÛN$¡vÛI¡`ý‰tÚݶìÏ™f[öÛNœöÇͶœ> §×5›7ppðÊø7œ‚ßñ= ðb??eÅÉ4­„xÜŠséYwêaO§{Û‘F{ƒŒÓû—ËÖ9¡iV#G¹Üßd'Ç#?õzï|z-²Oê¶¶·{Ïé6’4€ú5@Oõ—B` k[ÃdT£dÔý³³7ȸÙÖ{ßûÓ}¹.,BŒMcÙcÛ4ûë)£ž'e½Ô‡ÆÑõþ²×‰aXÙ †LËïA2Ù_wS·+£Ðì¿YñxoŸÔßµ3Cý‘ûeÿtÝzŸ>4]Þ#™ì%«rÛ©‚$£äµÙlÿs$é“ ‡¦Yï£îÏö¶’œ€ôoÉÿ7ÝòÁœ68©QÓ6ÈLÓ8U(ô¾ûg[,~Éý<¡°Å8ѼD)¶e$U½n5ØKD×{ ð’L© ¦i=¾½Ýk4¬V{ n†u[Ê[ixŒÇG7ÊU«½†z{ýHêh•J¯Á_nÅ% wr¬Ò0ê4bLž'ïkš½FM§„U}®=‘UjI„Õçª ´|Æ2âNîSGUêþxÅó7 ¼Sæ¯6l»{ÑH'c¼ð 'çÎë»ïÎ;'/¼ð¸—ŽåôÞnïsz¯gžy¦ï¾ë×ON’É““ýý™w•"Æ)^¼ØÆ¼âûääää£ýèÀ}¯½vrR.[q~ýºu_¹|r²¹i=vrrr²»kÝW(œœd³''ÛÛýï±¹iÝ/çÉõëÖóóyëþdòä$¶î“m,í“““ÂÇONNprr²ôN:sŠ—yóº 'Æëxñ£üžF¹Ü+Ã¥\—²~{Û*³³Ù““xÜzlwwðõÙìÉÉá¡u{¿÷žò>''ÖãrûðÐzž¼†¼·Èå÷áááI6›µHúø¡‘§ö÷{åE¹Ü«3:ßVë‘ÙlÙõ /œüÆo\hûS ¾zõ*vvvƽÏè ÞN±XÌñ±7ß|7oÞD³ÙD&“éëYe/&©Úí6nܸ۷o²íaFÅ7¼ñÆh6›XYYA"‘`ÍyN&ë×û{øÞð§|~ôÐßr¹¿7RZ·9ÖÂKgÑ»n¢ª`¡œÖl6qçÎ@¶=¯2œæÇ¾–Jz~€ÁáŽêsì† wT‡ŠÚ§¨C+eĆ”1õúàÐû|Þ¹ úä'¿€gžy7žxâ¾~Žó.¿í¤wQ>£JÅ*Ëeú’½<ßÜ´>7u¨ë¸ÑN#ÆœF©= Ã†Ú’7¤üS^˜Gù}||Œ´œ¸¼îê«×{#*äw$î• RöØo YÇGÊ)©ƒ¿ýöduð¹Ía—Q‹7¬©àúéÿM¸Ö뇃ƒƒ©›‡y”á~&¬šæ\!—ødȺº€ž¦ žcFïÜÑuë¶}ŽŸ:ÐiÈäÙ³ýCÞ%ászŽ !¿x±·jò ôϳÖõÞ°KÀº-s¶Õ„UM>Õá˜ößRûpGI´d¸½ý¹ê²¯êûª Àzõw\×­JÓî.ðå/·pæÌ+xûíW}‹`~åw­–pLÆ …Þ°Y©ª‘NÔ•Ie4Hù=.¦¼0ò;•Jõð¨>¬ÜvË>÷XÊWi8“Ûj9®.تî‡}ÕõõÞú4’Ü ÃÏc·ë^\¼hý¿\ž}¡Ty_9]·ÞW’ÓrÙz\“EhØëŒNuHµ¬k6­:ø¤B—°öºÍ°VIx衇N§»cìG}¸´Ü¤2,•?MßððÃwã[*oׯƒ¼æÔ˪Áú!– ùWG(.WQ*•º+<úm^e¸休9ÑõzïÇ;™´nK/—:OZM¦äyöŠK¥Ò«È(u5zù“riXR+1‡‡½ymò\û"€‡‡ýÛÝuу!‹ Ó´*Uûûý {yîöºdrºòœ—¥g1¶öWGûOÿÓ'ñÝßÝÄÁÁ›ã74Gó*¿ï¾»??Þú¿Ì“6ûlwWŒ¤EÄøŽ mXÃGÙ„µS¡\Axž‚ŽñõõÙ[è§•Í.бÂ> 8,‚Žm"¯yãÆõÿ ¸þ™ ’¢blšH$¹ v,ãEã{AÅa-Â4JÖ°áuX—¾ÙÆRö¶zã²²­,HÔÂ4ù|ÿM´ûlÐÇCD.iô~¸åBßeô®Ý X«¯+Ï/€?ö .LCD´@ ôÿÆÍÈÕà d³Y<÷Üs}×bJ¥RÈårØÚÚÂ… põêÕ ‡ˆ(¼œÕ*¬Eš6\‡µ ±&"¢pŠ£?iÕ`%­’¨½aÄò|½„µà<€³°æÆž…•ìª «n=öôÿ6ºÌ^†a-²DDD ÂGÑÜÜjµH$úzVk™kux°<~tt4ð\""r0n.¦:œ°† ›°‘H V«!—Ë9¾æÍ7ßÄ­[·pppÀ! 4ÒÑÑnܸ×_=íO߀Uá988è>Ÿh˜ƒƒƒ@+;,ÃÉK’°ešøfùMnIù}||ȼQ–ßä%©ƒOêÿôŸþÓôÎÛÅb1d2Ü{ï½Ýû’É$êõ:>üáceeeà5¦iâää¥R)èݧ[YYÁ™3gðõ¯=‚ušø€?üÃ?Äoþæo}œHd2üÉŸü >ò‘²}–áä¥T*…3gΠÓé,LÎò›Ü’òûüƒÈöY~“—¤>iùÊ!ÁÍfs`èts•2ZtŒoŠ:Æ8E㛢ŒñMaÊ„5‹acc­V«{ßÎÎR©R©TлG4Æ7Ecœ¢ŒñMQÆø¦0 åÖT*…µµ5\ºt ™LGGG€jµô®ÍŒñMQǧ(c|S”1¾)ŒB™°@©TB.—ëž(œÄMQÂø¦¨cŒS”1¾)Êß6¡MXkU2®¦GQÅø¦¨cŒS”1¾)Êß&¡œÃJDDDDDDÄ„•ˆˆˆˆˆˆB‰ +…V"""""" %&¬DDDDDDJLX‰ˆˆˆˆˆ(”˜°Q(1a%"""""¢PbÂJDDDDDD¡Ä„•ˆˆˆˆˆˆB‰ +…V"""""" %&¬DDDDDDJLX‰ˆˆˆˆˆ(”˜°Q(…>amµZh·ÛAï‘'ßuŒqŠ2Æ7Eã›Ââî w`˜v»r¹ŒV«Èf³¨V«AïÑ\0¾)êãeŒoŠ2Æ7…Mh{X766H$ ë:žþy´Z-Ôjµ w‹h.ßuŒqŠ2Æ7Eã›Â&” k»ÝF³ÙÄÚÚ ‹!—Ëa?è]#š㛢Ž1NQÆø¦(c|S…2a=::¤R©î}©TŠãèO-K+×ÞÞ^w8J”0¾GkµZØÛÛ z7|Õs™1>ZT¿w;–áˇå÷âc|ÕïÝ.låw(ç°Ž:):b±ØÀý_øÂððÐuét:èCðÔ'?ùÉ wÁº®ãSŸú>ðÌõ}oÞ¼‰Ïþó¸ë®»P*•|?®iâ±¶¶†G}tîŸI˜Ü¼y·nÝZŠG¯Îe]×ñÒK/v\,ÃGc>›Ï}îs¸uëxà@Žkšøfù=^—ßA•…,¿Gcù=©ƒOZ~‡2aít:C;>>vî—Z­†ÇÇäxg9–°' çß@4¾w¯ãÛÍã,/âÛÍã~™5Æå8ÉY”ã›å7E9¾h–ßLXC¨Óé Õj@ß*_óz> stream xœä½ÉÎ.I’ž·Ï«ø–Y‹ú£‡ÇV€H€ ‰Y»¡Ew«²‹hR ݾÜüÌüÏ¡2 nˆò;þÅàÓ㯙ùûl_ûg‹ÿáÿþ¯?ü/ÿñùüÓÿûÃþ‰ÿùïÿôß÷sß>>Þí³÷ëÙ>ïqnŸÿþ?ü?¿õOûö_çûi}Û¾zûüõ‡ãîÇ×{Ûò϶ô}ÛÆ_ë"Q_qþ¿ƽ_ﻟŸÿá?þûö«Ý_ÛYêLË~=q#?Ù6+Î"}ë÷x3³D?Ÿ¯öÔzl)õЦzô׬ç8öíëÜë3Ú’õÈÆzü׬'ž±¿Gûüüã£ý·ñªæåþþ¯Ÿÿõ/ãÓöÏ~|þ2Þ4þñ³Ÿík‹wÑö¯ñn?ùë÷ãñ§?Ï×yžíÇmùã~Ž¯Ñž¯ß.pýØ~­ÀñÄŸ¯ÿô—ÿðÃÿö—þ¯_øâû¾"¥•üô³–Í¢õ¯íZJ©ªg;¯~gU2Ôª²ªª¥\ÕÑ®¯~•ªhXªr!WUJ¹ªëm_ý,UѰTåB®ª”rUÏÑ¿úQª¢a©Ê…\U)åªÞ6Þß^ª¢a©Ê…\U)õ{[ÚxŽã|F+FÏŸl¶´µEüùùç×þF;ü‡ñ¯û¯5 åzG¹ïíõ{9ÕwþÎú¾7ï_+wÿfÓþ»ÏÞâÑÿÓø¿øáøü‡ß5&þ´Žq?ú¥.³ŽŠ¿Üa¾ÕòŸíüš.>ÚŸãëõ_îÙû×}ørÿþOÇöuÇóã¿ûÓõõžýüñÿÓqµ÷y~ü?üÿçF_Ø{ûñ§?ýùݾî§~Eøé?2\mï¯ñï×»?¸•ÈÏðOùÇüÓÝ~üëŸþ¼Í¿Þïòçÿ;Ëý×(7ÿ_1þýßÿ}ù[½²}»ò_òïÿå_~©àóoñù?ÿ™OÓÒö¾1FÌAs<â»Þç×maßÇ»{Æg|÷ýëíÓrãë´·ñ5§áýj1žûעrâcW5ÞP®ëënÃr_Ï;-ãO[”yçÅÓò~]-F®ñ_üRkãK @¸›çú:ŸÏs×hÓÒ÷Qž³o¤†åý:zXFGAÍãúç Ë:bôÙíúÚG™ë¼øëÇx¾Cây´¼c>–k<è5-G­oXžqÏó~Žsü[”ƒÑµO˵]1ŒŽ§9pÕÕ¿æà{Œ~; w‹Ÿx®>fÆ«Œ›‰Æ%Ï|“ϽÏʦ¥Eû¿Ç?x„Þ¾ö ^×ñž_-ÊŒ—sÍŠÏmÏ8,ã¡,£a9¿žù[çøøïx¥÷˜†”ÿ6®–—Ÿü<ÇË;|/]uöÑÈâÁO¾Àó+‡(soúõшŽx]£Óî¨g¼¦ïb\Ÿƒù>‹Œ9{>Ö9ÆæqÇgôS\3ÞÊvÇǻƠ=-ño«á™“ÄèÑV‡åÚîø³UÌŠèQoŒAó‡®c.gžóë…創ϰŒ'˜†ÑŽYdÿ:qÑ‹´­Ž_»Gû{/ýöýÄ­?çøîx®ä†åˆ–çˆ6,zéѦÞ(3^ÚKæüxŽî…>¯ô×'^>Zö½Ñ_Ç“ï˜ ‡åûõt^uï£O‡áþºqÑ1ý°\Ñ‚Â2Öñœ£¿µÃ;ûëùœl×÷õÌþzŽuÅzÇåÑ_Ïv|¡ÞqÑ]£% –Ñ“go½Þø„a‰—}DÖÈp¯xD™Ñ0ùŽïwŸ½5Ê\0¼³³nÚÖfOqb›÷ÖÆ=õ ­¡(zê1:Ý‹2cå=Õµ¶ÑÞ££ã–.X¢£Ã0°Ýûì§gÌ`0ôè§Ñ«ÞùÞÚxaǬcÿ¯Œ÷Ý4Ò1>E7çk¨vŒBÑMϘHP›ñÅçUc%8»éìä³ÌLg7S»{Ì…W|Øñ}q;ÏèæÑMñ óU–2{i©øÚf/j0ŽagöÒsLºhœÏ}Ï^zŽÉàF™6G¦Qf|šiˆç‹¦9nó„¡£—ŽAs‡e`Bއ_éy±”;Ç(úÌ'ˆ¥Á쥣 &Ž>~rvÓ˜ÆçOÇÜ4»©{SóÏì¦ãsáMô1<Í~ìåA?½oŽ}4ÊÙOǼóÎÇìãO³ŸŽáÑicħêíA7MËs¡›FS›/½w,cÏñ/7êé/ºi¿ùèý}ÐMLJÁèýnºéhìï¼êÝ/Ž#xéïŽiõš3 ÇœU¯ñQ·ùŠß³j nÞ ³ê³Ù fÕkÔ†yí½1«^ÑPqìC"Š<˜T¯CË€w OÑM¯ñª\Ô1©^ç(‹'x9©ŽŸšŸêØ6NªûƒµÂ°¼ñAæOÍ™äØvNªÃ²ÁrpRƒøœ1íä¤::Ñ…2çœTc›ídLè˜Tãk(rÏY5¦‰¿Ý0«zð̪gôsZ̪a¹çÁÖ1«F=ç>-/fU/0†³j|ñx•1©†a®ÆòâDoí;^é1!³·fÅcNŸÝ5ÊÌ6zŒ9Ý5n –+–Âay£…‡åƤzŽ.xtX0«žãu”ižUwüÔ£Yµa >FßÓ¬Š×5Ú:úk¼€ùŽGÓá¬zóoÅiuÇ@ ]‚òœã·Ð_µB;ŽCójGã?Ž“óªæ›ã¸8¯jz–':X. F5œWý–Æy5>-œWÇU³ýs}<çÌ`‰ié˜W¯íÅøqļqÌ&x`ü=bÞxf|xÏ1<¸cêì°ãàeœÇœWË5æÕhÈøzç‰yõŠ¥Ú|Ëç…y5,xª×0±rάcð9ðS­q<ºÈ|_1 Í™Õ_4¾É3ǘùþ§Së9f 9ñ§Ùe·sNzã;\è±cÚÅkÁeöØqƒs,8b…÷òuÍiï¸Ì®1œóvbØzëo_¦×¸è¢eίט\sc~-–† öŒ5Ál^×à ֟üz8Á¾_òÕÛ·{½'{ìŽý®ãÞ8ÁjN°£Q¢Ý;&Øxý®:0ÃÆ oç>9ÃÆ¢eÆX5»l ¬ ÃÅ 6‹Üœ`‡¯ën˜aGƒF§žûwY€÷ƒ6‹p³$Ö~7Hþïgã†I‚ã«öPIp¼¬kE‚=>6h $ØcÝ Ì ¶>– ààɆ1N$Øú¸k,IH‚­?'‰‰$Øúh+7®  ×fÁöŽë‚`‹Yò® 8,lrÁö޶Z¶w¬Ù1_’‡åX9°ÍyeÀííüèâÀ±»¹ ¶÷ÙøãàÀöb”8ª¹¸l¶˜Z±nÄVP`‹™–? –Îeƒ(0æU,/EÛø¸çû)¸mLÛÁÎh ÜFCHˆ·ÝlF ÜÆ¾€o¤Àm,Ip!póø\¸ÅŠ?E Œ‹°'nã®À¿¢ÀíxU (pÛÕøD[¬tÀK¤Àm|¬8…Û@ À)0 Çó)¸Z0 ã·Af¤À0àÉ·ñ/¸=Q`,]°S! œ‹2f«-F|ü)p? %ÆÎð¹@àvim&ÌÇ 0Iè_"n‹|DÀ¹°úÜF—¾ŒknÜ 0Þ)‘ ¸µ*vQÄ€ñåP1p ÀÝ·½óå‰ÃrÍW. Œ¶‡Ía`4€6¯ÆU/-˜©¶£a#ÚèÛ!Æßo 90lÃoc¡ €#Fï!ö³½ ã—ï£^ ÁøÚÀ`Þ¯@p;7±A0ÖÄ„E‚`6P‘`±££7‹ãSá‹ËýËU@Áhjx]BÁ¨ã9QpC"*y%€4,»M‚ÙJD‚q^ºH0ƒH0,Ø„ F£}Œz0¶ˆ·‹bÜb^°£cãL(˜ÝN(¸]/ÁY(XÊ£ßaD ncÄó ó*¢`°ÿ&Œ‹žÊ‚¾“@Ð}U¸¦‹)Wð㊋…äDÂ$êwHq ú¥(p»5‹ãev€)0,'¹¯ŽlF Œ2d*R`¼ºÜE ÜF;%ôKŤÀR (ÐMÄÈG¨¡Ïè6ctw6Æhø.è9À…ØE ,R`|ìÜE Œö j†åÆU¤@·S`ÔÜQ†X, @·+S`<(è˜.̯ ŒÇÜs„@×"Œ¯AÂ"z^0 ÐíÑ Ÿ j½P Ý  Ö4©r0 ÐÝÃ-¤!ŒÛ!rRõO‘]B˜ð_tàÖ¡9U-Xø—¼9â_üLÇÏÿÜûq·'ê!þEsŸ‹sã_¹ŠøçÞkü+¿EüËšÅqÏøâ??–ð/[£ð/¿%ñ/ïFøçOIú‹¿o¸„ô¿|.ôçáÔôç…é/n†äIúËæ(úË!úó§üeÅ‚¿J¥šS“ªËþ<¸þ²3 þr(!ü•ZšæTÕö‹KŽêÇ2-Äú¿û\“ñŽùÿëŸI}SÏ\„ÀXǬø[É þ½1,!pÂÆYÓB —N·1yR䣸>ùTüË©_÷­s¶“¸É  Ûè·{å¿'†jèlã×;î˜B` ðÄ= [`Ú'ùïÙÆ0÷.:à6 4 逡y㥆o̽è€[lùB+„¸ïÚ¥uÀx* 6…ÀøÔÅoÇæ†…Àø@ø0÷ §_ê"À|"Àñ¡±„Æ E¸#Æ,†É^¸/~ 1W…ÛþÀh@9`TŒ/%Œß^øoߤÖÿ¢`‹ZüÓ%šù/^'¨\ü?-Lü·F§È¡Lwâ檸™{À}‘‹¸.£àxì "À= †LÜC$ï‘Â$ÆC€Þ€aÙÐ_J˜ÝCwLAOØ%n÷Ø0‡8xŒz- p¿%ì £Ú£0ªjˆè­*àÚõ‚€ù„€qÃà 1`6k3àhÌÿÍ€ïÅj|oR`,ÏN œ­b˜â §«ai+Æþ8DFB`cP¡ŽÌ—. Œ‘ Œ% Œ† aU˜F}mÀR%˜W™ÕÅ¥ˆ Ðc‡!pTLíÓÕ{S·×Š¡0ÖõŸŠ€…€ïþ ÇÀ`Ì!è.BÀh`'à¾KF%@h »‚0Ú¶$€9r£Ë·sFÅR`|ËŽ«€9øõ:Íi þ/z­ø7þ»ƒä„ãP$þy2þÅ’ü xÜ£ËÂB£ ] „€1)‹`·p?/î˜B:ÕAP`8nÂ-Be0dŠ÷Ø‚ŽF Œ2¤7Rà^‹¿~á*Rà˜…±.†a#b^=(ƒ÷Ø3A@`\ƒE¶ 0f©F çU5%S`4Z¨.¢À˜y{¯&Ö[5‹õÉ“Ë Ø% ÔÐf Œ9 Œ†L‘è†l ôÜe Œ§8È…š[Ù!D¥Rà¾Q÷ÃĺÁ;É,Ì…€."Ì× ôâÁ=ªAâ;4­ÚBŒŠŸyoâ¿,±¸7úí5„%¦E8,h"À ü–Pƒc`#±OHgê‹áXe껹Mlìo[ŸÆ¾Ñ–0ËûÆU("êó3$õíX¡ú¶ðk¨¢ß$E° /ÜÎP­ o<,ÀZЗ”Jæ+‰ùÆ2e_e¿tã”쇅j¡¾mÜöÊ~±º]¨/fH,Y,û…ç`L²_–‘î7fZ¬ ­û…¯ìâý¹CTïÏínT‚¬ûæR?ãöP‡T?°èg À¢ßE£Tý¼ÃnÕ{˜)úiKÝ¢Ÿ·é«èwÒ"ÑÛ»)úi·4E¿,#ÑÏ…U¿”¥úYwIÕOª¡/V|p®¤ê—E¤úYU±ìçz¥û‹°kòÂ_þ’„?íaáÏ5KøsÓ²ò7º<µLQ_pêJ}÷#õMÔçfcêíû¦¾Ñ ŸUùÓiR÷1 }Ö2 }ãKÓù”ÊŸKVZ,ýi+9¥?md¦ôÎÒ‹hŽ™–þ´ßœÐgùÅÒŸu]SŸœ©Ïò›¨/ „>m™&ô]ç7Ðl9¢>· Y$…?¤üùîRùS3±ò'Ý¢(¶HùÓ&j*–í[ùãURþRA”òç†lå/ïÐÊŸ”Tþü[B¿¼JèçŽeô³¢)ôË"B?÷=)~N‹y‘Ô¿¼HêŸW«¬þy`JõOÏi0ïX ß—@ïM[Ôo¥¨õ@ €©§I´,'ýO²õ¿ƒîF©ÿ¥NGýÏš—õ¿X\ÓÂÙÕÊC €%¦°(0uN €*cô³ò`ô“Ô\@i)Zܳh‘°€7®’˜êžÀ¼J 4·*Jð£È9­(€–#­Ê’ Ç‚”ÕPRëvK€C-ZøH Ðe$ª¹'æo ‹EŽ5®Y¨N’è&hÌ_ºŒÐÕÝÚ…€YäÈ9–EΜc·U”›Tê€'·Sj|ÒåS’: »šuÀѱÀTÖ-´ZôUÖ5„¤è{¶è'µ¨N,пd0ë¥èÛ³˜7#!0/’˜e$Ê%…@¹E¥(¿“}••@; ¤H/ûTÇ,´}Sõ©ªX LÏR †¥ÀÔS | Ì»éé_3‹üT‚÷ïšß>=`+ûE0PÊ.Ÿ·Bòèòÿ@]>÷¦X?º|æ5rùEà[h—ÏŽÛéò;ưÈå3+¦ÏgX°o+ŸÏR3}>Kú|fÍrúÌ2rú,eèôYÊÐé³”¡Ógߟ¯ªù•Û¡Ïg>ƒ|>óÉéóYŠÿ Ü>K½tû,eÀ¥ ù¯”!ÿÕ2à¿òPä¿|(â_5Ìé©Åö+ _5Ì©©&ø•¿ƒûŠar_ýûƒðbÈ}Å ?ü·`ß1¦îcÁ¾³±Ÿà˜?H9æo“8 ð;^nwfÌŸBÅò·É÷XÜ7?Ô§`ßüN¨EÛ®¨@Eüm uÄßFñÔSÀߘ‚·…úÎMJŠþb›˜ÞŸ ø‹Øüþö[!€ øË_RÄ_Äî,Ô—/TÔ—Ñdò'ÕÆ!±¼d cþº5:…ýÅJ 襰?G·9ìïÑ.ŽÃþ‚Mê;:E…ý½ŒÆô9ŠŽÌ?iÅa¾Da¯‚¤ö·Ÿl4B¾èÞ´(ìO!‰"¾ŒwΨ¿ÃEý튫#ñÅgY¢þÒ  ?ÇÙ9è/VΟ|ÑÛ Žù‹I?Í ¿Kj°ƒþbAþIÞ‹â¡bþ©?÷² :äïÙ¾‡ü¯‚÷òÇô%äï¦Îë?ÿ¸Cþ.Å1gÈßiºÄüÝ JTÌ_¬nqÏŠù oÅEè;cOeó³ó‚{õ×1³UÌ_1¼ ÍíKÌ_D8­®žJ1íÅú.B_ÄW1–´wÆ¢”FÚ‹Øæ{ ú«Ð^\ÕÚsÌši/î§-îžç\–Ø °—!k‚½ó¡Ki/À®RÌßÉvÇü©Y8æÏadŽù{Æ’1ãáèÜ©˜¿q•bþòþó¯„Q€Œùs€šƒþž‡’Œƒþ†e'Û1è/¢Ž!¯)è/-úóUú»¹ÒΠ?ÿ–‚þ2TA¾eýéË(æÏ¯Ø1±1ŽRÌŸË8æÏ7ã˜?µÀŒùÓ/eÈŸž)Cþ.‰rùs5 ùs5Šø³AÏiÿON«.¢x?µbƒ^m èEÛßèþÉiÕíš —­X —/‚ øŠ£WP™@/ʼ‹Ú—¯Æñ~z‡û¹­9ÜoT €T´Ÿ¿œ£ýò—í—ÏDÌËÆ'ÌË»æågæùÇí÷(­–¢ýüq…yÕ‚hú4ó<d´ß(þv´s4d°_^¤`¿èèà>û¡iÊ«ûqôË`¿ŒÉS°ŸfÀì· ^©Ö¡~(à8¿5Èïk*ÈÏíÐA~ ÙyšùiÝw1ï‰\Ô¼5—K¸|1u r¹8žÌRž 5]8_îZËëÛŠsÃò`ik)Ï^.–òì—e)ÏîI–ò†…¾¡’òb}¸zp¾JŒ -Ï:iÑò$¦ §|ÀÒ…ÓõØ…SkP‹y1ö/j^Šš·-.œ’Œ"RóÒTjÞø˜Ð&,çõó» §+N9ï¥@`9ÏõXÎË«$ç=ò㵜÷(}†å<«¡–óÒ"9Ï‚£å¼xfwá~côVü弬Fr^Œ7Ôï°ß+öUгdjE/DdRôÆ/ÒÕSŠž›©½Gùh,éÙÙš^¬ùP³4½Q3V‘ÖôÚýµJzY$½¼IzY1Ø®õpaÛ…å“`W ìªe’]5€ì\ÇĺúïÀºjÖU °®Z€u‹åÅÖKZ€uÕ¬ó½€éj0]±éªLW-`ºÅÒ±ï’0]µL¨«PÝbé_ëÝëª\W-àºÅÒ±ñ’p]±ìª`·XæT-»jÙU ÐnZСˆvÕ¶«Wíªe²ÝbèØ€IË„»jx™áÍÒÝb™tW- »jÝU èn±0ÏeZ@wÕº+ONº[,“îªtWë釻êUÃøªå}¾õVÒ])º[ ¯z«.:uX9/wXZ®ÃöªxW-ws‡¥¥]î°´<»;¬,¯:¬,½¹ÏÒò^î³Wó¦‹ò]µìÍ}vñ㬖swŸ•¥­E®æ>KË}~­wÓv÷YYºûìU9«¥Ÿî³‹#çbéî³°ïÊs’ïªåØÜgeéî³WUóª|W-÷æ>+KwŸ¥¥Ý_Ë-“瘟oê³¼›þ¸Ï²È{»Ï^ðªEÙa‹åqŸm5 ¯–áÕ2 ¼Å2 ¯ZîÛ}–0ÞbyÝgiyrzmUÍ«÷óæ Û*ä ¯\DÈ«EO²2¼kŸäeGäÕ2wN²¬çÎI¶UÊ«–Ç“¬,À¼Å’ó,-oγøub^µì9϶êÓY-Gγ­du©†kÿÖgÁyÕp›gÅyµÌómžèÕŸê9ÏÒòzžý$å•jIyÕ²ßß:,)¯–9s’]@¯–¹r’]X¯<p¯i9ɶ‚{µÞž“ìL\ø·ãú¶ŸÇõEß<"Œ*ˆÏPøŠÌèß锆ÂȘT4¾g¿w¹s*Ágl²,q}Ç®ìNð9æÎgIð™jA&øT’¸Lðù0Ì>|: ©0ra£Ò >/ñ@Mð¹3Ô >O…â;Ág×>¾|žò5s‚ÏG:„|Þ 'ø¼…jÊðùRúõŸQ¤J|àĈ™ßs—»¤ò{F\ -Ìï¹K‘q~Ï£3¾RLxõï}ÑË$&¼cüSðÞ__ ƒAP„DˆAÁ‘Dx¹ž™g@„÷hQÛB„;wõðŒ×¹Äõå‹ÞcYÍ̘Âëà ¯¸o”!^O·cø¹­ïºéâ+¼F»d5äÁ+¢J—Ä.×xZ¸Ï ãª{û®G;"ûÊUûâ7 €ÌB)ŸÏx†½&v‰\²pÆ–Øw=Òß)öå#Hì‹›Y<<£E`Ý'­ïê É”Öc,SRë ˾j}ÚM­ÏªŒ´¾Lñ(­ïÚé`a­Oùô,õ……hOI}¡=ÑÀdã3_‹Òç”c’úòfœâ3àiA2e¨•Ö—ˆÄ¾˜®·%µKèPW$ö]—ö$ö9'ŸÕ¾‘¬ö…‡t…ÂÑ$v¥¡Ú“3¼ý,÷iŸ7õ¾ðKGÍÔûbêm‹‡g¾. ~±mV °¤V–àéŽ{õð¼"„D)~ÚÓÌ,ŸÎl)ÉïêŽ$¿è­Ì¥BÉ/†ô}‘ü¢÷+Û $¿lê’ü®›ϹZr»”z(ùE'½É/FðwñðÌ÷.ÉÏé.-ùŤ/¹]®S1 ”üâ…a3Ó|j†QžOMNó9ÖÁŒTšÏKÎþNó©vë,Ÿ]AŽÎòù8ŠPi>#+÷¢øÅ8H}Oi>_†r:Ëg³¢¦,Ÿá¨ NY>#ýÔ2eùÔíd–Ï»âàüå{Iñ9ºÒ±Äõ]wWÖÈ}~ –ûbJ¿çÎÈ¢z/Î1l‹sçQÍtåÄÄ«Y+R/Ù]bÎé‹sç\àRÜcâìXþ’ç*„ºÕ¾ø,Û’ÜåjÈ*l±/ji”ÿ˜7ûâªPb_tø‰Iìs_•Úw]Œ±Úï|ÃÍPí‹ù…y8©öÅ´‡¤©Rû<¶YíóÒÊr_Ü”0É}ñPðØ“Ü—Ï ¹/î‡áÔû4SYïË÷'½/0ƒ>šü¢Gí‹gg¾'øÌÛQ‚O­àS}!|jw‚ÏXÞ-žñ’¯Å³3†$uu‚Ïç‘(HÁ/^2óÂPñ+?NÅ/ÒÑÃûY’_´œw‘üb¤ FIÉ/û¦|úá³+ÒÌ>sid†O¿i~y?Ôü<g†Ï»-,˜Ã|føÔbÍÏë"k~qñ¹ˆ~×ù|Ëð‹á-Ñ/~ÍK¢_Üü³%úÅUð™–è Z!šKô‹;dšMŠ~×!ïpé~N©lÝï:äG-é/Þ×Vü¢™öŠƒsN†ñï:?‘‡´\¦A’4–õÛzâÆh{¼Õ<ÚC^ô뱈 øŠô$ýÏãØ£±Œ9Ù,ëNK3$Ïñ_ó˜¡ ´ízl)õЦzô׬çš~"õø¤´d=²±ÿõßúØ£ð&êñ.þ-=z|8È~»€þ΃O~þåÏ㺱ñ—'Á|oBÑ>bq¾RUO4RUO9ÑHUe)VU ¹*ŸhäªÊ‰F®Ê¥TU)äª|¢‘«*'¹*—RU¥«ò‰F®ªœhäª\JU•B®Ê'¹ªr¢‘«r)Uõ¯8öh:‚Ævéÿ¼Çýž±ñ§u¬ûÙHøÓ/v™etüåþò­–?|âPì×ìÏÿȇƈQ¯ü—4ÇE_cÁßìiÌS‡Ž¿}êÐxš1éÆûÆÚBínqr­sŽ uê o¬:îiÍþ™yŽ_¸JKg€.ã¦Îã™™`3ÁÀ¾Â3{Dì3^Ó2ÏãÄÍýÏa™‡‘#ÁÛpÿìX0á{ûÖÓ[Îpw>kJô3~ë“ÔèA3ÝÐh7LŒt>±³ôÖßzÂýíªO1:KôÕ;6æK×Ͼ:‰·Ó¶ÙWûš†5NWÀ/MÂô }FS½vë\Ò_î²RL8ŸHZæ5¡støkvV7¶ØŠ¾{ó(1þðeSý ŸÀEð½û97žØ@FëØÖà‹5,/ºª6ýÏŽ$øSMÀ3ô±âŠ®t…vÓc[éÅSÝ(ó¼ÁwÇÖÃøbqïs ÀwêqPÄ|'”ó´ˆåì²axyâ™Æ÷woPD|ï ¦"âŠß+©`½É²Ã2›ËÜ‹&ñ^ ½56`Qæžîõ¥a¿m6ëÁ—y[jSÌQ†¿7¶–úÇÛg£aîD6Æ3uÿ‹[Ž–umã»nWù¥+’çß0Ì1t àXDFã›ãÖŸ³Á2ÊæÚ¯kV ö‹8à“[‚sŸýšÉÚÇZË©æ¾ÍËä}W¸½µ†F;a÷ 7¼½öÃ+§c1óe§óùT'3_6g1_¾81ŸO2óù /3_)Cè+e}n@¦>¹¢¾RäH™…E@}Ñ)0U‹ú|^˜©¯”!õ•2Ä>w.c_ù)b_©‡ØWÊû6¬ó öYâ1÷E™¬Eî+e~y?¿¼g‘_©äWª!ù•" ¿H„E´È/ïx’_>’ÈÏÁäçÄL&?&¿,#ôs£0ú¹qý<3ý¢á`(ôËú•zˆ~>jÌ臎iîË÷+îóh$îËÖ'ðS ¾¬BÔçFnêóØoêsÇ4õ•zH}¥R_¾Q_)CêËo-êóünê+õúJRßìYóýŠú²é‰ú‡†¾l傾|í‚>§Â2ôåO‘ù²1_V#èËÛôyš0ô9m™¡Ï£¼¡/ŸœÐW~ŠÐ?uêÚ½üΣ Õ÷òhBõïtͨ®„Ø—õûòÕû´B5õ•"¤¾ì„¢¾R†Ô—ÕúòŽ}þb¾l|Â>gxöeöeË"öeûöe«öea_)cÿTøùï>dÈäβg%¿÷Ä– À/ó¤ üò,Ë~á]M²_ÀÝ^Á/3öXö ׫FÄTŽVÄ<)»”)Ç͸+G§ËU*Û¦2Rþ6æò·òƒ,õB_Œ¡Ôù¨üEÅä8Ÿ2Jü".«“ ~1Æâg»¶(ý³ä¾| ¡_x<„ALTQ ñè[ ¡_<ü±á÷.èÛ¡'Êý""Ës¡ŸsLý""»ìb¿|b¿Èfàû•šÁ~J¤dô³ä§œOf¿Ù.Hz;Ó3ml!b¿£1ÀÝìçôRf¿pB¼ö‹–!ûE+ê 8²_±ý½ñ]ØïÀQØï¸éiö;â°¶OA¿X´Eø;n:Œ ý¢¯aBèwœ—¸èw(ç¾Ñ︘;Ùè·4úÅÍ ‰~ñÛ”!‰~Õ‚¹êmÒ¯Ð/¢jÐ…~ñàF¡_UtP ÄdµÇ}ëˆ~á<û.ÂߌLqýâ**rD?Ÿv"ôÛǃ¸ˆì2%Ø/N-Øö‹¨(ž{ù²_µ¼<à¡KÜ$ü¥Eð§cÌ~¥Ù/Î¥:á/ïVìø!ˆýb½üÒ‚©*ŸZø—·,ü‹«ð1…sÝ«H€å·€€å""`Þ 0Š\ÞÈ€¥!0ïX¸_¯¤7B`XÐlñY°W"Ìûæ;ކô)˜/BX,$ÀR P•ÿüŒÆ¿¸[¬¶ˆnÑÆ??¢ð¯ÔBü+µÿü¦Œ¥⟿›ñ¯ü8ñÏßÀøe:`øWê!þùÕÿŠ…øçïdü+eˆQ†ÚñϯXøWª!þåË þå“ ÿbÀª|â_Ä5î9âŸ;”ñoR‚…øW*!þ…bé/‹ˆþBiú K'bR‹òéÍÈèÕ^‹ê—/Jè—Ï$ú+W‘þJП“2ý•"@ÞŠè/ÿ]ô—·"úË· úË· ú ð‹ð—w+øóÈnøóY3†¿R†ð—íCðWn‡ðW,„?φ¿¬‡ð—?%ø‹¾òVɯ¥Ÿ\ì—.ø+¿DøË·.ø+Â_¾ÁŸ›§Ø/{Šà/.–†àß[ä—÷"òSb_Þˆ°/‡"a_vHb_>³°¯TÓ–÷&ì+—<šK]†ØçõeÛõñî…|>pÉÌ—mCÌ—¯@Ì—]XÌ— \ЗZÐç³ÒL}>ÍÔ—OIê+?NêË7Eês‹ôù5ˆù\BÈ—)äóü#…ŒyçÜc©˜·_ïäÞ9Æ”ªïÍó;ÞÕ»S‡à¥wçùp©mïN¯%„yûÓ¸tæåJQ˜·ß„ó£0/,WÕ÷†…‘ÌÆ¼=–8¸Š˜·GLÑâà¹?Kb^L"Xó"„ýª˜·¿Lði΋YE.1%½HklÎ;6‰Kâ¼°P #çEð=>1!EX<¡Ž˜wlí›ÂwlÒw„y¥bb^þ¸0/à*ÌÛ#;.ðŒ˜·G  Ž˜çÓöŒy;]BÉx{(×(Æó餆¼°À©Œ”§ÖlÊS{7äÅJò!/—‚¼ˆÂ£èFÈK¶äÅB¿LÆ‹‹ G‹ñb±ŒãK×”´É”Œçà Íx>ÃÍç3Ü yáy>@ÎWª99%¹È¥)‰Cž!/ÁFG?>‹wg\µ/çà yùœ‚<¯/ yQó½xwî”ò$î鬽$<•›„§³á’ð|ÃIxØ‘„¡³‹kgÜ݉Ÿ"át°LÀ3ò=ë"¼by׳6 áé³™ð"È”b§%¿¨D<ƒF¼,#Ä;;ülñ|?F<ß/ëâù]ñò*!žÞ Oîµ&<×+ÂóÍ$áé¢$¼]bœ O¯+ OíÊ„§S˜“ðbl‘ù²™ðò· y¾Cž¾¸!/K—Ï%Îó::9ý%9OË3sžö_Ìy|Åóx{‰yy0¯Xˆy®F”—w'ÊK‹(Ï ò²^Cs‡ÈÛ¾ùvæU†<µõ„<½¾„߈/«ñùƒÞºb[Ü;Ãò¬Ä—w'âK‹o\E±MÈwìb*QŸïÎÔç_7õeQ_Ö,êsç4õe=¢>Œú”´8‘o³û)‘o“Ë´‘o{¤1ùX©€OgÜ&ñ…v²8w†þ¶F>ƒû Ç¥š7ó($æ=‘û¤ä¼ã:$Ñóâà”¶ÈyÎ1c΋ìB(BÌ»0æÝiÁy±ö„?–0o¾ø%Ž/²õ\Kß3Fζ`Þƒ\3óžcŽób•¸Õ8¾'ò ¡b^!uóbHoPb^døÙÓ3Òû,˜÷Üâ‰y}<Ù¾ÈyϽÉo“œ‰zÚÂyáNb#çÅÁO}ñäì£ ô…óž—Ê´9ïy.xa›óú¦]yq^ߘôÀœ×wæc1ç=c^¹—8¾§ÓUB¨÷<Š‚êõÈ4,ê=¯}7ÉzÏkoOÂÞËãÅ›óÙ$l öâë²Â^ D"Áž“˜™ö"±XE´—aG5–\œ±|ŠOíÙÁ¼Äòi¯Ä±|£À;ѱ|‘1®Ò^Æ!9–ïQÃP,Ÿb2–ï9%¼‘ö츞±|q —w,Ú‹Éè^bù©±|Ï.OÅòÅ‚x¤X¾G½Ê±|ã*ºTøÂ½Ý|ŽÈÈX¾Hʶxs†ÏûY½9Ãÿ^Ü9c¾«¤—oݱ|Œw`(ßx­Œ!$ð]ç.ŠT(_hº(Càs>7ŸÓ–ø"q”i_ÆŸ ø2SÀYïðÔ>' 1ð9©‹ïŠógà+¿Nà‹Q»BæSX‡ˆ/^Ö|‘ #/rÆÜ ð9;‘/_—€ÏyV |‘ …~”>Ÿ"aàÓ æ½r7ä=åYÉH¾›g}g$f _¤Q\œ:c%]´—qc¢½Œ¥ íE5 Üc– ¥¬r(Ÿ²r÷œŸ*CùŽ—²„CùNžœ±|Ê÷”±|'`ÎX>=ƒy/ÚñËi û|‘Tè^€oÎ$ŸÂ{×yÊ%RÁ| ÊX¾[ax æ ¨OÒ^dÈik,Ÿ’‰öœý)cùüˆå;þ¬Bùú%T(ßøÄç¢èåã(’O¹z2”O š2”o°€Ö¡|JV•¡|‘ÇeÊw„'‡ò)ç_†ò1:å ê]X/fnœ"ùl` _lË<É—•öäSdÖ;w­uȧ|MȧÄhÈ—ò1;]Æñ ÑÂ8¾kØ)Ž/8ýSH¯\¤0>׫(¾kÖ)ŠO¯ÁA|ÊÇ•A|þiñ)QTñmϪèÙß)ƒø²ñ)½ZñeÅ âSB§ âË2 âsSsŸ&› âS:Ç â‹½î5ˆÏõ8ˆOiî2Š/Ë(ŠO‰ù2ŠOiÚÌyÑ~Î%ŠÏ+}GñmòItß&÷ÂÉy³­ê0¥FN5ì‰óâà½{qè ŽÀ@(Î;Njæ¼ãfšÀŒã‹lm‹º—¡ãøÜéÇÃ1€Lq|néŽãsu_|£Åñm ,u(Ÿè9”OIÇ2”Ï#¾BùüvÊ·óŒã å þØ›©zQ„°ç³°Ê‰B©åÍüUË;Ξ.›‡øM.›¢ WK2Þqh±.Æ;wÅÒ ò"¯Éâ±KÙs‘ò"ßÇŠxüMÄ‹„s‹’÷ÄR}qØŒ¬³çâ°9óÅBQ#ⵃ¯™7„xÑ$[E¼=÷GÄk»4—‰x-V¦tàÄTt¿7Wdb¼v2·¢¯E÷[¢õÚ£¨01^;8÷›ñÚ˜KðYÄxÑø˜™…Œ×º"¡ÄxíbÖS3^Ü3U72^kÌziÆ‹¼¸‹”©tá<&ÄkÏ+äâµÞä JÄk]¤D¼ø!xU ñZ§K¬/àæX|6óý‰ðîaAü™/“4ˆðœAׄIÚ¶…ð"ÏQ¼Ñ°[|7“=•ï¦e«|7µð§ò]µ€ï¦…´4ù®ÀwÕ2ùn(Üm”Ü™á[p7-hÀ„»ZpW-€»iiUÊ«õî¦å­þšå*Âݰ§wÅ)€pWê!ÜU à®+œôà|T»7%|™pW €»j™p7 „FÀ]µ<ë »úà»jÝ•JHwÕº›–NÎ9 ‹rÏîªtW¯Â’b–«“î¦Cº«Ð]­t·X&ÝÍ«î´W À»R1ð®!ÞÕ"À»ZxWËïjà]éAÄ»jßÕ«Àwå ðª…$‹„W- ¼ÅÒÙ[µ}J«–Ixyƒ"¼ÅÒ¿®ÅpÊGƵ\™m«~›µ /Ó¤‰ðª„Wëé ‚/ÁgÍ ¼b!á•«ˆxµ /G@1^µœŒ‚Ï«&äM‘îb|Z&äÕZyµÈ€¼Z”—B”—S”W+æ 1¯Z€yÕÌ+DÌ«e€yåÃóª˜W¯æU 0¯<)9¯Z&èÕ‹zµÈ½¹ÇÁÈ$½jé•‹HzÕÒ+Ï@Ò« ^½ŠIW‹¨7I\g×´<ߦWÁ^ý­®éÕW½§;,ÊöKW‡}+í•—Ú«†ss‡åEgw‡}kð^µÜç·KÚ[,Ý––G3¬½k†µ´W¯zwØ·ªzÕÚ«–cs‡•åq‡¥´7ôIÚ«–{ûZ”´W-ºb¯´·X4Åú’þ¸ÇÒòjŠÕ/“ö‹¦XÕLÚ+ï´W-§¦Ø´hе´W-·¦XÿzÓ›–I{ÕòpŠUZÒ^µ¼»z¬ ¯{l«‰[¼"íMÏ(;©/ú§ % Ñ‹g§ÖIöìÔ²%‚O‘VÁwK½S_œ—dT_°ÒÁ×wz0fŸ’{ «Þ@èã „©Ë_È@ÍúX\;3g%ð¾o†,X];ï~KK$²©7%YI ܉ÂÛ—æÁûíÊr) XBøEï%„ïB.<èmÌÝéwåÜÚð0zsªäîl\‰:wg¬Mq•€0ö?•“Ƀ×)ßSñ`ãIæÁë”|&lò4^ÌvŸ@x+o¬€0i_@Ø»ñEºõk â‹×Š”â×ÌŒRüž›Þ¦ü¢E€!•»3Öd°Pï‹"Ç¢÷Ýq’QåÁ'RÊ37&swÆ€Á¨÷Ý—hê}7ŽKH$|âìŸgñî¼ozaKî‹f¿FðÅàÍ JÝ{ÆkêÎØ4@Å”û¢žgIÞ§ í«Ü¢/Q©;›b┺ӷìÔ£abArßÏ»øwfÏTêNœ`•DøDJ~ÆëͽIeµ/Rý=Ÿù×®t/ÊÜyõoþq'ïÁ÷Yü;󉜺3´È „Oœ;p,é[âë2S§rw^—ÀR¹;ï“ߏ;£ó~’Ÿ˜š±7âÔqñ’À%>æQy°äeæÎKÎòÎÜyiVæN?·3w ËÌþ’ÎÜ9žiUûJ=Tû²õIíËQ×™;cëk à‹wŒ¶&½/Þ1Ò¥÷ÅXÐ÷Îx¬Å»3Þͳfî<™™;õTÎÜyqû13wÆ S3wFêÛ{‘ûî8>µPîs³Üß›tˆY5Zù¶¤p‰1€œGµÏ=!3wêÛeæÎ8ëdQûüÅ­ö…ÿÃFgNΪòˆ°ÜÉd¡bJï›KÃ%…‹›º?¥t.¹;™‹ß¹;õÊ%÷9,ä>ç¹M½ï9œÒû"e9]99©*ý°¿ÈŽ‹#Á/²Ïb^‚ß}Ðß‚_´ósüÆ@òI ,oNj_|ì%yKÌSp)”Ø—íAb_Œ5ø´RûÜ~%÷¹;Yîs7Ü—MFz_ŒÛÄç™Åz_~Fé}Ñ+i¡Þý` â‹jZ8¡ºIKï‹ë®8ï˜ÄÇ5_Ü͵¤í,ÕPñËf/Å/›=¿¬FŠ_&K¥âYc¯Eñˇ’â—¯XŠ¿¿ä¾$÷•K(÷å –ÜçaÏr_,Tî%}K|ï}ÉßâÐr_ôÉ{‘û²iIîËW#¹/>&BØ$÷Åà‰Mrßá:Õ­3Tr_¶Ð)÷ÝgÃgÈ!å>ÏO–ûâ~W·Î¸§sqëtã“Ú7=\¼:cH£FHµ/Ga©}^YXí‹Uc©ö‹Ô¾¸Q(‚Rû"žë“ø7¿&2AQì‹ZîEì³Ë™Ä¾;ÅHŠ}^JXì»q|Xòß_sÔ>Påü ;Žì[Ž®h󨼧œ‘!‹Oúõ‹XDþçÝÏ5Á(ëNKž×#íð_ó¼ž6=âë9DiÉzdc=þk©'£«žC”–RmªGý·>?èžçdÝ¿|~ÐÏNÿÁñ@—Xù•àü Ÿù;\jæéÊy¤Ê÷&íãºq´s–R]y4êªg©®,¥ºj)×å³\W9Èu¹”ë*¥\—r]åt ×åR®«”r]>Èu•ã\—K¹®RÊuùx ×UÎr].åºþ§͵òõþÊ)BÇo"ô³ô+§ýZ¹ï§ý­ú¾7ò_+wÿfÿù)B¿g„üiñ~6þô‹g#¹×|«åŸ"ÓÍ6†˜_c¯ÆT¹ã´·‡¹î8'ÂóÒßq¦Ï­оÃ%ef Üxrï=Ïãë°\0L·þLŽ|Oÿ¸Î3<ïð œÁDwïðﻢÈË„^w¸ŸÎh¢±üî¸*v¿"jäÜÜÓ]›AÏ3ˆáŽm˼~b§âž‰ÓgètçO˜®áü=¯‰S-æ†ëÎÄŒwβG™ñƒsçqX:Ntï‹Å{ž ‘/¯^Ä-ÇgÇ ÎaÛ°pûê¾5ý$ºƒ.ú‰`ô¿ûLQfgÀÛ_3eÚÁ|”ÃÒác¶¿ª¹Ï³Xžà°¹`¼ïHøŽ4U3”òn±ëï"œÁ:,AÇÍ+Zø1ܨuº¥Ý±Ó:}Ì|/íÜM§ë÷’éc¶#SïÝb‹©á±;~ùžÑ*ÃÒ±[p‡# ¢éoÝK›^ë3L.Cï9¸ÎzUîðιçËz¾Pqì3u|4ëöÎÆü.ó†Ÿmz©ÎŒO7ZÐ\s:nX& jV¡wÄI̤iLp?çõÅ{9Q –VóswÔrEžÂù*¹D½7»ØÓ.DENóixvþåEÏ”Ofº<É~âÄÚEp3·ÂÜ®¾#䙹°}9 o8^–&Ü÷†°?¾–cn@Τ x3ýœeð×—1Œ»{°æ‹(1VÛ†înŽùwoûì¦/÷u‡¡£›>ØaÜÒf/Ujˆ»‚›½4²â‡ÞÝ´ó`åaéùë ã¸_4óGÌäw¸ÔÌnúp‹ö~ÇÎnÚ/5,ÝÔ/ï=otÓÎDó£N„üu¸Íßï½!âÏ ä-¦ùª¸×v¿ífÆ‹‹}ò}NDüõÆ‘åí3¡Þbé3âoü-evÑHÖ–ÑgÏr¯-²¨_wyÝ-2‡Ïp¿Î-¶á ù<7,çp¿´ 9ßø°<è£z ¶Ý7Âýb;ð˜–v ܯ3 ¥mVUaÙhy˜ä…ƒòd.&yyá¿Ùf$ñY¾Ó°¼ˆÎenÅw2È܃TËq âïáñê-N»{ÊÖ"®yöÒ‡àmæxÀOŸ¨%vK[ùü-nôÞKk覚5ZüéâkßP¦ïè§Ý [4LôSf`i1*Í~:Ö8sPnsÜŸe6 #íØwvTæRis<>ëoGcGÝ!¶HX8ûêƒ=ÐÁð˜QvÞ"‰à»¼ÒÈËxá“Ïѽ3ª’´´ãÁŒêjN¨yw]3ªky1£:?̘48£>tÜl‘¯R]¿™9‘/›I¡[ x=%Ëv;OΨ~î3vžÅraFÕÚÎûdWu‘ÐaO|´“³aB͇8L¨ña护EHÄöÂ2÷¢ÚùjFÕÇ;_~¹ ÀíÚ0£Æòã†eÇŒ?=§ÂaJgËá±…Ûúì­zç!9ÎÎÚ¸[Ô¦·ùžËšñ(³¯êpÇÆ(°ÒÔ®ÆùÔOµÜG}¢8™ §&²Ï‡ÚpUì2õú[¡ÏÎÚ¨”´{ãŒÍóÍÄæ1:«š@lló–Ñ{ï“SªÛMlè´ò˜±5ûªß^¨hJlx¢LÛ¡-+¢gg_u¸Ωî™wçœÚ‡Ñ©;?õÇ_Ωn#mӜʽ¿ÖvΩº¨šRÕDÚÁYÕÏ0ÕW6¬)FµÐuß«~˜vcV-ͪúR¡×®>ÈXûRzlí;»j£T6,œUó Þö­«>gU%€jÏÎYõáŽk‹ÈÝ‹/ 3Cï¾k™È3½´¿çâ´êgx.N«Ju47ûê/ö4N«ZÛ´çá´ª·!¿èªþñΙ5-óg–‹I—³«*Ű<Ébgë\¶~pfÕ/÷“k£:‘ «¾îÜxxÊ—ê7çU÷(íV¨Þß{¤P¢ß6çÆŠ~›ÖF¿±\ÂRJè×c]f#úõƒ–B¿k@ Èox˜ ÐoÜ=C7„~ó ¢ƒýFûáã-öŠýšýÀÉ~ó¬"pÙ¯…RŠ•?د½çAÅÒqÀëÁÅ Ùoᙉb¿ ;žd¿qÕ…c±_{ofÐûµXñMÉ~£ b¿Q†›Ôb¿öÆì Øo\E-Fì7Êp¦ûÍS@½d¿‚+–Æd¿H!÷IðÛ°áà7똋4€ß¶™«~Iõ?Ÿ'cð‹³–°’ø)…»Áo „Ãïü|œŒÁç™úB Æã‰ú|>©/ÎMÂÇöÅÚíCØçÌ}Îeoî IdEìó2ƾ-Ö(îó3 ûB…¯û"è ¾-òè¢b_дÉ}>ùÉÜO ^øÅÊ|N¿¬Yà·ÝLâfòó)&¿íb€—É/Þz¥È/\ðç³( ¥fÂ_<HšðçÜ…†¿ôÒ_ˆöÛBñœ„JÒ_<Õ…2¤¿xËØvý…Öv"ú‹2;,¤¿¨]Nôï]Aô—oPôï+üÛÃqà6ö/„±í…ï'ü 6X„ñz°BüË—!ÜÃx@€q €xóÔv3PÕ¸…Cˆ‹¿Câ"NW  p ¿—OÀ(rá" ©0*Æ$)ŒÏ€"ä¿x3XZ‰ÿ¢ºŽ$ÿm÷Òü·5úÒý} €Q« ·€[ƒ¾dþ‹¨øç/iü‹‡ÄÏþÊÏþâVúÛ£(MQæÄ/‘þJ=¤?÷ÓŸ\ð_ë1ÁßÖºPðWÊþ¢Ñ`ý ú‹ç2ˆþâb¡LúËo)úÛ¼&ý¹½ÿ¢–@üË7*ü‹ïÀ6â_Ô³â_þ”ñOçÄ%þ…÷aoc_íØb1þÅo`2âß>$(Cþ‹Fq“öÀñY3ù/ߎø/¿ø/žô’ÿ²/Nþˇÿå‰ÿ²‹ÿ²ãf°í#ŒzÔĊ–2DÀ¨À/,5chÀD"`<8)–­+X!`¾!`>—0KXÊó§„€ùSDÀòKdÀlìb@´fÀrÄ€ññbÀèX„Ä€ž(Í€å·iÆ—ÀŠ_˜¿% ÌÇæW–zHñm^¤À(ò,˜ã&)0ŸJ˜TXê%f+F[Æö00[“0p ì'rzu×fŸæo Kb`_ÂÀ(ó¢ 1p›Úÿ§``”Y‹³—ˆK=3‘j¨$pê z…`Ì1O˜Ã¿80?ž@0~ˆôH̦#ŒItÁòS’ùõLà”¡„ÁðÏÔ1°†Áw¼òkÕ;÷nƒéY`pz?VœÉþ•}n†…ÀÜ·hMJJ ·QS ìÌpf%0u?)Y ”À®¬†çß"Û.D“xoX»X Œz6Z0sÍY@F)0D=¬ü$ƼŒ·#)ðˆìŸ.J å +:W&•À‹#z*:r)•ÀëÓJ ¼›4F*/óTY Ì"H n“ø<‚0)'Sþ¤“2 LJ Î¦1†`GP³(©ÇR`dëÀ¯ S[M)ðd´xœú-iRþÄ„ÎóZ /]OZàË8©žF>‰AÈb õaRá9¨V1ÐÒÅ@m¥› £µŸ¬vÆ.9ZŽ©ðØ Ï–5 ¦¨]\SaJÈÖu"Lê±$¦Bˆi+>è½J‚7ÝþRÔ^ ¨0·#% ޶Š.#MP‡©ðØ»îF𠤛Ô©ž XU|%5Z|‚®0Õu ‚)A°SÿÜU®’"ØO¤A©yFÂh€ÊX´øHE°Ó{ÔHxLíAQP#GŠ‚£±(@$ŒKÀWÖ­Zäíšcd#"rçRªgJ‚á¸#–›³$Øà ›’`gúF#áÛ5ŸB„Ñ °”°"h‹ˆ0>/æOK‚V- FÌEÂI„ö¸HIPÑ’ f3¡__*‚z&+‚i!zpIEÐÏmEÐïOLÅ*ú¹-jÖLAP^)J OA0-dÂcç)¦©jز"Ø;7¬F€!nŠ`g’¹”ciõ)Hxl<°º(‚R]­꼊¢j‡^HŸ:¬pÆù"ÜÛÍ%»Á¶‹%>ÌêSAiZV-¥"è[¶"è2VOó_úØð±Þ:n¤"/mÞžA÷g+‚nÄ) Jºµ&híÛš`¿+‘¢ uc‹‚îô5ÜQð›"H¿‘TG @é.‘z ý ¬ºU[”[‹õ@ü®Å@­ú,úN­f©ù3R}ûVóæ¤ª[ ´ŸƒÅ@«¾Tõi­ú³Yôˆe90-’Ýh,ú]Yä¼–r`VC9PSlê~]Ö;#”SL‹ô@ßõ@¿RënVÖý’­z³h7‹ÔõXÖµ°O=2£Ä@;xX ´‡Bª.c5‡°P ô(b5Ðz«Õ@Éô)ÊßÃb ‡ «öI5PMÂj _°å@nËtùç%øó°š ~»} ~çô©ÜÛ«ÿçKߢôÿ<87ý?¯‹{ãv²¦(9ר·™Tp2€pcŸ²„ûb»bß!AO ÊñØë¾Õ4’ƒ‚ˆ}ªXÛTÇ¿¤¨ÉJP1• ÷#ORy€zq,î³×ƒ¹ÏÏÜe¶…ûÊUO:¬^û7‡qŸµýôã’?Â>ÞgìË•»°ÏŠ·±g™ùâîñ•ìþÙí”Ìw¿òÒ$óéôÎD>9m$òé !#ŸLKä;/ ŽrÿÔ"f>s”̇uAe>d(Ìëɪêä$>b÷Ï8#ED|˜ˆ"">¶‘þŸ:Ü,‰/XD|i‘è)¿l_Œ©Ÿ |Ê矠:°!OÙûøÜç,ƆÊHŒ9e|±ÅoÑ4ÖÏø)Ÿw‡|^¥¨»·OGˆ$ð M> ›|Ö|: ‘oë|ëV_æòNä ·‰ÕT"éšõHô eð½Øƒìºr òmL÷fÈS/n;Ú@¾QǾún—=C¹Kù2«yª€ïEžòe5rÝ6Ȫ©¾wp­êø—Tu¿É|Jl’2 X 0_X(\J ¶XdÀ¬Ç2à«Õ±eÀ÷$œIôíH  ‘ Ë8`!u@}¹Ô#åÐLBàûÐÛÇBà»ÉyTB`lgQö£›W”)f=Ç«€8'0¸Ä$!P)Æ‚ l&!PÇd¤éÑ)ûi^}$Jô[—èg°“'n‡B`ù óÅ;ÇÝIt+± ÿë#Ë€~5–ý”d¾ôUó ‹ÖG†>·cCŸºTBß¶ËwTÐ7ÚÖŽûô gÕm§Bkðerþ”ý,ºé@Ô2à{Hô“ ¨ÜRÔ˜”2àxÇØ~± èÏk0Blq•d@µ-«€þ˜Vc_‚šU@_$0ïX" {ŒEÀÎú)"¥Má¾¼c‹€/OD° BÉ"`VLÐÝÃ" Ê"àÈŃ×) RÌ«$úUXìLÆŸ"`çI÷)ú*‹€½}ó°¯"`°ÌÂ~ñèô(=srE´èû‘Ø™&'EÀ~q€‘è;¶ø0~Š€³ ¥Øyè@Š€þJ)>ôçKp&](诠Û`¸D.ž ±ðÀnŸ%À§s·è§²;2´Pô[·øðœ J€v–±8šT£(ÈÉu4.,X|p&B*€1Râ")€ÅÂÉÕo/@UcPJq*€ÆÈ_8(/¶ÓZ¾p¼Éwœ™sžOßÔõ¨ÙIé“/Q*}^[éÓ½©ôyí›J7£Ré‹4ã¨YJŸƒ‰ªÒwBµ#òÉe8‘OǪgÌß-ïQ!_äˆ\ ù´‘˜ÈgÒ1ò™–Œ|·]8…|1Ù}*ñµo~ŸE‰4ñù"Ÿö ð|Ý΢¾ókÑùR“ïY2ïÉß›Àw3H>¦IHàÓÇ |&_3ŸNmNæKóé¬Ñd¾ÑÎút]BŸŽLèæµ@_îØùS ¬„>­#ÓùSk¥ôþŒM+”‘÷§&S{j¤H÷ÏØ8ªQ12P.”ûgÄ1 õ…KF_½?ó"yfyÊÇ ½?µ‹bçÏÆTéü)ÿtþL)PΟYFΟr~Jê³£¢©ïFî½ôý”‹†}?åב¾ŸrN±ï§cÒ÷“^ˆéú)/“týôÝÙõS¾)éúÙÌl×O9†%ôÉë%]?ý&ìú)¯œâú©§2ôÉï$¡/ýIß”k>{Ƥë'}Ÿ~ÕõÓ~;éú)_K1ŸÜ|ö±ãgÖbÇO—óe™âù‰=T3_^%ÏO{0™ùä[\?۷пR³\?m1óÙ¯º~³ìúé«äú)w³ôýtBßÍÄ }Y¯½?廕ޟòáKïOy9¥÷§œHÅ|ùSb>¿.C_zNÚûS¯ËÐg/Øôþä1 }¾Áßðþ´§½?åºhè³/ªœ?]BÐgCSŸ½óL}Ú .Οzéü)O2;Æ~ Ü/åü)W÷âü©G°ó§îؾŸé³ißOû‡Ê÷ÓؾŸY± /oоŸ®Ç¾Ÿ¾ê]~(}?õ܆>ß^ú~êC¥ï§-öýdr¨„>ŽÅÅõÓ?%ès»I×OW,èKGO»~r€IÏO¹¼¦ç§šŸ¡ÏîȆ>w˜øD I|Ž%0ñ)&‘O/É|Á@‹Ú–ƒñ€œZÝÔÍ|ŠÎHæSã7ò)È#‘ïfZ"Ÿ=„éõÉ ”âõ)¯q#ß}(BPÈç2ó9:ÃÌW,œ\ýþÌ|W#1úÆýàsfv'ú–“ˆJz—yºìâÖ‰4cöé¡™ô‚µ ä‰ô´±•¤}ñé 7‹jæ£HÅÌÌ-$½¸)#I/8Üq/²*C`é9/²H/²5ÂoY#üòàD“žOõ3éÅ©yàN‘žR4é]7OÃ5éEþAø\‰ôbÔ¼kˆ_žÐgÔóÙžF=5jÖ+5“õbô]ŽÈjˆz>ŽÔ¬ÃúYƒü|†©YÏÇv‚õâ€Ë¾øtú¸@³ÞÌˈ2d½ÈF‰¬ç3‰Ízç-æë……Þ™d½™ “LH硸J±Þ‰†Ö‹DåmÉï'§Äzqø=-åÔ’k‚——*‘PïèÒ{ìÓÙ¹9-Ô‹“ÒŽE᛫Ènôé|º" ‰zå"²ÞÑ$—Ù§óéß"ý"qé»Dú-¿(|±(k‹Og8éâµ öJùt¶.´#쥧¯`ïh"Xût6î™öfžy°hoŒ(;ÇÐÞ4´éW-“öf.=LA{Ó²äy©e€{%l—¸7-tÙî•zˆ{õ*à^½ ¸7GEênÀ½zp¯^Ü›WÝ5ÑKµ÷êUÀ½ÅÒç!ZÒž öòÞ{‹åÁú]á^µ÷J­ ½Z´W- ½œ.D{µ h/â¢?‰zã¯Ì.Ô›ÓP4ˆzJ-ÔS%ä¼Y€¬ÅT”y 9Ï—LÈ«ÿÈ+7È›E°Î%äÕŸäÕjyõª‡û§iéšUÓB™¬ùUÆ4½RÞ¼Á“é\7ŸW‘òª”Wëå•_'å-–Î^j˸y¿R^µ<ˆ›Ïß~8ïZ:çÓò2pÞ÷GÌ+Wj¶¸çz,îe='çó*`^½êbà|^u3p>-à¼z?óWMðRÞ!¯þô»¹“&ä©^ùW^v?^-À+]‹€çZAwþ+Ø.GH±]Ž-b»Åv9^‹írxv¾ÖbÜ•zw‹åe¥û”ànÖÃd*îfž…»:sÎ‹Ž¢èµHbߪ¢7-(¸«?¸›–»FõÍ_"‚îJ5€»Zp7-Ðewó"€àn®ÓW-€»Åò¢‹ú¡wÃòÐÏpW¯º1‘ú·oΣ64L£yÅÃiTÏH²«?Ü9‹æ¿œEƒGj@ß´€‚HvÓüÚ9‰žMwpý\°«e.N¢ÅÂI4Üœj<ß´5žoXNÅê=œDc1_=9äC`W ó˜§g6 ë¦Ã±®ZvN¢i98‰žÇŠuù3¤ºi€s©®¹9‡ÆûA&2U‘?pÞPa¾é‡¿xtÕû"¯Ëß å‹™(&—ÎçyÉ¥SŽ¿Êw¿Ab_„Ó-9=âËÔwì±€Ô—Ù/E}ÇÉ-Gò9’JÔQzÇB}q¢¤;òmÊ;byO™Ç— 3Çw »Ç瀢Œã;n§@¾‹{¶Èç òEÓ®i]ÆU"â ä“äâ@¾Ëú#ùn‰DäÛœ¦ecLhIq|øŒã;•Fq|»œõÇw(™JÆñ59c’ùb1s-ú^~ÜLéé$ŸŽãëŠõ“¾§ø’d¾mÓSþz ŸÛM&õ<™üÃЗi>ÔSш仡¸$ôùÇ}iô9QifõÔ3ú6õ2»u:¦ÑЗ÷'·Î—Ç(§[§k¶_g ç«_§ß©ý:_åá±_çËLü™ÛÓ>ÏÈ·+“'%¾c,ä*zä»–ô.ñˆÍ¥Ä—-Ò|vȔƗßS_\õ._ÄQ‰£ÆmiY¨ñÅýQeS,_£¾ÄòÛ"ðÅ%‹Sg>’ô½ck‚Bê{qÑ»¤v)WQß ËQõ½cÜö¾ÆñÉB§Nå ¶¾§¤³Ƈy9‰o>àÇç›Ë8¾¼ŠŸÉ_tÖsÉíéÎa¯ü–ù›¹=Õ¬-ðùSZàÓ;Ï@>‘Zßˈ1é{qÈçû“¾WŠ@ßs{È@¾ü%ê{nÓÖ÷òå8’O³‡õ=é{ù”äÓ`g}Ï Öú^Ts1ß &Ö¬Gúž‡ë{¥fEò©“Yß+¿u{fežNê{î‡øâ—–ÜžµJ$ŸoøÕÌÊô\Éç&àH>{/gnÏ ËLíÉÔ[éÔþËk$_V|)Yö)‡Mê{ž¬ïyXµ¾—oTú^±Pß+5¿šZ™èú^¾ré{±Þy§Î¼é{Y‰ô½üié{n[’÷¢Ê„·²es²¾—÷+}¯X¨ï•Ûy4µêãIàËö'Ï­Bú^V#}/_±ô½¼Aê{NðKœ¿tÕÌ.NÌm}¯Q<ŸÂó3žoXè>J…/_—¾üVRøÊíPáËN%…/{Œ$¾,#‰/ïY_ö*ô¹õ; oüSu^šYO+z»ºëÆ?ͬꌔøÊ/=šY]K×̪7(‰¯X^ͬï$ñå–ėÉ$¾|;’øòíHâËY_©çÒìê«(ñ)©»¾òS”øJ5”øJJ|åÇ_¦¡~×>(`‰/ß$¾|7’øò§%ñe—‘ÄW®¢ÄWÊÜš^õ}èŠÚR9~è¹#€­žyÑ#Ýc=(†%ô«—°„þý_qöÐË^«NKžõ#úð_ó¬Ÿ>OU]nÑ–¬G6Öã¿–z" è½<) ¥˜T ÿöo}îÐÓc!ôüÎs‡ê Cq0j{|:ËÝ\àgœe_Fô[EqDHó!?o󀾨,‡´|k[ñºb;”QMyÞjªç ±¦,Äšj×äÓ†\S9mH5¹j*e\“ÏrMå¬!ÕäBª©”qM>iÈ5•“†T“ ©¦RÆ5ùœ!×TÎRM.¤šþgů}»ÿg>‹èw —?­à÷Ññ§_ì*ˈù‹ýd­ãŸC{ ×X,ü<‡hŒå¢ñ·_:‡h˜Ç•@ÿcq‹½ùÃ?-vŸúRæ™a?ÂmüaxiÁÍö§õ†ÝX"ã±b‰=ËPC‹®¡'5¤ay¿ 27žgoŒ®ç6ø ¯¯Eæ²ëy"ºœQÐÁ‡å0æ/]QEw3>yøOdDÉóÄÖÓ¬‡:ê°tcè8¸*öžžåªøŽ"®Xbó)^Wèê¸ÃÇŠÔfóµGªô}ÆþÞ€´g¦J¿Pfú~=‘*}&•Ÿ·ËL5ŸkÂòøñÙ^]rL1¿ƒ žHÌWcÓ‡a& ˜xIÆMõÄ]ˆµ .öô¾!Ö"„ØÕšvµ€Ý¼Ct)‚]-°«5O°«Evóõ¼¨f’]-²›ÌD»iyAW@»¼c±]ë‘쨲]µ€íòþÄvù–Åvõ·Àv³ž Wíj=`»<êLl7¯j•íªlWjÆœ;Û1!„»ò€»z è®ÔKº+÷Gº«WïZøìÀº«Õ€îò“‹îÊE€»bÛÕZÀvå§Évå“íf5€²Ý¼ ˲]öñÉvó’“íè®YÉd»r/d»¼]¢]-´«õíj½@»Òúˆvõª—»Î¾Šh—?N²+†ƒ³ªk!Ø•×@°«õ^œU5î ìj=»aaâ Ý,|0«úf:'Uè˜Sý÷—Sª ĺÒìˆuåFÈuåöÉuÕrrJÍ«¤&f€]µÜœSõäº9ÀÉu¥á‘ëJ÷"×åx$®+#¸®´hr]ùLàºj84¥r„ו¶G®«–‹sjÖsïî¦üñ›ÓªœXW«y8«¦X—3¼°®–y9«ªbb]ù0ĺr±®´Fb]½ê<ÝSi¹8±j¤!Ö•'ÖÕ‹Úé®J†ã¼š=œW]¤ßî¨0L¦+µ‚éæ²æm½¶30]¶z ]ùû$ºü]ù÷ÉsåÁs¥k‚çJ+ÏÕ{DcóýøZ¾ºZ|]Þ€®T +èr]F +ULž«ULž›ßĹrÁýÔ¿M˜›¥±Í ˜+—O–ËU+Y®^ñbª´,Wn ,—_(—7’«5L’[ ˸ ’«¿0In°Ó’+# H®¼Y\­ƒ’|Ö1In1@Tÿ' æF£—À*îï<V,—(žB6õ,Ô…pÀ¢N—z†t:ïK§‹zJnÔé"}ìF„N—:„t:ŸU".¼{Nðuºðp~HnÜOŒ5 •;î'ò<ËtûÁ ”éð$U¦êM e:¥yN™.(U–›çì¸AÉt::u:e%KNÉ”S§sëtJ’fŽ©ÂR¦ÓØ–ét`wÊtãcôŠrµ e:'~K™NÇ5§L§£R¦Sžô”锇,e::2]Þ²d:¥MK™Îwh™NOn•Nǽ¤J§ƒ¨ÒéÀ†T锄Þ*ÎN•N º­Ò9¹YÊt Hp’锩.e:KËt¡ô)ÓùëZ¦ÓÒ©ÓùãY§SîºÔéܬÓé|ðÔéb›åSe:eîN™Î_Ü2»ƒdºHL¤Lg‘Ë:NðJî¾DOê"gL¥¹ìã©Ô逢Têîk¥¹ié«R§q •ºÈ\…z¤Ôe=Rêî‡3¾•:=…•º=Ò§@—“R§sNR©»xž´”ºTe,Õ TÁä/©N oju:÷>µºHË2 ’ê¦ké?©.‚Qa‘T-|>“¥:%PO©îê‚MIuJ°˜R$ߔꂶÂ`¥î<ÄeRêb)uÒïS© `žŒÎÌE™BÝÁ A uêS¨‹€ÛJsSºçÏH¨Sjùê”g2…ºÑž®U¨ o^Ÿ„:¿a uãc@¶P+!Haê‹“B]ľ¢Œ„:ÅÅ¥P×_¶, uV…-ÔiâL¡.Ær\E¡âŸS«+E¨Õåý½9·¾ÐˤÕqæO©N~©ÕEDö4Hªó—±Vç7*­®”‘V¨¨GZ8R«³bn­N©ÕwCÍOZ¢S«Ëû¡V§uGjuz*Iuî˜’êœ 3¥::ZX©Ë_¶RÁˆÔå8³ú‡$Ô]'],Ôå/I¨óË’PWä= uöˆ°PR'47)u¾A+uþ¾VêÜ’¬Ôé9%Ôùè uòêI¡Î×H§ãY)ÓùX¦s©t®D"»¡D:¨éR ‡H§ Ý"ß Eºìé<ÔK¤sÛ•Hîá@2Šti€Hçõ²E:¿fˆt`$Ò¥aªt~7Ré©åoœÿcmî MmŹk2áÜA´ç.&ÜJ¿KúOÊé2VKŸÂrNýgŸK%äKŸKeª³Ï¥’¥¦Ï¥ªÚç²}“媅,ç¬Øf¹HÏvAs“Ïåq°sÎg˜s®8Ã\¤í¯æìÛ`˜‹2”ØsÕ˜ µî“‚¹HoG7LÂ\„ZÂeP0çDÀ‚9'ù5Í…hNš‹kÈS¤9'F7Í•‹äty>rÕ$Íù‘.¾/çc¯Íq®×çoŽ‹Ÿ¢¾FŽóý™ã”*ÚçCÞq>…ÛçÓqv 7Æ9g:\*E¨1.~“Ž›Ä8§FµÃåÁkqN°*ŒsÆ_cœ¿¯1.ïFçÔ²9ç°5È ANƒµ9®!Ç9Í­9ΩGÍqù’rÎåjS^sœ–&Ç<£ çdȹ|5¹¼9œs§äò‘rÅBË·'sì€A®<AÎùT rYF —÷#Ë_Èit4Ç•‹Äq1ˆW]®4-qœ3N›ã²m‘ã²ÍÚçRIÜÅqùJÅqY¯8Îs”A.I ç¬Ù&¹üž"¹lÆöºT2\“œ—&¹hm7L$wÜÉåc‰äÊ’ä²5‰äÊU ¹lê"¹|íD¹|N{]ja”Ë'·×¥-›å² ŠåòÉsù ‚¹ìy‚¹RF^—A‰¨™0—ßX0— C0—*˜ËßÌå³ æÊUr»ôs‘æœ!×4—ã›p®Üy.{xνF y.¿©¼.ÝáuyÜ_ÕéÒ©˜…så7uª…„8”ôTœ+¿É˜W?yNIÉís©ÔÒ¿p¢O*rXq†sxFJrÚ¤4Ã¥ZeIޱ)Ééh۔䴇`I.2g|ª"×:׆Rä¬fY‘³0 EÎ"‰¹Xš€‘¤ÈéÌÒTä¤àX‘ÏÙÇŠ\ªdRäž[^‘R䬚X‘³jbE.ÜŠ.ŠÜñ…;¶ 'Í)¹¦3 r:459Öº(rpƒµ"×pÜU*r~(+r~+rÚ™MEŽÇ§ 0Ä´ g±M‚œ›D rªÆzœAz\ h€+ëq’¡¬ÇE:ä⊘&ANzˆ9=d rúi r:U¹r¾ rä>©q‘=·f5Î7"5.’}Sãøõ-ÆYÔ³gQÏbœt¢"Æ]bA‰qi±Ç# ŠwÑ‹4Õ8†›§gE;ƒæšü/¥Æµ¯êZ™’‰Å8÷°ãx´ñ"Æ=ßÄ8¾­"ÆYü’§šSŒ³¬’bœÄ‹qÞµgÂbœ÷£3lNûšãxfoÑâ´ck-Îz‚¸HÕ’ê0`Oñ<$‡IŠÓ©¾)Åñ4Þ”âÆ`ö®asÞèµçˆBkqŠ®M-N¾©Å)H2µ8…í¦çMK‹q3k1ŽÁ€©Åíߣætð–ĸÃUÔœƒä(Æé|îã¼­n1N§$§—‰q hN-Ng§§ƒ”S‹ó‡²§°ÞÔâN¦ N-ÎïÊZœ•kqÒŒ)î!åI‰sü •¸¬EJœ‚²­ÄÉ÷$•8¿-)q3«¦çhÑTâË&)ÎWYŠÓ µç†e)ηg)Nm%Îñ¢Vâò·ÅoŽ ³g¹ÛJœcW­Ä¹3[‰³ô+%NÑÖ©Ä)ÄÙRœß¥8ߟ¥8·bkqî«©Åq°ç¾a-ÎoËZ\dxƒEZœÜø¦óRKМƒø4÷pì³çÎk-N_ÆRœîØJœ‡KqJ1sï7xËïRcæÞUŒ;n]%1ÎoÔj\þ”ä8û:fÎák¤7…/Cs´¨Ô8=±Ä8‰q~ýãÜ€$Æ¥bœý$ÆùcHŒsƒÖˆj‰q~PˆqnãüØã\ƒÄ¸ÐiðwÀ[—ã±´¸øäð¨¤çß”W <™^ßZœSZœ_•´¸¼+jqTG-.2Ä¢jqrÙ³çV -NÒ[Œsä»Ä8+~ãô21Ça3bÎñpÔâüy¤ÅùQ¥Å¹3I‹ó˜+1N9.,ÆÅ²Ž!t]|ÓPŽæ1µ1âû[n#h¢¶™»>‘¤¶º÷Ey»æ6¶Eše2æ˜ë²j‹‰…ž•Ķó ‘°í<”2CØ ÂEl;O÷il;Câ\°ÍG·ÛÎ]Nœâ¶8æ¬AqÏñ2@ÔÜv¼ìõ涘àá$Il;âXÖÛf‚Ë7,¥„mÇí¨=r[~q[¤`~Gʨg/AqO¬Z ŠÛJpÛqöÍm‘’"ޏíh<ØÜ‹Ÿ¶p[üÔ"½7¿·°-ŸRØvÜVÚˆmy±Íy¦myö¼a[T¼-ÙNÂ2¶ÅC¡…Nl‹,£P;…mQ-Ó¡ÛŽK)p„m>ÆØeÅ)rË7.r+W‘ÜüònQäXÜ(£EPº"¹×¥¤$$·¨†ÙCHn‘‚¨,r;ΛڟÈÍ?.p‹,­m‘ßb9¼‚ÛqrãÉà¹Æ/ZædéÈQ ÁÍùÉnÇ!Wàë{ø+ Ü"ÍùÂm±X?n‹à‹e¤\ÇÞª°íˆü‹øvìR»„mÊÿnjsšPS[Á MÔVÊÚœV5±í½% Û"0ît¡ÔAb[©Ü'—¯ÄmáǼ·)Ýv‚[Ä!®N”ùÛ·@i·éëä¶~(ÒNÜ1¢¨Fܦ-¡ä6y<'·ig)¹M»D nVNnÞ"¸EºßܸÛcnÓFNr›öŒ’Û´%˜ÜZ+;q[þ°ÀÍn¾·è>k¶yÓ'¸Éa<ÁÍN½7\]œ(µ³`p³+ŽÈ- ñ\Ä·t€5ºÅq&(c'JלN”ô˜$¹Ù Uä6:üª½%±šÜì¿irË2"7ï$º™ŒŒn"˜ŠnX¯eÆ“Kõ˜Ý˜ÙGè–ÙkÝú÷„'^þÿºiAjtãâ=ÉM á|'º;“›ö'Ü w·q¿ø*¿áDyÜʬ"r‹Ñ¯ÆÅ•$M™îäQPž¼(ãÈäæ- “[¦1¹„ ¹50®’š„7%.ìÆJÌn ‰…ÝÎoùN´Þ6»9‹ÐÍk]£›ßN¢ÛÁ£›rvÈ“2aMì†&º™!Ån‰Yb75< ovçu¶¥&!º9?ŽÑm³cåóÿ“÷6¹Ú䯶ÞTªyNã~ÈdòwvÇ€ h ¶;2pž?Ì`¬µ"¸«J*É×À¬†ê{¹™L’ÉLòá FÐoXl´ŒQrvB7LÕÛ =ÌÈÛÉ‹yè¶fênæhúü†ì »Y8Št:.yMrr“5"e·(²›­áaV g'¼'T·ùÑ.ªÛ¾Â÷†¨º-DF”ê¦K¨ºÑ¢T7ú‘ê¶ E³Cnë£ïbÈn‹Ó!e7a.e7î¨Qu³é2Ë4Õ-ü«@u‹KnÃÇÄ¿',*û9Ô’M*mQçDF“ÊŽp¤òvbË=èfðv²:Õz;±=#“]·˜®ÀÛ‰eqŸ…ôvb1%ü|¼œ ¿Øí„þÓ¥ù)rn¢U¥'¨o°þxªì,aýñL iðvbËQœ«£Uå³ ɪòýhCI«Ê~ïêòÅÒ/¬*ßF‹IZU¾póV•o¥KZU>“*´\å0%—ãi*?S9{IuÕ¿S'…%øÿÞtìE2Öý£:ÿ4(N¯=€NŸÿV߇eUm¿åÈ"?‡Õ4Å]%E.”±qPRŽÃ’"KʹX’bã°¤G%)“JJ¹X’bã°¤G%)“JJ¹X’bã°¤G%)“JJ¹X’bã°¤G%)“Jú7"è¬æ>×þ0€NÿGt~7fþ$€ÎŸåû@矕÷s´ÿY¾öÇôïèü…/åß®Oßヒû£7%*ÿä5¹Ëø—è¬q|€ÿaüœÝøÿ3þù¿+œÍ?‹Ÿsž‰ý¥ø9ýÊø¯3~Îê­þ ¦ñíY\ÏFÌN°)xÀduS Óžßž_} 6·Ôã$œø×1'ïLÁ 5MÁg;rw1Bx¹½Fñø{]“ZöòžótpŒ¿ëÓÏÒÉ×0¿³ ÝÚù;vN÷Ïé‡C¾_^‡î€j&áž0>?Ô~ Ûý-N ì„égCpºl Ûýí= ¼æóñPË‘ZÖv¿pTõl×î„y]PÚ¯|Îz¯EÎî.Nô®ižC~‹#è;aøébœßpÕ~}WB/¿pnü,gÖ<‡™Ï!q€ý5®›ž7ó.óøÖó%ë±E-.÷ŠÉWµ{p›ëýÙ)¿pn¿]©Ð=×7Xo¯æª¾¨åIëµZùUrg­¶x¬ÿ¬­—ípŸ‡Üy†Q=Îæîu[Ép·‹ŸPË=Šó™Çý‘xªw¸¯AvÂûþÂqÁY^ê;|°S ÎáXÑNùAyRl§T_Ú6˜‚XÊú…S¸gU¾SZçQçŠr:4UÔføò–Çz,eò<óL»l¤|žbªÈoá€`/ùGëão ¥Lw«0ü5¶ea÷6<Þ;eÏç-D†ïý…sœ«!ezü%Û ‡—M@ fæd)Åõ‘Ò@yÖÉR¦× ÎÚwÊg' àÐÌyúì”õø'$ò¬û1w<Þã'"èogcëEÊ›fÿ.O ”âûççÊíøRÁ ØúÜ) ŠýKq }=<õNè Ð¸h8†rOm§Lp(ÊZŠƒ¨íóàªu¶Ô^ß–{w[±Ÿ›R–ž[ô½N¤ÜˆÛ)¥zõ°=²S>_r“ÍRNlìçAPøR}IIf§4ÿžÉ†ýøâ´]åŽrúú™Ç…Æq÷M‡ÓQšwÊz9ŬŠÇÓ¨M}œOwžÇ߃ú: >ì»SŠêüžà„úvEý|ý ßo6$qH}×~§4_TS ²”uW¦w¯4®20K~üÒÔù²zòLŸ'S…—¿ÊѨö|| Þíõ©2 n¯Ï•ñ\ZñÉ’"ÜNù>ö1*Ø(ÊáÖ­N6)­± /îÔ?Vo zÃç̨Þð9Ó& ²m¶©¹ã[ûûúóð!¼H˜WeûÛ¨3¢Ñ;A)Ï÷üh@ÿÆÏ<Õ'Ïè˜Þ|öŒúöþü#hb8Úºþ½†l‡ uD?ÛB1ˆ:¥RuÃÀÎP2^ŸDãÖ‚”3ŠÏ£ÏôÂ;»CñTFõ™4•Œý¡”Ò|.}ŠÏ;¥ãmŽrFÉMcýx cú|šµ*Ÿn4M)M¥,#ôçÄNQJTª!1±U¯Æü|>}Ë}§`»èi¾Û) _ŽßØ.ŠweöÉ&06Œâ“`~¼ç}'l™g¯‚”ùc˜¯ÇçS³Þ@Êûqœãi®òòcó"a² hæúêÇÆwdA(Í)“ƒdxõVolšy–øwÊô)5Þ—5}Jµóþ4í1öüù¶µO.å=sH66{õ8¼gºÍýiS’çaŸÛþׂ븾5ö…úU®„îsªú×^2ö¯¿Þ6Šïg`ƒÄ÷}=bÏÀ€gbæñû˜ÑV½jkF[×gD{,)OY÷{ªæù«rDqïèi© ì¸SÜ,PôHqFÇWüNqûÿ}›·O€CÜI=î>º:,½î;ÚN 8~÷]‹Zp;¡bõîw–—xîD6÷ZŸ‰àºÐãîTÁ "„p'G±=§ÒæŒÍ!oú.¦Î{Žƒp)‡#\N8w¢ }H@‘@´âÁ÷ßϦÐA¸œý \7ë…â´uî$8h:„Çñë ÜIp>v„Ë9†Ç&ŠBÂå˃(¨ C¸ôwG¸T‚#ÜI¡•Š㒲X­Ìpùµ²ZÈq.ߥ­Õ: —sˆË9f¹Š<—ÄE!îJ9w§¬«î¤¸òþÊwe©/ëÆbÄ‹"qWžP$ŠïÏÚ†»Rfgí˜r.ßÈ.çq†K·r„; YÂå,â®rÄ]Õ~ÿ>— é4!e9w{ îÊs î¤ø¼ê we9 —Sœá®”÷»—çGýˉÓÄœqWŽê¡RžæÁrÊ`€cÝã'¤,Ã(씀6=‚BÊ3€bV»28Ã¥ ŽpW–×Ã(Ä}á®<_a˜ç \.¸6€YZ½+€³,)xƒã¢1îÓC*¤”õþlÁZlÁU=-`Ê[Ù”ãw§,6af‚»òÔÊ6ÌLp;åãŽÜ•£÷Ÿõ>C¦kæû³~s² LYx‘u•\Îã—ïåw]Uú68Â]yNÈ›ü{² ¼Sk?Úàw¥ Ÿ3sÊüY¿é³¦/DÉ^yâržþÜå:Å])ˆ`’R>ÌžQÊ7~ÝÏÊ)•mpŠ»SÛÀ”94î…ø~é^'žIºáý"e ¤I\3 Á¦<jwrŒ»R×$¥Ôò£ ¡MRž6~<Ǹ+Ï(?~/¶¡ù÷Ü9îʳê6€ãÒUñýR ✤ø‹’'B¤<ßúñ&¤< µÁ¦áD¸“”£O¶)£ÿèc¹+Bžä”ù£ rWÊûýhƒƒ\®¡“Ü•çëwŽúýº[µå/]Óæ68É]WïG;É]åÌù³~«Ým8$wý~Ÿ»@¹T PîÊó•ŸyêóëGÉuÜmË])½° LÛÀrä/å™íþ9eý¨ŸãÜ•òÖõ£øžSëw©Ð"™ò/DË!Ñ­çGIº\Áq%èrßt}…²\…'Ý2,ù-€n}ðóA [ÜIè,Áµ*0]Jp¦³e¿_áHgeNÏàH·¾DæH·G:àè ]º§3ÝúpzŠLg%x~G:»âñ[8ÒÙ Ó+…ãaD:»Ä)Hg•hKŽtQÆA:ûûë@æH7=H—þîHg_`¼áµf€tÑP ]ÊáH—Êp¤³»@„s¤Kµp¤³¾._ÒEgé¢H ]ÊáHOH· ŽAéÌL¢›#Ýúà߀Hg¦Z5#%àéKðfÓŸiÞ¢ À] Þlaï—ÞØýd7["…AeþésŽžñMO˜ø–äéÁ ùM£„üfóx­Üõ&ÀEÎ^ /§îr€3oA~Sœ)ŽÀ±¢Ap9eqü¶›àØÞ 8>ù ¸t.• ‚c qq‚€GŸ*qéÞ€8º³ ˆ££€8vw@ܬJÄñÄqøÄq0ÄE;âÒ½qð® ·¾Ÿê[dÂE›ˆp‘—*‚£° ¸õRq‚‹kHp|%IpöUƒh‚[¯N´àR©@8~náìø1ê„›“ËF"œQÀÇïX ÜNùç œùa$°ù“S|Š™p}·öÌ'ã®<@8~Ráæ‡Ý ß° ¸E$¸} žg>Ú’]¥2ÁÍB„'ÁÍG‡û@p‘B‚›L: pæÿþ–Þ¸-7 m‹ pQ øm¾<"H~‹ú9¿¥BÀoÑä·”üÆM±à·èò›ºœøOŽøßæËM'âÛ~Paˆot”I|‹ ßâÁßÒ½oé*àÛl<L|‹&€ÞFûIoÑ7¤7s’Å”ëÙÞ¢Õ„·t à-§ ¾ °„·háμÞ¸& x‹ê€Ýèe4Ø-sØ-^'²[Üšì#ì¶K¡}"Ø-¥€ÝR9`·”ì“ìoÙM"ºÑ9)Ñm_RnÑ-z˜è…€Üôø nQ9‚[ô/Á-ÆÁ-¥Ü¢Ù·F·t¯v¿–·G·øÜbLÜÔJr[J˜?ÞSb[ܛأ‘؉صqlSw’Ú¢óHmñPHm1Imñí!µEW‘Úâ+Gj‹*©Õ´©‚6UOЖòÚT=A»Șn³©ƒÅl©`0[*Ì–SÆÌkÄÙ4‹ÙâFD¶”d‹êÙ¢'ˆl)È6z1…êùÖ@rydŸJ'­Ž8á_BµãÄ9+lÇ÷LgßÂÓ9˜0Ôý—˜#ïšP-âZщ–Ó‰99wõËý—ÈS:ý—X—‘Íà\Üþð_rœ’¦Óoᓟ¨ö~Ø–  *0 ¹V;Ýé9œÕ,A6•Œ`t`¨î¿ä­} ÿ%5äu‚04,ý—Xy#~;¡`öèþK,ÇçEºÿóŠŠ£mî¿Äb5Btÿ%æ[Gô܉"!ЉÂ%ºÿ’·BA¡ÿKpªr÷%v‹d'y¢ÕfR;1%W"µ I÷%ŠI÷%Š9J÷% «@÷% Eÿ%Q »è ½—Øœÿá½Ä²ÏÌiFBîK©QîKz@îK,"&4¸/Q„O¹/Éå¸û`¹/yÃyÆq_bîi~éîKøÈ{‰¢=È{‰ |/‚÷{ ¡Ì_Ð'ìÝ{ÉKÙÊ]—¼¬·àº$§À{ ]̇÷{)‚Ñ"(B¸/1ò̶SÉ~p_b+”÷%½êÞp_b"+ºùYk›L³‰äñvCå îKœîK,@ ¡ÌÏZ‡{w_ÎU迤þ8ú&':ᾤfDÎö‘á¾)œ—Ô®Jü uÕ)7ø.ùºøpÝžVè»ä{Ø<ú.±% ° ¾KâÖô]b/h>ø6l Ó[|—ØÏ"Û¹.‚ëzž$¡åvÓu ÝäÑuIª\—|ÏNÝÞÛo ý“†ß³Z†€¿%Z…†ð¬©VÓq ~†ãzÇ%ôŽKÊG®wÇ%tœŽKèl7—Ыg8.IåNùØ|³idø™ Ç%h6ݖȱ½–Ø‚6›EæûÐk }yÒk =…׺ ¯%ái‡^K¢§èµ$êO·%)nKè·x–ûŠ~Kâ*w\×ÐqI<:.QGÐo ]"‡ß’xUè·$šI¿%éÖð[’SÆå 5ü–„Ó!ú-¡p:.I¥,9¢¦ý ]ÚêAÑq »†ã’”ŽKâÁÐqI<^:.‰KÇ%á[‰ŽKâÍ¥ã’TÑý¹†ç’T.<—¤x.‰‡çˆ&¶á¸$F—Dõè¸$C'·êRz.¡“ûð\Ø=—Ä­á¸DÆ~K¢ô[c~KÒ—^CÖ~K"ý–D è·$êK¿%)— @ý–Dõè·Ž‘ÃmI\¯%ñéµ$:œ^K,ÞrVÕò(§×úd¯%ôÓO¯%ú\Ék‰:FnKÔr[¢FËm ŸŠ¼–hpÊk‰^f¹-‰‹à¶$àµDßFy-Q#Ÿ¥WG^KÔyr[¦ß=ù-Ñ«"¿%Q2ý–h„Èo ]éÿ QoÄoæšäÏ¥¶ˆ !~³ø¢tp@)Wt@Y~P(1•à€Òîíd”ýÍಠº;J35KbÛqíw$ð@)/ŠîÒbíe‚K Û·Zb›Úóà‚rÏFO&8 I®„Úf{cÉHòÄ{~Al>)¥„å¨Ñ·\PÚæŠKcÇ¥í€&SÉaëòžÎbÝ.(ôH.(…ØtAɵ¶\PÚ.2•Þ„Èã[O¥#fÐNY‡xKCŒ ½¼óͧR±µ¿Sö·í¼¾S²Ÿ÷ØÞ@W½‹½žÖ†Ê:¥ßeÃþÓPÊ·ü-ÅÛµ¯9ÀkYðø­Ö„Kør:Å^êö¥øÎÓÙãÃEãðn)Üî+Å÷žJij“Ř-£ÖìßgëÉn„aô=n 4—R|ëÉ:Èc슺)Ь#Ÿo=Y?ãÖßç–@“çÊWÝÈŒGQLsK {ŧ¹%ÐDüŽòu7šˆ¶SFõÚU2Ý(2ÝÈž6òøÎÓ;`í¸¡ !îæfvƒ†¡;Å  ¸÷—Ì-í¢àú¹-‡?)9J©‡vßA+úR}ãÉ*ì[Qû8À›ïäOï€ÍäN˜Þ.ï7©yl–º>o‚ŠiÏÞÔ7í™ÞZDn†9Àk%»·?áßÕÈvêé,ßWÜ)nz÷nǵþUŠï;ÙUø6¶þüúQ²ï;YçøžM1(¹áÍ·ÒsiëáSh¸•o<¥>îOóFú¶Ä~Í‹çà‘²¼ êÐ^†7ƒ¤•c­× ¦,oëÛÛ`PŠï9åÊŒâ Ð5¾é”‹V¨iЍ›ï9E©›º9Æ1Іo9¥Žr°Ìw¾å”žäø^¯¿^„ñù«9<Ä¥u¾rã(­W9n*k÷Â÷}ôuçp±5=‚kÙA›Þ=[¸5^‡›K™÷‹0}ËÉ nHÅìœN§ï9EoM˜ÌÚï °_­ž°™ºLßsJ-˜°›Ñ:»ÞÁŽXΦêÁtvðXÂNqÛÙTÏFÊ‚õl”³`>÷Zï=:,h£‡—ï:¥6,XѦ<¾ë”žî‚môÅò]§\,iãí^¾ëôîii Æ°¥¯ÄZåþ’|ϱ¦Õ×è{°2Vo} j-ÒÞð˜ÔªÜïM­úï{`T«Ä÷ÀªVoÃ÷À¬vÏ9¾jùØÕ¦<0¬U_|&¶<ܾg–»Ms±;î óÚÁóBßûøœªçð½0¯ÕÿÌö'ß óZ½ãß óZ‹èmxa^›Êy­žÕ÷¼V_ëï=æµÑîæµÑîöµ|©¾æµfÆà °®§iør’2ï‘þÈÓáW``›®úÞü¶~å›÷Hÿö¬Ê‘ŽV—†I5®ò=‡ÔW¥cVÚøN…-d|ë寅Íö™ Ä~=ó&Ô®kh!P £Ò8öu…o!öí”JHqìÛ)‹/`_7Ž{€kÕ}J›®CȃO鸪Á§ôd,qǾë*ÆK±Yùï¾s+Ì)¸öíB>(*À¾nqá}Õ ìëóˆ§õ‹`åÔwR¼* Sz½¡ï¤L”[=`CgÞ qSR9½± ¼7§¤<óásà½8%ZîôwRÀí±S"Ñ_¾“Ó_¾“Ó_¾“ÓßUʷ؆‘ñïºw«lóôÂ6(eýècç¿+§tñþ»î„à)ö-ðRœÿN ÁSRžâRO‰{;æ{9æçéx•Ü<`C*¹{À†”2êý{¾?Û0'Ÿïà)‘â˜Ë©ž’S<`CJAðÛ©C9ßÇ60åOá§ ˜«W;%¥ôï×Ý¨ŠØ)9eò1ôŒ€ùVëc Å 0ã˜oîx]U¾ûšïùñ B§¤kjcV&À+¥?l‚R?ó „`JA Á¸×BÁ”‚(‚QÃõâ+à{Á\îBä””‚X‚©\DNIå"š`ʃÈ))â ¦<ˆœ’î…ˆ‚)±StÕÁû÷ø™QS  êu¦ú¯«Y0¥ ´`NY÷8^)£þ¬á,÷½çºû ˜z x¥ À`\å x¥ À`Já‚9Ra0êó"Â`JA„ÁtU¿kü"Ä`º!S B ¦”¥ÉÕ' `ÎSb0¥¼ý'@Á+å»[Pb0¥Ôö£~AS ¤~ÄA‚'K¶;‰kþ…ˆ;¡º¡ËŠ J@ƒÙ¹Ž\ºø˜†úr ÐŒ€À!Ðã„5@;}øà*×͹#Å5À¬?ºøØò µé8ÅHóbj€vÊò#ûZBÀ† "`˜»h¿a¯PvàÔu^B ÙCAê„ÖÏÔ­û`œ˜¤xìÕ/0_å" Î’R clŸs"ãï!¦Ž hv×U Z³©¼¹ hw€-Ø ËZ›2àÓÈß”Íâ\ ¿ªo\Œž¡¨ SÌÕsÐ*ódÜ)‹»õÐãiS|¾F©ÐuÀè_ê€vä1Ì)^)óª „@kÓŒñ±Z !0Uï³ÄèsÏY³Ÿ˜ §[»˜/âYâ‡R¦Ë€Ölh¦…‡‰uÑ‘cS´ãƒ\ç2 =ЊR¾Â³FØŒ‡ ¤¨Æ/ê€aŸO!ð)ÜU¢ÇÀ(ÆA+ aÃïB` ¤¨“bÔã¤uÀ8ÈF0²QL·†˜óÔú3O{yTtdLç©ærF½Ï÷>ƒF%05ó£ ú⣂)ê š¤ÀœBôÅ· R`fp)0_Saø:a¢J)0çé°}ry¢8òŒÉ6`ˆB Ìy\ ŒãÔ­St˜ h©œ£¦;A Lý-0ÕZ`ÎCô(§?|Y+¸6è‘ǵÀ\2mÐ#e=|P´ë910倘J˜FÄÀÔ7Pã€3ÕÀ\N]lSÚ`ЪÎ#ÅêcèWÊúõ£ÎsÜ÷¦ºúŠ`º÷ ºJ"˜S`„õƒ"x¥,æá½jÿÑ(‚9œçÄ<Š`þã—éN8ÏŠà•2ÙÜiÒ =Rp3úbòT±j M0õÅt3tNs±0CO…à fºìÐS Žb¦œÅL%ã0fJÁiÌèH‚©H‚éª# ¦aI0—Ct5Š`ÎB;ô¸QÓÔÊ‚{ùñE„"˜¯¢zTG3ÓU4EGu\Œ‡BA0§à|¦ÁThªMÔ£Ô£vÔS18¤©O&åÀh$åÀ|«‰S©pÝL90•90åx¥è5DO@Œî¤¯ åÀ\k¦ÖLõéõþÓš9eþx ÐsýpZ3R ¦úALµ z`jæÑÓ³„˜sÔö£‹¡Æ7^6Û©z8¬™Ê¥7穤'Ðo3ÝÅ}\"÷ñx*¸¯… î“sqŸZ,îSûÄ}:õAìKHìKìÛßBœ!öÉаOOZاóŸÀ>=CaŸNrŠû䉀Øþˆ}á€Ønˆ}Z) û±î D}Ñb_8Spì‹~ ÷EÉ}±¼$÷É1‚¸OîuÄ}±%÷Å2ÜÇ ûT`_,߉}Z®û‚&ˆ}A Ä>ùRöÅ$Hì‹‚}AÀì‹Õ:±O%ì‹Îrì“—!a_P±O„…}ÑyľT°/¨„Ü—Ræ6â¾@-‚_Ô˜à+?zN÷E±ä¾X®ˆû¢rŸ––â> ì£ÿQŸŽc‰úÀ>B>="_ÌÙŽ|1?ù"‡˜OUóiÆ&óéÄs0_ä!óE9`>äóÅk@æ‹ç/æSw:óÙ €¶ž/Ï©ÁŽÌg³ÈÍ|±º'ó©‰|ö@³ô—+CäK€ä‹täÓì@¾ÀÍ?G>u ‘/§ù"åO‘/ ‘/:‡È'7ùh"Zî; ùšÄ6"_äò%p ä#ùÔ; ùo@¾T‘OOFÈíòE}ùPù4pˆ|:…*äÛåÂÈ—ÊòÙøÉê_'B>®D|$RŸá¾Js?ŸzÀ·ßP|b|jµ€wï)¡ÔÛ½úÃ4Žu ÷¢÷î6{r Ü‹[“ö”°Gˆìá›&ÒSÕDzúfô¢A$½è‘^¤|pÙ‹G¢^*…'Ž+í…z`Ï.ÃñаÇ1*Ø‹¾!ìEÿ%Øc9{ \Á^ÜÝa…鑇&Tô‚H/n¼¾{‰ô€‘ôªL4AzrÙ Ô‹'Ô‹R€zñ”„zqïö]Ÿ‘^âº>ÀªHÿA0ÒŒ`ó‰^{Í/]ï³3A‰ï>óvñÝ7¾8íw&#ó sÉzÕ>ñ×Ѿúȯø®šûß™‹,¥dÏ«ç»oO'ã:Û÷­)«Ï3å,†wvk€šÓÝ·‡Ê¸è®>ì`âÝw¼£ü=èÎÚï »o Yk:Ý}û3U®“}¶4¤ètg J8ÏÞ}µüÀ;ësžÝ3¼û:czï>ó¾pÉzß3uÄÎñîûªŽØ9Þ}6ð/YÏR…r›ò „‹b•ÐÆ3‚׸§þÈÆ3ÂÐÐÆÓEñ0_Güˆ"ûR·ñ”wsÙxF<Úxš‹ùzÙx†ÓyÚxZ9$ö"`îÃ…#l<ͧNÇϵ§ù‘…½ˆä+O›b&e< Ñã ⸠άL<PX&ž•&žÖé„I„q1áÕqψçJÏê&žVn!ðy U¥‰g„C¥‰§T°Ø§àP”`á©ØÌ²ð4Ç&% {)¼-<-()ž,<#L)-šwF ?šwÚl ƒODáTžcÞ™êóN‹0ˆ!˜wZJË¢^Š#JóÎt'˜wZ ­0+âþ=ÄØwZ9™ðRUšwæbÉeWç Mï*–!8 WÞŽx'¾ 0ï´=kzç*ž¼cN5æVæ˜wærܼÓ\YâK óÎÔ9ƒç㪼èeÝ™š ëN«¹ñ  ’ÖéÖ“8Ÿû”ß)™°…P.Ñ¡°îŒêLÀùܧüòg ÆÖ¢¬èí„ί#l;SÄŸ¡ÓN»ñ Äçsª™å\¦x”¦©7aÚ 8–¶NÂÌËNË€XvZ»CLÔ‡Ñ7e!ËÎt#r‰‡ÃÎÔ0ì´b@è0ìL­„ag”ã†kÀrvF£hØŸ†¹Ä7ÔhØ™ËA„C6ŠvÑÁ´ë´b¾Ë®s™Cÿ|Àï4Trì:sõÜ®3WqmE‹ã|n×iyxäqsÊb3qÍb-+zçî…Vœ>©j Ñ®3µ v©sŽ]g¾â¦rçм\v1¶h×™úv©6°ëLý»Î8´ëŒÁåv1fi×™úv©M°ëLm€]gzš0ìL}Ëε'½)PÈw¾Î ^ø`£‚¾Ñ\Á“-‹Æ7ÂÈ- 7“™¦ 7éò…†›»Ra¸)»RJx)^ª[n~b>šnr ÓͰ„¤é¦Œ“é&ShºWAÂKy á…Q 5¼dZ¯6…éf”òç¶›a6JÛÍ0-¥í&Í\Ãv3J¦ñ¦Ê‘ñ¦®JÆ›4ð¤ñf\Uîre¼9 â%Oo†&7#*^´êXoƽh½õ óÍ[Ä‹b`½©ÉzS!ëM݈*^Ê/• /e¼Tt¼T#Á¨ ”òR  &RÖm‰K)/jC)/®¡”÷¦”—®*?l¨%åÅ㤔§MRžì Â|ß)yzÇ¡äéÛ!%ïËw¾ttCCß¾0ݤ9|˜nJÖ•é¦,h¥ãI—é&Í hº)ÓÒ0ÝôŸôL÷<Òð´ý- ï Ÿ.óv/, ïÀcJx<íP³—¸ A±CÂ3mÀ·‚ðÉ%Kx' /½³ðÖ:OqxxŠŸ+ÀSü\ž¢ð ðÃR€§h©¼^hªó± /®!àí™yd«Í2e.gÛ ïù.¶¿Èw¶ùJMÏùÎÜEe/ovðR^ŸâMÞîåvÀ;ôù ¾‹M*ò]Nq¾K)à;÷'wRÀw]îaÈw)øÎê šßµ%¹|gÇði¡é|—SNýŠ$:žFÏ6›'%E^º €yx)€%ðìÜ P €gÓ$8ëÞñx|~ðúC#Nð99¸ï¥,à»T(/]Àë~:Ý¥  ;d ÚÙrÎZV½¦S{º`—.Ø¥ v¼T—.Õ¥K€uQQb]CÄÀ: ¦K—€é”¦Ë¿ÇÕíB:ÕDH—Sû)@ºT0.åÓ¥<<«G‡ qV'"㬞ó¬^ú½ngqVO):«)<«—R䔂)<«)áÜâåñ¬^äáY½&,<«yú]cÕK)ógxV/RxVO):«—Ræ6è¬^¤ð¬^¤|?rð¬žÚ¤³ztógõâªþü¬ëE Oëá0Ý¿6H¢äÌÄ| §;éñΑÏüV}è°ó ¯,pØÙ_vÿûäÛß5‘#üuÊe£üu®GÅ8òí—ŒîS(ê=C+e8ð}Cî |!ŠørŠßg±œ²ã–a«l(W>+ë^Ÿ¥ÔËm§é¸-;nÙ)r¯x€ï³fÇ-§6X=ølýc_j€ÏjÜ.³Íχú9ð}æBî¾Ô*ŸÕø¹Ì6SŸõ:Oðñ}]KKß·‡Ù͉ïkó‡ÝfŒ5ŸýyŸ¥ô,ë»^Ä—DdŸ¡Öw9î´rèFÔ‰ï³i!o~‚‹ø,íñY 3ø,N¿Œ7-çA|ö:Oqâ³â°8ñ}Æ B'>Ë3/ãÍÏÐå8òY%j:°g9HtŽ|{†ä“õåRœú>Û~G9õíÕ‚\a:õY° ªtN}öA\×½½Úáj ÔWlú£–÷úÇœC_òÜ îË)~vM@ü,ÏÇ”éßôÁ5=À¯˜-Äå»3óü’#a€_ÊâÜgå~!ìíßS¾TÜts¯y%ºé¦¥¬ËsgªL7mÆ!¹éf1Ÿ°—馵/4L7s7ÝÜ#Wžf¬e…¦›–B×—O»jÓM«ñ“…½ìÖ¦›9›nƬIÓM+™D馛©60Ý̵qÛÍô¤`»y¥¸+lóQ \œ˜±‰†n¼™®ñ¦ >º8qãM»7õ7·Þ´Ågæ›ö½ GO7ß´<´çtWØ{ø¾ÜzÓª‡ï¬7íÁ\~[ò£:Ö›©³`¾™ûÍœâö›¹™n™†L8íNÔñÜ„3§¸ g*&œVÊi_¿ZΜâ&œvoêƒ þ°;gl˜p¦!ÎÔ0á,« LÝ„Óê9&œ›É~emï$<ĽçÇçæXpZ!xÁaÁi9®³ze1ê9 8 å@·ÞL£Ö›vß‘ðBËQ·ÞLM„õfúNÀz3½Í°ÞTÝxÓŠ­×I½h 7 õ9·ÜŒšÐr3jBÓÍ\ˆ›nÆ` éfª‰[nF£i¹iѵ§[nÆStÓÍbË$릛1iº£Ž¦›ñY¡é¦•Û/·–B“K7Ýd?ÀnóÄÈ’Þ¹„GçÜn3âv›1^ÜnÓz³\‡ôRÿÂt3u L7sŠ›nZJ»¼v¦&ÁtS#“–›1õÐr3&·ÜLM‚åfƒ…¸áfª 7óEˆ…²Â¸Ó-7S»A…/qŽ1ô­ât«­Âb !%b ýéEŒ1„ ÿNŒ¡ß—­”Û'Ý ²äAÕ:©ær”’ÊAËáÏ\N?º¢ÿ˰•p~¤ëÛ¿œÑWLIe ¥ðg.ç~,ùAårÒsHå¿{Ì#[‡î¹ü zdqŠl_¶Ïß”‰@Fß´ Í?ôJ½ýw!d~”ÐþQؤñþhD}3=“?ëß¾s”$/+G6ò²®ÈFÁ(•«1„eŽ’„²Rd#”•#±¬ÈŲ®(I(+E6BY9²ËŠ\,늒„²Rd#”•#±¬ÈŲ®(I(+E6BY9þËŠ\,ë߉dp¾çÿ?Ç?ú _õßDïoøßþÁ§8²üéWéÿEü##Úwþÿè¿þ¨Œÿúwã}ÇÔËz¬‹å¯‘(óyÞìAklœýVóÍã½4õ ŽÝK¦BX¤N\ÓÝ hÊÏú Kˆ¥L÷ùýцú[KÞ÷ááÛdщ)ꃱç±W rhÇ&*kSlŒiòšmñ× +_Oñ­±ör»¥>ußi¿ëX±ÕÇ7ÆÚCc¤jnÚvúƒŸýÀxë âj²w,fkGÊ<0Þß¡ÊÍã½p½>ëÀxßÀãûõ}Œºg}ßãVޝàwÊYÁ÷I—Ouú¾æ¥¹~}}WÌb¶úNéN90ÞDš§ø®X_4t©ÈÂÚ`ËÈã»bÝ&Cä9{¢ûªîìõõM1+¦á¢yX|õ绋Á‚;å°¸Mܨ`yìËnŒ‰ßïaq ëÅžàSÖ3“¿”å-àÎU-ßAñq6ðO‚o‰—›µ´Câ'èlAÊYÃ[#¢kéÅ-”.T±-±± ¯òë‰Þt=¦â[b½s‡ ‹¸]=š5ÖϷĬ•n‘V7…œÙë¥_ÝjRÀHíÞ+éÓ„½Ú÷½Þú}Ÿ?=9Û€|½™ö_=$n;%nÞÎï¦§Š£ïç‡g[±Ö„EóØjÁ6Îǧr}K¬-½–ßú|œ3,Y­¾'Ö-jô@ÊôqÎðUµú¦XŸ´Ù/èçA¯wõm±ñÐz§X× îdÔê›bÝê‡;µÃâ}òxP­ý¼Ì¶oã{Æ;åàxo¯î4Žw 9€’ÏöâyŸÑòºŽ÷Î]‰rp¼MÀªí98ÎÏDó=1ý,½ý/ìù÷ï³fï¤cTmß!ñn›CÈãÛaé9¶szb··ô½°¾¿ —ô꟫Í÷ÂúËxs;å xß|øàªéïqC<±j¸]#¦?v£Ê@kû÷Y¥!oåíú·Fƒ‘j;û¸6*=µ‡Ä-Š7ú±û^˜EñÆSìµ{¦Êñ½°Ô3ý´Øõ©ØT9Ì“¿^}·Ú`¼tß kJJíëÀx3¢Å|/Ìzÿñï¶©ãyì}žâòúײåç¸>íãø~Üó mFê¨Æ›Œ[5Ëa•;~·”‚rû™MÓ 8Æ™Míusö®Ã·Â,œyCž9ý%}ù-¾ÖL"ô6Ìç̦–‚îš¾Ö*B‡ì„3™Z”vßX¯Ó7ÃÚäغW V=ºD©Ó÷Âl¹ G?š0›onžˆ¬æ ÿ_{Ùç¶æ8Ñ×l¼îßÜ6ÓMTØÃœÚ~º÷ðtÍØÞ+·¸ÙoñãOaòS´|C̆ ^±e¢qšý——çvÊ™N›}Tâ;bíÅa“º\4>{òÞWË7ÄÒªa¹hl»ônQ—ïˆ5ÛCŠ‹Æ­ÝÊEãVx¾h§œéÔ–0®ZçáR—j‹ÆÍw¾ÛãŠq³S/RÎd³ö¸dlb@CŠïˆµ–ûØØ5áôºS–w/ØîOb÷G°0é펭>b:~»^Üöëê’÷N9“iNqŸM*N»ë5wýöãy+_Hå;Åßå§++Æ&ÒLäqŸMz˜Øð̦ñœvÊô/=×A{ñx~/¬¦Úë’ñþÄc·×5czåºf¯w{}KÌ>y\3Žoa{×ãõ+xuwÊôïeÃ~ßµq&òÍŸ?€ÐjØñ¶ì»÷‡œ­|¾¨µµŠuɸ-Ú›·Ò~¼Ì­¸d¼çv…êÜ)M·vÉØ¾|x Å%ã}Ovzqɸí•ë@É.ëëÓ>WŒmT G?SŒ› –†ßÃ×+ê™Ïc›ÝüSؾį̈_ýtcõŒ™I—ÖWí£büa­Ù¾îo¡-q•+Æö]{p¯·ùÅ9ùýÙ9³j[8r°_‹óÁ|¸Øq°V㕪.ǼÁ}жgÉâ;/1üQPßæ¯=¨Â£,¤¾ýüÈt > ;ï{¹‡úf¡ëRß´õ ®A›JWÀ ¾ÍŽ/£A-ıÙi€9õu3qEሳYƒ™^?]i=HÄ{hõ‰E¾Cß1­%ÒÁ¾lÌ÷˜õ«Ï`>ã8,cÁ|oá§‚Ø÷ ìľwÒ`‚Ø÷®Á9õ)V&¡ÏÞÇ sè;Kÿ ú ÖC >ÛS¡ççTŸ-ûIjN|ŸymÂBÇëI|_å‹Iâ³%³À|ä«¶@‰9óU[V ùL¼Ç4 æ³uAŠ3Ÿ•@>Ìg hóÙçCÌWí½Gg¾j­÷0ŸM¨ ˜/¾td¾fÃPåЗV‚€>›ô'ÓTÃç†Ðg„€.=Ðg_\âÌgÌ€1Aæ | óÅE@¾ÆXD>›þ¾ ùl’bÂäZ§ƒÌœøl2†9ðÙ”ÞT|†H/.:À+[_L†>s¸á Î{ÝÒI€gвżg_j¬7É{…ßâ^aÐ â^xÎV¸Wh *âÛÿ!®è«üáÄg³²ß†Äg¤€ø2‚ø(ô ú¢r„>œ(Ðש™ ú:- }»W‰ ¾¡aïÔdL곿— ê³rñR‚úµ‚úú |IêÛ_\¶œÔ× < úƈçÐgS,ªs /¶B}fþŽôÙ5낾n:ú}Ã¼Šœ2ŸY%x1d¾I÷`‚¾(Ð7lYƒ‡>k7HÌ™/mPæ³;ãÝóY ÈsÎ|Ý>ÁàMg>Û‘Â ó- òwèFŽ|©` _ÚñòWŸ0Ÿí©¡‚`¾¸ÕA¾cƒ Ž|Ãôt¦œ¹tÄxe€|ö(°yä³í< Ÿm-¦œÉtìZŽ ùÒ¶˜/ 50_ês0_*ç0_¾Æ™Ï†ùdÊ™PÇ£}c0ß0· úì*l\ú†­™‚-Tù"ôY§èúlÓŸO@ߺ T‡¾\ò:ƒOÀè³qîTì³'÷×ûâÖÄ>ëň}Qar_ì©‘û¬+ÜܹÏö${â>+„î³|÷Ù«¶.î‹VrŸ ŠvqŸÕf\Ü—ºÜg¯,¬ À}VÒ¢sߨýî³wÈ?ùÎ}à ~ps_¾“s_¾Æ¹Ï>¤Gç>3ù*Hqî³Þ|ûì%*÷J YrŸö»‰}vìKYÊÙ!1hˆ}Ãæ”êØ7Žé߃úöZ’˜ 곪TÀ¤SŸí«7ð›SŸ} L >ëæqê³]~tüLî3ÃêN‰(üg#lþ3•* ›Ð,Æcÿ…ØMþëH©Ù ¿Ô(ПåLƒþâÝüYß|ÀJ‡?}}È~¹\‡¿^&5J˜ÃÙkX°£á^¨³Ÿ5ïØÏFÆØÏž?hJ~6>ÿY€£Pú ]öÜò5ðòQ ë—sLòžĦXÞ è4îlÜEïyµïÙ1aì2øÞ&ã_±ïŸ@ß;¥ ø æeÜYì\ŒDë—¦øJk2#uà‹ƒ4>™¶ øâ´²€OG÷ |v +VßW´Aà«vêÞœ÷L^CuÀ{vîk'û¦Vû>S™¨:ðÕÒ~ˆ}¶üEGøl$=—Ø—ìZ|{mËõ3€Ï´³øê'ñÀ—n¾º¨øs(öMž)#ð™œ_Áw¾‡îE|¶÷ƒr ö-mË“ø´(#ð½Üoàãþ Ä>3ÕD±|ýU‡’øwßD|“¡²Ø7/âëïeÝÙ0êÉz±®#ë‰qÁzI#ë…³žYà‚ìÀz E!ó5ªü‚½ÅXU„=û¨“{2¸iç~ËÆ%ôÙjB ao·¤Þ°Í$ì…@¥OËxž&~ÁÞÒži/tšvj#ÓÎ0R”Ô*#´¾ÙDÐúô¥—Ö×éDZ_’îŽÖ7éž,ä¾Î*Ê}Æ[·Ü§ÉŸ´gÚμm<÷c½iÏ¡qў͜·gÒˆ(÷ÅʘrÚxöj_2}–Ú÷q‚j_’Ó öÙ‘f\µ/ ±©öE@{¶(ƒÚ7´v`/ö¥öM½¸€½dîKµoðD¦Ô>í(ÿ¹Ür…ä¾Á}7ª}UØ Ø³‹¨:ìÙ&3>sö²f¹Ï6(P§½$¨Qî+Cæ›”ûd2@½oñu‘ÞGQ°gêÀsÉ}V̼LÛuÁ5ÐûlGÀœö¬ßËÂ36ÛCî£$¹Ï¼r÷L$Ä$Ü eG¸·èÇVr_£—ǽPzˆ{ö`ÁB¹ïŽ> Pûýõ‘ö’ÜKµ¯Ê®´·W?Üj Úg¾uÀ‘PûÊ'ÖœP¨hHíKåµo„§Ó^µÄ½a}OÐå¾ý,È}¶psÜK2å>3’¦¸(•Ó öÙÂ ÔØ¡Û²ÝûC¡Ú—K¨}£ËžjŸ:Kj_£G©}¶‹ú%„Ú×éæQjŸÞ1©}ûKEf¤Ú·ÄwPûæüaåy^ý‹øÆÀ¢Eb_hQû&?Kí3Z¢¸çj߀Ô¾h5Õ¾ùÈÌj_¨U”û:])Kîû†È r P¡õíåã{ÁÞ˜UJ$´¾Æ­;i}«I¥ƒÖgÑYë› Ý)­/)rÐú&½KëkS !´¾ÆšÔú–ˆZ_ª ´¾ÁžÄ¾YÅšû:· |v±ðŠ—R/ϱžÀ—ôJŠ} Ûáç( ïxpÊWIM‚¼Â°[ÎxÉWéÁ¼as]tYtZ1ã²è´·—Æ£<ŧE( ϪCæX¥ðTOñM±#Nñ™0à Îxv¶’çèØiÉ©C|´tÑ!¾)Û[žâ+<™ÂC|6" ñÅÒ†‡øâx›âÛýŽGÀC|SæÑ ={”TôLHÅéQ_à>3Õ¸ÏðÅf7AOÉy¦x{NðÙJö:Á·Wíܨp̳zóÒ9;tÚÁO%-:'ßAŠzɺ”3©ééôŠ4½ ^jzM«5jz!KJÓk¡á=®ÎÕš— Òôb«€š^œ­¢¦WyT•’ÞKŸo’ôÂt˜’ÞË=½Wß*z¯ì¨è:uEïap)z¯F½W JE¯hSÑû´jåA>4H¤÷ê@Iï“% %½ò\69$½ï‘ ˆƒ|Iq„¤Wtä™ùBù¥¤%ƒòìñð¤$= ùij}ÓiÉþB'ùdÁÍ“|½° ®é…eOò…þIQ¯µV–¡¨WW˜—L¸)ê……Oò€ü êuò…™e½8éGùb÷‡²^`ãQ¾PzqàF²^ìíô’Á @/^_žä{µïÀ£|a‹Â£|:s¥£|EóŽò=:ʆ•8Ê÷¾y”OÓ @/èÕ£ˆêØi½ Î3KžÄQ¾W;2<Ê÷jšåQ>zPås”ïYÉœóªíŠ\²^üÌ’óê NJΫæ3 ÇÓ|œMtœOo«Žó=U"Žó‡Ñzõå`Ñ9/6vÉyû%¡}&8/WfÁV†òi¾AoÞ/+9owyœG=tšïán9¯.LòŽy¶Wý\˜_UæÓJV‡ù>Y7ò0_Ñ¡1æÓ—M‡ù ê0ŸF€óÅQBæ£Îò5q¨Ÿå I‡ùøÓa¾*CP,‘5oóâûCÌ‹ãÛ:Ë'{å³Ñ˪Ӿ?42ÅY¾Aç³:ÌׇˆìæëS²óéK§Ã|;0Òõ´Ã*]On7$ì…¨ Ò“ÙÎò™§Þû,_:[HË7ÆŽÐY¾t¶ðæ‹“š<Ì·xÆI‡ù£ZHÙ[jãà5Ó‚~¨x<3G¯3ö²T„wrÞº‡Ê(<øÂ;)4++£PÅù“´èðŠÞIû $idqÀËåV„$Ýyè^¥xÀŒ2äì1krʼn„€5)Có…^ŸAxç”/–°Nx'™oxÔŒÂm4 Þ•²Y´Kç“}e>[îBY£Ì÷É u¾Ððè¬S],gM¤Øº›‘.¡ó…3ê|_xˆÎד…:_R)ôõÂs®óÅ!hé|S.l ô%ë3ùê|åc¾:Ã!ª+}¡ Cé³sÒãvÝ/}uÊò„J_rr¥/™XÑ 36_ õ™­ž :—NÄBê ëJ}iÔ©/NiSê³Úàó©o4‰Cú’CtF« õ™¼2&ƒ9H}É¥+í9ebE­Ïöʸ_híê­Ïš0©ý¹í‰ÇË}KztÐú,rÌ—9ðt:5Ctî÷c ZŸ‘`Ïi^ü.÷-áŸ×í9'˜Sé³/->aϹ?¿ó²ç «6ÙsNnªRé3£¦Ëc§ÅDwBè s$ }¶ÙJ:ƒ=g˜"ОséT‚»o1¿Ïø9ÝúGêhÎÙå@ :ß|å7:ßþu è|¹˜sÊ6Š:ß|ZTî[FðsÏbõÐA'ì9Íõ.R¾³µúÉù&ì9e±DÏ<¾ß`Ð9Öã{óåÁtÆsÎgþçæ%ôY94 u¡/í‹BèK-‡ÐgÍ¥Jv :×óÃËX+L<}^5G(×…>‹ ‰}hZtZijëü^ê?Zt.z<¤Ò—6§iÑï!”>ër)}¶~ÈJß 6yYtžÇ|9p™û;$Ožn>³æ¥oÖ"«OWúl,uêzgbµM[QWúÌE]nºÒgåä|6Ú¨ºÔgþáo©ÏÖ©í’úf«:öçRŸ LQºÔg±¡x\Ï¥>¯ õM;ùqI}ödˆk.õY9ó’ú¦i€dXO›Þj}6úéƵ>ò2òœ|_Y?×úìäÔ…ûN+e]\l˜¼™wžW2£‹}Ó&\åbŸÅã¥lçbŸ…HHq±Ï>)ÿ ïâN-bßìô!F±o~ï%öå.öÙPƒØgÁÀèMÓžùéä$Ä>+ç½Ä¾4$!öYìUêv¯â’éjŸ~½(ð¼®·Úg0›uÚ×td <} ajŸõŸ ±O…äHÍMë·jÆ»ÃB2œÈ|ûÙ0åïJéöæéðÿø×E.æÉ×ý Áª{„ˆ;DŠ=|W-™Æ{ü_)¥u…|²>î#—¥”TÒRYJ‰²,`¨±~j¹R¢,¦EY‘eý÷ H´‡‹õ‹ØSò Âp-_„ú"†PŠ¿ò'êô?Ëàñ>júÝXØHjs\ ¡¿ýnXÙ€é'šaÎÅ¢Î$4Þ(Š ¹¨ÈÄ¢r.UŽì%Ȱ© fQ9‘GÅì5¡­T£$\)“JJ¹T”yë¹JH¸ŠR&•r©(‹x…„«(eRQ)×_e{íY¾a£Ü¨ü-TÿQh¡ß ›? -ôgù~†úgåýÚ¿ËwGúãQý‘…þ·òo¿ûêýÑ—ñoôÎüîkùÇ/ÍïËúOÐVêûÚóûoö ççÑŒÁÆ^݇ø?ÿ§º/eüÇÿôŸ{öûæ÷ÿËš$f±~þWýñÛŸ[$ÎþûÏÿfkÞÑ‹ºë_uôšcÔú›ÙÌlNºC}êè;¡Žú?rôEý?þïÿ,3'¦ØFß]JÿqåÅïkTÿBX£Ç-Áª!ÇÔ˸»·t9«†÷=îx6‹ÐŒè-¶Æ¯Ý×wo9öŒg‰Žøî¶4Ø_µÎ;¯êûñ)ꎙÎ<ö@mýäŘH·oý¾ý8õi'ÜôY±¼ætì” #‹wžEÒ^Û4E‰?ì{5FK‚wϚ͢KŸ˜wµ½ÒkÇÙÉRÞãùý,‘/Šû hÚw`ÎÙúý ú\ðX(…eYlá4¡lPØÿjæû Qs«-ñ÷J†þ÷§Ì6›¹5sÓ–b=` <lŽÝŠe©E)Çôo¯ªxtÿøhëV™¡¨Ÿ5¦ÕÝ(„ñ4gÑÝRä¤î9ž·wÊâi–÷8.iæ›M!.íL@ûD”ß^G6÷U<2TË©h³¶E7fö¤w…_yô:"ý.'"æœùçÜ‹g5ÝÎöŽ$§Ž'·ˆÎÊµ³‘Ç:úTGF–ëŒpò:»RÎ9¹f6¼Þ}æ§Ÿ±ê#Z,|ÆyQ9ÔÊûabmØÎ-¯‡·ŠÙ­¼ +Šm˜Um¿Ò/é>«ÚVßéÝýEð•sTy§O«)Ó*'ÚÝ«˜V+¼—ò`ZåìÌÍ‚Ó/çðNzS»ç)œVáå­”Óª7 TΩ4¿SÎ~ÞIñR¦T=‘Ò1¥~ˆ!¶S0¥î3|JµLO™>¥ÚÊÍ+·8£B{/¶lô—”ñ{|RåKX¾“ªzü+>©ÚêàóLª&û{õˆIÕÎ’{¹•“*ïm«Ïóž–'÷5ŸTµ„+æAé¼§ÃlR¤úùˆò¹°¸o….ÅV’ç5­.¡ àzÞÒý=» »ª¿¥/BÐû×yK?t–â=/©m¯ž&˜•zÍk×bž™,ËnÛYLë¶3£ê±Xœ'‡c®Å¾Ïç--ðÎPì]:4UŽ æ¸Sxž‡ø˜Cq¤œ©*×ðà© ŸôîbèoÊ 0_ãXã„ÆÞÿ¥Ž§º0¨þEGÿê Œ…ÃÕgž:µãè3SÙGéöæÖÎܰû¿ä#ð÷˜Iø3S,t {¾§ÂßÏÃè-€¿³ïBÿ/çUþEõ€§7¡ÙD•îCú³ÚõœþvxƒþNïádžÓß ´¹ýí”å8ý3?§¿ÔY ¿“éô·Sv@Ñ¡€¿è°ßIð;ØïÔØ÷9À~'«Î~§÷|Gìw@EÊü5ósûþtO d?ë?gp°ßÎC¿,`¿Ôëd¿xº`¿ssÅÀ~© d¿GN–Á~ç#à?²ßóÐ{/áïñ·$Á_Êø³‘ãÞ\ÜÄ‚þÒEÀ¿G¾ìzI ‚þâ•ý>v4!ýY+Ÿ‹þ¢¤¿ø ‘þùC$ýYÊéÂßóÒ^Šð—êø³ãÄEø{¶ŠðgÍ\HYxY£•ðg¦þÊþ¬ާ€¿¨1ùO5þÅ(!þYß«!þEOÿìFnWIüK·þ= LMü‹ï!ñ/•ü{^†—!þ±Æ¢?õ„èïa5ÑŸå‚þ4SˆþܦCðW­R¯'TL¬‘âôw C¼2 ?}ÛDÏã ôS…~B?+¶x _´‘è§!+ô³GGÖsúãË!øÓ¼ øÓóü=¾JMðU&ÿ®÷[9ÿiˆÿžó&ÿiDˆÿô¾‹ÿ"ù/ &ÿÙÃ- BΫÕâ¿è.òŸÆ¬Ðîî“õ!Ú‹èÅÓÍ€1Ö€€1©Ïôj¬žõ'Z¹³ÐR@sŽ€Ï ;"! Š%Úñ9¨õ•ª‘À”xÜ ;S`Nq|è;AøÐÇPß! ÝË·XÈ€VrsªÊ@ÀgÇ’@@}7ˆ€ñ䈀ú £ÏÉ€v£÷bÀ‡N#Ä€ñ\È€½ZˆíQ·Æ€ž5°ó3`µo ßŠ h#ݯÆ@'F;‰€1Ѐé" `ô0^©°,ð[ÿ+ñŽf)ô¾— Ø?_$’í°°K#Çû ¿9SѦàGû-j€9ärp„øÈ25@Kñ^j€"5P|õŠ€çôÂ%>rKðéô«Að‘Oxª€f…ç;žTíò@|&5Ê€Û(îªMŸÉ.”íVnî ð1n'<È€ÏÀª€"(P|ä†* ÉìåR7¦hgV|Z8iÀJ Ð|—h³™“•<á‹ h‚ήc®êŠf ð‰¨ª„À©sèŸð{ Ðî.ßI>Yµ‡§] >áh ™›Ò XÃo)&«^©ÖA´×áÆ@¹¦ x8'Ü÷®2Äl¥sTŸñÜxR2žFÁ%DÀG.Á(Z NB´›Ãâ"`*" ¥¸•&EÀG!{(ZŠ¿›ã›CÐR¼h€¶|ôÍh€)`<*h€ö²ú¤h)¸9PFÔ±È <†Àþ¤ÄoÔ¹¦øÈ÷”8Ðö”œú ÆPW‘âVhÁi0É.Åm^" =Îu©€1ú‰Ñ(r ¾T­+ ÈÐe@û2¸ø%”ÇI Ü ÛCÑ È'.”¯ Z)Tß#… ¨á&¤ï!q }/ð©pª" Ô[O L ˜\ÕäÀIÝZ(<âÀ”‚ÉU¯¢8PÏN8è›V˜RÀò†&ÔÃ2%@Ðf1G:‚ û/@°!že€ ‡N€`ÿ~eðùàHS2`Jr”ò… äª"X£-X0RÈ‚Q2YA—‚9³ r2ä%`Ÿß€ÁH! vxwÜw÷Õ¤`pRð$ râ¤O*Á`Gì€A ì`Azƒ äÜ,ȸkÁ‚ü& ªábAÓúÇÈ‚öoäqÃ`Á‘0ÈøîƒŒô =ó—ä@›)Ÿ›ñ¾ êÞdAæ V*4DÁŠpª‚Œ%,Èa-äùØ@Áéæ‚ƒú±P²@A~ì¹ê¡ä@.ƒƒm=ò[Æ@Æ{ Œb çyq`£¸%äAgq ú_¨6ŠΙr!hÎ˨/‹0PãLØà!<00R >üûK |Æ$8ßÙAu…@ “AN\Á:±¹"ä"M È‚½úù¹úHôwÔ¼  ¾Ädºß °-@ÐL ÒÁ Úé/PÀE7r—R\òÄIpÉW#@»êêAŒZKp)¡@;ºî–šTU  ­âѨJÓ)Tm5ï)T'ÙH¤:I€êÒ/‚×PTD"I€ûɾ?$Àà’hßoX|R”˜G pÐðô |šS×LRÏUÿ¬á¿ý=ÉR{$ÿÙZÒEC‡¿j~À¦”ÿÍn)ÿ£ÍOê_•ûÿ,Iü«EŽÉ›K á§–òŸ\ÛQþÛ­€Ï"G¿#÷¾°/™ÇKþK)ÿ4Ö€}'O½å?™Hþ“‡k`ß¾ï%ùO%ûNŠ€}ç*צ€}¹dǾ“çÉò_ÇÎ}iˆ‚ûNŠƒ³s_NpîK/Œô?3ìq‚£hG9~ ì;c¢œc_·À¾“Ç5u”‹·Üwªѹ/çqîKcÜ—Þp_¾—sß)çËÖŸù*¿S²ï‚üNžöž>±ª`ßé~§—e~ùšŠ‰5¥,½°¸uÃÄ)«ðËå8øÚø+ ðKõ[˜Wm¦ÌæŸñ€É}9Ï‹y•“û¢¡ä¾|ÀwPÞ£hŸ=‡Îæó*¾wä¾ó¥õ5¸ïdñe¸/§LL«Çä>}Y‰}) °/î ꋆԗ/*˜U9 I}'Å A}¹œ†‰•o©ïäqqÇ©/Æ>©/<¾­O¦¾œeajU`_ºO•ÆUÀ¾x]‰}ñÂûr9“+_b_ŒZb_&À¾+³k¤Pää 9õú¬¢×µ‚9½r:ø¥ òËYJ¹ÞW’_Nù8Áòúå‚'Xψ~9KÇü)£êuYÌyæúñ¾‚þÂŽôw>ÈNAÀ¿s0íÅË ‚þRÂçÓkiB=L¯)ŧ×(µazÅT@öK¥L®œ,£_®ÿÄä7Z˜\u'°ß•‚ÉU=# *Xh€/üfýb®"û¥ÁöËy&W½Î~9KÇäʯ1Ø/ׇ.•å¢ Å™¿Ï2]&Ÿ“ L>çø•ÏÎ úþ7Ïü®;“ OMÐúŠ‚îQë+ƒò)µ>+§]Z_‘ç#j}–Âzg7²Èµ¾"çCÐúlbì—ͧDøuÖg­ò,úl¦„ø{èJ_þ"Zßâ׿2(ÞRë+rÆG­/®¢Öy¨õ™–ri}ö°Ì@}O2ZN±¯t†V€ØWä\…b_éÔ2 öYw½™úZiŒ­M±¯ÈÕÅ>s§çxD±ÏRÊeôY*6%%öùk£Øw÷AþóMÉÒ„b_1~sÁ bŸ9»i׉?{~8±/.Å>[‹ÁÀbŸ¥Œlô™ªµÏRf6ú4'†%Sß.[Š:ògF9NP<ógVlNPûŠ-ÿ.±¯(<,Å>û¤‚² öÅ™Sª}Vçzª}ÅPö·€¾Ý §>)öYo¡‚ûì¢y‰}EQ;©öEª¤ÚgŽý Sî³…¨Ë}VŒïpPî+ ä ¹O¦Úg×ÔKí³kpjŸÍ?ýRûÌ—‘oPíK÷†Úgç¹ý™ç"ï?ª}Ežè¨öÙU¾~¡Ú§(µ¯Ðñ’Ô>ÕPjŸî.µÏ›@–á?ó„ù[@_³Ù¦®ö¥Ê@í£w‰}z%ö•&bŸ]D3OûÊ7~ˆ}ö1s>Š}<Ì*­/@­ÏŠù®S…¡I¥õFþ“Ö§6Pê+Œ`+©ÏÖL%Û}¾Gw$õ•â¤>KpBê‹VRë³?„F­/Š¡ÖW>XªHë‹fR볫ܚ•ZŸ¥¡õY9– ®õ¥’¡õYJ…™'æ×”‚ùµò8µ¾·Á=®Ä¾·uêŠûÒ½ öY9=þ‹ Rî³,ÕS\îË ˜_UÊ}6HÝŽ’z_ ê}éÞülÙéb.¿t/~)‚_NÁ«sÔüÌy.l4¡ùíå Œ")úFi‘è·‡žÏžýl ŽlüùÒÙ D¿—’)ú½ß÷ë:þgïE»4?ÙŸIóÓ×WšŸæ*‰~Ñ¥ýôQó‹HÍ/Æ5?ã—ê&šÐü^ºL•æW>ʃæ㟚Ÿ}ÆÝИš_Jqͯ”7‡æg)þ‚æ÷ÒO¤4¿w`’ƒ"‰÷Ö9ær | +¹`ÞIE(ì;y Bö //ûÎʵ‚ì;à í;ÃR“öa©IûÎÎà®²ï «PÙwÒ£FØw~°û‘}§òȾ“FaßÙyž^ö”Tþ³!V]˜wÒ’Šæ2¿’y§ŒçhÞ©BhÝ)ƒ@™wÆ54ï”]œÌ;eZ%óNîÉÂ3RháÙäfžfûZàÒ(•ëYxÊ’Jžòò, Oõ¨,»Î7¡ð¥(|æjdØË)PøÌ£hɆõxEͰ·o>a1 O Ô÷f}i% }Ïœƒ®Œz碙Qï4ÊŸ,>KYàK ø¬˜/ |)_º¾¨0ô½”ú^J¾g)o6ë¬,ëÒ÷rŠoA¦« ïý?ä½;²î8²¥9•#V)Çø&0ŽC[ B 5kºûz8vDÜÌH»VJ¥’±q@ÄOø°üu®Nz½úž‚ú^+¾þØ0Ú„¾×JJßK¢êv½¤ô½¸æíþ}­„ú^Ä=¼K/À×®‚À×J ðù9)ðµ|í*|­ŸG™_+ÀWÝ‹À×Kè5ñF!ð¹?øìõÏÍPà‹Çƒ•æ!ßyœ?}ç©ðõøÎ«7TøZ ¾v¾^R _{(|þÑ)ñÅU[7í\JJâÓÛ$‰¯•@âkWAâë%yš¯Jñ%¾VR_»_/˜²x ¤ñµh|í*h|½d`Îò(òµ¨|¾Š*_/˜³¹ *Ÿ^ ©|í*¨|½¤Tc0öè¥@åk•Ê× ^ÍÙcQù\B•ÏWQåë%¯æì±¨|­*_» *_/)•¯•@åk%PùzÉÔœE T¾ ‡A¨|­*_» *ŸK òµ¨|­äÀë‚©9‹¨|­*_+Ê×K¦æ,J óµÈ|­2_/™?æ,e¾±Ó‘”2_+ÙwÍÙøzÉÁeö®=*…¾Vpq™=Ëx:_8œ•A4u¾qTªvé|“ûêñ^z³/WYÁçà*«:“«,K(ôõ®²l‡BŸG‚B_+9¹Êª}­äâ*«–o®²ªó`•uWY•”ЧÁ¡ÎqÚê|ÿnr$ó`†SXx'›âAYÿB™Ýì3¯Zƒ~žÁ7 žÑ¿E<óDQ÷Ñ2ˆðtÆ a¬ ÌRRD-ß‹ í  TÀP.™½£N)Ï–:FVL5ª€§ó)ä!e,CÛ"žÎÜP"`$n‚DÀs£%EÀ¨ƒâPÏ© Ä!åÍWP* ¬ΗY ¶v¨Η‰Ñ¡ÆÝa ðÜxN%p:È'UÀ‹Ú!UÀر÷Ð/ßU  ‚)Fâ…ZŒ—®xŽ à×&ìI©FH—ÅÝÏQ¥†³K•PÔURKKÔ½¤Fˆ”_ÿl`8õ®`,ü¥ÓIüò3®*íXà@‚oéúSÿS®és_½ýZ³Ôÿ¤…J¼á¦`0Ó ý³éœz‰ú÷~:æ]oµô?KyÔÿ\BýO”¨˜Ñ_¦Û’8åUàË4¼%AKdÀjé2 þ÷*Ì&õ¿›G™ÔÿnºJH|‘¨WúŸ¤né/“ÜJÿ“-ýOÏ$ýO6Òÿd» ýÏ%Ôÿ8ZÖÿ^$eµþG¹Ùú§ªõ?ŽŸõ?Ø!Pþ‹t}£‡}I‘kñöÓcZÿ£i…@w˜à‹ÀIß¡Ÿß—¦¬/²“@†•¨v¤Ž––TÕ²@ —À¯d¬ ž‚àql¹$Àx—g?:@Xä¦Ì àØhÀI¯±@uF ¬¾ ü*P.o—@ß‹ à;iJŸ+€z Eÿ¼7^ÅèŸ÷N3T*€œGV5ìTõ¦Ht(€4±¨v¥ÒÈ à‹@Vc_¶Di%T_„i¶è{Qä·À   `ŒviekÊÇÀ%oå§þÇ/•促‰î(ÿéã+ý/~ÂOꓚYÿ{tÁúŸRúß{®<ØêHä·Õ D}¥í‡€J}”¨y/FUiûdP‚ í¤ÿÅæ±î]ú_˜0Ý‹þ—P#Úò$G#:G¦ò»èŸ*éùŽþú:×bÿ,OÒGglD|—8Ëœ•Ä%ÎGt†PyôœK.im¡¬µ¥·•ùEGϹä·Å2·å’ÿîÜžÊJ”èu.êÞ‘–÷<2_Ô/Û¾qh°¥5 7Î3NžF;¡9ãô&Ïuò& âà)ªLÙžY9ɺòcŸÈ`tÇ×9wmßËz„²~çÿW{ËÀó[)÷ßßoê„=x]óÜwž¹pÎHEtçÑÙYÛéó[;üþ|+è|ÄÄÌ‚yUÌyf%8ãŸÎ§úre;£#ê0ÅÈyţơâŽxÞ_¯¯ :ÃTøŒë÷·âÇçì™éòPÛÿ3M+7ÄÆ:wÏÞ‘¦ú­vÊzû> T²dÙe¥ÜþŸ‘fd² $î=#­Jl<ïídŸç^Ù!°…ü fÂ2CÑ7à±Pd˜ü ñíȯ:„erœó®,RÙLýwåvÏfr·zÞ¡ëåxÁdö¼ã ‹:‰ÍÏûÛìgàyfÎøJrG‘ùVPçyp ÈúÞ€³a|Ï{ìxžéh¾’Q‡°çxEa‘­LüzÏ•á`œiæŒñ™""2óUI˜dæxá<îcštïÏßêª:ofpuš›¯$ ÿaC6öówe‰˜¬:3ëÖr,²9Yú¬ Þš«ß j¸ÞøÄÆDÈ‚æb®Æ1ký‘¾R¹ðN‘¥û]ž<Òr÷¼<ç0òÄW!ò`çK1ðr½u0˜Ô¿ï2àïȯÙ¯eudÌš¬~Àv² ?Ž‘É8'ë„Û䇃é^C—Çzg(Æ9Y]'ΜÞþÐãÌüYR?\ØõÄd½÷‘ç¦g¤ ޹Éák>;]!ïûÃ<Å=ÇsÕ\{!~Ó8ÃD—ëÏYjÉøžŽ8Œ+à ÷Ñë•5ºRSwn‘£ù»1’ï~™#ûÎÌõùŒsr¢Þa¿Z%ß'jÃK5ꪳvT1Àõ©‹óéßåyet4'š8gÔÝq2×UaΘ/ç^”{FÔ‹š¨8J%|äÔ­VÍ= "ÏFžu™öŒÀµ9Q¿ÏaN+‚~æD£N®ŒÅZÝy«ÊQÛI×W2j¢Žš¹×vÞ5QãÄ2±0Œs¢òós…Q_NÔ åö ý/s¹Œ ?µ¨ê¾¶BâœOÕpÅ¢ÊþmÕ¿Q‹ê½a×ó-0w(¿~Ù®}«E5nž_ô+R1ÖDe—÷=5Ò¯ý¸•t)x¾%¢–Uug¿rUÞœ(¨e5^‹Ü\a4¾÷ÝŸ3¹º¾uo«™z×]ÞZV•4ïÚG­«òaºö‰uÕO4±®ê§<6¬«Ì?v;ÖÕ8غ³äÀºúâ°ÿ g—\W¹]±Ù°N¼ÕòÅuãpT/%Wº­\õXiãw¥—Ïloñ0œ­õ&Åܨ¡9ª7ƒËjÉ+W Ê[¾»rQW}³¾U.ß_ ÕCsXTÇQç×ybQåŒú ‹ª†˜žÃW/ÖyçO¤´f×ùpMeUy…`xœmEÿJ¦êΆÖT=wì¹îÙ‡æÚve×­76TO¬ ¹Iº®½Öԓ鵯Ô{cX1q®È¶3îÞ™L—¸·ïÆi +ëÎ^¯«"æäÔ¨W4¶X9S_HMWt+gê ©ìŠq»1Zw• .©g}â¯ü½µ‰Ûê1++e{ªø çT} •\wÝoó>¸¨BñùJ¸¨òî÷™*N¿êªU5¶¢uœußµ¬>8þü °¬¾‘þmI±%IAíÛéÖ²ê/Ýýb]eª³o k];£Îĺú@Vøô@‚4œª~%sÝ_Ae9Y~žR­¬_Ïy`ŒmÞWR k+¹žš­Èé÷õ¢ÖÕ÷kʲßVFTýí^ì·E °*û)οØÏo ÙO©Ä~ñ–œõ`?EþûmlsÉ~~ÓÉ~ÊÕ#öó«Eø‹fa€?O!ÂßvÀHšð¿î\à/öÝ`½í÷ÞG‹ð5†á/ÞÅk¿rŠúm_‹@?¹Ñýb,÷ýb¤:.ô‹:W#Ð/fÓXÐ/Æ{³ý¢:œ"ûùw#ûEz²Ÿ“ì×êÿ4R ¿pì©·•ôç‘ý¹ é/<}ÒLOôu@v ¿xÌúõIñY()úó’þ"±A}OI.ÒŸ"‹þü˜¤¿í‚7»èÏ?é/Ú9ú‹h£W€¿h¦PªØOáHÅ~Ûõ’ìÄw/ìÎ_µ'&ûÅ¿œuØObb¿ÖØ¯Ý ì£¾U à¯ÕüÉsKð÷š ü)îªà/zZŸ%ÁŸ–ÁŸ~aÒ_T™ ýµfŠþZ+ ?÷8éOž¢?¥ý)•Šè/^¤\»Eùsüjðç&üÅèõ°¨ª/„¿èNíš ~$Ÿ»Lú‹:ù¦‹þüVþZПMП¦™è¯5SøU®…ÿâ%.: ÿi(ˆ­ ðÏ!þù%þùç&þùÁ‰aYTðDþóëGþk÷ÿùÁÉòˆÿ¹òŸ&4ùϯùO‰SÈ~ €ÑÊ $ĺÊ\&Àv'`«líÃѲ ›ã~ £¨ÏÐS†èß(§N`«ÔþPè{ý\ÀøiÀw@¹ ¶ @Åéú÷%¶F€®Ct ßI`®åÎOè Klu€­0ê úCdÊ) ‡èÏ( п8Ð?8 P‹ 0ªø’ý¡’¨ÏfþF’"B`ì1V ê«ÝX²¾bÀƒ3Ôý±h€ñ‡* 0>vuO 0îPûF‰€´ –xž{ÙI ;Ú(PTˆ©€aÅT{>©€4“ æ´µ•¤ xÜ`iÊ€ $0‚!ÕvƳ¥~Q”]a ÜH”½œ8P¶yâ@Ùš Ãb¸6AÚ‹u* c»Ú¿‘Ãú]80ž v·äÀÏõ,¨`?â@ÊüW(4rà©¡êæà@Å€"ÆoðCý«Óû£t7p`Ds‚¢ŒYµÅ#*Ü„80bI] *º”@0ÜSJ#*”„@0ÂuÔ&” ¨X"Á0Õ¬M(Ið8ö:à>áÈNŒG=YPћȂaZ M §›±° Â‰ˆKŸXpŸ‚L° ŸŠ,O5°=XÐONp?wt™0¸U `p?¨¶c_y/,Rç"FÒÀ‚ûè¬bÁ°®ÃñjaÁ}G(ÇbÁv°`”@µÆmô}IƒûŽè²¢ÁèIU Æ^º~Â`\TßÂ`k0è" ¶«ƒÑ±Q¸ lí= ÁvhÐÝ ê¡ƒQ°-R`t¦lƒ-Â` ñ½HûŽð®‚ÁèÞX¤@?aÐ?a0êÔÛHlW£äªþ[ƒºJ4¨A&¶*ÀÁhâ[á ÆO8¨Ñêçê©„ƒeá ÆT8Øîl÷êÉ…ƒ¾qÐEô“[à 8Øêj^ 9¯Hƒ­Ðà~À?¬h0þœ î•!Ò`””àEŒ«.ða-­n–8è:ÄÁøfBFà`/©µ5ž¾dâ`´³ [ËÀAq°•[;ÀÁ(ŒîÇEòÆGu+M±pп.qÐONô “}oò ïMÔ]<ØZúÉɃ‘ýp,<Ø®¶>ƒ5;Ń/ò`ôgýamUð ‹<¨y0 ¶j<è{“ýTäÁv'ð`«ôs’=¦äÁv/ð`k<è9Môì$ºò ïNtËäA÷™<èLl÷*ô˜’[ÃÏ2~äÁvÉËåU— ®¯|'Ƀn‡<è:äA}Nˆƒí"à 8è‡8èW›8ØJ€ƒ{ì]A0JÎEô€‚[x°•L¬¯.˜š°p)ظÀªd¿4aë*¡JþE®"A`9¬wCз¼›$ÎØU/J`¬ž:²•žDŒ¤I¹= n“pßhgEÜ¡çÿÂÛ«Žjɱ©;º ¸”ÿy7Cþ °bMò_ìT‹–À{œ©Vð_˜­B),þK±BðßÉϪJð_Ä>,n#ÿ… Ù»è€û*î'œŠ{lÿp.ÚŽ‚þ" @Uüµ*€¿XGjðKí±FI 8á/ãTŠ€Ì˜&øóÐþÒᮘ¶àÏUŸ7ª€¿ØPÔ‰?áÏ»dÂ_lCÐØ+–®Eö‹uúØO+Ø/šxökuÀ~QT ö‹wo[l@#¶¨’"à$O“ýö0Q+ÒûEI…ˆýôÚƒý¢;÷bºo2ù<±>ñ9É~­°_<˜ì·o´uûm4†$ûÅ®©îôkU€~ñ…ƒ ôÓ7Ïè·qVÉô‡ŒU ~‘¥{?ÝHàÇÏ­ÀÏ¿öſֻ"¿­l¥~9_+ÁÊä6H~Á=‹èþ‹üt•ÐOO$ôÛh (ôs Ño“±&ÑÏ÷"ú¹?D?½ŸB¿VôÛ~˜ú¥úq°H~z„~š,B?½äB?M:¡__,è·…©aÝŠ: ³$Zœ/‰„~n™è碟¦¡ÐÏuˆ~zr¡žÜäÆ ÅQ ?Õ øáeîÛ(Í‘ûxãÆ}*!÷µp'sŸ[&÷m2 ^Pq¹ssJا‹„}ªBêS¡O!ô¹BßF @RŸ¯!õqú83¬†¥Ð¯}Êek ™ -Žƒ 5ÀqQ©£ÈÏ“5@סÈœäÖ™qÞà Ýž4@·L pÐNà(‡^K€!$ª@ß  .‘8'©Ž—"%@—P8¡¶èv(ú*J€Lxo pÐnOàWòÀà [¦èv(ŽY–!–çFX£8hÉG Д™ñ^à‹À!–\‰-ê$úÞ”c7[íP´”è«(NÚ\Jœ±` Pã% P%’ÕŽ$À ÍÁ`+¨>KT%ú*H€­ /âh•`ÂM#¾Ö@_DP!p"À¹SË£è*€.¡8áZcÐu¨úîT_YoRŒP¥æQŒÐIÝT u-2W·$ÀHZ÷¦¨*Ò™pÜ S‡[|áÙÿ')ЬõÛ®õ1_ª´>ë Ôú24ÄÂyçŽ(ââ¼xÉj©%è…›<zq`, —oÐÂzתXïò²ë=·ô6°Þsî?Xï9‚X¬÷BB,Ћ˜@0Ýè}ÿ¾ }ïC‹@‚Þû½ Èî[—ÞBªza>‹»ôÞ)³Äzï‰ÌAb½ðÂ<¿7 é¿h§´KÂÞØ`m!Ø{§ŒK{îa/ö¨ð7ì½ßrͰ÷~ÿr-Ÿé|[`ïýö%’ö"Sà¯V¦ñ핞.ôEòÚ"ë…‹.„5°^¼Þ'¤¿Z™ÞØòþj¬÷¼Ü'“õžÉÓ{ùûÉÍÉþ~ÜÛÛßñ!ìï÷`ѱ¿ßù²;ô÷»vÚŸÒßïBêûû]8:‘»ß…Pèr÷“«¨Üý\w¿ïqŸÕÝO‘»ßyá •»_àQ5Ôû–,šŸÒÝÖ³ó¨ÜýbåûÕP/BŽÔhÉÛï{ûÅHT Ýýºø’ö2– <ášp\´Í¤¿ßqQ?„¿ßN+@Ò^D¦‹Ãß÷ÝÞ/B̕ʓ¸wN¾kĽsÀ WÇISSОê‰ö"°^if€½ˆ 3/¦.ì…áMpž"ê ö¢pK8™¬%…Ûd½hfA½3>ŸeÐI¿oJÀ³×Ä€ôÂÓùí"ß+Éâðç‘!êùW#êE3ðêµvèð8·:üé!êÅðZPïŒã¿é];Íßåïwl$O^43‹ÏsÐ"Yþ~ñQ\D¾ø¥f÷÷ÓEb=9-Êßo§›üývö2üâ"ò±€ Õä í{¢ñXD¾¸ B `A ì…Ãvù'ö>ö‚ a/ÚYE¾\ÂJ$£Ã_‘KÃ=»ž÷â*èsÅ{Qð®ŒAIÞ‹’µù#ïÅEµÉ{áºÃ°ÖÕ3|Ù« _”À÷ÀÓJ&€/Ú=þ"„Z=þ6XJøÚU¾ ì´}Æ#Ü ð];Öp_´µÀ矓À(”ñž¡,î@|íæ@¾ˆ¤ZE|Œƒ'à‹+‹Ï õYUÀ{úŠ÷â>%e’÷ÚUà=ÅpïE;0Õï©wĽ¨²îjUí%…{1p{+➯î)„p/†¢oàž‚| ÷U¸×šî)ÒƒpÏ¿q/J®÷r¸(|~·ˆ{Š· ÜkÏ ÜsËĽVÜ;ç D%îEI™÷¢V¡À½ð›­Óâž÷©¿”8Ð^\6øT€6Ñž^?Ò^Xo-æža5Ø s®¹È{a˜µ/ò^|³Þö<å {žt„=¿×„=ÿà„½r’ödÒ'Øcð5±ž\ÕÉz1_Êä—¬CUó¬ç>Yï¬ Åõ~W¬§p·b½`£›‘lö?JyßCu)o".ƒÌ9wZâ)-”Í9ã©`æœ2Ÿ$âÅ,[¤¼ûeôžaMxè·Þs ð.÷S\@^ Ë ¼ˆ^\¶Â ¼“ü,æœ'ù†ñ&=Ðië°.0ãqX— Yg„yÚØœ“qlmÎ ¸~5Ê »Ç£+zßløAyW”­°C ¼¯äÆæ”÷•<Øï2¢^\ÓÍ\޲à…Ä72º¼ÚåµkòòïÙýúZïy½•‚¼¬SÏÈË’§C^–ÀÞ³ ¯×)ÈûJp¤JÊË’sñë‹’§SÞÒ4ˆå] ò¾’—b\Q^–@*,Êëu’ò²²_Q^¯’”·äetªMÖœý6EyY²Xsö’¼â ˜—T"?8/ë@D+ÎË’úØó®1&å¹â¼ÞrqÞR’ëQo¹@/KÞzí1Azýª"½~U’^ï`¡^«R¨·ÌJá’B½Ö P¯Ý¨×ž ¨—cQ.@½^R¨×ïU¨×ïU¬×K~²Ý½X¯·S¬×¯*ÖË»?õ\¬× Šõüƒ‚õü d½^åbÀ4•Üp™÷U7\æÇ\…½o¢mkl—Þã—ùVB—yµS¬×JÀzí*°^¯S¬—w¯x`½^R¬×¯JÖ[ ^LX•$ëõ‚b½^ò±^¿M±^,°^/)léT¬×šëµ–ÁzmˆÁzýªb½~U±^–ÀQ°X¯·S¬×Û)Öëíëõ:Åz½d½^¥X¯7“°—¥¦쵂‚½v `¯Ý°×K özIÁ^o±Z[IÁ^Ð^ëÎËÅUìõ[ .®*™\\Ù0`¯Õ)Øë;WWÜ»Xïû{‡9,X¯_sruÕ.®®*¹¹ºªäÙ4YYÂÕU-¿\]u÷ÁÕU%Åz½‰ÕU%`½^R¬×KŽM“õ„¿VW×)Ökwëe ¬BïZ^}ÑåÕ%Oa°^ÿ÷««KVW—L¬®ê h¯u´ç[öZA±^oåÄÚêVN¬­.)Öë%7ÖÖ c ^/HÔëwzkeu#+«Kf­¬jdbaU ž«ô²àíŽ}¾èoä#2ƉrçÀó®õ]ó¹aV#¿¾xí/–ˆ£Gwù^:ÆW_^$ñÛ<ýà×·rƒ{ò^±=ÉÁöEꋳÌÜ厨åuÎO´FÃàž“F|ä@Eª~ßÊòúnô)Œž¬ø}v¶Å«ï¾=G±~u ¼‘RÁ¸]ÃÃg’Ç¢õé$I¨ãZa …b Ý3Œ?­/®ô _£0p2Ú(00>•+>È% ¼-)‰T¿a`4Ÿ9``d¾yµ/òå â&0ð~ y£*„î|ï¥ ì§]‹Yg (ªÈžÅ6Eö”3#{†)´?(}o¼[ècØ< }ƒ©Àž¿ƒRúæ…×U‘=·s@ÇMl‘=9šî);O÷¤=&µ>Å_elÏí$'Qê“t.©O#¡Øž â'©/ÏÞ‹ÔÆö õŇz1êŒþnÿz3 í©@ž”ú¾õäìø×ÆRŸâNZêc\D)}ƒPú"JoUQéÓð9²'}<Ù“QÙ“i=²çYXÉÈž·x‘=AP‘=·‘J_Ük®Jßw‡:É–Ò§.+´§Ë¡=áNa¥O±¥ô'ô í©ç‚Òç`©RúÀ’J¾¨-´ç‰“ì í©À™úöò/µÎ·Ñ;R‘=ã´ê0²§~é|c§§Èž´!UdÏð^/[JFöTÜIé|Œ°lÏW)´'Õ:´'CF:´§zÈОz)Ú“f± í9‘ÈM±=ÌPÁ=™I2¸§cg2¸ç|~˜vf—jGÁ=çJŽYíàž“ÖÉ îÉ Ë-º§ât*ºç-cOF÷¤³£{ª?Œî9a¸íèžüd+º'¾d’ú<© õÅè\,;õmkÑ=9§ÝS3HÑ=ÌUÁ=iKäàžnFÁ=ù¦;¸'ŸRÁ=ý” î©è¸ î©Ï€‚{ê·RpOE¤upOØe+¶çóSèÓ÷Y±=5CÛSý«ØžŠëØžœ¿ŠíÉx¯ íÉ5É¡=¯Ý¡=#¡Ù/³_]x㈨Ú³¢K<7Ÿbæn#¯JDú†ï*ÞG°÷»]b ßz:®¼³|ýkpÞã-Þqà-}Ï+x#š|v®ö“¿‘) `Ðs¿‘¬j-©S ç¾ßÊ«ú• <Ã[îLaÔ­â0*o¾áeϘòùvÓ÷ˆã¨Áà+™ðn¡v¦#ΣF=gþ #BwœýÕq…*¹AÿJfM؉<÷¸2¾Û$ ßû—QÎúUáOU¶ßߣækœ„çh0´_.)7¥ö‹§v“±žÂÅ;MpžzÊ<¸#œ}ÎWÞiî'¦ë¬ãé{~ªœ®1ø(5]pëªórºÞ³ˆâŽhg¬ãˆw+w²_ɨÙzÃ~ì†Ô~»ùž5[Ãn.|~ïxÎÖø^U2Ò÷³­nõQlÎÖ§¾µßìÍ_ –þOÄ.¿îz!ò³õdLï½M…Qȳd«FΣüígòÉ0ÏO½Ž[]u½5Yo˜²}÷»&kä¿Í‚稹ʟò[7ÌU¼ŸÏV™º0äÏï÷Á®VçQ58T_欉ªg ¯åœ¨7l &~_ŸX"Ž{©“‚‘Úg¯œ%9|‰ÏdýË~Ÿ¾£æ)ßÅ'š»ñ“ÜUò<5OÝÊ{Õ<õÆ^ó”ïÃëJÎS¾Ï>Ÿš§\ƒžc»jžÆ™ásžjp޽VVNY¼dV;g­¬œãª•5ú\¿B†DÔóžãΕµ5ó`eå,xka½ïßuÅËuU½XW剙ÏÓ_ÙsúzCGúJ¸®"ÚËsî¹® —qîs¹®f œ\!ŸóĺzõõþJÒ=¢—\XW¿•?¿…O¸Íp¦ÖÍŸ ½ÝÉOËW‚eUq¾XVC ¬«âXeöøœXWï]ž£7~V9UãË‘ׇœªÜ—<á{“Sõûur?ñ¤ÛWîB^̨ëĺúý=Óua]=a/úÄivNÕpæ¬vn¬«ß»QïhäGɹ!ò³àÍØ½YP_…8g©eßKB¼73OéÜ@u|ÿ¤bpÕÆéB –ÕœnQ°cUõEG­ª‘£ªœXU#¢ð^%µªúš «ªš½±¨2æ*hÅXƒ”õ•`QPíUòbQõ½ÕÙ½ž°mÎÉznµ–|%XTHYOçdU°«Þ3¬~òçÀªª>G­ªîÏsbUUž «*ã%=Ï]«j+À²z!äïó<µ¬rpž«*ïg`QÕ‹ô ,ª²á=ÏÄ¢ª_!¼}s²r[ü¼;VÕˆH<««*·àÏ{`U½à³øõæ¬É!üslÞ Ëê ‘ñ+Á²ª1~k5j/öû`YU._‹÷ŲzÀ”ü+5[ÝÎÀº±¼s¸ÞŠ‘glµ°Æj•BÁ“Î9\¥¢~Ãw+âTýN™½Uêm'ÖU]tbY½àä]§ï/%u}"¿OMU$lÕF´rÓ/ýßÉNd ,­¤Q`ŒIúŠcL ßH±¹Ü ŒÍåU ÷.ÄŽƒà ¼â¡k ¼bçX[;`à•zm!^aà;G0^a MwWȵõwQ í¹A¶"°2)ðŠma1(ð+¹Ê<…˜ÚªPà nñ(ðš%ø˜¿’‰á~í 1_®V½NQà× ì#HßU“-fÚrƒmnD Ì$KÅ, ÀÌÕTPxÅö²øUÁª—øµAZ~—ì$³¢À¯D¢ÀÈ©v, Œ} TjR`h⳪€•TIÛø ÌW –ò+ˆ[ÿ@Ñ›â9R`œ·Üb @%ðÆ“1‘#ÝQý6ÄÀPöO@_-XÑç¢R`àæ5©‰ÊS$ Œçª·¨œ8â@Æþ'*¹•00á^0P9…„1Èu¦E Tq`Ô©©GŒvŠÄ€¾91P™u„ r 2ëˆå&Tj"q Rˆ‰#°¯8P¹ÄL8RÝ}Œ& SÈÊe$Œß •Qq`¤ç"õÕz¥t-âÀèK­iäÀJô$ Tv)Q`üEQ¤@Š•þJ ¨¤YA¥Dºe‚ ² 5âAeGÆûtT®%‘ æ¡H0î”ü.ô““#ÉÊ÷íH’öÔ *Œ§š…· Áøñ ´‚~(‚ «€•)CèW€¨,Iâ@?9P ·È~(r ÒóãEÚë ó> ·”*Å”@0î4‹¡‚þ¥‚qŠ]u‚~ìA¿Á¸û½€`»@°Ý $¨1&¶.ýVýS5› =zA%ÿÆUŒôÉJœ%Tw‰íNÀ@w…¨¼hÂ@¿Žä@¥+zzý¢“õÝê¥ FAê³ ôˆÛ‰°9Ä@ÿÚÄ@¿æäÀ˜tu¸AŒßÿX8Poq Rž‰[wÀî00Pé„þˆž Ä@1Ðó¨Q ¼áb)0öÛoã‘H'¥^JЇ')0ÚàA uÜ;wÂm@oM@'·Ô¢=© ²ÕA¼l@uÎ-ÐñxmËr „À=…ò– (ÃÍ‹÷Œš…{± Ù¡‒)Ä{q $:š€23ŒM@™µÂ& ûIÓMš€îð7² (SfÙ”¹Ã„|±É®g (­l¿¤>˜€¢Ã´ÿ„¸lóÏS²c!K_<5Ì++Œ;ò†ù$ ùt21–ˆOIólüÉt_6þdæ?2Õ‰‰o‡ïª‰Oã-ãÏÞÀ&>¦Ð1ñ1Ç‹?÷¦”D>fÄòÅ&"e?ÆØòmðé4ò1‡Œ?7øMù¶“pIäcv2õŽe¿@‹%)û1G’‘oÛhµIä‹•wA>åo°ìÇT–ý˜|òSEØúóziDJÙïF¡U¿X"êª~‚—[õ{wØëHõ‹EóWc>%²èçê~ïFz£îF¤(î<±0_´÷C÷ Kí…ùÜŽt¿Ø¿‰Q÷ÓƒJ÷‹m]iƒÐýž X£ì÷lØPö{vЇ”ýø>Xö{[Û²ß×e¿Ø AäƒìP0IÙO)Ù/(p1’úe¤û©?þbc[èEáïÙ©µQøc "ì[øsËþ4þbCZÝð÷ThHë~* îœP’#u?½Òý46Òý\BÝ/^·ºŠºßCú•î&ô%ÆQ÷ã³îÇIeÝÏ%Ôý¸[°ðGG ~ .¡ðG‡±!.¬¢ð§·XÂßsPŽ£ò§×MÊŸ¾Rþ¾×ä^¥?—Púk%þôkJú‹ƒ‰UúÓ+)éO/»¤?½'’þ>æª/¤¿0-H¢ö'cUBí/öõ%®Aü‹C›Rä(þ…mn1Ä¿{ü^µ?=¦´¿pB/†£öëJ°¶Þ/“Ú7¢Öþî‡ÒþâQWQüÓçMâŸÚ‘øÇuÓâßõÀ“ÚŸNá¤ýéTÃÔþtsj7Ž÷­ýù"h>i×IĤöw!°µ?_EíO¿¦´¿kä¤ýÁŒÏÚŸPÚß]ú‚¥?Ý\Òß÷ëÕ'éï†5 ¥¿kâPÒŸKÒ_+ô§ßAÒŸK&L~J´$‘ô÷u¯Þ}Ißso«ô÷}rë#éïBšKºµ¥¿çÿ5ÁPÒ”å?IOd‰oŸ•ŸÈ̇iD¾´dšùÒ^«6ÃRøÂ5ð×?›À§½0‘Ï;Ý®ðÕNW Ÿ|£¤ðmˆfaä‰Iáãñ<¾“f™Rø´Ÿ—×ýؤð…ÎVQâûºY¥vÔÍë¨+â“"⓺(â‹i»:ý¼|<}0ðÉ—KÀ÷]´¯À'÷$1¿†>©„>;ÃÑç/x桯±¡/^¾ª è6êƒVبo‘ù” ÖÐǼ„†>&Rô#\‹ÇŸp^¦žÌŽ&æó\¦žïC£HšzÊ„U¦žØù4šB>®È²ôä¦Ñ–ž\§déy#¸-=Ý.-=ãLºJhéÉ¥ËÈǯ‹‘ï¢:/KO®¶ôü:q­È¾‹¿ß&{d!Ÿëœ?lRŒ|´ó2òѰÆÈG[ !¿¼F¾˜¿ñÑ$ÅÄÇœ×&>~~|ºHÀÇ…ÞÀw!F€ÖC>uOÀ§1ðѶÎÀç«|42ñù*Í9L|´ôñ#oè Œ¢³„>™øúd Jæód¾^‹ É|ZLÄ|²5ôÉpÉ–ž4—ôñµiÆž“v¦„>™ úd6'èsdì9¨’údNdcÏI#ô©‡„>=º¨O%cOÈØ“FR6öäS‰údkcOš`ŠúÜ{ª„Ô§[{²eQŸÌ)eíI‹(AŸ,´lí©Y{Ò,ÉÖždBŸL¿líIƒ(BŸÛ•µ' —lî©veîÉ«„}6¸”¹'‡rŸv&’ûdëÞÌ=9€6÷äö¹Dæž|u„}SÛ{ª„Ø'“@Û{òÅöù¹ær#aŸ*ØÞ“ݳÁ'›µÁ'aŸŒàlñ)3QbŸ†ÝŸ4¯³Å',[|ÊrTŸê¡,>ù¶Ûâ“-Ûâ“/†M>y/›|ò^²ù¤I¥L>u M>eàÙL>q#™|Ò¸½›|ÂeO&Ÿj‡Ø§ŸÆ&Ÿ´X´É§¬VeóÉ k›OYPÊæ“WÙæS6•²ù¤qŸm>1ñmò©†iòÉgè&Ÿs5ùÔ5ľã$+ûèÞÐL> ¤™|ÒúUØ'DöÑ¯ÃØGßc+Ì}.!÷E0–_ûŽÊ…iê“y»¨OvÔ¢¾VBƒOZùÚà“Ï êCÜŠF};$j|nЛmð©RŸ=QŸÞ?Q_l¼‹ I}&LR½LL}ß¿xKT´(|Ûâß1Rï%ÊËÜïQ^ÂQ ’q_-ñž<-Í{´dïÅGñ]¼Däç’CÈ{}°tò^D¼‰O‰: |çó0¨ €/;£;|‘­íøèZÀwE2 *ŸÒ ø"TÝjÖ©ìa"¾E}/_DJÜ«ħˆÙB¾x8ïù"I(úä‹ ªWÁïº)ù"Ûd1 ˆ/º\¼â‹kÎEç‹5£Ô…D¾àk‰ò‚W¡!ߵѾ‘ȧL`B¾óÙ)Çù"<ø³}çM…Ìwî”?É|GH*Õ=0_ì$n L;ÇäCúÚU€¾#6˜…b4í|B_aßê; C²íd®2Rßq Å@}ǃ¼Ô²í¼‚õE bÅ€úŽ8ûÕ ï¸!£ú"*ê¹è|‘¶­†Ðµtæ«E)®‚q% /¶PþhÚyIŸô…1ò¹è|ñœwwïû®Ú~˜vÆp®ó}‰ŒÉ|YP/˜¯—$ôe úz•‚¾ôÐݺqg–ÔÏêë%E}í*P_¯SÔ×ëõeI=8¨¯—Ôìíõ5aP_/)êëWõõ–“úò¢£K}.Iê‹?ùìºLæËúPþŠù²¤;÷õ& ùÜW"_/)äë òõv ùzB¾\bj—äK¿é³#_ÖÙ»Ÿ» âkU¦2J:ðµ{ðõ‚¾Ö™>/€¾~£¾v£â½~Qñ^/^Y뢅U–36OE{m`@{¾´×nÚkÚë íµf öúE {ýš‚½^ò–Û¼yé5¯F½æõ^ój¬×®ëõ:”øôHâÓO Ösw€zmh€z½áNó¾y¡^¿êÓ¼K^8Íï} õzË^óîòýO ^{ žßq^/x5O¯®ïõv/øÌ»ä†Ï<¿2=ez½NÞRŸy~…ÍU_j‚^»  çï)Aï+A°^‚^–\ ô²àט©.™5S7Jô®ˆ©?ºeg¿S‘ÞR21U7p)Òë-éõ’"½~U‘^Þ½N“@zYR¶Ò ½ÖCÞRŸù {’^oùªê–ïZU[VU7üÔªê*/WU>P¯=P¯÷fbUUo€zö‘¾|XU’¨÷•¼¿»}g+(ÐË‚£ |K ÖÔ„êªB½,ݾó+¹(ù½XS¿’: ê}%HKLÔë%ó¬? zK ÖU—ìXW]r`aýn½u/ë¼ðöÃÂê:V×¹±°ê¡èTuþFª¢ðsƯûÃØóX=™žÏ(x?{Ž›A[(ý…ã „>PÒôÂÒ_¤&ê¡^šeœ¤?šÛ¹2™}ûèXDé¶Þ–þ¦,M!ýÅNúWÁXGá/ܰ|Eá>p“ŸFJù“'™Üû¶á5©üÉ™Gî};ƒjȽï8©Ò¿Ïý¡ŸœËäßwÔQÝûŽ{µö<Ž“ö¡pð;¨‘Hø›à¶”?ºÎØÃ/>…T öI§F)t ²‡ŸC„RúHèkéOÁIÿ‹`Ÿ/)Ú~,eï©@™²÷Œ|KÕCÚ{:t¦‚}>t¡k.~pè“‹ìSž‚tñã\°‹ß³†yi®ƒ-Ø'ä@ûTûT0Rºø½å@ºø½ˆt`{OõXöžò8”‹#9:ØgXEýj踓òð vAÜ8#ĹØêáwÜÔéá§ 9øEŠŽº=üôtñ‹lgÕ}üƒÿÈÇóY.~rU¬O¸0ÙÅïxÛäâ§·M>~ ?+?—ÐÇ/lO— /ñPpΣ“Ÿz,'¿q2^ ü4rò‹t0ûRN~rcV°ON"8ùñ=²“ŸÒN~ Ok'?>ü8vò‹O<Ð |&;ùqlìäç{ÑÉxíäÇWËá>åí$'?ß‹N~ ;ù1 °üÆNýN~ô–“;ù!` <üï×~\ìᧇ”‹?.vñs;tñãÄ´‹_d&/¤‹cEÛÅOuäâg§9ºøñCa¿˜I‹¹§T.~ü°ÚÇÏ%ðñãÔl>~s:ùùNôòÓXØÍO.7?•ÈÍOÎlòó‹~rùøù6ôñÓCÊÇÏÝM?z*ÙÇïx)ÊÑÇï]üôÆÈÁO•‡_+Á‚ª¾ÉÃÏ,?ý°rðãoß2½‘ìpÉ‚1"_Oƒ‚žoè/¯r%VùÏÒ½±Óý.q: –9ˆKœhdFÖ¥³*q[,s[.imÅáÁ½<7 ZKUÔbÁwŠ¢76c1&ÿVŠ¢žŒèŽoþ«d.÷£ øÏ¬;•·è¿ªZiD¥ùãkòÞÁcIêòã…‹ñŠÍûR‡-95[ꩉВ+¡¥^G-15‘rj"¶Ã*lÆ5ÔŠÒ©™––ˆí¨juÔ’’©¥–”ˆ-©[juÔ’R©¥–’ˆ-©[úÒE’رÝÿ§-ú7>ŸÿøÃ§ðO¾–ÿøÓ¹òó ú§så-ýí”EoœŽ}ËÖÿÉ”Eߣ¥,úþú³”E_ñ×F„ÿ~ßÿ1\è”EÏ¿NYôFðP'Æ›.ií#4×âÊÅêÜJxšä$Û©NÌ·Ž@ÞH†fhŒ¼ûFë·ÙU½÷·Ò—ξ‚÷7Õå÷çéCð«ªþ²Gç{Ç©ÚýËŽ”_I|Û5ê}êx:}Õó°òý µŒÐb«0ª$wmi§žÖYïsäR¡¿­ÏUæ9tÙ}?L(4ZÍ%¹¦ûr:¿Ïý®n½ïó\eƒFCú÷Û«ýÎC† zÁW2áŽÇã÷Û—”ZðR•ÌŒ•©`Rwø¶b{íI7ˆe_Éü ì< xßý)+4zè~s#Òfÿ²Ù÷ÜkGêk¾•}ïžÒï{=0ò~K {¿ß;ލÒÉ š}’íuð•ŒÚ~ƒWØçhU2ã7–è‘UàQò†MUîI·YgU_ɨ=©[†µ¶wõ;¾—.7¥;²Ò¾ãØkSÚJ2ÁG{ª‘;Ì ¹ƒß©Ò½Îéß66Œç³ OA¿‚´œ¾ã\$»;ž»,Ðè–ðítÎÚ•j8G }hð†°§Ïƃù4æ  ¨CoÈÛòf…–”èݪND½ý!çq—Á¨ÞµX¸ÕŸyåž:ë­«*I}ëá¼ïšªL;ô†Sè“Ê’^›ÉM^ø{Ýë›pð¹«Ëã®ÉJŒ÷[š~ç5Õ•9á×þ Þ‚Ç}«y9"*dÎÔùÖ±ÅÈHԘͳ®*ÛÃl'ßÏÆ¥ÇÑ~Þþn9Uãÿ͒ﵟK{=rbŽðÝ­© ©v„'ø2UG|CæÕ> #<øÏµÎ|-c/$ßüîu#FÿE•£ªì3§êD8ý•ö¢³2ÎŽˆ—æ¢ql]×\{MÕP¤ªÎw‡mÿå°#s¾<õ–ä's„¯Ó„“~žÉÀåóm“lCcéßxÊ^4 !«y–Áè7ÈÙãPmöþñûJFÙ‹êw8Jë¿‘(¹àŒcn5Yë”5K°ÿæcŸÛ]ÆÝ ž0Î=Ó{äÍók8Îc«¹ª.Ÿe|–%œcœeqì0ã¼°ª†Zv0¬¾R|%oÎÕÖòƒ…U]NcÑ>:çÀÂêŽZXbœ «úÆ™@ä©ÞWÂ…•xíXXÕpØ“ÖÊŠ<ß§+«~aàe{)®+}íòîù•וUom˜t¦çN|²«Î“Zéž^3äz±²Öâ%+ëxÊŽ}DêèqõWåš¹²z0î +«ùÞ±²òšûØ0.í_ÉÄ|½Ë&tÜ'–V×}]˜¯ìß}×ÚNîõ!¸ïZ[ctr™÷ƒµ•šq¿µ¸†s^Ý*N£à†U?Ö=¼ðYeriÅaÙx¶ *à,-ãÙkiõoõìµ´úÉŸ#ÓÒdÿò~ÎQ3øS=é™–5ÞjåªÅÕOðÜX]õö?ω |mŸ·V×(ÙP20a±ýÏÀêªwé)ÑÖäx÷¡y3D£7¡Ú3¿±K®‚«ZŶ rÉË%¡×Ö/}×%±C^zñlŒFòÔß¹ ÆˆT/^ŒÏ¬¹˜züv ¿ãûóe§«#vƽ#v¿Ëd¤ó/ûå‘î«Þ?Ž×LÝ4ŒÞ«£^™ÏLßå~û8ŒØ÷·eħõ—wçcäùcΛúºñüËMg­žz+ç¶s,s—8¬æèoAf“é¯N[Þû»žÁ·–KN8¸õglƒ9ŒÎ·k;Ï¥ðÃÔ£2_v~˜úÍyã‚X_ûðñ܆A/þÝDDb»wæApc»8n·íâĵö™d»8qíhwźvÿ@»+$ììÈv_É cÁ]ÚÁÔÎp÷}lDpg¯ ÂÝ5.XWî®8Ç=‹Á î¾xî¾xÜî®xgQYÁS ‘î®ï«]O ¸Ë ÜG‡»,)ÔÜ]!Â?URp÷•\µ?$Ü}%°î&ÜeIí‹wÙN à.32]Å\w_‰˜+á®ÜåEuM²]¯Qpw%¸œ¿ wY§Ž¢wŽFN¸Ë:O]Ut—í¼jEw½¤è.K¶Žw_ B]ï²å‚Ä¢»VtçÜT¤»^§è.KŠçAw½ä|–KêË~ÅqÿÞè.«ÌB·¢»,yë¢Â»üuϺ¨ð®7Sx·”ä<É `á]»ð.ëä·™x—%£X©ð®µ¼Ë!®¼ëu ïœÉ‹x×K ïúÝ ïz»ޟĻ^Px׆§ð®ý <÷„ç;‘ðz"¼¬s¢dÖthOEoExSžt^^5ê^Ex½"¼ÞŸ"¼ÞŸ"¼^§¯÷°¯•áùC@Âk áµÞ€ðzI!^o·¯×)ÄkÏ Äë%…xþmˆx½N!ÞW‚@D¼^Rˆ×îÆkí€ñzb¼^RŒ—ó¼àñ8÷>6`¼~I2^/(Æk¿ o)˜±ºª/Ÿé¨’b¼66`¼~U1^kמç)BÈëu,¯j×K.¬¯zuyí-äµ_ç/ ¯) ¯?ĨÖ=žX`Õ@^@^k×úÈkOÈk÷¢ÒØêäõ:7VX—<\a¹1äe‚/WX,O„¼þy^°y­@^»¨ ¯W9¸ÄbA%äõ‹N,±úey^kyþ¶ò¼xòúÝßK,)/—ó·ú3~¬±Ä¼VÌkýæµ»óz¼^çÄ2ë–/,³÷ÊyÚóÚoÌë%/VY20¯20¯÷¦R0ú¢Â¼ÜÖYb`ž÷KÀ¼~AbžwBÀ¼¥ 0ÏOS”×+$åi“ÈkR”ׯxûðåµ·4(¯5——ש\A^ûvä-3»Ìí1 /kl ò¼äù®Åx¹ò1^{¦b¼^Œ×¾öÅxÙÂÞ¯wsÖúË:n¯^ñ’bJ à](K/b·U¼ð¤.¥‚çG ‚ÇT!RðB+²–‚‹CimTðx+ xÌ/Aã¬ß1¼ô;¦â±~®áðš„*OïÇ*àéצ€G§éw. |‡”ÓVï"–VUz¡”w©wú±¥ÞE©U½c&z©w{Ü¡´:ªwõdUïžNâ]Œrõâ¾ïö§ÒïŸÎúÃýI¿Û#õ]ô;ÞÚò]8ÕÊQ¾‹|hîî ¦(whžB¬“|wWðËwŒG(ù.>-µI |§Ðñ’ïâªÊwî!å; oïôY£|gä;ï“|·;ÎF)ß)³ºä»P q'ÈwÊg/ùN’®ä»ø9k£|×®‚|çǤ|þC­+ý.ç…¢7 µÏú„J¿óO#ýNOéwÒ ©ßIk§~®/¥R¿“3Œô;½ÒïZèwQRÛ!êw´T|Ý­6å;-cÒïÜ õ;ßœú)éwñYÛýÎ?Œô; !Ôïâ*úƒ|•$Dù®5óbUPy)ßÅ«T§ÿïü>R¾óïDù.V…%XUÕ0å;}L$ßiI—|§ü’ï”C@òŒ$ßù©$ß…'Oµ ùÎ?ä»ï‹{-ò]“0Çø~2Çd<8›c2îÌ1Ïæ˜ÌnsL†5´9æ)U0·!Ï£í1¯U±sè^›c2¶¹Í1Üæ˜”¸Es 4ksLF\µ9¦‚昪Cšó½@sQP¼,sLÆ)—9¦«€æZ» ¹xªÂÙc†)`QhNÁá…s Õ+œ‹’­Jh©''Ï1N¾pNÁá…svd2>¢pNÚ¹pÎo$y.Þȧ@ëD a˜Iè-—@§8³:–,2Ö±î S„b‚÷ èüÓÉ"“QŒm‘‰Ê":EÕÒùV2ÈÔ$#Ò)ê¨N!P…tíæ4ÈdØJ!]„L¤>WH§À©dºÖ(vá]§ `:ÅÓÑJ[H§)n“L†¤´I&AL×JÀt 1j“Ìà¡.ص›éZ3@º­" ü³Yd2¹º-2™Í™Œ«i‹LÎh!]¸V–¹%-2üU™Ìôn‹L·B“LÝ[&™êŸL2ÊÒ&™û ‘&M2?Ô&™Œ«i“LÆ¢µI¦Kh’É ™¶ÉÔÝe“éÚdž[þ ±.ìýë—* c¥Çm/éq:”GoDëqtާYêq]³hŽz=T-ÈÑÒ‚“­ÇéÖÔã¾OÇ\ÜéâÞ?ô8÷†zœ»C=Žž®Öã¤AØŸnÐÁrœ«ݨÛZŽC .ªqH¹l5Îm@£*nx›jx›ƒ¾sTãtº,5Nã x“ë¡ä8yav9nvKË&‘QÓi®Ø®‘B·‰¸­F7ù`JŒcêM³›Ü±Änq‰qr%º1¡·ÑSUbœNâ…nßÿ×k$t“O£Øm"Ò¾Å8„´8•ÐÙÆÍnò#•§G»ÉAPZþÌnšcÖâZ};©ŸU‡ìƆèF !£ÛDØ[¡[­Ë¿Inr¹13¢É¿“À-¾+¸13vó£{ñÜ&âךÝôØ’ââÕ¨úÑÑ·Hè&`¡[Å{úgC7=·ÐYna¡›s‰nr}»Io»iúŠÝܲ2Ý4W…nr–#Ýó»XfrÖú(ü…L´DnsIn’ß‚›ÜÁ n_…½X¶ñ ¸é9 ÜôÓÜøàÅmþ«°MΡÄ6zæ ÛèìHŽÉ\íDÇ׃ÔVÁìþijÓ¤%µé5,j“5©MsšÔæ 6¹·‘Ú¾w½Ëpú-Èlú-ÈlZHm_ ïm®h“‡p©p ¹ÐÑ%‘Ц_ÐÆá'³é×"³©MbÓØ’ؘà»åò1©U¢ç%à}lHj±ÄÌ*Z„ÞR»jwÕHíÚy†OR»b€×\’ÚyÒTޤK¢›©„f‘Z””üR‹E²´*Ú¹Aá©E‚:ÍÕÒ‰^ 7HjçË#¡šÒºÕŽ«£P-7 ‹âÁ/kgMT‹ š< ƒE‹ÔbïR¢Qí8)þÕ"8óÞ]ä¾:–àrm‰fJX$¬¹ÀZDt®Àµˆ} ¤Ö–ã”*\ku€k‘Õå^ Äfw‘ëݯñƒ/PŽ¢&y­5 ^SâZd‹Çpí8%q×¢™{ÊZ[âÁdk -\;œÝ‘Ø"b6ÀŠÄ‹Æ¯l±Ôäˆl¡í®ÈÆôáf6Œ4 J©Ê‚’cÝ€rv߸fõ&J[GÊ‚ò¥Ø' JZØÉ‚’†q² d¤$A›:#Ê Â˜M gÊí÷d›«g\VÙ ®Ñ~’Vp²ŸŒ¸¨u•˜±’d?)sg1[Ó­‚¿2Ÿ”W‡Í'eGfûIž‚È~r#Ñ~ÒÖ‘°Ÿ´Q£ (ež(J5CJõÆÔ6F?ÑAƒ (ycjSR›‚2‰Ú­Aئ¼±íø©¸‰Ómª£ø'ÜõÛ¹Æ6d»3¶Müž€˜µ1¬¡Mˆ¶ýW$h®8ú cÎÚb÷ºPÛ{ Ô†|¢¶g0r °MC©è'Œs¡è'Dr›‚g(ú ƒ›0øÉ±íû¿³…?QP…?y¨Ø%·¹× ‚à6Š~Âh<ä¶oT›_\F¬9'nCŠG?a¸#?¹ˆi ~¢Kn\ð,ÜÆT÷~"£MpÛsâ±ÈmÏÁ&¸}?Ç»¨mº„ä¦P0$7€Üb/9 äî§Ðßfy’[ìºýdl&b¹…ã0ô·B·gâFts`·ð3\‚ŸðdEì†øz#9m)¿oX‰Çåd4¤dÖYǵ<˜ZÁOæEÏ?™7ý¤üdÞÐeûd†Ofµ‚Ø'3N`ëNû$v‘(®\³çƒgì“Ühv î+¹0“±OfÆûüe°Kß?8¢!ö‰ûËØ'sìÔÎü$v¬¥ª0øÉÏjJ™†¨g»+’j]ƒ[J*øI+Að“HàQg?™1u» ÷]…Àî ~2cƒ»?‰*o~UÞnJù•œ &‰è'±í.¤1ÚåUì²àî–”­ bŸÄë[DÃØ'3Îa7Y±O¢ä€me9fˉ:kì cŸÄ€"’bŸÌ¬;Š}ÒÚA쓸W0öI”t²Ë‚:¨aè“xCáç†Ð'­ËúÄoŸ )o*¯}ÒZAè“è043„>É\)[}/ñ í­BŸÄ­¶nI™-ײÄÐ'êŸBŸhF+ô‰†B¡O¢%òIk‘ObÒ?]ŒóDTä“’®ÅyDød>‚4>ñøD£¥À'~n>‘ở¸3 |¢¯‹Ÿ´vø$ÆæF˜“ |¢¯¦Ÿ´«øÄ¿ Ÿøî |wß–À'þeøD£.SÊØu8î‰G‚qO|E…=im"ì‰>} {âÞ2쉦¸Âžø`Ø“™c {ÒZFØÿt {âß›aOâµÁ#žø©ö¤• ìIk™¦”“+0ì‰_†=á„VÔ“V¥¢žÄÝ7®ýºˆzÒ:ƒ¨'®Â¨'ú+ê‰2¸+ꉾ@Šz2#œvœ\Y96 zâß“AOô±Sн²¤¼a¯ ˜'­Çˆy÷W"æIk1O<èˆyUÀRˆy¢5’1OüÙbÌ“ØÎ ’äá…u_bž´’‹ +IÅ<ñbÌ(cž´»¿\ZùT2¦|njŠƒK«®BÌ?(cžÄªo¹K+¾óŠyâßœ1OüŒyÒêTÌóD+°‚ž´’‡Ë+‹AOü3èI«ƒ '­;ôĽAÐN=ñï‚ 'r=i5*艿—z¢£ž´6*ê‰aOâk¾7¼ón¢ÂžøCÜ“x›_á]ûiøÄ ð‰Dà?Í)¹ódà“vI>ñ»À'­FE>ñðfä?'"ŸhÏÉÈ'­…Š|â "Ÿx4ù$^Ì­^ë"Ÿx4ùÄ·Eäw ‘Oü•=åóUD>i-Tä“Ö dœÇ®—O<£ø¤Ý³"ŸhÌÈ'­FE> ‡”Qæ”ʾ3Ÿ8¯mé¾mÄ™¿—ÒG°¤çÑùËË\ Uþ³ì;û‡ˆW¿Jœç†eNkágºÙ·È0z,m±¤·Ue½-–´¶¾m×Ò+üÝÚÉ’Ö þþïμ6º±jÿYâ™Lç¹þýÄ;Ïø2ïüá ù˜{o‰‹j¬Öw-_£#¿'­ZrN´Ôsê°%WbK½[bV6ä¬:j‡UÔŒë°åÔa3-§ŽÚQ%5Ôj±%åÔaK-§ŽZR%µÔj±%åÔaK-§ŽZR%µôdÞ™wmOþ4ñÎó_%ÞùÃûò‰wþªÞÏÄ;ÿª½Ÿoúê­‰wþüuþcâãËùŸÁ?ûNþãϦÊOç_L•?´ô·ïÌ7ØýiÞo þ_ÿçÿ£48ÿ*ïÎ’3çÿÏãÛv~xýïåÝyþ¬ÿõæÝù¶ L–þºþÍý®ÏõW‹ï‰à6óÉcìo½¾JóýßZž_$éþ6ãûoœ&åÙåW€õ™ïVç¯tŸï^ç¯ßçþûk¬Î_Ã(õ¨¹;ä.k¾çSn183ïuþîn}ó½á€¶×¿ؽá¾MByú‚Ð~ÙéÛòm…¼›uÓüAö-Ãì9‚•~%‘¨µ%e;Ê|2_ÉñðM`õˆ ü•\60u¢dVÿ1_É y¿ÞW’±íš·ä u”ŒzDAýJXæ|%¹YÎvÒàÛn{ÕÁo%£žQ=c§øÔ/°ÿ®f"ðœ²ëN,ï—üô£`TÄüJÊý¡,¿¿ãhïôWòÀŸQ2~#ÂDwßû7üÿOÜúûð DÀ…{Ç!Ó/‡ˆ’ÁùxT;Gš§Ùœø+a`üpaxWô‹%ygÄJøþ>K‡ä´ÿJ®ƒ^Æ[õî¸K‰„lÀõŽ}_Éß?fX¸½UpWÿ±Á –y<|À£æÜJŒ<ÿ>Jf}æ¾áç^‚¤[9?HKIj°oçY;Ã}¯‰%³¢rl`žïIj?YÞeYr×ôãG÷+yJ˜d„ˆ(©ILó¯$~äû{\|¶;wz…heÂp«ˆ!¶’'C ©ç #ȳ„¶§z|û²ÎDI)”t9þJÎÚJǯ±¸®Ò(Ãí£zxݵ»nWÝÑ¿ðýŸÌ°×à¹ÞÒ)÷JgðŒš€í¢QBe˜>â¡æÃ:xï K%lľ’½ÖÊvdQR‹e˜¢Îñüx„û¬å2’ü⪴ Q÷îkð î‡û®ókSð~NvÓô~kÉÜN–"ÄþP÷¨UÓ~À–3ûölµn†Ù݃’Q÷Þª•g¯•3šºÓkßû9kùD<š(x<ÂsÕúÉÆWrœ øb=Ïöc„„¨ñÏû¼µ†úÕz¤f|±Ÿ4 Ð?Qã‘yaà1÷ZG#9ü‹’ZH·²3þ ŽZHÝ—æ~=ßëà`*¼—¦!¦ü{×bêwí}j:S©þJÞcíÞ;‰™˜†ïxøxÓÞY ªº±Õ‚êŸ{ BM˜ W,üj „¨ñsØ ì?#„Õ_éÍŽ˜ ¸Ëã^ç倹€ßšñŒ0`0à`ŒZO7á+É€Þµ1Ÿà©çžÛÃ_ã9÷ZO}«yÔ‚ê—bƒ¯ ~»y>Kgæurªb<'"Ôl?bó®5 ¹êÁãøq,Cy™ ,q¶NÕ8#ß—oKìë—¯Mì}ꓟû¸}ÏÿìϽç¬íoh¬ë[«RÕáBßøú\çzù3 ™ûæ÷üÄÍŸƒSµÞ€˜fëÇ0Þc~mpž·eL½Xñ+Ô#ðuŒç^?%{µ]ºzcyLž¸x°Òsmç4|þÝD;„¹8jÛûqRX«e¤þ GÆd¹±‰ÔŠå”–‡,7v˜“åk²ÿ`¹+θëL³X.ù…ßnÐ\ÿ÷¤¹¯àî%Ì)åX.ÿU!Y./p¾•ÞÈÉrý¦³’/ðr­~¡\/Ø/öé­‚D¹^㨸ífP®_r]ìUUH’ëWÜ“˜%Éõ›$ÉõKƱ\$×n‘ ç>äÜ$AÎäÔ 9n©r^ì;¾vvM%³z¯ÏdqÜRç¹Ö¿ßÝã’ã–’ñ,KŽëuŠãz⸥Nr\öK{\œ"¹åªD¹åªÌ ÑþN”[®y*Í‚G¢Pn¹*Qn)I”[®J”[ê$Êõ:…rKÉ~®…i”[jœ•iÁ÷)”ó‹G”Ë:Z¹ßß?Úyn>뼟€%cã¨äýùó^jÏõþÏ-uö—Ï€­RñÜRç<~îTH·Ô¹n>ÃÓ‘n)y¶cü Q`«óÞ|– S`»W&Ai5(Ð%/ò øšbº¥2¡ø}+¨[ê J+¹>ñ éPZûýñ uËUï±ÖxçÏgŸ×ÌëÇ3Ôõ:‰[ ò¢´¤ lí 3J«sÎßÍì(­Î}­#;J/?ža¼ÏÏþóç3ÌýÇÖõ’º¥d?°n-yù5Éë–Þ Q`»fÎý+¬[JöëGÿ É/%óGÿ Nªäo$בL7Æj)07x—C¦;àÊ%™î@lkÉt'RE"ºøXQ,¢›Çó›eL›=tgæp_TktKɬîºB@%”ì èzº˜Ç»tQ©@—{èzËtsGþ ]´©8.®¡\X@×{S@%¯¬K8: èZ]k@/9^>]Ø£@.ÐÅS]] ë=ÐÍ2¯’¹<€®—ÐŽgWè²9€.FkQèz]/) k½ÐEÉ€W@×K èZèÚØèú5tþH€çzgŠçÚc‚çÚkžk/x®•€çZËÉs­3à¹öØà¹^R<×^ð\{MÀs±©†äžëíϵ—<×{\<ׯ‚÷c«“ÆÝð\»<×®ÏÅ{Pµ›cŒ x®ý˜à¹6^à¹ö à¹~¯â¹ÞÎsý˜®ÉsËßóÇ‹žëw*žkwϵižk£žkŸð\»x.~=ˆ‘éô’çÚ 'Îõ[ÃäÛƒœkœëu–U?ì¾ýrçÚ¬εÞçÚUÀ¹v/à\ëOâ\o¥p®—ÀýÑ8×^à\o÷=9Ä'5¹¯:&p®½’À9?Cᜟ€8ç¯(yÎí’ç¢Î’óø½|YÉsîy®×¹o>[~ŽõÈs½‡p$å€çz»ð~l÷žs®ä¹vx® x®õ<×KÎwyOþEN1\x¿?.w}`¸ 'ÄpüÅp;ÂaŠáørâøF âöI3H@ŸCLJÄñ7ÄÅ&º( w +!îˆât(N'Æm/qâUb·â¸±TÄq'’a‰ã¸·Çqë(Žã«ŽÃÞXÇM¸@Ž;I܉l|9l>Åq¾%8NÔM”‹gÙ{åÄ…ríÏ—ÛÝêQŽÝ&Éù œ¯É±—$¹ý §ä¸AÉé9 µ@Nãè#OÓ¯G’ãn’Û‡lArÞ•“äŽÁÓA’œù…$çÝ=IÎäA’ku@rÞïÉ툂k’k­€äŽ—ç$¹ý%kˆä7ˆ$¹ÆA$9¼ÉF9?'Q.¬P”óèˆåô Årœvf9NT³œŸ,×JÀrþ­ÄrüðŠå¼ Ëá(Ç(wÜ4n-”s³D¹V#YÎMœ?–±œ÷‚b9-«b9|ËiŸB–Û/b#QN\&–Óª–ÓšO–³eŽXÎTf–»q®ó•YŽäf–c²œvb9í’ÄrE]±œ,§ŸM,gF$Ëù²œ‰‹,§‹åL\`9ïAÈrîÌrS±œ¹ì¯XÎTF–㆒(·#Ö•QŽ‹«QÎïtC9’QÎdD”kp7~ ±PN- åÜò…íl…rn×(ÇkÈrúÈr‘÷óEÉø1Äb9!!PÎå¶Á† åöAx¢Ü>/Ê\»HΦ8v–§ñÅí6¼|¼ä¢8µ"ŠÓC“â6U3Å©·‚8ÝZ§ â ƒ„8 ƒ Θ™&R?@\XâÁ¦“çv q*Ä©7‚8³!ÎXGˆóU„8½3„¸mÊö’ç«îu@Å‰ëÆŸ¡QKHq~ª¹ÿì(ΧD¢8s)NÏù_RÜn[Ë¥Sœ˜mãdž*Ýà·†f”„8½&‚8w†ç† q"gAÇ·ÿ€¸VR³0½ëÿÙŽãi†óEd8×!ÃùÖd8_E†ãC™á8~b8}ˆÉpf:2œ[!ÃéNd8 N´(†k%µªîRo†ã‡øO²èÛp´Ý¸-Ò¨4í-~õÂ8ºÈ´³·1¸ÍNtà¶9cÄmÏNb·¹Üñ ÊŠÜv#3ЏÍà¶{ÐxóÆ¿×?ÛîI/<`[bO£¶g£xjû.,ÝŠÔæ[‚ÚÔ&©MÝ&µ=ۤ6݃ԦNµ}  ¶Ýð/¶ù–À6>'©Í€mÏö»9È9¨’¨íFxUQ›ž¢¨MMjã-¥¿M賤¶{@mz.R›šµiHm­ ±Í5€m®‘Øv¿Ô m.¶±ÀØvtè!¶±QcÛýpˆm÷+ܶ1œ±­Ý ØÆA2¶Ý·Á2&Å5`[xR’«5¦õ؆÷ÚÔæ*¤¶û"šÚ¾¨?¤6ÆÂ1µAS7´éNd¶vM2›+Ùî‹ ‘í>éBdku€l­íûnHŠ@¶¸ È/ÜÉÀln§˜Í×Ù"(à*™Íï¡í>é:Fh»&WpB[»3 â±¡ †¶v¨-²d-&•Qž¢6ÿMj»&×tR[+µq¾šÚZP›½Im±TÂM Ôv=< µ]ƒ;)R…uS[øP‚"“ÚÂÉ5@m­]PM/Lm.!µ]7Hmž?¤6Æ™4µÑ˜ÀÔæþ‘ÚÂsUà.dî"µµ ¶v'`!ÌF³3­Ìl~$2›;Gfë%ƒ€%³¹»d6M1Û…°Ñf6 ™­]f£‰Œ™­õÌÖî fkOh£QŠ¡->( œ„¶p™ÚÜ?R[+µùE"µ¹7¤6÷†Ô柎ØÖîr §r`&È­µ róX¹õ¿_¾Fø¥Hn°K1¸¹{·ˆ¼¾‚›<’[» 俇"¹]§„=›äæ÷ºÈÍJr£=É­µrókBróPÜü $7ÉÍ?0ÉÍ? ÉÍ/ÉÍ=,róHÜÜc’[ë È­õäÖ®š²Ã!¹¹Ç$7ßäæÑ!¹õ’ÁéŠOC‘›ïMrkw¹yŒ‰n~sˆn­7@·v' [»ÐÍÏItS ÐMí ÝÔ¡›~;±[» ì¦ÞˆÝÔ±[» ì¦ñ»µþÝ4^b7½9`·Vì¦Y%vs ÙMŸ2±›æØÍÏ@vk%`· Ù Z>ÛKfÄÆlŒâ–ÌÖw³95˜Í±ÔÁlÎtfs.+…5‰À–Í`2k<ÖÊG”±ÖÖ„‰‹Ö„ÉÖD·­°&L&¦°&ÌŸ¥°&B¹ *¬‰ò 0¬‰ÂÖ3®I«QqM"^êÓ´6g)`\“¨1JÇÊÜLɸ&{r -Ãÿ—‘&ãšè1×$¯nMkSÒ†5arHF5‰BZE5‰d‘†QM"iqÝ´¢šø’Œj»ø»ImÙBý ˆj¢dŒj-t«Iç£dT“}‡&è&JŽÀ¨&JD5iÕ$Ú¥UT“vÛLÿqÀBQM”ðQMâç 0ª ’n9¨É³*¨I¼ؽ"¨‰2i*¨‰Òü)¨INê%¨‰òf*¨IÄãÅTAM&]ØÓDI<ӤߨbšÄ@3ÓýÒ„Ð!M\M"Ô! !M",eWÚ²jxjÂ9Å & ùï &í5Ñ„AMZ+jÑ׫1M¾)ûtjSö‡4A–7G4‰}%è*#šÄö„ˆ&±%·Í¤ãè8¢ cï8¢É5¸Ê1¢‰ÃÌ0¤‰ÂÃ0¢ C 9¤‰#Ü0¤IlºÑ¤Ã 1ªIÐÔÕ„a{Õä¾W£É½†QM)ר&½¤¼¯Ï!ÁQMî…QMÊAMZ3jÂ\å jâ¨2 jâ¨2 jr©~j‚h/ŒhÂÌîŽhr^´²eD¦QwD6‚p&ŠCÃh&18k4“Ь{4“P„;ªeç©•!šIPO«Éç¨- gâÈ. g¢Î(šÉ¤0£™0¯¹£™8ð £™‡d/D3iWe4“P]ñ'¢™(£™Äñ0JÍdŠÞͤ5‹h&nÁLZïÌÄ1FÌDÑ*˜‰¯a0†7s0“c'½3˜ÉqÙxQ&ç(£™8¢™8p £™¼+ª-=F4“ã”t‡h&í^ͤý]áLBÂf…p&,E3±¢™((Š¢™8v £™(Ô†¢™ŒßÝï-z/ƒ™x@ÌäØ ÁL¯ƒ±LÜ*C™èÊD±Ê„1’‰ãª(’ÉˈXŠdâfÉÄáDÎÉh,xaÊDs¡LÜ B™l“. e¢ÑT(_…P&*…2Qˆ&Å2«¾ÖŸŠ±L’I±L\±L|/Ä2Ñ+–‰KËÄo0c™8d c™(€‡c™ð‡Q(w†¡Læ im¾#”‰ºëP&J²ÿ˜„eÂP@ e¢¡q(z…:”‰[f,·ƒX&ŠqåX&¾‚X&-ØJÆ2QhÅ2ÑLp,¾ZŠe¢°HŽeÂÑr,_ÅX&MHË£ó7çHxÛ2•lƒ8©.%¼ Df•ð©—K‰Ä1Ä Ž_:A—A#0’áÂȪ9½õ°‘`¸p7jö’¹&ïÍ^2£ÃMén¹¿Aä0\|ÖŠñÀpŽU‰Ð”q–[M24åË06%÷kŠM*eó{s`CŦ ‰àNšÒa"34eh$U Ç´JŽMù"z BSßüÿä½Í®67–¬7÷UhX=8B&™ÌŸ8ž°݃GÕ@ßÿÈ ®ˆX‹[RµªÜ6Ð#ióãËd2“I>Œõˆ¦Ð”.PhÊW®x MÉm!îê"G…¦|kd…¦Tæ&‡¦œ¯ iJ¡)u ‡¦ühV«Ð”P ƒÙšÒ‡MyÅÞÆ¡)çODuMY}ß2¥{†¦Ôø14¥ Ð”n©Ð”Þ¥ âࢊLé]°#S>¿Vå-Ç+Sò±—¸”ÍRq)£ ãR^Ÿ1o!Žcª½äº²˜“q)õÒ–¸”Ž9)†+1' q ¡ZâRv-…¢¸’—Ë®(NÓ2)ÎÃ×/‘nÍçU@„C–á4µár;-†+ñ-ÉpÜ’‹àú!µQ—Ú@¸\¤…p¹[ „+5ˆp¶N—ÁÙ„p8(õ䣨‰D|1\FlÃe 01\†ŠÃ!îhŽòHÙ͡لp³\Ö“D¸ù¡êÕVrE ¦ ‘î¨Q)/„z—É#%7eÓHÉ ‡Ml–’›rµ¤ä¦Ü’ÜJ+”ÜT~7”T”ÜòW’Ü>¤"JnJ¶•’›²N¥ä†c ’1k!ëã@PUr[%RÇÇå3qTJ?[G¥Ì8•ä¸Õñ(pTJ!¦¢R:Ö¡9ÎûCG¥ôvËQ)µávPJ¿Ã¸„ò¬[cœ"G§ä6Gž ’Ün:%·rInùJHr+¿RÿJ’›RhHrî‘DFÉ-·$·Ò %7%£Hɭԡ䆳K–Pr+u(¹e%¹•_Qrc޶TÜJ#I6KÅ-‘â–oµ$77+ÅM)NRq+Í(§‰Ç\Š[-ù~LU)ny—Rܲˡ¸áœ5¨¸å„’â–OJŠÛwÉ ‚[^H‚[þH‚[)Q²¿,Q~–ƒR6}»%¸•_ý•àVK^ÝÂSÉÒ ·RG‰NïºÁÌ»Ð[Ø#e‚–ÔT7þ»¬¥:ÿbŠœÖ`à˜íóï’Šf•”Üü»¤³iÈðùn­¨¤¶eµ%•”¶úŸßrÇ*)m±¬´å’ÿê9g;×Äþ×Rä¼ÿŸ§Èùƒwä|5Uj’œïÛz“îc{s[5N´µ¥Éa[¥ÛÚ“é°­L‚æJ¢µä:j¨&Óa;% ª©rÔRÖRS[B¶UÒà°­š,Gme-µµ¥Ôa[%ÛªérÔVÖR[ÿBºœ u‘Ññ¿m¾œ¿ò%ýíwßÄ?únþö‡3çç·ôOfÎïÚú§sæœgdný_;iÎ[’æüÇ?‘4gd:í¾ÛäHõë|yõŠëüžÁ»Ì£NN[%8 ‹ˆO¨°QПsÇ˳å÷Z@|âX‰uÆâó’íò,Y§°ó»«]À{¯SزrТàyܹwišçsÈ/ã¥UÁ¬úðWšý„ôççQç+L=—kJ˜¼%aUKœ¸K8€âpò‡Ä­ >éc'Ì€q­¹*~¬s-Yó„éLl™`­{Àֆ׺Ÿ“`x°ý= ‰ÑgZ>}Ï·ÿý.$n‡ï±3þP"}¬q$Õ²7œ‹ãC~(@x;âH ëiô¦-ñ uµüvÄ‘J ¾Aü½£$d€v\wô&ÙŽ_Gô¦ñÚq*ÕN‰ ³ä{Ðq̬=¢Žô»v¼=î᥽^Ûùî=^fµÇ°¶x¶væNpÝÃ)ñ ÁDç®#8KÞèñöu¼¶Ñá3N¦Ê@œc&£ÙØ0¶3N¦Ú¡8¼ ëCßnüŒ“©2\sÚÅcÈîÅÉ’$‡ {ÃsFoZ û\+NAÚl ^QÕ8Ã6h6v°¤…qÐwrÞµÖÃ:È/ÿ, ó WgFóGaô¬6Â@èaàYr‡…6e¬æ€0*møXáU‡‹ ¯g¼×­}h¢Ë}þ½l ©š—éG ÁÐ!~ÓüÏ"Qçau¥l³$æa—Õ{ë=¬„cÌ’+æs“eëƒVBt·ža$tÒÕ{n‰h#ÔyÀÕús#¨ù÷K#!Eªš%a$t*D×ï8™ú䕨®£oZ³„'S²=CÉvNro¦¾‡ÔÙ®ÞÃJ+ÛYgS²,š¾²x»ùZàÄ0Þ×ëîa?vh2_´0øä7KÞ° Ë ½ãg¯Ç3èY›{ÓÍÎi¼› Ù,9ãŒ9«4ªñË3úOàÐ(Œ°/ȇ4®àÔ‡f„yŒ×6sa§åÇ4¼ ^ê‰ø'‡ã6^Úæ)&^ßfd'u€YsðT¤‚¹×1.ðí>cE…Ë~cI,©Ù›»Åšz*úB»{¬©yW÷k* QKêÁ³d¦ï|«!dûhZ›ãû…yA˜/´ÙÚJ˜Ô:²°Í:a^P{“V¶Á/Ì pWý ‰6ŸÓöh&æ{?–¡­‡¦´´u#ý©m§y\?hkëïmõvöƒÆ¶ÿ¤©­o¨´µ=-¤4¶õ#˜«`¬¤6NíÇ+i©ón²Ã̓ûŒ~Ðâ6ï öí®ÏPksÞv|6ÛÖÎI“Û»“›ãÒŽLnóZ4¹Í;?mrÞW̶›—y¼–¾¬AƒÛrÜÊǺŸ!ÖæçµcWÕ¶:íàZ*ï¹…¸5À±J÷bmyØsë‘m¡ÓÖË\#F7›]™—¾iÕîgÝB¬­—‰ã 4…`þ+™uL|øJõè(3áˆøf‰~-⻜½EÄWƒBò]øÑ'˜ï‚Œ@Ë›`¾YÒ¸a!ó­_Ê|ëW'[¾#Üt—M¡o–t:ô]È6ÏÓá—iUºäì}óï[¼ù1­Ê,a¸€¾õžL«Ò•…зJˆ—óªte!$ô]áäõ©Ž0pD6‡RçW.kUBßÖÃçÛÿ~#›Ciå‹l|¢óª¸]Bß,yõ =˜W¥”´ÈæÐiC@æ+—"óm _ü›_ø`¾­„iUºLtÉ|Û¥Ÿñ³ÎÉJÉÉÊm~‘Ì!{ÌW[æ«÷ÌWnólïv¡`¾ZiUºRUùê]žL«R®|ÝJ˜V¥\ê=ôx)fUÉ‚/9¸ 1«Jv¼W/¼W/¼·ý¦7=—DdK毮ÈãPJFäqèa`&ÜÛ.Å”*ÙßçùqL©R.ýµý2L¨’%Á{[ ª¸+{[æSñ•ƒöjÁÅyœ¿‘Á¡–D‡¼Ð ²à¹¶?ßó×ïÑï̤’%z[ 3©dOõJédAïê= ®ý߯W]W›cüè[pÞVÂ,*åWÏ»~`^-øºzO$:޽óAyµÕ ¼­¤íï_`^m„ Tú§ƒ–À¼Z…ùSJ+÷¡ÞëGÌŸRê<ãÇèæOɆ¿cýÁü)Ù.oûûl?kœßÆ+ÍâÕ‚«í£„W Æ£ÞÇÖ†€·]çiê¾K¾Ÿ½{ŸýofNñ…‚ï¶‚ïÇØRp,}yÚõ£wÁwÛ¯ú÷³Îuÿ¸ƒ‡Ž’¥ä>uúÕýí3m`)aÞÀÒ Ö’÷Ç=¼Ì›’u^æ,%Ì›RK^݃Úé?þföÀR¼)¥f,unO?ÕaÁRò?ë0‹`)aÁlùcÁRÂD‚ù«ïÜÇæc*ÁRƒ‰SJ Ó Ö’çGÿ>f,-3qJ)aRÁZòüãiKËßy¸(oÿûùYƒ¹¯#þdfA_†ˆ—˜XP^×ÞuÞ^òíCKÀËFžX:õçJ+è?bÑÔŸÌ)È?ƒèêÅN&ôÒM¢ËŸ0`ù ·½ªpûH“å² êÏ{°ó9÷w€ —?` Áò¦d…@¸òg,úóäò(]‹ðV¼í¿µËo[¦ T…êóÏ·>t ”ñç?‘3'U:Ml¦ÅèG*r°‡H—ùâ%Òªtix)™®–„L‹:|P¦ƒ9¶…;'T§ZE™.“®K§ƒ±ÒQ‘­ºsP§sBèéŠçeºâB™Îv–RéJÎ^ªti**•®–„JãᱩtÙŠté’$‘îX]ø{jt™½84:üý±Æk³U‚+5:7"‰.o@]úÊH¢KïIt™ÕW]Þ¤$ºÌ]¹ô Ñªz'…®6´–FW¢µ4\–B—^MRèÊ¥>æR·NE._ tùP$ÐÕ:íÝÿîCv·½âZí ºzmÚŽ—’Pèü^I Ë; >—ïƒô¹ÚßF«²Å–>Wz¼ô9<â]ŸËôÖÒçrRJŸK{xési¥.}¯ßêshgðZ¡Ï¡Î½és(¡E}ŽfêçÒ|;xíC1 ÓñÏ€ú~C’åxVi´Yµ¾Øe9~[Ôë?lVElù±¥‘¥ˆ-mÛ…lµÎ³¿Ò„6üæ¬ݪslÔöÁtžRÛA›U?mRêð9‘Új ã5ÙrT܆:-¯xMß)E™äVkÈx<Û½»îA½‘ñxöøyujùªóT…®¶LxsÓÛ7g9×Io(¡@°è­\›ô†*\CÆãYç¢Ùª,GÅoµÎ}èÔŽŒÇ³Î3t¼«!ëñ¬ó?ïAö㾇EpeÔIppxz©À´[u+$¸r%"\m÷j?îW¯5݃Jd>ž-ÅÕ«Ë€<õîcsË|Ü5ˆq[IØ?ϯԸÎ[/Å#óñüQ§3ˆo“WW 1/—Ä=úJ–vîoÿ¼%óÚŒSZ®Ä@¥µäýq¯ìÇýˆq¥åWöã¥äýñÞ¾¿úĸڮìÇ}ĸÚîýs*ãj˯§´~Ÿ¥å®¸4EŒ+ý!Æ•k-Œ+/1®þFä‡tBb\ý•LÈÝb\mG&äYÂ(¦¥Ç2!÷}ãj‰ŒÈe—í ãò7¸Z‡áL}m‘\Ž`.ïJ¥ÖedX©u¨#²ü_Û¿¢ZWúGµ®ŒÕºÒç³ííR®+ý£^WëŒC÷06½ï1Œze[¯Ë·Kz]íŸböž?Ðï­$»œi!Ù•kS²Ë˜½’ìœÁØ’]¾Ù’ìræI²ó$—b—ÓJ’]½”Bö楆 õãl Ú›¿úÀp3Ò¬5(Ú•:¢Àëå®R¨´Ì ¥„XJÙ Pá“@Ø ˆÖØÌbÀ+AÉ€å7dÀréÏBE]dÀ¬sýŒÙkÌ‘fÅ€ÎáKtHR3`¹’böf2`i7cöª°´CÌ;fÅ€ÙŽ0¯%Ì;t@Y3`©‘1{U‡ XÚUÌÞ,¹ÏA XÚ!–:ŠÙëû–_)j¯¯ ˜÷-Ìñæ]‰óJbÀRçú„Û X~5(T%´Wý!æ=ˆK÷G» Ú{ÿdÀlE XJ96‚ÀcA`ŽŽ °Ô¹„[%ÃA¸‰‚Àr­{×¥„XzLt>mC`^[˜£#ÌvåWÊŸ%ýÞî[˜ý–+ó¾åÚãpÿ€ÀÒÎûþcA`öG˜ýæµ³A`^I˜oŽ °´¢ ½î± °´£ ½Ùe’/%Ïï‰ °Ôɰ½O…@÷ÆèV ¥ŽrÊg%•×ûg,u”W>ÛQbùìÍøö16–:Ïõ³‡ïV¾oC ßC ÇØèPɆÀlGXÚᆹ´CÌþKB`©s_õ]2–Þsl¥•¯ïïº!0{,Ì»æµù<Kþîïº!°Ô!f¥7„À¼sA ìñôw©z~›×cìn¹çÉo~ ~%|Aò눛³I~½¿vŽ É¯Ã‘Ÿl’_Ÿ[5’_š-0CòëWÆ–CòëˆÅ–CòCÙv†äWë„ä‡56™!ùÕþ@óÃöì&D…æ×o Òüú-?#‰~øÕI8 ѯ÷aé-D¿~Þ )úµSr®D¿¹C“¥)U¿†acPýÒm®yíºŒý$]óæç]­Ð5ïµ{\óîK– rÍ›Ãø¬èš7ø·ƒ¦duÍË<,É}}õ.ŠÉt1÷Ê#÷iøÌ}‰â>Çt7÷9Q‚¹o¾ÅCJàû8Ä}ù÷õ;e>¦ˆxD³Á}Î4bîCdºÍN+ÔÌKS·¯†¸¢9Û!÷uûˆûœ„Ó܇ÝN•þJnLsŸªšûJÉÉí‚(r_)!÷•ßûN{-ˆûœÒÜ甫¿ò+‚ßi/ Ÿþ$õ9³£©ï”E?©*4i’Ô—%¢¾ü¨ú6u=bŸ³ÌûN»âûò„}Îihî+W'÷•vÈ}§C‚ûN;ôˆûŽ—B¯°ï´ç°/G\Øç|lƾ_a_…°¯´Cì+%J¯IR$õ9y¢©/¶¨j6/¤ìšvõ)—ž¡ï|´õô93¡Ï)k }ù+Aßù³ôåƒôe÷}y ‚>Gê2ô•_úòq úòq úòq úò úœÿÑЗ¿ è“É/­ˆÏiGM|§=ÛD|g:Ì‘øò ñ•_¾|"¾ru_Î⥱Î">³øòB¾Ã¾¤¾ƒY!ø9^Š÷œ¦×¼ç+ ÷Ž[_Xáž'˜h6²Ó<ô?hï:ÚíöHívtí•K“öà!E7:Òb¥R@#íåµE{ÇЩ™hNÀä´E{Ç­c?Ñ^i…´WZ!íÁ®ƒ%¤½¼OÑžÇS°W.MØ›%Çf¸Yº#Øs3b½ìM°lCvÁï:–ëe#D=ìÐØQ¯4CÔË·H¨—C#Ô+í(·¦‡F¨WÚ!êÁ;_hwÔÁ3êydŒzwÌ&=¿5&=ß·IÏ7eÒƒµÍf¾é±1蹿=¿|=¿ ½rG=?&ƒžÇÊ çK‹ó4Myqc^ŽŒ0/o[˜W~EÌË–MçÇ40Â<¿yÆÅ siUÖ“‰…U=Äi`ÉRõ2ŠšT=ÞYÕûlD²Þ§l–õJ e=Gõ³¬gÖ²žíŸ,ëaÏÏ:”õlqdYon¿âƒ—ò¬e=XÖ³%˜e½ Éz N²Þ—\(ëÙ~̲ÞìÔÍ_QÖÃzÏ:”õl-fYoÖ)FEÔµ¬§`Ý)ë¥ý˜¬:]ÓsX:›t¦áÐγI§ãÌÚ¤3×2é„7,Y6iâ'›Î4 dÔ•ÚnD])&‡²é,uhÓiû]uæÕeÔ‰¹þè³gŒæ”Pd\²]ʨӱRÍv»°…]©uÈv~­Ív6cÚÍÿ|»¤·à' b%šû µK²sÝ|Qd¹ÀnŽªc°<V%JÐŽžB°Ó©P‚])!Ø5‡÷ص{÷ÁÃê½ûà}sG*CP¢]2‰Ú5‡’´KæÚe»B»ÏyìàíÌ’RÚHvN‰dgÎÙ!DéNv¹¡‘湎xØÍóZËsp#;Ô%(}ñ¾ó×ìÞùÐÇfÔ‰*ÇÄKŒÌBW<7#W¼Ù ï@¾x0á.ÖµÑovI–—ôÆCˆj ½ñæÓꛞ‡: Co¼R‡îxóöù>ÊoÖLÑ!ïUê%{ä•:ôÈËk…G^©A¼÷P˜zäegä‘W¡K^i†.yÙ =òJzä•fè‘W.E—¼l†.yY%\ò\Ay¥=òò:òÈ+uè’WêÐ'/û+§¼R‡^y¥½òJzåÁkÓòJ—ß}`ä”—È+/ëÈ-¯Ô¡[^Þ”Üò|!yå•*ôÊ+ÍÐ+¯ÔQú¬C¯¼Rçþ¶ Ñ)Ÿ$Âò² }òr\䓗בO^Þ¶|òÜŒ\òòJrÉË*}¿yäe:ä•6èWºB‡¼Ò ò²úã•fè—3RþxYGþxy)ùãå¥ÂÏ’;^©@w¼¬Bo¼R…ÞxÙy㕾Яԡ7^©Co¼R‡ÞxåZôÆSwèŒç vÆ›m‘1äŒç Ù/¡;^i†yY…>y¥úäe¹ä=ŽäB—¼ÞÅ}tÊsúåá<¹†\ÙjÐ;/ëØAϲƒ^7å}{¸ƒtÑËf™"ëÈK/ëÐK¯Ô!Ô•:÷c"}õ²}õJ+r×s‡é­—Uä°—ÍÈg¯Ô‘Û^7 ÊmÏcC·=]H^{¥‚÷\…~{å:tÝ+}¡÷^i†|êË?‘(‘ëûhSyY­çÕ˜+Ðæ|ë.yìE@¢Oûi z¦§ZrÎ’ —‚^ëJ;"A¯]ôŠˆEA¯‘ØrzsÁ“8GAC¥P !è!Ó†±@ЃdE‚2oŒÍ‰o~Ä-ú… ‡\ëBÐÃFõ©aWFûNc½W§šôk›ßüÉŸQ‚‚¯Eõ¼Oi?©çe…óæCV¯’óÕæøæ×J>Êy„Rƒ®l%áÆ7?Né´·˜¯Š\GäÃî[îv×úûµÈ×'o!‘C^ ßüÐÄŸÁ{Hd¢¸ Á{ýT,,â ¾3p×áQ:q%Äâz§ø˜{€™Z¶7.Ý«”7k8ö}øúéÐfÄ=´+Ô ¾~\rÐ >t˜R }øúqšds>·¡,dó³ò  ›ß%o½Uf—ß\í N|sµµTN|x7OÙk.'¾|ëåÄ77V²'¥Äæ±9ñµÇЉonáµ¢æ{Oâè”®q6Q¢ˆ™áÇ×NGL‰0›HØ#U.Âl–*es^Oº£l"«Üí"Ê&>ìW5á¬aKf Ä»ÇÙÄ‘Tß Úä´±Á>»I2Îf‰ˆË8›~ÊÉÂ8›¨#‰-âlf¼`ÅÙ,qtgs%Hâ¯"Î&BºŽD¾åWfŸh³Ümb©Üļƒ–q6Û!GT†ÙÄ÷^Ž~fуyžÎ0›%B.ãl"R±ðý1ÀŒ³YxÚ,‘mh3˜6Ñ™³ßêŒ~‘6ËÀ(Òæ§ÜMŠ´Y{‘6k;i³Ü¸"m–v"ÒféóŠ´Y††‘6ç7FJˆ"m:¬³"mbøTÂH›Ÿ½i³ÄëU¨Íì CmâÕçéCmÎÅA¦è µ™ ºCmædX¡6K(c†ÚÄw鬡Xê]1Ö&Þ©lk³´ÃX›µN§ŒŸ'cm–ÃŒµYîŠÁ6k"Øf­sÛ=1ØfíñËð՞Р¶ÙÎašü¾Ú½a°M\© z5ü2ƒm¢>ÛÌIµÂmÖ ƒWw‰Í ·YúÂp›¥¿ ·‰{ºj$–õ¼¹À3Ü&ê¼²ç|5Â|n³Ôa¸Íò¤n³Ö9ß-Z4Ãm¢Ç}n³„Éf¸M¬_­²ßv¥ÁèÕ·ÞY†Û,Ï›á6ÑÎUÙoÕ!f¾ãÇ‹Îp›~ m>‚ Þ²BÛ̇ `›9x ¶‰f¨@1Úf>(ÜDwÅdp3”næ-)àfÆNWÀMÔ ¾­ŒnzT¼MT‘³^ÄÛÌ·Oñ63¸ºâmæ³T¼ÍÒÆÛÌç¤x›¸)‰qoÝQÜÆÛt¤ï¹Yn›!7Ë3äfÞ#nÖ›Šˆ›ùz*âfN)Eܬu"â&ê|UÑ[7þ¦÷ÞV#‚nÖV"èf½Òàªz˜*™ÐÄ‘çt³ ±‚n¾Tjê Žcï-ýÄ`~¼LÄ’-uПþ®¤b1uÐï¯à’šªg¿Æ¿—’’öçÂ÷ªm¹¤´Å²Ò–Kj[+çmi)þ®í ¤¶—6Væúg=•”vXVZrImk^õ Ö¶ö§SŸ×yJ#ìVç‹¶å4B"¤»ßßåŒÉ÷ø•÷ØÙ—g-©åëùÄáÎUùž÷·H4ׇgx4üN¿ÇZRqÎÇÖ+÷ÅÝá ¼r_ Ã²˜Se-©s¿¥)÷v\ ghq¥7Ïòœ#ó^O܃ŒÐ®w¬©Ü‘Ï,îó½×šÚçëÿ°ÏZS;–®›%kM…$ïó¬¦xu­ðÅYuœ¹,Ûã5Èoi$>V öøÕ…yÌ'ÇùôÅù¦C¨Ò³äÓ÷žßˆ/ÎÏÊ;ý…Â|CCà•âü ksØMÎ’XS±keIœŸ•}Á óx.Å ó=_Ì‡× …y¼ìÌ·6'rÅœ%·lo³s5Ÿ½Y²Ôñhßµ¢ÙbSðè<qz6†QúòÀ'(>C_†–oÍJˆwGw.^ óÜ*ò»7Θ´¸…3f|Ó¯óÀtŽ¡9ãôl.±¾RhÌsðÝη–Ô']ö/DfhQ±¤Æi5J?gõŸ1±Çm¥, aŽ2zG–K³Dÿ…‚-DæÒ›Æ=2Ä3^;DæéŠí†Ê\û*3d9V ‘+ëLJÈ|}Ê#·ôfìà?iö£‡È\†býj…·ÝÏ'¶ð'7£‡ÈŒM}˜!ÌïL¨R°Ef»™×¹B•š³ïu‘BùÍkÝk^°EfoBd¾`0±C¾ðÕbá1Ïuœ†Ñó½k{ Ž\²1Y°/êpúêHe~Pî8uý‹©Ž’þ&Öv$uÉ“ƒô÷<Ú³ ÿ˜Š±øûªÄ?˜ë´ ÿ2añï‚nÄ 3Ö@І…Ñüñ†ÅŸ†øwáÈï#MÑÚ¾ÏÄ¿ š ÷@Ä¿£Iï ü;æÎ+'ùï@¸õÿ䑤Dþ;`AÏkÿA#¸Øãà¿6A„Ñà?( [þ;_¶ðƒâ_&ÎþµùaæFtáèƒ ñ%ì ñ&KÜÄÿÒTGø×^Íábpq%þõ¦I-üÃŒ¸ˆv}ý*ú+Nú¨BhöØèjÜe’þpþÊñ$ýuÐô‡ãá›”ô×_FXüÁN¬ø›`?I|¬ö»N{ˆý®ÛÛz²_ÿ$Šý®ã1Iûas·Mö»Ë‚lìwÜÉuÁ~¾Ø, ö›,ᇨG©ì!Ùï‚…\a?ü†úÍí2—@¡ß8LNB?‘’è7dvcúÉpŸ;©¯ #©o‚¿V/Rž*?œ¤¾D-Q_y[D}9¤¾2Ú¦>%Zð»ñ$ u¿9„ƒP'ðSâ ƒßüºþ¿ï0|ü ü^Y ü^™ü>eE!ø½ßOð›ír/ð+½ ðKŽøal>’ÁïUBl‘ß5$ÆBä÷Ñ Ãà÷ÊžÎà—UÈ}&ÿà¾F'ä5rß§=æ>Ÿˆûj_‚ûp~°cß×E®¤¾ìJ@ß}*y /ñ }“‰ù0vDøÅ|è¿x.˜/O Ä|ø ¹•ÌwÿŒ3T|Èn|÷Ò£$€o|²×ñ¹‘À=\÷$}îávÉ(pïsÅ=(ƒP¸W¸wÃxGpg¨‡6ÍÂ=ŒmÌcá^¹gâÎsÎ ÷0vC%q†zjÇ&ÞÃ@±É{yì¼Wï!xWŠ­–x¯\‰¼‡V…Gû«™’Œ|ï‘‚|ð“`P ~CÝòehž@>z„€kq:^™]ùæ—@¶ÏVünº[ðƒõ/‚_l£ñ“Þ'‹6É}°Ÿ„r_{k@j6²‚¹À=¼š<ô\¸‡½¾„;ÚË;ú™pÇ÷&÷á‘K2q6ÈÜJ÷ð6pCÜÃötSû4H{Øññp´w ï¯$ölOmÄüa+A{¹ìö.ìgX%`ö®·§²+”ñ{×#¯ÁvJl8Xo:à&ëá&50XçID% Nù„~zØ´st‰zXÚ%¾êáÀ޼@ÔÆLuõ°¹~7Ö«uÈzñˆi{eÿº`¯l¿ {زñ °·öûüMÀŽÀžÏ­{8ýÅ.óÜ@o ÞzeãOÐË@ÎËs·à¼R!8¯ŒŠ8Ï›â<ìÏ9*ä¼!N È'#I‹ñÊV—ŒI|gÙä øä‘yX(½òNî#äÁ¶rÓø0||çyy%CžŸ“ ïVäCÞ¼sjC‚¼Ä A^;B^8¯[çp:x¥K¢9ïÕ“çµn†#çùÔßœ—=þsλ|Œ#Î›íˆ zùæè¥"Ð+ÔIÐÃ?ì ‡•ôGÐóQ@Úuó ’ó†zšó^¥ßKλ4/ÅyiEœw1Z†1$bÆób&Æ›;çcSùðIá°ü9ä /^‚<|»7•/• q^nÝÌy·BèóJ+Áy)×$çÉÂ\ ‡=ÏZÈzE‹#ëå®P¬çOQù¬0KåƒéÑ*ÈS‚‘D>ÅÆÜ»q’í݆? |Ç.ð¥l)oŽŠ>KÐÒ÷š$ë{sÎëRAzØEJÌ‹fJ¦½{ùh¬‚Åyó±Pƒ!çÝ6©神kÎ{eÍ-ÎK­19OéúÄy`—.É/8¯Ô ÎC÷¸{ÎÓ‰„0yª2Â<D%æ1W§)ïQªKSÞ§Ö÷<Ñ“ò>~¤+æqMÌ+à$ÎÃæ`ã<ßµ8ï•”wÄðò¡YÛóÙ@2Þ%±T—Â,)¯ð˜´=[b%æ]¿î”‡öÉ_”ö>…‚¥´÷rme/9Vʾ”Òñ‚ò0€¤G*{Ÿü zÐÙ;‚^B´@oÎOéŠÁz ·B½Y¥‚„zFä?E½Sˆ/Ôkçe¯ õpSÔžz~´F=¹‚ õ0ž»²‡¹NI“¨‡Orÿz‰Œ_Û1S¨'ì'é•7ZÊÞC›°ÿ,R zøFW=¯hs„»&ß\›sZe£9'ÜòdÞæœëö÷b͉5 ¶;î´eø«99n2"­9ç×µoÖœ' žpx.9EskQÂ\æN‹|—nÿâ»óòdñ]º‰ïàwÃ{ò]›½áù.} ÅwEA#ß)ÆfÎÙ^…Ùà•:$¼>Ò82^ÝVøÖª„WRÆ‘^êüò“𪀈‡ÝÿŽxýõn‡ˆd8tkeº@üäMêyøtnˆwšÖónó½W‘ŠyPÕ¸%Z”—·)ßjÒYPÞõÙøŒ”ÿ`îxIy@Ù±QàBH‚žM yó¥x7kN(£^i‡öœ€QÊjÇ®LÈžKu6¢^¶b{ÎÇÐFÔóÉ¿í91A‰Œ´çÄ;Ë:´ç¼,(Ë 3­ â3-qeÒ _MÓÃ~º±Út¦u»l:mV+“ÎöÐrT¹å–EgR†,:_›MȤóR¤›tÞÖ“iÒéï‘L:ßö£´é¼_/m:/‚Ò¦³ÛZ@6¥Út^ Ÿg›Î[§¤6éì {ðžâgL&·‚FҤ󵕇D½´l–IçG»;³Þù”YïQüp³^š¿ŠõJ²Þœsº8Yxf²è<­‹ìᦤÊ-ØK»eÑÞwðÏ ½[Vc¢½GúQï~Åh$½×'—B½ñšÚˆzŸÏ…z6bf½×Ÿv±ÞP”€=XÂÓ¼N°ggÃÞg<Â^º öžãµøÖ/Yæs+؃ I9.`/ßÁ^ºPìݬ@L{ŸbtŠöò¾E{O“]€p¯üЏ‡+QU’¨„‚ =4C ØËç"ØÃ}K² ØKÏ€½4wìÁ¬½ ïÂ9â e“5½GpÄ{öï=Çeò Þ{Nê}:Oîá–È9ä½çPRñ^6ª^yïé¶+•ª÷¥=hlŸS‰p,ì}’xÄ{ÏuúWÁ{ø` 5ƒ÷žvÛj4xÑ5.ògßsqíï¡ /µx>ÅOøu><™ï=ÝF·ä=|Î%ïáë}É{ï÷ƒ÷ÐÉv7”äÐ#Þ{š69â=\ëaIðGâã×â7œ+òMÅç3å|N¥Ù´G«êüQ棄¼_UÂ;H%}öœçWÞ«ëEys¾6Û_†„­“)á=Šg&ÌëM_Sa^ F8'æ¸îówëÞœö檫Ï!1{_.$ļxcÞc»ŒpÚÃ^˜ãǶ‹˜W¼1äµç³${í¥Õ¿¼öò›˜‡ó1Áa`6Î\@íµ§tWÂ<øMÈH30ïž›ÌMÈÃ#ÜÌ6ýaåa+$ÛJ:í¥S)/ì´7ÌLrÚËÛ<õ7_œN{Ÿí"å´7®R^ñ¶Z”÷4ŸîÛiïÖvŽ”‡7[FšAyXˤ÷å=·"‰òàÙe¥N{0^£™&öpF¥îæªÄfŸ«~ì±wùÜ^{ŸlÝÅxˆ÷Cé‹{0ƒ¡Zˆ‡ïÄ¡’W«êFxˆÄ'=è¢ááJœ-ò×{À./}>‡ò¤¿Þe!‰„‡­6w›$¼â?FÂ+>›$¼²á#áåGÊ.{Ýò ð&ž‹E)w¸ì¥/(  ™$?ºì¥_§\örï&—½ÃÈxx¾×Æxؤªd¼ïò]ÉgO!óí³çY'Ÿ½Ä€`¼[aí³—Ç÷öÙ³§œöŠ_0ÞüÀÈ>{)/ˆñ¬aÈe/ýÅŒx†¹ì¥—o(€&]öVºø3¯PWzìqRŠðæñÐÎ{¶_·Çž\Óx:¦6ߥ'“øÎJG(yãýu·Ø¼"<-6_½ òÒ •BÜÃy·æŠ”¼|‡¬ä}Öä¨ä¥”l%ï¶¶G%/­ûBɃ_-™PRž¥æ¥ÝžÕã³ål ÝV§Eú Ì(Öé‘>ãsD‰`» ÑI¥ ^‘?cÖ¡%ØnÕ¸«z·•<‘Aã³ij°ÝÖ.SØ|éÆ÷E,¹˜Âf–œÒó"…Ò„±„)l>…Ñ´Ûša›Ïa ]íðÅ6¥ÆˆÙì}ü¬rG Ò—'Rh”†ßH¡Qê|‡î@u¾H¡‘cdW¯5˜Æ&GhWor0‰Mi¥_û- æ°)U®O· å°1ÄÚÕ4”æ”DœwÁv+CѨ–šò ÜŽeý}I΋4¥Æi4Ji4JI4ØÈ•ÅF›'ÒÝö+e±É’;òhÀ(_%ßÞîY4^.ðJFÞVGylÜNÞVrvÕ¹e˜É”TÊnBÀ[%OðJzÞÂ’K@wÆß•ï¶ 7SRÙÑ ø®þH™l†¨!ð®~¾e²qIàÝ*±ZÇL6YçdF*­¼¯rÙä:³wë˜Ê&u‹©¬@Ým%73RùtW_Ù »U"+Ðwü˜ wõÕ¼ÛK˜“ê•Þ ¼«½ù”ËÆ×¼«Wú”Ì&K®K÷ v•ÍÆ=ÀÛê0M©ó\ºÇ_iZ¹äMø2)•×20^i…Œ·jHZ;½°Š»N.¬YÒ˜•Jí’ñJ 7…{͵–Œ·µ3¸²öª»¯½Ý‡+k¶Â„6åJ/W֬Ì6Zø‰xµJ ^¦†#á•  oûQçºzî6›eÿ°¯6;¸¬f…ûØ·¼ú#æ³)?z¹ªºÊwh㢮©Ú•ïê…ï¶:‹ª41Ð]ý³uMm\íG÷îê—TÜ\Q-vÚm%/WT‰d»d»ú«`»ZlW[ ¸ÛJWTíÖw{ɧ}—J®XR?ÅÒ#Üm%wSÿt­ÈñXëŶ9s·ènûM„â-5‚î¶’Cê’&RÒß:ÃÝÂq ¬“þë\ôç•^ÞyÍâñï’nJ{šf¿š]øçÜéžÇTÊÆ?˜’¯ˆiÕ¦pœ½Ž“Û1Áß!Éš²^’ þ2¬áït£„¿‘PIøƒùì8ºêQÖKs*ã¼”;ϲ^{mçHú+¡6IrÑ_‘7L§:êzi®düKW;êzó¡÷]×ËÒõlqó§²Þs:âe½ Q²PžÄuì6D”õÊq¬bq>ŸIŽ.zéëQbqî¡83ôU½µ%ÜT=˜šÉN”¡8o‡ß‰PœRÂÞÚFnzÅÐL¡83Dž”½”_Š3­œŠ3ß…â,a6)íYQ$η›õ¨ìA2dqo†CŠÄ™z±”½|‘¤ìe,>+{-I¥ì5«bTöÒIÁ8ÓÖŒÊ^Ú…8ç0 SÙƒyÑ£’¥ÛÌÊÞ¥©”½¡LÍVöº>$ì•È öN{=J؃_/K>››Èp”Â^†y¥°—Ö$Vö2ÜéRöŠ|)eÏvLRöžö%í…²—!f)í=ke^Tö<1)ì567=PM¯ð7ú(PØC÷äXÂÞƒLÂßàåôÊÞ3” ]Ê^ŠÓöPåUì•%ì•§°÷Üvz£²—¶Z’öÐιÅâ,ñZ—¶W»â^ZÇHÜ{{PÜK{‰{H•ÃðF÷žÅ9« ´½g®wŠ´ÚÞ´oÓöÀa²Ô mŠ6ãEQÛ+7¾´½¢gSÛà %?øÔöÊ“£¶·ø®Â_5¦ ¶÷¼Ž0Im¦D j{¨smÚÞsY±”ñæ÷3"ËsÛ9wi{¸à¹Åã|†Íþ©íÕV­ÇlÃ@m›”Véo`ÐÔrh{NY7ëÍgtû÷…¸‡PÏæª‡vØYoÞŽäµÄ½çθ'!î¡7ß™×V¬pBÿßÔ=ô¦Âß@º$è\«j½t¨{Ø‹±¿!îáJü:Rß{Þ;K>Ý×Ù¥ï!éÒµé{8ò¿e°¹VÕ÷Ð6EúÞ€ýf;4[–¼÷¼M>s¡îÁ*LJb¨{ùIÝÃË£8-P÷|Wù›P÷ЊK^½#êo¨{ïJe÷÷÷òU“¸‡îº$f3Ì»¶ ,ïé|0÷ðT6ôÈP%g¼÷ÞCëwˆ{o»~„eAo*ú LkÓöVþ,¢jh{oë²&¥ç'ŸDJ{è®è0¤½6“«€Ê”…O¡ýæ+(){¥3KÙ[‰»¨ã…²‡®¼þfONt±AÆM;6çZPQ…ê…½^›°÷""KBØC;G¥¿Õެ>CÙC–×¾ÅfyD¿íŸC×ÃWl×õÞ.MKº’ ôM×ÃØq¨ëÁ¨QXºÞ{Ðe½ù9ìu=L¦köÊKNaï+Ö'kÍÏúÙ³¼íg NÜD {x7× bM„‘óK=·¬dßÿßVv¾¹ÇSÉß]ú‰ ðÿƒße-Õ©¿û'ÒÁkiî+ò Y28d¿¹L×ø÷RÒ oÖZù‚ŸÚ–KJ[,+m¹$ÛBÊPLñrç.ɶT–meI¶õ_•nh~Ô1.XçWråQB–ž €zfºgXù“ ×ßî?«i<®L!ô»wab(¶|…~ûÝk…±m¯­–›ú°{JS,Øšr%7Uj©©•œlÜÙ” jSYIMÕZn ‘&Ç(M±`kÊ•ÜT©å¦`";ziŠ[S®ä¦J-7¡tkŠ[S®ä¦J­¿ú¦û\ù‘§vnÿ$ºj!%ò9ÿìÕù“BVïg¡ÿ¬½Ÿ¯÷ïêí „þøÍþƒBá{ùÛï¾|ôuüíæÍリà ð½ÿöÛ¿ýuò}7×?ŸÆ:“~¯•óïÛÓõLcÔW£û?Í`4ë!oRݵ°ä-ê{+å+·~ôùw¦,ºþBÊ¢¡Ÿñ5 ÎÆ†ÇûÊêö<—(ß^ X”4lïĽ84;Ûb½ö]<®9xä—~ØKõÄ{pÏÛ{Í­ÎWúisôå‚>ëœ>*:'1~¨ó=j±´Ÿ_"ÉâÚÈ ö\™:¶M±7;g×çF¨ÃÙ;hž'ͺ”•õXÖË2§ _¶;§¯qüÑΦã )6%=7#½¿ê²Ü¨3çf^áQ‹™žPæõÔÞ £;>ºM j[vRýêÃÉg— YÇINœTÍ'~é+2yÔ ±rÕa.îo‰´skǸ`ˆ } Ê#cmä0s¸.@UœŸ+ØwÇÑŽÒS® áB %×—OZ_§ÊQ°œ¾:Â[ñXüZá«;bÓ‡ÚˆÒsÛØá‰Ì$¡_0‡bYFÁ‹s¤¾Î¢£a)á72¡ëaÁ¾J>·c_/ô­°¨± d˜4ð>wDlR¨š¸Ã]½É£?ï)=ãœaͱñ|<¾Ëxô· Í:\LdɾL,×ß:vÂG¯#ÚÏuгYr;ÌPö«¯ó=™!c:õ=ú—àþXÀ‡í¦¿•é¥#&57öDz-ŸÝydy¬³ÄÒXp¡0&ðà_J»%µ^­Ó{ø•-{–Âg¬ãÐõ£¸ò¤…k½}Cv³÷ÊëÔU›úͽR÷­:ѹg^u|:ÉpÕqZJN !¯¯dqÑð·„ÜŽ q¬ƒp<˜¬9ƒ “õj:ÿ¿ƒf‰ì<˜H¬#Xx¼épêÆd½æ ÅÓ„R±&«/á,vMV|MâGã]“õTt8b¬ÉzÈss%½ÂP@ÚXw¾Rýܸ+y@ݸ÷:ß³õ`%œS¯ÉzH˜Ë&&+¾.%Ëóª¯@ë6q€‡ÉŠyv<ë¤m ©\Tᯃٺ&à%ïš­˜€ñôžÖ8ëÜdœ«Ž¾Ð8bÄ]Ý´ôƹ f+bÃÇÚð¼88뺟ò­ A1[Q'n‘ì`ÍÖC±æ@“˜­¸©Õ»·-=¦ƒ%ã3ðöåj=›]“„Öh­›Ä†¹ŠSÿУޱ"et¦Ã¿÷^æåGø¾¾[gž+¦ê:JDÁ»Z¼³Ñì»ÖUãû~OÌÔSî§ØË®™zHÁ@HÐõ(•ðî;¿˜ª‡Ô¯­•¼kÒ×ceí—Üš¿ˆ|¿Ö¤8Äù®XY1VñÑÿF¬¬ø,Èw¬¬xGBÁøžXYqñxÚß³¢ÁæÐ|ïí¹ºîûû¸®êá¶ãàºúÆQÏ,XQZÖ3èQåä²ú0‰V;—UÄ9Œ’Îeõ —¢Y°VÕ¦C幢ǪŠeñ‹v×ä\»þ$ì²ç '=³ ÖÔöÑ÷«O¬©P­Øl>õ®S½v|±¨¢dpÌ’XT»Îv5kžâhµ|ÆåÜqpIjg‹EZ×ú‚Î’XUû6ðíìƒÓ”a°¢ò´£·z3?ø1K²™%±¨®„¾Ñ›õý]/M‹‚'Uˆ|Ñì»ÖT¸«¶hö5¯ÃÍ~±¦â[¹¦v[ ·ïøô¬^ÇëcÏ xLÓ§­5®©χZ‹¬°ùÅoíŠ55¯Þ®uê7Kô«áä`­©úðÍÝY¬©øFÄ}‚ù¾õ~R¼mkoümýy¹¨"ÏíŒöÅ¢êouk!Э«¯íbÃæ²Å·&žf?cUõŒŸw«êÁ(Z [˵ªj67$æ:ÊW­áÉÇLu+#VÕ®ƒºY«ê2_·ÙÞyÎø0%hk–<ñÞ¬% áûö¬÷ø\¶æQÑÖ®©õ/VUŒÍZ ÆöxóC×°.®©úÑC°Á3ùûêû"´j~™‚}±®Ål^Y G4ÓX²ÕÒîˆEÕkVC`൨ŒQÒxÍÖ÷ˆ?cEÅYÐZ¼ÛnŸ¹oWd6]Z×WÔ—y)òQ¬™êa«¹fêMß³†È9k¦ÞŒÒÞÖNøõ3^G$Yˆ©:8=Æ¥µÅä]n>W,Ão”ܱ >ŒŽ'#ÖÜ7ú÷ÄŠŠS•¸…W+ê©Ìá1i‘ùïÂñkÅ¿¡§#û5¬ã! ûµ¯Ó‘”è×¾¡˜D¿ÕJ¨D¿ ÜR1ˆ~í»õTÈ~ ‹?).Øoµ|VökŸSpýZ˜A%úÍ‚Aå‹ì×>§#ûÍfäeIökŸ3pýæ¯:÷„¿YG™fþfÁ+_œ€¿z©õ6þö/6Ž…ª}™Ž8à¯}…*ào–|2L øk_‰ôµªY’YmÖBµîá¨ð×°’ïó‚¿uªKÛ€`$vÉ^ëÔüÑc«åµNÍ:N|ð—‡Ã‚¿õ+%¡XëÔ¬£D`„¿ÒNÀ_C¤ ê–Aë>‡¤_9\LóÖdý2DÐߪÃèõW«Zÿꯂÿæ°Û¥+øo=áÂÀ¿YŶ„«¤Wü+¯-ño½D°À¿r)â_yæÄ¿ò6þ­KŠ«­àßz×+ýÍ¥:%ý•‡ô·Z‰'Nú+¯éo=ñ¥ ¿riÒ_ûÓŽô7‡XyRH«áø“þJwHí[*lÂ_yo¥7Á~å7 ýÊËGö«%‹ýÊËGö+“Œì·&Pp1Ùon¹ƒì×>GW'üegÈ~ V–A8ÒÊ>˜sü­Å÷šðW^tÂ_™d¤¿ÕÁøJ‘þ浚xð¥äWŸüW¦8ùoÝV©ÿʵ‚ÿÊÈísxÙà¿uŸ_å¿U’7ùo–ˆäÉ«ÎSù¯¶üWü7KNž$‘ÿê¯gÉÍÏ 0ÇT¸J*®»Z&Ï"Àú£ÆÅuŽElI€kØÏh§Çâ ‚_’KÁˆ¥õÕ.˜¸^Q^ùæÚªÏ¡p½8±×'®v‚+ˆ€9í„€ù ×ë¶0\XúC¬¿j\\& °OÖ/H,pÍ<7¸¸r>ˆsÊó–Ìá#Öß|ZZ/ÑÓÁ¥Õ£%aÙSQ ˜SH XZ&®—íŠ_]ZZµÅ&®’×VX(oÞ\[5Ä€µ?×V}aÄ€«Nð/p+áÚê·6°\Š ˜óŒ ¸®gdÀrŸdÀœT‚À5@¥Ç„Àüœg ·Ø¢ÀÚã À5‡È¤/×Ǹ¢ÀU'f)°Ì g¦Š£ˆ¶mB Þf§xÄ¿$ ®ʇT PC%ð@N +*˜bOEÁõ«x?¥θ*%ðpÈD)‡ƒR D•xg¥‚%l¨Â5ŠTgV’˜c!%ðpô)¨C¥’Jàáo’alR JÂîSR`©C)°Ô¡ˆ«S¤XêP <œ SR ¾u’ÑCêz!âÑ\•×kûìð“ —x8¤ˆ´@”4ªƒ§+?[’ó“)-/|n¤âC­P Ì--ðp”^i‡ÓI DÐÎÐÿ%–ŠùH <QRr`>aÉù+É^r¨â7»˜ÏŽjàá,R{¢I Ì%5°Ô¡ˆvâÅ‘ˆ:b?®¬àÃøÕ@±ÔÀÃÊ$¢™³Â`Ö±XêP,u¨ú#i=úØ·R<ûÍ‚  ‚‡¢[Z<”Ï’ ßQK‚úŽZÔ}[<Í‚ ¾±ƒ— è§iAÐÆ‚à!@ ‚èU8*‚^­–J‚‡îYô».IÐsÈ’ ïŠ’ nêd×Ve>°$˜u$ ÌPdE0ï@Š ÷@Vñ#rÁR‡Š`¹AÏ2+‚ÞòXô×׊ 7SV‰³"XêPôwÝŠà¡“i)‚š¾ó7kA,¯Ù= ‚yi)‚ž›VyZôwÀŠ`¾Æ’ó¥$è¯%ÁRBI_ÖG% z3bM°Ô¡&˜×’&èM£4Áò#j‚þúJÌwTš`¾ÒQ‡Z#5ÁC)- J¬hYÐ Ë‚X½ž²CË+·ÖKSË+7Ö…€³.ËG„,ˆ(¡,xÐs¢ ¼²ãˆ¢ ØClÈ¥uÐ`P¢à¡Ÿ×7O¢à?Êwd-ðY)*þ!.Wm ÿ0Wåÿ¾K>¶Æ¿!ÏáV¼((ø÷T1°Œ ÿ`è²ã £7¿Sájð,ÙñïTã_—é‹ñïTÌtãŸóašÿœÆü—%â¿S†W@C¬ðT"_`“7¹>¦4ýä*uÞVàñqÏfôX}ç@gº6†"ˆJé67)‚øâE ÛšEº6"ÍGüJxÈ4ÌxЙ݊ Ï ¥~Ž£ EP§JVuX–Šàç˜ÅV?jrgžZ’æ$êl1A S·“ ø^ò¢• ˆâ St‰A'§"˜‰ë¥ZØIEðUÄq)‚Eÿ“"xÙÙQŠ ì¹¥æ¤¾‡ÈâÔÒ=¶"ˆÇQíA‹œkE0µG)‚ù+)‚V5­Â4­r`Cx f,$¨óÇ”?šV¤$è×À’ Î(St;–/Ë’ EI‚~›, êäÐ’`þFš`þHš %k‚V¾¬ fÃÒu ¢ [¶(h+EA½Ë³ŽDAËF) ÚÜSª OcStSÔ$‘,èo»eÁ”(% v·Xt¤dË‚V©- úõ²,˜b¢eA+ZÌ_IÌ_Yd,â”e@`YP¢¾UAOF«‚¾ñT³äû1a­ zâ[t©‚žÁV¥ÍJ”ª•¢ ¢ ;cQÐv %Y²(èÁ²(˜íHýT\_¡oSw“(ˆÍY0“TAìùC‰“*¨ïGª‚ú2¥*ȱ°(ˆ/MH”öž² Ë‚)6JLðÈ‚ÃRqÞWdÁFƒÈ”¹dYPí¤,hв  A‹,HyѲ çÕ& ~Õ64_ê‚.°.h•Rº ïAÂàÃ)EäR„Aæ†Jaó,uA¿© ºé‚Ö^SÌꂚ2© êÝN]Pï‰eÁ‡6“Ve\‘ª ÞìTõ9IUPت ^þTùñ°(èÉ`QÐÍZ|˜©,EAwÏ¢ B;¥(¨å?EAeÈNQP wŠ‚¾M‹‚>‹‚²!IQÐÓÕ¢ îÓš ÇÆš ŒS¬ Ê &5A_[š »gQ6C© f³Òe!”š`Ö‘&ø±à¥&(‹›Ôý+k‚uk‚².KM0K¤ z(¬ úSfMÐ7jQðaN6‹‚~u, æ( úù¦ç1ߥ?J„dúûÖÒ^é/ÝüHi@ô×W( Ú†òˆÒ©yé x: £\OëG¢?x °GúcýµKgí 8tÖ.úk‚D‰þV$†øé¯á_‚ÈHmH‰ýÁ·`l®€øFÜ›ú× ¸E¹6…µ±+àüx7òà¢?[ü›þPGuì—L)E+`C´Kú[€h†ôWJH}(sƒè‘´è7Gú뗂ɉþV^Ú_þàvÊaüÁò™Fš„?Ô¹7øƒ‰rl$@>^'ü¥’@´Ó«G– ; €QXDoRâún`G,½ 2 €VöTú›Ïר¶ÇI©¶¡óu“ˆlÎmº)ÛнÀ†€N Ň”ˆÒÆÈpT[¦a¢ØF ªÐÌ” V:e Œ3ÊvŸN&g”¸‡Qد7Gó‘ØnKu¡"LJ«ì7«X»£ˆùA`ލ4ÀQi€íÖ÷D`ë Š' °t æÛ»i€­)O³4À¹Fò„B`s.Ei€ÍÙÿ¤6§à“ˆ{ñ°¨¶®ÀŽÒñ£*–ŸPl]ñh%æo¨®P4ñ#*€x Çæ ˆgèRó.¥æ¯¤6Q’ˆguTòëØQî‹J|Ü®Íp}z~Ið[¾U1VÒÿš"$QþËY&ùo Œ …ü‡mEDÊøjZ>v’ÿà»ýTî+—’þ‡’oólìì ˆÏ}”P„÷W¼$KËá(un`wt €+pOµ]׊%Åþ€p¯ö »CêiKI(€ç‰Õt^\«)@Dü‰£$ûž¯Aþ€ç³Ûƒ®ÏæµùâëÎ:òD(%ê}ô´oÊí`@ù´¥C`“+¶=uõô<™õ&]ì']ñdIò[?º6U¾ª®-yÈ%Pï…]á7¼ùâ¦>j‚\]µj§S`»Å¡r DXŽÝ)Pq¥Ò)Pûâ¨kÙ)°1¡I:6¦ûI§ÀlG^™C¬"¾ñPnz|é؆¬FC,Ý¡èQ§X.M ‚i€Ùai€xšcyE»×î˜%{˜¶Ù'°R÷äèçmŸ@xùG#TKùÚÓ>Ù=ùfg¨vD@ \”O >íè«Ë'0îÀùï¡ÿuE³þ—]±C »b@H#•ûÊ-Ù#Ð/Ÿ==£ì¨gkÀlFù#Êíò(ÿeíXJèØ" izž ú+õϹôôü–G »gÀl…ê_Ÿ_‹8ª°G ¾~éˆ$ÄA®r ›)hÇ“ŽŠ ª(îŽ qPлI?tPÐn·?žUÞ "%ð•y«•À¯oh¸B©Ý´údPÐóá 8((Î¢Ž‚‚ž”Žà)û1(hW¶UíNyL!Ó’N~ Ú•§LJ ê›# ˜§W6œÿ‘0$%ðêÌý)!Q% *€ã8YT`ªT/ÊJà •2 `YÄ/™vˆ2 ƒ«Yì7 Þ¤*êœU@|s7*ÌNVS• ˜o•UÀG>~­åH\‹B\Š* ô€wóÄ ¬äðTÇçò<§ìw¦cXç”ó©? ;R([[¨€¿°Ê¤ ¡áÚ"‚âG½Baǻݶ Ф RÔ!}ª€™ŽÃ* $R«€]nÇR»ó[X„oû//"àµ+€swxWëÏuЏ@„V»7Ðú¨À!×iuR"5U@ýÈ" •E@„EÀÙ›W’"àP‰€Žój°3nEŠ€šU)b/šžD@«~ÒFÞ: _œÔ{¾è€-뀰$Ú#ƒjÖ§ˆXéQbP¢¯uÀ9J B*!®ÔµcÈÈ ½I¯“ˆmk@”tÀÙÌ[A°¼€ý"Kœ÷rWûÏ5¢}%B[l» ˆMÆ®"Ï`üD* Ç3UÀCqK¥ÎçSÜ2 ¬+R´bkp¾ñ›õgyi-B©¢0HP6#–ó]¥ ˆMi‰“û¶Tá¾µ©€ÇÉÁ³ 0Šˆ0Σ4Gôسt¬#óýÝ%5ÒŸÿ.k©Î¿–G©#oê¨YF²$ó©,3–dIæ+ê°Gn5'S–”¶XVÚrI¶µ’޾5'S–d[*˶²ä¿:ÒúVb\þ+ó(=Î0rWÐÿâÿ3{Êïß…•›cfn™ŸïÞl×·JnÊ)’ÜTI‘ä¦\KM•Jj*S$©©š"IMe-6U+¹)§HrS%E’›r-5U*¹)§HrS%E’›r-5U*¹)§HrS%E’›r-5õ/äQ‡òÀééÛ¯ü-ØzŽ“Æ´ëxñÄÁãGûýÕ{¥búåÈß‚TCçU×çl‚+£fÏVŠâYÂø³äÃÉÕ"­ì6/êÌ äuæÁæsÌW€¿‚ŸmTYd3 VTûŽdêÑÁ±ëüÍ& ën°ý/rW"l?‘²ºEÁ·vŸãcHü•%iœupƵºÕWnì58cœ‘ëåã9â,YûŠ•@éÞÜwœÁÖˆ^g°OpÌìØbáÚèÏûÆ!ìæÜ)ç±ûÄÈ.KJm­Ê3¿Ï3RvúäÌœtló£7ÈξÏÁã©IšÈ»ZiQe¾àïZ_ÃÓb¼‘DâááÔ|cG$fº¸§#åüJ"‘%8xâKºNê:ŽGb&fƒî7NžV>"Yö{î¶VÛypô´NµßxTÏñ0/ÓÇI†\Ük²®Lñ(˜@·æ*¬bW‘ }ÍUe ›%+{óJ{1¢áÅ[‡ÎkóÞte{™ÍÅãE–oPËCK¹Y°ò˯'×ãÚOU:r᮹ŠOVÜÐû1Õ ³­ÎÖž˜«ÁB:L·^¦•Y|×W"Þ§¤=êoDÇX¹›ñud“]sð¿êWäerÞ«E‰Æ”á³ä[sy1âKñŽ;ò2)ÔÇõ8VŽsDy¿’Œ¦CxR‰56ï{G^&zxLŒ½¨—0™ÓÜöÀcp](&¥ÃMÞk‚wŧæ–„Ä—2~õ®¸š™E¤¯XW$Æà¥pîT³œ\ˆ£²æ*0õ^%gÁ„–š‚¯¬¹ª¼håŠ$Aë«:/0b®Ânw\=æjãÁü|½˜«‰YòÆ\Å©D\úŽuõº7çB´ž³•Ãk­°O9ŹÙkÍUô*~õ-š•ýlíf糕ýY§8²5öõÒÙf–,Œ¥­ïἿXY=ÈóQ7ÎVNˆ9(Ç–›ipeE¾¡¸ÔX++^ÚõºÍ§È•õ=bBÏyqÔ!?Ãå¦7Ø«GW"YÇYØ·ôÅÊÚN=¹ó‹•é¯×qÑ|ce…ò¸¾Äóþce…sÚRÕ.\ã|B¸Xî÷²¥˜ F"¼ZhM˃ò‹_]±²6„|XýYªL9¼ 5­ÉªcÙ ÎFïúú1×= ²¨1‡ÖµäžòUº–G&¿e¬²&JÎÄkùîÜ1§â-ÁQÿrœ’‹ÛòpœbüÔ g>c}E¹Ì_8™Y³UÛŽ N‘‘E-2À Ø33ܵNº˜hmDÉÍ…Uß­ IZÖl=#ÑùµÒ4½Û•^.¬úD^˜¤k²*ýÙ…QZ“Õ ãµåÃu­ÿeí½® 륑XŸå+N¼HZØëgþBúÁ5[•lpeÅáÝu,Õk¶Bnˆ_Ý\YÏ—Ï÷zbeÅ«=â^®¬8ò[€5}ÓfI¬¬Ö𦾣âM}ŽiêCTEêót7õ]›*QŸŸ›©uÎø©ÞЂú`gÛZQßј€WÔ‡*ÏF}¸R@Ô¢¾RÔçqô•ëú¼dúpoà¡ÏsÐЇ+"×T?GAŸ_CŸ'¡/_A_>nQßÛ”B}¥R_¹VP_i†Ô‡*w¥¾ì±¨/GGԗﯨ/{,êó ú²Ã‚¾|mD}|É…|þùðqe"_©Cæó[.äËWXÈÇëˆ÷òÙ’÷0—–Ñ’y//CÞ˱ïåÓï9÷‰y/gx¯\мWÚ¹µœºò^©CÞËÙ$àËÛðadž øÐΜEàËþørÊ øò+!àËð•kðùkjàË.}j‹ùJ2êA úJ_}YGЗíúJB_~Õ}ù„}ø”Q‡Ü—ÓGÜWêûò™‹û06qb#îó¾@à—*ðËIGðËy)ðs eƒ_~ ~ù ø¹Î?‘´Hì {Ǧýa #ü}ë þMQð·‚KGJçÙvöëX6bU·öw3<[jï#B£öw¾ ilñú õ5ŠçýrU—øw>·ˆ‘âßù‰º$þ7 %þÁ`/ödÿ°¾ü«Ò$µ?˜ýV¡ýÁ"†JÚÖ¬oã¿óyÅ`Ôþ–í`¨f俵°ý’ø7 èƒmþ;_†ç5ÿÕ’X«r8€Ë1Ú!žßñKÒßj¤‘c¡Ê' Ýï|éðoúïD¨ûåCý½š¤ûadbû(ú;¯WBu?Œ ôw> „fáí›ð*ŠþNÈsi¤¿ruÒ_é éWþÊ¥HåR¤¿|GDxàTõH¸‰xR¤¿ó¡»…鯔ýåk#úÃkO#ýáGˆ„?¼ñˆþòÁˆþp—°¢¿r ¤¿|¯EyS¦¿ÁijIÃ%ý]¯Lô—%¿‹Àÿ°‰ $þ iCÆ?¥3ÿ“ðdþtÒ!ÿ)¾òì6é¯Ôÿ¹ŽùoÐ(ùOé’ÿà%â?d…Þ¤?ü*1Ìù+ñ¾ÈÁšâ¿ü•øÏ}6ÿ)ÙAòŸÇOüçggþóh‰ÿJW+±ùo´ø^ÿ0Qøç*¢¿Á0r‰Øo„(üËá_6,ü»nÎãŸ_$ã_–ÿfÉC $þ]b¡Ç öæ-‡ˆ'ÖS ™Âz¯ÐNvžJÉXì<éž°wÊ0Ѱw^2¶ì!øð{Ne—°•+~%Ø;73O¬PaÁeÒ³©H¯Ó­,I¯1žQ¯Ñ)Q¯3V2QP¢ÞE¿•D½qʬR¨wb4¡^ì`+ë]t¨LÖ»Éb½kˆìÄzý•I©X¯7Irb½Æ ‰{ЏM)`T¸w„gMj}ŸLI{ʸšRßË@r‚=$\ ¦¥>ˆžUêˤ¬)õ½C¢aÏé-SêS Bà )Jê{i–“RŸ²å¦Ô§$¶)õ¹7+ÏÒi}nÙZŸ2è¦Ö§ÜÂÖú|ëÖú|)i}ÙŠ´¾¬"­OɆSëóZìSâÇû²‰}JI›bŸ¬´­õy¸L{~¦=Å¥OÚSÖΤ½‡+I{ð‚–E{ iaÚSÞĤ=e¤3í)ßaÒž²á‘ö”Õ.iï‘QiOI“ö”d/iÏuL{ÌØ˜°§”z {`å9Áž{gØ{d/lØóxö”0aI'“õ”^5YOYÍzJm˜¬ç‹õÜ=³žoÁ¬÷Dìd=å(NÖó`öÜÃ^6,ØS>΄½ü•`/{,Øó]öòꂽ¼-Áž®ž´§ަ=] iBŸºcæË†É|Ê$œÌ—UÈ|¾3_^zAŸÇ×Ч·:¡Oß„„¾§ ?}šá }zEú|iS_ÖõùA™ú|—Æ>}“û|æ>¿æ>Mñä>¿J¿lFà§wßàç*?ß•ÁÏW2øå¯~Jñœà§©˜à§t´ ~JÞ›à—¿øù0øeŸÇÝà—u~~# ~¾ Ÿ›1øe ÁÏíüJÉëéÏÜàçcðËÞˆüòRB¿,úe;B¿lGè§%0ÑÏ%F??Q£Ÿ[6úå¯Z.®ñ´Œ~~êF¿l™ì—UF®®½°ŸGËìççbøË:¢¿,ùru¥ö&þs_ÌJvœü§¥3ùÏÝ3ÿ¹?æ?_Ýü—¿ÿi×ü§¤ÉÉJšlþÃ+¾+Ù ùÏß3óŸ¶AÉJpžü§]Oàâœ?HK”Ä·â[ks`ØàʤL±B¾]gµíœr‘©„|°¡§LHäCØ-ºÿù¼é±4áSCÇ="Â2ô ù:¾o´ä¤sŸB{ù`ó»SŸÍ®M}°nôå „‹‰M}ˆðlÎ}÷% $õaÚ¾6𜽒”¾}ïK¯ûö}‡ }ã`4üôí;å"}ûÚÁ1·o_“ê!èC€„ݵï"E¹öaíþ¥ ߀%÷/…øŠâû.†âIǾKÒ¨ûÆ¡Îб.(»cßE7r;ö]—ä<9öaÿþKA¾ AÃäØw1W:öÁá—B|ˆºõm~}šýF|ù#߈]j¾Ñ†œ |øH$øP'0[À‡vv·>˜ooênE%kMBgŽ÷J•à=8iÆ)€xÏàÛxßçsóëöf³_ßw¨ò~%Á/Ö$<º÷ÒETÀ7cAX¾‹ƒæžtìûìËÀ—ýðá.è’GàÛÔ6àCÀŽxž>ÄCk›uçR$ |éAÙÀ‡'¦¼‡ ×|x ûfÞY~BàwøÆM~fêØä½trñ¥g¬ˆ!G¢€À‡€n$5^Õ¶YwÂí547š‰Ù+â7Câ›øpñøX“øÊ]‘øàsK;È >“£FâCÿƦ¯Ô!òa¸Þ ùðtã\EȇûŒwKȇpw„@"º,Å//Ÿ/‡]ÈW®NäõƦï¹ÄÈ'çbŸ˜M|µd »IÄç·Âć!½6×>L|ˆØ˾ˆu®MåÃꡪëª=¦|k“¿"ò¡dlÈ7QBäÃÕo–ò!êM Ž߯ÐDÄ|ø&~ÕÈs¼‡ä62ßxhÁ-æ›ãõK>¿é|#Âàóô6ðùŒ{ðyføpÙ÷Õ'|SM=Ð>|ƒ»zûð·BÁȇï|ö.«N›\ø”¸']ø”È.|/œ¿¥èÂWêÐ…¯”Ð…%5†ËJÓS)¯^;¼ør$äÅçÄGáÆçL?vã+mæ5gO²_Ö!æeWäÅç4C¢¼æäD¢¼ò£ ¼•èªÊ^æþæ•ыϹ„yÍ)„ìÅWJóšòɉ¯´”WJèÄ—}!å•fåÄçœB¼aHN|Îá#Ϋ—¢_©œ—Ùz™çG WëèeÎ^- ÐËÌ:Ž —-“ôjEzµ H/ÓËôÊ•HzµJ^æÈéeV‘^- Ò«íéÕv‚ôj ½ÒI/óˆô2Ÿ…H/³ÉˆôJË$½­äá\uÉ"½ÚL^­²H¯V Ò«%JçW$½Z!H¯Ö Ò+uHz¥I¯Ö Ò«u‚ôjI^- ÔÛJ>NWEñ!êÕ:zµN ^íO ^­³P¯6¨Wªê•*D½Z%P¯–ê•W€¨WÛ Ô+/Q¯þ*P¯–êÕkêÕœ,%±ý­íêÕ:zYG¨—uÈzµJ°^­ÒÂE"«ôá Ë’Kk«KÆáäJ­zóåèˆõꯞîäJ,yOX•ÄÚZÚ Ö+uÈz¥Y¯Ö Ö«uÚð„e`½Zç:~Ý:HÖ«UÆøu â^­ò[…À½Ì¾ñÿ÷.»¿ä؞ל§ØC ©·ân{HˆF=¨~P«…8À‘ºA<>±¼¾—åÈU•ɵÔ9Éý[‡oa‡ãëFÜ«’ĽZÉÚ°ÐÔ%ï•2à½*IÞ[$CYZýžÓƒøj™¾E’l‘$ðUI_•Lâ«M%„Ô"“øJ_)â«e’øj™$¾Z&‰¯–Iâ«eŸÕe’øj™$¾*Iâ[$“øj=I|µÌ@ŒZI@|‹¤ÿ\fÄçì. ¾zMß"éʬI_•$ñUIß"éʬI_•$òUI"ß"iÚ°wõì«’D¾*Iä+CòÕ2‰|µL"_-3‘¯Iä«EžeŠ|‹d(¯$‰|U’ÈW$@¾E2´cä«’D¾*Iä[$C;¶:öÕ"I|Î%Dâ[$“øJ5øj- |¥Ää½Z"yÏ%€{¥p¯<ï¹”]ù ˆ~û…¼¾Å«ïFä6©ý“B–žòù°[RaØ­ïBæs[zÆ¿¥gXq&µ1¤çyÐÑ1=Ï—Pû)¼‘Ô~Ñwèë ö‹§èbëYUò0´~ñX…‡´~%zhjý”SEZ?%²O­_Ý×û.2?ÎÆg¤¬8¬C€·ñ;Ü ¦’›aïÈa3õÿ~‡{Á332ïð.Ø÷¼h¾_¾’ùH|%°x¾ßå3•ñ`šjÞ‘(”#¦tŸ’÷á7Ž”\YóÕ3Úöûæ;,³C9ß)y&õÍ2GJb*‘{¾"Ýatʉ(“s¦}ϵHÆ9Cno€ ûÙ¶ ¹¶#gJ–vž}fFžíô¼ä˜y7KŸø,W3oBmèšÁ"æ¸çÛøûú;#ÊÏÙºR£Z™ôç™9*k‘vçi·áíö~ú<jã}FpžM,3ò­$®šþÎÞ•A·ÙTÛ§Ìì)˜J±)ÈuÝŽé$XZj‘µ¾v†¯eå¢kü|ê­l÷Üoe‘´çÊsÞÕ´¿Ü•Öfد²Š[r·˜Y½¸pånÕ ;”¹[üË®ãHÉtºÃ¬lîV톞12g™‘eâsÔZæØ­È«|χ#%óSç»úfN“ÒçÙí³Ë-wlV||çáfÍ+Ò׾Ǝ­úä7ó;ößÔüD¸#ÚŽ2ó“ï=ö{•ÃÇž¦:jz¤•x­çœVÙµL[*S<î¢Å÷ 2›š¶l÷xî´ÔÑ|Ž6ƒg”AŒ>ÍË ¿÷Ï}éÍû¯»>¶Þ½{–{ûD€öë.í<)zÔ‡Öq-ϧôîÙÎ#5ÿ–\ÓÌÂÃ~"ŒVÛó¡:Aï‰øgÓTg Vó=ÇÜ«¥ž–çtéakiªÓóÛ3Mô|~g½cFQ«µŒ‘†:Õ¾Íô¥ F·÷Ù#-u>O<§£-EÞgÔ^OŠg §Ž2âˆlOå~çJ©÷Ƀ5$[^Õ.ìU•é8Yü•àdõU'ë@¼‰çØ.ìU|ì~Ž'«®:vœ¬êóߣúRω“uà{Ï û8Y‹¤c¯êª'+´O0}nV|ÃâëЙ‚¬¤ñ`Õ5+‹Œ›‚s㹊#ý97ž«,²ç±ÚO˜ï>¡×š[õ=^³È¹a§â+É“϶H®;uKØsÞ'¶*V_¤wok‘§c§ªšvc§ªLŸ¾~惘¯ðsŽ [Ue–UYpæNå>ˆì*c¯ÍÌDCÏ*iب¬ôÊL¥šëÀ>U‘;Ô(2?^=‘ýnîÓŽïÄÏõÜØ§jªM—•ZOË3ÕMôËEc¾!”Šï4-’ü| Û2á\y,SN ­´ŽtûZâœgªÇt_y¦–¦ï7NT]óà@U‰†U³÷t©EÂ#UW ©¬·m8QuoÛΕµ'ª*nNTÍC‹¼™m©ç‰Z$8R;BD¼ownTÝ–öàHUNT :¶)ª™gଜƘwJòœ&í{íZ˜òŸËL+õµÌ¹i›R‚óÔ’‹ç©ê¹qžjˆä^MÞ?š”ÈðwÍÇq¥¿÷ù¯¤¿x?_D-–ÐB->ú'£þZØÄÒ_¤.âˆÚàfiø£g„áï@¾ Ãß GÃßè¶‚¿{#Çþž$#ü5hä êÆ¿0–˜½ýq%‹þF¸,$ë‘þvxè›þÞ²ûJ;®™þN„3ý…&âG…¿³aœ‚¿33Ä™ý®¼‚à1ñ²R€_ 90àgHû!ð ®Ï¿{Oƒ_¤ÕÍK~“-‰à×üÖà›8¯"ø=ðÏ6ø½ÿ_Áï¹sÄ}ïÍ>’û:Wž¸ïÙɲä¾gDz÷…šh¿ˆŠ‘dEò{:ÞàE~½“A~iüRÉ/BžA’äÙ6Éoª;*øÅ DV›à7ÓN u¿fÞ‚ß°êø5¥Àσ"ø…$©à™žæË­À/2r]À¼<¥F‡qÀ/A%¸/î8÷Ű ö9”¸/Jä×p_däºð Ûƒüî@ò‹2Ç~1åù- à7§o~aøù.ü§ö$-€ßðiøÅÔäcƒà‘4î‹»O#‚Ÿ ÁOá~1ð˜7©99£‚ßðø!øÍMùZ=ÁOÝ%ø¹Ÿ2tü”kKܧ1’ûf’¬’<§¢/werŸ¨¸/Ò—µ¬9¹ï-sæÔˆûæÐ² À/®ÚRòSâ1’ß[Ïý³‚Ÿ“²üJp_L9ØprßÌ]¨÷ECLî›ý=*÷y‘ûf­ysÅ}1ÅO¶Üç bâ¾R&¹¯t8±oæðÚ+öÍîÌ Eì›eòeØ7“`åýöÕzûœ×‹Øçd`ľÙ|ö)±Ï)âˆ}¾áà¾YËp_<‘ެ&Á¯´ò‹ùÃØWfÜ7î "ì‹6²Žä¾23à>'Œ#÷ùñCîs>3‚_™=€_ío‚_Yú¿r§~³­#ûow`_¹GÀ¾)I¤Kês’'$ö•½ì³í3±¯4ìsâF`_i Ü7×ø^¸¯Üp_™rŸ÷?¹OéÉ}³©+Ë$÷Õ¦’ûÊ£Ü7{œŸ?À}³õü.ð+ àW–À¯Ì ÀÏ·àWnȯI~³HÏ‹’üÊ*Ñωòˆ~µ3‰~µÞD¿rýÊìWn'ØÏùÉ~µL²_yƒýJë`¿ÚV²_ÙÏ`?çµ$û•Åø«e’þfÍGÅ¿ZfœåNümÎ1ø¯¬7ð_¹›à¿rgÀ¥!ð_é0øÏ™ÉeQs­'äÈM$„#qA@9[˜ïNÒþY¹þ‹÷£mÑþÅkZ²øÏ»‚xÆÀ-Pq^ÉAIþ‹€¼? 3R¾¬&ü9 %áï½"¿‚ý0šìwÆ{D¾üƒý"Ü5”(`¿™í¨UÍßï Æ`¿B:ÛûñRs ö{%Ë$ûÍ2UñçÔéD?'”!ûÍ´VëÏ)Ùôó”KÈWk}•4€ª™À6†ÖƧÔ 6Ü‹hØoÐ&§ª–5€¸4€;Âa à…SUÀṋ¶‹ÒÆiO ÐOš"ó^ŸV+ðÝ^ž |ÌLkÞ;:^ÇÄ{ñ¾Xm=Á̺>æô5ïq š÷«Œ{}µõ\$P÷ >¤îkdM©ûèUCÜc&UãÒ*šöФîã·t«ûD9¦=ä͵ºOjáÞN£ÍB{GµôœßLŸjéYÔ •öRU"ÚãgƒB{'œºD{ûC÷EпŸ÷˜« ¸G\íí') ´·E¢¨ä+ÑÛH{13€HО²¦šö¨–í ¹E{‚ áÞ}aÔÂ=½û ÷ô‘@¸Çw-ãr`›öxø™öÄ3¢½ qRhoGZÓŸ.¢=!íqÏ›ö|iÏm“ö"²M{;ýtE{´B0ííçWá·=4 %íÑæÀ´7í•lìi›Q¢ŒWDzê®HO%zúMÎó%=Àôh}cÐÓ˜z4'1èEpªjëYÚèÑ0Ä G+ƒžËô\Ao£Q»@Ö@ÅØ&y=ÎEµõLÅOr^Xm,ª>+ ôöÌ{RL=i…$Γ1›m=i#ÎsÙz^Јóde[OZÄÈÖSX=›§ôhzö7L=iTM=aØ ÊS‡eê©kHyêL=± Š©§ŠÈÔ“–Kâ<ŒÙÔSW‘ó4YzÒØÊ¦ž-=9Á¶ô¤1(OöO¶ô”}¨,=Ù?[zÒÀ¨ZzÂF˜§…dKOŠ˜g{QYzê"bžfÔ–ž²À”¥§,'eìIc5a^‡é‹1æÝÅÚ“ã´µ'çËÖž²ä”µ'GakO÷ÙÚS=”µ'îg5ö¼VÊ ¿m{–vlìɶ÷äV°½'ï¦ >Ù;|"-Äbð™oÒÕà5Ëâ“3a‹Oµ%“OΟM>9B= Ü&Ÿ¬Ù&ŸlÝ&Ÿ2 •É'mueòIcY¡Þ{T†4ùܩȓÉ'­ymò‰Hþ6ùìãËziv+ÒÓ¡ŸŸßýéçg uÛ{rض÷„•-ýü|‘XOMÙÜsö…^~¶Oµ±'-cONÝüLR1IÔsøù… vÞúù…d[üülßO??/5:úÙ ’Ž~rk£Ÿô>rô=³SÊÏOžòó‹CñXüü¢)püü¢;[%½éRM=« ýüìû@G?½µÐÒóøxúEçòƒ!=ýä"O?ºŸÈÑO¦rô«8PÐ'DŽ~±6ß4¹¯¾Ù¿3ã7)9QÑæÍ¼wÕ•¯Ó.O®|½ãÍX®|#o‡=ùÂûcõä‹êRÂ8.ŠcW¾z9ºòm²ÿ¤+3ÄØ•ùiìÊÇ6råcâ»òmWµæT6;òmôã‘#3 É‘™|ìÇgœÍ™DHn|‘D(MûèÆ’|'§_•t¤„€÷ŠÜøŠ~|!~|UóíÁ[-}ùŠ$}ù, /_,Ú|µ2E ]§èËW À—¯Hà˧ŒKòå+eàËWÊÀ—¯HàËW%ð8·Þ|Ê÷$o¾*ǹ%ðæ³„Þ|Eo¾*˹%ðæS‚*zó¼ùª$}Î-€7_‘À¯HÇ¥Jàs¾uêÇÅÆq‘Dq\Š>ç–0Ž‹%Œãb ÜùÂ[÷Fd8» ã¸XÂ8.– Ž s~9‹%äb#¹XÂP.E¿sµ¤P.*£P.–0”K‘Àñ܆r±„¡\,a(—"É)òTƒÎ"`$_ÃH.EÒ®C`$JÉÅ?Ée£ß˜"¹¸ #¹¸ #¹¸ #¹ <Ï-a$KÉÅFr)Dr±„¡\,a,÷±\$Q,KËÅÆrQÍŒåbc¹X‚X.0–K‘ –‹%Œåb c¹XÂX.E2´_!a,IËÅÆráZw,KË…ÏÇráÓ̱\øtu,_…X.¾ˆ±\øhW,*æâ‹ÌÅFsQÛ ç¢zÎEM)ž‹%Œçb º¨-t±„],a@÷‡]Š„'¬®bDKÑÅW ±”ô:L…tQ%Šé¢KÓ¥H|ÄBr~ŽXu±A]”àÄA]\æñ ƒº‰XHºXHÕEEu)±We½*9tÄBpúˆ¥DG,—XHn±<>b)á+ úX°.|%uX—aXI×E÷Xq]\†q]ŠdhËBÂÀ.–0²‹%ˆìR][¶j÷ª€¡]øìÐ..ÃÐ.–0´‹F¥Ø.*£Ø..ÃØ..ÃØ..ÃØ..ÃØ..ÃØ..ÃØ..ÃØ..Ãà.EÒµeŸjÙYËŒeºߥHš¶lV¢ø..Ãø..Ãø.EÒ>[Vñ]\†ñ],a|Jþ@–¢Â…{|ô]Ì<ÉT6ól©I·ÚO1K¤ö»`¸Z\üp [íG=®Õ~2½“Úï]¤{é¥zV½ß@B ëý®ƒÆ¡©÷ ýÜžúDéý6²#üübœ?L†Ó妛ý=¬÷ ûІÅyLn~r ´›£›Hï÷¾KÀ~”n~(þú‡ ‹+6¤øëbLùù© ã¦k"ÈÏO~ˆéç÷NðµøùE¶ˆ¶Úy>;Ô‰rô›Aí†o5ƒêDšyÒËÁ~~º—òóƒ›CqóÛÙ9ºùÑdÛn~ôî°›ÝnŠ›Ÿ<öèæw0¬ŽÜüäc²Ÿ~ìçG‹lûùé"ùùQK??Zû??®6ùùÑ4Ý®~§\ýèòcW?÷ÛÕÆêvõ“Û¡\ýè3eW?—9èÿiþ¢æ… §&7võc\U¹úÑ1D®~ïË*–«Œååê§}&W?º-ÙÕO÷A®~´°·«œ>ìé§;#O?:ØÓæôvõK+YùùÑ/Ã~~ôï)~~¼wòósµôóÓ(åçG ùù¹wôóãìÁÏOÎòó“7…üüØŽýüä$??yÈÏ/¶ñcaqÊ›Ÿ«¡›.äå'ß{ùÉï^~r “—ŸTäå'_yù©fyù©ƒòò£Ó½üø,±—Ÿ¼wèåç†èå'Ï&yùH¸f/¿T‡ÈÅÏ}“‹=wäâç¾ÐÅOÞvñ£sŠ\üT\üäER]üúêâÇy‡Ÿ«¡‡ŸMäá÷e{øé®ÈÃ/-„Šƒß gÒÁO~wrð³'}üøµŸ|:¥ú‹÷ÙTÙQõ÷¾Ê?‹…gÜõëïùøÉ‰S>~§|üä½*?÷™>~.C?×C?9ÁÇ3,?uFN~ºD^~ºSòòÓ$ËÍO7\n~Z8róÓƒÂn~\úróÓ”›Ÿë‘Ÿ—­ýüøÀ‘ŸŸzh??9ÉÑÏOý±ŸGZüüòÛÏïëä·Øxêé#?=kìãw0î }üt‘\üäX\üàp(¿áuìâ‡jäá'üØ]û÷qâìßGç\ù÷éØ¿OÎ{ðï+ôïãƒPþ}ò?”‡dÿ¾ýcäYª¡Ÿ|öïãUöï“7ßßðïãÛ¿/-Eå܇¹’oŸ[–oŸê sŸ} éܧG·œû´åÜçŒ3_ir«Ó¹O®]vîÓ-sŸªÎ}muî+î~FZsO—¼y'¦ÉëÛøS'ý}¯ABxIoÔ1E0ôs-òÜH¥ÔÛ‰t.*’QËRš©+j.«6óÎ`qMG‰6“µºpƾ!MoÃØ§ÃwYëãÅ«¦ßzßÀÜ«–\3*¹óõ¼’†<’Dœ‡« kFK5mÃnµ¤ý¬»*Œ‹7dÈ™VûmQþá,;-Ì0—ÝÚ·Œ¢æt3}ºtÔŒC=|ÓÎ}¹êØ®4ÐÃûó8–2×…íŠô2=\«˜z mÝÛqú K€”/óShŸÆ§…éál“ÛUeâ“R¾Ì,=<“z}RõÚPò¹ôˆ×j†œOGy*õùäY* —Ö})^ÂxhN»üjƒ iaz–‰RÈ£0üzDøÊݪ2mGJäÃy%ó=}–¹òªø&ÕÉ8•Óe~3ïGìö’Ž¥Ç«âs•û“ÊDõæ8ÎÜ«LÐs¯ÍgÇ^U3ï4j¥÷‰­JAD»_f!r?O-ÒnìT9ÒïÏrÑØ°S՗ѱSYæÜpªêœñ5ª-’§j‘àTUÍïŽÊQž×¡Œ.S“ÞÏǪë¹¶ª$Võ°é`E‘î“õ„D'+ƒ'+%/¹a¯r¾®'+Çpí>ZqÕÁ£•½¹N­*sòhUÍ× £P¯ºy´r×ã/¯dâg-Óx´ªæ~a¯ªÏÑÆµôgŒŸËͺӆ´ìÄ{¿~.c¸]i]rYßÇÀfåî“G+·ï}]جªçæÑÊßwÿlÖûy°YÕÁvb³êªx9+©~^AÇ^USãÁ^åEÏ653¥ƒÏ¾c·òªgçɪ«â«ÔX®:y¸²ƒÏµý« kÇæ¨ž›‡+'ùyxºªâ¶iÏ¢;§«Êtž®ê ŒzuQ Åm™›¶õZC µmíZ‹×äÚ³Ÿÿê¡0pi"t¶µ-Þ‘—VBc»´òàDUm™ Öu¾¯ K…ñfúc¦ôœÛ!͹KùjÚU0f¯ãD›ì¡¤­í°ÞU#=t´µWÆ».q¯Ä;ñ"õì*?—ýùc–uGöÒñx©l«`¬ñ6¼B/ûc¦@o=ï½Û™‘.ïá8G9¸F¼×NŒPÈ.å™qQ}ì"`ÆE_bt‹Æ<Œj¤Z½£ü£iˆÄv-²ºœËG¦Ö‰i`»Ö‘§Dl …Fòà® ø÷îhÏe¸£i½ènƒŸén?– »ý"ïvø ïö–fãÝOJãÝgÆ»#]4wÜGwÜswï¢ÈwSáÝ—bãÝxÆ»0>ÈÆ‰wÇóÐÝñ€¹Dw®tçjDwG#+%Ý©^ÂÉvå °]H¦v]l’Ä?¢ÝHB»˜™„Z¡]‘àü ÝÚ¼•D»È(µ%"í”cJh’‘ˆ´ É‘´›°–¢®"ÚU   €d¹‰vjZhçK€v'bQí,!Ú馈íb×d;d;WL¶ó˜Èv*#¶ ­GJÈvçž/¼f;KÈv¥Øî„C»ÙÎW‘íBM3ï°ØN£Üù*¯Üi2DwZ]¤;÷†tÇzMwióO…îx•鎹ÈLwo™žõî,!ݱǦ»v“5“î\3éÎý!ÝYBºs=¤;¦È4Ý©fÒ]DÍI2"ÞG'¤;U"ºÓ Dw–î|éNõî$ ÛiHb;×B¶ÓED» ’ÑN íx‘ЙBvìø Ù9Žd§+vúM°S£»ó$‘ìÎŒÕc°s‚n˜ÀN‘ë(Ö©aº/¬;Ï/ÖWj¢u’¨Ž'©Î“ê\1©ÎP/"չǠ:‰PG˜ŽÓ+¤Sÿ…t–éT ‰N ‹è,!Ñ)‹D§jžõ05Ï鶉ç´*ÅsqŽváKˆæxGsšIÁœS‚9uE0§®æ´‰sÚÑ‚9·E˜Ó̹fÂ`ÓœÆ@˜S5‚9ÝÁgB,ǧºYΑå,ËiPb9vF('IΕä4H‘œG@’óU 9!Éé“(§ ˆr¾(ÇEG’cO r® § Àqºä8­ rœÛluãô{RœÚÄñ¯„8í>Bœj'Äi qª ç+Àp*„Ó˜áôgœ~àü;ùMw’üæ>ƒß´÷Éo*A~SÉo.~³üÆn$¾ñµKüæòà7wü¦ €oÚšÄ7W|ÓÀ7ÿî?ËYürY7—_³ªnNßÏÉo# v@tyÜŒ÷-`O¿ùÈoŽ:!~ ¯ø„(ð›ò3‘ßœ3 üæX ä7Ç"¿)XñMq>Ho³Ö'5]Io3¶ ø¦|kÄ·Y&‹$½9fé­J’ÞÙô6£þ•Þfô»D¾¤·´îªº¹Y$áôVš½•Š“Þ¤ìæ¾€·zA›Þ_ô樤·Ú•¤7Ç$½9P$éÍ1Ios#[Oz«W%½9€#éÍ1ÿHo¹Ez+õ€Þj™®z9G$¼Íà’­ÂÛ¼KOÕË9BáÍ‘ o³žT&»9¬ÙÍÁÉn3ÐtXÉnec€Ý,‹ìæPd7ç”$»9fÙÍ9ÜÈn4Fv«’d7Ç»9¬•Ø-þåâd·SùÉnŽ–Dvs(²›B,ÝêE‰ngCt+%¹9 ÉͱkHnCrsÜ’›ÂÃÜ"rÊEÝÈÊa ÜB†àÆø â69dÜ Fà¦p67‡Ö¸•27%–$¹ù‰*tS€¡›ÂÁÝü4»yà`7o±›ûCxó¸HoÓS"™ø6ÒÄõŸ€o õ"|ó Àož>\)’WÆ ‚++€çqáÿE§X4b8‰çzq¥ .†•šXBœÂ¬ ât(‰âb·-§¨6‚8Ï Î–q¾/€8¯ëd¸2[„8Ï1)N¡†„q |DŒ+sLŒóLã|¯ÈqEŽ+Wã”ìX §|Ø"9øÈyÑäºIç;Œóí&ǹ+9_CóM!Èyfr D+ó äʉ ç;G+õä¼jrLS.Žó¦#Èyœ¹²rå!@’ó"ɹƒ$9$³³jåþI çÛ’+U$É•Få|Ó'Ê•¿O–+£N˜+óšSŠtÒ\itàÌÌt퀹RgÂ\¹Ý sån$Ì•Vs~TNš‹©ÀϤ9Åä#Íy— ÄFu£çj£‰sÑï³à\-1y®v ¦ÔÌ1ýwò‰âÚ§hßp 6Åa¡âx´âØU)á”ô»@œTw€8î!)á 祎éà"ÍБü˜:8y‡IW$ÐÁ…ä„VÇÍ{ší‹nÜZ¯“ÇÍEíÞÅ㇔p R'%\øs&vR 7ò¡R”páãb„.ÖD¾S 7âåãGQÂwý¯&–1×bbÙ±Ñ&–^9 &–.BKØ3Ò¾ÒÍ@ 7Þ#åÎ2´¯ì%PÂiýK WÊоÒMÓ¾2n{^EûʶCkHóÊX*‰N4¯|6,5êà8î‚£9NsCŽÓýÇÅ#: š8­kiâ|£Äq¾ŠwÁ÷Ýç!‘ã.ä£6ÇijÄqÒ‡šã4¡â8_EŽãd ãNxL›ãî=?Þ˜ã®AƒJ(㼎ÉqÚ TÆé1Oeœ'G '‰@N÷[ ÇSg1NÓ'ŒÓZÆij„qá¾¾¨ãbÉ[¤¸nᦸ+C˜ât{©Žó” ä459mœ:C³€ w!¼€ANõ ä,!ÈqLTÈy‚Åq“0Ns%ŒÓ}Æð¼7Çiˆã4L*äfÔ PVÍ–8ÎeÈqZkâ8õ§ý"ŽÓŠã,!ÇYœ÷&ur¥)èäÆ w}±œÖYîD°œf,§‡,trEJ9÷ Z9?Ž •ótC-WZÎ1µÕrJkxžíU/W¡˜‹Mtå(tÜxä9•'Ï©݉\Ï: ”@§qèôð!Ði…$Ðiy@9牀v® è.D(Ði à¹á_¨óôC;ç ´snÚ¹"г÷tZÕ: R=ç©€~ÎóK s 8ºjv  ó$Ðq2~‘䧨â¦Q…¸÷)Dś턚BNî?*ÄEªˆÅ’rD¾Ñâ"qHõ“;âÂL2ÛÄíýq¡Ù(Џ·»ÁŠg !î¸áG† ÅK!ÃHj† m Ì&qÖ½âÈpa™|F†;‰ ç2d¸ã¡ÎeÈpñzºXRFÍÉ‚¸s[-)‹€¶cÕ–2} îôT#ǹ%rœF.Ž 8‚WŽ×LŽs=ä¸Y’Ìqºâ¸ýüpÜjH9wa!Nó)ˆã Ã7tŽÉpBÈâ¤PÄ¡Uœ[%ÁEü™Åˆ²”!Á©¸ÐtV=\©F§28V#~ÓÚÀíHa€sÅ8õOç2¸P%/þqž:œ¯ÀY@€spa„ü£ò;c~Cã[6¾q”Æ7]Dzc_Lo®†ôvôj#½È…e|ãÂ4¾¹ ñOã›%Ä·wI.ÞqqSÇâ7"‡[²ð-‚¿,îq#ÔÀ‰]Ä·ã šßÜñ5ã›ú'|s=Ä7ÍŽðÍý!¾¹-âï¸ñMW ßt•øíØè…F~ãü¦‹ß\-øMc¿éÞ‰ßB¢¿Eð¾$Gò[²Õ?~sãä·÷*ðME„oqW|Ó°…ojJøvl°œ$½iQßö†qá[¼H/¶”¥)â›Öñí8©ð#¾qP¤·}§Ñ&éM“%zÓö½©iá›nƒøMs#~Ó¿¹òçFø¦I¿áÐ0¾¹%ò›/"¿iáˆß´Èo*"~S‡ÉoªWü 5¡šã‰Êû-~Ó(ÅoÚ 8Ý:œ%$8mVœî•n¿ð‰Kç2$¸ðaI¬"Áéî‰à´rDpªG§éÁi¿’à4\$¨\üã<©"8WL‚ÓŠà4…"8§“à"ãg¢Ð¶,-œ– Î5€à\ÇõJ€‹È°It8õœÇwnãéàüwœÖeܾ¨ãôè ¾©=â_×…oñ¾X +=ÝÄ7 ›ø¦ûJ|Ó\'¾ùïÀ7M-ñÍUß´˜‰oº¡ä7UJ~ÓXÉoZ]ä7M%ùMý ¿ñù—ød”¾ióßxIo®ô¦qÞÞ3ÿYèM7”ô¦[DzãHKò;À©!«”²+9¸ Ý8¶‰ŒmÂÌ2ÅýÍÎntkt¬£ûŒìþf Üß, û#RËý©ìþf ÝߊûŒ–oÿ7uXþo.Cÿ·"ž%ôÓ0åÿf ýߊd¬ñ×íg à$‘\‘ŒŸKÅò€s¸ÀiœróEt³„>p–ÐÎúÀIWüõÅŠ²v‡>p.C¸"銿{HúÀYB8Ý ùÀ¹ }à,9—E 8KàW°Úg¢%ûÀiFåç«èW$°Û·„>p’ÈÎúÀ©-ùÀYB8Kèg }àŠ¤iâ-úÀ¹ }à,¡œ¯‚œ‹ÐÎEàç"ôããÃ>pœeûÀ¹ }à˜Ë>p¾Š>p¾Š>p–ÐŽý±œËÐÎúÀù*úÀ¹ }àÜúÀ1¹—|à, œ.¢œÆ)'8¡œ%t‚óUt‚³„^pnœnp®‡np¾Šnp–ÐÎõÐNùÁ1„á˜.Ížp–ÐÎ’¼åª„®p–ÀÎWÐÎzÃáü²3œt†“€¾p®„¾pEg¸íJÃ{Ãm²n¤7œË>])ññú râ2t‡³„îpÍ凄uö†cþyÃmç×ÎEà §Jè G¼á,àáÊZå §Zå ç2t‡+®’ÐκÃY€‹ÈôÏ¢€óÌÈ!Î:ÄYB¸"ÁázÒ™.q*BŸ8 èç‹èç2ô‰ã—}â\†>qEÂÃõüœBØ'έÓ'޹íg âÔ9Å©9Å…a_½â\†^q–Ð+nÛÒñ[^qnŠ^q–Ð-N”_œ*¿8_E¿8Kèg ÓR¹¥_œZJ¿8ÿ~qþ;üâ\ŽqEžqê*=ã\\ã,€k\´ŸËpÓ5·oœÿ>ãüwxÇ©StS ºÇ¹Üãt£èçÌP£3ùÇ©ts+÷z<äüw¸È¹ øÈ¹|ä\>rª”>r*A9ÕA9õ“>r®>r®ã\f‹NrÀIΦ#T ð’{ù-’^r./9÷nr®~rLuú’ñËÕ°jçžÌ båÜ@ýE9w´LÚ9~r.Ú¹ñ‰s"Þ´vnPëGíœlÖ¨³€ê9ê>¥ž;Ûâ'75°`/jç˜)Èê9Z.õ>X=w4äzŽêc«çh+`õµþVÏQjõ•üVÏQánõœ[§zŽ Z«çŠÆ 'ô/RÏ©qªç¨5·zŽkVÏѪ­¨ç:ÐH='«;©ç|Õs²Õ“zΤzÎõP=竨Ÿ£Ù˜Ut®[EG¹Ut4Ã²ŽŽÆfÐÑQ3o¬I©£ÓôIMG½yQÓQå(5¬`¬¥Ó —šÎÝ¥šŽ&XVÓ±i騀·šŽvVÓiõKM³kéhOg-«¡–.ÞšÈóR—–ކ ÒÒ¹bié¤Úƒ–ÎõRMgÓGªédï'=Ý…¬IÖÓɈBz:—¡¢î-Ó«»\1·‘¢ÎõÈÌ’¦*RÔ¹?²³¤ÍŸu®‡Š:_%;˾:I °µt¶s„–Ž“e-« –îBZké4lié45ÒÒÙ€’Zº©DŠ‘%̽lc‰ü ÅÆRËÆ’c°%-{lc©22²ä°¤¤£ŠšF–°+“ŽN«†::™ÙØÆ’³'Œ;©¢³±¤L,1hièN$Í*–,"ËñÕÐÙœR–\UÕÀr,ÑN|Sl`IãS©è4/RÑi ¶°ÄdICg[NXžÕQ®˜rBC§E$ Ì© ;‘)¥˜WÊ8Qö•€ ,Ç'‚e5¹²†ÎîUK¨e`©š©¡“Þ–ý«¢s=ÅÄrÕÐýÆÂR··ZX¦ÊŽ–œ,Xnôy£‚Îf2°d-ÔÏÉàÊ–²¸ä‰ª"ÅÀr…»R†ê9×,–“ ,e)KIŠåñÄ7³ÚW¦™´s¶Ü¤}%²”ûJöÆö•ã«“qŸí+eMIíœæXÚ97íœ&‡Ú¹xÿ+Ú9ÿÚ9õ„Ú9 h_)SGÛWnÛ¾Ò¨ç4'TÏ©ã­-“Hõœ ¢a_É•N þ^ ,¯ú¤XKBCGc*XÒ$]–Û¿²Z\ÊÀ²(è4TÐiTйÚWî𪤂Î6šPЩWTЩ*èôȦ‚NNTÐi TйÒÔÛw8ÈËÀ’þÅÀJ@XÒâ–²Ù´å]Ñ®X\BEw!©Ž ,›egg»ü¦¦?œ`'gÛóëü:ïDü{ÿóß)ÝÍß˯óþ‰¯žöÌ«o±ù>øÀùùõ9ó >ž±Ï« i²_A~~ o×x>Œ¶åç×pÏž—´=?¿¶+)íóüüÚÎ|¤¼‚üü¯Ýó÷Û¿è÷;Ðù"0Ú{‹ïEpÏ¿?¹ÎFäIŠ~G²ì6Oª*ï<;^ÉYb~5­o 5~d‰>ÅøÐ4õ³£;ccoùhÄwíh6’$Ï^ô0JÁAÏŸ9×8ºÝÏt¯xßVÎŽn>^ÜËéG"ΈdíÑíH¤;çÿÅ•Ùm =üƒg‰ù«mÙç+ßyGÌP[*è÷§Ï#õ’ˆøý¾tlõÏá-rçÍšŸTF$ŽÚDL!ªûôá”гÓ*qL§Wõqº¶,MÄb–Ÿï§#<œŸÚéðß—íZ'zô£ÎJÄ%¸ëÌϸ 9ÕóesßfT¸ÒËW¦³¥c!I5$›y%ǃùÌŸg*!Ë%W*4âóäÉàŒ³’;•ïÕHÁTο?çg¢÷wKFøÒŸôì¿%=·×ë+gö_eö ›³¥.8$=÷žÚÚßù£l•W¦¢yÕ€$"&çîÙH:7 ËLéûŽt¡Äû¹¼‡_Á“úÇ÷ÖmèÞûŒ8׋Ú=‡À'Á+égvïÊ'Ð+‰!9ò³OHzvïÈ<ûvlwaÏh¯dÚĦÏZŽ#õ¢AÒ×+ÎÔ@òAöJ®TA¾O²’;u ¯0!I%d‘<©…|FÒð+i©†,ezê!_Éy@’ŠÈ òœ¿j–ç–ªH÷æ SÜò¤}%{ª#Ûž:™W>"Y+ö<>ŸÑ¿ó³¥ž+U’¡]ÊÙ:ïÜEò¤Rûë|r?ý'þ>˜µíýÝS' HF*%Yøóçµ=ŽMKw¥SQÇiLRÇ©ƒRÇi& Žã=‘6NÓ mœŠ´g^éâÜ0uqµtq¬Eª8õ_ª8K¨ŠcKÒÄ©^¨â4©â4d©ât0J§1J§{"Uœë¡*îJãú¢ŠsëTÅ]©‘*Nº%©âX¯UqìŸUq¥Tqᬖjâ\15q˜`)âJKTÄYBEG`Mœ%SWzMÜÝ2’°5q¾Fš8ëÔ¨‰»2ô‹5q®Yš8—¡&eþNžaZ¼\T3ksAbZ|J«˜NßiL Kâú¶=÷YÞ ™Š§`Z|ÁN0M­Ó"©P‚0-R]¥ 1Íý¦É<1-ƒÎ‘ÑÝ™ŒÓÒŒ%ÒÜŒ¦h®d´rI2š/£)8M£“ÑÊß“ÑÂÇdË¿gTM„B$¤)5!-|w“KiQÕ€•¦Xy„´¤á* ͤyæinvBZŒfŠ[cTBü=)ÍÓ JcÄKBš'£áîÐÒ“€=º KÄAšxСçJÓÉŽ›ÛÌ4€¦¨w4ÝOšú!@«’4…‡ 1þ¸-6À½C2rõ"Ä¡m¼Ä´°¦£+7­Ö’Œ6"P:“˜’}1–ŒÝHÛC`Ú{“IB‰iä0%‰i!¹í[•€ÔâëÐj,9ÏŠö-î ¾Ð‘ÔÂ-×€ÔâAvë|:Àœˆ¤ÆüË&µrHm¾ã¦ ÏšPÙ/Ê·Î\vµò æ†ÔÊoZ¼’À¤V$ µP@¯¤yÅÐH-tõ0±©…¦Š5 Ú»=;Ê€ÕÂ?mMV £‚•Õ"ÔW`5·MV oUÐX-´ð«±d©°æeCX+5Ö2uö”€ÖÆ.6­•«&­Í ù´§æŠka™€2Àµ¸é€àš»G\£±´qÍ!®ù6×"ÚŠl¾³D6W bs÷Hlå¢v,ƒ&²¹›6¯›»K`ó%°iblî ­T`s÷lEr_kC 67`+E@l~DÙéϰ°ƒñ´ hu4QM¯ï´÷FíUæ:h®€ÆÔ7ä3EºŸ©ðLT<ë´°¡12¶1¾EhŒ*.Bc6š 4&Å¡1öµ :h.@S hé!F:Óµ€3ÆWœ1õ‹à ©RÄfŒÅo6;W76Ñ…ØŒ©`ÀfìÑÌš1²‰ÐŒ©0ÄfŒ/8ÓD“ÏRÜxv¥^XxÆhÂ3žéö¦€[ÛX¢˜›ÎÑÙàctÆV Ÿ+œqeÎÞûNw2ÐÙÞ ¤³Ò8è «™pF 7œ¹ØŒ ÜlƤf3nD±Yé ÙŒ€o6ãW³_lV:6«m]+“‚Í È‚ÍDÝb3r¼ÐLä/4y ÍôÁAl&à›ÅUx šlVpl¦gØ,€›6 [°Ù ê—´d³Ø&+›Ð›Õš“Í hƒÍ hƒÍâ׋ad©l¶HFöO=›E-T€%›Å~€ ÎƒØ€ô`³‘ShV‹Ü»GI¢Y8Ь j¢™R«‰Í¢Õ|Éfz®‹ÍJK`³25`³R3ج^•lƒ‚Ê+Ѭ44+÷hV«¹q<^¸æÁùèkš¾`òšŽO˜œOᙾ7Ïʘ€g:‰…gúF)>+_Dh!éœ8)îï hQï±Zù^@«e’Ðj-IhžOZ½(-Šœ ¢•j€húÐD+3LDóG šçˆV¢•›F+ _Œvñ“­Ì9 -º› @Z™-Aš¾SMH«× 0¨ï (ÍC¤•qƒÒÊ|‚Òj„Aò|‚ÒÊT€ÒÊ"¦•!ÓÊš˜V;œ˜VK$§ÕÞ$¨•Pó0ÁienÀie˜µ*AL¤*\H&@­4u¯KœV+y:o,8É÷œV¾S‚Ój™Ñ?7œVÊ€ÓÊ„Ôj™5wg‚Z­ö:¹ÌP+C©ÕZÕÊm«UI²Zi9Q­V“¨æ5“¨æ¦‰jêIMµÔÜ0A-jm(smë£Ü¤vÃ@‡¤VZzŽõYIPóí'¨•‹ú½tá@u‡Èi¾5¯‚škeÄ w æ]aPƒö©¤»‘ Û<‹›ƒÒƒþ0ò`£s‰<ØèÏ!6ºsȃ~ò`S z°Y6_6 àÁf<Ø,¸×¿ÓƒMz°I@6øH؃͂¾xõ؇%äÄ&Ø,Xª”›çÒy±Y ëû-¡ë–ñ=ôcÓ%M¦÷[å´R‚~l ÙÝç%ðcãßåǦ¿ï×Ú-ù±Y “{ζv\~lÜÇÚqù±IðÈÚ~«!GŠ ¯5ôñéøx–Ž?6Kö}ézñc³äx–Î?6KèÇV$céñc³äùô¦íßþµþC–µ\üØTF~lEÒ?c›%ôc³„~lEÒ—E-?6— ›%ÏöƒüØ,¡›%ýüöolß1ÐMù±Y²¯-É­HÖ–åÇfÉu|F ?¶"iŸÈÍú±YB?¶"iߌµ¿òc+’ñéŸüØ,¡[ñZû]?6KèÇfÉñc³ä÷ýØ(¡[‘ü‹û±Qò·üØ(±›$¿ëÇF‰ýØ(éßXüØ(±½ËìÇ&¯µ¿áÇF‰ýØ(±›üÖ~×û±Qb?6JìÇ&IÿöÏ~l”Øm# mŸ1È¿íÇFÉñ݋Š4[üØXÆ~lÇ¢W«eží3†âÇv,ÌV%öc£„~l¬e´ÏŠ®)~l’ŒOÿŠËØû±I2>ý+~lÇmUÒÖ™(~l,a?6JìÇv,ÚµE2>c(~l”Ø’sÿô¯ø±Qb?6JîOoìÇ&IÿŒ¡ø±Qb?6JìÇ&IÿŒ¡ø±Q²ŸŸ1È­Húg¥ÀÍ%®ó3†âÇ&IÿŒA~l–Øû±IÒ¿ý÷:ú±ù÷¾­wÁ~l–÷:û±Yb?6I>ç«ýØ\æ9Ö1Ø‘­HÚw ý^ëÇw c|ú'G6Kökc;²ÉøôOžlü<76‘œŽUGõGjàÞ×ΧÆ(‰é­z²Åbh•ð"ÅE¯Á$ãÝ:UrÔÀE ܹ§yã$¼Wð$›K7=„wFNŒ§x²MÁ%Éù“*¹8¥ÎX\ù{Þ/ïð›€÷^1ØÄ¼3RjÅHò½¤s ðÞ{:ð^Áù³hàÎ-¬€ïfi­8ñîœ):~€îÞê† ™t7ÇЋ…ä‹¿ É3èbº›%Ž¥äŒÝ+ÌIw³‹9qIwo‰vœ“îæ0O˜DnqAû‰Ø“î΀œ 1“t7ÛH;ͤ»yÉYL$çÀ·¬cÒÝìø“—Lº›‚£èáê%“îæ\BÙ7é®Ì~Òg?à® 4á® &ܽyd9ánmqc;#ÓÊÉ“#×ÉÃVTÄøW7¶Ù îæÍ¥%å„»¥­ ws‰ÂÚ.àn¶D­à„»¹F3ÉWr¯ª¸Wræí!ÜÕzîæU•íæEÔ²AÇG¶›»ô®š¸W²3^ 5qï+ëUüÙF7ëA—‰5¦š¸®3‚š¸ˆj Tqï… Uq}£I!Uq¥ Tq÷tUÅEDÆªŠ »U÷>žªŠ›‹ùš¸û‘~š¸w=~4q‘–‚v“È}Кš8>Z­‰ OêÝòÃa©š8&“¢&î¾`JEÜ}þ\J*¼¾õp Éo=óXÇ„TÖýû·–Џ÷!y*â˜hЏÒq¥ÌTÄ1‘qÌžcEÓ XÇ,1VÄy TÄ1›qHÃ`=“XçîPç‹ ‡cÊêáÄj8‘j8æä°ŽùIDuÊXd=œ{G=œ‡D=óªYÇ4BÖÃ15‡õpÌüF=œ{L=3gXÇ|ÖÕ2ÐÃyTTÄ1mŒqEEœë¡"Î=NEœëÕU ð>QÇDGVÄ•† ˆóÀueeQçDEÓbXÇœ‚:¥ß "ŽÉ{¬ˆCæ ëá<&*â<çTÄyñQç!PçMGEœ7/q¥(âŽIǬÓÈ¡Óæ•F®”:X¨Û ‘sÿ¨‘s=TÉiqI%WêAêòÿx‹9±ï‹ÜÌcufêƒÿæ/ÊDð¯tà¿W6ƒ¿úï?$üÿçš©@Ù ÞõÚ¯÷öoÿõñoÿ«?Yùÿü¨r'Dø¿þò¯Þ‚Qx6óžŽïs ­ü·®åy[A5¿Lä𿯽¤eï)ˆzþºðÏ¿¾–ÿúõ°þkKÿú—µGtôvNÊßž“åbýó¿ûË;Î:Æó—`wn׬ü¨SñO™ŠÿÉíüßÿáwrYD]QÃÿXþü?|ºú{I(èRÙ§uç€wž™žh®^Jþ@xTTxF­), êŠCøjµ2Hþ¾¯(jˆô¼Û]k€ä×̸ê:¦›X¹ ’U›ŽÒ‘q_† ÉûtƒÚö÷=²=µ6H–¬XûÞz~éR¦•ó€¾Li± © ®~ÿ:—b™?™ë8¦*^õãwI@5%%Û ~—$VGäóíK-”ÔzRVk¢¤ÔõÎ_~÷ˆ))uAVê’ä_:1Ö~ìóàÏ%ÆêÿŸ'ÆúÅÙ#úþcIõYos%=Û²ÿêºJÚ+ÔU“c±.—b]K ­¬«&¾Êº–ôX¨«”B]k-ÔUR_¡®š ‹u¹ëZÒh¡®’ü uÕY¬Ë¥X×’H u•ôW¨«&Éb].źþD’¬}2ë¶Y²þ‘§é_ó\üÕ³ó¯¿Ü=ßçéïìžßÔõ‡3eí‘©ø=§þÓN•ÕKª¬þ[o)ŸTYïDöú`šŸý“:¾fz«¿Ççû{°ñùÆÞççúó˜¹1S/þåÞÏxñ?ߌ½_ñÞž¡;Hšéw¦Ü»™g¥Ë{\Ú ežLÔ×e€Øó“ö1NÆáŸ)ˆò•!?$ï=¿kÏï|èΈ—Šãdþ‘ŸµÈÈ“'vx'Äâ ø ÉÈ—“ÎA…kÏÆ )ûÈÏÚo!òMàd´u!sXHÆ,sñ‹ê>¿p¾’ûâ¨ÆsÍ1¼¬"m&ö;ßyl”Œ(±Ñb2>!_Y/¸nĤD½†¿[~Ö>_ÔMª|%}Žáá÷èc›ßµÏHo/G|¥ûÐi‹}lù];RH'+¿’žc8à®~l×ü=ðÍåØî©ŠœÒ$ó»öß;o\óLÔù0–õ±µ©…:ã{4®êS =~ÐöØr üÒýJ¦"*îLf£:^ì÷áÉðùñÊpæ8éÇ~L]Ôù®Ú\诤g‡óöû9ÕQ15˜ˆ}~Ùž rC-÷–·áÜ¿’6»¦<ùšûnßüþxìóÃv½ {ß>waŸ¶g™M©˜B–îóÛö{¿ðïÀsJì-K<ùñäˆ];²ÈÉyäT!$S;¹È/T{µ‚¯º¯\è²pÇŒ­3ÏÑWÍ/Ûo=ÐþˆGU aï¼uÇü¶ýÞ:~z8Ž1·?žÇü²ý nlçãܦžê<øéæ8ç—í·ÞÁ1Ä1LèyäF (ÊœOÒ\ö^É57tdj?ÑÖ=õTµÌ=òspä±~ãØéLuœm>^ÏgŸzªã88ñE"VÒÅXHï¤?ù@d²®ãÚ¦žê¸FìýÇT‡6%Ÿ ¯dê©J‘ùiû0ŠÑû¯©¦Š[˜¾To›ûÒò5¿OÉÉü´ýJ:4Çõœs¥––/…±H:G€;uõ|•ŒñÓ8ç.¦Dy³Í!„~çê­ñžc87hyŽû˜-!ÔëûûÜænD@ ÉTGÿ6ÔrÝ9êžß¶ß2L˜öÖ¸ýDÍxÝóÛö¸±ãª–¯ÑñÁ1“tæ}¹ÑøÈ÷êQ†ÆçÇíÙ4É7ʽLÖ³ç¹z#iHò` |væ9‡p¡–óú á¹p²²{Ï•ëyòÉöÜ ~ž,õœ{Þ…" 37|ßwÁLþû®}¬Š6Í9æU¹üÒ{ŽÛ3–!´iÐQ·a›u!µiÒ1mÚṫ¶GŸŸ¶çdeÇ£§UGÔƒÇjŸŸ¶ßÇÂÍ5ѧ]Ç|• ú9oKçIÑÓ®£Ü„>¿m×Þô´íxø«Í ¦=×M¾7e°ÚõªŽ í¶ÒÀãx˜Žqúy´eþFšx”iä5§£c8ÆÆ ø®0ÒÎ#vG¾½ïsÇgŽG{” €3Ι Ð35­ç²ËÆü¶]Ç0Òà£,®1¿m¿³ópT#M>¦–’q°‡ùÀ9·0úˆz~æv~k`šDŒ\eÒìÙ–-='+o̹¥áG\•o!ç––ž¾÷Õ6OÖ•C2rŠù0yϧy²Æät´Õ®ïúQ'ëý=²\Jï+óy°†u®Â7š+ãþ£™E€-^ÍÎåÓTœa@*¸«(ÒÍDÀC ’ˆ€ÓÄ®VÉ€GT³dÀWr ’0 ð£0DÒH¬†‚ ‡ÂÐ_É(">wP\…ÀWÂè^€ÀùâÎßP< „è.’=CO…·0 !ºãYžp™¸\…Ýáe^!pJ%zê]S'pîÎÐSEò uÇã ¸ÔÜFþ¾ÐvÏØS¥¥‘Á§T/ °Ô œ’^!9´§äÈøS¥ BÀ•šÏÎ1°æ ÷¥2ଖ܈pñ€Kž @Ušn7ËPÒ3Õ»Žçϱ±ÿlwtÎ/ÙmËTn: °6¸JúÒpà”4Ô‚p¡¡È#' °öfG¸Òö“!¨J͈WÚîÛçìˆWZ7ÇÉpE’Ro"à"9®ÏMH¬m'.’«q lé¾8†»2`]#"Àyv’—Ö®Ô3ŽÏï ‡?eˆÿÆG† ÒÏÁ©E“‰~µ‰D¿ErïŸéOôsµOFŸâÏv­¥ûþ™Ô„¾E‚Ào¾*¡o‘ ðšIäóO}ãÏ3CNyj®kÿüΈS¾#"¾•2ÏYçûB¼·R õ:ßÉyK‘!§"þEå¼:°ä¼E²ßŸ)ÎS3 yµ™ÁÞŠäºÑuÒHEòlè½%íÛ¹vcÖU3" ÉØ0÷ª'M˜Š$(où½ßûÀòçÑêÜ'ßÕV“ï–®%!ÉÝØ{Jë­HÚñéýƒhoEÒÛrD{s‰¼U2Ø¿œJ¨Ë¢½ɹ×UpWwJÂ]½C ¶ú~Ì6Ä3.Õ>ëêhHK{t“X>c|¶Ý:W +ÃÐÕ"HGSŠ ‹ ÈGSÚEBAB ¦´Ó®eeL”[ ôñíÚxÖµ”[$û¾v?I® ‘Æ‚S;—H†Œ4;ÞrK™ûYû¿?×Úä¤q¤¤±IiJ¥HJ£" q‹ ¯½O†+› W» W/Aœc ®{íÙqŸŸ¹‡î}‘ôOï¡¿Ô+ë0ﱯ=‡1#ÅÙì9).,ãÛBq£QaDŠÓ´"%'Lø:Ý«@q± ï…âj=Iqv Åä°ˆ'ë~R܈Ô(¸ ¡ââ½+M''ÅÅohà(®Ÿ n„¾`…@qU„¸!ùZˆç¦q¥{€¸:%àWB\Ôs/g×B\L`uB\„5( n8¡ .ÚÞ«&¯ô˜W%ðP)W%Ä…'ÉE½ÝÎþâB²Y“WÆDŠóLâ<RœÇ@Š«õ$ÅÙ.– 5÷ªÉ«õä¼pr!¹+míG_kI‘ó 8©È‡ Wæ ý{ª.oé TtreT9{ÕäB’ŸrÞ2 rv«!È•YÈUI‚\é @®ô Wf 7¦Î$ÇÙáˆÕà£.8.¶Ì‚qeýMŒ‹ý‚¯ÛÀ¸é¹nK’«8©¨Z°œŸÄ9=Hsv "ÍE‘NvKÛøRMÒ\\e.€nÜÔº'ÓÅðÅLWƦóSLçîéJ÷€t¥ÈÓxµ ® 4@»2‚+}T´B€ve6v¥¡$»˜Þ“(‡MÈ ÛÙ5‹xW%ã\ºMJnÐ]L >¼ƒîìYtWÀ+à•†®›+ƒJ¹è]¼f󦃊Öø.:•ìM55ämƦà¡âŠ'ÞùÐ]䉿„$ßż@ÕÄ+÷ˆWfˆW Ä+MÑ;EË „W«Ê{-^Œ'áÕjáâk@x‹d°{¸ ˆWö¯¬N ^YÑ <Ÿ–¤<¿nòÊ”ƒòjúd³%8e¿<õ,”WËÀ-;€ õÂ/[ˆ¤¼2NP^™‹N÷:UóJÍý\ÇÐ+wªÓ?¥HòD}_ÆBzåiÒ«½A˜d/Y ^¹ã@½rXÏþd½²_&ìE-ø‚ØóccÐ=ÅÕ"fr©ä’×'¦¸W&¼W*Fàdß_ø±bÎ|å)<Ʊ>JøÜ‰Ï!ñyD>oM"_­!”5Ä>mM2Ÿ ¡¯6Ž0ʺu¤¾Úå~¬Mw¨(€PÊaÙ}؆ót—žm×ZõweñûJ¼—"ˆ¤ÌÛDê+½õņ:¡|®åRö|ûª‘”õœ&÷y-üÊU ¿Ò_ Ÿ÷ÑÏâD??ÃÈ~åþÊMýÕ«`y]zÿm œæÚÂßñÆðE˜€}QÛ)¬„-7Ã%Ê´ |ƒßÇ|òF7ð=B7¨Å{rŒ4ïqû™÷dä(ÞkÔ“‘÷Âuƒ÷š5à=Ý$ðžÉ’À§—tŸ'‚À –SÞ‹Ysa=Ó:Þ¼Ô•÷lç„{áCS 7+ ÷št§‰{å7p¯4 ÜS½Â=6-Ú‹ÜÊ .Ð^‘€öüªAÚ‹ö"çr¥½H¹œ?{š*Á^¼KT³ÍÙtªØ{~ öb‡ã*À^䍯U„=ƒaOGaÏý!ìUÉZ/a¯”ìi˜d½wžÕló-ÒùfOÖÓëyÎÉzM†‘d½ÈY½²ž¾XÏSš¬çzÉzo-4ߟÚ&ñyøJŸ§“Äç‰ ñyù<ÁD>O1‘Ï÷;‘¯\äsÿˆ|ž"Ÿk!ò鳪¯”òù“šÏWù<ÇD¾GéD¾Rϳ|äòé}CÈç%Kä£]'xÏ—÷Üòž+!ï¹iòžŸ,É{î>yÏ‹„¼ç ï鯑÷|[È{B»Ov°W*ìùÃ'aÏÕö<È„=¯3ž×+i¯\ÚóH{îi¯H@{me½ÒXÏF²ž·2YOWõÔŒXO#ÖÓ]ëUú| ÀÀzzÔˆõJÛ€=><Íz·t€`½Ò8XOû¬GèirEzú¢!ÒÓ¬HÏ}#ê¹¢žæW¬§%#Ö3;ötû{ÚM€=­yÑ^©´§ý&ÚóÄöÜcÑžFNÚóìöÊU =Ý•„=O a¯\Øs÷{zÙÍvÿ¨úÊ¢!í±æ_xΓðæÊØÚ=lýÁoIx{k’Lß¼w)U¥÷ÿ¬¥s^„þ¢1g:ç½`"å\zçíÏ%sÎôÎÛ›M>Ó;/‚<.Ó9o¿w¹ë¥sÞ~1D óöKnlpÎÛO:™Îyû©Ð#pÎÛ÷%àœ·Ç#*´t΋Ø!p¹‡sÞÄP&MŽ#n›¬0§Aì8Â9/ 㩌7%@d8çÅîêèO:çíûM°žÎy{øU»ÌY BÀÀ9/âÊí•ñ¦¤2^8}ó"hÊùa<½€’ñš=ïÀxf0pØŒg6{¶Ï;‹zzRK¡g¥on) >OŸü‰xþîJÄSÀ6!ž‚ ñy ˆÇ¸F"¼w¥Ñæ„ëŠ9 ÞµÉ&ˆÏpT Ä{«û¨óŽa Ë#él?q¯TÂ;xðæ½™‚ÉwáÔFÞËóè]£¸kä»ÓNwà»w´ò]„HÁUà»Cîiä;¦™3ß)™šø©éŒwáVŒÆwE2ñމãÌwÌh¾cb7óRœ ð”w[€÷–º”€W®à1wºO™Çx±+¡šà)ϯ\ÀS†0s›ð| OyÁExJ¯%ÂS‚5“’›ðJ=×’áJ„§Ôá"¼°ÞLϦ~r-à»°Y¯~y%™Ï3AÀcñò‰ï” |§œbâ;eß)áŠøNIeÄwEÄS‚!^i ˆW$@cØïç3†ýY{¼3¥j‘ôïúóÃ8?cß-’þø®JŽó3†ÉwËïþø®Jîó3ß­’þƒŽRòâSÛ†3? WNYËiO¹hé$ÐðEò¢AÉÔð9M5|Êz% _ìŽV8g™AßÔðmd W¥Šo‹7šê´wF>'Àgjø¶ó‘>i¥Þ—x65fµ pC ß܆5òÊ”ÐY¥"°ð*5|[„ñ©ø77ï -[jøB„…†onðE÷]7•¨ÐðÕzRÃe¨q _­%5|[xW¢–Ôð…䩸wFb««òßû(Ù¤L_-“á7]3Ãon÷.{Ë ¿õÀ¤p†ßŒ‡p0£oF^ùoÁ6D߬e2úf\LëÐŒ¾¹ÝŒ/ˆà›[ê¢$³ÀÝ—½Yü}3ªSÁ7£ÈA__gðÍÒß,ýEðÍ™â¢b`í¢oÖš3úæœ"H2úf½*£oÖ!dôÍRÑ7K=3úf” Š,£oÖk2üfé1Âo†„úº ¿Y%~³Öœá7£Ìµ„ß,Ká7kÿ2üf½*ÃoF¦5:úõf"üfé Âo–Þ üf™c„߬e2üfé ÂoFØ_!üf”éUÍ·\•á7Ë "üfm½]ˬ#üæ–Õk¯®.„ߌ%Š/Ù¿Yzƒø›¥%Ä߬e2g™Aà,ý™8½Y³V{c#>ÔJ þf¹ ˆ¿Y›Îø›µLÆß¬’Œ¿YÚBüÍ™~¯zîÕEø›õªcm ñ7IãhM™ñ7Ë¢@üÍZ&ão–Eø›[Ø\¦ Ão–UŒø›Q„v¥³¬Äßt53üfé/Âo†ä¡â/ÖÑYip¹*ÃonwÕñÕ!øfi7co–{‹Ø›U’±7ã¢WeìÍrfìÍRm†Þ A«‘Yj%½Y%zs»¡7]1"o–ÉEäÍØN0*GäÍZqFÞ,ЛµƒÏXVBoFgÈŽz³^“¡7IçB=½/ì{ ÎRû‡Ð›µÌÑ?wa†Þ,-!ôf•ÜÛgŠz³³½é EäÍZ 2«zàˆ¼éÕko–!T!¹*–Ân–JfØÍRÂn–›°›õäXõˆv³Ü„ÝŒ¹£éƒ#UQ^v³ÖÜÚçQް›õª »ï*§U|³–£2`™ÆÝtowÓõ2îf­ WyWv³VƒŒ«U’'jøI¦)WK‘v}û×Q Œu³Jwõ¼å¢·á@ík¨–z¢nná¾VM9kov¾!oðËbØM¯{†Ý,³…°›e¶fØÍÚä]-½AÞÕR ò®j0ìf¹ a7Kv³´…¸›:.v³T<ÃnÆ¢Ù`”yâ@UgvÓ{Žq7k-w3êiKÜMoÆÝ䲩…Î0¹Z2RÜH¸éŒB,…~÷º’QeþdF¡ß¶ IÍà³¶ñ¿IÉt½{}‚³ê’¤ÔY©K’Z×Ì¥]jÊßµžÔZòw©ãÞ ñóìQRê¬Ô$I­k½_õÖºÖ»Sï׿x¦£xMí}MuÙ‰f”þ›42N_t†ñçñûi‘Þ‘ ã7‰c>5Ü+YÒ'ëѯVÙÙ˽ù½9FêÚ%7ê*ùŒPWÍgĺ\Šu-¹‘²®šÏ(ëZò¡®R u­¹‘PWÉg„ºj>#ÖåR¬kÉ„ºJ>#ÔUó±.—b]Kn$ÔUò¡®šõˆu¹ëú3YÎ6Kÿgœõèxâÿò¹ú›çû_ÿÆ3z)õ»O¨ÿwYÎpèÿéd=úç_e=úç?›õè 3ì™Pêû×ú`º äœaÒ^IcЦ33†Sœs¹=rºç;Ùµå'´}s 2mF|€)ÉohÕ<‡Ë$R—йáÚnDÙç ÷¯6£fö¹¶gbû© K×Ö&¶ŸïS6Ò_[ŸØŸkؽ>±ý-ûÕŒ‰íNhsíÛÄö+²Pdãáû)ä6&.x%ó}ÿŠ7\uÄï“/rמЮ°C‰sr{ä2¿ ÉhwõBrOn-;êÉh‘?<9犜W1„p ÏAíù-²…çG¶kï“ݯF£èk“Ýï ‚)˜è>¿¼dãÇöÿ÷溺$I¶žÎ§8b•Љ˜TI… Ô3ºoã ÷ýÁX¾3ß™ÕUÙhP¡R•ÛN„ÿ1¸‡ûçËÒ<o}lë`wì²èuoÛ`w§Cùñ¸…ÕU¬ŽQPá³|kq.žûgçÇ?—Î:¼Ÿßu?:†ûgçî«c»¼ŸÏò›ÁöÙØ¾á}øŒ¸¾ÅúmËXíã½9.ᄎ tìÜ>;O+òǾvGusn±(„cv%;Pwð=U†¨;ž–‹0(®…;Àü-Ë@÷ÜÂgþ=9üÐâ€*O'XÔî=ÐýZ]ù³<¼;è;·ÏÎ÷ôm~_Žq ØiãÓ;¸}†Ý#FË}–Áî'¶™ù[·ÏP¢qÛÎ{pñ’ãà޹e?}kWã8¸{v¡ ƒˆ¾Cõq\c4_ß³Zt-×€wü¥=ë „<Éò x?¿¯:þñx¿vGX~–ïçøRÁp.ƒÝÛ!'÷ϮҰ¿ë[p„«K|Ý3à½=ÑûôžÕëg9W¶¢QwŸƒÞû/]ƒÞ{+÷ ÷ëû2iÞÜC»Nçxÿ,WÎÕ÷ÐpŒF&k·é˜‡Ûh×éx…Ï2æU<6ôñ:dÙÇ/½þF=ÜFûSWŽ›ïáv|NèU»Iß ¶±›¸ªÕñÜ Gƒ÷æ?˘VÑ•ø´Ö;=ñKj†‘¤èÞ4¼ $=/§Î>^CGŠY‚K’ãå¾|š^ªÌFÞ/·Ð0 _Y¨2Ÿ—‹c/÷Ðp–zÖK•–[gq­}ê^ªÌ8Fë‹—23¦ Í™/efÌ‹Z†Ì|b½5Ž8ÊÌ'úÈE eæó{@œU? gÕÛéÏ…23~‰_æsá&Z}ϵw0~ë²…³*ƒWZNͪgÚÁ&^¢ߦÈ|~Ë®™>ËãgÌgs.”™ë.ÜD«Iô\M««òÔœŒ)m³þ¹Rf¾°†ÓY”™!pnûVœWß]ëÇÏÂy¨³ 3 ¯x¥ÎŒ'ñªêÌ×få峌yõZä3p®*äû½ v“s¥Ì|}õR3/§ÕÌ&çújZ=ØgOTþÂÕl–ÅÏmͬzê˜máõ¥lÛÃõg¿sÛOö’Wk¯s;4¯æ½l\%_›µÁs£Î|-®ÑsnÔ™ñ„©1~³ÝÆ•« ufÌ'·Ú¡ÎŒ1´éŠ©3cš§ qî‹&V³s‡ÎŒÇÇ…Õ÷·&Ö[£ãÜ©3ã—ÔÛPQqçUßÚ©3ãúô´¾e¬'V]ÍNß(~éÎýÒHÜ5çœ;uæö,v-“ñ‘–…:3¦uÎýݦQæ]Íyê΃:3žºz±÷B¶ÝûlÿdÙ£BÀÓÞÔårNF@”ª›ð>B›x_Êf¼ï¤+¢vÒª­ÛGéÁ¯ßŒ{ $Ùí#ÜèÀ¿Þáª~À .Z¥-Š’ÆC—mŒÐ<6­!ÅI#žŒ†cøü^‰ÿ„È ÓÈËå2aæ¿åÊ´$þ[±.R»ä?8mÂÄpôj’ÿðÅx&þÃÞ¼Sâ¿âÑÄ+ÔÍÆU³Ìü‡yNü‡ª[n…ü·Ý!lñ_• 3ÿí˜ÿmaÝÄ×QÇæ?”(æ“þaˆnþíÂW–M|¼›OþÃ9ËÄ`n³ù¯*¹šÿvaŸ·Aƒ}ßGß`(ìûιp\ãIø—Nm§V»Æ>+IÆ> åsÂ>Ü•º£°¯6–}ز~&ìï ˆöaób1rNmçûЮÈZØ×€WØ×áŒØ‡­€E¿DìÃvï9a_ë]¾¶™"ìèë ûðRËÀ¾¶Å ìkïAØW€±/› ¦TRÈ;³ø÷ZR2ùáã®üqÿŽ3BÞÿN-7úUbçˆð•W+}Œž¤ˆø·æ,ŠpA׌"ñÃ{Ä¿}ÝrŒÄ?$±…ê> þ¾–³Ø§ú÷MjúnZý;ì3õïÊt+úûˆÖ«Š¨*ójøû¸Óøñoõ$bõo»£œIý»œïÁô·£[¨þ5u ô_m­+E'6„[¥þ­ý«Ó‰Eý;î`éï@Ü¢ ÿŽ¸Å¿¯7.ú)‰—%∻“¤EýÃL€5Ô?l~‰ãHÇ•7gõ{h"FÒßqå-ˆþÚª\ô‡_23±–7!¿eª×+Vÿ@£BÂ{\Í[b°êÀnCÄ1f%`½^ËÐd,Ž)ë¸ßH„Òÿ°í'º¾!lëßj\zª ð¾µÍAùŸ ]Œðu"=à‰¦Î‘üWÂò_õàw1Z„‹Û¢Ëò¼s'ù¯-º-ÿÁµH”HlKl" fK‰{D@ÈÆ–%B-×o µ"4ÿaÚS£ä? ­Ü €nuK$@ÀÒm&$©^ðFÄ1Ò/€o´" fâIþC+¢Z!à¹9; ðÀGQšœÐn®F@¼¨CW#ü–tׄ€ø­Cg T&ÀÅTÀÇýŠÙ[Ê™°žŒû˜“úפqà’ï®ðpò› XèoI³Â¿ºiâß¡tœ¡¿‚gÓ_ÃUÑ_½ÓßáLï¡¿1X‡Áðç4ø?l•X $üLþ6Ó)øsrzÁßúõÌ~«Žá¯ž·á+Pý´à¯•鯼L›öm þœH5ð·/%þ ¸ »k  þ°mg‘oùÑA …׆?,u–t?8}Ëbú‹ØfÝŽzjYôWî À.È ËýCˆ-tu`Ö‡ÀöKÀB{K««×k K™b›0bŒãêš0Î(QþžÒÉí¦ÿ}/y™•¿Pyø¯–¸æ¿Ë9ˆÂ˜ÃhþΊZøg< ÿy–î÷¦Ýa…w”Jñ_5"ü»·ˆ‡Â¿ÓÙ゘ÊgÙ.þ“ìW!!ÀÃúD°äM`a/ ðv…×àáÔkE€År"ÀŒ± ßm°1­ÐûÀøÿ®vÀz-À(ÈÀó ¸ 5 €ñ*¬V€í—€T+x@ïaÿ¿ÍøW÷ü[µŸVø·¸þaÖ2ÿ®% 'ü«ã|H¬¾?ÖøwÙ›/ø—OTðO{ f¿FŒZgSÆì>|;ûµKû}—²HàûÕnŠ]©¿¹a¥Cí\)©”¾‘·ó^©vú·MX&ÜCdJúZV9ãgÜ»ì X¸gÇšà¶Û'_Oæhº î=0ùz>Ù\5îí"{²Ñ2ø‡õRsöÜŽ7àÆîŒtáZC÷_lQQ¸·Æå͸·9rxoJØœvÜ‚N"î!€ÆŽœÄ½ýu6ãàÞ¾þûšíë¹=Oùz~‡¾í]‹v˜öZ;töÜãÁ¯{vö´Pô¾ZÇ×óô7,¾žqj·¯çž!f½/óHœ=±ÊÑ1röünÁ9{n’‰{å4lgÏï{¢jgÏÜ‚}=ãíÚû~O·`_Ï+›Xöõl~¥òõ<ü=²«g¹éÒÕóûLÙÍT®žãÙÕ’ ~Z®žqñ‰«ç•-»zî*ŒOÏjÆžžñЧ'&÷ ø®o&Õ(‹§gwó„ßþ$õ]OP?nž[œ:åæÙ®VnžåUl7Ïr¬Œ›gnÀnžõôìæÙ|-É{x×Ä{×mmDnžuÅvó<í_#Ü»{àØÉK={å³k'Ï€LYï‰Æ-ÖøÐ«YïºâFIÖkÙf=|øDWëp[=~¸y^OöÅÄzxïÌzÐ*h êá–tF½ò1êµW`ÔƒŸÝäåy]ñ‹1ë\4¼vÈÖ 6Pï^žðQïú¾tvÎ$ê]¯÷ߌz¸ïc’úîeµŒGÔƒð9¡z¸e<¢^o†¬w/Þh$ë]¥‰õÐeŒd½ ئ[ ìa7i}×ãˆÃÞ½¸à…aï‚~IYï^=a™õÐŒVéb=Ü÷iýïá =í:8X™"ì:JÖƒS÷6»x¾v”‹‹ç}ÛÈz7´Î’ç{E5$ìÝpÔ™|<Ûo öîÕ«ZÃÞ…ÍHék„=\³T¥{í¾{78''OdÍØ…m\ãù­“ÚWÝÚ°wï.#eØ»¿Ë4þ‘öÐ)Nó<ï7ŽªÄ=|W%GÛÉè&äî¡]ÉÓvò̇ø‡Ñ`…PNžõlìäù>!59ybô ,‰{7V*ú-9yæónâ»×#×'µïq0™‰9E¬5'Ïê'"¾vWvò¬ž#âK?þ£jI¥ê-øèwÊ{ÎøjZÕ³œdÌÃÉg é« ŸÂ¼‘IáÂ)'¾I:†˜7Ò?ÉÅ“˜[&ÌÃÂØj1oGOœT=¸2é‹(ÌÛ¯,w…yÍL˜w,ñ̘‡%Ú2Åô÷ßQb^ öÆrá<“SgóçaÉ¡;œ‡]s9ïÚ\~ÈœWþÁæ¼u!ÎkQ?âfëÉYƃ·KçÎê‰Ír°zb½b\»@PÜtÀÅâ‰Kü_‰q-õ’0n4bU¥npÖÑ»~ 1nÓS³ô'AŠ–É7s:†µnú1û3ÿÍJ7X~Ú/ôdñĺ)‚\»ä¸é¤›µÛIÏæ;°¿æËÚ‰uO/K'Æ@Œë†U%ã1ŠkEåDqâ…)®_)n¶°pb=RÜ8FÈNŠ›,¬r3YX9±]ßsû[^VN\*õɲýøûõ=˜‰VVNlÇl‡ïÁÇì«_B,¬œ˜rz¢¸VrO7Y.VNlg]ï|Ä}ù|„j˜¶c^VNlǼ…9†×ïŠ×Ï"ÉMÇlïÁ–ýò=8„ïØÜHn:âÔê‚B¹ÉrsmÕ0mí<ïÁÕ0­³Èrý˜G5L»åùqʘ6Ë>ÿÒ£"¦Ýrÿ¸Ò\+—(š–Ãì¦I´Ž¹oßÃÕqn²¸dÚy]²Yn?eëtë¿UÄ´ã"eQÓvÖÏ"¹ÙòúÜŽª˜6‹‹@–åÙ~ã"Õò«v¥Ñ,.Yœ,¯ïáè<7£*¦í˜cýíÇo©Ši³œ×|é¦#îÕwËóóúͬV¨*¦u ™n¶hLç,BÝdÙö÷@¨›-šYë¬ãÇßçþãuÓ1×óãVU1m–GSkY^M­Íòø-·œ?®T7Y6Í­Í2ÿ6±nj÷Ø~ÜÃæuñ2GêM–ëô=Øro¾[žåÇ{ ×MǼ§ïArÝdY—ß?®\7YöíÇõì†E4Án:æ<|>æÚ~^ßõþ¸‡]ëãfy߃Ûy·¿¾‡£{knUèÕéISØõÏÔG*ð¢ø­ÑÕ ~N¯P®›k°Ž®›Ž1ëæ£jš‘ô³˜%=T¹{’–ÃpöÜÜÖ䦔¤‡åÎÛ)Io=ãaII]Í8FIY/ö)Po$Ô¥áØ§Vô‡ZFÑÛ",XÑÃsÐÅHÑÃþͨW±ôÎã§ WA#ô¾©ß¢š½ ì· ·%GÈôéï™ãô®ÌŽÓ«œŽÓÃn¹ì(è5ç9gé,ç9 z-é¥=Ô¶PËôZP»=ø¹8úð}g·| z×Éu³%= 19á9M'Š>LzÍ1Êi:_㊢wåÍùÚ+ßIB¥èa/¾)z- ¦ót–—“ót:¤Á‚Ö¸ösTšÎÊW Eï:‹¾ä»ÙwRуû‘^Œ½Êƒ)Eí̾›I"9ô<¬œ%ùHÏCÈH¸{ÙÉŠ ·­Öü¤çÁ}]ÍHÏË!ÎÑYþI–óÊ_Ñ9:ï±ZÎÛÞX”£ñ¶$Rô°-i=Q’^å7Œ¤_]Kzqø‘çæ[éS$é]IX#I¯£é”¦ŸÖ’Þ– ’ôÚåHÒ;߉ZЉ´  ¦÷TÂKjzQ†#éÝO<*%ékÜ9%é=wGYv¤ÊÃB]<à,+ÔõÐÙ¦T-äsvŽ·»$6NºÞûþÐõîÊæ"]¯‘¬w+œÇªvÅYÕ»“gd“ªW­HÔƒs±š¡¨‡iGáIÔ{’}uˆzøDÙ™R¢ÞsÅQ’¢vhw'e¡ªw?ÉàIUÇè·¥êá—öIÕÃMÅMss/·Û¨T½»ÀHÕ»¶ü–T½'9e©ê!§°ðPª^u«zWâ'­ê=G*ê¤8Ò‚D%ï/L(~øßþ§Q³ïkÊ–‹e[VJüßÿÁyu”éçý‰âHH…÷ͦõ ±ìz΋É?ñßšeQÌÓwÊî~+ºÖ”-­)™ZS±TS¨$Š®ÑîÛ–jʦjª,ÕÔU%¢o¡ÿÝï9Vw£@ˆ«´ìUh¯ÒAײ+ç€ã/×ß;€µ=Žª-ô»nð!(&¶ê=û]B_¹Föà~”›z‘‹=-éïÞPq;í7ƒŠÍX§zCu[êG¥©‘°²Ýœ SS9(Mµ£Ò q[S2LMå 4ÕŽJSÏ÷ š’aj*¥©vÔ?ÛÇà™ø­€~sñºæŠBÇTQèwÝæG¥ Ÿ}õçqnoÿ'ûÙµwÜ\Qè{õTú'>“ûÝï>Šû£1ó»åšß·õ¼A,ÍûwËÕ €”ï„ û (Î_~ýu,gïë/ÿË÷<<¾œÍxý+úo­ù—ÿ9¶ú×Ï¿þ¾™õhÆýŒÈ|«ÈÓúë_p}ÏÎþ5¶¯õ¯ÿí¯HP¼×_þ׿bcå[TÿåÏýù×ÿóûl!wôsýåoý—oéóµ¾åUþù’Kߠݿٶb‘xÌ%—ö*¹´’K×?¬¶´³Úÿ§[¥}n¥}|ÿ¿ðßëï*¯tüå•–wxñ€ö3ŠíëyH!͵öºŽxÈ,*±Žpç_rÖ¿ü{äîA±ÑEÕçQ þ{މ\Qôêú,Ø ‹o=†Åüºf3c=GÐ7ª¨k¿^cwÕOµð_ïí†êòÓ]é?JšÝ4 -%–"fþÞ1 ®  ! èÿ‡Soë¨-T—”…ãÎø°;Íj3øf_Î¥µí#Ó6óÄyÛ‡.¾ô¸Ì“@Ç8I•žÏµÑFÙv9°ÛäsîáGP×ãC7ô~äã‚w{Æ*v;ÍÃðŽhS`UWÅ/`ɪåìΜUXí;Ãù:œÿÖótçýûxHÀIË>vͱÏáâšû·gq|?F ߊfÕ=GbØYE¸=´ÎV$Ž—/ _€P¼›:Ö‘…?þ5¸àq}ËnÕúÄÆ!WÒûÝc"ãNPyüñ=Ã*yÖQ ßrÂb –=Ú‘ØE^m¹ï#0x M´m7¶ýÆub¬q¶"³—S\Ýø7@@¼ÆrsãìI#½u? ®›8æ:’kès8²iÃañxZ‹ó!¼gÃ1g8.JxW‚Ña¨t•#iêBšßÆmzë ‘ê¬§­`hã˜ÓqåCvÀ1w¸øêÅxúò/¼F•ÁñøåËxÂñHEÁψÊÿ/*G.ðÙ]”èéWlºÓ“fDÅï¼rÙÅÌ~+ö¹9ÐÆ2×ëëqò£>>ë›ë޳_jø¼ìÇ|¢ˆ_ãõvý(/3]Í5²ö­b§tt13íŠíröZ¨`¼"«‚Žy†“×xJÜ¡@|l 8CcÀbgž—ƒ]¦1`±A¹Òò`9:ž¿¾Ø[À•ßÇ}b£t Øïº¸C6<¼ŸÞ¹±‘3ìéòY F÷rÖ°é°·E2øâë¶—7_Ûèü ¬†S<ÓõzÁíÐ%¨Ø±žk±û©Ê ÃAOëpRe8qŽ{zÿäÙØÃY>„g+¶³ùBVÐ1`s—+2©éÁîùÎc8<Ÿë怽,>÷Á{:ÏÎópÑ]#íy^ØÍYþŸ÷æ€ýÚ#Ñ£zç°‡T_¨0|\œó^¦Æ[GvZ¶1½âCÙäÝ9½Öu$-/lóp~­GÍŠ1`E£|PË ‰2†Ûêgy±Å6.p(^ߢ•,ºÛØTX6ίÈê·ò¤ó+2r›Ï2æW,yÆghCoŒW”lXÙî9æWÌ); çWô“…—wq~yþØÌ}e¼Ž~²-'ØL<Ûòj‚Ūá¤E¬{àõ5ÁÒðÍ8c¸æPfc ×CžËŸÅó+k›+* $bÙ>‡µ2aà3v9ˆbäÀç¶<% |Pž‚÷+ |ÕŒ+aàóZÇbú?¹þ> Ð'¾ëؽýU„ÞÉЄÀ‰‡¹À¡RøB%ÖI„ÀÎ2\ ‰!.1àûÍC»²ê‘á ¦1 –+\c á ¦ØàëD²ä¿±â!ÿÞ‘¯L.a˜Ÿú…ÿp;‡Äkòß;ê +ÊdÌO­ T×Ý¥rÇõbûk鈳^geª{ïB9 `wª•bà½#1²B~Ç Õ‹øâ,Ïàð£‹>=6»Nêú‹c†j÷%l/Wˆ_ßEaq[aŽ —óXh Õ~Iغ‘ð•¤x ðE‰%± ðE\¹¬’ßQŠg‘ß-õ €/:˜n˜>!ü{7ë뢿wTÜ¡…ô‡ç 1(úÛºDv¤¿v¢¿—’_õU_?~€_{L?t}—~è|Óâ>¼®±…}hEß?a¶¾:¾Áè¯ oÌK¸åëèØ×º«°ï½–ÇûÚ»öÁ9S_a®xPûZ—ö¡~Ýq5ìû×gQØ×›؇sèò&ìÃO«/ûðÖ¸W!êC_X^ľwäÎ×"ì{‘¥‘/VØ÷ŽÚI² ìÃO½ôöÕÕˆúÞ‘š–WCêÃÃZÕ ©¯½Qß‹w·¢¾wäí•åå(ud¨ o¸¿òŠ}í-úê1ß›ôÅD¾6ô…|í…|pañµ‡'äk¿Câ{1)òß›Œáâ½w”g#ä=|ùõ–Ä{¸ÚSˆEÞ â½wTê¼W—gà«{2ð½£Þ:ÏÚ9—zÊ3ð½£›ÀW#ÃÀ7™®†À‡ÆùÖÀWcÅÀWÂÀ÷Ž,ó²p.­+ðµ_ñÕÇÔÄ÷'ÜN|5v|í×…|x¿ÇÓ‘¯·CäË÷GÄׯėž%àËÈ0ïစ‹Nñ^ó^$Ü«aÞ«~cÞk×"Þkw$à{GåCàk½DÀW+_ë[¾~ ¯½q_̓>\_x/â±p¯>„ƽz¤½ÒBL{í&E{õ {¹f½wäÛg+d½ŒK£^{âB½6V„zïÈ_ÞQï)Äy QÏ—¥Q/ “ž§#“^Öq½z ä¼v½úJ ôÚKèՇŠW{ƒ^½"q.åÑ!ä¼ö5çÕæÕ'٘מ0+Ò1k >Q^ëÑ¢¼zv‚¼f ãµqAÈkãMׯeP^€vsH+¦®’Ay-IõkP&Õ+æIõC ð·ÃÞ;Ê÷ÜvNR.æ)ÖƒK¢f ±Þ ?¨[ôÇIjTûà1Rý bÓT´÷B”ÀHÜ{G‚rYïÁoQ hß Çj¡oLi¼M KêÍXø[°È¤>'áoYáÂÂ\ É1þ–oåÆõ™„¿%u€,üa’£ÿ¾„?ð%ˆYø[âDoáoÙ,6Xøk)Ëð¬-ä7EqËÂâWp`á¯Y$ü-ÈD3 KŠdXøCbÕ?–ð·$´…¿¾íüuQß(? pUÒv xçŒÆ°ð×. NùÀIW"ç®äRߤú¡;*ÁŠT¿¥ê—‹ùjhšù^K%F¾zýf¾:DÈ×WyŽ úFé(b’¨ŸØJÔ7Ò…wÍïµ¢ºæ÷Žªuä@Qœuu É Ãvçªv5¿ 1K~K Y™üFÄÖ$ùÕwÌ’ß’Ää–üŽF±LŠ^#©Nä‡0 ~Å,øÕ×Ç‚_}},øá± ¿%%‘,ø-©àbÁo¸ ò×%ø-)’$òÜùñAIìÃýP‚³ÚW=Õj éѽÁjß’8Ë}5-÷-©Íeîµdˆpâ¾QM†0&¹¯:µå¾ÅÉì­öá1¨©}°P'6÷ÝÎ-cì{h}/’‹…}#F®k}­ ûª»ZëÇ‘á:Òú–”?¶Ö·Œù¸¸o.‰šSÉ–‚¾×:³e>¼$釒ùªM©|KÊrYå«wd•/–¨|°pgÜÔçJ×>¬:;óeDãš<‡È·K®b|ÿ™ú^ºJô½t•àÞ¨ÈÛq¯Ÿ%}–MjžæQ«è{uŒõ=B{ˆp ÁXß«C{ˆ¥ãêÓ°7"#'}oqå±è{Ý¢YbE×÷šAú^^µõ½zºæ½Qb'‰÷Êb}Ob¨ïÑ÷êÙXà[¡}/ë›è{{Ñ÷òÁ îå»ÜË ÜË„ÜC„$õ3ë{¸Ê-Ö÷šE¸—áÞó°6ïeâ ï5 /SW€/³G€¾Z×$ï-ŠsŒº‡WÇnmuoq9ò¨{õ´¬îåóuoqqô¨{Y¾FÝ[6yŒDÝ[àH¬’º‡v÷` ÒiæórÇÌWÝÚâÞâ"+÷²2¸WwiqÆRž'R­á"îÁrMÐW=ÀЗ/µ½Ì>¤}'èÃÔ}LЇl¬RéD}5XM}Í"ìËj Ü—¿¹¯z±¹ï³P°ºWCÞêâߟ¥ÿwk*™õ°rN¢V’äÌz—7—Åz_ï2“‘õ™ÏM6³–)’ä{‹QÌz‘Œz ›§£^S+ŒzÛbę‡Ù¿,Ò}ˆ‡ˆô@V¢/‘Þ(ÿÙIïE ey)¸a ÒàÈyu¼v•=ŒâyMh’°½#º^$¤èzÒ;¬êµ#¤ê•,fQ/ê†E½Õ5z-êa­¯CJÔÓ!õ¶Õó¤é•€cMo|;h‘¦7Æ"-Â;D‡)mƒT=¤„” I]o¬–i°‡é÷’Ž7ö!GéBåïãÄ„Ô>Kö|G•Î`ÌK†Y*ôb^zF@¯‚;¢G%¸{ª1Ù‘o÷êlò¬ÐîÓRõžïÕl ÎÅeáźíúÕíÚ0ÚÁ¢¡&´{FÉ^Ñ®®IvXr*(Á®Ÿ2Èî“ KºI©Ý’è*µ:ˆè®µK¸kßÁôpµ"¸Ë¨7Û•Al·$ÈNh·8…‚É.)2 vÕ9 v‹ÎÌu£âoWóªsë#Šêp€Æ¦=Ì<ƒT‡#¤ êú)„ºö+Òóª"–ÿ$!<n»lŽ™‡ìÖ÷ÆLôŒ ¼´éЛøiÒU/Ñ¡ªÝüé<׎ εNKœk¿Bšk§  «N-ž{Æz‡ Ã'ü`}%ê"ÏÁ"Á[<÷ŒJd]Ç«_ÎÕý‰æÚÅŠæÚ!„9ôs±%a®Á\û²ú=»’XîyVÏ ‚¹6XsÍ"˜ÃOs·Œ,׆œX® 0²Z—°*–{F‘gZs€‰ÝV0÷ Žì@׊D×-$ºzT"ºf Ð5yîy^i®~Ø4÷ŒZÒ]ÃK#ƹú™ç& &Íñb®.áÁÇ¢Þ`º<\#]õ#:;WŸ"ºf ÐÁ@çÝdy86Ï€îÅ»©Ä‘èªa]{ "º|9 tí٠躅@—¡fž«¡%žëò\ÿéÁsõ¤„s­ÕW“æáU¥hî¥å%ÖiÖtÿ1͵.œëgíš75úŒs5úŒsÕ?Ds5Ls&pDsÏØë4÷ ú¬¤ÃGó¦­i®ŸEšËH͵#Dsí¥æêq æÚ“̵›ÌÕsÌ=c‹±Ëwõ-0̵7)˜ë æêƒa˜ë·@˜Ãoq¯C,W+ ³*¢¾b#Â\»Á\{¤¹v}¢¹öÛ¤¹êõ‚¹ÞÈ¥ ÔF,‡/÷ÉÌrã+< x­]¢\kW,—o•H®]­H_{é½"¹¸ûä²î3ÇÕŒcŽk‡œ™A¯Fqý”K3hN¹§Ô W£úª$™ÛLãî݃Ì`Sd¶†5ÁÛÖ%¬Äm+¾j\›+4£ùè™+r]©…æ °¿ ÜVt}ÑŸ4ºý’–w8ˆÃò÷ìè™ëHGÐ=2‘zM+AGæpÑí.™c¥¿*VO‘yßW˜S|Eæ½R:™‡"ÜlÙ‘y—óH92ïuq t(¬Äu¨#óWn³@w..#ŸÈ<ì!L:-c1,ÐkjU94oUáF tp¯ý82Ož¾˜‡žÑ2‡—6·ë˜ÇY¸nÄèæm)¡¬À‡Gí4lÜYD°ŠÛHŸÛöÇ9¬¤Ï!›ˆ=skq«ü9ÒçÐÓÕŠ¡y[ÕÍ@÷Í )RÉØ §Ò'1víôš·Uù …æ¡'îÊbCn­"èFÒ'ëüm\ êßZŸyè”7d„l«ëœZ¤Ã ˜Eºv’Dº­ý+4)ùT¿O¡yk2Û947ÕEºq½ª È<¬ ØŠóp}Û˜‡¼ŠÏ˜‡ä1s`®o›óê¡;0eÙ®Fs+²ž’丹¸¥\Dº-Y·¬Ò!Ƙé|˜·&sŒUº-•h¬Òmp¢â=H¥['÷ÌuMa*Gåm«³ÉY¤ÛRøÇ"]ÒGD¤ƒeíH7ú#,Òáaq4X¤[SóÌ"ÝÇfúÚ)*oKý%GåÁrv¡î;Y⤅:X^Érêðùçã³P‡nsOBÝš’„ê*°Ûqy<ÄzŒËÛ–×bž„º5Å@-Ôá>»ƒf¾êêq9,7A¯‡å­ICè°¼ ¥¢»yΔSË[“ÜNayõÔ-Õ­¯C%Õ­¯Õ~Ku8‰CÈZ]·8ê]²Dâò6×±^×.FzÝšŠ/ìÆšœ?.Á®Ž;œuË)“³kúdÂòF>(‚–ÂòVç3Œd—þÍí<ñ¾u‚"œ—¤Qèu»ôþèvX;ìRò8»®¯u'ëv°H““n‡v®I·ûº¢…IévÛbñºݶ(`=yõ,,Ü¡m ÌÃgéàYŠÌCNR)‚RîV—¤‹r‡vnÆóI¹[WÍåVîVç=r×N¢r‡l^¼<æ­.P›À¼²X¸«V,Ü¡™C¾›œ^W ŠrWÝÊ]~Üʾǻà‘y«+ß&2ÊiŽÌ[]31‘yù®G¹[±”;%M`NZ§À¼Õuc˜W×çÀ¼vóº³ëêN Ì«®nå®Y$Ý­Nž鮵#é®#鮎¥»z–îVU .åÎ…ÎK¹{´ör‡\q¤')wePTÞºÛßTQy0P ·r7²ß±Y)wøvP´rw;Š6ʪ…Ê9““kæ”(w#Ï/¯æñäêï€ÃòÊbéݸó^3((oqráå5‹‚òðêŽ.ܵ1ï ¼Õ¹d”×,ŒÊ[@7QyƒŠzXÞêB÷•NjSˆ`¯›ÔD:ø€õ4,NìÀ»ï±½–äFð8kJÃ2òæ]õF:>9I*økž»;dÞcEô7&¤ûvÝn±Þ=>H]¤™ ß.Ò´~òë$îÁ¢øá®ÏÑuÄ=X¤ ÷îo'ËÀ=£øá^·÷º…¸7Y0!uq¯[îµç'܃Eòi¯ßi¯ßi· ­nÑ^{½ö¸„{íÆÅ{xìÚ-ïM–1’ÞÈ{ÝBÞƒE¾uâ½É2æ£öBÉ{Ý@Þk½€¼7ƄԂ=Å{ÝBÞƒE~}â½{ìk¯È{w¶ƒÍ{ÝBÞÃBWù~‰{Ý0hçNÌ䀸(É;”´‡“^'¾óQ·öúY¤½fí!kÒîò€c¸–a°^]X¯êáïãéŠ]·õº…¨×-D=€„~˜¤× ½~I¯[Hz- ”P¯Y„zí,¡^·õhRžB½n!ꢞvD½n ê"r-¯ýMÐë§ôº… ×N"ç51¯#Òë’ÞH¯yË2¦¢jF ×O"èÁ"±R ×ƒ@¯[zý,‚^· Ðk¿MÎk†yý b^³󪇈òš×^¾ ¯·BÈCÆ[ÅB:f³òz;„¼n!åµ,ÊëR^?‹”7YäP¿þjNE”×Î"åMNªÈn¿7XåO Ê©s{î•nà”Ú~™Œ×-„¼úbˆñºa ^{B¼n!âá$…Ðñ&Ë@¼úm#^·ñúYD¼‘3– M"zÉ:!^· ÄC»[÷ÌìN¨í— xÝBÀk'‘ïºÓižƒñ®[ˆw8I‰Â»ÉÂé´~[x×-Ä»~ñn²p:Õz.x× Ä»ûºä ¼› œNÛo“ïšE|×Îr®ÙnátZÏB|×-ä»~o² Àë¿NÀë^?‹€×-¼ÖMxÝòjB­³^ͨ±ðÚ‹ðºe^?‡„×-$¼~ ¯[Hxý,^·ðúY$¼n!áõ³M«e!âÝ{¢…xݲjZÍYb¼n!äµ^IÈë†CÓêâ7BÒw(¸ŽŒ7Ù«Y2jroÖï4¯^Š0ã!OøC´ãõß&ãá,:œ ñÚˆñ`q`!OBýV×-»fÖ:‹×[&äu !¯]Îʼnµþ~<^e„@“›€³±"Yù°ü™JIÄÉûh]WŒ%7ÍÓeµI€pÁ<ì¶Éˆ¼sñâÚ‰8‘¼“'â‘™¿ŠÙ¿ÝOsÅ’‡Hí[‹Hü·ðïƒ5Ç]% çêx)«}"¨¦Iíçf›òpns¥š&µtŽŽ+’·o“ÚΧIíCÆÑQìÛ‘«ˆ‰}ûî²=ûßýîôgÓJß¾9Y¥•¾}Uþ¯(}û‘BÅRúFAî©9ØíêùW¾º¥MZëÛ—ŸZß/ËIëCJxJ-ÖúðáQádi}H$o×LîEâS¤Ø@i}h™FZß¾êõ[êÛ9Ø‚~ßíÚŶԗ¤«VúvøÅ©Ø“•>×DˆÒw©™+¥ï^RÖJߣì†Qú§H³Ò‡Ï”,Vún«xVúÒ×¢ôaQªÂ(Rú‡ÝÙoHAªhb¥/õ?¬ô¡eF±Ò7Êü[ }.”¡ï[ªT†„¾c·Zh¡Ë®Yè«Ræú¢ÇYç«BðÖùPÎ…ë|Øzî›Mà,¡ït¥/g)}ý¾«»IÓ2zå8Ë| c ¢ò5%*ßæ BùôŒXäs¶K‹|c™ÃC$òá$æ]´È‡-î} Å[SèÇ"ê‚-þ†ºwú¿%Kë|Û*ŸQë|%&Yç«goq„®u>¨Iè¤ó!Íô1é|øJR}³Î·8µt>k Òùª×X烼Äolt>W܈ÌçÒÈ|x™Û”~³~;2_Ù’ùüã–ù¶T#²Ì—N™/Ï/2ߢèK«|)í[åÛRºÃ*„¬÷‡Êg]Í"ŸÕˆˆ|v#òE&µÈw;nD>8øå,òY>‰È *n‰|Vù¶ÅÁßQùðÍùUXJMD>XÄšùàJ<åÞDךr±¬ë›»ˆ|ŽÂ³ÆçGQŸ+áDãËb+ÒøÀcTT¤ñm.,os½ªh|x™Ò¥ñ¡çS´Ä‡ˆ4¶k‰¯DII|¥bYâ« ŽÄ—ûŽÄ§GÜ>ßw)|ëÜ›hXrž¾'É8%ðYÀw;¥§ô½¨ÐÖ÷Òï#ð¥DàËw#zÍÛ}9Ç1{ÀqÛ”'þ¾ÀW—c…¯ý–>h¦ŠÖ“‡+¤¾…ïU4m¾¤u/…ïNO)|+æ}¶#‰¯ôYK|e‘Äå<_¾R–øºAóª>¥ð¥ßDá{>j…/ß±(|ø¤ß“‡Ûdš>Xÿh…¯…¾zì–øðpØ ,ñ•e‰¯nË_½‹|øh>-%Kë_ùÜù¥ñáÓ!¶“Æ·ºŠV4>(àÊcï}œhÓß« ¥ñeGãËYÑøÞ»Yä{O)ŒVùPItï8 ŽîÕYžW¥òåz¢òåN£òÙ›#*_ ¢ò½ŠdÊãYås}³VGiNf½\Ǩïw®­@ˆ-½Òß?¯Žò1ÿ¹:J ¯ ú…Xªb‘MU¹¤,U±èã€xÕš²¥5%Sk*–jj”}zI¦Xª)›ª©²üW×Q‚s+¤ÖÿÂ:JwJy¬gðâ¿«LÉï»ÁâÀæ_«/ó³K¡³`¡>ä¦R$É-µ"In(Ǩvˆ›©In§—HrCu”Zꥩ”HJS­DRšÊQnª”¦R")MµIi*G¹©vPšJ‰¤4ÕJ$¥©å¦þu”ÀÜË7[þÿ·ŽÒ?ó™üÛï>xôQüÛŽ™ŸÊ?3¿o럯£´cOpÛ{%•?ºÿaù£'þQ¥?(Çt>ÐÐgœë(ýç ¡PôzÿYçèûôõ3ÿ{™Qçè·džïÅXÅŽ¶\ìhîãßäÁ±Ì_ïx䣸+……ÅÝI |¦®–vGPͶTûvR¶+ê‚.´<;ãN¥Xÿ^ÙÂ¥³7H?˃_]w€VûŽeþ(K´sƒô»ÇAV+V›Ã•ä»Ñá‡"Þd¹Ïr3m=ræïò¯³±é7¼¹¾7¼ÿ¸w ¶ˆC¡}­{×ø¿\.â ü6Jm\ } åQtr¸óë¤gÁŸ÷ ´ï¯Q¥vù1Þ÷oa9JÂÀn´pýbÔŘœw”\zÖ °Ìá>6ñ.žÅ=YÔt&ìãþáZ8Ÿåe…‰EÛ˜;.Œ)ëµQ¼'Þý¯ª´£.ÓHYN`Ë×@ôéÀ·pÜc‘X¾ÆÁ¤õNé¿£J{å¹ßƯ'â`8l®ŒýñKõ1Å¡8eÔßGbúQ…b# X®²£‚§Àƒ,·£ˆÐ;æ@íÎî¨5uó~ªà뎺ÏØaÞõ"PÉdì#l€íÜ;w÷ƒó>­kßwG…›±{ìR¬_ϼ¸'õºókU8Šv±›\ÜìgÙ‚\­ï_ÛIÔÅfô¸Q]G»®ªú}UGA™±'>öÍ?ËXw¯òØ j@€î\ü㣲›R*rí×=bÑVˆÕܸbwÜë99\/¥pÿÆÒøH Q€g¡p÷Ø•r…ÙÏr“táM ¶Í¤pðé v³÷³/$]ô‡–Q6mœ5.ù>ÎºÕ × µw=*+ flŽÒçö˜ùoîI«Úõ~?wQDWò¼Ä\G‚í÷;žÑ°Œ˜žQÓöYÛŽø>ÒôãYÊøY^bî(þ Ã6œ=Çv<¿´ÏwúØ=FDÙø)$ê_ºôYF²l£ïÏyr½Ó¾?ð4=ú=ŒbíØ¿üñûåò~r§wG äÓ8bcǦTn‰n^ÌØFÝ_V†'MýåžÖ8fìÆîHd½ÌÇì\¶c°g¦§Î©IHÇrÎ{Ž’iãøã׈(¨ú²Û8çæ9¨ñ°8æ‘sëÒ1œF àÁ7Å“€Èo{æ²´-G{™r÷œìXCN=©g ÕãàTvŒÕ]eóê8b|ä娹'¥;:–Q…¡u¬ÏòHèÑ#?Å8ªûô±ÜœWÑÌŸ~4¯ú‘Ϋx+yÇöY ŸC;–>v ®$ªJ¿–QÌ»=‰u;%ôìÜ ø¾¸œWëzÖcÌ« &ú œWÓÙŽõ<[û3_Y̹^Ô7.üá‹Ü·6¤”ô瀋ø»¶=Ž»Ï{ï{và8R9|ìUmzVƒ»Ž®´ñ§Æ6ȱm›Fª†÷1¢Óöê{Çè§OOÚ¹÷€6÷jˆ]²pZ­× E—#Õ×Ç¢‰Õ¶gLª<Ÿ“*ÞÛ|²õaûJǾpV­—½¯«Â¹ô8 ×rœÜW=°Òã4fßwÓ—óÆ÷Øú}k§¡½[”+ã@½8cûµg¤ê ï5#U-c¿lºÑýѬšN¼¿šUÓ5»íK÷YƬZïX5«î ¥žãØ8«z8޳j½ðc4V}ˆÖ¼õÍ:yÌ©Y5qµ—Âè†_ÿq\šUërnͪ¨k0îüx4«Ö=`Oýæ%MÝ룷Çh(+¶?ý¶N,l6Ö.ǹiVUpåêA«*¥wŒÂEã9$(€tImÜxÌÉi5wŽ’\¬±ð m@|‹VM«^4£Ðâʵ??‡ç£iÕ*Øq¾šV%iûž§¦Uïè~M«¨h4ĵj^uˆæ·Xaxí·®]óª%˜Ï¢yÕ™Çw9kð_§&V‹Çuibµ&üY†gb¿æ›ëòpmúuM¬V>¿Õ5'V句7bϸ˜±y²òò8ÈoþdmÑÿÜSúç‹‘^óZ;n ú6Þ»—¸bÀût²p3`œŒ€÷pzá!DÀûužT#à3’”±a" ,Ìaa|ðù܈wD@¬…˜ãÖˆe ÃŒ€•À˜,&ÀJ+#¬4^&@d6¢»š0©Ö €©×1øï=•ÀüWÉñÍï ³_jMý jÊ@ò{‡_Ù‹ä‡ÜŸL3gò{Oû¡šüÐÌrvòÃ1Ì?dòC?‘½Èk-=F‘ß ·Ý±mgò{ÏÍTGŠÀ!wã¾÷\syä¾÷r|ƒÀ ðlæ>4Êduæ¾v±˾K˜Eìóãå‹úð;ºiQ_9™ú^¬/Ô0©¯nHÐí™á"†>ÂÐC_¿Bß v\Aß{9èÅЛ>v‚¾b>—ü‚¾ö* }нŒdèCù]íúð ˜.ÄÐ×nSÐ÷Âé…+|AŽyt¡ï½¥$™ùð(èpg櫬±f>"_{4B¾÷r,Ò@¾ö\„|x¾B¾ö\„|¸EæZ1òáÝ24Éȇç+œ#ñ¡ /!žËr²ˆ|¸ºWØEäkÏNÈ׊Ì7\!xOb>´£+æÃåpsCȇf.]à@¾zÙ"¾Ö‰ZÀ×.WÀWw-ÞŒ=‚;j&çí¯¬p­ð¹ˆöÚ+íÕ7E´¢#¶öZìá@ ö^tsöÁÞ8”Íöò;f½wÄo’¯ëÕð3ëá³)¨W?cÖCî‹GÔãf‚³^k„¨WÏÀ¨WŸ£^Þ©I¯µBÐËÓ7çU>psÞ;üÁÆIâ<Ìâ&b^}*Œy½búǯ0¯êHóÒ}DyýR^{Ú ¼JjmÊó}‰ŽfÏ]i› y¸å]òj Í1¢¼z,‚<\ÁPŒ‡â5=ïµ2'=o¹­?YÏà Ãm\ëy+¶xŒô<ømmФ筇’hEÏC†Ž‘ž‡ E*›ô<Ì(\ÍXÏ[ñr~Ì­+¶xå<äwº¤ïqÛ¿Í%§ä<üÐÙiî»…•»`”óàî(B”ž×N‘ž‡¨’IΫ“,çá¹|´œ‡“¨XYÎ[Q-œ%9&B/Éyëa5ÊrÞz¨sä<¸_nêyíéy){=5|hž—òô–í2KJÐK-¸zí z)ŒE/%Ñ¢è¡úÌÓ½vˆ½ü”½;‹¤‡VvÒ£$=óvΫraÑôp 7ó­éµv¤é¥P^4½Ô¥Š¦—NM/Eæ¢é!paÖô–E.ÆÑôR;/šÞ²DH“¦—2}ÖôpÙÔšž«%YÒCQŽ•Izu½ቢ—žE•…–IÑK”(z.•E/”iE¯‘ —±AÏÆ"è¡n¯[ÐCõ°{½éyuOÖóR*‚^ý½<ëy8àèzžËâDÎK³ÈyùÐEÎ[–à &9/å#çÁkKÉy©Å9¯®Ær^]ŽÔ¼”7‹š—’WQóZ3RóêéYÍ«§g5¯Ú‘š—ºiQóê=IÍk­HÍk‡HÍ«+¶š×Ž‘š×Ú‘šWïÒj^»©yÕù¬æ¥ÛXÌ«we1¯.Çb^&Šˆyõ>-æÕ%[ÍK?·˜×‘˜‡C(OIÌ« ¶˜×®æ:§K‘˜×.Eb^棈yíw$æ¥âRļTËŠ˜W_‹y©H1õ%ïIÌK¥Êˆyí·$æ¡nÕXÌK¥Êð_ EÌÃìGM\Ø‘˜— ÒèPÑòR#*b^j.EÌsa©hyy6ÿ ¤‘¹Åûüà>ª]ƾQ¤PŠü8]qÝ܇ýħkx5 ûF î_ ûR#5Ø·¯YLØ·œŠXöa‚¤ÿ–±¯#ìKî¼`ßr+ z¸o¹•+ÙÜ·¼»O÷-ÒÄ} œ2éf*î[HÜ·¬´‹û–CN_á¾oFåó ø-‡<¦~ë:«yÃ/vr㬆Ã}¨´8¹q&ñ`¸×KÏÔpŸ3D†ûêY™û𬖉û–ëÕ‚ÊÜ·|+5qßrʵ)Ü·œ§~Jà‡÷-Ìø¥JnÀǬBAMQçf‰Oä×Úù!dRŸÈÇÌ~œ­‘z$•g“Úá‹0ùUÿ3ùÁBÿ6“_µlò«ë1ùá·È"?£.çìš^»ä ßioK“ߨáþ«“ß(Bÿ«“ß®´ÌE~‡\PŠü»"šüŽÍiò;äíò;ìò««äçüE~ß)KõÖŽËSL~‡}C~G¼"M~‡½6 ~Gœ? ~G<' ~ù©€_.0àwØ-2àw<†Cƒ_~ÜÜwÈG«¸¯îAÜ—áî;älîkMQù^‡ûüþƒ}Gœ+}‡½Uƒ}e1öåž‚}¹àp_eî˳ ÷åÃî«ë1÷U;æ>ŸUÜwÚ+SØwØÅ-ØwÄwRØW‡ûÒˆ©ï(¿MQbty¯dè;ãfjèË!f>¿–b¾º#3_,a¾²˜ùÒN˜Ï½¤˜Ï b¾3¢b¾#^›f>1}þìôÕIƒúòxC}E}GHM}Í"ê;ì¿ì;âoiì˃÷å×Ã}îF~~ á¾s ™ûê—Ì}îzÅ}G|=Í}y ¿t¬_]ŒÈÏ;Q…~¹§ _~)è—ë úñ·4úåǃ~þ¤ú¥ýŽx`šýÒIÂ~Õ²Ù/O=ì—NöóSúå§Œ~¹« _žºÑ/"è—ŸúU3F¿¼˜ _†fÐ/7ô«vŒ~¹© _nÊè—EÐŽ1¿:ùå—B~¹¾_^LÈ/ ýÒ—‚~y¢F¿<¿ _ú Ñ/O/è—'ôËsúÕýr-A¿´ôK÷ úy-ôËoýªýǼZèWgý<Ƴ>'A?/ ìÇ™uJ¡_ôjbõ§,ì—WØ/í†ýÒLàOóþ”B2ï½#œ»p®‹÷$óü›÷±<“·\fÂ;_œ˜|ö“¸=䂸~5à«À©Äíö.JÜÞÅdá½ýyÈGÞ;_²yɸpª°=U°IØÞîålÂö 6§Í©&Ü4­%ó\O7ÜC¸u Û»E•°½¯®{VŸ$.‡í}=ƒ÷˜°½D¸™÷ŽW›½-lÏ:y 5óÞÈA’tØÞº˜¶·F‰tØÞºYStØÞG-º/òÞM{ÒùFZ‰_…{8…Ò qß¡cÛKÄ qïä#i¸‡ fØ—q—wMBßH:FLîÁ"î·aظ‡¨K ÷PÇjƽãŽg ÷™É»0î¥úUpŸr!!q1Œ¼ ã^ý”p1—‡àŽóä> }(¢¥_î¡Ü݃sDsž“Ò‡Ycú`^(ÚCÃ"E{QiÚC_8%ýq^Â݃sœuLB_½>ã^ñ2 }èr®$î¥fVp¯BÜ]ˆí ÷š¸‡÷Í«í!…œ0S´ Ç”i¯Ž1íÕh5í!ñ1ø×ÎîáZø­0îß[v§¥%“·€Þ•áÞ˜º§¸= ixâ=ÙyïdÄ~ñ^Åêš÷ÎcQ qïDÞ1Ò”p—7yq®‘ËÄ{¸)éqVÂY‡¼—¢iὺ<óÞ¹Ù­Á¼wn—>€æ½úz˜÷êÆÍ{hYÐ*Þ«—eÞË1ὓ Ž øNÄÖüj¼‡õRWù´¼ÒƒR¸‡S&oÎQnŸT>¬±è;dÞC‚Ba£€ïÄ3š"÷ðÕ›ü9GTõ¸‡fè‚dàË!æ½j×¼w~N1yâ½jƼ ïʼ—ømó^7pbEWz»È‡§÷L¼‡·rï¥ó…÷WRñÞÈc$M3+^¤<¿+y@x/õùÂ{8FL(Þ«—`ÞÃÒ— &ÜóZ&Þ«geàK¬{€¯šïÁ°ñún‡Ã+My3Ú:Eîç&%X¼wžJ¬ÞÃ!‹âô4±6‹&V¬C&Þkñ~üÝqbÅ1«bù8±b‚y\@é¼wžªHÞk¿%ÞÃ]Ý·³[Ä{Õ²Çt©¯þîáÈN¤½zݦ=¤­¢jnÚÃ-“ЇDV"9ÑÞ‰|ñW'Âoæµïª•?ȦÏä鉧xOžž¨$‡Q)¨ìtõ´-+ûëz¤üíP¥rƒ–«#áwÍ›d+Èù¸vOÏ#Šò‡Û¢È(éwÎ_²ô·¹ D¤?ü’|-%ýÕ[úÃS>;¶«±ô‡Ù÷”E¹Åê×%ý¡rÕÝ“·ŒjI èSj±¤-´ò‡² ÷äèYi“°N’“òWi¥ü¡ÂƒR“°Ó‰¦’°Ó‚¢ü%UV”?,;žIùk¿ä„NR˜|ɪ˜|éoÉ×éT^•¯ÓÉ#“®ÓÙª*]ç–(;§ëL3I×™<••®3^N×yZƒw¾N|q~¶¤N×é"L•®³roŽt.FTé:7'èMºN>ªt9&é:7»°']g%ÈtºN9g:Y'B'Õ¯.&É:9S Ž;¢£D²un/C½*[çêàÈdëĪnŠî«›J¶ÎEŽ¿ÉÖ™Ëq¶NÎÙ:ó|“­s·ïm²uB7¢ûp •Ëdëô›¬döI²ÎõÖÐM¶ÎÍ)z“®s=õOºNºªlXÙ󧜭3Ï/é:“Ü-é:]º+é:¿GLOKgëô]&[§ ðTºNÜJ×é‘Qù:ëçë\{—z•¬sSŒjKÖéL~IÖé^SÉ:¿c¨²9Wg2ì%W§Sû%U禨ÑJÕ¹¯Êd‘T¹m§êDL¡|>3 »x¦¶W¥ê\Þøt.¿ªÈa$?, öIò«\IÕ¹( ·Ru~í0]Druæ¬äêtá³ÊÕ™DyÉÕ‰¢dTÙœ¬3¹þ’¬3¯%É:ë׬3™“¬3wšly/N×¹:®4é:Óœ®3¿”t`•­Ó8É:·ýGt_jœU²NX*YçêˆÑ$ëté¶JÖYí8Y窸áJÖ™¬‡IÖ9ûw¶œ©ÓŸ§ÊÔ™ôŠÎÔ™ßI¦NÖø ÿÕ÷ 2u:…|eêÌkJ¦Î¼¦dêÌØH¦Î¼§dêt»ÊÔYí8Sg]3u&Ed2u®—dßdêtrÇ$ê\ Ì$êLM¦Î¼©dêÌO%S§»‰uæ'QgýOp4muªð\ËÓ™C’§3×–<—’š&OgeÊtžÎŒËäé\'µ/•˜*I'™eÑ|º$ÏI:Í Qûxëä×[–Ú—z\•¤S±çQûRú¨’t*‚=j_*(U–N——jY:U¯eéܸJhÕNT'˜Šn\£ðßÝÊ|ØÒ«ýýóê(󟫆tÞǘþëb©ºC6Uý‘²TÝ¡k”ìí…•b©¦lª¦ÊÒš‚àÑ +ÅÒš’©5Ëu5¤s;ÿ¨Òïj±ØÑ‘’1ç€?Q é÷ÝàÜŸA½JÌÏ.…ÎrŒ”‹ý(·•RGnªÕ:rK9Æ µcÜNU:rC=O­[ª£ÜT?*m¥ÔQÚjµŽÒVŽJ[í¨´•ZGi«;J[9*mµ£ÒVŠ¥­Ví(m娴õŸ¨‰Ÿ;$·ûãšHÛTéwçïÔDú{Çý¬‰ôŽûÙÁwÜ\éûöïk"ý3Ë¿ýî³÷GŸÆ¿ýáÈùù¹üã‘óû¶þùšHç·j:¾OZ«‰ô¯ý¬ñ—ý•2:~ÖDúlõ¯¢&Ò¿FD9ßç¾&˨c"ÁX|ÏhÇ~öWYôN”«ù–HÄFç“o·bBBŠjfœû,#åÕàò{°sö¶üÀçà’žô<Îáµ]Yp?ËÃX)§ 9ÔŽÿõ~3!Sïlx”÷aãO=(:2ôÜ2Œ•ÎÈë3vÎã»ö­g~8áœ~õ@Ñó\‡ïÓÈóò˜uøoü céÎÀ#«€ì„ãñˆ•Ú¹p¢“½#ïW·ŸáQ¾nŠðÕ‘Rûæ‹§U«o¼(RJ›È'Fáú¶x¥ó|NÐoÅèœ'"]~<|-ײ(RŠ!:Ÿái!<çEލ £óú†Þ”Ú„ªßµ- ”Ú‰ìŸáfœñÑrŒÒ #ðáIçXHVŒõya×lDiá³ÜŒ“Jù,z–|µü¾öéúž—aRç>¿¯ fñ¼=ÖÍß³;&¥0³óFÉÁ>ÂG…,òwùþâVº•9ïQñ¤â¯¼Lì ¸öÄÅ}Ÿ§[QR9ç:%åôZ'Q5jWì„ܱ¶'q?—bU%áã›C1Ú;lœÝ½™ç£‹Mt¬ëÏ;g=¤ö|¶áxÙÙ‡³hëFû‹RSm<†NÛIüñu½‘Æ¢=ôçײüýý(¦QrçX>ðÑlläÙ9Nì|Þ•ã4ÝþySõà÷û>­ŠÝå÷éŶÙHx£À¤ó%¾[:y6ÎnZÆ.î7TNŽÓCÛLîŠiô"ƒ÷³·Ëß³1RnqH˜ÉªÒçËÈ«ö^ hš>û-:ҘߵZ\á7rõ‰ N!éÖ©»6&/d–qüñ¸Ü `ïÙ®…A5è.ü×vµØÉk|Gç»Êr9Œ¡ºk?ðZ®-Cu§å^4VËrs¬úËñ}kUç®7ŽUÎÃòr¬úCq­Ëͱš_R ËØ‚½Vd¡:ùÁŽ+²j0Ü4|_©1Vwm…_#idSòJ2ùÔʽ“ Eÿ彩 !‡c°îÚ<½Væ‰/o@øµ>+Gë®]£ Û»ò¾lç½8ZÓ2ÊFÑê~raóbŒÖ¼‰±·º·Ati·}Œ™íìG«£¯¯QgæÚù&1\Ëw¾š!é]ÇxÍ åÒú3†úÈñªiêÚÍ«¤hy5¯bór\14Â1`úîB-¹1`ótPLy‡Y«†mL«)vpí»§Um?~–g”ñn–£&Ö1;_£fž&Ö“ CcÞûóÛ/M¬šÁ¿éMójn|ÇÚÛñþjb­fÞ§ßõ±œ¯|À ºwm“äulžYÝì±ij­³vM­«Ê…¥©Õ«’oöÕÔZ-ŸžZ=ÎŽËs«¦¡ë€Â¬Ü žZýÑÑDo{hOÄ´Û>ÈÏES«V@×¥<»aãÄêÐuîšXó$Îkž/â\Æ`õk‚ç<ǪD€ Þëï|Òå‰U3ÌuÞšY3ÎçÈXÝØò«™5ýó|=³úНE3k~ýZ=³jG÷º6ͬy4צ™•Ó,»fV¯U¯ëÐÔZ¿urjÍ{¹NÍ­¹äëâÜŠoÁè7×í¹5'=š[ë˜Gs«éõjnµá^öŒÔòvÝ«¦ÖÌC÷ª©•Ÿ„c j©õ]É®ªúušWuÊ¡I5O冴¼÷/ê}iV­FnͪîU7#*sèu?šUËÂvªÅv=‹fÕu ¯Ï I*òx­#¦rôÅ=›&U牽ž]“j³hRÍåŽM”ûWå…½žS“ê¶kzë%Ÿ´¶4RØ™äîŽ~›íƒ~›Òu™ü†N:ûA?D[d¿óÿ"Ò“–µ\ºý°†u3üêÜCíì÷ AæI Ù:À›ý°eîs±_•X2û=Çê›"û=˜'ʼnýžSF¿ s®ü„~<8Äyc†zFIrÉï<‰ä÷ 2åæY$¿çQ¾“_?„è÷®‹*/˜ý ƒ3ÒÃìÕ›Áf¿É2¦¨w$ÉåYd¿¤Ã÷Böƒ N4³ßûM¶û»üai|“¤È~ï¨iÅ'û¡1ùý^È„‡`pLPÒwÒÑï) ;ú½˜VÞ˜Ÿ^|ŠxCB¿w,ƃû½û¢§)ôË’Àä×Û%ù½˜öù0E~°è—D~)\eð{åÖ6÷½—½ûÄ}ïHÁf¹üªÌóâ>ÔzN~hÅ'üP‹EÜ—:#ƾwÀÏ!÷UIs_ÛG÷Uõ(sß{(c±¯JñûR’ÈÔ‡_¢¼©ï=6U`0õáeëj„}¸'mûªX‚¹¯ê€‰ûp1Kâ¾v—â¾*écîK…2s_UK1÷á1 ûZ+¾*tbì«Êƾöþ…}U…ÁØ×!÷¥>б¯Š&ûªH„°¯= a_Õ«Ø÷^ŽI2öUƾ*ªbìKSžC¸L}ï­HkC_í1ôÕó5ôÕ»5ôõc}µ…gèKe 3_•Ÿ1óU¡3_kXÌ—!F>4sé¤|ã)ߤ."_Êçˆøê=šøª’‡‰ÇpÁ-à«mJß Êc³ä½”Z1îµFH{íµ‰öÚ=‹öªú‡iîDlW°—Rf½$>5êUÙ£Þ;ã‰zx+1ޤ‡ûá‡_¤WµWLzè—¯„ ×‡ W‡ˆóZwçá ‰ê„yph#X óÆòrü²8¯j:™óª'󪿋òZOåµCyí©ˆòZ—åµî"Êk¯ϧ=8Q^*]òªV¡!¯ú†ïŽl…Œ×z‚¿Ä/…¯º‚/Å»LxõBx5èxUÇ€÷޹–¿CÀKÕó]»#ñ]ýø®z%ù®ýŽøî}” @x×¾ð®µA¼«sÆ»ú²ˆîRPÇp‡ĹÇp×/…pWÕ½ wõÓb»öžÅv)d´Ã qª1ÚÕ{Ùµ^)²K3]q‹<‰êÚíˆêÚuêê‹éšL׺’ ®ÞŸ˜î}-´Ít8„+bcš¹DdĺT5ÕÕwR\×>âºÖßÄuUÔ\W}E\×^‡¸®7ƒ’T)j®k©À®:áúØ`×Þ˜À®nI\W}EX÷>®k¬ë¿$ÿ·ò' %ìÃÝÈ.¡Ö&» ̵§E½ë6¤‘ì^ä'{:Ùµ È®^…Ñ®Ò{í*‘¢Ñ®²üíF²æ›ò›e½wáf‰Ð®7cYï’#»e½Ôy)Yï{O’¬?Sª-–õV†šÜ­ëª?¹÷ˆš8ˤé!Z„“5½ÕUÜ#ê¡~Ñ)™ªÞúîV%ëaqN²¢Nø ,륦rd½ ]¶,Yþª;ñ²Þ Ò”ŠÇÝÇõ:a£ºÖûd%éz+<“‰SÒõVèG¿ŠíªÎOt=¬€ÄÒõRE*ºšy&]¯u=¸öÊ"ao,ê&a/ÅŠ"ì­ë)EÉÂÚáŠÚÂÞz*O„=œÅ¾…½jÇÂÞJ/ÒÞÈ\.šãö£–¡á»QUªãÝwÄ))8ºÞ·„—\(]µY´ýHÏÃkÂÞ{H³°—šG%ì=§Äô{Ï£'aaÏF¢…=̆³°‡©›-KØCñ±³#Þ7ì˜r°„½Ki¤,ìaqÍ¡eï»óeRöeÅs¤ì¡ Öe†ðÆ£XIk’öRº«¤½ï¬Zš¥=§Í´‡wÅ­H{ßç†;<‘ö¾ßâ[ÚKñ¶’ö¾ëâ.µ½ä³¶‡‡Á!mÏù£í½—”ok{9IÚÐc⌶çnmÏý¯¤=$_œ¥=ÔÇûUŒWO/Ê^ríGÙÃI!”²—§WÊÞ÷d¸•²_!¾û,ìÁID {p;¥"'a/UÖJØóh(aÏÓÂ^*ÐEØ[9L‚yíú,ìáëò²] {¾©èz1HÖKAµ’õ\¼ d½º'Éz©W²ž¿ %ëåõZÖ÷—¨dY¯nʲžb(ŠõV<£§³^{Á’õ`à²Ô²¢*xŽT½ÜTT½²HÕ[q™¼«zþ•ª÷lR/­ê!ă¯N¸7&ljžâ½Ï²s¶+]ï}c‘®Çɽ€oÔžØÙ²t=”§`¯°®×-šY×…É+#ì­p çõHØC×ä‚Úž _P×ÃìèÖõ0wˆÕ¤ëÕïX×K9èzëriÌ[×Ë”]o…÷'‘®—k±¬‡Ÿ ¯[$ë­®î]²ÉPº^øãÒõV—÷ˆ®‡O²˜t=X¸<¶°—ú#Vöª[ÙÃ}J£²—5[”=\‘²‡§%•²‡~ýLÊ^û%){í,){ø©M:§VÜ)ÆÊ^&ö({õ9‰²?|ÁÞªáêGae¯%e¯Y¤ìázHoöÒ÷-ìµs(ìµ’°WïÅÂ,¯,œZ›EÊ^½)K{¸˜EÐÇ©ð‘Ø§©5½Âê^ýºÕ=œEéÖê^kY_ûu |­ |õ-³ÀW¯Ï _}Þ¢ð½Ì±*ï{ÍüPDà˼…oGúõoMá+‹¾ôH |øaúaXà«‹³ÀWýÏ_=¾ø{pþƒzIÁ?¬höN6A«¢;Â~À§·Ëz/žÚ$ë!Drvé„qNÞm‰Gg¶R ýT3¬ÈÏï§È:lFä·î>Ää·=†U9tº¤asè?—ørV³†>—”/èË]Æ—«QJj†¾x’úr9ñå,‹}9½½Z¾œî‹åË™ë‰/g®Ç¾œ®Z¾œy覾¼íP]éYj_ÎtµPŸ ìõåâËY‰|(»NΜK‚CC}ñj õ¹Êsys‚½ºÎWk‡òæL‹7gzqÜ9=šË_W^Ý9]'XBß« õrçÌ3Ž;§;`¼9ó^âÍéRÑåÍéJÁå͉™Ù›³Ž±7ç²Yf”Ö—ŸåÍYíØ³.ÙîœéoVûÞÓ2–å¾±{EÁÌmZþœiY‚¶¢ÄxÔûƈ<<‡àçr£åΙ¥¼?$E‚V’óìÏYgIò«'aÉiœ®Iò²PòCRŽ}¢>´ÜÝ91eJ9Œæ— ´æ÷Þ¢Rk~¹MK~õÓÒüÆúUŠ~ˆàÖQök‡Höu@i‘î‡ ÷YøkgIùË[±ð7T˜îÍùŽm*tRþ†ƒÏ’òW}ÄÊ>³òw)Ùs¤?¨#¼>Kßk‘ºné¯î*Ò_µ#í¯Þ‚µ¿vïÞÝ5¢ýÅAÆÚ&hލhÝV¢ýòè*í¯”=‰ðkTËVÿ^{+Xý+´©´üA¤pŽ=×z*½_õèv2"$üÑïdLü$0¡ÆßÛQ¯†¯Q¯-œÌzÑSKç[•Ô `ϵÕ¾—A^´—80Óž+c·ð=UØí%>ªhÏñ<¢=ǽðá#=_£oSb‘¾õ5Jøê¬Dð9’1À—%xˆÏ~ÏE|ör.äKxfÏÕ-„ÏKù _~+ÈçÒçA¾¬öƒ|F_Öñ!¾aàój´€Ï5ê ø2¦|u–7+}^„ðaCšXfàο¿:ðF|^д>-ËZ_~ËÀ—}_}ßiqÒħ1àƒØ;_Ø­€OùFñ©Øx#>­ÿŠøÇFþ&>?À">ï&…ø ÃL|®Ö^ÄW-›øŒ øŠïŠøÔNCH‹øÂfKQ ùvº'òùž ù\ª½!Ÿ×‘…|zÆ…|u–™ºÄÅ—Uw1_Î ói?±¢øBgÅ}¹ÍpŸï+Ü—ß ÷…8ŠûBVæ>_N¸¯÷…d ü¼â/ðËÕüÜ‹üêjL~Å®!¿ ¥É/o"äç’€_[ÀOÝ­À¯š1øå~¹­¿X ~æ³€_À9àÌ ø¹[ü꤀_IÎåïçÎSÄ›>¹cW ŸK€Ä¹³Gvî,Q9w–WV¼;³2³wgÖŸöîl‡È»ó¹å6ïÎZ[Ú»óû ¬d¾¬¨íÜY­Ú»³åìÝYkX»w~–…¸÷ÎsVúš3ª½;[ÃrïÌÅùrÓvïDºWÊÊöïÌ+‰{§³'øà$Tð=‡öxìÞYë^ûwÖÕ‰÷â¨ÿÎ<*ñ^û9x¶FìáùDÓ#ï]wN’‡gkÆ.žõKâ=³^sëá0¹YÚ¿ÓÏÖ¬W.¬ç§bÔk‡Ø¿Ó~Šf=^ˆ};ËATœ×Z{g~C˜w¹^K0ïr¡•`Tî®óÊA7žqdçå¬xxÆ[ÛœWöæ¼")ƒÞuÄ/Ô>žq°5èÙ‰5žöY5åe<òš¨ ¯œtéàùà yKÀËž»÷l yåJnÈ«›6äŧ،w¹OoH!´ˆñUÆ‹¿i«¶ûž®¾çe¹„<ŽÍC€ÑÛ=8ïËáOŽÍû~BzœCó.Ó Ís@ŒCó®Ä-94ïú™–冟5ñ‹XÃC DX‡÷¦:b]¥?7ÖÁr7ªëi§r¨êª>€¡®ŠFê&˘vº…T—†ºf ÓuÃãZ’2…tÝB¤ë"Ýdy˜Ú¾,dº*."¦k1Ýdy¦?ÉtÝB¦ë2Ýd¹]<Æ2]·éª|‹™n²ÜLm_g‘éú1dºÉò2µ}YÈtÍ"¦ë2Ýd“O·éºe0]ÕÍIŠ¿vÈ€º~¡®[HuÝBª›,/]­ËBªëR]³ˆê&˘‚º…T×-¤ºn!ÕM–—Å(ÊBªëR]· ª› kYÕUU$c]·ë&ËÃá‹°®[ˆuÝB¬›,ÇkYˆuÝB¬k—,¬›,GlE¬ëb]·ë&ËóÛ|ĺ² ¬ëë&Ëík ±®[ˆuÝB¬›,·G¬-ĺn!Öu ±n²Ü±¶뺅X7Y^Øg Ôë%ÅlbÝdy›.GX×-ëºXWï×X×¹®yÄ뺅X7YÞyÄëZ˺n!×M–w±æºn!×Õ§É\7YžyÄŠëú!×îk˽þ¶Ï†Ç#Ö–çòˆU Џ®#®«Ì\×ÎØu˶{ÄÚ²/±n™d×-Çék˹{ÄîÚõ–¯Ç#vŸØ®C¶ë–÷Ç$;à®ý)¸ë–õÇ$k¸›,?&YÃ]·™dm93É®ÝuË•IÖòÝdÉ$kË“IÖ^³ð&K&Y[ÖL²¶lždmØ3ÉÆâIÖ†#“¬-g&Y[®L²±d’µåÎ$kË“IÖ–7“l,™deçuËšIÖ–-“l,™dmÙ3ÉÚrd’µåô$C&Y[.O²6Ü™dmyÖCV¼×-o&YYÄ{ݲ®?†¬x¯[¶L²¶÷ºåÈ$K&Y[È{Ýre’µå^~ Y1_·<ç!{¿S³b¾Érÿ²b¾nÙ¶CVÌ7YîCVÐ×-çöcÈ:Íj,¢8R9vŽÎÖǽ± ë[*ÐO®GrsÚµóM&N¹vF¥ŽkgÄΊ닫Wô¾¤^ŒÞ‡¡7{wÆqÐz_ê£÷%¼)z_|÷¬÷ݪÞSzŸK:•wg‚…×·^ÖÊ×gÜ íC†-È'¡} LªÐ¾D :´;™lÇ¡}‡³ˆ$´¹;¨æIðÚ„‡üýȾ²(²õµæÈ>èpÔØFdŸƒR*²ï»\å[qdíó‡öa9‡ö•Å¡}ÛùÃË5zBû&ÐBûv»¤:´/!˜ í³Ëz…öÙÙ»BûwQ¡}ËíP9‡ö9f¢BûS¡}ŠˆÞǹ Ø°‚Ú·’§*¶/Í^@°sbûìÊÝbû.fÅ/àÛ—³¢ø9” Š_üÞ+¶ÏÁ¥øÙ‹=Š_]a¿ót;‰íÛä­y:þ@þ‰íÃt1eíl¿}ÏÛçhœ(~©ÀÅ/~îÛçøœ(~RiÅ/q™ íK°à‡fä*Á¯YÚçÿ·¼wÉÕ%W²ôúE6«áÀßN‡F!Ü1ª¡T"š?D³µ–Ù⎈{ㆲ„²uÎo›N§Óé$?Ú«~ýfÚµO°\ûBñÅ ò?¨z ð³‹äÚ·ï ¬²î …_»¿”k_9*IáDtÜ;åPWɹ¯ÜŽÚ¹OîåÜWXåÜ×õ¼r@ÛQ)üÚsO ¿´Hú—&CóÖ¯z«½ûÊ•J ¿¾—~õí•w_¹·´wŸ|&Ê»ï•× ¼ûú"*üLB…ŸIäßW~*Røµ‡~íTþ}åM%…_ öÒøµGSù÷Õs–Ư|LÚ¿O^Yåßgòï«2òï;×`.öjÊÁS`iüÚ©¨üÊ¥4~Õ¾2õl7<™zÊãT¿´Õ¤â¹ÈDÉüûnÅ-ÿ>úâ¶¥gy –¥g7G–žõXåßWU–žå§Õþ}ry’?|ãÊÁO~Håà'·­òï«Þþ}tj÷>½Ërï«Ýî}rakÿ¾jÍÓËëçQ]lŽiÿ>¹G¶ŸEû÷•»\ù÷iŒ¶Ÿü¶Ú¿¯$òïSÛ¿¯åß§ï£ýûÊ1O¡;å#Ý¡;åÇÕþ}ålXþ}òÔkÿ>9š{ß冞öÕ·{_yÔѽ¯{¢Ýûä®Ùî}úbÚ½Oï¡Ýûôèß×½Õþ}usù÷i†nÿ>uhû÷UkþŽ_yá•_ùî™ßþÿ¯¼ðÊ¿O÷jÿ>͉íßWõ”Ÿú½ýûªžòïÓÔÕþ}ê¯öïÓ›_w!üf?>®œ’—ÈÁ¯§l9øuµîà‡AÚ~ºQ{øé¡Úïê)?ÍíáG‰åMzïm¬‰9FX {F <ûÑ^Õ…Tä¯%Mzcë3ü%éôDu‚’–tz¢‘‰a—¶JÒUIÔUµÄªúÒ°ÞŸ««G‚ÿè„IïˆMæû§&yj¤;V¤·RËÜOøÍ³ìWY”þ^Q¤y*%ÈoGÈ{™>×SÌükÑ[±“_ʨ¦J•¤Š,Uë©"¬ÆJ¨–N“¤j'mû>iÐÙAßçË©:\Åoî3wyXJ§äK+úm½ñ¡‡å]yö¼o8'üK{P¾±ïx˜,$­x§äƒ•œÈÞy",4lßù¶ƒœ¬#¢ëzü!Ãkq°z#Ú_Þ•¿Ëq˜?ÕÑÕÓÃjvè‰2áuvšãÛ;°C/Ó»w„ü•Eî4N}DZÃöN1ß#x[TÊyë§m%ß¹WKË»r%Ÿ³Û,i>Po_?Ñ›PÙ¾#â ï@ûï ïª6eo|F/ gÜýÐêûc&»ïønXÅÊŽñOm{Í öhëi[W}qäö¶]ìûát½Bâ¾á/5ÜÆøøàç¹J^ØÅ^ºè¾ñ‘ÖgÁŸÏ¿•0,¤alIÞ_ËçÍŠ¯ô>5Œòõ˜AçÞßÓc|„{ȵ›ÃÖ£ðáÆŽc›³Ói‘GøeäÓ×’‘^O‡Í#¼•â+}dé7,Áëö‘’ y2gQÅ5ãK‹IÌy#bZ|-{ Òç©£»Ž8 ÈØ§´Ä‰…Ü}0œRÏx#Tm@<öãAðÓ-éÔÝa°Gtä÷‰Î¡¿ÙÜÀvD°Æø>+ˆøÈÀ‡={±½þ€;æØ ˜tÆglc©g~¼ñ}>2]±äîÃ[I„Œ)|ç#2o¾8ŒÌ¦}e{˜åŽ#Þó¬‘óç€q¬T‰ã¸"úW›°Žc޶ÓígÇ1ÿ» Ÿ’tt‰5“Å8Þ[QÃUñHš¯<=ãø6ØÆö|@ŠGµs%Šqn8Î8b{m~˜SVÒ¾ùy`%íšç"žßhY#óÂJšþ‡(sc%½iÞ:o~£>NoXI+ý$ÿ\IkõçÀJZËï”äRÚýw~XJYñŒkÃRª S€¥´ÂòkÇRÚ}sXK»âëÄZÚß$iÙÛu¥o{ 윛Æu_ ﯊,¥áfÉöÅÛXnõb-ힸSkò—Qlc¸ñ»¼¾\LS#ší»·Gñýy«;”ÒfØ>§Ôáý7½…ûÀjÚ-¾O¬¦=Ln„e±×pßXM{àÜ7VÓþîî«iw÷{êkåÀ¹G†ùÒÏ’¬¦òÜVÓ9‹: ÿxv,§ïf§Ë©•‰3¶Ï{ð9±¦v Ÿ+×Te­˜¿±¤v_<7–Ô~{ôò^Ë‹%5œ;%cý^ŸÕ.B"‘¾Ó:iïšw[FÍ*iq‘tæó é ™73ÆC­¿ÇH9søzcOœßút q F˜¹ã#…Ãx—œã¹Šö¼9÷ 6¼¡‚ö!0b/ì1Bí¯{ÄV8Õläõ³óÌ!VG¨ŸýA‡tïÍÁè_òˆ=°¿Žšçå±îLs“ôüÞ™\Ƈׇþ>•¦¹ˆå™¬ò°ßy$r]>ÆÑÿx÷1-ô˜ˆ$!K÷Ç~æóYëC¦»G¬ÛK+˜(¤Æ O–*Dõˆ-å±< ΢b’2Áù3 “Dso0ù±™Å ÂN˜4^y²%˜{ŸÚßæÊÏA,f<˜0Årï+²\„p»–‹M>·Ð`¹°(HÔ É½C1ʼnroXùƒ€rtI(÷~Îqï'W*qÜÜ Ó!I ÷~ô1Ç…àÙá87XêuŽ‹jˆ/丸|°Äqï'£$\HøÈ¹ $[ÉEt.Aîý„ J€A¼É…„T ’ó" ¹NF%’yºÉÅcbpŠäâ*¢I.$Äi’œK@r!!“‘ä\’[$¹öŒíÔI.Z(¤ÊEÒQίÊY·Ëù%€¹˜ú8Zs!Àj%˜ Þ Y.šÂ±H–³"@9ä²c€ÜØŠg rvg‚ÜØŠõ rQf,$g}G”‹«05 åúæ$9¯(çå¼ Pn`óZ$ç7ÉÙØÉyµ ¹j‹H®‹ˆä¬@®>\Ü™Û)’œK@rÝ"9/’›BÆ實è?b¹î±ÜØx&#–ó‹Àrv+À\r‚9»7`.„,À\߇<ç—€ç¬pÎo œ ¥ Î~„sýÞ„s^8¬¹œÄQà\ßœ4gEHs.ÍÅÇÃu’4×‰ð’æ¬-¤9¯$iÎG𳦿FžlS2ð¾5°œW –³WM˜ójs] YnlŠ#(–ëI”³öåü" œ—ÊÅ Á­QÎZC– OÈrÖ¾D9{J¢œß;Q.8› ÉY ’\?I®¯!È™'ŒÃu³ˆpV§òÀ7û3è­']Ñ›}u¤7k%àÍžðfŸàÍŠÞìS¼uµd·š…n=üHn6ˆIn.¹¹zVSHn~ççч©Ö½§>LÕrëUOäf þ}˜\·.BnëG ¶ù5À6k ±Í>`›=¹­_<±Í’Øæwz·Ÿ&±Íª÷/ØÖ%@möùµÙŸÚìz@›Hf³6€Ù\ÌfÌæu&³Yw€Ù¼Ä{ûç fó¿Ofó[&´Ù— hsAB›Õhë¡ÍÆ  ÍZhóJÚì ´õÇ fó ’Ù¼Él=ºÀl~‡ïb³Y˜m`y¬6€Ù¼D2›U fëv~§ïìˆlöç$6¯0‰M<—´æ÷OZÓ_“ÔüÚ$5«mZKëÖš9ÐZE>l¥[×+­›ö(¥u3‰ÔnÚe›ÖMª¯„µÞØj·O$\j7Fœ5µÛñëuXë@‡¥vS@ ׺Iá÷ÏhÝ>¾ÈRºu5RºqÝh›ÆuéÜL '¥[¡„”nýRºÙUç³èÔ¤vÛKOµ›ëápFhê2ªÝ^f’*­[*HZã&½X)Üjl—ÂMñmZá¦$i­p+Řôm{¡œnŠxÓ·ìéÒ¶Iç(e›tU¥lS¶¹Öµ)–PéÚJ,U[UJM[••¦­Tæ¥iãP*M[+ͤhSÀ“V´)}ckÚ˜DñïiÚZ&M›’M¶¦­+nU›nN][©Í¤j ^VC]›FA©Ú*®tmÑ‚ËñÌšG][…Nie›®”­Û+…›2¥–¾Íª¡¾­úJê¶ŠTê¶V RÛVoIʶî;)ÛJK)][%9m]ÛWz4éÚFÁum­§€®­µ[ÔµAåH=›Ò–š­_†ÔlÝR³Õë‘–ÍŠPËÖÇÈR³½LpZZ¶¾SiÙF!µluQ)ÙªJɦ䂭d+ ”l‘N„G%›©Ç¤eûŠÕ¨eëþ—–­‹PËöê`TZ¶î iÙúEKËÖçüR³Õ«—–­ë•–M¥d«®‘Ž ïUúµîËR°•JU ¶ëÍ3ÛV¯Õau©×úª×ú­•zMšrj×ê ’r­ZJÝZ ©Öú–j­†µTk­J/ÕZÍ R­uÅÔ¬õÛ(ÍZ}ª¥Y«G”f­59¥YëæH³VCAšµz‡R¬Õ ½Z'éÕú¡¤WëÑB½Z)Öª¥Wë=Z35z¤VëyNjµîéÕì*êÕê©©WëÏzµÒ[R¯ÖuR¯V}BµZ÷Õjý¸T«Õ+¤V­E­Z¿@jÕjK¥Z}&Ò©ip¦J­»:µ®^:5•—J­VªÔJÏ)ZP£V- B­žˆú´nCêӺϨO«Õ…ê´î"ªÓzz£>ͪ€>­×9êÓºêÓÚF†ú´º+Õi5ȨMëé$µi=¤M«×BmZ«¹©M뉃ڴê*Ó¬”i=Z¨L+³êÒª'þAn¢Â²xÊÏUh_øGaÛ&.»Bo–•´°ì>´[–…KÇø‰eMe³Ÿ°å–5§ÊJ3XXÞH²ÌÕ%œÃQ©ÀlîZ¤4Ãâb¬-‘EõX°,Ò›ÔÈe¥Ô-.«Y±¸¬”ËfRP—5d8‹Óö Lì)¨¯#—EÞ*ÚÈe×]¦˜ä²Hغ‚Yæ10ËA—·—Åš4J,û2–5®–Å}d‰5¦{WTvˆiXa&Tm4s$•eö©ì¼õ–De¥ß/*;/èÚeóÑe²H( WΛڲ\_ænâ”Í•HÜF(Û_eÊ2nC0‹½%©’d>IÔä‘ÌÎKúH‘Yß\d6oNUÐ,2=‹-d¤†îSh–é¤IcÀ³Š3_|Ö/W€6G G§- ÔkÈ>!¢ÍjˆŽD´Xí‡#Z¤;"KÑ"ž8l ‰hõ^ŠÑªuÅhUM1ÚñÈPv\2R$£íÌ­Xˆî )B0ükZ— ŸErÒøì ÇxáY ˆg³GŠÎò`o¡³Ùҕΰf‹Ì*Ùw‘YÌ^2|™…WƵ˜BÖY¡YMçÅfûSF™d³Þ÷ÅfÙ‹ÍìÞd3}ÅfŤØ,‚ÏçŠ)4«N™¥¯É¬ÿN0ë$œÕ-:ëkgóuJ6‹àÎH‚³î%ÁY÷‰à,¼À¿…Îú*ÑY-ÁÙNgù‚³.A6‹ce"Ù¬—Ð,*ß]iÝ $š…/>­‰fÝUD³~B³yñ€h鏯‚f5ŽEfѬ†Õ3Ó…Õˆfó d_H4ëΛu Îj‰ÏöAö"eðö…ÎÂöáXÌk  ÏZ@:«ñ!8«QI8«ñ"8«+gý›pÖÏ"8ëLpQøW»Çî7ÁÙþJ,:«QpVƒClÖ¯LlV©šŠÍú‰ˆf%™E¦‹Õæ±zEhÖãIhVcCdÖm!™íô).0ë~™Õû™u·ˆÌz®™ÙHf&™ÕK"˜…*ì © /O0ëo`vœ‹îÌZA0ë>#˜UÌú›$˜…†+Á¬ÉqF“K€™µ1ÈLŸ¹¬»’\V—“Ëzz"—m÷/Wšõ݉eý†Éeý³þ°Ìì€Yw"ɬd–‰ÜÒÑdV­"˜õcÌÔIJ.,ë6ˬ‚øþSÿè\V¯XÖ“+±¬ö¤²ž²‰eõ9‘ʺ_HeÖ&`YÍ¿“>¨PŒÁÜ7m@b#|ˆf0ÂHO/'±Ñ#è«Ë?;Õa0ÂHÎ ›‰ùE@±‘î`fÍ8¾­b°ÁH “¡Øìî$ Øøn½‰bñÊ©Œ!‹…DÚ.°˜—‹ÅfYÌ ÉΊÐS}Žb!áæ–, ¦aÌÚ‹"Ä@ X„B:Ý1­/!ˆYãhÎZ*ÂÍCG¬‚9c?¢Ì#EÖç,f­%‹ÅUÃ5dq'¨SdÌ[pmS%‰Jh˺.Z_Ò–±Ÿˆ¦ŒaùIP¤)c·N¦Œaˆê$æEhÉØý@ É݆Œ™¤ §!c= íí7 1b'ÒŽ±{RvŒÝz2ÚhÉhš2v·È”±k–)c :Y2öØ•%ã¼ùç2/BCÆ.BCÆêJÙ1ÚiÇØÏ$;F+CÆ~$2öçHCÆPXBaG;ƺ¦ Õ¸²cl¬›R†ŒõæË±Þ|2êM–c5®ì58ÊŒQßbY1ÚhÅØ×ЊÑîL+Æ2²bœ%ÁY´a¬iL6Œ& £IhŨ/¯Œ«±2büŽò[££IhÄØ})#Æz Ù0¶€&Œ}#Z0vµ2at Lë"Y0¶€Œ5ÝÀQIÙ/vßÓ~Ñ´_¬¦Ê~±»Mö‹ý2dÀØ/LŒúÊ~±úZæ‹Õx™/öd¾Ø] ûžˆæ‹Ý™/ö#É|1½YÉ]\9¿J²nž¬íÞ0_Ô[Ö‹5µËzÑ.ùjå¼Ý­–ß²^¬’õbR2_ì"´`¬Ù¨L»)²aìΔc$RÊÈqÎ0ûæ–+k¦!cßœ†Œv+2Ö«¦cwƒì«siÆØÏ(;Æþ†dÈXcW†Œ=ÆdÈØM‘!c5EvŒÝ ²c¬’£ÝšfŒZ9eØH;Æ®XvŒõ²c¬IWvŒÝ^Ù1Z-çºxÊŒ±G³Ì»dÇØ.;Æî`Ù1vëhÆhÕÐŽ±+Í»ZÚ1¦JÁX÷$í«óiÆØ £U;Æðœ fŒý*hÆXƒ€VŒõ4bì¯ÿ}—FŒ}}Ø0ÖLÆúM ÆîZ0ÖÒ€±?0öÛ¡c7ˆŒ}Ø/öbö‹=hÀØc„Œv 0f®#·`ìV€±Û@Æjíµ’ùbõ*­»<Œëi¼ø>r½£ñb·Ö‹ÖX/öCÑ‚±{Œ} 1ö« c N1ê·%ù)²'õOæNV¹wÊL™vʬÒè¸;™´cò'ë2ò'ë2ð'3ýÉL²vS£C™•€CYßGe&¡C™KàT6òZ|Êú©åSf:•=ïO§2+C§2“ЩÌ$t*s œÊ¬f:•™„Ne-‘W™Kb1q0,$„®¤°øM.&…ù5 0/C§2“Ãü*p˜—ˆy€˜µfp˜×3 9¬/"‡ypX%”*‡²¾æ|ü(ÌIav=(Ì Â¬Ì@0ä"bX¶EÖEÈ_^æ˜K@`V Ì `~ Ì% 0—€À¬š0û þ2Aâ—Wþª¯."þ²"ô#3Á‡O³ /¾¼VЗ|™ðeÀ—WøZ$Ÿ¾JI@_‘ÞLJ¬¤/€¿É—Ÿ¥¬·Å_^üåØ"ùðYv= 0/ ÉIÞÚñU–—; ÌŠ€À¼Ì$D°¾ˆæE€`.ƒ…cò Aå›¶Ÿ_fE>„¹ÖÎÍ¢0/ Ìqa^fEa^fw"†Yb˜K.Ÿª˜æE€a•#Of×ÂüÖ€0+ój¬V@˜ rí|*@ Œ»- Áõ¸•¢Kv®uÑÁ¥“.c\6ëÏŒ¬i5À¬ÈÍE5<\0ù+¹Ë ¿\+K0¸Tö €]‹KåYÑ66.•-Ù±V¶ààZi®•º5ÁË‹\\*³ñ„.»àæ*yþû¡ ^.‘в$âò+×È.óq¬2$®P‹Läâ}È[þwð–×qr™ì2Öɺ1Ë%7WʾèáRÙ’—k¥I¸XžÜv¸¼b$(ìk@\V"ˆËÿžÈÕU¹¼@"×"ärA2— ’¹\е°FÖ]ߥ]öç ]þ礮þ3¨Ë €º¬@R—ýNè²ßHBh$s½«€¹¼Àýúõ‰\ö;‰ËÙàª.yËþþa1Ôß[v;ðV_Þ²ßÉ[ö;yË*<½9À-û´e¿‘c°¯NÖ²¿#Á`ÿFèÙ.Ÿ¤å¿‡·æŸÈ¬ÓÞbwrž›%R+WV‰÷ÎsséÂÂ?cq Í·\Ò…•JAª°:Ô§&¬U 2J ç~ú—Á*1ã-à>´J”¦UF‰ezÑš°¯Fª0“À°"¼JO±‘ñõPÍK‘Xf‰e%Qf‰e|Qf‰T¡–Ubõ¥¬¥-£ÄRä–Qbæ?‡„F‰¥ö,£DéÐe“X&Ne”(¥µŒ­%º„ÆR¼·&ìÓ{•U¢Ý‰V‰S‚+£Äzh%J“\F‰mý&«DkŒ¬A-´H”ÁC$¶¹œ «²G”ööˆ‘hžÆ†´Glm´w‚¿ L»E¥û~-°îcY"փʱTÞeˆXVeˆØfÀ2D¬jd‡([Ž2CÜ2:”b¡¢U++D´â&¿1!–1G!Ê\E6ˆe­Ñê¯Öv¥u…=!mÛÂCFˆe#Ä6N)D™È±Md‚صÈñ ’¾lÛ´IFˆû!0!v-4BlK,Y!¶‘Ì­1´ClÓ>¨¿JQ^vˆ} íû™"V/”)¢l·d‰X­•!¢ÕJCD3!”!â&‘!bœÈ±Ÿ±L[BSľJ¶ˆe#SÄíÓî¾l·*°p¥Îk±i+[DY.ɱ~Ó±_ªLÛ’¦ˆ}SZ"¶uJY"Ö`‘%bÕ”%bÑȱ†eY"Ö;“)bµW¦ˆýˆ2E¬É¨4`á+ J’)bY+ÊQ]]†ˆÕÚ!¶ÅcÛ!’´h†X-k+DÚìÉ Q_‡Œ»„lËäF6ˆu—2A,Ã?Z öãʱžN6ˆ- ê«ÌJÚ±š"ÄȱÛFĶR,Dº`µ "NÆÛ‘¿eƒxVÌDÙ –Ý“lÛ²I6ˆõ²ÊQö©²@ì–<ë*ÙˆÇï°0’á¹JY Vse¨ZÊñXƒwØ„aˆkô޶Ñ+ ÄêYY žåP&Ä."IJ†¤ b ÞuÁlÄ®ä õ@ÔyEÀ'?ÜܳíYœæ‡Çªóê‘'óê€Ö‡UAYòï4>¼JçãÃÙÏô…õa]OëÃËà«Ç…¬UZƇmùGëö „Ê«öhe~Ø%`ØCXö‡Wñ€ýaßåÆ:*×4Új<ÈüðZìËÀb¸%­ë^M\;Mùd ëC3å£ý¡ dXf¡²?¼‡Í3þR›ß Žï™ú^2|üf9‚Ž<¸±R¬©Ô°"KP£zªˆª±2¬¥ÓÓ°OO£zº*òRª©ÒÓ¨&KOS5U¡ªÉJ©¦JO£š,=MÕT…ª&+¥š*=j²ô4USªšþB›•ßÔôçsØñÎÍ…¥°ù7ežù?*‹Lç“ñü6ÿ õÌóŸ'ƒMøBÏ9õwØÌ×ü?û¿ÿ£òÉü£6³ðÿóßÃuÒ¾ýïO%°±y´ØXV›*Í÷܈†ˆpõÉG`ØÐLÁ—†F æßù¸m?<÷Ønȇò{„(ý†aš4ƒîüÉß»!¢³éÎÌØð½:+Èúä®CK¾м›§ü|Eg:ô3ôËüÏîÅ#VsæÅÀç 5Þ—±¸€óg4©âj}‡yXJ”/¢,– æ{#F”…ú2xœ}úF8vX¨ù{X®ÙœHKשcæ¾ëÄÏTñ~“I3kú–'€)xEææíÁú‘²bÄÑøD®_\V9Qâþ…[¼ofÂŽt¼hD˜\f¼¨‡Oñ\[ß_Èö!ð' Ñê)دlUY¢DlmCp#6×—c‚ %æ”s¢ŽL®þ¥×9J¸éÜË%÷‡f½H²ø…Û|$ MIÁ{¡Ä‰\œs§š50¡r$ˆBë™±6«ÌD“_ìB£·â]ìhy&…äSÓóñ#Ùƒ¶Ç) $'•Y™kWë3ëfH>4ÿÍ,ÜqÏÍû3Þª÷b¼³]ýz±1s[ù­ÕŽçgó"9ÐRO¦Æý!x„ªgŸOœpà°3þwæ#([ÜcÇ#lÈÏ’ýaÄÇÛñ±÷<ñ Û/VyöÈ ÉÀ æˆ‹fÝx„.îIøV^<æ>Gð‹Wwðª/ÓrGˆ¸4)Þ·cþñY%™?=¢@ü8ÆCއ’a‘èæï3)»²;MÉ•œ]ñÕ¦äNЮ‰ $‰ÚŸ‚0NÉ“°ý)Üð”D´’µu#;³³ÌHâ® PSòݦwûvn Ý5M…äûõÙL6%{¢·K&ßœþZcJÎÜù…oI$åþÒØ‚+w˽lJ"bCλuógÍt’ï—ÇšO?4Ž‹Ñ×^ŒªóCp–Goöü¾%ÊÉ$£ ÑYg vDgaÜ“)8í€1gB€è,[uîu>¿/`ëb ŸLɽ/a§Bò­Íxž%ÒÍ”¼¹8*PÍŒé#pÖ’\­eb´0L̤Çíüeº¦`ßÙv>î½69Çók_ZrŸçÖß—/¡ñ;WÉG ¦ä¾y¸®)yr¬pE¶¹PV‚ ÁîRÏÈ¥²bOE^Þ“½‹ƒÒ}{¶\,o™R…d,õÄu¹÷ÃÐGÕ»O¨p—[??cyÌ't¸õšŸÈyâ=÷„þÖ.…ä]Â#MÉ›‹¦—ŠZ¦üÉ H]-¸öÀ/¼¬Ú7ìq^øÛVê‹)‰Mž×û2žæ Ý­¥—‰EúñßPÝ.ï4-”òin¶ì]ס—g‹ ß*ù®ìx¥ò™+J¨n«az[»b0¹÷|SÅmyš’Š‡¤"¡¸µ|0SÂHý4ã¾¼FEDÂv5$ãÇ Ì0¢´&SŠÛå†Eªw“‡ÓËüóËà‹]ò³Ü*Žw÷ꕦr{k¿sùŠ#x͵^í­ £ˆþäéÃ"}úýkX˜¨HŸ~þ:Ö¶†·CO…`üÚ—¦„ן&ÖII¹ˆ/}Ÿˆo•ˆV¦©+–~UíµqhÔE׻̈1a¾Ã¯çøåiÖ"Mú¶Î&1h=þåÄÀ°×}ÏɤçËu²‡p¦_¿ê¶û~-3…‡¬áûñýòh‹u¢T¡Íþl&bYœ†î¥Ï½"Ë:&°,ìwüL.ë<5ä²7¨ë$†ÅÒ9Øw€[bY:ÀØŸ\öÞ°)±ì;o¨óÈeASÀ `Yè0÷“ËBjbYXN<¸Ã½ç¯ƒÜ—\Vö?Ä2/XÖFgIJ2ð#•ÁÊŽDV˜2û»Î²éL³¿&޵ hâXÛ{ÇÚ¼–8ÖæÀÄ1/‘8ÖæÁÄ1¿$y¬Ìz‰cÖ¨ï  8ŽÛ“ÆìzИÝ4ÖÖú¤1/qÀ†Æö„±2Ì&‹ù-“Åü¦÷÷ëYî‘,fU$ŠÙ-†{*Ĭx‚X×'ë[ŠÄªJ˜ ˜²ÉïCæE®}i¸0l¹è~hµ [Vp˜Wò¨í­ý>0l©v>€$`¯E²_|‚’û'~-e¿zþ‚-eÁÂWnç1l)‘¶”xa”j’±ÿÜ`°¥ž_p_ ó2À°¥ÌŽñÃ1¤8l)rž?á¾Ö‡‡y%÷ýã €a^äÝ~<õ’Vd`ulM¼»Z0˜w̳Á•bpc ³Jšy[%çÆæß//‹èšë^[óKžíGÏÂüš÷fëu œMÆÞ}\ûï/­½«øËKÐÜ»‡-øË‹Ðâ»×Á¦ßŽ`.¸_¶\÷}®%Þµ†÷[;üìÅ_v ðË‹ º/š„Æß}ý[@óo»æÔ‚©.4ï‹îk½„Và.?Ú?ÞgíWØRäÛ4îkó`.ØÏÍ­’Áæ—äüqÍuþhÿGF—Œ“6(l)óžl^IÆÆ'hI®—¯òcŠÃ¬Lr˜• ‡-%v}q7ê¸×G ‡-Õ\Û:>Èa‹$Al¹ê9¸å–„0¶”yµprrJ[JГÑî”4æe@c^D¶H ö÷«É 4 uÕ?‘s¦”e8ÇmeÙ1x eYì?6£²1§3ª‘@eã= ã’Ê‚>þNôÌ\äI*‹ïçDIJ‹ØGíX:¤G¦ºªä²Ž¦A.©3}™ æÛ ã¦í62 ;o‘X¢Ù³µÃÐ,j WÍA¬@'ä³xv6 €%†4d[6ü"@'¢…‰^ÍîŒÖÑTÈh~A2ZÇ%#£uè22ZÄ©Ѭÿh^E2Zt i2-!-Ih¤ÙSÒFZqâ‚„´Ž–FH‹*ÅLIi^Gbš=0m|l0Ío›œæ—Œc¹G‚ZŒ4¬ÿ$µ0ŠãÑ4@-†ÅàA;@­{G¤’“³P­G—P­¾¡Ú"ø²×­âDjQäˆEL¢8óÇ2 RKï×—E°;ôÔF*œÔâ"ªj#S÷ ÝFŽã“êi¡Zd¡Z~¡ZÔ3$Ùþ§N3ƒÔ¼- µþèDjQFªÚrU’ZôË!¾KR‹kU©yO€Ô¼Á@µ¸ úÈ µ°üœÔ¼Ò µ+©…d¼®+_‚DµÈØ%¢ª-’dµØ3 Àj!áa,Xm¹SÂÚrÑ«†k¡µ#T+%¬¹ amP P‹†I·• æ·¨E RÔ"G»œVu&¤L<áê±tÁÁ H“×ZþNH ‰´ €´¸«sÉhVÍÛDó"Ihözhc¾ ©h#èYKÚRï ã‘ ~à3ÿù`=¼Z«–x¶HÏFæ÷–$×ÄÈvNAÒ™w èl‘$yGά£@g.H8³n 6÷c¬6Ø~vØÌ‰f^g¢™õÈliX¢Y\£l½/-)ØÌFR ™ÝdæÄ<êg˜8v£N*ÁÌ_(ÈÌ{hæÕ&šE;¨O™ù šÙÍìË 4[î‹@ŸÖ€3»/àÌ›:³–Îü„@2AÂÙrA²! <[$¾ÙþJÐìЖIhKk“Ð\DóÆÑ¬ã@hñʤ#¢ù­ÀhÖ š×‚¨H~ë{™@hþB@hÖs4´ 4{©4Mm 3¯ 3k'èÌÚ 8³ÁfÖÐ@3ÿ™dæ2³vÌl€Ë¼’Ä2$•yo€Ê¼é e-H&óŸ‰dÖ[D²E’Lf'“y5ׯ¹ä\¬K"ókžƒs‰ÉcË}Ù3õ”Œ­ýŽõ{$uÇÇü"à˜_³Ö‚ÆìÛ"uëþAzXq}N`‘r¦| °“ X-c°ØõTƒíìäŽ0ñW}qâ¯ç+B¹ · ¯â—]q¯~iç*úJ•®Ó÷fb¯ÚÎ{‘¬Ä^UBìõð1‰^µÍz•ë»Ð«š”äUûP‘WmÆE^&yÕFUäƒØJô²K€^V‚èÕ ô*zNò*FyõŸ^M±¯Ú+ ¼¬ €WÌð@J‚ó5xY¥¯HJ‰1GðêÞ"xu»ÆZ¸ËZEîRG4xmС5w=šè„]†6À.c*RWHc×±hÈ–[“»44Ä]½ñxÝÚ¯5x‰¡^†b/C›"/Á«êwu `Wœ`Ë$QÔU Cì2z»s]öwB—ÞxCW?² ë¨£ ŸW:ÏýKqS'…’›—9‚}Êj#/+øyUœùy)è†ü¼¶—&¿òó²*àèU™Öäè5¿cÑØ¿ó)èêUýrõÚÞUqÕ1:äêÕBW/+W¯ŠB$W¯øÌê©6†B Îg0sÝó=Y;⮸ò Ÿº«@OÙ†ôÔ)IOÞȤ§Ï _¯înÐSH|²¾>ÙMÁOvð“µüäu$?uÖAò“_’üw9_ã'{!à'ë=ð“ ‹((ë_T,T¥’Êedô „Z$‰PÝ…b¨E’ ÕxÄPËÝ“¡"¾[‘WFzš²’¡–Z¢¢Œöh€¨”,!ÊëDõw+Šò«€QÑû¢¾Š¯¿p&A*Z\z¦©ŠQŽŠä~]}ÕsŠHª#߉¤I’T‡ØI…D*¹©9XÅ0 ©x€‡ ¡$©h?uIRŠh&’²¤*¦F‘”b7IU¦‹"©FÙÀ¨)‹‡×R8Ê.G):9Ê® GU4ú©ÊU U©‡ ¤F¿8Ê‹€£Â±Mdò2 )« U9Ф*yQJ™' ¥ü‘ÀRV(eEÈR1 “iÀR•^¡`JùŠ¥j+˜ªœES~§{]ISÝ8Ò”¢ýL1ýO¡”¦‹¤¬“ˆR²XJÉX §*“AáT? qÊê%OY‘k·4+ÅS•ý €ª_)yJ©3 §üð”õ™*T0UYbSE°µ›‚áÝD¢2“vô;&Q-’wm>¡ª;’LUùR ªdñQP¥¤xUö‘¬¬’¬*Žf‘•½S’•RŠY•ýE‘U™ŠYUÚ¤¢«Ê¸Vte/žxUI„Н\Ʋ•å%YýÈXÝSd,{l2V9"–õ71«’¯fu½Ä,{jrVZ-ÎêÖ%fU”â,{@‚–5޹=¬`˾ÒV¿6ÒVçmYsI\=+¸z’¸l|$rYPWBRW™uuÙ"uÕäCæò–»l°¼¬^ÕO/U* »ú.â®þ>Ä]]É¥Œ;›”N×ëmxõ×-òê¡/òò;½z ½üàW„ÞyeV}ñWØØu¬&ëž…Õˆñ‘,Œü¹î»ý¹Ê¶þ\íuC.ÀŸ«¼fèÎUN6tçj7ºs•;‚ü¹L. w(®úM®ú}/¥;Wý¦;WWOw®*0dµ®ßƒí¹LiÕVµåÑÕºt™`,?éÔÕ‚ó\~Ò©Ë/Ûü¸ÚÊtêjºLðþh6½ºô\òê’A,½ºìç»8b”WW èÕe‚ÕT½ÜººýºZ@¿®¾äþÖΔ_W ÞëG‰±Ö@Ï.=¨<»ÊåDŽ]- _WN˱Ë$åÙUzv™„®]]ñõÓP]ž]&yV_¹v¹d,á]»Ê_®]]D®].?ž »JBç®zùvYúv™äzÖßôí2IùvµdüZ|®Úµ«Š”kW–<»âZ¨Ê³«$û/¬òíjÉê•õÇ®]kl /òÇ®]Á³K‚?rì*Áúuýc·®^]ýlòê2Éyu™ÓÖyuýÆ©K‚òé*Á·¶½=º$(‡®òÞÚ×.mw. èÍÕ‚ræ’€¾\&X(åÊeºrõ%c_–8÷äR‘ïYÛÞ~\ìûÚvyqµ€^\ýbäÅÕE®}ý9Ö>•W žóG»Þmm¹<¸Z0î-ÿεOåÀÕý®.°ßk»å¿Õ‚s[[.÷­\÷Úr¹oµàÙÖ–Ë{«‡­Ü·ºÈ§sùž}ÛR ü·¤ü–W‘— ´*ª?äÀe’óúµ:­Ê…Ëܾ®™|¸ZðüøRáÃeU¼ßÉO^\}É÷cq”— ¾µëåÂeîXǵö½|¸LðÓçY.\V˽6äù¹0Ê…«‹¼ÏŽ• Wù~|hòà2¯©íç²(®ºH.\Väë †—(. ypY™òà*Ú¢×Q'°òಫÆöó àÁeãX\U\ÕÜrà²ûº m.“œÇÏ2׿çòàê[ÝëâXþ[-xµ8–³ÖûÃïî[vIyo±{å½e’öÞ*Iyo2(¾êN¥øŠÃXž(Rñ•-¬Н<¢乖8sT|YL;*¾b¯§æAñ5—ÔRŸAñU=KñÖ¤räJ½—UC½W‡š£Ú+鸯©£¦QëõtD­T{ÅÊàöƒìŒZ¯thqó€LÔz=íÁD­×§êÚËB=Qïu+âL)¾î!áÕ¿T}õ3fˆÃû*"ÞW…b„Ãȼ# "^OY."ÀáõÕù8^Š.$û®»ñ§duÛŠ«ÌŽð›÷×'ã^gõ ãζÈÞ°ë`tÃYKY#"ºáü@å–…à†×öÃs뛡/€Ñ çû×KctCæ¯à†1i³2¸¡ÿFtC¯á £× ‹ÖÉ…’ñ ­1 p8¿AÙë!Àá|0épáÐnŇçS_£žßXtð-mUD9œWQåp¾5 CF9T˜ôŠr8«•{‚Úø`”Ãû,?)D9¼ò½B”ÙŒrh£aï³mùæ0R@ñ¢k_Þ+£Fî"Êáy–ššQç·¯Jäpv®™A­bš![À‡@–‡öY1Âa<½ BÎ2šLâpÙc3ÄaF9ô"sèÕ Ìá,S6sèeæpJFynmk Ä9´;1Ρ=ãvÏ0Îá¯kœ¸ˆšÆ9´;3Ö¡ß Á­ûì0Vªáœ¶\õk½wèíE¸C¿á»yŒvh·fÄC»ˆmœ1ä¡KòÐ:”1#ÂÖ†<´±˜!ýÄ<´Ö%¬-— ä¡Í yh͇~bö‹cÈC{l†æ»Fn‡¹`ÅÎdî"nòû”ÄÎd?ÏÁ,û8cg²Ÿ1ØuŒ+v&{À´ê¹3)Õ™NÄÆ$‹ÐF)]2b2Œíq CäB┌#gÕÙ%«A‘빘öb³ìI:Ù–iD®Ü„¥`Ä߯hÀII¦ pF¶}®¿91‡Q«A‘;Ò>²ž+\ž|Y$w@pg¯Heγú8ŸÞCrüâ¶.N³î¨%öl”ÌÖ݇N„ö¶øØFäNJ€`ä#Ì õÃjß;‹äLÁ8ó æƒ\¼èËEè¾6þh~Ll!ØÃú=îrè ÷È6’ÁD$óÛÞ²õ‘®ø¦$ꜻvØΩ.óþDÔ‡õæ›÷ÜlU6ÿV¶)yѶÙ‚¦äÉì?wœºž …È}èã:bÏ»tÖ“'lylÎ9hòvßG²å°b›N~Ïq½]üý¢Äǽöq™èŠÖ°Ì™y€®èEI2нé\h^ôê`¼ÎMô…1¾1+ÏqÌ!wUsfB +¾A^uå—}³£?Ï;]Á¹¼ê΄@‘S_åq>™èŠooü|£Á§¼ÀŽsdF +NXXËÈŒ@qïeòœm3EÌ4ǵeF 3òB£Ì•'m³ÌPkbJŒ¹rPÁ2%yÔ6§ÜS {Bò0Ñ[ýœT{°Ä•ù€Î8ò… ÚæL¾s®<®'…ä£$ÏÚöÈ ÍZßLt^§öã¹} 0þ¸¾LtÎåo!P<Ávj¬Ý[&ŠœÔ=qï™(·±ÔsŠß:K>b"½q ¿–;OÛòNüZb~¸P lR;ÛbK¤ïç~¶|†­†ìÇm³f€Á;ÇÚš„·Y&ìCòå‚eø½Üyàæw¶ü}S={<û·°ÿÂ9ð”`AÝâ(’ êyC6%'Ôî‹ç‚ OJ°¢v_ÎÏ›Kj´gH’Kj|nœ_žñâv–È7ªwÛñ¤ƒ˜’í»¸T“£³5ü‚Þ¤Ô‹Š‚^„{ý‘Í÷üâ Ô}sʸоý3µó÷§Ù3Ô¹!ÏÞÈΛráKCÍÛ‘h/nôIò¡yšmΉöú=;vÈg8Á² íõ ™’³¾¾¨sG¦½èÝýáêsG¦½scs‘fÏrGš=— Í^è±H‹ÇÒ”iöÎð˜Ä{.ªGÌá¸õ4{ý=ͱ²£¿±‰š¿±¨nÌ%e±ªÖÄ7Ûu®SÎW¬ËgüxžÊÄ4üâDñÏ%«ùEršûõöû*†£I;3Áû:UаÏbVƒúÞ·²2‘úÞŒÃC^Kê{ßÒµ“úâ*—û–«ûâªG­ƒ]ûÛ¹À}ï[I”È}ïÛ™‹‚ûB[¤ô?à¾E’à÷fD«’´à³Z~!Qx€_Ôó ÙüÞ±ñWÛŽÊFì ‰ ûæõe´ì[j-ˆkŽÓ±o©7±Ïê%ö­’´¸í;ûIbßû–½±ÏîEì ¦£¤>ÿ™Ð÷Ž2Å ô­’4»•€‰Ô·HûIbŸß*ÁÏä÷ŽJ#Fòó›ƒü–2aÞÞ/Ÿäç·ù-’$¿¥X¸{k’ü–{ÃÆÝëIò[%iÇ7”‹‹à‚“ì;÷.ØçMöù}~`ŸW’Ô·Iêó'ôù5É|Ë`çîIè[ÊÀÖÝïô?~kãÀ|! ¹¡Ïæók`ìnÕù¼HŸ øÁ·v>poiÉ{-’ö¼Š„=ïÀžë¹Æî]+HÏ0v·vôb†¢Ot‚ÞR"AÏosw«59Ï0w÷J’ó¼HbÞ›ÑÞY$1Ï%À<¯˜gmåY½yþ9ò–:`óî’„¼E«woKBÞRvïvëd¼¥´xV$o)Ëw“âùxK‰D<«„gÝÀ[®IÀók’ï–"Éw‹†ïÞ˜Kg-hä»¥ÌøQ/LßM¾³Æï¼êRý¢ãú1>€w^Íùý˜ÛAwÖ3€»¥^8k.’o½Ü5]ÍpLå}à°éEà²i°ßpgՀ햋àµé’óÇoømZ%°÷"pÞtÉóóóÚ-’±ý,3ÆÉhçe€vÖÝ"XkØ-˜¿Û%påô"°~·"ðå4¬ßM_N¯ä}t.°n‘À¾ªIª³¤:/‡NÀ¡ÓCo"—¸®µ_‰t^&€Ggäk¸)y¯Mkã[»•KÁÙý­ß)y΋LœóÛ$Îùßç¢;4µÚJçâž0‘çb{ij ð\LGTl0’EŽTl t0—Ó×sÖ0À\»Æ‰æ¼saqªm5pn¹*yÎ+Nœ‹{K¹–4OsP·–0çOšó.œóŽΙ=qn‘$Î-WÁDÞú8ç­ƒ…¼=pÎÇpn©&yÎ^ßÚ¸~º¾Ÿ.÷§=¼?»oÁr~ŸÁø§WÓŒãí漚óñÛå–+`ßÝ”óžÊ-ÁÔGP/OPûH¡žu┳æå¼§‚å–ßðíGÊE·hnËyÆÛˆËyØÅ[û?FD=koòÑ.^[d9o>ìâK(gÝD”³–åìÆ„9{fÒÜ"wh Kâ\?in¹î¡Þø‡z™ä9¯fë% t^¢=\tþD:¿ˆÎÚ¢[Š`ìxˆZku‹¢Vñ³ö%¨niDíø‡zø‡Ú}vÖ;›:v1\è=F°ó·`·T ÿÐn ¸n¹¢.±ø"ëð yÝé$ÊiœC¨ëÆ9‹Û(œë­À9¾ñFGi€sáD¸ÍEÕz!Ú¨ÛaZ(Y’\D[UÈ6 \ÄAU°5¢Ü&«9’\‡J%ÈY|U€Ü|F.ÈÙ%ä¸-+Ž ï‘ݱ†Ç)va\ÅŽ%ÅutYQܼ’Îã,p"1΢ð㬛€qÑfr"ÅuóIqqgí?@q‹„Á}«1¢¸zAÜì.:ñâ*än2œ…‚Å續4Û·€·´—p’¿pÕ·"8¯gÍÁEc¸ÞàªVâ[„Ä7 mK~ëà‹Â·îâ›= ñ­‡ ñÍbÅ ßúy@oX˜ôfÃVôfÛô¶íŠŒ!z³G¾ÙÇ-|ózO„­˜™ä·èKmÈo^óƒp££´uà·î,â[L/d3ù= ù¾Ã¢1“ÝzÊ º¹äÖUܼOn¨“à¶Ipó7Dp³zÜìéÀm=k$·ù¸y[ÂŒ~+¸yCn1‡ý7ëg›Ó‹~ûí€Ü–š¯¥õ„·~7üöGxë¿d7 ~Iv[n“ìf½Bv뎻yó o6 oݺ`·®,t³¿3¾o·ä ÑÆ•äf_Èm¹ èÖ#äfwb„ßnË·­á• nÞ+AnÞ’›5äM!ýÜì½Ü|„Ü|´Üzb!¸uû†÷µÆ€Û¬âûZ·$·yknöÆnÖ-·îIp›÷ ¸Í‡-À;p['Õ¸yÄë±Ö¾LYÑmy¾eex+g…Ú†dhXÔf½lóÛÛºb› Ü·çZR›-ã\žØæÓ>±Íšnó‹€mýÖImöÆ@mÖ'„6k,˜ÍÞ)˜Í&02›5%™­¿m"[WJd3òÿY—Ùj'b³ZÞ×Ú`³Ç#°Ù5ÌaQ]B`ëk’ØFƲqå[mÄký´äµnˆp­_'qÍ>Rñš—°uOØ–ÆØªWÈk6þؼ-à5o.²Ö8¯U§׬S€k¶Š×úó¯YûÁköm‹×êÅ×¼c’׬[ÈkÖ:dì±B^ë­®p­æ.ÒZ/t¢5{DÐZGc¬õ“Õü'Br×]‰jýrHj~“gãl§vÔìyAjUäw²ñÎ"DÁüÇ=Ãz˜ÀKàØIu•žr‘¾?á(;%?ÒQ®löËQ®l[ËQî|E+r” %–¡§Ü-Ï"yÊ7]¡ä)çÁSî¼ej!O¹ó¿LÕfyt”37>zÊ…—‰Lá)wF²$ú¢ÁS.bíÈ´‘vÀÏ+AzÊÅ^ŽŽ‡t•ó«à+w†e(k†¯\”ÙÜh2ËH•¾rg8E.¾rg¸ÿñøÊE™±øÊ-XõS]CG¹sv¡ÜëÀh·Iv뽉ÑnE§¢­"êˆÑZAZz¶ŠS!E›¬µ¢í‚ÒæÞ¬ÈîÓi¿ bšÕCEÛ\*7Q8-lÒÅK µ¹ñ•o\èÙì Š¶ÎÀS¤Ö¬*T«x…j•ÛGš6ãÊFµ¼±­+'QÍöÅ@5ç ¡Zm¦ƒÔ, IÍ–#59ÁÓZȲœføDL«ðúÄ´ELëÀ÷ä4K9@P‹`x2]iR£‡LšEÆ/T«BµjíÉ\,½Q&«Í¦¨·Åjµ#«u~±Úl›^>X-ÓHËJXs h­“$×ü7p- ¾„gà5¯À»Eam«¯ÀÖÙ‰ Øæ®š¹nliúÆ«l•O˜ÀV9x l–_WÄV‡‹Ø:+¯­“å Ù¬b›_”Èæ2[ç&³ùS‚Ù:;1¡ÍžÔf9v…msò‚Ú¼Zäe©\¾‚6eÇ%²Yša2[§8³uþbAÛ¬DÊÐV)‚Álö3‘-—3*¯@lÿ—ÈÖ-#°u>`[eò%¯u>\òZ¥Ï.^{+ày-®)¶â5|¿öõN÷tµÉk~É»¯Í'®Y ÐZL`®\³¤µ®´æí ­Y;æn?¹ëI\ó.!¯Y—Ø–J½½ €Í/zƯsi€-($FŠ¥í)Ï6:ñ˜k[®K®E[üɹm~ù«m•À»í¬Hjòn«(±åÝfpåÝVeèÝV @y·í2!”s[…-ç6—À¹Í$éܶUÀú¶µ®móÛ)}·T@oz¶™€i[Z¿6 ùMß6s ¤o[L²w„o›KàÛæy4¾mÖ~¸¶•@žm™Ó^6’ižïx¶¹„žm] Û\0Øþºæúñžm.gÛ"lIàÙöT¤_y¶Å¦Cš>x¶u?ȵÍÊе­{S®m.kÛ"k-pms \Û¬Åtmëpîrm«$WåÚÖ#B®m.kÛ"Aˆú¯ÐíSz‰Òbmò/•*|Ûüç»!¹¶Ùеͺ¾m^¾m.s›KàÝæõÀ»Í%ðns ¼Û¼žïøñûû1HèÞfµÐ½Í%ðoó«ààæeààæx¸Ù §‹›—›õ)Ü\ò^ëox¹-’±Î4rs+_a¹¹YcèçfÑÑÍ%LëRc€Žn6jÒÑÍÝ\R‰]ÊðñQ&qâÌ.òt{ê(‡žnOåÐÓ-Œñe ‰LW©àéèfEàèötD‘pt{ú‰ŽnO…K–£›Õ?·GA—åæf%à塯…rÌîR4èåæE˜Ýe/Ëlº¹Ýeñ/7·9%ÐFnnw —ÛÝQAàävW0py¹ÝG›NÂÍm~ƒRÀÁËínvº¹ÍI-N77/77¿ÜÜî¶|§›ÛÝ&ßéæ6g½M° 7·«ÏÖèævÖ•ÁÏÍËÀÏí*‹ù¹]å@!?·«"ËÑíª˜árt‹mðé:¶ éévµ_@zºù5ðts <Ýü¸º]'V®nWź•«ÛUÑyåêæøº-’\M/ņ«›ý„§› àévõ‘'=Ý.E1–£ÛÕ¶ætts ÝI®¤.£›Ièèæxº]{ÍTéêvõÙ*]Ý\W7¿¾n‹äeûJg7—ÀÛÍ%pwó{ÁÝÍ%pws ÜÝZ·å÷û³Þ\·E’‹©Kàóæ8½¹No‹ä[ŸAno.Û›KÆZàøæ8¾™„žo.çÛ"ù~´¾o.ÁÆØ%ð~[$ßg ÿ›KžµÅt€[$ãç3ÀÎ%ð3 àÉøñ ô‚s ¼à\rþ(/8—À îª`7ô‚ó"pƒ[$ãÇ#Ю$ÿD¢ ²œä‰§9µ!¨,'Í=- '[#?¸G!ÊäW©|Ê .6*78Å•„åd&»uÚëô>å7^­B²œŒ{±&œà:/‹œàâ;v'¸ÊLSNp•g¦Œ'+ÕL©æ"¶ô %¼àBõ¹Ä2é$8¥š«Ü=¥šs Ts[(§ùR¢B5FæLÕ\d·]B5·E¼¶ª¹lN})¡I"4s[ÄØdàH(ç¢b™1"Še\ÄÓ\F±ô«ÅrËU.׳@˸ßáÔçmAK/‚ –ÛÜ#\T"ŠeθòyÛðCǹ dqëUŒÊ¹˜âgˆdiW1’å"¸÷³D²ŒòDC$KëF²ôZÉ2ê‘‘,½ "YFf$µo0ÃS_…H–~"YZï0’¥]•‘,­ÅŒdi}LG¸È†}9÷yÿ1’¥Ý›‘,­wÉ2®RÈɇùž^Ec(KoBYúUeéOõ­=ÁP–Ö†²Œá¦¨”ˆeiㄱ,{¸1”eT³¹+œ bF²´þc$K{&F² £¾2’¥ŠŒdiÕ"e© diEÇÒê`K— Ž¥µ…q,í³cË-mÜ!AËø¾…“×¾LŒciÍc K¯,m–` K¿"Yz͈dé÷F$K+ÃH–QÆut^1YÚ›Ë@–Ö déל̲öJÆ@–6hÈÒn8–ÖŒciãŠq,ýæãXçB†±ô"?Ã×õty‰BKî‡J,^qÞ^†±ôZÆÒz†a,ý*„±ô2ciŸÃXz{ÆÒÛƒ0–öTÆ2ê½ÿ¼ÃXÚ½ÆÒË Œ¥}Þ ciÏÉ0–öT ciŸ!ÃXöÛdK¯øÙ5L$øÑº—kjM> bi(ƒX.’¡' „A,­‡ÅÒž‰Q,ÉÐ8gfK¯åªUU%îMã¼,/kYåS1Š¥×óžšÎ¥µ¬Jˆ(–~/¦J¬}•¢XÚ“3Š¥uzF±´Ö0ŠeÜûs\j¹jY½]ƒç-fK{*†±´gø”8Ñ$irYé+Ž¥×üëÂ8–Ý>űìåPf—Ý7ŠcÙ=¡8–}'²t "YvïÈîrÖÌS E²Ü²«ÿµp©,{MG$K$^vG(’ewº"YöÈÒž›,û-(¥=YZcÈÒz”,½æûY77déõ¾»¾VÝûzö9cYz-0¾T"Ë ei1”¥5†¡,½ BYÚCe(Këa†²´æ1”¥=CYv3’¥WûŒuœËY®¶pžqè ÿá%uÅÍüæqˆ’%ãÐ^g‡Xæ/fúí$ñ?ë-þo“Xº ëøò”®«’Ī¢Èª*‰Wyq½¢üíÕ„À+Áo«âÞ ç³®£Äª¡È**‰Wµ¾+{{^ÕúbüUý‡çAŠêDK„¹‹"Ù3~“h¦“‘ì“&!<ûó›Ô2?j¸ÿ^*¥9‘~oxÃÞËu0òQ®™“P—å;BUžïˆ5uV´äMB=ží-ÙŽX“•bUkæ$ÖeÙŽX—g;R]]Ju-™“X—e;b]žíHuu)ÕµdNb]–íˆuyN$ÕÕ¥T×_ɉt†Qâû_9'ÒŸ˜æw6ýͤþ·¿31/¥þpjú‹9‘®ÜâYJ¤"éÑŸMkôEN¤>ýüHkãtnaÿÓ¤5ú÷ßKkôï5­Ñ™Aˆæk}SÙfÓæìâÑ”ÎK¶§ÒîäV8Ú–…5éˆÈIôh‰Ò·ÙQŸ ï+,Òù ì}‚ݱ§úx¶—‡aäÞ'2Yã öÚ¤fÿtRzm;“c(ùµáh/R=ébJ#b“° ÷Ψ‡5_9o^@ÃkÃÉÞÆâä‰Â;kÞùÉ…È)(%¯çz‘kŠ8üÇ3̪‡)A®©8‡‚à@ª©H|ƒ®ˆd/úiWf@ñtTSÂTSJGuÍùµ@ïp…'Òíɧ®óEª©‰V'˼ȊJJó.ÞØLÉ—ç WÃ…à©^$ƒEÄ” ÝTh…XÇz÷ìz•9oj¾)Ip°wÏ1)h0f‘뱞×{#ßTœ°–ù¦f-üد'®9áÜ,ó"ßÔ®´×5˜oŠi'®(馔ßgJò>þþçŠw–ßÂ¥Þ8Ù‹ìMÀêÙ¾ ¯›Ãúƹ^¤ûæ­ï3³bDª«ƒ×à\x'%H7ß+ëÁ¹^´Ø:'¤›šÃZ5ã\¯²~MÁ‡Oµzëøœç­Lế¥å™d|Cвë¹ò(!N„Ù Îôâ’ý<;ùM?·4ï¨ç̓›°êÝy.‘‚oǨwòàL¯‰]ïöà3Uú±ëÝù)+ýØõ;ÞÀÇ<4S’{á°ürß3"Í»÷½ò(!Æ ¿°÷Þ=ý؆D7’˜ñ%…5Õ‡{³’÷ÄwpK€½øÚIr5µçE^šNO7§®O A?p wÇÙ¤$ãcÐâ{~(¹˜ÚÚ3N~K8c¹ô⑸°ŒëÅøhÉLSoÍÜãA¦©!=Ä–õák8¤?¸Âë&ó^ša’´Úg:à÷b—pHOŽs÷‡#=ûT¾=»\Él®zÑ5Ÿ$^s]ÎóBpóFpHõ[#3uèwsE­qô=üåP3g¬¨•.ñúà‘Zÿ®opAUéx1¬0¹ßS7`‹/r7ÖaJ°¢Öî ©!àÅ{œ#ÔM™“fC/Ì‹o¤ÔOÕ‹ó¼˜Bw–éä,‚Ô4¡ŽB¾·9êr=½bb” ìi.=Ó­wHðvç-¸ Ê o¾ù]s ûfgîÆ]y|fß.ù(çä†5Nûyoæn¬q4%HÞXÛ¥ù¿[!¦Ÿù¡cA­ì‚smèâ—'S‚µßï±ÝšHØéôÞWlLÐâãØô­ò^Ç‘+¡‚ Þ±o¾|c6§<¬¨óÕí¼†kQ»fpì'?˜Á±æÝ¹ÎØûùã#À’z"ÖÌ ŽÛÉÉï> ÷¾bBÐ{÷|sŸÈàX×D¦¢lŸr®Ý'28v>Ì;’&EÇ.k§äÃÆ†0¦P¢Ìéõ™ËÍts÷ù ‡j UIÁqÎC|¨;äèäep<ùÍω'äYÄs›p¾MÁÅŽñø9nöÌߎ?™Ò¨¨ïIóI?,Óä+è‹TXÔ;úù3'ô½gqó™…(¡/ÔnŽa¿‡Üi }c+«R_èǸúÆõh©óY¨I2Ÿ#óµ÷5‘/ kN™,eæ'À/>kn‰üÂ`ƒ»s’_Ä%à¢Iò;ß[­!ùE>N²ÉïR ‹ü"rÂNªùÕah‘_äMæªNò b&ù‰rùà7·¸zá¿ü¨y#€ß•š¤û®ØÒÆÀ}a~ÁõšÜׇä¾€|Á"¸ï ‹_€}1ý„E`_P¾$wfcý¸Ð ûzÍ,ì«í$©ïŠ`è+õ= (RÔQ=HHľPV’€}†Ä¾9öŠú¶ƒSjQ_D¿>(¾îõÕºQÔ×»|Qß»é+,êÓúSÔW[Ž¢¾°áUľëäû e„}±AX±/¢tR’Ø.ü‰%ªy]Ô7¿Wn›E}·BõÅÁ„¾KGq}Á ä7B_ŸTˆú†²…õÍNãL'꛳Ÿ Ô7qj_¨ïÙ´<õ­è‹Ø×/ìŠB+ì{v¥!/ò ¨á½I~vÈï ³(I>œšAuZä_'ëùÅ5Yè÷ľ@’ü ŸHcIdú=óÑïÓÞAèw'müâÙøÙ‰üfsÉ$¿'f~49Éï à5 ¿ÇXä×ðã%ú=‡Ò"‹ýžÙJ Ùï ¢`Í`¿çЙ Ñ/ú†#Ÿì÷OØï¹•VZì÷ĉDì½w‹ô6(v#²ßs¾:¨ û=›R:ŠýžìÖýžØyñ" ß‡Q¢_0¯"ú %úÙ 'úY=@¿~OD¿¸f“äÃ@zKö³ö‘ýâóàÄAö‹¯DP ö{¢ Ä8°_t:)èçýb<Ž…ýžx=¼ÕÇÁ÷œÀ~јS¤·ã6m\É~ý¾Å~Ý5‚¿¸êàU€¿xãÜçþâ1_–üÅðÛÈmÏå£DðŠÃ Áß Ì2€¿gî€IO·¥€ðg@ø{N¥9ü=§ 1Wýõ þú üEcküÅn¡Þ†~xþÒLwü=1(üÅU'[ ø{®Ÿ¦à/fE>áï¹u¸/ø‹«Bà/ÊÉê Ï„¿h –-Áßsïb{Â_\5ˆ€?¯ð÷Ì·ú²fÀ_ô‚¿èÁWþâîØ\ þž4öú×f¿X .±Þ†¸“ìg]Lö{Zh ýžkðHƒä— !è$ Ð/l%OBÐ/îć$úEs9üˆ~Ñj Ðïy”1诲Pëjس¡Ád¿Xò8¤œ÷f¿?› Iø+Ô9ÿîÊù"þkgPò_,ô{ƒÖ/&fyÆ,ÇXÔúUôþRúÍ";%ˆ¶qênç¿=(E:>hýbFà„G­_X˜ ï õ 0n{¨õ ÌábE­ß! ¸NOP-­ßý#É òøt 0†*×h`'hà1wP<–Úo/#šÞ’87)Z/€9†.J ö{&æRJíwiÑ–Úo®Üì•Úo/å!Õ~§Âxü±æïÊÕ;TüŠ-Š¿€„[´‡½ç}×Cÿ®°µ%P¥â/Þ~ÿ®4JNõ~ñr½ßõpZ(µ_Ÿ³þâˆï”’o—6DJ>ÀŸ¡’Ô~}È›ðZß]¬‡SÊC)·Kí—¦¥) ÖoŽHî E­<–Öª¡_H–ίUb¿:ücŸ½}èü‚ãŒÔùÅQ„4|€¿˜u¥?Õ– ?Ócý‘MHñª‰RúE’ ””~¥JþÅñoRúÝ…rÀ¿úL…1²„ð¯ÞJ)ý†žøg'ï¿»Jé·é;þ šhýµ"Hô×úEÑ_k%Ao™-ÿZ‹"ü{e*]ø7;]W ÿ6=¸ø/ Iyoòß i+ýÊ,AüïEþ‹%‘O%þkzJþ‹¥X<­ßWV â¿Ö&Šÿ&fq¢ÿµâRü4OrÿRL“ÿ {¤ù{ê”ü·Ë»¿ø/\6X¢ùï[U±Ùd½ä¿ù yd!Õ_LìÜv>­çƒæoÔ1’ø/Ô¼JüW+þ«-85¯¼#ŠÿŽ¡Î’æï;«Œø¯ËP÷ÇϧàoSÿJñš •þæ×È©Pš¿øÎ©}#ýÅz²Ò_h%ˆ` ¿¡IKô×$ú»Êl¦èï¤ýUçÿî9Ýðì¦ð¯›øõðL•ø›öø7n“.ø+%û—{®øwÖÙ]áß¡{ ÿj \øW€-ú»îª˜ô7'E~˜¢¿Ú7þÕ°þZ‡‹þê$ôw}Òúˆþî)úë¯èoEW¤¿[ÙPšþi‚DaBBB$ýÕH*ú O$§¿]±IŠþ)D¡O"‹’þnZ‡ü…áÌJ¡Ä%'‘þt,Sð7_»hþú¼§à/¦éþê¤à¯‰Vð×ûzÁßy;Ä~±ÿ`µb?}bÅ~v+²ß¡ XÅ~ÏUJ3²_,@$)±Ÿô€É;»ÞµÀ/üˆg¿“GÍÅ}Mªâ¾ú”›û¤è(îkv÷Ù­È}—ÔÅ}sj{Vð«×î‹3lR¹o~¥9ŠÜg•üÛù=G)ëH~s¨?‹ÒϪȯF´È/b2C@𻕆¥Ào´0Á¯)”Ü÷–PÜ×£U:¿þ/ÿ8QRiú>å½ê™ÞޤwWš'‘ž4è½ë¬½Ž8\¤w**N¡ÞwŒý.ûÎrsêmO©„z³g¹¥%ê¥3’Ì9ádö–¶Š¨ŽßÜ/õ¶ppâUÁzáŒ-3Q ç}nľÅÄs‹3{ÁK<Å'ìs&à.HÚ¾ÈÅ{öŽ ÖCmßW ;a/0€+a/\‚d4 Ø i]%m×qÂ^ìúÏUÛ7>i{gh"xµ}co´ƒ¶/˜ŒšFiûj›AÚ 'i6°w|¥b•²¯)—°wF_›•gø¤ì;ïfž×1JGeßS)e_P‘Ge_Ì‹™çûM²•}Aj¼ ¼lÌí”}¿¥í{µñï•U@iû®z1¾°š¼dÔI³ê󵕾ÏTud¾2Rp…ŸÊùº¿ ð $ Rá/“µùê'Ô}s·IkW©û&(¨q¾~H_[IÝ÷*µ€/LxÀMà‹æ‘¹È{­ãHÞ3æ&ï…-„è¼wݵOï]£®’º¯¬3ËÈóÕˆ%ï]£Œ JÝW¤+à+Ó‘¶ò<5|2›íÅFFÚkó-Ñ^l©Y)h/L@NI@{mï\&ž[q›L<›4I{­Oí=ÊP´g¦¤=™^&êm55 õâs¡šŒ¨7«xVÔ»¶_+镳ì;ÛðZ ×–âRôõC ôbŽú¥’±¼z³¿8ÈdâÚjYtôÊX«l<¦zõ!Ôó=5/ ôâÑxA¯5ä¼¶¡–…gð‰éù"Aq8o“]Qq^«¯eâsçÊyuH]¨7ëQóˆzÝÙxv=B½ØªÒˆz1@`@½xw—y†!ÑFž}n#Ôk-Q/F¤êêÅCÒ £‡UÑך])úŠÈ¥çûÊÌD&žsÐó£èí5OBÏæT¬ôÂX%hâ9ïÇÆô´-.ÏÆúRó5Ñijz{9©ÈÄÓ ×DzñìWGÒ{JkÖz>êCDz‡"—焃Òó)Èq“žž¡õ|;T¤—Ñ-x•ô|…/ =Ó:’ô-Êeäù]Å‹Òóíe**Ô«{ê=<·iÔ{KBÖ‹ÃFâY/,“¥Ö£¢ï’AŸXo“{Y¯¹B¬×úM±^~Ëî¬WbÃ^[ªöšƒKÑ']yÁ^i8ÅzsqÊ‘õŽ»td½VL÷ê;l=Ÿôj¢=V´–oo£ÏWVª•´w¿eÐÙZ¾öZ&Øk½®`/>‰öbÙ4 OSBŠö樾 Ïç>Ûž´×”+Ú“kÓ^™J´žïæbR´×ÚôÒóQEQ´Ys¤½˜ÆdÑI¬ä°2oZâ©pïP®‚ßUóýÌ·Tê¼# /]÷ý’N.|§bk“ñ"îãw&äu‚2^„SãdHÆé¸0^콯Ňoµ”ˆñâ…‰³Ÿ«CÉñÌŒg¶{d¼N${Mªó6Y7Ó‰¯,¿ÅxsÃÖøôL,…^|>”ÐïU°µrã‹ iŒ«”$Tèí‡ÎTåÇWgcb¼ØÆ-ú¼>â>¯. ñÚ†„wæ׫aN¦"à™ëÏl\äÇ÷*È…¯W6ž™«ð"l@x½ºðžG‘2x1³pÓMÀ{"–ï[Ïexïì±(ôz6à=ß&Æ'àõ#ïâXFªÃ÷ÂW)×?ð]l¹Å#ßÅᎠ¾{âõ/n|}$¾‹ÓC*>,Hý˜ä»w+§ò]˜/Èß|÷Œ²ª$ߎXMàÝù¶ðt×Ç\¢»w.»ÒðjÂß=ãúaÎÙ¶ â»ØK »Àwñþe™ ¾{·¶Íß=9šR¾‹W)³ËsØIžðÎÚB¼{Þú²‰wcJù¼:ð¼tׯ!¢»>6Ýõ›è®;˜pËÜnÚ¼>ßõŽE|g/Ÿ|'ÛâÂ÷Äf–¾ë…[|«‘|gÏM¾‹‡ÒÝÇ«ìÅ…/žé6¾X,ÅsÛÃG^,Ý¢ªƒ«QÙ5ñb}¢¥¡”ys¦à.›Œõ¼«2ï-ê–1§Lt¨Ë‹CŽE—÷äþ"TåŨåiÊŸüªÊ‹ÝûâÅ÷Ì‘"_;êòLŸFSÎXødÜ™ˆgƒœŒ3ûŒ÷nr¾¡-çWNÆ{·Ÿ^|Ï\9žÅï9sñã³IŽŒ÷ÆÖ’öž´åüÊžCê¼ÐΙÀx1',~|q4¼Þ3Êm! /¾[¹þQ™g÷áE·²êòzª$à½Û¢È‹ÉEQx×ý-EÞ(÷\)òú-I‘7äYO¼‹É•‡2ÐãõZ%¼Ë…¨ñz‚Ý}o©©Æ›÷‘Žxgý"=ÞûÈŽWx7¯’Ñ&õxRÝ:“¯0ènlE\¤»Þp‹îžñS×6h¢»ª·è®U9¢»GfM¥Çk;:Ñ]ëÅ@w­‘#ÜÝw!Õxmã'¸ CóÅ…/”kr«#ÜQq"²kCÆ";íM‹ìb§·’][–¯Õƒ×ª—,ÎV¿I‹·yÊ„³M&œeþ(²kH+5žˆA`×7/ ζ~$Ùõ#ˆìþ’ìÌòRмRh íLßF¶{¾² %ÛÕ>©5yån&¶‹Q°¸ïÅÂ3xá.NêW ÎÙG2Ø$Üõp¤*OÊ›‚»ç,V’*OsÁhJ•WÏ ¸ë#¸ çöÕˆÓ H¥ÊkMq¶"‘t÷¹ ~ÜÉ-p÷Ñ=·Ø®–b»E^çe* Û2à¶+í†RŠ‹è*„Üó: üó2 ´xé —)½±áóöÊ!š‹ ˜×pš{C%å¶™.H–{#¬¢8 v‚&.Ñ]f÷˜’ñ:Ë-W]çú vFY²å–"‰rKµ‰ro̽¯;çE·0—Qn)“+DÆþ”rnC¦¬Ê‹E” ‰üãc'lKoåXz›(÷fŠJk"Q–I˜aÇ®º‘(Ë$̰ã$Êz•Vƒ0·H2e™ä;~–ù)«%AsËïýâ3”$in•d’—$Í…„‰@Hs‹$iNÉÈ ùؾ’<ϯg•D†ë àÜ*ɤö^,ÐÊœL±Óe€sözAso¦ãt ÍEr"_VÐÜ*AƬú,ç–ß2f™äEƬÊÁFž‹\iC$‰,;‘¥s¸ÂÎËèV 2fõ× [$2f™©vÞ«¼mƒè–ßÈ´ã’³ú+Ò­’÷Ç× ¤[$Ét!¹¤bL¦[%™çÃúL·Ho§óÏ%Ô­¿‘³îTfBÝ"A¾Î}G¨[$È·ã’I³L‚|;‘…uºE2ÞŸe>$ͪ<{IuëïïÇ8Õuz)B ’é,—™®sIé¼³€tËž/¡ÊDlMÿLg ÿuK™„º¥ ’íX@—Ô-’„ºåª„ºEr¦²]êɽ[²+2 é–;'ÒYC"ÝR&‘n)ƒt;³H’]d…t;^&™n)ƒ„;v¯€:¿ n•äÂê’¤º7œÕ‡SÝ"I°[%/7-Òþ%×-3eK>f t V“ìKª8‚%g#Ù-eN¥®«2Ì@)3:‚÷ç÷3%Án‘ ¥ € "ÿd_A®ë¦ëÁÇ"òOvc uKµÌ@ÙH³cäŸ4Ás­•"ù¤Ý9vLÀä“v RìDRÖ  [%ƒe˜šL·”aúÉ®ygþI—ŒõH¦[~#e?"näbj$Ø1“OZ­ßƶ=Îs&ÎÙ·Hœ³jAs‹`¹-XÎL;ÙíÊ-wAÚI— í¤K˜v²+fÖI¼ëÀ8*é¤tiÈ9iµÆ­¿ßm;™uÒ$‰q=Gâ\gó !n‘7Eî Ä-’Ê9Y’Ê9Y’#PŠØÀ-ÄunCEEU‰&S™fFΡ%bñ©³³2ÍÜ’–™þHEÂ43}¯C^L\çá÷ÍýDùíAm·ò*µÝ&7ÅòÂ{+àaÅÞ,Û=ÅÞ ¤rÔK:…·dìÍ«¼®{ó¬à[PÛ]o™K2øfœ,¦™GBÑ7Û«Mj»8ª‘’j»Ø†ÊXj»ölRøÍ6Í’Ú.F©cøÍŠâIµ9j¤Ú.œîÅ2óŸªàè†w—¢Anxmâ#Åbm•^ÛÔÈ ¯Â!•žÅÖdüÍã,@*îÚ•_ñ7Ï2…^èÁ–0,fê$Å]û+(gÙ|Qo¾&ïb˜iq¥·‹úG¼¨†ÚT)îB›Êz^F”†Š»:Ê‘âÎïDÅ]y«Wü͹îÉ‰ŽŠ»V*þf»Qqתú À9:,&w²î¯ø›ïõ«AÏÜÃËoŽIAÜËÓFk–+Þ|£TaIsá"ÙhîL•+Í]9v—殬Z¤¹ë3àÒÜuoQu[ùÓâoš%–twuTWº»Õ/÷ñ¬”Š»yÔÓQq×*C*îúHq× )îÚcIŠ»Ô•Qsgz¹cñ(ÍÝQñ^¤¹{+>‘4w0 4w± ཥ¹+ƒTiîZù$Í]¨—æîk»PiîJéFÕ© º‹^¤nŒª»¯ì,©¹ëÇ–æî«€9ÒÜ™vš»HÚC¤ânÎA|uRÜ•Ez»²râÎtSRÜ=w9BsŒF‡+iî^è“æ.´iÒÓQs×MÍÝÆ\´ª¤æî-Ÿ_i¤(ÍÝ[V륹k}Ú½j'¥¹3­5w¦Y¤æîÜ~£¹Ók‘â.|„È}TܵÑwaÌ#Šb–Qn¿ÒÜ‘ˆª»Ð}I’ª»³æÓRݽ—ª»³œê¥»«SìÒÝíeœ/õ]¸USðB7Zs¥½ë±Fí]hSRÚ;ù”ún~ˆYgÚ[¡ú.6L«^u0µwñH÷ê„÷)êdiïÎrQ¥öî WŒE{÷F¸"µw¦„úî=žrøƒú.Zl˜·Çýµà •«£@}‰Œi~Fõ]w¹Ôw1Ìê;¯ê»È/ý8êÍö}¥„ú.³`±æPßÅ'27¼QŽy¹¤Æ›SQèïb/…#ôwq§wñË \Š„^´X1M Â‹¤Ó‹^dö¢Ý5x‘jûZ4x‘ðXaY®|¤§¬7¡Á‹‘OKVjð"É·¬,¡Á‹ïG19¡Á‹}<í ©Á‹$«‡,17tñ]ÚC¨ðb¸)4 Txôù£ ¯‡’TxAR Ô*¼x&ê©Â‹Öœ‹ /rN¯8½¨ð¼ TxïûU€¨ð¼ TxÖ;TáÅ{XUxÈŽö¯­Á{/…{†/ ìÒèå²%äV ^¼*YHBƒc[°ÄC”@ƒ³†a -Õ'cÌC],nƒ/Ò—+üçûã‹–/¾*…jù<ö·¸ãYk¨Ã³¯•:¼È:ÿ ?Ïÿù¿ý¿Z* zendstream endobj 6 0 obj 210461 endobj 4 0 obj <> /Contents 5 0 R >> endobj 3 0 obj << /Type /Pages /Kids [ 4 0 R ] /Count 1 >> endobj 1 0 obj <> endobj 7 0 obj <>endobj 9 0 obj <> endobj 10 0 obj <> endobj 8 0 obj <> endobj 11 0 obj <>stream 2020-03-05T16:33:46-06:00 2020-03-05T16:33:46-06:00 GL2PS 1.4.0, (C) 1999-2017 C. Geuzaine gl2ps_renderer figureOctave endstream endobj 2 0 obj <>endobj xref 0 12 0000000000 65535 f 0000210778 00000 n 0000212528 00000 n 0000210719 00000 n 0000210568 00000 n 0000000015 00000 n 0000210546 00000 n 0000210843 00000 n 0000210943 00000 n 0000210884 00000 n 0000210913 00000 n 0000211007 00000 n trailer << /Size 12 /Root 1 0 R /Info 2 0 R /ID [<4C2D3269FDA12FEA86CB5EE73719E077><4C2D3269FDA12FEA86CB5EE73719E077>] >> startxref 212748 %%EOF blis-0.9.0/docs/graphs/sup/dgemm_ccc_has_nt1.png000066400000000000000000007570431422157504600215460ustar00rootroot00000000000000‰PNG  IHDRTjûF¦Â &iCCPiccH‰••gP“YÇïó<é…@B‡PC‘*%€”Z(Ò«¨@èPElˆ¸+Šˆ4EE\•"kE ‹‚tƒ,ʺqQAYpß÷?¼ÿ™{ÏoþsæÞsÏùp ˆƒeÁË{bRºÀÛÉŽÌß(ŒŸ–ÂñôtßÕ»­Ä{ºßÏù®‘iü常¼rù)‚t ìeÖÌJOYá£ËLÿÂgWX°\à2ßXáèyìKο,ú’ãëÍ]~ )úÿ†ÿsïŠT8‚ôبÈl¦OrTzV˜ ’™¶Ò —Ëô$GÅ&D~Sðÿ•ü¥Gf§¯DnrÊ&AltL:ó5204_gñÆëK!FÿÏgE_½äzØs û¾zá•tî@úÑWOm¹¯”|:îð3™ÿz¨• €è@(U  t0–À8à|AØø $ȹ`(E`8ª@-hM œà<¸®ƒÛà.L‚—@Þ‚°¢A2¤é@F²† 7È ‚B¡h( Ê€r¡PT UAuPô tºÝ„¡‡Ð84ý }„˜ÓaXÖ‡Ù0v…}áõp4œ çÀùð^¸®‡OÂðø6< á—ð"Â@”]„p$‰BÈV¤)Gê‘V¤éCî!Bdù€Â h(&Je‰rFù¡ø¨TÔVT1ª uÕêEÝC£D¨Ïh2Z­ƒ¶@óÐèhtº]ŽnD·£¯¡‡Ñ“èw †aaÌ0Θ Lf3¦sÓ†¹ŒÄL`æ°X¬ Vk…õÀ†aÓ±ØJìIì%ìvûGÄ)áŒpޏ`\.WŽkÆ]Ä á¦p xq¼:ÞïÀo—àðÝø;øIüA‚À"X| q„„ B+áaŒð†H$ª͉^ÄXâvbññqœøD%i“¸¤Ri/é8é2é!é ™LÖ Û’ƒÉéä½ä&òUòSò{1š˜žO,Bl›XµX‡ØØ+ ž¢NáP6Pr(å”3”;”Yq¼¸†8WJ)Hq¤"¥öHµJ IÍKËIÛJGJJ·IK”aÊ8ÈÄËì—é”y"‹’Õ–õ’Í’="{MvVŽ.g)Ç—+”;-÷H–×–÷–ß,L¾_~NAQÁI!E¡RáªÂ¬"CÑV1N±Lñ¢âŒMÉZ)V©Lé’Ò ¦$“ÃL`V0{™"eyegå å:åå–ŠŸJžJ›ÊU‚*[5JµLµGU¤¦¤æ®–«Ö¢öH¯ÎVQ?¤Þ§>¯ÁÒÐØ­Ñ©1Í’fñX9¬Ö˜&YÓF3U³^ó¾F‹­¯uXë®6¬m¢£]­}GÖ1Õ‰Õ9¬3¸ ½Ê|UÒªúU£º$]Žn¦n‹î¸CÏM/O¯Sš~°þ~ý>ýÏ&   ©†.†y†Ý†iñªî¯&¯v\½mu×êׯ:Æ‘ÆGŒ˜ÐLÜMv›ô˜|253˜¶šÎ˜©™…šÕ˜²élOv1û†9ÚÜÎ|›ùyó¦é§-þ²ÔµŒ·l¶œ^ÃZ¹¦aÍ„•ŠU˜U•Кij}ÔZh£lfSoóÌVÕ6¶ÑvУʼnãœä¼²3°صÛÍs-¸[¸—í{'ûBûªƒŸC•ÃSGÇhÇG‘“‰Óf§ËÎhgWçýΣ<Ÿ×Ĺ˜¹lqéu%¹ú¸V¹>sÓv¸u»Ãî.îÜÇÖª¯MZÛé—ˆÿ2Â6¢,b&Ò*²4r*Ê*ª4j:Ú*ú@ôLŒMLyÌl,7¶*öuœs\mÜ|¼Güñø¥„€„¶D\bhâ¹$jR|Ro²brvò`ŠNJAŠ0Õ"õ`ªHà*hLƒÒÖ§u¥Ó—?Åþ ÍŒ]ã™Ö™Õ™ï³ü³ÎdKd'e÷oÒÞ´gÓTŽcÎO›Q›ù›{r•swäŽoál©Û m ßÚ³Mu[þ¶ÉíNÛOì ìˆßñ[žA^iÞÛ;»óò·çOìrÚÕR V (Ým¹»öÔ±? ìY½§rÏçˆÂ[EEåE‹Åüâ[?þXñãÒÞ¨½%¦%Göaö%íÙo³ÿD©DiNéÄ÷e̲²·7¼Yn\^{ˆp(ã°Â­¢«R­r_åbULÕpµ]u[|ÍžšùÇ‡ŽØi­U¨-ªýx4öèƒ:§ºŽzúòc˜c™Çž7ø7ôýÄþ©©Q¶±¨ñÓñ¤ãÂÞ'z›Ìšššå›KZà–Œ–™“!'ïþlÿsW«nk]£­è8•qêÅ/¡¿Œœv=Ýs†}¦õ¬úÙšvZ{aÔ±©CÔÓ)ì ê<çr®§Û²»ýW½_ŸW>_}AòBÉEÂÅü‹K—r.Í]N¹<{%úÊDÏÆžÇW¯Þïõê¸æzíÆuÇëWû8}—nXÝ8Óâæ¹[ì[·Mowô›ô·ÿfò[û€é@dz;]wÍïv®¼8d3tåžý½ë÷y÷o¯ñy02*|ñ`úaÂÃ×2-<Þ>†+|"þ¤ü©üÓúßµ~oš /ŒÛ÷?óyöx‚?ñò´?'󟓟—O)M5MMŸŸqœ¹ûb݋ɗ)/f þ”ø³æ•櫳ÙþÕ/ M¾¼^ú»øÌ›ãoßöÌyÎ=}—øna¾ð½ÌûØú>|œZÈZÄ.V|ÒúÔýÙõóØRâÒÒ?B,¾“sMT cHRMz&€„ú€èu0ê`:˜pœºQ<bKGDÿÿÿ ½§“ oFFsF×j`` pHYsNNÆÊ/¥tIMEä&>(Ê vpAg´¨“ÁQè€IDATxÚì{œ$Uy÷¿ ì•Ý™­aewYÖnë,‚Ô€8*D­‘[â­o‰`ØîÄDW“ÝÆW’`Ôî8‰nLôí†/AÝé_1ØåÔá6…;rv¦v‡½²—~ÿ8}ººçÚsížÙç;ŸþLw]Nª®§Îéó;ÏóÌËçóyAAAAAA„9¦ÚAAAAAA¨uDPAAAAAATAAAAAAÆ@AAAAAA„1AEAAAAAa DPAAAAAATAAAAAAÆ`N *™L×u«] ¡‚ Àu]<Ï›tY¾ï“Édª}Jˆ}Î}|ßb×bŸ³±Ï£“JíÓó<‚ ¨vu…aÛÛ ×®êåb»µØæì¡Z¿KÅ>«‡Øçì`¢¶9Ù¶S˜yÄ&Nf«MÎIA%›ÍŠÎ<Ï£©©‰T*E$!‹Mª<ß÷Éf³Õ>-a Ä>ç6‰D‚–––!v-ö9;û<:©Ä>}ß§­­mJš„©Glwî2R» b»³±ÍÙAµ~—Š}V±ÏÚg¢¶9Ù¶S¨b“G'³Õ&«v„£—H$B<'---d³YÇ©vÕA˜¾ï“J¥èííÅ4M‚  ¡¡h4Zíª ‚0I&;¸$Âø­]µ,«¢2Ävalªõ»TìSFg"¶9m§ ÂXÌ •l6KSSóæÍ#‹ q™ÕªvCC‰D‚D"Q6 Äó<"‘óæÍ+> ÚÚÚÈd2444ÐÐÐ@&“!‘HÐÐÐ@SSS™r:žmGC—SZßJÖ†çy´´´0oÞ<"‘HñÜGZ>ÖºJê?Öup]— ˆÇã†Aooo±aé\=Ï+~‡ºÌ‘\ÃôvãÝO˜Z&cŸ#Ù&ˆ}N§}Že/#«þn Ã(þרÁˆ}Ö£Ùçlj;KË|_Nµm޶®Ú¶9ÒùŽ×ÆJíS¶,K~„ÖsÅvg²]m]­ÚîxÚUÛ­¤ß;:µØïéߥ¥ËÄ>g–éh;¡ò{Mú½ã»^cÙæHç;ѶS~“Î<ÒŸ™Z´É™þ-Zó6™Ÿåôööæ|2™Ìçóù|<Ïùx<žÏçóùþþþ¼aùÎÎÎ|>æ|.—+[¯÷ÏåryÃ0Šåêr’ÉäãØ¶]¬Çx¶ Fóýýýùîîî¼aÅºŽ¶n´ë£Ï_×Å4Í—¶O¥õ¯ä:¤Óé¼mÛÅÿŽã”ËHçšËåÊÖéïK¯ÓåG£Ñ¼eYùþþþâ÷:Ò~Âô1ûÍ6óùñÙœØçø®ÃXö2Ú¹F£Ñ¼ã8ùt:w§¬L±ÏÚb4ûœmm§.k¸ûr*ms´uµ`›#]‡T*5ê~£ÙgwwwÞ4Í|Þ¶m±Ë`.ÙîLµ«£­«eÛÍår#¶«º\±ÝÚAú½³³ß;Ó¿Kóy±Ïj0]mg>_ù½&ýÞ°îSa›£]‡‰´ò›tf‘þìèצmr¦‹ÖºMÎzA%ç£ÑhÙ2Ó4Ën†R#èïï/3Ät:·,«lÿh4Z4fþ"K?6ÄJ·  ¬³UÚÁmÝH$“ɼã8C®ÙHËGÛ§ÒúWrôõÕ¢þ\Ú)î\µ ®[4-–Fó†a”í?Ú~Âô1ûÍ6óùñÙœØçø®ÃXö2Ú¹ê†[ÿ×ûˆ}Ö£Ùçlk;uYÃÝ—Si›£­«Ûé:¤R©Q÷É>ûûûó¦iæ»»»+¾vÂô3—lw¦ÚÕÑÖÕ²íê>òpíjé1Ävké÷ÎÎ~ïLÿ.û¬ÓÕvæó•ßkÒï ë^ÉuË6G»i;å7éÌ"ýÙ‘©U›œéߢµn“³>ä—çyEW>išÅ÷A”¹ÑÞÖ÷}<ÏcÞ¼yÅWµ]ˆ×±ÒuÃAÙõH&“#.mŸ©Æ4M:;;±m›d2I4-»ö#ë`·hÃ0ð} Ì%o°{Ûhû ÓÃdì³mspdzn8jÙ>Dz—áÎ5“ÉÍféîî&™LÒÛÛ‹çy¤R)@ì³ÖÍ>gcÛ9\=ÇZ>±ÁZ±Í‘Îw¬ý†³ÏT*…eYAP »àyž$Ï­2sÍvg¢]m]-Ûî­·Þ:j» b»µ„ô{G§–û½3ù»Tì³:̵¶s¸z޵|$j¹íË6‡;߉¶ ¿Ig’¹f“ÒŸý|'ò[´ÒãU‹Y/¨Tst´‹m¶m“WÞ:Å×tÜxµ‚ëºìß¿Øå#Å•mÝD°m{ˆ‘Uúü}–Ö˲,Òé4ñx|H ÆÑö¦‡ÉØçÑh›Pö ³ß÷1M³Ì–mÛ.î+öY[ŒeŸÒv–3– Ž×n'ÊDme¬ýF²Ï H¥R¤R)|ß'›Í–Å f±Ýñ1›m÷ù矵]±ÝZBú½ã§ú½Õø]*ö9óHÛ9>j¡íœ¨mN¦í”ߤ3‡Øäø¨›„™ÿ-ZË69ëÓ4Éd2Å‹êy^™²å8NÙM48©ã8e3B‚  ©©iÎthlÛ.»>®ë‰DøÃ?üÃa—ëÓHë¦ Ë²Šª2¨ëžÍf‡(ªÃáû~ñ{ÔûÙ¶ „ l<Ç4ͲY£í'L“±Ï¹n›P»ö ³m×¥ƒ9Ùl¶,! ˆ}Ö £Ù§´ö¸mp4»J&j+cí7œ}&“Ir¹\ñeYÉdrNÿX™ ˆíŽÌ\³Ý3Î8cÔvÄvk é÷ŽN­ö{gúw©Øgu¶sdjµíœ¨mN´íùM:“ˆMŽL­Ú$ÌìoÑÉo&8®Ú˜,ÑhÏóhjj*>pÇ)®·, ÇqhiiÁ4Í!j–išÄãqÚÚÚŠûÛ¶]VÆlFŸ‹¾>žç‘L&G\>Ú>S‰a$“IZZZ°m»xÝ£Ñè˜ûš¦I,Ã4ÍâŒøx<>ä!«Ë×ßåHû ÓÇdìs®Û&Ô®}ÂÄìEw|J¿o˲Ä>k”ÑìSÚÎñÛ`-Ûæx÷+µÏJf\ 3‹ØîÈÌ5۽袋رcǰíêpˆíVé÷ŽN­ö{gúw©Øfu¶sdjµíœ¨mN´í<õÔSå7é "692µj“0³¿EkÝ&ç’ÆÌz<Ï+ÆÙ+Uà‚ (ºA€mÛÌ›7þþþ!qk}ßÇ0Œ9ÙÉÑ×Ç4Í2E¤åc­›*Æ{Ý]×%•J‘Ëåp]wÚ÷¦†ÉØç\·ÍÒëS+ö9Y{™)»¦†áìSÚÎòk3¬EÛ››ˆíŽ}mf»íjæú÷5×~oe×§Vú½é¿HÛ9öµ©•¶S3Ñë.6=;›ûÚÔŠMÎôoÑZ·ÉYï¡¢é¢A@[[X–E"‘6ãt6ß÷GM”dÛö¸\—ÆSÞH×g´›±tÝT×]3™ë>Q7¯Zq;š˜Œ}ÎFÛo™µjŸzßñR »&Îp÷Ù\n;ÇSf¥68Úòé²Oi…£Ív§¢]m]-ÛîL|_ÂÔQëý^¨Mû¬v¿Wú¯GG[Û9ž2kµíœèu›žm6y4÷g«±ßt2g•‘0M“t:]Œ¿fš&U©‹Žw7Z]«Y^­k¬zLD‘¬5%SPÔŠ}NÇý=›ís¦íEì³ö¨Û±ÏÁeI(ŒÆ\¶Ý™î‹Ö‚í s ±ÏÚ¬ûdê!v=7˜Ë¶9]eÖ±¦±éÚa.ÛäÑØŸ«¿açLÈ/AAAAAA„éâ˜jW@AAAAA¡ÖAEAAAAAa DPAAAAAATAAAAAAÆ@AAAAAA„1AEAAAAAa Ž«v&Ë\@sssµ«1";vì`åʕծƈìß¿Ÿýû÷³|ùòjWeDjý>ýôÓlذ÷¿ÿýÕ®JMñ…/|×u9õÔS«]•©õ{kçÎ,Z´ˆE‹U»*Ã2ž===Üwß}Õ®FÍñÖ·¾µ¦ms6Ü[òü˜»ví¢¡¡n¸¡ÚU©9j½o[)µ~އZ·÷J©ô;‘¾íð|÷»ßåú믯éö³R޶{z6Péw"}Ûá©õ¾m¥Ì†>p¥Ì•çL¥ß‰ômGæÜsÏåu¯{]µ«1"µÞ–̆çB­Ûûã?Î>ðþâ/þbÊÊœqA¥¯¯¾¾¾²eëׯ§®®®l}cc#c–×ÜÜÌ7Þ8Ó§Q1W_}uMׯ««‹®®.6mÚTíªŒH­_ÃŽŽŽ9ÑyË6K·©Ä>ÿàþ€ Ƚ5 :::hmm¥µµµÚU–Ùòü˜ Lµ}žzê©5}ïÏ–{«–¯ály~Ì޶¾m¥Ôú=8jÝÞ+¥ÒïDú¶Ãsê©§rùå—×tÛT)GÛ==¨ô;‘¾íðÔzß¶RfC¸RæÊs¦ÒïDú¶#³`Á‚š¾j½-™ Ï…Z·÷H$ÂÂ… §´ÌT:::¸ýöÛË–Ýxã´¶¶²eË:::X¿~=[·neÓ¦M´··Ït§”Z¾áA=+yV“Z¿†s…Ñlû¬íííÔ××W»#2žs…£Í>gý%ÏAs´õm+e.݃µnï•2—¾“J8ÚÚÎñ ÷tí1W¾“JûžÙЮ”¹rOÏ¥ï¤R¦ºo[ë“4j½-™ ÷`­ÛûºuëX»ví”–9ã‚ÊÀÀ@YCYJGG›7o¦µµ•žž®¼òJZ[[kþÆZÙPWWW6 ¤©õk8WÍ6Aì³Ôúµ ϹÂÑfŸ³áޒ燠9Úú¶•2—αÖí½RæÒwR G[Û9äž®=æÊwR)bŸÃ3úÀ•2Wîé¹ôTÊT÷m—.]ZíS•Z®Ì†{°Öí}Ù²e,Y²dJËœñ¤ô]]]ÃÞ¬]]]Ô×× ¶¹¹™æææ9ã2'µÎH¶©×‰} Bõû„ÚEú¶‚P›HÛ)µ‹Ø§ Ô.Ò·„±™QAe``€k¯½–3Ï<“óÏ?Ÿ-[¶*¹Ú`ƒ­¯¯·o0;vì ££c&OCŠttt̉¤€£Ù&LÜ>ï»ï¾²ra¦èë룣£ƒ;wV»*“f:ìsçÎtttHçW¨ ]]]d³Y^~ùåjWeÒHßV˜kHßVú¶Bm¢û¶;vì¨vU&ôm…¹†ôm+ëÛŽµ L[¶l™–¾íŒ *}}}´¶¶²aÃ{ì16oÞ\lôvíÚ5dûJÜ®Ž?þøšM$Ì}Z[[Y³fMµ«1iF³M`Âö¹fÍÖ¯__íÓŽBôÌ™E‹U»*“f:ìsÑ¢EGEØ¡6ill¤¹¹yÊVéÛ s éÛŽŽôm…j¡û¶Ç|µ«2i¤o+Ì5¤o;:ºo[ËyJ„¹Ëúõë§¥o;£‚JsssY¾ÖÖV.»ì²¢ÛØ`*Q/—.]*?:…ª1W~tŽf›À„ísÍš55KQ˜›ÔÕÕÍAe:ìS~t Õ¤±±‘×¼æ5,X° ÚU™4Ò·æÒ·éÛ ÕB÷mk=A%HßV˜kHßvttß¶Öó€s“æææÙ/¨ôõõÑÓÓS¶LTssóCܵk—4ˆ‚0Œf› ö)ÕDìSjéÛ Bm"m§ Ô.bŸ‚P»HßV*cF•®®.6nÜXŒÉ700Àí·ßNcc#­­­ìÚµ«8+¡§§‡¾¾>.»ì²j_#A˜óŒf›€Ø§ T±OA¨]¤o+µ‰´‚P»ˆ} Bí"}[A¨Œãfò`íííôôôpå•WÒØØÈÖ­[ioo§½½€M›6±qãFÖ¯_ÏÖ­[Ù´i“¸„  0–m‚ا T ±OA¨]¤o+µ‰´‚P»ˆ} Bí"}[A¨ŒT®»î:zzzŠna¥®aííí´¶¶Ò××7d ÓËh¶ bŸ‚PMÄ>¡v‘¾­ Ô&Òv Bí"ö)µ‹ômalf\PFMä')Õc¬$›bŸ‚P=Ä>¡v‘¾­ Ô&Òv Bí"ö)µ‹ômatf4‡Š ‚ ‚ ‚ ‚ ‚ ÂlDAAAAAA„1AEAAAAA„Y‰çÍܱDPAAAAA¡¦ðý±· ˆDf®N"¨‚ ‚ ‚ ‚ ‚ 5K† >Œ® ³’ P^&AP.¢$àºê}6«^±˜Ú.›…TJíç83W×ãª}±AAAAAa$²d1 BmÓÖ¹ÜÐ徦©þzÙ¶LR)µÎ0”P’Ë…a¼\·\lñ}µ½Z´¸â8`Yá±2X±bêÏO>2$IV»úS‚GJEáÂvÅbÐÙz‚èí‰04—2²YåÁ‡^,ÚËD{èr´’N«Ü'Ú;D‡÷Òb‰e©—m‡âˆ.WÓÙ9ôüœéÒÀ 1Ä £pâñiSVŽ™¦SA˜0Ù’÷ÊKÅCy¥Ø…Ï.D‰' T"Õ>AAAAa\h¡¤Ÿ,YŽ|–íž ÝôhölÍž‡‡?ì~³è½”XL‰þ×!¶b±ÐûD‡Öò —C'mO´&-Š€K"µe©c¦Rêø:|:z¥è[é´Z‡BL)驞剄'¤O„,š––0®Øpq AE„š£TñPŠh1^{§èpŠI”â½(/·¢# ‚ ‚ ‚ ‚ µŠLv™¿f°€ÞÉìðN&A¢lÛL¦ÚµÙ¬r¦(ÅóÊÅ“TJé® mmêõÿT*Ü>› ½û¾Ê•ây¡£†åJ@I&ÃÏÙ¬Ê?’Ë…"ŒNî®_ñøÐ¼&“¦T )¥ô‹ÔIZ@],ÆóÊ·suatÌ1wúF%ä— 5…žS^zY©gc%¨”.ËŠ(’´^AAAanàá±ß‹ƒý;ý–›ýÅõûüÕø(¡«ë“|ã_®v•+B‹:Tî¢ÃÈg³Y¹\ŽxŽ9¶ê¬'xú5«YÐ~×0xæ3ŸÁô}^Ù±ÿ §Â½&Û￟°ôᕺe/܍ޣr¬¨÷ënãïX(]B‹™L(˜èˆVÙ¬;,Ky¦è¼èÙl¨]d2¡³†Þ/QšD:žkéû"Z¨FQ¹á©§¸FЄ2¡Å²,‰Ÿ°möýÑñ?çŸÏ‡V­RÛÅbJ±Ñ•Õ•w]µÜ÷UÈ.­êD£|îê«ù`4Z>ÆVHïÛ6¦ibv!ÔX6ðR©b˜5-x¤\—Ür ‰Å0M“h4J†Aºp!,ËÂq¢ÑhQ() ÙfŽã¨°a…òí’0gëׯçž{î™Ð½73ê¡’Édhnnf×®]tuu±k×.zzzèééÖ°*Q/—.]*?:…ªÑÚÚÊš5kª]I3šm¶Ï5kÖÐÜÜ<âz؇Ï5@gÉræk¼¡¾JqP ï]$ü×ÑH]]­­­,Z´¨ÚU™4ÓaŸò£S¨&¼æ5¯aÁ‚ծʤ‘¾­0×¾íèŒÕ·„éB÷m—.]ZíªLéÛ s éÛŽŽîÛ' ‡N@^O¹§pÌ'¿ÍÏâ;Kþ“{x€Ý‡÷@4ž`ÿÄþýxÇ;8tù|žß¿ŸkÖ°'aâ·eYµd +º°ýÔ·@öžp ¯ô.'¼ë¦›xýÀwÿσ÷¾÷A t†G€Ÿ•´˜¢ó¥èW*ßùÎA Ô2tÈ/Ç 4\W½ÇÜêÃâûa.Ê«4S}°ów¿ã‡==**GSSY(/ÏóxxÏð}žmmåçÿùŸxžGÿòåì?é$upÄ=“X ¿ h“ÄC(âXärøÀÃ+W–TÓWû)à StZZZp]—L&C&“QJ*…_¨ŸišA@ãÅ“N§I&“†išEe0Ñh´¸®T@ÑåDssó´ômg<)ýÀÀ×_=  ï¶Ûnc×®]´¶¶qŸÞµk—4ˆ‚0CŒd›:.ætØg€T@å=)e²Þ)¥¡Ã\ÆŸÔ^j‰jا •!}[A¨M¤í„ÚEìSj—j÷muú…qÛe7»Á8Üø óŒ]l»ì[,^{{.»cÌ9’Žð‹½{Ù·z5õ§üavüèG¼fÑ":n» ÏóÈýïÿ²6Èx<ø »vï¦ù¾ûXá8<òÕ¯ò‹… I&“¸®KX–Å‹›6Ñ‘HÅ Ó4q]·(ލkâcÛ6ŽãÐÒÒB:Ʋ,2™ ¹\€x¼|”/Y8ïÑÄZfF•M›6•}¾úê«Ù°aCqžV@[[[éé顯¯Ë.»¬Ú×Hæ¡v©¥¾ív J†ð8+/”Ÿ^ õ»9rÚCì1ˆÿ†#Ø`eéï?Gwìàoþs~ûž¥ü?Þο<û,±gÏàg˱mX¸éEŽÍñ¬ê}ÛÛvòìÇ×pè²Ó9fûöÜ{ »zU ¸eÇÉüÆâ0Pÿ‰Ä EçT êê³bÅg0Í$Çÿ(¾¿•t: •RŠIIÔ©²„òeèDñ ”ÏÛfõ¾}<ÛÛ AÀÁÿwŽlßÎq‡óË;ïäÄ^àp?GþöoYõôÓd³YÎzá^sæ™Üµ|9æðÂîÝXé4¦aàï܉ã8ʓIJ0T&–d2<Ïöm‚ Ç)z¦$“IR…p^–eaš&ñxÛ¶Cï•9ÊŒ{¨ŒÆ¦M›Ø¸q#ëׯgëÖ­lÚ´©b—0A¦—é°Ïÿ*Ì<Ð. Ø…¿ñ …E”0yš‰*ÂÜGÚOA¨MÄ6¡vû„ÚEìSj“™²MƒýÜç®Í¦FÔï†'pÌÓq¢ñ,/ØÎ‘…jŸ‡öíc¥að§çžË»¿nÀò'0/1±mxøáá^1ï{‡éÿíb¶.måÈ »™ÎïXnœÁüW=ËüŽc÷VŽ}ó~ã)aä¸EÏqÛßž(A$›…“O~”'žXïD£Éìá½Í'ÅsESR´k‹^`ša 1Ã(º»<ùä“9tˆ_ý*/ÿó?³bÑ"ç™ßü†³ÿò/ùå]wñÔW¾Âû-‹\ÀY§žÊµ‰×~èC¬-Ü(¥yIº»»‹ž!‰D+ç]½‹Ÿ¼ý'ôoèÇqž¸ã ,Ë*z’¸®‹çyX–E*•"N󗔿4)õdÑûÎEª*¨ÜxãeŸÛÛÛimm¥¯¯ÆÆFqé„*1Ø6azìs?K1ððpP]wLA¥‰&ºéÆÀ(.k£ ›,Y||âÄËÖ Â\a¦ìS„ñ#}[A¨M¤í„ÚEìSj—jõm-,ž€éC*Ϋÿ3NßÄ!ïäÏÝÃ" Ž, Ç|ެZźcWa§¬|–‡¶¼Dæé q]ðý“‹"ÿykžW~3ÿgÓ•üÕ×qä©cøS~°?Ïé휇ƒÏì£×ZÈ%¯îçŽoþ‚ùuïåê÷K&£¢rmzú·ìwaÛ[·þ¸Šoõ>ÇÿÈ :VX<®Þ§RÐÛ«Ä÷Ä0øØž=D¶nåÍ®ËÙÇÏ3É$_îêâc›7c}ò“X–ÅMçœÃüXŒÛæÍ#qÎ9ìkl¤­­ÎÎNÎ}Ë[H&“CChŇÔ¼M"‘`ó¹›9sþ™x–‡eX¼æG¯áùo=_ܦ4ÙûH â&jÊCÆRj˜©²Ïó àœ’ì)Ã?Œ$H’ÄÃÃÇÇÅÅÁ!B ‹$Išh*Š2ñt„ÙŠ´Ÿ‚P›ˆm Bí"ö)µ‹Ø§ Ô&Ói›Y²Å÷/» ìHÇ -Gãå÷ð<&‡Ò ²ð’˜l_«€yóŠ£IÇ:Äâûc~@9~D£¡sÈ»[WW’JÁÙ'þ–{ԯᢋNä…àÆyœÐð×~ã,q+W®aÿ …¤é°àƒ{xùø+éü<Üò‹eü×EÑÙÙÉâH„í·Þª’¥”æFÑ^(ÀO~òV-ZDs,¹œòLñ<ömÞÌŽ“NâÀ‡?ÌÀûßÏ}›6ûä'q‡5ïxkÖ`š&ó ÉY’É$¸.ËM“|>_¼fÉG’L&I$,r±äKT.,þíbLÏTx*üKÛ–±¶cª]AŽ>þqn¾ôRvþÓ?ñ«o[ضÕA3¶mÛÆ‡ƒmó«%Kˆ'“$€þînŽ=öX²Ù,=‹±nÝ:¢ÑhÑûò,å2(Ž˜7Ñ% $’~"°êC«°Ú,pda}h*¼s7-ʸAE„ªË³¤5ôðÊÞëÏ.n1ÏŠ‹Kœ8iÒtÒIš4Ÿiz±¼”}+ûS¹%ÑJ,¦ÊÚ/|AAAA„š&(±ßì…CKÁôynÁ–,YÀq‡0ïðaêòyÀääyóÐѶ>ñ‰546”ƒH6«þ;ŽR’I¥Mœ{î•\vÙ…<¸”––@yµ44<€eYœÿè£Ì—*+…G–,á]â¡òõþM]  eófö~ó›¼ö±ÇX°`ë¾òŠ…ù>ÿñ¹ø…ø×Å‹!çûöñ¶·½­[·²ãøã¹ï{ßãÍo~3'ýÉŸ°fÍ‚ 5œV&“¡¥¥ebÙF Êe¶Â=4—,œ˜Oèä ¼T\”¸¢‡îR%ïkÒº´1­ •EP¡*XÀ2| Œ²S‹(~É“ÏÃÃÆ&F «ð—$‰ƒ£Â}yQ’IÕ0~À™Ï‡ãÛyÚ[A<mgÇ[;AAAAa¦Ù‘½ˆýÞ …OËس{7 .×¥ñå×аw/sä­€ƒ±hQYÿüÏó‹J(Ų”°¢E•dR¥I§•ØRÈÛÀK/Ggg'gÿô§,|å@é ÈŽ³Ïæ’ .`ÕªUœúùÏCI2øD"7(üJ¤ ÉæÇò4Ii”°G Ò% ňÝ(A%ô–év E_œÄ8ëŠ AIYƒñJ¶Ë „œÔ0çÕB(¢X%ûNãTºººØ²eKñsOOW_}5W_}5ÓSCAæúÙ¼’Ÿ‰²ü)~á/Aƒ5Þ;ŠyS℉µ ÕøuvªñÉU,È]Á7ó{öM£*-‚ ‚ ‚ ‚ Lž~÷<¶e®¼j{–-ã¸ãŽƒD‚ãŽ;ŽÅ˜œºlç65qöŽO–•ɨÿ†¡DM!—zYô¬htäúÔ=ñû 1îœ|çØ¶MÞu±ûúp¶o'½c†ïsä{߃d’CçœCÿòåàyúúú¸êª«hnnæöÛogãÆÓSKAæ·âa¢W~þólxé%6nÜHoAÕY½z5óçÏǶm¢%±ÆlÛ½M²pø¾ÃÅu«÷­.«ºY®Ùr uO¨qy ŠÂÄ£ïz”/}Pymx…u¥áµ˜‚|íJÐО%^á¿þ:´à¢cþëÐbiÂcÉ’e…}Âpd½…ÿú9”`bÎ)ÞZµkLG‰3ó¾LV8…ã*ݰ±±±ìsWWíííeË´¸"‚P ¥3 ´wŠn “~'ÉÞÆ æ.LAAAA„ñ¡ÇÝ÷•ó§¿ ™7°de_qðÚ Fôà>(Á)ì\Ša(OÇQF~I‰:›=ð»ŸüŽU‘WQwë­˜¦É óçctu±jç^î¼âNv®~ïÖç.þ(¿xëiüõUWñÌÏÎË/¿Ìßÿýßó¾÷½¯Ì£$îÄ‰Ç IF:‰b ' oë~[ÑÓãƒ?ø ‹_Z .œöÔi<ûígáiµ>ìž¿›U‡V±gåX‚Rl8òÅ#®;ÌüÌ'U¸DI¦@sÐct¥×|ðºÁh©ô;&º¿ëº¸®K&“!—Ë ñÖ)~]…Ó® Xð›×ÿ†fš™J*òP©¯¯§«««øùöÛo µµµ¸l``€žžêë§>.™ s_“- *iÒeë,,²Yx2û:δûˆFGq9V®G#{±‚ ‚ ‚ ‚ ÕÁ£<*sÜwÚ ×Æâ“ð‘²dƒ͇* ûža›Ò°Y¦©bƒz™¦XR)šÿ·™¿Lü ¿úßÿå¾ß¿ÄÅÿv7Ç}¿ƒÃ]OP÷ûs¹å¿÷Ò–oâ´¾ü¤®Ÿþ”0púé¼éMo".ïrÕ­%ª¸°øùÅ,Þ¿ðâ/rç‰wÏoÅŠJqJÀ3/?Ãâ?Z )xôìG9á×'µïY°‡­­[ÙÒ~8 IIxϹïáîWîæ£7´xIÚ(Ï?^|ß½j*t*Ûg´{ÂóˆDT"–h4:â>Z“2Q—(›Í’ÍfI$@äxøÖý1/W±OIET$¨\zé¥ôõõqíµ×rûí·“Édhmm-z¤ ÐÑÑAcccYX0A„‘x¿èA¥<7ʃ‰÷áºðåø*¾¿x\µu¹ÔíÑÄŸT{8–ð"‚ ‚ ‚ ‚ T Ï·5a¿á¸×óe¢#l‹ÊRúY¿ôH»Î§¡`RÜÞƒHDýïì„TJ½t(.×åM{ÿ—žßÅÛO;Gv H¬XÁâ©»¯ŽW½þUì{ùï8v×ù¼ØPÇ¥Ï<€iÛlªÛ&S×9N¬’zR’2pöçÎfï/öBŽ¿ûx®zå*•›¤àu¢5¥e‡–±æ“k ßuØøÅYxÕ¸ðû²ê«H¿:­ö醬›eþ‰ó¹èª‹èþÀ«1ÔæûÕÔÔD*•¢¥¥¥,ïK&“!“ɉD¢lß÷ñêkðð---Äb1,Ë*G|ß§­­––²%9mü’;˲ÊÊK$444Ç9xPÝ'ðÈôß?ðƒ‰pÉÓO“®¸mïÜ¡åT$¨477ãº.=ö7ÞxcÑeýúõÜx㸮+Þ)‚ ŒJ øLÁ×ÒÅ-Ë¡¢±Ý$Ž3¾|'c $¦£Ä™LFµ™‘ˆú/aÀAAAAªÇÝÞ6îÍ<˜àYœcÁ‚åý,ØsÇ{,0ÂÀ¿9hE!|ßkQ¡µR¨D!¥” årjï1üM Öm8ü–¿­>œl¼ÖdѾEì:ó4–ð+?åqв`ẅ,l]ˆµ ì}…juBϼEDn,ÔÁ'L¤nzÖX„ÂJ®ØvxÐï¦C¿Zž‚_·ÿšGÞñ$¡ïÌ>¥„8°ouá€|æ‚§Ë·xžG *¬×Ý]„gYdÓn¸³P ]•‘H$´´´ÐV2xæº.¶mÓÙÙ‰m—'>ñ}ŸîînÒét™ ¢Ã|†A4âÕ’L&éíí².ß0 ¶¯YC%í+ûV?oýú׋ߧܵr%¯ÿùÏùJOQÓäøýhÚîÙŠ•‘¨««+Ë¥"‚0-ií¬AAƒ@=ÿ“É‘½N†£’P^–ÝÝê½~æ»®Y‚ššÂvÕóFNt¯ëYAÈÇ£¥¥Ú5˜:2ˆÅ&_Ž ‚ ‚ ‚ µÏ3Ávù/¨žÅr.ïgéñ'³dɵ¸t‡Bz2„¢ÊŽÂ²°ÆRËR@6—ùJÀ¸Ð†U¦8v_÷ÕàÓæ vá¾ï³çÐ#Í~o1{_ÚËÁÏä†8ö‚c9û«gsöUgC/EO|õʽCÕÉÚ îÅà¶Aâàß_ØÎ-ü/ä¤Ç@y—DÕk÷üÝ$Hð£‹~ÄÙ×­–¡?Þ¶÷æ3,n^\Làþ•uëð€&àÆOäÉk®):Á,ùö·±€NÀH$xÇ’%ô+ﺫxG›ÇœÉdð}Ÿt:=$¼aÃîãû>¦iÙÞ÷}âñ8¹\nȾ®ëâ8¦ib–̬Ö^,ð@CßýÈGðQyîOÿèG±›/¹„5·Þ …˺ôàAνï>¢Ñ(ŽãËØqò¦šŠCåꫯfãÆôôôLyef .H&Î5€=ìºT F+F²½Ñr¨¸%)¶L“¢÷‹ëBo¯:f[›*;SÇD”¨ç)O–ÒÐzY$¢D˜ÁD"ª,]×L¦¼¼’$j;]¦ï‡á;‹õ/ˆ>¥eêz45©íƒ ¼ÜÒ}§êy•H¨ë“J©c{ž*_ŸW6«Ö•^#릿SvM{×–~·©”šâŽMrà‚ ‚ ‚ ÂÜâwþâðƒí²Ê‚¯ü[Ù6eÃ>‚q%d8(áäI(Ai~\0bðY52ÿ˜ ¢*äÖO<¸ß3 û0߀ùIXíóìÉ+1\ƒ½Rwþ¹´eÚxr퓪<›P‰Ð!¹r…å:WŠ Ö €K ²Ÿÿ«àÄ’(a%–ù‘w}×uËÙÛ*äÕ+ï|'Oœz*ñ¸Rc\àÖ5kxøòËq€w|õ«¬Û¶êôæïÞÍúú0ƒ€³}tˆ£Î`‰)=¨ƒA¢Ñ(–eašf1´—ëºEQÄ0Œ2o“RAÄ!ìŒaEO-xèò^¹è"–Î(s«‹yWR©Ko[ÊsÏ=7©{t0ÇU²QWW}}}ÜÿýÔÕÕ`Û6[¶l)&§===ìÚµ‹úúú!yWúúúèë룱±‘ÆÆÆ)=Ùñ-…X:ŽÓ[8oõÊf‡&Ì„ÙÎh¶ ScŸg ÄûÒp_®z<ärã+/”=Ž",ÁÐЙ¦©DM2Š6‰„,¢Ñp`¾¥%´ûx\m£‘x\ âçr꡽a,K ðëpfZˆFÕç–%îX–*/Uûjï-ôd2ê½ö˜Ñ¡>uÛ£… ß½p´(ÔÙYÙµÔ‚O:~½½ê8úºè륯ƒã„ÇÓÞ*ªŽ:tZ<®ÞFÒÍ4Uݵ•Ë• cú9ªü Påj!Æ4Õõ6 µo*¥ê«Å0Ûž{Ïç™°OA&ÆléÛ Âц´‚P»ˆ} Bí2Ó}ÛyFÀáàqÈ\ÁÙÆyÜÑ{-À‹KS=…R `5ÐSHÈîµxðÀ[|( >è0[ëA?³¡o+G#Òv Bí"ö)µK5ú¶'8óLì<°öphþ>vîÜYX“dqé†u€ ÆÂgY=€àø‚`r¯DÏSŠEÖ„í…™§‰„R"VúÔ¯~’Ëßw98päOîàæÅþ›û3÷spéR€¢pP‚kÄQUË:ÓxªúňaT›ÓÀè(aFáPxo÷Õ×c 3ÃØ¶í…”Ržà×dL¿$Þ}©·ŠT‚  »»»Ì3Åó<ÚÚÚŠyK4Mmmü÷Îø@ÝŠeÇÜ»n/e2œ¼x1 _aØ}â‰lýÅ/ø€mg¢Ñ(mmmÃæa ý½}ûßæ¸—+–@*bjKƒžžn»í6~ò“ŸPWWG__¶mÓÞÞNss3lÞ¼™ÖÖVzzz¸òÊ+immñÙýèƒÜyçÿáïÜÁ–-k¹è¢Ö¯ßΪU«Šƒu†QžWAf3cÙ&0¥öib%|8jQd,Ae¤P`uu/’H$†T(&æãe¤R),+N*¥öûûûikk'Wp£ñý†gÐaI$¬Xq,ñøw™7o'ÑhÓ4ñ<Çq a”²nY--Á…}°¸¢Û%ÏSÇîZX–P,+ ¦=:´wŒ­¦&¬»{¨x2Ö÷1Öwåya#yÆðëLS‰5Ãgi¾˜Ò:FyÓi¸úê,pùÄO¤˜iû¡rfKßVŽ6¤í„ÚEìSj—jõmwd^¯™—Þ}?ç6Ÿ‹©ÃK•lg<ÄÀº\íð`Cqx)ŠšI jðÃqÂY§ f¾ž ˜&<ôi²ÙF,ËâÛ±o³/ØG$¡·ÄÓc:°Cm5 #.Ê3%GIÌ.œŽ*Íe_ZÞd8°d mkÖ½ZþmÇ~ìcÅmšZZè›?ŸU§†WØVóÚ‹/æÀ'>Aüâ‹ËÊ}ê´Ó¸íZ`ÏâÅXgŸ]\÷üæÍüèàAÞ²x1‰Â9¶ÑùóIŽà}DZm{HÂûRÜ⾟ùЙÿêãá’I^¬*Ρ2ôõõÑÞÞ^ôtÑ·k×.ººº¨¯¯§µµ€ææfš››éêêš±úÕ×?Á{Þó~ûÛå»ß=Ì‘#kqxå•‹8å”ÇI&Ã?ºF{®Âlf4Û¦Ô>µgŠY"mèZc‰Ì# ð¿ôÒ“C’aið}¿¨üd³Ù¢ÚA™òÐÖÖFKK ‰DË ×=òÈ#Ř‘©TŠD"Á—¿¼ ÀH$‚ëº$ ²Ù,O¶´´J¥øìg0ä<}ßç/þ¢}û6—e©ëúõ¯&÷ ‚0œ—Î}Rɵ/†&«Ÿ(ñøðË“Épg6Øcg.1“ö)Âø¨õ¾­ ­HÛ)µ‹Ø§ Ô.µÐ·}åØV®\9¬‚ù›éêêbÛ¶mծƤÍ6AÙùDìsÛ¶môôô”ÅÜô(=´§Wžˆe¹‹´ÈNwrèÐ×p§àQb•yª <=À?ÝöO|ñSÿ— pÇÝw3Pðf ‚`H¢-]†iš˜¦I*•â oø p6õõObY‰D¢Âë‘Gþ‹®.UN$Áqr¹Üd\†a`š&A“‚Ù¶Moo/Ùl¶ ÞXD£Q2™ ¦iF‹Ç²,‹\.‡ïû´µµqÓMV±±O$ebÒþýÏã8–eáû>O=õSyä2‰¦YžPe8ñ_Ǧ)qÙ`|ßÇó<|ß/^{-ä´¶î%‘¸®è¥3Uè6Rç_Ñÿ‹ß{á^Þ¿ÿ”³ZL‡}îß¿¿èÆ-3ý„™¦¯¯ßþö·¼òÊ+ծʤ©Õ¾­ LéÛŽ¿o+3¾—wïÞ]íªLéÛ s éÛVÖ·]¿~}Y*‰RNŠÿœç"o„ôÍ,¿ÿTÎ:ë,¢Ñ(©Áž ¼Ð‹C?ƒÆtüñÒÁuB£“|ß§>ë×ãºn14–çy…Éš ƒóØ[(‘A{ªŒpFSŠïûÅñC‹QÀ[êêh›7O¼ó4•lï¡D §PWPËZð†7pçüùe¹_¶¯YêmÛè»ãNúÈGˆö‹3¼WÍóiÇdðÄêÁ¢KOO?^ûcÞ~ÖÛ§ôVä¡R__ÏúõëË–M¦¡êëëãúë¯çöÛo/6šz6ÂàcŒÅž={&¥†ÞrË6Ö­{˜k¯}˜ .¸™O¼Ï>4p%–˜9òã!ûš¦6“ÉÉÏîÎdT.€TjråL%%6E*~Ö¨Ùí±ØøËž+Ì•šál&nŸÛ¶mcëÖ­ÅÏZÅ.MH¯CRÙve¢Šºÿ¼¢—‰çAOϱm›l6[Ø‚€T*Å®–e)qö9û‘Gˆžu@Yã›"TßKoUöñ{{É¥©CLÓ,6j¦ib±XŒîîn<à ‚Š¥iêeYV±Ñ/Å0 òù<---üìÁŠÉ¼|ÐfóæÍœtR·Þº˜[n¹‹/Y S†aFéîîÆ0 ‚ “É`Û6邘“H$hkk#ÓÙÙI*•"=e´¢÷Õ×#ãy™L¦X¦Ptý3™ ŽãÉdp]Ã0ˆÇãEÁK'A+½Æ®ëRWw¸„h4˼yº»»1M“Ûn»+¯¼’o}ë[Óe.3ÎTÚçòåË'Ôv ÂT ”Í%Ñ ú¶‚0Hßv|}[A˜)Ù´iÓ!³éÛ séÛN¾o{(X ±4 Þú8Ë_ýê‘7܉РµèßþSÅ%Ë/ˆ'ñ8Y×ʼnǕÀ¢Üm›¯¸.A!Ç#Û·cÛ6¾ïWJj®PiH, •×$òJÑ#OZPqQã^¹AûD Û´ìÜI×§?Í÷{{1Pa½ÔÙTzߌåQÔÞÞ>-bû¸“Ò÷õõ•)ÿ\vÙe#ºm•²eËذauuu477Ó××Gkk+[¶l)Û~×®]Óæ®ù‰Oü–úú#üæ7o¦¥e/;v<0DLÑ$“ÊK¥Ô%j0ZXÐ ëuBfM$ &--J˜hiQŸu~$×U¯äXAã&I"z×è\ ñ¸z‹…õ,fƒ ô°m%Hø¾zŸLR–—ÁuG÷4Ð!Öô¥,7"‘0'B"¡êhšªÌÂsÏ+ïÓÒ¢Þ«<êØÑhJ*™¤¼èÙG$½½ªìÒã­Œf› Ó©°Ïán Ç9a9(å\‡”Zºô^zéiLÓ$™L‹Å8á„]Ï‘“ËåˆD"Eo‰ÞÞ^ÒËÓìܹ“O¿áÓêxkÖà7¬XRÔñ±±—BèÍB=]À1 žú³?ãÅÿγ}û#wÜËÅP` “=gEŠáãZ:„"’& L,6Ñh´&ËE58YÂY†aŒÚ®øÛ¿å­çžË?ûÙâ²x<ή]?eÙ²C<ðÀbÎ?ÿ4¾ð…†a éDhA£”d2I²ä58$˜.G ^aø/åÕãy^™`‰DŠç —ëï\ŸŸrt¸4ýÒÞA{÷^‹çA$âà8®ëï™l6ËË/¿<®{´™)û/>>"D‰bcãáabâæ«XXØL¯»´ T›ZêÛ ‚R«m§ bŸ‚PËT«o{ÀoàÄ¿ÿ>;Þ3t¬c ï ÃÖƒWú½½3“H¹ÔÊóÊÃyé¤ÑZÉfC/}Ê–:òŽ޲Ù0D™ 6Òuôý°Ùlx]V\rIq™iš,Z´Ç_V¶L‡› FòœI&“är¹²|5:Z2™,kdu@‰6½½½ÅPlZØÖyf¶oßNÀÊ•cÛ6©T ß÷éììÄu]N:é¤)9¯jS ûŽ€€,Y"Dppðñi£Úh#A‚ \\RÔPKA˜&j¥o+B9µÒv ‚0±OA¨]ªÑ·}%?é¿ÿÛ+ØqòÉC7€§Ã½÷^õ!Sƒy‹‡Þ*z|c˜¢ÇR©TqŒ(9ݳÚg)qÔ™ÃÐp^¹Âkðr»°¬¸¸±qN_ÛŠ=T:::زe ×]w]™›óÀÀ[¶l)º†ks8ÚÛÛ¹ýöÛ‹îb[·nå²Ë.+–·iÓ&6nÜÈúõëÙºu+›6mªÈóe"8°†«®ú9wÝu‰ÄyŒr­8P7R’fÛV‚ƒžiïºJ,ÑX45©Ð^£yoŒ¢ÙŒ›T*ô2Š«Ô;D?gL3ôÑÏœÒð^A ¹œ*Ó0Ô955)Oƒx¼<׊a„^ AzŸh¯í©‹©r¢Ñ0še©cE£j½e…b‡örÑâ®w*¥=ŠÂýu´Wm‡ÇììTÛg2êøÚ‹åhc,Û„©·Oý} 'µµµÑÝÝ]Ì…âû~!Y»ÉêÕåŠúwÔ±k× ÅÏÑ‚^ºÍòåËG­Ëp_¹ö8q¯½­—h kï:F¹*¦PˆC(ˆè¡ã(åbŠ[ò?(죷¶Í„ˆ ”GGaû4¡W‹k<ÂÙ#qdíZþ|íZÜAË÷ï_ÌóÏ/vŸ ðšŒ³–‚\×-Æ*Mp?¦iÒYxˆèГO®ààÁƒ8ŽƒišE—Ïx<>'â(WÃ>GÂÅ%B“8q¢…ÀufáÏ/È‹..Y²øøâ©"Ìij©o+BH-µ‚ ”#ö)µKµú¶KÞ}‹zZyåàAö,Z4tX^xQðtèîV¯A T|©Ky 8Æ¢C¬û¾O2™Äó¼ŠC_í E~ÝW(¨ôôôpýõ×sóÍ7‰WWWWQ2™Ì¨‚ À7ÞHOOOÑ-¬Ô5¬½½ÖÖVúúú&•ô~4”7‚ËŠkèìüé´pËŽlÛ.†¬i&·ã¨ÁzÇ^‰FU¸±íñ'¥×Þ"Z Èf•0 ¾PPÑž Zð)õðÐå<ãŠ!»ôxt©h¡Á^Éd(~´µ©ýµˆÒÝ ©”:ôvÝÝês,¦ê§Ç\ õÞqÔ:ß/q’ÉrAFŸŸm‡Þ5¾Ö B1+•RÏ\ßWeÛ¶*S‹1ZhÉdÔKç‘™ëŒf›0õö©½¡†Ëù¥spèó¹\ÏóX¾|9]t¶ýºâ¶=ö-- ÅÏSûÒòo?†ÇXƲSvÑo(!%MCÒ"%´'ŒSì’u–éÄ^>åq, à [Ø6[X½]  %²8…ϱÂö¹ÂvÑÂú€PZ´h†±gžy†eËö©ï¢P}NÚcg"è0_ºãâyÞ”ˆ)ƒ±m۶ٲ奲ëV?3™LrõÕWOù±«ÁLÛçpdÈàãÓI'Î 2:莉¥…R¤00°8zâÒ G3Ñ·uqE˜„qR m§ Ã#ö)µK5Æmýn5Çx¯aÙiO³‡Âx‹HѳLW—”ì«AB=ظø°,¿õ­Øï~7@1G«ã8Äb±bþ×¹ì9!Ì  *]]]´¶¶ŽšhhÆ ttt·ÑÊ™ÎÆÒ÷ámo;‚a¼Ä)§œÅ+¯Œ/±yé¬ëè0I´÷…Úvèþà ¦’qÇÒœ#:Y¼.[ $Ú;D‡ÈÒ„Λb¡Pâ8a˜,-8 öðÐç”H„Ÿµg‡®·®S<† ÓùVtŽ“–õ¹·WmßРÞ'“ás0CˆE£¡—Œi†‰ö0P(ñ}UG}Lý>“)¯³ã„eéü)ºnZ8ŠÅÂ\8ZˆÒ×T½»»U9?ûÙ¬]»ˆ¹ÀXÉĦÂ>ƒ‚¤`Û¡YŠŽ_©ó X–U$7ÍGޤÈdԵ߽ûÿ°}û£œ}öèuò˜¸ë—ìÞRϳ†Ï‚Ë—ç=SL”p¡-^Ï %RÄJÊÔa¿ôvƒkè¡ú ZPÑÇÑÉìuÈ1-‚äPýdI½(©…:¶,ÚÇêÕûxä‘=¼ùu´ƾôP"M[É1uŒËha;-Ðè²µGK@y^˜'¯¹û©§ØqÑED,‹ pÞ:§L:Mïkö/qìˆvvâ.ø †+N¹—óæôpãLØg))RÄ N¼±ÂÜOe*sœ866™Â_zع-‚07˜Î¾m† D‰’D~ü Âx˜é¶S„Êû„Úe¦ÇmtŸÆñûãÀKG€‚„Tv¢–?~š«Á9Ë Y†‰ê;Ä(gR(Ñ#(¬KÊmByª8…÷ºn:Ç‹žÔqÓ%ÎIOóòKçóPdO‚,^8–Ö~µè“tn¥O?ƒP`± Ç2W–½|ÆüåaÕÚ›%- - 9…ã¼kÂuaÇ)@¢°Ìfâ6‚ÂÅ%A¢®+K¶è…bT˜FN{±D‰!RíS„Y‹‡GœxqB‚ ‚ ‚ Ì|`þkçøÇOaïñ»Ã6û€µÀ¯…ÀüýàÞ©…Jû=2ñð?HôØc±,‹H$Bgg'©Tªl|I˜»ÌÔw\QRúúúúŠD˜¨VùïÿÞIcãAž~MÑCa¼*:¿A¶4Ãù2R±MM¥õßÇba˜0­ñháD‡ïÒI×çMñËy&ÒÇ  â,Çw·nßÎÎ;‡¬3PbÊhz¶;ÂrƒrÑfå¢çXºô Ç4/.Š=(ïa¢EAÅÅ¥“NL&þ0—`A˜Y²ØØXXEOAA*'4 ~‚P›ØüaNøýò~.ô€°nUïÀù÷BÂd¸92°dšfQÄúõk']–aX–UL˜=üñ||ßw2óBѤ4‰<„Éá;;˽Ml[­‹DBñIJ”WŠi†¹Wt•£ÑðX‰D¹HÖ'[&œŒE4Å4M®ºêà¸Â©Mß÷‹^ ñ’øa: YéÔóŸañLÌbrùÉ`bJØ/A˜¥Þ]"H ‚ BådP¡€uKªC1çPã²Úc¥L„™GÿfŸ—?Žwì{«W¯V VS ùÅË„†æ&(+Ç0 Ö¬YS6¶F‹âŠPÎ\õUm*öPÑÔÕÕq饗ñFéëë«Ù°_wßý#~ÿû4ŸÿüS¦¼E£QR©‰D‚xÌ;ÿë¿øòºuªÞ…—>½ç››ùÑÝwsóüW|øÃXÑ(Žmã¶3QÂË`‘­³³³x t®Ql'J51ii CÕA0a®™âª¤ÁgàÐIì'’¬}<þÍq,>{Gų‰²Æ5´þüóÏO¨~^ɵëxÆë^¢å ¿àǽbH…ÚÁÂ"FŒN:ePX*DÖd²||G„Åÿç;œ÷ù ,} \¨»Âçsaât1ÏAl6Ë¡÷"ò¾Hq¢t"‘AeDP™<ãTf#7Ýt<ûØÇˆF§v°6c‘H„ÎÎN‚  ¥¥… èî¥eÔýƒ  ­­­L5-OL3 hšeÏ R)%èÆ['Ÿ×e”&•×ÞpZpq Õi®÷Ý$)·¥i¹–E]]‚ºº'¦õ86Ú¿Ÿå+WN¸ŒJD-Z´P¡ÌcO3‡ËÑŽ¶“é=llRCdiAFÂÅ-KFoŠï ‚ Œ‰Ž\1Vo¶»ä½žÌåAöî‘…7YÊ»DGÑ_!Eô{Ë*ãBQÔd×TJ-ËdÔxO.'^+‚0/>7Ÿík S2W£Œxð·ßƒ¿hqßX,F6›å5Û^C4-F˜qœ©$8W°m{Â)*jT¦˜}ûöñ‡øši+¿Tõ,6M×u‹á¿t˜0Û¶ijjÂ4Mâñ8ñxœ¶¶¶Bbn‹XL 6ëó l=ÓA7æ©”j¬õ¬†Ò†{¸9<3 ¾²w/Ï£áúëñ,‹cÞþvNxì1¼Ë/'I(PØŒßõõ̾>~ùÇÌç¦YhøËË/çòQêgFÅ^FÉÿÒ=ì³Ï¦ûÎ;¹­½Þ’u:ÿˇ>ô!øÌg¦õ<çÍÁ›ð-XAYc7]!¿bĈO{0­É3—úÒ^x!žtÒ¸öñPÏ'í­3’À?üþ÷Õ¾ ³Žéò ±°ððˆ+&ÙatJíÑÄAAƒ,ã S p‚ßò!åCc –Ú°øVo8!´tXa¸Ÿ­•D2Œòðí¶ ±Xu$9³ø¡FHFõšÿ®;yÛ'ÿ wAaA;°­ð~÷n58jYåÉŸ èÜÏîb·&óñ 3ÇtMÒŽŠ•®®.ºººFÝf```Æ*=^^~ùUUÉašf1»išÅ|ù9ŽCKK‹Jï'ÉdT£ª=S@=; l¼µ7 ŒÞx·zšè«p˶mÜœ³l[¿ñ â°ñb²?ÿ9å‰hºÿsÁ$€?Ÿ‰ë<Ê:Û¶§dþß.¾˜Ô cé{ê-oyË œåìÇ®ö‹q^†¿[¼%‘ˆjø¦Y—„ØCÑ‚`¥xŒ?1ýÅ_Ìx$UZ¬4ü^)#Ý%ûtâºAXÀ …|LBåÓt®—^Zh™|A‚pàá•…ßÓÞ–‚ ‚ ŒL†rH$ÔÄÕ}6œnò4ì´áK¨ßÓ9Á¶ÃñD¢ÜãEŽ\·ƒÇØåÆvð*„Ç·¾›7+ã(I J¥p‡\.G$ÁŒ‹˜r´âº.–eÍèØÿ1•lÔ××GOOϨ¯¾¾>Z[k3“Ä 'ü´*ÇÇãX–Eww7–e‰DFÜF£är9@…åÒXVèRª™igìYz†wŒðÙôØÁƒ¬þå/ùòÞ½Ü{î¹ì<æþ~ñbâ¨gÕTÌá7N¦7D%Äãñ)Q¨MùÔSÀ±…!yÛ„¿õÇØ¶]Ì4ÝJòtÏFtÞšJÐώ龂ÚRõ0\ ß%MóæÑûêW³lÙ²i®0UØØ2(,Rê¡baáÚÑ)h C¦ÚUA„šAç=ëw‹ïCSS(¦ärK½6ÄlõÛ¿™‚Êr;N–hÔD|Ô>›UõlkSŸa.±SÇÏÉ:,h|A]id/mÈ«W+.Ï ó  Æ4"‘™L†îîñȨÂ\"’Ífiii™Ñ0oy¨´··ÓÞÞ^ɦ5ǯ½ èÞÌôxÁÍq|ß/‡eY…5L0¯Ï—Êw?س‡G?÷9º?õ)æíÜIü©§øóAß©ÁÔˆ)‚0>>'þêrÜ~¸àÅÃ|þÊϯéV’%™o9°Æó  /ˆŒ‡8A=ÃFªÃ[N=•ûN=UÒœÏ"LL2d°°Dè„ ÐF>>iÒ¸¸¸¸eÞ,‚ ‚p4âSYå¶65YUç71Œ0gf´¤,åñ’e|^/!£i¡'™TiuK&ç ¬ç7zbûINúøp/X¿®Næ•leî[z|Õ÷}Ç©JT¢¹À\È¥bš&ÝÝÝ3~Tä¡200@OOOU.ÌdùÔ§^â”SN©v5°m»èRš j @Â0xò¥—°¬ÐÅ0*o0]×åë÷ÝG Õøw9 ­¥…« ¹LL`ÕÂ…£ ;‚0èÁõ¥»—Â*X¼1 4Œ~?ê¤?‹^žTø(H2ßÛi:±ˆ°ÁÄ™¼(#Ô&&m´U»*‚PÓxÃ<»é&I§ðçâÒF dÚª ‚ h•‘О½½J¨°í‘Cl™%e0£>¡É¤J`?x¨œ+¾†„ÙæË<Ùü'{ ‹—¦²gЉ¦^°ß÷ ‚ß÷q]—LF<¶vª!¨U$¨d2:::Ê–uttÐ××7ã//¾ø"ú§‡§ý8jœ·h‚³5ø…í"…ÿ:_€YxõoÙÂÏ|J¼”¾±go¸óN|ßçξ>þpÕ*þº±¸ÿ¼óhjj"‰`Y½½½$“IšX³f¨·ÂŒ£;¶«ß¼x~þòÏYzP }Ãå*3–Tá} e\ T;£ð9BE#ï’GE1ô×+!VJ–r/ Ufo®¶A’$66M4áþA(ÇaHÈÂ"Y˜G%J’¤ä A„£t$anÚJP¿E:Q?E«9—Û²”dYJTÑ+ ê¼"‘0Ò L,Ò‰ Ì$û õY/ªÅ$Îv;…¤ëbêCŽÃM¯¼RTlÛÆ4Í ó4™Š¼ÓG# *Ãqýõ××¼ ’JÁ¡CŸŸ‘›# tPmh(üOŽ §Q9 ŒÂû$aî’5·ÞJ‹ÅÊÊ×ù\×%‘HÿùÌ3üvñb®»õV>»{7ðøã¬~Ó›°|ŸÓN8ÎÎN,Ë"NÃ*™ ¡q„ªááñ“k›ðž‡—{™UÛV©.”M®Õ¾Õ Œ#‰2š$åF㣌J]ŠGþ-¬,ž D£Ñb8ÂJéfüy„’Œ/Œ ÁPÆdtAe*B‹ åX3ÔJ$I%J[áO„ñ'Ž…E†Œˆ*‚ ÂQÍh*±˜òFÏØkõ›¦dœ·êD£JTéìTc^:,˜e©œ+‰D˜wED•‘Ÿêó<>ø&çØ Ô‡¡†”÷m=Ïò,\×Å÷}’Éä”äM„ñRQ•©¦¯¯¯(Æ Nd¯×566ÒØØ8©ãÜvÛAŽ;îåóÆð …‘JHéÚa‹PLŽ]¿žÿ0M>ë,‰Éd’D"A*•âïöîeËž=¬|ì1®Ø³‡ßÕÕ±ø”SøÞ’%¬þí„øŽe‘Éd°m˲¦=Ñ·0·Í6K××>=Bg’U¿[/ÃuO„q¡´" åYÿr„£ëƒuQ§°. µ×‚Š?t{ÉÕ2‘ãOJ?ÞœLúYz›ðvðzX@ÿt]¨cºìs0Sb+>Ý4Q¢dÉC€98Dÿýéá͘$Ã1Õ}ÛñzmÙØ$Hs«‚ ˜©¶S„ñ3ö0|÷3›Uè…(ì£'ÌÖ:üWéù”ý$“JL‰Å††ƒÑs±èpbA¦©ÊüóÑóÔ:ÃPïƒ@_ç 7 õ¹´N©B¸nÛËÕi1|_mëºjY4ª–§Rá¶ZÑž:®«–;N¸¿iª}âq%,y¤Óêû×Ç1Mµ"^ÇDarg4æ®ÉdÔ{Ã…8½¿öÊåÂívíj&éªö­1eÌĸíA` /ü¿º¡?ôÛÚÔ•ɔ݀aîiGÆ;…ª2ã‚JGG[¶laýúõôõõQWWÇ7¾ñ êêêØ²e ¬_¿ž­[·²iÓ&Ú%NÝÝyþò//˜‘óòP ­6óÒŸ²ýT>iÛ¶Oþä'ùÆÇ>†‹ê\ò?ÿCg?Û·ogþÿý¿4<ð§üð‡,Þ¼™‡–,aa[ïêíåà /H$èìì¶ü(ÈÜEaXF³M`RöPð4ØìÎ/é)£ÉVv¢¼Môô—±ãEY”[%̤P£ùƒz¿V¨öÜß·(w^:Z»LÓiŸSJ–Ю ÆTÕ ºéÆÇÇÃ#E ¿Ψ<<$È1Î_È‚0ELGßÖÇ—HhcÓM7M4È$A`µ‚p2SöjŸÏç[ZZŠenݺ5ÆgäŸyæ™QË\¯RÖ®}"ßÙÙ9®:N”xá5UØù|ÞÌåòí×_Ÿ¯ûýïó«÷îÍ/õ«óÑh4ßÛÛ›·m;ošf>:ÅÇÆÏ—¾ô¥qÛB­1–mæóã·Ï_ýêWù/}éKù|^Ý£É|>o¾dæ‹òù\.Ÿ·m»p£vHçóy'ŸÏ÷^“¡3ŸÏG‡.¶óvu/´0!¬¼º‡Ì ì;Z1[˜ûéºLÈFÒù°!Ò½ +¯Œ¾;?îF*šæÍ¼™'OÞÉ;ùt>gÐ’ù¤Øö,¤´˜ÍLWß6—Ïåãèá%óɼ“wª}Y„YŽôm‡g®<·„ÙômG¿.ƒ{„ét>ï8ù|oïÄë›N§ó¦iæ}å+ùöë¯/ŽÅ˜¦™·m;ßÙÙ™·,+ßÙÙ™ÇãyÛ¶ó–eå“Éd>ŸÏçûûû‹ïõç™$—S¯þþ|¾³3¼ñ¸zuwO¬¬J0Mµí Ÿò„I§+¿Wô½¥™+mÄLŽÛ6äí|oo>ÿîŸÎ—N“Ï«‹kYê†+ùR’Éd>织¹qå7aeär¹|<®~gÄãñ|.—«v•¦éèÛVœC¥¯¯ŽŽŽâ àöÛo/[68qýpe´¶¶ÒÜÜ\\v饗²k×.ººº¨¯¯/º’577ÓÜÜL×ïîÝ»GÜf```Ö&×ÉQÏãÇŸú—íÞÍ/ÆÍf‹ùP ÃÀql†zÆ 3GWWÛ¶m«v5&Íh¶©Ïs"ö¹mÛ6zzz€B(§— ¢ïƒ¦¦áFz²ƒò0™Hl©Áh— ÐBNL˜•ب¯p<þEtuu±ÿþjWÒL‡}îß¿Ÿ®®®!¹Ð&”A'ºÑ¡ö\B;ö·ý¥I“#Gž<N1ŒÑ<æ!B‚)R$ ¾K’iöÑ××Çoû[^yå•jWeJÎe:ú¶¹Þ‰Í¸‹' (zdNÖ3ÓÇ—¼,GÒ·­¼o+3‰îÛîÞ½»ÚU™4ÓÕ·½ñ¡‡†ôým[yT’b!›ÍÒÐÐ@KKK1wm[[™L†ÎÎNÚÛÛÙ²e ŽãÐÛÛKoo/¹\ÇqH§Ó¸—‹t:M</~N¥R¸®KKK mmm´´´säζ­^:l•¾ɤz'jRiY•Ðۆ̚ D£•Ý+z[íõ$}ÛÊÆm†¬Ëd`^fõÐ:;Ãøn%_Šëº8ŽC"‘@˜83ù ª6===ÓÒ·­(ä—Ž‹WÚylmmwRúÖÖÖ²Ø{Ü~ûílذžžž!±÷êëëÇ<Æž={èêêÓ/àðák0Œ¦ü¢ÄT‡¢‰Çã剣KZºÎÉú« SÂ\ùÑ9šm¶ÏmÛ¶±uëV¼æf`ï7?Dö÷àý‡æñÐã4S!¤”Ò[øo£(q%‰ /&Ìâ¨p…MãØGwøæ‚ 2ö©•ÖÖÖ²}'$NèÜE%ÉnÜ?óŸÀüa®£qØ·Yˆ÷çþ‚Â_†  „ŸláOr§Ì>úúúèéé)†õ˜ÍLWßöþ—îç}Mï›PbݱI‘"N£h["ØØÄ‰“!ƒ‡G’$1bE›eo9rÅÏ..66fáO˜;Hß¶²¾mé@“ ̺o»gÏžjWeÒLWßöžÇcí 'Àš5€ ßjP,²Ù,©TŠîîn<ÏÃu] Ã(NhX\sÍ5D‡ odYé’øP¦i’J¥‚×ué.Idâº.±XŒ\.7cù~…éEú¶•Û666–]£ƒîyd³ðG<øÓCój1%™>D´äÖ³uëÖê *íííSOV{·´¶¶ÒÞÞ>¬wK%ÉV®\ɦM›†,WáöÆ›yrHSxô±iÓ¦1=³fƒm(Î*¥û¼à‚ hooç”à¸ï÷« ÉÜŒ %FŸ&*1G¬@ üz¨Yó:ù‘ΆjPX'/² ïm˜@žlaŠÐZÛxæk766²iÓ¦97‹tªìsùòåöö(>™ 8m`ä)Ïo¤“$eÁ³Á¸ "wBü]wmÎ%´·qbþJs«8…$Im´ÍÀÕ¦ ý#m¬Ùl³©ìÛ®¼`å„…Š(Ñ¢gIš4"XX˜˜xxÅmô:›6Ú01‹Ÿõó K–Z%vÚØ$H`aEM“)Ég4Ë‘¾íèè¾­ Ì4Ò·»oë8N8¿§[c¸y¨®ë’J¥ˆF£Å¼'Ù’h ¦iŽ˜e<öoš&±XlHÔÛV“ ÛÚÚÊ„aö"}ÛÑÝ’÷†gžÙGKKK1×B*•* ¶mã8Ùlß÷‹‚ËTbÛ6#^êz´µµ‘ÍfI$Å0a‚PMfªo{,K0¶Áé/>t¥?ü/Ã0°m[DIÙl–lVO”Š•k¯½–-[¶”Jkk+®ë²aÃÙ¼yó¨elÙ²….½ôRºººŠ/ôHÇ7³¯¯Ë.»lB'vë­kÈç_]íë+³‚Ñl˜Rû ‚ ö\ ; ¯áÚd ÷%T•™²Ï‘Ü£}_½lR.ø@Ä^-Ô9ßcÁ‚‡Qs*ÔOY×u¹óÎËH$Àß |‚× D Ð9uÿÍ+¼‚’uãÀ)è¦K(‚ þ¯ëJÿÑõÑ¿Æ%ÿuØ2½]ª¤,wP"¼EÌdß¶–±°è¥·˜§%I’Úh£²d‹"‹x” 3ÁLömAÓiŸ6j2ïÃ?þãGH§ÓÅœ(®ë… 8Ó=•JU49x:ˆF£Åäö†aàºnq€3›Í‹ÅŠ!Ža&˜É¾í+Ù‹0Ž@ï²B¢£LF%>‚!Þ) Æ’|ß1Š0><Ï#Wíù7Û©(äWOO[¶láæ›oâÊ¥cyÖ××óÙÏ~–›o¾yÄrúúúèëëãꫯ.[¾aÃ6mÚĦM›Ø¸q#ëׯgëÖ­lÚ´iÂIž{n'TíË+³ƒ±l˜´}zx\²¾ªçé–Í[ª5ÈZcpô0ö #'ðËf¡?Øðû;ÄW/x‚/¯X‡iCÔ†löAŽ;î»ÜtS{öâ(#ƒN…e…\InÆ­÷ ó'eP!½’—UR?]G¿PLᘙÂg»p¬Òt~a‰è0g˜®¾­‡7jN£ZÇÆ¦“NLÌ¢ââ'NM88EA˜fªíaüL·}º.œuÖ\7À¶m,Ë*†ù*8´m›H$B<¯8Ü–Çô„!6 ƒx<ŽeYd³YšššŠ³ðS©TYÂ{A˜NfrÜÀ¸ü›| Io"ýý# *#å7$¬ì8üM“§"Aå¶Ûn£µµuÔ¸x6l “ÉÐÓÓ3âvÚøF¢½½ÖÖVúúúhllœ”Ëu_ß|®½ví ]FA˜ÝŒe›0yû 8Ò[?;]˜«¥L8º™ û‰¦¦B_¶ E¾ûýóWwþ-O\R…SH$<öîõÙ³Ç$—Ëáû>AðÞ÷þ„sÎ9‡öö([¶ü{ö<Å[Z^dÞ’< /Ï#ýu8ᘧ¨h-=vµ/aáŸ-$ƒ¤Q8¦ xཬ](±ÂA %>J ÉÀ>{5‰‚ÕÆkÁÌ@ÖT I¿ÿ0$C¢ ¼;!}2$¾æ0·‚ÿtþ ÷cCâuà`ž ¼Éÿkø›!õ(?žƒø>vBö¯À\ ö?{ XëÁ¿Wi2™Œòð1î‚Ì êZZfþ£`þåðßÁàðÁA ®»ç©ÿ¦©¶1 õÒï³YU¾Þ7Ô>–¥¶õ»E¯×ur]Ða‰õ,Ï PûY¤Ra¥å‚Zæ8j?½}6&‡5 ßˉ'.s™q¦³o;›…N‡1âĉ%K ™C Âd¨fÛ)ÂèL·}š&<÷Ü‹â‰mÛ˜¦9d¶aôööŽ+Ü×tÿ’Õ!Àâñxq~SSÓ´äx„á˜ÉqÛÅ_¼ü¯qâ‚1vïS?@F/Ò9‰F²…£Â40á¤ôííí ”-klld×®]“ªÐTufwîlžš’‹$‚b2öéáñ—gíÁó¼±;­z¤0•R#yɤ•Ó´µ©»q&"›ðŒ…Ù=¦%%L¶ý,Íw‹)+zSÂ^zè÷üúן浯×Íây¾ï“N§‹qlµ}Ÿzê?²ví£X–…eYxžÇ©ÿÕÍŸo»€/žôcþî“ͬ9ð$?~ï)Ô¯¼ž¦]M¸ØÔy‰à¶ÝûûÜôñãÙpvžï‡}øßëGà,W"„á‚õE0N‡ýú!˜Ä×AðDàl0¯ãÐù·jŸàt¿Œ_ïn…–«ÁÞöt¿‚{À-½Ù îÓÀ*ˆ¾x˜×@ð(߇è"0‚qìOB&æsÀ%1! Ùï@úí¼ÀxRk v+Xƒž|J„1 %Lh1ÂG¡ZL³\°0 UŽï«ï1W½‚@}§ºüR1DÖåzžz̦ӡà¢ëbšªž§“½ªÿZÈÑeèè–¥ŽŸN—‹>?ýé œsNµ­ffZˆþŒÂ_œ8>>-´-ÄþóðH“.ËÓ¢C„ ÎÝ"S…ا Ô.ãµO5ïFõmn.zŒ–¼zÄš\+€;€(¿„Çsß&³N?‹_ÛAîÀé·>ìú§]lÝöoÞþf8âÛ!Ò ¹_©c²ø%êÙ°¸øàÙ v€rM)„sôD«ÿ€¤£–qÄ aɺë c)#—SÀ PÀJtãá¶) -<Ø£;›ULjFË·Óh/Ã~½i†âÌHØv(Ö˜&”Þ"Ñ(¬_ÿ4…ðËÂQ@’¡7’‰I?ýÅÏ>>"XX´ÐB@Pa\Ü¢(HXAaf 'vL½GÇL *ƒÃ{Y–…ã8´´´`Y¹\®˜TîB=Ø,³-¨Ìc% ?iàu†Ç3kÞ¢~4æ 1%b±†aËI¸X¡6¨HP¹ôÒKéèèàöÛoçÒK/v›L&C]]­­­Õ>'<úû{‹³eA¨zñÀ“kÊRŒÊX"‰iªmZZʧVOY$1½pÔ^9ŒzøÓ!ê¡„(|3ñMÇÀuS¬yþy¢ Ò10@Jsi#LO²â’Kð︣L@õ|¯Ø6_ó½kÔ²÷¯.þàM=—bc4ŠÁ0Ά°)s%ñõq.ùÙá0 ŸÞÆ·^ù_û‡¯ÑpI´/nç¦ÈMøK|^xí sÇ1¼ÿÁ÷“Meyê§Oqì¿Ë™ŸÉ¥G.å»ç~€†# ,~ÃbÞ¹äôlîáÇ÷ÿ˜µ­%÷7ƒý¹~ž¼æI^÷©×qçü;ÉØþù?ÿ™ÿüþòá[?Ìóô<']r§z§ªi’HES|h݇X³f ,øÁõ.RHð”p+$¶FCoŽ!¸„¼už™ª,óÅ,¼tŽ¿°ÎPÛ:>8ú‹Šzá% Ûz`G åê|2¡H¤sÄèºX…óœÊ&¦Õe‚O!ŸMýêújßêÂX¸¨{f†&š˜¤I#†] –(ü98´Ñ¨phiÊœFÊ%‚ =x47ï‡9&º'“IÇ!“ÉÐÔÔPTt¢nÇqf­K³~üî¹çžã¥—^ªv5f¯üìlê€Ó¶_¼%Œ<ˆ––z{{«]]A(£"A¥±±‘ 6°qãF6lØ@{{{ÑCE'¬ß²e ›7o®öùjæeCCSµ«!B&|v¯Áz½rÕ,›ÍáTéñvgrN€xªs(Qv~NZ _­ƒ?x dY½ãûœþ¥/a˜&[.TãøuuX(1ÅGÏÇW®ºŠÎ?ýSåêPˆ75Ü¥ÒÙƒCfÖ¥æyóxOê=¼éò7q͆kè^ØÍü€þÜÉ<²ä#ääyçò³ù©›ù“ÿ„¯~ñ«÷Žãõ±×sï×îÅÄ䮵wqåá+ù—ÿ‚ó9ÕQïíî%L“‹åxð£rò;OfÇÒZvˆøcqÞô÷oÂqþké±ÔZJ6›%h 0ž6¸÷=÷²êŠU…wÿõ»‰F£|qßñîò‚€ H›i2f\Èf³D£Q|ß'ûÃ,Á·,ËÂ÷}þóÄÿä×ükNZܬæOþdïxÇ#D}“…·,dÇñ;Xzp)»/ÜÍ#ÛaÉ%œ¸ýD¾¹õ›\vçe\¿,5ÃçïvÒðÓþoöÿòæõoæUW¾Š{ï½—¶›Ú¸óÌ;iI¶`¦aâz.13Æ]»‹[·ßÊÓO³!¿—Ïx™þ‡ú9ñÀ‰,þŸÅô¬ïaot/Žãð¼áÙ7Ðø@#ÛOÞÎþc÷³nï:V%VaX†zVfàÎ ïd`àuxߨcÛïeû'XõåUìøÜ~uÒ¯XqÖ x±Úw}íâ JÞå3üÐÖ´â(1 yyöªpuöÙjYê)ài°—Aæ<°÷‚±üÛ€mÀ•à? öbpnÿ9  yeƒÛÉÓ”¶R¬K@¹€7XXÅDöÝ(תRï–8êÑD 4½ê’$‹Þ-qâ’›Eá(ÃBy§lß¾}N†²,‹t:]̧ÒÖÖ†ïûôöö’ÉdH¥Rø¾¯úz/rÝ/5 ¯ø.“ɽ½ëºêŸêýõ¾¦iª~p!)¸ïûÅõ¥Ç‹F£$ ÃÀ/ÄÕïu9zy2™Äu]\_¶€išÅ}|ß/~—ž§&féuú˜ú}éò °m»¬ -6éãémõ{˲ˆÇãd³Y\×-ž'¨ß(©Tª8–á•$Ôžø›6mâýïµo“YÅ1çmãÖrìúשDôöð±Ö;Ç•DfŠŠs¨lÚ´‰úúz2™ ×_}ÙºÆÆFn¼ñÆšðNÕ€¾úÕ¢^ B­°Ÿ×»{5 ün[g?ö<º«4sòxг²YÕ{ž.¥[r©s“ûwÂÞ•pðˆþÜÓáîãîæ'ýiþ"—ã› â_y%Ê¢÷{ßÃØ²…¦ï|‡ÜâÅ€éûdš›açN²ßøÎ~¤„•áBø…¶¡Œïï’ÇÁÿ8ÈG—}”|èüË-ÑýÊ+,>áy^¹àQrÿSâ~+Ïñ\ùŽ+8—s8Ó8þäãÕ3b)åbÞ^þ zmðZlÛÆ²,R©Tñ_.—+†œb_yžG*•"â8©Tª&-™Lä†AßC}\ôøEÜzëj`ÿÖý,zùâ¢-,‰,aÑêEA@ÃÎò¯Ë‡3£ÿžýwÞ{7@1_ kÁ|«ÉÇS/†‰øPêC˜ Lþ;ñßA@ww717F<çäwžL4žÒfCfÖ+Ü,ÖªóÉ&²d³Y Ãàî“ïæ¦î›Š?^ï[x/ƒá«°¦eb_ls¿Y¸_‡ž=ÿÄöïÇËx˜oP?’¿öñ¯ýöÞ•ßU‰0­­­èºîߟt:M&“¡½½t:Mgg'‰D¢$—G>Ÿ§££ƒ¿þë¿æ„Nhôë1©8”ùÏšGÓ|ÖYž 2oÞ mÔ»%¢Š6F””þúë¯çú믧+ôzΜ9´´´4ú:|fÌØÊÙgÏntQ†&×É´ ?Md°V˜ÒìxlùßÂÒ§ž*fKvÏ3e„É塲7'žÈ2Þ3’‚ã:Õ¦ OvT@àÉtmÁDąñý¬ ½[ûêÀ³t7/bKëYÜpï½ägÎä;xUXdûv’ÿïÿ¡?ötvÒ?kVñ`¶Mò7¿¡õýïG[»ý£E{úéQ?ª`§ì¨]Gq'wBþfËé¼aÎ <ó¿Éß||DÇŽ`'Î4MÚÛÛ‰F£5‡#0 £¤áÇýŽ«Z®Ž¯£Ã‡à‚#ŸƒÌÉ:tˆ‹ÛÞHô‹‘a¤•0S©ÃLÂìĶ··“Ëå0 ƒh4Zu» ÁŽx%Ô1T×¶mÖ¯¿‹c—­bÿÎH&¿^²ý»Þõ®’ö¤PŠTÄ=i­O\1mÐmÐMHÝ™K¡û‹ §ñ¦è&!¯ƒö8dz?µ»}dƒ;X ü3ÐYhŠÞ¹ŽÂù³3ë ³¬G!¹ bQÐ?Æ È½¬>È ñ<¤ÞÎ"0ß ¹Û!¾¬ Ð~:tþ[¡ŠVn5EPÃûY‹ø¡¶ÑÑ11K¼X‚ž)2$H”ä]‰Eh8)RD‰âäæÈUÌ7$BíD"ðïlE×/htQêN°}¬iZI»Sµ U»-Y!)^´BÜŸœCi›0Øv®$f(ïŽÖÖV²ÙlI{¹R»[×uÒétÕvåPmõjbYù±’ɤ_Ó4‰ÇãƒÚñÁö³¦iD£Qß›EÝŸh4Šã8þßå÷R=‡‹/¾˜G}t¤ñ°åO¹×Ûñ6ò'<¼ZuÛèXÇ‹¡ŒHPQ„Å¥–<ò «W‡¸£äàõŒ;ñ1ƒñÐÃÊdD.Ÿ®©î¯Š'æû=Ùò«ÓXöº]˜ÂóH‰DFç•R‰ÎÎbè°|¾(¨¨eÎyn?”Oz°mo»¡D˜$Þr o4JåÆYQ9 r…}LŠïZ”¢ˆªUX¥Y­ÂvêØ^è£D…r©Ü Á28¦‰—ÿ@mßd ûÄ ûr&”ØL¤°Ÿ8¦*4pÌ,ÅXOZáïŽÂqº eV!a ‹ß ?Wø[ lk®WݳtáÕ²|á¼ê<:Å4"ۇɜ-øØ?‚½ï†éxpÏþïÛŸáâ}ÿæsfòm]ÇÀ{4Y€3Ðnº©²‘Žºßÿ~œ3è8óLœ3Ï$I!‘òNÓ4Ïke41“uØÑºƒY;Ÿgú²'Ñ´³êwo ı&û¬~B4¸oÞ}ܤ­fËQ[øˆ[Óìþj³÷†"‰‹Å*v®‡*ûPç)ïÜêºÎ‰'®å8…ÿXb{†ŪC}"5 éPüÎFÁì‡Üù _|²¸¿ pfåc{ÁÌã‹TÈïiRÚô3~Öií}zã3À±m¦Oçåß-%’ãû`jЪƒýWßú— ñH¾ ‰O}DNãïÀ¹ìVˆ>Ú¿B.Ñù…rY…ëTßö8Å:j¸0c…\=Q'Šóeý)}‰Žu¤Eûv²MÙb¾ìNí í­Xÿªz‘ çSõ´ªÇóxÆ”÷Lüv³V¶Ê9¤~·×[ž³&ØN¬ Öuåe³Ç×çHáÕíJ‹–G/þ~ús§Cx»{“š)ll,,LLbx3¦U  _TÉS ƒ“#‡ŽŽ†F’¤?"GŽÉ!$xÍËýûæsŸûx£‹ FÒÖ+j2Q­“ê=H^.°Ôr¾jmýáúÙlV& x‹Yv6Ì:–-¬¸mÐkJÂĨ•°³gÏžp»x;SjtªQ‡F˜Ô@r°¦¾iªÌåÇFcS:¢8àmþ«„»Á>HU¸/NáüªM ÎSðºð¶ éùHϸ¿Ó‡+)R~~ HáŸYÖspH •V_<11}ï*ð&?¤H'N+­~Þ :Èâ …šxb ‡-}}Lúç“•j'‚Äfâ ]²ƒ¿{Ìú!pnÕíÅž…02åË‚;v`š«&ô¼%z©Cq†Zµvlù÷@ÍL ³×D´P¾<ÅÎ¥ºøÂ,I¿£«‚{7òz2xÅòÁÜàß6ÞàxœbGRu„Å«pÜØBžmÝ×ájßä‘«¯fÙxܲª¯3ͲÄfíÅ_{{‡Þϲ¼Á\Ûöĉàq’À&NÃ8ÖuÏËŠ"éÿèpS‚-Êíá_âÅ㪼2:Мð›+ Bê:d’¥â¡—~S¢Qo}¥Ûà N-–†k—£’vœ ]ngú0Ç*Áûvv"Œ«àÔáÀ[Þê-ûÅ '€m3oÚ4Þ¸t)otøÐ‡ »»¶ƒ–½¿j‚u ï±GÁR‰Òm3ïïಎÏ“%•òl³Ó{àÊcb×®]X[„±è]¾•C¢âZW¾_ÐÔ´ Û>—^x[£‹:.èºîÇÀjgßì}ì/üô<)0’xm¯(¥ßVôŸß, $‘UITÓé´üsÿ×Þt-ç¶·c­­­~(ŒD«$LÓ$“ÉøÉiþæ\ôÆ·³¥äVÅW1Ú5Mñ:::¼D·–…a&±–€Ï“+Ä\Ïå<µ!‹Å¸àïà+7ÞH8ïÙ-äV,!z´w‚q„×LsâÞ÷#/è%½yâÚÏðë@ç[…ÏÄÜ¢ƒ¨†·§¢o3é| ›ŽEíDvFˆn‹Â ø*6??3Câ[16ôü¯Í•G¤¹xm=35¼ºÏ€|á9˜ïsë¯@¿´8äÌØ±#^½›¦´ÎÌRW X'+Kå9¤¶QžzàX­…åxõa’¢€âÖçñ&/??'J©óxò¾'™ùÜÌZÁÔÁÁ¡ƒßë$N¼jŽ 4iìÂ?³JGÊÂ"FŒ8qÿ¸&&t þÙØ¤IW=† LUÒiˆÅDL„°s´µœyLŸ6Ç7ä¶#õÆ„‰`Ê *Ž{÷ÞÔAP){•Çë¨DŠ€âì1Õé v„ 8ªTéøõF‰#ýéÐJƒ±jÆ› ƒ`ðìõ‰¢–0eª©î‡V(kŒÒ0a¨Q¶ñÉÅýl9{§]tQNâŒ.dÐP¨Ùè†áy¨@QX1)j|þ_ꞇÈP¡iÅcd³ÕáiZ©‡Oµø²Õ––ìÍ3Vg°¸,›eñ©mËËϨ®Ö+¢QOL’öոІù3h?N:fÏæÖ7½‰ßÏ™ãmHx÷¼V[ë¬r¥)ŽïE(Ì6 &ªÅ¼gÜÝ]z]‡ÖVï*;®mÛœK$÷#X5_zí5Þµm¹3tÚ úíüi‹™^SN§‘R9µ¨[×úfHÞÛ‰þßÐ|§·LCG#Éi"ìߟ§å“_“âvN×s|êýi"_€/Ç2üã%)\4–crÓ4“M‘Ïaàg)ŽŽž¦ñ–Y:‘#8‹þÁp¸ »±9›8¯)Þa˜¼ |ƒ(ïÂá$4¢zaÒ¬‹ WH£äGî LBP5®‘s:h…l¹•Å&°©~äÞZȽC1ª§Q˜$e-‚œQŒÀ©g¯ÜÀ%'WŸ)*qpˆ#I2ûÈBGGC#EÊ÷H©½ð¯I’´Ó^’/ÈÀ 7àªkaÑ^˜HÔO?6¶x¬‡ù—;Y²D&rBØÙë¼ÂÜ޿ɮ†ÓN«¸M&“!—Ë‘N7‹S&ž)'¨D£6–õüÈvŠQœå¥:¬QJ]ïÁ뉩w£°Ÿ×Cù ð(Þ(”ÚGåHP9"íËS+Ï õñŒh¥(cOG)öȪwŒ$é³:žàT1^2õÖó3˜eûŽ•µ…í2ª,S±Å%éõ˜P÷ ]gÓ²ïÓãïlÞàüD ØÅbC{¶K;¾ž30t6æK—e2^ˆ3å%ã8Ðß?øÚƒ±Kƒ¡ÈÀ[§< À{&AñGåªQ‚H%ÁH­SÛ™févJ`±mï¸ííµ?aHòä™=ðIo”äßü ×­_Ïuɤ÷еäBrk6mâÒ#Ž@×u,Ëâk',æ‡oü$7ÞòÞùÖ8†apéþñ—+tþþ¶iBçíÏü€§íÀѾ¼ñËÜyÞ¿1sú­EŒOM‹s»ÈйÐâ­ñv4òÌÛÿ6®;êržÚ7›'_ûOÍuÙèvóšÛÏÜiI~:m.w¼=Êm_ÒùøG½°‰àð%"<ÿ§ßqÃò#™M„7‘çbLÏa\‡ÜvÈv@¬¿èP®º4ùg?|ÿá‡9xÎ9~×Dÿ ¤ßÿTL朠î;ï<.9p Ñf0)HÀÆ&G“ ?¬W”(9r%BÇx ¡ÑÍÐÞ¢I’äÉÓN;66"¤HÑI§x®SÇH¨QA9»±9ºÊã¤Ï~–­U¶s‡d2)6-„’)'¨¬^=›… WyS¬bxîíCÙž ïdàõ>TD —$M1G€êÐ*¯‹EÏ‹~0~ ü˜¢›½:Ž Q“Às¯¯6€¯¶IÁíîDàØµ&æTMÕqS…e¹Àz†8ÖHÆBŒ²ßU°VЉ»)Ü •[•3CiBÎH¡¬JüQ 5kéŒÅã'R(_ÅÜ1o$šäP!Ý„æì„…svup×ÉŒy¼ãQu"s¹‰mê Q¦òÀw‡ðn Ý0<ÏšjD"EOŸj 7®ë¥å ϲ<ÑÇq{75±à%ƒô=Þï¶msÌw²#cn$â½ÿãCD¡Ò?tàUC£–Y5+_sy¬ºµ¸.“ñÞóÂÀñ 0z–å­‹D‹˜™Ì`Ao8餓ض­‹AŲ¼²L²÷Ú4MLÓ7ýròc'óF’h_¶QÌQT*E>Ÿ'cš¦ÿSÝsÃ0ªz)Ï•r:^`Éd«ªK…«­<Ç`R©¶c“4J¿ïº®ÓÝÝ®ë躎¦i´¶¶’N§ùÉããxÍ‘§f%Z–EGGš¦ÑÝÝí'(=òøÊiû8û}tüú_1ÚÚ°mÛ/–û§"³è󟧣 Ü÷».úzyqÙìwý%ÿ…çm“ÉdhZ²„ÙÇÇž3Ϥ££]×1 ƒ_Íú ‘®æÎö8òÓQ>TðÊŒF£ÒxáØ±b¯Éw¬ š¦1OÓ˜ÿµ7pÂþ·3{×;ع3Î÷.ìãˆK`Ó×7ñù§s|3ÝÍ9MKùå«°çéH´ó£~Ì?ÿs Ϲ36l`Ϭ=\»=ÅÁ%ÙÝ?};R¬ÇâÁí§0³g&ûÞóRñ«Ø÷ÇßYsƒç–5ɵçxýí·£õõq]*…¦ihš†mÛ|nˆÂ©øå С(xtSôjQ>ùÁï‹Ô·ñjó …*£ð‡â(Uù8X¥q1%B©Mz¡Ì*tÙXÐðć҄Ôåýxåá¢Ê ’a’dúK"ðw0™š’g36AEÅ­–+xŸT@nà/¼“—Ûê› y²sÌÁY\ø?ñòÏwÿÁ'jÀS ¼NLÓ0žÄ3ù¡›O•g4ÁlÄáÈ_Ì"öUèü^„­[™{ýõž£˜$øI¯”"gX Ãóž™;8¶ìà!¨³³è!^o;•ò–Åã•ÃÊ©mÊE˜Tʳl¶(Âd2Þï…ÐH¤Ó¥ÂG&SÌÉìX–çe¥ëÞ>uóæÅŠÛµ·{ÇSžYAqÓ²¼ü2!%Ô×豞n¥jŽ(˲|O“|>_"¢(º«ä<2 ƒ|>?ìŒ?%Š©}œJ¹¹ª`FU¦¼œJø1 ƒ£þõ_Y|ð \Ñ>hûÎÎN,Ëò…ðÄ™ŸüÁ§¶“,«× à ‰”¼‹–eaÛ6?ï͹‡øAA@jnn&‰D|‘J‰,©TŠU·ÞÊ=o]ÄÎ?m [6ÀÈçÉçóär9"‘ˆ>í_¿w¿Š½Ÿ£¾û]‰=†Þë•ù´Í§ñ%#ê{ÙöUhk4òù<¿LoåÉk¢œðýï2½×˜=»ólLLî¾ýn¶ÌßBÿ¥.ŸØû î^ȳ—?Ëoûþáß>Êô}{YÙ}%¶m“q2Ìß<Ÿßîz/oØýŒ^ƒ+^½‚kg_K*ŸâÖ§náŸoZÁüïÿ–Çz{ýg¥i'ìÜÉ®íÛGùö>¤Hù¢EštI®,YßS¥‘˜˜¾‡L¼ðOåXÉ“'VèÐØØ$I6¼¼‚0VfÎÜ-°‚ržwáˆcCCn—ÏçÅÓ]-SNP¹à‚ûp fƒ½ívºx„Ô)´~—ôCiš?ÙLô¥(íûÛÑ?«ãœõ2ÑX‘§‰õ“ùihXX˜s ÓgËP ¡‡÷PyWl¼é»à 9¼‘§,Åé½A‚}È|ÙÏZ“O«c½V‚#cEÅz±¨îe2Ty³Â~J€QáÔ˜T¯ïn™Hõãµ?¦¶:ljðx÷vÎüÙððZc,/ò ÷“5Щk ŠSñxMÓxói§±þŒcXúÇÁBƒž¢ÑhÉ1þÚqø¿#9âˆ/€ûÝG*’* µž—̦;îàÓÇÃuÇÇ?TµoôýÅÆí—Îü’ÿûî_¯ç¶«ˆßõV®\‚£;äbÞûa7Ù4¯lf KøÂì/ðU¾ŠnêlýÃØ3ç}ì¾ê[¤8ÇpüUÇï˜Æ¦¦¿åÒ=íà æK‰Ñ²Ž‡Qø7h?»XUèz1Ê©ú=—ó~W)ç¢ÑbTV5F5y2™‘ÍwzËèèD‰’'ï‹B*©½‰‰UèP©í,Œ®ÃÑGÿM»¢.Çk„ña×A˜{B?{W=,ªj[ã.^Æ‘)'¨är&ïÊwÁ«ÍGáòÄ’÷Çá=ÍðÖ§q¯×áÖi' XŸj'wj†HÛ dÎö’}¨F¤ŽN†Œß(¶ ÿ"Dpp00ÐF’,¡Üó¡Õbd×:¡Ü,û9R‚}Õñž˜l0¾­‘à±”W*¾|û4ö®XÑ袌ž©43"8Ð<˜J×Ò ö„³ÏœE4 ™LnB¯ªŠÉâ9DªÔ[5UwÁ<=#¡Z;Ã(/x\å¥S)ìÖPž^¦Y+Êïip†{aÝÞð;–/?ŸE•œùª=% Ãø)R)oYw·7b{TH4Óô¶S×aÛžøcšÅŸê~Ù¶ç1E»S£y¶í Hê>årÅmTn&‰Ÿ÷“½×|Ø‚‡ÊH0MsÄ‚Šiš#òjQeéyž;êÛ#o4MCûfŠ?o+Nˆ©æ­£ë:Éd’|>ÏŒ­[YøÜsU[~ Ó49‹ñ¾2QG×õªÏëªóÎãÓ¹Y¶¬æ˜áY¶ŒÛ‡ŸsŽ/¾˜iïœ::qâD‰âà#G’$û£â–9×ðþ“÷#G„t&ÖçÜEõÕ'3VÍÞ*JY§>çê³mšÅê,/F¤4Mxä‘8x°]Ÿïkèù|QGÏå¼ã:NQ3Ïå¼cÔ∜ ø†fÉÒN;½ô’"…†FI,L, ^|ñ¸ºy¨„ÏX&'ËwÓ©ËYø¾E€g[åµM{{;𦉍"„–)'¨=ûUî9ñþ¸õOy­ÎÓà\àPîÎC·, ÃÑ1"Iøj†HºÐ¨Ta?’Iò¯üö±//¸{hh$H``ønÒωB£Z/üÓÐpp°±Kg)ÉÔá0ãÀ¡caÏ6555º(‚ T`Ó4‹¾ ßü8åöÛ9cݺ /ƒòLqð•ÖÂ2b²dÉ1N S›LRL.VGFã¡6Â}výx!ŸíZÀ1Œ0ÔŽ®+lÛFK§‹Ó‘–e› –é4ùB®‰T^¥Âhœã88ŽƒðrÙö‰OðÚ™gç_¨G iìhmÅuï9µ¶°ñb¶ýÓ?ñµ{îᢋ.b÷î:„œ"X€ÓR:x“Ïçý°Xþ`Q!ü” æg2žPE/%¢Yomi¡iåJO æ§²íâvj¤7ò«d*•òFqÕÈm…¬hð¸5Š£ íL&G,ÂüU[Ûˆ:é†a°7Ÿçõû÷è<Ç‘÷®ëD ŒlíA à ÒÑ^eŸ g‚ê|üškè‰Åør gN¼ qoÙ²è2;,¬ª9ù‚އAGÀxÜ3å šÉxq s¹<¶mã8Žï–ÉdÈç=,˲ˆD"ttX¾×T2Y|ßÕkœJ=\"‘â'@9+›ª“ ,¬‘M„`YðÌ3ôŽãeC„qeçq{{®gÖ§Šmª`+1—Ë¡iÚ P®‚&&¨ìܹ“/^\²¼¯¯¾¾>/^Ú&2€ÿyüqn8óLr…íÚwìàñ½{9sÆ ¦O§©©Ét2–…­ëìòIžu55ñƒ‡æ ¯{¿ûÝïX|ì±Ì>ûlNìë£çÇ?fï1ÇðÌ®]´Ýp'>ò<ð'ïÙþٳùØWpÿG°íÊìêü#;í¸ê¶M¼ù꫹÷ObéÒ¥ôö÷süôélÙ²… ðú^`CSØ6¿ñ VþË¿ðàóÏóì‚ôwv2«¥……»wÓ÷È#\öÑòÇþc=þð¦=ý4ÿ›NsÿÃóÑü€ôüù$2.½ê*žøêWy­­‰O:‰c=–C?ý)g]pþä'$“I:ÚÛýdåvG¦iú ÎŽCg6K"‘ í8hù<ßzí5}ç;¤R)¢/¼ÀwÞÉÁƒöžÕƒñlÛ@ì×Í›„JP!•òÚ¨ÞBÞò™Ï ž«rö¨Ü>P<¢Qf¶·sÞÌ™^Ù²¼ÿ*žŠ#ôØ*Gy)Á¥<—šŠ¯i^ûº½Ý;fP,ÉåòÉܵq#;æÍcÓ#ðüë_ÏÜÞ^¶ÌËÞcŽáÐË/³ëÔS™ÿàƒä^÷:Nüð‡™Ä´}4sàö}ûø³ë¯ç©9sxaÿ~¾õÚk|oÚ4Î|û~füæy>ùÖÿáÌÓfËïÏñø/¶µ±àùç¹à¬³ÈÏšÅüW_å‘OĘ5‹]y%'s©¦&Îijâê3Îà±sÎaæÌ™lÛ»—ýïygÏf祗²ìÔS¸}ß>®ºí6î[¹’wéKDŸž7~ýë<ô®XÁqÇǯ eÖ,Ï™÷ºëøþÞ½ÜùÎwâè:ÙÞ^oâg$âÏQyÓÛßÎMM^n€ÎNÎÿô§ù݇?Ìãïx{O>™¬i¢áÅCîêꢫ««Ñ¯Ø¸2^mÛ}³g³ßü#×ÛÆÎå°,«&J‚:‹wìàƒÏ<ã †Û†á ÂÿVíÞ^¯­™N—zŽhô÷.”ò\ïÁÁzu¼ J io/N“/÷<ÉdŠ1ŠÔ±óùb¬#ɲ*‡¼‹ÅŠÂ`º»‹ëU;]ÅF ¶õ”À'Q•å2ò“X¤R¾ð¤ë:7üèGðÉO–Þ7•«(™,]®òE"ÅPxÁOÁû®„Ë* ]åý•ÿ,xïÕµ«Äét±¿ÜFå{J¥Š¹™‚ärÅÜQSLP©GÝ øÊÌb±¢ˆâ=B‹T*O.—󅪯ê15m—V0P2™$ÒÜÜL4õû`Ñh”ÖÖV"‘Ǹà“ŽŽÇÁ0 r9ï½N§ Ö®½Ûþ:«Vmæÿñlû7<ùä±<òÈ›‰D ÖýI€Ê[¥™fIX/Ôñ´ÏO|…s^]m…Ó³`é…Ù0x?»·k¤MÞ€]ê1në³~¸Œ—8SV?¼nÐ6=Æ(£Â`î¸ã÷ãÿ¸»|ùr÷æ›o.Y×ÚÚê>øàƒ®ëºîÆÝåË—»Ï<óÌÇ»öÚkýß³Y×=þsÿÏíÝ\×Dê1½½®ÛßﺮëšjYg§ëš¦ë&“®ÛÝíº½½nww·kº¦ÛÛÛëöööº®ëºøùÏ]·»ÛM§Ó®ëºn¿ÛÝÝíºñøÐçK&½ M&½k,œ¿poÿÎNï¿úÝß½×;Fîîn÷Úw¿Ûíïïw#‘ˆÛÝÝíF£Q÷+ü ûëoÛD"n2™tu]w;;;]Ã0Üt:íÆãq·»»ÛÇãþï¦iºÉdÒ5MÓíììtu]w»»»Ý—?ùÉ’sö÷÷»O¯Z度é>{å•®‹¹›?õ)·¿pÝÝÝîÿ­[çZ©”{Çu×ùåèííu£Ñ¨ëº®‰DÜl6ëF£Q7™LºÑhÔM§Ón$qÓé´›L&ýkéííõˉDÜÎÎN7ºÝÝÝ®aþ5¨ëJ&“n:v³Ù¬ÇÝÎÎN×4M·;ð¬Ê¹ùæ›ý÷v23”mºîÈíóÁto¾ùf7âºî¼ï]ãþð‡¿pãC½ßUˆÇãn6›õŸµ¦i®iš®an6›ٱܸÛévŽhar¬#&3ãmŸê¾t»®{Ûés÷—ÜøÊÝîÀüù£²Óñ¤»»Ûu]¯ÎŠD"þ7>›Íº€ÿ-7MÓÿ.л~þB×0 ¿þ1 ÃF£.PòÝÖQ®ëºÉdÒíïïô=éííu; uhgg§ûÁ¯|ůÃÇ“~×uq]7êºîUïûW÷ˆk÷º'›Ýnoo¯kš¦_?V£×uÝdá85ßc×k·¤]¯^®V¿‰º®q]×(üÔ\×Õ çWëã®ëvº®›-,Ÿ?0àÎýÏÿt¯xå7^8§^øùßücÅwy22ÞmÛ·ñ‹îŸ}ÍuÍ¥®ÛýÁ¯¸¯,Xà¾çØc‡¶ÍxÜu+=Çtº´­d¤ï³®{mÜÑìÓ?‚7T×Gv…a ^¦ÚÆåtwª¯p͸/Ÿ{nåó¾)%¨öøHI§ï{ç¨tždÒû?R‚÷Á4ý~ƒ´m+£Ú¶ýn¿kz†áÝ:õXz{{ý6«®ë~;v¼Q}®áèííuÓé´ßWŠF£®a®iš®®ëî•W~É1ãU÷Ýï¾Ö}ó›á®Zu«‹9î'?ùrñn¯k¸†wãn¤ðO-—võÄ#mÛê÷å ·¹©…–ëFÓ®û¶¸×@êt½†OÒõ*ŠN×k¼D]¯A¤¿°¾œ^×5ᡈª#¦õ·ít]÷ÌïÞê.¼n£ûæ®®ŠÛ«±¿‘"ã=B5êѶp•+V°xñbúúúJ–wuu1gÎÚ É![ZZhii¡««kHµó•W^¡««ËßoNëОì€%0»60mÿþýpÔQlØ´ måJìL†ù™ û/æ3GÅSßxŠÌmVnÚÄŒ®.ô_dó©§rÑ /ÐZ“‘J¥¼YKC/^=CüÃ?ŒýðÃ\±gO<ñÛgÏæà)§ðÙDÂ÷ÄXs𠋜͛7³téRþ¿Y³ü¸¼à%Ï43ŽøêWɾôärÄb1æš&ÝjÖ_&íížWG!·ò0M]×éM§yþ±Çøí×¾ÆÉ—]ÆûÚÛÉf³Ø¶µt)úÅ3ýç?g©ë²á‰'˜ŸË‘ËåH&“üæ‰'¸tÏŽyñEšÿë¿øÎË/cÿljDhnn¦³³=Ÿ'’ÉgærDËfT¦ 3“…{§B.˜¦ ™ ÝjöŸ ÑP(Ÿò~¹rëVŽÉçimnæ{7ߌö¾÷•¸Øç[[ùÑ~Ä隤¦“•j¶ £·Ï­[·ò쫯rdvwLÛÄÅ×<‘Ô»›Édü$®‘H„X,æ'âÍf³d2‰± %e$èùeÛ6š¦•x–©²×Û¶í{Å©j¹¦iX…ÙÁjÆeµo¶móÊ+¯ðüóϳgÏžFߊqa¼ísÏž=tuu±å´Ó¸í8kÙ>ôãzÈ—çH¨3±XÌŸqŸËå°m›” _“Íú‰ Á{§\×%ŸÏÓÑÑá‡>xòôøèuå¬+Îò˯ê¬`âgµ¬³³Ówâ…zµ|”®ëþ6¦iŽ(ÂHЀž#íϾJËÓ·³ì­¡ë7×”\…= Å(T˜ ]‰$žGAq2gè(üîày YÓÔ„‹‘¤tèÝÛ·sí©§b67×åžN4ãݶmÚ°\ùG~wÚ rœˆóîwsµi=S¯Ü›A1Ô³i…d²Ôã¥âñbl¡Z „¾ª™|¾²×v¹'¢Ü{§F>ÐÒÂ1³fU>O¥ó—‡]«•Já‡jãFÑ{¥V§:Mß0èêêbëÖ­#/s©WÛöû›¿¾T'“):E9ŽC*•ñ½Q"‘HIý3ÞÔê¡­ëºÿF£…r¦µ™3™·OòÜs»ùâoaöì}üò—oçõ¯¦©s«ñ3~ªÿ'Q¢äÉ“"E†ŒïÅÒMÑ;ÌÁ!EŠ ,,œª9g„ÚØ¹s'7nä•W^itQÆ…z´m·mÛË¡ ~ éœÒ N²î+å}W£iϵ9‚—gE/üÞ˜àô9XÛ,x´35œ—¸ œ÷98Ë´{5¶®vÈ[‡ÛÀ>dc¿Þ†™Àï€3Ta€ó?âÅ¥=ØRX¶§°ì¤ÂOÅÒ‘Ý?eOzÁWXGB#5’¾¾>{ì1öíÛ×袌 õ·]±bù¦&>=cöícÿ‘ƒ‡¤U__Æ‹žžžº´m'\Piii`Μ9ƒ.°<öÞœ9s*V°A^}õU_PY›ÙÉ’kšàëõTU€š¦‘Ïç}cßðüó¤~ýkòù<š¦a\uà ÂduåG,'ã8ÿ“ËÇ}OQÕüTƒCŽãFKQR©ñxÛ¶Éår~‚BÂJ úh]ÄMŽƒ¾r¥7}Åd¯¸Â?–mÛìÕ4.tRƒM[Ã0…U˜[~*…mîoÛH°ÐqXøÀ8…ͱXŒd2Y(Ãô-ƒb{àÌÂlˆ2ø¨XÓ*¶w°ãaš¥±º ” ÎnÛ†Á\Çáº|, £pþîînÇa‘eM™Fm5Û„ÑÛçÖ­[yå•W8ðìBfž–Gׯ¬¹<ŽãÐ^î,Ëòï¹zFª“ªDÛ¶Éçóþ€looïˆÃ¹©d *D\¹ PÛd2»àà¾J(ªlU‰j%¨ïH$ñí8¶.QCmÛö…ÏL&C$ñÅUŽx<î'ÔyMÓ$‘Høë¢Ñ(ù|žh4Š®ëd2LÓôµ‰Ñh˲0M³$l^1lDδ²…< ñx¼¤ JS×­~QçÇã~™T\ñòcªò© ª ꚂטL&Éår\|ñÅüã?þ#ög6ΖÒÆÛ>• b/ZÄ2,NùÁñ˜7$þ­‰xbÕÆb1¢Ñh‰MêºN"‘ðݺ-Ë"›Ízõha»òÁ~Ó4}aU íY²‡™ gb,¬ÍÞÃ7'8¼oÑ"³ÎeËÏöE±' h Žž)ü¯FµÒÏííåý¹MMMðÞ÷6úÒÆL=ڶߺeg<ýG¸êRòŸ~`v¤ÄhˆDµg­¤–öZ9£yïU¨ª‘ ëà8X¶æ§6Q©«ajÎoaw!… xÛ«ßUªMS†fÛ侺ý- 0ŒbÔ`užà=Tº±ê#X[æcgŠÑÀ‚‘~•F¥¢¥™¦‰‘4I%ŠÅ‚Úr¹Ò49ù—§Ÿn僼=6¥¿YJúŠ(¦f’&í‡ÓÐp Ë"DHðÿ60H‘ÂÁ!B Ã^yòèè88þ1• “#‡†6¤8cብjŸà¹T˜6‡9?Œ™ø§r ªrªkP˃Ûë…V!—jpP[7XV Ë¿6‡Ÿ'ŸÏûƒ¨*A¡U˜M§K•øRëÀñ„(½º^ÃZÃk¼G®‹ ‚©$ Õʨ~V;f°³Qèd·Ô4K~ÿ{Ö®]Ë ã| ÃÆhíó¼óÎã…9GÓô¹à˜ÏìÀ4¿TÓù”(’L&ýUeå¨Üš¦ùŒdÏårD£QLÓ‹%}âŸÈ¼ãæauz•´6”ȡĉàLteç*ÔWBŠŠkmY–ïQ£¾!Ê–¿ìAqSCí«òû(a%›Í–ˆ:Õ¾jYù DÇqü¼j]<÷;ý†a‰Dü{ ÄÎ`^"u^u¯Ôu¼ w[ðµP~ 5`¨¼Ôru ê¹”ÿ Æþý‘|„Õ«W×\žÉÊhìsîܹ¬Y³†ЂÃÌï¬Â6ê;#(‰øïR*•*±…t:¦i5¿?j»àÀ…5i㻫/Û?¸ÛÞÆÕWOíZEÍj›j9TÊKÛöÙíg`^v^wÇðÞQŽ3HèÈç‹Mœ|¾T,Púɤ—¤Ú0ŠN!*ÕHÁÙ?–Ê_˜3ã;~曉” Át-*ýJ:]tÖˆD¼å©”7ø‰Ó~D"&ÝK¿bž¾¢µJ5…rí{7Öž9dæyçQ)E,ËkÆb^¹ÒioަAäŒÇøÉRß.έQ÷E9AçrÅ<ó¶ Ù/Ý@Ç IÎ.^K6ë¼ítš›‹×È»~BêK ˆí•DzŠéL¢Qïñ©ô'*eK4ºÔÏ]¯´2Ç)¦ƒQËÕ£wœb UVuÌD¢˜Ë^‰7Þ+5Î\‡¾o&±Xqa¬á7¿ÙÎßþm/S™±´m_j{‰Ço'ñ&½©þX-Þ~“‰t:Mkk+Ñh”óÏÿ·ßþ?üá"^|ñ Ìšû ºçýšw,ÜÊ+{¿€5‰ê&÷múW.=íR¿-¡Ûò„K‡1ÌÂ?‡vÚ}‘A +aC JQë”X£ 5 ø"ŒŽN ÏPutbÄJDµ^-SƒÐêœfñÌŠgýjÔѶmµ}pÂQÿM†^Rkî#b_Š¹Ì„ç[ˆ/|š]P¿› ½z•WÊü+ïã¬ë^E¡8Æ‚O¦À±ü š®y0~/VHoÔáë"ÙlÑÓ$‘ÁÏm"_°!ªÃCQ˜$ÁLäaÝ??¾Ñ(D ßC`îÔ`ežÉaîÓà/’^ƒ1 üUžÌÀ› ’Û#°É†Ö4¥ÖâÎö?o{ëäi]žBßmþç4Ú+|Ђϥ`n®1à·¼hk<•€ëuøJá}ü\~X¿ßC 8+½ºç¾¬ßÌÁÑ6U详¡ðúÃû¸%¯èÐdÀ<³¸ß¿%¼c~Ô€_OÚ°¬0îÎÁŸ˜aÁqÀŒ(h…F†œ—oYÞ>ç@WáùZx÷lS Î3ஜ`Àq¸[óf åðîG"‹¢ðaÃË·cýyØžƒã4ø” ·G›ÞiÖhØeÑv¼Í²«¹ï´—kªÍê –¡œJaÁe•®q’;ÿívH¥¬ŠmÇ©€®ëôööúuôç>W¬¯-ËBÓb\vÙ¿ð¶·½;oXÈoN¼çŸ?ƒÔ¾ƒwÜã\tÑKX–ÎŒMLŸÞÏ´ióH§5œDÛ3êÙôI3®äɾ£¸ê3?`ÿ¬Åh[Ûˆlü·¿Ä‰s¢ÇzŽéÓ—¡_~”7¶]ø–üüç›inžFdɶlÙÂ9ç,ñ½³¢I¸ñÆÝ¬X±—þþ¹´ë;¸ ¥‡»îZÄÒ¥K1M8æ®Çyè¡ypôÐA7àÍ'¾Â7¿y4¼z4ÉdQÜ=þøÍìß¶ˆoþÝ“|ìc§óø¡—ùô§ŸáŽ;–ðÜÁ&žÞ øö7mfŽ~ˆžß/ädc ô üñNàÅ3· =v>MËîã?»ŒüÊùÂÎf×®#™±| îæÂ g³~ý!.¼p;w}§möküiú‹Ìxé$Z¯{ŠãúîKÿ Þè·£¾ŒÖ>?{ô:¾ó…=ü€ ÝÓB[Vh_.,l —µ7#ï£Y­jÕ'išféw¨0J™7)΢ʓʹ¡µÝ;·šñ<|WìB…¡fE®ÍÈ逎©iÞºoçHý´~¿}ºŽ¾u‘³.ÄŒ§àó–W–(E¢/ _JÀÇM¸´P±ÿua½Ž×P0 Ø“‚΀•ËA¿Û3ðo é^ŒÙ›RðOèˆÂ4Ç»–àõœ…cløIÞ rKÞXÿ˜å…Hû‹<áÀÀyê™nÐá?ZáFàó°P÷®É~cÂ=9øx^¶àBžÐ Ü/g`Mf8”8óÄrÅÊÚÊÃU¦wnÑáÎìS³;’<ûПšõb<Æm-àÐ yqÿL–_5x¿L&3hÜSÂHh•––Ö¯__²l`` &µ¼Nί¾t9o¼è7£.ƒš™®f¢·¶¶ÒßßïÏH¯F= ½Ò1E4ÅXísàOoਸ਼ӇÝ.—Ëá8ÙlÖ÷Æ AQ¢òòÐ47¿ù͘o6K\ïk Ë0¯ A˜hÆjŸ›öZtßÃMè ò‘Œ¹ö,Óð¦Šö’ÉÊc1oL(õúýjüŠnU3VýT!¡ÔD\5¤Äµpà^y?¨q'õ³š³¯®=JÔ¶ªšÖõR!#˜‚DÓË­ö –'XfÛ.n Û¥ÆÊÊQ¢N¥uåcd %èTr4¯¶O$ây¯(Ï•ò}*¡îq¥õÕº#êÞUê*TkÂ(1ª|<Ð4aíÚ_ròÉ“??àPŒ¥îüµýïŠì%‘Hpñ¿þ«_ûxEÁG—/ü×üt¨–§7>XK¦ŽkS£ þî~7ËË·Ó çª6•'8á!ø»jsÿïÿ~˜ÖÖÖB$‚þ„@Ž÷ÏþÌkß'<ÁîÝ ¹ãŽ3X¿þ{¼ýíoâW¿z+¯|¿^w>MMßà§}ÿɱÇË /ü–æævîyü.¸`!ùü;è냽{ÿ–¦¦ Üÿq,_¾œï~w!ð[öïÿ.ßùÎGÕ‡ã8üÅ_,à©§.`úôö.dÛ/Ðß ?ûÙ­|÷»ò¦7½ùóaçÎû¹ÿþӸ뮭,]:‡Í›8餭tt8˜¦ÁÆ3ؾ}9óæ=ÄüÇ+œ~ºw¶lSO]į~õe¿¿qèý{‡YÀsÞD•C‡îcúÖX¼øC8ÿg¾îã|íkÏÓÞnððÃçaYçÓÜüyn¿=Å…þŽþþ Àã¼¼½óß´ ýBçž›Å3Ï4ñôӌ敟TŒÖ>WÌ|œØ{à6ùžHÃ2ÂI=jê‘ÒjjѪm­Í_]/*óêïJÛT‹|Rþá¿)Nˆ‚±æåÈ/²Hu‚†‰…IŽˆ)ûm„$UÇ(¹¹¹4negÖ«\óy¸&Pæ£ðHõÈ ïò ªã—_ÍJ›¨ûPí~øX¤ôIÀÈA*S]¥„¡Â­…ã¼ã÷lëbÏæ©‘¿³cíw*^yð\ž¹Ÿ¹sçZ§Â“ BØ  ÒÖÖÆÀÀ€Ÿ¥§§‡¾¾>.¿üòšö·,pO}’WŽzóˆÎ«BiE£Ñ’ Éd²$|Ž ÎŒÉ>gÁœy½5UŠš¦ùö8žñ§ƒÀÛxvláÙ‹Ùj2)üSäÈ‘'O‚„ŸÓ¨¦0º•¼óÊgCÀð ÊEµÙBUÆÚïTL;íiö¼`ðømGG‡¹GÂLh€5kÖpã7²bÅ 6nÜÈš5kF”Ô鈦]#¬QÉž;::üp^‚ f´öù§ƒ0¯iÿ°!}ÔL¶ò¤Õ‚ ÏhíÓöt-Gø=V˼Q[…îÊårÄãq?ôI­¹½„†QL(!L Fk›ú·°,‹O¼ªjªèéQ$)æ5©•e$ŒfÌa4c£ÉI?š9£¹«Þe›¨¹\‡ûœ±ÑÚç3mô¿oÿú§ùÛØnšñ„‡Hà?x°ž`áPˆÊK¤&ÐôB­sñâ`pùP¨Zžh§(´Øx)‚7j_ÊöW’ÀxVBR0 îmj8N¤p( :Aa'x/㚆‘Í2ž±åzã¨{géº *•ƒÚÇ¿ŸÑ(Náž•ß+U† —‚cš¤çS÷Il«Ò6Ë©¶3k‘ZÙ¶»N˜ÚyÖ£±Ïï¿ùþzÆ•u-—z&Ê~bxïÇøMœx”ÀbccaùâŠVTN#ÝÏ÷3%£È3 ë¸-ÀÎf‹S<¿d™ ãl™@+L TÖ­[7hÙªU«hkk£¯¯Å‹Èmlýožâ¤×jÞ>“Éø ¡“ɤŸ³d´Lþ@#‚àQÉ6aôö9ÿµ<'_tæÛضí'îç ö`òHA˜ŒŒ·}l{Ú´ž‘âÍÄÌå¼®¾J:¯1eŒf”[ ãնݵëؽ›|>O6Ûäç)y¥0ŒÁy@„ú Zçäd¼ëN×YÌñ7_Å»ªäV¨8¯Ö¶A׉ª¤@AòyoèÇqŠ ‰‚ž*QQYÙú9IJ½Xå¾üäÔòú+Ñæ(¸(áCÍè· ÇR"…òࢠÐ^8·Q¸Î|áïrч¶&ƒýW¢s«ó«aº\a½V¶^ ]•î‡ÿ8(Š_fáïàýÔÇTÄ(Š)‰À¹ƒ÷U…oS×éT9÷¯¸¢†'1yOû|ÞË5 ¯©kyÕ;©Hâ=ßvŠÏL‰l9¼wn²TzáŸòN±°È‘CCÃÂÂÆ&E ›LÌ©%°ƒïq[ð¾µ3¿ÝÁâÏ–Ö`*Dt0L¤ „™Py¨£2H€SÏïfëì§0ͪi{•dÚ²¬ ›oc£×8SÂÇhìsßË8æÙc0Þ_ÝÆòù<‘H¤îv(=a*3Úúóøg^Ç«§î†Ÿ”`Û6¶mcš¦ßàÕ4­$´‡ ¥ŒÔ6÷í›ÍÛN|tÝRD0„ú0Rû|è¬ÝÌ¿è6ˆ•å¼´,O)O*”ËAª L‰"åBL¾lj^A|)ù;—ó&©CJ|Ïå¼õ*iÖ4A¢^=Ò`h°r"U¶5ÊÖE,æ 5ݪ›Òü0Õž#>Ìú‘ Â  Ešb˜´áŽÅ0Ûýæ[ß‚?ÿóQ–vr1Rû\vÛ2XUÿrß ÈRêý”Á4îÆZ”¸¢¼Ö”R؇ŒÂ¿JdÈ'OªìPu©}ÊûÝJ¬¦£íwÌÁáÙ? ÄAá'OÑûç%4vÔ𼪠Gê>è¿Å"GΫ'üó}8³ÿjú—.õ—;ÎðýÑ᜹ÂD2e•͜ʊ%¹M"‘ ˬZA˜@^ûU ~e©Ä”‰pÍ¡2»wÛ¼íÆX÷XCÚb&“Á¶mº»»Ñ4HÈ23g©ßÕ ¿……Ž~ØäPªfðE” ð“'ï‹Dµ¢žJ˕ȢĦ¡Øºd+§ôœÒèÛZlÛ–öª „ã~ùçœñø/X2ðW°/9†¤(NåΖ' ˲§¢+ÔÈcŽb–ø – –«1÷4Å$ j´Qý=NÐ;¦R -%*1\2¨ZŽ1œø{ÿÇRŽZW•·™Ê‡ëß w]—äY‡µæ Rúmy£ÂvŠèÇ­ez”/ÀûÔ…ÿê­~ÂTø2 %¤xË3…uJ0‰Sütª/J¦°½^XN`ÇUb?»:”lÕ¶ê§Ìþ„—ÛFÝó HâŽ+[®¶w( )Áý5àOçLJz{k¸£‡7_|¿~`+l!n`ùx´{U¯ƒòä‰þ Kp¢BMø›ÁËœ @›SFP™Ù³ŒC—Ω¸.ŸÏ“H$Èf³VH&˜}žÁ.ç+®Óu]lRÈ®­;˜ñÓ#ªzoªÄóa?«5œ·›#i@Ö£±©âgGÏŽvîÝ9¡÷f2á8Ž„=„òççü‰÷ÿô.¸åsÞšúŒ?§j´­;ð{µ±ñ >P>]]e»VS×Õ´pµ>8¼™âhŸFéTq•¨!8U[í© N9¯„•”¦û`êý½vãI8,i„ùÏ™b›à°uPv­6œm–­‹Vù}¤(Ï›ò ,F*UÖúé[÷Øcüq å>p€}{÷1픇¸fáuþrÛ¶±í‘Mòª~›~úi¦Ù7W¾Mp`_M<«ÄP@p]@E)o¢[¥þ–ÚOMþS“Ñ‚ÔjÍ'¤Î—'á_kž¼á@§Z´ƒzå. †ùKù2)ƒ"/¨{Ü>ØŸIÙlì’s)¶D¶Ð¶µm\¯oÊ*Gû2‹ÞU9y§ã8twwðˆ‚ Œ.Û—¼4hi,£s‚g^©°<Í4cbŽhÆz0Ü ¿ø à‡ç™H‚pòr¨¸²0xU]ªðƒš:މYr U ª{l8„‰í‘í.Bh±€iÛæ2mï~Ì˪¬;Ž#3å…š©õ;pÌÀ1tíéjtqAFÄŸyŠÓ˜É!øõ*¿-ðS£4ñ‚"8²YiR´`Tœ5U[‰.Áx?Á)Ù–«içyJã9cDð¦’ë½r‚D ûXß•¤„láÜA¯œà6JRSÞUò‰ 8Ô‹ IÝ—E±È¦[HÅ>JΩþ›ý:)zé}òeåÈ•m£¼‘ ÔÃH¡D,«ÊýRSí3…ãQxfKg-éÛ$‡êÓTÎhûªµîuú+¯ðòvé{…ñÎû˜ñÑ­%ËmÛ&:œ‡bäÈù^)"´*‡ò;*4spLHý|WLÌ¡b"©—Ðq8²6·ÆWO™‚Ê7¬ q`ZÕ™|‰D"áIj™±)S‰íMg³÷¨mƒlS…úšèÙ·::Ý'ßjaq*¡f,TK°/T…'_8X[ W4ºáÄ=ý2öϯ(˜X–E,Ã4Íqkà ‚0<ûöíïA) ÿ°›-Kæ³|¢O<šq@½l_Á£ŒAQ¦–yNña–¡„œà9«5'z«c$åîWí~ϯΩB­EÊÖW*‡9Äñ*íWéE‘§ÚµQŽÍ«7×pƒABÈC°ç¿ßÂŒ·”,¯Pð::I’D O’pGX¨åz„ð2%•]îdþ‚ÍÆu%ËÇ!“ÉÐ’8†–oØ‚p¸pÖmŸÃH¿¥d™mÛ 9Ç3ÔTtÂd啞S8íÅßb?h¦i’wLÀ®]»Äî!¤¼|è§<óú3&^P™ŒL–ÏØDwIT A&IXÞxÞÿ6´Ó¾íÿmYñx|\BÁëèDÇ0NjgJ*G/ÛÊ ç?” *ãƒoö±FCAa Q}8Ñ{ÿG½nkÉÄ!ÕV„ÉÆ”Tþïû'ò|Ï;á Åeù|ž\.G:ýAŽx”C_RaªÁAB@Ó‹Ì;{ß ÅjOÄA˜¨ÁÇq°, Ó4I$$“I:::èíí¥¹¹™l6ë¾g2Òé´/Häóyð_Ó4_ÐP÷–eùøJüPõ¹3LÓDÓ4ÿ§LÓÄqœAëÕ‹òÉêøêo%èºN6륙5MÃ0Èf³~™#‘ˆ/ ©>€:—ÊÛ¦®+“Éà8NÉr DÐQD£QÇñ…%4©kˆÇãþu©íÕýP?¿LÑh´dûÎÎN¿,¶mÓÞÞN6›õ_þ¬Õ}Q¢U6›õÅ­à ÏÎÎNR©Žã é,˲,ÿúÕ}X»vm£_éÐrÅWÈÀ ‚ Œ‚n~Çìå/—´¹ ÃzU˜”L Ae÷³3aé•þ2ª$L88â¥2Ù´dmãÝhа¨ÿ;,3_F×ÿðò`Ah ÛàµÏ~ ãꯔ,ÎårX–Õò‚ mÛØ¶M>ŸGÓ4ßS”·Ô1ÊÛüÁåÕ®G×õªß¸jç×4­êD-U¶òë ,Ác«ŸÁ²Å£¡¼+-WbR%ªõ‡Ôó긂 ‚0Õ(OD.LýOÇg=„®{‰âU›V&#“^PYúòRÿȸà‘süe¶mû³ñÂ‚ŽŽ†&‚ÊdÓ’Mp Ñ¥'/ZÍLsNðdö „‡ûYÑ4»dM5hEL„p¡¼&r9/{r4%‰øÞCQm \&7„y6‚ õ%—ËùÞˆù|žH$â‡@Tž*|eyèEõ»¦i¾Ge.—óC7vvv–„rTa+…q,Ó¨ö †Tûvtt”ô*§ × ‹©Ž¡BPÃaªíU¨Î`ô­FR#xLR³<ü$P:³Úý©eŸl6KGGñxœT*E:Õy¿ëq®;ÿ:~ñÌ/X°`»wïfÖ¬YìÞ½›ã§ÏÓ;žfÙ²e<õÔSœ{î¹<ôÐC,[¶ŒG}”³Ï>›^xY³f±{÷nfîžÉãpàÀöÎÙËŸOûóF¿ÚáņGϲÙuÒ þ;ç8Nè& B­LzAeóñ›ùÓ¿|š?7½ÙuJáT³í‚ŽN šŠ¬ýåZÄA¥2;gïäµ§–žmgÑ ‚ÐXön{™¶ãìOøËòùü¸$a|p‡|>ï܈Ø)B#pgÐïÁ|CÁæà@3àÿ®Ö†á‡&TáþTØÀ`H»É¶OùOµÏxß¡62™ À œ`*Œ¥ ‘ á¨&*¨±¤H$RÑ£QMr†¦TB‡ÚWýTa*ƒž¤Õ(ß7èAªë:ýýýÃ^w0”$=EÕùÕrõÞ Õ7W¡@«•<¦ÒòrªÝŸÑì3–ó>zå£XXÜ6ÿ¶Š^*::œ[X¨~^PøÙ4x{ÇrxéàKl˜±aØgtØâÀ ?<Ÿ¯îò)1L&#“^Pxê\̤ x3 ‚1‰AhO=q:swøCz‚ÐXìg_`ïÿ™˜ŸðêKg_ìTÂC.—ömRa’`Y–?x®„5û=‘HTU­öQò¶m—Ì”Wûª¿G:Ë}¼÷Q3Ûƒe«v]A¡Aí£jÕDõw¥æåÛ„uŸJÇP÷@‰"ãqahÔD( åTkë–!USÉä£ñ§XÉNµŒ— ·M£ÆÜÆr^ “êû4i½¿½]]]ÌÚ3«!÷d2`„]}ÇpîÑóB9^FÂ4×uÝFb,|ìýïçžüeOõãH7b0¨OÁáÉÚµkikk£­MÜT‚tuuñá±X±` ©ü(ƒb© B½Y½z5ëÖ­kt1BÇêÕ«ybßżöôFþØ•òqt]aBèêꢫ«‹5kÖ4º(¡C}·Z[[Éf³b“„#mÛÊTún¥R) à •J•„Ýü߃Ëa¬HÛ¶2꾤R)4M“ B„#mÛê¬^½šïYGê”wsÝSWsëªU~;©…‰ mÛÐy¨ôõõÑ××ÇâÅ‹Y¼xñ°Û?wÔt8€Q Bý©}ñšËQG-”0%‚0ŒÔ>·¼v€7t4à¹[KŽ#A¨#µMðbÓé´ˆ)‚PgFcŸ±XÌ÷ =S ±cA#µO%pJ{VêËhêNëµ—˜ÿ,§}qù|žx<.9ã„IÍôF ÈúõëY¹r%·Þz++W®dýúõÃî³gïVÌù¾Ÿ¤³ƒ¶âx+ŒÆ>Oœöt\ÞL{{»4l¡ŽŒÆ>wm{W^¶Ø#-3ùaü•mîÚE{{»t2¡ÎŒÆ>wïÞí'ªŽÇã~AÆ—ÑØ§ 1'Bým<~`'³ëÏ=—L&3.áð¡‘„ÊCeíÚµÜrË-´µµÑÓÓÃÊ•+ikkRñ<òÕg82õ)>uÒI,X°€@ƒF>§°ßh©v¾õë׳jÕª ½#A)Ëavéû=<\}žþùÌ™3'´Þ)a·ºººF§M›ÆÖ­[ùÙÏ~ÆgœÑèK‡Ó;=Y¶í¾}û]Ôº3Ú¶íOúS-ZÄ¢E‹} £f2´keª|gjy&Ò¶fÜv‡ÃëöF™3ç–/CèÞ‹°×%“á»f{â‰'Xºté¸74‚ÊÀÀÀ eµ¨[?ûÙÏ]tA˜òŒÆ>¯¾új®¾úêF]¦<£±Ïïÿû.¶ Ly¤m+áe4öyÉ%—pÉ%—4ºè‚0å‘¶­ „“ѶmùË_6ºè‚0î„&)ýœ9s-Nåabû„ð"ö)áDlS‹ا „±OA'b›‚P$4‚JKKË Cm 6A8œû„ð"ö)áDlS‹ا „±OA'b›‚P$4‚J[[~̵žžúúú¸üòË]4A8ìû„ð"ö)áDlS‹ا „±OA'b›‚P$49TÖ¬YÃ7ÞÈŠ+ظq#kÖ¬¡©©©ÑűOA3bŸ‚NÄ6!¼ˆ} Bxû„p"¶)Ó\×u]ˆ }}}ôõõ±xñbq„!ö)áEìS‰ئ „±OA/bŸ‚NÄ6!„‚Š ‚ ‚ ‚ ‚ ‚ BØMAAAAAA„°"‚Š ‚ ‚ ‚ ‚ ‚ Â0ˆ "‚ ‚ ‚ ‚ ‚ ‚0 GÜtÓM75º“•¾¾>zzzüdLÕÖÌ™3gÄëÇ“žžfΜɌ3BU¾;wbY;wîäÄOQ&òþ “±Øg£m³–24Ú>ÃP>aò2”}†éÝ}6Ú6Ãv…©C½ì¶Qïc=ì{¢¯¥^õ´|#&õ쓆É>Çjy-õìãŠ}N.êÙ'mÄ»P¾k˜êα–Uìs0a¸';wîä…^mÝö¾qOOO=õTèÇm'|lÍFÅÍ7ßì¶¶¶º×^{­{É%—¸ï}ï{ÝýwÜá¯ommuï¸ãŽ’ý‡[?ž<óÌ3nkk«ûàƒ†ª|7n,¹‡ŸùÌgj.ÃDÞ?aò1ûl´mÖR†FÛgÊ'L^†²Ï0½[£±ÏFÛfØî¡0u¨—Ý6ê}¬‡}OôµÔ«ž–oÄ䢞}Ò0ÙçXío"¯¥ž}\±ÏÉE=û¤xêÑw SÝ9ŸIØ Ë=¹ùæ›Ý›o¾yÄ囈ò‡½oü™Ï|ƽä’KB?nÛˆ±5TFÁ3Ï<ã._¾Üݸq£¿ì’K.q3™ŒÿwðAnܸÑ]¾|¹ûÌ3ÏÔ¼~ÃònÖ>m›µÜ#±Oa4ÔËnñ>Ö˾'úZêUOË7brQÏ>i˜ìs¬ö7‘×RÏ>®Øç䢞}Ò‰~êÕw SÝ9Ö²Š}& ÷¤¥¥…¶¶¶Šy1ÂðLÃÞ7¾ì²ËX³f ;w«Ë.”ûnäØš*cäÞ{ïeåÊ•´µµ±jÕ* ¨Ö >¤áÖ;wîäÆoä–[nñÕÄZÏ?åëëëóUË믿žÅ‹³zõjÿŪ Q>aj0Rûl´mÖR†FÛgÊ'L Êí3 ïÖXì³Ñ¶YKÄ>…±2žv;Ñïc=í{¢¯¥^õ´|#&/ãÝ' “}ŽÕþ&òZêÙÇûœ¼ŒwŸt"ß…zö]ÃTw޵¬bŸƒ û= Û3 cßXÑ××Ç­·Þʽ÷Þë‹)Õ!ì}÷ñ(£*£dçά^½šµk×òùÏžÏþóþºJêgPánýxÉdhiiñ]Åèéé¡§§'åïE½å–[hkkcÍš5¬ZµŠõë×[†‰*Ÿ0y­}6Ú6k)C£í3,å&/Õì3 ïÖXì³Ñ¶–{(LMêa·ý>ÖÓ¾a[õ¨§å1ù¨WŸ4Lö9Vû›èk©WWìsòQ¯>éD¾ õ컆©îkYÅ>ö{–gæ¾±¢¥¥…uëÖñƒü€{ï½74ã¶[Ae”\{íµ,^¼˜|>_¢Ð÷²•?„_énýx±sçNn½õVn½õVúúú¸çž{¸çž{BQ¾¶¶¶A bðï¡Ê0Q÷O˜¼ŒÖ>m›Ã•¯–õãÁPö†ò “›jö–wk´öÙhÛ Ó=¦õ°ÛF¼õ²ï‰¾–zÕÓò˜|Ô«O&û«ýMäµÔ³+ö9ù¨WŸt¢ß…zõ]ÃTw޵¬bŸƒ û= Ë3 sßxýúõÜzë­þßMMM%ç ƒ}7tl­¦ÔõB wÜq‡{É%—¸>ø`ÉÿgžyÆß¦µµÕ}ðÁ]×uÝ7º­­­îÀÀ@ÍëÇ›k¯½Ö?_Ê700à¶¶¶º7nôÿ¾ä’KÜ;¦2Lôý&cµÏFÛf-eh´}6º|Âäe8û Û»5Rûl´m†ñ “ŸzÚm#ßÇñ¶ï‰¼–zÖÓò˜<Ô»O&û«ýMÔµÔ»+ö9y¨wŸ´QïÂx÷]ÃTwNÖgfÂrO®½öZ÷æ›oqùê]þ°÷UùÔ1Ã>n;Ñck"¨Œ‚›o¾Ù]¾|ù ÿA½ãŽ;ÜÖÖV÷Úk¯u[[[K^¸ZÖ7å/VÊwÇw¸Ë—/w¯½öZ÷’K.q?ó™ÏÔ\†‰¾Âäa¬öÙhÛ¬¥ ¶Ï0”O˜œ gŸa{·FjŸ¶Í0ÞCaòSO»mäû8Þö=Ñ×R¯zZ¾“‡z÷IÃdŸcµ¿‰¼–zöqÅ>'õî“6ê]ï¾k˜êÎÉúLÂLXîI5A¥ÑÏt2ô•­¨s„yÜv¢ÇÖ¦¹®ëŽ«¿àÓ××G__‹/®è24Üúá|êsæÌ¡¥¥eDehôý&7a·ÂnŸa(Ÿ05™ ïV£¿c©;Ãr…©ÅXÞ¹°½c)ëD_K½êé°=alL•wa¬ö7‘×RÏ>n˜ž‰0v¦Ê»0™¾3bŸKØïIØŸiÊ×ÓÓã‡Â »}Oä=AEAAAAAa$)½ ‚ ‚ ‚ ‚ ‚ Â0ˆ "‚ ‚ ‚ ‚ ‚ ‚0 "¨‚ ‚ ‚ ‚ ‚ ‚ ƒ*‚ ‚ ‚ ‚ ‚ ‚ à ‚Š ‚ ‚ ‚ ‚ ‚ Â0ˆ "‚ ‚ ‚ ‚ ‚ ‚0 "¨‚ ‚ ‚ ‚ ‚ ‚ ƒ*‚ ‚ ‚ ‚ ‚ ‚ à ‚Š ‚ ‚ ‚ ‚ ‚ Â0ˆ "‚ ‚ ‚ ‚ ‚ ‚0 "¨‚ ‚ ‚ ‚ ‚ ‚ ƒ*‚ ‚ ‚ ‚ ‚ ‚ à ‚Š ‚ ‚ ‚ ‚ ‚ Â0ˆ "‚ ‚ ‚ ‚ ‚ ‚0 "¨‚ ‚ ‚ ‚ ‚ ‚ ƒ*‚ ‚ ‚ ‚ ‚ ‚ à ‚Š ‚ ‚ ‚ ‚ ‚ Â0ˆ "‚ ‚ ‚ ‚ ‚ ‚0 "¨‚ ‚ ‚ ‚ ‚ ‚ ƒ*‚ ‚ ‚ ‚ ‚ ‚ à ‚Š ‚ ‚ ‚ ‚ ‚ Â0ˆ "‚ ‚ ‚ ‚ ‚ ‚0 "¨‚ ‚ ‚ ‚ ‚ ‚ ƒ*‚ ‚ ‚ ‚ ‚ ‚ à ‚Š ‚ ‚ ‚ ‚ ‚ Â0ˆ "‚ ‚ ‚ ‚ ‚ ‚0 "¨‚ ‚ ‚ ‚ ‚ ‚ ƒ*‚ ‚ ‚ ‚ ‚ ‚ à ‚Š ‚ ‚ ‚ ‚ ‚ Â0ˆ "‚ ‚ ‚ ‚ ‚ ‚0 "¨‚ ‚ ‚ ‚ ‚ ‚ ƒ*‚ ‚ ‚ ‚ ‚ ‚ à ‚Š ‚ ‚ ‚ ‚ ‚ Â0ˆ "‚ ‚ ‚ ‚ ‚ ‚0 "¨‚ ‚ ‚ ‚ ‚ ‚ ÔT2™ ù|¾ÑÅ*à8ù|˲Æåx¶m“Éd}YÂûœzض]Ñ®Å>'b›‡#±M˲p§ÑE†@lwê1ÖzUì6<ˆ}†—FõKÅ>ÃØgx­}Vª?¥O:9{<|˜ì69¥•\.7å ±½½}Ü{²,š››I¥Rttt‹ÅÆ|LÛ¶Éår¾4aˆ}N-‰­­­íZìsr1moû¬F­¶iÛ¶Ü¿I€ØîÔb¬õªØm¸˜Šö9Þ¯FõKÅ>Ã…Øg8­}V«?¥O:9˜ŠöSÃ&Ç›Én“G6ºÂÈÈçó“~&KGGñxœx<Žã8´¶¶’ËåˆD".š Œ‰©`Ÿ£Á¶mR©½½½èºŽã8Ì›7h4Ša.ž ‡¯}Žã1À$£åp´Ýñ¨WÅn…zèÈ/€IDAT3l³QýR±O¡Þ®ö9Tý)d*ؤPÊ”òPÉår4773mÚ4b±Ø —U)ÜóæÍ#‘HH$|…в,:::˜6mšÿ¡V´··“Éd˜7oóæÍ#“ÉH$˜7oÍÍÍ%êéH¶ uœòò%å ˲hmmeÚ´ittt”ìSmÝPûÔRÞá®[}Dâñ8š¦ÑÛÛ[R)Vºv˲ü{ Ž9”kXðùŽd?¡~ eŸCÙ¦Z_É>a›ÁcÕÃ>Gc·µ–w¸kÎ^*]7à?KMÓüŸª[ ±Ïp1–ºS­‹}V{Ggû‰¿eÁe†aˆ8B¦z»Ff»al÷Öb•®}´õjðo±ÛÆ"íÞRÂhŸÝ/ þ-öÙX¦Š}Nåvïpö9ýÒ mJ¿´qH{¶”0Ö—£mÏNùq\wŠÐÛÛën2™t]×uãñ¸ ¸ñxÜu]×íïïw5Ms³Ù¬ÛßßïF£Qp;;;ýujßÎÎNWÓ4···×u]·ä8ÉdrÐyLÓôË1’m‡p£Ñ¨Ûßßïvww»š¦¹~™k¹êzÕ¹u]rÝPûÔRÞZ®;N»¦iú?#‘È ë©tí©Tªd¹zFjßÎÎNÿÑhÔ5 Ãßn¨ý„‰a(ûÊ6]×Ò>a›êXõ°ÏÑØm­å­åÚ‡³—j×íºžÝE"7N»‘H¤ä~Š}†—±ÔÁõa±Ï¡ÞÑÃÕ>‡Ú¯šm*º»»]]×Ýþþ~×4M±Íq¸´{ÕºáÞ½°¶{k©çª]ûhêU×» Òî|?ÂhŸÝ/u]±Ï00•ìs*·{‡³ÏÑôK‡²Mé—6iϾa¬/GÛžêã¸SFP‰Çãn4-Y¦ëzÉË4‚þþ~ÿ…N§Ó®a%ûF£Qß î¤lðïrC¬uÛ¡J5Tƒ«ÖŠ1™Lº‘HdÐ=jÝPûÔRÞZ®[} U…¨þV½jמJ¥\MÓª>suŽh4êjšVR1µŸ01 eŸCÙ¦ëºCÚg#lS«ö9»­µ¼µ\ûpöRíºÕvê™êº^ò¼Å>ÃËXêN× Ÿ}õŽ®ö9Ô~ÕlS=k]×ÝîîîA÷Rh<‡K»W­îÝ k»·–z®Úµ¦^» Òî-%¬ö9ÑýR±Ïp0•ìs*·{‡³ÏÑôK‡j÷J¿´1H{¶”°Ö—£mÏNõqÜ)ò˲,ß­O¡ëºÿ»ã8%nµÁmmÛÆ²,¦M›æÿƒ;QùõŒÇqJ® ™L¹n¨}Æ]×Éf³˜¦I2™$ºß•®½Ü-ZÓ4lÛöÿºá]܆ÛO¨?CÙçP¶ ‡—}ŽÆnÇ›áì¥Òug2r¹ÝÝÝ$“Iz{{±,‹T*åo#öNÆRwB8ís,¶©®y*ÙçpûU³ÍT*…a8Žã‡]°,K’)†i÷–ævo-õ\ùµßu×]£ªWÅnô{K ³}Nd¿Tì3L5ûœÊíÞáìs4ýÒjí^~i#öl)a®/GÓž­e¿ÉGjƒõHl6{±m]×KlÙ4Í’}Å>ÃÉXêNûœ ö9Ü~ÕlSm—J¥H¥RضM.—+‰M,4i÷OÚ½0:»}þùçG]¯ŠÝ6i÷Oì³ýR±ÏÆ#ö9‡ë—Õî•~éÄ#íÙá C} õé‡Âä'š2‚Š®ëd2ÿ&[–U¢tE"‘’—ª|]pvˆã8477OêÆiš%÷#ŸÏÓÑÑát*­{Ç;ÞQuŸñÂ0 _Iï^çr¹AŠj%lÛöŸ›ÚÏ4M½*g<G×uÂpû õg(ûÊ6ÕúÃÅ>‡²Á¡lz<½(»vs¹\IÙÄ>ÃÉXêNµ^ì3Üö9Ü~Õl3™LÒÙÙéÿ7 ƒd29å:)“i÷–Öv/ŒÎn—/_>ªzUì6H»·”°ÚçD÷KÅ>ÃØg)am÷ŽÖ>‡ë—Vk÷‚ôK´gK k} õé‡Âä':²Ñ/¢Ñ(–eÑÜÜìD#‘ˆ¿Þ0 "‘­­­èº^¢néºN<§½½Ýß×4Í’ý®ë$ Òéôj®*¿º–eùµjë†Úg¼Ð4d2Ikk+¦iú÷:Ötí±X ]×ý™ñx¼â¶êK–,Ñ~B}Ê>‡²M8¼ìs4v[k©½¨†Nðù†!ö9 KÝ bŸ“Á>‡Ú¯| @Ùf$©iƘÐ8—v¯*ïp¶Öv¯*ÿHíö /dûöí#®WÅvô{K «}Nt¿Tì3ˆ}–Övïhís¨~éPí^uϤ_:±H{¶”°Ö—ªüãÙ­Äd'šVH3e°,˳TäÇñ]†ÇÁ4M¦M›F¿¿mÛØ¶¦i¡mì¨2–_ßp÷C×õAj~µuCí3Þ×Që½Îçó¤R):;;ÉçóußO¨•ì³Û„ÃË>Gc·ãÁXíe¢ìZÆRw‚Øg-ëÆŠÔƒB%¦z»7XÎZl7líÞ‰®W…p!íÞÊ÷#,öY~R¯^ˆ}V¾ai÷–_‡ôK§6Òž­|?ÂR_Nt?t²Øã”TªaÛ6­­­d³Y à •JaY^Ž¡%™¦Y³ÛÔxg"Ë<‚5û GXlS•e¬ïúd¶Í‰¶±Ïð#öÙØò‘zP a±ÝýÝ+ö'”ÛTe™Lõj#ÎW ±ë©‹ØgcËÛHÄ®ÃIXlRÚ³Û,ö8eB~ ‡®ë¤Ói?›®ëd³Ù /‡Š}7T9'ò8a;×Pe"V%S(Û„ñy×'³mN´½ˆ}†±ÏÆ–·üxR µÛ=ÜÛ½bB9a±M˜|õj#ÎW­ b×S±ÏÆ–·‘ˆ]‡“°Ø¤´g'¶:Yìñ°ñPAAAAAA-Ó]AAAAAA„°#‚Š ‚ ‚ ‚ ‚ ‚ Â0ˆ "‚ ‚ ‚ ‚ ‚ ‚0 "¨‚ ‚ ‚ ‚ ‚ ‚ ƒ*‚ ‚ ‚ ‚ ‚ ‚ à ‚Š ‚ ‚ ‚ ‚ ‚ Â0Ù茕ï~÷»,]º´ÑÅc^|ñE Ãà”SNitQBÅc=ƦM›8á„]á0fóæÍ\}õÕ.FèøÑ~Äüùó] á0æÕW_eΜ9œwÞy.Jè¶­Ðh¤m[™gŸ}˲¤m+4iÛVFÚ¶B£‘¶mu¤m+4šz´m'½ rÛm·qÅW4ºU¹ûî»C]¾­[·²uëÖPôÃ~7lØ Î2ºººøéO*ïÖذa‹-bÑ¢E.JE&Ë÷C:ƒùÏÿüO.¾øâF£*“åÝ’ïÇèÙºu+@¨Ÿq£{Û¶VÂþŽ„°Û{­ÔúL¤m[˲¸ýöÛ§Äwëp{§'µ>iÛV&ìmÛZ™ màZ™*ß™ZŸ‰´m«“L&ùÀ>ÐèbT%ìuÉdø.„ÝÞï¼óNÞýîw³fÍšq;æ„ *}}}ôõõ•,[±bMMM%ë/^ÌâÅ‹‡=Þ’%KÆõ†Œ7===¡._WW]]]¡.cØïáÚµk§ÄLµál3¸M-öyÖYg±cÇŽP?»ÉðnµµµÑÖÖÖè¢Td²|?¦ãmŸ ,õs›,ïV˜Ë7Y¾Sím[+aGBØí½Vj}&Ò¶­Ì 'œÀyç7%Þ…Ãíž ÔúL¤m[™°·mke2´keª|gj}&Ò¶­ÎÌ™3Cý.„½.™ ß…°Ûû† ˜;wî¸s•µk×rï½÷–,[·nmmm¬_¿žµkײbÅ 6nÜÈš5kXµjÕDq\Y·n]£‹0$aþh(Â~§ CÙ& öÙÂ\!Áäø~L7ûœ ï–|?ÅáÖ¶­•©ô†ÝÞke*=“Z8ÜêΑ ïtø˜*ϤVÄ>+3ÚÀµ2UÞé©ôLje¼Û¶---¾¤! {]2ÞÁ°ÛûyçÇYg5®ÇœpAeçÎ%eµk×rË-·ÐÖÖFOO+W®¤­­­&ÅS„±1”m‚ا 4±OA/Ò¶„p"u§ „±OA/Ò¶„á™>Ñ'ìêêªhh]]]Ì™3Ç7Ø––ZZZ¦ŒËœ „j¶©Ö‰} Bãû„ð"m[A'Rw Bxû„ð"m[Až TvîÜ Àg?ûYN?ýtÞô¦7±~ýzÀ‹·Vn°sæÌ·¯œ-[¶°zõꉼ AðY½z5wß}w£‹1f†²M½}Þ}÷ݬ]»¶Ñ—'†ôôô°zõj¶oßÞ袌™zØçöíÛY½zuÉqa¢P¡^zé¥FeÌHÛV˜jHÛVÚ¶B8QmÛ-[¶4º(cFÚ¶ÂTCÚ¶µµm§J(ar±víÚº´m'4äW__mmm\ýõ¬[·Ž®®.n¼ñF/^ÌÀÀÀ íkMÜöXmÂÔeݺuS¢S5”m¶µµÚ>¯¸âŠÐÇ£¦&---¬[·nJ JÖÃ>,X u§Ð0V­ZÅâÅ‹§Äl6iÛ S iÛ´m…F!m[iÛ áEÚ¶C#m[¡‘Ô«Ý6¡*ª ÜÃÚÚÚ¸üòË}·±r†S9A†²M@ìSˆØ§ „iÛ B8‘ºS‹ا „iÛ BmL¨ Ò××7ÈÅ«©© ðŒ¶Ü$±‘ LCÙ&ˆ} B#û„ð"m[A'Rw Bxû„ð"m[A¨ T”«˜ŠÉ·sçNî½÷Þ×N5+¡§§‡¾¾>.¿üòFß#A˜ò e›€Ø§ 4±OA/Ò¶„p"u§ „±OA/Ò¶„Ú˜Ð*«V­¢§§‡•+W²xñb6nÜȪU«XµjàÅ5»ñÆY±b7ndÍš5%3A¨ÃÙ&ˆ} B£û„ð"m[A'Rw Bxû„ð"m[A¨ T>ÿùÏÓÓÓã»…]ÃV­ZE[[}}}ƒÖ ‚P_†²Mû„F"ö)áEÚ¶‚N¤î„ð"ö)áEÚ¶‚0<.¨€w¯b‚Ð8†²Mû„F"ö)áEÚ¶‚N¤î„ð"ö)áEÚ¶‚04šCEAAAAAa2"‚Š ‚ ‚ ‚ ‚ ‚ Â0ˆ "‚ ‚ ‚ ‚ ‚ ‚0 "¨‚ ‚ ‚ ‚ ‚ ‚*, ÇûÝqŠÿËinž¸2‰ "‚ ‚ ‚ ‚ ‚ ˜I¥†^oÛ¥;ärƒ·sˆÅJkYžx’Ï{ër9ï÷‰äȉ= ‚ ‚ ‚ ‚ ‚ “ÛMƒL¢Qïo%”¤RÞ2ð¶o»|"OI&=Á$÷D%¨Ø6$ÐÙé-³,ïx¹èºw Çñ–çóÞOÓ,–M­Ïåàå—_ÏÒ¥3ÇõÚEPaRb9 X–l Þè ‚ ‚ ‚ ‚ Â"‘ðMóDŽHÄ-4ÍBòyOHÑ4o[MóÄ ]÷þŽF=¡C×½Ÿ¶] ߥëžè¢’TÊ[ŸÍ=^”`“LzÛj¤ÓEá%Ÿ÷„•ÖV0 ïïéÓÏçúëŸ×û ‚Š “Š yÑh1!;½Al»ø_…ÝÊf‹ÇQâK0OŠqÔvñ¸·®³³(–?Ü‘_‚ „ O< Š(@Å”cQ<1ŨrAAAAar`ùÙt+S‹ Ò ô–-³ð„B•Ò>—ó<3TžM+&`żuù¼·­ãxÛÇ㞈LäÞÙYÜ.)†î †ÑRÇïèð–+ï–înïü*¼Ê¢ò¡L¯‘‰DAB…Ö+‚ök(AE£²˜¢Â„ ‚ ‚ ‚ ‚ ‡å’Ko|)7Ž/ümS:¦¤|c´À²ÞDÞ ¦`Qy,j8§4ézk«'VäóE1D%~WhZ1Ÿ‰ Ù¥/^ÌâÅ‹Y~ÐjÛ†¼ï <Òç{–èxa½ àˆ‡fÓK/‘¦OgúæÍXxâˆNQpQãS `Á£²yóæb€‹6m`ÇCpÿýsðà9|;©LQL1M¯LÊ #Q¤Ra»”§ x:A<î‰.Ѩ'²D"EO” ˆ¢$&~=Éåð¤àÅ8Ž·<•ò¶QÊPå]¢¤|¾(”äóŘhÊ3%™,&„éí-u¦b©)µ?@4ʆ‹.÷KŸpA¥§§‡{ï½—hY07—/Èœ9sèëëòx[¶laõêÕ}‚ÀêÕ«¹ûî»]Œq¡šmªu£±Ï»ï¾›µk×¹M¾ ù«Š.Êø¦òláð §§‡Õ«W³}ûöFeÜ®g<ísûöí¬^½ZÂ' aýúõ¬]»–—^z©ÑE¤m+L%¤m;ö¶­ ÔնݲeK£‹2n×#m[aª mÛÚÚ¶===£.“¬w?¶‡Od`s~{œY%Û}(»þúH…Ï£ÄfþøÇlŸ=›8°ðÛߦiÓ&"xÛ¦ñÂÍ+a%SX¶ã¦_óÊ3GÊ_¸æsèÍÍìþÞ<Þø‰½|ø?Žy;ÈÝwÇ5OPú@{»÷_×=A…ùŠD¼ÿÅò'“Åp_ŠqÏm¢!o¸UTÊQÂI¦ e2Åujµ\‰#†áí£Bw)ï¥%“ÅXhñx1š:—rç ¢b é:¤Óž‡‹ºYѨŸ?eíý÷ó¥gŸç›8Á‚ÊÎ;¹ñƹå–[%´}-.cK–,aݺuy‚à³nÝ:®¸âŠFcÌ e›0zû¼âŠ+X³fMÍåH2öp_A4¼’Oå𣥥…uëÖ±`Á‚FeÌÔÃ>,XÀºuëXµjU£/O8 YµjkÖ¬aþüù.ʘ‘¶­0Õ¶íÐŒ´m+ã…jÛ.Y²¤ÑE3Ò¶¦Ò¶Õ¶miiu¹TÞÝ#þö¦Ÿúÿgû³·³Ãžço“ÉÀ.¢F,ƒ¹®‹î8lÛ¶ €Ï]ó+^½óNŽyüqt`ïü'>ðqŠáÀ¬ÌÎÁüü€Ó~˜½÷¼žG-/””eÁÓ?=ÄŽGþÛŽ0÷Ñ<|æ ž9ÿø·¹lîuÙªÁÒ8œ¤Ç÷UªcÝÏŽ_$/F¸R$#±’J¥†ßHyo(‚¹IJn²SG¬²Q´`‚¥ÙvñÂlÛ=”X£þN&K]uR)ï<ù¼·LÝ %¬FÑMG%†Q d*¡Â•oˆ›¶fÍšº´m'TPÉd2´´´000@WWôôôÐÓÓÜ9sm?œÊ)Âø0”m“Ö> ¼8˜’OE˜ÌLUû„©€´m!œHÝ)áEìSÂKÛ¶?²7ž¨rhÝ{Øñìfé°ÃØÊ’ä=þv–»-ŸgÆÜ^tÇÁÉå¸÷šÏñÕ¯ÞÍúõ‡Ø»m7là¼ó®bûݧ`Ýx¢ŠeÁÜ÷¾ ¼ñ{OóÑ¿<‚£`ï–#O—Øöõ¸î¹\xá'X¸øX¦=·›éß=–™?ÞÍž#Ž`ž›u˜«Ãv³¨ ˜&\Þñ=6¾¶MƒX,F"‘Àqòù<©TŠ|¾ö8+¶m“ªE„Q^êPø¢ižà¡ÄÓ„Žo™ºÁ*”–ò$Q‚G,æícEÑD ÝÝÞïét1L6ëy—ÝoÒéÊåWçž”~çÎÜzë­€gx÷Üs´µµ rϤc‚0AT³M³ö©fØØu=T¢°<0Þ^’‚0‘4Â>A¨ iÛ B8‘ºS‹ا „—F·mUx/•×äšØküu'X¶ŸÁŸmcûìŽZ<×±†|¯7ÞcYД'ç0ûàAR=D,•bÖ¡û¸ÿþ,û÷ÿ5ûö}‚–ú ÿupî¼s7ÎÓÜ ögÛ¸ï¾g8âˆO±ç³ÿÍK/½Ã8ž§³ZÁŒÀ¡ð¾÷õrûígÃ/a–»m8çm¿å÷-FØlÃÏó°? ÿnÛD" ë:yÿF^ÅÈd28ŽƒeYضM.èA2Žã‹ÅH§Ó$ ¾4c}ñ‹œûÉO–l·éßà…cå‚k®)Š(±˜÷3-æ, Žã‰¦é­‹D<I×½}2 ýýÅcAQ|QIã‰Ê±ÊÊÃvMb&TP)w^½z5×_½ŸÐH) mmmôôôÐ××Çå—_Þè{$Sžál³­­­.öia¡¡acc3>Éèƒ@/¦ LVeŸ‚ ´m!œHÝ)áEìSÂKÚ¶jâíϰ±ÑÙiÏ÷B{Ù:¼áqÿ*ý˶Ñ 9¼«ã%¶fÏ`/pžçÆòå»°, Ã0дÍd2[ ]70M“ï}ïiúûÏeÞ¼»°,øÂnǶßÏ¡C¯°yó\wÝ=lÜøFvï^Ķmðâf°}Ü`¡¯Lg‡6l¾•‡Û ÿÔrüxáoÎä/žÏ×~ÿSŽYs Á§ÿë¿xiÃÊåxõÓŸföOÉdÈf³d2R©5‰*¹\Çq˜7oÑh”ßüfš6m*Ü8/üon¿ßð.8ë,o¹Zo\fr¹b’å­bY^ˆ.]÷–)OË*zˆäóžR§åa ”%ãÍ„{¨ Åš5k¸ñÆY±b7ndÍš5cj ‚0ñÔË>ç`°£ð»6–UAGaê#õ§ „±MA/bŸ‚^Ä>!œL¤mîÀÆAÍa¦æy’ðgÀÝ7x€éæCìÎ\É{ÛxÙx†+9œmÓÞþ;|º®óo\X¬\ù§vÏ> }} xó›½C~á Oðä“Ç2oÞCìÞ½Ž%K>Çm·˜& Àœ9O¡}èE^þ̉|´NX±ƒcÝOG‡µ*“G‡3fžÅŒÿþor½½<’Ï3ÐÛ ùw›ñòœØØh…‚ Tf"íS„‘!m[A'Rw Bxû„ð2ÑmÛž—†Á&`)€eðã|tN~>u=$½Ü!®s,˜¿¤;ÿŽèþ4G?úÉO\È|†ÎÎ8©”—ÿdË–ùlÙâ9S¨ˆW[·^ÉK/måįàС]ìÜyŸøÄ|?‡»i¦MýlþÌ2fëðª ËOÚȹçÎãâ‹—¢iE§|¬L7ŽãÍfyÓŽ¼uÛ6~ÿ¾÷aÏšE¸ ¸}ófÞúÎwz×iÙ, À4Œb•ÂÏöX Ã0øk¯åË¿úÉdÒS°,ZwìàÄßýÎ÷Nyaÿ~–ÿ×±ð–[¸[%†ˆ"™L†X,†ëºÅÄíÑ(D"¼¼æ?é¾ã>.5/ ÈàÍPŽP '3”P¢Êu˜*@*KA1ãmŸ66»íÀ C(S_Í„ñFêOA'b›‚^Ä>!¼ˆ} B8©§mfÈø“lûËmË 35ã’Mì»ä!Üx 09 ?ær”ý fíÛÇoþîïˆD" œDøÑÎ,”ùïÐu/zU&SÌËÞÔô;w.¢¯Î;ïHlû,ËIR)/âÕ÷¿"Ûw÷ñ·_]Ì¿¤àd-ùçFý!A‡\.G:Æ0 Ž»øbnùïÿæ©Y³°ðt €¥K—òÜç>G®°Ì›`¼yÙ2NzðA¬¦&^þwOJ§Óô}4¿zÏ{ˆhš—ì aîܹ|áÝïæíï}/ÇìÝ˃W^ɧ®¹n¹…'¿ü%©L†|{;Ùl–T*…aÞ /Rž'I¾í%¦¿2]+ è,LÇKf£Ú2\ç:AE„Û9lZ¯ò³«Ü(*1}4z#7Ýäí7Ö¼ê¾`‹y Ü Ã;!x^%ŽCüßÿÝ+P<>¶íí§i¤c1V.YÂüûïç»@dÏr^ðÖ°aÁÎ<Ìy§Ç9Ö9^¸0›âO%®r¯¤“ib©Àøž¤ ïò>¿~1´Ã)gŸÂž={x¼÷q¾þ§¯ƒOœý„ïtßu÷1sæL.>t1û»ö³õŽ­ì=f/[_ÛÊãçÊ÷]Éô§óÛßþ–3o>“ëõëÙ<°™óvž‡¶OcÙÆeìya‰ï'hkk×÷³fA峟ý,ëׯçú믠¯¯k¯½–+VÐÒÒ½÷ÞK__·Ür˸P„©ÍÜBf+½ð¯œ ¢D}ï• ¨2”¢ŤAAAAa‚É“çlLÈ›­íbßù`ÿ1ǰ}æÿÏÞÙÇÇQÕûÿ }Jh›vB¡-!¶L(O-P˜\À  :‘" ŠNŠWTº«^Ñ^w½þ|BÅ]­‘+ܪEñ©;Ú+*Oî(‚P¡f*HËSÉH ¥-™6-¤¥”ýýqæÌÎ&›6IóÔrÞ}m³;;sæÌìœ9g¾Ÿóý~«xõÕW;a “Ÿë"ø×8v½‹ÚÚÚ¨ S‡e˦ãyBÓpœRù–%– Äe¤ÓB䢇Ü9E¢i¢¾/Öw]±i’p(àž{ÈÆ!‡=>æy“Ëõ»Z¿]³†Ì–©<˜ÉÐÜÜL±yÁåài`jàzYÀ×aëÇ>†³|9™LF$¯9â-Gð ÷`C6ÈÒVl^*zøj‹¹"5Äã›çôM§Cl×fî§ç2{ölꯃÿ†ûjïã„®˜u÷,ºªº¨½»–¯%¿ÆÄG'r¯~/¦!• ?ÞuP]_Í‹¿y‘5Mk8¯ý<ø\¬_ .ìš»‹­‡nå…¼ÀÑGÍlg¶¨tªÓÕTªùÿcì>æPY»v-wÞy'+V¬ˆ¼Pîºë.¦L™Â 7ÜÀâÅ‹Y¶lY$ª( E_ å2½‡G-µQx/7Ê‘Ò=˜LH¯P( …B¡P( …B¡Ø‘6Ÿ'|ÝG=NÕ뻘øú)€çy¼¥‘W««y-Ê~”p^þ30ÐÑi¤⋉©’Ò+ …B¡P( …B¡PìÇHAe ±îa÷·>Ƙ1cy‡}#ŒPòÚk¯±û á‘RûÏÚžÅçÝ6ƒ¾qàkW×R»¥Â>‚@„ö!‚Üá a¢|)¤Óâ}"ÑÓ5Æ0„Ðâ¯F_Ñ´2÷0ïz¨ÏÈdë®ëâ>¬G Û¯ùó&’k }|ô×/p¦ <¸q ~³³ »xw±šo_üNN¾ïn¨ªâîuë¸âÆÙqá…€–o}‹G“ËÑèû|øÕWyÛƒ’´mÞñŽw0uêTvíÚÅ=÷ÜÃîÝ»ùÅ›~ÁOßúSžðyn;î6o?œ.;þ¸ðÖ4­aÛØmœÛy.Õ?©¦my×lº†iÿ5 ZaÎisÀ€Z¯–©ÿ;Z! @“C#ùðhpðêƒÅûîAj ÊCÓháö}Íå2@ú$¨€Lâ¬\¹’yóæ•-“âŠB¡Pì‰Z°ÃÑbª{Iw70È‘ÃÆŽÄ“ 44\\44 ÔK¡P( …B¡P( …âÀÀžÇ˜5 û²ý @§ºº:ÒI~` ££ƒªªªòÈ%傊L¬;Ày¸u·×qâ'FeÏY?ÒÀï=XáŠrðá±0ù¼LØ"Ãz…º^\ ÜUÆ4K \ ƒªçFÂIë¯ t=Ð…ÿxù–—YyÑJ6Þº‘7ýód¾›ÆÚY'pÍvrÏ;¦ñTí \ø·üèÊ誟Éû–¿Äÿ~ö(šŸ:ˆ#ƒWyü¼W™þ­/1åé§©««ãÏø3¯¾˜ÚÑÁ´õëy×£²hêTLßçÑ㎣!檫®âMù¸çô|žÏ~ýëÜqÇrÈ!Ü÷Áû8ç®sØyëNîŸy?»Þ³‹sŸÃ¡;”ºê„G °rÓJ\yüRÉ÷<ßþµ˜TJbDgÒBx¦ô†Ožôä>^=éS•)S¦pçwFŸïºë.€²„.¬]»–)S¦ z% ÅÇx¾o£”DKCÃÄDC‹Äé©ÒJk$¢¸¸ebŠï‹¾Ë '$¥~¬CcÈÕi…B¡P( …B¡P( Eÿ9ÍpM±ëxå©OÀ'nb濪Ø[7´ê#ØŠIMM ³:gq•"—¸‘ã”$=LˆŽ…0ÌWJÅkÇ–g„X6±ýÆï¸ 8n¸`Ý ¢²ãW4Xêæ&›pÂkÅ0DX/ß/é™r›+ê'íS-á~üðoÈîÿÜ͘ùcð¾áqÆ£‡s_çx¾ôÙÝœ|ËŸ¹Ê¸Šo=¿‰kœùhé5ÎÞº‹_ËÌ?Lâ'7½ÂÚ£ªXýÞƒ¹wÜ“¼>ûpþãýãø<ó§Öpé_ÿÊý—]FpÈ!¬Y»Çq0 ý¯ÅqnÌç Ægý3Ïð¾ùóÉOŠöïp#àÏŸ'œÀŸs94M£±±‘Eß\Äû®|‰D;i…Btq:ßG×uÇÁ²,üØO“¶thâ“»üpy"ü)m„vâ#Ò¶H%Óíg$vJ½ñpÖg±¡eà^³}T,X€mÛ|éK_¢©© Û¶ijjŠüáS__Ï 7Ü0ÈÕS(*‡uK0ߎ––ÃuÁ eg€ òP©§žq¹/ ùg1^{S¿X¬†­Ü¤AK‹ð¢TbŠB¡P( …B¡P( Åè`÷áó:h>“õƒÙõÏ]ü±ÿ¢¶ã›dÈÐ[¿ªª €#;‚cŽ9FXÒë ÌÌäÅ>»á{á¶ÐŒ°ÔGn ±u„§J(vŒ}u'>ñ*œ ŒÑ˜¼û!˜‘†M†X1p`gÇ'D9çZ°.Üþ®Õ"U!0´5´ÀŠõ+¸°þBÆéãØùÓœ·á<6wlfâ£éúFÿºö_¼iò›8ë'yóÕ/óîçÇòå3'`=ì:ˆkõ‰`ÀE¿ý1ºu¹¨»sÀÉÐ#L:hšX(qìÓN#“ƶ|¾g .iB“Œ4„ç_ük®A£äeô¨apP³n ”"{}àè£9µ¦†.äë»v‘7(éX&B$I§Ó¼ó裹ùÊ+£ê”yܰîRìqÂe.BLi¥äœä„Û\¸b&?hÛ<¨×lŸ€¹sç–bŘ7oË–-+ ÿ¥P(½ ²=‰ÃÅý,Kø>ØvÉK2¼ÇGBŠÞÒ_H–DêE¾‘8—F±¸8ÊçpXæ›"$˜mSöB¡P( …B¡P( …bdØFÀF²ËNP Dô¬©S+®?aÂæ¿4Ÿ·Ü÷8!¨€°²Û”¼Q¤ÛƒŒ+w_€’W YÐSÂu"h†d îÉ2ñµ×aŒ ç$þ|3ÓÞ¡‰Ù»×XàuÀoÓpkBì×7à`°TÇ~ 4WcÕüUœæÆ|c>ïßô~–¥–ñ·Ùã͇¼™éNçêø·UÿÆÃ—?ÌSÓžââ_^̧N`ÜFïêòO_^ù¤j R“2)iTâ´Y”„gضÍ;¿õ-þóÊ+£ŸÉó<|Ç!xûÛÑt½l¿:=£ù[áOÜž¹ághúÌŽøèŽA=}TÚÛÛYºt)íííÔÔÔH$˜;w.555JLQ(}Æ‹e‹‡úêŽãñ#„âyâe"ÏJŽ\´î¬`>ß0jz-ëØtQVcãHŸ…B¡P( …B¡P( E%¦ê0yóíT}4Ç| ¦yZL¬÷S¸÷ ¸î¯×1þåñÐްð79„%]ºWÈøR:%Ë?”Bn-`ª é”°Îo7 烥C—Ïæª·0s³7¸|¦ñD~r­%r¥ÈX—gøé5?åÒ¿\Z 'æQÊç‘×ËgßÉ®Ïìbæ 3ùá'~È_ný ýà"v^±“ê˪?umÛW^mçû>–eáyº®ÓäO[) øco§¤¸ ÷uÅøÃ¬\¹’¹sçÒÞÞÎW\A{{û VF¡PØ8ÏG€Î=„ü²íRÎ.™ËË0„ "IÄn•5”ăƒ8¨L¸©ïÁš&^ ÊJ§ENÇï=OüÍfE ô}oõ”ø½N8ŽCsss/¿l6KñS( …B¡P( …B¡xƒ°ç‚0$“gp¬ëÖÕPSSäI“€Ðá¢Þ]÷n&к`ü»Æ—âANÉ}!î…"Ãy%J€Ì«òŠ ³Ó«d®ǘ¢¬ÿ `^˜™#hc >tf«ÁTŸÕE|y×öí'|>µæS¥XTQòù§g?ͽgÜËÆ 7âµz\pÙ¬íZËôéÓ™öñi\ôøE‘1¡i§~îÔÊÊÀP)Õ@1º}–¡Åä~ £´F.—#“É`š¦ðHñ}ÇÁ¶mt]Ç0 <Ïëu_•lh­Ðë”íYëf ú¹ë“ ²råJÚÛÛY±b‹/fÅŠL™2…åË—z… Å‹|.|ß…îêŽëBs³Qdx.Ù_í ,¬(´Xwä=]Š&--â¯m—„ßߟ~úÃd³¥mÓi8ýôN\W¬ŸL D9r{×uq]Ïóhii!›Íâû~Ygå8Ùl–ææf»¹Íxž×kÇ–W¨Ò9ÞC§£P( …B¡P( …B1šxØ=”W³Ç0©xÏ´š#œH‚Dd7’Ö£Çë‡`t fíf^'5áJZø2)…½J„ï¥Å]þèÂŒp½Ûj ^LÃÝY88|‘ŒàJΊͤíèåB<Èd2øŸ Ço`Ë–-bŸØqÃv}mG|èˆH<‚€‰·Oì–«’ëÇ>ÏópÇq0M³â:º®ÓÜÜÙÈ4M‹„YFmmm™L®_v{¨Çôg§ú±õ9äWSS55¥Yà ,ðN×®]ËÖ­[™2e sçÎ-û®½½öövêë멯¯ôV(½³§¶ ƒÓ>'cЉ‡Vá–çy%á$žëdOyOR)‘¸*“É`„ÿ<¾ïãy^Ÿí[Ožô$“˜4¨Ç×gAe°øÒ—¾ÄÊ•+©¯¯§½½¦¦&®½öZ–/_Î’%K˜7okÖ¬añâÅ,\¸p¸«¸ßâ8¾ï“Jp0=Å~ÉžÚ& Nûô™À£½hÇž'DDº‹×¾/øÁ7óÎwÍK/=ÍWÜÈG>òYnºéb¾ùÍaÛÐÚš Nãy¶m£iZ™¨ÒÜÜŒišÑyácË—¿Äç?¿ßóÖh¥0i™LIˆ*ÿý<4͈B³IÍç _XÏË/O§ªª ]ãÓ¿©ëŠß»Òµ`Tv`zC2íS¡P 5¶U(F'ªïT(F/ª}*£—Ûš.8Wðð­±ãÌÞˆÏ_5ŸU³À“:P7ÆQJ¤¡…³€ç€ÞÓi˜¦ƒ—€s¬ï€ÐH!cÅ'à8Üxãttu®ãÉ¿”¢Žd2™2¡ä‚Ë.@Ó4I¥RärÂíd4Š)C‰®ëäóù½Š™L&Pâë ZZZH¥R¸®K2™Äó<2™ v<ÿ^ØyÈN¦=7mPoX•µk×rçwòÇ?þ‘ššÚÛÛ1M“… 2wî\–,Y 7Ü@SSk×®åâ‹/¦©©iTÍF‚ j0Ã… ÔÖÖVñ{gNªuqAE.*ÅQq`°·¶ Jû €zV#‰uÇqÄ«PF÷8Ýë®ë’Í ¥ÿv iétZ¨Û ƒw=È{òïáQ÷Qÿ÷çÈ™3¹å/áŽ;6ãûâ8'A(h¸®‹¦ihšF"‘ •J‘ÍfI§Ó<öØýx^S¦øÁeœx≑€ÒÔô,gud^-ÄoÞÚZ Çvá…;øë__åœsj·ÜtZüµ,!ÆÑwÙ¬([ÓÄ8è@¹í WûT(ýç@Û*"ªïT(F/ª}*£—‘Ûîôk!0ÀŸC±áŸwÜqè•ÕVèïN£<_ ôÌŒžšm0´Ò¬Ý C‚™â}6+Œž& žW2&X¬®æ¡ï~€oûÛ‘ñ_F‰ +®ëâ8mmm´µµ i8­ÑŽ®ë}²Eïéår¹Èc¥¹¹˲hmmˆìà}ÙÇôg§3aÄA=¾> *kÖ¬áÃþpôY&¤_»vmÙzË–-뵌ööv.\…“ nëÖ­¬\¹’)S¦ÐÔÔÀܹs™;w.+W®U3â e0ˆ»2uGæap§l&½tm’4NS(Ðu=Ê× Ãyž]ÄÒ¬PtgOmÔöY…‡èõzvŽÒ+¡7ï‡TªÔ3Æã'N™òN9ÅÄq ÃÀ4MîÕï…é`ê&Ág?ˆD‚O<ü0ën»Ã0H§ˆ›¼t!Ô4|>•kš&étšÙ³ŸE׿ˆ#C×ÐuT*…ïûhšF.—CÓ4ÚÚJ"‘®‹¾9> AÎHøÜçJˤÇMuõÓ|éK'±}{¦éòÉOÎ &`Y® étßþ6¤Rc€IøþTV®¬Æ¶·ñÖ·þšY³f iBjm­£©éz~øÎ9§†›nÅE]ijÏ>϶m»8öØí<ô<þøElÛ¶Ë/¿•C©£µ5&ûLÓdÅŠiÜtÓ¼úêd=ô=|ô£gðµ¯9¼þúuÌŸ¿˜LFC×OŠ„.ÃhÅóà–[¦ó®w½™#ü‰DŠ––>ñ‰9á9šO*• À¶Ó|ÿûOò?ÿ³ˆÿøm¼ÿý·ò«_}‹®®3™1ãin>ßã9a$JB[: ÷ÜÓ‰ëÖJ‰ü6Jt³álŸ …¢c[…â@Dõ ÅèEµO…bô2RcÛþ¡à™LOýƒ­k_æÔYgW´_[Ã7÷!Ÿ¤(‰*µ¥Òmh€ø¤tY–çÁM™Pt1Åç 3a`H§#AÅ7M.lldÆŒ8ŽÃ}÷ÝÙ]mÛ¦­­ Çq°,+ ³.í>£ÙþZ)©ûhDNz–ïã¶øD"A6›ÎýžØR»…ªšªA­[Ÿ’ÒO™2…yóæ•-H¬¼ °xñb:;;Y¹r%K–,aîܹ‘²Ù½¼)S¦DÂMolÞ¼™%K– êI©D6›¥¶¶6š¿/H/Çqhhh(sS ‚€––£¼­­­$ Ç¡¥¥%V à ™LbšfT§D"çy‘ŠÂðœN§÷šÌ:ŽmÛ477—5² "‘GÎì·m›´œ2[oiœûÊ’%KXµjÕHWcŸÙSÛÜ>W­ZÅòåËË–ÍÀ"CéF"©»e‰&Ýû H&“ȦbÛv™ òÊ+¯H$‚ß÷iiiáàgfæ™3£¶pâæÍlÚTÇWœ…çyÑ=í©§nâ¿ø(étš††ZÒé‚ à’K¾Íþç:Ö¯_Ï?ÿùGZ[[ùЇŽàöÛ/bÚ´/pÚi_ • H$l;ë6ò±­&à׿~†§žšO&ãa§žšÀólòù©ƒ×PFˆ¡hŸ[¶laÉ’%¬\¹rŸëàWHŠÞX¹r%Žã°mÛ¶‘®Ê>³?mŠJ¨±mÿǶ ÅpÐÞÞÎ’%KؼyóHWeŸíc[…¢¿¨±m߯¶{Z¯J ¢;‡3f0þüòYЬGˆ!sÂåb®®…TdÀžîÞ-Ò8#E“ÆFñ9•ËB;+‰?^³&šŸËåxüñÇÑ4/~ñ‹Ü}÷ÝxžE’IÔ(ÊhÇ‹ï~BGGG™=Þ²,<Ï+³ Vbùòåüàà°ýØíƒZŸ>y¨Ì;wž'ý¥½½¥K—ÒÞÞ%·—³âôE°™8qbÔñ%¿ùͼó«ùå/g“L&q]7j0Rh°,‹d2I"‘è‘0(|ß'‚(éŽaa®‘¿ »aW&ª¶,+Rä|ßǶí²s¦iFõ’Fã––R©ŽãD‰»¡”Ä:^]×£c‘®kò&ÖÒÒW2™ŒnAÐÞŒ¤"ëY[[‹aQ² T*5)ÎÄÃ,õ•¾ºu 5MMMlذa¤«1hTj›0ðöYWW×CŒ8‘çD"s§TúI¥G–çyìÞ½› è$›ÍF[ÀÓOŸ‚aœTGñÊo^‰—ó¢W¿ðBnž?Ÿð9ÄÍX²7³šš›Éå¾Ïܹ}¿$<æqÇ=Ê)§ì¢?zd6+ÆÒ#ÆqÄçD"y¦Å™5k3gÏÆÕ@ßÂ꺈‰1eë÷6 ŸÏó‘|×…dò[hšyóÈ„ò>§i¾ï‡!lÝz5©F><‰HÄõ}?Š™)]=5-‡çJCÃjÞþöfÇÁu]N<ñDV®ü*G1o¯Ç·¿0˜í³ªªjP\³mìHLññI¨ÎO¡ˆS__ÏܹsyþùçGº*ƒÆþ8¶U(*¡Æ¶{¦·±­B1ÔÈYá=ôÐHWeÐc[…b ¨±íž‘cÛ)S¦ôºÎ½t——Ó—rÈ)›€˜­¢!”Ô3âÉùÀFD²ùJ&x¸ŠBA,žWŠnÑdp]×KqÄÅŽ9¤®Ž °m»Ì†iš&S§Nì­Pžva8ÓC ™[wGz¬ìÍy`Þ¼y<øàƒƒ¾ÿ~çPioogåÊ•‘²X__Ïy繃õ)ÐtvvrñÅS___±aµ··G14{cÒ¤IûüÐbF|2)ÄI]/å!Òõ‚ –Y³Ö1yr® ÿøÇ¿cšÏcÛvdÔM§ÓQX.)`HW¯†††H0û Ê“ ¢°]@E1F×õ(N\|Y_«Ü—s$D) e2|ߌ¯¾ïG7i¼t'Úü+ÇuW^å G6N9Ä ”L&£¼.2Þ 4˜û¾•/=`²Ùl$žÄEß÷ËrÊHG6&¹¾Ü‡D Pƒ¥755P³`*µÍ… ¸}ÖÕÕU\çÓÝ>Ë$å•Dòd2½ß²åŸ$“ÿ…®ë ð<˜`#Æñ–®i“&¥ £Çõé!ƹp»8ñ|3ºóŠÑuüD‚´tkÙ¾}‡ÞÎÉ'? œÝÇóÐ÷s¦ë:ãÆm'Ÿ'ò*Êçó=îmR‘Ë £äa/KŠBñVò^°cÇ|Ö¯ÃG?*„çL&C*•¢¶¶–cŽyµïå fû”ýÅÃ#Mš⾞$‰þóððñI‘B ÿôÃMKñ†¡¾¾žN8-[¶ŒtUÑ6¶U(ŠÛll«P 5555455±téÒ‘®Ê 1ƶ Å` Æ¶û>¶ÝêÎ/ÅŽ6ªª04SšR~ ¨Ž¾Ž0TÓÓ@"ÉçË«º.Q ñ0Gʺ+¯dɘ1äóyËŠì&rB¯´š¦ÉôéÓ£¢Ï>ûìý ¥7 ÃØ«WÇþ‚ÑKXÏóhnn&“É`Y<òH™p?ôKPY²d K—.¥¦¦&š™³téR–,YB"‘`Ñ¢E{Ü~ùòåtvvFëÕÔÔ0wî\ÚÛÛijjêá>½uëÖ!ŸaàyBHÉå„áïøã_áÝï>„æfhnÞ–-µø><òÈéœ|òX²YxôÑ7óÇ?~—ÖVa ´m›D"A2™$—Ëáº.Éd2òÌH¥ReŠewR©Tt1{ž·×Øo%~¡u$$ñÙçÒhÝÒÒyÞTZ/ަi½6ν‰? ‘bÛ6¦i’H$°,+aä~»{ I›–:ÈÕfÛ¶#(NG3Ýåïá8¶m“J¥†ì¼ïì©m‚èL‡²}Ú¶0å%*½âaë Ãà±Ç6ã8NôûéºÎºu먩Yœ ˆöïÜ<¼2£®è—íð½I)o™~ç Ä yEŒ·™3»z\÷B ©$tx”ÂwÆñ)Ï—Õ+Ö>»w A¸®Wa?ñ*¥R¥pi ·‹o³uë¡lÛ6–ÛnÛ =(¿_oø¾[&®î+Ýcf̙ӉãaÅ4ßI±XŒ¾Ëd2Ü{ï½CzŒÃÁH·O€Z01 pqññ Â+\CÃÇÇÄ$EŠZá…–'¿/»U(F=£ql«P(FGß©P(*£Ú§B1z©±íËlw!Uo{‚ª™3ÅBƒ’1ÄÃŽC`tÐwî¥PÛ3CMS*Ò¦éyJÑøÍo¢…¹_š››Éårø¾O:&—Ëaš&Ùl–D"Auu5gœqF”ãú@aV*ý¶m“ÍfÉçóضEfšúMä÷RLÉçó8Ž…iK§Ó¤R)lÛ¦±±±‡Û[:æ ƒê_PŠ7---#ýó ½µM`ÐÚ§‘Vâ8¥äí²©466F97d JÓ4é꺟㿴ìZضm3f̈>ëºÝT Œû3}rAˆ(.ЈG¤˜’’¯ÒÍgUñxŠÑËHŒm_õDR”ñ'=Ã'ž(Jc†ÈÀ%Sb `LØK¡ž' $¾/ O¦)D–|‚€µUU‘ !‘HÐÒÒ‚ëºQ>„1þá‡îwº‚ýI ’žEÒ>ŸÏç) ¼ë]ïô}õÉCeíÚµ,]º”+Vôp媩©‰”KÛ¶÷襲páBîºë®È]lÍš5œwÞy, ÁÅ‹sõÕW3oÞ<Ö¬YÃâÅ‹ûJ¬?ض0>Êz'Ÿ¼‹_¼ŽcŽ¹Ç©Ã0¦NMsðÁ—"Lε×>ΜIÌàK_º1š.yîkms<ÁÒP"÷Ñ—}†‰-qï•îâ•iš$“É(§‹f²Ù,^˜œ\æI§Ó‘*-oš2ŸŒ A&C¦IÑÇó<2™ ¿ýío‡ïöÖ6apڧȳ ÅäÛž)qQzù¾aQhº9sîáóŸÿgž93Z÷¹ç~ÇÉ'WÓ×ÐUñ–)=S@ˆ+qD¿.{Ó›X~啸ˆÎÛBôï&%ÑÄA JyÑ@xÃ$ῤ#ÇÙXy{¤wá¦?œ|ò ¬_?˜Ê¤I“¡Ä½3”"ñ¸qÛI¥Àuï–c †«}vÇ ÿ™˜XXdÉ’'‹‹^Å èaðZ)¬XX4ÓŒ}§PhŒ¦±­B¡(1R}§B¡Ø;ª}*£—‘ÛN3‡iÛÙQ-ò½ Œ-. 2»´®N¹mˆžO !¢ø~)Ñl[¤ÓbY"¦ÉÌ3ÏŒR€˜¤-ó»By„ŒéÓ§së­·†y\G—Ív_m“ú÷… 0MsX~£> *+W®¤©©iqñ-ZÄ’%K¢u{cÙ²e¬]»6r ‹»†-\¸¦¦&ÚÛÛ{|7؆hG©”h_ÿöoçðà ^ý˜æËضM>Ÿçýïšÿýß§9øàNfÎìBÓ„ÀÙÐ ¼Xd2è}¯Ïð^ÀCíÖ5\ Ž<Ï+ËOÓx¢(‰YZ[[˶“ Í¥ _KK †QÊg!C‰õ 94gXŽu¨ÙSÛ„ÁiŸR*‹‡à²,vOžV)ɼ:–eE!ÜÆŒ9—™3όڜÈÑó õõ +îOCÃÅP’lyå¸À+&ˆNvöìÈë#MI‘)°Òáß%’!®˜”€É÷Pn,Jžj¦i’ Ë-„ÛÄo3-áçî"ßm_™X$‡úoÜwß¶~ŸÅÈ2í³;n(ʰy..66ZÔ¶zkcžT4C=¶M‡wò £?É¥B1š‰¾S¡Pô Õ>ŠÑËpÛm“€öpÄJ“õ+æÀÃ/d¼tf¤jÏåDÑIω'N­X¶4ï 0ö˜c~˜É“'G^-¥ð`Òã$Þª´ð³Q Äx@âŶ‘âJüXmJˆÛ^–W騲ár)É+<@äl3aÍ@„þš2ÌWr着êâÞ{§«kf2tš›…§‹¢„¼uO便àû>®ëöPŸß3à‡?f6§4Ýô¤˜eY–e‘J¥zäÅñ<áâZ›9óËôvÏ”³êý™êK¼6y23»ºÊ–ËšIÅ äq7?Ë\+²Fl¹NyN•øu&ËŠ‹*Rœ139Z.²Rœ1)÷–‘Þ4V¸ì¡i"ýC½û¶އðh±cÇä„e6”†ùáþÒ᫹«!|}ÿk_ÀÕ4€ÚØ:áþºmÛ×ôåb‚J3po˜ï„ .àãK6ôÈÐ^r6|÷Yñ&&)öîž©£ÓJkúK¡PôsŸû2…B¡P( …b4RuþŸ9–ñt=:¿´0ž(EŽ _Û¢8¡=åöÛoŸ» %™L& Ýeš&¶m÷˜È[ å²àûþGd’ôIP©¯¯gÑ¢E\}õÕ,]º”ÎÎÎè»ÎÎN–,YÂÒ¥KY¼xñÈœ±~â8P(äéì\ÂsÏ­-óDhmm-sñš1cgŸýùä=îGΤßvMšÄºuëzý>…,â‚ ”„’¸€"[…ôj‘·z7ÜaÑr’PBPÉRò„I#Ä !FXöiÄ^ðÀy‡3©e Ûjj¸çüd(‰-Ò<žB3m”é]#E3Ü·|ÂW[ø:f›ÈÓ2û}ï#tÄÖI…ÇUèöêËÝ©‘RΚðĉ'°áüóqBò…8>>I’e9O*å?I‘"Ñ# `e LL5»^¡AÔ£¸Ð …B¡P( ÅÄŽ¿œJq'¼²ëy±`âÁ_D¼ÒdÔ™t^æ¢]]+Ã`þG?­&#¡ÔÖÖâ8¦iFi”çÉþOw;÷p *}Ê¡Db‰mÛ‘7ÊÖ­[éì줾¾žn¸  ã)Ù¬@vï^…ç‰K* o}ëOéMçH$Dy¶]JP?ÐE2wÄÄþ6«RÌDéA±?Ïh¡$$ˆk<›ífêÔ-xÞ3ضð‘°,k¯³2áf:{ûI¤ b1ðNrúË/³º¶³¦¦â÷¥ñq¢KÎeˆçQ‘Õ6Ãõ’À;~øC’µµ4Sʃ’ˆ­›AˆZ·÷ÄÖÂ,¥m$pÿ¯Ÿá‡??› Ÿôùì¦×0ÞtZõݶq)÷´íëÜŒÕÕÑù¡[™ý54 °¯*ôêš9“‹(yÓHIÑ?||lìÈûÄÄÏS…ýR(€…ÖËFr²B¡P(о„¯ËÊ¢P8H;ÑŽ?ŸÊsozŽÃ¦l¸/¶R8C´Çt¾ (Ípw¸r &þ冸ìSŸÂq\×%‘H”…þ—v¿7j’y5a|ß铇ŠdñâÅüñŒÄ“… ²lÙ2\×Ý/Ä(%´3¦³‡˜R Ÿ¿7Ï]BŠëBK‹x MÓ¢ÙùCÍþê9ÒCíÕ%Aåz³ *Ý®M¶lùU”CÓ42™LÚ%ttˆ÷ŽÃE}†ÏUUU4×Öîu=á!Š|ì}Ž’Ø‘ úÑU†A>Ÿï5¬DÐ÷ÔØLòyhk+å:ê/Ãé™r 5)t åùS±x+J$D»7º&û+XY–x µÎ5·ºš“>üámkRšµ§«4ž/e(¯8Ã0˜ØL]»vHÂicưnÝ:ºfÎì×v¥Ü0Ý‘Þ'œ•¢CÂ,*cÇÑ ncPš=fìa8µµµ¯"΄ÈóÍf+æÞŸΤô}Ρ²?cÛ"´^¡ Ô*Çqhmm’}IAe4;5 ‡‡Šïýä@…ÞˆÈÙ¶A Ú£L–Éd†äFn`ìsÜùbÀ=ÔW\†ÒÀ~(éìœÃ¶mÇôy}ùáÑ¿¼$ÛÇcö„(y‡ê‹ifWgÎì^ÌDˆSGò¹;ÐŒ|)½¡¡ÑA4Žôa*û ñ{::66‰ž¤ …B¡Pİ)Ï·`tûK·ïõϽLzôƒ<7å9@!¿z#n0O¥J¢JÀÏó<ÇAÓ´Èn¨ì‡åÈÔ ñ¼2û3R8ƒá›p?h*£™ŸÿüAþþ÷ i`Û6‰D¢_†Ûþ¸ í© ²xTÔ-]ׇÅj8ÅþÍK/½^v†A"1øF¢Á˜Ñ«3´a¸â ×~êênï×ñKú: Ñ€³?óê˜GÅ¢o!»&íÚÀT™T'†º Œ¡1¤£©p£P(t÷P±°È’Uùˆ …B¡Ø ôyúʽ¨PŒO…Ï…;¾œä…­O1~×xñÅLö¬rº®0®†ÆsXµjUôu"‘À0 e›ì…|>å™9‰ÔoAeýúiL*Œm¶mcY}Ÿc­ëz¿ ® 7"g‹ã@m­HVŸNC6+<Ôl»ç¶Ãq Wc9Õ_u#D\¨ß¾‹d2y@^+£þx§ 8ãŒ3x¬ºº_ÛI¹·¿s ªººz,ÓW'Nòc=Ðê°BJPQ(úN\à41IÀUf…B¡P(zÅC<‹ôuDk¡…b$ð Q\“1³6räöÍLxu‚ør&•±ï #k:]6S]Ó4Ž;î8\×%‚ ˆ&Ô+zÒ»øhg¤lŠ} ùµråJV®\¹Çu:;;GäúÂÖ­ÓÖVÀóÞaýrÿ‘‚ÊÞ¶ —ŽI³Y‘ßA×E²zÏ9#4Mx¤†X'•*•áyÞ£jš¹(A rµì>°EΪõà´-cxÅ0°,+ŠÝ8T(ãS9ãÇßGGÇQýÚFÞãúKº6 ñÔ›tYiÿUUU¬þç?9¾‚pcßyÿûã”)SµI…¢TòD11É’- ûåãcc“¡IÅ …B¡8Àqè_˜bQ\-À÷ÅK>Òʹ˜Ž#–©9„ EOlà÷x Ï¤úúÿF?áV6õšør•ËÆTÓ,ýELžßvÕ6²Ùld÷‡R¼1NO•> *ííí¬]»v¯ë555 [ÅûÃîÝ»pg@F[ß÷÷ªxy@hEäE²¬òNÓ0D×ï5Mt®ž'D—W^9ž ð0 ƒlVlïyâoœlVl»/"ëp&é9Pn^Ò;E *Ǧ⣣Óü;X>©“™Ì°¨Éæ°ÒÚ?xùåó[NëÓú"ÉPûhIw{™²{WX©k<~Æ ¬|¾¢Ø’þpÇð¶· qÍýAy¨(}# èÑ4ЀŽN† ž) …B¡ñè{¸/I%«EˆÈ"‰„°ãH;Œ2$#™f)…ƒœD %q%Är)® ) Š}fO€ýQ:ϾÉošÌ¤™áDÉ™TNLŸ 'ÅŒ¥žç‘J¥ð4/Jñ ëúåÎVŒ^†ÓfÛ'Aå¼óÎcÞ¼yÌ;wÄNÊ@ ˜x6ãÆ‰ï=OtÒ¹\©s6MÑ©F)¼XüX}ﳆÓÓb¨åRèJïMÓ†%ïÌžŽ©ToeŸ¯GRÆ@¥‘ Ó4ñ}èû½ æm2¤ R±îÝ>K¦·ºM~á…}=]ŠAFGW9 Š} @€€,Y%R* …BâÓÿðÁáÄ.OD’fŒ (‰)q“ƒaˆh#¾_ž»7äú¶ ÂÆãº%ûš·©x#òYÀïs‡R³¸†Ãï ¿ÜS”r)ª„ µ¥¥MÓÐZ…íN…•câûþ°Nêï“ bÛ6k×®eÙ²eѲ%K–°páBêëë‡ÿ,õÏùJfÌ8‡ãeÀî^©Tj¯õaè“3¹ önï5ŒRG=ïßf2s*¬_?‡_ýª´ÜqDG›LŠ™ †!„XßËZ[…×JˆuAtÆ™Œø¾è¸å `î\aÀ~öÙ7ãºb]¢ìÒ ÌÓû7øH#¤‘º]Éße(o˜êf<8x@Cø>ñxã<Îâ,ÚZÛ„)õNéo-GÃâb3 ¡¤èÓ¨9 òÜû rÆÆPbPŠ_j‰b²Coô´!„¥BAü½þú‹y≯°víѼúªXWÆôü¨ ¯;pT >›¦èÜ-«T®ìðuž `y 4»b½dR¬÷Ê+çc›X·®&ò±]"Q wfBì1€Ðu1cCzßärbÝTªäbŸ!"K6«EaÔL³tLÍÍ¥rl[¼—žÒ}×÷ÅòøywÝò(ŠÁa*°î/5Œ©…ûkogá™ K£Ô¸õ¼™’R@ÄÓ³b/ *‰Tš~ݽ8\¸¸Xýަ{`bF¿sõ÷áDnÓß3nS£ ÄOœëÃ~ƒÃ>{ŽØô)Æ‚ƒƒ…E-µèè´Ñ ŒÂ EÈÞÚlG hhøøªí( …â M_'t¥Ó%û…i•˜¡G62i»IQzôŒžVŠ+’dR¼r{{ðQ(d»zÈQ;u a«hŽ ~yóÍœvÉ%ø¾ã8hš†ïû´¶¶ÒLóHšbq]·Ï¦ƒ *ûB{{;ííí@ϼ+ò»úúú}kš›Á²DÞ”átû2)uÄ>¢ãqo²L+Â,'âÿÏ·¦öƒ«™üÞu4stÔIkÀ¸l@Üt´°L˜lÀ¦™¡»)¥‰úr=(b¾ûÝZ@cæÌ.2™RgÄë[`LB d,ÐlV 6òyq>S)ñ]"—¤aW üS3!­­R„ÙÄ~p4 b°¢ið{N÷ ÈÂ/r¥m\·$†$bp!óËxž¨”–É6òÍo^Imíj@ì#Ö#›…–±,—+Å9•ÂŽ´%Ûvø;ù¢ìLFl+c¢BÉ ·³sÍÍ%ï)úL›6,—Õ°°§¶ÿ~ íÓ ÿŸ»újÖN#6!Œ¯ñxRY„u¼#Ü@ö¢zö¨&ÂZoSêxÝð}7Ë¿ÍàUq¹¿‚Ê@¢û¹¾A¹p“§äÕ´§m¤wàÎP¶OÉ€<¹|Ä'°>*©ðŸ††‰‰ƒC’$I’û}õ(#Ëpm»cb’ O -äÉ«¾N¡ˆ1}§B¡CÑ>÷SFç¡Òs9ñ×¥ò$-ùxÙ(·¢s!m é´°1 £MP¡¨ÈPŽmƒðÕ…XL?W˜€z}Ž”8à¸ûîƒK.A×u,ËÂu]2™LŸö«8p±m»OùÏ“aT–,YÂòåË™7oíííÔÔÔpË-·PSSÃòåËY²d óæÍcÍš5,^¼˜… x_†!ªÜÈüqÛoo÷„%q$ûNî¿ÿÆl+÷þ¿RG-'ûʈGR0ñÍ€ LȉÏaY)„Z‹mg#nPßÿþdþö7—߉=‰pÝ‹ò„·3±OIØpqÿ’ÞïËÀlJ¢Ä÷¡£ãT|ÿ×@7×UÖ³ZË  ¦YKº…CŒ¼Tº{îù¾9@lw·M¥Ê!2는e•‡\“å¹®x$ býO<‹çŸž+®ûÉçKBÏöí朗iû°\WCÉžÚ&°ÏíSžêª—fÂذuC©HaDŽ€årIoÞB„Å]þÖ2¼¨£ÍM²dGú Õƒ q_Œ›óã¡Ã‚^¶}G2ø uûŒÓïî.âGÊPúÁÄÓKQqÑÆÿ¥Iãà £ãâôÉ0$I'A12 ÅØÖÅ퓸Yce(Dž_ …bxûN…BÑ?†ª}ÊPì•ð<1é2‘(Ù(¢É§=-J[ˆÖ¦¡À†ÒL'=Vä„ViÛ°T—®†Ón[ã™týk/+əЙ O>ù$ÿF)¼“ëºèº®B}½‘ÂÚpÛþ‡UPioogéÒ¥¬X±"Jpoš&Ë—/gÑ¢E,Y²„n¸¦¦&Ö®]ËÅ_<à°bÂØÞ9¬êT#DÅ'ÒvÒ$~ÓG&M*bïe¢f ‘>BOÀ'|¸ÑÁ§6i9QJ9¼SòýªçT‘è>,Ë¡ªLn“ÿ¶!Ä Û&Ú¦9,OîÇC 8²»Z^BG̙ӉOm$ ¹á¾º›¶5M š›ËC—Éï*ÝujjÖÑÑqjŸÃs™fiÖGw{² GDzÄÀëé§aóæÛH¥Ä¶²,]‡ï}ïö>~t³·¶ ìSûŒf m¯ú…àݳ©4:Õ)] ýíÛbï[)©‹©RY*wJOFkn îMY§$¨ $ÁäÀP·Ï}&@üH6%WIÙèû‘L'JcéðŸOš42èè½ =2)·B1 娶¿y…LLÒQÐY…âͨï;Š70CÙ>}èõÉ/Êó£Ä‰ocS. $Â×P÷°ÒF‘J‰ð_Ž#&{ŽÒÇ6ÅÊpÚmŽ`ìó¯ó W^Á‹ùù>3fÌÀuÝ(-C&“òü°ŠÑa#bß:¸¯+¶··³dÉ’èp×]w•-“Ë÷TFSSSÔ(,XÀÖ­[Y¹r%S¦L‰\ÉæÎËܹsY¹rå€Ì÷¡ºú±Qk4ìÎ|^ym2ãö`L–Éßå­ÂÞ­—ò³˜”ÞÇÅbËS)ÑI†øÎ¢$º”Œ–%ûv*%DË* 72Xœ€ìÆÊÀ€šš6m:„™3»¢ôò¯’<„0Ô–e¢ný¹ÖÕÝÎäÉwíq›î4M ¦úB&#„¤qãÖîñ½®Ã‘Gnî×o=ÙSÛö¹}JñÍë£?cw?":À4%·)ªì+:BX±ÃWˆÌ£¢Ø¿0)‰¶Éãr 0ÔísŸ‰'“j;ˆ#÷²hhxx´ÑFž<-á?›€ jÏÞ^ƒ;(CÇpŽmû‚†F-µ#}ZŠgÔ÷ Ř¡lŸñɥѲ@Lª”9\÷´-”œ­}ý@‡™À¾P(…>W(†‹áÛ.Ð`ÊžÂèËœ¹XË_]×£´¦i*AE1"ôIP‘qñÖ®]½šššhoo/[¶víÚ=–ÓÔÔIJeË¢ÏÜu×]QÙÝÍ)S¦D1ûzcóæÍ…]‡×_z¿T4à, &÷1°I©ÃOPC J³)¤Ð!…¹¾ôæˆüN† “I¡#¡Dáż°l‚Ì¥4X±⌉°‘wUW³fÍ+ÜóÊ ½R¨Ÿ4 ]y%æ•W’¦|öˆŒ@“è¶]_Üt“a}¤mÐþ÷ðéšüp8nXNÑÙlذa€¿øè¤{Û¢ÙBqúÒ>ëêê˜7o"T¶id³pØa§‹Yò‚ ä^Àæ‡LÜU.ü•7FÒ™7ª?È™3ÞöÔ1Xí³ªªjpš¤Hø€êy,×3 øòF/“ví%ɦAªÛJzø/  •V<@Ñ(åJˆ‡ ‹<(·³WÐÈ™ë•ÜzãåwÇ‹mÛÛ:Ýg£,¸æ ¶ÔÖ¢!)Ðæ©‰ÓнµMxû¬««cîܹQR?Imíjñf¨GªÒW»ôí:^£G"\¢ä…&ãÜÉF IJ¡È‹D‰0#†Ùío_¨©©¡©©‰¥K—Žtõ…ÁnŸò¡³Ï¸`¯Ä[))ÊaΔô3⯜Agpÿý]TUiV—Üú¤r¾4OÃ2z>õfÈ …ÿ$¢¼)*GÒþG}}='œpÂáAC3¶^7}Àõ±°".(åb±±#‘ÅÀ MšVZ£ï¥©¡‘!ƒM–, ‘¨™$IŠ”ZPššš˜°WC9¶U(†5¶ÝûØvBSU±ež'•Ô^&óÄÉ0´ÉçB.'„”æfaWö7ŒºméZ8zœ’‹•üQ³”»vÉøv­”T;ňÑg –¡lŸqz óã‚·Rh# ˆÂéù?÷³¹Rˆ)ò¡.™ü4»vK\LvX.¼ÚòWN~ÓÉR{ˆh—ñЋÒåQCÜœÛzV¡{‚Â)F’áÛö‡lìÈÃÄǼTtt$pqËÚUwq2þË’ÅÆ.óhI’¤5šš-´#§NŨb¸úN…Bц¢}vŸh)E‡¾FÏÑs¾ŸçyA€iš<øàƒÌ:ôPÌ9sp]— ð<]×q]]×Ñul6‹eYÑ,z™ïA×õhV½eYø¾ÕׄM9ŸÇ"C¥Ó%1AÒ]Ø¡Ââç!bë ;uˆ÷†!„éý"¤MÛ²„§ŒiŠm|¿äAãûâ{Ï+ ¾/ÊŠ›¥mÜqDY–U^g¹Û™¦X/•ë¹nIèïG¬'5“ÛÈs Ët]±L×Ų\Nüõ¼’P¥ë☲ÙÒ> ô½DîÛ÷KÏ?–u*×\s`LHê±­ÌStppîj8oA0©|¥d²tц…ïû˜¦I"‘ˆ’Ò+#EŸ“ÒéK_bùòåe ¥©© ×uY´hõõõÜpà {,cùòåtvv²`ÁV®\½dÒ#™äDÜÌöövÎ;ï¼Ø[Þ²‘êê#}~ûL%/Ž¡@&ûÖmœ¯|¥šë®›½×8¥Ý¿¿N{>ÂÞ=[©Iå0B~…õ¤=ý@½eï©mûÜ>Ežž€ñ?|…BÇðå6’±ëâÈ\2î\’R¬9ƒ’‘Wª{2éB1B uûŒ£÷â6<Á ÀO)Ň,@öçp饯póÍ/†³½ÄÔu]~ô£ÓÉfáÁgäÂ×»H2üy쟅»¤|°j@ÜtÃ\GÑè: ”Ô~‰í#*åméËzvH²ÃéqrX7ÅÁpŽmûƒ†VæE¢£c…£¿)4´èóÞ9Y2d01i fš£ü+á¿Z°Ë2Ε9[Š¡f8ûN…BÑ?†£}JÃz[[_×zŒ‚}ß§¥¥ÇqhhhàÉ'Ÿäúë¯ç ƒ"›ÍF“‰Óé4†a i®ë’Ëå"1EÓ4ÇÁó<²Ù,¦id³Y²}Ì:¯i%Û²¦•¢ %“âB(I&¡±Qümhb‡\–N‹—ôÜÉfÅç–±Žãˆõm[¬ßÜ,–{^©<ÇbB2)¶O&KŠëúG,O§Åß ß».ÔÖŠ÷r;)ÖHaĶÅúr›Tª§€"øIO‰aˆz뺨·e•„]eÉ¿òÔçr¢|ù”E˜êqº.¶1 Qwy~ëêvÒÕUÅþÎpŽm_÷N¥ð-`rÏÜG‘"S²|ßÇu]UÈ/ňÓ'•µkײ|ùrV¬XÑÕ«¾¾žÅ‹3eʾøÅ/²bÅŠ^Ëioo§½½øÃeË-ZÄâÅ‹Y¼x1W_}5óæÍcÍš5,^¼˜šššØ×¾6‘‹/Þ¬ :½‡×L4†'¹Z\É7û§Ç£”ï¥/˜ûôßÞ-s²8ôÌÏÒ›hRÉffëfÍ¢sF%{k›À ´Ï-Ï×»†ïÀâ1ð*!“înJ2ɶ\§{’…b®ö ½ *žúûÀ¿üЛ+&¥Ú´éZvïÞ L§¹ÙÁ4M|ßgÆ ¸ýölßþ ÆŽ­aÍš3øÚÏ&rÜ»b®óâF,•q¡¾ŠA†Ü‹'·w(¹zDm×À(u) ÑfÝp{éùR@ˆ3™p{î¯(RòV“bkk¸O#\_ºR6†ßÅ÷)‘±+GKðmÅ2œcÛ‘BŠ3 4ƒ¼JQÅÆÆÅ¥•Ö²D÷-´``àà``Dy\l쨼¾ : Å@ξS¡Pô¡jŸq¹^zaôºn8 H×uÒé4¶m“ÉdÐ4t8ÈÕuT*E"‘À÷}¾wÄ\pùå˜7ÝTVV&S9æ…ô>Iu‹9&gØëºNKèFcšf¿'J™cŶKBƒôÆ€’ÇIK ´¶–ÂôÆ«É!"—+mcšbÌ.Cd¥Ó%O)(H‘!‘û—eÊ}†yÄ£eº.Ö³¬ž! …Ò2iK‚òí»—)ßÇ=cä~âẤW‹|/O–)‘-qïûL¦r83ËÇ“HÀý÷?Kgg¿~ÂQÉpŽmǹ§ÂŰyçf ›—K>/.Â|É‚iº®G` ÅHÒ'AåÎ;朗©iqñ-Z„mÛ¬]»¶×õdãë… ÒÔÔD{{;õõõv¹ö}˜<ùµá<ŠnH±¸¯b € -%›\3BdŠçžéŽLÅQ)WË£Óç|´°·¶ ûÞ>vŒŸÍQG=AGÇHqHo‚‹ Å©E Gû¬HþÏÀyœƒÁÊC0'à=﹃7¿ùƒQBÌ–Ÿûîsyùeƒ¶¶6Òé4©TŠü$ÿïÿý®ûN‚  ººš›n2xÏ{6sܬgÉ;¾å£Û:d`çµ;yå• \?ïe®õ& Ï1é±"rÒ!CŠ!Uþ $]0Æ€yh®¸?»àð úZИ‡"Ä• x뀛AßÁÐ}p@kCŠ8 :™Dù9DÅÁPm=¼%¥*dø¯8&fY•¸ ›!C#¤HáàDùZiÅÅÅÆ& èQ¦B1XŒXß©P(öÊPµÏøóºç•ÄJ´´´–eáº.mmm477£ë:…Њîû~d´Õu*4KYn>Ÿ§¡¡Û¶#cqoMÏ2ÄK ñÍdŽé¥BL‘6èJç¦Xì}_º^²kw·cKQ"¾)dÄוï{ËiÏUR)oɞʬ´,.€TÊïÒ[n)Tu?ÆJhZéxþñÝÜvÛi|ñ‹ì× —Ý`¼u†y*ÛïÛÞóKyáÆ~\Ûÿܳ€IDAT¶ ‚`mÄÅUchÅË€“Ò/\¸Înòk}}=[·nݧ Æ`Ö÷aüøGUL½Dº?öW4Žâó÷ÙÏõuŽ£^á³ôRé­ª2Åô[RÀÛ¦OgÛ>^÷û ûÒ>½g<&wœőݯPÑIûƒe òÓ™¼ïã0u0pwp7O]û6¾øE›lVÄŽÎd2Q»–Üæææ(Ôœ™÷“Ÿ¼ ]¿ˆGþüUÞwÇnžzý>µäËü÷—Æ1cÝÞñõ©\÷Òs ¼«çƒœihÛ¥99SÏ÷ËãUËÐr6žŒ-ÃÈ0 ’B¡_ÚóÊ“sÊÐò%ãH˾]ÎÚ“ë&“¥ºÉY~¾/öHˆž'¶/Äç3fqä‘kGºÙ m›ûÃÃ`o9S,,Zi­˜¸^æqI“V‚ŠbÄQBŠB1zHû”½R%ï×uq]7.r¹Ùl–\.‡¦i´¶¶–­_é™u° 5M£££# eä8 …>Û³ö$>Ä¿SúûŽa”9Fô‰#ŽØÁé§?“e·w³ï\ÿÃõŒoß§uâÉ¥P }T¦L™ÒC(éÞx:;;Y»vt<K£€jh#‹LÖWRá¢?¦v£Ûß¾â!„›¥H.2Fwä0¦·ï.ûÝï˜Ü´¿ý>þžõ¬ßň **n»BÑ;Ax—svÀ–Âûç@p¯ø.ómÀ'ý0;wv²víeÜz«ˆ­ë:‰n ³|àÅÝ»£$žò°P(D}óa‡}1c¾ÎÿïÛìÞ=‰K2Ÿe龋w,Gµ½Ÿª¦*©}üá,fUÿŽÍ… 0çŒÇYÎýào+ –·ŸÊ![7q×ÁcwÙ8&­^ÉÄ7OdÇcX5}:S/œÊ´]ÓØ~Âvþ0ïÜ^ucËS§>E£?ƒÙ“wó'å=[vñŽÃ¶±ùM›Ù¢m¡0ÿÍ0¼ùà| Üк &¢iAt"ãÁJ…ËtÐOãrð¿ zN¬—j€Â­âü|À· ô§€5Ðø%0…Â:±NCXÍ`®ë-ˆkh—€‘o¯¾Œðœ|¶´íço9ûtªN©ŠBä¾L€d3䲡3ô“ÀóÁsÀ•!`G‚±[s!‡èu(ÈœT1\W: „–¸gbþ¿àgm#صs¤/{Åbìatf`DÉísaò2¿×°ƒ …B¡Pô•J©‚ ™LbYétš|>¦i}öñì?T©óäx:‘HD!È”ñxÿbòä×8ôÐ7ÆDÛÁÁçÕüYŒ­Ë ‡u1!öMoÑÖãmW¡iú$¨,X°€%K–p×]w±`Á‚ŠëضMMM M£À°lš°råo€óGº*oX2™r—Ͼ`2°((ýÔÈ\-ñþÉØw•nÍÊ ?päxÖ«ö¸ù—yËÅ+Vë–‚© *ÑxH¡a<÷Í-!HI’v¾÷½øùKÙ€7þPøÐC ãVÅ‘^½ÎˆâWÂ…pøÏ¸Ì(¬áo¯ÿC6×=ΡŸ<”;¹“ k6ðµ_¯Vó“9ëçPwH>;Ñ?¦³åW[Èy.yø:Ì×xzöÓ÷ìqüîÈßqÜ+ÇQ÷È<ž2žâ™_ÏbÝÛk €ìç >·‹ª›ÀeˆYç'xDaÈôKUOnìx†“_ŸÂüc烩¸;¦ Öz0^-f,´šáá€e ÜnR@4 83¬C’RΛT¸^:¼lñ©ƒñ1±Os\¸%¶×¸ìà™ü¶iÊH_öû Ýó½äÈ‘$I -á?#X …B¡èrÒ¤zäÚ¶M:&“ÉDá½2™L¿D”8ñ´~C‰eY466¢ëzL +Š:t:'u2v×¶ÒbÇÁôý²ÙÙ¾ïÓÜܬÄŨ¢O‚J}}=‹-âꫯfÑ¢E,\¸0òP‘ ë—/_Î 7Ü0Òǃï‹d[š¶Ó¼~¤«£bd®áþn7«ë>wGÀ~‚€p6Ï6¨[%Ü#2¾L|°ë8åIy<¯ôæž=—uëÖqögÎæÞ{ï¥Ëìâ¤÷œDÓeMÌþÔlžó0]c»Xvþ2:Ì&ížÄ÷ú>»¾µ‹éœŽy‹IÍ—j¸Î¸€ºMu<;þY^ûÀküýûÇ›áñÖ½•;o½“KXHøý½ÿâ‹|wÆ·X™^¯ ì úlYf³úu¢ìãöÇI$\ç\G>*ÂqÑÄ&0øU,Çsð\´›fêQSéÂ6ùò² ¡õ0Ï.%Œ°våZ6¯Ü8ÿ_ÿâÌ xÇ>Àºš&ÜvóˆœÈ î¡2Œb,7 Þ±hµ@Û–-hS§¸nñ°bÇŸ<Ο€®é¼íÞNž¨ÝÌë/Ná¼I‡säÙGÂÙáF2!¥)îì5ÔÀ?ÅßÂ9±¸~·q³út¸Ot~rÿOa´]ѹçi§ÓzÌ ÿIj·Ô›ášÂ5A@6›å[áë.á’žî‹4ïÏýˇ®×«˜vc'Ÿ>áÓÜjÜZþ;…Ô¾ïcÛ6ÍÍÍ´¶¶–ÍÖò}˲Èf³‘A [r{)dyžW.z…·S×sI§ÓB´±LLÓ$“É“§82žB+»¯kXsíjœ«Ø°{£k:žïádÎ;ï¼Á»xp䈶‘’Þí;)fJ=+Ý%D’ìLÐëçbyË…tA0Ì"8ÏAæApN‚ÚC@ÿä6€ód? ‰Á˜'r e>ü4¯‡`¤n&p,dvSHõS߈çQÉ‘£@<[X‘‹‡‡ŽŽ†y³¸¸eùf‚Ø?)Î ¸ÿW( Å~…ë {PxQhZ™ËošÙ.Çf‰D‚ÚÚÚ¨î¦i*AE±ßãs€gOÞ@í#µh;ŠÐÕ%lAù¼PEchš†aQ[î :V1œô+)ý¢E‹X´h+W®Œ–M™2…¹sçŽôqDzèV²kÿ˜Ìž “e´yžx‚ÍdЂ€ƒgÍ¢öCBøaÒ6;Âp¦ÂÁrÎì<¯¾²…#>@0ùÉ‘/wmÜ0 ²Ù,°—‡ñXýŠË®¶ñPÐyöüg™9³ Ã8³ç.B9.Š444DFY_ Ì-Þ¶íÈ«¥¥¥…T*Ecc£Ø}J"‚èXÇ!ŸÏc®ë’ÍfillÄ0 ,ˊ´yžGsssYH MÓhiiáÅ—ÿ›`ljüêWŸgçÎêÈcÉ4Mn¾ùæQ1g´âââPOät‚æð}"€ÆCÀšÜ é³!µB ˜z?x·ƒv ¸_€TXÞ° R›Áû $ß ¹µ`^)ÆA9À Ù1à.“I¼iž&ôÉä5 ? ÖZH|š?z¡îf‚û-Ⱦ Ì.H}Ü«Áœ)êí!ÂÉEî3{@z­dÈ ‡ÿ@$³÷ñqp¢÷24ÓL†LäáâQšT•"E1¶"L†ŒšÁ¨P( À×áÅ惡ùÑ8)±!£GMÓ¢Ü*---ÔÖÖ–å%T(öGN^þ­QŠ3gQ2 ù”â¬ôvxòûJUóbßiDy¢©þ^ì½°|õP_–ÄÊ‹±äf¹®N)~ aÙñíd0b·ÛñÆëPrá’Ëâç‹}Äö#m^Fì½^¡Üøy‘ex#´<?ö½<&`â«çx C~ò÷lþÔñìîÏÄ«†î·6M3r5ß#‰C£ºº ¨®~ ]ÿ·¾†0¸mÛhš†¦ie¢‹$>£Ë²,š››#a$™™Ää‹çye^/2)j¥n†aÐÑÑmÛØ¶f‚5M“§Ÿ~ 8‘¹s7’Ë•»çÏ›7¯l‚Ž¢#SlÄíNCDW³ÒúÉàý²gC~ âÞgö­P̸)¼׉r ã@;¸Üj0ßY¾_k:X3U›R~;hœ/®Ñ¿{ˆ$7IJâPw;žKi !û4©Vµ„ëËŒÇrÌ‘¦Ô/JäxÀ§4¹#þ{Kצðw!–a‡å¶Ä–Ër³±ýhpÖgñZÓkƒzM+ÒcJCCGÇÂÂÆŽÄ?ü—"E@@#ÑúAxŸ똘*Ô‰BùõÔS¯qÓMéý*ÄW_‘ã½ææf‚ Àu]t]'NGb‹Ì³"Ey‚ À¶m,ËB×uš››ÉårA€çy¤R)<Ï‹Ä9¦“â„a$“ÉHàI&“d2\W<È™¦Y&~8ŽƒeYeÂI6›êèºnÙ÷ yPò—â˜ã8$‰è¸u]'›ÍFÛø¾O"‘ ›ÍFû”"N¼ž¶mGßË2ÇÁ0Œ¨L¹OÏáãÇ¡££ƒ hllŒÆ½²Ìl6»_{C 7ÏkK¾æÃê?Ák' ûŒzý¬PŒ*Šû9W\qEÙçTªX\¸pi1ŸÏÎÚŠÅ¢V,­=¯f‹ÅÂHŸ Å>S(ŠŸ¼?|ûÛß.>ðÀ#]õQÇ Å}æ :²Ö4­5M+êº^Ô4­hYVԯ˾^þ•ëE]×ËÞÇËè¾n÷÷•^Ý¿ë^¯îûªô}÷íãËäöry÷¿ñm*}oF¯eö¶Mü½išÑx§û÷—^zi1Qé¹FÑã¾e‹Å9WßõµµÅT*U,,]Z4=OØ[:Ê´©Tª˜Ëåú´ŸT1U,(ˬ¢Ca·= =T6oÞˆ®Ÿ28jˆÙgÍ#}dŠá@y§ Sº^b÷îUÔݾ6l(y‘ì+aþ† ë»Ï¤ÎçfÈgD’û¶6±<“)ÕÃóz&¸÷<ñ ‚ÒK¢!f«š¹RÈ1ÓìY†®—瀩4âP€æfødlJk_ÎO>/‘† )È2©mm4›híº•¯ßJTð°È#&I7_=ÂY÷Ý’bÛâz‡i°mQžãˆ:´¶F׺ïûLž<oÝ/1ç||dO¤EÏYéý ³s® ]]3Gö8 >á@œ!:Ôt‡ï­ë Gz2Z”{MK¯‡Ø2Ïóp]—T*E2™Œf‚š¦‰ëºbæg $Þ‘ •JÑÜÜL[[žçqUú*‰Òr˲Èd2ÔÖÖ’xÛúhfªœešÉdH§Ó˜¦I.—£¡¡]×1M“ñ÷ŠD|ÿБ®Æ°`YV”ëNzz‘wHÜKEöÿñp[©T ÇqÐ4T*yrÈÐXº®G-Pòbö}¿ÌkCz—ĽG¤§‡mÛÑ6rŸ¶m—y‚H/MÓ°,+ú^Ó´èØ¤w‰a¤Ói2™LäM“J¥¢íãeÊïãuñì ë.·‘Þ6žçA´Où}÷zÈó-Ët]—Ë/¿\…³í½ÝLü‹Î5ÿiÂܹðòË#‰$ õ,¡•p‚йw†ñE± Må,äqz‹óä@ŸDÆóßC;VCÒýˆ½ü–ŠÁÃÖãrìÜ:6lö8þúAŽóÚß^R`èí»8š&D Ç)‰*•ŒÉº^ÑxÜçïå:–étÿ„¦¾†K‹[_oVR$ê^wß/}'C·u¯³ë–¹êöؾ»=‘(ßm—ö#—wßG2)¾K©ÌGûŠÏ3èÔß—þ(Œr×ÑA:™Äô}Ñt]ü®{Ë#"éEx £ÑH˜;¾^KKI0‰_š&BúYVë*ŸÏ“ž€~Îèܯ¯‡ÚÚÕlÚT͉'ÞÜ4ÒÕdèEÿx˜^í ÂIh4ÝO§ /ñeÎn<› H¥Rd³ÙÈè sâ444D†Ïóè˜ÚÁ©Ú©˜¦Ikkk:#™LF†ŒÖÖ’u^†ýH$躎ã8Q†t:ýÎ…B!Š'^Ýx+“^›Ä{ï÷o¢$•J‘µ,‘Çç'bûts3¾ï³ã¯ky|ÆAL8åÖiVк“Èã–a0åõ×™xÑEØß®ÂÝ ¹g@›#NY$à­uåiÉÒ³ µ$ƒÿ5ð«d·(Lâi4ar""B–A‚ ü ¼ýöÏœšâ̰¬÷QÀ úñb¿ ÈãN…·NÕ¸¦®ÿnŸü=.k§T°“]¤9×Jq:÷`ÐEšò,DÃxXŸûW„™5bQ ÐóâñF½ŒÁrÀËAZ+Eì”â“8®PP Ë´Îã àdÀÖJ‘95àÌk6ó±CßÉ}¥™f‚Ø? 7Êá#sûT/LLräzˆ1 ÃwihQN îËAäb±Âñ}¸¸Ñ²Zh …(g‹]TØ0ÅþÎÛÞ¶‹ÿ÷7Æul†aD‚G<ä–aQH*) È\ úS)`È>;SáT†ˆ…’€'•JEŒÜ>žÿ$žÃO¾ç¶‘c‡ø²xΘø±u_ߦÒ÷ñe•’™Çe evß^‰)}§‰Ä&ͬ<™Ìu]’É$ù|~ϹxŠà€TGú(Åå—xˆ'#7ØGÄ!N!Pãq…eâi#ü^f,—÷X‡Ò,ï£Ù”ö›dŸgªŽ*dÜj;Zæ6ýIo ²û‹Œ—=XÄ“TKlJ3ø”¨2äø;áÑÜ©óÛÁßëVΕ²'ú™›]¢AŒÉ!•"Ápáºâ<{žud~è™Æ÷Åv{¶ËðqKÓJFq)ˆUò¬ÙÛï$(Ë*_7V·Ã¶m¾ó¹Ÿóòvããñ¹åóŸçŒóÎðmq ¤Óý»þ÷4E”š4¢+Ñ=—+ÑâeU*Ï÷1tcýapÉ©ðm§² 2ÜI#À±Çn§Xìàï_8ÒU¤GBj?¹F‚çNxN¼Yðˆ{¤t;•rƧô±,+š¹i Ñù—3Es¹žçE3I¡Ü(ËåzMä7’Ä …B!*#žÿç†à+Ly} ÑÞí'‚(V¹4èäóù¨ü+~¿€ÛZ[ñ}Û¶£x옦Y6³tÅÍ7ó·ŸÞAû˜qzº®£i ¶®ëü×ý-ÿùŸQÝt]ç”·¿¿½ÙÂ3¯ºwóæ(^ü‰W\Á£ïz¯¶4‹TcaµþÜsÉ\ׯM_}uŸ½ˆôš5ѱNúÌgøîI'Quá…l8ôPnºåþ»½'ÝBú¼9áù¯óžLç¤IÏsí»¿Œõç+øÃyE^Ýýõ/|ó F~<£–_ìœÇÞ6ó»ü¼¸‹÷?r+v¿ÈøGÇó›ßü†ŸþòJ&¼r>úÞ÷¸àÌ3YÓÔ„,?i&Ö¥“þ²¸D4Ïã§›61ÏuùÜw¾ÃîÝ»ùÀ~Dcm-k/¸€G}”÷`ðwo _=u'~ákäæÏGÓ4V×Öò‹éÓá5•Ceo¸áƒf+­ØØXXxxdÈ”‰${)¬ >ñIÀÇïQž†V¶,G,Ylì¨~RTi¥ -ò°ÑÔ“b?â˜c¶½¡g³w2â@|‚‹Ì7ᙣKße³BHqñ·P(/ÛóÄ:†ÑS„q]qÌ•ê"CÁýॗNaãÆjÆŽíêYyÚ‰êÕƒõ@0Ð ÜM)Ñ|H‘ÐM!gªb÷p)²@ÉÃD®'ºv§71Å0Œ(Il¥ï*ѽüx(‘B…¾F×užùÈGÓÙ‰ö‘Õ† 7AN§£ÏñµŸ:(€?¸är9Ç!ÚÚÚÈf³\÷¾÷ÑÖÖ†®ëQâÝß?ðÿ÷mt¾ÒÉÇN<í¬³ð}_x¼¥ÓÜwÕUäZ[£ºš¦1æž{¸oÁV}Ž\zi4X&ùm=²Ù,×^t†aðô¼y\6cù㫹úõ•øw²¤f /?ú2+s+9¤®Ž÷Ö\ B§ ’ãþö¦ßpÍç·³–-?¤í‰>>¼HÅÀ †(Œ˜O‚N&ÌÇÇÀ Ï0MŠ}$ ££cHÇÞ¾¡P¼áÙxvw/úµÔ«‡J*•RbŠbÔrÀ *ãÆmÇ0 ’»“øðI<™ =!ö¢†µÖÂÜd¢ÿ·Ž}‘¹ÂDû±†žÒ…1]’CÛ+„TÀ@ˆ-Ò^Cá;BŒng!â™t/CÆ*a=* ,Iå1÷D!"¤(åw1(yvxáË¥ü!Ü ·Í‰M=Ê•Þ9tÛN†=“<¥ðòÜÄEƒ ;¥0lvXgY®–cwÛÞGÉÎÐcf&-á~»{›á1¶Å>KñÉêV)Šéaùép}ñ`qá¬;Îâµ&5‹ohpÓ}«øî;w þLq«.M2´A¿9BKy46 ¡c((ƒ‘#goH/•^öûç˜Ë‡¾û=¿|Õå[ߌ½Nè&étš·ìØÁÁßúV¿ÛXÐ(uSRX‘:wŸî†Qî-o£‰„¸Ö‰òûŽï‹ÐbA ®•øC·Yäûîm$M*U i†#¢¥E|î¾M2)êßD9òÚµ¬²ïª««ËS†À3MQ¯\®ToßÁw(!e`L~a2µ˜è«ã–2<—t:‰mmm4‡¡²*…³ˆ‹ÝC¯ doÓî"L_Š7*„›Ò4­Ì+Fbš&“~ýkZ½ýòËË<¢¤§Ž¬·¦i˜¦.~0e“ïúSó’ÉdÊ„@¤sÅ ®_0†q¿õ°.¹¤ìx¤w‹¦i$ lÛ¦P(0ëî»ù‚õoœø³Ÿ•ïç]=‡´’OýøÇܼðPŽZ¿ëØËÉÔ‰ý{x´?ÙÎç.ý¯Ö¼ÊǾú1n¹í®Z}×m¹–ôû`Ɔ5<õõ§;v,»kvó=¾Çø—dz`Ûì6)R‘·Â=+:¹ù»Yð“0?øæ²ú]ÿ裬{ñEšú}…¼±pqÉ1„žË݈;ï+2$™þ“$H%‰.iҴТDÅ~çÁÔ©C+¨(Š}çÔW`Æ«||åo¡Õ)=Gu£¥¥…¶¶¶~–®P œ rÍ5O°í‘Zœ³rµ9²s³dnÈ€Þ‘-iÁÀ@C£ùâfô³t-À̘Ñ,tÐ.nùÌ" !‚tg%ëƒ0þ›Q%GɃ"Jb®'CiÉD£PzÂÚÓsn|L›AR˜!¬£î_Š-^¬^B4‚Ž ²ÜBÏœ22Ù%”îB‘NIP (ÂãÞ<òܸ”Ï»ë긱Ëà£ßÎ{I©Îg¼‡÷|*àÌÎÄÂ⑵ùÅ™3¹ê/çpÉ%§E!šll̉&þDŸë¹ž,Y\\ž9ûì~GÖÇ&&]uä»=0Já@zƒ8›£ZQ!AÉ["n#Å•|ø>¾^÷ BñçÄD·ýË\':åB„ôÂñbëJï”$%K–&ŒØ¾d°ûî±²¥çˆI¹̈ýMÅöwKO”¸0%—KÁȦä¥#ë¤lÊ…¯¸('GO1F–‘Õ/îU„Ç TOžô$Mjß^yó¤ âÍ ÌŠÇpïê/Æ(ô¶‰ÿ®žç¡ë:¾ï—¶‚ @Ó´h&pÊ xØZï½t=¦9Ûv*ÎtjtD÷&}J·`ÒéL–ziÛ>%gÒ2z;¾¸à¿®4Mˆ •B}ÅØÝ¯ÅD¢$Rt}7òFÛµ³qc5-ãÿÌõ¬[%âû!¼t?ÖLFˆ"2\Y÷ï“I±<.”AI2ŒòÜ6ɤXOŠ<¹\ù9õ<±?PŠFRÓ4˜7o¯×Ä JajCä=²·ö©C¹·§ò»_Ç27–Ü*¦iö»ïM¥R½† ÛSÝúë=÷Bé+¦m÷ë^§ic~¸_¡$ Ãàõƒâýý0˜¦ œ»— 2™0Àg«.ãi‡KV™<Î’㟸¡ü¼5¿á½ÿw}ú®h€€—ÿ_Ž´½_çó†‹ÛgAÅqJÑ']WhìÒ¹R×Á4“8ŽÃ±ÇêÀ |ýëoá±ÇæÒÕõ–È[*LÓdùò—8ï¼{yæ™ghoÿ_þò%tv>Ãu×Õ0yò÷8úèÓÙy÷Üð1vìø1¿ûÝeÔÖþŠ1cå°Ã¦3~ü{7®½Ì+Iz“Éö'ÇW¾ïóïgü;?Ÿôs iD ÿéè´Ð]_òsž¼s+FσÇ{ˈŒc Eßéïâß÷9Þ{ù<:=S)§Ói<ÏS¢ŠbÔ2b‚Jgg'[·n¥¾¾¾ly{{;íííÔ××÷ønoø>LÑÆ=¸‡ õ {®`@ÂIôHÖ§‡ÿ güYŸZ¢Ù:Y²èè$Iò^÷Á£LjoE;êió‰çh‰OŽW±@)„Us{ôzKî³û¾Œ°Rˆéöª¢e*$Óm=ŸÞãÄ÷W‰JyLâçR®#·—bS@¹Ð?½í¿Râ¡ÏtJ¡Úò”Ä)/Üv ½µM؇ö9¶¬˜ÇŽ8‚9ûP77|úL§Ó$ <Ï«þcCÉâbŒ‹/cÞKã’œY(cè[–Å=—±Þå¹Ñ4 ]×£¤Ðr™ŒEA“>–EÓ´(|ŒŒ·/—Çãî;Ž0¼§ÓéÈh?ùÛÈòed9“Ú¶mR©Éd’T*Õ#ž¿,Ç0 lÛ&“ÉL&ÉçóѶÙl–|>ÅÌw]Ó4£ï=ïÀŠt<$íxvŒÏ–ÜÑp¹³¬ò^’{•Ñ4e7e"ÄÙ¥´„ß»@æ×¿f¿ä@M¸­t´ôceI“®”_¤ó¤,GÎgðcÛ&·~ È™f$ìÈy ›vîdçΜSS•_ÕÕEuuu™cªœÓPê:d=âóý^ÔÆî‡ŸaÕij¢º¬Ü´‰¦3ð(ï~MÊSÁÉnûþN`þöíüfûvΟ1Í4¹¿«‹·X7×ÔðÿŽ>šSÂ2þ™Nóù_ýŠ_ ü}ëV mm¼?øî_þ§ Ö¼ò o …g¶nåÄ=HÏdxö–[8ê;ßÁN2 |ÏÃ÷}æ­\Éä‡bÛé§s|:-,‡AÀæÏ|†ÚÕ«yé}ïãïÏ<ÃËŸü$]]ÝrÅìç æØVƒ²‰0Aà8NI@–W6ËÇç¹™3¡¹¹$†Èõd8º¸¨ÑÖV–›$ZÏ÷Kaï2Q†mG¹Š4éÕ"§ÓÇC0A)\žaÁÐóÐ#.:J‹²ç a¿‚p²7O›J $WO<¿L_0 ƒÝ--=wn¿ö“J¥úmÜK˜f¿& †•Íöë¼çì÷øùeŒ|Žyøs Íо³·p_²©éºp X¹r'µµßbÚ´1èúI§Eˆ¸ÖÖVt]ÇuÝÈ« àÐC¿ÅÛßþ7~ÿûbò+_Js"½Ü4ÿÛ¶y꩚V\:^5?Ûþ3]]]d³u̘q>^ø’É$'žxÇ7ù‰¼¤‡iš¸¾Ë%¿„o\ühÏNø/O «Ld‘eä ‹‰^ÝËgmŇÁlŸ® »v=_ '>úæ)ûCa·u1~-ç^ÐɯžýIDÿ7ÿù¾ïûea\ŠÑƈ *¶-2†/^¼8Z¶|ùr–,Y¼yóX³f ‹/fáÂ…}.3à•I¯ð–¿þ©{ixú5HÓÑi­ÜÄÀ ™fZh!A‚b$‰Qæ ]ƾL”¨”Ûd(Ù“Óäôá¡ _Úý\v¯ï`&•'®ïãxU©m¾µÏWVÏá ×:yáä“TMÓp]—D"ëºd2\×fÐI~ HAC<äçlhÐu“亮…|pŽ‹(qÁD†a‘ÛÊã”b† Ó÷ÒH¥RÑÌE˲zÌî§â^ äóùh;yþñsÊ)§ìõ§ßŸ¬±íK³g‹7á%ïº._ÿÈGh7.ºŸ’N Ë‘e1ëž{8„ʡÃu¨?EËfK¢FÜ;+4¬†%BÓIo°tºrþ­tZ¬#CÄÉòºç¸’ÞP¾_näöPÊ$Åîu÷¼Š¹‡ÊÄÏ+…âó}!üÈ>QzO)Ë*­Ÿý(] d¾$y/Ìfч÷nß.Ž#Ju”Çáûâ»Øv=¢ yÌâÇBš›…ØeÛâ…â¾_ 9(1Ö×ç3!ªÅE‡Ì'÷§ëäR)!Ék@†<ÀоS¯ðOuüñøìg_àÊ+w³k×g¹êªÇNÿˆvÝÒÒ‚a=·åËOí·@hY2J£Ù£¶m“H$( ‘¨åÉu%‰Jƪnûª$déº^Ñ{(¾î`…ê’bÖœ€r(Û§WOƘ]?ù 5»wªü:Òè$…·2±!ª< lûÁȾ$ÚOzRIo¶ Bað9ß'pÝÈãÍq¾“É>óL‰?ÃÍM ´§Ÿ`Gk+;î8Z¶l¡á ƒHœ}6c&NIJ,lÛ&pYV$>:ŽƒuøáxÿøƸqhÇ_–4\¢üU«¢6–ÍfYõÄ‘Ü쿱û„.>ºnAp×7àíÞ-¼mžã’K„A|Ù2!(nÚ$<ÚfÌ@“ÆðùóÅýä¸ãà¸ã¢s¾¦ñþåËùòQGññÓN‹îaœvZùÉŸ>=ú›Ò–…I8Çàӟ懀uÉ%8À†ë¯œ>uàJà}ûŒÏñçŸÏÛgÏÆŸ=›k€ï.[F§ˆI³ß3ØcÛñ/¿Ìe€ó?`Îy-™äöW_eâŸÿ\2¼ÇÂAÕ'¿ç=•ÃÂõÖ–¥°PÉx¿wçr%£½®÷ž;n¬ 2ÿ,S–÷héî±bÐÐPî#ëÜÒRtz %&a)JØvy˜K¹­ŒÃdš¥8Èž³ÎšÚƒO¹(¢Þ½žÊÄ4+lÔÚW'ºO6[û9ô÷O¾ÓTn åã,‹VÕÑÁo¥akšƒãdKNaIFFF&嫦ÝFJ³øÓ? ¾Ççž[6eNêu,˜ï~÷!`ù<ø~’\.1_ŸD"†›U …““²?Ȇý¹¯{1Kw-Åömö&VsÏ=ÇpòÄ¥üÜýcömKóåÏ¿‹ÏœÉkþè¿9~å›Ù¼é踭Í×8þÉãyüñÇ)|¨ÀËw¿œÛï¿¥;–²tÇR†^?Ä1¯8†ÿ}ÒÿæÈ¥G²ìËØý¦Ýìܹ“5;×pÁû/à̃grëã·òܣϱì–eµö(–¯[ÎWÏþ*î9Àc=ÆÊ3W†!*Ÿ:á)–.]Ê‘£Grô¾£ydÝ#`Ê“W°gÕ–-[ƪ=«xú¨§Yöð2V½t{{öòÖ_½•þ—ö³t×R–ܾ„U«VñÔ O±ûÀnŽ8â^èx€:^àe¼ŒÝ/ßMbo‚½ð#<ÈþýûÙ÷~Ž|í‘,ÿƒålc[ÛÞ›fÑ ûüáÇ|044†(ÇrUùTUÎZ`T7M9ƬreVŸ\å`©âĪåO(Ç•…r8p•ЈœCiÿ%; óܪõñ&qZ9në+öþ}û8°bEÍm²Ù,CCC OÚż *Ý¥¸Ãˇ‡‡')š5+Ø(»wïfëÖ­lÙ²…bžÿcèÍX³m›d2ÎW1û£îû®ë²ïŒ3`Ù²0—Àˆ6‚O‘"/ßÿr._zy8s&J3fUW'r6 #,G>Ÿë©T*ÌàºnºGåˆ j‘çy¡° f©*Õˆ&-ŒÎÚW3ô•¥„ Û¶Éd2aŽÏóÂÜ ®ë†yÔ,%‚DE-%TP©°?*Etv½Ê7¡žet6˜çyáàºïû÷I‰,ê¾FïùO~òž{î¹°BYÈLe›0{û¼õÖ[Ù½{7ÞI<úÌ“¼ó Òªû®ž“ª!£—Ì€S^,ùÒÌW%ªd2î9p¯Øð Þµù]¤Ói,Ë =L x—kU܉D" ]=Ÿ ·µPÂSÿ¢!”pZýFGGÙ¾};{÷îmw›B³ísïÞ½lݺ•#/¼—v?̺0M¸ãÞ5<³aCK®!ô‚ˆÐÕÕÅÐÐPX?8ŽÖIŒŒŒ iZèn®Âý)AÐqòùÅË‹\¹tøjþ«|ÿ®ïó}'xv¯'œ¬•xIÓ4ùvîÛ¤Þ•b£¾1ÈøÑ|8Ùê¿Þú_|ü¾óþÔûö„ïû¸{\ÌsÌp’Èÿýôÿ庿½ŽWýîUüÝ‘‡ñá ¯ MöD÷ñy÷Qïæì¿<›ïüÉwxϱïáò/§H‘ÿÓñø_÷ÿ/ö~/¼µÝoÏÜiEÛö¶Ûã V–Ãu§ Œhb»Á,‘å²*ù^ºôÿ!Ê%„¨„|—ƒ³ÛA;\ÃÀ‡Ûõ๮颬ÁoûÀøwއqª·ÎÃÚeÇÈŒ*ç€béÿý”g¨(ŸÎ½hÄVmÛE@«Æmûúú ³“ÑÛŽe5ðÜ1ÇÔÜ~1LüâÃöíÛ[Ò¶m[•jÆÆÆ&-kÄelÅŠáM¹ùÆyÙÙÇÁ™s+‹òvPÂÀÀ@8°«rD½0ŠÅ"·èCäþs ˜Å®},ËâŸ/ûg®ÿïëñ>å…ƒ2J@P ”£‚Ñ$Ð 5ÃV J I&“aBçh먡Ê=¾jÄÖ:”gÏ*á@Í  E %¸Ô„J§Óa‘¢bGµ¸„åWeo4I¨òH&““Ê¡Ž¡–«{ª¶‡²d«0S/Jp©öVQçbg¶ö¹nÝ::úž<zè§èú[:_>Ÿ¯x¦vH ÃßëjáàtNçœÓÏÁÀ˜ÑŒÃ0H¥R‹f–Dµ0´Ñu½fc5sf±%¥¯Ålìó裦··—íìäxnáÀwÞˆö§`ŸrJ˼S‰D(䩺C ö*V>ŸX¢¨:‚ï´NLÓ$›Í²víZN>óävÜþ¦ò»—ŸÃð])^¹þós?XŒéì줻»›G}´ÝEi)siÛî{èõŒï_ÃßïßÉ¿ZÍ}·}|t4SÇ÷"ËüÊñõh:“©Æä]wrÔ« 2™JïF˜Ê+£¦9ó}f1©àÈ|`Æû`A(¿R»ñýÚMµ÷ e'—zÎ;d2Fgó¼òóTÏÙ,%ÓP‘¾”SÍ‘G^Èš5>‹¹´mŸ|É“œìÃw0 ‡b±†ðZÌhZeD@…J¯ÁkxÆGS,¦Ãe–• ?A ]ï¯H´téV¬€ë®‹ÎV^ɹç–E™ï|çÿ•ú»&ùHŠÌ0ϙ㸖Û^v-Ûíòy|ß"“Qe3KŽYÉÐãæLÍäóW.ðé1pزåw<úè18ÎÑ ‘Ïö‘H¬f``ß·xïmV åêåÔPž§‘Lš¥sj@†ÿó Æá`_DŸ RR%ñ}Âï‚úÖzžÆæOÐ/‡^çkAtB@× ø>Åêk‹ì¹o{»_…–3Û¶íŠ+øéYÿÁz>H^ÏãþÊÅ?"«V €—ñ02úHj-Ož$IŠñür¸7#ˆHâ˜Nð›à÷Ã@~Žv–†††vˆ$ëÁЃpÚéZZNC;IÃØ`ÞmýâM7>@å}QŽò€ÉÌ\ÉSur¥uJRË¡ìñ¢3Ùû%êA#4iÛÖGÛ†Ír8ÿ¬Ãá7“·uJ¡™Ëx…Ð~6nÜÈ/ù˦76‚J­™ £££¡2:ÇsL(¨wæ¯Ðîm<¤PH©éG0+±C Ú¨Û¶1 ƒb±y&“áŽ5k0>Ã0BáC…ºÿöûyÍøkBÏ "ÈuÝ0¹hºä/®¼<Ô,]¢Ä4Ípà^å^PN*B-ªöétºbÐ9J­™öê¸ÑFÑ®©Î«òIDËÍ·Pk¿ÙÌþîd2I>Ÿ¯9»º··—ÁÁÁ–—¡ÝÌÖ>×­[Ça+v³ìT˾7€®}Ús)ñ.›Í–“ï΂fzŽär¹0,ÐbàPhœ¬\¹’ÞÞ^®½öÚv¥åÌÆ>• ò=`ÕgGÎ) ²¹M±5i *ž¨ðl*¬¢ Ÿçy^8 i¤:gB„©ì/—Ë‘%‹‡ÇBçÔ7=Ǻí=|üè#€Ï´»8-£³³“3Î8cÑxMÅ\Ú¶kž[Ãû_ úé·1ŒéëN(škZÙ)D5'HãáyA¨T*³×õrš 5Ó<›-ç&O§ƒÁw5ð¯šjŽSTiOT uÞlŒuûÉF˜¬»P(§NQ§Ô@¤:ŽJ[¢Ò‚¨óD¯G ÔªIë¯À?°;ˆ,Fö²íò9«Ó¿är„ƒ¤ª,ÑmTZå0¢ë00 ï*ƒŠð¥öñý`PÙ¶ÕýÀs‚íU¤3õ,t=pÆQÇRÏ&—Ë^”]9ß ”sÎ÷ôÇ)ƒm ( œbùºÕu¤Óe§õ|£÷TÝ£TJ½Ý8ŽÅ%—ìšw›™OæÒ¶}|ÍãÜô™W’LÖkN[ŒèzEZ§05m—¿/Ê**î)A¶Ñ[õ~”P¨¾!Ñ”@Ñï–úÞ©tP¾”M…>‹ŠÃ®»†“Nª<‚sœÅÄÄY¡0©ë“Ï©„Sõ]ˆ¦'ReP×]@Õ·-’‰ÎÎcøð‡áóŸ?ºÝ¼å̶m{Ì Çpʳ§ ‰IÿÊ~44Šé¡ "އ‡ŽNž< àá‘"E®ÄÔÆÆÄDC óû¤Ð¨~y:A°iºWEŠTÕ T¤cÒJ˪)‰Ò: *š»•!ÅüÈOi?({ÂTï«ÊÑS:¿O9šxT‚¼li­¿´ŸI ø8¥íU(3“@0RåÐ#åw#åÊRé™cQÕ–,ýVצΟ!ð02JÿWe#R~­tÍ”Ê-ƒÈ¹ó¥sg"Ûú”ãØ¦Kǵ"åPÛ˜¥mRÁ9;û;I“|¯÷{,fš1në/yóX÷Õ1FÎ:‹—Um[/ ³ ̆îînÖ­[×ôãÆFPéîîfûöÊÙccc '6صlëUÃÅN%b ½­6Õ:Éfƒ–Œï“[µŠÛW¯Æó<~µf ÚÁƒèºÎ{þèø‡ïŸNÃx•G‰Šõ¾råÊŠøæÕ.j+W®¬ðŒ€ÊAMž«X,†‰òæ¨E­øëP(Bq¨•˜¦† [ DüEæbŸûöyŒó|à¦ÝVyS©0_qø_,bаø˜sýéÃñ'Áá‡ß šsE *–e‘H$º϶mt]gdd$ óÕŒó©Ä® ~ô£¬¾ývÎ?üðvEhs±Íä*¸ÿ¹ûyÙ˦Žë¢ÜÔ ^:4q•å|ä*Â”Õ ½®Wh:Ny`2:×E?•  £Úk±{öTz[ @:}")/‡QšÙnÁòh~ùhº‘tº<«"ó)¯Ã„ޥ𳠳‚lº|¼¨7†J°u–Q3Òm»¼ÚÏ0‚² çK&ƒÿû~Y0ÉfË÷AÃó‚íÔ=P†LŽêŦYyÔ3Sd2Á:5È«ÒÃ(ñE•9‘Îg¸¢D˪Œ˜¦œwÔ2u®l¶,þbQyŸ;ïÜIŒº‰-a.öéâò[ç¾_€|ÞÓ ÅЦ•ß9õÍ©f.‘4Õ7J_¡þ=v­óT/‹#ælªõµ¨— *ïú~V+ºMuš$õû›ß¼mö7n0[ûüL×óç_ú?|‚O` 9Wúçã“&MŽ>7Š ,j[E†'5Ðe51I“ÆÅ Ú¬zi¢,Ó ë^,zäojü¿Ö{U~j ed ÄŽ©ç3•©%|NDþ_=<•-•Éöˆ]¥rDm¥Vj¶FDÖ=‘ÿO5Ç6úøjG GêœÕ¢‘¹»‘{7ü÷ÃìÜÝÀN —fŒÛìþ÷·qøàG?:išœ.q'6-åÞÞ^ÆÆÆ¤··—ááaFGG¹ð Úßóà·¿x¾¦»/Ÿ/·T\7è¨Ìz‘–Ë®Þ^®ä.¾øb.Û¼™ÃJSúVê:+KS¾ó±AUl?5ÔèL^—úáTˆ®h¨“V &ÏÇÀp³Éâ¡,¦ÀÜíó‰ß¾ ýôïC±XÄu]Z–¯`1 º B”¹Úç½k\^þü»qRX¯<ø<Ï#ŸÏ‡9§<Ï óª

qÒlxfC…(EC£ŸþIËŒÄÀšK ­@ ’$Ñа±É™²¼!­š¬Ÿ¡1ñb6T ¨·ïVõ[¨Ë\ûŠñ‘S¸gÿWÐõ-“Ö©ô‚wb#¨lÙ²…Í›7³qãFvìØÁ–-[Nêäy°öE±ìÙgƒÞãTNý¨ #¢fϲq#»¹ê? pûíµ{›Õ¨éi‘xÍÓ ÑjÓ|¡5M[4Þ€¸è-BfkŸ¿;Ö¼ìNŽÙðŠºÛ‹Å0I|+qqI¶¬å(ía.õç3?:…g~½‚ç_übò³¨‡ŠÅ"žçá8…B! ù˜Ëåº òQ¨ƒë–ãñ‹‚ÙØæÓG=q̯yô÷ßâœsR@Y4 é©¼Ô ¸WªQ3­«M¯‘\ñµ˜iª¾«Qt½,XÔbª¦¹JŠ=M8*TLEô\Q±¦º SW…3šÉ˜»:zfSí[ë>ÌdàZ‰]‡2³­;w»'sü»å³{^NO"¡"¾ 1y¬PE¿‰ö£‘i´Ò7Å>ê˜.åh<ÒËfcŸC¯âeû^Öàæ“=× ‹,ÙðÿóN­V³0\&,8æÒïT칤ÀÁ¢[1nèû>žçQ,ÅóSX´MPÙ¶mÛ¤e}}}ôöö2::JggçŒÜÆîÙµ›ƒK’Z²$èQM3(dÛv²+LvÛè@êɪ Ê–…;;Ӻr BL¨e›0{û<éqxöàì:ñÄ)·q‡|>iš-Ta!ÓlûtÿgxÕS7sëúcgU&Ã0*¼OâªoÁ¡b÷È=\4·mû<¿%óUx^9J.7ÙëB…†ªÅT¶S õ¨g:f3y6Í€Ù8ÏÆ!o6¦9›1™ï3Ó´‚š6i¾Ù¢¥Ùuçïí7ñÅw¾Àì|’k<÷nðW{RyöºJ `ŒYÖBÔ:²¿z¹Ycÿ©b(F¥ˆ.Wé ªQéüÈßJÄ™ UN³tÌèän©¹„ÙÐLûüÅËÁ¿}vüSºR™/Ë µ*®âDÿ¯â,F÷/Íj0?òzV­Â[³¦œ†äá‡1ÿó?ƒ?Ôìåf¨¨ö>Ö4tà GŽ4é@Pñ"ÒªLPb@³Çm¡”Cå–×sþÎë+–çóyÇ™³ç§D$æ‹Xy¨³2H€ŸÿzK—ïbÝ~7Ý4mdš&‰Dbv T/T„C„ÙØçs‡;lüÜ(û†¦ÞO×uf3z0CLÌEHª™mý¹ß‘t/ý%c¯}íŒ÷M$xžG&“ “Ï sDDåEÇLmó÷¿?ƒc^xÓ4ÃDæõ€¸šÞbÓeÂäâc6uç ÚAzþâ/ø_ú§àƒññ`¹éQN¼\ §ø©ÏJ‰pKÛE'Xf.í¤R.è;Á}r¿)m£Æ™”b£•ÿÔ™,†äK?#‘uåÓåÓ^Õ¾êr¢—`—–ç+O_!̨¿•çMõe9®Vµ¯^:®N9/uô¸ê“âGΣ®;Y*‘ó©í“¥2ûUËÕã j?=²­½”°•¤œß[¯q®êûÍã­îKô˜ÕD=‘¢÷Mý÷!fn¦öùºü t¿ä-“ÅåÂXÊ;IPQ.›*9OõdYM+·ÏV¯ÆzòI¬5kp živõj¬åË1|Äg?‹±k×ä”QWS…½ô/ýø{)¤Ç+÷©žd“J•§y^e¬l¶, )Ô:ÛîC½cWï¯&ùDËŸNWò*gN‹“Ý_«ûø‰Dùÿ¥ÉÉu÷Ÿi9•·w”L¦²}ÏO¸ê•³Ñ²þå_r¨0Û~'ß½½Ã§ñŠª´ ™LMÓæÜŸ”ˆ$Â|;Ae¶¼âÍ¿dü¾ß°2;½˜â8ŽãÐßß?·™´µ¼`¢‰ïgsìtº²B¯T­2XFƒ_G×—ò¾„ êõ‚0ÏìûÉËxüKoż⅚ëmÛ¦X,’Ëådf» ´¥wŸÂÞW<<:í¶¶mãº.Éd’|>O&“ =TAh§-ÝÁ{V}Ÿ{?Äó‚&¥4å!üæ´Ó8îÜë¸3õSŒ/lƒÊI‰•‹H”"ÁH~4&˜Ù^ýß#t1•àbBR‡dTU°#¿•x“C)A’iÈ@Æ˨¸WÊQÇ.Ý]ô)ŸK…ËK²TÔ"•y¥§ÂÒ¥m£­üèP¦º-JppJ—§Ä³Æ>a¹Kû¸¥ËÎEn‹òÚq SŽrŽêbUÙ´Òñ ¥ý‹LNÿ ¥Dé8ª\VÇÅ™ÁýRØ¥Ÿè>V©Ÿ´m¸è¢íÐá-w> o¯“1š¨«]ŸÞÍ1"˜€µz5P=séR—\‚O&Ä~ÙËH¼{ÉÒ–…_Ú¿ºÕ\ @jMŠô€Ž…5uN—zª~½-Äžœ.ìoT¼™ŠjÚZ¨cø>ôôTÆî¯&.W÷1ªËéUYŸaLPª©Ž‡Z«‘50Pnj­·¬JñMÓàg .ýv+õ˳Ù,š¦I¿RX0,AåÚ«z8níÍðÉ©{œ¾ïã8žç5=Éxø¹V"†R½3™Ê ‘jv€ë–g@TWŒ{öL}"%¤¸npüꌚü¨¿ëNVõÕùUåSKmWÇVT»¬FÜ^+*ÀÊT’ÉääÙ JñWûVÏ,hdvC±ì¯iÁ¶Õ±(§\Fß~ªÝw]·ÒËH=“è5Øv9Û¨rŽìÎ 7ð|ïâNÜ9'^¨¿Úu]S¡Mì{Êcý¦oóðë§ÍõAx/•„W‰)‚ 4—£zš‘ן„®ëô÷7‘V„Ö3úôc<õ©M¼ÛŸ?ä’º¥`ÕY¯4/µ:Wš‹‹†††ÔÑ+öñªæµš¥aµ¿:§ú¿)Ã,‹žÇŽ=–_=ô9M1EbÆŠ»ÆYuÒ=|âîOÀO#+Òéò„4]‡¿1ƒIE#@Ú)÷ «'oÕ›9>Õlðzý(#Òóý £N—Jç³àNÊž5žN$ªã”]#,À)%rZíÂ7 xsŽÑ‚‘ãO—Ĭ4`sÑ‚ä$p[NKÂOmøø@ äKÇ^“†‡5¸Ó…}À‚óe£<Ø…ûKßÖ&áVÙå¾,öh°Ï‡5%Q©œ—…Ý.lƇ-Œ§“ÁH¸üMö¸p¡O”.Ô!(ÛÙ.|5ë3ptnÕá ¹² JÈ9p”»pß@9>Øz?¸¦Ÿ”Êüràˆ\p_<ÀKÀK€õüprÁµú€› qp7ÐaÀ_æ‚rýÐ…çXæÀ«“pR«Þî…®¼Ú€VõÕZËP)Âä <£¼ÒrõjéhX$ù1î¤6£‹K‘".n(®XXa³Q”ÈãWý_…§S¡ö¤¥)´’§víbÉ1k8ò„*–§Ói†fšNÚÈ¢T^ôñ/°ìë»ëncÉd²-.daEW=èߎXéÓ¹s6R®F*Ó‰;saºì¨dON´Ñ´à~)Ÿêë6 ~ûŠW þ)µÙwôÑL|³m×/& ÖzžG±:–« óÊIãðäÊ}øÓäó}? ñešf,EP;ê^K)nІ†?Iä˜ µ}£èèø¥µÖEgª²çѦÚÇšj½‡W·ìÕn·n'¼^Ù«E­ôOhq´3A8Ôß½öN𲥇U®H&§ž×äÈu‰ö5«Å›ê5Ñ}¢}¢êþ“êSù~0Éìí‘>ÖÃ¥Á/½à¥c«îædà= Èõ—G•Õá?¡ÁÀß Tº„ ‰,¬1aÀš† @('WÔ¥ÿ{ô ¸|΃ϸpiäV.Ø÷-Y¸cI"¼'œ™„b6x¦?‰Ì®ÌÃ}yøJ¡$^EŽû+à¾$ ”²êI‡^vúð¡<Ü^€—Rvk¨vÿûb HY€ííB®Üÿ“ÎiÕÛ³ð™®oÔ“v ¼UT.¢"¾f sí(ÌÈvËqÙ…Gy^Àãx¼ÔÔJÇŒæé!r,?òÛRTæRû¥KëUØ<’Ï.m[ÝÚTù€”i«ÜI*za2r¬¨p£Sß» ÊÂ:®9gôÚ¢DE¡ê¼EDþ¯ÊãF®³úxÑ\G.e$%DIKmæ<ûô¼î‚ß²îœwV,·š`¿µ&« B«X4‚Êíº•«Ï¸ æ:óÝuÝyI|-ÐXœÎ…„ jÌšñÑ#áá&-w]]×›Rq6åbÅÀÁBaÑ11ár~ö¿p¿„Þ«…ïû¡½&Kßõ¸Å¶51adîZ¤85"Ï[Xß9õÝ31+¾J,Q“™9 0U}}Úî1ŒuÑ;"Ó¦Âu§A˜Ý{ §i?æÈ§†©ÈpÑŽIr3e®eÔ4˜jöðTíùw›Á>µúR_g’ßÀ^°nZíkRç2sŠ![MƒÿÊgM˜¦êÇêÀ—,¸Ô¨}ÞWiðªÈ~Õ)õRh´Ñ<|?¹ŸÑòŒŒÀ¦MÓï/Ä•EQÏ:£­8$_Ææû¤øpÑp 4ºFÓ®E¥Þjkt(‹J è§,’¨²+ÁAåVRâE‚rê¨4•¡Ð œÿH;ê)£ŽÝ.úÿ¨@]¦EŽ‘žb_½êœêFiŸè¶Fdµ]tšQ´œð»³Ï榋ÄrˆãO~íl~}çn¨Ò†½é¢Ë4€ŽŽM‚ Å€…% ê…–±h•#_y;O,塀NÓ´XÚ Â¡À ãÇòàƒÏMZîy™Vz0Õ@ vÑ…ß‹´ƒCnFé$ç¨zƸšY^=k¼zVº‹[s†~õ¬ôz3ìãÌ/y¢ÝEˆ5OÞzåÖÊM)’äóy Ãzt3U˜°F„F5S‡Ü=ØÖûgÄ;EâÉÚw—KúomÿÓî¢,âú=«öàitŸ… ž ‹Š©Þ¸/d-iÒè蘘ø%a%ê 3oóEÏ™¬Z>UyâÖSîÃdf*¢=}å‘Óh€cø»îâ×í¾è˜ãûžç(ÿN ã]ár ¾9çp`z00Âñh4š¹z<£z²ØTxxáIô8Õ}%§"¤³ ÕDZ¥ÙSR÷¦š™DzPcYш swºõœ[é}¾¹“ù‡ âògŽà%oKÍÕÅbñ‹õ.qáùÑ“y±6ùã׎ٷ::ÌÎK­‡žp¦C”èÇ^Uª*„Ϥk.Žm…§ËTa€f‚_jUVJ„Q‚ŒªÔ¢áŠ¢×<ÓkT÷­ÙÛ¶›ÖßL’ Ç.räè¢+4Ôòè;¡ÞçèX†Ú~ºɳ%Mš%, ËP 0íXHu~Îj¨zÛéˆjRù™Ô1«ïÏtD'Ûj‘ŠÙŒ…M5¦‘PÝ“îÉNÖ5þŒaQ*û½ÛYyØž<õÔIë|ßÍ@ÐLâ® ÂbàéÃO繳̞ÛVT,ïééYp ÇúéŸÕln¡½lºMÂ"L…<ûÓå¬9òþš³áÇ!ŸÏcšfêK„Öóä“OƦí*B%øÂ“,[¶¾ÝÅAid¦»‹K–lØŸU¥66 LæÉW¬ ä+40*ö‰ÓÁ™õ Ñcª‰‰ªLQQgºrF÷ÑÐÈ“GCÃÆ‰Õþ>>™I%BSy~¿åSœyßT,ö}¿)*féŸ"I’ &f}¼Vˆ)…Ò?l³H±a¡AEOÂ÷»ÞýîØy‡*µ8é´}¬>óÞôîÊ„Åb‘b±›[Wâ÷ ‡O­8’ާOà´×¾¶bya>“s6 S„EÉ/°v×=Æ&­RÉç›å~-BcwÜqóS„ÆøñêÕœpÚi\Øî‚‚ ÌcÖ‘ Q¡M< Œ¼”g6lÙ¶®ë±ËÑ9_ÞcÂÂaQ*?¾óv<·¬b™çyhš1ÅÄ”·pȱâÉìûÍ)hï —åóy4M“øð‚Ðfàyýn¾sä(ÿ_ Ѥ§§‡I¬( ß÷Ñ4- Ýç8†aP,C±TÓ4òù<–e…ë}¿ìQ­„º®K.—Ãó<\× c]Û¶M.—öm’É$Ùl–\.þv‡d2I:®X^,I&“8Žƒ®ëáyªÿ¯Ê ëzx¬b±Xq¬l6«P(J¥*–«ý«ÏaY®ëâºnŹ ÃÀ¶m2™LÅ92™LxO=ÏÃ4MŠÅ"–e…¿Õ½T¡+¢engÛ6†a i¾ï‡ýul•³J=µ^_­3Mß÷Ã6•çyáßê96kÖ§p÷þý¼ùõ¯ow1A„b`4%L¶0{î}Î刨 òŸ§¿¿¿B¼Èd2ávŠD"ÁÀÀ¦i†ƒôjp_×õPpQ“ ÇÁu],Ë ÷UXy´ ³_ÕoÛ¶ñA„ÈT¹B…ùãöýÏqô²çÃ6’ëº2ñCX°, AåÀú{8jÕË|ßU¸ "Å0Æ£ƒƒ†F’dï±@J Êçóá3ß³gžç…ïZ®i©TŠ7¼á 3~‡ Ë–-;dÃ’‚03|ߪgä+‘\-WÛáMÓÂm”®~G=Õ>j`:º­išu½£ž—µÎ£ýéö‰ž'Îû¬šXůÆÅ O¼0ëóDÅ€è1~ÿûß³oß¾v¿v±æ©'áÈ>ãÌwL² AXH,xAå%O¼„oøï¿ó”p™êlÆ ƒ=ì!OŸ~úqppq±°È’ÅãH‘¹0)‘J¦MÊuSTI¹A‰9ýôÓCOø·O©.%‹þíáa``aQ¤ˆ‡7)ÑX­e&&2$HT̨N.Anƒdé_ŠTÃ÷ÕÂÂÀ Mºá}2dÐÐÈ’­x>::)Rá=P(àáMº×kXÓô÷e±°ä¶cxâ¾÷¡ÿyyà@*LAˆCG;œðæÇ+ülÛÆ÷ýiVA˜_òù|ØéT? ™-¿ø˜Í3­·O-o ]×'-SoݺµÝ·@¡)8Ž J|Påù|žB¡@6›¥P(„^ˆÑP’QÁC‰ Õ!!£¡!ë…²¬Þ'ŸÏ‡a3ÕvÊ£Ñu]’É$ù|¾â¸ÊSQ…ŽTפöW"ŒÚV º®‡!?ÕöP)îDEžêcD=9kí=O;ö‰†Í¬·ÏQ£GÑ÷ª>v´‹Ž:[7ƺýë=i”ã8žç6<Ç#<‰NäÈcŽä±×?FçsìZìó¬÷,¾î³~ýzžèx€Žåø}Þzà­í~åã‹ ·îy'ÇOÀøãà=tgÊÉ7‚w–LLLL´»saÓ¦M\wßÙüú…•Q;ƒ0§_jpßãŸÖ…Yé¡ §á󨨏¸$Ib0ý`¸O=dÈàâ6”`ÉÃ#A ŸÓT]\²dC Ó{$98ØØ¡P¤–;8äÉ“!Sq~%$ùø$IVx ¥IsóΛùÚ®¯ÑÛÛÛä§µ°ä¯ÿóß¹Ç=™û~ôI\× ÃÂ|±iÓ&¶mÛÖîbÄŽM›6ñ ëhß³ù«óþ(ˆ+‹âE&Ì ƒƒƒ ²eË–v%vD¿[¶m‡ƒ7b—Â|±uëVz{{¥m[E³¾[j–s#³¬kÍ8Wy~’Éd˜¯'®OÍ®V!ܪsü¨ÅèìöZù~ÔÀ¯ú»Þ`g«öQ³öÕu©ÑëŠæ¤Êf³ N§±,‹l6>c]×ùÅ/~!mÛT·ù³Ù`|%V˜”{J8ôpqà Áj³ú?ãYj²±Z¯&« ÈÑýÕ>ßú8·Þz+Wüéí¾ÄرiÓ&¶]±ýÃÍvø ýÝg€²È(­¦mÛï¡ðü¯_…ññ@^¨É®“$É’ ø[E† EŠ ‰Ѳ%iƒÏ²ìÙeí¾¼Øbß µ›óÖžü]§a¡;•ÑÑQFGGéì줳³sÚí/³’Ø·”w=ÕPoæê¡",\¥Y|3±ÏÁÁAþøó.×î$û±? X,†qÜa¾8”R©ŽãÐßßeY LÓ”°™‚Ð$fcŸÙl¶"tž Íg¶uçM+nçðžË©§žJ>Ÿ=a¡«_[·nåšk®¡··—ááa.¾øbz{{ë*žG±þ°ŸÍÞËÑ'Ä6oÆ™çr»í½m‚0/ÌÆ>:êN^ÿúR©###í¾AX´ÌÆ>Ÿz¶ƒ×_ðêpv Bó™m8p`RˆAšÏlìó¡‡"•JM Ã$Bs™}J{VZÏllÀ{|7/>l˜ž²…¬ä1±ñP¤££#t¿éî»›ÁÁÁºûuÔÓìµó|ý³Ÿå–Í›±pæñLJ)3ŸlݺµÝ·¶.ÃÃÃ3šÕâ~fkŸçž{.G}4CC帙oâþnmß¾ááávcJÂ÷ãP`¶öyÚÄ_²fÍ€Øu>»%ßa:fß¶=jQ„È\Lï`Üí½QÓ3™+³µOX^×òNÇÅòLšÁlí3níÙÙ°ÚÀ²XÞéÅôLæÊlmó©]GòÌä¬ãž óvÆÉ;%îuÉBxãnï÷Üs;wîlê1cã¡2<<ù$wß}7»víjwQZÎlìóþûïç™gFùô§?M___ì@q~·òý˜=»víâž{îáÅ/~q»‹ÒRfÛ¶½ë®»H¥Rœ}öÙí¾„9çwp¦ÄÝÞ¥‘g"mÛ©íó±ÇÃu]žzê)N?ýôv_œ8”Þé…ÂtÏDµmãÚ¯j&³mÛ¦R)Ö­[· ß‡…Ðn”Åòiä™HÛ¶þûºëÙß²æ±#yæ¤_b×_}»/¥‚¸×% á»g{¿çž{p]·ém·Ø*ccc“–5’Üèƒü œqÆí¾„š É[MœïáªU«Ø»wï¢wWœ}ööö²wï^Ö­[ÇúõëÛ} S–1ÎĽ|qæ™gž¡³³“ýû÷·»(-g6öùᘃrüñÇsüñÇ·û$q·Ï8—ï±Ç£««‹7¶»(-e¶mÛT*ë¶m£Äù7mÚÔîb ¢GÚ¶ÂBDÚ¶SÛçÉ'ŸÌ–-[Ú]tAXôHÛV≴m……H«Ú¶±É¡ÒÝÝ=É}ill¬!µS„Ö"ö)ñEìSâ‰Ø¦ ıOAˆ/bŸ‚OÄ6¡Ll•ÞÞ^ÆÆÆÂdFÃÃÃŒŽŽrá…¶»h‚pÈ#ö)ñEìSâ‰Ø¦ ıOAˆ/bŸ‚OÄ6¡LlB~lÙ²…Í›7³qãFvìØÁ–-[X¹re»‹%bŸ‚gÄ>!žˆm B|û„ø"ö)ñDlS–LLLL´»QFGG¥³³SÜÆ!fˆ} B|û„x"¶)ñEìSâ‹Ø§ ıMAˆ¡ "‚ ‚ ‚ ‚ ‚ ‚7b“CEAAAAA!®ˆ "‚ ‚ ‚ ‚ ‚ ‚0 "¨‚ ‚ ‚ ‚ ‚ ‚ Lƒ*‚ ‚ ‚ ‚ ‚ ‚ Ópøç>÷¹Ïµ» •ÑÑQ†‡‡¥³³sÊõ3^ßL†‡‡9úè£Yºti¬Ê7>>ŽëºŒs '̨ óyÿ„…Ç\ì³Ý¶ÙHÚmŸq(Ÿ°p©gŸqz·fcŸí¶Í¸ÝCañÐ*»m×ûØ ûžïkiU=-߈…E+û¤q²Ï¹Úß|^K+û¸bŸ ‹VöIÛñ.´¢ï§ºs®eûœLîÉøø8>úhl뎸÷‡‡‡¹ï¾ûb?n;ïck¬¸úê«'zzz&.½ôÒ‰óÎ;oâ=ïyÏÄØØX¸þºë® ×÷ôôL\wÝuûO·¾™<øàƒ===·ÜrK¬Ê·cÇŽŠ{xÅW4\†ù¼ÂÂc.öÙnÛl¤ í¶Ï8”OX¸Ô³Ï8½[³±ÏvÛfÜî¡°xh•ݶë}l…}Ï÷µ´ªž–oÄ¢•}Ò8Ùç\ío>¯¥•}\±Ï…E+û¤íxZÑwSݹŸI܉Ë=¹úê«'®¾úê—o>Ê÷¾ñW\1qÞyçÅ~ܶck"¨Ì‚|pâÔSOرcG¸ì¼óΛ(‹áßѹcÇŽ‰SO=uâÁlx}3Q/FôÅŠCù¢÷llllâ¼óΛ¸ñÆ*Ã|Þ?aa1Wûl·m6R†vÛgÊ',L¦³Ï8½[³±ÏvÛfÜî¡°8h¥Ý¶ë}l…}Ï÷µ´ªž–oÄ¡Õ}Ò8Ùç\ío>¯¥•}\±Ï…C«û¤íxZÑwSݹŸIÜi÷=¹îºë&>þñOœzê©5•v?Ó¸÷•©žZå‹}·clMr¨Ì‚ÑÑQz{{éîî—]pÁŒ088HGG½½½twwÓÝÝÍàà`Cë›ÉÖ­[éîîfãÆá²8”opp±±1.»ì2V®\‰ã8\pÁÓ–a>ð˜‹}¶Û6§+_#ë›A=ûŒCù„…K=ûŒÓ»5ûl·m6rÄ>…ÙÐ*»m×ûØ ûžïkiU=-߈…E+û¤q²Ï¹Úß|^K+û¸bŸ ‹VöIÛñ.´¢ï§ºs!>“¸‡{²qãFúúú*ì°ÑòÍGùãÞ7¥¯¯•+W„áÈdl-@•YÐÛÛ˶mÛ¿ÇÇǹ馛—kxxxRÜ»ŽŽFGGZß,†‡‡¹é¦›°,kÒòv—ott”7²}ûv6mÚÄæÍ›+^Úze˜¯û',LæbŸí¶ÍéÊ×ÈúfPÏ>ãP>aáRÏ>ãònÍÖ>Ûm›Ü#±Oa6´ÊnÛñ>¶Ê¾çûZZUOË7baÑÊ>iœìs®ö7Ÿ×ÒÊ>®Øç¢•}Òù~ZÕwSÝ9ײŠ}N&÷¤»»›ÞÞÞšy1âðLãÞ7¾à‚ زe ãã㠆… â`ßí[AeŽÜtÓM\|ñÅôööÒ××”Õº(ч4Ýúf0>>ÎæÍ›¹æškB5±ÑóÏGùFGGCÕò²Ë.£³³“M›6…/n½2ÌGù„ÅÁLí³Ý¶ÙHÚmŸq(Ÿ°8¨¶Ï8¼[s±ÏvÛf#eûæJ3ív¾ßÇVÚ÷|_K«êiùF,\šÝ'“}ÎÕþæóZZÙÇû\¸4»O:ŸïB+û®qª;çZV±ÏÉÄýžÄí™Æ±o¬åÚk¯å¦›n Å”éÊ÷¾{3Ê(‚Ê,gÓ¦Mlݺ•«®ºŠ«®º*\WKýŒ*\Ó­oÅb‘îîîÐUlllŒááa†‡‡cQ>^Ôk®¹†ÞÞ^¶lÙB__Û·oŸ¶ óU>aá2[ûl·m6R†vÛg\Ê',\¦²Ï8¼[s±ÏvÛf\î¡°8i…ÝÎ÷ûØJûn‡mµ¢ž–oÄ£U}Ò8Ùç\ío¾¯¥U}\±Ï…G«ú¤óù.´²ï§ºs®eûœLÜïI\žiœûÆŠîîn¶mÛÆõ×_ÏM7Ý›qÛv­‰ 2K.½ôR:;;q§B¡ƒàe«~ccc¡Ò5Ýúf1>>ε×^˵×^Ëèè(7Þx#7Þxc,Ê×ÛÛ;IAŒþ]¯ óuÿ„…Ëlí³Ý¶9]ùYß êÙgÊ',l¦²Ï¸¼[³µÏvÛfœî¡°øh…ݶã}l•}Ï÷µ´ªž–oÄ£U}Ò8Ùç\ío>¯¥•}\±Ï…G«ú¤óý.´ªï§ºs®eûœLÜïI\žiœûÆÛ·oçÚk¯ ÿ^¹reÅyã`ßm[k(u½PÁu×]7qÞyçMÜrË-?>ø`¸MOOÏÄ-·Ü21111±cÇŽ‰žžž‰±±±†×7›K/½4<_Ê7666ÑÓÓ3±cÇŽðïóÎ;oâºë®k¨ ó}ÿ„…Ã\í³Ý¶ÙHÚmŸí.Ÿ°p™Î>ãönÍÔ>Ûm›q¼‡Â§•vÛÎ÷±Ùö=Ÿ×ÒÊzZ¾ ‡V÷IãdŸsµ¿ùº–V÷qÅ>­î“¶ë]hvß5NuçB}&q&.÷äÒK/¸úê«g\¾V—?î}cU>u̸ÛÎ÷Øš*³àꫯž8õÔS'ýD ôºë®›èé陸ôÒK'zzz*^¸FÖ7›ê+å»îºë&N=õÔ‰K/½tâ¼óΛ¸âŠ+.Ã|ß?aá0Wûl·m6R†vÛgÊ',L¦³Ï¸½[3µÏvÛfï¡°ði¥Ý¶ó}l¶}Ï÷µ´ªž–oÄ¡Õ}Ò8Ùç\ío>¯¥•}\±Ï…C«û¤ízšÝwSݹPŸIœ‰Ë=™JPi÷3]}ce+êq·ï±µ%Mõ·BFGG¥³³³¦ËÐtë…ò©stttÐÝÝ=£2´ûþ ›¸¿[q·Ï8”OXœ,„w«Ýß¹Ôq¹‡Ââb.ï\ÜÞǹ”u¾¯¥UõtÜž‰07Ë»0Wû›Ïkie7NÏD˜;‹å]XHß±Ïù%î÷$îÏ4åCaÅݾçóŠ "‚ ‚ ‚ ‚ ‚ ‚0 ’”^AAAAAaDPAAAAAA˜TAAAAAA¦AAAAAAA„iAEAAAAAaDPAAAAAA˜TAAAAAA¦AAAAAAA„iAEAAAAAaDPAAAAAA˜TAAAAAA¦AAAAAAA„iAEAAAAAaDPAAAAAA˜TAAAAAA¦AAAAAAA„iAEAAAAAaDPAAAAAA˜TAAAAAA¦AAAAAAA„iAEAAAAAaDPAAAAAA˜TAAAAAA¦AAAAAAA„iAEAAAAAaDPAAAAAA˜TAAAAAA¦AAAAAAA„iAEAAAAAaDPAAAAAA˜TAAAAAA¦AAAAAAA„iAEAAAAAaDPAAAAAA˜TAAAAAA¦aQ *ÅbÇqÚ] ¡¾ïã8®ë6åxžçQ,Û}Y û\|xžWÓ®Å>b›‡3±M×uñ}¿ÝEê ¶»ø˜k½*vÄ>ãK»ú¥bŸñAì3¾ÌÖ>kÕŸÒ']ˆ=:,t›\Ô‚ŠmÛ Ö‰DÓuqÃu]ºººÈçó¤R)Òéôœéy¶m·ûÒ„ ö¹¸Èf³ôôôÔ´k±Ï……Øæ¡C£¶éyžÜÛ€Øîâb®õªØm¼ûŒ'íê—Š}Æ‹…jŸ‹ýš­}NUJŸta°Pí¿M6›…n“G´»BmÇY´3VR©™L†L&ƒïûôôô`Û6Éd²ÝE„†XÌö9<Ï#ŸÏ322‚®ëø¾ÏêÕ«±, Ã0Ú]<áBl³54c€Iê/)ù€IDAT!¶[I3êU±[¡Y,fûlW¿TìSh‹Ù6avöY¯þ„V³ØmR¨dQy¨Ø¶MWWK–,!NOz‘•½zõj²Ù,Ùl6T]×%•J±dÉ’ðC­H$‹EV¯^ÍêÕ«)‹d³YV¯^MWWW…z:“m§"›Í†¿]× -{#¸®KOOK–,!•JU(¥S­«·O=½nõÉd2hšÆÈÈHE¥Xëz]× Ÿ™:f=×°èóÉ~Bë¨gŸõlS­¯eŸóm›ÐzûœÝNG£×>½Lu­êYjšþV Ø©î¡Øg|˜KÝ©ÖÇÁ>«m3zÜCÙ>gbgj»êe†aˆ8C¤Ý[IÛ½Ø_­ëm½ý[ì¶½H»·’8Úç|÷K£‹}¶—Å`Ÿ‹½Ý;}6£_µMé—¶iÏVÇúr¶íÙE?Ž;±H™&r¹ÜÄÄÄÄD&“™&2™ÌÄÄÄÄÄž={&4M›èïïŸØ³gÏ„eYÀÄÀÀ@¸Ní;000¡iÚÄÈÈÈÄÄÄDÅqr¹Ü¤ó˜¦–c&ÛÖC•Mýß²¬‰={öL Mhš®«w?Ôõªsëº^w]½})o#×](&LÓ '“ÉI×Rëzóù|ÅrõŒÔ¾á9,Ëš0 #Ü®Þ~ÂüPÏ>ëÙæÄÄD]ûl‡mªcµÂ>gc·–·‘kŸÎ^ê]«eYÉdr¢P(L$“ÉŠû)ö_æRwF×ÇÅ>£eSêöYo¿©lS1444¡ëúÄž={&LÓÛŒÒî|?âØîm¤ž›êzgS¯NLˆÝÆi÷N¾q´Ïùî—NLˆ}ÆÅdŸ‹¹Ý;}Φ_ZÏ6¥_Ú¤=;ù~ı¾œm{v±ã.A%“ÉLX–U±L×õŠ—#j{öì _öB¡0aFž–e…ûFu'õ`£Wb£ÛÖ£Ú£4¾r¹ÜD2™œtê­«·O#åmäºÕRUˆêoõÑ›êzóùü„¦iS>su˲&4M«¨ëí'Ìõ쳞mNLLÔµÏvئ:V+ìs6vÛhy¹öéì¥ÞµªŠ[ýŽ>o±Ïø2—ºsb"~öY«cy¨Ûg½ý¦²Mõ¬u]ŸjøÞ ó‡´{+‰k»·‘znªëM½*v¤Ý[I\ís¾û¥bŸñ`1Ùçbn÷NgŸ³é—Ök÷J¿´=H{¶’¸Ö—³mÏ.öqÜEòËuÝЭO¡ëzøß÷+Üj£Ûzž‡ëº,Y²$ü‰›;QõµM‡ïû×Ëåꮫ·O3Ñuþþ~LÓ$—ËaYÖ¤û]ëz«Ý¢5MÃó¼ðï¨^ÔÅmºý„ÖSÏ>ëÙ&Zö9»m6ÓÙK­k-‹Ø¶ÍÐй\Ž‘‘\×%ŸÏ‡Ûˆ}Æ“¹Ô ö¹ìsºý¦²Í|>aø¾†]p]W-Æi÷Vçvo#õ\õõþà?˜U½*v¤Ý[Iœís>û¥bŸñ@ì³’8·{§³ÏÙôK§j÷‚ôKÛ´g+‰s}9›öl#û-äq¢E#¨4ƒtª›¯i¦i2xì„?­x ÛI½IŽãðì³ÏÎhŸÙ`šæ$#kô#SýüªËe…BL&S{qºý„Ö3}Öû0Jö9SlEÒ³ÙØ‹çyèº^a˦iVì+öOæRw‚ØçB°Ïéö›Ê6Õvù|ž|>çyض]›XhÒîž8´{avvûðÃϺ^»m?Òîž8Øg;ú¥bŸíGìszâÐî­}N×/­×î•~éü#íÙé‰C} ­é‡ÂÂ'Z4‚Š®ë‹Åð&»®[¡t%“ÉŠ—ªz]tvˆïûtuu-èÆiš÷ÃqR©TøÑ©µîíoû”û4 Ã0B%‚{mÛö$Eµžç…ÏMígšf¸^•3“É ëz8 aºý„ÖSÏ>ëÙ¦Z¨Øg=¬gÓÍd6ö¢ì:ÚY´m»¢lbŸñd.u§Z/öoûœn¿©l3—Ë100þ†A.—[t”…Š´{+‰k»fg·§žzê¬êU±Ûx íÞJâjŸóÝ/ûŒbŸ•ĵÝ;[ûœ®_:U»¤_Ú¤=[I\ëKhM?ö8Ñí.@³°, ×uéêê ?¢Éd2\oÉd’žžt]¯P·t]'“ÉH$Â}MӬؾÑul6K¡P˜Õþªüê~¸®6Ö¦ZWoŸf¡i¹\ŽžžLÓ ïµeY Ý“t:®ëá̃L&Ss[uŽõë×Ïh?¡5Ô³Ïz¶ ‡–}ÎÆn[qm3µÕЉ>_Ã0Ä>s©;!~öµÍFf<Õb±Ùg½ýª ”m&“ÉYß?a~vo%qm÷ªk›©ÝžsÎ9ìÞ½{ÆõªØnŸg``ÇqZ¾ŸÐjÙg#¶ ‡–}ÎÆn›Á\íe¾ìZh>s©;!>öÙ,یޓ…nŸbg‹i÷Ö¾qi÷Îw½*Ä i÷Ö¾q±Ïêë“zõÐb1Øçbn÷V_£ôK7Òž­}?âR_Îw?t¡Øã¢T¦ÂóãØg{ËEêAa&ÄÅvõv¯ØŸPM\lS•e!Õ«í8_-Ä®/bŸí-o;»Ž'q±IiÏÎo?t¡Øã¢ ù5º®S(Âxlº®Óßß?ïåP±ïê•s>·sÕ+Ãlɸ*™B™¸Ø&4ç]_ȶ9ßö"öÄ>Û[ÞêãI=(4J\l÷Po÷Šý ÕÄÅ6aáÕ«í8ßTe»^œˆ}¶·¼íDì:žÄÅ&¥=;¿ýÐ…b‡Œ‡Š ‚ ‚ ‚ ‚ ‚ Âl9¬ÝAAAAAAˆ;"¨‚ ‚ ‚ ‚ ‚ ‚ Lƒ*‚ ‚ ‚ ‚ ‚ ‚ Ó ‚Š ‚ ‚ ‚ ‚ ‚ Â4ˆ "‚ ‚ ‚ ‚ ‚ ‚0 "¨‚ ‚ ‚ ‚ ‚ ‚ LÃí.À\ùÈG>Âé§ŸÞîbLÉã?Κ5kÚ]Œ)9pàû÷ïçØcmwQ¦$î÷p×®]üÁügŸ}v»‹+¾ûÝïòßÿý߬[·®ÝE™’¸¿[O>ù$K—.娣ŽjwQj²¾÷Üs_ùÊWÚ]ŒØñ©O}еk×¶»S²Þ-ù~̽||ä#iwQbGÜÛ¶÷wp&ÄÝÞ¥Ñg"mÛÚÜzë­üÛ¿ý[¬Û¶r¨½Ó FŸ‰´mk÷¶m£,„6p£,–ïL£ÏDÚ¶Sóþ÷¿ŸžžžvcJâ^—,„ïBÜíý¾ûîãýï?o~ó››vÌ/¨<ñÄôöö¶»S²uëVÞùÎw¶»Sr×]w1<<ÌùçŸßî¢LIÜï¡mÛŒ·»±EìsöضMww7gœqF»‹R“…ðý¸å–[Ú]„XòÀðž÷¼§ÝŘ’…ðnÉ÷cnÜu×]ŒŽŽ¶»±$îmÛF‰û;8ânïÒè3‘¶mmÔ=Y öy¨½Ó FŸ‰´mk÷¶m£,„6p£,–ïL£ÏDÚ¶Só»ßýŽüãí.ƔĽ.Yß…¸Ûûý×±cÇŽ…-¨ŒŽŽNúÈlܸ‘•+WV¬ïì줳³sÚã­Zµ*ÖÚÞÞÞX—¯££ƒc=6ÖeŒû=dùòåí.Æœ™Î6£Û4bŸÇ<ëÖ­‹õ³‹û»5::ÊÆéîînwQj²¾«V­jwšB³íó˜cމõs[ï–|?æÎÞ½{Û]„¦p¨µmgr_âþ6JÜí½Q}&Ò¶­ÍòåËcß¶m”Cí^4úL¤m[›¸·me!´e±|gfòL¤m[›¸·mã^—,„ïBÜíýE/zÇw\S9ï‚ÊÖ­[¹é¦›*–mÛ¶ÞÞ^¶oßÎÖ­[Ù¸q#;vì`Ë–-ôõõÍw›Ê–-[Ú]„ºtwwÇö£¡ˆû=\,Ô³M@ì³ Äýþ.„ïÇbáP³Ï…ðnÉ÷CPjmÛFYL×w{o”ÅôLáP«;g‚¼Óñc±<“Fû¬ÍBh7Êby§Ó3i”f·mׯ_ßîKªKÜ¿- ጻ½Ÿ~úéMç]P¯¨(£lݺ•k®¹†ÞÞ^†‡‡¹øâ‹éíímHñanÔ³Mû„v"ö)ñEÚ¶‚O¤î„ø"ö)ñEÚ¶‚0=‡Í÷ kÚàà ¡Á*npp°Ý÷H ¦²MµNìSڇا ÄiÛ B<‘ºSâ‹Ø§ ÄiÛ ÂôÌ« ¢ù]y啜vÚi¼úÕ¯fûöí O2ØŽŽŽi“:íܹ“M›6ÍçeBȦM›¸á†Ú]Œ9SÏ6aööyà 7°uëÖv_žp2<<̦M›Ø½{w»‹2gZaŸ»wïfÓ¦MÇ„ùB… xüñÇÛ]”9#m[a±!m[iÛ ñDµmwîÜÙî¢ÌiÛ ‹ iÛ6Ö¶n÷å ‡ [·nmIÛv^C~ŽŽÒÛÛËe—]ƶmÛdóæÍtvv2666iûF\ÆÖ¯_϶mÛæó2!dÛ¶m‹¢SUÏ6{{{gmŸ]tQìc) ‹“îîn¶mÛ¶(%[aŸk×®•ºSh}}}tvv.ŠÙlÒ¶Ò¶­´m…v!m[iÛ ñEÚ¶õ‘¶­ÐNZÕn›WAE5½½½\xá…¡ÛX5£££±O¼#‹z¶ÙÛÛ+ö)mDìSâ‹´m!žHÝ9w²ÙlÅߺ®“L&Ñ4-\oYº®×Ü¿X,¢ë:¦iàº.¶m i–e…Ç-Ä>!¾HÛVc^C~ŽŽNrñZ¹r%mµ›ØØØ˜$6„y žm‚ا ´±OAˆ/Ò¶„x"uçÜÉçó8Žƒëº¸®K±X¤«« ÏóÂõêÿµ°mÇqÂm‰D¸ÎqœŠc ‡bŸ‚_¤m+1¯‚ŠrS1ùÆÇǹ馛*\;•‹Üðð0£££\xá…í¾G‚°è©g›€Ø§ ´±OAˆ/Ò¶„x"ugsÈår 000ÀÐІaP,g|œl6K?¹\.Ä>!¾HÛVâIœëN×u§ôИ/t]¯ëu̓¢˜M™ …B(ˆäóyÒé4¦i’Ëå0 £bÛh^MÓèïï˜TŽj4M£P(`š&–eaÛ¶*1&Îö)‡:Ò¶„ú´EPAAA„C×uÛž”Ý4ͺ‚J.—«$ŠÅ"‰D‚={öÌø\Éd2 ÏåyétšT*ÅÈÈȤí\×¥««+ô0Éd2Ó¿Z˜Ñ4­ÂÃFA¡Yˆ "‚ ‚ ‚ óÈBÌï¡ëúŒ=TÇ!›Í244TqœL&C"‘¨¹J^ï8Åb‘t:]ST‰ RÕâT»½AAX¼Öî‚ ‚ ‚ ‚_|ߟU-]×q]—b±X±ÜqœšÇÊf³¡Ðbš&ÉdÏóÐ4-,LöðñؤÜ"ŽˆÊÃDy†(ñ‘Ä4ÁÃuË^'ºˆ-JQž'¬·¬ào5TåMÑ´`Ÿþþrî…Úd$Ø&•* 5Ê“å¾ûöò¢ÓÔ{zX ž“ ‚ ‚ ‚ ‚ ‚ óÄ÷¼Ê¿ó.üi:7TN•»d:òùÊ$ŽìW,ËU¯B!K2™@)Ä÷ƒõ*Y|¡ˆ"x“(±¥PþN&ƒ]~Ô2Ó,{¸DÅÄ“èœ Ï+‹/¦ˆ4Ç7Öôû,*‚ ‚ ‚ ‚ „d³ÙŠ¿u]'™L† â³Ù,–e¡ëµ§¼‹Et]sš¸®‹]šÎªi–e…ÇAaæDó™ø>ø¼« ¼=ð Ù"Œé0î@Á†ý>üc>YÚ'š4¾¤} x‹°Â€ûíÀëò¡¢P({“@ œhZY(Q"†¦•Cq™fY|`½NÔru¼¹8œF…—èõrÊN`]Sï½x¨‚ ‚ ‚ ‚’Ïçq×uq]—b±HWW^iJk>Ÿÿ_ Û¶qJq@òù<‰D"\ç8NűAA(£¼I¢(Ï(‰'>\™/oÿ–,¼> K 8+—áÖ"<àÙ¸:_*Âs>Ü\ʃ¢Ž™Ïû_” –ßâ  ?î¡BKy¥d2ÁO”—ˆa”½K4­ìeS XMTßLô&…6›ñPAAA¡‚\.z˜$ ŠÅ"¹è”ÖÈf³ T+N“Ïç) í¾LAA˜’,`–~ZÊ3’L–—©Y*ñºçÁeyø«<ã? ìöàœ4 {°8Nƒýnðó‚ ¯HÂYÐ ð° {xmîó`™xž¼Ï Ä–UfpìD–é°: ¸ðKÖX`jw ”Ãn5"^Ì—À1åýmÑqÅCEAAA„ºèMÉd2X*¾G®ëÒÓÓÃ’%KH¥R¸¥îÑå===a1(‹=]]]¬^½šl6K6›¥X,†Ûø¾O"‘À¯žö+‚ ,zœ9ìçÎrßj|&ð_U„A?Q”È:Üì¡·¾X„.üuþ,lÿ]~V„§u8̃×›3ð® œ¼µä-²5 Å ¼Ó„ uxÄ…}&¼Ñ„o¹°ø'fàmð‚—ëð6–&|Í DŸ¼^6÷Ò`2—d§¸ŸŠ|é§øå+^Á“G4×§DÜîA!+ X­A*oÊÀ¯u8Bƒ»À‚!ö9ðF ~fÛ58;ßÌ^$ž6 kAH®—jðRÞYÊsr¶ ŸÒà'><Õ¿ Êrµ\k¶Tf]‡À7 ÕÜWPÎ4söÚQ*R-Ï×T ¿¿È8€µcæYg‘¿óNœNÀ]»5­Â €–Hà -=77¸]ÜðÊWòÉ‘‘ÆÊÔ "¨‚ ‚ ‚ ÂBññÇÑŸ{Û4áñÇqÖ¬Á'»j ¯^uË-.¾˜lé¼YÀ}øaLÇ!õÜs˜Ï?OnÙ2üÒs¼öïÿž#ÞüæÙ½PSÐVAexx˜ÎÎNV®\.ett”ÎÎN:;;ÛY´ƒñW­BÛÛàùçO£;É ‘yä´}ûן[o¥¿tp–-ÿê*´‘2W^ …Z>xr¯ùÉO8üÄáüó›öžµ-‡Êèè(—^z);vì—mß¾‹/¾˜k¯½–‹/¾˜íÛ··«x‚pÈRË6AìSâ€Ø§ ÄiÛ B<‘º³yT à8===“Ž“ÉdðŒ›î8Ï>ûì¤í)‹išØ¶M±X$™LJ¸¯˜!ö)ñe¡¶mUÍ'@ÔF š(¡$*¸d#ûébCöË$IºJËŠŒ )e—–-Õ mÃeY¸x6+LX—€‹²ð]ÞdÀ™&Lxpo"Èubð7¸* û²ð~N#È’+¹Á˜f –ŒäA1Í Ÿ‰ªÒ¦òDQTÔŸ¥ÜbzéžÔÜßó Ÿ¯y,Ã÷Ñ÷ïgÀ÷úô§ÉýèGd€Þ¿H­Xóüó8_þ2‰ƒIüìg¤9†"xÇ;°=ü_þeçäG?¢ç™gÈ¿ò•X÷ßõ/ÿ‚uë­ô¿ðC;v,Å"¹tíë_‡LÈq XDÿ“?Áß³çŠ+Hž~z ¸(l›Ÿ^tc¯~uSß³¶y¨\yå•“–mݺ•k®¹†ÞÞ^†‡‡¹øâ‹éíí¥â)‹•Z¶ bŸ‚Ä>!¾HÛVâ‰ÔÍÁ÷ý0×LÐu×u)‹á¶Ç©y,Ó4I¥Rd24MÃqR©T˜F…ïRåéï¯d„d2I:j‡Yڋا Ä—…Ú¶u)‡éR‚O ŽäK¿íÒzå‘¢ÂW)O%¨('½´Ü†JÇUŠ|Û‡‹<¸Õq/XøÀj8Zƒ ˜ÁÉ¿›‚×%áœ$8Å@4yZƒKJ'Ê_¬ŠLy·ˆ' Mó1ÍàʪëÖZÜý¯ÿÊ­Ÿúú‡? †ÁÝW]ŵO*Qw× Ç ÖôôÀÐPðÿl–'ÈP¯íØõÅ/âÿË¿à½ÿýX©|÷»ð¥/á/[Fêã'ùóŸ“<ë,Š?Œuâ‰8'œ@Z×Ñ?ðtßÇ]½sÿ~$§ë°j¼éMÁ¹:;aG•/ZFPFÃÀòÏþÃ?ðí·¾•‡víbƒJšâye±"› \_‰ `–,K&By}(ÁŲ‚míî»)üýßÃ3ÏË L“¡ñq´ûîC{ÛÛ0ÿ{¸æð}zr9ú]ýæ›ñ ´¥KÑ”N5êüêÿ UÖ\LÿÀ2áÃË”÷)ØÿÍo6ý½›wAexx˜›nº‰ë¯¿žÍ›7W,¯V4;::­{¼;w²iÓ&¶mÛ6ß—"lÚ´‰;w†ÊBf*ÛTëfcŸ7Üp[¶li÷å ‡ÃÃÃlݺ•Ý»w·»(M»žfÚçîݻٴi\ptL…ygûöílß¾SO=µÝEi Ò¶Ò¶•¶­bbbbNë£ÂŠeYa L?…B˲Â|**§J.—ò¬ÐK%šk¥º<ÑóOçŲPmÛ;w¶»(M»iÛ ‹iÛ6ֶݲeKMu® D»ô·Cॠ@,± D›ÀÅòà‡œo–ÅIRÓ""]Ó^jƒíÛ¼àÂ2‘æ• yðZ>›ƒ¤àí%ÿGœœ™™,¢DQÕÚ7þá8ú¤“Ð4½·ßη݆»wo0™ÀóÈf³ø¾Ïp÷Ÿý÷ŽÒýðÃdï½—Œï³}ûv~ÛÙÉÁ{ïåžU«xxåJöïßÏ?ú'/œw‡½õ­å»nY(Éd‚ßJD±íàbóù ð¦üÖ´²À¡’Ë«‹+y·èšêŠÔûCgŸ ‡Ž^}ñÕLuÃt½ì5£i ”ž5P‘›eëõ×sÃÍ7sÖyç5õ½›WAe||œÍ›7sÍ5×LJ86666iûF\ÆÖ¯_/N¡mlÛ¶­[·¶»s¦žmÂìíó¢‹.:$:œBüèîîfÛ¶mlÚ´©ÝE™3­°Ïµk×JÝ)´¾¾>:;;lwQ挴m…ņ´më#mÛ¹1‘©—j!åPAÚ¶Ò¶â‹´mëÓê¶­OæK…øÚC ª˜B‹ªMLJÉËK¿=î°á£‘ªI¥ Éå‚õÅb x^à ¡´JûŸkãúʹã•:¼Ö€–ÔUígÀÙ:˜õ£sáº.étšO=ñcÇGÚuùÄòå$–,áß×®Ï㊣ŽÂ^qÌ1¾ñ³Ÿ±iÅ ^qøáX¶ÍËW¬à¾^À=á¾~ï½x{÷r÷'>ÁÍÏ<Ã_îßÏà#°ÿ7¿aY&ét š¤RÁ…F `¨zVÓ‚mr¹@ER¯DŽhrùd²"Ì4Ë ^¢Dëv]¯Ÿø¥"ç˜êH­j·Í« R,éîîfllŒÁÁAÆÆÆ¦££ƒŽŽŽIÛŽŽ¶D½¡’z¶ÙÝÝ-ö)mDìSâ‹´m!žHÝ9wŠÅbͤñº®cš&ÅbQr’³BìSâKÜÛ¶Åb9A;”Ãx©ñjPýûYHæÏE>Œÿ”Ľ¬@9R•:rÐÐõÀáBÓ‚ß–h ºh ª<…BàÌáyÁ¶QçÈ\.Ræ’—¥Âó<<ÏöÆu]ö®ZÅÞà£gŸÍé¿ûÇžtWz*®]Ës¯x…—¾”µwÞÉ#GÁÑ_ÿ:þ­o±îóŸçà¯ÍΫ¯¦çóŸgÃë_Ï5kࡇxÛ•Wò¶’øpk6ËÊ-[0!@” ŽmWæ(òEFÙ ¥ÖäM›œßd‘3ï!¿ÆÇǹöÚkÀðn¼ñFÆÆÆèííeûöíÛŽÅ*±‘ ,f¦²MSìSڇا ÄiÛ B<‘ºsnضïûh5f˜zžG>ŸAE˜5bŸ‚_âܶý² 'è•‚Šò:Ñ( *ÿiÃß—ª(•DE¯:[‡ïÛpFä8®[G ì¢¢`iZ°Î¶Ë^+j_ß~^óš?áw¿ûÇšåt Ÿ{¯»ŽûÿöoÑï¿€]ßûÅÁÁ A%™Lòë;yÓ£òñÑQ–Ù6·<ü0ïù›¿aùß«Vaz8眃{ùå¾çžËó¹gŸ{.~8KK^"zU=®iZ9¯˜r¯©ÊV «ea~•j7›M›6qÙe—…1z•ÚÛÛËðð0£££\xá…í¾G‚°è™Î6{{{Å>¡Mˆ} B|‘¶­ Ä©;›C.—›2L×t9Ta*Ä>!¾Ä½m» øA˜/² âQÞ+êyâºe‡ ·äÊrM¾¬ d³eo×-{£Fàe’ÏË”(£iÆJNù|°íÏí{Ãsª¤òÊû$8O–Ë7làüG`ïý÷sßûÞ‡÷îwã8–e¡i¦iây¯6M–•b½þƒ„}û‚ ËåÊÊŽe×ìû ëœ©Tž:‰Z à _:®ëºd Œj“©¨ÆëeÞ=Tê±eË6oÞÌÆÙ±c[¶l©SS„ùGìSâ‹Ø§ ıMAˆ/bŸ³Çu]²Ùl˜øÝu]R©¾ïc•q’Éd˜Åu]òù<¶mc™L†d)‘m"‘ ™L’ÏçÃýÅóEû„xÛ!ˆ} B|‘¶­ Ä©;g‡«FŸ"躎ïû8¥Aß÷I$ LÓ$›Í†Ñõ™L†þþ~Ç!•Jaº®ã8º®344„çy$ LÓœQ{aa#ö)ñ%nmÛ1þº÷á #`heaEÕŽ[ö6QU‰ ËåT!žW™;}` ,¨ø~肦ëT’úd~ñ‹¸ˆ›o¾ƒ§Ÿ¾Žï~×åt`å½÷‚irâ®]üùˆïûa(/Ó4ù©ãpðõ¯§ï¿à¾^ÀÐuÞùÈ#l¸üòÀåeÃ†Ê 6Œ ÀêÿѺqddV÷P×u4Mò¬Ê|iùÒ9qÅgêLïsÄ÷}R©{öì C‹VOÖ€ §mÛ Ïç)‹¸®‹®ëd2R©@èÝcÛvY ¢<ácýúõM¿†Xy¨RY BŒû„ø"ö)ñDlSâK[í³H9›.ƒfi9Ùª}ÌÒ>*Ɖ ÅŠ#º}­ó˜”G j`Ûv(œ(’ÉdE2Ýb±ˆaá,Ó\.G±X¬8†ø€`@)™LV$µÏårálSãHd+4†ÔŸ‚OÚi›3ð¤øðÃ<|©”d^eöÈçËÛ:Nð£ë&M¢ih24죒É+G%À$“póÍ×ãºëKŠ8N0©à¡‡~J±X C{½oÕ*ý§âóÿøüå /á´L— Œf&ƒ]3þâÑGùÇ{ïeüì³Ëî.–UVq”êcš•"JP^¢ë:aNžˆ¶l‚ö…Y*¼Mоð)ÇU›®ë†õ»ÊÑ„,¢'Q”'M>Ÿîg&C±X 'kär9Ç¡«««b5ÁÃ÷}2™ ãããMc'¨‚ Ìß÷ñ‰ö‰€âÀ¾ßïc÷»yá‰ÐÊÊ3:Ѷí0,—"‘H„ž¨ét:ô²hbšf8¦§¼a]×e``€«¯¾š¿û»¿ãÑG%™Lâû~8AÃ4M2™ === ŠÅ"ßúÖ·øõ¯ÍÞ½{éïïç«_ýjÓï¡*‚ ,”û_èZi5AÁfŽšÌÁD­´,Ú,ЩL&çSžp©&>¨uj{UM›uΫ~{ÀØg´ûV‚ ‚ Lfªù?õ•ZèÓc*šQË‹fÿ­B%؆ðA„FÉfK!ºJ?îÂ#ø H”; Ð#'ø;“ D•d^yž ðîwïfçΜ{&Ü}÷—ÐõËÃó~á OcÛ7ðÖ_ýŠ}Ë—ÓÕÕæòÐ4 Íóø·—¿œ;3¾ùå/óè‹_ÌU?ù ·uwóä°mçN–ŸsË•ûKI4‰N(‚‚)ÅGåFiò$ᨇ ˜8°æñ5ûà±ð@i™?ùÍOxöà³ ®äbïbö/ßÏoïþ-g<“Ñ#G! žˆJ»¿¹›û7ÜϧÿùÓÁq=BoÒSMÌÈf³¸®K¡P •J‘L&Ñ4o|㘦† ýéOЦiôôôðÆ7¾ß÷¹í¶Ûxï{ßä£)º|âßà{»¾‡ã8‹Eúûû"•Jñ†7¼ë®»Ž^õÏ\÷Êë°m›'žx¢éïåa3ÙxppíÛ·‡³iÓ&6mÚÄÖ­[›^8A„™ày¶m‡I/U¬ÊÅŒŠ¡¢9”êER!0}*EŒ©pJÇò &%d#?« ’¾e®ÒO"ò»§ô;E=¢‡`‚C¶t¬®R²”\]K¿£"ŠFû´Pú­d0r4 u}vé|ªLDΓ/•Á(ãÀŠí~D‚ ‚ ‹–d2‰ã8aøŽZ!Â\× Ãpø¾OWW×!ÑNAfJã¡Âxy@ß`ÂV—–hÂyô¦a°íÿ/_Žf¬Þ»—õŸÿù|ž 6`YŸþô§yç;߉mÛ|ñ‹_Äq:;;9î¸ã¸ì}—ñÚ^Ëúõëñ}ŸÓŸ>Ï}îs¬[·Ž3Ï<“K.¹€ÿ9ó8üŽÃI$XXà–¿ÞB÷ÃÝ|òÑOòø_?Îृüløg¼èÙqöágÓ÷@ß9í;¼í{oã†nhúûÙ°‡Ê•W^ÉöíÛ¹ì²ËåÒK/eãÆtwwsÓM71::Ê5×\ÓôB ‚ L…R½u]Çu]r¹\“1Îá²â@† a™áþvä·F "¨ ŠJœ°K?iq!YeqBy˜‚„Ce²‘R]`€©£Ct•ÖåD©\Vé˜z©\ŠäÇ™Ê ¥úo—²€Rœ¢lß¼í¶Y?#AA„C™D"QsyÔÛDåOééé CtDQùS‰D.E…éA„©ÈôïU¨®Û=ØYšAú†\)*…ü@ C¤ÓwJ aèz Uäóå ¸»v]Â?øq2Ûþ ù| r¨S@8QÀu]ú^ö2ÖìÝKnË–Ü?çÿûüL×ÉýçJŽI4¡¡¡ÀeÆó&Âó‚Äó¹\ý WûLƒïûd³Ù0™ •¥pÓ4Ã\f¾ï£ë:GÜpÏüÑ3ì\³“ì¿fùâÓ_ä}/y¯|ì•õ‡Gaš&7õf®?È‹ÿèÅ\qúô|±‡ÿ߃¼é¢7ñ•{¿ÂÇF?ÆE«/bÝÄ:nÙ{ Åb‘»÷ßÍæg7óŽËßÁwÜÁ®ïí‚Ã’%KصkgŸ}6ƒƒƒônèeÆ üüšŸsýk®çQûQö}v&&Ÿ=é³¼áEoà¥ç½”³¯?›ŸýËÏ8éç'±¦o Oþ¿'ùÒk¾„~ºŽk»>~8't'žÄø•ã| ó¶ì0>=ñi>öøÇصaëŠëX§¯ã²K/kúûÙ 2<<Ì7ÞÈõ×_Oww77Ýt\sÍ5¬\¹’¾¾>LÓdttT‡ ‚0o¨0_*wJ&“!™L†î˜óš“§ˆyÊGTT°~aE'#ú)çúÒ DŒbäØ6åpXÑpZ~阵ªe·´­F pø¥ã' „µO¦´­]u|…Áô¹ÇT™UhîBäï|ûÏ£TþTäü‚ ‚ ÂÜ™.D×ÄÄ èX–…eYaLó%K–T„Qís&%ºN§Ñó ‚ ‡±Ã‡¯ÇK}¸D‡“Jƒ†x ¤Ó00==At-¥K|ùË»éì\M:F×uN=õ¿¹ûn—þ«&&*¼(£“s]×E×u~ôªW¡ë:ºv-+2öŸ|2ÇœvZppÀ®® J(Éå‚éz9á¼a”·o59A•#Zo‹E,˶m<Ï …Ÿt:ÍÈÈžç…‰ÛUHN%¾X–Å)ןÂÿú÷ÿÅ>ô.ùâ%üôòŸòû|ûÛßæuÆëH&“ä½<š¯qî¹çràì\úg—’Éd°5›§ÿôiVÿåjž>êiú'úyûßÎq»ãðë猣Ï๟ŒcÿêX88pê¯O…óšûn6$¨Üxãôöö†b á¿.¸àV®\ @gg'"¨‚0¯¸®K&“Á0Œ°ÔuB¡Ð²P*Œ–K ’ø‚„ÊÛåüŸ#¥¿•€¢Bj)/Õetƒ@ 0 ½0C¡¢¿´¾‡07ˆ.µÄ­t.³´^•-AÙ+&:7Р,ð̲p¢D§jy3Ñ)‡AAæß÷I$ô÷÷cÙlvR2Z ô(A„™p”cœèÂYÀNà9Nö è”S@ð[×áæ›?ÃÀÀç±m¸æšOñ±u“Ï+ï“`Új×^øÄºu|¼$JÜtæ™\pÇèºÎÕkÖð‘{ï ½)s–xž\z)K7l óÆá—¿,Ç‹æ=‰Š&¦ü@ ¬ ]³? ÈIÒßßNJPŠMÓä̃g†yDnyã-l¿l;‡½õ06œ¸'?ÌõŸ¹ž ÿâB:¿ÕIVË¢ë:^~€ek–aYV &]åriòR²Ù,oyË[p]7•ÞøÆ7òÈ#000@>ŸÇ÷} …ûÈß²p?W|ò vnÝÉ'ÿ$û×ígéw—òÈgá%ϼ„±¾1γÎCëÑ@ƒåW-›–ÛËáKÿ7–ƒK³KËdjF®O°L…UQ33”ï`5«Ë7Ï€e¥ŠU·®âyžoê{Ùpȯj‘dpp¾¾¾ŠeJ\YìLJæ#B[P.IË ¼- #Ì2dY|ýç?ozè/•_$IðMW^%J\¡,xôGö‹ú×úz˜”­t >µÅU—(‘Âeê|¤ÊC„È6™Ò5äjWÕM³Á ¨÷j-o• "¨‚ ‚ ´ 5‘)_ r¯ë:ýýýs<ª ‚p¨ãŒ!ì5á yø ½¼H+k*wŠÊ‘â8 rÝuÍ¿ýÛçI&!þ>ÝÝË*<6LÓÄuœRH1ƒ½ãœS( ë:†ap®ërË?ü'¾ímÁ>®ä8I$Ê'W!.“ɲ›Ìt48–|Ñë.âûßø>üø±,‹Ëßv97Üs–eaš&þGÎÎ;ùÅs¿àWø+r¹'æOdýsëyÍ¿¿†%é%àÂùwœÏŠÿ»lÈerÁ€ÍG¡`JÅ1B¦¿¿?ôÐÉår¤R)t]'Wò¼)DÄ ‘~¨'~éDÐa©¹l8óà™A¸’`åÀYÊ‚IÁàWôv)‡JQ¿È6VÕ:¥M4$¨tttpã7†ßtÓMôöö†ËÆÇǦ£££}W3‹E²Ù,{öìiwQáÆ¶mRÅ"'~íkôPöÜ0 „¸ó _ ›Í’L&1M³îñ|C#Tè+•KD§œd}ˆ²HAéÜÑ&³%*dD…j”ׇÙ¦^µ\].«jß(õïÒôÔÚ_«ú-‚ ‚ , lÛ½ÀU¾”j’ÉdÓr¢d«öêºN2™¬˜ ¥fîÖóxqÇq¦Ü.š¤WÓ4,ËŠuþEA„C‘›]Ø_„;€³Ì@pݲvá8å¤óh–K–”ëß÷)‹èºŽ¦i˜¦Žyß}èºÎgM“}ýý¡€°üª«Ø°t)8†®'5Í ËýÀ@ ¦¼¥”gÌб"7³ëÂäµ=©†††¸áË7pÔ¿ÅÙœäH1rüÉ“ŸiÆ¿øE>zîGyùª—sì+Žeé—ràÏpúÏN‡ÝðÚÌka”ÐÃcÅVÿW sk$¬-‹Ø¶ '*ÜX.— ¨j¢âÊÒ+—V†'QñîMʳ| *Ò˜<ˆUk.Æ\¨ eQ *\pÅb‘+¯¼’ÞÞ^ŠÅ"½½½¡GÊøø8[·n¥³³³",ØbB5"•ª†åt 9AšO6›åë¿ÿ=¿ÿ}¾¶tiøö ¾•Y‚oöøš5|óÀvŽ“¿Å*t—OP·(Á[%s7 „sà{ï0YL²—ˆDšñE¨w ² ¢¾OUG˜S«ž3[O½t¦Z'_JAA„… ååû~(–d³Yòù<…B¡eòù<†a„â†ã8d³Y†††Â~w>ŸÇ4ͺýð|>ã8hšF&“™´.ŸÏ‡áTÇ!ŸÏWœCAh?~)lÇ1I¸Â€wkh¸âûå¤õ¾7ß|¾ÿCúéë]×+¶+/MÓ8ö›ß ê8Ãà®ÿüOÞù¥/¡û>ôöj #ø9\ ‹Š<ä—C‡¨$ºÓ*ßýÚwyê?žâÿãI§Ó|þ‡ŸgÙç–1ú£X–ÅÏø  8çßõ0Ÿ?÷óè;u¸ÈÂßø;Žºî(V+áNàn¸|éåð.‚œ4å¸îÁÌ_ØSú»”s$ÊÐÐP‰)Z·× ÕY±<2D;ÚD¨%” .küö¿¥‹®¦ö°F6êììäk_ûƒƒƒlÞ¼™ŽŽ¶lÙ¡¿^ýêW388È5×\Ó¢«o?Åb‘T*…a˜¦I:Æ÷}òù<žçá8ÎÜO"B]T¸­½ûnÞñõ¯seDLJo"pæ­·òôWpïúõ ‡ ‚ÐZ~ëÁ½>éÁS‰@L‰¢i³ˆi¿5 vî܉çy¡§…òFI&“|ò¹ç‚0ë%Ïĵ?ù FÄ óòO ”Ë 躰 H–”’ç´`°ÉÎ)çù°aßIû‚ÿC0àä 8•{Z‹sn8§éÇl8‡JwwwMÑ`ãÆlÛ¶­"ü×bDÍnQ†¨i…B®®®Pñœ.¤ ³' ÜùÐCtÝ?{þùŸq™ZHÐê“?ök>óÌd2œ…Abv› ®©Îo Ó¨–)•©ˆŠ ÍxPO¼1JeVç©—Cd¦¬ç’DytÖb¶yYAA„ùÅu]Ç©æ:—ËÑÕÕ&§…`ò¡ò‰¶·]×%ŸÏcÛ6†aÉdH&“$‰PÀð}˲ÂP#µ˜©×ˆmÛ˜¦‰eYáÈ鎑ÉdÂëAÚÏ“EÀƒu<0E(ŒD¬ÈÝo}ëüê;7±ox'ò=4WãÒw]ÊU¿¸ d2É’Ûo/çCÉf5&Ÿ‡`òj|­  ¸Ù D” À±Vy® ‘R2öüýÖyë*DlÊTyXª-åÔwžÊÒO/eóq›YyïJVÞ»28^.2.âu½¯àu?}]y E%a¡ìu’$€±JCÙCF§9ᲄ)iXP™Š•+W.j1Ŷí0)Q¡P@Ó4|ßg` Ȥ300€®ë¬^½ÏóÐ4Mb¯ B“Éwß}7»ßþvîñ}>”ÍòÏŸþô”Û«î’¡ëlH&Éf³a eE4¼c5ÕÞ!*¤W=±¡=o®¹ž¡&‚ ‚ B³Q‚D­~­¦i†Á¯~õ+¶oߎeYŒŒŒàºn˜ÀÖ4Í0dX&“¡¿¿ÇqB¯5!qhhÏóH$1íU¸m(ÇÀWýïF˯Bs†mÛa¿,Ë"•J‘L&ü0êK!>ØùÌWhð&¦øD¼Ü=À­ÿtŸ¹þ3\rÇ%<²ÿ–ógXôóŽ—¼ƒ£¿ûu>ñÅA61Q™Þ÷ƒ,öÌâÝçÁÏ<ø¸ ÿÛ‚ëاI\´ÒHŒR>:ìûù>v¯ØÍ:{]9 o)6ûãý8kÆ×0¾fýq;ÿçNŽxðN;ò´òà‘„²Aë×*EREa2yPHˆêb[6½4W»hXPåÚk¯ett”•+WbY֢͗¢ð½ bš“•Z¢Kµ 2ÝyªPQ¦Â÷}Ž;î¸I}^MÓBïÏóp]—%K–Tl£„zQr¹\E8íb±H"‘¨‚¬Û¶Ñ4T*–U•%ZÞd2Š.žç‘N§I¥RŒŒŒ4öüA„¦¡R€ÜâÁ^Vð@>Ð9jÅ'yöág9öˆ#8òñ#¹÷‡÷òcÁ²µËÐÇußx1zàCð0^„'áW6œ0PÎ/rðð*®O{à NOÁ,rè‘úª:”HIür†x×+ßÅÄ'øÆCß`ÍO×ðæçßÌ_ÝýW<¿æy¾´üKŒŸ?ÎÄßL€çûü Éouu\×^Câ§Ç”†•ÁÁAFGG¹í¶ÛX¹r%Ì0Ù¾}{˜œ~1¡]¶m‡Éê¦CåWÉd23jˆù¾/!¡ÅÒÏ`—ÂéAãɲ¢ATh×uÃΙÊCR‹\ƒËAAaVX d®›®jšÁÏ\ÏSE²2·ÖDA•ðýÿñÙºukꍣúǵBuÍ4ù»®ë {¨¨ÉQA&›Í†y\Ç!›Í244TqüL&C"‘˜ñ½AæN4EÊÃ%eå9:4¸dŠ! î¹?{è5¬ã,øíj\û /{7®¹íýWr¢¾:ð2)¿óÀ4‚™µƒ.±÷ ’Z’eoXÆçŽþ—[—‡‚/çòÊ !,`ktÃÞÞÞPLÀSe¶ 388Èððð¤u£££¡€Ó.ÒétǵÑXªÊ…Ù0 t]jQ|ßcɪa:Ýž¡ÝÔ³M˜?ûTuÞ¥_žWÑ)š †a„vgÛ6žçMª=Ï«°Ûhg/ËYÚA\ìS„ÉĽm+‡*RwÎ%0¤Ói¼ˆw‹ ‰mY§œrJ(®@Ð×Uá¾ eTø-µ¾«« Û¶gT–êãÖÃq<Ï#“É„9YT?]WE”¨îƒ;Ž3çþ†03Ä>!¾ÌwÛV¥ I8p$pm¡Ò13$pBdé3K)RäG/üˆ×=ý:ýä£\øÔ…è†xlða¹û=XgÉÏŠð˜ ÷™aByN ŸÇu]r¹\èBìû~E¬ÖL&a´7]x1AhõlæÏ>}‚ ý”Å”ê„ò³AÓ´°C˜Ïç+DP(Ç[Îçó8ŽC2™œôÿ©…¶ûa2qnÛ Â¡ŒÔs#—Ë‘ÍféêêÂ0 4MÃq2™LØÕut:®ëxžW‘3%êõaF8AJ…ÙªGµ§ˆÊo2Ý6º®“L&'E€P7ªÏ](Èf³‹ÅŠ>B»oû!ƒØ§ Ä—v¶m}à€'pM¾” ¢X†C®E‚p#>¼äö—ðÕñ¯rpýAÎßy>G>Êúƒ:|ˆ ¬—ë¿¡Ç„׿ «A>{p¦§Ú+ÅÓZ­MŽ _ª®Tâºn(ð»®‹ã8ô÷÷ÓÓÓŽç:ŽƒµÍ’xñ1ã7¯ý ]뺚zÌyT†‡‡¹ñÆùñÌÊ•+Å4MúúúèîîfëÖ­\sÍ5ôöö2<<ÌÅ_Looï¼åiQ·µÜ’'0`Ï›B ›¦iÒÓÓØêºN±X Ì®®.’Éd8K&NW$Ë„ùb:ÛæÍ>S =º”ç×\P¹t: ±˜‹Å"{öì ;Tº®‡öŸH$ÂÄ”©T* (‚Š0ßÄÉ>A¨$îm[A8T‘º³9är¹P<@pˆŠªíì8N˜`>J&“!™Lâ•Â÷ªõÛEûßÕëjÑÈ6Qt]¯ØÇ²,,Ë ½kj•]hbŸ‚_âжõœ Õ×»zjDµ´ÆogßQûxýI¯ÇØéƒ–’d` w܇o¹¾,û¼k E¬ *_¶šÐÓÓC2™ Exå©iº®K}Cvž²“u/Z×Ôc6,¨ìر#LL„®]Õî_Û¶m›ò£££ôõõ…¡Ã”Á188HGG½½½twwÓÝÝÍààà¼ÌDPña•!L^Éd fjZýp¶¦iR,ÃÆe"‘`dd]×Y²dIÅyTlYÕ*¬P:¦P( ­ žmófŸ*¥¦òEQ"c³¼¶†††èêêÂ4MúûûÃØÐŽãP(H¥Ržb–e¡iÉd2ìp £ÂŠ57âbŸ‚ L&Îm[A8”‘º³y¨þj=ê­×u=¶mA ñÕÄ>!¾´»më¾ w1ŲqEqçwòû•¿çüƒç³lÙ2ÞÀxžçyþøçƒn¥ù»n  hZyV¼mÿÿÓd°>‚²Njk˲0 ƒ|>O2™dhh¨"¯WÔóR&É:4”C¥££ƒ7V,ëì윱yÁ°eËÆÇÇdëÖ­tww‡Êfõñ:::¦É·sçÎ ¡g¶(—å`¦ ¤R}­^ ét`ÈÉ’ÍM—ò$:ÃÅ4M†††ÂF¤išáºd26â”ëq­d{µb¼ ñ`Ó¦MÜpà í.Æœ©g›À¬íó†n˜”¬²yÊ9¿\×Å÷ý¦‡ÀS^aj†²­d2Y!Z …p^¡Pg×U£Â„µ ×u+Bäóù†“v¶šD"z5J:žñ>µfÓ¦MìÞ½»Ý·aδÂ>wïÞͦM›Ø¾}{»/O8Q¡üñveÎĹm+³AÚ¶ÍmÛ.fÄ«c~QmÛ;w¶»(sFÚ¶ÂbCÚ¶µm§Ê—¤ðK?XÐWÒ%’É@Q<÷Üs,¿{9…UÎÚsWdIb G|ëè3‚%Ç „Ó vVã#º^>˜aÔ ?”Ífñ<Û¶Ñ4l6‹eYaxI©ÿ[·nmIÛ¶!•îî'3ett”k¯½–ÑÑÑ0¹½š¥ÁfýúõM)›ÊeÑRåLQ6P(@U®ùI†Qá¶5´B¡Pw†Žõ3iÛ.v Ã¥yDÚ¶Ò¶â‹´mëÓHÛÖ#ðN ¹°¬Æv?]ûS>q÷'XzæRvýå.ö}vÇs<˜gU $Éd0˜›Í3ãM3ø‰Ô[žeáÕwRã³*}:fhh¨mÏD˜­j·Í8‡Êèè(ƒƒƒ¡ÙÙÙÉ…^ºƒ5‚j ŒsñÅÓÙÙIGGGÍs©š­$N‡³ÖUH½©Æ3•í5’K¥Ó¹;eðÃ0DvÉͲ,\×Å4ÍI‚Ð,jÙf___ËíÓ'ðNQCõ*©W«DMÓN>Yms*\˜aø¾O±XÄó<òù<{öì –yž‡a“i†×^ÚWÓ4òù|úO×uºººèïïŸtÔ±mÛ&“É„ß ×uÉår¤ÓiÇ ˆÎÅíÔ÷}Ç!›ÍNûýІøR‚XÔ«Gå©™ª1âû~ ±§§',·ú† 5‰D"|GšíÅWÚeŸ‚ LOÜÚ¶‚ HÝ)ñEìSâË|·m}‚ ¶°²ŒÊP_ Ó3)Rä}‡½Õ»—c¶FÇ™/ VêzRÈ÷˶–U9x×±m;g¼¹j¿è•vÛ§ SǶ­ Rw6ƒlUX]×I&“aÛM…?™®ê8ŽãÔÜVM‚`òRµ‡µš°TšT3ÕzÊ[¡Úâ´ý[Ýê#ö)ñ¥]mÛ=æ‚–Ü©'°¿øùó°ç¬=¬v¾BÇ§Ü ´ïÈfOu€:u”J"„aÔs¹Ùl–B¡@¡PëÂ\.Û|`B{h(‡ bÊöí۹ꪫ¸í¶ÛضmÛ¶mã¶Ûnò¬Pl™eœãããa ¾ÞÞÞ0Éq3GGG¹ð [z¢ƒ•nɧ›«8›I.—#—ËaÛvÅ ªr©V¦Ùl6ÌOH$Èçóá,òéP™Õø¾O6›Å¶íp ²§§‡D"AOOOØM§Ód³Ù–$éV1ʨ««‹Õ«W“ÏçÃks]·"ÇBu&Çqj†fŠ^§Ê3ý?fŠLe›@KíS¹v*ÿ 剭 g‹aa‡M…øR–e‘Ëå( ¥lÿE—Gó:ŽSq| ì—F'\¹®n3Ýzß÷ééé©è#g³Ùо­ÐÄ>!¾´«mû¼„€_F±+Šã8ÁX¤‘ÅÄäe¯~¬*q¤RÁ¬÷l6ØqcjÌ#™L’ÉdH§ÓìÙ³'ƒP‘F$Ä¥PMC*ÃÃÃ\{íµ\ýõ“\¹V®\*—Åb±®—J__7ÝtSè.¶cÇ.¼ðBúúú€ ®ÙæÍ›Ù¸q#;vì`Ë–-3 %6\×å ?†ëNpœàq¥ÙQ‰Ô¬îè`©¦i!ƒÔ`©\Íf³áìqÇq& €FI¥Rá ñÐÓEí¯60M3œ]®Bÿ¨<ét:Ü7šÌ{¶¨ÙK@(()uXå¹èêê ·W3ÔLþd29iV¿a“f¯+1H j†AOOO8s^ͲWBK#3¯:ÓÙ&´Î>‹€zB¾ï‡a¬”{e\Ъ\C‡††Â2FßêJ„ì³,‹T*E*•B×õÐfªC)×R•{E 4ÊC­–·‰òr‰Š&juü|>?ãyù|¾f¸0åmS+ŒYuÙ2™LÅ1TXÃj<ÏÃó¼ŠcÖòN«þ®éºþÿ³÷îqrÔe¾ÿ;@HäR !d‰5\M@–Yv¥F×˲öDWTâ‘îƒgÝ_ŽÝëö({vO÷š]eu/ݸ'®·%S»xåæ”º°2;ŠŒ€$%q€„T2\’p›ßÕOUuO÷LÏL÷tÏäyç•×ÌT×å[ÕõT}¿Ïçû<ϸz,ò½tuuqâ‰'Nñ›î<ÚiŸŠ¢LL'ömEÑwg³¨SöööFýÔFIB2¡&Ù'ÌårÑxSÈd2 …бåDãÚÉ>OFZ'×Ïd2š ¿¨}*JçÒ®¾íhBãþ˜5¾füÁÒóÞ|‡½«À ëØëÃÎò†½½qdJƒ“¿}ß2a$S¯+J#4$¨ ÒÓÓ3a^¼Ë/¿œ-[¶DëÖcëÖ­ GaaÉа7ÒÓÓÃÈÈȸϚ¤ëÙ¾ý)>ô¡ð8 ö #ûL§Ãö¶=ýš*µh¤®CµHÐßßÕ'™:ÉŽ¥ÌØ6 £¢·ˆ(Ùl×ukv*S©TÔ–Ùïù|žl6Etär9R©ÔŒT[Çq0 #r¬Ê¾$ýü-6RKaÇŽQ %q\K@r†S2¥^Ño™Å”|˜öööR,[^Ï£ÝLd›Ðû oC„3ùßiø¾O___$*Jq²É{W¢P&B"3„l6K:&z{{'´±¤P‘ _•(•©´YfíU?Gäg½óhäŒö™ÎöIlÛ&“ÉÙl6~wìØA:æ‹_üâ”öש´Ã>EiŒNéÛ*ŠR‰¾;›ÏTM2INƾïO¸éË5©Á—ìW ù|ž®®.ÇéÈ1Ç¡€Ú§¢t.íèÛ¾À <ìÂ:ÂR'I—î]»X÷ø:–,ÚÅÑW…¡,'”Õ—BÄŸ9 ’Ë墉¦¶mG¾L™ÌÚ¬w2ÿiHPÙ·o_C;›HHI2‘03[/KqÞ/YòÞñŽPi´T‡e…Eë ººÂTa™Ll»í YxÚ4ÍHèçd__ù|>ЏÒé4½½½QŽÀúçF}H=9f>ŸrßöõõQ,#Ñ¥ÑÚ'RÈ[Ò‰£U¶'p²-À¸”hÉöKdJ2-™ˆG§Ëó<ŠÅbä”–TDrM¥mRP|ݺumùÞ›ÍdÅÄšmŸaí”èoÇ©+vuýýýQátˆSñ5Êtë‰=e³ÙºÂžƒ’¶dY{öì‰R+4"&ë¡T·?y ªÉ6êWm›2¸žŽh)¶/s’‚M>›O̶}*ŠÒ8зUe<üî̦½m')âHñZ$ÓbI6êHì‰~™dHF©Hô¶LœK¥R5Å–êÔ\ÕcÃZ©»d’¡L‚ª&9æSA¥}t²}*Ê¡Îl÷mNÃ[]ð ð_~å„wÇqXù«•<¿øLŽ>¶,zÈó;³ÂÀÀ¸,‚iš‘¨R(¢Ééò¾ÐÎJ£4$¨,_¾¼!QepppÒÂô‚t¼z{»Èf'SÄí—#ìpFØù4€0MŸç…?!´ié ¶ÃEü(*êuéKÄF­Œ8•S©T$ŒHº®øz‡×¤Öõ¡CjÇ´ IÓ4Ù²::H:ÿ ©“$?ïé§ŸÎ 'œÐ²vÏg\@Üï“ÍXëj “E“5“zÅ×Eô«^V}=§2ëO"Òª÷ áó³á¤©Tªbð+i¦H"iÐD¤IŠËŠ¢(Š¢(ÊÔ{=³d>HÒh_Rê™ÈTÒ3K?M&øHjÛL&!“}îê6TOhªÕÆFDuš)3E²dÕcß÷ÕA«( r| v° ðªæØ>öÇX¼x1¯<ã•<2öÇ©3Ã&(€-bI521À÷}úûû£ÉèêCP¦JC‚Ê…^8i:¯-[¶DEŠæ+V¼›»ïþ·Ýö¾ EnÂH2ƒPDÉ”:€¤¸n¨ž:NX‡¥»;®Ç2 ÿ`SÀ0ŒhPÒ1šË…Q6S™Œ#ÖZ³Ö%ÝYعí'vÇujE'ÉçÃúPž¦J ‚€ï|§‡]»>À¥—‰mïnJ˜ˆ@טNgFÄ“|>Eô@(¼†Á–-[fÜÖCо N÷¥L™…×숌‰®f ÄΛaïÚREQEi.ÕõIJ¥½½½5ÓhU#!úúú€°¿'5@¥Ïšœôçû>™L†¾¾¾ŠˆõéÖP‘TÏõд.J£A¥OÑÄó<úúú¢ kžçÑÝÝ9h È&{ÉVIAq zqìvúÄBEi5‹£}Nú€W¸’Þ½lcÿõæÿâLΜtõ|#R¶··—Òé´ŠžÊ´8¬‘•Ö®]Ëå—_ΕW^ɵ×^ËèèhôÙèè([¶láÚk¯eóæÍí>Ÿ†p]—Ý»/㨣>ÃG?ú\´< ŒBÉÊö(Î ÊŠ(ýåå.¡°gO(  …"ÅÀ@ø³N‰€–áû $¤NB6›Å²,úúŒŠöÔˆŒ&ÂÔeÂÊ•á²xÿ~9=W|× k?ÉöåþA¹ÆI| f©}}áú[¶üˆÇÿ`$¸<þøvíZ2®S•׳^JÄÊknñ Çð…/ òÐCÿíkåÊxÝR©ò§¤ûÊf³d³Ù(òD"Jº»»Çí;›ÍÖ­³7U$"ºVJ0©ª“¹”j$•yrœÒÝÝišÑ}“Ëåèë룿¿?ºÇûûû±m›R©„ã8ø¾ÏÀÀ@$$dΙÛÕÕE&“¡««+ªMÛʬŠÒɬ7¡+áxàOàMðáufÅŠ¼áýoRAHdÞq]7Š“l3òÞ‘”ض•,P”©Ò °yóf6nÜH©Tⵯ}-¶móÚ×¾–×¾öµÜ|óÍ\sÍ5\xá…í>Ÿ†p]—ýûWsÛmÏqŧ¡xÒM(”Ø@PX©îb‰Æ™"NVm‡ ­šô’ìcA,.x^ Re…Ÿ•€[ˆŸ;¾ŠIr¹pyÄûó}¢Ž°ïý·¬PL’6åó°k×úrøk(¶A(0I´Žï‡‘yA¥’G&³·â›L–’úò?•JE3ó=Ï«H—$Û5«O(M&“©i|ß§¯¯t:=ïêí)3Ãqœ¨¶B&“ÁuÝH8‘¬Aàº.CCCãîÛ¶ñŸ'ŸÏcš&ýýýìØ±ƒŠÅb”z('¹äå$Yòx÷îÝüìg?ãþ5÷³ñávØaóOßz¦Yב'5•%í^6›ÅuÝhÂ9 þeÆ4,¨@(ªüà?ˆÄ“7²uëV\×bJ¡P ¯¯Çq8óÌ£ÃP/ —P<é'¬‘b'~¯çž´©/¨IŸcò÷äûq:áL† ¡AöWÅÑÕ‹:Žþ÷ Cè~¯|b¥R¸¯R)üoš¡ d¡"Çùý>¸ÑMcÛ©H0*à¾pý¾¾ðo߇k®Y›¤Bóýð§ˆé´Oo¯Ç‰'¾“w¿{žnÖY/°sç)Ñ5“ssÝP” ‚°m"Éõ”ˆ—l6Žr]Ø»÷ßøüçÏÌHDÉåÂu #üÝuãóL 2®¦oK^C¥yTG¨Lå…æy¡X×ÛÞçîdÆ8ϱ,‹;v4<(œl柄¢×b"¡e:Èì@-EQEQ:‹ÞÞ^,XÀ‚ X¹r%¾ïWÔ‰H~¾`Á‚(5²ã8¤R©q³~S©T”õ X,’Ëåèî·—®®.Ç™rM½ê6ȈÓuuuU§ºÞ§¢ˆ144 ¥R‰þþþŠ1–ëºuS‰K]ËêqDãOT»VjßÖJÿÕŒÉlŠÒÉÀJ;ôë$ý¥+÷®dïÞ½,\¸0t¥€Ðy™JÕN½Q$Y˜a'N³'™|¥LIPX¶l^x!›7ofóæÍQÍ”‘‘‘ޝ%Q*•xõ«ßÀ)§|–ÓN[ˆK•’ˆ£O(ÿ>Ñ\oy}®$)j!ïKqÌ ÉôW…BcÎàªÉ;‘“ß÷Ã}ù~,„©Tœ‚Ë4Ãÿ°$€ÛüxÛb1üÌ÷a§ñ2ÍðóŒÛ 8`Cw/¤=(¤ÀñàgÌðX¥œdÃmxpç @‚/° 0ó°ÏlxëÈÒ?x‘ç ߆÷äáIo~‰Ñ“–ñøQGñº,ø– Ëçsf7|®—dÃv~Ù ÏÙ¶cǺi†í?Ý‚ÓOÿ9ûá……ÇaXÐßGÊÊw:‹J¾^ÞÞp¿Ék¨Eš‡oP‘Gy"’)ã¤ÏÐPøý9N,Œù~ø]I­¥ WŸˆR©ÄÐÐPÍÏ<ÏkjH¬¦ûREQEé<ÆÆÆÆýˆúíõ>‡°à|­bÀ¦i266†mÛ¤ÓiöìÙC>ŸR&UO’”,õ¨Ùޱ±±h|>_qù]S¼Úø¾_‘¾.“ÉP,£û"ŸÏSDô¨wïȘ¦zlAÃ÷›l›¬ÛÛÛK__ŸÖýQæ-.ðJŸqõ­_xâz÷ö²gÅžÐAkkgn§Rqñê*$¥—eY‘°®“8•fÓPQúFéè:*â´=á„+9ûìÐþz …”éš”¼Z]Âh–jr¹Êp5lj£'’ŠFÞ‹™Lè@‘£P¢î°cG¸¿B¡2Ä¿§R¡ˆp¥ù"|Û‹k‡Ø6Q]£Cfø÷ /‡úàßà&ìñ¡Ç‡«`(|žõnŽþÙÏ —ðw%øn¾”†Ãøß7ÝÄÎßåøãŽç˜eky뇇‡Ý0½ZÊ€÷áÙŸ?ÅË—ó艟å¤ãaGþ8~(<κx2€ë-À†é‚sò°;Ç&”L0wÀn໾ËIO>Éò5 ɾÅt(„Y<˜Ó€—Òð .ó¤Š`ßÜ¿ôཙðчU&ä{á‹0jBpÒIôÌÚŸ'Nc†a¨}(-cÊ)¿æ"2+á-oÙH>_NoÅÌÄÁ"ÜW-³NF”Øvœ’ȶãzÕ‡ü-á%m‘¤¥‚Ð<0P)°È6¦§¨²íPùOî.§{Ñ…ÓL¸×€TŽµÃ´g.pz>2À?¤áóF(hH0€Áx1E–W_KãcÃ<’†¾þu …ŽãP,£0ë¤ÃV®¡I8S}Ù²dÅç‡9£ÉðŸà»4 £"©Eø°®ç.¶Ëÿ³ì ÷ý­¬³á–•àÑ>x]_Ë‚ŸƒG.]Õ„;éÐÂ'¾—DìLR(Ä5y¤.Žm×謉L@H¥Â(®ä{t‚úe‡<“uÊkåõ.2XЂ Š¢(Š¢(ƒïû‘Ó¹ú÷êBòŠÒɸUØ\.‡—¿³ÙlC)¹Z=fI§Ó¤Ê3mǩ٦b±ˆeYd2™¨.£[eŽã—¿!ôÉþùìmϲäÀuÃkÞP.Ì\G´„ÐFƒ —ËáyÝÝÝ㞊Ò, AÅó<òù<ÿö_ë"'jÒ¡;SŠT{D˜f‰’NWŠ(†×,ˆ£S'C #N]$5B …rM“L¸_)ÔžŒH‘bí’VÌóà“¹°†I`Úr¤Lš02ä¤|( È{˜¸~L#œvãY¼ó§‘‚\œà¡g&¾ qÔ.{衦^’3W°£i¦ðýƒè3à»ýqÄ‘e…NûtZ;0SÅ£,n•éqhs|ïZåš7Íê·Ê÷•ÏÇg;ëâÔKõ×îÔ¸ ?¾ )9§“ÇÐÖŠ¢(Š¢(C²oõïê¼Uæ 2L¢=‚ Àqòù<–eáº.®ë’N§§´ß©+Í2•”sR«¥Þ6ét:Ja400 žŠ2W±€ÜÀ¹7üû®[îâÅ_ä¶#ocÑÛqø‚QXK\4¹®ëâ8…BÓ4±,«B¤T”fÓPʯÁÁA'\gtt´ÝçR— xhÙ2þʃ(ÛR2åÐL‘‹j’³àÅ/5K t‹€20 0’&LD«\(^j¦XV,¢$£WBGt±n·×„´á…þÊkƒ\Zn—t „i]B¥Y"Ó’]»¸ëÍofhhhÒÙì6q‘r„¯¿øâ¦´¥Ö±­iœ§I9E˜BW¦O2:L¬!¼‡]7Nu7Å~í”°íP˜ñÑ4cÓ÷§.âÈ>‚ iòùð|¤~KÄ©¤1K GRÿŲ ·7LaV­1ˆÐ"éÿ\7\ß0*ëËHœì_þW¶·~Ú.×uÙ¸ñ¿“ËÅÏ,× ÷ñío¿L毧|½'x¥m¶m°ÿj~x_ôÌ“cºnhg¡'í—ïIQEQE™lÛ®(ò®(s…ê‰b…B!ŠF‘ÔZÙ©¤@ ô/tÂd0Ã0"Gq*•"—Ëien³?Ì$cpÄÓG°üåå¬X±NÀñà­¥°ØqLÓ$›Íâû>žçE¦*˜*J£4$¨ŒŒŒ0<<<éz==Yšû§‡Î÷»»9ú½pxr„NÝ©½:'Æ&Œð¨Ö>ET‘Ú&Ž:[ÅiqHÛsÄÑkâ,uÝ8JE²òS ÕCè€ÎåBQåro«JXØý\#N’Å^ÊuÝ£ö×!™:j×Hj ³ê»âp­Êt¨zH{q‰-ÉA뺡ϯ‡Ò*v쨬­"¶æ8qбB!´©j …жS©pÉÔ}IÁ$• í4›…®.9çX`uœÐV³Ù¸n’e…Û˜f,dˆà"}w©™$ÑnAnkáòt:>é?d³"Ȇ¶™DÚÿÙÏ>Ì#låœsÖEí“kaÛpÛmò£òúׯ"“‰ãy±0$?'ÜÆ²âsÁLR!Þ~ûW8þø¡·7”ä™&×F!i‹ëÆ‚•¬ßcEQEQ”y‰çyär9â\.G©TÂ0 ²Ùlä°ª.î8N”-"—Ëá8¾ï“J¥(‹‘cº··7r C˜e@Ò‹†]OQ T<ÏÃqÇaÇŽÑç–eMyöz#µVª™®ÐÑ轜ÍféîîVAE™ÓÇXÏ®§wpÊè)°×‡7رSDf›'ð<×u£wM*•²,ú¥(µ¢´€†•‹.ºˆ 6°~ýúv·wZÜûŽò™Æ V(z„µAšéƒ³kT 5©Tì”ßÅÑêºð‚ÇæÃ:&¿pàºb¸ÄŽÄt:ü))¿$u‘mdzÒÅ¡èŸKÁ™©PÜIC]å(Ee¤F³uÛé†Ö©‚<¿ñˆ…GÏóH¥R‘è8ÛãŸt:´·8åžm‡ËDÈÌå⨉sݰ½+W†ûI¥âF"\x^¸\Dl6® #:£ˆ ɨ5Ó )ˆï‡ön±ÐZ(„"ÜTG±‰`!ŸKŠÀPP1=÷”Øb~ñ‹¯òOÿtgU;’¶»{/_ûÚÙlßÞÇ'? }}q­¨t:ŽÈËfÃ6‹’NÇ× â^ðzÙ¿5Ÿþô+¾{Û®LÇæ8qžœ«DÉqÓé©ÕØQEQEi'%Jøø3ßÑ °Ëÿ&"‚Šô®ëbš&;vìÀó<úúú0MÛ¶I¥R  …étšL&ÃÀÀ@äÐÀ0 2™ …B!rKÔúž={( d2™(us.—£P(”'a5¶ž¢@8ÖL§ÓQÍ‘jçªÔ#™ Ó‰N™jÌTïáùRx{:µ:ëmãû>AÔü~µ†ggáúfÝû`è à¸õ™cxtÑ£á _¶ è'š…Y#ÛFoooôæóùèžè„h2eþÒ R*•fë֭Ѳ-[¶°qãFÖ®]Ûîs˜ûÞ ä¿:äú‹¬7Û¬Ò„Q½åcfåg*QhÞ„Gmøš%`À…Å)ø}Nvás> šp ÿ^ ‡â •™Þ…Bì4,áƒ0â&káïC€Ñ Ûª×n£…Ý”CŸÊ6Žcáyáý<Ûý@Ó¬,^/ù¿4Š"1ÍpžW`ÕªÛx×»®ªÛÖ~ð _ûZ†mÛÂAsõØ Z lìày¶m×Ò’‘(ÉëX}Œdж¾¾8š%>ç‹QEQEé4,,Ì–Æc:Ç—H¿étÇq"'p?½½½Qm ˲*ꮆQsÖ°ˆ+â'´mÛQ Œ©¬§(Ig»ˆ~I:Ù©>ÕI¦†aàºî¤bL53‰H4Y:Æ4MJ¥RtÍ$"LÒ)U_7I'í8N´¤TK¦H ‚Ïó"(—Ëáº.©T*`%‚-#ÚÑ:ADÇáÖ²,JåÙÈáØ4 ¶2Δý'k·  ÃÀ²,²Ù,¦iFÛÈyê$ßÙņ>[»víŒÅxúé§9ƒÙ˱Ÿ'TJåß!;rå¿mâÙùo-†â‡Ynß_å€Xž…‡{Ãu²Ùrº/3Üεâ¨鶦 œZq¢Ld›ÉÏgbŸÉ®ìSO½Ì~Ðùâ„8ê¥ÞÞ‰0 8÷ÜJývHJ¥RÔ˲¦Ü¹ŸlÍ¢Ö$¢l6múMÓŽÑnfÃ>E™³Õ·Uej軳ùøUéV’Î-ùÜqœh&¸Däóyòù<®ëR*•¢t`Ê¡K+í3™ÖéPpˆKd†ÔŒ±,‹®®.,ËŠ"N¤v‘D‡H¤†¤ÒK§Ó¤R© 1ªº.Kww7ŽãDõ‹úúú(‹×8›ÍF‚D±X¤»»›B¡@*•ª™þLÖ—¶š¦Y1áOž/rnÝÝÝìØ±£B1H„$!)UG)Éuñ}?`LÓ¤X,FÑ4ŽãDÂP>ŸŸpüúàƒòÐCµûVhméÛz€é#lŽ:öküÖù?n6k&“‰2yßè»Di³.¨lÙ²…mÛ¶±aÃFFFX¶l_þò—Y¶lÛ¶mcË–-lذûî»Í›7³qãÆiË^=<ÌF¤dB9Eù»ï?™Nn:õwe¦Ìª 222µ×^Ëõ×_¸·m›mÛ¶qùå—³eË®¹æzzzæ’K.™QZ1xûÈÁƒŸœÍÓ‡M¥À"$'TKzÀ„¯ö‡J©¼}:±~­ù –LQ”šLf›@Sì3 ÿîï°dÉ.4=éìcÛ6}}}ô÷÷ãº.;v´2¢2SfË>›‚†J*‡³Ý·U¥1æÔ»sŽaš&}}}‘3Rf¶Q{X¤.‚ÌRïîùzE•yÏlاÔÚ8Tº$S …„i˜km#b•auÇ‘ÉkoƤo©»’ܦž°SïÙ1ÔnRKe2lÛf``€ÞÞ^LÓÄqœ¨> „BòË/¿ÌßøÆ)¿™í¾m@9Ïož}öY<íWœó úzüë‰È¢\. ó’–MÅ¥4,¨ŒŒŒ°eË–Še7ß|3ƒƒƒË6oÞ<á>zzz"£¸ð ٷoƒƒƒ,_¾< %[¿~=ëׯgpppZj§G½ñØð0+VŒµãÚFTŠ'pgù™ÞM8«¨­g Ìw&²M iö)v pÏ=û8ÿü'f-Ÿ“Ïç) Q[¥³™-ûl ]ÀáŒÐò5ʼg6û¶Š¢4Μzwv ¶m366Vó÷;vT—N:#³ÙlE´JÒñ¹gÏ\׈ŠC ²ÿêãÉßÒ_mt=¥³™ û¼ãÄÉuw·ûTg ˲&­‡YM²ÅT¶™ªhÑÈúÕ©À¦“z:Žu‰thôܳÙl$W‹Iƒƒƒãü£s‘vômo(Á£?ކïð=6yy8Ž,* ÑCX‡U"%§*"*J39¬‘•$/Þððpô¿§§‡‘‘‘ŠeÃÃÃî§§§‡­[·FŽŽróÍ7Gû®V4—/_åì«ÇÎ;Ù´iÓ¸å¡ÊùÄ/°fÍQí¾ÎÓ&KXh^éL6mÚÄ7ÞØîf̘‰l˜¶}Þxãã„X:½ç=;9þøGÛ}ê‡$R Ŷíy;;pxx˜M›6±{÷îv7eÆ´Â>wïÞͦM›Ø¶mÛÌX „Ó‹d,ä–ÿû„9+%¤ xòÉ'ÛÝ”3›}[E™ ´o;õ¾í¡ˆ¤Ã™ª#KDC)S³¾íÎ;ÛÝ”3}Û.»ŒâŠí>ÕYe:BÇTEÈé—Óa¦ºM>Ÿ¢å%›ÍN)’)•JE)“hß¶±¾mµÏ8ëW€âé@ î}æÞr° ¬00P¡²`Á‚¨ö¾K”FزeKKú¶ E¨lܸ±é3un¾ùf¶lÙBOO7n¬Ù1m$d줓Nª0vÁ#Œ ùô/—òØcM¿n³†Nîíl¶nÝ:ïUÕ¶ D³…’4bŸ_|qEÔšGèoõ<ø»¿[Â'>Qž ª šþkÖ6ó•õë׳uëÖyç”l–}®Zµªæ»sZø„Æm†?ƒ{ÀûXGƒá .:3@I°qãFÖ®];/fñ%iußVQfíÛNLußVQf íÛ6Þ·u€c|gíZ âù>J%Ét}SÙfªBG:&‚)m3[éÚ¦ÝJ¥Æ *Ú·˜z}ÛáPñU&yÀW¾ò•ð$¡Ó¨Æ÷300€iš”J¥v_eŽÐª~Û¬¥åÊ+¯ddd„«¯¾: [¾|ù¸uGFF*Â̦B¸¥Ï>û·³}ŠŠ2'©g›Ð<û”*…7v+oyíï‡8„³Ù'ëÏùÄ5\B'nŠ¸Ú½ 2ÊË)×_ÏͶM7*¨ÔÃ0ŒY.&+t?טjjµ¹ÈlömàÏS0ú‘Qî8ñö9Ž-+ŒP©¢P(àûþ”Å@Ei6 ¥ü¶lÙŸÿùŸG¿ŸvÚiÿ ý»ì²ËX»v-®ëV¼4ׯ_?.Llß¾}Ó*l$é¾¾þõÝ\|ñ‘m¸¬Š2÷¨g›Ð\û HwÃí^ȺË×… mBA$ú§)@è„u :S^.©„l­ˆ)”/ÇŽå}åÏ å幪õ VZq¥Ì–}6D•=¸@aàA_¹ïBúSà¯,ð>XÞÆ ¾)Êf6ú¶Š¢LŽzwÎAr¹\ÝÀ…B!ú,—Ëáû•ƒ ÈårxžWwåЦUö÷v¿·lápQ»ŸŠ25f«oëô`Ímðâž;¹þú ùÀ¾Ûá¹L¡R%¨ø¾O*•"•JÍ+‘N™›4¡òçþçÜtÓM*`OOW_}5Û¶mãæ›oæšk®™pÛ¶mctt” /¼°"níÚµôôôDEŽzzzfdd„‹.ºhÊ'%…¯¿ñ«ð­o]Õîk¬(ÏD¶Ù,û”èσïýãž?õgð{@oy‹° õ¡xb Vù硈’$9)AfÀ‹0#ŠM(Șåôùòº²„Kš8}Q–¸„]ÞFQÚÀlØgÈ] „”–@pt?7‚ÿv°Þ¹kÀÛ ½o‚=ÇÚ¡AlcšÓR™ÌVßVQ”©ÑQïÎ9J¡PÀ0Œq³€}ß'—ËaÛ6étšB¡€mÛQaç èíí­H T½ŽrhÓJût€³|0úÛ$öYèpNQa¶û¶—à~Þl `kÞè׌NI¦ŽÓ¥Ý4$¨ ³mÛ6®¿þúq¡\k×®eóæÍ,_¾œ«®ºŠë¯¿¾î~FFF—÷óòË/góæÍlÞ¼™+¯¼’ 6pß}÷±yóf–-[6å“ò ý4û÷ Ï«¨_¤(J &³M`Æö)%|ì[À²ËÂ^­ˆib9k#¥‘Þ¯ ô—$ÂJ‘°÷œ%tä&é'®ÝR.LÞÝiâˆEi³aŸ c‰¥óÀì·CpTØç5~¬GÂϳÙrêÛ7@ð8ibû ¨TÜò2›PXÝÓ¤ö&Ÿ+Éevùx±x›­Z_DÖRb}‡ðy”`eßò»¨ÇÊ!ÁlõmE™õîœÃ˜¦‰ã8iÇ©[w )¦‹Z@M©M+íÓV EÙSd˜éwE©Ïl÷m Ì3àÅ'ÿ€ã~ž=¯zk ¦ b¦iª8¯t *7Ýt===æÅ»üòË)•J ×]OŒ¯7n¤§§‡‘‘‘hvÂtð }>Ï?¦Š)ŠÒ“Ù&4Ç> Àÿ<{Þm/!š’ÔÖ¤9µ,b§§ì¯žsÓ`òº+&ÚóVÚÊlÙç„D€¸_çYH¯‡Ôg¨ic¾Ž +}%èÿ&¹DÈ€8‚ERõ%ÅŠ•…í=b;'±T&Ê–ýåmÒ„‚N‘XÄ)@¬TRåmÓUíJÄÏš ¼¿^`Gy;yn”ÊûOžKtj,Sæ³Õ·UejtÄ»sJ¥p]wœ "Ë“¨˜¢4J+íÓìíÛaÝ: ìŽ Q™¼@Q”úÌfßv žöýðÀëžgÉõ¬8áxþùšëKêÈFÊM(J«™vQú72::Z±líÚµìÛ·oF jVg6Ìת3Œ¥™ÌÄ>ÅOém‡ÓýUœõÇUê‰ÁøÕ5Ôp€IDAT®ë†S, J¥ð¿eA:þ¬GŠæ¥’™êúÎV:œ–:ƒr@ ‚À·¡°²°?WÛÛÅ•¾>èïS¢=D|ÈO!‘Ó#Îái$Ú‘LÍq´ˆDœ$‘ô…"ëy‰Ÿò_ÖAG¶7/yT ?É¿­Äß"údÊÇa&tŽðUT™÷¨£VQ:—vÚg.Fr –©T¸``z{+·I¥ÂwªçÅõz§r|>ÞGrýZÇI¥Ânu=Òé4]]]‘@âû>A`YV… "bJ*¦(McºöéyÞ¸t@6a7.CØÓô_Š2}šõîü… ™ œ þäO8zõêÊ—Vß÷ëFH*ÊlÓ ²|ùòqBIµñŒŽŽ2<<Üîó‰Ò Ýu×KœpÂv7GQ”&` ÿùè=Ɔú+ú~8‚´íx”—N‡ÿK¥²g¶¿¾¨Òßä†k%CåELM Ê—nïEL,¦@hž¶j¢Ùlø¿»‚¯Bz-dB‘æ¯À7Á²‰·ü{–r®@b"K,x@$”87‚q)Ø>q´H°Áÿj(â÷o#ïp0?¾[Þí#À7Â]ºw€÷¤ó+E”JÐÿ:)G¡g>ðû˺H2å ˆ°ÒVÊú1µRÖŠZ‘´ƒ%ÂtˆNy=I™˜-”wÊ×PDƒñiÏ&;f5·‚q~y¿v¼<‰¦’æ,˜ÂºŠ¢(ó”|îÀ@íßëQKid»FÖ1 Û¶£¨”êô_B&“!›ÍFÅê5·½Ò<âîH­”@EbA¥·ü·ÎkQ”ö±Ä‡§ÂÒ;–2öêWǃÈ*¤~Š *J§Ð rá…²eËn¾ùf.¼ðšë”J%–-[FOOO[OHü«Wïçüóÿ8³­íQ%Äžó¡àÂ9«~e}°r™j¡7Ÿ§ÍU“NÇÓñfëeªïlåÄuC3ó<°Êpç È^ÆŠÚÛä¨,Tí, M<³ º‚â— t˜o€`!ð(Ýé‡À|8Að‡ål\Ÿƒàà½:ÆB~ 6îW¡0Á§Áþw0¿²Ã[Á` \é×@áFàiè¿5L]œ Ýÿ Œ§¡9xkÀºø5~ Þ7¡˜ûXèû‹ ½¼ûÀ=|Œå`ý9˜î€Ôå`žλÂs7ÿ‚Ã!{&”^ þ~ÈßÎñáçé`¾›P· Ç‚q* Þµ`/Àÿ+倚ßop:ø ¯»ùuÈìóp(þ8?ï0ðûa`5ÿþg 7 Á À¢0±õáÈæ40nãï'†Ÿ›¡°¬#!2ôý 8 Ì“Áßýg†×=õH_½ç†õvxìÃÂGøwwÿ6oíÙÛîÛ\QE™Û¶£´_ŽãP,+ d³Y²Ù,¦i’Éd´½ÒÊY}¿æçÉR9Âù(%4`XQÚ,À\ÆOá•ÿ†µÖ×k®›Ëå‚ fô™¢´‹†•µk×rùå—så•Wrùå—³qãÆ(BE ÖoÛ¶k®¹¦Ýçe)`Æ“ÚÝEQÊÀýØû¡´÷ß(D Ö÷¡X ½­étm1E°mfµ@’ö°•CŒ MÒ0BaÅ*G=äó`^š„Cè¼wˆ3u(¿ƒ‰µÕô+}Ÿ‚ôÛ`è$ƒõBj•u Üð¤ígÀü{ðó`eÀèÿB°ÎÃ…Tø(˜ öoÿ>ȼ/<öPúC(„ü_€y˜v"â H—S¨ APNçB(†™&Ø·Bv9¿W¾~(ý1¤Þ Cɼr 3Ï·M§ãsªŽ@I–ªÙq¬“œÿ ¼ ;n Žf±`ñ5>/¼ð àâvß(ʤR)r¹Ùl¶fº/ˆg ‹è’Édh$FQZ@#b^Š0JÅ,ÿL—לJЭ¢(SGj¤ÞÖ3.ÁÀOꮟN§qG…z¥£h¸†ÊæÍ›Y¾|9¥R‰k¯½¶â³µkײuëÖ¶G§@\svïÞ•œsÎ’v7§>Éíâ€ÐYðÊ<ÆŠo#ÎxšylüT®–A—iNœÌ¹H"E9Dèë òÅóÀñ€<”®‡Û‚¯èÊ¥Šž|’àè£é]²„ìd^z ûŽ;àÄ N?=ª_a„ÿ%Õz­”ëÙëˆ »§]B§Ø8\ Á ðHVyé×T‘”Y©òö6•5–Ê¡­Ö;ÊË“é«ÊvoÝY ’H*´d¿¾¼¾ p~ùg>\`Ê>S`Ëñ¯»;<—ôãåu0ÿú?ZCj\»F‘Äg¿«êº–S°£œÌJlÛpý(«ò§ƒà\(žÄ8aúµ¯ÝÇà`ƒûVEQÚ†¤ýÊd25Ó}US,éîî¦P(­ù²Q”Ö0•,ÍÒm)R9¨‹¸›()ĤŸ”ÆS·¢ÌXf•'²}Ì爱WÖ]WDz¿Nô™¢´ƒ)¥¿üò˹üòËLŒ€—/_ÎúõëÛ}’ò뤓â”S:´(}@XŒ6é¸q¨á­Q”ùƒ>›»¿ÆeÏ?Ë…ÞAcsúúBï`«R€éDåö¡t XW€ùh(ª”~þ5Ö4R€¿?Þ’%ì¹ýöp£Å‹É{þÝw“Y·‡P‘R(SÆ"Vcdt+õ@,ðÀ=¼È~µê Fù¿ˆ)õ²ÍT«“6ú¸™l=›°ó²Vž{|ðÞBXƒÇ-Õ¯ (Š¢t>"¨äx˜†A±X¤··Û¶£è•ÞÞÞqûÔ(¥™ÀÊ»ïnxûq7M¤¿<á¤!Ÿ0˜G(¶H÷SËÀ)JsðKRÀ\Øï³ëå7²´ÎºòîÑ¥“8l:õôôDÿ;ILØñàƒ/4¿XQPãïµßª%B'N-Ĺ“/ÿ,QY`·ñˆ{ò{_ùï qÁÜ\»š@f%÷¢=Ÿ6#··ÿkØwÿ¿È‹Ðóâ_3!•ŠóµûV!`Wg®„¾«À|Ò߃7}îûÝXß°n¹…ìýÖƒV¦à³,Ì .€%Kpwï&{Ë-”ˆ_!3¶Õ~ÊZÀ<¼çÁÞÆÙuÖOS‘Òi䉢]¬ãwfs§`Yaz2û(Š¢Ì=ÆÆÆ¢ßÓé4cccÑø:)†ŒaW¥âµm»bý±±±qÿULQZ…Ñ`'ªž·¨H\kÅ"ì¦åÑ!¡¢4›Á 0Ài°íÕËk®ãº.Žã´»©Š2Ži *ŠK(¨xüæ7K~‘NHŽØŸV–ÿ‹“^’ÿõ ±è”–ó’G •>§Mèì ³þN¹}âdùFùÜ$å‰E,°ô–דjoí Tn›ÕÆ6(@x[X€¿Vïfñûß~`Yqª¯™J…ÝÞÞ0â%‰TÖvÝð³ê—±ã@©T.*P ÿ'ñ<Øã¢(‡ Ÿ àÛüñyáßÿ¸¼þ3} éŸþûÿý?Î9güN, Íü±1²<åí z×{{ãÿºíºáÿ)`þ+x¿ãÔåÎb¹¥™’—RtËæ‡ bšáy4!FQEQeFxÀØž=ín†¢( ò¸Üãq÷ ¸mÕm5×1Msœh¯(À”R~u:’=Ë÷aéÒß4¾¡&¡`{€¥JY–PD(×?1 §+xåÏ]BQ¥He~‰VqˆüÉçAžÐË$`ZáDé&.*[Jü.iPJÔO‰"‘]n§ÄÆJâdäw‘8¿‹A,0Ê?%‡=ÄbŒ$-5«®$Aµ¨LˆZ£8nM¼ÄºÝåï ÃÛOa”ŒõõÑĨ-ÂÜ·Ÿç{޳Î?¿ù;ÏçCñ£Ú Y*ÅÓ£Ms|1{©¾-¿'£e‚ aŽúJãÓŠAè‚ÐcX*O_–Ë%*{[áçÉéÚ¹\Øîä~“é|?ܯœ›Ô˜IîcåÊØs a[’ç!¢QòT{8Eˆrœ¸Ék%û¨×Îä¹H;m{ü>$*É÷Ç·3Ù¡z¾^KùÎ c|1ß®ÏÑÉôrʤ<üm8é5œ æ ðË^ø“_Àu@Ñuãïc’¼è&úÎw0ÞøÆè5‘º²Y†6nÄxù帊<¹ïù®ëxåóùùã°w¾ÑºÌ…íÀ¶k?–EQEQZAບHQ:™ ÿþïÿn{àçu'Á¹®ÛüìCŠÒæ• âå~°—W¾òׯ,Ñ ¡]Ä)Xë'Ò´…“PL§?‰Ï! $VâótÕÏZˆ¨!ÂG‘ú¢A•Es¥‹ˆ/3ñÊw»#±}r¢ÊPU{å~("‰Âb~$±ïD³´Œl^þ[|»UÞµZ/Úþþ‰·™(ݘa„4}ÀšrKr¾ Ž3^¬Ð±¡×W„€d'?Ÿ—‰Ó¸z`á~³Ùp ﬞ‰UN)•Š=ÎŽþ¯ö@'ä¾?þ–¶u¢TM¶^Ï ÿWŸ‹eÅûµ¬ðzÖÚGõõK"×JÖój”ŸÌd¢_/Þ½¥q<nü8œy-x)È> ö~0ÿþÒóÂk»£±‚_iÀ¾é¦ +>ªûÖ­c\lZ* jRWÉ4cÁR"Ël{ܽ™N®S(M*òt:ÞSå‹”™éž:ƒä£GQEQe6h¥ ’L6¢(ÊôÉ¥?º\¿†|~¼_Æq\×Õ¥#™W‚J@èÿþÎ#ÏÒÓ³¨öJ.qŠMèÙ 2Wò'Äø€³TF<4Š9"ît‹qm;±L“X ‘v‹°àGc$1D©ÄïI/WR@ñyè§â»’u«÷)H¿GŽ‘œü^¯þar¹=k_kÝþò5+•Û*þcžü)ž·‚œèÃé¯\Œ»`ÑŒ÷7똀ÿ'±¬É§“'›zëšfý""¨L´}­mêQÏÃYU£f'c²ŽNõyÖ*l:Ù>ª#Vj­ŸH#çlÚÄÅ]5…P¿8®vŸX~½ æ« ,v‹ ï+ðÍoÖ\îj×ã¥ÙleÑ HR©8zÊ0ÊJ!×$:­–¸6ñ‚9¯ )Š¢(Š¢Ì:yÂ>f«y·‡ ’`!9WN†™É,½²Žaĉ$È<9ü“¿e‚l#ûße9†tõe^ž %ÀݶÃå©Tå¼GIœ se¹$™H&H§ÃõäxÉáE:]™X¢TŠ3x¬^]»ˆR`l?»ßpÿVÍ(Ã0Èf³u¦t$óJP‘LMkÖÜÏŠurgJl™DH GuL„¤ú𠉶˜.&¡‡Iœ)áìx©µ"õXŠUmAFh–3¦ú™ÖŒ™¦­ŠÖkæ3Ö¤R¬a%Cø=HœÎ[v/ö¼Ø¢“š?<ñoðÈË`;s¿ˆmI‡Ê%ïD´Ì¦4‰…N‰ø’h,øáó"O\ã'Med–Ô'J¦¡«'H*Ê ÉQð¼Îx=x’ýëá-o‰GBMš$A+© L§kGÕ/m;N#çy•Baoo8*¿¯ê´b‚ŒÜÚ˜ŸJ™½½¨¬(Š¢(Š¢L‚ä¯B!lÓÀ@øSö-ûóýðúõ÷Ç©m廨»÷ ?ÜŽ;s^<ê·X`}Í]×%«3Í”eÞ *ßÿþ:®½¶ì,ÉAEòv©ý1ç{;|,)âš$&_Ú.Ä—Ìt38pàË8b~™RKøåxÝšG1×ÌÁÙ6q-$ˆ£Ö$rMjõÔÒqkøs+D‘dT•Ôo’uâKáóÀ'Nû'ǵ){à =ÕRŸˆÄ>JÄQoò™›8®;)âH*=‰æ3«Úm&¶‘IGÉÁ(×G΋ò¾²‰}JD´C¶·ª¶W!©¥€K3/÷܃±qc8’“ú@M ,ßSÛAy„ñ¸äày` 1uw‡'…‰l±íʈ©ÞÞp¿’ÖO„Ï Ï?Ÿ¯[‚ \.£Àj’Óð’Û%ë  á(€cÛ‰v&k#U‹J’Pó +Š¢(Š¢L©Þ‚D'@\rR–‹•BÄÝ.ÜꟖ»œ"4HW,ÙÝKv“e²ÙÊHò侨 2*‹jknXÃÒ/­¹ŽišZŒQéPæ•X Ò8p;–õørÿR3§Òr™¸–I'’LÁ5×Ú>ßIÁ];žv·¤£ñ€þ}N>øCŸ«/Äd¢$Ó9“}|ƒÊȯZéíª;µµÖI‹ÄÑ4ø¾ÏqÇ_ààdÍÖ„ŸËqE(qû’Èš±à!"G.±ÿ4•‚IØO2“¤Ñ“cv§0””…-è%~JûDTÊ–—ëè§Zô‰Eèr[>8øÁi|A‡&&àäáMß.g|ßûâ‘IÅ”$)Â[An™©î@¦”•JãE©OTýÌ‘©y…ÂøÑeoo(ÂÔªt_(„Çå2ݰ¯/ž‚(#,Ï —‹qª4iŸ45ûæKa§„8+ðE¼IŽ4K¥ð„ßSµ¨##B9¦æVE™t@À¤¢Ì;¤+•,]iYqiÉ|¾f©¾Š®âF ^‘­N”Ñ*³77ŠaL½ëÝH&êfl3:éYV-ÄTw‘k·+Í'Ö~ÝøO8å”Sj®çûþÔv¬(³È¼TLŽ?þ_0ŒÂ\øàj>À>œ–UûÙé̱æ*Šð…o˜üYÏmÆÒ™ï ‚ÏóZZ ¬ÕÐ<Ïò,<ÏÃ÷ýh†œ[X–…ëºQÞPi“¬“Íf+еÉOÃ0(•JäóyJ¥R¸Íh€÷…ò5³‰ÂáÇÁÂÂÅÅ0 ×`o÷^.yé¾Ä—°½p}Ó4ñ}#kðÌÈ3<÷ù縗{ñJá>Ç!å¦ðññ}Û¶ñ}+°p=—?ú_Äg>ó®øÔ|í¨¯qiêR<'óËÏð»ün˾Ãù„ ¼|X2»¬Áâó3=¦d¶ÊfÍóƒzÝI¼~¾N¡­Z‘#–®_ë3,’ŸÉú}}áߩĴDÉÝ I—“ÛHþ}„t:ÎPÂîþÉØß½’B¡¬e%Ÿ?ÕO*îËuC(Ÿ¯<ŽïÇùªkIΆ®®pyR¨‘©–Òöê0ûBYѬ^žL°­´‡Xˆ–ô°‹Ù’–â(K´e™¤¥LŠ×Vâ3EQfL„lÉõ¿cGøØ•t;>Ö“¯¨LÏ#9þ!NS“|ôêãX9”ñªjêÉ|éÞ¤R•]¢d²×Ðü¨Ø§ÅâÜs Î|àm<ŽÍÎcwòô©O[Çu¥ŠEÊ\dÞ*2üÔ§fÍšw„ƒÊ=.¼ß„pYo¹g ˜©ðÍ*1‘’LªãhEXEi2þ³G³û°£§‚Äó< ÃÀ4M2™Lú†aàû>é)Nå) ضeYÑ>E4ã ,ËÂ4M,˪h¡PÀ4ÍHBÚ$¿G‚Fà8¡Hàºn´/N|ß>—s’ý–J%R©ét:Z&Ç®^a¨»¬SGØó<\×­h—œŸˆ2æ»M~èÿ#j|ßÇ0 ,ËâÁ?zl:‹mÛ±èRn¿eYÑu5 ƒÏ~é³ÑºADâ\YDû“öWÿäÃmNyë)ü…óᲟ„Û•J%ò—åÇG÷(5ñ€ý>üàUÀ+ÚÓ†Fe$õòt[ÖÔ·9þøÆÏAFÕbItAóq$Lõs·TŠ=vIOBR„©%RI^Ã=‚I!F¶“ã%ŸÇ"ˆ˜¤4ŸPIª’ÅÄr©÷–&4ÑHBc“èB¹í]ˆ¿îÄz’.2Cø<  RÒMJZFEQê¡~-5R©xVt©¾zä‘)u¤†äò—ù€ÉYöÉZòèÍ–ƒ …8pR³B*‡ɱšd… ‚úso¦‚M(¯Ì´[Ú>Ž Àÿ/øæ«¾ÉÇßõñŠÏ\×¥P(hý¥£i› 2::ʾ}ûX»vmÅò‘‘FFFX»ví¸Ï&BÒë? sÌ1áàp… o*‚eVΕ™£]]q‚DRdY2ç¹ãÄ‚K­4 Š2¨g›0}û  ûpŸ?ê²Æ[¦ÔqÎg2LÓÄqlÛŽÿ@$,$£:‚ ˆ Ã0¢K©T ×uñ}Ÿ¾ò¬ó|>ïûQ´D:®XODø¹\.’#rl:|ß'ŸÏGË‹Id ’†¤Rk;³Êù;ÙßBµ0$†¬_«c­e²Ù^„ÙÏDâ™aãò¡V/k$_ªˆ;ÕÇ’6­[·nÒ}Ì%ZaŸúH_*û¤Gú¼ÞÊ$ȳˆè_’µMññ&ËíP^.>Ýò[šá`WJIÉ#)”Ì^‡|æyä-‹Bù˜vùgšÐÇ,™ùd[Ù> .'„ÓuY¶lWœ{.ny_¹\˲8p ,}Ík8ÿ˜cøÜm·±é¬³[±‚}ûö±îå—yë‹ÿÀ“ÁFؾ89z&Õ²¥¤È} ñSÄÙ ðËϾB¡@>Ÿgô=ïáìtß0Èõõ‘Íf£g¦‘χÑfåcdÏÚTð/==¬Ù°ýó?sR©=ëž=ýtî8ñD.º÷^ž{ðAn-?ûð<ö÷» ½êUÜP¨]×åüäùW´I½kÍîÛÖ¤D|ÃI*[Ê˯6ÖJ]a×ÖªõJªœ&J§’ÔÁr©¬³%†kQ™Ò2‘ŠRQf“V½;«‘È)Rœ,rœÏWêÌ"ªHÖÈdÍ‚jM*õëjB§q!áé½PˆKŽ¥Óq:1^Q:…VÙ§"Ÿdè¥(Ê´²ok`¾ ¿ÀÇùxÅg2©RS~)LÛ•R¹â×æÍ›£eÛ¶mcË–-lذûî»Í›7³qãÆ)í÷Î;_äcïx¤<Í5QÀµVe­d:™ÂS«¸¬ä?‡Ù‘°« Ø*Ê,RË6aföiz`¾¿Žcp"$ D¢OR©©TŠ®®.Òét$¢ˆÀ’VR©T­á‹Ù4M åg…àRËŸLùÕÕÕý^,ÇI«%:$·×‚jÊLi…} ßötÄÈ3éGò}ŸR©ÄŽÄÔBØŸ›ÌJ$ŠLÈ¿hd„×®Å'ôK6£p×C1zøáüÙè(Olߎ_ÎñúGáGÉÏo»m—\ÂÚ^`dáBnX»–[.ßgñð0ßZ±‚_ìÚÅaûö±nÝ:/^ÌÞ•+Yxâ‰<ûì³\yë­œ~úé<ðüó,ÿÔ§Øöļæ‘GØtÜq,¾úä“ìÞ¿ŸUÏ>Ë®N`Å_ÿgþý <~âó³{7K?œ§Ï8ƒÃn¿Ï<ß÷Y{ÖY¼ôÒK,zÅ+xú•¯„Ÿÿœ¼ïS\±‚ÃÏ=—ÛS)Îܽ›‡Þÿ~>vß}˜†ÇÏŠ±1þÓ?qÁž=¼ñˆ#x“ç±ó­oe痾ĥ?ú¯yÍkxæŒ38æ…xäõ¯çöce{Oº`·y$§=ó A9’Í0 îzç;Y²v-vYÔt|Ÿtùy·`åJî¸÷^~ûÍoæÖU«(<ø ÿí+_!UŽBËçóüÙŸý«W¯n÷­ÖTZÕ·jPI.ŸP}4?»©-žLD0ÅõMâÚZÕØÄbŠO\OË)·±À©¢©òçq:1Q,³Ä‚LŽ8ŠÆ/æ$Ž™LQVë:¥ˆ•Q9_QCåÁ!7q´U^VJ+S*ï#M¬Ü&kyåˆ6fbi¯¨¶±e'¶Ë'®¥Ÿ8†a¢Km±äÐ¥D¥2,m’H#û¥X®s:ÜþÜ#Ïe>•lå»SqâD"bØvý ”S.6Ó ÿ[Vè@Îå*‡¹¾FµHê£B!ΘiÛ-+“¦( ÑLûŒ&¿ýè§d.;ƒÛµûôeNÓ²¾-á{³gßÿÃþýñ‘ö¹\Žl6;íì&Š2̺ ²mÛ6¹ù曹üòË+>Û²e ×\s === sÉ%—ÐÓÓÓâ)“ÞÆöÆ×] ¯8azi»jõvëå‘wœ0å…ä1o–±K¡YééF¥ $½bÃíºã{ÂRmMzØ»/aF…óWRíø¾ëºaÇ!ŸÏãy…Bt:M__ýýýär9úûû£l*•¢P(Dû4M³"uÏLHζ•´HΜ•ôB¦iFí–º’ÎIBå¡\*•Èf³ ŠÅ"¹\Žb±X1 ¸:_c+ëht Ù&Lß>`©Yó\z§0Ã@¾g‰J‘”Vù²SuGÂ.e¦¶ÔI¦Ðr]—þ²ýT§ “ý7ÊŽY¨)¡(µh•} ðøÏÁ\Ûv¼;3@žé‚¼Ÿ\×"’ð<\Ç¡˜Ïã–Ûïg2xåˆ6R)JŽE´†S~_È3bK&C*•âì ›ÍÒÛÕE>ŸÇ0 ž¿ñFþ‡eÁ=÷`Y÷ŽŒpÅí·óÑE‹8vt4xÇÁèêŠD†è¹uúéãOlÙ²è|ljžgŽãétšu¿¼‡ƒ]¿Ão¬Wò̪WÆÑ8oxC¸³Ï¦TŽ I‹XÀÇO9…OlØÀk¿Y²$ô÷®Z^Ë "¿±'ûZ¹’¾“OfûË/óÌñÇó¹E‹àï¬ýe¬YÀ«ÞùNJÀUÄ>\ß4£ +&Cìû6Ï;ƒ_ý*?½òJn|äîZ´‹Øï{饗288ØÖ{­Y´ªoë8`_ƒ±ë ;û«Ó–øÀ›<è.{s‰¦¶˜zJÄ,qŽÝZûƒ8Wå¶ú„bJ­ÇŠt]%Ô«T>†8ý‡ˆ… YÇOO"b¤vŒ¤,“2«¼/§¼Ü£2¢Æ*ÿnQ)â8„ÃPâ|LâзTb_rý¥+²Žü—h ‰î1ˆ#Œä\Œò5‘m2åïZÂìL +q~Ò55ÊËåûI%Úl—¯¿„è‰Cü2Äávr úŸ+þv/>öâoΣÕïNÁ÷C1¥¿?üݲ*‡_u5›)"éªÍß4+Ó%k³@8”<†:J‡Ñ û”>dæÏŽ%½æLó’vŸ¦¢ÌIZÕ· põAîÞÿO˜æŽû<ŸÏOÉO£(í`Ö• 6°víZFFF*–²|ùrzzÂéPëׯgýúõ 6¤vÊ·[OaÿþÕ,~Ý,„†YV(¶ÈT „ð!Î’¬eñÎO|‚-ù­^ÍM?ùI$V\ôº×qÓO~Rá<Êçóõ#e™N$…hu‚ À4 ^øÐ‡Ø¿z5û‡‡yá˜cxò/ÿ’‡ž|2*âýèw¾ÃGþìÏø|„G?ÿyν⠮K±XĶmîûÏÿ$•JÑÛÛK*•"›Íbš&{öì!¾ù7ƒqq£*™Ê(— HÿɦM¼á`쓟ä†5k¢cûÒKùË“Nbø±Ç0,‹|篾:Jµäû>W~8WmÝÊÿ|ó›yá‘G¸õ™g¢tMžçE‘ •J¥"1Dîét:ª#qô@².ƒ´ÛuÝ(M“ëºd³Ùhÿ…B ( ô÷÷G:=ôPtßÎeêÙ&ÌÌ>=`áMpËó/Mé¥X*•"!϶í ë£T÷Éåµf5h¤ˆ2×h•} pʺçáx£í’ÝÝÝìØ±#J“%‚©¼[lj"׺»»À6 ‰è y'äóù¨Æ< d"ÀÀÀ@49*ÓjÝ4MžxðAÒü`ÅòꨴFžq†aà8Nt\Yлd _9âÞ:x|ä2j}ÕÏÂÏ/^Ìç^÷ºqë&[“|…óÏ|Γ!¾Üñ„ý±}ÄéÕú«ö÷jàƒù<ÿ}Ѣȷî–ÿ?uÚiœ;<Üð}ÑÉ´ªo[úÔÃËÃ^÷ ¸)×õÃk|c&ðe ØçýqœÚÑÙI$7‘e5n÷SÛŠp1q2ˆÅ©ÓRMÒìDàè*o/ŸÉvýÄ¢]µnj§Iá*Ãå²åãøT¦J«•—_Ä PÐH×8N­`À¤p"LõçrÍ’Ÿ‰5Pãz‹˜%‚ «vP)‚¥àû;¿OÏ Ú·m„\.¶ ÄQ"í¤Z<©‡¼¾$³u6þ´íŽTUZeŸûö½N<‘¬ÿ.~oâ÷[ÄjhƒïApo» ¿»›ôQGM¾DlN5k|2Ç­¢Ì2­êÛ ž éSŸdûo–×ô×d2š©(-dÖ•õë×°|ùòŠåÃÃÃãÍåË—×|Á&Ù¹s'›6mbÕÖ­<Àã?Îçl×,mýÉ”'¾eQ(§$rr¹(§ù;︃Û>÷9®;ì0v]=Aùa‘J¥02þü¹çØy챜>0À¯?ò‘Èa4át%TÊQ¦iâ•£NÄñ¼îu¸®KqëV(•øÁ¶m\pùåa½Ë‚R‰·y&ÇÞp¼ç=Ja—#zLÓ #`>ñ l;˜' ׆qÓMØÉ‘ÍFS›ŠÅ"x[O?ÇW¬àý7ÜPòÚ›nÂß»—>Êq?ÿ9ËÿðY\®E=Ls9¾òÆ7™græ‰'Â1Çp~ùø©T r9²Ž®öM\3ÙûwœÐI Ó¯Õ#‡Woox.¦IÚ÷£˜wqVY†žG±<Ý+54Í~ò–[èý_ÿ‹Á£Ž¢û¹ç ÊÉ6©g›0}û¼ñÆy褓xæ?Sì]¶·áÍd±ødÑrEi”ááa¶lÙÂîÝ»ÛÝ”¦Ðlûܽ{7›6mâ /Œ:¿W¼ëHø“©NYŸ™L&Šéëë#•J100@ww7CCC‘.Ïe©_Ôß߉,…BÇqªxVȳ¾Z€HþÝ?™Ã¹Îv3¥^­¤cvíâ쟎rÒs¯léuOú®¥ìg­ H<1_‚’|oÍš(óÄ>æmÛ¶ñ·##ìöÙ–žçlѪ¾­»}+Ùo^?9>Kešª$"Š@Øß©ö†J"yéÿȽ,U¯M³uBêtj‰NÇÔj #B­k&Q>‹Dfù|¦Ò>‰>™Ê6'OíTm’òl¢(ƒlmŒªóϦM›Ø¹s缘,Ôª¾-„éO\7j4£Øu»HÎ Èçãùzž§ÓIÂômwîÜÙî¦4…Vômÿñ¯þ ž=/Ý ü© ßvá²rFøãªžÌ‰,  »;U’cÕîîðÝ(~‚b<°@á•§a âpçúµ'WHÖ“äD#¸¥¼ÍLBÛ’û–TÉ6À­.¬5j+Õ¾n#Ÿ¹åÊ…ÉôœÉs¯ÕÏñ}Ì8J4:ÇòwTÏwQ£ïðýÿûàðsÏþ5é Zշݼy3ëׯçœçÀøÑ µü(Œ÷s~.¿X•ŽcË–-ÜxãMïÛ¶­†J5ûöí·¬‘±“N:‰­[·Ò¬ôà…ŽaéOþ½9í’"Ó®ëF©CJ¥Åb1ŠB ‚ *Š-i†,ËÂL¥X,1ŒÚc©¡!Î(„O2 È墨d+Z¤0¶ëºÑß’fDŠh—J%Òétü*§D‘èþ~ŽèÄ's2%_ü0þ…í8àû_,2P~yEÎ(Ãà컬p¶OöÍçÃÿžW®fUu|Û®|iV¥ð©dâdÈf+_˜Aw‚ z{¡¿¿rÖòWp±çáHÇg3]û¼øâ‹Y–J±gXqøØ7é±Ã`ll¬Ý§®ÌQÖ¯_ÏÖ­[Ù´iS»›Òr¦cŸ«V­bëÖ­Ñß÷]ßW´P¼”w›D Ê;Ôq Ã`hh¨¢¾‘aã"E È¢!!ìlû¾?ç„×zi$Ï9gÿñpÇ¢GÛÝĆ‘lAµHfJ²qãFÖΛ”_õ˜Ißöoÿv+ï{3X'ÿã0lj/žö)ë9X2™¸Ï”ÄóBQr;Ï‹sù“8KÄ2•—V1‡ïtÆêÓÙfªµm&:ŽDó4«m5fLoݺ•-[¶Lcgs‹™ôm7oÞŒã„Ã…ù06)ª¤R•þ^%æóEY¥•ÙEû¶“÷mßwä‘ü¯,\ðváùü³C|&ÿ6ç›aåRöC*qCûÀÕœ”‚÷dÃgî.?Œ2ñ!,Xo_©U>¶ŸÜëñWÿùÝzø²·:ð[å´ð9ÂhÉ唜À].X6ì-ûR\àó8Æ€·Ùp×ñʾó'Î×—NW 8¹\eÄi©TéO‘P4Ù>› ÷Q 9Șá$ ÷‘ÏWŠB…Bøw?”,~éÄ…£ #ÓƒpÝÞÞøò¬oÊC!qûúÂõågõ¤â7”`Ôƒž²Ø•\Q´“ø6ùh»ºÂ6”Já¶âïéë‹'šìLÃ%i0rDvɘôIZ~Ë‚oÛ¡P'—8“á-¾µ`Þöí­5Ž63S¿-”³·YþÏø×u£ ŠÒ ªkt5‹ŽTjÍL‰”ÑÉ€ øÆS÷ÃÛß6£¶”J%|ßR^¥Ó騆ƒçyQÊ.NÄ9T‹I<Ò;-#Î&I+•L&é t6™¦9e’Ιf΢”z½éÙR”ë=d«®k]‡€Œ jmŸ|a׫ÇcYì<åÖÌÎÙ¶™Ø§øëûyq™õß'~)ŠX844šÌôý ðàýð¾ÍkS”‚²üŽÈ%¢7s¹\4Q``` ª)bÆ”g#†A__ß¼yft/øW­úgÿÃ?´»)J˜‰m–Jà_þO!]Ë,R©Êœ=2ë´ÓŒåõeU£†WÔ?ìdÌB&ž¬R(Ô÷»nìp‘Ù°É>hõŒS™Ü""L£eq¤´[´Qæ3}w ¡oq> bšò3•Š3#‰Ö*þÆB!&U½ þ¼;E™ŒéÚçÂ{ïå˜cp‚ ¿g‡BÆÛ øë!ø¦oÀ‡£önˆkdÊËr€mAÚŠktùqƒ•.Jý»%dSëðï*ïbxş܆¹&„“óT]Âýœkñ€a†Ç»%€Ç=øà¬®.¯—!LOIŠùrêÆ|(¶äˆ Ë23lqý®0R`¦B1§…ÿ[ˆÛSì#¥¾W/Dʄ̜)•éiJEÈã:bâšgyÖÁ\†÷ð}ö¶ÁòCá>¥v˜›¸>>°& ï ®mF¹ nù¤!_¬ Ž:…xÙÚ!ø—^x[ Vy¦O  °öÄi6K@‡þ|¼­Ôa“}æÓðœý.xÅ0çmoù¸Vx^\º›{_÷UÞÒ³èš1îô×éç×ñ+§z G­IuŠÒ‰tŒ ²~ýz¶mÛV±lß¾}S+lôÙ/ñéÅ¿j,!x r¹ét:Š ñ}žJ{Õ­»ÀªU'e•¯ë'îÇ \rw]‚uÖ ø¿8§ŸN6 …wÝAðÜ"Œ£b/½“àƒÇ÷Ãï¨÷ûñ‡÷cuí%xþhò[Wa®ÜK_wèÅ1—ì"M‰ÜÊÖÅ«àð~VÂq©ßß÷ÜØgî&óñ%¤—þ+V÷Jwwc]~étèôv¿ÿ2Æ]Øë¶c<ùÞo˜t÷ÝôfÏÁ^y7ùsúÉÝ݇ùîs8å”v[Oë™é»³V€ü|EüZ2ù½œ9Ìf”˜Ø.¾å™ÒßNR—ë$?%Ó‘ü.Cö#û’Ä¢{^ø¼’ã&Û™Ì"äyñþeY6OjO§ÃIûÉrRÅb¸Ì4ã’¥ò\õýp™ŸÍƺ²hÇýýa»‘-ÿ—;Uº¾5À¨19¨ÚýSËÇìS™ò1Ùf/â°á±DâWY·D(Z $–I-³Þòòl¹Í2œ¯Õ7qíø<;ÜæÛåc{埽„éÌÒ‰}ÊÛ÷3>êÔ"nŒòvrœâZiÕ×%o…‰º„‰•†Ÿñ5‘ëDb”¯Yª|œ¡€òö<|,·"€ÊûØqÿ˜ßÁ×MwzÀ_τӻxüçåÌ?ŠÒétŒ ÒÓÓþ}û¤§§‡ááaFFF¸è¢‹ÚÞŠß;•köò®)úa¥¸¸iš”J%‚ ˜T¼˜K©Ee¦ÌÄ>}€—ŸçG{®ç÷Í¿©»žÔ§Ù³gO»OWQæÍx.úî^‚Ã~D8ånzH¤I*•"ŸÏGu½Òét4I@–+µY½z5«Ï>»~®geN1ÛL/»Žà‘7áÿÚ1°’*ݲÂ4ïÅb¥ˆ’͆·‘ã„Nºd·6×éë;“Ê”¡¡Ð˜*g*G¦a@÷+Â~f?©‹„mL]:Û†ü[YVíuäü<ý÷ì#–ãr©kÎ †ÏAæï_ Uά‘¹üeÒ ú1g=…ÿw*ö¢p©ÿùaœuÀûñ~Ü~ÎŽ²Æ)ÇÜ»Â_øx+2ôóE˜&ÆÉØ_=™Ò_ìÆ+ýó¸]Øï?(;doyï–{p×¾û ÇGÁ4¾æÅ¯§ïšÕä¯Ü…až†õÌ‚#Ë×ó “zjÁ{?L0¶ £ì`ÎdÀýöo1”[Fžëqï^Iú]ká¼ÓñnyŽ9†‘3ñ¾v?,Ka½#ܦP€þ¯„oÏ °ïÿ…¹ gp öÛO ýçÇãßòÖ{¾Ì€aP(€½þäÿxÁ#Ïâÿǯ±.í!ç@áŸ%»éWd¯Íàýã]ô—LŒW…ß§aÀŽ·\wp}7|¿<‹\ÜÇ^Íž»ÆøísÀÝÀõ*ú2pãçÑÓób»M¨¥ÌÄ>“%‰%’çœ@ª‡ÍÉ@µäœ-$JNÄYV.[YQ¶BDR) ‘Ëʼn¤ôÄ—ü”õEôIŠ9Éã$³>Ëgòü”À¾Baüºét¼Nr"µ¼¾óùpÝ={Â6‹HÒß×§IŠ5ÉTjýýá~j%H‚M›þøÝvß-eºöyç£=Üé¿™÷Ií‘Ù$ÿHúÚ=“,åÀb]!Ò8fê7®—_&®«•¤Vq=«ÜÈì$ǘèxVÕOù<_¾@ÉcJí°ZÇ‘ã‹ÈaÖ9Nõ6Õm“¬Áá,ŽÉ¯IR¤²³*ïæ!D1Óq'„_ãñE(¶ña>}æ—Cu¼¨Ì:FP0¯Ù•W^Ɇ ¸ï¾ûؼy3Ë–-kh[ xrl>ê̆öa’,„kétZWQj0]û €½{V²rá3ug]û¾O©TÒÐNE™&ÓµO—pÂÕØ‹±¾ÞØû¶I“iÛ6¾ïGé½€(-¦ ³&Aò^W§NRæ,ÓµÍÌßœÊÀ›ŽÂ«*@.3Ÿ=/Îú%RO7ifé²£3™IÃ~ìÂË„YLªËr$£Ô3žÃùÙûÈW™q>_™Aµ"sß²eôþî ìH¤ÜŽ":J £ÛܲÃtöB6C©;N'$ëÁ …³«²Ê®Æ~ÿjº–KjíO0Œó+LǶW«*ÚkY@úXºŽ±0_³\š¢ 8“þw‚e œM\ (¼ùg8'}Œü'Ow Èa|°¢®P@.w,C÷‡• ­Kψ¶‰ËA­€û〻Ôs¥Öúèñ¡#øŠ8\$t°†Â·X—•¿gçpRzrxœ+⢸Ñ÷Y²0Siþ<ÜØ¶¡·w1Ùÿ½N.VÔ®\n'Ìû„¶Ó·OqÈ+S£:•XòÖËÔ,â„€6T=ªŸ‘µ~¯þn«£‰Ž+ÂK’êl¦²½üLFðÈïꎘž}þ›aóGU³hølc—ÿKÆ*“°Ï-#vy¹MÜÜ4ÓN¶23êMH–hV¯ú˜Õ›¬2WÃ!(¢×c&~[ÅÿŒÝþ³ ÿP©TÂqœ°õ¡8kA™s´MPIÃ6nÜHOO###¬]»vJac¿t¯}xICë–ʱÈADÅÜ ÃP1E9ä©e›03û4ŽXÍ6¨…8cEèT¥6ͶOxµ/üå´½C¾ïGÅå“ã•i ÓY•9I3û¶>w<Á&ç‹qD „3˜³Y¬X]Ÿ‡=ÝÐgïK*rÉÒ!™A~œ a– Ÿx­Gœ=CÞÜpÊçÎà°›^S«'0€¬Í¸åÏôxŽ|"ÞF ï“È ùÖ4 ù•í”HožÜô=Ÿ=–߱ϧPn+ÔÏŒ"×èo¾ -²¤fq p­²`‘8Ó€Ö½™ý¯…QZ}9>FeÆi³Yv¼øFìT“ÊÕß ¶¶ãqðÊß±#é| Ê×0]^–2áí©P “ïOÚµ%¯My¨cØð¹"xå¿ÝÄù?ôßN‚çO„J³ßýP‹èz ™ß/Õvå'ÖçkžÊÔýRâ >>•Ùuª³ú(Ê\¡™ö¹ãÙ#9)XÖQ‘"¬@œÙ*M¬UH¶®äûXìØ!Ö$xCµ\e6i…ßàÿüÓv.íù5ÆY•þ×T*5¡ßHQ:‰ŽŠP¦eÒA]ºt”Ÿ¿v;ç×MŽãº.ÙòÀͲ,R¥¦ûÂ,žu¹eõ‡w¾ïcY–Î^W”0û €7»ÏxŒ×Lº¾ïû¸®K:Æ)'!—ú(*ˆ*Jm¦c›/Ÿv$¹£CåÓ…°ê±)XT ­&¡c5 Ü ,ËÃeLÁ‘jR‘ÿ< D†êmcÖÂq‹”&yƧT÷>u8pxäê+¯?D•X’hG®<Vª:%ÓÌCeºxOþNÓÄ"B@숒ýгYŽéÉ,qbgV/q†ÖÉãþü› ùDùÚK»j‰"”8€SŒÛ’O´BqH2˜È9z€“Žë×K–ÚÉâ`+Ï~öó°8q|q¸ rL©ík^:ž|ì—¿ÇC­'6ûüÃ|µGqÍg‹xLê§üI=ú(lßNñÎ;1V­Â[¼cãÆhÃ÷ÃB#åÜz½û·ä–.Å_·.Jåïÿõ_ã¯\‰¿v-™×¿ž`Ù²èž)Æá‡ã?ý4Öá‡ã•ëýÔ#i ÒVÉ„#u¡!¾ïÅ«#e¥LÕ>ŸîD.ê8WÉ÷dRMmˆ;Dh{òw¹<>q”K2«–<‡ª'¨ý*Ífº~!ˆEÓ¸“Ç~XÃ0(•J‘ŸVQ:Î~Û4H¬ພàˆ÷6vJ–eáº.¶m«˜¢(-Äõà“¿|™Ãºk^(ð}Ÿ´¦·Q”¶ðôèQ¼íãU ‚€'Ÿ|’ (•J‹En¿ývÜrÑß÷1MÏó0 #úݲ,<ÏömLÓŒDTyû¾_‘ŠÓ¶m\×DÖ 4ô[9d8~Ç{–/Ç;J| ;KÆE¡L¹~`5aÖéÈ¢)B§O-G|õ²bâͤh,ËH3'!ÛTΖs«>W“JçTj’}Êþ<Æg9‘¤z’²^H:Ò²Œr± …ªbƒ×îú)„OØrÛmÐÓÓÄ«;Ø¿x1£ÀÕå/¨˜Ÿù }ŸúÙ… #¡¯›Ð¦ìnˆ‹mxvõä!Ó¬(4ÒÿðÃäV¯®tº®X¹n¸.©›o&X½ó“Ÿ ?,•â‚Jå"¥|>¬Ç ax›Ta—ãUõ¹3ÀJbq±:‚¦—XXq¡"­]qÜ&ï­¤pj$~T:|«£âdb7Fb=³jŸÉgŠ´!ùyR’b#‰cÖz“Âl-äÕm2êlS½~²mAbqŠË9‹`÷üÑG£Ô朥; ôšñõ@æɨ–ê¿E0‘È6WJÄ‘‹R£â{M„TÙÖ'¶×j»“í\Æ °’š,IdXSæF¹ï©çH¥>-*•Jäóyó)s†y!¨<ìÂÓ÷½sé/ê®…B×uP!EQfS…SW?Íò:Ñ'žç‘JÍ4!ª¢(Ó!ŽÚ½óés&\Oê¤|ç;ßaûöí8ŽÃèè(]]]˜¦YaþïcF” ˆ—\®2Ya …Še¦iŽ[æû~”š³:’Ͳ¬Hà1 #fä÷ê(Tx‚ ˆDžF´„žä^J´WÚXo_AhŸCi˜ÿ:çÞ²f!ïûøi6[µg—zžG‘Í%…Í$òwr€š¼'ƒ ˆö#ëÔJƒ›\&Û@lN6š¦Ys`œlaµ¶³G0ÙœÈéDoÈ6µÜõŽW½®‘X7y}ä‰ÓOãÔ{âÄõzyä‘iœé¡ÁC'Äóp<áwb,^ÌÀë_Åð<¬XàJŠ ôwuë—¯K”9żT|`·oxþHÎWýt_2 ,‹êØP”Yâ„WíâÍoú~Íïûd³Y}q*J›ð®ã£ã?ó<\. äŒ3ÎàSŸúßüæ7ù÷ÿ÷Yk§žçENcY^(‚ uÄé+Næj¨ØGò÷Z×À²,|ß'—ËUGÐIª… ‰ö+‘8I'¶eYäóù¨(c5éS‹äyO„Æþ‹N«XÖÛÛË­%©Ì!æ ò¾×=ÈúÃÞYw=ÏóÈççxü§¢Ì1vþÍbn¿Éä _<ªb¹ëºôõõ© ¢(mfá³`¼)þ»T*Q(¢Ú(â,ìëëch(¬®p饗Îj ÃÀ¶íš ÒÖùéÖÕÕE>ŸÇuÝq³´Ä¡›Ífk:KÅy›¼Fâ0M¦Nóßzæ[¼zõ«9ÿ‰óyúˆ§ùÕÞ_ñÒ²—xlÿc¼kí»øæÓßdxÿ0ë—¬çk÷-zÆ¢^2‚,)Ô "&ŠˆžmÛŽê¸D˜& Õ¿¦þ·¬ñBÐ?Aü”eU µH µ¶O~îy•bŽïc]wV±W]‹>‚D÷¸nø³Úvª÷_‹|>üïyÓßG: étýè¼*ÿ…³i£ÔÄcòPC¥i$£'¡¾–Uâ3Uç÷fÒH ÄQ4­+‚ŽD%:„‚Luã–{ïå®;[tFóx!€“–t³Û¸©â³“½¥Ã˜‚ ÀÖOÃæ¥µ Ðqœh†œÖiP”Yæå—9nõ/0Œ®q5:ðW¥5ø@ÿs_+ Qñ}ŸB¡ÀÐÐPÅŒåR©‰)Æ|*\˜œ5_í¼Q©µ>«^VoÉçp½cLUø6 ƒhÆ{õ±<Èàààl]Ú9‰ëºQšZ}WNÌ¡z}’ãš©Ìê,‹5—[–…eYlÙ²¥Ý§Ö±ìß¿˜¾¬ xàš.‹Þ¿ˆµ?YËÏ~ý3œp€…Ï,dÿösÖOÎb•±Š›Î¿‰÷¯~? ŸYÈ{}/GŸyt\ø¸ýññÅ;L¸í‘ÛøÕµ¿âKoý‹þ|äà«k¾~n 9H”¥bªô®%»xyùË|ïöïqâó'²zõjž~ÝÓìÝ»—;¼;¢ˆFÇq0M“L&SõqÊ>yŽËßÉè&?Àu1Ëbëºã„šd PÙouäšô9Dì©N•™¬¯6!ÕŸ§ÓåcA‰*ãÚàûã—©’ØÿLÈ8‰8“è8ùžþùcÞ"w”CžF{­:ò¸l›¥/¾È’Ú}êïÁ=cûX_õŒïëëc`2ZQ:ˆy!¨ÀKÏ=Í}½Ûk~.ƒƒCu°¥(íâ‘U«à°ùá‹#¼Çì­øLf`+ŠÒ> ·à H×5“ÉÏçkÖQZ8£&K¿5W¨—Ji ‰"Ðk¨(ÃoZÆ_±ƒ_=À§Oã:nAöaƒt:]3JêLά½³IºÁçqç]}^¼ V°Gr>¡äÛqa5«Á„Lo&œZ}pðàæ;ãÜ8EbQ¦H8õڇ矞gFžááÞ‡ù­“~‹gî}†[Ÿ»•»ï¾›7-yGÜu‹[ÌiœÆ³ï{–Ç~øÿðaÎxÝ÷ãØ½b7¿yñ7Ü÷±ûxúˆ§Yú[K9ãÑ3xò¥'ùʲ¯ðß^úo<·è9Ûw×} §~ ýÏôóÜñÏqì)Çrú·O`ñâÅÜuö]¼~ñÞqãKõ )sy!¨øÀÞÇᬣk×OI¦)QeöØ¿x1ÜÇ/9¬Â!4_œ…Š2×û×ç0ÆÐÝÝmÛ5BÇÁ÷}íàÎɺʡM¡PˆR²)ŠÒ9üîÂ[±-æ+?þ Ø000Ð9©æäqQh˜ü{ˆÊªê²¬ªòó‘Æ‘¬4V²’•àñ£Ç²Î\nSN$3Ü”pq´Ì†r»¬xÙû¬÷ÅU®ËÕ¨ßj½5.’`à¿ÇçôNëaáÞ™zg¼­\®w‰qItŒwšïŒ*»ŸïžošpœoŸ_YñšòòàüøÚ$«vá1δΌ÷k?¾z|u1©\ŸøŽ>j||8Ù?9ü¼P^'ï÷¡ëâäSNædóäðøfx]ócù_,oÕ¤(ŠÒrïy˜¾çðhbY.—ÓlBÊœc^*ìß9¶‹Ï_ÜTŠ^+ŠÒN;7þÛ«£e}}}š#SQÚŒpð%Ì¥Ïã8NT]ð}?J3¡Ì†aP*•ÚÝ ¥z9Š¢tærâ·?sæGÈÏÑÔ$µtZÑ„j½òͪåµÖIλ¨ç3'Y'¹ªõ!̳“̵S]Q»úfb;jüÞÕç^}þöÛM´N²¨D |§\qJÍk¥‹Š¢Ìe<àgÿï0nYvK˜î²L:ÖIDÊœã°v7 l?°„GÖŒðêßuÅòB¡@.—›…je.räÁ#Ù»s|ALÍ©(í'ŽüÞ^Œ3—àºnÍâÄù|^ß¡³ˆÖ…¢©öšKQ½„‰¢d}ß'‚ ˆê8Èö“Ön˜E¤ò»œ“çyŸ ò¹ëºÑ¹ø‰ºÉí«·U*Y¼ÿ÷¹såot&m«QÝ@QeÞ€ßì<ޝõµhY.—ë¨>–¢4ʼˆP9&€ÌS¯—ó=úûûg°gEQf‰þ‰lÛñzwì*•JZÓHQ:€xÍ®åícGðö«ÜqEŠK¥’:Œfy.ª#ýÐæé§ŸžÑ;Òó½»eŸ²/¤Às*•жÉård³YJ¥ýýýtuuÑßßO__Ùl6j—ïûQfÏóH¥R”J%lÛ¦T*Q,Éår °råJƵSêÍÈß…B!*âÏ.Ív'j—ïû‹Å¨0·Ÿ(X-çè8N´Žïû‘í8étšR©D6›Š©–J%R©…Bb±H&“!›ÍR(H§Ó¸®}ž¼ÆÕ×Zö/×I¶K^7i«çyÑ÷aYÖ¸ïBŽ%m•ÂáÉcˆ°}ûvzzzÚm ˵{¯å+©¯´»Š¢(Š2·xâ§­©X”J¥Ô7¤ÌIæ… òÒ÷àÇ//æY ¤Ic 9È¥ðM8æÜ§BG>·Üu ëß¾ž…¯YH@Ùª¢(³ ý5|÷=_©H-äº.Žãhí±6`š¦Fð),Z´hœÀYïû‘0"â§8ðÅy.Ns‰>HŠ ²ïû¤ÓéÈ/Eµ‹Å"¦i’Íf1M3jˆ âÔ¯U;Bîáb±ˆa‘0+©>'Kù)u›LÓŒ¶•}îÙvÎf³†-ïïï÷w=dŸ†aDc…‰Æ ²~±XÄuÝqmaJÚ&µo¤-ù|˲¢(@9®|^ýS®uõþS©T…ÖÕ×C~ÊùVCزeKÃÇ8ÔøÁÊpàÚÝ EQE™s>&&Y²ê;R:Ž9/¨<ôѼ|àev}âïxŠŸS¢ÄÚÖòÄsO°&µ ‹€Ú!þfùŸ¢(ÍÅñY¬£Ä‚ÞôÒË‘KŽdÙéË8û˜³ùÿøÿ(RÄÇìOlÑÅÅÂÒ—¦¢´˜Ç¶‡³ÓÅé&3²;-2E:Õ=\·±'ì4sÒö+Špä‘GÖœ©'"H²¶‘Ìê³,+rŠ‹Ó\j"M¥KÒéŸü»úóF&-É9LµS#³«?™Ó™xÕȹT¯S}œéÖ¥1Li/=ôçw^»›¡(J üò?›é×ÿ“4ˆÉgµLP~r½í$R":mÛÆuݺË>h²ÃDûÈd;&ÛÆqlÛ®Hç(ëVGšÊº2QCÖ«Žâ”PÓ4£u«#Ûåo‰®”IòˆÚZ½äyJ{¨M’F¢7“Ñ¢2ñ#ZÕéû~ÝãÎd›ýû÷·Û:ž§^yo°ÿš .°qqù·îãâg/æU¼Š%¬D‘/ ‹ Ò¤£e•)JE€©5¾“ýÔZžü§(SaÎ *Ϭ9W<þ#†?ùžäI~µ÷Wüúé_ó%¾Ä›x}ôEÎZ1°jª ÎËœõ˜ìó©PýÂO:˜•æ"Nz/z'¯u­¨ yX›˜øøÑ6AùŸRŸç?ŠÇãõ_¥H‘à€Ô™¡Ã§D)z!Êu‡¨\s?zñùøÑ÷SÏ>d]¯æ s¢m’Çšï$¯S3°±£Lrß:‘Å–äÙ—´MíØ´߇÷¿æE~p vž~òûŸà_ƒÔ¾ODŒ˜Hø”ïQžŸÍ& ÀÆÆÁ‰öŸ´ayfTÛµ—ø7çÙmä‹ÝM…ä{­ë5ʾõûèÙ¡)…êá”ÿ<øÂƒ¾ópÖ|l K–,‰ìÓÁa.½ºªßíÕˆxš´_y÷‹-YXxx3r˜ µä‘&=#›N/Ù¯lÍÜßÏÏý9=¨}Ö⬳Îê¸IŠ¢„øø88dÈ"Åxà8wô\®>ïjÎÿ‹óY½zu´ÍÒ¥KÙµkï~Õ»ùú¿E#¶ÁG>òòé<ŽãD¢€øRóA„ùLœñâØ—õD”¨vÖ×rÚ'÷aYV… #ªÒމŽ+û¬ÞFD#4’b‰-²iŸ0²?‰¾4 #mr¹Åb1Ú‡DÓÖJW ã£Ee_És“T–¹\ â»¨>¾¤&•å²ÏdêOù[Ö‘eÕÛȵªÞFÚ]½Í¯~õ+~øáv›AçâÁð}ðË»Žç–ø$¯åµ¼üî—ù§oÿY*'ÉØ¦H‘…hÒ-Ä>Sñ¸¸88¤H‹tñðjN¾óð¢¾Sõ¸Pú¬²¬Ö¸²Q¤?›·Û÷$ç+ýGùYolœ¼¦sÑ_ýÐI5½o»`lll¬Ý'6ÞýÉOòã[ÞÅÙÿûjn¾äf …0µÙxSAxÓu¤'ö³9;öP$9ðNþ-4kà¹sçN¾üè—5×tƒƒƒ|ú†ƒüø©ŸñŸÿô&ðˆr¡7q&÷ؓخ8S;IkV´êçLõ>«mc¢åsýµûÆÝÜ{ñ½ínFDZiÓ&~qÉßpÑG¿ÁžÏü’Ç?ø8g?y6_>òË\|äżzñ«+:JÓu\º¸MqzÖ" `%+É’%O~JÛÉd‹"Íyu9rØåSe*"t³dppÍ›7Ïêqç›6mâÙ­Ï’%‹[p£:Jó©\Ëà\& $g4úøtÓMªüo:$…Üf‰BИÈ=>wÛçø³#þLû¶U òƒ»À³üì”úGû÷ïçˆ#Žàé§ŸféÒ¥<ñÄwÜqìܹ“ãŽ;ާŸ~š%K–D³›—,YÂèè(«V­âÑGeÍš5ã~îÙ³‡%K–D©ædûãŽ;ŽíÛ·sòÉ'ûùÄOÔ<Κ5k¦´Ít޳ÿ~V®\ÉÃ?\s›x€•+WFëC˜FoåÊ•ìÞ½›uëÖñóŸÿœsÏ=—»ï¾›3Ï<“{“O>™Ý»w³lÙ2FGGY¶l£££¬[·ŽíÛ·GÛÈñV­ZÅþýû£ãÈï»wïŽÖ9çœsf´Í<Àš5kؽ{wÝmå»LîãŒ3ÎàþûïwÜ#Ž8‚… ²ÿ~–þr©ömk°iÓ&¶nÝ À=ûîáã÷qN=õT–¼q 7/½™žx±cœ{ì¹ãœSïLe’Édë6kÂJ#ÑÜÓ=¿f¶QöÓì‰:ÍÞßtØ·o=ßéáóïÿ|ÛÚЩlÚ´‰«®ÞÊ_€G7þɦpb\Y¬œë$í¯z\•œÌ ±ÑÌI5ÉvÔHjùƒ:É6Üu×]üŸÿOSû¶s>Beéo~C°g5>}!ªÕ­ ‡oözº2¥sØâlA'ñÕæ¹Û²è¼G0Çsšê’—TÒ1Ç„ÚÞ¡Á&g\ÜîVt&;v¼Ì?Ÿó2c﹞òQrÇæ(Ü]à“ç|²iÇh•˜ag4K–4S›)l`0Àü«S2Q©švÏRÆÓO?¹\.ªÇ¡´†zϨZé€ML†šÑX y¼f÷Cš¹¿ŸÞõSíÛÖá¹EÏab’"Î8-§Ëq§b†·ÌÄ–4:Åb‘R©D>Ÿ'÷…\˜*æK¥hv³Ìü†8õ¹ÜÄ{ØÃz…5î§ÿx9mÎaå”?‡ûÌW˜øc>æK&¼ Œeþ ã%ŸurÕódMùç9u~.›àbLg›•u¶9·Æºkª~ž_þù†ª¿×PÙoõñj1Ùµ˜Ê6çV}^ƒà¨rÚ¦)wÓ_jßv"$ŠáÖü­•,›ÆÎê lyL6i¥‘ì(Ò¬ 2ÕNØf‰Éö5S‚©}'­bpxÁ݃m;~§ãÝ ¬/rÊþQllr¹Ü¼éã&ï»j¬g“í¼W[9FïT¶ÜÖ|¿mÇ *###ŒŒŒ°víZÖ®];éú«>ÎÂÅ›6¼)Ê+­³ø¥5LÕ>?úÖ½ôtê«(J똪}Z73|Ö÷ydÑ#8ŽÃU§_ÕT1e6˜‰ˆ (³ÅTm3É|hÎæbŠeb¦jŸ¯Ø÷Š0õ›¦Žá3™z¦I&uªN„¤—©þ9ѳ¡^!}žtZir¦jŸ’Âjºµªe*BÀdG3'µ4k_µ&4»}Í~Ÿj ŒÙe:}[ïxì'’{sœâ­Õ¶ª(­ä°v7 ɶmÛ¸ä’K¸öÚk¹ä’KضmÛ¤ÛüüÙßfÙ¾‘(·b#SEQ¦ÎtìsÍÊÛyÝK¯ÀuÝ–¥áSezöù_¿YÃycgáô²£/k÷i(ʼc:¶ ÐÝÝ­}ZEi1ÓµOß÷)•J N§[ž%AQ5¦cŸ…B!Ei Ó}w~Ëø&Gï\ÉÛßøv2™  Â²2·é¨•-[¶pÍ5×ÐÓÓÃðð0—\r ===*ž‡=йòr¹AlÛÖ™7ŠÒ"¦eŸîä­øN¾ño´»ùŠ2¯™Ž}®þÕbÞrúÉtuu144¤ZEiÓ±ÍçŸ^'!(Ê,0û¼÷Þ{¹ë®»èïïowóe^3ûT»T”Ö3Û<úù£Ùùà>Ì—Æ0ÞI*•ÒèeÎÓ1*ƒƒƒ,_¾<*³~ýzÖ¯_ÏààÄ9<òYN<1xvb1£M›6µ» 288È–-[ÚÝŒ éôkx(0]û<묳øÉO~Ò±ÛN¿·¶lÙ2é5n'sáùq(0]û|íÛŠ}ôыŎSæÂ½¥Ïe2¦ß·=²#û´Se>݃nï2Ÿ¾“™2]û<å”SæEzi½§;ùò4ƒéÚç|`.ôe¾ÜÓóé;™)ӵͻ^~‚ƒŸû=Î?s½½½IÖéï’¹pvº½ßu×]üâ¿hê>;&Bexxxœ¢¹|ùrFFF&Üîþûï'®ºê*Ž<òÈvŸÆ8vîÜÙÑ7Ö3Ï<óÏ>Ëððp»›R—N¾†ÃÃÃ8p€5kÖD/•ùÈtìó?þã?øÎw¾Ã+^ñŠŽýþ:ùÞؽ{7wÞy'×^{m»›R“N~~<óÌ3ìܹ“矾ÝMi9Ó±Ï_ü⌌Œpï½÷òš×¼†¯ýëí> :ùÞôù1³¶=þøãœzê©ínJK™nßÖó<Î=÷\Ö¯_ßîS˜|N•N·÷Fiä;Ѿm}ûܹs'Žãð£ýˆ“N:©Ý§0#¥{z®0Ùw"}Û´»©-gº}ÛsÏ=—c=–U«Vµû¦Í\è7Ê|yÎ4òhßvâ¾íâ¶sÆa[þ.çwñÑîS© Óß%sá¹ÐÉö¾sçNvïÞÍïüÎï4u¿#¨ìÛ·oܲFŠuò ¥(ó…éØç§>õ)>õ©Oµ»éŠ2}Þyçín¶¢Ì{¦Û·½÷Þ{ÛÝtE™÷LÇ>ßûÞ÷òÞ÷¾·ÝMW”yöm¥3™nßö¶{î.ÿöévŸ‚¢4ŽIùµ|ùòqË&S9E™Ô>¥sQûT”ÎDmSQ:µOEé\Ô>¥3QÛT”˜ŽTÖ¯_?Î÷íÛ×Ú©(JkQûT”ÎEíSQ:µMEé\Ô>¥sQûT”ÎDmSQb:FPéééaß¾}Q! ááaFFF¸è¢‹ÚÝ4E9äQûT”ÎEíSQ:µMEé\Ô>¥sQûT”ÎDmSQb:¦† ÀæÍ›¹òÊ+Ù°a÷Ýw›7ofÙ²eín–¢(¨}*J'£ö©(‰Ú¦¢t.jŸŠÒ¹¨}*Jg¢¶©(! ÆÆÆÆÚ݈$###ŒŒŒ°víZ S”CíSQ:µOEéLÔ6¥sQûT”ÎEíSQ:µMEé@AEQEQEQEQEQEQ¥Óè˜*Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(Š *Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(“ ‚Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(Ê$þéOúÓínÄ\edd„ááá¨S½Ï–/_>åÏ›Éðð0‹/fÑ¢EÕ¾ÑÑQ<Ïctt”ãŽ;nJm˜Íë§Ì=fbŸí¶ÍFÚÐnûì„ö)s—‰ì³“î­éØg»m³Ó®¡2h•ݶë~l…}Ïö¹´ê=­Ïˆ¹E+ǤdŸ3µ¿Ù<—VŽqÕ>ç­“¶ã^hÅØµ“Þ3m«Úçx:ášŒŽŽòÄOt컣ÓÇÆÃÃÃlß¾½ãý¶³î[S¦Åg?ûÙ±îîî±Ë.»lì‚ .ûƒ?øƒ±}ûöEŸ_wÝuÑçÝÝÝc×]w]Åö“}ÞL~ýë_uwwÝ~ûíÕ¾ûâ^uÕU ·a6¯Ÿ2÷˜‰}¶Û6iC»í³Ú§Ì]&²ÏNº·¦cŸí¶ÍN»†Êü¡UvÛ®û±ö=ÛçÒª÷´>#æ­“v’}ÎÔþfó\Z9ÆUûœ[´rLÚŽ{¡c×NzwÎÅï¤Óé”kòÙÏ~v쳟ýì”Û7íïô±ñUW]5vÁt¼ß¶¾5T¦Á¯ýë±SO=uì¾ûî‹–]pÁc¥R)ú;ùEÞwß}c§žzêØ¯ýë†?o&rc$o¬Nh_òšíÛ·oì‚ .»é¦›jÃl^?en1Sûl·m6Ò†vÛg'´O™›LfŸtoMÇ>Ûm›v •ùA+í¶]÷c+ì{¶Ï¥Uïi}FÌZ=&í$ûœ©ýÍæ¹´rŒ«ö9whõ˜´÷B+Æ®ôßI§ÓîkrÝu×}ìc;õÔSk *íþN;}l,¤<µÚÛ)öÝßšÖP™###ôôô°~ýúhÙ…^Ⱦ}ûdùòåôôô°~ýzÖ¯_Ïàà`CŸ7“-[¶°~ýz6lØ-ë„ö ²oß>.¿ür–-[†ëº\xá…“¶a6¯Ÿ2÷˜‰}¶Û6'k_#Ÿ7ƒ‰ì³Ú§Ì]&²ÏNº·¦cŸí¶ÍF®‘Ú§2Ze·íº[aß³}.­zOë3bnÑÊ1i'ÙçLío6Ï¥•c\µÏ¹E+Ǥí¸Z1ví¤wç\üN:N¸&6l`ãÆvØhûf£ý>6aãÆ,[¶ JG¦¾µT¦AOO[·nþåæ›oŽn®áááqyï–/_ÎÈÈHCŸ7‹ááan¾ùfÒéô¸åínßÈÈ6l`Û¶mlÚ´‰+¯¼²â¦¨ ³uý”¹ÉLì³Ý¶9Yûù¼LdŸÐ>eî2‘}vʽ5]ûl·m6rÔ>•éÐ*»mÇýØ*ûžísiÕ{ZŸs‹VŽI;É>gj³y.­ãª}Î-Z9&í{¡Uc×Nzwδ­jŸãé„k²~ýzzzzjÖÅè„ï´ÓÇÆ^x!›7oftt”ÁÁÁH¸¢컾5TfÈÍ7ßÌ%—\BOO7nbµ.IòKšìóf0::Ê•W^É5×\©‰6Ú722©–—_~9k×®eÓ¦MÑ;Qf£}Êü`ªöÙnÛl¤ í¶ÏNhŸ2?¨¶ÏN¸·fbŸí¶ÍFÚ ö©Ì”fÚílß­´ïÙ>—V½§õ1wiö˜´“ìs¦ö7›çÒÊ1®ÚçÜ¥ÙcÒÙ¼Z9ví¤wçLÛªö9žN¿&övâØXáÚk¯åæ›oŽÄ”ÉÚÐéc÷f´Q•i2::ʦM›Ø²e W_}5W_}uôY-õ3©pMöy3(•J¬_¿> Û·oÃÃà wDû ¼Q¯¹æzzzؼy37ndÛ¶m“¶a¶Ú§Ì]¦kŸí¶ÍFÚÐnûì”ö)s—zöÙ ÷ÖLì³Ý¶Ù)×P™Ÿ´Ângû~l¥}·Ã¶ZñžÖgÄÜ£UcÒN²Ï™ÚßlŸK«Æ¸jŸsVIgó^h娵“Þ3m«Úçx:ýštÊwÚÉccaýúõlݺ•믿ž›o¾¹cü¶íö­© 2M.»ì2Ö®]‹ëº „7[õ—°oß¾Héšìóf1::ʵ×^˵×^ËÈÈ7Ýt7ÝtSG´¯§§gœ‚˜ü{¢6ÌÖõSæ.ÓµÏvÛædíkäóf0‘}vBû”¹M=ûì”{kºöÙnÛì¤k¨Ì?Za·í¸[eß³}.­zOë3bîѪ1i'ÙçLío6Ï¥•c\µÏ¹G«Æ¤³}/´jìÚIïΙ¶Uís<~M:å;íä±ñ¶mÛ¸öÚk£¿—-[VqÜN°ï¶úÖ*]¯TpÝu×]pÁc·ß~{Åÿ_ÿú×Ñ:ÝÝÝc·ß~ûØØØØØ}÷Ý7ÖÝÝ=¶oß¾†?o6—]vYt¼Nhß¾}ûƺ»»Çî»ï¾èï .¸`ìºë®k¨ ³}ý”¹ÃLí³Ý¶ÙHÚmŸínŸ2w™Ì>;íÞšª}¶Û6;ñ*sŸVÚm;ïÇfÛ÷lžK+ßÓúŒ˜;´zLÚIö9Sû›­siõWísîÐê1i»î…f];éÝ9W¿“N¦S®Ée—]6öÙÏ~vÊíkuû;}l,í“}vºßv¶}k*¨LƒÏ~ö³c§žzê¸ÿI½îºëƺ»»Ç.»ì²±îî‘Ï›MõÕ í»îºëÆN=õÔ±Ë.»lì‚ .»êª«nÃl_?eî0Sûl·m6Ò†vÛg'´O™›LfŸvoMÕ>Ûm›x •¹O+í¶÷c³í{¶Ï¥Uïi}FÌZ=&í$ûœ©ýÍæ¹´rŒ«ö9whõ˜´]÷B³Ç®ôßI'Ó)פž Òîït.ŒÅVäì·mßÚ‚±±±±¦ÆÛ(###ŒŒŒ°víÚš!C“}~(´Oޱ|ùrÖ¯_?¥6´ûú)s›N¿·:Ý>;¡}Êüd.Ü[í~~ÌäÝÙ)×P™_Ìäžë´ûq&mísiÕ{ºÓ¾efÌ—{a¦ö7›çÒÊ1n'}'ÊÌ™/÷Â\zΨ}Î.~M:ý;í„ö G©°:ݾgóª ¢(Š¢(Š¢(Š¢(Š¢(Š¢(Š2 Z”^QEQEQEQEQEQeTPQEQEQEQEQEQE™TEQEQEQEQEQEQ&AEQEQEQEQEQEQ”IPAEQEQEQEQEQEQeTPQEQEQEQEQEQE™TEQEQEQEQEQEQ&AEQEQEQEQEQEQ”IPAEQEQEQEQEQEQeTPQEQEQEQEQEQE™TEQEQEQEQEQEQ&AEQEQEQEQEQEQ”IPAEQEQEQEQEQEQeTPQEQEQEQEQEQE™TEQEQEQEQEQEQ&AEQEQEQEQEQEQ”IPAEQEQEQEQEQEQeTPQEQEQEQEQEQE™TEQEQEQEQEQEQ&AEQEQEQEQEQEQ”IPAEQEQEQEQEQEQeTPQEQEQEQEQEQE™TEQEQEQEQEQEQ&AEQEQEQEQEQEQ”IPAEQEQEQEQEQEQeTPQEQEQEQEQEQE™TEQEQEQEQEQEQ&AEQEQEQEQEQEQ”IPAEQEQEQEQEQEQeTPQEQEQEQEQEQE™TEQEQEQEQEQEQ&AEQEQEQEQEQEQ”IPAEQEQEQEQEQEQeTPQEQEQEQEQEQE™TEQEQEQEQEQEQ&áTJ¥®ë¶»J™ p]Ïóf¼/ß÷)•Jí>%eš¨mÎ|߯iÓjŸsµÏùM£öéyA´»¹ÊPÛÔz·N彪¶Ûy¨mvÍ“‚Úç\Gí³³˜®}ê¸tþ 69™/öxH*ŽãÌYCìíí^Éßç*žçÑÕÕE¡P ¯¯L&3£ýù¾ã8í>-ešÌÛ¬õ÷¡B.—£»»»¦M«}Îmæ‹}ª¶9اïûzýæ j»sŸzïÖFß«j»É|±ÍZÏ5š=&µÏ¹Î|±ÏùpoM×>u\:¿P›œ¿Ì{<¢Ý P&ÆuÝhöJò÷¹J__Ùl–l6Ktwwã8©TªÝMS”)QmóÁ>§Šïû vìØišAÀÊ•+I§ÓX–Õîæ)‡0óíÝÙ.šá`R”© ¶;ñ»µQÔv•f3ßú½í“ª}*Íf¾½;§cŸ:.U:‰ùf“Jmæe„Šã8tuu±`Á2™LÅÍ+j÷Ê•+Éårär¹ µÐó<úúúX°`Aôà†PU,•J¬\¹’•+WR*•Èår¬\¹’®®® åt*ëND.—‹~^vÙeÑ福žçÑÝÝÍ‚ èëë‹¶©·|²Ï&¢Ñó•I6›À0 vìØ½e?ÉïGÚ%ß•ì³^x˜¬7Õí”Ùa"Û„¹cŸIÛ”û,ù÷DLÇ[m›ØJ-û”ïÏ0Œè§t`ë]·ä5SÛì,fbŸõlÚkŸÍzwNôY§ÚçTí,ùþ”¿-ËÒAè@û½ÙïÌëõ{§òn­¶[Y¦¶Ûh¿wvß«žïdcÒä~šù^•ejŸö{;³ß;]ûÔqéÜGû³ó«?{HøqÇæ;vìÆòùüØØØØX6›ƲÙìØž={Æ ÃëïïÛ³gÏX:ÆÆÆÆÆ¢ÏeÛ1Ã0¢}f³Ù±±±±±|>?î¶mGm˜Êº“‘l_ò÷É®œ§Ó4ͺË'Ú¦Ñ66r¾Åbq̶íèg*•ª8`,NíÙ³glhhhÌ0Œ±±ŠÏä{‘Ïdÿétz̲¬±={öDß_½í”Ùg"Û›söYmØçtlp6l³[©gŸétz,•J‹Å±T*UqýêÙ§Úfç1ûœÈ6ÇÆ¦fs­°Ï™¾;'ú¬“í³P(L¸ÝDïÏ¡¡¡1Ó4ÇöìÙ3fÛ¶Úf£ýÞÎí÷Nf»õÞ«cccuß­ÙíØ˜Ún'¡ýÞÙ¯6z¾“Ie?Í|¯Ž©}vÚïíÜ~ïtíSÇ¥síÏοþì¡àÇw‚J6›K§ÓËLÓËf³cù|¾ÂöìÙSqs‹Å1˲*¶M§Ó‘1 ò'ÿ®6ÄF׌éb>ŸK¥Rã®K½åmÓh9_¹ŽòR”¿“d§S:šb@µ¾gÙ:3 £bû‰¶SfŸ‰lslllÎÙçt–Ó±ÁÙ°ÍFl¥ž}ÊK[~&·©gŸj›ÇLìs"Û›šÍµÂ>gúîœè³N¶ÏB¡0ávõìsÏž=c¦iŽ EûêĬ¢ýÞÎí÷Nf»õÞ«²^­wëDý^µÝÎBû½³ÿ^mô|'“Ê~šõ^•ïWí³sÐ~oçö{§kŸ:.Ûhvþõg?î¼Kùåy^æ'˜¦ „!ôÉðÚêõ|ßÇó<,XýïØÐ¢ ‚ :g!ŸÏ×]>Ñ6ÍÆ4Múûû±m›|>O:®¸ÆÕ߉Pm¾ïT„ÞU‡·M´2»Ld›phØçtlp¶l³[©þNn¸áÇahhˆ|>ÏŽ;ðÕ6;‹™Øç|°M9ÇùdŸlWË> …–eA”vÁó<-¦Ø¡h¿·³û½“Ù`-»-•J¾[ë½WÕv; í÷vö{u²1)4ï½ jŸ†ö{çŸ}ê¸tn£ýÙùןl»ùàÇw‚ÊdùH'ú ÃÀ¶mÆÂÈè+nÈÙÆu]8Psy½¼’Í.ždÛö8C«gxÕToÉvY–E±X$›ÍŽËµ8ÑvÊìÒH®àCÑ>'³Á©Úít™Ž­ìÚµ Ó4+ìØ¶í†ìSm³³˜‰}ÎWÛ„¹mŸlWÏ>ƒ  P(P(ð}Çq*òƒ+ƒö{kÓ ý^˜žíú¾?á»u¢~¯Únç ýÞÚtÂ{µUcRPûœ+h¿·6sÙ>u\:·Ñþlmærv²íæƒwÞ *¦iR*•¢ îy^¤|¥R©Š›«º¨P*•ª˜)]]]s®£cÛvÅ5p]—¾¾>~ÿ÷¿æryÕû¬YX–©Çr}ǧ¨ÖÂ÷ýèû’ílÛâl6›Å4ÍŠYm§Ì.Ù&ö9‘MÇn›ÉtlåÔSOÅ÷ý '¬ã8m«gŸj›ÅLìs>Ø&Ì?ûld»Zö™Ïçˆþ[–E>ŸŸƒ’ùˆö{;·ß Ó³]é/×{·Ö{¯ªívÚïíÜ÷j«Æ¤ ö9WÐ~ïü³O—Îm´?;ÿú³“m7ü¸G´»Í&Nãy]]]ÑÃ8•JáÃ9•JÑÝÝišãT.Ó4Éf³ôööFÛÚ¶mßLÓ$—ËQ,+~ŸHÁ•6Ë5ð<|>_wùDÛ4Ã0ÈçótwwcÛvt}ÓétC×!“É`šf4s/›ÍŽ{˜Êþå;«·2ûLd›0÷ì³Ú±ÏéØàlئœÏTmå¼óÎc÷îÝß©eYu·û<餓Ô6;Œ™Øg§Ù¦´©YïΉ>ëdûœêvÉ÷g#37•Î@û½Ûï•ó™ªíŠã Ö»u¢~¯Úmg¡ýÞÎ}¯¶bLZ µÏÎEû½óÏ>u\:·ÑþìüëÏN´Ý|ñã.(‘™wxžåÚå+‚(t(lÛfÁ‚ìÙ³g\^Lß÷1 £íi‹ä\•ßQ嘦Y¡è×[>ÙgÍ>§F¯¯ëº p]·åÛ)­¥–mÂܳϤmJNÇFís:6ØJÛœ©­Ì–M+­g&öÙ)¶™lK3ß}Ö‰ö©vvh¡ýÞÎë÷Îö»UéL´ßÛyïÕé^[}¯Î?´ß;ìsºÛ©]wÚŸ?ýÙCa ;o•Zø¾Oww7ýýýX–E¡PÀó<ÚÒ–‰ %Ù¶]3¤iºÛÍf›MÒ fc;¥=¨}ÎNk1Û¶¢¶9÷èûœ ¶Ùìãé;P™.b·Ò–N·ÝfKmP™µÏÙic3Q›>tèûœÉ}¨ÙçtQ»î|:Å¥-‡Úûr¶Ç¢sÉ&ç]ʯ‰0M“b±åf3M“þþþ¶´EòÝMÔÖfn7›ml6ÓU$;YÉTÆ£ö9;m¬·¯Ù´µÍ¹G§Øç\°ÍfOßÊté»…¹a»Í>–Ú 2jŸ³ÓÆf_'µéCƒN±Ï™Ü÷‡š}Τíj×M§Ø#šïËÙ‹Î%›<¤"TEQEQEQEQEQEQ¦Ãaÿ?{ç'GYåý/Ü™I…@‚a+ —Ej¸ Š5Ô߬݃ŠBVÓ½î¾uG»_wEEW»ev5âªÓq ÞÍ”Ëz‚S‚ ŽŠSÊ%Ã}Š@HL%CîÌûÇÓOuõ\;™K÷LÎ÷óéOw×õ©ê:UOŸßsΩtAAAAAAªTAAAAAAF@AAAAAA„AEAAAAAaDPAAAAAATAAAAAAF@AAAAAA„8¦Ò -—]v§œrJ¥›1$[·neáÂ…•nÆìÝ»—½{÷2oÞ¼J7eHªýnݺ•üÇäïxG¥›RU|ùË_¦½½½ê»jnßöíÛ™5k³fͪtSe2Ü?ž|òIî¸ãŽJ7£êˆÇãÌ™3§ÒÍ’ÉpmÉýctìܹ“SO=•n¸¡ÒM©:ª½o[.Õ~  ÕnïåRîo"}ÛÁùùÏÎ7¿ùÍ)q-i×ôd ÜßDú¶ƒSí}Ûr™ }àr™*÷™réÛÍ…^ÈÙgŸ]éf Iµ?K&Ã}¡Úíý‰'žàꫯfåÊ•c¶Í Tòù<ù|¾dÚ²e˨©©)™_WWG]]݈Û;å”SX·nÝDFÙ¬\¹²ªÛ×ÑÑAGGÍÍÍ•nÊTû9liiaÁ‚•nƨÉ6£Ë”cŸ^x!kk´´´ÐÐÐ@CCC¥›2(“åþ1kûœ3gNU_û“åÚªæs8YîS#­o[.Õ~  ÕnïåRîo"}ÛÁY°`—]vYU?›ÊåH»¦'åþ&Ò·œjïÛ–Ëdè—ËT¹Ï”û›HßvhúúúªúZ¨ögÉd¸/T»½Çãq80¦ÛœpA¥¥¥… 6”L[·n ¬_¿ž–––-[ÆÆinn¦©©i¢›8¦,_¾¼ÒM–ºººª½ihªýN†³M@ì³444”ÕA©“áþ1U8Òìs2\[rÿ4GZß¶\¦Ò5Xíö^.Sé7)‡#íÙy(È5]}L•ߤ\Ä>g2ôËeª\ÓSé7)—±îÛVû j–L†k°Úí}ñâÅœp cºÍ Tz{{K”QZZZX³f tuu±bÅŠª¿°G¢Úúå*Ê•¤ÚÏáTa8Û±ÏJPíÍÉpÿ˜*iö9®-¹š#­o[.Sé¬v{/—©ô›”Ñöì<äš®>¦ÊoR.bŸƒ3úÀå2U®é©ô›”ËX÷m«9Tÿ³d2\ƒÕnïã!¨LxQúŽŽŽA/„ŽŽjkkà yéÒ¥,]ºtÊ„Ì Bµ3”mêybŸ‚P9Ä>¡z‘¾­ T'òì„êEìSªéÛ ÂÈL¨ ÒÛÛ Àu×]ÇgœÁùçŸÏúõëèêê`°µµµòöõgçÎb¼BÅèèè`óæÍ•nƨÎ6áðísóæÍtuuUúð„#ÞÞ^:::Ø»wo¥›2&ÇckŸ{÷£cD„ñ ŸÏóàƒ²ÿþJ7eÔHßV˜jHßVú¶Bu¢û¶;wî¬tSÆäX@ú¶ÂÔAú¶åõmõ¶a"éêê—¾í„ *ù|ž††V­ZÅ#<š5khii¡££ƒ;v X¾œ¦]»vÉŸN¡bL•?ÃÙ&pØö¹yóf6nÜXéÃŽ@vìØ1e•ñ°OùÓ)T’|>OWWûöí«tSÆäX¤o+L%¤o;<Ò·*…îÛîÚµ«ÒM5Ò·¦Ò·Ý·l}Ao6nÜ8ù•¥K—–äákhhàòË/ÃÆúSÎÃpáÂ…477OäaBHss3\pA¥›1j†³Mà°íó‚ .¨ú\ŠÂÔ¤®®ŽææfæÍ›W馌šñ°ÏyóæÑÜÜ\õùb…©ICC±XŒ¹sçVº)£Fú¶ÂTCú¶Ã#}[¡Rè¾mµ×"(éÛ S éÛîÛV{ajÒÔÔ4.}Û Pé"]SS(£íoˆ;v샄 `8Û±OA¨$bŸ‚P½HßVªyv Bõ"ö)Õ‹ôm¡<&TPéèè`õêÕaÞ¼ÞÞ^6lØ@]] a+¨gù|žË/¿¼ÒçH¦<ÃÙ& ö)DìSªéÛ Bu"ÏNA¨^Ä>¡z‘¾­ ”Ç1¹³¦¦&ºººX±buuulܸ‘¦¦¦0lº¹¹™Õ«W³lÙ26nÜHsssÉHAƇ‘lÄ>¡Rˆ} Bõ"}[A¨NäÙ)Ջا T/Ò·„ò˜PAàú믧««+ ‹††555ÑÐÐ@>Ÿ0O„ñe8Û±OA¨$bŸ‚P½HßVªyv Bõ"ö)Õ‹ômad&\P•wo(Ä ¡r g› ö)•DìSªéÛ Bu"ÏNA¨^Ä>¡z‘¾­ Ï„ÖPAAAAAA˜Œˆ "‚ ‚ ‚ ‚ ‚ ‚0"¨‚ ‚ ‚ ‚ ‚ ‚ Œ€*‚ ‚ ‚ ‚ ‚ ‚ LJ;Žz¥Ó¥Ë46N\›Ž©ôIAAAAAarJio|ža($Ô˶UtI6 ±˜šïºH¨w×UË›¦úlšjYËRÛô}µŽþ>H„Š ‚ ‚ ‚ ‚ ‚ CM«¥…Ž\N #®[\FG”D—ÍåT‰ã@2©Þõ:–UÜv.§½íXL-·d‰š–N+&WëärE&Ú¾\æÏ‡ï}ïïxæ™Ycz$BEAAAAA„!I§¡­­eâºEñÃóÔw=/WBI.§ÞGm#—SËzžŠBI&Õò©”Ú–a¨Ïɤúlšj¿z»¶­æëˆÑbÛÅ}¥Ój=ÃP˼ìe{Çô<ˆ "‚ ‚ ‚ ‚ ‚ S:«œå £(Hh´€âyj;¶ JÀТŠN¿å8J0Ñ©½R)µŒã¨uƒ É¢SyiE‹%zZ,VŒTI¥Šûvœ¢€bYJÄbÄKg'|ï{÷KÆô<Š "‚ ‚ ‚ ‚ ‚ “Ï+­%Jt°m%L,Y}}ÃoC‹&Q!C“É(D¿´€âyÐÚZF´È‘L*Q%“)n£¾^Mó}õ®-àèe£ûÕŸ£ÓúO÷}µD¢(ÄXÜyçVDPAAAAA„#æ*J}=tw£? C‰#:JIJЅá£d³ê=•*Ö@Ñë¦ÓJäpœb­”¶¶bíyª=ɤРÉdŠõN¢$ê%•RïApøçÃ4U»Ê‰À-"¨‚ ‚ ‚ ‚ ‚ Â$!™„öv% D ÁçrêÝuá ¶R¬wM¹¥…Žx¼U#,3a™¡R…F1…ãH¥J£Iô±½Ã‚½J çòÁ7Õwˆd#U8ÎxáêsщƸêé]|cÚA^zÙ\܇Yàׂq4ø=`ŸZXØ…À†ÏîÝËݧ͠©gÆVøßÓN㌇ÓvU,åW>Ÿçšk®aãÆá´õë׳bÅ Ö®]ËŠ+X¿~}¥š'G,ƒÙ&ˆ} B5 ö)Õ‹ôm¡:‘g§ T/bŸ‚P½LÖ¾mT I£„‘€bĉ|”xà¡D‘B0fá=‹Ú ëkAF£o–øj^¸0ÉBOÖ:s`Wš’ðÉ,ܘƒû s]¸6 ›MxÒ‡})x>› •¦ëb vpl+L3 iB“v'|'W›ªh¼i‹Ä÷/þ>Rj®D¡Ýú¼˜¦úܵLá˜m”ˆ+œ›%…ó›,|îO”æMËAcá÷ȶÝL|'¨K¼ÜczñúöÀÝàÌî£ûHoo3loÚNòaØuë.þòêi¬¾~/ÿ²ê%V]{-µþó˜^g‹P¹îºëLkiiaÍš5444ÐÕÕÅŠ+hhh¨ZÅS¦"ƒÙ&ˆ} B5 ö)Õ‹ôm¡:‘g§ T/bŸ‚P½LÖ¾­®qâF¾»…]Œ^ (Q¡ÄB9òM”3ßFc?Ë‚«-µœ46*!ã×9Xƒ¤¾§vVkÂó>ø…‚,'°#»³p‚«"T¦Û°Õ…Sc*ÍÖëlxÒƒ{²ðVN1 ×‚Ë-ø‹ߌŠ%&¼&5úódöŸà.ª<²PÂ’fIa–[x7 çP¯f D—î´8`î´-,Ltà/~œ½3§ñ×?d¹åO±ñò³hxl7ÉÓå’?ù\¼Ý ÿÕýë/²pë Üó*8õÑÃq1î{ù ľ3wù+È&jؾ~;«^1àé^rï¿>ÕǬÏYœ:gï{ünzßÿþ1½Î*¡ÒÒÒÂÒ¥KY¶lY8­££ƒÚÚZTF³¥K—²téR:::†ÝÖÎ;G\FÆ‹ŽŽ6oÞ\éfŒƒÙ¦>ÎñÏÍ›7ÓÕÕUéÃŽ@z{{éèè`ïÞ½•nʘ1–ö¹wï^:::Èçó•>,á$ŸÏóàƒ²ÿþJ7e̾­0U¾­ôm…êD÷mwîÜY馌Ò·¦ Ò·-¯oÛÛÛ;êv•õPÀ£4"H¼ÂçvŠú޼0H…4XD>‰\Ö*U—e©ˆŽç •î}Î-ˆ?jUi¸0àÊ4ðh#œS¢ÉRêPc§-øtBmûGÌþ=¶ ÿ7iÚÛGyÎ|Ÿx<^ÞÉÕªˆ‹R”tN´ld¹8tûJ`iû´å ¶[‰&¹ÇÕùMÛvÄ/lÊ߸ÿx/Á5·ì#ý0ƒk¿ý¼kýGÉ<ÕǦùÇóÛËbÍ{¹2u'?½ÜæÚ+vóÌïžaÚ±eû¢ÿà^¸£¹—?¾ò8ÎÞøwÄþwïº=ÍÖn㯠§ñ£Õ¿fÅOÿc_þ}xÊåÅÚòÌ¿àÔ`/Í;êë/Ê„ *]]]lذD"1`zE³¶¶vÄâ®]»äO§P1¦ÒŸÎ¡lSÏ;ûܼyó€ðmA˜vìØ1¥•±¶OùÓ)T’|>OWWûöí«tSÆéÛ S éÛJßV¨Ntßv×®]•nʘ }[a*!}Ûòú¶;vìuÛr#O†ÂE‰!…L”xbRUttFªðÒÑÙ¬z´ùª@|ÀÆ‚ÐðgGÍH§áh`1J`I$Ô{6«ÛR"‹iÂ\®‰©ùHÀGc𡘚–ŠśƂPcÛª­#dí*‹Þ'{ùê±_ ³kÑÏ/rb\””D‰,ÅPŸç²# fàCìdH<íß‚¶z¸õËð¦ovS¿÷ +víç_ZîæÛWþ”wüd»wÏ䛋’ÊÂiOqýÿ¹‰{Î{'÷}y's¶¾ƒ—f7ó£/=†a4²xßCœ~ñ3ãÛ?åÀ¾/ðɯ|ˆcŒc¸ôkÇ1ëÕg³ý¤£°Ý±©åJžÅ4n¶Ïá‚ßÝÍŒ×Áµ1¦OûÓÖþ~íØW|™PA¥··—Õ«W³fÍšÇ3¬rBÆ.\HssóD† „477sÁTº£f8Û„Ã·Ï .¸€¦¦¦JžpRWWGss3óæÍ«tSFÍxØç¼yóhnnG ÂDÒÐÐ@,cîªÒ·¦Ò·éÛ •B÷m.\8úUéÛ S éÛîÛŽEZ0oiéÈç\a™z¿´ŠMQ(ÑQ)ž§ÒyE‰ÅÔ+™T¢ˆT4zZ.§"Wb±byÃPÑ$V!e–ï)‘%“z,:;‹Ñ0ýkž€ª‹r(ÌŸ?ß÷‹''¸ç÷àgÕô\:Çó?~žü]yVÿÝjöÌÚC Jç?«/¬ïó ''™Vó²„a'{¹—w}M›6©éøðÇ#ÿÙ¼‹¯üü+àÁåÛÉ¿ï¬Zw7O¼âŸy÷wžâ¸_>Ç{~ói3a»1ÔÓ|ýŽ.ûÏ‹Y°íçðc—Ú—qâì»à,àõœåÀó.¼Óà±ï~ê|h0!—ã˜Ä»™÷Ì'8ê“iZ?Ÿ ýÿ}ä®^¬{ïUÇfY‹ñòëÈÎeÿ<êk¯?*¨är9–.]Ž®Ø±c]]]tuuQ[[;`y] Ãp¶ ˆ} Bû„êEú¶‚PȳSª±OA¨^&CßÖG*×JH‰>»À÷ꕈ¢E• P¨h-¨8Nq»¹\ñå”Û†T!—ΚåûJ(1 õ2Mµ¼U,K-ošÅÂð™LQh)‡ Š¢G¿é^¡qAðÀ̘¶cŽãà'}ðàઃÜ×ýÜó…{xøóé÷}š¹ÿ2—ïÝÉôŸNgÁ“ ØÿÎýô¾»?î³÷«{Á„矞MwlR;zÄ€S=HÁÁmñL{‘ý[÷³ûø³8uýAî8óz:RìûÓõ<üðÃìþËwˆ¾íÓ^ø)ç¦Ïüà ‚ÿkÑ;û^οÿuò¯HcÜŸeÆIÝ«^¥r¤-ðàÚ‚õU®KÀ/SúÀ9몫ÔIlkS'8Vˆ:I¥ Ã|©“Ô¦M¥'¬µuܮà /JßÛÛËÚµkex·Ýv;vì ¡¡õë×—,»cÇŽª*lTÍd³YR©1¨J$± e›:/¦Ø§ T±OA¨^¤o+Õ‰<;¡zû„꥚û¶Oü׋Üyùt0K‹ ë—J•å™)LûX¬TQ@шìÐïɤòÓû¾Z&›U"Lª°®ëÅ-¦hÅ÷‹â‰öóÛv±Ý‡"¦€òñÚ¶mÛlþùf ßàØÅÇòóÍ?gÍgÖð‹÷ÿB¥h]þm>;vì ?=Ï#Ÿ„^£—·¯`ÏÕ{ØøÛ,hYÀ1ÇÃÂ] 9ëÞ³xñÒYx×B¶ÎÙŠ¹ËdûÛ™õÅYì»ýFf\TÏγÿ›ý#Ç>ã±ÿ¨[ùÕe³oƱ<ãvqÚ½›8gØrÂ%,>áÍÌ}öQ~·g9÷½´·ÝÂY,ÂÏŸ]³ø=ïà7û÷sÔ‡ŸÀXaÃõ6$ŸW¹ÒÎ&Ô’H¨—]8ñýOÖ`¡<±ARxy^éIP»­–mlÓkqB•þé V®\ɪU«Â°L­€644ÐÕÕE>ŸçòË/ŸÈ&–…çyX‡j £À÷}êëëééét~.—#NcÛö„¶K˜:Œd› “Æ>aª!ö)ÕËTéÛ ÂTCž‚P½ˆ} BõRí}Ûü÷÷1íe{9Å,M¯æ Ä]/¥¾0ÝvÅýžL*¡Ä²ŠBŠ)XâºÊ·E1Ôò†QŒ@±m50ŸÿhоÝÞ;{¹í‡·ñ†?½MÓ6qb݉ü¹ïÏ<8ïAæÞ;—öý/Ón=Ÿ“z^Ïüø|~ñ [/ÙÊ|>,ƒÅ‹a†Ë‹/»'_û!æÿu>ûŸ¿”.Jrõ;®æà†7Q³½ ,è™×ί§{ÄîñèZq,æ­µÜÿÉ«ÙsÊ)$,‹ƒ/­gÏQ³8xå»Yôͯбì$ÎØ<7¶}€7z<4^o©2,ÁV8ç–·ú0-£ –Áà'LŸðþ !’  »{ˆ“ ÷¼ñ–°dL£ PŽææfV¯^ͲeËØ¸q#ÍÍ̓æÔ¬$¾ï“N§iooŸ}A@:¿›¦‰ïûø¾O.—£­­ ÇqÈd2466’H$ÈŒµ% “Ã>áHEìSª±MA¨^Ä>¡zû„ê¤Ò¶Ù××Çî£ÆCeŽÒ%P A&˜(C×G å§×iºLSMëìTÁZ`5Ïu‹Ù¤\·Xh^?Æ@-`( ,TA 5ÕJc²Ó4yðê9çœsxéÑ—¨¿°žgì¤fk 3öÌàèÞ£©ùF Ï.}–³öô²à÷G±}þfÿ~6Ì3fs¡Ù@Öeúóë8mÉN8ÅdÎÜs¸ú¦«!€i;ø»ƒ—pã•û9­n!ß^°€-ïxo~ù4‚¿ü…S×®eEw7$LæX$<ðÂßXñÀ¹ç Ù[¥á;:œà§‘V‰ÌJ\pçl‹Oâ•þ¬[·®ä{SS äóyêêêª.¤Ó÷}\×ÅÕÒäÐØØH&“)‰,ñ<ÏóÈ*&e2<ÏÃ÷} à ãyfÁj}ß'‘Hàºn˜KOFCÛ„ê·OA8Rû„êe²õmáHAž‚P½ˆ} BõRm}Û¾¾>6/;6ü 4•ê«×/¦ðrœ¢0bYJøH§•Ï?VbÉž={H¥f‡âK,V¬}âyê{„õͱ?TvüuO½ç)Îyè‚ ÀˆÐ»7îfÉ—–pï}÷rÒΓøÄyŸà˜ûŽá`íAÎ}þ\î9p§ÔœÂÂ] !§dOáä'Ãy÷óbþ6æ}цŸ»`9h? ÛlUÀý-ÀKL|C„1 Øð¥w½ƒS¿ò¾ô3_÷:«©Áò< ÃÀøÄ'`ÉU‹$Räœï_}Ðj’iªÚ&šr£J&ˆY{fù6«*B¨ê‡e:31Åu]r¹žçáºn(¨èô^‰D€X,FÄãq‚ ‘HÐÙÙIccc¸®a´··ÓØØX²]ÄȈƮ ÂaRÍö)G:bŸ‚Pˆm Bõ"ö)Ջا T'e›YTJÔ5ÿR~º K1Q Ja·ðþ,ü~ö^`±˜Òü‚ÈbÛ0sæfg1†¡Ä‘SOÝL:}00%—S¢ (½@o¯,ÜBûE¯|wÍwy÷3ïî~ànή9›…ÿ½Çîy ›‡g=Lïïz™±pÞts_8—™›grAêµÖ`™m §˜LŸá©—|ðHR(À5N±ñº@ sš™&gíÞ ííL+d? çk«W2ÉxäUpÇé6§Uú &žç…E´P1ÉdrØíd³Y²Ù,¦i’J¥JÒzår9Z[[éì줵µ•Ö‚¨E“îîîð·,‹\.7 nJ<§¾¾>Ü®~yžGn95á2T´‹ã88eßEAAAAŽ,$ƒˆ >ÚëZ2l¼i“zOÂ÷äýÙ¢¾²À‡[oÝäpxà]%[Ü¿+ "NfÍÚx%…è£&ÛÞNAxÉbšjF4#‚ëg_ÿÙâL]ÔżÂÁ̇w¿ðnô.`ß5û8ñS'rzïéôµõ±óŒì|ûýlß¾…»bàb¿ÅdÎGçÀ¼4ÌpTj°u<•S*“åÀ½<æA2€ñ$Tãu¡—DB¥ÛÒŸ{zJ¿ÛvIJI„É(+1¯gÞ˜o³ê"Tª]¿¤­­d2Š+z^.— SsiQ$ºn6›¥µµÏóp˲Èd2AÀüùóÃm˜¦9@$±,‹î~vLÓ ÷«ñ<˲ˆÅb¡ˆAhè–e…‘/ n®ë’L&1 ƒ 0M“D"A2™¤»»;L-*²&›ÍÉdÓ4Ãó=Oƒ?Ã0DÊè:1zžDÒ£Áq|ß'U‰¼ŒG ªo0R0§Oq‰™°á¶åG¦Ù€Q˜Ná³~· /c˜ýùÀßÎ?¿Ò§IAA„#„ ÂtñétšÎÎÎþAÊ#ê?p]¾b3kÅŽ2澃­.´ZШª&`JÉp]˜>½šš³`Á[è踞3ÎÎòà/yˆÙ³ŸÅ¶‹éÁ¢¦ª]›Ú‡Åó<ž~àižü×'Á„üô<Ÿþݧ#E96âªê5ó§›Ù3ósÌÞ¸†‹¹˜½ó–ñë ¯gÅ‹+ØÕÙÀE»Q-ÿëü{+³sŸ…+€9>¤U£r90 â‰e©‚0¹,5KE‘Á„¨P2"OÊå‚;/ ƒŽ1Ýæ!E¨ttt°~ýúð{WW+W®dåÊ•´´´TúüŒ :C 00}–Nߥ—7M³$5˜ã8áü\.G*• Ã0ÂBóz?å‹Åhkk+0,Ë ʆaJ¥hoo§³³³D´Ñ)Ä’É$®ëÒÞÞ.kÛvؽŒn{2™¤µµ•öövº»»imm%²Ù,õõõ,Y²dÐè\.FáhQÉqÃuu͘ÁH§Ó$“IæÏŸOccã€Ôf¾ï‡mÖíŽ<\×6zìHA ‡‚zæë³çR¬c–æiT ±0­%\Ôæ7F^KP!ºNá»Q؇Ùµ#ûÔ}V ³ðÞiW¬ðÒëéöÕÚCa_K /=F$ÌØ‘"‚ ‚ ‚0z´hýÿÄãñÐ÷õ ‚P>Ÿ£þãë4•šËØó çµÃ¥õŸÿq¯4CÕþýû9»ælŽ9æ>Î3_ï̘ñ3^ùÊûX¼øF ˜9ó+,^| ±˜ŠFÑÁ%m^‚…w/T< 7½í&Ü´ËÇ·}œç¿ño#;޽ƒÏó9žzYÛ»xû¬·³ù¬ÍìÜv?ç„ p*ªÎ‰ãÀfO…Îè{@,靖MtžÀÖ“·Žù6ËŽP¹îºëX¿~=«V­ ŸÏsÍ5×°lÙ2–.]ʆ Èçó¬Y³¦ÒçiL‰Çãôõõ•*[/øÙl6Œ¾pÏóˆÅb¡ ¢£W,Ë ËÇú©€,Y²$ün—Y¼Ç0ŒA—ÕK¦ŸÙÖÖ ZÜ0 £$­˜¦±±1l§nw6›¥­­­d9}\©T ÏóH&“ضM"‘ —Ëáû~¸ Ïóhll Û¨·çû~Iª45™Lß÷ÃmZ–E}}}I4Œ>.-N™¦I:&“É”D+är9b±X‰(6TT0yH§Ó¡MN–('Ýí>ÜÖ(Q!Y؆.ÄVxf‡QúsëûrQ”,J´HS1ôò1Ô3ݣ⦠×þÆÂ: H Ù¢·9Tœ‘™ŸFu®r…ýÄ ûL–ûÁƒæAAAP,Y²„T*E"‘ý:3Hggg(¦$‰ÿB<?k_DÔ¿$Âà虤ÁÁöíÛ™ù•.^ù¿Oñd®Ž'}ød rçŠm«W}ý´r_<õq-z‰lp—°™d2Ža|á rûí÷ðw7ÏS+÷7Ç{jïáØï˾[öab2ýþéáÈÍÀ XùâJfìšÁ¼¾yÜõÌ]œúçS9…¿g×Wï‚“áÀó8:y4˜pËé·pî=çò¹o}Žì$³ö?H÷;ºÙþãŸðØ1syÜw¸êgWÑÌI¼ÄÅFÛ}Õ¨D²Yõ^(üâf{;ärüìé§¹Š"Kϲ\·lÿòTgïì½c¾Í²•®®.n»í6n¾ùf–.] À† ¨­­eÍš5ÔÔÔÐÔÔ„mÛäóù)Q8,‚Ñ"†aàß¹öZ¾³d vA@ ‚€¶¶¶P4H¥R466â8N(X¸®‹çyƒF †1fS¶k$|ß§½½}Ðy–e…©¿2™ õõõär¹PÌjùX,†iš%‚I:SyÅb1Ç!‘H {¢Q::4¶­­ ÇqÈf³aÇE‹ÅÂhv¬µµ5t¦†ïûÄãñPPI&“áobÛv˜º ”ø;‚ÂݦŽãJ¥BÑ®ÒDÅ]­¿ðD9þõUgE>÷ß–N«•£˜+(L뤘«•ÁÑQ$±Âº©Âþâ‘}´¦ ‡=Äç¡HQŒ>ŒÂ>#çØB‰Cí£Ø® ‚ ‚ G&Ú/¡}Ú'ašf˜‘Dû+ô`OP¾X,Vâ·å[êîîãj_Dÿ”î‚  Àÿs-GÿùDî»ï$\˜ð¨§2WéLX:RÅöîý=µµ¯Æï58Н)?dþºøÈåþ‹O~òC¥õ¡ve³wöÞ‰q½Aýõ,½”ü“yåX±a÷ÆÝL;Ëj–±ÿ~6ýi=õ=̼w ‹¶Îawz77vpék.eõ3«¹v÷µ˜ “ô«Ò|ðãç¢éu,|àÛ…Ü{Ú‡Øñ­óDSwx"ÇøY.ŽïâÉÞ^n·mb–Åý;wò\(Ÿ’i’Èd𠞘?Ÿe³œüÑ–øjuùíûÔY•Ú¢`A—u,…¾ˆÀ)KP¹í¶ÛhhhÅPé¿–/_NMM uuuÔÕÕMA%›Í†a™žç±eß>nY¼˜ÝÀ%[·rwk+~2I*•¶mLÓ #3,Ë ûÑz(®ëŽû8V‘–e…J¦6À¡˜þëµµµ…:úx}ßDz,âñxI}™þmO§Ó˜¦žG¾«¿ªšH$ˆ- õ?v-´h!Ë÷ý°ÎþmÚÚÚð}Ÿ%K–„Ç‹ÅÂv{ž‡ëº$‰±j²DAL%ÇTôr'Œ^0L“,…]Ø>]oÌ@¥¹rQá§9ŠâG4‚”’E Nd=»0MG¡X(Æ*lÓ"2Z£ÀpG%¦è¶Ób ÿHÑ]ã…Ii¤L´.‹ ‚ ‚ B¹¸®K<'‹…c£âI2™$—dîЃ9}ßÔסëÒêÁªÚ‡!JA(“<ý ìvŸ<‡šYÛYœ€—¸Èù*ˆÃ÷áâ—ïâU5»X´øE?t#¯½™ 6Í>YðSûðíÄå|íánb±Xè÷½ñšù‡þ茶ϭ?¸•ÏŸùy~³ì7œ¹ñL^zùK왵\˜½w6/ÿÛËáv¸íÌÛ¸zÙÕ<ðôì™1‹Ž+;8öëÇbX./ýâµ\øÅ ÉÞ›å÷náÇ~ g¿ïlz9›ã×®å‚x/¤²äßúVê>ÿy¶}üãÜú±ñâOpêóÏ“(ø#ÍK/Å)dÒY²Ù¬šW(Ù ï%¹\.ô=ër :CÑphß§eYašBí7 ‚ÇqèééÕϨï{Ùl6Ÿõ€èñ¾ÞýÖ»YÂ’Ño(BÙ)¿ú‹$455•LÓâÊd'îìíÅ0 v>õyÏ㮋.âRÓd&ð©àš}û¸ìöÛ‰M›:òµß0Œ£´˜0Y­ôq€/tM–Áˆ¦ýj¾Þfô½?™L&LݤçZàè¿N´€½.j?ÔqhQ¦³³3W\×-iO__A„¨h¤KX–FßD§}ôÑ444Tú'›Òè”sQAÅ÷}ÙV[Ë7Þ Û}%d<êc4x(DçóÔé¶<”ÀáöiÚÐY¶µ°œW˜fÚJôHSŒ¬Ð¢ËPiµõq££9tÄKŽ©Åýu±zAAA„CA§9× @{{{IZu=T£S˜ëÈ–þèu à “Éà8™L&ÌÄ‘Ëå†t*à@·=—¹/m`Ö¬=¼àÁãä%¦¼ñÕ·³ìáÅLÙ‰,~h12¼îä™õf0kV(GŽÇÇò‰¶OÀ*øàãdË5[8pÏžØþû°Ÿþßyù¾—síw®Ön_˪?®RÎ Yù'~Ží°íñm¼þ´×S·¤Žm?=ÈgºVó¡ž ø?Î×ùõ¬ŸðòW¯%ÕârÂ1ÇpÏ•W’J¥p]—c÷íS Pwé¥ðÿ DÛ]»¸tÿ~Ú3’Q#Y¢ý£ét:ø­»®‹ïûtvvbFIdŠUti…è6umí¶¶6âñ8žçÑÞÞ^颫—+|hQ&:0?‡÷IÇq°,+,71Ü=0’…€†Ã^.¹õ¶^>¶uTÊTjkk¹í¶ÛÂï6l(q"÷ööÒÕÕEmmí˜6p"‚ Lq…\ü_ü"ÿú×Éwx"=/{_ž9S96m›¯oÞÌ÷/. ‹Å†Lô8RÉPár)7mÕHû‰W9Q/Ã]Ôz}½ÌPçȲ,,Ë ‹· Ö–þ¸…œ€ÃµQ‹':Ü-›ÍZF§%ÓËFÓ–és‹ÅJÒ•AÀ—¾ô¥²Î¹pøè”yQn|è!Nüö·áÒKù J(H§}ë[äÞõ.æÍ›G#ê™™¢'ЋSb1xêÞ°ž3©;©Žä%GÑcô0ýéÌzí¬bªÝË$tÖœÞ{:Ûð7N÷é?6X²} gœx†Zæ. g|ù~Ypg—C®;ó:¾•þGÝsW&¯äÍñ7ÿñÍÿ䚘Yû¾Ëæ³ÎbÙSOq÷e—1cölÎ:ûl2©8±DB5º.PõR >Ƕlám±F¡d ¬‘­]ê ‹…”4¶m‡ß£åú—‰ˆFŸh¿¶Îè£Ñâ ¨ÖíííîyÑÁëétºd?:2O×›Êf³aô_2™$—Ë…©µ£—s]7ˆFÉ2çá9ð–±»>§•³ÐòåËÉçó\wÝulذ\.GCCC‘ÒÛÛKKK uuu%iÁ& Z9‹£Fˆ·õôpî¾@¸è®»¸{áBöíÛWâ}ÇâÅôÉI-³m{ØTQÑôU‡‹%†B?¤G»ŸþÇ5Ü>£yDûwHÛ–Ž‰r…žþ*ª=2œ°Sn§Å0 Ž?þø1;—ÂàD@×u9ù–[øÑܹ\tâ‰tÝÓ`±s'm­­$ãqÚQ"‹[Æ>\TÊÌ%¨z#õ‘ïÙ«%zD¯£°ßèwÚ«ZÑiÄAAAŽt´OH;)-Ëud(,Ë*É€Q:«‰eYáót:M2™$›Íñxœd2YéS#‚‹ò¹D €-[¶(§pð7'0ó”Ì›×à #U- Î}èÇ<¾ù /ôÀ3Ìbæog2kÏ,^yÌ+Uîtí°ñQ#mµC'.}ý[÷óæ¿¾™9WÌá­»ÞÊô˧3ýòéaöšMñ›ÿVÌÍ\ö÷—) Poº½½¾în.ÏçyvéRN<ñDvíÚÅŽ¦&έ©)y‰Öl‰ÒÖ…ú%oûò—ÃÏ# š×5OÚÚچ͈¤ï3ý…½ M&“t;¶mã8N(Þ¸®¦DÔ™~tô‹çy%iA‰-Ú'®k`···‡âM.— Åí¯Ö‚R©­­­är9C±&³dÉ’Ò:8Cð«¿ÿ»ÎÜ5—jHY*uuuÜtÓM¬^½šõë×ÓÐÐ@ss3 R­\¹’ºº:Ö¬Y3¦›à‡uuÌyà<ÿ<ìÙÃÇŽ:Š$ÐýðÃÜ ,¸ÿ~X¶¬d]íÀ-÷±©Ã±CçÝœ¨+c¹ŸÁŒ-*ØDÓs´ßC3¢…ì‡b°ó"L\×åÒw¾“³wïfÓÒ¥¼úÑGyäïäË‘Žºù§:*¼¡úžG²†Ì”èÖ‰u×W¨¾r”¸Åðý1û}®æÄ~6믂 ‚ ‚ ©èáÚ0˜Óq(t ÝÃñ±èT<Ѻ :¹]¨ ³rÂTg0/ÝΧŽáè—^†u?üÇ/;–“~ýK¶l¹-Âóà4.â³oäÜíŸdÇéÀ[áXŽå¨ß¢D•ó\;bêý­óÞÊ/ýë.‹yï™§%º ¯ ¤àÏ?ÙÆ©/Ä3<^xàŸyűÏÑšL*?P6K¢½Lãþë>ùI¾˜N3ýäox«?óhl}OÉåŠ7€ór3•s¿ŠÅb%¾Ù(åÔˆŽFº€;´0ÇI$%µõ²úþ5\º0]bBß÷–,YfŠ›eY¤R)²Ù,K–,!“ÉH$”BÁ'‹á8¯þÑ«™V;mL#TÊ®¡²téÒ0º!ʲeËX·nݤ­!á÷Ÿq;_ÿz>˜7ßÌé…âåî’%uÛm*´éÚkKÖÕõReîk8¡`¢Â8'j?‡›º¬~À± äP:GBeÉårär9,ËâWÿ8ï|òI~þö·ó‡în¼öÁ+€|fõj>³z5¹\. ½Ž¡"MtaöÅ"òúÙ:Tuƒbš®¡3‘ˆÑPh­vDPAAáH'›ÍŽ˜Md8K'~¨ø¾¦ˆ·m›\aÔ»þ,‚ŠpDÀ®ütf<¼¶Ãé—œLoo/ûöݦMÁ¢Eœpô œzàTì=a[ÓÔ(ÙBj‘ÙÎìbQZ=’V¦-8D?õqNu*ìSûä˜/¾]ÙæmÏ=Çé½½4Ç9‹üïóœô™ÏÀë^§Bd ¶ Ãà’ïŸã.½^õ*V›¦š‹©• €Ã¼ÏŒ–þÙŒ†«E=ÑûN16X q®=Ífqg@ºÄ¡¶kšæ Ù—´¯¸¿Ï8›-mÒ~DÛ¶©¯¯W™Ž 8ã´3Æôœ–•òk8jjj&­˜-÷ÞKÍÌŒk¯åè›oTý*š!F1ŸPd´Ñ/ã=3ÛLPÆÏóX½f ±ÖVfíÙâŸÿ|È(+=ˆ@‹ÅÂÔsÕ)¼¨Á:%X†á…ÑVÂ(ÓA‰Ö#±GX¶H15ë§‚ ‚ ‚ ŒD6›¥±±ß÷Ôp­Q?T4m¹Ù=ÚZ»‚0ˆ–U¨ÈÂ?|‘Y¯z‘ù…éºôľ}ûxÅn `Ƨf(GG%šèô\^déÂ+…2{él/[¬ÖI¶½wùò°-—|ô£x¦ÉkÿîﰀΙËï|§SLS¥ñJ§¡a¨é >kÁÁ0`˜âë…Nÿ‡_"“ÉŒ(Ș¦I<'ÚÚÚÊptºÅÃõázžG.—£½½L&Cgg'íííœþ¡ÓÙû²½czËTt ••+W²zõjºººÆ´!M5býösÏåà¯~ÅÅO?Í?þñA‹‰ š¤G¥Ë£­m$õПÈô]Rnbñ}ŸÏ¼öµ¤)D\S„J6¿ÔpM±ÖŠ.Ê^.ý·ÝŸEE?»«‰ÑAAáHD‹(–eÑØØ¦Â©ºŽ¬FÿßÕï‰D‚\4M xÀ1/½Ä¶G_bÆÌ™üL%l‚“öœÄôîé˜q gÕîæ’[/Qb µíSŽ‘ézZÎùþ9œ¶ö4h‹¬ ÔÜ~;7^s ®ëòú׿žW=ò³÷îeúÎ<ø²—Qó€çA*¥“2êxJ„©0Q¿¦çyãvÿÓ)º2™Ì¸–·ˆúžƒ (‰8Ïý–-¨¬\¹’ŽŽ–.]J>Ÿçšk®!ŸÏ[ÃÆ›omÚÄ[ö3fnÞÌ{.ºPU•Í4Ías½Y0 8ýᢩÂD *#76;ttŠ*Ã’%KøÈÞ½¸ííá ‚×îÙ3¬ bQ|‡‰ÔAAA8Ñ)©TŠ *¢‰Ö(hŒbO$8ŽC:Æ÷}©+Li¢^Äã_õ,Þ(Âèã^<ŽÓ{NÇØ/;z6/¼õ…b>w…¢Ýº1”ó§'²á`‚oúÜóo&z*Êå”_¼x1Kêëñ}Ÿ%k×âš&÷¾å-`Yܲx1Øv1BE¿ORÆËÏiYÖ„—\O¨?e *äóyn¾ùfš››¹ù曩­­eýúõzbÆ’žž¶~ík|äÆCµL«gQLÓ ‹á ÆX *:oæx3‘ÂÍxªåîg´$Q&?‘`ý¶m¼õÚkiC=¯<ýt:;;‡-ÌÕÿ¶9ÔTG ‚ ‚ ‚ G¾ïcY†aÐÓÓSÑèü?k´&atwwãº.õõõ’Š\˜’h/e•ž^èìcúé§sÊõû‹ Ά“·žÌ NÀz~þ¾Y¼÷O ‹—Ò”!?ór]—cþíßxìž{Ø»w/®ëÒØØÈ§¯ºŠ½Ï>Ë{ö3æuw³yófþôêWãEë…DÅ‚LF‰,„õÙA0a~è²#TÂ\uË#ùä•®®.:::M–ÏçCgÊö†ïûò0Ÿ(áf"ÐQ0÷¡ $•ËT9Wå0œmÂÄØçªÇǰ,¶œ|2×\r …:b†qÈ7FÃ0ípêOA˜LTƒ} ‚08Õзa òì„ê¥Rö©•ja8_T”öövR©žçñxœt:]ÆáЙè¾m4îê—ÌOÃÑ?ßÍ‹ß:ž=·+_´ðýäÑú'žàƒú³ººàª«À÷y¬P#eª”jðÆÛßÿþ1û}'ª– Œ•´OA†§ú¶‚ Dž‚P½TÒ>³ÙlUúÊðªâêtõ±X,dšN§ ‚ ,qF†¢Ò}[ø; Ž5`û#ÿ ÿüv^5Ù—ÀÂÂøÓtîzJDɡҚ"^x!üñ<»w/§þå/lO&9榛 ™„ÖVho×… À0 r¹\Xƒi2cÛv8 "SdýS~UU €7²råÊðµaÃ6lØP2måÊ•Ãn#ŸÏÓÔÔ¦Ó·cÇ:::¨­­¥¡¡€¥K—²téR:::†ÝæÎ;G\FãõÀ¿ÏË) (@/Ã1X4LGG›7o®tÓFÍp¶©ópìsóæÍC†pkôyýÊîÝ<ýÀ,={ÌFÕè…D2yôööÒÑÑÁÞ½{+Ý”Q3ö¹wï^Iq"TŒ|>σ>ÈþýûG¿±*8–Jöma¬‘¾íèû¶‚0è¾íÎ;+Ý”QS©¾m}}=Ùlv‹$5ÑÚ¿¦i†õ€Ç™£Í'#Ò·-¯oÛÛÛ[V¶xê5mÚ—Àƒí>Ê¡»è…ß.ú-O­x ÎC *#eÌËå `½wÞÉî¯|€_ÿä'üöª«˜ýº×±ï꫹뢋¸oùrµ¬¶%Û†LÓ4Éf³´··º¬@µ1üâ®ëâ8Π¾¿®®®qéÛ–¡R[[˲eËJ¦Žú¸|ùr–/_Noo/7n¤££ƒ¥K—ÒÐÐÀÚµkl³¶¶vDgÏ®]»èèè z8 ¹};Îw¿ËV­ó“9Z\×2†9äƒÕ¸™*:‡³MP7 Ã±ÏÍ›7³qãÆp¤Ñ`xžÇÝ òƒ}ûxÿïÏ7[[Ç츴Ò>F‡†îðMAe<ìSÿ锑¸B%Èçótuu•Ôæ›¬Tºo+cômGß·„ñ@÷mwíÚU馌šJômõ¨åžžžJþ¨imm0Ѳ,ŒBJû©T3w² }Ûòú¶uuue#ãf`1Çó{T톅`mƒWô½‚íÁØDiñ•w]|1—þá… ú``Y¸Ù,>õÇ~ä#¼~ñb¾|üñ|ÿø{÷rÉW\r ¤Ó0ˆcÞ¶m±­*E ʃ æ7n¬œ ²téRÖ­[7f;Íçó¬]»–|>·×£¢”ãäY¸p!ÍÍÍÃ.“EE€üÇ}÷1¯§§ê8˲胚ÕÂDFxžWV·±8žþ¿Oss3---v¬ãÍ`¶ ‡oŸ\pÁÈù4 ƒ/¦iíZÞôŠWŒéñ†A"‘˜°úDBõPWWGssó”E:–ö9oÞ¼Ÿ‚0^h‡ÉTŠÂ˜è¾­ ŒÒ·ž²ú¶‚0Hßvt}[&k*0˜C×¶m2™ žç…d@áÄ!}Ûá9Ô¾í“ØÏ´ºç˜¾:$`QGy°/…K¶^‚{ °pŒBµúRæ>)Z_¨‚mc=/¾¹ß~á^ûö·pjÁ§hd20ˆÏx¸ÚÛBåH$$‰!Å®¦¦¦qÉÌqÈ5Tòù|I(e]]—_~ù!)±Z éííeÅŠÔÕÕQ[[;è¾ÆbôO´¢¢Àr<2æ'Tm–Ñ`Æ„=à=Ï÷}Ù¶=¡¢Êx«ÄGJŽÁl³©©iÜìÓóÝ·¡<äÙ)ÕËDا.ØÁ¸¬4±X Ó4‰Çãa”Š8€…Ã¥’}ÛžmÛ8ÅžCß³!³Ö£¢QwðJ •ököìÙSüâûê³yãFN=x}œ÷®wq«ëâû~éýaÿb&“™2¢,(‘Ùó<Ç™ô™’*5Tv P…ÁlÛ¦¥¥…®®.ººº¸îºëxÓ›ÞÄÚµkG\ýúõ%ËÕÔÔ°téÒÐû+F;vì“T$ìÚÅ–‡ÔõpŒ НÁ»WW¼ËÈLÄ`"Ó~§MõŽ o›À¸ÙgÔ¬XÁ…¿ùÍaÛæHL´¸'cM¥ìS„‘©TßV„á‘g§ T/iŸŽã„ŽÃÃý¯é¢ÒÇÇQeª˲0M“T*…£Gå Â!Pɾ­ö¼Õš°ðÄyË[¨ [P#åu  8Œƒoç±o|ƒ×îÙ£"S|L“=Ï<ÞßýÓ4ÙwõÕüô®»8á…H¥ReÕUšJbŠmÛxžG2™$•JI³Ã¤lA¥¥¥…õë×sýõ×óç?ÿ™uëÖ±nÝ:þüç?“H$hii)[TÑ…ˆz{{Ãü˜ a^PPy3óù<—_~ù¨òÁgŸeãw¾~?œt_Ù,,Yñ¸J§×ŸÉtùyž7a)Ï$rdò0”mãfŸÕÔ°x˺~÷»q=¶©XÓG8²¨„} ‚P•èÛ ‚02òì„êe¢ìÓ÷}ÜÂô¡| ºÞ5¨Tñq ,QbŠ×o¹j¦½½=Lÿ%þáp¨Dßv‹›sÊ·:mÎ~ZðŠóÔÌEêÍì.l0Îû”È?`Þh8~Ó&|ß'Nãºî!EgÄãÐÖ¦¢R2õjl“fUÛ¶',:e¢Žg¢˜êi£†³M{û ß4¹¡·—0¾¿¥a¤Óé²B9¡™hû¡|*Ñ·adäÙ)ÕËDا|iš&ÛçÏ' ¤(Š(~á{k¥OÆ8‘H$0 ÇqDP‰Jôm·zpÀž=sL-‹,T¾=M¼b„"²LÓdÓqDZiÓ&Nš6 #ÞØH{{{ÑïdšÊÙ+‡IY‚ÊŽ;ÊYlX!%ÊpÂÌX¤ÔÇú>AŒX£!‡TJ ›Ž£ìË÷‹µSt D[›ú>u ˲èéé©t3&%GBÚ¨‘Љ¥}®Ù³‡c¾ýmìO|‚D"1®¼ÖÖV%¢I˜ÔL¤} ‚phLTßV„CCž‚P½Œ·}:Ž£œ§©C¥ñJí•>ø À0 ‰Ùl6Uô cÛ¶e°¡0,•êÛÞŸ58ñï6Fi±êð`ß0+œ¸ßûêWYtÊ),Ú·ß0¨_²„ÖÖÖƒx'£SW¨ʪ¡R[[[–¨¢óèU Y œõ•¯J¥ìììryßWBŠëªš):Åó êëÍfÕ´þLíø…êe¢ò‚JÚ¨±å[·òÁÚZ@ ã‰aض;™óõ ‚ ‚ ‚ eáº.g]u9 åê)¼IX–E2™$—Ëá8™Lß÷ÉåráÀcÙ¯âû>Éd’ dïhll<¬ÿÚANO¶djÂxñ˜Ïüù }æl5Á)Ì8•—¯¿˜âyª.ƒ&“tš<í4¶ÏŸÏ/^ûZ\ÛfÞ¼yä¢Ë ÂPV„ÊòåËGLçÕÒÒ)ª˜CÜu•pbÛê=S¢ŠN¥—J)%Z«È¶Õzé´ZÞ²TA$¡ýÐoDè˜|xÀôŸþk‹€Y–E{{{جc¤GêHø³ ‚ ‚ Âää®|ž]Ÿú¿C l?Ò1M“îîîð»eYxžFš¸®Kww7Ùl–d2‰a¡pbš&†A, ÿKÏŸ??`b±ñxœ\.Wâs]7X‚ EP5^´ˆ“Œø,Ë …ß÷ôݹ\.~R©T-ÓÚÚŠëºär¹pùD"A<Å#}LŽã`F(œèã±,‹t:]"ª$“I,Ë E#]G§×y¾úÕ¯òÿø•þ©'%>ðóí gËN¶¿çBØ Æ·Ô<ËóIT "˜YѶ‹é…l›Ý7r¬irÜâÅœwöÙ´MP6áȤ,A ¹¹Pê­ŽFÙ±c½½½ÔÕÕ±fÍ–/_^éã)Á`äB⾯Dí÷/¤Ø,™¿d ô÷½zž`\W *B)ú!5L„ "¢ÍØò“íÛ9iÏžQmÃuUÙ¡d ³,‹T*Eccc(¨$“ILÓ ;e‚ ‚ ‚ Âäå†iÓ¸ø0O?½ÒM©Zt¤G___8­µµ• ˜?>­­­!¦ÓiLÓ$“É :±­­mÀ Z,*èh,Ë ÿ£G©¯¯Çq‰­­­‘ZAÉdBĶmlÛfÉ’%˜¦Ö nllÄqÚÛÛÉf³á±†Š<úxÚ #ªëëëÃöd³Y\×Å0Œ0GGË¡8ÓÝÝiš|þóŸçÞ{ï­ôÏ:)YœþÒKêËîÝÀ,¬ÇÔW#s1*Íɼ~+66*ç¬eA.Ç[ëêøÍo~ƒwÉ%¼ò ¡§gÀµ%cEÙ‚ (Q%‘HÐÑÑÁÆUˆ¾¡¡|>OKKK(¼T%¨¸®‹iš¡¢Å÷•Sv8‡¬i*%ú‰Š/G@òÃÂ4M²Ùì¸ß¼ôx¼io?ÊÖMOïÚÅ«Ž;î°××b†¡$$å×3MÛ¶Éf³aHq, GÍL”(‚ ‚ ‚ Œ=˜3‡O<öX¥›QÕh1¢?†aJ¥Â”[Qt­ÁL0Ñû® ƒ¡ÿŸæOÒõWû :¦i–lOÏ×Q%úØô4PþÂè>Z[[1MÃ0hmm%Nc–e…ßÓét˜^Lû.»ì2fÍš5~?Øç¸Ë祿=Žqþ6æÃp:G¥øz°!p×]PW§œµ ³–®Ë¿}ûÛä\—·ÕÔpðì³qZZDPÆCTjjjX¾|ù€h”|>ÏÚµk«FP P¡¹\ŽT*…ëº%7WíŒ-gtû`Ùôs'WÛÙf€->÷åz¹IÍ49ytî\V<þø!¯§LÇQBg,¦Ref³ƒÛ©¬ÐŸL&C}}}ØQÒ£OlÛÆó¼0´9›ÍÊ5&‚ ‚ ‚0Ip€—?ú¨d™X,6ä9ê?ðá hÕ5Y…Ãq‚Çb±’ý”ÓNl¨uúŸíB¯7)î¶þòel½ýUÔœõ[5a=ðE”AŸ¤&·Ý¦Ä=ê½­ ‚€{~üã0…ûY–űÇ7¬(£å•É‚cAÅua,jµµ)[>/^é#®N¤#ôçPã?t#ÇQß-«T- F ›U¶Åzd:%˜a” +†aÐÞÞŽã8ضM2™Äó¼ðzu]7|¥R)y ‚ ‚ ‚ L<àÀí·c¾÷½•nJÕs¨BÇá0Q¢C9Åãû3T”ÎPýŠ›OÄù;R6ϱ ŸæàsKŠ£§Wk[º¨µï«€a°àþ‡˜a`š&û€×OP6áÈeZ¥0^x¨BñC9B‰^<,,K9k/Í@»Ô;*AœÐÂ`8ÀñýëˆËù¾F’I%–èiýû,–¥¦¥ÓêåûJTq]µ’LŘ(ºn ¦þÒ*]ÈNG·yžG<Ç—¢f‚ ‚ ‚ U‹Ô<ö˜8»…Éd2ât¯0QË~Ãe Õ—“PNݳ€ó ŸA9z´zS팄þxÀ)=6ìC.›UvêºÊžtj¯Xlð^ R€ù¾Z>•RBJ—_²DM7ÍbÊ>îl›¦ÖX%´èBõ–eáû¾tÌAAAª~ùËJ7C„2•ƒGqôSo丅½@¡ÞnÌî·B.Wt¸|ŽŽãÐÖÖ&¾aB)KPéèè ££cØez{{+},%xÀû÷ìÔ \wì÷÷‘ü—£FÃF´á”BndÂP¸@ìñÇáÔSÌÓ‘(¹œJ§×ÖVœgšEQ¥?ƒ¥xÕë&ªÖ‘i*‘¥½]E²$Åh—T*5è5«‹ÏÙ¶M.— 묂 ‚ ‚ Õ…®¥Ë8EH¾A¦Ÿ¾—E÷Õ°`Î,5á$à/ƒ,hY¡Sçû3Þû^R©ñxœîîîJ†pQ– ’Ïçéêêq¹†††JOˆœ´gƒµÚq”ý%ï4à6 ŽœBÚ¡¡jYr§RÉ"Y„Ü!ð}™’J ìÛv1Eæ¡¢#[²ÙbäŠa¨W,¦iaÅTaZ´I§ Z[•€bš&žç…íÔëA@"" ‚ ‚ ‚ TX²};ãåVAEƇ™/;À‰ÅËöÖ¨ §3¸ ¢‰Åؼv-mÙ,±XLÄaÂ)KPijj¢©©©Òm-]?E;?£ärjTúx) nÁœÂ¶§èvå¬õ<5M;ŽûË„©LÔ6ûËf•hâySrÁÀbô‡‚HZ[• b*JŠvšÉ¨ûC.§¾k{Õu[tñúx<Î3Ï|‡÷¾÷î¼³ß÷Ã"÷š €b¡ Èf³òyzž¦ÓË–¦Ð-„Õù¾çy˜¦‰a$ <ÏÃ÷}b…ƒô}Çq‚Ã0°m»$/¬Þgÿí÷¼Ñ5eô}Ô²¬ë"yžƒÔPAAa"ñíÛ·K] A˜¸EÊž¯Ïçì;xê¥ ]Õƒ˜ñž={ØøÀ¼óÎ#qÞy2¸U¨e *½½½äóy–.]Zéö–…‡¯ E ‚ÃwÊŽ„Yx¹m°È&•Ó¶­Mz÷}èîV\]ï!™„ÎÎÃÛŸä€ÃúO´ƒ\ÊÁE]«¥iá‚@½|_ÙËx>UDŠúœJA}}qžã(1'ZE‹°‰œ{î8pÀâžæK_z‚÷¼çJ.¹d_þòÝaJ0€gÒÛÛËYgíë®X–E2™$‹áºn(ºÌœÙÀ¾}†A_ß›hl<*Oô}L‹¶mãyŽãàºn(è8ŽŠ-¶mcš&¾ïDZm;l[´µµañxPBŽ®£ýûèy˜¦I,ÃqœpžŽÎ‰®£-ø¸®‹iš%BS$‰’ë@oÃ÷}|ß/KÄAAAå#yåSO±¶m¡þÇ ‚06¸¨,&GÏíão3ÿÆ«—¾ŒŸ³Îg_÷:ìÂ@N€\.G[4W¼ Le *¹\Ž®®.Ö­[Nkii¡©©‰ºººJC : ïQ•˜2žþ¹¶Â~³€WnàŸÛàÁ@=àÍÔ1 –YÐàÀ%1È æßïÂ¥V1õP8Ù‡»Óªí:UØûàÔŒþÙÅQüÌÈM™Ø…c(—z vˆëG6ƒi%:Jd°ú(cÖX3%šd2J0Ñí£3®«ÄÓTm{òÉO’ÉÀ 7@cãé|á ªÝ_\Ç—¿ ±ØÅœtÒ,::^οØÃ\C*5ËÒbMŒmÛjyÓ›>ÁìÙ³yðÁÙamÓ„ýû·òÄóijz€††d2Ë%ÌêöÄb1|ß禛v‘HœÃ×¾¶Ÿ§Ÿ~Ë:9L‹æºjÙsι†XìiZ Jr:Æ÷ýPÐH ¹iÁ%•J *bd2î¼ó^6løííí¡ø2Øè/Ïóðýëx¿9PpSŸ|pàòžç‘J¥ð´œ ú\tëÒ)“ÁCÙG4_2©RkeEý#t •B ý6Ø¶Š K&Õ2‰DQI¥ŠBŒaœÃþýð¹Ï)Ñöî»!›=‰9s”¢SüY–F«e2°w¯ÚF[›ŽˆYH@:}^I‹©vf³ÅÔ‰„‰ëÂÖ­pæ™38óÌ“KìLלqÝ3I&Ϥ³S}F«èH: ¦icJxÖÛ1MuoH¥Tûs¹ss™?_µ#•²ðý¢ ¤°H¥,OMM 7Ýt555¬_¿ž–––-[ÆÆinn¦©©é¶}tê¢Ì v•¶5£ð²#ßmÀnƒÓ ùɶ:ðš ü²0:}aÜ,¼¯ ž3T8Üœd£z0'6 eÃwløHö›÷àý­ð}š,Øâ¾õõpš ÷°8ÿlÃÊzØÔ¤ éÁ6žèçükŸp¡'çdà,«è;Ó1ÑÓìyÊ9ìyJ\Y`Ãß*Ja(Wç’%…óc¹‰„rÄf³ÊѪSŸ%ê{¶pþt}UD¼˜*IgŠÅÔË÷Õ²zô¼):â Øþ¨ 3•šálûô(Ú¥¾&LSÕª$#‰9¦Yž ½Ç 'Дs/Ц?‹^sÚ…LF‰*ª>ÍtÎ<óf̸Ž_ÿz]¸Ýèþû=G:({ê< –Â-zìƒígà:‹¸é&ÈåáÎ;Å׿ÞL.7Ãx/®«ï Äó|n½u??ì±té[¸êªëpœ9ùäC;WÕÊDØç˜°è«ôÙ„‰e¼û¶‚ “æÙ)G ãeŸ&”ÔváЩDßöÀ1ÓÀóeê{è~Pi7šÿ‘χ(ÛÛÛ+}ª„#˜ TòùìIÂ7\xÒVû{{nÌÁœ•ŸÅáž à­ð/iØçÛ§ÅÑõžYæ˜ð5Žwà¿cª³óL¿ àß £×=O9H£NÚ¬Ëá}™¢ã]ßS³ÙÒã:* ™T/=*^;ƒs9µŽŽhmUûllTß;;Õç¶6å€Ö‘ mm„©R)µ ]ãfÁ‚J_U£g$ÛÆÄ>-ën8Ž:ç¶]ýU¥ÅØÑ¢£b´|ík·Wýy’H$B!I߉¢šJ™…h§3yã•}nÜxµµWºé£f¢ìsÔ‘wI2-!LDßV„CgÒ<;ád"ìSA8<&²o«KÔùå$ìï0Õ5 Ο\{-W|ìcS.…0ù([PÉçó´´´”LÛ°a%Óš››‡ÝFCCCh”Ë—/gÇŽtttP[[†’-]º”¥K—ÒÑÑqÈj§…*°lG†TW‹Ct(]§&€[rª`ýPÇGEvX(ãé´ðK º(¦Ë^›RŸ­ÂË¡ÍaÛEqF³Ì€-–Z®Á„ø®äàƒ­ð°/k‡Ÿ™ªè}}7´öw'ð¾vØá .¼2€O§ Æ„$²m° ¸Î„oð  ßJÂt>îÀ•ºöÄT±{(Œ0‰ÁwbªMÕnÄ—Å 3¯³À³ iýyF+üć節š+lð’ÅOú‹©s£ËRâ l~ëÁÞ›Pµfô¥pá…16WúÒÃÙ&0&öúZ bg”Ö$ÆË*°™JyFM³T€FÔ,ZŸûÜ[*ÝÄQ3ö9*Ò(O nözšY˜–+¼ Âd¢ú¶‚ Uÿì„#˜ñ²O5¦Ç—”_‚pØLDßÖCù÷´¥Î' Ÿ2J'FÑN;ËâÓ$›ÍD¨eZ9 é¼x]]]á«¡¡|>_2­««kØí444°nݺð{oo/6l·Ý_Ѭ­­ sö Å“O>ÉÊ•+L×£à' §Úp§=îàóM ‡b¡{¯ðnÛðômÄFu"ÌÂË×Ë¡„’Þ‚óúäDqê¾¥Å`-Â|À‚?fà„ºâð §„½\@éçð·à.à—|ÖUÓµŸ-¼Ï†Æ`–÷·— Zá6_E•üÊPBMga½ÖÂzm…÷öÂyØcÀ4~ç)!H§k/´é¦Ú‡^>ÜmF „—žcFÌO¨¬5…s¶%ÇÛÐîÁu–š^È0ÆÇ>¶’“OxýM6†³Mà°íóÖ[o …X}½iÛôï­¡óH` i(eÑÕÕÅ}÷ý† n®tSFÍxØçÖ­[Y¹r%ëׯ}ÔÃF¿;¨´ (ÙÃÜ®0eÑ©žþùJ7eÔLdßV&‚•+Wrë­·Vº£f"ú¶‚0‘tuu±råJž|òÉJ7eÔŒWßö†n`ßC•d+„‰@ú¶åõmµÏ8 2ØùoÇ(çbŒõ8µ=[¾ïã8¦iÒÚÚZéS%LZZZÆ¥o[V„JSSÓ˜ÔÙ°a---444ÐÔÔ4hÇ´œ±SN9¥ÄØ5žç…*Õ’îk8Î3á¯ípÖ0ËD3¨´ ±LŒÒ¨“hiŠN 1?BE€èmd /-ÄDÓß÷A›ŠÜH$ŠmˆÞºlJ£ò~dÀë=XoÃÍâÀä¨?·;cÀObðé|Ã(Öa‰nW‹Dú³ŠDio„·™¥Ë&úíOo/Íȵ0¼~ç-mÀçáÊ”ªMCùã@lÝ:žœbªúÛ&ŽŠRŽ}¾õ­o4jm–w6™“#Û”ösú ãÇÒ¥KY·nÝ”sJŽ•}.\¸pÐgç!¡ Ðë°Ir½ð ½¬ë v ŇCQõŽhššš¨««å<Ùï¾­ LëÖ­›r‚ÁDôma¼‘¾íÈ}Û÷~üã¸ÀnI÷%L0Ò·žáú¶í€}ÿôbvç©<ÞºpjÓ4qGj% e3^ý¶ /JßÛÛËêÕ«Éçó\ýõa¨Xmmí€eóù|I˜Y9xë¶mã8ì¯*1 •¹üá ìׂo’bz0Ù·¥#7ÊŲàTà8Ô{9@· (H·@¶½8ºœófÄÔº…óQÎ¥qŠ÷ðÆÂ6ZQûÌ“?¡b(Û„±±O‚ízú<'ô@»vÈê"AÑa ‚ „Œ·}@7øß…`X.x‹ ~+˜g€7b.EÁ%ÇàEÄ@l_˜ÔŒwßV„ã*Ÿ‚ ãcŸ°wïÞJš Lz&²okó—?Åv^Y:#™T©¾‰p”¼Ž>3MsRe$¦&e¥üÒ´´´pÝu×…ŸÏ8㌒—]F1„k®¹†ºº:\×-yh.]ºt@˜ØŽ;«°Q´ºÈyµcö{/R…•ñä#1øà!,¯o…þ!¬Å 3å ˆÐ~üÁ¶Å¬V87Q*dÙ‡ÑÞjf(Û„±³O xþù\xÂ1d^‹r°‚r¶ú(…Êeð¼™–ñ Ÿ”CwId;‚0E™û<$tœvü=~â !ñYH¬ƒØ€?õÐI¡n˜.Åz+ým(n[a)”@ãG¶¥kêx‘ö¸‘õµ³t³ÂÔd¢ìsX´MnœþÿƒÜ^ðß ­ßW÷üþÿ]S)pÈüÔb@ì³`¦Ž4K¢lP§ (†ÿeQ÷»°œ¶ó¡B,u„KŠBÁ¬Â{¬°Ý,êfïŽC«øÔ=£§°ŒA1?f{á=UØF®0M?8´œ‰´Q8¢˜È¾­ åSÏNAEìSª—Jôm§¿4ˆkzTCR7E¨&ÊTn»í6†Í‹·jÕ*r¹]]]C.§o(šššhhh ŸÏSWWwXacÚOjž79 ÒOE7áp¾²Á8”è†Ð5¯tÀÃPþríwÓŸ£Ä€·\r ÿØÕ5Fg®2Œd›0zûôPÀc§½ã÷‘úÔ EŽC!zátS,¬ÓŠú‘#ÎàpÙta¹dd^®0_;xµ¨#‚ŠP!&Â>G$GQìt!ûs°¿ ™kÔìÁf³êYH€½¼ðvCö]Ðm¡nøÑAZÌ4"ŸMŠ¡…ºCÙ£c<”0’¡ôæíGöCä»O1dQ ¼~dŸ Šâ¬Ù†®ûUêT…aQQtÉÂvô%* “š‰èÛ ‚pèTųS„A/ûôMùKÙu\oô›„ªf¢û¶® µÇ—·¬ae•š„‰à°‹Ò755ÑÛÛ[2­®®Ž;vŒªA£5Hƒb¡"ÏSQbÂÄcšêu(ŠMÑï].ÚïVnª4‹âä°­(?™=àX ïÁÛ[ý½ïÁyçýI¬BFcŸJP9n×…ƒ_Zð+¢ÏÙ¨@dz'E‡ªvžjÆ:í Œãá ò¼Â}<\ð¹]à΄Ök†_·­­øÙ|GѼ=rÏCì0b¨èew:bÅ£¹-–¥?kÁ#QX¿›bJŒ¢ÈµßEñÄ(¬[O1"F/oD¶­Ó“%(ZKQUt 1ý]ïC§+„RF?p´xKdÛÃ᳜>FÉpQ•ˆ£Vª±OA¨^Õ>`éæÍâp„qf´ÏNý·èñ4.Ì«ÿpÂË{ž‡ã88ŽCLFÍ UBY‚Jmmí¡¤¿ñôööÒU£ô ”±™¦‰'Ã*†ïC:­jåögtíâCa¤4]C-¯2Cq 0Sõg8Ÿúì½{ÇôÜMEô sß÷‰½ûBì‹YH;9£ø>Äãjø»çA&3hèç¨îBÒi~'jF&9ñ8tv‚Q¸þµà¿¬—þ6S)•2þG°Ï‚ ±U»ì Xgï?ÆC1vxIˆiqG‹…hÿ{àÜJÛõ"Xç7¯ÜÏÔ²‰>ÈÞÞSk?™×@ò}̆ÄçÁ=¼+ÁœöiàÇÁ?2í`à Ùz0OûŸÀû  Áü¸çŸ‚u2Ä|p›Àø>X‘Åmã\Ö§Áp)Fâ´¡¢["BT)×H˜’08Á*0o.lsØ-à¿ÁqªmÁgÁXÁBð{øçƒÿuNvAìœBÐÏÀ^Î÷SÁx𤾯n»AætÈéúT§¨å'ƒsûð—‚/Xõ`œ©nÛÑZ:þïÁßF'œzʉ̚5«Ò—¸ ‚ SˆY{öŒÛ¶%Ñ Œ=v`á)…/¾A€¹lÌœ.ãy–e‰X*Te *Ë—/§¥¥… 6°|ùòA—ÉårÔÔÔÐÐÐP±ƒ‰f™=ûe%£c…‰Å4•æpS•‹H|(èRa[)½v†ü+¨Ñ¡ÏßW¾|ÿðÖrW2U˜™ë*u.šWÈqŠ"Ëx7\ÄYáD;Ó…Hspñà)¾ÊÅ4•Ù¦Ó…Ú+¯PÓì·Ì:Ç€Øðç‚ù<¸/o†ä`î)8þß ™×‚·‚¿ÿn0þ Ák€?A¦ ØÖ0Þ¶|ÜσÙæ9оŒC. ­Oƒyx½`} ü7I%Ø$o÷ ´žæßAðESÀ| ì·¨ïÎ`þ Üzð›!ñhL‚}*ð-àIH¥!{øÛ¡m ¸«À¼[ 1àC‰L<ÄÔmÐóÕ¹7oV·ÆtXæ·!ùù ~Œë óHþX-Ì÷z0ê€ànƒà»Û±0~Ö,à§J4b8¯w!OCj/˜g'€ùfð×se`M‚ù=0f‚»ŒÿãE0¾æ,h¼Zç»x‹:þï¨ã}WÏDAa2 þA[z=˜Ý»ysgau=_ÍBÐí8Ð×.çû>±X ×uETª†²•ºº:V­ZÅêÕ«YµjMMMa„Š.X¿~ýzÖ¬YSу‰ÖÓxøásÈåÆß×* N"¡Ä”Ñ8ÝÊ¡C÷u[” ( '̈676üîwÏpÂîc†Îë¦=¬Ñ\}–5¸2‹©" ‚ Œ ž§" ]xoÌ¡†Aÿçs,V¬{V2O×oI«÷î¸zwïPQl…àO`ÿìßPTÍ“êÝ~¡ð9RôÞÖiÁ<0 Eêp «° s»j‚Ï…6,]„ëI°"5™L€³Õ»ÖhéÔ_1èûñÀs`__øÐ¨„ˆsÀ]Îi`¥ võÐÏÒööÈçK™ÿÉÈùL÷}%bEãýÌA–‹~.‰ |ŸzìRÐëøwAòZh3Á<ìß•fbìèðèè]šXAAM;Ðèy$Æ#£ cŠöÉ}ìu?ä‰ýqŒÞ}êh{;ýÓ ™¦‰eYXã=b[²k¨477S[[K.—cíÚµ%óêêêX·n]E£S ˜5Ãó<öî½´ìTSÂø0Q÷ºCÝM+ÓwÙ¨Ô'C]2rÛúqxÁóð©+§ ¾P<·‡Ð¶m5¤}¼óhJ„Šp„ƒU ©Û!iBp5dƒqÖ+†!-cøGVoJ‹,&Jñ ÷[ÈÕ‚õØ¡nÖú†ÝÙ†Öhûßä£Ë·õ›Þo¹TÿiƒÕhÓËDrv$ +{€4¸AìºòSf*æ ±4/°2þ¨7'‚ ‚PæDttA>pV žýÁ³œ¿u÷œ°XÍ0 èî—ó¤–ƒP¥RQúU«V±jÕ*:::Âiµµµ,]º´ÒÇ(ƒŒNð˜0‡¾0¹¬{C *q¤TÆx kÖܸåMxg!\¥ÓJ…;Gl,VðüZãë!”AN†i‚û}ˆõBûjH~ Ú¾<ÈÂŽ£Š¢rÞ=Éf‹9 ÇÂVµða‚¹¼?Aî7ûU¥ÏÚ(ˆ©—Yt‚×8´À?™èìT—†iNÜ AAAªŸg}xvï³\|Þqpêσ LIPÑT:e(ÔàдçñÃ~Ž÷½¯Ò-&mëþ ãÃ#{Ã8è2AHÔ™P•Lý&ªýè|ä‘9ãŒéc·aIUqÄÐÆ¤÷ÇU%:ÅÚŽÓ0ßQø’Í**’þWßW/{3œʹëºÅïš\N­çºÅš.óÄ ÂÆœ+Ì<ÄÞ™éyÊN4†1 ÈG:æùF:Å­­|öu¯Ã럞¯¾^ÙšŽbÇÜ6‡ ¾bcÐH2ß÷ ‚Éc¼Éd¥[0¶hQHþ ‚ ‚0ˆãU&)RðËõÐÓ3è|ß÷1Æ»8³ ‡¡R­hGøôé]j (¤àQêS¹M>Ê>gX¤œ¤õõÊÃfÛÊ9;–¹`´GR†O$Jk¬h‘Ä4•Ø4KÓŒù¾ZÔ¼ ÓPŠ­1®…šþíö}µ}Ý‘÷<5?º\.§†ÿëí÷Os¯+GG+Oƒ:A ŽËqÔ°öè>‹ëëÎG4|6ŠÇ ×ý#}ô64mmj[žWÂ,Kí#•*Ý29Ð=† €ùó‹ÇíûÏS6[üô¾¢‘ º†¡Îƒa ÒïyœºmÛá\EG6YȜևRWשYÞ׿Î÷öïç+Ç.þÖ»îbÓ´iü~Ù2ìL†%O<ÁšÎzàÇÁó‚~á?_l¼kæ Âa0emžç1cÆÅcçŸu€*T÷(·%G0ðæùUE:;ÇoÈòHžÈhNÁ,Qªp¾_l C‰}}‘ƒ4”÷P ±Øà4:½™ï 5Mלl”~gg1'•0â9‚¢XaYƒ§[‹ Zt‰ÅÔ´TJ—>Îþ7ÜÖVµß\,3 uÞtËm¤Å°¡þétoÑH£þmñ}T‘ €ìOSÀ² Y´"§tówðuëøôܹ€ <òâ‹äÏ8ƒjiáÁÏ|†===sÌ1üݶm¬{ï{ù`k+·ÜB*•Âq|ßç™Y³X:{6îÐyì±üöé§1øCžûã¹}ñbnzï{yÍ©§âº.¾ïóÈÿÈ¥Ï=‡]°‡ßÍŸÏÞ׽ޣŽ:ŠöövnýÚüõî»yê I&“†mÛd2Ç!Ncš&†aÉdˆÇã†išá¨§l6‹ã8†ïû˜¦Iaꈶ¶6|ßW4ôüÖÖV²Ù,žçaÛ6±X,ܯg,Ë #fÇÁ¶müÂ1¥R) u½76ªË[ï/‘H„û1 Ïó˜¦i†Çáû~(ée¢Ž…þÓôñÙ‡‘_L‡8.AAA(íáøÛ¯Žbó¢Í˾\™ ¡LAÅCAÀ)§›ÜãNáÕVØAåXÕÎ%åMŠ1õ£Wô ž ~“,J“êóFüüç›ytî£@ýäËÿ⢞ú)>™–º7t¢®'}°!²«0_r7€DáÂóÄ*òŧ˜…CŸ+Ó<üóhš#×±ˆzÑû)'Ï`BK†»Q—«Šëúƒ‹ñ›[oåêÃ;KG$® î³ÐúuùÕÝù<ÿoï^z}”S/¸€ý/½„|xóf^<ÿ|^õÈ#üöª«øÌìÙx‹«šf}}Ä~ýk^óè£t\z)ù÷¼‡3®¼’Ó ƒö—¿œãþ÷yýg?ËU‹qpÅWpõk_ËÌ|€dá7m½òJâñ8_þØÇXÖÑ^‹ß °mr¹žçqÔOðŽ3ÎàŠ™3y[{;étšLáO&“d2™’hõ¢£Q|ß'“H$Jæ9ŽC,Ãu]–,Y‚mÛØ¶ A„BJ.—#‰¹\Çqhkk §e³ÙP„‚ S,Ë ÷¿sç¿aš—âûJüˆÇãØ¶M<ÅGXÿÁp‡îîn‰Åbá~´Ð¡GuyžNï/†¤ÓéÆ÷ý'j¯××¢“>Ïžç É×çËó¼!*V¬XQéË]A„)„ÔO„Ƀ<ÒwKÿt)î_€ó.ãº.‰DBp UÉ”T èëß±ãxF´7Ò⣣&*ÿzT41PNw³ðîD–uQNÓ,,¯ý“^aZ;ã/@¸…}”‘ãŽ!Aù"“ 4J']ØwŒ¢Óx4~òta_mcxÞ mÒðý¶ƒÂ+º/ò}’ùû«¸ç;8e÷+Ý”ÃÃFy–]R–ºV¡X¸É¢xoÈ–P×[‚¢ cP[ˆ,cQ¼­Âò&ʦÜÈrDæ' Ó¢Ÿ…m$#ëú…Ï9Š÷5-àh¡ÔŠl? ˜ÞÌ+|7 Ÿ‘c6#í4( @ÑmRØnô8½AŽƒÂùÓíÐúˆÛïÜ…ù&íW<®9²oT§Þrüª¡ƒ^ˆ»q#§ýÏÿðéË/gAo/_;õTþëÅi»àêQƒ…ŸgÑ"\`Ý™gò̓™?mιçò ÔÏ_±“âãå¥þ3{{IŸtRh ¦aÐÖÞ®.Ïw¼c@{-Ë"›Íâû>¿þ5þW`©¶¶ðRYÛÔÄ{÷ì)#ÅËÊÛ»kûvLÓ¤3šð #W,˶í’teQLÓ Ó†EE™(m#EÇŸù̽Á¥œþ·H&¿I[[ÛûÔA@:Ʋ¬PÜè?ßó~;pR¥›sx`¢®¿,ê (µ/-RꨵþhÁ@‹ ÚÛ«E/²\Œ¢0´À¥6“,¼×S u;J-R¤(ÚFe/F¤=n¤­Z4u"ûND¾SØŽnŠ¢ ‘ãµ#mÖöm´k±6z.½Âö³‘ó®ÏŸ‹¢Ë„^8a"®)AÔ$àñß´ºƒÉ|èCd>ýiŽzðA>dÛÜø‘`}ï{üäoã_^þrÞyÜq¼³°~To×.šN€yóÂ@.­/Úý^`ΙCãœ9¤ mɡڡµHýx°(^&‰ceÆâÅlûû¿gUm-ÁÍ7cöõ/½-[àsŸã/{ÆæÍ˜sçâ×Ô¨y›7cýéO$Ï?óàA|³÷àAŒM›æÌÁ\¸04©˜e‘ ‚mÛàÄ1 Û €iMM̰,n^°€þéÖÖ­8€1oÆÌ™á£Ù‚»îÂØ½ãÒKIYß[°€ÝwLãGŸý§÷Ka¦ŒLûøÁƒ¼¥ 3:ýY¹DS‰D,6§±ŽÜQéÌ”x¢ÛòŽw¼ƒŽŽŽ²Û%‚0Õ‰Š#žçáy¹\.ü®#þtJʨ ¢k(Fš¦‰eYÄãñp=Ý÷ý0ŠR£#ÃJ)Õ@%„Âh¦c]J³G»q:‹‘~×Ùž£/½œ6QËbäAà ½]úu¹Òh–h×-=V×<ñ.ÃÍ¥3RG»ËúüEK‹ö?ïý›,«8Ͷ¶¡PÒ1l¿ÞG>\¥ŽIE¯G|‘“~µ†®ëþxþÒé´ÔOª–)%¨XÀ–Y{hh˜©&:(Gy7E‘ *¦hÇ^Œ¢G'Úwì?pR;ÿ³(Q!zS·PQÚÉÙYØw†¢FåmD9µÃS. =œW‹G)ŠÎÓ4Eçf¶ðÖ³#íÐNYí-ë.|ÎEÚ–£(8¥ Çݯ¢ÁÒ®e ÛOPtG ·¢D°ÅH$}^³‘s9iˆý F÷›¤ÀÎHìrïÚ™7ÁØää›`ôµ3Td„¶ó¡ž÷zú`²ÍÈüÅH ?òYoßE]¯ZdÑ"¨Eñ~ =ÒQ±DO£°½%í_‹¦:ÊF‹®Ú?ëækáÃï7_Û¹¶UƒÒ(}ÌiŠÂ“ö;ï­z¢÷©=ÚÉÈ1kϺn³C©@“QËÄJ¬\²À&àÒÕ¥Ÿ6§Î8ƒW>÷{_|Ø=s&ÍkxÕÃó¡sÏ=ä}èŸJÇèÛoÏ ëh 0$å–ÍÕÔðìE±¶© {þüðÖíÁ¢EØ‹©:=„kÛÊ”~ö3üŸüë«_ÅÛ½³·C *Ÿü$îë_ýÛߪË3“ ý‰Lû¨£Àuñ:;Ãq/Þr ¯ûÏÿäÌ·¼ÿÜs1ßøFÜÓOWíÞ°XOÆcáu­ï|'¹º:¥ÉÖÕáåó¸?Œ±u+ǽø"›vžÁé§ï)=étñ_gwá™cœ¶i݉Dq^!$ ›Uÿûÿ!lù1D§ “?BU‚Žç0c× ®¸â ‰ò„ £ë„éúbÇ»Œ|þ45Ïm·=Â{Þsmmm%·ç©—*ÙW@I¥R%é-5:z1º¼ëºa=±¨xâû>®ë†õ¸,Ë2ÊQGÀ”ý(ÕŒîé•Q'{"Q,¡™ÉÀ_ÒÊõ¢èÚ|¢þX¬èt§°lA ŃDB9êõrž§œö†¡–qÝR [”J©öø¾*«-ï©Û˜NïºmËR/ÝžÖVU»Oo#Ô6G­—J©¶èœ¦©–km…x\}O$Ô>£]ÊD¢x¿Š–åÔB„m«wÇQÛK¥Ô6tô±8NñœêvÄbjZ:]z×Ù9èz}}ÅËײZû¾þõ?õ]pÌ¥ûŽ‹•n§»[µ+•êëkm¸¬iöõe2}}–UºÍž5OÏÒÚÚ×g}}¶­¶]/•RÓzzÔykggÙ÷xýŒ2˜}–Ão.úM_þâ|__g__0?èKÙ©¾~ö@ßCW<Ô÷Ììgúî_xß7ç}³ïÞò?}ªùS_ÇG;ú~sÑoú²Él_ÙÓ÷ô¢§ûnºö¦¾ÝŸÞÝ$ƒÒ>¬pD!}ÛÁÍ}«³³³ïŸøfß9ç\ßwÖY_î««»´oñâûfÍÚÝWW·¿/•R·TËêë›7ï›} lêkmU·aËR·W}ËN$Š·|ÃP¾>µ~&£¦ww|;N¥R}݃>ûŠÑºtWv8L³ô7³,ÕeÕè.¬&ØuŠÎÎÒu㪫žîK§scò¦ýï[v__ßyí}}'_ùR__¢-t jº»»ûLÓì‹tÒ¡LÆ£o;¥"Tî»ïÎ;ov1"B§§j¤˜BF–>œA™çóÒQ#Pý§´ž‚&ùm›ŽâÐ)(‹E®GpGƒ"R…—Ù6SÅ(‰¨#j²”¦.Ó‘+m¨Ñàv¿õôèõþƒMõrÝ6=Ú]§òûµW§ ,…ý÷OY¦kJèTAÑh}œPZB3Tú®ÌóìH{[)^O­S0µös'Â0èàŠGfíä˜Úcª3VùHd´ÆÇrP{¹—„Y>QÖÿ˜"÷”¿ýàocØÐ©Mm.x'8úEvrÓý÷ó/¦‰YxAyY'=Äm<ˆnWÓŸûŽ *o˜¼:ó´ËOä¸ã^äàÁƒ`ša™$]ŠÈÌÏ~ÿ¤“¨Ó4Id2ap–®hÖ 7`ΘÒI˜‘QË`Åãøÿþïøo;üøÇÅCüÝ»±»»Ãá’¾Ná¿}—\ÂÌ™3K×uÕPB=¤2‘P¯x¼xôÐGáðÐ}#þðƒ?ðììgyã=o¤÷‚^¶=¾ÿœùŸlŒo$u^Š+¾’¯7#0øx×ǹµíVLÓdElÍyˆšÕ°qÑFN9p i;¦š{Û\~|Ïùú¿¹—Ì%¤yç‹ïdËâ-ìø;Øúƒ­˜†Éy¯8_ìù«¾¸*,lYV8r=zÿ„#•K.ù>=t,'tçw o{ÛL<ï#ØöÀG†mÃ'>1»î2Â[¨¦»_@¼¡žË©Û¯N_£Ó %“j}="¼ÙªÌ÷bÓ4Ô¸J$ø¾O}}=©T*\×0 ’É$étÛ¶1M“d2YV 0Ak†*J¯£;¢Á¼º[×ÿ2)‘ÂŽi±˜²É¡‚s3 q6>ÝÙè6£i«&:aÄh]¶=lWPQ.Q2™Òý¦RÅèú7 Ë‚‘‚%>ô¡'éèØ1v'íà  u𢵵Už#BUS1A¥··—;vPWWW2=ŸÏ“Ïç©««0o8´/? Î;ï¼bÊ(m(Dœ‰/8^N”ZTˆÑ‚Ä¡lc¸TlˆùºJÿ¼+ Š©Ð…¥ÂŒ‹J¦Szõ_v¤ã±‡˜>”¢—ëÌ"ÚÓ¥E”rÚ?‰Ê6áðís‹¯xá%¶Ù¯aîa¶ËqŠ;b±¾ï1©d<Ï óë4 :‡¶NǠχïûX–…ã8%y¸c±Žã‹Å0 ã\žç•Ý™Ñé$¢yÀ£Eª£ËD·=TqT}ìÑõ5AqÅ'ÇÃ>Aݦ·¶Á¯¿î£÷ƒãðG”HMR•nðÖÖCZ|°ë¹ÿ´ Â"óÎUázu_ ‚€T*þ‰w§¤˜»Þ–>Úþôµ­m¶qþ|Öíx3/|£‡¿½­—£€K_|‘wÜÁë—-caOçœs¿>é$v=ð{Ï?ŸMÿó?Üò®wqû}÷ñç×¼†÷LŸÎÃ?ø'\x!]¿øûÞýn:€-÷ÞËš~÷‹_ð–·¼…{,`S{;oß½›Àq8ζYrï½lݺ•gœÁ³¯|%/ß½›­óçsê©§Òóøãìœ>Gkj8k×.νà¼Ï~–¥³gsQ6‹aüáá‡ÉŸx"Mÿ87?ô[¿ðÞ¼i­¾ÏöùóùâŸÿÌÿyî9~qÒIH§¹ãŽ;ˆk¡eŠ0Ö}Û ƒl¾ë ?}ÏO9÷ç2oß<º­nn¿ïvÞÜùfø'¸êÜ«°m;¼Fï©¿‡Ds‚y¯˜W’ è“ç’/ÿöËœþûÓ1M“&TÚ¼ ˜?>–e±üæå3ÚîVŽÑüŒ<×Ýzk\ÃK䟿ýÏ|wéw9ö¡cq:Þsÿ{ØV»-3·pÚ³§áĶýiÏ^ÿ,wÜp5Õpú §s÷Ówóšm¯¡i­ÚgI]=AÆëÙ9¾ï³cÇñ¬Y³× èééaúô Ù´éôÇÞPÝWÀM›šX±bä}éîO&G¥…ÑGbggÑ‘lÛ*­Îþ˜Íªõ¥ eš&íííž¡ýS²Äb1Òé4AÉd°m×uÃ>lô%ciŸýSÐÅãE¡1Ù!?†²½C]绳GåüvýEãþ¢‘N©¦9Ü£f<û¶³M¨9ÿ%`Æ€1ëÙl6ô[BµR1AEØknn§­_¿ž–––-[ÆÆinn¦©½\^|ñ8uãÔÅ•£˜”F5) ÕQ¶(Ô$8|¢ëf†ø¬™l÷ÅhÏg0Û„ÑÙçÞ^s`ÓßóžÃj“çy¤Ói2™ ¾ïsÔQG‘ÉdB‘E ƒå.=²œ¹\.|ˆ†1ìö£¢A6› Göé‚Ìú¼ê⟖e…ÅCõ~õ4}\©T ß÷Ãíår¹PÑ„뺡cVoOŠÖûŠ1õ}?,î^²Ùl¸?ýÇ×q2™LèX‚ß÷KÊZ¬Ñ¿^V·K·©µµ•xN“J¥BáÍ÷}âñ8aÁ_Ó4C[××›¾Æ<Ï ¯Û¨Íš¦‰ã8X–…išá2úšÓ¹ìõµ¨ï ZxÉDýÇß0 ÚYòίñìÞl~÷©d²Y\×å-–…}ôÑär9ΉÅèqUhxËNzúiÞrß}|wÏÎøÔ§”£jáBÌiÓðN>çÃï[`¼ÿýxžÇWæÎeÑpΜ9ób>q×'h3K;‚†aÐÚÚŠmÛž«Ÿ_ùyÞð7Pó‘.Ê\Äܨ{rzIûa;Œ\9ÿƒçÓÚÚJ~Fžÿ¸“U±UxÃ:ÿ«“·Õ¿c~s ÞΞN.;xÇî;–='íaϬ=ÜzÍ­ÌøÙ ®xø fΜɉÓOäÀŠìøëj_SËc5qæMgrôÑG³oñ>f¿nvXK¯÷Ÿz™së¾æ Óÿyz1J\G3[”FuëÈgƒbÈ»®Ñ¥k"Z#´uQ%íÃó5ϳàC Ô²…bO»fìbÎGç¨uu±8¥}àXd;zŸº}¹ÂüFŠ5Ìt½´4ÅÁGºfš^ÇEõïë)þÒµËtÃh-6=À*Rã0vtŒÍ ›GoUÂx=;£AÀõ×wðӟ§¹sÿÆŠ5üíoÿ‡ÚÚƒ‡4:;‘8tÇï`ÎbÃ( lm-ŸËƒ G--=å °±,‹öövÇ!—Ë‘Ëåð}?|¦Óé°o4.ˆÅbär¹g¢ƒ‚ôÀ"=]÷w£ý÷è =˜!ú›é>o´=Ñ~€þ®K÷“Ç c¤R)²å*º¼Þ·îKé~Gúê0M3ì£÷o·ïûlݺõÐ.Ž*g¬íSÿö¹œ²Ähüƒ0 + Âa3^}[85'žó pűˠü •þ*#qT___ßDîpýúõttt°aÃV­ZUb˜çŸ>kÖ¬¡¡¡®®.V¬XëºÃ*ž+W®dݺu4¢‚!fÍÚÈÞï-+&„q¤¥¥…††*Ý”Q1œm¡ÛgGGhnæÙæ^°ŽÏ=¶òÛÕØØXâäÔøl6K[[[èðÑAÏóBª tÁÏL&þÉ ‚ $ú£*´7“É`šf¸­T*Ž(×b^_Okoo'—Ë…Î}-ÎhÇ­þƒ¤¨zŸ¹\Ïóèìì ²úTf„ô8Úi|(#8ô¹„âR}œ@ؾh$‰ëº£­úÿaÌårRJ%í*÷Xô¹ÔçW;É<ÈO~ò“Ãnsµ0Öö©ŸšïùpÝ;ቆ4O4—ýøÇø¾OOOÏ„ ÒÂaaÁÞl6KwwwÉ5£#²b±¦i’N§J¢´´óÃ0 ‰D˜†D¿ëè}ÏÐ×§¾ßDïZÑ‚v˜D.š¡"®Fâ_ÿýë´î¼œÝ›¦±ùë5ãvîàÓ›7ó‘Å‹ËÚuQ¾Þ¥ã4ÜÂ+``·«áé§™>}:ÿgî\>rì±aöLí»]ý½ïñ•÷½o\Žq"¯¾-Ù,<ý*ÎøÚ‰\»ð&^ûá×rå'¯,Y>Nãg³´é{f{ûˆÃÎs¹ŽãÐÞÞ^öqf³Yº~ÑÅw÷Ýa—ÓlÛæ¯ú/ýí%®~öê’e|ß§qI#­íEñ”#lóû6ÓÙ×É»¾ù.yî¾ùÅoRs †Þ£{ù§cþ‰÷CŽ^p4žçñúůç¬ÝgqÚù§±gÖÝð(8ùE‡h`ðÓ3Ê[®àuK_Çù§Ï–[¶pÕî«ØqþNœ~"ŸÙóN?útvîÜÉöúíA@ócÍüãöäŠ+®à™=ϰç{ø¿ ÿ/'žq"Ï=òŸØö jÖræÂ3ùÉöŸP{°–/½ùKüÿöÞ?>ª»Êÿµ…mIz%Eˆà…ÒÖ‰Z¹ml‹Ê‚]kE'qÕ®d]&]•ÕùìGjÍHVE?«fâ.ºuý’ÌÊ®»Z¨­­v´•Án›±µ%·„Ú’Û ´@æûÇsï{næ÷Ï;Éyòà‘äþ<÷Þ÷yÿ8ç}Î{÷û±ëÉ]P‹c‹ñÁÄqýõ×#ñpïhx‡Ù_eÿxã?"v*†‰‰ \9çJÜ|ÇÍxôþG1ëó³ ¨ NÞwŸ[ö9løÐƒAȲŒ!ua=ŒÞóϘøã¾k!>¼7¿t3®ÛxÞý0þ銫šmâÏ~³¯ž€n|OÅNáÿý8uÛ)Àüøõ?Ʊ›Ž™}ƒ×žz-º¾ÖÅ}[Ô·¯C ßøÆýxá…&¸\w¡¯ï/qÝu˪Ú~jÚÔÙ×¹Žïè0ª ¿ßÈðH B+Š‘‡‚.]×ÑÑÑ¡¡¡)ý:š¤ÀìcRìéé1»âñÔ7'9PŸž4 HtÔˆ¡´úýýý)…˜ÇE£Q¨ªjö ¨¿IcªKÅþqºˆW]×ÍÉL$GÓû¡hÀJµFïA–eÜ~ûíÜ·MCww7š››¡ª*EEG‡‘¢©Ü6Ù>ëz›ÊTžtmD½RѾ-€×耮Lâuÿò;üæíSûõQ&•°ÛV=B¥µµ---ˆÇã)Û#‘͇s¹\p¹\ˆD"yy;5óú›€è>ž:À¤¥X#×L “n¥é§ày?ðÀØ«ñÅä¡ š NÎôPTƒ,Ëælpú›.€aØ¡ÁP[[›9£Üèl+æ LQ”œŽ‹¶¶6ó\2´êº>Å)î:âìzq E$räÐ,yûqÙÈ%w:ÄûˆÛ<¦qÑ;*ûù™îUèlÒiz—t]UUÑÝ]¸ωTJ?‰û5`Ù ã7ÜbŒ¨$™DD£Q3‹f¥J’„ññq3ª#˜ºN¡àÁ`0%RÊ+m£21<< I’R ;Ci"ÓsS™õxðx é¤yõ¬ì–ñ•ž¯àÎÛïÄOÞùüÅ»þ»»Í™ôkÖ¬Á»O¼»Hp•n;uݘÛm;°té<<ö˜ºÞS“Yµ…Þ’Ž²œ(Ô-#çL `D®x½V4‹×k¥Pʧ©“$)c¤œ¸Æ’=-¦1‰Âpòx<@[àvËðû¯WI9Çø:zzz°oß¾)m°še±Ç“r¼ýX±nJ)ÛßßoêV&È!#– û}ìcƒl}°ùó‹M ì,*©Ÿ>ŸÑæÔ JM^`·gP f†Q©¾-Ñô pɪ³¸¥Ý_Œ}ƒaªMÕ*.— ÐØØ˜²=‹Mñh666¦m`EÆÆÆÐÝÝ içNè:ðÔSA£U«@~LšQF3fê qMz2&‹³ý)µJ4M1xÒ šåKÆ,1ôÙãñ˜Æë|ß§8#GœeN¿ƒA ™”žˆf?†QNL5D†4šÝL©^h¾8cÉãñ˜²Ó¹”¾ˆf4¥Ëõ‡ñ½ï}ãããu?ƒȬ›@ñúy÷Ýw7Ý„EÏ®Á»š.B¾P´ \Hßìáð4Œ ä,¡4[RÊ£öOäSVé8š)'IREyk-±X }}}Ó&-B¹õóرcèîîÆúõëÑÕÕ…KW;`ß>ü¶£·}úÓe/TŸŠk‹PĘØ‘sQlgiV)E®P .]×ÑÖÖf:Ü}÷Ýe·ÛÖl ;S¶å³¸Ñ²eËÌ”_»v=‰% Ž=(i­ÑðN†õP(dÎ’·Ãá°ÆK³dIùÅ|íd8¢tEâšöÔrAaÇ4cféù|¾”´&4sŸœ ”+¶­­ ÃÃæ3Äãñ ©©É¤‘á«££~¿===æ"»š¦™¿SX¶˜/–òä’ƒ‚žÒˆ lS(µÇãIqˆH’„ÎÎN Ãï÷£³³Ó&g4뺎ÎÎNsÀKNrê‰d¦g¥ðnÊk/þ'£Í¤çgѹÁ`ï|ç;Ñ××W1½p Åêç»ßýn<¿f \?{s/x[^÷#GZ¾¹3é*#¢ñEÔ×R ĹÖp`œƒËåÂÎ;§M„J6ŠÑÏææfìܹÓc>þÿG·!½ã±Ð:#öÜã”nƒÚt‘K¢aSŒ®×{˜>?ýýëá_v]­E©(]]]hiiA$©µ(¥ä¾­üë=cøMJ5Âøý†e12¬Šª 9SZU5Ž!×–J·XB(dY2Å)ëD `\S<,œe¢'ÐSð9oÿòÛ3Ö[™ú×Gn>÷Æ©ízºNÚ•£p¯›zN&g]+]ÿ!]”¨™vHŠbÈ=u}›L*UUщNô«ý9ïCx½^t„;à•S¯¹sçNôõõM›Yð™(¥oÛÛÛ‹`Ð0þ?ûì_ãî»÷Õ•#…È·[+ËVUçy(¯»!Éùü,¨IYtPC=ÆAOª%°¬©bMÓ,ë¡Øž'8…Ûy ;Y3óÔïbú Ô.ôœluNºu,ì}è|ÍŒÄÉW‰Œ¿Ô­Î”VÉî?¾€Ñ÷'k²&)æ5Oš[ðû¬7Jm;àcÛ5%ätG,f¤>ªšZž©\RÐÙi ³‡†¬·ÛØçñXÕƒ8LÌ” ‚)Á ñ ÈÑÓc\{xØrvˆ¾dr\H’¥?Àçñ¤F×Ö5ìÛDçŠ9ĺ‘®A÷ëï·¶Ñ5DçÕÅ”JÎ㱎§ªTÓ€_ÿúµ.§ý ÿÐÿ[ {SéNþÂpž(°Ò}‘ä'¹- Ë£ÀŠ@ʺ@Ïó@§Çø½ãW–FrÃaQ9è”fL”Oƒ1#Ø,Ãè¤`,R×!Ü4,\ËŸïUÛš I€÷íçÑ´fÒœ—à™wôÍ·›Ž2·¢!zçÿ@¿¸ÞÆï!ôÊç† ϧæ@ßõ$¢¾ Ú¥ ¸?ÖIîºë=X·.¿~[½RRßV7†–»w÷•fj¦ F€Ø»õv'L!H’¡›â ÑÑ“.•Y>™zEyн†HºîT¡rدÑÖ,_þo*îåÕ ¥èçÐõ° ô™ÈÔÕ•a8,‚°ÒƒÑö ×ë_˜D„`â–ù.Àó’í:™HF¾@ƒá$,`e` $!ùÈ‘BŽ’¶äöaXN))`8yþ(,g‚ÃI@× sdŽ$Ï÷Ã2¼Ñ;Ô„ûJ˜º¨9K(å™}?G)Ù<°œ=t:¦-¹½_8Ç/\³'y/E)Ýýh#§‘G<&Ý3‰N"XǼ{gSÓ‰Rt“Мx8Üt+MM _oé3™™‹c*íí혘˜@$A{{;b±âñ86lØó\rZÿbl!Þvj) Gž áÙó %Ÿ»çŽfÈ/½ú¬+0ú”5ã[ýãvøžý,”7œÃ¾Ø‰à'FáöHp÷¯Nýîÿ÷¬8púÿu6ö©¦ÒdÌûÌ|¨o>ù¦¥p{n7×¹I’ÑjKÒ£µý²Œ@ÀØ74ô.hßxþ»»áV=€¢bÁ‚ œ8á˜abE(iì–,9ŠK—¾²lÚZC0ÚTš8-.©ÄÔIîÔÓ Á²ã‘mS®XöM%y<„¿ÃV)f,ÏI7"Ëb.;EŸ2Ø·èîþC­Å¨8Åêç‚]Ý(?)áæ*¦Ñs ZX<ÉÓâ×%C°ô1+ù,Ó+ÛŽ³;È1B7KI «bQlûÒ 'nKgFR²/Þ3C°*ÁL2xaUt]–ÃÉþw&yòù¶jŽãíæ¼ä}&.™ÀéÈiLgJwFt]üö¢ƒ¸á7XÛ“Ya8S S/8ª§ÜÛÛ‹-[¶ µµ###èííECCC^çJž{n>Ð:vL“®''IJ:1($Åáü}u:ã’$£JâJ‰d‹„œ0^]::Œ:YQR§±P‚ZãkÄì@ó=2†©JÑϧO,Ä«n¸!çq´ž‚¸<Ã0¹)E?U¡?΃úÕðùÂ§Ý ‡Ãðù|p»Ýèïï7×RUuJ;ÀíBð;šV­›÷܃+•Wpî즔ÍÁ Ñ¤n(uAÍìYRjö ·7ƒ=!ÙĦëBŠÛÄ´;ê†Ù)kˆÇóN–·ø¡ÀÊü6™©¦ÄkS1O×Ô«MП;—F$Œ>Öûózgï¼i!¼îqͦóH¾o+ôPêÜ'cŸ„þ=¯FÇ­Ÿ‚û¯ïéóWCýèIS¦”™êßœ ]_IZß]Ï ÿÿ°Ï——Ác¦“Ì©(€.ÉŽÌ1¥¹@)™Õ„|d”rÈxÞKµ(Åûßÿ ÌŸ_Þ…;H±úù €Ý·^†Ùoû¾šÜF§Ã°œ%ä ÑaM§b-Æ!’ý“ Œ5T Å,A”íFܮØœ­bj–› ¦Úû(“VÑ£$°tŽXáttX¹tÝiÔ¨Ö½í ªN• {ÓO{Ür 0µSÐÙiubh¥A±CB+%¶ß­¸Ÿ®™NnjÍi‰¶w'v2ÒÞíï4]ú1ñ[Z ï¹ë.oŸ>ƒÎtº ¯ŸQyÉ|\|Í5Y£´wÙÖëa˜™N¹õžŒÊäCXÑó©¢B¬iý0€éeÚI¦î(gß6tðMøÀœDõ&³{ÒÓÜ î!£m½F†5`0 -ãV¦ êE‰3ÙaöºÐ=Fæ –1VÌàXFQ¸Ô<£³mu¤‡3qÊ—€˜:YVLå.Òpûå8£MMµNòLé¡ÉÀM߸çå+Á‚Ìp§7(cm þ5 èRò>olÞØh¾/1ãH€"÷½í ‹qp¹•®žŽµ? É©ð?µZò[Øß­ø]Ä÷Ðùý…Ê©kG‘Ùx ¸ñSsL¹è<ðø¿}H5rK àï·žEs»Myºé&´Ÿ;‡éB¹Ûί„W½üô+ïÅÚË/OÙg¯½• ¿g«å3L~žrž¸½˜¹¼Ù²"QyÓa”]1[Í´'§ !FåP&(¬%+ì×÷ÀªKÄkP]D‘; ¬rMËž“SG‘Šú)NÂ'GÝG|gâ>÷¥ûPÆ"ñÚ“sª°Ö3Q]@™ÄLC´ƒøM춨mÿñåË ýÔŽ¦¬ú? åÁï"eá±@råw²¥Ø'¤z<é×û¢pE]Ÿº¨¢Xvû-Ödÿæªj9Äìö4ñˆ‹.Ñ»!yì/'¯¾sŸz*w9­#*a·€Ï ŸÁ-¦l£µ—yb-S/8*B@Ñ ×¼ü"°ZÍkv'¥öêìì,Ý€›î~öJÀþ79%£ñ ¤ÎÔPdŠŠÉ5s¸¿ßjÒ9Ä…CíŽÀ8·£#}Ç!6FóÔÑÈätèè0ä'g‹Øø¦ƒ-t?{îx2.Ñ;³7ˆÁ åp¡oa~Ñ D ¯è Ò4ë¾ÔøŠû)99½7áÛ?ò–·` fÅè§ àá•»ñ×RkÆcÂá0ü~?ÏH`˜")F?£Ž<eÙi貌þþì¹hMJS‡Íu¾†IO1ºù«‹¯Ç%ý+ðwMÀYXÕ xXæ"9{]Ðe ,[FX2þQ:rÑøI©‡k6}FjvÑIB?SŒ™‡üdèÔÉö"ì &ÿ¦ÔH€5«¢20G.,ãJÐ ¼` S³Ÿˆ³üEgÆ_ËVf2“œQá¬Jf{©d›ëaŸyMÐùbȃ©³áÓÞ…98$ÛOñ~ªí§ý÷|)æœlÏmbÊöB)Ôݬ"õeº†ý™íÏãŽ##3AbÊíoÿNÏ ‡J¡nnÆeóN[3hÉ9"†l4h†—0ˆχ€]jÀÃð\¿aQ§Bõæà, kèI¸?9ëÛ›¼ö_v¯¯S€?F-~@v…£Àù à ¿×s0ÆaŸP,Û?û€Ë<à}ª11 ãœñ0p" Ü®»“ÞS¬ÐŒŸiÀ[å©^˜¤÷$]Š0ú=]Ï‚¾vìË:äK&Ý̦Q¤:@rAÎLÑy=0ôɾdEÖgÌ2¤‡`9;µäïÝ¡ðîwñ–¦?ÊCzëkËs±ruÓØ)hR}›ÚÕ•órnHFƉ™bW@R×P-vè\š,@Q—¦£Ôf‡‘è² åg?ƒ¬()“0(º-å>öTjõŽ¿˜ÞCè–Ÿ~ —c‘mŸg:•fÚ3-*0/ ?úö¬=]×ÑÑÑÀZwFΆÏåìÉ4ÓXŒÉ¥í¢¼”õ†½Á§¨1 8SòœÌ‰Aü~?;R¦†„ÿ xǵsóÒCZ%šÑ,Â0å%ræF\6KÆ¿}û\7´Œ»LIdêõ+Æk-\r¸¹óW‚úfÕ˜bî€d>ýP0™ï)¹°$Yy 4ø…|H'Mœb³û 0i+–FSÇl[Ñöâv²¶ÿ( ¼W~î±² |VˆÆU`5€ûU`1€Å²å)Ý {’ñ÷9ð’Çò|]N… $àˆ|hhW¬¼K}Àh8ÜÿZè²ÂåvC!`¬‚·زäFÜÛ\«§¬W€×¹-‹®à>p«<¦Ρ£*ð7I§ÀHøq8 àºäþw¨–}à™0ðïaà˜Ì”×JP>4Œ† W†Ç\*-:°8¹?i‰–FP–*À†e¾â7C`úe;}Æö±ä=½*ÔËT+”æ>°@Î%S © ðvzó‚üoò­ð¢ ïC:ðÝØÿ—¸¢ÖjàXüç¾|f¨ô Õ öž;õÈUä·¾½в¢9¬ ;ÀrÐPtUèæ›MgJ©é/)RML¤úŸéš@j„˜x9uLuÁv-:—R}JΡˆ4Ýv1u'E¨‰ëE‰UV”ÿÊÕWãmû÷—øU§? €Ç'/Ãê†ó)Ûg¤m–©k¦Cåà“ÏcÝ+—å<®¿¿º®sY¥™n^{ö”Å©¹s1{Ö øàÙï#C%# åL3Ä0LåˆÆßòçœÇ…B!„B!øý~sÑ@†aÊÏU ǰdÁ/±ìoÞÄΆq“¼ã?>‹wÝü.Âè %ŠÞ·/ýä+3­Pž7ÉYŸi-Oêq潓ÿɵv[º ËÀÚ c·!$ÓŠ‘ãÁ–éÀÃzùSðe°D¶¬’bN­ë<ÀFpe˜ ‡Ž˜“Î ÀÕì×€§tàƒÀß+ÀaÙzŽ&øuø“ |Qâ²åˆèp´hóWIÀÛüNFJÞ$—l8žáTzF·Î—“û¡™£QàVxZدHèÀö`£¸Ar2Á¸ÖõŠ¡´:9î‘d`pÌ™¤cë$€ý^BjàI ˜'EûCÆw•„óŸÔ1÷W±< Ò äÃùå¥dÒ"Z<” Ûüª2r^`T#€UˆÎ J©ÙÔ4 ~Û1éÖS¢c)N‡Qí Ãr€3„Ρtƒöš”TØŽ˜Ñ-\‹dÓ…þËÉ“øýë__ñï4øZÃSˆ^yeʶhºµ©ÆÁL ‡Š uÞ(Þqé½H¿„¥Agg'ü~?/rÄ0Uâps3Ž÷_x-6Úö…Ãá”Ŭ†©>Qê9à7s~“µm$gÊp2í!G•1Låxñâñ««¾ÿ#çNýÁ0LuY¨éXxò 4üxПl7i-ÌéŠèßÉèБÓoŸ‚­ÿ@–O dà6ºN†Dw«Õ©9ì€ä¢B£©ÛnµŸŸ)™mÿmÉ{¥Å) ÆRr¦‘{mŽ÷—‚ÜšæÅ™9üì|hn“îž:r2ØkF»Š£Ø~ªíºj–}™½«Â1žÇäÚgO¡Iœ9r‘‡nb ÍÆ) øï—_‡7¾r %R–í´L½1-*€ý;—¢ëB-íþ@ €h4Ê©…¦Ìñè NÙ®( ¼^/G‹1L Q¨/ͲžE£ Íœ Skx–Ã8“ãÇÑqú(°Rbãm9(t-‡Ã0 ãxQà…YOáÍW\Ê1‡¹ïËÔÖZ€rqê¹ÓH¸.M»OUU^ðšajÄ)}.zÍ”í¬“ ScÎ>„η!gÔGN“É0Õ‡ÛG†q&ÇÆ.Â;'ÿH¬£ Ã0 S€Ùó›æÃÚ–Ó.Ë2g.aêŽiãP9qn.f½UÚ}µaf,'Ž^‚Æå©Ëžn0ÆœøÕ \7û(dYž²`4EGG4Mcã.ÃT‘ãÇ×Z†a2°¡io¹hiþë¡0 Ã0 Àp¨¼ôïÇqõ‰ûR¶÷ôô@Ï’1aœÈ´p¨D¬˜|‰«®JÙ®i‚Á ™óa˜êr¸¹®ÛÎãèÊS)Û5Mã™ Scš{ ''ϦÕGÒSÇSøÅ†)šùó磿¿¿ô 1 SvÞ4ö<ÎK³yák†a†)‚î»ïµÖ¼ŠF£èïïçŒLÝ1-ÖPQôÎ~ 墔횦qª†©!§æÎÅþ¯7à3ƒ–±6Ãíæi} ãN>uN- ŠÒ6eŸ®ëðz½E\•a˜R¸øâ‹kÞwÕ4Í”rZS¤š¦ifäZ45ªªj¦ …BeÙü‡Íëɲ ŸÏǃ`0UUSî'ÎP”$ɼW(‚ÇãA €×ëE0„Çã1·ƒA¸ÝnsOOÜn7t]7¯C÷×4Íô÷÷ÃçóÁï÷£§§~¿@ªªBQH’dÞ›ä‡Ãæßt]UU …àv»Sd¤ýŠ¢˜ïE¼¿Ûí6£é=Ò»$ ÑhÔÜç÷ûáóù044dKQÀô ô>h?½I’ ˲ù}iŸ¢(¸ë®»ÐÞÞ^Ó2èTÅ»ÑtËZ,©µ Ã0 S‡œ~ñ"õ+æß@§æ}_†)”iáPß |?ÃQi“¹- !ó ?†©!³ÎÍÂÒ‹S·qú †qQW·.‚þÈï ª¾”}š¦™B†aœé,94M3ødX·ÿìéé1Ñh4ÅàÎ rxD£Q3r äƒ)Ó~ŸÏg¯ªª9h¦~€ªª)Çëºn:@ìÿUU…$Ip»Ý)ÓóÒq´hhÈÜGŽr0?ªªšr ›Îdú†††i„=yoEQ ˲ùS”‰Þ'ʬª*t]7'˜ã‰îGŽ¿ßoN,§Š¢(fýL2““ˆîE×òz½$iJªU*3´Þ;ìß¿¿ÖEÚ±<÷¾ç ßÎF†a†)††+^L™DãõzÙ>ÄÔ%uïP9qÅ8õðæ¹oNÙN†ajÇUOœÆÂQs€ …ðb» ãt~¸ ùHÊö`0MÓL"Ã0΂"DÈyA‘ ´"¨­J1°ÓÏþþ~(Šbþ]Lô(㩾 ¿é§= ýoê«‹ÎÛL}:–®A?é^¢“† (Œt×!‡E:ìõ¢èI'S&ÙsõƒÄóóψûzXÙÞ§øÞÅó,Xóž3• LyÇ Ã0 Ãäfÿ·ŽàÂù“f( A×u¶1uÉ´p¨¬x1Ž”?Á‡B†ŒÈÑîûÃ}ø®ÿ¨µx 3£¹þ[Oblt’ò^øà÷ÿ7ž^ü4‚bÄÔQD¡#ýBd ””c†)OOLâ–w[XšÉÍiùÆYˆNÀp@¸Ýî”HŒæ»v ^†a˜™†Õ(¦¯¤hK1…¤=rStp‹‘štE¦K )¦x$2EÒý(í$¥›¤ûSÛ/¦fï'ž Ík0£í× û¥‹`¥(I1ú“žWL79<<ŒŽŽøý~3*–ä°§™Ìç¾éÎ …Bðz½)é,Å祔œbêÐ\ï¨\²ŠÈ²ŒÁÁAlذ¡ÖEÜÑ\üº%XùÞFÚS„¹%‚#WAÈÓÚ|4hðÃ7ÜðÁȪà‡?íõµä¿\¨P¡CgSuïPY86†yCûñ•»¿‚zðÓ å9›×mFz C† QDM¥Ñ AAöA¤QDsr(ˆ"™{X¨(РA‡ÉÜÇÉ}é®'A2ϱWRòŸ $ÈÍ{ªPF8í=õä?ñ9ùŒ×*TówŠù~èYìçˆ÷Ñ ™ïT|Wa„ÙÎÎ&.ǽ OãŸÐ†;^ºïüþ;ñÍ/|ÐcÍÒÀÒ ÚFå1TÆ©, Õ¤c¢ÞÖ+Td«ëÒu"è}’s‹t™êú¹êP§p⊵Á±DŸ8‹m×þ“‚Q5 âÊk¯„®LunR]Ï0åàȲ#X[Zk1 õÏöïßýû÷cñâŸÙ3˜uqa³ŸÆ0Ìô„úkÔ7+vŒUë1š˜VÎni=&Sædj>Ú/¦¿£µRÅst]OYÛ)ݹ'Ä+Ç_ÁuË®›rl¦sì÷Ë÷œ{Î߃.ü`Æõ¦È`.¾2æêºŽ#WÁãÇǪU«ðÄOà«?€ãÇ×äûÕ>øE4,>µÍ/6C‹j˜;w.`Μ9€3gΠµ±8*¬ú%„ù~Äs4h"hÞÓ ·yñþ2d¸áN9G|7ô B¥ØE¢ø}*Ùï¹`rrr²"W®Ÿüð'ñ«ûÜXrÿ—0,Ãçó™!좠Pá@qF§BÅ(:Ñ9ePLŠ':<29?Dç ý.žEÃÆ ¬€ 5­“Ft)PBn¸ÍN¸XÐÓýNŽ?üXiùö žä¿NtšÏ•é^t¾^(PЃž¼Ï釱®Ž>Óá…xÌíÑä?’}CС£=)rÀØØ~pä¼x§H$‚ÿì‰â;7žÆýßy$M2g˜0pµ&ßFªžÈwfÆLàÛÿˆ{>wO­ÅpÝÝÝxä]Û±ü“ÿ…þz~ÞúsìNìFÃùÈ’œq†ÀcLyˆÅbHÜ›ÀÖOn­µ(Ž£»»÷ï¼ <ûûgqæÌ¬]»6ãñµrtR?‰>ŽE‹áÀX½z5öïß•+WâÀhnnÆøø8šššÌkÌ›7GŽ1¹æškðÐCaÍš58pàV®\‰gŸ}óæÍñcÇ0oÞ<444àÔ©S˜?>Ž9‚%K–`ll ×\sÍ”û>úè£X¾|9N:…yóæ¥Ü÷رcæ}í².Y²'NœÀ¼yópêÔ)0§ç£céçòåË1>>žöœyóæ!‘H`É’%iÏ]¹r%ÆÇÇ1{öì”sÏž=‹ææf9r‹-£>Šk¯½GŽÁ²eËðì³ÏbÉ’%8räæÏŸsçÎ¥Üwþüù8pà€y»dÉ’¬²Ò7ÉçúöGÏÅe-—ᢱ‹RÞã‘#GÐÔÔ”ò ÆÇÇÍïøêù¯ÆË¿Œåo\ŽÇolÄÁ8ü‘õVÇÑÝÝ;wšNµP(„=+°zõjÀÉ“'qÙe—™ÇÓ¤T B¥óA‡Ž0Âp#s„·h_I×VV q­h¯!YÒM®#Ûµ‡Bž{5¾;ûóæâf~â ˆ²]?[cšŠ¢‰"Š!T.oý ¬0TR˜\xàAá))š2¡CG:Lƒy>Ï£A3 S²FØTÂ|Ï "hz2U¨ư)¯ÝtíÃ>óœæ}Èé#>ë×~ñ5ÀU‘ÏU÷üéÔ%X´x’ö~ô÷[eÎ) §ÈÁT†î?u×ZÇ2ïþçðË<…±ÖïÁ /Ô{Tcý1©>:µL}sÉÄ%ˆœæY|™Ø‡}èhëÀÐÐPÝ 4ë‰t3ý9 ÏBÓ%µ–™\ræô£ß4JPZŸÏ—’vFŒhÐ4ÍØwPƒºR…þšd„ðêäEégºwNÛÖ$ª¶s²œÛlûi¿ß[³<è’ ç¬¶]3™Îi*á~ YÎ]i{ž&Û9+³œ»Úv ýÌVþ› 8'y¬iL_©¤?W¤9ÃßÉ2ÐýËnà#`2àóù (JʸpY꟥d7˜.¤s*QDÍývã&M̵ÏhgÇ “À80Ò÷M¬™ :{:áv»ë¦Ÿ[ŒÝ(ßzF¼v¡¶d)6Ê|d LEôStÂd’9Û³d’¹˜sŠyþXaþEx¦\§/Ô”yžã*ñxñx---hiiÉýgŽá‚åÖ¶¬3Òµ/xYÈB¨âÆ]*trVµCƒÓBžGŒÉWT¨fÄH¡çˆ!n$ c>øÐ†¶)3Rè‘CÅþ¬ &fÎÂ…êç#׋.˜ ¸Ån†ÉŸBõóÌ‘û°låaìÃ>sðY/Z†©' ÕMÐ5^¯—u²BdJ¿Ë6ƒ‡Çž1•BõsÞéy!›í&¥yêïïϹX=é3/j?óà \ÅQ¨~†B!¸ÝÕ‚lm^º}4„“ÿÄcÈùBéÖD§J®(vÂÔ'ÅômµCÞÿ×øÐîQsý ÖÕÚ CFaÓ¡Rï:HxdW.Ä~] Žr¨ ¢¯¯­­­Aoo/ººº²ž3öŠŒ%xáð$$I‚ßïÏónΠ7:ÐQpxi¡È@ ïè”bQ¡"ˆ`J¤G.üð#ŠhAIªò} /³¯£#AB?úá…wJeb_'g¦RŒ~.mø>>"===y/’Ë0LᣟǞ¸zË„™×›;´ S~ŠÑÍ—_~­µø 3­)F?˜ «ªÊ†¦B£ŸÑhÔ\sƒ)?™&Úfr̈Q,a„Ó¦¤ÎjwÎP$)­ã X$œ°Àø„kí£Ó?Uf±mçðØÑ°ü ܲ| |›7›©à™ê£@AAs¹ƒJÛ¡«ñ<RÒWG9Túúú°cÇ´··#‹aãÆhooÏêñ<î1¼ý / >èÈm,ƒË•;”㯸<Þä?"‘H`bb"o¯r¾ø“ÿ Áüg'Û;Ì'Í—lNžLŠ7 6j£Ÿ¯¿ìõh¿¶‹<‹j-~ZòÕÏZÇÑØØˆ†††Ò/V*U0…SŒ~.ñ¼ë-kÐÙÙ‰}ûö9jÆl=”-®?˜|(F7/¾øâ¬‹¬Ö Ó© :]ßóe:}“rPŒ~þþ÷¿ÇóÏ?_·“ø.ÓÎcº|“rQŒ~Ö»^õÑΗS±SP]ÙÓÕù~“H,‚ȱéŸÎ¶ݼôØ¥8|ÿÜ ?Š? >•WTg5qz[RîzAbÚkÅåK¡–m˜ÞœNœ8—^z©¬÷½°&O›†H$‚ÆÆFs—Ë—Ë…H${…4þ|s&‚¢8/”¶¯¯¯Ö"deddƒƒƒµ#+N‡3bõóÔ©SøêW¿êHg'àü²588ˆ‘‘‘Z‹‘‘z¨?fÅêç«oº÷ÜsFGGÕ¡ê£lqýÁä¢XÝàÈ>m¡L§2èt}Ï—éôMJ¥Xý|Ë[Þ2-Œ¶\¦Çtù&å ”ö³Þ©‡>p¾L—2=¾I©«›¿Yxçò&ÜtËE‡Ãùܪª8½-©DT…å –úNi{U¨Sl>öØc8xð`Yï똕X,6ÅÛÖØØˆx<žõ¼?ÿùÏ8yò$¾øÅ/ÖúÒrìØ1tw;wQäÓ§OãôéÓˆÅbµ%#N~‡±X /¿ü2V­ZUkQ*þœ…êçƒ>ˆ?þñ$ɱßÏÉe ^xáD£Q ÔZ”´8¹þ8yò$ÆÆÆpÁÔZ”ŠSŒ~:tcccXºt©#uÀÉe‹àú£xŽ;†cÇŽaõêÕ¥_ÌÁÛ·}ôÑG±fÍšºŸ©ìä2X(N×÷|Éç›pß6³~>ÿüóøÑ~„»ï¾Ë–-«õ#”ÄL*ÓõB®oB}ÛW^y¥Ö¢Vœbû¶kÖ¬ÁÂ… ÑÜÜ\ëG(šzèçËt©gòù&Ü·ÍÞ·=}×éÁ½÷¾Y–ñÙÏ~¶Ö’‚ÓÛ’z¨œ¬ïcccxþùç±aƲ^×1•‰‰‰)Ûò gÚ·/ÿ5:†)Žbôó3Ÿù >ó™ÏÔZt†™ö£Ÿ¿üå/k-6ÃL{¸oË0Î¥ý¼å–[pË-·ÔZt†™öpß–aœI±}ÛXì·µaÊŽcR~566NÙ–ËËÉ0Lu`ýdçÂúÉ0΄u“aœ ë'Ã8ÖO†q&¬› cᇊË嚢ˆÓe1.†©wX?ƹ°~2Œ3aÝdçÂúÉ0Î…õ“aœ ë&ÃX8Æ¡ÒÞÞŽ‰‰ s1£X,†x<^ög Ãë'Ã8ÖO†q&¬› ã\X?ƹ°~2Œ3aÝd Ǭ¡½½½Ø²e Z[[122‚ÞÞ^444ÔZ,†aÀúÉ0N†õ“aœ ë&Ã8ÖO†q.¬Ÿ ãLX7Æà‚ÉÉÉÉZ !ÇÇÑÒÒÂac ã0X?ƹ°~2Œ3aÝdçÂúÉ0Î…õ“aœ ë&Ã8СÂ0 Ã0 Ã0 Ã0 Ã0 Ã0 ã4³† Ã0 Ã0 Ã0 Ã0 Ã0 Ã0ŒSa‡ Ã0 Ã0 Ã0 Ã0 Ã0 Ã0LØ¡Â0 Ã0 Ã0 Ã0 Ã0 Ã0 “ƒ‹î¼óÎ;k-D½Ç‹ÅÌŘ2í€ÆÆÆ‚÷—“X,†¹sçbΜ9Ž’/‘H "‘H`Ñ¢EÉPÍ÷ÇÔ¥èg­u3j­ŸN©_²é§“ÊV1úYkÝtÚ;d¦•ÒÛZ•ÇJèwµŸ¥Rí4×õE%ǤNÒÏRõ¯šÏRÉ1.ëg}QÉ1i-ÊB%Æ®Nj;K••õs*Nx'‰DÏ>û¬cÛ§c±8àx»mÕmk“LQlß¾}²­­mrÓ¦M“ëÖ­›|ßûÞ7911aîßµk—¹¿­­mr×®])ççÚ_N:4ÙÖÖ6ùÀ8J¾‘‘‘”w¸uëÖ¼e¨æûcêRô³Öº™ µÖO'ÈÇÔ/ÙôÓIe«ý¬µn:í2Ó‡Jém­Êc%ô»ÚÏR©všëˆú¢’cR'ég©úWÍg©ä—õ³¾¨ä˜´e¡cW'µõøMœŽSÞÉöíÛ'·oß^°|Õßécã­[·N®[·ÎñvÛZØÖØ¡R‡š\µjÕäÈȈ¹mݺu“Á`Ðü[ü###“«V­šñMLLL®[·nrÏž=yÉPÍ÷ÇÔ¥êg­u3j­ŸN©Oré§“ÊV1úYkÝtÚ;d¦•ÔÛZ•ÇJèwµŸ¥Rí4×õC¥Ç¤NÒÏRõ¯šÏRÉ1.ëgýPé1i-ÊB%Æ®Nj;ëñ›8Z¿“]»vM~úÓŸž\µjUZ‡J­¿©ÓÇÆä€$O:y¢ßµ°­ñ*EÇÑÞÞ—Ëen[¿~=&&&‘Hhoo¸\.¸\.D"‘¼ö—“¾¾>¸\.´¶¶šÛœ _$ÁÄÄ6oÞ hhh@8ÆúõësÊPÍ÷ÇÔ¥èg­u3—|ùì/ÙôÓ ò1õK6ýtRÙ*F?k­›ù¼#ÖO¦*¥·µ*•Ðïj?K¥Úi®#ê‹JŽI¤Ÿ¥ê_5Ÿ¥’c\ÖÏú¢’cÒZ”…JŒ]ÔvÖã7q:Nx'­­­èêêJÑÃ|嫆üNÇãqtuu¡¡¡Ìtdl[3`‡J´··cçÎæß‰D{÷î5 W,›’÷®±±ñx<¯ýå"‹aïÞ½ðxðÀ)ÿ:dÓÖÖ6ùÀLNNNNŽŒŒL¶µµMNLL使ÜlڴɼŸ䛘˜˜lkk›1ÿ^·nÝä®]»ò’¡Úï©JÕÏZëf>2ÔZ?k-S¿äÒO§•­Bõ³ÖºéÄwÈÔ?•ÔÛZ–Çrëw5Ÿ¥’í4×õC¥Ç¤NÒÏRõ¯ZÏRé1.ëgýPé1i­ÊB¹Ç®Nj;ëõ›8§¼“M›6Mnß¾½`ù*-¿ÓÇÆ$]ÓévÛjÛÖØ¡RÛ·oŸ\µjÕ”ÿ¢‚îÚµk²­­mrÓ¦M“mmm).ŸýåÆ^°œ ß®]»&W­Z5¹iÓ¦ÉuëÖMnݺ5oªýþ˜ú¡Tý¬µnæ#C­õÓ ò1õI.ýtZÙ*T?k­›N|‡LýSI½­ey,·~WûY*ÕNsQ?TzLê$ý,Uÿªù,•ã²~Ö•“Öª,”{ìꤶ³^¿‰“qÊ;ÉäP©õ7­‡±1é ÝÃÉvÛjÛÖ.˜œœœ,k¼ cÇÇÑÒÒ’6d(×þ™ Ý£±±.—« jýþ˜úÆéeËéúéù˜éI=”­Z×¥´Ny‡Ìô¢”2ç´òXЬÕ~–JµÓNû&LiL—²PªþUóY*9ÆuÒ7aJgº”…zªgX?«‹Ó߉ӿ©ä‹Åbf*,§ëw5ß!;T†a†a†a†a†a†arÀ‹Ò3 Ã0 Ã0 Ã0 Ã0 Ã0 Ãä€* Ã0 Ã0 Ã0 Ã0 Ã0 Ã09`‡ Ã0 Ã0 Ã0 Ã0 Ã0 Ã0LØ¡Â0 Ã0 Ã0 Ã0 Ã0 Ã0 “v¨Ì b±"‘‰DMåˆÇãèëë«õë`˜š‘H$‰D‰Dj-ÊX?'S­òI:Ê0L}RL;[Íöëf¦S踔õ“©Wêml囑ˆ“ÇÎ SÏÔ[ýä4Ø¡2H$èîîÆ¦M›pÇw`ݺuˆÅb5“'c`` Ö¯…ajÂàà Ö­[‡;î¸[¶lªª5ÕG;¬ŸŒ“©Vù ƒèîî®õã2 SŶ³Õlÿ¸Žaf*ÅŽKY?™z¥^ÆVN³N;3L=S/õ“Sa‡Ê €<Ž¿üå/‡±aÃlÙ²¥Öb1ÌŒ¤¯¯ápøÃàr¹xVÃ8ˆH$ÂK†©cœÞÎrÃÌdœ>.eýdf*NÕM§·é ÃÌ\Ø¡R#úúúH$Ð×ׇîîn ÐÝÝmî/•D"ÁÁAôöö¢¡¡°yóf¬_¿Þ<&‰¤m”H†rË”Nƾ¾>žiÀ8†J–ýD"—Ëeþ½aÃ3|9“.Š2UºÎH'/ë'ãTÊ]>‰¶lÙ‚ÞÞÞ)ûœ¢ŸÕj›&…–õZô1³µ³…^§Üí_¶:†aJ!—N9¡ Ëg\ZȵX?™z$]ÙÍÕV:]7ë¡Mg˜rSmûL5Æ€lû) v¨ÔˆlÙ²p¹\¸ãŽ;°qãFÄãq¸\. bëÖ­%ßgddàr¹RòNŠÅL3q°uëVLLL ½½‘H¤ì³‰6mÚ4¥¡d˜ZRɲßÒÒbêa"‘Àž={ÌÎj¶YqÕª3DX?'S‰ò¹uëVtuu¥½žSô³m3Ãd¢Ð²^‹>f¶v6_*Õþe«c¦ré”Ú°|Æ¥ùÀúÉÔ+™Ên¶¶²tÓém:ÃT‚jÛg*=dÛOá̪µ3™õë×£«« Là¶mÛ ÇÞ½{K¾y,7nÜhn‹Åbضm›yïÞÞÞŒeKK‹¹¯¥¥¥" ÛÚÚj>7Ã8…J•ý;v`Ó¦Mf§¹¥¥»wï]êÔë'ãd*Q>DZcÇŽ´3ßœ¤Ÿ•l›&…”õZô1³µ³ùP©ö/WÃ0¥’M§œÐ†å3.Í笟L=’­ìfÓÏzÑM§¶é SIª9þ£kVBÏØöSìP©!---)‹^@û>"‰d\$oóæÍSbšm°aÃlÞ¼€ÑaìëëÆ ÌÎL´··›¿g:¶P™ˆM›6!‹ÁãñTöE3LT¢ì' lݺ6l0gÖôõõaË–-عsgN™ªQg¬ŸŒ“ɧ|Röc±±cÇŽ¢eª¦~æS?1L¥(¦¬§Ã‰í,Pþú(OÃ0¹(¥m¨‡q)ÀúÉÔ/ÅŽ­êE7Ú¦3L%)¶O\©1 Û~ª ;TêŒöövüùÏ.èø³a EêëëÃÈÈHŠBVK&¢µµíííèëëC{{;…˜º£Ð²¿gÏÄãñ”Y5;v쀪ªˆÅb ­dýd¦#ù”ÏBÊþž={ÐÐЀ={ö`Ïž=æL=º~9ÚÊt«Ÿ 3S¨E;[îú…äªEÃ0•¤ãRÖO¦^©æØÊ‰6£bäªÅØ™aªA¥Æ€lû©.ìP©3âñ¸¹Ø‘t¾ÆÆF†wŸ”¢Ü *A¡d{÷îE0䙺£Ð²ǧÌT ¿'&&!#ÁúÉ8™|Êg!e¿VÆ’bõ“af µhgË]¿Ð6†™nÔb\ÊúÉÔ+Õ[9ÑfTŒ\µ;3L5¨Ôm?Õ…¥Ÿæ¸\.´´´  šÛ‚Á LeŠD"èëë«™ŒÛ¶mÃÀÀ€™sa¦+6l@,KÉ¥900€††´¶¶Ö\ÓÁúÉ8™r•Ïööv3uoo¯™V ··×1m%ÃÔ#ÕÖ›\í, flŠ”³ý˧Ža˜Jâ„6,׸4_ÝX?™ú%]Ù­µ~æc3*D?ËE>m:Ã0åƒm?…Á*u†¸Q¾ÐB^ÔMLLà?ø¹?‰``` h/d12‰´··£«« [·nåƘº¢Ð²ïr¹°mÛ6lÙ².— ‰DèííECCCɺXí°~2N&[ù,µìÛq¢~2ŒÓ©v3W; ÀìçZh·šõ ÃT§´aÙÆ¥ùê&ÀúÉÔ/éÊn¹õ³6£Bô³\råÓ¦3L=R©vŠm?Õå‚ÉÉÉÉZ ÁTžD"a.6ÖÚÚ:¥êëëãŽ'ÃT‰lúȺÈ0Î…õ“a §z“«ßÛÝÝÍ Ú23§´aÙô“u“™©8A?Úvæ’‹a¦p„Ê A ×´‰D*’#“a˜ôdÒGÖE†q.¬Ÿ S8µÒ›lýÞ’fØ2L=â¤6,“~²n23§è§SÛÎlr1 ÃÔ ŽPa†a†a†a†a†a†É/JÏ0 Ã0 Ã0 Ã0 Ã0 Ã0 “v¨0 Ã0 Ã0 Ã0 Ã0 Ã0 Ãä€* Ã0 Ã0 Ã0 Ã0 Ã0 Ã09`‡ Ã0 Ã0 Ã0 Ã0 Ã0 Ã0LØ¡Â0 Ã0 Ã0 Ã0 Ã0 Ã0 “ƒÿ{ĸ–m´%tEXtdate:create2020-03-05T16:38:18-06:00n;×+%tEXtdate:modify2020-03-05T16:38:18-06:00fo—-tEXticc:copyrightCopyright Artifex Software 2011ºÅ´1tEXticc:descriptionArtifex Software sRGB ICC Profile †2tEXticc:manufacturerArtifex Software sRGB ICC Profile\~=Ÿ+tEXticc:modelArtifex Software sRGB ICC Profile1(‚¡!tEXtpdf:HiResBoundingBox1584x864+0+0û8²ùtEXtpdf:VersionPDF-1.7 7ji»IEND®B`‚blis-0.9.0/docs/graphs/sup/dgemm_ccc_has_nt12.pdf000066400000000000000000005142401422157504600216030ustar00rootroot00000000000000%PDF-1.7 %Çì¢ 5 0 obj <> stream xœÜ½Í®6»‘¥7×U¼Ã£vgò?§ìl·jÖhô@U. KeW—¾}3b­ÁÜç;GGêB UIß›Éüc’|¸"‚ÿís}ÝŸËþÃÿýÓ?ÿîßýÇùùÇÿçw÷Çþó¯ÿø»?Üõ¾>(Ïõ¹W›×ç)õúüë?üîÿüµ?Ý×S¾êóëº¾ÖøüóïJ_åëéaùsXÖ}]ûç¯Ä"*GôÏÿû»}ííy®òùù?þã¿ÿAi¹û×´ ùã»â,²®Õ÷“ñ½¯¯ûUOXŽzhS=ú™õ”«Ô¯çuaÉzdc=ñ󨧭çk¾ê ËQmªG?³{Vë)ãóóì—ÿßö£ð†ÁÿùÓ?þ§¿ÛMd}îòù»ýÆðÇýç}J{¦ãþÚÏîówÿü»ÿôÓõû?”Ùöƒl?uûçW­uÀÿ¼×Ø?îŸî_*p–í³y–ýÅzË´·ÿüwÿáwÿóßýîÿøQ3¸¯]ähŽüYµö7Ö×Õ^¥TÕ¼Fùš+«’á¬* ©ª³TTUKûš÷Q ¯ª¢PTu”Šªú_£UÑðª* EUG©¨jµõÕûQ ¯ª¢PTu”ú­íç_¥î;û _û9gû‰×ø‡ù)cLeø÷û¯ß[L¼P®¢Xù Åî…rõ/”ÓiÛ¯6³ÿô¹‡ÝÑÞÿÿ÷¿+Ÿÿð›:Ÿõ?ߺ½?þJ/E~Ôx¿Õò+o£~ùû°wñ{)«â…Ì«íwZñBþýïËõÕJ™?ý/¿o_O]õ§ÿõ÷e“Ïœ?ýoñÇÿ}ªíkíOû§?æ?ÿÝ~ZûåÖ{ýô§ßÿ¡^_õª?ýßqø¿þ¾<_ϼîŸþa¼î¯ý±ÇcÅåþ5ýѾ¡«ÝûÖw¥÷Äåÿ}¾ºÌþÃïûøéŸÿ‡Ëöçõïÿ’åþ/+çÿuÿô§?¿Î#Ç·#ÿ%ÿÓ¿ü¨á É\Öd>ÿ•wŒñëùZÞÝöuñc,,í±añÞyvX–JÙ/tÿ._­Âð| /Q¿jwK{؆öÕo7´ý¯a–n'4K/_——Ù'D½ýùj^f} 5Æ~Â6è\_sºe¶¯:ÍRvoí–µ/«``ºpò=í·eêì» ˜Öè˾¬Û ØÀçwPîÛ:¨mé_{„q˳³ìþÆ/¯ìOµÛ³ªû„8ªrl­»Á¢LÛO͞ľÿçe}Y‘V¿îá†>ì!mK·{3˨_v5íáå–y+ÒÛ×ÀÕÌe}ñ¶ÅÆÖYvIôeOõ±uëhQoó±ÕË°Þæcë¶ ûšÌÒ}lÝ– bØçô±uÚ@‡ÁË{µ‚2†Ç?Ø4,Y§ —øžÇ×]KG,×åƒë¶ì†Ãc:‹õ9[n[·åB× (Ý–…¼ìÙ®VÆÓ¶ØØêÕøóÜ㺭þøné6¶âAøïáol_KÓ‰†­Û²0)×ô¡uÚð^PËò¡u[ú©r=>´Î²Ï8PóãCëþþ*ZR±ÏÝ>ײ߆ŸÊ&Žöµ–@ÞWå×6ì²Áâë¶<,R}\6~“ö1+²{¢Š2ÝÇÕYö\ X|\ÝeÌâö{·quumû úà³Zè3ËþðìcÝXQ~|\ÝE/æñaÕ >w)û=ù·ZöWWüÔû¶ý[-»5ù·Q¼…y™~¶XÛ°oµ,‡:³TY§MkÔÓ|dÝõt˜¶awîVÄf(Ò}`õ›j¨xøÈº«©øéÃêþYðeŸ?^Ø~íV‹ ¸(óø¸º«}øn˃qÕÊz+ßmÐÇU7øµÔkÙÀå¦XíÑ®jÁÈZ¬g€¥bd-û›¹PMÃÈZªJíV‹=xÒ1¬(ýžëÀ°j79pæ‰aÕn¶àr÷4½Ì9æ¶`Xå<Ò,†U»ýÛ/¦ŸY™Ý÷,Xn «ewe8ªÝV‹õXþ*[Á°Zmòï†ê£ªÍF±4×FU;fá˜æ£jÙß«íUíÆÑÈú~¯_n›Ví¨Žj&†ÕMlömaXµ£üå¶£ªÍ„Ñ„û…Qµî^ ÝH¿0ªÖݸñ.ûQÕ>î^0ªZ›°TŒªÞ¨±¹û'ÿRòAé £ª=?¼‡Þ1ªZÍxÆ}ø¨êWüÀ€aµîþ}¢ÈôaÕŸ0 \/q°+þ£­\¿ö@ƒ/ûT¾ ·ƒbT ¼9'òKK,dDÀ}Ç8(°’÷PäÃI àņxuò¨p?Ÿ‡LHÜ·ò¼ ðâ L¼/N‚÷ÿ‚ÃÄ€7¿ˆdÀ[Ø ¸[O hcê!Ú” 1àîÿy5d@ä°Üæƒm ÿfÀmÁÌ.°xÇr2à¶4p™°^_À'! M½š@@»9$¬‰«^x`ÕÄI¸ö°¹^hS3¬.ˆW]lJ$@3tà' pí³{ A5 F¸¿ˆ ÀÕ¸ôè+ˆ°“¼6-Ä,\èE!pu põ Ê®Îq2píùÇMä.û X’¸v[À$zr+ p[ŸŽ(Ð ÿ">ø\Lüì ÀÍøZÝ nKe˺áF-à@_ÀçJÜ첿˜Obà.òpÂH ÜEnÌV„ÛÒy(Ð"á½Þ…ËnK%‹“³B ¯I»ÈÄ,Hè+Žî£t›„ÀcmèEpS„Àaówp p_ !Ð-¸Bàx¬õÇG Ü}T¤Àm™ÄRà¶<¸MBà0R ˜}Y¥ÒâÃÕxv¿…EB [°Côu•XާÄQ€@_žé8 ¸-KdÀáT‹3 Cº½ ð< p[.~­„@/3ˆ…ë56!¼·¥°Ã&¢ž}±ß/!Ð"·¥rmˆ¸-@èõ '–lŠV4É€ãÙX‚¯Œ ¸-WP!W«ƒp—™ìÉ€~n è]'î"A…΀ÃÈ4Ü–Â÷@æÑÉ€X&C5蟼 pØÑ0÷AZ!úÚÚ:!pÄù¦ Ð+îÀ,@ [€ èËkø ÏîO`ÕK«ẎÑõÙM³ ŒSà.²ì $º1P ×{ú0º>{¼@µ @?¦Õ¤À}PÕåqy>í"ú™È› À]fqjF ôÛÄQÄ@¯·@Ü.žŠ½žúŠ%è ˆÕHÐcçkŸXFz¼€à6ÆÉ~Ì$öa}u7ŽâÜÂÃõÕÁ…y [n€ÕÍ%ÖÉa[ 8¬‘ajKܖކ,ôÕ ¦k\bµA8Ü–‚.P$¸-gÚ$ÁmÑ‹ úõ -·¥ë ƒnAÅ×Xm ¤ ô"pËYЯõ’û îcI…,èãc½XpÄÞW,h ÑŠ8¸-œ3}µ™88žÝZñúˆƒöH?É‚~KhZdÁ]` ¯ ú‰êÉ‚~ @Ü'*_ / àq½DÁm ®sô¥pÀ6YÐZ´øàjƒVMôÈ‚Ç=’Ý‚"“c«ÍPdql]TLÄ‚Ãú¯·áqîqÛ€ºÂ±uWCb«[—Vˆ‚Ûrñë% ú‚ý‰‚¸oú@Ám Š!ô œ8ùÄàº(%„R·i(ØùŠÿ÷ùoB Ëšo=pY >ip¿Üú¦ÁÒÞz W`6Á Y öw{˜Ðèƒ%˜M0Xˆá ƒÛÂS ³bÁ ¹8¹hÐêÁQ¢ÁÊ>0i°^ßipEÜ î2˜W²€X0˜#XpwÌ8Q°`׺ºXкIÔ*ìâ±àФ!Xкêö9Yp—t,h‚ʈç[ ´µQ@“@p‰‚mîë§N1p¿E‚6±%Ÿ]_-Ÿ+ˆM(¸ß¦)VIˆ!ò“ Ü{½Å@›ƒ1)îÙð‹íÔ ›Ð{`•´Àýè}}'åÀÊUÖ”KPžäÀ}y©3ä@1pÈC3æ»ÖWB¬œf‡hóx! šPŠoA$hS-<õЧ D$è7 Ž >Öù€ÏH‚6q„šOÌ©¸HÐ'uŸ­_³‹mð^ˆm†…µ‘ ‰àG´Ûœ8Š(è:(Á(hç¢øH´' `# Ú\‰ÊQði’S…‚>i=Qp^±°$´û`mÆ‹cH‚6°“}JIÐ&Ð<µäÀ݃â—xíVÌ  îáá¥ú¬¢žz OÇ÷Ûì/=ðÚ]Õ ! ü„‚KP'4ìM‚]ºl`—â%9ð271ˆ}¯[$(hØ¡úŠweãM‚6ž$8ÐqI¼.1IàssÁ%Hp© LP$8BÆ£x•õEíjàeLvªûT“ŸP M0p"Áýê©iŠí©}÷K-|Z­àT ðÍ.iáÁÉEñA›-û ^Zï“hFZàu…)49ƒÒAp®PÍ+¡ý„xU5Z©æM,x]TïwY¢@Ð3”ÚÇt‚à>WEÇ*9ð*Ò&$Úma¦+ÜørãàÒÚz )eÐ/©šÿŠP´V2ND3yÉv»˜/>·N ¸.ŠQ¯&r xÙÚ Šàusq,AëOúŸ8»@pqDŠ ùp€o¥Ú©2Tíuà5H¼p/' šjd ƬU’ =Àv’ ·É2”í\(BEÐ^^'öqp59ê”1‡ÒQ´»"R´ö" TÁk?l¨yRí\`àAk¿ÔåmsqN/UЛØ ªàµÀ¢TÁ«¨ ZC¹Þ$øh} Hð¡;]¨‚æ]C6¤0hn;,Caðº¹ü 9 áy >z}ƒ{bÍí\Ðo% ÚW}½„A몰^!aÐ:ÿ—.hmÂpÀ §Ò¯ÝVûK´O‹º õô<ê‚ÖLh¡.è‰åUºàq*ê‚öªðü$ ºßHŠÂ =Qô­àƒ ÜŸ;Ö$ ^mR¹”0xíyë¡0hÍŸìGaО(©’Â` r³G‘0hîSõ) Ú™^QÙU‘ãÿ’¿{„ú²ÿ‹§\7ƒoY„€U’a `ÿzy„vl/¼¾à'g —~ì_o‡Ps¤†ÔŠ¡0\ÚÒ!ðô×è7—¡šÝ¤C¨î °4¢°P0O4 j&–à´åÒb` 1°PÄK1°È=5ÄÀ¨FhÓtJbÀÉy‰Ѐ ü(G!! áŽ œòÑ ÔD>ÐÁrrÝÑ ÀZèÃX:ÛQ¸ƒv)ˆ"À*…8ÜA%û~“‰€6ÝÕb¿öDÀÎ E"`×d:pj%áåJK"à|©Ï‡r  yÍà(1 Í¸q=bÀ¥In2 ßd@-„&ÚÔ2à¤ÇF2 y‡%É€&Š}}(ÁŒ;p,¹wŠ–P‹pIô Ì2bÀGä ¸‡¤—hs?ê™B@›öB£îŠÑ–‚—ä¢`ÀE·ŽýrNŸPŸ” Å€`Ğ˕•.¢\®lt£ œMt'-Pë«©jÙ6 p[€\A€¦Ú‚§D€6 ûR ÜS7¨G!z˜$N}®‰€rk œC5 ÷­£§ 5Цʟ?§h×H ¼¿‰‹3ðDÀ} èp­(xJbàƒÕÝÔw«©o\3”? 5ªƒ$À¥Öh]N.-ð‘—JhOHBÀýÎî7>òH|NoPÿRyÁR÷\ K&¡î[þ >…äü·^Πþž7ÿ-z¦Fùó!Z5°H|´,™(7öÀ}ósòŸÍ}^Þ 6E!ŸJÜw9ßB  Áo!ðô¥7¨û¾ö„n€2逿CÿÒÆUø7¿úsx+¥¼A}>÷òµ«Ä 9èïê¥ÚT õH|8nø'ÉQÞ —õÐoО @N: =‰Ó¯&МʀˆÒ÷£hßðopîø÷(>V:à¾tLJC4o \2…@ócÇ1­œ)ð#ÅAò= pÍP9°>âÞЮ¤>¥Ä?I]†f(#Ð.g—¸-íÄ?Œ8Ÿ?2àsŸ“þ¸¬—ô‡ïøÏ‡à+ÐpK: –ÓCŒv’ôW¹Úô7ut@õp”tÀ‡‘R©î2Tý‚þè}œð·¸Ôðg«fo%0¯XJànnøhB |èò‘J y5ÒO”ë#Iú›.JÛp½¥@s«!.-×`%¤@ëFQ‹¤Àh'‰rú -Ð>ÿŽþ$´@û¬ ÙI |èK’bà¾@´mù…zOuú…ú%>“ŸQˆæ-’“h°¨GbàÃØ­wÅ…abÁƶdÁ~E, Y°Ž-Á‚6›ÆQbÁ.ߣ€Á®È €Áq«fÁàÐúmÀà ÿLò QÑzù†&óˆL׃æ\ƒ¡O0h^;ò嘵›õ)ºsNC´* Úä@ô—Þ^Z “T¡ ‰\¢ ]&ÃBAÓæ+6ÐqçÅ‚.¼ä@FrÈšŠ š#ÃçdÁ=µ× .qK°`LI‚¥ñ Òß Qp,óô }¥AVz ä@_SyIÞK⃭ã;Bý‘£fr hxxä@—Yx8ÐgŠœn9ù’«úéêeÆéêex.…Þ!2*4p{ Cr ¯]áÞ#6Ð¥Ã+Ô—A±¸r‚¼X¤e*N'ƒP“Áå’㨂c$‚-ŽG)8°49¶*8pG±Á{RÄ›Rp ²Rp y@ƒ£X¥Á!ÿ‡X¥CEpஇʃKããŠà@ .'r¹ròKŒà@‹tB-R÷“,Ôþ¨V-Ê(:д!­VN~A ´" W^æËßQ‰»ÛY' úª'ÀEÁ.x1P«•ZõPp =œ ƒmÊMaOj`+’+©V=Eº8ô[\­  dt ¯jŸr ÖNi¡Øn©m’+çfh÷ÙOô+&²1:Ðî ëyŠ´šï·؄סÆËRt`¬ÄGt ]–4èç:õ@¯y¾A›íÁ$î†7Ïè@«øåê/7Áè@Ã`2Fz+@‘ûÍP«n(‚ûeݧg(ž)ùÑþBé,úð“ÕEa»¿+‚úR¬”±#@Ð,턵qþ­Á BÜÏ«‚,©î^o$ÜX‡k(´St½¨¼™°*B,Á‹SÌëd ¡ÁZÂY”HXÛÛ5ÔO…[P„ ]E9)‚6ºþ|‚µq‚`½e‘ òšBí;y†â¨3DÐ)‹H´{x ‚µKh” Hq9BíD ¹cˆ ™¯A«÷:‰|¡×CN‚ N¥A3Ô½Go=ЂEz yzÑUTz ã^SÜ‚²%èà ÎÎ(ÁKno©ª/ =оÉW”ैÐmþLWQÅßW®c(JЮ¯¿õÀ2¥Ñ…xÉ…Sz }Á¯@A×±q. ÚÙ‘È@A³àY„Ï"ôÀBƒÔM§{ëE±¹!–"ŸÍ¢!–3’PKˆ{R‹DþPïo‘‚V¤áÜRo)ªŠ´2ótõS·"XäŠà½Bÿ“"¸ÞHˆ2§"uùóçC¬ô_IAð~ÞDè²f?‰3¤Ó=j<ê¡ ¸«i§{¨_ ž¨ˆðVÓAðîrllÕB«_Y~ötÔF3,‘%í—bˆ#2Íý ùÕ~^wZ2ÙëYäÈCVm5_õ„娇6Õ£ŸYOÛEû{ KÖ#뉟G=6߬¯zÂrÔC›êÑÏëüjÕý€úßš_­ý(¿ÚÝ¿ýó{~µmí¿Tù‹Jä/úQ3hÁ|™æê{[µ†h0ð*¤ª2ušª:S§©ª,ŪÎBQU¤N‹ªŽÔiQU”RUG¡¨*R§EUGê´¨*J©ª£PT©Ó¢ª#uZT¥TÕß_­Þæ!]ÿ˜_í·tˆ?ë¾uü•^,Šü¨í~«å¯NSV-nVÿÓ”íÏ÷<ò_Òl}í‰þúi¥1s••¿œ«¬Z&¦*ËQé>7¨–z£2æÜ¿¬ý.Äón‹Iµt…©É|Q=ŸS“ XVE<ïÅÐŒjYºÇœãDûäx¤¸Ïk½:¢yxß`A4/SöMú²ÂÀQ¤L,°î¿à̵v,°j¢²Ûg1õÒý[|Ah¹¾¾íó”m˜X`­ÌNaOßX+c6ö ’£”Ö`k]Bœ ÷ωÕÕö€kµ…p_]m¼Ç¶bõØÞÛ“K¹>j³5¥‰À„æ8ÐŒ5¹†T›-*yÆ1.üoËg£ TÜüoËë„P[÷¬$cn`¥ÚlUÉuá ´ -‰")™?‡6="ÇýR*N¾Xmݧ2wÌG´údvh …=á~àÆ^îaâCóžl7.°^˜œÕnÞòL8æË²Ûòpub\;‚Ý£cÁÒ\fqÏu4ؾÿæÃgê±5%v{°:]û”ï/Ân•ñF>áê{_¨p-\ž­(ùò*Ýß7 .¯22¥ŽËSn¹À€62îIE/ÊUÛ²¾¨¨âÌÃ8³og°:ªyö`°µ ù@âLm‘ÿ†Êôþë\¼Ú¬RÁC[Ó¿’yÉ[{[ppѵŽÕ€–> Ó‡½Ìà=ÌëZO@ËŒôÓ–”<ÍC=÷T€ë‚®^g½€OrmË´ouÞŠçÞ|Õ=ÓE¿­:{A:'[ÉA‹BÞ/3\b˜wáÊ|ž#J Kê´pOÖ±·-¾ÈæI¿Ðj¦ÉlV¦P,­Öá-+cè ‹]ƒåDzå‡ËãôwWdôª–5âžÈS†žÐ:ƒ?Ëñå4SWsÍ-ø^<Ÿ‚•\Z¨.Ñþl‹ªÓ–®¼Ù´rMäsR®ÏVî†|NJØì!ÝžlŒaÉÍ®Üó9uêµR'ò9 ú]4{$¹Ä&Îe I‹ypT÷au–=‚ãTÃGUdéfCB§ÉIU³DS ÇøBa³¤WžÐi]Ÿá5²aùl¢ULÉ&/Ü,÷¼k£¢ƒoƪžwMÙNšMsû F£­ÕGÕiÂhC=íFⵥ˩ÍGUOˆõ “^ Ò_5XFEB§‡ÞǭΛ †›Ûàñ‚^„—¼|\õlW¼­ÇÇUÏ8…вíî“_|êíòqÕ„[ï‚Z»{$tòIRk¥âk-lÖ­b\µ‹ÁÇÐ*ÆÕz1dµµ†qÕ2Pù|r0®Z¶+,è´qÕ3buX0®ÖÁJ{6†aÕW pаZ•÷£5sæ™Hm…O¨=Ví‰âTý°j¹ÖÜ“³uÌÃ<Õ¾ß^0¬Új*¾Ö^0¬gÔSÝ{ÐÏîCøžb\µ¹wWM±FÓéãª)Öx‚}8½«êãªMÂY`b\µG3Pë¸jóý g~0®Ö[w9.Œ«vu «ÕV¹ý qc\µêÓ€6ŠgùôUŠjYiÚò/ñ¨Wk¹UOóÇ¿ËP²j£c\µ=Œ-ëøçZ9>o‹;Éú³A5ÓGV{2èqÆÂÈj„â÷=YýÑàꌬ¶¢;ð„ׂsÞYÍ‚þ&C,ÇñoÍS–ôç£Ø7üÙýÝœõžôWhýýUNî“þ(ÊôG éà?züǼ°´õÀ{ ÷€7SX8ñZhN%,ðÐOþ£üWïüWç”Á•¡šÉR(“ÿ„“ÿ:X’ÿz¦ {'¿ÆÔ>pÜBB yH¼ph6hƒéó9 pÐ?60’bzÜЕHôìX % Í€ ®}ÂI 0²cù€ÐÊàò€´5 IÆ7Ê×ÙF îèÅ€FǤX2 á1¯G hyýü\Á€×M&n æÉ€î …7L„oÔÁ€»Ï w¶Ð-@7 ò|ž¨ ôNôˆÜÐÓ2§ˆ€™ÞI虚Xèe¼ 2ˆË@€(€úÉçI€( I¡Ö' Xsô"$3 ¯ eƒ‘$ E@€n&ÌÉ}\-ÐSO‘W€nÁ'"!È ˆ,R^ɨˆ„á!GŸd?lBÚûù ,öó+ö«!úe’ÐÏŸþƒ«\Q5Ò;ÙÀéŠêä¬KìçÑE$Ú+ª“åb?ÂzÙkš¿ÌH%ðÃãiU.§*‚À٥˩é„ü2•ÀÏÃÂNîóëeÅ?wÔ-'øyàÕ ~|8˜*üMàç– Žº0˜N†* üüúP Àõú'øùó*GÓÉÿ?dÞ.vަs‰1GS¦7÷yÅ,29˜.¤>÷ù,\0¸Ïýt'hñá`ºO!îó2h#ä>ä Y¦vŸŸÄ>4‰OR_z ‹úà#ìWêsiH}á5ìÐçëà턾Á7¡!jŸd>/‚o’ÌçOߙϯ~Ò¡Tx‚>? ôKèô›KèóçÂz*‡RÅ( úÐQ¦s(ÜFEЇ^Àès·ìú¼÷öúWó`(µ?Ó‹ûìú í’ûò{÷å üò6~~jœ‰àçõüü(¢àН_ÀÏ·ÚúÜ—§øù+XüìÙÔSúC?EðËg,ðóg Žàçï ðóëûÜ—ï…Üç‡ûò˜ùjâ>ÿ_Ü·$m÷åÅŠûüižÂ¾^¹ÏÏ…£È}Þø>ö-ù§öÅåŠúüLŸúòÕ úŽË#ôå%è;Žôåg(èË{"õyÓã‘úâê}qub¾|Àb¾lゾ|I‚>»{ô¨‚¾üv}y—‚¾¼'A_^™ï89™Ïß.nŠÌ_X0Ÿ_à'‘/n*OBÐçB_–hPÙ óEë æ‹0˜Ï.¥¼˜/¾“`¾èy‚ùŽs‘ùâuóE3æ‹çØÏ<°ï(S5¤¶¯Cö;îAà\àw‘ÇgT2¯ó†~yC¿-ü¢“ ðËóü–Â?üü(”)QùÝùåÙE~ùðD~þ¨^è-@äç·uª~GÃùå'ùEVލ¼š'GTPÒ¥Uü ò‹ï)à//Xð—×'øË·-ø‹*à/æÇQ#GT´tÑ_ô-AÇQ+GT^á“#jyÑ_4Â_^Ÿà/Æ'ÁŸÝŸƒýbÞìwœ§å€Š¯NìÃg°_ ±ÑüÅt-è/:Á_ö%‚¿è0þbð—G þŽ£ÊŒOKøÓÀ?ŸVQ㻾ΉCàßQñxÿœ%¾Ö›–SÑýý¡Ÿ¢ßñµ ýa•®'¾V°’0ï[˜_¸rY…cBÛŒÆ,>ÐË@OœVÙ¸ÆÒ¨J©Ih3Yx8'NÙe>ÿEäܪ \þB²d¾ËV¡_ÌG¹>™™:ùª¼ë‚ù*㎓ùª¼4úªÆ÷€¾ª©P@_íb(A_íòŸôaÄWÃù“À§øµ>…ƒ%ðU¦N¥ñ®/WO\‰”¾*Ù.”>.¼Jé«ÍPúè“ÀW%~¤§'ó JŸü:ÃÑsp›žžòf Þ³EàoBß”ø&Þ›M§ïM­ùïÙ€CéÃÓdZÖä½ðØ à[Z‹ðiƒ®¾%/.ßbb®¾‡IéøÝ›øm'ði‡˜tõ¼n%WÏ‹éSøäBq(}ÊJ¸z^jŒáíya.=/­uœBN•B–8i÷C绩:2ª=d>´é_–ù®!¿NÉ|wœd¾[Óðùnn8{È|º¥ùn¬¦ÊwÏ`;Ê|·ÔàùîõöLæƒä”2—dSæ»é2sÈ|U5KæÃߥñ C¡ñ]ò锯W™x€_árEh|eéïÒøJ—ê'¯Lqœ4¾BÝ"5>¥ÕOÏ4ÊëY—4¾²¤Jã+ôDi|e½½<Ý Ü_YR¥ñ•ª5¾Â¤ ¡ñ™ÛnB_aŠ‹ù*“2¥Ègš(,ùv›4¾Ê-éR㻃Ó$òU9„È·Zo‘¯¹Jä«Ì "ŸÅFÝ$òÅà ‘ÏÓ¡¼IÊSã3ožÏ{‘È#$¾:]’øªÖ¸¥òÕGzT¾vщS"_¥‹{Š||z©ñUº¡¦ÆW ™_ _Pi|Öñƒ¥ñi³îÔø,Øó­ñYl7K_£nÊ|6—ÇQ’ùZ“¿¨”¾Æôh¡ô–BækÐŽCåk̶•*_ã €È×çš*_+ºv©|•1˜©ò5úȧÊ׊èJ*_ãvß©ò5¦ÂO•¯É§7d>\`‘ÌÇ=gSå‹Ç2Ÿ-ì‘þ(ó5샒*_ã^C©ò5fc•O¹çSåküHCåkÜz0U>@RRùl›>”¹3n‚<(¡¯1&…> V{±žïÄDéB_c*üú;µúZx“Jékjy¡ôiÿ¦Tú÷qM¥¯s{ÕTú´A(}mÊçSJß®IJ_£c@*}íù®ôuæI¥Ï6ßBÅRúwPL¥¯Ñ­#¥¾Î ”¾} Ä?I}ZAJ}®S)õµ%à’Ô×/‰e’úš<©Cê³–ø9`ÏO‹´¾~IÙ“Ö—§¢Ö×™¿&µ¾^ä:êGij ±¯³çN±O[Ž¥Ú×/IˆRûô¬BìëLЛb_ã¼1ž~«ŒÄ¾x-!öÅÉCìÓ~)öÅwbŸ5p%±¯ Õ#±¯Ý¢Qª}ñ°{vhRûäדjß®m"Ô¾Æäƒ©ö5ä§Úw-EHþæœcéæéFßȯ½Õ¾`žTûH¶‡Ü'ª@¿.^ ôëšÖúYÒ­7ú…Óa ß·V ßàv I¶Ë;Òo ¹‡ÿlÖN©Žøg“Óq⟸¡¯úÔå º¥,¦ÜRêéééÉç>‰žž`žŽžžê…G4ñÏ“š·“ÿ¦M îBþÛsìëé7¯ÅÔâ¿i™OPøçÁN<ø·Û•<úˆÓ2ÀÕÓÏszr”ÓÏsZÞ8̸‰Y3?OBhø0$A)FHÓ‡pHp7CŒyÀ_…! wbaHB•&Lú›Å>6Õ’€ÉdÒŸo¥Î`À΄É݆EÓò°­“þ¦·0œ ô7-%Ȥç§ã߬1Y&þyÄâßôá—^ˆIðô#à2Äú™³ù;Ö¯†Û$cýª¦:ëW›b;ëg+¾MÅúU懋P¿ª ÀêgãjeðBšò]E¨ŸÝ&E¡~æ\Žù½Býªv¼ŒP? ÒÁ%+Ôo¿£7úN8d2Ô¯*¥d„úíI°Â ê·gõŠd¨ŸYèSŠP?› éêçJ8zNKÇÓ0Ôoßÿ[ñó‡5OÅoZ¢°±Býü;þ$nw½H¿fÝ7‹¡~Õ² ¾Bý,ÿÝÃÀ>„$XZ\¯BýZï/Éoú´FúÙËl§Ÿç¬ÌÀ±~6k:Ý<·aJ³d¬ŸÕR(ð!$aqƒý*·ó‹X?KOC©Ž±~öÀnÇX¿= ÇOûÙ-­Sòóhˆö öó·zìWñe(ÒÏò âS¤Ÿµ˜òŠô³‰àE—N„úe#R¨ŸåÊ—Býì‚+ð¡~öþç©øy‘~àlê"Ô¯µç[¨_œ;Bý¬Õ”SóÛW>œŒõ³aŠ…býZQ„Œbý,¡¡~6†ÔÓÍÓ[,£íêg-€>™ õÛ’+(Cýüá×êgà ¡¡~5ܧêWm¸>5?€˜ø0Ôo¿f)x õ³Ëо UðïŒôkÚj%"ý,‹a}TíiV†þaPµ<•d*úÙ-^§ä7-+%è·?½ðþÄ Z•¼=ýª­k~’½âuR _1^“âüì®±’ @?;ù½‘~Ö¬O ÜEÂC”~d—À@ï4l©@?Kà QúÅ—~ö¹<§ä‡Æ‡zè×l«i… ôóOê”ü¦%¤:Ý=½ñõ“½Å–Sñ›M9¸"ÐÏóZŠß´©Q?ý=½LcXUm”§@?ïù »1ÐÏ_9ü==jŽEè×¾Eù­GÒ£ülx§Q~6·£¼‡!Õžð©÷Í`Kôë! ?+úž2ʯN¦ ˆ(?»G@ƒüª¶1Í ?³œè>zù=H"ÈÏðéî¹ÇG&T_SŽÕò³{ H8:{š½Í<'ú ,äÖä7ÂåRA~«½>·…‰92Ê/ùNQ~3"øå§ÉOFù ñrDùu)øå·YQ~Ú÷-£ül3hœ]a~C+̯ëñ(ÎoT隊óí&Âü:çBæEå§…–#ÇX÷~÷Ìtã{¡^ó“)ud‰Œa¿|‹¨Àßcìçu§%sq½NEŽ\\Ýd»úª',G=´©ýÌz†E߯{ KÖ#뉟G=Sé±£ž°õЦzôóß:ÇX7R°gúÃc÷/çûžcìÉÂþMrŒý¨¬ÿ‘Lõô½­ZCla–R]™>LuùÃTW–R]g©¨+ò‡E]G±¨+JE]G©¨+ˆE]G±¨+JE]G©¨+2ˆE]G ±¨+JE]C¢1ˤøìùë•_K4ö³—þãDc¿Tì{¢±_*÷=ÑØÛÚÏý–^ñgз>ð¿Ò•E‘5àoµüÕ‰Æzµ,¤õljÆöøÇüç?D°¿”mì•3,ÿuüù¯Ì;vÿé[ů§ ëÆšîcf½íŒ6Ï€rŸÜvãgñ…2ÛòÀÇìb^n“ÚéeèTÐH1w yÏunø˜)[ü¶xX¤çs(îx:tŸH÷Ö|ÌQÞ›-4=X@åÙû‚—Y!Åõ=WøbŽ1ŸÝô6kÆXà—…Ù§/Í6,$д…LÔû úÛpilÏÎjx™ù4¥÷›CYãÚʶ,îýÀU›ÞËÀ¢kg(u÷ÑÃféîÑ{s7âÆÙ{[\t…¿Bï½ÃËlR@ë}Tlý0)íÙâ—›¥ÇÞç‚—™íã Änp娰X #Ü0® k®7Ã.¶e¡€Ã`–©ß 0¡\ÈÔŸsìk» ;Øz “Z>×Úû@| b’qP/Üû!,ã‚î`ÐÄìP³Ý»OFH_8Õ*”ò9Ïß–²Cáv{žï[?XÎ3¿íy5ÈÚлϻ@v¨L´-žF[›ûžÈYŒ c7Ô)ŸÁݦ7Ktßø¡Å™û¤è@ÕµÏѨ³gØÁ;Ûð`§¢Æ £ö›T;¦Þ›Bfcîö¥Oªˆ¾ð½-¾ÿ ™ý(Ëç0¨­øL·!oÊ8<ªÞØV¬Sî–iÁºà×í›h¤”K÷]¼Œãl· n`j›nÀ¢$°p*Ûeîƒð+Y; .ù÷…m]$Àw¹°JVÝ\vnÆô¢ù™ËNg4Ú5DÅëúºbw'ÆôÒR=ß6ñ{pœ‘gø¢ì9¹D8¸fÔíËâÙqÔþ›Ë#ƒ®ÄÝã_”q&ï¾}zƒe¡ŒmцK~`@>\޽¬ýñV^‹³‡í¼ÑXÀ—ü‡¥`~ø´,ö-)º•Ô‚u0÷à°Üðþ±öã‚¢íe\P—­3MXPd|¬ƒIº†©)‹8oËdÜ.µ˜ÝÙ4|¬ƒÙ¿6ŠîÓ‚Ý”‡ïåóà '©k°LXî†ou0”mø^>Œôg>l3&#ôánø^> ƒf¸òcŠ)ñ5ƒaJ¹%áð½|X†GMŒ¬Ú¾‘Ï|XV#ÄqøF> ÷µñaùøÇ:ø½ ßȇ»!z‡4l#Ÿ›qоØ3|/mØéç*H¶ïaÙêÁGê1ãõ´…Ul?l7ŸÆ"0ŒÊÈ]ºÆÛ·qÚ¼bD{p7^‚%…BànQ5Oeà.³!ú†ó  «fqL–ŽÈ?ÖI?ìQ‘2Ý[Û2ÃêqT]ܱ³`n0l;„î2¯Øðí|ÖË2.nÙy³ñûv>ØGÌðí|Ú'ä‡oèóЂzެŠ%ß–uâ;ú°nÁ–&>.œÈwôç‹1Ecé‘¢žÊ¡u²£­qhtؾ£Ï<_–íèƒøÝ8ûàØº-¾=lGŸ^ÎÆä;ú _z»a;ú46ƒG=-6íôϰ}ð½rYhøŽ>ÏËrslUö€a[úp{Z †oéÓaA´=} gj]'• a[úôûì=|KŸñÉ|£ޝØòÆ,“ãë`b±a[úà“EXîð}Ø» Z8¼F·ä;ú,Tƒ6i;úà‹¥wíð}ØvZ8¼†»ßÑçAÇŽGê;ú0$zÁÒ1¼ŽªŠ;‡×éà°}*F´ ßЧã#ò‘}؆>]߸oèÑ]•å–÷Ö’úû»ó}蛂nhÞ];½v†ïè39g€¥ptíˆïè3aAûŸ£kg Þá;úøl„Û ÛÑÇ?Ø}¿×38ºÚ_PóäèÚ';SßÒç9¦#÷ôé¨ÙgPc>ªÖú†>—×aÐèzñz}?ŸñÉpqì„­ s¬V®7»ñU5º"ž áaÙv>ƒÍ¯âäC£+È~k>²ÝSç…‚7ô“5;O,‚¦@AdW‰mñDæç„ öK mJš“â aàô®AŠÀ@ó8"Ñ-Š(. ´eÏB +Ï5æ·-´üdàuq EHnÄK8-B K hõú C/ž/ÔB 4Ãxa  ô@a`ÄYú&W/ \‹®–Ï{h¡¬˜hÒ?«Z–3 €@Ð7´-^c E‚]ƒzÞ(xMaªPðêB$¡ }P?¡à} ê„‚æ±` *'t¢ TËDAû¨p”Pð&„$ ÞÈ/$xÓ³>IÍFx/¡¬0°ttñ‰å‚ƒnb ¬%Z†ÉÏIE=@P v—;)°Ò›9)P{T%zÑ&*x!)°^| A•îNIeé(Q`YଠÀJ—²¤ÀJwrR`åžÔI–PíMûÌ7°K¨diI[×'Ê)!°1'fB —;ëÒÕ½7Û-JVæ3M¬ŒnJ lL.˜ظSR ÍZ¢ÀÆäŸA­snØÊhŸ°_^@`ã"hB`cþÚ„@¹;'Ê 89°QNlšCÊù:9°a{¶ÄÀÆmªÍà% ì7œ+;Ój%6F3$v®›vn»•Ø™Ë70°Ó­"1°se%1°WRC``çQ‰]SÜÀÀþpʸ¯ jk` ÍEQFØEƒ©'û¾ ûN ;ç)‰yÍÂÀÎ¥Š @-Œ%v5[P`Ôh{ù!A1S „kÄI»¨%j1-)°O nI}ˆðD[…&vJP`çnqI]k+A½§ÀŽÉaB`g ^B`¿yª€ÀNñ€@y½'Z¢Åçs@`¼º€À.ÔÌ3 •Ó1!°ßB>A``D@`çvºI{F$Êu?)о™Ï a, ÁT£EB`çl5!°kÁEØkœ(—‡ À®õƒ ÀÎ,ÐI9æ“Ñ“(û¤@¹û'*l )PI ?H ´h Ôx±K äö“IÑÓ6!rP â0 ÔzFR`ÐíÃj˜(°W;³s'¶^M‰g‰Û;&vÆá'Zÿë'80¾à@ufE†²DÁ»bŸôDÁÂæDÁváãIlœs$ šÖ’ ZÃR'4µ Ì&ìÌy,ع½|² õk¨Y0ØéÀš08˜]/h°‡ä'ì÷ƒ;¢V‡ÄÏ€Aí]08µl08ᯜ0¸„3Aƒ‹ûÌ' î© (hPnîIƒûˆ A›XõHƒ¾·..8èó&Z8jÙ¨ò$šÏñ =Rì$U°Óª`ßUÁÊùÅ¡ "éÒ! ÞørRÔæ?© ö)9Oª`c2üCd´FÊ‚õ!L§,8UF²àbÄqÊ‚V×#Yp,lÈ‚C·²`§£kÊ‚ âAß@×ô]×û[\ÒŽ% Z"DœIÂààPœÂ`gð«x›x¢ xз5ë> ÞtɃK˜<¨ÄœÉƒr-Nœú†‚¥?$N.¥&.æ5Iœq.ñàD†þàA-!'î»Ãê“ÐúkT+$\j´„‹½{"áz¤Ö —N0!z“ × G-<óÂ'˜L@øp£û‡éGŸK# |nÕ# |ÔEÎáSE¬Â5In΃þ’œ'®ùõ§8.4A.ƒ}C-Œ¦ƒ˜ >‚AÅ{$ Nî9r(‚|ü‚Ái¡(ƒ®N,øˆyƒý “g ò# NnÂDÜgbö|±à¾É*©‘0h;z ÁàŠs WÖ ç™ýÃÅT’0è.Oô“cÒ0ȸdÁE׆„ÁUùr ƒ%l" Z”Ü'IÐß$¡N$¸ïR!IPÛ° ®…G$ˆý yN‚þ8Áì$Áiq ý ÁG˜$ø`M”¸@Ð7<†jLôÇ , úãÑ·Aõ º'>¡ô}ÃhH Ä@0¤ÁÇÓi_¾R ž'HQ¨íè†g:úvÛ˜ý­½0Ðw;ÆLè÷Å8múçM.‰cëqA`no-ô͘y Ð_%^!“ާzqd@l ÿIô ¯d@œ Dô{¢Êwk4­RùÈ€š è;÷ݤÂÇ·¸½ô™’ñÞÀe`@¯w¼0ÅB1 "Ä€h°€½Â’p׌! Ÿ ¯7ÐöY?‰N.Å€h8 è_§¸- }I´=ÌÀsdÀg„£ésÑQ h·ðIôŒAôÓt ƒJ+¿ÁÀ)Gˆ@%Bzî|º‘øhU,pq'ŠÀ5$ñ —Ð?øuÊ€þyàà |˜Ö\èGáN €>yC TíÀ‡á €6ÂúM>Üÿ#p©‰bÞr b°ñ1@aÚÜ ¢…ÿBвú|–ñ‚>ÆQ'ôUnr’ÐW™ºý€>êñ }J0šÐ×“Ð§Ü }í‘›§ ¯=æ}–ÊG úö_êKTªêú.ú^ôÝ_oOÐÖuŒ ¯sc™„¾~ËÑRЧjÒ”ñã‡#hÿ.vn}™Ð×¥¯ô ¦L p‡ÈMŒ_PMòB”{ubŸVÅ’ûöæ0'îëR SÔËJðÂ]…8˜ìñÔ?'öufRL°rR`cß— 4ÌÛƒÕ¸Ä>eù9@æ¼<À‹O8@9d¥ØE‚•öìGXH~!{¥¨ûLpÊ{4@½»r€rLP„“ àÃ);ÀNJ PO+À!å8Àù3¡‰~CÞ‘éõH ÉOpÜßÝ@G8††¸ÈB¿x(ýopºxx2‰Ôኰ‡h¡ úŸr†û ŽÆ©ÿ lŠòߘB6ÉæÕˆjôqÍ&}@;IÒTâKú€J¥KP9§èÒN ßä¿ÁyÕá*QétåQáa8>*N  ÞI'P¦­;œ@%8‡(¼×Rþãjlªû-CÙKøãÜå€?n ,øsRiÔúÌ 'øsмOP÷O’Ÿ@EòúÎ7òãÞ')ý=UŽ›A~ZM!ù9 ®·ô÷ÜbÊ ?=rßÃ}E“ü––’ü¸®ÈÏOçä§U¼¿‹#Ç ~X: åï‘> í;øiï·¿"[Ùáê<ú‚@©R Ì2u(Ì š˜:_(\N8”?e?f3{é~@è@ÀçþŽ€'! ¹á):hÎ{¨X²_Ñ]‡ì×.Y$û©'MÙ¯Ëk1d?u1!ûMîQŸ²ß”® ÙÏB­^èÚ//P™yyFÔÏ¡û »B÷òt ÝO›‡%ZºZ²À”Ôý¶Áj¡û™_<Ž*ˆáÐý¸ ì¡ûM>¿À@ °¥…£Õ\Òç„“³ˆÀÀ¹T±0Pû¦îw1ØOˆWxRàà„ )pÞ E“nXI“ÁŸŠûIœ7+œEx¡úÝ1A ¶~— ȳG$ ¾ ôÕ’> \–È@@…½† è·z(€(8¸ýaº€Ž*ó!­‹úgÏ Æ ¨•ŒlßÀAf8"'ÛhF’FŽP@=›AÅ;¦ (Wޤe³_ë5g¹PøÉì<4D²_<„%ô÷¿!cÙôú¬:-™ÙK6& ŠŸ™Ùky6æ×%†%ë‘õÄÏ£žÇ³9ŸwJÃQ Lª„¿þ­³ŒMÓ—í9œYƾçbúµÌa‹Ö>¢ÀÏþyËš—ɶµü†ÃehD–¡Ÿ7Ù×Ѩþø½Ù£³Éû«ŒjÊDbªéL$Æš²k:ËDM‘F,j:Òˆ©¦(¤šŽ2QS$‹šŽ$bª) ©¦£LÔ)Ä¢¦#…˜jŠBªéoH3f¹×ž¨üJš±oé¾úsÕß–‚L¹Å¾g­û¥“ýb®²_È-ö:¯?¾»£ï}ÕØX_ý×[껎¿:¯Ø´ñp&ÿ#óŠíoõÈ+¶ý(¯Ø6ï#MEš¯.ãŸî_ýâ1¯Øì·TûÙ¹|õê :†ØÙë…ÀÛ‹‹™Óò®-fó&¾XGàíͰÆ=šÞÞô[¢™Gpß0LïPä47­/¼ѽp¦U¾¾ Ãã~=¾}á ÷+õðmŸ^ÎaÑêvPåÆsÀE9Ä*,¾õöÀC™2¹¹ç {öÑÂA†57÷Ô÷ }j±-¶=æžr†ƒÌ Bü·ebŽ<æ§îÓiyÂAÆWäçžø¼Ðã-ü=ŒÇginñ™×ž Ý\åbú¶:¸¶2‹qŽÓ\{à$¯™iqïð‘¡?üt' güö´Â>-¼‰6m=øÈp’?}s;/CçñiqÛ£ÇÑÔ-Ú?Ö‡³ßéÛ‡y˜ ;§-z¶lÓ_9yð-/Kî_ꦖËvëéŸ\^žÐÝUäN‹m™wk*mË7ëñ2Ü÷ryúsƪàcöÍz&êq5nÙ–‹èè7=~GYx¿—y0+Y¾[ƒvð]6¬}œ×cëA ÚY8–Œ؃£FUë™ð ùn=^†IΖí×üáŽô7Уý‰Ú~=tƒFC÷íz\&fÎóeÛõÜ7´eïü–o×ÃøÜUÇØîÐŒÜáÉêNاê+b#pŸ¾]…÷ËôQõ´¬[‡=t‹[¶]‚#.ýñaÕ->ä,Û®gTœ‰o×C—4nß®§á¨‚2Å<øÁWÝ–ï×Ó’€Fiö¨Ô|hÝE?sÛ¯Ç$ ÓR.ß°‡q–y!@BQ@Ë7ì¨=´mØ3oâëgk¸vê ¸bÛ¯§ÃUox^ ÷1}Ù^=v‹…Kg˶êáúµÚF=•!-¨À³Œz8À@ lÓcQ¬ÂfÈ ¸ÀI°K¿\•­$"Îß7鱟¨ÀÔR«€;­=g°Ÿª–mÏÓwã{'œ}™e_òˆ:ó.ã…Ø¼¤å.Ÿg †FV&ÈZ6ñõøÊwkµG×ìâÃZ}âïî{²lÞÙq•x ¶']V£‚º,åOCÌz+nÉs5æ‘]æ~l®ÍÁwä±!ÿ¡áÑ…{6á`ŒÈ¦ÇߨÂg&Ëæƒ—Cª]UyØd|ÿÉó"ÀÎzXDv…M'Ú!'Ú± ],3Ú•Á‹ÙUæ>H²«LU’dW˜Y1É.ˈì*ƒ“ì*#Î’ìÊ’‰ìª€;È΂hp”È®6ÕL²«LÀ‘dW‘Þ2ÈÎ6±}“]Å>Z v•92ì*68L®+I\\W§(N\g=ʈë”ñ$¹®2ˆ7¹®¤…\×R ±.V\ëZ® ëZ\±®q[X‡À€±NÔë´Õ»°.Ãyë´ó¹°Ë)~5Ä:? 쪑áMTç·€@ªCô.GTט¶]T—{‹ê2“¨.csDuØ*Ъó€Žê2š Î•v ) .wPÔ¥¶-¨ƒÿÀ ué» ¨Ã¹qÔä‚i‡ß»˜1 °Ðv0¡™‰±yt‡}¦;&˜Îo°‘á.9Û_ÔÁg‡:Ä‹øogºÌE¦Ã“Æo¬‘ýž \"Á-¬&Ær¤‘oŽLç ­PÏ?Pož/F¬€eu#¶ Ô¹‹S€: `¢½pKO'öù«r~%ØY;~qÝÒŒ-¸nµï\·¸Ö\·˜Û<¹nqB–\³Cq]H*Áuü…ë”(7±îá´ °îaÚ÷ĺ‡݉u’P‚êžEÝ(¨nJw ªSέ¤º‡ÞVIuÊÝ•X‡¹w0Ýäa2ÝDj"ݼ p"ºÁ¼.‰tÊœLg¾Ú 2]ÓMÆžÓM'ÓMî·™X§«Kª“Ú˜J&ÔÙµ|ê¤|¥PÇ{¡ŽY¡®HmÔM®ØPÇ| Ô1ÇuLs@]£¬J¨cxÉuߥºÉÜ?ÔÅyDu“é(“êfrŠê&St$ÕM&JªÏw­ÎšŽTï;¨NÍ&¨n,Á—¨._PRp'ÕMÆ¥$ÕM†.'ÖÅk¬Ë $ÖM¡~`Ý`¸x`ݼU¯°Ž·T7ÉɉuCKÚÂ:/¨n ­­‰êÌ‚nZTëAuV†§"Õù NEªó“ƒØHuþi¢ ©n æ&ª3 FHQY0…'Õy k‘êü&`xô­™Ètö81fŠéüƒûÈtvžþRë¬ÌýRëÌBPgƒuEAEËŠ˜ëuöD©èêVŒê‚:³HÀÔEoP· =ˆè|9z˜¿l2!y[iº<,xÎΉ ‹xÎÑ¿x.ïOB]¾]BÕ.B]Þ¡.¡.ß5¡./Ë¡î8P—o•P—mžPoƒL—ý™ÎŽ éòQ‘é²µ“é8¼è²Ã&Ðå]g¥ºìVä‚*§º¿Ä+)®$ñJŒë¬31®kB×»Êã,ß;,¸®ù`\žã:“¯&Æõ%m§¼ÍÉq]Šâ8†…'ÆuæHKŒë‹ÁqáŽ×™ 09NÈÆA§O9f ââââ:Zr\_r¨Çõ¡£rq!ÍIó iŽž‡Ë%³ô¸œ¿Bš GIsRSšÓå¦:§› ޳épƒÇu:%Èuúä$ÈÅMÈuNÐ䔸,A.¯G §pä´[n‚\ç@ ׇ¤6\ÖSyÁp> Sæ–¹Þå¤)ëSΞ9eyK‹ûëŒòI뜽N—Ìë gšO¥‹%.µyM:]ÖK¢IÎ;'Еœ.K',‡×e)räӥ=¢ÈyÖ1˜œ. õtº¬Ì¡^—Eš^8]>º<:]joÜtº´¬¢/óUw7Èç²j)7乯‡Ï%n)Õ¹VäO)u®Ñ–Ô¹X.OŸK­º§Ï%CDSkT>©sÚ#Õ¹qËMTê\cî¨Pç”Ù?Õ9m€êœvÇHu®¯ïê\[ò©”:×騞òܨBFÉs#ê‘<׫N~—Qsø]F͇ß%`OêÜ`pùáw¹$›I‹ÅÓPçFþ…ß壣ü…[lç çÕ¹GÓ0²œý¾¹]r+RÁ²ÜÔs~9…Ž˜þŠü¾/Ô˜s÷?´,Â’ãº0ç®sä=©skr5'ä¹Eß“”ç7£̹C »ç‹oN]áui{ÞœæÜ ó"»ùÈê>–ÐÙätyËA0ç~qè&Òé’‰]RcÒŸÃç2ÈMêÜä|èð¹‘åüžˆŸò¹¼¸Ÿ|ªs둬&ŸË›)”Óç²ÜT¿Âåò¡ˆ›.—º‡p¹,t uî ÇH©sö¦Àr¹¼Ý{¸\r½1]./M‡ÃåÒž>Ž —K97JžSjëp¹¼¹ ].µ™c¸\ÞSìG—Ër‘.Âç’MQ.—æ¤ð’Ë¥Üår©äÔérɨ‘p¹¼ùqN^d{ù\ÞÜI›>—ðÖ“Çå¥nL.—7ÓU†Ëå¾)t©r¹¼´)—Ë›̧Ëeÿ:8νD‚r¸dx½.'½>éoY±$ý-•@<ý-™™*ü-ï Eú[ÖJü-Ë ÌGέoKÅg„¿åõElƒ»e¥;¼-[‘„FoË ÂÛò¸ËÛr?áK ·åEï±ð¶¼é.+gËKÏ^Þ–á¢Þ–å7Êr×d9ÿø_@'Ñ"€n°»J —‚ítC^†t£ˆÖt#øM@§It!èlYš €Ž‹%ÁsC Š€îqÄ9x.ÃwÄs9óÏ…gHð\løHg-ô éŠüÒż'Îs'àìD:ÏGAÈ{˜ åQÔ™.ÒõÔE*¨€:›I´Sœ‹LãAuÖMƒAuØ%æt¸Ìôw¢:o¤ð‘TçÛ# LçàsKµ$Õù÷wáúGŸ›y[Eu>ˆÁë‘Tçßd9}.ÝÕš2ßÃÑ',¤:ÿÐ(´êü[¼Ï@ºØ@P7-—P —K÷C/(Ð8ôt~þ„ºm¸¹A¨s×g€¡n “ un¡³çâÐӇμ8ôL:ˆ êvÍœéê¦ap‘P·-ò|&Ôíz°‚˜nà-éö0uɦÛÕpëAÝ4^ég$Ý®‡ êv=òP&Ôí£èDF¨ój¯¤:s7ÿÒí¿3Ù³nWŠÝ%Dt»!s]EH7=wÊév™Î~œHç–rz\Îû òÓíSÉõ†L·ËÐíYL·ë‘‹™na¥L7ÒêJ·Ë0¹˜n¦a"K¦ÛјnWCgs1ݼËžî›ß·˜nZ&©vªsûܪ$™n—aW,¦›–£ Ï”L7ïÆ-ÅÄt»žÐôÀt^5ÁtÓ®âK7íœõ ¦›vé˜Sêö¼Hñ!„:?ªœP·kf'.¨ÛõTÂAÝ®¤òD„ºy×!gI‡:¯µŸT·k•@ªÛe.TçWÇP?PÝ®X:/©ÎŸúuú\úåôÓér[¤¤êæ­=Ku»bi ¢º[[Ï‹ê¦'ùzQ >‚¤º]O‰Ø9Yç=/éoÀºÝýë¡ëü\刦ÛÏ‚‹Zâºiïùˆ¦Ã=¡Z`ݶhºN¬;Z€°îžŠ!ÖÙMùO2¥-#å‘éîQðF¦»-(0F¦»ÇâÌILg—K ¡Î^Ý<].ýÉ\g(Ý®çV° ÎËêq€:;fý„:;£Ùu–i­¡tÇ] êìÜ´``½§ÜÀEu÷~Ò˜˜‹êî^˜ ¥ãç÷çĺû K†ÒÝw·¬»×‹éîÉÑ.˜Î*Y¯8º{)fXLgw ÓÝ»c_Tì0¬ÞKÉ‚:«ç:õ¹m¹‚á|d½-)@‹qt·E+ÆuVÍKŸÛeÚý+1°ÞÜS,î~¸ûJ Õ‹7FÑÙ£" éî)§`GºûéònÒÝÚøKHg—‘„Hg5PÑÓÙ9ð‰’éŠM\]`ºûQÜ4™Îl9|.§õ%œ.qY¸J0õ¯#ãèì5Üg ý½N—»ÂðÖ•KîÇĺ[‰…uÅv™B `]¹«¸ \W´C›ÀÎô`våV00ÉÎn‹ñ| »RÂ9dwk§;‘]á®Z;ËE¨×Ùß©|ëìYõìì²Ë vžàêÈÎo,:ôŸ8hgo'Ú•Kí•hW ×ÍHvåÒ (ÉÎ $9 ]Ùýc§çhWŠb»‰v6:q—ȱõ Û¿û“ùcöü¡BMUšY"gÖ/Ãüûßcë¾n£¬³ê°dV+Ù˜5'~f^«=ñÑç¬G–³Ø¢þ<êÙÓ«×Õð÷Q‡[T~ü[çײ…8CÞ¥×úÕ”Yž^«ýöôZ×ýß›^ëgM㱫îŸ3éÑ÷æí§@ãÏR¬)g±¦3q–jÊBªé,¥š"q–j:gEMQ(j:J©¦Hœ¥šŽÄYQSŠšŽRª)g©¦#qVÔ…¢¦¿!½–-.˜óÃìZãײk_É®õ³Vð Ùµv¹þk'ûÞÖ¾§púž]ë7t[|õC?ë¤þø£¶zö[¿ÐPßuüÕÙµ¬;ßãð“kí›ÿÇüç?D®«¿”\ë•+ÿõ›’kÕñ/ÿýɵžÑá¼rù~PgGÀ p¶Áö.ª“ϘÈqäý¤à¼r1mÌ3ä¿¿9Ù8¯h×Îg^p^± Ó 7œWŒ » œWnâû6ÀyåF4Â3=ÊËcµ}þÌV¿˜–ëÂÝÿ^ jìŸË¯»@ÜÃ3œ< ÎgnÝþ 3g®Ë¯¹0'È6`\*TeŸi 0ø|ê±0váfÒÖÇ"Ô™ã Ü7Á„h¿;™]q…Dºçvîíðx>/ÿôz,1—]n¥_Åãþ5ß8¡àpã)30íÊcn¾žìÂJîc[ x´8Ó°<¾ÓÚÇ#Áq’ë¯Mg}® ?ñP,¦´”0Ô 7œÀ"žß2샠ð|À:Ó‰<&—s{<\¥©ÁÅW¹cƒ¡¡Ž°Î¼À§¼…Á_ç„§¯ˆÿ–çˆCàãË¡ôÄÁß=¾×´}:¸{‰«ÉIÌf[îWŒ|0 ý6Yï¶”!—+³m©ôܤ'÷¶4ú‚1 ˜Yž/CøÔ~[:üÁäæ¾-> òïßþ`“k¢fY¯P‚mYø¨&7ðÙÛ –õìÿ  ]Ñ̲ü&7ܶYÚð{X\LØ–Rý.¶ÅÒÖ}<¬œ×s{è¦ïÝ×Y³{ý,†Ëìß½ú=ØâëÌ\Æ|$fY~}Ï…Wµ-–Wèãñ2²ÌgìyÁ£<ýUæñLöf¹q5†, ßéx:űJ®ûwA(Þu¡ñ›e}2àgÿ®Æ»$½- Ñxƒ·¥#ïâJYwµ¶2w1ëñ¶L„ä]Sí¯,Ää)+™YàCss3ÊmyÜ…¦è=Õ‹‰ËŠJT ùþx¸3ŸC½œwwµ>›8-¸âL\q­Ï»á­c䲿™4z[âóJÕMÕŽdö UÞ–=…<›å‘Ф[5|Û!¦Ãߨ°–QzX5‚azÜêoOæ/„é•¥wiÄ(twÙ õ*AÕ,ð¡A¶k·Ô¸äx¢­!V¯V}ÏÍ7äD˜4ÏÕýò¸µßþ blÝýa‰‰x½v©%q‹ó8â·j›ÄpÃ•Š·`›ÄTèOül“˜Iç&Ôc›Äø±ýÙ&1ãð&Ú–2°·¢·¡úHéÉ8UwÁLþFö{iK¶‰÷Ý;|hlO<šîÑ¡ŒkXv}q/8ÞY㦱žÕ¿˜t»ááh‹˜>1Òß—í3àásß´,ü,qwE >xu#ÃbÙm“s²C²Mb¸ ;?Û$†>Ilú¶I Ó£³s±Mbè®ÃV< dš ÂOÈfëÚ¡†U´ËÄã#;+l¿™»Œ+Þ÷5%[ÕCM µ'㟴 NÖQíSá£Â¾äØ!æÆÕLOƒ--Ìe?£LŸˆJeäÒ¶ |жý1-³À™ˆ}”mÃ|lkY!µ ³®mñÕ;?Šmßöˆq_º…›B¦üM%³j0¶—ƒ ú«ÆïÁòpàjnO ’’s.zîði–N*LGšK%•Âúoͦ•$w_œ$ÏW\E?– ×Dv9†•ÈÙ2vû wq¼Sr®¹kAw »59ŽÓÈÝÈ€w3G*9î.ñ—0I»« d¹»ºånîâ,wsè–»™Å+Xîfª­`¹›‰%s÷#¶"ÌY#‚ÁiN©Äè‚WtåV ]a–„ºB >€®pS¬ºB×ܺ¢W(¢+ºu]ü»ˆ®0/@å*ûDÇuîºÂ(€®pt ÛÂ$¿èÃ#.^8 ÎÐuè*óŒé*Ýé*w ¤«SÓ2!]mš éjû"‰‘èêÐÐ.¢S†µ$º:5âŠèêÐLRDWŸ`EÝaq¢³}ЕŠèêó诒èvÓäB’¹%Ñ1\²»%е¸tN/n ÏÙ«áç–K„s&ㆄs Þ§Ismè‹æZLDs6;%%’æ”w+5ƒ`®­1DÖÄc!̹û`9sälš,geÖ‹å¬%DåÎ2`9;¯ÐYÎa nö9о@²œÕ¢2ÜîsÔ(³–ÖŽTæa´^¬&‘åÌÒÈi÷­œ÷„²\„µËEünÀœçàQ”|•„9[·5ö§/˜óPM^ `Îê%I˜³„0€å"‘A°\¤Û–‹L d¹ó7XΖÃ8ù ˆ¥óT°œ§j|±\d –³£Ø'å¬f¾²œ'a=tJµ»%ºåÎ2ôJñæ"dÀœo!@4btìŒ%)œ%t¼eÁPªsîSH b„¬rŒÌyH"cd§æÜ‚9¾NœMêsÇ=æì˜ù‚¹Hh0ge–ÐíÖãzÁœe²dD˜3 ›èRΘG£ aÎë!Qæ,cP{Áœ-L²u-ì”ÐÙ„¹cé’4§íæ¼Z^`ÎÓh Ýð%.ú– æ°ŠË#Íá`7ܱHÊ… ЮO.’.¬=ØÛ¡|,—{HˆårDZœ/£6–TWWw–ÃyxÔºtlÕÜìÓŽÒõ>UòåüD‚²ƒêšìó‰rÇ*/QÎ-•Vñ9¯D°†au­®†aõáÆB9?J–aõ¡ƒ•PîUò€2ýPîu}JZ «Ï-ÔÊù™ÐŒˆr^æf*áOFrÃÏõ$ÜQ–|øaþ)´‚æªÏ”š« å!Î5fŸœkLù8§ùdà\ã¢Tàœ’ε›Ržp®Ñ+4pβZ¥ÈsuI¨#ÏYÞt$¹ƒ¾„¹ÆŒøtMš‘€N{ÜÐiò@—‡è¬øMâ\¨cç¦Péf•×Pçt’ç¸c}*tKÇèz¥) Ó .€®Óå7€®SÄ  ëíÐõ*($Ðu.Üè:ÐuÎäè:3éÑ)ô;5:î ‘]‘àF¤SH79ñ ¤›S„F¤›LgH7¹~C¤³ÎWA¤[¥D݌مˆnÅX-¢[úÜéRÎÒEG-¢[1_Ñ=M²„ˆî¹ãT$ºGËF$º§iÐÑ=-U; >GÝÓ5-Ñ=]W#¢{†x!]jWB:íð“Hgn€ä12­²0ÝSFèd@XVÔ¨3i¥K‘C<^i IuÞj^Tgõp’Bª³2MŠÜõÅxtNvHuf©/¬³k‚Iyí|“Ey›<ÊxÿXQ£«Sã»4:ShhÔè˜K6%:“‚x%ºúhL•Dg%/Ž] BvÙ‘Dg]±‰]»$üH¢k7W%¤Ð¥Z$…®ÕPú¨ÐY ËP¢ë³’è”%%º™ÌF‰.„ )t£êB¡3ó[¡›E³.)t#ô)t–Q 7%‰Îf—D"JtÜ¥>:ã D…Μ¸É‚TèfH¡3ovrº9Ô@¡³Í¢Y‚ ݺƒ ©ÐÍ`U)t«éYI¡[E‚—:mb“ ݺtRèbÊ'n×ê2Ú[P—ûŽêÎ5~@GJó&u~ WuÞÚ„p—Vý)ê¼fYœêrƒQÝy5 ºŒqÕù1œBƒê|%ž-h3M'Iu®qÞTåuRÅöªC¯ô¸ «þYÆ©+ú'Õ!@ø¤:¬äRÔð(Y›¿²^§:/Á6;µ;Iˆò :_ѧkÄd°¬MwN‰.wÕízQ¨n—!¥1d¶—·DçeÊ)ÑyÄߌQÇ«±CÕí—ž ¨ÎãâtÅNuüÅöªs ‡PÇ´ñÍ,FÏÚÌ4Æ`CÛ"‚e@kS"‰vî¡©›ZÚ³dr- yÿ°ƒh»¼Àt{®Ú´H»E;ê×)ÐmÏJuÎz;éuPçF >:·HÛ¢<×›¨^úÜ(¡¾QŸUË$ÐçF¸HŸ3zᙨÏö%ä¹þhh‘<7þ?îÞng—$YÒ:ç*Öa7Òÿ‡ B ¤ž; ±¶`àúIw3s\UÕÝÕÚ¡9[_¬ÌÈŸ73#ž0wóŒ<7®ÇJ›[Ÿ#©s3~k©sSÃ0Õ9;[âÕ9Ó‰PTçlþFð¢:7adžâœåŒ¡ÚÜdòljsSa¡Í]ýR›»Z¨Í-ºü§6·nanQúIanÎó(ÌÙ`tÓܲ¾Åeælq–0gÉ ”ó(ÌÙ2P1Ì xøöYIp^Äþ"¸^Å_ 8‰Ap4cI‚kX€I‚ë”=‚àº`KGÕ# Ž ÷Ipƒq8-ý'ÀõŸŽVÑ8z˜'À5õ €k¿|£+{U—8ªÉoåì@|늜$½íŠÞú#:szËPGÒ[64ä’ÞòÿIo…í2¾22ã+€ôÖXÇ4è­i„¤7É@Ao• 7ûóCo‘Aoуè­Ix½Åi‰Þb¡ ¹Cì A.ÎB‚œ®$¹ØE‚œ¢_)ÈéJC‹³ w4ùAîh‚\̺B‘Ë)r¹—¹W Eîj EN{¥"'½möëÖ9íC~»T<òÛuUä·“_ñÛݲºñ›®ä·kòÛݲãÐÐççô¤Éé‡M|˱À·¥yŽðÍÖ}Ä7™!\ø6S‰oïÜã'|³d‚L´†ÐQøVc ¾Üƒø&k©Ä·Q%M ßFöK~3 †ý’ßúÑUŠßFW¡øM… ’߆>úä·±8R ßë/'¾½}qò$~[[§'~›EDüz°øíå ùm=Õâ·]µd+~³ìNÝQÕLj± "÷ذZyMÝ…o;ö ½íÐh@o¾çÜ¢·}»ˆo{ý`yZ„F6ä =3B#;,Wžò‹8d•ªÉèÍäKoòØJz;¬öxÑ[DÅÞtø@€ÞPN‘ŒÍWÄ ÃºB¸¾eÈŒ¯<±DøöH |{nM¶Qh ½Õà_yVpé­–8aÒ[MV½¥Ø—ôVîøÊ¬O)z³Ÿ‹Fz«SÊèíz EoHÝG fŽVˆñޝL‹Þ‚|Do­fÄ%è­†>-z«K¡¢·ëªœÞžÊ£è-HCôfFž#½%ýŠÞÊÕˆÞÚ£E(Ñ[­z?Do5– Eo5‚ªEoª“™ô†œoqzËßAôfŸÍ/½ÙÏôöŽ M¬z³ºÓ·&‡žÉjò>:±é­—ÁTm2¾Ö¢·6,)x‹8kÐ[o!Ñ‘ÞZD­ ßêð©âdôJz+[ï³®ÅÚªÎ?‚ÎÒî‰H8‹Þ&iàzz‘ßúÒ“~«[º¨ø­=Zi¿¡ç\×"B7F(p8S¾÷îÅçH×¶ž>\ Q § ŸIpñûÁõ)^#ÀõZ ®ŽÃƒêþhr68 ÇëäáP¦ ä,êúÑhý9™S’m¹R’Û;±îHVŽQ’›”R’³M@£$7¥<‡$7glÓ‚z+ºòï´Ï  ë>9¿€nLÎÛz:€n¥ÒèX%xnÁ.pn1r(pnÑå,pn­ŸpnÑÎ-x΂½ÁRä¹E·¸à¹ÜÂyN¡Ásk2"“8·¦6 ÎmÖRœ[[!˜ä¹µµn1 *ˆn3+ˆNZ‰ní_>Ér‹‘Ü:)ýtRuèT_(€nsò@·ùÐIñ Ó³@'E7€îp…‹@÷N-ð èÌøü ³Œ!‚€Î‹<Þrœç tf÷»n9Îò|¤¾!ÀߌçÐ)€ÎË.Þ@gI>À s«ÜÏ# óDœÉs¦ÖPþÎY çÊÄ9;]‰[å(Í…± Ä9• š3@9š‹JpAsQ±-h.jŽ‘æÂ7hÎn˜sÓ5n²Y+œs„7ål. ,g·OYl`9›ï÷çF¬–‹êñ©Åí‹älJËaSB܉sÉù¤ò¹ISe4,õÇÜ Bè`ЉÔ9FôG” (îžàÅùš<'à 8ÌÄuœÓI¦kCƒþsÇV¢î73Í Ehk†­ýr‹p>nI\X2©ÿm,Žª,)@œmƒ?Í3ù`Épô`:¬ŽÈûÁÙê±d<œ/L¶;¬vmj‰CåÑu¬®xnApë9]ÓsÜz,òެ\Ïä½fgE3o!œÙÜ Ü»Í£¸10œÛ–IÃË‘¿“äV)K³V0œ[‰r4%ëºd8³6ã<‘ WJ@!Îz–p7z 9Ĺq˜øÑ!Î-À¨]âÜ’L‚ Î,É”Žˆ+uhÎLˆ3Ó¯G)q>y4ï°yV.› (¿ \yŸ= w€8s—z.ˆ35%Í9ÃÙ‹\?œuÂã@+=¸… g/sû(p椄=0\yû/†+ö°}8s ªÛ°êRŒ"η¸ã*ýØEé gîXʈÃ™Ï %M2œ9‰q \xK•]#`çöF®Œ[#ÂY? á4„«OÈD¸0( „3ç¯gDÔ‹ˆpöeSØ"®ìˆX ™…“ð g6DG’œ¿‡îCÄžpö…<„3_'kUü­pM œûq œùíÂÕò|Ã*ÝGiI’s„«5Ö/‰pµ*p€g Œ;'ÁÕ6“éœàª‘=AŠVGµ ñ@´:j±ÄE„3ç"ê«d¸Úã]%ÄÕÖB”ßÑŠ‹ÄÙE=ˆ³3–~ˆ«U qNpuĪ®ÎÈés„«=Fh"\}¯tßa•~ºM->˜V•È„«Ô$‚à¬%ðà¬EHçé‹Â,pu(UW#¬_WâWU¯*®ÊL7ÎúÓA„«*r"\UõúáªE~3‘ "œ¹*e"œí%‘"\]šŒ@‡³¿ûUù¶h1H:\e¾áê¦â ÎŒJBqƒ?ÙÖò–4¸ºéH\Ýôf¼²ÞÁf¯ L«L7 ‹,¶„åÕïïÄM´Á?b’õ>²åî™_¦TÞ"ßüq™ZUóóÝŸÔr÷¶è…^ý´Âö¼Fµ\ý°MýèÏi“¬bß½òšdíÿ”&Y¿ñp”ý äø²Éúé)óGh>Ÿçî/Ñ×m…¾>FYìëÚŠ}}í´Ø×e‚žn«,õ•[©¯¡ûºl°Ø×m–¥¾r+õõ±Ôb_—ûºí²ÔWn¥¾þ»¬¾àiþŸ‡_ÖßóûË÷£ô«OÖ_~óÁý|Æ~ç©ýöò‡=³ŠM÷Æþÿ¹iÖõùßÿù8e½·k=»b|¾‹«ñes½GfXo‹[ÜM"‹§óâÓ[Ô‚ÕÎq0”ÎdafÕ[´…§ÝÂÓn5;Í\e°‹UnÅ+Òýð\]&²oÉøš÷Ëaêí`?’òŨï¼ÙÕë©YÄ‘’/÷ˆr 2ûšdÛr¨äw)pÅÂŽ=FC«"åPÉï]s!‹‚e´ g^LéGæ~[óaîçäNë²CÄWl½†ÙŸ‡Ý,†æóW1g‰þ#ãæß–Ó"NÞêC(a«šTèò¬ö¶PÇÒ«éaë»uüA ¶ÚR=ËËA¨OgÉ/¬ŸT Xénòd˜\;%)V ­êŸn³ú¤×w¶ÿ ˾ñt“ú”Yͼ~ÎżÅ¶ÁJM5$/?®|Ñj¦åÛ`º÷¶(i‡. ˵‘ðX‹²kWªùœ²B"Øjavm$vVû¼ûš¾1javm¤IV÷f ·avíìœ÷U3‡ý¤EÖÊüÚ)_Š—›ü½øg”¬ÅÂK5ÞQÉKvÒªZXô’fcoK_’%°èöNôXöR?ñ‚J5r¦×NåWûP©†:[˜`»dcör”ª;³¦×ª8vynJàïÒ˜^KMâm¨t>;º‚ÆìZ)[SúÄ\µõ®møôµÁ”¾ª‡¢£ÔJþ¼mÒù,{^,©ž®mÓù •d¬aGV"[˜\»$fÕþ´ÐQpèÎäZ)+ÖBã3#}[˜\»„µ7å,Ö#y[:·à.}KJ)<б„}ÌöÍ™|Ÿª%±ÉÚrnãÏß÷ø*oËAJßRî]RúK£ZËVÎ NÆ ¾0ç†Þ¨íÓ­•{ØbseÖæ6)}këÝʬ=„å:æ£KP?ʬ=ú4Ú ž)?:bˆ²3«Õ{)hØjÁ[¸µDõΕŠn­à [øZÁþX®³.ùça=ªZÁ—gqq›^%Æ!Ä©ZÁ—…¬5T+øÂb¾>S‰µ¹×ˆºhWh-GéÁêg³ßÎc+±Vrµr/ô÷ãù©ˆg^ƒhp)£ªŠç’S_]­(XÛ4¾ÍÊ`¯‹«K&>uQêÌ×eQë\Zh}[Îw ª‹…ÙÞÉ’hë’à/Ô’äøÍÌÚ|y·DÏlají¢Ôj-”=§Þñ\Œ2¨[ª§-ªŠx®©÷}KùTžEÝÌ­½ö¢ø¹´„R÷þé}ÞR?£Aê§âžê¡üËõPÿ\Z¥®§ìÏI Ê ¨‡©µKyñõP]ò3k—b£ê¡)Ûõ0³ö:4•P~X¾Ó7àq(„ZÙ@nC)h£=.…ÆaÚù±$Ü·…Ñ­K±íaxkd†·‡ñ­‚߯·ÆE·'Ó”ž˜GR~¢R…Û“ Š›-«ë[XØÏf’cåí£³ë<;e).N«wú6- s]Z†k,ßy»0ÌõÚ†“㼆Â0Wû¢¶Iû:–¬D·nN™ß3.+rä1·l…a®ñ]nEV¢¹—¬D•Ù¬Ò¿æU-a%Šh¥f¶ÿŸ§¼U†¹^Û´rÎ[eë¢ÍDcùN¸…ŒDs®·lÍP[¥õÌ~ð'aWãÊßkªuAŸ{.~ /²úš‚S}BMú䵕Ð÷t­ß úd¿•Ð÷0O1 Ï$ZvCè“EWBß3 }Äò€¾GùŽ}.þS0ß3 È|*€ÌwmCæ»¶!ó=²{ æ3s:Ò$™ïm©„32ßµ ¡ïj!ô½ÏÑ[Ð÷ÈÖ’Ð÷þ½yìÖÕ‹ûú¢— ¾gq:,è»6!ô]-õëz–Ð'—ì¤>Y¥‰ú®}H}W ©ïnÁe-˜€ûÞ–Î~‰}(‚û®½È}¶ ‰Üg{¡Øgõ›lľìØwuBìËNH}rË‚ú®NH}W ©ïÚ‹ÔgŸŠÔwmCê{”†Ôg{}©ïjqêË^„}W ±/-ì³GƒÛûòØÂ¾‡‘.A}×&ľ·úf`ßu(b_vCê{dvKê»:!õåÙ‰úòªE}×6ľGZ\`_ZÔ÷l=Ô¢¾«Rßs’®@{‘úò”A}פ¾»eëDœ'¼¹°/ûö=JdìËóö]ýûòVû®}È}×侫…àwµü®³!ù]Ç&ù=¨qžà—øÝ-¿<”ÈïjqòËC‹üâ@¿«[‚_nBî{äÌÜwõKîËK÷]ç"A*EðËCõÓ÷å.â¾<¸/OOÜwõBî‹ û®†£Û«^H}¹ ¡ï:Bß#¿€€¾«›ýýÕ}yr‚¾ÜGÐ÷(À EÁ܆З¿ ïÚ†Ðwm£ªqû}×^r½ZÎç*}W¿YBÛÈF4¯A>¢ -èË~}¹— /ÏFЗÇô][ú®^H}בH}v6DÇùÓK(è»:Þñ.ëФ¾ëPľlöEÇ¢¾¼ ¾ëoR_ž¯¨ïÚ†Ô—Ý’úòìD}×¹ú®mH}wËúé üòPä>5ûbÀ¾¸½}¹ ©/®1¨ïê†ØwuCì‹ûÜÜwmCî»¶!÷åéìú=±/7 õåÙ‰ú®–R~ºQ_ž‹¨/ÏEÔ‡ôå­ô];ú®ŽgÿnAè»[ö÷! è»Z}y'}qzb¾øªó];ÕNyp0_vÒö÷% æ»:íû’¦Èç+è{”îž"'·ù\‰~&aú é'~½…|V>¾£~]‚@ _Wa _—‚ègA²¤8²_< ±Ÿ½„6²_¸´ûu) Á~}(ÿBì×Glãð×Cü½³† þÞ~»$ÀóÓù…à7hzß”…÷¥÷ÑQ.ô>EJ§à7Gìg س?­N’ýzüPb?e­'ûuY ûõ”#½^bž¼tÕM°_Üó`?³D£îFöSº´Ø/R{ƒýš‚ȃýZª„d¿È÷ ö»ŽDö“Y²_$GûY ÎFìwµþìÍ$KþšJþ®¿ mG/¤¿&ë ¿ŠƒþšŒcƒþšB¢ƒþTë(é¯Á¦:á¯Iø³MF„¿  ø3g¨Â¿—¶X_øË‹ü…#tÀ_œŒØ/¯@ð×Tå"௩EÀ_^¥àïj!ý5½‰¤¿6Bn$ýåé‰þš2sƒþšB‚þ®mH-¤Má_[’âzxcw¶þ®ƒ“þÂ-;èï:Ôâ ÷¯æ×˜ô—¿¥è/{ýå ý5ùOýåíý]{‘þšÂTIù”ˆþâ÷üå%þ®n ס rLø»MúËÑ_þ.¢¿¦4ƒ ¿ìô—?‹è/ŸGá_Þtáßu$òßÕBþ»ö"ÿµ¥QüwíEþ»ZÈaŘç lqóŽ ›"tóþ -‡õK€W?DÀ«…˜g,¼Î ˜©0 ൠ0$ÌG˜!`>‘BÀìYxõÜ~~¡…€ùã„E€yÿ@€ xuBÌO¦0ïŒÐ.Šº °)H;0÷æEí´Õ6m~nðÚ‚x·ìŸ~àu6DÀëŒ÷óýì‹›ü̓óEæ s/ àµEU½U 00OO ˜%ÌŸJ — ¼µb`U7{ü4*‰c¼#ªÛ`À8»`ÀxHï–WëWû‹< 0~Ì€ÀëXã§5 0îy@`\8)°1î, ðÚ@7ºJA`G½ˆ³1`ž®0o„ 0»‘¿M4ÈÞ&=û·WÙÛh†˜¿šðÚKö6Ñ"Ì#‰ó'Æé cÚGÌ“ÆÜ,0¦ Á€×63^AÞ*1àÕBTËßðíº¸Ï­oÉ},cÜG÷å‹û’ Å}ª/‘Ü—÷*°/Ï÷„-öúJ~q÷’ût‡“ûhã™Ø!Â>KˆfÇľÈ2"öéƒúdÔ×3ˆ“ÔwuBêëŹà {(®“kúmƒú²Q_ö#ê‹§/¨/ž#R_² êËû)êëÊF ê»¶!õÉX<©¯—86©O¦oI}yU¾ë|ˆ}25Oì“9¸°/¯IØÏy`_Þa_þV¾¼*qŸ ì&÷]gCî»Î†Üw‹Ü—¿•¸ïêç°—øûèü$™‘ûò‹ûòþ‰ûòlÄ}×6侫Ÿï3+_Þ_ÞeŸêÈ}yÙâ¾|pÄ}×NXÔÿì™.î‹sp_žLpßà'=¹oþÄ}ÊzKî‹Ia€_`K€ßøÅü.À/ûÙ1ÝT??Ò¨o*RRÐ7ŠõÌNÉ|q9Á|3XMÌù²!_î$äÓê["_t#â Æ âËn’øø\Äljoßþ‰øfññ„ƒør¯$¾ù õ¼8Qħ”†$¾˜bñq=3/îD©Q¸'ö<ý§… ÷n‰{‚;á^Vâž Q¸—Û$îiá^ö,ÜËmÄ{‰à=­ÿ5ÞË^’÷„¬â½€Ïà=Uªºy/è®|q4p/ž¸Ç]„{q‹/ÜÓ6½ìeŽŸˆ:p/~¼ßǽ¡Î ÷DF ÷ž;Îó‚² ÷„½XS ܋˼pO{]â½<Öúi5p/È ÷€Â½á•{D£'^åó+ÞƒÕú½„›÷ÔO[ß—áæ=†ú]¼ÇM÷´É\ß_á¯áž¶¸xïëÙ””ŸÀ7õÀWKˆh$>óiâ^$¾*{‘ ¾k/ßµ‘ïÚ†ÌwõãÌùÿÁ|¶i“ÌwõKæ»¶!óe¿b¾ÜFÌwµùTÏò‚¾¡¸RBßõ7TU´K蓓Ч/PBŸô³„> æ }T£þ€Ï×€þpÜhŸ‰o¢­»ÄŠZ ü{Ç=åÞÿÌ݃Ûÿ¶,ÿ²~‘ðïб.èï4EjþΔնàïÌDÂß™™÷‡‘ê(‚žðwv`áïDµ'ÁŸy}áïìŸE?«¸üø< éü™ÙTÿПÕñzÿÌ:ê«úyíêgÝ)[p¹U¬ÊmÿÌJà ü³Òæ8E§¡ZÂ?wµ#íÉã©Nÿ¬rF•ȧՔ“@þóúlé_(àÉü1`¸±’ÿܦ”Ñøä?s–àüçÕ‘zèÚ¿ªŸ×Dàtüw¹|’ÿÜÙiÜ!ŸîÉôˆ7 ˜ÊéçNïì„VO]ŸÄ?7Uäý,´z²:4ajeoüs£¦uãŸ;5©y=üÀ)tH¶£ß“½º™ç·ì–)°À)Ô {°¥Â)t+Κô·lPX7ý-³ ;7ý½ÛÈG™ô·ÌL¨£PûÀ܉~Ëì2È¢Î~«<1ï¬ô{z‡êG_…ÿ“”Cº=Ytþ­ùùù2xW쾋Á~{)+Eìg.&_Ío«Vw°ßÕÙïÚ‹ì·å`ì·UçšðgŽUdJÂßδCÂß>q$Â߉ 2Á_— øËž[µRþŽ’ Å~;žP°ßVºC°ß»Ëø²ßuh²ßyB“$û™óZ¶¾ç|UÅ~Qm.Ø/ªÍþx ÅG¶Q€×6€×ßÀS#%xJÈn$ÀSB$dA€oËO¢ß©!8mÜú&ûå• Oc5¸‘*mæ%ˆ£_à‘Gnà‰ï£ð݆Ëw"À(Öhfml!úA€§G|) ðD& ðÈä5 ð´D>Ž«q‚ÀCÓ­`Àw§õ•üò Ä€Q\,Ð<ˆÈ›dÀ(u xä“ xF$:ž¡“!f ðÚƒh›ˆ A€v¾ß˜Ï«…ø^%9Gøö³¿Šßµ—# é›égC€ïÑùi"àÐI¼Zˆ€Qd-ðݦIÜ?ý bÀw/ö#´kø2àQ W2à¡co à™Š²$^}ßMú7èój!žÌ!TÍÌ!$¾=ë\TDS…ã¼c"àý÷Ò‡-DÀ«…h#/c1‰€GYù€'rÈ„€×6DÀC3ÓdÀk/2à™cJ´ ®4¾Š¿—òÿŽî±bEÉ€6™"s‘²HƒíØjá{¨ UÁ€Gco0`L·ƒ¯mT–p«©,áâ3J¼þVYÂÈ|æu‹¯•%Œ~Ä€yUbÀŸbÀk›,K8”ßÇ-´I¼ö!¾ýòNˆÏ*$^ýßmøTˆõíø®B6O{§\6l¿ó7²ùoþ¾2ÿ:-dþ‡?¿Ÿ£ç}jÿô—üÿÑøÿ?á;óõš1÷—ýËÿö_ÿÿö¿ü;ÿwÿçoãü¿þW±ÆÄ³<Ì›ÝüoïaØÏoúòüßÓmŸÓý7qÿüÛûê_¿}]ÿu¶þåÏÿª˜ëO÷{Wþ§ËËçü©§ßs푊[«½—}§Gï¾S7¥dËHU_fQ½ûÝ[þX`±º›Ëë\^ݱåokÔêÂæoõÓ[þØŠ‡ºëæ½ù¹@¶|öš‘ûÇ;jtå“Éi-é´÷»;Éiü#N{½¦¡¨ïh¹îØ&×,ýy9åu¸g/øûîÃZ¢ÿãÚ<ÊekTËÕÛÔ‹þüwÚëï¨óòÃÇjïw}ðJ3÷Öúû^|ï9p›jý û¼_ÿâÍŠ°®ë1ù˯»!M Œ—ÉúºñÐ×Ç}][ !ß&{ìë2Æc_·1žúÊ­Ô×Çd}]Æxìë6ÆS_¹•úú˜ì±¯Ë}Ýöyê+·R_ÿˆ}^[þWìóä'K»¿e‘×þ†óÝONzíol§Ãþü\þM'½¿ã#õ—ïGçWŸ¤¿üö3|¦~ûþ©—?î¤×lÓÿÿã¤÷Ï¿ÕÇÕøÇœôš­áÒžð|¿ …XÒ¬ @A Öš-Ùz‘{Ú™¾E—I…-ÆzÑàÂX;Wr<÷Ù-ÆnÃP›»òØgKÁt¸? •y§=˜¤v[kU¸êF‹BeÿÄMTí<ÑTC©?N2 Ýþ0NÆÖæÙËðFC·…L[Ò.Rªº9ÎÛru“#V·%Ȇ‚ ›{í…åjÕêÏA1—¥r˽<¬©¤úêÝàéôØ‚µÒÞuôwª€ÕU,põ•R3ìâ> û[•b{áJi”Jïf/¾á¯#a©ÔAñoË‘©xç± ¹Y™´—ÝáÙ-çän†Þî­:ν8r[ NçÝß¶Ð*}¯~ÜSÅ{zußEw"njq?îf’nºyVÛ¨ÒT=¬W_*]­sõ¶ 7Ø·2X!ìÕ—Jßy–ÖÛº™3¿×`ë¡…-ËGÁ…©nÉÃz)ql_*}{éX/àÜf½¿Žž€ö`Ð3ëd<}/–bÒ·©š½-î¯ß£ÂpoÕý¸mëmÝèÂ.ao=Å­\‚|ÓÞ÷×ï|Þ/ÄûÇ`Éš÷ïéÖúVI`s‡å~Ü}háçmqÙ£oÖÎy[6,h•£êí4x¢KrìÝ×I—¹ØlqÙ£7nà‹¤ï™ý$ïïæg…!{÷eÒ÷ddn÷¶Ø]1‚æ¾Hº¼ŒN×6¶ ØÒÞ{è¢Ç;»ã³Ù§kýhº÷åšÇx?XYí}»æÑ§’²{?®yô-ÿ®·Å5_îÅÁÇã¢Çh*H¾Júªè5xa»¨Nôû·»q?oƒï¼F“kY¾Dºìp|2G?øÕ‡/‘¾Wpâ\f†d?¾Fúî5øçÁéyûKl§Âwbø²ç橆mæcG)ÊÔ{ÿÆì©t=„³¸àaË×X\ê³bÎ5T¦¤Ïæ®ú­+Yêm9xC%“ôÙ'foR";Ê>­qjœÍt[}+÷Àk4Xã‰WÂ*? ü"SÞ_ÔË[Œ*÷nÅŸ:+,%u”z¯ŠrQGù§ee$°îÑ­þ“m²˜ƒÕQÿéíwñOL>ß×v²ÅË?ùCÆ×Ñê?ùéËR¯[¨÷¡S]· Pöü޲¯µ¬$änE ìôÍ²Ž½øê¨½èüÓõí±‡ÓQÊž.Eu³L²³´ÞQêÝkèÝÅ=õ»"¼ÁGWå­[-(EÔ­¯¾[ÈJ©£Ô²r!êvðV`G=¨÷Nuæ:ÙP‚Ÿ.T„òâ ülúg?Šî¨ å=óQÿ²½7B¡%Ã*DùèÑy6=àý"Hq D”ÿ“½xü€ĵ×Á ø¾<¸5¢Þ~*ÊQ<~`ùøŠc£FÔ2Å£Ù(?°ìkÈžQ#êmQyÊQ<~À¿r¸V%Ê/©²xOæá¬n°JÔ˜ú˜Ž‚øñ,uB+÷¢ôîQ>ÐMúb ªDÙ»¹ÂìׯE²N”5p“Šè¯‚ƒ³a¥({ŠøLx¥¨îã¶ÿ‰BQ6Pá«8X(jt™ÚŽŠèûµ1´ŠMvGEô€ ¿‡'ƒèq°¨ò6 x`>²š,åÃŽè{øÐ/‹EÙ Ægc4 C0X+ÊÆ;mà‰xM¬e·ÓÑ<0¬j0[P+Êâ ÷Bð€—]Á ³VÔ°°ðÊ ¦S)á£aJlã{e?xÏ”ãøh>`5…t~\‹è²‰áö]f¿\u°ùX—“ÂßµxzÃÞÞ?¯QظhÁvA{EÂi¯RÜLÚSAͤ=Jí=*«´÷h6´÷H Ú+r¡ Ú³W_Ú³âY$B_U…ᾪIxïý‰wQ6¼tIñž WgÉ{{<ø°gÙ¶{n£Í]{é8-Ø3ý’` Øóòˆœ_ö\”^!-Â*ðà6ë¡ì ÿFN„ Uëf=gQŽ}`=¯»ÍÖs:%Ó‚õ^•KYÏ [s²ÖóyœÚö¬ZŽZ{Y?U°çÕ…qQ{V•#:aïɹaÏ– ›ZP?7;{TEš"ìY]›.´C55KLà6€½¨¥%Ö+í=¿a„L€ž]:6‚^®éÙ6üùIzöñÒ³@'H¯ZA]ÂH¯Fud‘^µq‰Ò{Oó—èUž‹ƒ^(ž•ëá#EÐkïGMôÐkˆ‡½Öè#ÎkMQ‘â<;Ÿñá<«7Äš¨×ŠÜF„zM€óZ•Ë>8Ï/’ƒóì*ù´óÚTñ.qž}e×ôìt9ã"èµÅl7q^#›òÚŽß×,(ˆÈëQI"(¯9ïÙÙˆÜÀ{ö(?$Bðž=Ê|òÅ{MÓžà=›¯r/ðžM¸ç‡÷Œ§Õ3y¯4±œx¯Æ‚Œx¯Å2¤xï}°ëÍ{-0W¼gU6Ø yo*ïN¼g{éHä½Öôõ Þ[Ášà=»üÍÅ{+{&ï͘òøVŒí>+aÉ'ʼnÏÞáITñÙ5G„|S¦õ|SŸå@¾E‰ôB¾8GäÛì–¼·™Š%Ü›œÛ‰{Q2qO׸gfù<âž7ñ@Ľ%žÜ3d!a÷ìØñ ¸gß®Åm€{ï×_xáÞ¬1½î½_“C¾sÞ³¨&\“xϾZ¢;O­èb¿ä=›Õ²Àg’-¾)“cñÞ,ÊšïÍúïÍ'PH¼wô ïͪé6xo>q.>ûhï |³¨„†€oVVaïͦQA¼7{ùºªýòY€*{!òY!ð/òÍ'¶QÕ#é|HTÃTõˆëùæ Z#ò¥"äSy_Ä‘ùì~ˆ-|Qî=%>S¸%>»‹Ü‹_WÝŒ ¾3ƒH)ñ=1ÑÄ÷Äš8©Ïj•K®õY„'?ü’øž [H|F _‰¯(Ï&°Ïø g,ìÛ+ÐØ·ûWâ›oÊ©§°oÊá#°o*~šØ‡Zïìk5 Bßz>ØW+K¥‹ú¬/±¨¯ÄŠ'¡¯|>«dÊÁ–Ð÷ì¼÷¬$GßÓ…Ð$>{rÎ}±¼»R÷£Lúš­K²ÐW£$W@_ÙQ€>¿]è³"Ѥ&BŸµ¦Lè³Ü ò„>˜&[| ²„᤟I¾ûɾ*Ÿ bœ MÉ.ô2ÌÖ' €ñ˳!ګǧ‚XºÒÉBç3\¥FGŒÚ€EF`À÷‡æŸ>Tµ\ "þÙ“J¾&þÕ¨#ü«=$^âŸK¼ÜhµµÐrÁøÖ‘=ƒŒÛ›êçZý7ntZFÐK~E}9€»[ÉÖH|Ö¡BÀjÔBœZ´4¿ @‹±æ•è;Š@›Bðü$ö ‘‡Øg‹h€Ö7u â¿:ƒ4ÁöªªüçS¶lV’UNšøÏÖqžÿÕ$sòŸ}¶HÔ俞>â?K⑞Fþ›OlãüWdýzßJUŽz_XSŠÿšýbÜü׆¼Ä¶"DhþµGb5éÏ>Q\[ ýY?†¤¿Õ&E6û¿á¯ÇÂ¥à¯ÄRáÏTO.tHì«qº„¿vò@€?[hê±ïÒ¼ –ëÇWŠðgq*PQ3'n9áÏj’K|<±\5«$üÍ¢ ƒ€¿UBû½íØÀ~ö¤ìAö³¯ï#qÏGÕ^{ìük§ÝÿlÐ<<Öìømχÿl®Þ?r_{Äÿâ¿É90áÏfÛ¡ìQë{8Ê þ|Y†äø3$ßø³áƒIøë•ϕد§àâì×bðûY¨qqr)µr\úµ¢$±@¿1z ? ;}zú†Ê® ýLL¥4Zß‚ØÏ”ç!ÒCÔLÛö{'¡\yûY`µI²_›Å~­«ìàÏŸ$þ–Ê+ þì›1¤íù€jìÌgFjßXqÆTûª|"=2‹Á{Cøë‘Ê,ø³ˆÍú¡¿Fˆ'ú5‹f!cý|rC$úEÁÚ@¿2C¤Ög%[¨õ*bj}º×úzüd?‹0"’ýì’Æ‡ý|©ùb¿ßÍFHÞ«6ùðž¦AÁ{%*“ïiÄ ïy²æ?]¸—~' ¯™$Üë÷lmàÏ9b~*Ü#Ü1¨÷¬,/‘¸7¥âïr]§œ,r[‚î(ñ­ýR⳪ˆÞÛ[0¸W#Ü”¸÷ÞaNÒ„{–áO0"î5¹óî5ˆ ‘o òE`˜4¾ÓÁÞhiÒø†pD°Ê„=Õ´N¯E,©4>‰é{öÔ*|_„ô†Æ—.4¾¢Ü¡ñ•ï/Ü„Cã³Y·¡Æ·”}¸9¢¡ñ•{Qã3Å‘=SäÊݤÎgUñ¾éc“¥Ø`‰|µ°ùÊøYç{Ç]µùNÀ¤t¾(MÈ7N¨tD¾)×!Ÿ¥ Ö€|6£–8üï¸ äs “²ç” 9œ°ùlÈQ ‘/góB¾·e~ľªÀJòÞ Q1x/+ñžOƽ¸wj`™ãÞQ‰p¯bÍÊ[€{—ŽJÜ«ák&Ü«©ž÷j¥S›h¯Ú×Tl烓uü…½Ñ_„=‹uft6a¯X6ºÔ½ÇþŽw[°g~ „4ÂÞ‰C öl´b¿€=»ßR{~z<`Ï®Iª!`Ï_#B#xφti„à=Àutòž÷7ï­à ò^{rê-ä½Vb±¼×ÚÏŠ_Î#"°sGL#y¯Ùì—=ƒ÷lθ?ŠŸ´—à׿±‘¼÷>ýÃ{F:xÏb½Èûä=S¢Enà=Û‹+ä=ïGtW°&ä={§×'¸³åyÏf%"Àá[, ý¾QD|fÉ^|) øº–öøF>ÏÜ?¸vDàó;ÈŸe›}Â;-.ÈBÞk9R8ï™…Ÿ,ò^»ˆ¼×F,Š÷z¼â½Z£…¼÷~u$_øOñÙ°Ãó#ñ…/‰ˆï,ê›Oâ³2¿ùŽ|-Çf"Ÿ¢0|~ljy@>ûø ‰|óùE|⛚¾ñ™Ÿ [@|žcÀŽA|ïP®W“Ä×›~…wúKâ Þ¹kDB2¼ó½å[Ò^³jµ[ÀgûÑúÞ·147ñ^”x/âzÄ{½e˜(x¯7©à= ô7xÏì`¨Ó‘÷llPhéf–„ÃD©X@-A î,Z²ïÙšÕ—÷zjgä=Ëe‘®ÞëîUóOîÙ½#?9îEIãÀ½Í!‚;­,FpgQz@wÖÝøF“–$à3]|*”z{‰€¾ªeؾGn#|2|öã/{ž¸´øŽìÍ|fQÿ¾löç7Ä>/ýÄwJöM±BY²Ÿ¼J¤õµ•Ö'öø{oÔOÉ|«üò•úÖˆ¬Á£BÐÁVd¿÷W礃ìg_ñö‘úL“Ûö3¯9e‚ýÌ%î\ìwL®¿µ¾õ¨~3ÑÏÝÔˆuC—óÉïLJÇD¿e,·ƒ ЪÐÏÅ+©dHæsg"’ùÌ1ä›Ìg_ÎB\é«Q“ZJ_}O˜Š“ùª_‰7 —Ï Ç”Gˆ\¾–)@Ìåk+ò‘˜Ëgâ$;<ÛŠøD|§­Céà`¿áÓ=4 $e†8úÍ2$·ü, \4ò³`%Ïü<݈Ùs ¿™ét¿ù^¤r~sV…r‚ûlf'Ê÷Ͱu÷Y®õG鳩ßù„wÚ¦Z”È×#ïá5~Rú¬…KJä‹Å¸Hä!’ûlPŠæÄÕOà™ùB©@._††û,¯‚·“Ø7jè]Êå[rAö¹õÙ'—ÏÖQ—89‘[Fò³³ø]‰X?‹¿ãÍ!ùYVO—ôçS $l¾µC@ùµh?ûýõ‰„±9™Ì·e#ð;n'ÁÏœÐt¾Læ;* /ò›95#ùyêÍE~–<Ð>äg‘LóC~3’ߌ:p"¿iqؙϣ”>2ŸÍÌgÆG‚ä7«\‰D~¶p¾?)}³Õ 쬌«âŸG¡W µUF߉ X‚ŸÇâ|„¾¹(~ÓáĘÐwvhà¾9R÷YlÓ-ôM“¦?‘žvEbN€ß ×HŸÝ«óú¦LbÅ}ÖÍGæ›#óõ€}veRüûÖÜB쳞þ‘ùæŽï©cŸ-(OœçÜñ|û¦Õûøäô-«}NöÍõľi럴>û–öÙ ©RõûæŒt^rŸ›ÖQ[÷™ÉžøÌ¸Ï¼ð¤ÏûfFàûÖ3âØà¾™ñüä¾µ´jCî3á42ý|H]!Œ`ßAÖÄ>»9Mç#ê4WjbÀ>û5”lW~–ùÁ¾UC'öÍ-“1aßJÎ'öÍ3‚×À}«k¤#öÙóø|°o½‡ýÁ¾v…¾«´øjž„ÊL4ð{gèšYK蛊ËøÙÓÍ90ÁoÆB¸ÈÏŸböò›K+¹"¿w2!q‚ä7}VôO ~v(…qNHv‰yUÃ@Uàgo,;÷-I‚”úvˆ4ä>³Y,©Ïî°"?~+s~ëÉŒ<€ß;Ö)5àg?8°üüMøäõÍH¶#÷Ù— Iýó1u¦TEî[CÁ‚Ä>»ãÂRpßú)Æó4åÈùì¾ìηžõSNŸ¦(êÓM®wŠúVÕÂK„x!4¡ïÁò!žá3+ê[¡Î‡Ê·å¿.ê³û/Leˆ§)$CPßz4 ‹O‹ò•ª÷Ø/T"6“!ž‘%î[h`ˆç–‘¢°Ï¾ßý“ÓgŸAA°o¹ÿì?]2ßäL3":Íž]©áî*7RW÷VÑ•1ÜXWWløtEW×VÑ•={ý\]±áÓUl]][EW¾S®®Øðé*6Š®®­þÞçÇìS_öÿa mïGü'—±þ×\Æ~õ{ÿ¶ËØïm¦îÚߨNndý¯>f¿á2öw|)ë{ôëïâ_þÊ·íÞê·žâ_÷õW~›™¿¿ý.ÿÊ~ Ýðã¸ùÃ;õç¿ÿ³ýʵ®?ýw¶å­Ýþô¯ÿlùMæûõoâ?ÿç÷µ}'¦ïkîFžüçõÞ¹ñNòÊþÓ¿ûó¿²eò§ýéÿŒÝÿ¯?Û„÷_þéß¿Z~÷q‹ÿ¸UZ1ßêòÃ’:^˜úZ¥µ´Jkn•6ÿ¦KZs‡³ù§ÿøçºïÆË­}{™?íùÏùwÚ¢õ¿Ãí•‚ÿ²ñŠW (dW»Z0=(Õ8àm Rª[ì¿-ò‹r -kP Kéý¶,µ §†·e“Æ,> Û6[>^æÓzl›]Ie¹W7ûožÍö`î·Efj¦F¿óC`#® ¤/6*óÉ‹mcQxx#BÐÑ’¥2Š›¼-’ýM~Ù¶§iœ-SÚkéþt‡ïž2Üw„ìW›‡¿ Eñ8—Ûl“>ù–Io 3 %ûÆ}GÚÅ´Úm³í¦Ò/¯F½ã·¤ïpóÀXßfQllWMé^®RvζtÐ-šIÖÇ^§äm9²|nî£àÛ`ÝÙ„ðfÛŒ0Ä~ÿoÙ6“FÍòí^½qü%Ši7ÂÖdÑà…Žº­‹ÓŒÛdkP¤ˆ9€>vv‹`+ƒoPjÏI{Ö@0[°nw" ÑÝ”Ì:6ç.Ê:Ð÷ó„µ›¥½Ûœ2~‰är“8¼EëbÝžƒîë@Ý- d7e‹Ç/R·XW²oÓ‡ìªDZ»ÿoK¬Ü/O. ?Û;^¨Ð©/‹Ú6E•æûzle+vh±„:›UOx)+›ãG²„º>°~[™òN´ˆi rͧ] ã±õ™NÀ¶*Q}¡²¡”o‘'=!ËÊÁnÜ9} ” œñìcÛ %F)½¯ë°¤¼Ò¶Zô¾®¾&~lɦÛ6Sæ/«zÝ™aõqð^ÐE° ZºÇÃó wÛjAµ»eÅ„üoO»KŠÙš®•LGY.³ûr(ìsþØÍXÒ…Ö¶56oÀçÄj]ùLö¨r§Ù²¼/¡/€¨Å±ãgcF(Í·ÑWÝê]½/¬·`…Ô>†Õ¶yŸµ,;1ï"²}ÄÞgÚ[ð¼Y½«a÷âhÅ2ù»_G¶Fï/9Ìh¯¹U¼z_ØaØj Ø,ׯG¼5^¨¥[‹ÆAs¯¶­µú^Vóê}a½gôcŸ;Áw0À g_›9Ђ{zª¯ïïyøi°èÊá÷Bï§•±zl›ÒW´øøúžM§^d!—Çî—}èü:MZlv¿š|­âÕ¶Ó±†-ÇÞX¿(ÀVóÊÞØÆAö~Ûkåü#è5¯ìõ‚-™ò¶pyÓk^Ùksƒ‰½«ÃdÆŽXr O)h±ñu˜pذ Šfû§é`“aãë»ÉÔ‘;LšÄ₽-öÎZU¨‚–±Ã‚üØ fÃbý­©þ O´ø|Ä‹^Ù;[4‹ñ¢WöÎZ?þyÑ+{g-IÊ¿”^ôÊÞY“$ý—°¢WþÎÉÈ^öÊÞYkñÇ ¾#”¥Ž½-”0¼î•½³&ÂúשÚ}²wÖÊTáÚí í”MäœÞ°|õ%?ü4~PûeXêÇ«^¿_,”ëe¯üô…ñ²WöÎZ,¨?íVö ïìaVº¾²w¶>Lä¬Þb¾ÍÀ^ÍÙáq‘ئ?xgm›ƒš~[hHúvãOþð³@?ÓY´`d÷{ϸ>U6^.ðÇñÊWxe™áb•¯ü•µ<ÇÓ9>Æ ŒÅé4›6[¿Wn!tÓ7¡æ[=êÊÆn¯|e¯¬Ú¿ï\ÒÙá©gþ“[å«>ÑMÅ^£à•=ŒµñÊWþÊn†ÿzå+e×ï¬ò^YKž@ÏÛ £3²ÅÃmápöÊšûWÇ^HeðŸ§Vs{õWVÆ¿^ûÊ^Yó¶u¥Õk_Ù+k? š±W¶vNѽø•oÂä«}åÃlmT½úÕF/øñ,©z/Z´è"{eÍ.hb§…aÖÔt\¹™´L¿§ k}gãf­ç«:fë äèů앭2š×¾ê ®@xí+{cM•ÇkdÑ7þÆ6¦5zõ+{c-út²Å“=‡I÷{aâ=ì‰~ÐóÀ(kbþÂéLe-$àÁéLŒ²Æ ¨àůüæ Ì´r‘ǾpJ©ø»ìÓn(\?SáŸÕ…„ɈBBÆòÊP5‰PÁ,I„о"\\¼ \J¡ \’œ—ä×Â¥ »Âý¨*ž€p×(3H Ü-Š=|¸Ú‡E²šÖ`gÔ_ÚJêþ‘<¸ö‰d¯¬ø ]ò Í”X‘<¸l\ýð K¡8="áÒ÷7ЖMDBka•!a¸‰> ¹g>ÁeBÂG1s„ð)˜0Ò…ƒ Íþ -v-„B+|‚Ž…¥† °¤³¡°Dœ† 0 G k¸Y ͆:`B/LËX0á®’íÄ„ÖÂ\2¡y·+íLèÖ p&t~—èîLè%©݃ ½4­Dcg¬ÿ-&´‰î : &ôÁ’ý}ÝíDˆ©C¡§_2Áô÷uwåÉ mù< ̓:¡ÐBè˜ëE(´µ¦Î -&¡Ð¶!\ ­“ 3ŠPø¶¨ú ¡°ï aBa7|<Ü„ÂnzüÄ„Ân9VX{!vË—ò }q?¨Ð×6°TE*´–„ï_ 'öí±,I„ݼ=x" BoÁÍ#v+‡ß€DØ-¸‰Ð—LrBo¨7z|›@ØÍöÐA ìY€@ؽÞ¶z 6úê Î<ˆÈ0£ó ïƒÜò ¯×` ÇÁ¾ÃÌ8ø¶hñ‹8èÛ`µ‹8èûûfÒ wƒ^ƒ=k»—Ö}b&`°ï03" ^ëK„AôŒ½0ˆu/„èOaÐ[&[0¬úªú zP¾%„AüX v¯ÿÖ úR ÒaÐûùýÐ7 ¾Ç‘¿?QÐ[ÝAìV9‹7DA0Á7‹(ˆ~ph `7o™r£ ï…Q“(è+m˜û‘}•P°[j!á(øn³ýqó<ülˆ}é “=`?ŠÃ´›5ѯ“ ÷2oôÓã¡A‚~ í&Á~d¯,¼O$è'ü!A_>Ä$$è{é‚~:¸|7é‚<€ V!AgAoÁ­ öS–,|7YB:pàÛ2¹‰c`·ª<40°ÙW½1Ѓ z/R o‚«&¾-ôév/Ç–Ê¥ÖÊáFØ­.%бs¥µŠF¾ÛÐ2¸Òjщh™\iµeA ãäJ«® èQQ ÇÞ\h- ]z,U%r¡µr}›ˆ³™®´Ú£ ,¬Xi­Ì…z Q²q¥µÒŸ@øRÊ£nWZ+ÙÞ‚•B`?²0z?Ø Ø­€ú¼°Û'ŒEÄÍñ$â‡A °[Ò/nÐ×Àq»È€WÏ`@ß©c0 Ÿ1˜ xÝ.2 ÷;nìV­ô¹Ð÷ÂU‘½7 è·‚äôëÄ $zÏ@,0 _8֢ȀþãÂÉ€þúÏÉ€þäàªÈ€þ ûý#âüp(  ÿ2X-âØèxÛÐZöBÝÖZ¤ø¿ßQ-(†á7e†G“0œŠw›zÝ% ¯I‚;¬ÔE‚¶ F‘ mƒi™HÐMȆ Aò#IpG"´Hм_$A¶€½¦àKÒ`Ѽ&¤Áð+ i0j—Hlò½i°•¨ i°kÑ6¤A›cãØ’ö.ÔÁ¡b´¡æÅ…88£J«HpÊõ$HpÉŠ0HpjØ4I²¦æx¡ Ö‘™{²¦2!%†:"LËÕå¢â`¸±…8haŤ> Y4} Wòà)ÚF<¸¸Ô<¨œ´BÅë' h„’O £«…ÈpѼ3‰p1>?‰PùI„£ÿL„‡é®A„‡iÙI„‹S˜ ÂÅ\î$ÂÁ2ŸI„?_"48ʉÓE“—p ˆp±’fá8R)…„ƒÑk‰„/“íCvšå:ˆKD¸°•@85“@8ÎW´ºEAûúþ¸hpKÕ\:ý ÁIK˜¤Ak¹iÇÁɉí‡C‹hpsî”4¸éß•88™%8h†ïò„ƒïC; \Ï‘(´ Gô#\ç+ ¢çN¦¡$ž!ð$&y%*Uýo™¬¥èö#e:pïŸÂCí›ÿãB@ÃÆõE@%ȇ‘c¡EZ†xäöb`TÔ1PâxŠG[!†#TF‡ÊÔ4£CZD‡*0£CbàÑâwŠS TVâ¥RØ“¸·ˆj`6H Œ)d¨[îR¡nåº%j‘:°394p¨Æl àPrp àKt!àPèl  ½² 3!à`€K"àiE0àPäSFˆÊ_ 8÷/ßÑw²© \Á€›>dÀ•õ‹©ZR&3ÿk Ì\”¸ŸôPƒÂp‚æÄ€'R6 šµ…Ä€O8¤‰Ÿpp“xÂ)Vb 2?.<éÉ øÐ'Ê‚H <+S ¡Ú+"‡Q* +*B <[.¥Á€M©bÀ£¤žÈÿ’x†œM¤î®ÄDiöHþø0 :†h—ýQH |DÀ‡¡A€EöWA€qÏCÜ’@“îø0†"•À³q( GUxƒI{Ä¿Gµ³ÿÙ+þ…ÿ\(‡ô•ç‚þâ± ü{4!ü{TÀ)ðï‘3Wà_ømþ=òW%ðœÐ‰ʰþ=ª—ø÷èýþ…KGàŸÅu+‰*hþ=*~øW¸ðžü÷¨TKðŸ%ôc/ñŸõàÿEhðß» ”Óà¿¢èøà¿¢ûüWdŸü— â¿x %U%†[`Qmæ ÀGQë"@“ä@X"ÀGÎUBÀ‡€‰€ñËÚc! ¶Üzü‹”À?~ÜôW4†ýY°ÁŸžÇ€¿2¾A¡¾IûÒ_vR`°Þ%"ì+è¯p¶ðgѹßB lœÀü•ú+)°h¯Þ–R ]æ“þ ].-°RóL-.)*ö/ÅÀ¡0V‰QôW"Uô÷Ü¡8Ì›ü >’üŠ$² ¿Â܃$¿¢H» ¿¢)sJ´XJò+¬…˜äW„¸A~ú%ù=!)Šü,Ãç#ò“_J’_(Ñ¡rˆOò+C‘œ$?ƒ†/ùñ•JðÓòl‚ŸŒ²ü ? ~Eêz€_üÜ~EXàW†àPàW¦ôL‘_¡uH’Ÿ¾bI~…¡€‰~…‘‰~!4K Œ:ЯÐ5<è/nqÐ_¡cVÒŸŠî%ýš¥øH!ú+4ëHú+\aLúSy­¤?û\}éïay⤿§~BsdHú+¬ ’ô—{‰þ,_’âÂlŒÿ®àŸÍÇ*‚H‰Çòã9®% ®+·2?ü'<;ò©jj Õ2Ç&@AÜû  %¾=_5°ª.A¨Qr>ÔÀªo¡VEÊ…XM¡6eû„Ø•”jà Ά¸ù)¥g„8iŒZàR¹ÀÐWtR ´åZ´qr6Í.?A¡ö,ƒB}ºùã¢@o WÒ¶DjóQM¬Áé M¦[1ÐV°™n( < ¯ž0sZ õCb Í8Ð@ 4™¥}(ð„9)ÐØÁ|-òЇÑÊž/ºûi­2̽¤®(q%%p†µ˜”À÷Ð*ÉÄKkƒ™&8CÓ®©TBQà OaQà ¯j)ïÄy|Ó£Na`àˆ³ÂÀÈš %p+ó2¤ÀŇ8³Òù¨šóÇ7Mp©ÊˆÒOú„H ZFŽ BŸC\RâB4(Äq.|>襽~Ü x× ’E@ठøÞŸqgú±¿Á ¶‡nRTÁOÐ%eÀ­üÉ€À£`hq`è'Á‡qÿ™#øÈA:dÀ£ùÁp¾ 4»>P•@p+ rßç[-ÒU-@Ðì¾ xT­$tÀÈÌ œ²d ´€El: *ã„؉‚æ…n‚[ËE‚o/ xå>fˆHe ¨/Gp`„»a < {Œ—>8ð(Ë7uÀýMô gtiè€Z6  oÐàÀðð Ôzð%*8;•@ ¤âÀ1 âÀ£q Í!ωƶ”;?á)N*´)V¾ÔÁ‚‹rD²`¤  –O%PIðÁ‚Ü“õÅI4-À–XpÌ_îAÿ…ÛOB #Œ‚÷üY|Ç9,°‹w—¦'|Ãþ =´%KÜí—oTè–à(¸I,¸”û,88$ n._$ †Ä,¸¶¶ ŒŠ‰‚‹s DÁ%. <¢W¡àb½ëDÁÅeˆÇ/wv ïs'ú© æ7X0~•”I…‚A³ûÂà Áa ]6 N0h¿“ýe`º `pw“Š·˜8U@Åï n  Á‚UÚ\° ´ƒK|¸¬ |;†”,8¶2í¤*s,XP–Á ƒ‡%:ãI \4j¸TÀÆøÜTZ˜*`UÄ©`p±JÂàÛB  ÚgØ$´yÀWœKáš¡"î&Y0ÒeÅ‚KK.Á‚óôÈ‚“‚—ø(ËO,8ª²üÄ‚–¾•O,h¯ëCu”ÁB¢ †‹Kd\F¢à¦9G¢àR(8¹"(8»‚>…‚S¹Î‚PJ *š¦øv|çú'¼ß¹å0rbk–íùqûqÐQ.!µÜŽj¿¿_n¥mþ1'¶_![Ò¥ìçcü‡«%]ÊšM¤Ö§¯h¹úbÛÕW´d_î5=>W-Ù—Ú²¯l¹úšð[¼úŠ–«/¶]}EË¿´›Õvÿ1'¶þ[NleüôÏŸØÞÖñ{ÛÂݨ†»Ño=Ý×ÔnC¬Ÿb{<ÝZùÞH]¥ÉšººMÖÔUnŮ0Y‹®.“µè*¶RW×FÑU˜¬EW—ÉZt[©«k£è*LÖ¢«Ëd-ºŠ­ÔÕ?àÄæJl`ýÏΉíïùRþÖ÷è×ßÅ¿ü•oÛ½Õo=Ä¿îëšY-ŸöŽiÿ ÍÞWùÞóŸ³ÙöüåEý§éjVÿ¶«Ù{çL_†©ÙŒg| ?Ý_ªfyüù虦ϼaaÔ`òttWÉZ]ñä« {m¯ÿ广>YiY‚ž6áÄù¶øR‚g–»¬Ü¬üg߈¢ñIcóRSßøæ-Õ§^Ò¬ž’¯ÁŠ8›—í9HoØ«;Lù¬‡14«øÌé߆Ō ®ÒØ/€5Ø¢³Y½ÌŸÌ ´µý`‘¶ðÏÅXÊôÍËp§Ò[õ”glÓ‘äæÉË.5«·ãi¾ó­f5o֙ܬ MYHn8ئ¦ù2½Y¹š‡‹´¶ržøësãÖgašïÂÜømq¹Ø[6¶Bx¤·Ù‹°/të¶"…ƒ¿aÞa¯€h <7É@¾¢ïûŒZ(B4ðçÛr(B0ɯæëXqõ`غ›´¼wIŒýlö­ßƒËäß6æÄ̳Óq¨ äGxr»pâùðFŒ½¹ËÚäÍÊšb –*N›Ó•O–qk¬ïÓ1uÇSlÆô>¹÷^­4ÀÑ"…Ÿ®•ÄpøPÿÚìž~ìÁy‡é®Í¹Ó—Ç15+-k2^mÝL·GVCÅךùµÏ Û.ܳë6™§š¹:›‡ŒÙ„û1 çÇ7a9¬f¦Úf!ãÕR ZüñVúÑ/qA>^yÅû5oh³1×._hæ.n2æ¿u°Ms¹îmi€Öf¶ê–NGî(7¬ô ^©eþ<ðÍÂÙMóy·`èN[Ëÿ$Ç5÷Mœèbã¸Û‹½ù.-äÎQŒuk¦×l?“ø›-¸}Ìúµm£ú ;má͵÷¼,ž®_€UUuÇ'¥Ô5³„}LÅÚB³È³á®P °Ò6ŠÅ¼-özy¨›%Oaìfá`Û¶ìØ,'½ ì…;ly9n.Å5Ùfá5nùÔ¤‡æÑ4ØÄé´y …Ý‹ÎÉWs©³Ð£ÊûµDRw|2ÓsÿY,_qÐ9ŠýØ‚]¡p6^Ë”.Z¾~ãåˆö‚³žtOÔ±m‰Ð ¹ãÓd@WóU™F¿)ìµÝ¨h˜†çÏWªí~-}CmÉoØýZ¬äØmÕ¬u£r£W$²»³¹öâ‰ÜòÉÖ#Zl\uï¦ã7Vß–|°rD0|ZPü½‘{´-æ[w+ ¬ˆhú°:L tTïæAç~O›r«W$r¿§ÍU©þ`…þmÙ:øñbhîÂä¬î‰à÷x/HÔÜŠŸs/H´¼œÐPìž*¼"ÑêpŸòwµÛSF;ªÂ†»§I*ÝžŽϨ°žû?Uì³;Jà áň`õ4ðÜ{1"WÍj׃Tw¯ªNŽ©nx„»i§`ïªIŽþnxA"·zêtÎë¶¿½«f4U±W=´z¢ß͉éq;(‡óŠDö®štY±Íð 5÷qò2/Idïj ×ò’Dûàèþa³’Dðz4ðªD´RÂ…Z¡ÃÊMЋa·ù-|‡{{:œžÖ‚ô’DîôÔ™DÐ4dwŒÂ-µ’DŽ[c³—$²Wµ]ð’Dnõ4™õî%‰¶}`eßJù«ZmiÔo²%r«'K"@?«ÀêiÅ9cÍÒ[°ÓžpzÚEcÉòp ­[ ŇnP¸ÇV“ÈîÍâÄÀk9jÚB¥ßP«IÔa-†Ó³’Dþªn. YI"U­|^o+JäÞl{¨›qÕî¾á^•h:žÒ6µ[E?{W+WyU"{Um–ëŸÌÞñªöp=Ö«ù«ºX|Á«Þ-|¬*‘¿«“ùY^•ÈßÕÅ+J„wõÐŒÇËÙ»jµÁºiîëà%&öêXíY÷Y^ÃV+aåg¯Jdo«ÉÞ¸ÇcúŸ 0ô’Dö¶: gad­§ë6FÖªè`/IdokS\ª•$ò·Õ«v¢«¯ûNFeeáîùº¥%š¾.r¢ôóhM-+Jd/«õƒWܪßF^«Jd/«-6ô<1°ÚwË— ­*‘ýŠ~Ê~‡§¯ñ ðu¦n%+ªßœòªDvÂõÑ Œ«öø*4Ö .ÁǺ¾ð¬zÇj«vèþGÌnÜågÄÔ(jö‡ŸŸ ²òÓu tç@jíÿQʼø†ÿ ήƒÿöɉÿöáD8ùöØÿ5mþ3 ,8ùÏð1ƒÿɸ+ùÏ„)´8ÿ©Úyò_A2jâŸ]‡ß©À?UâLü«š’þYéÃ/þ©®\â_eM®Ä¿Æ@ÉÄ¿ÆÔ¿Ä¿&0 ük[€*ü3eì%ü3K ¡ð¯Óß&ðïÝ wOüÚÁŃÿ,ªhÜ€†°˜¢ s¶!zrú!F.FàÖPh¡GÀ ¥ì €–|È{ @kÁ½:.I€–zК=Àó!@S¾¨$À$jA YO5 ÐëeÕ݃X¸™Œ±Š€@O¿ÇS@DB9¶ºƒÀ¹!®L¸@ ·”›ß¦ŸŠ=ì4L ô|+ˆ¾Þ`b ‡õãÒ‰~¬ÆzÈÀ è D:` Gp =ï9.L8öbþn9aÿèˆ]p`p`ú ‰;†p ²æÁ]à@Ñ߈PqlÌXgq`Ê3V\ˆêe8p`: ‰}/|$Éî­öz.è-“ØgŸ1?VÈnäólq gÛ³ˆ¼t°"8Ð%ð3ÝÑ×Iô|lHbä@8÷àtÀpvÁ±ÀðKÂ^à@œó;^„‡”è-$Up`GlHb ¼rÐâèäõÆ@¿†ìs ô}_™ÂÛ¸ôe(lôhAl ô›UÑ ô~PhÁ‚?’ý0›-Z=‹ÇzR?fad@?•ç†À~:sù®‡b6B ôU³ƒ~@Hξ(л©7úÁ1¦ Fƒ–·N¦{1ÆØø¶0ÑX˜’¯0ðÞ ˆy€0Ðû!dý@o @O‡'™½›îúà§%ú€†IØ Ä ô[ƒ~6˜ø‘ýî×ÌŒtA _xÇ‘œ=2HJ ôUÉqS Ç=ù‡Dˆäwï˜è‡Â–è-ÌÇ¥ÕÜ«siµ³²(Ð[0ó%zÔžR`ŠYN1)УüxʇK«ƒ~«¢@ßwè õ¦@?cÅâê`Z» Wä"ôô{üÀûd¸JlÌ&Q Ÿ_à ƒÑèÁ\xjIÞâÃ’(Ð÷±H×oN ô–sc öB 0Á‚è§×0ÏÀ*0Ð7ÁZ1У6ðË ÅíÇÕ±…‰‹ãêØbËÍquÐÊEè§‹…R nߤ@jðÚ‘ñaP *}ܵ?w7€@ÿy× 8?l39ªŽJ#úƒCn]U»– Hþ1¹)Ð7ÁJ D‰„‘<3ln°@C ¼>m’<ÝCéÇò0 ÜýÖÍl4=šKWƒ^GÜ fíÕèõd?: ùS`$î‚DåÀ@·þqQ ÑÈFè½€»Hv.àQ ŸÝG´É¦E¢@kôA,UŸT@;$6‘ Ø(¤ XÕµ=/ ¤Çý1½N lÄ‘À@[˜ˆ  _ÖÄÀ¢©s``¡jb`Ñ:|` õŒm„…Y݉2nK ,Òf £îËÏ* ÕzGÇÂ@〠X61°ðI Œ+ ̽„*?˜ýU'1ÐîNPh÷g( Œû˜-ÂÀ˜ôÄÀçݤÀˆG ,ŒÀM ,˜æ5$Z®ã­^¿x@`áG'!0~߀ÀÂÑ5!°HY ,4…N,t¾K´;ñ…ÀxÞã!,L1J´~¾˜Ç"ÆéóÇ#^gCŒ_ÁлÀd@ÎI…‡oë ”IôN?˜¯‚Ð:†ÎFÌ#‰í¾° µ-I€ö] [’óN‰ó©^-$Àë”I€ùܯC‘óVóéz/`'`þn"@Ìo%£`Þ@ í~\¸ 5?ÐßÕé/ŸWÑßÕBúó;f$ý¹ýä þü—»EÀ|YD~ÈzßSÞÑ_<‰A×&=ÇTEÂ?¿¨[¼÷š#^Tù/nE àu‚DÀxåóXBÀ¼r!`KV  냀yt" wnìWY3Kc àu¤õ\@ÀëÀ»Ç›:±ÍѸÊ'60[„€ú"ú¹ø4¬j.ŒG+0/I[  š±Í8ñª¶[¼ž 1`þ¾dÀ¼r1àuÊgêUűŀñÌßI ©`À|&Ä€y~bÀp‚¯½È€yÊbÀ|CÄ€y—Å€ùc óBùœóºyÊ‚ÀbÀ|öÅ€ùInPæU }"EÝO+ƒc}"Š3\S“àuKwËáÀJKá€@Ÿ9û­úäÀ¯Aˆhg3ÿë²$?U¸@¥Ï¤x¶¢9E~O× ýšw'û=´®Oö{xEÉ~O¨PŽR&IA*E–ô÷L2EПÊå$ý) 2éï™âAÑ_n# ð4#”±&©jÊ– ½2¥ÒF?éÏ>¿ßЇ?äEýW" "¬R¤mÂ%RðNúkŒ“¸D@­Ð§Ø$ ^"`ýÒŸ*u&ý5ÆE\"àfúíPû„~‹‰~MãÇ ôÛ¡í ý¶ÞŽ@¿-Ä ôÛ Þ ôSÔP¢ßÖ3 ôÛAB¿=JôË}„~ç¹Ño Ðý6ÇîD¿ÍBËÉ~Kðe?ú…$ú*Nì·% ûí-ØûE>ûº@%ûY`ðýŽ€,ÐïtJèg9Æ”‰~G IB¿Ãº`‰~GŸK¡ßA|K’ŸÐ?nð;Šðcä¾Ã~É}Gß•à>Ÿ¿ÞÜgãe>¢ßa’e Xî3”C'Rýž‚EàTýk“àw$øÉ©#ÀïÐS-e¿‡å”Cö{ø}MÙ)ø¹ƒ;v’î÷u,ð;Gò¡ÀÏ2gïøÏtâKíïy¢…ÚßóPË÷˜a§òg_)P“”¿‡õ[Sù{öÊß#0 åÏøI}ö÷fà ÇÄrÅBLÿqAŸ)çfƒî§ÚJ©ûÉt1u¿§óz$ûÁÙâb>?W •d¿‡Ö)ûe‹t¿GÁ•’ýÚŠ¥ìgÎ2èX²ßÃäü”ýÊ#“ìWPc"e?Ëû _dÞ‡ìgv_wì'Œoäó•d?9£¥ìWž•QA[¾”ý°í…|ÖÒ?Èw Jͯðw ÉO.h)ù©|J~…ñ)ù±W ~…Ê)øÅ.!øÉˆ,?YŠ¥àWžŠŸ-¶SߣâW†v’â'ÿÂTü,Ûç«ø…tJðc¯Rû ­ôRí+SÁ¤RûÊJí‹^%öš §ØW†"&%öºÕ§ØgóF°”ľ²%Jì“mcŠ}EÁûŠ^¦ûÊ”t7ù'!Tj_YÑBµO¥ºSí‹Ëµ¯°ÈRª}…Σ)÷E·‡ÜgÚ ÀNr_iÂ8É}EÒhè}¥‰¿¤÷Æð¤Þ¡­¡÷=[Òô¾g+x”zŸ­¡þ¸HÏmÞvûâñ ¹¯ÐC;å¾x>Cî+¬ò›rŸ^§?`S–qŸ>|¨¯*‚SzßÓŠût¶¤È!ªjÊÔWiàx)~‡3É ¾F§”¤¾¦øÑ >+DŒõµÐõ½?LƒúF„lŠú£žÔ·é|šßaÅî ¾¨a#êó Ká)S½ìúlùP_„Wõ™µÆ¹©Ïó³ Š$³sŸÄ?7³ÀN„>³™¿óþÞ^–$60Ÿçt=7ó½Ÿ ü àó¤*\2ïm©‘x˜L4˜¿Þ³\¢ {ïŸ]ÀÞ(³è¨€=T¿¤>O†b:hÏëdSZíyiûqÓžPïwÊŸ§ÆÌ[êó”–OÊŸ§€àÙ$ðyfɾÏêvÿHÚó‡u‡{zùhÄ“‘ö<¡ ‡© ‹ÀöÞ#/Åi¦&tZc’ö¼P5‡´çþXvíyT?VT”òg,LðëJM(åϬêêM{ˆKG Sþš=[Œÿdj‚UÁÂ3å¯.ý Êù3/½I¶CΟML‚Éœ¿ëBJú³óP1çϲÝñ@+篩Päüµ¦ eÎ_k?é|ÃÞfÀ;sþìefæ “þìÝåN^‹þ0l>’þìTæ-ôy~~9%ýÙ”ˆB“þì\Ê­ô½çÂbZ‘ô××#é¯MEž*é¯)±Z9m³8Täü5sÓÁ6Ìù3ß™çÆ½÷t (åüÙÏ;ïXÏ÷éЮœ?»$+篩ê rþ,åáܱž~¤z+}™L96³Ã ¡œ?;ãöÉù³ï!9v+¹«œ?sîÁ§]96ÑÄ…rþÌˇJsþZW¨³rþl6Š…rþÌÝgÜÔ7Ì*‘é{Ìù{_vÎÆ™ógà˜ó×VÀrþÚÑâ±’þše™B‚cÒŸ9í›úÞŽ¢¥¬¿fƒÚ-÷ùÙ0'‘YMeÄ"ë¯E0¤²þÌ×¨ÞØç-@-&ýµÒ³þÞ o…²þÚRF’ÒþšL†"íÏD\1íÏžÌÉ”ögW^®€Ïa±ï€Ïü‘÷g/I‘yö>ïOÞŸeÕqæýÙén¶`HµßwFyv÷p.Êû³½&Acª}(¸1ïÏÞ!Ìã”÷gÅM~¾ ’w”ögNƒ,ˆQ5¥ýÙ+ƒÙŸÒþüÃuE|¾›,„«)ëÏ^ªr|¾ š™*í¯©€N¤ýµ!ÍAiþÙÿ¤ýÙÝ‚FǬ?¨ì¾¬´cެ?kY7üùÛ±?YïP£ƒ3믩>Xdý™#)A”ifIºï€Ï·¥üBØÃÐï³²þìùd¤&³þìü¨È!ëÏUñ$)ëÏnè¹>ß–²þü„!2ë϶9·Ô÷žÞQ &³þºòô#íÏ\ÀðlEÚŸ-€âXLû³›¤D@ ­6:|ÓþšR¬"í/FÈûË[yv#¡Ë)ïÏŠa …y 7‡Iv¾w°çè2'FΟyÂò<˜ó×%âDÎ_“«aäü™!íøæüm®SEÊßRê[äüŠ™ó·µL9»S÷Žœ¿ý(pS9*î—9»KCTÎßÖÇ%rþ,d{)篅†È¤¿N!5rþÍ="ç/ V9UßîÈùSÖ~æü5º­fÎ_eïåLæÏþÇýfº çºüvÔr;Œýþ~¹•¶ùÇœÉ~}„lI×®Ÿñ®–tí–ÅÖ>}EËÕÛ®¾¢%ûš6?-Ÿ+–ìKmÙW¶\}-•[о¢åê‹mW_Ñò/íL6Œ$ìÿ¦3Yù}±ŸÉ~Ãbì_ę췋íAÔϱ=ž} vSn¥¾ÒtL}Ý®cê+·R_÷VÑW¸ŽE_—íXô[E_×VÑWØŽE_—ïXô[E_×VÑWøŽE_—ñXô[E_ÿ€=Ùð¦çwìÉê_³'ûÕþÛöd¿·ÙÏöd¿·ÝÏöd¿ý¬ýÚžìïù\þÖGé×Ç¿ü•ܽÕo=É¿îëÛ“™/æzǵߴ'{ïÆÿšÿü÷aö·<Ê>NcÿñÏÕVöç¿ÿ [ÙÕø¿ÿîò×Ë0%˜HJ§tzþ™¦î3Ÿ"îŤô†–ãš„¥ û,Ùg(kÁ–̧ï,ÆÑYéÕ[ªÏÜÜ–¬¡Á³‚<[b£¥y92ÿ¾o@žFÖÅ}¸Ë·'œ7ìdÓˆS2œ_7g³ñ¿ìJ˜‚1Ñb ˆþ½Q¢ìaÖÜèg2øŒ&ÅïÜ­1øŒ+c l–páÓ¡·e£”DíX$£Næ`pùuø²5‚³æ äd€ímÙXíäø÷›5|68ïKŽžˆÍ3\d'PÞ–è3[´EϘ…{:çø1\G\_Ä4Ás`]×'Moˆ”ïQc¢ ¡ÑRkˆû¾6ñžÜq?·1V§bíKñc"OÅãÐ2*‹I QmÌùP8lˆOy[âÏ3ÛÇ\^»9ÎèÆ|ïÚ§ã} J<,A1&л։Ÿj!É5IܬU*E ¦5¿-^°Ý´ý³ÿÎеCJAcÙÊÏ, 5lrPÆ%K¼-çÖÙØäÕÊŒ­£Tí…0å «P9äbã°7«S4+hÙ“â!e²:ÕC.Äb§žÓì0ð¶xæ-2¡ýt,F™½tÍöDÏþ…ñø°À¨Áä_ÜšÙÛ±p3ÌY óŽ´ /ÞíÙ¿Y€u¾Ž„ OÓu8^óÃÓqo,ºÆÓÍ} ‡åÀ#·—SÿÁçÃSw(†kÍ…JƒŸ+GÌÿÅ3`7é½+Zv¤÷b§æ!üÞ ¾H–bêbc>ϰ\7×c'›02©ÕÉyXAƒÅrÜøaÌ0Û%ÄFÞfæ<;Z [6²{YÃ{˜ä–{ßÞÆ=–ÿY¸]k•uš¼qʧåÅ#—Eæ£ oð'b>Ý+Ðûù7êmYxWm¬DËxY™‚=M™¼›þ¨½ƒ2†ë(¢ý¶,&÷²ÎÁû±éxWyó^V­¬û˜ŸùÀëê¦àËí-þ•šJ¬gû÷qxGz‹¿àÓ|â{-Œ«®[¢çÝPû¥3aoz ñ#íßÈo¨—â Åýëp·¹·©3ñ;†Ñiå¶î¨wÛaN"ê´ò@Kýøýóò@LÅßhÀÀšçëÕøôñà&bq›C-¬)ÁÓªueô{ƒ-Gí«a<V•¸;½8>L¦â½ò¡cZu Åȯۋû•²ê@ ÎwÓ뱯‚Õ´-Àåõh0qìÉq5ÞL¯´î·Î 5ú@àÁöA(ð6X ª÷ÙoºWâ­@Cá°Ú(«ÌY9®¶ÍgVŽ«í`B1½@­"ðÁñAÜf¡e`\m\.›^ h`ˆôeâ9'ÇU½e^ ˆc+*Z4®Ò"pš?½¿­¸¦š?Òd®ÂqÕ¢Z8®V¨ïÓêVsez} Å :îW+2§×â4d£Ÿ1ð¶Êƒdz} Ãm¼aq\5[[tlØB›_ð^hp¦âwtyäP¥.0½:o@o˜iôpäÆâWà)óšLK¢ÆÈª'ÒËñ†b²ò@Y™Â€Õúødaî¡¡•C¶@Øõ¥(–¿ÇºìB@_ôþ  Oذ¤s!`'%$vÎji™¸ÀˆÀ¤F ª~$šR ZÚ Jî&%Êï: ÐÈŒôbå´È0‚ pI` LÔ.•µJ Ü |¶'*{ –`‰£  ê['ªta2`e¤h2`]º,2 =ë$>2 %2 D4 l ÎLT Q2`[ÑBl¬ˆ— E÷b@K[à±¹;•í½@?‚ÀA“‚€Àý>-´w‡E4*ÁínÅóx¯z´”ÿ.d@c™ #îI;1 8ð] h‰ ˜Hܓё)èÅ!AŽ„@óHã¡–qpY„@#)!ШŸ-„@Cx#ÐvÍ‘­˜HôLp"Ðk²ûÏ ´~²d@‹àǃ.Œx}1 q1– è~hØ„ h;á½ | hk8”ЂäZÄ€Oç'(PËŸÂ7: ð¡·FBàƒZ? Í:q%šW>NGh§þÀGŸ¿€@mB|X°*!ðaGB .)!° À(!ð¡×wBàÛ²‰…+êßbn¨°è¤@œÄM…A[I kM |«–XºTX&· ÄÀ{c`áà¨Àç ÀB?)Ðb6Ð/)°`õ#!°èN˜p&–#*VHoÃ"+ÇŽDÀÊá/Pt‰€…ÙaÉ€öÑÿ2`e€r2 JRÞ X9&f !°êI ¬šWŠ+cÍ“q7Æ$-(°=˜a$V®×$úvC`ÝX2I¬LÉM ô/@"`cmŒDÀàF`eFn`cÜW`ãšm`Ý¿ðP"ÀªŸ%°²4 1m7Vz˜&V†ð%V–SK¬´­Ml\æMÌžE€•Æ€‰€uë|„€íÁT!PÁk‰€KÓ‰€*‘ ا‘ XõÖÃ×0P^†Á€•‘œÉ€•¡îÁ€rLD=ÛF‚ëR7bÀÊUúdÀJ§¡dÀ„ÀdÀª› Xµô XéV™X‡ KX9wI¬,’X¹þŸX¹þ&¬úÌš•ZÈ€öIB'b@•7æ>BÀÊ © Û/À2 }0AO"ÀÂ"0I€Z¬NÔbu"àû(`y!%‹ˆ9°D-+åË€e@¼IT­ùdÀB† ¨EúdÀBådÀÊ8¡dÀrÄwb@•¹OÔàXY£=Ðç7Ö¢c mºåóï6.K D¤ØE6WDÀ !Ъò@ïº2‰hsEˆ1‚@/#zét 9Ј¤C#ZjƒOz„6çÄ ¿0ÐZ0Ï:‚ v6ã«ÖùÁ@;2&Ý¡ª$Kj†h`*i]Û„Ø™L—84· ëg-p2|*1pÒe)1p1ô11ðH¡ |¡óá@›ÍA Ü´bLÜëSÁ‡ö—Áö9ÉÞë‡#i39ð0¾óÒélh+³´Ö5`§´ÀÂ<É-û˜Jtéæ > ÉV$ bàxD˜{•Ð'1°VI ¬ÒˆC ¬œ¦øÞ}hŠÔU 5µ@ûcjv§©6¸j¦XY«:µÀÃeáÔ×â/Zà&„¨(ÕÔÇ'-°Ó)2µÀ.° -°S>-ÐÜ °‰´ÀAÏÀÔÿ?îþfg›\ÙÚBûû(ÞæZ¯vúß>è 4±wƒ±„8‘cŒçSUsÖœ,¢Uõøu:y;m_ñ£˜ž©*rih]â[hƒ†À¡*qlj WR Œ\”8¥È†Ø33¥ÀÁXƒ‰ 'š85i㓉Í ì+NÍJÁ ó™8é­›8›dGbàz®Â@™HçâŠ8˜#1ðí VÓÀ@u79piŠâÀM±äÀÉ`‰Éó‘®'›£àÀ^Õq`¸“ Ü’l‚éï‘Ã÷Ç”>( 4pƒÚjàæ.F¨ÔßÉK»qà»;Ä#Nμ ‚ìJH‡»œÀ@›¬Ý¸6Fyb Ùñ aà¤~bà¬?•ÀÁ€>‰J×—¸ñ§p-IxbÀ÷·A!àÔ®G8$¾mŸ…€ûH‚n ¢@ÀUõDBÀùUÍÒÿ×ï÷LEMü·ƒ¹ÄïK¦äGü[ŒÂ›¨äYI€ãp‘F îF@/ …€‹°D@³Ñÿ" l9ŽçžöSÜŒfŸ¸iQ’¸hs™¨LØB@Ït÷Ü" J€nB@™'ê(=0M àäOø¶Üø€GØ øÖ]_pw±šP¶gÁ€ë ÕKê‘4#´´ _p÷Ÿ:àâZ“ 8±$NM€rH<ôdO\8dN\Ìj•8™Ä, Ðz!¼‰£ã$nA~à:¢D -¿.œš‚§lD€›^I€»«ÃBÀu~ª€“¹bm‘+‰Í•ãË€‹yš’—ã‚'£ã$jÙMêO0`L}Á€–FL*T÷dÀ9‰­BÀÉì ‰€c [#ZøWœŒ²”8õFgÓUB@y&%*Zx2 ÍE_\Ѳ pÑ|*!P’Ú?ˆ[vŸ[ ÞòßÔ‡‚ü¦5Kò{xÈ—äWž_7ö)ÜsbŸ"¾%ö¦¤Lì<ÝÜW˜^!¹¯]%î«t`Lîã‘óÅ}œˆüø!$ø)¬^‚_…\ŸÜÂ>;x… hœ… ¨lû BÑŽ°;Ä`¾F×°d¾Ö%Šù”¥6µ¿ÞdÛ)æë¢`¾Î¥:˜ïe°_ íoб†Úߨâ9iãwöŸ“A’ù&C¤ö7i8Úßd>¸Ôþlþ¢¹'µ¿E³¤Ôþ&Ó$¤ö7Œ;¥ý-l±Rú[49Iío1ìUj‹ni©ým6Òßf” ”þö¡™&•?s¬¢ÎGåïÐâ$”¿SoRþÞFÀ„þC+¤ðwh‡–Âߟ„ðwº„I –œë×|Fø*é~Œa”¼gŽï¨"Þ Ý*„?oJáÏ"*Ì$üæûLàcRâà½ç äêôБ6xï‰þŠ÷ í=!&Šö…'iOaƒ’öd'aÏBÍSÔéä%¨`q’õÊP»b½ÒCÔáä’™§Xϲ/ì• Ÿ'i@°§À5 {…YÊ{:IØ3qì {EF.©ù1œBÂuD‘žÂã\Šß’֊ߦEZ*~Ì|–¤gkÀWñ³tBèp(~…BRžEÆ` Q/Œ„õjãN$P¯ zõ*’õªLõâ4]¨6LzJ•¨W™S-i¯>ºSˆ~2ú ÜcT¢¤½'øO´¯=hïÑ1E¿@7Ñ^Ñ;hÏ‚ÝÕ|EèÀgÆè€7Ÿ)ÁѯpRKâÓá\_aê¸$¾ÂÔõI|e«]Ÿñ¸™¯Ùy ú ìv’ùжžÁ|Ê·™ÐW¦€NЗW úŠTòÔýa!¡/ž* Ïì«ûZÂ$ô®˜—îGbê~E»¶€¾²t‚¾Âd }…éú ú¤„ì§HU—ì÷;æ+”Uù B¾†ŸrHä -U¿¡§òU½\²ŸÚIÙ¯nùˆwÒü$ŽÝš&4?ÉË©ùÑ^éÒüÎóÒü¢s¡ù1@î¥ùÉä €/fŽÔü4«¦æ'Q25?ÉÝ©ù‰}SóÓc¥æ‡È¦—äw(wß’064?~.)ù1ëUJ~L={I~Üt_šßTïBó£UÖ¥ù1ZÒeö©µ¾FÛôÛê“[˜}róv™}"eÜ%ùé K«Ï%N «O=UZ}ê©÷#q&ïµxñžª‘÷Âð7%? ÌÉ{ rrñÞVà=žeîM9î½K÷ª,qo2ôNàžml¼×ÿrð² ýÜõýƒ~¤ý˜W<Ñi.ÍOúέùѸ24¿ýiìמ¾&Å}|ÿ¬€œ'ò›¡’ü’“ü {%ùUMùmnÛRò«2ù5ô^’_Ò#û Ù ¦ä'GÉ`¿)ߥ”ü˜D>ÙÏâCàþ úólš¨2µV=ò=”âתTÊ¥µJŠ•èϳ‚AqêŠß"%dããøJů1éÏ}ƒ>–ŸaHþQüÎÇòÓvÑx5¡øéŒ>¿NÄü:ƒ¥à×›LA%ø)ÅW ~Jx ~5¶Ðû޼ö¤÷‡Oz__? ?­Ç r ~ÃABí³+ІԾG¶™#]~xþõ6ž%݉p•ä>s%AW$÷Ù‚ÿ±ú”ßEª}Ö0íRûp”’jßÀÐK±ObUª}]–¢RûºàBí“CÂ_Ÿ²ÎLµ¯~é¯ktŠþ”51é¯o9/ ;cÑ%vê^—ÜÇ¥5°3‘R`—mu`Çò›Øu@˜%"À>~`‡¥~ %™üuó_—ÙBð_gÐðà?{ç_þ³—˜sþë4áNþëZÉ‚ÿ4“ÿúT#â?½ÎDÀÎøÚ‰€Ö2¨QØÃ;PhQ§èè'±O.\)ö1Íh" R"`_!ÿ;­ãU¤ïßâÊ™jßÎÉ÷oQHß¿-kRùþmò@úþé9Ó÷ïèNB@›7À–áûÇX‰€ãùïßJ†ïSƒ_¾Úæï_Ô ç?idéü§>§óŸ~ÑtþÛ|§éüÇ‚tþÓ±|zÿÑÉ:½ÿN¸îøZQ#œÿ´CLç?Z¥\Îê]:ÿi$§óß©‰;Ï/ï?9Ÿ¦÷_´Þ[\ÞòýJï?N¦÷_Ü=¼ÿ´‰Mï?Y½¼ÿwÐôþ;|¨ôþƒÝÇåü&›áü§û¤óÃ/ç?†²¼œÿô5¤óßþéü§—•Î28Lç?ýxéüÇ)ürþ[’3ÃûO'Ýÿ˜ÖørÿìrºÿÑc!Ýÿ$ð¤ûŸ$”pÿë2 ÷¿Îƒ•tÿc,ÞËý¯æÚŠWšî2–O÷?Ù*ßåþÇ@$‰áX˜þü!‚Íy—J`ºÿÑÚòrÿí{Óû# ïvÿƒ6˜îõ+üÉeþãþ·¸ÿ…Ó 8°I©LÔ‘\ºÿÉ£-ApÒ.6@°q/u Î.‚å"Ÿ$ØÚOlU>‚"Á÷Ëè_ᯅ8$('Ú$A3H°Ñ~)I°qK{9 'Óy®.À©:á( ïtÜr- @}{‚ ‡ Ãýõ d¶¢ßgœœmrù¼ó°àGö§We%Uù×¢˜-ÛúìûY’¾T–ƒ²$#|íŽçWg£$ÛRY¶•%W[žâóÜ,¸ZBÑÕ þ³£Ž™Wc³wrGû›éïEÛ,3*üîKµ{¡ì-­á2Dšiè÷CfêT}‡€ú1øìÝÙÆþSG-e`1µtcKY‰-Ýu¢¥+-]aÅÔRTRKWh)‚ŠEKWP1µ•ÔÒU'ZŠbÑÒRL-E%µô/„³XÐû/ìØ0aãc’µ¿’ìB—¿kìOc—ýI¬±¿0£ýíw³ÓL`ûÃ!ûsRûÃ!û»–þé8c¶Víw÷÷_œ±÷+þ£8coñÛÆ»®õ™>þçòw¿þ?3¶Fqc»÷õ¹»ÅgZ€­ÒÍaèc9¶ßßEºiÊÂjÓÝrÈýº c¼»qû¾é¶Â1¬£`ùÔb$‰f—SµÛ·ø9ðz¿'ÿmMG•ãécÜ÷áA³KꜺ½+QgáÔíUf©t˜`°„·ÄÃöv;g(©‹‰/i{þnN:ífû5- S,VÔéXÈÌóÂÉe½{RzLÐÏ{MX§)Êz·TvŽæ% =\¨•‡{kšso§)Jó’ã1Mü`Ö7©ïf©àµÑá-9¿ÑÅÏ0×*3œ&ð«öß`з³L˜ð¢X¨b;Z÷™¨|§«O všƒ½Ã¥›Õ¡»ú»Ö,H-Öéìú–lÆOc”eÚ‚• ïGgwÚöýæò´ŒLzQðœÇÍ×ÝïÝÉ ¼/OÙáîàtÛ^4:ò#^gçeËÃëtÿ¯-Sg™µqä‰dxÞámÁöáã_Á¬m<±Ødäïå!%Ç–ÔÍígðª6‚»© ‰9T{b±ÅãeÆ"n·ãÓ¶”#<Ñö…f{^5o3ÆÀþªqoŽ…Ô TXH¯fƦ¯Äáãy}èÀ†/ËRûlùSàª]YiÑ4u[jØ^?üu=·ÏF‰o–·åö™ô§ðes{n7þ¯ü-=·›¼7ÜlOîãuèF²=¹[«3âöì>n¿9ª=¹;,DÛ’ûø‡º¹ÒoOîCL39A¼ïÝ“û¸_ÖmÉ}à-ÁS¬=©§nžoËíCczWn߂Ǡ±¼>}Ãdly}¬û‡I ¶¥õñ…ØÛAî—ûQøB»™ÀÕ®ðc»m9}èÕ&‘¾5\W¶eô1hVF²í }Ì…Þ¾zš?σ>œía ØF¹ãzï’§F¶- ?³ún¨°QÃvÂxu¾]Ý&ê[$ñG˱§,ƒÃæWÛš·ŠéX½¦Ì³÷XlÁÓö[þ'bæ¿^€[ظF¯0Å0{5ÚLg­ßE/ŸÉ{e“ßžðÆvk;t/×…¬€îEÖ/^€+|J8L6±]qdþ·)¥èÖÞãBéð½HCÁön—®N¹Nz÷’‡ …Àö´gÖFÃÞ0ÎMbýÕpa’«å'Éù p¢œÜ.”c°‘ å½öb9æ?L–{'”ÞÌ=pFº`ަç sƒ4 ˜3£P$Xβ“7pQ°½°‚åÖ¡™ÏÅr\ “å”P=Yî™â4±ÜCÅæb9n’å Óø%Ë•FÆ –+Ìx”,W&õB9Ú$Ê$ÊU®²ruÀé1Q®N|Wr•Δ‰rràO”kLW•(×N(I®ÑÚ;I.Q$×Ô)INÕ“äÚPwDrýQ‘\ƒ‰R‚\ f€\§5o‚\§Ah‚Ü ‘ AΤ,Pš@®o•äúâë Ü¡$Èuf?IŒž('Ó¢D¹Á¤‰rëB’Üb;‘ܬ"0‘ܤñy’Ü`ØÊ$¹­C‚ÜdV¹I¯Œ¹É9)AnrYJ[tø›Œî‘ g¾™ ?‚ÜäR” 7™š2ANä¬ ’@ÎÚÙómh‡$g?$g¦Y¸ˆ ç¶Z.’œ•|IÎ$¡Õ‚äÃäl‰š@O’Ü–ä ’³ÁQ$g%ƒlw~#ºã™Dr6~°íÉ™) ˜‹ çàqYÎ:ÌvÉr‘}>`Î#²yYÎúË;æ<*¼¿,ÁÜõL„9+ñé;`Î3›”lÆ©  uðœûµ€´ÈsžqWùÏ}&’: :ÿŽpgÂÅÐyŠz &‰Î®zPGD÷ QmÅ}C Îvì Π% {3€S@çg^@ž³# —ˆîygB:Ûy‡éž!PÒÙU,!Ò)ò}2b¶Ó=´«L¦{hÁL÷0ÏS2ÝC{Ídº‡––ÉtJµL÷ÀV6‘®rÑO¤{øj‚èFóI¢³­XQPW¬& Î_(n%¨{ƒ1¡Né ê D“êŒW>TW(B%ÖlëJ² ëlA'èð†@ÿë ¼‹ëâÀ$°.Înëä\Xg> hGXWi¨šX›ÊÀ:øO¬3ë*P“°®òœ<±®>"+a]eNÄ:‰ë‰u `XW5rë*mAë*œÿ“êêù‰ê*_`@ì"êâ. ®qGP'O BÔ)7B@]Ó© î*Õ5†¬ ª«4Œ"Õ¹¡ >va]íbIÇ:äÀ%0ç8¢7yx”L÷V!¯IŸ› GEÉtŽ·‰tƒÞH‰t“FH‰ts ΄tsð™é:gézä él…ÆUBºÎ-} ]ã9d"]gLôD:9&Òõ‡ä%¢S³º^a£|isLtsis àwisEüvis¸qHs LvIsp´½”¹¸“x®·ÐáÄstNž‹——@G¼Lžã1éÅsŒc‘<×™8^<§¡˜<×Ù»à¹Î!¶`._`ÎJ°ÙÌ]%‚9™ Ìù½ÀKë)Ìå“ ærìæ¼;À§GÖ.út sWœõBŸ`.{,˜Ë—,š»ê ‘Æ­ÆuF v›:#•ä)šÛÇAsöT…|·ãS%£’æ²?¢¹9¢9kÃM4w]Eš‹ïA0çvÍ·Fç½A»„9:h…0—Ï šË'Í] çòÞ¤¹ëð¦1H›hÎ:³X Qƒ?As9ƒ‘æ|²ñ¿sÙ Â\Â\NO„¹ü² sùûæ¼ß¡Ñ]ã”0—Ïå0—o‹0—ß+a.NÛÅs9ç“ç¬zIžË›’ç²Sä¹|7ä¹ë¶ã³Šèr´èâ#Ðyª #€.¿ ]\]Î d:O`IF–~YZ$0—¬,›ìñÂʲ1ûdZYšÍùŽf–…ÒÌR‰òÒÎ2Ž$ÃÎÒhëƒsá˜v–Ug²³ÔÁr˜Y¾ýÃé¨Ì,›Ž_Ã̲Mñ“Ì,™û4­,[¡X†–Êp‘†–t³MCK¹§¡ec¶³´´ ˆ˜––ÑŒ -íÐÓÐRþÆih9ø©¦­e×û [K;H€Òæ?wØã…±åàÆ–‡‚™´¹Á0il9q”Æ–ƒÖ)Í mŠB››²ULcKz𦱥¢‹¦67I›akiú7á¶–Sûýç–ž!ĹEG¿ç†v}!ÎY$EP›[]¦ŸÒæ6³‡6·¸Î¦6w$K›› –ÚܦýCjsJüžÚœÉÉ ³­ >Õç­Rœ³(¹¸JêÜ¡Tˆs››¾ÐæÂh/ .©§6·µ« mÎb! DÚÜÖ®,´¹]eWJmn‹C›Ûõ¥Í™z 4’6·™Ê'µ9å®OmnÏ&—‡ù Esi™ÒÜat¸”æÞ †vš’æÎT÷$ÍṰ̌*apy¤Ÿ…Á%O^S™;EÌ–ËÑ—Á¥,‚C™{ÛÁ •2÷6ƒy- .Ù¿æÎ£*`9·9¬?ì-‡”ð·Ô(iî 4YÎû‹ù]ÊÜa|@g¹ñÔ)cJg¹·@¶`9@s˜sÓ¹Bº[²¶›̽—ÈÜDö–µKîs˜s#ÁN L\6ÇÃàÒôAüé07lÝ#ý¹Áeeäß0¸¬2Ù—Å¥¹Xƒ’hqY0‡ó¿epÙe_IƒËÊPÆapù0ÜE\²A·¶¬Œ Ö–MoRÖ–¶1¦Twd·¸>æ–êhkYiÍ YÎÖaüÂ^‚„¹^Øáæ¤.J˜³ÅJe·s™Zú¡œ s-îAa®1†R staN²¬„9XÀ'…9%Þý'Bt}„¹5¿D×(@ÑY¤W™ù":é9At6 >žsÞ‰tGrÞÊ£D´²ã$qÿ :ž|Ñéx%‰n1FNÝ’¡šˆÎí%pU•Yìlèl‡ÊftnSñ:Ûv? ‹[ïܨÃqíiÌ-DÞöAt‰ %D:Û?Ñ ‘H'W §løHsfí»Íùæû#ÍyÈ7–ÈØ¿PcÑÙà¥#‰ÎçüYγ],{At6á»_DçëéGœÓ, {§ 9‡ è|¹è|ò!ŒèÞùªˆ¢*מúàÚÄ¿CˆÏaú8÷þM°ÎùŒ‡÷Oœókèš·¸ìTÃÎùLºnœ{§©)«OàÜ[R䓜ó:•–•Žs˜i}é87žÎðÀÂ9ïó¾qn<ƒžK¹·õÎ »Dw7lȽñ8‡vˆoÎsÃ1 ýYXƒºì­ t>áÏËØòm%®н%KJ€n¸Û3T6?' Žt^gÑüÒîÝi5™7èÞšJ è¼+ n=·ßÜ[G¶º÷^;3Ý[2¹õ!нí¾èÆ£˜{ºQž!?¹ëÓl°zÑçPÞн3Þ¶€î-)¤KÝ{kY´è†Å±C‘èÞúêèÞ‹tM¢ó7AÃIÝ(Š+,¢{›q»âÜ(…ò­xî}Dï’ç†EЙ0yÎ{Wož{ëhHžó§¬”ãŠõ¤Ê <÷Þ:HÌynØ ·­¥¿îC_9ç¹·™GF’ºQZ”è¼*vº·*Ï>ê°¡J]òŒÐ ‹Fy Dçíß|Q}o®]-ÎßøèÞ’"HFÑ­ÏáæD<s/cTé| ºaCc^Dç¿ ö$º·Jô9ѽª€èFQ Ý( .¢{¯’ó‰î½J®"$ºQßODçO>oº·ŽöŠD:ï Df2ݰáM90¿/Zi‚éF²õÒyQ¢ówÓn¢ó7ŠÃ!ÝÛˆüaHtÞ½u tþLõv¢{Ÿ›°Eto3tÂѽWiO¤eÊ6PHgÏÍvÀto;r"Ó½%Kvœ`:ïO»Í-ßþLN„º÷^²î%Ô½%ÚQꆅ˜Û·¹¥ß½} Îæ<¡ÎK0÷êÞvè/M¨óG_´¿ÄòZWlQ¿wü4¢ºb?+nªóÁNÆÕy—q¨@ªóÇ¢i'°Î›¹ .}ô0¸ô‡(O¬+KnÚÄ:´wit>а”ëÊ»-7Ö•©aO¬+æ1 JÖÙóvŠv¾¤–Å0ÉÀ:›ˆaÊL¬³{ÐdÓ°.Pb]±=˜Xg·¤¾¬+æÊÖaו-ßgr]Y?rµÁ»€ëìmaes´+§È hW ¢Q´+J=$´+ƒ›¡]9ã#ÒyÏíIg˜1èIgý¤<é<âex9lݪ—áå[°È^>34tzÒ•#siºÒY‹ä=¸ÒY'0Ó•Î~<]élàPøƒ+]9Ñ\é,>ã¾gù¼Û~ÄÝz÷õó5æÝC4×T#JJîZzYVb•-îVylWÐïDIF¸RYFÏÉ’Œqõ.u6Þ?m©än ew[*¹Úz÷\Ÿ^ñï«/¹ZáßÿÙ1·¤üaÈ­¿FËCnõ¿rë)ÿgCnýn°œ9˽ ¯í;ì|DU—ÿ¯Zl)ƒi±¥;˜–ZÊJj鮥–"˜–Zº‚iEKQ)Zºj©¥¦¥–®`ZÑRTŠ–®Zj)‚i©¥+˜V´•¢¥!ä–q¿±ûFÜš/âÖü;·~7 þ$âÖ[oüQ½Ÿ·þ,”Óψ[a.ûÛÏiéf®¿ýшý1™ýɈý]KÿtÄ-“pÞên½/âÿŸÿû?Eü«pë,ëÿwË0ñòîýÏpkþQÿñ>àÖ™ÃÏF—'I½çj¼æj½6ÖÎ3×Ä‚ÀÆ»0úѨç@ãá}=!Z8~4jÜö…õLT˜XÏ*ê·¹©<ËoÜÛOÑÞU;Lp–ÜÀ›»øß½ÁU›tÖðî~Fôþµ½×JWð®Þ.ÚÆŠ&ŠY\Ž…Û—ó÷Y.B¹ï7;å2•Çþò=ÁÙ,Æu¢wM üm‡­eÒ#÷Ÿ(p+ÎüÓ ­€®ÇÜ…í(öQŸÌ÷Ö½½¾9wᵞ¨smõaŒÞzöÂYm¡™Ì±$eilàxõºèUœÇ,Æ ƒÑw=üå.æ~&rÜwTß#\—TXŒUÚ?'ÿ•AÈŽ9ê,œVãešR\i„K,Æ*O%މ”¦hÈô› Þ WÅŸÎÏÇÓÌÒ¢É_Ž O´¿ñÁ\;yì8ìö~½%ï«dŠ=ŸÖ­ä„A6K*ÍÆxtý–´~[h½=ìÆ:«Xpæëü-°ë®çïß ¶còê°’ ÇêÉoɆùX§íê[b àÁ픩-: Ƭdû†b¬má&¼?¨¼%Æõ¿Üýüa;¦ürÏž§³dû3X¦ƒ…7’×Îû·¹ýr·ñÆ{OXÜÐ÷Ç ¶wÏdýŠOãþè·~çz×7OÞ‚ÚÑ=æBKŒ>³Ã­tÑüß’³ÏóèÓh£«{ª3aøy„1o Ó2ŠÌ[‚TƒU/²˸Šß’ãÏC "+?ŸM¾èŸ¥—Ùy Æ«¥—iT‚ðT½B;|*K/SÑ »×]°sኇ²ü2.(QØ}KFASûMnGuô£0»Œ\“ß‚±å[²™iÙ­â‹N“p !"äËBTDezK ýû½òQèà×4ê-½Œ›ŽzË.ãg×1:+°3Ãú»ü…n¹e˜-ïÅrËÐŒŠ²å–Ù—‚„©eÞ’= ƒ>šÂ”[Æ `Ñ=K.#U•°]ί–]f •ŠÏtÊu–Ñß’öüÆ4N|{ӧ㈻öô!WU>”%—aèuÎh–\Æ èZj%K3çË.CS%£ Á3œjß8Ѳ ˆW£‹>´J:ð–€´#Ù‚•À‘VÉÞˆ‡dxS‘Y¦âXç-é¾’†Õ”•À™V6]oÉXx€ŽS—·d"©Å˜q÷UQ£ þ}›íè3µ-›c-(*oÉéÈ­ØvÉáÑ×J¨vM¨› þœêñ¦Þù–Tü,›¾…ÓT‰/¨Öòf uü¹5îÁÀkè°rË,æG·’ý#±u¼%—YE¿¤Í¶ RÆá¹©å¯¡áèÖ¨ÃÕÝSþrÓ%N6¸=ÖÔK·°@|-*ñõÔm¶x2º7Mæž <ìñ«Õá‡iæp ò,§¼ƒŒHö–,_P#ŽÙ[²<ÃÖL­ô2'VGOC À‚ü2G;”‚€UÝ$B â f`Ó£’Êèf´é)¶$¡…;ÀÁÍ ¼S‡Åâ‘›¥~£ TáÝgÕ3`ØÚ—ó%³X°FY-6LÐ,ÿ¤ÜùöåðÓ;MufÖúb­ f3¼%¦w^‘³òüãiüì ’ËøU-ëÔäáÉø_·• ×>g2Nv~F,’£ùo’ã6É-&Š’{ßÏþœYßyP.h0PîÁ‘p¢\Á!PN¾å6Oõƒåì@ å,gñ¿ˆv€9Å¡ ˜Û ê0·ç˜ÛÌ´(˜3ä$ƒæ¬„I˜³‚Àœ1h8•}EÍ™áCÿ·†?y=hÎfÄœš[>ºæœaÑ`Î n–³®Î›å kÁYd9ÃÚr³œx›Îrµ€ª‡!Î6’,g5ð“å¬à!Üåž"0#ËÙ猲ÜÃ%(Xî!­ åæR ”{ë,Pî¡Q4Qîa^@9…Д{†–O¡œU!Måžõ› @rOìNDrÏÖª"’{¶."É•G{e‘\áéD’\y´É•¢ý«H®íErïíKr…® Ir¥«ŽHkˆH® îqr¶[ý‚\éZŠr…Ñ0äÊ”u ° b\YZà„qeëmŠã®:ä8{ñ,!ǽ_a\‰m…0®ÆÛÆÕX“ÁqµjS)Ž«]0Ž«ñÄqµ þÅq56â8ËEl#ÈÕÆ½8®ö 2r\ýŒ8®"xkb\M0®m®„q–5•”DŒ«:RÅÑ•%)NÎ8Iqõ’â*ó‰&ŵ¢-¤(®Ò8).JDq•FÖ¢¸ºÄc¢89ç$ÅÕóÛâÂ÷& νuÈc€8wâ³Ñ¯ÆU•~|†)ÎOmÈ[ž|CEŠ WJbœG"$Ö1I¨Mp$²Eo>¹ÇÙ‰·~ä¸p'Žsÿ<ÒÔC—¾8g"Ç…'apœÝK¬Ž —ý9–\ØYȹÓ/[ÉExƒ ¹pÆ ’‹Ar¾Éfœû³7r™=n’\x?’ä"ÊCœG‚ (Ñm¶M$9 ³“1 IÎ;LüÉEˆ‰ ¹ÝKÜœ†«=N§Hrw;4]íñS9É9[èoˆö®AA˜³~|`.„ÌE°€9;ƒ{ˆ\ô£íK‡0g§r|Å„¹»Àœ•<¼ 0gípfs˜ó¯ÌyÖÌY~á„9;YdosÖc‘‚ÊÄ©!aî®CoÄQ4æ®sDœÕáoE˜³vˆóA7ãt”4™‚æìôQ\FçZ³+#ñæìhq~hή:šóä¤$!ÐÜÉn…§£bÑœÕá'MšSh$œUàÀ!Ìí±ôÓæó3XÎNKy’L–³f8"ÉrV‡YÎê<¢;¬ªCd$–³:Ø]€å"zg°\œÔå¼Ä/”ó׉‚†ÏY¡DEr~Q”`U:ÆÉYIa_@rV2yÕ²:D¾B¹ÈÌ”óg<ü[qB“OÖÕY¿,çaš0+åÊ WQ·«prD–ó:¼eÒ‡å_3èH[Â9O ×.œ‹½À9×\ð'pn—-á8ç[-(u‡[Ež' ç\•ù•4縛æÜ–ˆ:¾Œ«kTávB4—Ý ÍíÂøt 9ßîÿ@sÙMÒÜ.ôçÍ¥šDš³wC±Ò\Þ”ÒœµñëRæ9”9ÓwJ.Í埔æ }–)Í•Tâ°"‰¤9…iNABšS¼æ·x!Í™©&.¡4§h0!Í)¥9­¦!Í)\AHsZ£CšSð£À¹Îsв87¢ âœ}1`Dòœ}ШAž›œ«ƒç&És“Ö~Ás'ÏÍEž‹/.xn†’$ Sȵº9´ ÐÍCDtûùí tfLK\#Э #ÔlÑ2' ÛCÛ Ý^?n/-#º=õ˜º”Gt ›D·§î%¢Ûƒ'ÛºÒ΄ ª‹Nt6dÔÎ|iTHg%Ümé<¿ @tæÊÍ]*‰ÎÖCõHgOf‰tø4ÎÚá Âÿ¦hÃD¤óÈžD8¤¶ozSD:÷ëBA¯‘ŒEü†€šöɰˆîôçKtî?Æ’ÅšUª!€Î“¨„9ÏÄ} sžç›|¢‹¢At&PœÒ™"2]¸~Ó™³òG˜³¯²΀tfÖÈ ‘ÎÎáÉD:;-çÈ#Ò¹× à°[tÖK¢sßj¢lÎGïWºÜ<ÚíI—›SoFºÜ¬ºµt¹‘ EanÅ®VÂÜÚ2æÖÖ@“0—§åPæV(ßRæÖ ÝÒÜ^)ÄAšÛU’æL0ý ]Õ?H'gÛT掶0¡Ìí,FeN99RšcŸ"ŠlT掶\!ͦZÐᬜxé@—§Þä9?z&è€çÜ•­¤×lÈpNû¹sŸÏ¾òwç¼YN“ž³%æ[àœ{p=·0—y(Äsînu㜻¾òóÎ Û‚ö[˜sOÒ[—K¿^Ñœ{ȪÇp¡i4ç½Û·4ç·–8æ4çcªC7ÚÆH㢹ñôÌEOZÛã³§9w‰ª·47Ì¥‰xç07ÌêÜÊœûy æÞ¿§N?s^"UÐanØÂF90çR’µæPçVæü8Ô6³˜Œ¢u07ÌãJ@Å<&WËsÃÑv+s(!t¹«Ð Az3›Éì’TsoIáD½™ÎdÎ 7g9÷Å:7˽%^Xî-9:þËùU}`9» :Èg¡'@Î}Çf’œ{²q,‚äÞ’ªòÐqîÉyÁs«rîVo’s‡®}“ÜÖÈNro¥±’{KŽ{'¹a;’FíÌInØŽä¨ßàÖšF”óV*ùŠªÜaVÊTåö -ªÜæá¾XÎÝÔÄižð[íP•Û#úC?DyÄI–ÛZ?C—ÛÌI™ºÜÑéfèr‡ÇË!Ëm&Z YÎ\º-í)ËYÆ?âe¹Óð`+èíq¯¾‹Þ.ã¤7³U•>éíaþï ·g çHo–;œêèíÙ8 |{f;ðíÙR½ˆo·Co]šßâ.·‡Ž”Ä·'H‹øöˆC…oJvøöUßž4µ¤eåR²¬\!YVªFXV~ùí‘Ib˜V2eL+ƒÿÒ´–š²¬\t›¾=“HoÏ’ÔFz{8 ½= ïô–è-.½ÙäEz³ÿ|èíá,ô½1nÉVSb%—ãdub\\"5N¶°¡ÆéIB‹~ìú¹‡Ô8!{¨qKÓ{¨qÚ\^b'­K«_xÓ ¹Ô¸%„·«éMƒ!éíª3Ù™"ñ­Äxà5¤7½ê¤·«ÒÛ3VæU¢·¼Jô–ª£èíiR+„oÏ ãKêqW;}~z,Eî ÅNô‹RÐ[ µPø6~VFp„ ߪ¶^oKGôÂ7Û |ð­ßJâZeÌ-ÞGøVƒ?Åo%^§ø­&&’ßJ˜¡ àjöŽW«ì]Epíwg1“y/'¸¶´ÎŠàzp‹N™1“à†¤¾¸ªS\“ §øÍ‚ˆUä·g… 'ù‚··Có¦·4l½)Ú[ÒÛ³S¡£Ue|„UåÐÖ'¬*«ŒeT™“²ª ›Ä°ªÔ¶Vì–Çb7fZº) K¢›Ò“\V•]_‰Ðí‰=¬Ð;¬0©Œ&•KZ’À­Ä˸) K‚[‰-mØT6©¯aSɯOäfg¶?Œ*) 2ªTŠ˜4ªL—QåJF•srv•M厣1¡Û A6•»¨Ñ¦ÒüX?J\„ZJ›Jó;gÚTš'Û¡QåLÍF•«h®’Qå*šýeT¹C§”Q¥í±?Rœ™Çõ„7yÖ?RœEñj_»J³‘!QѮҎÆf´«\]'(²«>ra1,7ŠD0²œùŽþºPnè¦B¹Î/.PN";QnÐ 7PÎòsƒýˆr\ œ2_ÊöÃI®rΔˆS$7ô0@nàÔ”×t6rÜPÀqCº‘8îíÀ¾*­=º·äÆ ’ä&‘ ¹qdwI’›]’äðZ„q‹ñ?ˆqsaºŒóØ,Å­&·3RÜš?L*ßIö¤¸ýà,<ÑG€Û8ç ‚³Õþ×prºÀÅD€;]|¸³hÇK€³ýš|ÜpæLÃsÜ]¹ ƒà<°.KóÙÅ™" ÎÞJùèo— ÎÑ€ü8†$¸H¾g“Tû\ê88Ï*FBÀEò²8s±à®ç‚Ëàlâ’€³:GŠô·YÂiÕÃåBúÛ {OÜØZÉDp¹Á)i\n·Dpé{ ‚Ûaƒ#‚SRÜ®áùV#G¹,&â-ìžDp Jšg>br…{´µš_îlQÎWgþ 8¤GÁ¦ÿL+Kf+/Üï¿ù9~­ÑŽ?¬½Àoƒqç~ón²¡¬XpÚÒ–7léTÖ›Zd¸‚ós2³8µ·ñy+pŽ{U@œÇUã·Ñ ­jˆâüTü¶©ÌL®rˆ¦9FH^ÂiŽ8)Ây8Š `8?çv ç'Ú†óCdîôq~Ô+‘n ĉ=»QœŸœ—›âü0˜Ã 7l; ÑÎ)΢?ç»"½ƒÃÈ ÿ‚eA‰,O˜áä<âÛȽ%±·ȽWQ†KpçíVà>ã–=:q WJ쬩ÀÙT!Ç7Hp·Œ{YJp=…¶åÔ଎¨íÁÄfÛ%¸RvP$8Ûõ›ã†m‚ÚÍq>K²$¸R³HpL‰#–œ6 Êñ²=&5¸ÒS„gñ²ø+P„³ Qêg¡½ú‡â, Ò¼)΃HqœïŒƒ$¦„g ÇðV$¤pù¤g •( WŸp WŸ©I•WŸ”Ô@qÕ>^Öi~M’(΢0qBг†ý¦¸·ä ËMèpU±B‡³{¯Û;Î{¼Äu®ÃÕ.‰Ôáìö¥ÃU;Ý!A‡«¥r##.ï$®>É_ÐáüÝþ ÃÕ’ªt¸ìŸt8¿×mSù–Œ0ß„g±åëÎBv=,ÙÞã t8‹9o›J¼? hÐáªlÿÅqµkþŽ >]Ç⸪t- HbÒCëj÷øF‚i{£ ¢Å’;ÖŸ_—µTç_ £U«{°Eûüû Wå%W4þ}…¼ªxZQÉÝÊî–TrµÕ Ò®'VÉÕË®¶¢ä?;ŒV©Å·ËÿZ­ýe­?.Å\ßʯO ­CÏÕ|>ƒñoÑÖ$ m}Bi±­«ÛúÜb[W˜,¶uÓR[YKm}Bn±­+PÛºÃi©­¬¥¶>A·ØÖ*‹mݵÔVÖR[ÿB@­b{ ‡þÿŽˆZefûÛïæ¨?šÇþö‡Ã÷çÜö'Ã÷wmýÓQµŠE†|w«ÿÏ«uM&ÿóü±´ÞIoÛåÑ-?3Öƒ÷¦ÇíÖAî.ÎÌ`€âù­àÍÌcQwÖƒ+òd¶à”«]WÙžè܉y ÷æ®ÁO¸.ïà·d"vÚ‘©VÙ’úîô-Ùðý³˜)ìäþ®Õ}š`ƒ_ŽÔþ¥Ók“œÏeGb%G±«xo“þ¼ ÚW9”û‹”ç‚ØnxÏ}ŽÌxÊÞÅŒ\' ¸9²3:Sàø£ØÙ½[ÕåE§þ¹§Üx›ƒ3ÜÊäD¥>Ôú«þ¤7…vrõ¡Ð>¨Õ£Çÿr¿Oœ@Ô‡B?B¡£¹µF¤XëÜÓÖgà WŽŸõ¡ç­PW–à,÷ºhá07\Y«YRµo÷Žs«b|T³›â#à ZÈjz·âÍUCçò¹—Åæžqb޶{X£ =‚jÈùV¿Q5`ì?Jè|Ëp×oÉÄénÑyßê|¡ZÐV¦ïÃ&·¹ß*.HµÝ-“µác©5pµšNàéÿ^ 'ÖPP»ü[Ùlm8éÕ®÷-`ê̇ÈWm»«4‹x‚:˜<“QjÞ]t•‡nc»ô¾ 7Ùj³=tÕpúßrdU$ækÀUî·LyTj{" [it¿µì%•јPÛJè~Û4ò[›roåh½«Î kŒˆÖ³„Ñt>WÛd6Í&muü=Ø›ÍlšƒóÞ[²?ªÅ[’î·(èO“+GMOïÛ(ÙŠéÆQÓé}Ûd½]{ƒÝŽ™ˆàzWrV¶ÒaµÃ ÊoÁˆÔ›ÍÎöu2~G>ëٵå Ûyë=äd¬«|þ²d¼K”Tžýuµ¢aŽ“­ºZ$ÅåT¸úÔ0çÀ_”Dí3g‰4јd×<ŸjQmòR­‹²¨\äÞê¢Ê=l%;¼æP²éyÛ˜úæ-¡6š÷Þô¼U¦e+ÙzþœÈzýMy´é°¸*h8Ó×=™{³ºé{›okS$½úG•T‰ˆ­dë[ÕUÔI•¸ÔóDþiZõ”p¦çà?‘‡›5(—¶Xü½o[,u‡’éU§Gj.mG΋òô©‡Þ·M~=õÈ}1{¼"5ç#Æìá‰tÔ¨ÓWOcÖjOú0âÞí¹œJ¨ ÆDÖJ¨šëÚ“nŒØ+´‡2jÄ+huÔ¦ðí¡’z•PKé®™Ö±°ÎV+|¤}ôŠïDƒX{÷h…y@=V hôè¹™ÔJpÚÚŠfÄÊ‹ÔJŽ&MìU[¡Al£Îþ–ÌþéŒÒ‹»šÃÆß Ía¯¾(Ψ¦âf‰cêÝL¥5l¾;5dçpÛ*­a# jó< îåZø÷Öœ¯’1-&oMk؈Œ¡ó+9¼Šñi®:ŒOÓ©EýÕð[û5Û/~ØO‡ðÁ~ŠÁ%ø[òÓ ø[3ðg¹#x áoI6ø[+‘ð·V€áOÁ¼þ–L07­þ<þ3ÛüÝuÎÂß ÝFø3„ñÔV««àÏêðÞ„¿»CÛJxNø»ëþ¬¤ñîƒ1Ãe+ú»ÛY Ƽ!¤¿»ÆŽ0× @þ[H°cSù/ï$´’à à]R¿Òï–c¤eIçßÜ„ïVÀ€÷5“qÒžÒ5TGWmFJSW1à]ç0Vån! p7B´®íDÀëæŽ€÷5@@/!¨—’lÞW½ÃD7 à]´’ùAÀ»ðî1Я"S=U=d;Ž€Þ Q­¬Ÿ5À€W»dÀ¥ä-×sïv iç¼x· ¼{ ¼ë€ï–[Ùì(ðªA ¼ê¯Þa†‚ó£{„Àû"@àÝ0 ÐJx_¼ë¬þ¹5ÐŽÔ¸?%^UÎÔ €x5Jô’Å’­àEuªo¤à]Ò˧+$ÀûFƒ_aÖÞ·^ü ¹„€w;@Àû* àÕ"à§dë·¯{9Þ×€ãÌR xW^!Þͯ'^‚xwOÊT–ï–O|‡Â·g|zCÌG ^@À«wDÀ»U àÝ.ðê ð¾ x· ¼ž‰huÄ|{}º¼!^·&^Ý ‰0:C̆I€wÃíDRq\ 3ÜèU‡ñF¯îÌó­Áˆ£×2y„®Qöˆ¬£ôr9^Wm…Í:5UöxgàQ’®àÝŠfÉx~ôo+ø¨^ðêðVôÑìÌŽ¯™)ühöEñGãNGH£òßõFÿ²YâßUÐêwþîÛôõãõþî:³þx½„¿«áµ~¼]²ßÝÛ“ß ±È£‘F ±ß]ƒñH£3b¿OɉG`;méÐÁ_tXìwW'^/o>—AuVÿ°_þúb¿»3gêØ Ùïºáï®SÎw"üÝuZÿ~¨‚¿»N?ߟAðwß}ÞCZðw7²öwÉýå|%úËfwÁþñ„¿«ÂßÕ9‡¿ûš¶£ûx ÂßÝÊhŸ¯4´÷­h2b¿»™_rÿk>®+ð‘Y/üK=Høg¢“”=O’]¸Eøçñµ>ø¡­ÿ"UàŸkUíσnñ*àŸ \¬ü3QLÊ#µ¿rG©ý•M³ëÐþ"€+µ?ÅóJíO¿Rû+ŠÂ“ÚŸBÛ§ö'?ýþ¶BÂ…ô·õà!ýeiY'µ?í/»¼Ø=é…ÿB ¤øo/Ä¿òô¿"ŸçÐÿЬ Bÿ+¡‚Hÿ{"ô?%ù‘þ'ûÔÿ® €Bï†(_óÃî-@…HPñRŒ€È!ÊU>@E"Hð‘#ÀG?T€ 4 Ü—Cÿ{/#ä?¥ü÷(‚FÈ\§üwõŽò_¾ Éy•ä¿g~å¿èŒÔ¿, ú—¿Ô¿g‡JGùï‰\ÉùL’ÿò™¤ÿ]½£þ—ïSúßU‡úßÕò©ßÞPÿË_[ú_¾éŠ!‘úŸb‡ü÷h’ù/«ôþcIýS ‰TÿrÌHý»î½¾ïSê_Þh‡×>»%þå —ú—/Oê_4#ñ/¬Büˆ%þå3Aü»nDñïjeÄ7¨k¨þ)Hª×UTÿòKýË7#õ/ç©ÙŽä¿lGò_<8Կ몥!ä¿|LÉùÃIþ{d"úŸ -#«Pþ{´n„ü÷h ùï.ágˆ¾@ûËžHûËF¥ýYVÙøÝWQû»J¨ý囑ö÷h± íO]¡ð—_—„¿«Y W#{]MPöËÇ•ì—Ï#Ù/ŸG²_ÞF²ßU‡²ßU‡²o-Í猪˜6Gó¨4¿«Ùy>¿©4¿•Òü®kØFCC’_>£$¿lxgh›#¯üèž$¿«öão·‰ÎHò»ê(À QŽz_®×Òû®+ÀÍU²Œmé}Y"½/¯’ޗ݃Þwý­07 ¾z_ލ“¡n¸w‘Þwµ£h7ú $÷eÂÝä¨öeÅ»É8õû~)öݯø>©®)ænb_¼ªûb<„Úwµ¬¸7Y’oÉL‘oòî }“WQí‹§¢Ú§Ç±/ üæ0|Dh}نľ|J‰}W‰¢ßdIë?ë(úÍUr¾¿Bˆ}±¡¤Øw]£è7z©}Y Ø7Ù†bߍд¾«`ÆPH}ycI}WI+÷è ©/¡Ò—=‘Òw•Ì`(}WÉŸ:ÿ ¤WÞãi´nÂSP¯$<Û"“»ŠÂP‘ºjì+e;IÂ{"Š™ïQ2Ž < {ôø<`ÉŒ„¡‘‚ðyéïŒã$t”qg"ifVÑ­›ª]Ƥ.wF»¼lW€§.IxÑ=^¾ ^>¥ïºï*YlmHð;Ÿ툶&$àÙ‡*œ+znÌxƒ¬ß)ÔYò]VÞe+»°j$ÞÉá&ñnl ïÆo*ØŠ¦Eû› ;%yKº‹‹w#pTp—–‚;]líÛ]%ûóÉvÙ¬Ø.¯ÜåU¢»x¦ »lGtÝÜeÁZ$ÜE€»èáîú{ý¬!¼Ëá:tÏtÏt î²w‚»lFp—÷ÜÅoI¸Ë‚»h%à.îp—%‚»¼Jt-Ýé‚î¢3AwÙ°è.›ÝeÐ]O¯èTCx—Ý;óÇ#ÞEoïÔáÀ»èLà¢&Þi¾ÞÅ x'G½Ä»lEx×¥¯Þu™àÞåU».áQtU‚ ».›· ».+3â| ï¢{wÙŠð®þPö¼{lGx×~({~/ïjÜJx×exw•,u¿ Oo&¯ësÀ‹Fð²^^%À‹7€O€ï</¯Zá-AE3/º¼×çOA^´ý È“ÇEB^^%ÈËA^üºyñÜÁyÙrÆ.ýaÛ™ÏM΋1œ—=çµÔñJ<ƒ¬=÷gÐ!¦ ô²D =ЋþôôŠƒó²‚8/:œ—ÍÎø u•P/ÞÏÏ*"½,é)Ò`’^î·Ã¹/·Â¹/®Â¹/œ².ç>ùÜɹ/îÎ}¤©pî?L;½Îï¾ìŸ¼ûÂJxµ,ï>eLï¾õÛíÇ ¨É»/ªÈ¹/|»èÜ~\áܵáÝÞˆáÝ7Ãþ’üwÕ!ÿ¥§”ø/=°€Jwv¹÷…7•ðº0}!éÞ§‡ ï¾x„ðî ¬ðî[?L;¯Î„w_Ú›¤wß V’w_t&¼û–h>¼ûV°œ¼û¢a9÷Ž/ç>5,ç¾p»œûXeÒ§Œ¿øöÅ/¾}á¾}á¾}áw¾}qëðíSØåôíKß9ùö¥]“ŸÜDzóòL ß¾Þ~[N[jW¾}[ËeøöeoÒ·O-§oϨ.ß>¾Ë·«KøöÉW7]û¾R_ø³¥k_xó^®}r·»\û¾Ø”4+]û¢Ã—kßWë‹ä¿·gßǾô·ƒc_zÅɱ/k¤cŸ<éÒ±/JÒ±ïcÜy{ä]ž}(HǾFŽKÇ>5“Ž}¼SúõÑ}-üúâïó³w„¿x1·_]/Ǿßùõµßùõu6“~}S†œ%\i§IöˆӭOUäÖ§Þý®¥cŸérìÓ­‰~‘×9Ð/Ý…~éR(ô‹î‰üÒ‡ä—ùÙ¾äg¾‹_¹/|~W_Ò¯O­pÓ}.'â†5‹3û‰u3˜ã ㆱä7ìO¯»â†±Î¿7¬[L¦~ß!J®8],»âþDÉó«{ê«%ü}·c%w+øûjc!ÃÐÖæ m}Â| oZC!_ïalë óŶî0_j+k©­OÈ0¶u…ùb[w˜/µ•µÔÖ'dÛºÂ|±­;˜ÚÊZjë_ Ö–'Ný;ÁÀïëyýaÀ¯öâxýˆ ÖþA=Åû9.ÿa\°¿0sýíwsÐÍSûã‘ücîúã‘üû¶þù¸`öë¾0ôÿ˜¸`ÿñGmüÇ¿¬y˜r¾´ùs’8\(:\!l‡‰õÓÒ·º'³üÇ_ÖõSûK±â~Ì bÑNzøªÎnZ0htäá»å.a‘·=T˜bÕöGv÷jý)MÖS8Èè ,xè` ´* fh ДLª?ÝWæùoD;€¡Üý Ð¥Èý™ ÐÈü×-«¢8=ŠÖ-IaÃßR Ê4löçDb_œàtËù7_¯¸[ç‚c4¼®^ SÊtêŸý¥RäáŸ<zyþ-AXñpãè…Ç@MIE»Eö|¦ŒCÜ O,øðdÉA@kÆïÇ@Å@u6âw…ï®· ®ocË¡ˆ›¬Ž{}¢£Y‹ëfO­{­VÜBÙV^R=±ÿ‡%ÍãŠÛö«ò*?zy“÷:<®x{²o‰"n¼™%ÓãŠÛU‡-¿Ý|¯QÒéþR =@óÀÜ(ð8ÄšvcÜñŒf; t¦ù9а##\ÔŠG·¹æa•âQÅ{“ë­zâÞ˜A¶Û=í áØL÷(ÄÝFZg‰ïPýíÆûwWêªÞ¦‡ïѧ·åQˆ=zc‰G·ê‹ñS ñ~ßD‰ÞŽG1ž'xï=…Ø’Z¨Ät{×4Ñ»Ÿ½-ëõ½??ÂÐ1Kï~4º…Hí,±[oeêÝÆ»9åAÖ[à'ºd½ñFÓOtÇ£C´·ÄOtíÁ;¯Z~¢ká¯Ð·ŸèöÑ£Îñ];)«*ñݾ”<¡ÇOt­¬þÞç'º}"#Ê[P«ÀSö÷OAlßùÔ£uür}ûPÑ;å†zK~E/ïÃO†þ[Þ÷èGºo/õÃOÞku˜ù–ø™®½ÑÊþî…'Pù÷®¿BÓ@šOå×ù÷Á ÙzêéqßgØ”(û¬¾y²w޵¥ÏVð¥*Ëü[âÑýíag÷°â6ò;¯òs Nœ™÷é¯ÖÇMeÿ¦Ý[ðºe¾ñq>4/#õÍûZÙÛã!Å{áŠÌ7þîøµ#÷ÍÛˆ²ºuK~cu¦ô°Žì7oƒCénéo~JÈùo†íþ8Û[œ‰8vË€óΊ4Ô—kg£Ù¨å<ŽO“%Ë#Š·C?%Æx1/ÚP¼›ëoíG@^‡k„é”ö ˜Ú†« ÇK8©™Ôh<ŠˆÍ˜oi1¶´Z˜Ú‘gt™ vdÄ=rU3ùÎ[eÄ­='Î;§M=‚g·aÌvÞh!°ÿQê—éü”6­#5ÎÛ!ñ%Ú‘Yu–¸²b‡ò\±NxRtäÇy¯9úüK¤ï3<œÁ ç­¢l˜ý¸Bú6£ŒYr¼áÃ:.Ž`ÇÊ[M|ƒ%¯r‰tØ,ŠcÏ€âu*Dzåà¹ñnÞý!V¼½d9þÃaÕ+¤¾Ž<*9x„ÆçvË…ÆÓd9þ˜üB’=6]ÉrüÝ4ÞÝÒ÷ã(ü¸M²JBçY=F¦îd9>l mz®ãŽÞÂÒýHÿ­$ÊÍÀ¢ÚûÜ`†ììóUïƒ}®ï¨„YÜdFìØg)Ù(V‘ûºå26ä/,2¯!÷yö_înÀ}¡º àö«sëðë&Ìð ü<7«z¼3(K~O8Û ü®ÅN}OhÞÂ>³qè¤(`Ÿ' ú`ßónU쳤ODbŸÙ’<ì3u„ÛK$,÷ÓÅ1<É}eß>Øç²ñ Üç¯ç°‹Tžeû,Ó¿‚ŸaôbË¿ó®ÀϦhÁ¡Ÿ=Ùæ5¿:.ÌCúÛÓ±7¿zÚoî³'™ì¸Ï¦c!¹oËÄEÜgkwZä>k~¿ºdE*ðk"ÀüZQL1ŸMâüt ~-ò# üšâ°€_3+lÞà׿~f,r>à×–bB üÚÜM?_E‰M¿v˜[žà5"?Û²sÚ ù™ )”ägË_„ȯÆn‘äç*Û!ùµøRE~-[&ùuÅP ò  ¿¡Ó$?³ÒßX¥ºì²‚ülÞÀD~±ùùy ägï~É/rdù¹á‚ü¦lá~K{ ?ˉˆ‚Ÿ«þ^@ô3 †€ ôó¯SèwdÄ&ôóŸ˜%D¿-»±ßû1è##ûÙ®ä|Øï=:ésö³'â¢@ö³ÎYd¿î©Ü¼è÷âˆøWìg#ùÃ~nžÃý†¹“À~vÊÀ1Böë‘ÄQìgíðåýÞG«8û¹ektž¿Pû™!ײŸU!ó’ýÌ(HÏÙÏ>X~.d¿wÕ ìûõM(ØÏ2õ ®˜2æQ5±ŸÁp¥pö‘ŽOìg_¬  ìgýÛø³«8¨ #'tÂßh²Ìü¹Q{ø-F5áo4eöüy;ìèoô8{tú3ƒ§MrýÈâ'ú]yÉDöTâ-ÐßûÚù.Df’ÕɃ ?K7Ø?ôg%…$úv¬Ä{ýw0O±ž¯«ö”•­€þl¯‚þL»+ú3s0|w¢¿1µ×&üÙHð$ü ËÇÀŸÕ9ø[ ƒàÏìÌp.ø³W\?ðgvgK¨çëª=öøÀßx?èó¿q$ þ¼ÁðgSô#ô…Õ,ÑD`€¿15øc+"±àÏr<>ÂA»÷–9¡èïê éoæ§üM³¶h,ñuu>:üYÖÇö¿1eÉ$øUKôç‰×Eú'~_ÒŸ­MüM3¼&~þf8; þfaT±ß|‚ÛÉ~cëxOìg€ÏDö›¶2ÒÀ~–óÁ~cËLEìg?”hðgíŒ þì}ª7€?³ä›!üy»xL)ÛÊXûÏKþ[öp7ÿmÙÏÿjàÇxŒf0 - ç£ýyRögpôe@KçñÕþv:‹3Vyha¦ÚŸEäþ0 ­/…ØEíojB ío…Üæ è«Â——µƒßo‚[_2 ùHw¤øWôþg° Ð21}Ä?ó‰ø¡ýÉ·<´¿w?ÊSPiXhô\¯f1'¸$šœq‹xÂBB`S´¦€@[yT¬26 |7@\÷%Šè ô@9¶ õÏ$© h²?òŸMðlEhQ‚I}äÀw…XùÏ “ŒG4ÝœÌ ´E¾:Ȫf~ÜŒÒÿ¤ú7RYX| „Õíè¬@¸i’8¶Lh¶wí£þù2FðšsEýP ™ÕKh>Cy‡AOÄ™Ú'ÂqN 4é¯hb(ð’W¥þÙLO‚ÚJ7Å…È)ld3P`yŸ„Ý!Z–a~R¤@Kʼ$Úo»â°ƒh½>hIE‰}Ø~VaƒÔ?Óúx!ÐvÖì !ÐÂIö³“@Á€æJAj%Ö:»À€åÈ·èŸÌ-å1Ç+!Ðr+‡Øç«U‰tõ‚@Û¹‰?)ÿ¥”O´óî# ÍÜÀx Ð\0ú«ÙÍð*@`©Ú6‚ü,§¸=70‰ X†¢ª -A³È hÙ²9Q Ã(ƒügòÅî9às²tlµ…ê´Ã‚ ÐŒ1‡€¯à+•±´ÐÒò' Ú¹ •h" è´šÃþ"`¤™ 爀[é刀¶Ëþ  ôš÷Š$CÊ ’%`@ÛQIFšOý0 É"l‡ hïb~Ь0¨ž‹w¬ÄdÀw"œ3àŽAú_8Lí×äBBl‰0„Àfæu(ÚùÒV‰3`µ™ëÀ¦ìðÇ#š/WP2 ãþg[îñaÀ­Kÿ[ Âú_xˆÛ Û €ï“ˆ )öP €-Âo í4޳9°®âÐV®ª,©æ†ÄÎØCÚIaN»g €k†Qì=0‘ }ØÊíÁÕÐ\ ôßF€æÚ%%h èø Y–P£!N3;g+$@3O –‘«Ž­„€6«sÇM4»–N “þ÷ªÝÊæ£ÿÙ&ÿ°åîâ8“Pˆí;l¬¦…ó’k*%$à4Áˆ@|1a]X•ž!ä¿­ƒòÿFÀ’俚Fù/dvÊÖ…63ù"G‚[?‘m÷Bâ'Vób °ièŸã½pvî™ßA1¿òßÑ|ÈSêå¿®<$"@ûá$É[äz¦i–Ð̱ûGþk!Ö"øVbà­^`íÑAÊg H]ýëÊM“ê߸Gõ/‚v m¯0ªýû±Âúº}Úè‹pÓ‚¾M2£è§ $¾ÄgIßY¢ O3,DI|ïpYl…ÄWj–€ø"ÞqßûcNÒ‰¯*tH_m©ÒÚS!ƒøj¬AõkO°›rzžß¾Àλ†;@Ÿ‰™²5ñ‹LÎþùJ}#‘Ïž\‚‘¯Ë²#/b$ò…–%äë2ò•q‚» ùÊ U"Ÿ-¢üš‰|¾dJæóåÉF%÷Ðd>ãl d¾2ãÉÉ|ÅÎs…xvô¡µúÜH™pè³ï†¶Ä‚¾4ÖôÍñúŒÐXƒÐg¢ÑŒÐgˆ#+Ѓgy” Ï~aþ„>ûf9½úì]¢ }õ ÃuA_ IA_8ž“ûÄo >[â9´H}¶~ A}îÌO2õùZ¬’£½°Úõ™BË!!ì{úob‹¦À·@ä³÷+»Q ŸûDñ* Ÿíˆ]D>›a8‘ùr×&ŸfJX£Ég #™|Úá hñù„l‹Ïfâ$>;Zà'ñÕ\ÖH|¶á—©&ˆ¯žÀ¥@¾:%‘Ï6dI"ß YMÈgþþш|¦e ùlË ³øßE• ¾ºÂÊ–Ägox‰¯(š]_UüÍ$¾Ð˜…|s„9'Ï­5˜|Ê~@Ÿï¤Ià _O;'¾wnãq¨ˆÏìÊÎGô33BjK"¾ª„·iò¹Â4SÄ‚D˜|i]2ù,Û{Y|†a+->Ú¾ øl³[YAŸ% R|nLŽðÙÒõ5ølöÙ“|më _ÀgK­ |f›+=À÷§õÑüú#f…½gÄ‚½í=¥?¦½'FöžU¡iÓÞ3Ô&Ù{FÞ°÷4'•½§ɺ“Àg‚ á Àg¯”XCೇú_K|.ð-}¼A|K–ì">·Šù|JJnñRòÙ3…dñeù"›KZ|.=ïý½Ø®,>»rQ ùÌÀaIãƒÅg2ªT¿G°Bõ{òÞ@>[ÕË×âs‡²,>ß–U‡Ì÷èd€È7ì³áÍËè-nDÇÔº~ˆ~¶rð;”kì;C¿&ú= ú5;-ÿð_då ѯ(»oˆ~Â'‰~=˜Q¢ŸŒWßþ|þÜù­ß_Œa„€ï>¶|ðÝÁKŠ#ÎX­„€û¤ èxžàÈÀO­†¯^§ö¥¿€G'9D@w¨7 ÑnÍo<·„èᘪLAŒù§óß0 Û7ÿ¹¯œ¨Ìùï½$–EðŸoÊW*~ÞÊü¸ûY„«~óß°ÈTåæ¿Q#=ÜýŠi2òôµªF®ùûÕô ¿ßµ¸Òßϗ俟jê¨ø½[\9ï=‹;Æâç9B"?ÛûÉ:hGÂû£øÙ±âWñ³PSâèð'“Nzû™¬ùΈùÀÝ7êþ'ðÏÌшòö›±G“·ŸDzœýl“IKo?þ(áíz´¼ýj8‘þ ²Ê‡þÜ…àcõi¶õçÒûúŒMœÜýÞ_cSî~6&?ôg6û|L¹ûfIf€&IÐßËj¢ÒßxB´&ýÙù%ß°üýVH‰ò÷;!P9ý¹(Äk@£ï Júûõ0ð’à·ZȆ ?Ó'ÊÇßÏ͆>þ~vlÇÓÒß;EkÛFú3Î HfI$–ýù,Žƒ?›öùBåðg3áþÌä†?áoÚW(ô•ÊìiäjøK3ÙÏâWíû™ KWÉ‘øìgu¾‚ß47f‰|•o˜4õ0„#ΊþÌæJ€5¬S>’ßl!çýæe ö3¦çcò9K §AÀŸ=µêL7í åžð7ÒGŒð7#Ü¥èoDqÑߌ ™Â¿áãß @³ÖÐá@ö¦$:üÍ™¢ào>ý‡àg½‘5éð S(ú›ŒóCnMÅk@s1G’àÏ^‘‚ð7mF'‰þfU–$Áßq’Cø›æÕüÑû,…:À߬ç#÷Í•ŠàÏâ™ñ$üM­¹Ï†:ø›ïW&üÙ¸úúûÍöä„?pü” sʼn*áoF5ÁßzŸV”Vü×d=_Qm¨p@úó§â5 ?{*Ùj‚þlàn¹÷ùŠºÌƒàC3=±Iv/¾Òß|·%œ7ˆÓàD.€'ÆÉåñ·âTXøg‘æÆÿì·’§ðoVÅ}þÙSÑ´øç=ìùŠj÷*ü³vÈ ä¿i?Ñmºv§ÐÀ¹‰Üâ¿Ùe=,þ[ïï%ÎÿÍ.Cñߌp¬â?ûÁåÞþó×Geü7§¬›ÅëI­ü7ûEóýŠö‡þæ|ÂPô7ß^¯ýÙˆ%9‘þVYáEú›S:èo=ìÐÏBýõ«ß<Ô,D~sêˆ]ä·Ì÷ôU7ÆýI~s·üìåÊiÖž[ÒsX{š-ä·ŒyYò›c¦m§/§öu÷ùY]ò›»ÈOàgjè= ×híi³*kÐÚÓïÆhî9: ~ÓÌþÙÀÏÞ0OA¤õÈø™¡&Ï~ö©È<›ãù¤üGsÏ.5„æžUŽIaî9ÚI~3JägÂ÷b8¥ˆöw"{·¬.Ñÿ/ÿbùî¡Uò_£ÄÀÀÿïï\—µTç¾îŸˆö»;dÉ }ûß~wÿå*©Ì hQ~ÌêûÓV”\m±ìj+J²-ˆ|>O%ٖʲ­,¹Úz×hW[QrµÅ²«­(ɶþ“â5Û;¶öi3¶”m+û¿ † jH ÿë±¹[‰HS¿«p׵ȩsÝuÿ´]%ê ì÷âU_ãõo¿Ã6:MôéŸZjê…FÛöEKüûn(ª¨«N4cgȽ]í°àÓPTŠ–®ZÑ”{QÜ]bÁ§©¨M]µ¢©ßžljÉÙçj**ESW­¿:v^„­í]­ÍJìeƒqÉú—LÂ~Ž–¨øÇqÉþ¬ÚϸdVïg\²?b—ì/Ì’4ý~NüÛß™×îZ4‚ßÖßùeloþþ6ö»üûvãsì¼fàÇùoÿÝÌãjŸÿößü»mÀŸ2þí¿û÷w6-<Øÿú?¼ß¬mJ÷ü·¿åÿþßWgV{ÿö?þû±÷þßÿÿoÿn;Þõ”ûŸÞj¦¦­oøŸ§V,>vùå‘ÞIôO­e<µæñÔæ? ¥öÖ³j mÞ…Wµömef±_ôùwÆNë!vÚƒxCþÃ"vš}—Õ„\¾Ý\w „IÒ-òÊ/mŒ0“Ôç@ 6îwl:Qt7ãi% Ëjjïcu˜åÀÖ«0èïdºóñïÊ?¾<;Ô[2#ÁB±%§i*% ›f×5åMQާ®{KZÄû÷*o‰’Ú™…ìô:‡T‹Û0½¯R6Sfý>ì]Ù™0ê4.µfcˆÐÈÝ ÉêŠ8DÕ Æ â¢·óÍ«D–âiPm’SÚ ¿Ú#83Lü{û^Ì^‰%ØÆVϲÅÁÍTïj¶HC€Í& Ú7őܹš-£#ïX5Ë#ŠY¿o÷-QÀôÖü²š¥“ŠÀT´zdnØFuÇ%S°6ü€´š©vƒÍ"A½/cGÄ%s<.VgH»4Ñź<‹ÒM¾“Å»ÝD OÜ ªy¾ Yjùôd%Mïì¢eó£¸ÕLµãu9·»/M5o˜-yû Þ’pßl;Õ(;Ìû vë¹LÍë)õ7&Ø,YO˜ûN·'®ñ1ÔuÛPU3Xâaïr?º·¤é8m»-‡rÄô¯Õ\h$Dúùf=}ÁûZ’ý Þåˆ1û=ûZMܘñ€Ç¡V˜·[©îŠÃ}»çˆ¨¦Pw.Ws%¡°7Ý¡¥Z²¢ÛôÕ¬¡¨z.÷ÞKdd®jÕêœÇÿ<%ÕÌ¥0ÇM©<Â5ø{BçzÇ·Œrgñø7oÉVê¦-áÛ@åX÷#ŰC¼nª"3Ã/«b¸ìÏ4‡D‹=P`Dþ6"cZÕj5†¬Ï§Ø+Ñ'n ø~­ÍÎ ð>çöÍ2àðdšÿ¼×Ñáã27Äjuä¹fÇ<ï×êu0¬âqÒ¼fçUݶ™Ç $¬¿ü*l­wL-«³tŠ`3uµ×µå첆­ž¿^NÕ¡€Í ÅêfÁXËÎØÞL­aáû­¾r6µyo 0Üf9ÛäÙª‚aQ0ß/ ¼+Jü«õHÞ˜ç- f³:«Äom‰~–Õ©ba›ªÕ1‚>(qY©ÙqÖŠt –• OVô>S'›Ýco O`(ñ~ªï%ƒ?¦¥ùyÿ­¥Éš¥ù±í­-i*ñ…µ™¯žéøºÚL…Âaƒ™8.{]‚”Í Ö¹!Ül§U1/ðÓøfâ Ü&a¯!TN÷eµ™ oÔ}emn¸…’áKk31<“¥¾iöª,‰¿`Kò³ë§åå_’FÇôcy~–½‰­ˆÜöÕÚ·jC|ñðD?Su*J<ÿ°Ç=wÀýØ·j‹·ÿàâÓffê4_Z=~ºï<ÑÏAwnÕ}im¦DòæñÁRÃç\]Ðô—Î,žêÇ>V‹îŽfá›ÐܪmyÉö•µ™^Èî_Y›iuޝ¬­>\q<Õ}«&Aú¬ï©~ì[5 ÒçxOõcßj­œ¿-Õ«&eúåÉ~–¿®…½Ú¯†tÏã_V›‰é·†_y³ƒ3ÞÈüÓß% ©ï¤àŸªíj&îlÞÕv›®*{ß.UT9¾¬67§³Kóc_ª…‘ò#VËôã_ªùâàÀÆrý,¯óÀB šcYõ:Ì’à¹~ìK­ ¢Y­²}¨Uip<Õϰ*²jÇö¡Zû‰[á»h&“6–ø²ú–дÐsý8 Ê@žëǾU—[ý•›ÙVuˆ¦Ÿ§ûYNÌÌoW-èªupr=Û}¬æ°ãŸÐûP¶¬zoüÄÑ“ýØ×j­ø껃ôeµÙQ$Kº/«NâxÁ¥ðåT”ø²ÚÌôC¢!(ŽÑŠ{-_V›ýDxƒ–ðgU<'¾)fïK[4Oø3uZ`žÁÍDr3<ß}¬ôßw@žïÇ>VÓ–ýèÝóýØÇj–€èŽ[n¡ Þ±…Zi^…n›žðÇî´ôMy$L¯ÂPÏ÷ck]êÞÂÂjø5ÍáÇ>V?¦E» «u¸áÞ kÕRëù~üc]Tþ=߬Œ¹âù~ü[ˆ—eé~ø©N4¬ªöÙM\Ó6¾ÔB/$Ï÷ã«h‡ Ô €&¾Y €ÖýÉ€»NŠ‚@@oC¬f¬½ŒXÍXr$Ðë`[N¬žíkd×VÏüæN¬–u´“ m¡ªfðA@/a³@Àj¡øa Gôã짉€Õì1ˆ€•P’èWŸ@€ÕL ;K|¡Â (X-Ãi» Ðë€ÌI€ž—ë!nœ×„•& °zŠS9$Àº#$°:4‘ 7Îk†‚«€=ߦ2`u´"ñ=8¯™ @¬f9  7Ct¾%šˆ€Õ²lB¡# ×Á$OôG \âmãøH |ëÈGšè%XIÕ|âÆMžÆ /™X½.J€oÉáwE ô»ã»z¾Wbà[ÂÙ X-² V7b Ÿwáw!V³*Á­‰Ì©–øÈ ˆèIÖØ0(ÐFç~¾;Bà[¢„À·„-¬ß³ÝX÷i‚@?¡ùHÊ´î P °Úk\¨ãèU&xèÍ`ƒôs>Þè–ð|u3”±(°šƒãBÉæùêÑ6’èÏà3¿(ÐûGæ{x¾zèï, ô«Ð2)°ž‡S¢@og‚ùÏWŠEÕRõbKMôÜ è ñðXàÀ·`ü¢ÖCûnR _L ô#P04)°E¢äÆÀ·„¶0ÐSñ‘ĪWA›X-ø9ÐïÞoôØ-¯Úö WM¯>tMz;\äÀ÷ª)VÜ<^µƒ\´|x¼ú0cš8Ð{è»'r _TU…Ç«…‹9ÐïÔQ¥òxµÐ¶Oèϰn¬}hÝX=2ê ¯ìN„õÔÀÉÅÓÕÂÐãÂ@/Áë"¾W1€0°Z0$<&9ÐKpŒCô{=7z è è ßøîS«Y©á¨è œÀ@?,›ýFdGp ®b VW;PÇ<@|ëèý‘«ÄMR–×ÓÌTè÷B‚~/À@ £$èá4ˆ$èaØ’«y3à—! úëê?_]­aÜ èï³@е|CÒj½òû_§,8|!½YÐb)}YÐüÍÈ~`Á%«º€Á¥µ`p)WÀà’ÛyÀàê¡—<§ƒ­@ÑàjâNÑ cÄ ƒkF‚rÂàÿÁÝ»$k#I{[9Ci’† q[G¯A¦Áß2ûÚ¿‰îžÌ¬®*µI22O| ò% <ð¸,m ®¨+ŒT%ƒ;dCÁ`„g î'ë#ƒOÔ9zõ'£xð„–´•¿*Ôrʪ3ªÏrʪZî†$Ø”ß7%A…‡$ø¨X{H‚=ŠZIìJø–’ <4C|t®m5H IPåHBì"š”Gˆ„”cE)I0„œ”O÷@´;«È,1µ§—’àÉDå”OÄéHÜM¥¨Î9§1iùJš÷˜´l‰®xf)‚3jÏP´¤¥t'î>×XaÚJK1®XaÎöŽHµ,I°¯p4åœU%ž‚ B&½®®$NæÌ9Еh!9Ђ-q^ÉEBJÐàŠ  .–O œŠV50Rj… ؆:& úd QŽ4è+(ï'hpë \”dƒ'ƒÇ*ì€Ú@ƒ6;±Ò -$ÀM¢Á£|oAƒ»sŸK4h•Ð8`ÒàyºÎM´ öÜ‚ Ÿ âxÐàQrFá ­×p»„ƒgèžGä$ô_ïý¥°H´•áøâà/¡Ð8h 5^Dá ÍrøÚ’˜ŠmMŠ2hð(—hðDé áà 1J8h>d.á ýzø< mA÷QýÉÁe -é$ôSá ×üOW"@á ÝÒúÁÁSõ ž¢¸\á  †pÐ~¾‡ô糫½{ûƒƒ'BŸÉƒv¦ñáÁþÅâÁ3U{K<@=á Ý5Zˆƒ«I'Îó‰ƒôÄAÅC$6úQ$ÚBB¡pp° g´JgH|(Ü®ÀÁ.I-pÐ>Þ∃ ñbIƒ¶¢Æ‘G4»Vá—h0ˆ'hÐÂÛ•¢ÁÅmIƒƒ©‡ÖeOì+à8عÖL´s+…ƒ‹i2'ã ‡¶# ¢Áƒ}þâÁ£÷*x0ăSêlðàXêW<ø;uEpûµÈìΡb¿Uå š™Nä j{Yh#WPûb8‚¿ÈØ”ðÇÁ~ecýšBà„~¶|«ôüÔV¥ŠÁû5%ƒ ö‹šJb¿`ö`¿ª Ed?ûÅ) ’ýN¸.ûU•u ö«ô¸Ñ¯K _@úÙš ¢c _UæÜ@¿¦‚ ~û ýTÙ7ÑOäèW%ƒ ýìÊÛG tŒû Ÿ]¥ANPE~J#ä§ Ù ?kBOäžÒA~‘Û9È/J ùõâD~]%8ƒüºò+ùuåËòëòOOòÓÞN_Wî´ ¿<—È/ªùuíùuÅ`ŠüzxrŠü"Ï¥È/Fä׉Tä×U3)ȯó ðëÊOà×UË,À¯ëëàÙEƒübW#ÈÏö§@l"¿GþYI~¡Ø‰ü¦ÆKòë¬ùšä×·üJI~o7ë#Z¸É‰üÎB sº'üŪ5àïazß„¿‡mÒßÓ5š‹þæG 4 t  ¿q S’&üüõÐ]E³Ç&ü© EÀ_ï æî áÏîôíꪃü®þ–|'!†üõ"·QÁ_çœðg Ûa ø‚HÁ_gàGÂ_m‚?nIøëT'þ´utÁß#¨½àoàì'çWJk„¿ÎïoÒ_g¶ã ¿Îí㤿ÎÜýñs–ô÷Tµýõ<Èùõaº“‹þ ŸÒ ¿§ðMKúªýõ-¿QÑ__¿éÏŠºÂ"ú3'_0™èÏÞêŸüÅAMð§ a½QQ -~SÉ~]ït²Ÿž“Ôƒ;Å~ëž%þÅ;øm’ÿHqñßCM1Ð~³Ÿ»\TõáL´¨øÛ+Ô-¸¡€ª£øïa=°@À‡QÁ€æJÒ.ü§Ò¬¥_¨ûJýÒ±ô¿y°3Z sG¥ȘÑà–'RÐ`¸ê *ÁzÀà‘Î4x”öÁf' fúG ´{*Z›EmJà_ Mªé7Úö4f|ñ Ë!`=)[ùHB ”ÃPààVòŽÀA °9 #O„pÐ%hK×AøãŒUU ]8hnŠŽÄÁSµŸ/ô‰äç¢AÏl÷Ñý늎Aƒö!g4ãÖŒ¥¨MÒ sñi»rF9eÎX#²ê3¬NDxä…@8ºòB+2pdÉNX#Ê1 ßE†2&GÔŽH£% Ê™@˜m„#» gTÖÎE'˜94µ]YT6ƒ@8Od.á„õ¾âx‰- ÛÇ5ôÄJá”+páT†¦Œ ”‹na \ŒÇ ´¢khl÷&.eI "\ÚÐ "ÜÚ‚ "\Ò¦E„K‘uA„‹~mA„‹î,I„[õ¿‚·²îçèãÛ_50ʉ.}, ·^´@­Bà„[¹( —|U w wQ"áRE×@Â-¯Š@ÂÍx á^:•pëIn¥ (\GBš p«bj@áVÈe@a¶îöË;ô`õ~CᎰBAánnH'JÌH(\K~ž‚Ââ¡pëá (ܪÞPxŠ\?…o[|¦…[ÞÈ…‘WP¸‹\4…[;-…1 n9ÛÆÝ *Ü R*Üí7nÅ2ÆSThÉÜ©þ‘ 7'–¤B»PÀ›¨pJn‚ÂýHÙnRu@¡Ý㯸«Âû…›îK …+ô?A¡ru_Š ‹¸%î.°î˜H(T~€„Â%õ1 p3“æ% 2VR¡ÅgüCí%& —£€Bû.â AáZrN•"X g¤"Èêk…æEñ…·[Z…¶Ð ]§ ×”ÞŠ \+ mQ,.ºÞ®$.®t -Öùç?¿rࢿ('ØÅ‰1‰péé "4©mD„‹™™“#"R¬rÙ =üA„61~õ@OG|á Sáb¯K|äR* ”?]á’scá”æ@h'GÏ;'XP@8™øí’™>p"ídòà|ä³) ´a „s)ŽP@8¹ôN5ÐI„¬“œ@8t„SNÍ„QɃ³(¨Q<8Xj)yÐêŸä48é]—4OMààØB=áàè²£fÇPh!qpÐÿ pÐ’e}A ‡A’àà.ä•{ÍC ?9~<+è¨?™UH–;‡Úß—­Ôæß˽öç3¤%ó’ý>ÇÿqY2/Y·UÔúô–«/Ú®¾Â’}yŠéñ¹ò°d_²e_i¹ú²Õgÿô–«/Ú®¾Âòß{­[J »Çÿ^îµç¯r¯Õñëç^{­ãïÚ"©Q‹¤FõX<!~™ë÷Cl§áÁ§‘ºŠÄjêéJ¬¦Ž¢ û¹šD7‘V-ú¹ÒªEGÑJ=]¢«H«]]iÕ¢«h¥®®FÑU¤U‹®®´jÑU´RWÿFîµ^ͳ¹ÿÿ0÷Ú?ó•ü«oÑŸ¿‰ÿñ¾kw«¿z€ÿÜ׿œÃÌK ¾“Ùÿƒ9ÌÞ×ø>ò¦Ùúã%€ý¿ì4f"³ö_'2ëV•1ì»Å3>Oè H÷j·âÏK阨æF¸ïC?SO0™·ìA›í"ÇH¸Ý½*ïBl¹³@·Äv¥!¶Ü§ôn†ž¸qßÉx/Ò}Ïü`i¾=áqá8»3ò=ØItêVÌ>9ô¦éVŽg=ˆ¤88Êö‰®x‡n……}–äd¿6a¹~W˜œ¹6ÝYzß;°´ÝŠª` vÉr¸wÊYý…l-ï¡/­ëq MêBø îŽY L×·þ D{³*‡ίå0Òwè<ÏBì`×ݵrƒn*¾1ߟY±ýªÔ¯Å7ˆ<°ÀWÈýYžºÜc`ŒÇ Õ# Ó Gç@7çÀ»ÛÒ_ø°ª+ Žûî û.Ål¿úŒÜ½hE o\v«á]y€¡Œî;ÛÕÖÑæñ e—庵_ú— ÉðÍ!w}ð¤n)ç¡ÒY£{õ(¨,ôaìéÅ ËærS÷| ¬ v7ý"§m6¬˜Îº%³/\áã͘V  å;qÝrhû‚sÓ;¬[:v;æÐÁ£Oˆ+Ý2|/Z<™½§ûê8µ =M—ï¾vËumdÌ‚_nÂeµû8b4Ë3ètÛhèg».÷µFã]Öu{O_ËÃwÇ[ ™Ò˜C¨/.ò‰wgU¯ƒáÛ4.«¼oûU8çõÕ=áùÛ3³&¾wåë–ƒ™ m™Ä¨tû~XÛmh8Æ=;ª±øß.ö“XJšbw#Ý>fÏó…Yt‰u°Xû¡ÛûÛ­j vCvE,|Q,¤È=æ!-.ªxb/\½Ÿu!µÞ\{=ÑScèS·ÀOôÔôÍð0voÃ|(Ý$OôÔY%¤û»g÷ipË«›„²gä–M7ﮎû ñ؆ ‡áìÝw=ӓܺi( ù¶Ð/¥eKåš³MEÆ«#Úƒ4O“…¦½ôÐ`æ,ßÀ÷ÒCÇÚ¨¢”—z,x¨Ü×ב1DÚJÙ–†g ›8—m1mdÿÂc˜nÉc*÷¼öÐô&,#ÑÍËÔrÇÔÂЯ=4~)ªž‚@YOæ¿‹×òLZß#/=äIÙ´#í<%›u½ô§d[ÜÅ~,ž§dÛ| ½öМÈýUÐÏêHÉvè‚æµ‡ì5µ½§…ž·O§~rŸ`½üÐcmüþ¼ú'e; „òêCiÆ|žöêCÛÛЇʪ!ÑSgFQ¯?do©Õ¬hcŽ*f Šèå‡<ÑS¥føX)ËŠ¼^>kñºíiu4YÅvÁÇÚK!'kzé!U7U¼ô¿ª‡j³—²WÕ«#y?–nÌ_ÕÁ‚¯^|È_ÕÅ¢@%óWõ}Eü!ñâCžåI¡K æiž0ZK5˜6«Á‚ˆOæ¾zÜMžzú|Šüf8õzä©2„Íëùy¸ùXÉIOòôd¬]þž>V6 IžX¢ÈËM¦ÖB“zãI‹¯>䘅g¾#H÷d~3­ô< ìûzé¡Í,dÝ×u|]¸a™9ž“ß>}Uäx²-ú ‹+¨ž3Ë—ÕïóO[σ²÷´)ññZ®Ò?H^|ÈS:QöÚC‡iµ|ŸÒk=H(†-+=´®Ó¿øVzÙTgÜ‹-&Íèf`>5ḡŸ‰ù´mÝgb>µMÎá,̧¦.ã…·îö¢v,üÌr<¬´Û#‡n¦S+—Ðjù‹úpöÚC»#¿+·„ŒlÝXõ!O7ë¼—0lw´{!Qô`>íªIõŒáó©-ÆñnXñ¡Á&´àˆÎ—ÝJy:¶s4Ü…9Õ~K|ž¬ôPŸ¸{>1{é¡]ñLàÏ‚9ÕVý‹Ì©v.ô3+æT/6æÏ„ƒ™ Æïë•6Æã‡×òwõpûÐëÙ»Ê-k³ Ì©öààjõ‡öádƒW DKœjaJ]1šÍ)u³h™×ZHzÈn¦TËèÚ+¶øh¡«®aïªíûÝŠ‘=„Ðÿ\î²ûæú}¸ا…XbßÀí¹°oâM»°™Éûä)øÁ>ž+°O •Ä>ú+]ØÇÇ'±O;Íö1–æÂ>¦;Jì›ÌÏØ7ùî%ö™ýá>S'1>qßb=xrŸôÙä>¥ï î[R¾’û,g%¨‰àg©µ°Öø™{°Iìg´ø|ØÏ,8Hègê _c _á4”èW9U%ú)oV¢_}¦"¿Êïf’_ÅûàWY-Á¯²Ph€_Õà×Ç“ì×øô'ûYð#ÙÏ +U±_äÑ öó(}Ò àÏÒ]õüy*+ôCø3_&¬;»#>-ØÏÖê TIöÛÊìgâ8©ìçëy´ûyÊ) Ùoz0ˆýlÅ¿@`¿×BWQ±ò@Áöóñ~³ŸøÄ¹Á~Nà Øq"8 ì‡ÄKþp‘ý2L[ìçnSd6°Ÿ'ÒŠý¬M ‚ýüìøùÈ~~.\)ÙÏcPðþ€5ɀ™€ è±xúÉ€ˆ ª=câì`@9ÁÌDDà,€ÀŒ'zÏ$]@ ïÕÝÒAY9A ï&a¢â`"ÀÄ1¤@ØÀ‰Xs3 Ç…ÌÈ€~jð1FàD0`‚ˆÝ‹œmÀ€ÈÞ†Âû'0¶Å€ðƒŠÝ]‹M2 ï¢ÅœÑ$„1Nå ˜¡!Úô1 "Roô˜ü&d@Ä=  ÐÛ,R!¦Ö£b½bÀ T¦ƒ±g¬³¼€á/èèENfÔ…0ÐûY`R` F 00c>ˆ0  0á8¹c ûQã¹!f†0â-p âf  òêÜXÿ% Âe»ÿ$ z ~M’ w\ot×Òq“ ‡Œ Ìv‘ œMa9ÜYºL_ÀL«ª]+ôýÙ^kØXµïŽŸš ˆáá € Ÿ»<AÞ¹‚nÁ Côíâ Pº¿BG€ ·Ýeµ“û ÞÖ1þsíª~’± ¬úE‚ð~Ø›!º¥Üè'Æo@ ÌÄ ¤@w°Å. )w:„׈ IP zEP w‹×‡èÏ vH~£ð’3ï€(Ð-¸JR`&Ëb<`³Î‰UŠ¢@XÐãy ª‘—ÊłٱXpaU—,·B(xCÌßW(˜¿”Pðê—(h BÁ«g¢ ?o· ˆ~@IDÁ|J…‚y“…‚þ,؈‚~.‚_‰×•ŒFôë‚(˜Ã ú Œ“½ ÎM\»êÜ‹â{#\r¼ÚÓ"̱óFó† sxBAïùÖ‚~ÔÏE‚×A$Á|ÔE‚~Y?æûAôƒ9 ‚Ù A0æAÁü)‚öäãmæ5 óS&Ì/…@Ðûù¹80¿×âÀüaÄy‹Åù‹¯ë$ÆèC†’Œ›W.Ô= ŒïV`àR¨@p ¿R8ÑØñ²²ß9âeÅ:K ¨g"8ð:ÕÖÔZ¥)’ã#eøõÁ Œ38Ч´é9³B? æ€Å×¹G̬åÖñ{'Æ#˜7Fxõz4³êw¦E˜G‰ã9 ÌŸ[˜gÆï- ÌkÆw"00ÐÀÀ¼Pa`v¼c^4h^^NÌ«0ˆs0¢Àx‚óqææ+ ŒµJ``ÞQa`>6ÂÀ˜ƒóÂ…ñA Œ]˜ ó&æÓ' Œ§š˜÷kZý@`þÜ‚À|Sy#y‘‚ÀX©^GíœVq0)A <Óc¾ ÌG@裮µœT'hŒè XžœU±¡@tÃù¹80Öà@û³PûËYuÜj Îs«÷èÎ5«þ\è+SÉI_ja`¬T5qÆû$¼Ž!æÇG˜½ÌœRE…`@/Û‚ƒÝ”ÜO¼¨xŸÈ€ÞÜHtiéçbÀ¨ è‹ÉÆ÷_d-Kîó=¡÷1×äÅ}rf îS¥šä¾Eñ8¹o±Yrßb”¿PÏü~y}®ó›úk$õ)à1©O1VI}K[âéõÉ$}·×çø%ÿ±bPÊò8Kùþ/¤¾l êK‹¨o1YPŸÅiîü·Ë” (¿Ï¨»tý´ºTûèúYY>+õ¿Ê"©ÿ]áì¡ÿÁY蛫§Ðÿš\åBlô¤H°É=L `ÛŽÀÆí²PCæSìô¬I°3Þ<À΢˜©Úî0¥>L~)€,Mš à#Í-À÷hª„RG“F)ða ¡”³Ÿ\`‘ ¦$ÀÌ$ p0KYJ€[^š!²ˆcH€³ C<qH€×…ƒ$æK pÒ5!%ÀÉÍ”Uk/%À)í8$À¹äp) pžp¥h•_€g!¾4)2íqJ€SrcH€ƒ6”Í[ÝH\¬ ­qnI€‹ù;).&IH Pñ)®£‹”¸ä÷ž < C´¤?ö™'4žãPí£ôÁ>Ó0©ûLdýbŸažcqŸéã£ÚÇíêB,<"~>dœ àgÿÁÇXàç ï ~›´Fê³.>Ðg Zô™ÆŠwCÐg£]Ä@@Ÿ—©…Ðg+9BŸI·íC}>jZ@}~.({¤>OÒ!“ú®£H}¦ÃJõy|9°ŠÔç¹ïoê3—tJ{¤>³œËÔiì³3a³XØga(ìólèýÏúè¡%öíÃü•Á}–Ûëâ¾(×Ügý¬Û ¥u>ÜgVÞ?³Ð{“àgÑ÷ð‡øíÓ¥îü¶<ülÈð‡$øù™0‚Ÿ's¡âW †Oú„brõHh@ð³ËFä>3@¬÷mJt„>¯ˆ%Mâ_)r±$ôY'ç}Qé<Å¿"d ñ¯piÚ_a†¿ÔþЏFЗ÷RÐg±äTjrêÛáÓ&í¯H íO%’Rû+Ak5£*!þ-ùCü+tOñ¯tªm!þ•`NRŸ Úmˆ…yRRü+å·øWšY%þ)ûgŠò~Hõ/~©q“Cý+”-Bý+ÒJCý³yM¤þ¹‡úWŠN¥þ•€:©E[¨ªõ”ê_é|Cý+ýëz=;!ÿÔWM°h7 ÀÂ4€©–!d“XX!ÀÂt>©j¡Æ³ `‘ ° ¨<ÀÂ|«)úȤø^5> !–G<&P™eS,,7`aR™Ë#^ìéY3?ìçwøçB¿¼êÐÿìaÃAÒÿJ'™Jþ³›‡3Qþ+Ü®NùOuáCþ{¯Sý+ˆCþÃ2òB¿|Ì…~[¥ÿ…de‰õ—u Dº´ö¯¨õRÿ´¦MõïO¸BQà¡<›xšd;àiò¼šÿx h+-A0¼õÄæ‰ÁC˜klràžò™F…Aq -¦è)J´%CK7ÐS%ûˆÝ‡#Chp )üëÃî;ðQÿ"ƒzp ©ütÅ$Z èâ@K¶òÜèW¤>p`/ŠÓzpW½Õ¿n+™q«ïÏAŒàÀ^l6νl>IÄÀnëq9‚¾sÔøŠ½LÝbàk9Â7``·¼1ãÆÀnYbÚ­þ½sÝø¾ú£ {í\Å’»­Y>èQ"hôÐ¢Û 4]»Å€ï‰Â]/¯o1Ä øžº‡ÅCÌ•ŸtK½ðŠsR`ZÓ*°†"¢@‹P¢«(C-¼§Qé+Œ-Z">†6s¨¿µ¿n¹pÎÍ€ïÙ)ó!þ¯Î›þ®+Ò_·L9í¦?„š·êçÁ2ûüg#Á»Áè¿1Šþ³ p £ÿZWÈ¥ÂÿìãF†\áU”-h·‰°ÊÀª¤\Ø"žQ€­0ÇlDZÝòçVýz{_×›þz‹] ¶~þøÄÿYhcÿ×”81âÿ<ÏÎÄø¿V*»aøŸÝÍu‹~>¼u‡ÿYÆ Æ 2ü¯±®¯¢ÿl+d¨Â£¸iÚB‹}¼ ÷Sö†OôŸ…úôOôŸEí  ƒÿ,*Š0Èà?[—·[ðÃøqfÿYbI‚£ÿ,tŠÎªŒþ³$Hóvüôh¸Ù(ú¯G^ˆþ³Ùº¢ÿÚ| ˆè?»ø^2ø¯iÏ/¢ÿZç‰è?›‰±BRô_{ÓÑvƒûM~ìEÌCðŸ%Ë$‡2øÏšÌü|ÀŒìcô_SÁÞˆþkÊ~Ñm±šlFÿÙ&öíùÙ=ÏÔåùéOù¸=?}€ó?ÊiPôß ;£ÿ1FôŸ]Ò¸=?ýŸ'¢ÿì]ŸŸè?K znÅ、.}ѶJ¡TÇè?ùN Ñï¯R‰è¿Á܇ŸÀu{~ú˜ š |_j h?Ã-ùuûnw«¿zŠÿÜ׿œšÌÒa®wJûËÔdïÝøßóÿ·Hö_å'{ÿŸÿ«¥¡9û\ùÆ®þ3•]Æÿñ·OÈ?NZ6úšpACñ=ÿ V÷uÂè§Âíaòk9pAC]†×òØö“¢“c†Ý;wAœ‰ßµP… š­,Ç¢Û<ÝççO¸ © ìx,ÒŠqèN… àô®y->hʈ3[ëÿ <Z{±‹L7ó±üñ8ô…Áì,œ,_8“o´wñÖc+Ö%—1*'¶C'‰×²QKâÆh“[±Œ >‡¸+JÇ[1Þhëé×BÍüµlnÅÐÂc@6¬øÊ³=Ðí*؈mâ^‹Ç¦zár܈±åM/ ´¯•Ák᤺~“¼(;×ÑYv·“êbÖÎiU~·pªÁIu±ãœ“ªÖÓ‹ .\pÐæ¬:YÌjzQ ÿ RÝ™––¾2Þ(/ Ä\8¸òU9­š·'ÚTN«¾Ïá–†iÕÝUý±ð¢@\H=°<œW'ËN/ ´q.4ÕÔLÎòËZðÐ…?-†³8­Ê{vzQ K…ec^µM›ƒÊ‡xI k`eEX0¯úèÜP9­.j¿Ó*ùXE¼§Wš°à#¿!ú™ñ6øfÂ7Ô|©'o–¯1„Íû¸(rýŸI`öAÀ÷Õÿ…€Xˆ$2ƒÙ…€ &O|蟑øp܉€Ô µ*K¬øp&fìIT1´dÀ1~1 íûãTbÀAº`Àˆ*œ¶Í'2@$NTÜH|Ÿ•P9Ï’3ú þC€/mþ\øg~@ç!þY~lA4ö¬Ä=`¸øTp%pÉ‘0°ð{œX„ÀBç¢Àª¶ €…¹I+o\ð_¡@šü—ñ_k"Kñ_ÿU=gÁ5€UüטF3°3Ò*° ¡’°÷ߨ…A€Š¥H´%3Ž">”2F‚vm©JkM|FàçªÑ á%F&†~%ZÚ’õØÀAO–ÀÁÂØ €ƒÅyQuí&Àwìør$² Y X8™ ' pRÐ œt®H´{‚ƒ„€“Ž?É€Jž 8QU1P!‰€‹©jƒ‹}ÖAÇbÀÅp£dÀ ú`ÀEi:puQ!ÐøïQ0àÚâD0 Bí@]¥s>þ¹ÐN‹E¹Ð†Ey ÒÅúYÀe$@_âÝH€¶µ°Ð3 УÐ3 ÐÚ gªMê´ßs`0ànbK2 -ƒ*ÎE4 b@[Ýá*Ž+ÚòŽm@៊ ÀU¹ÐVï`B" €Ýˆ€Þ,DÀ}˜ó)ÐW°è˜è.G´Íb-ÐÚø¾ÕÅ€ø®n¬Ðı7ügc!’ÿ ܰÄÿ倸ÏVû`'òŸ„ÅWò“Šÿ¬IùÅÜÝ þó°'ùÏw9Àmä¿„†à¿REiä?•‰ÿo]ø×ùœþÉûý¿ò'üc¤Þźˆ@æ] ÜÊhýtôCôM œ]ÞÑçŠi™÷%ðB,2`„7škòd@ªàb+ÐGš ÜâQ" 402 GÉüb@=èÉ€,– ˆÕÕÍ€‡^ßêaºð&u€¹ù*ŒÐ… @ßXõ!Œ @‰ÀQvVYC40"^‚­M‡Ë?»,!ЖiœZ.zW&ª$i2à–Æ ¸hN ¨j É€‡9G“í‹ðpË%ð¬_ ¸µ# hqh"* §%b²Š¡@@Ky¼>2 ùÞгúÒ²™çWON¨€]_ ! ý Ôl! %ú=ÐúÁ…€–/!v¦ì ´s©ö.ÁQ* 9惎 ýCä£ Ø©§ Ø;•#AàÁ1$À*‘(4ÀQ u‚%Yh€öICi€z} =Ÿ­ž ú!Ú=Äöt¨€JÏ›*àS¤ÎI|ï/XN*`£û@Ê€æÛ)Ž2 j.¥ hõ«o`@;Q¡èGмaÑ‹dÀÆ€”mA‡6’íãKÚÝ0.B =“T!=g€{rþ\x<´ãÆÀG¤( ìLÁžعžH DãMª-øh?&(PÁ®Iö½¹(ðï²—]äç>/ô“Ó`¢ßħïB?†;]èG ½Ð›<‰~[˨@?E‹^è—¡‹üª<5ƒüð©KñÏ& ¥À‹› üºN$ð‹c~; SâßÑÊ5Ô¿Ó$Ë…hç…h#˜¦è”¦ô¿w}Šeßí \IP†_ ‹„ð—^¢‚¿:ÃBø«G#ü5Éœ‚¿Æ¨ô„¿Îùü×ÂÁSü×9…'ÿõ*"ÿ‰Ð-”{•ïû× ô¡«G`g)“À‡iLûú € ŠLð‘—`ˆ€ý»R|Îo/P‹Výà˜ò²J±éвÃ!N©·!ΡQœRŒBœ<>%NFΦ8J³!NúP‡8™".@ónÈIœGZ™ÀňýTWèiRùC”çN*€«K7”8µc‘ àüƒz@ c!.y}K ¿Ö¥Á…¸6•»7gÈ7S8¥¸YiåR½¼CÜú¤8å«)p³úo*€òÊIPrT*€»è()€;œR¥n‰Ù¡²®@J€€ñŸí¶Ý$n;·&CÜZa¤È3_" Ô›µ"àú…€¹Ý"`ìå‡x(¬_Ž , •"à‘;\ˆ€çáì"àAµÔC}H P®YÒ™ó*%À©B”ûkª€]d)0 ðùE€¹iœ* W )j™"àf5ßב€'pK³!Pu·.!°$%†ªBàfFšCÜ !°ÊçTB`8Ú…®«dÀ¨çu Z^§HÿñK”Ï®Ð5^XBÔ~:‚²ˆZ0 ‹{1 çЃ… èúæ‡#¯]0`<\B@—fpò·†ž ›€’Bà” ) ΗD@×¾ ×st)òÁIPÒBê€xR,”¤„€®óþüç­2YÄ¥êE¼]A-ÒYïÒ™-4°0¸ùÒ—€J(ñ ÀRD‰’ƒ°D€oo´Å†›l •K§ê'PU Í– ; r‘%*«X`iº&`á¶i`xÓ†Ûv `ÆÔ$Ú1,¡ÊCXV¨üsA€*‘—øžOl Ä¥$À¢Í @¼ñE»h¥ÊUTø }àŸ¡ÿìž}ñ/~…À¿òüÆ?æ"»DÀ’ŸD@º&}EÀŸÿ¼5Àç«ÒY1EÀÍb³éz´³n GójŠ€ú‚†¨D†tM‹Ü@ÃÝ"Ü@ý Ó ôPyý2˜](èKú ÒYÿ£ÂC/Q 7>í›Ë¥Î?©€ p(Èì® .®.ƒ·m†€…0¸û‚õ’"àüz„Þ‡Í)š" âClUì*àÂg;UÀÎ̉©>Z *!E²à`’ŸdÁõ(O,¸ÃïT,xX4XÐÖ¸XÔ‹SL Ú&ÍøÚ– #î §E’_ÍéjYÐ~ð?¨§ Diú,^b ë? F¸M° ›~.T¸F 8>I…»i)–%6”¨P‹¸È}ܱ¬EÊIÐU³;¨ôR |›ÐcTR`¥÷PJáBZ %’Ô+—±©Ö.QZ`:·´ÀúH˜”X%S¥Èý¾K œŠõ“˜iuQw -ÐÎÎANX¶ÍNZ`Ñ>BjG®Òå\Zà{*¸OK ¬Ú!-°ž_î ¦óµ¯hm ÇI ¬Kâ[húÀ„ã 1°nJ ôÔs Ú…¥V¦ML-åžS Œ )К|XÐ%lœ›Z ôÕ«ÜÁ b !P•ZS4^@{ U¡K©*à)´@)¶©ª–ljV·öXYV µ@Õ¶½´À£h?iú™R |Ïÿ»Ð+sb^Z "#C Œ+ 1°Qí1Ð`B“XDFŠv¦ ƃu‰qî‹Rb`+Š$”ØX3(ÅÀ&»ÖS lÒÉR ¬"?‰éwR ´ñÀ Sb`“«aˆ­ˆ)¥6y8Ilrp =0n©ôÀÆâ.©Æoz`c%ØÔ㞆O\…áEPàá"/ôÀ*/®Ð[ùíÚÄŸz`+t%•?DÈvÛ.LƒÄÀVuj‰yj‰ñãA Œûb`“›¦´@}×R Œ/´ÀVøš…ØXt)Å@K`ø!Á¼Á!Vù ‡¨P‹+«€¤Xå¤b`Õò VVcK5°Ê/að*N0(Ÿé€Áʪ@ ƒU¿_À – n9| ®?Á óP_0Èt©©…› .‰}AƒLÌž4(7Öt ]ÂW9…ã|ôÀ¤žð =Ò\åzŸ@ØÄd‚õ‚ˆž8È”¤ ÷ݹ€J ,rA5Ð"?aé–j V’TËÚI |¸e†S( ¥‘ËÁƒïóý «„Ûk•ð(9ÐÖˆ´~:(9°1 ì•ÙlwÔŸä9Û’wÎ+[ w~²¿=*©É¿—ÖlÙªgß'HK¦ü’-³¥%S~íúô5ذd_²e_i¹úòÀ÷ÏuÓpõÓÕ‘ ÿÝiÈLfívOî4d¿6ý£Ôb›Ö1£ÁŸþ·zVÂLYöZÛ?qÒÍH?ôçGf ãÃýÉ õëá³{g‹úOõ¹ÆÔÑ•kŒýDvsµˆ^"ÏXtsåS?ÑH]m¢§È2=]YÆÔS4ROW›è)rŒEOWŽ1õÔÓ¿‘‡ÌòAï÷ëýòýÊ6þ2IYÿçr”)ùØï”vw²¿Mfö7ÉÇþ‰¯ÙüéËô¯ÿøËÇõ÷í/×?õô/'³ijÏóÿbâ±÷ þ«Äc¯ù=Òr˯ϧãÔøæÿmâ±5ª{zlx;ßOÝN–½Sˆùòàµx$¹‡)LL5Ï@¡ÀÁXÆ÷6_6úgm¦/®‘ClòüË"—±eÅÊb 'ßí†y޳â¼Ñ¯«@çí«ƒ5˃ ÔÅ kÖ† TÓ¤,î…Ñ¢dó;ªÅz˜Üýy‡õ¤/×|Õùíµp³Bín+x/Îë|¡(Î mÕ·B;Žz;<³•¹áxšTßEÇ ÅPÜâ/Ök9.÷Ô'X«NnŸV. V{¼$DaëZ½r÷´ü^ûÁ‚±PwZ–I`0>¿6k,¾1õŲØý‡ÝZ66O+rÖB&.ï§â\ˆªwGš+@¦[ú9ZŸ’¦/¯%èN0:»Ž4ƒÀ—»£Œï,«Ì7X|)÷žÜ}bXey©<÷¤áŠvYðöÁ¦ñÁyÆF£Î%î2?ûÚF,ó¸p ¡?@Ôµ‘eØ;^8Ê6‹ÜÙfj¼g@B°­W¿JÖ…ñr_Ü/[¨ºÚ§4õËwb¼ ãØ–y‘†e—¹ÐyÔŸÒ¾/sŸöÚ€m‹58°­³‡G™XfCmÀÉ4|Ë‚\WZêײàKÃtâïoç;ç~žëcò;ÎðΡ+Mù¼K÷EWš‰%ö¶º›N:Í ­¡ÜØ¢3Úk9t¥!ÿîÒÅyúYïb;FŒ èg4ºÒP¢~-‡®4Í÷µß‡Í]^áb‚Ž×m~1–ú}›*µyª}¯åøÛjžm ûQþ¬¿¯Êƒ°¿Æk¨/S,FºûȶÚwòš÷ešt¥¡»Òûè?t¥¡¦¾ëSÕÆQçµ¼¯†Áhƒ² -êÀ½¯WgØ«ñ½¯`eÜåײñ¾VÚÛÕvŒ\ì —ù¶*Ðæé3´­|C¥ÞÜiÙ”üXùc[I„¢RM°´Ž÷õÐÿâ}Ýɺ>ìOY›°XÕPàÆÃufè²°ÌѸ[^é‡!ÍÝD<*Û+ýú^†ð…Ëæ–LÇ›·­ÒÏ ºx°½Ò·!¼c+ôóh;µ;2¾é»­ÒOïØÙñoööJ?‡pë'÷J?ÜáÐóp ;'8ùÄÜj.³0¬öÙWߘZOcrŽmÅ~Ü@7Ëíµ~pá†E¯Þ&:—ú¡¿±OTÛJýxÁ±FÞ^ê‡<Tç! 6RgøD7¤:ÛgÀ#!ªó ŒŽTg¼&R]DÍÕíÅÝРºÈZXçN€8bg²ër?@Xg_Zˆuž˜îXg=c7BXÁ5â:ÏíMŠÃ¼ºU¼L\g½àžŠëì›|ØÙ}Ç ,°³6x…vlÖعó#ð‹`·UY+ÀN颂ëìx¹Î:Æ-×ÙUáá×Ef¿à:ÈA?;Ùûì<>Gì"Á€us€z;Ûä ûì|Ãg™u³Jc_h‹dçy±üDv6šN çÖ­GYdçAà8’'«’ì<úýì"yV Ç˜Ah‡ŒuÁu‘µ+ÀÎ3êã‚GÒõváš-°s÷h’gW…Ø™[*î°Àγÿ™`9¦’ì*}šDv^ßÞON²óˆ,`WÔ¶Ç¿“ìTù\d·] 혠-È®0ûÈÎΉa‰ìÊQ ]^É.¨Hv±%²‹ B‚ìä¨dW!Ñ® („È.÷ûDvr8 ²S9‚ »Ø_#Ù)D…`§‚vx$EuªêTW67Du•Õa‚êb¿LT§týAuÌT§h ºÊ%qP<&AužÔ xEª+taÕåC&ª+M]‚êÀŽ–»° »NžM´Ó¼ÐîçÃuS\—)®‹[“\Çl¾Éu…{[ v6 ýÜ\g«g—¸® ¬Æv1ü »ÂBŸAv…A°Iv…%N“ìâ‚ìâW ²+Á˜";ûò ‘] 'È®<Â$‘]\Sè:À®üƒë⪃ëâv×V‘M®+"ØàºxƒëâÜĺøqëâaÖ•®NÄuì$±®0Š'±N?vbÝÛÍùÊuEK`]éç„u…ñK‰u¥ÿ–ë ?ëNñŸ×m„×” N¬³É a]Ñ~¿°®ÐE8±®PƬ‹Öq&©.NTǯwB]aÔ¤ºB¯á¤ºRد ®01`B])ÂPQ]¡_{R]aa­¤ºR¨Õ•"UMTWøAª³'L‰ º˜–íöëƒÙ;r§fÛ!ÍÑÓ2x€ÇäƒÙ?J]ås+už~ (LùÖ…&'ÖËSL˜üÂÂsTé`òÀKª—<0ç0<0ߣ-òÀd ®ôÀ´D§_ÌðD Ì¡Ÿ7<0‡|ÃóaùtÁ,£ž.˜*I˜.˜ÜqMÌG{Oá‚©¦pÁ ÁðÁTºèôÁ|¶:–æKiØŒ ÌÁ C郹Xš#}0]äÓÓðÓ™G]ûú`Î&6”æ,ÒÝä…¹t/ sÊç!Ü0'³S§æXÞä†9å+7L92†æBÝË óHò“æÔž[hu“!Ïé„ù®»Ö× sÊsB^˜¶4Ñ 3n:´ºÅ ñ¡ÕYÙÈdô´ˆ¨攞ĺ%' ¹a.Vƒ ±n-”n˜“Éᆹ4pˆuæå‡“R¬›,VN±îЙBZÝb&­Ðê6ëE¦&³%¤&³³„XgÅgqźM÷ÆðÂdhHxaN¹ÎÒ ³ò«^˜ƒÓžôºÍä ¡×í"ùz]ø;†æ¢o„ôºÅÜ8é…Ù¥®É ³‰À(Øm–·Án§_¦‹õTÓ “5µÂ 3~b v›ùá†iá¹I7̃èöðÂÜGª ½0÷#ê£æ¦#Æ¿ÏëÃwk|ù®áUMGLĹøN^Œ7àQZ É®Εа^ À /OR$»Ð—ðžoŒ] vÞ#§µì³B$à-zI¤d·Ë¯;Okùs+vJÜ|gkús’ïBK¾³˜ \·øÎã1 ó‘ïlu:ñMýë£ØòùÎÖŒ¡ßYŠðóQìN¿½0}6Á¿wÍALÁtwž-ïÑ´dšƒªÂåHw>S€Ü¦æ ¦$ º³g¾|èÎÞ}tgïÐþÐÝ9XÑ]¼©AwŽº³TG¤.Ò¿8é‹i/ÖsKv½Xšº;‡q[AwÆ$ð|Ý™åwvP¿}1ß~wDÝù ägj·b× mú­Ø½–Á÷‡t×KÝXè‰î^‹¢_Ew62!ð®[§Êˆ:_¥v'¢ïÞ6^ÀÄ»·ÍƒOÒÝk˜rûݹ¥PÄ[UßY0Htçãk”èl>òcÎí‹ù$1ÒÝk 0ÝuƒºuãÝÛfÒ‘ŸxçGM0!ð.‡#¼{- G#Þ½+q֌޽æ&ÞuKU…Ɇx׋Êù ï¼LiÄ»×Âmá·Áš x÷v#" ÞùAwÝkèœÆˆw½LmgïzY”èœíz1_q@#ØîµtŽl÷ZXŠLlç—}¨Ñ9ÛõªJib»÷(¦ŸÛ½”ÓÚuKÐ…5Ñ.›ìzQQN‘ÝkaÍK¡Ý{‘+›ÿÚ»JÚùP•@»·®#ÀvïP¦ü%Áv~Eô²ÛYÿ`×íw)·`ç·\ ®ó±rôà:?ˆ.àº×2$~ëÞ£´²#ØùX¨ÅìÞ±ì/ØõZ™Q`çý(”ÎçÔn™Ìn·ð¢²Ä©ÐîƒK@;ü$·\ç#pí^ƒ<’Év~¢Cq®á==ZÓ“íüLØ2 ÛuK«†}o²ÝkQÏd»w8ŠO"Û½ç‘í¼gúJ‚íÞ~X¸Ylç7ý€íÞ6ÌÙ)¶óëšwx]÷WcÛ½–©³;Û½'gnA±]·—±_zŸI$çóª_ä1 ]·dqx*ˆvo/Cp´s˸0ý2×-×½ýt2ÑÎLJý¢·Á'”hç¿p¡Å§Õ·üŸ‰v>B¬,‰vn¹ý0ý y«u°  ÈÎ/âëÞ&,RA°ó{Ün˜½>]½íÞƒ&‰Ÿh÷Z¯-´óËl7Ú½ç~°ID²{›p+“d×í3‰dçw†¡mÅoB8e:Ù½èÑÙùXé1édç'Å/²ó ÆGdç÷Û »nyé êd÷ö¡oÈîm±¤)ú÷È©dçÿΈ»—ìÞã¹6 Úù°Á*@»×Àu Ñ®×!—i ¿劰{[ þp@;ï*>ØîmÁŠd;¿½ÈaŒ.Zt¶ó.ï»× wt°2ð‚íÞ.Ò¶ó7l÷Xh—l÷ÞïÁIl÷žEŽ¿`;‹ 37Ãk)^f YІ¯`_K­ðÔB~43Ðã®x¯¡Á¬29Ökéðø¬®^˲ʳ÷2SÀùkp#«LÃñZ’N½çý{Á¬2ŸˆYö R/¼‚ G2Kø>`9ݯ qÇå]œ”kz¦ÙiÙ~ –'†:ýÚþ×T[÷+hT_‹Ñæ§Iß~Åõ^‹»§ö &~ÿÝ/I}Ý2IÑð®Y¶®Sã{-¦ˆýdYÁ×b±Ž?ЭÁØÃ÷ãÏuP5M…ki^2ÂCÅyöæ^þ³¼7Dñ=ƒ·¡¹#ûÃ:ïßÝ¥A{+»xàîùÄE·Ïg§ŸƒœúZ&<>s‘¼–—O°²[6¢ùÞtï´Àåf4>zí0Ü{ãD½ÀáF!áf90›ZÇß+\?gÕcÖ°ÝÂ;Õ;œ?'Ã<Í‚’ià Ã÷Ïɬb¯eàõ› ~- ïÅò9ë ïƒÌŸ²#›Úí½ï>Câ×rຨå˜åàÈïÚ¾ÀÔv­1>›½™N?¶Õ Y¿,ð5µ†>1£àNXý™u9¨½–_¡´/¦{0i†›…µÆ .Ò*Ð0EyE/“}‰ÑXÃ)–¥PÑãž¡èÕÅžýÝr±Ã£fA,è£×yBê<9IX †°NZ uz¼'{Fhmö ©Ó|»aQ¯Wöñ×ÔvG. Ø›o mýAw5>4Q~fð™¶ò3í'Ó†›%ÊÏð[ééTPu€ƒ™Òè7f5tË×Ö)>þ¥¯†%'õ Øú™³*ÓÅñ—´É™V£2gc©Ï×Bñ¾QÈy-”:•0îµP¾oL´o–ƒkxôAÚ”ð[× ÝƒÅ+øuTí™ö艵oÊ ËO–ŠÏ4ýNö>ú%LÞáMÿ}­8‡™¨Ì”r?‹;È¡ Ÿ{Œ'5aåe6~ÜÕ‹÷Ͻ¾~Ü«ŒWy:}Óô÷ã3ªçã1:{×§Ð|‰\HšÜ9æÇ®ÒÜ,|SÍ!ýQá7 jÏ7VGö’áèƒgxÝ<k{J ˜W/V?7‡ç‘é~nÜbë—Àìp¯¥ú¤E´bÅúaϪ>cIð0bò¬µ‘ûÇ?“„+InÜ2Nv>/äìD¾ È=ÜJ{6V]rvÕ@=3$ÉqÚH’#µãF¤ã‚…q¥½‚â¿û¤8[Ÿ‹âCæƒâ†.K78óÅY:ŒjçŽ# ¤¸ÉL Aq“É3‚â&7v‰q³ñ²…q³“e€qJ6gÚÝù¹0n‚ã¬64z ÆMú7ƽ3OÇI‰q“õ7ã&ÓÆ-zÝã´® Œ[¬í·jP0.X·té¸@`aÜbB‰À¸ÔFŒ[Ôöãì‰ ãìšg‚’‰q†Í¸[Ä83ŒÆyÒmÌ2Ä8›´d@ôÄ®Z¤‘㬠g0ÍÅ>1.’yÆs.%ÆÙQœuãÖfr‰À¸µ­ˆqÊîgZ@qÞ„pŠó%„)PœG„g 1Îàë8b\ð}pœ½*² Ø£j-CŽóÐfíY6¿òŽã¬Iÿ`œ5ÙŒó@˜Æ]mˆq±™@Œ‹ ¦À8{µI ­1̉ÈC޳õ‰úÇ-®8q±…Á+qÖí&?â"x% .¢LâÌŸÖ)ÎýïÄlíZØ/).B΂â".)NšIqа Š‹]–Ä8Åj'Æ)6?0ÎãòvGm:Ï®¸Ýç‹q%¶@„qŠpKŒ“?`bœþ%Æ™GÆ'Œ+ô\IŒ+±¾Ç&}MŽ+±ZÇ•¥=p\¡—rœ•$Ç-‚ãJÓ*Ig—Â~Èq%ž\Ù\Ç‹ã =ô“ãjçë#Œ+'z!ÇÕ'pÐ9®ÆÚZg´ãL/æ‰ÈqeksBWcå'Ž«5 ’W™¥09®v=mâ¸Ú‚·œãrËKW/’g†?œ0®ö@4`œ †1ÎvÊ*.iã";c`œßaZ€qÖ¿$SYfVÀŸÒÖ­oîT’™øqÉq¶ÇMrÜun‚œ¥†ä %ÉÙ™Èm §mUÛ)$9³,Yð¶Â>An×£Y‚ g)'y•r×þ Aκå#A»G‹¤”rž ó¡£&oíZÛš&‚œWÌe? ®m=ÚäÌ"üc€mBš=8Î9oA6F[¼Íä8³ˆõ67F'öƒƒä¬cî=’ä®S“䮓䮓ä|kTìvýR§sk”w g øÔäÌòí°5ÚD9?¡9¯@,lÃÖhÓ“EŽó 8Ά³AžÛ¤á 9Îo;-x ƒY‚ãì¨ÆY‚Ï.jÃÞh6ÆÙX g»½cÆÙ®ñù`Ü=^¥eúbbœ•]>/ƒ»^aœ ;Â8Û{ÆUçÎ2´ã"¯j`ÜîŒ Œ3‹5ùÒnÉ-ß\ºPn1ËQNfåòɽÏ$§EkœÖËAr¡+‰ävùãÃr»ˆšÈr»HP#Ëe ÂÜæâƒ0·X*1`n3“sÀ\Œ;$¹0H’£}Jr~e)Éqg.%9õ’œÔ¬Ðäþ=59¤É¡5Yn±Ø¸X.b%Är±èËE¨¿X.Uˆå"ºB,狊›å¼ÅP.ªíåbÉ&”ótJ7ÊÅ‚M(çZ @¹’ÊÙ O>Ê™aÓp$jUÀÞ\Ò´Ø)9M¨Täê#¤"W§ "g3åW‘ËùUŠ\ý­ÈÕ¡øä¶>¦!ÉÅÄ-I®§PFIî‰O°$9Û™âQ.É™o'[P’³<½¤=Jr¾V!É=C`IEîaDZ*rÏÐ,-Eîy¨(É©tOjrÏЬ,Mî¶`âK‹DˆrJ§›¢ÜÕ‚¢ÜX1ŠrcýåÆÖ"Q¢œqÒW”›Eë2‰r)5I”{Ç#VC¥œ¢e¹D¹Ù‚Þ4¸Hó”*géa?4çÒ ÛP•ÛTZ©rïGDÐGUΜg©ÜQ•³êìyGŽÍÏEZN©rÆXd!ªr©gH•;]jE¹‹pnÝ_áÜ eG¢ÜÙ’i„sWâÜ à—*§¤ ‰sWÙ-MOqÎ,¼çÄ9³°ÉaÞMBPÎShRàÊ™"¬1ï&ù g{Ù|ÈÈqVd¥|8Î>_\8‘ã,Lê’ãl‹œj71ηÕ?gÛê‚J`œYˆ«Ä8·ðÔ‡BÀÑö<1Îc›a¨TŠn-1Σ҉zà8¯ÕÂnÀq¶?¿/޳]t¾$ä8Û3ç3FŽC(X@œ×ˆ §‚+p½-`ÂY~k‰p¶_Nô'™e^¡ðpvfÉwªYrIJd8_šJœƒ0Ço)nÅÇWRœ¢SSŠ[E_IqïçIÂ¥8Û)…JœmI²‰+q+>€RâìSNÜ¡§èÝ”âl·ôƒp¸ÆŠÄ8«Y£TÅ$û¡÷öCÄ”§¸TãV¸gH[ÏâüþyT섯…ĸÞãÖÔ¯+1n=º5ãV׃†óÐ5B#œÇ»Igƒ»u)ñ±Âu›»ùÊá¼ ?Û£‚ÊX„˵Yê¶Ç½>$`¸þNY¡':ùWi‘öæn×,Üeý–j—3Ú€œáΔQÑ1ém„ª zÚn¼=M2’àí ÝUô6Bq½YŒ¡‰ôö4ѽèmÎ gÅ$ùºèí o#¤ñÛÌ$€›"¸R¨Îî£\G©i‘àf\nj3J7N@•ÒíÓp3<§àb08ó¬!äàì÷b?¸à˜8ɜⷷ‰dD\øàf%ü¿µPÊ”ú¨Š?ÄoóÅosi-~› â·¼7â7óäåQâ·Øï ~ÛÑ3ù;Õ7¿í'Ž!ÀÙBïëM¹[u¸}ôà àöP?¸3è2*gÊ3ôy—3¥=ÔÜ”gR.шÜ^úºJƒÛ+BÞkfEă4¸{€ÒàN—×¹4¸³µÒ Ìô-s˜³ûÝ?\% ˜óLnl˜3^Q0`ÎÚp4„9£E•æ,ÆMÀr¶ä,5ºñ'vºñ/m æNë"À‡^üê,g«J¹=NzñKÕ Ê©`zœ©: Hν’³õ+K‘\.°ErógëW±^‹|™·;e$M”›!Û årûY({Ö"¹µÓˆr;š¬Ø3ä>­HŽY/äl²%âä,œˆÈCÛ±µ+;±ÈÈ¢±äîMm€œO‹Uh‡-Ã^9ŸJç ç‰Þ\r¾M;d9ØöŒíòîùÏZ¼(9ÏR¶nýíÞÔÈ!û'ä^KÕ¢$×m &s’óÄeô¸Éu˰&®#ÝÃû¶Šä^KHV 9ï™@m$‡^nwÊ×› ¹nïü–êV}|³‡êæ$÷Zâ5Êy~Ž€r½ÌÔ¶*–‘34? œeV ær”óÔYçF¹nk¾Rãa‹v;Tz1¾>`¹nyäÐæ,×í‹SîÀ8 ×Î`9OìÆg,×-ׇ‡äF6`Þt ÜÕÄHÎÿä‚(÷Z"˜(çc·?¥gÖ’^ç(×k ‘ (çiÝڭŹEpç(ç©Òä—é(×-ó … °œ÷|GÅy²¨•kÞ,×-WoÞb®£š æ+Õ×D°˜íÈXçÖâ<5Ù¾YÎ3øHÁs–óDd<ui] 9OJ%ÏIÎs"qÆHγþ(–ÎIΓN}Hγ qG$‡DI„)'9O®´n)ΓqVÛJ|¤u¹´8K1$/G¦>šõH-®Ž–Ldu2.îý»ëžS‹«kê3F-®*Chquĵ¸ª¨• ¹ª’Ðâê<ú’æêzô‚“æ,#!?Ϥ9!ï:iÎÎÅ=J§¹ºÃA4WsOš4WwýFÆùuîgG}*ß6+¢ò@sõDl$µ¸*g¶ ¹ª¬ºÔâjÄ]H‹ká!/š«–B÷ö¨|ÚaÐ5•…  «{)O®†¿¾ˆ®ÅJD×Ê /K¨q­0­|]=K`h@×Â[@×äY*žó,„5hq­·ÐÙ ÅY7åö¨|-úI‹kõ‰~˜H³Wî¬ZMDúdé±&‘<‹–; Öß—­ÔæßLŸÕš gÑ?ÿ¾ÒT¹åʄÿ¯TWÍÒþîO/²ÜýÀv÷$ËÕ—?ןôãD_Wz,tu§ÐbOÙ†}Òl±Ÿ+=;º“h©§l¥®>©¶Ø×• ‹}Ýi´ÔW¶R_Ÿd[ìëJ‘žîDZê+[©¯#‘Ö;ù#ÿùÿ?2iý3_µÿøÓ÷鯾aÿñ—îïïÚß<ºêë_ΦUmfz¿âÿßN§u}HþÇÿürh½7’*ÿ³D+¿ Ê&i(ý–ǘ–êËk©úöØG.3ÎÀC"~˜Œ9Ð’Ûx q' WÛ\bœ0½w,7Œ‡3§”Yó·bÕö‚Üm^«Æ÷bÈmö¼›ÂÛ\a·X‹ìÃŽøHóW¨fEr w°tÕ#Í_n¡Õò(УpTDÿ£•‘¥ð¸Å’–ƒØKe„¨¦¦MlÛZ&7rµ®­ævç‘•ÌŸñóIª©gÃ#ÇÒWsx§+ô‚ù»ˆªòð‡èÒl€U'-ôÕ¾, n9G±þ­ÐW»HÒo–Þœhxô';;ÑøsFêÂ[º¶§ÃÑ®¡W•î É) »lìùl†TúŸ–Pw¡“Ce•Ln‰¿–†]Ý"9õµllŠ7¶èCÛè¯Z¥—¶ C¿–ÍÝFl•^Ú„Ùì;Ï\#Z¥—vQHm«»(`‘÷ªRðÆw¹Éh?%éhŽÚªóýZjÁ1Xl¿/,b}ØZc´3g5_ê¢ÉÃ&ýh³Ÿ¿c{Vèø Ú`´ýu[›Øê…~k3Â-:ZŒ·`!›×°[#Eåõ`küNA·Uâdë…1Jýñ.²t[ìõ^c.XHÄ,çPÑzŸÚùW?ƒ.äBÑú`´øíú`´Ÿ\ZŸŒö+|[_ÌzÆ_·oæASÀÇkÙŠXÔ1 º•ìPÛSî§=—ö0êÖ6*-[‹•†Ý6̶§g¸Îõ<”] y˜­Ç1 »½,³+¢’Éð[gzî'Ïåöì¡&‹Ýœ®ˆE8Ñ´QŠ„#ì$¼ÆûéÙ²J1숶Ñ(˜ðý·µ#.Õm•e³—gHˆi<£nŃÍÊÄt¨CS–¥`ÄMËBÐ…ÒÈ5•‰iÚðiV'†À×Eub,ÕÆ7 Ãñ%oV&†ìî5+sðKZ¢.Z<ÃV&fÿ\YîšÕ‰aÌ%vU›Õ‰á%ð šQR ^‹¢n•˯Y]ƒ,Œ»Utì»g¨)ßÝ©¨[fÁ™® ˆÞ¾iaÔ- íw)ä–2ákéUÀiÃêÄ00‹ÄBöU _øYôúåuѼék2"”€Ee´i#K(oû¥6ÚäæÏZšþÜó)ߊ¹Õö#âÁ®¸QÈêOjz+–¶t«¿©vm}¶A·ì„"i„{:»ÍK`ʤ׉¨“^K(=z6•Ò.*×Êüš¾—‡ZéÛ†ç:•ñ¾›-¨–úb º¥ˆ‚:€?WÀª‹HÔCù#J¦=^Ô£ Ûªn¤™Æ‡P@í»ÂŽ©šÚ. RÔ-K UsíøA®þ^ú 𠻃€®`ÀBé4òFzÁ›ýµP‡±¤¶m{ü­C6æÔ®È÷^(¢6ÖA¬õ?¯£*EÔÎ$Wõ?­›A ããðík¶il£8FmYõJ ÕÚàNTÆ16;{-“ÆœoÑÒÒÙ‚qŒq*ûfÔ^ÇØ%òõVª¶iŒcìÊ>껃øâO1*$¼{éÏÐêíïßìµ?óíêmüŠž×¦K†°û^?4jCgØF¥æŸM·uAŸg¶ülao&™ïYJ,æ{sš ùmÌò=t˜ â³ä¢d7ßka̺ˆÏ€ˆg&ñ='X’Ä7 þ$î… ¸7èÍ´§l_¢½4*ÚJË´w[@{f!#’ö†"[‚ö†4Þ =s.´œhaÏ _ØÒ:ö†¢BI{W Òž*^$í™`Ži/Ûˆön =¼¯£šR¡i}BÚó£Ä[×°/Ü»ÿLˆ†O=qï>Íܺ"qÏOÌÓlæDkTS„{÷Q‡YÑšæiŸNMÞó$,ðÞu…Î{Þ)ù¼w[˜c)/€¼w÷Â4K:1`ïnÀKöØÓØ»®™°wØ»Ž"ì]÷Åaïº+„½5$ø öîcz‹ ”ötD½» ÞÝ Xïºýd½²¢Xï¾°Þu‘ÎzÞ‚Cë]ƒ#ë]Çõ®Ë&ëÝmÚ‰L Xï1Yï:;Yïc9ññ(°ÞmYÏ÷o°Þ}n°Þu'Èz×Qd½ëy%ë™eȲãwÀ/CÖ»~²Þu.g½ëšÈz×øÈz·¬wýd=³p©LØ»ÏØ»¯°wõCØ»Ž"ì]÷‚´w·i<Ó¤= ‰ ´wŸ ´w†´wÝ âÞ݆UAó÷î6R r|§èø[‘÷¼ é©|_^òÞݼw¼w†¼wÝ-òÞÝxÏË<‘-ÇÒ5ÂÈ{×5÷üØó:¿>8Î{÷hÎóë“÷®ñ‘÷®ß*ÔÀè‡Èw‰ÈwÈw[Xp#¯œÈw=)D¾ëž®y¾£É:·jDä5¨HDö«ä¢q‘ïº;Ò‹j|D¾û(åñ8ò]çÞJ2šýŽu’™ÆøÈ|÷Q+¦Uþ¾{Ç;­£vL«js4­êÉ&ó]=“ù®kpæ»®›Ìw½„¾ë×$õÝý>ë×7‡Ôw·™9¹²ç“«Î¾Ö¯gØw÷sÚwêöåï ìË«öåÝöåh„}9a_ž[Øw5ÚwnöÝGÍõ}_Å}÷¹öç­÷Ý-N̯­ò|çqß5‚ßmi1¿Žøå]øÝG=çû;üò™øÝ½¬˜_ò¿ï«ÈÏ¿€0œ˜^‰·¿ëVü®˜àw[Ú¯éðw÷Û÷¯ üå`È~×x%¸ç} ûÝ'Zãóåÿrt%þYÕñÁ¿½B‰StïM­~²ªnåûTdv 9ð‘ÌH€û4GS85+à5àž!@*ÆWIìƒ#Ãl@ ¢ÏCò›!Þ/N’_œ;$¿´¤äÇ@üÅž¸ÛxE Ì›’_ …¤Àë¨ÅPõýÕü¬.Ïýq÷6;¿äX—×­œa•D'áo!¦0A©.5 ºû¥…¸k¯µ¶'OVe•^bR•ÿއÃöÏkˆó7ISÂaBà[ 3C JÄk‚Àé€1 Cz“‡ÍÄÄ€Ão’ÓD-1ð¨# -µEaàñ+aàðS&Ž}ÃÂÀ·DÇwÆÀaÏš$ÁÑ}-“ ò±•|Û5 íŠGKµP$x\I$8üvG÷i¨ap8Á@Â`š.& w,–͇âG÷{1 îg0 îg0 îg0 îû3ŽžÔ&-[:‘ÔæÁ£eñàhîóàPˆó #moÜÏ`„‘±M<˜æ˜ÉƒÇ¯Äƒ{,™GKN<¸ŸÜ<¸ßƒyp¿+óà~òàhy7âÁ£ñ ®-fØNÜ÷gÜoÜ<¸Û1Û$î;&î÷bÜï×<¸ŸÉÆOS‰Qp£`ö…PЕ$˜ý™$˜$˜o*I0o&IN'â³Z¿ÓM’`>x’àqu'¤ÐÝ ³„ÙS‰¹$%f/$î:ÆÀýÆÀ}%cà~lc –6Õ©¹¬^Ãõ}‰9÷ w7GË+ ó=™îKóG¦ÀÝ[¦Àܸ$îû%æö,)ð¨Qsƒë:­|§šÄÀý”ÆÀü ýPÿ Æ×F¿ù;ô[·ý6Ýú»Šµ6ú­¯ö—i86úMƒžÉo¦Õ¨ÑoÿÈè·²ŽÑo_Êè— ›üVržÉo£)ÉoÚ¥$=óBI~ó7Á¡ÁÏ×IîËƾ–±Ïæ–ûòVû¶}¨°o¦çLbß®3Ö·cßþ±Ï¹±Ïî¾›û¦ “û¦îÍ}&ýä>÷DrßtÊq_¾¤ä¾iŸÁä¾|ÙÉ}ÓÖªÉ}Óæ¿É}Ç•Ä}Ç ‹ûöC™ûvW˜û°Ž},>w‹ûöµÍ}~߉}ûfŒ}Ç…„}o‰ÖcßnFÔ7s_nê›3TÔ—]nèÛmèÛ]LèÛ/ÁÐwÔôí—`èÃý~ì=Ïv}»ƒ }û¹ }3·†¾iï„>‡òÛÐw<ÕRG8}û5úöµ }»Cß~S†¾ý䆾¹ñ­æ1NûBßÜð(ès¿ }û,…Ð7ÇF¼Ì˜T?Ÿ™µxCŸƒnèÛwcèÛwcèKëó„¾™æÝ†¾´t7ô9·cBß¼m ièsîæ }ÓA‡ú"CßQGÐ7m½¿¡¯¦ìfèSâªd¾ýf¾éôLb>8, ²Ä|û†Í|ÓÝÉ|¸=µ"æ;ê˜ùÒ^Þз»ÏÐ7v3¡ï¸cAßTz²úì-.蛎J–зŸÒЇˆùö͘ù2è`2_õKæs¿D¾y»Ýž!eãmâ›Îb™Ä7ÍQÄwüfeÔDÝ‹‰ÁeSy­ŸîÎÄwÔy2lb±…çý ¹‰wÃßñ#4}Ò,ÔM÷¥ºn¯‰ï¨á ¦vÄMâËî4ð½÷òµøÌ •›øòG¾ÝY&¾ £(âÛW6ñ¥{oßñG7½åEŸÄ·;ÏÄwÜÞ¼~úŒ| 1‘o·cäÛwhäË@B¾i&¾Ýå&¾ýšL|=2‰oßÌÚÁNÛ—øöÈ2ñíÇ4ñíÛqÈÓ};ëùÎ$¾¼t⬠²väÓ&ÈÚ¡O‡ØmÇ>u;~ª›Ià›–#øòõ&ð·çø§žŽ’ùœÍÄÌç)›ùŽVÌ|žž’ùö¯Ì|ûWf¾6É|ûnÌ|N¶²™/WŽd¾£ÄÌ·l^ÚuòQ5òåT˜Èw\Ú1P/÷¹™]#ÛË+“ø`ú ljæ[iú䚪•ûûçô(_â›ÎB˜ÄwÜJÏp|…¿ý’øàŸ öþêýþÒ¡-éo9ÂéoùÕ$ý½Ù4Tô‡@Hª#úË,‡‰+âkKŒÂ¿ÕRçþ-SHü[ŽûŸü÷–4!¢øoùÀ@ü·œam+©šÿV*Š@”¨Žp¥Viè‡:Rníí‡1ù1ý<žÜÞ~­¦ƒ¼ýP¢:òöÃ\),ú[³½ýšCߦ·_{²]¹û!vÃþPÇíÈݯÕß,îñƒnõ·úÅÛd|ýZ36ÉÕï-¸mäyùþõæèê‡qõÑú¢_¾¾~-§i;û5ÅN_?ݾ~àƒø¡ä²°wý4Ìíìoš¯³ßvökž›åì—í¦³Ÿo/}ýÞÏJžhöõkN •¾~­f³”z§°'_¿æå5}ýðÁêZòõ{KʇüΔ³_&Ó³ßû÷—üp7ãëì‡ÎÕÉÙa„Mrök=ñKÞ~­›Ïäì‡}åGìØôäì÷þÈ ËÙï(‘³_Û]7üص«j³kZ:û¡‹UGÞ~mäµåí÷–èÅØÛ¯9Ukzû5¯×éí—S]:ü9Ê­=þÞVÚþöÎ==þÞ\Ûã¯9P`zü¡ÛN¿9B>ÎZ(Ë3ŒXA|ÖOø›¦Ä;Œ˜J>aÄþðwG1ÕùÈÕgñP-¯%GØ.•¡€²äV™ƒh·Ä¿ÏvPr¶Â¿6Ú%•n?±KŽvTv´”%ÿîaÄê)‘?qÄþ0È×]pÜöüq ±·âž‘‚þAl°ß4?>Áš~OèeßøDc[GÜ/6uÆýjäê:ÍÑ_øajçˆú¥†Î¨_ni×rSŸbjëˆú¥¶Î¨_nk×r[Ÿbjëˆú¥¶ÎØ`nk×r[ÿJl°‚ìÉãïÅsø/ÇëúGñ¿Ê?ëõS˜°òêù²?É&ìOÌZûÝüó«9êo¿Å?Í[¿Å¿o럆·Ûêÿw„ý×_… û¯ÿj˜°ÉFÙiýùy‚ÐÙj¤Õü^å2aù‡Ÿy®î«G §ø+ˆ¹^äKfYv¾sñ™òpÌŸ²ì쟂Ú8̱ƒëeÛo'¿©6ýðô“˜P/ÛØ´,æö›§”Cí8îSÕ– ãäÇN;ðþ­¨O³<½%„Ðêýg½z3 qS¯AíÚ†×k*ůãŸWDnŽÄކ[¯Åã·ÒÖÖûbv™Ì[øæi·Ùo €z—jT_,Uú6{ëhÙÖ°"þïb G¾©w`GHbÄçnºvcŒq¼]];Ž€b_zéÚ1Æ—£Õ{0(ñåOõž Jœ>Fïrø0`®“WVDƒ€¹Þ‡Õç  «·‚h«•ac©ÜÖç¹ÎÕ±Õß’JüÀ[˜wó”ˆ1þâ~¶§@åAîýªEŒñw÷%„zK"(qÁ‹ÚécÁÚýj¼wƒ£)õù3#ÂxÁX5â,¨  :÷€Úð¼ß§-­j‰³ R¦ÿÔwçgxŸß}\îˆ1^«ÃG×òDPâ\%BŒãIC÷ñ>b£ë啈ÛP*SsX¼óÄûw³†ñÖãG•*“¸ÝV¬Þ’ÉÓ§ªµLFÜ|L)õ;bEà/^»ÆaPÁA’º¸^b¼"Û©qôÞ±ƒsÔ÷íÅ3@5àË«qôÞá£ö[‚®™ÎMZkœœPµÛ"&q»|öSÑñ àá-‰˜Ä–¬ºöˆ ãøßñŒ˜Äè¦_­2Þ.£ê[1‰† KÚAÆÑƒºÃçAYêÓö\ïßM)ß?#(qØU…AÆërä·Úâ0èíôËßx«‹[ «-µÅaÐ[ÇVGµõêMÆj‹Ã >BWIDo™jîÝ‘Äݪgì÷…T>‚ ÞÅ•n#æû77V¨ªqǹn+é\ûÃíXu„©Ú#œÏ;,óõö8 *¸=y¯f'qzÜóÖ‘ËYEFœ÷zæÏ Fx›]Ùlˆo; [eRœ~¤HâP_"Óâ”~ùœ¿2/Ni™vª"1a9£vefœ÷nF°Ž&Vz¦0¨Ì¯\ ×2ÞúpA»ù\h+VK<Áp4žÊô8 ôԘ߂cU&Èy»êö´†ah¹øu3EÎ[Ç'^9rðº²T&ɉu¹$bŒãµèWq3Aº"UÎ;Hl­X™+ç$>¢¯L–Sb¼óþâ%Ž­^™.'~UT2"Æx©=ï8æ`§äá7ñ·dâ¶Ê”9oÉãÉx1pÉÈé•isÞ¹ÔÁ(ëºñwÉÞbÚœ·Äßu…X³–¶ LœSp°®­Ê ±ô½a[wVæÎ‰Ù™g‘u…Xó7`•ÙsJË|•és ¾bõΚü 3Vje wDZ }É}ðsÞoÌ S0mW•„X‹ÛmÌ óŽ}‡iWˆ¥ï8±ygc‚o©Nõ;ö‹Fzc÷nîßÔph¥ñyTU镟&`ÛJé{ÃŽ¦Ó˜@§ )Å­K‡Vú–8arcø‚8O4&ЉŽÐ¯î‹4–\Þ03è¼à|(í±ô]ÄÛoªZiáÈ‚ÉA¡¨òç¼ÿ®0IíŽsÖ‚‰•;¶Æô9o‰ ÆÛJé{Ý®£Ý d½l^ÙîJ 4œª'Z\V‘±N-‡Tú~Î/Ó˜@'fxžŒ¶'¤Òòï¥SèÄ ÏÝ`C øà9õ5¦Ð‰yXÍV®ªïæ*_3¾0—Ī qcéB¡”¾ÍXGhÊ¡ƒQTtéPJc@\úU(¥Ñ9ì‰'„Ò˜à¹*4fÑ)H1ò¨ä%ºxzFæÐy·8ESh+!”¾·ç-HS¶lDÚJ(¥¥g4Ú¦:­8âk+M«ªÏA›rè`-*ࢊS?ZT‡æ¦$:-7Åï%Ρ:­ˆ\6(¨ÔJ1ŽºJtĹýð§c†}ðgì‚0 í6:ã½°ù¬9Й0«Í.¡ ªŽðJÔ\é"¯™ÎØŒ£ €Í±»sÌ'‚³¾ptÇ##†\¤¿ÛÎÌ­VšŒO›·D@,ž†O $·#|oüR;"À»%6.Ž戀;|£0³»%¦ÄCÄé³€KQûOøÀ¶æ€’¢Ü'FîbmÐnÙÜ·¯Ó•,¸ædPëojw2»è»£Y'þ…M€öÄÄ¿g¥U=ñïÊì#Â?&çdéGÔ ¢?ä²Ò‹ýÁRE»GÑ_è(|q¢?¨/Ú‰þPGx ú»–¢Xþ½zhÁÒ€h§%ø»/wƒØ‰nú‡ý0Ñ®È~÷»M¿md¿X„[d?LôæCÂhZ˜$ø‹:9ÂúYBÀ߃<Õ¼?Áß“†¿lä’É£×'ï˜ð‡§ýÂßûmˆMÅ~R$•Ä":Šh‹ì÷ô„±.®¢ÎH/—àÊËñI~X ÄDB?Púú _)#ëýð+m…~åyòJD¿RlÜgô+Xú—Jb‘â Cȯt‡15ù½=ï¯=È{RCѯd\{£ß;£«D~ѬªüJ†å0ùñFÁ/ìUt/¿²œMÐà‡½®æ_ͰÚ¿Š°Ð¬àw_ü°éf~õr¦0ƒ_Ͱß?¼ôò¿Zs-ðÃ8?’ûp b@#ø½##ðÃOtÎ$ð«Åñr ~B§~CðÃàÑd$ð«Óɇ ~u$ñ ü°ëƼ?*¨³~53Áüêe Ï䇭·Õâ 'g ¡_­ ¦F¿÷Ð÷nô{'.„ ýÞÎ÷S ýâþ„¡D¿÷ÿ=ü„~ïçhxú!¡žæ(¡_MsB£_m9ýðaõúÅÁ †8ý¤é$Ç¡YM~øÒÚ‡üjÊÀ&?\JߘÈÞU‡ä‡:¦:’®ÕÍ‚A~8Éó’ü0ç‹«D~+g1‘_»œ¬0Éo:ƒh’ß̵Ãä·z2ɯbQÔý‰ü.KÎI~w¾N“_®Í¿'Ϥ ~E¹Ì}˜Ë´I÷½ÿ/&6÷5ì+¹Å4÷=ö2÷쵑÷µêÙÉ}åN$øôúüŠN6øùŒ#Áï^y?XZêW?És_&¯3÷!]âm‘ûZr2÷µŒášà×>:ɯø¨DèWí'”ì÷–Ü¢8±_Y6f¿V…~Ýv?F?Tbý€h¢£N,¿è‡—)ôÃ!œëý`Çã’ÉÓHu„ѯë°y£_1މüp:¥‚XSÛ‰‚¿•dð«6K6øµnÅà@íüPG=,ò£=ß6øÅ¥õ'OSÇr±Ä©ƒÄ¾ËMúйæKQ_Ÿ‰k¢>û$ôuŸž'õí#Sß{3zhSß´%©¯¥¯QRß²Íob_Wø¤¾*3¥&ZØ?\æ?˜°â~}cÀ/#óüæñ7Áo,ø-GL2øÁIÔnð›™#Þà‡ì)Zÿ.§{Q¢QsªÔð73±¼¹/‚ KÄ“ð÷øÌ•ºÒ Ťû'غŸs?¤î×[b©t?ôŒ~%ì«6îLìs³b¾²|iË~w Œ–ýn[V§ìWÜÁ’ýŠ- Sö+r@2ôE iU‘Ý÷»–„>ûV$ô])SŠúÑÞª\/ËG=Æ>Øúö¨ú=6LLÑoÙeJ¢_m‰tý.ÛZ&öá|S¿öµ<95ö=vDHì»l¼&ì{Ö)Òúc²1cÊ{°øjî [{­Ëâ¾g•M‚±BÁþËÒ¡ÀoÖÔæ~)›'øá5Ø~×»á.ðÃøÒ™ƒÀ‹m3æÅu•Ô5~XÆõmø!™óü¢'¾ª_¹l¿ÁÏ‘ü®Ô9~È”z}T? CíüE~H« °È€ì)Æo£Ñ†Ç%S©š?ª_°€äO}Rý®<ø±è÷x–Oò+¶<4ù=«n‰/V)ØrgI~a8øA¿;}˜Œ~‘|Ö¨‡ÔÂ5§,¡¼VĘB?l_,’ý.8Â[äJuÙoÎìW// ­d‰àv j‡ð÷ çŸ2üÁUDG0‚?˜Lê øCúW;þ°Å1]þ`ªv7á£ú… ªLð×ì;kø+[Äý•}ü'ú‹oéQ >Åye»¤?EèpMô÷lÛÑöWz›¢?¤÷Õd,úÃYÎý‘ýÞ¯ÀãMôw?¶÷4ýáu¨@ªßåÜ" i[.ø “sþìWº]:Ì~p€ùÊ~˜‰tn#ö{Þº?쇭œž[ì‡ý E>²_˜Ñšô‚ý°£IõÃKP‰Ðo9”©Ð¯:/_¢ß^ÐÅ~%ó0›ý°wÓŒØÇ=ú|Å~²Kë†É~ÄšÛÄ~sKýžÔwŒ~w&æKô+vûúa®·ÄGô«¹TXô»rÒúÁÖã+ú›—&úÁåI;¡ßD JôÃј¥B¢ßSáËè‡LÇVceEFeÍ~Lª˜ìoÎ Ùï~²ÙŸ¡4±ß»Ü§ðFö+äÔìWºwZf¿R,¡ ýÞH#”è‡eTÐ!ôÃSk£,ôƒ£š Hèׯ‘—úµ;ÙŠì‡áhB#ûÕv›¶ˆ~ïGÍ?É}8M³6GîÃcMÅáŸtÎÀ¾þÕEˆ}øE^¾wîÖ1ö=éó“Ü7m³“Ü÷ØñvK~61÷á-Ý4rß»{2ºŠû lO‘ ¹gýà>hè&Cr_ê/@#øa_P?ä÷L«2F?ì~Òü– èýý‹~Å€~X[%è ý ™óE~8ëÖø.=Z0#ûa¸Š¥¦&‹ý°•º-ò8õvÚ Ãß³<éþúeoØM6]Iú+ö%2ýá\ç«ùU€•îg…UÔ“í.§æ)‰è¯ GÙ1þ•ÅœZÿ(HØ&¾0ü _U`´$>ßÈ&¾’B^ß°‹kß¼“ïïÉÎp)õ¥Ñ@J})¥¾•牖ú–2nâË)ÚJßÒèHà»rŸ‘–žyŠK⃅hÎù=sïdâ»S1ñ=i1eâ+yÈgâ+39QÄ×u }ÉæSè{7)²l²Ð7ö*…¾•,Iè»ò<ÛR|ìmýI©Û7Õõ]ú.ún‡¦ÙJ_Z¨Xê{ré´Ô‹=5,­¯lÄ{l­:NKÏð=Ö±) ïYqK}ÎE'è{ëØ†!¡º< Ä|wÚšùʵ R_MûK}žSN¥Ïø6*wqÚvXêk9Š,õÇ'ØZߓʙ‘/­ŒùìΙZß}ý¬õ!“¨~%­ï®©"Jë{옗ZßûÕ@¾hE8G­ï~¼Œùî·[e-äÃŽVãHÈw÷m*äëÎ@›È÷8Ú`"ß•ûJ!ß)F>°Oùzâ~žÃÐ+¯9ŒÈ‡¡lSP2K½%æ»G€˜{yq’ù[UBæƒÇ¾5B2ß]ò8IÌŠšùž<Ž1ó•g3ÞÅq" òíf|%Õ !”åòA¾U Iȇïä‹0¼Ç’ð2ÆúÙØF¥D¾;ãÉ%ò]=u¹ë!ꊰH| Äç#÷áËú¨}„‡µ½›’ë*"[cMª¾;AÇÀ÷Ø÷5ïIû`ßû5ÛXTÀ×ÒÖÀ×fZ~øbƒ­:¾(—øb¯&¤"ð=iq!Þƒ6>ÄaÜ™¼ÁÀ¿ }á¾gP‚÷Êeß{(ÇðIàƒ2nëQõÇÎóAÒ£€oåG'à+ûxAÀW®–J=l#ña/¯‡ñÅ^ë >˜ÓÛ´Jt·+‰‰Á!,4’ø°5ÔS™øzNII|#ïOÄ—V¾’vÇ&¾÷6ê¼xé€T&¾§¦©N\̆ùîá ¹}d'â+ûÔBćͰM/I|Ϻ~2óÄ ö•H|˜êõaŠø°ëÔG'âK~‰;J}B>ì¿|Pºï¯Üw¹CÓÌóÖ¶/‰ï±‡‰s¿6Õ&¾îìœ'ñ —ø†½¤ù2*!‘¯´™W"òá!}{C>¦2ò!,‡˜DȇõË:‘¯ôï• KkàƒFùh}¥ÛS8™oØE6¡XW@ßJTЇ3ªÛÊÞåSë£õÕL¿nè XûÚyÞ£ú×]*èÃ,$­ŒÐW2þqB_·oNBf¤¢’I3i¡ÏŽà }Íæp†>0Ð×Ð'Œ¶1%ô•Ô4Å|0[)æš[É|ØUÌ¡g½žDD>1KŠøî'[5ñåx5ñÁâ°ò|—ÍŸ¬<ñ®4`E|ŽKÄ€$¾ÛŽvÿL”°áõÁ?¸Í÷ϦžÃŽ5Vül®º?…•8?ˆü|ʰ¿•ÍJð»[jwüGéNþ{Ç¦Ýø¤øÁ~^p'é$\WîŠ×SÓúRÑžJÀñlv3$®žöl@((íôõ+˜*û €/i”ÄÆÀ‚ªZI €…3Vÿ…¡a=ù¯àÿ, >[H­Bä¿àmÒ×ïNmÖ¾~8õŸÈ×'ãó4õŒ3¹uÚzÆ œYsèl2·òõÃ1’ M—VªÜìIöÃÌy{¾Äá.–ìWO‘‡“Í“… v[õ#ûa‹ß?X·ˆ&„;‰[&¦Žol™¡‚ØŸ4*öêàwéê×Re³«ß ÒÕolàãJ5džB.Vkþ¤úÅÔ/x+Å«íÇÕÆ}–ëH€˜H%¼ÑÕ¯¦k]ý`áoÇ>®UÃxL€8_kW¿j ø‡·.'?¿÷Ѹ·Ÿ¶ÝÅ/ÂAɘR~~ÅÎNvóƒë•yp~™Dà%íáìæ£h³žÒ>Pôc&ë{¤?˜%YÍ#ý¡eíâìæ—&ìéæ×òŒÅn~°zýºù])ÓÍïQÄïtóÃP”HHúk釓n~+ûSô×ï¥'J%‚ØÇoøä.}üºߥŒdT"¿ñü„~-óŽÉÇï±M¹]üÒÖ?]ü°vˆ¿äâ‡ÈØöCë6·$ûáû*±/<"?b¼†ÆÇÇ/¼˜,ÿ-ÚðÜöÛ–4f?ø£õÓÇÏñW·_÷ÝØÇÐöa?œþÖü…y“Käã÷üdê‰sp½oÁP.Ë{Q#×Ñ_›¹AÅLv¤¿Ž(ASOøjµ—_/)–Šþà óQûwlYܻ處8-øë=O(ðŽzøëíI>Â_ÔÜð‡èeóq{, ûõÃö“ì'O½)±_o9í þú{—fHÂ_Ï š†¿þ¾ ƒá¯ã ¶þ0,«í:cIíÝë²Ø¯Wûýzs”}£îζ D¿>%Èèw¼¡_ïþÈD~XjÌ‹$¿ÞŸß>à×[Ž|j}Ã~¿ð³²wóÜ/éßBGòëu+„òï«WzüÉ¿oØ·Õ䇯ùÒµäà×¶BØ+û×5H~¨qÛå/ÖÓ^¼ÍI±oxõ4ùÅö!¿ÞL,üŠSÀ¤ƒÈL¨'¿f÷zÃFÄúÀ®u*~®÷UüУÆAÂ&*»ÊÉ/# þú|~‚?üÊÊ!áS Á“ð£ícé‰ðvé#üá#ëÅ¡üŒŒOôÍ”¬)öC×ÑÅ~¶È$ûõ´€K'¿üšÍ~ˆ*¨#øÃ#tÕ‘“ßî;ù•™ö òòkÛR^~°d9¿žakÓËÏ10Óɯ¥+ÑC«}}ü2—é¯×êV¤÷9¨nÊ}+-\=­c pd´Óá_ó}È}˜ÿ½xÿ¶>1üa2Î _ñ«JøÛQ€ ïzˆÈ‹5B@GË—\òŸ³ä¹nÍDÿÛßùÝ®å:çïþ‰(a¿»B–`ï¥çøéÿå(¹Ô#ñÓ˜ähÊ%GS*:šÊ’ÝT„B^ŸçvÉnÊE»©]r4_†ñiÊ%GS*:šÊ’ÝÔ¿SÔ1PóÛu-N#vL)l)ë_šB•<Œÿ!¹Ë¦~Wá¬Ûâã¬û‡í2QÝAÉ~? î «è©ûÝ蟄 výÔrS qjßÍv6傳©]ÉMµÜ¢ôj²)œMíJnꬕM)Èn*ÃMe¥lꨕM Š»©aÕâh*+eSG­?;z\ÓÇý0Œ~þÆ$«/&ÙïÞ÷¯c’ýQµŸc’ýQ½Ÿc’ýz˜ý"&ÙŸ˜#5ý~FüÛß™ÕÎZ¿Å¿oëï¼ìÌÏ/±:Ö£ü² zý_~üÿþŒþ—ÿþí81^í(ì}7ëýÝiþå¿Ë²ý¯ÿ–ÿúûfîzþ§·aG‡âÄÝ?þî.r7 Ö C w÷?þÞlOíùþŠÈï;þËÿ”úŸó_ÿ—wJyw'ïô—¿íÿüoq¥ß®ò—ÿõ¯ÿúÞÿú?òÇÿç_±×ý—ÿøVñŒðìŸóv îð‹½fý†y+;Ì[‰0oýFx+ŒðÆÿ9 ¸nåÛJßÅÿ†+ü×ý÷éVÿDH·kE€Œ¹¾gŸcõÅ_%m€©T‹’É}ì åç-˜Yå‰ $J¶î8¦ÃHÁ¦áÝü+# GX1©$\â"ü3ÕzˆÕ uÞ 0± ü»s8w§ ¼!Ü‚3FÀ3N'à µx—2‚ðK;7ê€7¢åçŽqs³bø‡Ö½(YÓæ(0‰zœ‡ŒûlÖo»†÷,B(4üÇ~ŒÐAX’j ú/ Ýǫ̈œ1)ä"†àu¨‹qe+/êÜog §àø¦V͹enœ¸Fn‘Ló‰ý,r‡ÝŠ{G~R$úX J‰×ÄãR"ÚZœÏËÛ¦„ËÎ* bìÏ0’z¤´8EÐë*µ‡î댤n] *PÇnáPûD5Ð;Žö"2‹L¥ÈD’3"ÝÙas$üfÒ#„@Ùcß=Ä”×y=LHÞ* sõ 9qBȶ†Áº)3tìÿn‰ÞétâèÓ¦aOœÕ²0O#x_—AJgÛ9³à \QçCŠOYÀ‹YR¬…Ç™#¤CèVbïÊ„ÏóFê^j\aptC”âŒ;¼knªð$ slEbŸ¤˜'Jœnk”8%}ÛQ´8Lj#ªX©ÆŒõ~Ÿw¸Å›Eˆ”÷û|ëØG`Ðh>ê°·0ÿàŽ«°Ã°³"ºÎàÜîa„ºÅ†ñ 9ìàÉWÑ]rYYG7Œîx°a¯ RáF;H84Pçý€xLƒYà‰:KÏ€„CÝ5šŽA&¦Þk9|‚’.¼%¶tƒx¡»¦mÂ@7u–#9" Ί:>y@Pì¶·m½£(JxœO·uàI÷6˜èÌJg½U|ÂkÊUl­€/ω÷—XLïŸÉ5ÓX½)† ßPEÛz¶¹Ü8¸â„€/ðýPïãŽh+wW¶<Âhë†>¨f7݈õN#|ïÇÛ€ØDÆ¡u$~¼% wö¶sñ…FÊ¡VYG¿"0Çæ!fËH9ô~¯ñ+þ(¢nƵ‘p(>X„rl¼‚ù¿U m²Jåô†QœºDÊ¡9Å…ybœ¡»šFäê¨Ó$<°÷¼¢ŽÞ]ä‹_ÅÇ9‡ðÁÆî;î–ø`o `‘s,Núâ„ 9‡âƒ½Z2²ዽy_(©‘"Jb¾‹¬Cøb#kÕbE½ã40îY‡:ßÌdÁˆ%õ÷œè üCI'"çЊ’KωœCøbq<BÎ!|±rcÅGΡøbqí˜Ã#ë¾Ø¡ò¢OŸ'&HäïâðŠ´Cøbq6›ŸpŒ/öqÅH;ÔЧ’-VUä…âáV¤Â‹M—ÄªŠ„Yê®ØÚ±ˆò–gåÛäS„´CñÁbk¿Të*²>qƒñÀ, ÷‡ï>ž N=ªt<% =RœšFâ!|°Ø@r À{ìã´R‘x¨vþ( "÷Њ:Šâ¹‡ðÁâJìÑB÷$»ò¯F¬®HA¥‡‚æ;PçY«+RqÒ‰Dø`n‡cØ#Mí(¸cyE’! IäÂ÷ú8·LäÂ÷ ‹Ç¸ã‚ˆ¿eÊ„ìC¨{‡ï«J°ÀF³|ßPëñ½Â^4 ÒèyÇ> ñ¹Â½éfë+²é#¯“ëk8ò±áÅõj~œÐGþ!|®Püo•p}…]gìÆ">×(‰Šüî¢#ÛaDEW~j_kDóç¯*××ãRëkŒF¢¸c9§ðl¦±aΈ8L‹î“¡ì>fR>’?Ìí`¿ö!¿n.9Èï"u˜üÞ/I&¿ü0}ÁïN¨3ø!»&ëü ÕÄ~ÀÜ9V*cßÓŒZ¢>¬eÊ·+ì{r£fìÃÊŒ±%J-ì+Þ{ ûH0söÁP¢œØW2Uš°C‡*êÃv\9ãD}#taøçú`_†U1õa«+õ‘é„}P]Åkâ¾ê½¨°/ò,ûF¤=bbJ4b„}#-D}âqP*({(¡oD¬%1V¨ iÈò,V( ôÊøëX™P23ÐV(Puw\·X¡€Õ½â>Èå׉}£ÛmJÔ‡ïe#,O((vÒêCŒyᰨ魇í±c}‚]œ†ƒ¨oÀº¢ØW5N 3ë´ oÌ_5V§‘´"èCÌÁbCÑßÈ÷ö׋¥ ›òîX"Xš+|XLНQ£û‰|‘¢Bº*¡6{rè$ó…óU;™/„²€Ø‡¹û"Ö‡dAbßymb_dÒ$$‘ú"C)_€°/"&²ŸÄ}¨#ôøÁ­«óÅ ü"ˆÈ~ПCWäC£ Ö¥@Ž:jèE ü" €àà±ÛÍ}æžÏÉ}3ÎyIpä¾`>¶¸%º”¸oÆVlHîÃñ‰Z÷!ë¨ÞœÀo˜E-ücTãWà7#ØC<¨Àf:: øÁ–@pò`¦z’$÷MŒ.5BîÃÙ Ûöá^ôA ûPE¯RØ7±ãákö¡DG3¾‰#ˆ©’À¾h社H§Æ®õáG4êôÁO·GæC[ê*1_DÐäó͈¥¡’.•…#MÌ·ÀEÌ7‹ ‰|3üwXƒÈ‡Xqw$>Ü­’„|3œÉù"_¤·T+D¾Hí(T#ò±;X‡È¿â0ò¡e-2B¾³‘i2Ù2‘V:ü•‘¿âÒdä›å„uˆ|‘óì9‘oÆ*Ã"S} ±”Fr=2 ‘/k4Ò[ ß Åƒ`Fä #¢Ê*D¾ˆÊÃ*$«HáÅf |‘Ö”HÞ›ö™6î͈¹·&Ü‹âŽM¸É OÚ‹¤||BÑì™8_™ö"·y¢=œ?r0í!\ë­_‘öb$σöP îíE2îI{‘«îæoH{¸R¬†=†ò„Ò°{«.ü#ì!¢×ÃÞ ‡Öyt„êIذ+-ÿªêõñý öð DF²Þ„Y±@“¬7»W ³bù¹›õð+¾m¡šÕ¨êá†}3D=Üž^/QWâLmÔ‹HNEh‡õtÂòâoÈz¸´:K¬7‡7Ef½È¤L¦$êÍ‘†P kL õ3ª¬õ`ã&« ¡^´ÃÓ¡Þ ›lÒƒ±^¯Hw¬ïI¨7gòIfòœøLz–ýuõ¢€5Hz¸_ø‹ôpeÎF&½é(Ê&=t ùV MZ$çŰ3Åy¨ÒŸ“óÐ/<`6ç¿çaŽ' ó"1¦ÈŠœ‡ÁÉ]¦9o:’¾1oFä]^‰˜‡f4^…yxý3ļxIº1/Îļ³]b^Ø]\´øóáÛŒzOLJë!Lêõa½ &Ô«·>†D=ôKz#êU{ã™ô2æˆI¯z$éa•`"=ø™ˆ1Ez<û4åmÍÍ”WÇÏò^M‰Êœ_=¥³¶¼—Ò†Aqˆˆ[âòª(‡¨8od†nrÞHD6ç!zŸdCrÞºŒ_=x…I5é-g9èa‡ôåDÚïÂ;.P𧺅€±@!nÆuê| NNjF¼‡öÙ}æ½éu.yo\žŽÌ{ÝÙ?„{¸’†¸騄*Þ‹<#l—¼·ü¶{#OãÌ{=O¯Ì{+‘E¼ÛyŽxÌ$}ܼ·²Í{8)aø†c`ˆ÷೨ÏGÀ‡wç‹“ø"5?gß\›ïH|µõ%>e“ødê?_DAé"<¬¦P뵚 ùÂÓàD>ìwØÃF¾!=ï¡ï“Ñ®¡‰F´·.“3ì-Ç0ëMÏÀF=Ž aÞ*9,…yÈ,¸NÊ[@;±)/ü%ç‡òÐGuDyÓXoÊ[qè ,¤„Öñ„y0æ_æ­Ë|›˜7¥óñ¦N)ŒxìTz"o=+o–of¨$úÑrHQ¢<øÇˆ«Dy3‰C˜‡—ÆWnÌÃóy˜åµ‹æáZnG˜·´°&åÍáý:)ߌ¶¥¢¼ÈÿH0 o9ÓšïxHCÞòœ”·¼ãÁÔã:¶ !Þº‹ß¢ã£QàáÁõKxDEdãaÜI$âÅÜ×NÄÃ<{„‡gÔ„/Ü´XGˆ3Ã¥ZÉDfòQ Þr¨^|žÄB‚ߊ Lxk&Šð–Ï Mx˜x¿"¼å Ú¼°Ï¼ðx×ÈGÀ[—W±¼5=8xïÖÒãC„‡îÇŠðâ˹OÂC.á³!x±¡Þ„·Â²Š­ñÂ3œ¸„C“ß¹oáHR­ñ0ä5ŠÄx¸²zO·"z Kyx&vŸ«¡NÄx¸”9‹Œ‡†õ‚<”èHJ‡OCHÆ[VcÆ‹,Âãd<<æ}Œ‡V4ÉxxÊöcÞ¶¬áí¹6MÏðâEhK¨ãNîKuÚ<%Õ=–·„uÐ¥úGÁÃ0OËÌ;Åu%õ ƒf;| ìJÚ9šìJŠ&»²qPt—A_ÒvÓ+Tšnæ–6M7sŸf¶Ûwl¶C t‚;X@}m7‘4°}EIS6Ýœ~·ñÃL‰xÓbÚnVo*Òv³J1J´{̈v·X¶å¦Œvàö·Ù͕Øó«ã¸‹í¦gÃ6ž 'ÀEéy,˜îöѾéîñä–t—ÄIw5cMw8¼pPdÒ\_Ö‡îj¦¶1Üõ ßD¶Ã´§+‰íj:Úí"°»AŽË’óëVï9±K‡#sëZ\ ëjzû‘êp¤¼>†›&l*ªÃ×GËLA]ñˆ™.,1ØŠ ®ØVNPÝ&Y€öý‹êš! uÅÉ“én3þ[ÁkÎñi¯ZˆÏáû‡çpb%~#ÐUoäèÒØ^µ}žõ; ‚ëÃsÕ!œŒs.ðŹæSìĹb7nËw-EUËw˜s¾8·ã\õ1`â\õn$q!î$ÅI¾ƒsq;å;œ}=žËçε}3â9|MôFžƒC)¿ó\ <©ß¡D²šô»æ Ç8×¼óOœ“ §Pa8•X»ƒë%ߣÅ;œ¨ŽÔ»°*b‰X®åLl–kiëa–Cê·úQïš_œÅ»æÐ¯ïš³|¥v—g"¹=טäšo[»ƒÆ%Ð’v‡ñÁf%ݵTîMs-W9ã\³dmœkíH¸ë¶Ø¢]Kå$E;[HoÑ®'dY´›ÖÅDs8'åö'5»®¡‘šW´¤9ƒÔ씇/Y®Ét7q®ùÄ3%»^܆$»x¼^'`´`—H‚]K‰Ì‚· [±«.¬Øuo¬¶b7¬šI°ƒ6Ø>$p£.›8ïìÊÅ ùêu©Y¯ëùÒëZKÕO,‡Þ–ï„KìZn7-Ø¡'ÜìåGíH°Ã·¨á†÷óƹ&¯‚Tìà-2“b×ì’Š~$À“b‡W¥[Ï! ‘D<ñœ‰ìp3 v»Y v±o;p.îîRÖÎì>ãÜÖQ-Ø!0™d¾–'¢h­ØuŸ´¥b×%<»æ3›ä¹n£YëuÇÝH°Û¯Î‚]¤cúvígœC‰îÏŠÝ~ Rìòø=%»jûH)vÕ‹@*v{°d×.¿8kvÍþW)ÚÕez“f× 2%;ÇàHÅ®%»[±Û÷oÉÏØ?’].ù)Ù5ïòS³s¨„”ìrmNÉ®jÃbÅ®Úo*»j9Ί]-æH võJ³Ì?|-ÉîŽõúKvÖÞ¶^§Ó` võg²ƒÁé:É®9МÁÃ%&Á.C>™ë®A¢ž¸®÷´ װޏ'çщ“t%Õ„h;Ö¶Í$Áû mövÈâ$#2D/u„À.¬²ŠŒ1¹>EÜçC¶ƒ«™ýöHv¡É<‡l7kÝ"V¨ÔÄv{ÒJÝu¸?ÜÅ£„;„¿ùøå…´#X’r7dô’Âݼ7Ê]Þ@Î…&ê´öî°NÊátwx’ïVî…w+Ó’îp$Ÿ@Âù¸åá|×&›£°G|½Ry¸—ç+ÖÙÍNy>NK±®n¹Qb\®S­ËcåtÉ+NÚl—¼r¥³œ|òjÛ¤ÇsFœ™ôVWì'§<²Ø'/ñí“wçéˆ}òöäg©.Y©CD!nŸMvKYv¦éã‡+ë‹Ø­mF:] ‹êêÏB]öÍS¨C[b#ÙA°H²‹3CúÖY¨kžy%Ô¡¿ž;œ¿[Ë›:gü±©];ÍpAux "ƒ Üc‹F‰t%íß-ÒEĤS¤[i».¨Ã±9!H\‡W$|±F‡ ÌGn÷·5º°N` ¹nÝ[Ç#×­ðdË予O*”F‡1öccÝŠìè„)*tûàÎ Î&erI°CH©v‚]œˆŸ~x+´þL‡ø'™ÎÖª;\[?$ØáÈY_£ÈãE™Åº'¹ÿë$&Y­ÃT‚¬\x漕֩¢¼ø%êmÁN `Áî±Ç@ v1‚¿’`÷ؘǘ‡ñ˜àÇå³äÞŠÝ•ú¡»´Ÿ¶d÷(}TJv0…é§d‡Uًļè¿çù)ÚA'¡C›4;H jFš]š„˜òÐÖßHyØÖ %Ú=f‹vÏÆP‰vOºZµ{ŠíðRµó9±)ï|*«vÍÖ¼Ríž'u1Év—¢ºYµ{’J„yñžX£h%Í»³h÷˜J,Ú=WšSnÕN«Ví$'å-™òb?ÕîIYԪݭ€Iy+MKS´³®kÍîÎwiÍÎéìÙ=i÷jÍE;ï4»ÛNšF¼-oZ²{RGµd÷¬´•d‡Ø"õ„<ì#ÍkÒì­œv™{ÂOÍD²²d§Èš)ÙÝiDnÍî¶÷lJv·Çƒo-c ;äãe$Ù=%m0)ÙÝÛTŒ7‡Þôeíݰ_ßx>´ÝG!—œÑÒþøw»–ëükQÖ~…,ÙAÈ~¾Ä9Jv²‚=Óø4å’£)MeÉn*bI·Ïs»d7å¢ÝÔ.9šÂ³|šrÉÑ”ŠŽ¦²äß;Ê’¾µ·ëþ¥(kõWQÖîöÓþeí-mT—ñžŒô«}sÿ»úyøb`>•ÜÔ æ¦Îjnj×RSg%7µ¨¹©3€š›ÚµÔÔY)›ÊjÙÔ@-›ÊZnꨔMeµlê –Me-7õ/DY+7cÊÿ£¬ý™9òWSÑïgÄ¿ýYí¬õ«Aüû¶þ|”5XïO9£¬)8Úø‡ÁÑfVüUŒµ_kkó ½…ß(kÿZP3lÞþÿÉ fïdtþò¿îb5ûí…—ùöQîÈfÏ?ŽlVÈ@Íf~¤tT¿¹„¾ë¡£z¬åÁÁ=Љ‘ÚÞÀZ›§òŒH#'³= f wàÇ®Q‘ǧð9çAÝ[¡»ác{ÓÈoàLJ˜ïó…Íâ°_$°*“¦(A¹‘* ‡Â‰£‘^)…§n¦ ÓE Ÿ îÞ—΄ý›6èÄaî¼.wsün‹¹ê6;”2¯8#f?E&:V]eUžËú6¯TY’¾"ŸÐ¼ÃZ]Y¹½„çDlÞ›4®°y!•Z"j3N0x¯Ö N¦»¯5ÞÀÂ…çK¥¶È`ˆèdd—H›²èë{«áa»Ãè…8;ŒKÚþ<9-u!(ý|ºïw-J!ÊǬáÛ Õf±eiÏMÄÊbDʳàKøéMÛ¢.O†"›Ì¢ø´Ôr‹ SB5€Z¨¤‡Ur$NÅa0&žšÑÕyˆ‡Uïv4¼€W³Û\Wr+\'KFÀls¾÷ãhøF‘ãE¦ÉX±—ê”Ø„¬é(‡ŠÍû‘î€beDêG3£¾ îï8¾‰ Ÿ$ôÒ‰|²ÒP¥(öOƒaËhJUðeqR¯[aŒ?œ=ºð t¥G44i|"óŽ{ Õ¡à A0™Ë‰ |€FÜ­V8t߃%ì†Y"„÷[¢8Nö4&sÝ2_/Ð[Ä(c#8[ †6ØÈ»²VDs²Îs¨ƒè*‰hM÷å9£{ÑÑÊdð¡(ál†ÓœÁ8g/Æj S°(¹#ÚÊ{¡¥ÎÅAMÄjÙN\:"â¡NU¨¥È´:Ã¥EVˆÈ±Ú@- Z$­ºÿ¾³ S]Ý^ùbÉd¬¶®l=MKæB A^|†ãè1ñYgÝŒÕf7¨ÈÔ#¨ÅM½®HgÅb Œ IiìfôþHÁÚVa ñH¿iLZù‘&¢CÝJÎüHŠÕ¦øZ‘!)bµá$Œ“¡Úúb|²HÔ;K"hR½Fa¨¶¡Øc‘ ŸpXy©Ki„|»Y²"-Ù[G‰‚"AR„jCÒ¨x*dH*“ÁÛâ{Š I3êLv 2$E䧸KJ¬¦Ñ1ÔD‚Ê )R$1T›Æh½‘>ŒÑÜnV!žF {ôC·]¼æy ù–=Œ˜Z+úsøVV¬§q˜Â"=ÒŒ )“$Ò#ñS] :ù‘ð¥Þ0‘fž'ÖÓ(yø£g1NÛÍD#êÓ­7‡XD­ðö"€^dGZííÖÍ<±V1"\a»=ÖÓûFêþjÄzúŽš®w€IN&òoÁbœ6¬ò,Á1BP)z-We˜6l5¢•Âx7ÞV|«°aÚ ñEÁ+ê}?”â#9ÒŠ./ÜñGv¤҆ݰ$Ôx¦Xåj¡l~#y«®Ý ƒ´Ùq¡"Ui«7“]E~¤®ÇdO”Ù¤­ÎŽ‘"©-Öá‡Y¯XQC cÛH‘¤î‹….2$E”¶Jù*$U^š\#JêÐô#ë$1Fg[”ÔÆm¸ñèâÚ c´YŽ‹IøT£„¿ê±¤F”;d!ERÄhƒV3–ÔDaÆ3d@=>ÓŒÑÖ”Ò72$ïã-#C¾ÔÈ4Æ:ÏÅ Š‘§) bExuÉR¢¤±™Ê%õvŠÊÚZ,©°TàoWTÄsX·øÖÂèÎH{„s…ëbª¨È’’—™±¢Æý³«Ã(>Ô0ÛCI¿¸¦ÞÝó’$ †Œ?o.¨0´ˆ 2$õ‡%œ5zႊtkE%\PQÂé iF–êðÊK*¦öwgê¾wÐxb‰¬2UÏÄ’K*$ N°}rIE_ò³D†¤ÁЄü”û⚊E&ܼ6jÜ\SñYršó¡ "TòˆäÏ…2;`~U'íY}Ú¸7¤ÁlÞslŒä½[t‰{©lóޕ͘÷|¿yÏ[ø Ÿæ½GÏ6ïY³ß¼g©dó^Ï:¾Ú÷>™lÞ³5­y¯v×0î] £{·ö„Æ=ØeNÞ¼qOžb÷žŸq#øúàŒ‡ØŒyo(ºlâÞp™ä½a£Êä=¤Bæ‹ïÁßžyQ°â‹3îG>'ïaK¬Ý±x/<ðU¼ÖT¿øPb âC+"e!ߎheäÛ¾þF> +u#<9ô…|ðöWoù®;AQÈw)—]ß{SÂ0#ÂÏ ç„|·ò”%ñÝ4¶0ïE¨§îÙ'ô‡ØOôbí…1•𴱟ˆrA{ó1ë öàÀ=®Xä Ê$ëÁ‚^#H¬‡’ê$Ä_B½í‹`Ô›±ga²Þ6+6ë…‡y9YTnú#ë…Ź‘¬-?'ëm£g³ÚÑ×GÖƒ £q¬&d"»ë·û0R7êÅoØ›@½0£Øu„«D»myf´ÛvfF»°k,!Ú…Å<Ñn;u›íº&Þ­ÐnÅîƒUˆvÑã±p í¢;» b E 7OÁvÛ£ÛlmpÛ…Ñ/ ˆvaÀ,>$ÚánÇIvh…;\—çB»´Æ2ÙEç>Ä-’.̨Én[øšìv|£mf v¨ÁMšÁ«W-]ØÕð™v+‰H`à J®ƒ9&s]|eâºm“j޲"v™ÙNBÁÁvEQyíêb·'Ùa¢®²s,ÿ$»6´û1صÜ*ìšc¶$Ø5Oí vͱ’ìhðþ òýŒÙõ;µ=‘]sì…$»–{j‘]û`ËGÆ+¾ýCÆ0ëzƒ]Ñ&Ý\×rco°ËäE vÍB„¹®Ù±#¹®éØ4¹[\v¤¹®ÑÂ>©®)Þ`B*áÈtè¡~jx#nêšC&&ÔµTqu-·„†:ÜÜ)ãÅo¸›6Ô5»È'Ô᡹I7Ôµ'IKPמTÿuøSP¿N%ºB]ÆÏ6Ó7L¦;ï˜PwÃ&ÕE+ä"R]¼GѱîxKĺ³ ±nß±.~ÂïA\·r"Þ窓ìâ5 ÛHv{P‰ì†®BªdÕTw¼iQ]\æ>©.nE Eª;žPTáž Þ~DA]´êÎÔW"Ôe0A]4òc#ÝñÞtᨥúDº£Ý~£º£ t£9Þš‰..Ãó !ÝYB¦Ë[Ñ$¢;Þ—îpBº£ „tg ™nw­˜.%ÈtѳϩÞ×&ÓiÏÅ?ÏSº‹‹°MñÜñ@ºcŠèŽ—,¢;¾U!Ýy+DºøÕ)Ý—"Ò½ ¤;/N¤;¦!ÝFº°ÒàâM¦;«êö3ˆêb ÐHuçoHuçoÚåSÐ$¬Ûó¬±.A73´xîvæå/ÔךZ<ù "ÝBFºèÖ}ùëTBºÝFº=†ŒtÃÉåEtÇý éÎv[Óç©ý·-O›"ÒíWo¤;odV ·h=þBl‚ºãW‚º=\ u{4ꎻÔíeÍT·¿kSÝžŒuÇkÖí±h¬ól`¨´ƒO¨Û³¹¡.žû: .¿ 3Ý^° uÇÝ ê¢¯XåÉÕS£APw´[sñÔ[Ô%„º£Çu{17Õåêc¨Ë‰ÊLw¼%1Ý1„uÇ•uÇKÔå",¦;žQLw6Rrù”ÐVsõÔ½ˆêöý êvO‰éöJn¦Û›3ÝY‡PwŒA]Ô'Ô ¨;Æ .Ç”îhWL·kÔ\>5¦HtG¿ˆèŽù£õsßa¢;žPDw|YBº½1ÒuÄtÇ¥u{'mª;^µ°n¿QÝà‚ºãŽuÇ# ꢄl=×P½%aÝ1ËëŽÖ··n}¢úÄuÇw-®;Ú×3œmiè'~õB–m–ûpœA6ÈÝÖßrÕáÖäªóO&ÉaÁæ ¿Q®Ê° I®®TErqœOøÉU;9&ɵ+KLrÛ¾R(æ{¤*¡\µ—Û¶Ê\6Ó”FG(³@7ä˜rtëcYGʉ9ü)ôÈUÊL’Cvq϶ȴf‹ÌbùÍ™ÕÀ’ ]¯¥Efåàát$º¹?EsSÆIs+í Ms8£¾?ݪÉw–èìIo“ÌËN=[¢Kã:eB6»NšCn>·2¯–ÊšŒ2/G®M£Ì+)e“y[Fµ>wÛe3õ9˜¼ÉÞRÝQ"în¶ÝúÜe#M t3yOÄívÒ\¨zý¤9˜¯ªk,Òu£°Eºr¥4&•΢‹U: ƒû¤¹&uºÇ¹j·N—©…º"ÙÔé m—“è j [§+ÚÇ¥L·d™®8¥pÊtÅFºVéjÿÉ"¾ðB+‰tÅ!m-Ò•™ªy.¢néBTé¶Ðh•“ÚH¤›Õ_—EºZ³Q‰tU)“R£«:OL‰®¦¾l®®4ФF—qHR¤Ëà)Ò5û¦H×ì˜*]SXé@“’%ÒUÌ[¤kW¢¢Tºæ´VéZÚt[¥s(‹tFcéZ pÒèšò°¤D×ܹ–èšã<™èÂùCtŒ'5º¦|/)Ñ5^Uúj]}®Ùg3õ¹æŒb©ÏálO”(}ΉSžË8jÖ皃‡¦@—j­ºž§ò–èºCE¤D—ÊqJtÍ R£kŽW˜]¦§I®;Žaææ’ú$Ñ5[Ë çvH°Tèš30çŽv…sÌþr⮤ãpá\H:p=A_tãœ3ÆæÂZ^&̡ĬùÒ®¡ÃsÑÜÑ+¢9´Éíš`.nU7O˜‹¼9ó„¹Ù@Ñ07{¾YÁ\\\Úanv‡ 3ÌEfšuÂÜNDc˜‹”7ýÇf¹È¢†Érhæ9a×6ªÍ¡†‘4‡f%”æ"‰Ÿ@8#=¥p.^mIsñHóĹ068i.Z1¼É§!ŸQ8‡òÒÉ„s¸’T á\üJ:q-k(Šç"#ž@·S)èŽZVÏ¡kdIœ; çâoZR’æÂ\bž4nüô…si…aš‹Û—”Fœ 3 ±yî½Ù›å0ëÈF,‡ŠXîˆb¹È£qŸ,‡ÉLb¹£ãÄrè¦Û%\=GÎL¢¹xHQ"yO Þ'Ïeb㮤Ù8$ÃPâ Mnžl\äýdš‹|'ÌÅíæpûÂÁJ4Æs¸ÒG¢Ë\Rf¹¸Y~j‚¹HRE»wf­â…ÈrgI—ËååðDÖìåâBº9¢:Æ(‡tC†Q¢\¼“ä¶ŽI.R¦Ð8“ ‡=Š"ZYB]ìN®KŸœäº´xK…îòN8ºšúÛ!Ñ}¸®ÛT$Á®Û"Á®ç¹­Á®3hàèªMôŒuSYÐMuór€.SœÊlIªÃþ+]ëba*¶Ø0Úao¦Ç&ÚíT&f;|Öñ^¶c¶ þ‚lÎVõ´¾„Y‹´'±]Þ('Ûa[dµì–õÈÈ_îvÀÃâñHCÜacdÛJÂÝz—’©kîàeG9ÒÝ‚ÿÅ8éîÆÖGíî»§P$ÝÝØétj~Aw7ö5. ƒMèEº G#ê„¢»·+½Â»·$Qxw_N[m¼{KòÂ|^8tsà…÷D¾ ÿɆÉwá”ÑO¾{K*S½ðîûn_ Ì0¯—õ'ï}ΘÀ6à½×êò±à…»ÇEº›o_PD{ä p+ňøîFœîqxap} ùä!ƒöǼ·¤ýö1Ä|wo“nC¼øqº‹lð¼Ô”ƒÀí‚%[Aä xáX2û xÑY÷ xáå Ì"á½%¾¶ö?6ß…ßA¥üF‡;˜¸¯“ïÂö çä0ôÐv¸CØBzwïÞ{­®@À»±?¥‹˜/îŒ})‹[‘Ñåe÷Úè§ÇLý?ˆ·«yÜápœÙãKäqw#LÔMxáÐÐ>>wÒä’ßäs‡;)ÊçîŽpÍ?6ã½7X~£H—»áRX —»ØVÿHÄ‹Þåé‰]îàApŸºÝ}ö:u»p·h—»‡aç6åEœH nr¹C $ýJ>w¸¿uêvÑ¡BAùÜ¡CEmò¹È.T>wÑ]vô¹»—\%Òçî^r|LŸ»'RoüHØ»ágßåa§0¸oŸ;夑}îër~|îÂå‚uäswÏÇÞ}rºC/ÏöÞû»}rºÃ3°ùÜÝkúþäs‡‡âÆÖ>w‚HÊäs÷Üàí›önÄŸ’%¥|îðXë´ÇŒÇâÎ>w71‹>w÷œ¿É>“.wñ²†\î°¡å…ìrta \îXÁëOºÜaب‚\îîwR*§EfÜ¿<år÷<·J.wò‘Âäs‡¤åës÷~åÇæ½¸_Ihò¹{pŽÉ:rºÃ¨¹y)9Ý=ðÇ>v9Kät÷øP2îïÛéw宩q[ñ½pÓ9îž²~§€w,Ç<9ÝaHðnìu÷\K>Xv»{"¶ÓÍ|qÇt²Ûî˜Ýn·»çñça·; ›õq»{ì{Ÿnwxóñnô¶œþäv‡@1Rìn}¬õ7‰z±¤â=Ó£N>wØé¯E¦œrºÃ¸Q9Ý=OÖ‘ÓB±q´Ùé°Nê‹×À÷b§»§È 8îÞ–®Yöº{ª¶-éu÷ÈÁ#îð^xšc§;¼»N_89Ýá-<„+9Ý=OI7<.«Ï#Gðôº{ùO¥×>ú$Êënv»C‰ˆ2~I·lò»çRH·»øüN!/’ãÈnwág³ß[§écµÛFŸÉžw{¬ÙóOP?žwxÊGÚWV„›ùHy÷!)lü‹’~ZhÆt¨väz‡°~uèz·çY»ÞáÑOþ‹ßØd“kk¼Mš_Êõ½3>®w¨Ã©8]ï°=%f$³ww¼¾1szêG”—œÉþøw»–ëük‘Ì~…,Ù¾~¾Ä9Jv ¯ðûiÊ%GS*:šÊ’ÝTG€çûóÜ.ÙM¹h7µKަ†‚mï¦\r4¥¢£©,ù÷ŽdÖ€o×µ_D2»ÿ8âØÏ‘Ì~’ìß%’Ù¯Ä ô3 ÔÏóFVœ³–ÛÚAÊÜÖ¥ÌmíZnë¬å¶v”2·u†)s[»–Û:ke[¦,Û:â”e[Y+Û:je[§,Û:•e[Y+Ûú™!|#ÎÚ~Îìù{áÌ~÷ÒÎìªýÎìêýÎì×cí÷áÌþÌDù«ùè÷ÓâßþÎÔvÖúÕHþ}[>œYCpå±Îpfÿé¯ÿ±‹¯ò¢ÝÎìú9°Ùû¯»Þ?ØìßÞˆ½ÛþõÀf _λ<ÿ2°Ùûfÿ÷ýŸÿ1ÃŽý£èfoåÿë¯ðmYsÿuüó?çì(üO8Úÿ~ȳVé…s”Ëtzç~+8S;êÙ[ÇÚph§óöW‡ ;‚8Pi/t……Üc¿¹w_»RxeЂè-Y˜àâÇæ­2ZD¤¬XüÑK50‘+Òq[őڊ“bÇ¿%“qHåÚ*ŽAÞ¿·Õ„‰çÑýÂá3ìe¨Ÿ½‘Žö?Te[]‡Ë·^ßmháá²S'¿Ê%º-7ÜÀ ý8KnÁ@è‚g¼-ÖÃÁ¼ªSã f4Ý%“çËM­!és_Pák­Ç¾¶-4y÷ÅW˜ -™†¼3¬ä–-”Z›ð(„Ãwüõþö‹µŽ“fS§Xó–ÌÈȧì8ƒdruž¹·N·o4B­à½¯8ÎB#qòð·†!‰®ƒã´¶&BTdµ>0–œV-­#paºÅ:3ÈìTê­Ãgµ„ÍD-½½VCUAúNŽ©q‡^Äi lâ¹ãhµÕ0lZohÌGJfúc»ÈîÜv^¿{®3ÉMŒk¡¿ñ'˜jh©Ê¸©z^Ä‹†¨‘#Û™ ¢Lfù¢¤Ñ`Ìf –Œ¬™Æ8<ÂL•:µ³'=w¡+ž›V TO:¿y®ZØÀÐ4A8N£ñ=žs¥…ôÏ·6 •yå>©zZ||á콉-q6ȃº¨kÀÙZ©Â]2-zj Â?õ¾)=rÜÁ¿³1˜&¡ð±|KŠï6ŸÍa©[DĆðý!|Zûmò6ËÎiõL|žaµ_ÁB"æ+äC-Ìk›D´5¯ø8»³ð¾%ó·{û×·µÅ‡³{?Xö§_8Uh‡$Þ?m݇ôØ ßç°¡W¿ÜáWù€ÆŽeø>ÇÒ\÷–D04x໢I缄¾£Ö¾ØÌˆž+EG€ªVŽÑûÎ/•º§“¿S`œZ‡qI1²­ø¸É"„O›ôÈn´â©¨‚÷ÈnD…˜kPG¬¦I ±Gv£v$€î>)ªÐà¡Gz#”xXuIsÚS¿G~£%ü,:òU ˜lfÞŒ¶8õuuä7ÂG:ž|„SGÜM|oÇJϳëé&ߪܱŠâ)Õ£‘ÞhR½åÝ<%–ÑH ÄQéV<' z¤7ª!$R¦ëÈoTc pé‘Þ¨Et=ò•ó¡"½ª4N®ÙðÎ"¸Gv£­p”›b‘c^ÙzCàäÚËëèd <±Œ"§úŽìFøL¾²Gr£¯ŽJhGr#|¥C!zä6šçC"·Ñ` ˜=r)ø/=¸ˆî¯#²1¢‚înq!Ùã˜AñÌä‘ÜH¡'ØuÈn´8dhdÔ#»Qg§‡u®¤SaS{$8êQ ÷ˆ Gyÿ– Ü#Ãш›c¿ÔÆ•tØ<¸GŠ#ŽÎ¡fÆÃüRvní‘ãhFÇèÓ@–#%˜âˆ‰$G3ÖwÚ˜ ý*iG Ó¡Ï4r5¾àt„$G#:BKä8jñš䈭Ù(’1N‡K×ÒYý–"ËÅûE’£øJ§ö7=²áÚükr•úH G#Þ\H§³\÷ÈrÔ9 UÀ…£›ý#ïü°Âø•“f!ú~Æ?èìD<¼­ñ"k#ž#%ã9õI"Þû^EF<$*Eñ»h#Þ­]½ïñÞÏ„÷ÔÄB!Þã€X‰x™:ÄŒ÷ØÊ)'í"º@¼bcÞD¼¢o9 ¯h¹HÀ+¶·JÀ«’¾’ïªbI&ÞÕD.Ñäðù¡»æôyIwÍÃ3é®-ß‹à®Ûß-á.Ì@pדuw`Mõ?¨É‘eÀjrÓ€‡øibQ¢¥i_-ÀÃ!W xàÁ„/ü,Äf$¼pàà.Z„7–-”x(1’ñ‚_ø”b¼±d)jÄäêdAˆ–º!Þ%ƒ<#^T):.L—]“ñ®Ç\HÂ=ë¡Dx—CÀ%âÝÞݘñ03ˆÎÄx÷“H'È»µŸHÆ{”/<[þDˆ‡46$#ÞÓ|ÌaÄvâ=ZiñpS>ˆ÷´Ÿïñ7á!…\û ^¹’½„x lá%¯JßJÆ+ Éxe%n òªS¼'ä³JÈ«„‘iñM‚¼ªì?ÉxÕö{ÉxÈ.«1žó·&âÕAé> ¯æÉ˜¯:ÊJ2^͹Ë©ìXG”×7Lȫݷ+Èsîo2^ºL$ã™,ñšßñší¶ñ2‹u2^søÂd¼ÌˆžŒwÔãežè yŽŽ·!Ï6³ yNÝŒ—ô6ãù¬i3ž}ç’ñº{&/wÑB¼î,­‰xm“"O )¼ëަŸxw4!¼ÃLܽé®kÖOºk+[Ýõ„lÓ]Ìr†;ò%ÝõÜå%Ý•ŸéîýU Ÿ„»îx wÝî" w0õç¾Dp× 4á®ÛÐp×eR”l7œ,=áNì'°ãžÝP—öã u#‡—¡näÕT—ü›êžŸ©nò¤eCÝ*6ÕÿÆPw™êj⣩îñ&ÖT—=`ªÛ' Aué’êÂÌ>‰nØ4‰²ýõ!º‘ƒÀH7Ñ*‘nw“‘nlz4ÓåiB2Gm"Ï7Òe'é`ç†Ít²—K¤ÎQ±™.©™n$ié†r&Ñ Ç<2Ña ÄÑ §ÓH¢ë>üO¢ÃQ‘îNH×íé˜H׿4©+Na]¯œ‚“êº=â’êÒ!!©NÜ$ªÛ×5ÖuEðMªÛ7kªK? S‚6€Lu¨Ø}.z ñDti žDט¶4.=º’èš}U“èšâ&Ñu;Á&Ñ¥Õ&:9&Ð¥»VÝ>¸3Ð¥Q]ž·&Ða. ë×Ï@×=-˜çº|#ÉsÝÎÉs°WžƒUÍó:û%Ïu/µÆ¹î\ƒÉsÝçÉsݩߓç°º¾i­–L†B tX%Šº¡xµÉs8&¾‘çbÿ8pn\ÞW‹çzª-æ9œ‘ tÃçé:äZä~Ý@7íµ’D·äªc¢;À@H©Ø)B:”ˆúHté”m ƒ+².|‘»pDw¨4BºC³^÷´”!©Ù!„“B§EÉÑj¨Ù5ͧbW§úÖ‚Ý3S5³`×~ûàÜ |b˜;Oè©×¥Wb vÍécR±C¢õQìjÉ{%ÎÁÞû‹s8Ôˆ3ÎÁ —¨`ÉnÔ$1ñÜØâšx®+4„y.‚GrÄçTWÏEHX´x.’›|4»<'Ožsübó\$R+º•R·€.Àšç@3ƒ’—pn9ÚGâÜœf*â\D:%‰æ¦ãŒ™æ`=ÿ¹URÌM»º&Ì­[3¥an]îmÓ\ÜôIs«%|’æ¥WI˜‹ö¶`n]Îæ0·î anÊHrá@ÉŒ ±€Ç)Ö!-»@ ‡¸¸¾ Iɧ4.Er(áœ&Ã@Ð “@NTíÃqSA:ÄqèjYä"œ° éám3Oµ£@+±P7¢S(‡çÑÆÂ(·ò|\(·c‘åвL¡\t©Q$·še,“ÜrüÇ$¹™{b‘<Ç´+Êá¹×IrÚ«ý¸InyI’[ž´å¦ÝÄ„r;æ­QnÙJ$‡‡Ô†J4‡8ÛÚ!šæ–ri$ÌÁÕì:µ: y‹ævvkÓ\$þÐæÁŒpCFu„sœR „s«ØaÖ8—Ù—sˆ—ª¼p.b—çðµøâsxnqºp.2²÷C«CÀ]¤‹çð˜ÜÜç–’bl¤‹1}R.4U0™Ï>wx‚ºˆ+Kø"ÓeŒ[#®£—˜ƒ\¿!ÓÅ×öc¾eã‘©ÞÔ*‰#“ûm]Dέ§L·îÇò.ž/U:\„M ç]AH‡‹èq…t1X y±z""5¯"¢ÃÓ ëEt«ŽD1F†^©ˆnç„7Ñ!o@wŒS]Lš§D·b×ÍK“çðLbòÜÊ<"æ¹ð½NžÃ3ó=\:SÑa ׂèb¬?§FA Ÿ“èðE«óDtxñ|º˜šYƒ<·jJŠä¹\\spæQò ëM<‡ž2J‘çŽ)SL‡®Ò×*¦[Úyo¨‹k]§T‡™¡žP·ˆ›éðHš‚Èuø6¥Ø‹ë" ô<¹n]'Õ¡MnmMu±¼rÞ0ÕevS]„0N}÷|tºÜT˜êðF’á´~:\©%üöu+m uñÔêð7ƒm_Êùj_ÖlXúœœ­Î-E[IqnÙ†¬+O­¶ F¹Kr—|Ë’äàÌÿE¹Ûg‡‰r·¼Aå®™––$¹XÅv$9ìWû‡äîjf”ée"°9î‘ obܽ’¿„qˆÌ/Ja\ÆKŒÃbDqL†—±‰80f nE²\ñþÈWšwüƸâ½Nb\)6×”,Wœ–9u¹ÒÔSÖåŽ I—ƒK÷øèrEIÖ’ã"y(qJº\u|¡$¹zý؇Fùý¤&ç£SÜVÁLqÕëAJrI=¦¸šÊ®(®:FüÖäV|J“kû¥É5ï€ãZ±©£(ß;7í.ó˜(í.»§´»´H”¢\³¬˜f—·y6í.æhkria†—·OMNÖ åš˜·(7S UnäŸVåš¶^©Ê95ÂVårß›ª\O¥l«rÂ4‹r¹Â¥(—'Ž)Ê [±åÄär»™‚œ“Òm«ËaÕÑ‚\÷Ò{rºÿäœ|+ruƒ¹'$E®o¼’"çÓ¾­ÊÑukrÉ$5¹|)Ê­4Ë”*×kÞT¹æÍï!Êév­Ê5{.¤*gÁ6E¹öüDqøQ;)nFzè“âpÌ­V¬É9æIjr6‡ØšÜó…¸I¹e²(—QÆR”˘])Ìí£o‹s™1<ŹçšMì͵Ü+Z›ëΠ”âÜQ"u.Öz^\ê\ÚœYÛ–ÄVçöÛµ:‡° $D‹sÎ,¶Õ9 =!Îõ´³8×tšú\wzë­ÏõTѤÏu•Zž Ï*þHò\ÆQÛòœ#ímy.éûçÆWžsž®”ç2˜VÊs] ü¶:çsæSžÓ9JÊs—¶l[ž+i)}.GH tÅØE}3 [µ<'ÉâÜP쥭ÍÙvÙÒÜ|*s˜Ž?ÊÎôy[¶·l© J™[!³½¥ûÄÂb>Å9àÅø±9.Za#Òæ¶½®µ¹éX§Å%‘4‡4¡Ÿ .WÚdJž[ R[N.˜úÜ*ÒëÄq÷´]"1ngèÚçð£‰qwž+%ÆUS½99Å®:·¬¤:‡{Ò¯¤Î-Ÿž¦:‡F2ä4È]‰•¹4i4ÈÝþø‚ãœcls\I¾Ç]#ÉNêܲi]Ês+‡‡IîÖ¦Ó(‡‹qF¹<,5Êݲ¿Jun* Ú?ÛlCáþï‹s6ìÞâ܆1‹s¿ƒ:Ìx_Ÿ:7l_qÎ;Ôdº´tJî²Ãœ‘Îú…‰.äàÐ=fÐèܪˆÎ>>)Ï=F<«sÃ>U)Ï9ãnݲYƒ‰ÃCø’úÜø•>'€ã²”ÙESŸ+)¦@—"‡ºZÓNS]÷¤ÄŸv2]ÄVÕ­—Bx"Öá O]šý$×aÕ)°Kcœ$»qå¯Dv6ŒÙ]MÓM‘JäÎ'´ÛzRh{jv–Ñ.’íF:LîàCˆÜT w™n3án**U²Ýô’—p7¹ñ3ÚM½šìÒÜÞd7gp‰.aÊd‡[éðÈSŽ#í+EvÓ¾#Ivl°K+í­Ð9Di’Ýœ¿ýäT7‡EÓÝTʤ;|BjFx—‰wûG©ÑÙÔ­R£»ÓSt·”O9án=0†;´ÂW]ê³[£³ØmºÃJ(Ü#ÜÅ—}êtáö¡:‚»éUÒÝ´wNÒÝÒáoÒŽ]$݉îœ|õê¤Ø îfNȦ»u™ºw¾H²Ýò‰PÂ]j¤ wËn)Ó9{^²ÝÊ-…án=†F±¼wÚ‡íÖ•ÚžeºÛWÞíÑzR¡¢»­zï2-ìVé.íËS¤KW"ÓÝYt·R3Ý-/îÞVµŽî–§ç-Ò=Yb•nëƒÂ»pwÌï–¢Ö$Ýag"kPáä{‰i»e/âÄ»lÆx·Ñ'én=_.ƃ0Lt·œÝ%ñ.?%ãÝ2Æ»=¬„w˹æïÖ“V™Â»%Ÿ„¤»åÝ‹áî(7¬$Û­Ç.mb;L€¬!´[N$’h·oÅhç¼ÇIvk»ö íÖó3Ú¥]C¢ÝJáÔl·ž´ Û)æÑn¥kŽÑnß›Ù.S 'Û­Çì$´K[ˆd»•ž“‡7Æ¡Ù.g²d»™B—Ù锥 î`ÂR>ît3ímÓn¤çžè§Ì_ãË9LH‚»™ûsÜÚúi|¹læ²ýé¦_®ýézl:]y»Ó•/à¡YVÚŸ.ß[úÓ¥AúÔ5ó³!Ï»ííS—¦àf¼y'õÙ§.݆ӯÎi%“ò¦3ànÇ:AoÌSØö¤¼á©È˜7ÓTÕ˜—¾bƼ™æ‰æ¼ÙÅy#úÒ³.—ƒÃ³NÔdÇ:FÞŽuÍOi3Ìé$,Û±nü¤Øáâ:„KǺ™4hǺt²LǺiI×v˜¹y9ëøU¥_]:ŽÒ±Î‰ ·cÝòœœŽué>žu^Ó±Î™Ž¶cÝÄhϺ4EHÏ:mϺtÇ3ê9ƒúÅl´k~CåL„ë©àŒEö‡¿Ú•\å_ a6°Ã™ç²dGørÑ´Kv„¯áš?÷ê’Ý”‹vS»ähжçS³àhˆ%G;.ø÷Ž9†lCå}Ö#æØÏ‘™þ^±©ÒÖ³Âïþó~XoÇ'{KŸ?ñ3Ææé›ç÷£e4†<@ý4îÐsغ긥VÌ-aÅÔÒ®¤–Î:nisKgP1µ´+©¥³N¶”!Ų¥#¤˜[ÊJn験-e@±lé(æ–²’[ú‚ŽÁ1t^íïû)øWûeD²òç’9ÒØÏ1ìþèb¹ì"ý‰Éìo¿›˜~1wýí—Cöçùì—Cöw-ýù(cÞgig”±3(د‚†ý[†û{!ÃV{¿ö¨Xÿòß¼ÿúnÜÞ•íø×ß3{Ë~ÙÌíf.‡ [ÿz²8|qéÿ½dïtõ«doñ¿ýõÝ),tì1Oþ§ûïNs‚l´;SAê9æ¿ÇÛ¶ÑJ¤ò×xìþÞ‚1,g¸‡­FÒ•ñØ ñÝÎ<Øcýq3pH¬á¼ò L¢ÅZÂÀü·°¿áæe4ì8~`ÿÄ]Æh°‚f4±ÊVa¬:ÜŽÆ»L,v<£ÓOÜü¿% ñê#ñ2 Ðw÷á®ñî½*z|¶ýNa¶ÅÜØ¿%\«‘]¾±äýÇ8ÿuÌÑqøÅdq"<:v—%œ-âdö-X<ÿ:¨»þ§¹n7<²™×/ Œ¶[xŽ7þ½pþ;šŽÿFÄ”S…8ƒ8Â=ƒÛÝWÀ6Z8#ÿ ‡ßÒ“žiËÖ)ßY‡4;F上ƒä¥v¹ý‰ƒdø‰ø‘Ë%|`‹0ú‘sxDíIóþÞªù÷¼Â²®"ì8fî;ÄŽœ¯3éÇ€›ESbØ”¾×íQA7£ˆ¨viPB“_aÂà 鈴_й¦&!êŽ:K—ANÆæ8äñEîpM¿ØÌ !nºÉyÉYúËÅ„ÄÝ&¹OxžmFXÒÏ<öuö¨àÖÇp6`û n}ìë2`­‰<†Óá Ø¾†]Oó‹]È’V poÏGV ôá­_!–W ¿âÏ[2²Ç‚ï[ÃÁzä¼U§8få°ðÂh &’Tú™Çè~a¡âû„?;ÇØûþžÈÃTç-Y´ë±íÏûR {l04¯H©Þßâ… /…aãŠJ{äÓð3;a"@]g_t"ç÷8¯y3¦Ú%}K"þ}X)LÞàê®™jn"§=Øõ÷'†a囹Zšyÿ: žNãžÊ3ûwøTúÛOÎy5dÛCŸÈqÑdE=s·Îti±7‘ b9sÞ;Þ"*|Ø#Ä€žÈ«0éÉiu"-Eö,͉Ðûƒ~æ<€Ÿ Pé-9¾?ll75þ’ήEtòÆ`t<Žx‡Ÿ|y*ÿšÔfdT0‘«hô:#UQÛ^Â™Šæ}ù32×&2…2#IbF¦"¢¿z™Š:ítókR—qⲉDEMÁ‡xó‘ªh¸=‘ª(N•d?7#UÑ<"M¤*ÂÇ9Kþ¨>4PZ€™Šê!‡ÌHU´>%½ñTÉ‘Ò&r1ÒWgkçNM4‘¬¨ñôjð'«æÁ/ßréP)Î*g¤*êáÒÁµf"UQ¡$AƒÅ©ŠekV)Ï}/­,fØ“u%$¿¥‡¯Ýª¥®Ü³öX=CâáHŽLE´}µ`"QQœüά‡ft ásWÎF¢, bÞ^ä)jáiÁÇD¢¢g[-ÏHSÔéûÄQ…4E7 ›9#KQKs]¸ÕX=·yôŒ,ElFãiŠõp7Ü;mÀ³¯¦h²N¬§3²ÉL\÷úU˜ èóŒ,E3~Dj"KÒEÝòªš‘¤ˆ–Ó%±‚®[8fd)ZLL—Ž$E-ì!š~ùp/­f$)jaaÏE°‡±öâoz¡éÀð”ŠEƒÝYTK(<½ä( +p8š]ê¯"6Nd(j4Þ`¯ äÂzü‚œ¨†„&mä&ZQAW@4Ür²æÒàRºEÅ™šh=vŸž‘H=c4Ò™™Æ&vz‡Ãájà s„úº „ó&×E߄ʿ£¿æ¾n"!Ñ¢ÿG v*%ÜÕû‘ò,|œxd>‘Žè ½°IOÌbÍvÂ:öŽŽÑÌ6Cç…Fè«´Þ&œfØ|CTÔCGÀ‚h ,Lfœù~î2’Å6„yx3FZ_˜„54ÏÄølgj1oÊŸ@Ýë:Äß{Ò¾¸«%ÓljìCï}7ešÈ=´¢>Ocæ ]<<øœÈ<4é(Ä_„ª»…\Mð@§Û¸d"ëÐ{ÛÎ,ï# ´Gù³±Ä6«MLÅ?¡wª [þ«9$Áf5{˜nVs°‘„5’›AÍÚµbKÔ j˜“ÔŠ:f“šü6©iÝKP{»ÿ&Ë Ô`™»Ëµ¢´AÍ26¨Ù×2A­Ù¤"A­9ßú&µä£D5 „Õl‘’¨ÖKò‘X-ò%uHk™Ú}ÓšC:%­ÝYE´Ö×Ï´– (VÃ!jt–QíÿîîmvvÇ‘e½¹¯¢§ž,Hü‘Dø*ú NÙØß?¬ÈˆH¦¾®êêê½mlÔZ/—DQEòaäÏ­àÀIj·ýÈ’ÔObIj‡ÀDµG‚f’Œ>n±YíÙà%Z{ò+qí¹ø­™ÖpˆÞœh Q˸b Z4r¾2­í„òÂ5@¢ë ®U*$®5Á‘´†½FÑJ¨T×pc¤ÑÚ½:iíbÖÖ›'¬ž±’ÖŽ|¦5ÀÁüÐÚ±/%Z;œÔ7iíMeÂÚaù2a-ÑV¬v j‡-5jgKš«2ÕIVK‡–„µSŠx²Ú)KDµÓJe¢ÚyynTCn,NRFµ¶9L¨Öìmž¬vÚ(Y-è³D¬‹@%Vk–“՚ݪÌjÍÒoÂZBµa K]. kÝJoÒZ»~ÐZ“×zÂZ—õ_²Z[Y‰XÍJNâZ“yOҮƛ6­uº&­u;x'­õÓS—‰­;Î][Ò± æC\*4qùa~#±uÇi3²õn„±u7ßĆȂ:ÛX‰–"¶¾¼0²õäk#Û8ò1uˆuf¶‘ˆmfŠŸÈ6”f>‘-£·'²™%B¶!Ë×D¶i¿—D¶aCõD¶‘ì.dŒ‘Ä6~ÚÄ–±æ’ئ­Ô“Ø`½ÅÆÙ†XÙ¦× ‰lX˜“Íl±´Q ™m(Z‹‘ Õ°kšØà§3Åg$6$ÈÂ°Õ ‰Øæ•4Fb W~³&¶Ë!.El;î‘-=&Dl‘4“D!dÃ&¾ !ÛŽ6gfÛAÝÍláã¯VÈÑÏAÜCOŒ“ïMÀfãZÄjÒ䵘›îÊk^‹£’x-¼9ñ†¼†HĶƒŠØÂSé)ÄVº)‘­ôd"[Äš¾ ²EFyQ_0Ûº÷â…%¶]M. Ém ±‘¸í¾Hl··Ûn¹$µ=gjn¢6Xe™ã‚Ú"9+k¹=-O"¹…ÙŽ8äöôlÉíqh©$7xdÈ }CÌ%t{Τ'±Ûí  ÉnÏñKð$t×K®4ºå]›Ünot%¹ÁêüÛŠ”Éíþ‘íöÞÜٴ÷E6'wÿ'2›½fܦ˜ÖÜv;™Íæ¶Ma›Ü¬ ÝþAe»½©–ìv+fn¢Ûíô0‰n·“ݰ‹-°»m¥Ðì–)’’ÝÊ1‚·È _¥¶]Í-ƒ€·Ø.ÿÀÛ­ÍF³ÛnœÙížY…Ø-#d'¼ÝÖOÍnûõ›Ýnmæ&»Ý€dv‹ÆR”"»áé‘b·ûvÈd³[yqb·òâÄn å"7¼þ&·áÓ—R(pî•à†çï¶¹¡@½Aè†jÜD·;4±\ [ÔRÑ-šÂ¹XèÊ荒E53ÂÛ®ØðVKo÷}þ€·èŠùoq­Vá-šÝP YìvߊÌnñ(Ϊ³íG!vCk¨Ýâ™ ²Ýp„YŽèmïÝ""§*±[ˆð³*mõÒ¤7Ô¬)PôV¯E|«ÇßPÂ-_áöƒÖUŶr’ðmGz4¾á5Gø¶…ð-6šxDgû…¢7œàJƒÞbªàߢ%]úÚÁt_—ü%~‹X :‹üvG ÚÊo÷›íâ·û–‡Œñ-žf«ø¶çRó[¹ÜÞM3À•& àо\¹s\\<Cü¶ßñ­@~+¾•Î |+ïUø¶ß™è-ÔU7¢¦‰ÞP¢¾)z+OÁ¦¥»bÒÛnè­¼6Ñ[˜¢¬ª·•o]øVªyÒZE¯Dôý™/€ôvß hx+O†ôVÞèmwÁ[y­‚·\º*¼•G%zû”h"ÍöŠßʃÁ•Ž'‚‹kI¦{£nòºüªf\yQ"¸èxO•ÜöÀÅ3‘RW®D€ qŠrCSiŽ¥¸¨õ©’[yæ¸Òpå+À•Æ(ËE¾ò[¼Û-º•«àâHC €«5À•¾K€+ÏšWz!®´œW†Ü~ª÷·¿‘àÊ?¿·¿d\û pqUvÛçàJ—'À• …W^ îÎ\?"¸2Ô‚àv£Hp¥—áJ'%ÂŨKæ „+}€ Wž4n_ƒé©GÝÊ5ˆpåÝá¢ÎÔÜððµeA„+7E„+™WÞ%®¶2®j[Æ JµÍd&ËHÇÝ–‘NšZÛ‚µ¶Û›Å–Ún‡$߯‘·w%Ó8Ò9RkÛ&ˆÉíô‚,µÝw¥6è眭µÁßúªbìÍ|a‰méâžbœ¯ k;%bŠmÌÕ‰m»Äb›PÇÆ‘Þc·Ð†E*š#m#’JÛÊm+mÅêRRÛò`lR‹ØÔRÒ:Ry{Šq¤öÄja%HÔ‘Ö–^Í©µ=ÚÜÛÆ‘vL©íɶ¤uäô= ÖÐ:~FVÚ§H7«U[Èm)³1ÑZØê}Œ#WnÌØ8òTÈÊ”Ú[‘lãH9T˜ÕJ‘Òöþ_vÕ6Ž<óQÙ8Òq#·u¤S¥Ô¶†R+m©¹Xh{ì›Æ‘ç“bœ#ÇWiË|Ž©µ­+E>ÙFbÁ3*©!î.k‘edó6ã¶ŒtpójÙ{UÚP¢w¶‘~Þ¶ÜÖ²|†ª•i$T5 ÏôV9 ëlö[F– Kg[ÞDLÓHg4HÓÈmÉHÛÈf¿yÚFž z2ŽÌÂ6ŽùBD6˜9ôÈl°Ömf[ÝYÍl c—ZCh[óJ{NBJÄ¢6Ø·ê϶®|·Â¶àûo›ÚðíÓZýr tS[4 ÚÖe«/CÛÂÎ ÈlëÊþ"f[÷•V–d¶õȈÇȶÛG˜ÙôÞV¡m=¶2´­PCÕŠÐî1ZÚK´³­åHÊf¶µ®ôB#³­e“'3ÛZv6²á¤)> b‹AHîwAl'ÂM]´©$±­-ó·¶ó@z©nlï9Šbb{K€QBb[+m­Dl賈-R–±½5Û:CÄösþâ2FÈöÖ|!ÉoÉlçѧÖTb¶8F®jd¶·/mÑBµ™Ôí¡4 j{k>ÑŸ~Kj{Qí}( ´Å/"¡-Ž8hÜÐvFà i¤¶·_r”ÛÞ y‹RØgužEl{P”ÛÎã²oˆ°í<")u”ÝÎH®’sÞ’ç—ãˆno=”kMnïÅã½þ–èöž¤hÚF·÷˜©Š…nï1–3„n|3Énï·–Øí-Av‹( v;„lŒßD·¨´W϶¸£ƒM!ºˆRÆ“Hn'Þ:Eäö¶öA/ü-ÉíÄ;~ªÌö^Û&™"·}Eúé-.%q‹ø-n*‰éô-Á®h”ßâ>Oá[< ñíD/”ñí]A!aH”ßâ…/ÚW¿½Gü"¼½×™noÀÛ[é…P6¿%¼½%ïí£@ðÝA1•Fc*Yd··!ä4‚Û[VÆ¿%¸ÅeyÛÛ®KM¸ÅId#[¼®àDnå]‹ÜÞ+Gä­ßÝÎó8ô]ÝâÕ^²[ÔÌ®Iv{«™¿Ze·!éâQ°[b?¶“_)öU‰jd·¸¶l oqï\ôöóXŸ#½Ek¸œ½½#æ(!¿Eɬ¶’Ñ@‘#ù­¼ñÛ{Öa=Ü[°4Öˆà¢Ä–‘'?Sx!R%#ÁˆÆ7+Ág¤E‰"Ü[ÏtI Ü{[]G 7±ªØvb¼+ÄEÉAÝŒwbdUlãM°fR\¹QbÜû»ÿ¢›-1î}8òŒ{O¸Ô“ˆqoÓ=rb܉áºPÜ[£”ˆqå€À¸·†S÷`›& ‚ãð™0Ì‹8..ÊÑ Wî‚ ÉqÑ‚%ííŽ6çË$˽Çû®ÉrÑy¬˽/¥iŽ Ëˆ™ÈÁ’,÷xË,÷ÖÉä¢+<©µgƈŸroÁÃoŸ w*&ão&¹·‚›$Aî=à¶ø ÷^ï@§ûÍ -:‹½dÜæ,ö’ìEl‹VP}%ÉE3zªm1–>…äø&H‹ArÑ >[’\¡ip¥F3ŽKj„®?æ`\hé…ι·žâ‡ÄÅõDJPð<0-Nè¹"-XSû  ¯â ¾ …ã [‘®)¼ÓùVÂW%~sãz…L$“ç¾õ‚pFÁd Wl7_²õ|9Gü¢ö³BS)©W¤Ke¾?ßb僸;±¾^P¬ž8àâ ˆÖT¬~V¬ˆ­tŠÑ Z±Az Òšífجß&sïW0dæÎýØwI“|î("\Þ¯šs~a7[óWC/ž¾œ0¢€RÈ[‚P+¡:p'%a™eKZ˜´=öóxKz=JHýŒ°i{.Þ> Ö/¦²ç[Ʀ`ص=N,ñ–„¿»]NÞßwص=Ò~Pð„÷º ¥°ÿ_Ór² ·r..óþÇt½M”<¸5òÀôVïzJá)ÿ¨9X­CKð/¤ßÜ~óo ,#å~¢¿†DI›ŒŽ•Æ÷’ç½Û'c?†¹ ÝT„ú §ôGOéÄÍ–øj(‰§c“acrB¯ ¨åYí¤ß·ÞOká3ØDö( §øt =¼3)É[2Âmé{õÐÚ ¿ÁŒ’†’p¬õ\á9Ø×í-ˆ ;DH¦Dý–<á;ØÅ %Œ’vÈîÛ” ‰¦ŽÐÆHsR”¬ðš¶m¶bǰ;•Î[Ÿv:p멼Sô/Z3.XNÎÈ ÷n„ZõÎÈ0J½WˆœÎwˆ‚ð$¥1”°C«Þƒ,;2eâC@’NÔmª`)ÿaWScç k"ª[oÉIC ó—î)vîhí©‡;Õ)ù-Á"&Nrãc§æHÄVínÓ+{Ô˜«¤ÄŽt¤˜Œ`Þ’;$Ï©tçØAeö·– iv¦Œó1+| ¯}iäÙ¡+°?’+éOŒz2€}K°4 ËÐH³3™i¬ë˜qnÛ ü|仨§cg…\羋;µªRX+Òå³¹ä‘%zìŽÎ_Œf~ûÂtؽ=?böˆP60%˜_,rìLfÓôÙµ/)6v1IF˜÷[wÑ4” ¿N/’56í1KîÄØt=~1ï å;”ܒ³)f™†Eå išþác༻–B\à7-îoúï®'­;¶ zù•Ýtá­Ç`QWc½%40h‡;V--ÄOw ¦ØÁí¤‘‹Ú[hÜaê Oë¾iÆÀ©¿—¬>ÝÃÂ,Ùzš‘é6äQ½C$ØQ2sýYöœÒá°Ét) ù­C(Ëž3—‡˜Î™“¬ióáqàa¦ÖÝsŸI»½UæÖ‰–©­ap‡øóer(ÄþÊ"KT连[bj÷¾¨²aâÖ…¡FœåOàŠx^ꘑ@=ªYjlhfâ.µ Ëb ¡S Ë–OØ6]¶;0 Jž$uæt„ä:OÙò”…ò-‚O¹ÿ »³±{‘Áì:H•×ë1nÁú&bZqèÅÇ.-g$؉C– Z ‹ÞØ€n:dª`„5Ðtð”„=ÐtÈS졇E½›¡\í^'>-´w^ô^´:\vgÔÒs ­`Æ9z×±+ÝûÖŽâ¶A)ÀŸ±«úĵ]¯vn.…*AÁŠ`^)šÛ=УìGð¯ïJ2»¿{I· Ìû†Ì"0;ß@‚™î3›È&˜9M\’Y÷^h†õÍ- 4C0»QѬͬƒlÖ¼¥a6Ëàa„3ï`›Í6’Íšõ}³Yw HÃYw|ÃYO~œu‡V5 u§ 6 uÛäÐ2s´­ç}¡uкm hxÕqâ³nc]Z÷´bBëšà h›IhCóµmØš—„æ°Ö´áÔ´Ñ“ØHhÃö &´‘oWˆ6ÔÈ6fÑÆ†8"Úp¦b#ÚûÝâÈhÃaWÈhXŽùç <‰hcåbXŒ6Ï\Ë‹Ñæ^ÛˆÑæ‘ˆ#F›=—Zb´Ù7ÒfÏáQ”6GN ¢´)£SAÚ^‹‰Ñæí YŒ6¯\F‰Ñ¦Á&£MÇçLF›Nñ“Œ6ï„ 1Z†OF»O¨D´HÙ?˜fú* '[Õ™ÓÒì͘ù#õ ˆi÷Õsž&¨…?‹^A-rLj&$¨…›É¨ †oÜ— è¿ÌG§¶ ø¸ j‘ESÓr“{KþîS>k®!@ uúYÔ`›e&&¨¡ÏzµÏ1AjŸ¶=‡6 üxIjÛ™¤¶Ý–j¥y$µÏ!§=¹“ÔÒgÒ ¶Ý¨Lj̨ۡ–AßMjÛ?ˤèÃì¶dgèÙoƄ𢇨¶½áÍj;Ø„a­ÖBXÃ1Þ0 ¬í ¦µ8ÆlÖèhÿxaJXÛ1@ k™ÃÕ¬í¸ô„5ü^êeʈzg¯"«E6¤n4‹ð¾³ûÖ"¢Šî’°VZGVÃ!î!dµ0ZMz£‘jÏްËWWLXËð(d5ì%‰¬á–¼8%­íЦµĨ1¸†Æh])Q1LƒuHÐÚçRtÏ}F~ý¤µØÛ´FŒ«Òv²²„ºÏer$®áä·˜23&¤­ìv‘×°“•ܼ†CÌUä5´ßм†³üj/E¬qØBòÚŽi^Ù¿%òBIê×P­‘‰þºÏò†a-6ÞÔku»Ž´V/MZ‹•¼kÂÚ½6QÖ‚·L“7S!¸Ž 5àDâÚsi\ÃuŠ‚×"ª¥ê!±¡dV`é~±$¶{9‰-ö ÍgAl“ƒ ‡ø]ƒØ°uè ‘È†íGñ&‰ ÚŸ#°…¡‡à˜À†·–öáko/’×p£~%ä5„ÜlZ^×`oëÞA`ó°EX‹}ÍÍj‘eÂØ°†Ëf•Ê qx›™¬\€¬†Z½KBVƒáŠ'j²ÚüË,ˆ}νÅJRÛé)Hjø=…KAjaþm¢ RÛ1Gj8†‹‘6nÍ{Aj±KÛÍn·öiI&µ'\!To Zîí ÔpƒMS|Q+iˆY2) 2/”¶“m˜Ò¢„W!¤¡@_˜ -êþ) ê‘[×¢4ó/fÏp]µÉÈÔ¦òÉÔ.=3¨ÅÆ!9Œ¤¶_^ JÞ¨]Ê>cNËu 9m®„.rZª;Â4\S’1mÚĘ6ó†˜6+£Í”³ióÉÒv“iyOb´é,3Z®wÍh¥€Œ6“5(¢Ýf0ihóƒhÓ®)¢ÝœMŒhmÊŒ–‘ŒÍhæ˜Ñrv7¤Ýv—4¤ÝÞù3¥Ý÷/Ñ -ë™Ò¯ÙLiôÌ”ö8L„)-—;¦´ÛÑ¡Mikùši1ôi‘ÿú)–Cš-š@´eDh‘$G-D{Â4D<ˆ†+xŸˆƒŠ1. Ÿ¿g1"ZßHhu$¡U±„„†iÈ‹=úC*vð”mÇÑTWëb"Z.WE4¸KdI ZÄÌ57¢¡Ä4„†ƒSZ$?+ AEjОöl--"«šócŽÞ­@m^[⣎–.Ò©¤Í™³’”´yx &!m>[¤0+mŠBZ¹T“×·*‘† @‘öåòt)!-³›¦vߞƤ£ÝÉØ’Ñî•«hÉh™c6u´ŒÑ™:ZÆMíî~C!£Ý+WÈÒÑ`ŽmaŠ:Ú½ïG:Úsæ:I:Z¡Lmíz i«¹·HHËÙ)¤­-¸ÏàÙª»O¿Ð~{ç˜t†/X¤¤­ÔN¤¤­åçM6ƒ ¯›B6 ¯BÁ…´õl† 4 ׯ»²YºPͶ{¦Ñ ƒZÕÑb¯ÞÜh‰=,‰›Á¡Ñß<Ù,¼m?BZ&æ0šáB¾%²ÙNÍa6[m@d3 ±¾Ù c¬/E6ƒûV*tãŒ]v„3,õðÈf;m„Ùlõ'·Èf8éÉ’'öºowV²Y¤Š°þFŸÜ±¡l‰4Ɔ3ìÝ[ œá„³5EYAfëÚZ3ÑlÁ÷DU™añAfáÅ7O0ƺ Á¬ì„ ÌÞåPbdp¼ÑÃŽ·Òæíua.c¬¡‹îu'¿JE»d!úèÞ—;¥4´gËÕÒÐèèÔÐÐ§Ž†¶ž|;ÒÐìÚ•Úºr"Ú:wÛ(¢a Òu(¢=×®•"pÊCm5÷Éhé¼–2Z:@šÊ0iýqÑÊû8N7—P†¹ñ—ú¤d4Tc©-|0«U* ˆ8Uo`fjÏNä2Ì.ôv0—Ñ]L%´ö>ÌvAe˜çüHeÑ~kPAeqÌÐ1Ae˜^~IÃ#™a‚¤Å>Ñ,¼ÒÔ·‰fŒ¥I’Ìâ”ËÂÚÃö_ÍÍ0yüÒÐG4 Pò…Í0a&Š›…œžá  n!à :Lg˜~Y† : '¾©c‚Îø‡h,ð,ÎZ:&ø,|â.[¸dà˜)ú >ÃŒ¢7'>‹ûìUJ‹^UJ /¹)( §>X¢Éšïá2¶-¶oÒ÷dž¹J‹Qn&k¼‡~B¿%¥E‰¤>£æn1íŸå2š!fM¯h6œŒl–ªÙl8t²YšîÎ)Él6OÛ’Ͷ b6KË9³™§ô„³­_ÎÆJÞœÙ^læ&Ïv…²otâÑÄ3Ç}K<Û—ŸåmȾqÙôÎxvþú(h3å(ÒYªU¤³á¸ó¢3gþK:Ë'oG)¦³±ò™8ú®mâxd eâh£˜TÐíÆp6Ôž@g»Q¢3|$´• E8›Éò‚³y䄳Ý_,¡]8«gPA+uRA›“ ZÒ}(hû>·‚Vñl?™TÐÆÖ¨$ ¹,4­<­Ÿ•Z¨Ÿ½z¶~vxkùìØÔ'ùìHƃ|–ýbëgå h[±€¶í$ •¶X@ÛgY@+%Ðö=I@{·‚¶¯%-û‰´òð¤ Í#W¹&´ã§¥c†’JB»ÒºJ€–é’Ð`D;\„vm¬¡][0 B £XÙaÂÔ{ D»óµ Ñ®Û/ß„vh+®šùƈ¶º„h×63¢Œ#¢áÎ]`B³ìBD»r¸íHE-íÙ*¢mk¥F´}i!Z=‹ˆöŒm¥(F›ùÄh¾ß´u|¶Ì)cǧ{¹¶ŽëÜ)DÛìF4›¹’ÑpŒÏ2¤=[~"¤a?ÔfŠ¢´ä[Aš£Ç$£[§•±ãJ™EŒv¹¶ŽëI–­ãºó¥ˆÑŽmb%F;zª„b´óò*OŒ–³’ÑŽ­ÔŠÑŽQ!Ú™¤'B«GBk©- ‡þpæ˜B g§%œ…i縶p*8+F\¢³s_•pV¸Upv>Þ׸”M2- Éf}+b³óô—'7\)¿äÊ/ZŒVlÙlç¸ß‰ ­oŽŒÖ__3ÇÞS³#¢+;\ >i+tD4WР Fý§¡#’ >KÇÙsp¤öÒæF[Ç‘F~2uœw1~ SG$º:?¦Ž¸S«v°u„«‰Þ«Œgû•aëˆClI[Çþ¤PFSDZâ2夻®,Ç™{¼²tÌÈ0iéˆÙ©"Z­F–Žc¥j–ŽðCqµ4uÜ66uœå™:ÛÒÑã½-ï|‘²tÌÐ7ié8/2t„Ò¤@ÁÐq“dèˆ@HU=[óü¡ž­éèŸièˆÎøÑÏ"ÈŽÜ•mé(~“•ãã;¶™ã{›wÏÐö>+š¡±šChåoI™J?Û3§õ3„x™Í"Ÿ¶K( ]N^–Ú•FõÐ.ÇèL-%”ü…P\Æ´‹þNÓ¶#O`Ú# SZ:í˜Òlm`H{lÜcJ{ä÷cJ»o{”Ò–§3CÚò>¥!mÉd„´ôÖ1¤­Tn‚Ò–ŽÓÊ5ˆii!cL[=AŽ˜¶®dGbÚíèœæ4Ëä´”T…i¯Ì@'%ó[?ÉiËs9-½€ÄiP‹guEC…²| NÛ +ÅiN¾jjÏaûÚsºã ÔB|}ŠŠú¬ç5¤´~ ö`+šzU€ÚsΤ®µ€úß’Ó #I§#§Á+Gä4HBçGEëGZGREÃ*ò¨*ZŸ)ÕQFë÷¯Íi;I¡u´q%~RG×®¨£Íí"íÊ-PÉh×Þf”Œvõ\LJG›÷v£Ž6·Œt´kÛ5RF»mf©€³&7ÊhO¹2u´'÷*%£­\½HE{r§O"Z|Kmž¥¢­­·HE{ QF{ÒD*Zñ8#è¶Ë#¤a­©u/ ˾õa´÷ÓŒ–iÓÍh;mº Sß×-"oŒª¢Ed2[ž\串b0ZÀhÕNŸVÖ„4¬fÒôprž™¶%"¤aoß^ngš+¸mOo¦ ¢¡Dωˆ†xhyÈš1¿Ù@Œˆ†ËØÿ+m!¸”ÝÓ‚Ð0K´Ihˆb£%ޱ—[>+?Z¶û¿€û·ö$£ˆööÓ7ÚZc»½AD[ÛçJ„ö,÷[ÚZÇnm= q´w¬ò+# Å6v峈®ö1pŒu„n‰„è§ä¹ ´Ø^* D‹½o»µÍØ&®¾hÜææÞ3ù,öž-ÖŸím泿¦“·ò{î°“Ïpcn ùŒ[Öâ±4°šV5Q€W²ÁcÒê=¡,(m‡Q3¦EÉÍæÓ"ŒZ—ÇZ`Z,¦–˜óN=1-T‡ŽaD$»*§ÅµºœÇÕkƒÁ5ܬ[CP‹+=æ²#îáš¿lÑØo‡hûZ¬Ý$†Ô"‘å¹ 5°×¯SZÁŸiÛL£1-B•= ‹Æ£z¤E|6‹Q ‘tÜýkâˆcUL‹k\Ajˆ©ë,†IÂHoš R‹›ô1Š•ôÜÆÄ@µ·šÉ  fµˆ¦®VcP)¬öÜþJÉjEèÒ9ÁjŒyVY-â-iXÁjXcÿý(h’Cञ†Å±.%AͨROC-jïãÈIg1BO‹T= Á˜\-õ4DJ2¾9v’"§¥ž†L>KÑ“°¾©†ŽQ"B¢¢vöÜi“¢†Š—**j8æø(j';¾¿»d$+j8b|$µstß¶$µ³‘j¡¤vŽÃŸ†$µÞ(¤¤vËQ–ÔÎw8ÕÞ1®e¯2Hjç}}‰í½öHÑ’ZLÿÙÞeÆùKüEE휊™ŠÚ‰8ÿÕâñ-i¿ljIE-"Iê,*jçðànE õŒjô¨ b’Óž²« ÊihÛ¥(§XˆÉÄ‘rÚyÛfØržƒ%7ÊiX®¨Éi¨g©ÊiçÔ¬Rbn½U=ó>¦7º|ì [*©á³þø¼}”ù7Ãnµ®Úõów p%‚Ž~—Y §?ŸJTR«aQ­È%¥ª~Ò¸¼Ü¯JJU**UeÉuØ­wôÁGýo…Ýzþ¿ »õ;=ågžßÀ[?z]ô§ëøôÿg]5¨ëú„ÞR]å(Õõ ÐźjX-Öõ ¾¥ºÊQªë¢Ku•ÀZª«†ßr]û(×õ Ò¥ºJh-ÕUp¹®}”ëú7p½ƒEDðûÿI®ePûû? O¿7„ýýw»ïÏaíºï?Ôõ¯Gáz¿nD¯a¸v€¬ÿWãpe´¯?©åù/ˆ¾õvìÏæ¿wø­2VþÏÿø 1·Þ~B;„3 ‰Ë¸çÈ (K„6Ò‰á9éD-¿leÍD áTØm5|Æ6Tø,Ëä&"þ‡O²Ûbt¸Xö‚ǽå«v†(.ÀvëxdŽ0sß@'­fÔ|Z$¤õÈ[²ª Ìy.ùô:ƒú[r†OáL›ÚsÉ$áJ·}„k W½Ym`¼¨Ý÷0}¤³Ät 3æ®Î‰mtúÀÊeé ;Å­ê-¸c úr”0™™Ô„f|ƒáªÜàÛÐâê]Ó(áÊ'Ü`]Ǻ…vÐ(!³_¾%­+Ï£Ü%ÜÍZƒ-ÕU|=Û1ø“ý¡!ü8sCdôêÍ,Ì(‰é Ÿõ–ÜÞ’–†Ð´¸Ç1ê ÑŸ’¤%Ü•Vš½·[S~Ë%'s~f°“T¹>—:ÛSü30ÔÅÞôíDvïÿ騛YÅß’vD·s÷ „™?•.â-¸¦ü%òúõf’û·ä9ävš—¢_ïö!mçšòÚô»lôì}²óµ÷Îwvzü´»‡_vkô÷°GfkþJººf<—÷”°)‚µù`Á ›¢']t[»èVxæ!ôê-çÜ·¼:µÜÝzS$yKlÆ©‡‡Sïãœ$gëG˜= ÿЧ·Ò?­–Ä÷WKúe§S½Ç>†;ýúdµôÞFP³šÞúÅjÏ®æá\)ù±õ‡Ô–G¯·„~…ŽŸó>nP“ÕÊ»~s5}ØmЩw>iœ;¥Û·AŸ^„Ê÷I~…vÓFøô:äÎûó‘^”gÐ¥·œquùlê#tè]m7íÏüZòÄŠc9þL+óìMe‡š¯¶Ì#üò÷9ÈŽsUÒ6[çïS§ôC>§ÒÖÛ¤GïîÊÈ3ÂTÆmʣמ¡ ©q(yé–•ç=ÂãЄޮK­'_¥ßgCfœ³F³kÊŒ³2´Þ»¦ª$$Æa‰{;ã°ùB‘gЇVÍGbœêqÚ§S>ëªwÄ ºäô؇qõ8±´Kμ»àŽÙs¥ B»äÎ{í’çŽ#¸‹ß.ùò¦1JCRœ‡hzjJdŠýj5Mˆ»ì*ٔɣ· ú)O2_8‚fòjJ»{v-…7ÕÛíþÚîoßE~±aÚ°o7ÕÛ•š-|ã«On‹Ï¸í¦z»òÃäÄË~B¼Åé²cixÝ¿©·ûšÈƒƒS¤F´'ÔÛí#÷–ȉ75šöHÁ]»D^¼å˜Ðp!Àj¨xBÃ….ë/'ò}O ·^|m—‹µ¶¤ä¦„ÔÀAõ¡Ñg;*·%?^'0zK$çZCjK~¼<ЖôÜœ –¼xÓÝ¥- ºi±Ñ”ºô8wk%éî¶È—7Ý]úMË@ÎÊý ¨›ÎÍý ª{ Ë£ý ¬‹XgM¡ëFÚ+ÕJaw?Ü~PÙ=œ´í-‘ƒdfý‡dšKõC.’åâwD,ágµû‘ž’ã»R—eú)GÉéq´+ui9D~’~ký”ŸdšTõ“úîa%¡ïFÊ?•PàEâ§ØÏk|ÞI…÷ȰXý¤Â ¥ËW¢Ä‹Û˜:†oyT @¶ÏªQä=¬;v¤ÀaѬ7мG¨õH_úùMOüôÄêÊ_Zn¡)èèeSmÔÑt4CȘÒ/¯¨þÕ(]›ånPÞ›XÒ4‡X]Ÿ ¹3oŒsgÊóæ¹–Ä:ôú]KAÞD÷)‰ù¨y›Ý@×Ò,Ê@×RÇ4Ð5g–M¢km7D‡fŸ"(]FK¢km#‰®µÍx$ºÈ¼'¬"ÑÁHRì(¢ké#e¢kÝcŸ‰î-Ñ>º€®YK6еnÆžCÚ%ßÀãÈÖYBžkéxkžËZs-ͧŒsõ$âšÝN·ÍLEški¡Mœs”íĹÖM5¢¹ra®A–+GåêEˆrµõD¹–Æãf¹Ýz¡\ë›§ˆrÍ>a$¹rA®ãv[…q¥RNÑ2P·oGWÛAŠ«'‘âÚH"Å•cDq8¦Šké¸hŒ+µã20^r\^K‰ãêIä¸r9®ãê9ä8;««äÚHÈ$Ç¡-‚ãZÆÚ5Ç•;Ç• äj A®Ô++w-+ÍÈá®ðÅq¥9â¸òârõâ÷çaŠãÚØxHŽ+oM WîR WŽÈíÖ äJ[rå¶rå‚äJ%$¹Ò|‘ܾ‘\­•(W¦P®œD’«&Ê•¡Ü>I(WƒX®<¼`¹re±\©„(W ˆr¥ýB¹Ý…rõ2d¹z!²\ma®–æêYëþ6/`n?±\9C,Wš+˜+×Ì•Z sõ$Â\­˜8Wú‹x®žE +“çÊ[ žÃî®DÝÞï5Ð}J–š§ÛÏ•. «%$ºrÛ"ºÒYEt¸”˜EHWK”b79°¾(Py!ö=Þ @šáVÒ}Žîsv(I ˤn á®T#¸+o pWŸÂ£¤¥d?pÁÝ~¼d»OëhŸ[á®>^Â]¹k²]íd»Ú²]9 hWÒJwß2É®4–`WK²«wH´û´äjj›H²]½ôíÔW¢We¹e¢]©7ÐnŸ"²ÛÍÙ•ÖŠìöuEvŸCúýßEvŸ Ïößv{”×Õ¶ÜãgëŸö½ð³¾cŸ°®\†TW^©°®¶–X÷)i9{ ôúø<}a]½4±îSËôäéÆ\ãóó>¿–L÷©âñÔy™AWÿNþbºoÉãÞcÊ;=wjÐÔ}ÎêçßÏwpÔ•ž+¨û”\9{<ßoÓLçWÿBz%ÕÉ·PÝ\)4‰êfƹ'ÕqJT·£¼šêæÖŒDu3íLu—M= u9ÉkdºZ ¡nf{CÝ娣f:ÜÀ¥‚¥Öå•×ýù-¤»¶h‘.›bn?ktŒP$:WKž«"Ï•sˆsÐl töÝN Û7@WšFž›öõOž›+·ÐÄssy·N%??^‘ܸóDrå¶Er¥ ÉÕz3N–åö× ”+’XN/^ç_d¸r´®<{AÜ~ÒÁp塉áF†4Ãíw!„óUÉoe¿Õv<Ç^/~ÛoBüV^±ø­œ$~+m €Ã',5VW.-„+OY WŠnOðB¸‘kN#ÜöEpè©×Ýj]ž”‘q¤™áö8J†ÛGâv½¦¸q%5ˆâê1Ê1QJ”d¢\)Cä˜Ñ2Ë„:­1.óN$ÇY­»=afsŸV_ˆ!®^vyÂô1¢¸r]QÜH4SÜ~˜¦¸rma\-ž1}uq\-™ž1%¢äê$¹Z/Q®ó8þT£P9û>…r{Œ2Êtn3Ê•z„r>£Ÿß:»'L?a\yšÂ8t×BŒ+ïUWk¾=g’¢þ$èWÂΕÝì•jt w/¡Ï9ë=ÑÍN©In‡,WÜDÇÜlªTàvnÝOäVJDn‡V“Û,6˜B·tˆMv+%ëÞѳ¶}å±m…ngÞ£ÙÍ!¼6»eì#ÃÛ´ëQÂ[9DðVJDoûqŠÞ2ºTÂ[9é^%4ׯ·|¾¦· •ôvž{¾q­’ߎDâ·Â^ò)ùŒ·Em‚ó9IpyD\^›·_‚®R®–âö£1Ä•k âJ{qù¸Ìpµà[«0®Üµ1.{°1.ß›)nÇÔ2ÅÍ ndŠ+'=Õ–÷¶‘áÊ[2Ä­Í_çQ¤%Å•§"Š«µôoÀ¶¤¸Z2²ÍOFWë¹µÍoI·oAW^¶(®<à ¸r !nˆáJSq¥A\iŠ ®¼A\i‹ .¿c3\=d®7 †+¯6 ®Tò8v[¶åqì6?^Q\yM¢¸] ®Ü¶ n?™Íp WÉp?NK%ܳM4ᄤáÜÇ’áôëñ:Ýö—â·BtÉoçǶ²°åƷĦķ¤3á[^ò›·(~ŸßreøÇüVªøgüf@Àå*$!î p{1I‚Û@tz÷%A+ NÏuœq­ï:×ü¶k¾X¾m4KzË ‹ÞÌrK ó6€ÙÍ dvËfÝJÁ“›q¯9J¢ß¿Émƒô&7Ÿ$p+˜&p+„•±K³š‹K®¸í1óÎð¥þ@7¹é±%¸åÇ—ð¶¡(n},,c_Q˜$~ÛHA€Û{­O1MCȸç+•‡gŠË膦¸ZÏãmO¿ISÜúIqûžDqedŕГâÔ˜Mq~À¢¸zNRœŸÕ¦¸¼v7Í’ëÇœiŒ+ÕãrÑš—ïR·[CŠûüöÊ7Í03ÈiÂVóÖç)–Ä­V–e‡;!®”d¤Ómwé93m*3Ö©¹C$W›ü´:Œ'Éyà/ ÷5²4ªâ XâœÏ1®§—“®B„«1_¾ÖÕp{l]íßJ p¥ò ,¼‘ßëEš`â["RâÛºGšð•ø¦Á?ñm“8.ã&¸¬6 .«Á*¼¼ƒâjಽ÷w#æ/„«0w¬Ì÷3 q90’æŠl%šS€±ß6Î턆æ¹+ãW¦×·Á%îÛv’@‡˜§âDò2Z”7Ó38we!ㆺ*Å!h€¨KJÜ. Í¡ ¥¹˜šà &µ‹0¶ËaQ'‘P0·]Psµõµ¬Üá»æÞ…@ÚcÍ!ÁŠq4·3¥æp@â^ÐÂkÍê]¹Ê5„,÷ômhp(½JOq.Pî WDãBÁÛwrÈ+? XH¯‡F;½ÊáÛôåQËÎ!D9DËJÛÉ@9„ÝmÕ¼rçÈáõÛ£ )K¬´È•L"9„²õ2IîYŸ#Ûúg€\ha@C®"8QUó ߋÀqv¿ ÃDé[$È=ËÁ»rˆ*jÿ’z£&Z’¦Ò³êȘºArˆ¿jó’ú¸J‰äæík_íõYArý¦9” ‡h«yR€¾ 3AÇ<•ã«+É.@_Oz×1:Ôû±¤æb$O;×16ÔÈ|b"¹È[m&“§ÜvKG9_g;ÊÉê1Ýä²¹É9zPzÉ¥ Ïv’³Ý˜½äÒÚ]^rOZhÊIîÞ !Å=™ÐÞW\íDq饓ܱí/å%wä§&ŒÃp7?÷¬m)7¹´¥$È픉é'W\öä(·PDrϲͱ厭ñæÊ!d¹g%Ûæ2Ç£Y®<{Êm_ºÆËX´£ÜQàŽŽrç&3yÊíÆ‰çvã„shÜã’ÛNˆèä*—~Šv•˱é+—‘vÓWîð‹¤«Ü™HhW¹sƒ“\åÒÑÕ®rúg¹Éµì'·Ûa?¹–|cO¹öè2äæv•Û.¸v•;;è*—©ÉÒW®å¶œ}åö¥í+g×£t•Ëd™é+w&7uϾ²¨®tûÊíÛ¶³\Û%ĺھ‹­óÓ¶Ã\ÏÍ>aÝJ§aQ]½%ùÌí×(¬ÛyEu;멱%Ó GϹ¼T`ÝÊU’±®<*a]½çö³ÖmÏÖ'cŸn†;tH^ŠTWÚ¢è§=ˆP·2ò¢¡®ÔPW^€ .£®&Ôm§T1]iœ˜nm·x1]ñ‡ÓÕcu«ýðœ«ýUPW^¨nÇ3PÝÚ^p\¯Œ¹m¨[#ÝÁuå$BÝ~ù†º•ºÕB]­˜P—^¿fº•Žýfºrí‡ud­DºUœÉt+½&Ítk;ŠëÊs×­žsÅ3Ø\·3ÚìvŸ1ÙíWi´«Í¹Æ÷¢]¹4ѮܓЮžD¶[Û…PlWîIl—}Üh·ÚÖÕˆv+c=í–×'F»é×h·›+²+OJd·½·vû=ŠìØ¿0hýý†Ÿß¢þþû=ùǰõû=ùëú ñÁF¬TJx°¿ì_ ñõ? ‘¨®ÿDˆ¯¦ã¿Oˆ¯ÿø½_ÿñï†øê‘Ò…¯õù1Š]šÃFLãgÂ}á8.7,áîýXÄʆ«Ä±KÒÇW›[Y-á*‘˜Øí zâ[Gkì1_æçqÈ(\ÙÝðvÒ,õÔ!²'ÈP‰ÏjÇ?š\ cƒi¸í vPŸ(ÌŒý¡EÑ@üäñ·çL'ñøÉODóׯ@ ã¡÷µË:ZøŽWÚ£ˆ$ܘ£Bwy‘Và>³f„ó=cOÜ4ÎØ‹B¾§<«ÍÈÚ«õâ8c' [^ÚÖ†»"ÅãäVÔpø‹x´O$#ÑšwœÜ‰º3ùò[Â|‡‡Òü½%±…àöŠK=·Q’‘üçf J0´2Ão¿%'+ 8£7Cvs×h´s8Rµ_C¬qF¡f<æ·$¢$£D•`köoj¶©d0JrGm–ÌóÃ÷-a˜dØéâWÄ;Ðrp/'3Ôä¥ZžˆvŽ©My&y8‹“Vcç}-JúÁ0ÉØháY/Älìl(‰ç «&Õ"Nr°5ï€ó:„¾˜>"NrCè<DÈóÖnm#ŽwˆÀ]OG¿"â96 »Ž¸#Lò æÚ|K"æ9ÖóSg=Œ)Š8|ß}EÌó8†õŒƒa’Ñq†J"æyC9Ö4Ÿø”ÑݦÖ£j1¶7cÅÜ/ý^|¶oÇa%×yñù;ƒì¸Z,ì:"9³1WxçxÓú’¯Ø—Š 1ãð÷½TOìK½õ ÅMÈÁsñ]O]ýZ|4nÍñÎûtÆÖÁ<<ñî5 Ïà1‡ê©è1š#˜Œ³‡’ÿ¤ãÁ1ˆ„¦’Èǃ!çiz !Ï{ÁËùü˜‘'j>uÖˆçýtüýœ<ؽÑF߀ã]|ùù3+Ø6ë½;¿ƒ‘%±5õ>‹Ó_\l§£äöpÄÌWȳ˜|«~0qO”¨µ µ¾-ä6™¶‹} ó}6Ëž6™·çDbNóë(=…ɼ=ÑË/•æÇ¥‡jŽÍ©X?óû™G(´ñ¨øµL$îÁx®Qz¡ÏbêU®‚ÉÌ=˜)$Ì#$ZL !?™»' çžÉä=X…(Wö<~Í8KÇ„HûŽN¢6ÏPiÏPmtV¨´Ä=—JbFE{x ÈÞƒ¹Cjž!ÒÆçÎj2}æ}}ºó ‘«…l0ƒaîUÂQIÓ¡Óbÿ¥ëÄú8'åÉ >6÷f¶Ði1På1¡ÓböÒç>[µ˜«”*e2‰O¼:=­J-ÖuîHL㛃Äìv…¯…߯dŸxqœ€f¥S“£LfñÁà«áröPjã6†Y|b|Rí““j8†³äâgøþ¡[`Ÿ¸ø¥s}ŒÇå‡T‹#󻏯ƒÀ íß1«âˆC»¡ÕÆëÖw¨í’ø‚þö¢Uì»~î^McžÀ/u߿ԶE~wºÑ‹üig|È1¤e“eò˘¤&¿Ö(—äe‘dðkiÝaòëgá¼ ¿Þ ùuÛü÷å*à·}¯L~ÃJªÀV:ßÉ}”YUöaöÕcöAÓÃöA2¿L®kJc‘Vcì;ÓóÁØw¶pÄ>,èõdû"ižÈè|¹$’)Ž‘ÔiË—Ø÷ܹøÎ#ó®«äCN2& ù«EÆ(B>äj¿ ù&Ԉķ°^×\â‹.¢JH|è"§¡«1ÃÕåÄÀI|ïdý²ˆ|˜º´òòØ;šùÅ  ôD|ÇÈ¥Fß[%óó[ݹhñÅûý”!Áœ€v5߉áS¤Fàƒê3>À~Ò FÀ=ÍwLŒƒG×"ñÁÆ( â;aõ%¾ø"Y"â•ø°_ó%>Ì«5">H¦¢._ÛÔ«ªˆ¯!¹ øŽÄjÕÞˆ¯ÁÖB1CA.Òg*âkXcˆçD|O.|çLp$óõSK€d¾áäi }ÈÌ'Aè [þ$ô½§¨-†¾sxanèë‰I}žç’úà“¨ ‰ú2Ç]RßÛQÝQ>X#ê s@–ˆú°ìŽRßåäáI}Ë¡M’ú0°ñ¦L}·£ý›úúÞüõ¡ˆçE}ïxèqCÔëc1(©oD†$,.åEÙ†>˜‰éB„>,]BèÃZ#K®ÃX‰‰on.#ñHÀß{‡KH|—Mm’ø÷œOÆÄ‡±Bg͸ÃË»%">|Bêõ">”hJćµœzžˆoì=4ß@N;øúÌøðè6|XQ©Ïø §f>#X à‹4:‡À‡/±  |ãšY/oÌ'Àçøð²5k øp-Ã%7þ|€7>DU>xKŠ¡|·ƒØøÞÖ4óïΞeâ{œx2‰Äó%¾LøgèÃrN¯ÊÐC\Õ,êÃì'–õ½%šwM}On'˜ú`륚Wht~6‰}WKðöÝN6hìƒõÙ©aLÞ„Â>dIýbB^ëZÄ>hâaß„©’ÐØ73u|bßûD}maLò„†Ä¾÷_47'öá#‹û&,0ºJâ{~IÉÀ+ì›Ø¤g©©O3^̪³ÙËÔ‡™¯ŠØ#»!v$öá¶—CìÃTàcˆ}óæqaŸ‰f¾Ùœ~Ò̇ÉáM’ù&Vs¼˜ï}ÅÌ|èz2‚¾™{„¾ÙœuÍÐ7»—$†>6Cê{AD[<¦¾öû,!õÍ ;dê›ØTQͤ>\]\Ô÷Rš7D}/(ýú@ Ž}sjN5óÍÌoæ›o\&¼ÆÖ‰]d>¤í*!ô½-pŸôÍqiì3ôáyž¢IBºÑ! $ôÍÌhè›Їß>BÊ9¦õôaÁ 'l½½+ à_ fð‹îP°¯mÇa_ßξl5©Mô¤¾ëÙZ©/÷Ú }ïpöú°Ò4’úîµÔ÷¤œ©ï±=¡CRûÈ}U‘ f…WQûÀCyÊd¸ù™—侈÷̪}4ÆKíƒÆpWì+qÕ­ö÷¾Õ>|¬6bßc‘AÐ÷>0MIb¾åX_Rúžü™&ç‡:u>†ÈÏVÇù2ì±ï>·¤Ø÷dþVQfhôErõ»B̹- Hçƒå™e2è|çé4R©óaY%ÒùFªz‚>ðƒØ¬3­±£ŠùÖNø#æ[éõ"æC&P9ƈùÖ[ײĸ2ò‹vWB拺„¤d> ”¶›­òE½(Ièë)¬úà~1>*²qªA_¨0Їt¡ÚzôA~5ôER‘7 oÝWn-ú°¾pó¬ò9w2_wúN3&©ùa>¤Gý2rN—0³1žš(Ìw\¶ó3óz ªÈ|Èxº óÁ>T½SÌw=Ï æCªU«øb>l9¶ôamR2ßyf‹}—“ú¶ßUÀd¨0UŒ1X\Eä+s ,=oî ¤L&æ‹DZ™/R>«@[’·aSÄw{{>‰‘èÍwüï”ÍD|@h_›Ä×€T*!ñ!/§¾„@>$›Õ@$äC‚V­Ã…|ØÚж€»ú¸…|G þ€øBqÒ1Òù "G¾Æ«è|m8Á¯‘¯åÖ±‘/,!ò!mmû ßû—ÔÈe6NIGÔ‡ë«óa4ÙŠú°„Ñ!êÃ’_è ê÷B}ýNHµÎ¢“†'ïýÐôD}ØyÑkõaíe |(Ç{·ÛÔ‡qU#‹¨ò©ŠÔ‡µ¬øCÔ‡¥°;AßÌ7EèËÄñ©òAåJåƒY‚Ž!ôaÕç³}ø§/ ¯uk/†>¬n ˜Ê€Š7¥c}L.‹1f%‘+uB¾î~däÃ`®sˆ|"Ûùº"ÞÃKÒ "ÞkÉSæ=Ì#úrÅ{Øx»>¼‡ùð±¦×Ø~'U2ïEVe¼÷x¤1ïÍælØÉ{Ï)›˜ä=ô‡ïAžµÔFÞëp¿mÜ뙈۸72kƒÄ=8t!á{uÝ•ö`¤mñ´¿8qiï9’=I{à¶%’Èw!CˆJ¸{sÍ´5îr÷pOª†´‡Û^'®fÄÈóX½íQ¹¢½ðõ3ÿ媬ÈM{ønUD¾D÷ù¦ó¬§È×4|š÷`t`…Lß‘\!Þëïœ9-û=4KYÞƒ+Ÿlhõð] ÷`ô¹… ¿“îáK ÷®CHÜæêüˆ|˜ƒ¥[äË,ó^lÎ –À{-“¿mÞƒ‘„^œx/Ìsä=Øç\ÞÃ4¢æ‰÷àq9>"_< Óyï­Î¤FÞƒmð^¼‹C]¼‡—T¼‡QÂ2 ¬®A8¢;òjѵÅ{ØBý³¸b)î=áò¥<BR^æíJÊó„KÊ{;M" y ÇŒ·£áò Ÿ#cD]ö˜5äá£ýJ{Ø-ÕŠ[/“)/}Ä yJ¬õ) g 4éL§&+{8-íÁÝÅÀImo¥ã³)ïÈHÿ¦¼³mLåU‘”÷>ð¯IçȤHÆ<;“‚&0Þtò=3Þ»ÔóCã]!#e½ÌfkÆ{23`J{ÞKe/sƒZÙ{û¡åL){˜ÜN y¡ìmã$¥=lê=EÚê%í½/ñŒÒÞÌ5!/¦<›O òœ8…½3÷?-ìaU©c¬ì-¯~¬ì!èÙ¦¼@í[ÙÃhb‡õ: ,ì="u1Þ5‡hMÂÒêÙ¶“Œú%KÄx+×Õf¼•â•…½#MÄ,ì¡×¨žöŽ\ÑKØ ðú{Çó¤‡cã¢<øêý‹òÞµWò)Q¬!’òΈ ÂR¾z_‹”w®DoR^dLÕoÎIÝAMyXfKÇå5[¥5'æRÑ)˼çCy¡ëR^C”®‡’Ë%‹Rëyó§®×fÛHwÒ—)wÌy*ÖǘkéE‚<ŒA-B†©þ‘öZûiÌÙ¶¥ž –Úi¼yrѤÙL×¶2%ÈC‰_B^âOB^Ë{åÝ|‘”wçv‡(¯¥¡‘) r}u¢<œ%錔‡P•ö°Ø»?Ò^4ÏÜwó5X0ä¡§‰èÄxÃ+íÍx›ßÄx[M5ã¹/eÆ{ïì+ìÁµÛ¶3(ÛF´s¬†™®±›')ò`Œn­‡ç¢ƒ8¯=_KNXF Îy½y¸ãa%®Ý1^‡)…JÈx`Ý´¯ï­·`<¨Ùă<ÿH #âuÈu‚(Yrf*çx2>OÂÃD¡j„x¸²t6!Þ=µ]“ˆ7siˆ“ü)“L2ƒø2^uÌoñúœ„x0aÿ"l4m‘i;Nkàilj1D%F¼iØ1ãaEùe¼Gª8¯_Ã*/,ìui"Þ6‚6âÁäÙ Hăi·ì/…xØÚ’Ú)ÄëñÉÿ¶ /l+DCB¼ Û„×s9 o¶„³ <|B³žnçÇŒ3:§`ˆ‡«uD<À•€^ˆ‡­8ifB¼Žþõ±ã„鹌ix½gÍKf2iþ+ÄJÍ"éu¸]é'Í8!d  dÆ ÷Él2ãìÛøSfœó§¤÷ñi]Iăx|$=Ô£^c;Î\X¦¤ù+éI²´ãD݃ì8ï|X¶ã̱3í8omûü•Èc‰{wpX޾­0…{é¿5=¹˜IÔ³yq ,ØIÓ+*ŸD½'$ˆ÷g?¼‡W:>¼·®]¼¹¨Gå=˜5*Ü„€€Ô{>ÄãHo»wÍ n±‰þn‡!1ˆˆŠâ#⃢]ÿøã0Ýa’‚â÷ÞõÛ¡½Ò^È&¦À½óˆI< ‚ö[>–œ$Z‚ùÂûÍÎy1V¾GÌô¡ æ#(¨Þ`¾X kGæ !ÂÚ_0Ý*ô…k›ýõ´yŒv, † Í[öîôm“°×"ä B×ÃBÌv™Ôõ°øX]cʲGßâÒ²…¬9ÃÀN\HèÅé¾}Ø8¹?Ð×VZ1 úà=$! ^?V }á¢ÎRïðbóSB€ÌZ©³õWÙCÉü˜sö½a!êƒ ˜..êÃ_ÿ½>ÒŒUÔ‡yÉ á ëø–Æ›¤>XµõõÁEáùPƯ´‡Ý_Cê+Î0¢¾¿>Ô7ÂÁš%¤> ¬bNQ®¥'(êì·.Û(|’ú€WíãÀ³áè%Û“ÜRö…ÖÇžóîS؇ðXýC~ˆ†¥½‘v–Õb‘®u| :,í¶wpãÖçüºË‡üëüß¼ò›ùÍÇã„ÀonDøÁèFlxk/Òs­¹–&¦ÅG¶'‡—È⾉Î_¸ol3qŒšì~Gî›gÞ¸ͶPGð›˜O?à713ê,‚T¤û~Ø ·cÁAÈ̘—lw,÷‘üpFL’ß\iH òóQßùÍûL1äÇÀeQ@ðÃs}>à‡ed#ø]‡Mu ~x=Öî~syÌ‚à‡ ©Càwa}÷±éÄ-Øî“àw¥G–ÁõX?#ø]‡û¸]ÃŽtä¾+—N?Ü‚-6~hL·Ë¿Ãe¯ƒ:‹z¾ÈïJ'9‘ß5·&HòƒÙÕýñáCÅV I~ˆg %ù]¶J$¿ áî>>|Vÿ…üpÄñ1éŒèoVüb^ÝÏJäwaW ÉïÂüõ±è¼ðEéB„¿ȩ̈%ú»à† ³H×v¦ý]=wD×;F4AW. Rá[¹ÚþáÚ¶ª$þáëü»Ž+ÝÿÈøôµœÿ]ý'„–³wßrW· ©ðòö£ñ]pÞéÞi³N¬4x„Í:gŠ…6ë„ÑùþÇÿòÿýL™endstream endobj 6 0 obj 167462 endobj 4 0 obj <> /Contents 5 0 R >> endobj 3 0 obj << /Type /Pages /Kids [ 4 0 R ] /Count 1 >> endobj 1 0 obj <> endobj 7 0 obj <>endobj 9 0 obj <> endobj 10 0 obj <> endobj 8 0 obj <> endobj 11 0 obj <>stream 2020-03-05T16:35:33-06:00 2020-03-05T16:35:33-06:00 GL2PS 1.4.0, (C) 1999-2017 C. Geuzaine gl2ps_renderer figureOctave endstream endobj 2 0 obj <>endobj xref 0 12 0000000000 65535 f 0000167779 00000 n 0000169529 00000 n 0000167720 00000 n 0000167569 00000 n 0000000015 00000 n 0000167547 00000 n 0000167844 00000 n 0000167944 00000 n 0000167885 00000 n 0000167914 00000 n 0000168008 00000 n trailer << /Size 12 /Root 1 0 R /Info 2 0 R /ID [<1847A4F1DA91275B101E7C22DA8F8AB3><1847A4F1DA91275B101E7C22DA8F8AB3>] >> startxref 169749 %%EOF blis-0.9.0/docs/graphs/sup/dgemm_ccc_has_nt12.png000066400000000000000000006031241422157504600216160ustar00rootroot00000000000000‰PNG  IHDRTjûF¦Â &iCCPiccH‰••gP“YÇïó<é…@B‡PC‘*%€”Z(Ò«¨@èPElˆ¸+Šˆ4EE\•"kE ‹‚tƒ,ʺqQAYpß÷?¼ÿ™{ÏoþsæÞsÏùp ˆƒeÁË{bRºÀÛÉŽÌß(ŒŸ–ÂñôtßÕ»­Ä{ºßÏù®‘iü常¼rù)‚t ìeÖÌJOYá£ËLÿÂgWX°\à2ßXáèyìKο,ú’ãëÍ]~ )úÿ†ÿsïŠT8‚ôبÈl¦OrTzV˜ ’™¶Ò —Ëô$GÅ&D~Sðÿ•ü¥Gf§¯DnrÊ&AltL:ó5204_gñÆëK!FÿÏgE_½äzØs û¾zá•tî@úÑWOm¹¯”|:îð3™ÿz¨• €è@(U  t0–À8à|AØø $ȹ`(E`8ª@-hM œà<¸®ƒÛà.L‚—@Þ‚°¢A2¤é@F²† 7È ‚B¡h( Ê€r¡PT UAuPô tºÝ„¡‡Ð84ý }„˜ÓaXÖ‡Ù0v…}áõp4œ çÀùð^¸®‡OÂðø6< á—ð"Â@”]„p$‰BÈV¤)Gê‘V¤éCî!Bdù€Â h(&Je‰rFù¡ø¨TÔVT1ª uÕêEÝC£D¨Ïh2Z­ƒ¶@óÐèhtº]ŽnD·£¯¡‡Ñ“èw †aaÌ0Θ Lf3¦sÓ†¹ŒÄL`æ°X¬ Vk…õÀ†aÓ±ØJìIì%ìvûGÄ)áŒpޏ`\.WŽkÆ]Ä á¦p xq¼:ÞïÀo—àðÝø;øIüA‚À"X| q„„ B+áaŒð†H$ª͉^ÄXâvbññqœøD%i“¸¤Ri/é8é2é!é ™LÖ Û’ƒÉéä½ä&òUòSò{1š˜žO,Bl›XµX‡ØØ+ ž¢NáP6Pr(å”3”;”Yq¼¸†8WJ)Hq¤"¥öHµJ IÍKËIÛJGJJ·IK”aÊ8ÈÄËì—é”y"‹’Õ–õ’Í’="{MvVŽ.g)Ç—+”;-÷H–×–÷–ß,L¾_~NAQÁI!E¡RáªÂ¬"CÑV1N±Lñ¢âŒMÉZ)V©Lé’Ò ¦$“ÃL`V0{™"eyegå å:åå–ŠŸJžJ›ÊU‚*[5JµLµGU¤¦¤æ®–«Ö¢öH¯ÎVQ?¤Þ§>¯ÁÒÐØ­Ñ©1Í’fñX9¬Ö˜&YÓF3U³^ó¾F‹­¯uXë®6¬m¢£]­}GÖ1Õ‰Õ9¬3¸ ½Ê|UÒªúU£º$]Žn¦n‹î¸CÏM/O¯Sš~°þ~ý>ýÏ&   ©†.†y†Ý†iñªî¯&¯v\½mu×êׯ:Æ‘ÆGŒ˜ÐLÜMv›ô˜|253˜¶šÎ˜©™…šÕ˜²élOv1û†9ÚÜÎ|›ùyó¦é§-þ²ÔµŒ·l¶œ^ÃZ¹¦aÍ„•ŠU˜U•Кij}ÔZh£lfSoóÌVÕ6¶ÑvУʼnãœä¼²3°صÛÍs-¸[¸—í{'ûBûªƒŸC•ÃSGÇhÇG‘“‰Óf§ËÎhgWçýΣ<Ÿ×Ĺ˜¹lqéu%¹ú¸V¹>sÓv¸u»Ãî.îÜÇÖª¯MZÛé—ˆÿ2Â6¢,b&Ò*²4r*Ê*ª4j:Ú*ú@ôLŒMLyÌl,7¶*öuœs\mÜ|¼Güñø¥„€„¶D\bhâ¹$jR|Ro²brvò`ŠNJAŠ0Õ"õ`ªHà*hLƒÒÖ§u¥Ó—?Åþ ÍŒ]ã™Ö™Õ™ï³ü³ÎdKd'e÷oÒÞ´gÓTŽcÎO›Q›ù›{r•swäŽoál©Û m ßÚ³Mu[þ¶ÉíNÛOì ìˆßñ[žA^iÞÛ;»óò·çOìrÚÕR V (Ým¹»öÔ±? ìY½§rÏçˆÂ[EEåE‹Åüâ[?þXñãÒÞ¨½%¦%Göaö%íÙo³ÿD©DiNéÄ÷e̲²·7¼Yn\^{ˆp(ã°Â­¢«R­r_åbULÕpµ]u[|ÍžšùÇ‡ŽØi­U¨-ªýx4öèƒ:§ºŽzúòc˜c™Çž7ø7ôýÄþ©©Q¶±¨ñÓñ¤ãÂÞ'z›Ìšššå›KZà–Œ–™“!'ïþlÿsW«nk]£­è8•qêÅ/¡¿Œœv=Ýs†}¦õ¬úÙšvZ{aÔ±©CÔÓ)ì ê<çr®§Û²»ýW½_ŸW>_}AòBÉEÂÅü‹K—r.Í]N¹<{%úÊDÏÆžÇW¯Þïõê¸æzíÆuÇëWû8}—nXÝ8Óâæ¹[ì[·Mowô›ô·ÿfò[û€é@dz;]wÍïv®¼8d3tåžý½ë÷y÷o¯ñy02*|ñ`úaÂÃ×2-<Þ>†+|"þ¤ü©üÓúßµ~oš /ŒÛ÷?óyöx‚?ñò´?'󟓟—O)M5MMŸŸqœ¹ûb݋ɗ)/f þ”ø³æ•櫳ÙþÕ/ M¾¼^ú»øÌ›ãoßöÌyÎ=}—øna¾ð½ÌûØú>|œZÈZÄ.V|ÒúÔýÙõóØRâÒÒ?B,¾“sMT cHRMz&€„ú€èu0ê`:˜pœºQ<bKGDÿÿÿ ½§“ oFFsF×j`` pHYsNNÆÊ/¥tIMEä&>(Ê vpAg´¨“ÁQè€IDATxÚì½{|W}÷ÿ1¹Ù‰#y”;qÔÀ(& RBÈl.] IÊlcs)ÔeV-׸ Ù–piUfèïÁð8”δzÚº@éŽCh«Ö…¶Áä —%MÁJACÒÅ8I¥8±ôûãì™ËÞ%­´«Õ÷ýzé%i®gfç»çÌù|/ëæçççAAAAAAAÔäEínAAAAAAD§C‚ AAAAAADHP!‚ ‚ ‚ ‚ ‚ ‚h *AAAAAA A… ‚ ‚ ‚ ‚ ‚ ¢$¨AAAAAA4€‚ ‚ ‚ ‚ ‚ ‚ ˆ¬ AŲ,8ŽÓîfMàû>Çëº-9žçy°,«Ý—EÔì³ûñ<¯Â®É6;²ÇµI³öèû><Ï«º¿ã8U×ËÙj÷³”¾“lµ½}®ÚñÞYË6ùþdŸ+ Ùêêa±öJï¡«²ÍµÉj³Í5!¨Ø¶MƸ p]0Mét™LfÉÇô<¶m·ûÒˆ:}v7º®#‘HTØ5ÙfgBö¸6iÖMÓ¬äZ–Øx"‘XUƒàÕ Ùjw³Ô¾“lµ½}v>ízï¬f›Ùg» [],Ö^é=tõB¶¹6Ym¶¹&buN§¡iòù<&''á8Ϊ2&‚ âxžÓ4199صeY-ó$be°, ét¦iV¬Óu¹\ù|ù|™L†¼k b ,¥ï$[%ˆæXé÷Îz¶ }D=c¯ôJÄrÓ•‚ŠmÛÀºuëÉdàû~l=W¸ûúú ë:t]}±º®‹t:uëÖ!‘H_Ö©T –e¡¯¯}}}°, º®£¯¯1u!ÛÖƒ'ÚÞfÖÕÃu]$ ¬[·ét:¸öZË­k¦ýîƒã8ð}š¦AÀôô4E©{­®ëŸ!?f=žèç½ýˆÖ±û¬e›ÙçrÚg#{©u­ü³!ø-ŠbÅg„¶ÙÌùˆÖ±ìq±¶È¯±“ì±ÛhEµG$ ªªB’¤ØvŽã@Ȳl'Iy”-kÁV­«G§Ù*?þJöÙj»¨gŸ‹}ïšÖZe›Ñcµª/]Œ ¶û½³Öõ.ö½¨m›¼=dŸ+ÍÕ§ûÒÅÎÑ{èêb9úÑn·ËzëÚ=Æ­u½]7;ßeLOOϘ7 c~~~~^Ó´yóš¦ÍÏÏÏÏÏÌÌÌ ‚0ŸËåægffæUU0ŸÏçcëùþù|~^„à¸ü8†aTœG–å  Ù¶æUUŸ™™™Ÿœœœ!hk½uõî¿~ÞQk.¯·O³íoæ>d³ÙyY–ƒßТĮ¥ÖµæóùØ:þyñ}óù|pUUç%I ¶«·±<,Å>ëÙæüüÂlŽìsa÷¡‘½Ô»VUUçE™Ïf³óŠ¢ÄŽYÍ6›9ÑÖŠ=.Æùýé4{lÆ6Ó_Ö³Ç(²,mäí,ÿ|Ê·!–ÎZ±ÕFëêÝŸN³U~¯W²ïŒB¶ºrԳϥ¼wÎÏ7ÿ¬µÊ6ù±ZÕ—.Æ;á½³Ö}0MsQïQªÙÙçÊ@óD«³/]ì<Ñü<½‡®–«íf»¬·®Ƹµ®w±ýh§Úe× *š¦Í«ª[&Šb졈ÃÌÌLÌ ³Ùì¼$I±ýUU ŒšÃ?ÐèÿåÙì¶õˆñ •FëjaƼ¢(÷¬Öòzû4Ûþfî¿¿¼ƒäÿG_(ª]+7¤ò¶ñg€ŸCUÕyAbe½ýˆåa)öYÏ6ççfsdŸ »ì¥Þµòœÿnd›Íœh kÅc‹üú;Í›±Åô—õì1JùOµŒès@´†µb«ÖÕ¢m•ÿ½’}g²Õ•£ž}.å½s~¾ùg­U¶ÉÕª¾t16Ø ïµîƒiš‹zïŒRM(!û\hžhuö¥‹'âûÒ{hç³\ýh7Ûe½u0Æ­u½‹íG;Õ.».å—ëºAXGÅàoß÷c¡¶åÛzž×u±nݺà§Ý¡Dåmlv]5|ßÝ0 £æòzû´Q‘Ëå Ë2 Àªª±{_ëZËC§Aˆåœ†çECÝíG´ž¥Øg'Úfy²®lŸì¥ÚµZ–Û¶199 Ã00== ×uƒüѵl³™óKg-ÙãBm‘_'Úc3¶±˜þ²ž=Ö¢ÚyÈN[ÏZ²ÕFëªÑ©¶ ¬|ß¹{J¶ÚêÙçj|ï¬ÖÎFËk±ì”÷ÎZ×»Ø÷Îz}® 4OTŸNîK3ODï¡«‡nëGWÂ.ë­ë”1n­ëí¦ùÛ®Tªå%-§ÞMçùKçYôNð³`§à8Nœ8Quyµ“Ö-Y–+Œ­Ù/›òϳ¼]’$!›ÍBÓ´X>ÆFû­g)ö¹mè ûg/žçAŘ-˲ì[Ë6{>ba=.œN°Ç¥ØF½}ëÙc-$IªzÌòA<±4ÈVN'Ø*°ò}g-ÈV—FöIïqÙàBív1´ã½³dŸ+Í-œNèKk¯ôºz ~tatB? ,ÞNºiþ¶ëQaYVps]×)\ТĦòâBŠ¢ÀuÝ@ ó}±«Y–c÷Çq¤Ói¼á o¨ºœAÕZ×*ø@2zßmÛnj éy^ð9òýxQ? ìp5Mƒ(ŠWB£ýˆÖ³ûìvÛ:×>ÅÙ ·kÞ6¾_´8 Pi›‹=±0ÈëÓ©ö¸Û¨·o={¬w|ß(ôjK±ZûÖ³ÇF^c†a NÇ®·ÕöµÙj}:ÕV•í;ÉVÛC=û¤÷Î…Û`7¾w’}v4OTŸNíKk¯ôºz ~´6Ú‹·“nš¿]W*Óu¸®äÛ‹F|ßB…|߇,ËX·nfff*rN{žAš ]mðû#ŠbLݯµ¼ÑºV±Ðûî8LÓD>Ÿ‡ã8˾Ñ–bŸÝn›ÑûÓ)ö¹T{Y)»&Ùcs÷§ìq)¶±œvÅŸƒåd«ÍÞŸN°U`åûÎ…“lµõT³OzïŒß›…Ø`7½w.´=dŸË Í5w:¥/å,ö¾wšµ¡~´ñ½é”~t¥ça;Õ.»VP©…çyH$Èår$ ¦iÂu]äóù¶´¥^Á$Y–ÂÔêãuʹê5¬•ØX^:Å>—ãù^Íö¹ÒöBöÙ=vž=.Å6È®º—N±UÞÛ2Èæˆn¶Íå:f'œ«dÓÝM7ÛëZ³Õ¥@vÞY]¶ÎV:á´Ûæo».åW#DQD6› ò°‰¢ˆ\.×–¶ð¼wõÚÚÎãuʹµc1Êd§(šDœN±Ïåx¾W³}®´½}vd×þ¥ØÙU÷Ò)¶ ÐØ¶üxdsk›n¶Íå:f'œ«^Ȧ»—n¶×µf«Km?Ùyç@vÙ™í_éyØNµË5¡BAAAAA±P^ÔîAAAAAAt:$¨AAAAAA4€‚ ‚ ‚ ‚ ‚ ‚ ˆ BAAAAAÑT‚ ‚ ‚ ‚ ‚ ‚ @‚ AAAAAADNmw–ÊW\W¾ò•ínÆ’9zô(Ö¯_õë×·»)KæñÇÇæÍ›ÛÝŒ»ŽG}###øßùv7¹£ø“?ùÜqÇxÙË^Öî¦,™ny¦×â÷ÌÔÔî¾ûîv7·ã¸æškðò—¿¼ÝÍX2'NœÀ‰'°iÓ¦v7eÉtË÷L³ŸÉìì,úúúpË-·´»ÉÇÕW_ÁÁÁv7cɬÅ>§Óiö3¡±muþùŸÿû÷ïÇ…^Øî¦,™µöL¯hl»4~í×~­+l“ƶm—N§m;½/Y ß nïË1¶]qA¥X,¢X,Æ– ¡§§'¶¾¿¿ýýý wúé§ãÀ+}-gll ÉdÉd²ÝMY2»víêŠÏ¤ÙëëŠÁ[#ÛŒnÓŒ}Š¢ˆÿøÇkêYètÖâ÷Ì®]»ÚÝÔ–ÐjûœŸŸïŠgºP( P(`tt´ÝMY2Ýò=Óìg·ë¢6ýŽmÆvËìŠga-ö9N³ŸI·ŒmÚ¶Y¾ŽSÏ>/¼ðB¼îu¯£>§ƒX‹ß3Ý2¶ZoŸÝðLÓØ¶óX‹cÛVÏÛvúضÓû’Õð½Ðéö¾cÛTÆÆÆ011[vàÀ$“IŒcll CCC8tèFGG1<<\÷xÝ2ØFooo»›Ñ:ÙÈ×âu4K=Û°`û|ÉK^‚K/½´Ý—ÕºåY ï™ÕK«í³[úΡ¡¡¦ñ«ny¦»é3i–±±1ŒchhÅb===¸õÖ[ÑÓÓÓÐv»ês:núLš¡žmòõkÕ>é™î<ºå3i²ÏêtÓ8ª[žénúLš¥Õó¶N§÷%«áì{_+.¨ÌÍÍÕìÇÆÆ°oß>$“ILMMaçÎH&“uœ7®ô%, n ¡“CùÖâu4K=ÛnŸgžy&Î>ûìv_VKè–g¾gV/­¶Ïné;{zzêzú¯&ºå™î¦Ï¤ŠÅ"öï߃Ÿ¡,ËÇÈÈHCÛíf¨Ïé<ºé3iD#Û÷­Ý =ÓG·|&Í@öY›nGuË3ÝMŸI³´zÞ¶Óéô¶¯†g°[ì}!¬xQúB¡Põa- èíí vppƒƒƒ]2GN-ÛäëÈ> ¢}}DgR,‘L&c/Û·oÇìì,€ú¶KÄòÑÈ6²O‚hdŸÑÙм-A4fE•¹¹9Àž={pñÅ㪫®Âøø8V\­Ü`{{{+òö•óøãclll%/ƒ ÆÆÆº¢(`=ÛoŸwß}wì8±R‹EŒáèÑ£ínÊ’YûêÙ&иo%bù û$ˆÎ…æm ¢9V4å×ðð0¦¦¦°sçNô÷÷ãСCreŽŽŽb÷îÝ¡C‡0::Jž±4²M€ì“ ÚÙ'At.ÅbÅb»víŠ-ÁèèhCÛ%byhd›Íô­A,dŸѹм-A4ÇŠ *°wï^LMMaaQ/ƒááa$“I‹ÅŠuA,/õl û$ˆvBöIÉèè(FGGk®od»A,l û$ˆvAöÙèºû_E(ŠA‚õªªBŪû[–Q!Ë2Àu]ض ªªÇ"Vš·%ˆÆ¬¸  nÁ"2H‚hЉ‘}Dû û$ˆÕ °&ˆÎ…ì“ :²ÏÎÆ4MH’ˆŽã@×uLNNBE˜¦ Y–k *¶mC’$Ȳ Ó4aš&TU Žešfp,bå¡y[‚¨O[‚ ‚ ‚ ‚ ‚ V'†a&J¥`Y ÃXÐqt]G>Ÿ+“ÉÀ4Md³Ùv_&AD+Z”ž ‚ ‚ ‚ ‚ ˆî¢•Ñ$š¦+å躎¬[·ét¾ï`iÃR©TŶŸÿüç¡ë:t]G__`YV»oA«ŠP!‚ ‚ ‚ ‚ ¢i\× þvŽã ŸÏ/ø8ªª"NCQH’EQjŠ3¼ÖJ>Ÿ‡ A$‹að}ŽãTlß×פ›žž†ëºH§Ó±.A ‚ ‚ ‚ ‚ ‚è<σçymmƒ $©æzÛ¶+ -²²Ù,dYj§d2Ȳ Ã0*ν'‚ —Ë5}-<}˜,ËPU¶m“ BÄ¢ A… ‚ ‚ ‚ ‚ :Ïó*ÄŠ•Fź‚Jy ˲J¥033³às)ŠEQ‚kÏd2H§Ó˜žž®ØÎu] &š¦5L7V~‚ Ä"l‚  *AAAAÑ!Ȳ¼ê¢'DQ\p„Šã8Ðu“““±ãhšVQ…c Àã8°, ™L¦fª1ÑRí³˜H‚ ¥'‚ ‚ ‚ ‚ bQø¾¿¨Z¢(ÂuÝŠ"ñŽãT=–®ëÐ"Ë2E ÄA‚¶¬~JTPá?‹m+A‡"T‚ ‚ ‚ ‚ ‚hšò^÷¤ÞúòHQ‘Íf¡ë:,Ë‚ R­>ŠªªH$H$AÚ.~NI’ I‰DŒ§úE™L¢(Âó¼ † b1 BAAAADSÌÏÏ/i}TXQUªª$‚ Ô¬Ý"Š"fff‚m%I "S`rr2XÇ#PÇ(ŠÈçóp§îñ ‚ š‚ ‚ ‚ ‚ ‚ ÚÆBRpÕÛv±ë‚ š…j¨AAAAÑuPD A­†"T‚ ‚ ‚ ‚ ‚è:xm‚ ˆVA*AAAAAA X´ 277‡B¡€©©©v_AAAAAAIJ²¨”_cccØ¿? ™Lbdd{öìÁ¾}û088Øîk"‚ ‚ ‚ ‚ bÐu=ö¿(ŠP‚ ëUU…(ŠU÷·, ¢(Eâ]×…mÛXÍUUƒcAt ŽP™˜˜Àøø88€`¢Êðð0nºé&ÌÍÍ5}¬©©©Ší‹Å" …ŠÅb»ï A¬YªÙ&@öIÙ'AtÜþ …BÍud›±òÔ³Íèz²O‚XyÈ>W7¦iÂq¸® ×uaYày^°žÿ] Û¶á8N°m*• Ö9Ž;Ñ>hÞ– ª³`A¥P(`xxÉd2¶|ddýýý8tèPSÇ)‹¸é¦›bÛcçÎØ¿?vî܉ñññvß‚XsT³M€ì“ :²O‚è<ÆÆÆûÛ³gvîܼx’mDû¨g›Ù'A´²ÏîÀ0 äóyäóyLNNB’$X–µàã躎\.Ã0‚c*ŠÓ4Û}‰kš·%ˆÚ´­(ýž={*–aß¾}8pàn½õVìÙ³‡O‚XaªÙ&@öIÙ'AtÅbû÷ïÇ­·ÞŠÀqÌÍÍ/—d›ÑÙ&@öIí‚ì³{©•Þk1hšUU«®s]‰DëÖ­C:†ëºU×%‰ X*• ¢húúú‚”eº®ÇD ß÷‘J¥àû~»ogÛ¡y[‚¨Í‚•d2‰ñññŠbôããã(‹jxŒ±±1 ƶ- èíí "_188X3ü“ ˆÖSÍ6²O‚èÈ> ¢ó(‹H&“±‚Û·oÇìì,Ù&A´‘z¶ PßIí„ì³9ÇeYð<º®WýmYV°]ôïVíÓ(ÚÄu]8ŽÇq ë:Ç©)‚ÔCUU¤Óid2X–ß÷!Š"$IªØÖó<¤R)hš†ùùyˆ¢ˆt: CEÁüü<EA&“çyAz²ÉÉIäóùàÚAˆ]§mÛð}Í×o¡y[‚¨Ï‚•íÛ·cxx;wîÄž={pèÐ!ȲŒ±±1ŒŽŽ¢§§§îþSSS˜˜˜¨ø’ššBlYoooC¥óñÇÇØØX»ï#±FÃÝwßÝîf´„Z¶É×-Æ>ï¾ûn %ÚB±XÄØØŽ=Ú„VÛçÑ£G166Fƒ_¢- ض§Ÿ~ºÝMY2Éd2¨)sss˜˜˜@?m‰UI·ŒmëÙ&@c[bõÁǶ?þx»›²d–Ã>»qlËA ËrÕß’$ÛEÿnÕ>Õ(¶mÃ4M˜¦D‰,&²#›Í"›Í`õTúúúJ¥b‘'Ñsʲ EQ°´cüo^è^Ó4,ÊE–å JÅ0Œàºøµ©ª ×uƒz-‹…ºil ,ß¼-E²í`|||Yƶ§.¦!¼=/B444„d2ÙPL™››ÃîÝ»±oß¾Šm¹7B”rC­ÆYgUQÏ… VŠd2‰Ã‡·»K¦žm‹·Ï­[·6µF­†{ÎT„¯6–Ã>ׯ_d2Ù”D«éïïÇàà žxâ‰v7¥¥LLL`ll,'WEhlKt:Ý2¶Rn›m‰ÕÛÞu×]ínJKi•}vãØ6š>K–媿ë ­Ø§‘ bF°-ÀT*…™™™_¯¢(0ây2™ Òé4¦§§cÛñè•òvðuÑöðûÈEžjQ'‚ @Qض UUá8N î4K7m—sÞ¶···Ý—G¬A†††pçw¶ü¸ TŠÅ"ÆÇÇqðàÁ Ãk˲088¤A˜ÅÔÔz{{«V±XŒ…VcãÆôÒI´d2Ù^0õlspppÑö¹uëÖ†ÛÄrÐÓÓƒd2‰ýû÷·»)Kf9ì“¿tD;èïïÇË_þò®‰ ã/žÅb{÷î l‹Æ¶Äj¤[ƶ@mÛoŸ4¶%ÚE7mÖÛ'm;ƒ¨xÑ,<]Øäädì8š¦!•J5} .þðHN3é»dYÒ~)вàt_Ý4¶¥y[¢ÛÄÖ­[[~ܧüRUCCCA8eùO#æææ°ÿ~ìß¿Åb·Ývn»í6 V„ÍÎÎv•‡At2µlÙ'A´²O‚è\nºé&ô÷÷ÃqœØË"Ù&A´—Z¶ }D»!ûì>|ßÒq-QáºnE½Çqª‹‹\¸qét:ˆ4q'Ušm“¢(p]¶mQ2kš·%ˆÆ,8BŲ¬ ol5z¨æ¾£££±ÿwíÚ…‘‘‘ å h2™ÄÔÔŠÅ"vìØÑî{D]O#ÛL&“dŸÑ&È> ¢sÇÜܶoßs,êïï'Û$ˆ6RÏ6É> ¢½}vå$²,é·j­Ïçó±e¢("›ÍB×uX–AA$—ËUœ“×O€$Ip]78§$IPU‰D"X§(JCA…‹1®ë.Xê6hÞ– šcÁ‚Êèèh…µŠÑÑQìÞ½CCC8tèPSEî ‚XÈ> ¢s!û$ˆöP,Q,±k×®Øò‘‘‘`ÌL¶I+O#Û¨ï$ˆvAöÙÌÏÏ/i}TXQU5¨_ (_‹l6 UUƒz*Ñš*†a@UUxž[WÞžra§šxCTB¶IŒ *Q¦¦¦0;;äq_(ˆý?<<Œd2‰b±x'±ò”Û&@öIÙ'AtÈ6 ¢=4ãHöIí쓨ÅB¢Cê .å" ±xhÞ– ª³(Ae||ccc˜›› –õ÷÷cß¾}K.ÒGI Ù'At.dŸÑ™mDçBöI Ù'At&d›±ˆ¢ô…BcccÅ=÷܃‡z(($vÓM7µûz‚ ‚ ‚ ‚ ‚ ‚ Z΂#T&&&0<<Œááá`Y?öîÝ‹B¡'"‚ ‚ ‚ ‚ ¢»°,+(EEȲ ˲bê ‚ º‰ *³³³5 Q!"‚ ‚ ‚ ‚ ‚è^lÛ†ïû¡bçy0M“‚ êâ8€ïŠ.³,@’ØǶYª|Ý´ *Édû÷ïÇŽ;bõRÆÇÇQ,144Ôîk"‚ ‚ ‚ ‚ b™0 £f!ùùùùv7 ˆàûìGÃežÇDŒ¨áyñmšÅq˜X’ËÅ—•‹‹,傊 0Q¥SXp •ááa$“Iìܹ;wîÄ®]» ËrPW…¢T‚ ‚ ‚ ‚ bíáº.R©TŲôõõA×uèº×uƒuétëÖ­C"‘€mÛÁ~©T –eÅö%¢õXû‰¢ëLàˆ’N3Q%J•ìÇr]&”Dñ}¶œ¯³¬PÄ)ß®|ßD¢½÷kÁ‚ ìÝ» ¢TFFFðõ¯=VW… ‚ ‚ ‚ ‚ ˆîÃu]8Žûñ<¾ïÉÌÂú¾T*Ã00== ß÷aš&|ßÖI’„ùùy†L&Ôgq®ëbrrù|–eÅŽMD}\— #Ql»rE¢æÅÅŽè²ra`"Kù9M3¾¿ ªÊ–[D<­ËdX›LÈfÙ1Âã9N¼\ˆqœ¸˜³’zë‚S~qc)¿‚ ‚ ‚ ‚ ‚X"»lYü0JëÝÈz €ÙÏP>Á¨ðJû•o_~©tŒض]!n(б,‡eY$ J©P‚a°Jîë¶mCEhšeŠ¢ÄŠÚ†A I¤h ‚ âûL¬ˆ–4r]&DDÓwyÛ&fi¹L3L³•J1¡Ã4+£E|¿ú±$‰WÙ~ŠnÇ÷ÉåBQ„×I1M¶Œ›:cµmf†µ_–ÙoËbû>Ûw¥J7-JP) ˜˜˜ÀÞ½{„õSTU¥”_AAAA±XÔÒO9ùÈßR}«m&¶_À~µj¨”‹,¾ïÇ„h!{Ïóàº.Ö­[Û‡ ,åÛÄRÑõprß÷YÔÄjÅuãµFù19þÏ ^¯$*\d2€¦±ež¦óâ!¢ÈÄ€m°ûeYaÄ 7¸(ÂÅ~Þ>.®l›l–-“¤PôÑ4¶M) tý=9ÉÚ+Iñˆßgçæ‘)µ>˧žêÅÓO/:¦¤* >ÚÔÔvíÚKïÕßßññq R©r¹$I‚®ëe9Vl^Eˆš‰èx­€ øÈñZ@<Í\qœð'bBAÝ.˜¨j™R.šðh M²Àz2Óÿ@?k§Bxš8ÀKaÐêo"ILl²¬ð* ðè£hmy’E•¸ß»w/†‡‡qÛm·z{{±oß>S‚ ‚ ‚ ‚ ‚ÀÄ’l6 ³4ƒ+Š"r¹\»›E¬Ax=Ž®³´Q+…놑$µå°ÊÀkOZ¸hà8¬þˆ ‰[/ŠñsDë–pxj¯…Š) >ຂ”ÀE}±ÄmbŽ_}±mÛAŠ@Á ¯‰¥üòcÂm+iJPÇøø8vìØíÛ·£¿¿ƒƒƒ\–FAAAA±úQ…ê¢m¡<Êc1B«°í0õV-t $®ËÒVEÅÓd%\RU¶¿>.¬4cj¼îÉ‚ï‡&‚Ô;‡‹0ú¤MlãyŽ|ç^ùúWâLœ[700D¶É² !!3áýH@–elÛ¶m¡UCšT†‡‡±cÇ ìß¿ÅbƒƒƒØ±cÇ¢D•©©)ÌÎ΢···bÿb±¾§ˆ‚XYêÙ&@öIí„ì“ :›¹¹9ÌÎÎÆìÛe”¡¡!ôôô´»¹±f¨f›Ù'AtdŸ«Û¶á– 9ðâóˉ®ë±ÿEQ„¢(1/t]סªjÝbŽãÀqœšÛ¹® Û¶‚ @UÕeótïDºiÞV×ôVÑU,VŠL&¬a„áy»xy.pèz\ì0 âûLDQU&žLO‡ÛÔ|D-e)¹ÊïEÓø`•émã£qÚ/,•€t:‹\ã5•|ßǽé{qÎߟƒKþàø¾×uáºnFÐqpì{irrº®ãþûïÇe—]Öº HùÕÓÓƒíÛ·cûöíXúñññ‹+{öìA¡P@?ŠÅ"’É$öîÝ €EÂŒahh‡Âèè(†‡‡[zÁAT§žmdŸÑNÈ> ¢ó±JU-GGGƒeccc˜˜˜ˆmwàÀ !AËO5ÛÈ> ¢ û\½ðº(¾ï"Š®ë0MÙl6VX¾•˜¦ I’qÃq躎ÉÉÉ@1M²,×TLÓ„ã8š¦U¬3Mj©(„ã80M3vŽn¦Ûæmyáu 2rc%S~9+àžJ1¡„u7Möwy´‰ °ÿ B®ËÚÊEM+üžmpbL´(TxZ¬ã¡qŠ.L,‰DŸp‘Òˆ¨X?üÃbýÔz|MøäR>3.šÚ¶ Y–!IF6àEâ‹P¼£ˆë÷z†I’‚ï™L&¸gÓ=øná»@ªª*Þüæ7ãmo{[K?ÏEÕPW¦¦¦pÛm·á#ùn¾ùæšÂ ßîë_ÿ:zzz‚âöÃÃÃÄØØöíÛ‡d2‰©©)ìܹÉdrU(ž±šid›È> ¢M}Dg3>>ŽB¡€‰‰ ŒŒŒÄÖÍÍÍÑA´‰z¶ }D;!û\ý¤ÓiH’„l6œÍ5 ™L™L“““ËvnÃ0‚ÉWH¥R°,+6Q[Ïóà84MƒmÛ‚Š®ëÈçó±sd2™@,êfºiÞÖ¶Ù(2ñÀ¶Ã$ËãÄÏ‹Èóbí\(‘$™¢il{.²ñú*ÑH–òG;x =4W§¤ ‹&“˜¨hXû=&: ávžè%ålÙ²›¾´ Žã@QX–QaÛ6¦#¡7?¿þçøÄÝŸÀ6¿ù|¾BØœžž†çy8õwNÅóû<¤÷KÁ6®ëbÛ¶m8ûì³ýÙVãE­8Èàà FGGqðàÁºQ*ÅbÃÃÃA˜&7¸ÙÙY ôöö&¯ÑR(ZzÁATRÏ6}D!û$ˆÎfhh(&pFáÞ}A¬<õl û$ˆvBö¹ºq]ŽãT0 Àçy0Mº®C×uôõõa`` ˆHŠ'NcݺuH$AŠ- IÐ××W‘ê+ÊB£F¸ç»ªªp]^¹4M "Vº™nš·u]&hK·eš‹ŒÈhßEŽ®³óLláç–$&¦DÛây슊2®[=MYåɬÀ„—F˜¥ŸF`)¿ÊŽiÛvh§^¸Þ²¬ u·Uß÷™ˆ2­‚Ô]ì^xÈ—… öÖÓðäO·ýšö.Š"zþ¶ozÓ› úá6ªªâ†nhâÂÆ‚•B¡€ñññàÿ©©)ìÚµ »víÂØØXÃý·oߎÑÑQÌÍÍ¡P(`ll ƒƒƒ²YÞaöööVäÍ,çØ±ck¼D÷S(pøðáv7cÉÔ³M‹¶ÏÇcjjªÝ—G¬Aø³|âĉv7eÉ,‡}ž8q…B¡¡ ÄrP,ñÀà¹çžkwSZ·ÇÞÞÞØò¹¹9,mÂÅ_Œ«®º*6Ž®m‰vÒ-c[ ¶m‹·OÛí‚;Ö„VÛ'mW.HT«)"$IÂ÷¾÷=˜¦ ß÷1==l6 ]×á8€0e˜$I˜ŸŸ¢[¸¸á8NP!ŸÏò¬`_.èðt_¼ÊBÚ¯( DQ„$I1!`°ét™L–eÁµÒ˜uÓØv9çm¹m¯‚À";…‰Ùìò¤w‰Â£RL“-S”0D¥”®+‚$1Aƈ#ÿû¡ëS’5K„&·ÑXœ81x¢"òÅóŒ5·ÒØ–h'Ý6¶­Åbí“Æ¶D»àcÛgžy¦ÝMYvcŸ4¶í,¸Ð"²Ù,A"B¸xaÛ6DQ Òmɲ¤üá†4ÑIVÛ¶ƒ:'<ï73Œ õ¯ûR~NÈf³Aj/Ó4Ñ×ׇT*U5eÐcÛ嘷­¶ÿrÂkpQ£ZtJ«Jâ8;‡i²ÈßgÅâE‘-3Íúç’eöMÃõéOÿT}î<¥Ñ‚†Æâ¹ÒÈD\ÔL=/ÜóÔ=±mmÛfEážçá–[nÁÅ_Œ¹sçbµQ†‡‡¡ª*¦§§¡( 6mÚĎôRH’Øf .?zþGU¯Ã4M9r„Ý ™]‡ïûð}wÝuײŒm›ª¡ÂsèESzMLL ··ûöíCOO†‡‡!Ë2ŠÅbCƒÄ077‡;w¢¿¿¿ªg/x_Í›7W0#ˆ•btt´©è¬ÕB5Û^´}^}õÕ_ ŒèNúûû1::ÚU^¤­´ÏM›6QßI´ þRÖí¢·ÙèuïØ±…B¡nNxÛí¤ÛƶµX¬}ÒØ–hÝ8¶­Åbì³+Ƕ–Å\Ý£”»ªë:›ÅåHR¼Ø‚ë²m¢(Jè*ßìyÊàé{jáû>Î9çœ OsA‚Éa>!¼nݺØ6Ñz&BüLå5T,ËB*•jÊ Ý¶m‚€t:´•·%Ú^EQ‚‰]ÏóÉdN§cu8Ý8¶í†y[Ó uU­.h´"/*¯(,Ê$› Ï+IL\ Îí£¢¨;O“UžBÏ÷}(ŠRñl¬¦$I\‰«Qm ÍEŸÔØÆq9rþð‡ñÀÕ`ëÿيÇcof/¾õ­oáÔSOÅý÷ßAº¸k¯½–ÕYñLôˆ^§ëºPj¿[û¼®ëBó5‚€ËŸºœm[v½¦iâW÷ý*Γσ뻸๠ð÷€_þå_ÆÕW_½ôºŒ¦"Tn»í6$“ɘ‘ lß¾=–W¯¿¿¿®GÀøø8öïßüßÓÓƒÁÁÁÀË÷¥¼™±Ô³MdŸÑFÈ> bu½£ðq3Aí…ì“ :²ÏªÊ„èO9†__^ÓD’*Qž«™ó”Á'ykyÎ;Žƒë®»®¢6IT„áQ+óóó±Ÿf ËGE±éÛ¶¡ª*4Mƒ¦i0 #–öËq$‰ŠãkšÖT­•ÕN7ÍÛF” ˆ{®ÛܱêÁ‹ÑK?§öØr%ãA|&”iœ<º£²,WØ™ã8ð<=F•@*ý8ñÅϳ @ce¦TüÅó;.0Dkžlò5NCUUlÛ¶-W6QÊk¯•¢Œïû¨¨gÒˆòãÖƒODkšÔuà©ÆøyEQ„ëºiÀÇiêÝ@7ÌÛÚvsé¼›òk` ^,^áS,ÍWA`çÐu½ê³ÍŸ+nG–e……ÝØ:OYçû>æ¶ÍaîܹØ>ðT^¥Ãð¶pA‚óäÝOâ…÷¼€ùéy¨ª ß÷ñ»¿û»øêW¿Šw¾ó8óÌ3Y[ `ff=Oö@QxžY–[ß²e úîíÃc7=†ßùqÑ|{÷Öµ]‚ –Ÿj¶ }D'@ö¹º1 #˜ü˜à+DQD>Ÿ‡ã8Aqù(š¦îåëçççcÛæK©ÈÊ—W£™m¢ˆ¢ÛGUU¨ªxÉWk{7Ó ó¶ŠÂ2Þ5B×›ÊrÃqرM“‰*¾)&©ïÁ#¶&''Ù*žºËÒ^:°MÓ‚ÔVADŠœwü<ìùÔužç!›Í"ŸÏã?øžyæx‚‡î}/ë{Y¬¦iÂqäóy<üðÃð¾êáúç¯G*•Âôô4Òé42™LPÈó<Üxãè}I/Þúߊ¿ü«¿„aظqc ©ñ¸Þc?ø DQ ÒyI’I’ðåǾŒ™Kfpõ¦«ñžì{ðøƒ§3[2M3K6ä7¿Àà!^Ù}v IDQÄõu=¾pÓGàêG¯†¢(°, š¦aÿ‡?Œ—þ—†c罯;õtÜ{ñiÈ=‘Ã;7½sÙRõ5%¨ô÷÷ãÖ[oÅîÝ»1>>Žd2* صkúûû±oß¾¦NZOtédƒ$ˆn§‘ JöIíƒì“ V'l— ˆöAöI Ùçê€×B©G½õ¢(Vxäw k%ÅW5Vó¼­e±•ZuSJ*Åê HS‡›gÙÚ¿ÿø~/YÀ‘#G0åLA–eX–×ua¾sä;¸tÓ¥¶m"„ °,+&¨ =ÈÊlH’Ó4¡ª*n¾ùf>|¶m#“ÉàžÉ{°áÄœ3wN¬ÍŽãiÁÎ;ï<<³ù<ùÞ'‘bê‘,Ë8óÌ3aYV=3)OâæÛoÆöS·crr‚ àÝï~w HȲÌÓ’xttÝQÌL³T\¼ý¶mCQœòÙSpú§Cü3›fp6Î"Y,Ë „Öœþ\'\Ôxñ}š¦!NÛK’¤ Çw0|Î0AĪwÜÙK~/¬.ûΟãonº ‡Ô3±N\QñÔSOµü9kº†Êàà ÇÁC=„Æ544„Àqêð‚ ‚ ‚ ‚ b ³Ö¢:ˆÎÁ¶™Ò \—E ˆ"`Yt‰)²Ì¢STø³?û« "–kõAxmŸh„Ö½_¿§ÌMÓ‚ÚMbuzT ;Ã!"Ë2>÷¹Ïá’K. ¢¿þ°ÿñê?x56Ÿ¾¹Ô^étù|’$Á²,üßÿ÷ñÑÃÅ¿ÿ+¶üÇø¾]×ñØcÁó<œ8q²,ã¶;oÑGðö3Þ×uáy^ Êð4c‚ àÄ'à8þâßþÏ|ó(ŠÔ#â"ȯ_ôë8ùàIˆ¢ˆƒ7ÄÓ/{C'‡ TU "Y¾sä;°=.\@cíçéÃx@Q±ûøî`Ó5qÑìEá‡Tªã½KÆô{æñÉw½ —>Ì¢`l`øœaÌÌÌ´ü9k*BŠÅ"öïßb±ˆžž¨ªŠÁÁAôôôÄj©AAAA±6ᓟ±ÒärLìh–ÅÄ“½{Ã×¾öøÏÿ”ƒc‹" Ët¥†ƒ lÙ´ßN|;H]ÅE ž²î³cŸEï/zÑë÷BQ” ¦¯=°è’;÷NìÛ°®ëâöÛo‡aøö·¿'Ÿ|o}ë[ƒö=ÿüóøéæŸâ²ç.+µI ê Ù¶Ï~ö³øâû¾ˆ?~÷cöœYœ9u&öš{!I®¸â †DƒÜ»î^À̦œúȩ؀ x¿öþر¶>¿oÐßß÷ñ¥-_Â/ø`°Þu]¨ªÊ® FP›FlÍn ?$ÛÆÁoÄõû<Îþͳq|ýzö”8ï¼óðð÷nùsÖt„Ê®]»P(088ˆb±ˆ›nº Åb±å "‚ ‚ ‚ ‚ ‚ ˆ…H4¿mI{¨Šï‡EçÇÇ‘#ï„ 0!`‘*¼Ð¼ã8ðV‡„§ÐâQ%\X‘$ —&/ÅñWÀˆjéîDQÄ£>ŠÞ_ô¶m\xá…E<ð Ãа³ ¶mÅÍgÝŒßû½ßC"rñ®ëâ‚ .À‘ÏÁw>Ï}çsxïÁ÷BEx> ÃÀ»|6Ío†_݀ĺð8²,b 8~ü8ÇÁž/íÁåo¾<Öv^ódÓ¦MøàÞP9~Þq_¼â:/½ôRȲ Ã00så Q Îãºnpúúú‚¶är9À«»““LD©Æµ>~ýÃÕ÷݇Ÿýìg­|Ìš‹P) (‹¸çž{‚Bô²,c||<¨¥BAAAAAŽi2Q¥Zßg¢‰(¿øÅŸáŒ3þ¬b;ž–Êó<œyæ™Ørx DQ„mÛ0 ’$1 Äû÷¼Ÿ‰u"hDQÄu[¯ÃÆÚˆW¯d2¨ªZQ×çì?=îN;ñ1üôWŠ—¾ô¥¬ÎI©mš¦áè7Žâ‹Ç¾ãkîî½å/bP)òÄuÝÈÉÈÀõ‡¯ÇNþ£‘$ §Ýr=ý/°È€‡°P}ô8Ÿ 63¿:ƒ _ÞPõzƒã+R,&6E#czzz0/Ì÷2عKõ\dYÆ]GïÂ5/»¸3rðÏé8íøiØqñÅ8qöÙ-}všŽPI&“˜Û·ooiC‚ ‚ ‚ ‚ ‚ b1TGjÁ£P8žçù–Å Ðû¾“'ÿ¢hWìÏ£(r¹¶ÞA ,þ;…â0”4 ^˜Þ¶íàüßùÎwpÇw`ãÏ7»išV5…^OO<ÏÃC—÷~Žã •JÅî%IÂÃ?ŒÛ½333¸è¢‹Ÿ_»û|é 2ðêW¿:&q$I‚÷”ƒ÷~:»y~x-ñhäy6Ù€mn«Üîç>N³c v¼X &¸è¢‹Âÿ}@êšï_ƒ³T&šü~8_Á† pv»‚ ‚ ‚ ‚ ‚ Ö6º®Å·Ë1M3¶N×õ˜·9€ 0¶ëºU×ÄJ ªqƲ¬Ø³+Š,­×ßølÝúåŠýy­”A «ª8`bƒËl€ )³“L&ƒ+¯¼¯ÙûŒ¿d<Ò1ˆ<)Çu]ø¦â‹—| ª*$I êžd2¼þõ¯g‹`bG#jEù¸Àû>“¿ñ€¦ÕTJpèö¹Û+o<ÀD‘|˜žÃ…Êkà`çá8;·Äîw”ýèG•×Q0{Î9M\ôÂhª† :t»ví þç駦¦bÛ8p å$‚X­ø>JTp] F¿  $ðËõCTm›O’€*˜1t¯,Íæ¢hÔv‚ ‚ ‚ bíÀkE(‘lÛ¶kN&¡˜"IR¬6A´×]˜ó©ç…ó/®ëâØ±ãþû/F"øþë Šï‡ëºÐ4-¹âº.,˪¨iR5ýU„GyyoüË7"›ÍBEäóùŠè“Ç¿ò8Žl8ÂŽWO *­ÛøæÀÇÙßumK«áÒˆ,˜PR%(æÊ‘+ãŸÃÿé¿.¯Œl¬Æ÷õ}çÎË&ÈR)@JZ¥¬‚(š *Åd°èIbÛóíÊîOE$¬?^£hýh*B¥··CCC±eýýýèïïoyƒ‚ :…f¢J|ŸuÚµ0Mæ!Qo;Ïci#Uµþql›‰#““Í xÎϥ⺬}AAAŠ¢À){á,X¢˜B,7¾¿ø}?ò‘c¸üòëpæ™â7~ã1H’Ã0 (Jl’žGg ‚D`5Hø$ žùÈ3øLÏgðXá±XAbçøáY?Äì¯ÏÖ-^ Q;ú$Š…Êè×½2%×fø ¿ùVå}ðþÄÞXšøÊç™(Rí«Â¨ÓFÏx:51~ýOõ>…™M3•‚®ô>Õ»ÀÕ˜¦"T)ò„ ˆ5G&Ó8\”;)Ôr±m½èºµË Eöji1]—'— v¼èù<#š¦Ó²XÛ£ý{-¢^åË3¶NKµ¿ª´Gz×JJAAA4eU:øåó̹`ï^¶Ç”$öÞÆ÷3Œð]£(ì=g ˆn_~Iªÿާª*qÄó¼ W¹ÐMóEb ±\ŠÒsÒià;ßÄ?üÃ>þñâŠ+Þ-[<(ŠQ!ú¾MÓ*£SR`b@•9˲ I~ü–ã÷þ#Κ;«fˆ$Ixê¾§p|ýñú.//!ŒäˆR-ÝÄÅ •©Á, Ø,³4]Ñï…÷I€œL?ü¸Óy@ÚÆy/9 ïÞŸsrÜ“¸Z[õTỌ̈̄XB(°D¿;$Äk«˜Ù4Sy]Ž‹íöÿÃÃé´’¦S~qŠÅ" …Bò«¿¿;vì@OOOKFÑN<¯ºxPŽm³íÊ… ¾œ÷½’T[P‘¤P á¢>@±¬PÀO$ÂÁ,³m'[ë_%§ÓlßZ¸.;îÌ k/M< ¢E‘3ÚvžšÌ4Ãí£×'Šï]:ÍŽ[k;ÇaÇ„ú‘;AAA݆ªVоÛÕrê‹îWï]°Úö ÙOȲD¥Ô‹NÉd2Ð4-(X¯ÒK±L,TPùÌgžDÿFlÛ¶o~ó$þè|<ö؃•‚ ˜˜Rq@*•‚¢(ð<7Þx#6· ¸L ©‘žýò‡.ÇÝWÜÍD Õ#6ÄEÕ#Z¬Òyø¹jEÑD£]$0á$¼p6I“ÍV -7HÀFÈ”&ÅlxÔ®‘€éi<ý›¿ øñ®_ÃK2M¤H»Ðg‹®³É­ó`J¬ŒŒ˜¨ä•ݳrT½ý1ZÍ‚ŠÒA–eŒajj SSSسg^ûÚ×bÿþý-oAD»°¬Úiµ¸·M¢ø>[ŸÉ„bHt?€ ¦nﺬÓwœÐ;(“ Ï10Öçâ‚/êáäyá}äõdt]oT¤áçO¥Xûxª4ÞV‚ ‚ ‚ ¢³e9ˆF©'¨hšMÓÍf¡ë:¡'–…ò¨­jDŸ½ .ø üÿ°~ýÇ‚e¢(Âqœªµ€Üz穪ÜpÛt: UU¡ª*LÓÄxï8+TTDWT¥^ 1q¡EBSEì+"V8Q¡„¯çúQ&SßÓõ‘I`¾´“¢¯Èï1AÀý¥€ ,-Z¹pSŽ(7¨À_äÙdÒ—})µûð–Ã5î“€#¿|¤‰³0šTÆÆÆ0>>޽{÷âž{îÁpàÀÜsÏ=PUccc$ªÑ5x^uAÂ÷Ù$¿,Ç#B8\à˜œdÛ–;0èz˜¢‹ÿæpO Ódk;T•ý/Ëáñ$‰íÏë³Èr(îLN†‘–üwTıí0…ïÏÛÃ#sx o“$ÅE}½öl6.ÎaÛki»¦èø$‘`?¼ˆœ¦…×Üh@DAAA¬<<2%šî«|¹¢(e™L¦ÝM'º©P‘Éd‚ó_øÂY¸îº]°,+&–×4˜ÐÔU\01£,’DӴฒ$á罃 €fœGë *¼X{ÐhTTÊÅAaú˜°Y.²D3ó5Ê'ï–]Ïë„à^ÄÎá#ùRïºï.ªO¼ƒ Ñç¶·5qàÖÑ” 255…ýû÷ãÖ[oÅððpl]OOFFF0::<A«×e}…¦UR1˜ÐŽ|žMúóm‡uÞ¹[ÎSoqøñd™õ \Páý0¢‘(<å_/DDM …ޢģf¸€Ã#\Òé0ºE–Ùµðt]¼î /|EÂHšF8‹’áù}]—-3 ÖfžZ,•bíK¥Øù²ÙP(âb–aÄšhJ´¥œ#‚ ‚ ‚ –Oû•ÉdjF§”“ÍfáyLJG@´Ï󂨪3Îøk|ô£ë!Ër†N’¤x±y€˜À"T¤*ÿÇa@ŽûxÚ.*0f³YœùØ™LhP¼> ¬ðzCª™à{-Vã$zÌÒ}ˆ‰Õ2œpñƒÛ¶Xc;¹ìz¼ð<1‘UB((ñÿk]G)ø!±s_vóeØýÝ57{ü‚ p›£)A¥P( ™Lbpp°æ6###˜››C¡Phy# ‚ V^¸Ïq*•tº2r… åEìË#"…‰-<]–i²mx_ì8LÔ¨UW„GmDá}S-¡CX›=/‚x ?†±í°ÍåÇã"P3d³,ý¯blYô¾q‡Ÿ›×aá÷& OC–N³(ßg¿yäK:ݺϞ ‚ ‚ ‚hžö«YAE„ õ÷öO¥RX·n]ð“J¥š:Ap¢éÔkoãCEöÜùÀËvn¸á är¹@$1 #^?ÅBE4IµH¬oÿ6|ÁÇo?òÛAz»š”×?)ãÆÝÈþp-à÷àI*#.À8p·œñ.¥%ãbJp-åµQx‘ûèé}Ôxr‘uqE„xí™hÁûZ÷€ I\|ªWrI~é¿ ßÜüÍš›|óu¯kþ6IS‚ÊììlSK&“-o AÄJaÛ@_뀫…‰ò^傇(²IÿzÕÈçãûð(FÝ£0?_{=OÏnxôMTð‘åP©E“ãã`£iLœª•²k~žµ¡\hq"¹PŠòÌdÂ~¯y”Jy‹®‡õ\ž{}(AAAD]æ#/¡ªªb~~>˜˜•eùHUûùùùŠß²,ûÌÏÏWüD÷'ˆF8{ÿ7Œú‚Šëº$ ¢(âð·cç“;›;Aƒ(‘{ï½ëׯ‡ëºøÜÖÏ5Ì*Z‰(ŠÈzY¼ò©§Ø…½>ü^3y²¦ãXðRøƒlxcJbÅ WÜÐøxåšP=A¸³kÙ|ZE$ Ÿ#jtYVi[§þf/Úÿ"üË…ÿÒÜ=jM *½½½M‰*ÍF§‹E …ªÛóuÅhÑ‚ V„z¶]ß­ö),‚„;”G„Ԫí ²¸ˆÓ(ççB¯):å‹e-m]ë»,ä”_?OAÆ£]'ˆxº3~=ܑɶÙÏÉ“g.ïE® kÝ> ¢Ó™››«jd›Ñ^jÙ&@öIí†ì“ :“Õ6oËk±6Ê"Ç#¢$I·} }ëú¼¹¢¶ nñÑÛÛ[ÿ¢tø`xoY•Z‚_îUß&UeÔ8á¨`ŽƒÆiÏdàØiǪ׷Y&šT¶oߎ©©©º‚ÉØØúûûF©ŒaçÎØ¿?öìÙƒ;wbnn0>>¬Û¹s'ÆÇÇWìFÄZ§žmÝcŸµjoðÂìÑÉ^W$ú5Ñ$Z¼}©T–ã8ÎÒÓì¹zýÕîqôþr1… ,ŠÂ>¿tšíoLDÊçýèú•¹Ðef­Ø'A¬f,˪°=²M‚h?Õl û$ˆN€ì“ :Õ8oëyl. QV ˲ ª*AÀ÷þí{¸ræÊÆ/¥½ÚpbCÕÕº®ãÃþalIn è}OoíÚ QA¥F•ßq̨ҢÏW¦qPáQ.þ;Ot¾ÊuOdðÁ~°Î5;ìç“ÀÝ‘ë *Káe#%Sõ¦‰$õÑÄȹà¤+,$åË8µ™úûû122‚Ý»wCUU £§§ó(°, û÷ïǾ}ûê§X,bÿþý8xð`PE–eŒcddcccØ·o’É$¦¦¦°sçN$“Iô÷÷¯ÈÍ ˆµJ#ÛÐ5öÉ=ÊÓY¦Óµ;_Ï £Pª±ŒFTK)Öj$iá‘#‹!ŸgµN¯ñÂî…ÏóbùI¹àdš&E$ ø«¿:Ï=wDø½ß›…ëþ¸Æ H’  õù2W’µdŸ±G¡PÀÄÄD`“²M‚hõl û$ˆvBöIÉj·u]–Õ¢–eÁu](ŠQ!It]Çã—=ŽÍØÜàà²Àwþü;xð±133¬âµAúÞ£ß? ;oÃP –ªªÚü‘&ðâîVÙzßÇ/ý÷øúûè‘Ù¼;i¨s}XºÏ^ÐO ňrD’ÏÅų/ÆðÓpy4ÚÅ4™§*Jí4K¿¹PRk.IiâS¦óª'ªH¥í ¦Z}›÷íÙƒ{[ìUÜT„ ŒŽŽbxx–e᪫®‚,˸ꪫpÕUWabbûöíÃöíÛë£X,V·ß¾};fggQ(ÐÛÛD¸ bpp°a±cÇŽ5jŒ ZM¡PÀáÇÛÝŒ%SÏ6ùu.Æ>>Œ©©©v_^¼Ø<ϳéy,Ú¡Zd„e…ÐmÑ©¬`]o¾îJß÷‘N§‘H$®RqÞu]躎L&ƒÜyçC8~ü8!·¼åJ¤ÓiìÚµ —\rIG> e9ìóĉ¦M¬ŠÅ"xà<÷ÜsínJKÂððpÌFÅ÷4¶%ÚI·Œmڶɯ³›Æ¶D÷377‡B¡€cÇŽµ»)-¡ÕöIc[¢tÓØv9çm£ZaÔ_oš&A€QÚPEÌlšÁæ¿ÜÜ0Ô#<‚Gþí\÷óë ¸>oÁ¹iÓ&hšÆŒZs÷±èÄÓ€mãE‘ †`; ²ÞJ´X»^ U™œ>VvÐjÑ"Š‚‡{~ §;-\Æ£]|ŸMäp\ LPiF(Q™† e5T&¨4ãà+•® sqSSSXüøâPƒ¦€‰*_ÿú×ñdxx€ã8 Å€­?pà@ðÿÜÜ&&&Ðßß©©© E³···a‡øÌ3ÏÐK'Ñ6ºå¥³žmX´}>|‡j÷åð ~Mc}„m‡y6«MüË2‹²0 ¶íJ¤c\‰Ú{<]ÖJP~Ï|ßÄr|߇ëº0M’$azz²,Ãu]ø¾Ó4‘ÉdN§‘Ïç!òùY–ño|ïyÏ{°uëÖ•¹Ðed9ì“^:‰vR,155…“'O¶»)-appÉd²"1m‰ÕH·ŒmÚ¶ tÏØ–X;ðÉÌgžy¦ÝMi ­¶OÛí¤›Æ¶Ë9oÛLmîÅPµ>l*üÓó<ˆ¢Tn}ÿ­l»é©N;í4Ü{ô^l›Û†-[¶àÇ?þ1lÛ†ïûL@qCUU&ø5f žLE\,àbF92€ð™·/O»â!n$‰Õ[à2¥q±wYƳ§œËn¾¬r]ù„‘`&²¾QŠz‚’_žw_@ÃBó±{¶„û‡‚· ^Å T §§Û·oÇèè(FGGe²X,bll¬éãLLL¡aÃÃÃU «™±Í›7ctt´å7†Xxž3lß÷ƒ4C–e!•JÁ²¬ªûÚ¶žž\vÙeÍžnUPn›mŸW_}upŒvãºìG–Ù벨“hújðšš¶¸h‹…ÒªZ,õ¤å‹R±m;Rè-¬Wãû>R©‘`QÛò}‰Dº®Ã÷ý L“‡â& ø¾EQ¡%—ËA’$lØpgžù dY†(ŠPUŸýìg1::ŠM›6-ÿ ]AZeŸ›6mŠõá±’$“I(Š‚³Ï>»ÝMYVhlK¬FFGGqõÕW·»ËN7Œm‰µE?FGG±yóæ¥¬Ã¡±-±ÚèÖ±m«çm—+-˜ãTIg™¿/O#ÎyÍs¯aB…_÷ðxä‘Gð7ü þçÿƒõë×ãÜsÏ…ëºH¥Ra½ñô]ª åB‡W¶Ÿ¦U/ª«ø¤Nf%ñbíŠNòðÚ,|]µèYÆ_ žƒuG×áågžÆ74É•~7šKR]$IB¶Ú¤›Zº®F”×€Y ÃÃÃ8åÜs€4UC¥xž½F/€sssؽ{7ŠÅ"öîÝtxÕ<ŠÅbÕP‚h½ò¦iZEQ"×uaÛ6l›IÑJi¦Üqœ@`QU†a@×u8Žƒ\.ß÷aYlÛ†$IÄk_ûÚv_î’©e›@wØg´Š(2Q²QʎüV*ªc%he´ q–eAQd³Y°uëId21Ùl¢(Âóæ‚#T–ÊM7Ý„þþ~8Ž›¬›m{a#¢3à5ÊÃĸÀÁ's3™ t]ÇÀÀ@°M"‘<æÇÁÀÀ@0i›Ëå099 Q!Š"4MC>ŸÇôôtðå˜/å`²m;ð’ÏårÈf³0 —_~9ž~úévߢ%SË6î°OljGe¨jóQ¢ÈR~µ¸†U[YHj1žn«ét:AÀÌÌ ÇišøØÇÞ‰'>A I4M 2¼\"‘€ã8˜™™ªªE±ÂÎUU­+’œwÞz<þøkÚ}K—•n·O‚èFÈ6 ¢s!û$V ¾Ï»€î©çزO‚h/«mÞ¶æwcdZ¡¦ RKЛÌd28¾û84MCß½}€¾¾>(Š8VEAÃÈÖ0°¯Êòr¸H¥ÞœV ùÁ%?@Ï3/·»À3 ÂEÄÒ½jÆ9w²»”ãÕé$ï¿öÚ–Ÿ¯e*Í0>>޹¹9lß¾=–º¿¿Éd2È šL&155…b±ˆ;v¬d‰6ýÛË#J2™ dY†išP¦i*³ Ðu=˜tå)ø¦¢(H§ÓA-ž&(ŠÚ ô@’$d2†Q±íµ×^»êC;ëÙf·Ø§mǽ4­ù}yß»RÅÜ; žŠ @˜,Ì4M¨ªŠ\.ÛG’$¸®‹#G\üꯞY–ƒˆ“(ÕìI„ÊüšMðì³ßpe»oײ°ì“ º²M‚è\È>‰N%‘`ŽOžÇÞ=,‹ý]J¬€ .hw —²O‚h«mÞÖqÂ4ã1òD Û¶cs*˜ QE ð<žçÁ0 ˆ™¸º133ƒ¦0Ñ\†à6ð&„yæí*ûòb÷räÿZ~§ÂÔ_uøöÔ·ñÀ‡ÿ—½æ2ÖÞz4SD¾ðZ9+ÅŠ *ÅbÅb»víŠ- j²ìÞ½CCC8tèFGGÑÓÓ³’M$ÚOdš&|߇aAY–¡ià8NÅ$®ïû" ‡G™8ŽS=o_p§‘ð²Zid›Vµ}òâóKÍÕ…™¤°È­¨àÁSpq4MƒmÛðÏö+e¬zúeOã¢G.ÂÖ­[+3hˆ¨0AC*[VŽ àfØÛ ˆŒx$‹ˆú*2âõYÊà©ØŸwœE³4šîäN‡:¯¤˜4)¨ …˜2Y¹¹¹†ÇáÆW‹ááa$“I‹ÅÀó–è~|߇®ëp]Ùl’$)¼DQ„ã80 ‚ À0Œª,BƒÐµ²XDQÄôôt»oÕ²ÑÈ6ÕmŸº¾°WÕ;\_ ¼P ¢[8pà@Å2²M‚h?Õl û$–]g⇢°É>ßg‰ç™LÂ× ’5-tëR_¾dŸÑY¬¶y[×­ãøj–`UN‰Â£T"ÇÉåráWS‚ÊŽ;044„ÁÁÁvߢÃñ}?æÕŲ,X–Y–ƒ¢ñŠ¢Q)Ñj2&‚´"òÏuë„“v(©T*(–æû>\×…ã8ð<ªªÆÖñH°Z¯a´[EqÁ‚ÊböáûAAÄJÁ£LŒ’'±ï³w†|žÍ‘ñ´Ã² ¤RLLáþQ?ÁÕô~AÑ)x›ë)Ÿ ð<?ÿùÏñÚ§^‹¿¿åïëLDÀD •¥“$)ÕI qÙw/®®r,À³>bª„PZî!Œê(ŸNáÙ¯vmu&þ˜`I™T•5b*è’)ÙzóUz¨¥Q*/jf#˲066[666†b±Ø¦[D´Ï‹[¸ïûèëëC"‘@:ÆÀÀ@:Èó<¤Óiض\.Ã0033ƒÉÉISˆ–âû¬S˜gX.Ç^pZ1מÍvÆËŽëº0M³á6<âIJ¬ µO£Wn¿‚ —Ë5%xäJ³,VY($¦AÄâñ¼] ‚€ë†QïëÖ±¿–Ö‹CN¥˜€’ɰå{1 ö>¢ªÀôt(¼AKǶ«_<ÏÃÜsøÊ›¿‚+ž¼¢ö<0±D`#HžÉdâs&‘)˹¹¹ês˜<àƒ}á„TtßhôJùÔ… „M™H»j!G¶±ÐX,Ì´ò®¯^Ni¢TÉBhJP©ÆþýûIPY£8ŽƒD"L&Û¶‘H$000MÓËå099 UUoxî%ŸÏçcŸ4 J´šL†y‰aaÇVÑ «ïûH§Óp]:[+#NC×uˆ¢QK$PU†a@UÕE¥¯“e9 y]Æ}ƒªªó¢AÄòÂqQ=Òé0-‘®·ß~uãbÉ0ûà‘(é4O!L-¬ªì½CÓXJ'8aAt;<°œ?ÿ Î?q>¶$·4!'OÀ4Mär9äóùxš°R‰ H# 'ª¤ýúKxÂ:€ývݰ0=Ç[žÉT´>Âh˜zóOê‹.kîÀ_Ç/¸ åçk*åAð Zžò'—ËÁu]¸® Ã0*r*Š.¹\Ž¢Pˆe‡{ˆÉr^ßM]&“eYÈf³P‰D"è,\×E*•‚,ËE1Ö‰äóyxžW!`ºn3#‹8lÇT㈠‚X d2ñbÕºÎ&p%),pmÌc^Øÿ|²WÂ1’ë2ÏyîŸ!Šl’X»ï^àùv_*A´ ßgö I¡H WóáQ”°¨|— ‚ º >þ‰âû>^xò¼ìé—UF‡Tãa€¯|÷Q\yý•u7•$ *T\ðHÙä¼ï8€=FSà§§™ ͦëÕ;î‹*¢~­ a4Ëq§kœS«Õæ|ÿškðŠK.iéùHP!âû~G0*ŽÔ+L-Š"\×…¢(= Kt–Åú$ÓdùüÒÙn¸â8\×Åüü|°.šºËó<(ŠY–¡(•=oµh°ZµŽ‚ ‚X:¾_Yhº™}\·ÒÛÒ¶™bÌDQÂÉ^×eïì®ËÆBÙ,{O7 ¶>fûò´¨Ü‹žo„ǵm¶ÿOºhyéN‚XY¸Ôƒ‹$¾ÏìDUú(¼#.Ó°™ ¢s°m6v)3e2œáUU™ðPÏôQøÇ4æ¾p ÎyÑ9Øyé ÕjP˜ÒþÜegá‚ÇËA2Óñe’ÄŽã8€'³c4KQ=´F0 ‡Æ(\TYb‘xY–ëÎív ³çœƒçÏ>»¥Ç\tÊ/¢;á©„t]ÇÀÀR© (Ê‚#M( ±’hZØ'µªýJây^,W'¯{’J¥ ëzEê,I’H$H$à8NM1¥‚ TZ!‚ béxH„µ2™ðo LIªëì'•b¸‰Dé½Ûc‰[/Àä$ÛO’œáÜ™DÂHQ ÓwlLäûa^{r2Œæ•e6ñ<=]ýýž VŽÃDÇrt-·,``€Ùžë†ÑY<ª‹×?!… ¢3©äáû>\×Åçþës8sèL¶0Wç gXÀ‡4<ÜÓƒ¾Tpªw‚Þ_üÚ/pÙ/k®‘’ThÀ„Û—B„k!ƒÕFi$¨¨4ÔO Ö^¶XMG¨‹ÅŠÂô( ±e£££í¾&b‘ð ]EQàû>&''—”FÇ ª{Ä Á_„r9Ö©®&€wú™L’$µ‡,Ë‚¢(¡jÝMÓ iLÓ„eYÌ£IxAA žk!ÛDÿ÷ýÐ[’OÈòèA`¢Š¦Å#A\7üíºatíÀ[žÏ³¿v¶m3'S,Õ—\úí¡z$GÎÆƒ¿þ9ض_¹äWpÙ§.ü2%Ãu×D0 |À÷±~r p¼°Õ¦?… 1"˜ø!)À|'X lÖL)Ú%N¹RÚô¥Ñ” Òßßþþ~LMMË’É$¥_ÅðâÖ<âD’$èºÃ0šör'ˆNÁ‹ôc«Å³’G ø¾Ïrqª*DQ„eYð}?((_ ¾N–å ¶AAÍÃÓý¡‡ºª²åŽN°z{çÁ¢’Ä–¥Rìÿ\.Œ 1Œ¸P‘ɰh€-ÏåB±Å0Ø9E1.lF(~d³a£‚ˆ$…ÇE69\Í¡¤ÖPB’Ÿrî¿ÿb¤ÓTC…X½x³.˜ðÈ. ´kn/µl‡ ‚è<';•ãy^eú*LT©6͹YÁ_ßñAút|ÀF1>Áä8ÀŒ äÙqAzÿØÿ_À¼u0'zzA×saÇP/==_|NS‚Êðð0†‡‡ÛÝV¢Eض ]×v>‰Kb ±Z©5!Ð)¸® Û¶ƒHÓ4á8TUE–p¡3›Í6í-°T_A±Ö‰Ö6I¥˜Á£D¢ÜM“MÀJÛ†G‚˜&{?VU¶¯9ÊÓf B8aËSp B¼–ƒ „%ªÕ|‹¦°h¶‹_è8ˆ×_©ÆOºO?ýx{> ‚XaÄ Š¥ét(˜ðH”r›"1… buÀ£'t*‰âº.›_‰™(¨)N|òº­PÕHÝç€ß—₊¦U¶¿IaÊ'.KBX˜¾§ü"Ú¥_¤Ói‚Y–ï÷òz(4!K¬FL“M`˜feþÌN ˜Š¢BŠ¢(Ð4­ÂîA€¦i Jß`Qy/)åA±Ú‰Ö µ¬0åU9–Å&X5‰(\ôàâI:Ͷó}61Ë.†pÇD"Q¢ÆädýHZËý6zF&˹üò‡ðôÓ綯qѶ¾ ðº¿\ÍçÉ7þ¡ªñ(/‚ buá8l¬Wk*#¨[.Fx`5LJc2×u!vÞ½gŠg†Ûù~ªRÕCQ€÷O§Gy*ê‹%BéüÍfÙ"±¿ãY 266†¹¹9ìÝ»cccØ¿l}?ÇYÈ!‰eÄ÷}˜%÷7Q‘N§!…ŠQ«ò\å¡âû~JO–eôõõAÓ´ºõ…Vªöïûô=@A¬¢i´>Žþþþ`Y2™„ã8A?öíÛ×îë!J¸®‹D"Èf³Ð4 ÓÓÓP…&Q‰®€{¤u¢˜âº.ÒétPXž—ç¶Ønxt}A«]#:R©°.‚i²å®Ë&[Ói¶-÷X·,¶a°eüe\×CAƒ/ç× üÔ´ÖÕj+r!¢’TŠÙp_‹s]&–Ú6³iIböJCZ‚ ˆî'®íÄâ8N8¿á°"+åÒ20ÇRC’ð±w¾/~ñ‹+d .”H¨^ü]KáÅc<4®{"¢~ýbUÑT„ÊÔÔÆÇÇqðàA ÆÖõ÷÷ctt½½½øÈG>‚ƒ¶ûšÖ<¼CyZ/š<%º Û½ÎãÚ*¸wƒ¦ið}–eBŠ®ëÈFòi,4•×rÑl}‚ ‚h¼ÎI*LO3aDØÄ*Okíû¡ ‘É„5L'L–˱}x· Íçkj ™;¤'ˆ®Ç¶C•§êâuQ¢Û‰¦³$‚áûõç},˪=ß" *>s~Ulâä$ð=Õ·× .Âè“rT0áfe’ŒFS*·Ýv’Éd…˜eddÅbSSSí¾¦5DI$èëëC*•B__TU‰)ÑM¸nèa*ËÍlm5¦iÂ4MX–]בH$ òù|‰BvHA͑ɰ‰$ÓdõJ…ýÉ„©¹D‘‰!<âDÓÂq +Û¶V&M^… ˆ•‡§ÖÓu}âº,…ÿ8³é|Ä“—†ÔÄZA×k׈ ˆµŠï×vlñ}žçAæJ¤•EŠ÷qõ}÷±Á¢ °‚õåh¾ ¼ ÀFãÈ¢+YtQúááaÌÍÍÅ–õ÷÷cvv¶Ý×´fp™LÙl6ð8w]ù<ÅÝ óÚã½£ë:<σïû˜œœ ¢T¦§§cÛe³YT‚ ¢ŒVû€×-ñ<&œa4Šª2ÑöÃh]g ïÿ˺_‚ :Ó mzšÙ÷ädFÃgb­âyLLqÖÿ•×"ˆµJ:¯‹ŶíPLª×=Ñ€Ãׯq"LÖB*CFuq†#€‰*zéorÔYS4%¨ôööV%ÑZ*077· è”¹¹9ÌÎÎV§X,¢X,¢¿¿¿bbš&ÇA6›}qÐä-±TjÙ&ÐöÉ™íÂó<ض MÓ‚Ú(µê¢tJŠ/¢{ètû$"·Ë(CCCèééYäW/9šJ±I!‘¢ªLDÑ4¶Mô¸ÜGº+b¹X«ö¹Rø>P ƒý抢Ç=јµdŸ¶ÍúDQd‘)šF¦d2¬ï´mÖ·ærín-±–è”yÛz‚Š®ëÁühŒ²íS©òF^Ýø„X «tœF)À„Ò¶mJEO´‡¦•þþ~ŒŒŒ`÷îÝÁððp Bò‚õãããØ·o_Ãc£P(`bb###±ucccØ·o’É$¦¦¦°sçN$“É5íiË Ì+Šä¤4BÄrPÏ6ΰOb´©èW__EYõbŠ,Ë$¨¬2Vƒ}QÉÜÜ\WNñIRŽç±š'Ù,NÒi¶œO ,ÒD×ÃT]íêË ‚Ó­öÙ ø>›Vö#Šäi¿ |0g l¢Î›Ð[CÞÏÝnŸü½Ö4YhÌFL3™)IÌ–x”A¬6oëyÕS½û¾Û¶+R¯GqKéME Ós‰`ß§õ2q‘¤™©À̲]>Ñ¡4U”`Šäèè(ÆÇÇ!Ë2.¾øb\|ñÅØ¹s' …8P3z%ÊÐІ‡‡+ Ü ôööæàà Q(êïØ±c ·Y­X–…T*EQ`²Ù,òù<‰)D¡PÀáÇÛÝŒ–PË6ùu.Æ>>¼ T€0Í•óTu]‰DŽã NÃ4MȲŒ,åYÌÍÍ¡P(àĉínJKhµ}ž8q…B¡"•A¬Åb<ðž{î¹v7eÙ) ~Áìô±-Ÿ²,ybšL@QU6Ù“H°—ÞÉIæQkÛl_Ft6Ý4¶mæZjŸ­ÛvŽÃ¾xTN»öõÕAõ\ý˜(â ,XlH0Á’4€Ti}¢ô“0PZï”þwÙ>' 'ñø§Ç›¾û¦v_õаPûìÔ±-0˜SSz^xß)I¬ä6uDX¿ªi™ÒétÛØv¹æmËëp/„ò~Ä÷}¤R©êé×¹`V.Á²¬ø<ªUúm68iͨ':–©©©eÛ.¨(ýÈÈFFFbÆÒÛÛ[u‚§|ÛÞÞÞŠ ,ï0{{{vˆÏ<ó …B×y.èºÇqÏ烂óDçÑM/µlX¼}>|‡ZÐwD-‡ FWBÏ0M¶mC’¤ “®(t¶ÊÑb[åÌÎÎv• Òjûä/ÅB´ƒb±ˆ©©©®Îƒ xiܳg …zzzšJ‹Ðic[^W™˜âûa’\ŽMEÓwy^8‰jl;òEX=tÓØ¶‹µÏVŽm»Ç EÖ\ŽMóHµUÏ›o‚y5Ë£F¼ÒN6Aç•þç…Œùúo¹@Ád•CK ÃÓÃTK##¬ž(>ññq|ã¹oàÍxs»ïβ²ûìı-åÓ9¯¾úê–äÓt]6!“Ï/ÿµrÌ—N&IEiš]%Bt“8Tþþ~ŒŽŽ® /ÒÅØç¦M›V}ßI¬^ø8²“£0ZA±XD2™ÄÈÈ8€B¡€Ý»w£¿¿¿îXºÓƶºÎ&JS)&žÈ2›à‘å°&B4ÓBt‡ -D{áN"åé>yª QïM×uqþùç·»ÉËÎbí³UcÛÕß+¥×¼ç5m•Š):”ZvdyaqbÀŸùÀu¾á#FäeQF(¸àK€Qºi“­‘É?Ó Cª1Ùµ4¶]Œ}vâØ–Gh&ì=–×E1M&<.tžE×Wæ}˜X8kelÛŽy[^_¨r¹ÌÙT® ض¬,‡j¦6wØ,TeÕ3<<¼,Ñ‹‹T–ƒj^·Åb±«½x‘ùt:QÊårUSzù~\œ0Mæñ Ilàjša^AI CIyÎMYf¶®³ŽÝ÷ܶºÎŽ­ilÀöÏfÙ——ã°—cÓdÛññž,æÇ¿¨¿&ÀäkÙ~ŠÂ¾·„¯Î£€ü'‘ë¸ÖÒ­áu9{lü—†/éX&nðÛ⃠t„‚‡€0"ßÎdÛš"kûô4 ˜¨Ì•è¢27¢P:nã€à ¬ù~.¿ór 3œH—vÚ'/h99ÙØƒg©xžÛ¶199ˆ™ÜãAQJ·Gt$k±ÿ$ˆÕÀàà 8üŸL&±cÇŽŽŠ>‰Â'HyQ\ËbËøØ²<]W3A²L9ß— ¯äý$Š"Ç,Ëp]žçAÅ@,Çqðî^À£7ÞA‚åw=ù$n{å+qÚ‹_ EQàº.dYƧ?ýi¤y!œ.eµÙg§Àæxš¿U›†h`Íc`€½÷åJ¿ù»Þ§ìð¥˜ÿ=`_°îT€7ìØ÷ÙoEaæ*æ/Äù|ø’„Ŧ,kA/:?ûÙÏÚ}÷–n°OÏ Ç çdø A¬FÚñÞÉç.£¸®[ÕQ$ʱcÇ ô Ì)–'â(X˜¨BUèAeppããã±e³³³®¹ìÝûIüó?__ù•O!Ÿß€u¼ºÎÆ\Ñ—Pßógra#*xø>=|?ô äÅÿ¦§Ùv®Ëöã^„Ž )Š ¸Ï†)TR€)¬¤ª€ÿEÀ9 øÏ±íòÿ@ ð¶Îcìx“»a/€iÀ,×ø9 ž XNx=Ú!À>d^ È7––ð_ðº°}î¥~Pþ¬4.ÝxS€t3½Ÿ-sÇõvþûJû}΄gÙ`ß4Œ‹é1@x{é>¼ßˆ°ð¬ ý ü ðû€ÄÙÀäI@ÐÁÞ[÷Š]¯ÀáŸuwj„vÚgSÑNK>G¦iZÕȰܪ}c$ºµØvøÇÅT•= Kµ™Ž³9bͱÒï¦~}Gi”ŽÝ–lXŸ¶ Š"²†ª›ìˆ¢¨‰%Ð1‚J2™ rÞ'“ILMM¡X,bÇŽínZKà^\íé¹ÿò/ÌãÜs·Á²Jþ`Î+ž Ü3{ cÄȘOáyýl`&"‚ðBxjé»C’ä ”£E]@*RtR…oË—¹€ð›l›|Ññ󀚋œ3Ç~iRlŸ¬…ÐëgJãÐÀ3È‹QæJË@FP8Ê}À#¥Ô%DÿcÿàZ@zþßàsì;TÜAÀùG@z€³°¿ˆ_dx. dÎä÷ö€'õ5@êû¥”¸Ÿð€û(ðð¶GññóŸo÷#¶¬´Ë>-‹½-wº]ס”&ªæà$ˆ¦ÛûOø`ßû0éÏs™×Ãë·¢c|a^NÀtÙ±3¥íøµ `b‰9ÏÙÎ_„}e¬ÿ-õëðJó}Àú`þ?/˜½.¿ÔÒ—L¡PÀþýûqðàAôôô`nniwÓxÑxIЧ#¡€ÌEàºÌ«IÓª'ºç^O¾ã7°eÏxž‡½oz~í=ïÁ¯¾ñ°m®ëÂE¤‚ @’$¼ósŸÃï¾ðœ>\×E>Ÿ‡(ŠxòŸÀ±;ð’ñqì[¿»?ö1æy¿y3›¬E(Š‚­{÷†AÀ»J3r²,CþÙÏB%覉ï;†vyÚ¯Õ`Ÿí†;öé¥wÇ•ˆ__t€ßL±g])‰Ix¿ |2ÇúcWzeàS à J)— ¼ø pJ©2™ølµï‡Å`ìH0Am%yÁަqàDr!zž]×!I|ß"ʸ—5˜‰D°œ£ª*|ßÇääd šÞ|óÍí¾óËÎj´Oß#·ø<·î °T'®ÉÄJ³ÒïµRÇÚ¶éééÊ´ü%^ýåWãŠW`Ûïo sï•#€íßݙЉe¤cÅîÝ»144„C‡atttÕx"D'}]7tdá…Ç|عóIüÉŸœŽ·¾õß!I>>ô¡×bï/`y¯Žá½ÐÆÆd^Ùw€ füâ©°\ÄSU9D•`"ÇûÒ‰nWm_®Úò‰¿´ŸƒÐ³Ö)7šk–/û 8 àL7È€(Žî«•¶K”Î]ž.ýv#máEþJ…þ¤R>[™¯“ã¥óK¥6½̳—HµX-@ ø;®²³´Í;Õ‹´C¼ÿÄßcB >XJ{7 |Þ8`ÛØÚÎGpEh‡}Z%Ñp¹Ê}ø¾Ó4!Š"TU%1…Xµ¬Öþ³*Ä#-¢ýÝJzæ•Gpc²lñ~ Q±„÷Áü7ïW¥}UÄûU aÁD¹t<¥t_œRL0g…ÑqçøR±™ŸúÓ¸£äžÜwï½xÑUWá?ñ ?ò¶{.~Àk~ò|3‘úÅ/ðƒ/} æàm¯{Þuò$ÿõ_ÃÈå Š"<Ïë4 °,üíwâ‹×^x±Ÿ{ûí8÷³Ÿ»aíàí)m#Š"ðþ÷³ÿËgÃ! ãÎå‚kþ§?üC\ÙîÏ`™édûl¾Ïô5þÙ6‡KÒ2OâÚvèM·¬0íWwîð P%àƒ6°9ØJéQl˜1ï–:\¥ç~šõe ‘¹†·Fô‹°ÑÅkZ,·!¯Êÿ¶,+¨‘ê8NP³ˆ¿ðT}ÓÓÓAÍÆji†Wª¶j'°Úì“Ïù(ÊòÚ ¥Ð$:•zïô¼êcÒ :EGèxW&ªÜqÇ~{éû¢VhŸ$ˆEÒ6A%š“3<<Œd2‰b±ˆþþþOW¢ë‹›à5H 6è´¬0,M€nx_ûÚ=pì¿ÀØØ}PÙl6µf³€,‡ï8*UÒ0oQnð\øˆF|ðœ¯Â/á„H·tl0)¿%ºÈŽÁ…ì‹*W:æ—å¡Ð/pƒ\`B\÷U0î—ûÀ×l`NrFè{È"õ€ÀË.²|"I+-â…£x:gS+D€IDAT>Páªrô:ÅÒv9”r¢ÙÀG]àR¸Ú÷ìµ€3½’ #³o‚M‡<ˆ—[ÀC.` ¸ëæ)"à²äã'_¿Ý$¨T³M`å퓇L/§˜’H$ ( £\ß ¢1bŸË ÿÏGþŸ,-“QÙŸ-þ"ZíÂþÆ&Fnðˆ·´Œ®å‚OadeA/`ý‘&fp§†lé©H¸Ð‘F9’Cèà`—~ „ý#`¢bïPÀÉ”öQKÛóÚaji¹ 6ÖˆnÃ…¥t¼ÀñÂnÒ£°KN”\1o÷7fX£~!ï1€¿‘€OXÀí%ï0Y€‹_y1¦®îþº{÷îÅÔÔT¡Ý¶É3ßðÔýçqÞjL³v˜+Ï)Êá OñÃ÷+ ôçN9¿H¥°é¥/eË- _}áüN&EQpaOn·,øÇŽA²mø¾OÜsnÔ4hÙ,~çK_Â}¿ýÛÈ¿êUA“c÷ß ÿ8®Îç™Éz°k6èCè+M«ªŠk\³p$úòRmLSO%“¤p[€|'l÷'·"tš}¶× ¿Jú]k¿€,•Ô"ðrx<ª£ð$à|X_ú`sßø¼pÅ ð=çÌÎ⿯>ýŸ±ð£‰ \½mî¸ÿ~\§2Ï¢·Þñb¼â®»ðü߸âÏl;XIûtœåÉkš&|߇çyPU•)#:Ïó šòÈ[ ü²Y“jQ ¼â°F/òe î ì½Òß™Èþ¼Ï䢃‹Ði@EL Iõ¿<õV¡³@>ò›§úâ}Þ†è÷¢i?‡Gò8Êçgx´ /ˆ¥m„‘) _Þhð˜·'Ÿ`’ü.ð¤Üj¨,t™‡½M9€îŸµý"ðRÐ&ÙOÀ75à]ð”ÀŽÅ£@WŠÀ[ à4ø Ø –Z iPeàÍÞ,‡éÀ¢÷/0U GE)í‰O“ÂÓp¾go·ó<ࣹÊ Oø] •MÆòY3ËÔ¡XàùÒdºSÊMíM±I[×÷¡È2ܯ~Ò“,Ë‚ªª°øC¨ÓÓp}sÛ¶AÿøÇ‘»ürxž‡;|‡ï»C+þÔv?²ÜúA©ã8°mŠ¢@’$SšÄó<¸® Û¶‘ÍfƒÎü^Z–EQ`Û6TUE&“ap]²,Ãó oð À~)à«€ü€°ð‡I.ÕDû€=¦ÀjI€ûW€w ÞxV)ÊnÀ]€x- óIm·®¥ŒA¾ˆXà‡ë²{ãK¥ŒBNéÿÒD¸+~)Ö4Ãû+:ᜱ¨6øþäÂO¹ %!^;…§5J ë‚Êa½³ôÙˆ )¥ÏSaËEþ‹€ŸÞcÿ[Æìñq¢p¢ÝiWcÛaÐ…¦…@@õ—ÔUë²ýôtèU*,x÷g>ƒ¡O~gž< ·”JkÃ߈‡_ÿzNžÄ?ÿò/ã´‹/†(аòÀ4‘ÍfÏó\.A000Àœ¤JÆÆ½É¥Z ²\{P½Òj =Ô¹IyÈaaíÁ³Øñ÷\þ^ËËç,Ù³>êu„…³Ùx{>ÀwKï¹Xd!Ì4ð€Lz€£„é\DÈ—ÙÆòr¡„Û8O£Ç#P¢v#IDQD>ŸÙLµh’E‹)©Tx¯ˆŽÇqâW+•*“RrkÇ©îkïe{Ù; ÏÔ£ðÞóŽüü]8ïïÀú+?@µQˆe‡°IîUÀg¢ð´É™ ë0zìxž¼á·ð‹#¿À¿Ê¿ŽWòÔs*ða¥äMZJ°É½TÀ«À˜ixlð˜ðï3ÀÇMàK à4Ál`‡ ›À'À˽6ñ‘ûbùˆl+õôi!î+0àæÒÿ2âž­B•è!ïùÒ5roáh4 W‡£_||Â¥œj:H¶r‘ÿI™å’à–QƒÉÔL)ÍBt’Ü*…9Žƒl6 Ó4!I²¹,,Ë &c â¢g¢]þ›'Ko†až‡G¿üe^Æçs-âyì½"RËqIðÐ|Û¶™ÀÙ£ÑhËèurqƒ‹`ÿKXļ(|ý$Î_g{Ýøs¼ÒìÅä·àÔÿúo Ü‹o>»ëÿ}=ÄgEÜÿ‘ûñŠWÜ…ïÿl7â²ÿù.~`ŸŽsÎyNœØ€Çqòßü þs¸÷Þ><ýôËð[¿Œéé×âĉØ´i ¯ï^?~ÞAððÌ3Ï`ãÆË±aÃŒŸ‡ Ž ¯ï^>üz€eýžzêñØcá%/y {ì1<ÿüžþzôöþ6lx›6mÂøœuêãäógãô3ÃEÝ‚ŸýìØüô%Ð_üÒð²3ObÇY_Á/ŽñÄuqßOÒ¸ôÒÃxýëÏÀµÇŽaãÆøÅÈî~ß_âZ¥5/-þùY–J…Yá°ûëû¤[48ðµ?‚_¿öáv?®] œ®%žtÍ\:ÿ²Éd‚0ñ‡ÿå_pÚUWáït=ˆ¹Õóð©³ÎB6TU…aÈ€‰ –eazz:˜4UÊnÜôB&Í8m4ÑO5?,Ë‚eYÁø@Ð×ë¥ëÏçóð±Ë=Í9º®CÓ4æ-XÊEÀLÜò¯Yò(äD·õ}Š¢@EäJ/Ü|ÂU„Å žiÐÛrx]ÊV mÛ†®ëPU“““9QÀ˲‘‹@èaZþ»Zä€@x$)˜üÑu¡ÅEj÷ÛJ½ˆY–ƒí¸ÍðÿË'ž¸øÁ×8š±=Þžòsra‡ß'þãyä‘v}¬kñ©ª%ŸDè¨{ mAÐGøßüÛÿWo = Hçò0¹ä¤mFæ#'á}L)r… 8‚hC(M"ò<ç@øÜyži§ä=O¼G &+3¶þÒ,rêœsؾ?yÙ¼õ—áî—Ü^äWÀõ×_ŸoôK˜Wâw_ñÎþÑðüÙgãìýO\wæ¶½ÀϤ°áȼjË ^¿›ÍfßWá§·ÞŠOÁC?ÿ9.¹äÜð ÿY<óÌý8õé§ñ‹ßz7žØ¸±Åu.ùÁð?ßEï?‡c›á—¶o‡ŽŸ@’îÃ\ÑqÐûßoņ pÆg’Ï0pèгøÊWöãȉpÇéßÅœ¼ß=ú*œºñ"HgÁ³³øêW{ðøwïÆGîÀ3§nÀ£Ïý?ÿð98ûޝ}íµøüÏÄ/ýÒ÷qõÕ¿ øö·ãÎ;Â…¾Ïðž÷< @À /ôÀu}lܸ'N<ß7±n]W>s:î”~Nµ —^z —[ú±ÚŠiÆ=ÛKýW‰øÄèé_ú^÷¥/á]„÷–ŠÃžå¥ñ¦i€ãàŒoÓû€Jñ€ þ-£ÎxÃó|>ß÷ƒß¾ï£¯¯“““Aú"Ïó°mÛ¶vúD áõ>yÆ­ò [MáºaMßÏtñè.깞S€“ ð)„é#yí0ñ4žKÀó¼ ’šA(e*@ ¤ðÚ%Ñô\å´=U—m³ï7z¿ì(xI-Ëb¶-”ϯ¬soK»U‚Xnª}Z–Y–qîܹ%1>zùðsOâç‹èù¹ü!šž—$ˆÅ²æ^|(¥ÒˆÔ”㓺 'v]àoù¾q옕gñ[?Œ¿ùƒ/áô·_ ¯tðû/d« žÞF<ºƒ§Ë⢠ÏÉÎ…–茉êyÕ£ÛÈ`Ñ"Ñ8ð£š'P•/¤hd÷âB ÷|Wét:ðx†PótAÜCާ!ð´kfœ/Wgö`¹R‰8$€Ü(`݉ìä5QT@x æÜH7€õcå}™ÊÒlq¸9€`2@):É úUU›³yÏ siEáöǽ.døëØi>ž˜{Ó›ðÂWŽg:„™»îÂyÇã_.¼×oÝŠ9 ˜èü‹ƒqøÔSñâOõ¶·a¦™²õ±Ç°óÉ'×ÅÅ¿ôK8½¯}ÿëA’$ßö6œvá…8þ³Ÿáä™gâûßû|ì± ’ìÏ_ô"Ü{ô(®Ù³ÿoàøÞPêcu]gž¹oyK&˰Òid³YÌÏOãÒ·¿;B6;‚oš&þPÓÉü)r¹R©þèÓ9d2Èf¡ë着øÚ×®À5ל‚³Ïþ&Î;ï<üÅ_äpÚiÇpì+L¹iÓ×00° wÝu.¼ðB<ñÄøýßþçþW^y%þñÏÁ•WzøÙÏ~†Ó7_ÐîǶ«àÕº^;#jÇËòÚ'=ǧ֯ǯýÝßáÞ£GqÝïÿ>nݾg]vpÁ¸û oÀ‹/¾8Kª"ËØéÃ;.(õ<º®#›ÍB¤ÓéˆËÆÁ²,#“Éi0ù/O!&I‰²Ù,TUE—NNN÷Àqœ`ìÍ#ø¹¸(Shd ïë]×E*•B.— œ4ø˜¢¿¿/yÉKÚû,‹‚› °¿¹ÂSp.(Û-ñ¢KsÉçyÂÓ òÂÇ‘€×)̃X{¿­önÙ¤ r±„ÿÍíxºØòhf×u»[5(J8¦Âñ3©o+<²‹§‡/Ÿä]é×Ë.H²@ áÚ}9–e±9­”·R€ÉI$ ÀkòùÚYr¢Å¬YAÅu« &¼h'ÏÐL§5þwãØ´iÎÙrþôŸÿîè(.u/§Å2Š%9°”\ÑÁ¥‚0—|$J"âÅèù—Ct®µÚ2 úÀuãJ?¶Ã'€Ç Ree2hšÔ:ˆzÖ ‚Ô]E1O¢¢JyþéÕV×âþk¯E²ÝèJóú-S¸æJG¥8ŽI’N§ƒ‰Ï\.Lòr;âSåí‹Ù#*]4Âå<Éhô ‹ç®Ž¦ˆÎ°ñ\ó\èð<`~>~ŽL&,x+•îPüüüåmä•U5¼ŽòÏ‚ïÇgÜ£a‚@X=™ÿ]šLàbN"Á¾ÌË"ÔÎ9çœýì×2ލ—2/ðîÒ¹‘Äë«ôp}Ì© ä­êø<«ºÇ)·}ÈSy¤ÓéXš¡ ¸.›ˆæëô}Ö`]gÏUDŒ·m—}á €G}‚ªâÿÝ{/ÞâyøÅßý~ôG„¿úÒ—`ôô@O§ƒÔzÙlöƒÂ0 œî8894§äI®ª*z²YÌ|ï{xlnºî:DNÈÚóþ IØ àÚÒ*ñ»ßÝã+"s‚—”þÿèoüÛ§d‡ÑhM1ï\ÁdŸ¬å^îÜ™OÀòÿyÊ Ç1ñ£i0Í{/zùv=A€iþ²,ãCúDQ„®ë¸ñƃšIïxÇ;…B…BDkpݰ¨tKÓø´’h¤ëpùøM7ᬠ.À§zg>ø RGâ¾w¿Ÿ½ývÀóà•"5AÀãŸÿ<ÞUê‹>ÙâæqOö¨Ð­³Àm†÷í\ÐåBV¸<ªŽ¦µä)‡Êk3”ÿ=YVÐB„`l ; ®‘$ ¹\®"ºÞþö·ãüóÏoñ&–…‡Qü·Ú¨¦VùA4-¬™Å½$¸óX­Nì½S K€6¾³º`}|¶¹SrqÿÍ£µ£QǼÏçýH®TÉqœ ›A”U™Ú·|/I,œˆh ºÖÊÍ6ù,¯¤¯kÞõxÀÉËNB~;Ë´ìûQQ€Rt/ïV‘žN¬^Ö¬ ’NöC–ÃpΪc1ßÏú¾ú™Ï`þ?§qé)Søåÿ¸ÐÉØ€R3ötiߨ(b€ 8ùÜ!/0o"^_DC˜ö‹Ã#UÐ`Y øÀ4 ¯™­GM+ÍßÌ'‡<σmÛÁK_3u øDΪèËŽe--Õ÷à´m®ë¶^Láî¿’L²¼ýÒK1©ixù>€[n¹ÃÃÃpff‚ˆ©Y‚tš}©¨j`Ø÷‰ã°Q{täJ±ßÜÅP–ã_X‚ &Üž¢vÅs.ÕÊÇ,IlÖ­¼rx”F.ÎQ!¤Öz>Q]ËK°ïÁè6å‚«(²ûRí Ãqð’§žjþó%çÎm@¶à&„õµ|„NàÃÇïnü]ÜôÓ›ð¦ï¾ ÷Ýr¾j~5&œ(BØ—hšV݆M3ˆl’ÌLOÇŸaËÂÉB_¾új\ùçŽuÿú¯xØqOÖcï{’‡áî¿ý[L?+‘€¢(Çë7_÷:R^š‘ºrÛ6‚€gñº÷½¯{ßû„‘a\|(OW>Áù’W¾²òZÚ”;ê¹MYQ¡†ÿ.¿ÆFÿ­'“ uö8d[k@tæ6ÚïpñD–á–j]€šËá¾÷¾§üÑá_ðØÖ­Ð4 ï7M÷ÝD|ðIÔ…7ËŠE…ò¨.zl<ÊSjñï‡D"MÓ‚z#{ÞÇA*• DÈh„)'ßDhPt Ýw¥#iyäk5ÈaõÀ3žø>3¿E}åz`ï§·»ì ?ï;ÀhÐeæ¡ aî"Œ<ÉEþç)¢«|ñÈkîTÄ—qфے¦iÃDÔ¯«*e¡t`Šâµ€ï‡¯lét˜Å®SÐuÖÏwó£O¬mx]kI›Õ€“{OâáÆŸÿÞŸ³>¦ÇcýUižãb¥Y“‚ Ï"PÍæêÚ¡ï©æ¶mCÏ—¤>eâMÏ=‡Ÿú"œ*œZòÒ›HâYr0$…¸àÁ…–èÑ@88EÙòõêáT^¬™{ÖñõÜCžyž:±ô[åuM¢ð"ÓÑ*\wñ^@¾ï#•J/aÙEˆ{Æñc ‚€ÇøC¼móf\úÿMóóØ·~=®¾åÀ™¯~5®¹æl¹ï>è}}ffpeô‹„¿ájZ˜Ú*úr˜Í†Q± Ñ¤LSùÑ8½›ÅMßÇUTCeE0M@»À™`ýw€g_þ,°°¿eツ¦iø®ÿ]8Ï8ÀpÁk.¨(Œ&¦NÔFŸwY Ÿù>Ž~øÃ˜ÿ³?ƒ®ë̃¼4°ö}/üøÇ°~ƻߤño¾=û,¦Jé³øäj5‡ƒ(ÂýW»o5AÄpKóŸÙÿŸ½oä¬ïÆÿw ’Ø™M ‡È2›³ …Œ@-Øq³hS$s•ÒîB-•ç[Ø–Ç •§lÛåP©è÷ÐmúÒÒn8´Äž6 ‰[PH#’à 4Ø$!Ù!AÙ$›ƒ'öfÙœÀ¿?nÝ3#Y'Ë’5’߯ëòz-FsÐGsÏý¹¹.~ëºØˆÒü%H§á”æKZ~õƒàïÂa\kP}½3äpWñÏ|A²Ô¤²lY/&e2ÖŸüˆ•zŽÉž ###˜žžv{‰Ê¤‡œ3¤r>>ÙPHö¸ö'Je™YnS7‡¥õKNYˆËd:½ŠVô6Ä=é$€û Bœ¦+M$ÿNx“Å×*vú§SQyoD™4‘×_]×Ý^[rƒZÖ}<ÿXä´& QÜŒ7ÙP•ˆÚKn"™¯ßþ8ný[1ô«!q=ZTݺÓ4^Kˆ:e]&T2™Æ–¶¼}?_Œ¹+Îþ×—Bۥ᣹ð6ðŽÒx[þV:~•CyÉe+µpñ–à É©;nºe¹-îde•ªªîbµV?ò¦Q~!1aBkEö k…mÛn¢0¾’°iÂ)ÅŠªªøþ?ˆßܰ/»í6üñâ‹Bi•Ïãá¿ùœüÖ·â#¥^!n|\w€òÑ‹\ŠÒ¸T.¸vKÔºŽKß÷¾noE_“•:ñ·Ú—¼À0ð£3~„å?Û¶ñëgÿ:Þ²ï-¸$r f>5ãxÓ+òS¯v8/{Þ4M·€eY˜œœó8¢Ñ(4MÃRÅðu•=(åï!T¾-[„Rï#òt»Qž£(P¢Q¤dO³|v*EQ°xÁ¸å—¿Äö׿«$$eDö(•ÃnɉÙ‰r¹œ;ׇìÝ"“Ÿ2få[rÎï‹ùùùªÛÝhˆÙj7ç뾂—º*Ÿ÷z£âwKÌûÉy=U§ÙËòÉFUÈÞÚrŽLÙˆOΩF— _ fÏ(ªÀ{‚5%"àa'êÇ)Å @¬¼…Ø31ܹíβ9§åÈ$‰D¢êu†h-¬«„ŠãxÉ”† L9´W2 ¨` Oìǧ¾ýidþþJœ=w6®Ä•b.Gþ¤tåUP½—I/Ì2"'²§‰LœTfheKý¾_–ú’ŒÍV °²gJ:n|ƒ–Ï‹7RU,>ð~xúéxôƒ„eYH&“xÍK^‚ͧŸ\}ùëJÃJ-ÿîDìt»F¬) MǺ½}Ì0óF·Úcâ±§^úþâÿÉO$½9µ*çK‘sY–ø2Yþàû¿&$QjÍnY–;q³¬¼‘-ÌÙ:‰Ö“üµ€þFˆ†ùÑâ¹³ÏF´4™,(û÷wûPP›ý„“êvLâí@ô…Àäë\,3M©§ß‡.çæ1 qáõW„Ú¶w723”Z¦Ëù ä<òšÇ‘Ëå–UØ0BëF©¥27™ -Ñ߃V6 1<‚Ѻ͡a‰„›$ýã‹/Ʊÿw\{ øÄ'>¿þë¿Æ›Þô&·Ç¨¿7X>Ÿwÿï8’ɤÛ;DN4-±R–HÌ“`Yâ2YÙÞ ù•@|WÈ¡SdâU…ø>‘“¥Æ é4ÌTÊí¹m•jeâÄ?LWåüA´r2)%·aîhº®Ã4Ͳ:Ý5O÷žH”O-©i^º,¦ý$G¼5Mo?dqº4U™»OrŠNùq‘C„Êâ¹izƒ$È‘våsñ¸8^ò˜˜fùtòqY¿69éú)E£¥9Kïã_¦‰ç·írZÎL¦f<w+‘Òé´;n´lxãK3‘BýÄqD\¦RÍÍ"cÆ0 üÉë_ÛŸxÇÇb8vöÙ8zõÕøÑW¸­å,Çú®w‰ä$°¬7µÆq€‘KEnzA<–ÏçÝ‚íää¤(àúk’à-'[cÊ¡Cä°>Ñh”­Œˆü2• DÒRƒW9 Qlµd%DååS"ù¢—–÷·F—súYÀ¡Káð݇qôº£xèØCxòÉ'ñÚ‹_‹¯<ö¤—ÒØpl¾5ò-¼î{¯Ã'?‰ù˜‡~žŽ—^ôR¼ø»{ñþí׉7QJ$ë/L@‰*Ð 1d.â¾í‘ÔÒ¶Yð*eY\ƒ×š^M$—! 9‡˜ª–†¿4EEœœz϶½ábr9/a’N{à âR¹¢I°e<ËdŠ/NJ1ÿdþIÌœeZî]•sœp0ô2/¹¯Žã¸==d/¹x<î&9ä=¸aî=¾Ltø6jšÛ¶‘L&Ý"äkâñ¸Û«NWEQÜÆ ²žL‚T#Ë=rhC¹œ¼÷—¿aYÀä$´Š9å¨:Ã÷—ÓÓå•õ½D~þ íñ+zŒNE¢ÄkÄHXîcâ{Çr{™Þwø¼Š×E£QÜz«·¾[o…û¹>î8à÷~Op LÓıc߯–-A4u×­(ŠûþÕzPù—©¶Íb»,7æd<«KÞjš†ÓOî¾ÛF"áTÅf{Ûù·½ò5òÞæ¡‡¹çžÛ‰Dß’ñªª€¶ PmiÀ€Û´Eèð°¸xj†‡‡Ýy÷ˆºm]$TLStY¬l @>mˆ½$pÿñ÷ã/2 œ© obN†ÇA"‘€®ën7^Û¶ÇÝBlå{4š$“¨—É2V,&n ›™Ló®/oý‹¿p'·<îÏþ ÿïÊ+qb$‚g Ì?ú(~p[×L@­Š¬œñ·tÏö! þN þ~ßõͶqçÅãäo~Ó{}©§¬õd2é&Tä| D´Ü©O¼ ‰»€hiˆ ä½1»u½4¬ÆsÏ!úæ'ûÞ˜’hSü~ê¥O¡øÝ"¬?µ`8~÷©ßÅs>‡;bwàÑùGññ7~_zøK8÷²s1ö{cÐ ³¿˜Å~û^ÒCÖ%(n™Nø€7´Xé}Ê’$r lË·-’îû[…7 Qi83·U}ª´Œü¿ /1#wY¾ŸŽòä zíÄ|ÿOø¶G&o4ˆ–²7ßœÅáµþ—ï+'ôΗ¶A/½ ï»T¾7àõp7à%Š´ÒoyLä{ʺSÕ{ É^L2ñ–.½úMû$—‘½dòJwyKòïÞ÷nŒôhMä°,¯«ë5î1+ø{œ´œÃÈC|+^oYòVNÆq+3eâD^s׺\\­—šLJøWÈm•”r˜OÙkC&CdÏÿp r.QYþ÷÷¨“ëO&“n™Cþ–É\ʼn“Û,ï+““­Àäq­¬¨mk'ãÉ9ç¨&Ûõ>MÍ™» þD‚l,+{iÊÄüLV~Þ%ÿòµÈ–ɆÊÿûÉ„ßäädÇ*›ýs¤É¡é*É$¢Lhú‘ÿõ2vûI¡P@¡Pèöfôçg€= ¤®¦/u¶<À¯øR˜rÔ˜žF*“ZºŸd2…‚¢/*r!@d†ü‰'â´­[Ëj“Çq[É¡öXð%jÞ‘ÓŽ£‡ ¤®‚þ«ÿ„~éCPßþj?z'TµtýL}´TsTʺÄã^E[øÅßþ-žN Ï>ŒaH^v^­½‡n>„+Þýžþ»¿ÃïþÛS8~aøÕ³øèw}…©†2™òAÚçç½®ÞûÒ€æ»Öú¯á2a࿾ó£ïàªSOÀ‰g¼×Ü} Îþͳ·ã^‹MÙ Sþ‡hy)×[Ù"Ö‚¨8­`“¥ÿË‚¶láŠÒߥ.§ÈW¬Ã?ù¯V±¼‚!^Z·|OÙÊV)-ão¡ª•þö·zEÅë¢ðZúÊV¥D‹Õ|é9K\Ty]E‹e÷¸%QÞrÖömJ¯“­r-ˆ š‘ï#+ä *Þ'ã;ζïGõ­G~6â¥íÒ|Ë诩<ÇÇíägOÕá™+}|Ó8u €(`eoBì3o„:0ý¸{˜È]w ,ËÂðp—nØ€Ìg?‹ÓÞýnض|iÂÔ‘‘LNNºCXQk&—äEâï1ÿ•ž‹ßùn7Müýßÿ=æççqß}÷app£¯~5 <‚ÿ“Íbû­·"‹J Ƕn­]#œNןܬLJ ¢væ]±Ÿy“¿ñhŸºK<ð”üï8p¯æõ|º6üØNQ€³U`€=i¯\¤ø’ <1¡ß‡|TÅ“wlÄÜ9s¸å–[ð‹ÇáÜ_ƽ§Þ‹‡ŽÃëo~=î¹*Œ—o}9.S.ä å8~¶?.¼ðBüô§?Å…^ˆÏLMáþ0òùƒä½w úö3_WEa4 1`¦e§øÀ3 Cø/lÃ}š¢á=ƒ/Åο—EqÅû®^ à9ߺåý˜lu™(ùË”:¼Jy¹lÞ ®]þ¡Mª­#Zñ>þuÀ÷>rùd•çåoÅ·N |û’(G¾r[*·O&¦üÄ8¥ý”ɞʲˆâR9v½ÿ¸ø¥î{øÞË?´I­c"‡F©ÜoTyÿþW7Å÷[n³[|^üÌ‹±^´Ÿ©×>çQ Ú_/ëe¢}bfÆÛÞM;_Ì“‹Á²,ožxÊË–±óÕfŠ$ZçVS¶­Ç²,Ü|óÍø·û7ÜyçØ¼y3ÞøÆ7âå/9®»î:å z®¼òJïÅUæ9"ZVŸW>ù4´›Ÿ~£TX9Àiª×ØCðª$ð´ï´T>yúOcᇠxàÞpÁŸ‰Ö#Ï>ó,|áƒø‡=€{Ï;ÚiÔËT¼ëꋱéÚklëxÌÆ]ðzœå›äGÿëáe=†Ã‡ãùSOÅÉ'ŸŒ|ézœÏç199‰#ÿöo8á„0pèN9ÿ|¼î¬³Êz´\ô¶·áÔ¯|§qNãÊ* ‘Ê9=äãòû%]/ùJ´ +Ïøä`ñ<`Â.SÅuîÞóOއâGÄO=Ü ú§›1{Ù¿#ü[¿MÓpÁ__ÅùCwVwå$U$>/@ù½ÛØ")ókþÝn€ht–0oó¥ï€‹|ÕþR~Cõ†Z<äÇJ7KWÚÀíªx\6Rûo8Tz~ƒœà·à$Åk·ŒÏÛÀsp™‹ÏĽûºi¸¿4å1xEi Mù>)ˆíX´€£6p€×D_¦½¡7³Ûz>€»ÓÀš¸/5Ìæ»SÀ©*°QNpfŶÞákõw&€—E_–*£¥còÔx-œfgL–“ʆ…òœùßçÇ1q<4àÏDÂ<üíðº.³å²­¤^v?f¾(/ß,Ó4 —C"!ZxʺÙTJ|XÏJA¨„ÊÄIJÙ,†††0;;‹ññqŒŽŽ6õÚÄE÷ÛÐþóÿ6íµôNNžÇó8òÔ…ØÂ8øŽËýÓ(®Õ¯lì܉ 6àþûïÇÙ=„O_}µ;æ»ìŽ(ÇŸ)u¹e`ÓzÒj|¦>ù#èÇ݆è‹~üz¼¼½tvãßÿ=~01£?;€[_iá-ÿû-øßÉÿ]šÕóÕâ"+&• …Fª5dð¿N©±ŒZcùVßGoâuzuÔë½Òc¢7xLÖ±©u–iÇ1iæu­¾OéÞþ±]5±‚Þ×J|:_ƽÏaæ†S€ßYÞ¨À4 w]×Ý9P ‹!WŒˆ<«)ÛV²m7Þx#n¹åLMMaãÆ¸à‚ pá…â»ßýn·w•¨ç´Ÿ?ÑžÆÕ_©2¬Î«½ÿZŠ gH$=mÛ†=kÃŽ%Ä\«PP þUUñÔSOᕯ|%Þ[º¾Ê¹G¾ùÈ#0 ’±X 333ø@,†\$â^—•O|O* .)%6ÇAºbµ4<Ôù¥m{}é·ÛóCU²•( Zº~j¥Þä5°,Ëmå.“‰š¦A? WvJQj sR¢øY$â4PÞ ­Š¸ûOrb¯zïÓ`q uÇ~ÔP¿7ªû> ÆL7ØßiÔ߈6ØV÷˜ÕÙçf¶µÑ1QìÒv>º^1Œi P W^8W˜ÃáÂaô»Õ”mÍmÃùå­P6_Uö¸?™’Édà8Ž;QP*¡’Íf±oß>D"ÌÍÍaÇŽˆD"u3ž‡FêŒÿž~¹kzÎkuÑÃÄ“Ó]ò‹_àMo8‰åñ×PUÃÃÃß±/zä\vÚi8묳pôMoBz'|+ mo¹Ø--WI¿ìG»¬4>{ì1¼ô˧à³G_‚™{G—Ÿæ>ç8>ýéOcqqŸÿüçqÁ ãš|㯜UÕÎÎ(ؤ~ù,ð{¦­4>>ŒÔ»Œä›åw¼Š™@‘=2=ŠééiÄJ½SìÒ¶î$]&[GE"½?Ö¿|¦û霴C+e[¿/ùËøïÿþoüÇüžzê)œþùxå+_Y6^{Pñš<ýtNÚaµñ ˆÊZy}”¿Ï8ã \rÉ%xá _ˆSN9ùÈGðÉO~ÒTÝÿ[-çgóŽù‡Î’CfÉko­!+™“€Ÿéàé—sÒ.«‰O˲ÏçÝy{d£Ø^˜·£ŸÊQ=ù™¶m·‡’T¼è¢åçd÷Ìk96¿ê 1ó+L_r‡®K¥Req*§SXëyv‚~-é…ï…žŒ÷U LB¥P(`ppÐý€„Ãa„Ãa …º'åÔŸ(øæÂùxÛŸ}ã?=„ƒ7Ý„G}=ôŽ9‚3Ï<ÃÃÃX\\Ä›ÿìÏðå/bii ÷Þ{/þîïþN¬èoÄC¾õ>R(¬éþ†p8ŒK/½t­}ÛMLLö‹¨Ýûñ“ŸüwÞy'^õªWu{s;ª•ø¼÷Þ{1ýø<.¿äŸñ¹ëŸÇ÷¿ÿ}üò—¿Ä­·ÞŠ“O>¸üòËñ¯ÿú¯8õÔSËÞ+húå3½ž¾g~ñ‹_àþûïÇcõ•Vâó‘GÁKκwœ?ƒ·½íÿâ§?ý)žxâ œtÒIؾ};Ž;†‘‘|ûÛß.»V á™gž Lœþä'?ÁÜÜ\·7£-úå{¦™sòØcaffÏ?ÿ|·7·£Z-Û>òÈ#زe pâ‰'âõ¯=>õ©OáœsÎ)[wЭ§kN¯h朰l[;>ñ‹_à»ßý.®¿þz<÷Üs°m¯xÅ+pÿý÷㪫®ÂÆqÙe—ᡇ™gž‰sÎ9GŽÁ³Ï>‹D"gžyõWµì7 ®¯€ˆ¹}´ž>Ó½¢Ù²­üŒô³Vâs~~[·nÅÝwßÍ›7ã„N@&“Á—¿üelܸW]uÞ÷¾÷᳟ý,Þô¦7ᡇrcôÈ‘#8çœsðï|ï{ßûðçþçøÇüG¼ç=ïÁÇ?þq¼ç=ïÁ‡?üaÜsÏ=8õÔSݺ¦7½éM¸çž{pÍ5×೟ý¬»~ÿïoûÛ8çœsðÐC¢¶IþÿÍo~sÕ×\uÕU˜ššÂ›ßüæ¦_ÓÊûÈלzê©8räHGÞ'•Já¿øEËÛ”×|ꪫðêW¿ò'"^sèÎI§Ë^sß}÷AQüò—¿ìvøtÔjʶïØñ¼æœ§ñWæ¿bñ†,,Ërcók_ûFFFðÞ÷¾<òÈšÏýZÒ ÷¼A.W<ðÀ)Û·´´´Ôí€ýû÷£P(àÀîc»víB8ÆøøxÍ×½á oÀüc\|ñÅp/}éK›7oƦM›pìØ1œ{î¹ÝÞ½†Ž9‚O</zÑ‹º½)«öøããŒ3Îèöf¬É~Ü~ûíxâ‰'ð‘|[·níö&wL+ñùÿøøô§?ÇcË–-xì±Çpùå—c``çž{.N:é¤nïVÓúå3½ž¾gŽ9‚»îº O=õn¼ñÆnonGµŸoyË[pß}÷á™gžÁË^ö2;v ¿ýÛ¿|\pA·w©iÏ>û,žy晲¤l¯ê—ï™fÎÉ¡C‡pß}÷á¯x>ùÉOv{“;¦Õ²íÖ­[ñØc!öÔµ²ÒzºæôŠfΠ˶µãó[ßú>ô¡a~~ï}ï{ñàƒö\™VZOŸé^ÑlÙö‰'žÀ·¾õ­nonGµŸoûÛñàƒ⤓NÂë^÷:ÌÏÏãÜsÏu˶ǎë‰XeÙ6xX¶õ¬¦lûäÍgá¨*&¨9ÿüóñ’—¼ƒƒƒ¨¯ úµ¤¾‚ïwß}7~ö³Ÿµ½l˜* Ëk&»õ½ï}¯Û›NÔ÷Z‰Ï÷¼ç=xÏ{ÞÓíM'ê{­Äç7¿ùÍno6QßkµlÛïeDAÐJ|nݺwÜqG·7¨ïµŸÿú¯ÿÚíÍ&ê{,ÛyŽïöHƒƒƒË+‹ÝÞ,"ã“(ÈŸDÁÄØ$ .Æ'Qp1>‰‚‰±Iä LB%/ Ä………ÀŽÁF´ž0>‰‚‹ñILŒM¢àb|ã“(˜›DžÀ$T"‘Ü øæææP,±}ûönoÑºÇø$ .Æ'Q016‰‚‹ñI\ŒO¢`bly3‡ Œc÷îÝÂìì,ÆÇÇ100ÐíÍ""0>‰‚ŒñILŒM¢àb|ã“(˜›DÂqKKKKÝÞ¿b±ˆb±ˆP(ÄncDÃø$ .Æ'Q016‰‚‹ñI\ŒO¢`bl0¡BDDDDDDDDDDD4™C…ˆˆˆˆˆˆˆˆˆˆˆ(¨˜P!"""""""""""j€ """""""""""¢NøË¿üË¿ìöF´ªX,bnn088ØíÍ©»rÒ¦b±ˆÁÁAœxâ‰MïG·÷sqq>ú芷-ˆûUm_V{Žº}~‚¨WŽI?œûZñ¹Úø[ë}k´µÎQÐö£ôÊ1éõsßêµ³ÑóýríìÖ¾ÐêÍÍÍaÆ m;×ký9ï·¸¸ˆ—¾ô¥mÝֵؗf®—Õ&ˆí¥sD­©›@oûzñô²m3×ýVâ³ÛûEíÑJ|éܯæÚ¹Úýl‡Vã3èûEu²|Ôní.c·Ëââ",ËêHÙ¹§-õ¨ë¯¿~ixxxiçÎKÃÃÃK×_}·7©ª|àK^xaÙÏ-·ÜÒô~a??õ©O-}êSŸZöx½m ê~UÛ—Õœ£ œŸ é¥cÒç¾Úgzµñ×}«õ=Sïq?‚®—ŽI¯ŸûV®žï—kg7÷…Vçç?ÿùÒððpÛÎõZ>õ©O¹ï·uëÖ¥~ô£mÛÖµÚ—jñX¹_o{ÛÛ–zòQkªÅæÒRoûzñÙ eÛZ×ýÕÄgö‹V¯•ø Ò¹_͵sµûÙÎ}Xi|öÂ~Q},µ[»ËØí2;;Û±²s¯ëÙ„Šÿƒ6;;»tá….ýüç?ïöf-³sçÎeΕìG7÷óúë¯w+Lª]|êm[Ðö«Þ¾¬æõÊçp-õÒ1éås_ï3½Úø[Ë}kô=Sïi?zE/“^=÷«¹v6z¾_®ÝØjyCä?÷½ò™þùÏ^¶þ………¥ /¼pivv¶-ÛÚé}©r¿üû±uëÖ¥|>ßsçˆZW-6—–zçÜ7ŠÏ —më]+WŸÝþÞ¡öh%>ƒrîW{í\í~®Öjâ3ÈûEuº|Ôní.c·‹ÿ˜-,,,mݺu馛njjú=zr•B¡€ÁÁAD"@8F8F¡Pèö¦UÝÖjÝÊšÙnïçÐÐFGG‡W´íAܯFûÒÊ9êöù ¢^;&½|îk}¦Wk½oõb³Þ9 Ú~ô‚^;&½zî[½v6z¾_®A8GÔšl6‹p8Œ¡¡!÷±^úL/..ð†@(ª·u-ö¥V<‹ED"‘²Ç·mÛÖÔ~íQkªÅ&Ð[ç¾^|½l[ïZ¹šøìö~Q{´ŸA:÷«¹v®v?Û¡Õø ú~Qc,µ[»ËØíR(°°°€±±1"þMÓĶmÛnÃzˆƒt{Z177·ì&~ppÅb±Û›VF^|öìÙƒB¡€Œctt´©ýèö~Ê/žjãÜÕÛ¶ÅÅÅÀíW­}YÍ9j´ŸëQ·?³+Ñëç¾Ögzµß+k}ë}ÏÔ;GAÛ^ÐKǤ—Ï}«×ÎFÏwã{§×Îfž§à™››ÃÔÔn¸áìÞ½»ìñ^ùL‡ÃaŒŽŽâ£ý("‘ˆ›”7zA/ÛÖŠÇH$âî âsjjʽùí¥sD+W+6ås½rîëÅçþýû]¶­wÝ_M|á{‡V§Õø Ò¹_͵sµûÙ®í—ë­T/>ƒ¾_ÔX'ËGíÔ‰2v»‹E abbSSSÀèèh[ÊÎý '{¨ÈŒ¢_­V’Ý$3¢ccc¸çž{°oß>d³Y7#×h?‚¼Ÿõ¶­—ök5ç(Hû½tLúõܯ6þ‚´oõÎQ/íGPôÒ1é×s¿šmÒ~õsù†–[\\ÄîÝ»±oß> ”=×kŸéwbÒÊ›À~(ÛNMMaÇŽˆD"n‚³×Î5¯^l½wîkÅg¿”mWŸ½²_TÝjâ3hç¾Õkçj÷s-UÆg¿ì í.µK§ÊØíR,ÝÞ&ccc…Bصk—›YïqГ •jÙå f¹Âá08àfï"‘¶oßîV84Ú ïg½më¥ýZÍ9 Ò~E/“~=÷«¿ í[½sÔKû½tLúõܯfÛƒ´_ý\¾¡åòù<Âá°;ÆÂÂæææ077×SŸiÙºî†nÀøø8LÓÄìì,öïß¿êmíögzqq»víB6›ÅÞ½{±wïÞ¦·-HçˆV¦^l½uîëÅg¯—m[Ï ïÕ·šø Ò¹_͵sµû¹jÅg¯ï *µK§ÊØí …°oß>D"wD‚‰‰‰†Û°â '*ápxÙ‰XXX\¶KfðýüYÇFûäý¬·m½´_«9GAÚ è¥cÒ¯ç~µñ¤}«wŽzi?‚¢—ŽI¿žûÕl{ö«ŸË7TÝââ"öïßýû÷£X,⦛nÂM7ÝÔSŸéb±ˆP(TöYD"n º^.Ûîܹ¡P¦i– oÑ̶éÑÊÕŠM ·Î}½øìõ²m«ñôý¢ÆZÏ ûÕ\;W»Ÿk¡V|öú~‘ЩòQ;u¢ŒÝ.‘HdYÏ™~¨3k›5˜ø¾#†‡‡—n¹å–¥¥¥¥¥ÙÙÙ¥áá᥅……noV™ë¯¿~iëÖ­îv-,,,mݺuéúë¯oz?‚°Ÿ;wî\úÔ§>µìñzÛÔýªÜ—Õž£ œŸ é•cÒ/ç¾Z|®6þº±oÕö£Ñ9 â~]¯“~8÷­\;=ß/×Înî ­ÞÎ;Ýs·´Ô;Ÿé›nº©êç6ŸÏ·e[×j_jÅã-·ÜRöóóŸÿ¼çέNel.-õιoŸ½P¶­W–m5>ƒ°_Ô+Ï œûÕ^;W»Ÿí<þ+Ï^Ø/ª­Óå£Nhg»–†‡‡—fggÝ¿{±Î¬SzrRzÇîÝ»144„ÙÙYŒW›²›ää¹;vì@(Âìì,FGGÝ1ûšÙ ïg½më•ýZí9 Ê~I¯“~>÷«¿ ì[£sÔ+û$½rLúùܯfÛƒ²_ý^¾¡•é•Ïô¶mÛP(°uëV ¡X,"»““®v[»õ™.‹(‹ØµkWÙãcccï©sDí×+ç¾Q|öjÙvµñÔý¢öè…s¿Úkçj÷³“Åg¯î .­…noßÀÀÆÇÇÝùgä<šýPgÖÇ----u{#Z%$ ºÛÐÜܜ۵©Úv6Ú ïg½më¥ýZÍ9 Ò~E/“~=÷«¿ í[½sÔKû½tLúõܯfÛƒ´_ý\¾¡•é¥Ï´|¿ÁÁA„Ãá¶nk?Ó½tލ½zéÜ׋Ï~*Û®dÛzy¿¨±^9÷«¹v®v?»©_÷‹ƒñ¸>4‹™L¦j!7ŸÏ»q><<Ü“á^ÇXí/«½v2Vƒ…ñLí¾÷\͵”± ŒÕ`j5VyÚú1.þˆÍvëÕ¸\W •~dš&Çéöf¬J,C2™Äôô4fff`šfOQ¥~ˆÏVضL&ƒ™™7®óù< ÔUë5W#ŸÏ#‹!“ÉT}>•JarrÓÓÓ˜žžF"‘` [Zµõ««¹v2Vi­ôC|®õ½g½ødlR§¬×Xå}(]?Ä& }P1 [¶lÁqLJD"±ìC+3Þ7nD*•B*•r¿h-ËB,ÃqLJááá²/î‘‘äóylܸ7nD>ŸG*•ÂÆ±eË–²,êJ–­G®§r{”mw=–eaxxÇwb±XÙkj=Wï5Ílo£ý–_&Éd ( <ˆh4Zwß-Ër\g½=þó»’×QçÔ‹Ïz±)Ÿ¯ŸÝˆMÿºú->›‰—jû.Ï¥¢(îoUUkŸÝÇx,×JÌu;«íw3¯óó+Ð4 ñxš¦-[Ö4M(Š]×Ýe5MëË–dAÒ‰XšÿöJ¬Ö{®Û±Zkß[½vŒÕ è—ki­ëI?\KÝ{®åµ”±Ù=¬'*Äki«õD¼í]ý—ÀÊ®£AŒËV˸}[»Ô§<¸`)N/----%“É%KÉdriiiii~~~IQ”¥ÉÉÉ¥ùùù¥x<¾`izzÚ}N¾vzzzIQ”¥ƒ.---•­'N/{]×ÝíXɲõXŠÇãKóóóK333KŠ¢,MOO»ÛÜÌñû+ß[UÕºÏÕ{M3ÛÛÌ~çr¹%]×ÝßÑhtÙþTÛ÷L&Sö¸ƒ…ñX®•˜ B<ÖÚïz¯«‹•ªUðT»©ð—•¨ý:«KKÍ{!Vë=„X­·ï­\;ý«ÝÓO×ÒZŸOù\/_KÝ{®åµ”±Ù¬'*Ôki«õD¼íMë%.åsb3¨qÙj·_ëoûvÈ/˲Ün~’ªªîÿÇ)ëvë_Ö¶mX–…ãŽ;Îý B·¢ÊýY ÇqÊöÒétÝç꽦TUÅää$t]G:F<_v¼«í{e·iEQÊÆœõwÇówukô:ê¼zñY/6Ƨ|n­â³™x©Ü÷o~ó›0 333H§Ó8xð ,Ë*;šñŒÇr­Ä\Pâ±Ö~×{]­Xl¤Ú{1V;‹±ZŽ×Îæâ•±º6ú->W›rŸƒz-mtï¹V×RÆfw°ž¨\¯¥­Ôñ>´71.Ë9.[)ã6óº^ŒË¾M¨TC¸R­“ Ç2]=xÜŸN|»©ÞdH¦iâé§Ÿ^ÑkZ¡ëú²`kö‹§òüUn—¦iÈårH&“ec06zu^£ø¬÷Éø\»øZ‹—‡~ªª–Ų®ëe¯e|ã±±Vb.(ñØèuµb±MÓª®·² OíÃXml½^;ëa¬® ÆgcA¸–vêÞ“±Ù;XOÔX®¥­Æ*ïC{ã²± Ä%ЙûQ 7ã²o*ªª"ŸÏ»Û²¬²ŒW4-ûpU>gY–›s[¶l)›Ø¨×èº^vëŦ|žñ¹6ñ ´/^x!lÛv·M¾Î¿mŒÏà`<–k%æêÅp;µõ^W+›9NŽã”MRhÛvÙd¡Ô^ŒÕr¼v6¯ŒÕµÁø,Ôki§î=›½ƒõDå‚z-m5VyÚ›—å‚—@gîGÞŒËt{:%ò,lÙ²Åý2öN4MC4Åðð0TU-Ër©ªŠd2‰‘‘÷µº®²p£ª*R©r¹\ݬ®Ü~y<,Ër3¶µž«÷švQétÃÃÃÐuÝ=Öñx¼©}O$PU¶m»ç­ùçwÞŠ^GQ/>ëÅ&Àø\Ëø”û°ÒxyÃހÇ—_MÓŸÅx,×JÌ9ë½®²ROÆb4mª¥X:F,+ÛçvÚÉÃX-ÇkgóñÊXí<Æg¹ ^K;q﹚k)csí±ž¨\P¯¥­Æ*ïC{Óz‰K¹½b3¨q)·¿÷£ÕôJ\Wš4¦oY–厷ç/œ8Žãvrº®ã¸ãŽÃüü¼»œmÛ°mŠ¢4U±Ð r+÷¯ÑñPUuYv¿Ösõ^ÓîýhöX›¦‰L&ƒééi˜¦Ùñ×QgT‹Ïfb`|6óšÕZm¼¬U\S{0«•Ä\ã±Óq%k'ËTޱZýx¬×kçJ×ËXí,Ægõã”kiå~áZÊØìÖU?A¹–VîïCׇ~Kÿv6›A‹Ëµ¾ z\ö}B¥Û¶1<<ŒÉÉIhš†L&˲0==½æÛQoÂ$]×›î>ÕŽõ¬å6¯†?°Öâu´v‚›r[VûY_ëxiçû­u¼0>ƒ‡ñØÝíõãuêé·XmçzÖr›Æ-×oñÙ«±¹Œëõ#(ñºÞ¯¥k1lŒËîo3°ö÷£A˾ò«UU‘ËåÜqÙTUÅäääšo‡¯Þv®åz‚ö^õ¶¡•ÌdÐ2š´\PbhÏg}­ã¥ï·ÖñÂø Æcw··r}¼îQ-ý«í\ÏZ¿cŽ*õ[|öjl®v;×ëCPâu½_K×c<Ø—Ýßf¹®µ¼ z\®Û*DDDDDDDDDDDDÍ:¾Û@DDDDDDDDDDDtL¨5À„ QL¨5À„ QL¨5ð‚noÀjýó?ÿ36oÞÜíÍ uì±Çƒ¦i8÷Üs»½)ò“Ÿü÷Þ{/^ò’—t{Sh»ÿþûñ»¿û»ÝÞŒÀùú׿Ž3Î8£Û›AëØÑ£G188ˆ+®¸¢Û›8,ÛR·±l[݃>˲X¶¥®bÙ¶:–m©ÛX¶­e[ê¶N”m{>¡’N§ñû¿ÿûÝÞŒU»ýöÛ±iÓ&lÚ´©Û›²j7Þx#®¾úênoÆšíÇí·ß¼é¬ð•¯|ÿõ_ÿ…k®¹¦Û›²jýò™^ß37Þx#o:«Ø³g~ï÷~¯Û›±j‡¡C‡úâÆ¥_¾gš='‡€¾8wíöùϾ/> ëñštÍž–m«³, ÿôOÿÔß[ëí3Ý X¶]Ï}îsxó›ßÜíÍX5–mƒ‡eÛÕ zÙ6è×’^ø^z¼w¢l»æ •b±ˆb±XöØÐÐÊž…B…B ×·aÃŒ¯õn´]6›E$A$éö¦¬ÚÜÜ\_œ“f÷#›ÍöEKµF±é_¦™ø<ï¼ópöÙg¯«ÏBЭÇ¹¹noj[´;>_ô¢õÅgºP( P(ôžôË÷L³çD.×/ü1êÿŽm&v+wÞy}ñYXל köœôKÙ¨›•ÏIõâó%/y ®¸âоø,¬·Ït/Xoe[ ½ñyæ™göÅgšeÛàYeÛv×Û½lôkI/|/=Þ;Q¶]ó„J6›ÅÔÔTÙc@$ÁÄIJÙ,†††0;;‹ññqŒŽŽÖ]_8^ë]èˆ ðVêÀÝÞîG êÅ&€Ç祗^Š'Ÿ|²Û»ÕýòYà÷Lïjw|ö˵3Èß•ê—Ït?“fe³YLLL`hhÅb¸îºë000Ð0vû¯9ÁÓOç¤õbS>¿^㓟éàé—sÒ,ÆguýTŽê—Ït?“fµ»Þ6è‚~-é…Ï`¿ÄûJ¬yBeqq±æ…0›Íbß¾}ˆD"˜››ÃŽ;‰DšÊxÑêÔ‹M€ñIÔMŒO¢`*‹Ø¿?n¸á7Q©ë:&&&066Ö0v‰¨3Å&ÐøÚJDÁø$ 6ÖÛ5vüZ¿a¡P¨h…BƒƒƒnÀ†Ãa„Ãá¾é2GtµbS>Çø$êÆ'Q0‹ED"‘²^_Û¶mÀú±KDÓ(6Æ'Q·0>‰‚õ¶D­iBeqq€˜ ÷¢‹.Âå—_މ‰ b¼µÊ€\6n_¥x»víZËÝ ríÚµ 7Þxc·7cÕêÅ&Ðz|ÞxãÈf³ÝÞ=Z‡æææ°k×.>|¸Û›²jˆÏÇc×®]eë!Z+r¨€Ç¼Û›²j‘H¤¬‹ûââ"¦¦¦ …Æn-,ÛR7õKÙ¶^lÊ¿•Ç'˶Ô-²lûÀt{SV­ñɲ-uS?•m;YoÛOs@QïÈf³)Û®iBE¶DÃ=÷܃}ûö!›Í¢P(”µFšÜh=ŽÕFÁpàÀ\}õÕÝÞŒU«›ZŽÏ«¯¾:ðãQR ‡Ã8pàÎ<óÌnoʪu">Ï<óL8p çÇ»¥Þ4::ŠññqœqÆÝÞ”¶šššr‡=m»µ°lKÝÔ/e[¿ÊØ_[kaÙ–ºE–mÏ;ï¼noJ[µ+>Y¶¥nê§²m'ëmûeOê-ããã)Û®é*² E"lß¾Ýí6V©X,2àˆÖ@½ØŒD"ŒO¢.b|Ûââ"vïÞb±ˆ½{÷– ƒP/v‰¨³jÅ&Àø$ê6Æ'Q0±Þ–¨9kÞC¥²‹×ÀÀ´•ÝÄ8n&Ѩ›ã“¨›ŸDÁ¶sçN„B!˜¦YVÑÓ(v‰¨³jÅ&Àø$ê6Æ'Q0±Þ–¨9kšP) ؽ{·;&Ÿ¬ÌH$‚……·çÜÜŠÅ"¶oßÞícDÔ÷êÅ&Æ'Q1>‰‚kbb‹‹‹Ø¶m …‚ûS,Æ.uN½Ø_[‰¨sŸDÁÅz[¢æ¬é_£££˜››ÃŽ; …0;;‹ÑÑQwœËññqìÞ½CCC˜Åøø8["­F± 0>‰º…ñI\ÅbÅbqÙ$òccco»DÔb³™k+uã“(¸XoKÔœ5M¨ÀÞ½{177çv ó·2E$A±X\öuV½ØŸDÝÄø$ ¦ñññºT7Š]"êŒF± 0>‰º…ñIl¬·%jlÍ*êNXÄ€$êžF“‰1>‰º‡ñIÔ›8Q'Qp1>‰‚‹ñIÔ=¬·%ªoMçP!"""""""""""êEL¨5À„ QL¨5À„ QL¨5À„ QL¨5À„ QL¨5À„ QL¨5À„ Q-'TQ(077×í} """""""""""ꨖ*Ùl—_~9víÚ…l6‹B¡]×™\!""""""""""¢¾´â„ÊÔÔ&&&pàÀ8p‰D0::Š;wbqq±éuÍÍÍ-[¾X,¢P( X,vûØ­[Õb`|ã“(xdü …šÏ16‰Ö^½Øô?Ïø$Z{ŒO¢àc½-Qu+N¨ ŒŽŽ"‰”=>66†P(„ÙÙÙ¦ÖS,±sçβå'&&°cÇìß¿;vìÀÄÄD·ѺS-6Æ'Q0>‰‚'›Íºñ·gÏìØ±Ã½ñdluO½ØŸDÝÄø$ >ÖÛÕö‚n½ñž={–=–Íf±oß>D"ÌÍÍaÇŽˆD"…B]=HDëIµØŸDAÀø$ –b±ˆýû÷ã†n@8躎‰‰ Œ16‰º¤Ql¼vu 㓨7°Þ–¨¶÷P‰D"˜˜˜X6_ÊÄÄŠÅ"†††®#›Í"—-[(088èö| ‡Ã‡Ã5»QûU‹M€ñIŒO¢à)‹ˆD"n…lÛ¶ ŒM¢.ª›¯DÝÄø$ >ÖÛÕ·â„ʶmÛ0::Š;v`Ïž=˜…®ëÈf³ÇÀÀ@Ý×ÏÍÍajj ñx|Ùã•ÍÁÁÁ†cò=ðÀصkW·#­S»víÂ7ÞØíÍh‹Z±)Ÿk%>o¼ñFd³Ùnï­Csssصk>ÜíMiÛþ´3>>Œ]»v±‹6uÅÄIJÙ,üñnoʪE"wNAX\\ÄÔÔB¡˶ԓú¥l[/6–m©÷Ȳí<ÐíMYµNÄ'˶ÔMýT¶:Wo[Ù0Ÿh-d³ÙŽ”mW<ä×ÄÄ„; ½œ„hhh‘H¤a2eqq»wïÆ¾}û–-+[#ø5Óeì¼óÎ+»­¥ôÅMU½ØZÏ«¯¾ãããÝÞ=Z‡Âá08Е’ˆÏ3Ï<“×NêšÑÑQ„B¡¾kÍ655…l6ë–“«•X¶¥ ë—²­_el,ÛRïé§²­_»â“e[ê¦~*Û²Þ–úM§Êm+N¨‹ELLLà†np/xÍÊçó‡Ãî0 ˜››Ãàà «¾—¿(uF½Ø ‡ÃŒO¢.b|›¼ñ,‹Ø»w¯; c“¨»jÅ&Àø$ê6Æ'Q0±Þ–¨9+N¨Äãq,..º­*U{Ìoqqû÷ï 鍊n‚;7‹ßÂÂ'6"Z#µbSދɸ$êÆ'QpíܹCCCËZÞ16‰º«VlŒO¢nc|ëm‰[qB%ŸÏ»$Ìïž{î©ùÚÊn6»víÂØØ˜›„‘ÐH$‚¹¹9‹Elß¾½ÛLj¨ï5ŠÍH$Âø$êÆ'QpMLL`qqÛ¶m+æ! 16‰º¨^l2>‰º‹ñI\¬·%jΊ*ãããl||»wïÆÐÐfgg›šäžˆÖã“(¸ŸDÝQ,Q,—i?66æ–™›Dk¯Ql¼vu 㓨w16‰„'Tüæææ°°°àŽã¾R•Ý;GGG‰DP,ÝÖ D´öªu½f|ã“(854bluG3ŸDÝÁø$ꬷ%ª®¥„ÊÄIJÙ,ÝÇB¡öíÛ·êɈDÁÅø$ .Æ'Q016‰‚‹ñI\ŒO¢`blǯô…BÙlãããøÁ~€{i"‰`çÎÝÞ"""""""""""¢¶[qBejj £££uÇÉ …BØ»w/Ë&#"""""""""""ê+N¨,,,Ô|ŽQ?ZqB%‰`jj ssseOLL X,bhh¨ÛûDDDDDDDDDDDD”Ï™Lùc¦ Øv··¬±'TFGG‰D°cÇìØ±»ví‚®ëî¼*ì¥BDDDDDDDDDD|†!XVsë«L”ضxÊÇlH¥Ç?†!’*~##ËÛ²¥»ÇkÅ Ø»w/n¸álß¾ápcccøÖ·¾…ÑÑÑîî Ñ:ç8Ë“޳¼ˆe‰Çü‰‹‘‘àð'QR©å¯)ÿÛ4Å{Êu^ÂF>º(Šx,“b1±¼®/ß6ÓôÞGn¿ý0<¼vǵ¥„J¡PÀÄÄÆÆÆ0>>ÈçóX\\\»-'""""""""""¢ed2Â/Ÿ_ÞŲU‰ ÇɤÅð°XG>/þ–ÏâÿþõËçÅKƤRå ÃðÖ©ª€¦‰×ªª—Œ‘ëÊçźE‰DpÝu×aqq…B¡ó[MDDDDDDDDDD´%åËd‚H/EIŠDB$"†‡Eò!™ÏË!r.ù˜LÌÈž+2)Šå Ã{®—ÿ­iÞ{†—\IJ©”XFþÈž'ɤØv]÷’6¦é­G>¦(Þ¶Éý°mñÿjÝw Vú‚b±ˆP(´ìñNHODDDDDDDDDDÔA²7‰2Kö,‘ÃvÉ^þäŠ|Ü0ÄãŽ#é´HFÈ^rɤ׳D®KUÅ[r>•hÔ›t^&WdE¾nzÚ{?™D1 ñ¾€—\Ä\)29{C~%“^‚Ȳ¼ÇeF&mdÂEö˜yç;ÛìWÜCehhSSS(‹eOMMann®j²…ˆˆˆˆˆˆˆˆˆˆˆê«¶ªÚdð’œKD&;LS$,KüȤ„œ¯D×½ˆãx Àë]29)¶í%(TÕë"{°È„Œì-"$Ñ«¼÷’Ã}ù·G×½eåûúÿ/וLŠ¿ççÅï\Î[F&YÒiñ¸X±DÂÛîcÇ6´ýü¬¸‡ÊØØŠÅ"t]G$,,,`nn{÷îeB…ˆˆˆˆˆˆˆˆˆˆhä$ð2™ Ù¶—0‘Ë¢‡¿§I<.z¨d2¢WH&S>ñ{4êMö®iåChÉäE*å=¦iâ5ÑhiCb@Þð¶M&6lÛKär€öI@›öæSDÅO¾G%¹žx¼þ±šœ,ÿ;b1ñøð°— ºõÖWbëÖöž§'T`ïÞ½ÅM7Ýľ}û˜L!""""""""""Z!ÉÊ*r¨.ÙD&Pääðé´H„är"!“¹œ·.Ù[DN6ŸN‹žþÄ 1Råspõl¯'H:íÍ_"é:€Òü.þ¤ˆ¿Š\jƒƒ’P‘€©\Ÿ-ó¶ozøË¿\pz[ÏSK ‡Ã‡ÃmÝ""""""""""¢~"ç8q{{TaÛ" ¡ª^"ÄqD²¿eÏÀ›D&Xä<)rh,©2ù '‡¯\ðzÁT¥“€£yÛ'ç`)߈d‰Rg]@u=÷ÏÏá…Î ŠäŽ]M-m°z—HìÈyetÝD>o╯<@dµ§¯LSs¨LLL`ÇŽØ¿ÿ²¹Sˆˆˆˆˆˆˆˆˆˆˆh9Ç='*{žT’É€T زEôXI™‰Å¼yNl[$GEü­ëõ6’Lš,ë5Òð…oN–ê;[Z®Á¾Âl¼ŒmÛøîw¿‹Å-.{.‘H ‹!/³K Xß ©N¸Žã@QtBS=TFGG±}ûv 7©‡±}ûö–z©ÌÍÍaaaƒƒƒË^_,Q, …8„Ñ«›ã“¨›ŸDÁ¶¸¸ˆ………²ø“qé744„no.ѺQ-6Æ'Q0>‰‚‰õ¶í—ÉxCmù‡Á2 ‘‘=<’I¯—‰œŸÏoÙ"z”Èu9ŽÒª2)ÒLBÅ0ZH¦€‘™¬³Œ@Gã„ z²ÈçóˆWLš’J¥ ë:6oÞ S5±;à8LÓ„aÈårP¶mò,¨Ð𲧃mÿ#Þô& ¦iÂq|ç;ßÁæÍ›Ût&…¦‡üÀ¶mÛ°mÛ6ÀÔÔ&&&Vœ\Ù³g …B¡ŠÅ""‘öîÝ @ô„Éf³Âìì,ÆÇÇ1::ÚÖ&¢êêÅ&Àø$ê&Æ'QðÉ–QãããîcÙlSSSeË8p‘H{»œQmÕb`|ã“(xXoÛ¦)’²w‰aˆ„ˆœ8].ã_ËÄãÞ$ôrbútbž’ÜJ¶Â#‡[1 b¨®zˆ¤‹RZp“Q_¶çÖ[oņcp}êz†]סªª{mPUº®ã¹óžÃ9ÿvîÇýØúŽ­˜™™®ënï“X,MÓpí+®Åø‡çñ…Yº®C×uÀ;ÞñœsÎ9m=Ÿ-Ï¡âO®ÌÍÍᦛnÂG?úQ|ìc«™X‘Ë}ë[ßÂÀÀŠÅ"t]Çèè(Âá0²Ù,öíÛ‡H$‚¹¹9ìØ±‘H„O¢k›ŸD]Âø$ ¶‰‰  LMMall¬ì¹ÅÅEVuI½ØŸDÝÄø$ &ÖÛ¶N&:jI§EC×Å^é´X^U—ψå4MôF™™%“Þ„ôâM!’õzš˜2¦ËÖu/I³"QñË8¥m*%l2™LÕ¡·Nùà)xâsOÀqÌÌÌ ŸÏömhš†h4ê¾æØ_ëàŠ/]éééeëšœœ„¦iÀpæ_œ‰ôÁòIY^ûÚ×¶°£õ55‡ŠT(011áþ=77‡]»v!›Ín¸á†º½TŠÅ"FGGÝnš2àP(088è^0å¤÷…B¡í;MDåêÅ&Æ'Q1>‰‚mhh¨,Áé'[÷ÑÚ«›ã“¨›ŸDÁÄzÛÖmÙRþ·a7ŠÿÛ¶HŒb8®x\üèºH¨”æVà%T4M,ãŸ4^&eÊ7õ&—Ìå-K¦¥Ÿ½ûBÕ^*±XÌ(*ðÔEO¹ÉUUÝç,ËB*•ÂÁäA\yÓ•ˆF£°, –e!N#—%M>9€Íoߌ ¸À€ÞO“-]:6:®é„Êž={°k×.wËb±ˆ;wA455…Ý»w×]ǶmÛ0>>ŽÅÅE d³Y„Ãa7³YyÁ\6nf¥Ã‡» ¢µ–Ífqûí·w{3V­^lh9>o¿ýö²$,ÑZ)‹Èf³xòÉ'»½)«Ö‰ø|òÉ'‘ÍfYø¥®( 0 GŽéö¦´…ŒÇÁÁÁ²ÇÅĉ{öìÁE]„Ë/¿¼©k"˶ÔMýR¶jÇ&Ðz|²lKÝ"˶‡îö¦´E»ã“e[ê¦~*Ûv²Þ¶Ñr½Ì¶EIJÄO>/&•—uÿòyÀ7\—e‰„‹ì±x=XâõzƒhòMl`•9U4­b® ‡ò°é®Mxúœ§—%-b±’É$EÁSO=…»ï¾ÇýÑqPñxÜ¢kxx©T ñx×\s  :Äð\òõÕ\óåkpÆgÔÞ0"Ñ£¡,411Ñ‘²mSC~É._þ(SSSľ}û000€ÑÑQèºîNLTO±Xt'·—Æɖ¶~Í´H8ùä“Ù ”º&‰àСCÝÞŒ¶©›@ëñ¹iÓ& u{·h’-g¬–ú°S;ãsÆ ìšM] …‡ñè£v{S:JŽ9=66† P(`÷îÝ…BuË®,ÛR7õ[Ù¶–Vã“e[êY¶½í¶Ûº½)×J|²lKÝÔeÛNÔÛVK öÓ½QdO“TJô<™œ‰Ùa£4GUš&Ö1=ÝÜ{ºl4×CE&K|CƒU¸¾Á$ò¦iB‡ŽÿC¼Îz,Õ‚mÛ°mÛÿ$‹áO†þÏßó<^pÒ Ê&šF£PUÕ›GEN\oËãPcì2¹­Éû©”Öéëi344„[o½u…¶±¦z¨ÜtÓMˆD"eÝ1 …¶mÛVÖ LNXÔH8Æpà 7¸“ÛW ¬fÖuÊ)§ð¦“º&‰`Ó¦MÝÞŒ¶©›ZŽÏM›6Õ¨S‰D°aÆnoJÛ´3>yÓIÝ …p饗âE/zQ·7¥£dÌÊrj$ÁöíÛ¶žeÙ–º©ßʶµ´Ÿ,ÛR·È²í)§œÒíMé¸Vâ“e[ê¦~,Ûv¢ÞVÖ÷ÙûDÎm29)†é’¹TÊë} @lù:’I‘LYñ$ñÏg¢–~$KÜá²ü«7 ض Çqà8òù</X„£:¸ÿ_ï‡a0 ªªºÃtiš†çíy\ö¹Ëpê©§–õz)K¦^B¨Ñ]2Ab¡êðeî~Æ!*¾c‡;R¶mzÈ¯Ê S¡PXÖ:§QpLLL`ÿþýeˇÃa‹E÷·ßÂÂ/ˆDk ^l`|u㓨7‹EÌÍÍ•=Ö¯7’D½†ñI\ŒO¢îa½íÊù‡åJ¥Ê“"rÂù|äGPGô ¨Ò£DQZH¦8tÉ! Ñ`!§ôcÖ_ìé?yH‰ äS©Ñ#Å0 $ d2LNNâî?½ïÿôûñ¹_}Š¢`rr²‰º‹õ¶¥R¢7 $J -æÍ{"išè±òÉO~H GÞ¨—È }á_h<ÈñI$ˆÅÊ»ÊÜ}÷Ý€ß8ç7 ë:lÛ†¦iH¥RH&“H—&~yõÄ«¡ë:ÒÑ4’Éåcp¥Ói\vÙeâ8ʆ«ºm€H Õ;6rqÔâÌŸPÙb'53ZëššCeÛ¶mÈçóسg"‘òù|Yw­ÅÅEd³YwÜÀZFGG155…;v  avvÛ·oÇèè(`||»wïÆÐÐfgg1>>ΖDk QlŒO¢na|õ¦ÑÑQÌÍÍ•ÅîèèhYìQw0>‰‚‹ñIÔ=¬·mN>/æD‘“È' äìâó¤(ŠX.•r`Û¶H´ašWwÞGÇs¯~/´_X;Ñ çqÇq0<<ìÏåw÷îÆ'ßµ¨bñØ"2™ 4MÃüü|Ù²/|á Er¨^ ÞP^€\­)ýÖKÇ¥Ö<3ò½T™*ËÙ6ðù<ð¤! xÒ7æÚu&³oQS •P(„ë®»»wïÆÄÄ"‘ÆÇLjֻvíB(¾}û®ëÀ˜››s»…ù[ŒŽŽ"‰¸Û³ÑÚ©›ã“¨›ŸDÁwàÀeíÝ»·nìQçU‹M€ñIŒO¢àa½m}¦)&t·,ñ30p;Ù]¥F/ ˲¼„ŠÙÄ›d ’‰Û¶‘H$`Û6EÁ—Nýu›íÍe ˲H$099 UQ xüöÇ‘ÍdqðàA" ä_þEß{>xñ±aqð1¼Rm²(0ŸÛ(ç@Y¶Ã¥ýLC ¿U‹L¼ÄÑ8A#9¥õËÇR)À0€ßN›Kc¯}Ïœ¨Ü9ફZ9Õu5•PÄí¦¹ü¬ •MÖìºjY¯I&Ùd|u㓨7qk¢àb|㓨{Xoëñ÷F‘«ªòË0€_ýêð­oý þÆÃxññ/Æ Ê§Â°mÑ ÃMº”ŒŒŒ ™LB×ktË0QµÇF.—ƒã80 _À¦?,Ÿp=ŸÏ»s›Ø¶»¾y¼îAĆcرc‡»œ¦iA:†aH¿*-’¥ à•Z“ºÈ^%õ†òòÏs¯³\^¯€É:˹^:6òýH&5î%«tøg½ñd÷«Ðô¤ôµ ¬(™BDDDDDDDDDDT¶-æHÉçý‰1WʹçÆü¼ŠË/?ªª¢xQNÆ©²ÉdR¼^Ûöm¤R)d2d2™²×üè;?¡ÙCe cxxªªBÓ4躎cÇŽ!7s –eÁ4Mäóyض Ó4qÙe—aóæÍøúì×qÅW”­SÓ4ï·o˜®zäe6€|­WñÿZÜÉÞ+ê…æïå¢W,›Lñ¸X‡LÞÄãÀk•`$TŠÅ"öìÙƒ]»va÷îݘ››ëÜVuA*%êëŸ~úiŒŒŒÉxÿûÏD<žÄääòn†a ‹!“ÉÀ4M(ŠÛ¶qÿñ÷ãÆ½7²,¨ª ]×Ýe‘€ 6¶H¢¤R"›L&1??ヌ®ëxé?¾W½ó*,~gù|Žã —Ëazzº®C×u$“I¼æ5¯Ái}ZY¯EQ ë:4MC4õ’Í$Uärõ&’W|¿›æ¬QRÅ¿\5Ê<֢ͯ¦*»víB¡P@8F±XÄÎ;Q,;·eDDDDDDDDDDDkÈqD2å‘GþÜ ÛÖà8"ÉW_ý~ÄbÃîòWüè 7ñ9,ž°EQÉdʆK¥RØó–=8í´ÓpÍ+®)ëéFˇ“ó™äP>IGí„…o˜®Ê%~Ó¾ÿkuÖ7]ñw¥2¾ JeHîÏô4:¡©9T …ŠÅ"~ðƒ```@]ÇÄÄ„;9=Q™¦Ò+¯ý¼e³³7ã©§vã„>‚‘àÜsŸÅÈÈ[xCfÀý£÷ãÓ/ÀÈȈ›¬ð',r¹nþpýõ×ãMŸxÑ+åŒ3ÎÀM7Ý„W½êUøÚ×¾†©S¸í¶ÛÀ\󰨶íNr¯ýLƒªª¸ýG·#ªGEOŸ™™™æ{ž¨ðzuÈ å+%À]€Èº ú„ô•êõ<—,‰¢vBÅ¿Jûaȧ¼˜Dy™f{¼´¨é*‘HÄM¦À¶mÛ:·UDDDDDDDDDDDmfšâ§–ú§»q÷ÝÿUUñ±‚_ûµ¯ þ>t]ÇtEχco=†ø|étéôòl„¦i¸à}`ök³8óê3qôèQ¤R)(Š‚Ï|æ3øó?ÿs„Ãaär9Üÿýxý]¯Ç7÷~ÜáÁb±FFFÜù\¾ùâo"—ËáÒ —ÖNäÑÜÐW¥ÉèÝIâk´K¯gHÕ“4fÅãQÔL¾o•u9Žƒûî»ÏÝgw}ß´q謳ܡØ)}&“Á3×>ƒÙ¯Ï6±ó+·êI鉈ˆˆˆˆˆˆˆˆˆz…ZÑÃâ«_ý.¾úÕï–&t·ñüóA×u|ä#g`ãÆ;LW^ySYÏé’/\‚ïø½òa´*¥€¡?‡6wß}74MƒmÛH$0 ×^{-N9å\|ôbÜsÊ=ˆGÅ_###¢(H§ÓÐ4 Éd¿óÊßÁ\€‹_wqYÄ?ì—ØQßïF½6TxÃuUÊŽ¥E×”ÖUÊ­X–…¼L´¨(6,|ïÓßC&“©ºZÓ4EbÄAYòÇ4MìïÆüü¼;ÏŒØAOým||þ9w¹²ÃœJÁ0 |`öøÊ{¿‚cÇŽµü©¥©!¿ˆˆˆˆˆˆˆˆˆˆˆz™ãˆdJe^äÿø)„B§`×./yÉ›ño\½¢õ¾øõ/®ûü“O>‰Çõ8¬}¢ÿu3ŽãÀq(Š—…¸vÓµøÌû?ƒˆ¦iH¥RH&“e ›û>|ÞþÁ·‹äE©‡‰išˆÅbÄ0cQ=ê%TÒÀ¾/îÃnm÷òóuªy¤ðΊŸU}'NRÙGÛŸH$ ( ÇA2šÀ¶m(ŠÅQðÔÿ} ù3óÐ4MìC>˜ üÓï\ƒO?ø E º#öO&š¦>:…Ó?:þÁú@,Ã?úÞyø Œýű´u ‰DÿýÿçŸzO}¦ibzzŠ¢`ñÌ× œ[·nmëg¨é„Êìì,víÚåþ-'¤Ÿ››+[îÀmÝ@""Z P ^ã"""""""¢•°,ÑÉ"•æçÅc_ýêw1?çI|ðƒc÷î§k¼ÖªÝ ¥VÏŽ’ 6à”+OÁö»¶c@ó¦ÕP¥¼×K85~*”œ]×Å|(~6pꩧ²,DÓQwÂyÓ4‘L&ÝmªQ··Èÿržþ«§1rË4M+šìØîcxø‹#ŸÏã’ë/Á+.}.ûðeH$pš¦áµ½W¦¯t_“Ég°ùì'pþyŸÇ×Î= 'C7 üÁ]€o<ý |ø??Œd2‰d2‰³N< “““H¥R8úþ÷㲃ñã ¾Œ½ëE˜Öu8Žƒ?}Ãppò£Ø¢lã8ˆF£¸àª € 3!z±¨ªŠ÷~å+xùä˱qi# ‰yÞ¹ÿÌÿtŽã¸É8nŸ|û·ý3ÔÔ_ƒƒƒ*{, ! µ}ƒˆˆ¨ÉBK½±J3ÑXAUŲDDDDDDDDí`Û¢§?‡ñ×=\ÎÆ‰' '|ŸøÄyË^'‡–ª6ä1dUÅZ†a¸¯»í¶Ûð¾}ŽþøhÙ2𦕝ÓîØxGýIämà…/|¡÷w¸ÿ‡÷‹$JTLPoY–X‡#z‘Œe¿wÉï-"˲,ÜqLjÅb0 ¯ÙöL}f ¦i¶mü¿û»XüÑð½O¯¬'Œaxþ_Ãy[?ƒM·Ü‚Óffð{¿ø&&&pá…"™LºÃ}þüÏCƒ†i]ǯýÚ¯áÔ{îÁÕ;Þ…h4 EQ æóøêÑ£xÓ¦þûð,KGìëää$Òé4r¹4MÃÆ‘eÇgþ²y;û˜èãëéƒÀEw^ÔöÏPS=TÂá0{žuX>/zdTŽãéç8¢5E{nÈDÉädõ}Ãejšø¿LSw+>óÅÏàáðÃxçûÞ‰Mö&LÿÝtYR%•Jaâ’ èº]×q1.†ö! ±X ÓÓÓÐòy\ùÞ÷â÷ÿ‹xäåàìãΆªª˜œœ„¦hÀˆØLOãOl04à À³x·|ã¸ÿïÄeóŠ˜o%—ÄfùÆþ䓪â¸|[þò³øþmë¨%zÚXl@Óoî@ 7æk€{ÒÃ'áØÙUæJy©H¨Üsäž¶~†V<)}±XÄÄIJÙ,²Ù,&&&°¸¸ØÖ""ê'–%’ •ó‚U[FÎáUK&$^rb-d2Àqljm¬$÷)¢Q‘ñïƒe‰çdÂ$ËâZ(»Ú:Ž(ÌD£b9Y>‰FÅq1 o½©”ø¶la/"""""""jެCˆÅD]ÃÑ£ŸÆwü&1ïH<oa¥¥ß¾:ÿááaèº˲Édðóÿú9^ò‚—àÐ%‡jö>Ñ4 ˆŠa¬ ¡ö$ò*°ù“›Ý¤Íãã-'¾“““î"Éd‡Æ[Þòhšæî× Ÿz¡è½ ‘H@UUlܸétÚ}ß«®º óóóÐdKW]Çe—]†¯}ík˜™™ÁÁƒŶªb[`cy·ïúÚׇÞrbÙ„óbg}ÿ/U0r~}áloN¥´þDbù1˜ï»é‘M8îgÇᤇOZ¾ÌïFñ½«¿‡iï4ò+Z[6›Åþýû100à¶ÿ~d³YÄãqŒµu㈈z™ãˆJÿÉIñÓô’ •ËÙ6pð 0<¼¼†Ldhš¸ØONŠ@iXL^/ÿkl»úûÉåK×DäóËßSn“¢ˆÿOO‹ë—¶Ó¶Åßò}5Íkå1Wòo¯\_%ÿcV­DDDDDDDD%ŽSÞ‰bÓ¦»ðªWi+x}•¡Gˆ éKõ8###P¹\Î]$•Já`ò p €Gê¼Iiž(‰Ž:õI“““Ƶ_¾·U| ¹\ŽãàøO_»Rß„7wJÆ GŽëPP>ÏHåºJ |£Ñ(Òétõ9W*ëGjåF*{ÁDKï­ø^ {­T…7lXéµò8Ø•“É×9ÜêÏS©´y›ÙTã8™|â‰&WÖ¼¦†üZXXhje‘H¤©åŠÅ"ŠÅbÕ×ÈçB¡B¡PÛw˜ˆj«›þç×C|Úvíçd¯ÇI“-[¼„e‰!±üÉÿ:åäê21¢("pð ø[ÓÄk+‡õÊ“ŠR>ÌW2¹<‘ ‡òÄ{èº;ôeÙü*rU?õæ_kÔ0¡òý;ÝÛÒ4M˜¦î¶2‰Ç½!Ób1àW¿zIg7` 1>‰‚mqq Ëâ±IÔ]µb`|uã“(˜ú­ÞVI‹ú]6nyGo> µQ%‡-~M)O T#:Ûp¬¹^2iP±¨¢(8õ¶q\ñ#§îrUÉ-þ„E®Ê2ÕÕƒ\FÖM)¨‰ÃKÞT&۶ˇâJ˜n°/3¨¼©°xÁbí'M§u ÕmS=T›Jª4Ó;%›ÍbÇŽØ¿?öìÙƒ;v¸]™&&&ÜçvìØ‰‰‰¶ï0UW/6õŸr’õÊÞœ2)"‡´¼äˆì]Rk¾Mïx\Tøçó"9S™8iæÚ›LŠdм&É Õ*E£"±09é%Jd¢Ã=“Ãs¥Ó+Kšt’eYHÕSmdd‰D±X >øcX–w\å°f–üøÇWw{7Ú‚ñI|ù|~Yì16‰º¯ZlŒO¢ `|O?ÖÛʹmGÔçhðŸü„Yµ·ÕuÜ;p/Çi<„[›4•P€ññqŒŽŽ"ŸÏãòË/‡®ë¸üòËqùå—cjj ûöíömÛê®#‰àÀîß‹‹‹˜ššB(ÂÜÜܲŒæàà ;f_-‡F6›]“ƒET)›ÍâöÛoïöf¬Z½ØÐr|Þ~ûí=ÓT’#L¥Ó^Ï)“©žQq­‰7Ñ 1¢Q±Íz£‹W ü=KüÇA*•ÂÈÈTU…aeËe2ضD"˲ ë:E¦iˆÅÄlmÓÓÓ˜œœD:†ªªîdpçœóWØ´éZär9¤ÓiìÝ»ñxï{ßû°eË–nîUëD|>ùä“nÏS¢µV(`Ž9ÒíMi‹p8ŒH$‚ÁÁÁ²ÇY¶¥^Ô/e[ vlë«lKý¡X,"›ÍâðáÃÝÞ”¶hw|²lKÝÔOeÛNÖÛ6Z®],KälÛkøŠŸÁÁ LNN"•Jáío~»¨ü·ë¯ïð‡që=·âgwü 7ß|3N>ùd÷9UUEâÃB7…F«&\‰ŠçR(LÓpÓ•Wâ}ç¿OÌ9"Ç•fxÙQa%çqqjlû )àÍ­ƒãq`f¦l˜”¿8ö8éá“–efÛâ}eåWµçM©Ten–ª Ždi½êÐôÒ:W07oåû}sÓ&ÜØkgSC~IãããˆÇã( ˜ ‚­ÙÉèý¦¦¦Íf‰D0::ZõƱ™.c'Ÿ|rKïOÔ‘H‡êöf´Uel¨:‡R3ñ¹iÓ& u{—VͽkŒœø]RÕꓬ¡×ÉJX–w n·D"h4ê^”óù< À¢(PU“““îs†a@Ó4†Ã00==ááa¯Pˆ àöDQUuÙò¾ûÞŒ‡z=tý2blÎ .¸³³³µ[\ô¨vÅç† Ù5›Ö‡P(„p8ŒG}´Û›ÒQ­^;Y¶¥nêDzm5ë©lKýA¶ ¿í¶Ûº½)Dz-õš~-Û¶»Þ¶Zµòyxcs¥IÙmÛÀoÿvÑh†aà=o|ðˆ@ƦGŽÁy:o~êÍø‡ÿû¥÷Èöm·žB’>%i\2Qñþp׈:E=Mßu€S,¯RªVBå3éòž$Q,ŸDÀïÀ¾ÿ ` ô€œ$Þ4—Ë’‡—Ôh4çoe EQÜF³Þƒh<$š4Óär5l~ó›qZ*ÀV”P€lÛ¶mYo”b±ˆ‰‰‰†Ã~-..b÷îÝ(‹Ø»w¯{ÃX-°ŠÅbÕ. ~§œr o:©k"‘Hß´‚©›@ëñ¹iÓ¦†Ëtƒã”_KòyÑ[CN6/ɉÞGFz/iÒH»zÓ8ŽãöJ±, Ñh¦i–M&_™‘ÉÞ#2™¢( E)ëF«(ʲBJ¥³Î: ¾‘(ˆkU$Áþýû»y˜Û¦Ýñ)o:‰º! áÒK/Å“O>ÙíMé(–m©õSÙ¶ž~+ÛRÿë·²m=,ÛR¯é·²m¯×Ûš&ÿ•øí¯ßñWêONNŠÞ!I4¬ØÁ ^€³/=G?w÷Ýw6mÚ„|>ïÖ_I»ÏZó‚DQžÐ±¬÷‡®ëøì€·n@$O>®3zùc?Jv¼¼7ŠœG% ‘¸¨‘KøÞ™ßû‡peøVQIö[ðßjõÊ"97J{‹è†T̯i21‡±iÓ¦¶¯·é!¿‘5²sçN„B!˜¦YPápxY÷¯……¶0 @’ó?Øjæßµbè¿øÜ²¥|(¯|Þûñ_‡ä÷½mWOÒ÷²*S˜Ô•ɔςæÂ˲,hš†t:t: EQ`Û¶'ªª.KŠ(Š‚ùùyض ]×Ý^'• •fœzêOñ‹_ÜÜíCÚQë)>‰úc“(¸ŸDÁÅø$ê®^®·5M1²U|°n-¯ß1M³¼— ’ &|àŒ8ïÞó ( žyæD£Q·Q(ÑËÄ_ÇbÕX¯ò„„œK-|Ku!§žzjùëTßë%@H•;¾­D2EnOA;>éa,^øNDÎü8Vû Ä}ël4ˆ ‘¨ª (+·«k]?Û¶„J3&&&°¸¸ˆmÛ¶¡P(¸?rÒ#9É ÆÍ,‹Ø¾}ûš"ɲ,¤R)˜¥šw˲022‚T*…D"D"X,†|°Û›ºjõb@ßħãˆkM.W~aD”ƒ—¿&Ë÷QîLÌ+ÖÄü)¶m»qª¸@g28Žƒd2‰t:]6ÌW:F.—ƒ¦in²¥9'ФiZK“ˆuÖYÝ>¬³^ⓨß06‰‚‹ñI\ŒO¢îéõzÛ|Þ«»‰_å=nÛvy)Žš=82™ †‡‡ñÜï<(À ‹/D.—î]»l4„I•¹D€*)=M~舤HiÙÍ›7/me¯ÀIº˜ì·²‚'Ñ£DnK ?ý£Çðu}÷þÛ ÆÖ2Pž4ª§âð¬´Ñl+äè)ËX^yë­m¿ùµÅbÅb»ví*{|ll ãããÇîÝ»144„ÙÙYŒc`` Åw#jÌ4Mäóyw’k?Ùº>“É ‘H¸Äù|Ñhù|š¦áË_þr . ­h›ú"> C\\ãqñ[UÅWMY‹¦‰ëS¿$UTµ¼·M&“q ²ç‰œ÷DÓ4÷·ã8P™L¦ibf¦úW&PEiš ["¬¶¥ÂÕW…e}Àh·mG¬—ø$êGŒM¢àb|R/1Íú÷+ý†ñIÔ½^okÛ¥‘Fâ@²¢wʲ†žrøªõ<Š¢ —ËáÒÝ—ºó‚D›¶DCÝyYÊD|Üp+iE~£ÊrVéÇ7Œ~[þ`Æ^ERá%kê´WÝ÷ïûðÉ~0ÏËÖ•+‘PYaû×VF!i…¬³ZÆqpÚü<žoóû­iBE_-£££ˆD"(‹…Bê6FýŶm$ 8Ž]×122âf«åE¦iâ`©ËÂÈȈ˜333îÛÑh_úÒ—–wÇë1bèø4MÑEá¥iâÿ®‰N©±€üÍ^'’J¶;߉¦i°mÛM®är9ضí&S©2™ òù<âñ8¦§§¾G+=MZy Ðùî£Ý´^ⓨ×8p`ÙcŒM¢î«›ã“z‡QjeœÉçžÛí­i/Æ'Q°ôz½­[Ÿn¡¬—„œïµLUç0€D"áÂqRéAÙë¤Ù©@ˆ^$+—ØÀÇ2Àç} V«U‹h¨ÞC¤Öˆ “¥÷—sŸT‰Ž‡ÞýÎÏœ_u™2jég…¹‘x<¾fó§T}MÙ>ˆCm~¯¦*²‹W=‹•3·(ˆIýC¶¬O&“˜ôIÓ4¤R)Äb18ŽS6  ¾€e"€ûüw¾ónïÖšéåø´mÀ²¼$Še‰a"gf·öRU±L3Ãdõ’DB ÖNjŠë:¦§§ÝÏxerÃ4Mär¹æ[e`åéºÞÒØ—­&búI/Ç'Q?clã“Ö‚m{÷©”N¸Y™ŒèQ?3#~?ñÄænïΚa|SPcSŽB"þ€˜t~î¹Z_¾¾DB>Ÿ‡ã8Ð4Í›oE¶%ÕQ;™ byâD…Hfø¯V=òŒèéòŠ©jI5{ÓT¥”ŽAú.UUaYž}óÀ+Ðxn@ôŽYa[V}*Ò&''«7´Uœ6?ßö„JSs¨‹EÌÍÍÕý‘ãéuC*•‚mÛpù|™LfÙœ€7ŒWe70]×Ýî|D2™,›D[Q”†sAPp%âDæÈTUôPÑõæ»Î«jo ù%‡îòÏ”J¥°qãF¤R)7A8==í&s¹\ÍÄ„œe%ÃV.œªª®øuýÜ;…ˆˆˆˆz[&#î= CÜ“†ø»Ö²##âùLFÜ«LO‹ßÑ(pÿý—w{wˆˆÉq| k €ãÊQu¸ò¸·œL&ض½¼‘çFßkj|wWMtD«,_­mj4 \m.¡¡Ãë¥"·¿ž(š[o³½Njôè ‚zõB÷¼ò•m¿¦z¨lß¾CCC‡ÃÝ;2´îUN"%'‰Ïår0 í8–_~r®97„anE­eÕÿF©œ`Jfn©÷ÈÞ(•×OUÃ5+Huö–eÁ¶íš=EÇq{ŸÈ¹~‰t]Çää¤û™…-OnàôûOojüÃø›ÿü(в|Hqÿ@D’Ê*È·Ä€MàH•¡Ô-xÃ~ÀKªd2ËǦ—ÃxÕkË-)2©Ò¢d2 ]××lÒø~ÓÔ¤ôDí‹Å0<<ŒT*…D"á&L’É$<]×ÝyP€ò9Oj‘CxÕJthš†ÉÉI^ÿ¼Íjeˆ$Z{r¢GÀkÖ+­»ÇA,s'?“CÖ¥R) #"—˹ŸuUUÝaðòùÉ{><í3]ýâò.Ç›cÅñ½&-KRö>Þí}¢5æ8Ž;/I&“¢(PU¹\ÎM®ÌÏ{ÝÞ–uŸó±, ™L¹\º®7lmßÊœ&­ÎƒÂùS‚ͲĵL~¼äP”Aá8NÕÏmÛÈd2PUš¦Á0 ضÉÉɦ’$º®»¯o?ËDDDͳ,oÈ­DB$,‘ø¼!´ Ãë!+x¤Óâÿ““Þ[ɤ·œiz-ÛÓio8/™øÈå¼ ­óy¯XU½Q"TU,S­Ü#‡þªzC…UzãopJ·;Ѫɘ‰Ç½áïdo“|^üÈ¡ñTUÄÛô´H¨Øvïôt'"Z¯äP§~OÝùÆ_5Žmû¶á®kîªýâ¿ÍãÙÿú>¦§§Eo•L•e2@ó] 4Iˆž! ¼‹Gªâu–g{†áõ&‘˜j´$İ`Jéÿõtyžßõ®©*¡P¡PsssîO$A±X,{lnn®ÛûCkD&P •JÁ0 X–…\.‡ééiwè.Ã0ê&PüäÄñªª"•J5õºÊÞ-;ÏJišÆ-gšâZ•JyCg¥F"‘ÀÈÈÇã8H$îc±XÌM@ʈÇãMÞd"…½MˆˆˆVÆq¼ Ûý=CѨpdÄfKÉ¥i¢±a>/Ê€7„—¦‰ÊXÛ¿£Q±ŒÑA¶r—ï ˆ{ðhÔëù¢ëÞzåßò~Û?ᵟªz Jª=W«E­éÔŽÛ€‡ÚÐíÓCÔËòzŠÉ^_##^RrdDÄ[<îõ@9xÐòN&+™L!" Ãð&¢—P*Ý{ï½8óÌ3¡( .>zqÍa±žYü&~ôÍ—+Ùœ)Þ ¶Øâš, øB~y%oâyÉ_§£C ç•Cý‚›RZ×*†ò¢µÑT•ÑÑQŒŽŽv{[i ÉÉã«%5R©”›0‘óž”MõJäã¦i"'ûF7 [ÍÇãqD£Ñ޶¸_é8Š¢0¡pò†HVpå&(ŸÏÃ4MD£Qäóy·§ŠªªˆF£eŸEMÓà8Ί>Ÿªª"”%"" Ëò’ Žã5ô÷‘÷ϲ—«ªŠÿçó^ÿ¤îrB÷\NTØF£^9‡ Z¿¢\‹ÕN‚ø÷ÏI겫YM¶_*{ÿZïqÒIOãÈ‘ÓÖä<­†¬T“½­,KÄ\.'âUÎ ”Ï$?û2V‰ˆ¨7†(Û©jõF´¶mãá‡ÆÅ¯¿éi‘˜°Q–ìp“é4Æ~u'ÎøáÅèZù<ðùp§ Üæ«ÃL§5ñÆš&–û¦¼H’Qѳð&“¯U•‡èyÒ̬Q0¡Òšò‹ÖÃ0*a ªjYå®eY0M333ÈçóËž—d‚c¥­æeâ¢ÓÃMO¯¼o\åþŠE×¹ ä¿ä0xÓÓÓPÃÃÀ™™™šŸÛ\.·â¸iå³éŸçˆˆˆ¨Èž$Õ.{ù¼×â¹Ë9ER)ñ¸®{É•hÔ«XËÆãÞdðKKÞdï²Ø{ÃoùF³u{¦TÓJ…íZu:­Õæéµ¯½]Ä!¿(ØLSÄ«®{£§¤Râs­ë^c+?9tõÛöæ€Óõò2š”Ïç1::Š 'n Ä,›%“ÉÀø—Á°ó7€ãˆÆÓ©ð¥à oêØ¨V©ŽìrüËfé[DÅ ÛBÑ:gY¢ç¯,V–×LÓ X-0!*DR¥4‰¼eYÈd2H§Ó8vìX•7ø¾õ÷†®V¿¤–~lßïfê¡8ðMßh*¡277‡‰‰ Üpà ‡ÃeÏ…B!ŒcppýèGqà 7t{Ÿ¨Çq‹Å ë:lÛÆÁƒݹRb±ÇÁôôtÙpCš¦Á¶m·7‹®ëM G¤ª*,«™¾lD«#+H¤µ¼¡’=½d¯“L&ãN*¯ë:¶lÙÈÉâ9‘œŒ=óæÉç½azüãf뺨H5 qc-‡ì¼–ér(.™œñ¿åomfãd“ñ¸¸x¼Õ—MøþÖP; "'šO¢¼W ­ M%Tnºé&D"‘eÉ¿±±1äóyÌÍÍÕ]ŽÖV&“ã8H§ÓÈd2nÏYÉ«(ŠÛj^UÕª•¿ªªŠnsÉäŠæjð¿Q§tkä*Çq0<< ]×Ý_ªªº=¼¸‰"""ZNNˆJTÓôzŠLO{sŸLNŠ!ºl[<.—‘½Rjõh‘ËTû?ƒm‹ø–1¬i"Ægfú$Yˆ–ÒD¥Üpéw¢òM)=¯CTÈù[9kúÖãç½ö¼nï ÑšËç½kB:]»L§ªªøîô_?¢À³{Úk¸üôÓX´Ì©V½){›H¼Þ.•¢ßéÁˆ„ÖX˓ҎŽbqq±ì±P(„………¦^¿¸¸ˆ……„B¡²Ç‹Å"ŠÅ"B¡Ð²ç¨y‰„H©Z–]×122EQËå°qãFD+šâ5Š¨Ùž)•Z™0žº«VlÁ‹OÿXékÍ0 D£Q¤Óiwx»ÊávÔn½ŸDäÅ¥ßÐк½ikΟ<¼ŠÆG&Gä„£@ùäóÓÓâ¹j7ÐL”P+ŸkOÎsâ/2çó"ÖEÄx@FÈ]ÅN«ŒS *ÚˆJº“¥e¢ð*ýªUÔYXÞÚY¾ùÞˆ7v{/;ŽñIÔ}Aª·õ_jµYµ, ÉdR$°/Ñ¡.:€§ÿûièçœäSªÍh ¡vÏA?â;݇e\‡šJ¨ .K”TÍââ"æææš~ã|i6¡ññq÷±‰‰ d³Y avvãããíö1ê†a •JÁqD£QD£Ñªºš¦­89¢iÚŠ[Ú×ìnGV-6àŧm‹°µþˆåóy†Û¶Ýù„Ø‹ÖJ¯Ä' ÙlSSSe8p‘H¤Û›¶¦LS´@Ÿ™¿eâ$É”dÒ«`5Íê½O…‰j/Æg{Édh­öt–d2Þ°}€˜©r¯@É@ åˆÊ1ˆ#&D *î4ˆ$I®ôšéÒãNé5rȹ®fÚ\­óï»õŸþFÃâg¦ì ˆk£Î’h­©ÞÖ²÷Z´m[4ê®(G:Žƒ·{+6ž´0ÿÀ &§ÆŠÒëÉðzU¡D/쩲Î4•PÙ¶m›{AÛ¶m[Õeòù<^à&&&P(055…±±±²ç²Ù,öíÛ‡H$‚¹¹9ìØ±‘H„-mH¥RîÝÌÌLÃÊ]94ÑJ¬d¨/€“]÷¢z± />e ·µ¬\ÉçóÈçóH§Óî¼)Dk¡×Ⓢ„ÅÅž®òóWŒÊÉâ5Í›ã$™É”ÉIqC\«(Ê"$­•õŸkA&KªÝ6Êï„™±\*%*‹5‘vKJA$EäÄà ˆ„H¾ôx¢²-]zíti¹hé7+¿We=ŧey×G9wPFLõàÎÖó=·¨§­Þ¶²—s-eõœ¾ïó|>ãž=¾åÀí[Y­2§ ñ]oB|§7ê}2 ‘‰ÈS(°wïÞnoFG•Úô¸ó ¨ª×EÑ53#*Oå_DA°âs-Õš×Pö(—EÏtºzÒ¥+xI“Dëb9œ° /YbBT˜Éâse²Ä_¬ʾõ¸õŸ2™ÉˆÆѨW,±, ‘ðþ&ê¤ ÖÛNNÖÞ0Œª ÇÇ®ë¢þÃp‚oEõ%iˆa54N¨¨‚ÜÛ’:âøfÇøø8&&& ë:.ºè"\tÑEرc …8P³÷Š_8F$Áàà`ÙãsssË2šƒƒƒU+ü>Œl6ÛíãØqN©¿§mÛ0 ‰Dét©TjŽMâñøšU¦ö{O•l6‹Ûo¿½Û›Ñµbh=>o¿ývLLL´}[ £ó“TæóylÙ²¦i"‹!“ÉôM¯”~ÙzŠÅ"²Ù,ž|òÉnoJ[´;>Ÿ|òId³Y …nï­C…B†aàÈ‘#ÝÞ”Ž’s îÙ³]t.¿üò¦®‰½P¶uQI‹y­ÍãqQù£(¢ÂG×Ås±˜7ÄO ‡öégù|Ó“ÎõSÙ¶žVã³SeÛ~N‹¤Êð°(«â£'{¨ŽQYfCT˜M—~O–þ¢er¢¢¬Ëm‘dÙöðáÃÝÝ5ÐJ|öjÙ6“1£ëb®0Ù`°²ºFÎ1DÁÔoeÛNÕÛ6Z®–X¬|¼jäüÑD‚Cõ¨™L†¼(YþÃ\ Ö‰iˆž*ÔÓ&&&:R¶]Ѥôccc+»H "¯zCªMfßL—±“O>¹¯»†˲ÉdL&݉°'''ÝóliÞ=‘H‡êöft\«ñ¹iÓ& µ}{¥³-\eÌÅãqÄb1är9¤R)ÄÙ׺gÈ–3V“H½¬•øÜ°a‡£® …B‡ÃxôÑG»½)U,‰D066† P(`÷îÝ…BuË®A+ÛÊyd²$Ÿ÷†ì’I”XLT˜úsõ}ž·ï¼Êñ-d—Y2 /I"¾e‰eü]xS)Ñ5Èq€ƒ«¾•s\Qœ~úé8å”Sº½÷×j|vªlÛdâDÓ¼žkŽ#©]™nЦ =Ox½O4ˆ!½tx=J4ÔNšàûL–mo»í¶noJǵŸ½P¶uo¸;ùU-‡°n#k9:­Üz)Û®¶Þ¶ZãÀFl[|þk•+mÛÆðð0ÇÁÒÒ’x°”PÉd2PUիljC$Ò ˆ„y3ú»øº044„[o½µíëmº‡Š_$qÚ‘LP5°šÉ^žrÊ)ºél§|>T*@Ì¢ë:¦§§ÝùÑÛ$¨½@ÖÃDÝ‘H›6mêöft\«ñ¹iÓ¦¶|GÄb^A*չ¤mÛq‡ÓK&“˜ŸŸG<‡ã8}•¼L²©`ûÈ9½6lØÐíMé¸Vâ³n:©…B!\zé¥xÑ‹^ÔíMé¨p8\6þ{$ÁöíÛ¶ž JÙ6•uö±˜wÝFE…i.'Z£ëº¸Áž®~£«iâ«%¦éÕH¢ö-ã½ÈÇe†KQ€-[Äã²¶nËïµ¥1cn …) ÊŸÉdÜ{ Ó41<<Œ‘‘Äb1|üã_ZÏv•mû‰m‹à%YãqQvO&»LÉØÑó$ ‘X)ÍG "©bÁ›(>àLÓP*Û~àzæ™noRǵŸ½P¶M$¼á½dâQU›¿N²‡Jp­—²íjëmVüž²çs-²îfÆß Ú`‹é¢²kÛ"9> ‘PoÔ;EJ‚sbõ¸p8Ü‘zÛõPéôVvã\XXô±“‰ÇÁôôtÝÄ„¿Å|>¬ÉÊÖCBe½èv|êº7Ì—atnÜåL&]׫&úmî¡ &bi废DT]±XÄââbYåk+7’kɶū¬µmqÍõ7dXI£MkƒDæîâqñ»²c”Î”Ž±K?&¼Éà ˆdÉ DÅ™†å­;1…eÕnBJÕ½y1Mù|¹\Š¢Àq7GFFJÇSÃÞ»ïÆó‡!ôóŸwøÀv_?ħãˆUõòÝñ¸—/®³²õl;òîAjèÓ6r™Z==MSÜ´ÏÏ‹ƒ)k’I¯ð/ 3²–-ŸÇ“¦‰ù¥%Qd5 `r¦i¶m÷Çí9RJ–(Š‚t: Ó4122‚x<Ž_F£øDiýòõº®» )d9G¾æàÁƒPUµ¬ÑÈÕW_Ýí£Üq½ŸÝfY^r4“eš&& îxòÔ„¸¶É^'DKã8Ä„òyxsž4’Ï7—õÉdÄÎËûy 万Ž#–ÉdħL¬økÿÌòZ;Ó4Ýqýå<©Ñh#¥¸Ö4 ù|Š¢ ™L"#•JaÏÅ#ò¶·á%û÷wø@w_/Ç§ì ˜N—êOJu8•=9eC¢^²Ö÷™Lí^\ù|ù|¾j=My\¤^äÕíd2åå¶$Äõ¤z)Rp&¡ˆ‰ïwïÞ¡¡!ÌÎÎb||¼çZ"Ô“Ï‹‹¦¼‡J$ÄÅõõ¯¿ßýî\z鯣X|)t=‡¹¹³`YÞ„~‰1Ç‹/96m´t?gÛ¢,7ýç€ý€ý_ëÂïæO€éûÅûéº(çÅ_ä ñÚ\˜< þ”H¨È¤•¬Ã€ñ.oȆTPÞ è׋åb×¹C€ž,ÝëA`쮾ä¡i È|˜þk@¹@iB5ãªRÂæKâ1Óð=@¿¢p q?jß ü€¨xÝ–-ÀÌ%€zPv––» P~LêJÝgóY`fDáZ~QÊVKqx•E6Ī#¶ÃMÎ@¼§›Œ1Q^ñeˆe_ùÄ+îÌÑqÝŠO™´“÷,íîbR©’ÉdÍd QÐõûõ1x­MƒÄ)ýø[LÉD†ÿ»*qíñ?fB\‡d¢Å‚HðÇ}ËÉõÛpÇ ®MþÇ亷”~ËVºÉÒ:Ó¥÷Ê—~’ðZìæ!23¾ueJËËûå×ÒzÇ#h程FGG177‡;v  avv£££íö¦ðÆp÷7Ô‘øÖe'cYóåo¹aÛ¢Pé/|ŒŒx³ûË rNÃ- eM™¢š†c¿ñøöé§ãeïyžUU8¦‰'>÷9œúØc8᪫ٱ,.â•¡þh`ÿ+ƒ®ën«ü ˆa;mÛv{ƒkšÇq®($Õëªë:fffªö(å+_‰SO=µÛg¤£‚ŸA çOJ§Å}d:íýíÏCÈÿ·­r8q}³à]Wd/yýª¼¦NØçˆdÃòÆ#”üC9ȼ/=Ëòn¬ôbß4½š<9ôPj¹è;¥dˆFÝæÔ–e!•JáºC‡°sdš¦Á4M¨ªê&Cu]w{£ˆÍC~OOO»=Ì”Åö®ÿùüÖZÖX/Ƨ¼LNz1z™<¡~±–÷²HUM&“©:¢mÛøÍû¯zÇ«ÄýŒãˆù‡Ä5%qý jA×*XöØèè("‘ŠÅ"B¡PÏ W"oHå…SÆk<î•ÏüÙdC5øä±ÿÄ£?Öð…ûßÇ»¿úÕ ¾úÕ³J‰×ÉLZ¶ÀÑJ½† P¿¨obZú’ÉÚ€¦Ž.ÞcòZÿH¼ˆïåÁ-[€üwéò¥îÚ3‹€~¥¯Nn UóU"‘¢*ÀLÈÌŽ! ¹ö·‘¿¬RïõW€v>pîÉ×`d¤4~î¹€s+û+@ýÍRƒ'Ä-ÀÌ€ü3b}Ö·\°¶ú8ô3+ X÷ö"0ypN†?¨Ÿ’Ÿ’Z©Ç^ °â€¢ús€œ‡çO%RzßÓÕû–ù½P£†Äã0`<Äwº8¿ d&€´Q ß ¤nÒŸ^sÕkpð›þ¼]µØºŸ–å5òêD¾CÞ´pˆ:êA‹Ï5aBT¨ÈžkA&7æ}9¥Çrðò²µì¤ï1YäoõdC$Jd™L‘뜆—ì—½!åú&KËÇJÿ—•HxÉ‘$ÄMÁti9¢ÂI6ˆ•–Ñáµä¼J^2Ç.½F6,H–ÞG7¯¬£­èAŠDi;%^@ø‡aŒôϵ³–½{÷bnnΡ۱éo”Ɉ²W2):SHë¢ÒÇŸrÂGð~ ù~üãwAÍ‹õ˜¦×»ØŸ=5 @ß(Êq©]ÿöî=>®ºÎÿ«@i 4é)¬PJh=åj(' ßq]N -r±ËLp…µÙ¥3«®ÖKtF]ºZ¿«3ÅŠ»ëœ®ßà"+ÉÑþD¥Ds¼¹ä  ·Òe(mµô4i¡”ùýqæsæÌdnÉ$™3“×óñh“Ìœ9s.óžó9Ÿ÷ç(—¥—6& †í þP¯–}ˆ¦¿?äE€r³NÉJI°á$F’?@¦2ÆÔíéÖŠ'8ïaÞ h?úJ7Ê]„€&;÷Ÿ½—Ö»Óì²lXð5 þ ÀHOÖÛؽ@ìß\â”O¥Å€¼°ÿ]D€tÐv Ý ô?H *°MbAÀø!€‡€è¯Ð?æW€ðÍ@üÀ|`Ü èÿÈ¿—¡Ÿ½/Ú]€y"`Ÿè­€Ô¨ßô}@o %mý@Û;ûÀþOÀ¾ˆvö·í·€•Þsã]¸àäÓªý1œÕˆO1,Ýä¯×Bkk+Âá0“)Tjñú™·GCÙ•ò"Ñ›¤˜ÑÂÕÎù[TÞˆ!·Äغޡ¯D¯2CDÚéíÉ1Á­ŒL¯1Ìd0ýÚ6Ï{†=Û!ñôßé†èE¦·¤x paÏúz‘Iª´!Ó»DI?ç²²N#‚`úyq|Åcâ£5½¼›ÞB¦·èÍ)Zv‰žb|oqž4Ý1àóAàjÅ]æÀÙÿŒáãß]Áɬ~™ÀZŒD#Ê©½½S7'™o‰‰,Ë)h‹ìxÜù©ª€eá7=†æÍÃñ×]‡ª:ùÄt‚IJ,ر˜“(‰ÅÜ„Š,ˈÇã0 èë×#ºÃù MŽäö,™’D‡ad&Å!—_âÓ/L3Si›;DQEôô¿$œk™¸öDà\CDLq-Ë•¯RÍ4q‘F³0 ç OU³‡z½ÐŠÕtK’ä Ã>C³, s‡å’eÙ¹ŸˆFÝ9P¢éd«’ïi©$A)4L`9JÌÃR¯j!>E#XËÛ~²Mõú‰Ê5÷Å&£ÿçÿ€8ûœëˆ·ç½mÛ°mÁwªÀÅœ¡t¢ÑÒZˆ¦›ï*~§ëÙ=ˆÅpDɤó\"áô…ÑhÔi ÓÚ ¨o}çÖ½òŽ]؆ÞÞ^(1Å©ô°€çŸÿ'\uÕC€~‚WŠ(s‰¡¦ÒÃRõ÷§{XH€| Š‘ D…‹Èée´R/ЬÓsä½€z5€ AÕyâ?H—1Å{¦[­ª2 Ì ÁSõËNDÒÛÔ¿äÅ€ú2`\78Ë„E«\ P~ ˜äcè@8´Þ >š>¦7xnô$  Hï‚s{; E™ÛD¤ó€„Ä/¤·Ön ú œ®S@¹ À.@ï‚m€y5 ýP¯¢_¤âßsŽÍÂ…@ðX@ ª„b@üZ[¶N/íO€nÉ‹KÌ! TûƒY§,kòÇ_O$ÐuÝíjÏV`“ÇJ·~H²,öm7ae†;´Xζm·¯,ËH$Îͪ¦!#‰ g {àeÛ6,Ëšñ­lý¨Øü¬.1•¨Ó°Ivˆä‰‚ÌÐV1d†ºl8•øÞzÑ‚O$cÄð! d*þìD‚è‰!Ö=ˆL#‰LCqí½D¶¥_#’*"Á  “éõ¬G$OTÏ6˜pnD]Iº¡ƒ»ÝH¯O$2 ™Š(ïc½ÈNT)ÈîÝ#¥ßËF&©#¥÷Å›äê‡;¼¥;¹o4}¼dÏóÞaÂâÈTœé×þÙÞŠº=<Ñ wýÓxí¼óÊú,QåDo”dÒ)§êzñ–5)·†ènšN-”ø2wMË µ :ó©E"nÅ©ªªØtï½ø|z¾qó‘ˆJTÃ0Üáyg._!*&O$òдÌhX¢oEõö"p®cœëçû?="€{íõ&PÆ[”3ŒÌ„O"ö½åAYFGÝ?½Ck]•áÉ%z•Y–MÓ (Š;|^$¢(e¹àyÎfxÞg2!ìšàK–åÔóD£Ó“ïŠÅ²G›#ªg¡Pþá¾b±Þwäû°øÃ‹3÷‡éûEÓ4q𥗀î6àX0ƒ¥çÊ"š &TÆÁ;T—è‘bÛNT´Ju³Š(&€t™²·×€^n|ÁÀïñ©[ÓC YÎ20€—_^Š_ÿz)$Pİ@fY=Lá@#Äp(¢u«h @ùG8WÛ€ä1>` œ‚ln‹Üð'ápE«Ýteôy@þ‹³®à?xNAÙÎl£ü÷À`ºE®r)= 3A`z?Ô¥™uIÐÿûô=n™ŠèÿDúwˆ‹þ2;p¶×úg@>ÛùÛmI•3ßIø?õ—®‚Кpz´Hë³Ï±wÈëpØ9§"a5˜NžÙvºQcº0ó7s"€7ªô©¬oÞáŽ'ƒišÐ4 ýýýÐ4mF$S Ý<ŠaJŠ%$Ä8Ïš¦! "‹!C×u„ÃaD"‘¬¤‡˜øV$V‰‚Á 4Mƒ,Ë@f¨Û¶a¤[þÅãqw\iqã !Ë2B¡âñ¸»NÑXìŸH’‰áR %`hz„Bî´™!ËX‡2s3«* ýÓ=>L пh¿”Ã@xAúÒaÀ¹6ˆÊ˜`*€}&€;õÀ>0"NÒÝø`/¤ËôÑ;­°_Â?¬—ãÎ6‰¡Œ/úÀ”?Æ\ÀlK—¿ ¨×;I¦ÓAûð€Xº' è×xˆ›éyÌHÇø4ÿ–ó˜(?Ü·i;úÂóqúé#عs¼}6BÚ£0 ï{_$ɽý4õn§¨öÆoছžÅwœƒƒâ’KvcçÎyغµ‹wÜaD" ñƒ¼Š“N: á0pÛmãØcÏÉÚ_Ótާ¬äiìMĈñê½r»Çs^+!SY'˜ÀÊÀµÐw˜²cŸzªÚÓÁ02£áôöfÊ8Á`öT!5Aô,I&3;’H8Ù¡drìw[ž}×»pÊUWáÅÏ}_†$I°, áôlÀ‘ô$ÐB<G<Ϻ.zË š¦¹Éa:úâú6‘ewî܉Ç~ùK\‘®õ+V¹LõM×3ß ºž¹òæ%ÆEÌ69†Ö';˜é‰âÍ[9Vit™=>,Ë‚iš…Bضm$IB,ÝËL–egH>Eišî¼EápØ-oæÉE3›}DôLÙ»7Óè–ˆ&‡h¸žË¶mœýƒ³qÅÅWdæ¡L7æJîMbÖ²YXûÄÀÕaàòR-ûˆ*ÄJl;‡½½îhœ ¢5BV«„ô°›¶oÂ[ïÜrÒ-Xü‹Åh×Ú352œ/‚Hú ã02‰ ÑuÍÛ’¶N5ÝBW™à:dZžŠõŠ¡8¬œ÷Ñ<Û(z ˆ¼â=BéÇ’™åâýéeEAALtë-ÇŠIpÓ“®µmÂA ž@VËXùk€œÈ¼§[p÷®È_ÈÎiðg/´@tYzSÅ÷eNF–ù#ÎïŠÜu×XÖ.H’ävÍv*r3¯OÞ¿Å{¸C±X¸p^zé„Ò$‘¼œ¬:ñX,]×ÑÛÛëËáG¢G)"I!–‰ QÙ#~Z–]×ÝD…išn%‹øì‹Çu]G0ÝJW´Ò‹F£nK¼þþ~ضíÞlŠç ô?7"¹Q,Á!–?Å~‰ŸýéæX½éà æÔŠ1ç½IMÓpÎ9çTû”Î8¢7uê:Ãa'9šø$Ðÿq§¡¸èÑiÄ?ÄTóøR ¾°ÒÃgš‹¼–]¨6_¤Í€|€]€M„±P®Ôóå8€»_Ù…ß]õ~ó½—qôó/â·ÿ{’É8ùä×ÐÜ|2î½· Ï=gaþ)o ­ñ(ÌŸÿî^ô8pÇ¿Ï?Ìyû,}èÿà­a ÷<ÿ0ž|òWx|ÿÑÀ~ ôÏ>ûßÂÛÞv€óý%I\„'ŸÆŽ¯â‘ÿ}o{ÛEضm>††vbÞ¼“qúéN‹ˆE‹œmÞ¹s}ôQ 6âÒKð644< 8xp~ùË#qÔQû°lÙlìØá¼¦­MFÿ(N?ýt>üg\{­ÓN»¿úÕNüÏÿ¼€#üŽ:ê!À÷¾7‹ß§Ÿ¾¯¿þ:Ž>úqyä˜5köî]€7ßÜŠ .Æk¯½Ë’1oÞN¼÷½ÏàÒKÏÅþýGaçÎy8ÿü¸ñÆEcO¼çkËüâ&ØÛöBZ¶hhÀž‹à˜uãõ×ÏÁÖ={ðî¿€[_}gÜóïèì¬ö'¶>‰F@"}zÉsˆù%3¬e¥[µ¤?Xbˆ.UÍÌŠ d†qˆÅpÇ9çàDÃp¯†m¿þµ{Ý•¢Á`Ðm…Þßߟ7©P¨uº+S-Ër“@b¿Äö‹‰éE¹A4v×CÑ­$~é%œyàôô@ÿ÷uuáøï}K7ó4² ú"ƒ‰ðŠÅœ{™P(3ÚPF™;Ìð”¢gezÔX¾aKÂÀÇu`0XyÂd‰„[.–$ ‰DÂQŽÇãhkkD£Q·\MՕϤ%ÅÜ,bbUï—²è}"b/7³å*¦ï`RAbÔHѰV\‚¦ëÒàëk9Ñ$Ë÷yO$¸iîM™ÞÿvÞ¾×Þq-æÜ5Ç È€«½Tï˜P)Áma*eZð™2N¿Ó›Äí]á©ãûöœoã†ïÞ€­_ØŠh4š"#·Ç®(/Lÿ³2CKÿ-**âp¾~/1üHÙ…V1Öº·ìM¯SÍyÌ›dœ/'1t‡w}¹­PsëPE«T1~á«€r%€Ûò,—¯0P¢ "n*E%0èXzÜM>4ìîl,ƒªªn×mѲHüÏ‹Jçp8ŒX,æÛL&Ýa‡B¡;Œƒ(h‹ç ùA½è¢ÇpòÉr>NT&ÑÛ«Ò{Û¶¡¥‡ô$©äæÕÙWËm)'>·’$¹7pÞ^"áp­­­èïïw+UZ[[F¡i¢Ñ(‚éIl{½Y?Àf+X¤IrnE‘X6wâÛÜdG)å.W ïvy÷§££cÊß›–å4LÃ…(`=éT؃@ï§y€ôœ®0á&ôûtæ©’N 8רÁA8׬œ¡¥òñrÛm'a`àVD"¦{}qtë­Îw¿sø>ýéôö}ضÍÄ‚ öîÍôÚš3˜3hoÏ|žžÇó¸ÏãrÌp%N;þx,}ùåt¶~üY_÷bØ;ÑÃJQÞƒ§žêÂQG…W^9„DâC°¬eîkÄpx¢‡X4…aÐõˆçñûpÕ‹ðä®Y忆eý°ò裱ÿ~œqÆÿÁâC/`àÉ'!¥‡Óûú×ïÀÚ¿>sFߎ‡o¹­­ö.“ðÄûß­[â_þå(444 ðúð»ÛŸÄ?~*®_ü$Ž8ã(|摯¢¡áM¼úê«8yt/þ~îcçÈ‘xXRpÊ+Ï¡iÎIøõ ;pP_†Y³îÅâÅ»ðćð«“t$Ϲ®ÚÛºdšNý[8<}•òuÕUس?Ž=öX ^v}øÃH$¸âŠ+ªv|hr%Ný}0˜ ³Þ^§Œo(•‚ldæâ2ΘѲ™™‡H «À¯Uà=mÎøÓ¦•{‰ä¢¦iîµ[\S‰'ÆEyÙ›0åäi¿ã.ÚöØZB‘P­8s‡/ŒÇ3 šv‰„søU5súªÕÓC~ÑL‘o¸/wT‹ö±•‰ý¥¿Æ#×=‚ê‚ôuªÚ{@3*Eˆ‹§ee†[Î*{Y€"†âJOoÊN¯áÎÜ÷§ûðÉ+>‰¨œ.DŠr§@*ÆH€( ~ °æyÖŸDf¸,Q¦R‘ÞÛÃ;1,5Ü—KÎ󘘛%Wîcù.ܹƒoÛ¶gÐ|9k®oëCqc+*”ÄØ´b.…=¿ü%޼ðB7q‘H$FÝá…¼s,D£Q\ú·ÿŽÖÖoCUU¼oɬ<úhœzüñ°dÙþGUU,{î9Ìß³¿ÿÒ—°èF']-*ŒƒémˆŠa†úûûÝ–ûªªº•_Þ °Í›7#`Be2E"“Ó' AQ„ÃáªVž†á~^ŰY¹?ƒÁ TUu‡Èò¯%ZÑI’„½{÷È´˜½C‚%JöS2¬‡¸¹+vSjYÎrùÞß43cN˜¦ó}â=OÞ™QÛŸ^ô·çð^U'†òu+ýWú;Ò7ž¢5+àÎæí)åCÝ”M¼ö߯á q’$A×u79(†˜•‹²,£··wl%‰§b"+ND xÀùy“–å<–~¯CwßÃ_ù Ž{ðA@Ó°÷íoÇk_ŒÔ™gâô|ÄM|¡ÖlÛ†ÍÇ‹“îº ±XÌi‘´×»…ûöáüë®s+{^¼å4ýøÇøÆ…âØÕ«ÝJPÛ¶µmŒÜwÞÚ·ÿío!t¢Ñ¨{]’maÃÀ¢ßÿ›: ³o½[n¹Ç´´¸»tÌúõØ·o^þãñÒ¡C8tÑEnåS0Ä/ð¼ëå—ÑØ0;¶ìÀ¬¶6¼þúëX²dÎ?ÿ?‡ñ§~ÿ•øÇÝ›÷|§üÕïðÖ[oÇk¯½Ë—Ù=†·N: £--øÌ%ÇÀ4_í·~ Ç7à‡·ß]ÿƒ;|àOþéŸ0ï•Wªý±­ â#.rÉdfZ)%&bÉ7_ˆ®;&*R éÕ2›îYâ>`øŸþ º»qøÇ?Æ#Ï> +‘pcAÓ4à‹_D8vc>s ,wØÈ\•\ÿ¼ Ú|Dƒ Ñ«Côà&>EžÞÞ^·ªªˆD"H&“î÷G2™tˬ‰DÂ~ ÈôÎ=kTUE2™ÌÚ7±¬(ïˆDrYvÛ/Y–…[Î;×_=Þsã¸;C8]ö=ï¼ó°téÒ)ùØÐä‰Å ϵ‰dZÑ{§*È{M6«;à ´cœÚ„e@±-7{Á s?*¾sžð´@Ôõñ%T Ã3TĽˆ«oÙ‚kƬ ð®†üÛç>‡®¸Â½‡Ì'÷;¡jÃÁŠ®AÁ<ãù—ºéIQHÓOtŽ”eç§®g«Á;z Q=*4ÇŸ¨AN~ùµO~¿½òJ,L,tâå6,'š"L¨xˆz9q± ‡òŸ¸×SN“í¥ç3ÙuhÖ\·—·_Ž›½ +?´Ò æ68LqñíE¦·Ê›&`Ë€*ß”#Óëºóïô(Ъ8ãÍz'‰Í•oîËܲ«{ZTnæV^Љ;E¡M–³ x–å¶,Ü;:Šùóçãà‘G¢á}ïƒiš8ûw¿Ã#==¸pûv¼òÊ+xcþƒ0Í$ ³ž{KÃaÌ™3[fÍ‹_û¾òÝï"™LbñÝwão¾÷=Úµ £o;öíÞ<âV"÷Çã@(„m²Œ7¿úU\qôÑhP„ÓÉWœp~`a´·oœwf_tÐØ˜=„Pk«s3¬(Î~<˜ÝlS×ZY†dšPÓü‹¡Š‚îù÷G€Ù÷w€çÆwáÂ…ÕþèÖ•ôH÷NI¤+a¦{h/Q**}E¯§d2én¢(îVýyš…Ãa÷ó+&¶÷0#Þg¾›GQ™,’ápörmm™ÅÅP,Þ“‹9¯Ò’”îRfÎͶW<>vÞ¿sïD²E<ž¯t%¾×‚ÁÌ]Žg+|²O1å!ò^a1ßIz®+é=@Xœ™­ÈæÑ²,@v*/õ˜î¶>u+M‡àV˜ˆan¼óD"ìÝ»7SéiYNå­øŒæ|>_ýö·qÌúõxþòËqÒI'áÅW^ÁéV®–eáÇ_ÿ:>·`þë'?Á¥Ÿþ4:Üpø0þýþ_þÿ÷<ø`¦—ãé§CÓ4§27Ç,UÅ•¡ áÿûæ7qøÒKømkCØ“¤q'’I“V¯t 4 8ç ÌTˆZÒ{-X³ z†/‚eA•ÚéÇ3©”´ÛnÃIyÎHðäKÊ^’þ)¾Ä2?¼ÅNWìΆªþÞj(‘H`yºÁƒèY÷ÛßþÖVSüëïïÇÀÀªýÑ­ Ë–9oÑ+e‚§ÆO$½C¡ì&â{p6$Ì\GÒ«bØ©]‹cñ‘Gâ«­­Y=‘¥'Ÿtc\´@×ˉ&HÄÜ[b8 î÷‰&ÓÙdçs‹ÅÜ×™žâó-'¢‘h!æ÷2‰hz¿½×|OùÊ)…Ix‡TÚPB–e|êÖ[ÝýónÇ7Þˆ“O>¹¢õÓÔ²,§˜¥(™ÖòbNq™É½Õ+ȄӈOJÿ®À™E•¥2°ÔŽ5`z\êÞÞ±½(ò×dï°~iÿçâÂ|$½ÝNò]ë×£³¡»_fφàœõë‡Ïi"D£8ß{¿ZK5˯©æ$N|‰Û°ÜÛ¥jmЈêU¾[þ·¼ãx§^mÈŒncÛ8ÐÝÁ °ÈÌÛE4 ˜PIõŠ¢R(Í”ùDã—ÌX±é å7¹ ŸýÝgñð9¿ÄñÍGÇË8-‘ž-þ89-ìuV˜ðc øA°= Äã°Ÿð6¿Ž/§»Pëé~2œ+º¨ü­þÄÕ]×Xo«¿ÜŠZqS›§+±î¿**£žüáñä“ObÄêáºFFðþÕ«q×ã»Cby[ÜI_ù ^SÜgü¢¶ý ÃveibΖ-øð“O¾æ ®^ P~û[€èœs~îÉQ·"ìHIBCÎÓ ï{0:ŠYf:Áƒ%¾UãñL!WTâzÙ6V<ö˜³žPÈ=î’$ᢋ.ššå UIWfÑzÝ0 X–…mãË`,Q‰#Ö'*EE‰¦Ë;|¨pã8ç&B1#´øŒå«ùÁbÆCYÎn‹enNeÙ)qx+_"çË,ÌL>‘;V³¸ 7¸¹ÛÐÛ›¹#7Œñ·¦+ç.¾Ô‰.w"y”§™ææsÎA•zåÏ(¶ D[ü ™®Q8…Úóûž†=ø¾ö}hº†•¯¬Ä¿lþÜ%ß­Õiµ.*REÜkEªx®yaIÂ…W\‘Õ‚<•J¡I’ðƒ+¯DËÅ;-ÁMÓ½V%~øCÄ{{Ý#†a8Sƒµµ! âü뮃­(øÛô0!w}ä#NBçþû!Ë2.½öZcçúq·¹·0 çýü–ú¼Ër¦¯ifÇ´Xo¡cRÁÝýD†>‘$)«ÂWT‹ ÙÜVõ'ó|â+Þ²œÝ´Vôä&ɽ”LbßsÏáùçŸÇ›éž¾`´¶º‹*ŠõÊ+Ñ IèM':¼ÉÒ‰×dhmmu4x!bX0ñ¼³é¦›0œ¤FÔ“RU¡P(ëñBªÙ+v<ªÖZŸ*fÎíˆif'Q‚ÁüÆ ¯NïÑ$Ò…poùNÄbž’T¹ŸhÔ-ËŠþÛ¿øEüã›o"µv-Ž:ê( Í SUüq<™þL—ˆÆpÞu•·º"*BÄR$âÄ’÷ãVí¯L~ôi&Ðu “èOÏñüû¹¿G2œÌî¢ë8ü™Ï`_(„kÒu‹DÓ‰ 8AmmÎ}ùîõEÃ:—˜Ã$ þ¿‡ñ›Ç~ƒ/ ¿¿Ç_¾«vºÀgY@Oþ虄N°E>Û ü!è:¢×¾”SQ™5çI4ÿð6Á`vå‹™=h mÛÎô)鱚Å$•rz,fÑXÜX©ªŠ†“NrÇgCü[_$IÂÊôzE…un+û`0˜lQY®¾zü=ð¦³õQ¾ÖNÞÈK%ghÂt}ì<ŒåÒ4ÍV'wŒr‰D‰Hʈá„DÅa(ʪ$éñè}/Ms’¢o¸m½³Ï;oæ|¶¼ãMpäk gW¼æ~^KÝI—“¨¤Ì2~¯òn+M»XÌDÕàô@Ñàv“N,y‘xý«¯ãÏÿöé6aÛ6Ö%ÖA²$w¬ÿ,Ë–eî½ÍŒ\qö¶·;󘯸½Žyç$ ‹mÛO\«DL‹x÷IzŒ;ñ0ÑÏä$5OõM´T­ÖxîÞ7CW™¶ #á²Q ©Úßßï6>ÈO¹×n±¬³¯™k´˜„]L¢.†ÉòNÊ®ª*Óó éH&“î$îâýÅwƒ÷}ó•D2pe@ò1¯y2™iVÖ0D&œFb¸jÎ5[\vrî‹ñÞ7Š2³ø]$G½1+¥ÿƒ?ôPæºoÛX$Iîí®û8ËuT¦é´TÕ±óý`¢÷ÉDµB\ϤA8£ýXÀóG<[²qtMæú•^¸ Àÿûü竽Ù4C1¡ç¢Y¬±µ$ª(p€úá! ýxµÿ¯0§}>¹x—SJ4³¬,££Nå’ @ö?)PK4 Ò·ƒcÆÌÊð”YÉ"ZÜ&Ò­ç#‘z{{ݤˆx^Ìé`š¦{£›[©ÅGš.¢Þe"½áE2¥¿¿Ü-­½q!\~Á§#aÏPRnëê¶6ç§x/ï]l0˜™µ°Ð’¥îzË)½‹÷æ 'U™®Ñ›‘zÒ4SCla̲êÚ¯Åûo|?Çp’Éb‰?ѻ̗Ëù¼‹Éo‹v1‡B©ù„Èy—lÞ tvV{SjZÖ|uÓH$0MÓÌš7D’œ^ÉbŽ1|é½N‹$Œè=&z²¨ªêÎOâ-¯æö õX¨”ÓÈÇù^e™=¥¨&išÓ€!Ï M]´¸¨ÃI˜p†Ú·‘Vúq ™ž)"$KL|®ëzÖ\fb˜LY–‰D²â\ôÔ–$ÉMtæmìTKCvQÝ‹DÆŒLDÓ¨­-]UbÃiXnÿ°ç°!¸Á¹n½-3¸àÿûßÿwýÑd™q 1”:à\0£pˆá¼"pæ, 9ïÙ³wžøU¼kï¯ðŽÓþÒÊóÑd5Ác²[’ç›ü½Pœ{ç*)ó»@L$«ª*b±z{{ÑÖÖ†ÞÞ^w,wUUݹ¼sIˆJ,ñS<Î/"ª¦DÂii7ž¡: ÜdŠhÉ*I^¼í6ìß¿ûî½Í'ŸŒÅgŸ+o¹%³°˜ß@Ó²“™b¢B™ŸZÏ™¨¦ Äÿ ýÀjç±Ðm{÷îÍÿ"1Ç‚~R a™®ðq*bÕH$Üħ˜_ˆÃÔÔ¾C‹cûé§ãÂjoH­±3ÿbDØû¯Ö"Ójo’ÃC”9L"¥å˜cpþe—A}ÿûÝ…NK$:Å?EQH$F‹Å  …Ðßßïö ƒÎœu鹃DFÌ›ä•;÷H¥C„ù‘˜†NLˆ­ªN[IÊ?¢‚K|ÄàŒ#/ù—-ç{Á“Pñ6`ÉS1$§¢(¼oœfù’Ó4¹D?_RÄÜüP=òN¿ @øú×¿Ž • qΧÎZ#@RÂȦ/`«¹†a°‘ UÕŒK¨D"™¤Šw§,&2Ãz%„€Woxú釰ú•Õø{y'Žx?p¦ ÄÓËOá•×íq’N D"ô÷÷»-D/1ü–³Ü;‰&‘ŸYVþi<ŠI$Ð4 Á`Ð} Ó4 ###x×û-änÐðË_â’÷½øÐ‡EÁ;scX´rÏí&IœT’f<û9 v= -âGXïT¸„B!(Šâ\‡ÄÜ6–•}÷'IN|ÂJ·@¦[ºZ–•U™*ËrÞI›©¶½vòÉØ~úéÕÞ ³à4´±á´0—à´6O?|ˆþ> à Ïó½ÈL}0N¢UT¦ŠIÙE%ªHx TZz-уDÌ­×ÖÖ†x<Ã0Üøq-I’[ŽÍMаìJ3•˜Ẻ$r½½9ítbÈÌç)ÊÍ81ŸDæ6œ^f™ÿtúé¸3sï=Å5Xô<£Â¼ÃpË3b(4oÙF =hÛ¶ÛëÎ;la,C<w{ÿÄb1D£QD"„ÃaÜÿýÕÞÝšdYN;9Á¶º X:fª:|f™<¶‰êŽ;|e:&mÉF²?éÔwêp– ¬Nâ»ßý*N¸â„1s5M·•PÑ´LÃrË*pÁLØd/D€clúáÅø]ü$ ÿ.ˆkŸÞT€ïz*w*,_ŠaDáU×u·õ^8v3¯b²^‘8a6–êh¨^n}©mÛˆD"Y2ùlZ¾WîØ]’pÆ?ˆþû·ìe¯¾ºÚ»NT“tˆÝßÄ»Hΰ{‰D"3äV,æ, :¥ãœ ®%Ë¢Q´¶¶¢¿¿ßD×uÄãñ¬X嵎f¤œäˆ'ALÿî‰5zß§U  !3ÔO™Ä#º®»uÎ:ë,477ãýï¿›TB¡â¶H"Þ½{ÝÊA]×Ý2ªè¡&âWô2a¨]×ñÃõëqúuhooÇ[o½…Ÿ\x!þº¹«O9sGFðR8 Ù3ñ¬H~¾³Ú;LTCLS€õS@™çú¸ °~D®‚`pT,kbÓòåÐÞz ,Ȫ20 ·×о"™Lºó$Q~oî]‚€ø›a¾r¬{ž†ù¶îtCæ·~ûµy.Ù h¯dûˆñLN’f ø×(öí›…žó{pøþ{ð¶¥0râæþþ,üÁ_ãÑ?Šxïp×·ø›Ï~?ùI´|ùËHíy«¾´Ê¹`Û6N´,@z³ÓC÷-ÄB`™ŒzʯA8I “lHO& ™!r½IˆÜä„H"ØÈTø‹$…HXäK˜ÈNÜxå&)LϺ½‰±NÊDf>Do²Ä»NoÂE‚sO¡xÖ'öém³ÓëU<ïã¶É»­âØy!bû ÏvëÈN¼$sÖ!&—<¯ï#Ö›ç˜]²ù¼xcââ:vðà\´µ9a—Lf*En®pØI®˜¦“„ºY»d’q*2ÉHq΃p>C9”"Qbš¦û»¨h½D£À騀‰ÑóB4&•¸ÞÞ0²žÏ½É‘(÷Í€3ì¯H¢¨ªêö®û¯ªjÖð–e¹>DC‘IñSô?ÅãÞã—;D!ù‡¨÷ñóÄò¦iºŸK‘ÜðÆ®·'™÷5Š¢`Ë–“ðë_·cãÆ˜=ûæÍÛ‰;®ÄáÃâüóûñè£ æÌ™ƒcÝÓNû/üùÏ—bdät,\ø(fÏ>€Ý»b޼Ř={6àÒKïÁo~³"ç÷¥X¸p!>Œc} »v½Œ§Ÿ>ßùÎ8çœ;ðì³7¹=QÄpÌ1Æ®]‹qÎ9Àž=[ñÖ[7áðáãÐаð¶·ýþó¥€Å‹ïÆóÏ·cöìî>Λ·óæíÄÞ½ç㨣öãÄ‹;®œtÒI€óÎ{O=u:K–lž} 1<||Ö±:'ð¿ÿûî1¿ K–8Û³}ûéhl|ç7Û·;CÐnÙ2š~Ý!lßþNÀE‡^8 /½4'žx"€³в»v-Æ’%ÀòåÀw.ÁÂ…{pèÐPiÖý‹€5è}[à”IúáçÿèNs¡ë: Ãp{ðùA]&TLÓ¹˜Úv&‹ï™ïÖ!nÞ·k´®ëˆÅb‡ÃE‡ÊGLØ)ºýÆãq÷oQ`cË[š±,Àž„®0$¿ lñ¨§ÿ9 ^²hšMÓpá‘G¢ûÅñøìÙøÞ÷¾‡`0ˆ›¶nÍZ–·4DdúfgrkE‚ßb¿9õäç 6ýx ¿|.Â_‚`âDض®~ÿô“Ÿ óÒK±À3À»®ën…I0S1AD¥¹p;¤ûïD[çÅ.ú=¡}ˆ&œzò #^zOfaÙS+kšØ·o^ùÙ·ñlc#îY¦á÷ïxŽ;î8üûÁÿÎyמ{ žxàÌýÒ\œ}ÃÙ¸àøãѸr%ð¥/áskÖ/¾˜ÝÒA×øã ¹1í­ö^•¿ç{]©Nà2òÏám˜Qê= ñ®£œâz¾uzI9­‡KíK¡íö§d‰uä.Ÿo™<Çì·ú-”±3ÏÖ­K¾‹@ ©@¯Hè‰^Né¼ATu~—TÀþSžùm8 ïùV3­É%I‚mÚ™Þ&m¦Û›BÌq¢( ¢ÑhEôö=÷`ïè¨ÛÃ0Œ1s{D£Q·±„˜ÓÛHœ$†˜wEô7 ÃMvÈZVÜs‹ý*už;Y©¡™ø˜9_‚M€"’Ï")”"á-êµ—~|dû~¹ç—nñÓ›ñÛ&ˆˆ7±Xès(ڊϾ9‹2‰?à¿X`QÎZTd¾DÄû,ðžeÎ/pÔ>^àwáDÏï§xOže~³-^â}Û=µ£´›òÞs¬¤ûsJŸÑ:1‘ø´? D~ĘBÿÍMn'“~<ˆÈçBŸ{.Ôów"¹z¶r4b±t]G8FÓü¾ µµ¹s}ƒAV^yL$6“Ã×§ËT:8eÚà}Ù7”bù_þò—°mgušššðÒÂ…øï[o…¦iXcYzùKrßì]ïÊß]TLêcœêÄxã3àªÈ®”½…¼=‰~^`¿ œ#C²°…Ì0Ó:Üò箋wágÖÏÜÞ&¢VUU·bVü]NâÄÛÄ4Mw>`0èö?ERä„M› xxÕ*g—<=<Äܹ½6D£ÁÜ¡¹¼¼Û^ Ë”k¼ñ© Á3‘éhùo ù2½ áüþè¾Gñúæ×qèÐ!|ÿÈïã=CïÁY¯œ2þ2ÿ/ØuÕ.|îñÏÞúÛ·pÜŸÃÖ£·bí߯u†ˆÊNRÜ3z‡gôöÎï-îÕ„Ü¡mÏ2ž$OÖûäÞç*9¯ï•; ¥Y`¢gc¡a"‘çuÞa-Qà}¼=0‘çuuò>Ç=}朋™ ¢z[°$ zWúo N7O_<áìùЇܞ(¶mCÓ4ôöördò_%TzzzÐÕÕ…––lÙ²ho/'{ít ]$? ôÇáRp*Eå[úÂvàcpï?ß‹ïÞñ]Ø!;oQ •$ š¦¹Îx<Ã0Çݱgs'Þd S=šh|ÚßB£÷…ïA‰ž©œ ÃÉ~jéZ÷á'ŸÇ?½ÕŠc.>ËÞµ 'Î~g~†Ù×\‹ãþçCYíc8•ò¹ÊÉcŽsù|!¼ï­X&Z`y!˜óº|ëðnß¶2¶/ßûì-cûËXÞû>ù¶E-²|¾×år:\âï|ï“{ƒâÝŸŽ2ö½L(>m ñÿvA^ðÈÿþ“¬¦¥k/EïµÎï¦i"¢i0"ƒA Â4M¦ Ã0²æü"¢l•”m ±, =ön¿ýv<ôÐCX¼x1N9å\z饸Ä'>1¦µ,[ôå7‘øÜ·ð^àçŸlOM¨’žyV xËr†K(0‚ªÛËdäû÷á¦gŸÅùØ‹G÷-Äì¾Ù8vßEP>ô¡LÂ$ÃÈ}÷aöìÙ8Øßyóæá;é!®DdÖå—ã´ÓNóÏ>‹¥o½…ÇÏ: ÷\z©;çÇÕ»váÊ;ïÄ¢Ï}Ÿ:õTœhšÙ ÿlƒ¶í´H€hïÌ“ø(• a"„¦ÂDâ3¨&œ™èU0,§aÖ¶Ì͇%[xë²Ëpøða mW‡rÊn ¥8ã–ˆ ô_[ÀN ?þ8~Äïñ‡þ'ÿýß#gu#“eº®ã³¿úžß¸Ñ½![Q7©žf’‰Äç܃sûþ“7PÎ~ul‹Öp¦¢àöÛoÇwÜœz*NUOEkk«'¾¾Rí]'¿c{Bñi},ãÕa n:P³Ç¸1 ëVQ·až®xQ…µD%L´l›Ë4Müüç?Çw܃¢©© 'Ÿ|2n»í¶¼ÃƒQi‰Ïݧœ’UA›Ë0 ˜’K’`¥'H—Èéa´E¤ªxáÀ¼ýÒKÑ›žäÛÆ‰’„X,Û¶¡ª*,8÷›¢g¨­i¢/¿ 3 Î¥È3PÍ-·È Ú“U—¤¢ûBTMº~F£YçZ–=‘pç’eÁÏ>kø9¸"w=Å*pÏ•¨àíwÿ+,Fѱ.û’ãG>¤”~Ÿx°Ó9)JÖœ‡îþÄ=ë°ÒÉ`o±B-±­*5È)”`ç¼i:Û"ã} œ³¿–•½ŽÛÒÇÄÝ<å#5îÒ}̲,„B!¨ªêÞoJ’Ä)È÷|“P@cc#g¼Þææf477c`` h¶sï¶½ˆ¬|áÙ÷ ز Ø.WÈ€ìŒûj$ Ȇ7žyK–,Á‰‡A …p•i" " !ãúï³gφ:oÐÞŽÓò´Ä™Êž'===hiiAsssµOEźººÐÙÙYíÍà~L¢‰ÄçöíÛñúÆQXoìGòñÜ›mÛ0 ßúÖ·°}ûvqĸòÊ+ÑÛÛ‹%K–ø²•[½|ø=SŸ&Ÿ±Áÿôa·×˜išÐu===8õÔSÑÑátïã¦/^¼8«!‚ aË–-·ø÷ƒzùL×Ó9©ÔD˶‚išøâ¿ˆÇ{ xÇ;Þo~󛏸â‹k¢74¯9þSOç¤R•ƧmÛNoMÀeYxä‘Gð¶·½ ²,ãõ×_Ç©§žŠ+¯¼»vírï9{{{Ý¡¶ ÃÀ¹çžëVìŠyHòM¸+¦¢C9Ãg•ÂÏ´ÿÔË9™ •ħe9Cº‹É݃Á ¢ÑhɆÞ9LÄP{¹?Eœpç²m²,»Ãë‰ÆH¹¯ñÎä}Mîû{챸ÿþûÑÞÞ^ök&ò>%_“³e¿çø‰ï»¼¯ KÒÄßÇûšô:ò¾&H+y ÒÉ÷}<Ëüä'?Á/¼€S-+û5éÏ‚x½gñÄè{ãOøóÜ»pv`vïÞ·Þz ¯½öÎ>ûl444àúë¯ÇÉ'Ÿ nË!?ª—ÏôLúžÙ¿?ž|òIìØ±£Ú›:å&Ÿ{öìÁ¾y_ÁM½OàÕÛ^Åk¯½†¥K—²,„ÃaüéOÂÓO? Y×ÊíÛ·W{w³ìر;vì(YV¨õò=SÎ9Ù±cžzê)œzê©ÕÞÜ)5ѲíO<#<K—.Å1Ç“u­|æ™gðÌ3ÏT{×Ê2“®9µ¢œs²máøüË_þ‚îînÜ|óÍX¸p!<ˆw½ë]xöÙgq饗âÕW_ECCæÍ›‡ÑÑQìÞ½³fÍÂ}÷݇|ä#îõô¾ûîà 'œ€M›6¾ÿýïOûþϤÏt­(·lë·²ØT˜H|>÷Üs8õÔSñòË/㬳ÎÂðð0.»ì2|ùË_Æ‘G‰~ðƒX¹r%6oÞŒsÏ={÷îuãøàÁƒX¸p!{ì1w™o¼·ß~;V®\‰Ç{ .üñ€—_~Ç<¶nÝŠw¿ûÝx衇pï½÷⡇rÿ~÷»ß­[·âøãÇËéeâ÷ÓO?}̲=ô–.]ŠÇ{ Ï?ÿ|Ök^|ñEœ{î¹y_sî¹çâÅ_×ûLdÛÆûš¾¾>,\¸pÊßgª_cÞö¶·áàÁƒ_³mÛ6>|Ø-¯Õ«Jʶ—=<gÿM´~å.ìÿܼþúë8å”S°téR<òÈ#¸è¢‹pýõ×£kšëbÿ_Kjáž×Ï劧žz O?ýô¤—m}“PÛ5®œ.c×~üb<øà=¸úü«ñòË/£¥¥£££8óÌ3«½Kã"2¼õ ^ö¥œýX°`öíÛW÷CmL$>?øÁâÍ7ßÄóÏ?w¿û*¼üòËxÏ{ÞƒùóçW{wÆm&}¦kE©}yõÕWÑÔÔ„C‡U{S§ÜDâóSŸúžxâ ìß*.ºè" ã‚ .pŸ¿îºëª½[3N=Åg)ùË_°lÙ2´´´T{S¦ÔD˶¡PkÖ¬Á;ÞñŽjïBEêé3]/û²mÆDâSQ\sÍ58tèþöoÿ¶Ú»P‘™ô™®å–mó}vëÍDâóÃþ0víÚ…9sæà¢‹.ÊzÈßP(TòýÅ2—]vYÙ¯¹êª«òþäkêç5Åüå/A*•bÙ¶€P(„ßžô¯8ûì“ðŽ7>€‹.ºÈWɧzº–T‹ŸáâÅ‹qÖYgMzÙÖ7 •ÆÆÆ1¥R©’]®>ó™ÏT{Óióó—ÆdšH|¾ãïÀW¿úÕjo:QÝ›H|Šá¼ˆhê°lKµˆeÛÂñyÊ)§°lK4 X¶%ò§Jʶ,ÞRµLUÙöˆjï˜ÐÜÜ<¦ûÒððð¸'í$¢ÉÇø$ò/Æ'‘?16‰ü‹ñIä_ŒO"bleø&¡0<<ŒÎØ|©T +V¬¨ö¦ÍxŒO"ÿb|ùc“È¿ŸDþÅø$ò'Æ&Q†o†ü€ÎÎN¬]»---زe :;;ÑÐÐPíÍ""0>‰üŒñIäOŒM"ÿb|ùã“ÈŸ›DŽY££££ÕÞ¯T*…T*…¦¦&v#òÆ'‘1>‰ü‰±Iä_ŒO"ÿb|ùc“ȇ """"""""""""¿ñÍ*DDDDDDDDDDDD~Å„ Q L¨•À„ Q G~éK_úRµ7b¢R©†††ÕÞœ¢Û˜J¥Ü˜3gNÙûQíýÁŸÿüçqo›÷+ß¾TzŽª}~ü¨VŽI=œûBñYiüM÷¾•ÚBçÈoûQ jå˜Ôú¹Ÿèµ³Ôóõrí¬Ö¾P円†0wîÜI;×Óý9ï722‚·½ím“º­Ó±/å\/›ššÆ½m~:G41ùb¨­s_,>ý^¶-çº?‘ø¬ö~Ñä˜H|úéÜWrí¬t?'ÃDãÓïûE¥Meùh²Mv{²ŒŒŒÀ4Í));×´Ñuçw޶¶¶Ž®^½z´µµuôÎ;ï¬ö&åõ‰O|bôŒ3ÎÈú÷À”½~ØÏo|ã£ßøÆ7Æ<^lÛüº_ùö¥’sä‡óã7µtLêáÜçûLWÕØ·Bß3ÅΑ÷Ãïjé˜Ôú¹ŸÈµ³Ôóõrí¬æ¾Pe^xá…ÑÖÖÖI;×Óý9øÆ7¾á¾ße—]6zóÍ7OÚ¶N×¾ä‹ÇÜýúÀ>0:<<\“çˆ&&_lŽŽÖÖ¹/ŸµP¶-tݯ$>ý°_T¹‰Ä§ŸÎ}%×ÎJ÷s2÷a¼ñY ûEÅMeùh²Mv{²lÙ²eÊÊε®f*ÞÚ–-[FÏ8ãŒÑ^x¡Ú›5ÆêÕ«Ç\8dzÕÜÏ;ï¼Ó­0Éwñ)¶m~Û¯bûRÉ9ª•Ïátª¥cRËç¾ØgºÒø›Î}+õ=Sìùi?jE-“Z=÷•\;K=_/×Îjì MqCä=÷µò™~á…²Ö?<<÷…>Ó•Æßtï[±Ø,vŽü¶µ ÖŽI­žû‰^;K=_/×N?œ#š˜®®.477£¥¥Å}¬–>Ó###2à 444 ©© ÃÃÃoëtìK¡xL¥RY/_¾¼¬ýòÛ9¢‰É›@mûbñé÷²m±ke%ñYíý¢É1‘øôÓ¹¯äÚYé~N†‰Æ§ß÷‹J›ÊòÑd›ì2ödÀðð0Ö¬YÀ‰Ã0°|ùò’Û0âà¨joÀD ¹‰ollD*•ªö¦eŸuëÖa`` èììD{{{YûQíý_<ùƹ+¶m###¾Û¯BûRÉ9*µŸ3Qµ?³ãQëç¾ÐgºÒï•é>‡Å¾gŠ#¿íG-¨¥cRËç~¢×ÎRÏWã{g*®ålÚ´ k×®Íz¼V>ÓÍÍÍhooÇÍ7ߌ@ à&Åžß˶…â1¸û8ñÙ××çÞüÖÒ9¢ñ+›â¹Z9÷ÅâsãÆ¾.Û»îWŸ~øÞ¡ÊL4>ýtî+¹vVºŸ“µýb½¹ŠÅ§ß÷‹J›ÊòÑdšŠ2ödI¥RhiiAOOúúúÐÐЀöööI);׃šì¡"2Š^…ZIV“Ȉ®Y³O?ý46lØ€®®.7#Wj?ü¼ŸÅ¶­–ö«’sä§ýð‹Z:&õzî+??í[±sTKûáµtLêõÜW²í~Ú¯z.ßÐX###X»v-6lØ€†††¬çjí3ÝÐÐàNLš{XeÛ¾¾>¬Zµ @ÀMpÖÚ9¢ò‹M öÎ}¡ø¬—²íxã³Vö‹ò«$>ývî'zí¬t?§Sn|ÖË~‘c²ËG“eªÊØ“%•J¹½MÖ¬Yƒ¦¦&t‘yÁ€IDATtt¸I‘™5™PÉ—]öc–«¹¹ÝÝÝnö.`ÅŠn…C©ýðó~Û¶ZÚ¯JΑŸöÃ/jé˜Ô빯4þü´oÅÎQ-í‡_ÔÒ1©×s_ɶûi¿ê¹|Cciš†ææfwŒááa ahh¨¦>Ó¢uݦM›ÐÙÙ Ã0°eËlܸ±âm­ögzddèêêÂúõë±~ýú²·ÍOçˆÆ§Xlµuî‹Åg­—m'Ÿ~ß/*®’øôÓ¹¯äÚYé~N‡BñYëûEŽ©*M–©*cO¦¦¦&lذ@À‘ §§§ä6Ì„8¨É„Jssó˜1<<ì»l—Èà{y³Ž¥öÃÏûYlÛji¿*9G~Ú¿¨¥cR¯ç¾ÒøóÓ¾;Gµ´~QKǤ^Ï}%Ûî§ýªçò å722‚7bãÆH¥R¸çž{pÏ=÷ÔÔg:•J¡©©)ë³Ütµ\¶]½z5ššš`FÖðål›ŸÎ_¡ØjëÜ‹ÏZ/ÛN4>ý¾_TÚDãÓOç¾’kg¥û9 Åg­ï9¦ª|4™¦¢Œ=YÀ˜ž3õPg6i¦aâû)ÑÚÚ:úÀŒŽŽŽŽnÙ²e´µµutxx¸Ú›•åÎ;ï½ì²ËÜí½ì²ËFï¼óβ÷Ãû¹zõêÑo|ãc/¶m~ݯÜ}©ôùáüøM­“z9÷ùâ³Òø«Æ¾åÛRçÈûáwµrLêáÜOäÚYêùz¹vVs_¨r«W¯vÏÝèhí|¦ï¹çž¼Ÿ[MÓ&e[§k_ Åã<õï…^¨¹sD•ÉÍÑÑÚ9÷¥â³ʶÅʲO?ìMŽñƧ_Î}¥×ÎJ÷s2ÿxã³ö‹ ›êòÑT˜Ì2ödmmmݲe‹ûw-Ö™M•šœ”:;;±víZ´´´`Ë–-èììÌ;6e5‰ÉsW­Z…¦¦&lÙ²íííî˜}å쇟÷³Ø¶ÕÊ~UzŽü²~R+ǤžÏ}¥ñç—}+uŽje?ü¤VŽI=ŸûJ¶Ý/ûUïåŸZùL/_¾¸ì²ËÐÒÒ‚T*…ææfwrÒJ·µZŸéT*…T*…ŽŽŽ¬Ç׬YƒÎÎΚ:G4ùjåÜ—ŠÏZ-ÛVŸ~Ý/šµpî+½vVºŸS©T|Öê~‘cªËGÓ¡ÚÛ×ÐЀÎÎNwþ1f=Ô™M†Y££££ÕÞˆ‰ÒÔÔäënCCCCnצ|ÛYj?ü¼ŸÅ¶­–ö«’sä§ýð‹Z:&õzî+??í[±sTKûáµtLêõÜW²í~Ú¯z.ßÐøÔÒgZ¼_cc#š››'u[ýü™®¥sD“«–Î}±ø¬§²íx¶­–÷‹J«•s_ɵ³Òý¬¦zÝ/ÊðSœùuû¦²ì\Ëj:¡BDDDDDDDDDDD4jrRz"""""""""""¢éÄ„ Q L¨•À„ Q L¨•À„ Q L¨•À„ Q L¨•À„ Q L¨•À„ Q L¨•À„ Q L¨•À„ Q L¨•À„ Q L¨•À„ Q L¨•À„ Q L¨•À„ Q L¨•À„ Q L¨•À„ Q L¨•À„ Q L¨•À„ Q L¨•À„ Q L¨•0£*š¦Á0ŒjoåaÛ6 Àiš“²>˲ iZµw‹ÆñY,ËÊ׌Oÿc<Î åÆ¢mÛ°,«à: Ã(øýñ83”‹‰D"o!WÓ47Î[[[k² \ë«õ¥Òk'cÕ_j5>ë=6'ûÞ³’k)cÓj5VúŽ×‰Æ*ïCëãræ¨Õ¸œQ •ZflÛ®öfL‰P(„h4Šþþ~ Â0Œš &š¹ê9>'²,$ ºq­i 4-“GÓ4„B!$‰¼ÏÇb1ôöö¢¿¿ýýýˆD"laKec¬f«äÚÉX¥ÉTï±9Ý÷žÅ⓱I•ªçxH¬ò>”ü žã’2ê:¡¢ë:–-[†Y³f!‰Œù@‹Œ÷Â… ‹Å‹ÅÜ/ZÓ4 …0kÖ,´¶¶f}q·µµAÓ4,\¸ .„¦iˆÅbX¸p!–-[–•Eϲ…Äb1÷§išî:½Û^Ó4ÑÚÚŠY³f! e]T =Wì5Å”»ßâ‹&$I¶mÛ Ǭ˻¿¦iºçL¬³X‹ïùÏëhê‹Ïb±)žÏŸÓ›@}Çg9ñ’oŹ”$Éý)ËrÁBã³úÙ&sÕŽÇBû:ž¸Ë Š¢ CQ”1ˆI’ ªª»¬¢(5Û’¬VLE¬åk%V‹=WíXõ®k2®cÕ/êáZš›ÞõÖõ´Ô½çt^K›ÕÃz¢l~¼–N´žˆ÷¡µ‹q™Íq9Ñ2nÝÖߎ֩mÛ¶Ç㣣£££ÑhtÀh4Ý»wï¨$I£½½½£{÷î ‡Ã£FûûûÝçÄkûûûG%IݶmÛèèèhÖzâñø˜÷QUÕÝŽñ,[ŒØ6ñ{8Ý»wïèààà¨$IîsÅŽ‡Ø_ñÞ²,}®ØkÊÙÞrö;™LŽªªêþ ƒcö%ßþ&‰¬ÇÅ9¯íïïwß#*Šâ.Wìu4=ŠÅg±Ø-ŸÕˆM±®zŒÏrâ¥Ðþ†ÃáÑ`08šL&GƒÁ`Öñd|ú ãqìñoÌù! ík±×ŠÅ\ªªºÛ(Äãñ1ç%ßr4y¦*VGGËÿÖB¬{αZl'ríôb¬VO=]K½Û&þ®—ki©{Ïé¼–26«ƒõDc‡¯¥­'â}hmb\Ž=~ŒË‰–qëµþ¶n*Ñht4g=&ËrÖ‡Ä {÷îu?ôÉdrTQ”¬×†Ãa÷µÞ<”8ÁÞ¿s²Üe‹É Ho!MUÕ’¨x<> Ç£bÏ{M9Û[Î~‹/Jq‹/¿Bû›H$F%I*xÎÅ{„ÃáQI’Ü׋,ô:šÅâ³XlŽŽŽÏjĦXW=Æg9ñRhÅ\üô¾†ñé/ŒÇl‰9?Äc¡}-öºB±˜+_O¾› oY‰&ßTÅêèhùŸÃZˆÕbÏù!V‹íïD®^ŒÕê©§ki¾„J½\KKÝ{Nçµ”±Y¬'Êæ×kéDë‰xZ›—Ùü—-ãÖkýmÝùeš¦ÛÍOeÙýݶí¬n·Þe-Ë‚iš˜5k–ûÏWÝŠr¶·¶mgí?Äãñ¢Ï{Íd’e½½½PUñxápxÌñη¿¹Ý¦%IÊsÖÛÏÛÕ­Ôëhê‹Ïb± 0>ÅsÓŸåÄKîþÞ}÷ÝÐuƒƒƒˆÇãØ¶mLÓÌ;šñéŒÇl‰9¿Äc¡}-öºB±8‘ãÊXZŒÕl¼v–¯ŒÕéÁøÌæçki©{Ï麖26«ƒõDÙü|-H=ïCkã2›Ÿãr"eÜr^W‹qY· •|cç*tÄX¦£N÷ßT|«©ØDI†aàµ×^×k&BUÕ1ÁVî—MîùËÝ.EQL&F³Æ`,õ:šz¥â³Ø$ãsúâ˜X¼ìܹ²,gŲªªY¯e|úã±´‰Äœ_â±Ôë Åb)Š¢ä]onAž&cµ´™zí,†±:=Ÿ¥ùáZ:U÷žŒÍÚÁz¢Òüp-h¬ò>´61.KóC\Ss? Ôf\ÖmBE–ehšælÓ4³2^Á`0ëÕûœišnV̶m,[¶,kb£Z£ªjÖñ0 ¡PÈýòÉ÷Üûßÿþ‚¯™,¢ é=Öº®—U´,Ë=oâubR? sÁF£eÙm•Pêu4õŠÅg±ØÏ3>§'>‰ÅËgœ˲Üm¯ónãÓ?Ù&sÅbx2M4>н®P,–sœlÛΚ¤Ð²¬¬ÉBir1V³ñÚY^¼2V§ã3›_¯¥SuïÉØ¬¬'Êæ×kéDc•÷¡µ‰q™Í¯q LÍý(P›qyTµ7`ª„Ãa˜¦‰eË–¹_ÆÞ‰¢(ƒhmm…,ËYY.Y–FÑÖÖæ¾VUÕªndYF,C2™œÐëÅö‹ãa𦛱-ô\±×LI’ÇÑÚÚ UUÝc‡Ë:&‘H²,ò,÷¼å#ÞcÉ’%ãzMbñY,6ÆçtƧطñÆË%—\‚Ý»wg_EQŸ>ÅxÌ6‘˜ós<{]n¥žˆÅ`0XVK±x<ŽP(”µÏ“]h§ Æj6^;ËWÆêÔ«§øôÆf9ׂ|üz-Š{ÏJ®¥ŒÍéÇz¢l~½–N4VyZ›—Ùü—bß&ó~4ŸZ‰ËYéIcê–išîx{Þ‰mÛn×!Û¶¡ª*fÍš…½{÷ºËY–˲ IÒ„ ““ElKî~LôxȲ<&»_è¹b¯™ìý+÷X†D"þþ~†1寣©‘/>ˉM€ñYÎk*Ui¼LW\Óä`<æ?ã‰9?ÆãTÇ•8ÞSYF lŒÕüÇc¦^;Ç»^ÆêÔª‡øœ¬Øô¿\Ks÷Ñ×RÆfu°ž(ÿñð˵4wÿx:30.ó¿Äåtßú=.ë>¡RˆeYhmmEoo/EA"‘€išèïïŸöí(6a’ªªewŸšŒõLç6WÂXÓñ:š>~‰M±-•~Ö§;^&óý¦;^ŸþÃx¬îözñºGÅÔ[¬Næz¦s›ÆUoñY«±Y ÆõÌá—xé×ÒéÆ÷7Æeõ·˜þûQ¿ÇeÝùUŠ,ËH&“î¸l²,£··wÚ·CŒWl;§s=~{¯bÛ0‘̤ß2š4–_b˜œÏútÇËd¾ßtÇ ãÓÕÝÞÜõñºG…Ô[¬Næz¦û½s”«Þâ³Vc³Òí`\Ï ~‰×™~-nŒqc\V›Åº¦ó~Ôïq9c{¨•ëˆjo‘ß1¡BDDDDDDDDDDDT*DDDDDDDDDDDD%0¡BDDDDDDDDDDDT*DDDDDDDDDDDD%0¡BDDDDDDDDDDDTÂQÕÞ€J]ýõhmm­öfTlÿþý˜3gŽ>úèjoJÅöìÙƒN8¡Ú›1mû±cÇ|ðƒÄ…^XíMö•;ï¼÷ß?N;í´joJÅêå3=¿gžzê)ü×ýWµ7×wÖ¬Yƒ3Ï<³Ú›Q±×_‡Âüùó«½)«—ï™rÏÉþýûÑÔÔ„›nº©Ú›ì;7ÝtÎ:ë¬joFÅfâ5ÇïÊ=',Ûæ÷ðÃãG?ú/^\íM©ØLûL×–m+óÙÏ~'žxbµ7£b,Ûú˶•ó{ÙÖï×’Zø^ð{¼OEÙ¶æ*Ï<ó >ñ‰OT{3*¦ë:š››ñŽw¼£Ú›R±®®.\}õÕÕÞŒiÛ]×122RíÍõ_|/¼ðþþïÿ¾Ú›R±zùLÏÄï™x Ú›êK>ú(:::ª½{â‰'044„+®¸¢Ú›R±zùž)÷œ<ñÄH¥RÕÞ\_zùå—ª½›‰×¿+÷œ°l›Ÿ8&õŸ3í3] X¶­ÌóÏ?|àÕÞŒŠ±lë?,ÛVÎïe[¿_Kjá{Áïñ>eÛiO¨¤R©1_2---hhhÈz¾©© MMM%×·`Á_æxŽKKK š››«½) uqNÊÝsÌ1ÕÞÜŠ•ŠMï2åÄçâÅ‹qòÉ'ϨςßÍÄï™ T{S'ÅdÇgccc]|¦1þüºØ—zùžÏ9Ù·o_µ7wÒxcÔ»ïåÄn.–mý§^â³ÜsR/e[±Ïùb3÷9¡X|sÌ1X¼xq]|fÚgºÌ´²-0¹ñyÜqÇÕÅgše[ÿ™‰eÛ™Voë÷kI-|/ø=Þ§¢l;í •®®.ôõõe=ÖÝÝ@ €žžtuu¡¥¥[¶lAgg'ÚÛÛ‹®oÉ’%Ó½ S¢Ô~Ö’ÎÎÎjo÷cŠÅ&€qÇç’%K|Ý­s<êå³Àï™Ú5ñYš››}[ð¯zùL×Ó9)WWWzzzÐÒÒ‚T*…††ÜvÛmhhh(»õŒ×ÿ©§sRŽb±)žŸ©ñÉÏ´ÿÔË9)ã3¿z*GÕËgºžÎI¹&»ÞÖïü¾ýµð¬—xiO¨ŒŒŒ¼vuuaÆ ªU«ÊÊxQeŠÅ&Àø$ª&Æ'‘?¥R)lܸ›6mrotTUEOOÖ¬YS2v‰hj”ŠM ôµ•ˆ¦ã“ÈßXoKTÚÓý†ym`` k‘¨ö1"š ŦxŽñIT=ŒO"J¥RY­Æ–/_ŽááaÅc—ˆ¦N©ØŸDÕÂø$ò7ÖÛ•6­ 1̺uëpæ™gâ‚ .@OO`hhhLÀ666–œÔiûöíu1±.Õ¦ŽŽlÞ¼¹Ú›Q±b± L<>7oÞŒ®®®jïÍ@CCCèèèÀîÝ»«½)›ŠøÜ½{7:::²ÖC4]ÄP{öì©ö¦T, »»Ûý{dd}}}hjj*»…°lKÕT/eÛb±)þÆŸ,ÛRµˆ²íöíÛ«½)›ŠødÙ–ª©žÊ¶SYo;44TíÝ£¨««kJʶӚP-Ö¬Yƒ§Ÿ~6l@WW²Z#å´HX²dIÖŘh:uwwcåÊ•ÕÞŒŠ‹MŽÏ•+WÎȱ©úš››ÑÝÝO<±Ú›R±©ˆÏO<ÝÝݾ/–êS{{;:;;q 'T{S&U__Ÿ;ìA{{{ÉØ-„e[ª¦z)ÛzåÆ&PúÚZ˶T-¢l[/óà “Ÿ,ÛR5ÕSÙv*ëmý>Õ§ÎÎÎ))ÛNë*¢ ¬X±Âí6–+•J1àˆ¦A±Ø ŒO¢*b|ùÛÈÈÖ®]‹T*…õë×g ƒP,v‰hjŠM€ñITmŒO"b½-Qy¦½‡Jn¯††NÐæv渙DÓ XlŒO¢jb|ùÛêÕ«ÑÔÔÃ0²*zJÅ.M­B± 0>‰ªñIäO¬·%*Ï´&T°víZwL>ïX™@ÃÃÃn7Ρ¡!¤R)¬X±¢ÚLj¨î‹MŒO¢*b|ùWOOFFF°|ùr ¸ÿR©TÉØ%¢©S,6Ò×V"š:ŒO"ÿb½-Qy¦uȯööv aÕªUhjj–-[ÐÞÞîŽsÙÙÙ‰µk×¢¥¥[¶lAgg'["MƒR± 0>‰ª…ñIä_©T ©TjÌ$òkÖ¬AgggÉØ%¢©Q*6˹¶ÑÔ`|ùëm‰Ê3­ X¿~=†††ÜnaÞVíííH¥Rcž#¢©U,6Æ'Q51>‰ü©³³³èÕ¥b—ˆ¦F©ØŸDÕÂø$ò7ÖÛ•6í E',b@UO©ÉÄŸDÕÃø$ªMœ¨“È¿ŸDþÅø$ªÖÛ7­s¨Õ"&TˆˆˆˆˆˆˆˆˆˆˆˆJ`B…ˆˆˆˆˆˆˆˆˆˆˆ¨&TˆˆˆˆˆˆˆˆˆˆˆˆJ`B…ˆˆˆˆˆˆˆˆˆˆˆ¨&TˆˆˆˆˆˆˆˆˆˆˆˆJ`B…ˆˆˆˆˆˆˆˆˆˆˆ¨&TˆˆˆˆˆˆˆˆˆˆˆˆJ`B…ˆˆˆˆˆˆˆˆˆˆˆ¨&TˆˆˆˆˆˆˆˆˆˆˆˆJ`B…ˆˆˆˆˆˆˆˆˆˆˆ¨&TˆˆˆˆˆˆˆˆˆˆˆˆJ˜pBeddªö>M© %TºººpÁ ££]]]€ªªL®Q]wB¥¯¯===èîîFww7  ½½«W¯ÆÈÈHµ÷‰ˆˆˆˆˆˆˆˆˆˆˆhR;¡200€ööv¬Ç׬Yƒ¦¦&lÙ²¥ìu IÀ¤R) •JUûØÍXùb`|ùã“ÈDü |ޱI4ýŠÅ¦÷yÆ'Ñôc|ùëm‰ò«Ú¤ô©T «W¯ÎJÀôôô`ÕªUظq#V­Z…žžžj¢'_lŒO"?`|ùOWW—ë֭êU«ÜOÆ&Qõ‹M€ñITMŒO"ÿc½-QaG÷@7ß|3V¬X‘õxOOR©ZZZÊZϺuëÆ<ÖÕÕ… 6 `hh«V­B @SSSµÑŒ‘/6Æ'‘0>‰ü%•JaãÆØ´iš››ªª¢§§kÖ¬alUI©Øxí$ªÆ'Qm`½-Qaã|ùr´··cÕªUX·n¶lÙUUÑÕÕ…ÎÎN444”\GWWš››³’/hllt‡knnFsssÁîŸD4ùòÅ&Àø$òÆ'‘ÿ¤R)·BpÊÊÃÃÃŒM¢**›¯DÕÄø$ò?ÖÛ7¡!¿:;;aÖ¬YƒöövtvvâÞ{ïE{{{É× ¡¯¯ápxÌã¹ÍÆÆÆ’còmß¾Õ>Ž4Cutt`óæÍÕÞŒIQ(6Ås‰ÏÍ›7£«««Ú»F3ÐÐÐ:::°{÷îjoʤíÏdÆçîÝ»ÑÑÑÁ.ÚT===èêêž={ª½) èîîvÿA__šššX¶¥šT/eÛb± °lKµG”m·oß^íM©ØTÄ'˶TMõT¶¦®Þvhh¨Ú»F3PWW×””mÇ=äWOOšššÊJ xŒŒ`íڵذaØž,¢5‚W9]Æ–,Y’u1&šNÝÝÝuqSU,6‰ÇçÊ•+ÑÙÙYíÝ£¨¹¹ÝÝÝuQ)9ñyâ‰'òÚIUÓÞÞŽ¦¦¦ºkÍÖ×ׇ®®.·Œœ¯|À²-ù]½”m½rc`Ù–jO=•m½&+>Y¶¥jª§²-ëm©ÞLU¹mÜ •T*…žžlÚ´iÜo¦iš››Ýa†‡‡144„ÆÆF466æ}/o7P"šÅb³¹¹™ñITEŒO"7ž©T ëׯw‡A`lUW¡ØŸDÕÆø$ò'ÖÛ•gÜ •p8Œ‘‘·A®|yŒŒ`ãÆœÀ»çž{0<<Œ@ 0¦{æðð0'6"š&…bSŒ‹Éø$ªÆ'‘­^½---cZÞ16‰ª«PlŒO¢jc|ùëm‰JwBEÓ47€D€y=ýôÓ_›Ûͦ££kÖ¬q“0"044„T*…+VTûÕ½R±ŸDUÂø$ò¯žžŒŒŒ`ùòåYÃ<ˆáq›DÕQ,6ŸDÕÅø$ò/ÖÛ•gÜ •ÎÎN7À†††0<<ì;R©ÎÎN¬]»---زe :;;óŽODÓñIä_ŒO¢êH¥RH¥RcÆ´_³f[fflM¿R± ðÚIT-ŒO¢ÚÅØ$rŒ;¡8- ººº022â>ÖÔÔ„ 6Œ+±’Û½³½½@©TÊm@DÓ/_×kÆ'‘?0>‰üÃÛÐ(Æ&Qu”ŠM€ñIT-ŒO¢ÚÁz[¢üÆP@WW:;;±bÅ 444 •JaãÆX½z5y䑊6ˆIä_ŒO"ÿb|ùc“È¿ŸDþÅø$ò'Æ&pÄx_Ð×ׇööv´··»Ýºššš°~ýz466fIDDDDDDDDDDDTÆP.øÇÍ#""""""""""¢z4î„J @__†††²ïééA*•BKKKµ÷‰ˆˆˆˆˆˆˆˆˆˆˆjD"˜fµ·¢´qÏ¡ÒÞÞŽ¡¡!¬Zµ ÍÍÍhllD*•Âðð0:;;ÙK…ˆˆˆˆˆˆˆˆˆˆ¨ÄbÎÏx<û±`P”ñ¯Ï¶IÊümY€aápæ1Ót–SÕì×êzö{Z ËÕ>BÙÆÝCÖ¯_M›6aÅŠhnnÆš5kpï½÷¢½½½ÚûCDDDDDDDDDDD9tÝé â%’–•½œaŒ},W(”ý·emmÙišó/w;l;û1Ót’8¹ë7ŒìÇ"‘êÃq÷Pš››ÑÜÜ\Ý­'""""""""""¢,¦é$Oz{³3M »lk+08èô ‡„DzeÎc–å$2d9ӃIJ2=M¼=RlÛI H’óÏ0œŸ±˜Ó#Elƒè}â]_,æl›ªf.–å¬Oôp±mg¹½[¦Ë„z¨ `ݺuîß===èêêÂÈÈHuö‚ˆˆˆˆˆˆˆˆˆˆh†ÊD µ%zšˆD†¢8=D,ËI¢hš“ćÌÂ…ÎëÅP[mmÎã¶Ý«D¬WÓ2ï‹9ëÑ4çõ±˜ó~ɤóžâ}mÛyÏPÈyláBg9‘T1 çqUuþI”¶6g½â½ g¹Üž2SiÜ •¡¡!tttd=ÖÔÔ„¬^½zú¶œˆˆˆˆˆˆˆˆˆˆhD¢¡–µµe¡%z˜ä>&’$‰„ó¼i:½E4ÍID˜¦“ Ð4'iašN”`ÐIXôö:ë¶ms^‰8ËŠ„‡¦9‰‘I—XÌI¤$“Î2ªê¼>tÖ©(Î:ƒA ¿ßù)Ë™uÎr{÷:ëlksþŽÇ3 ±=Þó©i™ÒT÷_÷ÜsÚÛÛ±~ýz÷±@ €Ûn» «V­ÂÀÀÀÔl-щžÕ2ªR¶mÃ0ä¬ ÛÅ\'ÞD„·§ˆ¦9‰1—8¢gŠè¹",€ó·ªfæ5Ã~‰÷Ï…BNâE¼X§˜ìÈ 1æÌK û%¶)w¹p8“ŒqÞ;†“NZàìÝë$[ÄñH$2I£+®˜üã?î*©T cohhÈû8‘ˆžµ"Éîma¤»c<ðÀno 17eÖ,§GŠ,;É…hÔùg³íÌߢwˆwRøþþìĆ,;ï;?£ÑLo”`03´—$9Ë:I‘HÄO¥”x<³\,ƒ–ÎþÈr&)£i ÃÀÀÀjw^1\˜˜[%ÑñÒKs'õ|Œ;¡ÒÒÒ‚¾¾>¤R©¬Çûúú044„¦¦¦IÝ@""""""""""¢J‰ÉЫ1äW9CPÅb™$v:[‘;wÉO~2Œ††|ûÛg#szˆ´µezeȲ“˜=EâqçŸW08þ¤’ gÁ óÓ²,èz ëÖíp“<^–e!‘H@Ó4w_ÆÃ²,Xéî0‰D–e!‰ ‘H ™LÂôP‘$J$DOýýÀÞ½ pòɯMêy÷_kÖ¬A*•‚ªªîÐ^ÃÃÃÂúõë™P!""""""""""ß±¬ÌÐVÓI •Õß_|9M=MLD" º²ñ‹Â÷¾÷vô÷ïÅÉ'Ïã.t‡Ê½I #ÓK¤P1¤Wn’¥ôNñ$`K6dÙF[[$I‚išeªÈÐD$¶¶6ȲŒp8 Ã0Lw±, š¦!B*ÒmŶm˜¦ ]×ÝÄL4E0„¢(Pº®# B}i™¡ÇfÍjE4:ŠÅ‹wMú¹wBÖ¯_öövÜsÏ=€ÆÆFlذÉ""""""""""ò%ÓtzXhZåë*W¹=btÝIŒŽîEW×&˜¦éö¨ih؃‡~'Þóž0gÎMX¾ü˜;÷ úû/t“D€3y|)bx¬ñH$øÈÈGÐ`5À„‰P(UU¡ª*"‘H&™: )‚Á âñ8t]‡išnRE$I ^$«cYZµ`àî$“I7!#¬\¹±X ’$Aú‘ ù çø‰Þ2á0`ÛX<©ç³¬„JOOzzz°bÅ ,_¾MMMhnnFssó¤n ÑT=4¦‹¦9=HB¡±ÏÙv¦'I"´´ÜŠžžýؾýßpá… ÞûÞÃøØÇfãÁŸÅÒ¥û°wïEд#1{öq˜3g$éB7™8I¹ÄJÒø‡ûÒ4 §Ÿ~:VÉ«`$Irz†¤W”H$8óžÄí8 Ã@4=鉪ªîóbè¯uW®ÃQOåOM´µµ¡··MMMøôÀ§ñûM¿Gð¶ìdŠmÛ¸ãŽ;pÎ9çÀ²,„Oþë##°¬=0MsçÎÅ'>ñ~¼÷½ïÅd'TÊšC¥½½·Ývššš°qãFttt «« CCC“º1DDDDDDDDDDD“­­-3ä—7 Q©|ÇE"ÙÏ‹9>LÓé‰ÒÖ,[æ$Qg»Âa`Ë–`ûö/ ^ýÜtÓ¯øÃ9øÊWã׿>Á pÜq‡Ý䄦i°, †a ­­ mmmî¼%Zž®8ã?EÓ4H’„ÃO 'i‡ !IÂá0dYv·NøÓ PÒY ë%I’;Œ×…G^ˆSvŸ’çX:=Yb±:„ùóçã“2k™X,†D"þþ~Ì;×™gÅŒ„Ë.» †aà”SNÁðàƒNÞ‰N+{ȯ††,_¾Ë—/àLBßÓÓƒT*…ææf¬X±¢ì+CCCFccã˜×¤R)¤R)455q1¢iV,6Æ'Q51>‰ümddÃÃÃYñ'âÒ«¥¥ ÕÞ\¢#_lŒO"?`|ùS=×ۆÙÞ)9£GM˜m;=O¶mËû.\xá?¸’à 7Üê®ë¢!bD°lÙ2p{¥X–Ó{DÓ4†á&?&Ê0 躎d2‰×.~ Ð(p“%^š¦áÆ÷߈?ð'œrlv²DôdC|mýÛ­Ý; ˲‹ÅÐÛÛ Ðu×\s 4MÃ]wÝ…Óþí4ü¿¿úøYÛÏ ¡iz{{Ýý=pà4Mú³×á§~ŠÅ‹ò,D£QD"444àÓŸþôäœì´ Í¡ +¹244„{î¹7ß|3¾ò•¯M¬¬[·hjjB*•B Àúõë8C‹uuu¡¥¥[¶lAgg'ÚÛÛ'u‡‰(¿b± 0>‰ª‰ñIä¢åWgg§ûXWWúúú²–ëîîF ¨öæÍùb`|ùã“Èê­ÞÖ0²{bˆDÄb¥'ˆ/‡˜ãÄû^‰„HžèˆÇqÁŸ°ÀÞËû¾â5†sÌ¡ªª»ª:‘ˆ“9眧²Þ÷¸?–eappУDQwÒvm’&‰±mÛ¾çÄ @Ϟŋãë_ÿ:þÔõ'œ»õ\œø¥aYlÛ†eY0M3k¾”M'lÂüóñó/Y Ÿ[o½‰DÍÍ͸úê«qø[‡ÑöhÔÏ©8û†³Ç$‡n¿ýv\zé¥þì0B‘Ö.Z EQ Ë2Ž;î8455ᥗ^š”c!L8¡âUî|*"ñrï½÷¢¡¡©T ªª¢½½ÍÍÍèêê† 044„U«V!ÔdÆ“¨–”ŠMŒO¢*a|ù[OOÐ×ׇ5kÖd=722 ¢*)›ã“¨šŸDþTõ¶‰„“ÀP'a‘!kRFöœ,±XæïõëˆcŽù0öíÛ`$iì6$NRE–]ÿ6n¹eÐSÂá0"‘HÞ!/Þõ"+‹aÛ6 Àa$ Š¢ ™L&p× w¹É–‰ð¾vç¼xòГÀœìet]Çœ9spùå—ãÉ'ŸÄ¹Ò¹8t÷!hCš;X8v×£ë:T¨Pö+ˆ™1(ŠâñõÞ÷¾ÿüÏÿì®{ö7gãg—ÿ 7=~SÞí“$ G½p}÷%œ÷ÆyPUÕM¨|ìcÃã?>é缬9T„ôôô¸ ¡££ÃS¥”T*…ööv·›¦¸ááa  ±±Ñ½`Š$ÍÀÀÀ¤ï4e+›ŸDUÄø$ò·–––¬§—hÝGDÓ¯XlŒO¢jb|ùS½ÖÛŠ†e!+Q1Y½S$Éé"†ù2 g¨¯]»váè£ÏÂ?¸'ôƒô|':Òó´C×uÌš5 [¶ì@"XVÈ“Ä+Ã0Œ¼ ‘ÅÇŒl=k9¸üùËa¦'yÑ4Íý½üãg»ÛÔ¶¯ ]ˆÅ»»Ïµµµ!‘H âG?úÎ?ÿ|ìk݇7zñxápñx¦i¢µµ±X ¦ibÙ¬eØÚ°ñxªªB’$üô§?ÅêÕ«³7@þéÇÿ„…Ï-,¸Ÿ>õ\¼úè¸í¬Ûðõúº;§K<ÇûÞ÷>œ|òÉ•Ÿl²*ëÖ­CGG‡;Že*•rw°¹¹}}}X»vmÑu,_¾ÁÀÀºººÐÜÜìf6s/˜cÆÍ̵}ûvtttLêA!*WGG6oÞ\íͨX±Ø0áøÜ¼ysYÉV¢É&þ»wï®ö¦Tl*âs÷îÝèèèÈj$A4]ÄP{öì©ö¦L YŒŒpÊÐgžy&.¸à‚²bŽe[ª¦z)Û…c˜x|²lKÕ"ʶ۷o¯ö¦LŠÉŽO–m©šê©l;•õ¶CCCUÙ'1? à$T¼Ã-\XÞ:–-[†ˆw†y]w*ñ¸ì®;™t~>ÿüó8ê¨âë_áµ×æ!‘H ‹aáÂ…0 à dddN?}$IÊKçíabe–±¼“µxqüÐu­­­0MÓÐ=K @"ïËaYTU…mÛhÞÙŒƒ‹B²¤ôþëeÉdÒÓä£ý(~ðƒ`ãÂYëQU½½½ˆÇãˆÇãXpÝܹäNÀrÖFÑÞÞ>&¡hx_P$tÃìÀÅqüÃÿý4>’¹¶tuuMIÙ¶¬!¿D—¯M›6¹-úúúÐØØˆ 6 ¡¡íííPUÕ˜¨˜T*…7"•J¹ó°ˆ–¶^å´HX²d º»»'ýÀ•£»»»®nªòÅ&0ñø\¹rå˜ñp‰¦Css3º»»ëªRr2ãóÄO䵓ª¦½½MMM5Ñš­bÌé5kÖ »»X»v-šššŠa²-US½•m ™h|²lKÕReÛB&Ÿ,ÛR5ÕcÙ¶žêmÅéE"’Y7ÊþË;ÜU,“ð0Mଳî¾}³pÝuoáÑGp‡ûJ¥~ ËŠãþûSøÌgzaÛ6¶mÛ]׋ŠI‚Á ‰VlÝj£¯o[Á툊n-^a’Ø/¶mÃ4MÅ$1isspÖ+gáXõXÄãqwh°1 ‘¨I$ˆ#ŽßÌþ æ¦æâŸø>ùÉO"»II’ð©[?…Ó<²&g­Gõf³ÒN}æT¼ú³WùT$ïó±;ÑüOò€ý6Ži»Ç´¸5}l€)+·••P¹çž{²ºc `ùòåYÝÀÄ„E¥JFFF°jÕ*455åm™J¥Êš›…ˆ&G¾Øloog|ù㓨¶ˆ˜V¬XŽ OTeŒO"ÿb|U_½ÔÛZ–3±»È/Èrö_…êï½t]G0D0Dkk+@Óœ!¾Ä{üᛕƒ8tõÓ峡ë:àÈ#G—^ÚÓ4ݤH0D$qæ8“,Ó+£!júŸGVO € Üš¼5k9;7›äÉ}†á&7>ùÉOâ裆®ë$ Ïÿ<†OÆ™?=¿øß_¸½R¼VþŸ•No’àô »Húœíûóƒ†,ËÐ4­À‰ÌyMîy3Mà£aàjZ xØÿñ‡²‡üÊM’  ¥¥%ë1‘\)¤§§7nÌZ¾¹¹Ù ÀÜnbÃÃÃ7“h‹MŒO¢*b|Õ¦T*5fhƒRee"šŒO"ÿb|UO½ÕÛZ–3ä—¦9uîù:e”âM.±Xf]Á ³ÌMoÝ„³Ïþ]úù4MÃ~ôZdYÆ œ¡µô÷÷»=I‚Á`áÞ¥xò"y‡ü’á$ <Ãe½úê«ÌZìî'ïÆ³_{­­­…B°, º®£··ëׯG0D4ÅÏßÿsü÷Ïÿ_Ÿõõ¼Éw›, ²“!y¼ðW/¦3OLÁ¹]ÄPdœ„J®`¸8 üÌNŸ¸½ÄW¨¬„JcccV×µ¾¾>Èj022‚¡¡¡¼K¯žžwLLñÑuSLr8ÃŒ¥R)¬X±bJ9 Å&Æ'Q•1>‰j¢Ä»}}}¾¾é$š)ŸDþÅø$ª®z¬·µm'¹’;IÎÈXy^çd+DïEQ°nÝãPUg]_ýê¸ï¾BUU,Ù³–eÁ²,ȲŒþþþ¬ž"Éd-Ç´¸ †¼ó¡ŒÓW.ùJVBE–å±I Î{Ú@(B$Á“O>9f]ÇÿñxœöüiˆÇãØ¶Ízì€,ËYCˆ]õÀUxå•W˜U`ÂÀI|Èp{Çs`ö÷çãÜã‘7©"ò6Å™ à)Ûév´a8(c*•5ä×òåË¡iÖ­[‡@ MÓÜV###èêêBSSSÑ®^íííèëës»‹mÙ²+V¬@{{;g\³µk×¢¥¥[¶lAgg'["MƒR± 0>‰ª…ñIT›ÚÛÛ144”»íííY±KDÕÁø$ò/Æ'QõÔ[½­a8‰Ñ‘"w«D']׳zŽÈ²Œ;î˜Oþõ_wàG?:Ë—ÑèbÌÖfãØ? ZÞÞ&ªªºC\M”eYhkkƒ,ËPU|áƒ8¸ø æ™óÅIÚØ¶=&thñ!¼õû·Ýu÷kÇŽnòÇ4MgŽœ  Ê*,ÛB$ÁÇ>ö1Ì;7kpMÛ5Ø¿qáá¼DB¥ÌœÆu×á~å~$Ò]QÆô|‘=?e8É“Üã(¸NÔt— Sª¬„JSSn»í6¬]»===î¤.èèè@SS6lØPr]ÝÝÝr»…y[´··#¸ó°°Ñô)›ã“¨šŸDþ—o²Íõë×]"šz…&Âe|Uã“Èê­ÞVU]w’+¹=R̽'œDÃçaYÎÜ+»v]óÏïÇ 7œ…›o~Ç{ n¿ýgá0°ó¾xØxýýýEVZÙþ ºs´À¶ÏmC‹âLÉ!Ë2 Ã@,s'§WúÒ< A8+Š‚žžhšÓ4¡ª*¢?‰: °d'Óô?ÿó?czÒì¾d7 óNüZúuþL¯q8Éxžå‚ÀŸŸú3n¹!+Rp(1ïºÅ¹ŒÅàŽ«æ•€;1ýT(+¡8c´y›kiiAww÷¸&+Ö‹¥V’¨•šLŒñIT=ŒO¢Úäç‰:‰f:Æ'‘1>‰ª§^êmƒA§‡J[ÛØÞ)ÀØ!À¼"‘îºëh{ìRX–Ó›å< û÷ßEž{îǸçžwf^`_ûñ×ðrãË…'˜¯`”/Ó4‘H$‡;™‚ƒÿ}¯lyw†(Ó4 Ñh²,öm¼ùË7ÑñtNÚq–ÊKÝõÍŸ?ßM®(Š’IhØ@$A<wßÏkÞÎyÀR ýˆv@Gþ¤…w¾{N$_B%¼çø÷àà{O4y_«"“P±íLVL$ZDç ÀO àÚ ÎMSBÙ“ÒÒÐÐ0®d ÑT …œŸÉdþN ÞŽ¶mÃ0 ض ]סë:.\†xÜ™Ô^–ûïŸ}û~ Û¶°{÷­xöYÏ<â6ÐøHcñÞ&ÊKªh3ùº®ëc&¯ß±cî}î^w^Ã0Ç¡( $IB(Â-·Ü‚¥K—âµæ×²’{÷îuçGq·Ylƪªƒ3|YÃVgˆ·?7ý¹ð„óÞäH™$H§_:®\w¥³\!1ÏïŠg]ºžÉŠå&d’>ÐVÆÁž˜²{¨¤R)lܸ©T ‡Ãl1@DDDDDDDDDD¾aÎp_.0ô“®;ËȲ“°H$ƒ°mÑh/Á ‰8C~9ËÊÐ4 @Y¹† '¼œ—Kå7Ý¿Á®]»ðÇö?²,Äãq¨ª:&¹qÊ5§àˆO‘í#Øcí3çK8ÆUó®ÂIC'á¤NÊšÓäÕW_ÍÎË\t{öìÓ+%—išXÔ°¨x¯±á"Ç%\ª\êü\„óv?~Þã¦i@o¯ó»³œ ठº•Pv•ŽŽ  ¹¹©T «W¯F*•š² #""""""""""EÉ?ÌW.11½išˆF£0M†a@–U¤çvG8œéá¢( 4MÿýÛdìebl¥~.Noó¨¼øÊ‹xû‚·CQ¨ª MÓ܉潞›õ4MÃön‡¦ièííÍn,cÑK‹œ?$dÍS¢äïì–[n-ÛPŠt£™?>Ž;|ØI|I”dõ8 #ÿõÞž'20ïy…×çÕ à7V&æîTα-’µªPY=TJ¥ðÈ# ¡ÁéÚ£ª*zzzÜÉ鉈ˆˆˆˆˆˆˆˆˆª)‘[ߞ˛S0 Éd‰DªªÂ43Ï{‡ s˜Èò Ù+“Pº‡Š=vÓ4aÛ¶Û³$‹aíg×bÑ¢E¸P½°èêNûãi~3ˆ%÷-A<Ï¿âù)¼®W¯|·Ýzn¼¹hbh6¾…¿yöY¼ÙÐ4äD%'q$:ËšGe¯è¶3Ù ¼ï?ß+ßAŒèÏ9ŽÿWú½'Ù½W#(äš ²{¨7™Ë—/Ÿš-"""""""""""šoB¤ô²&EI¿Æ™¤Ý¶|sË˲\xž”Rï—“P1M¡P‰D·E’$,ZT4ù!Ìž=­­­°$«p2ÇBÑáÅ„gúžA0tzÏ$Š,øé nرAÛþ6˜Õ률BI­£$'óÕÖ$ÚpéáKËXYú8K9Û©alÏŸP¼ø¾T âI鉈ˆˆˆˆˆˆˆˆˆüÀ²ò'D¼Âa§‹a®D[°p¡†p8ìΙ2.Á2–I¥ë: ÃÀàà ¢Ñ¨›T‰ŠqÊÊ™% â«ÞYpÒwXÈôÒðNèžãõ?¼îÌRlH²ÿ4[e„|qûñØ™9ó•Dña¿Ì<盀ÝÛ[Ä3ïˆ$I°m¡P†a@±<Ù9Ï{ë:Шd÷±,àmÀ  µ5{ù–s"D’ÅМá½Üuf¿äÀìX<0¶w‹œ~/‘œñ>WŒ¦í~õ·¿ÂóßÀd*«‡Jss3{ž‘/™fùËÞ}÷“0Í9ˆFw¸)Jyɘ¼Èê%¡i,Ë‚ªª0 ×ÿïõˆlŒ8IŽRÉ€ €Ð8Þ[“ˆ(5T™çùH$‚x<Žx<ž’K,c"{þ]¾9<èyL–cl`Søƒ'›tWØd«T u^»C.îÏžØ&gþ•KvïÆÛ^»P¾¼a÷÷¶â,'Nï¯RI/Ëd ÃÇã@–g܈¥R) ¸C~555aÅŠhhh˜ô#""""""""""*G¹ ‘[¡( 35ó¹uöe‹Ãéqáé]aYäô|#¶mJ?aÃIVLBñ* ²ç:‰¢ì‰ìEOY–‰èsÉ;„Xo/`çÉ ŽMü|ª×Ù>‘¼Ñu ¿0r^Ÿ3OÌ£ âÀìýxŸe,§‡I0½“ù¶ÓJÇx™û>‰Æ5)}WWTUEWW†††044„uëÖá²Ë.ÃÆ§wˉˆˆˆˆˆˆˆˆˆˆàÔÝ—“P±, o¾ù0úûã™ÉØ'Ê‚3–è%g^nÂ" â}ït’(¥’%"©-ñžÞ6²‡ã*D`:É”h´À(È3I‘®/¢G‹—7w :½YìœåÙ/90{6]¸ˆH@RâIgÝ…z¢x玑Qº×Ï$*;¡ÒÕÕ…žž¬_¿<òº»»ÑÝÝGyáp]]]LªÑ´3ŒâÏ' X–]×KÏcR. xà Ø·o‰lÛÛû#†LÏ”b oïÃÌÎYG¾yO A~É^Îp=Yûߟgý¹o-#¯š(²“9=u\œ„NŠHÚˆ'fú_¡×Hé÷¶ÓÛVj¸³ITVBehh7nÄm·Ý†ööö¬ç°fÍtvvBÓ´rVGDDDDDDDDDD4-b±4Mƒa0MªªV¾R[·nÅâÅ‹ø¾ÿ€¢(H$…_ #ÿò‚HdlŠ7Ç ¯CÍó˜7‘aÛÀ7Àã–3ŸˆX&ŸY9Kp#ÞIir“8^‰œçò%7Â_Ò£œa¼T8CŽéyž‹Ç³'±ŸDe%TÐÜÜ\p™5kÖ`ddS²¡DDTÿlÛ†eY0M±XvÁAÓ4Äb1·ë,‘ öÉ4M„Ãa7¡¢(“Ó¥á7¿ù zã!„"!|潟ªªˆF£…‡+ÔÓCG®Q}ã˜$wè-IZ{+ÃÎXh¶ o™ ȳ=A‡ À›*–P #Ó“$ŽâÃo•èE䮯œDâûq•ááá²VÊZNLlŸ/ù’;é=MŸb±é}žñI•Z¶l™3)[ŽD"ÖÖVD"˜¦éö|´m‰Dªª"‘HŒI¶ä‰D°ÿþjïê¤a|ùÛÈÈHÞøclUW¡ØŸDÕÆø$ò§Z­·µ¬â ˲F¡ëzþÉØó±‹?­ë:Nþë“qÉúK`š&ŽxþÀBéõêÀbYÀ·Ûœß?¢ $e¼s¨$ÎîaäIŒ(Àê :½Mz´Ì-^â1Ûv’/SOVCBá.Þ÷.V]#¥·;‚üÛáÝ¿Xéãïì#¦u¸/ Ì„JcccYI•rz§tuuaÕªUظq#Ö­[‡U«VaddÐÓÓã>·jÕ*ôôôLïÑ šÁŠÅ&ÀøœéLÓ¹>—bYVÞD‰‹Å I2,K†išc^«ë:öîÝ‹ÁÁAôööºcŠñMUUE?lÛF[[[Á÷², š¦á™gž©ö¡›ŒO"ÿÓ4mLì16‰ª/_lŒO"?`|ùO-ÖÛº9Éå)ÿ2¶Ûc¤···ð„ì¹(:ï‡iš8çœs°hÑ"lÛ¶ ³ÿnvá…Ud ò÷ÔÐuà°'+2/ü¦D÷ Ót&·á$*¼,dz‹È²³¬‘gŸtϺLÓIì\—ŠâI¤·%˜þ—§.*k˜4N‚¨T’ócYÎ5¶Øó¡sÝ(•,1Mg¹BÉ’XÌ)Äã6lÛÈû^çžûúÖ®}þîï>†G]MÓ eJ'ª:ˆÝ»?…ÿøÿÀC5à¼ó‚ax×cáî»wAÓÂ0Mç:?8¼ùæ*lÛ¶ Û¶mƒ,˰í̶F£QH’”wø/˲ ( .¿üòjŸ®Š1>‰ü­¥¥ííícædlUW¡ØŸDÕÆø$ò§Z­·•å̈V…¦E1 cìœ&åTÔÀîÍ»‰DÆ4èt{½äöÜ(8œ2 1¤UÖö˜N7›TNR¡Øv†BÙ;½ âŒB‚AÀÔ ÏObYÎDîɤ³¬7IRêxåKÔä“DÁ ê%ï˜mÑôú¤2Ö9ÍÊJ¨@gg'ÚÛÛ¡i.¸à¨ªŠ .¸\púúú°aÃ,_¾¼è:º»»Ý¿GFFÐ×ׇ¦¦& ¡©©)kùÆÆÆ’™ÎíÛ·££££ÚÇ‘ªL×užÚYMÓH$HŒý‹D"…Bèííu+j·mÛ†ÞÞ^„ÃaŒŽŽbÛ¶mP†aä]‡ÐÑÑ[o½O?ýtµAEŠÅ&€ ÇçæÍ›ÑÕÕUíÝ« ºî4"(–<·íL’¤P«‹XÌYO0è\S‹%^L3síõ&^lÛy|Ù2'¡;½G~ðƒYIÃ>ýé;ðö·oÃSOÆ¢EOÃڵͰ, »wŸƒÓO7Þø;üÍß¼Œ_< W_½°rå‰x饃îºþû¿Žƒ€dÒÙžpØ)GØ6²ÞS *’J÷Üó]lÜ8¶YÉã?Ž;wï®ö©­ØTÄçîÝ»ÑÑÑá›.Ú4³ôôô «« {öì©ö¦LŠææf466f=β-Õ¢ŽŽlÞ¼¹Ú›1) Å&À²-Õž¡¡!ttt`ûöíÕÞ”I1Ùñɲ-US=•m§²Þvhhhʶ;‘pêATÕù—aPsŸ,cÞ?Û7þòƘaÂB¡P&¡âd^Fñá§$ÏrùÑhvrF }%vTTòˆ¡°z{¦ ´¶²˜Ef¼FƒdXˆ<=UÒ-\ïp[¥Ú›‹}SQZ9É,@/Š3VÂÃ?<%eۣƳpgg'Âá0°eËN°¤R)tuu•ì¥"ôõõ¡«« @íííy ¦¹šÏ’%K²‚ê—eY$ÉÍVš¦‰D"á&>,ËB2™„aÐu’$Á¶m„Ãa÷5†aÀ¶mlÛ¶mÌúEq»ÿ™ ¤–-[æ¶„ÏÕÝݦ¦&œyæ™Õ><“&76äC©œø\¹reÙß õL×kR8œ}]4Íù—Lfz‹Œi8a‘ˆsÝ ³%¶í¼Þ¶ƒƒN2Â4Ç&TDB¦¿?óž¶í< ?ýéwÜq‡Ä†$eæ6yûÛ¿…Ûn{ªzÞõ®_bß¾exóÍxá…û/¾xàÍ7—@×ã8çœ×ñ—¿ü#Ðßߟµ矿¿þõ çz~Ë-+¾1¦5‰¢8û-’,–å$x"çÝÿlƒ=°íó³&ŸÛ½{7ê®Rr²âóÄO䵓ª¦½½MMM¾hÍ6•&zídÙ–ª©»»{F$ X¶¥ZÓÜÜŒîîîº+ÛæÃ²-Õšz-ÛÖR½­i:õ ¡°wïØçEì¼=T Mª¹ç¢íˆhƒAhš†ÞÞÞ±ë󷈤JnýŒìÞJúµ¢DTˆôæ¼î5àí àr53Y Ôì÷œÄ dg(³¨ç=¼$ÉùLo£Hþ,Kop2™]!¥Àé¡"ÖS*¹Ñ‹Â=t¼”±Ë‰zÜ,Á2ÖUÄ…^ˆ•'œPÙJòWB°|ùò1½QÄ8{¥ ˜###X»v-R©Ö¯_ïvË×2!•JåíJ3‡a0 ’$¹s(¨ªŠX,Y–¡( b±úûûaš&ôtíñàà ;išPU–e!‹!^h†ª‚Á –-[†½9ßʶmgõŠ©u…b`|#’…ZAˆd‰è’{ýÖuçùÞ^ç9EÉŸPÑ4§€L_LDrAÓ2½KÂáÌó@& 8‰±Éd&¢ª™õÄbÀw¿û[|ã'à#¹Ð]O(B<ÇîݳñÍo΃¢ìÅ¡COâë_,sÌ>‡ÃζJÒѰíïÀ˜„¤$Ixíµ‡®¯‚$G}¾ð…Ë».q,¼­M¼ù™½{χ®göÕ¶·Þú* ``àÃUúdL.Æ'Qíalùã“È¿ŸDÕUkõ¶¢þ]’2uhEÖœ‘HdL#OçÅ(šP1MKYŠK/½°€d2éΛR”˜p>w2u=ç½Är¹IïæŽ„χõ‰IãǼ§g%²g¿ %$7XÀÿhNRå/€hþVÀœIäÃ(=ü–”ÞÏd‰åä±û-ÌOIröÇ3uÉd){ȯɲzõj455Á0Œ¬ ¡æææ1ÝƇ‡ËÊvRýˆÅbn6RÓ4Äb1H’Ó4188]×ݤˆèn'&§¿'“I·òV¼V¬/ –þâËÇ¡(ʘ,i"‘@(Â)§œRíÃ6) Å&Àø,¦­­ø°Z†áTþ'“ÙIÓt^+INoÒÀ{ýÒ4`áÂô¼aÁìõ¶µ9…‡þ~§×ÆØ÷6ð©OB"á,¯(Îrbx11‰,‹Ä…†Oü8FFîó¼¿EQ ±råY8í´àŒ3¾‰/y1‚Á`V¯.A–áöñö*óR³g@¿³Ïï|çÃa±n»`Û $™!Ñš›bîܹˆF@àSÿ!˜ŒO¢ÚÃØ$ò/Æ'‘1>‰ª«ÖêmuÝ©/ˆF=õ"&Üá©ÄP_cz§È›ðÈaY.<òB'I`ˆ÷ÓóÖƒd‰¢ðpbÞÍ£¼adæ1-gÕ"Ûô,_lNö«eà7†s_.r0ÄSJÕ%Ø‹Òdd÷®™ ÞVÆ“lÜ=T*ÑÓÓƒ‘‘,_¾<«+\SS€;ÉQ ÀÐÐR©V¬X1›HU$†ê²mªªBÓ4ô÷÷gUÆÆãq¨ªšõX¸Hpx³›–eew8Š¢¸=]lÛF"‘€®ëˆF£xüñÇ«}è*V,6Ÿù‰¹=œùEÆ>¯iÎ󢨑¾F%ÓYúX,3t¥—$9ËŠ!»‚Ag¹Üëµè­"W”±Ë躎£Žz¶}úû3IUu¶Ù›  eˈF£°<3Ô{»²Ê² ˲`Y~ô£±½IÆËư¬rÏ,ì´ÓŽ@oofh°¯~õWxê©?¸¦âmôÆ'Qmblùã“je9÷± F¬þÕ¯>[íÍšrŒO¢ê©Åz[UƴṫN/9_¯ Nҥȼ º®ãÚ£®u éåòötÉ%Ávk[˵ø¸ÇSa”›há$ildzˆˆyuó%%‚(=߉pdø’üw‘®'2Ct¯ú¸(Š’·A®MkB%•J!•J÷sÍš5èììDgg'Ö®]‹––lÙ²hhh¨ö1¢)`š&ÚÚÚÐÛÛëö‰ÅbH&“ˆD"$ ñx|L ƒãÉol;s¯Hdî7TÕI¬Ø60þ_ª½™“ŠñIä/µVo›oþYç &`)VáÆÕbC¸ëºîÔY*jÉĢIégröÜ×äKZLà>¯(œäÉx¦Qà$ftOªÄáô¦É3§É˜õå÷|ñ ÓĹ>ä ^©²*©T CCC%— LÂÆù! ib,Ë*YÑÚÖÖ†`0ˆmÛ¶¹“ÄG"wŽn¥îdU°Š^*•T‹m©§JÚ‰˜)ñiÛN+°|saY–sƒ#zCN7üdÒYÞ0 ѨiÎMR¾d‹W©dŠmÛ°,kL¡À4Mض Ã0ÜJ0ÌêÙeFÞ…eYîr–eA×uôööŽ‰Ã¼cN,˰mÛæ¯bŸt]wO¶z1SⓨÖ06‰ü‹ñIÓM ,$Ñhf¸_]w(šæÜx‹Çâþ¢£ã•jï´a|ù“ßb3o[l@ncî¼d8CYyF w†%— i$IB2™Ì ­d¹…œÇsYp†ÈòÔeõ<ãÀß­Ëh¸-†Ü*—' SÎkÊM’ÔhUË’­[ñò$¯³¬„J{{;ÚÛÛ«½ÿäc–e¡­­ ²,»C å«ì•eÙíyâ—$)Æ ÆÌ‘R)ÑãÅûã%˲ûê›i:ÃyƒN’ͳ‡ÆÒ´± Åy\Ó²'˜Ï;ÏMôcä¿¶mÛÃ0 …Ü_"‘bÛvÞ‚ƒˆ»|ñ)1šïó>™=´dYv<•$AÄþNÂh2z·—in‰dzŸˆyr çÞÀ4ó YCDDEF‘©À€Q¸.ÐÀ˜!³þöî=NŽªÌÿK€ÌP f5r‘©±]a‘š5ÁËjÖîAe5Y7ݮߟîh·º f½t˨uÕ®|Ýàí+Óå/»¸ N­ˆ+­«S.ê ˆ8%¡‰SÌ@`û÷ÇéSUÝÓ·™é™¾Ìçýz啤¯U]ýt:Ï9ÏI¥RPÅë× fxDQ´.ËJ™Û5T^ÀÝuÅ @× Lá²Û3ç=d)3~B¨Õ¥—’¨½Ø¼|\»Ñ4œðôÓ Ùº*³³³ÈårèëëköÇ@-ƶmD"ðÖ<1M¶mÏùÑ2MsÎ(tQz¨ø×¯Ñ‰ YRl1¶ªª.*!C­%‘(^Ð]²,q¡“ÉøIÇñç8bäXéÅŽYV-™ˆÄÌbúúc±TUÅÄÄR©b±,ËÂøø¸·¾O­Òt]‡U2õÆ0Œ¢Ø\®²vr‘{ ©“)ˇµKÍM""""j/®+þ8ÎÜAV‰„蛞תê'Lä5E,ìßï?'8눈æ§bB¥|pP»’ÒÀ½wÝ‹K®ºÑhƒƒƒÊôQ証~ˆøw"!6*ö“0ò¥d·¤e‰Î!y"qQœP©Ô¥ì–¬'¡R˜©S“†êå¾ÚÜÚGÁÞ¿f] Ã0055UTßrddCCC-5Í‹+‘HÌY?ð×V‡Ã°, Ñh´hD¸®ë(zŽ,!4]Ò½Ÿš¦yåÄc¥—ûê¦é(G&SJ¾ü¿¬e\JQüõTʲ,†×u½¤ˆišÞ¢ðŽãÀqd W]ñxÜ›y¥iZݳ2d ¼ T*U3³äš.rvÉbE"ïó!""""j´DBÌ&Ñuæ¹¼¾P‘,1Mñ˜dRob£€Â(^ˆ.Zàq€èh v"… –¼V9:€^ð0µÆ£sl8~qùå ͺ*åìܹ¡Pˆ ••H$¼š€¿`µªª^'¯\èºVG®ëºÞ‚îÍÂë$9ŽHŠÈ !)8Á¢¦‰‹#y¤ë‹Oœ”r]±X ®ë"Ã0 o¦E"‘@4E2™œ³6ˆ¢(E Ïzg`)ŠâÍ ü™cÍ(g'_ûÞŠ¢ •J•-5HDD´R”.ÌZ®“ÁqD»&8û6øœDøÉO®@(ôl³w‡¨e¸.00 ®l[ÌJ—·âÿÁ¦¸˜ ,¼Ô/UW)™rÛßކͿڌoL~Ã#Ã5_çóÙÏãOð'¸"zÂáðÜþ‰€iˆþñ*Ö½RèQÑqT¨ Åë“ȲZ¥ý£Á’aD²¤ÒÌ’0æ·– á×\ƒÆ.I¿ˆ„ u&™üPUÉd±X ÑhÑh¦iÂ0 ¯LW,ó®.¥i,Ë‚®ëD4å j:ÃI“hÔO’¢3Áq€ÒŠ"nÏd€ÁÁÆ'SlÛ†a^¼"y™J¥à8&&&088ˆd2Ù…Û%¹¼\l­ÜL´åÒˆ} ‡Ã°m{ÙJ•5‹LŠÈR¦ƒƒþÂÕrqk ¸³ÁqŠgÜŠòDª*:‡]8ùän áKwµc±˜ˆ9Ã$1%ãJQDì8ÎÜY'ßCD´ôäot©üàøÈEÁe|pL•(tƒ¼ùKßÇ©ÿsŽRbå×s–ùEžg¢æB"ªêÔU!Ö0qQ}}@$PR³Yª%ããðgº0iß4L¨¬`–e!‘H•Ã2 š¦u°ÊNJ9+EŽO§Ó;0UU…]˜æ¦i;:©éäš_~gB&# ×´¹É@Ü.«Ô-¶j\°|—ü*•B8žS2oppÓÓÓPUÕ[D¾‘ Ÿr[š9«C×õE—üRU•¥¾ˆˆ¨¥ÉNÚÒÙ €Í-+Dhš¸O×Åó¢Q¿s×uÅ ÆHDÜ.×f°mÑá½½â1º.'¼Ö4ùüdR$_\W´‹TxÏ{~QO‚he1  E¥J›ÍœBDÔ–UþwúÛO|)#å¯KRÉËÀÛˆ8¾÷Ô§€ÿŽ/©Q—ñù*p— \Uxœm‹FU¸d¡ÝàÉâ,ø Dòã§@Å,ˆÀ€(çUíÜ¢ö+Q~Œc×›‚ •Ì4M(Š‚H$‚d2 UUaFQ‚%Ø+êÔ+g¨ÈRaDÍæ8âd«(âÜæº¢³BŽ8[º÷u`Û6b±2™Œ—ÄH¥REÿ—t]G:ön—맸®Û°²\rÔ…au— [*œ¹FDDí*X>+‘m YVTÞH&ý!‰„è|•‰Ûö“#€Ÿô `"EQDÇ¢ˆûåëMLø3jÃa ‡à6:Ž "·K>N®‡*Ê–ƒ2o¿ý lܸ¯Ù/Ѳ‰MU11>îǵ&9¤”ëºxÓ)oë–ÄQµ4Ö³¿ø¾pÛé¸ö¯ÿø™üÜ^.}A`Ÿo5ù?Ò€´ \U˜¾‹‰Æ\¥â ±±D 7‰ª •0Ķ;¨>FÎf¡¦©;¡’Ëå022RtÛØØ²ÙlÑmÃõëÓQs™¦ Ó4½Å¯‰„·Ž‚¦i姸͓\øZQ”¦wØÒÊ&'¥ë£(J¡æ®ÅnÛvQÉ;Û¶½¿UU­˜ &2å •FRU–eÁqÆ'­h®;w]P™xP‘ü°íòe% C<7õ“!½…‰Ѩ»L¢ÈqI¦)þÈ!2 #‰ˆÛTUl—®‹×–ÛˆÛ储rn¹1Lòµq¿|L8,¶]¾np¢çÅ?€'Ÿ<­Ù‡†hIÈ$£`eÛþò2˜L!"jmrmÜR¶mãÜsÏÿ©ö[nÛxè§âçÏû9Ö:k%› BYO5‘Î 47¨ÀÇ ÓŽe­U]e½tÌ-¢ibCcŠHÔêÚIB,N_k\º`,ùÕDu%TzzzÐÓÓƒ©©)ï¶P(„\.×ìí§:É’A2É‘L&½‘ááp©”Hm6j6IpákÎP¡f*—L–fù ™L‘kÉ[€¿|=4MC"‘hè¢ñrÖ‹ã8ŒO""Zq‚ã,Ë_oD&ELSümâ1†á—õ1MÑ®0M1(#×Óº.Úñxñ%½½s/øÃaÑ`bPc0Ñ!GÆËfB°ý|àcdÙ¯J§ôrMù>å:Ž/¿ü8ãŒF/ÝIÔ<²_,ó”¢l|\ÄKwµ>™—3vKY–…—¬~‰ƒ\o¤ô±¶³O{N9å91¨<ª7Ráp¡”W¸ð"ï‰÷HÙâ„R«,»ìtÒ!ÊyÙð&»TTo »ršª®„ÊÐІ††š½­4OŽãÀ0 ض ×uá8¦§§çÌ@Ñ4 Žã@Q”†®u¢ª*G¿SS9Žè(™žž{ßR.ëcR©”—L)eYVÝk~È8jdâ#¸ÆQ»I™dp]ñ9[C’¥±äzi±˜H€ÈE¥MÓo#ÈöÀà ŸL1 Q6KÎ^‘ë)Æy³Md“:8 ¤tG¥ÑhùRŠ"?ŸÓ¾¢ˆÄL9•Ú;šV>ÑBÔ)äï…m‹˜q"c"—L¦µÃðÛt娶wlz°§pƒ…Š‹¼?pÿÅxÍ'σWøt ¯4¸ î`ÉãL HkQTŸ0€úf”$ëx 5×Pé`±X º®#™LÖìŒUU¦i"]éjlÆ—²–Q¥‹»ÊuS–’LXÊ'†axk“—2‰188èý¿^Éªp]—³Sˆˆ¨­È…ÝåL’TÊ/Ç•LŠË¥åŒ“DBt Æãb¶ˆœa"Ë~Ú¶_Ö+™ )õËoiš¿®I¹'•ÆUjZWš,¬í²"K9¸„¨Ñ*Í"‘åò‚³®,ËOrÆã"ÆeI=""jO²Lc¹2¬€¨¢ª*Î}õ¹bV ’)ef…¤\[Ïߊ>}£  ´íVÚm¢þXðK|(_òK’ë£PǘWBedd³³³Ø¾};FFF°sç΢û{zz¼’6Ô\†a@QÄë\m»ÞÑòD­*X¦ðGž.uB%‹AUUom”T*5'™ø MÓZ"Þ&d!w""¢&gŒÈ1Ž#fœÈ2Wããâ1rÍOÙ¡‹‰ŽTÓôÛþcäÂì¥c t½ø"=8ÃD–É&¢åe"Æãq÷ºî'PR)ÿÿ€hÿ»®HfŒ]"¢ö&K²V»mY–¨’ãBüD£d‹¬à³fÍšâ;dòÅ <ÇEåY%&*'PÊIB$^¨#ÔP¹ñÆqÇw•„ …Bؾ};FGG166†;v4{VÇq¼…¥¥h4 Ã0`š&gˆÐЉˆ²ò'*‘Xú §D"]×aYLÓD"‘@:ž“L‘äL–F®‡BDDÔ© Ñ9šN‹RÓô“²3ðב3Lä'ÑhñÀ ¹»Ñ^à,U_)."Z<Ëq‹ÄŠ,ã'cybBü?öã:•ZÚµ‰ˆhùÕšihY–¨ºc¡xVJ@€**Œ†!ª€¤Ê¼ˆ‘(‘í?»äÿRâ}拳ƒ;F] •©©)ŒŽŽb÷îÝèëë+º¯§§ÃÃÃèîîÆ 7܀ݻw7{ŸVŒX,MÓ¼ò=ªª"‰Àu]L—[4‚¨C™fñ“ét}ëƒ-†ëº0M0MÓ[3¥Z²D×u–Ù"""ªƒm.'T¦RÅë§Ç.¸®ÿxy¡]ét«ª _/%²ˆ–‡\ÓH&GÓiû®+âwbB$Rer´taEˆˆ¨MØvõ $¦izeØ¡ xVI€ Dì,ËÂÿ=÷\1¶\{P&T‚*µ ¯ËR^+S] •;PhN2%hëÖ­0 SSSUG‹ç8‡ç¬­`šfÅÑñD*¸(™,ó±Ô­LÓD8†¢(EIÍjÂá°’'""ZÁ\×_ä=™ôŽO&Eâ(>—‡Ãþì“RñxåõHˆ¨½$þŒ3¹n‘Œï`œ/&9JDDíÅ4«ÿæ[–UœP ¬ ˆZXCF6:ò3Otøë¯H•Ú˜*Ä‚õáÂóxNZQ¼(ýÐÐfgg‹nëééÁÌÌL]ÏŸÅÌÌ zzzŠnÏårÈårèéé™sßJ&\×E$A2™µK$“I&ThQ*Å&кñ)K}þ¢“KÍ0 1¨{ÖI”C[i‘Ú1>‰V2—Aýýýèêêjö¦5iú‹L'âïéi¦ié¹\U+Ïa§*-ã³y‚ Ër~2™jÛþŒNì^¹ŸDÍ×Jý¶2Á^Ž\AöÏxë”Èsˆ <õÔSXÿÜzq¢©5ÈÕ)ü©Õ¾T!))ÌC¯®„Jww÷œDIiÐÌÎÎbjjªî76 Cφ‡‡½ÛFGG122‚þþ~LNNbxxCCCÍþŒšÎ0 Äb1ÄãqX–…h4Z6™€k3Т•‹M uãÓ4‹§ù7rŠ¿\D¾T*•**ß%gª-µv‹O¢•nddcccE·íÚµ ¡P¨Ù›¶äG$J2ñ·ü ËvÅb"¢ª@o¯xœ¢ø¥Ê5i¹&5ÒJŽÏfq1ÓLögÉf¶,çŠØg³šŸDÍ×Jý¶rN9‰DbNõž Ó4qÒ»NÂ9Çæ¯˜þèJOÑÄŒþ]-¹Ÿ„˜¥"¯g—ìŠQWBeÆ Þ mÆ ecºººjžàFGG‘Íf166†­[·Ý722‚;v  ajj ›6mB(ZÑ#mÇA*•B<G*•ÂþýûÙqKK¢Zl­Ÿ‰„èi×uaÛ6,Ë‚aÈd2p]×[¯¿w:$\…–Z»Æ'ÑJ7;;»b:€ Ñ ª(þ‚ж D"â¶pXî_$3iBËe%Åg3Ù¶ÿûø‰“ޏíÂïX+û@tÎ…G —·ÉQβ.¿ü· À^ú?/mö. Æ'Qó´Z¿­ãTnÊþ›L&S|G`ŠmÛ8fÏ1øøw»€OêÄØ_æEÃ3TLˆ…çTN¾(Òðg©ÐŠQWB¥§§[·nŶmÛ°uëV yÁ"¬ÅŽ;j¾V?zzzæLßÌf³èîîöN˜}}}èëëC6›]±£l-ËB,C2™„¦iP…ÉZ2•bhÝø´íÚ³5ç+‹Áq躎t:X,×u‡‘N§at]g,Ò²jÇø$"ŸÛ·ooöf,™XL\ä&“~mk×õ“&šV<ð¡ÒÅ0'XS3tz|.5¹ÖQibD–óÄo„,×§ib±ù`µíÙ˜Û–‚è„‹î—I ")¢þ–5÷Q¸ïmÐcWÅmà$¸ÁþOpåTàà_lö^/ Æ'Qó´Z¿mµr_†aÔ,­®ª*8ÀÕñâÙ&n•'Å!~Ï¿«Ñd@+LÝk¨ £»»†a`çÎE÷õôôÔ=z@.XßÝÝ]tûÔÔÔœŒfwwwÙΣ ={ö`Ë–-صkWs?ɳ, ‰D™LÆýod-#jˆ-[¶`Ïž=1r¦Rl ÏÛo¿ÀÜòD00 :pd™ÌÅr]×KžgŸÈòz½½½°m©T ãÁcÔ’¦¦¦022‚}ûö5{S¢Ññ¹oß>lÙ²6l`Ò…–ˆsÞyç5{S–”\kðÆoD6›EWWW]eZ­mkÛÅ%xDÇh8,’)º.:VƒëžÈÇêzqYNj}Ô¶­f¡ñ¹”mÛvcå×6J$ÄßÑèÜäÉøx›–ó’õøUˆä‡Yøwp6IÀÇRÀ.ðzø­$£€¢ŠN»µ.ðÍ ûÓtGLéSà ¸J£ c†ÈRkp=55…‘Ážgöà}x_³?‘%µøìô¶­\o¨c’‘¦ÓÚ¶KÕo;<<ì½ö|T[Þ0Œ¹ý3QŠèãq¦iŠÇ8(N¢Ô*4"ã,HÒÖFFFpûí·7¼m;¯Eé·nÝŠ­[·"›Íz·uww/( J•[̾ž)cëׯo™ ÎŰmŽã ÃqÄb1ŒsM”åPÏbS·k×.ŒŒŒ4{–ÜBãóšk®Y’ NÃךâº.F+ŽnˆÇã@:f\¶¾¾>ìÚµ [¶liö¦,¹…ÄçÚµk;âÜIíIÎt¶';Q.—C(ÂÖ­[±k×.d³YlÛ¶ ===UôÍlÛ×é4M‘4‰DD'ަ‰¿ÇÇý~>yý‰”?'Ë`Ô>VJÛv¡ñ¹TmÛvåºÀQG‰5 ƒëUØ–MhÃðñ8 jbVÉ `¿#2Îé ©ˆäÈå.ð–BÚu ?‚lKü‰øÓöd=D@|hò3-þ?VVÛv!ñÙém[Óœ»v(µŽ•Ò¶mV¿­ªúknɵmçôÏtÀ†ë-V¯H@$Æã¨¯D—†ê3Y¨å-U»m^ i)F,•u›Ëå’¬ie®ëÂ0 o±'UU‰DjvÚ&âGE×ýÑ ©”h{…Ãb±?Eí5À_àð³»²¶µãˆvb<.^϶ý ²V¡,á ïÓ4ñoùÞš&ÞÃ4ýײ,q›ëÆç䇧PŸPUûý€z ^ü@0÷GÍ€È0•f‰mˆÆ`Ã߀ ¾–Š¢zŠˆAŒ( ~ÜSöÔÀkõ˜(y߀Ӗõ+Ó­Ÿ¦Ù¸™)€(ó‡«NF£°m»ætR¢åÖjñID‚ìü’B¡6n܈l6Û’£ÿ§Ðf3üö`°|WPé©0Ã2Í红ñ^®$ðÁÿG"8xÁÈårX{÷Ýp7ßx#vÜw®8ç<Û‚ßÑFj·øl52©šNû_½Þ^q[[þ”[íØ4ÅÅôÙ*O¯Vü‡õ¤¨g‹ÇÉ‹í*‹"#ö/ÔƒÓùÊe£Kã58Mp`|“}=m™¤ŽÒŒëN9zîíΜµmƒ~ö³ŸÁ˜0ð¥ßüÇ¿öµÀç>'^(Ñß…(½X Q J¨,…¾¾>ŒŽŽÝ633Ó± ê:ŽƒD"ü`-®½ö4LLLÀ4M¼ë]_ÁË_þ¯pÝ‹`š¢Ý”Hˆ“¨®ûí(ÛI ™ôDûMQ€5k ¿qZu*å’‘ƒ]Çîþýâßr„¡ªŠçÚ¶ÿ'™,~ŽÜ&<Ø®¸Ý4‹3±˜xlô$Àý2øYáÿQÀ~°Þ@õ§‹'"€sÈÜ*ÚšŽ¸& í¢_ôoÓwÊ;ür²8à 'à-å|Jlû:§ùÄ #²Mjï‹(kÚº TÉÇ9?¶rtCüùÓóÿBšý•ZR­Ÿ†!Žc£”¦iÂuݺJ꥙Å!jVŠOZ¤zgLÖó\YŽ„SÔ›&—Ëavv¶è"³«««Ù›UÑà HžôöŠÿËŽÒÔ‡×:\×ï¤-%®p]Ñ9ëºxæoıçŸ'z{‘L$ ( ŽÿÏÿÄ›~Ç{,ž~úisÙeøN(Ã0à8.Y¿ï;xk÷îÅ»_ñ dF8ÆÀ}÷á‚ÉI¼ýÉ'›ý),©v‹ÏV‘Jùeþdî@Q;Щ!Ê Ò»ËþÊ.‰çš@8é—1"¢4W¸ ÒÜ£¶X«”_d~¡;=ß)ö†!b½Ñ G¶0ƧOö¿$“L¨Pó5ãºÓ4Åߥ?†a —_ÛVžìóqã×aÝÁƒXuß}~ƒVèÛK5ïs¤ÎÐ2 •P(„™™oÔÁÔÔr¹6nÜØìMk˜DB$^óš§ðío«V%qÅ*Þýn‘QUqÑôñ‹“¦e‰$@:-©†_n¨ÜxÝ¿?ð€[2X¦0KCÕ?Jƒ€šÒž5€6hk9mÐ&ÄóubªÜ»½0›#“·pS<˜îp0ž„×¹–=‘QU`"^xÍBB&ú@y°8¿ÏÓÔW– 8rÖÌ1€z)Ú £€r*Ìx ?Ø/Éý'€qЯ¢ßRÛç(@¹ÿ Ð>Ø·öE@ü@‰‰í3R÷ˆNª0D<<öåÇp2Nnö×kIµR|ʺí‹åº.R©”_O“¨MµR|. þâ®í*1 *x!\8×,ì§<ïÚ(Näâ.§©Ëd‰ 1X x®¬÷8HðœžLº,‰l6‹;wb÷îÝèêêÂìì,ÆÆÆ°uëÖfošÇ4ýYÍá°ß¶”ƒx˜LY€D¢¸Tœêcšâß²±íº"‹%G2É¿%ÃÀ£«Vá虬}ë[a˜&ŽþÞ÷°ñî»±÷ôÓñÒ‡ŸZTUÅø“OâÖGÁ{èºÇqðŽãÇ¿]x!~ÚÝ EQà8¬DÓÓÓP‰DפRxøûßÇëÿ{¼GU¡i’É$Þóž÷`õêÕÍþ$—T;Äg+‹ËËv²2AK7c~i8À³pQ8CB*p¼Ü5<2îDxÐÿŒŠÛ4ˆ¿/T€×¿­YVàñJŽÏÒ I±˜8¥„Ãâ”ÑÒ±Go¹¯;S)ÑZnæ£išg§<5ù>ù­Oâ‹ÿõEàõ¯Ÿû€8Äu×Êûy¥j™„ êšmÛ¶ ýýý˜œœÄððp[ŒD MM¥–å—$’NÓ”3:,|øÃã/ÿr/z‘ê%Gòùâ׿J›3HM–ª’ˆ”`ò¤Í-jªðj z\Ìm,FQ\FË)<'X?ÐÁÜr\rOð¹náµÀ6Ë瀖,üß*ÜŸ3«áøk@»ÀÅ×½ˆ¾¿ðzã?†×x× ïÕ è¶ø tâÇr@$rìWÊ |! ˜/ì›åÀºÐNÜ·kzmàÆ?DR€bÑ{Èç€ðÀÝ{OǧÑÙ3T€æÆ§,ggÛ•O¨ó‘H$`Û64MãZEK ¸T5–ey5MÇv"O%®ëÂuý£•~ [ñüÙ°‘íü„Dðõ 3 ÑÌQ±æžS…Ûâð(2yüšF ÎU²ä¤qþ¶J^?ZØWùz2)<^ްš(<Î.Ü._+˜)”E~=àÁÂëŽÃŸ¥™*¼n=H¥ ™rå6W¨¡¡!LMMaÓ¦MèééÁää$†††š¾X®¬l‹‰8Ç‹«Ë4bÐBGsœòÙ&™41Mñ˜LŽãà¬øwð øÐƒ Çâq8©î9<³j~gÛ°, š¦áÌW¾¿ã˜9úh¼ù+_Áì1ÇÀu]|ñ„ðÒË.Æ={,¬½˜H¥ðÛ† ͸½ À_UØ ù¸ž+¯Dé¸Ò³Î:«ÙŸò’kÕøl%¦éWÈdÊO˜Z49ü^×ýRXÕÚt‰„¿˜»®û%tÝÿ!»-„làbÈ«@Z¾ž¼²Pr!øÑK˜Àµa ܺ3@8€ß;Ίiï®´øŒDü²²´W<î'1å%’¬BÔLËyÝiY"‰8g‰Ã@8.?;ÀÑ¿úó¿ªü ĵS¢9Ÿ!u†¦%TÊ-H444„P(„\.‡žžž¶)W‹‰vÝà ?z^&Jc1¿øo|#\÷X|ï{q¿£00Y«Öq!GžÊß ÙáRZâÃÂÜQ¯Š×!I^«t*´Qø¿^xÝàóåë Ð ÿ¾Ï.rGõßCvÅ\›þ×~Y˜¦lÞð…ÕEgŒ?¡#;ŒŒÀþE!:‚Âí– vTÉ$Ø7 ¢Fâ€4 œèÿ&^G¿À›€° „7C$a4o¯—ß_x=Àkè:À}P?ó&º~[]ƒ‡îÃÂk´´žJ‹…5+>ÇoX¦R‹/)+\Æãñ¢ü•Ķm(ŠR÷E™]Èöš…ù¶Ñhªªzk?)Šâ%@ Ã@&“A<÷ÊŠï·, Ñh¦i"™L"N{kIɳãããH¥RˆÇãH$H&“ˆD"Èd2ð:4Mƒã8p]ªªÂ²,$ Óñä>všV‹ÏJR)Ñç1>¾€ ˆßtyÎ’ç#Yšç "1°˜2Y•8‰†àÌbB01âÀO>ÏÏzáùã(Nª¤ Ûlž¼-Ü.¼ŽV¸/R¸O ü@ñ9q¼p›q5^x¬<'j…ÏPÎú ¾–|Œ`AqyÌRVá±òqò5äíéÀãlÏ0ŠkÏY <¿ÁÇ­mß¾SSS^9„fÇf,æç,Ë_™JÈŒ°ëŠiäÓÓþÕ¼Ý!ñ8fï½'ò“0uC;wÂ4MÄb1oí5Ó4¡Ø6TUõÎ[Š¢À)Ì ImÛæßæ8Ð4 £ÿâ‹ñ½ÂA³,q ëú¢Ë*Šâ3WªV‹ÏV*”@‘ƒ'&ü‚ #kŠÇýÅΰņ¤!’q@Ä.Ñ” DâÀ©… ϸÈÞ¤jásHx‘ ­ÑBÏP¢3'¿A~ÀGm ËìL!ËÑÁô\ 8­0êq8þ= ¨bÄûs›ïÄiŸ¸xÎ6ö9‚Gví‚fk€è°€/$D-Ý“4èûGO9„NJ¨TÓŒø”×[rÇ…r]ƒƒƒÐu½ã;ìB‡åjJ‚È¿x‰™”Ä,p8ŒH$â• Ñ4 ®ëBQ/‘’Hˆ¡ÑhÔ»O×u(Š‚pá ÉdUé…£L†„Kf¦0jWÎj)ýÿt¡×/ŸÏWÜo™¨±mÛÛþ•¤UΟ²ã¥Že‰Ê<þ,H™(ÑáϾP Îe²ô¢‚âÄG0cÃO4H±Âýò¼(gWÈ$‰ 6Hâ+gj…ûS(.Ë•„8¯ÉÙ"zà~™`P ÷…mwï;]x™tÐ Î…ÏbàuáŸßuˆ„‰œ©‚Àö¤Ÿ£l+h…ûäº*r&!“H2Éœ*f¨Ï^΄‰ÃŸ}+lS¬°ý²4¨ ·ð¼Bç„ÉVDBÀ’.ÔY/¹à¼ãø3w* –Ú’å´äôÖàú¶í/úL¼Ë‘î†!ž‹ž.MR)$ ÇÂqÜñOÿ„?ýÒ—pš¢ˆÑ™(ßû>ØÛ MÓ011H$‚p8Œ‰‰ X–å3‰,ËòÊUÄãqïþJ34Wê@¥Ô ñÙ ýP±,q™ºèq)²&{Ã"…i’r1P@Ä¥®ÿj'ëþ9NÖ´m šçžWNS§¢âœ•T€³uàu:pü™ËÌq¯ÝY:ãÚqØ…Ùg¼„ª|N8†®ë^"E¾Žã8H§ÓøÁ7â—^Š¿á €-[¶,ÿ6I'Äg° ‰ì®ÿWñÿñq™LqY÷ÒS\ȨٖãºÓ0ÊÏÊ’¿¥ª¡Î™Qï8>{ýõ¸af-^ðä[œÛìŠ:XË%TšIήÖxð¯Óq½Uí‚Ô0 o:ZTï²ÇSþ¼5…™!¦? ÿß5à7.ðÆÜå{@ üRJ½z3–ÜnPŠgvD :7âð ¸N+ÌBq€w‡ÂÀ °Æ.N=Š¿í[’ÀWÀ^UœÍOUü$/R-.V…ϸþ6ÉQ¯I¿›ö§Ðý.ìrõ’*@-üJþeøGÍ/¦èJ;]à‡…Ûâqàù)ÀU jW´öåº&Šâ·0Þ®ô{Ñì° ö>yNüX¿7j~<=ŽÓ¹ûŒ}°, ›.¹þì!¬^½ß;MC8†eš° ª)F*ñ8lÛF8F"‘À«_ýjô6ûËÛ¡lÛŸæ¹X©Tªå“)±X ñx¼êÌ9zMUU˜¦é%5ê«aˆF£E£ÜTUõ"•†Ó4‘ÉdªÎî˜Ïg¨5tHcmáp¸(Yó£ýhYߟ ëU–ƒ*’Éùµ –’ä ÙQ/o~ÂE$ü½…ÿˤKâ|›„8_ÈdAþš$2I rö‹<ÊûTˆs˜LJLÞ;8m\–½’IÀïä‘3.%ùÞzà¹ð×<©v[¹ßG9›ðg®Èvƒ$gÊèÇÉ}–·É¤ˆŠ¢µÃŠŽ•Ñ©œ½“†?ã&\øÜâðgÚd€ÉKöâ韜Z:¶-r 2ÇÇ;¸öºe‰+oEñ%ñøÜ•Le £xèí¢Q8…d|< ‘kµm¸ƒƒîê¯^ûZ|ïÿþ_¼èºëH$¼„½ªªø?Ÿþ4TUE*•òJˆÊY—rA°¾wðü”L&ç$þ™0¡å$;wåz Áõ“ê\ìAN ¶eC>õË8”Ö”É|èâ|RX¿ÒKž$uño9cÒãâ¼­¡0û2í'm–8„dD¶Ãe›[¶Á]×õfÃËgjaš\<Ùu]oÐR9¥mõ+¶o_Ú¢%%'5ªª¦é—‹Ïd kÉ–‚XæË'¢–”J•o·¦R)|æåŸ~@\á똯|Ÿúïÿƪõo^Ê@¢¥Å„J@"á7$Ë1MÐu52ï²ñ_±/Â\ÿ0ÆÇÇEçd€>ŸöÏ’²CâGðϦƒ…×£:q_ Ÿš"ª_û\ðËð'6p¾ ÃûÆoØ@H £x”ŒÏéèuUJRe‰Qé©T ѨË4½ÑôªªŠE¦äŸ$Å…s<Ž£zÂY…™?B&“뺰, º®c¨ð>º®{#ýe!ÙŽF£¸çž{–ú«¹bÉ‘´‹!gY–7k¡UŸO¥RÞ—ã8Àôô´wÑ&ËcÅb1$“IX–åuÔ¸®‹ŒC×u¨ªêM•jõ–öŠ.IqlZId­çhTüíº5žìFÛO+‹¬¶¥ª~§®¬¶0o‘ˆ_Š«0“Ë«u-gžÈÇÈžäRƒð¯mƒ‚ç˜r׿ÁÛG®ë"•Jy׉Žã ‘H  `’×òïp8 Ó4¡iÒé4 ØךŒÕf¡QçH$üÙ'ɤ_u¨¼f.ù’ɹ?ï²ÊÆEG.׋aøé Ï}éKX5= 8J}kA-*òºÍ¶‹¯Ýdƒ3•*]WJ6ÌÞ»ãÿá²ÃÏÃø[lÿbϰ=ì ü*ÈѵVØOhÈQ£rQ÷§Uàeqà/££€÷K™ü™ü<d44¨=ûJ8~´\´^þ°hðKšÈ“¹¿Œ–¬ý.G­ÆÏU!FåGÊbTªUr[¹kÊ2·¹ð“¦i"Ã>Ý…â‘Þ^Äãq˜¦ ]×½"–ey„¶m{ UËiÕÉdÉdÒ!TZnH6fåßÁ’EArÄ ü[>>cÏž=‹þþÑ\¦é÷™,”mÛ^b±µÆKŽX•%¶äÈ6MÓ¼iþÒþýû½$Pp­—t:írüòYû÷ïoê¾U$•sÚ« ÖRô?4ÿG¹ÚB¥åžKM#ûEœ;½þÇÂzN\ÆDÀ(‰Óó ¿Àó-!&eš/ôY |1`?Pèœÿ@}ÔŸ”hÛ€¢éÿžûuKÿàÜ h ¤ÿ+)G –”¯·öþƒøÕé?‚®ëТ²›V¡cVž+ÇA&£y#NÓ×ùŸ…­nÛ6ô7ùå=Òió©TªÐ‘«BUÝBÜGqâ‰gÂuÿá°æýfˆ÷IÎ{.¢Qÿ\æÏBó,†!~?í’ótêcÏÀ²Ž…mûŸ…ëŠã”úÐ,p챈d•—ÐQ6 ýhÂo.*fì8€òƒ[aßsÊ•Cí[ã»g{ÇÁ²ü÷W`Û¶G‘J€/|aþú¯„?üá^×ì¯lGq±ùtÚï,mY–%6Xfƒ ’àBÓ²1`~vð‡ô~h,Ë‚‰Ì镱"g«ÊÁ2²ü–Y.ϯ—\uUáe“Ë6³U¶]eùÍr÷ËŽãxeLƒeÃJG½Û¶í%Oäz òvÀÿíX) ]¯ò·¿ÁÁßaÃð—YpÛqD0]÷g„E£þ|s9S¬ô¯íÕàN/ù}—³AdlɤH°¤V´P¾O–Éd2Þõh°ý]*ø»°l3Ëdò™Z’,­™J‰ëºX~Ë{Ú ¯I0¾‰:U,Vþ•J¥ðÁWø €¸ 8.Vxø‹ÏÇ£¯ÞUfoͱ´ÔA˜P¸&sݹÓÉ ÑÍdê(‘`Ž=€Á bëÕWcUßÛpÔúÕÀWSÀG . ÀU?ñø%I$¹Èz²pŸ,éµ9 ìƒ(³UX,PÔ!/dBdY) ^ø©¿Î¹$ß'xRC” Þ¦–õÎfqù±Ç"ÉàgkÖx#MG?ùI¼kÜð»ßá¨5kðË .Àèè(Ž>úho4ë3Ï<ƒ .¸ï{ßûðÛßþgœq6oÞŒïÿû¸æšk`¾óïࡇÂm·Ý†×½îuíÝ‹Ó~ýk¼ZUa àñM›ðõ{îÁ[Þò\{íµxñêÕØ?=7åóxæ™g>ç<ïyÏÃÚµkñäÃÏLJž|güû¿ãé¾ñGE<“•ђ⫊øŠºªÂÞôq(êep]`ýq·â¥7›øísëÅR,Zö=Ð7ŠpûñŸÁ±{_Œ N˜Âá¹ï}Þ§=o:ë×?Žçž{ŸúÀüæMoÂÚƒÇaÿ·ÎA8ü¨ªŠññ_áùÏ_!‹¨,Yñªôç¸iÊT’Ó¯ä¢Órf‰e¢™ÎHDôHÉ—,$4MÃýßøÞ=8è­å%Éó§œÍY©³s9Ëk•®'&=2‰#×S‘íZÛ¶½%‘Hét¦iz·\×Åôô4‰„×\ÐZ¾–\SL–’mo9Û5‹Áu]/¡$Ÿs9Þ® CœsÇÇýJx™Œ?3%žÇ¨øHDĬœ&)“'ª ŒâR–¯pTq])!D8Ií±`YL9°oùÊ`\ÉAvr¶ï·!{ñVºæ_9-Yz/‘ðÉo»pZ‰œ¬iâ…Ãþ9¸Ñù¯Vüj5šl>–v•ÈäwZM‹dI"%‚nz†aà©#Oá=¿GœkVÖRªÔ$+þllÛ~m>Ek¤È¨\¯øÐV(šøè{¶à5©”_«\./Kt¡p›\èÖD¡± ÑØ ^ËZï:M”Bo’\lVž åâ±ÁƱ¿fºT©Öz¹s¹ qEhr±jY3vppÉd‰DÂ[ÀZ>^^¼ÉŽ+ùØh4ê-Ú ø£}JgmF¡¶UFÓ­}äìmöFt™LYh‡ëº^ÄR'Sdç†\LVUUl}Ó›ðÏÿüÏÞ'2!èm‹.([ÝÁï²L2È?®[œYJ$Ä“¬¥¤ªÅ_ù£&²¾µ|ï`Ý ±Qs?èñq¿%Sºh¯|N ƒ«¬@ù“²êyZ£‚ÃáêY·Dþîw <²4_†Q’»Kú üªš\£ÐÀM~ þ¹LX|½t¤ª ì—¶q]1‹CUUo¦ FF"ï¼ ;)MÓÄõ/zô÷¼ÇëL”3ïø§Âç7oÆê|g¿ä%Þ[¦R)ÜúÙÏ¢ÿÄñøO~‚‡¿ÿ}\ù—‰ç=ïyXÿ¥/áE×]‡Ÿýö·¸âòËñ³ÉI\wÝuxÓ›Þ„¼îuXý_ÿ…¿øÅp, ‰ÓOÇÍO?Ha´ü×Ï<=ôΟžÆ ûöágû·˜Z·ªª"ŸÏãon½£ixä—¿DhíZ\uÕU8pà€ˆùþ~@QðàæÍ8÷ÚkqSáC¾æškpÙW¾‚™½{ñDo/Nø‹¿ÀqÎ=÷\|ãßÀƒSSØuòɸíå/ÇsÏ<ƒ=bÍ_üöîÝ‹~ðƒ¸å–[pøE/ÂýÑá­o}+Þö¶·á=ýýÈ?ðÿpÒI'¡ë¬.üáÝB½ì2hš†w½kéwÁ0ŒBâ)ø'ÄìÑä­I¤RA×…ÿø›8ùd³³6N~ã— ¿úÕ^Oÿ•…ÏùÄOD6›mö×¶cÈŸþ¦•öJ.jeÃ9•òÏuò„.§,ÉÞÜ`’¼0ÓX†¿ã8â§"“kYH$…§ø;纮7hÂ4Mo¶‰Ô¨rV²´æÄÄDÙõ,ËòÚ»òÿrZ¼°îžmÛˆF£Eå„ävË^Y"Ø0 o1jEQ¼6²œµ*gßÅ£äMÓôjT*á,[¦ë:¢Ñ(Âá°7k6\(‘öþ÷¿!j;r J2)Â1-ŒP³36¸& žœN‹üÛ x³6‘B¡Ô Äuk¬ðZQˆsxâ\/¯M@ÎÎ’ÿ–‚ÉT9`I~¯åÂïuFjuɤWÖðÛŸù þ¤ÙÛCÞŒ”`ŸÑR—ðj‰ÁDKLNP.%ÛUHA\xZ0=í'Ͽ繶3Ñ[ñ 9HN¶µd™ Y*¡æ“‡®~;ýö§Øûý_â5'÷ˆûäbºnáßð“'qˆ:Ášäaˆ²¥³EP¸}~E¾nP¹²Zj™×ª‘ƒMòbQŽXK¥RÞ…Ÿ\gÄuÝ¢±å… ü[Þ/§SuZÍæØiÛ0Ž#r µúãË‘¬rœ…Ž0 –ÆP‰DÂ*;D’É$vlÛ†÷ž|2ôõ뽸ˆÇãøÙK_ ¼ï}H‡Ãþ}ï"Ô¦²çÙ0Šé´_#¾ÜœîZIM«þá)J}®œÙÒÎT}·ßÞì­Xäâ×ÿ¸1 $ +š\ƒK4žïäéAÏ‘£¬eòDvžÈçrAè~:¢é4‰R©Âá°hdËz ¦‰¤ªgž‰‡N=g¿ä%°, o¿ÿ~tŽâ}LJ~ô#üïI'ÁøéO¡i ÃÀffðûO|¿ºê*üüç?ÇšDÆÇ±mÛ6Üûå/cõßü ~Q˜=yz!Ñsâ‰'âŒ×½/üàq¦á‚Bâò±/¹èC:]^!¨*^¡ªxEá.]–Mqüöµ¯Å'ƒ£O1_:f\/LÑéÐSò]×½Ž`@œ£ƒçøT*…ÙÙYŒãƒü î¹ç¯³Vž×åç¾ã†pê©§" áCúN>ùd|ûÛßö~gƒç|MÓŠgŠÊ’M´däi%X1kYÉ2‰<ÞÁĹ\ô§¤M(gŠÅb1ï¼-g!‹§¹Þ,O9ã"8ã ˜Û®,½¿ô¾à œÒ„ˆŒ9ÓCÓ4oˆü¿%iÛ6’ɤ÷þÁ¤D&“ñ¹r ·Òí,×N©” ‘e>Ë Ñ4mAH‚k½ÈmSU—_~ùb¾´Ì,KüÄ㋜¨›H·å ÉóPþbð²4tð+Fa.ø×­e¶%xm)èÉAr†Vp€ âBΕ÷­ÈuH4 ;®Ù[±¢Ér¨‘ˆøÿr.ÑiY^3’¨cÉ5ƒžøí°m[ ™´ýŠo-,EQüëÍÎên¤µb*r‘°x¼8XçÓ‰ûìµÃøÚ³OãÒûòxúúÝxùÅ=¢ôÖüQ·záQòd¹Ð«¤n ®q”/¿l¤Îƒ¼@´,Ë[s€7ƒD^ôK zÓ¤ƒ$òù²òüî„Dé½ÑQ`tàê:þó5¯ñ’¦ñpVáµÃá0º5 gbö‚Â6M ˆY1¯xEQÇ¥üûSŸú6oÞì e:ËÎ+¥ªøY$‚'žx¢!ÇEQd2oVOLB©ªŠ[n¹Å»]Î<•ÉÓ4ñÞ÷¾×;ªªbýúõ^çv,ó*²­ ÿ-Öu‰"68èЗöîÝ‹óÎ;¯!û¹ÒF“W1 8 иöÖ+PUXŽ§Ð LÜbíÙVÍThË6gðû,Û£†a ú –Ît]±X ét±XÌ›EL&½ò³r0Qp­¾`DÓ´9³`J•þ6ˆ¢¾ê‰æ+‘§yMÛ¦cµ’zJt•4¿å9EÎâ–3Ee ËÊ2Ùq3K¨­¹.°f¸6Çý1oå:|—Ciud¢N¤i¢@LxU}¾û ¢-\Gœ¨y%†d»­%K5RÇ[‘ Ó潎³\é3<ŽÝ»wcðg?DïKM\òú+·BtEáO–’#z‚ý(rúÒÛÊÍP™GDz¼h•#ä½Å-ƒkŽÈzñ¥å¸dã¶t’rV䨠2~rÕU~³7£#Èuiç3I&RäÐy_€™&nËfñT(Û¶±æ‰'0Qؘ$P4Í‹­p¯–´Yê9ßT›®ãì?ü¡Ù[ÑñPt~i "±¢@œàö³nÇÍ‘›½(מ{-î¹ÓK‚ÊŽ”\=þlß>àì³»îvïJ†¶Ói¼àÀüÍßü ^üÖ·â÷Ÿþ4¶oߎO<Æ¿ý›×YFË®µõ¢Âß2¦eçm¥sž<ßUš]m`¼oûÈGz|*\ÇãeoW¥h$|麥-ápØ{Œì(Ó4ÍKÆ…uަ§§‹JµìÞ½>ø`C÷u%2Í&ÍL‘ 2{q I6Ó4½"òü¬ªª—‰<Ù¹üŽÉ™UÁR>Á×3GÀ0 d2oYæS×uï;(g•¤Ói¯d—,Ã)¿çå’7•Ú¸¼`§f‘ùÊHÄ_*/­âqU²œôW î“¥RdÙj ¢”WE×¥òºS–äL¥RE‹¾Ëûd©99º88#,Ykæ5Q“ÈRšñ¸¸6Åüò^ÍÊ“¯ôSPp¬¬N-)ŠŸe‰Ëûƒ÷†_ [þ®Êòmr‰Qy»®‹×ÄmŽ#~wåsÅ_Ùuu뺛ýµ½D¢p¬yàð߯¿úwÄÔ˜¸Ætà%S Ã`¿$5ÍŠK¨TZਦ àÎ ]ÇYï½gžw«{1®¼øJ¿± ˆÎ¤AˆÛ‚'¼0ê+Ó5“¤\|ðËÈÑvòB4X~K&KJ;¤NŸIB­Í0De>çC9â-™LΫ“ã¹—¼{öìÁi§†½O=…K¾øEÜöØcˆF£"Ê•Ú âI»m|5‡›½.⃎‡8¯Ö=I¥RÐu7ÿàf¼â‡¯Àc¯| Ñ÷D½XDr8)fd;Pèlý³o|Ã{mÙA/ËìÉõä ŠÏÞz+à'?ù ÆÆÆøç8v|V·Ò›å:¾‚1Áv„ì<ïííõÄ®¡²x^©½:×ûk¤o¹ÏÞv¾¿\¬ŒOMÓ¼$c¹8”‰YRszzÚkÏÊ*ÁÙ+rÆH0Á"‚ªªbbb¢¨ÄWð7@.ÈNÔÎ,«p®-,iâºó,ùãþ×ó”ä¿Uÿäø„ Ü}ìÝ€;w¶Iô2ÊÄ©LšŽW©$Ï·Rn·tyÓRÁåá‚aÙßÿ²Ù}õLšÃuIK@8>€_¾ý—ØôÆ«€ks£jyX¢å²¢*ò¾fÛ϶"ÀÇÇ¿Öpøsá 'ÁåégñŠm…%dÏŒC…Ç—›í²€öNi© Ù•üŠËJiGúP;“#[êaÛ6"‘ˆ7 N‘‹à–•-´,'o¾ €+z{½Çkš…1C´`–$Þ$¯’?…×clÛÆ‘}ûDÂD'Šë#Î_n2)’'¦ ·0`À²,¯£&رZújóAHó³T­,ÝU: ]Q<õÔSøÎÅã@×uoM’ 6àì³Ï†aÞL2YÞ«ÜLÙŽ –Ìc‡!­D²ƒTTÐuÑ‘Y÷µk9 ˆkTeç•åðäcå¿eÙ<9ˆazzš‰“*d²#¸î‹¼Ž®Ëü[Q¤R)o 'ù;šN§‘H$¼µJãñ8111áýžÆb1ôõõ5{·;VpÆB r]ËPÕò×Ìò4Z©M¼½ôùb`„íí¿‹6¹iÚ^Y?ù» ë: ³ðÚþ‹kšæ}÷%¹&™¦‰j*r&ª¿mzÑZŠ2©(ãI>VÆS¹çß_>NÆ¥œá*Ÿ#o“¯ŒKù^²$©Üïà¿e?\¹Øß»w/Î:ë¬æ}AÚÜà`!‘`θƒAsÓ‘Þ4|4èÀW¿óUdÍlQ?)Q3¬¨„ŠœJX•à/, +ŒŸ%~†ð#xÇÆwàÚ›î£ßþ¢ð89zäâ™r´o¹ö‰¬ ]º– GàQ§I$ê_3%‘HÀ4Md2hrβë–…{¶múW¼Âkh%GÄÒßþ-ÆÇÇçÔL'¢…1 Àø>hCv|Žˆ©fñxš §iEWn®ë"‰ ‹Ñ–… ˜h4ê]Œ4r=j¾…”£úÈ©A®m$^7UUqÖYgáÓŸþ4xàìÙ³÷ß?6oÞŒGyg:„Ù3ÎÀ¥ºî_K1‘F+‰e‰ÎNYK_RU¿¹*KèÈþ®+ÚÀ²|Op„8PGÂT–?ÄlYº«PŽÚÕ\Ø–íu‚Êr{r¶ƒœE¨ªjÇÎ8‘ë.Éß#Ù¡*ËK ?'Ù1¬išw.:F"/ù‘L&½× ®£ëº—‘¯)¯ýãñ¸w=";gåïhiùšý…E_eÇáôô4¶lÙÒìµc™¦¿FF3Ã!Ø\€—(½]ÞgY–÷]În’¯%¿Û2iømµàûF"¯tf0â8"‘ˆ7k-˜ØƒKGÈu}åíòwGVƒ/Åjðÿòß¶mÃ0 ¤Óé9}c†axkµÉ|Ã0¼µÔйYv6µü¼JÛ2r›5M›ÓÆÇÓO?ݼ/N“¥Úˆsظ¨xŽFE·Â4ÍT*UU‘~“)Ô|+&¡"ë)VœV¨ˆðà 'àë¶gÌ·åFËɺ³ur§h‘>™ DçQi­i^„ÒJaYµg§¸®‹ÁÁAèºî5„žºðBÌ^v>Ûmg2ø·;n,ËB8ö.H˜@!jç€1Œ÷Ê¿P;Ãñ_ý*´~Ô·ÀyÓ+µW¸’ ÐËQ˜ŒQ¢*äÀQÙIjHŠXÔº!F¡Ö-òÖIÐÏŠÚ«rTºœ vdßü"÷ <ýôÓ˜ÅÀÀN:é$Äãq¤R)œ|òÉÞš%ïxÇ;Š:/.mögCÔ$2)""©”8íÉr<Á‘í²ÌMpy¾d²¸î?Pçl3"®SÛRÂÀý÷ߣ~{öíÛ‡ÿžùoÜ5{žŠ<å]ÇÊÖrÍìè•k1;“ƒm†T*…ññqÄb1ïw*˜äˆD"Èd2^»Ã) °êííE2™ô®Åe³ì(‡ÃEÏÁÙ%²ÓT®#¯1äÿ«Í¬“÷ɶŽü¹zÔ|Žãô[Ì„I™@“3ä¬ÍÒÄ„ŒE™è”³äwO–Êüî2PÚ~vÇKØÉs¼œé!ËÆÏ§œÜBFÿ'+\ÔËäM¹û+ ¼©Ô¦iZÅm ÆS0aZm–{¥÷/]û/x{¥ýäú€óç8€ñ9Àº ¼vnÊL‰c ëËûJ©ut|BŶÅHÓ¬°½Ñ05€»?}7>¦} ø óãÌ‚GéÈ‘/rDL0ó/G‘_©«ÇqJ¥ðªï~©ÓNC¾Ð! ©3ÏDòúë1üÙÏBQ\rÕUx‚%Z,×ìô µqÀv€Ø ~ 0ñ=ñ¸Û¿ùÌ~èCè[µ 'ÿèGˆ¿ä%Þk Ã0 D£Qo$à_&ë­óG´Ù[m÷]°º_ë`ѯ\‚Ô'ºá’ý÷#rË™÷ýXópŠîw´fmàÛ pÈ~£`ö™Óðì³ÏâȾ#Yû!¼ÿ—oÂÙÇý9þ¿?¾ [îy/.<áBüêȯpÁq ë5‡<}ÿ XežŒžít?t¡<ã_„Hâ@¢,ƒ¿Ôm´ð" .üÛ†?z>¸þ`2ðz(¼Ž´$Ÿ…h¯oÓá'ž$™d’‘ œé…mu Û¥BŒø >/øx©ôyå¶UÜ_n[KŸWé5jmkégRk[«|&WÜ~ž = šëé§OÀà HŠÈõMêiz–¶w‹ú/ÿÒõ95*ðÌÇžÁ/ÿæ—Øß_4XÏI‰ÎWåÚ[5¼^{=Þ£¾g~;&3AóhGË[Y}A&?äµop¶Gðo9ª=8ë#XŠG×uuÔQ˜žž†eYˆF£H&“^92Ù™,ÿ­(Š—ä3=JkëWšIW|L4o»Eá5{‡“‹¢kšø·ã”ï/**xß_ùý— ù½¶wƒ³#äl`I+Ù_T:3ɲ, bzzzÎ÷°Zû9˜P^WJÜÉRØK‰C*ǽ p”oão”Àgm<ÓýcÇqQ¸n´, ‰D‚‹ÐSKéÈ„Šãˆ‘Bñ¸?ul|¼BÇ­ ö‰Õú–'ÓH$‚h4ê5*ƒ<"òªsÁ¶ÅèŸHˆ_¯4AP*•‚a¸ñúëñÇßù6Ÿr ¢…crý"j Û€øå€¶0þsÌßüàkÍ¥H¾þ è_³À¾ù…/àßý.Ž¿þz¬I¥¼ZÅrª}&“ñÎÁs*;'ˆj{þ“ÏGì_×Â=ñОyúK…òŠnh Äu@Mý#Æ_q03LÒE¬ðU§œ‚ž~Ûûûñ˧âeúËð®ù¬>í(O>‰÷Òûù Ð¥vá2\&~þSŒœ]¥(@|¼°‚-€˜á¯hAñj¬•ú(ƒý=åúQÆáŸûãðÛ2‰"“/(ü»´i¼-PâÈ›ã–y^ék¨÷QJ/(y§ä}äó´À{ïGàÿnÉ>ÉÄŠVòÞÁm’Ï©¶­•>ùx·ä¶àóJ·µð˜'¾ûNÆÉ ¹~þóóÊÕÊçÁë=YŠ§ÞŽJEÇæS3xàÇ`vv–+F®;–ƒËN¸ ]û» ^Y›…$*M†üè½ïEß¡CøIaD}01"ËëÈu>äl9R^Η³`‚‰ ùoY6H–Ö‘£Åe{^vË‘çù|¾èv©´,ÛTIJàüÛ4ÌÇ®†³g4íYàÌõH}ÿ) _¤Þµ8ÀaOÉ/>Ûþå4<ñиïG£8ãøû°æ{OàèßzÀ¹çž õU¯ò¾k?ûöÏðµ·½ ë‚3Ná7@•õüJKrDòbÖ¶¡É[–_*âûýßßûÔÒ)o¥‹*Éá ¯·¨i5DËÈ~71€äÛø/] ·PUøêßã­7d‘þlÚëG@&“aÿµœ–K¨är9är9ôôô §§g^Ïu]q¾‘k2¨j…_€pøþÃØþÊí¸óÁ;F1­í”FÑhÔkLÊ5r 5ë…S§Zh|º7ÆÍ€rà<h«- LŸf_wOˆhÀ»Üû®{ñóŸÿS½S»d G>óuì Æµ¯ù &DGŸJµFh–>¦ÒMÞc1#AõÀcJGá–>¯ÝÞg¡£}ƒÛ-ܿѾò}dgUø·ì”(lëKz)VЅħû[`ð’Ç‘yùÿ‡|:ë@ÿ[ ìDl»ëô׈eP¢|A$² ®ë"cÝ¿þ«±gYÞy±´ãƒ3ƈæ›ÿ³ú0ñ?ë ݧy·{<Ói¯_Þ¶mX†o~ó›xôÑG±nÝ:ü~íZ|øÃÆÏþs¤?ùI¿œÇÍ7½OQ7dpÄŸ\‘þû!ž»8ÄbÉ~ŸJIµÂíµ[é1õü©5^#ZÇóÊ]h|l=ï3Ÿm­çy.Y~qù/B¨ŽkóÏÈóÿ‘¯ý50^ø g|: d YðUøa¡žôªÂkÜŸ™¤O½èxî¹çpdæV=¹ »ŽÁW?Þ+ûóú3ÏÄÆ»ïÆõ«VaõêÕèR ýŽâÓDOä#8¸v-NÚ·Ï<ó nyÇ;øå„^¹};Ö®]‹ûï¿]tþùÉ'ñʯÝ[äþo|—þò—xÓ¾}xò]ïÂs%³44MóF——Αçxyî¯5Òƒ i¾æŸÆÎDê¿/Côø Âëý¸ÿމ"ú¶Â@æS8üûÃ8räž8þ |óú}ø‹ŸÂ±/8ÙËŽÇ[þåÕ8YsÎ1Àþ?žàDÅõ§èyøf¸dÊcU…œ…!G•.Ì"§ÅïÄÐ%ë׋ڂÕ^#•ò<(ŠxßàùÜ4ý’ò½ä"1r;S%t¥‹9ÚúEJgÉ$Ÿ²¾að1²Nb0É”NxN$üûeRª´3opп_Ög ~î²Î¿ªú¯•Lÿn¦Rsº ¾†ÜÖ àgVïgÒáÓo °ö™;í*P€éi¸ëíD¯¿Þ+“ˆs “çÔŠZ*¡2::Š‘‘ô÷÷crrÃÃê빮 ^xqõ×ÏE¢΄è¼{³¬;|ø0þó…{sRÐBô«tL|«8‘òø'>{/»Ì›Ú)kG' d2oæ‰lT.Ç4I¢f[h|ºßxƒõ?Ÿ6†èöã‹,ï ÉÃ3‡1;:Œé/Oã›çlÆ‹^þ"\}ÅÕ8ùÔ“±î¡û€¿Jçbî¨Ìr#A+ÐD™Ç.l‹G¥Ÿ±Zë}Ê ­4:V ü_–Ñ—à}x~½#[ƒ÷—¾ö|Fû¢Ìóäñ+}¹€UòŠGÚÊõä¶Éã)??8xÜA¬ ÏØ¥6ÂÏûÔˆ‹Dy‡¢"}³è¬5M©”å† ‡Ã0 £¨´A¦âeD+Û‚Û¶úåšßøÆ7066EQ°víZ¼ï}ïÃ…^8§´°€vj¥ÇË¢±ø<||?ð¶’È~ˆÑî²øž(ðú(Ýs=ö{ì1üàŸÂú;×ãØÇâ}¿Ÿ¹à38åÔSpüÇã¸kŽÃé—îÇx¡Ó¶mÈåð€¢àÒK/Eæ¶Ûpå•Wâý÷wø?ÿ÷H¥RH&“øÊ]wA×uÿÔSX÷²—á—ÇW´Ø³¦i^'à+ ›úUçíë‰ÖãLá5×BâSyå‹0‘”sþªèv¹¾ˆeY°¶¡ö‰j"šöFÄ å·à"\T0öÆÊoâˆ$ýëŽ$ÄsLˆ$µÀVQ4U3‰2¥.×Äòyƒ×F:€ˆ h%¯QÈ' .ß' ¨…Çh…×é-…Ù0ð¬ 쇸ö/}Ÿýqà×ö@ôﮊ÷‘³=»`:*ö}Uáó-¼Oa¡sd4àgð‚ë)\\Ê÷ù |MNs'mà€ \®øÇ/ à{~¡ŠÏCÒÐ`{£{ÑéÓo 8ïAdþîA¨W]ãÝ츮Wñ'{eÞÃá0“ñÔºò-d`` Ï=÷äóù|~rr2Þyçå~øáªÏÙ¼ys~ÿ׿Ÿ×Žúe>}êgóù·Çóùé|>¿ßÌÓÛ¶åÿûÕ¯Î]rIþ¶“NÊÿë[ßšŸžžÎçóù|2™Ìß÷õ¯ç<ûlïÏ÷/¿Ê‡¾-Ÿ¼ê¿Ê>fbb"¿iÓ¦üºuëò\pAþ³Ÿýl~bb"¿ÿþç3™Lþýï~bb"‡óétšqJ‹vÏ=÷äoºé¦foÆ’[hÛ6hzz:ýõ×篸âŠ|WWWþ’K.Éßpà ù]»v5{÷¨C±m[^µß­‰‰‰|&“ÉÇãñ¼®ëyUUóº®çãñxþÃþp>•JåÇÉÇãñüþýûóñx¼è¼ÇóétÚû÷ôô´÷ØñññfTÔBض­ïs™žžÎ'“ɼ¦iyMÓ¼˜#Z*lÛV&ã3Þýý|üœï{·ïß¿?ŸÉdòªªæwíÚ•Ïd2Þy¨‘–¢mÛ23T²Ù,º»» ‰éå}}}èëëC6›­ší<ø£ßað«§"ºa5¢·¿€Õc[6î»ï>|÷»ßtwwãý(>ÿùÏ#½}»W® Ž… üìg^æó…MØÿ‘‘„B!oÿÛÙ–-[°k×®fo÷£Ÿ÷Ýw~mœ(=ˆï""6ï¼óNüú׿F&“Á _øB\|ñÅøÚ×¾ÖÒ¥:å»Àߙδøœšš‚ñ«÷"ùù3½õO,ËÂ7¾ñ ¼øÅ/ÆsÏ=‡oûÛØºu+TU…S¨©Þj3Q²Ù,²Ù,†‡‡›½)‹Ö)ßéN:&ø,Ò¶€»ï¾wÝu>÷¹ÏáÄOÄË^ö2¼æ5¯ÁÝwßÝìݪÏ9­§“ŽÉb-&>å9ó¾ûîý÷Þ‹_ÿú×xÉK^‚çž{ëׯG__Ÿ·è´ëºxÝë^Ó4½uAxªWe)­¥h#ó;Ýz:å˜4ÂBãÓq˜¦ ÓÓ ^ûÚ×bÛ¶mxík_ë­$˵Ë5\×õÚ¹–e!z%ñ‰„÷]×½Rzò½äëÉÇÄãq¤R©y=§ôïóÏ?·ÝvÞùÎwÍwÇ+ƒTî¹r¿Zé9oxÃð¯…Á­¶móy·?üaœuÖYÈçóUŸ³fÍüáhvø,©Åœ;íÐn˜O¾ ÿ}’wM¥Rxå+_‰×¼æ58餓ຮWfr9µú¹¤®¯Vâ9ì¨|°e×D;wîD6›-:[¶lA___Õ/Íùç_Ž3~ójLú%ìß¿«W¯F>ŸÇqLJç?ÿù8î¸ãÐÛÛ‹‡zçŸ>à¸ãŽköîαoß>œtÒI8ùäö_rÏž=X¿~}³7cYöcjj ‡Â>ð¼ùÍonö&/™…ÄçßýÝßá[ßÃã?ŽãŽ;ˆ§Ÿ~§Ÿ~:fggqþùçãüóÏoÉX,§S¾Ó+éwæÀسgŽ9‚{ï½·Ù›»¤Ÿ_|1~ûÛßâðáÃXµjžyæœ{î¹xâ‰'ðÇüÇxüñÇqÚi§µ|Œ8pÄÚµk›½)‹Ö)¿3õ“}ûöá±ÇÃyç‡[n¹¥Ù›¼dÚ¶½øâ‹qÿý÷ãœsÎAoo/N?ýôfïÊ‚¬¤sN»¨ç˜°m[9>¿õ­o!cïÞ½¸à‚ °oß>¼ô¥/ÅÞ½{±nÝ:üñ8î¸ã°zõêfï^M+é;Ý.êmÛ:t¿øÅ/š½¹Kj!ñù²—½ ÷ß?àÜsÏÅc=†³Ï>O>ù$4MƒmÛ8ï¼óðë_ÿë֭üïͰnÝ:<úè£8ûì³ñøããŒ3ÎÀï~÷;œvÚixüñDZzõj9rÄkË?ùä“ÞcñœcŽ9333X·n]ÑsŽ9‚Õ«W{môÒ¿Ÿ|òIïqZâ9÷Ýw.¼ð–ܶù<ç‘GÁqLJ£>ºâs}ôQ8p½½½Ø½{w³ChÉ,¦m{â/¿„ÇW}¹çþ'žx¢÷Û½~ýz9rgŸ}vÓö«ÕÏ%ípÍÛÊíŠ={öàñÇoxÛ¶ef¨ÌÌÌ̹­žÅxàÇ…}´Ù»@Ô±ŸŸþô§ñéOºÙ›NÔñŸ~!NÔ Ú¶e|-½…Äç›ßüæŽN2µŠ…Äçý×5{³‰:ÞâÛ¶·7{ˆæèfo€ÔÝÝ=ç¶\.×ìÍ""0>‰Z㓨516‰Z㓨u1>‰Zc“È×2 •¾¾¾9833SW¶“ˆ–㓨u1>‰Zc“¨u1>‰Z㓨516‰|-“P …B˜™™A6› ê÷ær9lܸ±Ù›F´â1>‰Z㓨516‰Z㓨u1>‰Zc“È×2k¨Àðð0¶mÛ†þþ~LNNbxx]]]ÍÞ,"㓨•1>‰Zc“¨u1>‰Z㓨516‰„£òù|¾Ù”ËåËåÐÓÓÃicD-†ñIÔºŸD­‰±IÔºŸD­‹ñIÔš›D-˜P!"""""""""""j5-³† Q«bB…ˆˆˆˆˆˆˆˆˆˆˆ¨&Tˆˆˆˆˆˆˆˆˆˆˆˆj8æ#ùÈGš½ •Ëå055èîînöæTÝF¹hS.—Cww7Ž?þøº÷£Ùû9;;‹ßÿþ÷óÞ¶Vܯrû²ØcÔìãÓŠÚå3é„c_)>˽oµö£Ò1jµýhíò™´û±_è¹³ÖýrîlÖ¾ÐâMMMá„Nhر^îï|¿ÙÙY¼à/hè¶.ǾÔs¾,·@l;#Z˜r± ´×±¯Ÿ­Þ¶­ç¼¿ølö~Qc,$>[éØ/æÜ¹Øýl„…Æg«ïÕ¶”í£Fkt»QfggaÛö’´ÛZ¾MÝrË-ùüæÍ›óù[n¹¥Ù›TÖ»ßýîüyçWôçž{î©{?Za?oºé¦üM7Ý4çöjÛÖªûUn_sŒZáø´švúL:áØ—ûN/6þš±o•~gª£VÜV×NŸI»û…œ;kÝß)çÎfî -ÎÃ?œhر^îïÁM7Ýä½ßÕW_¿á†¶­Ëµ/åâ±t¿ÞøÆ7ægffÚòÑ”‹Í|¾½Ž}µøl‡¶m¥óþbâ³ö‹o!ñÙJÇ~1çÎÅîg#÷a¾ñÙûEÕ-eû¨ÑÝÆn”ÉÉÉ%k;·»¶M¨¿h“““ùóÎ;/ÿðÃ7{³æØ¼yóœç|ö£™ûyË-·x&åN>Õ¶­Õö«Ú¾,æµË÷p9µÓgÒÎǾÚwz±ñ·œûVëw¦Ú1j¥ýhíô™´ë±_̹³ÖýrîlƾPcÈ ¢à±o—ïôÃ?\ôú333ùóÎ;/?99Ùm]ê}©r¿‚ûqõÕWç Ãh»cD W.6óùö9öµâ³•Û¶ÕΕ‹ÏfÿîPc,$>[åØ/öܹØý\¬ÅÄg+ïÕ¶Ôí£Fkt»Q‚ŸÙÌÌLþꫯÎßqÇumC§ÇA[®¡’ÍfÑÝÝP(èëëC__²Ùl³7­ì¶–›VVÏ~4{?ûûû144„¾¾¾ym{+îW­}YÈ1jöñiEíö™´ó±¯ô^lü-÷¾U‹ÍjǨÕö£´ÛgÒ®Ç~¡çÎZ÷wʹ³Ž-ÌÈÈúúúÐßßïÝÖNßéÙÙY~¹®®.ôôô`fffÑÛºûR)s¹B¡PÑí6l¨k¿ZíÑ”‹M ½Ž}µølõ¶mµsåbâ³ÙûE±øl¥c¿˜sçb÷³Ÿ­¾_TÛR¶­ÑmìFÉf³˜™™ÁÖ­[ˆø·, 6l¨¹ +!ž×ì Xˆ©©©9ñÝÝÝÈårÍÞ´"òäsã7"›Í¢«« ÃÃêk?š½Ÿò‡§\»jÛ6;;ÛrûUi_sŒjíçJÔìïì|´û±¯ô^ìïÊrÃj¿3ÕŽQ«íG;h§Ï¤ýBϵîoÆïÎRœ;빟ZÏÔÔÆÆÆ°{÷nlÛ¶­èövùN÷õõahh7ÜpB¡—”z­Þ¶­¡PÈÛ@ÄçØØ˜wñÛNLjæ¯RlÊûÚåØW‹Ï;w¶tÛ¶Úy1ñÙ ¿;´8 ÏV:ö‹9w.v?µýòuKU‹ÏVß/ªm)ÛG´mìFÉårèïïÇèè(ÆÆÆÐÕÕ…¡¡¡†´;A[ÎP‘Å J£$›IfD·nÝŠx;vìÀÈȈ—‘«µ­¼ŸÕ¶­ök1Ǩ•ö£U´ÓgÒ©Ç~±ñ×JûVíµÓ~´ŠvúL:õØ/fÛ[i¿:¹}CsÍÎÎbÛ¶mرcºººŠîk·ïtWW—·0iéE`'´mÇÆÆ°iÓ&„B!/ÁÙnLjêW-6ö;ö•â³SÚ¶óÏvÙ/*o1ñÙjÇ~¡çÎÅîçr*ÏNÙ/Ý>j”¥jc7J.—óf›lݺ===زe‹—YéqЖ •rÙåVÌrõõõa×®]^ö. aãÆ^‡C­ýhåý¬¶mí´_‹9F­´­¢>“N=ö‹¿VÚ·jǨö£U´ÓgÒ©Ç~1ÛÞJûÕÉíšË0 ôõõy%0fff055…©©©¶úNËÑu»wïÆðð0,ËÂää$vîܹèmmöwzvv[¶lÁÈȶoߎíÛ·×½m­tŒh~ªÅ&Ð^ǾZ|¶{Ûv¡ñÙêûEÕ-&>[éØ/æÜ¹Øý\•â³Ý÷‹„¥j5ÊRµ±©§§;vì@(ò*ŒŽŽÖ܆•m™Péëë›s fffZ.Û%3øAÁ¬c­ýhåý¬¶mí´_‹9F­´­¢>“N=ö‹¿VÚ·jǨö£U´ÓgÒ©Ç~1ÛÞJûÕÉí*ovv;wîÄÎ;‘ËåpÇwàŽ;îh«ït.—COOOÑw5 y#èÚ¹m»yófôôôÀ²¬¢òõl[+#š¿J± ´×±¯ŸíÞ¶]h|¶ú~Qm ÏV:ö‹9w.v?—C¥øl÷ý"a©ÚG´mìF …BsfÎtBŸYÃ,ÃÂ÷Kb`` Ï=÷äóù|~rr2?00Ÿ™™iöf¹å–[òW_}µ·]333ù«¯¾:Ë-·Ô½­°Ÿ›7oÎßtÓMsn¯¶m­º_¥û²ØcÔ Ç§Õ´ËgÒ)Ǿ\|.6þš±oåö£Ö1jÅýhuíò™t±_ȹ³Öýrîlæ¾ÐâmÞ¼Ù;vù|û|§ï¸ã޲ß[Ã0²­Ëµ/•âñž{î)úóð÷Ý1¢Å)Í|¾}Ž}­øl‡¶mµ¶ìBã³ö‹c¾ñÙ*Ç~±çÎÅîg#?ÿùÆg;ìU¶Ôí£¥ÐÈ6v#ÌÌÌäò“““ÞÿÛ±Ïl©´å¢ô0<<ŒmÛ¶¡¿¿“““.[›²™äâ¹›6mBOO&''144äÕì«g?Zy?«m[»ì×bQ«ìG+i—Ϥ“ýbã¯Uö­Ö1j—ýh%íò™tò±_̶·Ê~uzû†æ§]¾Ó6l@6›ÅÕW_þþ~är9ôõõy‹“.v[›õÎårÈårزeKÑí[·nÅððp[#j¼v9öµâ³]Û¶‹ÏVÝ/jŒv8ö‹=w.v?—R­øl×ý"a©ÛGË¡ÙÛ×ÕÕ…ááaoý¹Žf'ô™5ÂQù|>ßìX( ===-=mhjjÊ›ÚTn;kíG+ïgµmk§ýZÌ1j¥ýhíô™tê±_lüµÒ¾U;Fí´­¢>“N=ö‹ÙöVÚ¯NnßÐü´ÓwZ¾_ww7úúúº­­ün§cDÕNǾZ|vRÛv>ÛÖÎûEµµË±_̹s±ûÙLº_äk¥8kÕí[ʶs;kë„ ÑrhËE鉈ˆˆˆˆˆˆˆˆˆˆ–*DDDDDDDDDDDD50¡BDDDDDDDDDDDT*DDDDDDDDDDDD50¡BDDDDDDDDDDDT*DDDDDDDDDDDD50¡BDDDDDDDDDDDT*DDDDDDDDDDDD50¡BDDDDDDDDDDDT*DDDDDDDDDDDD50¡BDDDDDDDDDDDT*DDDDDDDDDDDD50¡BDDDDDDDDDDDT*DDDDDDDDDDDD50¡BDDDDDDDDDDDT*DDDDDDDDDDDD50¡BDDDDDDDDDDDT*DDDDDDDDDDDD50¡BDDDDDDDDDDDT*DDDDDDDDDDDD50¡BDDDDDDDDDDDT*DDDDDDDDDDDD50¡BDDDDDDDDDDDT*DDDDDDDDDDDD50¡BDDDDDDDDDDDT*DDDDDDDDDDDD50¡BDDDDDDDDDDDT*DDDDDDDDDDDD50¡BDDDDDDDDDDDT*DDDDDDDDDDDD50¡BDDDDDDDDDDDT*DDDDDDDDDDDD50¡BDDDDDDDDDDDT*DDDDDDDDDDDD50¡BDDDDDDDDDDDTÊL¨†˲š½Tàº.,Ë‚mÛ‹~-Çq`F³w‰ˆ±ÙÇ)ÓŒÏöÂxìlõÄ£ëºp§âó-˪x?-ÆjgXì¹³R¼2V›‹ñÙZyÝ ð\Úi¯­e¡ñZî|ÊëÐöŸì\í—+2¡bšfÛäàà wbþ»]Ù¶ÞÞ^¤R)D"Äb±E½žã80M³Ù»E Ô)±Yîÿ+E"‘ÀÀÀ@Ù˜f|¶—N‰Ç•‹µÔ©Tªl#×0 /ÎÚº!Ü :%VËý¥hĹ³\¼2V›¯Sâ³b³Ñ×Ï¥†ñÚ:¯•Χ¼m_ŒËÎÕîq¹"*í̲,¸®;çßí*‰ c||°,«­ŠV®Òxì„øœ/ÇqJ¥011áÅ´al8вë´sår3 ‘H©Tªìý‰D™LãããG,ãèZZž;ŒUZŒN;—.÷u'Ï¥´œ¯¼¥ÖÓiqIÅVDBÅ4Môöö⨣ŽB,+úËÌ÷š5kH$H$Š~pmÛF$ÁQG…ïG|pp†a`Íš5X³f Ã@"‘Àš5kÐÛÛ[”AÏc«I$Þß›7oöþ]Ï Â¶m ਣŽB$ñžSéöZ÷USïþÊ”x<PÓÓÓ‡ÃE¯<>r»ä±’¯YiD|Ü|ŸGË£ZlíŸÁؔ߳àÿ«YH .ulÖ+åâS?EQ¼¿UU­ØpSÆfó-&+Å"ÐÜxlÔ¹²Ú}­ó«àùRÓ4D£Qhš6çq–eAQèºî=VÓ´¶9ÖŽxî\ÞX­w—ûÜ)UŠWÆjsð\ÚšçÒZ×Á×â¹tå`?QgõÍç|Ê~¢ÖŸl͸¬'+²ÿ6ßᦧ§óòÉd2ŸÏçóñx< Çóû÷ïÏ+Š’Ïd2ùýû÷ç£Ñh@~||<ŸÏç½ûåsÇÇÇóŠ¢x¯Çóù|>ŸL&缇®ëÞ6Ìç±µ·/øïZŸÜOùžªªV¼½ÚsêÝÆzö7Nçu]÷þ‡ÃEû Fóû÷ïÏOLLäEÉçÇÇÇ‹î“ÇEÞ'_?æ5MËïß¿ß;~•žG˯Zlæóù¶‹ÏÒx¬'>ƒË›õÄJ¥øŒF£ùp8œO§Óùp8\ôùUŠOÆfó-&«Åb>?¿[Šx\ì¹²Ú}­©Tªêóª/%]×½m”’ÉäœãPîq´4xî\þX­w—ûÜYª4«ËçÒÖ=—ֺÅséÊÁ~¢Îë'Êçóϧì'jŒËÖËZq²ûo;>¡ÇóÑh´è6UUóñx|NCfÿþýE_òt:×4­è¹ÑhÔ jIèàÿK²ÞÇÖ²€L&“ùp8<çs©t{µçÔ»õì¯üå Rþ?xálÊ‹UH厳|ýh4šW¥èùÕžG˯Zlæóù¶‹Ï…t -$—#6뉕Jñ)OÞòïàs*Å'c³ùÕb1ŸŸ_Œ-E<.ö\Yí¾VŽÇT*UõyÕΗÁ×)ÝŸrÁãMK‹çÎåÕz÷w¹Ï¥J㕱ºüx.mÝsi­ëNùZ<—®ì'ê¼~"ùÜrçSöµÆeëÆe­8Y‰ý·_ò˶moÊŸ¤ª*1%08·ôqŽãÀ¶muÔQÞŸ–›bT×u½}–’ÉdÅÛ«=§ÑTUE&“®ëH&“ˆF£EŸqé1‘J§N+ŠâÕœ NÁ+æVíy´¼ªÅ&°2âs!1¸\±YO¬”“Ûn» ¦ibbbÉdÓÓÓ°m»¨vt¥ødl6×bâ±bQîc'Åc=Ï«v¾¬¤Üû0V—Ï«‹9wVÃX]~<—¶v|Öºîx.]IØOÔyýD†aT=Ÿ²Ÿ¨õ1.[;.kÅÉJë¿íø„J¹š¥AÕ†¬kš3y¼?KñÅ\n–eáСCeo¯T³¹Ñ‹(éº>'à*`©ÒãÜ.MÓN§ÇçÔ\¬öÛû‰Êkç~"ÇqªžOÙOÔú—åµB\KsMÚÎqÙñ UUa†÷ÁÛ¶íeÀÂápÑ—¬tq¡p8 Û¶½,™ëºèíí-Z °èº^ôX–…H$‚×¾öµeo—?D•îkÙ ~¾¦iÖÕtÇ;^òyrQ?¹ñxªªð«öe?Qëc\¶n\KsMÚÎqù¼foÀR‹F£°m½½½Þ¬l¨hš†p8Œ¨ª:'Û¥ª*âñ8½çêºÞÔ†ŽªªH$H§ÓEÿ®–É•Û,?Û¶‘L&+Þ^í9¤( ’É$ ëº÷ùF£Ñº>‡X,UU½‘ñx|Ϊ|}yÌ*=–_µØÚ/>K㱞ø\H .GlÊý™o¬\qÅØ·o_Ñ1Õ4­âód|®_¿ž±Ùd‹‰ÇV‹E¹M:WV»¯•ãq¾Ï ž/kK&“ˆD"EûÜè;•ÇsgçÅêBÏŒÕÖÃsiëÆçR\w–Ãølì'ê¼~"Ùá^î|Ê~¢öÀ¸lݸ”ûÓÈkÒvË£ ‹Çt<Û¶½š{²¡âº®7…Èu]躎£Ž: û÷ïŸSÓÖq(ŠR×Tî¥$·EÓ4oûƒûTÏg ªjQv¿Òíµîkô>ÕûùZ–…T*…ññqX–µäÏ£¥U.6ö‹Ï`lÊÚŽõÆçBbp)cs±±²\1M·˜xl•X nK#Ï•ÕîkÅx\긒ŸñR¶¨2ž;;'VK? Æjûã¹´õâ³tŸx.%‰ýDÓO´ÐçñZ´õ0.[/.—ûš´ârÅ$TÊqÈd2Ð4 ©T ¶mc||¼)ÛRmÁ$]×ËNmZèó–s-XËñó½o×ø\Ì60®WžV‰U`åK›qÞ—˳Õ^o9¯IÛ!.Wô """""""""""¢zÝì """""""""""juL¨ÕÀ„ Q L¨ÕÀ„ Q L¨ÕÀ„ Q Ïkö,ÖË^ö2\xá…ÍÞŒE{â‰'p 'à„Nhö¦,Ú¾}û°víÚfoƲíǾ}ûðÎw¾¯ý뛽É-å£ý(îºë.œsÎ9ÍÞ”Eë”ïôJüÙ³g¾÷½ï5{s[ÎÕW_?ú£?jöf,Ú¡C‡pèÐ!œrÊ)ÍÞ”Eë”ß™zÉpöÙg㦛njö&·œW½êUX¿~}³7cÑVâ9§ÕÕ{Lض-ï;ßù¾üå/wÄwa¥}§ÛÛ¶‹‰DpÒI'5{3mÛÖöíâµzÛ¶ÕÏ%íð»Ðêñ¾mÛeO¨är9är¹¢ÛúûûÑÕÕUtOOzzzj¾^>ŸÇ®]»–{7ndd¡P¡P¨Ù›²h[¶léˆcRï~ŒŒŒà´ÓNköæ.Z­Ø >¦žø<óÌ3ñ‚¼`E}ZÝJüÙ²eK³7µ!ŸO>ùdG|§³Ù,²Ù,†‡‡›½)‹Ö)¿3õù¸NŒÑàol=±[jýúõñ]X‰çœVWï1é”¶-P96KÅçi§†W½êU<ç´•ø;Ó)m[ ±ñyÒI'uÄwšmÛÖ³Û¶î·mõ¶m«ŸKÚáw¡Õã})Ú¶ËžPÁØØXÑm»víB(Âèè(FFFÐßßÉÉI chh¨êëuJc? ÕõCÔ6lØÐìMà~,@µØ0ïø|þóŸ3Ï<³Ù»Õò]àïLûjt|vʹ³§§§e¾óÕ)ßéN:&õÁèè(úûû‘ËåÐÕÕ…›o¾]]]5c·“ñœÓz:é˜Ô£ZlÊûWj|ò;Ýz:å˜Ô‹ñY^'µ£:å;ÝIǤ^î·mu­~.i‡ï`§Äû|,{Bevv¶â‰pdd;vì@(ÂÔÔ6mÚTó‹ÝÊSŠæ£Õƒc>ÚýÇ´Óö£^Õb˜|vRB¥S¾ üi_ŽÏN9wÖ;*ªtÊwº“ŽI=r¹vî܉ݻw£¯¯ ë:FGG±uëÖš±ÛÉ:iŸ;%>;é˜ÔR+6ÚçÖNÆïtëé”cRÆgeÔŽê”ït'“z5ºß¶ÕµúïL;|;%ÞçcÙ¥Ïf³e¿ÙlÝÝÝÞ¹¯¯}}}3eލÕUŠMy㓨yŸD­)—Ë! yB€¡533 zìÑÒ©›ã“¨YŸD­ý¶Dµ-kBevvpã7âüóÏÇK_úRŒŽŽ¦¦¦ælww÷œº}¥8À०Éf³Ø»wo³7cѪÅ&°ðøÜ»w/¦¦¦š½{´ÍÎÎ"›ÍâСCÍÞ”†ì ÐØøÙ¶¥f‘mÛ4{Sm)â“m[j¦NjÛ.e¿­|m¢å455µ$mÛeM¨È‘[·nÅ<€;v`ddÙl¶h4‚Tψ„ƒò¢“š¦S.:«Å&€ÇçÞ½{199ÙìÝ£hff¦c*KŸ¼è¤fÊår˜ššÂáÇ›½) 566æ•=ª»•°mKÍÔ)mÛ ÒØjŸ[+aÛ–šE¶m<ØìMi¨FÅ'Û¶ÔLÔ¶]Ê~ÛrÏ'Zj“““KÒ¶]Ö5TúúúŠF"„B!lܸћ6V*—ËM-gíÚµ^ÎÝ ò cdd¤Ù›±hÕb3 -8>/»ì²YK‘𝧧ÃÃÃ1Št)âó”SNṓšF– 蔤Áìì,¶mÛ†\.‡íÛ·•A¨»•°mKÍÔ)m[ rl O¶m©Y:©m 4>>Ù¶¥fꤶ-ûm©ÓÈn¶ì3TJ]]]DЖîàÌÌ ëf-ƒj± 0>‰š‰ñIÔÚ6oÞŒžžX–UÔÑS+v‰hiUŠM€ñIÔlŒO¢ÖÄ~[¢ú,kB%›ÍbÛ¶m^ݼ`­ÌP(äMcD³\.‡76û3"êxÕb㓨‰ŸD­ktt³³³Ø°a²Ù¬÷'—ËÕŒ]"Z:Õb¨}n%¢¥Ãø$j]ì·%ªÏ²–üÂÔÔ6mÚ„žžLNNbhhÈ›6=<<ŒmÛ¶¡¿¿“““æH¢eP+6Æ'Q³0>‰ZW.—C.—Ö-[Šnߺu«Wš¥ZìÑÒ¨›õœ[‰hi0>‰Zûm‰ê³¬ ؾ};¦¦¦¼iaÁQCCC…BÈårsî#¢¥U-6Æ'Q31>‰ZÓððp՚еb—ˆ–F­ØŸDÍÂø$jmì·%ªmÙ*ª.XÄ€$jžZ‹‰1>‰š‡ñIÔžjÅ.5㓨u1>‰š‡ý¶DÕ-ë*DDDDDDDDDDDDíˆ """""""""""¢˜P!"""""""""""ª """""""""""¢˜P!"""""""""""ª """""""""""¢˜P!"""""""""""ª """""""""""¢˜P!"""""""""""ª """""""""""¢˜P!"""""""""""ª """""""""""¢˜P!"""""""""""ªaÁ •ÙÙYd³YLMM5{ˆˆˆˆˆˆˆˆˆˆˆˆ–Ô‚*###xéK_Š-[¶`ddÙlº®3¹BDDDDDDDDDDDiÞ •±±1ŒŽŽb×®]صk  ahh›7oÆììl³÷‰ˆˆˆˆˆˆˆˆˆˆˆ¨¡æPÉf³B(*º}ëÖ­èééÁäädݯ5555'“ËåÍf‘ËåšýÙ­Xåb`|µÆ'Që‘ñ—Íf+ÞÇØ$Z~Õb3x?ã“hù1>‰Zûm‰ÊkÚ¢ô¹\›7o.JÀŒŽŽbÓ¦Mعs'6mÚ„ÑÑÑf>D+N¹ØŸD­€ñIÔzFFF¼ø»ñƱiÓ&IÔ<Õb`|5㓨õ±ß–¨²çÍ÷ ¡P7Üp6nÜXtûèè(r¹úûûëzo¼qÎm###رcB¡¦¦¦°iÓ&„B!ôôô4ûs"Z1ÊÅ&Àø$jŒO¢Ö’Ëå°sçNìÞ½}}}]×1::Š­[·26‰š¤VlôõõUœþ)8p æcˆ–J6›ÅÞ½{›½ S.6å~.$>÷îÝ‹©©©fï­@³³³Èf³8tèP³7¥aŸ‡â4mjš\.‡ûî»GŽiö¦4d_B¡×!ˆ¶òÌÌ Û¶Ô–:¥m[-6å~²mKíD¶m8ÐìMY´¥ˆO¶m©™:©m+-E¿-×ܦf˜ššZ’¶í‚J~ ò,lݺCCCÆüÇ`hh¨®C4s{iF³»»»æ ñàÁƒ¼è¤¦é”‹N rlÊûŸ{÷î׺JD";3;%¡ÒèøäE'5S.—ÃÔÔ>ÜìMY´P(„]»vyÿŸÅØØzzzض¥¶Ô)mÛj± °mKíG¶m<ØìMY´¥ˆO¶m©™:©m ,]¿­Lš-§ÉÉÉ%iÛλä×èè(zzz …êJ ÍÎÎbÛ¶mرcÇœ™,嫞)ck×®ÅððpÃ?¢z cdd¤Ù›±hÕbXx|^vÙeóþ j„žž wÄ(Ò¥ˆÏSN9…çNj9ª­Ó’cccñÚÈåÚlÛR«ë”¶mPillÛRû餶mP£â“m[j¦Nj۲ߖ:ÍÐÐÐ’$ÛçPÉårÅîÝ»çýf†a ¯¯Ï]133ƒ©©)tww£»»»ì{§ÑÒ¨›}}}ŒO¢&b|µ6yá™Ëå°}ûv±IÔ\•b`|5㓨5±ß–¨>óN¨D£QÌÎÎz£J•»-hvv;wî ïŽ;îÀÌÌ B¡FGG‹;33Ã…ˆ–I¥Ø”u1ŸDÍÃø$j]›7oFQùŒM¢&«›ã“¨ÙŸD­‹ý¶DµÍ;¡b†@2À‚xàŠÏ-âµeËlݺÕKÂÈ h(ÂÔÔr¹6nÜØìψ¨ãÕŠÍP(Äø$jÆ'QëÅìì,6lØPTæA–Çel5GµØd|5㓨u±ß–¨>óN¨ {655…™™¯ìÈb cÛ¶mèïïÇää$†‡‡ËÖ‹'¢åÇø$j]ŒO¢æÈårÈårزeKÑí[·nõÚÌŒM¢åW+6ž;‰š…ñIÔ¾›D¼*€Q022‚ÙÙYï¶žžìرc^‰•ÒéCCC…BÈårÞè"Z~å¦^3>‰Z㓨u•ÃØ$jŽZ± 0>‰š…ñIÔ>ØoKTÞ¼*Ùl###ÆÆÑÕÕ…\.‡;wbóæÍøéOº¨ b@µ.Æ'Qëb|µ&Æ&Qëb|µ.Æ'QkblGÏ÷ cccÂÐÐ7­«§§Û·oGwwwQ L"""""""""""¢N0ï„ÊÌÌLÅûX7ˆˆˆˆˆˆˆˆˆˆˆ:Ѽ*¡Pccc˜šš*º}tt¹\ýýýÍÞ'"""""""""""¢†š÷*CCC˜ššÂ¦M›Ð×ׇîînär9ÌÌÌ`xx˜³TˆˆˆˆˆˆˆˆˆˆˆÚ€ãˆ¿UÕ¿Í0Mñú¦ Äãþm®+þß³^¶Ý˜íZ¨y'T`ûöíB6›ÅÌÌ 6lØà-PODDDDDDDDDDD­Å4EB"™ôoK¥E)¾Í²DÂc!‰ Ç)N”˜¦x­ ËG¼¯ãø‰’p¸øµEü‘ééâÛ–Ó¼K~I}}}غu+†‡‡‹¨'""""""""""¢æq]‘, ²mFŠ$“ƒƒþó,Kü»·×\,671‰ÿß4‹Ÿˆ$‰i‰„xÀO¦Ø¶˜ “Hˆ¿åÿ¥ÁA±þ¶&“s·c9-h†J6›ÅØØ¶oßÀ_?%2±BDDDDDDDDDD´ŒL³xv‡m‹Äƒm‹Ùªê—Ú’b1‘¤ÈdDrĶÅëD£âqŠâ'3l[Ü.g­˜¦?ãEÓD"IJÄûÄbâ6¹ ª*+_OÓÄ{:ŽH¦ÈY*‰„xŒãø³d‚  DÂ/¹ ããâ±Ñèò|ÎóN¨LMMaË–-ònëééÁèè(²Ù,vïÞ½<[NDDDDDDDDDDDH$Š*Š"ªê'JÒi?!Ën©ªŸÈˆD] Žñ·œU‹ÇÈJðo9&.N®âõTUü­(¢\—L²¨*01áo³Lø¤Râ½E$gÆÇÅߊ"'½½âþtZl»e‰÷u]ñ>KiÞ •;î¸CCCÞì…B¸ùæ›±iÓ&d³Y„B¡¥Ýj""""""""""¢HÎêäl™Ü&SLSÌò‰9ÃDÎQ”â™%2q’N‹ä„LÒX–(Áåºâ1šæ'¯Ÿüä2\}õ³ }º*£££ÅƱaÃôôô ¯¯}}}ÍûtˆˆˆˆˆˆˆˆˆˆˆZ˜\@^.Ì.Éäe)/Ók˜Äb"Q¢ëâßšæ—íRUQª k‡ÈõR€â²`µ¶ðg²Ô- ÀDÙr^E.¥Æc5¶wppÉdZ ˋŠiTU…¦iPÓe¢Q¿4ØCý_¬Zu8§¤¢º^mhh7nD6›ÅÎ;‘ËåÐ×ׇ72©BDDDDDDDDDD+’L˜T’LФˆ,Ùˆ„‰ãˆ?º.îK¥ü…ÞýÒ_º¬Y#î &LE”üš¯zfÊ”Uo2E)ü]í±…h®æÂ0 ÄËìH"‘@ZfäË;Eã8p]–eyÏUº.žgY4MÃÀÀB ÜáòêNÏtuuaÆ ذa±ýèèè‚’+SSS˜™™Aww÷œçär9är9ôôô°„Ñ2«›ã“¨™ŸD­mvv333Eñ'ã2¨¿¿]]]ÍÞ\¢£\lŒO¢VÀø$jMì·?¹†‰dYbfÉô´˜Y’HøÉÁA1ƒÂuEBDÎ.±mq¿¢øe½LÓ_EÓJfŸTXø½^ NªÔZwEP’±m‰DÑháàÂ-¶¸¯T,C´°ˆŒã8°, Éd†a ‹aÿþýÞ¬Û¶a‰~øµâmy¦§§ ÇÁÂ'>ñ œ}öÙ ÿ ÊXð|—`rejj wÜqn¸áüÃ?üCÕÄÊ7Þˆl6‹žžär9„B!lß¾€(-622‚þþ~LNNbxxCCC Ýa"*¯ZlŒO¢fb|µ>£°Êäðð°wÛÈÈÆÆÆŠ·k×.„B!ED••‹M€ñIÔ ŸD­‡ý¶ó'KvÉ]€H„%²•œ•"g¬@o¯ø[ÎTDòÅu‹“%o\ïÂïe/Š"^ÞÂb&ª<Æ`A”üÒÓ4aYÂá0 Ãð*wß}7Ž?þxX–Uøl,èºÛ¶½R^²Ì—¢(@&“A>Ÿ/z»T*…h4Š»o¸/¼é…Ô1s áŒ3ÎXðñ-§!Äê]OE&^þã?þ]]]ÈårÐuCCCèëëÃÈÈvìØP(„©©)lÚ´ ¡PˆO¢%V+60>‰š„ñIÔÚFGG‘Íf166†­[·Ý7;;Ë ¢&©›ã“¨™ŸD­‰ý¶ cþl)¸.Цù Ue¼‚‰ù<Û..ßUW9¯Zë”XR˜“xYH™0›—³L4MÛT ×?‘e»d‚IJ,œÖ}Öýn7¥º YR?-‰ ™LB•d@¦0…'wl{ÿi/.U/õî‹F£˜]àÎVvô|œÍf1::êýjj [¶lÁ–-[022Róù¹\CCCÞ4Mp333Èf³èîîöN˜2I“Íf«¾æj>†h©d³YìÝ»·Ù›±hÕbSîçBâsïÞ½˜ššjöîÑ 4;;‹l6‹C‡5{Sm)âóСCÈf³sJ)-‡\.‡ûî»GŽiö¦4DQ‚3HŽî›¶m©™:¥m TM¹¯óO¶m©YdÛöÀÍÞ”†ht|²mKÍÔImÛ¥ì·]ŠNíV`Yb6J8,f˜¤RbÆI&#"–%n+LÂ@4:w­•tðŸ3/v±êxŒ‹¢DH%OïxGÎ:2ç}MÓ„išÞÌÃ{¹{C{ç,&/Ks¥R)\òÅK°ö¸µ^’dppº®ÏI¦ˆÏ(]\*¬Œžgzp饗ŠÌT៚šZ’¶mÝ3Tn¼ñFŒŽŽz£r¹6oÞŒþþ~ôõõall ¹\;vì¨ø²LØìì,&''‘ÍfÑ×ׇP(„;wÎ9avww×åE'GQ3är9LMMuLtyŽëîî.º]^4ʲ ]]]u•E`Û–š©SÚ¶@åØŸlÛR³È¶íÁƒ›½) ÑèødÛ–š©“Ú¶KÙoÛÓÓÓŸQ)ÃIU"ñ·ÌÈÛƒ¥¼Ê‘¥ÂæLQ!’%zǨu¼Vªðw²úÃVZ…Cgòʈ¹®‹ÁÁALLLÀq8ŽƒÑÑQ‰šý¶õ+,ÍòùâY&Š"Ê-8aRKbøj\ˆ…ä³T\×õ‚÷–eyë˜H†aÀu]±V‰œÙ&~õ†_k”g¨ªŠ·m{Nì?Ç{lÅ$xraÛj”-K¥RpÝòõÈ䬤RÀm¶x-9E¨P"¬ûhøG_÷*¥YÇl6‹þþþ¢ÛjMÝÅÎ;‹ß×ׇ\.çý433ÃéšDË Zl`|5㓨=ÉòAX怨1>‰Z㓨yØo[Ÿ1,.oÌ}œªŠdŠ·Žº¿´V#¨¨ºî‰\(fáOàvツ‡þïC°U±X̻϶moQyUU¡ª*VíX˲pÊþS ëzÑú(€XL¾ûÝb¦ˆVxßJÛhö¡ÊÒ(‰D†aÀ4Ͳ÷Çb1üÝ_þ¥È\=«Š™6š†ÁÁA ‹áŠÛoÇÉ<ÐÀ¾Î„JwwwÑh€±±1(šn9;;‹©©©²Ë ÑÑQ¯&¦|Žœº)ë‚¢ÌX.—ÃÆºÃDT^¥ØÀø$j2Æ'Qû‘%J‚±;66¶"/:‰Z 㓨u1>‰š‹ý¶Õó®+” ’%%‰M+Y€ÞA} Ä×)NT½ppI ˆD"Þ‚ðªZ¼°ÊwÞ ÍÐ0õº)$“IX–…T*…t:]\¢+!f¸œ~ýéÅ·—-|&¦?Ë¥¬ˆøË0 ¤R"ãdYÖ¬Y˲0>>ŽT*5'©’J¥ ( Þ´?zá ñ‡ú2¾{û'‘H$ ª*&&&ðÓï~/Èåpàüó÷Á£Î5T6lØÃ0pã7" Á0 „B!o”Àìì,FFFÐÓÓSu¾¡¡!ŒaÓ¦MèééÁää$6nÜèÕ¡ƶmÛÐßßÉÉI s$Ñ2¨›ã“¨YŸDíihhSSSE±;44ÄõˆZ㓨u1>‰š‡ý¶µ™¦H¤ÈŠY¶]HšÈ5Hj­S²H†aÀq(Š‚ŸÙˆƒƒq’}Òœ÷5 Ñh·ÝvÎyî\¦_ÍÖ/ÔëííE¸PË4M\û½kŸ'¸'Àu]˜¦ ]×ç$^±°¼· |¹ïµÂí*Ä:/&0ÅL“p8ÐÙcf¡9t]‡mÛÞ¬“½ßÙ‹{ß‹3ÿúLüô†Ÿbbb±X ƒƒƒ‡Ã^òI˲°ï û°ö‚µ°\ ápŠ¢àÇçŸcO>3/z)V?ð¤µwz‹Ù\÷ÙÏâÏÿüÏÑûä“ ý^Ô•PDö9 Öèïï/Z0¬Þתd¥$Q+ª›ã“¨™ŸDí©VìQó0>‰Z㓨yØo+X‰Ñ¨ŸPI&ý5Q¢ÑÀú( Äz!Õ _DÉ/YîÊ4Md2$“Iäs8ó¨3±ÎZDŬ MÓ ( Òé4ÇÁÇÞø1üý宇ºŠ¦iÂu]¨ªŠññq1ã(›ðq¶m#ã7oú NýÙ©P Ž¸OÎb‘k³|ký·pë­·â(ã(D£Q<;ü,”^Å›“H$ÐÛÛ‹÷ï?~xç;žöAo»-Ë*Zè^Ò4 þû£¸õÖ[aÂD4Ü}ùåP]gtaíó.ÆñýT×\s V¯^ÝÐïFÝ‹ÒWÒÕÕ5¯d Q«J¥DŲÄBôP˜„5kü²_D"Å­ãEÚylóc¸õº[aY"±Àˆã80MÓ+eeV¯^Ÿþô§^’F®S"Ëi©ªŠ/~ñ‹X¿~=fÏ…êøÙ’d2‰t:í'.‚kÔÖ[qƒƒƒH¥RˆD"x衇DrGD,ó¶q||W^y%®ûìu0 ÛœñÊ_YôÞøó÷ý9¾~ß×Ñÿö~œŸkœ(ŠâÍ<)¥i¾tç—ÐóŒHèÉ‘ªªpOO¬ÃñGnöf§,¥ºg¨är9ìܹ¹\]]]ˆF£1@DDDDDDDDDDC.>Ž#ÖN‘ÉÙ__4‰Â®ñ¢ÄBí5˜–‰‹{.ÆÇRƒªªEe²üí³ñ›—üù° ^ù®Ò™ç^{.ðêÂöÙkš”ñË_þÿúÿŠ7\ùüîK¿ƒ{šXGŶm$“I¯\×¥Ó—"–Šá‡ë~ˆ«v@Ó48ŽƒD"á¯b8 ˆF£°, /<÷…XuhUÑû)ŠÜàƒ¢œløI ëÐ躎ÁØ N9ålLnôn— øÍ_ý/Ä —â+Q¤î*[¶lA6›E__r¹6oÞŒ\.·äHDDDDDDDDDD´Ç/ó¥iÀø¸H²ªV!”ûÄì”Dµ!f¨T˜¥"“—\u ®¼øJŒ#N#‘Hxå²LÓDoo/4MCÏ3=¸ýöÛ±ûÞÝÐ4Í+÷U$À€HRT˜¸aY¾yÑ7qÜ5ÇáŽßßgÿäYŒCUÕ¢#º®cͪ'‡qß¡ûð¡ÙA×uÄãq†á•à‚@…W ì‰'ž˜“P™C0‘Œ©@Qœ2}ŠÜhQ-à¿^ü_xÁÝ/hÌ †ºf¨d³Yär9üô§?EWW—ølt£££ÞâôDDDDDDDDDDDíLÓü„Š\’#0AÑÒ™&õ.6opÓ6¡iZÑú#‘Hét§ýÏiÀ%Á÷Š=NÎDéO÷ãpþ0.Ü!.ÀÕ·Aýú£X‡uÞûÈä‹eY¸ö˜kqIü‘ì1ÄS‚ñ<0ˆäë¢H…Ãxùg_Ž+´+ Ø¿¿ÿ^òÆu]Lœ2¾3úæ,b_´À}"©RïçhšsÂË~þ2t=Ø5ßC½ uÏP …B^26lذ,HDDDDDDDDDD´TlÛ_%‘ÜzÖD ªc}” Ã0`š&.¾øb\{íµ˜˜˜€eY8ýôÓ‹¯‡Ã^BŲ,d2D£QýÒ£ñÛßþ\sÁœ÷N$ÞBöÐDbãðæÃÞ{¦R)o,ËÂùÄ&Pá•Þ’3T<_0õ`ÛˆÇã¸âo¯(Ú΢ÏÁ…Wì鞆j«À{Ýâ…g‚3zTˆ™-±:>¸'ñ:òf®ëâ¸GŽÃÞ×ìçA[˜E/JODDDDDDDDDDÔ§dQyˆEèåmÁ’_õx×ì»ð\×s5÷¿Ýÿ‹Ç¾ñ,Ë‚¦iøÊW¾‚gžyO?ý4î½÷^¸®‹Óo<Ý{¼ëº^)0ù·Lrœré)¸è¢‹Š’ òq¦i"‘HàÎ;ïÄc •JaÏ1{à8NÑ:+r!ûUo ”䪴ß?´|ÈdÄÿãΰ€ ·×œ @ñ·sÕ¡UXûƒµÀ)b1ñ!ÇbÀ3e2Võ$¥2üÚkð×P9þ©ãqúÞÓ‹>‹¥Â„ ­©”øˆäI,&›—‹ÑË2_õ°mWýä*ÜzÍ­U·óg;ñ÷Ïû{œrÊ)xË[Þ‚­[·bffüÇ ]×ñàƒ"N‹uO6J¥000ÇqJ¥üuJÀ,$YtxIÇq088ˆd2‰x<ŽÜù9¼öݯ…eYøþ»¾cö3gÛ32A"EQ~=˜÷%Á’Uí?¢b¶ˆQ¨VH¨È×ÿîÿ~O¯{¸N¬aˆûÙ@B¥·W„u52*In¸è©ÅlŽyõ1b=›%V×*099‰-[¶xÿ— ÒOMM=n×®]K¿ÕDDDDDDDDDDDódÛ¢¤—냃¢>™·ÇbeÖH©Â4MüÕÙûÿÙÀ&Ì™áñæ7¿?þ8^ÿØë1;;‹¡oáE'¼333øýïw¾óà'LœÂk¸âµ“É$¡išŸP ”årJÚ_%",*އñ¿gÿ/~õ¿ÂnùÔ¨ »9Òuš¦‰ŠÜç’/5ðI‡XH>‹ÄG£¢ XaazMÓð7?øV=¶ è0X8e0ð:ÓÓ"ÑrË  ©€•I—R ]š—° úÁÚàR\ºdß™ ºf¨tww£¿¿¿è¶žžôôô,ËF-F"!&Ud2bmódRü‘÷YV}å¾lÛöÖ*9cÛxâ‰'¼ÙŽã ‘H ··cccèïïÇáûã…/|!¾ùÌ7aš&âñ8ǦiÞz#rÝ“Ý÷îÆÝ7Üp8Œh4Šéééâ™$…÷QÕBr$À •`I/X@÷º¡( Ž\q4?ÙRuçäû¸b ¼Í(yœ.Þª*>Ô ËÂ{î¿¿=ê¨ÂÆ–<7Yòÿh¸iøLºú¶%Ë߬¸ –K]3Túúú¼™'¹\ÙlÖ›¡ÒÓÓƒ7-XODDDDDDDDDDÔJä:)²òT2ÐA¯ªõ—û2M†a âÄÇN„£:˜9uÝè†ëºPŸýìg‘N§qÝu×áŒKÏÀ×ïù:îûÖ}xۛ߆ µ Åì‚L&ƒX,†0ÂøÜ}ŸÃ§f>…øíñÊPX§Äu]@ÓmÛE¯,¿urÏÉP À©g¡ù¦)*É YŒ0æ–³ô9ÀGbxvõjÜû²—áí0‘’y€é2¯—R+KnwqÀ’I1³eÉ[Ú6þþÀßÏçk°(u—ü€‘‘ìܹ]]]ÞŒ•;wbddÑh[·nýÿÛ{÷0IªúàÿrYX™ÙB”›“ÅZ¹lfA¡¢ˆJ삃to‚a7¯Û­&º˜LìŽïÁÍí~™|5Sk²x{ÃvTd±K”AaŠ ìHL…e@…­‘;âüþ8uª«{zî—îžý~žgž™©®ª>§ª¾uÎù^­á‚ ‚ ‚ ‚ ‚ ‚0âÅæ‰ñŸ÷õMÿ\ºþˆeY‚N8€_~í—´žÚŠïûsÌ1ÜrË-¼ë]£ƒ­Ý[Éd3<ü¶‡¹êÒ«ðƒÊñº¸ú 93ü3j¦¶”Á#¦«"T’é$öî?£øoUõPDç°, —„™ @¡ª35Π¬OÙIŒ:Åðx‡rôÈ› (•¸È4¹Hï— Û£»\«Ö‰žÇP9ØGý^“Tõė»[w«”d‹¨2mƒJoo/Û·ogóæÍtwwGÛGGGÙ¾};½½½bTAAAAAêN(¼.?¢í3)<_û¼2ˆ„ƈ·Œ½…—z™B¡ÀM7Ýį~õ+º»»É†_xÙS—±ìÙeœ±ë pÀL›ä«"?LÓäñÛ/G™Ä#:âx€ fBavîÜÉõ¯\ÏÉÖÉ•ûÙT1rä0¢öG”ªÎŸð•!cªügÊXbÅÏeÔnx܈2AÐ y”áÄG}¿iªP"+¬ÏRÃcš&+ZVŒë/ÀÊGV²ì¸es¸Óã™V •ÁÁA¶nÝÊ 7ÜPaLhiiaãÆôôô`ÛötN'‚ ‚ ‚ ‚ ‚  Šã¨lQ ~ë”_sÁu]L3 •ü§œs ¯=ò_ýêWyíµ×ø›¿ù›È`’ÍfY¶,Tê'`¢¬[–e1ú£Quî"S’H$p‡ÍߨÌÊ×VN¹ÿg¯ø,:8E¦Ƨír€ÏÛ•Ñ)ã‹Òƒ2¾ÄS]ÔÆBD4eKÆ®Q:­~²Ù°V åkî Ò†L&9o×yáÍ¡â÷‘OÉKǼ4õÅœÓ2¨ô÷÷ÓÙÙI{{û„ûlܸ‘ÑÑQúûû終 ‚ ‚ ‚ ‚ ‚0S\·*àa®8ŽSQÜ}Ïž=œñÑ3xåéW8äCH$¤ÓéÚ›ŒO±ãîWîVçv :3WÅ9Â( ÝŽ–··0Uy” .¸e*ë­Ä±€£²•a<µŠÒƒ D雼Oª¡(#G&v¾É¨î‹CÙØb‡ç1êZ{(ƒO¸.õ}+™ÚÐ4S¦•òkdddZ'ëììœ÷ ‚ ‚ ‚ ‚ ‚ ÂlÈåT •ZµS&Â÷} ÃÀ0*ÓW¹®KŸ.¸bÁ†W6p37süëŽçÊ+¯äøÀÄ'5©]?eyæ‘gÔ÷UGtTtˆÈॠˡŒ qƒQµQ"Œü0«­JÕé·’€i̬Iz‚sÅéC‰¦ŠJÆÚž²án7(¦wb×ÕŒWTßõÀ;à ¼a™šiE¨´¶¶N˨2Ýè”ááaúûûkî¯?ž×Ž ‚05“Éfüs‘OAX|D>¡±­)"›‚P_&’Mù„z#ò)I³ëm3aDuí”BafEç®ýøµYšr‘ ê·X–Åy£aê* eD¨EÌ ‘$48Ä>¸Ðƒ/¦T-’¨pæÑgV›«ñecTDÅÔDAœIöIÄÚ9e£“Oeº1“ÊÔcAØ~m#ʇ?I Ÿò0óÍ´ *k×®epppRƒIoo/mmmSF©ôöörñųuëV>ó™ÏpñÅ3:: ÀöíÛ£Ï.¾øb¶oß>ï„™àû>¹\ŽL&ƒçyärå7Œçy¤R)^|ñÅz7s^˜L6AäSê‰È§ 4>¶m“=‘MA¨?µdD>¡ù„Æ£Ùõ¶ž§ ) R}e2ªžy2 ¥ÒÌÓ}½ù{oæ…ë^ˆþ·m›®®.V¯^M*•àŠ+®à¥—^¶mNøù §²²)6YÚ¯Ç e«PŽ)ÓxEXÀ7°ºÊF•¯Zð$¤RʺrÚžÓ&>.8S!SˈÇ:˜Ü ʨL±‰Šd ñ’¥2 '~ç4jÎÌÓJùÕÖÖÆÆÙ´iétšîînZZZåQ`Û6[·neË–-“žgxx˜­[·rÓM7EõX‰Û·ogãÆôöö²eË:;;äâ‹/¦³³“¶¶¶Å»"Â>CضM†A6[iöÍd28Ž…ÁA@¡ ’ê¢O†a`Û6çž{n½»3'¦’M@äSê„ȧ 46Û·o§¿¿Ÿ;vD2©Ù„ú1™l‚ȧ Ô‘OAhL–‚ÞÖó”ÝÀqÔß{öL°cþLb`q‡£Ž:Š7?ýfœÐ¡S€½ð $“Iººº¸æÓ×pÜ%DZçÆ=Êà1y$‡þ~‡rÄŠ:¹²ý. A ::`(€%aGžiñã ¤²•–£õIx—]]ʲ”„Ón8ÿôÿ³F»Ê“N+CEq'ú¬¯¯¾¾> ÃÀq²ÙldDq‡¾¾>6mÚTïîÌ™Édù¦ÿ§ÚǶ§w>AäS5kÖÐÝÝ]!£ ²)õf"Ù‘OA¨7"Ÿ‚И,½­ç©)…ÂÑ(>µÓ\Åp]—ÝWìæˆ]Gà8¶m³k×.öìÙÃ¥—^ ¨]oííåbíi*ÓQʼn§üªe pVãÅ" €3+«,…‚2T÷/—ƒ„N¬:µ˜iB>¯2?z|dªête!úå(•©ŠÈáþS“¬ð\S\²á~S3}æ‘iT@U~ðƒDÆ“îîn¶mÛ†ëºSS@­ß¶m[ôÿèè(;vì ­­ÁÁÁqÍÖÖÖ)sòíÚµ‹ 6,îUÏóp߯4ær9öÛo?<Ïò,òù<ét:*$µjÕ* …ù|žb±H2™Ä²,,ËÂ÷}‰Ùl–b±H©TbÆ |ï{ß«wwçÌd² ÌZ>¿÷½ïÑÛÛ[ïî s$T´iW×äûårjg‚ðNß/ïãy•)<㸮ÚÏó&ÿNßWûÖ2à ²aÞ~úéz_¾9³òùôÓO³aƆ Ñ–>Û·o§··—gžy¦ÞM™ÚÛÛéì줵µµb»Ìm…fd©ÌmabÙ™Û ͇žÛîÚµ«ÞM™æ[>en+Ô“¥4·]H½íààà¢ôÁ0 ïãêïI‹ÏŒ+Œ®­»ººp]×uùÄw>ÁÑ/é<ð@@eµI&“¤ÓUÖ•öªºh<” ¨k|¿l ‹m44Žûûµ ù¼2.Äëh’ÉÈÊtç‘wò©ÿÛG×~û©Ï´AÂu+/œ.?¦J½¥ ËO‡`ߣ··wAæ¶32¨´´´°víZzzzèéé‰,“ÃÃÃ3š\îØ±# ëîî®Yô~:!c+W®¬vaß&R©©TŠB¡@GGGy’Ëå‚ *·Â†A>Ÿ§T*Q*•°,«æ¹ãX–ŶmÛ8ÿüóëÝíy¥Z6YËçùçŸOOOO½»´äpœ©£@@9-ø“ RA  ]]ï§ †Q{×U©83:4¤ö­þ× ( µO6[ÙÛVçp]õ·a¨q>Æ÷5“U«ÊûÇs¤jÚÛÛÙ¶mGydýnÔ0_òyä‘G²mÛ¶è‚°˜twwÓÓÓÃGQï¦,(2·š‘¥8·­…Ìm…fCÏmW®\Yï¦,82·š¥:·o½m­ˆ´ùƶ•- øúÊz)U…áujÿl6K&“!ŸÏóä“OrÍþ×pìîc¸çž{H¥R‘¶YëKLj×©ÞæQ6–d2aôˆÕŽ¥Õ…é“I¸²’«TÔäóJ™¢kŸLUò“ßÿ w·^ÄñöýjÝjƒŠ d(@¦Š>™.I¦U’ŸfBOOÏ‚Ìm§UCe:è<{SM0GGGÙ´iÃÃÃlÞ¼92ÈÔòL^šy¢_\v˜?Èu]LÓ¤XTæÐ èèèÀ4M\×¥T*Q(ð<¯æKÏœäm;Ñ1K…‰dD> ßWcŸaLü¹ÎêºV#—Sû˜¦:WµÃ„NË¥ ÚB?ÞÚˆ‘J…Þ}j\µ¯iª‰ŠŽDÉf+ÇÛ\Nïž§Úé8ê{ªÛ›Ë©Ö\8H&ÕyâçJ$ʧ™ŒúmY•ç²mµO>_ÙGce치zƒIDATóg.4"Ÿ‚Ð|ˆl Bã"ò)‹È§ Ô—fÖÛº®Ò=X£ÐwÍ4Ð5LÒúx¥74 ƒ¡¡!lÛæ°ÃãÁw>Èç?ôyÒÙ4§žz*Ùl¶¦#v„6hÔ25ö³€Riê¶êóe³pGZ‰­F9j×( s°/?y9§ýèÓ,ÿm'üUê: ?&Ji–fþê”L³$Ìb§òš.3ŽP™+ëׯ§­­ ×u+BíííãÂÄFFFª°‘P_\×%—Ëá8©TŠ®®.<ÏÃ÷} …¾ï“L&ÉÇ´ª†aÐ×ׇëºQ- Jß5]ô¾KÙ 2‘l‚Èç|à8“G‹èº"«VÕþܶU$I¨qÖu'>(CE±¨ŒÕŸwt¨h‘lVM6‰²%—SŸ†:¾T*ÏÙ¬êG.§ŽÑŸW‹’iª~8Ž2€”Jã:¦©ŽÓ¢b±2M§Æ²Ô÷…f$ãÏ•N—L]]åkåM•ß³‰ù„æCdS‘OAh\D>¡¾4³ÞVëÈ‚õÚ4°ˆ"/ÜPÉÏf---|íO¿ÆžìÇáÑGœºË_Leä†6”LôΫPµOµ±!QcŸïeaÇÅZÒ(ãK-ˆï+…pÝêëþ£up¯3¹áBŸÏfê:*ûó¡2¶oßÎèè(k×®­(ZÔÖÖFgggT䨳³“ÁÁA†‡‡Y·n]½¯‘Pg|ß'2™ étš\.G±XĶmºººH§Óã )q‰D…ñD¡ÊL&›"Ÿ“£ÓMMfŸó}]1‘ÃA&£ ù|mçÇQŸÇÕÆ‡\®™…\Ný¯ÓY–ú_‡Â‚ú­ )ɤ2ÆL)ãûÊ€1™mQG™NeÔõЊä×Ìår¸®ËÐÐÀ”÷¡TR÷!V÷¤XT×í±ÇNŸÅ]m,D>¡9Ù„ÆEäS‘OA¨KFo[`êȆeñUª¯\.G2¦hÑzÃCþôh?Ó4%›ÍN~î$µS~U·ÉŠ>ŒT„~8UûVl \н–*ÔD¥Ê Péº*>3#eзö~‹®}¬\‘_à¾eP™¯”_M΢T†‡‡WhsãÆQM–M›6±fÍvîÜIOO---õ¾FÂ"]]]äóy ÈBçlÛ¦P(`FT^¿¸tĉïû3ŠÑû3ÈoÓRd*ÙöIùìèPÆ…‰ð<•«8IÁ-ÛVãU±8¾Î‡ŽJ#ˆŽìp]elI$ƧËÒ©°\W%òùÊsh|_µ±¯OSôc_+bDR&Â4'N3g&¢R-º¾ïG©ûôf:2®?ö<›|>]ßû·ßŸ~c‘OAh^D6¡qù„ÆEäSêC³ëm+|§=&¯½aÀSg=ÅÑ_;šB¡ÀÀÀ@…ž0ÒCx¨ ,[);Æé'|”Á!QµÍc¼a¤ÛÇ‚¡Xckù€[T¦ý‚ÉʘR­'2Må‘Ö™¶,+2MŠŽPYºªÑ1-ƒJ…e²£££SžG ßDtwwÓÙÙÉððpäy+,mlÛÆ÷ý(u—6¬‹E‚ À¶íq/µ8–eQ((M•kp‚cg²ïLR„5SÉ&ì[òiÛS×àˆSr¹ñÑ'ÚaYÊø¡ëŸÄ£®®ñ%¦Y.´©FoŸÈ¢_S¬é4 A.´0A@6›Åu]\×%=A=ÏÃó¼(zÍq\× ÉqÄ®zwiΈ| BsP«¼È¦ ÔŸZ² "ŸBó`Û*Ú|2'®fEäS‹fÖÛz^Lwb1e!óŸþïŸòÀ eYzG­gÈçóʈ3iF5+0o,1(×GÑ8DõZ*~è42ú|3)Ðî¡"Yj¨L-Ë*—F¨Õþj̰ ¥Â4 *ÃÃà N¹_u^÷ÙÐh), ºŠiš¤ÓiÒé4žçaÛ6‰D'¬v],'$™MM“ÙFòùéVLZºì+ò©SlÁÄûärå%ÕûéÈ’|¾œšË4£4•QTJ­è]ð=ž<ÒC×?™J £vm’™®ëV„ÀÎäØŽŽŽ £ADÆd2I_, Æ0 …BdPñ<Çq"¬žÌh#ÊÀÀ@dTq‡NøOàò¹_€&`_‘OAh6D6¡qùêAu„ºï«õƒiªù¿ëªù»vÐJ$”óVWœzêëÝüECäS“F•Í ˆéG&4$€Ò+üüç?ç®Cîâзé s¹¶mÓ××WÖ}XåsNäè‰Áx#ÃD5L*æAŸ†nÓ¢œækºLRËe6ºòLmxÙG˜–A¥»»›îîîz·UhB|ßÇqœÈP¢StyžG±X¬ˆñ}¿faùÉÐÇÏÔH²”£M„¹£20>ºÃ¶•Á¥¯o|=“ P†”l¶²Þ‰Æó”Q%&Ž*1Mسgê6NTãd¡èêê û:³AWKª 2::-N“J¥H&“ì©Ñq˲ð}Û¶Éår†A>Ÿ'™LFòßÕÕ…ïû „ªt:išQQ9AAAh\W­ £ì¤åyjaYåô¿©”ZWèéw6 ÿ÷ç×»ù‚  ‰~‡ª~ˆ]{?ÏóÈd2lþÛÍüæ[¿áðÃ9ßTïV­gÐúK l@ÐÆ‰ZêDý]q=n«Pªõ@ú…ï Rn%cßUÖÿø”kªLeܘ¨–ËlUjÄ´ *£££ ÓÞÞ^ïö MBºì¯Zµ Ó4)•JAy”›¦9.å–VœÎ´VÉl¬ª³I&,}|¿\ód` ì=V½.º®Ñ*]]“G–X–ú|1 !sÁó¼Hnµ|A0eý!m1 Ïó0M“|>O{3M“®®.²ÙìÄž¨è0×u)•J5߉D"zçh´ñvùòåõ¾Œ‚ ‚ Â>Šëª¹¿ŽV¯N¥[šN”Œ0+¦eP±m›ÁÁÁŠü–½½½tww7d˜—°8A@&“¡Kæªëž¸®K6›ŠÉO'5—VÒΤXó<‡qØÄÎÝZÍ‘`òÂíÖÛ¦c„IaŠxß÷yúé§ë}9AaQ°m5ŸÉfÇÏIººÔ¼§z{<©ã¨ùγϞÂ<”Æ„¦&—›8E¯Æu•Ó÷•|årê·e©u„i–×Ó-ÇišåˆxAaj\W¬#ýŽAÙ¸3:ض9~kŽ?þxh/{ë“è#õ&aßÅ÷•¥œ$¼û2ÏS/ôÓøß@¾Êò¡S}iâé¼âÿO„M¹H¼PfmPöMt (¯ñ¾¾>\×Òù¾O6›%—Ëͪ~Á@-÷A˜G||}]²Öã§k„M¶¨²¬É#S¦þ´"¿ªÑâÇ…±ŽãP("ƒhu-£d2I.—«¨§¥RiZF’Å6–š¦ÉoûÛEýNAA˜\Wýè¡8•R¿õœC©¾¯"h‹EeÑs™\NÍa,KLŠEu]ôZ×mðý²cH¡  .ßùÎËÀëë} aÑÑòP((™0Œñµm[íêDzÊz³|¾Òak¶S_Ó_‹QA¨çUéjtx—ŠˆÇqjë-XùÚJ–'–O­c ­þÐŰ.ñá>|(t(÷}åÍbYð¾Q„ËbJ£\n|˜b¾ÜžI£JÒ(ÃŽTêŠT„q \×<Ê5žçaÛ6Éd²Âª[«†‰eYxž$êTªÒSÌóÔX6Q LF)'*<ª˜EŸ9aÛ6Žã̪P¡Pˆ¢ÈtHkGG¾ï“H$(‹“N"Òé4†aLZó¤Q(•Jlذ¡ÞÍAö! 5_H¥Ô’‡^&Q*Â>…ç)ù0Mõw6[Ž`×2/xlJaéD© ‚ 4®[®iáSN³ε´þ£Â4Mdxæ™g0*=ˆÎ#VŒ£kœÄ *Å"œÕŸ•#H&ËŠ¢o{ð³pûåäœÚ¹ E¹îÉDFUK¥ èczi¿„ygÿz7@hŸŸÒ]£„FÁq”‚Aç,‚r˜~:]Û bY06¦~g³“Üq|ߟtÏópÂÄÍžçÑÕÕNÒé4®ëFÛ,ËbÏž=SS€) È ‚ B3¡ÓE×Mƒñ xÇQ X]WMG¹êýr¹r”H&S6‚¤RåBÔ¶]ö€×F½ÏçËÑ)‰„úž|^ÍQ‚ ¬ÔÕi†tÚ!}|"¡ 3Ù¬ÚŸªkc Àùçßɉ'>Wï[# N.‡^^xž’¿b±\8^×4ñ}%;ù|ùGA¨/“¥f×Oq]w|ðáé/~‘Ùr•Ÿ[–š°¥bÛ^q௠ã÷Û´N›À÷B n ¿ûÿ„zœ‰¼rMT:¯©0(×vê´#T†‡‡éíí­Ø¶cÇúûû+¶õôôÔ»OÂ,p]Ïó¢—ŒaäóylÛŽ³¦iÎX‘j-v$A¨^ÅS}¥RåT‹a2ÇÁ¶m|߯¦ ‚€L&4s¹¦i’Íf£”[ŽãÉd¢h“d3\AAX …ÚNÕµÕt* &T§ÍÒEàõPZ,*ÃJ"¡~Ûv9rÄ4Ë‘":­e)ã‹ö|O§ÕÚ½T*;=jt1k¨tÑÆ• ({ÍëùÎDžó†Qy>AØÑ)» …r´––i!W'A„ÆÂójÏãvïÞÍQæQ*Ò¢´æ¸ð g²çñûY}j'lª²”§Ój€8:¬âyðr°ÈUåƒL0y¤ˆ.hÿDò“ (YÊÅé'Ã@¢SêÌ´ *mmm´µµ188mëììdxx¸Þífˆ.$¯½ÐljŒ%¦iVDŸ†A6›Åu]2™Œ(]…¦Åq”b"ŽÎ'Þ Š]$¾X,FFÊL&ƒëº$‰ÈˆAŒKËWubš&AŒ+È&‚ K ] ¡V4ªNmíºJê8J™ª"ú·6¢$“êÿ|^Í#tîTJm×ÊW=ì&“•›¾¾²¢6n„1Œò>ú˜Zó“‰üštý½Ó©½ 5„¥N(YÒFL²+®OÓÑ^eÙ@A„æ!>ÿ‰óÕ¯~•ì Yðá“ë?Y‘ò\óÂ/à›}¼|ìËêå¿ ¨.5›NC1”Ô>·—àþøô%>“×3É£"b¦Šn4PFŸ©m]™–A¥»»›îîîz·U˜#AJ¥H$xžyº§ÓéI#O´Âv¦°k½°a±©™S¥ÔhtcŠçy |ß'›ÍVÈ“iš¸®‹ïûضM:Ž>ŸJî,Ë¢¯¯OŒ)‚ Â’Â÷UDˆvÔs€tºœFK§¹ÒÅÚ µÍu•¢Õ¶+‹»g2eEk*¥ ÕÃl>_®‡¢Ï åz)q#ŠF+r«‰×e˜ CC3Ûß0Ê}„¥H*¥dÑq”Üêô~«V©ßº–P29¾˜¼ ‚ИèúozW+ýâý¯»›¤ŸäwÇýŽ—x™¡¥;vðÌÅϾ0Ô‡Z¨ˆ–øokkï&„†Áó<2™ ÙlÛ¶1 ƒ={öLûøD"1#ãˆeY$ô—êôA ~jW5z\.‡ëºd³YLÓ'étšŽŽ ௯oÆÆK©ƒ"‚ 4™Œ24ø¾R”VGœxžRœêˆme8ÐEàum‘U«”‘Ä0”¢U×ñýòbÝ4U„«Náeµ½ MsâyÅL  Š]A¨ÆóÊ)óª·ëÔy:òĶ•¬ëètzÏóʵQL³™’ÎK¡YÐ5­,«ìS=oýÑ(iÒø¾Ï}¯»ù¡qçñ}ŸD %ÝRÞ8QôHuyh‹J£ËtÉ¢¢TD³$˜¶Aå3Ÿù ·Þzk…®³³“Í›7³}ûvvìØÁ–-[êÝ¡¶mGìétÛ¶g¬|-Æ8Oñ|êã”A Ryd³Í¥˜‚€B¡€çy Lâ:ªëY–5ãè1AAh&|¿œvK†ö<5ÎkÃG¼îˆm—ÓkutÔVš–JåH’xDH¼Þ T¦ãÒÆAªËq”qT×eÚXšÉ”#Qâ©~“ÉJÙ×ïƒfZ‚ å÷¿a¨±a¢t_ÿõ_ÿÅI'„ëºÜó³{ø+þªâs¿Pààë®ã¥Cþ™Ö•?0 D9}—7AcÒ¨(•©RxU#,¦ePdûöíÜtÓM´··W|ÖÖÖFOO­­­\yå•ÜtÓMõîÓ>‹®Ÿ ë# ª’‘뺋ÅHéšH$­Š(z…Å$V‹-({“6¢ÇYQÚ=-Ÿºà¼ëº$“IJÕE_j uA„¥„^(ë gÏS mDéêRæºx´ëªñ^×7Ñ‘"ñöDé³&2ŒÆÄŠV]L^„…EGœé¹½NÍ¥£Ç CP´ÏŸ®=dYeÃê’!@y4˜°ü•åõn‘ B]Ð:™R*Õž³ýü7?笳ÎÂ÷}F_7Êëx]”’ëÎÏ|†•_þ2÷_vì\7þà`SNÍ5QâõnÎ2yí”jĨ²d˜–AåÖ[o¥³³sœ1%ÎÆ±m›ÁÁÁI÷Û¶#J2™Œ”²†aP*•*"Fòù™˜Pç†T„Å"“){ªd#«•çyA@bšnnžç‘J¥"cˆiš¬Zµ ˲H§Ó$“I©=$‚ ìär•i:A-–ƒ@¥ÊÊåÔÿñbîz¸Õ V](>^ེVÉ|!ÓZAX8‚@ɼi–(©”’a¦««K)Ñj-g³ÓÉK¿¨2@±j›VÔÙ”•p9”rÎCy;[(EA¥2χó<¿Þ=A¨ ÚqÆuÕß¶]{ž÷øÏ§û¢n~èý°¬§qÁ1NrVþË¿°2‘€®_’D½Ÿ5ÊÈR‹,êm  %Kɘ/LÉŒj¨Äéîîftt´b[[[###õîÓ>‡ëºØ¶¥* äóùi+x¡ÙÑ…fMS-¦tÚ…¶KA@*•²¬Iå-w1 Û¶)‹‘ÑDG•IMAa©£ó^{^Ù]C|¿¼(ÖQ%ÙlY‘ åš'ÕHÀ¦ 4'APž·C9Ý^6[[®§À½øÔ*Dì£r>ÊHR@IÜp[ehI¡RËQŠ8m@qÃs&§ sžv81ª‚°o¡ 톡Œï¥RmGÏóHžúô„2|‰€“ׯ/O8kùšëwµÆ`âz)i”á*±m› p]—¾¾¾( e1#P&C¼ì›“‰dS>}_…øÇËØv9ÀBáy^ æèn@É0Ÿìëò¹è]ÕËB]ëÐ0Ô;B§ñkh<ÊJ5¥ds(çÐ7(Lÿ/¡Œ&åô1ñHšãuÚÓyGäSêO#émuzW(§y­…ã8\zÌ¥•-p-ß÷+Cs¨÷p5q•ªz·O4F(#¹‡Sö1¦ePY»v-½½½ìرƒµk×ÖÜǶmZZZèììœÖÛa^žžžžhÛöíÛéííeÍš5ìܹ“žžº»»ë}×u) †a i¼ÂôÍI-Ù„Æ•O.D?nñâ± …ŽLñ}Ÿ¡¡¡¨ŠNqçy¶mãy^”vOæƒf“OAØ×Ñóç8Û¶m›ö|¹™ñ<•®'^ïÄóÔ˜mšeLJj%j>_öV„…d_–ÏÅD×BŠêÝÐPiºjEšh”²Žq€>”2®þŸDG´qE_T÷·ñ–ð ƒÈ§ ÔŸFÒÛºn9‚y"rß÷q‡|2_ñ>÷<ÿý@ò¦é|n¡ÒMG“G²O ïô}ŒiTÚÚÚØ¸q#›6mbãÆtwwGVH]°~ûöílÙ²eÊsmß¾þþ~vìØÁÆ+>ëííeË–-tvv288ÈÅ_Lgg§xÚB¤˜ÕŠZß÷)‹ø¾ßІ‹Fn›PÉd² )ŸA bñEÚbx¯ ’É$‰DÓ4±, Ïó0M“B¡€mÛôõõ•CLaŽ4£| ‚ <û–ª(T„¨ã¨…­ç•Óv¹n9¿µþ\ÿ=§™> ‹ÁR–ÏFA×;ÑÆUË‚ŽŽrñø†ÁE)Ï(%\¼q!ü=@92E§uÙî'^ÉóŽÈ§ ÔFÓÛêˆç©Ðå¨0nø¾ÏÊ?]©ÞõñyèDö3ü±QÆò©¾»„C´a]Ø'˜v •žžZ[[±m›­[·V|ÖÖÖ6íÁnÍš5´µµ ßìïï§µµ5:G{{;íííô÷÷ïÓ^¶ÚÂê8Aè®W*•"OøFŒLÑ4jäŒP›‰dW>s9µ [ÌÇÌu]Ç©HÝ•L&I¥Rär9’É临^‚0WšQ>APò¹yóæz7c^ Ë‚EFRI)HÓé²±¤¯O-~ƒ ²6BCy£ û Ï+’ÏfË‘*CCêýШèP‘&.åÈeXÉSV¦MC¡'Ì"Ÿ‚P?Mo«£§B—CˆŒßeöIþÈ?ÏC`–£;€± N–§œîËcbã áw ìc̨(ýÆÙ¸q#ýýýѶÖÖVÚÛÛ§}½okkkÅöÁÁÁqÍÖÖ֚ʣ8»víbÆ lÛ¶­>Wpðn0±,‹R©¥àêÏàà ½½½<ýôÓõnʼ0ßòùôÓO³aÃÖ®]+FaÑÑ‘Í'œpB½›² ŒŽŽð™Ï|†þþ~ZZZ¦•¡Qç¶ž§êŸÀøz{öŒß_|jš“¥4·ŒÙÊçBÍm—Ž£~´ñÄqÔ{```üû`ÑÞAø£—ÏZ1– çPÞÊÚØ«vQ’´=·ÝµkW½›²àÌF>en+Ô“¥6·](½mOOÏŒôÇÏ›:ÂÙ¶mzr+oš&ï{ë[Õ$ö§&ÜJù?ÙXd Æ RתÉéííå{ßûÞ¼ÏmgdPÑ,Ä»ºè=0­±•+W6Ü‚s® •÷/Ÿ/¿BDYÛXlÛ¶ÞÞÞz7cÁ™­|žþù ²à,ÔïŲٹaÅÜB¡0aôI³:÷ÚÛÛÙ¶m6l¨wSœÙÈç‘G¹äÆN¡yЩcã:K‘ááa:;;Ù¸q#Û¶m£¿¿ŸM›6ÑÖÖ6é\ºs[ß/§ë…’H” ÉC¹@|¾ÂüñÁ~ô£z7eÁ™­|.Ôܶو§_±me ñ}¥ðÊå*k$ÕeŠì¡Œ(.J±–G‡O ”dTDÊ•õNæJ*¥^”óáñ•Ë1zÞyüõ7’ÏçùÅ/~Á‘G‰çy‹{-ëÀläSæ¶B=ÙWæ¶õÒÛ STÇ—r=—Ë‘H$h½÷^5 ¥Q©¹tÝ«©Þÿ ÒÀ.ÌŒ…š·í_ïŽijyÝNeå\Šär9|ß§¯¯oœ1EêE#Ég”ó1/†w›ëºd2R©étZŒšBÃÑHò)BmØÕÊŸÎÎNÖ­[׋mÇLF¥îÊ唂4•*³–¥¼ÎŘÒüø¾¥¶m›ŽŽŽè³B¡@WWO<ñD½›¹à4“|6¹œ2´¦RjNžË©÷‡NÛH¨4€†¡”_u1¦Ø(ãI eX•¶e•Î+ÊwoP[™æ8j±'“Q/Æx®2×-[œA}fê·öþŠå0?½¿mC&ËÇÓGã8|õºëxpõj(øç?ÿs‚  ««+R ž|òÉu¸¨‹‹Èçx&Mž°OSu§ïOîKš#'׹ܸ ©Î_­¶ž§~ CMf'š¼Vj.èy•y­s9H®ë²Êý,«É …ê\Šñ>8¨P? 0˜F’OÇ©L3²är9lÛÆ4MLÓ¤¯¯ÏóHO§’® ,2$ŸÂ< ¼k㋟rºn+»3(¯ªø~.j¼3ª¾£™Çõfxx˜ÑÑÑŠÔ---s8ãÂàûjX,ª9žã¨¿õX+þ=I¡P [U”& à*sõç]]]$ lÛŽCLÓÄ5tûí·étÏó(•JœwÞy¤R©zwqAiùlô°P(G¦$eÛ€~w,^ƒPë¶¥3Qc[5ÚTFžL6ÎéBOzñ캪£†Q~ùé…¶ã¨ÈÓ,[–´¦/ŸWÛu©B!*óü 7Ø6¿ý½ßcïÞ½¼74Œ,ûÉO°‚€Û8€×­#™Lâ8¦irì»ÞÅÏÞö6Ö|øÃ\‘HDÑò‰D‚o~ó›‹x±ëƒÈgß/?n–µx¡‹½îtœé§ûªÐÕäà‘•»)GIOjµ—I9í£¤§æ@ÃD¨tvv222y 2<<̺uëêÝ´yÃ÷+]28î¸{øÀ6ðGôWüÕ_ý_žyæb>üáôÆq"Ç•ŠÁÔuÕÜMOlS)~ îMªðß~û©}?¼ì ê|¾¯<;:Ôqžž™õåv&Ðõ!8üõåã]:ÚÀ‹eȬÿŽÊ>¦R¨Élè°ãy[šüRîW¦ üÏ•·årã=/\7<6¶}Õ[À«Úæ~œË* ®VU~/9Tá©8…ð'ŽöjŠã ÂõaŸ‡8q!—†¢‘äS§X‚ •J{öìa``€b±H"‘ ›ÍJtÊ<Ľú„YÓHòG[s&`üû¸‘ÑùÙã¤(½Õdªþ÷Qã“]µ-WµÍ ‡þt½¸¨±-~2Uû^µŒ…Y¡S”è\ð£££ìØ±£!Œ:cL.§dU+Luáx1¢ÔÇq*ŒÚñ ”â —Ëá8žçñGï~77ýÁpøá‡³jÕ*‚ Àó•½Bä³LW—z솆*`¡,æºSGAN¥2p]ÏóHÆÂX^zé%òzªžuŒ¿~¡þv]5ïì*‚÷quþbö˜à½ Nhˆñ~ÅwBð÷¼=œ{> ]@ö4p#Xûcêoû™°ÝCÐq$þÒŸSßi< Áêªkf@îjH÷ƒy*x%ðw€} $~öõ£ù;è{œ÷„RÿÞn°Îó'¡ràû> ²xaôµãBö2°| t.â­O£&åyHéÃÀz ‚¤šÈ „VìàjðÏÜõÀ9°þGg0ô‘¡z?† N=å3•RJß/;€Í'ADµ‹´²A˜9ÚÓU+|Òé4¾ïG¡·:×ó^¸_"<‡Ö9éW¡6┪®‰ö ž©‘;€Ö{[Yöâ²½…õ¦»»›ÁÁA.¾øbÚÚÚØ¹s'ÝÝÝu+–«³ØF9B:Ô.î<ø`Ž}è!¿ýv^mk«wõ˜jM’'Õ0 Š1·çw¼ãsÌ1õ¾r J£Ég£Êþສ¨ü‚âÇ~'PcTÊ“$jüµPŒ¼.6m(JY–¤<&wdÊ®üŽ£&#Z;§Úh—K}L(/žç)Ù‰MfÇ!åî¹#“Á²¬hnêû>Ùl–¡¡¡ ‡,Éš8=D>CÝ…£Æhýøår2f õg±Ö:K×Téf …‚2œÄ¸ÿþûÙõü.º?:É;#A¥óµ ̺Tj$êî³“ááaÚÚÚšÆA‡¡é°gm¤p]5øéB}ºæÃæÍ»yà/p÷Ý×sê§Î4l+‚mŸƒe•=»º”'€•ŠÊ ’JAâp0Î…àP`uèI fi1¯Ã¡$·BG!4º„Fûðü²Å7}&ØWÅR†ÃÌ ¬ZÙn°Žƒ\äÞ ‰ó oþÿÿÕyò+ ð³ðZ<¢æ¥V‚¿Ï-ö‡Ì“`¼ ?Uó`ç?€·ƒwþxú.Rï…Ä¥ÍÀÀ%üøw‡QßoƒÄ‡ÀvÀiãxX…ãÁû6d¾ Å» 0Á=ÌoCpª:>yä¾ÞÍøQxM΃ԯ¡ïk`oS×­ð Ø¯£²G¨v8ðžãwÕûœW&*V/ùôýr$¾çÍ¿1E×HI§Ó -}Ø6¥Óéh1¨‹úÿj´áC_§B¡@±X$“ÉÏç) ‘QC{¼tttDFPéE à ¦.ÐÊm€ ‚ ¢¾ïG R홫ۗN§ÇµU^V­ZóÔSOÕû’Ï+&ŸQ(”ʆ'üß Ûn†çÑ‘6Úø‘¤\Ê•tl?7ü] ¿[aÂ/Üî†ûèðõT؆D¬ÚP•@yø¦Ã6%Â6æÂó±c»Âóºáþ”GŸóŸ:à–\³Yõ½†¾¶zikÏ0¹jp9z¿1Zß>>óRcóæÍ Féê)›®[žf³jþ*þ”ó¨L—x5nÇáÉÿ˜—¯¸"м´r9ž¾è"ž?ÿ|LÛæ§¯¾Jk?û}à\•îyäFöß_)[3þéøã9òüó9ó;ßáK¯¼Âµo;mßü&¶m³~ùrÞù¡ñÙC!5_éèPvÛbQMú/¿œ¶‡†sÎQí²m¬tzRCʾN#Ég# ø´þß0Ayk£ÆÍ,eƒ~5.ý{NÉ–Ç)5ÁЋîR©¼èÖy ÷Ñ]ô~u¢Ãñ€T*ÍQãNU…B\.E©A€ëº‘Léyg©Tª9æÆR–Ïø#šË)¥±e©ÇXßÖ¿åÑêI=õ¶ñ×øDèºpq‡JÇq8û¸³yÇñÏŸ³ÅÑNj‚0K*BhøÁRG‰è]SD¯e@ýí8åZ†¡æ}gß²›o¾ÍW½47ßü)N=5T$d€¡r:.Ëcu Kl¨lI&ÁzHBâûT*qLu>k ŒñÀºŠ$Bå”w''¨ïI!x ø$û ©•:}HÌ0 Ú 0ß Ég!›'òN5ÿ?H«.Rщ·ûsø8–j‡Q‚Äõù5˜oVç²ÎçÓ0t=˜ç‡×ânuÞ\Ò›ÀøS°ÿAhÀÉ«vÿæpoä }#äF!ysqb‡×0¯ 1§Àž;ÀyrÀXÅ.ÕþD¼÷CîýPLƒõY°SÐõ(”6‚ÿߺJ¡¡(÷>(¶@úpõÕOóÞPïGsQ¨‡|j/÷tzþS}A@&“‰R\Ô›êÈŒ¹ô ʆT*E©TŠ "º6LGGù|>ZvuuÑ××G&“¡T*ÑÕÕE±XŒ "ù|˲"¼¾¾>LÓ¬ðj30‰Kc<Ç©žé{ ¯AüZ˜¦9e }|Ü0¶aƺ[G#ŸétÙ»uFE¬=”ÒÝ¡lPÑž©JÁßîgRŽÒ¨5Ž×ÌòÃ]WD?ZZãPµ¡£;ºÂ}tI¥üÑFy’"›ðbmLÅú‘GAºÂs§Ã󔪶îW l€ÐÇÛ±¾”=«â¢a…çŒS¤2â&þ‰Ø1:ÅX2v®U”=ƒÝð8Ý–Ÿ €ïÂe8Æ+ÿíCfaÂê,œl ¯ýËxÙƒ?°xÑx§ßü¶Y>aÍE<üb“˕ב‰„OuµS(§ýÙ³§\P:ž¿(Üæ‡ãª °j#÷ÝÇ£¿ûм Cv6z(–ïóGÉûûùÄÍ7³¦¿Ÿ½]]tä‘I‚½`¾¥œÑóÓ,äoë^à,È üûÛ(+«ëõPØ ùãÕÿé4ÝÀ§Êû$.ÿûDE m`àzàÛêú躃Ö¿¬pîy`fÁ,¨¹¬ž?gƒq¥ºOßûÞ»øÈGëýx.IôDs¾×:÷¸öDkc (O8˲&4è4W™L†d2‰mÛ‘A$NG‘ê°WmØÈf³Þz»Þ¦ Õ¿«¯6tHM¡Z«ÓôMJj ‰O(…½Ž²p)+þ“”#5´ñC5€²ƒ+m”Qaˆ²Ã€AÙh‘†`øw•‡Àÿ&õ7”º®Þ¦ÏŸï.U㉀=`Ý^'åqóÿónvB õ·EÕWß-_» Fè¹e¯EÌðÇ-ÏC‚Ðq£BJkÙeã;èóÕû…Ñ©¡S‚Zå§á)O]Ü­YH›a{ê|Æ…o%À4`ã@˜Š…˜‘(€Ó\è‚,ìz¹ÂüË kçi§Ÿ}f=J iYå|¼¾¯VæÕb'0϶1}?¼P^~þÞgŸeÛsÏqcK w^{-x ·Ÿy&?9óL ÃÀ´,¬tšS?õ)vôôðú׿ž-_ûWy&¥«¯.§ ªbÙUW‘½ðBp–_t­_¯>H$¸ªZ“fã5i:p-ŒYcüáËÈ™;Ï QïøÒÅà Šp¡„x ‡Tf€®c§ŸµÕT¯eÆ-Tspßá÷‘Èc×µ_Ç!Ç·a4~”5GŒŒ%yÊž<:?¹O9ÝF=’OQVˆè¼³}(EÔeŠQÞf= |¸¥tŠ{ëj#L– ¯Xë›`ýðûáv¥PÊSö6J@ÂJ`öA°?ðeàð¸ôJum8Œ,d¯û£^a{“×)Ò Àzð*ŠóZçAßOÀ:¿| qÞ¹‰©Ôe㪫^„Õ¿€Ë*™}ÿ;&î’­ÔEÿ½ü÷ñÇïâ—¿\Úyàëö”›Ï¼Íº`¤ïû M˜âj±ð}Û¶±, Û¶)•Jø¾ÏªU«èëëÃu]’Éd”Z+—Ë100EŠ$“ÉŠz"ÚRñ¡Ù—ŠY õÃqÔ89.ÂZ7qý_€tú.ÜÇÀð 8ÜÓ€À^ðèCû>ðìÙà¬ÿ>HœÁ¯·)C†Ön±¯®ƒ`?0C…r*£>Ëç!w‰ú¾DèD`Yà½N‡2„й£÷‚ß*§WƒäÁà‡ `^kžxõ R?ÞK¿rœ°¶«Ór{÷îå÷~ï·<þ=5{üñŸsâ‰oâßÿý@vÿÃ-¬Xq Ç{,ÙlÙùÜ4á[ßÚËÍ7ßÌyçÇŠ+xþù›Ùÿ·òÀÏñØcqðÁOòÊ+Ÿ¤½ýèòjöG}”W_ý+~õ«/bY>/½tt¯{Ýxî¹ç8å”ð?ÿçk¬\Ù øÀëc÷)€Žœ#ÿë”U˜ÿ¯qæ'›á®Ç" 8~x[=ááçxîo¿Ëw¿û¸–/ÿOV¯>ªÞë’ÅqÊéBj0,itÇ=¯ìÝmì:ã ËfÙšJ‘L&9|¿ýØ}÷ÝÜpþùà8¸žÇÇwî„3Ïä¦#ŽààÎN:::xk_»ùf^ëïçäõëùƾÀU7ß\û¢†iîòúP´i"§C¯¸BM¿§*TµÈˆj‹UYì0’•LRSYáþk.ºˆžž´µñŸË—ÓöÍoJš¢}ÏïÏ´Pà1+\¾hƒëÁyi8>«Æü­>üc¸¾3ž^×€ëÂÿkÉÎ…=K·üB¡É„a‘#Õdóáêhéº#ÎKM‰ÎL§mÚÙlyn<‘{:Ns6v B1á«:Œ¨ÿ|ëç9âÓGp¦}¦Ê¬cšôõõ©…“ ZïK1¨Lvr+•ÔßñÎ0Ê*ãðá¶Ûnãu£¯#™O’L&£h‘¸A Ê»JE;ðdì³ eãIuÑW¢s¬ët%PÎÁ/°d¢, vì; 9e„ÑûhWܸqmìÜPöÖ՞Ädžm5MH,3 L¥÷°NÏŸ§&€=U×0IÙk™ªãu·>… ¤?DM´W`.—ò,<Ï#™LrÖY¹\l6åÆÕÅ­õ1®ëFµtîÜq·Ù÷ùà¿Ï1ÇtNï¦6`ÎßùÔ¢ª¯¯/ZH-V„…çy8ŽC2™$—ËEÏ•N™•L†ïÔD@F´¡DG’èßz±§ÛŸ•¼-B¡ÇÉq*6¸Bpr˜Rä»àŸ ÎÍ`~²/ƒÿSÞ–‰CB—À¹¤|ÎÄ%ý<.$L¥´Ïl„ûƧȭåÅ/•TúïñŸ+E¥¦ÂKSúI²œ†,<_Ƀût?oüÍyèЇ°,•WÝ ÇO~Ò”6A s`+Ï×®®.LÓ$|ß<_?òƒt:M*•²,>ó™›YµjßøÆýÀe|÷»ßàòË/ã'?Ù ÀYg…ïÿ+§œbð¹Ï]ÊÊ•gÓÕµ0Ùo¿Ãyè¡ÝärOðì³ÏrÌ1Çð“-yþ1·o{€_>·?/vþãÿàÿûÿވ繿ãK|gϧ8à€8p¬DzÙ™ûÖÇØ»÷¿yòÉ?ç oXͼé Bч믿…_ÿú·<ýôE<øàó¬]ûÏÜqÇ:~ýëÃ8òȹîº'1 ø‡x'žø×ìÝkóꫯ²zõ{Ù³gË–madä§õ~\—:kU¡ ”¤¢œªóÚ¶êp6)=Ï£àûôe³ø–…ã8¤}_m¿í6þzÏ’…‰|ž½ûí§Æßpî—ÏçI$ìýÈGHÜy'Çê4Bcc{á…ä/¼°ýù1¾}ñðôI˜(½§N;¯E¦ºiGNñ¹*¨”EÚ¸’N§1 £"…g¤R) ÃàÓ—_Î{ßüf:{{)¾óQáìø{H§ }â‰'ê}·…y$—S¶°¥mÛž¦·»®3TÎà³6 ð/érjËA3*góq&|È/¯}jG—Ì-+¾ïGók?6áÐéºLÓd`` ¹#ª £²°Ð°ø~¹Þg(§ÀêÛ6×€Ay „}×ÄÈèÃý£÷³ë¼]|:ýé(Íò—_û2—þðRµ…ÔG1¨LBWWy!Z(T¬×"òyÔ$1…جRÜ.»zOóùb¾2ÿ¹‰ú_Ïùb¹Ú󦚃f»(G„uY"ãC•– ʹáuž÷ø +³tñÛxNö4åt_Tm‹Ÿ/ÉøÔ µ&à±4[Î ¼ lŸïCËK;W5#ôdØqœÈ(’H$¢â×Ú{ÿ«N"çü-†kDùmµ‘Dï“H$"e–ºŸJ¡g¡VRëEh<5ƒ®5¡žçEÿ' lÛæ¬³Îš¿‡Nˆˆ×–œ+¶mGEÐ:½—ïû†¥ï* ‘Dz¬Èˆ¢ “¥˜³¡ÄuËî‡}®]«óO§Råt"º’qÜzœË•‹I鼇ñϵ¢Kcš•«vÏ« ñó¼Ê¼zú;tŽEMÜ#Xç©Ðßcê¥,‘8u#“©Ô':Žúíº*ý£{P‚ä!m¿Šc”‹«ÿ ø"Ñøc~™(ÊQ)úŒòí ¿':¯ª±D"Ôyѵ=?ÁŒÜqœ¨˜¡iš8aƒ‰ù|žT*E$“I‚DÀ!_¿‹—o¹…ï?ú(í¿ø<úèÈšH$è3MFoº‰ßõ.Rßü&×_=O<ñ+V¬à€àÈ#dùòåQÄY__ŽãDFÖõöòꫯ²ÿcñ‰O|‚“N:‰-[¶pøá‡óÝ—_¦ÅóX=4Äi7rοH>ŸÇ÷}zâ ¹à†^|‘G÷;Žå–5kxðÉhÌô‡_þä'¼þÌ31~û[>xê©øÏ>ÊE}€?<ä2Þøó[9aíZ~þϧœó+Š|ìcãÞ{o%™Lò®w½‹ƒz€5k.äÄßȉ'>ÀÀ€ÁºuÎÛß~çž{7G}tx=.àꫯ梋þžÖÖý ‚0ŒƒqÝoñãû¼ímï¨÷#»äèêR¯Ú0(£¹¨VêDóÚC=,Vèû>-7ÞÈëõ+vïÞÍ:Š-GMïèh4—ëèèˆæ~™LÃ0(‹j®é8ø¡V{­Ç=ÖWüã?²"Þ®¾¾šÍÇuݨPNç™Éd¢y¥aê½*†u¤j6›æ¸z‘Ï父빬ž‡f³Y‚  ««+*ޝ%æû~Ñ 0ôѪËkÛQ9]S-—Ë‘ÏçÅ ²DÐ^òù|yŸfMjLÑÅÞõ@>0ŽßIÁë-Xé€ëÃP^ߟž,ÂGõľhŽÆÏó¢Âñ˲‚€ÈiIFb« NùÝ,å•z·Jˆ¡(©TyI´Ï¤Ø„@§¬­%Gžç1à#{?¢æ:¾…ÿyò+œñ™1•.t)9 ‹Tj ÔÊq”’hœ@;TDlŒöŽòî|7§¿ït®ùÀ5<þóåº i”£D9$ <æªdíiç20Ÿ²ðć¦R鵚.Ê_»émÕsÈ,娀Àƒ„V“ pÃbµ–z!YVU2öðüPV¬ÆI¥Ô$YO¼Ã´E–eb¾°rßPÑ0 ÆO$"…ó¥÷ßÏ3<›O>™;ž~€‡7l <ÏãÒãçxÏãwßÿ>Åd’—îë¯çã×^Mšß|Áß’6 Ì àþûïç-ÝÝ$Ã…d:Ví ¿Ùp%QŠ+e  5PVbëÿÓÀKßý.ÞÑGÓ§sg„¤Óiz{{íÙÜWÈåÆë÷gƒmÛ …(üs6áûÚ •áÿ…B!ªc¢!qe„iš$‰HÙª‰ÎáºJÞjå@•Áú;™¬”»®®ò±ž§~ÇWÅ™Lyv¯?¿Àl;zî#CGuô¹U£Ç»9'“eCF­$§:O‘FŸ+þùTùÜòùÉW$Så±Éå8ý±Çf|Ï…ÙàÞÓ=®‚ì¥`¾'ŒÐ°!ñ/¨t‘/‚y\ø·…ŠŠŒ«A(ã.Þ*¥,Ñ5ƒ´ñÜ4MlÛÆ4Í %¦Ž*|í¶Ûxð†øØ 'ðÈÊ•Qnôd2‰çyÜsÛmüuk+#ï{÷û~UòÂu×±ßw¾Ãœq?ùÛ¿åò+®à®CᆃÆþðC(®^MѶI¥Rôõõ‘ëêâ=_Ì_}4Ÿâ/ýkN¾å–(Úñ‡Ÿþ4~ï{•ìutðw_úgÄ¢ÓÒ…ø>Ü{/|ùË`¼ç=ïQäSŸ×US„\Ž=ÕÈ0ÅÐ[Ãÿ¤úUiÎlÛV>–…a ú>o\¶L½£þìÏ8}¿ýhmmŒN|0Ùl޳%ŒðÜŽëºär9Ž=6M.—£X,’J¥(‹är9’É$ŸÿüçI§Ó‘g~"‘`åÊ•<øàƒõ~l—A ^Íu Z¬U¤Å¶'®ó¡óžèPš°ïc=Æ/Î:‹':ˆ³zˆÕ×]Çðí·ó¯ï?ïºûnŠ7âtu…ýUQæõ×s¼aP Õc}µs‚oYx¡W{܉FbÇ!ŸÏG†Vµ¡Ú¨¯Ã ×LíÜ“Ïç#£‹6ìÆ¿Ï4MŠÅbdôÐçÒ‘Õñùª¨×óý?P‘ö³š‰7ºO?”ç±â-o {ÿý÷×á!æ‚Ϊϗ‹[›fm/ùqè'ú·|ÕW飯.ÁçØnï ŸI-Ãá:qnÚ+–WþôX¯ez2§¨†IϵT˯ër¹Ôk‚@©J¥ùMS=RKØpœÚ¿:êöËA&õ©ôõqA&ÃP"¡ôŸ:Õ²Ô1¨„hgétZÍ}¿rþR1x9”Ógõ>|õɯòPËCüôäŸrPòNØø9Zþ%g¢¢B^°áiC˜Ïá·g *;wƒñ6àôºRa…ú¡rQzí nøj‘êÆÜL ŽR¾êÑÜ “+w*ŸŸXyÛÕ¥”¢é4$“jahYÐѦÉï}”_ÿÞïqØÎô¯Y)²Î8þxÞû¾÷±ç´Óø³‡æÏ‡\.Ç•W~o}ïVÞùüóüóÉ'óîw¿›¾øEž#RôïíaÛN0M^Ëq‹ïCKKTPcÙïÿ>7_uUE¬\.2Ö¼=‘€ãŽ«ì_±XöÔ×¹0âX–zëÏ«µ–Å2Ï#O„ªñ}–½øb½ß%….È7Ûµ‘^|icÊlCýS©Tä5® Á÷õõE à xí¶ÛHVL)ZJ§!—Ã2Œ²ÜÅCmtÔE"¬$­gá?”o},k¼±¢Tª|QU_¬ ¼i#jUB¬fªÔ%:¯µÞ·Öçqêá5hY÷½ï-þ÷î£þ’Ãá?6kfé ­.$_DEè¿C|ßÇ7||Û¯Hã‘Íf±ÂÔ=ÚkûMÈ÷·o¢}ß§T*•e=¬þùòÙgã¿ò ³ÿþ|áØcÉf³|å+_¡åsŸcãcÑÓÚÊ]/½ÄÓ¯¼E f2Ö/_ÍæËâÛÿþïái]άD"ò;Ðáccl ·¯_dét‚óÙgËc´apFõÔÊPܾÖ{KËÑ<¬Ú«•¬q…TµrJ+mµ—|"tŒÐÊ^ý[¿µbWo¯¥Ðݽ{÷œû (G -Õ¶óEE{#Åǃ°öétå¼*øÝi§ñÚk¯ñŸŸü$on{í5.-xêÍoæÆ;ïäÇÃO–-ãóÌ»ÿìÏè_¾œßnÛ†ñÐCÓ×mÛ÷ìéY†aàû~ÑìÄ ,‰DÇq"G ÅAd$´,+:·68Z–U¡ðÕò ·U+ƒãm›Hæj‘œe=‰jZ·o=*4:ÐX/a‰òlÚÓ_µ.ÕY àì4\޲“Ü…Ããé4&ê:êSGcic£–/md×2Ô××ɦ6F U$“|é{ß‹æÂâ£3àé ÊdrñÒkV, ÂRĶCõ‰®)pj®v0«A¯«‹ÑýW>wÛmµ¾E— pgûí‚0}Ä âºj­Wk2®NŠKÑÏüõ3üëÿ•Ï|‘ì@–ƒxþGöZ×>±- 5ú~*…,üãüUXæû“ø.ð×Ê8 ">2eåhWW¹pKµ²3ʉpõ(¯±¬š Ö(UAè…燓Ý\.G:Œ1ÂJ……Bì·¾¥rQ_x!®mG Ê÷$”Þþv‰·‡£»^”ròFLÓd›õ¯¸¢öŽaU6•«e>?µ»†¾µöK$”rª–—½>&ŸW×·º-žGÒ¶:÷Üi>iÂd8U6Á™’ËåðpÇ}î8ð\¸Ö†—Óðù˜B$‹Jëe•ÊEÖ=/ôÐ •,…é÷Yp¬Ö/Iª/ b9»&Ó2k£@lBª=yƒD|ŸŽŽJ¥Rä±§½ìtŠÇq(‹Q¸?”Sd³ÙŠÔÕi jyË-t­ŠŠ4W cò™I-Źê8_ßµ )I??è̳A~׿Þê“á8Üñ…/ðð† QaÖƒ¯»Žcwï†ÿûUê›|~|ÈÚD³Yý<Æ#8„ú`8–Å_×»KœT ’GAñ­`t2¾öW °á?ÿó?9È?×u£šæ¡*‚cœ¡Bç+ µr #±¢ôßnͲôRŠæç¦CûêFÙnÊ”^AøãSv ÔÛ¨¬ úñwœiE,ÅSåig&Ï0Œ¨öX>ŸŸ2¢J¢P„FF—{Ô‘(ºFY½¦Ž".ÂR§P‡!=^…êÐ[.¿…3wŸ‰é›Ñ8æ‡ÑÁKjn&4û¬AEg&ÐÞãGµñ$GÙ*ÀKo|Š;¾Ÿ ý–Kö\Âê5«á½(Å‘aÁÉ&ô¤á¶ªóU{.Tx®šµSôL2Rë"–zAiYNh@Éd2Q í¹—L&Ù³g@Y¢—:s­Q^*ª ‹„ÎŒ5› j¡Pˆrž[¸éÏ¡ÌAÀKßý.#ÿú¯=½ø:jòë‚×çQH"%åwÞÉìÿ<•y Ã0Tô(m°6žÄe7,Ì eci"ôx×,r]wÜ85QzAXŠ,¶1E×yé»ßexåJnxþyn[µ 2nø¡ÁTGvÄSýh¹Ö©€\×êëèTºp»ê_"ò`×Ñ$z¼®ïõ» /6§ƒé$h÷j¡¡Ñ%÷ôß:;ó”èÔšPŽM¢Œ':…ŠCemΪçÁó<‚ ˆRåéµe\¦-Ë¢X,ŠaDXrè2”¾?ÍZD‹€¨f„¥NTŒ>¯lØkïÅ>ÛfÛŸlƒ/Ûp|Û¶ñ<¯bÎ'‹Í>gPц=_¬ª1^ž\:¨Ée eTIÂNçý´Ýû0í'È{~u v§*ÌW@¥õ2Œò(÷žùmw|«=ôôdV/>u^ójÏüb•˵'°(„F “™ù$Q&ÓÂè¹×ÅÜÃ|/~èC|ÖqH$d2>uÉ%t¾þõ˜Ù,oÎf+ïDÆQñ<\ ,k괺¢áyjêjšêÖ eJ˜9ýr7:EçË«5¿6¨(Øëº.«_xo ø¾e:Ð)îÄh²pè÷§NM74ëHÜl6K¡P ™LòØcÕ»ÉKš®.%k¹\¹¼]£Ë©w‚LgF<ªNG·êHXŽh bbtä;”4ⵟªùéOʲeËêÝݦ&ò•I¡êU§ á$ØzÊé~ýé°<Á¿¼3aÎ[M9A˜-û”AEׯÌf'QÜjcжˆzAŸ)…ò¥¯«œî.ÊøbQQTw>Ð Km(ÑE±õä*‘HT¤ßÒVY‰&š]ƒ}&¶=]t^§¨@u0M¾zÁÚÞŽ†„êÒ‚ ̞̻ ¸ú~ œZÞîº.™L†l6KÚ4Ig³eãf|õFHzž‡Q$¥Ž¼Ô‘”b0„‰Éåf>vN†ëºÑoý·aœyæ™\pÁ<ôÐCQqé p= Lë¥ -@ÅozK/zuš­xŠ-‘ó:¢bQæG F8-†Äjt¦g=…­YSç”×ÇëÚ')T¶„D¸Gm#J ×u£ŒA`ÛèÞD"±O{ýj…jÜ¡QGÊÅ#eãu™ô<¦PPѹ¹\®âs½fÑF±gšfeWغ® õ;R Z N_]’¶‘XèÀB1ªZâQ¦µö&44ègWË’6fh¹ò'éTÜ™C×gÒõÒt&}ÝÖZký¸Q¥ºÚØ¢™ã}ײ«¿ Ã`ïÞÃY±b=öVî¸ãÿñWõg {ƒ–0:ËsTÛË€›ßy3Ÿ~æNýÕ½ð©¸ÚàÖ\Ž|BtŸBýÙ§ *  )5 ™”‘$ |ÚƒÛödÇøÍ?ÿ3ïmiQÊ¡¸[ÐÖ~:²TÊ×u£j<ÒD¿¤Åò*,e2™šNꢋ\~øÑGù¯+)•xñ'?áë/½¤ê*„¡‚ãÐ××ÇËÀÙ¡‡ÈbDæBðßPøð ô$QšmàŒŒ–…‚Z‹øA€ïºØ¶M__‹E …ù|>R$Èx'ÓÇ÷k¤¬!ºÖ‰VPrÈ!´´´pÍ5×pÏ=÷DŠƒ—_~9R€h/Îd2YQh:Ny0;wšrÈc sçpÜqòóŸÿ»wïàØcoáÑG?Ì~ûý7‡ö38à††ÞÂØØ ;ì0~÷»{yãÎðð‰zèÙ¼õ­_áÑGUÞ†7½éH^zé^ÞúÖž{îD†‡ßÄÞˉ'Èß«¯¾ÊÇa‡]Äi§Ù±ãJÞô¦ç8í´"÷Üóqöî=œ×¿þUy¤…øQ~úÓGصëxþààœs~ŧ>u*'œðöìYÁž={éí=€Ï}®…ÑÑQþÇÿ8€þþCyè¡—ÙË:0*_ª#tŠEUÃʩؒɲÁÚ²Ô= ³‹FÆêøqñ÷3¨wqõqù¼úθܲÀ÷óÑ»ʵ­^xá~üã_ÓÓS罹ùÈdÔoÓ@q õ>ÿË»ÿ’?þq¸ür0 R©”¬…†aŸ1¨ø¾zyŽ«ëOñU Øùí'yá¶Ûxæ‘Gxõ‹_dhýú9~wÙx¢'±†a`YÖ8ïz­ „}מ1E§éïïçSŸúoyî9~4:Š$ Ò¡ÒF/t$Eˆ Ì]ÄVëV<ð]0þJ_%ÌÁðã3Ïäȱ±Êè¯P¨µò&“ÉN§#e€Þ·:%¥ 1šD(‡¼[À¸¼U`@W¸o5—µÕ5Lõãû>OÝõOÜù?Üÿ‡8¶ƒi˜œqÆœ°÷²Å,/ÙÈÖomŶmV®\Ià¬~a5}ù>åñž$*ªÏ‹û­¿[h>´ •Rš¡k®©w‹ßWžì®«tA þÏç•R-®”M¥”Ò-‘P†—R©†ñÄG9÷A$ëÑö%ßJÆûªÛâGm4*”þZÑ?ešçE4¦hìöôÖÆ íX¨•Èñl A8ç+˜õ1®ëFÇêµ€Nª£^³Ù,†aŒ›ƒhåÜdk½Oõ¾z¯·W_c1*7ú·ž6ðUÿ D©¤4q=Q¼N‘–e€åËçÑGÇ-·<ÀÈÈñ¬Y³›·½íݼöÚáüÑÆÑGÍûßßÞÅ /XvØïñÚk-Q bœuMLóK±¶AœŒeůÃê zùñð÷òØß‡„¿ßŠï¿ÐAÇñÑ~®~¿ç=-\qÀÁã¾)n—¬e£¬áZ"?n¢W^ü¸ZßS­Ï×ûèC×s衇 LÇÜÇ ùfÈ¢".Ãë™J¥Èçó^píˆ.¡QXòí «sL£ µø+‚ør…¨ÈmuÎö©ÐCÛ¶I&“Qè¯öúÓ©º&;§S„} Ç™:lúhî÷}¬D‚|ÕLHj Âìp¿ ‰ãÁÛ ÎÇ!¹¬ƒ>pî„\ÒŸ†ìÏ€ àŽóÿ„ÖïŸ_[ÿìgçÊd2©ª=3%RL&Ç»à&ü?ƒwÔ‰¸C­$~#þ“Çâ½òŸþ îÁ’xÝAp\œÒÊàázð‡×~„~s0£ÏÏëõ—ìiÙÃ×ÜBá…ýx×~Gó¿?øG<÷ãu¼ù¥‹øÕè¯86w,÷ýñGà¯\ú°ËÆ|W¾q,\ŒzðQ6ð^I€“PJ`m¸ÑFX—²¡%‰JÝP6¶”€U(£NWdQV§Ãcð·Nÿ'Û¦×ÕNìs+Ün‡çÌÖ8G2üN/ÜߌÃú¨4Zi#—F¯ôq}±þÆÛª¯Sü;'êO|M:<ƧlÌr&9G6vâ×$k¢jŸ£KpaA‘?üúÃ<ÛùìLÙ}†_\FW—ZWöõ)a_Ÿ2¨è)h\§÷ÑÔœ¦ÆŒŸhï\u-¥xm½·•|‘oÚߌ”­ÚO‡O§Óó¾–ÔÅèu]³d2ÕDÒ5?t­$­ ÖÑl¦iF)°tZ«T*ÅÐЙL†¾¾¾ ³6Žèm:Цº_S)´²MLª#æôDæ"û.¾_NeYJgäû•ú"m Œôôöø>éwâò©#œô3èû>étÃ0"]ÑÌ8gZ{•O»fÂ}j½2æ{9½¯¨¸Ž9æî½÷Þz7£)ðÿìõN(}Ì33LÇás7>S‘2Ö¶m|ß—2BC±$ *®«~,K)lMSy EŠöð(ë¹Ø9% ÙlvÚ9cõdOO.S©T4q3 #ò ª (ü;À¾ ¼]ßö§ û@¥ˆÍEuÞÒÛ¾üe¾µÿþü¿¿ý[ΰ,>ýéO×»‚°¤ð¿ Á“Pø;H= Cý`®ˆÌ—_ÃjÝEðÁÃȾþFJ_üÌtŽãð-[øà³Ïrj©ÄÛßólÛŽRcèâÒ¢¨„Ù±ü•åî8ãô·“8öA²·½ ã-+"/Rø0 ßΆàbµÑPŠ=Eëÿ~ü ¼éÀ1­Q6ýd%÷y÷ñÇü1=ö{úSŽ>õTÞ¸Š—p,Ǫ/v h àMáäù£Fy\ö °ØåÃLHJù[+È,=ÅÿP™¢hÏ"~\­l9ñmeƒVÜh†2&”bÛ'z=¥cçӾ猬ØqÚxcTS¬ñÝZ¬÷‹÷'M”?<Ú/IeíŒZ×µÛ_ë¼Øwêï׆ #l›ê9â2x ó@ù¹*øùÏO y2¤}*"ÁÒ>Ê •¥lü2 ¡`@Ö¢|?ô}ÒÙŠ¡× "#†Ÿ+§¯"å¬a3RÀêºzœN§Óã"Cô8®÷·, ×uÉf³‘28žâOG‹è¶h¥rµrYGrèßCa•oíh¡•cÕû ¬Àû$8{Áû9Xìg¬“ û?!÷Ô®Æ20W€™‡í{–ž»NøgÎì$öîÝËQGÅŠ+xÏ1ïaøÀaºé`…½‚oY1oM–(¦¥Ãé§ŸÎÞ½{ëÝŒ¦Àþ3`$ÿ5Ff2J‰›LrÓ®]üú¨£¸6V­Z%up…†¤á *ÃÃà ÓÖÖF[[ÛŒŽõ}¢(‰$”'¬Ú#+€çOzžÛ~;×¥®TNÒZƒY¼X–.¯ó¯f2J¥RŠ©'ˆzÒ+žòÂRc¶òé}ì/“¾ìÌeÇ’½Œ³¡ôQîsáaÔ@ú1“—¯»œßþö·|pÙ)ìWàÿî·pÀɺYµµ)DãÞ˜ÔØVË´ÚÛµˆòŽ3™×êt¿§ú¸ZmÎ÷”ŸÒ¥™¿§e@Óç¨öÂÎ÷ÄÛWË39v\òé}Ç =ùô ú_£”Ö(=ñwÑöô©«±.ƒ XC"¡ÂþÇÁéRãàŸ^}uT„Õ|D¥0MsŸ.b+1SÙ|þ ç)>wrø_<Ÿl§°8òm·Ý¥ú9äC8묳øåÉ'óo|#RÄ^¢NpÜD_<™öNjTjM¹µá Öö™œ/~ÝUç©þÞ‰¶Õú{2½@b‚ý¦³´¨>¯5ÉÿñèýXÛv¿kŸ1¨ÌT>?|À³¬ýy8y¹#Üø¥4$Ìr”Õ•U—cÒp´ 6<óögxꡯ³â‡üòjžýí½<Ôú2½êLÓÄ4MŽ9ä>ùôÓ×ÞβxØK(îëòÌç>ÇwÞÉŠ+Ø»w//þþïóàI'EŸo¹þzú,‹;s7nä5Çá…Ï~6JÅéû>ïÜÉ…ýý,»ï>†AT¨ý••µ=ôÿ:}§ÔJš™ÊgÁºçécÉ{;éß{sÅøp^Ù—CCø¿­ù †‡‡yþ¹çÙóð¾ü?ÇøƒŽ?ç„N`ì´wsÎoÚàøouÒeÀ†4¼zœú¿86*™Z£€ òåÈ2øa^ _˜ K” Úwùá÷„´‡ï µù žòaoxŽÀ%áX¬ ´_‰½oVoKÀñ‰²Ñü._Csp¿í†j‹ ´xð›pAö€ï0á‰d9ÒÔú]ø޲TF«V5ËcÎmÜÀa¼8<€ã’ðz£ÜÖ[ìr[–›`¦Ëë¿;Øæ?ܼ 8$$ÊŽ ?páß\uÝ—…×íýá5Ñ‘—ñkrŠ ÏïIW^“[l8-|wO&“–Š7܀뺸®+Æ¡ai(ƒÊöíÛéííeÍš5ìܹ“žžº»»§u¬÷mHý1ô½ú>ˆRÀ¹”CïÃEÂîCwóÝ—¾Ëçïý<Éd’¾¾>LÓŒ&–žçqÔ·¿Mÿš5‘ç=ö}Ÿd2I©TÂ0Œ¨PœD û³•OïGI}ûyúÞò·XG¾kGÌóìNKðÜsÏq×?üC׉¿?ªÀ¥—^Ê5_ƒišP8ÒÉJÁL¼V'¢4ÃýÓSœCPNÝ0¶N÷{ô¤.?ãæ£?Ö4Ž›ï)Nã¸ZßcM²ì8gƒÃùœ?†67³•ÏÔ§Ÿ¡øÎ^Ì-ã/ e)¥M.çâ8Éd’Ë/¿œÕ«W“Ëå"e­Œ‚01s™ÛÖâ‹_ü";wîdûöíuÔQ¬\¹’Õ«Wó•¯|e\T˜8öÂäÌF>‡ßòœºL«\Åø8Níô· î»ï>~sûíüÇöOpËË/«@IתUœÝ}$Gÿr'ŸÚÉʼn+ÃCƒ à™{îal¿ý¸êÎ;ùð‡?ÌW¾ò>ÚÝÍ%ôõõáº.Ç®YÃÃmmœvÚi,Œ'žà¤d2›ÓÉ$xÝàûœwÍ5`Yä/¼#C2èì,[kå!4³‘ÏäßMöAp§© UËÖ³=Çá’+8þ¤ã9í´3yßi§ñ>U@¤|’ €£«Œ„§Ä"6À¨¥ ‡…ÛãŽh~¸ã²ðø­ £ÄjUYýÀw uŒ®M„–†ÀÑá;§Kå9LT´¡n€[|ØËUù¶pÇ—BãAüȃ‘˜h(P%L´aá>ü<<Ç.îB:6Õ÷øÀÁøïyŒr\à!Ô÷eÁï‡Êp¢#ù~À^V˜pd 2•íŒõÇ|S]ûæøk¢ *Ë’ðRÏ÷¸p¤U¹g¨ïù·pã`— +òµÛKÌXÚýò±  g‡š,^ÎÁû¯ý²Ô˜ËÜÖÿ6ä>÷$¥_®Š¶{A@ª«‹t:9íé”_bL–±¢££cì®»îÛ¹sçØ 'œ0öøãOzÌ%—\26ûŘ¹ÿ¯ÇÞúѱ1+•¢Ï÷ìÙ36”H¨í0¶{ùò±——/»öÚkdž††Æ²ÙìX±X{ä¸ãÆvŸ|òØ«W={Úi‹Þ÷Ç|ldddÑ¿w!عsg½›°¨ý¸æšk¢çv)3Sù,•Jc½—ÿý˜¹ßãcù¯ã>»öÚkÇN:餱#Ž8bìïxÇØ×¾öµzw³&Kå™Þß3ëׯ¯wS…™Êç%—\2–=æö±ì›vTlß³gÏX±XK§Óc¦iŽ]pÁc×^{íØ9çœ3V*•ƲÙìX)6ÆÖ›‘‘‘)ç ÍÂRyÏL÷žÜu×]c×\sM½›»àÌfnoíÙ³g¬¯¯oìŒ3ΈÆÊt:=vß}÷Õ»kS²/Ž9Îtï‰ÌmkSë½µgÏž±R©4–ÏçÇÒéô˜eYc–e]zé¥c™LfìãÿøØ×¾öµ±l6;6000–H$Ɔ††Æ,Ë+•JcÉdr¬¯¯o¬¯¯o¬T*•J¥±±¡¡¡±¡¡¡ëû¾öL72·­d¦òYkìL&“c–e¥Óé±b±8¶gÏžzwkJdnÛ Œ%ÑÏ«ï~÷Øî[n™ò0™ÛNÌúõëÇÆöŒ%ë;õëÑöR©­;¿ô¥/EkÍÅ^o6úXÒ ï…F—÷…˜Û6L„J?­­­tvvÐÞÞN{{;ýýý“Z;_½ŒÔ¿¾ž¸¼ŸàO.æëO½“|ãðoÐßßÏ+¯¼Â;Þñ~qòÉ|á _ˆÒtí¶Uxe"‘P9a¿õ-åu©šµ}ûv:;;£þ73½½½lÛ¶­ÞÍ~Ì#³‘ÏÇ{ŒÇvÎÅí¿bøìýùÇY¾|9wß}7O>ù$/¾ø"ï~÷») œ}öÙ ]oa©< òžYšÌF>wíÚŪƒá¯9ŒÏ}îsü×ý>ú(ƒƒƒ\tÑE<øàƒ‹ElÛæÂ /äŠ+®/­ÇÎ;éïï§§§§ÞM™3Kå™^J÷d®Ìvn ðÁ~ÑÑQî¾ûnÎ:ë,>þñsÁ4ôXYŒ9ÇRº'se¶òùâ‹/òÉO~’ øÎw¾ÃêÕ«yöÙg9묳xê©§*ÆIéàýï?G}4¦i’Ïç1M3ÊtP¯qUžéÆc©Ü“ù`¶òùÅ/~‘›o¾™‡~˜ÎÎN.»ì2úûûÉçóär9,Ë¢P(TÔ‚ry]7(—ËQ,I¥RѱÉ0Lg7‰§…×ûè´ð39¦ú{Î9ç~øÃr饗F5{Í0Íg:&—Ë‘Íf) Ñ1ù|>JO?Ñ1ñ}ãdžAêÁôñÉdrÒcª¿g¢c.¼ðB¾ýíoÏè˜Ù|Ï|¿?ù|ž~ô£t~ÿû ^{í¤ßsâ‰'òÄOÔ[|”¹Ìms+oƒåG`þŸ£¸úê«yøá‡¹ûî»9ï¼ó0M“3Î8#ú{±iô±¤ÖWûâ¶ßØØØX½°uëVúûû+nÀ† hooŸô¡9å”Sxè¡ÝèõåAIJeË8øàƒ9ꨣ8à€8âˆ#¢Ï•½{÷²lÙ2–-[6÷“Õ™§Ÿ~š#<²ÞÍX”~ òÊ+¯°yóf. Cè—"³‘ÏÏ~ö³üÓ?ý»wïÆ4Mž}öYV¯^ÍîÝ»9å”S8ì°Ã¦ûõug©<ÓûÒ{æ¹çžc×®]ì·ß~üìg?«ws”ÙÈç;Þñ~ñ‹_ð»ßýŽ+VpÐAqâ‰'2::Ê 'œPï.M›—^z‰—^z‰+VÔ»)sf©¼g¦sOž~úiž~úiN;í4¶nÝZï&/³Ûvttðè£ÒÑÑ1ã¼Ôľ4æ4 Ó¹'2·X>¿ýíosÅWðì³ÏòŽw¼ƒgŸ}–O<‘gžy†cŽ9¦Þ]šûÒ3Ý,Lwnû»ßý.2È-Uf#Ÿçž{.>ø ---¬ZµŠ§žzŠ“O>9’Ï_þò—qÄ<óÌ3vØa¼òÊ+‘~èàƒn]‘Ìm™Û–™ËÜöÍ÷},ÿ2ô<‡rGu‡voxÃê®jô±¤Þ ,ï»víbÏž=ó>·m˜•‘‘‘qÛ¦³ˆ|àêÝtAXòÌF>¯ºê*®ºê*AXXf#Ÿ?ýéOëÝlAXòÌvn»Ôe‚ÐÌF>/¼ðÂ%md„Fa6òùƒü ÞÍ„%ÏÜç¶Sï.¼±½ imm·mxx¸ÞÍ‘OAhdD>¡1Ù„ÆEäS‘OAhLD6¡LÃTÚÛÛÇ âÈÈHS§:„¥‚ȧ 4."Ÿ‚Иˆl Bã"ò)‹È§ 4&"›‚P¦a *ŒŒŒÐßߨü½ÃÃì[·®ÞM„}‘OAh\D>¡1Ù„ÆEäS‘OAhLD6¡LÃÔPèééaÓ¦M¬Y³†;wÒÓÓCKKK½›%"Ÿ‚ÐȈ| Bc"²)‹È§ 4."Ÿ‚Иˆl ‚b¿±±±±z7"Îðð0ÃÃôµµIؘ 4"Ÿ‚иˆ| Bc"²)‹È§ 4."Ÿ‚Иˆl BTAAAAAA†©¡"‚ ‚ ‚ ‚ ‚ ‚ШˆAEAAAAAa Ä "‚ ‚ ‚ ‚ ‚ ‚0¯»úꫯ®w#fËðð0ƒƒƒ´¶¶Ö»9“¶Qm¦µµ•ƒ>xÚý¨w?GGGùÕ¯~5ã¶5b¿jõe®÷¨Þ÷§i–k²îýDò9Wù[ì¾MÕ‰îQ£õ£h–kÒì÷~¶cçTŸ/•±³^}æÎàà Ë–-›·{½ØÏþ¾ÑÑQÞô¦7Ík[£/Ó/kˆm¦{$ÌŽZ² Íuï'“ÏFŸÛNgÜŸ|Ö»_Âü0ùl¤{?—±s®ýœf+ŸÞ/ajr~4ßÌ÷{¾Åó¼™;75cMÊ7Þ8ÖÑÑ1¶~ýú±ŽŽŽ±o¼±ÞMªÉ'>ñ‰±N8¡âç®»îšv?¡Ÿ×\sÍØ5×\3nûdmkÔ~ÕêË\îQ#ÜŸF£™®ÉR¸÷µžé¹Ê_=ú6Ñ{f²{Ôˆýhtšéš4û½ŸÍØ9ÕçKeì¬g_„¹ñøãuttÌÛ½^ìçàšk®‰¾ïÜsÏ»òÊ+ç­­‹Õ—ZòXݯ?ú£?iÊ{$ÌŽZ²96Ö\÷~2ùl†¹íDãþ\ä³ú%ÌÙÈg#Ýû¹Œsíç|öa¦òÙ ý&g!çGóÍ|ϱç‹;w.ØÜ¹ÙiZƒJüAÛ¹sçØ 'œ0öøã×»YãX¿~ý¸s&ý¨g?o¼ñÆHaRkð™¬mÖ¯Éú2—{Ô,ÏábÒLפ™ïýdÏô\åo1û6Õ{f²{ÔHýhšéš4ë½ŸËØ9ÕçKeì¬G_„ùA/ˆâ÷¾YžéǼâü###c'œpÂØÎ;祭 Ý—‰äQ÷+ÞsÏ=wÌ¶í¦»GÂì©%›ccÍsï§’ÏFžÛN6VÎU>ëýÞæ‡ÙÈg£Üû¹Žsíç\™‹|6r¿„©YèùÑ|3ßsìù"~ÍFFFÆÎ=÷ܱ[o½uZmXêrД5Túûûimm¥³³€öövÚÛÛéïï¯wÓj¶µVXÙtúQï~®Y³†îînÚÛÛgÔöFì×T}™Í=ª÷ýiDšíš4ó½Ÿè™ž«ü-vß&“ÍÉîQ£õ£h¶kÒ¬÷~¶cçTŸ/•±³î‘0;z{{ioogÍš5Ѷfz¦GGGrº––ÚÚÚ™s[£/Éãðð0Û×®];­~5Ú=fG-Ù„æº÷“Ég£Ïm'+ç"Ÿõî—0?ÌF>éÞÏeìœk?çƒÙÊg£÷K˜š…œÍ7ó=Çž/úûûaãÆ€’×uY»ví”mØäà€z7`6 Ž[Ä·¶¶2<<\ï¦U ŸÏ|æ3ô÷÷ÓÒÒBOOÝÝÝÓêG½û©_<µòÜMÖ¶ÑÑцë×D}™Ë=šªŸû"õ~fgB³ßû‰žé¹¾WûNöž™ì5Z?šfº&Í|ïg;vNõy=Þ; 1vNçs¡ñdÇŽÜtÓMlÚ´©b{³<Óííítwwså•WÒÙÙõB¯Ñç¶ÉcgggÔPò¹cÇŽhñÛL÷H˜9ɦþ¬Yîýdò¹uëÖ†žÛN6îÏE>á½#ÌÙÊg#Ýû¹Œsíç|µ_Ÿ·šÉä³Ñû%LÍBÎæ“…˜cÏÃÃìY³†íÛ·³cÇZZZèîîž—¹óR )#T´E1ÎD^’õD[D7nÜÈÃ?Ì–-[èíí,rSõ£‘û9YÛš©_s¹GÔF¡™®ÉR½÷s•¿FêÛd÷¨™úÑ(4Ó5Yª÷~.mo¤~-åù0žÑÑQ6mÚÄ–-[hii©ø¬Ùžé–––¨0iõ"p)ÌmwìØÁÅ_Lgggdàl¶{$LŸÉdšïÞO$ŸKen;Sùl–~ µ™‹|6Ú½ŸíØ9×~.&Õò¹Tú%(æ{~4_,Ô{¾Ž¢M6nÜH[[6lˆŒ"ûº4¥A¥–u¹­\ííílÛ¶-²Þuvv²nݺHá0U?¹Ÿ“µ­™ú5—{ÔHýhšéš,Õ{?Wùk¤¾Mvš©B3]“¥zïçÒöFê×Ržßã±m›ööö(ÆÈȃƒƒ 6Õ3­½ënºé&zzzp]—;w²uëÖ9·µÞÏôèè(6l ··—Í›7³yóæi·­‘î‘03&“Mh®{?™|6ûÜv¶òÙèý&g.òÙH÷~.cç\û¹L$ŸÍÞ/A±Pó£ùb¡æØóI[[[¶l¡³³3ÊH°}ûö)Û°/ÈASTÚÛÛÇ݈‘‘‘†³vi ~œ¸Õqª~4r?'k[3õk.÷¨‘úÑ(4Ó5Yª÷~®ò×H}›ì5S?…fº&KõÞÏ¥íÔ¯¥<¿j3::ÊÖ­[Ùºu+ÃÃÃÜzë­Üzë­MõLÓÖÖVñ¬vvvFtÍ<·]¿~=mmm¸®[‘Þb:mk¤{$Ìœ‰dšëÞO&ŸÍ>·­|6z¿„©™­|6Ò½ŸËØ9×~.Ég³÷KP,Ôüh>Yˆ9ö|ÑÙÙ9.rf)èÌæE(|¿ tttŒÝu×]ccccc;wîëèè©w³*¸ñÆÇÎ=÷ܨ]###cçž{îØ7Þ8í~4B?ׯ_?vÍ5׌Û>YÛµ_Õ}™ë=j„ûÓh4Ë5Y*÷¾–|ÎUþêÑ·Zý˜ê5b?f¹&KáÞÏfìœêó¥2vÖ³/ÂÜY¿~}tïÆÆšç™¾õÖ[k>·¶mÏK[«/Éã]wÝUñóøã7Ý=æFµlŽ5ϽŸJ>›an;Ù\v¶òÙý懙Êg£Üû¹Žsíç|^ÿ™Êg3ôK˜˜…ž-ó9ÇžFFFÆ:::ÆvîÜýߌ:³…¢)‹Òôôô°iÓ&Ö¬YÃÎ;ééé©™›²žèâ¹_|1mmmìܹ“îîî(gßtúÑÈýœ¬mÍÒ¯¹Þ£FéG#Ñ,×d)ßû¹Ê_£ômª{Ô,ýh$šåš,å{?—¶7J¿–úüF˜ÍòL¯]»–þþ~Î=÷\Ö¬YÃðð0íííQqÒ¹¶µ^Ïôðð0ÃÃÃlذ¡bûÆéééiª{$Ì?Írï§’ÏfÛÎU>µ_ÂüÐ ÷~®cç\û¹L%ŸÍÚ/A±Ðó£Å Þíkii¡§§'ª?£ëh.Ù|°ßØØØX½1[´€´µµ5tØÐàà`ÚT«Sõ£‘û9YÛš©_s¹GÔF¡™®ÉR½÷s•¿FêÛd÷¨™úÑ(4Ó5Yª÷~.mo¤~-åù03šé™Öß×ÚÚJ{{û¼¶µ‘ŸéfºGÂüÒL÷~2ù\JsÛ™´­™û%LM³Üû¹Œsíg=YªýÊ4’œ5jûrîÜÌ4µAEAAAAAa1hÊ¢ô‚ ‚ ‚ ‚ ‚ ‚ ‹‰TAAAAAA¦@ *‚ ‚ ‚ ‚ ‚ ‚ S AAAAAA„)ƒÊ>Äàà ýýýŒŽŽÖµÃÃÃôööÖûrBÝ¥¿¿Ÿþþþz7e"ŸB#±˜ÏãDòب²*B™ÙŒ«ð~ÑŸÉ;FXêÌtÚò)²)ÌͶ¶jQœF^; B3Ólï§Fc¿±±±±z7BXXFGGÙ´i;wµ•‘‘n¸áÚÛÛëÒžþþ~6lØÀÃ?\ïK#‹ÎöíÛéííd±µµ•-[¶ÔM«ù‰Åz‡‡‡I$ß388ȦM›¡­­n¸–––z_AbÌv\­çûä#ìÌv*ã¿°Th–µU£éŒ4¾v„f¦YÞOŠD¨ìh‹ã~ð\×eݺuÑ$Q„Å¥··—t:ëºÜ{ï½´··‹W€ Ô‰ááa¶nÝʆ Æ}ÖÛÛK{{;®ëòƒü Ú&BcѨãêdïÝnyÇKF]‡Êø/•4ª¬6ê/‚ •:ÑÛÛËèè(½½½lذíÛ·D;ýù\eûöíôôôD^57ndíÚµÑ>ýýý5%݆ùnS­6ööö288¸P—[fÄB>û£££5ëÖ­‹Â—'’Åx›úQ«½"ŸB£0ßÏ£NPíu:<ó.¾øb†‡‡ioogûöí\yå•sþž;wÐÞÞ^‘w²§§'Ú§¿¿Ÿ­[·Ölã•W^ÉÈÈô÷÷Ï»—Âèè(ëׯ7P B=YÈg¿­­-’ÃÑÑQn½õÖh²:‘,ê6-Æ;#ŽÈ§ÐH,ÄóØÝÝͶmÛ*ÆDP  â{ÚÚÚ>›lì\,Y]ŒqZØ·™éó\9ådãêtYÌ÷ Lï#S1™\5œr:ëÐéÐhã¿ Ì–‰žåzÏ)ç*«>Æ ÂB°Øú™…^÷‰îgæPïìˬ]»–îîn€È¸yóf@ ;vì˜ówh‹åÅ_mdóæÍÑw÷ôôL8X¶µµEŸµµµ-ˆÀ®Y³&ê· 4 õìoÙ²…õë×G“æ¶¶6nºé&`rY„ÅyghD>…Fb±ŸÇZJ=±ŽÞÉëbÊêBŽÓ‚3{žë1§œl\õï¦óŽ„é0‘\5œr:ëÐéœ£ÑÆA˜ “=ËõžS·¬6ê/ Éb®ùô9BÎD÷3;$B¥ŽTOȪ=ajÑßßω'žXó§V˜¨ö6X·n7Ýt7Ýt===ÓëììŒþž¨ßLÛ¤Y¿~=ƒƒƒß!ÂB<û£££\y啬[·ŽmÛ¶±mÛ6ZZZ¦=.Æ;C#ò)4Óygû¬/‹)«ÓyW Â\˜Íó\‹FW¡ùÞ/‚g¶c@3¬CAäSX:ÌvmÕ,²Ú¨c¼ ,$³#/ÔºOt?‹‹D¨4<üðÃ3ÚëÖ­lܸ1Ú¶qãFz{{Ù¹sç¼ÌLÛ¤Y³f ôööÒÙÙ)Š ¡é˜é³ë­·2<<\áU³eˉƒƒƒ Z)ò),¦ó<ÎöY¯E­ °ö:Z(ïÔùl¿ 4+õWûýõyÇÂ\©Ç:t_ÿ…}ƒÅ\[5¢Îh6íªÇÚYƒ…Z÷‰îgqƒJ“1<<;ª¦³³sÜ`×ÚÚ (뾊ù.\4Ó6it(ÙŽ;°m{Æùt¡ÞÌôÙ¯•*@ÿ?22ÒmÔˆ| ÄtžÇÙ>ëµÐr—ÙááaZZZL¡2Ÿí„f¥ãêb¿_âm\ÌwŒ Ì•z¬C÷…ñ_Ø7X̵U#êŒfÓ®z¬a1X¨uŸè~IùµÄioo§­­ Û¶£m¶mÓÒÒ S]á7oÞÌÖ­[#ïAXª¬[·ŽÁÁÁŠ\š[·n¥¥¥…5kÖÔ]k!ò)4‹õ<¶µµÑÙÙY1!ݾ};ëÖ­‹þoDy„z³Ør1Õ¸ Jv'Z\ÆYÌñn:ïA˜ 0FMµ®lBcÿ‚0j=Ëõ–×éèŒf"¯óÅtÆxAæÑýÌ ‰Pi2âEˆ¦‹.䥢‘‘n¸á†èóþþ~¶nÝ:k+älÚ§³³“îîn®¼òJ)0&43}öÛÛÛÙ¼y3›6m¢½½ÑÑQFFFèéé¡¥¥eβ8m¬FäSh$&{çú¬WÓÓÓÃúõëéïï<ö¶lÙ}>ßò:ßí„z°ØsÊ©ÆU šÿNUXw1ß/0õ;FæB£Ì)'[‡NW6¡±ÆA˜ µžåF˜SN¥3š‰¼ÎW»¦3Æ B3²Pë>Ñý,.ûÕ»ÂÂ3::[³f͸¨··W9‚°HL&"‹‚Ð8ÄeµVˆ´È« Œ§r1ÕB<\³í}#Ââ0‘<Š, Bc!c§ ÌŒzÉÅd²ºuëÖ9yÔÖ«Ý‚0iŒšè9ÙE£Èk£Ž¥"‚ 4"¡"‚ ‚ ‚ ‚ ‚ ‚0R”^AAAAAa Ä "‚ ‚ ‚ ‚ ‚ ‚0bPAAAAAA˜1¨‚ ‚ ‚ ‚ ‚ ‚ LTAAAAAA¦àÿ¼q³Ùð¶`%tEXtdate:create2020-03-05T16:38:18-06:00n;×+%tEXtdate:modify2020-03-05T16:38:18-06:00fo—-tEXticc:copyrightCopyright Artifex Software 2011ºÅ´1tEXticc:descriptionArtifex Software sRGB ICC Profile †2tEXticc:manufacturerArtifex Software sRGB ICC Profile\~=Ÿ+tEXticc:modelArtifex Software sRGB ICC Profile1(‚¡!tEXtpdf:HiResBoundingBox1584x864+0+0û8²ùtEXtpdf:VersionPDF-1.7 7ji»IEND®B`‚blis-0.9.0/docs/graphs/sup/dgemm_ccc_kbl_nt1.pdf000066400000000000000000006271311422157504600215220ustar00rootroot00000000000000%PDF-1.7 %Çì¢ 5 0 obj <> stream xœì½K¯.9–ž7¯_q†UƒÚfðŒ˜°l+{&´Ú Hn£%ü÷ÍŵÞgñÛ'«*³ÑÐHRK}6“ãÆÛÃw]þëòuý(öãÿý?ýáúwóÇ?þ¿¸~Øÿýoÿø‡?_í*?þ\ßòãzú,?ÞÚÊÿöø¿þÚºÊ[¿Úûã~Jùzîÿô‡:žúõJþoJž«”õç_ûQTQ~1~üX÷Þß·Ô?ÿãßý›?\ý_¥mfÉ5¾¦ÝÈ/”톳ÊSž±ÞÌ®ñ´ùuϳJŽv¢LíèÏl§Ö«|µë|FJ²•E;ü™íØ3>o½üüõÑþëzUûƒÆÿúûúñ?ÿÝú´Ï«þø»õ¦ý?þ¸ÚýUì]Ü××z·?þîŸþðïÿXÿôç:¿Zk÷ËÇ?¯¶¾Æ=ÿØÿz…þÇû/U¨ÓþÝÿÃßýÛ?ü/÷‡ÿóW¾øu•Uåè%¿üÔs¬[ÜÏWéµÔÔ,Wÿ=›RÁÙTVRSg-šªõùª×ÑT|4E%š:jÑTï××óMEÁGST¢©£MÝc|ã]©à£)*ÑÔQ‹¦žûýªíh* >š¢Mµ’ÅjïJgSYIMµ~k§}ïuñ¹Ì\ƒt}ýÝi?;ןçz}µ{®þ§õ_¯¿Ô ‹×{¼Ú÷žÿ½šêµ¿Õ\÷zßÊ_joüÆzßÇÕç`ú÷?®ÛÞÐXÿï?ý¡þø·¿iþåsVýiÎýå×éç<üëCô[+å붯ý}íÛþÙ>òÓüÏëYC²ùþ7ªå«×:ÿø¿þ©½íiüßþTÇ×ýÎùÇÿÿø¬Y¨=×sÿñ—?ýù-_cÞ•Wä—þ=dy×Ä»úéõ®n:ýVþS~†Ìþ߯ýÇúÓŸËþs¼ÿþYïÿ±zûÿ; ÿþïÿþøëüåýí—ÿœÿ—þµNàŸ¿ØçÿñŸã‰m!,ïûõØœyݶ¶Å@­ö]Çü*Ö®k½»¹>ã»^gÛµ®s¿ë“¬³ Þ¯Û&ÐÑõ›µÆÙ·êãëí» w›hæõ^_uì’Q¿ÊªS{ÝË×*x¿úªÒÚúÑ.¸o›f[·ÒŸ]2ûW›«äy¿.ÿѳæÂjsâó5ýfÖ«Ï*Y¿~üWkr˜6»®éeÔÒ¿®Ue¬—6½äº¾îæ%W÷’w­~«dÝ^Û—ªõ¶Å`Ž'öõZ•{ÝÕ¾v]3s_/b̶f!/y¾lz.·½g+÷W³¹x½ç²_D½Ûº­Up}M¿ÐÜïh• k—<ößæ}U{Z+yî¯k½¬±ÞgÙ_¥¾íë¾¼Ýn[ÿX_cýhÄZYc§zÃsî’õßÞõBïõl~ñVÛW·õÃ>²ÿª{‘ón«»ß^ò¬þµJÖ ûÛúÐÓê¬E ïçlc X[aîbsº•¬Ýö.æþð»ä±·½W¡¸Ÿ5}Û-ß՞ŠV'+ö.Ö;Ž‹ÛøµVÖSùs¾ó\ÝVI_Ï×íUL}ßn/Î^¯vxIÝ»§Ý°¼n½Áêhõ¹úê‰ÕêÐÓ{·Í޵³ÆÄ~ò>Šý·]ç^2íg‰ïׯÞ//X¯ ï*uù]²^®UYßµíïÙŸé+»õðýûÛí_«äõ3Jµ±ºïxzÁkCu¬‡Û¿×Î~¡{?÷¨}Õ{½ÆÇ[i6÷íîæ*x÷X½m¬z+}î±z¿ c õ¾_ÖzEþ«µ]|w;û¾wÉ»GëQgÞ{´Þ5^ÄxúWµ*kTtox]tîýK³¹KÞ=ZïþÆ·³Ñt7ï[þT÷š£ÊÞ=ñ¥îµHÚh=~µv`ol•®Ýò½vº}øÕýß½íájwßÎ=.®ã‰ïbÿzÎû»×D³‡ëЈ¾×ðßÃÕ^É~Nûˆ6\ûê«O”<>\×4è}ô^ÓÔ¯k>ð)r–æãu͌ϾÖ\{þwžwlëa¯þ.úny®p×lgMT­cqöãµ{WškžòájÐ ÆðÑJÕܬ³Ø²’õ¯Ûrù•×4µk‹:×—ßcµÅä<ߨ‰®Ÿ–ÝIls°Çê}ÇDö¬™ÑƪõKŸö ‚öXeæxÖì´Ç*“ü³f©=V™zƒ³V7ü¬YjÕ~GŸxÖÛßcuçk¿«ÇÞQó_½Q2}°®¹#êÌîƒu=Åðûyb>Gtœçy}°®û‰:ïôѺ~íWK÷áºÝoð½ê®3`aøÒjCÜ_Æ[§×óoó•5§­·ûʺ¶œ1‹¾ýÑzǺùŽ;Fk‰Ió½{ŒÖ=‡XÉôµÕ~¥’ׇ«m0¼äñµ5Gýûúâʨ¯¥øâJUòÚGÚu¼àòµÕ.µ«–ê‹ëÑLóÅÕêìQµJ|qµèUz,®¶•ØÃ×Öµž\Ï.¸cm]£8¹cmÕ"TËôµÕ¦™=)ÕòÄÚºÆ@ñ†ßX\54WI,®š‹Ï}q¶ÚW_û¢¬5ÞÄÚ‹Ä`> VI,®ëÇØ%-×ÕrÝÝ6Ã>·µýàkæÑÚ|F\%Z[«o"êuûÚºª>ÞuíÍnoæñµuMîÓÿÖÒïsõ­kAØë|]ÊWÖ½ZçûÊ»“¬’XY×$³ÇB­5VVmkm¾²ŽµiÞN••§¬ëªcú#ôýÒ눕uýz µI‹¥Uû¶UâKë oíýñëóÔô;|bi½ôêkë(>WI,®ë~öÚ_[ñÅÕˆc7¼¨ÀG«¶Jë©|q]¯¸T/ˆÅõºânZ‹Åu}ø½¢ÔÖcqm1ðj±¸^] X\mœø¯n_\Çš¼K¶é«ë¸bm¨m­C³úÛ™^ç‰ÕÕwùVòÞ±Ž=áú݇k‹­ÈÚçÆêÊûêW¬®«dì'í5V×5¶÷&§ö¶W×±–¾ÇÔcu­±@TÛÇïÍðz^eøêÚ×ÛñnÛïX]‹¾LŸ¾ºM›«ÄWסÙwíÃ}uëyÇ~òþúê:Ê”vöX|uo¬«ÄWסF—¯®cM5^P}qíoHÍס-Â*yö€ÚŒÔÑ}yÓVÙÆk7Äñ“Ð{/¯¶™½¼•Û—×Ñc_VÇÜë«ÝBÝo‹C£Õnk÷;(í “ýmœ$¸zOý Ágí­œ¬œŸ5ú‚ûœo[i}}w\svt‘àZ ªÏ:"Áµ#Š*\Ð+ö¤Á‚g‰³àÚ’Ž•`ÁûåG‚àýÚjï÷â xÛâ×£œ7Ëz³A‚÷»×ÁÊIðÞK× ,«/ø(x¿¯ž[(Xx{‚…—%,z„ËúÉ-Xpõ Ø ‹­Ç7DZ`ÁkõýÛQ+Xpu™hY,˜ Z;Á”Á‚—­wÞN°àå[[àås íü¤D$x­ä '´s'ÿä"Áõ…âf„‚vé(ðÕʶåDÁ«é#Wï-s  Œ`C_­Ö»W+‚«¯~g¸@ÁK34(xÙ î  ^œ3³ˆ/­° ½.ïýbAû ŽQ‚k´GW ®ùK8(xéx´Ïëø ¼tz$h­øð ÚœW‚ ÷Z•oX$h%õƒ/†¸HðÒz òé‚ö²>8Ð:‰Ï.âÀËúr¡¯Töí¼#‰í†}dŠ×T$#´NÑ‚ /­ã`ÞN  Eí$Aûˆsü f· f· ž%Ž‚¶ˆøD+\óW@¼PpÍ_1¦„‚Ùý„‚ö˜>% óÁ…‚~BÁ1BAÛ‘û$%´-ùå%‚övþ…‚—6E‚¶>$h?ò%0HÐ |Ñ Úý9˜ æ…„‚Wí ÖX(h#úq` Ì×%̇ ® 6NË„‚ö+?] ^±3‚¯g¾àg¾€ ñË ½›î? ¼´§€/¶SA‚v¥þA‚Ö+¼]'A¾7$xi=†í7¾! ^œHþ Z‰ƒ–Hp­„_—£Wà¥gHÐ~åÔ)´ãoK$È, Z]ß¾ /ˆC(HóIíRÎBÁã–­•âw,xik ÒGA+¹šó9ƒù.ƒÇ¯é’À Æ,hŸf÷?XðøQ° Ó,HÄwøbÁ|;bAz?,˜"X0oG,˜=.Xõ Ì» 2À‚ö¡‹Å‚v7Qghu¹Ì1#´øÉ‚Œ`Xð¸V° uEG\± “",Ȭ æ° ÚGûêÁ‚6b‹ãX×úúF/ d ßÜZ^/ßÊ‚WõëN­­CwhÝØèý¶¸‚Ù…9‚„Ö¯ýChKžŸ¦ˆ7©à@6ˆpàuÅñ' hû?Á‚6Ñ‹÷á @›\ßV¨ (I ¬=¢@6P ‹/Xa[Q c ¬²¤€k ”A5Á5(Ðú¾ë¢Àª?(°‚?¢@ûUÿP™ @Û¿†–øJRfç dEÙò$>ÜŸ0PÊ@’ *°HÐÖ­Î@Avé `Þ±PÐ~Õ?ÁºZ“ߘg“%‘$¾·êˆe}‘(IIxI{¯Ÿ8ðÕ(Y%8ÿIöûfj}æýÐßÐü“ý:%Á~öì?NôÓI‚ЯÈlEäWž˜s“üØT‰ü FŽŸã$¿˜äüP¿ÕE}ø©‹'ø±¤B~ð,äW‘ý.–fÐ5_ègíx'¿ÔD~yÖ+òKûÔ ?»Ðü0 ½ôVêh\è—%ô»Ç‚ûRð÷]¦Á})j‰ûRŽ÷%]'•2¨ú¥Ú„QýlMôÃé@?ÎÙRLTuô;®èÇIÌ!êe ý.ØUèwÈyˆ€Ú #‚™B¿KËDŠ€km¹ÂDT" ãԽɀœ!¤ ¨]uÊ€k£é¿’ ¨éõX§è¯T:`£t@ÞŽt@Õ 0Û•Èæ0Vâ”Qñ‘Ád@íRLR2 ½ øcbHPûqà¸GD}EL“¨ˆ^: ¬"RÔ¹2`ª”È€\P’: ß!0‘ !06˜)2ª¯0K!ð'ôË/“B >0B Ý %0Û %~œJ %0#%”@%Q…Èy J c%ð( %#H”@LôWXðPµ=L%ÇB ÔB„˜ Kä¢2Q¹””@V/”@ + œ%"r!„ÀlVB ‡#|q„@ #yn„À¼º„@N©PÙ:£b‡¨“”ÙM#Êü+k©{¢Ä—WµÀ˜R d¯Š¨9;¥@x)P+ZJ w’y]Hù+IWÚ€j¥I2%A Äü)P_)P°„˜5¤ª¤6¢jL§…Õo66)ÂrÒ³ÀùÏÞýí—–¸ÞyýÔ㔚g±ý|ØÉöóRdûù|§¾³N˜fË2ÿ|Ø+Éüó¨æŸG§¾£e™uœúÎ:ûî‡Z`ßYecßYűïl×±ï¬ãØwÖqì;êöu‚üÎ:N~g'¿³Ž“ßYÇÉïxˆ ¿³Ž“ßÙŽ“ßñ–ƒüÎ:›üÎ'¿³d“ßGÁtcJ‚üŽ~!òH@¸®‘}˜Zòé ˜ð%W@¶n¸†ÁBzV¼å pã ˆ¿%®€²ìOW@(WÀK¾Mø¢ïà ÉgTœ×È}ôÜ_AF>é ˆËž|Ñ2ñ\Ëw÷KËV|ñÔƒã á ˆëi:êHg@fœmÏë¶›8ê{â ˆ #΀Mn›r”*΀G‰»+`L‡3 b4¤3 ­áΘÁ~8…΀2ÀÃ=œñtNg@_ÍÓY_ÀðèIW@Üq2lÆGIœq¯Äp„áœqäÄPX,g@§3 :9΀òH‚ûnÛ÷9ÁÉ0Kä (ãµt΀,q8:6ù»á Ø}W˜¾€tQ|W‡ !P¾€›â (÷,|³Š|™5å (¨tÔ÷ÆpH&Ç*rE'W@w¤ÀPŽO阭Êð»ñ'­¦` Ïít¬á5™~€&b9½É0æŸtÌ÷ÔéÀ7¾Ù~Þi¡)/ÀVty²-Ç ß$¼±eÄ P¥éhcèÃöÓê¸^€½¹†…àU¤±É P^Føbš—N€º¶pÏÜ—>}óÒáH³‡ `‹áˆL'Ú·(<凄 QI°ÖTÉ$é¨K¥ .{鞆 Ѐ`þJN€fNýé(@/ñ «öÃÐ}po„»ýᨠxà¾`øÿùXÊÿO•ÐÞH;ÌÀ½{lúÿÅR”þŒ áÞ3„{æ‰édÂ={¤ëÃæÓ–ãò¡öÙjŸ-µÞŽxohÈ¥ûŸN pÿ+òyîõ[g*{Ý|sœÊ÷ƈ—po¤´¸g»…ï¿ÁÁÞ¯l ðþÓríuE„Hï¿!bîõNyÿ ôÀÀ½þ\rí ÜØãþ§¥ܳ]ýÉýïþ0ûlC§{Mq•À½®^´×CYJï? º_6ä}ö|?:Ç™) o–ûòNM.”½ O2u¾ZÜ0êœxæ)ÖKš†´Wñ¤´W9Y”´‡Ú^Õi°Ù¦}=¥=Bk¤Qg ~J{#íÍÎö²°êLMi{ù£Ðö¹´ íåKÛ{†ŒC¥íé˜3µ½W>h{´Œ¼‡“?òÞ#'Dä=Â: 亮žä=ìm‘÷žø¨{Ù°Ô½ùݰó",‹Ô½GŠ%êÞJHÝ›òBÝ»¿1Þ~Çao)uïŽr<üNu÷†z¶¯ #îÝ‚Ä=m¹Ñö2ŒŒ´½û»eçBØÉ!îÍ©„w¿åÄ»õçe¥ãUˆžx·ëøËs¼ÛUîïv•¡]l9:«8ÞUœ‘VÉõéà·ëÌpç»Ü7ë8ßí8ßm“ñr{9ŸÊùî¬ã|wÔ‰•×q£¿à»³ŽóÝÑNðÝ*!¼ŠóÝÙÎæ»³ç»³Êæ»ã©‚ïÎ*Îwgç»]'hÎùî¬ã|wÔ ¾;êßuðÎ:x‡a~ÞYÇ ïlÇ OÝ-ðî¬àxG… wû¿û1AÀÝy‘Mw»Gø¡EÐÝÑk‚îŽf‚îÎ:NwÇóÝuœîŽo«¨›/ç Aw«$ö€»³ŠÃÝGÉ^7wÃí4ê<šq¸;äpw–¼“±æ% fÔŒ³Ýñ›`»³d³¾@€ÝÑ‚ƒÝY>󼕻£Ê.óÌð˜Ï‚7†¨¦™»£ÊÛ¡AS%\æu~&°;ë8Ø%5\æ9ñ²;ël´; í¸›@»ìB»ó7Žvç…íŽVœìÎ9Ù?r²;êÙ%Nvù „v{\Ô3¾ËYÇÙ.o'ÐnÿÈ-ðíÎK9Û?Úh—S»Øî¨±ÑîlÃÑ£Ýqsvǯšö,™1D±•t´;ºD Ýù+G»mB»ã¥ÚuíŽç ¶;K湚ŠìÎÛ{µšò˜¯VS]ÈÙ.—WÁÝÑŒÃ]Îg‚»³JËÕô=ƒ»×¸;ëŒ\MýeÜu¦VS®åpw>ãՔ:ïÍX !Ìáî,¹´š‚e×·ÕTtwôk§»³ çjúÁ]Žû º;¯t7kN­¦åG²ÝÑgƒíÎFÞ\JývƒíŽ_Û¿ ¶ËMØ.wb»ã)ƒíއ ¶;¯5´šR²Ùî~PƒíVÉç.wçoNuU)¿Í¥¯üŠKß¶]<%>p³Î)× ™uŠI“þ®o.}yÑŸaMènA-ÉN¡>‰YF¬OøAô×± "Öç#'tb}¾qÚþÙ ‚ŸÏìSæþìU!ƒ}êÜ™`Ÿ2+ÈhŸŠEÑ>ßJÐ?ŠÄ¤FøggHïiÚyãzB´Oy›f´O„áß¡Šö)‡Š ÷©Ã¾ ÷©Ó´ ÷‰2B¸Ït¶#Ü'XîÓ|ÁÝ–Sá>±Ñ#ܧBVe¸O{'~u…ûì,@#Üg—G¸Ï5ï;§)Ü'zá>ušá> H¸OžkÂ}ˆ’øxH|CfhH|G>i|D[“#¸gGÎïA^Ži|ÄADã# ß-9(ƒÒø¤Ë ñ¸òù‘䌠Q)ñ)Ô#’Ÿ"˜¢ðeQ¢}>òôCá“•f*|Sº >Å]AàC&BàCrAà3ßÎÀ½8”#øísk¨{©ÂIÝSIuO“’Ô=‚Y¡îá1•ê^ ãO‰{2÷>µ=/´§°…H{ƒèQH{LQh{œ»¡í)¬ˆ´½>#Ý¡íJBÛc¦CÛ“Ô¡ív4Ä=°§¸G„S©{• îép7Õ=z¦º‡k·Ô½—Z†ú”ý#ê§”¨{lSêÞïÔ½¼–Ô=âKg¨Ïoq>kmÇDÛË(£Òö8ÕÊ8ŸÖ3â|JûFÛ#€(q>ý°7¥½©è8h{šÁö²YÂ|6æS“9ò1½RÞÓ‡BÞã=Ã|*Fa†ù”ìF”O¹å ïiÖ8Â|*´`†ù”ø!ïÆ\Sa>³áŒóÙ>>‚PfœÏ° N…úˆó.º©ð©÷q>¿q`FÆ=â|fTOÅùÄ8Ÿ‚4¾‰ö&oÊ#î ôY>œúXDùðfDå#¶ T>žœHŸ„ÄDåKw7©|ü •Oî#Ôgùðê»ã¬3E>˜¿ésÈ#E¾©x—ˆ|÷-ËOT>Z•ohJDæ©R‘>ƒ%ô ôEúä£ô¡¢ôÅAuFúT¥Œô‰”>[eÆ kFU¤Ï”¥ôaŋ҇ŸJVÏRúÆ[¤3¾i:3?,;GÚR†ÔgÛg·1”Ô74ƒ õ …—Ô—R?‘>‹bõJê{$ʧԇFZ_פxDú¤Ž´>E¡>´>©•’úˆ;J O:\úT3)õI]“Ò7ij(} ”¾áÛ™úpa–Ð7ŠªDœÏWŽÐè|˜4+Î'}VJ_ÓDõK&gjæ”ù‘wcí?/[3Á‡JHšô—UT_¤éþé–šõÊqæ É’Lo¤²È8Ÿ™Þ¨YLÎz¦mÊ’£(S;ú3Ûéͺޙ¶)K²•E;üù¯n©­>øØ»ø×L·4Ir *èŸöïLòó—oæoog~G>˜ï]Èú‡íË?*©©Ì¤¤¦ÎLJj*kESg%š"“M™”hŠZjê¨DSdR¢©#“MQKM•hŠLJ4udR¢)j©©£M‘I‰¦ŽLJ4E-5uTbh’IIM™”ÏÔŠ¦þ%é–šY*Ù¡ëÿH·ô7Ò-ý–Ùø—ÏÙõ§¹÷—_¤óñ¯Ðo­üîLGv:tÍÿž‰ŽÖuþòŸ³Ø~ôµãùã“…™í¨þílGÍ"#ì3нkÕ0±·*K•¶Vp7dÝêZžmG[>f•XUʶ[Ó¡Z³K÷8ŽDíõïíl‰,ë¶«ýkýÈ÷-­=Å7œ{ž]ÎØÊ^jtíhöVV[ÇÖý<-ÐWÉk$ˆõlë×ô˜õÚ¥®»ï³>NTšÙ;]óGÚ®’×7²b©µ¯žaZ6!­}⚔ֺ^¼¾™^ÇÓí]êë·3¬÷GZf¯m@÷ìA›šíÓž™e¼ŸÊe°Þ÷¢äi¾·vùÝÙSÙÆ¬›=åÿ؆ßû>—óo;̰û4ÕmvNòÆÁÜÞ6û> aš™Á=Óá}-¶qßÁžU÷cçXë!¦‚ê7ûŽÎžn¿Ýlû¼ÑS¡ðšš:z–m2©=[2v³£ðhðŽ£ºfÖËûÝ„¹X3Hðœ0qLجÃìS‚0½jvgdÜŒ/7y*^FÛcûMÜñ&ö‘ì>£Œ“âf¿·qJ&’f§)6N§À©ÙÁȶ/qÆ×ì3Ú8µS ÿÀö–ú¹ñ_%ÓÑS°mÚIÖ>ýˆÐÙkÕ=V§Œ&Ú´“¬W:Û¶–\u"àÖ"»áGEq²ÙæØ7¶ªýµÕ_¿‚°÷é×*˜{¬Ny¯¶éçO}»MK's<’)—Ÿ y·™ëõÛ`¢Ž5à»Ö7QdîØ\ûB>MØZ1#ã”wãDzv÷ ¢mM®íüTe=þaž(ÙyöËòòØYÖ{öœçî>\jeÍA×®Sšã*y}¸¾qvÙ,ÍÀóѰ‰Þß¶wHÛ¢›U‰óïUðúpÕ m{-ÊÁudÛhoí>\E«ím±|¨cGY·ÛúÞ^§ßžŠZ×^;ËšþœÛ¡eaúe‚×>$ë^dzž³ãæì'ßi) î]åŽuë]ãÿêþX%J¯!½¬‰ªtï\——¬ùhx»ÛNvÍá¾qR¹V‰­«{ me¬—¶×ÕU%ÎãúÝË †/«¼ôUòmm÷¥^n_VoÙ8ö2}Y½%¹õòø²:¥ãö0 úƒï³£nÎ}úûÛ F7'Ï}²ûNäÝœm}¸†q7/î§ý­ï(îï1IöÔ¥§ Ý¢éÖ™àjÌÈà ›éìu|ß~ݾ´2>×"XŽ¡ØÍbrë¥JJÕ¯§‡^>/}ï=îyŒÛ-ªÒ®:ˆî¢oçŠÚ= [ü°=\%;uÛ±ìá:#M·N~°«û±`Q{¸ê,º[Ð6_]CÙéÕfÂç|éuÄê*1´×[«ëÐÎÎÑîë×z|u¥WÔG«kìz}}uÕ!_o%VWM0½]œö´´Jbuõmí*bqÕafoM‹kD°ê­Çâ*E@ÇûåÜÞŽi¾õGõöv·pÞˆSµÞf,®|š6®OÈ0½=Z]»ÚycyUb¯Þ‹–×ÈO³J|y͂˗×&«½×½ºh÷Þ´ºFD¢UòÂi¯T½÷X]uö» buÕakïw¬®Ú;w˸yÅëê^gÆêª|z½?±ºV®þ®ZTº¥Í{Cö§%VWírúðT»d zk««vj}'ü<“²usøBRõû±„Ÿ~²Ó} _^¥†tóØã•ï9îðtó gÌX^óîf,¯: îÛÝãþ‘*[o,¯±ê¶ õSÝØ|v;ñÝÃUŽÝÎnm¸†½ùÜõGJÝvÎ%œ&÷b·cþqf¹ëvºü†Ž½·+}oy äøÓí%ÙpíšÄ­‹·î§¦þ†mÄ=÷÷øâ:´²wÛ†î½07üúâÚyÁû`â û¼bqUL§–Ú+ o¯W;³Ñ{bàøÖI¸ù¶+0pÍx€¡càšü#‘0p-r@“àZÀ F$¸K|ß(¸3$x¿Ê° o‡‹|eE‚E=,ê+"Á¢‰`ÑHs,ì(h«õ ^ì¹D‚%º H H°ÈÞ $ (hÆLg‚—r•‚ÄØ‰ð è$´<(x” ’àB(x)^%(Hœ¡ a@Á«ÃU‚$KIó ^2k¯&‚  1ÿAÁK/$Ï$xÉÏ$F(HšPð’'9,xёĂDí ^`”XÀ|bAbþÂÐIó ^  ’Ú¼$à ,H¦X„*° ¢‚„+•ÉT@0_Ÿ@ÐÞÏI‚äIà $… H®ÁìARÑ‚ù6‚¶“õ³,`v|àÕ¼AÒÓ‚—„L@<á€à54‚—|÷Á‹³ õY¿ÁàÀKÞ}p õü­éŠ/¦oq €Äd €­=^%8P®F`à%;A00«’ ̯- ¼d{ æØÚ¥üðBxi;^ÊÓ^²ÝÍPs8ãòr„$/vW|0Ъøo‚­ŠoM„z7P ÈSB—å Àl& ×’èÌòú€À¼¸ ”E@à¥}[0 ݤW‹ñ>ƒ™œ/¥*„ òªÂ€d%/%„™ßaÀKÏ0 ³% ÈØ€/6ÁbÀ£N0 y·`ÀãZÁ€v?¾ß’ÑK Èä^:ð²¤Ã€—Ì9a@fðR` ð‚=—,Ò€ÀKg†@ s3ÈL zfŒK ³HnE9$­€h á°„€EçÓ ‘ë@@Âp‚€È… {6°DðRL¨d`y# Xd ¥…‰lÎ)D€Eæ5 !³ À¢£4°€âA€ ü¸g ”ù1š°(º=HX0°Œˆ? I`Q2h°p`#,LH"À"K°„mX˜_€E~« )LÀB§Y¨‰‹ ­!ÀÂäX~"À¢ X8dE_>ì|Òÿ)Ž`À}øs à‹ø¸>º„()„îC ¬,ÛRÍÖÝ÷™R[Øÿ"Êm° Ø‘͖÷/’GæÒ[ªz¡6ˆƒÍdË92°ÍH ìhiÀ^›âA€Mvñ€MIWÀ¦¨ã`C¯vò[J€MãìÒÎAÀ†î(‚À¦†@`khˆ-…Ç€À¦-– °ÉWlÊ'âØ´›¸MÍ€À†˜/lr\Ó¡ °É›l ¢æ3 k6y|³ A`‹$@`ã”BØ4õæË𕆓™#`ƒ˜…€Mo `¾1`Óæ ´vîlœ‰ ›¢MyÀ–²c@`ÃbEØà <ž" °éHB ØtXZ•î 3`“ƒ x–ll:x›\f€À£Ý€À£™ À¦0(°Éu äãAz((ðx¨ À&·(wu‚éÆP`Sô8(°)£0°é$ <šq lŽ0°Á1q«– 0°êŒ ÄÔ Ì ›ŽyÀ@† Ød°æ÷VYdƒ­!;6ðHØ""3ØJÄ„›ÎùDMñ­ Àš‚¢S`•» ØK lJS6/†Û…ZØbD VY|@U–,P`ö`M™/@°Ê`<Ú ¬²(+< XÁ1ÏÄUÎ7p`•©XAdq`•å>˜¯]XÁ|`™‚æ4ëbœ@°*Î) XD $« ˜¯B Xµe+‡Ášô ˜O*$y“@ðh&H°ê<ØIˆ`-¢3‘`•q$Xµ&B‚µéŠ/X$X™¸D‚_O$X9Ù V„‚d€Éå ^B P¼` à…ME  É“@ÁÊ|(H"$Pð¢w ÉA ^:e š`2Ý’ù¯f9ÿÜ{úä?6*ðŸfø´}f¬½â?2÷¤%¨ºüG 1°Ê¿$ýHJ5ð( ¬œW‹I³Véí `Õ‰ °Ê ¬œ{V¥×ë’hXÙé «|AÀªPh `MV ¬:ž«ìr@@+ñí¬°*xx´ÜµNé~„€Èw(PY„AÀzÇÁXA¬@@&-°ÊDȪ Ú J ¬ ¿°Þ˜ˆægÖ8s‡kÖù!ÿjxPAG• ¿š–¨AU@à_¾Ná_•ý…ð+ ÿòJù2…ù› ¿ì¢¿Š\.ú«qüU gÖgæüU¬}À_U’ëÔÿ°güU$Â`¿¼¸Øo³{3Á~•£š`¿*¯DØ/<Ø/oXìÇsoôË"ôËŽ(ô‹Þ!îËO&î« ì÷ULÄ}5õ·à¾*¿¸¯*–ÜW·î«à·¸¯rx"·üê,ªàWû ¿Š,ò«nÜW9÷UNƒÄ}VòÉ}Ug¨pßÑNpyXá>[CÆ îcO÷ÙпCt â¾ã~‚û*Ç-â¾³ÄÁ{ü˜f~UG'€_å:Àk~U'0€Ïø‘·ð³é5„Ç¿ãnüŽ’¿šZd_•Õ›À/ø1I~yƒ¿¼”À//%ð«œxøÑS¿ãG#T n-¨¡`nàÃ}2$IùiOÜWå¾÷U¥õ‚ûHù ÷‘Cî«ЋûÈçšÜ§-ÜG†\¸¯ÊàîcëøÁ$⾣羣qŸìµà¾€µ€>r@}5Ά`¾lTÌ—(æ«ÊYóUa+ÈÇ»ùàäóü )ü=qH–¼‘§Á=¢Ñ&î)©Fê~)šî)\âž"(‰÷òÒðžÂ-¦î‡ïA ðžÑ'ïi›¼Wdv*ÜSžFpïJ@î)ãWâ^±ƒö.­ÒI{rE‚öpÇJÚ“Ø´—¿íaú.Úƒ_D{{ÖO}œöämí]Xµ'íéí‰öˆz ííeI¬¨ €¾ ½f]æ¿ À{±à½CŸA€÷¦æ€÷ê8 À{ñÓà½ìÏðÞ´ ÀËÇ À#Ž!€÷Fôvøî™ß­<\ ÅwïZpBÐ ¾{éI¼©€9ÞLa0o>:pø“+7[xyÓâ{øÕò&¢• oʰÈ›:»äM)QÞ=8$(oÆv È›R®ySǶ@ÞTB ÏÂ^ɽ/\â¤È»_@þ~Êuøûá•'¿ÔÔäï§mTúûá"&Ê#h”7uŠ|øû©Ÿàï§)ÊKo¹ ¼‰š-Ê#®Røûᑊ¿ð‚¿>ª"½t|ÄßiI¤§Äéî§é9Ýý8ÀÝsÜýèè½Ã¹w?eáî‡ò*Ð#Xºûq¨ G€©t÷KsÖËVp÷ƒŠÅz7ƒw¿;6zéî—Œ&w?ކp÷ãw?Þî~Úü§»_:ëÝ hüý˜5Åz7v§r÷ÃýE¨7d^-Ô#®¨wƒIzÄ@õŽvåî‡!%þ~ø—àï'™2ýýäÒ‘þ~ÙN ž•hÊßoƒ; 7ŠöqöSt°tö‹ˆ‡éë}楮~:œÀÕ•W?YÖâêÇÍâê§`Sáê'«d8oðVÄyƒ=®~(â¼ô²ÁÕOËaºú)aPºúጅ«Ÿ"ÀyCÎÅéê—:œ\ýð/ÂÕO{™tõCÑÅÕOó7®~ŠM˜®~ý›«ŸeqõS¬GèÖtõK£N¹úÉ{"}ý.©Qøú±ÏÄ×/Û‘¯ʦho$ÿÉ×/ÅDùú)aÀ7d;~aÊð´€”«ŸØSž~é%¼×Ážà=‹?Z?\ýº&›tõC]ï¥S—xoŽ}¾®×Þø° øðïu™Q ÷†r{áU¼×“¨‚÷ìùß3Ï®ˆdð^O£Îས3Ax¯G‚:á^—á>¸×å_î¸×Ü„{á!ËÀ½–7¸×•Þ ÜëMŽuA{™X´×ÅÓ‚½†Þ+Úkʃíɺ Øë˜6öÚ…'`Ð^S_ì¥a@À^Ç.@°×+I°w<@ÀžG;IUïu@¯qä%ÐÃÌðHgàùKÀÛ&·¾kàU -ƒïš¬rỞžâ;N¥ÅwÄN¾Ã!J|w'…‰ïd¯’|Ǧ¾c ßEH˜€»Én¸#²ƒà.ºl7µÐŠí¶‹b»™þ…›íØ6‹íÌ!òý°ß|8ÇÛM}aØÎ6J‚íž$Â`»Gqxa»‰ŸØnú>è`»ya›l7#%h72ß|d ÚM\¾„v³+H‚‚¹4OúÙuöÒŠåra©X.˜´e,É ÄrÑÀËX.²À"” ’¡\¸_B¹oCdgA½J€]Q4À®Ø"¬9ìJ:!Ø•˜ Ạ5œõ|*:וKj‡¸Î6‘§ífÑ2 ×™]÷û¡ÞÜ3vé¥*°#@`wÔ ²+2ր슎)!»r¥XçdgVÅv Oô‘ïF`WÒÃ/À®˜8¡]ÂÑ@ÇÉ»Âá’À®(“®Àî,G…gw°;*ØågØå;ØÉ⺂ ¥¸®è|°+Jœ Øå3 ì >»»ÂÄ!°+„5ØNOvØìŠlƒvG3vùvì2t—À®0Tv·J]I£Ë»âùѰ+i`—ÃN`—\`WðÏØü>vE.\€ÝqÏvEÙ™sÄg —‚õaÝŽ¯þz­ñ(ÙdG4È®èè ²+±¨v%Í0ì ÛEÝÑL€] ç¼ ºç @Ÿ®Ë»וÃNÓÔ¼²À®4¢¯Ù EvǯœìŽKÙå› ²+5ÔyÈ®¤-§‘& Àî¸J€Ýq'vùvy,¸®hï×YoÃu9q=®+²•Ö-¬Ë.$¬ch€u̺`]~¹Àºì º£Ä±ŽáÖåÝëN`]‘ M6 £ÁuûÒþÌÁu÷ ÞØíp å4Ù\%%z~€ÝýÞ±Ùådw¿þžëî—€/›êîWfu¢ºU¢ù5Àn× QÏÉî~e¸D¨R[þ.Ix¿1•äçÎ!§´'Õ8£xr¦ï»l71$ú¥ý ¾{„ÀÃyOÄŸQ<ªô³pÝõ3gk‰@ž¨&"¿¡,'ÈÃQÁgq‚?rŸCäÝ&'‡Ò¢¿ÿä©$±Ðß-1Fð—Ú <=SÄ MqÿS§¹ÀßÀ-Fð7â'A~ƒÝ¬ÈoÈYò©Ï)Žç%ï9¡Ÿ?=ÐOQ-@?üÊý&îBb¿‰Rì7‘zÅ~3û‚ýRþûÍÛí;@¿I, ±ßTRžTõpHEÕÃ] U8®¨z‡›žT½;UT=?cHIOŒ¤w8é…¤G ÏPô”¦)½NXÏPôèeHzȨhz0§¦'É MoH'úetF‚xÊ“ô›6&Ðoe QOÖ)êñàB¿ “Ä“P³ˆzœý ê …¹ ö›ÊY•A<éIõñD¶ßì7 Õ$ö›„:ûMì¿ â©ØZÀ_~o‚x* _ªz„­üMy~“²‚¿Qñä3þ²; þòÝÄ3ï'àoj“DÏ|ˆ€?»à¸â©YLì—½Mì—cLì71ûeÿûÝrYú¥š)ô›Ê/úM…rùM¼‰à‰›¦È/_ !<ñ"?f­ áÙ_Å¿ŒžÄå „gŸa §ž×Bxâ"ò›êú™}Àû~6nÜNMè7Ùj ý&áòˆáYyQø7•.ü›֚国 øÇÿ&Ê1<ÍPÉøÇÈþü‘„½—9þgüdÃ< {hY{D>ÿeôՌᩨ5{„æœiäȸgB¢„=…ʅ픵~{æN4àÔé'Â^¤;vTôZøoê þ›i±ü7e´”²žbÞÂ3-6c]E_þåC ÿ¦‚"¤ª—@ø7uØ”ª^Æô”ª§9 þË[ÿeüÚà¿ 2KOÙ@þÝ„ "‚§â-¤¬Ç¹< pKOB—¦¬—@ö2:þΞËâ¿/DðļYügaÝ?·Œ4®TOí 3€'³Rêzò1þ¥PŠ®§ 9…=,çE€#EºPöÒ¦e>H{µéâ’öˆª‚´—š¡´=L¥í) ,Ú^ê­Òödrh{Äë y¯² }OÖP™¼¥àIŒ†…¹øÈfqït}óH›¡RýåEUø$1¶z^gŽ,ɤA*‹<ü™Iƒî,éL†”%ÙŽÊ¢þ<Ú±„¡ýL†”%G;Q¦vôç¿v£±3u_ObôS "ÏQÔÉÍò*üŽ$F?ùa1c,Áó‘eå{²þay"?³©­ÌO¤¶ÎEj+k©­³m‘ ˆ¶Ž E´E-Ú:jÑŠhëHQD[Ô¢­£m‘¢ˆ¶ŽE´E-Ú:jÑ9ŠhëHRD[Ô¢­£”$EjëÌRĨ¦–Úú—ä2òÆ÷/ä2ª-—ÑOñ×sý¥jßsýÅæ¾å2ú[íßXïûðúžGç{.£ß2)ÿò9Éþ4ÿò«cõcZþõú­•ßËÈ΋ʚÕ~5™Ñzÿ˜ÿüR ý­ŒFy‰ò_Çþ¹ŽÂÿÒGn£±ƒÙDf8•c¯Y±_Ç^zí­Ê¥tì˜^{Z‡çÃM;âÕÂ=Ì6æCèf1u?ïÖŸ¯mx×;ü|Gow„) SÑÍ*'ÂÙî½È°‰ýõ¨™ÍeÖýÛ&dF7‹\sD ûµÑgs%)ÎÃ6!;zFœŠ¬‚g'ïÄ~Ø–m»+ébئsŸô*ÂÆCìó˜aé»G„°x½Ž™.nÜ ªaI1·¿’œ¶‡ÑÝޝ¯·Ów*|ÃOb¬ÿãKù+;ä²:ŠŽ6ìˆ×£Éøž}õ¼Ýs÷Cyg|ÖÆo3 :ZOÄ} û·a~.íJ4sáÀÉÇûc±ë¯³;š¿‘‡}ŠÃ™;ÊÖº”îæµã­ÛM÷ë2¿œRχÚî=óGR[CeìJجo-Â>üsÚaŸº{ ó?ªÇò¹å]\<Ã6ÒûÑkÇ[¯ß_ñÛy¶…Ü6;¼ýWkŽºüþüöì\i›O†÷Ümb`ŽÁÛB\îqªÄ÷Vh¯¼·Û´Ì=LuT}›@ëÔV{ñaªÓàU2}¤Š5ï2Fh š¿‹Yþ×DM»->é¨R¯VÉŒølaw[ÈÕ=P%ºÞÞuTùH­’ת,+o Q»j¾ùdà¼Û"ÒÖ3ŠÖ½£áúÇ­þ#ËeQ´¯bïþ|9€xT¾­߯bz_÷í#UѾ«w¬-<«îë¹b°ÆTw›wíÇ`½Í‹sVù#ßÛ‹³æLr›ã¬Æª7c~¼{¬êxóÞ.Òçx¾kë¢-l'ï½ê½Ç”tWÀŒw×±WÕ­Aî¿o_T›\aï:÷¢Ê:q[8 Õ=6n‹ÐâC•K¿¾¨¶°P¾m©Ú#Uñco{I{¤êÿ¶£Ø¿ÍKj‹Ø¿ápï°aõG†»íéÚô9ß?ƒõñ'†Ìôv†¯©Äé»-†ãl>¡ï̽ã<¾Ç$°V6_T 2v[ ÏòþÈàˆ·Å'Ý£5ŸË£›½®Þf½G«©»_±ªÊ®âîÕWÕ*Á~•Īª½ØVÚ«8¸º{…UËÖm–üÛW_é£W‰Öp®»ÍvµD|œî÷3·L—±·nË–ýžS›Î Ž×eÖôÏãQ ö'Å×U¬_W‰ßr[Êí¬Ï u¯«U¡ÙïÑ|]­ŒE;J¼ÓÏþÝ×Õʼ`Y¸7Xkox[B£÷ e²J|i­’nóNðÀnu~[âuw×YaíÌ}e5éá}eõè÷N;ù¸—°ÏH–íæÚ_ÂðùŽT@k—Sþ½QnßûØÜf+ÞÃK}_Ù ß3ÉmSÿ‘±†n;ôßû_i;·9­5÷¡¼`úªjñÔ‹—<¹/öŠ~o5áv'zÎûÄü:Á<m¬ ý¶„oÛ__f£·ðï˜ú ªt›ccõRèÎ{ HáöíÝÑTäS_æç÷¸Â{|¿“þ滦ÿ·™³_ï8þ6ÉýÞy B"X%Ϫ—ü^ïùøÂjÁú}æo]÷¹pÅ#úü*ñ…õ’íÈ>Oó°aé¾¶¥5’Õ„eñ‚,_YI½±J|e½èYûŒbú¯|$<ÃWÖ‹AÇ©’Øà·f5Jô~{`Œ¢ä?M›ðßÃÆXü÷Äb/üÛ÷êÐø·J"‹ƒpe…9îTH¾÷ \ø×{àýjÝföÝ ÀŧÑ-E€÷«¨'A€÷›w㸺t؃ˆW‰°QXÌFç$ÀU'M‰·•¿® ÀUV`‘G¯pÕ‰M ˆ¥Hdu°Hº„±¾Krl àñ+GÀr_±‡6¨‹3€GI `ám ‹Â=€€ oßœ˜ó@`QZ9 °(£Xâ:A€Ež¸ ) À¢¸B`¡¯‰‹’B€vð]¢ÄWª¢\à¥`("À"‡*Ð2'\‰Ž€…“!à¥å,oäØó|D¨|X@ ©ÜÓxIM÷ö‡^Åm`@ÒCÀ€— a@f!ðòn&¼¤‡€¤µ^rÉü ¼8G^W,xà¥2˜7'$ùxÉ ôdàߥ=øwé|üËo"ü»DðßÅq™øtcð_>¦ø5Qüw…Q7ü—+ôæ¿KÆåðßwˆÿH0æ$䣀۠!Jb™ÒÁÈÁx\=ðR¨rðÒQ h‹ºïpE€Û YP À¼ºðêé¼p[xT ¼±€—ÌŠ€Z i™@²;€„£v b’G $›H#0_»ðb#/$_¨ìX@å+s‹x%i^²/™+€\GÈà/ŦI|Âd?P“7xIÀ/™Š€ù©€Çµ/ €$(I’6¼ ¾ €¤%É–’Ǽ´v€do Q’,̉@H&ðh'ð¸Ÿ@rº€ù€E¦`ö~à%3O0yà¥Àd`nƒ/ê‚€$/ـǵ/j€—ü+`À<ƒ’2$É%XP*1P®ÿ‰ Ö’ Ìî.$˜8Tzp`>„80ÜE¡GÀÀ"ã}0°ëÂÀ"… Üv|Žx%Ù,0°Èœ <~Hn#0°Ü~l íÀÁ@¶³` ½u?2Q¡3`áHB XÂÔ°°¾} ÿ‘vþ#üWdé ÿåQ„ÿðNƒÿ ë‚ø×¾ä?y€ýޤF‰€ÝáD@%……_Å«¦©pÏÉõ„ÀL‡x)!2 Â¢V6£VH£*\qŠ€Š$-0õDÀÇb9]KAM" N'!@Ž{Ñ›¼ƒÑ9 D$?؆ °ÉãÄÈ l ›€ ZÚÒñÁM§6ð_“  ÒÂÃ- C䯠¿.ýï'ø#gðG”ŽÔÿì/%@ÙɧøÆV%%Àà' P¹Â@I¤î©*JB*€oâ¥å¢êh(Àd¹PµIK, Pv')jÕL PAWRÔAUª€èب€Šï›* Ö©TÀ'U@'DÀ0¼L pÄ© NIÁ¿¦\u 2QJ€|» Àž\) P1”2 TT“Tåä’ ÃIصª¦H§ETÀg°kuN © P9¶`À®º©* Ù@@2q€ì·!À”ÉE€Jꦽ…°q0 4*_vÄ€M$Q…8°j» º‘Ø´á¡ °Êk¬‰—¤ Ksp¥ÛùéŒüü ÷?qr‚Ÿ‚¤ñ'Û<ÀAŒ?òiüÉNFà—böŸ:àIûOáöŸ²ãú‘ú)í?¿©kïî#Cä‡â›äÖ-iý Þbý‰Êˆõ§DOŒ?1âÂøSDiü á¤ñgŠaü™œ‡ñgùnü©ð–  ¦iý©|B?%¥õ§ÎýªRÙiˆ*ú# ôGn—´þL" ú«rF‚þ4ƒNüU)^b¿ª iþ)W8ØÏÆŠ#…à/ü1$ð§ ÷À_e£/øÃžDðWµ'üI\ öK\±Ÿ•ö’PŸ¹>1¥Þ§S0ô¾ú“Ó.irú“ýTB (ê«øØ‰út/@ŸL)ê júä¡|@Ÿv¾@_œÑ&óÉ^$™Oc>™O–ÝÉ|2ŠNæ“#N2®b>*'óI4täC)ùz,‘ï$O-!_•ÃćIćkȧ>œÈ‡1"ÌŠ‹ùH±Ì'8ùd,òÕÿ/V%¨ä£G€|ò°ùÒ,3Ïf–úÁ|<̇Kª˜¹æ;®-èÓ$–Ч9ÔgÏð©÷U„W¨ïjÒØD}´,ê«:\P_Q°øÔò‘FŸØ}cô)Rõ‘®/©i"¨¯Ê’êÃãê«iÆ*êƒÄ}ð¥ ä†@_þḢ‡©˜ìw0_ý‰ù¸aŒ>u4FŸ˜‹ùªÁ|ùPb>^˜¯ÊvÜ™¯rž(æ;Kús4¡=CÐWù@_MX“Õ狟¬>Ù ú*X#è«VŸœocõ9ãÀ£O@1i“ùàK˜ó¥F0NB .äÃJÈWÞdô‰§Ž¯*|'ÈWÑž„|žÓÞÓŸ2÷DÃÜS†iî‰Ö#سë" öÔ]ÓÜ358™{F†³´öD^“¹'‡ÝØ{jÛ"sÏW6˜{¾2•µç‹uª¬=9ìÆÜÛ6Ì=“þ‚õ.ÔS±Þa‚)sϳQ™{²‡ÇÜ3Å?™{Ê Í=Ÿô sOE*HsO6ߘ{*å{š{*šU˜{riÌ=eøŠµ'RÖžóX{Ê€*­=•f9­=ïïî~é…µ§Vë´öDNÅÚS©7kÏðÆIkOÅ¡‚õÒŠkO-‡ií)+•´ö^°öÄ”SÖž/'ë]8ùbí‰/Öžx¦µ§ kϤ?Y{"ñ‹õ.œ«±ö4@ù€½K›`ïúIì»pCNkO\áôGoÇéσ°w…ñg˜z*3Çaê)cY™z–ï¤wi[.µR.Ú(¤ËÚ2.¬¸ü1¥âò''™´õD(ÃÖ3Kdë‰SÆž˜?`ìÉÆØ“I'=õzÒÞSƒ{OÜà+f >’I$~ÇØ|2‚±ùLÄæ³á6ŸÊ½sØ|ê›O™½f ©è6Gš£d<7Y?ïUã­» Ä¤“¤Ã0^ÅMŒgæåƒñº¼a¼žÑU‚ñFžx#ù-o„—0ˆ7RgtÄã ñnŒÇñnÍ0Þ­°0Þ}E^?Ïò6¶È»yS–.PÞD‡åÝÊL åMC˜·»¶Ëy·g0oBD˜GXU00¿`9J…y“Ø/¼0½=Ÿæ+† γËNçâ¼;y·hW”w'zæÝÉy„d󯔬0oüdÖ9°æ Ì|…yÃâòF¾‚< ‹ÑVòÆ Œ7èåb¼³X0Þà¨@Œ7äm%Æx‹‰ñÆOŒ7t˜ã Å_„ñl¬„³`0Þ â‰o( +Œ7"1ˆ7ø,B¼! 9//%Ä ñ†‚ƒxŠE)»_x'¼º_^÷¿U”Ó ¼]š¢Þ.‰(3Nxg»Nx™%@ˆ·.¥±ˆ—¹„xûW¢Å/3ˆñΟŸw;÷éÙ·ó„ ç·K'òv‰÷Ù€¼óWyg yg3yùèòÖŸéÈ·W£´Âäí’넼³ŽCÞYâG®1^&€ãåˆñî{Ç`¼]r‡¡çôdˆ Áxg‰CÞ~é- =_O6Áú·J"ŒŒâ^f3Áx»äˆì²þŽfb¼]y›ñöÇí^àŒ—DŒ—IŒ—]BŒwÖyâè”SÙÀ¼ãýéíÛ™§YçñPAzû;øþ7Hïx7Azg;NzÇ× ÒKwt¡ÞÙòpwyõ ½³ÝéÞòÉq3¼åéÁzç¥õŽÖ;n&Xïh'Xo—„Ûž³ÞãEÎuMÞò´ã¬w\=Xo·WwÖ;>z°ÞÙŽ³Þñr‚õŽÏ¬·_Ož:ë=®yZ†`½ãB{»NDNqØ;ú@ÀÞžGööDp†vɾ¨—Ó¨Poÿæ>ûŽ>¨w|ª@½óŽ#Pl¢@½c: Ô;ž!Pï,qÔÛ%Wõö ú ÔÛ ;R8êe Ò;k8é퉢œ~}»¤Ÿ¤·/lꤷÛ§ªgÉl‹ÆIï|L'½UçRl'½cjÒ[uäs¤w¼ö ½Ur}Êzg;=VW…ØËEP°—«kÀ^®®‚½Eoäómuìíµtž²Þ¾ÔAÎ}÷üîܧãP0m¥öaC'LW#y÷… 0$˜K8÷±!FíÃ'¹/E8É}êP©÷aLˆÞ÷Vpʽ¯¤î}r¨I÷>BuàÞ[áSÁ$qïS†ôtïCe“{<Ž{âX‰Pd—“—|*lR:øÉÁ=ü`mL<“àäà1ÿ>„Dù÷)ŠÀáß'¹%ýûˆ#Ï”0å߇×~8’bãÉÇÄÆ3èpðƒ åà'~üˆÞ§ ÿqðË+~8¿8ñÀÆÓŒsýfðïÃ2ÿ¾P8ÒÊ3]êdåI$£ôï‹@‹éàGÄY¬<ñ‡ÄÊSÚ7~?‚qÊÈS9©0ò|D¦8ø¡ÿÉÁo|ñIl<åû‘~œãç8™x¦û~:!Ægb~ „‰çsËQP1>ek‹Ÿ¥óøˆñ’~·˜xr>„‰çC€ÑðïÃ&O7ñ<¸/L<±"#È'öt8ø= ='8øé¸(ü0K‘܇{þ}Ø—†Ø—WûŽvå߇3†Ô¾ž’%þ}„Ì”ƒ_êt¡öÙ¯üÈVj_OE0ü.y„Iîë)ºÜ—wŒƒß¥óXÉ}]¾ È}Ç•äáw59 †Ü×9ƒÇ«Y<üÒ`¿ïA>åÜš~J•ƒæ×µ®¦‡?å«Dôëß-<;Æš ò©… ¿‡ˆ£2ðä~ÿ¾öaà™w‡®„éßê"šF]©ù鼟’1ñîK Ëü:j(Þ}„ØKï>u­ôî“‘/Þ}ŒCB|ònñ™0ëÞ}èp¸÷ÙSâß§Þ‡ƒ_:Ý…æ—·GˆOvŸÒüør’ü:z$¿|&I~̆‡ŸBýJòKÏGI~ÇCÈ¿¾&É/+ýû$èãßÇ·’vÞéßW)‰ØÙàšüû0'Æ¿/Måß§3$Üûžöݽ¸NRüðO÷>P÷>ìqï›r“ƽ/ÃqâÞ'ÛWÜû2ìŠÜûnÅŠ”âÇŽßxŽSþ}€‹üûdŠ{_F•{_š„ʽOJéÞ‡_#î}éð'÷>íìÒ½iTš»…tïûɺÓ2nÝš_cÞ½ÏF¬;q Å¿·EüûÒ"Uþ}Ä\vÿ¾¡Ž-͇.4?¶ÛißÉú+ͯ*¬šŸb#ùµ0¸CñkÄ’â‡ëþ}Úð‰æXÓçGê‹Ç,5Ï5Q@£¿ø“¨¡ÿþ/Èz4m§óœMgIfRYdüàÏÌ2ôìÌ®·HI¶£²h‡?v^óLüxÒ(8Zñ"5ýkg<š6áØ{øMÎÜFÃÖŸI2—qSá§îº/yZþZUÏr“)äçN±ÓîÚAà‘«å[ß²×eö:j)3©¥3ÓQ´”•¢¥³-‘爖ŽeüH3Òo˜Ÿùœq¿OÇ¿üêØü˜¢u`~¶ñ»óÙ±E_kãÏüGkj:ò­¿~-ÿÑ*^¿4C•9ÿødaæ?ºÿvþ£­|oÝÓÓݲ­vœ`Ùpxñˆ%¼7?.…÷#hñ6@Øq‚e±­*ÑqןÓÍÛâŒfÚ¤}áIç°tvîì4˜eüÈp¤;ËûvÞ¥»u›Î‡¶‹[·… Ú¶ÂxîÞ|ÞuŸw¦á×κ­ÛÂHb. qã6𝒽ÎnÇÛKVgÙ罚”æ}w7nÓQÔ¼íµÑ~gƒïïaî9o;Üþ¸A;ä =Im«–màöèuYZا¿wo;ñü6p“íնñg¦°“`»9ªN픿n^h;Yô6oS¨Û9í¨ò:l=ç¼·ˆ—*«ä kÔЧ朷[£JõŸ¶xêq<>ç{¹ƒ‡ïÀ¦4·öÝ;¾ùØ×6W}÷|®æ¦¨¯[‘ÎÇŽ¸^7;ÞâÊ4OŸÑý±»—(0½¿¨µerKTYqO‹øÆÌ«àÙÙy/ù¯•g¸%ªr·ÏÇŽüî¤&˜½Äë°M^%'(MÎg #èiQÝe,îÞ«¸Ça‰sûU2íì+ éçë67™™`íã«[¡J!˜¯…nl‡…ó*™n…*tœ ¾öÃÆ|n è=_–é;n/î¤=MЧžÞ®ë{‰sîÈïçxß7¬Åc#°fìÖâÁXmö0•ùSêv^ß¶õ»Ã¬’7ÒNð«59m×ücZ{œj*ZKv ›q~5Þ°yâ1CÃÒŽ.ðXðÌ­ËZÃÑå1MÁGktÚ¿éìúíñE5k<{MÅ ö±ª÷ã7v6·×TÍ7û`UŸíîuô ‹’6Ï¹í±¸sõã¼fïëk’ºêG3£ÇX-ûÏ;T鈫äµûÜGñ»›wŒT}ÝþtFêãz·šuôK…Ýr¢{,“ø<ß”6ÖCÌ}Ì®ñŽ>³5¤UâëiöÆmSyŸ4zqª>c¦™ýô™]%±ž2Æíëi~'³ õêëÏZ³®Gûþ‹GË©Fÿx梁—Ûµ„í€U½äÒzJË×Óœ†ïºï!ݶž»µ¨ú²wßK*ËÄcF¶mœÝʰЪ†å}·¨±‚>÷ÔšªzÏ'j±ÏNÍ^ǨE‰îñI3–'>b‘ïÝÓ*x~¤WÎ3M>[°Œõïù<Óôß³Km<ßÊ4õ÷|•Ó6Åç­Ï{§X¿"®ìú{jpzœîN¤Ùp>¾ŽÊXçYû…+ÚÚþ#“ð¬ H÷—®Qù˜à{v5›Ç÷Â{·ô<&÷úR3¼F¸wòQž*#W{wòõŸ1ÏçÞ¦¦ôž]ê±=°wŽæ÷ùì|ê—bÿ>ÏÛu㾺½e§S¿4h¼_õ|³kžŸì5‰÷¼ìkÛ_®Å²7ÙÛ–úÙ¹rŽßÚ©µÏ¥æ•#§žëÝVâÇTÿ†gÄ¡ Óú6Ïû‘m:é 6×oMeË=n¢])}¬`nǺîw{é¹mƒëõ€¹! ™ÃܽI0¡³Ü*ðV7Ë­¿„Ár÷ó\±‹u–[az(–[%ÓGX°Üýh$–»Ù4Šåv`î'èn¯;«t–ÛuºÃ“³Ü*‰Þ%˜[%·~Õã\•ÝqÀÜý,‚å2“Xî~A`¹]âÈ,·KüËݯ¶Ob¹U’W°Üþ‘`°ÜÎúäoÔYn„¬Xn—8´Ìݯ¶„‚¹}íê¿r˜Ûu†_Êan—ÌæîW{jÁÜ®ãP0wÖq˜Û%qËÎs«$æ7ñÜñ«à¹³ÄnÿÊÙ7€n—ø³?Û­„cœ€î,Ù@· †s—ÝYâ@w¼ÑºûÕ* ¢Û%=o¯>»äv t¢;êÔí’'®Ä¹KL‚º³Ä¡îlÇ¡n×Ù·L· œ©ƒéÎK9Ó ;Ó¿r¦;ÞLw¼à`ºÌ:LwüÄ‘ŽÝ6«óMbÝQÅ.¿“€.?¶€n7ã‹^ÝnæövèÎ:tçÅèÒÊO@wþʉî£äõÁ*ç>Ý*©±5p¢Ë—%¢;«l¢Û÷Itg‰]~nÝýJ@Ñí_ù®5ˆî¬ãDwJ¬ù+gº]²‹Ätç39Ó­’8ÖÓ¿ ¦;êÓí:ŽHŽtgGº³Ä‘î,q¤ËùEH·ëøF4îü•#Ý.ñìL· šSŸ3ÝYeCÝYàPwt쀺c€Ô¿ ¨;î/ î,q¨;†žDË£ŽSÝÙ²SÝñœv¹~ìŽA`wtÀ»ãØu^_]©dwTq´Û¹ëÛ€ ´;ë´›%=VW:e ÝYgÄêš%w¬®tî@»³Ž³Ý1uÞ×zo¬wåÀ»³äŠÕ•–ïŽvïÎ’Ö³X½hÈ–“îŽI:è.gÿ€»óff,¯t€»ãBO¬®l´Ë¿ìŽiÔÈîèVNvgÁ&»£ vç߯uÇß뎻v¬;ÞŽcÝ1Å9×5½·i 9×cѸî˜ÁëŽ纳`sÝGÁûun¾‚ëŽk8×?Ù\wÖè¯nÛïÓ¸îüÁ溳`sÝ.x 7×î\w^ãíºñ`²ÍuÇEëŽÙ͹î˜;œëŽË:×}ÄÒ±ÚÑîlr£ÝÙdxpÊ?;Ðî˜ÂÞpàÌ·8 6Úm¸:ÉeG–"ÑÝ,n;tš(¨R-øQàçŠÄ½@©»Âp¡Ž )ÔG¡ÕUö~hu²ä•VG\!´:‚‹I«#ÔZgˆF¨#ŠB]ýI¨«? uµ¢•…RG”D”: Öõ8¹…RG´1”:"‰¡ÔU…%@©« ‚RWåŒRG|4”ºª”IRêð©@©Ë[¥î(¥®† J]•ãJ] ß„: [ö)ÔÕ8qB§#¾+:E| Œ Ž Ï©Ó)² R9Í‘êð%Aª³_½¡ÌÅÙ¢ ÔÑêªrÙ†V'&´º*§}´:ç¡Õ? ­®6dÃÐêêHi.g˜â¥X—º¡Ä:ž½N~ü©×MÔ¯Ðë*r®ô:¢õ¢×UYü£×UNU¤×)_Êu2ÈL¹N>b)×)p¬ô:bË¢×ñ\zqöR¯Ó‡J½N¯½ŽˆÜ©×É©<õ:É©×IÇF¯ÃÎ/õ:¹ ¦^7IoÒëôä©×É/;§¦`'[©×©gK¯«²¸E¯«IÏõº*ëUô:Æz]•·aêuêé©×é(½®ÞPbèuŒzô:>‚]•¥l*v 뜊¯ ÅN=9;åOÅŽ'•bG¸TWìH^—м]P좧`ÇÍ!Øù:ŠZGçC­Sš'Ôºã2R븎Ä:ú b‚'¤X‡ŠX§i!Å:y]¦X'Ó Ä:›ŠŸ±ÎVŠù)Ö)pUŠu²âE­“5Fªuy©ëò$×iâ@®#ü&r]•OÊuY"¹îëŽ I««´.µºðèJ©N1–Që‰ZÇò˜jµŽq€Z'ÛÔ:¹¤\§)½N33z]U¤°Ôë˜|ÐëËèu¼`ôº£$ÖUÍù©×ɱ½Ží‚›&4»ª|©ÙE&º”ì´sIÉŽÛA²ãÑ‘ìø4HvZ$ÙÙp UO’S*’|×R²ca@²“É’Ýqƒ’ìä€dzœëu5¼Y]®«²âG®ãa$×i[ƒ\'Ó,ä:å²@®ãI$×)›–äºì—Òëäiáz]‹’ëH?rÿÙÕºüü¡Öa7Zw£´¹ZGL_©uU9•Qëda‹Z'7Ô:ùi‡Z'µµNû6Ô:^L¨u ø+±®*Òbœ7$ÖåçX÷hÙXÇx–X'W‰uö9ê2j¸ôº:PC¯ãA¤×)LzÓ«ôº¬zkFèu$vÁîZˆõ7²¥É¥_ãä´ÙÇæRÑ ÒæR¶e€œÄä$9”H.¼,0º”AP‚œb÷bt)ë4ºT^Œ.¯èÖit)Œ4º¬2Åè²jƒ+–+˜±at©t„iu)O—´º”ÛuZ]* \Z]¶ùåHÓV—™PV— `•V—ZÅÓê2º1ºÔøK£KPCF—òO£KÙÓ§Õe‹2,—ö³X]*^]Z]Êç?­.•ª=­.-ÄÕÍÛšK Y /1´Åð²]ŸB]æT‡æ.esNˢ)殈ùv—|ƒ`¹KiÞÒî2Û –+Ø‘bw‰°XŽˆ–°\ÞI Ü…6.”»z 1‘\v,,/åž–—r³JËKpËKº,–—¼_¡ïF$w4$wÜNX^*Ä$WÐÐeyÉëÉ‘æ’SŸNÃKõ4@Ž> Èq3€ÜQG†—U+@ŽÈé¥Ãq˜ÕÂqtX8îŠð `Ü'`¶ã¸‚­f—ÊØ„Ù¥fŸ4»T~†4»¬˜KÆ]ÊŒÆå«ÁìR‰Õ¥¦Ð´º„£0»Ìû ŠËW#Š#Š-guæ©Ñ¿ÅÑû ¸"+а»ÔІâ˜"Dqù%…qL|`£’£;BrÇ¥dw)ëaHŽY”ËW,”Óø†äòvDrù "¹üQ€\t¹1p!]rÃâ¸|â¸+éo†+7—48îh78.G*f—ÕÏwÓê’*Œ£«‰â²]ýit™W ’³^íL!”Ë.”#:m^j•å²ó åŽkÊ0Y(—·,”ËW(ÇŸ¦—b’Ë^#’Ëþ(’Ëþ(’#‚rZ^f 9f /†9–ï4¾dÈeÉ1çCrùnDrì8 ¹ãWMëªz­Œ/á’Ë·#’ËçɥűH.û1Æ—<–H.¿U\þHÆ—2w ãK-¢9+ðúsÙæ²wÌåÓÌåÃÌa{©$®‚¹ã*3ö&ñƒ0¾”dà4—ó¾Œ/9Ùñ¥¶gÂ9³n—5¦_ò"d|Ù#€pî(pœËŽ8G xǹ|sùvçòûÈø²Fp/Œ/•^D<—/OÆ—|õà¹Kžíâ¹¼ñà¹|2¾ÔÖ>Œ/q¦ý%O<—ã%xî¨á<—‹hð\>IðÜñ“°¿”×ö—Jjõ+9„’áÜäød¸TÄ$Æ3©Æ…ÅvBœqUù8,_SŽC÷ Š«J$Œ§-)ÇiH9.érœ´ƒTää •ŠÚš9F‘ë´5)r:ØHEn„£B*rŠŸŠœ–¥"‡õ*ŠœFá¡Èqu¹Øú§ … §tO‡ 7%®IsÏ4Ô¸8U9ä8;ÉqÐMêqXM¢Ç5¹èI‹3ÔÔãxyèq Y‘zœBa¤§“ÍÔãFä§L=N'*©Ç¡£Çqƒ¡ÇÕO„ãv¥ÆéÐ,Õ8>,jŸ(Õ8µ"1ŽGDŒË’¡©Å ¼×¤ÅÁ¨hq\--ŽK¡ÅñÐâ䊧õ©Å5¹@¢Å©'JŠ£÷"Å]R7%ÅÑ­âFÌ)ň•RÜaRœò¥ÇyR\¶,)N*iJqˆ_Hqò¸M).%)NÃ)¥8 å”â8ðC‹SbèÔâ"ðÜ¡ÅéHVZω'µ=µ¸,‘Ç:‘Zœß”â4y§'í?¥8uÀ”â"M*q¼u”¸TÙ¤Ä)êʡą°‚Ç+N!Nû™úù½â4þâø(qŠ~žJ\^Gb\6,1.qRbX‚÷ÂUEL5NV©Æt” 5NxƒÇC Æñ†ã”R-Å8TTÄ8ú5bœÆJÛÆ¿¢ÄL(qiŠ'è@‰S†ï”âØl#ÅiõK)N)Å1¤â”ï)N{³”âx_HqLHq?\v|¤¸¼IqÊeŠǦYj–m!Ç é%ÇåBŽKÁ.ä8ä8-–ÈqÜ»ä8@Grl,9Žqâr\¶zìzœvÀr ¹‘Þr.ÈÑ$Èñ&$È1‰IãmJcR §^ízFz\]èqÌœèqä²äXÙ%È1Hß½ç:¾q!ȵˆ€ §Or¢_r|0 rHÃ^‚/\‚ýU‚ó¥9)¤à#/F”ÕQ÷ආo˜¸m(ÂÜ6=n»#•*Øv#8ÛnKTvb›…vûGaÛ ¶Ý2àµÝضµÝz§PÛ­ ÎP›‘YZµÝˆz¢¶û’ÙŸ¨m¬×WÃ%Ι[¤ ¶ñJ%¨m¬×çÏ-j3d6_b,iQùÞ†ƒlG@¶Al 1ÛàÁƒÙx-f)Îlcà’Ø64í€mCÉÁ6 ÏXN¹£&´¸À¶‘Fžm£†‹¤°mû¶yfPÛ€ÒEmãºd¹Ô6p(µYÿü´¢Ìûµ 0bSÛÐb¶’F“{éʳ·uYÂÀm]æIp[—)àÖåI ¸uÅÇܺ™~[¿#v,äÖ ¥#rë1з®åp³` åt›Cþ΀ÛPÐ\Èmh/¹YÈô'üáœÜŽ[vtëvdðaEÙ5ñݺ’ÂnÉKèF3 [ÇÚBèF; [UˆÜ:V"·žú\[g$rë‰[ON rë2Á†ÜÈn¹u9NBn½Åë¹u¼LDnû ·®Ã&È­×0]…ܺ’;Cn½$Ë9¹uvûB·£å@7B¯‚n(B·n‡‰^ìÖ•rvë—l8ÅnVR?ô·†L"x#ö4ðÖØ™lx#Ž.ðfÑcý¡ÞÆZ‚7bÅoMá“€7bëo ¡BðÖdí ¼5eÞÚƒzðFx[à­)] ðF¬gèÍ¢†?¦”÷õ9äf ì tk˜Í ÝÆdB·¦$¡B·£JЛ…FOzk˜ù‰Þæ[¢7"Âov%ÿ.·†U§ð(Ãà[Ó”¾a~kIUÁoM³üÖ””~k:¶¿— €#n<×0ƒ €k9 àˆµ+€Sd]øØ¶ðáüá·† —®)§!GÖŽì\K2 €SBø­]²'¿5™$Áo-¹+ø­)« üFÀ`ø-?Œø­)Œ‡ð­3oíÂJ2ð­ÉR|#AøFöðM) ·†*+zkìÛƒÞg[Ao-½Ívö f¬ ·¼µ 7 ‹ÞZ=Ÿ4ŒVÝÈ•!tËWèÖ{ÝšÏ;ºYÞŒçŒ|bä V+?2s‰Ð­É¹Hè–Ÿ ÐM!ˆEn-#¡ˆÜ¾ioÄx¹‰,t—nÇwt#â²Ð­±¢º5–Î@·va}éèÖ”0WèÖdäÖ´×¹5Eǹ5%¹5EŠr#КÈí•¢äÖ°ä rkéaçäÖä†%rk˜¸¹µª©2È­¥§_ [XìÿŽr%5:ÙUÖK’ÁvEs3lWt Û•8ùíJÆÖ ´+2ÜmÇ€»£Ý€»‚ù£à®`'¸+:©Ü„>Á] ýÍÉîøïAve| ~²­j}[MeZ>Ù•Ÿ¹³Ä—Ÿ£å@»‚x)´+’¢„vG•@»’ÒZ ]Ѧ´£‘]A˜Ù%ãq²+ƒˆ*Ave|†>ÙUʇMåQ"›JkAvxÙ¿ ²+ƒ*AvRd—-²+ò*€ìò)…vùB»r_j9ÐŽ¬Ñ ]AÏÚ%vE¦È® ¯ÙºbU‰lç`Wnâ§Ø©U¸Ž›ƒëx¸.X‡Õ7\ÇýÃu|¸ÎºÑ ιŽ> ×ñLpï®ã©àº¢}°Ž‹Ue{¿9ÇXX— ¬+7,X—.¬ã«€uWa]QD^°îøU`ÝÑr`]ÁÏIXw”Ö@våÞ ;?1ÉέL²ó¯Hv~s’]“[ É®\²ó“ìšœ(IvneÙVj M²+Ï ´ó‹íÊóí³ íü#¢_”ÚÜ2ÑN‹™ÐÎC´óìA´s‡#Ú¹ãíüÀD;?0Ѯ܋ƕvÈvnR²^‚hç×$ÚùGD;-;B;=²]“÷'ØÎ=lWn¶ó{’íܵÉvåÀ]©pç¶Üyܵo`Kψ B÷y lç¹xç¼kt^'Þù©€wÿÀ»RGn済ï´KH¼+—'Þù–À;7 ð®ýt•kÒ5Áw¾)øÎwßùÓ‚ïüõ7ß©©€w !HwMno ;mHw屓îâ'†”•ϼs·Þy„̀w¥ŽÜoóÀxWnšxçµx×ä ¼swÞ•{ q‰+M¼Sk1Õ ­yJúžu¿OTó6¼Ûˆs‡«Qz–(ÏïþWàÿÿé{zK‡¹RµJœ0‡eÈV¡?2§·HNz|êaI­'ËTþ,õ¼»¬ÏÓàïRÇ.a ùÇ¿:uOäÂÐd¿•¹çfã¹ÇÏÜsÏ*uÏ/ýaÅ£^©F~v«ÝiŽ9©\…šœ”5Õ¤<¬É±¦zkRRÖT’ò¨&]¤šÊU¬IIyXSIÊ£št‘j*W±&%åaM%)jÒEª©\Åš””‡5•¤<ªI©¦rǪ’ò ¦š”GÃ[±¦&uϺ2œÛofî¹ÿ^æž_zßogîù½Ë~fîùÝê~dîùGõ]ðºŸCëg¦˜Ÿ™{þÀÔü·Ï\ûËDü·ßšunþqù­ãOgî‰\åÇýÛ‰{Þ—ÿ¿üÏÿCytþQâžOÒÿë%Žÿü'÷¬ûÚ!ÏÀØ“Ý"T¿ûЇwë~vfÓ†Sãw=Ï%Ÿn瑎Kß‚\òy®°Þ¥|_ÁÀo ç’ÏÔÁë9rÉŸ8 rͧ¹ž8 ÿËö‹ºò'q¼Øœ¬'rWb ÞÓ(>!ï¦#½jõmÃs;xвa=ï½ÃÇâ ævð …Öz"„þ_¶‡ûÞ.­ÙÒ?‰>ðkÆ9nqˆy PeË×öLáôün}¶ 0"¬ÓˆÍð²Ú~lº4®ƾŸ+â€â/Nöº"ÖövÒ˳ð÷ïtݧ>½æ^ßwÁÊ_¬ô1äññ»iõ!#üÝUœcÖLWü“ÖŠF+®/oAú'Ñ-ýíNÏ~nŠkôO: &®õ²ÀQŸs]‹þ4#¯ØÂòîoÈ+ô`ôOÏ[Dzš¿Øv…×Mqö}ûJ¨'¥Æ·¤÷|ð”£`±Á”7ŸüÌ‚3] )c½%£óÁ&KÖ_áþ»u§·äJ/%¶ú[²½méþþý¤—?~”Lv‡ÝFoÉL?%~Ì·$âÚG ´ŠwÙz^ÃîÇ>Ôò"›ÖQ>Ï[ò^][ÿ-yߦnXÛ”ò–¤ $,Éß¿ã =¦çKõ; ÝX=¨§ô„·$bßüe§øš(y'ã/Núõ–¬ÆÁxá‰×ükÑ[d¸¸³æ %Û‰<´•¼÷q¤C!“‡Fɾ3¯÷ï3] õó-éT˜ˆß\éUH!-JÒ­°\s§_!TÄ·àI¿BŠ-oÉLÇÂ2Š’ô,ôÖUÿ Ǫk¡dñáð(!Ž|él¹ónðŽW¶Bˆßg™é¢deëâØ÷-é`ÈœoÉ•£IMÞ‚;= K5wa7ïù ¦.˜écȨoÉJ'CêƒQ²øžl–m³“¿šùÚ‘šûÌg9òWãHGC×3Žô4lj¬°ë¹?_;lœ¾¯0¶ADíyãZÙç\qßù|8¸~Kž“ïÀzgAÆO‰’ô8¤~ûþcÝ\‘PO–íwhl°ï;²fÜýêéuˆØ¸oÁqç+øGçÉNžßû?.¹Z2 Ç[råréŸÜZ.Ñä×ÓØÎ%X0]ñÄŠ©ÁsÁ¥Wß­±‹°`æŸ3k½ûõ}úN½zãûÌU“‚|”ä²Éåÿ-¹n2²î[råÂézïÆ¶½XòðñYò\ì,aØ}‘{{÷2Tkü¨7|Þî½îOÏõ“!™£¾8×zKŽ\A˯àâ[JÆÁ/pã^pòõ0ˆÄ”ý{ͬö{žã3jŸgñÐzϼùX²;¾þlý¯ßÉt"èï=áí[JõFÍ5áîëiIúç'\~Ë­¶¯»¿å„˯xÞ¹˜º‰'œ~™^ë-™¹˜–—‚Û¯oM¾Ïj¹˜zòÜ!Ÿ?7_Gÿ1J×ÅÚÛ[²ZÚú½\L™4ä-AÔ·Þºæ‰fݹ˜z,D¾èï8 ã„wÂ^$Ìú§[G^Ï»NÕ±ñ©=+öüù›XÉ9ähŽ•‘Ÿ!Ÿ8Ö£¼†3KÌïìé'~5ŽÕlј¡¾móB~lè{ ´ý-MÚ¢àá+ð’y}QoÊK­½ nsl„¨]­ÇXŸŸ÷ÆAEi«½kú–äñ†êù£ézDp¹M(ÇUÚ[o‚›Ú{'Á½3÷ÅIp÷¤· î-€Õn܉>›àîI œÓàîIyÜ{Bƒàvzö3+Ý÷À(rÜçϹŸ›æ{€¸}¨nCÜPÔ Ä½°ÄÝ“&#€¸}ÅL>ÚW~’W¯èŸ*âÞ¢d@Üþ³ÙZ>6ÔH@œ%âêâvÁhkû±KAfJb NPÜ.ØK(î-@øúMqå¦Iqû9†6Ä•[$Ä• 6Õ§L†+·L†Û·Üã WŸa3Ü=)®€áêO6Ãí+À’‘®`BÃí¿[>åf¸]€)/!Î÷ ÄùÉIqn>Rœ•ç#Æ}~µ1nÿ kFbÜ.éxž{|ëݧW"ÅÕ‚™£«¼Ó†¸{ÒæƒWï“÷)ÙW[")®Öœ÷©ySÜ.ÁF.(îsŦ¸OÉ~öÏo6Å}î´)îó«Mq»«rRÜçšMqµæ¤¸ú«c§×*WlŠ«µÅ}®Ø÷)Ù÷)Ù·KžJqŸk6Å}žecܧdcÜ·äáWȦ Œ«$ÇÕ%Ç}®Ù·KFä>לÇWHóð"È}®¹ÆN’ûÜë^¼†Oø<ß+6Ê}J6Ê}î´Q®^“(÷)Ù(÷)Ù(WëI”û\sÞ?Þ!QîsÍ•ëä}pÀÊ}ê½ïŸÏ÷œ|–Ìþóùf®–·v€‰rõN‰rõ;$ÊÕzå>¿:îï,÷)?®¹j–Z®ëÇ;$Íík€wO®›åGÐKÉÌ•Ó?Ê*¥Þ„¹ú£ ¹Ïßýâ7¨4Wç¬Ä¹zÉ™ëg©e\üİëà `Ï8W«A²ÁRÍ“kh)A¶Aÿ(ò©Ô kÐÓ\Ò\Ü_ÿ(a®^r>K >–ÌóGçHŠ«·^“ã ÕîÍŸW~“ W/îó£óûÎÉpõË'Ã}®¹æH†ûÜé9>Þü¹”&ÃÕ¾š W~µ®Ô †û\ÑŸoÿÃ}®9Ÿ×Œö}0Üçšëâ;°ä>¾ï†û\ó<|–Ìëû›uð„uXM~Iqõš¤¸O ~~p@\Y¥>òG"19.Ì‘ï^•8íÈS‰{*Ä­H\°wã ¸m=St¸·öü¤¸ÅÔ©¤¸è‰h qË"[B\t“V!n1-5!nÑ·˜»#!îåý¹—£Å¼„8ùIâ^@ÉÓBÜ¢ß#!n!¡*.sU†[ÌÁJ†[Ìœ gQ ·˜8ÎwÃ-‰‹`¸(€T— ·˜*œ ·è3I†[LÂL†[ôt$Ã-f¶&ÃE¥SJÜ~¬»2œŸ·ôœ ·˜Ñš·˜ý›·è¡Cˆ‹¦èYgB\©#!Έ[Òbq‹¤ q~QPœ¿(N¢¸Å0»¢8uFQœî+Š[t@ÅéQDqÑáîÅ-ÆfÅE=žg§§ä+‹âÔLÂ8õqÜBŠ,aœúº0n7(1®<0®ÜWnŒSÆÕkÆý½"1NŸ^Wï”Wš·˜9YW¯IŒ[ˆ1/Š+?Åi®Å-&[Å-BÅÕ¿“âjIRœo ˆ+ŸW.I†«Ï– §YN sÒQ&ÃEÉY ®üW> ®8û6L*› ¯`S©Ö‘Me³áŒ*› -`TÙ¶ù®L*åS&•ÍöR0©|JÛB˜T¾Õg$:QœL(DqæNRœK@q…2qÄnc\«´©ä ˆá0ü ÃÁ€ö”ÍæB8ÚÀqèVwÐDPwѸ“§œŸž‡Ó‘pjœJDpjM(¿Ü%Æ£>‚{d)I‚SC á6£ œŸ… §7ÃM¼¶nÒ¬T‡!œ‰Ç:pj:¿¢øÍ—àô´8—àôeEp:ÿÂéVD858NB8íhˆpµdqOHôÂù3 ánÚ¦ á´ó(G`3£€pÞû áÔp:x!•ßáÌôD8Ÿ@á4h‰pn!œº§N]Z§6ÂùW@8òd8wj2ÏñÌp¥2÷Jb8ïtÉpþ2b8Žn"œ:1 NWàØ‹Èo~ñ›¾ ùÍ?"¾©RЛ»«èM}Fô¦éŒôæo"zÓŠÞt«„7?.àÍKxsµ„7UBv+lvsÅb7õE²›ßIìÆ–º©ã ÝÔ€n®öÑq(ºÑÍóÐM§ŸB7¾ÉMÏBp+`p+%7Íœ7ÁM«ÀMIà¦g!·iÜnã­ÍmäAs›Hn~Ϻ„mš®„mºÄÔÖ>:\ýÑù=|$µ•R›NHm¦SQ›ÞRÔÆ†´¹bB›†Š 6…`6öD1›º™ÝL̦g1³Bkßs"3›ïui)¨‡ÌÆÏ-f+wžïù„™œGfs-K«iƒå$™ ­'dÓ€«È6X²øxx"æ72ïXmÛ±s ¦Y?»ëR/¿7úÊïù0å÷·¹½1ÒºÜÞäWEHÃ_ðy“÷ M†›$4ùY‘в Æ”c¢4Æp¥1ÌŽ(IÀDi§;PÚäJ¤QR¢y ÒôT iª€Æ(ï€4˜¤1I” gi?½ÞÊ€´R懤ɦ•6¤bmH i²Š%¤©B#é Ò\% áži =/Hc$4AššÆ¨Š‚4Ä3£É•Œæ£ ÍZd´RFÆ 0ÚÐ2FF–è€iC{lbZ©˜6 aÀ´Ró=¾õ¦ç[ÚaÁóMm/Ï·z§ô|+%ð|+õÓ†Vt¸¾•çƒë[½¨6´ÈÃõM}®oõŠt}cì/y¾ñ³Éñ­¤ß[iø½•KÒí­Ìì:¾…×›ú-¼ÞJ­ðzó£m§7u9½)NŽœÞÚÐvNoåáô¦¾-§·ò¥áõVÚ ^oåaÒé­Þ|í§5ÂÀím|Òí­¼#ÜÞÊG„ß›âºÈïM“¡üÞÊKÁï­–\ƒí; f_O Ç·Zò|‡<ßJ£Ãó­^“žo¥kÂó­ íÞàùVêç[ð|sÃñͽ~oå-á÷VÞrû½•ö„ß[¤e¸½•Zgÿvp8½Õ‡]Åfžtzkã‡Ðö¹&ÞÚо^o~E8½•¡¿½ÞjµéõV^o¥åàöV¾ÜÞJ;Àí­|7¸½•‡A°¥¡“¸½•m¿77ÜÞÊ}à÷VßJo€ã[ýU:¾•÷†ã[½õÅÓâ’z9€ç[+ð|«×ìØK~„%õð|«%ýøñ ð|«×Ï™žoåÓÁóÍ7‡ã[i-8¾•Å Žoµä9r='Ë=XKˆlµGÀñM ¶ß´‘ã[¹ßJÿ„ã[é$ð|óƒã[­fÜ?ºù¼¾í Ç·Òp|S=9¾Õ’yþ˜hàøVï½æNÏ·6LLýäg8ÈfXKù¥àøV^!ßôÖð{+ë üÞê¯É7@ãÁï­¼üÞJųñÐ4p{+/ ·7_“noÜüÊë­1/ ¼Þ6K^onz½ùéèõÖè@%¯7¿½ÞüÞôz«%éõÆp¼òz«·š×÷–´–`=•·79º½y$(ŽÑµ+Ÿ7X…>b%%ÅmãS¯±“ãÞɲ-«% E¤Î˜¤3 íPZòÐú¼ªAäÓŸ‹fÉhˆjFëT’ŒÖaóEDë<¾DX[;"2ÉDÆgE&¡•®"“ÈzŽ‘IdYÈÈ$¶¹Dd’yR³BdÙT22ÉXÍÀ$áŘ„ü˜D%“<Š‚À$4Éd\\".ɰP\’…lT L‚SÅ%‘Pʸ$Ìž„¸$sÒ— qIxn©¸$ý—qÁ–Ä , ;£’ø–ˆJ¢ïͨ$Oe³hÖ§XB¾×+hÉI¢wbLÚ(& <¯‘„?pD’ÙèÌ$ÓQK’äf`†$‰€—Y€ˆ$ã "É-WvF$¹ê #’<·¢ "Éû)i’‰ˆ$ñµ«ä~¬ÍŒHâz‘äQ`†$Á`vD’›¡"D6Ü HB_B$™ŒÞ’ñHÞn ·zÆ#±i ã‘Ì“>~ŒG2Jšä2ÎŽGÂ,¾ŽG´`0’Ç¡FŒäV‹ FbçB#aŒG#±Ïƒ‘è;3‰Z‰¡HìÈP$ òèP$þfŒEâjŠ„qeŠäVtŠŒEr+ ¨¬ÿŒä–W>ƒ‘0Ø”£‘0(¥£‘øñä§ÛÓ/9µ3 ÒŠ8 bP;‰ü72‰=(Œ„aªŒäv4#q_f0Fu0’[Á_ŒävX#aÄO#y›œf“FâÂ`$~ž FŸFr1( c‘¸Å‹äVÌÆ")7B,¦–u,’ê®–k£;4c‘Xúg0’ŸluÐf4ui#±›Ù¥r|¨¬ÛqÁHä¾ÃX$ö}a,æ÷t,û42‰Ý{3‰–ÑHàÛáHîŸáHÜ[ŽÄÃp$?ØÞ[ɾñH.a<’â+‡x$Ì×èx$åšD‚áHüŽ ²r#Æ#q‡`<’â7†x$åWˆG¸oŽGbGlÆ#ñüÄx$Ü×9É¥°R„øŽG¤GŽG¢ÑÎp$žŽäRïd8{|3I¤ØüPYyMÆ#1|0ÉÅ㑸3‰¾Ñ\²›a8_‚h$×h$÷Ò"É`$•ÒæoÀh$îÃŒFâ†`4÷ F#ñ l(«W ÉÛ!G#±,£‘øK2 ƒ<8IBƒB‘ø›0I¹B‘h"‰º™B‘¨Ë( ‡©"‘¨ZE"Ñ­‰¤\ƒH$\fˆ„)ˆÄìÄ@$Z­‰D͉H$LšáH$ê¿d²®3E…"ñ{3I)A(¿C‘¸mŠkùŸÈŸ#]í¼„¼E¼±¤6„JVc WéjB`›ÂÜÛfna¥9b[GiaÛ¡€“À6†ß¶1±¸M! “Û¬“Û$R‘Û$íÛÜ&MŠÜ&½ˆÜƉâ¶k0X#¸g_7…D!¸)Öf‚{ÀA=Èm¾À]\ঈ7tyq—MSí ܘŒà¶G¸¨MW“Úô̤6æÍ¶1‚°°MÍ@nSC’Û†<åMRèÇh’Hâ,tHhtãR tcZ ‡“ì\—Ho:ýY ½•Лgqâ›ÎȈo>×%¾•j€olâ2ú™Þ.L‚Þ†ÝÜ@o>G#½é|Kôf-ˆôæ³6â[¹ü6ìG~óÝÉoãcéQh€ó #Žê²nÈ ñ$}BK~+~+· û€áN™ˆ$Âùñˆpã¨õáˆp>c&Õ@œ¿6!nÈ"‡çw"ÄY"%Å1¸)ÎXRÜ9¸9 Å9î')ÎPIq¡d ®\ˆSU2Ó0›á<|Èp§èœç°©¤8·pbÜ)WbÜ)S/bœ¿$1Î_’ç/EŒ;éÍIгEŠSCâ\†?œØö­‰_›á8™á|ÞMˆ;åCˆc‚@C\©÷¾ý½q‹ q~Bœ»!îÔ !Î1fâNy‘âÎGjÀ8p Îý W*Ä?\Øöã_ˆókâü«„¸¢€âÜ „¸S^Œ¤8£ â<˜ wÃù Èp´B1Ã9ì/Ο‰ ç› çQ@ˆ{KÆâôxd¸óüSÒL†ó€p~"œŸ…wÚ1îÒRÊk€pnÏD8¿#®üçïF†ó“áÜÉp›L†s “áüÈpLèg†óóáüžÉpåÞ€¸SG³„8w{RœCA3¦¤{,1έNŒó€'Æ1«1ο"Æy&ÆùÍãü–ĸr'`œ[”ÇÐèÆ8÷Hbœ[‹$Gë4“œÆAN¯Só äNd‹ãôŽ9vbqœ0`œÞZ§@G 0Çq Æ©S ã|ëyÕo$ŠSÅ鋈âÔEqþ)NãGç¦#Å¡©J–œÞŸ™¡V”%á<MirP¢´7¿ÿ#\ þ™D9DZC=ªfü]Óìæ…È?Jb›#ÒzÎO ,©ud™jÁŸ¥ž³#à“ß‘%¥”±þù¯N”Ó¾ ™ÿ¹D9óÿóD9¿Ñ#zü³ÿå“*çG×ÚýænŸÎö7ÕUÓàd]Ÿd9¨«\…º¾)uPWI„ƒºjºÖå«X×'©ê*©pPWM˜Ãº|ëú¤ÕA]%êª)sX—¯b]ŸÄ:¨«¤ÃA]5iëòU¬ë“Z·$Äɺ>is8Ú}êúgÒæôÐ5"ÏòåÍùysþÈdý·ïäûËÔü·ß«Ÿéúwê·–?;§‡’ÞÿÁ“çÌ’<ç?ÿDòœ·  )Ãc”A§•8Û8àbFз$2±ÏÕ|{W°ûFÉÞDZûÜOõy"/½5ö®à¡öJy§NÇŸ{KpÒ°þ-¹÷–à”ÚÒgrÒûœ™›žc:JöÖüTT >#qk0ó™»òœ+ò£b;²zæ§§áD”ìù)'—w5Üd0ä>gå1׈ÐéÙvklÄ®½ÆÊk M÷ð«|foÞùÞëÞŒ=oPñ“)ΚŽÁW¤ŒŽ1Îö#ÓpÅÚŒ=”ãhyÎ×ä‘ÐŽÐû'ýhyÎ5”³ãxyD-Ϲâ<á:Q²{(ÍÄÑÆ~'Z ‘|üÊZ®Ès®Ñ§žïžù®÷¹òšv?Âf!Þᦎ8hŸùÄîµf¾S„ï¯Ò@ÏjҤ툳õxdˆ‚Y>ÓÓ+/5žç\CaÝ8ªù£$ó£ç9W}”ûÊÀò k( þñ¾v~ƒ&&zK6bŸò*=Î<çŠ[ã¥â¹f>pžÃ#Ϲê5}#vÔ“³Æ1òœë”«Ù1ÎØµd칒džïß°O†|;Fs §sŒûÌÉ’ìÛöü”lÂ>€åsoäN‚cmÂ>aÌÖ«mÀ>oÿ«MÎåè{×»âlˆë8ë4}\gË mÓ[òä¸d\ù<%>®<銒|íëÞˆ}ÊÊè-yòé4=ö h†½ò ë¤ }\«å ¨®<éŠäÜ©ƒ¾{ÐëóŠw?xÅÅ’\M¥y¾£+WS­¸Ç}æj:y.sÜ#WSEFI.¨4«|K®\Pýåî<é:iiw¼û×ý ²{Kr=¥é[2£Ú8ÔÅ­ó ë¼5í½|³_A¶)oI®§sâìî"NOtæ•çÜ ª;ÍÛ™÷%xŽ'“qÆ%XÔž4Å-ø¤¨[Úï Y·Þ(uÝòžvãÌO*»1˜~•Òî)£¾cæ9Wé$3ÕÝxÍŽkòœ«4ÅL}7ž÷šçþ{p˜©ïÆ;aêžyÎU>ËL÷”Ì1óœë”Ã1Så=evÌ”yOw½%{A­×¤Ð{ÊžîX©ô–á±Rê=™Ueáwf’éOɳ—Õ“goIèÀ§Hß¿W61Ò¿%©ÇŠ—ûŒT:gΞJptÉ\DÏHÒvägÈ çì©ûÜýĈf·={JÁÑgO%Ø£á쩻מýŸæë–UæÜ;{JÁ§ì0ÏžR°ÇÇÙ!s±;Öó ¸C~KrU•©Û»›ÈU5„Jü*•`wôóÝ…ÔÉåý{r°â[ãâ`Íç=Rö¬ÅƒŽrIêÀÑ0¹å鈺Ú͹#ðCŽzòesœÉ +4áÛà·£N“ÐD¦æ.à÷®|F€ß[‚ŸŒ K­IÔ÷ùÉ•q©îê~ûW`­‰<+ϧÎLò uà÷–ð°=¸ïž&Ã…T+2¨÷íJ’`ƆW·øízŽ ~ŸzFæx óÁïSreއò ~ß’ÌòÀpë¿Úä ~µiüî©ð‘¿OÍÏóãk¥T³Ž/>^2Ñoßè7!ÓŠoè·KFE¿ú0‰~µ¹ý>÷º2×C¹×•¹JÍw&{(×<ãû÷Ìdå7sò3ðNÈ´âwHöû” ÓŠëIö«Ýo ÓJ!»óä;ðW£FK²_™}õþ>%HµRê}&ß÷ž¯AÅëä+ãZf{(“/€×Nô«7 öûü}6~ÜøBª•R2.¾n„L+.¸Ûqz!ÓŠ›*ÑïS™­ÜiµŸàB²Ï Á~åÖ‰~û‚²ê‹“åýê·NôûT;ޝè÷ùÕõðx ’­”’çàlÉçA¾•R2¿3ìl+.Iö«õ>È·RJ v–$\ñ’ýîiØOøû”Œ›ŸÔ†ì‚.@vÁR°¾·AzÁò(H0èùóA†Ár R ºž‰Œ+ Ù òû” åŠë™H3X®9ïo½H3¨`Ï ¿o VT—Ü‚G%¿Ïm°–ÌŸï€|ƒnò…„ƒ¾×BÆÁZ2¿#ç ÇÆBÊ•R/òzª^H¹RêAæÁR‚”+¥¹§9)WÊ5È>è÷\Hº¢çÙäW~òû\„ªä÷ù²Š9²–K†°TŒ<„µd}_ä÷¹æߎ²Éïû÷úùxHG¨,ȯt@_½S’_­§#a)ñ™‡t„úÀ@¿ý«ÂR‚„„åWHHøýêä#,%]‹êBñ@¿Z-’–JÆõíè@¿Ï5wûvt°_mŠ,ù©zˆðú¯¶ ïXA2Ê~ŒÇ ÙO¹Î©úE¾áIÉÚyˆAÕOI©)ú½k¡°-E¿þýºôŠ~QBù–í‡õÆI»Zü™Æx‡rÁ„ŽÔËvÙaAð³m?ÛQñëP¨øñá!÷…u@î È@»BïëG§Ž˜r_—PG¹/,Ì‚aË}å}!÷½)Aé:¿vd”û:ã±Iîë–„ ÷uë`ûbDOl0k×+PîóÝSî‹vA%ìi}#Xµô¦Ú׋>ùÀ¢ÖªáD–vªpûê%)öukBûlËGµO¾0Rûl«r_´´&è}ñN8 „Þç¯@½/ê…4 ½¯|è}õÞÏ×z_?¤ AïëVá ÷•—‚ÞWpë}Ÿ¿‘¨ýæ’½/^á¦ÞW•z_çOÒ´óÄ“b_´øAiiÚ%,Cì+b_-];â Bî‹?q¹¯ür_Üè«Á¨Ýr_éÀûjÉ “Z×<Æw’¡ÜýrŸ§&Ê}Ý*ì–ûâo è}ÑEiR«> ¹/ª=K YÚoÉt0kw Cîs vÊ}NÜN¹/ê¹|µC@îë]çøÐûÊ+Aï«¿‚e{y¾Ôûê5©÷u+ßÐû:£ÆKðë²Ù¤à×Z‚_g„v(~ð¥øuFÝ—â祋Š_—?ûvSòû”¤m{)Iɯ3н$¿z¯  ÝÐüºÌ¶ä×-Còë2>€âWj…âW”Š_g||)~ÑæØéBñ+_ Š_·©¿NDI~½)‡°n’Ÿ“ÜSòs·†âW.âW.IÁ¯Ü‚_ìÐ!ø9Ç=¿Î ÿRüb_ÊzRñ«õ0úÓ!¦âWÞŠ_é{PüºM_ øÕ—‚3'“HñÛˈþœú.PüÊè€âçÆÙ‚_ùüºK ø•¦à玽/Z†ô¯ÎR1Ü:}g¸uº‹@î+ ¹¯T¹¯4è–û¢Á)åÁ·³ÔËv0È}¥© ÷ù öÕÁ²ÝÆEPûÊ7€ÚSoJ}½ý”úü±SêóÄC©Ï¥>? ¥¾z œ=õpÔúüpÔú4þ)õ饩ôÕ§ƒ¿§ú•¾®,©ôÅ¡¦˜J_cB }M†%ú<–(ôù³Qès¡ÐçùŸB_—É…¾ú+ø|jq¤Ò×eó“J_ùPúõz*}åñ ô5†|’Ò'œI¡Ïƒ€B_y:}å3Aé+JŸWaJ}õaàó‰.ò²ø˜ð²ý?ˆ'fâ5EòNÄkN¤Æk²^ ãµËX˜Œ×$KòšQB^“rDÎkï‚à¼Vt@–Õ9/®¹«Æ÷´¢®]/ˆ ‘oá$@/n|T…/~BZè©„.$èµG ÐkVzM6%$½ö®ËàåažýpˆK&Ò‹’ö!½ðÕ9iÆ™qImÒk¶^é5¿"é5Éþ$=ߤ×l«²IÏOCÔ«%ˆ \×$bõüÞD½F;Ͻö;Ï KjC€^S\"‚^“AÏ*AÏŸ‰ ×l˜Ðk2ò è¹Côšm•zå‰zÑYç‡ôê5üV“ôšM“@zIzí1Å%é•ÏÒkà*AÏ£Ÿ Wz X¯<0XOÑ-ÄzCˆzüp༦dqä¼Ò_7è•GCXà0}W%çµ)Œç•öç5Å\#ç5Ù†óʧæ•Ì+­Ì«%‰yM6q›òÊ0å5ÛÈòêX'lļҸÀ¼¦øWļÒ6À¼¦øyļò<óš Á€yeHóš"oóÊHæ5Y­óƒ[‘ò<“òØ€xajHxM&#$¼h`áq~¾+Ï|W†ø.æŠ"*°‡ø®ÙÊ|Wš|×lã¾+|Wš|Wä<¯m¼Ò¸ ¼ò©Axl9à—â]½Mâ]“‘ñ®LêÀ»2{ïJ¿Þ5Ù­nº+ tç @w1³w B#Ë~ÿ˜`€werÞ•O ¼+s-ð®4ð΋>ñ®Œ“wqolïj-ˆÔãµxWkAŒ05º5-¤hàt×{“Ï[íÍvåIÀv¥]ÀvåË‚íJ»îj=Ȇá>¸«÷F> Oò »ò @weŽÝ•©tÓ]L »Ò. »²¶îʃîJ¯Þ•^¼k¶™Þ•IxWÚ „×lÁ Âs¯IÂóÓðZ±¹DŽ ÛòðšŒ~IxnžÛ˜„§µ‰„狈Wo…LzM"^½f'ËPˆ2!ž¢Äx7’7ŠñÜÍÉxnb2žˆ×н'¶ÅÅ&Ù2ôʼnx^ü‰x¥m6â•ÖâÕ‡A¶ õ "žV"ž;: Ϙˆç IˆÇ剄WúÄFŠòÜ'Hy§Ì#IyÇ/”§ø? ž[" Os“¯Ü„'žpD„'Ó/m ü »Ñ’.È‚]&lý„bQ€ÚdJ¤M¦â€Ð(³˜OÒ(s}=òŠ1‘­2ñåe”©0 ¶Ëôh—©#´Ë”¡•ì2k ,I–¼4Í´{L3mïIÛLÿF¶™6´„m¦ôfÛfvI6ÏÕÎæcÕ<“ÏCûLÿŠö™®ùYßZhŸi›NØgÖà+–ußp,żö™¿„cù ûÌ®£XÚg–’q×. ÍR/ 4m…FÍXšåhÎlWï MÿŠš¾;-4}/ZhÚ¢,-45™ÊB³Ô M[^ÑBÓ6q´Ðt«ÓBÓ-J MÒDÓÖv4Ñt¸šh–'Mƒ±—,ñ–'YïùaÔCM‡z¡‰¦Ífh¢i+$YiºVš¥„Vš2С•f)•¦¶4Ò´ýbZi6…¢ •¦›FVš.é2*鄹þÃüŽVš6y£•¦M«h¥i3>Zi–_ÁJ³Ô +M›¦•¦,Šh¤Y¢¶ÀH³}Ø®ÑDÓÆŒ4ÑlCL4› œ&šïȇXN¸[¢½Ív‹©öÄvL–f¶ÓižØn1’–Ø®ü l'[±]©l·pKl· í%ÛÙw†l7ÍW›í~‰ÉÒìC¶SÔ±Ó&˜í³xŠíŠO Ø®ø‚íÊ5`»R¶sd²=›“íä#¶“ûŠØÎ £÷’€çX/;‹:ð$šn·¼%gs+xÄ@v>—“„g(û] Ïz¨$<]HÂÓ+ OX# O"µ$<ß‹¯ „çÐ]¹%<™vïn[_ïÜûÈw>'$à¹fžOóðÊß<ŽHÆÓ Os.ÏÆ¼"õð¬“ðn­$<¿' ÏaxHxÒ‚€xŽ,DÄ+±T€x:¹ãùÈx%’ ¯Ä[ã•Ø.”ñ|/0ž$%ãi ã9¨H2žî-ÆS>-1^)ã9°–-B<…ƒ㩹虷äÁMϼ¥Ð‡ôÌ‹}m«Œ÷¹&<ó>oϼZ’žy¥žy+(¨Êxo‰‚ Ã3¯þ*=ójIzæÕzÒ3o1Ó¨<óê¯Ò3¯^sŸžyŸ’ùóÒ3¯Ö’žy¥®yŸ’Éw`Iºæ•šáš·À-]óêoÒ7¯–¤o^-Iß¼Z’¾y¥á›·$®Ð7O¿ú ˆŠoÞÎ^[APò8#&ç*z^F.R0EÅä,á4“SIГSâ¶brÖx-ˆ"¶T3¾¢ù% :î!I0öDt4ÂAņHÉ8˜ ‚CGÂÁŽ['½¡CX…åTÆ0…åÔ¦°œJ`§¸œ’|—³vˆËéx¤—SÖ7ŠËyK e\Îø¼2 U\NåNT\NÙ¶1,çEõSa9mÖðœ·Clî°œz…å¼Üa9•ŠNa9•ÿOa9™ÚMQ9K5ˆÊYªATÎû—¨œL@ä°œEÀCXÎbC¹ãrÞK#0§-Q˜Ó˜S!l˜3vþ(A`N…d\N .çjý0à] £r. ŒÊi©3£r:L£r–D匠ó2*§ÍÛ•ÓîüŒÊé0‡ŒÊ¹$Ç;˜¡0£r–8ˆÊic]æt¸–—³D“A\ÎÅ|4ŠË¹$Kq9e[®¸œ¶ Žq9ýxŒË;uêy¯ðEÀz/Äå´Žžq9· X:p“SæŒM'ð-1p”È—ÌYÌ(‡yXÞXžxsà°¦,898¼“Žbæ™8dm Š ,ßy|ð5AÃ{uPà°éÙ¦Àò¼ Àaj–Ö–Á ,_8ŠõgR`éÖ Àñ‹gˆ Àò¥@¥æM£PTR`é À2;‚‡íCAeŠÖz’½$‘½‘‡¹$8~!Á2…no0kAp0-9°ô|pàp¤FpàPŽErà°8p˜QÀƒÉþÄCy"Éejº‡n F ``¹ )pØ´8ÌàÀxôGPà(ü–8nyÂXRísw`I•=ĆÀQP2!°¬P€Àò!Ã9 p(Ó!Ð è×XU€ÿ†Âó‘ÿ¼!ÿ S÷æ¿¡ô¥ä?o„Èå€ÿ†öä¿QØ.ù¯4ø¯ÌNà¿=mÑo/WTW$ÿ ÛÇ€ÿÞ×þ˜qúÈÞ¨‘ÿâ7ã“s(B(ù¯þ*p(!Ð[RŠ|nuåä‘5¾á¸˜ÐøFAع¿dñÜË%ÕjT¾!7g¹ê]¦©Tùüñ¨òy H•¯4d¾ø0­òß.y*ÿ}®azF5û–ùü1)ó}JrIu°TÈ|¥m óyŠ ÌçŽC™Ï“u¾1š\èRç²¾I¯tè|ÞSçó$L¯´ó¢8,t>O?ʦÂ4Ö5wÑ¹Ž =£,×@à:!%Jœ»èwÄÜE¸àŸÉ]ôkÝ*©9ƒÊ |IÍ=4Þ¾ãب•”zPÆzøg­çÞ¹\Kþ]ëˆÕ°ÿ(¿¿boº­XRê@k៵žïg©ªÖS¾Cù,ÿò\J±}—ÕO2¥È™ËîùKr'HŠØÞçñû‰—ú~ÿ’OæG ×ßKÇô#¯Òoõ¨s–oò{í{"Êc;”uÕŒIY×'cê*W¡®oö%ÔU2&¡®š1‰uù*Öõɾ„ºJÆ$ÔU3&±._ź>Ù—PWɘ„ºjÆ$Öå«X×'ûê*“PW͘ĺ|ëúd_Ò WƤ¬ë“WÉ]žW¡®*¯R=½[“ÿÊ«ôó*ý…ä×yû»lüíïÌþ¾äw'Âÿy•¥ûü'¯ÒþVÿùÏæUz‡IF“ËÑ:vyᬑÑädL÷î3šœ|nÖ'ÖŠ…ñþ'ÖkÑàiÁÜÞ¡Ñ×Ìð޾²Âñ¤õ-Ù;–C†ó£åYÜ){æÑú>¸”He4œÅ<a>Á{´<»e¦1Úˆ9kî?ó(î–eâ[²OüŽÔÞkåQÛ[èœtÄ>¶¯Ü{M8Žáç>¨%+S̽О 2B‹_Áq'GX¼¯ðhK:zÈM2ˆ…õNŒ|…ž§qsgóÍ‚}0eó2zÆM…ë‘Û=Þ ,ñ«<ŒC`ô÷Ï}°ó×çK÷<‰›VGŸû`ë ¸ÑÚq|ÝQÏÚS½ÆÑv½ŒÆÑGÎôÜOãØGA‡KöÀõŒ’s,åøGÅÍðz²äÚGKÉaß’Í 3w©ã¸7ÿOÅîGœÃM»—Á÷Ó+ñÅ[²™Á± ±e|Ÿ„§¡ãÌc¸¥<«ãìû ²ÁNlþŸŠS0ÎcóÿdB¯¹É¢¥Â õŽÍÿ¡Œ%|ŽÈ3²;MÆ;;äß ÕÞ›ÿC ˜Øy âé.vºgä1Úð¼y y1"Ã[+:¸D•1ò‰iDB°x…0¬À5y ·ŽG¿:Î|rãy·dÓó–DÓ(ËÖ‹·{N 8 НpéÃʼnלgF@RÔ#Èq.ïX…kæ>ˆFG3Ï#žö:#<Åîh U/«îC€GÇ·/YíC€GG‡ï¶xb˜Ž+á¦Îâ_òÛ‡S//oïc¸õvÇ›%+{’&ˆ+á¦3Œë|ä)Ü”ïÔ[²ÏÊ .t%ô¿kíC€)ß©·E£!d™üþ½·dKöù#æÕ=Wj¸ßÇÈ&žœõîs<’UÞ’}ðȯãç;·„ ɸó.dM ¼@=Ù 6qÖû7§÷{ß9Õhƽó$n†5p~Ì{íC€@¦‰Zò$nz°>íædƒùþ鹉¸ªYpôü ù-Ù»Ú1¡>ç>xdú1ž±Ï¬;d\9Öù÷>xÐñßÁ•Ï@¶±œÄóëüi¾úº?@_—äMè‹#xV›Ðw(¡ïÐTBè;$úg”ÄwzC â;åïŸÄ7¼AòYŽ!ó2® óY” ó oüÁ|Ž|@ì²Ý&ö #°ï’q±ïVìubßPF’ľ«òû.…Z!ö]«Ä¾K ±/¤ñõ$ö]Ò‹‰}·€}wá¼$¿-ºãWA~·\™ˆ~[ŸÆó%úÝ (Éï>)â“ü¼|üîÇpرFé@~·¬Ú‰~·ÂýÞá‚É„èw‡õ1ê ô»µ4ý' _9] ú¹õ€~GÑïaƒ —‹”÷}@¿GÞWD¿GÆ©D¿G.¨D?O£‰~Tq¢ßãÝ9Ðï‘ùœÐO>*D¿G.B?SÐ/¶%|«D¿ÇÃèçåÙèGkC¡_Dg nôãÆ…ä÷,šü‚p,ÉoºÑA~3EåK¼µ`ÀGñæÈ€÷íçÃá†ÎbÈ€W[0à” ðQ¨dÀr< |¼AÆJ=8ÐG"d@¬-‚d@/dÀ0ùÅ–êŸN “Ù•Kþ³â|Ü#¡­~°` 0v ”'OÑð¥¨þ)Ö0Î/Š}¹T™ÃÀ€ÅÈ”ÿÌ\`À²½N™’'sC9#8—Žf€€SæêRÿ,­C«ˆåNœ>&‡ú‡s@‰óñÏ›4 Nð$þiy N™Jü³š,ò)ÐÛ+à4‰ƒ=­‚­íRüÓj`ñïbC-WRüSx‰rð²ø§ó! ð ¸“˜/.oX-§RýÓ¶RxKò.‹DÀ8ÓÞu‚,4Sýó|Ht7IõïÐéÐF$@ÀU (W&"àRŠ,«<-K ê_¡D ,àÒ XdÆ$Àb¯@ô” \Z~‰€ö÷$.OlD@«Ï@ÀuRÒ–j@€ËG Àås¾€ñÚX#‰€^;€€Ë«pÙ × iÀ€K™¢È€Ål (é¸hçlTøO2àr‡L|¸7&./`Àb¡\r%!ë0àòÔ \‡ï• h»"`8_¢$p)ˆÐãe#à’o­pò@‡ê9 (%®¢Á%.¬£ä îeuiº.š€åê$´LC”Nôà.‘.ж-b@ .M™é!Ô2E¬o”}‚F$ÀåÍ;pšP=—`"àÌ‘ ø ÀR Pk’P>^@@™¬—ö†B@Ip Àè÷øþ$À‡'&DÀ˜kÈš‰€a½…Kfû û4 pÊ€F¨¹: ÐóÐs7pí¥ô? úµë°rÔ+TB Å*BàÒù§ ðÑ·$ZùNÔž‰¸dë$ÔN à‘šÂ?JµdîÛ§H•ûžLÜW$;€BK$õ)9 ¯Dù“¥§\˜héI;$1ŸCŠÓÐÓÇd>‰¢d¾C‘ É|‡¢ƒ“ùNÂùï7óÞž‚ùÎb.šÌwê3“ùηñ¿Ì7Å„Ì7“ŠÈW2 ßðú ä ïÑE‘/Ý=å.Kä+À™²Ÿ’9ùnéþD¾wò¥€|—ÈwÙ>Èw[¾ò]rÍ#òÝ£Hö“ß d¿9~È~w§W"ßþJÀ¥D¾"ùžZ²×¦»à\"_±yòݧvO@¾ÇX@ÙχÚ@¾G6.ýlGä{èt)âkÚ—ƒøž¡íe?«@¾býKæ³&æ{l Kæƒ4 à{äà-à³ÙÞ¾Ç`AÑÏÚ ÏÛ-ߣsQ‰~ .`ÍO]˜šŸ÷©ùÉþFšŸÏ:|:ðùÐ=5?ù'‹ø˜~P’mYÄ{E„âgS:òžOY¨ø)–•xÏDÅOÅ{ER£±§Z"yoðPY’ŸŽ½Å{¶Dï=ž}(ùÙ’¼g*#ïÉP¼§Ö’±'ݲ…{6Œ¤â÷öÌPü¸o’âçí6qÏG>Tüªigâ^Q{²N'íÙ¾ž‚ŸÒž6ülæLÚ³?¦½©z%õ>y5[ïs ô>Z`õŠu%P¯iðõ û<1&êɨgsj¢žÏe¤öù«}¨¤Çm½µ¾%ÕZß%KZj}æ&€ž€¨ôy¤@êÓHçé´œçOO©Ïs µ>ÏÔú|†@­ÏÆÕä¼"".ùMÐ( wÒœQbßcy­ƒšî¯Øç·¢Øç³FŠ}¶œ&èÉ·\b_©'AozY¦Ø'"éUivÛêŒ$=ÏCë“„@O4+­OK"=ëWûÔ|ûtâ'±ï±±ÏÆ•$=&ƒôä3bÒã1Õ>³Ô>›ß‘ô¼¦ÚgEKjŸ ‚jŸŽÞEzã§ÚWöÛTûl+›¨§í§POXD±ï¡+ÔÓ:bÔ0PíS”«}Ü8ŠõŠ ÀEÖ“fEÖ3â’õîÃÆŸ3Ç&ÎÈz¢¢žö=Rû|d@ÖÓR#¹O Ÿä>##Ô>Kí»-#‚õ.&®¬GËd=º–Hî3LSîã9XO¼üäAcÁÜcÖsÅü¤æKðÓ‰PÏv¦@½%Ix£^Agê}\Ezaû+÷… W\ó[—þެ* 8 x§çÞ9hA^Éf!]o1ç í:ãT®U»Î—ߔیwJs"ã_ÏafÉx·çx0Þ%IŒw+ßÏ›õÍxÕSÞ|^wÁxÓ˜ÆÞÏÓ›¯kͤ7 J“ðŠ8CQOq‡åÊW 'áÊ'¿zòÙ`fžó+É•Ï>8¼Ga´äËçv¡/ŸOÝéËW½ûrEê?o*po*{‰4½€¨…pçcTÊä»â”Co¾â1o>ŸzÊ›O\#o>{ Ò›Ï%—Î'KrEºM›·Î¯êÐWü“ïV1D¥GŸ¶xôèëò,àÍb¢ >ï†éÒ÷‹¨WDùôÉX¢žfûôÙ?ïº?ŽXõ–RèÓgû7Šz2‘ªçAÈ› ×dUÏ™PõÜ%©ê™ÅySÁµäÓ' ¨z¶¼ä•cmÊz“ÉÑ,ëIý ¬§ÅO˜çã"ÊzþæÄ¼òÄK‹~ÌÛq4_õ´3æÓOÈzÅ"˜ç-/e½bm YÏg$Ä<÷@`Þ²×”œúdó(YOç1äý#ãÉ•„çy‘„í{Vo6™?(^‹-²yKY+yS,My¶ƒ<`°OûϤ¼eÛ4Flñ– ”·l­FÊ{~Èx»qH‚732é9)Ï™7Iy­ø&åµ!PMÈs*ΤwÎHH¸kÊ%F¸kÅÝ.áÎI w­[Â]S&3Ò]Ëk—$ÝEnKŒ¹MwÍgP »ÖN%2èÈ{p×”Q‹pה̎|qv)É%ß5åÉ ß5åÌ"ß5Å3#ßíµ 4—|×$®n¼kr 'ÞùyAwµŽ¤»Ø¾´ÏÌô9>=Ý•¦Ý5˜íšý€vMiĈvÎÃM´kV7Ú5»híšb½í.ðpÉvwl ÐÁvõi6ÛÝK9µÀv÷ò‘Ø®1ÑÑ®ŒA ]³3Ю|ÿvå;íÊíÊk횀v­˜U"?ª¾5Ю|J ]³ Юü(É®|[]“˜‘d§±N°sk’ì¢;ÌÞ—dç̱$»öµÕl:èÖÝKgQÄ:·wb]S@r]Óá=¹=“PçqO¨ó(!Ô5Y²êÔÈt­pU2]ye0]i(0Û6™.þ¦)g2ÝÞA~˜.꥟`2]kÖ‘µÜ)¡®ÖœPçžH¨ó¬C¨‹'°%Ôyê<{%Ô•çÔÕ+’êÊwÕ¹³’êÊ;€êÜ7IužwHuõ^óá4ŽŽªk&ªSè„:/‹„ºú“‹©Œ‹u^u¥ÑuQÀP×ìî ¨+P×t0F¨+Pçi$¡®^Á¾ “N¨Óì︿˜gþL¦¥j¸ù |ÏnÕŽÊó<Ën³Ëùn›n>J‰LÛM%ó ôEbDô´:VNydÊ_Ïj™ÏûQêz?ãµ¼«¦6HÔõN‰? Òiÿ™Ôõ|–H]ï}kò¢t:’¡ÏGÝÔõìAE]oÊy‚Ò^dIýoÊ5ZÐWä5@ŸgtBŸ’/úä6)è‹ÝK#è³uµ O®²”övv´íf‰HIiÏQ ©Ó'à”öì*Fw=ÇeËHfoºëÉÐ@îz2j»Þ’( ê›¶¥¶çõ™îzÅ9îzvѤ¶g$NmÏ‹±¢uJ]£¶w¸îz {%mÏ{úëÉ CÚžY€{æFm¯ÄÕ„¶'ÓÙoÒ’þz¶R¦´WB‡Â|ÓáC(í9‚¤=é&”öäÞî+1U©ìùÐ\þzVÿ ìɉ֛öLa¯øâÁzs B)ì"ã5Zî“'!ì+P{¶ß¢°gË+ëÔY•„=yoQ×ó‰=u=»oò+ŽO4ß´;ÈÏ^ÒõÜÔõ딺žf^ézvK¥®çi•ºž'Q딚J]¯¸Õµã+“Q×Ó÷¦ý¦ç(êz>ÆúÉûD²žl‰$ëõ_buútö›–ÎRדÝ"e½¢(BÖ³É,e=TQÖ³ù#Ì7ítEaÏ“ …= )²à´$…½S~rÖ›üêŸ)ëÉL²ž_(ë…¼þ‘õŠg(e=™›KÕ“!#U={¨QÕ;¥”SÕóÈ¥ª‡£¡”ôlÅHI¯FîLIOÙΤéùLŠšͽd¾)*zÊÃ$E/¢>'¡è• +PôJ ºé9\J‡|Ó)ï€hŠ?SÎóÄ)9Ï2!L7½RJÏã ÑrSá%çúŠEÎãÁEO Ô<Þ¥šg=€jžã—PÎÓ±¦ä]b^ê æi.1¯øBÌûÅG¯¼xŠy§¯ ˜wK£˜'“eŠyD3(yŒÚÏ2Þµ$õAÆ«%ë;ÇHÆëÂqBƳó%deïñßKÉ…Ùü½jGÇxj]*)u¡¬Ô¥×ÙHƒýË›«Äu±Ìu¹Äuý«½Ku´Ë» ïöpgaî–Ó©‡Nç&º%cù †²«ürA&õN^ôK_xá3&w¡¿ýÒ­¢ÃÜÛ ·^¥ª2 °kÊ¿?ñÕãkXÍ;Ç5–ÍzXP+òE¬©^¥ª"´éS‰Ÿªt‘ª*W©ªî²´ >Ué"UU®RUAÝm•ªPð©J©ªr•GiLY¥­XP«òE¬ª^õG;ì»;Î'L8e?2¿—±è—øÛ‹~ï2Vwþ±ê~Ž‘Ÿ—ýLXônûsH}ÇÑo$,ú³óß~™gk.þÛoÒ_æçߦ¿Öõw>tpÀû©ã3ÿ·øÞïÎdëHvû¼l°¿õÿòïG˜SÏ¿ýÏÿþ®´ç<ÿíý÷°o‰Bÿ›þçÿþNFïÚØçýoû÷ÿöni®ç>Ô\>ƒR[ä·Ë¾ËëË`ß J§3(;ƒÒý“';ñÑýoÿ÷¿³–”Iç·–ûÇ/ÿÓ;[ÒøÙ’Ú»êϘ:_4ëcömÞ®yÑS4aŸf =Ž˜ÞyòjÌÿî^4¼B§Ì½e½þû±Þ½aî–ú»·ºîø|NPã_ïÅWäLPèaiÿ^s¼wJù¸¿[ðw¿²7R ÏýÙúîçMøU<ï âÏÊ’†ï57ˆ5õ_¶z7F|Àãe’F®8Ê]ÓÑ·'Ü5ôG<ˆ);Vï½)ŠDNWÌÆo=yÈÞü+® ŸÃ¼&v¹1‡®, ž¸FäaÈKÞ¥ûŒKô¢ÛÍä/×Û‚Ìáwx/ Wö<x—ä8æ¾"'rV;wºk'ÿÎz£¾÷’8öaJÔ{µ+†MÚb¡.Q2!áý/±]zšÙ8ÏÐÑö¦™JÏ}+Nßòä0Ü`^о®wÞF˜ó±õ˜]’*Ö§#JNÆ^¸·Àu©ϰeŠk‚Kòœ?Ž£`Уçü-Úâ½åÂÁÅGUȺ6î_‘ךñÉw×»"~o«Ê·¤óôëØ[©ò#œ·ãš°–§GBt½+âÈD$6sWdæ…E‹#€+r_+q|ë·æÛFñdoÉEã“g[Rך#žÆ™%¡€öú‡i"û²ï½†tË#†ì¾æ$ƽ"§7-Bƒ,öãÐÈqì!ûN…Ò’,>kÙ8’Ž$ã—'Ž–»½nšÏÆùx ÙñÐÂò^9d£å5ï=æ‘ïõpîp’Wü¸ú²×}FÃ5"š+Œ0÷kÞ),¾Õ4 rÄ4±Îs®ºmd¼KrÜÇÜ#öRç¾ßoŒØð#ö [¢;Kæ±³çhŒ‚{Àúñ‷ç­s¤EÀò¾[ô¼Ý/¥ç{gßïTµGìbûEPó=b׃S±¬°GlœEÝY²Oëß.yâx0 Ι_/GÄ“ÞáåîKaØØIY2sÄÆ¡k^s]9bÕ€áê¿G¬Ÿði{ÄîÔßûï™VovÁÄì“î»’<%ˆ€à1`# eGÉvݸ$ò„mGøtÀ;tÒ<§Ý=`ãt%OØ€úÝÈ[uØ8ÅÙ͵ã¢Î|Âa¶ó¹ûIþùäh}°{îáé£õŽ¥$xbc:Rþjîö-ih«™_ñÚw_³½F>­*ñt±*çß¹¾^!4äo޽¾†?]Ú6ýïÁªp{°æ“Ä!Ä©øóÊ•5Ú?'º8GŽagò9}Ç!ߦ)+OŸkÉÌ•õÝ¿cp¯•+k<É6}< aÓ5vÿ8BD~oº[eï ŽÆs˜â£a€•ÃT%g.¬qó½8–2èŒ+ív|1LcÝòÁÑ®\XùYvcaåØyK&Æ©øÉ•5~õd5+kÎJQ²°²¾éB VV ƒ#v?9L1tÞ-Æ66ÙßmOçÇ»Éaú~­=å¿%XXß¾¹OµŽwÍaÂIÖ3b;\:ÄÑ/,¬zœ~aa½Ð=ßV.¬ìgG°°F8°¬fæÂúä'VU²Ù»#ª¢Ó®ãýP¹ªrææÅžgöLø–`U½æ&ëã8°¨N,àGÄÏÝc4&Í,XT?÷ñ.)×SÛḰ¨r‰z7hXT/ìëÞ,ªû„9 ž\SON"G„RŠQú’XHÇâšzæ!á[‚5U7?[®©oý{ÄgÇš:0:Þ—Ê55”# ¸¦b-|÷XSß}gÉÀš:<[>Î+×Ô‹Ú·$×Ôˆ†”7ž}ÖëI“#²ŽíÁÊÝÍq¾_í9jㄉìœtH{×=ÈûÆ­×`ß‹j8Í,Á¢z°'‹ê;1m/¹cœ¹¨ªÙ#ó‰M[~½1rQÕ'ƒ‹Ü9‘!~oƒc´íþ›ñ½~ÛwzrUgN GØêç6Ë÷[ï=X£ûî{_ ‹*·¯G¸<ïÑã/¯é¹¨Üá)£õ|÷ùi®‹jXŒ,™9ZCˆÊkUnÔØ"ïÑÚ{ÊGl/÷âw§"’'%»¹0ö›±üË”ã£õl¯ˆ?œ@I®Ì³r`dœÊcràc:K Ñ®bàžÜ¾&ŽïSlŽX€÷ª ž!…Pà…ÿ¨¸KÒá8ÂÍ5Pàã \ÑA#ä\“8ÀH#„“Ü—€Gèù À±´qŽ¥çŽ¥m:(p„òšx¹!plÓ¢¬7!pëg¹mO|/AÛ«Sß n+¬¼ °±ßÃÔ¨Ü6Í(É¥*üRô"† ~îÇÍèljcB`˜(! 2 ° T2`‹ÛûYÓø ¸*†@¶°½_Š ½öRn7ƒ8ìÞß8Š[vë€s…0¼ ·‚ãWŠ<¶—«¸f~0žø`ð¬½\Åþ‚¶É€¥f0` ËøÙærÕžSr¹j" 2`3É‚Û=çf¯Wþ|dÀ(¡Ö¸×«0cj„\¯âè•"÷zÕÄëdÀx>8L‚à ª&0¾'ä&0`|sø‘›f2`Ø»AwÆ›# 0ž'¿!°éŒmú| 0’œ@-7½ýÌ„ÀèøUB ›ØîÅ%ú{’÷ ¢@· )0ºr6;)°i$ºç’·¢@÷JR`{°ôˆãk%“ÝãHa1x(°½Ól’Ûƒ]Š(0¬ ³wƒ›Î؈MÇÀÀÓs²"úÞÄ@éÂ@,b`Û¦œ…ýÀ¤À&l%6î9E'j„À¦£NB`0KŒØŸØDgäÀ&Ò&¶·ú‡ãWÉ_ÀÀ&Ú6îµÅa ½c:‡=90JvC›™$Ø´´£d|`pÛžî¯@l:! ÆÓ¤m(a°ia$ Æ—¢£žñ¡A>²`0~”ÛTÂ`ãž@0Ø´ n¦ ÆBØ“ï€u€Á €LÀ ZT0¸­Bö6‹0X^0XK°Â¾Ý$·²¤A <Ñ :¶hPÃ^4¨(ŒzrLŒA4ò^ Á¨'Ÿ™4¨i’4ØÂd8otó€K-Âè£ Bÿˆ@‹S"xP½V<¨¾$ Œ×L6%Æ\–DA ŒzJã¥ò Õ·„š¹„ᢘh÷p%:Ãg1ÙŽ@¨V@ØŒN „ñ{{$ l2Fkåq0¶1yF@ ô'6 .B­DÂró› ,Ž»„häÁXó’ÝɃ~Mò`Ô’ÃÕn|xPÛ@ñ`Ó±yÐ Œ7Ï÷$jq'z“·d^lJă1Ú³Û’…aÌG> €°QøÆ›³ëkÇÞG@¶ÿ9Š„Û!$¯6>0ü¢®DDaÔ“Õ€£³ q°ü8ØN΀ÀÁ–û‚ƒpúg’*‰ C¶ZmPK™0ìˆ@‰ÐñIÚàûµs…‡6è}µÁFÔ•6¸ÓÖ‚sÑêFIhƒ}[ ¯Nð–4&u baJƒ/kᘗÒ`gÿ–4“10׬ðQ¡ð-¡ÀIi0¦Õt%¥4Ó3T>Hƒ½ˆ…{Ñêa[š<i°?ÒýRìa3˜º°°K["v©0ÄÂþÕˆ…gp¢Â~KÆÓô4ص %vm“I…]Û3Ra" K=ÀB7±Ð/A,ìB!`áþôù#`at!xóì%«K›&ví\I…= ³á’KV1 »ö}¤Âx`DÖ–k@…ñ­hŸkVÇ0º  »EH@a¬ô× ÃD‹6̹f½ÏNl@at·Áˆ8{ÍÚ6¦ôWÜkVŒRºî5+ÞüÄK™Ð·&Æ8§ ãGpy†*xLØ9‰ »!È„1ü&L®ppv‰ÁdB› »NÈ„]ûY2a?±3ú½È„ݤ–Lع/FIöZ0¡Ç+™°›PÁ„îKdžÕ&Œ7OELèá@&ìâO2¡Û‚LØÅSdBX2a©L­3Q’L¨‘F$ì:J!ú£ cneÐãHQHØuA$t_.þ =/‘ ãi² »Ž¢È„]OdBM“dÂxb(x`Â~ò€’LØe@&t· –›ƒ c½‚Z&ìEƒï®Šl  χ;ÙŠ4("Æ’x~p°ó\Ù8Èá öÂÁÞqüe ¿ÇÄJà`§™p°P¹…ƒ½µüžÄÁ¨â$p°K®Γ/ ì<.NªGÂÁ5Hm‰ƒÑ\ÀÁ÷GçGÔùqp²)„ƒÜu »pA8ø\€?Ñ !Ü8Hõœ8øÂÎ]„ƒ833 r vZ8˜Åò¢Aiœ¤Au~Ñ -Dƒ:d Þü.¢Ažwš¥äйÿ+4ˆ³rÓ wš¦AîMLƒ,×Lƒ±ææ¯HƒbeÑ Î]Dƒ\ðLƒ’J…ƒï0HÂ&J6RM%À}á`;éÀñ÷ó+Cá_|ïÞ?²`øµ­Ÿæ¡˜0uÁ¥2tÁ%È¡.¸&÷^DÀFVÂ`„YYÜAu! .ÚˆX´lIapq%&6›_R´\ŒÅ*WC2 šÓ -=) ò”Wº ìn( ê]Âàj°Ü’0Èf àû£‰ÏÜÕ俏¯É2°\Ü5'gƒ÷¯r|KZú ÇÒù1p;BLÜ騸¿^«Êà~OŒ‰€¥-€€Û'#·‡‰€[5…±j"`}âÍ€»ÞY­Cw½Œs¾ªÒ`À±xèLÜ÷ž•Ëó÷ÍÏÊ€å‰Á€»-ªqèˆø—Ìù™IK‡ô`À]Â$Å:Uož Xz°<2p¬QCË«'–'ŽE}%°´°V› Xo Xo” ¸ÇýYpד{i0`éì`À2‚Á€U@À{Ë$  /îZA€Ÿ’‰ÑzÂ[XúRàþv@ËÜïKPÍ&ÀÝÓs£ ,}¸”¬wJܯЫ*X®–n,#Xî,S° "à§dj¼¢žDÀbÂ,Ã3pw%ˆ‹‰€¥½ë]³VºŠƒ‹ÅÐ]¸ç à^`©XÞ›î{žk€õš$À2ÆA€e¸‚÷ãäi°Ì‰ ÀZs`}Â$À=B`„Ù††kû$À2êA€n‹À2 €õ7 €epkI`iR`Y¦Á€¥)À€µdÂîÆ5/,¯Ú߃=}=YÓ=¯9°¼²qµž3×רí%J¬¯ª~>Bàî€3/¹¹¾ªäáúª_M®¯6 ÅúúÓHt¿CÒG¸agAr ™èQNÜ‹2$¿ë«L!‚cQ©&ºOËK$Ê ’èÕ¸g@¼Á|Š'¥1p_Xk\]É5tve§%– tËËo–V*Z@@Ï~D@("`©åæÊÊÆîzWU÷³´¬fae•–ô\‹–DDÀ]q2C"஥ÃfK+ Fˆ€^$‰€»â4‹îwÀ½/,­zb à¾fæ½,­±Ÿ„Aèf@ïÕÉ€û‘!b.¬­æ çÂ.í藍¨ä¿SÛjêÑ/¨}õÑúß©-<õ?¹»Jÿ;±Hþ;åaFù/~”ŽW”ÿNn=¤ÿ"Uê§Ñúß)‰ú_Kÿè¥âÔÿNÊHþ;¥£PþSG—üwò Kòß)m”ò_ì >êß)Y‡êßIÁ@êßI©§$/ª'N®%þ4:’øwr;,õï·Õ¿ã¦!Ä¿Kƒ´¿“öÔþNŠéÒþbS5`ù¹WÖSnbÔþN{Bû;Œ^Ðþuj§úµ¿CÍGíï ÿ%µ¿ƒkŽ´¿cÀGZÚß¡£j‡Å¿ø„×Gü;à¶/íïÐg¡öçKRú‹|~¤¿.¿TH‡ !ýuY„Sú;¤iSú“-¤¿CNé¯Ë"€Ò_wÜ2H]º2¥¿.’¦ô'ÃBIÝÆ¢þ"ú0 J!ýuºpHúëR=)ýu¯Bú“Ý™¤¿.W_H ƒ´¿ÎS›š‚I¼–Xgå½%kðÞéIÂŽôN°ÒKÏ.¯F‘#•¢ÀÈíF–žGdè©P2ôäi° =cWTE¾+¦›»ÂÞ®w|D>—ÈГgÅГK˜ =•@†ž<-²¡§¢ÈÐSïICÏ{’Ûhè)Ë6zj÷(COyòÉÐ3ò}üÿbÖÿaèIKzÊ®M†žú‘ =í¥G÷¿ñÎ ôO”§ŒœdçIóÛyjc-;ÏS*$í<µ‡¢ç)õîŠTACO‰¯2ôäaCOšÛÐSËÐS»]zÊ|J†žú2rÿ3DÒýÏ -={ÿÁz2Ê(îSé\àœ`‡@¨|SÆ[Tù¦]ð òMgIå›6ÀL•oæCöÆ´aÊ|SÞœ”ù¦­A!óMxwHå›r}¥Ê7eF•oÚf*ß”M$U¾ˆ»û‰³oNÀ<ŠÜ¹ÜŒ óM[¢Î7/rd>¿e¾É“4É|¾d¾R™o^.È|“[É|S†Ù”ùÊCæ›? =Ç”E0e>ÿŠ2_)Ì7åÒH™oÒzG2_ùd>{[Sæ›2•¥Ì7aW'•¯ü*_ùQª|“V“ùü] ò•Ÿ@äóPå 6Õõ¯–@æs=”ù¦íE!ó¹%(ó•È|S¾¯”ù¦L-)óùËPæ‹øî³Ò^†«_Ê|SN«”ù&R$óMly¥òM­Pùü|Tù掴/ØÛá­aÔ •Ï-A•Ï÷È燣È7åO‘o+!òE ,A!òEF‡tǦÈWJ ò©A%òÕ’ù¢‰?ŸÚJß”÷5¾Z²R§í-¡ñMÙKAã›´J’Æ7iœ,o*ü5¾ROÍ%¯Ô A$ñMÙhBâs-”ø¢–ãω±JÃ:J|jbI|¾7%¾R$¾yJu>J|“.:’ø&^)ñMûÃAâóóRâóÓQ㛌Þ'/JR¡È7åpF•/Þ»d¾)÷-Ê|Söp”ù&Ï2¥óMóÍ“R d¾Û¼2_TÃØ0XZÙPù&7¥òMºbPåóóRåsÏ¢Ê7¹Û“Ê7¹q“ʧžE‘ϯD‘oro'‘oÆQk…½] ìE!òMY@Rä›ôÈ7éì%‘oŽ“^tùü9)òù^ù¦ì“)òix@䛢gŠ|ó¤Õ)4¾iÏ@h|š¥ñM…]¡Æ;“l j|Q‚˜/XWÕC)ñqÞ•Â7Ê–Tø&7ˆRø¦ó ðÅÓ´d4H|¾7¾)w(|ÚIIáÛISJ ˜=Ñå¾X¾?š˜ÉN»/ÿ}‹OÉDA<ËéÏ}@Áù#ÌŽ‘ óNÄUxF¢à©x-Šª•Tñ@à@ñ@µë' FWR‚Ç­¨)Œj:djö'—”ºPVêR‰ëÚMgÍþä×Å2×å’uƦsO§ë_›±éQz‘~éþ3þíÔ)¿ö…3ìâ°ä•ùÙ¯¢ÇÄŽýs‘ªb:&ÕätLªˆ×°_ÂjœŒ‰õÔdL¬ÈW¡¦z‘ªR2&UU’1©*]ŪÊEªJɘTUIƤªt«*©*%cRU%“ªÒU¬ª\äQÊdL¬ª&còèæU¨êŸÉض9-Ž`ÿ+cÓßÏØôGfç¿ý2ÏþÖ\ü·ß¥?ççߥ¿Öõ§“%EæžÈ|÷ÿ_®¤wªª¿üOÇ/ÿúâÇü·éB'L:þq¤36"ûxtoŽ8b®rp~¾«{:65D*>Ðàïâñx† âŽoAàŒÓ]£ÕœG¸ÅæÝ'¶´pãYÓ¨ÓŽ4ÛÛ’óÿaïÝ‘u¹•&Ë©PìRhH Ÿã¸c(+¡Z(¡æo@¸¯ˆÜ‡¼$¯ýÝÖBIäÆÉùN`Á="Æ„¼»x~ß“ìšìJ1sê9îà¶ÛÌå5Ù Œé«[“]ݾÏkŸß³´¡¿›´ß{Y¡ÓE·Ö’l+œ· ŠÊˆãÆœhGð´Žæn¿­z@kî;FLìÖêè-çgѳ˜1ç¼cn£À°1M¨÷úrj;¦³6’ßûZí³µªY,ûœl]±ó˜·ìs)~ÒÓ2Ç;u¾"ù½¡|L·ü1·29޹ŠÉïeÊ{[V½å,54&RÝ«fŸïË\iž“ÝÓ+›ïh>+R¯ŽŸ8­é­Ò&‹nƼ²«¢„2!¹Ú²­!Bëc®ŠœŸËuDÁÎãô\w³Féöég.u©Ÿxæ±GI}æÇ*pÕ3Ÿeæd÷4Ý Õo8Î]¼?V©ˆµNg ~‡’c½­sYQûŠ´ÂëW«›k.vItˆsµ+^VûœÆ5»æõZöûõ¨)ص®–Iß–k½¬'/Þ¬ðÞã¾´èæXõ¼ÓÎ…—ïfiê÷€ï˜¸¼ Ë2³zé±ÉuÄ3_¤ë^&òò Ϭõ²Úßò²ñµ^ÖÓ%µÞ~·Õæš—Bûz[O>ß–g½­§WƬH·­mbñpL1p½¬ç£OïT8W]gYS^]/««ee7™×Êqkc:—v=&#p~Öõ”bÜ„|ÌGaMáÇ=ŒgÇZŠ«üÚD‹McŽë€µü6<ñ²æ&Û/«ãvÆó~¦ÖËj›ú˜É5×´ý ~?/òüŽYðxïE³rüzYåíÅømžñ¼ñçoª3ÆšyŽÓn´±"Y×6ÒZÆLa°^Užš™"e½ªÎa¹·9®Ìmn¥­ÚÛ6~¯ÏÑ>óœ®WÕrÛ¾ò6G/ë˻Ϥ¯ë]½µ<°ÏÑr½«FÚgFÜõ®: sŸùƒº.Ö÷•¨~m#Ak_ÞºOí;¿cd= äûL®´ÞU¯.îÓö¸_q«VäêUÿÉš×>}ë]up÷>˜Þ£\À}š×»z]¡Ví+KØÏÖº83O×zUŸø+ÕÙE\ß™ñl‹GO›œ1¨2N¼£_‹7¥ÇW ªÝõ}ùm·XŸYǾ=]ï©4Ñ}ù”·èg­õí½Å¨Ê¡ö-ÕÓ€½÷T绳œ7û4[Ç{ªÏðÞG ª§öÞ¡Yc*ûž*ðsÇ7"N©1¦æÒO©N¼¶O?{¼¦úÖìsùd Gž·AcªƒÓöþ¬15ŸªÑöïkºMcª•ù}.Q­×´k©ôLœzM…ûSeèßgÕÊ5¦ºØ¡×Ö±¯)¯/ßgŸËlëMõh³Kc*g>ÃQâM•™sŸ…câMÅ}ư¬õ}±bWst½¨Vöö¹øº.Ž&_û\‡ŽÂŠZÇÛ÷¾UDÑ}Eì}ž¾ /ªVS÷µä½U™zö¹ä/ªD°}?5¨ò,M=^ÔÃ-—U ÷)#4]Ròœf_1áØcïQdn=«›)…¬µßaóÙ§š³^Ô]…Âö©%­Õ ûÑÖ‹êeÙ}ʵ[™ÉìS#AÕÁüFo1›ˆ;~T½2¿QˆQÝý¸4¨z=xŸÕ™Ö Úc¾»ÏzWë]åâÍâeë]µV¹Ïù_”T”’¶Ïù_Ì€p·Ï™RÌ€5<îçäµ^¯Ìœí­—Õ1oK ªLÛç¡®·Õ©\÷ydûëûñõ^ïöšŽöu®s¶½ÏñÿŽ{ßS]ÝæXǘ:WYc“'ÆÔ©Š¯a,–'¶ºÍµÅ˜zpXjqí¾¿[* Œ| …/å!À9󊩌d\fªV p9Iƒ¯D€éü6î·«&šWú5áRàÊÉ݃܂ߖþ%À•’ æÿ"À•á & \9•bÖ+ÌÌ.&ÀæÕopJzlóÕ‹ã6Ë(A€ÍÖup&ß׎E€˜â!@çð‡©žRf¤PH °9àlžª@€Ó%P6'K?"@RFB€›}&@²"B€ÙJàVx/F+Êp@€ë@€Í2¸ùëÎ̘1Ç5΄•ÌKjœÒæóÀÆŒÛè”›`s‚,$’`ƒY€3ä‰`{@· ÀÍBHNpó§l¼¿&@òšB€›Œ!ÀÍa´ 1*àL$jàkD€Ä56Rý$½'˜—ÝèàÜ&ÀÜB˜GHÆMp>éGÐÜÊqjCH ¸Áò@µ€›M`>|@×Çÿ6{dÀÍÛàfó˜£Däà46~d®àæðàæÒäàÆ×PHL ¸Í“‹M€eàæ$¢`¾áÀö|èoFGÝúÛTOøÛ<)‚ÿʱˆÿ¶ŒŠÿ(…ÿå7Áü·yUþ›—&&{â?n ü7Í =À-øosõuøoc`7ÿQ ÿÍ#XŠÿ6»Ãà¿Ò³ø3‡ÿ¸ßð×þ#›>ÈÕ]“þk6ÄÀ›‚ÙÁ?î·ù$ý  ï¦ òàf§K`ž¡ pVŒ¹>8W÷uh"@¾i ŸpcFf$ò ä+òô€›×$a@²uÀ›3)À€óMn„€¤|›sœóNù4) æCmܬ¿ƒ€ÍYÙ@@†(°yalŠç6ñ`›3H‚€ÍòØx=Œ€ m µaÀöÀXb@Ê™]\ œÙˆãi6/˜€Ì8@Àæœ Åü@@ê€Íá `cõÆØJ æ³mœî®ø‘°Ù_ 6xŒ€d[b–°±ž`dþ 6û=Ì€3`³'4°KfÀfw2 H±F ©5Øl—›œ@`îÚØð­y_†Àfo,Hm& °½ï…°0 0Ó3ã%Ø,—ÛOlv›³Ís8C`&G3®ÌËñYÅNàÊnÿ <’9PA5…[mÍù@™3½;Jà·X •ÀaKg*&y”À鈕Àá¢,(ÃJà$»˜G¢Ú%ˆ8”þ!p8ÂÈ8çŽäËÀÀáZ¨`à8!'càðÊ8œe $w8àXsàH•O8œ¬Äâ⨄Œb$E ˜'eŸI §04ÐàÀþ ^†‡¿”p`ù‘8pxÝÄÎÏŸ9p°2a.˜ÄGŠ—ÁÐbÌgÔ$8üÉ…‡+@‚ÃK&Áá¯%$8úm6 ©ê‰‡?„ ñFà@53 ’b .@ æ3h$S$8ÐÀL‚Ý©r Áî<`àØüN˜‡ËÍA‚¤òs¡àLÿ·Ï,8œÏ,8:žXT\Á‚ó3…Y°³8eœÛeÅ‚:4 ÙàAÁ<£`·ìx#Ì‚¹+³à€Í‚ƒ³à€ýÍ‚f7 Ú ç¹2 Îk¥£ ç#1 æI»NX6æWß8Gv×6ƒ»+ØB‚i1 Înzô#Ì[kÌ cì¹AÁn€»Ãþ@A3£ WN­h^e¹q  G v+ç `÷º(ˆ·ôÍ…»¿é`w:YHäÝ…;“q£`wÙ P°;þì&Í‚¥v³`w\†a°†Á¼€ {ê…–]ËìVäÌ‚åŒÄ‚Ý#4,ؾĂ¥E,Ø]Û ìvÁ‚ÝßKXpžSLm͂ݙ¾aÁîÔžÀ`÷( vg7 v[±€Áÿ»#€Án›?0˜GcìÌ7 ƒ3P³ôÀ¼†ÁîjÀ`WH,X~$t>2PìX `>GFÁîÔg `·C ìv»K2‚]èFÁn»(8o¦TF¡`wd6(Ø=¬‚‚Ý" `·© ì© »í< `G–5 vW¶‚;jšP°;¬œ>É[à£êæÐP°oPPpsnP°{Û(H5JP°;d$P°k…$E$Hè$è$Z€ ƒ«áÀÍÓP8°k0·|v‡ª€QÜ0z˜»¥„ÀYT4úH˜¸Ùâd,G+ìž±˜7§˜‡7G!R!p³À‚Ø\ð/j"Á}±¶U ^éH¨Ó¥$÷)È6  —BÓÊÂ*PÛÀ> «‚}[²˜°º‘`ß– (ìÛpû6Œ>ƾ͕<ྠ«¸oCC2÷ÍìuÑØ×µ^õu³|P_ǽhêë^Ñ…ú:—ÁÔ×µÊ ôõŽü&èëŠË…ù:z«™/7òu„S#_wa:¯³\oäëiìò‘ äëiOòuå~0ñu×”„øºóo˜øˆs‚øò´M|Ý!Ö_w<2Ä×½”ñu`ÉÄWúñuÌ©&>>¾_WÌ2À×½FðõÍ¢¬/»1ðuûT¾¼3¾nW À×=ÅÀו•Þ›ƒNj`r&:x¯;TÞ+¿ïuWS„÷œËÜËcÜ#ñdâž³h€{X÷¶Gp/wnÜ+ý÷8sÑM¡½ÒKÐCkÒÞ^úS‚£i/ûíug€öz·eS°×í£‚öò@{Ü~hÏÏ•a¯;%&°Ç¤ Ø+»ìå“fØ+»2ìùÓbØ#9©a/_Cñ^>­°^¶÷òsdÜË÷z tæ=MÁ=FAp¯£e÷ò}÷lîåÛ îñA÷x™Á= žàÞÜû]q¯;¸×•·Ä´×» ÚãÚ$í‰ÈŒzØË@=K̉zèT ÞÀ•jÖK…ѬçTÉz¾-ÉzLLa=_Ïd=?$ÉzNBŸ¬ç¬Ç¤ÖãDÍzg§X¯§X¸XÏs[£Þüïõ6 =)ûÙÒ›²ŸÓ[¦ìç°[P:¹)ûÝ·Ì¡Výœ“+U?¯tBz Œêç˜øTýœÑÒÛð›ô6¯å#ûy‘7e?çò6ém(ŽÈ~.h–²Ÿl€Þ‘ô6Ä/ƒó4@¯t,Ðãjô¶d6Þ¼ ò¡Šô6O!=j0Czy«Lz›UHoó*¿IoCÄ5é宄zT®õòÙ2êm)& õʾ…zd"õ6×@õòþõ6—ðõȱ êm^Yõò˜Ízkf½M…qõã„z$øMÔžzÛeªé™” z›Ã6ô(|ž¤G½ÍzG‚Þe‚IoSLI’žOÇ W` ÒC?éQ“;IÏy¬öøLö6güKØÃÖíyÅ:io˜iÏiî =Ü@Ð>hÏ ÉI{M¹j“öðg˜ö0íüAõ#/V>ÊžçÇ({XÚLx›#@¼Ž·Ðˆ·3‰2âíJV áí6¹CxsVü|„½Óùà ¼iC1È„w13á]LéMxWº7ExR_ÞUˆ/F¤+ƒðˆ+ñn AAx·ïÞÊÞP(»m¿€ð. Œx7ñiF¼…ÂŒwã4ãÝó)Žžy7ʤ!ïfZhÈ[™AcAÞ5Çêä]žd›ñn‚ìÌx7wNwždÈ»=ß0äÝÌH y·«Ìy—qf¼+ýžb¼MÊŒÇ]1â]NFâ]N»â]Žpñ.„,ÂûÈð¾)PŒwiÎâ]s~ åð¾Û¸¦è>/#BxAÞeÏS†÷¹:B†÷ÒdÄ»T·)£û¼fApŸƒQ2¸Ïßê îãpÛǽ5à,èdpþJ÷ ­Ogp 2Á}ŽÝÉà>kîzÌ îSı}?û”ãÈ}–|Mw÷0û¼ŠD`Â,}À$®Ï‹›ÐÝáItw°ö¥µÒ}¬ØçHØg³SöŸ¢»ƒ@\ß~ú×ÇK@\_WÀq}¥Aq}|äˆë¨‰ës¾´Œë+-Šëc•€¸¾~Z½s\Ÿ«3®Ïo‘}\Síë¾;¸Ð>§x„¯Ð¾Ü«oGâ2àíVˆìsÜ.€·§šæÈ>#SÝ«ÒTw2Í0Ö]‰ÂXwy`ë.&ÒÆºÛ~¨îþ…ꘛên'Õ99Ÿ±îÞˆõ3Ö¥4°îrð(Xw9*Õ\Gfqá𙸅xAs݉‰Ì-ó%ŽL)â:»‚u§]`]NõHÜ’Û8q §d¬;\+·¤(èÄ- •âº=Mžâº£9ö0°î(œ÷(©(ou{B’°îp!D°ŽÜÂpݱüç¼-ÃZ³¹næÇýÄ`ço?\çôÓ`ÝÌl®\/uïqû‚ ëÞOŒ…u+4”ºý±Ñ<}½rºå÷¶–w¯ŠÔvö˜ëÞzYÙÒI`]ýM`ÝÛâ›+¬{w¤VsÝʺôQîÖÁÄ›*°+™™v«¥U§féGd·JŽ+-J]!7Ù­_Eì®È®öd·Ž90.À®n²Ànç¨A{ëjõBvk“³——ﺴý-™®GíøG-ŒvïqXEÚ­ÄzAB»¬mo¶«ÛÛÕ–`»1ܪO³Ü'±Ýº»q†!˜‹îÖ‚QŸánN¨Xw«›h¸= v‡Û­@¬@ÏGã)уB;R½šìÊeÙ•Mº†S4CÝj‰nw §ƒëö'í–‡ÆSW ]h÷nàTJB»•LcÔ|-û« íVz 壕…±ÝÛâ±]mÙ4 bÑÛ½3K?gb»ýÁ)¸[GxÕ„-ïÔÍ€J¬gA¬1§‚»ýqº›`»wO^VÛ½[ø¶{71ÁÚ­ß¡ßþì?ÐoÏž…~»}Ë ßžvB¿L´hôÛ3*Pè·ƒÉäìt͉ÌÙɬÞ9;‘bÈÙi9Iè7ÓØíŸ@½“8)Rv:Ÿ)Š“C“ßIV“ßÅm!cç­5’”ôÈTCÆN¢Ìô¼Ö’’Þ¥J)é¹nF¦ìô·5Svz.mIïÈP>izI[ÎØ‰ò딤[ý7šÞ£lN™²Óc¢ÞÕ~†é·5H‰zeD=sGªzöÎYÕ;7ë’VõN²ø ê9ÖU/÷…ªw_9¥êÍiFl#U/Òª^<Öôœm°Èz YG|Üd=¾OÈzB¿²žÇôÔõ¸äëôjfæëL%ͺœ‰®÷ì¤ðtÂNº^ò¡u=Ò$‘°“óBØsîB„½ü‘…=.…=Ë>)ì9c+ºžÍU©ë©ômÊz<Œ†¿3cû§sħ¬—¹7-륷Ӻß5t=F)t½ÜƺË^èzÄ¡ë‘éѺžC~?;e±”®w:,]x t=2)fÆN²±8c'yöÈØiƒK {Äd!ìáaBØ;`F {™ÑÒÂ牰—é8IÙi-Š”œÂ¡HöüÉLmÏ‘h{i³tÚÎãøh{{s§Öö¨ÒÚž5÷÷<gÚNn/âž+ý¤¸GÆ Ä=ÒŒ"îa-̼¤RqâNŒ·ˆ{™í“ÄÛq¯ìÝê:­Õ=2ZÜãb9ogGMsÞNäVòv:Epæíôü!óv’d2óv":o§?™·3MŸÎÛ‰¡¼ö,•¼ÎœBÞÎC߆ÌÛÉ‚‰;¾’¼È®ÎÛ‰:’y;æÃy;I•k}ïàÑ·À·“V/Ó¸HáKÒ ßžÉ_¤ð™ØE _9+|nGá;leD೉-¾SùÆSàó—4>âØ,ð¨Iø"N-ð‘N±Æ·“’vi|#óxZãdÐøÍi‰oV:RÖI|$i@ãÛ-ªZâÛI܊ć?Ößne %>ìÎh|Ž£Oïp $>Rc ñ Õ!BáËZ>G‰¢ð9ƒ# ßÍXá#j…ïwUøb—m±Wê­dŸúçªÝw•Šn©u‰þüw¹•·ùÏê-Um«õ7²%ë¹-kydKÖ :WñÝZ)[²/·e_ÙRúšî½ÖFÊ–Ò—ÚJ_´üW×3:V)¯ãëýR(ÊíÔjù“ þA=£_Ÿ…÷‰]£K­ºòó¹šOL·®[Ñ—‹ÑUV+¢'oCG¹ûÉZEî¨+rO¹•»ª[ÑÅŠè«T+¢/¶¢¯²}Q­ˆ¾J¹"úb+ú*[ÑåŠè«Ô+¢/¶¢¯²U¾«®Wä¾jÁ¢|ǽ•ûúOÊÍšoÏþüIY£þïÊýò þqY£?ÛìgY£¿èîç«òs³Ÿeþj·?߬Ÿet~–5ú;éýò¹ý£Oò¿þðeýù™þã—õ×¾þqY£)®ïÇíë½WãäÿþwªýUq£O‰¢ÿýßÞ¶—Ô>ÿüË•Æÿ¹ÿƒ2G‘…k~ÏîUUÞïÐÌWíD¯+ÖAnÿÛòÌÑ}¿”eؼæ÷Íuyß/È.$>pQ¨HÖƒ;VìÐÑèwŸk_OdM;âGûñKv°¼s®mrsæd^ˆô(:éŽmÎs0yÍ{-"ÞŠzê±É=§Ø¿¸,+ðÕ¶Ã(ͲEËšÿ,cÅZ>åg|gšÛÀV±ÆÛÌ¥¯3ÂÄ÷.KïŠ5ôì6J¹_%ævy¢…öh¸#ÔÐîžåù[¡†»R!sí+ùÇáÙ‹»«–¤Àh¹·š*e¹bÎeîÒRÂò6n%qÐZ^±†žúO×Îo™™ÄöâLŒ³–„WL°Ì‹ÍVH°P³¬ °##—­§Ÿq’ëØ&o®Ÿšƒ®¨€MYzZüæ¼"W·òŒltëGË›¶–~ŽQr,­•¾È*£ åZ”Ý•Ég­+¼×n °_Çõ2Çò¸Yy~[ž9»Z{_ô¢ÀS`žÐx³Y¸àéÝJÔuÄ&SQ¾Óãz¯´s@Å_s-z+Y¡^zÛ"_OÖõRǾ.—|ïÝ>#*Øë¬/˜ìJ%Þ9î¹øuý–9mV(K_©gäÁ>î¹üuG&1mÓ×ÒDæ ;fFûceÃ’ ómy"*ØÕÞñú\o+qöïÓ7‡Ðz•ï•»sºã¯;‚‚mjxIêü}ÄnÖ}ºïÅx]|Å­\m Gxn¥VT¤ãyO[–A-Ï\ø:3ÙñÌëÚã® µÜÊÿtG%Û÷MYg¶fáí1=Q‘©MkOÇèæ‹jšyV\ÙÓû®×Ô–‹cêQˈjGó1¥×sår‹­ciíñÊÅO&ÜÉ]¹.ÔûÖŽxV×lëlÛâ¶¼çÌ£ùè"lñ“÷¾Dö'92Ï6z¼¥¶ñžm.S‘?U4$Žsfç_˜jwâ9íŸõB½£pLê†S ¿-WDî;”÷œie¦úM9gVðùšR)øœ©íï§à ÖkÊi ‚ò9WâºZZy[žEª¶ž3,q[OžÖúΙØãŒÇj}"Ι¸f½¦¶¢Ÿ3×JXQ}fhåzMeE9W ôV¾çŒv]o©Ç‘s… ÷’dïÜž5¢fb¶³¿ÿ×{d\cÖ9cÞã-•H|Îë-u©¾s&09”+ö¥ìQëR,…ñœÉæ[:\Ý휃̳—ÔwçrþFBÂØ÷CjÞ˜9<Œ8íèºõ¢J.<燪ë!îÑm$[g9IΕ\o…Sê5<ç¼ÞT¿»çzÎj²àsþÛ2Yl=ÇhzUå:g:ÔU7Û1,ç\Ò‰Tm§û94¦r„+¹cMçö¶Ä˜JêÀs&D]cª$±s.«´§|cÏ™;4ÆÔ'V=Þ–š6îœFã5¦Z·8g­óSe˜<÷®AÕ‘0oK ª¹£¹xÔ•Ä,œ†ºFÕl94¬zÍúœ«_1¬²÷Sê#TÏI=«p¶ÓÜžû¥aÕó/ä'óœ’í5¢sZa×Â×Ñ4¬:êyl1¬vKåïÔ †U§!8—vmâ/Þ±2¬œTñõ˜µ%ÛùùÑÃjžÃ `yjœÿÛ¢aU“±ó¸4ªzø<îU7‰ŒçŒ¹®’sàœå'çëº9RàËÄ Ú=¤Ÿçƒ*AýçŒ:îˆ ïñ«ƒ*Çç ÷ZS`K+çÔž•-FArç4gﱫ+º94®*áÉ9ÔóF9cÙ¹VÊÈÇ/Ì\ïʫբ—ûVõR­kŸSÅÜÖ6ZÅ>¯ëæ ¬çµÅȺ9áÅ9C‘W¿Mæ/iÆÈºí2³3ˆt¾®›Çku†˜Ç·âÚcdÝœTæ ëmÝø,]g ­Û¸ý«+†Vgæîõ¶nè:gäîŠá÷Áy­ôJouÞ-ÆÖmMZÞ?¯Oª÷ŠßWû9ã¢Wü>Cä=b\%WþÛkc4^k볦€™ó>b`mG÷6Z-iº³·ÂQÂ_˜™ ü]¶šÓmÃßåÀß­ë ûÝ~_€¿Û‘õ¦¿—*›y+èo¿O“EûíÄ£¦¿·%ÎÕð·?vN þöÛi3 ûãIð·xÇSð·?~F o‹ðUì·?@ØïÝD>!³_ÖV2û½-æL±ßþ$û¥‰ øÃñjø[¾¥˜‰þÊ6‚?|§À_s¥à—®á¯9!ð7+;õ„¿æŒ À_s,;ðGŠxè¯ÍÙGt+úkÜ]Ó_ó” ü#¡>üG~ø¯÷æ¿6 Bñ_³ ÿ5ÚÀ¿)J)ÿš=nà_sÈø×ìÁÿšó<ÿš#¥À¿f-Úø×,¨ƒ”°ÿšÜÐ_³`ýá\ƒþšÒ:¹'Ã_– ͶGào֗ЯͯÙZ °_spì×dvýfŠ'~èGè¯^Ð_sYðÏõ‚ ¿æàß,ØñÅ?Šz€Ô­€ÿš³Á®¤þQÁü£ø·ñþ˜ÿš£=Àr8ÀÍÆ!Ä'&@Šÿ€€Ô3 l^,7— 7{°A@J^€ÜpŽªíÀ9T™7q:HõÓ›Ã@@*ô€€›¿k à€© rù@ÀÆÔ^˜°pób‰póª H)psx*˜Glœ5…†ˆoûTX7 Ì8wàhÌI„bd E™@Àe ”^Võ|ÛH]!KF@j‘Á€yEÅ€4g¤V ÈKæí4RÜ\X1ÐÁ¤É€–åa@ Á€Ì䌀yqŒ€Ô£©?² æÃd¤‚ H•µ`@ª;Á€›VŠ@ÀÍá `¾ÒF@ž$` ÿòFÿòå5þQü›¤˜Áÿò97þånüc½üÓÁ˜ý6Wœý¨œûù'~©´Á¯Ù¾iðkž~ÍËç€_~{?Dƒ_S*/Àáðk@’ɯ±˜còkNÞù5üòM~ÍF7ȯí·ûùQòÛX8ùQ‹òcŠbô˳2ú5'øýfËñA¿f+è×\ ôkÉZB¿Ù„Ñ'è×ÌÛ&¿64~ƒ~³¼QŒF¿æÜ' Áo _sJpЯ٫ ûµX‰0øµÓ('%óä—7ÅðGy&è¯yÖý5>Ê¢¿ŒŸIúch†þX2…þæ"z¶³ÀþìPÛ¼#§q•ÿÎø>€Ï¡`5ðq%#`™(‹såÀ˜Y»ÑÿÈÑþ——õ¿¹x´fE–ÿX)BþKDò_wáoä¿îË)! ÿù+“ò_LЬý ;SÑþX}EûΊö7TÐé´ HÉ=Á?çl@úNwý Ïü ¿‘²žèo8ï(ôWÎAÒŸ— ¿á×*èo ωMËöÐßp^'èop¯ÑþÐ¥Läy€þ†ß5èo0³7ý gi†þ†¢àSüs‘*ào8ô7ö¯ò—:š•?¥ú…ü†ƒöSøãñù ZøËIøsœW HÁìÚºŸtB~Ãn!¿áx¤Ôýð¶ý¨ úå=@÷síÔýº)βŸó*~Ã+Å Å_Rös´²ŸYÕè7œñáÏ&ÀTþœ®%•?;Súãš#ýÁ”H¬3 ýÍz„mb¿òŒöç0µ?¾rhŠLíÏæQØo°€aöÛmNñϾi³ß°):å?T‹ÇÙ0fíõK´?±ü†“I¦öçù¹ogâ‹ög·lj¶C~»…áÔþ ~³Ø—~%ðÛ™@£ýŠôMíun´?W"JíϹÔþEúüvWôü†×àÐþ¼Œ“ÚŸ#–RûcàGûóz à·ûÓ ø æyˆ'8+òÛ™Õ!þÆbÄ?™'¿r6ø ­À¤ôçÏ0Ü—WéýÍÒŸc&á¾½]JièRhNi ÷ fVhçõûûòF!ý1q6ö1"}T¤K鯀 ¤?×ßû†mép/Ü7 ¤?§ƒûTlî¶ÉÃ}µeîÈCpÙž¿áê±€_°Áo8íä7œ*øÎïü Ûæ¿‘¢àoØ~üá^þ(ü1wþ(‡ÿQþËO•ùo8†Ú8Q{ÇŒ€C ¼àð\ŽL…|!ÀÁrŠ0­FÀ1ÀO! ³Ê… à°ZâççYå™S€€i80â@1¦µÁ˜'!¬k‡ v€€x’@À¡<› æ ÀÁz ÐFrm`ZCL€yN&ÀáU`wn0ØØ=ì<[Àî:Ò0 …à‚û%­/†Ö~¢ÆÈÚþëN|ÿu>‡Vÿ¨Áÿu´Uó_÷ÌþëI–öƒ{®ýuRõ‹Ô•ù Y8>}‡’ùGp|::ækŽ’‡ù¦ê2¾žO8ϧU‚´|j|,–Ok5X>7˧#÷Òò ‰ù6„3©Ïa¾-E>[>½¢Y,Ÿr/¤å;–O£|Z>ø2-Ÿ~áÒóéü¤éùDÚÂó饑ô|š°|ZO˧o°°¯;'ŸøwÃñéjÒéø´Ù"ŸH›X>Œ¤Â¾î”ôiù´+"=Ÿ.ÿ›¦OèiúLCªMŸŠ!ûº'HéùtThz>køõTâ~ ÍŽO.…Á¯£ûÚñéÜ€_^`_ ~Ýá“€_W5À¯{i' Ÿ+Óðé92àGµÎ4|¢QbøäbüºG|Às®Á¯Ûb•~O½ø=qbŠûÒÇ,îÃô—ŽÏX ðëž5~¹€cð+#ðëÉL¿ŽälðëöÒ~|¼ÓôÉsmð£ä#àWúøQàò›«ý£úuçL…üºc" ?ŠIâûdýÍä×­nüu‡1$þ¸iütÚuà¯üJô×]=úëÖ©¡?×þxh¿´Ÿaüd}×ðLJø+;üuXÀðGÙJàÃ1ûu 4b¿n&ÂöÉŒTè×OdA¡7ôë6Ê€~éF3úñЦï 1úugýøR€~|A¿¼yf?–/Ó÷ÉüÂð—WËð×]ëøëŽ¥0üõÔüuÇ¡þº#­¿Òbã§ì °)f‹ïÓPnøË§Mð—¥ ™ øcWf¿®åÔt}¨‹v}Ú¿…é“ßü: x>5¨¦çÓÁÚéùLsk HPž=Ÿé¨´çÂóyX´å“ç˧¦éøtv:>A(Ÿ­Óñ‰ÂSŸÂ@©^¼JÃç/ÐGý­4|zÑ; Ÿ°†O§qÅðéÂdiø?t¿žÜ…áÓK2>“èD}”.…ú6…¤á_¡¡û¤™¯ž˜²^iøt,Ì×ðÍ|ÙßÌG98˜¯¡PýpÙÚï¹i¶›~ÏÔeøÄM€áÓËÞiøtFA¯Ûfóå®Ì|ÝDiøt®Â4|¢òúʯløDÆÅñéßt|:YJ:>YÁñéÔ(éø´,-ŸÙbË'ŸÐ°|î¾Äx>ù2cû䣀ï“#¾O>bø>YÊ3ùQ)òÛlOƒüÊÞE~ÔWúƒG…ö%>›‘øºg!àÞ…ÓßN÷}|dñu#€¯“ï¾N¾ø:]Ü7}™åô”¯o¾Ng£Hc'Ë];ýZáëÄN‹¯“Ç_'b4¾Î¾/íët]¹´vb' k'–R¬f|œ<€8;÷ÓªVžà»Ü3ÎN‹Ó;=aMc§,Ãúì *EŽÒ¸’XÅ:¦0ºµËËé™;MuÝÁ PÝpI¨n°fªÛsQÝž²ž¨îÀ,eª;vóDu¤ÿ4ÕÍ—HÒŸ¨îÌ]ÕµLu3](J¦:’vBu'¶6SÝLáëT.1$$Á0Õ‘hª[¸ýˆêf*Y·ÕQª£j'Xwâ˜3Ö‘À®»À%£Ýép£]²Ùî$»Æb»3áIlw:›†ÑŽ„œ ÝñKæ–ã÷æá$¢ÐÝAêÓÝÌÁ¨žEwÇ/2ÞéÏtw¸\-tw‡Çtw´h¼;ü-ﻡໃ‡Ýˆ7³p?UÉ;ð-šñŽL Œ·s{Íx³””ö-Æ›a÷‡³o·¾ãJÙâí.&åö…Ay&dSµÁ¼Ò0ï˜Úóo…òlSÞáä Æ¼Lß/Ì#å¿1ïmP̈0oýDœ˜W; Ì[U ” &0oŽmÎ[-¥â¼Õ2Y`Þ*%ðòVÇOòŠ‹A˜Wv.Ì['µ üÖˆ´?NÅkÌ[ÛÜ•ôVÏ’ƒôVÏ \\S7 Ò[Öú‹ð½,˜`Ò{[œ3B¤—çdÒ[¿Úª·¢·¾·JY6‰ôVËV…¼º÷ ½ú«K±Œ»"½UÜâ£äÕ– ½ŒŠ6é­mª·.¨ÒŸ(Ù%U3Lz¥ã ½UÁCÂ]Þjé%|oýf«.μ½&½õ£éÕn‚ôVË^Ã÷>-Z3ýéâ,ûê•ãê•“ê•~Äzy¹„zåî õÊ!‹õ²¾‰`¯ôr*.žSØû4(.>wt+.>wôŒïÛjÜ+÷N¸WúAÉãn¢äíUÆ+F°WO°Wž,ÁÞzНªä­w¨*yå!ìå«jØ+g)ÚË) ÷Êá ÷Ê­îåíÕ†+ÞTÞoÁ^m Ø[-MvͦÒ0ÄØ앃ì½ÓŒ`¯<‚½Õ³DBe…åZ‰õÊ&b½òqë­m$÷ëÕ_-Ö[x¯¹[ê&‹õÖGVù^‚õjK°^†"™õÖ€sWÖ«¿ Ö+H±^¹ßb½§Ìz«äaMŠõÖÞƒ+ÅzëÉ<뽿Âö¬·z¾*ë1rõrpê•7J¨·z%{Ë»#UÅ3êí ¡Þ*ý£ÃÛ«YE¨—#¶Qoõü(`/GÖ[òÞíWÕ¿êYqÛ õÊ õÖñÈŒ¹kdÈ{Áz«å#æíOä]YÇe{f°^íùÖÐ:ÖUfJºŠQo%ü…X¯l²i`ÝU Ò¨·v|WçºßvCã*ú¸P¯þèиÊCB Ÿ…íPô¨¤ð\?®(hi: .v™ '0t’…ÏÔ_> ñÙ§ž _†þ9ˆð5¢ø,NgŸ¤D…ð ŽÅ!|xì,ïa$$„Ì„ð9½RÊ{™‹Óò^—&íœ^‡JyÏCrÊ{ˆ¨È{^_Oy4È{®<”ú’)úžmÍ)ð¹Êpj|ˆ¤ð´ð„ÈçUÅñ‘½‘8>"‰ãË|,ŽããÚÇg}Æñ¾˜q|Œ#Žà/âø,¾eŸÍÃÄñAñÄñ¥pé8>û\2”`DBùHWC,/±|„‘ËLjåÛ¾–ÎŒW#–Í7cù¬[ÌÇ$˜ÐÊ`>G:–ÏÙk2”ÏJž#ùvG«ÉgÏ/|¸‰ä3d$Ÿ (¤¡3sÁ8’@r$Ÿ+[d(Ÿ‹Ê·[q#”¢#”Ü:„ò±>D(ŸÇû åó’‘|©?Ég²ÉH>'ש|×GíËã#’W*‘|Ù±ÓxzÕ=#ùÈÑëH>rɇú `>óeôœƒù®æÐ=ó‘†`>ty²úJ4¡]Dóå6Îäi‘ˆ`>BŠæCÆ ‘'RÁ|iSu06¼ æ“ ƒùäF,ßéŽÎãI¿Äò¡69–/yα|÷ø¡÷•8BÇò¡å9'‹é„òa "”/·qÏÄ9‡ò%:”OC3'z$¡|¬Ég,ŸƒLHãé•ÐŒå#ð̱|H–äñÄÉJ,Ÿ>èˇ—X>&ôÄò±úO0qŽóaIMÑ;T?kóC0Ñióq„Ìç… æk´(˜ •`¾ËK æË‚ù,­+˜ÏÝÌÇËI00‚ùÈÉA0_&ét0Ÿc~3˜ØG‚ùpÚÌ—ý8˜ï Á|yÌæËôŸæË#t0gA0ŸÅbùøzËgçPÆò9H‹X>\tŽåˈ@ó‘“`>° ƒùäU%–-bùì'”D"”¸ä å³1•P¾ Ós(Q´Ê·ý°utÓ åó«G(_æXQ(Ÿç!ʇ Ö¡|ž\¡úul„òÙF–¾NŒÞÄòeŠbùÙËG¡U¿Ì²K0ßæÁÀª_'ÉÁ|ž4"û‘â"£ù°ÊZö#•9²ßH/ª£ùìöAö›_Ÿ<º ™e@ßAÞé~ƒÌ@Öý2´ˆ>r_Ñ÷KF—N´0}ÎÁ} Üѧ5¬Rüèz?•ß*÷,òW+Ò¨¡–0úÓ_åFÞä?«|t͉Ï]w-YaÈmYî#[²Âнê¼~––ìËmÙW¶”¾fZÐãsÞj(=ESéÈ ÿÕU®{Î2¯¿Yõ¨Ö7:æ¸tQÕå8Ùà—ÿ]Û>lùw›F™“2!¿>&×Tæa)Úòã›×kÎå?ÛГëÑQÖ;r?ÞÄÝäî%k¹›ZëHýäFê¨nCOT:¢§RéÈ=±‘{*ÛÐuŽè©Ô9rOläžÊ6ôD•#z*UŽÜ¹§²M¾»®qäžj#^yo¤žþ“:H³„íÝŽÿSé¯ê ýïõ¿~ùöþÁçù_ørþüdÿáËùKOÿ¸Ò5×æÞ©Ëÿ—5Þ/T©ôþõG5Þæ·÷s÷\×ÿugcÖ@:ÿºÒ55ùcU3Òj~¬lì½Þ?”‘gÐrE^Cg«º¦ca¥ ÞµTòÎ`z¤6Ôüøše(û^rí^Ó@q…Akqø:”‚T2ñ{õûrÁyÖssW95u0Ëh½Ò‚®)×µ*ŸÅ˜vÍ­a‚¼-k=ÿؼF~Í¯ÓØâh✦­e™à<Û¼^P œ¦Ù×,}^ÅxSiYkÂòÒ]«°úò *˜æš…y—­ÙŠË5M,»"r^\ïL(ÓÄ~Ïÿ©Nè{yÄ"Š˜ïù÷÷hæ*Ø].ÍŒ¤¸êµš±Û]£·å–±\+$·BAó©yÉrÄkj!æîq·÷øÿ[áÂÌ{†Š/›¿VMï~ ½¥tù<·"\÷èr>) ‚X_ÿ[ªÔº*gô3/óY/˪"Ô뵜…^Ökª¯à=Krž¯Â=WE=œkÉûžÓ>ê³4»žÄˆa©ìj®À¬×ÔÖ÷Ò öz€s±'^S°÷\yð?3s-¯Þý¹ ÖÓ°î¹|{Ô[=§<{Óxj/Ù=S¼Ýõõ§è1žæ³¸w§~Bö¡á4;O9š}_ª^¹1«ðô߯µ*yï±¾RqÇyϲØû]>Ž÷~iL×à¨×bVξ>à±Å€Ê£tt¨¡ÊÜÓa¹mŸß §^š¾]ã)ãЀšû>4 æ®N ¨^¹¼Ëª_ºcþþŠ1*ÀãÖˆê,÷ñhD¥ŸsjÅ£^ÀsÓˆšÛlQ9¯YKþ)A7÷94¨rÈ烪“´ÝÓÝï«×pÎC£*ÁyjTõû=ÍÃ×öùÕ¥Q5wukTÍ–PŠ7g¼¹¯Θó·¡FËÜÓ!ýy ®9;Ž·&‰ïxß~¯!7÷ÂÃzQ®)ÿ–a[÷5gÆ¿p_g‹£ÒJãÛ ¡T~þûºjpï= –Öàšû/ÔGçšÊpÜß%&¾Sý÷§Lî{êÂñ¶.ú}žuÔ\ˆ{ðËRL÷¢0`÷=EáoÃóûç¼Oc}ÆgZå£<³²ÍçÓ}ÏYp|Ðâãyß«æ:ÁT/¥Ä¸É+û´ís-Ÿöøm\sŽû™à8Š=¦\¯æ3'Àu®ð¬¯‚#Vîi¾QhüÒîåU*çñ(àÓa‚÷D§ûs øä<´ŽQ~2§½õåÒÒÇV3›ýÂFݵêv ›Em×ÌÑÑÜjyºçVË.xëñªæ¯çÞ ¹ÚOà\m œ«¿ œ«-s«%F(ñ\Ý&xîÓòÄ»š¿ ž+-Ásëê ÎÕ-έ†˜~ çê&sµ%xnµÄ° ž[-K‹3Ïåg [-1ÐåÍ2ÐÕ–ºÚs]9f!Ý~ƒBº|˜Œtk›h¢+‡Óㆋ@Ätù°‰éòA7Ó­>ÕL÷i¹ãuu•k3]m ¦«ÇL÷¶x–"¦[-1cÔÕ–€ºò+A]9 A]y°uåáÔ­K#Ì;4¨æ¾êj?§Ö9 -P·´ó[kvsÇÀš¿y4°Ò"ª+݈êê6›FV'£1Õ•] ëj?Ò0KK`]m94²fËé¡U+SƺòD ëj˽óºÆ;#¬ËO©°.AQ]y.‚êjC÷àê[%¬«ÛŒóÇë*¬«Û^K‹†W¿0¢ººÉ¥Ñ5[‚êÊK%ª«Û<'ok<ÿ¢ºòÖˆêr為ÒLW3Æ6 ®ìZPWw}h|å•Ô•GPW·¹4¾òPêê6 êÊ&uåÓ6¡®ü  ®ì7 ®6,¨+/j@]ÝbA]Ý邺ò¦Õ•ËTW·¸>ohP]ÝéKuu‹êÊEª+[Õ•.ƒêʇ4¨®|K‚êÊAÕ}žïaOª[Æ_ êÊß êêæ êêQ.¨«[<»[ ·}) ® öuu‹uåÔ•>c¶íuÇ`ºò ¦+ÛGtçm÷¿˜®î2¢;KCHø¥ÏÅtõ°CŸäþüƒjE`Ý^Ã"˜7D-ÝR‘B°PG®„:!ët)XY¨#³›…:R¨£ét6ƒ¢Óu›î­ÓuG2£ÓQ§®»Ê:sY!Óm.]™2 º!Ó­éJE»Uð¹’Ý Ëh±‰dºÜ“TºžšœTºî„ô¨tP ÒÍYOìÛ*ù(­ÒuUíA¤#šUºî$ö¨tÝv9Tº™µz«l·oD:²›¡Òuä ÒåYZ¥ëvï¡ÒÍT“g…»Ìù†L×t‡L×€LGMdºÎk™®Û{:ÔÑéºBÈ,Ó9})2]wdºî¼üÈt¤™D¦£*<2]ß?]wDºÒ"•®;¨•Ž£µH—×Ò"&8Dºn›("ݼ q¼éœé®Ûñ‰F×9a‰®#V[¢ËwRÙÜÑèH©‡Fס‡HGú_Dºîšzˆt݈tÝ%Žéº+­"Òu‡»!Òù‚¢Ñ9E,]9itÃÈt …Èt¥Éty%ÓQ”™ÎC¬UºüÖX¥£Þ2]wt2]~Å,Ó1!Óu—ù@¦ëF¦ëÎo„Lç\§©Ò9Ô •®«z""Ýœ„EÀ"]¾ºéxQ­Ñå÷ÇÝüÇdØ"]wý<‹t]réüÑèæ>bOÒèºÃÜÐèº • ÑuíX¢yþoº¼¼èýuÇ(<©s݉֬μju.¿£RçÈ0nu.Qê\~$Ï‘gÛò\wžçºC~-ÏuÇé…KŸe¶ØhÙ¶J-ý1I£¥À4Zr³pZúÉášÃ–ÓjÉbµô;Ä5ü6aµô³•nK.ŽÝ–ÜLÜ–ÒmÉñâ¶´«?Ý–í´SלÅ;Ý–N›nK½ãé¶ô(Ý–\Ü–nËü•Ý–œ¹!®]¿¸-ý¡J·%W·¥CLqí1£c·äþÚn™½ØnéçôÐé¶tXDº-1Ý–œ8vKž?ì– vK;ýÓnÉ“„ÝvKg L»%—»¥g pÜÌê+ú“ÝÒ™\ÒnÉg»%!ƒ\stJú-¹Áø-³û-³û-¹‚ø-¹5ø-¹5ø-7­•Crùèà·ôw=ý–ü ¿¥Ÿmì–ì »%/0vKÍ<ÒnÉ·ËvK‡¦Ý’× »%‡‡ÝÒùXÓnÉcÝ’ÏvK&Û-9KÑ\s˜†ì–<¡¶[òÐØnÉ]²ÝÒר-¹³¶[ò±±Ý2÷"¿%0e¿%~ù™ÓNå·äV„ß’qÇ~Kžlû-éÁ@§‰›y.ŸÛ-¹T¶[2ÚnÉ·Åv˦p Ù-óße·äbÚoÉka¿eö‰Б1¿%W×~K^ .=ÃpÉnm¸äû!¨kÏæNÇ£P«P—c´ —žyâ¸ä–ÚqÉ÷ÐŽË< 9.¹Çv\r5uÍžÁ?¨(” ^® ræ ÂuÛôR…{~ªp;fÎÖÖ §H7Ép¶&¥ ÷(I:œs”%Ë9ÿ@êp¸%Ñá›.‹â˜e8¿wE‡» Xb¹îA u8—€+:ÜóC‡óܪèp–fâ$Bˆ# !ò@ˆ#.0…8%–I!ÎZ"Jœ—”R‰ÓbO*qE(qèyâüN%.ûE‰“.žJá†(q^¶N%.[Š'µG?(q^gK%Ž_¡Ä¡ ¢Ä9•»”8Ÿ%BœgR‰»¼KqÙ‚gäBŠë?l–¹žRœWS£gÔ¸þ#d.„ç ©ÆñH Æq{Qã¸æ¨q^MN59Î…‹§É`êqþ¤gž·7ü–¥ç…>ô8åCK9Χ™r\Êh–ã_RŽó ~•ã{‡ç…Iä8ÜÐãœN.9/'£Ç!Ù Çù“‚'`EŽEÎ)xŠ"‡_ÒŠ«à(rE“"ÇA‘?CçJ?s%ªTäº"S’ãAA’s 7$¹÷Vç,«†8×eÜ·6Ç‚œµ9k÷"¹îZ;DÎÙ–Òœ¯7ÒœOÓÒ_ KsÎí*i޳¶4Ç‹liŽË`iŽhmŽ‹mmŽ eyÎò ò*µõ9ͨçx&,ϵÇÁuC5ìb Ežó‹<‡GRò'byŽo¾å9„fËsŽ^CžóuèÜ.ˆR:Èü¶œWŽ[ùp·;8~;æÀöIwrN$‰_‰ßNßTømÂT ò ~;Ux|›kb-|;}AÁ·Ã‰Wo‰+Œo§‡~ðípz6øíàœÌoåWâ·Ã¾)øíxTŽ~;fŠþwdМî€6 p‡?8Ü‘öKÜ‘ô(€;ülpÔ{1ÀÍ´ŠqȸDwXO4¿\cóÛÎiàö ÏÀí{Àí÷a ¤nwwn'ˆnw‰Nîð« ÀºŽÒ7Ü‘%€£ÊwÌ7<Õ¸s­ î(âÛavÜî€gnw"n·s‚Ë«e‚+Ûˆàv²ÿ˜àöSÇ@¸#Ü.··;Ç0·Ÿhd"¸Ü¹ ®l#‚Û±A›àv’ʘàv/U™àöù• |ÁÍD©:œ ¸ùÕ·Ã&¸F#Üî\˜ \ÙF·§Š'„ÛY3Âí©â áJ?B¸]·!¸Ý‹\éX7s¹nj „Û™éáÓ'!ܰ;„]*B¸Ýê%·»ž·3K4Âí6,€p»‹ ‚p»‹Ypdnáv¾peïB¸1óë<•ÃßA¸ù+ñ™ŽË0ÜÈ(71Üp∅pÃy™@¸AF !ÜÀ )‚#90G*`n(‚€òòÃoÙ­ðm`Ô1¾‘U|þøC¥…Æ·<<ãÛÊX¿¾ OøMoƒfÓÛ° z#}:ôFÂwÓÛpýèm`—½ ŒÍ¦·y0·X-†ÖaÉÅð6˜Ž˜ÞsãÛÀ—)zËã5½ ܦ7ÀCoÃAùÐÛ°Áz¬ë˜ÞJÏ¢7.±ámÀ›Ándî‡ÝfžÝصØmûdŒ«ä…ÝÆ¦:yÀ)k·‘Ššàmà{» >5f·ñ » ij[wf£Û? rHn·aŸ„¹m0g6·åÃhnh=æ¶‚\ó4¢kigѵígÒ“¥ÏD×~qW¦íÔD×¼*ѵíGÒ“U`xÿ{!ºÖíE5Ñ5Ä ]C¤3ÑQ‡ØDWDtæ(¢£01H×¼œ Ò5WåNå4*Å6Bº±é‰CtøI#ÝÜF>M!]ÓDלMÇ@×R)³½²;ÉŠ®u’šèª±®yQ'€®¥r& +?  kë¤€ŽƒÃ]‰-Ò<׈>4Ï5öð\s#x.ežËmÌs¥óÜüÕó±WΓ”¡Q@×ä;‡çZjkâ¹æe#x®´ˆçÊáˆçjˇڀ7m¯Äi*ž+ýŠçx"à9NžãWðœO œ› ÒÍ„s<$i¯ôKΕ_ çÊ€y®9×-Œ• †n©¥yþôg¹‘6ùÏ úlmZ{÷ºZ²tŽÛ²pE¶dñœ­Í ¦ýÓ—[j_ÑVûrKéën}ŽJ—~VKéEÿWóy¦°¸ÿq-Ÿ¿¬Ïsî¿–ÏyÿGÅ|~yBžó}´OᑟÏÚzŒúJ T¶rO.Ô㎲PýxºÉmÔK–éQ7µLûÉÜQÝÊ=Q¦Ç=•2=ôÄFôT¶rO”éqO¥L=±=•­ÜezÜS)ÓCOlDOe+^[—éQOµLO¾ìÞÈ=ý'Å|fAó™Öíkùœÿ®–Ï/OÞ×òù³Í~Öòù‹î~¾1?7ûYËç¯vûó­úY/æg-Ÿ¿ñ©þ×ϯî}˜ÿõGïæoõŸ¼›¿ôôkù<×âü?,åó^ˆÿ‘ÿûß©¬óW¥|>exþ÷›kIï„ïï•ò9ÿ¨ÿõ–òyÎ#r E9€ò©òõm˜«™§bIŸóšß§9쉽£ýJ‚ö8ü9Ÿíw­[-ŸîÛOiŸ«Å„ÀžæçÚbBàÊäï5 K¼ гaä¹&ÛDÃ}¼½­V}bžëؾÞkžâÔzï¬$ÈY µïe먜*ï¹fóo+€NGußë¨,¾>3]¶j­™ãs·˜d³“û…²¶¢ÄMoÃýùÁ²Ie$ä;5%òê¹gꞺô6\¿××ç%£nRhÖ3óWßßõ̔ҊmŠk9Sc^%,ëYÙç~#Ô÷yGö߃¿¦ïÍnÑáZyÿTô¡‚^Þé¡KWlÑ{ÄÚ(ÚémÛaãyÞ7³ =ϾB€žçe…^ÂÒÞ†ˆ]òóóÌ›ÿi¸ö[¬0;ÇÔÌzY‘¹_àóvñûS¶x/ü‹ µ’ÈÛ2¯S„a-GÇl‰ˆC¯¿-]ñK²ç¾-C!‡ Qy[öHïõðÙò¬ã÷šôÛrÅ´ÞŒ·åÔÑlúûÚ~ÿÙrÇ9HK~[îˆcò:ûÛ2#d[™úÏØ÷JÓÛÆçÙx[Έ7”ep6Üqpœä,KpG7§¶yß1ÜzUÞ–÷%«Ïõl¹?áo[[áJ%ìmq y‹ƒ™ŽÀk;[îò¾ݲ+âpÄ ó¶rè'q¶s8â¡™Jb/¡™oËQ‡yÁ§üµ®¯Œ†³%âó¼û³.¸ëßOE‹ÈC¯Ï–'.°ÖzÞ–-¢˯¦T2[$l¼-#â=i›-OŸhýmÙ#±üêˆwÐÈÛrv?æ:âi#9?¯Ë¸tÞ—ú½#Ñ Koˈ¶…ΖˆDÔÚâ‹-íô)ìqc¦aI§pÆŽö¾ùë`öÁˆ^Üy[ƧÀIí{„#ZCy[Ž5[ÝL¨³å{‰÷óüq‰÷kø6\Ú÷½9ÄóØÔrûk£ò|×6Ò^^Èk•h]åmÙ6Ÿ‚:žÆÀósRG?ã8Àc _ã-.αŸµc_cfÙõ¡ü^,{[ÎG§¥ŽÉ íǃTº~µÇY÷áSð¯ö›¿:[‹SØ}ýÎø›×óÜbðÌ£9ú›÷û1€æIžãò]Ð¥9÷BË6GŒ¡y±Î3FÑî?c -\1ˆÊò6(ª2¿åçŠæbžÊ“r)8{½¶Hó£|mŒ¤úú\=†RÞƒKaÀy½¯]c©¿Û—â€Ë¾ëÇóqñ&sÀïÄúó\—†ÓÛŸ«ëÖxÊÈx=»_RÝ×»m?ž[Ùql~[Ìż•'w~«KÞ´{h8Ýýuºœ_‘ûø<Ï·b‚ó šU;¾OÇ}ñþy›{øép·/ -M9˧?NáÙ†£¦–ÎpªÛýt§ …ÏÊŽ“ó“gñ4ߥGéqòþ?‡Ô¸³Ï£iÙà~Eoms·ÑsÇhjÝãmy?!±Íœ÷|ÿÞš?“qps(ÿ¾¢shô+úh›¯qùÕÞü™‰Ïíüšúâ¶l‘°em³–&·ù=ðxå}]1žržó)ög¦ë˜ïã{4ÊSöýØŸë¥?ø·€9îºçkwÛ¸wÛŠkŒ»§fŒ›‹ã;qûz Æ­†åÃÆí·MaÜ*ôˆÚ"™µW¨…qûm£†0n5¬‰©0n¿5\·þZ_QÜ~w°îŒ²ž:ãÖwô°0îmP© aÜ~{š Œ[ ‚¬ÙáýmÆ­† Œ«®Ã¥Ò¢¸õÏOÕ¢¸õÏg¡¸ýöÃ!Š[[4ÅÕ-Æ­†3:½¢p’M¸ÕÐ㨞¨ð`§Ââ¸òƒà¸õïGàÒÉá­Õ‹ãê=’ÃgÃâ¸Õð î‘>Ç•Ž«{YW;]W·X… 'Ž[?Ø Ç­-„V ã²c\þÆ—×÷߶ã>ýì›MÃA`Üú•æcqŸ~νœ€1îÛrÇ)d/÷éK;´Í¸¼PƸrâAqõGAqyCLqõRÆå“bŽûìjU ÈÃ Ž«'·Zv!ٹϯÈ}¶Y ·Z„ƒ‹ã>?Z·Z4ÄÇÕ“ê󿆤à¸Ï«R W*0î³ÁÞ`ܪh¶ ÚŽËÇïC9£ªCÙæê>mr7¿¢¬C6<ǧ‹`¸z(Ápå'pŸ-„û´Œþãøáêã·¶Ñ÷ùÕ¸xApõhV9—ÒÇ%l;7À}z}Ÿ~÷iÙvŸÁ¨÷my|ÚW\ÝWÜçWÇöã'Á}þ>ÏŸÇw Ÿƒ[îÍO¸pí¾} îæ9} z¹‚àj7Apß–ûÇw&î³Í?¾3Çþc‹ýö)xßÇáSpË9||:â@¸oËýãÂ}ZTS%[áêñœíþì;îÓ¢º*¥e´çWoo ÜgßGÿñ¡ „«WëTíÁÒóuøMõ6ª?X¶Y%Vêß×s¸Td¥´lýÇ9\*³RZúåsx*Ƚ-òñä>Û¨ÔJéç¸~܇ ¹O?Wÿþæzü$é›(÷ÙÓ³ÿ8‡@¹ºÍ­úƒ¹§[eWJ‹ –_©ðJmy~܇[ÕWÊ6«äPéWåWjËýãn`ɧ"`îó«gûy|Ïýãæêµ˜ûlÓ5¨– ªÙ2~üf?ÎáQÂÚrÿøžÏÕ³ ž«_à¹Ï6÷ýóøžã{‹çÖß‚¥­}O@8÷iéÇ÷„sµ›½}ŸÑ\VEsk›S\vöï]Í•;%š+Ïñ¢¹ÏoT‚°¶<ßà ˜«›Ì}Zz÷ƒtV˜«ÝŒËgêùß.Ücœ{bºÈr)ª-YÎÚ5²Ü© #d9ñ4Ï=.Ndž›sé­ÈrûœKŸJÁslŒssƒ^T¹<;±*ç2¨rЖ*çØuT9¡Ê9YΉ÷åJCÈr|@–s°6²œ3â"Ë¥Š¶d9»Ù-Ë5$¯%Ëá°´,Wö²\s¶1ËrÍ9E-Ë•.C—›}H¸ ]®tº\›ÁgqØ!Ì5¨} sÍÉ,ÌåyH˜kÎ¥fa®9öÏÂ\îTÂ\Ù"„¹æàZ sÍqåææM~ Э†x<%Ì5' a®±!a®9ÖËÂ?@˜#aއ a®9(Â\m a®9‹,Âçƒ0׬©"Ì5UI’.ל¼]nn 4ér3vD+‰ÒåjKèr\9t¹ršÒå¸6èråâˆèf¯V‰îÓs(sµç]÷Dj‰”9^V”¹ÖÆïèÖ5—&$e®vÊ\ùQsÍ•µæx‡æÊµYÂ\sL"@÷Ìb]-w|nÑZÝãˆ>ˆîqÂ\¹væê±„0WNRÂ\³ 0÷i¹üŒë>-a®µ !,„¹æÔñsu›æòâI—+‡']®ìHº\í&t¹æHvt¹rRÒåÊm‘.GÜ™t¹ú›ÐåÊm‘.W{ ]®´H˜+7WÂ\S:tt¹²kérÄ^¡Ë•^º\9@éru›c=*ƒ.W&t¹r±Du£Áºòô ëÊó'¬c8ëˆìC˜Ë—.WN\º\³ DTGˆº\9` sµå¾Ân¹šï‚ž såK˜«GT7÷~~¨Ç„¹rÉ%Ì1ˆ#Ì•£‘0WÎRÂ\y¶Du忉ê§*…êÊmÕ=Ndƒ6WQÝü•ÌKœ«çàK®Ô¹rý¤Î•³Õ=áE+ç)y®œ§ä¹O o¢{>®ÏÔ }®|Ê–@W>/èêßW¹èJ¿èÊÑH +=‹êÊU—BW¾S¢ººMP]y¤Ð•çm)tåˆ%ÑåQ ]p¤ÐÕS¸‡?š>`YÌóĥЕӔBW~%¨+·SPWNJP÷8ÀZP7ÑÓ•çQLWžk1]ù¼ˆéf‹lGbºò̊阱Ãtõ`‚ér›Ðèò©±F—Dktù7Ôå9X£Ë‹nª«{ ª{œiªË'À]ÞqS]í'¨.¿8¡ÑñµDWOêy‹sórÞaîQŽ.t¹ÇiºÐåjKèr³åøèrå>I—›1x·¡îñ)ø¯+.u¸PæêžB™+BÊÜcC>Ê\m eî9./CK™cÈ@™›-wõVÖ (e®\@)su›ÅpeO¡ÌÍ-ëH™«{Ãå™›áÊñ‰áŽM —’îÔ¢Ò\¹ê’æfÏîgh´Ì_íß;%i.â'WC(só¤$¹K™{\enÖ|Lu1f:Te®œ¦./¨n~ò“áÖ§¸*”¹<< s³Ar„¹ò„J˜+×Á—×Á—‡g„Ëkc„ˇ.7§ÉÒ÷Mpy%–.W; ]®œ“t¹r0ÒåÊ›à<B—+=K—«ý„.W·ÙŸ‰t9f7èråÑ_º\í÷z~¼ Òåj¿ÏîsØ?º\ÙFº\y…Lpy;¥ËåE7Àå4Àå)H–«Ûûç$ËÕ·Ÿÿæ:\bÉrå)‘,Wï¹ýœëÞI•+?2À•\m‰1õ8p:.€Ëke‚ËS0Á•^DpyiLpe\9b\Þ;\ù•ŽKª\þƲ\þƲ\1Çw²\¾S\ù•®ìKÇ9X—ãÆplj'€cÈY®îèéßï¥e¹|&¬Ë•]K—Ë'‰0ZU¸G–˯*çsúƒš=)À­h;´ #h“5RÄvÙhdsò>ÍÙç@6¯#ü™ú–äIP"‰ƒâ¬B¤ü&m#å7k7’߬A!¿YƒB~{Üƒä· ”ü¶ÅÝF}s^UÔ7çûsõÍ­¾iÖ…ú¦¬ß‡ÐI|sºõßèÏâ›f`ˆoNsŒøFø™Å·ÜBâ[öañÍÇ!ñM3Ìßh°øfD|3![|Ë-,¾ù(,¾eƒÄ·ü‰Ä7G!¾aܵø– K|Ëã”ø–‘wßìôMñ-ƒ—,¾•m$¾•‰o@cñ­´H|Ëp‹oe‰o¥ç¥¾•ßH}«-±J˜XVßÊ6RßrOVß¶ä©o¤eõ­lQqˆ¿©¾•P4©o›G¯ßòOio¥io#©Å·áÃâ[ž¥Å·r¼Rßò¼­¾åX}˽‡ú–{RX\9š‡LLX\í5ÂâÊž­¾•_I}+ÛH}SîõßJÇßrio%”î9>[{ËgÈÚ[îÙÚ[i‘øV~%ñ­ô,ñ-Ÿ"‹o¥Eâ[éYâ[éGâ[¾c!¾•-$¾•^,¾¡áZ|Ë+lñmcÉÅâ[ölõ jñ­üHâ[>ßx†­½•MŽçs㬽•n¥½å9)&®žAÄÄ•·)¸mõóÑÞ2G%Aqåݰö–Çcñ­l#ñ­l³oß~%¾•‰o¥Eâ[ž§Å·rÄßJ‹Ä·ò+%m*1d­ùöWÿ–ø–„ßJ/߈³ö¶ý·ø Šk[2â©QLSáø²'Io¥EÉMKÇKzË'ÀÒ[þÆÒ[ÞKo<±Š‹c”Kå­t#å­t#å-»‘ðV~$á-·üÑõíC²[ù…d·|3,»å·ìF7VÝòhÇ\+U·¼ýŠ‹+' ¸¸òa±êV~uìß¿Ïí{y­ºåÓjÕ­üHª[¾§VÝjËíS0ÞHuÛ~@[ý•ââʉ+.®eùŠ‹«¿Ù‡¿„nQ^Ó|€—°"ãÊRd\ÝÑÝüY¼5 úuR`\^‰nåo‰nt‚èÆív`Ý¢¹q,Ž‹ËSr\\ÝÕq|?4hneWWóv?Cê–NÊòP#ºåáIsãÑCsËn­¹m?ˆ­Ü47:VTùTKu‘Ú!ÈíSžÈ5Ô`;0­ï’–i3)ÚÚÛßAŒÛcúáË$LëzcZ?ì¦õƒ\&i³¡½­Ÿì5wIwÁcZ÷ªF`Zý3ªí!… Óºk¸ÓæOä² LË !Lë. aL£¾¦1­t˜Ö­ÈŠÒf¶Ö¸¢4=# ÑòÞÑæ¥–4ˆ6Ó¼ïD£6'ˆÖ÷‘Z[”×ÛO'ã¢õËŸm˜$° ´~`7¡Íkn9.ã¡ÍÃ;-¤Eø™êóCh³úéó!´ù+‹mAh]504ÊËh=“‡Ÿõ ŸQm>£.|Ö3½ÄÕO<‹Ah½DÍ*­—¹N‚Ðzæ(¡õ Æ¡õ’U%­gd¸Í´^²’DäÎÐz†Þ÷(êë">›{éb¼à³¾¡'‰ÏÊ埕£ŸõLÅ"@«-· ì%-¡u¯žˆÐzCì¡•£¡QpB£Ê)„Ös¶+B£x„VÎA„Ö7kEhåò‰ÐzCX¡õ-•³U`3'"´žyvDh©­ÿÌZÒ%× ÎÊeœuÕ βO±Yωج<‚³^R¡zxõ ÎÊÅœõœ¤:a‰«vgõxÎzÁ˜€³¾ý„³ž9jg=sÂÎjË~ÆL»ÎR7_pÖÉG$6+χجoȳb³ÚM°Y¹|b³^¸Ðµ-“[‚Í:Vµ…f=Ó;Íú/hÖsáEhÖ3ÁƒØ¬§ÕXlÖ½Ž ›QÉ6£Œ:pÖs&+8ëi¥œõôß-8£´%pVžµËÕ.¹O‚3ªDBg½øƒÎò'8ë[‘кOáìV/…謜”è¬ös©‡ÃŸQ>+T|VžñYoO[ §ùM •'I€ÖÓSïÄ%ƒ°—xÊ  u î¨ÓœæE%.qŽ’ ³îJFÐYO—³è¬ô©Š*Î=œ•ÁYO'¯à,rç,I{²Ø¬gtDä,)¦Ä`³ž!ÎY’6cç,q|R¦-ÁNh8ëű©´%åhn¥\ ÑREg½XƒÎòy0å&mÉ£Y!xÖ‹mRiK8ã—¬%N¨åCn:ë¸dÉZâ‡ÎZâ:@ÐY_Æ3’–<ž“‘´äÙhQҒ瓱¤›3–8ôä”áAe yª¨l³ÜM°ÙYy×ì6§¤RÞ‚Ýš…D²Ob[töÉ‹| Ê>ù^Ÿš¶¤äh´ÐæçÌü¶9¸Ç—)…p¡X á2Å¢ŽT?F¸ÍæŽÔIF¸-“§ÂmŸp¤D3ÂåO„pd; „#Mé'€Fé'óß•~òGâ2(‘}2;PöIÏwI? Í:ý$É=œ~’lÎ?éŠÊ?é„âäŸtZsòOæÊ?éxMòOæÊ?™Ä¦ü“¹…òO:•ü“NòNþI›’êŽü“ói-yKÞ†f5Où'ß8òO2ƒtþIg<Îü“åWÊ?éCËü“eåŸLqþI'Ïü“"O¥fº>W·PþÉ òwþI×Èü“Žìü“™pÊù'3­óO’B)óO2ù %iÀœ2óaEJ’~9åÏÄ%5³•3PfÒ/2PžÔÝä̪Éõ‚Žš¸¤ž (ïÈeîKçŸÌ=GþÉ‚dÊ?™™¹œ²ásþÉQòO2÷tþIæÊN?YT4§Ÿ$䟦ŸÌ´ŒN? X”ô“ׇã¶ÌRCúÉLQéô“ÜYÒOÞ?8®¶8ý$9 ~òŽË§ì“™kRÙ'óá$ûdæ¹töÉL©ô“y_œ~’9û¤m%ûdf–Töɼ6Î>™‡CöIÞÂÈ>™ù{œ}2WAœ}2ßÊ’}òªQnõ±??ße§ŸÌŒ®¤Ÿ¼À\Íéô“¤øtúÉ ÷`¤ŸL\rúÉDKçŸLwþÉTœ2õCçŸLqþÉüŽ8ÿdþÊù'3P8òO|RþI/gþÉ CŸóOVÀ#ƒó7ýdŠN?™ËN?Yvu~³8gÊÒâ”䥔eO©œOÊA™ÃÎA™ñ¦ÎAÙpc:eîÉI(“IB .9 eÊëÎBYZ”…²ä»\i(3§¯ÓP&¬; e~Èœ†2_<§¡L‘Þi(sßNC™Ÿ硜ż o›Ïáúæ¡,ÒžòP&^FÊ<'ó\9%¢ÌU'¢,œQf6c'¢,ç D”†p'¢Ì«C"J~e¨Ëãq"ÊÒ2¾÷ʼn(sIÏP—×ÏP—8l¨+G£\”ùœêrõÓ¹(ËY)% å¢ä¾‹’g”\”EõÔ•^”‹²*lÍÏú{)e!6Qׂ\”0<¹(·4AŠêx÷Du¬š‹’O¹(ùV€u,T ºež±.Ϲ(½ÊØé;UJð¼÷ê^&Ь´0zÄd µÔj:þ»ÜÊÛü‡UxzŸAiÙ¿þ.ÕnVK©6¡¿KÅœ>«‡ÞŸ^ÜRû‰¶Ú“[J_c ›z9c·”¾ÔVú¢å¿º Ï6×Ŷÿ´ Ïýÿzž?xF¶»-?q­Ãóãy[OÒÙ>O࿲¯¬²£®J%÷Ä6î¨Vë‰~j•èèS‹G=•­ÔÕ·bú*uvÔW­Æã¾r+÷õ©Ù£¾J¥õUëñ¸¯ÜÊ}}ªö¨¯RkG}ÕŠ<î+·r_Ÿº=~‡³ÚNôõ©ÉûÏVêë?©Éó~磤óÿ)Êóï‹òü÷¿~ù ÿѧú_ø²þü|ÿÉËúK_ÿ¸0Ï6˰¾_ÐÿWæ¹Kežÿõ*ó¼RAÂö]ÞÇYó&æ ·Â\HçmÙÖ*ð¥¸ø»Çtá±Æ¾­¤Ä!?*.þ¡©Ú ó¶ì¡©:2øm9BS=ˆ‚¿XÎc9CR½/Ï“n9H¢²ÝwHª,é¿-!ÅØ¬ó¶Ìz±ƒyÝöĂج-«¥ø”ñÌÇç¼-kæ^·é‹Å‡;‰Õ°Ù­.Ô¬ü¾vD`˳‡ªJf‡m°œ³[‘Ú¶"/géflô{VïçZÇF.…FŽÁÊ6³Ê<ëØ$ ô‹aƒš}…hÌÃól»·X ðTŸç-x"OÀÛkaƒe >ë:®[ ¢·¹6@÷þRø:~ ¼·X ÒÛ²0|ÀˆýÅ´8?D}V<šgÀêRŸËéó X y[†–6û\PŸ7áÃ`ˆ¾È9®V<Œ}¦BŸÇLöõ·eÝY/õµZ[œê%ÖÃe5úv´¸ ®¸Àv(ô9€ÌS`µo±6XêÛ*u Õýœ kÆ>XnêïS³ÎÀk¼ï3Ä‹5ý=ñØ‘®ðÒ?ç8ó vßÛi;Ù£“Ð,û4ÝqñôˆLCÎ<ƒ™³Y»>ö¸À–ë{?{Ü»@Þ–'.°VÛߖ늛`_ËûµØão?&ý韶ÇrØ`¥³EõvX›½Ä%Ÿâ÷^ŽXs¡XÛŒ3n‚}^”üÕDZÅ]ðÝÇBðùðÅ¡¿ë:<*}\ºžM»¾·xDò`î…àƒeá÷’ŸßMßÛˆS°\ß÷X Ë/ËÛ²|=²ï±V^ï}Œ¸ ñ¾>5ïßw¼ª—’ô=VÃÊK·Ÿ#î‚WëÞG"^CVcß–;>6W,Jöý>| [\šýñðà­ÅçÒ+oËí75º9¶àå3qôÁ'ø:Z>/Ü as¿:¡c?â[³M¬„•‡è8[|ir7±6XÆì“?Ö-°äßX +ôñ4,cy[â-dÅå®o»=ýÜâMÎ/÷¹=‹‚£ûšSÏ/ös¬át˜¬û¹÷¸fÞ·%FSõó¸â¼|ÑÏXŽÕ{[®·€wÆRXÝù}Å)Åšêû²k8õRE¿Úæ¾níÕ4œZëÙÖKsÅBØ ›N¿†FT›|Þ–x™óm¹¢èg\®ƒ!Õý„·ös>ß#¸qÈÀ9ìö+tà•ám‰!•eÌ~ÇBØ z¦ßrò¢÷;ÂÊ[wËÌ{z.Ñïq~æ;ÄàŸ ß±ÖI{ô¶Ä Jö©~ÇBØX#àj©w.à©›„«SýM¸\¾;Dáò~<¡ ìïé5¿ª±hþ¶ÜŸ~B.ó‚'ÖÁNwÞc*«roK˜8ûúðÀÑŸX+7æ …¸_¬ƒõûö%}B#®G+aù«÷ÿZ=âÑbv\·x°?š¼¾XSF ¥x CŒ&·/&Ž÷jǰÊ÷å}ÄêD^ºÑB-žGÜô+Y~oç&~¿1¬²¶ø~ù>SÐ1]ìóønÏ¢Þ×?¬J—·1— GÍ¥9oË8cj<=ÎáÖ6rþÞί<69ó<7Y-{Ø|¯SX•\Òòm9uE#©Öûê„õ7Ï{“õ·ìIÖßûÿaïMruG–l½¾Fq›™— $xê€;I eÙÐü!šÛ*ŒûD܈¸Jj¼VÄöÃßYzñÙ²‚Käh)k8Œp«é¹—M/©ÑS12èŽp¼Ú˜U+FOÅ8΀]r´Ï#îðü½9©pc~òóc¿){M—eG™áÞ–\We–=ˆôg«ùˆýV&W+†«%s;àÏ…nþ\‰ð÷6pþfT¯'mLu=/1ÚÌTדïð7W¡Ì3S]‡»7Îue®ë)òD —É\˜€¿w³Áð7ýÿþÞ¿E™ʸœòºJø›{B%fÊùÓÈÕ³ŠÄÛïUùoßæL›YEâT6¸ä¿¹NºG%þíÔtJþ{[¸¼‚ÿv7"ÂçÛíÊ"Œ‹ ÿíc°X¨ârÒaüWÎþ{[´_Iþû´ Œ‹ÎÜý`sLüý€Êά!QZPÆE@€»åÁõÝYE‚i€»¡Uütü,ÞöÓ €õT €û€ €å5l¬·”¸Ï}FC%åõî3 ƒJ.åÜW‘(ׇJ.¾«$Àrã ¥\ÊÉŸ¬!á–Žj.¾œ Àúæ’K· €»¯2 ðÓíÈ¥Û™%$JË™%$JË•%$”É ø9×}ÿ¼Ôs)ý<è»ÑŽj.î7w¼õyTsñ[Hüƒj.¾šDÀz5‰€õj?ýœYB¢\ÏuñØrãŠóå&~Öïh ˜‹ûH¬Ob¢˜‹’+?¿B1—rÌÈ:ùܵ\”2ø9j¹”n¯ñã%LÔrñÃKüœz¼¶<ƒ·È:²|„/'°NZI€õíÖnk·¨äâ†y~_Á‰:.åÄWVP†&`ýd’?§Fwü|lÈ1è~ƒÿjÉŸ#Z®¨J2þ«!ù¯N4 €uü'Ö»L¬sî…*.žŒ?gG—Ò²îz“Џ¨!ñ¯žùF —Ò’ògmA ßeâ_½ºÄ¿z‰õäȪiïFÝÂò›ëó}Ü(\X.• ýRn”.,Ç v¡Y(àâcªêT õ[ÊP¾°´ŒïY(_èë_¨ßâ7²N­¦xû õ[ÊÅ ŠaiAC u ËÕ ¡Ïõ ’¡yPʰ¶¬ïoPÌÐgzPÀ¥ü ˯PÁ¥ƒš†~:*¸”cPÕPY³À~ŸÔ5,¿z4¨hW6¼ÌcÇý`¿O ŠÖ–\Pµiû•«û•»û}®uÅ`¿OË=?+þF¿Ï‰ÖÃËc ªú‚ýÊçôû¶<¼<þ eK öÇ¥e'-@¿rÁ U}íÂf=÷µ ¿O·¨rX.UË1¨rè'œèWÏÔQæÐ¿Jôûƒ2‡~æ~eO ôûœibEåè÷9Sú|ZÖ{€â©sÿ…â?¤?&¯ÊŸj Aù;¥›Âßû ±”¿ã¦»2•¿ƒ¥üE Q/•¿cÁa•Âß±è”Má/ZæGù‹“Cƒòw ©ü²Pù;Š^øì~ßÏ¡Âß§%•¿`UáoŸéü(q5ð‚øwÈ5‰â_\ͬð·“€3Sû‹CŽ ûTR2 øä÷¾<•£‚øwÈÈBñO'¢öwH¥ö§ÒþÙX¨ýÅå¶qÊ&3h¾ºÿ¢Êx)þ•NrjI©‚öW[Rû+?JéÏwM鯞9¥¿ÒéOA7’þ…4Qú«¿ê褿ƒE­$ýù‰Sú+Oڟߤ¿Ú1rNÉEé¯< hþ¦©ýù»¢öç™Ú_<3¬‰Ðþ<ž¨ýE ÕÀÿŽ›¾æÿb ®Š~gDcÀ˜ ñïP®mЇ„}Ї²PSü‹~`&‡øW{~z^Í fÒ)¥”¦øw(“6Å¿rPÿÂé±SÌQx#6šâ_95Ä¿èæcˆõ˜TÿÊ-@ý+—¼Õ¿úwªµ—Tÿj ²N1Í£Ô?_0Ä¿u-Å¿rrN¹!¥¿Ò°3NÝ Ô¦ò§6)‡ŒÀTþbtÞÀEdœº©Aåo;Ý %¥¿˜!‹Aú;”jÒ_9ÒŸ× jµ¥ï(<:&Sþ;”é›ò_ýMʱ3êù/Zpçÿ¢E‚`机ñgjÑí]Éïs¢Ôþê‰rê¶²wœùð v@û+Ú_éÚ_97´¿r¹ÿx¹PþÊÅAùÓH6åGÙO ÛÔEwéÔü–æÏ^ _.¤Ej~å-Có+_4¿h9g©ùÅqšßqKg‡æçå—š_í9{j ®Ò4¿zB?Ëõ!öÓw~3ø!N”üJ‚?}ßPüÊ!H³ê†iÊ×½¯¶ Ó”RÀSï‹–0Dª)¿y~åIAð+w ÁÏ»8 ~å9@ð+Ï‚_éy ~¾%è}¥©¦|fÈ}Ÿ–ûǹ¯ƒTSL}Oµ¯þ™¦Ê{ÕëÔ>O]©öùµQíÓPìóÒF±Ïß&Å>¿ûê1HÁzÓiŠbŸ/˜b_íYXU‚bß¡¼û)öÕ^Rìó[¢ØW®b_ùľð?(ÿåÔìK±¯\_?Æ2žòˆ!öÕ³#«ïa‹}åCì;XuƒZ_í‰XK ±ºb_¹<ˆ}~¿Ðúê!Èê¬Ò©õ•ç ­ïP¥j}åíBë+oZŸ?Gj}ÞÞPëSÜùT*î?Ü­ç£Eß#ý5%¾8⬘WjPã+¹À¡ñÕ–‰´ÙÔÊ©ñ=Sã{´rQãsM Š|.B‘Ï%*(ò¹îFŠ|.PA‘ÏuO(ò¹î E>×j¡ÈWÒƒ?¬ £ëƒÈ÷há£Èçú(Tùâö|¡ ][!ò©„Jj|åÏ¥â»ô.}P‚j-%¾O ªQh{‰ÏG‰O§¢Â§¢6ø\Í%>ß2¾èuRÎCòzŸùZ|}¯þh¡x'rè{þô¨ï¹|õ½r×Ð÷|G÷Ê™Z_µ&å½Ú‚’0úÊ(ïÕS³&Œ.ò^¹íÆš0>f©˜@YÆÇ<*ç´*å¹ô½Ïß7?!¸sAà+WÏú^¹è{þÒ¨ïÕ–«ó-ðä— ;áá@ß«-¬ óÈ)õéß FM˜ŸW}Ï·y¯<=È{åÔ÷ê1sr à›€¼W:>Ÿ/ê^½š{~Xw€{‚¾W/æQy'\ ô=WÇ¡¾÷x/}¯¶°"Œ®úžÊ¡Aàs™ |õÜ( ãëƒÀWî _y/øü° ï•†gð3¯þõr!ï•SCÞ«Çôñ—÷ÊÇx² Œ._maA]Ìu|'{ |åÉ@à+?B=˜ÒïƒúN¬æD…Ï¥Rá+C _é _95¾òAá«ÇÌÎÊ~æÃº*è}ZX†7¯žŠa|ªu`9‰ÏÝBá+?‚ÂW>"(|®OF…¯ (|å†ÂçU _½šë»š¦ÂWÞÁÍZö¾³÷1¨§áO_9Ñb5·  ¢VÏÅb0¼–ÕµœÞE᫳ ¢U7Ö‚1Ú±¢µ` „,†¨¯s- 䓸·~Lå‹uOPøj‹K"ÞEá«G¸*"Æ6¾Ç …¯|ÏÔŠÊ~QÑW …¯öìòˆ”ü~.¨ë#ºcVƒáãJÏŸ>÷BO'¢¾÷ Uõ¦¨ïÕ¡N¢Þ õ=¿Mê{õW(•¨]-õ½ÚÏêß#TŒê{åDÐ÷üd¨ïy¡¾çi˜úž?ê{µÔKœò_„¾WAÁD_r»>Ü\/±Â^}+÷Ê!¨–苃ºWÞJgµÄŽõivVKä0Õ½Gf0ª{冠î•꬗ȆÁ¿•þÖwÀˆabÏo’ˆ×Ò]¿† ÛAÊïœIÉPñ3SKÅ›½´l£ã,Θ©âÍ‚€©âÅÆ ¹RÆ›ï|ã÷¦B¯(ãÅ&äþðÍɨÊxSÞy”ñf‰ o^Ž´KoPKo-!ãͦ†7oÇÌ¥¹bÊ|L /ö:ý£áÕ–ñæ:ä{™"ÞtÍ+ˆxSÆõñ¦ "^œ›4š"Þd*l©xÓo¨x3¼µ@P©âÍwyCT U¼. 2e<‡yQÆsHOÊxƒ¨d¼&2ƒŒWÂó ã)·–d<ÍQÇk_À{»‘ì@¯D»AÆSú'Éx%°2ž#SÆS:(Éxv ÉxÊl"ÏÏŠ2^‰'„ŽÇdZ’ñšYÊxŽ×¢Œ×~ž‹HÅSBK¨xŽ/¢Š§¼RñŽâ®™ë‘ƒ|¨ârZ¤ŠWZ â)«T<ÇKPÅ+g‡Š§DDRñ”€'wz©x‡¡â)“T<·QÅSnJ©xˆ¡ŒçhÊxŠ|ŒçøÊxåÈx~)ã9Ö…2ÓkJÅóçHÏ/*ž ïAÞq©x޳¡ŒWºŽç­¼[A’òº»QÇc„±d¨^ÔñôiŠìüdRÇÓ+’ŽçwB!¯¶“£š„<ÅáJÈÓ”"!O‘¯‚;9IIÉÓ—%¯ô¸+Ñ€€»õ#wʤ’Wú’ç»R>¨–ËU)6d×Ì jª®™‹iùfÊ/„ΙÎqçÌ’Ιòð“sfIÝBçL«ðÎ9Ë;Ó°EïLkiôΔk¯¼3Uô\Þ™òå…w& Ù;ó䣔wf‰tƒw¦üèY"èðýÊ|!ïLYØä)‘Vî™Tƒåé2¿ôδ¿kzg¡Þ™7k¼È;Ó¦<ºg†äJÔKŸ’¢äÁ=ÓÞd;û[È?SN};»Á?óPðÀíì@²SÝd‘]¹> õD;›r‰v‘X¶jwõ¢"8…v,ÇD´óõíôÔ…vt]Ù±~´ÀîÔn€`çCv§¨ƒ`çpC‚Ý©MÁÎ-$;ÕQÙ±œ”ÉnÈ7”dGgl¹gš® vãþFæícˆ;eߨ9 ÁŽ•¿ v¥€]9W‚c]vÎÖ"°£!Ì`gm `ç{dW‚÷;}k;mí vÞ*Q»3Œ&ØykJíŽå±­Ý•hwKO‹Ú]'’ÒóP»ó¦ŒÚ+¾Y»Óš ´ó¹©Ýù©S»{·x¢Ôîb‘üjwJáDéÎ.ÏÔîÌï”WËp§ÑïìêK¶»iå*âÅ0ŠwrD¥xWü;vÅâýƒ©ÞÐêÏu}\uª|‡¨wÅ™ó¯¨wtæÜ}ÌòÝñ…; zãû'Õ»¢ÕÉf}ÙÎ*¶Ô;%Þ)¯ŽÄ;}D»r*Šw:Fâ“[¼Óê ñާ&ÙÙÁ‡dçC(Ýiž–t§CÎóÇ P¹+?¢rçË¥t§n¨Üùú èLŸ’Ê~báŽ7háN‡P¸sÃó¹|ËvãGX^m¡l§1*ÖBGå9ÿ ¢ò®OF–Ïo–ç†åé7 Ë+-Ë«-ËkÊ¿‚°<ǧ),Ï¿BX^my~܃âòÜráŠgÍÈò9qyåÇå!zŽqy%ÊqyêçÄå©gÅå¹e|"Ý—WúE\^é—qyî…qyþÕïÆå1>þ/T+2üe‰é®6¡”œ5³†Ú®ƒšY˜IþºÊÉi¼aNN%ðQNNídCiï ÎDEø%ÛgÂßp&À_ä4$ž&üá³ï¤œE4CRΓû>%åÔøSRÎ"›!)géy93«Ëæ»ñ0ê%ü QòržN÷‰ÄœÊÓ ÄœZ>˜³¸”"1§B±”˜ÓK-sÆæ ™Dl æ=AZÎe-Ùo,ÖâQ^ΗìWÏ´s.V(UbÎ0ãLHÌY‘˜S_‰szkÈÄœÞï21ç»Óøømîs1ü ‰9½SebNYW”˜3˜ª&æT¸¦szOÌÄœ*v¦Äœ*(©Ìœ¶ó23§wèÌÌæm´$þMËGLÍy;{'Rs>ÔÛ•šÓýlü³N®Ôœ¾¦æÔ'ÀÔœ÷ئæôGÁÔœ~1À¿iI©9ýÐõršSÀÀÌœA&¤½þùú@åÉ03§7ñÌÌ©lVJÍ)Œ™9Ë!ÈÌéÀJÀß´Ÿ™9ý€™šÓÌÔœ¬ ÇÔœN–ÇÔœ”š“¡„ÈË鯓y9ý®™—Óßór:D^N•Ñ£¨72ór:è“y9ã1ƒ ‘—Óã’y9Ãü‰ÎŽše^ÎÒ3sú=11§ÒÁ)1§·˜˜SssÊ/‰9eWnNOGÌÍé fnN³ ssʼªÜœâ1¦æT­K¥æ%13gé™9mcfNãvfæ|û"Y!3§¿fæ,|ÈÌBZ™³RszÊB€ÞbLdæô=13§“¬ 1§}LÌÉbèLÌéPR&æ,Þ•H̹”–‰9=Ó01çsb˜2/§g=æåô|ϼœ2+/§_órz c^NŸj§å4Á3-§ý˜–Ó¡¬LËé‡Ç´œ·´+¦åÔ‰£7LìÌÊ© 1z£øWÊI ¤œ2öRÔ%fRÎ_‚ôÊê7\̬œžã˜•Óß'³rjÞfRNÇë2)§?áLÊé fRN[”˜”ÓŸ“rêá!H¯LÌÉéqÀœœ+ÌÉY޹onY(!"'g999/%[Ìœœ¼k¥äT'JÉY\f”^|Ç %§ £ôF0¤ä”.aÏß•2rúŒÑÎüÈ„œZ‚3F¯ž9côôå1DoŽC>Î)‘ºÞPr2 {Cy5¢7JÐÞø1”¢7¶Kio¬Ÿù8=¤´ç‘@io(ÞŠÒž×dÆèyÈ)§¯ÒÞì¡„œ–W¤çÇÅ|œE“ eoü„¿²Ñ`Œžªòq:É(”½!£òqúËBŒÞ8¡*Ö’FïW±éÖ5*άÞWJ¡åSÒèwWJᘲ¤Ñ¯gPK-!ô=Ç”–RŽhFÞÓYûRKé m¥/µÔ¾¢6oí)ÿ®ýDKí%ÿ.}d%ßÏÓcKém¥'µÔ¾¾ï«¾ÁÚ×÷íÔ÷õ_^j)6©ïXþÔZŠòHÛGyýRÆõ“â+ý÷ë2µ ­×/%g~ôpþ£jM?Ê.ýÖW6Vy7¿÷Œ³æ·8úrI%tUJ*±'ÃŽji¦ì§TÊŽ>•ÐS9 ]}‹3¡¯RP }Õ‚JìËG±¯Oq&ôU *¡¯ZP‰}ù(öõ)΄¾JA%ôU *±/ž>Å™4âUP)ûú”]ò÷ΣÐ×?UviÏþ÷ÿ(»ô‡e—þÄó›Óø/ËÉßÿÁ’ð9êw'Äÿwe—b—ð>­ÿß”]úÏßêã?ÿÙ²KïˆÙ6íû3I¼KHgºg¦A[Þ¡ï^& Úrx7@q„R›CÎ"ÙNª&ýneP•ZùØŸ4Ô5gIß:v–jJËÈ<`¨SyÊ{Ø`è7´ÓMe@Ÿá¿ÿî¹NNioKZêNYáæ1cêŠbèwþvºóA-óhÙ&‚[>Zs'@y%3 ˜÷î®@¿k›nU*ŸáóôÞBç‰_=ÛFp–ïç7£jæ{]fÔ»Œ:wrå˜--u·êFÌÖãïw×Ïߤ¡î–myFyô÷‚ñ3„à ›,îæ3ÛHpÁ¡% u·b^Þ–m$¸éŽ4[Úén)½³­m$¸…>³=ÛJ°Êå<ÛJpË«eö#V™îfoÛJ°ó0{ßV‚%ÿÜZÃÛK¨öùbúØV‚¥ª:³§¥n5’îìç68óáÛ²ÙâŽ{C˵Í·òFÌ–º;lù™¼¬¾ï`c~6l´¸•¾[É÷Ô´ÌÏ‘¶º¸¼ï¨Ë]TÞihÙf‚[.Ä3ŠÅ-¨0ÐŒªAûqÑûpF¥ö¹ñ1·¡ Æ3{>ãïð„ÌÇätÆoh¼™ãÞ†‚%¤šÛbEL7GÚêNÕ ™‘ï=œAqÙÏL[Ý9i(x[ïŸÀLc]Ø&ð:ß··ï!BBòŠgšëÖ;hÕÏOþ4s¦±®þæÜ–‚è§¾ö€sÐÜJéû£OŽ9ïm)XŠÔ™sõÜ›€¡ç|¶¡ ¬+ ‡<ÛP°h2Ïc v¥‚ühÏ4×-Ùx/ïˆ^hJxÿ¾s{C#ð+ÞÇÐö½ŽëSu¯ôˆŽs±¨]8!ÇÕЈ´½Ÿã¬ˆß¤Ù.ŽaKjÚ·V¡óH³ÝæÑì·¥¦}©ª]Ö¥[B`ÎsµTµ¯ÈíŸý´Tµ¯÷Ë]л{Ükëu8ð«Tµo•º<[¨Ú—¼:Ï–ªö%såÙRÕ¾–¯&Uí+ܳå‹ey<[ŠÚ—”w“¼—ÖK.oË^Z/•>|W˜½´^R{Ξ¢öÅð»³÷#÷W~úQ'5~Á±zö‘[Ü÷#ÉÍêÙSÒ¾÷îαS¦mòm¹óÐ=sà \8Q*Ú§·]ó©G ‹iemÕ8•žxOEûR¸s¤¢})1”>zÿ–ï.e×'­t׳{¢åÖ1#e0jÜéRå w5¾)§âòmÔ¹ÛæùàŒÉ½Õv¿¸¢p²¥¡}-ÆÛ”("'ó0ØÇT•hù8U×§|­?í%gGʶ?]zÉü·çÌL2ð¦ˆI¼¥æ&Æ'7àWçRÐ3°&PCGþ¬@À=k¯Š€ï„;1Sw[dK·@<¼ÖôÔ‡¿\"à!3<ð ~Bl^@€Í;2`ל@ìòW'vïäA€]þ<$À!WO`—LII€S ðTõXà© $À‰íðïT‘*âßûðíÿ.+ÿÞ½Œ 1ñïT"ÁÄ¿³À^ËɇaÇÄ¿S2'ñïR„;ñ¯ <ðïšÔ£ˆ—·À¿KÂñï’#ñïòFøçe,ñïò£þՖĿ؀•—–xâße–þÝ*~Iü»åñCü»4ÿnKÿnÕK$þÅvç.øwwÁ ðïŽ}[Þ7ðïVòß-'òßeÌÿÅND˜üw+«ðÖæx=F·À0˜tàT ·_ €·Rc§z|ðÖO,¨DŒpÿlHþ+Ö%ðß-q^ü±Ž$Â'5²H€ÿnã2ù—‰·'âŸ6yÆ? âŸ÷þÄ¿‰…2€ÅîBü“§˜ð¯#7þEµ]À^âß-‡B៙‡øgÓñÏæâ_£ïñïVÄ#ñïçüªKåÉ%ýÝÚ-Šþ=?Aг2ýi ý)Õ„ðO1TÂ?шÚRÿlþ•_ÿŠ=‘ø'ßø§gãß­°eáŸjAÿ „'ì9ÜÿÊÿÊü[ Ã'þŒâãþ݆cà_e'ðŸŒ>ÿâb0ßÿÊ—^ðï2&þ-휉· (À¿ò(„pf#ý•{ý-ýyjý-e»Iú[JÞAúó‹þmà¤?ó*éo‰Z¯ 7wMd¿¥Â°d¿°Ý<8÷5«ì·ûd?[QÉ~ëò$ûÙöJö3•“ý–Iì·ÚÍÉ~K†±W~¡Ÿ<ôý¢“ëƒ~ªJòóKò[f^ ßþ´?èwË/šèwËg“è·”D‰è·™ä'#Éoi•èçO‘èºý–Ò.ýÖ;c“ô’ýl©#ûÙàBö»MÅ`?­-D¿[I¢ß*`—èç©%ÑoÇ~·âçˆ~å“úÅ4·ƒMï8$ÑoÌFô‹Éö °_|“-¹¦j?Iø3þnù”'üݪYSeïN9 eÈQ,çõWŠ/™ÿ¶A±ð_|–Hƒ^$@Š‚ €ÖÀÀG…k€ïèbòEd§Èé `lu+ÀnlKðd[ €Cæ'Âß”‡áÏnãI§l%¤¿ió6ðï©ÿ‚Ì),&þ]¤Lú;-Wþ.•¬$ýný]r5'ýÖm@—më›þNÍ Òÿlo¤þGãä?c1å?›²)ÿi—bç¬ÿI—¥þç%œúß¡}<õ¿¢ÊýÝ }!ý]á+žJúó@“þ7¸f‚ÿÂÓ–D8e£þ+ûÊZ§$ÿy‡–òßÐŽCò—éŠ"Þr±&ÞïF¶YêýÆ7LùÏòå¿C øï–[³ä?o (ÿÙd±ù¯ à¿bå§ü'óù/ŒµÏ‡ÿÊ[ ÿJÿ=ëÿ-åN³üGëå?!ä¿©‡œüW¸ òŸG&å¿"Bÿó“ þç¯úŸÌÝÒÿüST˜—@) µQ¦(xJýÏ_õ?ã õ¿›ßå?oÑI ˜üWÎ ùoø˜K•,]”ÿN}7’ÿ$:ÿdÿ„üg‚ü·hÒ'ÿUëðëÿ‚ÁŽ/ÿ- É”ÿäg-þ[Üx˜ÿ¤3%ÿ…%&ÿ„úwjOü“÷³ðO6~áŸ)CêŸðï¡!XôWô¶¤¿ÇªÅ¿»ô§Ì+ÔþÊßIž Iv»ý…s=yôw˨Aú3µ‘þ”:˜ô÷ØÛ…âŸv¦?D› þ´±ƒö§(ÁŸ× ÀßÃä“b? À~ÏA-è·CpÐÏÞD?‹ð@¿8 ÊŸ'x¢Ÿ6à`?½% ßco¢_g¸Ñ/°™ ògÂú=ï§óUþ–§K²ß)¯²ŸÙì·´"úÙ‘è'ӭЯÈs‰~þŒ„~rËú½ïv}„¿¥õ‡ì·nKŠ€?Km‚?Ÿ}Ãß4Aþ´7ü·ðð§9‚ðçùHð'7ÁßIÛ¢àO±b‚¿È7àJø[ò/"ýÅwÉ– ?M‚¿a /éoYZ#ý]CdúÓŽŽôÇ !á¯@/áÏ‚,áOÃ[ôç{"þ]N…À¡Qˆ×Mú³² ú{¬ê’þ,$ú[fÓ[.5<5èOw ú‹Uâ@ èOóéÏ.+ ?˳ ?׆ýÉø#ú›’!A»~<(øÇˆ8ÑŸ?jПýHHK[dÑß-õô÷ØÎ°éoi_(ú“ÉÒô§Gú»iãú£JL&¾åv¥ø9 ˆÄf’ J¡Ó§Â5A| )ªìóÉø-*~#[èô©”±$¾ˆ*â©ù3¨“øš]r€|MwÈ|ÍÔæëvŽó5e Jæë,ðLäëV€|]20‘¯+u‘oX.ó kK`¾áí<˜/¾Hl Á|ÅoÌ7ô$€|ÓvG~$ê}×Oâ›ö<£Þ'Å\zŸ8œÈwú¨÷ÙaÈwz9¥Þ§’‘Òûìiä³tÈw^¦®D¾YÈ ‚ŸÕG ßûî$³Aó“¦/Ío2]šŸ‡©ùY†ó]F¨Ôü”ÌÇ¢Ÿ¶û`¾Ë@ÑO92ßé½E¿Ë”ý”«[¢sÇIó“!WšµyI~ò¬äg`¡ä×õž(ù O¨øÉ¨BÁÏþl¾‹.¾Ë›r ~ò'ðÙ)…Àw/Q~Ê!’Àw-ûBð³¹Àw)ù´¿`$ [ß-Ov ~~O¾Øö/ü~pªä½pš%Rï“ã”ô>Kè©÷E®`Ú&û%j¤Þ'WXê} #ïfx¡ä>?<Ê}ÞÜ“÷úøÁ{wáFÈ}V Á{·í¡÷)I yϦié}§„Eê}v‚£Þç¡KwOQ¨÷…sZ’÷n+Çཻ Úó:0‡zŸ²áø¤M÷ê!à½Ö~ðÞ­°OÉ}Šéðiƒ%¹Ï´$½OÆé}2@lâ Ù˜¤f½ó0ˆ¯xRï“aœÄW¾|Ÿý@|·ü¯¤÷Ùå€zŸëI|SÀDäkVÇ×H仵ϕÞ7.¹ˆ‚ù¼öùn¯ÔûŠ’è+ %Ü=‹B wO¥Ð—Þgi–Ð'Mæó4L½OY3 }·rõIï;ÐWD¡÷YÐ¥Þç¥ÐW4A ~L$èS|Q_ÓüÁOB Osª Oj³¼=­>Hïƒ{˜O2¬õ>©0töTâ1Ÿ´y8{>¿0ßA~—³gáM0ŸfL ~ˆü˜ÝŅÝ;‘¯8SùäS-äÓÞF‚Ÿ1:?ÙõÍ|ò3$ó5û™&ó…&SŠŸ!̧8 AߌEèÓ®NÐ7¹n ú¢p ŽôùåúÄ(Eó›?¨O>Ôüä«F껕ïIÔç'Jê³ÆKêSH˜°O¹g„}~Ä>9‡ûì%LìÓŒ$ì;­ßû¸Ü ûºü}…}Ò6É}r÷½ÐCÐä¾ñ‹êgOgpŸãkÀ}ÍX î“Gî ó?žU?ªßªÊTÕ½ö ð+Qv`=MêR÷ôÁmÖ+‰p¥îi'yOe%{Æ Â^w=*ÀÞ´ªÚ;JP]Ò^ñ—ís*8/iïò ÚëRäâg'pÏ®â ñS‰r…øÉbTCü¾ž—ш!~²ƒ÷¦×†ø9¸w+yφH|²F‚÷œð¼w[êï•Õ¼wÛm¼W\šÀ{e‰ï­¢R.X#}Sø”ö‹¼Wc2ĶEø9‚„~ò'îy:V„ŸR+ÂÏOŒð“úï?A poI¯Ý´#ñúÐ^,@{KÖ~øÙÒÌ¿wré{ÓrY²žÇ³¾¡XÆ÷ù¶)ð%âoýøŒRàó¾Iñ}Ž d|Ÿöløìv Þ+qPà½ežï-#>?- | |¾+ |r/…À'¹‘Ÿ%h |~Ýø&·ø$-QàS* |V…$ðIW§À§ºuø”¿P_‰ÄÛ ŸåF*|~ZTø…ŒXá“áJ ŸvØTøJÀáõ±æV‰Þ¥øìÆ*O­ D¾"èAâ3›3ÀÏO”~²’ølš¡Äg¨&ñYJÏN¿$>{¡Sã“ÊFà{ä>@‰¯œˆñ}¤Äg·KŸ™šŸC& |§£ù|™Là3Sã“㘀ϫ3¯à<å %•Ͼ×¾ih…ÊçáKàSn'©|^à§!žÄg Àg U>ŸšÀç˜*Ÿ7Á{ʯ&‘ïÒ”DÞ³_?yÏf‰|óä=‡VlÞ{Œ¿| ‰–Ègb!ïYD#ð™+$ò’)ò™$|Rt ñ1¥€xOá‰Òø4ÉŠ÷¤¢KãbBò^l,¿¼çà3Ÿ™€O)‰|ÚHIã+ð¶O~­rð´ (5>û–Bã“…xÏ,BÞ+Q„à½{޻徙¸÷homÜ*÷,8%î½ï* pOcE¸§ìðÂ=¿)Š|3„{ )òɱ‘¸wúŠ{*2 ܳ®JÜ«xwü­x¡÷¬÷üµÉÇS]T>|[Ä=‡±ÊÉ“›ãžÆ”d>®IÂ=•ˆîiãÜ«ý—îÌg§ã†]-ÓdÌÛé몧û„yñ¸áÖ ÌSF`ž¦EbÞPé=b^w&:`Þ)Ç/bÞÔfƒ˜wšS€yÓ^À<+›Ä¼Ëy€yê¯ónÙ'óg2æÝö£æç0bžRZó–£í˜ÉŪ0Ï“®2¹Ø Ì{lã%昧Á‚L.öòç=6¬Ó“Óænrž=MÉyo!çÉûœW ·‘ó\nœ·¿z–&çÅ+£V™œ§ú‰y*®KÌSaJR^¥ïgGmòAy®ŠKÊsmMRÞQØåv˜•™”ç:ª‰yª!GÊ+—‹2ªNêÊ; =ò\õ‘˜wÈúHÌsñ7bžK²óê1‰yQkõf Š8ÞÌóãLÊc¹C"ÞÎ?ʤ.¨àØÕ‡J;ª™Ä+Õx€x5´6oÿêÂçÚE ¼R…„·w-ßÊüPtE¡ð©Š^)~Â+õí@x»`ÆR^™Ó@xû˜«æp©ßsÞ>£æŽ¬ô¡J0 ¼R²e^îßH|¨´sIhYêã–²~¢ÔŽ »ƒðJ ^©¤Äûœ ÅvTã ˆ· ¥`$'âíŠ7¸©Mxû!“ÄŽ^ê ðJ=!ÞîuÔ .{˜^ðJeÞ.DçЙußcèæÉZ;zã x¥O¦ØŒçIL¼¯ûTãàí=ó¢ÇfVÎ*fPlÇÑà x»¥WÎÜ{“ç²r–êéðJi"Þ~¿­fpùô|¶Z/„çÜh¼ú$áÕ™ðF¹ûG_yw7ªíø[KÀ«×»Pmç6šµ,œå·¹PpÇ>xûòo¨·£ï*ù®¾îä»B.»²n–?­ä»RÂ|W?¶ä;™Þ•RÀ»ú°”ÜQ‰ûwõÛ{PqGé~Áwõ?¨¹O-u³ô<ÔÜQ10^½ÍåT홀÷¹âÕ9b¸T:‹Âà³g1º_ðö»|è´™¥³Þ!Á¨¹†%•™„Ax¥Èo÷sÐiµ³ù•„Wž ¯ÌàñöhAD¼ò´€xåñÊ3â•1Ä+eÅ€xåÙñÊóâ•Ñ Äûô3Ö÷=lÄûôræª*îJÄ+“¯ x Þ§›•ëª Þ§Ÿg}+¯“ŒW>.0^›ñêMÆ+ŒW_2ÞþÕE×N,¬Ñ»ra•ϯ~nÉx¥Zo÷C÷Ï'Ö’|åÈ…5L^dº#Ï´*ãí~Ÿêɹ{Y•ñJ9\0^)ÆÛý0ðœüL‰.‡¢”0Þ¾悹sH;CO2Þrî#ø¦ûÕMÆ«Ç(G0ç_©ÖTÝ:?Ƀ§…x»u*Í9Ý:µ-„[§B`È€H¨ lÍ-ˆäsŠuJ}*r¢P¾éœ›¬ºÃZ=Šå³ñŽÙû©•l^ Xò´€K ¤>ÙÇœÍS‰(õy%Ú´ItNÈÍ€ö¶¶Ög’„Ög¿81 Ò}aLZŸýL¡õÙ‰ŒZŸµj}EŠ„ÖgáN饯 ØWÒ¦Ø÷ØÝObŸîœbŸu0‰}NÍ™bŸ\l)ö• 0)öE•¸ûÏg/GÅóQ7–اì¼Êæ)éBbŸnbß#g*‰}þ,(ö9CDŠ}fk‰}’™(öyV ØÇPyk}Êz­ïñ3§Ö÷hjƒÖ9½‰ÐúÊÉ·ÖçiŒZŸ¿Ph}]¨õ)74¤¾ò(õYe4Ÿµ¤Ò÷ØG…Ñ|–ó)õ9i2¤¾Ç®)õ9”R_¼&ûL©ï±ïÃùìU­ï±w"´¾§$ …ÖçQÇp>h}¡¡õùÆ!õ=Å¿rìY0œˆR–I†óy݂ԑ„ða<Ÿ­ú§XÔ=_Ÿ\.OIîùȶÊP7H}EpƒÔ¹Qª¥5fIZŸÝ¡õ=^¥ÑWâ÷¨õY!dDŸ#!ö9P™bŸmZûŠ™bß#ã¤"ú¨zAë›ÜîHëóŽZŸc%ö)å9žGá…ûüÂ)öÙ¨D±Ï¡ûžÈXȼ>/œjßcgI¨}1¦ŽODߣXaª}]¡ö=Nÿµï‘‰›jߣH6ˆ}2+Sì³£ž§¸î€>9 Ií+Bcª}ñù€€¡ö=Ú`Pí+· µ/~Ú†Ú÷8{ Ô¾G†eÉ}?ó¹”[€Ú†ÊÝVûän.µÏ„µï‘ƒŒBúŠiª}Oq#Mµ¯|[Pû­ÏTûz@Qì{œ[bŸICbŸ"`Sì{´-¡Øç©˜bßÓ±OË Å¾ÇÞ²ûzQì{ìK±ï)9^àDó(UÌ­u•Ðɘ>h¦Ø'†bßã|Cû,ºRì£{­Üù(ß½J¤¼ï ðÿÓ.)øœjùwµåCø?þÁï|©¿û •›fµ}·„Ó`'²çøÒÒáeò…½héK-¥/´•¾Ôâ¾¢ÆiìÊ«Å}±Í}¹Å}ýWUJz·Ìñ\bi|çÊ]S„`†k 7ºn•tù¦j´ür@–™®~ôË·ði¬pþ„þþËgL˜¨çç(uõDÕ§³t…†OW:H]•£ØÕ.Ø–¹h³+6Ô®|»ªG©« ›«ô”:â!êÇǨ›3r;–çĆOG:H=•£ÔU„h<å9±áÓ•RWå(Òw¿ÊsbCíʱ«zÔŸý`£|åxW¹(ÐûÂIJG³–=ba¡ö{_ào—=ú½Ã~–=úƒî~Ž‘Ÿ‡ý,{ôG§ý9¤¾ãè7Êý‰Ùùï¿Ì³¿5ÿý·Fé/óóoÓ_ûú/:Àà}Õñšÿ[¼ï5ò]øâÞmÖ~×ÿó¿¾Û‹Ùçõ/ÿý_c½>Úù/ÿË¿¾|pEõ¡ÿUÿú¿½³QìÆ×õ/ÿ×ÿöîlÂÏAÏë¯_zgàõnrc=|—Ýoñ¥áâKc_ºþ°îÒ{\T[ŠÂIWm,Õ–Æ·—òìý§ÿv¡¥ù' -±kˆ¹3öS´=^oìTöN ’¥½4ÑW-±¯yP-þÝ\1¢¤ûˆÝÇ88…¾?ßü®Ñ™»Ëw›vª%ÅŸ<&–¼÷˜÷m%·kûRŒ0Þ&ĵ—IÆýN„£™Ý¬mÜz7R Ûš¶öÔ6æqç¯=›¨Æ|7[(kþ5qH” ÞÛÖqdqÌËQ¨Ýv~ë‘æ(~~:1wìžûØÑ5oKg¹æ—Jf̸žœ=‡q0&Ü¡úÍ[GÚ"ºWàĈ<ð¸šØ]½‡„Í5©Cf|Åõrº v{ŸÖî®ûÆÃ¢}Å1»Nò¿GEÔÛô·ádýËJ^Z‘-Ÿèh[¹xç•­ãx©dŽèøaíØ±Í*#Ìù:G„Ä1ïe¡Ègø´­lAâõ°0½ëzŽä¨,úâÒ¸ß'ºÐ²AqD]dU¿c…{.د"ñýq~ZbìF/‹±F€_´„5–ÙðFX:è_ÔãŒð8ºí[¨÷˜öoL¡i#¶Ÿp—afÁbae‘7F<€}&Y½b²«¿ÊM䈀`ùK%så¹é´ýÄa„ýžIî½*ßz ‘züý·qÇpòn¶‘`Žégž8Lj[&›  ù º™1R÷õÑy0pâm Ëß©qµ`Å¿ÚLÂí‹$s?ªE}òÚ:óˆxuÄ’]»a½¶{ÞoÀQ5¬äw~€ÙDšµ"À}ïäCÕŸy]ˆ¡é ò"y Õ¨K‘—¡ÿ1Tý}FÞÃg|vÏëý\b¨F ü*>—h¸1#!¡âÛÍ •z'TC.€_$/ØCuq¨ÆHÚCuñsÜ×_õ}À*é¯öé'&Æýå“x"BÕ¨]ºÚ‘Cõ%Ødö­Vô:8"x=‡jîÛýNQ{¤Fµä}Sñ}ï‘ú>œé}{¤jˆÌÞE†FGtUìÚ}{¨†4‹†µ‡j$VLóÊÎû›Ã;ß]XíŸÝ²O³“d·zšð Ýãôý—ôeŒhÉÑÊc_Ù{?©;ÏŽ mõ1€µFd>OëävaÄ£J£HøÁÆ@cö+éØÖ#gè$ósÈ»þìaÚ¸"mƒÙ“-ù5nSv Ó€úrIÕüÙûÌ%U›Ÿ·åŽÏeÌ|SažØC5ô¤}›ýÊ%U+G"|FîZV^óKª>õÞW.©[ »åÉ%5„þüDû“KjdœÙ¦½>޽¤Æ{È -×ÔHM›0Ê€6/uïß¹ª^ÛB #Õk«­Ñ0sMfÏî}œ¹¦î;W¶äšzq·Ñßs¬ž ÝÜXS'¶T=r0ÝxžùÆÂš:1;ö¨}>­Ñr¨<ùlXSÏž–©·ea¨¶œ0ûìXSÛÅ–‘kêàg2'ÖÔwœç7;g®©ï ÆoN¬©¾»ð¼rM × üèÆšÊ>o,©ýæå-,©Ç™fú>,© K_?\SOýê<°¦ršíg:y¿s ôÕZb°žïµíà=æ™{è3wœ=R/÷} ý…“b´Æ~ªå1g.ªsñóË9cÄ«¿Ð‹j”³ÉW~n÷Ì=ßôjRÝ×wÑ9çO•XùåUò‹¯$;ßmNKò‹Èý”-áÎSù¯‡’—Kø¯GÄkíí¥ª/1ø¯GèK²°ï´¼šÀ¾¶ncþë±Æ¦æþë!ˆ¤2ì¡Á•{,©¹?ö­£eàKUT`´%ög«4æ¿þaÿúvM’Küë[ÜÊn÷$±íùwÒ_´9ýõpKýô×·ÃØ‡þb/èᄌãý½- R@¿Xq¿è} ô1Ðï0³ýíô‰~GÌyyj _ôœ|@ö;Ddd¿ãå€]²ßñ¾“$È~&Ðïí†_ûÓ?Âl`˜\©ŽX!²²WªC\ò;Þ¥‡Å‘r¡:ÞËäe¹PœpÄ~GL¬ŒµÞ ÕïïÃ~GPÓCí…* ºÃãìwÜÇß øœö~¿rß¡Hî;Lyà¾ë±ïˆõáoû|±À¾ÚkTh¢PA~qfˆ¬ ¿Ø6y ÐÏï€è&?¢_¸Ñ¥èw¤³¹/^mÂ7¹$ôED¼\ ŽXç’8ú¢!?LBß¡Y’Ðç'Eè‹;èó«&ôù»#ô•P_|A *Pßñîñ€t ¾x—©aûŽkŸ°/\Ó;‘ØWúöEå¹´”ûbk 4Lì;4¡ûnó‰}G¸ñf°/â÷Ú‡üâIŽøÅ@l¿ƒâ‰È/n!'’ß±hd ù7§’ß¾¡Ù3ȯ´ý>ѯ\Øï´N‚ûm—<ØÏ‹ì¿µý| ØïØŽ%ýŽÅ)è'J»Ñ/F]~D¿èåAK¢ŸG&é/œEó« ý‹¶QÒß±z®#„¿|¹ï’ðwȦ@ø ^ÊÍ+áïÐf‡ðJÁÌÀŸžà/\.úþÚO ‡€ð§€ð§O]ôwÜÜt’þŽ= ýô¬„~ñÓÜõ‘ý¢ÛIJŸ^¥ØO­à—PàOïNðŸ_nÚIqÁ39ô§RôwhJú‹~¤?}8¢¿ò£Ä¿¸‡Ürÿâ+éyðOºðOFø·Ÿ[üó=ÿ¢Ÿ„ âßA%ýÅãº>ô¯·e7 ¿8Uòé/~u$ÇþÊ©@~Y¤¿C[tÒŸ/ð'ƒ%üùj0d?Â_iýùÿâzÇÿÜ/èÏßéï?»äLàŸF¸ðïxÑýÿZÝ„{PìAüómÿâñM´pi½0îˆG”CHâX]±Ùþq²#ýÜâ‹þlñ±Nõ<àO+ŒèÏ:éϯ›ôktÞ%éÏ3é/ÎÖk\[a¤ýyf ýiÝýiw%úÓ2)ú;ì“ôwäD1¡åWúÓ®Yôw,§ˆûçk,YúÛ»å€Q¶/ŒÊMUä¿ %ð ´?íå€á/±òßOü+»,Êú¥ÿ´LIÿ;¶×°ñoÄÜ< ¦ü§yHú_;Òô¿#WmŠ& ‰ÍÂÄ¿¸Y`Ä¿pëËn ý•CRû ¾Váï2HÊÐþ^¬ÂžÚ_’»}jᘨý5^Dm7Ó߈H d´ƒö×B†J5Ø´Ù$6ɼÀ&Ô 6mË €¥`Ó'AlÛw­ð_£YüWzÿ53 €M»Z`¸<.FÔ쵪ÁÒ&þ‹3³No.UM›u`ãÄ%lÚôãúØœkUãD lB`¸1R®UåzÀ€M°qjÆ›aΙ\«š¤fB ¯!2Ðà€M[K``ã' l@ÄÀ†UQØLŠ ÀÔ“ô láýŸ¿6ÚMEMõEp¯V~/DÁ&q”(è”(Ø8‹ =Έ‚~DÁF+­Pп" 6ƒPÐ_2QÐßQ°É¬Fô0" 6¹p›¬_@AODÁÆmQ°‰ˆ‚MÂQ0v¦lIô˜! ÚY„,Ødˆ ¶ë†ðNlR:É‚qLúš“w¤Ù‡ã\ÐïÀ‚¢ QÐ/‹(è/™(è(è (ؤˆ“·odÁpÎ~>,ØÂ=? ,ØV¢`9(ظ‡ 6Ã!P°IÛ& 6C&X°oÄ‚šQÄ‚ú•X0¦¡;9,•3rOŒw•/²`³%¶ 9°‰«Àñ­õ<¯à#6š3D‚Z§HP­H°…îöQý7D‚ZE‚M I°Ñ¹A$¨×-Œïš¨ ·(ðÅR(06ã£6j¢@_)0‚ŸÛ‡µ¡åÃ#ƨÎïœØ>`k$q"`“¤ Œé§¡ãyÃLùG…–„}i½©Ø7åFIî{Èä>*‘?+mðû”¬&ðƒÿ¦¨oI}tÃôaZ7óig$èÓ.[Ч½0¡ÏæPAŸöä¾r ¸ïÐî„Üwh7@î;´Õ%øÚUüdEø•Žü®n? ~‡õF€ŸåÉ~Úï‘ü|r’ß¡­¸¤?í*$ýq -åï=d@ „•R›D)2ýKù“¦ åó¸•?©'Tþ|•¿SB$¤?ê[RþÞgÃwTþ(¬Zù#»Jú{§~f熑R‡’þ"ë.âµa¤¤#†¥?mî,ýÊ`Eé¼-éÏL)õOL)õ›DÉ…ó`¥”O§Ô?jM”ÿtnë‡òJ¦™R0!ý+šå?‹t”ÿ¸–ú'ÅSê_DN¸Oö;«fCªE„•RŸºÔ?í–¥þék“ú'USàE—8 €zÁÒqW’õ¥Sô‰(ÒNm Ðø( ߨ%@~I’5ê%ÒR"ÐpFÐ(FPOÝ §Z)€V©ê©KªJœùÏÿNùOŸå? oÉÿ%ÿér¥ÿÑjý_¹ä?[òŸ¦bÉÂVÉBvÉz’ÿ¤ÒKþÓ]Iþã $õÃE⟼¢%þiJ’ø‘ö÷NQÇWüÓµPüÓ@•ø§›”ø'›ƒÄ?ŸšâŸ>{‰ºI‰’¨¥þ¹ª2ãHýÓŽPêŸv±Rÿ| Õ?Î}Vÿ8Yý3hAýã§dõARÿ¸_°ú'YBêŸàB D XG ß„@>S €Ò3$r°ZÔVV \ý$ºg €ºB €ô]°¨{§hæ¤ÈïK |Î$ê>%ÒZo#Ø ' €º> €:—@Áµ@"‘@ŽW €>@ŸŠ º¡þ'¯Gér¥“þûT –Öô¤ú`²êg;ÉÂhÉ¢sÉ¢TÉî˜ò –Öÿt¹Òÿ&U¥ÿq²þ'âþ‡[¢ø7&e<Šò­¤ö'Ÿliòz–ö„“Ý@û£bí»/‰s¤©@ÚŸODñ®Cÿ¨lXüÓ¤ ñÏýPü ÏãöÅ1iú‘øG1ÆâŸ^â_‡mÒâ_ì§>Ø'Ç:‹±“Ì~(þE‘¤üÅ?i‘ÿäMñïKÑ ñV³ß*µ$ÚK-÷C{˜VE{Qü,´7"ÚQe¾­ËæÞ´×´™!í½«Õ8_ìäǨ0ò^Œ‰ó|ƒ Åø­EUŒwÉ ò“Ç?a£cü¸¸÷âsIð îÍçapcüd¡?z+ÆŠ¨BüûÄ?ù)’öN…‰‘öÊ@{§ Òž/†´wÔ…H{gà Ø;ét/Ø;iÍíœD{'í$¢½“Ö ÑÞyEòÐÞ©HÒÞÉÒÞÉIK´wJGí‚nâޮƛàÜ;EÔĽ )+´wr6íÒ#H{rÓí÷Ï ¿Sñe¤½“þD¢½¢¬Ì’KR9´wÒ!F´„?°wʰwÊᎴwÒy„´wÒ¿D´wÚ)3iï¤y]´WZ€{§ÜÙˆ{§¡¼w)Æ‹¼WŒ¤¢à½ÓÞóÃ!ï '#ïE®ÄõÑùN¹v“÷·±‹ ô;°¡ï•cÀ{‘jì¨Bß)§ßIß4ß©2ßùÐ?•Àw*JšÀwÊfFà‹»;>À±éJàSNŸ‚Pé§€1Eúèêw7êçcêç†ú5†+Ô¯ÑÃP¿FÖ%ô \P¨Ÿ¢¥ }~Ÿ„¾Ú’ÐwÉ1ŸÐwÊ÷Ôw^ ©Ï''õšÇI}§‚0I}¥gPߤ3 ¡ïdð$™oׯ†ƒ'Òn8FÔç/…Ôß"ê@}§ìdÀ¾øÑá/W×ëà\ì‹§5?á~ñ­gŒ0±/ž_Ž=b_L19ˆ}1Áe¸"þŽÁ°AFü`[üéÅú<ðwpƒJê;å*Eê;²*ê;éÿEès˜/æÄ§2ß)b!óVäî'¯FÅûq˜‰ù|"†û Ãî÷ü ÷ã w¸ßCÜT¸ŸïÄG+âÓÂ-ä‹e0ß0‘ïälç€?{©ùN…L‚úN‘7©ïl´(€úN)F¤>E ú&¿?2ßÉd b¾¸ÞD 2ßÔÛ$óІ%ó²€ù¦Ld>Ç­ûâIä`%öM…G’ûâ®î›v×÷<•û´)÷MÅ$‚û´øŽÕøM+€¿)}à7$ð;¹¾ ü&M·¿ñШDð‹8<øfüÆ£(;€_ÐÃæåê: &ð›\ÿ~SA“¿qbÎVÌ÷ô¿qI¢LðS¦ˆâjÑ%Ë{E—|šÏ%ïu8+¡Kh§Hyo™ Ö׆¦°¾¼×#Ës®5Šés cúr¥7ïõ¨å} „A} òŠé;Ö—÷J cúJ bú";ï'¤oç-NJDH_iAH_iAL_mÙA}º<Æô¹!CúÊ/ÓW[2¦¯´ ¦/Zzõêì{ŸTq¯Gjã„õÅMÎ××£ŠTîÑÁ{=r­¦å¼×#4ä¾½í†Ü÷zdc¸%îõ[UàÞÛ²aÀ½ÝRq¯ßÏÜÛ-ùé%îí&î•àÞÛ"å.q¯ß\‰É{»…%q÷zT•¼·[¶=y¯þ*yo§?b‰Í{» [˜?P10à½eÂXPe/H=¶ÂLB{gÞ,eðí$-íȽ4T³ðÉÜÈ­<œ÷ŽÀuCòÞnA&•Í{ûòXk|¯GåbÀ{µ%yo·5¯Ë§e¯Ho {àÞn8+îՖĽÝ2*îí Râ^mIÜ«-‰{Ÿ–½ íØã¼W[6î•ðdàÞ§%¤Ý€ð½Ä½ýS´îõ›Û(âÞþÕ@Ë^jKâ^iîí–£úu~Zö‚T[÷Ê îՖĽÝrÕ¿zLâ^=&q¯¶lÜû4¬±N³q¯|ýÀ½}È'¹K9¸·É”ÇXö3Íï¸Wž;p¯þŠù6ýê{õ˜Ä½Ú’¸÷i¹sÄÆ¨LLà«w±éNoÀW€¯à+çJà+øê!øÊÕøjK_¿±¾}ä½Úoò^í&yïÓòäÕ‹ðÕ–>·øÜ¯“ÀWIâÛ7‘;) ß§e¯°åG‰|~ç@¾zH"_=$‘o“‡$òÕ%òùÅùÊùÜâ+ |~-¾Ò-€¯ü(y¯þ(y¯rby¥]ƒ¸W¹ruUÀ$h¯þfåêªp/Ð^my°ºªО?#g¦õ1 ««ž&h¯3°ººebu--{kà›ìÕC.,®>Õõh¨æn¬­þÑÂÚP/N,®¥‹«ÞBÂ^9`¯ü(a¯ßŠ[ìÕ–ÅÕ-‹«^ p¯v|bqõÕ\X]ÝÏÕÕ-‰{Ÿ¬®zÀ½r p¯¶4¬®¥ei¨5į\aâ^m˜X]ÝÍÌÕÕ‡œ\]uÈÅÕ•2%p¯Üp¯³°ºúú¬®:p¯Pý‹i*_•Ô?N´ÿš„3ˆñMõOªO_°Ä? i‰й´¿Þùx|:O³´¿ÎÅŒÚ_Ø›û'áK ˆãåçg#õOK Ô?}Rÿäï õOYµ¨þÑ_„â_TïAüÓÄEñÏ'¢øw&j¡ö7~ùЧöowÂÁ3WÖs8ì/Å?iÿ´8Pü;•»@âŸ0JüsÞNŠŒåµúç41”ÿäåFùObå?*QÊöIõEòŸœý$ÿM˜*­ÿIpºO$áµøÞËù™?Ù \%Ê Oà/‘~'ó]Y´ƒ'@i¥ãHTbS €Js!PaH»$û4 €œ+,v©iù!Kÿ›’¥ÿMe¥þ'aGúÆ´å?¦‚³ü7”]†òŸeDê Šõ?f¦³þ§SAþs FÉú3å¿¶»“êŸ|©þuäQý“,ùÚ2å¿É¸lËQB „ùÏ ^ ÿYt¢ü7¥±[þ»~düô{¡ü7õ^$ÿ1FXòŸK©JKõoÐKêß\ÊæIõo0~êߤ/‹Ô¿yLïIõOy”¨þ ÉãRÿvõo2®ÄêŸfª³dúGï$©;h‹ F)âg%ŠCb¤Ä¿ã§ø[Õð·×ÉÄ(ÿ4S@ü›úÐ)þuzb–"LïÎþøÝØUOúwµÔbJ¿ÿ;Åcþ¹"LÛßä¬ECÜâbGls·¸ØÑˆ²Ò½trKé m¥/µ¸¯]ºtÕ‚Nnq_ls_nù¯.Â4¢Øf<—ÿÊ"L· †´Sðãÿ] å×oaôÜ®ÖR1?¿«øbbËþ9H]©¾’º*õ•Ô•ŽbWå våúJìªÖWbW> ]ÕƒÔ+,©'WXRG<†ýøu£úJê§ÔWRG:Š=•ƒÔ•ê+©«R_I]é(vUò(e}%vUë+ytó(tõÏa-‘ñ?Š0ýQ¦?3;ÿý—yö·æâ¿ÿæ(ý9?ÿö(ýµ¯¿\þ(ŠF1»ÿ諾SUýåº9~ôo/~¬Ynt ¤þÇ%Þõ1û‘¥1g¦AÛZÒè½Óœyzôwåõã™êß–•ÑM3Í»Bï2‘h,76£¯´æÜfÏØìö†½ÅÛ²â2Þ_Ã{{ŒtîñØ÷ŽsìX# ¢{ŸõþÛÛ û¸í<ö¶Ü{³;é8ù>»3w»t}?×½Ù­í±7½tÞ†Ö$¸¿Çø·VðæÝÛöØ^mÐÙ²Ž¿Ù7ÿýóN6¥öîãfz’7¤ëÙÛ¤q•ìì{‡¸Z–uÈG3Ûôö°4lãîNoßö6KÄ1/|ÈvzûmïÝéíéºÒ9²XIËc®–éíàŒ–'¨yÜ2yŸÚV\®äÝ̽۽™a‰Wò áÙ»Ý{`þÃ9vY!ðĶÆf7l:{Ï·Y#6»ª<²1,6»Ñ² 5›cu¸è ºAö¹²äR~g¸Úupòn¸ÜgOdFì"'ü Ã726»7-*;"6»*F²½K/Ô"y/bÄf÷¦¹“;9×Ú.åÇ~¢ÆÙ®p•Åœö¾ú}g–wb=•qíÚ­ûÆgöu¿ÃyšÎªoËÊêNº‡(ß°Ë;ñÝEm†Þ>ÝÄçzýÍõ²X?hWnÙ–®xZ ÙŽ:½T€Ù¯:ËÆUöcÚuc¨D컉ÑzÑ þþ[ÏZ\Ê÷Òáš¿oÞ–­Ø¾-€—¨Ú´kQ"w¡§íH~©›ðÕÌÚùb¢€TŒÖ‹ùµÆ.`ew¤AÇãîY‹(3ཱུÇ]Þdø›íÑvý.cW²GkXW¶<9Zi[÷¦wŽVÍ+J,ž1ò˜0u­R÷âmyr´2Ý»+»r´’ëFÔÚž3ëÆl1w¯]°‚Óq”ƒÏj‹×¢`ž*?œ(×Ûñxòaìbàùt¶1vDÅÜ,FR##ªxïjLQ2ž4½»Ôˆòê{¸ÒÏxDÏ4O¾ ¹÷,b’sŦ®;ëãœù«÷:F¯w)ZvÜC—É=»NÈÌc2½ß¸4ОP³fýžg{Úî1¹ïbÇÖ(÷ܺ'”yÄD—/bÏ€ï,ž;Ù‹Á¹f¹â±¨ë,_ÊÞ‹ìâ1ÜïÏZã*}îÀç–_Sž:‹`»äÐŒTí.3ánSÒ€›ÈŒd¹ê¡Üù«gëb~Y³¹º^Ü"Í9÷xö™‘mg,d²÷Ë3ÒíñÊG:#9Ðr«35÷êzq“ý6Ü üØ‹éŒìP­„è̹¯:ð¿«à‘ké6"ÌH¬Æ8­‘§Y¹ºž¾¥'Wס‡Õž\]jÌ~äâ:¸˜½åâ:¾4{ÏÅ5„´¼ÜÞhªÐf{nK‹)¾kt.®“Édf[×*î·%×XÅò…÷+W×S—Üï\]ýlúj9\¡V¼ ¹ºª~ÔìÏ^]Uæ½Ð‰Ò‰gª9ZCéD„&½-¹ºjÂ{wX];ôЖž=\uÅcæêzq£‘@ujæˆix|ÈãÊÕõâ:9ãìÑ AïmX¬=û]¹¸ž,2·a Å ö3ç‘‹ëEcÿÛ²׋1s¶\\cŽÌ«™}/®š:f¼×µ¿>lÿf8àïÁªxÎ\\£†Oö{æâzQõ1°+ƒ¢gÓ²ÐöA3,p{°j¸Ì50Xù™D$Ĭ +ÞÛ’‹kTêÜÝ„¨3jäå aeBÜs«²Ò:ѵ“ïÜßæ“¿Ú È„ÑOôWþêÌŻТñy~Δ£›ŸÚycm¥QpF´ÇƒØ‘·7cdÄæ!O.­' (LLöwï(”±µnûqBã}‡ß&G»ÎkäÒª­úŒRMç(²ÈÜ è6µ#Pe^g.­"€‹aŽÕɳ‡2<‹â7÷ö;ö]EåÅ;z>ßëÙ+«¼&fTÞÛ1TmÒJÑê4q·\Y'¥l[\fÈ?[I 8W¥À›‰0D7C3„r±%Ú•žØ—ˆøþ.HÄÀ¾˜ˆ”ø'÷ÏÀÀ÷PDß–[зªK›Àpc`¸ûC/ bà;Ur“ <Žƒ'O Ü%‡®Š#F„C0®™ÂÀÁ‰ÀÀƒk…0ðàp*3¸0PÅb„JO/ T’a`äχE Ìb`cTªP³¡Pï–ü§UJü§ÄÁâ??@òŸæ`£´ lðäÿùÙãú¶½UØâÀ&'j¢%6Y(€±åGô§DÔ’$lG#ËM.¬>D€1$žô󲄊ð` ¶@¿àAŸàa ú’I€öV ÚE€n‚"ÀÆ-. Põ³„€Úì%F‘¡´ƒÝ…€*Z#<Ý*T‘!1àÁ¼ b@ípÅ€0"<¨‰a7I˜…€¾" ’0 ’ðдTå.1àAT#*á²éY…€J>'Tª4!àÁ ç/”E²*’å@äú>pàfŸr Ä6ÊÍŒ'9»c©M¬r·D5°ÓÍIj`gX©áðÑj`—œj /¤vÁ,0°3lAjà@P=)pX/vÉP›‡ö¸¤ÀÁò°¢Àè$÷ʤÀÁ ¢ÀA7ZQ OD ,ý€‡tRà L8RX#ø. Ë/zdÀa5 ØÉ{{™êðþÿ àÿ†E7àßà/ü‹ëhÉE*ÞvOþ ƒðo`uý 3#èoüBÃú+- ¿A/MÑßRLú†)àßІœø7„<À¿aáø7Ìm‰r¶þ ño ÄºèoÐ4,úÜI‰þÝ^EƒÉE¾qÒß ƒ¹è¯k¨“þºöߤ¿N;¥è¯³"ƒè¯3áŠè¯#="á¯_?à¯3Ñ=á¯Kt#üu&)Møë4/ þ:3V þº,D„¿ÎÔÕ‚?ÿŠð×¥zþ:ó2 þ|‹„¿ÎÂ=‚?_!á¯K…#üù ýâ€!üuÍÉ„¿Nì üéù’ý|Å`¿.óÙ¯³“ØÏ§&ûÅÛ^Iƒ`?ùq þ<³þt5d¿nì×YîTì×Y IðçÉŸð×YGðýWy„,Jøët~üé kœØÏ @¿Î B?}B?}ÄB¿nÍè§/_èWzúujÛb¿.Ƀì×9äÅ~z1b¿N5’ì×½„?Ÿ ð׿ÎÄÝ„¿N‡eÁ_§:ᯠœL.&øëÈ~~T„?¿7Â_'û þºu<À_×6Ÿð×±3ûõØ1æ!`¿N· ±_gþ6±_gˆ¢Ø¯ãÀ~:7ÙO3ªØ¯³nÙ¯3ˆLì×¥’ý:Ó„Šý:âÌ~L–)öë")²Ÿ:ѯ3 Nè׹Πýºäi²_/j`²_§aIìW~Eö{øÔÉ~¾@°_g.c³-È~]¤,öãËì÷P_%ûu©6d¿.¿²_£\ì'·7Á_D•$ãþ:=ÂÆPÁ_“ÈEøë´nþXÑð§Jøëj!þ˜ßXð×À_éð׬n\|h¹ü-d1üEÔsj°„¿ÆÅCðטQð'£ÙÏ7)ö£çد™¿À~îBb¿Æ¥BðgË᯵VUÚ¶²×þÓ þÄC„?Û ¬$%øSAÁŸì£†?bÌDð¥˜^On‘">Nï&>y³‰ø˜“ÄÄÇœ¬&>©(D>æòÉ~*äkÖ|*ý(ä‹à.¨o@>Õ ò5¢¾¯1¤WÈ'©…Èט‹̧Qhæ;K3™OCYÌ×%f‘ùº¼É|>†Ì×éF`æ£ÔAäë[øñÿìÀ9ð^î÷ºø“È×Y8LÌ×i‚óiþôuíú}"rçF_§óÉÏç&ù¹’ŸÖ]‘_§¬Fð+Ýü:=MD~µk”¸•äW|~ÈOk¨ÈÏäW~òó$ùuZ]E~]¢ÈÏ7AòëVÚÖ(ŠP$¿þ ùu¡3ѯËAô+×ôëÆ: _¨‚.ôët–%ùuiP"?+x$?=v‘Ÿ…ÈÏɯ´`‰²‡(йÌ~’•É~>7ÙOSR²cÍ~‡p‘ì× *b?µˆý:0à§Ç+ðä>™.D}+¢>}g¢>}g¢¾¾%|!S&ù°™3ñé«#ñáÊÈ{úäÈ{ýú¡õùSïi.ïi’ïIšï¹òž>omÐ>i¬>ŸÀ'—ŸÞˆ€¯ÑP à“` à“¨@àÓ6RÀÇ“ øh­1ñõ/ïiŸ)Þ“Æ Þk(iÞãÃ2ïña™÷p"žBØã³3ìQM7ì1׃aON{¢=]°h«h¯£°±i_žhï3’ö|Ȧ=)U¤½Î,à–ú$Iê3÷˜‚øÇlÜc̲qfNÓ[ã¤qKŠq¶\ãž6ÿÂ=·÷&LÜkt@2îq1îaOa©Á½Æ=I¸‡µÔ¸G_ã^£-Ü“Sœx¦fK}VÄ{4P›÷h?·ÖÇìBæ=fûïuF•XëC>4ážüŠ…{Òp(õÉUö÷q¯ÃNmÚSaï8øÂrššõèLfÖóõSèÇIèƒÍܨwSR$ê5æí4êY7#걬…u>Ö0ê1u u>FnõÄmD=|õ¨™‰ô¤y‹ôd3é]_OOÕÜ6èéúMzôýéI„4éaëbÒfŠô˜5ߤǺm&=ZŠMz“ž9“¤'`$éùG$=Øz–ðHzƒò¦HO+¢}-ÿLw;áD¥;{qŠî±èÎTº‹GŠcn®HÜÃî†yt7n‚î¦ÕHw“ùKDw“¶èîTéît˜ èî⩊îcºyñ2«‹ï–q€·‹FÀ[ ;"à-î\xåÞ’ÿ%o1"F€·èp$À[ôRà-î x‹¾lä»n}Ðúö¢´8¤Åw‘ÆéÝ'!ß-XÚ…w_¼[L5$¼[ú”ˆw‹Yƒ„wkò…ïœ~„w¾â]|©ƒï–± x+çâÝrüðnQ$Ý­ Ù_Hw‹ ²Dw夻# ¹(-æ~Iº‹?ï²·Náèn±ˆèn±Ršèn)l™€·˜ÚL€ç†Œ·ÊxˆñÖ;Ç0’/—¥%']2^ø½Ã=Œ·nò<1oqÁæ­[‘|à¼ÅÀr^<­ü&ˆz‹yÞˆz‹ÉB…z‹î;B½ÅR$B½¸‡D½e!¨ç–¨·Råõ–œˆ‰zkt¸Aõ–üû‰z,s Ò[Ì#$Ò[rÒ éé’Ez‹â=Ioi{HÒ[vMÒ[óƒyËÁv ½ÅL‘ÞjSZßÂP•Ã&HoÉ£¤·GÒ»XñS°·XR°·hìùz{‹ùÚ{K>„½¥ð+ž&QÂÞb@´`oÑšIØÓkìEË0ìÅ[‚—'ÖÕÅÈ ²ÞÍxU±Þ:ä¹ Ö‹÷ëE‚½ó#í9¼¬·ë4 Ô/×UÍ}‚=Nb½¥Ð%²ÞÎýÿ‰ëó&ë-Æ5‹õ´ õü1’õnZÀÉz n:B=wBÔó["êÝýëÅ—õe= ²ž–U±ÞNùþ·‚zKn±D=?t¢Þ-„ êÝÌ_)Ô[be¢Þm1 ¨wk« Ö[ÖÉÀz*ÕAÖ»õ™õnÙÈzÚ…ö–Œ ¤½[”´·h_îÅg‹c€{Š‘î-yV÷¢Léýá½ëáHÞ»™£L¼w³¢°xïâ.Þ»éU#Þ»Òè:²ÏB]òÞ­08òÞ%/ìÍ{·ñÀwO+yïâ¶D¼w)Ä–Àw1Ö¼w³Æ—x$Þ»˜!T¼w+´“¼çÐIòÞõp$’÷.é—ŠìCF_öùä ìczjâžòW÷®Ct—}š‰{J&(ÜóÃ"î©ô¥û8|KÙ#a޽Ͷó˜¥×I\ lß[²í*|OÖU‡ï :{2|¯Oʃ ß+-ßS Ã÷b˜Õo³{ëÈð½eå á{‹U¾WZ¾WZ6æí:A A„ï•C6çí†Ü‚ójËËyûϳfq©-Éy¥œ·[Zå¼îÍ8¯“œ§ JÄ<C"æíbHŸè½}“­êx»ÐÃõÊ9ÁÏ”·ËAØKÊÛ‡ä åíc@‚{tº~)o·ÀercžK!ó\ ‰˜·Ë}0Ï…Žˆyµ%1o—,‚»fCu… žHXG«)¯ü(!¯’÷iY(çÄ+@žK!9gK!‘òv Ü*7åíFH¾’”ç*8 <B"å©)O…†y®ŒDÈs!$Bž !òv Ò¼$äÕ–¤Óɰx·,ÕqBljyõä‰yµçļú«Ä¼Ú’˜§R0¤¼r(¯’W’ñÊÅ€ñj/›ñê!ÉxõÍx.›CÆ«?zïóç­ N£ÆîÕcòüþ y®XBÈsåBžïŒW®ŒWNÆ«Ç$äÕcò\R…WIÈ+ ¯¶lÈ+oWïêÉUUgåÕ–†UU7Ê+WÊ«¿XUý«Ù¾eaœVW Ì+Ì«-7ÖÕÒ²0XÕ²°®ºåÁºª`ž__R^ù»aUeá@^íc`UÕ]òjËĺªý< ¯v|ªÿÍú«ëªôY@^yꀼÚóƒuU¿äÕ–„¼ò+@Þ§+«±/!¯\3 ~~‚¼Ú͉¥Õ'ç/VUõj7–VÿdqitP^90¯ôÌ«- K«zæÕ–Á¥Õ-XZ—À/1¯¶œX[…èà¼zLr^¹‹ä¼zªÅµU‡RJ}ƒ>¹”ú†vóŠÝS69h}“Å›¥õEÆ/d ­o*¹!µ¾ù“·ž Gh}³PaÚ$'=~¤õM%´¤Ö7%UQë›Jù@­¯´@ë›ó§Ö7çÏ,.SÏ“ZßœwöÔÖ(ôMxóS盲PçÓÐù|u>eF“Î7m-oÊ«”:ßüEç›´•Hç›Ê]I¯oZS„ΧÚÒù¦R®RçSÍ,‡ð=4¡óMé áÓ®BŸrü;„ïa6y†ðiû¬>IåTú¦@\1|:}ï®P!|œ÷%ôMYCÂDzá£qVJßp ”¾!ƧÒ)Ö³BßT¢ }qÈú(}“ñßTú˜Z\Bß`…>¥æ“Ð7•ej }Cá\ú&€$ô .0ú¦,dúb˜Ÿ¡/pC˃¬€3}qÌó ácA }“¶n }¾ }Snäú†SèóSèóË„Ð7e¢Ð7”!BŸÏD¡Ïß0…>¿' }ƒ®vú&,ÒùΤóMä§“Ì7”TŠ2ßPàe¾áhAÈ|ƒ~”ùü}RæL„Ì‹Âú¤oÑC§Ì7XðN2ß0…Á¡SNUTúË|HéJ-G¥+”„¾¡œuú†rÖQè〒Î7ä Go ,‰d¾xäãÀ7äEE™Ï÷D™oÐ}F2ŸÞ‚d¾QörM¥÷‰d¾áL›)óÅÛ½?2ßP˜Ë–ùÆýÓ§s(&:Ÿrs:}§z"ž2´ów2ßówÒ'*ß.Ýáðz Tùâ5Ù d>?NÊ|CI-(ó ùïQæ‹~Ò±–2ßXðs¢Ì7´9¤Ì7h2£Ì7îŸé;}ÔùE Ê|±½I¿@Ê|C~l”ù†" )ó e®¥Ìç‡Co(¼‘:Ÿž1e¾¡¬5”ùóKæÓt-™/îóîaQåv“2ŸJÃHæ·BïRæô”Ì7.Š­”ù†Ü()ó åܠ̧¥X2Ÿ¯˜2߸~Fð %P¡Ì7­E™o(,e¾1™í*ß ›‹T¾¡·Tù|rª|ƒY­¥ò ¹ÍRåtü£Ê7›J•oH6Û*ßP4U¾!WÊ|ÃR!d¾r½ù†}$¡ó …RçLâ%o(:_“ ™oØe2Ÿ?lÊ|C1Ôù¢Èg3ê|ƒ©Ó¤ó1e¾Á<«Tù½g(ó å}¢Ì7XðH2_×J™o0ù›½: H¥Àѹß]-hqíb~.àóïj©…Š~ÿw>ŠÇüsŽÎûýºZ-Èáb›‹{¸Å…„®]·Kr‹ûb›ûrKé+ªŒÎZ,É-¥/´•¾Ôò_]àèÜÕ½Îß.pôKy¢¬_4U¼åwø Ž~ýÎX’¶ñÏeX~~WñÅDiÉo…#õ¥ÚEê«/R_:J}•£Ø—‹±¯Z½ˆ}ù(öUR_¬_¤®\ÀH=ñuäcÔÊ©£R¿H=é(uUŽR_ª_¤¾J#õ¥£ÔW9Êc•ŒØW­`ä1ΣØ×?Sç(ÊÀ=ïÆú·ëõTçè—ñ·ëýÞa?ëýAw?‡ÊÏÃ~Ö9ú£ÓþY?ëêü¬sôg&é¿ÿ2ÝþÖ”ü÷߬?§é߬¿öõ—ëEQ¿óÜ~³ÐÑû4þOÿïÿ®2DTíè=øÿþ×pƒÖSª•þ‹uJãÿ5ÿBÝ£36¤[‰=È­1›;Þ3vâ«:kœa•;y5ÜâÏ0¬ÜqL~?wK†Eu9Ò¾[¯¶EEùþ [UCòê+û;®¬?Œ|>ÃÐ"ÈÃÑzîªOšnñ«H ™©é¨z¾{—°ï¹û&fbôÛ³ìõÝãÜLúqFÅÊ{Wªk£Í<ó'Ûær^}[zj'/zŒ+ï ßËõîCyhÕ8£ZA¿>¿Šœ¬-¯.;¾vm Ýp£åÞ*ÈC>¯—<öòª‡u½{‚PARâÛòlÄ& %Í} Ï(”´žú«p3/y{ñœw&#x[ÀïgÄ´„ ÇlÛǹÝ#??ÂNÐw~ÏgW8dʾ3 +¯ïÉ^ÞæÄãºòúâß®<÷¦°3êlùj¶4|nýòΖ•'6oí gx6Ýwý”bxw|¤ù"V˜¿ÖçW/|4<¯EáŸ{®z[Û×™ä÷nþ _ë=`ßž·cÂûýmÇ ÷WÈFŒÃn€Öò6¬°îøý7¼Ï|{ëeË=`ý£wªÚöF<ðÛ²rÀê}>Ç•VOð û×çM<æÛ?¿ê+¬.çy©hØü$£ Ü­þÉK–{´Â.pî aÕ·Ï(+ìugüÛ¬Œk8Ÿuä`Õ==asûœé9s°âLïàùƒ=‡^Ç‹ã{¬øß–;Ǫ["%ÑUNsá[Ú>ýÌ#Ç* ooÃC•#á:Âöu—{¼ŽwBãXÝêŠ|˜{¬Ò\÷¶Ü«°¾“ÍÄXí)‚¼lÜ1Vñþ¯HWšc•ý´w!õy š4½\‘~Uæ»"Ñû]ž^¤LΡª^ޅ媧n¹jx½v>ç–ÝæmFHgUL WD^Î:œ¯%ÜC•ÐJâªzþº‡êtW$Yé½^OÉ_X+¶…ñÚÙNF™"¯ˆTÏ¡z¤ üêcj¨æ5÷‰µÕýÌ•C•“À‰Ç°Àô<äÂÚêŽo¬­#=˜¯È]zŸeR¸úÂÚ9àò®®­XQÞåk+bDß,­ÂϯѰ´Rx¸vRÑx\4Ú_c`ie®Ö+¬3äÈ_M.­°“_a=É¥•—Æœ{߬(WŸöh¥ ø6µk~nbííŽ#K¯°æÚ +ÙÛ²Ê~…Þ°Ç+]Q/úcÎ<¦cmež¸+*2íñÊÌ•×\[Óˆ|ÍÉ¥•W7O¬­Ü)½-X[i‹¾¢Rv¢+6F×¼wí]Q$Çм±¶Rä–‰ÁÁ|ö³ÛŠ?£Ôü¬QÊñÎ,¬”i¯³aa¥/ö•…ÛwÑÍx»†ý~X4rae0íuN,¬±çΖ +c¯óÂÂJûܵvöheÔëuÞXXI¡×¹°°²èá%{öheèÒµù7ŽaÐá¹{´vÌ£QàoVÚÞ®¨µëH¿Á+ ®å>øØ¬©LÄp¡`ÝÛ‚mÞµk½Å/°¸va·xTÌHr]W®©TåßÕÐ&x¯s/*bM¥5ñmÁšÊ\:×õ`MmXá¯hÙ#•™Ò®»aMe>ð+ZöHe®š+BöHeB’+ `î‘Êô×=±¬2/ÈÛ’ëꊉ2Ïuž9RÓÑ"Z.¬«¾žë*k´¼-Û-÷“,̬ER8ø#dþss ¤r`>dqà­Ë’Ï’ÇA©ßx/µÄyà¤o d(1ðí#£QMV¤Àwy‡ c |ø*Aãÿaï]v×±}¯>OQM i/Åv;M@Btuž„Ò¶tñøÄßËpæ\W6è4vUcÍßø;ŽíØq>·ƒk„øJ°`‰Î&E |oÎI \v]#î˜k ls ³$0pe¥Šy \ÙžcbW¸{0ÞÂÀuó3cà[þ ÀÀ%Ⱦ)0ð½÷ жÃÐØª­ˆ¹5+nþ‘1°ȃB \)»À…Aï­xÄ l‡ÎR@o‹€Wøý5ê€À•ç <ØäJ¶C\\¼®Ä€ï}°csë‚_ 'påˆU|oÅC.0à*sglOð€øVà \ <ƒWF†XÏÀÀ5X1«ç±žYت‡+>I¼·€+D ®:s›W&³”¸FªglBWW2†ØÁ€í`ìBà[q[àª#6@àJ€;®4GPbà[‰x/pÅÒÄ­ƒý¬I€N€Al#v_ ì]H€JàÛ'~~=A€€ë€ ë“èü&D@g†#Î<3ÿ­ ½à¿|çà¿ÕÀð_;hªFþK7ÿñF€¿õ ‚B«ÚH𷢦žqUÀ_;èóøs:<Ÿ“þÖôŽgøËÍ øKO ð—žào=íx( ¿4¾ ¿µ‘Ä ý­—òÖ;b‘ÒR…ôçµNúóËô—Fô—Ûô§¼$„¿ôìkõgö[/ˆ ɈˆƒýÖ~D+ØPy–Hö[o¢øÔûù¥Gö[e”iÚþü¶"ü­ùXoì¨Â}À_š³€¿W“"À_š€¿ÕÂìt`Gå‘ù¯ôBü[s)ª ü{G'>—HÞV@k $ý½“„ßß ¿· t¤¿ÔoÐߺSLZÐßÊ9‡] ¿x£¿•3 ô·¸*ü­ÍäV¸Ÿ"@ëèFüãW* °Œ HL340Í ¿-@€N¿I|?¡`I|PdI óÑL€<jsúãÒÈoT põâ®z$8XåK|ËÀöÕ¨& éèD\_˜w\5°¥Òþx`;œ¸Æ&ØîÀ¦ª ðßš%Ñoñ³=™ÿÌ‘@)4€>bR?e+jæþDÖ£¤ \Õ%”¶•°é>ÒuðC|G ðvˆFA\[M|[aj"`+¨$øo=@0"À¡T+IãØ‹—Ãâÿ–w±]:`ÿ*“ø·ü?FHÿVº‚@Û•kþ½W!;ñÏYbÈÎäDþ[©…FÖ:#ùoe$!ía ×°¡’ÿVn§@ðß+Á'ùOù{Èë¢Cü·²…Öhs9`ãÚ#® x¨ØLnA€+ÑTô’8­÷:xï@.'©ý@€•žæ"ÀÊo9`ã;YXéÑ ¬:’ º_$Àª/p`¥Y§P©ŒH€•¢"ÀJW`c¤7`Õ $Vºá‹CÒˆ=‚$À&&6&÷6F6z܉€y…€!„€Û†°Åd#VÒ‰°1’ °>A€U‡3 Àù b’£lŠSŠ#ÛŠ§j<`Ó± ð}}À`˜®ÊÄT(X!`38ƒ|C" e%.ôÂ*阰1ºc  ’ЉÃ‰›ux @MHa R‘ õ”ÂÀV¥Ã ÎæÝ Nsê€ l|mŠOÍD‚MJ2’à´3é‚ÏãD‚²b ÎQϪÀ5ul‚ò²6&ô$ÊT_ ؤ?Ê V¨leâ@¹gcž¬ tÒ3¡ \ü„‚mnMA[@ÁÆüäBÁyU|;’›>€IƒGL¢Ay:ˆµ‘“4Ø&48gιѠ’§‰•0J4¨Ä~¢ÁÉ€|Ûk«‚-Ð`í` 0X5ƒÚ‰ƒ ^|bÁÆ•bÁÆÀDbA½¨Ä‚z =Æ„A¥– 6)‹ 6¬‰™»O0ؤ±! zn}gÂ`ãq¦`н$ VÑaÐOŠ0˜ê zþ‚i‹½„È‚MŠ ²`;µR,Ø2Z0¨ü„Á& 6„ú' *ûœ`°ÑáM0XéÓ'ÔN%¬Œp#L÷ *M—`0u0X™~G4Xé#¬: º ÁVu¦A¬| «ŽÆƒ•Ñ0ƒ•þ9„ÁJˆ# Ê™Y,ÈttDÁõ•Û3 ®ZŽ ­`ÁV¥‘% *;Ype(»³2peOƒ¢/XÐ9ËÄ‚JÞGtfC±`eØ6² ¿ÕÉ‚«žXVdAEº Vfª ,:4$ ºZÂ`e°<Á bØ×Uñö ®ÐÆÖZµ‘‚—ß9$Á‚ –n#qúÍýN$ã_äÎøG/c㟬ÅxC%ü{¨`#þð¾7þUo ÿè×-ü;~À¿].ÿ?؆‚m ´‘Èñ&ư4JAœ©«`U dâ^`‘-!°èã•X¤æêk‘¨b@%l12n¨P@E¬|É©·–‡ÚÇà?ååÿ)“Dð_•røW­^þUãðO©H„J¨bücLt្ ÿj= ŸÄ?fà2þa;ý)Užé§v¦?§ýù*Ñß"¦?ÆNýUég}¦?îø¤?e(1ýi‹þ¨$&üU¦I3üiEþ*ƒ„ þª‹„?e>ü)× àÏ-&üÕSPø«ZB„¿Âüâ?%âÿUF‡&ÿÕsSÿ¥Z4;üUüy²þ<„?¥°üUYþª´§„?åàü¥šž„¿¹³Äþ”Hð§Œ$‚?% üi‡"ü)¿£àO“6àÏ áOµ þ"]ŽÈOsFäWÅ2$¿Êœî"¿Ê¸"¿Ù’hÀ/ž¬¨¯Ò€AÔ§ü*¢¾ª/5RŸÒòˆú*_Ë¢¾ªãR_’û””ا”¥Â>½Äˆ}Ê %ìÓƒ÷i5‰û´þÅ}³5Hä¾ÊOÜWe¯H¿`> îSfLq_¥e¸o~½õlšž/¹/²g ú< „>ú”bGЇIâsI|µI¯Hâ#t ø˜wJÀW™8\À§÷­?¥¿’ñ§•t >åSñ)=¨O™±„|Z‘B¾Êo!!_µé)OÉׄ|J$äS.¤@>¥òUž:‰ù\-™O©áÄ|z¥‰ù*¼u…|ú°òisò͉¶_eÀŸ?FI|Jø$äóÇ3‘O)$…|Jk&ä›Wšø”]•ħœ`"¾Šð"¾cÝ@|•'k"¾Bçl_‘Z[ÄÇ0."¾2¤4ñF´ñeIì§…¾">å„ñ±€¯PO àS"O_a´G_aÜ _ùAýW¤Õñ9ùŠ,‰|Å*B0Ÿ¶r1ŸüOÅ|Jž+æS†X1ß|wÖÿ¥GCæSFX1_¡Ç•˜¯PÇJä+zùJCE!_Ñ9‘¯ |Jäc‚/!_Ñ„$ò•‘OÛ‘φ D¾B/71_Ñ‘«˜ïøèÿÖÝcJúÂç'¹å­7[¦<ƉJJ¾ß>¢¼";Jb^|«‰ñø7ã5;‚ñ˜±Á*>™ôIÅ'Å‚!OÖ¢„<[ò¤70äíî~+ÏŠòhnÈ£5¿!O¶«¢<†ƒ0åÙ)O”G )¯0*ž)@¼"’%âéu#Ä+²$3âQçBÄôñ.Ls2^aÈ3žiå “*!¯ØG73~¼y…±gyÊ-È+:= äÍz`^ ÈcB41žrD‹ñ ½@yE~T„¼bA@^aŒAžç!¯è#›çá#äÍyZ@^aÚASs“ñŠmGÁxÅpÆ+IŸ‡MI³š7cÿò CÍò,!ä‘+!¯HOÈ+üää³ ¯ðüËFž²¥–•gçq!o¶j¿€¼ù–…¾œçp^j18¯ÈV˜§wµ0¯È)™˜Wt6AÌ+‚Cb^ág¦0¯ð´_˜Wè¹.Ì›CqEÍÀ¼"–%æiò”¼N”{"^‘…;¯è¥JÄÓ Ä+Œ¼(Äã]ExÞøyEö(„<š ò 5¾‚¼"]!¯0-´(OÃ+Ð+UN{4ô”K… =eÚDÐs'ÀyE_·ä<-)qž7^ržGœWª¼íÀy¥Ê#/8Ï &ç•&ûQp^j 8/Ý œçÁ!ç‹‘ó¼Å“óJ¡¯$9Ï[<9¯ˆÈy¾;9Ï5“óÜf¢ž»NÔ+²(ê~“ô O¦Áz…gtb½)ië+ {ÅJ8À^aÒfÁ^¡©‡m=eX%[Oq%a¯_Èz…Žb½Âdb½Â¼b½Âs<±^jX¯ÐÝC¬—:Ö+„“…z…æB½bø£­çCŸ8¢^º ¨çWÙz2M”m=e<-Ö£¡‚m=}/Ùz"ƒ±m=øÏ¶žZ­²õ”)€l=¨Ú¦ž9™zâLÛ¶ž´”‘­§Ü{mì) Œ=?­eì)“B{ê¬IÆžv*¤±'í:lì) ‘±§k¦±§Üyeì©zdí)|‘µ'c'kOüÄ®ê4õ”§¤L=uhDSOÜØÔ“Š0™zrÞÈÔÓN„4õ”Yoî#ñ¾&ëÙ€•¬'#H™zrÓ·©§fQïÐYQï¨ô©gÍŽ~ï}è¿(;Oz ô½ z‡eç©w€í<¹Ê–£Ÿ]ßéè÷ðÃÆŽ~4ɲ£ƒôÛГ!’¡' peè©i.COéŸeèI3rÙy’S¤M‘wß›/®·+×µcºÌÝ•”š\ùä*'W>|—Ñ“o úæÉ§ì0òäSyò)ïŒ<ù’$<ùf‹ã›ž|]Ê4xòMÁw‚'_’À“Ï÷¦'Ÿ2ÜÈ“/K“/IàÉçöÑ“/IàÊ—%c$+_’À•¯S+/W>w®|J$W¾$‰.Ìÿ#O¾$ùù,@8—N¯Z9òeI¸œ' ù\ ¢¹¤"ç’%árž$ç’$ç’%árž$çb ù$ ¹dIx' ¹$I„sIöK’åuÞååÈp.I‚p.I‚p.Y^çI‚p.I‚p.–0œK–„×y’ œ‹× ù¤2ç’%«$ç’$ç’$Î% «$Î% Î%IÎ%K+% ç’$ç’$ç’%‹õÞuyY‚ˆ.I‚ˆ.YžI‚.I‚.I‚.Y2~Ù;.’DL—ô1]²¤cÁâe§˜.§JŠé’®BL—,éZ±O6äÌuQ’2uIeÔ%•AP—$AP—,y´b¡‹CP—Q$LKÔ%KžX±}G½,‰¨.FuIEÕ%IÕ%IÕ%µxpwퟨ.Iòpw¥„Q]’¤pwµ„Û+¿ÇÕ%•iÜ^%9¹½Z2°bAóÂöª"wÛW,£ºh«RTÏ8FuI=Ü^Y†Q]|+†uI’rï+Vš=m‚ ëâ±`Xm‚ ë’Ê ¬Kªa] @a]R™Î핚s†uIežã³dÛ3rÇÖÅŽa]Ü<†uIe*÷XI÷XINn²’\Üd-á&+ÉÍM–Cʸ.©L÷&ûdÜËýB\?>†vq= í’$ś쓔{©b†vÉ’ç—m21´K’\ŸMV¡]R™››¬$ýÖñ½…vñ³ah—Tæá&Ë2 íâ2Œí’$•›ìµÛsæ2›ìµ{÷eÉ¥M¾|×Ð1ª¹ï}É2¾Kªex“9Ž¡%[3ò¥1¥{Ÿçã»è‹HÌ—ÊÔKK¸÷ù^Œï’ÊœÜdÙ-Æwq›éÞ—®êÇgÉ2¾‹ûÎø.©žg«–ØçJˆ}IR.}ö¥2íø,YbŸCìK’«~–¬¼ðçO¤EJ\8OÇ6÷>œ|Yó‡ˆ[VüÑ4Š¿A¬ûS éþh°FÕ_9‚Áª?FJêoÈ“~ФIÕŸÍܨúc.O«þd‚EÕŸB;XõG½™TŠ·`Õß —¤ä/Ùx“~<ô—}gU:øIÑ#ûNZTÙ¾öS6ï<ŸŸì¥mÞyÑQþ}R‹Ñ¾Sˆòïc€ØwʈUžmûNšwÛ¾sÈ “öôø·}']1lßÉD3¶ïTÈÙwJÁ$ûÎasNx:¼ ‡%÷¾GöœtïS(ÿ*ƒÚÃÎgöð+ŠÎ?Eþ¡òOžöð£:U~…ájíá§80ôðSûäáåErð£"Y~TœØÁOFÇrð£ÃœüÖI~òª”ƒŸ5wrðãkS~zÈÁ~rð£õ¥ü¤ ?©uäà'w 9øÑPÔ~4¬µƒŸ¢ÈÁÏÖ£tðó­éà§`|rð“É¡üð‚¶ƒŸ\äàg%üä6f?º¯ÈÁÏj8šzÒ‡Z7É¿äìßG•‘üû5D @?o*å=l÷>¹‘Ù½n RJ;% b“È¿Ïnxòïcô9øÉƒS~š²ö´ç ü iLÞ}»©g“…°¼ûø6†wŸÆNÞ}…^Pr’ÜûøÅ“ÜûØZ»÷ÑH[î}|Kÿ'?Gy÷ÑbÁÞ}LÙf[OÓ½ûh^b÷>¬¡{?‹ìÞ'm¸Üûdrk÷>j…éÞW7KÏ&KT(ÿšTãrîãF!åßtÁƒñWûš š©ü«²”•sŸœ½ìÜ'óU:÷q£—òÏN‚rîSp$9÷éÅaç>éàèÜg—@z÷I%ï>¾äå݇D‰rîÇœûø!oç>f‚KÞ}°Ï²wŸ®’wŸV¡¼û:¬òîSà^y÷i…É»O‹äݧècòî³ß ½û3H–žÚ‚äÜwQU/ç>æL²sŸ aÃÒSÖµrî+t½–s hèYå1mß>ÚúÊ·ÏA\èÜg¯Á“ÞŒŽFCO›¬Û»߇)CR¿¦…|N…1f<œ¶‚œçèW¯r!ùké‘úŠžo`‰ÓQæœ –8 ÑXy`·ÆJâº(s]–¤ºfüÔkë7©¦¥Š(ø×NÔÇüºì05RN‚tÍ-©+õËu«Àÿ\eeuù­¢‘KäV.‘§I¿&Ž¿åÌ.Ÿ 7Çk~ÄoeT“R"©¦”‰5©kJeX“"±¦œ 5¹jÊeT"©"'Db=,Âj\Bµ(’ªIÉX ±¢TF5)’jJ©X“ ±¦TÆk—‰XSN„¤%ÏB¨é¯$KšYnÇûjÿ·dI¿“,鼯ÿñû÷'¯çütq~_Ù?]œ?Ôô§%Í ÐÏ»[ýÿ™(é}C¥DIﯟ%JzÅï•Ó¯÷ÿ|XèDI÷ï'JêW8>ÔÝé]5I¬_mÅg¨ƒ„¯¤GÄ{#õëÝÛ¢´·%˜Ç`OŠM߯wk¯+n;‚¿’þKêÖçë;bÞ¾ƒ_×K’øþn]ë³Ê9^Iÿ%çHê/ÐGÄ{úHôŽ#â=!ñ•<ó,ze"¸CR×ÁÛ a½XãýÞ:á ‚³É~O¨)ˆü+‰ÍùAœáþ~cGÄ{¹Ïˆx?³GÅ/}-é%OD½gh¹þ~EÔ{Kæ':Ê,£Ê÷ó¯DØ{†ö%Ï/Hä°>ÿzÙ2ÂÞãD¸÷é/88%뽕ˆyHó¹Wò =ûŒž~Ý›ä-}”­âû»jŽj¦ûAý›ÓJôÞïˆyH;Ç>¿ FÝ$O‰˜‡<í}%é)Xfj Êø›ògôQZ„<äç|óìÙ.š‘Î<8£aÿ=ãçû–X¦pÜ€ßoçÉ”›`LÜÊu¼ßÕËŽ#}L¯´;w{¼(ÐËvUd—^5¯±óP°æ"3ñDZŠÇò”#’S¨Å3óÂÓóÍg‚³¥‘™á+ÆØª™çA[‘ ÏVËûë6œS)r?1‰Ÿ¨æ…µT5­gˆÌ;fþ+ÖêÓ»>£|^[‘çAvŠ˜4/ôXªÌ÷nαÌ(Kšöc†!ÐhË8ÞÔ¶RÇ´(½QæŠzÞåWÚVóõ`©J2|[Z.’ý¤Æ ÀûœÛUóøë‰«ÎhÏsk©®ÓʹåNLKøXªñ\^ÁóKÍ¿ç§Êå€Kˆ'è(óE‰2#ª¶µ%WsÝX§lîôáäBEãzÁBU™>´P£šqcrJØ\$I§_#ͬ±œÞÏ¿9åʘN±Ç“bz+ÇB…ð¨­ø;¦Óy¬SÄŸÓ¡<¿=Ç¢Ð+½ÓF»ÊVæX§P4:SD¯Ê1Õ;E&óÐ!Ö)óø[?j™'±L'f¬£qDŽYœ>KÎwšH±LŒÝ:niµyÅueŒÆ:ÕÍçëIyÖIû˜©¯cª9=öT öTæí3Qü•›÷`KUÎ[ªn}ØR]¦`KÕd<+¶Ô ¤ï;—[*'5yW3휻vMÛå8/n©,rW-Ó˜2ç½7M«³sGUkwTìã|Ö‰f›óÁŽÊn^wT>©«`GU‘Z´PãNWåŽÊz¯†Uc~ÜQUñÅ•#z]ÜR±ëæ–Êy}un©œ×<þêé=üJ¸¥â_wTÞüžzâ–«¹KQÂ'”)ØRéÕ<îˆ+‘Ë4œØUùÄï“»*Ç뾸«âß·7ÕXów?´Xc}Ü›*Öæ=¸©ªÒA²Ú>µÄñšXÇO¯`äùЧ’8?Ú>?ŽsKûÔç[,:ÌÃÖ§†8Æh„`µ/=ù>ÿ•ƲoÏ#ÖcÂqnOk÷mDß…ýgÿe›Äc~ç;N~n»àùE¬Æ˜êà\ã@ÖG ¦68Ï̤Œi6Þy7ˆ‘ó+8wbZ~¶VtÃÜê©Þnú`ˤ`fÚFrk®¹Ò™FjkÇÌU6ÁüüÝ*WÔhï=ï_¶d­½í¤xÔž mÆÖ dxôMyÔþ>ó«7oä<ýÑ|Gâ¹Òù‹‡ßâ¹Îìâ¹Áˆ~â9ä莅Åsƒ^+ä¹A/?ñÜ ç nPë# tZ"Ð z® èLºÁ“dÝ gŽ€nГR@7¨`Ð zÚ è¦d‡‹èó°‰èƒ3‰ècÔˆè•q"ºW_Ý ´€nP§L s½ºYK7€nPW- T€ èã èÜ<]* {wN<<ÝY“è’D7¦{VÔ¢›fD“AtƒÑ EtI¤toÒ ~Á é†d!]ú ¤Â ݸJ¨„tI¤:- Ò A=‘.Kb÷|sˆéƒuˆéO ˆt¾ˆHç" :߉Hç" º$¢›‚;]’€è¿mEtC ºTDçÇ¢KE@tªEH7ô‰B¦S·ÅtC;1™nèÅK¦K5ƒé†H€L7ôD¦KwÓÍš×9”˜.Ý L7Hªbº$Ó¹Í`:-_1o¨KPïMªƒ½楶óVÂÊ?`ž£†óœþ˜—ë Ì[)í²ÞÎ1VHy«}¸((o¥> ”å­2@Õ ¼·^@ÞJÔ„Œ— ÆK Œçì©‹ñ”…Œç`]`<'á$ã9Ó$Ï6·d¼UM I0žS%’ñÊ…Œ—Ê€ñ<œ`¼ô(Áx©€<§Ÿ$ä9² )o] j`ž3@óV¨óÒ¬æ9q+0/7'0o-ç8dÌKS˜çŽóÔqRÞ*Ç^ ¼|QPž#üò´6yî!Ï#JÈKãy°ÈxÎÜHÆËe‚ñ<Èxkˆ¡[Œçܲd<÷;Ïm᥀ðÒ}@xë•õD-Axk¢Ç§ÏipIx~×ðò½‚ðôÊ"àyðœæ’€ç¬¥¼Ôd^–à­±iPÕ•Ü:ž‡&øÎK—|—+ ¾Û$+•|çõM¾sj^òb7ïÒdÞyyïÒïü´wNùJ¾Ë’{* hÉw àW%ñÎkx— ðλð.Uû`KeÒÝJH|÷°¥j„Awi„Awi„Aw©5 »5±âà t·^ø »õ\6ºó§éÎÜ勯ùY¨€»Õä※ôfÝ- Ôi{ªŠTì©ÈM¸K‹p—ú ¸K£¸ó\Û¥ÖíÒÌÛ劃íœ;šl—¯zîÏJÛ­­yyá‘íVs.Ð6Unßd»\¦q_=n'öU¾ Ávë# ª¼ û*Ý wùVýØc¸îüQB¸Ë7σ¦÷€»´¦&ÜyÜeÁ‚;ñîü­¸[%â›=ànÕôZp—šp—fxÀ].ÁÑ#ªØI9ÎîšRHîÒd ¸Kãpç"ÀÒ5ƒíÒhÛ¥Çl—ÞŽÁv¹Ä…ï½#þ¾Ø.µ:Ø.=Ã`»´¸‚íš’nƒíl—^·Áv©Áv©Ž`»Ôµ`;&-¶[/“øµÐ.—_h—žG ]nÄB»ÔÕ@»\"Œ“`¡—;Ì–õ]ö;ŠLsË»:Ü>Fs+ÿwf9¹¢åè…—PŽ ¡œTB9øæådeF”£öÒ(Çh€F91ÊrÂ=¢S†å艙PŽßéB9}*åðíd”cþ£=ÆÊYB–#iˆåèd–ãz7ËjÈrúM”ëÇßlj_Äq|ɘãD½â¸“[qmüÍqÜØ r–ä409~³äÐ^Rœl-Iq<â3ÆÑLÂgãJb-'€q‚vaÜMå11Žù;q7"®ãèµgŒcìkcœ`F§É)Œ£!‹1N Ç1ì·9޾Uæ8)QÅqº—8îFŽ+sœÎ=Äq|ÍqÈOgŒóÍq†6bœ4àÄ8­Aa× 1Nßcâ8™ÅˆãdÐ ŽCóŒq㨊5Æq Œq–ãÜ>r‡ÆÇcŽãؘãèq'Žchhs3Zän8ã›äT¯HN½É}uu~‹˜ä¬™#Éñ=l’³(IN'éB9nw"9¾ñMr7Bþšä4\"9õ\$Gû œFB$w#ùˆPŽ{‚QNF.B9·…(ç¶å4„rô#4Êq½˜åT³XN}ËѰÜ,§6 æ¬R#ÌM¥B6Ã\3\F˜Ó’Íùî÷ç„T4—Œ.¹­"Q³hÎ÷~¼­>;Î1h­qŽïx㜑pNT8gëM✕lÄ9=áœk&Î1™˜qÎí!Ïéi‰çl›Iž“¦‹<'Í‹x޳Ÿ8§j…s çªæ9Í[ñœ:%žÓÃÏ1¨³Ž/[†T@ç2:fŒ5Ðq«7Ðé*Þ::~ñ‹çôÄsšoâ9=òœìjÅs.BžÓϹbòœ­@Éseñœž yNÕç´¬‚ç¸U‰çdKNž³^ <§w1yNë‡<ç:ÀsÔç˜#A8gm^‡º<àƒ2çdßLœ³j8§ ‰sRçCœk!Ĺ !NÝÄU)ñq®‡§Aœ;EŠÓƒűɂ8Ý\§jq´Ä5ß âôÉEˆÓsÄiôq¾!ÎÕâôäqLŒmˆsBßF†8 – NíÄq2ÄñElˆ3²â4qqQAœ¾Öqj3!NÏWç&âtÐ ˆÓ( âªôd„8µX§zq®§}6VCœº ÎWâ4µq…$*ˆÃn†cúY3œ+&Ãñ•(†SkÄp–âT‹ NX‡`¤f¸FݾNOJ §#†£/ŠNÇb8_E†£×‹NC!†c¬B3ÜûjV1œ:*ˆÓ3Äi âØu2öQ#³ÏáÔ)!œ]§n át#œÆ˜Ç¸CÎytJÓʱ¤ñågë$Àé.$8_‚Ó]‚àø½+‚óMAp®ç 8î}8m8 Îuà* SV!{Ì…n~ó˜¿|æhjGnëÌ[,n›Ðæf.IÇÜ,³yÌ¥jà1§äDô˜ëŒý)9EϦǜoM¹yÑØB ØçsI9¥A’Ç\’Àc.KŸÌxÌ% <æ’ssH‰ð˜Keà1—$p™óUt™ë6V —¹T.sý‘W]¸Ì%\æ|'ºÌùáÑe.]—9&‰’Ç\*9?qzÌù"8Ì¥‹à0—%qáY æT ýå:£4Ê_ÎÕÐ_.IÚÖ\úË%IøËeAØó§¦À_NQáå/—ÊÀ_.Õ¹>ªîà/ç I9×C‡9u›þrî6æ|+:Ìù"8Ì¥"ð˜KxÌ% <æ’sYÒc±ª5ð˜KEÂc. -Ö3ëà\<æØ9Ì¥‹à0—$p˜óEð—KEà/—î¹yÑú5øË% üå”lLþrzKÉ_.Õ 9—¿œ–ªüå²äù%wîrîÝåÜ<ºËùÖt—Keà.—w¹to¸ËÍéuÜåRÍp—Kí»œk¦»Ü¼*ˆ Þr©¼å\Îr¾Såã¾3¼¥ÃYN©oä,—.‚³œûHg¹t8Ëy¬è,§‡@_¹t|å|}å|súÊiß’¯œë¡³\’À[ÎsÞr+:Ë¥[ÁY΃Cg9_Ô±­ªÚÁm•ã_9m¢ò•óè+ç~ÓWν¤¯\ºªr[ÕUÍÛ*Ê4o«w&·|ÕÅmU÷º¹­RL_9eñ¯œÒÚÈWNiPä+—®z¦5 Â:¸«²øÊùúÊ)C¢|å:sÈW.UsrW•äâ¶ —rùÊ%ÉÍmqcå+×™!@¾r©æÁ}Ueî«”ÐWn^u!ì 7Ö.˜ãÆÊa§¯\ª§qoÅÂU.Õ{rkÕ5·VInn­’tn­¬®r©yƒ;«šç$ŠŒ'_¶§Ùmà*—á*—á*—ËUÎýƒ«\„«\º$\åÔxÊ)sLxÊ¥ò£òÃ7Nq–§œ§1<åÜ+xʹxÊeÁÃV÷ %•`ÎDÎ=xÊ)=å”1(<åR á)çч§\ºixÊ¥KÂS. žso8<å<ºð”K%ÂS. ÂSÎï@xÊyžÏ»,çfý³ä>¿›°ç>ÿxrŸ{ü¥ì>?Ìç¾KJŽcµÏµ5j¹kRÞÖ”òö¨&RM©jrÞÔ”óö°&bM¹kbæVäÌ=ª‡ET˰åía5)oêQ!U”J±&åíaM)ojR!Õ”JiÙ2ojÊy{¼ØYˆ5ý•ì>+2ýý+É}îßJîóÃÌûyrŸ_+öMîó;Õ}WÌ·Ø7¹ÏïÝö»ª¾ d¾É}þÀ«úß·îÏ^ÌÿøÙÚü¼«emþPÓŸNî³¾ îŸçöyâö?ÿ'¥Úù½Ü>oáÿãïïûõxÑ=eèùC¹}îŸåöù—¿˜Û繯„¦ï~S úB¼‚æ ”ûÜó‹çýM=þ»ÙG4žc?÷Ô¾/±.}¯ ¾˜ø%Ûø(ˆÊð~–Ç÷@Å××;äñ=PáÖû â{€æsïwÙ½¾c`Âõ~°´õ‚¥uó‹J%Ê?ø9ÖW Í}Þo’€fUÐÛjmª_P9V³i€õLSŸå€ã›gæ÷\ç8âÛš¾´/a«ÙôU[•£®d{OC÷Ãh¶yUŸOúÜ®Ið‰ñtfd¸¶Õðràˆ1¸cÆõÚȨôð.óão«ã @f|ë÷g~`Ÿ07z3"öûùØLüÌGyæ{Ì3B°œÏžy·¶ÝãŒol×1FF³z\rÅ7¶KÜ=Žîg~·¢áG”X ØÂFkfÒŠv#LÆ3h0œ+2D9ŽÎô^É4N£3%Ä´'|%5>³ÙÔWÒN6¾„àŒí䘒gµžÃúJ®øØæÓ}%7&-jíñ­Í 4%#zjx%#VsT½’ùÆVíûÿmÖLÉ`ZÔSʽ͛W2­k·±)ÓrkO™>¦¹Ée<ÍîÞß/?ì]xw >V{h`镼ŸucoÞÎ<èÔ´úÛR¾<ŒxGÀf¹uæ}'W¢âZZš•ïïzðœ7$ûk»8C0šõ &nн’ëàøâ¢«ó`¢Íd«uëcíÅ ôJÆÁùGPGß^(¯ä¹¶kfã}­<ÈÛäl%Ù ž–÷)2ó¹·´V¦äáÁˆÏ„ÚuœvlÛsWö5ß±Œ58­÷íç8÷)Ԟ ‚ahÏóyçqóm]ã¹Í ë Fê¬AË´C’ÀeÝél7›‡rž'ßèôy¾³1œçõlsè¼ïh†å쀒Q8ÅoJ§8ÏÍI„]G쓞œW)Û;rJb§ô³½êÍ.àæWkì:u­“L¾‹çïÁ÷7:u]×§ ×ݾíëØ2q˜ j}˜+þ•ŒkËç÷Jp"åµqgj¾×±”ût—‹³ïŒS~¥Ýíàc`-­³LÜú>±{jfÝ—¶OV|cÿÄž2%ý³î¾ï ¯*[M­{QyîÝPØbo*GÇ!•çt/ØDµÏtS¹K½ö_ÚÖÞŽ³*?º~Ö}/ê8¬òxö«³¬ø>ù ð¼{¯{óúóYÓÝIeêC€ˆ;ñHˆƒõGSúã¦ùÁqæ£+hÆuªÈqº!r\Ç™;1Žþ ¤¸NƒRœÌDIqsÉ_™âd,IŠ“M)N¶[Ä8wÅ¥_ƒO#7ÌYã~pý}:¨>N‹ˆp³°0n–x°á| n^ÒòÂôYD¸tAk[ñ@¸ô÷@¸ù¼ƒ¶áf‰xT@¸T"n –¶75î—. „Œ7DJ!ÂͿDŽÂMA”‚K‚à\ nþ>ƒ à’ . ":ü ê¸T"Î7Y™ Ä‚'ÀùÏÁoó÷¯YðÛ¼¤™‚ß6I¤t`3Äoº‘ø-— €Û$O´ôpSßâX7DcÁM ^³ ¸\&nÖrãNApé*\º —%ApSrƒˆ‚àr=Ap›dD,9ï½–@¸\".— „Ë­ „2/áòUp¹æ`¸T —%¥mõ‚á6 îŒ áÒm€p¹Ò@¸tQ \®5.Kár5p›$2;ˆë„Ks—®ÂeI œR¯ áÜ`ܲ«<Ñ<_—Ë\çgxApùªûù–é}¯%nJ° q©yÁp©Z0\–ÃeI@\º .Ý ç[âr5qù¢ëÙ« ˆË×ÄÍ5zã»q¹žçfp'P\–Å¥{âcµˆâòUAqƒ¾´ ¸í÷`( ŠË’ ¸|§~°,—ï=.öW!±Š×(.•Y—K”ëóªÅåköÏÎåŠKíÆeÉ…-ÔWÝûÀš‘‰0•éØE-A*ÂtÕʳ’c#í=p\ê8.]ŽKÕþy À¸ôrÆ¥Öã²äêœ%¬ç>?=X·ý~>¯Kp\jÞsò…‰ŒsP\ 犈KEt% žÏÃeÉun— íJh?Ew@p©Èhû«ü–ïò ¶ÜuÜ{ãoƒ.Ü·M2öɱè-8ÛÞzÀ››vKM»¥"½}ZtKß*@·ônºu[úYŽ­íä6·žÜ–Š´ú-rj½Á[gßf©-_t×mð m¹ÒrÚüÐ m©ŽçaÛâ(šÐæ"`6W dË×Ôgy“ÙXËŸÈÐ#å[Xþ'åÛ4óeÚ²eäç-©-¦ž¡í©°H—ò­<`0*ßèÕ.å[ "ƒæ gæR¼ñtNŠ7"¿oÔ©Pñ&=N(Þ¤’‘âº"*Þ¤£¡æ™R¥ycŠDiÞ˜¾Tš7&’æ1u¥y;áõÍ[4j7Ý1ÔnÒoI톳«Ý¤‡£ÚÃ’ÔnÑï¤vƒ¦Žj7 ¨v“Žj7"v¨Ýx µ¢y[ëßCiÝÔ/jÝZZ7ä¯jÝÎþ>ÒºáôÃJ7Ž…”n8K¢Ò 6h¿¡uÓ©›´n:©“ÖMG‰Òºù*jÝtÈ&­›fÔºYU­ãU$­[å[Z7 Kí¦3¶¤vk¸µÕnîmµÛA%[áI'ξ¥vÓ¹°Ôn:”Úíä ÔnVÍQíæ{ûÙbÒ»¡}Ò»©ßÒ»é Pz7©ó¨v“€Z70ÕnîSR»QR @¥Žj·$Á}¡7”ÚMí—Ú͵RíÖvfËÕPíf ÕnUÐb¶ø3€Mí°!„͘IŠñ@lgg ¶qP@lÌ+"bÓØXÂÄÆ"&¶–Á&¶¡#LlrÔ1±™áˆl2FJ†’0E²ùª…lsl`J dãÌ0²1ƒ‘«ÆÈvîf’Zóš;@^sµäµqâÌkÄpó8Èk'B™×¸‚ÍkX±Æ5 qÍ.âµGÆ•¶Ô<›F“ÀväqÙIŽMÇ6KtpTÍö½ ØdI“ì$Í"_>õ^2ê`›æƒˆÍ’!£*ôˆlnϳ+ Ùl¼xȬõ ÙÔ>![2‹¬ó%"_¦ Ùh$;Isí$Eù"6}.€Øô˜Dln ‰ÍdJd³y"‘MW ÙŒcD6~&'bë›–-WCbÓ™Ívš×nê+d³„ȦnÊVÒõÚV’V™Ïý9³qÌ…lšZB6CÍ![I—9÷¯EÙJÚ¢‘̦¯C1›ïMf3@’Ùl•IhÓ'[Iš'’ÚT³l%ù»ÈÉ€æŠUÖUxÓÉVR–¥ÉV’WÛ rĶçcIºl%maI[IõÈVR´i„m† R[2¬kOQ›–³¨Mý¶iZÛ{³–ÄS¶i´„m `[²ž”µäNmÉr“Øfr¢±¤IÉÆ’ nq›^%2–´}"¹MOAÜ&:·iÝÛ´êÄm®—Üæÿ*·éÙÉXÒ°GkISÏq^7ÉZ²lê¶Í~rp­b(Àm®…ܦ³qЦ’)Q›oÓåz€‡+l³¹'M%ÝcM#íel3\¹ûܸ†Ø&#BaçÑo™JÒ€mú Ȧ’4§ì:-[I×<>Æ´•´á棃PRš%ë¦xËr›¬2n.pã×ÎORîÖÂ2Ã\Öø"¬Y^»h„F^cª>ñÚÖâ5挰1‰‘€m¢F(ÁlŒÄ%`ëålŒ>bë'ÿbëÒôØEÄÆl¦"6Y…’Ø:âl q"`c2qâØ:½èl @`rF°¯‡›K؆ôf6&;°É4•ÀÆ„Ib6_f“  -ýÜã¿ÚÓFÜ–Ï÷BèF×I’bU ÜÔl‚›šMpc"bÛÓÜ7†>¸=òÔ¸ ƒÀm¯nýÐnC»Á-Iné*€[*pK÷¸ +ñîs¿à–®¸=‚‚[º àöGÈnù ì–Ê€Ý\Ùͽ"»=†,°ÛàWN ›Ñ-UtË’±ÅÄ0»¥ÝÜq²ÛÐÇÙí8’ÝÜ©`7_CvöW‹HVæ?°ÛøÝÆì6î/»¹d·¡]ì¦Á#º ëõ€nÃ^oæÌI¶º?’›+!¹¹Àm$LSjÖn~L7&É-•¹y¦‘ÜÜØMq›À6~0ÛÒÆ•wXa[–Ä–ê¶Û4äÂ6÷›Ø¦I#lKe€m|ß§D;òc‹Ä¦ÉMþVŽDÞTŒG"ç)Æ#‘kÙØy²1k qÍÎSÀµ$¨…XÐuUØç«=Ù"ýÙøûÚþJG6þ¾•–!ëÖü;@M©gìÈö±ˆ´¤–td³`l?ƒÔ’ µígZt6‚ µ$RK‚ µ,èl6 9ƒÔ’à©l6ç8öŸÍî™Ô’ H- 6 ‚ µ$8ϽY`5åŠ «¥ÁjI¬–£î?Ÿ-Ç Y­û]VË’`µMòlm«eI;7GL±š„X-—¹îmdÁjùw/¿|%c|±Z–«% Xm“ŒOÀjY¬–%Áj›d|úPÎÏ5kYrŸçXË’€µ|UÀZ–¬m’ñi`-Õ\Ë~'ÀÚ&Ùg`-×zÖÏS¬å«®þ™I€µ|U¯Ÿ€Ö6Iÿ<…Eké7hm“Û&Ùë°åõ»Al›¤Ö-—¹êç9È£ÍWѣ͒~}û0äÎ2+ŠO[î§úЙÅTê§½<ŸöÙ²¤Ÿ1²m’ïZ³eÉý]Ó‹Ù¶ßØ\e§!Ÿ¶ºI¦‹€l›äù¼6ó£XB¯6V,¯6 z¹Cp~wÖq}šB¯6=%¹µYÒ¿ëÈ–%ÏwÙ”])y¶©f [.S±³š“ªvV–iŸkNí¬”Ð¹fSþ*A[zp€¶Ôy·©š¡}•w¢sâ:€Ù\‚ÌæÙ¿ã`ÿ6Kèàf Ü’¤ó)ð^—vVJèá†.ØÃÍ fš@¡Ô1@BaHêþmʬ“|ÜÔ<@[ºJ^nl ˜-¡“ªùÙu¬‚[Áës0\iÔ– N!3‚éÚQ¤`‘ÿ•†Þ`ºvÈ/˜n zRÁ-"},¦kG‡^L׎Ù½Át³Äßtm¦·ˆXAt_»æß§â+YL¶ƒÇ€º÷[‡®UAuíà °î-ûɱÄ F`ºv(\J0]+ŽV²˜nŒù³¡MÁt­0ÖÀbº÷çÍ¿/¦[@]·˜î0xg0]+ô-Ó­K \L×fz¾Í](Wº˜.×±˜î½äR@Écþ¬ÐŸÓµ w2™|gÓ­ž ’ÈbºÔð`ºUirt[z²›\U40Þƒ©) éÞ*ŽÍÓ- çDºÔÑ@ºù¶ø‰Ý´Ûìh1A >%¶S®C [ [š@·ÔM [b [Z @·W‚8ŠD·4è`·­æÞÙJÆ•WØsà–Fà¶šr€ÊÊÉ9Rrx’\m›ßÔL q¬oŸ?“ãbé[ÕÊ”Õ"íÁõwe!øwN8ðß*“Á?ü÷¿IøÿÏ=K2¼Suœ/Cü‡÷Ÿý‡ÿâ/Vþ?þïªÜÉþ¯¿ÿÓ[p^·yß gã]þk×ò¿¼wA5?Mâð¿í­iÑ^ºB=ÿ^Mø—Ÿ_Ëý¼[ÿ¥¥ÿøû?•™Ã ­]ƒòÛc²]¬þ7ÿþ’tË}ü÷ÿ§ p/¯ÊkŠvÿÓPü¾Ïÿý%ŬkÖðß§?ÿwŸ¦þZ zQN4}çîJžÛ"RÌ]HþDðST5Â>¹¦ü¹<¨kn¿gÏ•Aòûafþ=®\$?·SÆUç<ƒ¨ù*Hv59JÏL‹eë2$•Ø+Sm…»gJ¿UJqš¥,+­B&¯8Hr&­_¿Î¥Xæ/fàªu)ÙU?~§LWK’2ÍàwÊ–Ug²à±ÕBI®'d¹&JR]ïø…îÚ=¦$ÕYªK’í \¥–uŒû×2pÿÏ3pýdŽ”y"Zþ¶åàúÌ·5“îc›ÿp])¿êÊY¸X—K±®-WWÔ•3lE][.Ô•J¡®=[êr–-T•2q±&•aE9[êIY¶PQÎÅÅš\ŠUm»PWʳ…ºr6.ÖåR¬kËÙÅ5ìL[Q×–Kk_¥P×_ÉÇUÊ)gÿ-!×o'äú#/ïüðþÙ«ú?]¬ß×÷¯,ÖêúÓI¹ÊL¿ün‹ÿigå)+׿üÖGÑ'+×;ðO©ó`(-Çãä‰g8$O’òþ®Uì²’z½™¡¿’…ó릣-Ìh:·+ã\˜qÎÓÔsEÀ« XǸâcã]nEîÈH§WgåN¯d¬ƒ»fÛˆóòsFÔ ”Ïü䙊‚€­'ŽËçù݈6³†½]8Ë3ÃòÄqù9E½+FÐ+a°‹W'æçdSHÎutwÎ¤ç ’uvwNj¾ÖÙÝ)[Ð2³+—)‘{[änï~JÛʧÏöÝ…–”Ë”tÖ«F•³ÌÊøú ê§æó”o@°NîNz½’84Ÿ‡|’ºNîNj{^IœšŸHs<ëàîŒ×ã’œë7^×ïïkÛ]ÒPÔ#ÎÍ/Å­ßÌsÁ0x­ëðcJ‚*_ÁX'wWqÅOì2 b^—Nà½9÷÷käX'w§lÞï“Æñs†Zê:¹»Þ Æ}%³Þwzünëäîzyõˆ‘)qt~2ºL-×:¸;~h¾’ÍcÜ:÷½¬¨8ŽÎ¯Òp˜[ËX'w¹1qt~-EÜ<ëàî*†¦Æéùá8(©o¿g[dþ^+ùÔ¨s?1TqYë ôJxýJֹݩSï÷¢un‡ôÜKr­s»\æ^çv'õdS²ÎíNpÔùž*1ùP$ŽÏO½Hêûfš¿ÛŒ€¿×éù©“ÛÚŽulç•R[œžŸƒt¼}ZÇvç…SkP·~_)«3"jÜú]ÖQ„GHu¾˜î¸9–Æûq=¸ù,ß½uuA'2µõÙà *Æ÷÷X§v â)Yw§bœ¼C¾îÎŽÐ>¥ÎÕ7»ðb‹.œq|>×\h^ɈWÍû ÇUq~~^Œg[ÏÖb¥B×øJæùù©$.ïï/šŠœzÆzZÝç½îÎyâý>ãý<¡k«sZ\„¶ŒëÛƒ§ExØWçä/ü^aWPç(10æsÆÏ¼ÂÚ¸j‹W.^OW[Çvi̯8?÷Kø°ëÜîäÇ÷+‰óó©5Aû®ûˆ>ê_IVƧã+éëƒödŸWçç¹}ÏÚSÏS+ñŠôݾ+Û7¾K?“s_Il¨ómM¹ëÚPOM«w‹ uF‰¡ºÏµ¡ž4_˜Áþƒš¯µ£žr›®wžÏy~}¿c ®Ã;ŽÏ׌C{ƬWqeÞÕ¾vÔs†v‰Zú;êÙ,‰Õ6è6gÃósºc£L‹µh‚ö¶Vs“ÿýû;j*sÅŽª!+‰Íì ýží›®àѧ"§>u¶æ-3To˜ˆœrg¯=lDÎCo›çç'#´ÕF"©1#ŽÏOùä¿’ØS«°Ž¶ºtñ;ÂR$5oÄñyz˜#¬Ešb#ÕÇçgåçGa/’ï=°š‹® £‘SñWjVL¥Ð…Ô'ÌFÎvazÂld>q”˜f#MŠÿœìÊŸT+À³­°'lGÒ*|âôÜÛîÆ#gÓ«ú‰Ãó4O˜¤‹âì¼¥;…ýÈœÔ.ŠÓó9æ1%Ú1-Hæ´Šúý½VrÓÚŽ°!9aò †dVó~üøÛV$M†ïxl©•zv„!ÉY©.{%±¥¾s'ÎîßÍ0¶Ô oþ²ö¯<|óÐ~þÆ7á2:ó°TÞO,§˜yËe½ ¹-3œS:öËW[êŒâ‡s% JNÅ¡lŸÇ_$ï^{*-n¦$öÔÂþV¢Ä;f+÷ƒŸüëÜcI8__ÉÚS›4­„IÉÜ[0 %LJšöµVµ§Îm=¯aUÒ}î•”µ§V} ¿(´öÔ¦WT{¿Aæo*ÈßßkOmŒ~ýJε§6?––%…ô££mQ¯d ñK\ç7ÓH1ÿÈY¶ÈoÚŠÝçv&s ßz¡à¦²%ŒúÕ©×ЯΓZ ÓÀ÷ëžY~ïîÀNô{Ëœ .ì·®"ÅÝaXLƒÈâ¤X˜`¿•fj´TN ]ìW‡ñõA*'†®'û­Zi0²N¸–`¿­¤rÒBûm5Ÿ‘DFqwÁ~¯„ x°ß’°æáúõ.Xì÷þ¾± À~[½Oø§ùõv •“b³‚þ6 R9)Ž)èoI.Â^aûòàØû°ðo«÷Š2©¤rò—HàßV¦GÞÿm’çøöá‰,2–ÿå^ÿ- 6Áà¿\sYÉœ*µ à¿ô\ÀK‚o°Àô€Ûî‹}`ÍHç”î=Âæ^aI€Û½ž‹Ïð†„NI2•1鹿;n’id<¸Õ{öÏ\ |¿Qø².IÅÝ‘ÏÉ=ÜNîùdÀ­^$t²$0ß©!¡S’ÔH$“%Ç÷Ì=Ü$WXݧz®0»O’;’É$IG‹Ï [‰1øÐNúj ̃~"¡“§d0àšnàÏ ¼¬‚×Ío3`n^0àv§KK ˜»pÂý%Kï4.–὞ÆWΕ)0— Ì<(p+S÷;î’ÎiÁy± ,‚|N.rìýÛ¸~qžSß—Ô¥ç`P Ò9I00_ ˜ ”‡­Gc7I;Ù|JÎúy€›äêìÈ唊ôº·ÿF2' ƧR¤rò¨ÿ¥K:R9ùÕh†¯EñþmWµ‡íÇÍÿò|épHeÇ͹÷áípùNø|'I8}§JÂé;µwÀíÅ ¸}' 2:©š¿owr´{Û-þ¶ðzI·÷ï,AN§$ ð,A6Ó,Ÿ‡0ÏÔ’ M“$Á‡BÕ/üÛ~#§iº~/ˆiMS‘S*†âAbÓTn/éVHmš%s·BnS ž} .øKUþ6 ²›&IÕnZP œ& Rœª ¿ôtA[ÍÈrš$Hsš$ýd /0㨟ßLq Ù©[ø·IìTð/=àßvUÓnZ2þåö$;M$;M’ûÜzYì4Ý ÉNÓ5Hvš$áž$»dì ø—ûY‘ìÔÏjâßþ{|zø·Õ‹d§Irßö!Ùi’t­gÐüa$+ÿÂý%.(¶6P¡û€€ŽØEL<€€="H€üEÌÕ\ˆèAïàcG4à£$jÿúÒˆ§G ¯b°º!æÔþJ„JíßaŠ…öïPòTjÿF‘ö/—¿Œ½AùwLÚ@Å¡ü;ÊÅH–PþMICsBùwHFåßA!(ÿf½# }Ù¤üsjÿæ;ꦅúïàYµnµG¥6µ‡Á¨þ;Äü¡þ;ÊWý—ë…ÛŒˆŸê¿iZ7õ_.ú¿, ý_¾wèÿŽ"Åô³ftú¿Ã‡©ÐÿR5.õ_j0Ôi<¡þ;tL@ýß!¥1õ©SÐÿ¥§ýßásGèÿ6IXúNå#€0€ž7Ôôƒðð!84€óÞP=@8ït@+ÀYæØ4€i, ÌeBè9K `¾ þ3éî¡ôüƒ0=ߥiÒRx(Ï-5€S‚ÃthÓ, pޛʼP¦.@8'†*ÀÊN¨k¤— ð° *À9X7%ƒ3÷†ë… 0=p¨7Éøô*À´¡ô{+T€óÍM7T€u©<”œÀC)‰©Ì7  ßZÔN ÔXÐNI!ë…é¾:À4¯¡\.¦¿­DèÓ*ƒ0 (t€éÕà”PO:ÀC ?©¡Ì’P¦C èÍŒjÀ4ÆP¦×Ô€Þ©¨LKjÀ´~¡Ì}}u¨Ó„„0ͨӽ¡<ip¡œWaü Lc 5`ê'Ô€i^@ ˜0Ô€›s‡…Pòm§0½ÿ Ì÷†«¸ŸÔ€iž@xÐYXzÀôô Lëjéý΄0M¨Ó;jÀÔ`¨õ­B-`zRЦõ-`zvЦ'-`êÔ€‡’•‡0'ô€~á@ ˜ú5`zA ˜o}ikÅ…0ô€³f¨^¡ô€B˜æô€~ß„ЕPè™F=àl¹+«¥ÐCE= ¿g©<¤s¡ÐÃI= Ç†zÀC™Ê©ô£ = ÷ *ó5Ͻ/U*S ôk‚ŠÀCÉŒ©ôD¢"ЋŒŠÀÔ(½oRèWx(ÓhAè½—Š@¿®©ô÷?©PΫÈpp/פ¥"0õ ŠÀÙ¾^+1¨Áƒwyºæ¼ö¯*ýJ§&ÐK“š@áPx0@á︘þ"[S¶ýTsiûyð$L?‡÷‡é§WM?=Chúé'KÓÏCù¯aù©À2ýô·+M?'þômMÓOÔÑôÓ°øs ŸֲàOê"ÁßÜ„ ÈüU˜@Šý˜nÍð'}½àOÙèÈ~©^²ßC &ûeuà×<¨ìW—ìGŽøUúø ü’Æä'û›/ðóù>Á/©ìNôov‚ŸT—?[œüRc~Vvüf0Ô ð«4üø¹‚ßÜ^vðs¯~RÒ‚üê =ÉïØ­ˆünÕòó‰3É/© A~š""¿Ô_*òKõ€ü<:$?‚€üü\H~IòsH~JI#ò³:“äçÖü<:$?)®~Öü’&ä—šóÔmâü¿7}ö ôÙö„Ðç¶ú<ó }6z èóª#õùMGêó!õ¥zo­CÌbŸÇ…Øç§Mìó!öé3EØç÷,±ÏÇ£}>§#öyÛ"÷¥kÀ}žä>¯rŸ^[Ä>?*bŸØgK rŸõ²ä>=`pŸ®÷i¿÷iâüd”&ðÓ·‹ÀO'2?m&?½¤~zä¿d$ ðÓKà§·¾ÀÃ'îKº ±/Y„ûlÂZü‘Œ‘ ö%Q`Ÿž‚°ÏF­}zùûR-À>MaŸ-.‰}ê7©O«WÔçÁ#õ% ¨O+Ô§7–¨ÏÓ†Ôg£[Qßà õi-ˆúüèH}“O4àãòOÒ[Ó§o>ÅꃜüÞ­ †áägy:ùuŽ I¯&?» ½ªÀ@$½÷½ŽÏv¢^U<¢^UN ¢^U:¢^•ŸQ¯:& P¯*£F ^sHJ ^• 0Q¯:%P¯*VQ¯ÍÏHbWÇ­ëU"ë½_l`¯Êƒ°W•N˜°7¯BÏìU„oé½Û/ gAz3fýêöª±öê `¯Y@Ú³_iïÖgi¯›ÜNDYjÙÌsF›ági¯“ME{·>­I{róíÝI©‹ÁÞc¤½Û*<ÐÞmhïÖIi¯Û­oÑž=­H{·5v ½Kžu¤½[Ç“¤½‹G?¢½[ª,ÒÞ…AÁÞ­³HÂÞÕe س aïlr¶[°ç)@سßaO‰µ{öÆ!ìÑ@zvB"é)¤IOŸÍD½Ä™¿Šz:FêÙ·„¨§d×F=¦kê)µµPïkâùJøj1êÑÑW¨×’WP/Áßóù@#êÙ;¨'0‘’Ï Æ¡=)[xf¢êÙ|“:>}i õth@Ôó·ªPO_czVrõt BÖ3½Šõ ˆTòI¡"ÖÓ‚’’OËYJ>-L²ÞÑlô9xtGµ•|ô ’OŠ²Þ‘\ÿúG1#%ŸïM%Ÿïd%ß½³ž•!IÉײ•çFˆTò]›•g¾t|ª–¨—ôn q´T‰zIG· ¡žŽž…zvC#ê¥2¿ªãK53-ã`õ½¢ˆzÞMˆzVÀwf¥¢¨T|R “ôtš/Ò{˯ÂÔÓY©DzL™cÒ³#4I/©ô"´œâ¤âÓ|$í¥zA{¯„üŠ„¬Ók \Úó€JÅg U|RÁÚó±vОiÏ*4Òž´,´ö|ôUbŸú@ڳ–´ç5kÏi/Å«¨ä»?®~YB%Ÿj—µ§3SYÉÇ( ¢½$¡–Ïõ23U‚öÜâž§:qÏ E¤¦²Ã?Ì=sÅHN¥Ž‡Á§ Ðhðéµi-ß%BdÂVºˆ‚ö¶z˜²•; >µ>hïéæe-m7‘·õmιÙ{>Š}öž¹jù¤y;˜»U½ç£ÐÖòqîÓÞ3u öžÏ³³^R¼õ4­â“š ÆžNþE_Rèjã¥ôœFTè!q«BÐØ3uÆžÎül_Ù}ý–™âWÅÇ—K{®Ü„?ÏðsŒÆžb. öÞ>€• Ê~¤RñiÈBŠy&S¤6©óFìFɘsH+LcÎ!*ýùŠì)+BýßⵊPÿbXs¦Œ°æ\/Hzï!‡iÍÙ•á”Öœ]K’þ|=Ù‰†5gO¡eÎJŠÃŸ¯+>1ýùºâÓŸ¯ë1ÒŸ/KŸ¯Û"þ|SBÃÌðçÛ$Ë@î|IÞ|IÎ|3Üì°>oûÎ|YÎ|NžBg¾M t’©¬’$œùº™Î|›$è(M8óåáÌ—%He5_©›3_–„3_Wº@:óeI8óm’Á>‘™/K™oJºå`R0—íw8óe ’Y%I8óm’þ˧žpæË$³J’pæÛ$ýÛ¾pæK8óu‹„3ßö»K„3_–„3ß&‰:IÎ|YÎ|YÎ|›$è8 œùr¤³J’§î× ™Õ7 Ë&A2«$ g¾M‚…hI8óuÉЙ/K™o“Dzº$ g¾,éçþ;œù6É`(A2+KàÍ—%Hf¥4²ôæË$³J’ðæË’óS"¼ù²ɬ’$¼ù²¤œ'’ ÎJ›/K›/IàÍ·IÆgŒáÍ—ËÔ}´àÍ—K„7_–„;_– ™U’„?ß&éßö…C_– œfjO8ôå2Oÿ´p¹ôåߥ~Kë¥7)|úr™ðéË’ðéÛ$çzËöœ[$³J’^?}ëeÉØ÷ ¸õ¥pëKeÀz©5 mšÊÔ“í“õfùìM€½,9ï_ö½~}Y‚L®Yòi_¿ÙJFûöÙ\SÎÕeàÙ—%廿³o“ŒO–k_þ}~÷W¸öm’ñé\ûR‹áÚ—ËŒãÛ$xMdxµ®}Y‚¯Y²× ×¾Ô¸öå2Èôš%ýÓ>øöeÉ]¿íC¶×,éßö!ßk’å†Î¯ú¼:¿ÔMèüªôPùyh–ƯÚó¿êsShüŠÏ¸¡ñ+rԥƯæžÔøUG…y§¿½©ñ«²nóN÷ ¿ÔGXw¦@á—scªš{°tDš—é2”©=5ØV¹.®gä²Ö‚dKô«×¥ÔH(óS#ýxIr*¢ýÿk’¤´Fç»Ì3«.IR]¥º$Éu­Ôß©¦øë™’\KüNu\Ô=JR=¥š$ÉuíÏ+?Á\×þtòóúWOÙ4¿UßwÌ–³i¦YšÙïñCçajïgQ«¿žß©Ì¼åþ!uͧ†ë·²>}Ò7ýl–µ‘žÍ¯qƒ¶)'yB])1êʉ™X—K±®-ÉSÔ•3E][b&Ô•J¡®=Éêrj&T•R3±&•aE9ÅêI‰™PQNÌÄš\ŠUmIžPWJÌ„ºrb&ÖåR¬kKò¤¯ÄLQ×–¾Éó¥P×_JßÔú2“ÿ·ôM¿—¾él0?}ÿ°üã7¶„­Ô¯¾ÿߥoj/½£õŸLú¦ùYú¦ù«é›Þ'ÚaÖ߃—l¡ž3N´»|nž+Ö9ÔÂsOC¡SfdϽN´9­½ã6L:åmÏh4 ÇE0Ñw ûiI7_t7¿ƒÎ#ÎëÊÅOÑsZ¾NW«œÎëdn¿v»P]öìç'vJ5gI„ûoøÇuMQÚÏiA|Cª½#HƒiÎ9½櫲Ñ*蜉r[Ns®$ç3É&mÏ•D~VL^>çñùÛƒ[©ÎR"cž’‚¼’·’.œ¥Îߢ÷³ÄyÝ}ݪ¥­“‚K=ï¼^Xq+ øY®uRpëì,q^wK­ðJ"Õèô> A×ÝïN4f¬ƒ‚[Y¿ÎùIü–éÌîpN&š-~©ÕcfCå©å¹XqÖJߊ³ÖuLК¯dÜHä¬mtÉŸ5NëîI`!¸ÖA×T|%‹)f^òÕÞ댠§¶Íú®sâsÆï[ß•Êù¬qZ7%Xf}H¶.Ç”³Åi]÷D›w&…ðŒ{눠ÏWN4¸­¾¬[ݸ¨­#‚9–eÎuD0«Á™)f<‰ÞĬ…NÕç;yVR-} a¼’uDЕäälq\וÃüœIÙÚ6Xg×­4ê7$눠+§ÁyÆqß"çÌL1ûpj±œq`7B¯dÞ[Þ7çÇu#ÔKçLÑ4ŸÁÄ;Tz¯…<æ9&ª¸×A÷º˜©ÔÖ 윉Vf^&¤:gnª™yR¾çÌŒµ”«à:ÖùÀ<­ ÔyÅaMßö³Ä…÷âû»Gó˜ ë¼Ú:˜j±8n<¯8ª<(yëx`fx? ‰“ºÞ;‹Üët`Èœú¼â ÎíêëpÀÁ’ßošEôÒ»žu80_íÒáNäßlüŸfLüJÊ::›:ç‹¢íµ´‚t{%ëx`\Ì©÷RÄŸ†ôß8ï8§›÷ªÜ…}(¸×<§­å߇}Ç¢3ÎyÇ9Ý<ë¨å)1‰\KœÓ›çˆg?ÖùÀhô <ç[h•©œ#½®‚áÕ=WßìÃt_C™¶fÏHÎu@0„Ðïtœ%Þ5Î{_ë„`ZâbÆöûŠ…ÊwåÌñƒ¶•ÇtC9ÏeóƒƒÅÑã˜nø]3ïQcjÅE#N醜gÏÙô²=—uslBOq¾w#ÃìNçˆcºþhgi~éš+–2SÔsdWè#u޾¶Ó~2€ë+‰ìïR8Ÿc\ñ¦¡·âdÙµPoVü„»+Õ+Y»iWdØó™zì.ç°ó‰CºyÈ‹§ò„*»{¡>qHוÎí|B•ݽRŸ8¤ëJóJ" ¸†ü‰3º~k=¡ÉîßO(²ß‰ÂõŠì9™*úô¬Zø¼ºŽÐcw…Ù¸ŽÐc§"¡Æž=:P$ÔØs¤¢××Gt]¾¿8žh]^¨×gtó=Æá}3b?e^Ëë¸Wcèv¡Äv§_Iì§úú»ŽPc{ƒx¿™°ŸR—x•PcëMø b?>îWHB‘=oî}MÇ~z–_PKè±ûÅ÷Jb;)xpѹ&]i¯zì®wÆUB=ËÄ,z%ØN©ò¿JÒÍo„‚æ…»ËÑüšÚÿm»¿J(²»2‡^ë¼6oËW Mv×âUëÚN笹Q¦Ž¨7¾ì®Ú®hŸîTC“ÝåÆ{Õ k™Ÿv¯$vÔwý³žÐdç;…&{¶½ª¡Éî7ÓV¾’Î1Æü«¡Éž#ïš«…*{!KŒW›ºlÖ¼¿×–Úå¥}µÐewå:½Z«1ÓézµÐewíï>{*¹¯ªì.ιfÙs õ†&»ËkûeXÌr*½Zh²»vÌ«=5žS¼xÜ1ç0Jœ¡Éö7+Iæz?¯íen2ô­õº~ѲCЗp- ¯_ŠÊ· ¯3,™¯Ó»DÌ×í̗þ?H¿Ã7˜¯%uóÕgî¾ú(€¯>ï+Ÿ|õ´2"ðMoß#ßÑù#ñÊIIâ+J³Fâ+ŠAä³á‘Ï*4"ŸM ˆ|µ5á\ ßš… ¨@¾šð FÞ¤ò½Å>ùš¬Žˆ|M™øˆ|§Lˆ|MþýD¾Ó;ïôƒùœ™Ìwj—ò]ç#A¤}l´® äs^M2ŸÓæ’ùæg1Ëó9{(¡ïR RßE[ Rßeˆõ]7õÒ¤¾KnãA}—¿c@}·^¤¾Ë ÔwÉUŒÔwû‹ Ôw7ä%õÍïí: ê›zúp%õåj‚únÅ õM]>dQßí™ê»/~:úzÕ7* ïV>LBßm ôÝ>Ùôݲì"ôÝÌóLæ»§³ŠóÝró$óy3ó%N æ»nÅÂ>}:‚úzŠún¼‘úºlD}Ú[H}}æEPßÔòûRbŸ,2ûºR×ûºO¤€}]ˆ}]ÙúÄ}Š$"îkúâø%º%øés‡äç]Jä§ï3’ßòp‹zùÍÅ#ùÉ…äׇ8ä×ß)†c ßr…@½ ¿Ï õùå{ùuO’Ÿ_³A~²2!ùõnªùù‰ƒüºâÖˆü{Nä'k9’ß¼Še‚üÒiÉï¤íɯ{Ú’üæY[ø) ƒÁOpÀoP’Ÿr Šü<$?¥`ù)‹«ÈO†OF?~†ýÇBèwè è§vD¿ùL$¢Ÿ€Aèç÷7ÙlBô2¾úUA~üòS졟NA~ƒX ~ú;¸Ïgƒä>¥÷é{MÜ—ø Ü×áNÜ—(”àÇ/bŸçÉ/•ùéìgßàÎ'ð‹s7QŸ"áûäq.ìƒPÔ7…@Ô÷0?³¨O•D}3Jõá°NÈ7·,(O¾£D¾!{!ßÔuù†¾DÈ|>[óé1’ù|¶(èÓüôiøú†Rd úa ¡O¯*AŸ¾5 }sÒñ*@ßÅ-CЧW¡o¦+úúœÒTЧ˜J‚¾‡‡o€¾‡ß‚¾g¨D@ßHxiC%¾úô$ôù˜JÐ7˜XYÐ÷Þ}PÒã-Ót÷çâ[&nEæÓ¹d0ßÊ×Äß«“Ì7˜§Xȧ¯\"Ÿ·!Ÿ$d¾á2ß´w€ ÎQõf"óù„ŒÌ7ß|-3Ÿ¾žÄ|ÓD8`>ùÉ‹ùR$ÿ™lMƾñ;о‚ „Eß…ÿÐó9r0_|N=ß-Ã*èùŠ£RÑ'¨§¢oN;|œQѧÐVTô9Ó³}º—}rH¢ï°Âpiú³"4}]{5}~ÅJÓ§ªút,"UßMcmrßîÜwj÷¡¦O¯@iú¿Róé΋ù.E›"óu†Qͧ‰Cæë¦Tªù|È æë…ZRó%#3®Kèù<Òóñ8ʾk£¾^ÌoÐôYWEMŸé©é³Þ‰ª>+ƒ¥ë㱘•}¾7”}VrPÙg­”}µ4TöùsØw?:n¥²O„¾aÈ‹³É‹vøRöùøšÊ¾KúW*û¬¦²Ï_TöÉ<”Ê>nRö)˜¸/q*•}TÑR××¥¯ö ècþð¤è3âôu9YÑÇ/7éù„(Á|ïZ*ó¥ïU©ú—ÐôyºRÓ×O1*˜Oþ)b>/[júNNÌçc©úê—ùR™PõQMäÓW–4}§ †È§`)VõI]äK_ÜÔõ%!‘OJ/*û.M""ßÃ/lêú.©"¡ë;ù‘®~YÒõâFêú¬dJº¾g'¾É2¨º¾¤£®Ï5“ø|Õ"¾Î8vÒõùÉ‘øüz¢®Ï"I×G\ñIÇ!]Ÿ•çÒõéÐŒÄwÈFƒº¾Tħ­º¾Cl äKŠ<"Ÿ(Äç7‰ïäçˆÏ$¾ùѳŸÎÈ|~â¾éìœðù… à“ïëú¨WÄ{ž$ä=}· ø|ØAàëø¤#ð Ú@“÷ÒÃï%µ2Od¹€oÎŃ|ª×ˆoø\Ä7î”Ä·¼P¡´ â>%ñ ùRøæ+ UÄG«_šÂ¾á—}ßÛG¨_€|‰m@}Ã_¿ >+ÆI}ÃjbŸ•À¾¡×%±Ï¯Bb_úfìÓÛœä7„Ç$¿aUÉ/)ƒüF’üNA(ÉOyÒH~CÓÑä×vmßš¦(à7tbGð{„p~>µ"ø k¦~CÇÛ?/û†â¾’û†U{ä>ÍjqŸ”½ä¾¡ãCrŸD‚û†,pÈ}cÐB@ÜÇÃbß°ÒØ7Œ\Ø×ï®oœÊÀ>Ÿ† ûÞ »ìãW±/qà¢>OPßHÚÁ*ãh}©Ûľ›'¸Ä>[Âû¬¯öy#÷é­ îS€[qŸV÷%*…esò»0öáŒØW°~/5“QoE¥Î´÷ön?¤½ù© Ç ÐÞ»6)Y¸'T’YgÿÁ¬ó«â{qO9š{ÅQщ{r‰1îYë¸W5óˆ{¥3.:q¯úÀ¸g_ÍÀ½&@%îU½äˆ{Mñp‰{UþÈĽ&ç´ÿ‡½7Ùù$G¶üözŠXÞÔ îN‚¶ÒF€Ô3HZ´ú¢ýþ›Ù9ÇÌ#²*3 ½êM"?ÿô‰ÓÇâÞL+BàÞU®¸7›¼w¥ìÞ»ä‰Kä»:ïR¬w"ß­„MD¾Kg€ ¾»PX_½tß­à $¾[ƒ›Äw+"7‰ï–‹*‰ïÉófß-!?ˆïÎÍ1u¾”;@|O‘ã‚øî4§ñÙþ±}¬;o:’øž|NLjïÉM–ß#PŸ…G¥ôÄGÁ]Ä÷ü*ôÉ BÈ7$€ùžÜ‰SéË •¾4%%ò¥¤T”>Öq¥o Þ ô¥52‰/û,•>_ ùòÃùò“úò¨ôå&õui^”úÌÓ’G“E¥ ©OÚ°oéÜLØ—£ŒZŸ‚fˆû²C’ûÌD}©™PèKžô=…ª ô-™ÂúR_¡/U\Rß­³ }K`èÓvIЗR u>Y Iç+¨èKëHB_UB_Cè|Es¯ð¨Ï ¿:Ÿ¥óå±u¾$é|Bê| ›"ê{ïßÔ—Ö< >ó[Ç• ó¥6-OfÃÔùRý—Î'É Ô·N*v ¾4Υηuü&oÊžÔ—€NêËC<§¾¥H¢¾´+ õ¥VIì+­ö-ˆØ'ùJžz¤¾´è&ö¥ÊHìK¼öÉÀ¾œ}ˆ}<œNì{d­_t>L7²ñLÓQØxšíîÜ7ur"ðÓä"òÓS‘üÚÏFžÅð7´¾ìú@¿bÌLôËé†è—+Ñ/ï†è×S¤#úÉ”„è—‚¦ÐOê*Ù/þÄ~:B öK !ûMêD?ªnTû¤íˆû’½`ä)ówq_jOä>mâ’û®ßªÚ§%Kا— Áˆ}Ú!“úä½/êÓ1ORO‚E}ï¼ßñ+PŸNu…}È.ì+†–Ž}ɿľž¶£À¾)‹zŸ&’Ôûhb#îS‚…ä>©¡ä>…A÷‰ˆˆ}r(öé`rŸ¤\R_bj¡>’"°ïföi*ö=—”<`Ÿ¸šÔ—8™Z¯Mèc¬/QŸ||€}yb_ù °o S‰}ZH„}Ú; û¤ŠûF“ûAØ'ƒxa_AC`ßJÌÃYáõÅ> P_¤¦ì ö÷R3UÒ‹$¼"½wm]ogXr’ž|ž9ç‘Ð ì´e’v|‘žbk‹ô⌤7s# қŧ/HïV:.’Þ•¦o ½;}$@z·Bmé=¹ê‚ôî´é=©D€ô º€ô Ô$½'-y@zKƒ—¤÷äÞ¤gö_¾%7€ÞJóB½¥³+i{¹Aè­‡Azvxñuá[E#|m{ª}‡ÊüWÛ+–E ½ôè•Ój€^Ù39èI §n,ÐÛ©^ôÊy;@/iÁyeg Î+Þ!à¼Mklb^9ÙwÌËóbÞNñ˜·Ó¢˜·sÏ Ì+LÀ¼Ð ÌKë$Pž]êù{iÆ@ÊÛ©¯‚òò@+(o§¤ÌË£Iyñ%°óò䔘çfÖeoãÇÀ<ûPÔóÊf—^|ŠŽHÌÛrqº'wQ§¼ÜJHÜ{´ëåÕ›y´$õºgí\_?¾‡ÆB=ë±ízõZz¹0HÝË:½²½ uOF´ôã+ž}Skq ~| *=û J¨{y2Au/ Çz;Å]‚^žDôö/ W¾xÈ{iãMÐK †òÞ“Òä½-‰ò^jÄ=™²HÞË!OÐÛ:Ÿ¢¼§5 —V ”÷–,Î zÒ0©îó yK5¥½œ– y6Êau i/ïMn|dv2^ú™’ñ6×x({9ÉxyNAÆ3›d´ ÆË.BiOÚï¤g'ŒÀ3Ú!ˆà&]ÞÑZDYϬÖÐŒó]šwÓŽó¤Õ&ùNrùNö{â»ì ÔõÒ¸—|—gd仜CÀw'=¿Éw9vÈw²l ¾;¹Eß%‚ïÒ†|wRÐßth%ßPðåÄw9šÀwe9’¶§Ï ¾;yV|'¿nñ]a3žÆ…´½â¶ÆÓŽ”Òž†­o ß@x)”ðÊÝ%žÄÃJ°^Ò}Jé>¿Š„:[ùû€tŸ_EBZâH7üø°úè}K<‰‡y‚ØÚúÔ¦ók“šœéF9¨ ¦ûüÊ™îS'êÔ‡ºoÉáýóœê¼ «Q]}AuŸ‘PggT„,%Auõ©‚ê†!ר,^0ª—ÞÈ@ uõíÔy•Æ’ÍaÊ:·ÿM[l@]ɽ¨û´âPçuzÕîF ¦%:B0áŒ9˜îSÙtÜ. B3]9BÓ ?›XÍýý ²é˜;`µØ«¸ >‘ÁC " ÎK° ¨iÚ¨+Iæu^B.=‘Á#K꼄ASOGÙêüï‡ÑZªN†AuŸ:ȦSê\‘Á£´‹l:¥Î<^Tç%›M/ÁN4¨ÎÛ¹ªÑf-1ª«W ª«W ªó”|ôFOËkÕ}ê ›Ž‰V ¯+2xäQÙƒl:Z‘@u^RÜô>¯ÈßQJM§´r"ƒG©ƒl:Êh²ó:£’×:XT•g`÷ifbQÍ’+<ßKÉýS;\ßÓ;1È®>BÝçÚH¦S~µ#‡²Óíj »Zg#™ŽRD€î>%H§SJæüþd:µ$d•’ûfHâwŸ’Õ~û©å ²’{ï>%‘k¤”Þ}KNGΆwŸL¦“5}ò-¡,Èd:YÙ'K “éä¯2ûäUƒ´|êdöIÖaöÉRrø ü³Oî*ßy š=2û¤„‹Æì“YÂ쓼øîS‡Ù'KÉáý±„é'óêÏõ­Áô“¥dÿ|L@y¾¦›õ9;P–’ýs& ÜЮ:óOª€é'ó7L?™%×óù ³Oª€É'³¹±TÀ4:e†©'Uå4Þ«0ó$«ÚÕ*ƒ‰'³d4ÞïÆþþ=oÞÜ'B˧„‰'³]&žÌ:L<™æ L<™u˜x2ë0ñd–0ñ$­Œ@wŸ’H<™˜I겄‰'‹•æàý±&žÌ’kñþVå»OÉ3~¾?&žÌ&žÌ&žÌ’óÓ•˜xR%O2;’b’²Î_I¿”ø(Æ5 D’xKë£Çw‰PöDé²§„ÈTöît⣲w„šTöPE6œyeoä|L—½´ ƒ²7ÓÊÞUôÀPö.å eï.íBÙK‡Ê^*HPöî<Ä…²·äh*e¦òØË°oöÒñ {ÎɤìñäÂÞ-›% {i8aïÉ÷I§½4£Óž è³—&~ôÙ“Õ¼|öÒHˆºžÁÅ'PË’Ag¨ziš{é¥Uo¥k#U½–&•ÑÄd^JUOÎÜ’õòé°—GöõŠE"u½ô( ‡½Ò¨ëet9FçLy{i}¦èœò¢®'+uyì¥àEa¯8þÁcOó¯„=yƒÑaOö)ÐõRd¦Ã^ú2R×+–£ÐõÒÆ‰º^ÊŽõ2¤'e½”Q(ë¥Å½;QâžÂ€PÜKŒ€¸—–˜°ßÔ¢/qOËVºíq6”¸Wîâž|$îIß¡ùf‘¸Ç—ì7óå@Ý;iîêêÞÉà6rÛ˨0àTL-p–à,÷Ž<%ï)œ% 8e"" Î“Ž†Ð÷Rê¢ g~rè{G©ï}=÷м ïÌç§åÝPáK£Y*| Ý@…ï(ì±$>™ÂHâË@?2áLÑž{’C!ñ=zH|[QO)ñ¥‡"5>ŽÔ$Líøïl“m™ÿËÿä ßnË’ÿO%£Ù›´ûúþÉï²ëÔßý…$L—ùBÏr•¼#mȲˆ—ø/¥¤Að~k™Çû9KS,)M¡¨4¥’ljx¢Ì^Ÿ›%Ù‹²©,ɦþ£2=¿µ÷yo_\<3Ó¸ÌÌ@43Eѳ”˜åT¸”iå— ‘ÔãÊF¿tƒ—BmmËÞó÷_z”õ•ÇcþÕZlʶ ïÿgS,¨Me%6Uk±©n¹›Wiе©¬Ä¦j-55-úÐSšBÁ§)URS¥–šºßÙ:̤Ñ >M©’š*µÔ”Qã.¯Ÿ¦TIM•ZjÊNR®ú®PðiJ•ÔT©õg»¬ f/Õÿ0|¶¯ÿM`tý³F¿ôÂßO`ôªýœÀèšûyœü\íçFtÙŸ‡Õw,ýN£?19ÿý—iö÷¦â¿ÿÞHýezþý¡úk[ÿäCÔÙÉœœ; Òì„Vgì8]/2]¾ ¨ÀhçýûÂÙŠÇæ~kÞýö‹{Þ²œ¾{çfuÞwìX/3ÝïËzÞ!Îô©·µØíÌ©\m§loâíqÌ8ßÕzÛ¾ã i§dw "}—§úêÜ Fb/5÷m={ÜLË¥aË`;tþy_d·*êsíôçÝ C‹0[hC^E;ï¥R~9¹uϺ¥³€¡±uÆ÷}y˜9¯ó4?ê–G!®õ˜ë»½/SP¢ÎpXëž:ãDÉökÎoƒ6lÄæ“Z´«b¹‡ýeXoœþ¾.œ?f ní6 ™ŽcCÖî8ÍóN}6dí4žÜ£>õëYLs²ËÏœ¬À ¬ŠI=þöÕlÄæCYÀr±V'Tö/¯Ã®¼Þ5ÐFl¾d ­8ñºb ´ ƒ6bí–o”l±K³ƒm´é˼âZ& y|pœìqºíGHk*— Y N=ÐIïxªì,ß7»ï3D+fæCö][âÈÏmól8ê%›éåìñeân<¢.¼ïn·½vpáû‰&ŽÙÌCȇì{?apnzĽã–Ã,ÉÜØmÈbeôAï͟ªf¼¯úàúnÑàãÏ^üž8D³ã•ÝËþ4í…¾³¿aÛmZ N W;ÿöy†¯®žÜÞ¿Ü™±ºfŸ=n8»Ö¹bqµùÎïìܱ¶æà8O¬­KkôY±¸Ú{(91X' ¤Ÿ‹«½<Á‰ÅÕNνg½ Ý1XO8 ¾%ÇÆ’÷T×”ß-ëƒÁŠŽ4ÚˆÕÕ2þø÷mÆòj'ð>—½%¾¾škèˆf®X_­ä‰ݱ¾zÞuû;âÃúíùl<,Çê18|umÅòj¯bEÉŽåU¯x´Ëky„Ëk>xYÅܻѻϘ1XMûôÇì#–W›ÿP°1VwàŽw1ÕXõéeõŽYzþ°Ý»/¯¶h]Q²5V¯(y|y-ͬX^]öðóŽ;«+û[Ë«æ‰wcËkÞßû©|¬šN~¢$ŽPr¾–‡|áuÅI•Å`ò±:±QcÆòº|‡iW׉G Êæ?ºo Õ;T¦wŸ«ëŠIÅKbuµ5Ù×Òá{d›Ú¸’±cuÕÆçÝ™Æêêî·Qç`ue÷³ÅêÊykÌ««¥šðMÃûP¾ºÚj½ëå)®ÚE¼ûÈ…áÚb óŠÕõy§ÈèÙ–xÔ샽å[‹«­ñe¬ÓÛxuÐ_Å\X\;‡ƒm‹×ˆo··cmµ½ÈW:X[vTïg¸b¸¾oÂWÛa¹`l¸>ÎQkëãà%#ÖV[@Q2}mµåÒg®q]±¶>¶9D‰¯­¾6FÁµÕV|ç׃µÕæR/X±´jSý–ÄҪ껰ÆÄ:®k«ÙF¸ð4îkë³±æ¼%±¶>&,ú#Øp5ßsŸã‡ÅÔšÎ|Ç÷Œµõ1 `F‰Ï Ý2«Æx½¯X[Ÿ6ãsÞw,­¶³AÏ>÷^¼ç8ö¶Œ«¢dùÒú4¾aIYÿ ‘?™ä‰,ØOAŸÜ|yæzh[©çúJåIó@†Îß%Q`àòí`4h åà ´h-v£À@+AF'` É Ðçó ©`whÊÓ jšGí @÷‚ ª 4uuG+ @[¦GØ>6€@“Œc×<ì €Àc±'âï`@[µgðr0àÑ2 <ïR5ck<>”â7€f¾5ã­AN¼9 ày_B«ž·Àó.fqiðßyÈÀ? ÏÞà!ükæFÍþŸóâÊÇ¦ÐØô‘ÿZìÓ“ÿNìƒýló0Ðh°ß9ê`Á~g‹^~- è×Ä6D¿övèöA? A‚XšL&eÄ5_šìÒ›é¾4å{"øY+æ¶‹,÷ ð;o›hà×8Wü\Ç¥s«/MöT°’ø5íº~Ǧ~j¦6:ËÅÁ}Ó¦¸ÏŒî¼ÄW¦æ½ûGá¾r!p_ãZ îkoWBüÑà¾c÷œÁ}¾[D Ÿà>û¼¼?p_>8¸ïðlÔgyÂ~ÔWz¨ÏJ¢CúL¼âúš}ö†Ã»Ð×Þׯ†Ð׬û}ar“ÅÀK@Ÿ•Ä¡¡/_¡¯qá$ôY'î1ÀH}ó¼¨Ï!ývH}v;¤¾f³p¨Ï®Ž_úš“Ôg{ëö¡¾ì‘¤>3¼ŒÓ;R_ÓA ¨¯ Õ‘ú¬$N"@}Íçñ…úìÚ1ùƒúL–¸0ZÙGI}ÛlQŸ•l0^PŸÙ0&™¯ lrÄ|ùnÈ|ìEækn&T¨Ïž ú(¨¯Y¼‹À3P_v PŸõ‰8ž"õ5:úšékàÀÀ¾|{ä¾|{ä¾f§q)pŸ=7.îËÞFîscÜàGp_K ÷ÙìûÏ-Å}z£â¾Æ£q_32 s²=€Üg651WûÔ!~MlCðk½~Ó?»c &À¯õ¸]P_^ˆÔgŸ*ö°¤>-K¢¾Æm8©Ï®{cR_sËà}ùb}΂>M„¾¼BŸõs2^‹¡ÊÏDèÓÊ èË:„>[v”t.¬) Ðg¿ŠwCèóŒèË@ê+×õ5n²D}fì„Nê³·sÀGƒõŠ’Å¥u°NPŸ­9«+‚úÚ Ùúìë­ ³ >N/‚¾|¥€>Í ‚¾|pBŸ-¤A„¾üV„>M¢>{ð P@_7ú²úrØ‘úr0€úζœêËwLê³o€IêËk‘úrõßôGÃA}6©\à¾r¥›‹+v¤¾£ ½°¯‰~€}õRÀ¾ìÉÀ>»x줅}Ù°ïÜü2 ¾³Z E0ŸmŠiwÌw cöóiËHäË]™ÏªÄÞÌgRî-ï¸Ü%Ž|çíÿ÷¬ÈwnlÿJŠ'BŸƒs¯àgfÀ8(€¶7„Þg‹•“ý$Úv£pßñý}ÕÿÎòPÿÓ–þgÃõTðë>•çAÿ³¤¼ýϪ„fù¯Ý<.¥ügjdûÈæò|ô?søýÏæÿ8 ¥þgÖ‰_ýÏÝD!¶÷¶b× МBZ¥¿ÞÙÛ¨¶Å•”  ;›±R½‹ ž `wrþ‘øçwŸ  ¯XÂX¬º6ºT»*€mßôåØv4$ÀŽÃ éÝUá €þà@Mà9 Ð^EXB4k‡Z(¶­ô¿F«A`×:!° }&FÂÝk•>&)°‹j©ÿÙ¸>úß;UÐ5X~ýÏ^1\õ¡ÿ•:Ä@ŸlT ´m­ c­Jä$ª„ú_vêÖHô7¿?Ñ0°sÓ# Ô¥…z]ÄÀÎs0a`—8Jù¯-nb)ÿ•ÛƒüדAýg ,/‡ò_“ìJù¯QΠú×u 46êu;Aq4Aжìõ/ßAPÇFA{£±5'Úë * úÕ¿æ'?*JÍ%fšJ‚z9ÁÒÁ®Cà¦t&ÔôA´Oƒ_×áý—° xhuì:A vî"$ÿµMÍP hëP`@0ï† h%ZäÀÍ3JàÛp|’  að$H°ë4@$(y^$¨^ Ôü&ô3˜•7ÉJ(h aˆydAýŠ,øví8 êvÈ‚šÈ‚]gdÁžIŒó6 € X~ì b1rà>q*ÔXH¼1æ7v`I‚fõ±¯a¬Â*I½F$È!%ìÚªƒ;ŽF%Ç¥ˆg,9ÉÜp%Ò"9pS®$öTÛÈF8ëGå@ÎQÉGÉÆQ‡(¡Gøà Nê_ãQyr ¾§8ð½:€ h)x ‚60A])A{| ¾¸@ðf¯Ò†-AêJ’àu“éH‚7G‘HÐv A‹$Á÷W1Œ¨ÿ5šV' ÚF?JH‚ÂY‘à-0Hð˜{˪ú_žqÕ³ ‚Ü™'òäSò_²µ@'wÒÿì¡VAC-õ¿&û ®Eý/¯Eý¯q (ܳCþãa£Ô?;›½+ö™cÂÀ¾3$”ûNÊßÀ>»8ž“ê_>å¿l'¸Ïª@ ÷•†ƒûŽK"ð;1HõnÀ}ùn€}¥âŸK$ñˆù”ÿò…‚úÊt@ñÏÞ="Ð@þ{5ÇGþ3oÆë#ÿ™ˆÓ`âÙCŸ¿±èûJßö•~ØW û>%Û5z`ûʰöÙÎSõ¿Ú ô¿ü À¾ãfw¡ÒöÕ’À¾]‰ÀW ‚÷²Ÿ‘÷j+f4Ð ©ù9F•Aóë60ïH¢åÙë‰òÞ'¢ææ”·eÕ!Êë4!æÙÌK'1/çé}’,Ayö±]–Ü—)¯Ü ä¾4¢ È;t‘Øçž7!±Aí“ý+Ï}h îÅZêÇ-•ñŽË°Æs! †Þ—7 ȳM¼q@ÞŽc’<[VV0aðÝRÿ^Š'BoÕª5çÖš¦Ë1¦K™Lçç OaºÞyü!¯>ïÐðàÕÇéz2ÈO¯¾w?G»Tõ.Χ[Ÿ[àýH´³ÀC¿}d½Û‚øAÖ»mýH²³˜8m•W?¤êO:zõ½S‚†GM¨ê½I9Ž~}ò,‚ªwûÄ»êúUÏöW…»÷mXɯOŸA~}÷dÎ,úõÉ*I~}Y‡~}4¥—ªwsÖH¿¾[.zôë£Õtúõ%‡A×{xðSûø–éØgËÀ¤»t”„¬wËiNn}ò‚”[ß»°!ðd½kч‰²ž•tÆyó£ÇK^¥”õ.ZQKÖ»ô&(ë]œø$ë]<’“¬wÝ—òµÄÑã¥ñ@Yï’'e½K”õl–d2Å8z¼Ôß(ëÙ|Ì$‚~ôès-µÄÑãelÏÍW–SâèqJr¢®wý¢ë]g¨ë õRêzâËUóÎ>ÓѺޔòB]o®M‹TèzsË‘ºÞ\´¦£°7åàKao›Ï8zœœ'%ì͇¢0„½ùÐÍ–ÂÞ¤¿…½©>Haoê SØ›r%¦°7éJL]oòèz“.4Òõ¬Ðæ3t=Ûb…ÊY/¿e½©ƒJÊz“çã’õfŒ_jzS~€Ðô²UjzS~ºÐô¦Æ<5½IÇ!izóûNÛhÆh¥¬7í9†¬7'mR(ëMPÙ›vrí@Ù›:C¤²7uäOioJ¼¢´7µÝ¢´7åbFioÒ@ÒÞ¤+1¥½ág+?’õÞuvÒõ/¤½IoPI{Ó ~$ëõ©Ý6¥½éÄÉzï¯bi’²7Ó ÊÞL›J({S†£TöfÚfBÙ›²#¤²7eåFeoBÁ–°7¹rJØ›\S$ì î(ì iLö&}ª)ìÕ‚X_g:+BÙ4Z²7'”öìÁ!ÛAÚïÛ¿+ëõ!U‘ÒÞH×:H{“^é’öÆÃ/CioÐå\ÒÞ¤õ’¤½±Ã¿VÊ^çâ e¯Û2 /¾X^ÃSHÙ´¡²7MP©ìåsBÙ”ò¥ì Gg){CN™Tö|ù1ñ)"BÙë´Í²7èš+e¯k„PÙë|öýÂ%ìy˜¹à%{=ö ì Ú¼KØëÒªhâ9’ÍBØëö ¿¾A {]o‹Â^°©¤®×iq']ï]vÑ÷©ë õ?xvõQêzýã××±FKÖ)âQÖƒA‘¼úÃAÈ«Ï#†YÏâ%ŸŠ|~7Ño¨ëYÜå “N_[ûøÉƳ÷öatëërrUü+–ÔÌOñ\+6œ6ýíóÞÖÉ4¼÷vŠmðÞ+†ŸðÞ£Wš¼÷6ß{ÅÁ/ho-¬‚öV:¥öÖ’™gôót&`¯–íYɬÎ{Ù `Ï¢5¯]e< ˜ FÀ^- Ø«%{fùس†ï»*y¶8°ÒY¯þ$XÏ~ÓGuà[>çÄíë­ÅS)²žåî#p žíÆ`C¤gt« Ò[2&é­ê°çKÑJ7À½•º½e# îwzVòõà[ zÖ0̽r¥½¥è z+Ý ƒó,G™BµÛ2T ‚òì'CµD¿Zâ«PùQ@ž¾¿«„g“¡‘} ²¼È`¼ò#1Ì‚ ¼ÚJžGØ_UÁ«%Ax¥„·ÒÁ„WKœðÖ#M„WKœð–ô^- «íáÕ’ < “Ð <+A~÷¼Úp^- À+þ¿<+¹ ˆàY 幨œ- Ù-Ïê@càÕ’¼r­¼Z€g ï*áÕ‚¼zxµ$Ï~Eá/¯–á-ú ðÊ ðÊÅxö#ˆb¼Z'oY$VHixåuð¬Ìí¼ÚN^-qÂ+Ï«%Nxõ7AxåŽAxëž?ÉxëžÒÖ‚ð¬§U¾Z„WžŠA?uÜÀ+÷À«%xvƒÔõœï<Øö¬2^½R^}ªT];ø. @x¥• ¼OA¬§Ùl^ù– ¼òå@xŸ’XQÕµx¥ ø®^(ø®T ¼+¯x—o t§ßîj³]6B¶[Œ¼E´+AvùÌ ;EÈ!Ø-ØÚëÊUƒêêUƒêÖ­ƒvP]­TWKë–Çø¬XWÚÖY NãuzM¤ºZ%¨._?©®ü(¨N݇PW/PWn/ Î†òAA@]iÖ™®þ$˜®¼m0]þHWª0$nV ¢³›ƒŽ ¢+ ¢«ÍÑ}Jœè²3èÊ èJ•à¹|Sà¹e§À»Zj.·ŒV‚çj»Ásåf‚çÊ3ç¬JX2çJ+๼à\ýMà\y3À¹òisµáÀ¹ÚNàœ}m¨ÉÀ¹Z'x®–Ï•>ž«%ÁsùŠs¥à\¹xà\y*ð\ýÑk©<·Ò1 @W›YXKóöÖÒ,ÙXKóWtåãèJ]>&€N;])˜XI³Ùà¹òPà¹òjÀsµä‰•ôg ÏJz1Ó,ÏÈÈ­oI˜%ü•4O½0¬6› A“͕֖´3wx4Ù”‹bvB‘QÈN·ãú‘´ç8^iÏÑk}"vZ ×81§¶7´‡¦¶7鯈 ¤FmoÞôࢶ7S¸ƒ¸7Óùâže«ùh{×Eoj{×DTJJ{—¢ÕAÚ3uèã¯weØÏPö®¼9({×f<*{`žÅ)­F›–äƒù± ë¥ÂD]ÏÞÀºÞåhÿ#iÏ)i~¼õ.ºŸK×»JºÞ;!Aõ¤®gCt}t½+#xÆÁã5'²Þ•ê t=§^ýõ.íE(ì]¢jBØ»7Ržô {tRØ{˜GºÞC§+ézµoPõì¹ï»ž©©Pß êYÉS¡Ïß(ôÂPõ¬à·ÅÞ«„ª—‚©êY•ñQõ.…E¢ªgÓ\ú ë] ÒDYÏúÉ'lK6CUïºi£@UÏ:éWÕ»)”ªž55U½+D¨zÅ©z—ÛòÿHèó_í*ëådGYïBðAªz¥¨z—â;RÕ›ší¨êMyµQÕ»®§Þ•$=›:Ì’^)¤wePPHz9È(é]Œ§(IïRÈMHz×/q:mÆBÒ»ÓP’Þ•ÊU=ÅŸ‚ªgóW¯–›ïLÉ€;Põ.ù[SÕ»•Qª^ÚHÕ“§4U½‹×õ.9\SÔ»Žˆ¢ÞEJ¢Þ•"D½K¶NõjIˆz¥¢ÞE§ÝõÌRÔ;$;jz@EÓ»éšÞÅ`ÊÒô.÷SÓ»è蛚ޒ.IM.”)êÃH4õ® † QïÊ -õEŠzyu‰z´²HQOúƒT=ú᧪'§Cªzz]õæAì]‰z²I¡¨w1 5½òLÐô.§‘¦÷P7¥¦w1 %½+ƒwBÒ»ºI’Þ•16!éi´JÒ»øW’žºº$½KB%½‹î¸Òôì3œ¸Chz2獵m4½‹qs©é™µÉý Û¢±HMïÊÈ)Ðô&çkiz×/a[¬ï¯¦7V]šž†´4½I7izSONMÏö¸ÏWÔ“HKQoF ¥¨7å¹HQoJP¢¨7a+'MoÒ€šž½ëP)êMy±AÔòv”¨Ç ƒT=ÛyĪÞè7ÄBŠz¡¸$ê¥þOQoh8PÔ4 ‘ª×õÜTõÆÏ–œ/ÕЬ\²µK©zÒà©ê™â3ƒT=ÆÃ’ªÇmFzëÉ3•ªžäªzò%,ÉžÞ}}ûf÷ðT„w/ùDXR“6ýãße-Öù×’=M Yz×ì$*É´J,ÊD'Y’i•¦º5o”JJS(*M©$›òô¨»æRI6Å¢l*Kþ£“=™a”™âÿ&{ZÊüÑoUàÿÚÿgV“_»Á|§ý•t4?w)ë,¶UÿTbS™Ç‰MÕK#H¾½Ï[C\œ¶O¾­ÊÖv‹ðèWÜî^«M÷4¾ò°ú´ñžÎêî_žW¡ñŸ%vJgþDëi̵Fñ‹˜†=}E;®¬M;’xf¤*BËC9ôÇ J¼äöŒ¬ý!+N?j;%YÐôS[Ï­„íñ´CÐí© ®Øè¾Ûš Ykør.ÏžùzÞ‚ƒL0þ›æKS½F¦åÃêx¾{Ÿ÷èá²Çá-9áB“óißìî%Ò¼/wSð¬±5'¬ÏÓ”·Ä»™ç¸âZïBäþ(™ZÞ.0YŸÝäÞ="ë#¿Ç[°‘g †Ô/z=áŽÂ|nEã(Лñ>TóL»Ùâ[™óŠ{¤àÀy>–ç:®ìæPïœêI­ß€ÙiBžfŠñ±¦¿É'~5¢³B:ƒ+nfy6„·°3ŸHíÉ âGvN‡Ä]ñú,›„Ö‡ÆíÓó_ØËj8EŸöN<†¹¤yGöÜV;\~üKy¶¼üÈŽêà߯Ær¬«~“ïýÚ8µž+¶½™Sjš- |¢ÙÇUü`µE#ë.i¼¦YúX½‘kzÞ€¹|ð“÷ùXeþˆiK|¬ê5ì>b¬ÒÆõ-91V©LóŒó±ú Ç“ç°ö±J|óœà>Vyî驯}¬Ïç¶sº¿Š1ÌÈéÇä  ·;áÀÜ“aG ŽUË!¼?q®p{ ÎS#¯¸öˆ¿†*û½ù[úPÕà5/Óªð2ñLØ>T)ILËBàCõâdwÞÿó¡ª)Ò"²øP…š5=SÁ¨sÝ …*“ÚüM¸(9ÓíúÍ-Vy¸|5ψiË Ì·/ ¸åcñG/‹åC•©(.‹zeCUïﲫ /ÄóWqÇÅí nÅëò¥ê²8X>V¹4\³l¢WøBpYµ=ãëʼn@7+‡ËL†}°vµsÅÊÊS· VÖ‡)t®~ÇÊÊÅì2óe­ToÆ%¾,ƒÐ8ñèñ\¶ùõM0·%—½¸~âm¸ûnca½y4zÝ·/¬7woA¬¬·ÈÇÅýTé/÷~~¢BÜÊŠ…õ¦ryÝ;Ö›þV×}ba½˜Êâ²]„ ÕÛ¢ÛDA¬«·¦¾§ÇºzS]¿lˆ>¾¯Ç yÙ$cCõnÀƒË&ÓÛý¶9ýØdêC•¾…—ÏþnŒÀ÷`Óâ>E“¿,Iè´÷ÉÀ»—-|Æ/¤©Ë¶Ð.0ÝáuÙ¾Û4 †¸| b]µOê«è…LT/½pYðÔO¨âÑ‘x,Cwõ?›†‰ˆ8¶ƒ¸åŒ˜FÕ$Àµÿ¸LÛÁ„€[! ˆ€ûknZk÷b`- <œëÈ§ÑЊü§”HÄ¿ VüËëÄ¿#4àßñH¸Q%ð/ÓBþ)ª<ñ/à ÿSOø×”Zøgé'b+Hükœ½…í‚—™ðÏ’qŠ*ükt~þ5N%¿F_ø×(K ÿšö~Ä¿Æ,ÈÄ¿F;,áŸÂœÿC5ÿ«…3ž“ø§Ø­Â¿¶õAø×(’ ÿÚ ·KÑŸB1‹þZr%èO‘zE¤"¶¦Ä¿F¥Wø§@¨Â?äþ)6*ñ¯7xå ÿ,ømf‚ÿ,DmüøWjÿº œøG?3Ñ_gþÑŸL‹þZ"ðOÁ…t§ý)B­è¯ÓmOô§põÂ?Å þ)¸ð¯ÓÞø×tHEüchfÒ_£[¦ð¯3àHà_;Ø)üëÔo…Šý.üS4_á_¾<â_çNPø×a'(úë´2ý)Ò±è¯CµüY•˜t f}7öS´s±ŸBs‹ýÿœì—‚ì—O öëbù„¿Nå_ð×)n þú€#¬à¯ëð„ð×[Uð×5Á“þ¤†Šþ:=¯E2'ý)ijè/"T ýW]èרƒè§gúuFu%úñ«ˆü8R~Џ-ðc÷÷ñë‹ûôiÅ}š+Å}JŒ¸¯Ó™[Ü×™Uܧ(Üâ¾Î,:â>õiq_g¬1qŸnØ×…)ľž€ا7CêSÿ ¾Îø½¢>…¯õiÊõuúz‹ú¤„‹ú4.„}Ù±OÃ_Ø×™CDØ×™F]اÐ÷Â>ëw±s$ö©· ûJ`ŸF±Oó“°/ß'°¯3ùŒ°O«“°O£@Ø—wLìSVaŸÒ:û´Ê ûÌ[Ô§y[à×è±.òkÝ0™OÁËÉ|M|LæS4sB_­ú”·QÐ×h'èkšÌiAIã/db"÷)¹o[Ô–XBÁ}ÆPÒŸR1éG#Eú Ø—ôÇh©üáPFÂßFáo蘘Âßй6…¿Á 6ÇšOáo0¿„¿ÁFþdw&áo¤ªÂßl!ü ¤½ ðÚR÷›´Ûøe ÁoHî$ø æ2ø1Þˆ¸oЊOÜ7$ðûÃn‰û&“ˆû&— qŸ,ÞÄ}“)ŸÄ}#ÅBpßûò]û²Ü7h¿(î "î˧"÷”ôÀ}ƒË”¸O_Ä}ƒg'¿A""÷)oÒNNÜW.îL´%îÌ™%î›ÜøûŒnI}æœÚ©/ß ¨oÄ•ÌgV«"`¬RC¬KæSÐAßÛúIÐ7™»DЧ¨C‚¾)Ë>Rß 7¨oð VÔgÃ2z©o0(¨o0â´¨oèÔ78‹ú†‡Úþ‘Ø7&O!ˆ}ƒÓh`ßìOìL7'ì3cÐ/ö ­û'9RŸÌõ I¾Á€Q¾ÁÐc¾AGqŸ=$JÀ}ùf~ Œ)ððJ÷åSûlS ÷0Ðô ÎúÒúlýJÐG]IÐ7¨ú™}ƒ–Û‚¾|3„¾ÁŒ‚¾Á˜„‚¾1‘6IÐ'Ë^AŸ>±oøaà‚}C{`Ÿºž°ï—ÔgWŽí0±O/\ÜWZ÷Y+í~åf@~êÁ"?õ‘Ÿ¾¥ÈO½Fä7¯QägíìùéŠüFò"É3”ÈoL$P#ú”ó€~C[  ß …²_¶kìW*€ý!™è7´i"ú ¦]ú 8ˆü†À•ä7h-ò+uH~Œ<$òËû#ùE´paßM›ØÇ•¾ÁÆÂ¾A$õiÎõ Ñ9¨o0]¬¨oà¤PÐ78· úFª€¾AKuAßHTô †³ôŽœI¢¾AO!Q_ß°Ðõ £úÌ®.$A@ßYúÌ7†¡oðèJÐÇൢ¾|Pß #‰¨¯êU¿Î–¿Î…Zà×¹³ù º„ˆüʯ@~=9ä×¹|‹üºÔ\’_“üòI~IÎD~ùÚI~=E6Ÿâ±‰ü̳:> ȯ_—$¿Îä¥A~®ž"¿ÎÉ‘à×i-ðëŒ=%òë´úùuê"¿Nwo‘_§ÑŽÈ¯ÓËKègNÁ~¥ìלyŠýºl&È~‰ÇÄ~›²QGè—§ƒ@¿ÒêáQª´¼Æ£Týèð(½Oigÿ óyQþ)ï9|xo1¥Lòžv ä½F_KŸðúØzê¼FÈÇs_V!ñélMħoŸNl|];@_§"¯ë† |][V_îb|ò· âëtñõ¤Q_g:9_çÁ…ˆ¯ÓAÄ×iä/ä{—C‘¯3á¯SÞ"ñufÎñu ‰øºÔ_ù’øúæ‹Ä×VúºLI|=U² >-Ÿ">ÍÔ"¾¼?_gPL_ߨ‰øJË ¾RÄ×¥_ù2¥>‰vD>›åžÔWJ€|Ù‚SéÓË!òufò”Ò'"%óÑ#LBŸH}]Æ«Rú²¨¯3ubJ}ù+P_Š“ú:ó»¦Ô—LJ©‹Vj})ÀQëc0MQ_gZ]Q_¾uR_ß?S_—}7¨¯‡**¡»‰|úúôÔN|å¢ú¶ÄW~B¡olH|]æ£ú$VKè£}O*}º‘¯ËžYJ®…|¥J}ÒÎ¥õi¨JëSÖ§ÏD­16Së;¢*h}R"¥õ-˜â¥Ö§³a6$õ©ÏHêÓá–¤>õ4I}Re%õA¢£ÎÇyN2Ÿo$óåu@|Úb¥ÒG;•>™xQé;²Î¤Ò÷H „Ò§£¤>‰ù8µ>ê¸)öåÝPíË_ùzÑöÆ)­ ¥öñl0Õ>é$Rû¨WHì“Aœ¯ýlä©ðµ)öéA©öqšKµO¯D>œ†âã^(Ô>¦Ú'‰AjÃò¤Ú'#@©}<:LµOvwRûÎU̧±R˜O¿¢Ú—%W.ª!u$r_Oµ¬qM%‹ûpÇľNß{‰}º=aŸ¬êûø&„}'mûhùKìKöåʼn}´ƒOì“ §°/MJ‰}âaÃ(%ö=„a_’±¡–û$@ ûè8"ìûÅ̳Ó ØGçˆÄ¾›§ â¾l„ÜG‰&¹«“û®‡6‘ä>T‰ûèõ•Ü'kuqv ÷ñlBÜ'‹vqŸÌÕÅ}4™Ið“é>E?fIòÓ!ɯë“ü½8ÉO§"?îÏÒY™¿ú”L¤=yõQ÷PRhoË´W¬æH{œb{ƒ¢©`oòu ö&wdd=‹¹k´üúäÚBس˜ Õª³ß©åöîô¥ìÝ’£{í{Ì$Ö“…¼únº²‘õÒ&¼úOâ¼Ý7Yœ·-qHü œ·xŽBÌÓÇæÙýjй=Ãç‚yµÄ1oÛ\À¼-퇘·åeBÌÛt]æíŸ}ù¶çlÿQ(o#\¨ oKâ"äm¹×ò6-›y[9¤Â‚<­V‚¼…аb¼-“@2ÞæÂ#ÆÛ2Þ%ã-Šñ6ef1Þžðøãí8Voé$€Œ·ôQŒ—=‚Œ·™IŒ·Ó\3oq!ÆÛ\ÝÉxy„¼-É·„¼­­&!oÓõ^·™·K”·¸íåmÏ ü£PÞ–âFÊ[<Âåmå­)0åå×"å-&ÌåÙê%(/1o1X$1o!d°(oq&Ê[mHy+Ýû@y+E9PÞÒp!åÙƒŒ”·à¥,ÈK_bBÞâá” ÏÖòÂ,Ïò´t˜pÆšid~Æ[ljx‘=çGA<ënaÞÄ£K·Oë{žBˆðÒe™„·t*AÂÓ~Z„·4ùð99’ð–¼HIx«IÇá=ÜJŠð®|"< ø=B®|:!áÝ:K#á)‚/½ªAxwÊŠ ¼'Nƒðî|NÞ¥aG»å)N»¹ôf )t€’{‰`çÖ–Ÿx-<‘·žŽÔé­§íõtL_=eù%Õ-@ê–æ?ÕŶ8 (¨ÎçÛ§R• T °Ny•Hu«øóÕeN'R]­ãT·¨~“ê|Å(›åï`ºõuÕûü¹"“SÄ“éòVt1Ïò|²´KprÒGH •|Ô»åçEÑL@ò0‘锇‰H—y˜ˆt™R‰L·&¬'ÓY Lg%ó.L·R‘ ¤ó OéíHt™„‰D— Ht+@tKº€nùÙneºÅ ›D:+@È– ºú› ºò›ºò›ºõ0õ4‰nñ`Zá•߉@÷)Ù¿•¼R:%–Ï•¿ç, Ó†/^à\- œS¾'Ò\æ{"Í}Jvä‘Ê’ ¹Ì÷DšË\S¤¹OÉŠLRY4— ŸHsµ$p.³9‘ç2oxn)T p®8ÍÕ6‚æ2Ó\­4—ÙŸHsµ$h®4š+ŽÊ ¹O‰¯<µ$h.S;‘æjIÐܧÄWžZ4—¹Hsµ$hîSr˜F >ÃAsõ±‚æJ• ¹LÿD «%tµ$€®–Ð)7 y®Ε›Î)ƒi®læ§AbnfÌÕ’€¹ò£€¹LâD˜S°\­,÷) 3˜,–Ël)d¹|D²œÞQ.?Y.‘åj€¹OI¬¡åWsÊC–+w–+?Ëe2(²\- –«%ÎråÁs™t0W0WK^šË˜«w0WªÌ)s Y®ü,WK‚åjI°\¦Ü!Ëe~²\­,—](W”ËÉ•‚¹üFÁq¥B`\¹ŠS\þ ˆË_€ájÁa†7Á•‚¸RüV>(Òf•À·RôVúè-ÓK‘Þj ·ò<oùFÀn¥+»•fÁnµÄÙ­\ð–ùqoµNÀ[v'°[m7Ø­t°[- v«¿ x«ð–oìVš»Õ’€·¼?°[­2°€fIÀ[- xË7ì–Y€oå~ïï‚Ýʺ•þt+¿ r+W¹e+·RÜVîÜV.n+÷ nËlNä¶òñÁmåRmµáÀ¶ú£‹§~³±vªÀ¡Í.©_ måæmå5ÚÊu/•I˜þB†%A-üãc›)¶’m&—C‰uôNÓL¦õMW<ìOW¼ÉØ é‹ÇãY9ãÉ—DÎxTÓOWÊu“ÆÏ’ë¦BFP®› µ$¹nNH…PëÇ^rÝd QºâÑDjÝûê ò¸Z7SZ¤/eéôÅS¤ªu6û! Ôº™”Pë¦\s¨Ö]R)Ø]ŠL@ÁN1ÿ%Ø]!Öå¥X—SĺlZz8¤º™A4¡ÖåË£Z§D±.V7•”ZÝ–Ë O'ƒÔê¦f&juÊç"±n*Ê0Å:L;Têæ£à,Pêrº¥T7µ.SªSöJuù¯¤ÔñÍQ¨S¿•P7e/E¡nÒ\BݤÁ½„:ö) uJp"¡n*’•º)Ã0*uRê”BPJÝd¦)uÖL6¡Ôé;I©› T@¥N=JF¨¤:MV”êf†÷|r) ½Çµº© ¦Ôê&=`(ÕÍt!„V7|[ZÝÔÉ9µº¬C­N ¥ÕM¦÷‘V7e J­n*2+µºIUiuùö¨ÕÍ+²´º© ¦ÔêòÝ@«SŸ T§™žRݼR]6B©Î’†2¥n>ÒÁ ÔMZ9I©ãR•^xŠdB¡nrÛ!¡nJ[¤P7©ABݼ.B]¾ uS!)ÔY"ÈYŽki—f,¦zêæø)ìæ”•ºÉhaRê¦ló¨ÔåÝP©Ó.SJÝ”'.•:ëÖÐ ¡ÔMz¤Kª¿¸áM¹µQª› s/©nÊõ’ZÝT¨KHuSnÀ”ê&m›¤ÕÙæùu³4ZÝTTZŠuSž¡.Öiñ—X§4§ë¦ô|Šu–‚ñþ˜cÚgx>nxSÞ°ë&]ª$Ö É€ë¦L)ÖMùÙR¬›’»)ÖM9;S¬ST‰uSÑœ(ÖM †X7å•J±ÎSœV±ndøˆu¡ã+Ö)ƃĺI™UÖ˜TKJ¥ÛÖ‹OÇÓ®’µƒ%55Ò?þ]Öb-¥Òm–v½æQI&/bQ¦É’L^ôxîßšI%Ù‹²©,)MYNÓ«fgRIi E¥)•üG§Tº=—Øý{)•~Iˆ“.¥ŠùþBJ¥_»Ámаñ•¤/?w)ë,—klµÛÊlIl«¦Kb[Y‹mÕZl+Ó%±­š/‰me-¶Uk©-åKR[%a’ÚR-µUj©-%LR[%c’ÚR-µUj©-eLR[%e’ÚR-µUj©-¥LR[%g’ÚR-µõ/dV²´s&êý~f¥ñÏ2+ýÒ?³Ò?ªösf¥?hîçáòsµŸ3+ýÑe]?çÁù9³ÒŸ™£ÿþËlû{3òßwÀþòÈñ-ØáûH"¾-½Û¬/xGtP÷cG2qW03KvŒÑ;B¬Þq¿»+_„¾Ø=õcŸwfr¿Gž¼%;üo„a}‡‰û•»³Àý>B/D:¿bÍr{çÞ1@q´rŸ÷&"Ø N7n câC”zŸÝbŒòØé-Ù ü›1öòÞa;Ë­=-,˜ó2ÅçƒÝÌhyaÛ÷ðxÔ~ Ó ï+†é@è¢Ç¦f¦” ÃâÔ£ç±ðÀ>LyÌK„Ó÷|*ûð ù±K¬ÒóŸPP% Ì¿¯øŒ>öjc”bgÿØ«QŠÎùXH•ƒ:ñæGëÔvûÑ¢_áfö‰aÊãÍǽýW´ìÞóaÊû³hS>L9š dçÔÇÌï¼üÄ8U¯° o>N&ç± o>Néžö–ì§œžá/2?M컾œ±|)íLšýl Sv‹Z:j¬¥Ç¢K>Oí¢vÄáUíø¹È%¾=vvâk)ƒâT9Ç>&=õåL;±C>0VTNÃÏ ×^>öÕ¸¢by,}û©~sRõ±J9ù±´ô>Vi7ÿ\k*Aöe¬ñÓX½î\S£áKj‡hóXËö©bRöø´»ÎOC‡^'ÞÕe'v»¬ÕÏ݆âRÅ`¸[®¨¨Ó±¤8 ?–ŸËxÆ=–ÇÇ*—–·$–Tn7óÅõÁ:öå¹o,©Ì¿þX¢ ƒ_Å3ÜÖT:T?÷š:°¹{î5u øÏc^¾ uâ[º(¬<Š~72XTéø˜#€Vš3<–RÌGk)ÁªÚcSûXî/¬Ü»=Ï‹j£ãÆã™Ó~dðõÇr½Eôp8G<–îÑS@Š|<¡½Qz'<æ0þáªó<«*=O ¯ðXPVúJ§ÏÇÓnz¬uËzK°®Ò5ëeä;ß°¶x,í«Öƾn>¹±ñåB°.¬«<}ÜÁvF‰ë‘=ûheÄÇ ÕŸ«$«xÌÔ¾p.—a¾@œž ÏŠðæÏæTfÃµÑ þ1'ÂÓKPôÇ\û<€8R‰½›ÒXYæý1+šá˜€ãÇÜëVÿ”\7býcOüì;VÖFN4œþþlŠ%‘_SýB~žœäg3*YÐW«uuÕ“ül_ÛG%¿4ù'ùÉ•€à·¤ˆÜ·ƾͤ¤¾ÝéZ@êÛÚ´õ… j\7¨oËŽÔ·åG@ìÛ…+ªöm—¤½Øw,À[‹’À¾í)Yƒ´ûÃö“úN£í©ÏTñðÐwºnÐç;ËØ7úŽëÍQ' ï\Âq@ß±¸Å»rßñd¥Š~GhÜw¬#ÅgúZB¿cZòªèÊzü$ØïÄqÃd¿“/ìçÇ…ÁãÇ€Qðwö„½+áÏJâ„—ðw6V²ß‘cد5Èõd¿#!±_k„+ Ÿ\Qôkôú"úŸfÀÀ~‚ØïXÔ ørd¿†Ô#D¿F=Mè§ØùB¿F‹:±Ÿ¥ÝdûÙ }N´öktLûåí‘ýµN±_Ó#ü5Š”‚?§ï6¤¿6SBô×hK&úk Ú*úk\×IMxMúk”I-9ô§ÍŸð¯qO!üSÆñŸòõE r… ³e kºC ›xhUƇ•›@XJ@€M° l 3-lnŸùƒ¨ BÀ– lL2 T^ !`£/¥°%8ítm𛋨W#lazV°1˜Š°%€‚Ìk„€fì6á°ñP@ Øû•h64÷ÕKÈ€Še*lB,2`{p6)lÚ¨“•D ˜o ÈüBÀÆ#!`ÞP–µbÀö`6ž¡‰K;`À|,2`¾Q0`¹Ô“ç©7˜/ÎSµQ"6Úƒ ›ð˜_ŠØt0@l4X!fÎCBàq™hØã¤Àì9¤À– T~@Q`ctbQ`£uŒ(°1ܯ0°]8ò6!ñŒžŽ˜JÂÀ&Ü$楉š„¥0°ÑšZȬ3¢À65RXJ€åvÀM K,uÀ çÍÂÀÆÃWa`£¡‰0°%ÑíJˆ “DÊ^C lÓ )°1ä·(°ÑðT¨yŸhÙkÂÉOX.µ¹ºâN$ãÿ †H—ô7`g+ü›ŒüEéo<È)ü4I'ÿM†‰ÿì3…Dþ $-þ›< •öWnü7xf%þ“5¢ø/Ÿ›ü7xÞ$þ› N&þô}ÿ FcÿMFÿ îüÄy‡à?hÿ)‹ùo0²øOV«â¿ÁÐÌâ?YGŠÿ&“ΈÿSŠÿ&³sŠÿ&Wtñß`¢ñßd(ñŸÌs€ã倳Q ÿMnyÅÊzEþ›M"!øoêüßùoÒéKü§. þ£_›ð¯TþM¦:þÍT÷€2ëþɆVø7Sþ©—ÿäœ'ü›ŒÈ$ü›Lí"þ›Á!„?yhþò'„?pÂßÔvð7yÔöÓD"ö³‚Îö³‰-¶Ãd? ±ŸÙ Cìë2‰¿ ú)ÉœØ%B?uE¡Ÿžˆä§ ü¦„‚ŸL–~SðEð›\ ~s`!øMIr¿|j‚Ÿ½™8È&øM&øMít ~î¿A—©ƒaµ¥þ îH~SúÁ/ïàg%±¡$øÉP]à7zTà—ÏEð“ý¶Ào"S’¸/ßàŒ.NىܗÉÜ'yq_vrß䑟¸Yü„}3U:pߠ馸oðLKÜ7¥ ‘û&OUÅ}ƒ’ ±o2[³¸OyÅ}öíÆGþ´‚÷)ë%¹Ok¼ÀO)" ~ƒiG~Ú–ü”ÔRà7˜Bòßà‘©Ào0b¶ÀoÐ+Qà7˜NVà7èÆ'ò V$ò:B ù žJþSŽ8é#(”è§-Ñoh.$ú)7Ño脈â߀yÈoèà„ÚßøSûË©ý á”þJA,¨Jƒ*寴éObIC)”þ”´MÒ³ÞIùRTþ†È~Ê”&öSÆPþ,X|#*q&…~Jê"ôZQ©ü §Tþ†¦#*Ê!&å¯3H°”¿Nß¾4eç„ùÉ–D|s{d‚|Ì"âŒrFâ;.«CùæøÙÔ“0+KÏJ¡¯#kuZzÚ:JhéÉÓß´ô”m”,=uË4õÔÎR¦žÌKFêëˆõ™ÐGÏAÓħ¥'mðˆ|Õô“Æ)´¸#ò)»/ÆÈ|µd+×ÌCièI'ê4ô¤~œ†žt"M[Oæ7JcO¦*’±'b˜¦¹'mÃÚ“1ÈÒÚ“ÞÓÜ“É;ÒÜóÈNÌ7¤æÊÞÓ–ƒ¯½'ãh¦½'s×¥½§˜Eöž2¥%ó íÜeïIË^!ßÏ’_þFÈÇÈŸií¹hY*sÏd30- ’ù˜5Ì——&ò¥¶Häã<#äÝdîÉÛiîɬ*B¾Á.,âS/ñ1¿ˆop–ćlf |Â~ ~T„ÒÜ“Gô |´ó ð )›>½>Ÿ>/Ÿ‰¼§S ™{2]KÚ{(cÉ{zJòÞà†E¼7¸•KÞÓÛ"ïéÝ÷`æ kOZg¤¹'ÏH{JV)ØIš{ùb{ƒ6ð{ƒ–‚½;Iž’åõFÆõ†öÉD½A&êéõô„z¥ žr¦µ'–ÒÚSû&¢Þsõ†cI{ùH{ü$‚½ÜÆö†è°g ZïJ{Vp>J_¹2h/[ì)¨`Ï:kØøöʽö> =™Ì%=…4Ľl‡¼7±|C¾&;MZ{2t®€oðtŽÀ§©[ÀWJø”\5Í=™@À7šÔ@_¾R_Gt€¾&5JŸLz¤ôÙpðFLð^öu™{>›äÞ³§‚ôÞSÌ!ñ^¾@™{2®mÚ{rñð)ÿoßh¿Ø{òü;í=êYÀW~5rM Ž”½'Ã-§½'cÿ¦½'cë¤Á§,_eðɤ‡iñ)eGŸLV˜ŸŒ“Ÿ²V“Å'¶iðÉ3¾4ødZ|þB|}ËvŸLM—ŸºÐ.ñndï)khÙ{jäÉÞs÷ß>¼'Ç‹4÷\i sOFñIsÏë¢&Í=î!Í=u;2÷ÝÑØ“¡iÅ{2§­ç-«Rà^§÷¸l=¥2ËÖ“n6iëÉ$_ië) “­§\dëIl”©' zÒÔóúÐ^šSËÐS2ôd(ü4ô¤qQzÒHI¸×˜•L¸×… ¥>Þ ÷Òp7 =™è; =uD ÞÃvD¸gF§!U÷Ò–¸×©' ÷º¦Báž· =m6 ؤ¡'O-'Ã’/¾\!<;ôó} O±FSÓ»e$ ²¬KQ'úÿHÔ£Ñsò4(ñľƒ]IòüÈw̉—|g®›på&È—9Q‹/ÍÖHx“n"ž°@¾|ÔÀDxL^\ù°ö¥+{R^»è(W¾EVûÇ®|k“€ÇóâÍGÞ à1÷I^ªvŽx¢ !Üñ´!âÉÀP}t%IÄão"žöóB¼9h IÄ„_!3‰¥KŸÌ …x4íH³NÉ,réãqNºôI¨äIðäéZôéÓcɧO7HŸ>Î$éÓgÆÊñ#úô¥©'úx¦›”"!O\>}fòé“R*Ÿ>šó§S_’ úÒØ’^}iJ¯>ž\%æñØ<½úôôêÓ»W_ pºôéåÉ¥OƘòéÓ—ä©ÿ òäÇ*¯¾A<—WŸîE^}ÒíåÕ§/%¯>{I¯>ù³ ôÔkzÁ’n}©:Ò­O'HtëKð£[_Šdî×ÇG¹õ1èMºõI·[IE^}òb‘WŸ%yõ „\L¯¾TùèÕ7¹_’Wf¨ä¼dAyõQþWŸÎoåÕÇeUN}ڤȩoBN}Ú;ЩOŠœúH^})¾Ñ«b"]úô„ré£=›<ú´³G_Þ,=úô#2ž~$ÆÓ7‘GŸš‘G-™Ó£n:ôÑŒHˆ'Õ@}éô‡>Ú.¤GŸ:=úøºExHåϧ—+>™™ÉŸOömòçÖÈŸ(ÓŸO6µrèÓ¨C©_€'9Lþ|âèÎ7°'Hw>£ˆïÔCÄw©åÏdžœ Vš|'C?ñ¤ùó1STr2æ^ržŸýù” 3-9y ˜–œÉ’´äd"ç´äd¨ƒ´äÔ^W–œHÉœ–œ’›dÉ™j-9u˲äÜr³ƒ%ç‘ÏM9y6,SÎÔÝhÊ©–)§,ÅeÊ©¯IÀkÏ׎Sœì8y†žvœ¿dÇ©Órއ 9eÛ+CÎGîrÀ»4 'ᥩ}s†iÌÉ~.[N:gþ#SÎôHSNÍö<¹Ì’ïšl&Èw9‚xr_à5 Y4å<´㥩,¯i0ñšOƳB<ÅÈ—O>•@¼bÄ Ä;çÐ*Ü­9•GÖœr‚"âCÿ62ÞQrYsªÓ˜Sr—¬9¥»Ò˜SG´ådæMÙrÊ+ª$XJéÎdj”ÿ–¯ž’ÛÈWO ]õÜp,XŠ®zTè©÷Tª[nÂ%Au ÁMÉtË#ÉV?½µä°¦[«èu™gˆ<·œÕŠ^·<iuÒS¶"â\€æÖ’ï"hîSâ«OùQМ¬¸Ð\- šû”ìH•%As™^‰4WK‚æ>%¾ü¬ôÀÎÕǹõ‹“Þ§dþ œ[ò„ ÎÕ’À¹OÉbÊ(–ÎÕ’À¹òY€sV>oÀ¹Z8Wºp®Ö œ«%s¥8WKç>%¾üÔ’À¹Zâ8g¸†¬%6ëÔ‚À¹Z8WKç>%'쩳$x®–Ï•ðܧÄW Z›ÃõŠŽHW«ÒÕ’@ºLIF¤+%@ºZHWKé>%›#ÃHWëÒÕ’@ºOÉŽ›%tµ$˜®–Ó}Jöo߇¦Ëgºúg@ݧdqIJ$ ®–ÕÕ’ ºOÉŠ›%Auµ$¨®–Õ}JG,Kër'Öe· Öe/ וv”³”ØåˆØÕfìêìjA€]ýQ°]- ¶«%ëâˆe;wŸ’ÃË’ »Rº³>yíj°YëÝÕ’ ;-O¤»Zåê°*Ù°,¹Ÿß¾Ö×,Yý3`‰wµÊ~¾–|W~¾+uÀw¹Dïj%6Û™V%ÎwõW—–ر+àÕ_á}J°Äª›‚ðr³AÂË圄WÛ9Ÿ ðrm$áÕ:Ck¬J°Æêå€ðjÉ…5V «íÜZcYòܱ, Âû”ü´Æ*Šm©ˆ—›9"^¹C ^iˆWK×XL¬±šñʵxåÃñj3ÏOk,¯| P^Ž"@^ýÑÁ«— È+ýWä•vyµÎЋ[ä•kòjÉÍ%–ÍÜ›#–%—X¶»´ÄÞ½ò©€yµäh‰Å3€óJ;à¼rà¼òvÀyµNp^¹ep^~`^ýQ`^™'Áyµ™¥–7œWµµÄ²Îù4 Î+Àyµ¤ßßM19¯ôZ€^­3µÄ²äº¿›b¢^mÁVùnþBZ¦DÁËóõUÇ=…0¡Èçù1>Ž{nù5ãlp‡L‘O1L$òéx_: R磟Î{Šy ç½!-Î{Ôlå½'5yïuˆÎ²ãœ?ë|]!dÈ©`²äÜ?Çì4ƒËÐdÊIS€ôÞSp yïÉGî{Š•I¡oŒŸM9ÓNþ{õõ#ô †«Jÿ½46¥ÿ}?©ô úa¤ÿž¢w„ÿÞE**}ƒ9ÆÓOoT|ºŽŒ95âãÀ÷UúÒá‹Jßà¹n:ðñ,ø²9™&ødk(kÎGJÍ9éš|Œ¼"ÿ=ÝQç³­Ð)`X\ühË© E´å̟ИóQÜs> CcNfì*þ{´F”ÿÞ¢®Œ9iKSü÷²Öœ² –5'3å¤5'm{Òœ3½ê ó žL¦ÿžd¦ÿ^“õf˜sÊ…Næœ< Nÿ=§9§l~ÓONôßK/;H}ƒçmÅ“ì9å({Nžz§=gþJþ{œòߣYXñߣ4¥>óè;­oJqM¾›QhèÀ§:ðé<5l:iÇš|ðL«NÂU§"¥ÅYuÊæJ|¼—tàKG@:ðIP‘U'?^qà“-(ød­“|´|J¾ŸÔ¾)ÎìÁ'' ºðQÑ..| ê >)7òáS€?YuÊv+}øøŽåÃG!I>|º_è}v¥¯ŸnW.|´I¾´Î¤Ÿ>‚œøÔE(øÍösô–|Yrâã2.'>š^§Ÿž’N|:M—Ÿ@ȉO¡ûäÄ'›ÓtâS\MÚtJ¡’䇘éø¥‹M:×P6LÝ—>|ºeùðéÁåÃ'k,ùðéC¤C Ê‡OýDN|zíáÄGyB>||ød5+“N:°§_þ ’ß”å*%?M6ʼn²%?%ÇI'>Ùœ¥Ÿî’ßT˜Eyñ5Å’¡ߦ?hzñQLL/>:„¦ߊñ@'¾4´„ä—Ï@'> &éÄÇ`râC:ÇôáSd%ùðÙnéÂsÐæ¬øðaÿU|ø LOºÆm:Ó31}ø¿èÀ'£w9ðÑ‹§8ðQ0K¾jÑiû–;.K>î'äÀÇíDqàcL ôàcÿ•æ¥37>޹ð1+cúðIèL>ö+ùðÝœ8Ò‡¦•éÃ'ÛKúð)œ™œøºª:ñÅ)'>E–Ÿ\Èݪ³ÓzPVŒ.£Î´þ—ŸBèȉOWN|²³÷õ²êL_ Zu¦‘¾œø¢djZwÛߜۃþ•$ (¨ù–þ᯲«ükiš–mwv½€J2!‹27I–dB¤íyh?÷Ê’lŠEÙT–”¦<Ðæç©£ 4%¥üG§hZæŒø>ëŸIÑT“1ݶ-¥Ÿ¹Uøå½îQf™V5²<ÊòkY÷ðÎ_³ËüÔ×ìmÙöýS‡-ej&¶TS3¡¥¬„–j¶”‰™ØRMÌ„–²ZªuÔ’Ò2©¥’–‰-©[*uÔ’’2©¥’”‰-©[*uÔ’R2©¥’’‰-©[*uÔ’2©¥’‰-©[ú’6-÷´¹ÿGÒ¦?JÚô'¦ë¿ÿ2õþÎìü÷ß ?ÏØ¿;@iéÏ'l²…ó0j¦šié÷21ý»ò4ý³6';ß|­û}Ûï6ßâàØ ØßkyFwã2-è`øö¼{³f}Œz¿îÇMµü`xG;Ž‹ ‰¾Y¶>¹Yƒ-®Û¡~xàGߊ¯ûŪæžب¾%v„çæw¾ ¿Ÿë «>j]/úê›è·ÄmÀ{£ýzìíõ°óÝÙ»™¼Â°A×cѲGðýî[â» 7åìq­÷>ü´›VZë±>J^ñ«eq³ÈwÉoÉ Ã¾ø-ë± RîÄ›òõØ_õGz7·=LûxŽþ–œš¡jÙHg†*üæý n뉣e»pjÉ’¦}×2,7íÃÁæ²\_­‡æˆ_ÙéÚyâRφWËä¯ìxocÏeÛž]=_–å sÓ>‚ü2O$7í‹gÜáŸ6¤k›5á ƒSÝÚ£‡ .œè—…§¸¯°hVwDÛG}÷‡±Ç§;Õ;¹½ Þ!ÛS)+9ÀÚöhü½¶õ'xw9Û¬½ pAãË"!vX4?Qrnàòµœ6a€‹£½eßÝÁ’‡+o‰SCz’­cæÙ0Àõ“³e76’8̬s¹>¾eoÉ‚.ïðÜw U.K·öœÏµ^²ê÷·dùF‹–‡Pw»Ò°=_Ç»e­a—DŸñS¯m¶™W/u¶˜úPeØ6ƒLôÏ %'¬åù˜Ûúµ|–ØÙÞŠ—Ó¢es¤¬ù¶ÙçúPÅøÙ¹a@yÏÚ–FáÂ(t‡–m#=2jèvìtï„Ø—zÙyßå­oûú3ßÍ6¬u—ž³ÍOOàÝd›æ²½Ð·›ì÷b¹½-»×ýdÇßæ´§îÛ³=õ±Íù“™äâ™Ì3uÖþ·ÍOvÏØáÞ.#d›Ëðš9ª¶­½}×ƺ¹<Ñ6ŸðVÚ6)ì¾ÊÚ±Çìõ^ìÈÇÝ,³ä] N}WChV ñmÇáf‰³Èmá–ÂZ^ͬn–ì5~õÔWcšÂóéY#<%sžÛv®úè†#1Vá1ñÎtXWàpÏ5~{êW˜;ÖUMJoÉú WüæÄºÚ‡d_ ë*—Ž·$ÖÕR§ÇºÚéÖ¿¯ð<‘ßÓ;õŒUôY°ºwô­\îוy ÷ucUå!ñ¾¬ªYVÞ’c¯?ÙìkaU¥"±¯UUå²Éèú\ýœ„c®wix0Xq¨µï~Å` áe߃«*¾Ü=Æ*\Œ÷cGʳ¾š'”’t™|Kb]-¿²ã½%'êL®­ì[Ï…µ•3æsqmeo{îÕoçy¸¶"VÙ~â„¶ôýgqmåëyöáÊþ÷ÀßUw³L1sµýùwÁËÖa/Û —lÉnfíœÀŸ&LÿŽ[÷Mê^¶?Ž‚x^£Œ^W'3°â5ÆH_ë®×ÜXKù ïž¡v”e§íõß·ÿ2­0ö6•«…m›âØ{®½Mñ®7¹áتn¿Mñ®Ã}ïUÝêퟷÍp}3ÛÄîO“¶þ‘YMßíÒóÛ®/bŸë·ê½-ÒØªÃü´óöS= lüù‰©Ü?ßkÛ~á“9¾—|â¾ù‰ÉÛŸ ; ×>óþØun<ÈMrâ‚8…Ò‹0ÿ‘QGdíÿlš&¤àvS¾à&eQ‚­ÜSpãÅ©·1®G nŒ4'Á1øRp£] nL°˜‚Û%YŒ‚#õ§àÆÀ#)¸e 7f HÁM/G‚[^‚›Ž¤¹Ie•æö «47…4IÑíF²4ˆnºU7»™ªT7½>ªnùRÝ.(RÝce¦êÆ(RÝ”l2U·[ŠU7ÚEJuSRM©níŽ3ÚÝ$ŽStË—EÑ-û‰D·¬CÑy$%ºeϦè¦ÐGÝr|¤èAx(º)ÏjŠnLÞ)ÑMo=E7öÑÝØ%º©GJtÓÛJѱ%ºéU¤èƸ<©º1ïkªnY‡ª[Þ3U7v/©nJ*ÕaJ%»åC@vËkSv³'gìÆ>)Ù½"e7D^•ê–÷+Õý/U7~p©nùÖ¥º1ÑjªnªCÙ­–l¥½+¿eÒÔ"»E 2¨núrRÝôf º1IhŠnœ$º•;¡èö rD7ÍH)ºé)ºå¥¨¹é¨¹å¥¤¹qp¤æVJ ¹qD¥æ¦Ï-Ñ“±D·ü˜Ýò±$ºe;!ºeÿ¤è–ý¢[¹ˆnùJ%ºéåPtÓ²)Ñ-Ÿ“¢[Þ1U·|í”Ýò(»)°ZÊnºeÉn4ºNÙMÝX²›¾d·¬Ù-'Ènùè”Ýræ‚ì–¿‘îvKû‚ðÆtÐÒݲëPwÓ¼/á­\éæÚŠHÝ-ßu7û2h˜º6J’Ýr†¤ì–ŸS²›:d·R••/”²›îª[cf©nÌû+Õ-?U·Æ ØRÝòSuË~LÕMë¯T·Òr¨nÙ°T7„ Õíÿoï]r.ç™í̾GñuÝIè.…ñ¡P Û7<x“ë‹;3Ïw©cà4ÜÊÜñR)Q¢.FÄÆä)ÝnI{Ý<ÍJuÓ·˜D7OðÝüù&Ñ­ž‰nJÇ"ÑmS¤sˆnõSu«a1U·º6TÝê)“êæë ÕM°®;8(ºmò±‘èVWŽ¢[Ô Ñ­¦£)ºU«)ºÕð¡èæ±"ÍÍ#ƒš[ÝbjnÕSin.!ÍMuRr«JÉ­®¾47?@ÔÜ´˜@ÍÍ»­¹ÕÔÜäIbÑÍ æV€ìV¯8Ênõ”Hv“œþ')’DsÛAbû¤\ŒÄrŸ*é¢%˜›±éðG˜›!î(¥™æ‹kÚA¹i7¤hŽstÑœ‚²šæ†÷KŠæ´±P4§ðsï7Î)ânàœ¶ çä!XϾÝ$Ç9¢®7Þj\¿uEZ¾À?W:Àõ¦Ôu·>]¾pâ‰oa ¾UTsáÛüxÜACÀ·.WÑÛøâ<ðeIzëÞºIxëÓa!Ÿ>#{ ^À[Ÿ»ŒQôVÞEo]›ÈEoófõô~ËßúÌâ °¿mR—ÀoQ ù­O™üÖí(F|«Nßjà¾}º½¥7N´i—äœbªK¤·Š#/z˶€ÞF™›Õ€Þ‚ÌHoÝAøŠÞ.mÑ$½MGí–ôfoL²[o¨ž¾¼å@nq‹@n}ºᬠ·h+É-Æ*É-ÆÉmÜF¬n‰Ü†åhéü6]±¹E=$·nGBƒ›œyn5 Ém“ÚªÂiwq[Un‹1dn«2â6û ŠÛ< n]»ùÍmåu'nóŽrs›¥Èm5ˆŠÛªŒ¸í'×·ZA$·Õƒ[ܦ·•EÜfŸr[]Òâ6;U™Ûì“an+³Émã:7î–Üñœºbq›[cn+ÿ3p[ Iq[V#n«zÄmn1¹-®¹mܳwO®÷ÕóM¾b¶zp‹ÙÊÝ Ì61¶< Ú<¬Íl~ “ÙÊ}NÌVŽnd67…Ì–M³•Çš˜MΤÅlu*0[½É‹Ù|#Íl>ÊÌVîhb6ß3›ÏnhóÃ`h«š mummõ–*h«šAm~1Úâ·˜ÍN•b¶ê˜Í×ÌVsn1›Ïlf³–™­ËNΨ°f¶:—˜Íw˜ÌßVf¶Þ‚¶z‰Úªç¦¶ªXÔæ‹.j+O2Q›/—¨Í &¶Uja[Ÿ¼(s~ͩ¶šÖ„mÕ`S››gjó¸1µUû@mµúZÔVG‰ÚÜ S›_~¦6ŸÝÔæ­©ÍwØÔæö€ÚúôUm]œZ%BÚªA›G—¡Í¯C[µFÔVç&µÙj›³ÕÔæÓÛä&%j« &µõ™+˜ªÜû#¿NHmñvµÕìNjë_žoñâyçÜ ßU0›¾m&²ÕÄÇÙêh[Ÿ¹—‰p“ØÞ®Ýý!ÀÑ#m"›O`ËSL`늖@^Ó%®•GqÍ&­Å[L´æ‡N¸&ýȸæµrO#¯y‰×<:ÄkUb|^¿Êßj^«s׆#åâñV5ת¶j8¢8Õp±U³øÉ_É‘ÒÈŽm\ Â³ÍÙ†ìÙ¦À%¿ukcm{µ9ô·½Úäã6]Ú‰Û.mQ'|Ú¢ môæw< ­b~ ÒÒH‹jiY”–PZZ€iÑ>bZŦ¥˜ö*t±(-‹ÓÒL«‹IJ«øñ¢´*HË€´´LH‹Ci^”V­%¤e@Z®¤-–¶¦‘¥¥”–PÚbiJ#!:¥Åm!¥ÅQ¤´Å2g”´, !Djy¢IjY¤–Z]O‚Z O‚Úb™ÓIZja!¨¥ ¶X&©ÅÝ%©e ZZ€j•úJ¨–e€jiª¥¨–õLTË"@µlàdµÅÐñ¬Ú‘‡¬VÕˆÕÒV[,]Ϫ,`µzVÅji«åQ`µ´€ÕªŸbµ´€ÕKÇÓZ°ZXÀji«-–þ#Ó‰Õ²X-Ë€Õ² X-Ë€ÕÒVK X-®Y-Ë€×Ò^‹£Èk‹¥)ï ½ÉkQ--ç¾`‹nØêE%`« HÀ¶XžØ²ØÒ`«ùCÀ–ç°ÅQ¶Jà"`Ë2çÔ°p^- €-ÎN`Ë2·&V—°E liy1»J"±e-íý±ú¥–÷ÄÕ’Øâ([–9®5틈-bôÑ(bKË})O“,gתÄ–e^ήU¦]z`UÈ–e:æWy ÙâbÙ¢"Ûbék*D![Z®K¬,7gX·†Ì–eΰeyO=°²€ÙKÓ«NôG,-d¶è:™-ê!³¥ÌæÙQȆ Slèjzb· V’EžSì–»&ÓÀ Ö†v+ç‹*a*G÷¸V‡¼[|±Öâ¯Öâ÷dµ(?Q-þ>I-~OP‹ß“Ó¢}µ(°3€Z>¨¥'ªUs@jõwZþî?–û P‹ÌÓèY¤ö¾› 0Kc¸³ µø=A @JËc'¥¥¡_ˇ-)m1`¢ BË¿NBKÃ$´ÅЗŸ“ÐÒ0 -^噫Ä$´40c±7 “ÐC[šõ72•ëªBk›»BASr}“û°(®yEI×B£Ø6âëo7,΀(¹­:Ho;Ær%…ÜvÚÉj£e†Úv*æžÄ6ù˜Xk»,Il;-ëIl»ì(µm|ý‹ÚvôŒ´Úv+ºŸÄ¶¹åyÛæ~x”¡ÚvŸ ì"µmlA‡Ô¶éê‘×+† Õ¶ÛAX¤¶},¼qTÛœqØrÛܺœ$×Ë­rÛeÍHr[5Or[øÂAn‹"”ÛflfX(·Eó(·Eû(·ÍmÎËfɺ’Ûê(Émq·êçTÜêÔ’ÜìÈEÅ­š+Å-NCÅízÌ”T܆'ù(nqb*nÑ8*nÚÄnÁ­n¥·:ˆ×çNêY±7ß)nU/(nÔÂaNŠ>`ÜŠ OWR\¶fR\(¸]T<Ápyf0ܰ<[2\Z¨·¹-b¸ñ¥TE†«'L WO˜õ6?ºb8_!\]N!ÜèöÅ ‘”Ûü  áúx nZ:ÔK¾óD¸zP%·yØXnó&Âuûoàj`Ym«æImó5ÁÅ%Á[ŠVÛ¢fªmQÕ¶ºê$¸<;7íÈÀƒ^jgܪ nÕ@)nW3"è%Ä pqf\ÖJÅ­:@€‹D€GQð ÀÕ¶âæ'^7Žê<9n4G*.ÎN€ëåD~˃Àoc0Dùm”¡L"ÁÍÓ–·êù­Žô¶j1·ºä·¬eò[Àoa‘âV·ü÷›ü6¯(ù-î•·ºä·xÈoY3·ºÆRÜ.ﮕâm¦âVׂü™ü¶Xæ´ZM&¿EsÀouÑ¥¸Õ3%Å­ŠPp«Q‚[µW‚[]cÒ[\QÒ[Öz‹Hq«gŠô–ê_Óªè-j&½EÇIoÕ-ÂÛ8ˆ7†ô‚[Ý_ nqø--à·¬æåÌ:2¦Û[Z€p].Ü$¸è·Ë; ÂÅõÃyN%ÃÅM¢à5Bp‹* ¸}:À# ·Uߨ·Õ;Ž‚[”x—+HÅͽš’[ÝjnÃQ‡Ss«&Qt«FSt»´c‰,—% ºùœTÝìýGÑ-¸ß唿ê*æºòIu«‹žëv0Îue\$Í øp€æê ºñ›Ï€..+€®ú4·zƒ€çâÏçªÉ ¹øû„¹¸€¹Åž9„þ?¥þù/NãS }2ÁПäþyþã¤êï bþË BŸÛüÿÖÿ'ôù³ BŸÂÿë?6ÛŽÿûK„bˆU¡H+ô·2õçžÛv„0ð›¡É­áóûó#7öþ¼#ôA¿´ßûósrék›ôÒŸ¾s0>z?†ù¥#—´þnÜWÄýÝá ²#w:‚pÅüà"w¹þNçµò?üÜ¢ó½—O”¸÷ò5ùüjs³“"C|¾µ°ñV.Q}3ÖÖ÷·m F°£Æ'{1Œ+Tȧ>¢^ÏP8Ì ÝG¸êÚ¡csàÇ0#›ÑW°˜u£ÕÒ8>_|'ŠO¿òþÁäÙlå­ÿÞÙle·ìm„ëB‰MësÙÙìyÿ§áÝf³_zö| ; ä§Ÿï×{6û¥ßÍçNÁ5²1=ýçóm<$JDþù‰=¶JáÓç*ý0Ð ¶UúžÞ ¢Óˇ¡O÷œ£ã ®UUâó4ÓšÐðυœ×{iØah(ñ^*AÃÜMZŒ1øG¥éÓ¿öÊ`3vd^h9]¥ÆÒ¡à9´†ûjÕ²±öJ}lšÃÆZÂ;爛žÃÒgû;áð…Æ¶=]„©‘àÊ7žÆ©§‹Ú°4uAÕ6†ª¯j? ›Ñì‡sÙ¾¤–¦ë¿á¨}<ôÌì9-ǹ\ßðbGªž³Í.ĹX ^ñÛëD‰`ÄÈ`B‰‹?›Ò`©À{«ýìãÞN\^8— ·í ͧ+û°´Ìqõ âc»•&€=vfȸpµ~nì1=ý/?¿Ol©Õ£1¼é±©VOψY±ýÈÄÃgÈ8ÑoȰ¼p‡Œæ6øCrëê0ÀQE‰Æûï^FïÈ휩b†¥+qDljÎýUBŒ¹£¸^hžNô™¢œË‰Î³/I†[ß«, ¼˜ç}éòÞ<ùïH¥Í>Ü †ûß»ÖÒ°ã¶®ÞÙw%kx;-]ÙÜ—k{t…yÔµcÛ­ò~ wa&šp¯®Ã™&Xóu>?–Ñz]××(ºî l>ùÝ—Ks=šWyo‚ݼڮwHçQ)'ª1ýÑCJ˽_]¸÷ýë=sïM)í}`¶”›Ütjœ¨¥âv_M£¤Ñrß|Ju%îçÔ%V™wÓm8Xï‹Y³3P݈æsk « 7¶WkžmÓ»r“e­÷Ù1u*wÖ˜†ñ V/ŸsÓ0Ùdy¬÷ê¹0*ÓH<ˆ4j~¶%!ɰ`­1ð¼·®±êa잤ÏôO®çîa螆¯”ñÀy”óÓDzs"e<„aáLÊï³åx5”øæ~é¦\Cའ“ç¡ÅO"O~¿_ëØªý b>¬c÷C¥#¿9¡V‰†µÆõÛ/¥„á©G¶¶Ì–±{ܘÆðÊ8ú{}õ q|ÍF# æü’aȉ1?pB}5_¶ûZ:Ù¸¾ öpFõÛ¸>ZÓÎï.p/|ݩ铼LI}{T†—«ïœQ/õ¡˜QC- KÓ §ó(d?ôcׯóë•Þ¼§®Í\&\ÆÍt^葱ûÀ™6ô¼7L«Ê.8,œVËÒ9­2<ïHvfk¦/û/ù­Ÿy»öêéZk9ù@«ßø¼Ç¹çgü>cóãìfÍ÷½¤ÈÜçú›c`~pgâ½}> ëiw^ N K¯z×Ë„µÌ\KhߣöýÒË„=ç’Šæ ‹çVÕs®së_MD˜{G´\X{/9ôLš>V­‰s¯hâÜë­Ĺ×qnæÕ_Èä¹WëÔĹ÷yð ç^%t%Í ÙÞ᤹± än0Lš{Ñ€Arão/aq¢ÜØð{°!WŽ«]Tä¸ÚðDŽ«}yä¸(ŽKÃä¸Ú ;9Î[͈qµKxb\mR$ÆÕ†obÜû*¤91.KLŒËãF Þ9`Ü(qñ¤ãÊs€7¶Ò`»Áĸ¨7jh`´[øå‡?°…OþÉp¯2ìáò„á¢ÀÝÙ"V0.þ>ù-Z07–*à=ñ-Ÿô6 œxÞª…‚·,²w¶¹'ºÕY„n‹åÂ^¾ªe’Ûû*¢¼È-ë»Ï=܆»¿nYiÃn¾8ï䶨ØÇ€Úê’‹Ú| m¾b¶¬u"[®gù9‰-{ b[--ëÉlï«t$b¶a¹h˜Ì–ÇLd‹ ¶¬ä˜ÎUàØÖ¦G[þ~Þ?–û\[j¼±±V™T„kK™çfÓ]æÅöÚ°´/ËËÖ«5ýΟ µ<h-‹ìØfÛ¸H° °¶™°–µ\ïWóÁjYËs°õnËÓ×ÖŸïÚaÚkßK‘ÚÒ”Þ¿ÚR[,ûõÕZœ –§¨es@jK™Ij«¥¯ÇLR[Nýž_]©-G5ìÃz;]¥œ©eÚjÁ^Ü8j’ÚRf’Z¾7îk_ÚR[j¹1'F-ÏùݾwûêÕÓ´´›}ðQÜÓ^­©e{ž õb'¤Hm±pk{Õ R[-ïW@jK™ûøñu®gc\† Q潿ÞÝ=@㨹×=¿_}x¹ß½ú TË¿Üó^õÕ†EÔËmïa¹ö¡,íóÙï—ãÄ5?×w™w½`µxÕ–õ‹]P%@µ,Óèe¸>,t wç¥ õÆñQæFkšhŽ;â£5OûêC{Ÿu"ª-Eúþݼ‰jÃó„jY¨¶XŽ]PÍ@µ¥Ìù,]ª-ú€F-wûé@µ|;ÕòIª-õ´Æöù\ý^û0Q-JÕ¢¢Úb9îõ6Õ–z®méDµèQm| ïB¾çXû@T[j¦hô¡Ýk º€¦¥µ¨–gªeû¸sÁÓI-L9ÕÕüLBRÞ˜–¨”7瀞°Ö< kÍm¤½mÚ,,ím×N=io{±Ö„µîÔG¤µ®(¤µîÌĵîtJĵ>#Øá‰kÃïâ!Þãï õBd^/ Ú†ãv<’ÚúIú&´õSÑ©m]Q|ÉlvÛ ²Å@¶±‡Þ&² 좥Élµ‡m2[ù±Ùæ.*m“Ùì¬AdëJ:@b3h ÀŸ¼6~ßT '¯ fÂ;‡¼6÷‘†>¸Vûw‰kµ/“¼–%&°S"AlqN[ô È–•Nd‡ŸÁli˜Ð6:J4µUϵå9'µe«&¶u…}¶õ«ôªIm¾¢¶Ú/l«Î Û†…P[mѶ-ÕLlë—â›€ÛÆï· Óæ¾½KÚ°m\·GGLn[Ž™ÜV£Mà6jáJ4À­.¼À-: pËzAnýR89¡[öq°ÛRí„·1í`Eð6jQoõ0ˆÞF™Æ+z[Î4ñmißä·< —G €ós,€Ë. ‚‹«‚Oö‘‚[=Ù"¸ì"®ž-œß0¸~y‘üÖO¯½ßrl ~‹{~ç=9ÁoÝËm¸~Yç¿e-“ß–Z&¿ ËÎ'·”™—}Á-G=el™^juU€pñÌ€à†Aã7,/o.º€‹.ßò2à˸85ø-/7ø­½Aoy–çYžL ÛÒÒ†§®Z:Ém9GÇëˆB"·|ÀAnyÝ@nc¬4)s“Ü–z&¹ÅÉïk_«à¶T;Á-ºnË:&¶-µLlË"“Ú–"ØÇ^Emc†Vó´åð´-ìeÁhë3Ž>mB[¿(€]7¯þØrØÆŽz|ŸØ–Zßûk`æ“h¬Yƒ#Ži»´h¬PvÒXëæ-à˜]£&ŽÙsŠ4æLF¢1;õÆœD4¦ Ò¢1'ŠŽ9œp, à1ŸcâX³ŠH«6ÈÜe™ö‹Çê7x¬NH ë Idi˜³JÓƒ¬ê‘9¯ˆÌ)tDdQ#Ì×ÅHÖkYLÖØÎP6¶ Ó@eco¾àTÖ˜iÌTÖjÙ—TÖk™—XÖjapr™5gsY¯5.rYÖ.sž sY¯Õ4rY¯•1rY¯5trYy²ËÂ,‹öËjgþ¤2tSY8ºÊÊ'‰P–•ʲi€²¬P–ee­dBY”™PVm!“Å©'“åo0YûÄüÉò¼@²¸õd2=áF²è‘ÌcÙH6#’ù©7’UµD²V+±D²´É² ™S[Érƒ",F<‘,zI&‹ÊbsÍ„²Ú/D&ËJÀd~èÍdÎfc(óÛÉTÍ#•ùl,ó{ÝX–GËÊg„XÍ™\W\–Ղ˲ À,ºI0ËSÌ¢ Á¬n/¹,"˜åA3ÏM&³¸ZͲ Y–›ÅÕ#›E7Éfñ(Íò(°Y¶l”pæ ¦„³ºd³há,-€³é%›ó.΢ „³ºÂd³x.Éfå%F6 †À×·õÄÌ;X%gñXÎâáynE_ô„3ˆÎüµc8[,z Z€3CÎò¨÷XKÎä—n6k§,Èfq Ù,·β àìsæ¾lhìáE8‹»M8‹KL8Ë2w~C™ÎÊ%‹pV7ŸlÖ/–βVÀYÔ6|³²YÜ[²YÍ"D³p™Åu™d¦ô—³˜efÑC’Y~"c¼ÉàÈUÎdãC¾XÓ™lÆ+ q,<«èLöÆÞÄŠ.G²2БÌñçåIVg +Y¶З¾da€/Yîõïô'c s;”Uz”…Ùo<ÊÊð;2{ŒÙ¡L¿íOVQAâ½Éê÷›‘×íKæßt%óoz’Õï7ÅÛÌ¿éF¦ßð"«_ïÒV9‘ÙùM^dº¾ò"ó ‘™k ™Ó‰¬j¤™ Ћ¬ ЬNÑŽõgçŽd§÷%È“,,ô$KKÿq®ú’Ú!W²(BW²´ô¼ÞåJEž¯¶Ð™,--A9“•¾duŒœÉÒÒ~¼«…Þda¡;™+–;Y¡?YX®µÏò( =ʪZ:”Ez”……eu=Ê¢]ÊÊ"Ÿ2—²(pl_͇SÙî}Žò* Ëu| ¹•¥åýj¿ÜÊ¢º•……neiy¿†üÊê·ËÒÒ¿Ú'ϲ°Ð³,,ç±"y–UcäZѵ,,ô-KKÿ.ó®÷MÎea¡sYZúWä\–ýZ» ß²(rô¯.ȹ,,t. ËêRÀ¹,~Ó¹,Ž¡sYXÚ÷3(ç²°ô竌œË²ï_#IÎea9ž¯‘$ç²°\_%®ö5Òå\–G.׶й,-í»}t. ËW”r.KDzø+ËÂBDz°Ð±,-ï×=cÙéÝÏr,‹2Ïö5FäX–÷þ#r, “¨Ôï÷k˜¿ÛõÕ>9–¥¥µOŽea¡cYõ\Žeiù~ åX–çûq†cYþîß}hßó©<ËÊ"ϲ´|ϧò, Ëñ=¡Ê³,-ý«ò, Ë½Ž y–¥¥}õAžeaišS5räZeú÷œ*ײ°ìçWäZ––ïI®eñ›®eÕ¹–¥¥}=«r- Ë‹YUèµ}#¹•……ne¶Ð­,Y¬~½k›ìNæžØÌ×ÕîdQæúšMåN––çk6µ;Y”y¿fSº“Å1Ê(È__3©]ɪµr%‹2DZ¾cäK–eèK¦3ÿÔ<–ÎàFQuwsZ÷8U³þÂQÂ!Im|;ýaL= B¨ø‡" *~ãù:Âbáh3ª8έšÓÆÜñ#C~ŒIRÀñsKoÀŽ3@÷æ´Ž‘Ne/¢Q=·B@2‚㘆Q#8:£#8B±RøÆ†0Oß8ÂrDøFè­ðŠ_Áð÷\ŒÞ8•Ã?LjRÑ·…ÕÆkø%0FoT8ÂßGo[VqÚŠÞˆŒÞè`ŠÞÈU²ŠÞȘH½‘!‘*z#ƒ:9z££L*zãˆ.Ù‹ÑÀxScå nbŒÞøÞFŽÞè°“ˆÞhùOч(ð‡±mÀWŠÞø\Œ#¥àMIÁg˜ X¼ÑѲ¼Ñë} ÞøŽ‡„šRüʈÝȘ—ŠÝx7 á Þ'bðÆ ÿ¤àÃéÆnœž¾Ó¢Ø.²3tã;ÞÓÀÈs%FnÔóV‘u +rãgh±ÁˆÜ¨Üº±ÎÌÈ3â -3¥»ZÁG–aðÆñ•ûçQ RÂès eZ½±šƒè%0‘ÑßS²¾ñ¯§ù“ÑçKFo¼ÉÑ‘0Ęzn»Š1zãÈ¢ÀS3z£Þ½QÏv…oÔã¯ðï¡(|ãHÞÀ-„ ßX-VøÆá«N1ŠáëLŠßXBñ_¾Ä+~£ÞŸ¿ñ®í”ŒßxUHÆo¬›€øzéVüÆçÑʲâ7*NnÅoÔ›±â7*HTÅoÔ ¿â7*oÅo¬ž+~cµOõÖ®Ž3»3-¿ßô,Ë«®Žz1WG䩃¥éåÍ¡¯ŽŒGo¯VÇj±8ÖVǹpTz p¬{§Ž#ë Œß¨È¿ñz+Z#¦Ìð@cüÆûú‘[çD­`’ ßX…o¼¶Ñ5™WôÆ‘` o¬÷“‚7V¼ñfÜè Þxßz‡)xãÇ϶0xãȺÅs1xãíMª Þ53xã]û5gðÆèƒ7^ŽÊ§è# Þx9ö¥‚7Ž 2¹¹1bìÆÏ}»´“SiÝ8Ån¼PÁ}·»ñr˜>ÄnŒJ»±üâºñrPK…n¬ƒºÑÍUäÆ:B7Î0°0tãíÄ ÝxozTºqf]ƒ…¡ë6!tc …n¬›­Ð#yºœÍ—ÆmK§º±ŸB7Vº±ú Ð·7Y+tcZ0¥Öƒ‹Ð~š¹ñªˆ‹ŒÜ8òˆ%³Å½UàÆº ÜXß ÜXÃS?eöĶª˜qÝXÇmôÅsÜF?qŽÛè‹ç¸¾TŽÛõ0n£³+n£ßîŽÛxípŒçtWÜÆ¹¡–·ñŠ(Çz ·ñ®ý‹ŒÛX}PÜF¿Ý·Ñó¥ã6VÍŠÛ8s|þ±däÙ÷·M<­Ì çíJÉCK&×ùýqUJeþaRžãŠXÕß‘þf"ùGcÞ–JhÉj`ÊŠd‰ªÎ‹fÑ_Z¢*š¢*[þ½“òìÇpùùgIyÚÿñ¤<¿{ÛæG¦åùjs=Û2øþåº2åêZó°®(źÖô=¨+“î ®%5ëŠR¬kMàú"íëÊä<ª«J©®%…ëŠÄ;¬+Óó¨®*¥º–$>¬+Rï°®LУºª”êZÒø°®H¾Ãº2EêªRªë¤èùPâL>ùsôüIŽž¿òîþ×Ooá_½©ÿõËöûíý›ö§ºþzžžÏKì™R"QO¥Ðù?š©Çù€þ¤–öï¨çóÈ´ñõø;SO‹L=ÿóodêùŒì‡?±/-^#¨7¾w?–‰%»ƒƒïmÿü>ðü3O΢s¦¦e~Íœ¬økçü ºÆb>mÚ5?ˆ®¨÷žD×uϢ˱ß÷áH?^¶»@oXä»/%÷ØG¦¡ñú5Zí }·£ýï­¿ã©ÔwjÇ2ßítût þX>uñ˰c/:æÃS_MË|ƒ4ù:b Œ3ZÛGܪQ¦>0g†ße¦Ð„å™K Ö‰ÇÕŸK Ò KG-ÜæCÖÛçÃ3ó;Ëç[f.1<^8ùXæÃs*Xýç™™\òx)å õ/ŽÂrÕ±a©oäI—|, }¨š¯ù[kiÇvφǫvdžµ¾gÜžé™K Ècí£Ãr°L›k Og™ÉæS 39 KÃH; û6ž –}.0<—ký6Û?öÍ7ZÆ„:ŽXâ¼Ñþ±_,õ=—ò1û=—žxü¥ebÉXÀ³qŒ9r´ßKÁÇŽ¥¾Ç™ŽÏC7»Ðõs2Éã¥Ëã3ffFÌtX¬ô=cY >F ÷ÇKÙŸß/Jhíè8Ž i²>†s®/<^¸úXæúÂãå¸Ï1/Úï+uÜ®ïóƒgzæúÂÈÆ{ÐÐ5ÂÕ˜÷Åz±ôþ±`™ïñòÜqôQ‰·‡~~w\]©s{0:Þ‘+xZ°È7z€€ùŸ.í¸\hÿðÎð°œ: ½ã¼ð ýÄ,sïè‚ö¥ã¸ÁŸÝÞ 7 »¨³Íõ…çÔKåc™ë âa‰o<é<ѵ_Ïè…%¾Çhû±Ìõ…z–ø/e×y¢ ŠpŒ/x§|~7¼ev.ÖøžS[¢ë™ Ï¡eþÏ€ØÔ¾C–¹ÀðH¿ûXÚ27ƒ>W?1HÝ»{›+ ÷ðλh™+ Ï®zïs!N~óDãyž?ϹÀ0 ܬ‹|ÏtI„åš ×kŽ‹|qžg®/<‡Ÿ•k|õ²?|Êø…vcoXNÖÓ7tÀ¯Î«|§ÆÏçö°y£ð,¡õšeN§w½\GÿÆ|5·ºÂrÎét$ÒæÀ®óYeXº.0;>ž¿É.~©=Xæ{vêñÚÙ17ry°ÐwÏ ñ°´Q¯°ãÁ:ßHÎôn˜OÇ<öÐ2çÓ{nE‡eÂû~[e8^,ôöñZ hçÒh™Ïó]÷áe¾Ô™ –©f> ´Àu¼J¡Ú¹ÔwŒìó÷ÁöMUûSKÓ[á²öçJèSãx!lßÞ'þ±Ì µ>>ކ…¾Û*Íç{öDü 6,ôžÃÃûc™ê]¯¿vΰ›&›û*K`¥ïögÃÇ2'Ô!°1Xé›.VƒÊ}[@ø|ÙL=g5èÜ·ÅŠ£Aè¾ýÍrtˆÝ·sØjwÜò¾óÜ/K@ïʻݱÔw[°::DïÑ>N‡K}·µ£Cö¾?w™7³c©/†h‡ð}×ëºc©o Þàéû¾º[ŒÅ¾)uÌ£Îmˆßõà¾Ç+D% cv–þ}[=7à·c–žð{Æä‚ø=cŽÁ üöBè¹A×ë¦*x ‹sèP_}hú€7ï9$ñ õ²ÁÂ/­ìç¾]hžnÞ¹C ¿gîZð$jù÷Ü!„ßž÷Ï_È÷¥d:Ÿ {_Ö¥ã.è»êÜ¡„ß̾ù1<×rwá·ÖI‡¥á&hHœ;„ðÛ3ø¹C ¿½|bMšË+œëÎÁ œ«±IšËÖæò<À¹ (œË‹œËçËä¹å(†ºòÏE—ÀsÝ9tñÌè‡0׺Y4Oq./ xn)3./%€.‡/ˆ.Z¢‹çH·Tü^ñàéòÚ‚éò*ê"Ö©.O¬‹ªË ¬ëÓ©€M®Ë[=¸n©vr]V{ëás‘ vÑ%p]ÜCp]^9p]Žnp]Þgp] Up]Þ€]Ììòjƒìº³T‹ìúÜRÆM²ëNà-²Ë²[êAˆ«ˆ »åìr•šh·…0WqWÛ-¿w<ÃÕo°] < ]&ÚåÚeëÀvË™î—7ÁG!ÄÕø¶Røìú¾Ë> ¾ë¥ùƒïzmbÞEswyÁw}je¾C³¨Ëœ;Gˆn ð.o%ð.Ï}cƒàˆZí}§3ju|·XàšÄqËÀëïé%/^žº1”«O ÂË»Ô˵º=/OÔ˵*A«ho93‚\U>Q2ÞrbºÆåå©Ô5Š€òr òâ yË!ì­äå!ˆî:6BìÉxyÀxy¥ÀxË©ã5B˜«<ªi•†Ø¿>c'ãE%„¼¸m„¼~ŸeA¬×j !o©ñ^³ ¾Ö]!åÅ GÊ[,ˆùZO1o^"j`óº}àHyK%ˆû•óâm@ÎÕ4«xÍ£ÆAÒ[,ø N ¿.–ÎqôRnCÜ׸ô–߈û‡ ìkAØW'0çÅà#çåQ༼½à¼z­óâ%=9o©Q_Ëž  Ao9 ×ë-BÐË1ÂíîrŸÿ“”BÅvÊ)TlÈ…}TÛ wGðànKÜ›KŽ%¢îö\lW|,¶;AÍpW‰Bw•ApaÍ w•öCxW1¿'Ý9ã„ànL=b#ÀsŸˆíöC¡w•wCtWiADw•TExW©Y„w•çFx·æHÐ]9߀îœ[ÇtWéfDwÎY#¸ûÔÚj »J) ºû¼¦+VxWíÞÕ©„w•“xç‹'ºs² Ó]uZtW)_Dw^fÜ9»àn÷»Bp§,D†»Ê#¸³È.¶‹¶L¶ÛµïAh§ÜHF»ýQCHvuƒDv{}’ìê†ìœÉ`W÷U`—ŸdWW…`WéRvÑ’]]‚]%ØE[vÑ‚]=»h ¸®Þâº8÷«¼P>ÀÎYœÀuQ)°N©¨Lv~œv•ÍH`ça»º«äºº‰Äº¸*ĺ¸京\Ñäºj>¹n×esÁu5ˆuõæÖÅu#×EëÈuñh’ëª5ëêR’êb°ëꆑêâ¶ë²)àºxÀÉuu¹‰uÑZb]‰X—E€uu]&ÕÕ €PW’PWoeA]¼Xuñlê*™Š ÎÙÉ uu)ÉtñÞ ÓeÀtqa&ÓEµdºh ™Î¯1]]2]5…HC—H÷ˆH— ]ÍNBºxÿ颓é²¹`ººdºšMuq¡®z@¦«gšH%@t»¿½EtÑ#"]Ü"]ÍEé¢V]6 DW…D=d¦úº«º*Bž«‘çœþÎ<ÍŸ<—µ‚çâÑ#Ðå1Η¨gž@—etiaÊD?Iä¹èS&zÐçê‰&ÍÅ¥›8ŸĹª”4¯â\Œ\â\4¶;y"¯%i.ni.Θ‹(a.ŠæêD€9_±\uP,ç‹"”«ÓåöÂ)gRä¦>‚\”`.Åò­&Çù=-Œ«—˜0.-íÈô8â¸,Á”Š?q\uˆWO0®.Ëü&Åù âjP âªÓ„¸8ós-gJÅǧÂù«]·‡'ÁÕHÁÕ‰p5?‹àª;àâ<¸º$ä·ôŽg:Å\êðZø–õ¾š4ÑÚ_$³Í0Ç›žuG%9¢gÝ1’š³}n“¶çÛ³nÄCá1ô¬ÛE²ö¬;š½ïèYwýäY§^åY×AWžu3E,ô¬«„Pò¬+(“g݆cÝHFÏ:¹Vرî3]vmº„#À©8Wò¬»í‡"Ϻû3™œ¬žuµw\žu·#~ȳ®v»Ë³nXº$¸]{ÐméØÄ,Åžuwe¦gÝØ,© žuU¯<ënŽgÝí0ò¬ÄÚâY7þ°É‚à=»Ý¦gÝx§­žuÛ&‡7:ÖÐôS cÝhÜüàX·ívì¢cݶ)ú„|ë¶1²øÖm;áɷnÄõ #}ë¶!'º bÚÓ?}ë6§”oÝV;eoNc#xs.2yÖÍð ÉnK-€·Šp/x«·‚·ØJJçºmSÀÑ[¥T‚sÝûAoQ ñ­¶ï ß*¡ƒð­ö0 ß¼9Zôæ€ûVåJÑ!½UÊá[mº¾¥eêrλ!€S®+œs€à*瀕9kö¸Ê"‚«\-B¸ÏpÛcVæ–½–‘dEW;ËApY‚ÒÜ^{:p•ëBWÄpÓÍWĆõÄêî Σ6W*7®’‹P›ãæ+sq¥¹Rà q¥ìKšÛk#'µ¹ºod¸Jô`m®”\BÜç ߈ Ñ’—ç¢5ãJš!Å9±Á¿%Í=Ál“â†çêµJs¥—Jš+!@ÒœEJRÜã" sõ\@˜+¡@Â\JuØÞRÌö;a®„Œß sOñŒ„¹º˜¤¸¨˜º\4÷|A\È,„¸P¾(Ì…a2œãEY—ëÚôc].”/êr%k]®<).®ƒ„¹â[˜sÍããK sÒš$Ì•è&a.NŽ{‚(Ì…¦Fa®#eÎË÷"¹¸¾¿SæêÜ’æBÉÝNy)’ËsSš«7ˆ¤¹ÃD¹ré,iNzYîöFV²\ˆ¬“åâÊHš«óHš«¶H›;<$sO¬´¹Òæ¼îom®^NĹoÙ™ïdòœÞ‹”æ\‡pî VÎÕ]±4GQš;¼@÷˜s-ÍùÚé$Ęèêb é.û é|ã@tÕð\ÈFä¹1â¹h-.zD «»d]î'¢Ëz€tu½­ËE=`ºÇ«[æªÓæ@ÒÂ\T ¬«·¸…¹:±îñbаîM \xÀºzaëÂåº\œ\·Zº\]ér{©pÔåê’ìn%ÐŽÌEö—ãlþrNaw908ÌyÖ•¿Ü£¹ËÙXÞrweò¥·\Ý-¹Ë=^1»ÜcùDîruIä.w—Fw¹Û«är—»K›îrNvk‡¹´Àcî.™Ns·sÇËi.-pšK œæ*2}æ*ä]æÂ¹0Àa.6´N‡¹ü ‡¹´Àa®,r˜[,í×7æÒ‡¹´Àan±L‡¹´\_¿á0—8Ì-–™@#-åÞòmÉ¥îrihì t– |åÂ0)n1,U‚áÒ€ 6a€£\Þu`á²Ò×d‘Ip«åeËl™÷Ö¶ùÉÝÎ= .Á-–Ip‹Žr‹¥u·X&Â-–Ép«¥õ ·XÁ&-ý«ä¯ n± MZ&Å­–Îö1öýåÂp]_%&½wÉ}á²Ä$¸4¼×òsòÛbhl» È[SÀ[µ& mm8È- p– õþ}‚[î{m°- ÈVS×Ô–%&´¥a2[€l‹¡­ ±¥áXÎ^[ ïÚpàZ¦& ÖÃLRSû’ÈjYra˜¨¶ÞµeƒÔòç~|ý}rZŽwm98- ÓC_/( - HL†÷XD{ool™ˆ–à€hQ„®qYd×ühË¡§Ë–SócYðŒÖ£-eo1-ȸ¸Xúú9Ó‚¤‹iAæÅÅÒ¾úH[,ûùÕ@Úji_}¶ü¾Î¯ÒVKûê m±¼çWiãŠÚÓ®µï>ôû«t“K˾}õa`Úòû¸¿úL[,×öÕ`ZÞq`ÚRæ9¾Û÷n_}¦-¸É¥¥k '¨­¿ßïûµö ¶Zúzj‹åºÖ>ÔVK_û@R{³@jK™öUKëßíëÏWk£^n]#¬-eöþÕ>ºËè#:ê¼¾Ë sãbéë} ¬-–gm1`mµ`Þ¼äCZ[Êôó« µÕÒø®·Ûþ|µ¸¶Xίgûêx-¯(xm)ólßíCúÆQ›"!"šº}#½‘C_XÍЗ›cvS «pæSŸsúësÎc}ns,?és»ý‘¥ÏíÖC¤Ïí»ò—HŸÛ-›QžÛ•4ÉòÜçÝ˰†’ç>_É(ÏíŽ.}nŒEByn W‘ô¹ñ9%Ñ},Ýñ)¡Ïü.*}nø”ÐçöÑYž úÜ:ô¹,}nwìésYfès{(Ðçv‡¼—>We¤ÏíŽ-*}nw¢ésÃÂåTês»€ä¹Ýâ ä¹(rñg[Ô¹ý>~,L·Tyn¯è}”çvÅõ—:—CSh£:7°jclÈsH³3 PçF½b%¨s»2g@œÛ_âÜ„5‚À—»S4(ðåîS’ç²-çöZœfàËÑæDà˽¢§1öey.ÚÃØ—Ñ©)ÏÛ¿§<7ëU„ľŒö1øå^‘åü2†ƒ_îÂŒÁ/wç¸PôËñ(PU`øËÝÙ þrø¹ßŽÖ7Ã_îJ¦¡è—{¢_îtÊà—u+û2.ƒ_F·ü2.0ƒ_Ž.-[,ç…¸Óuni ‚_îÖÑýrwBE¿Ü+j,£_Æ…aôË}¤-£â…è—{ÅeôË8ŠÑ/w¯)úå8ŠÛœý2íŒ~ícô˺ž ~w‰Á/óÔ~¹Ï¥6ZÆÈ+žÁ/÷ +Çà—»²ž(öe<@Œ}'gðËx?Íà—ùÑ/w'™PôËÑË›:¢_îN;¡è—y&„¿ŒÁÈð—㾜É}y)þrŸÄ`AøËlOçƒèöÌð—{E2eøË=D9„¿ÜÙXá/ãL /Ã_æ™þr0š7&Õ(ƒð—Yá/we€Sô˽Â!Ïè—1‘0úeTÂè—1@ý²æ ¿Ük¿ƒ_ÆÈgðËÅÂç¹B— øe–Að˸ã ~ws¿Œ«Çà—1¬ürw¤A¿ÜCàCðËx—0øå^ñü2jfð˸  ~YOâŒ}™Õ^œT+´Ê½i(ËÍIõÔ4Ëà—»³¬)øeÖÓ8«úÔ­iŒèäˆ}¹WøNƾŒkÃØ—1fìËx¾û2ž ƾŒ»ÂØ—Yïõê sÄ2öe<‡Œ}w“±/w'–QìËøbìËl1b_Öû±/ëLŠ}YÃZ±/kPìË< ±/w§SìËz[+öe]žôQè˺ã }Y‚ }Yß}YS›B_æ1Óª¶‘)öe½ û²>êû2:8±ºãûé‰U-üÒ/žܭ)öeÝM¿Ü#¦&‚_Öó£à—5fü²žC¿¬‡AÁ/ãš3úeœ‹Ñ/ëûAÑ/kEôË‘‘¬§bdðËzé+øeMûÎÚ2&\*ƒçUMàŽ~©oâÌŽt•qÉwq3s{íÿ¤eÉŽôÛã";ËüÃìH?ŸA–ÌG´žâ„%R]Ÿg}€sU%KTESTeKV5RúfEówV3 Y ~G÷/.-Q MQ‘-YÕz¯âîeUëÉ[õïž³i|©~¿HÚ4ò,=?Oû)‰M%b:?ŸDçñûOŸŸ™ãù)oÍW ÷¿•öé+Ó¯†×Ùâ¾üî#‡æšå uef&Ôµdfb]QŠu­YžPWffB]Kf&Ö¥Xךå‰uEf&Ö•™™TW•R]K–'Ö™™XWffR]UJu-YžXWdfb]™™IuU)Õµdyb]‘™‰ueþ&ÕU¥T×?Éßt~>mÏ÷ÿæoúÓüMavùåKü§¹ä_ÿÆ|°”úíñæoºæ§e¤oú šþj ¦ÿ6ò7}¾ßçÿG ¦1œ?ŸÎÿaR0ýÏ_¥` ãßKÁôy¦ç²;æâm=WdñÓ/,»W„¹¨bÈæwÙØŽÓNï>ç6Ýtd;;µcÛר<=“&+âxçŠâ®îs¼DÆÛXù¹¯ Ї?®m­y›N–ÁŠâéÕìe®e\þ‚º6,*^ ×v·ëÁ2׆ÅÛ»û¯‘£s&_WË5ΰÚò"‡ò–_ce~&SQ‚˜käJ_¥\[G¦0û׾ͅ ìeGF¿]€rae>’•\ûqg’–kg2­¿Æ:3‘쬄¹tœEák˜ ùK°$zíL¦ãË\Çx.eIºvfÓ»äX¦!‡}‹®½ÏuŒ÷â!}®bT ¤ëØf"¥¹Ž}®b¼»ÒG]Ç1W1Fꟓ†®öcL]Ç9W1ÞM\yJ¥£Œ,×qÏUŒ×™>–I=¯}F®ãAN¬.,»Žw6F»Ï¯£Í5Œ¹óŒõ2—Ži”ß¹ŸZäÿsXM|íåtû\Åxíåô± '–Ó-]ö}xís}^?–œR×yÍUŒ×N7 rbÙÇêú¼p‰9ÐÎg.cŒ,S–w.c¼çé3½Háá|Q׉åÄ»nÕp;á……•ƒÏÛ¹tì7ò±4ôAÐu]XO|çúÜ>ôA¹¿® +ŠcQig=gC/;c=ñÝ•åèc˜ëcùê噞ù4¿öH»†+ZCê)Õó2/–r½]Wc^,ùT]Wg^,ù|]#}܃{ŽßÛ¡¤…éëf>;¿}Ú·_õûEäLpÝç\ÆxwìˉïqðÕ2ò^Œ+áì×ÕÄ×~M×HZ2Fºa]7ßóÖÅ gXÀ¹×¼Ó¸|X-¾FÞºy”ç;6gÂ0–é„FÆ:óìnB·åÀWç¡$.×ÈêÔpn,-\–ß1½°Ì…ÜX~æ¬&Ž^ò¹ÿè¡|, çoÞ·‘ìÆyØ`¬&¾Se]OßqÎËuoÜßMRʽ=ªÝxj&šüôñfë°˜X/Ý{ƒàþ*æ½a-ñq²Ì{g¦ÉéþH fÕªfß9«n|¤îz{½úî‚û«V÷ÎD“cÆc‘ëÁ‡~ßœT5ï‚{ž‚ûë8?÷Μʾ;óLzUõÞû†!R§†à>¥XŽíÖ(ÇgÕ}0פ¿ñîã@Ž:'ûúXZf:¼sê¦×ù}0×䈓Ízñ…Ý<îWß-°ŸÏiÌ©ý²…¹&½‰ïƒ¹&ëcaºIåꦛtF°ûdºI¯JßçL7éoñ{|þ¡õ¹Œ˜'îSé&¥›ÜÜœo?> óbiÑü3Ã/ýó\uÖÉýn·ëyðÆÙ™q2ÊèYjÕ}2ã¤àæ>û±`ÂÉz~.&œt:W­¿Œ$Š3ÝÖ_ÎÀdò›±r™®?üŽòc!øUœ·I~ïL½Ècì·ª ¿7B‚ü"qѯU¼8¢_;í·KökåTBöë—ý—É~?‹è×ç ‘³·vk€ý6sÙo«o`²ßTfxØo«¹Œì·;]Ÿào=AþJÈüÅ™„¿³f.Âßq(ç›àïxø²û§rЊýÎúà%ü…„¿Ó9F§÷Ãþ.å÷2ü]Þ<&ø;»‚%þÆ×<ç2ÂßíÄÄâ¿ÏeÓÙ'ÿ} @üJþ»üºÿÝ›4.àe!^x×”M¼æ›ð_å£ÿæA¯ÿÝNœ þ»cTü÷8€øï®\òŸóÚ ÿž¡t¦€ÏÆV¢¿J'ú»‹LH÷¬‡ŒÈ?ÓŸã6þ6ß\Òßshq…ð÷LÝäC®ÑIö{곞ìW¯-±_½ãÅ~Ïå²ß£g³_½Í~5d'ûÕ;Uì÷HÙúeµ?:_Yˆ~~P~þŠ"ú0ý^ï4úÕ¹Ä~µb!öóvL²_ЖØO¶ÙÏZÅ~O-= þnÕ)ð{­Ý€ü9–¿1¥VóH~ƒ¼x¤â_];Rþz¾&Áßg4lï¢ú)}†Ø/5½É~ƒÈcª~å¯&Õo¬æ¼É~‘ǪŸ§?É~ÛgŠ`H Ê~ã[ž+|› ´“ܺŸãI÷;j5‘ºßçêZ ü5ëLø»ê-Oú;g¨Z üÝ¥‚þ>h¡ šôw×›ôwÙkEôwûí%ú»¼J%ú{ìÇbéïÔ›Sô÷œ‡Qî˜Ù©ë7¥?ç´þìãªEÚŸ¿ëˆCR¼Wío¤›!¶Qû#˼– :û@í¯îžµ?£œå?÷ò_óº*ñ/P‰øŸ¸ÒÿêƒVú_h{Ôÿz2Yþû0ÔM”þ <‘¸üŸAœÙ'þ=Njnù¯äÉãMÍæÿÞë0”‘ÿœÈÞòß§æwÀZ¸²üwøAò_}CJþ³gHʤð €~ýZý+ÉCê_32Cµ#†–&¬Oeàˆ%õO¾VÿüaaõïòöÃ*ÝTÿgJý« !õïsÑßãsšøÞÕ àø>áòƒð²‚MlfDÀ×eFÀzƉ€¡øÛOè]ÖBÀV+ ’ÿJÅ&¶Z³ÖÓJô´g|,ʳ"àˆ6H °‘@@ož ¶º/"ÀÇJ. °ÕR’ðUäP`óz¶°•úClõøŠ-"€›÷–›C°¶Ó»„€53£WDÀæÅ`3ZÇ×ӻʥ›ä ñ_;Š,ï=?aÅÍD€s}tAÀæ]-"Àj.°o€ãâñ¦ã¦ ï €í4žLlµƒ…øF-Àq(§U` ɰEÀmïÚ{BþkŽ…jþ«ò_«9ü×êÕLþ„°}öÈè¯Yºþň&þµZF þ5aØoäRêþÆE– økv±(ø;¹JCökÖLÄ~1V'ûñ¼f¿V(ökÏ—æ×´(òí‹üL·B¿1Âøµ+ôó&~¡_½=„~F6¢_ó:ŠÐo ѯI°ù5Ëó"¿6Ô;’ÕÆE‰¡"¿æýM"¿fEWä×<{‰ü†£õI~íò… ùÕk´ÈÏú¨È¯Ô0’_=²&¿¦¯F‘_óªÉï4‹üühòó¼(ò®ÞâÅ£-·Eäg•ZäWËb"¿V*ò+ &ù5}q üÆ«…„FòkW ƒ$?¯œùéÓCä×j½ä÷iÁ£ß/šw Ð~5@E~þBù5 í&¿Z­0ùi2úYÝú5oëúmÕêЯ]š\~Í{•„~ÍQ¸~þD´è'iäÏR8Yë›Z@àÞéx¼â½we=!QÏùK„z‡ŠŠôîJeìýŽ'Ò³£´7xÎWéxmô†Ô&¬蕜@owä{Þx 9kôv_F€ž‚ù“.ããŹìð<ŠRÈyG­$’ó†Œ&^ç¥[óÎÒŽ¤ò5³HåóÇ81ïô… åÞ¦A‘/È”÷AÉaù^WÈ»¼ÍIßkr•Ä7· Ó‰¯6€‘ñ®ÇZ—%¾:Š_ $’øäüÄ«pîVøjº”ÂWwM _}˜Ká‹z¨ð5ÍÕRøêëS ßn"‘šß@¼<ï.:—ÂW%…¯1 …ïóв-ø²¼>kÔä»ÇÃ-ðÝŠb¯65’ïn/²Ràsì{Þí)È Ÿ'’ø ô’ø>—™2»¶wvoø•Ä'gH+|%cIá«[)…/ø |W $¾ñÌj)ðÝV‰¥ð•žb…Ïô.…olçQTøJ/ÓæÎZVñæN猪ÂWKìĻNjÔVø.5ñîiÅSÀ»gäN\ð®¶ÅXá«ïe)|‡Ž…w=E­ð• C¾{ü+ï(nÞ=E]RøbëãÜÞY©Rø4­ ïBª‘ÀWßîÄ»'T6 |GûÚÝù:_Œ¾Zy!Þ=E›Sßs0ƒÚÝY§ÖîN£…èÎä&}¯þbw'Ÿ0é{…÷Ò÷œnÀxWúŽvwž–ë¥ïÕrwwê.IÞ{7ŸˆxW|"…¯öºKá+­V›;cÛ(¯º`…Ï0ïÍúJñæÎz€¤ð»5¿©ð=+ÝÕržå=3,é.ö‹îj2"ÞÕF>Ë{¥² ï<­HÝ«7¹Ô=û—ºç=ë¿S÷êÁ•¼W¶å=¯-IÞ+=Zò^œ›ú^¡¯ô½Z%â9Rß+MUú^ #è{Ïå͓ļ@6J|­—è‰ï,mŽ_Qˆ@¯vàIãó”½Kûâ¤ñsôJ^¤ÆW„!¯>ò­ñõo¯[‘ôêK[¤ç Ó¤·iAi|†`i|µÛÏߥ ½Íˆ!ïj¥èôJ9é•r)¯éY5é)”IÒ ’û;k_«H/¤W; ¥ñi¹€_@œ@o÷K‚ž¤íRøš‘œgMÁ _ѵ¾Ò^%ñÕµè9ªƒ@ï­ É’ø 'è½±—SŸG±HÏ>2Ezz‹™ô¼AÞ¤e@zµZ\¤§/[‹|Õs‘^h…ùôQJÏ‹¼=ïøçÚÛ`‰OÏá¯R=Û«_nÊÜ]Jë"¾K—¾gÏD[à»}sô^«èú¼];ëìÀ×+M|w:So»ìÀ‹m}òà+ï<ðÝ]¤øîöwëä»ÚG'¾R¼Èw3ʈïæpc[ÀwµAÝ.|µ@G¾{·‚Mêxµ™Q.|Õ`ÞÓï­%¼‰wWûñb[•øj7ùî­µB^ø€ð^‡/à½^βˆçà…dIxQ o,ýñ3Pž·ÈˆñF=×ÂxÍûIÄx­äukxî'!¯–i­áËNÈ»9NýÆ|T-&åµrôµˆW`Ê«Ï,‹xþ@²ˆçår‹xŽÀ#Ê˳O¯^ Ä¼±0Ê—µD¼râ$æÍ§Ë>ÎTÅ(âUû¤â•º/oƈ¥û8MÖRñj³¼d¼±i'0¯ys­T¼×W˜×ü oÏKxñ’û âyí×j¹K*^m§Šçmñš‡¬D¼´)âÕ¾Díâô7¿E<·E^Í6¤¼N~ñj\IÄÛQ¤¼¯ñ,ŠKÄ«U2‰xµÐ ïñ²”d<xµŒ÷”c e¼Ø×I¯îœ”<ƒ••<ו¼h 0/ÄkIyö>ù’g:åµà*Šy)ïAÍ '?Êy!ÞòZùIγ_(¯ýDy%þ‚òR&¤œçÅxËy¯öYÎ+²‘žç¦<ïîñNΟ)ï.¤žç ©Öóì÷n=ÏëÙ¤¼WÖó<ØDyy (¯]µÓ”z^mì#垟+åÅnOêyã»”ÀFÊ M ”×ÎoÊó‹‚r^ÓûÜ”g§%oä<ëD”óR”×JÕ"åu{@JÍkW©y–yõtXÍóËÄjž¿éyãDÄRó~ÞÇéï]A^+½Y7@…@^}XÎ+—r¨ä<ï•ñNÎB`Éy#kžržÝ—Myž„yÍ!¯…yÞ‰Ÿb§æðŒK¼³gœð®R2ÉOï­íœÃMo|æNÍ·ÒYÊK¯×&L:é9y)ñîuŠNÒÝ;]#S¾{CT›pW«9d»,1Ù.ÎC¶Ã^¬òÐ{+©'áë²Ìä"•†’p7×Ï8ÏîÞJ^I¸{k{*áî­¬˜„»,¸Ë2€»Õ‚d\a9¾~#™Ïb™iFÆþ-9ú!™OåÉ$ßÕ$Þ½•¦‘x·Tƒ\>qФ»¥È¤»Õ2“T†ÈIwÙÐÝ[iÎHwK™Iwo¥¢$Ý KÏši˜l7÷ºÝ)ß½•œp÷V.Ç wKk'ܽ•_‘p Ò­°ò+î^çž#ÛaaG[6g®‘è6àŽÚ9Éî­Ìn$»·²¿‘ìÞÊT:ÉîU?r]üžTË €:läcÈéó8S8¡n.ü¥gÞ0,AYæ -¿ Àt‹e2Ý[YÉt«¥-Õ"±Oœx]¶ D7]§¿¼÷qxL]Ö;î­L§ºÕ2³‹TRJÝ[z+xî­|““ç"Çyn”h²Lž{+™ y.¶ÎçÒ€ ?µ30—-A†Ÿ<Ïd¹w®ZÑ2Yn®òÓ0Q.›2æ×sIrKIr‘$ùøHrsã–ˆ)~>OðBryå@rÐ?´ùrÿº3”geÔ$É-¤ø©°¹¼%¹<@n±LË£rÙ€ÜrÔ‰ðfNDH’‹ùt’Üú{ΟÓï8Qn)3Qni 2üT¢D²Ü[I5 sY3`.Ì-e&Íå Í-eÎ%m#in)1in±Lœ›á—®Ü’ù*/a.ÆÉrï„»Tìrdå²K`¹Õò²:ªï÷ÒÅÎô>5>Ár9ª;Óû„…-£¤÷É3!£e…ô>y”3ZúìÎh©qÝÑÒeÖŒ–„¹8a.Ž!Ì-e˜Ò2Ê0½OÔÌ”–Q†é}¢ “ZºÅæâQ Ì-çfzŸ¨—i-£¦÷qKÂÜ{;m$an)ã´–ò§cV˪xgVË:ùά–a¹¾~3«e[·fæuؙԲŠ0·O˜Ó2ŽéÈ—–öurÙƒy-íyŽÃ ~\8o¶M&¶tÛ&¶ŒóÞïÚüƒ‰-ËÀÄ–U+óZF;˜×²Š0­e9™Ö²Î|δ–> n9„Y-Ãr"UÞao8&µÜ’ÏKž‡I-•Õˆ·ÔËœ–aaN˰0§eXz¦}UTâ2\ÌhY&´lŽ5ü×Ó@Y¼K9m¡»S—ÔtçO2ïÎÜc;æþGóNíÎj½¶w"¡Ï¦ý…ïÆ²—hŽ!ϵúS~xû5ü¦š$Þ]¡ÌQ¼ ç8†ß¬8o ¿Y;?³Br8§×ö€Ó[b€³Vó€³UèÈwwãRÎDò]­J¾«ÈyRðJ˜ Þ[2¦¼´0§Ý¥àUè2…à¬ýCÁéµF‡àôµ‚W:Üðì5 /<{íÚ ¯b;BÀ;3@^xÞè§œåÈ%ýnó6OúàÕ²§ä»Ò±ä„W¡ä„×rÂ+QNx½B†Ò /\î¨ß•˜$'<ïå®œŽ“('<»äS¾{Ë#Pú]«”€ç}HrÁ«ÝAÔïj¯õ»ò•”^¹ñH¿;woý|í1ÎÇG>x^̧|w_ò]9ÊȯÂJ¿ Ñ.x±O’ú]=ÍpÁóR©õ»Ðé‚wzXY¿³2,ý®b^Z¿óökéwv”’|÷ÈŸMê]¹ÿI½«h†rÀ+Ùê]m”zW¡ ¥Þ•£ðj™Õ»Sª‹Ô»rþ²zw:(Õ»(Cõ®\›¥ÞÕ{Mê]éßTïZEäì_*ªÔ»ŠÔ$õ®ÂOI½óZ¤Õ»’x¬ÞUôOªwåd+õ.÷¦z×;Sêמ­ÞÕëÈê].­Þ¹5RïÂ)ê]mܶzç Rï*r¢ä»:—今ù®´ëwĬßysˆô»ˆÝ"¯dA x)g¯ž+x~†¤àmޏI¯5¥àÕã ¯6n;K9üAÁëõ6”„W;·%áÕE·„ç}’ð*úqHx:%¼Š£Þþå‡çýÉð¼GÏžÝKÂÓ{ÁŽxv€—‚w”:G¯[O¶‚çËgÏʺ¼Zª‚—¡Y áÕvHx!½Q«¨‘öÇÛþDyB ¯W€Ix¶ÄžBq[Â+‡'JxÝa½(á9Ì’$¼>Þβ@ÂÛ+z %<_¿’ðÂ^‰ƒ’ðœÄ´$¼Û2%¼Š * Ïßc–ðì® oŒ…¥„·WhJxÞëa /¶eÊ%Ï÷Až}[³b Ï_Á’ðú^.)á•%¼Ö¾(¨ëJÂûÌO}ÅRz(áuù—”„§Ý*vÈ ’£†ç•HixÝáá¬á•´* o<×KÎæ°xôÈ르IÃSHkx&Ôž¾CJÃ+£†g_kxs jx%ãJëmËÒðB±£†×Ë!pjxfkx¯¥áÝÞH* O4ð¯ÿô_ÿÓÿÞ|Üàendstream endobj 6 0 obj 205791 endobj 4 0 obj <> /Contents 5 0 R >> endobj 3 0 obj << /Type /Pages /Kids [ 4 0 R ] /Count 1 >> endobj 1 0 obj <> endobj 7 0 obj <>endobj 9 0 obj <> endobj 10 0 obj <> endobj 8 0 obj <> endobj 11 0 obj <>stream 2020-03-03T12:13:16-06:00 2020-03-03T12:13:16-06:00 GL2PS 1.4.0, (C) 1999-2017 C. Geuzaine gl2ps_renderer figureOctave endstream endobj 2 0 obj <>endobj xref 0 12 0000000000 65535 f 0000206108 00000 n 0000207858 00000 n 0000206049 00000 n 0000205898 00000 n 0000000015 00000 n 0000205876 00000 n 0000206173 00000 n 0000206273 00000 n 0000206214 00000 n 0000206243 00000 n 0000206337 00000 n trailer << /Size 12 /Root 1 0 R /Info 2 0 R /ID [<451791DDD33DE7544780890234E0FFF8><451791DDD33DE7544780890234E0FFF8>] >> startxref 208078 %%EOF blis-0.9.0/docs/graphs/sup/dgemm_ccc_kbl_nt1.png000066400000000000000000010627631422157504600215420ustar00rootroot00000000000000‰PNG  IHDRTjûF¦Â &iCCPiccH‰••gP“YÇïó<é…@B‡PC‘*%€”Z(Ò«¨@èPElˆ¸+Šˆ4EE\•"kE ‹‚tƒ,ʺqQAYpß÷?¼ÿ™{ÏoþsæÞsÏùp ˆƒeÁË{bRºÀÛÉŽÌß(ŒŸ–ÂñôtßÕ»­Ä{ºßÏù®‘iü常¼rù)‚t ìeÖÌJOYá£ËLÿÂgWX°\à2ßXáèyìKο,ú’ãëÍ]~ )úÿ†ÿsïŠT8‚ôبÈl¦OrTzV˜ ’™¶Ò —Ëô$GÅ&D~Sðÿ•ü¥Gf§¯DnrÊ&AltL:ó5204_gñÆëK!FÿÏgE_½äzØs û¾zá•tî@úÑWOm¹¯”|:îð3™ÿz¨• €è@(U  t0–À8à|AØø $ȹ`(E`8ª@-hM œà<¸®ƒÛà.L‚—@Þ‚°¢A2¤é@F²† 7È ‚B¡h( Ê€r¡PT UAuPô tºÝ„¡‡Ð84ý }„˜ÓaXÖ‡Ù0v…}áõp4œ çÀùð^¸®‡OÂðø6< á—ð"Â@”]„p$‰BÈV¤)Gê‘V¤éCî!Bdù€Â h(&Je‰rFù¡ø¨TÔVT1ª uÕêEÝC£D¨Ïh2Z­ƒ¶@óÐèhtº]ŽnD·£¯¡‡Ñ“èw †aaÌ0Θ Lf3¦sÓ†¹ŒÄL`æ°X¬ Vk…õÀ†aÓ±ØJìIì%ìvûGÄ)áŒpޏ`\.WŽkÆ]Ä á¦p xq¼:ÞïÀo—àðÝø;øIüA‚À"X| q„„ B+áaŒð†H$ª͉^ÄXâvbññqœøD%i“¸¤Ri/é8é2é!é ™LÖ Û’ƒÉéä½ä&òUòSò{1š˜žO,Bl›XµX‡ØØ+ ž¢NáP6Pr(å”3”;”Yq¼¸†8WJ)Hq¤"¥öHµJ IÍKËIÛJGJJ·IK”aÊ8ÈÄËì—é”y"‹’Õ–õ’Í’="{MvVŽ.g)Ç—+”;-÷H–×–÷–ß,L¾_~NAQÁI!E¡RáªÂ¬"CÑV1N±Lñ¢âŒMÉZ)V©Lé’Ò ¦$“ÃL`V0{™"eyegå å:åå–ŠŸJžJ›ÊU‚*[5JµLµGU¤¦¤æ®–«Ö¢öH¯ÎVQ?¤Þ§>¯ÁÒÐØ­Ñ©1Í’fñX9¬Ö˜&YÓF3U³^ó¾F‹­¯uXë®6¬m¢£]­}GÖ1Õ‰Õ9¬3¸ ½Ê|UÒªúU£º$]Žn¦n‹î¸CÏM/O¯Sš~°þ~ý>ýÏ&   ©†.†y†Ý†iñªî¯&¯v\½mu×êׯ:Æ‘ÆGŒ˜ÐLÜMv›ô˜|253˜¶šÎ˜©™…šÕ˜²élOv1û†9ÚÜÎ|›ùyó¦é§-þ²ÔµŒ·l¶œ^ÃZ¹¦aÍ„•ŠU˜U•Кij}ÔZh£lfSoóÌVÕ6¶ÑvУʼnãœä¼²3°صÛÍs-¸[¸—í{'ûBûªƒŸC•ÃSGÇhÇG‘“‰Óf§ËÎhgWçýΣ<Ÿ×Ĺ˜¹lqéu%¹ú¸V¹>sÓv¸u»Ãî.îÜÇÖª¯MZÛé—ˆÿ2Â6¢,b&Ò*²4r*Ê*ª4j:Ú*ú@ôLŒMLyÌl,7¶*öuœs\mÜ|¼Güñø¥„€„¶D\bhâ¹$jR|Ro²brvò`ŠNJAŠ0Õ"õ`ªHà*hLƒÒÖ§u¥Ó—?Åþ ÍŒ]ã™Ö™Õ™ï³ü³ÎdKd'e÷oÒÞ´gÓTŽcÎO›Q›ù›{r•swäŽoál©Û m ßÚ³Mu[þ¶ÉíNÛOì ìˆßñ[žA^iÞÛ;»óò·çOìrÚÕR V (Ým¹»öÔ±? ìY½§rÏçˆÂ[EEåE‹Åüâ[?þXñãÒÞ¨½%¦%Göaö%íÙo³ÿD©DiNéÄ÷e̲²·7¼Yn\^{ˆp(ã°Â­¢«R­r_åbULÕpµ]u[|ÍžšùÇ‡ŽØi­U¨-ªýx4öèƒ:§ºŽzúòc˜c™Çž7ø7ôýÄþ©©Q¶±¨ñÓñ¤ãÂÞ'z›Ìšššå›KZà–Œ–™“!'ïþlÿsW«nk]£­è8•qêÅ/¡¿Œœv=Ýs†}¦õ¬úÙšvZ{aÔ±©CÔÓ)ì ê<çr®§Û²»ýW½_ŸW>_}AòBÉEÂÅü‹K—r.Í]N¹<{%úÊDÏÆžÇW¯Þïõê¸æzíÆuÇëWû8}—nXÝ8Óâæ¹[ì[·Mowô›ô·ÿfò[û€é@dz;]wÍïv®¼8d3tåžý½ë÷y÷o¯ñy02*|ñ`úaÂÃ×2-<Þ>†+|"þ¤ü©üÓúßµ~oš /ŒÛ÷?óyöx‚?ñò´?'󟓟—O)M5MMŸŸqœ¹ûb݋ɗ)/f þ”ø³æ•櫳ÙþÕ/ M¾¼^ú»øÌ›ãoßöÌyÎ=}—øna¾ð½ÌûØú>|œZÈZÄ.V|ÒúÔýÙõóØRâÒÒ?B,¾“sMT cHRMz&€„ú€èu0ê`:˜pœºQ<bKGDÿÿÿ ½§“ oFFsF×j`` pHYsNNÆÊ/¥tIMEä&>(Ê vpAg´¨“ÁQè€IDATxÚì½yœuÿÿÌ}2I ˜ƒ0&Ô„#L8k@,Z£šµ&¬¯Òãº"êÎÒýs•UP·[f³êj7²AVV2¥(*œRaä˜ W†+¤HB„©d¹“ùýñéªîž³çê陼ŸyLfº®®ë]ŸO½_Ÿ÷û=®£££AAAAAA¡GÆô‚ ‚ ‚ ‚ ‚ ‚ ;"¨‚ ‚ ‚ ‚ ‚ ‚ ô*‚ ‚ ‚ ‚ ‚ ‚ } ‚Š ‚ ‚ ‚ ‚ ‚ Bˆ "‚ ‚ ‚ ‚ ‚ ‚Ð"¨‚ ‚ ‚ ‚ ‚ ‚ ô*‚ ‚ ‚ ‚ ‚ ‚ }0&•T*…ã8#½Bø¾ã8¸®;èmyžG*•éCú@ìsìãy^»ûˆ}™äkŸ®ëâûþHï®Ð b»c›îÚÕ`ºØnq#¶9z©÷R±Ï‘Cìst0PÛlÛ)±É#“Ñj“cRP±m[Œpàº.ååå$ jjj¨­­Ôö<Ïöí‘>,¡Ä>Ç6±XŒÊÊÊ.v-ö9:û<2ÉÇ>=Ï£ººzHMÂÐ#¶;vé©]±ÝÑ€Øæè`¤ÞKÅ>G±Ïâg ¶9ضSÄ&LF«MNéŽ\jjjˆF£D£Q|ß§²²Û¶±,k¤wM„ày‰D‚7¢ë:¾ïSZZJ$é]a Ö¹$Bÿé­]5 #¯mˆí BߌÔ{©Ø§ ôÎ@ls(ÚNA„¾*¶mS^^θq㨭­í2¨Ú¥¥¥Äb1b±XÎ(×u©©©aܸqá ººšT*Eii)¥¥¥¤R)b±¥¥¥”——ç(§ýY¶7‚ídïo>ózÃu]*++7n555á±÷4½¯yùì_çÁq|ß' i7n ÆžŽÕuÝðÛì)4,X®¿ë CË`ì³'Û±Ïá´Ï¾ì¥§c ®­¦iáï Û±Ïâ 7ûMmgö¶:ß—Cm›½ÍiÛìéxûkcÙö|6 C^B‹ˆ±b»…lW{›W¬¶ÛŸvÄv‹é÷öN1ö{ ý^š=Mì³° GÛ ùßkÒïíßùêË6{:Þ¶òNZx¤?Û3Åh“…~-z›ìålܸ±èˆÇãÑh´èˆF£mmmš¦u444t´µµuD"‘ £±±1g~°~ccc‡¦iávƒíÄãñ.ßcšf¸ýY¶7€ŽH$ÒÑÖÖÖÑÜÜÜ¡iZ¸¯½ÍëíüÇì‹®ë=Nïm|÷?ŸóL&;LÓ [–•s,=kcccμàzó‚íG"‘Ã0:ÚÚÚÂëÚÓzÂð1ûìÍ6;:úgsbŸý;}ÙKoljD:,ËêH&“–eålS쳸èÍ>G[Ûl«»ûr(m³·yÅ`›=‡D"Ñëz½Ùgsss‡®ëmmm¦iŠ]cÉv Õ®ö6¯˜m·±±±Çv5Ø®Ønñ ýÞÑÙï-ô{iG‡ØçH0\mgGGþ÷šô{3û>¶ÙÛyHÛ)串Eú³½Ÿ›b´ÉB¿‹»MŽzA%vD"‘œiº®çÜ ÙFÐÖÖ–cˆÉd²Ã0Œœõ#‘HhÌÁ…ÌþÜÙó]¶7€œÎVv«·y=Ç;,ËêrÎzšÞÛ:ùî>ç!8¿A£|Îî”tw¬uÞ·H$n?‰thš–³~oë ÃÇ`ì³7ÛìèèŸÍ‰}öï<ôe/½kÐp¿ƒuÄ>‹Þìs´µÁ¶º»/‡Ò6{›W ¶ÙÓyH$½®×“}¶µµuèºÞÑÜÜœ÷¹†Ÿ±d»…jW{›W̶ô‘»kW³¿Cl·8~ïèì÷ú½Tìsd®¶³£#ÿ{Mú½™}Ïç<ôe›½‡´òNZX¤?Û3Åj“…~-v›õ)¿\× Cùt]ÿö}?'Œ¶ó²žçáº.ãÆ F:„¨ó>æ;¯;|ßÏ9ñx¼Çé½­3ÔèºNCC¦iljD"9ç¾§cí­ižçä„äuoëm=axŒ}£mvÞÇþÌëŽb¶Ï¾ì¥»cM¥RضMss3ñxœ7âº.‰Dû,6z³ÏÑØvv·Ÿ}Mï‰Ø`±ØfOÇÛ×zÝÙg"‘À0 |ßÓ.¸®+ÅsG˜±f»…hW{›W̶{Ï=÷ôÚ®‚Øn1!ýÞÞ)æ~o!ßKÅ>G†±Övv·Ÿ}Mï‰bn;û²ÍîŽw m'È;i!k6)ýÙÞw ï¢ù~ßH1ê•|rŽöv²5MÃ4M:T´Nø37^±à8{÷îívzOy%{›7LÓìbdù>d:_Ïìý2 ƒd2I4í’ƒ±·õ„áa0öy$Ú&‡}ÂÀìÅó‹‹¾ìSÚÎ\ú²ÁþÚí@¨­ôµ^Oöéû>‰D‚D"çyض“7\(ò‘n§¦žæ †a„ª2¨ónÛvEµ;<Ï ¯c°žiš@¦F£èºž3 ¡·õ„áa0ö9ÖmŠ×>a`öØu¶3Ƕ휂€ öY,ôfŸÒvšý¶ÁÞìv(¨­ôµ^wöÇill  à é—•Ñ€ØnÏŒ5Û=ñÄ{mWAl·˜~oïk¿·Ðï¥bŸ#ƒ´=S¬mç@ms m'È;i!›ì™bµI(ì»è`¾¯Lé,‘H×u)//¸–e…ó ÃÀ²,*++Ñu½‹š¥ë:Ñh”êêêp}Ó4s¶1š Ž%8?®ëÇ{œÞÛ:C‰¦iÄãq*++1M3<ï‘H¤Ïuu]§¶¶]×ÃñÑh´ËC6Ø~p-{ZO>cŸcÝ6¡xíf/AÇ'ûz†!öY¤ôfŸÒvöß‹Ù6û»^¶}æ3âZ(,b»=3Öl÷üóÏgûöíݶ«Ý!¶;²H¿·wеß[è÷R±Í‘AÚΞ)Ö¶s ¶9жsáÂ…òNZ@Ä&{¦Xm û.Zì69.]4fÔãºn˜g/[ó}? ò}Ó47nmmm]òÖzž‡¦ic²“œ]×sýž¦÷5o¨èïyw‡D"Acc#Žã ûzÂÐ0ûë¶™}~ŠÅ>k/…²kahèÎ>¥íÌ=7ý±Áb´M±±±‰Ønßçf´ÛnÀX¿^c é÷æw~Š¥ß ý×#i;û>7ÅÒv ô¼‹MÄ&û>7Åb“…~-v›õ*=Tß÷©®®¦¡¡Ã0ˆÅbÝæbÎ Àó¼^ %™¦Ù¯Ð¥þl¯§óÓÛ͘=o¨÷=`0ç} a^Åv$1û¶Ùßm«}ëö—‘°kaàtwŸå¶³?ÛÌ×{›>\ö)m p¤ÙîP´«½Í+fÛ-Äõ†Žbï÷BqÚçH÷{¥ÿzdp¤µýÙf±¶=ïbÓ£ƒ#Í&äþìH¬7œŒA¥'t]'™L†ù×t]§¡¡aDö%Èw×Û¾ŽäöŠå»úÚ(’Ŧd Šb±ÏḿG³}Ú^Ä>‹b±Mûì¼-i…Þ˶[è¾h1Ø®0¶û,Î}Ì~ˆ] Ʋm×6‹á»†±éâa,Û䑨Ÿ«ï°c&å— ‚ ‚ ‚ ‚ ‚ Âp1~¤w@AAAAA¡ØAEAAAAA¡DPAAAAAAèTAAAAAAú`Â7¿ùÍoúKÛÛÛq]—öövæÌ™“3¯µµ•––fÍš5ÒçGŽ(z³Mû„‘DìSŠéÛ Bq"m§ /bŸ‚P¼HßVz§à‚JKK Ë—/çµ×^cÍš5¼òÊ+\pÁ¬Y³†k¯½–×^{üàÌš5‹¥K—Žô9„#‚ÞlÄ>a$û„âEú¶‚PœHÛ)ŋا /Ò·„¾×ÑÑÑQÈ/4M“+VpõÕWÓÞÞÎòåË©««ã /äì³ÏfÕªUTUU…ì8eee=nïœsΡ¢¢b¤Ïclß¾¹sçŽônôÈÞ½{Ù»w/³gÏé]é‘b?‡›7oæê«¯æ“ŸüäHïÊ èÍ6~Ûçw¿û]ÇaáÂ…#}h=Rì÷ÖŽ;˜:u*S§Né]é–Ñðühiiá‰'žéÝ4CmŸøÀŠÚ6Gý%ÏÁ±sçNJKKùéO:Ò»2hŽ´¾m¾û=ØŠÝÞó%ßk"}Ûîíó¿ø·ÜrKQ·Ÿùr¤ÝÓ£|¯‰ômGgß6_FC8_ÆÊs&ßk"}Ûžû¶gœqgžyæHV{[2ž Ånï/¿ü2ŸúÔ§ø§ú§¡ÛhGyôÑG;*++{œ÷Á~0gÚÇ>ö±Ž;ï¼³×m^uÕU…<„~Sìû÷è£vÜtÓM#½½Rìçð¦›nêxôÑGGz7Eo¶Ìï¯}ʽ5xŠýÞ’k\†Ã>‹ý¼È½5xäùQ¸ã8Òú¶ùRì÷`8Ò®ÉX¸vGjß6_Ž´{z4ï5 ×îHìÛöçÜÈs¦¸È÷šŒ•k7}Û³Ï>{¤«Wн- ÷V±Û»eY·ÜrËnsb!¡ÖÖV–.]Êš5kX»v-%%%¬X±"T6;+š³fÍ¢µµµ×mnÞ¼™•+W²zõêBJÞÔÕÕô.ôÊÒ¥K{U’‹b>‡+W®dóæÍTUUô® ŠÞl°}Þ{ï½@ñ^Ãbݯ€+VuNÒb~~´´´P__ÏöíÛGzWÍpØçöíÛY¹r%^x!+V¬éCìB1ß[òü8kÖ¬aÍš5œxâ‰#½+ƒæHìÛæK1߃ý¥Øí=_ò¹&Ò·Ý}Û|íûp$=g‚¾íæÍ›GzW͑ط͗ÑÐΗ±òœÉçšHß¶÷¶sÊ”)¬\¹’ººº¢ŒÂ.ö¶d4<ŠÙÞëëëÙ¶m‹-Òí\Pijj¢¤¤„«¯¾š¦¦&V®\‰ã8ìܹ³ËòùÜ0 .,êÎb|XdSRRBIIÉHïF¯ó9\½z5õõõ#½ƒ¦7Û,++°}^|ñÅEý`-æ{ ò;Ç#I1??***X½z5+W®é]4ÃaŸsçÎ-ê¶³˜ï­y~ œ+VPVVFSSÓHïÊ 9û¶ùRÌ÷`)v{Ï—|®‰ôm{§Øû¶ùr$ÝÓ£…¾®‰ômGwß6_FC8_ÆÊs&Ÿk"}ÛÞY¼xqQÛg±·%£á¹PÌöôÛ¦OŸ>¤Û-¨ êF]µjUUU´··³fÍšnÕÀÖÖÖ¢¾(‚0–èÉ6ëêêÄ>a„û„âEú¶‚PœHÛ)ŋا /Ò·„¾_È/«ªªê¢ªŸ+**º„‰íܹ³è•BA ôf› ö)#‰Ø§ /Ò·„âDÚNA(^Ä>¡x‘¾­ äGA•¥K—ÒÚÚJKK ííí¬]»–²²2ªªªØ¹sg"×ÒÒBkk+]tÑHŸ#Aóôf›€Ø§ Œ bŸ‚P¼HßVŠi;¡xû„âEú¶‚MùURRB]]Ë—/§ªªŠÖÖVªªªÂ¢auuu\{íµ,]º”õë×SWWWôyâa,Зm‚ا ŒbŸ‚P¼HßVŠi;¡xû„âEú¶‚¯¡²bÅŠÐ(gÍš•“k/{^YY™„ BéÍ6;Ïû„Â"ö)Å‹ôm¡8‘¶SбOA(^¤o+}SpAèÕèÄ aäèËþÄ>aäû„âEú¶‚PœHÛ)ŋا /ÅÖ·uÒÿâÄGúÔPà*‚ ‚ ‚ ‚ ‚ ‚Ð.n—i>~¯ëxx#½Û„*‚ ‚ ‚ ‚ ‚ ˆ#ÖeZo‚‰ƒC-µ#½Û„*‚ ‚ ‚ ‚ ‚ ˆ"‘&£‡D\wðÛð»eÜ^þö),"¨‚ ‚ ‚ ‚ ‚ #Jw‚J0MÄ–¾±³T /}º²Ešš¡û.ßÏ|Ç@pœÌþº@ª—eS@,½ŽëBuÖ¼ºÃÊ TAAAAA„¢#RbÄppºÌ﫾ÊXÃ÷ÕO,+3šm+¡¡¶6#tÄbjzuµ"´FaK&pÖ¹ðB6? Ïû°â〠ÿ‡û¿ßú/Ø‘€Ù¿RûçÇ}Ú ˆÇáÌJø»¬òáwÜ”‚©|*¡ö3™TËÝåÁ6øpÜ›ø>œV­Žk‘¸ðŒK¡É…W=8' /xp¢§ÔÀ%øN#HGÇr`‹ Õ(ÑäÇŸƒß/'¾{âJ€áªAØW¹j_‡TA(Z·U„È\KíÛÂFxƇ+áG‰//úpЃɖyà~¶%ào)Ør\ÿMxg#Ä¡=';pT#|öOð»:hsàÌ8ü%ÇÏ‚+uøW.ý<¸„©hQXü¼ÆÏ‚ Æe¢y–ÛLðm¸Âƒ;ká9à­·f ù})‚Š EGPÏÊG=À]”ºA +:*—bCzº›þ±AEAAAa¬-¨¸éÁßá2ÄŽðã øÐ¸q¸®›#¨x¨è”ÿøõ¯ÙÏ=Ý~çïöìaë´i9ÓºY²k‘¨ˆ“ÜíTWí·N Å‹K×qxÌ…Éóvãy?ýýV޳à€;°_ƒGÿG}9.j‚­:Lú<œºüàÀïà=„?þ8{àc¿‡iMð“³áçÿÖÙʇ¿ôŸ«}‰´ÃIAßo|î~|&¼ ¼nøÌ-{=xl h“áUS¯×4°ã0S‡Š´È2{)¬: îЂk£Ro °# ‹Ï„ýTYgb¨t]s}h­…/†Ù?‡ÏÀ¸éŒô…iz bšZçŠ'T„ʇu5Øú¹xm#ø“à†($« kvÃ5RËîsáÑ$Œ·¡á¡‹x饙Cz/Š "BÑQ‹zP?>êÛ#=ÏDE¬4’^‚&4Æð£AAAAGwæÃi¶Å‹þv^´OåEûÔ.Ëþû¿€tå~»{7÷:DÛñdzæÌ3¹ë˜cÔ¦Pþ¢çN>™ÇÊÊØ3>_Ú²%L#ïßß½›­Ÿù JJ%š¨t\.±X,'µXMMf‚”]åå™i¾ÍÓ¦±û Ù\ƒß‚3à˜Ýͤó~Çö‹¦óZ¦$aKævý®*?Ä…;O†š@ëU`݉(œ½~ò=¸þ×`ÞS¦Bûøh=hí`>ºý#µ˜Á¾DÊ…ÿš^ ÔÜ«¢X˜ ã.VËLbÿüD-0ö¨sfݦ¿ŠÂ]ï†3Ž÷IøÇWAÛŸöÁm‡ä5꫾x4Ü‘}ûˆz@܇¯{pÆîƒ&‡†ïÀ/ÿçwXß}NÕIö@ó!ê*1Ȭ„äÑð‰rµMM#¬`ÜÚ€÷@ü:ˆV¥ëÐèpÊQ°eÒŽ­Ø;¤÷iÁ‹Ò·¶¶ÒÚÚš3méÒ¥”¤oÎ`~YYeee…Þ=A8béË6³—Nû Dý ð<¨‡vwåÄtÒý¬Ï™‚õAMîA-‹} ‚ÐéÛ Bq"m§ /bŸ‚P¼cß6HûUšŠÑª­6;'0UÛ“Îg¥Ñî€ lÚ´˜Nø?~â &œs/LŸÎ 'Ÿ ÀöãŽcÞÁƒ€xûäáôík$€Ùmm¬ž3‡B¥æòL“¯Oœ¦ÉË›6*ò¡©i¦i2ýýïç–sÏEGùœ\Wýüìg[Ø·oû˜Ö=q]˜¼ë|ySøõ$À€w,8¹í¼ï&s1ÏÜ:ó  ƒþQøÌ*øÊ®|äÛO³ì¥eX—€ý{¨8 æCP{3$¿X`ÝêÂïu¦†ù¼ÚÆÆUÀú Ñ†÷'•£ÌÁrÀ¹’µ±ÕþT8 ¨¿_©ßC«ŽÚ§ v2lü Ð f:ûTHñ$wCb2ø»Àº˜æ™ÀaHÞ¾žªU…^|Ð=øð½><™À8Ï„µ÷Ã4+“¦ærlK)4€ùY †¥ö•«cpK\9ýtµ/hêø"6aeú÷m‚·—mò{²à‚J}}=k׮͙¶zõjªªªX³f õõõ,]º”õë×SWWÇŠ+ ½‹‚pDÒ›m³OõlL¡D3=]ëfÙH7ÓÒb{X´>Ê“ Âè£XìS„®HßVŠi;¡xû„âe¤û¶A=-Ëdbò8p0ýyƒ³¥ÿ‚††ï¦Io¿Í¬Ã‡ÙœñÊ+´œr ¿Ú²…›/¦´½ Û·3é7sðOž ‹TÔÃ#ëÆQù¥±äsŸãg(ßÓ ^ºÞ‰7¿v7‡¦Çã/œÀ.SÕI9ûìM”N.e÷ԙ̛w˜×gïàð/frþ܉<|Ã$êþíMZ7i¬yÎ=¶ÉV°]—¥SOÃp XÆ>°§‚qJÏÙÁ1Þ;˜ëf–YО€³LŒÜWÞÓ÷ƒ¡ñöis8üøJ">ÔxðãèÞ ô""KQ‚„î©`lƒþ)ÐS*ÚÄx/ðè3@¿xÔ‡ûp~0Mµ¾V«j¤ð à.lHmÖQá"¿nr ª£GtâÞ<˜–žŸtT~0Gm‹?§à¹´Àb‘e]Ô9°)žFD9íôEÕlU8Åîѱ^obú³osÔÁeCzŸ\PiooÏi(³©¯¯gÕªUTUUÑÒÒÂòåË©ªª’Ñ‚Pz³M(œ}‚9t•ÒêY›"™"‚Š0Ú)û¡+Ò·„âDÚNA(^Ä>¡xé¾mv]3ôÁo”àm&Lþ‚Çk?ƒÙ¸•'õ·xWôN.[p.¯½v oþ0—LÚ‚,zòI6é:§¼þ:î믳éœs8–´ òÔSœ:mŸX°€oFçÀ‚WyeÁ&}c2o<ÈÙ7ßÌÆG¿É ߆w¥àŸ|h=›—^Ê`ü¦M4þ÷"fø UÃ\xõ3æ 1•à;°ß†»§Mãü¥3ùúñ\~æx™úKŽÚʼnþD¼Ö£ùLÇVžß±ƒ?Œ[̵«À?¶'¶Srò›üzÙ$^þßç8K?K¥¸ú¸Ï|ˆ¯=u=_­ü5ý ´UÂANPÉïý …ݦɿŒÄ³Ÿ%®¥CMÎ÷¡¶–h2 ߯…úÜl(AdÏ>Œ=ÀT´UÅ ¬Oƒ÷0?JÀCœã‚‘»õ`•€îÃR:ÌôቘRWþÙ‡¸¦rûïðà¾0aBž‹Áv¾çÁ|®õa2`i°^‡ufîhjxF‡o4@¬êL%¬$I§ºÑ¡­n4átcÿ—X÷áX_·]¿)x •¦¦¦n ­©©‰Y³f…[QQAEEMMM…ÞEA8"éÉ6ƒy…²O%‚ć`;Á¶a´S,ö)BW¤o+ʼn´‚P¼ˆ} Bñ2’}Û :ÅH{rüNÃcïœÅÄ ¦²¾ç!ðt¶»—qÂßÄþ£_dË–ß2÷¼ ðáž 0=“&MâÁÖV>ZV†L~í5"À-›6±åþ_sšÏ?ø.¾ð3Þ4ƒwœËdóaîÜp'ÇN »7ÃŽ¤â`Yœ>n»×¯ß'‹áû>¾ï³{xæo»T8iB“ [Rª‚»f£?÷gxãE@‰(ÑBC AdÍ·ˆ¬Á[6œáÀWå@X·§à5.rTî3;%2Q&ïÒa¢§„ ˜‘^î-]¥$Û‘`ãØþÕí0SƒÅžP<À¶9<{6|Þ‡ŸèpƒÍÍðXéêËQÔö>S"ðst‹Ùmg ¹TPiooàúë¯ç¤“Nâì³ÏfÍš5´´´t1ØY³fuÉÛי͛7³råÊB† „¬\¹’{ï½w¤wcÐôf›0pû¼÷Þ{©¯¯ï×¾øä¦÷rpº4¢ù`õ{ a,ÑÒÒÂÊ•+Ù¾}ûHïÊ ûܾ};+W®ÌÙŽ Š UÀ›o¾9Ò»2h¤o+Œ5¤o;ô}[A ‚¾íæÍ›GzWôm…±†ômóëÛ¶´´ôùýAtІ†MŠÔ4„ó'üÃŒK~™×fµ²k¾ ‘ÏU^áÇOáõö~|賿ðŽúD;³ÛÚ(ÿå/ùÄ„ ,++Ãôuî]¶Œi[·²ÄƒÿþÎãÌŸÿýpÛºžý!Núë»ØôÕSq]H¥TM–ñŸ;ÌiÔ”À¾o½‹Ûÿ0ŸEõÐñÒÑ”úðÖ«‡Yð\;;¢°é“8mßs|ð„")Øñ,œºb'§¬ƒÛÆÃ²Ó–1ùäÉÌýÆ\N{æÛüòKãÁ‚-ó¶pûÆi*㇠~3éTÖTœ‡_ý ü±<ßwø·Sáç7ÜÀ¢E‹Ôηzp†¦A¬ý ünÕ*°m,ËBÓ4|ßgê¼×™R} oÿÏÿððõ׃eÁ‚ü,ÆÏ¶lÁ?úxŒu¨4iN-X>.$ªÑ?‚±Î*> 46‚ïýâ;èQ \—í•Çqø¯ßM_PJØêAª’?Ÿ7?û=XWŽ?߇ÆFn¼ñF]²Z[WóFÙˆþ©vyà×âèíõõüâÝ%ç¢išsÊË!‘PÓׯáN6<±°Žç}~Èm¥ ‚Jkk+UUU\}õÕ¼ôÒK¬ZµŠúúzšššØ¹sg—åó [¸p!«W¯.äaBÈêÕ«¹øâ‹Gz7Mo¶ Ø>/¾øbêêêúµ/duB‚Dبö‡(ªÒ`k £ŠŠ V¯^ÍܹsGzWÍpØçܹsY½zµä¢F„+VPWWÇ1Ç3Ò»2h¤o+Œ5¤oÛ;éÛ ÂPôm.\8Ò»2h¤o+Œ5¤oÛ;Aß¶¢¢¢_ûâá)_.{ðÛ%íïã­ÿGÆi¾Jõ¤íá©Gæ3ñ”gØuá…ܶh¯Ê¼-[hL&¹íæ‹q]UËDN½ñF®ª„×_„åËKˆÅÒeVÊ ±q6Õ<ê[Ák†–me꾃ò`Þn8áðL q?üsÇz‡Ù¿o?3Þvù¼½“ØœuÌôwÕîÂ8Îú+,=´”ê¿¥Bƒ çL€œ{ÌëÊfÁî%»yæÄgà÷>»_ù-¼þ:†®Ã2¸tòV˜è:žçqVCŸ|2 ¶mcÒÛoóÜäÉĪ«I¥R¸®Ëä“OfÒ§>Eû­·²ý«_Å4Mb±³¯<‹kž¿›Ë–qã_þÂÎϦ ëßÖÆþcg¢=÷ÿúž÷°§¥ª«•(bê7@4ª¢[ ƒÍ›7sè7_D×|°m|æþ¼d‰R¢t]‰.çh𺠮Ëô/™i‹'¨­¢ðÎûÞ¡ýœv^0—rÜ´í´ml¤ê{×ï"àºl´,>pèï|ñ‹´O˜ „˜l,+uaTNÊIáhÇ^zìÛJA• „‡UUUqÑE…acéKåahèÍ6‚ا TÒ5E—‡þí§ÿ僆T$å—0Ú)û¡{¤o+ʼn´‚P¼ˆ} BñRL}[Ÿc¸o9g¬ݴþj‡Qüq•Œ;4"OpÊ9ó™{òÉL?xýý(–e1iÒ$låÏÇuaÏžùø>45-Ŷul[6xOdüô¦ Ž ÚaøÞºRΙ÷çøà¾ŸšÐJ¢b 8xà(æÿ6óLåãKÎáǵ³ø»ý¹hâI”l(Áx¾øëƒ¼3éôJTñõ(ªÞ‡ÌÖ¡Ù×Å0 ?ý¿áÏ5ÿ&•ãÆAi)wß|3¯MžŒ£ilzê)ê}ï?;~ùK^X°€¦+¯ä¾eˈ¥RÌ™3‡ËÞÿ~ž3‡…Ë—óÆoðîÓOÇ Äx˲H$D£Q~ò‡?@ i<ô›ßðî_ü‚·?ûY®þàyíÓŸV)µ‚“b˜9“M;wªäylž0Î9š›Ù3>_ûÓŸ8ñ“ŸTó-%„ÝýéOó±ûîà ‘HpÍÃ×ðô9O³óè§”P“¦ä‰¾ô³Ÿñ‹óÏðÑ•+q<½ç‡‰L&ñ< uu iá1yž‡|É|]§¶¶ß÷qÃ0X°` 7 ý`„‚G¨tñ*))”Ñv6Ä;wJÑ1A(½Ù&Æ>cÀ\<ªÒ‚‰‹K‚DŽ ’Hÿ„#‰b°OAºGú¶‚PœHÛ)ŋا /ÅÒ·ÕÑññ9´»'€¯qŤ*øÚ‹Þ9žñ3¦2iâDø×[!~3®ndbi)Ó§O' ̶Ïó°, c†Ú¦¯‚(X·®œ%Kv3}Òûà Ó„Èbˆ¨€":øëÀØsÚ'ѱþ,Œv ÆÏØÄï”P“‚}ïÚÆ[Õ]ÎÏ_ØP²ù{æS²ï»Üõá»Ð+ᣛÍ'¾Žw4ô3uG–éð~G…ϧ½ô¬sh?¸™“_{=óçsÙôéÔŸp¿8ê(¦®Z…üKI -·ßNÓ¾}ÜqÇÿÁ2ûøãù—ùÆ•–òût4Ð?.^Ì ï?Ñh”h4Jii)›7oF×u ÃP¢„ÿpÊ),xáîû¿ÿcË%—p]BÑ÷A×ùó¼yüiçN®½ôÒôEÒÙþƒò}\ß§ãã§±±‘/Üz«:¡iÑã‡wÜÁ×ÿã?ð0M“ÆÆFî¼àNþðÊ+ãy¦iBâiÁÇ4M’É$†að›9søÁ¾}†A4ÅO×…‰Åb¸®K,£¶¶–é_þ2•••hšF2™Ä¶m|ßçÀ˜²eÊߣTššš¸öÚkÜ|ííí¬]»–²²2ªªªØ¹sg8*¡¥¥…ÖÖV.ºè¢Bî¢ ‘ôf›À°Ú§ ãTBýq$˜Žj\|ü.âÉ@j©Âhg$íS„Þ‘¾­ 'Òv Bñ"ö)ÅËH÷muT (-]YwWzú œÀóÏoeêŽR0áàßuÐqü&î?ŽIqƒçP™Jâéu,¸ Ã0HÝ f© †H¥`Ñ¢W8ûÐN^ÿÛ)DÎëT5ÝߥRE£à6€óXûÀü´Ç¯N"ò&4|Cm{üâñ$÷¿ëINÙû:~ćÔд¯‰—z™£¿Ìg<û¬¥–åÄ10°q†ÓÁ —qq11ÃßýÅé÷‚P<Œ¤} ‚Ð;Ò·„âDÚNA(^Ä>¡xé¾­Žž“¥äåtEÜ=Î2¶/düQUª,Îb›p™ßÜFkU)%dR¾×Ö–²yó•ø æFˆ~]i¥n`ó^UïFHäD6Wƒ®;À]f lÚ9‘gßûËf.Cû °@}QdGû†o³zܧ0£×‚­ó³CßçŸßüLÜýWlÛ¶Í[ûßR_ðÐC`PÊNu5G½õ29ô]nݶåo¾ÉOúS¶M™Â§&OÆ¿øb¦®_ϧW¯f†®SS[ËæÍ›ùÝý÷ÓðýïcY¾ïSQQÁ‰'žˆ‘Nåy^Éá8š¦¡ë:Žã`š&–eqë­·†¨¨Ïó¸9-ÄÔÔÔ°qãF<Ó䆯~•/ΞïûhšòÙÙ¶Mcc#555èºN$ …Ÿþô§xž—‰2 |ß÷3øÞ ¤¡¡˲ðè퀭„ÿàJà©ôF“@-¬Û¾ŽK"—@BgòÜ×xã£oðÜk¯qYi)»Ú¿Î®óé»ï†ª*æ<ôPx\»×¯g×ùçóÆÉ'sÂóÏóô s“O>™u÷MŠïûD£Qn¾ùflÛ&’L&UlÝJ×&Ñ4K.¹„]»veÎ[ZPÐÒé¶!"TLÓäꫯΰu]çÞ{ïŶíð{@ExÔÖÖ²sçNÞyçPÌBÅqJKK¹îºëÂïR‹-Z´(\^Ó4n½õÖP¼ –5 ƒd2Š4A4Mö¾ù ÐÇb±P˜1 #G¤éö^Òu-4Ä\P•w¯'¤±„‘£7Û„á±OŸ÷á!‚‹‹Nû*..V—´_1bXXR~^㌄} ‚Ò·„âDÚNA(^Ä>¡xé¾­ŽÎ4Ð=&\ù$‹}‰£/ü+Ç ýp; öíæ:“'O¦¨&#¨8>ð_ MÑž.4ÿ\}t3+w•ñ¾ŽIª@¼f¥¢$ 4 \[mpÚÚoñìI,ó–ðð܇UÎz¦ê§ð…‡À¶ùúĉüs[§¿ý6‡€i{÷‚i²è‹_ rþ‹üõÁ¹íä“1M“wýõ¯|âúë©®®&ÚØÈÎgŸå•úz–,YÀ©§žJ4Í9/@°bÅŠ0µ—뺡0ÑYd°m;\wñâÅ]¶s÷Ýw«âîY(x³zõêpûáõÑuâñ8ÕÕÕX–•ˆ@—óÍ7±m›ššCñDÏJ–J¥röMÓ´p:Ÿ“|ØQºƒ™ÌÒ{´ 5TA² Ä‘Gpy9+W 5889"‰ßmtŠ›þ'‚ ‚ ‚ ‚ Œ~&¥ýAûæ½›=oÍç¿û¥¥¥pÆ™;yrÚ çss’ø`jXþÃÀ6p=0¥Ÿtì<‹wöÏU¢ˆØ(1%‚š¦©¿-ÔôIíÏò§M›2Ë€*ºr³§ÒwÙ6ÛÝK–ðȹç²öÝïf]"Á—_ŽgÛìš8‘«þîq®¿uŸy]×I¥RÌ»í64MS®³ì£eÚ´iaº®|"Q‚ÔXÙ†—®ËbÛv¯QbYVXà »¿ñ†ŠÀ ÒrD"jjjp'üß÷I¥RaMö~‚eLÓìuìG¶Ó¾ïw»~gjkkÿßóà{ò:ŸýAAF —)ìã¡£‡âˆ‹ÖSÂt`#T\Ü.©ÂºcP‹ÔSAAAA(V44¦¡ƒ§ƒ7éîb ÄbárVw+»`Lc¤ÖÛ`ãÅ€ Z+l:8ÎBÕb1ÒñÓšÁ&hHBLœ8‘·'©Ô`hlØ ŠÈO÷ ‡¬4Y/uÿ9gëÖ­ã‘©S©‰ÅxiæL¼­Ç2kR+ã?ÿù°Î (¡!‰tw}¦² –q]—D"A"‘ȉæŠÅÇb±.)9§+-rt:n¿ývÊËËÑ4­K*® è}°“H$Âz&Ùtwá$ØN*•êVDò}ŸD"Auuu¸ ˲0M“X,F"‘èV\ „|…© ‚Š #Ê 4æ¦ë§éÝE¢ó³Å?ý¯Ë²YúŠëÂ5.tK|5ˆ@AAAAy||R(§üF6b`°€Gkó@ßÃîj¥¤¤PBÁQG¨²&9®þà‚7h½TMÖO%-ˆ(ÝDŸ—^Þ"#¨¸©ŒÀòŠ i ¢¤¤„ĺuêƒãðáÍ›Ø÷•¯5 0 6~ðƒ˜¦ÉÔ©Syå•WX·n®ëâë:O,_Îä}ûøçk– G£Äãñ¥­êñÜù>ñx¼[!öm6nÜØm±ö×uÃZ$Ù"O?ý4?ÿùÏs Þg¯ÇihhÀuÝ0ĶíP Ê3‚u=ÏËglÛ&•J‹Åº ŽãP^^N*•ÊÙ7ß÷©®®FÓ´PpÉ&‘HP^^ž3í·WüvÈÎw€*‚ Œs±8µ“(!¦ÿÒШ -GTqÓi‚ùžŽÕÕêw,¦~ß“‚𨗂GÒQ¾Y€‚ ‚ ‚ ‚ BÉ®¥ °ÝnÃÇN³}K—²xñb<” 2iÒ$´ÎòÕDãhÞ æ6°–C˜%^ƒ¸ úW€j<;“ÊËVß ìÍòQyG<¨Ò|E"LŸ>4)ë×3þ|<ßçðþÀqù K–,ásŸûëׯG×u®¾újŒy[ðµžEÁÇ1M“†††±B×õ.©·º=÷éMÓrD“É“'óÅ/~‘h4Š®ë9ó‚(]×C¡#•J¡ëzu\ S%ØV¡ŸÏÞÿD"A$!‰ä*AL4í6}X*• ×K¥RTWWsþ½çùyAE„c=>ïBÇÁ ”Hú_P>¨£’¬’J|üPP9àϤ¼\µo‰„V‚¿}_}ö<õyOº ÚJÇï9P ¡¬“JåF¹dãºj]ÇQÛÎÆ÷3"N ìÇbáÆ÷Õ>Û ¾Çqr¿Ï¶3ûçû™m ‚ ‚ ‚ ‚ ŒE²ë趺ðö×ÿ¼iL›6 hllìy*×;€qŒ§§›(áÄB‰(÷²D‚tY&pRFü¨1 <¨–õ<~Y^ÎwÜÀÌ™3q]—£þö7f<‡bëÖ­9¢‚a¸ÎÁŸJ^çÀó¼~¥ªê)ÚÅ4ÍÓ‰u&{³‹ÜÇãñ‘$ ˆjÉ^?‘Hä"×1M3<ây–e‰Dº¤% "o¢ÑhŽ Ò9Ê¥säŒišaÄŽã8yÕe‡e«‚ yð2.ËI2‹(ª„”]üAãˆ)..Q¢ÔÛí¼™L’IˆF•ašJÚ[ÇopI ¼£ÃžlAe‡´]9Ëe»è€О`’‰Jѳ~ÜôŽr¶d’ 'F×Z–ŃO<ÁÃ×åá¹s99aû7òï~—T*ÅîgžáCŸþ4oØ@uuu—è ½bÌìû<¸®Kuu5¾ïçùD§t&RSSC2™ì5MX¶Xˆ$AdHoëë5N à ™Uƒ&;b¥s=×uÚ.Áùí|ž}ß× R‚´ÏmgÖ“³ jP§4TA||¥ÿn ï†b}ì ˆ¦üòðÂ÷$so&k‰¸I"Õ&ÖÔ(±#Ó„©…W<˜Òo¸°h‰ÀüÖ‚'mØ?¥£Z‚6VÓ”˜’L*Q#Ɉ$ ÄÛ†ææŒ€’J)Ñ$øÛ4ÕO°@TF3Q-®«ÖÑ4µ½@I¥”â8êÇ02(º=¿~fý^êõˆëªï„¾HÀÇ'Nœ)lliü†AAA„1‹›S÷„àÁ¡WŽ …”ÀEºB|ÀF $³€F (ŸÑT£”Up>ø ÀRÎPbJà ÑuåD‰ÅÀóHx»§OçM“øC¶lÙB*•¢iãFnN‹—TUñ×­[¹ñƹýöÛÃãD‰h4¿®mi'–ëº]"<†‹ìhÃ0hhh ‹õ(ޏ®›#¶hš¦åêmŸu]ωBI¥R]¢‚Ôb¾ïwKI$9)½}_°~4eóï7s<ÇéyAE„ÁÅe&ùOìñæó·ÔÇð£ÑT}•©pô–ÚëÑ?L kkZ&B¤3gÀ-&ü'J0¨6TÔçd¾W K6Â75¸³Vµ­¶‰H1 5-hs C‰%ñxF$Ñ´Lê/ÏSÓ@ýmšªµ¬Lc´'@¢ëjßu]‰5Ùß©ëJTI$Ô¼ææîE•DBíwc£Š€ÉGP‰ÅÔ:ñx&¥ÙƹÛw]uÁñ§R™ÈáÈÂÇSðÙØèéÔ})R9aAAAAÈ×…ÍJ9n'ìšÁBŽÊY&Ç”BE©ŒCår7È(/*Z%][…îüïååÊùÊÑâû9)GLË¢±±ÇuÑž{Ž=‡ÓØØ:öãi'ÊÄÊJ’³gsî¹çfö3íøéoÖcG·†ÑmZµàx}ßÏT‚HšÞ"Z¼NQ?¦ibYV·‚H,²¥s 0Ã00M³_)¼‚”eÝÿÇ.8vHÏ“ÔPaDððØôÕLx<íN`¾Ù¢Òe¡£¡ac‡uW³8,\Гˆps²2i37¢ÚÞ,XÐ45ýé”3‚´[Ým3H‚ Á€†@TÉŽÐŒÇsE“ε^‚Ú*IÖy ò%•‚ÒR%†¿ƒm46fÖóûðo§S’Lf"e‚¨˜ìÔ±X¦FLP“&Ø× MY*•IC*Œ]bÄH‘ÂÁÁÀÀÅ%FŒ$IttUAAA„~ãûpÀ*å÷3ýôƒ„É«Ú!çU3øÛ¢œ9I2ÂI%¨£oƒ"¶ÙΖ eH0ßóh?çÞw÷ÝìÙ³G9tÒNž {ˆe±±­X,Ö«°PŒä#Þd¥RråCvÝ“lñ$wû½º®‡ê»ûŽH$Òc͘î ×ßùæì=vïž7‰P¡àxÀµx›“!³{jkaš~)GùïÆ¶•ha` ¡…õV,KEyzx]„•îÈþÎl=¼L­²#7â”hÐÐà‡A*•"â8nNQ,×uÙ¶m)©Ô’I¼Ùù"}ß fÓƒš'A;“i×]|ß‹“E"AبRx"%€TVvr,+“²¬'t=]j‚Z.xâyjz<žI…DË"P0Ïq2Q,ÂØÄÅÅÁÁ Óðùøé.n(x ‚ ‚ ‚ B>¼ ª6ŠSËw0av”χÍÀv_5#¨´^xO (]BÁˆTMË88G90ñ$•ÊŒ–Õ4å J$ØsùåÌ()akCCÚaáÂ…ÝÖ'1 £KTE¡Òv †|öQ×u‰DÎç|Öñ³F÷æ#ܘ¦‰®ë8ŽÓãòý¬‚ãÛµkW¿Öë‹~E¨455±fÍšðsKK +W®dåÊ•Ô××éŽ ‚0vñ€E@-}?¸ fjBg}@3ÍaÊ!ÏËÔVéõ{Ó‚Dw¸®‹Š\ñG"‘X²Û¹ ¢&8gÂØÅÄÄÆÆÀ@GN 1œA~ƒ ‚ ‚ ‚p$±K ˜ôù\yå•”––é`”‰¨Q±k:E¥âéžúÜ™ìA¡Ù ºã„â ¦©F‹ap÷äÉèÑ(;vìà±Ç£¦¦†I“&õ(Bd×1MsDSwõ†ßW“nüP¶mçu\“t]Ç4MâñøŠQ§vÚÈ *×_=+W®¤µµ€ÖÖV®ºê****X»v-×^{m¿¾¼¥¥…öööœi­­­455…ß3p']„H% lÛ&‹Q]]Íÿþï£|þó;úLÍS,ضã8xüýß¿ÉSOmâ©§v’HdFß £—îl†Ö>gg屜ëÂ¦Ä ¦û rRneG¢ɺuëBq£3‰DÇqˆÅbÔÔÔ䈶mS]]ã8ضMMM o]woýýßóÿýŸÿy7Ï­šÆìœóþë¿x`Â0Mþpæ™Ü³`¶mSéy¼qà¦i2qâ׹ムJ¥¸íwX—Hðÿ¾ým’ÉdXŒ«¡¡¡Ëþ&°lÙ$ ,ËÂ4Mš››ihh ™L†ë™¦Ieeeø I$œvÚÿñüóWRYYI"‘ ‹ñÿ÷¾o¾ù›6ý4üž ê$(p`jP† a…;îØÏgÜø9‘3Áµð<%ÔiÎjkUº1¯wmK…°ÏÞÒ|E‰†Q)Q¢DPG +¬©"GGJßVF#Ýv ‚Ð3bŸ‚P¼ªo›Œéž`ÂøÇ0{öìpº °% límTª¯l¿{O®ÈÎÅa•Óƒ‡Þû^5*4íÀ°m›{Ï?ð£ÑЇ;aÂ6mÚ¤âæ)’stJêdcFµOŠ™ .¸€cÚ*y¥üjiiá¾ûî㮻¢€µk×2kÖ,V­ZEII +V¬À4MZ[[)++ës› ³jÕ*ªªªX³f õõõ,]º”õë×SWWÇŠ+ }ž„ïûhšF,Ãó< ÃÀq4MÃu]4Mã­·pöÙ‹Ñ4-Tõ¢Ñ(ßüf’?È‹/žÄƒ¾w¤€Ûn{‡={Zؼù.n»íb¦MÛÊøñ_£½ýìÜùyN;ícìÞ}›7˜^¸Ÿ-[.¡´t-?øÁ,^¼˜÷¾÷"¢ÑÞS ÅGw¶ CoŸÛpщô8ß÷3B‰iªŸêjå¬ïŒëªˆÏ‡~˜¥Û–vš§ŠX,F$Áu]\×Ų, ÃMÓ¨­­ s5^?oþ_þÂm›Ö²wßwqœétü`'[ï^ßøã<-Áÿ—ab]7ÔÕáÝ}7×Üq_ž>ðñ¼*b± ׮圳ÎB{ðAL2m¾ œò‘P[[ËæÍ7ÑÞOúQÚ®»ŽRT†ïûØ7ßF˜èºNYYG}4ÇsLÞÇÔ‹} `ÉdrðF* „¼•ûªªPL•þë /¤¤¤€²²2ÊÊÊòT®¿þú.ÓêëëCCmiiaùòåTUUåµ½á&¨w`FX7Á÷}ª««C祪¥ rê}ÿûæºë~ÃþýwpÊ)?cöì~ùËq|üã<öØ$“‹Â¨3Mƒc5¹ì²uüú×C‚¨©º®S[[‹eYèºÉoû3,˜Îþp˜3.gÛ¶ŸsÚi3¹ñÆË9öØG™=»‘––@Ópæ™üå/3ˆFWpùåûøÃ¶ò•¯ü…Ý»ãî»—`šKÒßx¯¾ºƒŠŠ=<û¬šÒ¹·ïga]WwÙNÖ ÒÎ0Գζ•`œ«`|vÍaèèÎ6ahí3xÄõVïĶÕuŽF3µL²ñ}ÇqÒ÷´J3ôè´GÙçîËY.•J…i¾lÛÆ4M<Ï ë—"‚išTWWÇÑu˲p‡D"Á¬ô¶&–Ž ·»øObÚyç¡¥sožþío³hš>/C˜SÓó<œsÎ!ŽJíé£ÚøZT]´u‰'¶·³!•âškªxôÑK‰FMžûÆ7ÐP«VúœEÒë׺e·¬œš¦ÑÜÜŒ®ëaz°|dÑh’K.¹ž—^ZÌo¼Áë¯ïÁq¶ñøãóæ›×pÿý?céRx<Žã8a=˜T*Å¥—~–÷¿ÿlî¹çrÊËˉÇãaº1]×yöÙÇøä'?ÃC½£ÎËâ?å4b/¼°½{÷òä“‹Òx6®ëvÉ-êû>±XlÈC;Ç…°ÏÞpprêõ„††‡‡ƒƒ‰™w}#AÍ gßÖM·œ}W¡3#Ýv ‚Ð3bŸ‚P¼Œ„ßönàkØáÀõã°\ ¸ /ÚÔß\^!ÈÛÞ¹NyvÀ¡T[«œˆÍÍÌ|ã0Úäì_þãÕW‰F£ÔÔÔMG§óÛÛÛY±bEAöÃÅ@ÒÁÅè«ñ²Ò£2[RÞEé;GSSS2Wú¢¾¾>Gœ ¶7kÖ¬Põ¬¨¨ ¢¢¢Ûï ‚tAA:«`d8À·¿ýÇß„m_A$!‰JEøá!™Œàº°u+œwlÛ‹-"‘ȤñÓueßgŸ]š3š;HÖÝÍžíLN¥RhšFeu5 iµ0(býÊ+opÞy«pœ*'™ÄÕ4šFJìÈÆJ&ñÒkk¨ú1d„‘So¼‘㯻Ží/¿Ì]—Lfzú±üâŒü¨Dõ‚î@,ý·“þ;’Þn°Œ®ë$Ï00¯í,Þ÷±æ­0w§žjåÍ7]êêžÀ÷ÏaêÔÛùÝïLöìÙÀ¯~µ“ßýn_(´bu*•Âu]‰DŽØCÐ5d6ˆÆé,ÎŒU eŸ}‘¯0%J-µXXxx40¶FèB6ÃÝ·µ±ÅŽaKÛ)BWÄ>¡x)¿íA4n¨…é—½À©ç·â’®?o¯f-ø4ð÷¨ÈˆƒvHËMï¡j¨Ñؘ’å;h9÷\Ç!ÒÐÐÎÂccÙ’Å©§žÚïbèc MÓÂAÃý!L4^§|óÃõ=ÉKP™5k÷Ýw_øyíÚµ9!™ííí´´´0kÖ¬^·ÕÒÒÂÚµk¹ë®»rj®´´´tmfÍšÕgN¾Í›7³råJV¯^=¬'ÊqÃz‰D‚³Ïþ# Ìç¹çÖòéOŸŒi6“J)›ÇU4™ï+‡paˆ™‰„J]äûé‚ÚhÚ"æÎýµµÓL¨Y`´ªiZ8ýg/ŸNÓ¯qríž¼ï§>)“¾²Ÿõ÷Ï,yÏDˆÁ–Çrç]o²øÝ³Y´è\&Lø{÷¾Ì¸q n» JKKùÄ'®dË–›ùÉO> À 7¤÷04õ|JèpFìô½yRâ: )çp¶«óãßÈõ×/á²Ë¾ÅûÞw–õgZ[ÿ“;–ẗ_þ¾ñ3ø×Õ™0á lÝúù¶owÙ·o=t7ÕÕ¿¤FÎ8ã lûš›Õ3𦛞ƲÎÏspnt]/¸ZºråJ6oÞœc £•žl3˜7û¼÷Þ{¨««ë2ïí^•XL‰(ÑhîÀ‚€T*•óМ=;ÉÞ™3¹üò˱¿ªjÑd¦i‰DÐ4-ŒªÒó麞²Øx9þ|¶íŸÑez°¬iš˜dDè({ÑQÑ%)T$ (!% ˜V½a‹~òJÏ<“]Ó.à‚Óžá¡‹. #Wã(;tQvæÓŸéÏzúohFõ)¢éeîöì:‘ãç}ؽý8fÎÜÎ%×láŽí¥X‹ "ò Êuh€0îÀ0ŒôOfŸãñxÎ3 T$Nm­Æ¡CíÌšu˜™3ß"³r囜pÜÿrÚÚnâŒ3>˾}MÜÿ4æÍ»"]«Æ"W×Ò4M’É$•••á¶#‘ÕÕÕ˜¦Ö´mAÃÜŸûÜçØ¸q#Ó¦Mc,0Ôö¹}ûvV®\É…^˜Wç×ǧœò0ÕW>Dˆàã#&Ñ)BkÖ¬aÍš5œxâ‰#½+CB!ú¶66Z(R¦H‰¸" Ò·xßV†“––êëëÙ¼yóHïÊÏHöma(‘¾m~}ÛºººnETPþ¡Ih”`°eÏÞœü07lXf7ÁJ%(ÇÈÀô¼ô«¦1Á Ì*oÊ)‰„õR:ç³®Ž¸¦á8Žã`FNQùl&MšúA<)›ß-ˆ.¡£/¡«¾¾ž{ï½wÈû¶y *^xazòõTUU‘J¥¨ªª #RÚÛÛ©¯¯§¬¬¬Gã–»öÚkú+Ùìܹ³Ëòù„Œ-\¸pXÄÏS¢‡ea¨‹¯iÑh”ÊJд(³f)½þúˉŔ}ÆãÊéßܬº®¶Ødàœ RéiZ®ÃØóâLŸ~9W\s ãÊ˹úºëøøOsâms©®žÆu×µqë­8ö ïâß¾õ<»î_ÈøãËÙT>E.¬ý]Üqü¨NJG¾¤fvàÌú#ÿ~Õq<ðÚ\^~k)Û>ƒ/}I}§ª%±„HD=£”øk§PÎÚàFÔ³Ê< 4K=Ó¢(Ço@4%¦G¼¿ÀoûZ[ŸEßøk6¾ý6w¿ªóµöv–7Ãߦ_ƒ¾iÌ^Ìÿþç$O¿‡þÂ…¬m›ÀºÀ‹?ŽqÔ×¾ÈÍ“OÀûëa>tý;,𽇹>À4\×åòn`ò´orþÔé,Yòý0â (–F ¥ª¼zõjêëë‡üþ+4½Ù& Ü>/¾øâ./œ1bì%Êü¬¾¯®™ãäÖKI$F4ü2 gñÛÛ–`c«D‚H$‚eY\Pwú9:™|¸Ü'½qÝYgñ¯Wìæ¹ó62aÁ¤>—7Pv¤¡ì¦™Î±-]ñ<ÓO=• _y‘£7?@ce÷¦çYéŸj”ÝE²¾'‚²W5jÃÏúî`=Ó„”¦_Ö`ßž©üæ¥2Úþ4….8ž3âðM”À“^Ì4M4Ó$F&ŠMÃÓ´ðÊ)ÁUcÞ¼-\sÍÞ|s2;vLÀ²–sÝukر£”%K®çÊ+5Ö¬Ùë¯> èüêWO* [CCCh—Aª5MÓB;PAŶí0’%‘Ö—Å1ÇÃ1ÇÃöíÛû¼fÅÎpØçܹsûÕv&H ¡áâ¢$ÄüˆÁÃCC£’JhqE`ÅŠ”••ÑÔÔ4Ò»2h Ñ· Ræ%I’ A-µxxøøh}¶0‚Ð?¤oÛ;Ýõm¡TTT°zõjV®\9Ò»2hŠ¡o+C‰ôm{'¿íV<ŽÂ`+*«ÆŽ;˜ó×Ù€òGàŸ¶&˜­à¾ åüèüz¤´ ê¥èzNº› sIPëÄó]\^!AióƒˆÌà™¤¯K$|æ3×âû{rjAz´ó•ãVÓÐu”âsO|ŽúÅõhh4“›Î+÷8ú 3ãJñü[‡™7owŸË(»rPöÒ—«K×u<Ïã}ee<³u+Û, rÇ´]£b\rmPOO3 ,vßÓ9Õu8#Ñ¡mË”œm¢eªQBªÞvŒÌs¡%¾xéãl–.]ÀwŽÉ7M$¢:(S§Neݺu”—73cÆå¼ÿýÓyì±…´¶¾Í9çLàå—7°{÷GGÓÔ³3MR©µµµ$“É0Ú(»¾K4 Söx¯¹.Çw\^׸˜)¤}ö„‹ŽŠïWC#I?‘æà!?»„Ñ@!ú¶)RXXèèD‰’"E„NŸõŒáH¥ÚNAºGìSŠ—‘ôÛÎôÏã¯öf<ȼyó˜={¶š±åðØLC9)o&¡J<9ü ,&ãL ê+@¦@}¾ï‡5b ÃH6ïÞ;Ö ÌŠìL1c¼k¨TTT„…³Yºt)«W¯Î;t¦½½[n¹P†wß}÷±sçNªªªX³fMβ;wî,hÑ1M#¬ÙØÚÆI‰3ùä'OÄu{®Ý‰t*¬ÜêÃY,³”#2N\Ò)´ÒŸM”c4T™>ºþÞÿKÁ;8߃÷0% GûðU¾Rãv}»ÎeÙ²7ð¼E,xÊÉÙåYa”'LœÈ»~òÞÙ´‚í;Ƴ2NÑÀܹAà°íÀéš}‡4¢„Ø6}:;>ùI¢éeÞþÍo¸ùr"éã¯|]‰UvÅ4vOƒ¿ÕÎ`â_à±e˸y÷n¶þ×±å_gêÿMÂØ²…ÇÇÍå‰3ÎÀ¾õVæ>òopø0—_þ]~·.ÆþýwðàC—ph¯FÕqÛ¹Ë ¨‘íñxœòòr6n܈®ëØ6èº{Ä+Í=Ùfs(ís ¾×Mªß'´³ [,KÏó¹ûî×xä‘O`Yž§Ä×u9õÔ¢s; Šûÿû~xžó,Q¢¸¸ØØ9ާ|¢S¦,“Wž(¡ãè}.¤êÊŽ&é ÊfæÌ™á´™t»¬G®-éŀж:kÿ†¡ú® o;0épÌýÌ^þròܰ¾ (1ÅNC,ý9™ž¤‹ ž~ú;S@¹¡¾{^é8jj”T6{öl6l(a÷îÝÜrËT-‚yóæ±eË".„µkuÞÿþ8öØehZ×Ü@8 Ò}éºæÝô1B?C.Þ4Í0 åHb¸‹¸Q=Ã¥2ä-¨ôDIIIÞbJç0›•+WrõÕW‡ë hUU---´¶¶rÑEäD6fšÊ©çº.žçñ‹_ü‚ýû?ÃO~2TJ¥ŽêMË$Kï×à ‰Á%J4ˆ@˜B'Šr\¦PâŠ<¿æƒƒ.|*ëtê£hzûéïh²À¶æðáw€Ópœ =™Z¾º:7]R]b””„®°‹u%žT§÷É¥«˜¬Û×xä8ʱA9yƒíbñó?ù 5 è×\£ [·æDæ¿ C9jS:”Pû•ýÜ\6}:7Ür 6&8v-|åŸ.ÂòÞÀ7MÐLöß:ãVàº+®ãÎWŽÂ©¬eæiûÙ3å-nŸ{Q.Ÿq*ž¦±âë»`öñ|²¾ž JJ¸çžo±~}‚ãcR5͇¾l³ªªjHís ÉnGÕ&ê'[üŠ–kšÆ¶m÷°i“rª744P]]ïûlÙr}¸¼×9‡spL‡µ¬ECÃÆÔHÞ}wKv3娽}.DõÇåû>ó÷ì¡íøãyþþû© Fbd‘mOÙ‘)™T}9ë¹êùÖØ¨ž /¿y€¦Õ“Ø·jjÎö‚-Ñôß¡]¦?C&R%šžïg¥–—IaxÒIÏ2~){öÌçÌ3ÕH–©S§ª}6á¶Ûªxæ™]\}õ§k­]×CÑD­c’H$ˆ¥îòo󂨕@píÚ>;¤lª.“jÐЈwÛÚÂèc¸û¶..FNdX j6ÓŒƒC 5D‰bcc`ˆ "Œ|Û)Bψ} Bñ2R~ÛÃþLv±b°ÿŠvN?ýΚ½#³€\ úV”ƒâ`O§LJ§hD‚xjj2Q*(¿mÛ˜¦‰ã8D"Ç9b}Ãé/ |:)f?È[Pimmå–[n¡µµ•’’"‘ȇ\ÖÕÕqíµ×²téRÖ¯_O]]]·95‡×…ü/Ï’%&‘¸ŠH¤êê<Ï#™LbYª¨qžÙBÁäz Ri/g 8T’qH·T ÑT£–Ó Uû£¹´Þ‰ãqp]ß÷¹ðÂùÂ2#ú»]>ëï‰w1mÚÖðs’Ìès£u{B§kÚÂÀ,- õå—Y²;7]R¶Ó9K+ÂD L#ðù%Uü4½mÃ0xæÅíôçr™ã—ìfÏ)§°äÝ“ðn…q¿™Ä“ÿ4 ¸òË_Æþó$ÞsÒž¾ì2Æ_|˜'o>ŸÒê¿ñÛN¥¢¦–çW}•3o¾™-[¶0eÊ%¤R©0ÝЕ¡²O#§<{ÏSvöç?ÿ ˺2œ®i‘H„DâyU>Ý jšF"‘`âÄ[2ÛH¤7bZ\ÝU1b>öS§²ôÃ/ðöÌÞFo¸®Ë)S§r`ï^vx"gu#¨d‹Ù$³¦ké¿;Ûq$¢ÄÊh^¶_gîÿ7ž§>> ´\FïaýÎ4¤—ñPvî£þû¯¼…‹?{)K›UÑÌ uX :|ö³%Ô×{ìÙs9ž—‰¢ „$'3ÇŸîøâZwÔÖÖæt„6nÜȧ?ýéa¹fÅÆp¶ŸF˜nh0ĉ“ !‚ŠpÄ0XÛtq{3MLi¤†š0µž ù1ïž‚ 䇨§ 'Ãe›ûÝÙ›Uë}öìÙ,zk¶ú°—Lþñ](§á|`JÖ ¦.V».?ojâŠ`z– ȼäy^˜î«'ÿ‚08ºË(2–È[P ŠŸ]xá…455qÕUWq×]w *´«sQ¢+VPUUEkk+eee é¼ûîçxýuùóSìÛ÷"‘H„šššÐi«Â¾úÞŽ‡D‚[¥pӅ탨•+;MO@Ùa¡þK$Èë{Ž?~6š¦ž¸Ø›.ðÄ?fÁ‚KÂÏ2”šay“>Œ²2´ÓN çû¾ŸãRïlbPQÓƒ’5š¦ñ‰—×Ò¤)GûþGæóîm­œ¶i1/¸pØTÏX¸âæ›ùu5|~eŸYW|íUîøò»™xÅl&k‡.dΤI´èóøÑ¿gùò:\÷ç¤R)t]öAZ©#íÛ]Á°¡²O£Ëý*zÂ÷UtʸqWqÙe ˆÅbhšFcc#®ëRRrÉä1áõÐuÛoùó»6àÅ1=iß_Æ>Ì6…I5lçÜ0 ¦­[ÇÞ½{{ÜÞ\e½Ýº®„*×UçxÒ‹ûiþÚà ºïctº·{Ÿ\·@pѳ¦¯ðawkððöžù<ðÀ\ …“Þ÷HDíƒëÂO,äüó’.‡ƒ¦©ëD ¦Rê™–ˆ’L&I¥R=†¥Åë³£W&Ožð@;‹¦±±|dÇó’Iå@¯¬¬¤¡¡¡_Nô h»I&-O7iÂçAçÛU#WÐè®ð}o´µ¥·›_gdO:tFÞ7%{¤{öJ×õ.…¤;‹9z7›¦‰±t)ÿ•>7Sbâĉ,Ö¥šúN 守@‹SÏÝÇNy{nkg÷—–0!êá={ïvo(aöì³`ÁR6l8ÏóøñÂ…üÏÎÜ÷£ûxöÙ·Y´è‰\I3ö9­Ëýïº*3ûžL¥R¸®K4Å0 |ßgÚ´ihšž#6îÚµ‹óÎSu;œ f+!g`NÜ û÷óÖì9œR:~ÈÏiösf׉'bìÚÕã²iæA%›7_>À쎎Nç¨g<”}õäÖ›g@© W£¢îª.ÛÇî߾ɬía–ß»ð¶¡ú:AšÂl|l[=»âñ®Ï°H$ÖFÉ]ÏÇ÷}t]Çó<ŽT†£ýtqññ‡TüŒ- Âhd0¶éâæ%ІF9åaAzGµ‚P¼‹}yú›ÖYÆ*Ãa›GEîa§³"3ŠsGa ¨,ŽÏ¬c<ñ8ë|M§øºôÚkiû‡'©äu]GÓ4LÓ$2ÜNQ¡àt`;œäí¬ªªÊ ãºð f†ÿ÷ÿÞ`åÊyõÕR¾öµ aD‡®ë´µµ 8"!(H`ù§ GjŽéÞÒà†Á¶m n¿cO»<¼rö‰\gnv}•€@=аŸóИàÁ¦é™g¯ÌAÿe÷ÝÇž–&ßÉ{}J'>ÃøE‡™aÃC1ˆÅª¹ì²lÙr Û÷Ëú¶Ù|ë÷¿çî»æ™gÞsD;h‡ƒ]t½¶¾Ÿig¹ïû†Ú¢išœzê©9÷¶¦iœþq¡øøÝÍÖÑ•æÿ=]»N ×m7ÀlPé]7‘R]‰¤qÂ"õ™{"# †‘#È‚TPHβ,A‡ÀvÓð HÝAèƒDrEˆ 1Ò».‚ £5H>B¦†¤ ÃÀ!ÆM<8æušß_URõ8TVÂæÍ`ì{áÇ 3Yø¾~«Òt²ý¶…JavÄ *ãÆ­`âĉÜtÓ9C²½žÜAÑhï©·Cw¹þt]EÄô%mÚ´˜B¤ è¡ôÞè$Þg©c5M8OÏ*dýÔÉi¿ÿ=Ÿš4 <½—N£Õ Y;Ø6o ›gÊøñtÜqdÏžùìØaóÀíòŽ||öÐÕñoYÐØ¨î]ÏóÂûºóýÝÙžt]gÞ¼%yE[e;qÂÄK¥tÁ¾a9/ÁqÐë¸ý|í©³ídŸÆwíbßëSÙ¿~J—õ¢éŸžÐz™f;²˜1s&óçÏ÷); `P3'(Do¥m9¨÷bY™¨¥`¨ç^¶ÈÖíy4Œ°Øœ0p\\,¬!OÍe`àà#†ƒ##é¡*f5U$LAN åß Þ]%Y­ ;'n¢d ÁÌwfÂÓdÒÞÌ£{g„ëªt¦©œ ‚i²ë _@Ó4<Ï#–Nuáº.Éd²`é Š±4p|¤jàä]”~ýúõaaz€ÖÖVZZZr–ë® X±ñÛßnaêÔïsöÙó9ÿüˇd›=ÝŠ‰lÜ8|ÇÒÝãy]ktæ˜cÚÒáÛ±4ÝŽv×õ>7ÍøÇ&øéQ쀔“n-ëoß÷ÙvÏ=\ö¿ÿ›>Að. JÒ ¥€ýwѱq6ÿ6Ã:tL\È´wmçÐäãYóäO¨¯ÿ'Ž;î«Ø–Å-XÀK– ûùk¸¸´Óõ¾ˆÅ”Xây6©T ˲ºMÛ´•Ùm ¦1ìâଠ±}œxâ‰Ã²ýÀŽã0È’ßéíõ2oæhĤ²]æõ¦å1=»{²øC›¸ñÆrÊéãsQ"ЦeÄ” /a”n(”E£™”_=áºnÎh“#½°ÜPàâÒ@ðQ¢áöcÄÐÒÿôô¿| ÆC™’LŠ¯Û–ù`aQK->>qâDP¹1k¨AC#I2gùJ*i¦ŸüAa áÕdj²š@}¿# ‚08Æ1ŽñÍ2­ &ö«x7¼@Ͼ€x\¥»hkS¿KÓd³¦¡··£iZ˜á¢ººß÷ –ªØKiÒGêšæ¡2kÖ,–.]š3­X „ „ÿùŸ]|Ãïˆ5Må,$A‚žÐ4’’’a?öž\º®I–†å^S“>fT§GÏšj´ºçy™ïL_웿˜ù©“8pÔQLÕ`‘3>ÕÊ¡c¦¡qç¯ßÅúƒùÓœ÷²ÿ§³þ•Ãø¾/©…ÀäNî¡TJ]ÃPNq×u1 ƒd2™×ö: *.C¯´¿pÓ+K™™Žºmt×¾Lþßü£m4èÑ¥Þ]½#€ùÀ+XÄ™g.Â!ó<ˆ¢"U1èa¤i™t` ÄËRËõ&¬äÔXAeHÐÑó*ˆÝ_"DH’ÄÄÄÂ"FŒZjIÑwŽLjHÀÆ? ÂXb0Q•&&éAú//l+Sé.®D‹ ‚ G$ê]§hD½·DQÁ “8FŽ\‚róþu ÓÞ€¹[™81=ö?H)>‹LZ ‡Ê[5ŒnS~¥ Õ—®ë˜¦)>‚4"* yE¨TTTŒŠÈ“|¨®†^ØÈXÇh0ÒºuzŠdÓuO}ê9`Ù°î‡F)‚4mÈdÁf4ôØKEö¡kš–£D¤Gœ˜™‚ÚmgŤ]»¸,yO¸°ùŸbÆo Ä€wž«äo+Æ3ëU‹Ã/Žg}Ó>Üi.µµµüã?þ㰞DZÆÞNŸo¿}ŸùÌ4@5|Ñh4§}6Ùéì'»ïçÞïùïí/ .ä±E‹†å|ä+.æ›é³»£Dr?Oÿâ;ýÛGÔ‹FwûГ%_bÂéC3É;!E‰(Q-WÑ|¶­®g4š‰X R€"Kpʲ#ñÆÒ‹bÀÁðÈøþ%Öj±±Ãȕζt¶S¤pÒÿ<<i¤šê‘>e‚0丸ƒ²Ã ÚË #S‚4~66 øø˜˜ØØXy·6‚ ‚0zñPïM1TÊe å»5E I0Ègç>ÁIo¶_–²ó‚Éh>Ê@“;­äïa„¦®ëD£Qt]ÏI .($EúÐwʯ€ÖÖVšššÂ”_eee\tÑE”””Œô±ô‰ïÃ#¬â¼ó~ÏG?ÚX¾ÄF˲ ¢Ì…Û:cÆ=Ìt]9b;o®·««iQ":T’º'½ý6“MŸ‡bG1Ï€C호d7/´Áä]'Âÿ½Æ;ßÍžé“hÝp>¨ê}<ûì³TUU ûù lfwš¶nÝn¿}+»=ï9é•mgjihšŠNÊ^|¸Àg.ZÄ–¤Bš¦ÑØØ÷ó(ß#ën¹Î‚Êþk¦0ë•Wú½¯=Öyþ¶¬`!Œ]º@czŸ\7#Œ–—CCC×íöD3]AÅó<T†oXÄÉžˆ§“Ý¥HááQN9:z˜–ÈÃ#A ¨¥¶`¢ ŒCa‡qâ¡ ØL5Õ¤Ha``c%F|YXTS‰9,j‚ ‚0’ø(?€…V†1C» ½ ’31y´m&'̃Wññg—ad—1žJÆ™0w.üèGÊ9ÔØ˜I ÔØéAvžçá8š¦…iÁ#"‚0Hú%¨Ô××sË-·PRR¦»å–[¨¯¯'‰põÕWôñôʪU{0 7/çå@èÉ­3\B¨®ëݦœ2M5º»Çý,2[ˆ1Žº®F±Gûxß7M3¬Û^=­b|ùev>0™£dÖÛuâ‰ðª€÷éë™°½¢0ï¡-ÀL Ãàµ×^+Èù lEÕ ð<˜6m+ž×F*•ê³¶ŽifR|™¦ºöA]•᤯bíÅF_î·3žx‚mÛ¶ÁÑG÷k»Ý=9¬¬ïë<v'ÝVÏZÎÊQÂk¶œ} d?Þ Cõ™‚Bö¶ É$a±¹l‘¸§g£A¡ø‘p¤uâÄqq©¦:e¯£Ó@FqÓÑEPÆ4.îÕê¼ ‹ h‹ØTRÖ4òñ©¤’F *° ‚ ÂPŒÃZÂZÔ;HÈ/É´ ÃA ¦øøÓ-Ëê1O r ¯øaÞÙp×~ î÷á1`Á¶møúbvš@ë³LzçröÔÂCíà3Œ¦i:th¤OÁ¨áÙNùà=ÚÚq]H¥R}Š}SdF"#Vìôåb^vß}¸®‹Ùq9I÷ϸìïÊîÊèÀü^üñÊöt=s ;_߆5Ï0Ôrš¦DÛÎ<ç ÃÀ¶sóþKNÐÁtlGºÐ»A#øéÙ$IŠ“Wó —FÓÿ µ¤«¡&,doc‡¢ŠNßÑÍÙ‘0bŸ‚ B1`£Þ=6¢2ù¨÷– ð¼ #‡‡ÇžgçséIÛñ·>Ævþ6;Ô29u’|P94-SK¥±XŒH$B*•Ê»6ï‘J_ƒšG…ÐòTZZZ¸å–[¸ë®»¨¨¨È™WRRŠ(©TªhσK/}þˆp´Ib tMgÔ½¥ "T–65Ñ>ùöx§sšwXPZZʇJ!åÁÉçÍbó#€ßÞÉ /Lçµ×þ“öö§GúŒ6â²4í`qœ À¸ƒïNÙäºéèN€áÒpû « "™E J›j™g—a¨i±˜Š> "“tæûj^ðÓݾÂHãã‡}Ή§¾ÄÛo¿Í´ié¬B'Ò³s#É8Ò¸®Ë°m›X,úpjk3ÂKuµÚ¦mCe¥šçyêïÊÊÌòÙ™–qÔ²cl ûO¡ü¶&&ÓwÏãï¶ÿÓMW3võ²’®ƒe匮Öu³Î: ÇqˆÇ㘦I<.ÑÒù0×uq]· þ®¼R~Íš5+/Q¥©©©Ï”_×_=MMM”••ÑÚÚJUU7Üp@X‹eéÒ¥¬_¿žºººœz-ƒaïޭض}DDtt®C ôNö©*-]‡a¬@×àÊÉ«/¤ŸÃËtØ¡Á3óæÁÖ­œxâ.ÆûpûHÆ éÍ6ahìs[Öߎ¥¥ÓÐ4 Çq°,k@òì祉ÙëˆXq6rÃBEšX÷!ý[G½èx(Q%¸”Áç{¼ôKKZP‰Ç3/¦™y‰Ð4 ˲¨®Î/àh¤ö9šÛF’‘êÛ’$IbÄpq‰!E ƒ1,¬°ÖQ0¨!x9¶±Ãôa D—#=’T(Òv BñRû´Qï!u¯e‹©<ãÃ$ó3þÜî|w¾¯ÄÓTD4ªÖolÌ ¨jíöäï Rw¦¡Am¿ózѨ8‚íýñ9[–MQ'ˆ–1ŒŒˆcšj¹D"S¿2ˆœ‰Ç•¸DÄe, Cm'WëÆbj;Ašæ &¦ç©uu]}·ëæÖ6 5ÍqÔþÇŸ]w¼¦FíSö¹Qu5x‘³®Y~:‘È âËÞ~Ôù}3•Ró¶lYÈé§_ÆžPè¾m ˜º÷6°ãö§&ž| ›…{0šT*EÛumD¬HèT—¬GÊTM$)è5ÏKP¹ð ©¯¯SuG}}=eee½F©´´´pß}÷ñÇ?þ‘’’Z[[1M“+VPQQA}}=«V­¢ªªŠ–––/_NUUeeeƒ:Hσ»îº‘h4:æ"TºÃ²¿# r^ëKK×…£Ó<€KLøUºceÛ6 ~–={¾?Ò‡1hú²M`Hì³—¦+¾›6­ E”>ø²;²:zXsAyòIå’I¦¥{YëÞ“‚}Y±ùš–éàª[G#›\WÝW'4g¤}H)”}BnØõhB¢Ï„‘b8û¶Å$<4Òˆ‹‹ŽN„>>1bøø$I†*Á  ŸjªˆAGS zxÝÖI„ÁPȶS„þQ(û´æ|—µ•ˆ@d:ñ}xO^ˆÁÅiçzuµrî)¶á2Ñ!†¡–kkëß9êÍmÕÝ<ÃÈ'ºGf„Ãè* dû©ƒõƒÁº)X§±1W ihÈDÏ8Ž:º®æÛ6lܨÄÓÌ]>XßuÕwxžÚ¿ÚZµL b•®gR ×Å0Ô<ÏËC rHŬDe‹6£R“CGGfÿu=7Zp.m[}¶,øÚ×frôÑsûw¡‹‘ðÛÖ—}l=ö§rpœÌO/ð…/Àÿw®º–E,ò,;ê1,qˆq†–HÖ›’— RVVÆÕW_͵×^K$aÅŠ”””ÐÞÞN*•â–[naÕªU½n§µµ5gÝÀàvîÜISS³fÍ ™ŠŠ ***hjj´Ú9}ú6.Ü@$òß;±Âè Km‡NNýÎ}×…£4˜7oyŸøÄ ÔÕým¤cÐôf›ÀÚ§ª8þâïöóêÄŸóõ¯jPûžý¼ÔÓÿzýn¡ ôÕ eoAh¾¸&,ê¤ÊèºêÀ:Žú‰Çõ0”×÷U§vÏž¹,[¶|Ì„Ò>g© ù1R}Û‘"hGƒßÍ4SN9N(ŒXX$H`c“" ()U5‹(Ñ0…(¡¥¯Â÷‚/…l;Aè…°Ïà}"_©>‘€ææL‰ï+'½ëf‘„ßhÈ ü ¢, #9f¢(@Í믘2\ÓC¶P£ë¹¾mMSiÅš›3µ_‚—ÚZ5=›àüv'þ”—gR<›¦úg²tWO³²R}gQcY™ÚåAdNCƒºžñxF´ ®“¦©m74¨ùŽ£¶ÕؘùÏSßaÛêwssF”9tè%ž{nûÈ^ä!`Dú¶.<þ |uêYœõìYjÚü¬ùo¿­~Ûv·‚ŠmÛ¤R)Œ6ñ÷©Äãñ‚G$å%¨ÔÕÕ*Œ*ˆFÙ¹s'íí픕•±jÕ*.¼ðÂ^·qá…rá…ÒÞÞÎúõëijj¢¢¢‚ªª*n¹å–.Šæ¬Y³úÌÉ·}ûvêëëÃýëŽmÛšD¥úD×u¼>ª³E£ðмAʺõÖz¦Ly‚—^º(ïBÅHo¶ j”Â@ìó‰'ž`Íš5aãº'ÈïCG{Ÿúâ{±,‹ÚÚÂäY—ѯ…§7×XÐÜW%p㻨‚‘5ÀÙô˜ÌÉí”y™™Æi§ÌÓOÛìØ±c¤OÁ ûܱcõõõTUUå<»:;Da8hjj¶íðEm43œ}[êÂIOÏŽ âÄCAÔ³¦šj44šiÆÇ§†š.‚Š‹›³®0¼Ô××óÄOŒê~-®o+…¢µµ•5kÖ°}ûèwØ¢o›¢÷]Ã?HSÕÐSß:t’é°‚ÏÙÞ‚lS¶oãÆ‘>Ã#ƒ®«¨È)mFstGOùãñLIí\ƒž\{Á »H¤«pd2R¯e‹` üôA:5P¢KwûDª8ŽÚN°OMMM¬]+}Ûžú¶+V¬è>’Ň ïžÁĶ‰ìšº 8*wþüù™Â>ž—k¬ú{%kÁ‘Ko>ÿ5kÖ Kß6oA”¨‰DhjjbýúõaƒÕÚÚÚ§°ÐÚÚÊ-·ÜBkkk(ÂtW£%Ÿ±3fôyRü飼[7¤'N{ä#¨h”û,àáê«™üËJàÕ‘Þý!¡;Û„Ûç‚ XºtiøyZà2¯/Ÿw‡Ò¡y ù- ã8ƒßHh}Ì ~²¯~±D¯x@ ¶¼ŸùmkQâ‹çeBó=¶nÆÌ™ULzW!Oë°2”ö9uêÔnC³]Üœz£…au¶fß.jXb£ÎMÿm•ôœW¢¥.ŠOP÷gEEo¼ñÆHïÊ1Ô}ÛIMéCÊ›xºÜ¯G×>”Ñ­ ¢£³‘ŒÇICÃÀ£ULLª©ÆÂ S‰•SNm88áòÂÐSUUÅ–-[Fz7†ŒáîÛ B¡F…?þøã#½+CÆpöm}zT‚¢ì7*G{e¥ràwWÎSÓr3"ôî-|ßS©êRã·³o4ŸÓaY=‹-ñx&•Wu‰äÖ_ Ò½ô$eG¬Hß¶w¿í¬Y³r¦«gÀ€9;À1÷öÊmtTf΄uë2ÅÒj—çy¡½øc%=…0ä,]º”Ç{lÈ·;¾¿+”””pá…RWWG]]](fÆ–¬^½š»îº‹µkײfÍš.†l³/fΜ٧ 2cÆ_TìZ8²Ðu3X˜6mh³fÍ¢ýí÷rÒI'ôî ÝÙ&0`û\°`A˜×ÁÉ*:\õÇËr:Šc©Ó8(–óݹoífM³²>~ìÎ2ÐÏÓyŠƒ¹Ax÷ÛoObúôL:u¤qÈJûìIPqpŽì‘à6™›,œK¤§¹é¿t)5ÝA½]»YÓ:¿m¢ŒƒRpÊÊÊ8å”S˜Ü1KUU ,éÝ2†³o+…¤¤¤„ªª*fΜ9Ò»2d gß¶·qê±X¦g8â}ß'‘H„-=ÏÃqœ./=ÏË™fÛ6±X,œüÝ—“×q*++©¬¬¤¦FµmåååÝìs¬`YÆ*8(AÄ t_ç¼?þyéÛöNà·íÁc`¨×¦ly«£JŽbÎÜnê¡~ãê…ß²r‰D8P4ÞC±z¡{\÷ȉ橨¨–¾m¿•Á°f͚ѥ¤¤„ŠŠ Z[[ÃßÙìܹsÐE},¸G¡OòT&NœÈìØ»eÊHïú éÍ6!³Ï-hàCj œ:i?“ÞV#p ŒŒƒR(Åd©¡’"“úË"3 ?ðGg7ûG°;íœ A!áêGúȆ†BÙ§?¼õSlzÎß6\t'n¤Èˆ&Á{«›^>PÈúì¹!]õãµeÖñ—÷¤bº5ë{|¨y ìëÁ{¿ÿ) 4=û)ðê~}¿Óè87}dB·„e$ú¶£‰hú_>˜˜a4ІFœ84b``c!BŠVmc³Í€IDATú_)¥"¬=R¨¶S„þ3ÜöéC·C‚z‹†‘q uE|ßǶm*++ñ<ššb±5558ŽCmm-¿ýþ÷y衇¨©©¡ººšÚÚZJKK©­­%‹áy^8=‘H‹Å(//—Ï^¶¼¼œÊÊJjkkihh ™L†âïû9ÙA'ØGaà¤R™wEËʈ&±núÔ¦ÙsÄËX¦}Ûìt±Gï?šq³Þ™ÕÃÂZN¸“çyX–¥j§Œ•aTQPA”q¶··ª }³ªª*,r*ofkk+]tÑ ¾Ïqàå—O/ôa cœ’’fÏžÌ>q¯Qð=Ù&0$öéà° \¨}Ž™¼™c· ÀO?üS嬴QÎÎÐG¬DrŽLTº.õÒc .}à³6€8JhÑÓÓd´·­aN1×…× Õéýçô¨³e5+ÃmŸ Ò} zD| ]m4xAIu³üpÙs %nÖ~÷EO.;·\Z( R|ù@‰{ÁÛå1u¯ÅÞ 5+¡ö'`ÿ.$öAí§ÁÝ öÏT*‰à#ƒÔ}ºÜ· ñÿ¥¿×Är¨¼P½àw>/©k ú}ºìÛ€Jp~5 p,ðƒT%Ø?TëWW§÷¹:3âN~ Ý·mä[—IOÿK¦ÿpa``a¥G1z˜˜Ä‰ÓF6Ý;—\\|é4Ñ¢ía` §}fG¼g“H¨~\v /P#µËËËq]77‚–ÍÍÍáÈ÷wíÚÅ‹/¾ˆalLJ‰ÇãX–E<§¡¡h4ЦiD£Q\×¥­­ ]׉Çã477£ë:º®ÓÜÜL4¥¡¡]×1 Ã0¨­­Å0 R©åååadJ$!‹Åp]—T*…çy¸®Š4Bßèº tˆDr?BJ‘$u(8ïÛº0u~Gï9õ:E ¤iš9ÑcÈ 0Lˆ54ô«†Ê`Y±bk×®eùò唕•±~ýz.ºè¢°¨_]]×^{-K—.eýúõÔÕÕ º¨“ëBYÙØÉc(§ìcœ1ãEŽÝ{p¤wgPôe›04ö9tÐç»á„NPçðŒ3`9Êáj¢<æ¨Þpv‚Xús%¼@„ŒSTÚ…¼p]·hQu !ãçÎî·Ñ+ÁßÁ ¡ðvVrd߇'485›cçôŒ#}„ƒ§Pö9¨"~A}uM‚ å .V<=?°q;=­hH/ç£n†Þj‘ô†M&7\Ð÷ÓßÍúÎásÅoVâGêˆÿô—€=Pó0§ýqˆ~¼gÀ¿’‚Ú´hÿ˜ï@Ê7ÉKA›ªŽÅ?Nºh¥fC¬>Õ¿ƒæwÀŸ5'Cƒ ÎNh\¡vÙ®«ì°}ˆ~¢_¯jþ?ðCêIˆ| Bòëúè·AthKÀ¹"›!u³Z´“ÕK¡ë‚ვì×Yú`¸ú¶^A²´:: 4t‰” "\|ü.µS"DÂ()âÄ©¥6<‡ÍéJŒX(ÌcŸBµ‚ ôŸá¶ÏžZPÏS…Dz,LÓ¤¦¦†d2™SÔ¸sú d2ɳsæðØÌ™aÜec7Å4LÓì’õ"{[ѬJç‹(G£ÑpZuu5‘´òÓØØf\ DÃ0¨®®F×u"‘©T*Œ¤ jÃZ– <‚¢ó©pœî³µÏM³ûÚ:c™Bûmƒ¡/“ç‚gºÎýi»J¥R˜¦‰®ëD£Q‰D¯É…®Ï„ òMy *MMM¡ÙzÙ«W¯¦¥¥% Ë [±bEXà¾ó¼àyp×]íTUµ ÷yŽ@Þ™<øIé`ôç²íÍ6aðö:‡\ˆ~Æ?ö(8K”#5(–a¢Ÿ™´6ñô´j2bJ Õ²¦PØj;2Þùôw…ˈÿ$¤ØÍÞ.Uõ’Tœ…u>\ƒk"2T‡l|œ0Œeÿþ1 ¨0üö ÊY9 ú)1”­9Ú‚ôXqr#Ë‚ŸìACZúsð;»IOßefmÓJO‹C8HÝLO¶çÿ-ð"àÝ©‡!ùOéMÍçY5߯A¬"g€5"¯€¾6½O5@"w¶Lh†ˆø¡Ð«¥_¼ªßÑCê³þYˆ—€f€–PâGì0–‚Q¥îûj,Ü7Áø+®Pë6¾‰©`-ƒè7 _æõô‹žè÷C¬’çBà J¬1ªÀ»´÷€w+¸5B3™T‚Ï‘ö’8 GßÖÃÞ|EJob‡†F#]–O’ÄÁ!•ƒ«¤ ‹¨¡'ýÏÆ×É7rF½¢ía` §}fG¼ÔÖª¾ú»–h4J,#•JÑÐÐÐç`3]ׇ}¨C½Ôf‰Çã]Ä˲rœÇ®ëbYV˜¦,‡BL"‘ ¦¦&,Ú­iZ¸¬iš†ÖŒq˲Ðu×us„˜ ýX¶P¬gFa3ˆÇ»ö}»+%Ôå‹© ‘#ÇA×õ0:Å4M €ëºTWW‡â«ÐòTZ[[iiiés¹¾ŠÃôVÈo(;³® ÇûÇçÔÉŒ“ëHÕÉ8I-ÔÉn&7%O%–=ÛFÔÈö`yõ¥™ÂÙ£²(‘åmwƒŽo1ÒÝ^u¾TA½•Ã&,ŠA“W¤û÷6àÅÀ2”¨þæ› Gú†Œá´OP*"Y1“2+Šº@)2vÖHF8ÕÓ?µdD X;émDP¶k“¹!b¨g@uñÓÏû0ïâû3DçS5K¬‡Á;üéÀÝàT?ñ“ õï 7C$¥~° ²X7¤¿ç; e‹?é~fdð 2NvDNàëMå€ö9U3ÅHç³³‚g‘IÜz0~‘>_>øóÒçb!O“Q Ð> q :—£0Œtþç8˜ë!ñ4˜¿WÛ3À `D/@lxŸûé̺Ùi/G þ’w’þ3}Û#QPé‹î/Qâ¨ÑÀ&&ÕTcbÒH#±ô¿$I||bÄÐÑqp00ˆÍKl©¦:LQ&/ÃÝv ‚0p†Ë>³‡Ž9ŽS Cõo‚Ñí…‰bB×u’ÉdŸNâx<Š/–eaÛv(¦€ŠxÉŽˆq'Gª««‰F£á@»††R©®ëâû>±XŒdZ Ò% |ß'™LRSSC$ Ó†A<3!Ûð±e—–|¾³÷Št„J^–™È†#ËçóI>–±±1 Ãh M&ù[D¤‘¶ãÈÈH"-ë±200€Ç\®V«”J¥$äØððpÒ.å4 Çq( @4àÏ÷} ÃHÄ•¬Ø"Ó}ߟŽ "±È², àR©$ž;’kƶíDÈ1M“F£çyÜ{ï‰|íkw°sç²eË») ضÍç? ßùÎå<üð_³fÍm@$:9ŽC¹\¦R©$9l ÃÀu]n»í6~ó7³×·Î²ÁÇO°8@¬ß$ÍñLi«Døó<¯mØ=¥3ªÕꊗ’Ž•}ûö1111ë‚~Ã4û+W€²r¾6€7¿ùV^þòàžÒežŒÇÁø˜¿ÆncjO¹¼=M¦ŒÂn‹Œp—ú¦„ü’| 2h´oû¹ø³J$²ˆW‹äp°HGÌCÚ PfÅP­VûvB½Ãå¤ú~Qøð¬‘^¾—YðsNÍÁÄ1ôú– óÊ¡2L*JdÛp&©pç-ñ¾æ0ŽˆÖñ'¡¶ òÆs`Ü TÀßüÔvCþð~E¬ºà¼œÏ‚}Tž„Ü À{ &o¾ÂÃû5ð'ÀþC°%ºQ.ŒÊáPá6“'±÷l»µ1Mýa.óÑñäʱ !! å»+²‹"”a,æKÀz[Ëö,R¯» †‘Š!ƳEÎ&)ÊGaʼñ(ä…YˆÎ±óÿSpþ8%ªÊÁ·#¡fp0êˆð¼ôÓ÷ÓdŠÒxxm½W Œ&1DQ% h`Šññ)Q"O ŸF(RÄ¢B…9Ê”ññf8é¨QÃÆÆÂÂÆn+R;8˜˜SÊ+9bEQ”…“4+Í´Î222¢9EbLÓ¤\.ãºnÛóÑh4p]—ñññ¦é¶mÁ”<1F#ñB)•Jضˆ0F¬^o~‹WM;oœjµµZ­I4 ‚ S”EÄÛ¶q]—b±˜ˆ#ò}||Ã0( ‰·Îèè·Y¿þÞúÖ«¾|>O¹\æK_ÚÍ®]÷P¯ÿ-7ÞE¡PH9PZ¬÷¼ç=|ûÛßîõ¥]V˜˜<䜲ÿ”© øþ”‘]âñÔÎÃL½»;§SÑV™žŽ•Z­Æ®]»¸þúë“iÛ·ogëÖ­}ë"pÑE÷a*¦(‹ :qެÁÀ¼Ö¬ypæ…¥v6lh›ò¡uzö1ð¢øs<³¬$ʉ§‘ÖÂ-¢‘öޤ_æ•~Sæt ñÿ/êà}© 2bÃ-¸º'N„+z]ÚåÁl‰šK¥È"¹}|";m³šë‚Qcwt} F~òoç‹P<ü/€oÂà;¢ŽúÊÇû3 :œ #?…Žù q4>í³‘Pó,|â_NãìMû¸ ülÚ +G®ý†‡ˆËæyV1 Eà¹^Ò0pÛ¶“ÜääÔl2:./ZXMôXhj27«å{˹3b¯ÇióŽéDmìàÙäJ³<˜WG·jFK+? ¼Ìì|$ÖXV”w¥PˆêWž—¶mìy¤ÝQ”ÅÆŠÿ:ÅÄÄÀhëY"!¿Ê™ŠˆƒÃ#Œ3Žƒ“$º71“0c&& xñß0ÃÔ©caááQ @ž<5j4h`bR @@€‹Ë8ã*ª(Š¢,éj¯TÒÁíêJ;S$¡ý\æåóù)bŠ,‘°Ñê5`ÛöDhY 1&Þ,BŒŒŒL™‘ãº.F#ñB‘PYaH„×u9ñÄ?eÍšM¼á /àÆÓzÿk^s6làøã×$b D"P¥Ri{n~ë·~kÖÜÓÊT‰Û?nk…mG —–Ä7’+(‚)ƒß´¥,%GÌwÅë®»Ž‰‰‰^—Z|?MÐ¥(‹D|Q:ÃÅåx ŒÍàn†k¯ýrÿTfËñ¿MÔaÙzqe¤=D‚‹„1’bæßµø{@’¬]øÙ’ow¿¥,A¦œËq"çƒC¤É'-`³ëMØœp÷£½.æŠÀ÷£F©ó—¤Âãt÷6QÇ»çAá“ñgÞøÆO³gõʵÈ#¢ü#¨þcR*Ÿ‡ÆWaìQȽF¾—¿þ[ÔÿÕçó¿} žú+r¿æëHDß÷!#kNz÷éJº@’B¡€ã8I£IFµyžÇÈÈ•J…ááa6lج[(’ä|’¬Tz–J¥d¹‘‘<Ï£T*1<< DüÁÁÁdÿ˜$ HÏóp‡Z­–ž¨j4?Y¾£ká'sEÚ¿¦ Ø`O· 8˜$ ?Ǭða¬µgêuÈ¿ WÄ÷C|”Jѵ–C™Ã!)m˜—ǘ2'êÔÛ *&f“˜Qè0›%,¬¦»…•„ÿ21ï•:uJ”’Ðb5j4h$ŠƒƒO@@ž<à S#zFT¨àá0’<|¡B… ~Ëú²Ž‡G‰RslrEQ”Ãéz­Õ`÷îHêsýòx92×ÁyÙasY§\.OM ÃH„’V$¤YÖ£eºå¤~~Í5—rþù/˜’¨Þ0àÀ5MÓ$™išmE%e~<ô_pêÇÚÌÈç£ ÑrqêõzºMQzIG*Ëσ»îz†\nùå~Q”•Èi˜ðèû¾}ß'—ûÛ^i*mFŒ'Ó]¢û2ÍK•ÔƒEbÁIG¢ä!MÌ-¹ $OC@$â8¤^9Ã4ç¡È†)râyvüÝ&ÍÒ.ÛÏuvWI=püø3Ÿ9Ù„lò2ǺLBœ]hÃ¥f=iŒT«(ÃYW~·×E\öT*Qƒ4—ïG¤'Ø…l.æ ˆIbsß— ÆÆò ~œry]Ó@Ïs)íDìÈår<öìÖjñ‡?üCüáÈØVÅ—Ž:-ËJ„‰7¾ñv¾üÇÜøÉæˆò½R©`Û6###˜¦I©TÂ0 êõ:¥R Ó4ixI’ÍZ­F8Žƒã8Ɉ8Ã0’„žõz=©ÔK£]ö)/i$!g¹\Æ <†‡‡“Fã=÷ܼˆ-[nÇ÷OjJ*¡ÇÁó¼y7äÂ0þb€ñ¿alÌ/€ýbà,RÛÏ>Sâgƒ‘Jÿ'°ŸƒÒƒ‘°Â±Q[§R‰²Z-ºr¹H„QæÇ\<.wæê¡sÅ(‚G±MLR;5²e‚HLñðoÙÖ ƒøø”)'Ó†ÆÂÂÍüÉo“ lljÔ(Æ..#Œ`a%ÂŒx½88äæ·PQeùᑎ{ÿûŸâ“ŸL{jµ¼7Ì'qø|®U§áÜLÓL<ËM3ê³—öK–\®9}GåªQæÆä7àÅ?‡‡ZgFÛ†D­VKrò(J/Y±‚ŠïÃ#Ü ¨ ¢(ýÆ 'œÐë"Ì y‹÷ŠT¬¤‰í+L 5g˜HqH½`²Tˆ:.KD‚G#Þü–ýIŽŸH¤©Çˈ(㓊#Vf™€4N ޝÅëäI…K’pŸT¬‘Dã}ܯ·ÞŒN™QtªÐÏÓΣN˜i$³ïƒ¹1òLÐ%:éDž AÕyƒ úó›¿È ^p\ ËI¼D²ž£â-Òh4¨T*IÒÉϾ‹cAxd¸®›ˆµZF£‡èº‡â…_â—ÊaYVâ–/bG¥R¡\.S,©V«xžÇàà`b@\Æ[{–eQ­FŠ‘$Í”˜½†“ŠGAàº.6lHâGK™kµZ[?I:c¹ãO0r¹\²_fä˜$þ²çyT«ÕDP¹ûîWeλO£ÑhDJ¥Žã`Yäóy*•JÒ@–­T*ÔjµÎqH/Óni³¤®_ERC“g’ Î'¡øRÈ?•5œ ÁWï€ymfS™gØðp´ŸÁÁÕݽ©•Ê¥ŸÆ˜Û¨T ‹"ŶÏ×¹¶õ‘9Hœj¦ò0À@’,»®‰‰Kô0±DÖf8Éû"ù]*ThÐÀÀ ÿ‰(U£†u¦ÅCKrNEQñt]8xpŒ·¼ÅÒ0ðÊ$Y¤^õYjµ¨™ Ó%xøøÜ[úMžûwxnø¹ŽÖñú=< ĂͻŸz*]¿V‹¶‹6Åb‘ÁÁAÖ=÷¦iÆ#ä<ž}ö ˆêõztœâö/'8®@B™IÌhñ¸±í(”Ú¬0¢P]S¢$d…Ó6i¯ÊÿFT X‡œµ_% ö˜ß†ãÓüËàï‹î€?øƒsxßûþcinnEé!Ó…ÙšnºAƒÆ´bK«· D!Ä*T¦LaÅÀÀŒÿrä¨QcAÆÃÅM‚¸¸üÙ™%(SEYfxÀ©8.Æ?ð‰O4¼Måð$Û0M3¦,.Ïì…Ï|fêŒ6®CÒRqKé:JJ¿qãF6nÜÈ®]»’ÿ¡¡!&&&š¦íÚµ«×Ç“ðîwïæè£Ÿèu1E‰Y‰õü꯾xæ4ýÊRôÐ×Y\W7ƒÈ;&Ûg“#‘Þ´Üiþ)‹$§¡DB„•‰’WDÂJ%^w€È#¦O#^¦ËÉ©³ŽB‚œÓÝÝŒHdpàÝ»~ÆûÞ÷) ÒJ%°,Ï«Q¯W±m;ñŒð}?éÌ7M“uW]Å÷:ŠÛ6o¦\.GÞŽC8þw7õîpÝhãÙ ´eQŽM&«ÕøÆ?ÿ3÷œu«Ÿ~š‡^þ¢æáe"Œd?¹\"ªi²CÏ‹ÄHd“gZV´=ˆ¦{^TNqÉå)öŽ)—Ëóî^ŸEQ”ysŸo}ë€9çîP?,kjªÛNªíJ—ððØéÂsr¹è ¬B!õÂñ}pÖ¬9߇µkïÆ2^ÓŒ}Ïqx_ÐØÇÓa/ef>ñ$,âO(§V;Ä#q€HLŒ§ ÇßKñ÷QØIY§Bôp¶ˆÞƒñö1¶oßÎu×]×4ãÆ¸­2n&&&˜˜ˆ fhh¨í< 36LÞð†[XjñR­Êrg&ÛÌΟ«}úø¬:dñí»àÇ÷Ý͹çΰp¤£¸Ý=]BAßOFl“IDM©”Ö†²/fã¾O½^ç¨ ðô#Ì‘‘H<Èå¢û:ö  “FmDöÑ*‚È6Z†òãG §ÖÙÁZÖT”ÙÈÉ6²Hè°ÖýŒ§ÓETšŽFƒ§€gž9~æòÈs$Û ˆŸM{^ð‚D/mxOz*o=ê(î°íHÎ娵?¾ïsüí·Ãw¿;í3­T*%âØ´´x±äóéé)•ÒÇ·è9Âi#ðŽ[fz!,º]·3iÞ« D:yrÇŽ=«%üã ©^‹·eÇÛ²â ÔIôj¼ Ñ"k™íIç½K‚R\­·VVŒ!õntIã;Öâÿj<={¬#ñ¶E´©=¿¤¼"ùñ|‹HLcuãeäXd›è]dN¤M*™™m´ *"ÌL’Š)v¼žl'ëÅ#b‹Ï“ã2HE/+ž? ’#âyÅiÎ[%]‡Z|<ùôz”ßPæÐŸ¬Œ$*Ý|w*в0ºeŸ_¨axIâqE™ßê§¿8œ•®÷Ûbòðk»à§ûÇ#Ïuéi#šÔjµ¦ÒŠÒk:Tþðÿ›nº©©Q=44ÄÇ>ö1vìØÁÍ7ß̵×^;ëv¶oßÎŽ;ؼy3¬]»–n¸µkײcǶoßÎæÍ›Ù¹s'Û¶m›W¨±R ž÷¼ƒ¼å-òKQ:e&ÛlŸG‡¬‡ÕìŸþ%X«¥ù :AÏ‹zìZ;+¥·uÙða²Üääôû™kx±|~jI\ Q§¦|ÏvÒÖjÑt9ÕjsG§ˆ)2ÔÛ4£íz^2(éh•MÏ‹жVNæ.mF$$”O:úØ"Rrñ<Íku¬Õˆ:{Jñ2°ÈE;ñÄ{—,îF{@·í2qAíß w9i(à'›· Ž?ë'¬¾äð/-sÁÝwãY#@ð ¿Àø#P{þó±ô#¬|dª7ÇŒ…0ævú>þá¹ô?Ÿ‚ çp°ói Í$*L·½¹„4 Ž C^ýìíà…Ÿ· ÿùîw'^CÓäŸþ4'þÙŸáyæØ†að¾ÁA¾øþ÷sû»ÞÅ›ëõôY*çÞóÀqxà›ßÄu£žŽòÌ>²$­ŒmOÕsÃ×MòÈÑß^3÷kÑg,EÝv&DÏ.ÿ(‚À¾ žYŽ¿…ç ÷pNãȯÿVð®€Ú¯¦zCn2ê÷7_‚à× x >•ëÁ9?î7âÇýxô(¯vÖTŠà ü‘Ô9D"BšùÔÃ%z̸E(Ž‚ÿp´ g‚õ$ØŸ†Úm;*/ã›`­ëX®+Oú¬Êꃲ3y¼Y`‘¼“¼Û!Xf9£=¹À8Ÿós`˜üøÏBN¼T†¡vX¯‰Çä£éžmÇ #OV|‚T°ò‰Þ‡V¬”I½TRïP§DÄÁÈO—µÞlaaÁ¯7 æ7À8>.Cþ8øoï4(V€UDâN%*ƒšXúê–Ž£¥xw*Š2?ºeŸò*ð}Ñó§hïÒÊC"ïJo%¢Ûu[?žw—“oœd#OE3¤_£¥ÿÆó<Ç!ŸÏk^$¥;`çÎá9çœîܹ3™vÍ5ׄW\qEò»V«…ïxÇ;fÜÎý÷ß?e;—\rIX«ÕÂ0 ÃÁÁÁð¶ÛnkÚçý÷ß?ã6³eL3 ‹ÅbØh4:9¼EÁ^²=õˆF†ã3Ì—ëuA—žk®¹&¹o—+³ÙfÎÝ>o»í¶ðšk® Ã0 íЧÃÐ>+ ·n½®½m6‘ñNNv^ðññ0´í0,;Z¼ÃFØÃ\. Ǻ|³ŽÏ`0íö=9™N7ÍèûLÛ˜oYk›­´>ÇÂ04ãO;Œžãaãß0 óaÖã#þ=¯S §æ”ãítÀùç¥;Ç»„tÃ>[߉mD?B›04ׇÑ5°Ãðæ-7‡õz=<õ†ÂÿëþðÔ/Þþ~½æÆÇÃj]êÉhÕäwñïþ.œ|ýëC#œþÕP_„óÓ€ð¬ÏJË¿ŒyÛºO…Fþþqœ÷3ªÑh„ù|> Ã0¬V«aFu"Ã0B˲ÂÉÉÉв¬0œœ +…BX,£g¨i†a¼|hšaX.‡¬Y~çoÿ6Ìårs{6Ç”ËahÑ㽕ì;b9Ó­º­ÝaÍr< CÂÈ–ì;ðñ{ah?†öÞè‘Z¼! «7‡¡í…a½†Öϰñ“04ï¾Ù­\ÝÉ0 ­0zD×3ÿÇÃÐ|" ÍÇ¢õÃx3 Ã\˜>ÖsñúR- «a˜ÿÿ¢iÅ0z|Û™ÿ\üŸ·U Ã0÷04†¹'¢}Ë>òÂÐ8¾ì0 çÂÐ~, ‹†Ö“ѲV½R¬x»a¼|>>Wùx~ñ_¢ó`?-kÇÓí¸œV¼o#³½±ßŠ®zozÜB9³¾Æ×áÎhçcïÃâOÓó`dÎy9>>#>×Õxñÿ¯ù•9_ðúCÑyì0 ‹_ÃÆ7áù?³ÃÜxZöb†ÅÃк7=/ò¼.ÿ Þy>º^f|n¬0 ¯þìgµnÛ†•òÜR–7íú?–ݬÛ^0†_ÿúý¡mw§‡fÅ÷û†‹SëªccÍ] F#œ­ût¥¼#–¢ß¶6Â|˜/.†ágþö¾ð·þº†a˜ÏG ˆ ÃhjãLGS›VQ2t£ß¶£*7ÝtCCClÚ´iÚe®ºê*&&&صk×´ËLLLLÙÎe—]ÆÞ½{eݺu‰+Ù¦M›Ø´i£££sˆ$êMܽöî^jUÓã>“XÑ>Qê~¦D4‚­–ù.q¦%NµO‡4L„Oo3·Im/.£‡>mÃL¶ ,Ø>=<¬ýÀ8묖*¿ß²¢\sq Ãçêq‘M€=J¥©Ùéf+[;Úí[¼idD† í^ ²Ûé–›r£åw@BÅÎü.Ö{‰—i¶•¸ó2ê¶?³-‡YíÙ²˜¢è¶}N!Á™Ðøø·¿ßïS*•xê¼óxÃ_åw}›_¿õVìµk“Èm20¼^ö2¼j5‰Ü#—Up3Ó«V¯æµçœ³„W¤{<¶y”#ü>îÓ—Ï{˜œmÛIˆ ñ*Îår”Ëe,Ë¢R©D^‚†ÁUÿx”¸Þ÷£ç¯„ Ìå XäÕ§ÆE¿õ[Q8×ÁÁ¨’%y¦: XŒ6»’=ó»Q·}üäÇgݯT¯jßÓ‡Bѽ?„ÆÚ85Ê;Á_ æ³aì °Ï†ò­`ŽAù”æð_õK"LÉ¿}<Œ Æß­O¼ŒDªjÄŸuÒô( ôZpßm³L䔨Èü×ãÿ*Qİ<࿬û¡~\åʪÇÂä±Ñ6ʲUPßîÀüQ´1"Ç‹1Ò׌¼6ñ÷P»¬ã¡±&Z¶¯'“R¾ñø?¸¿îv¨•Ù"M‡âÆËIÚ)û0^Γ0ò 0ÏŠÊ.‘¾œø‰WH¡ì ¨0xyTæb| Ã@É„Ê)Ѻ•xº¸/…ŸýÔ‚'òäÍèxêñyãuѶÇâÿ\|}*/ï>p~;Úv9.wøÚEuÃ\–”%w*ŠÒ1Ý´Ï#<øÔ§žíJþeeÒ.µ¢i¦i7–¢ß¢ègÚðÐøM„Ï;6ª‹N^}||Û¶©Î5l³¢t‘y'¥ßºu+Û¶mkš¶qãÆä%ØŽ¡¡!®¿þúä÷¾}û¸ùæ›Ù¸q#»víš{oݺuI̾éxøá‡Ù¾}{ò[Rø¾Ïö‹¶ãáQ‹ÿæÅ|ûâœÖuˆZ?yÒQk¢ËÅF„ä¿Sªñ¿ÄˆÎ“¶ž¥Õ)-eiUf“s¶ËÿÛNÜXlÁC 9q™Gâ² dÎÅؾ};·ß~û"¸7Ìd›À¼íóöÛogÇŽQn†£Ázmä®™¸iú~ZSÉ&]î7‚ MÐíÊy6ïÊR#×ÃóÚÏóæ`0©}iö‘Eâ׋ð"˸¤¡¿$y°$.ÄÛ±´•øvš˜˜`ûöíìÙ³§7çré†}îÙ³‡íÛ·'•_/ ù\ÆÙ`¾ 0Á/þ‹.¢:>ÎI]Äÿ¼áÞú•¯`~ò“äN:)é|…èJG¦ÑE¸gŸt¶Jô›aÒ×C4²Í|YóÖ·rÚyçõú2- =öË|÷»ÏqèÐÂr´Æw¶,+q‘w'™o–eá‹ÍY9c‘Z–³$Ôðpó3pd$Ê?LÛ=2GGGq‡ÇŸ]8èwºQ·8z‚Ÿßõó¶ó¤Ú8¼†'Á=ê7‚¹ìÓ‰ž±AÖ‰Dˆòë zAóvr¯„ú·È$RéQL²Ûaj”K1ô9â,ÝÁܳCu'Z§N þpšZ¨çÀïùiRâ,UšãßûDvêÙ¾ôÊû¤Ãl“í= 9³zõòŸe±ìsõêÕ %Ëùø‘ð郷!í¯—íÛÇq—_žÏ8ã 6mÚÄ!ÀÚ Þø{⎶JÆÆ.Päói‚ön!ÛžË0•~f`ÆÇÓßÙï­Ft~Û…I«Õ¢ù¥R4¢}` ÈòùHh)вšYÞu£Ž×r†Ø'³]Ç\El¢gX…ôYjÅÓ$¼ Øª­³Ö\ËÐyC\·úº^ŸíEa±íS[ì¹ N}<:µ;x÷]=k xé¥ñ2ÙlöReÉ>f!VäQk‘¾šjñ¿„j¥˜ÙÖ§IÇHL.ê¤é]Y#ßÅË,ç‘I2ãfÖ‘PB‹Á¥§ÿ+§öv~Ú%áV„”¬ bÛ6¥R ß÷Éårø¾išM‹išAÐ^/—SÛ–ùµZdçÅâÔÖ(QÃë%/yÉŠð ƒÅ¯ÛnüùF*S]{å~-¿h€ñ{ñ ©ËŽÓwI«Ìžçašfâ©*b^¶ÓËqœ$dÝlÈö‚ H¶áy®ëFžWñü\.×4Ͳ,‚  ¯ãû~" Êö,Ëš"*šA€kšQØ®xpmÛL®_ÏÇãŽÂýæ7“u-ËJªÀ/ß»—Êßý]²Ïó’|•L’UÙgÎ4±‚€ZìQAb£ÙrÊ~’W¢çQrš]äóù|r~‚ À‹½M-Ë¢aÉ:rMlÛæ²íÛ9ý/èõí³`ºY·U”¥FúZ®»Në¶íX½z5›6mâä£á‘G¾ƒiP”Nh'¨ØöÔP`3…‘ÓºíÜúm=éˆ{.ú°ÂéÇ•gëvŠ26mÚÔ;AeãÆ\uÕU\}õÕ\uÕUlݺµÉsÇŽìØ±ƒk¯½vÖm]qÅlÞ¼¹É…L°Õ}zïÞ½©Y\ül›rÜmâã0È ãÁxÔ*µÀ?Õ§ö¯5ÊYN½8ªDóeäôS{L$X|¶o¡uœÁÔ¡gÓ5v³BD¨s_ÄŸ4dN@* @³àP'jP‹˜"!rrL? ±µŸ#+–4˜Æ,ó²ÏÁÖžµl™ÚõÄÉõqãsTŽ¿W3e—5rfB€I …‘ÌþÅ«(ˆ·½ÂÃ5Ng›°xöùøã'±ûçœ/e:årÓ4) ضM­VÃ4Íd9¤1îû>õzß÷)•Jɽéyžç1>>Îððp$$B"Æ09É÷¿ÿ}<ÇÁ², …»ÿâ/ø½O}Šã.¿œ>ó\×%r¹†a0V­RúøÇáG¥‘‘‘H¨1M"Wmý:66F¥RI®AöÜÊ2–eQ*•¨V«8ŽC½^g°PhP|ßgdd„z½žˆ@YA«X,2X(P,“saÛ6«V­Z Óè9KQ·­PÁÂJߣÓàãcN#¿K;5 ˜u;вRè–}þb~üퟨ‡Š2'ZÇgvš6u¥Òíºm@À ° „M·=È®³O›vYÓ4§oƒ(JéHPضmëÖ­£V«M±qãF®¿þúY½SvìØÁ¾}û¸ì²ËšFõoܸ‘¡¡¡$ÉÑÐлvíbbb‚7½éMs: µæ£xÏþ3nz°©BjbR£†ÏÈ·Fð®òÈ2o‚Ê©Šï,bØžíQ¢„U´1& ž¼””IDO­VKĈr¹Ìàà`âé$¢A±XÄ4MJ¥R"¶ÔëõDxØõz ’ûÍó<*• žçQ("/Ã`||œÁÁÈO­R©ÏçÃ0 \×Åu]Ç¡Z­6`t‡B¡ÀøøxS¨i\×¥Ñh4u¼ Éçó‹ÅÄ.òù<_Ú½›üÅ_ðÍj5YgxbëV~üãó½Xt–ò¸®‹ïû8ŽÃx‹7¨ˆ<Õj•|>ŸZ‰Žã$Ç(ˆÈc¥R©Ix*•JI¾¤,®ë2<Ÿ§R©ðÿø¼õ­o]øMÕC–âÝ ‘—gÓÀ¢º¯‡‡ÿ0‚‡G•j"ªdÅ•% F!GŽOÅ‚›àÉÝãì;ûlÖ,fá £»ùS„•ªÆ¶£Qâ]ÊÓ0…ÌHõ)‹í‡µvà—Ûx šft]jµfqHÂó•à%¼diޱ‹tÛ>³pfžüüÎ;YkNºü¹$´˜D¹¬Ñ,è¸q™²‚Í‚Ïgì%RäS:r+• ®ë&ÞÒqœEFæS¯ã¹.ï}ðAþ1i$^mO¬Š]­Ûúàßœ æyÌ)Yt°—J%òù<–e1<< ˆù|> ˕툗Nú\.×ÔyКûC¡¤µ£AD‹¹6„}ßÇ0Œ)ëär¹iCÒµ†ÆÊÒ®Ķm …BÛuZ;»ŸK¿ð¼§žjÞ>à}4ÿ¿õëÛîGì¤íöoYÖ´"LÖ&뙌"^ÕÛ„eœNüϳv‰^_ÿú×súé§wr¹ú–¥xw–(Ñ A‘"^"|Ô©'^$Òn´±iÄîeà “‹Gt‰Š'‰™,#¹@Ë”“ýñŸˆ(Ò.•ßÙ¶kUªÉr*É>œD¤a„"Å$²C‘bêź@|üä܈WŽrøÑ-û €Í/~‚wõú•åÄtMâÖé‡Kbô¥è·Ž€ùši½S$Ü—†ðSú‘y *Ýd¡y¿/üÁ!>óÙϤñ@|0F pÀ:/š˜­¼¶;rä’Jhv¤ŽT@!}_¡ÂQ™J+ˆ0^üg`$Ue`“½.ÄÒ3_û|Øûè§¼ò•‹[¨Ò)×é ÊÆ}—¨3uÍŠdÙ[ªQ6 l:"ìäó‘ Ò6ýÛá“8v¾ö™Œb À=ðàë6üù 7°ùŠ+8æÜs{}hÓ"BÇàÂ…mjFl¢Ð]gIË×)𼣟`÷“Oò³{Îbœ4 ¹Iäí‘–oÂlF¸“åDdqâýÏõ)19Ùþå&¢JÖ[%›Ü:ëàÄù%<ÏãÑÛogrýú)º_~9d<žW2ó®Û–ÀÙ9qš }U«Õ’0YÓ!a¢ŠÅâ´îí„‹Va¦Q›žçuœhÒ„ë­†‘x[´[g®ïÄ™òú´Û–a‰÷N§ˆÌåøgÊY$<íÖ™®ÜÓ!¶|¸wRÌ×>kÔÈ‘k á%‚E6$WvÀž|6h$¢G+¾E³ù~)g‚SZXŒ3ÞÔîÌâàP£F:ƒ âà#Ç0É—‹üΑÃÇo:bjÔ°±›–ADŽ?;ÀP¢9È>sä’ctq)QÂÀÀÇOΕœñ¸)RL.æÉ$mq7N[œ=v +)—‡—\ƒlصv´ ’9Ú¢1Åí9[é±°¨SçxÁÇgŒ±Ä;GŽ*U†“®E9×u©Æ1Ù¥ÃJbžCäîZ,“Øö"²Hò`I¾+‰l¥Ç4Í$ñ­mÛI¢\Ó÷!ÃuÝ)7YÁfAâ t7T”iFÞ+ÙL‚ÃÑXT,óõ[¾Î›ys÷ö¿B°±ÁïH8ŸÆ_üÎw8Ù4¹°]¬ ¢×ýž%Ø×x‡ËÉèúÙž9íìîÙ“Žä®={Ø»ÿü¦ÈŸÅ®H$H:/“4ÇË0‘¨R!Xjñò¹Ì÷©çÌ\‘däÙŽsy†•J¥$¾±çyM ¾7ÞrKô ¸÷Þ&qXé€"8›¡~lûÙºKˆB¡@.—›âqÒÉ•2qÀ4Í9_?æòîÄ~¦[o.ض=§uäØçz,s{D4™î\·Û¿>*L2É0É"ë‹'M‰R2°±F- m&bˆZ&fÓàÆl4/Ùw«1È!M@œ·µäœHΛ%jÔ’2ɹ (Sf„‘¤¬²m9õ-Hx¸€;°äXÎ:ù¬^ßþ}Í÷n>³û·êª(J̱Áfydw¯‹¡(ófE *kžYÃåÇ]>µ· Ë¹t×bñÆf—<ù¦ÑDË ß®³GæÉˆ6I )£SeD$í%ž$ÛPœ.&µÒ}òGÂ/o¸ìíKº_Çq’{áÛoÿ6ÁѶÕY-Û÷ý¤Ãp¶p%Òaäºnb¹\.IÖëû~2Â"j¯Šr¹œ$˜•,¹\ŽF£‘ˆ/®ë222‚eYIB_Iíû>Åb1 -QÈI„›Ïç¡&é¨O~·&Ø“p#ÙŽa‰)/á},²,6…B–J–R ntùo?ùo½.Ùò¡ÁZx± ø>/½ë.Ö,ƒPwyàk‹¼Íù±boŽãP¯×O2×u“|":ds•ˆ½™¦És·ÃÞg^ʺ}û€uÔjµ$iõ'vïfóÁƒ˜¦™x£@œ.È÷yÁqÇñþSN¡L$2úŸÿÉ¿sæ)§÷Ç%)Àñz‘·‹¥äviwÔ"ÚV«U<ÏKž«â"Ï…|>Ÿ$Ø®Õj˜?økþçÿÄm;²^™žàO€žêe$ïyA@¹\&—ËQ–¼UÓ %™ºÑ”ü!YaÚó¢íXVÔÓ?óŸüá#Ç hîõ…tz.—x@š¦ÉÙûöEÛšîyâyM“mß-žíGl2š¼mÛæõkׂë¦y¸¥R)éøñ}?éÊårÉÈyS²Cv¦q*ëµ3d=)BŒaIUéD–²KǶtKy¥ZFãg°JBQ !ËI¢THGhÊ>4>cwxù&ì;é¾EÛfö~Lâþ‹¨`š&Žã$÷Ý}/»½ë÷&™YÁ$‚D¨ä¶Ò9(÷„tnÊ>³‚†ìOFðJ8IÒÛÊt£‚e›ÃÃÃIèÃ0’åÅv à —ËQ(’;%ѯئ¸ÉJù%ÌK­V£\.Óh4’P1A022B¹\&ŸÏ'"j¡P \.ãy®ëR(OlW:æzVéÉvˆYVT3®T8ë±k{Sžåˆ ãÚ¬7<Ì k×òÉ_ø…^—jVŠ0í[W:û³Ïu±éPö}Ÿ‘‘‘Ä»+—Ë%Ó$¡µˆ‹b;…B|>Ÿ$h¡ ^¯'^a¾ïS.—“wjµZMÞ³Åb1y/J÷§ßôxzÕ…59N­vSRîB¡<$)÷ÈÈFœëÁu]~æû¬*•xðÚkñ¾üeîã…Ï<ÃW÷ìá=ÇËçÖ¬Irº e}+D—*‘3L$Pe‡ƒT*ŠÅbJÞûbûò,ÊårMôR.ß²h¼ímSÂ{×]œy÷ݽ¾}úçuS«³"¤Ø¶ÝôÎò<ßyÞóÒžÚJ%zæóÑ´´Ç¸à7~£y @D=µÕjÚùnYQ-@>Ëñšý(푈zróù¨.-Æðp4-,ð–Çz†+•¨ "6x^´Ï–˲Òw‰‹çä Œ>ãý‹Å¨gÙu#=.s‚çEËKÙâäë†a¤ËCt~ÆÆÒee;™wð«O?=*“¸üŸÿ-wãðÝï6‡¸ô}ò¹\´b´ç[Îçðpt.ŠÅæçV©-cY÷ÇÌq"¨ø~tþl‚€Oäó©påyÑzù|TÖz=Ú·œ£\|Ÿ²e5ç!+Àó¸èÜsaž93$÷ætˆÊí-Í» è4ñqjRõ<ÈçmòùTHyÍk’Ïÿ%åòU|ä#û9ãŒ3’}ˆ#—VtVËJ1oÛŽÊp[؇Ͱµ’“ê€r{™fôïºÑ#FnµÈl †G¢é¹¾…ãDë˾ #÷‘) i5Î0¢uƒ|ßÀ4 r\ï<Á¯Â3š#Åú>8µ\2Íu£mFž@`Û&µøÑƒ[ƵRI×1›Rý¥Ñd­è TÍ*• äƒ2Å"8®Í&¨•seÛv" ɺÙÄÒ"Àˆ¨Z,“íŠMæóyœ8EV¤Qf.adL»gu;ãyß{ÞÒ•c9€ÿ^øïy¸ëÀ~øa>ùĽ.Õü'ó,N~y׈m•J¥$ŒU>ŸOÞòœ©×ëɽ,ïˆî÷±±±$$<$,ÀØØØ/IÙo6™´ã8T*•$7„û•¯PyûÛyö©ï'Ï5±5Yß÷}Ãó<†‡‡i4Ñó0>òøÈGp]—ãž|’êå—óª÷¾—ªUrkÖP& ýuúþý¼wÕ*ö¯^ÍiH1 f_Ú¹“ïxb2@"k×R¿ÈårÉôÖçxêÈ<fs¹GîÛ§‚Ê,¸gÐtVÄ“jµŠ-CÖ!©¿ÇÇÛ{Z˜&„aÓ¶Ïö<^ûïÿžöb:NôÜÌŠ)â`ÑXüO|"ÝH¶ŽjY©à!½¹D÷ûÑÏ~Ôà 4õZ:N*ú¾OÎó¢zºˆ0’FD˜|~j9—‹þÛÅÚ–}dæ™r¿V«iOqÚ‹­#=ͱ0uáä$ûO;-=ž,wÜm¿µÝ!½Úízl¤ÌrÞbÆêõôÚ´´mL3íÑ®V›ó‰YVêÆ ÓÅ;GÚ@r ²ïOÛ†j•õo~3Ë÷ Ð}\Üi½Sä¶­×SݬâÅ'ï+Aê“ÙA?N¸nƒÏ`çÎÝœzªÍªUÿD>ÿCÎ?ÿÇI½M<زÏå¨=Õ{ 'ÄcÛU †m[ ~J}}÷QÇæ¬¦2·ë\,—S™R)MÓgšÑoIÆÆšÏE¬éašÍ™&Þ6†¦P³ |cä{üG¬£ ©Ö)æm‘)d›Óò(‰…ßÊ'ž=²_AdŸbަiÇâ\–u€+¢mNzòÒüO¸ü³ݲXLuLÙ~öÑá8Ñ9Êz!‰-iŒÙ"xFŸÜëÓ½x%d€„ ûû“ÑV‘üÓy›,7D2MsÚ„¼³­/ðr¹œØïððpjL„ž¬`Ü5ï¯Z- —ÒBö¡¤dÏËŒ»ãÿœ¿Œ7}ƒ×}ûÛ}S/Élg¾ÜW2­D Ã7ð+~"ЇˆãÙÜC"ž‹€*Þ]â­X*•šÞ#KEíÒK©æró™Ïð­o}«í2Òù6Û³(n¼ûnþûE¿pÏ=\µ~=—Þw†aðÒ?þcþÇÅS*’>ˆr°ÔˆÚøw>ø 6°ésŸcÝw¿›xÑ:Ž“Û&Š”r=N:òHÖ=÷W}üãK~žû±ÏÁ»aììtz­Vã‚O}Š‹Ž<2zæÅ"Ã÷/»Œ-ßùþ\Gñ §Cç§öx.ÃÃíňêäccSë|©€Së–íInáûìû•_aíw¾Ó4¹DÔ7VýË¿Äþßi^GÂnÍ5¡ª´IæòŽ–Þì¹ä½’^æ–ç‰ÖmÛ#uÛ»·ÝMŽ\SÎéd—Žúf/ ŸÁÁÁ)žùR“÷mvPP+sm²ƒ¿¦ E;Ó22PF"ˆ§sö{í®kyð³òþx?_ùØWoNXS(’IRÎì #ñ~Ζ½5JA»|Zí¢*$ç–€ là?‚ïqfpAjl¾«ùŒ™œé14Ì0yòmóèd£$.F3üŒ;Ï`÷K4ï@+W^y%wøzxï{ù£o¾Oþ&=8 ìÿ´ñ_èÆÌJgD÷—ÿœå[a@ð‚ã  0öp&ðc0ï6©mñ)V-87šÆYÀ)À}œ`ü܈~ŸåÊñ÷øï-â^à&9vÊ{˘ß5qNqðNö°¾daÝ΃JžùY’¥æåÀù—|焦]&Ûq5†aðû—]F9î$·=ûï»7 1 ƒ‰¿ø …#ÿôO‘Nì”J¼ó¢‹xvË.}úi^þÌ3üúÞÀÛ~é— jG¾ehˆŸýÅ_°õ±ãcXñÈùÄ_ýüà{rž— -vßü£?â=¦ ×^ÛT=õÔSÉͧg1Û#Y,ÎÞ;)1tæÚ9]ÏgV4É"ÃÓÅf;éÌz¾tŠ„Ëêôbš¬}ôÑö»hS :W-yÊfEœÍm½=Û§¬³Š,5>þ1E¢ÉµFo1Yê®Å8¤[;$tìtX–5ëûi¦e²‘²ÓÇIêe/~âżƒwpÆCg066–„GL<2Ås3=þ ‰„`Û6ÃÃÃÉ@†\.—xâdÅW²ƒd›2Wò’Y– ø_Ãïk%õx©gf…4!!3%,­ˆY"î‹' ó¤ÛJ6—¨œï{ó^ƒþò ·¥ÒöJ‰jµš “Ü…²Ÿì5ÏzÔŠ&$å8žù•gà%]º¹—9ÏÖ`§q¥GKØŸ·ÉûyÌ›ðEð/ôáA°Î°’|9^Ô><ÂÇ‘Ÿæ·9«ÍÆÏ÷|—v!¾g^—™¿x$æÇ¬‡Á hÐÀÅexÝ0¦m&ý¼—zp1T¨ÀN`M´ ÉÍc62÷HÃÄÀÀ{ÆÃzÌÂ8ÕÀº;_þï6ÁÁºs‰9hF®®òŠ4‰z®‰?óD‚Œxâ‰3þ÷3Ÿ~¼l@*Ø8D¢G*,X™}ˆPƒ¨·ÜÆx_•xûV¦<²/Iì'ÉþÜøß$ˆ·#§GfrdE$9þB|,f¦ü%R‘%;>¥/[ËlÏË0O…¥u­cõi«ëv^ѬÎdOŽ{ÑÓÀ1SæKŸÂlylÛá3:¡¢Ìƒ%¨ìrOã¨ñsyxäa^Tútâ¶¾ †B›0>2òæSÏ>KpÓMX–Å¡W¼‚J¥Âÿ.ÿo xã×îër^xòÉ4>ýi^{ðµ³wÊ÷]z)ù¸"%ù |ßOâdÿö'>ÑT¹{Uüiš&þÆ7¢ñ~ÎËÌC¼Ä—:[AÌå¢Ñ€­bJf[Óž›éFú~äͶ(ëdãggÉ6jÛ5¾E(©TÒ ÀŠ4q(ƒ\6¸pvtŸ6†m§\ŽæËèAi¼EwñÑŽC*ä%FøÈŸ~ùËñâFÁ¿ýÛ¿qÉ%—Ìÿ[áìž}ø(ÆYÍ‹/¾xÎë …$U©TJ·µ†šæ°UÊôH#w¾H¸£V¤!œËå(•JIÇ„U’‘&®­5·…ÒLLpá´‹áe/…Gk·cÿéŸö¤,Ò)S.—“œ?ÙP{@zJrtÔj5†xÝë^Gñò´31›ïc¹011Á£““ tÒ¢l/ŸÏ'¯ÛºuÊ|©³£¢nÿÔ§È?û,Žãð§õ:ß>þx>ù£ñÃSOŮݰM¯y WmØ´¹sL?1›M¼\>ÿùÏ÷út÷5î`íΈ~ ÞþÒ—²fÛ¶)uÓS‡†øýƒ綃ÖzV'ñRœ‹Mµ&}ïtÉóÑ)†Ñœ ¤æó”䙺†œ¶µ©sÎ…ll¡¹Ð‰'O+ ~^dóeJó"½®Uü¯×ë}û.’pÊÂñÇÐ4ðED”,­Ç322’«¬+å"Ì4Ã8¢ˆ.2BþE|—|‚5jäÇ¢2´ópÉ"A¦iNë]ž 1_«Õp' /ÝnikÈ€{κ‡×ñ:þþþ>9—¥R‰áááDHIê-³ÝµZJ¥ÂØØŽã0<>öE6Ávhc®6“råk…‘ RÌ& üÌo9Pñ<‘pfø·MsŒÒÖWKÏ—S\'$꤂Gk÷ˆ6²Nö”×o;LR„Ì4xäE=/g%´I]#²û¯ŠNffýR<ÍÈ‹ »´›uõu(³³ïh §þßÝpñ/`na¾b ¨ ¢,!á2çŠ+®Ã0 ÇÃñðüúÇ·­»3üéǾ†¹Ü¢î§X,†õz=l4¡eYa±X s¹\899ær¹ðuO?އ°6ÂFÓúvh÷úTÍLµ†““‹·½ÉÉ0l4¾vÛ…0O§‡a>ß¼œe5/ÓÊØØÔí¶N³í0,ð\nž^¯‡¡m‡ŸxË[ÂF£îÚ´)ôgñu™sÛm·…×\sM¸5,†çòöðêçß‹Å9o§Z­†¦i†ãããáäïÑFØ‹áÜË tÆøøx؈íÞ4Ípll,ÌÅÏbÃ0Âz½ŽÇvišfhYVX¯×ÃrlcÕj5l4a>ŸO–[(òŽPšÉž;´ÃÆuah¾' Ã\.|ÝÆ]Ùg»kjYV899Ž…ãããáøøxhÛvX.—ÃF£‘¼c³÷V;Šñßrç¾_ù•ðóGÞqâ‰K¶O±S©çT«Õä|g¯YµZm»~# Ãr†V†õø{ë“Ú¶í)ÏÿË/¿<Ì·¾»•0 #û¬Þ†Å Ã0— ¿òÉO&ÏÒ¶ŒEu–¹0>>µ~3åòÜë×ÅbTÇœ ÆÔ:Y'e›ë:ùüÜשקԗaÎØ êF}¸Ë\sÍ5ám·ÝÖëbôR·5C3™fYÍ·„Ô[«Õj86×û«˜ '›Ž¯SlÛí¹>‡VVhµmëK]f¡´¾?µnÛž+®¸"ü»Þ~æÜ¿ ÃÓ̹?ß;Ä£:†a1 ñø³_ŸôÅÌŸÿÉw;´Ã|˜Oæ—Ãr8އŰVÃj؈ÿÆÂeô,›KwÁXU^çÚÅ0Ö~yG(SÉ>·a#úèå=Ò:Ÿ_œ ®B6›ßbbQbÕì¹6Í©þõ¶=óhÈÖû£uÄ¥Œò+—Û'=õ<^ûÚׇN8§Ÿ¾øÇº‚Xõý£8ð¼¹¹¿º®Ë† š¼ºšÿGY0¦i&#IÆÇÇ›ÂNˆG<'ÇÇÇ“pâ¹’.á\×1Œ›²H¼žÚ GGyþ<<É:AÂnA$9‹ÄƒIÜ»kµZbóõz= ñ7+%NîO~ý×¹ÿ²ËxÙË^¶dû;-—ËM!NZíNì´Ò¾H%VI£1\ùôÓ¼ôᇣßqþ©VN8á{ì±%=¿Ë ߀‹x|Ÿ/þð‡3‡hœÉcx:$¡ù\˜k~ˆê—s­ÛöÜëñmò€ÌÊ|¼Ø%„ð\GYQHBúZ-Š„EöL< ¤Þ³ÜQðóÁŸOè½€AûgB±X\Ïù•z¸[|íOÎæ–短F*”JQ\¾vž‰®›~ŸÉsÑq’e«D .0òÌ3˜_ø…ýû)9/xÙu¦kÇtb/’˜i¾ëûQH1ùÿä{ƒF’ÊÄÄÁ¡ôäûáÞ{ññqã¿ dpß9Œ<ýöd:D{Ó×Ñ ‚ô¼J8ý¹0]ý?–^’XAœÇ%sngúmX¤ž&¾ß\Ι®‡äPÉ.W«±úævl‡1ÇŸv›þþIž8®}RúvmEé7VLÈ/u¼“ƒ?Kí¹7Û !0¤ó [™iO¼9mYé: ­xÆÌÉM''¹¸Ø~ß}hÊÎéyŸgŽ7ØóŠÇ¹¤Ã†¥„I8ÓÆkùÓ®1(±®¥Â$†¶m'¡œ€¦\-ÒÙ+¡ú%qúr'ø4¬^ý$¼ð…]`Û6µZ-‰y.¡> …F#éx²m{Jh‘Ã%œŸmÇÒP¶q¿„HÜv˜Ú1M3 Õ— Ù— R®øà¹åÏþŒÓ¿øEjù<†ãÏçùÚ‡>ÄoîÙÃß­_ÀÞð¾ò•¯ôîd÷;ëá«OsŒùë¸îÿé†å|ÂP™æâ'ºWŒç%é4š›Ž[™ý«Ó܉…¢Ax’~¹j0G–¥x¤¬<î¾{-×Ýóÿ{}~\Išfô98}—A’³*Y—ôÈý,9c¥£Ý²ÈŸ>Ö)§`ïØ}ÇØ6à{,îk^CníZFˆDÿàAòÿðø?ý)…ßüMòk×&iHŒZ-K #ì³í×ö-ï^y`{^tlY²$º„Jo4Òu%,z>ÍÏç±-;:¾Bà{)½Ïcò~ cÈj 90–Eíì¯QÛö$†aR *‡ùðqøkÄÜ},Õ_ÚMéoÆ;îÇѼ§Ã¼íAX»–à˜' Ž?8˃ܟ܅ñà½ólŒ#OÂüäWpq±°0‡ÓЙíòëŠ@Í+$÷.Dç¢uð¬„ŒÏærsÝè|Åaä›ò˜‰˜&¹wåz8NzïØ6ëÖ¯‡“Oîµ, ö{/â¾/<Ë ®<0ežëº¸®«ï¥ïY1‚ŠÏú'Öól¸fÁbŠtòA€mÛI¾†™hÕÙWÊhYEY(OpÁùGò|vcgu´N©T¢X,jgù g¦NñXo@ÉŸõz=ñQF–ù!£Ë>ÿœöÈOø—¼tÑI*›M›õòLÎÂa!šô3¼¤>$ ŒEøÎår‰ r¹7¬Yƒkš\qð 7är–Åþÿ˜]¿žQêOmÙˆz¨LË}ß;þËàËÏܵ¤ÏµlǺëά‡d„J¿BDý4µZÚeYÑoéß‘£¹\4OÖË:û~ÚR,6§µ“u¥/%—‹Ö•}Jÿ”¤ÞË:•~©J%MóW©DëÔëQ•¤Ùsœt}ӌ֫ף>¥ì9ÙRFÀ­Fëȹ“²F´]ÓLSÊX­Fól;ZDz¢}Kÿ‘¬›=?¥Rê(yFDŸÙmÕjiÿ“”Eúë|?ÍE/Û“¾5Y÷è£ßÈÐPûQ£‡;?;åg˜˜x^ê|$¹RòsÉá³YîBÒBpéÍ@¥™£ž:ŠCæ‹Ò—Q6ÁQ«¤aÌìáÙÆ4ë/ZÞºâue¢>!y= ùw¿›w½ ó®»°¾õ-*—^šxóå2õÿñ?¨pþúõÔI󱛀ñ7ƒó¹Ï‘?Iej“ã'A^(ž×,¦È¼b1zðË‹MÎC±HÎ2¨a|¢ÍàÔX|È×jä+~³¸ñ‰Ãïþüñ0phðÉÈÛí¨üxäÌ-Û"¡ƒ5|ËgðÿýŽ]‡µw-žñc`ÿàà–'17 &þ3ÿ +êk+Û‰ÕøX8øE¿])sj†©P FçÈ0¢{Drñ¶”—cëù,—›–}xtFGv¸¸¹ïe¬zfUÛùýžgÕÃ# Ð>_eå*¹ÓÏâs¯þ [Œ·ÎkŽã`Û6žçáºnÛ|³¡F¥(-<?ýÒFîúÙS|ä#³2ð}ŸF£1cxeå0X-¢ÉððpR©’ŽÛJ¥B½^§P(àº.“““ضxª¨27,,z¼âÙ£:$·XÀ$L¦¼KÅ%[IÖëÕBvbašfrÝr¹¹\×u›D°z½ÞtmOøÉOøÀÎüšmó«çžK-(GVX·Ž‘^Tóàñpõ‹oãæ=?åSùk¼½¦h™<é"Zø~$È@Ëz=í‘õeðl¥’vÒË#<ÛW%"ŠDÆ0Íhݬ  ƒ‚eÙ hQL3í¬–²çói>x™/kÓÅÙª»¬ÛªÕJnùÁÁ¨lccÑúÙ>ªÖ&€ï§bF¶¯Å(¦‚¤ý326ŸOÇ{‰è$¦26 )CüøLDb±ù\ärÑy’íÈ:•J:?—KE$ÙOëñ¸n§^–ÏŠL7žÂZð}·R10ð¼è>(•J8ŽÓ^d=D¼‹W:Ih¾Pæ(é°äȇŸæé.j?ȶ‹#Þ ÒÜíy"Q$øGÁÀyçQ?ï<ŠDùÓLjÞƒ7&wŽO$Âä÷Ùg1>ñ 8ë,jDáÅ$ÿú¬ÌžS¦·{^Y&Pf–HíúÇâ—¢‡‹;%t`þ5Ÿ›º™8Ë|yM9=‚c86Rïè¨Ï¯ÿ™™?ˆæ‰°ibbc'áÈ<<òä£ã«×£—ºxœ´9–æ‹kÌ=´ª2#þÈâÄçžk;OB@Ï{^·ƒƒ…EyòT¨P¥ŠA‰¨rV¤È#©°§ÖôLPÙ·o{÷îeãÆMÓ'&&˜˜˜`ãÆSæÍFùÏC®|á…ó.“çyxž‡išŒÍ¤ú+Ê f:Û„ùÙçäQ°z<ûøã³Ž\+•JI¨¯~å'±Y+˜Ê¢âû>¦i6Ý ÙøÜõz×u“ðŒÅbqJ~‡•ÆbÛ'à§OÀK.?ŸFÅ_÷êl¾±ìöƳ®õÊT$œÀ2‰—ÞêQ”SlÛæ²¯|…ï ÔˆB_/Aü_Éì»u›^<]¶ad¶é¨ÿ™†kÉy âý:ñ9p3ëgÏ3ñò·Å¥ß@Üž™ŸËœ‡l9³ÇìÆûÉ–Ó"º¬øßËló¸yv4ö+‹iŸ=åqì v÷ú0H=YL ÌÌ“Gmv~-þϽK¼#¤pÖYŒÝ÷äÏ;þ” 1U¢{LéJ–gŠûÉ>S’T ñ¿¬cgæÍoQ:šÛå&20(2ý@¬¹i§I.˜´°æô/H%¡ý¶Çýü(Öýâ#³nÝ”y éÅÂ^9rI_NŽEб×Rd >>%Jøø˜˜Ôbë²°` *6ƒ ’'O ÚGtÓ3AEbãoÛ¶-™¶cǶoßÎæÍ›Ù¹s'Û¶mckìBÙ /|îÇ;¯òxž—„¬˜OgR'æ.ª(ýL;Û„…Ùç‡NúkþbÏg].—Ë‘Ïçû.d@…J2"FFÓ,&~æ/G®mRF؈›´,ïâR¤ˆŸT`kÔšÖµã¿ÈÚH*“ÓUH%± …•Œððð’ýøøSF´þ–rJ…&O?n Êo9ÎéžíBx™¦Ù4Í÷}‚ H˜›¦™„Z‰á£ºaŸ<÷Á…¿Uß_ý•J¥$/N©TÒDª‡9CO=ÅëÇǹ|óflà«[·òWý(ßÿìg9þSŸâgq ò•ÂbÕmO~üd&WÃÇŸä˜cÞ<ã²âÕQ,¦ùv‹ÅH@‘üåòT¡AB<Í¥Ê+yìçòˆ(—çžVÄ‘¹0ŸGÍ|œã$×\˜«ŽlYÑ:•JÒl6DLšËk¯UÈYÉ,æ»óg§üŒÞÛ1ÍtàGö½év~g;Ï]¢ÎJƒ¨sT:F¥8ó= êTá@ˆ—ó‰:f;­•Jg|«iy¤¢L¶5[& EdÅÇáÅÇYÍ”×ÉŸtYVI‚éLºUèÈ>’H¼͸n¼¿j›m´"×B:‘½x³™°„dÊÇë”™Ù3 „…‡G=>vÙ‡xÔÛ¬/àíL¶BÔ©=žYV<®txóÌï†åÄbÚç{ÎÞΪW÷ú:Fï"„ÈkÉ"òb!ž&÷¡ ÆËÓ,ÄxD÷Îxü}8^Ljױãå ¤‚Ïé}èÇˉX!µŸb< RQØÍ¬+ó6?&±áQžs"–Ê´Jæøä»Mú,aÑ&yä¹*™òñt7³/ÉWcµU³‚J…T°ÌŠ &é3ÑÌìG„b®²âïJ¦ý¶§\ð G¬;ÄÓÆISæ»®» 6¤‹‹‡‡‘xžÈõ/R¤D‰¹$\eʘ˜IÿE¶Ï%ë(ýAöKúcä¸dÝ þ³°šúAÚõyt«Ié>K.¨ìرƒÑÑQn¾ùf®ºêª¦yÛ·oçÚk¯ehhˆ]»v±eˆ††:R<Ç‚qnÜô'üäÀ}s*ïû”J%lÛ¦X,Î;V_¶’ÔNT”þf&Û„ØçÑð‰o]ÊIç}qÆÅFFFð}¿ëÞa>>N\í30fA#BF:%J‰ ‰@!£qäÅ+È´vdGNÈË`Arä¨QK¦É Yö-/dyÖ 2DE}‘u–² )ó#ÉrN¯6~Ne+&&ƒ &Û ©»TäwŽ#Œ#ÇMËŒ0’ìKbÊ_… >>eʳ ܦi&!³¿K¥Fƒ§Ÿ~º«÷ÓRÑ5û8{ÖÀ­·Þ:¯w '%Ã0’Ð}Êá¸ëK§ |à=ïá#øùñq¾ÿÄÊÈѰØuÛGNxãåÀ-§œ2õ("Šx?Øväϧ¹5fc>ƒ2ç““æ.@ôsÀ¶Þ.°èAÄ;e.¢×aqª-ÝxwnسÝÿ1„mGƒ^ÿ¿ÁÍ÷9šG‚·Ò®›È#ê°k} ·þž¯yL÷vŸ®Œi‡nv9;þo-G¶õ›uâš­V!óÛ•#ײ]h/ M·vëw‚#s\ß ùÚš¤ï¿ve›ʲá£V"ݰÏuOÜÃ罷ׇ6g,¢þéîå¬M‰Hѽ!÷‡x·@tÿŽÑlWv¼ýjæ·xBÉzRÛ.Ð,â˜D¡ÇJD¢Åxü9€ÍìÇeEJ¤bEf»RAv8þnÆÓóqÙJqy²Þ{â6O·HäÉv}R3ŒåyüŸxI¸YƒÅÓO„hö‚aufñÙo³Î^ÈoÞqÇâß = [ý¶ûUœÍž‡náô-©'¶ïû‹ö]Ä >¤Ï$O ‹2e6°!Y¾N½©O(ÛgÛÚ—“„ª£œô 3Œ‘ôs¸¸I8º •dÀkõؚ廟xºH‹ô2ÐÖ˜u€Ò+–\PÙ¼y37ndbb¢iúèè(ëÖ­ch(r/ß´i›6mbtttFµó‰'ž`ttó©ÿtû‹yÑÛŸ7§òT*lÛN’­.u¦ÆXЏªÊÒ3::Êîݽw+^ ¦³M9ÎùØçîÝ»™|öŒ§Îh_’¤ºÛ"8d•¥ÄóBÜ@e´"É?Á Ë”(aa%/C‰ÕjcS¢Ôô2QcŒ±¦é9rT¨0Îx2½UPie67Ó¬È[¢”x‡xxÉq)6•ÃÅ¥D‰±LsºF-9Öc,y¶Éˆ9îFج׃Cz2$+$yx($ef ‹*U|ü)^5†a4b‘çù?øA6oÞÌÉ'ŸÜÕ{j©Xlûç²I^Ó4UDY(† K_aa²O.Ó4™˜˜àùL|¯‹¶(t£nûìòä“7ðþ÷ÿ·dz¤¡ $¯n£M—<ÊÒÓ­f®ãt5Üÿ´hÝvfûÜxÓF¾óØ2´“ûN: ïï¤ÊÂE5ÕÔ,íž+ûöícçÎ<±B#t£nûä“OrÿQGñª^Ü‘ëÝÉ#¿ÓgMv[ùiÖ·[~g[YÕ–ïRÆrËú“™c¨bñ^¢vnVñ"6/šPÊ0ž™.n#¤ÂŽ´h³ÂxÀñ²9ÒЈ©ÇN8.öœ1H=ÉJ™óõhÉzÞA$0‰·„²•å àLLðÁ‡âޝPÓ­~ÛÍ›7³-ì¯Ãã—6?Ëjµžç-¨OHByIßC¶6û]ú(Z=P:%;ÈV"Tۼɥ¿ÉÃcŒ±D|10(PÀÄ$O>éññf8éÊ‘KúB ê#qq)PHú‘fÄ»R‘ˆ*ÒO&‘ZDØ bùSîƒ]»vu¥n»ä‚ʦM›X×+o×®]SÍuëÖµ}ÁfyòÉ'… `ýª‡ëªT*A°bÃÂ(KÃJjtNg›0ûܽ{7WíáÁý§ÍFH:c—"oJë‹NbjÉKMÜB[½WÚ‰¥zŸ‰¸"ëI23 Ë•ë`œ›…5e?‹92!+¾Ìäcc7‰)@“+jƒFÓ‹;+tÈù+RL*2_>[¯ƒìKD©Dˆxòd…›¤\mî›SO=•W¾ò•8p`QÎ[¯YlûAåñ3gíc¯æ?…÷ž|òœHȵryvo"¥, ÂpáÛés&&&8æÖ[yõÚµðÆ7öº8 f±ë¶{V­â¡úzŽ9Ù瓟<ƒ·½-š.¹8Zy†¡Þ +Éó²ÔhÝvöºí¯üÊ×ùòþ'ðËenf†NPßþ=/R>-«9†›çEîf™üp”ËÍJÚH<žZbç‹Í®R’{ Ò¤Aú>^‘ìÝ»—ÑÑQž|òÉ^eQèFÝ6·~=ŸÜ°å†„žêW:í-;-9žæ£‘0YÙßí¶.çD¼p²óŠ-Ë Ùtv ]øß€?Ççe™¡>åi¶%!Ä©fe…ìôщ 6:k×®…7½ig¼÷t«ßvãÆ<¸ÖçÌ3€—>Ó,üåóI~ÔùÒiŸ‰ôk,†Q¦œtà·Û‹›x¯4h$y\F¡B…1ÆšúF²ý5ƒ &‘=ÜøÏÂJìÖ¨%}WÙÐb*XX)ââ&ÑB d;ÎxÒ•Í!$QO$T{6ü<”ÇÃKúϪT“°gÙu$d¼”Kú‡$*Š ž=ò™EBÑK)g6¢ŠWÙlÂÃg? %È/n²žåPieïÞ½S¦uâ2vÊ)§ðÛ~ƒ¿ÿÄ?phUç‡ãy^b¨*¨(óeÛ¶mlß¾½×Åè:óµÏ‹.ºˆ[Ÿ xîÈ#g\®—yS² Éæ‹<ð§VWn’²ÙB¥Uç9Ö2{=Äk¦D‰$TX6ªi™ä­|“k-äY¹òÊ+{}ªºÎ|ìsýúõlÛ¶%¾z÷^zÚùÉ'̺/Ïóp‡r¹ŒïûŒŒŒ´Íu£(3!£ÚFGG{]”®2ßwç/9'ß5‰}±ôÅ Ð刘ÊèFK"Ÿ®ýR£uÛ™¹è¢‹øÈGÞÂ*÷þòÉ'±Ö®fÔjp§(g2¡û‘«‘aÀÏ,ø¶Ÿ&(&ìÍÁ¯pÈ„¯ûàXéé°.ˆ<ÀѤÙà àvÚpp‡ÿYƒ¿ªf² {Q Z<¯9’ç¥±å‚ úom‹`#˶&à ‚hž,×êe)ó-kî1ÏK÷/1ñZ…#׿ÛvúÙZÁ0¢ídËS«E¿E¼²íæ„NAK1ÎÌúµ%äܹn´-ÃhØ$ž£e¥ÇØrn{ýëÙµk×üÎá2b¾uÛ3Ï<“K/½´×ÅŸ3Q8­åN7BÍw¼ˆÉÔЄcñØ´Y—†Ömgæ”SNIò°„<Ã<~èPÓ2µZmÁùSzÁlƒ_³ƒeMÌdpètƒu³ˆ“'ŸD iÐhÊ‹;Î85jIÞ Ö A!þÃÁIúMF!  H¯I’ôUªI„–2å¦è,’cW„ ñ.ÑL í3’Å.nS4ñ&‘r‹ "óE8‘eCÂi=rd..UªÍËÛ?·†÷Ú÷ ÒndÂÄÄD¢ŒÎ„‡Ç±»ÎäÌcîÆ¶g™éû>ù|^GÓ*J‡,Ä>Ÿ9 ^þªN;ò½V«Q*•˜œœœu[ÊᇄL¡¤77d„‚¼X%<ÛáÄBì øÞs¼qã]<»ñâY—O2ñòìvΣn%#H¬Ú,Ra”€2HFÏí<Úœdc77û[*‹ÙpO ^ÜgÀABöši²†»p*ðr¾œƒS¬(ŽI´Ì•n´÷äá.¾f¥‰,`(€«]x¸™ð>Ô€/Æïœ:pV”ã8¼µOYéÐöÝŒùð‹6ìqáã ‘‹Ïí¾B$Týܧ÷˜éˆwÛ€IDATð¢Ì{Ùöáïâ÷ö‹Àƒ+Êð…¸Î˜®÷á!¢c]|XCš¼á†|;€ß©À«,Ø_†5¼/ÞÇß`‡}D×ìT Þ^NÅ1ÛƒÒœU„W˜Ñy²âc°=ø+Öy`TàXNŠþpjþÁá£G­Œp¶3±Ðºírd%<î[ó‰ö#Óy(±¶¹ƒï|þ8^öŽæÁ|¹\Ž|>¿h©VFSN˜,Ù»Åij¢i¤ZɱkcS 0U€ C²mÜì2Ùè+9rMmæé˜mPn'ËN·})Ï\ö±PúFPÙ´i;vìhš¶wïÞŽ½âª»yì–Ùg`` ‰±ß«ñвÜXˆ}†ϪŸ®QPQ1E™‰v¼Ùláããà$ÈÏ?îù½.~×Yˆ}zxì[÷;œ¶ú$~Æ]³._©T¨T*Œõ]e×ãD HE“l‚¿ì}$‡ aùZACFäHx@ɽ$B„TJ[÷‘Í$®ØrŸŠ'—‹›ˆ ``Р‡—ŒÑDˆÂ0@ž<à 7’:Ò¸•Ñ=r®¤Â+.Ûâv-‰åXd¤‘”]Ž7›Œ±5yc¿7¦—ŠùÚ¦ñ“Cl:ú˜¦‰eEá¼úÌÜ”%@”î° ºí‡öñîÙ NGÁËE‚‡M”ÒÄ9Úg9¯Oó]–ÉöHì›™Èö!ˆp“3Ó\*P|€8yŬcãóE÷¯ÚÌÿÁléßMx[(G¢G ¸•41‚üG5ºé}~`Àñ™÷ˆMt ’aÚ²IÆ@¸ñqÚÕHˆ*ÆÛ/ž$¶ÅÌ -_‹O”!WnîÕöây^¼½¯Ôi7¸= [òòŒgï»F”5»X9(fÂzºñ2^|ý\š¤Á¤9ƒ XEø«"þ«¿Í_³²™¯}.·‘í+‘ü¬ªÞ!ƒ”: í´g¡ý¶ÂªgñÄqÇ5M+•Jšs‰e£í&mÙɾT†††’¸ CCCìÚµ‹‰‰ ÞÔaüÁÿÝ-œrèùã–ñ}Ÿjµª!¾eŽ,Ä>yçL;/êõÙ]e&²£'$@… ÿ÷Íÿ·×Åë: z>']q*þ»±föŠ”mÛX–E¥Ré+Ûm7Eb­fˆ…îCöÓÒn. ³¬«w»òËIr8Ý>eZž<VÛð‚­ç¥]9e4Q…J"šL2™¸]Kã³@ˆÊ’TQ¶)aø ²»“{'Žåwo{äMø|ü~ÉÚi¹å³´{íõC?§ m£œHäÓœ>Oö˜ì–O˜š-{&:‰#$ûËfînS¶DP1›&¦ûÉÓþz´Ù²û&“ø“ǬŒ*31_ûÔ$½§ŸÃ]·ælPæÎBûm]\ö= /yî>ÕÜ­‚èÒa`Ì;D»’Ò7‚ D1{¯¾új6oÞÌÎ;Ù¶m[”Ôi||8p¯;mfU´V«éKVQæÉ|ìsÿêý¬Z·‡žu1ÍwL™¿”Éè••K™r[÷Ò"Eþc×À›{]Âî3ß÷çä8øa80ø ¯~õ̽¥R4ä¶X,öå»´¨²G ç÷w'üük·¬íBé9íÂ~6ÑU¦eÁ|ߟŠ2òká,Ô6þ×­œòô}uæËš¦;ŽÓ—mLE™Žž *×_ý”i[·nehhˆ‰‰ 6nÜØ±Û˜Ï«^x:g=¹nÚe¤aÚËÆ©ªáÊr mÂüìóg§üŒ§ö¯å¥G|Óüݦy¥R©ç6©¬ fr/=ýÎÓ{]¼Ee1í`÷*Ÿƒwƒ3/788H½^OÂ|iÈÌîÑ«pY³í·uÄát67ÓÈD eðï?øwnß{{O޵[,fÝ6ÐXO‡=ꡲx,æ»s÷“§pæî½œôÉ•U¿P”^±Øu[E™ +Iä­tÆbÖm…ƒo¼‡¼÷AVí?·iz¿…“V”Ùè+`Þ/ËGîzšC/ÿIÛyµZ Ïóz®vª ¢,wæcŸÇ}åÚ{Ó”é¦iêKSQ‘yUh‚7ly×u)Û{FA@±XT{U•Àškz]Œ%a>¶©‚Š¢, sµÏG}¯<úK`¼§×EW” )Êb¢9þùÚf@À3{_ùæÝüÏžxºçysÞ–¢ôš#z]€ÅâчNå©óÎk;Ï÷}ÊårOà nÉy%áÐsøÏ=6e²ïûÚA«(=fý“&GÝúM ½×I©Tbxx¸çåpCߊҟ¼úÑQ†¿óÙ^CQE™:ȹ·xx³ïXÖ®½›ß:ûì$бïûAYv¬AÅ{ÆcõgÛvøH§m¯SÕpåpåÐý'³öŒ3š¦é SQúƒý»OæGÑ6ô^A@¹\ÖÎ]EYBüñ^AQ”iØtÂßð¼ÓÖëb(Š¢(ó@ûåzËà”K`Íš›¦{žG.·òs+*+‹!¨Lþó&N<¸J­çy8Ž£·ŠÒ#öw‡žXËààždZ”J¥ià )в4xx<ýÓ³9ÿÙï´P«Õ°,Kó)Jè¥WõRàû~Ó§¸¾ï'ÿþAæ¹®Ûö³Ýr®ëâû>®ëâº.µZZ­†ëº”J¥d™çû>¥R‰ pˆ¼ô<Ï£T*%åš­,Rvù—ù­ó*•4Ž»,#eO)ƒïûIÙ^–ì>ä·§—œ9–ì>J¥®ëòío»×·HßrÞîÝ<{晽.†¢(Š2TPé-{€gª‡xðÁÛš¦k¨[e9Òw9TæÅ¡#9öy'Né¡ÑhôÍÈZ5||LL¢‡†‰‰AÿÉw™obâá%ÓfC’4‹K£……GslBÙw»ß­eéí–‘ã‘ï­®”ÙåäXsäðâ¿Ös åw‰Å66&í¯§¬/Ç*Ûrq±iß!hbb`àà$Û•óíââã“'ƒCŽ\²Œ2;GØÈY¿óŒo7W\tô¢ôž€€£vŸÁÃbY¯š2ß¶í¾y*ÊáÄ 'œÐ•÷¤t¾;ŽC±X¤V«aÛ6µZ|>O¥R!ŸÏã8¶m'„išø¾ß4 ¢wy©T¢\.OùtÓ4 ‚€\.G¡P \.322B±XÄu]lÛn ÿ)ûrˆÀâ8år×u1MsʧG©T¢^¯'ƒ©Z÷!Çašfrܾï“Ïç1 Ã0’ed]˲0M˲‚€‘‘êõú´eñÿ\.>?=ÿ¥R‰jµÚë¢)ÊœY†aØëB,„+¯¼’Ùþ N¿`»&¾œL—QjKÕ4 4f˜ïãS£Ö4MÖ"°ˆ$⃬+ˉ¸ba%"†ˆ%Ùu²/räš„?üøO~g…7Ù¶ì/ ÀÃÃÆÆÁID ™–=vYÇÅM„Ù¦”'G.™ïáM)‹ˆ6YÑe¦ó-eµ±aF™ ó4?Ù—”MD¨VAJöñôÃO³c|CCCKr¯-FGGù_Çü ß¹ä:þöšLFÛV*•¤“BQºÍ•W^Éõ×_ßëbôW^y%¿zý¯ò¦ß;Šsþ~»ýTÓ|­\¯×{]Te…2::Êèè(Û¶mëuQú޹>·‚ H:ïkµ†a$ž –eáû>–e%ÂD­V#—ËQ©T(—ËÉ|Ïó’O²H‡þ\ÞßµZ-0”åÃöíÛÒºm £££üÁüúЇôžVz†ÖmÛ£çEé7þË’íïQe6OéËþ>îáã8ïKçññ«>ÞëÃì;Ä>ÏÞù^žùå?çïøKÊå2…BA¥ët£n»"œ4Úýîd]ù!CÖ‰Öugò.m-ƒ,3ÝtA!˜Þ‹UDŠ™Ê<]Gyë6dŸ­ÂH'í Ôœ©_°Õ«×0Œi½k³¢”2?Ž 8xÌn,ëõI.;EYŽ,{AåàóòPñÏX½åf€DMV1EQzÏÓOÉ“?3ŽãຮÆÇT”>Á;ùÛ\ôûÿëœLü_ÏÓJ­¢ô2:V…EYHÇ­„ё߭!w$ÄŒŒâ–P?Ù0A²Žã8S:úÚ…Ü©V«I¬úì6Ú…´É†Ëiý”ýͶŽìOFüOHò;µ†ô©T*É9‘óÐI%R'ûË–QBµ ó#õ£Å<'²h¶2ЧDµZ¥T*qÄGôú6î{\×MÚâe õÛÖÎpH¤(KÇÁO¿coê©” M§(Ëe/¨œtßIüèÞ³±íC€v)J?qú­—ñä©ë®Ú¦¢ô}3Oüõ©ØwF†‡‡Éçó:êJQúÍg¤(ËÉÐÚ±$alä{¹\N„ù̆º‘ð9²¼ü·†Ñ‘O y#eÈþË2Õj5 ­“ 5$#ã ó3Sˆ™:ŸeÙŸü–ÿí˜.x¶Ï†tº2ÎôÜ”ó5S¡¹î¯“s"Ÿår˲f ÙØzNÆÆÆ’ßW^y%ÊôÈ@ħ(ý…‹Ësáó9ï¬c£ß:ØVYæ,{A匇ò¢C$W‰á¨(Jï9ó_ïÄxÑ^\÷(ÇѦ¢ô{ïxg¬~ˆ:P¤óCQ”Þ…BA=S¥ODòJÂfÉÅЊïûIÞHCü´~Îôn -Ô¾§ÝÀ%Ùž4²ìt‚ÃbÕc;Ýòèu.Gõ†è.–eé@EéCžxNÜö¯œö…€Ä“PQ–+}'¨LLL011ÁÆÙ¸qã¬ËŸð“M|kèqÌc0jµžTPÔIM9\˜«}Þó‚§9ÿì#1M³£˜°Š¢ÌŸ¹Úçó&.æÅë¿„âPAEQŸ¹Ú&Da2ULQ”î3û„(¯QµZM¼ fëÒ÷«¢Ì¹Ú§$˜ïµh¦(+ù¼;¿úOsàSoæÄ?}4l«¶ª,gú*çŽ;زe ×]w[¶laÇŽ³®ó°±Žw=ûC¶ïÛ—¸//5*¨(‡ó±Ïuëv08¸Š‘‘mH*J™}®[Ã{çI¸®›ŒªUeq™m>þøãI2]EQºÇ|ìó±Ç£T*166–$·Veñ™}æóyñ®(]f>¶ ðý?`ýÉbÛ6Žã¨˜¢,{úÊCeûöí\{íµ ±k×.¶lÙÂÐÐÐŒŠçýë¾Î«^õ g>jðg[¶Pza–ÓU¥wìØÁÖ­[{P¢Îeyhh¨×E™–~?‡‡ ó±ÏW¼âlÚ´©oC}õû½5:::ç“KÉrx~.ÌÇ>Ÿ{øÅ/æOþäOfŒãÝ –ý¥Ï¥æc›'œpÿôOÿÔë¢/˜•tö»½wÊJº&‹Á|ìsrr2É?²œÑ{ºÿX)×d±˜}®s9Ô;e¥ÜÓ+éš,ó±Í‡~˜;ý‹xåÏöP*•’|^ýB¿¿K–Ã=Øïö¾{÷nyä‘EÝfß*£££¬[·.¹A6mÚĦM›ñ¢ìÝ»—O}êSlàô‡êí1´™¶cÇŽ¾5J€;3]»võº3ÒÏçðÎ;ïä?ø\pA¯‹ÒUæcŸ<ò_ÿú×¹ýöÛùã?þcFGGç²Ë%¡Ÿï-ˆB¾lÚ´‰—¼ä%½.J[úùùñÔSOqï½÷.úK³™}NNN²qãßðWu2ýèGûÎ>ûùÞôù1y䯯Æ8tèP¯‹ÒUæ[·}衇øô§?Ý—×n.ôó=8WúÝÞ;¥“k¢uÛéíó©§žbÿþý:t¨ïÞ›såpº§— ³]©Û>Ôã>¥`¾uÛOúÓœ|òÉœ|òɽ>„y³êÀ²Rž3\­ÛÎ\·}ö8œ-œþаoß<ôÐC}õ,ë÷wÉrx.ô³½ßwß}|ï{ßc```Q·Û7‚Ê®]»¦œüuëÖ1111óugŸ}6÷Þ{/÷Þ{o¯c çœsN_W¸Ÿ~úiÖ®]Û×eìçsxûí·óØc±jÕª^¥«ÌÇ>Ÿ|òIŽ9æN?ýô¾½~ý|o¬]»–ŸÿüçìÙ³§×EiK???üq~ô£ñÜsÏõº(]g>öyÔQG±jÕ*N9唾¼~ý|o úü˜?»wïæž{îáüóÏïuQºÊ|ë¶O?ý4·ÜrK_^»¹ÐÏ÷à\éw{ï”N®‰Öm§·ÏU«V±{÷n¾úÕ¯rî¹çöúÄátO/f»&R·}úé§{]Ô®3ߺí-·ÜÂgœÁgœÑëC˜7Ë¡Ü)+å9ÓÉ5ѺíÌuÛýOpÖþ+Y·î˜æ‹úî¾è÷wÉrx.ô³½ÿøÇ?ଳÎZÔíö ²wïÞ)Ó:Q·¾úÕ¯öºèвâ™}¾ë]ïâ]ïzW¯‹®(+žùØçç?ÿù^[QVöyÉ%—pÉ%—ôºèвâѺ­¢ô'ó­ÛÞzë­½.º¢,:}“”~ݺuS¦Í¦r*в4¨}*Jÿ¢ö©(ý‰Ú¦¢ô/jŸŠÒ¿¨}*J¢¶©()}#¨lÚ´iŠ!îÝ»·oc°)Êá„Ú§¢ô/jŸŠÒŸ¨m*Jÿ¢ö©(ý‹Ú§¢ô'j›Š’Ò7‚ÊÐÐ{÷îMb®íÚµ‹‰‰ Þô¦7õºhŠrØ£ö©(ý‹Ú§¢ô'j›ŠÒ¿¨}*Jÿ¢ö©(ý‰Ú¦¢¤ôM€mÛ¶qõÕW³yófvîÜɶmÛX»vm¯‹¥( jŸŠÒϨ}*J¢¶©(ý‹Ú§¢ô/jŸŠÒŸ¨m*JĪ0 Ã^"ËÄÄlܸQÝÆ¥ÏPûT”þEíSQúµMEé_Ô>¥QûT”þDmSQúPPQEQEQEQEQEQEé7ú&‡Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(J¿¢‚Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(Ê,¨ ¢(Š¢(Š¢(Š¢(Š¢(Š¢(Š2 GþÑýÑõºË•‰‰ víÚ•$cšn>Àºuëæ<1Ùµk«W¯æØcí«òíÛ·ÏóØ·oÏþóçT†¥<Êòc!öÙkÛì¤ ½¶Ï~(Ÿ²|™É>ûéÞš}öÚ6ûí*+‡nÙm¯îÇnØ÷RK·ÞÓúŒX^t³MÚOö¹Pû[ÊcéfWísyÑÍ6i/î…n´]ûéݹвª}N¥Îɾ}ûøùÏÞ·ïŽ~oïÚµ‹{î¹§ïûm—¼o-TæÅ5×\†W\qExÉ%—„ïxÇ;½{÷&óo¼ñÆdþàà`xã76­?ÛüÅäþûïÃÛn»­¯Ê·sçΦsøá¸ã2,åùS– ±Ï^Ûf'eèµ}öCù”åËLöÙO÷Ö|ì³×¶ÙoçPY9tËn{u?vþ—úXºõžÖgÄò¢›mÒ~²Ï…ÚßRK7Û¸jŸË‹n¶I{q/t£íÚOïÎåxMú~9'×\sMxÍ5×̹|KQþ~oøÃ/¹ä’¾ï·íEßš *óàþûïÏ9çœpçÎÉ´K.¹$¬ÕjÉïì…ܹsgxÎ9ç„÷ßÇó¹1²7V?”/{ÎöîÝ^rÉ%áM7ÝÔQ–òü)Ë‹…Úg¯m³“2ôÚ>û¡|Êòd6ûì§{k>öÙkÛì·s¨¬ ºi·½º»aßK},ÝzOë3bùÐí6i?ÙçBío)¥›m\µÏåC·Û¤½¸ºÑví§wçr¼&ýN¯ÏÉ7Þ~àÏ9眶‚J¯¯i¿·E€§]yûž{Ñ·¦9TæÁÄÄCCClÚ´)™vÙe—±wï^FGGY·nCCClÚ´‰M›61::ÚÑüÅdûöílÚ´‰Í›7'Óú¡|£££ìÝ»—«®º €µk×âº.—]vÙ¬eXÊó§,?bŸ½¶ÍÙÊ×ÉüÅ`&ûì‡ò)Ë—™ì³Ÿî­ùØg¯m³“s¤ö©Ì‡nÙm¯îÇnØ÷RK·ÞÓúŒX^t³MÚOö¹Pû[ÊcéfWísyÑÍ6i/î…n´]ûéݹ¯I¿ÓçdóæÍlݺµÉ;-ßR”¿ßÛÆlݺ•µk×$áÈ´o-B•y044Äõ×_ŸüÞ·o7ß|srsíÚµkJÜ»uëÖ111ÑÑüÅb×®]Ü|óÍäóù)Ó{]¾‰‰ 6oÞÌŽ;¸òÊ+¹úê«›nڙʰTçOYž,Ä>{m›³•¯“ù‹ÁLöÙåS–/3Ùg¿Ü[óµÏ^Ûf'çHíS™ݲÛ^Üݲï¥>–n½§õ±¼èf›´Ÿìs¡ö·”ÇÒÍ6®Úçò¢›mÒ¥¾ºÕví§wçB˪ö9•~8'›6mbhh¨m^Œ~¸¦ýÞ6¾ì²Ëضmûöíctt4.D€èûîeßš * äæ›ofË–- ±uëV Uë²d/Òlóƒ}ûöqõÕWsíµ×&jb§û_ŠòMLL$ªåUW]ÅÆ¹òÊ+“w¦2,Eù”•Á\í³×¶ÙIzmŸýP>eeÐjŸýpo-Ä>{m›”AíSY(‹i·K}?vÓ¾—úXºõžÖgÄòe±Û¤ýdŸ µ¿¥<–n¶qÕ>—/‹Ý&]Ê{¡›m×~zw.´¬jŸSé÷sÒo×´ÛÆÂÄÄ×]w7ß|s"¦ÌV†~o»/FUP™'ûöíãÊ+¯dûöí|ìcãcûX2¯ú™U¸f›¿Ôj56mÚ”¸ŠíÝ»—]»v±k×®¾(D7êµ×^ËÐÐÛ¶mcëÖ­ìØ±cÖ2,Uù”åË|í³×¶ÙIzmŸýR>eù2}öýµûìµmöË9TV&ݰۥ¾»iß½°­n¼§õ±üèV›´Ÿìs¡ö·ÔÇÒ­6®Úçò£[mÒ¥¼ºÙví§wçB˪ö9•~?'ýrMû¹m,lÚ´‰ë¯¿ž/|á Ü|óÍ}ÓoÛë¾5TæÉW\ÁÆq]·I¡ƒèfk½{÷îM”®Ùæ/ûöíãºë®ãºë®cbb‚›nº‰›nº©/Ê7444EAÌþž© Kuþ”åË|í³×¶9[ù:™¿ÌdŸýP>ey3}ö˽5_ûìµmöÓ9TVݰÛ^Üݲï¥>–n½§õ±üèV›´Ÿìs¡ö·”ÇÒÍ6®Úçò£[mÒ¥¾ºÕví§wçB˪ö9•~?'ýrMû¹m¼cÇ®»îºä÷Úµk›öÛöÝÓ¾µŽR×+MÜxãá%—\ÞvÛmMÿ÷ß²Ìàà`xÛm·…a†;wî ý{÷v<±¹âŠ+’ýõCùöî݆;wîL~_rÉ%á7ÞØQ–úü)ˇ…Úg¯m³“2ôÚ>{]>eù2›}öÛ½5Wûìµmöã9T–?Ý´Û^Þ‹mßKy,Ý|Oë3bùÐí6i?ÙçBío©Ž¥Ûm\µÏåC·Û¤½º»íÚOïÎåzMú™~9'W\qExÍ5×̹|Ý.¿·¥|²Í~ï·]ê¾5TæÁ5×\žsÎ9Sþ³zã7†ƒƒƒáW\6ÝpÌ_lZo¬~(ß7ÞžsÎ9áW\^rÉ%á‡?üáŽË°ÔçOY>,Ô>{m›”¡×öÙåS–'³Ùg¿Ý[sµÏ^Ûf?žCeùÓM»íåý¸Øö½ÔÇÒ­÷´>#–Ýn“ö“}.Ôþ–òXºÙÆUû\>t»MÚ«{a±Û®ýôî\®×¤Ÿé—s2 ÒëkºÚÆb+²~î·]ê¾µUa†‹êo£$LLL011ÁÆÛº Í6ÿp(ŸìcݺulÚ´iNeèõùS–7ý~oõ»}öCù”•Ér¸·zýüXÈ»³_Ρ²²XÈ=×o÷ãBʺÔÇÒ­÷t¿]ea¬”{a¡ö·”ÇÒÍ6n?]eᬔ{a9=gÔ>—–~?'ý~Mû¡|»víJBaõ»}/å9TAEQEQEQEQEQEQe4)½¢(Š¢(Š¢(Š¢(Š¢(Š¢(Ê,¨ ¢(Š¢(Š¢(Š¢(Š¢(Š¢(Š2 *¨(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢Ì‚ *Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(³ ‚Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(Ê,¨ ¢(Š¢(Š¢(Š¢(Š¢(Š¢(Š2 *¨(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢Ì‚ *Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(³ ‚Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(Ê,¨ ¢(Š¢(Š¢(Š¢(Š¢(Š¢(Š2 *¨(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢Ì‚ *Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(³ ‚Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(Ê,¨ ¢(Š¢(Š¢(Š¢(Š¢(Š¢(Š2 *¨(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢Ì‚ *Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(³ ‚Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(Ê,¨ ¢(Š¢(Š¢(Š¢(Š¢(Š¢(Š2 *¨(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢Ì‚ *Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(³ ‚Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(Ê,¨ ¢(Š¢(Š¢(Š¢(Š¢(Š¢(Š2 *¨(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢Ì‚ *Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(³ ‚Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(Ê,¨ ¢(Š¢(Š¢(Š¢(Š¢(Š¢(Š2 *¨(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢Ì‚ *Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(³ ‚Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(Ê,¨ ¢(Š¢(Š¢(Š¢(Š¢(Š¢(Š2 *¨(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢Ì‚ *Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(³ ‚Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(Ê,¨ ¢(Š¢(Š¢(Š¢(Š¢(Š¢(Š2 *¨(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢ÌŠTjµ®ëöºJ‚ Àu]<Ï[”íù¾O­Vëõa)s@ísåáû~[»Vû\^¨m>ÌÅ6=Ï#‚^Y™µÝ•ÇBß«j·ýƒÚgÿÒ«v©Úgÿ öÙ¿Ì×>Û½?µMºŽãôúД9 ö¹²(•J ¶µkµÏåÅJ´M8¼ís::µMß÷õü-ÔvW }¯ªÝö+Ñ>WÂýÕ«v©Úg¡öÙŸÌ×>§{j›ty°íV†M.6ËÝ&êu”¹áºî²É222B±X¤X,ƒƒƒ8ŽC.—ëuÑeA¬ûœ¾ïS©TÇ4M‚ `Æ äóy,Ëêuñ8|ís1XŒ&E™/‡£í.Æ{UíVé6+Á6{Õ.UûTºÍájŸ3½?¥—¬›TšYQ*Žã000ÀªU«( SnVQ¸7lØ@©T¢T*% ¡çyŒŒŒ°jÕªäA- S«Õذa6l V«Q*•ذaMêé\– ÙNky¦rÏ„çy ²jÕ*FFFšÖ™nÞLëtRÞÙŽ["ÅbÃ0oz)¶;vÏó’s ÛœÉ5,{}粞Ò=f²Ï™lSæ·³Ï^Øfv[ݰÏùØm§åíØg³—vÇ $×Ò0ŒäS*°íPûì/òî”ùýbŸÓÝ£‡³}ÎÅβϲì4˲TíCVz½æf»ýXïíÄþÚû|ß«Ùßj·½Eë½Íô£}.u»4û[í³·¬û\ÉõÞÙìs1Ú¥YÛÔviïÐúl3ýø¾œo}vÅ÷ã†+„ñññËår†aX,C ,‹a†áäädhFX¯×ÃÉÉÉ0ŸÏ‡@Øh4’y²n£Ñ ÃÇÇÇÃ0 ›¶S.—§ìǶí¤sYv&€0ŸÏ‡“““áØØXhFØh4’2wr>äxeߦiÎ8o¦u:)o'Ç]­VCÛ¶“Ï\.7åxÚ{¥Riš.×HÖm4É>òù|hYV²ÜLë)KÃLö9“m†a8£}öÂ6e[ݰÏùØm§åíäØg³—éŽ; #»ËåraµZ s¹\ÓùTûì_òîÌÎïûœé=\ís¦õ¦³Mall,4M3œœœ mÛVÛì#—z¯Ì›íÞë×zo'ï¹éŽ}>ïÕ0T»í´Þ;õ|ô£}.u»4 Õ>û•dŸ+¹Þ;›}Χ]:“mj»´7h}vêùèÇ÷å|ë³+½wÅ*Åb1ÌçóMÓLÓlº9²F099™ÜÐÕj5´,«iÝ|>Ÿ¬›ÕäÂf·b§ËÎÐÔ©!®N_Œår9ÌårSÎÑLófZ§“òvrÜò€”¢ü–‡ÞtÇ^©TBÃ0¦½æ²|>†Ñôbœi=ei˜É>g²Í0 g´Ï^ئl«ö9»í´¼ûlö2ÝqËrrMMÓlºÞjŸýËBÞaØö9Ó=z¸ÚçLëMg›r­MÓ ÇÆÆ¦œK¥÷.õ^™7۽ׯõÞNÞsÓû|Þ«j·ýÖ{›éWû\êv©Úg°’ìs%×{g³Ïù´Kgª÷j»´7h}¶™~}_η>»ÒûqWLÈ/Ïó·>Á4Íä{MnµÙe}ßÇóçc·‹ÍlöÒî¸kµŽã066F¹\f||Ïó¨T*É2jŸýÉBÞПö¹Û”c^Iö9ÛzÓÙf¥RÁ²,‚ HÂ.xž§Éû­÷6ÓÏõÞNÞs­Çþ•¯|e^ïUµÛþ@ë½Íô³}.e»Tí³?Xiö¹’ë½³Ùç|Ú¥ÓÕ{AÛ¥½@ë³Íôóûr>õÙNÖ[ÎýD+FPé$ét'ß0 lÛ&ŒpZ¯_k¹,Ë¢Z­R,›b/ζžÒ}f³Ï™Œ‡“}ÎÕ»‘ØìÿÏÞ™ÇÉQ—ùÿMîs&5cb B‚ 5DvP¨ÑTÜ`õ°ž°J·îOŒ®ÑîÕ•U<¶[³jv¥;¬ñ^2­¨Èœ’SFŽ)TÈÈ9ì’ L%“ûþýñíou÷œ=É=ÉóžW2=]׷ާê[Ïçû<ÏáØ‹ïû˜¦Yd˶m-+öYžɳÄ>Gƒ}ö·\o¶©çK¥R¤R)|ß'›Íå&Fé÷öO9ô{áðìvãÆ‡ý\»y¤ßÛ?å`Ÿ#ñ^*ö9òˆ}öO9ô{×>û{/í«ß+ï¥Ãôgû§ž—04ï¡0ºýDG bš&™L&<Èžç)]Žã]T]§Ž ‚€šššQݹ±m»èx¸®K$ o:=M{÷»ßÝë2ƒ…eY¡’ êXg³ÙnŠjOø¾ž7½œmÛátÝÎx<Žišá(„þ–†ž¾ì³/ÛÔÓûìËû²éÁäpìEÛuáËb6›-j›Øgyr$ÏN=]ì³¼í³¿åz³Íd2ISSSøÏ²,’ÉäQ÷’2Z‘~o1åÚï…óÛÓN;í°ž«b·åô{‹)Wûî÷R±Ïò@쳘rí÷®}ö÷^Ú[¿ä½t$þl1åú¼„¡y…Ñí'7Ò ,¢Ñ(žçQSSÞDÇ §[–…ã8ÔÖÖbšf‘ºeš&ñxœúúúpYÛ¶‹–/LÓ$‘HN§ûTsuûõñð‹)×~ïáÚg_ï¥}õ{õ1“÷ÒáEú³Å”ëóR·0ßC{b´ù‰ŽË9jðK±M8¶ìópìv08R{.»Ÿ#yv‚Øg)ÓŽy =q´÷{ ÛYŠí–[¿w¸Ÿ«By!ýÞžG¹Øg×ýçê±…ØgÏÇ£\ú½]÷CÞKn¤?Ûóñ(—çåp¿‡Ž{<ê•Þð}ŸÚÚZ±,‹T*…çy455 {;ú*”dÛvÉaSƒ±žáló‘PhPñœ0|”‹mê¶éµ>šms¸íEì³üûÙö"ÏAa ”‹íëý^±?¡+åb›º-£é¹:Ûë ±ë£±Ï‘mïH"v]ž”‹MJvxßCG‹=5)¿úÃ4MÒét˜Í4M‡½:÷]_íÎõ”Û¶újÃá(’åªd yÊÅ6ap®õÑl›Ãm/bŸåØçȶ·ëúä9(”J¹Øî±ÞïûºR.¶ £ï¹:Ûë­ b×G'bŸ#ÛÞ‘Dìº<)›”þì𾇎{ú(À¨~éìË6õôÚgss3¿ûÝïäÚ:}ôQæÌ™Ãœ9sFº)=2Zî£ý¥s(ìó¦›nââ‹/é]ë•ÑrmÉýãðÙ°a@YŸãR8û¶¥Rî×à@(w{/•Rωôm{¶OÏóøÙÏ~6êï[pì]Ó£RωômGgß¶TFC¸TŽ–ûL©çDú¶½÷m“É$ùÈGFz×z¥ÜŸ%£á¾Pîöþ›ßü†Ë/¿œ+V Ú:‡UPioogÑ¢E¬]»–uëÖQQQACCC¨lvU4+++iooïsÇO8áæÌ™SÖ}ÛR9–®éÑBçD÷myä‘‘nês,ömKe4ôKåh¹Ï”rN¤oÛwßvüøñÔÕÕ±hÑ"***Fz»QîÏ’Ñp_(g{ommåž{îaÆŒƒºÞaTš››©¨¨àšk®¡¹¹™«¯¾×uÙºuk·ùKyîØ±ƒæææ²½ð׬Y3ÒMè“r¾ihÊùê—ÎÑN_¶Y]]}Øö¹aÃÖ¯__¶/å|meû@Ò”óýcëÖ­477³{÷î‘nÊ3ö¹{÷îðÙYŽ/å|miäþqøèB–åøBu8ûr¬õmK¥œ¯ÁRîö^*¥œéÛöM¹÷mKåXº¦G ýݷݱcÇH7õˆ9û¶¥2úÀ¥r´ÜgJ9'Ò·í›Y³fÑÜÜLuuuY£r–Œ†ûB9Ûûúõë™6mgžyæ ®wXPƶjÕ*@]¬]»–ÊÊÊnó¶··÷ÛY5kVÙ_üÂÑËŠ+X¹råH7cPèÍ6W¬XqØö¹xñâ>C?a¨¨®®fÅŠ´¶¶ŽtSmÓ>g̘!ÏNaÄÐ/ÍÍÍ#Ý”AAú¶ÂÑ„ôm¥o+”'Ò·•¾­P¾HßVú¶BùÒÐÐÐoÕá0f8w¢®®®›©ÿ^¸pa·ܺuë¨] £…¾lÄ>a$û„òEú¶‚PžÈ³SʱOA(_¤o+¥1¬‚Ê¢E‹ÂP8Py@×­[Guu5uuua+¨gííí,]ºt¤‘ õôe›€Ø§ Œ bŸ‚P¾HßVÊyv Bù"ö)å‹ôm¡4†5åWEE+V¬`Ù²eÔÕÕÑÞÞN]]]6½bÅ –/_΢E‹X¿~=+V¬(Ëüz‚p´ÑŸm‚ا ŒbŸ‚P¾HßVÊyv Bù"ö)å‹ôm¡4†½†JCCCh”•••E¹ö §UWWKؘ #}Ùf×ébŸ‚0¼ˆ} Bù"}[A(OäÙ)勨§ ”/Ò·„þvAèÓèÄ aäèÏþÄ>aäû„òEú¶‚PžÈ³SʱOA(_¤o+}3¬5TAAAAAAF#"¨‚ ‚ ‚ ‚ ‚ #NŒØH7AúDAAAAAaÄññGº ˆƒú—*‚ ‚ ‚ ‚ ‚ ˆââ–4_û†¿M+›×Ï+}½‘ˆZf´#‚Š ‚ ‚ ‚ ‚ ‚0*Hå~Že2™îßÕÔô½L6Ûÿz]‰ž§~Ja¨Ï½ %A „PâK©LOí(EèDPAAAAA„2'•Rÿ‰bÁ÷Á¶•€áûyñ¢¦FÍïºya£/|_­£'\7?ÍóÀ²” âº= ²Ã÷¡© ¸È ‰‹Á>?ƒÄûÀK·÷ü¸ZgMn¢Ñ|/ÓTÿtôˆë*!'Ï‹%ét^²m5¿mççÕÑ5žöÉ@Jm#“É‹0ZÄ1Í|3Ý¢Wí©C[oEAF>8ⵂ ‚ ‚ ‚ åF„Hé¾ü‚ŸÃe8c^ Óbi‚ ƒQjj`~šÅó7{°…|äE¨y3%:øB´¢› R­b¸@N¼0ÿ¨ÄM4 æg½*úÃuÕ2ÍS€lN x Ÿ€©ó õÈ&Õ²™Œ-ž5`å·U›LSMÓuT’I%˜´´(¡&™ÌGÌØvNIä—ÑBeÁb¾bªe2øv‚)êÄÅãÐÑ¡æƒ|„Kcc~Û¦©¶ 9±f2d®/­fÌá0nØ®&A„#ÀR¨›½3ÒAAAA€ ×t_I þÖt›†q_,  —}‹‹š 1È %ÀŸ=À‚Ƈ WÀYx Eé!mx%$訧Œ:%$?³S­(úQð_càBæ]uÕ²¼>e4* ÆOÀþ*ø ùQð‚Ÿ×Àe?çz0mÇÁCïûy%Â@®À}3tØÐñ¼/tĈaäÅŒ¢sf¨}µró86džƒþ½Šh)LO¶¬Ií»N– àßÕ‰ïF: ·`“mjjT{"à D·‚ÿd€Å‹ÿüJ„Š eMuöQBJöÈV'‚ ‚ ‚ ‚ ”!]…“¿÷Óz¯B¿QåOòrßG¤ŠeÁWSpv.êä'.Ü•€õi8ø1¥ò•*Ò0ý«pÎE°3 Ñu¨‚Wß'FÁÍE}8$çC|1°÷„ä*:cë…š±o¨ï-®ûàV©÷Óü0Áî"T$ˉ°o1üÛ àß™gÀÛû–À¢÷Cªê-%¨|l&`½¢ªo‚EYØ2¹ƒœP_gõ< ÙÅP÷!Œâc望xHCË,”#°¶øÄ™&\ŸkLS *mmê8ut@Ë E‰)ñóa×®Iƒ~އ=B¥½½ööö¢ï-ZDEEEÑôêêjª««‡»y‚pÌÒŸmÎ3ö™!C”h·ïS(E_ * ŠU~A8iû¡w¤o+å‰<;¡|û„ò¥Üú¶1b8¹<%OÇ>ËÚèÆ02¢'Q¥ë7T$C€rð›äRcõƒ,7_$(ø>N±_êÝïþ·ßþ^ àíZà—Ôn…¿<“áî×ÒéŽaâsßçËïù s|€}OÜÿnøhÌzV×A`‚ås;$>ÑÿóA /¾ø"ó˜Ç¾ÿÚGô¬ñÔ®„µ¡òÀA>wÊþ÷À~c2þ ©ÀÊBÔï\0ƨqß §Nƒÿ›½üjp7·^€LÒ/AöË̃ŘsÁúCî æÒ‹Õÿ7$õqM:ñüφ'QÍï³Àµ;¡ã1^õÈ:¹€PX±ïÀù,*ä(ÈûçÁ‰@ð¸š/w)„‘.æIê¥os/|óÞÅ\rÉþA½.‡]PY¹r%ëÖ­+únÍš5ÔÕÕ±víZV®\É¢E‹X¿~=+V¬ ¡¡a¸›(Ç$}Ù&0¤ö%Û£ Rø04P*s Іˆ*±ÃHÚ§ }#}[A(OäÙ)勨§ ”/åÖ·õð°snó­û·òúÞ×ñ€W²ª r¹ „åS2 ¾‹÷²úú\ö·øð›nNwð‘+òes&©ÜúµH£ùžçñ»;>ÎO|¸Ù‡G†‰çÁê"ðŠ÷= oþüÝŸáÑy¨X¸ƒÅ§¼ÀåË73eÏØcpÿ . Ñ,<~6ØAöõÏ;ì›À°Ò“gpë{];ýÏî'Oü0–Blå·¹)ö.~žO¶‡oÕ¯ÂøŒྠìÇ·€Û¼ÿ0 ~ÿ¶½¼²eñAê£þ dß‘·AôS¿ —†fÁAóÁ[þ\ˆt@r"xÿÑoÁ”n"?ž‚š_BòÀŠAP©³Ôâ%nçô-$uŽCã,H¼±ã€9`ཉÙL«ŸÚÙ“o€±¼u`ßB>¿›—‹H:ÉC)¢sâøÏ•ƒ]» ÒÙÙYô ,dåÊ•¬ZµŠºº:Z[[Y¶luuu2A†¾l†Ö>=¼ ¹(ÑÄE=ÔÃO,Z*±ÂHÚ§ }#}[A(OäÙ)勨§ ”/åÚ·õñÙ}ÂF‚ lðNS C)àbÀ'¶â¾¹åSÊ’¨Ø´iÌžÝmýnAÚ*höáQ&Œ˺¦|ùJõ½®ï令ÏÙl–9|“ÿùýJÏà„óa“ çGá‘ œlÀk'tðÚ÷ò/L$zþ 65¥á¸o‘%‹ã8¼áögyG•‰iŽƒ8$Ï«âÔÿ‚iðó¥Ïpù⃜õ—ÿï7ùñ_á~sþ œs¡ö>ðcðÀ{wðô‰0Œ7€±bŸ{/Ç©cf?Ÿþ¯ YrÏ8˜ÖÅ`ݩܩ‰_ É?BM‹Úvü?Á‹@ãPßÑ× ˜ºÞÛFì «¢‚ÿ=H-‡è?eðÍzŒïË¥þ@ÏÏ›ÃeØk¨477÷hhÍÍÍTVV†»páB.\HsssŸëÛ¾}{¿óÂPÑÜÜ̆ Fºƒ¶/½=×>7lØ@kkkIÛ/ ÕÔ¨®¢‰Uð;Šú„žèì줹¹™Ý»wtS…Á¶ÏÝ»wÓÜÜÜ-”[†ƒöövþú׿²wïÞ‘nÊ  }[áhBú¶ƒ×·„ÁD÷m·oß>ÒM¤o+MHß¶´¾mgggIÛ×¾!· 0G@€žÅþó6ò¢ [SÝ#cnËÀk. ðQ¾%K­€§êaâÎ<óÌ3¹uæKüÚ…Ù¹:!™ Ô÷0˃½W²eÜDŽ#_`}ñ}<öÂëxz¬¿ÿÍœ÷ÆÝÜÁiÆ~>¶ñiÆt@܆Ïÿk; vÄxõ¸‡™›5>Ìïìäç§Ã–Gqܱõ…‰øvï»;ÛVü…ß¶W²äïòÔF¸ÎåüêìÉŒ{T?þ,›×À×>ô(ï³aË3_çú\Å/º”©gMåšK®áß&ýdaâ‡&rÃ7ðü¼ç‰ž¨z#&¤R)0aöƒ³yð{ßcÊSO1õ,•+Ë0 ì›áå“ÏàɳxfÎ>Œ*õ؆Ûn#îyŒ3†À xòÜ»øøÃë0<ýgŸÍþ7¼|u<›^†Æ¿Øµ…'¯½–ßgÖ@˜›\øn€ëº¼ûÝïæ¬§ŸËbúägÙñä“‹ås¡%•Èóç{ïÅܸ‘tH¥¸ò]ïâ _x?±DŒL&×N;8à&9ÇÎ~à¼e6ãêO ±±‘‹Ävüæ7¼póÍ´êS|èwŸR|ðñûYþÐCt®\‰q–¯Vðç ø>é–ìµk™ÅAj¼‡ùÈ/žà›ÿòYœ§ŸV×ÐâÅŒÿÜç8yÝ_yêSŸt[VAeáÂ…EyøêêêXºti6Ö] ÃC_¶ ›}º¸á(‚÷àqYLT4J×ôNË+%ÚÉ}΢žOÙ‘9¬‚0(”‹} ‚ÐéÛ By"ÏNA(_Ä>¡|)˾­gåSÄÿû¿r°æ)È:lÂczSœ-õ~…Ï*'›pñï~ã¶qnG©TŠ À…ƒ+™xè’0‹Å.öx°;€ wMã´¿ÛÉø¯ïgÌ#ûÙýÐC4?¹‡ÇbÞ¦ñàÀd³àýÅàûc@ ¾¯ç2½]1#`qÐIýñÇa}*`êÓSIf“JŠ£œSQ ‰ ëðɧdA [ŽÛì\¿“7âyŸÞùi&OžÌ‹ú“:æßùçÜr ó.;@õ׿΄¯]K•ñ8µ[¶0þ|ššš¸âŠ+xúÎ;¹©ê&|Óä‘gŸåŸ¿û]þþ¿ÿ›Ï}¶] Xäáû>“þðþiÛ6~´`ŸŸÿM^;p@E²ØùFNÚµ‹×®¸‚‡þå_pS)výö·üîýïçáÏ}Ã00M“MO=Å£ßü&'Mš„ïûàºX?Ì®^àÆÍ›Éd2d26]~9ïº÷^.ܼ™åÿó?üáÇ?fÿÎe´¿¾ë~ó&t/ÞsO^ÜñüásÙe—1gÓ&^غ•+/æÐ¡C¼÷'ëøÄ/É¿ú!æé&¾ólÛÆÌdxÛž=|ý‘GxzîT|ÓdòÉ'sÅO°|÷nn¬®æ»×^ žÇ]_ÿ:×Ýv×77óÖI“øãÞ½\ÓØHÕ–-üß}÷‘Éd‚€[¾ùM>¼j§¾ó\ðàƒøAÀ´»îâÅóÎ#>ñÎwrÒ»ßÍ‚;ÙüôÓ|öä½×_Ïü™3q]—¯Þ~;æÃsò¶m¼gùr¾»`ÜòÜsÜú®waš*dg_âíT?p'–e1væL~7ožSL“§¦L!‹aÛ67]|1c,YÂÇ¿ÿ}žÚ´‰× ‹áº.¾ï“YcOGÀî“OÔësX•ææf–/_æäëììdݺuTWWSWWæ•›¯½½¥K—gᘤ/ÛÝ>$¨¥–D.㥅…‹Ë3¹4_>>A®JŠIψþÎC¥™Ô‚Šû®7!FFÃmŸ‚ ”Žôm¡<‘g§ ”/bŸ‚P¾”KßÖÂ"C&™âÚ,x¾Žã.{ <•l6mÀ>ž‹|ãíljç–_øòWø¿šq‡—ÿzl©âÌÊI,¬žÌökæ1ïU|þÿ9°ÿ¡‡¨¢Š÷?3‹7ün?WŸt:Áx›ö'2sÓbà„×ö26|àõùüÇžçÂÓ÷rQô3÷óž÷L潟™ƒ™4•Ë€S.?…ñϬ5ùT¦iFذ`[j¶ày‰D‚ÓN;-¬Óöò0æÌPPI$xžÇ|ùËŒ¿ÿ~>~Ål=u+?ýõ$>ð c^|G­»¾^à `ß¾}œóÜs,[¶Œ7ž{.U?NËŒ¾Ï—¿óžúÉO˜0k­'Dmm-3fÌào|#»ví⢳Ϧ}üxßçšK.áî½—›˜wË-455‹ÅxóóÏó½;I$àº\öÝïòÑ={X3k'OfçìÙ\ú©O‘L&¹àÝïæƒÉ$þàX–…çyìþÉOˆÅb˜¦ÉEÿû¿áqšùÅ/‚aèƒÆ»æÏ穟ü„H"Áúk¯Å0 ,Ë¢îÚk‰ÇãD"âñ8Ñh” ˆF£*ÝÿL#Í[Þ;è×è¸A_c444ÐÚÚʲe˨®®fýúõ444„yhW¬XÁòåËY´hëׯgÅŠE#Aú³M\ûL‘ÂÆÆÂ"KC: /Ökrb~¯øäÓ|aš0ýYj¨£™á¶OAJGú¶‚PžÈ³SʱOA(_Fªo«Ò¿{n<<&ZëÙcypç;;v,ûqæ5“Õ¤œE^='GïÀà3Ôl«!µö¤Óî+Læ=|zö$²ŒŸ´ÓçŒçîFøïÜOzòdnîP«»xb%ÿ9}ŸíàßyŠIs¸ïÐ6–¾{;ï¿ê$2 ðäûȹœËýÿv6±ïÁ‰í𡪔]ñxû,**hüÁH$ø¾Ï'ÇŽ%ð<~9u*ç§Óø[¶ð/--*}*ÒæŒ ˜XW‡aü¿¥K©ÈÕI!…ÚZ6|æ3|õ¡‡øUÁþoœ<™U?þ1¯WmÞÌôª*Òé4µµµ´´´`F·cF<Ρ'žà‚üÇP\jkkÃu]jkkéèèÀq\×%’J¥°, ˲H$¼gÕ{8uÌ©ƒn+Ã*¨\ýõ´¶¶†aa…¡a ÔÕÕÑÞÞÞmš CK_¶ ƒoŸ..&&66÷âq< ES§ŸuéT”…4’¯¡"£á¶OAJGú¶‚PžÈ³SʱOA(_Fªo`c‡)á=n1WÏÚO|³rèWý¢ŠåãŸâÄomãñ'ŸÀºÞÄŒC2€ï½×ÖÖÒÖÖÖç>F£Q¢Ñ(®ëÒÖÖÆžnÀtq]—k®¹€ŸîÙÃ×÷ïçÝñ8ŽaÀŽaýù×ÕÂË6¬LªZ(ɤڈe©ôX¶M`Û<óÌ3ù875Ñ`Y|èŒ3¨ÅxáïäÕ3Î`M"išd2>¹x1cƒ€ñÿ÷¼kåJ¼sÏeÆ L™2%·Û¶Á0Hêu¿ýíùíÇã,ˆFYº`A¸i۶ៀƒ™gY\ßÑÁ/½Ó4ijj Ó}uÃ4y»i’Þ·/¿žÜ簾& ÃPiÎLÃ0hjjÂóà³oóY|·î»|âŸàÑ_cÂ]kؾý|’5àO«¬ÿ„X½Á%§ÂlæÔçÏdÒ®I¼å¬q°™0‡ü\Ÿ„—Ü—x‚SÝSÁƒûß~?‹XÀ›©étºÇ}p]ÏóÂè Ã0ð<ÆÆFŽ¿ýv^ص ‡ þðþñoãþáL“s_}UåK¥”H‘N«ÏšÀ¹¹$÷¹¢ïayÇ Û”H$òËØ6ÿðH&™Šò£}cÚ46:„“K¦£lNþǤ¦¦†ÊϞ〧žzªHôè1šD“Lx=äŠ)ˆà¹ö‡? ÛkY}å¤Ñ»äàû¾*pîŽ]ô[·«ðo ¨|½rP¯Kæ*‚ ZPq ’zyxü “+‰†ßû%È ªð|·^£ß5 ‚ ‚ ‚ ‚ ÃNïÕ•§¼)úÕ%ìüå[©:õ&×=Ä„‹ŸåÕÝ»™¾ys8ï† øÒ’/ññyçä»Nf/—ó__›F°’‹s3ÕCõYtàϼõÜ…Lz÷$pÀÄ4jDn¼¸Ëî^¦œOqØ>~{7Àu]êëëCg"‘Ócéz®ë’L&¹ù¥—H§ÓX–ż+®à —\AÀä… ùòŽ,ܽ›¯}ík*âÄuU±ÛV¢J¡P`FᤜÀašJT%¦äê´˜¦Iccc~ÛfãäÉEmÿ¿Nà / k»˜¦‰išÜwß}ê»dÃ0H¥RÄb1²ÙlIçÔ²¬p=Q$z”ˆiš_΀ӟ8}ÀÛêTA<¼0åW@À.Ì\Ay³Ht9 Ô³/dFzÇAAAA@ù‡ ý?³±ØìëYh9©óNà„“/æ¢9Ï1iÇß1vìXŒÜÚýû÷3{âlð”hÁ¸¸ƒßr™€ §·á­±s˜¸~"9'MoÊmØE‰*6Дoß®I»T.úœæ££3´hbYmmm˜¦YA¡k¦Ø¶ëºXAÀÞÍ›™uíµ¹µT/×U¿×++Õú'/ŽèÈB"… LÝ Í¢×9@Ñ¡°öKOh)Nãy‡W¥Øó<"‘Èa^!G†ŽBLDPaÄ01Ù˜ûÜF’88aÑúþð(-B¥6÷¹4-]AAAA.´8b`pLœðî?pêjåžÊtn󮯱c™¼kWè7ªªªRÑ%¦ªUoÝ6Ò ÀúFnåq ªôã·ä#Q´Fa¢D£àïfoPާÝ!jk•§)•JQ__ëºD"LÓÄu] Ã`ñŸÿ žGcN8™9>g]x¡ª{¢Å—Lnèo[ßýЇ°tˆa¨T_=a´1/J§Õ…¢ëö?Ù²,Òé4¶m‡‚J*•¢ªªŠúúú¢y#‘H¢K%mk(AE„Q‹[$”¤sO€õ0—«Ï!Qò‚Jüq¶ŽÙª–/üp]7L?Fyèmo£¶¦†d2ɇüc¦ý×qüÍ7ó¦gžHDExžJå«Ï–¥þÖQ%¦©¢Uü¡­ìpý†aà8†aàû>‰Dß÷è×uq]7ŒÈé)-˜ïûApØ.G–ª-ƒ¾NTAvlì°àüäÜo};/¥½ÆAEcöÇ’]ô­;ÄFú@‚ ‚ ‚ ‚ Ds!#û2ï‡TÜ*&O½€ìïx#[*V°oß>@E T«R$:Ï{ÆðÆ¢FÙj ôhÞÂöÊÚµk¹ám7t+Î{þ‰'òùßýŽD"Ág/¿œí÷ßÏÝ_LçÊ•ŒÙº•¥÷ßÏ[ÞòÌ (NÃeYùš':•W2Ù}ú01К$Éd’ Hæj«˜¦‰çyd³Y2™ Žãô‰âû~˜úl¸yàÒ·mÜ‘¯¨TAÌ.BÊÀËQ)!%zËè4aú•EÕW¡ºæ·-¤·b‚‚ ‚ ‚ ‚P 66‹¢ok+öîeK.߈~ÓœðòËá¼›6mâ¼_Ç”W¦;v °Þ ÖlºÂÀ+ëe—]ÆîÝ»»}ÿËo›7üío,›;—¤mS=m /¾È…^Èq55l˜8‘ûcÎ;U=”ÂèŒtºgáÄq”À2Dèz(‡‹ã8¤Óé°ŽŒeYxž‡ëº466DZm›X¬ûæÂ”a½‘ÍfAÓg?r6SŸž:¨ëAE„aÅÇ/Jåem´‘>üU–D$©lˆåë‘™¨´_:ý—¾­º­=ÜÃu/A8VÉæ~z¢žzbû%‚ ‚ ‚ Ž‚ÄÇ™4»#üÎ@E:LËE¦{ vþÏN¬k,Æí§fÐ#o“ïÌ *…D)-ÍIŽ[n¹…—^z €L&þ}ûÈd2œtÒILøà™üŸÿÉäÛogÛi§ñÔ”)†Á„3ÎàòE‹8aÛ¶â•uä÷e …ãË˲Èf³D£QlÛÆ²,’Éd7áÄ÷ýP|é ÏóÈèš2ƒÄ¦9›8Pq`P×)‚Š ÃJ@@”(M4êy×Wš/w•N|_¥›L$Ôïšõ9SBH*§Ä;·m% ˆÁƒÄ}˜“‚of Km-|jk!›Uë×ëí¶Aþû òô—‚0¬x¹‹K@Š¥¢< ‚ ‚ ‚ ‡Çž¿í`úyG¸…rÌÏž­T’±;ÇrþÎçÅ1/æÔõP¬‚…ž/+¯¼’³Ï>ß÷ñ<_|Ã0øÓñÇC:ÍY{÷2ïõ×Á²øÑµ×2ìX0M Ã`Î{ßÛ{Qù£ö+í;L¡àÒ—¨âûþ G¨Þô¦ÍüÃ?t‰·;Ôü¾ß»Sø¬ùéOŸéÓWÔv‰Ø9vÐ"ŠOqç&C [Ò~ ‚ ‚ ‚ ‡Íø}ûÀÚÀô7MËë/Èÿ×ù¼iÿ›øÁù?€ýä>+‰rxùå ¸ðÆyø®»Èd2ضÍK/½Ö ¥šš˜ùÅ/æ¶…h”¦&5ˆx8롌mmma 0M׿5Ñh4,jßS$ÊH®("¨‚0bxÐo ú)žÚé/âÏ4óÿôsÍq WBŠiªˆÊŸ¤!U¯˜³Lxă*~ÕÉÀ‚XÝçÄá„¿Î_øÇœ8âºðÿþßv~ÿû­$“ñ¸´Ø“ͪúa<°ƒçž{ €GùAá™g¦²ò&ÞüæÄãd2~ö³ÍÜyçÓ¤R„û‰¨è˜o~ó–P„I$D">üá‰|âß"ы”Íf¹í¶õœp—p]7|A0è*¿ç)qI86ˆÁÇÇÄ ÅN®«bæ~bÄDTAAAŒë®æ)°Óà­wMÉ™t(AeÖ¬Yœpà ×€¹¨¢ô…˜ (Es÷W„Ÿß0}:'œvZ˜ÒÊ0Œâh ÃPŽ ^àýhÆ0Œ"aDÖQ*±X ×uIåF#A ,¦i”ùèÝ•¸onn¦½½††Z[[Y¹r% .dÅŠ#½?‚ Œ2ú}¶E¹Ãš£¢! ~¬‚¸ÍDB &Ù,èAŽ£¾ëZoË÷U´Šï+Å3àlžïÈÏ´çºÙ|;{;WÅ?Ê–œáyk×^¹׼Ÿ³¦Nå#Ë—“°àøÏ½Êk9€T*ÅÔ©ÍÍ_å-o¹ŽÝ»Ïæ?øA°™L¦‘tú D"÷òƒÜËöí'2mÚòúëŸgÊ”½|êS¨©ù=v ÿñWÏóõ¯ïçK_²™;·‚³ÎÚ˼‹Å‹Ÿáïx˜¥K·ãy¦L™Ã=÷ü‰ööû™7ï‚Àáïÿþ«œþv ‰ PùËLÓ$cYV(Ê$“É0}Yc#Ü{o'ÿôO/qà ›|§À÷Õ1uì\·8z¦T‚ èu´‚PžøødÈ`aabââbcãç~ ,¬0 ˜5ä´‚ ‚ ‚ Â1ïÃç0éªÍŒ{u§œr çªâYÓ¦Mcæ†à XöãeT¬ÈÔÍ2 ú(½qÎÝwóá3Ï$žLrÒÖ­üëý÷óþK.áñ^à‘½×âA%O¡(VsNG÷¸®‹ëªšžç‘Í¥€ÑiÁÊùx–¡rÝu×qõÕWÓÞÞ@{{;W]u Ä”uëÖ±|ùòm¼µµ•ÎÎ΢ïÚÛÛCáF„‘¡'Û„Á±ÏRk¢¼èžÊøàDnÏNà_üÕ¤HQOqqσ—^ú÷wO(Ú=¯×qò‘+‰Lúïýüß÷R[[‹‘˵¥Ã÷¼ímÌïhã™;ö0gÎOéø÷/pë•Wò›3ÎÀΩx”Ck^&‘HpáOJÂóðTÇ%—¼ŸsΙËu×MäàÁÇXº´σµk+ùýïWóž÷,gÑ¢;ø—ùW\1w½k1üàœyæ¿ñè£+xòÉ |å+­AÀÝwŸÃÞ½w0{ö˼øâY¹ò/|ë[ÿ®]'ñ裯1{ö‡°, ×u ‚€Ûn[Ï~´€Ûn›Íu×=Éÿø4wÜñŸùÌW¹âŠGÙ¶í>"‘ÿüÏ›I$ÔÃí‚ ~„a¨ãíº°iÓ&&Lø ©”Ï”)™>ýï»"Èf³Eaœ©TŠúúú²mPÎ ¥}ö†‡‡‰IŠNX˜^×NÑ)¿ll©£"“HßVÊ“‘xv ‚PbŸ‚P¾ wßV§‡ÿ«fvræõS9û­“‰àí:áÜ7ž‹ñ¬šogÇN3÷ÞYÁ‹)º úþw¼ƒï.XÀÉ_ý***8uÌëè€D‚ùù»BŸø¾O*•"‹ *šÂz*®ë†ujô²}­w¤)IPimmå®»îâÖ[o £PÖ­[Gee%«V­bÅŠ¬Y³†uëÖ•lPZY¿~}øÝÚµkY¶l«W¯fÙ²e¬]»v¤ sôd›0xöiçX¨Á½Å)x<’z'šÛ™dì"‡§ü=dɆQ*š‹.z[nù&O?ýµÝX7lØÀîûþk×ây‰D‚úúz<Ïã«wÜA<“áçÙ /<¸€[~w1g]~9óoxËW­bó7²cÂ\×åÁº:*þ÷ijjâê«_eË–ûöU‡ÛK&“ø¾Occ#×]wýè‚ Êòå“Y¼¸“ë®›À£¾ÆŒ3°,‹þp"¿þõ§¸ä ïçÅÕ§ò²‘ƒfÍz™©Sÿ™7¾ñý$“M|õ«åúë§òïÿ>ðùÌg>ʽ÷.fìØoÓÙy/ûÛ?âºiN?ýW<ýô^æÍ›GGÇ5üú׿fÇŽËX²äÿز¥Šo|£‚'Ÿ¼Ëêàùççqï½üö·`Ó¦)̟߉izœqÆ ËÞ½䦛˵9†kꇠçyagUUÙl˲‘ †Z`)• I¥Rázu†Ú>»âááã“%Ú®……¦ýòð00Âé‚p¬"}[A(O†ûÙ)Béˆ} Bù2œ}Û?àq¶ÊvàÃÞÆÜy"gÂ4ð ¯æ¾:c¦ŒÁzÞºû­œ>þtHU¨‚ó%²þ¶Û¸ùÊ+å“Ð)Ó}ßç®iÓØ?}:{žzŠ?ð~qÜqü"ÏãY³È:éSTÖX–ÖIÑ™Rºb¾ïS[[ĵ, Û¶ûôíéta#II)¿îºë.êêêX¸paø]ss3K–,¡¢¢€êêjª««ioo§ºººßu^wÝuݾ[¹r%«V­¢®®ŽÖÖV–-[F]]]IëapèÉ6aðí3 d€¦^¦[Üš>¯föó÷Tì8üÜü=Q¢dÉâá…Ü'žØ®Ö™Íö¨‹[¹®‹mÛ<õT=Àž_ÉdpÛ¶‰F£d³YR™ cž¯Äuá¸ESX>y2ož7žzŠ}W_Í®U«˜øå/ðöêjÆ‹aš$“PS¿þ5¤PÿÒ¦I¼©‰*ÔóÞÍ@­ )–.}‚›nšÏOŒã-oÙ¶Ù0 æñ‹€W‘¬¦ ž÷'‚àt c‘ˆJÁ•NLå Û%¼Ô×Ï"™4Èd*hjË: x<\ÿ 7Lå _ø«W§1M×}Ù,|ò“*J¨¢¢‚§Ÿ~>:ÃHóÜs·°víM<õÔϘ8q7ß|%Ï=w¾¦¹”TêSlÙRE:çСC€I<Ï#âû>Žã„‘2Ùl6ì¸455‰D0 ƒH$BKKKø·ÚŸ8Ç:ÃeŸš||Ò¤Ã:)@¥bå~ ‹ZX¤L8¶¾­ ”'Ãýì¡tÄ>¡|ξí.`{]cÂìI[H?^‰yšÇ~¨€ÏÌù ‰M`lƒ™3grhö¡ )š—î½—w<òiÇ!õøãÜñ™Ï]¿žh:ÍlÓ„  '}Ûm<ô­oAm-w̙Åɤʇ>ÊÊH•¡E‰):ÅWoóév˜¹T3Zhåç3 £È×§}L#™¬ä”_]£¹¹™E‹}§Å•þX¹r% .,Z¾¹¹™ÊÊJêêê•FláÂ…477ØÁ„cžl†Æ>}”˜ÒÓíÏ÷!•‚sk*™ÍlæDïàå`c3Ÿ$I‡7† öý÷ „õF*•"“ÉJ¥Èf³d³Y%¦`²~ýmÄãq à±±1,0fY60qánö.š>§ÿëÙg¹uÛ6R‰¯½Æ”Ï|†ñãÇcª.YG®&KUÍEEæÄQbÒT&8Jl9ù­o`ûöñ´¿ñÔ@èŽÎÑÜz¹ïÇaÖ?H< mmJLÉä¦ÇL“`Zî€hܦ­M 1ïûèO‹Ž‹ãÀ /<ž+®¦ŠÌFb¾ï}ÕÜxãÏX°à:fÏžM"‘ ººš\@¸\tÑ9$JÐÉfáÄÀí·¿‡SO]]p>}¢Ñ(Éd’ÆÆÆ0¬Óu]b±X(²Äb1Ç¡¥¥…x×ÕÚÚʺuëB‡eá÷]E›ÊÊÊ~Sˆ½ôÒK\}õÕ#z…c—«¯¾š;ï¼s¤›1(ôf›zÚáØçwÞÉÊ•+{œæ½”9¡¾^9ç£Q˜Á ¤¿Ç/^[ÍlfªvÇsÏ=¦†Ú´iÑh”ÆÆFü\ }sÕE®‰DXE‡ž}öt>ùəضištty ê°ÄqgîÂuaÒþ¿…Ó®ºürÞ;Gm÷”½{sê©X¨g{¡«?’û­•Ö3 ¼Ü7XjZüÜsyåÕj.»l­×œK%¤Ô [X(J‹2†eñÇ /¤0È4ƒ¨Ò¹ùS¹ïêsŸàW»>ÌÚçæòôë•l1£è|$ŒâÚ3¦ ̘Á+>‰)SÞÆ_ÿ:…h4Êw¿{-'nç³,% Ù6<óÌ۹첼ôÒ•a¸l:.º®ôh×u‰ÇãÄãqlÛ#‡4AF‰ÇãX–žÓT*E$!›Í’H$Âó®sžÞ|óͼÿýïgóæÍ1ƒ²e°ísóæÍ\}õÕ}†hûä;Wf/ÖÚ˜ûéoyA(díÚµ¬\¹’×^{m¤›2( uß6C¦[í0A*¤o{ø}[AJZ[[¹úê«y饗Fº)ƒ¶?ÃÝ·„¡Bú¶¥õm[[[ûœ¯‚8X|ò– ‚G°}¼ÊDB-ÊÒʳd§èî€éÏS#x„çñý¹sÙ÷óŸ³ø¥—¸ÿüó9{ÿ~æ~ÿûZhpœœ$9Œ£c¡Ù[âA N÷›iĶmG ]6 £H€Ñþ;Ó4‹ÒÊÇãñðïþX¹råômKJùµdÉ2™ ×]wuuud2êêꈔÎÎNV®\IuuuQZ°®tvv²|ùrV­ZÕ-šeëÖ­Ýæ/%dlîܹ¬Y³fÐŒ ”š5kŽŠ—ª¾lß>/½ôÒ°î¨z ŸÞýìÒQîÙ„üJþ÷]J̽ûî»9ù¯'SEUU‡7]Ó4Éf³˜¦I4%“Éàºnxƒ6M“ Èd2œ|òd\ÇîU57 ƒãÞñ7ìYÇ“÷0§Û<±ÚZ>;e ç£*R$™ÛOín¶Q"‰MNDA=ûmàÅÍ›yä#_þ÷yœ°t+vnŒ¿“›Üñ² þÎ,l” ¢Pµ8“vOž À‰oÝÍÔ·m'‘[ÖȵÕq ÉVë}— ÿí« --úœ¨“²qc€ï§ÕúÓª_aɨ¿÷»M<úèPéJ4%‘HÐÑÑŽþ0M3TlÛ&‰Çq'ŒJÑÓõ¹Õ"‹>Ï™L˲°,‹†††£Â)4ö9kÖ¬’žvx%“ZjI“‹Õ @CCÕÕÕGÅHÓáèÛêÚaõÔ%Šs89 ¡D¤oÛ7]û¶‚0\,\¸5kÖƒIG²o+Cômûf ~[8øØAx×6æwÎÏOФ* ö!ðÈG¯”J6«F‚æÏ®ðAv}ãì:é$ªß÷>~õ›ßðÙyóTþóžhlT#€"Œ!†Jkº¾Õ>Çq¬%z®eYd2™0£I) U¿­¤•êêj~øÃÒÜÜÌòåË©¬¬ ÔÜÜÌyçGss3«V­ês=™L†… ²uëVš››Ùºu+­­­½F¶”Zà^PhåîHסS"Õ××÷B¥Gþ £›¾l4û BÇjO·UßWÏ7=À0 |þ¶ÿoì¬ÙÀ 1nºé©M<^•¯²k×®nëJ$ÔÔÔàû>†a„,:õ”aÌ›7Ï#Œ€è ˲8¸a"õõp`ÃÄç¹jêT¶w6JÈh$bì«ê&&ÓŸ¯œ9“à•Iœ¸pcèzn"/žû\(Mèõºä#YÂvç¶åç>'síÙóéIœ²`'Ü:“öŽ7â¡ú :‚%…K-·Á‚‹MÕÆ®ÚáÈýŒôý|º°Ù³7°m[ïš}<§¥¥¥èáÝÖÖV4OEB™Æó¼°Ka°d2 >¾ïãy¯¼ò £á²Ïž°°H’<ìåmlbÄH Ï áèd¨û¶>>iÒ88ĈQC  )xx¸š'G?#ùì¡oÄ>¡|i¿mìß¿Ÿ™_ç ûß@è°˜—ûmó ”³b z@3‰ðÓ;îàÿöoÌúÔ§0‡ËúSUŒ¶! Ô¨ˆr§\÷ÃqœÐä8NXƒÅ¶í0m<¨¸:•üHQR„ ¨=å¬_´hkÖ¬)JÿÕ¬^­rë···s×]w±uëVêê꺅gnݺUŠŽ¡.ôúúúnéˆ4ºSÚÚÚH$Ý”½D"eY¡ÃÑó¼PÑËf³áHò Â*]¤[Öó'“Ép}A‹Å‚àºB<§¦¦&Ì}gYiU5»hß G§ #Go¶©ób¦}öæöÉdÈ7Ï;æc±€ïËǿH$òÎ}ã¹ìMMÊq‹Å¨©©éVœ;‘H„áRšH$Š+Ñh”T*E*•¢­­-L‹T[[*‚–eÑÖÖ†ïûÔÖÖâ8étš ðAÐÔÔ ú$·´´„BJKKK8âZ :rÃqœ"q#‘H¶mE–R(nôE6›í¶¬eYa¤K466–4_o†A*• Û`Û6õõõÄãqLÓ$‰A˜¾L‡ué4cz´ºv¨ja)‹…}u­)£…—B¡(“ÉŒˆšYÎôT0l0ìÓ§ÿ?Žï{ß?sÏ=ß#˜šššr¶¥ÎUÅi|ï1ù¤Éø->oûSÀµnO©ÁK»^y¦Oк­.¿ûm PUU¯¿Î¢)SJÞN#ô×m(jÓi³×³y§]²iút^èÒ]sT:±tîoº4[0¯A>iWN:i[¶TñÊ+WbYJ¸Êd` ƒ?º ºétºäZQ£eÄÅá0TöÙ•€Á;†4RCÍa¹„ÑÀ`÷m{z140Š"¾LL,,²dñðH(AèÂp=;A8bŸ‚P¾ —ßö`0­x¤è&T ít(¡\tÑûk&£ Ä~6 &ÖÕq¸ñg?cÕÂ…%û´^µ04者‘ ¤¢ô Â. UÇ%K– Iƒª««©««‘f6ÛwúÏóÈd2¸®E&£æO¥Ôˆz ,¬Oh$‰0‡¿.|ÉdÈf³¡xÐØØŠ-Z0Ñ´µp¢k“D£ÑAqþëíte¸Òci!¤p{:M“N×¥çÑņtjuP¨¨êÕ£§ëcŸÉdŠ¢St @*•êU ‚à¨vÌ”#µO³Çga*¥œíé4tvÞŠ_…×Á¼yo&óÉùŸ`×I»H§ÛðýÞEÄ 2dz^Ê%?nÜ86nÜ8 }=œ1Âû§Og÷îÝZÆ ·Š+ª/Òu÷&LÙÃÔ7ìgÿ¶qì7®hYƒîâŒY°Ž•âç¾×…ï!/´ø¹ùv-ËÙg?BUÕã¤RÐÒÒ=(Óå´$ú©]®#ä éId1MÃ08þøR¨~ûùÙÓÈø#ÁĤ…–"ǯ  ‰mödƒA·T`º~JŠÔ  ¢‚p43’ïž‚ ôا ”'ƒm›1bŒ±ïgò!À€7.Ù«&¨ž:ktpv~¹>]9…Q ú³i²ùg?cöÈ¥kÖPño”ÜFTÊ“‘L¿V² r4£ë(ÄbÅ6WÈûÞ÷3®¸ân~ùËS1 ÛöijRË-YÒÉäÉ«øÇü:ñxœx‹‹Ø‡S?Þ4Ín}_±,‹ & ÒÑ<6ìh]X;A‚,Ù’¢ÖA(ÆÄ$N¼È>llÒ¤‰ïõ¹'‚ ‚ å@† 2¼ž]Ä‚À´uû™²{2¼ˆJí•!,kU3Ô²}øZ‚€‡z(ÿ·ïC&í·ÞÊÂÉÊwä8NiÎ aÔ¡KlD"‘!MvÌ *®«œz:}—vìÖ«Tï¡“}óæS˜;÷c\qÅÇùÈG ðñ¸ÇܹWðùÏ_Ìé§ß‡çÙ¡SP§æê…F‰ç*nk'²WàIìIa3MsÀ…’Ê-ŽhtÄŽ>v…‘þ¾©©)b ïšÆÆFlÛSŸY–E*•¶mÒétø½®ó¢S…¥R©¢âÖß÷‹ °0ê%‚Q™w°\(|ø²?ËÊ *A k–eñ¡-—±°˜½a6Ûý7æÍ›×mý2¤Habâáõ8Z×4óQ ý±gÊ.œ:u@ûh10Aå‚“NbÁ‚ƒ¥{ʱ¯UðjëILºl'óçwvkoÐK›uÊ/}¸ »úÈúä#XÔ† ÞñŽéÜíAúüæ£P’ÉbÅ÷U¤Ò@Ð÷W³‡â,–e1sæÌA:šÇ"C¶n]ãÁÅ¥–Ú#U$ÒE8ZéÍ6LÌn)½,,âÄÃô_b‚ ‚ B9ãã‡ÙDÆšDÇÍ{¨¨ÙçCÑø .®7‹>êÕz[ªªÀóØý™Ï°yêTv~ï{<=u*§ Ч£ÑþIïpF ÆïûÔ××ãû~®sªÇÁóƒAÉEéׯ_¦hoo µµµh¾žò_–3ž§RþXÌšõæÎ½ˆ¼Û†oÜÌµ×ÆˆF£lÙRŧ?ýŸüä,R©I¸®¦#²,‹ë¯W…}_ 4º‰ïCMJcj[¶¤¾^9rƒâqøîwóÇ­kÚ­œ˜ ¨vjñG; #UwB;+MSýîIlíI„ JI“u8uXÌ^*ZkJO·, ÏóˆF£ÔÔÔ„–>¾$ ‰D(Òh±¤PÐÒÑuª±H$‚ã8¤Óé0ÜâÅ‹‡ôX+X,]ÚÎ3Ïøa„QSSS‘=8Nþo¡…K¹”¹ö\è!KV† ¨kÌÅÅÃÃæðG lš3‡iZæpÊnu’–cÇò§qãÇ>¦ïßßmºTt±{ý]Š|z¯B‘Æ+˜/K^ÄIûßö«W70¥F­ð‰¦¼˜’J©ûa*•¿Wé@}Ž˲H&“EÏ-¡t‚!+ocÍ%ŠÓhí Îé–ʨ¯vÖRKMGdß‚PŽnÚ=›‰0ŠÅÅûAAÊ=€èäOßGÕo—°—Ê7UÂ#(GC’bçDöwßôê«P[Ëîª*žßµ‹ víâ^Û¦sþ|׃§ýÀ¥Öž mƒÄµRX>£¶¶–O~ò“ƒ¾­’"T*++Y´hQÑwGKa0ÃPNÚD¾öµfëÖ?ÑØ¨|?ûÙÓèd}»wOGsë:(ŽãÕ9¼Pë ©”SR)õ]&£ÃPNÃtZ-sèÐ%Ýږͪšúz5ã¨é´Z>’@¬Å“úúüü™Œ‹jkÕö@ýւʤIï£c@§Z¼ã:ù»ÖQé:MG¼D£ÑÓ¤i#ÓQCº¶J×ýÓø("€IDATЋh ç‘ú*£§(‘lV]¿É$Üu׋ÅÂóÕU\Ìf‹¯ÓÏ¿ùóÌ~ÿÎnâ¡®Õbç~LÌ#J2y€õS4M–ÔSDÉ`óκ‰L]ºwMcÚ¾}ݶ§÷¨ý}a;uÁz½¯àä¾_ù€Š(ª²aŸ ÿË (:ýW¡ ™&46–Vצ/Ì#Uc„!MÅ¥Óʼn“$¦æ%~ƈõ[ÿA¾Ï’ÅÆî³N’ k88a-•zê©¥–‘>Ÿ…¤áAA† ý^·õÛWòì °ãÙéLÞœKùù°NéëÜRSÃc_ –ÅŽ ØuÛmüyñâ¢2‡C6›í–…H(ot–¢_þò—ƒ¾î’"T.\8ê"Oú#‘PN=ràÀk|éK>Ï<ó0ozS5™L ÏûðvnF'¹±m›–––nN»°PsA‰NËgYÊqhÊihYJüÐLŸþ,p.6\ÆqÇ©¨=ݶ‹Óé4Ež—l ÚÚÔt­ïA>2&•Ró_pÁ‡˜1ãÜpÿ!Ÿ†G;«›šß©9\Î̾nb…éĺ֣Ñt­ábÛ6‘H$ŒfI¥R=î‹iša{a`h¡Ã#Ÿ2J‹¶¨º¦ƒë‹*.⃛ºß›\Ü¢Q½Ö *ã·o§s€Ñ)‡ƒÃ€ú ‡MðíãsÎNÚµ«Û4}^ººÔ ÏYר€ž…ÍþÆDá §&!j+Wß5:2%›-=t¸³m[ŠÆ!怒ÕNîjÏ’ÅÀ B$Œ$sqÃéY²E,1b¤I‡ß'Hv;¡\9’ÂòI’ÔPƒA”(&& XX¤éÞ7J‘"C&¬Áâã“$ÚÙpÜAA„cšÝÆæ‘-ÓØ¾&ϩӦÂ9§ù€ ¥­ŸìÞÍW]ÿýßìxùeîâ(®ëöê_ÍŒvßf˜¢Ñ(×]wÝ o·ä”_šöövš››Ã”_ÕÕÕ,]º”ŠŠŠa:TGŽv๮rܵµA6»Çq‚ Œ>±íiÜzë?ñë_7°zuÛî×ÑÕÙëõ(AåÍ6x)%bÄãyA¥+NžÓŽŽsijRów­/ÐËR"ˆÓ‹V‹EZ,ij‚«®j`óæ è–x\9/uª0ßWÑ/º šHD­³ðþ‘H¨å µ }l†#zÃ÷ýApôz|ß'‰DQª0M:&‰È(øÃD;dô-ûÉ'Ÿ¤¥e¶}¾ï‡ÑB¥^?•î¬5ž'e ‹$I\Ü¢”AGšO~öìÙ¼xî¹ðøã#}øŽ˜iÓö°ïƒ}k7)Ž–i¢÷èÕ¿q{™gsØpYÖÖ€uHÝ_*,ØR`F®«î9:Õ)ù¶—(È =3Ü#Ô›h"E —6ÚÈ’%A"WR¤ðñqpððH‘¢…"DÂz‚p4âᑈ‘$IŒ4†)¢D©§¾Ç4`..M4QO=iÒ˜˜dÈàç~DPAAÝ¿ÜÿâI4¼¼ü/LÛöN¡r˜]O˲8ýüóyòŒ3x}×.Î:‹§çˆÄýÂñ@Ok-Ë⢋.ôm ¨(ýÊ•+±m›•+WÒÚÚJkk+×]w—\r «W¯¹#6@²Ù|ì³ÎÚK}}=Ùl–x<Žçyd³YÇ!‡1c¸ùæS?~{ŸÆ§‹5;À=¶/::”ØP ϰoß´¢ÈËêYŒ%‚ttô_kÀ4¡¥Eíï¶m§‘ÍÂäÉÃõ'J¸1Í|4LS“rlÖÔ¨‘䙌jS(gg,¦¦ezò}uÓ4}ºNûñx<,ˆÞu»†a„ÂËÃ?Ì3Ï<3¤ûz43gÎOyÓ›^eýúJ°Òõ/z¢«³ýBóí(Y²Dˆ``ts‰¨2÷¹çÀuù¹çŽôávM™Â¾¥}ëé&ÅEÞz»ûä£ózÃpà70ÞVt&/09·‘OøPk«ûÐ@nGÚ)ºs¸uŽ„8ñ°f‹ƒÖ?Ò)½LLbÄðñi¤1aŸì½¡ ‰ˆáàÐAG·çašt·¨. caÑANhgºî‘ ‚ ‚ &66bÓøMÿ{6öT4kNg'$¼\Wú ÏûýïÁ²eÀ·øÊ“ÂóRX¶a¨)YPY¹r%k×®åúë¯ç±ÇcÍš5¬Y³†Ç{Œh4ÊÊ•+G…¨âûÊ!*!áŠ+Ã4Í¢ÂäŽã„餿Î}ŽiÓö1wî-%åÉÓõ %'!™3ç¦O_7$û­¯§9sîÀó`üøí€:ŽÓ{z¶¶|„M:O5ª¿“Iõ¹¶¶g'èüšlv`mõ¼|m—¾(Œ(,tª ÂÔSš®õU<ÏÃó<žxâ‰AÛþ±ÈÓO_EKË n¸áú~E¸x<‘åyJÛŸ5/ë1˜˜=¦29’´_óžžè@/ä2fòÎLß¿À}”®˜¨h#ƒî¢‹>ÚS ˜kªÔ_ÓQŒmà 6äjE=æÃG *éëHþÒÁ§§:Ú,Mš8q,,’$C±ÇÆ–èA8 ´Hãã“%‹O†L˜f¯+z@Ba­¢€ 9Ëáž!‚ ƒ…$„áC¿ßM^v/¯=o°ïÄv2‹y‡±²çŸÏcѦM\6{6õõõ¡¯·»A•ÑÁpùˆJJùÕÚÚÊêÕ«¹õÖ[Y¸paÑ´ŠŠ ®¹æ2™Lø¹Ñ©¬‚ Ÿ ë—¿|‘K/µBÇy[[[‘}Ò¤]üèGó°íçJÞŽ®%à¢ÆY”³1…\z Û°á2n¿}#/½4vHÁœ9wpÇŸäÄï0Íþ£h SŠÙ6Ý €G£êxêg…÷˜ªª-˜æÔ°~ (Gx_÷!ZL×Sèß÷Í`LÓ ú=¥ Ò7PË²Šœÿ§Ÿ~ú lÿhG …Ô;7pÎ9ÛøóŸý~C( CEG¥ÓJLÉfÉ]ÃË1l5º¡7‡Ð‘®ŽF£G•ãþÂéëxdêé|ëø“XP|z°Â³g“TvùpvV›1Õý1†0ðxŃu¹ ´Ÿ2é%<¼²*Ê­=‚0è´wCƒCŒQ¢dÉÒBKó¸¸á¼@˜L  ‚ ‚0ÚH Ú¨w]ÒÉ}Wøf™*ø^„Áeïó³9cÊXvœ·_Õ£ŸÔ}ž¾Þ·ÿú×ìz`Y¼²~=3Î=—¦¦¦AKÓ•N§%­¸PDI*ÍÍÍÔÕÕuS ¹æškèì줹¹y¤÷©W2%46B,Ã4}öí{¸[îýBfÏÞÀ‡>ô`¿ëî:®>@9ã¹iYÔƒ·¯ññ7ndòä·ùqøîwdîÜ×u–¥Žk&£Þ*5Ò¤I»ð<%¶€š‰ô¾×U‚Mc£TJßþà8Û Óˆõt³<šœê#]d+j°@Àüù+K^G2™¯ÝÓØØ{¢®XX‡]B§y;Zxæ™71fÏžAÙ§(ê>ôèNó€ñï«ûâ%9³Šå„•w9°Ã€­LÌM³íÙ¿çy’Ït)GAÅÁ‡­pL2T¶¨SzéFF/»‰‰‡F£$r?ú¹êâ’"E‚ÙÜO 5¤HôáAŽaà8zÎ’Í}´Ú_Ó–ûA (zžLÁgAŸý9ƒýÇ·sÚ­j°²¹›nê¥C±ÈI„é-ö¯[ÇÖ±c!åà-·°wêT"}9ÈÑ&¦ u‰†c’•­[·–´²ººº‘ÞŸ~ÑÑêâ‰ðôÓwöéŒ7M“9sîèwtáT¡ Œ=‹R´¸Ý˜††?qÚiÛ˜5ëå!?®ëÙÍ ™TÇwܸm€¤l»8—aäÓƒe2ùô>©”r¢:¹´?©”š/z¯©0#ÓMÓÄuÝ"g³ÛC•l½í—_úsv4‘ÒäÓïçy˜¦Y’0fçj†ºÖâñ|ô“P[¶Tqê©7ʺLúNmçØpRî–S8o°xÀƒñÌÎÍãyJxõýÒ꩘¦)‚Ê "ŧ¡|0%ް;&f˜b¡‘Æ>K}?ppÂHOŸ8qÒ¤10ðññðˆ#B䈢BAa0È¢¾N %éÜ<ä‰Ù¹ñÜ<õ¹ùå•S† ‹i§¿ÆöŽé0Y•'0M”qöE*¥þe2ìÞ½›ã&L ’Hð¹ÿú/Ç¡¥¥¥ßm Gžç•WʯÊÊÊ’D•æææ’R~µ¶¶²uëV*++»E½´··ÓÞÞNuu5ÕÕÕƒº³–¥ «+G¸a=/DG, ¤N‡zhkwT£^êìµ@êA·øÖß|~QGÔ÷áÑG+X¼x>>ª¢¦ŽÆ{9rÎ9âyÛ‡tZ@.$MþeEßßnÀ.m‚³r˸À3¸?§N§]p¬|m%˜¦Drã¨JÇÖCmŸ… Õˆø¡Äí3¡¦ -#Ñ·nÒ¤ 00ppˆ¸›t‹ûѸ¸E‚ЇG‚M‹àY²˜˜"¼ƒÎp>;ACmŸê"ò‹$ÈGÖÇK^‹òéÈwáXc¸ú¶^AüØK¿˜ÍÕ—Ÿ¸8©Ÿ$“ÊÙhܵ‹©3gɠ룣ÍïfšæˆÔÕ-IP©®®æšk®aùòåD£Q¨¨¨ ³³“L&ÃêÕ«YµjUŸëimmå®»îâ÷¿ÿ=´··cÛ6 ,\¸•+W²jÕ*êêêhmmeÙ²eÔÕÕ±â™Íæk.€T§ÿÑxE›¬Aï] % ¤Qy]íPíq\vÙ~7~<õäöIò#)s¿=èwüp,÷Û§ô¢i‰\ûãÈlÝz<Û¶cÆŒ@‰&…Á@…ÅíMS9I»úD]W‰)†¡"\€¢âöÚ^vïžÌÚµó¬àÃ0hkkëwžÂߣþl8bûôñ™Uäªmhx‘×_¯é݆}ßÉ’¿7öto1r3wd‹°øÀP7¼(¼˜‚Œ­ñXL )¦9ðâõ£•á°O‹+é¾a eßöpë~ ZL);;k©-ú[“%KŒX#ƒÅp>;AÃaŸ)ò‘&:Bþp…‘£ã_Jc¤ü¶3ß°Ÿÿ¢Ô±æé4w}îswëì^»›^øVè?ÚTòrf¸ éh“®éººn½ðù§—0r7©WÝS²Ù|TÛ@ŠÖv†Ë>5"¨BéŒTßv4`aáá…µTR¤ppÈæz±zZ#xx¤H…ÓáHîg§ ¥3öéÑùAº3œ}ÛÂÁ4‡âÑIòʬW¸‹ñÿú¯,øÐ‡¨¨¨À4MTJ 2™Ì°ÖR®ãH))BE³bÅ ¢Ñ(ÍÍͬ_¿P…èK-F¿dÉ–,YBgg'ëׯ§¹¹™… RWWÇêÕ«»)š•••´··÷¹Î—^z‰«¯¾š5kÖô:O*•/t^_pª¯ÁTì TþMM%~ÜôüóA@çüù(ÁEG³Ø¨ŽfI’O›¤Ç ¦rŸ3ä˜yÁD§{ú¬³ØñÃbY©Üt]×ElÓëЩˬܴB±ÆÈM‹Ó]HR¶˜âÙgSüå/oQítºG XV¾®v”v^h ¾ŸŸßuÕççŸø8ï|ç²¹wpÓº"å]Cï¼óÎ’ê •;}Ù&¨Q ‡cŸwÞy' î[È]/.œ8y;>ú}V¬PáG"¨}èH¼®X§B<3 ä¾ÓbËzÆ'Ô½ã÷A^|uÝü=£¯[ykk++W®dóæÍ#}Ž˜¡°ÏÍ›7sõÕW³dÉ’¢ír_*C2²=E~„~èe)ΑÍM/üÎËÍ_xKË ¤>ùQÇìǵkײvíZN;í´‘nÊ3”}[sÍè~.êbõY²4ÒH‚Q¢$H!ƒ¦ ‹ ãáàâ’$Ã÷ñEøB®¾új^z饒ßïÊ•áêÛ Âp¡û¶/½ôÒH7åˆ޾­îŽzÇ=\a´ }ÛÒú¶+V¬è±^RØ1},/Ø/pÂŒÜæH$B؇¤h©èzâAõ)ÒV®\ÉwÞ9è}Û’#T4,Y²„+V°bÅŠ°Aííí¬\¹²¤u´··³zõjÖ­[.ß“Sº”±¹sçö)¦´¶îbìØ?A (Ý—aƒ>š»Ðâ÷¹dr!vÁ|qò‚†C¾xšM^T©%ÌŒCJpÑók!ÄD‰*y‹8^üÄ'ðP" ¹íèù]òÑ+ùh˜lnþÂ[T-*2¦å{ªÉ}WùÞÿàá·¿]™¶À5Õ<šd2?Ú<ÚÃðÃPËÅã*ÊHG«¸n>EXgç•tvÎgâĉatJáéÊdw$»VnµóÿÒK/¥¦¦fð60Âôd›pøöy饗†/œÚQk©?øÍˈF£GýÍ»ÜHtÞo‹ÒR¾Õ„zSÝo\Ôýh» §çR^ÒÿäîsÑ|*À¾X¸p!kÖ¬aÖ¬Yö¿CÍ`Úç¬Y³X³fM·|·Á¨,JXu_ôèþ–LËäæÕÿº®£ë²òBK$÷Á §z`Žþëâ¡¡+V0sæÌ‘nÊ 1Ü}ÛÑ‚… 4bcÓBKøwš4I’aTK–,õÔ!‚‹KŒUT‘%K-µ¸¹ŸTQÏR Ö¬YÃ¥—^:ÒÍ4†²o+ÉîÛÎ;w¤›2h eß¶ëf9Èðºd¡¿Âuó©Ì5©”š'[´©?AÏþ ½žÂizGAFŸ¥¯ã§·ômûF÷m{S@ù*Ç/‰Ë¸Œ“§Ÿ\z#ëëhll$Nô!U¤ÓiâñøQuÜ|ßïq öŠ+†¤o; •¾ÐÆVJSw:;;Y¶lÕÕÕTVVö¸ÎÞ n ,ZtwßÝÁöa9 ÃòÑóÓ§O`òäɽÎS¨9$)öíhaDG·hòéÃj€y¨t?o¬¨—-txêBÒ6 Íª¾`š^¿]ÐýÌ®Íýmï}¡ŠçN¼q•o¢žqDQ~$“|ôæE`_Áßnn>x!×áÐŨ=ššÔ¨u€›nšKGÇôP|éŠNHå¹0MÛ¶‰ÇãÜx・ò¤'Ûlhhûôñ™®Ï¼ÏÜzJûÔÃáá×BÆp÷ݺËü]–Î*J 3u=·lîù’­ÏVÓ©½<ˆ¤”ÈWdnƒª÷ø7B}Ä÷PÿÄêÁýS~ŸõËp·ã`¤¾ÞŸÁ}+$þ¼« æ‰ìC,?Šn0ž}Bÿ UßvXlqˆ':W–ƒƒ‡‡‰‰……þ%‹F·$I’  .2pBÐ ç³S„1ÔöÙ5«ªöW.^î}ãé,|¤Fùs åwÈf•¡…P¾^-0h±!U¢A:`ÕûL4ª„“lV­£© ::Ô÷ét^D1MhkËgðhlÌÏÛÒ’ft–¶65½k¦TJµ_góH¥ÔúR)µ/…Q-±˜ZN/¯—Õ©˜³Yõ·îËê߉„""‘¼ðJåÓºg³jÝ©\_8“QË鿵X‰¨ïb±|[ôñÏf¡¶Vý‹DÔ2±˜Z—Þ×Â~q,¦Ú‰¨y‰üô®‘CzŸ´p£ýLŽ£–M¥ò¢•>Ï<3mèg¿­ O>ˆ=èï0æ.´Mo{Û¿_²ž$ <Ï+Ý·8 Z„J©¬]»6,pÔÙÙIkkkX‡E9ª««£µµ•ööv–.]zÄÛ3æE‚ À÷ýÃR«ÇV•«TLz.øÜ×ü»N:‰x<ÎÚi½ß¥ºÖEÑ·¦þ$¥Â[Øžª*æ.ÿgŸ_”ºÌ&_tZgSYmÀ¯¢ù»&ùZ Ëóß¹@­¡¾×ƒ‰§O–ªªÇ±í†°K¡ ¢¿óýühˆlVuN¢­õTGg µxF½Ù&0(öéá1.'ÿU}fTÇšÓ¶Ï”%ïÈÔIåtŒ¢‡ÚÙH>D+K>WTιYTCž¯ÝÎÔ_]1úø^N²mx87£ œeÂ:-èÈì¿>ø+Ô#¡Ž6†Ú>p$ø  Cu¾É&Tc ê¦Þõ‘ê“·Óp¨‡é…M rÿt4H׋*K.Ô‰|˜faÄIœPˆÎPë0îã|¨_ Ñ1Xæ„ø°.Ó‡Øýàü¤Ÿo,÷¨UwÄ Ã¬‚ï9ˆ}Ú¾î&°æBãÛÁû2¤þ ‰_CSîÑZÉ?¨cäûàÿ;Än‡èŸ °À?R'Côjˆ}Ò…ÄûÁª€¤ØP¿¼Ÿ@ãmêEOœtœâ‘ƒúÅZ†¢oëuË/7:10TãÈÀ ©—¸C½žÂh;UÒ¤©§žCÝn ±Êp<;A8<†Ò>õ«à@ñ¼â¬zp¦ç)ac· WµÀ>WMëÉPè6êÍ]`šÅ5fu¶®Û×4æÒ‘h?aa”I×q¿]ÝV†‘þ(lO(aÂóò‚M"¡¶¥Ó«ëHí£¦F=˜Uÿö2GG°h¿’žÔ¼Éd^ˆJ§ó"Ñg>sŸýìïãÊ+?†ÝokÂ~{*§N?d2L¹çN¹új®ýÜçˆvJaTDZ,kØ}\Ã*¨444°nݺ0\lýúõ,]º4Ìs¹bÅ –/_΢E‹X¿~=+V¬ ¢¢âˆ¶éypèP¾ïcFY+—»Nê/¶­˜(ÊÑ8Ø™Ù'’L&û|M7{ø[û¤JÁ<5…g߸ˆ‰3ÇÅ™Môs\G×¼Ù„×Í|í«p#ïÛàCµ•ϸ’Î8ãI<ï ŒœãÎô‹ë±8Nx¿ ‚úA]jˆ§mÛ¤R©E•£…þlÇ>_ÃÌãáŠ1m,þóÛà}¨“¯ÓÙÔ“/¦á¢N´VÑ¢_L)òUíÜGñpÙ§‹{äÅÝuñu—|áu}× Q”hªÈ‡7ê‚_*ÑvœA‰¨µ¹ùõ}¡ •ϲƒ|„‹‡ÔöïåÖ£seæÖ—XÙ­ÀçÀ˜ É›!ÒÖ“`œöéÐô˜2¸ÿ ‘ÙÀ»ÁYÁ+{ üi<ñÏ’ñL€ó ¸ )@¼ *+öS`·€{=ÔžñwAf-Ôï…¦2ßã.°k!ñ ´ÝOÓ`ÛÀO¡~)¤—@öe%ê$nƒ¦;sÇ6P/±55ùºC¶­FðéÔ--Cqµ{ eßöˆíñ(ÃÆîñ˜ØØ¤H!‚AŠA˜,NŸ âĉ£1L–+­ ׳S„3ÔöéQú S¥LªÈÓT}(QÑÔ”·ðPƒçm§»p1zJ~2ŒƒªÃ6tí ö´O…î³¶‚ô¸º?©£7tÔ‰e‹*Éd> ™^—UmDo³©)/ŠhÑD÷}ãñâîmmjÛ™Lþ¸éõŠO&ÕþUU©uZV^˜*Ü-ºè´bZ`ŠÇó©Ô £ûùÑ"’þ޲ছvðòË£¿~çpùmu4¶›ûïÄñU%-÷äŽT|ñ‹|ÿî»1 ƒh4zÔ¥®†a#Q’ ÒÜÜLsssŸótvv–´Á5kÖÐÚÚ†…††544PWWG{{{·i‡K"“&ýÓ4‡¶Ÿt›˜xq ·Ã9ùÀaË–*f¿² èùæZèTÕA]õDuƒo·a|ΑªýuéÆF,Ô€ãÎÕLÑù=¡8*E‡}Ž­yÞÑ1Z´7ú²M8rûôñÕ#Óûí°å¹ß3yã;Ã45!z»‡ Cê뢵P'¾‘|®(¢=J`©É­ó`Áºµ“¶©‡mø¹ïªÈ‡lÉ ‡aÅR X;îMMê> ýõµÀG,ÀÈçã½5“}%¾vÔ†Ú>A *NÉÒy”Í$É+å:Rà _ 'N±½kõQv¬4-Ósi·B%]‹2…'¹™L¬w•…ì`ŸÁ`쀘 ÖXð·AüLÈÞ n-Ÿc¤&Bìg<#ùù60êÀHVN¬ÿD HÝÎ<0ÿ‚ïñf”˜;u‘¶6˜.dRªMEhÁÇû»àü‚û exúXý¬¥à|¼÷æ_äÑu×A4|Y/€ “[w‹j‡a©ÔBý_Õã´üK"äÓ0˜fÞ™ œáîÛ˴г˜&‹K† 66288¡Ø¢ ÞgÈô˜ŠL×dކãÙ)Âá1”öÙ5°¹Çyü|ô¨>Qc£êÕçR»ê¿…žñ}%|¦ ‚îEܵ¦? ³ˆ”Ò'íɧ£ÅÂõØvïÛ×ëæ£R"¹-«{Ý—¯}í~ûÛÝC{Ї‰áèÛEc»0®¾´ñþûs¿ñ âAPÖ>^á觤+¶½½ÖÖÖ~çÓ!šýÑWÁ¢ÁîÌ~ñ‹|ó›1M³¬£SNÚµ‹6ndÒ®]0Ä59* èçÔ@ž1÷5&TœPÒ¼úyÕSÛ²¹6$ãʉZ˜¦0³“Ÿk¤—˯s}‚zH¶µåGèѺ¡œ¯ŸÁ¢¿bbGbŸa*!œI¨z\y.=Bçb耵€RFOÇÉW4‡ba¤ÐOÒ„rÈnG9}µJè£.0»  œÂZDѪž0¬$L—þ‘Oõéúƒt¨ï§¸pÀ…SrEuÞÜ£‰¡´OPÚôáTŠ÷ ~G)=Ô Š¡Ò\ôIò9+µâ£D¾Ï'/Ðèuæ"Òü§À¸j¦Aãé°ë#'á·AæF°Ïo"$>ì‚øü⟆ÄoÀ};ØÛ :ŒSëŽZà6B4 ÑlAÛ €¹¨—xøˆÚ'àͨ{ŒNS¨¯[šìî/•]G$µ Ô_ `ƒ:æÛ¡ñ¾޹M˜KÓ±Ôà‘ð¥£q2(ƒig%$n„¶W•Ð’Z 5‰|º‰ ÿ©‡øµ`¤r«GBI gßV莙ûH‘¢¶0Z%B$Læáab†‚J@@ 59Ãõñi¡%U2dˆÃÁÁÂ"Nœ€ ¬ó"”?Cýìáð ûÔAÒ½‘J)‡{}}>;Ñ{Ž"žvÅ÷ý˜÷ðÊT }ôiLÓ–ÂòG¼yóx˜Ñѡ⇗‰#Öç80a¦îe|åÁ’—Ñ5u o‡ºæJ×ÁºŒ†öã¹y²äG*x^~t‚έY[›Ÿ®£UJí«”óõSî×uo†”Þë^¾¶A’|QèRÊi1{YN§ŠWêtŒxùbO%$ +]ÃÐmò~mP§MëpÛL˜eÁÓ,6¡%3Ëÿ=¤¬ð)AòèžGA‹‘:jD‹ .ꦜ³£0tz¾27@¶’·€¿‚õÕoÁYÔÉÎÙ_ör°ÿõ›Ày3džƒôÃ7ÁÛ ¾æIýD§_PmñÏ‚Ìí`½ˆC2J>˜Négçê÷lÊíO® =¾ÌêB?úÂëjÙeÀ{O/•Ý(xÀ µïç`çJ™oîe¹‚?e¢…à\„³Ì‹ÀÈ©‘ÑŸƒm‚eææiˆ]¬„%s/$êóitáTA(wLLœP\‰Åà ë¬88¸¸aDK”h(˜ds?)RaM-¬dÈ}_(æ‚ #Oo]¯lVýÓ)T »y¥:óûKîû>555´µµuU 5òÓó–eáºn˜UÅó<s/=¯ž?,ËÂ4ÍpY=_×~k&“ÒͶ=úÞÖ£9R¦OßÏñÇoé]µ8î0¶gûÕ…s²YҹР˲F…ð(½”$¨d2Z[[Y³fMøÝÊ•+ihh(ë=ž›7ßÈ¿¸|T8ø}ÜЪÚýwƒñ_ÚÆ_bçqö¹J^¦·3¤ ÚëöëüP<0:ý?|P0ʤPDõÐÔ…Ó´ð" zD¨>_–Áó&EƒásŽÍaG;mukÓSÔËQB0JÂc»vÐ-ò—ŒQðÀ ˜oÁfž¯‡üÙ‡ó¯{ÇHïÆ¨¡¤47.J0Ñ‚‡¾!ëB[:cœ|ä™YRõ`¿ ‚=`xà.P÷âÚzHŸ©-àŸÞÀÜVª]bäî×ÿ:[ å`¬w.°f}z—Ì>?ŸŠ[?±•Ôµ•J ȵ%“Éà8†™·¢‘„qH¥R¤êStttt?úºL«ù@ÂÃ?ê÷èXM¥R8ŽÓïhÅï~w'D§´ö‚ÚcƂ轰öŠ:Ñ÷¥/YdóKCtدñVH} ¢¹¢¤zRÔ~è9ZŠÒ7&fQ}³¨È½Néåà%‹‹K’dxÿspHåFQ$Hàà„‘(qâ¤HáâÒH# ØØø¹Ÿ–’BkA„¡¤¯áA™L¾¨z×Aí½½¥R©|ÿ­—¼á¾ïãºnøÛ¶mjkk1 ƒ hllĶm\×%‚°Fk2™Ä4M2™ ---ø¾çy8ŽC$ ·›É9. ÃÀ0Œ°ßêû>Ñh” Èf³¹&:¤Ói²Ù,±X,¬%ÇI¥Rd2âñx¸ÝxÓ@"Ñ=/ó€éOð°Q£Ò„e]þ÷ÀþXw«óTƒq Ôþ ÌEà<‘ͪΌ}m¾€g"‘•Çå‘H-AÆÆ…ª(Qj¨ÁÊýba…5W’½P‡1âÄqr?šZjq òƒjQÆÆ&^N–%K@€‰‰…ÖuÑâƒö—A„ÓSýßW}ÈG¥O(Ñ ‘Hàº.MMMEïü¾ï‡q²Ù,±š:Î=P"‡ïûضM&—~Ȳ,Ç!‡ÂƒçyÔ×ׇi‰t?1]—JOÓ˃Ft WÓ4 ‚ P|ß§¾¾>ü „¢MMM ±X,ŒlÉd2aŸVï‹çy$ ,Ë¢¶¶6\¿g - 騘H$B[[†aP__O:Æó‚°ï¬¡ ŠŽmÛ†A*•"E×€z?5 c@©Òú~ºÎ'EËË—‡séföìÝSô}QïL¿,&“$³Y ÃèÕÏ+õð„áâèJò×…ûîû?ɧ×.NÙá1攽Œ™º—󼼡äåtM”ÞèÚnm£qàÇà÷>ZÂ4U§J­·¬þk-xž§F ‡Í–Üow!ÜñË=G²ª¡CÐ–jP¨¾à¢÷Øu ¿`ý]™õáF»@¨[_xX›ê°ètáÖ4d¾üìH7õè@ˆ‡|M¢ÂKÈAf/ÈCmêå5“Qâ@}ýU¹ô›vQncU]©™Žc‹ÅÂQt–eqÓM<å׿þ`øBäº.™L˲x÷EŸæîŸOçßbŒ;&|‘ÓÇìÙg’JYÄãq"‘ñxœl®#î8±X,|ÁÓ£ £Ñ(ŽãÉdÂÑ{ŽãH$hii)²Ÿšš<Ï£©©‰T*nS3¤Ói2™ ¦i†éô w$ ÷µ³s>ûöí#ù`8rqÈÐéÏ "Y´ÀÅE€†Žt‰¨ÁÁd°'ƒ± ‚ÿšÏµ¬óU>rËRç½@Wq¬>ú%ÛÀ J´Ç:(661b´Q|ØØEBJá2"ẓ$11©¥–8qbÄÈ’ Óƒ$H„Q/qâxxDˆ„5Aî§°6L¡8#A„žéÚsÒõS ûŸ‰D"tÊê/µµµ9À EÇqH&“8ŽÃ?Ü|3g~úÓdŸ|2ì‡êÈ®QÍÚÙkYလ’÷¡ b¤§im½t´´€aA@}}})£Û•N§CñD÷‹u_òïŠÙl6l¤¿×}lÏóBñF/Jl ºÔëÓÛƒâAH™LÃ0Èf³a;ëëëÃK¶m‡št{LÓĶí"?ŽìÉf³D£Q à ‹‘N§Cñɶí°O¯¯…x<Þçû±±t;‚ —‰ÅbX–ÅW¿úU>ûÙÏñõ{¬ñ—\ Ê™oÙûL=\+¦i†d!Á°ää„£\PùË_ÆñÁŽžá¨{ÝSÚ÷¡`jÍqŒ?¿}@ËÄ)­„Æ¡ÜomƥؿíðX~ v±ÿÛóòBK4ªœCMMjd­&‘È×^)DF5>[ãe¾·ì¼…¯~u¨e½AÄ%_à'û¬ Ië‹P£‹mëPª,ù 0WÔ:¬–˜K;‡ºxsµ%ˆå~GɧQÊæþÅsÓ»FÑh¼Üü]ûƒ:úFoRwuñ¢Ñs« ±ÉßÓv‘FgcM¸+¯½6w¤›9*è·~Š™ÿès¥’ 1¶\qs®¾z3ïxÇ~ÞûÞ9,_þp&žç…#Ô4555¡¡_|2™ Ùl–d2‰çyá¨8ß÷C±B¯+›ÍÒÐÐÀ4ûaÞYñÎ0ÿ´D‚ E’ÚÚZZZZÂ4ŸZ &©TЦ¦&b±X˜«Ú¶íðÊ÷}•*¬ËË–~áÕÛÕû¢Gê8-é—9ýò§_êâñ8êØLšô[‚ ‘HF‹ö«¤ó™K9ÑS{‹èáRô¨+¨›bZ*Ýšq>$«Á¼ D/†Ä­ÐÄÏ‚`,¤ì¼¸¢óR×Ô„‘ E”d/½a]ƒ¥'A«‰žCÇ,¬néÅ@ - xx´ÑV´ÎZjI‘¢‘ưöK$÷“$Ösi¡%¬Ûâã%J„ "m ÛÜ7y@EÈ8C>¬J¡|5²PL|ľH£ïõõõ8Žƒëºá€PBÅÇ;Ž¿ÿ~~ó‰O`YVQ”I$«PG?èýЉ@dÛv·ýz>ý½Nÿ¥S€itß5‘HN§CA%™L‹Åhii Sˆ™¦FÖŠU:™®P[[Ûcú²H$¶IG´€w´À¢ß ôy ‚ Œ¾ÑB˜vô*½½Œ®1£#Éõ?£'Ïóð}Ÿ BqÇÍÎÕï+™L†“O>™'žxbXÎóhG"9(/XÐ|Á”’–u'Œ„‘ä¨T<vízeÔ™ö—õXÄ(ùóCÉô+;Ùzþ‹@UÉËØ ¬„†Þí?Ö˜&<æÁ™qåwN’X]“ëCØ6D"ùb» ®ÓT¿µcÖ÷uÁ:)xu$xxLÇàø6ð΃IL"Ey˜LŠC» ò¡õg]ÔÞ _ »k=uQ6,§Å%Îx(ÑF+1”Ó3‘ûmæÖ™E™—a,ÔÅ#oHÙܺ´ðC~Ú[O~«Z§ž/I>DLûÖ£äòçQ\È»L´ÅÆÜá󀪂¢ˆ5QØ•;þÛ·Ÿ8ÒÍøø}t6 á‚yA÷ût&“úK&•(ýꫯòØctvŽåÁ?ÂòåJÑáÿ:-‚ |ß§©©‰ÚÚZ’Éd˜v@“H$ÂÔ :꣩©‰L&ÃÂ…¸çÑ}€Jw ýR¤_Î _$Óétø"”N§‹F·566½DêÑOÙl¶ÇçÂçƒeYD£Q‰¶m‡óë"£:ÝA!úÅW½\ª£»uëñ|ík*7°5¨_^ G êßžŠŽÜ t¤},Ñ&uHÖóÁn#×£ìs ’ÉÛd}½Sô€Gü¹ý"£ëF–F~è¢ö]‰¥žzâÄ» 466.n‘ÒH#1bxxdÈ``PC -´PO=>>4b`É̈¡…bĺ0.nÅ¢"Dˆ/“||2dððŠêÉ‚ ŒFºòý|jo=१ÈÈG÷&~œ{î¹ÌnoÇmiéQ.ôÔÓS -Ý/Ö)j ×WXSEϨý¹0Y×6& <Ï Sí&“ÉÐa^¸~ÝgÖiÈ@‰2ÿŸ½w“¤,ý¿\—å²C- à2îZÃ}רԈÉ("¡& zDIªWãÈ‘î$'Šþ²Iw. '9vÿØó3Fs鯣¹°Ó9&jDLwŒ76Hºð’] .Sò 0ÅÈr¯ßÕOUuO÷LOÏôtÏìóÏ|fº«ê­·Þª§Þ÷}ž÷yÇq"£¤qL "–eE‹š<Ï#—Ë‘Ïç#q û&×jš&•J…T*cÅb12º‰Ç»Ìòù<»wïæÛßþv¿ƒÃ!¤¹Ý¡ãÅIãÖJ¸¡¬|:6¨LMM±}ûö†ïn½õVvîÜÙðݶmÛú}M@¸aÿþïaoêwU:ÂlúÛ+ œöŒSöîå>Ó„'žèù¹Äq@H§áqn±âèKBPïû 7õeá1ÕjøÜH|Õj5öhiµ¢CYg`1}° Öï¹ØÚï*uNžÐ°ÐJ/)E³ðšÄ–¼äwÍ‹[“ù(Ä%Yf‰Ðða7î—•4ô¤õ…Ø‚êA¹d4(Ÿü­“á3„— ±Á¥@làý®ÌÆëuXŽ—H$#´“›r­ Ϙ`ùpË-'õ»š+—ð™*‚w>Ó`^2{·ºž¿þN-Q.§¸ðÂòàƒgãÆŽÜá“1ª-ËŠ&3¥R)ríÏçóÑ$(‰ã8Q¬hHËä¾Ã1×þ¯™¸³M1fIofWñVÞˆB̶í°s°¬è<Í“T™ü]¹eKÃ÷͡„ä <áá‡7÷5”Íf£I£KÄsFâfË*>1²4{-Ñ9 /–,`‚•l2 #ôþ”>Õ8,7l²T*Üvtg‹ÐZ<¼–J÷Ø Z¶³pZÝ/ñiuîv!Ç °°¢íâ‰bb6ÀÅ0’!CŽ\dlÉÁƦFF¨RÅÁ!K–*UR¤ðñ©P!E 'ò|±±yüggŒ±å½AŠ¢(K@ÒñÞóÂq‡D  éÕŠùŒ—_~¹š,ÄK§b@iðüt0É1ºŒ©“aÌ$N2lY²Ù/é5#cç¤Ç’,âïñºI„lÛÆ÷}2™L4?úè£yþùçû}KV Ïø&¤à‚›žåÛoZ3{'Y霸§â夥ßtdPfxx˜Ý»wGß15µ°NˉaÀ+_,¾ ¥{L“³wíêé)$DXrm‰ëÂgR04 7¡>ºJ¼’Ýl+\!ë5åZqÝÐØ÷Ãmòþ–•]2h “ªtÂ7aóæ}|ç;ûú]“…³9Ü+Ì^1Œ2ÛcÔ÷Mî_mª§I˜÷%ÛøÝ»{§¼õ8Ø*!^*±A¦Lh¬IÕ˘q¨0ñlIž×ƒ¶ùhz@+¯;MŒ½hŒø×78û ó/P|WlÌ(•àüóg¸ì²ÿdß¾µQö³Î2ñýrï½ðç^iˆ›,F1´d³Ù(C6ž}ãr9,× Ç\}5“ðP*ñ‘ÿwþúœsøÅffâSB¹¾ÜåûR)|ñ›føR÷¼Ðªž¤Z g൘&V¹Ìg?ñ‰ÐÅÂucYIy¹\è†Q­òàš5¼ìÿþ_øìgÃ}FF0§±n¾ž#ŸOLs@™™™Ù·£²¡P(099Tòù|º@Œ2žç‘Íf#/œ¥HÆ)·¥RITZé§m þÉö%¾ 8Š¿ æË¡º®øÈªu’^2Ô ²:¨Piy/%ŸJ3UªL01+<—xš4#9\&˜À¢F­á<ÕúÍxx”)“!ƒ…åf‘sÿéÆ?…ÇûÝrŠ¢(Ý!#É\þÏÿyŠrù«‘r\”áÊ`!^C ]ĚܿÓc%Œ›„ûjöV*—ËѰV69^<`ôyꞯׇž|ÿO×Wc%Ú¹!O½l•夣ÙìÖ­[Ùºu­&¦¦žâe/û&ðá~Wå dãž=Ü~ûí¼½Ç‰ÜMbÝ­ JŸ;Íp{ŽÐ¨" õ%ª‘‘Žý— á€+ŸWßF¨/kî“ËeI ëÔ”…qçOpúé¯ëw5“VÏ“¸•u¢WƒHs™É1ž ~üBŽý걡wŠPavÜAÑ㈠9„ƃ8‰ävIÆ-¬ÖÏ+ùf §Æ/QÕäe›&œzênà²Þ|5“l(üxçAþáõ¯Ÿ!“ÉÔÃm…»|ò'øò—wGÉ×E‰_­VÃxµl³î¢oÊË4— _®†ºA˜fh¤(Ãm¾¾Š€aÀoüçŒC:ÍÞ·¾•ééižþy>uë6þŸk¿×_^ع\8$>™oêõm0ªHlªL&:öÊ-[àío;B!,Cù¹ßýÍßä¢mÛÂÇ^°ŠÒ½öTif¡†1ƒ,Ù–¹N²´WK•VÇØØ˜˜”(‘'r<<2df_Ò¤ùÝS~W *Ë„å¶1–k%Š¢x^8„¼ýö?Œ<{—+‰ÒI’åÀ²¬(ŒYɵ2߸Ùqœ¶žNJg<é«,øÁóß®˜½ƒã4L>Ĉ¥(ƒÀ¡ý®@¯¸ùæÇ8öØ û]ƒ–Ÿé%ŒDø’^!zÝ$‰E^»¢cNæéö,%êQê…ÈBcÃ`‡“²«Õب¢t†‹ËƒõÖß·o-Ï<³¶ßUZYtj¸“$öI&hÆSã±{WòíWœ‹%2Ø/™óESÊåØý/<(4ZäóáË·\ކV&&âÁ´mC@±HpñŸ®Ë0_ýêø\¾¼ÇÇÃã““3ÛŽ÷±¬ÆÄYB>þʢÈmI¤#P:–cš\ñGO …Ù‰C #Ü71±/‹¬­W{fæ σÑѰ=êç²m›?ز%4øˆE‹zîÏctýzlÛŽB%HbQÉÁ"÷©ç¤ ß §@upŽ´+˜O@yÞ¹^C"ÌÅ@äPq ähY¿¾=Gœó+GøÞav {Ù·šøÎ«ïï·9ÇÓs…µô…‹$™ã¨úO”-ÑÆ“QlÏzÜð7[ÿi(Ï‹ -ÑjNŸ¨¿^ÿÄz:ê¡Þ¶ÕAJ•*^ýƹ¸Œ2Š‹Ëxâ§L™QFa„ Fòãøødê?nÓ€ÎÅ%Wÿqg öeõ#]L©¿$ÏE2Q»2˜$Ãwõ %µ¼ü?ó'- i££áß|>šJ^LEoaûöíÌÌÌpýõ׳}ûvn¼ñƆíÃÃÃÑÊÔ~³gÏ:^õªÃ–í|‹µ‘JþéþwKƒ$[š_§²èWÝ®èteþ/ííi36ÄXVlT‘EÈŽëàŸCPÏã›6á|à˜¾Oõ©§0O8SbE¹nìJh±ìˆÑC 4Ú¬VKNºŽ=öØÐð"e‹QdöA¡‡ˆA²ÙÙYÒ¥NòײBÃF² !Ù×™fX‡$‰I@ÃwMض͚àgÙbÝÎùçÿ:X—J…1&Ëe ÛæÂO:Ô¸Š²÷¯]Ëî_ú%Î#Tˆ‘Èu]²ÙlŽí?¿øEn¹åŽ?ï¼yûé\.G:^øjÁz±æY­½9K%xï{Ÿ^X™½0¨ø„¯ëá-2ä;—ð].$“؈b{Öûïf0Nã‰úÿ¡ô;ý7ðÆÁ8J_§î-¹ S?‡ô'R1¶Hþ1ÉLýX ™O\L²OÆ>ʧ1÷Y.¬»scÌöš,Ç…•|%B¯ÌB|í¡û#qŽ)'Q'û=YíÓœdµ\/â r¹ÄwÉ@¹úqéDúy$$gFdµõë¨Y0!vÆŽî±Y1c#Œ¸rÀ\”¿ˆã6·4ž‚‹‹A•* ‘‡…i+SÆÆÆÃ£@týG¾C „Æ0Ÿ% "£Y©þ#¹©(ßðWQV+òt‡C;7Zì£(Êà±! Ö—àðÃÛ¨¦}¿ažV.——MϨ(óѱAåþÏÿÉW¿úÕ†‡wllŒë¯¿ž;vpë­·òÉO~²£²¦¦¦¢ü+ccc-·IÞ–n¹ôÒoðâ‹{—­!;íµ˜"A™Ÿ4­ÔWZ4f–ð>eˆõ2·÷}8͆}>ìôaêôl;V•JuÏ3^¤¼Ú˜K6“Û»•Ïoý7øÁŸ?ÉUWu©HßmhoÍóÂfÛ¡òÓqoÔð·Ÿ×6YÝJ¥ÆXo²ª¾jHòDÊU ñ#B2ÜOµ*k-+ÜnÛ³-bxn¶þ5_‹„&ůpäú“×V_ß 5f´¶ZX‰¿¢L@ÒX‰rG4yá /CÏ_|'œppnoO²LôZ>#| ®—…½{÷òôÓoetû£¯2ôÁ ëÖapÕ—^ u¢• æûßOyíZÌû7ʯ=lØ@eh(,IJðˆu’ £<÷ Pàû¾ÏKÿñœGglj‡‰ìÛɠܶy¼_„J…3.»Œ×~á ýÎwb§Ó” ƒó3¼µkñôÓÞ?§=f9ûN1\ˆ‡ „ž$*”)“!³(ï32¶$½M,¬(NsX;»þ#¸¸¤HEÛJu·©2å†cË”#/¹¾%räppÈ’u¾*U,,J”"ïÁË M6vT¶ÔKÊ·°Ê•ýÅ“ÖÃ[¼ÑYé;½”ÏrYÖÂT£|sвvOˆ^m%$åó>fƒ  W¤ƒÀ¶ƒÀq‚À²‚ ŸË¨T‚ ÿ¿á†¢çv¥2ŸlÁÂåó¶Ûn n¸á† ‚ÀŒÀ‚À^™La~Ù,ƒÀ4ÆnÅôtx&'ÃϵZG×™ ²A%¨„e‹íË–r{A»ºNOA6»°r¤¬J%|Pm»qŸt:~P{A1…h1L±&›=A»ÛZ¬ooC¾^\´î#V½ÏævIéP6‚ |áã("899d³ÙàÔ÷½/8ê駃ãÿâ/‚ó<°ƒð}:(k¢þwúºë‚Ê7AÞJ³þתŸÂ âGȨoï¦}aݺàÃ}j\ÿ̦M7…‚üͺ‹Z¿+ÒéöïÅLLL6DX­V €`ß•Woß°!¸px8øµ3Îwžœ ߉÷Ÿaúš“É÷b‡ïÈl¶ý«6ÙG¬dz1¶ýåÿñËØsî3íÁôƒPøšºŽÊCAà|%Ü”<Ìç_¯A-Š¿N-XÐe¿f¢êÓAS¹-È7²ÿÌê+¦ý°¬i¿éû ì=A½;Ìã1›„﫾ßdýWº §öÃAPùQS[áûEê:Aþé°²7ùPXÆï±Jâ|ÅDòAØÏAíׂÀ|&jûÃïk‰}¥Œ‰úßâ£A`MAöá9fÝÃúù&ëÍc×ͧƒ ò‰ HÿýìkI×Û SßßùaP?¯½§±ì@ö©×/]ÿ?Aú»APüDýþ$ÚÕ ‚à²o~SǶ-˜ë½• ²ÁD0Tê?­¨W;e"êqÆd⇀ dƒÉ`2(Å T‚é`:˜&30ƒ|œÀ ìÀ&‚‰ÀŒ äƒl ¬À ÒA:(Å`:˜¬À œÀ‰Ê´ê?ÁDòYÿÉùèûl>gƒl`v®¿0¤ 'p¢c“?ÙúO:HNà“ÁdÒA6ÈF`“-ÞPÓÁtP *8-ïÓtÈ&*A%¨µ¨Û¶o—J¾ód˜bYV°”T‚Y]®² )‹°`}¢ŽmÛÓüÞ½Ì9ÿ;¾ñ–o—üÛ÷‚¤rš h˜oäóù "}¢4Ñ ½m×¾Ü[·neff¦á»ááaöïßßö˜©©)ÆÆÆ¼\.½ôRöïßÏÎ;Š\É6oÞÌæÍ›Ù¹sç‚­ábnÓ|ݲ§ÔÃde`GuÐÕ’ÞAò¯bÂÝ|¾¾¢±Ù‰@Bðçrpâ‰ý¾¢Å3—l‹–O 'CLÆæiƒd»®ÕÚ»IÈ!•jôD™Jeî²ÛmËåZ‡ðZí¼s$Iu2|X§å´«SóŠuˆ½|–"–ðR,Ú1©Ç!LbÎy. ³~å7“_~Ë[xÓ;ÞÁ1û·üU&Ãø¿HúÍo¦:4Ô°>UŒ},Z—j:1åïO–8]„*’^À­o/¿¯çâ°¯5#7²8å”Søã§~Ÿ÷´zW8N¼ì²,Ë e¡îu"Þ§|ö³<=>ÎÅÏ=Çù33T«UlÛæ‰ñqŽ/—£ýßvî¹|î¶ÛøãsΡ\.“ÍfÃóË;wžP`–µ ˆg+’^ŒmÛøØ¼ÉÓs·;ö¿€í‚u6»¼—À97|…ZëCùj¸S¤K`ø\çך~M£woÒó·Ùó ¿ÉÑ8&Ÿ½¿A~Ê& ¿Ï'QŒ\t î«BûœÆòlÂnEÊÈ® C‚eÞ†ýrÎ Ï'©O&[Ô) pT߆2³Î‰š’±Ó¥‘¨cúD0÷AfœÝÀ…³ËM¾£{{äÞ NÓ”Êfv˜[p×ù}(œÎÚÙeË:ÎrýVÈõžÜ ÎÆ¸<“ð]}鯰wùB'÷‚åè;Ÿ*Õ(wI;¬%ž-:]ºö&½;òä£ð^I'ò¸I“ŽˆØÓð±, Ìâ¼ÙÍHάA×íoܸ‡SO=‡—^z©õ 4蚦ALÖϦiò¦þÇO>™Çêïgr’ì/ý6ày¾ûn¾É%\ùâ‹d$ÏJ.Ç¿œ§®oÇŽìØ±ƒ3Ï<³ßM¾hz1¶ùþ ÜüÖìm%ÀŸ†ê(äÿåÙö½`< •)âU#sQœ—fÌŠmɇ߿úÆÏ<ñÙé0‡K§€ñDhpZÈ;,s Ø3³Ëjw‰ö©õwϺ"ç((¼¦uê²Vu²6Bõö𘹚:i‚zxµ+gó¿®¾š‡çwxòð•C¥×cÛmÛ¶áâFF‡•šè}®\)-â¹6+ÿeÉÓªì4éYÛ$ß‹üŸDæïÍÆ”æ}“s{ù>ù]Ž\tü$“äÈP«'f²°È‘‹>(4}šI‘"C& Uããc$~܆j¼ÝÂ"Mš©ÈP#F—QF£ãÅÀãà'OBdpÚýÐnþàåÀÈØHž†å£WcÛn¸—^ýNN<ñe”Ëåž(ÆU­«´BǶém·mÛÖ`¨9ì/`ýþõwäSñ›7“a²\†ééh¿ƒÝÈ¥,ŽíÛ·sË-K¯·=´“.½ôRvïÞÍ­·ÞÚvŸR©Äºuë:®à­·ÞÊW\ÁØØ[·nméÙÒIr£76S Ô5ì;ë(Qb„lìh剢4OwäÅ-úÉ Zuà‘ú¼Á#Ö÷º„Š¢#:—3~í×ú}IKJ³l]Ëçe—]ƶmÛ0Ÿ‚ê­¡’nÎÄ€–Õ^ × I&¿x^oÏ%•^bYqbûVd2ará¤ß¿KR(4~–<3'Î^(ãÄYw%€¿Uÿß!NlŸ©ï'Zwˆ ,Õúo9\-sÓM7qòÉ'÷¶=—™¥’Ï“O>™›nº)*#ZñX¿ÉG½\.sÄÏþlè=²n™œœz*öùç/ùõUW{OÖÿæ o³ä^ñ Wݘ=¡½¹¾mœ07Kó¯l;„ð‘)Õÿ¯—UMìëÖ·eˆs{Sÿ>Wÿ\%Îë,Çw™¶>âĺìqÄ‹,)&ßä&Çqxõ«_ͦŸÿyr¹¹\×u©ÖßAžçQu^së­• Ïÿä'¡gÊÄD£ÛI©z­,àݵuëV¶mÛÆ‰«ÁÅ3ÁRmÏ>òl¾ö[_›õ½<‹þBåä0—FúÈå³ { Q.•Œ¼þBúœÐx±ì àlZX½¼ÁX`ûZ€õs Ûßynv¸sôÝVý%µ•¾<*q®$€ßøßàî»oÅT’ôjl+ùGDù}03—÷M»mfý§™4iœ© ŒY÷@¼oòä10(Ö‡I&#ƒˆì׎"ÅȸQ£ÆÔ¨Q¡ÂL6ýÔ¨Eå§HQ¡BÓLS£Fž2À ÍÚwjjj–ÀÍGµþ®¹þiŠÜÔ0Pa„"EL̆¤w¸„ÚnûÛ*ð`í’Üe™‘Wµ¬~–°àÖ7z$‘XágÂó*®dºÃ³ .íd–F>àñ§_Â<³Eù¤rn!Æ•ûËSf|¼{Ï–N1Í…_ÿB‘Ðb*Bm;<¯xÆXV¬M¥Â}›ò%÷•ϲ ¾\7^· )–ÉÄZúäv× 3§ßòÁòÂÏ‡Ï Ü&n " õ¤Å¸õÏËos½mÊå¤×ò™ ¡AÌBØœ¯}ñE½øbÎyúiÞ´~}´4¡W~ZÍ–\Q-Oa–ðÖÖ·eg€=ÀCÔ½ ‰ɧ×%´ËÕínLÖÿ__ßOö%^ž¡1 ™xÎT‰Ç‘D=G‰ õ±NŒ.Éë“UíÉÇöùïǾ‹×²ç¸ä½é~ܶm(8éÝïÆ¶mªÕ*†aP­V#ÅíôñÇGûÿpjªu(FÓ eÛ²æôžq]·'¡7^mÅgÙÇ ý›P_P @úh°îcémœ^½ßƒœ„‰KRm2ªÉ gŽ~-S7؆A6› ÿ_üâIýíßâyŽãDe¥ÓiJ¥¾ïc¦iây¶mcY™Lß÷£ï à ŸÏãºnTjµJ¡P ŸÏcYår™\.‡mÛQY¶mS*•¢ ¼<¿f>ÏÆ={¹ôÒ†ö0MÛ¶Éd2d³Ù¨-LÓ¤’ÏS.—©V«˜¦.Óé4Åb‘\}ƒÈ_:fÂq(  …èú}ßǶíYFR€oûEŠO_NꪞçE‰[}ß'Nã8£££X–…뺤Óiòù<Ÿ™™!õ4”_­V9ûì³yùïý^ï¨e¢—}§„ùšd!g•ŽiåÓoš6ó…pKzÍdɶ45—?]ŸS¦IGÆ á9³Ê,½^hÙé…|ºÀÃ.üô§R©T–|Üa/²Q”ÕL¯Ç¶Ïß?ŠûŠXÇgpïÛêvŠÅ0D{ ù¥ "/=Ú¶mCCC”J%n¼±1Vùðð07ÝtSGÞ)W]u[¶l™åU²yófvìØÑðÝþýû;²v&ùßâ3ÏÿˆŽ{¡aUK–,6vÃÕÇc½ÎäáE°JVxß%^] ԸȪiÙ±ü3ÀßbŒ^á+Û"×Z!œÙ‹’â°;+ôÚóÄ+"mâð¢,ó•a¢Fˆ"\ð¯ß†ãÖ "íd'Ÿ..€µÓpº±£y`›J…Џ‰.'N¦Ù˜O¥WÈj‰^³œçH&ÉÔi†Žb14”ÆlƒU: ££¡rÂcDÉšNÇ-™Lã½I§Ã2=/ôjÉçÃó–ËðábhD¹¼·¹ðY`Ø„lÈÚ¡Ðm_××àûf¨í® «XBE3-÷]Ø´vSïÛsè•| ‘R  …÷ÂaNØŒÏ}úÓlÚ´‰ÑÑQòžG~Ü­Å‘&ö|xS}»ôü­ÂøHhÇQb¯Ät›}Ó‰¿âǪUƒVÇgÂæ¤@Øm&[NS|2ÒG•Ÿ…2±ñ§£u\• ÃÀÄ…222)nS©Ô,E¸iš ý`„(Õçx»®K.—£R©ôÞÓ¯ôzl+ :Ì— øZ.²hLcƒÏ\×Væóy …B´M”óâÊå2†aDÏ „ùy|ߟ¥¼r]7Rì‹AÁ÷ý†}ÇÁu]ÆÇDZm›t:Íß~úÓäóyªÕ*år9ú||Çq¢gU =Õj•R©C¤üL&ÃøøxTß÷##E¹¾ —Ë111i2™Ld0’:Šåä$—Éðõ‰‰†kM¥Rd2&&&H¥RäóyÒé4™L×u) ¤Ói|ßåg||Ó41M“B¡@­Vc||˲(•JLNNFלÍf‰ÚUŒAr]ÙO…©Z­ÖpFFF(—Ë‹ÅH¦GGGÉd28Žãº.©TЉ‰ Þýîww/D/ûÎ*Õ®s˜(â³²õŸÕL/äÓ¶Úð·_þ–õž~_¢²BIŽyVz=¶}ø6Àø‡Ñ û•Óà­oméñ. >eÐX/÷5×\Ã5×\ÃÎ;£ï†††:¶FîØ±ƒ™™.½ôÒ†2†‡‡‹’±{÷n¦¦¦xË[Þ²  ú?âô×ÝÇ)w\g4n³ê?%JL¾s’Òï”ÈmÈáîQ»·†á¡$O$K¸Ð%6¸„KQ!6¬8ÀqÄ‹ù ’ ]´"RN3²òºY2[#4n¸„Y$¥®Ebk€h@ ‰:'Ëcï|ã<‰·â×ëìÔÿŠu¡Dì>™ 3y¼ÓÁyú@r¸*·MdÒ¼+㤙OváÈ¿5ÿí_è÷%,йds±òéãs<&§ý<}Än,ÓŒ•ñâ!±åšaôÞsZ{j¬T’×áºáÀEBÙvî«ÝÀÅqÂ2,+Ü7©@“-ž–—4ª$3T—Jñù‹ÅøûÛêÞ.¥ ð†z]Ë x b’™!|'’ø®XðÓ{ÚïÖ^4½”ÏY”àî7…Ü<Â3ÿüÏ\ºs'Ÿxï{ÃçdrpVâJ¨pP~ÆŽËÜj°fIOÓ;]ë(9aZå°hôx‘.ÕËŒð³OÝGùè Q·nw½±·Kr݇¬s®=Ggù’ضa‘b¹Ù£DV¶—J%²Ùl£â¼ÝsQ7žö{¿‡+*—Ãﯼr5L–clëÝù;Á~’ð†w±þ T*Ežžæ2³m;ºÏâ!R­V#ãZ±þîÅÂÈÈžç‘Ï磉­GÄ(Ñ’a||<ò(‘gH¼4Êå2Ùl62‚ˆ±¦P+iY–eEy€,ËŠÎßÐ>žG&“Áó<&šgȱŽãD^#òŒ—ËåÈ’|žºwH¥iu¤çyxŸþ4ÇvØ,ÃQ:Æ0 lÛ¦V«5x®Hÿæ|FÒÞr=ɺ–J¥cG²n¾ï311ÑPǤ×N3R·¤´V«1::yùHûJŽ¥ðä“O.üA zÝwV©®Ø¼)ŠÒoz)Ÿß,Ã}÷íŸw?EiÇÁž¯c9ƶOÕ•›~íÌ&üñÃĺ„ú=ñ¢ã8ý}Q®‚ãv›ÈejjŠ©©)®¾úê†ï¯¹æ¶mÛÆ¶mÛ¸öÚkÙ²e »víbÛ¶m¬[·nAç¸Ýû ¿¸ï\Ž8ÐBÁí‚c9ø÷úOd·gÉúYrå¥ß,‘õ²ñ$5©m)k5’Z–q<’cëûˆh™Ø  ZAb…ˆ "ÙĹªõÏ’S _ÿ[ª/ÛKÄ|mBƒN…z¬*b+€Ô_41ùú_YÚ*ÿ7k_|â|bL*&®Í!^,sNñbI×÷I¯$/$Ú´À쥵JÒqI§Â¯NzÝIýnéEÓkùŒ’¨ÖPw ÎôaϺu¼²Vã·ƒ ”Õåð[ ÒÝ=Kçè< µ`;©vúÚ·‰»ïveNG¦Ëçüsìù«—xöÂc“r}Ù4†“œ/Uâ(Pã„]±¬ïè¨MêJW R 7#¡‰2™ •J¥u<ãj•gþùŸùâ¿È×®eÃÛßÎþýûcWýlÆÇúÿXà]Lz>¶õÀÝÆÀæ´êù¾)×!TÒ‹ç‡xX–Åèèh´=y¯“Œf’áµÃ0"C\Ëê×=Hš–eEžÉïLÓ$•JµÌÒî<2Ánõ<š¦†šŸé¤á&‰-Ú]+¤}“õ‘²«Õj˰3Écš¯³]ìÿ¤1)ù¿iš‘q¨™v÷S j­¶_tÑE+Þ Òë¾³Jµ!‡¢(ÓKù¼çŽ9眧û}‰Š²bY½í><p×ñÒ§çío\ gœk×¶ŒÖ!aUeÐXÖlƒ"|íØºu+cccLMME«ʳÞöÞ÷4ø@ 'ïà˜Nhò>>Mæ-œ»F­ÑÐ¥>ñqq©ä+”)“#G‘b¼I 2G”S:á¹" ˆãÿ;Ä{™ˆ³ŠÁ#KÓD *¢›¬Ô÷KÆßì’yb£Npâ]&T6ŽÓºLfýÜâa#†Ií'®Ù"6Ô˜õ²l⥲ÒFãÄ«ÉåúÄp$AHÍúvÑ%µE%®ýZBd44ê0ŠÔuÑgÜlè_—€ùd'Ÿ§üyäŽûÑb%ùRä iRÒôŒ^ç6Yn$ï‰( l;v±]¬'Ž´•x±´Ã0fd’Ê ¤¡­•á¦R ½|&Š4y•ï-c›öˆ^˧†üÊ÷¯ð“ð…4üËŸü îø8ÿrÊ)\ÙªýqÂ|‚ÐQ´WHÈ…š~;úË´ÁžY³†çÙÇ+8¹í5'ÕÆ¡ý0ù†’xÕú÷n½îb»c3óÅÏçóѪùR©D.—‹BFI.ŠzA<÷ë¿Îëöï篎;Ž–Jì8ãŒÈ;ÁªAOûµ_ C>®pz:¶­¿¼kÀø‡úwmn“ïûŒãyéú;\òv¤Óéè;A”öé¼ï%ÇÇBhg„°mÓ4g=w†aD4 !–¬ãæMäUi®s¾Í;¯\./¨nÒf 9Ʋ,r¹\Û:´b.£Ò|ukužŸù™Ÿáå/ù‚ÚsÐèuß9_>ŒåÀóÂu+âœ\‡«.º¢²Šè•|úÀË·<ÌϽ:s¶)Êr°z[€Çüó9í¬9û§?…Í›áˆ#f-b- m†(J¿YVƒJ',F «T9ÚßÀž=LóçÃÐ\úJôÉ8þo½Gæ Š£°`‚‹‹ƒC† >>yò˜&662܉G®>ËÍšYŒš;$s.ÄI•“ÜeI©x€ˆGK:qLZæ=àŒ#W~¸_Et=ï°à¬=?æ„3¶¶í\Ç9èÇ)Êà2p•Åàãó’÷Z^zé?0ÝB¼¤4é‘‘¢å’QIT/ÉóuUC† ný§H1J*W¢„cð8<&.ãŒS3j±–Dæ‹¡A!Klàc«x»8„Zޤ¹„[âAÒŒÅlÏêåWë,š;qÌ$Ú”-õÎG’óNÉó"qH¤Žbô)jÄ-Dê#¡Åd¬)0Ë´hºymeò´·ßþ3ÀËS‘̾pÜC?â¨sÏí}x®Çó¼(°Äj/‹³”'¹\˲b¿§R)*•J´‚UbÌË$KVÏ&þÊêØ¶Ê™•ì}#Ú…dNÓ +›=Nÿûï&OÞpõ9ûÔ š¯KWñDÏ# á»ír’ùæbè°Ã¸ïÀ¹wÃ~øÛÎ\çeF+ñ7EØ…§>“í.ñp@¢|æ‰#‰ÎE±XŒ’D–J¥(|’çyüPüýßÇ,Èård³Ùè½'J§þÕ_±?—Y™MùUP=*Ç·ÞžËå(—Ë‘2°yÂ9ßt¡Ô…9ä­”ˆóg¡ŠÃå0ÂtsýÝ'aÔR·n¯w+î›W¾år¹(Q¬$Ó•UÜét:šÊ>’x-9ñ“ £išLNNây###‹Å(ÉpÒ`R*•(—ËLNNFÛ%¾ºhdâ–Lb+õn5X,+æ8¡AEøº%vŸz7¯íw˳À­Û»³@.ÇkwìÀZ.Ö6ð­”Ûìb>Q—•¤Gr'“%¦R©h…kÒ+#“ÉD+hÅZ.—£Y¾ïóìó·³îÕ/Á!¯¦P(D ­“yäý‘¬›È¸È¬¼á’y\Ò‰Ï4GØ}ˆhåÿä:ŠV$•½’‹!Nãû~Twñ‚H§ÓT«Õ9g+³)] ëfçí©V«Ñó$ÉÉoÿ»¿ã·eiz:jm“žˆÕj¼½n;ýÿþ_ µªµÚì ¸n¨E­/)×a‡qüyç…ïÙdÈȨ¥ð‰gsÃÃÇËàE)¹³²Ù8ì›ãDËÚMÓä-ßüfœ×KÈåÂ}ÊåY1¶mÛfü_ÿuvn­äõ›f¬Á.—)ÚvXYº/Ç4ÇM’º×ûÙC‡ï‡m.ñRÝÃ=ŽÎ×àéW*…õwœð<ù|¼\¿Zr‹ýàÿ±±þâŠ.éËñ¼ð»j å#R©°Üt:Ü/“‰Ýòù8'M.–‘χ׹\¡TW0^Gû‰¢\›U•¾Fú“ä¸Rú™]Êer™hßðÝ›©?þf”먣næ”SÎá÷ÿR>ðOpÔQøÈGÊ‘1óƒ4ù»¿»‡~-_þòû¸çžOqä‘?åÄOäcÛÎÚµŸç]ï:Œ©©·ð«¿z££?flìs¸.8Π[Ü¿ò+¿ÁsÏÝÄh'Æ–oàºëR|ÿû‡ñOÿô††6ð}ŸsÎùO.¸àkü÷ÿ~EèxlŒëžA¹¼ˆ KâÁã8yÀÅ0¬ÈXda[›¦Ç®]køÔ§>ʼn'žH>_«{ääø»¿»+®ØÍ7¿ùM®¼ò¬Ys® ÿí¿=Ã=÷ÜÂðð§yòÉ'ù›¿¹…‰‰ þ×ÿz¿ôK“¬YsNäd±ì}ïÛËèèÝØv•{ï}-×_ÿeÞö¶£êù­ê}´¿’‹Å<®~'¯4{ʈ—èûÞ÷¾~‹ÀÀr .š+b£ 4ú õž3ž‡ÃίÚì£Þ)Ê ³ª *֨Ǒ^=ÜË2Cc‰;+N®‡…s[S®ÿT¨Ä«˜Ú bo•^ã/¾ˆŽðèîÈ1)BOìUS$ÔøUµ>)bÃYP[”"4\ɵŽj†DSdgî0ŠSâ« ÿõ_Ç26¶LíºÂðñY‹É§î€;xqIËN®XH®*K*ìJ¥®ëb?ù~ÂOïÿ)œGtŒ¬M*Jee˜cš“öʶR©­^KÖEŒ%¶mGF©—”ßœ8v||Q|Ê ½l6K¡PÀ²¬(IõŠQ~š&LNÆŠ°·åYÿõ[ú]«±Ö¼˜x¥¿°BßEb§ÅNH EÖK¥Rº*©ü/2ÙWò ”ËeŠÅ"Õj52fø¾ÏèèhƒÜ'½2lj "Û†aD9IJ¥/]ðø÷ŸÏ)¯œŽÞ’»DöO*ÖÄ+õÌf³”J%,Ë"“ÉP«Õ¢¡Erˆáª»$TX†°›”´gv½MüÏÿäšãçùáá9û@i#QìÉ{%NG†yW¶Kœ­ÌÆÌ&G¥\.G©TŠ<Þ53Ã/NM±þ߈—Á'û,QÖ×ïÔ§mÞ ¿ñûz^økÛñ»Ô÷Á¶ÙèydZ%e/—cïÀ&CÇ•;wòµ?ú£X» ¡¡Gb™f¨ðOx±üÚa‡ñ²Ãkþa||¶W¥ïã˜fxݵZ¸EªÕð¼™L£¡@b¥ÓáïèhlPI¥Â}ÃåûáçDH­‘ÿ8.§Pˆ¶—;>iÌr”XV¸O.¼|?<¿ãD†¥á¤"G ¥RX/ËŠ5²™ºâ:›ÅtÝØµ~}|mbHsÝØ"ªN=ù†ë6¶2'^œS³ ±A–JqdÓ„}mvYž-¾Ù ]ÒétäÁÐiè8éÛ¤_hFÊ9úhpœa±ÇR¦®Šçy¼÷½ÓÀ{"câûÞ÷m®¿~+Ç$Æç­¯ÏqÀu ›MϲÁ^wÝÚ–õ7 ƒ‡~ð¦†ï¥ åu"8,š=Þétl£ô}³~/òÑk¡\ÛÎS.ÃQGÁ 7\‰gÈQÀõ{²žññ÷R.‡¯ÌBáÒéø•’ av×]p݇±¬ÐP2>_þ2xžA±ï'õ“Pj"¾b\Éå ŠEƒT*~Eæó&…<öØ-Åc¼*9̓Ÿ? Öïª(Š2/Áó7ÃËN˜Äò<ª- 'É…Š2+œ«®º*úß ¬àØcŸ ®»öº È.Mù• Ø83k›8XAø¾ƒl ÌÀ òõŸÂ ‚ ØãsL×¥¶ˆ2&ëeëu¶ëßQÿ;A%‚|Ff}_ç•m•úçlýw²¾دK®½ösÁ­·~·Ç ºò¸í¶Û‚n¸!ÈÙàŒ ØëƒÀ¶íÅA­V ²Ùl`šfÍfƒ‰‰‰À¶í`bb"¨T*išA­V Ç lÛ¦§§ƒb±\ò½K‚WýÍ«Çq¢ã¥ Ó4ƒt:X–Ôjµ R©µZ-ÈçóeYÑy+•JN§Ó4ƒb±d³Ù V«µZ-˜œœŒêhYVN§;¾¦J¥T*•Ym4==T*• ŸŸÿ!œœ ¦§§ƒ ‚|>d³Ùès²¼ÉÉÉ V«EוÍfƒb±ý_©T‚b±äóùÀqœ NGm$çëÎfã—m­V ¦§§g³oT‚àŽMwô»I²ïLé òP%˜þÇ HOÁ…Ï=|gíÚ~WqAdƒlðáþpÏç£ç;f?ÛŽã†aDr_,ƒt:½jµZP,£g]Ês'’óJ%ìPDƒȶù÷CRÖ‚ Þû®Ï‡÷|pÔ;oŸWޤþÉ:Êûirr2˜œœŒ®ÓqÇ0ù|>xÍ­·• ìå*¦ƒ¸‹ÍApÚÎÁÚ‚áçž :›Qû·Â¶í V«E}„2‘Oë{ßONNï=çœàÑ+®høþáW½*xíÐÐÂO”ÍAó3[«ã´?ƶƒ Õ³é8Aè#êýLK*•ð|­Îaš³¿Ÿžn_7ÛŽÏŸ¬G6†1û:§§Ãc„t:&&âcäÿ¦sÚ¶<³aC\ÿv×'×5=î·Ð~±R ‚ú»+˜˜hüôt¼-›i>g­okGâ^Üpà Ám·Ý¶°:È{+¤ƒJ0û}_,†D+Qhfrr2ê&&&¢1”Ò=´{’bqá¢Ù •ÊìWP+&&Â:Õjáµ8N,¶ÙløÊªÕÇpJÌUW]T*A°iÓÍ=•¥¥™Í*«Û¶§ù½µéi;ØðÖ ¸è7*AA塇dkzz:°m{Ö\k>²A¶eÿ¬(½Û®*ŸW¾ršÓï;Î^š2-,ªT™`öjÊ<ùÆp^ullF!M ‹2åNNÕ›6I¸ —J¥p…{0ÃUOÒ$¹2]VÀÊJ¤äj¨ùr1Hè“´•ž%wÁ•'ô"÷ɧR£1Ÿ‹­'½Sj„ž-2Œz9vý{Éïbz»˜Äùkºðì<í´G8ÝÁÕÁSäO‡ïÝwߢÊÉårQè*Ó4£ââ"‰y'&&¼D \¥wÓo´L¬ÃP=Ñó.rPL†H†Ð<â…’N§£ƒí¨Õj ZQ!õl–-ñBédUbsX€V¡udE{6›V‰Kx0©‡¬‚”˜Ò¦iR­V™œœddd$ò”‘wDµZŶí¨ý%\™Ðiþˆ%Ç‚»^~¯ãuË{Þ†‡‡ýI›K ß:~ar’/èC¼añE÷ é¿òù|ôÜ¿øš±O±#¯‘IÚ-d’Ïöí†grdd„|>õ{¦iF+{[yT̵êw>ÒétK™8éÅ=ú‡/°ÙxÃxýœeä›V’K“u˜œœŒ<ã2™ †aÏçÃkw]ª¹ù|ôTœe%•šsä‘üïþ÷8ÀŸ^xaä½âv½íÞ€s½Ç¡\.óö·¿}QÏÀjÇŒ—¿+•J|ê‘G8þóŸoø>8ï<ÞÙÍIZ…ô³¬x™t«û(É šiçu$åµ’vòÒî†ÑxñI&ž€Æeòš¬ù\â}Òª-,+ôüpœYçüÜûßÏšï|'Þo®ëÆÇCo”t‡nÑ{ÁÜyÎ’í$!ÀZµ­x¢4#±‘šê¼qÏÔõº=^Cßos6;75#ý’Œ[%Ücz!Ï…2' г\MßáÐ`–¨'_/ê<Ö–6|…’qUª‘.ÇÆçþqŽ]=6qþ]qáuÛ$}ΰ¸†8‰]š8׫”]M”‘'ÔA$ÿ—g¢U"Žyã¿“&ù^óý&`\hàM{”)“%Û:Ï« þO}RN œpñ¬‡G•*æz“û0¸ßðÉmÊ…º¢|“çš ˆßV:ñ˜¯[¬ê%d!h¥þ2w¬ lâs–Æœ¹fb›^gäq#F1꤉6çŸu 5V}ßñ¦:;ÄF1X•ˆ 0âåãׯ§Tÿ•ò¤|P/#%q6ëûSßž!^Õ#mT­Ÿ£Vo+¹^q»–ó;ÄÆ \}{±^—jâ|;寕#eaQZÛ¶ãp\Äž&¥R)Z.߉§‡$ªuëI<“+Ãe5® ÊJÓ4£©Åb±AÙ$F”V (9VÊL†ùI*Ý’¡’$™÷ÄÄDš)‰(m’a“äÚä<¦i²÷”½ä³ù¨ämÛftt4*¿9D‹xàÈʰr¹Ì‡^úW®¿’ãí㣠žç±ih‡:‡†bаC´‰;ˤ¥DØi=Sfááñä׳ᙇyág_Ýùqu_&“‰žY‘å6l¬CŠP«Õ­l–pâ­’Ïç#C§¼#\× 1’ U”õ’„5›ÍFFÔd¢íæpLÝòÓ#Úïæx,,páÀw3 œº{÷²=ó…B!zç»®½ëGFF˜œœlQ'ïþäj%yç—(ááu[aì[ß‚ë¯ç¬ú§ž”oFCø21°H-¡ËårÔJˆ0Y(Ñ ™S–¹lr+†T9·ã8|ýë__‘F¯åÂ^øÑÓðÊS£ñÑ«æò´Xˆg‚ÓÄBéæ]’Ïw»G®[²~÷š…¶3tׯ-¼Fæe¡Æ+Ûn{ÌýgœÁñO>ÙE$Ã} ¡”ïû …H^êÕ¬(Êâ9,ý—¼ú^ û—Ùp0Rý¦I3Ê(†‰‡0|»àã“ʧððH“Ž )iÒäÉS¢…€ÁŒì&fT®‰‰‹Kš4%JL2I™22¡‡Ð³Í¬ÿXíb}Ù„‹<“ 8ÅÓ¥“5­Šmî[½ú „¹vë|+mþo.à Եˆ·Oó9Å´)_ #~SɲjMÇŠ÷Œ”Ùª Mvßåúït½¾%BãJ¾¾Ÿè€J-ÚC<˜Æu²Âú?õëOñ3·ÿ Êü¼ðƒ3xãÏÃŽÇwð>4ª×dx7T©Î»(^Q–‚UcP©Råáê;zÂãÐ_8téËO¸lKøñ®0 ƒõë×G«r¹¥R‰Z­…™˜WÛZ–¹¯yžr¹\´*TþNNNF† ß%Þ'\ªÕjËØîI ÈŒ5ɘ½Í,D±!FvHXYÕêøæxˆ­öKzȤD¾›˜˜ P(D.ôÉa’»"›ÍF¡N®M_K1_dÜgÃÎ |(ó!|ßçŸü—^)~3™ ×½ÿ:NýÜ©<óòg8ôòC9’#ÃŽ]–Þ&W)(sr?>Gr*ÃÇÞÆ„$‘gµX,Ι·GY8K¡Ä”Ü2Ë¢(beð“ k$ïFÏó¢ïÅ[NÞ«òþÅyµZŒ®Ý¨þìÍÆMÜÔï&XÄñùß#>OûÛ<óÆ7öä\’ÇDžÏó( ‘g„i†á('''I§Ó‘1_r¡Ì…¬"\鸮˞={xÍæÍËr¾¤Ekeу`Û6ãããщæ÷ˆDØ„úbÁéižX¿>\hhì‹¢i:ŽÃe—]¦•9xæ~xò±§±®1(|åof-LY4âÑ1ˆtó\¬¶UŒË5æiã!ÇE1vÖYýn…äñ¡Ç£ÿs¹° r¹BC¤EQ–ŸþàWùöîp‘d§þãâ2Ê(2‘·™O–,VýÇÃÃÁ‰”²­ýs‰r暘øøŒ0‚Í(£L2IŠ^ ÞÀˆêe6[^Î:îT^¸ø•Üklêè‘7 J­ ÉЀÉ\MbÌlFîaòÝX.—£UëÚ-ùþ“<9ò¾U·ß¥GÂìûcxåÙ?åYïÙž `eQÜk½¥2™  ÷8y¯&ù·m›Íûö…y–vrå8Nš3Y7Ó4#yO† MrØý÷óÁïŸc^õ*¼'ž€Bïvþïý¹iº~ÌúÕÔÏ÷~ {~r"×ÝõF<ïú¥—KËZ¾ŒÌ+ˆdŽödžûÅ–Õ ®Û˜rF¢²ù~cªÏ m;Ü&ÇÊg×mŒš–<Þ0âóÈw¾ßX®27ÓÇOcaáûa š|ž(:A2œª¢(ËÏc»6òêÍ?jk°°˜`‡QF±±»³c…¸äšì&ä…²ì8ŽC©‡½ÒÏ0ŒYÖt:y»Ù¶Ý`4cµ$oŽIžôjX ïÌ~³çdX³ksÁK¢¸•û#ý¨„œ,—ˑפ<3•D5šÁ©§ž ËdPi7i%¯‡XƒpqˆeY‘¡LB}nüïÿsßð¾≜òôÓœzî¹r啌íÛLJNéä“xÝë^Çž={úÔʃÏ;!}ÎüË·÷-½w „šõ„±Rñ–þ/JöäœV^µ†§Þå¼ã„ß™fh§©VCå|2»( }?Ü?†ññø³ÔÁqâãóù0¤’ç…ÛÅ$ç—úFx\.~N'õN§cƒ‚eÅ׿3Íð8ˆsÉ›fXoÓ®¸.¤Rqd²ÑÑ0äS¹îŸÍ†õ€°‰ #γ!×)Ÿ¥ž²Ÿë†Ûm;Ü>1™L£aE®;ôŠ?{^¸o©ŸÏuú a=ÅHãya¾Tªñ¾åó±Ó’ïodӦνŠF|?|¦$Ç×R…*U¥{}öPÒ»¬9“¹9ueQmVܨΑ"iBgI"©D,ÀÄ¢Jè<Fï ƒJ=ÎU‰#ŒDÛ<ozàõìªþμ·s¹\d(ƒŠx§H¾®vÊüƒÑì®Ï¹’ïJîm*•­ÕÂÅ¡GÍ?_{->ð~ðð<þ¿·¾•°ùW•#?Ñ£„w}bIǶûÁxÙù<üƒ"¶é¸¢p/—CeyÒÛA”ï–ÛRÄx ßF¨h·¬F»ëƈ|>>Þqb£…<¶âaš¡1@†dɲBCŠëÆ)I¤+ðýÐ@‘NÇÛ’Nj’w>ùª—c<¯1ϼ—ô4Éåb[ÒÈHø·yx/×”J¦ÓáwããqÊ1 LO‡F‰Z-¾©‡ë†Ç¤Ó¡òÂ}m;¾/ÙlxN9ÖuÃë)Ãs%¯I XÍç)Âßt:¾ni+¹/årxý““±á«Pˆë%F€ø^þòg:~î¥ì;÷lÜÃ%\Èr¹Bƒ±Yé/~âï Œñ‰RyFxsÔUÒM¬fSÝRÊçáOÎÞSör:§÷´Î"í9Â{š­ÿ/ùÌå„)AÒõ¿]äžZõ;Ÿ'O–l¤320(S¦H‘%ªTÉ¡Be–aFQzÉRëm!L×ðèßÁOÞÓr»xÂwƒ„ÞS”å oY™ºmÛ¶è»;v°}ûv¶lÙ®]»Ø¶m[·ní¼ÌÏß¿ì®ë$+g%9+åH® mÅ|"{0®(万íòÎ4¿¸MÓdbb‚ßÿõßçœ7œ½Ü-Ëb||œ Wnàÿ žÌ¬žÄ­d!ŸO‡Ã¾÷aÛžs×B¡@©TêÍj\¥§Ì—Ëi±$CŒŒŒÍfI§Ó !ÿ$T\&“‰r"­6–Z>]\x¬ÂÞ ÿ^òí%âº.Ùl–ññpý^òÙXí¯E“t X!$•ˆ###a?Zä;½ðB~R*aæÝbY¼ÿ’Kú]ý%e)Ƕþ‡àå¼S9eÎýä(Q´ËpF”è•J¬|/•b¥~«ámr=CÒîY.‡ øæWD«W†|ç8±òâG»VkôÄØÑÎ>ßj~-Þ)íÄ&ù}òzš 3ÉòZ]“x³8N¸=¹O;]º©Òé¸óÙK-+lŸV×ÓîõœNÇž,íÚÊqËÍfcï¢fN;íH¬–^é,ußia‘)Ä*s|ÂÜÆ&u…êÃÀQྼÖ#஫>¢~àL¸õ4Æê_/ä³êå‹Ò]Î'ÊÚVÊûd½dE}’j¢¾ÍûˆòØ®ïg6•'çv›Î)õ0ëÇš„©)›ÏQªï'¹¨ëŽa]©Ž¥.Ò¢è–sJ™ÍumnÙGæú’o»Ù ’O”+×kÔÏ'û'Û–¦ãúv£©#±úuœ¶ÊÆRK)Ÿæ³>žü`Oë›ì6 ê¡L‰ó¢OW¦‰ó—Wïýñò_Ÿ0Ò”ØQ˜¯*%K XM‘ Ï[e&¯Àfiž¢ÌGÈFÆIBýÍï€ä³¯(Ð ½-ÀÉþ)˜OÃ_ÿúYÛºY¨)XXTëQ¢„……‹K‰EŠ(Dû‰Ž¶J•2ellJ”Z†íS”V,»AeÇŽìܹ“[o½•k®¹¦aÛöíÛùä'?ÉØØ»wïæŠ+®`ll¬#‹§‹ËÖûÙgîkÜ Á…“Aƒ[§(å$Y¼°aóS”ÕeYXß­nêK5mÛ&öÿó~&Ÿ\ùÞsÉ&t/ŸOîsÁâç¾^ sî+y8¦œ ..F”XÛÂjXy$É !|×%ãïæ—ÛØ žpû·JuÖw¥ú´²HqÖy\ÜhpQ ocS¥Šzb’&s9ïÙÄÄåzü•\.G6›}|¬)‹¿~>ìu7€•‰¦i’Ëå¢þT½Ì>Ç =ÉÚh}Åû7—Ëqùg>ÃWIÒë^Œm» vŸ÷'Ÿ<;¬hµDªÕP¡+6¸VväVz^ñbH¥æ å8­ s‘ÍÆCñfÚ½¢»YSÑÃ[7ëòùÖˆ¹Hz®tÊBíÚ†ÑÞ4W¹«L/;‹^ô—}ë2Ìízظx¬áŽr}À›ï0÷§‡ïa0¿ æ+ã }?økÁ8)ÜæÖ—ê'Éjd-B ©X¨ÿ-[Ī"Û]B ¯O¨••ÐUB «Ÿ£0 ÕCÄ×g< µSÁx,ü\8ªëÃÿ³õ"J v·'Ο´P˜Mçª[`ü#`ô|0ž‡Ú4‡ÇÎê1àL׫>…ׄç‹Q±´$Ï'l9GÒºd@á(`møõ`~\ ìÛÇ$ëì&ʰÃk(Þ î9`Þ Æ…Mç©‚kBy pð°)¬¦›h1–Ô¤©dcü'À}ÒgÔ >ßï5u%¸þçÁÝîPû \·ï¸ì²îc@è…|þÁ‘ÏòÈ/nZ¶k˜ ~ôŨá³+¯ÛæüåÉÿSõ_‹PäÅX)xh çxGSäC¤ùSª Ê×a-6·àò ¤ùUòdÉ`D—¼&Ä`i2Û8X©×Á¯_ƒE„«Ä9IQ÷‰½m ĹäsMÇ7' f§¸©&ê$¯°j⪔êÛ¤¼rý>eÊT©F:’…p.Œ…‰I669r˜˜dÈD9–d?'ñTÉþjt9xYvƒÊ–-[fjjªáû;w244ÄØX;ióæÍlÞ¼™;wv¼RÈx­ÏÃÇ_ˆµ.Ísœ8þAbÖõÜ;ÞÁ]×^Ëš½{9ç”S:Ή²,4/”enI$óä*R2­”Æ×L°ùå›û]µEÓN6aqòé­u9ô³kxã‰'ιŸä(êõ ör}h™%K™2.nd,0«ƒæ¬oݰ!F)³• ¶‡‡í'+% Æ ÒQ(àááàP¦ d•„ÔOêŸ&M‰RCÅ aˆ˜d‚Ã*Õ¨\QFÉ’Vj88T©baEeO0‡GŠL!­ü(PˆÜjÓ¤£ãÓõ¡e•jÔ>~d0ZÌŠä{:ŸÏc™L¦!‘x>÷Üs=}ž–‹^É'€ñ¼ÁšpØa3]¡Ä3¨P(DžA’‡L9¸˜o •Ífq]—J¥Â† øÈG>ozS¿«½h–zl{Ò“'Á!ÏbeÎ:«±O”!ÉXž×º«Sº‰P´P±Eÿj¡›h|ËuýêÜ;›^õårh\, <ÿ¿þãσ7 Î7À~œWk?O¬ôÏÒryxÔó~0ñer=_+ƒ¡Ÿ8XŒ%UBc‹˜%vÁðÿ×ãeS„ÚÀäôæ›õモ…XÃZwCÉŠÁÆHœ_´ŽF¼åúçº&Ò0 ò]0€ñ"iVÜWê.0† yÑXV µÖ¢ñL’¥Qûœ#v ²éÄöt¸ÝNj@ B×›X“,mW­_{Ýhc‰v÷Ä£º»UK®¡Ld=q, KN|‘VÖcl«^‡Txý–¸¸L€qØ/ýÀ¯ÜòfX3{!Ÿ?<뇬;uݲ]ƒÑæ³x®ÌGÒ®Ÿ#||dmD¦¾ÝÎÄâ/°y`acbÿB•ÿK ‡¯0 8¬Ãç: ަÌé˜üo`-&ß6bs36ï¢Ê«oÅŽgúh¿«¼$,õØö¶—?à #{©V«uÔÇ€xÈhY³½ LsáÊtÓÔµ8Jk¶oßÎwÜ)KV2½Û>ûìÝü÷ÿþ"ß>çŽ>÷g©M¨K3;¦N¯Rb%‡téß VÓ>IŠÄÍær³MeÔ½6Z&ühwÅÙÿ7Ú\ß ÉOª‰2Úy”ÙMÇ7#ËÍ%Þd3IwN¼ÖZ·ì6ÿ']¤[Õ1Y‡Vνõ{155ÅŽÃvðõ‘¯ófÞÜAe›^Œm?ýܧ¹|÷å+2Ú¼Bäq‘ÇÑ­çN¤¡Æª{aØÜ˜xˆFÅÂâ ê¥úg9>é¥#wP^Q.¡øyõãÄYhj79gÒÆìÖ÷“°kb)תï+a Ű#žG©Ä=©ß/1Â\¹s'×8À7öûQZz¥·Ýºu+†á°ÚQ<2ݘC¥Z­R(!È¢F ·Á›Dt8ò7ßâe.ºä¶dbhqq©Q‹ÌJ~£%Ê”)Pˆô>iÒ-ϵґÅÁI¥×¹Äë¨UŽœd”‰¢R¥Ú°˜÷ßøß}컌-qòë¾åPifÿþý³¾ëÄeì˜cŽá„_8~ò(/[ûï9òÈPÑŸÂæ@Çıí?øü?ùNo¥ü‘x’u²y›ÍF szzöñ†`<^õ“Ù1ôH²\®qF<ßÒÁ¤qG ÍÛóùÐH‘ÍÎöóŸëE%Æ ‰‰°ìf’Æ1ê$g棣aû%3\ ²¼2› >²ÄR²¤Š'Q³çĸÃI²þããá÷ÒÞɶK¥Âc›Rû~d›eH’:Ï£cïÞ½¬vº•Ï 6pxð8“Ä©œÚv¿R©„mÛË’ÐÓÆŽ^ÈY²up#ŒD†‡,íëèâ6cœY^É»ÝÐI'Iz›tƒSÿ™ “‰úÐP:32žtŠÁ‘¨ ¸¸‘¡§FqÆ)RŒ<^ÆŸU¯ù°,«eh©n¸sÎ9‡o|ã]·áJ¡ù<ꨣÃ;Îã¾“Ž ö·§³~Ý>>·Àå×’÷Èqœ(œ“²šû£U†äÇšššâµ¯}-ßúÖ·ú]¥žÒmß¹víZûûçáeðò—¯ÖÝxÞÂCn)ÊBѱíÜlذ͛×ò×kþ‹çœ«¸í{ÄZ:è]‚y,e?Ûé`Y,bhÚÙyZwC?ß™r-KTYþÝï~·µ#¿ü‡üëÓ û˜¦‰iš”J¥(òÄBÅ~ósÚlPé†V‹`mlÊ”a$Ò‰$Ï=Îx E"´ªCŽ\I¥H±!l»‡äºLÌhQ*ECƒÈ®,jù…0¢Š‡G‰R]$Ož©†ðóR~ò<ÉóbPI¶»ƒK~J”¢ñÒþÍQ[äù_"™4G4I“޾“òÅ(OžQF£Ðn²(Zûnܲ‘û¿?Ì$ ŒA¥ÕÊ„©©©È2ÚŽc=–áŸføÆ#9$x–Ó?óøÎwæí(%F¡PhçÝ0æ6:$Y¿~¶Dâ˜adIÏ3ÙÆÒùç·0Et£œ1Í8+i«r› CÍË‹ÅÐXÒêE˜lÓf#•ã´èœN‡“‰¤×Š01N2ZeK˜$õÉÑu‰Rµg4…Øó(¹äSŒ/büªk4ÆÆÆØ¹sg7leÑ­|nذÎÞÅÆÓÜ»iSÛýÇYÖíV+Ýá²AéÔæÛ?Ž«Ébó<–»þÓ-V[c Ðrà>XM•&u¦9rŒ0 ’+ dp‘'ÝÃ*ÕYmùë¿þë8p ßMÛsº‘O1¨|ŒñÄ?Ã%çìâñ5ókI\×¥P(Dyj$w °ªrÖ@œ»(ޝßuY- óÆ7¾±å³»šè¶ïþÉOxnzš±_¶£µ=ÒIYtl;ÿØöúoÂÿöÑL^r Æ'˜ßÈÉıúªÕÙ‹âr¹ØÍ4ÃíÉ>Uæ0†Î_ŠÅö‘$iQsR%)ChŽL,C,·É…NžÖQ½5/¦$ºB«PÕr½ºø¢+Ö­[ÇØØ7Þxc¿«ÒsºÛ^ô⋜~úé³7f2³u ž>÷’g7Ÿo|f“2!Ïl2ºÄCL3Ž&’\ù Û …P6l»Q®$"H’|~ö9’ \-«õ;$IR¾}Ÿâ¿ÿ;æ'>1÷9Ãó°}»ùýP­Öõ!^Cdu¾ÿìÃÔÞu:ˆ›•÷ë—2ºq4V¦ÎÌàعw æÚÍøçœ±Ý½_‚GÀ>ù=T×߉¹vs4þ5îØƒÿã;ùæÏü ÷ óú;ï¤ð¦ËB+y;>Öï”Sàá‡á¬³à5¯¹fõîOa=y&ÖÌX§ŸNaÓ¦F§1iëd„Y¸+«Z²ÙÆ\õÅÂÞǯïßÏ¿¼öµðîw³ZYŒÞV<_ÄÃø×|ðÙgö©V«d³Ùžy˜-tÑh§äÉG†ˆVÛÄX!F1Ž 9oųFBÂËÚYªåž·;g«LªI›‘˜žŽh££š‹T*+&”ú„åä\¦Fí‹’Ï`ó[ö´5˜är9Êåò²&°–¥SÂb JgHË@A&UªQ‡+qM¥N.deD‰8áÀù–[né÷eõœEÉçóðØ}g±õ´2w¼0¿ÂÞ0 Òé4¥R‰r¹¼(—ì¥&ùÜÈó ƒ/?r¿–  ²$P‰Rtœ„¯“AœôÝÉðu²zOVÒÈ`7¹oråMr åˆÛ²<çÉAjr)m10JY­Œ,66 ³õVÃq’?)9(OŽQz=f9î¸ã–ù Y~º•ÍM?Î=„á s¹ØáWQ”¥c1}ç±& ÿÕí¼ì¾½ÃÆCW«á")´¶î“JÍ^¬gYßI~Ì$óõµét|ŽvÆ ‰”ÐnS:þºn- Ï çHe¡R™mø‘Åg²È-9we¥ç5’×^.7†•nž¬_§dA\òš3™x±œü&燥Rñâ¹_²]FGãm0;®b©‡—ùeó=J¥ÂãäZ&&Z+É%64¶…(ÚÅж…ž«€nå󌙙ÆgRÚ¹).;$jFóbP‘ ‰Æ³;cljŸ%ñ"K’4ØLLÌ–¿äbÒvÆÆùVê7¿C`V=Ìo}k¶%I6ÊŽ¼Kšñýð™l*CÂ+ùk|Œ4fÍ–ÓüQüáæRCôÉÿ)côʆÛ06¸Õåo_ÇĦ?ǽü´ðôøxçØçÿG·?ÿ¦wÔÇØ‘rwëðÔSpóÍðÖ_‡SOŽÏ#îÅ;p VõB8⌠àˆ# UuŸŒX’4®ˆa©¹ýë÷ò¿¾ö5¹ãV3‹ÕÛœŒÅó?xžá‘ç¾w§§Ñz5¯™+¯„N—yxLÈ\/ôì²£…»66*³tOÉ…½­Ú%£®$=;š‹¡¡D‰ &˜ÀÅm0@´Ó{5ŸüÜIti¡UD¹Gòw! “m¸\ ŒAellŒýû÷³sçNÆÆÆØ½{7SSS¼å-o™÷X—×ìÖÜñ4k¯›;+g&“Á0ŒHP—kEm?W¶*uÚM L‚ q¿æÁ{:={bQäþÂ=÷0™J±šYŒ|>þ­óøñ÷_Á5ÿí…–Û}ß_Vc Р´T掿ù³¸rN0AŠ5j¤HE ` “QF9똳ú}9=g1òÉx*XïxEGƒL ñU,ʘ’\u#«¤w‰Ä°MHĨD+Ä"îÚÍ•¨êù†’F™…(ž®|W¢ÔQø: )˜&MŠ>~´¢ÇÅ¥H1rÍn~oÉ>’£(GŽI&gÕ¹D)r}×t)O¼¿LÌh`Ÿ¬{xѪ)1'­ŒM‰vyá¸ãxfíÚùÛb³¨yg‚ͬåñ&o—\.7PóË¥$9/›/äü|ùäm®yVœ‹É‰æsƒ5e¥10€mÛ¶qíµ×²eËvíÚŶmÛX·nݼÇùøÜ{õ™~`î”çyضmÛš0WY­õï>É%Kí96t#Ÿ=/Âдßr»çyó&1î­ò›(+ƒä d¢žlQ¼WªT)RŒ^¤HŠTdÌ’YbÄ£‹Ë£ç?Ê;Gç7y…Òl>O°ö6 ãµ ÒÅ(в0º‘Ï<™Ú§á:I3Óju¸2?íŒ6~=¡T§ó›D(éYßät#ŸoügCYK•šH’×·¤‘VV‹™wúøÌ<gû'ž~ö¢Æ¶]62OUÚÓ7ƒÊM7Ý4ë»­[·266ÆÔÔÃÃà rÛç­åsŸR©„eYjLQ–qÞ¾½ß5YRZÉ&t'ŸÓÇO³fø0Ö¾ðY ãªYÛËårßä±Ó¤çÊ`#ÊoQH'•ÆY²ì8iGWå*K)Ÿ|xà}àùsÆ«õοäÄ~W]QV=ÝꆔÕM·ëê%Ï ²x#›G¯=‘Wýˆ§6ŸW·le…qèâ‹è?..Ÿþü/ðÆ}ûZn/  |ß_`ÉŠ¢,–§:©ÃOšõ½8¥ÿœ³ÏfëÇ„ëºm“V«UjµšSeQojEL¦žÞÀYGìì<4•¢(в¤¨Ú}eóÐߟÏ?ÞxÃܳT*Q.—û]5EYç¡Ò-g˜æ¥×¾¶íöb±Ø÷É©$oU”ƒ‰ÃŸ‘>úhÃw¾ïS(Ô¥SQúÌ“S§rà¯Â@ð­úÈT*…ëºÔæKЪ(Ê’Òï1«¢(­¹ìð/pÑüpu¿«¢(Š¢,¾¤‘JOññ9æ'/cÍñ»0Œ÷EßëB[e%²*O.—Ãqœ£„cqÏóp§ÁØ!†‚äg1Fˆ"ùçy¸®K.—#ŸÏS­Vq'2º$ b6 Ã0¢2Ä"ç- ‘!BÎgFô7Y†P.—£ÏÒnrÝ‚iš —$R¶šÏ‘¬³ü/†’dý€è¾Ê÷…BÇqÚ–)ç•2ªÕ*…Bb±ØP¶æœœ›ïu§|¿«¡(Š¢(+’fŽàÙ7m‰>ŽŽj(xeE²* *ç?{>_Yó%þ˜·Dß¹®;pVN—*ULLJ”°°pp¢ÿ-,¼úÆTV>Žz’ý×]Žù‘/Eßår9²Ù¬®zW”`ù?8äNLóº†ïeŸ¢(ƒ(òÅ3$i©V«d³ÙY ¢<»,r¨V«‘!A£…(ÚEa/ßæ¿s!†9_óßæýZ}'ç/W9V>·ZHÕ<Þϲ¯”-ï<ùÜjœ’ü.YÏæ}e"³ÙlÃ1 ™£4ÛÜŽRïN<å¼Íe5_ûE]Ôqý6¦§§5Ö»¢(Ê ¦D©¥§ŠéãZmóë?†31£ÏGst¿/màyèŸcNy¼až™N§5¼´²"Y•Ÿüõ…œµæˆ†ïMda‘&M‰>>…ú…E‰5jdÈ`bF}| â—‹½ü}|òä)PÀÅÅÂÂÇÇÃÃÄÄÀÀË^ò&&6vdÄ8¯‹ƒt\܆sšõ·¡ãðñg~¤‹A꯬|ŽyòhŽ<:ˆdQ”;jLQ”þSyÄåˆÏ`øÜ ß—J%|ß”xŠ¢ â¹Ëå°m; Ÿ%ÞIã„(Ï¥ÏmVÀ7+õÛ)‰“^ƒ4¶V”~pÙe—©AEQV¢/J*r]×úU ))ތ͞IJùßu]²Ù쬙L&ò®LzNÑÿår9òøœ˜˜ •JÍòĤ‡§„¬Ìçód2&&&¢ó•Ëå¨l˲¢úJ¸Hñ<-‹ …è|r 2κJÛ”J%ŠÅbä5šËå(‹‘«x¯Š'¥x>JY–yHʱãããT* …BÔþIïÖdXÍäùå¼RñÀMzËÊõø¾Ï– ¶ð±Ç>Æë_ÿz¾ûÝïrÉ%—ðµ¯}-lámkÞÆñÇÏÏNý,?øÁظq#ÿõ_ÿ…e[Œß=ÎùçŸÏ½÷ÞË駟Γ?x’ÃÏ<œ'Ÿ|’õë×óÒ½/qßÙ÷qåä•ý~´šÝzçx"› 5¦(+–UaPyñÀ‹uÊ£Ñg×uj°k`àÔùßÀ C†%<<*4®òKĨ!ÿ0‚ƒC‘bd10ðñqqI“ŽŒ+..2ØØ(DFŸ¥(ÇK²Ž>>UªT¨"…ƒÓ`pÉ‘‹Œ,I£ŽƒC–,#ŒDuãN–lƒ·ŽA•*Y²¤I3ÎxT2e*T¢ö‘c \) )Ù&F¥"Eªõ¹¦2å¨MšÛS GÊÒñôQÏ2òžÀ²Þ  œEé?÷?åsà†K°ÞwGÃ÷Iå©¢(ƒRR©8ŽƒmÛ–OQEQÚ )žœ™L&RÜg³Ù¨_e¼ô·r¼ ÞŽã´ ¥hFtŽæ’•J%Zø ™D9´ó•—²¯išÑ12¨Õj LjҺ•W¤S©T0M32ÖȱsÍ$\f>ŸoéµAÃ=h¥0—:I§§§Ø{´ÙÓs!mÕ<6Z¿~=µZ-j÷Oð‰pÃÙõê6ŸûößÇoð·ù×⿆ #\¬ l¨ï{^ýïõ°ª÷¹˜‡š˜ç›ìܹ“ììæQ=hxéôÿâô—ÿ4z6E&e%²â *û'nøg¿ü5ÑwbÍt’^ 662¤™Ýa$•üIï›,Ù–ûÉöæÏ66㌓&Ýpì\äÈ1Ê(EŠ Æ–vøøŒ2‘òä¶(`c3ÁDôÀ(£xxdÉF†›,YªTÉÁŠŒ1â!“#^²d)SŽŒ*2T©’&MBÔF9r‘ÆÂŠÚ­L™þ¢½qV;Þs.k¾|*ÆÿcDƒ.í0e0xæY8dÝ™,—˸®»"úPE9Xð}?Zõ)ŠíKEYj’+î}ߟµz_öűäJ*Ÿeõ½¬l—ÕéÉUõÍyz$W¬^—?–eEeHùíÎ'û&•º&CÎwLóuI]›ëØÉ±­Ú$Ù~Éë“ï›Ïת®?þx¿•Ç÷ý(¯”´·DJ¨T*†)î'''¢yªŒÅS»Ù»s®H ²­9¬",~ÁRsN¯¥B®k¡e7‡k¿~#ÆšyëŠ1d4„1ëuÚÂyò?Çã=w¥RIó^++–oP˜¾îwáŠ[¢+-¤ƒƒÑs}žü‚Ãråë?b`&M™2Eг¶5—%†%©›•Ä ÔìÙ“¬{¦þ3ÉdÒ BCH‰LÌºÖ  ˜d²Á¨%†™æóU©F™,Y,,\ÜhÛg®ù _Úý%”Ù¬{j˜#~z(*jeB (JÿùÞ¡»øù_ü–uç`´ücŠr0“ÉdVŒ*в2>5©ƒ…„éÉårT*•(EY©$ýñV ïù÷ðíRž¿ºå¿¢¸V.'ã€NuW/IƒJ3Û·ogllŒ±±±~Ws Ø¹s'ÿû·ã'?Ë“N4 „U*ÊÁÃÕW_ÍM7ÝÔïj W_}5_½t-'|ìØ}Ï;§X,êÊweYعs';wîdÛ¶mý®ÊÀ!ï-‰c®ý¦²ÜèØ¶5­Þ[ɼF’+¡X,FJvArµò8P”… cÛÖH»¤R)ÇQokeÙѱm{®¾újÞsÓ{xÛo>ϯNïáoúP´ˆ@™ÊrЋ±íÀy¨LMM155Åðð0ÃÃÃóî¿áágyöœc8ìüó5T‰Ò3: ¶ÚY¨|òÀ“œîC”J¥hÕš¢(½a¡òéÿ‡Åæ sP­VÕ˜¢(=b¡² ³CÛ(ŠÒº‘O ò8¯Q IX¾¹DÒ×ê¸XQæf¡ò)ãYí;¥·tÓwîù8úˆŒ?}§Æe%sh¿+dÇŽ\qÅÜxã\qÅìØ±cÞc¹ëçyù>½fMßB•¸‹/BQžnäó'/¿‹c^³Ó4£ø³Š¢,=ÝÈçQûÞÀi›×aH>EQ–žndˆÂÂ(ŠÒ;º•Oã¾C˜Á4M5Ž(ÊÓ|–J¥Y9zEYZºí;¿ò“ï@å,6^´1òNQ”•Ì@y¨lß¾O~ò“Œ±{÷n®¸â ÆÆÆæ´x>þòsу_妟þ2¯Ù»loŽsxeÍðëÿ'¿“cÍú¯[ßo.´ËVº‘ÏcŽùw6m:-Š{¬(JoèF>7|ã%ÞöÇ'Eñ×u5Ÿ¢,=ÝÈæ“O>Éë^÷º~W]QV=ÝÈçž={¢<&Š¢ôŽnäSåRQzO7² pÇSÏsÊ{Øòöw`Üm¨wвâ•;w244Å3Û¼y3›7ofçÎs÷Äñ?浿7Ä%33|åÊ+©e Úæ×#4’¸‰ÿýúÿICŒWß¿c‰´ó‹Ù¾}{¿›vNvïÞ½ ÕXý`ÐÛð` [ù¼è¢‹8ì°Ã6™î ?[;vì`÷îÝý®F[VÂûã` ëþ3Èsâ‰'bÆÀSV³¥ïe>º•ÍãŽ;Žlvå‡]MÏà Ë{§¬¦{²Xº•Ïõëׯ ùÔgzðX-÷d)èV>W+a Ü)«å™^M÷d±t+›÷ß?ýÃ[xÍÉSŒŽŽö%²Ð\ z_²žÁA—÷{ûï¿I˕ݻwϲh 1555çq÷Þ{/¿ök¿Æ?øAFO8€ûPÿûVÏ-·ÜÒ‡ÚtÎÞ½{Ù»wï¼íÜO¹ ï¸ãöíÛÇgœÑïªô”näó®»îâsŸû'Ÿ|2333ý¾„– ò³áóuûí·³aÆ~W¥%ƒüþxòÉ'¹ûî»Ù»wo¿«Òsº‘ÏÿøÇ¬];ÅoÿöÝlݺuà@ƒül úþèž½{÷rÏ=÷ðŠW¼¢ßUé)ÝŽmïºë.R©çŸ~¿/aQ ò3¸P]Þ;¥“{¢cÛöòùè£òï|‡G}”³Ï>»ß—°(¦gz¥0ß=‘±íR+„‘nǶ©TŠ 6¬èça%Œ;eµ¼g:¹':¶ûy5=ƒõÏ­á‰#¿ÊßøFþò/ÿ²ß—ÒÀ ÷%+á½0Èò~Ï=÷àºî’ÝÆ ²ÿþYßu’Üè}ï{CCCœ{î¹ý¾„–ˆåVéžAnÃã?ž'žxbÕ»+v#Ÿcccd26lØÀÆû} më8È zý™§Ÿ~šááaž}öÙ~W¥çt#ŸW^y%/¾ø"'t'tR¿/aE2èò9Èõ{ôÑGaË–-ý®JOévl›J¥zlÛ)ƒü ¬×ÒÉuèØ¶=–eqùå—ôضS¦gz¥0ßµÈØ¶Õ³»Úбíê`5Éç|èØvnÆÞr&›º™ .Hó²—½¬ß—1»~ѳÚ+¹ 7lØÀÙgŸÍ»Þõ®%-w` *CCC³¾›ššbóæÍs÷›¿ù›ý®ºr3È/¥¤ù<÷ÜsW¼2HQVÝÈçÕW_Ýïj+ʪGǶÊJDǶíåó´ÓNcÛ¶mý®º¢¬ztl«(ƒ‰Žm••H¯Æ¶“CeóæÍ³Ü—öïßß‘µSQ”Þ¢ò©(ƒ‹Ê§¢ &*›Š2¸¨|*Êà¢ò©(ƒ‰Ê¦¢Ä ŒAellŒýû÷GÉŒvïÞÍÔÔoyË[ú]5E9èQùT”ÁEåSQ•ME\T>epQùT”ÁDeSQb&äÀ¶mÛ¸öÚkÙ²e »víbÛ¶m¬[·®ßÕR•OEdT>e0QÙT”ÁEåSQ•OELT6%ä ‚~W"ÉÔÔSSS «Û˜¢ *ŸŠ2¸¨|*Ê`¢²©(ƒ‹Ê§¢ .*ŸŠ2˜¨l*ÊTEQEQEQEQEQEQÉ¡¢(Š¢(Š¢(Š¢(Š¢(Š¢(Š2¨¨AEQEQEQEQEQEQeÔ ¢(Š¢(Š¢(Š¢(Š¢(Š¢(Š2jPQEQEQEQEQEQE™‡Ã®»îºëú]‰•ÊÔÔ»wïfjjŠááá¶Û†††¼})Ù½{7GukÖ¬¨úÍÌÌàº.333¼ìe/[P–³ý”•Çbä³ß²ÙIú-ŸƒP?eå2—|Ò³Õ|ö[6­ •ÕC¯ä¶_Ïc/ä{¹¯¥Wý´¾#V½œ“’|.Vþ–óZz9ÇUù\YôrNÚg¡s×Aê;[W•ÏÙ B›ÌÌÌð“Ÿüd`ûŽAŸïÞ½›{ï½wàõ¶Ë®[ ”®¸á†‚ÑÑÑફ® .¾øâàï|g°ÿþhûÍ7ßm n¾ùæ†ãçÛ¾”<ðÀÁèèhpÛm· TývíÚÕІýèG;®Ãr¶Ÿ²òXŒ|ö[6;©C¿åsꧬ\æ’ÏAz¶º‘Ï~Ëæ µ¡²zè•Üöëyì…|/÷µôªŸÖwÄÊ¢—sÒA’ÏÅÊßr^K/ç¸*Ÿ+‹^ÎIûñ,ôbî:H}çJ¼'ƒÎ ´É 7ÜÜpà ®ßrÔÐçÆýèGƒ‹/¾xàõ¶ýЭ©A¥ xààÌ3Ï víÚ}wñÅ¥R)úœ¼‘»ví Î<óÌàèxûR"FòÁ„ú%ÛlÿþýÁÅ_|õ«_í¨ËÙ~ÊÊb±òÙoÙì¤ý–ÏA¨Ÿ²2™O>éÙêF>û-›ƒÖ†Êê —rÛ¯ç±ò½Ü×Ò«~Zß+‡^ÏII>+Ëy-½œãª|®z='ídzЋ¹ë õ+ñž :ýn“›o¾9øÐ‡>œyæ™- *ý¾§ƒ>7¤xZÕwP仺5Í¡ÒSSSŒ±yóæè»K/½”ýû÷°sçN†††`óæÍlÞ¼™;wv´})Ù¾};›7ofË–-ÑwƒP¿;w²ÿ~®¹æÖ­[GµZåÒK/·ËÙ~ÊÊc1òÙoÙœ¯~l_ æ’ÏA¨Ÿ²r™K>éÙêF>û-›´‘Ê§Ò ½’Û~=½ïå¾–^õÓúŽXYôrN:Hò¹Xù[ÎkéåWåseÑË9i?ž…^Ì]©ï\‰÷dЄ6Ù²e [·nmÃNë·õô¹ñÔÔ[·neݺuQ82Õ­…¨A¥ ÆÆÆ¸é¦›¢Ï333Üzë­Ñõ{÷îYq†˜ššêhûR±{÷nn½õVÒéô¬ïû]¿©©)¶lÙÂŽ;¸ú꫹öÚkÚ¹ê°\í§¬L#Ÿý–Íùê×Éö¥`.ù„ú)+—¹äsPž­nå³ß²ÙI©|*ÝÐ+¹íÇóØ+ù^îkéU?­ïˆ•E/礃$Ÿ‹•¿å¼–^ÎqU>W½œ“.÷³Ð«¹ë õ‹­«Êçl¡M6oÞÌØØX˼ƒpO}n|饗²mÛ6fffعsgd¸Ä Èw?ukjPY$·Þz+W\qccclݺˆ­uI’7i¾íKÁÌÌ ×^{-Ÿüä'#kb§ç_ŽúMMMEVËk®¹†ááa®¾úêèÁ«ËQ?eu°Pùì·lvR‡~Ëç ÔOY4Ëç <[‹‘Ï~Ëf'uPùTËRÊír?½”ïå¾–^õÓúŽX¹,õœtäs±ò·œ×ÒË9®ÊçÊe©ç¤Ëù,ôrî:H}çbëªò9›Ao“A»§ƒ87¦¦¦¸ñƹõÖ[#cÊ|uô¹ûRÔQ *]233ÃÕW_ÍöíÛ¹þúë¹þúë£m­¬ŸI ×|Û—‚R©ÄæÍ›#W±ýû÷³{÷nvïÞ=õƒðAýä'?ÉØØÛ¶mcëÖ­ìØ±cÞ:,Wý”•K·òÙoÙì¤ý–ÏA©Ÿ²ri'Ÿƒðl-F>û-›ƒÒ†Êê¤r»ÜÏc/廲Ջ~Zß+^ÍII>+Ë}-½šãª|®û-›óÕ¯“íKÁ\ò9õSV6íäsPž­nå³ß²9Hm¨¬>z!·ýx{%ßË}-½ê§õ±òèÕœtäs±ò·œ×ÒË9®ÊçÊ£WsÒå~z5w¤¾s±uUùœÍ ·É ÜÓAžïرƒo¼1ú¼nݺ†ó‚|÷U·ÖQêz¥›o¾9¸øâ‹ƒÛn»­á÷ˆö n»í¶ ‚`×®]Áèèh°ÿþŽ·/5W]uUt¾A¨ßþýûƒÑÑÑ`×®]Ñç‹/¾8¸ùæ›;ªÃr·Ÿ²rX¬|ö[6;©C¿å³ßõSV.óÉç =[ •Ï~Ëæ ¶¡²òé¥Üöóy\jù^Îkée?­ïˆ•C¯ç¤ƒ$Ÿ‹•¿åº–^ÏqU>W½ž“öëYXê¹ë õ+õž 2ƒÒ&W]uUpà 7,¸~½®ÿ Ï¥~Ræ ëm—[·¦•.¸á†‚3ÏWžçµ”k•Ï•…ÊæÁÃBdÓu]|ßïw••9PÙ]},¶_U¹T>—~ÍKU>•ÏÁ¥[ùlÕêœte òxð°ÒerUTÊåòŠÄñññ%Ô ®ë222B¡P •J‘Éd]¦çy”Ëå~_š²T>W¹\ŽÑÑÑ–r­ò¹²PÙû5/UùT–‚Õ,›Ð|ÎÕ*J¯Yí2©4²ª»‘ÛùèôÚç“—v×*÷Ò0Œè¯ `Ûµ¡Êçà°˜¾S¶‚|6Ëf²ÜƒY>"g²_ów–e©qtÑqo#ƒ8îíDþZ]o·ýjò³ÊmÑqo#ƒ(ŸË=/M~Vùì/«A>Wû¸w>ù\ŠyiR6u^Ú?t<ÛÈ ö—ÝŽgW½7X%LNN@Ïçƒ ‚l6A6› ‚ ¦§§Ã0‚‰‰‰`zz:H§ÓT*•h›[©TÃ0‚ÉÉÉ ‚†ròùü¬óضÕc!ûÎ…ÔMþO§ÓÁôôtP«ÕÃ0¢msµ‡\¯œÛ4Í9·ÍuL'õí事Åb`Ûvô×qœY×Òêz …BÃ÷räØJ¥#N–eEûÍuœ²<Ì%ŸsÉfsÊg?dSÊê…|v#·Ö·“kŸO^æºÖt:8Ž‹ÅÀqœ†öTù\Ów&·Š|&ë&Ÿvùœë¸v²)ÔjµÀ4Í`zz:°m[es€ÐqïìöÄqo'ý\»ëí¦_ •ÛA@ǽ³Ûcås¹ç¥A ò9¬&ù\ÍãÞùä³›yé\²©óÒþ ãÙÙí1ˆýe·ãÙÕ®Ç]5•l6¤Óé†ïLÓlx8’B0===ìÅb1°,«áØt:›´;ÉM~nÄN÷‹fAL*8:|åóùÀqœYm4×¶¹Žé¤¾\·¼ ¥C”ÏòÒkw½…B!0 £í=—s¤ÓéÀ0Œ†Žq®ã”åa.ùœK6ƒ ˜S>û!›RV/ä³¹í´¾\û|ò2×µJÇ-“÷[åspYL߃'Ÿ­&–»|Îu\;Ù”{mšfP«Õ:n;eùÐqo#ƒ:îí¤Ÿkw½Ýô«*·ƒŽ{Tù\îy©Êç`°šäs5{ç“Ïnæ¥s{u^Út<ÛÈ ö—ÝŽgW»wÕ„ür]7rëLÓŒþ÷}¿Á­6¹¯çy¸®Ë!‡ýš;QóµÍ‡ïû ×ÏççÜ6×1K‰išLLL`Û6ù|žt:=«½[]o³[´axž}Nºá%]Üæ;Né=sÉç\² —|v#·KÍ|òÒêZK¥år™Z­F>Ÿgrr×u) Ñ>*ŸƒÉbúNPù\ ò9ßqíd³P(`Y¾ïGa\×ÕD‹‚Ž{äqo'ý\óõ~å+_éª_U¹ tÜÛÈ ËçrÎKU>•ÏFyÜ;Ÿ|v3/m7î—öÏ62Èýe7ãÙNŽ[Éz¢UcPé$i»Æ7 Û¶ Bè·a?™+ARµZå™gžYÐ1Ý`Ûö,!ëô%Ó|ÿšëeYÅb‘l6Û{q¾ã”Þ3Ÿ|Îõb<˜äs¡2Ø‹¤gÝÈ‹çy˜¦Ù ˶m7«ò9˜,¦ï•Ï• Ÿó×N6e¿B¡@¡PÀó<ÊårClb¥è¸w~aÜ ÝÉí¾}ûºîWUnûŽ{çgä³óR•Ïþ£ò9?ƒ0îíV>ç›—Î5îÕyéò£ãÙù„þz3…•­'Z5Ó4)•JQ#»®Û`ér§á¡jÞ–\âû>###+zpcÛvC{T«UR©TôÒiµímo{[Ûc– ˲"K2„m].—gYT[áy^tßä8Û¶£íRÏl6‹išÑ*„ùŽSzÏ\ò9—lÊöƒE>ç’Á¹dz)éF^D®““År¹ÜP7•ÏÁd1}§lWùlùœï¸v²™Ïç©T*ѯeYäóùU7IY©è¸·‘A÷Bwr{æ™gvÕ¯ªÜ:îmdPås¹ç¥*ŸƒÊg#ƒ:îíV>ç›—¶÷‚ÎKûŽgÔþz3…•­':¼ßX*Òé4®ë222½Dlj¶[–…ã8ŒŽŽbšfƒuË4M²Ù,ãããѱ¶m7¿Ü˜¦I.—£X,vu¼Ô_ÚÃuÝh°ÖnÛ\Ç,†aÏçÅ¶í¨­ÓétGm’Éd0M3ZyÍf[î+çØ¸qゎSzÃ\ò9—lÂÁ%ŸÝÈm/®m¡ò"äýµ,Kås°˜¾O>“²ÙÉŠ§V¬6ùœë¸fEȦã8]·Ÿ²<踷‘A÷ʵ-Tnßô¦7ñÈ#,¸_UÙ tÜÛÈ ÊçrÏKU>ƒÕ$Ÿ«yÜÛ­|Î5/kÜ+í©óÒåEdz j)×¶”óÐV¬4=Ñ!õä1«×u£8{I‹œïû‘ËïûضÍ!‡Âôôt´Ÿçyxž‡a}ìH]š¯£Ûö0Ms–5¿Ý¶¹ŽYêëë´­«Õ*…BJ¥BµZíùqJoh%ŸÈ&\òÙÜ.‹•—å’keéYLß ƒ#ŸK%›É6Yéò©r¶ºÑqoëö”qïr÷«Ê`¡ãÞÖí1(òÙ|}Ú¯\¬ù\ÍãÞækÔyéêFdz­ÛcPúË垇®y\u•vxžÇèè(X–E¡PÀu]*•ʲ×c®DI¶mwì6µå,gCR –ã8eùÙ”º,öY_ɲ¹Üò¢ò9ø¨|ö·¾I´T ÈîÁ>îUùSšÙ”º¬¤~µçk…ÊõêE峿õí'*׃ɠȤŽg—wºRäqÕ„üšÓ4)‹Q<6Ó4™˜˜XözH컹깜å Ú¹æªC7ÉAµd*1ƒ"›°4ÏúJ–Íå–•ÏÁG峿õm.OûA¥SEvöq¯ÊŸÒÌ È&¬¼~µçkW•ëÕ‰ÊgëÛOT®“A‘IÏ.ïðÎ>ûì~·c[{ì1N<ñÄ~W£-Ï=÷Ï>û,Çw\¿«Ò–Aoý{÷òîw¿›óÏ?¿ßUYsÉ&°`ùüâ¿È7¾ñ 6lØÐïKkË ?[O>ù$kÖ¬áÈ#ìwUZ²Þ÷ÜsŸùÌgú]E³Ôòù[¿õ[œ|òÉý¾¬¶¬„gKß‹¯ßðð0øÀú]•Es°m;eПÁ…0èòÞ)ÞÛ¶–Ï;¿ÿû¿è±m§lÏôJ Ó{¢cÛ•9¶í”•0î”ÕòžéôžèضýØö]ïz£££ý¾¬¶ z_²Þ ƒ.ï÷Þ{/ïz×»xó›ß¼de¾œ°sçNöïßÏ5×\Àºuë¨V«Ñ¶¡¡!ÆÆÆØ¼y3›7ofçÎlݺµm™?þxtÌ ²}ûvÞþö·÷»m¹ë®»Ø½{7—\rI¿«Ò–AoÃr¹ÌÌÌL¿«±(æ’MÙÞ|*Ÿ‹ \.³yófÎ=÷Ü~W¥%+áýqÛm·õ» ‹¦òyß}÷ñÎw¾³ß—Ö–•ðléûcqÜu×]LMMõ»‹æ`ÛvÊ ?ƒ aÐå½S:½':¶m-ŸÒ&«A>¶gz%Ðé=ѱíÊÛvÊJwÊjyÏtzOtlÛ~lû£ýˆ}èCý¾´¶ z_²Þ ƒ.ï_ÿú×Ùµk×Ê5¨LMM±eËvìØÁ­·ÞʺuëØºukdÙl¶h ÍûBzöÙgÙ¹s'Û¶m[ÎK阱±±t qÜqÇ t¹ ·oßÎÞ½{9úè£û]•E1—l]ÉçI'ÄÞ½{™ššš×èÒ/ùÙ‚ø¾lÞ¼¹ßUiÉ ¿?¦¦þöÞ=^Žº¾ÿ†['™€†À®& 2 êQDtVnU,u6ÚJ…Zfk[‹~›ºSki‹—îJZMmío[ÐZkv,­U!¸ã”£ÂoäpÎH8.g’C€$@ö÷Çg?3³{öœ³ç~Éç™Ç>rv®Ÿ™ÏÌ{Þ¯Ïûý`óæÍ³ÝŒ);–©îŸ/¾ø"===s¶ÌåkK2WÏd.ß?zzzèë룣£c¶›2iFÛv¼çf.^ƒãe®÷÷viç7Q¶íÈýóÈ#œó¶m»L×ô|a¬ßDÚ¶ûöí›í¦NšƒÑ¶m—ù`·Ë|ÿ-$íü&ʶݶ=üðÃcÑe´H–Ù>æ¹ú,™÷…¹Üßå³ó˜cŽ™Òíθ ÒÓÓCGGW_}5===\uÕUø¾ÏîÝ»‡-ßNG;ꨣæìÌù—a©(Ïeæò9ìîîfûöí³ÝŒI3Zßìììœpÿ\³f͜Χ9—¯-`ο¬Ïåû‡9Ál7eÒLGÿ\²d ÝÝÝsÒ …¹}mIÔýcâtvv²víZžxâ‰Ùnʤ9mÛv™Ë×àx™ëý½]ÚùM”m;:sݶm—ƒéšž/Œõ›HÛö§?ýél7uÒŒ¶m»Ì¸]Ê}¦ßDÙ¶£óÊW¾’îîî9[À~®?KæÃ}a.÷÷uëÖqÖYgq 'LévgTPÑÙ6mÚƒ}hhˆÍ›7·ìXc^4Ë–-[/ŠùIww7===³ÝŒ)a¤¾¹aÆ ÷Ï5kÖÌù¿baÒÑÑAww77ÜpÃl7eJ˜êþ)_:ŠÙ ³³“W½êUìÚµk¶›2eÇ£l[ÅBAٶʶUÌM”m«l[ÅÜEٶʶUÌ]Ö®];-õï™Éƒèîî'¿¯]»vX˜ØîÝ»çý…b>0ZßÕ?ŠÙDõO…bî¢l[…bn¢ž ÅÜEõO…bî¢l[…¢=fTPY·nôõõ¢°ß–-[èì줻»›Ý»wÇ#¢úúúàâ‹/žís¤P,xFë›€êŸ Å,¢ú§B1wQ¶­B17QÏN…bî¢ú§B1wQ¶­BÑ3šò«££ƒ 6pùå—ÓÝÝÍÀÀÝÝÝq¾º 6pÍ5×°nÝ:¶nÝʆ DQ'…b®3VßÕ?ŠÙBõO…bî¢l[…bn¢ž ÅÜEõO…bî¢l[…¢=f¼†ÊúõëãN¹|ùò†\{éy*lL¡˜AFë›ÍóUÿT(fÕ?й‹²mй‰zvNÇq¾ëºŽeYhšÏ·m]×[®ïº.º®cš&Aàyš¦aÛv¼-ÅÁ‡êŸ ÅÜEÙ¶ ÅØÌ¸ ŒÚéT‡T(f±úŸêŸ Åì¡ú§B1wQ¶­B17QÏΉS*•0 #=|ßÇqz{{ÑuR©„iš# *žça¦iR*•(•Jضo«T*ÅÛRœ¨þ©PÌ]”m«PŒÎ¬* …B¡P( …B¡P(æ.Åb1Ž0Èf³¸®K±X×vÇ¡Z­6l+ŸÏS*•(—˳}˜ …B¡P(ãbF‹Ò+ …B¡P( …B¡˜Le4I¡Pˆ#Všq‡®®.-ZD.—#Š"‚ ›Í[.‚ ÀqÇaåÊ•tuuáºîlŸ.…B¡P( Âpz·ÿ.~>Íû/JPQ( …B¡P( …BÑ@ø¾§ûò}Dd4lÛ&—Ë‘Ïçq]—(ŠÐuÃ0ZîÓó<ªÕ*ƒƒƒ€H?E¾ï[6Š"¢(Š—éïï§\.ÇíU( …â`'-xLÇxƒL¦½ånoE¢úg,¾ïCµ… âû.ùV/Õ6#¨”_ …B¡P( …B¡PÌ R ˜Mt]5êÄó¼a¢ÄDÚ\.—1M3®’Ïç1M“b±8LT S^MÓ¨T*cŠ#š¦ÅéÃLÓĶm<ÏkH3¦P( ÅBÇuAŽ}p]0 Èç¡·WL+•À4AÓÄ ÄríBȨVÅw¹f¤Å Ÿñ¡ìA*Ó§[_¦Øbûéö<AØÂ\)•’åu]¯eÍÌyV‚ŠB¡P( …B¡P(3H âÁl0ZQy^CÅu]²Ùl92,˪{9Â0$ŸÏ“Ëåèïï¶\tuu¡ë:¦iR(ÆÜ~³0£iAÌêùU( …bªC!¤Éå >î š–l÷ûü¼Þ–! ÈT\.Ñ#Žœ4¶Á÷¡Õع½0€CmôÄ´|}ú@“ò|·R*V€»}XBÐÀm]¢-Å"d«pSþ¤®üHáÉ ñe:P5T …B¡P( …B¡PŒHEJ¡¥ë:A +ïû~Ëm9Ž -¦ibYa¢Õ‡ÂJ¡¤9Â' Ã8-ØDÛªP( ÅTÐJÓ©vIP'\Wˆ¹œø[ $®+Ä” g³p[ ¦…¡˜‰@bÛ°Ï‚ßÔ§Ã/ð[,cÛB¨‘Ñ)jðBBèø­¼øÛü!„"Û ü,l<>ùw« Ð_øð¯,ùmx0 š¿ç€‰ˆ‚Ù£ÃÎrÀ™!¼'=Üo¿FðÅ<œ¤ÃõtFÐÀKJÛ¶Éd2d2™8m—¬µb™L&NS–Nó¥ë:ù|]× Ã0Ž‚Q( …b&H×.ÉçÅß2"„hrŽ eÞmŠéïÍCBèø¨ï©‹OFp›GðCVèIZ¯ßh°Ø€#Cø¢áÃ> ®,À=eÂŽ¶zðá*Ô ØÀÞÿÿf(å R€C „?wàvÖðŠL>çÀÿž [ž€ÀCø^ô P]/Äσk B0 ð`]ØîÃ!6ÿ„œ ÃO|È;àáàÞîvà~Ë€;<¸§¼Ö…Kªðfuà—¬°à•&¼ßQ4:œV€o”`‘aXu|ò2Èið[§F÷ÿÞJPQ(Ši&Bˆ'õçeDø¤ÌK9Žú_ …B¡P( Å´R«Õ&5?-¬Ø¶mÛq‰¦iÃjžHt]gpp0^Ö0Œ8:¥··7žžŽ>ñ}]שV«ø¾?êö …B¡á› µ8@øl$Vj™Rý{:æ1`¸GÖñ€$ W.—Ô ø¤·z"ÊâyDJ.â‹ëÂM,)ÀPo°à¶¼ØY‡ »4x=°?€¾ÞóøÍ³BtYâÉ&¼¯ŸÝ …KÁÖ!Ò…àaê kpT6i ßƒðyvhСÃ=8Ä…í|׃'ï‡%?‚¿¾üüY$NÆržøl~ñÑþM&œàÃÃ>¸ó°Æ‚“,¸ß7ü>¼áópì%pBjXŽaVépð©²8o¯ á gÁk5øÚ.ÈÞ™ð.l퇓êçÝ4á¾áÆ\¸¨þÜ~?œÂ/?q*<ýô”^?JPQ(Š â#®ÕQ– ÂI„ˆD)¤Ö bŠ3Æ6 …B¡P(ŠùÎxRp´ìXÛPi¾ …BÑ>"J!œÈ‚çÒo#}9&BœCð blZTÑë$²ŽI.×8-ŠàÛžØØ½ΰapqz °µ—K ØìÁ* vzB 9t ¸¬á¼wÃM÷ÀË~õ¿œúÀ»ø€-ꎔVy ð ,(}ŒÛÀÿ ÏÛO;OwvRøèçB° :NÖá0]D³¼ ÁvN< öEðuž¿¾ö| ú¿'¿(ÂK?{‰óÿ ÆYÚa|^‡Å!¬sÁ^'jª„ÀŸpaõa®¸âD‚zz£,(€õ†EdûM z(ÀgåÉ-Bð (^p’Lóâ)Õ/l >ëÂß™°æÐ/±ù/ÞÏþs!ttxç>º§0LEÕPQ(ŠqR2ˆ.Á¤Ôô?ˆ‡G¦þ¿(æe ΢—QŸïÔ×U( …B¡P(í£"R …B1^‹i9’ "%áÄ#©» D•À‡m!¬¬/ÿÃz¹ÜG|øçz-“#øN'XBxÙ^/ Ybg˜ÐaÂGmø' ¬2ü¹ï«W¿q=üsÇSœxÅ>~-ô¾>ò™ç)xÐû%x}öלøäÓÜ÷•ûxê_>Éž¾ç±C!H€íƒ~)¼ðÀ ¢øü7CX yúÿ»Ëë³`ü]ß o¶à„îy¼üÛpø[‡`­Ñ‹B<úN¾ðâx¾{%\v\pÕ½üà°ÿáï¾å õì¿ û@Ï qä[‚+¿1r`ÔiÆé í‡¢!"hÒhAùsÀÏ£º‚…× áE¦U#›…kê!>Y( þ¨V!û†}˜Ï<Âo¾(ÖYzä>Ž_»wJ¯«P``` aÚºuëèèèh˜ßÙÙIggçL7O¡8h«o¦—Y¨ýsBôÐRQ" H°•úrB@‘ˆ†xÛˆ‡oTÿ?!Z¯O—¯}F}r$DHc8éh´ 5 ëûP,TÿT(æ.ʶU(æ&êÙyð ë«(æª*s—…fÛ–H"L N@øR"„Eúb"  áSYÂa|ÍløÛöšb½{#pJ°øM$V¸Åƒšû °BƒûBp\8Å‚ãLØw7œð,èD!Wƒùu(zààðšS?…ö÷‡òÐÝ»ø›ìã\ùþ3ùÅ…¿`é¯;á¹3¶óêðI6½ê—ìë9ØþÔâ$-Š—}âv­ìæ?Nü>d|ãåÏA×·y&ø%K>JàÂÍÒ9¡N^ §>ÛïŽÐC>ùJƒòs`ý6‚ù×`ÿ#Âu: á„'´Û,ì??¿ý*âÃú‘ˆ›o‡èâÇÁüAý$çð©Ôs\ûÛÀ6O„½jRÜ­Ah$ή‡Mx< ¥ øöF±O½ úáó#߆ ¡éöŸ=ÉcK–Léu5ã‚ÊÆÙ²eKôo¼‘îîn6oÞÌÆY·n[·neÆ ¬_¿~¦›¨P”ŒÖ7Ó?=ijF¦ÞÒâ$Sñ0•£¬ú¼<‰h¢§Ö)7í#¬/Ô÷´h‡ARŒ^>6t [__†Ê6Õ+Ä#!tê!§4²:BjW˜©§ÃĬ2@ïË:$éË3ÃÁÒ?Šùˆ²mй‰zv*sÕ?йËB±meŠŒ4áëþ”ô ×á?ù\Pkˆúç—àbî`ÑJXmÂSƒOÜáûÀ8LéD“Ž)8%@»ÜÀØÔ×O¢vA8Ù¬úzEpL?ÓîÛw/ûÚË8ö‡ÇbõÖ·ùº@Œ>(#D‚bj]qÿ—L:‚d4Šõí¦k¦4c“<¼¥`“?òõu ijĩÿ]%‰Š‘ià õã4êËYõiN};UÆŽX HRIÈ!‰®ÉÖGž3‰£D•™a¡öO…b! l[…bn¢ž“ÑÉÍë躎eYqxÇq°m]omeº®‹®ëqM“ ð<1&XÓ4lÛŽ·¥8øPýS¡˜»Ì7Û¶U†éÿ—ÙDJßF™Ä¿ó³j¨Á!ËpœB5i¨î5à1 \Glìù´PÔEñ}Ø‘…%!Ô€'Bè a_/¼¾þøü;DdÊxð¤ëžÚÃóÏsÒÓ'Å {¡óûåaܾ÷vÞÿüûÙú@™gwu±tÅRïZÌŠ+èÚÞ…œÏw}—Mo‚Óá™ß<Ã.m¯ô4öî¹MÏð7Ǭf1Û‰ô£9öÐ_>âóÙÿÇ:þ’–.ãõ‹ÿ„»ïù{ž­Í6mâ¤}Ýüì\Õ_}íÿ½íL ޵áê,ýgT äI‘©BýdêÂ]yxm?,Ž a¸="xËshÚ±Þ·ð 8&€Ã}8Ja9÷}…ÅÏ~%q²iˆ¼\Ÿ„Ã)tám&;O¾Ÿ½ß¾™ž³áæ\X[¾Á Çöʵ¬Y×Ïãmb‡PÒùÜç>G)(ñw]?à—ö{9ðñ;9t³rì”_w3^C¥§§§eGëééaùòåq‡]»v-k×®¥§§g¦›¨P”ŒÔ7å¼ùÖ?„hâ"î¹åú§Š¸GÂG™¤àX3iAÄ'©2VÔ‡Œ)’ˆ0ÍX$}=µÍb}ŸR8¡þ¿l+4FÅ4 12]˜ŽBlZç mƯ¯g¥–/‘¤5“/2¶\_ΧuNó¶¥5–¥hÍBëŸ ÅBBÙ¶ ÅÜD=;'G©TÂ÷}‚ \×¥««‹0 ãùòïVxž‡ïûñ²Ùl6žçû~öª*s—ùfÛæG˜&Sy™$YIÜÔ´w‡ÂwŸö×è!Ü’ƒÕ®¨¢iðå²(²Ô¶ ûØÁ‰¯<ÀgpÜÝÂoòÏEøýûî"ó™ŸñèGgíöí¼á··óðcŸÄ>à³ì…eÂaåÁöíÛ9ùá“9rÇ‘Ü|ìͬܵ’ŽŽN¯3á÷-øSM‹‰\Q“Å ç‘£y÷—`Iñ„¸b[B<¹ w_&jœ„!üY–{>tl®•yÚ†[Küj`€¯¾¢Tá °\öõœ ž¿qXùŸ7ðÊ/Â…°ÊÛ á'§.ã…Ãnå£ÎÕ¸¾KõÄAð<8ßaÙ ·ð¥žÁEu_;ïÚóˆŸT†††¸öÚk9í´Ó8çœsؼy3}}}Ã:ìòåˇåíkfçÎlܸq&C¡ˆÙ¸q#wÝu×l7cÒŒÖ7aâýó®»îjØÎL‘NÛUD<<õÔZGVŒ”yY'L¦?*C 2²@šŸ:†æö¦Û¤Ú(‘Q6+‰ŸÙ1yDj/ +·'U HR”ÒêûˆHÒ•y$iÊHýŸž&#D}Z;ÓÁÀÀ7nd×®]3´Çéc:úç®]»Ø¸qã¬¿Šƒ“žž<Ïã™gž™í¦LeÛ*ʶ›¶ílQ,©V«T«Uz{{1 ×uǽÇq¨T*‹Åx›–eQ*•ƽ­ƒiÛîܹs¶›2i”m«Xh(Û¶=Ûv¬å&Š+ã*å€O™QÃ"ÉHâ!R›‡~"ŽH21mwø" Åu…â8"2Å4…Èpì±ÛxÍk^â¬s8ö—OsêÑð‡OÁ¿| 7Ÿç¬ê ì¿e?çýû>>´x+ÅßÝÁÿâcüñqÏQ׊sýý!NòTô]}µ8yšÆK_ø4/õÏ_ðF^xþ¸ØäÏ|†ëÿoüR Çq8í4>ä‘|äÈ#¡·tž};øä‹°>„7h†|­ãkì;r/¾æ•,ñ!t]gÉ’%Bõº½Ä+Ÿ|2ðÑßßÏé}:{£µøß»§üº›QAe``€îîn®¾újxà6mÚ?ôvïÞ=lùvBÆŽ:ê¨ÃDŠé¦»»›5kÖÌv3&Íh}˜pÿ\³f ëÖ­›‘cÈ¥þNG[Xm¬+…‚‘õNÚ­G2UÈ葎¡Üb^…DìH·½Zo‰$‡hD"ܤ•axÈmɺ1éZ/ò¯¾¬ŒV‘¯Øé¿C!'mÜDÓxîäÈ™%S\xl6˜Žþ¹dÉ’YÍV¼tvv²víZ/^<ÛM™4ʶU,4”m;:3iÛÎEFJï5 …¶m·œ™L†E‹‘Ëåê^¯ôôL&§Èf³qÍÊ•+qÇq (ŠÈf³DÑtZ¡Óƒ´m:ê¨ÙnʤQ¶­b¡¡lÛÑ‘¶íòå˧­ÝRT‘ugå`Ú"¸Bx*Ÿø2²Y!ŒÈ@É0ÛËZ–ønšÐÛ;È;Þ±M¢J¡wÝõ‡^xàî»ï>þøØc¹ëòËyèä»ùÿúÿx÷SWƒmãº.–ea ¹.†aðIJe,îîæ_ø‚8ɚƚuë8½ò§p\D¸Zcè‹_äØseÙ'–‘NøÀÈf³Üyüñ\ñ¹ÏñüêÕì¼ì2€Ø¾p‡}ÝïG_¾ïã8¾ï(‚Œ†mÛär9òù<®ëEº®cíð0 Éf³ jµº®“Ëåb1IJ,jµ–e‘Ïçã´a2=Yoo/Õj×uyúé§ŽÑó<¢(š—µ[¤m»lÙ²ÙnʤQ¶­b¡¡lÛÑ‘¶mGGÇ”·7húÛEø‡NqFˆŒP¿p›2|¤VC!¢xžUÂ0Ñî¸ã~ë·~„i EÓ„@ÿéK6óã}G±xßbÎØ¿˜÷=Óæi,z9Ï,û%oxät>räG8ò°ûÐ/ˆXóþ5\°è5À÷ïØøtö¯=üi^óà]ÜõÖ·òO‹h íÛ·£ù>ßyúi.ܶ­W\ÁËy„kÞô&ÎY¿ž ø¯þÔ§xéw?ÍŸú +3.>í4N¸~Gy&‡ïÙC¡Pެ,¹â Nyó¹Üþú=,[¶móÄПóÓŸâ‚ . Š"N?ýtþmÇ6Øi0øgAµ*NŽìsá pÑ͉AºÎº;xâüó‰4Wõ«,Ý´‰í—^ÊS'œ€çy¬þŸ/ñÖÏš÷U> †eY¢N›i¢ëz\cͶmJ¥®ë²ã¾ûø¯_ÿš›o¾™Ï,ZD) ãí†ÁãK—E½½½\ø±±æïdÝÒ¥ÔN: ÏóÐuMÓ(‹<~ÄZ^¾äâ)¿öf´(ýÀÀCCC F¨ìPk×®>½{÷nõ@T(f€Ñú&̽þ!"Rä« #S<’™í"#4æ+íŠH"Í$"4 1…Ô¶´Ô²ò»žÚ$¢‹´GdJ°fAÅ#Z‚ÔvÒ)ÄÙoýS¡8˜P¶­B17™ÏÎbqø)VTëNŒæÿ[1™uZ iÒuP$‰î(—˘¦‰ïû”J%òù<¦iR,‡µÁó…Ð…_×o÷R9Q¾Ž ߣHD›H<¯^3!ªx‹P0n¡¿ª‹gS8 µ¾A´E'8‚oß:âß9ïWæ›/ÿ&+÷ÿ%/í¹œ‹.ºˆ½?Ý áíð1ƒÁ-U^ŠN xà7Ü7tµ“NæÄGïæ¶ÛúYÿðÃøð‡yþá‡9ùä“yñÅ9âÒK9açNžûƒ?`QO¯éè€óÎcµ¦ñ‹¡!¼;c³Â0X¬5 ‘Ÿ¬PhŒ*­D9?uÀK–,a×®]|âŸàØc¥¯¯þKø:7oû"˽åñ³˜Cur‰4ƒJ¥‚ëº×ÝÍC¿ú/¼ë]\õµ¯qè]waA ëzü¼]qÒIX'?ÿ àZ­â”JxaHÁ²b[CÀè¾é&®\¾œ¿ø×åÚk¯åÞ{ïÅqœø˜4M£P( i®ë¢i¶mÇÓÒühÉ8î¡ã8ü™Ã§ôڛѕžž®¹æš8'ßÐÐ[¶l¡³³“îînvïÞJèëëc``€‹/žzI¡P42Zßæ\ÿ”‚IoýSA8÷K@IQöñN`¹D»‚DZI iškĘ©ík©¿ ’è-µ)–©ïZj[R¼’iÂTöìÑ™oýS¡8˜P¶­B17QÏΩ!]C¥Z­R(ŠË˲(—Ëô÷÷Óßß@.—¶œŒ^inGE˜fc^]מf'ʲe˰,+ŽLñ}?q)f Õ?йË\·m/)Áí©´Ò·"|D6Ÿñ`jt§¬…r¢vJ Q¥T‚þçûY¹R,³hÑψ¢]wñýð4kŽ\ÃÒwÏßùwœûÅsyåÞ§„`Àg_·ŠO>ðç qê¡¿äø·ÏÑü”ûöícè=ïáÝ»Éû>‹·nåã‡Æî߾ϯöìƒaëE\t]§ã _à쫯ÂE\Ažäÿ1xäe/ãë»vqÖYgŃž}öY~qè/xñÅùØÇ>F„aȃK;zn¥R ß÷1M“W\v/|â¶Í÷~þsªÕj\+MFžü¿ÿ÷ÿÄ˲âèÃ0( „aˆišA@©Tbppuï|'çŸÏÝwßÍŠ+b»@²Ðuo}ë[„a )rpEzà„®ë,;k}«û¦üZœÑ•õë×Ó××Çå—_Ngg'[·neýúõ¬_¿€ 6pÍ5×°nÝ:¶nÝʆ ¦%$l¶¡IS™{V¡˜ Æê›0wúg„pħÇôY‡}©>}¼¯IÍÃ|dòVœ­³£§‡—vÏ-^Ì|žß÷»Ylš|J>o5õ¶-,åO>åƒl}’ Cä%ƒ;V­Â¿ç^¿{7¥R‰gŸ}–§žzŠ^:Ï<ú{ì1ÇÁ0 þèÿˆ»N=óµz<¸¡R© èâ¹›Ëå(—Ëñ`Ó4Ñ4-ŽVõ}?@qË-·ÄëÊ4ž žñ‹/楗^Š÷ă#ä Œjµ:¢Ÿ=þêßþŠÿ:á¿xñè§ôZœQAàºë®£¯¯/ K‡†­_¿žîîn†Í›¯ÈP'ÏópÛ¶»Ã0DÓ4eØ)fÑú&Ìþ™#)žžF/Œ{‹ó[HI´¹\:ýAc4Á$ýˆ4h}¾¤8/2:E )6"å˜Ñ´LD’~¬Tßgĸű…Ê|éŸ ÅÁÈÁfÛ*óõìœZ¢(ŠÓq9JÕu݆Q£ÒÁÒŒtÄÈ´¾ï“Ëå¨V«d³Ù8}—lt°Œ„¬µ­Ó¬)fÕ?йË\¶m×àA࿞æ]üÿ€ði"Mƒõf(ý›W¬º ö¥—îâCŽfåÊ'ùÃí¯bÅ£5úÿ÷Yllžî¿9nûø@Ç8v×±üàÿSâæ ßÌå·u°fi/k>Ô 6ì»i§îÚ½!,‡7¿ùÍxAÀÛ·sJò…›nâþ3ϤX,âÿÑDaHô†7P6 ÑXÓÄÌçAÓÐd¤‰LÓÕ®ßXׄ—‘þ¿ÿýïÓÛÛË«^õ¸Ò÷€IDAT*n»í6¶üz Ï=÷Ç{,œöúÓø‡øŽH V=U—3òù<Åb‘®®.n¾ùf,Ë"4M£««‹ÞÞ^4MÃq4M#lÛæÅ_Œë§¤• xç;ßG¸ø¾§ •6„iš”J¥ØfÛ•Q­òï/®à)žšÒkqÆ`ÔB~ éa) çٶ뺔Ë帠ïûT*2™ –ea†Ê窘uÆ*²9›ýSÖMÑi]¤Ý@qWŒMºÊx-šLõÕ\¥yßI-•Æö>I¤‹[Ÿ®^}s¹*;‹m«PÌ7Ô³sr4GȺ'£Ío®Ý¢ë:årÇqâ<çÒaÒJ ‘õSºººâ\ì²ÖŠmÛd2™xºeYc <š¦ÅNñŠAŠéEõO…bî2gm[ 6!òà¶*E¨–€‚ð58Ÿ^. C‘â}‚`Ý]Ïì"`Ë÷ÃÚ÷òâîcxœGX½V3dç?ß›üc^yòÉÐåóð¶‡9vÏüÕ_q®¦qï¦Mºs'Ÿx×»è}÷»ãQ ¯g&ªÞÏÈéÔu×uY¼x1¾ïsÆgpË)·Ýqá…²ÿ~¾óïpå•Wríµ×ó[;Žƒišq´‰ëºÜ{ï½”ËåX ‘Ïýl6T«Uòù<¥R‰3Ï< ~®çr¹ø¹-Óƒåóy‚@x¤ÀbÔ Ü—J%²Ù,år9hƒ.d:±ŸÞùSºèšÒs7+‚ÊBÃqÂ0Ä0 |ßsÁ•J¥XL©V«†ã8€Èé&pÏóâ"{ÊÈS(" ‹ˆ:qêÿO‡ìEQûjÿ¦½L™“‹Èë%ÅY+%h±žžZV†è¦ÓŽI‘E§ý¨…B¡P( ÅÔQ«Õ&5?-¬Ø¶mÛ±D¾/D¹\ƶíØA“ÎnÛv¥’NñÑÜžôþÇŠbQ( Åü`g–Ös’ßã ?CÉ,áGˆžà áyBT±–¿‚õ(,;ëÇüèñ X¿ï>¸ó0>Íê7~“ÿ¸V½âþàÑ¿ã3'†u­c;xý+v›Ï?t‹î}‡Î“G}€eg] lÂW@>¶s';Ï<“ÕµxÛöìᑟýŒ7ßu/;ã îÚ¿Ÿ¿ûû¿ç‡NxöÙq-‘IEjL¶m£iŸþô§yï{ß‹¦i\tÑE¼áÒ7pSþ&>õ©OÅ©¹ŠÅ"år™|>û²]×SzôööÒÕÕÅÙgŸÍW\Á7¿ù͆2ªD>ÿÓ$2’EŠ22½¨mÛA€ïûq{eʯôv\×Å÷ýØ·EQ{%ä¶Cvà»ôkoºÄ‰P«¬úÌ*.]¶s_†U/AÇk:øÀK`ÿI?ç•Ï¿’‡}˜Ž‡DMcŸ>–ß~†è¤G9þ‰×®~Ž\{$ÇüÑ1¬~íjQËË÷é_³†onßÎ|2ÿûÐC¼îu¯ã§?Î}GÉö;â‚ì‡Ü~;Fgçèe CØ4#Ÿ¥ßûÞ÷bÙM7ÝGÎ4?‹eÄi6›Å0ŒXd‘~l]×ãuÊå2aÆQ,rpƒôÁ¥ýsŽãP­VR~ÉÁš¦Å…çåzi; P(ÄA É)4â(€ß9ð;l?~û”ž?%¨L’tqJ$/ºV†ž AjÆ4ÍXŒ™mAE†d©°hÅlâ"FTøvj£¸®K©TB×uljE™~OöKycR)½XŒ•qyÝA? äöÍçs¬*AÞ9J©iòìÉz7iñDF¥4·'-¨È¢õòÛ|'u™ž&…B¡P(Šƒ ×u™UÁuÝc+ …bîâ8`Åûþ%ýp‹G°2/ÚCÙ†Hÿó`ïx=·¼¬·Aä«ð¿{þ—³w{àDn?üv>ñÂrNÚs«½šó/]Ì`ÿ ;:„3Â=¯Ã€ö#–ZØ÷ÂJ8Êx3Gx߈|6ËýçŸÏêÓOgåñdzø›ßäœk¯åØÓNãkW\Á çœÃÊK.Dt&ïz—¨ u¹Ÿ bqÅ0Œ†zå{—îeÙË {êΛT&‰ïûñ" NyQ´b¬Ñ4Ñ åɉR©盓Ç"tK†YIUP¡˜.B„#^êvÅåóùX$ Ã0N¯'Cûûûãð@™OQ×u*•J|½›¦I)“Áµ¬X™/—˱c®ëÆE¯æ"é:$í`¦ÖKŸl̦mµº£Y1Ä WÂúty ²0}ºKˆ[¤Óü ï¡…B¡P(Š©@¾¶E†!¥RI * …B¡˜v\Ì"¸>¬ÈœlÂ3õÇ“a@p=-‚˺÷sÔÍG¡ï¿pÒOyòÅéx¸ƒÁ•ƒœ8x"G¬:‚_?ùK.8ñý°Ðaÿ‘û¹oç}œ¡!½b_NÞáýûöqÆ™<à@±™ ø×~ö³»ÝÇìæ¨¡£¦ôœ)AeœDQD>Ÿ•¸0 ±,kÌ<°íТ”ÆuÝI]dRø‘m–JLy$ùd½9ª_殓£(;ןB1Iê)0Ûªõáû~qɃ R©ËåââUR5O_»¶mc†ˆ2+•(•J”Ëe‚ ˆ `Y)‘e!2U•cLqDb¤>i¤Ü6Í“Q+òÿæbõc‹Fr}…B¡P( Åä(‹#:Yƪ¡¢P( ÅTñõzÀäéü¤§›pÄ àÿ΃üW!ÚæRøÕ7çO éÜûÛOZÆo~¼ˆm§o# À\a²ç™=lûà6ÞþÉ·'NŽ;÷s—)À•|«_. è–ÎI÷Þ ¯2á«9ˆêC~]—“ÞñÞvõÕ±ð``¿óE¬Ù·}—\BáôÓgûô´JQ&¹ã’;è>g ÃS€Cfû€ç¥R‰(ŠÈd2d2™Xˆ˜ ¤ÀÑL†±Sx¤6ÉèYô^âyžç‘ÏçÉd2q®»l6ËÊ•+éêꊿ»®;,<«P(P,©V«T«UlÛ&›Í6D±L²°‘ïûär¹iÛbn"‹šºLÉdÐur¹LµZ¦†Ë¢Ué—A˲â2MÓ¦KÁÐ4Í8Ÿ Ô@Ñú馹ܧ”I”ÑHGÊ4ßQ}Ä5aS/4Wÿ8$é¿är …B¡P(Šé%‚xÀüÞÕÕÅÊ•+qÇqÞ]ƒ —˱hÑ"2™L\ƒˆßCÓë+ …B¿ûG°+„KU@‡W[ðO¿‚à>p¿.ÄC”>á?ŽÝGHÈ÷ÁG~¹Ÿs÷±æ¾5,Ê/bQ~»ÙÍyëÎcÿGö'©3Nˆ`§K¡ØôPÏ1ÏóøÛ%Køõò£yî°3ØüÑ‚i²r×.Þ|å• þ£¸v¯¦A}àï\Ír²ÐèííQ¿ŠPiéÜ7 ß÷©V«Óö#5‹2JÄ0 ²Ù,¶m7,##NÒ#è]×#h¤Ø"…ÇqbÇq¹\ŽÅ R}t~;¡X2’&ŸÏÓÛÛ;åÑ*AÄiœä±ÊtKéxÒHŸ*AK17ˆŽñòËÉkÞ0Œøºm¾Ç“¢K×uz{{“v¤R‹Å8Zkºñß÷c;< C²ÙìœN³«P(Š™ÁEøÛð8°Ú‡×jp&ô 4(^Ñ͇t³/qìq‡rÈÊÝx;=>ðâ¢E?æ.“³ß}6g›gà p$p_ù4¬Ðà×:<À…õga€€ãñ>ÊÎB—v<È3'?òeË(T«üÕË_uÁDúŽâ ÊO¹àQ‚Êø¾O u¦Sñjvçr¹¸.„L7& õA@†±ñ)…ß÷q]— ¨V«‰B #æ¹5 ƒ0 Û'd±Îß©¬©âº.®ë65JGèÈ•,<.Ïbágì:Žãàû~CÞÆ©@^ÿ²É~“îs­ÄŽt汃 _0g#…ÂlÄßh$¿uº›©ùB8‘õVäßкnÌìV¡R( …B¡h—ÆP[aÉqrED8nYx.¬/¯3Ëe1¦ß4Mòù|\„»Ú+²Ó·;HÒù|Ïóâ´J“1€=ÏÃqúûûD+)œ€%%÷—ž–Þ¯ !Ÿè(Åì!_½F’èäoëyÞ”‹)išë±Èiòš!¢DQ¿höööÆ¢g¥R!Š"ººº(‹Ø¶çy )õÒÛÉf³ñöe$\»}1Š"r¹{>þqÎ?ÿ|Ç¡P(ŒKøÕ˜ýè–fdê/q]Èk ýmÕæ€öRŒ) …B¡PÌ*ë£mŽfsP' ëmµ~_á:v²›£ø1gr?º®ó[Wü?_ÿs±àÃ>ÿõ©O%+KÿKˆš&ôö&Ó÷l!“ÉÐsß}<½|ù¸|œ ¨ÌKÛ*×^{-›7oæê«¯```€+¯¼’uëÖ±víZ¶lÙÂÀÀ›6mj{ç}}}tvvÒÑ‘¨… ÐÙÙIgg猟Y#Á4Í3ÒH£t¤z's]×ã‘ñÒ˜–iÀÆ" C …¨)Žäo!S"¥k\äóù8í™Ü†a”J%jµù|žB¡G …8]“,4.Ý*rEЪoÂôöOŸ‘S5¥Siår¹ñlvÂÈ”y)Jä<)†hšG”¥)"ÅÇq⨠y¦—7Mß÷±m;N&#²dÝ)Ƥ۱òg?#óÝï²(µžŒø+Úf´^*HÃ0b±RF ¥ûl.—‹_˜eûÒ÷ƒæÈ°±êÎÈ,ZSûÒuSÌúßòWÑS{̽4fSÅlôO…BÑsѶU(êÙ9Q²ÙlËééhY?%“É4Ø~Y?%›ÍÆu;e…TÿT(æ2³nÛF°8SfØÊ"òpýÛ¯çoúGÜý.æ“ãŽ;Ž%K–Äå ÃEzwø¼çMp]Hù(·~èC|û¾û(¤ü1®ërÖW¿Ê«VQù‡>HËÂrݶӲ+ÚŠPéëëãÖ[oåæ›ofÆ lÙ²…åË—³iÓ&6lØÀ7Þ‹*í ™­[·ÆÓ6oÞÌå—_Î 7ÜÀå—_Þ 3¤‡³)¨”Ëåy•KV϶mS.— ‚ N62u×hQr´¿¼)†;ªå¾Ó¿WÚÙ[.—c£Ý²,4M‹¾2b ›Íâºnœ†ÉqVZõM˜þþ™.6ÞŒçyX–ÿö3ñ k~ÉK÷Gß÷Û¾?èº ‹ò…3}Í7 7 Äy Ë,¥R Ó4Ñ4­¥ð'#C¤ðaF|]Ox4EýXËår\×EF…9ŽCWWW|ßâèÙ^¹¬¬äºn9–ËåZ¶KF¬iö[ÖQ-¤æ©y2*%bxÁú…ÀlõO…B16sѶU(êÙ9QªÕ*µZ­åÇ4Mjµ@C–€B¡@oo/Ð8ÀHN/ T*•¸ö'o'½_å´:xPýS¡˜»Ì¶m{w+Xl©§ùdÏž=ܹæNò_Ïó®ýï¢g]>>;/Ûɶ ·5úr à!OT²—þ߇®.vÜw_ƒÏ2—Ë¡iÛ¶mcÕ%—4DWŽÛG¬R].hÚŠP¹õÖ[éîîfíÚµñ´žž.ºè¢X¥”ʤT)ÇâÚk¯6mãÆlÚ´‰îînúúú¸üòËéîîž±Ñ2MNsÝE{ÈÈh¿°`EqMˆvhõÛÈQþéh˜V‚˜œ/CÒe 1 ë±A@Eñÿ›AߪoÂô÷ÏhUõ# C<Ï‹?)6Ì&ã¹f›±m»áš*‘wS ®ëÆ/¨£!ÛeYV|;ŽÃààà„ÛlYVƒÈ+#U4M#“ÉEÕj•\.ßC]×£í<Ï£R©Ïçã8Rh1šFƒ„aØáÒŒA£ðÖ\c5þX˜*³Õ? ÅØÌEÛV¡P¨gçtEÙl6Ðã8N<(ÍLÕATÌ/TÿT(æ.³mÛj.lwá¤b’9«:Xå´ÿï4V?¿šÇyœ†Žâwøªï®OëoùŽÓ’”J iœüóŸÇƒUåàú(Š8²³“¥ÇÏ©²*›¢™¶k¨4wŽžžÖ­[×0­9Ds$6nÜÈÚµkÖïééaùòåtww°víZÖ®]KOOÏŒ ]×G,Š>ˆQÀÙ  7µ¤“Zןh…,Ø=äï•þÝšÓ¥I·QÖŸ¨V«±“7Š¢¸î…ïûãªE1ßiÕ7afúçHõSòù|“«õ3é6†!™L& &ÊxÁ4MÊåò¨ëÉë7](­Z­Æù©¥X1|ßÏ{ºÈ½aqëííëÇhš‹M²OÉó&ÛÓÛÛ‹ïû±Ø’>·ù|×u)‹£ÖiiE«h”…V!i6û§B¡¹jÛ*;êÙ9ýèºN¹\¦T*ÅuþÔEE;¨þ©PÌ]fÛ¶õ€£ x!‚Õ)7ÈêçW³ìe„„üç™ÿÉᇚð6¤“¬§ü ‚Æñ¦É®]»âì4Òoâyï»ãÎxßûfû'PÌqÚT–/_ÞÐA¶lÙw"€¡¡!úúúX¾|ù¨ÛêëëcË–- Î99½Y´Y¾|ù˜)ÄöìÙ3%W¦ð™­h„qÃDˆš ’h”õdj›<‰S1@ŒÖîEŒÒ.!įþ÷xܪR¤qêË6åIÄ›fg¦¬1ZÑ÷ø—ˆ•Þ‰:?G+fß YЄӹ¹†œ.ÓåóùS—õôô°}ûö ¶|n1Rß”ó&Ò?·oßN__ߘû-Ý—¬±3èïï§··—ÞÞÞq]s“EÓ´¶œfÑE ‡ŽãÄu„Ú%-дCZhI×–IÏ!™¦ßdTŠ\_Ö4Z¹reÛé÷"뫼øâ‹ü|÷nöîÝ;%¿Ál3ÕýsïÞ½ôôô´¦S¡˜J¸÷Þ{Ù¿ÿl7eJ˜«¶­B1”m;5¶íBB¦nugÄBòràLµZtêj¹/ù‘5/›—k ïû£.'£¸ljÓÖÎe†††èééaÏž=³Ý”)AÙ¶Š…„²mÛ³m‡††ÚÚˆð?nw…rµ|Ñw„ °æÈ5\ºýRv¬ÙÁâ3Ïü‘ išIEûlÊe°m^ùä“”ËeÂ0l¬»¢XPôõõM‹mÛ– rÑE100Àµ×^Ë–-[p]—îîî8"ehhˆ7ÒÙÙÙ¬™¡¡!®¹æ6mÚ4,še÷îÝÖo'dìÙgŸÔKgEq‘èÙù^¿7ˆ6„xÑ…V²4F¬¬OËÔ§å£ûˈÚÅúÿZýQð;@ÜœJ©ý¦ñêûËÕ·í‘=Fj=¯¾=­¾íV¦µ1/ÉÕÛÝ䃀ówî䈿þkœºÁ'…¤ÔÊümnóDŠŽ”:)Š"4M‹£•Æb¡¼tŽÖ7aâýsûöíÃòá¶Â§µ "ëv(Ú£Õ‹ ŒÂŒS€µK†ã2(4Mk+½C¡Ph3åËr¹\Ž_‹ÅbÍ"Sññ÷xŸ$âsºÞJìÚµkA*ÓÑ?ÕK§b6 ¯¯}ûöÍvS&Í\´mŠÉ lÛÑi×¶]DQD&“iÜâ8™LfRõùÆBÖá”öŸëºtuu5#¥RiLA¥T*Q*•ZŠ@²†¦Ä÷ýaû˜kìÞ½›žžž}öÙÙnʤQ¶­b¡¡lÛÑ‘¶m«õ[a‡#²tñìS†Náþ÷sÆsgpéöKX½zõpŸ`ÚdBD CQÙ¾þùøa‡Åƒ|ßGÓ´9/®+ÆÏÖ­[§Å¶m«†Jgg'7Ýt×\s ›7o¦»»;.NßÓÓÃUW]Egg'›6mu;®ë²víÚØؽ{wÕÒ*²e```T`ÕªUq[&‚,ž.‹?O2B¤•Dã“8„0¦>~}Z±þ]#6,¡DF§dHD”Vh¡E Ę®Tû !ÎÈÂÎ&B,±ëëʶK“TÞž,„X‰áHM¥>0XÿÿÏž{ŽíÛ¶ñÁ›oÆ;ûl až«o[¯/›ÖÄsõi½©ù&#ç3Œh¬«0RPI#‹}·rìoذ7Žcs“ÑúæÚµk'Ü?Ï=÷\Ö¯_?æþZ_¿Í56##Óm5“6,ŠÅ"¹\Žr¹Ü–PÁ˜5^Ò¤£NÒ´ŠšiÞÏàà`ËvGQ„çyqß”ý±¿¿_l q_€Æ{Üa‡ÆS'œÀŠ+fàìO/ÓÑ?W¬X1©g§B1d„óB æ¢m«PLeÛNm»Èår†Ñ` ‹Eòù<ù|¾­Ú~¥X,6تÙl6N Ûaâû~\‹°ù]ÑqªÕjÃ>òù<¥Ri\¶ïLÒÙÙɆ D„”²m eÛN­mûx=Då¢"<'Gukâò7Ïÿ ÷}ø>ÎØzµ jÔÞV¾MÅçMä³C×!寸üSŸ–ac®>gýúõÓ"¶·%¨€È×*íѺuë¸ñÆÒÆÐÐ7Üp :Þ­·ÞÊîÝ»éîîfóæÍ ËîÞ½{Ú‹ŽÉT_Qê¸-•D¿+Àó’h1‰¬ÿ!¢+| -ZAB®^A"Ô§ÉÙ…õÔ¼æ`X9¯@"xŒDóºUkVÈô]‰˜b •t\!º¤÷'Å%"œãPþèGñëÓÔ6>äž?ôP‘ç0u¾ õóäÕ÷+¯8—D@*ÖÛ*£cª©sÚ,`eêç²Ý‡t:0 ®©"‹-ÊÑóóµÎÎhŒÔ7e^ÌéìŸRŒKE¾ï«Z›ÈûØh˜¦I¡Ph;òg¼£3Z…ÈŽ=&íÑŽKŠ(²6‹¬µbYhIzC÷‰…Vòt6û§B¡¹fÛ* zvNœ ð}Ø€bGWWWCš,×uÑ4B¡Ð"F^”ƒ¤d”r6›Å²¬x¶m*–Œ7“„çy˜¦‰mÛq4ËXÛ( jdò ¢ú§B1w™mÛöñúHóž<ü´Z¯%_w´Þ}âÝð0t<(¢gÞó±÷4®†b…JE*2*À²øÚƒr¨çaYŽã`š&®ë¶|Þ)£Ñ¶ 2m‹)ÍŠäUW]ÅÕW_¯/Ðîînúúúàâ‹/žÖ†á0‡m5Ö+’bJ‰¿½H8ïCG¿ŒðÈ œ÷÷á`uÊO(#9Š4 „ Q@DŽŒÙ2㫉"qIï#Ž*I}däLZ:°H„¢4R8’Q59à’U«XÝ×Gïyç±’Dԉ¥K—r`ÕªØù*#ø‚t#`ҩɤpc×Ï“QÿȈ¯þHäo3 ÃÀ÷ýx„|WW…BaJ£™æcõÍîîîi럭/¯þSL-¦iÆ©FKkÁ”D¶ Y§h´\MÓâ‘…–eÅ5V|ß'›ÍRìíe;}D?ü!˜&:iŸyÙËfã4O)³Ù? ÅèÌEÛV¡P¨gçd‘‚D«Adš¦a?ÿùÏÙ¼y3¶mÓßßOär¹¸.©V(¨T*ø¾G½ÈA½½½„aH6›kì )Å|ßÇ÷ý¶Ò1§ÛoÛvÅbÛ¶Éd2 NPi‡éêŸò÷k˜VÏ™¬•ñÑNä”®ëØ¶=fîkß÷g$ÝZEcF¨Èš*ùÂÍf9|`€go¹ÿ7¿/þ$}¾\}\C³ñüT(c£ú¦B1w™õþ ©GдdDŸ¤9C„Ìý. CñIcõá¼ãØÏ8‘6§¦iñàD"ÅÏóÐu=2dÝK·^(¸X,ÆâL³Í)óÙ§i7z¤ù=Bî3-¨Èô·¾ïS*•Èçóq p•nxn0ëýS¡P´d&úæló`íÄÜ<ìÊïbE°‚7¯|3gs6œI\W©„J%! äóÂá)G“ËÿëT«UJ¥RƒÿDÕîUŒ—¶•«®º ê{zz¸òÊ+¹ùæ›'Úuã76|_¿~=ÝÝÝ ÐÙÙ9í!Q ‰"£ÃªUÑ"†êõ˜¬ á->œèšX–F ¡;€ „Þ^±~;}R#.*Œ·æ‡€L³µ],íNMƒ\Nˆ<#ùÓbˆûÑH˦£æÂPØéž'¦yœkÂcÞ!wÌjV~r6|ýߟ!^Î]w}Š5<œ§n?œÍ:|± Wzý|÷¸P)жëZâM§(“çÈDYq%Laæˆ.é4l­h¾‘ÊQT†aÄF¿ /•JÜvÛmmGiÍšû&L_ÿ hédÌô š¢=ÚYW, q¶"‚kM%í¼ôbk·þË¿ C‚ÔvBD?7î/} Î9gÚc&™Éþ©P(ÆÇlÛ¶ …¢5sòÙbˆ®-¨˜æpA¥•èÒ,¨ŒµŸ&Æ*ÌEÇsÌ0MÓ´xÐŽLÙºhÑ¢†e¤}9Ú@ æ*®ë’ÍfÛJÉâyš¦‘Ëåâ¶Ê¶¤ÛkYV,º„aH>Ÿ'—ËÅuú3ÇœìŸ …˜yÛ6¶ù°LíYb‡àÀžjˆZ)CçÑav$)m ^¹ñ|s]~¸};ç…a2¢¼þì‘ug=Ï£··wA¦óWÌ m *=== p÷ÝwÇÊ£išlÞ¼yÊ ÍäÃ2=ÛÞ—ƒ•!¼ÚÂÂãì(Ã/|8LKj£¼IƒS#8*„¼—ˆ+-4M ­¢HDbT*¢o‹‰M«ØÖFqF Ž#¾ËýŠßFüŸÍŠåŠÅDñ}!ÀFãöL Á>ä}q¯‘÷M÷&MKj8årbžm‹ýȈ:Ûûsø] ¾öµóÙ½[²ÿõ¯·qÆ7k (žòôl `ȃþ~±=¹ÿ§4p‹pJÿ…3ëùÒ–„ÔO–I´úï(kÕ¤—Æ´a…Ôütm›æÈy}hšõ²¦ƒ¬YñýïŸÇ{lF®ÙÙfº˜éG˜Lõ¥ÂîLJLŸÕ.£-ëyaNû=ùÒ=Ú~F*t/×/•J‹EJu\CܧyøaÂxà'?™Öc˜K¨—M…bn¢ú¦B1w™ÕþÙ\”³cEÅ›æØ#øÚÙO2·|+;M|ÿ¾ÀÆæ¥m6ùþÔ*U—´ÛÚ¥Z™î+-È8Ž×qñ}ÇqèíímØ~¡PsÀ‘bfQÏO…bn2}ÓÎ7á­Ûv¬ÙÁû?ä‡d¬ g_}¶p6k!2B³Pà+¥çÙö°¨L]×ÑujµªÄŤ8¤Ý»»»¸.ºè¢Ùnû¤u1 ÃÀA8Ó_À ¬ÛœÏá}:üÚ‚ãÍ$‚ã­:ì¯GNÛ¶ˆf±,!T*‰M+ýÁQ$„LFù¼X.Ÿo=¨HɼRI ¾/ö“Ɉï !¥Z/Ôä8BÈ‘BM²)†€XÄþs9øbý$üº^;&ŸÇ!}®²ÝÙ¬hKµšW±(>i[½XízñÅ/®ëò†7Á‘G®¡\.]`ÀŽz; ±¯ €¾˜^ áÌ2<à‰6Ü“Mj¨À¡h¡I²õO„ŠdÁzêÓ„Ã5_Ÿ–Cü¶Î׊Ìï+Ñ4­!ݶmŽ?þøY½žç3Í®tß÷dšéFœŸ \ב蠴`9Ú2#¥~3 #Ž4”œS·mÛF†<þøãÓ~ …B¡P( )0äóùx4/1%—ËaÛ6§œrJ,®€Sdº/¢ŒL¿%çwuuáÉÑ6iÞîhø¾O† …8E¬L5&÷«ëzü~Ú¼®Jù¢P(³ÏKøíó€ŽÛ~úÒ‡¨Páu¿|]’Ž¢¹ôIʯpÎúõP.³½»›|å+ ‘)Ð~v…b$ÚTN=´ãÛï|'_ràx¾QûŠIê(É i5Em›D0‘‚Š®'ƒƒšZ;Ž>‚@¤ !¾†%*•D´H_½ï áCF§D‘3ŠEëÊÚI2rÛ0Ä>Ó)¹ä¶dj.¹\&#¢UŠEX­‹>ÕHD"¹-Çm®VŧXç¤\½ Àw¼|>OüñŸŠçÕÓª5-g—¥¢\t]l÷² ÜÜëÂ2à#±ÿã  ›rð 'Ž'ò`Uî“Ñ~$)Ã䘦ôéêóÓŸ4²vúf›¥K—.ÉKwAÑEÑ”C?ØÐ4m\#,F;Ç3ùŒeȤ£ÃFZWMu‡ßÿýß'lÞ<,÷¶B¡P( …¢=dÚ­®®.2™ Ùl–®®®¸Ö[,ŸÏ“ÍfÉd2 5SÒQr¾7Æ"›Í²hÑ"-ZÄÊ•+ ÃpØ`«ô2‹-"›ÍÆ‘îÍ6±eY±ø£ë:årÇqŽËó<5 K1!‚ hu%ÓȵB¦¢S(‚1Ð9p`y„ øˆ÷úÍ'nn\I:,A8ë5~øa¾zë­ìX³†­Û·Ç¿ºÏ+¦Š¶k¨,$äƒË¨Tˆ€u|9€ÇB!P$57$é.'”4†1<"[ú#«ÕDÜHÿ-#Ït=©·"Ÿ·2=®LµeqÊ¿†v4##ÜšÛE‰H!—K§û}>çÀUåáÛŠ¢áûné” Ãw¾sW^Y‡ht¤ÀMÅôzBxy›å,¬áSD¶œ`ƒ%¨Và¯=çö ޡçóô‚“l±ŽGR[Á'ÍÒíðI¢Y<Àjá NçxÅ+^1±“£ ¢1ZI¾)f—™´&32$ýÒnÛvœ~âwœŽ$R£N …B¡P(&L±X¤P(Äï>•J¥A¬iS|ßkM¦‘ƒÓÂ0l˜_«Õ–K§kž×Šv–I£ëzÃ:¶mǶ#вí E;A@.—Ã0 òù|å†!aÆÂ‰üåº.¶mš¦ K‰'—U©ˆÂ_'¯|]G8‹tÐÑÉ“çÂÓ.„ÝM+tu gnýýÿį}s'Žp, „aH&“Á²,*•JÛíR(F¢mAeëÖ­qaz€úúú–kUPl®áû>Ç~ìcxÀÇ}°ËBȾ7 Ñ™Gsë6 *šÖXûZ§¼måß+Äþ]WˆA R^õö&Ñ*íF·òEËBñ22¥Õ1¼Vl8)u 2Šf²˜¦á2sÖX.s™šL0à™ QÔÚ`ƒo‹ûëkJuDÔÎêíÿ’¸õú‹!hF⸗Hò†-ë§X$*¢fN«v¦ívsù*ZãÓ(¨A •Yf&GJéº>é—W9ÂD¦tˆ€Ž¿üËøXŽ9æ˜;…B¡P(Š…ÆhÑÂ’Ñæ§S³Î5TŠ/Åd(•J¸®K¥R‰•l6K¥R¡T*ÅÂI†xž‡¦iÔj5|ß§X,’ËåpÛ¶c§o6›Å²,5Š^qÐ!=kÀâz®þ/-þïÏ¿Ÿç?Gy_™½§ï¾¢….žŸo þº ¨T*söy¤˜´%¨,_¾œuëÖ5L›ÏÅÁî}üq~uÅô™ºp! ɃpðÎäã+Q¢ëI­“t*±v(´ZNF{ŒÉ4´išñM«Ý{—¬Ç⃈0iJ‹f’DÉhžô±ŸkÖ’¨¿²ÔÓ ˆtúÿÊ>¤7 *²Ö ±Å$)v­‘8• 2yš•™¨Ý¡™™(F/Ñu}Ê_4àÌûïGJª2…B¡P(Š©GEu(*2zd,Ç«ïûôööÆÑ$2•\©TŠßk¥ âû>ýýý@"äIᥫ« Ã0ð}?þ?Ý]׉¢ˆ|>aJlQ,h^ˆ`€o|èì9|O¿öiö ìcÉß,i\8 “Ñí)ßœaq½Uù}¤HJ…b¢´%¨¬]»v^Dž´Ë÷N>™ÓnÂ{v)–•¤ÔšMš÷/…©¨1­ié¾FÂnosãf2#L~0J¤ŒaA,Í¥üƆ#"BÜ[ÐëÂåQkå\  ¸±TÀÔÑ%]oÅE8iMê¤"¥nO†€é»î7¦iâû¾T …B¡P(¦é°R(®ëR*•0 #N $E‘ ( ±€"Ós¥) 8ާ%–ë·Ê iÅb‘b±ØPKTÖ]q]×uc§°LŸç8Nì –)³Õ DÅ|go~—ið'±óí™ÃžáéåO³ø'‹‡c®T’¢Ïõbó@\Ó(Ý?}ßoè— ÅdwQú6oÞÌÆÙ¸q#›7ofhhh¶c\<ÑÙÉaßXE´N˵Ј"‘B,F_n®>‚Û‘,†Õ´ž¬×¥ù¯²H8°Û‡<±ÀþûðL]=94‚^GˆÜA}¿!pO¬Ÿ»$rE‘›äï+GÜ(fŽVEÛe±ÎùLºýG}ôl7G¡P( …B¡PÌq¢(¢T*ÑÛÛ§,Ïd2d³Yœz=Y€^ŠÍhšF¹\ŽÃ0ꯎ„L­'ÀžçQ*•¨V«ô÷÷ÓßßO±XŒÓ‡A€iš Æu"€8¦U& YÏh«M ÅL²£>šy¯zÂÐЫŸ_Í)ÛNIRÔärIm#¬M³a”ºišDQ„뺆÷+U›H1•Œ«(ýƹá†èèèˆS€Ýpà lܸÛ¶¹úê«gûxÆ$ŸÏóä_þ%aÕþÙnÍÌ0ß}Ôù™tà†ˆÎq]qöFð¾éÁ…À Kˆ+¿v•À×á'tßµ`?p§Û<ˆŠBTÑ!ÉULiÆÉ‘7*|yæM4™ï‚Jºã²eËf»9 …B¡P(óÇq¾ëºŽeY±%k?´“É÷ý–ËA;‚5Mö퇗ëº-±ÉÚy#Í×uÛNâॄƒ[ÕlT´¢T*Å׸išd2LÓlE¢(Âqœ¸?Œ…¦iAÐp=Ž…Ü_º¿5ÏO¿7Ë,–eÅ#óóù<½½½DQ„¦id³YÂ0D×õ8’_×õ†âÜRpQ>Ål°­®‘<àöû€gûgãáqàM8ó˜3ÅÍba½F…~½ø¾Gtɾ¤|MŠ©¦mAEF£\wÝu¬_¿>ž>44G¬sZT ‚€J%ÖüÇèú‰³Ýœ¥··ýú% Íçy" 0S¯µâ†P¨×§¹Mƒ?vP%'à9àW¬Òa "JàÀz°¢ Ž=÷\¡2HSM޾™ïŽüùD+ã\ŽxZ¡°SQð^¡P( …â`E¦=’6£ïû8ŽCoo/º®S*•je޶™»>mc–J¥¸p·Ü¾ŒÛôŸˆkµ8ŽC&“ˆ¯ýÁÁA2™L\ûeåÊ•@’æLÖj1 #N!&EKÓê8d?+‹qº÷‘–U(Fb°TƒÓ,Ðß| gxUß«8ó”3á£õ-kÄ"ÑRX”×r±2™R E+ÚTúúú¸á†¸ùæ›Y»vmÃ¼ŽŽŽXDq]wN *ŸïéaÝQGñ{Ï-Æš«ù­¦‰LúûÛ/n¿Ǫëâ~Û[Ó¼zŠE ø·¼›~[+‚Àþ^Q€ÛMxG¡÷×+Ówú`XððI'ÁCÍö!ÎkÒAÆíý“xžH_gšâoÝ©ìµÉãº.ÅbqÞ‡ÂZ–“T( …B¡PLŒ´ƒ ›ÍÆöb;ÈôC…BaØ Çq¨V« ÛÏçó±Ø1RÆjcš\.×à–Ëçóùx¿B!…¹j5)Ü*£TÒ¤ Æ·ûî*ÅñŠ/i±1M¡Ph¹o]×ñ}?n³¬õbš&Ùl6U,Ëj(Ô-?=¸1›ÍÆïRR8Íd2±0)Ŧl6Koo/®ëI:é0 )•Jq˜É:²ÓéÕÒǨXXìVùp†…(jÀúEëᨦm[D©D”JqyÍú¾‹€žç©¨+Å´ÑV •žžº»»‡‰)i®¾új†††èéé™íc‘<ó Fí$\×<¨„NçƒÕá¬ëâ#sÛNþ‘ì´¼ˆbYÂÇóðP(–Ù[?gkŠ@:R÷a•wtr„ˆ• Ú6HÃPü–†!~;Mõê6œb’ÈóÃ0°mÃ08þøãg»9 …B¡P( ‚ñŽ8÷<Ó4±m;.ì=räÿT¾ï·Òµ(ŠñDèËh«v‘ËŽÇ¡;Z?KG5“P&# Ãhˆâ* ÃúDs4‰eY¸®Gã”Ëe*• ýýý±$—ËÅËÉ~AéS­V)—Ëqä 5›Í’Ïçq‡E‹Å)™òù|,ÈDQÿ-×ñ}×uc±§¹ý£õåæô…#¡ü;³Ë^Üè •žyæ^>À§Ѹ°ç‰QãM¿™išñµ ¯!%¦(¦‹¶"TvïÞÝÖÆº»»gûxFeßš5<ù¹Å‹W¤ÄiJtR©AIÛå²pÒKÛ¾j›ƒ·ÖÓ2FˆÚW~Öûð˜”aW=<Ö4M~ñ‹_Ìö!ÎK\ €0˜Úy9ó}!œØvãõlÛBTY´HL"ñ{–Ëâ·/•D7 ±¾i&ãÁvôÈ¥…B±X䪫®šíf( …B¡P á1b{6°€Ñä‹´ƒQÖBIâ ÏóâÚ)†a48®mÛŽ²²®I«w‚f'§¦i ²VNP]×c1§•óYnCæÖW,lFK?†aÛ#Øå23å O$†Œži%HÊšC­hÕoÛ6]]]q—<Aàº.¦iR(Èf³”Ëå8¦X,6ˆSÒÁ-ÿïïï'—Ë5D®Iá¦T*†a\H\ +•J…|>‹D2= L딹šû³\VÖÕ÷™ŠP¦xËårqDªµ1;lwádàd¶?·C–ÂŽU;Xßúá ‡á°Ô_²ËT”òR(¦‹¶•åË—·%ªôôô´•ò«¯¯Ý»w³|ùòaQ/ ÐÙÙIgg用ïû8çíØëD±òƒ)è3oÉæñ<áx¢Ä¹žÜtD…¼Ç€)‰ï·<}"÷ø&  ÔD£õM˜ºþ)_{LÀ©Äk& ÅïãºBüñ³-(§Y–øÝ‚@üíyÉó5¬GÉu3!²ì©Â¤!‹*ãqn3SýS¡PŒŸÙ°m ÅØÌågç|°º<Ï‹GùJÚuPAÐ XÈÑìÒÙ*°Òá™ÏçcgfÚaÝÜÃ0F/÷5*5ìì3ýS^é´oir¹\Ûï@½fúûûǵüd›Vm,‹-ß·¥Ójžš·gaÆhúؤ0šFöq¹ˆ¾†!Q‘Ïç±, Û¶1M“®®.lÛŽ…YëHîGÖ{I‹Dår9|¥Àªë:–eá8¦iR*•q_’©Ë¤È•J]×Éd2 r¹Ü¸Äã…ÈlضA |4;ïßIïó½¬yaÍð…\W8xÒ©g¿¹¦iñÚ{(¥-A墋.bãÆqê¯Vlܸ‘ÎÎÎ1£T®½öZzzzèììd``€îîn®»î:€¸¸ýºuëØºu+6l`ýúõLÿ¼s'Kžz =¿88ÅÈø¾¸ËHP×ùìL›gÕ¿<Ào>yÐÏw¬âÞ{ÏbŽgµÅh}¦¶F$éaxXs©”(2ЍR9¢$-lÉgf6›üŽiÁ ÄCÚq’H–ôzi<¯õt)дjã4FA¶Ž4‚@´Qž†™yäK®ïû*vŽ3“ýS¡PŒÙ²m Åè¨gçäi® Sî ޹®çyhšF.—„#ÓûH»Ó²¬Øá†!ù|ž\.×à¤h •R©4ªø£F.Ï.3Õ?[¥š‹¢(Ž‚hU+e,Æ»üxSå5GaµËH)îFÛÖHÙ"ÆZ§­jI!5}žåñÉ{‚œ®ë:½½½†A6›mÙ]×cq¦ùw"mÛ8ŽÓP <—ËÅÛNŸ/y}-©T*µq¸÷jµZ­V(jš¦Õ*•JÛëX–5îý˜¦Y3M³e³,«å:º®·¼GÔjµ–ûŒ÷S«Õjår9þ»···å:ÕjµfÛvÃ~kÅb±fYV­R©Œëy¡<#f˶]ñçµZáõÂÇòãó\«R­}kÍ·’ªUἩÿ®iªÕêˆ×’BQ«MmÛVQz V]×åœsÎÁ4MÎ9çÎ9ç¶lÙ¦M›¸è¢‹FÝÆÀÀëׯ§££  Û½{7===,_¾<ŽpY»v-k×®³Èýž={Æ\æ#ßþ6'Õj<»}1j¶"M¡0<…”a$)ÂLDnáôX‹K,ØûžC‹ï|g9Ï<óÌlƤ­oîŸÛ·o§¯¯oØô‘N ÄH’Y*%‘#㌌7ƒƒIš°rY tðý¤V‹ç‰ë#ŸÓG¤ ËdÄz®+¢`\Wl/Äß2…œü.S—F’ÂÌqÄ2…‚˜ßÛ+æ×#‘ãõ†·z}˜(JfD‘Øžë&ëËý†<çQ ™E⸣H|r¹Öí™Ë ÑÓÓÃÞ½{g»)“f:úçÞ½{éééa```¶Oq200À½÷ÞËþýûg»)Sr,³aÛ*ÓEOOÛ·oŸífLš™¶m¢(Šk!Œ…LñS(âÔ<¦ibYžç¡ëz\‹¡y½ñŽþ ]×) q‘lI†är9lÛžWÚҶݳgÏl7eÒÌ´m›Ž¨)ŸÊå2AŒûzk·xýL3‘td¦i6Dg´ÃDFÿË4\­öSI»m:ž‘"aZ¥P“Ç/÷eÛvœ²Ë0Œ–)ßdú²ô¹“uZt]§T*‘Éd†Ý§Z100Àÿ÷óÍo~sÜçg®1¶íÐÐЈËòsöƒ÷ç°oß>ö­ÙDzÎeÉ2µGê:’¾Œ|>¯¢#Ò××7-¶m[)¿$6lÀ¶mzzzغu+ Ñ·[Œþ¢‹.⢋.bhhˆ­[·ÒÓÓÃÚµkéîîæ†n–{oùòåc:{ž}öÙQS‘üdÙ2.Þ³‡o(AEÑ@+»#%Ûl^Y>ð6€€§ž:‡E‹öKgûP&Åh}Ä h"ýsûöílݺuXÎÍ‘ò+ò‰ð0S5 #)^ï8B8©V“ö¶-ÚEbz.'–q„¡1ŠE1_¦“µY¤pbšIÃëI[T¦þ”‚J±(ö£ë¢’ãˆù¦)„Y+&ŸO¶éûb~=³ Úkš‰ÈÒüÎàû>ozÓ;âèÙ Û"qdº4Çi×Z!—I‹.ºž2³u+ ¾… ¨LGÿ”/ÝÝݪ¦ÃHDˆ¼>↕~^¸ ¯â5-£‘úúúâµùÌlÙ¶ Åt±P•™¶m*2펤¹`s«ùÕj5NµÓìä•5 Â0¤\.ã8NœHŠ#9XÛm£¤V«Q,q‡®®®8½“,†=Wã#!mÛgŸ}v¶›2ifʶ ‚ .\.I_›Rð[(LD Ôu}Ü"Éx÷3‘âàé:­ÚÜŠÑÄ!»…ƒAÞwZmOÖ]éíí%ŸÏ£ëú¨×ÊÀÀwÜqÇwܸŽs.2¶mggçÈöÿ ÀNà¬Ùµ†í)[ÄuG>×)•JèºN¥RQu±#²uëÖÙT:::â–f``€Í›7³aÆ1·100À 7ÜÀÀÀ@¼VEïÛqò¬ZµjÌ}Þæ™ߟm¦P C:×;ì0X¾™×ÿNç\ ¼8ÛM›ZõM˜xÿ<÷Üs[æÓ ~GiäBRÃf„zÓFZØHx6—-4mxÔŒ ¤ø ß/ÓµPÂPl3m¥m¶ôs_ .ÕªhK©$DMß…X"#T|_,Ÿ~”‡®'Û"KŠem|°ƒÿû¿Kñýûˆ¢?£¯OL·m±®adûgx}I“wŠÅ$RÇqÄv¤Ð#·gYÉ:rûi1Gž³VŒ$ 5ÓÙÙɆ Ô(Ò©ìŸ+V¬hëy½ I ÍbHä€*PBTÖ("|1¬/kYÃ#"& ) c¦m[…bºØ°a7nœífL3eÛ.DjµÚ„çT\×õ†õlÛŽk´ª1VQèvŠF‹E …B`šæŒÔjM虈ˆ¢hÜm“õXš‘ŠaT*r¹åryÄóÕÝÝÍš5kXµjÕ´çL1ã¶íKP¬× ¿aå ¼÷Óïå5¼FLé9ÊåG¦i8Ž3/ErÅ̱~ýúiÉÌ1nAe$dgkçpíÚµÜxã qùå—ÓÙÙÉòåË[ns²£B€;gË·_ÍŠ*BE1y ¼ŽŸt5?ኳºf»YSB«¾¹~ýú)ïŸét_"ÔX8Ñ[€Ÿ)t=)bߌeµŽ²éÂF²}|ÑiA&-F"¬†Ø_¥’D¿´Úˆyù|Å"S›¹.|á ¯æè£¿ÍêÕGQ.k-ïi{´Xëvu%¢Œç%Q)2…Y¡ Ú/…Ù>ËJÄ)išøÈTkÅ¢ø_ [AˆU…BÅãºBÜš‡ï“b¦úç‚ÂCD—€ˆ*)y„(â!Ä"°¨!„­¾Nº_Ë¿ýúº•ÔöåuÖ?2+@±>ß"`äý@KÍS,fÒ¶U(í£žsŸ™ˆ˜HáqÅô3Ýý3‚X4(•J¸®K±Xœ—‚Z;Œ7ºKŠã]'+·tI6Ñh›ñþ¶#íG×õXxÓub±H.—£R©´\'î¿ÿ~Þô¦7»Ýs•™´màðà=ì…¿~ú¯YöR=ÝW%#IS‘FA†á¼KߨX8´]Ce*ؼy37ÜpCü½££ƒµkׯ°Y1Ú½{÷¤S‘xÀ¢/¼HÿŠYuÖ*Åbݹ¬zÃ*žn¹åͳݬI3Zߦ´¦Í/¡ây ?W˜æèˆšÑu1}2)¯d)”ØvRG¥÷Âþ~±n±(Úa"rä}ï[ÌOz9Ï>û{cÖ[IŸ‡JE“Œ”‘Q&2 Ä49O¶Ý0’ïa˜D9Ž˜ÞÛ+¶!Å•0õjÒÑ-¹œø^.‹eW®ul:3Ù?B ›¦ÉÈ’€D, ëßeNBêóBD”ŠWŸï#¢Qp¿þÏëÓ4±l´ü*ø×BT·ùƒ!úf};õh<òMíRÌKföU(c£ž ÅÜe¦úg:”mÛ ¶Lý¤h]×[FtŒÆL X‰ÒiÓ4ãH•VÑ6ŽL·±˜ Û6.úñ÷ë3{Xö²d šLOÑä´Ð4-¾UýÅl0£‚ ˆÎ)  Åù1»»»ã¼  òf pñÅOj>°/ˆâÑÍ ÅdˆGÖo¼æM¼P†›²@¯Ye¤¾ LiÿŒH|•2gi¶'Ì>Â陛솄Ø0•ÇæºIÄëxÚ 1ÍÆ4a…Bû‘A2BF¦«T’š.ÐxmŠÆmØ¿…d¹œLS"ªFÚM¶ˆ9½½¢½…‚HV(Q¦U­Àp9«gªÎKäû‹Wÿ@£r"ú´œ'…”ôõQHM× ôÛàôƒ{¬| rD?AD¦ø€ ÁW xòÿ ¹› 8O¬ï¼þBTÉìý5÷Èÿ8e(}D´ñG>¬(ç]½¥ÞïoB2¥Ô±Œ‚LQ©˜~fÚ¶U(í¡ž' ÃØAØüw;šб˜‰þ) ŽÛ¶­ÒMT`b'3E»m3 ˲ð<(ŠÃ0®ýðïÿþï³}(SÆLÛ¶ðõ `¾ž¾ûn|ÛOžçQ V )‰‚R(&ËŒz‚ׯ_Ï–-[âp±­[·rñÅÇyh7lØÀ5×\úuëØºu+6l˜tÁÒXòRÇÜrÖ*æ=àörLàÀŸL}.¾™f¬¾ S×?¥É!sÚær‰“\§âX©oeÁ¹ŽIâlÕꈤÈt‘†Ç Iß3‰L2úfªžñ2íÕdH§6›È½1mËÈãrÝÆcí÷Ìf“z-ÍËM<¯½ˆ%)ÊÈ™\Nl·P¢Ì+^1¹s5˜Éþ9iò@:mºì[cý–R éýLÖ8 ¨ß€bD!0H¢N,D?î'?Љo>þ‚ñ8ðð7Pz/„ÛÀÜ'„3‚hègBôôÿx÷Bæo¡òà@+¿†Â߀ù à(àrÈ;`›`¼O´Áþ2hè?[´!ú#Ⱦ¬;ç!ü8nÒÒä~Œ_Bô=ÞúbL0º!ܹ¿s9¸?ƒòÅ ¿2 †àV ôI(~ìÏüep01¶­B¡›yõ윃„aH©T¢X,ûÛó<5Ê_1)fªŽV¤\1sL$MØDêÛ†1¡”_ãYÇ4M|ß'“ÉÔ††ô÷÷ãû>÷w7='p†™ Û6V æ‰ÀÎ Z:«;.\×kMTàS(¦‚¶•žžž1 ‡Jõr,n¼ñFúúúâ°°thØúõëéîîf```ؼ‰zñã}k¦ù4*¤ƒ×EøæŠÀï~ì¸õ§³Ý´I3Zß„©ëŸ!uM#0 ÏÎó–ïeÒAÚlGõ‡;ô¦y҉꧖“…£ÓßÔ2)‡k, è©e'©lÛ­#'&ƒ´÷æšHÜFMÐÓLŽ#ýŽ£ë‰ÈÒî»®')ÀJ%±ž¬¹°ÿQ³}j¦„™êŸ“ÆEˆòº7]P‘‰;!e|ÁÓAˆÏ#n¼A꣓ˆ¤²P<¡Å„èƒýÜóÁ;¬“ ?X§ƒþ'`žÑð¾ö;À ñ»ª·ý'`Àg/g‚ñ+à60Î+}í»à-©_¿&è‘´/‹ÿìWCé/Áói°3õȬ²ë úœˆ„,œæDê;m5Xï‚ü-`wƒ¿´!(ÝexüA°4Þá üz0ž"£eÕ#ÑBî—2RL19fÒ¶U(í3ožsÓ4Ç,P¯PŒ—™èŸáB WŸÇX–5c5ŒÆ+  … ¥$“5Vòù<žç-8án¦mÛø† ”`ëâ­¬ ׉A ^VR›ïû±˜µÐλb~Ñ– 200@__ߘËuww·µÓÑ M¥1ÇìÞÍ»ßýM„gD¡˜±¸þÝ~w9£Æ*&6ýSf ‘EGLÇ!ê”›¦—HŠKêß!qZ:‡aŽØ‰;m¥P2Ò †t4 $…©íh×m,Ì>UÌ51e¼Fk'îd¢o¤£ëbrÔSO0Û‡;eÌDÿœ²{º˜»,¯#úŽŒT±H„"zëë–H˜rê»N"|Ê&iÁ´"ÖÏ¿´ÿ —Aæq°¿ÑÁ»Š—€y ØGþf°¶Cöèh'ŠvY%àE‡z 04Ñ^iÊ».xÿæi§¢ü­Ô—J}}‡¤ˆ=`½œ^ÝR¨GÅu…ñA{Q,ãÿ3˜õ¿£º k^ÆN±oÛ×zÅÏ%çJÐóýàGÀÿ€õAèºÊžˆÖr°íã`¾G¬ŸËœžO1>fʶU(ãcÎ>;çAà8N\ D½×uë¶|!ŽXñ<ß÷)—Ëñ÷ (‹8Žƒçy„aˆeY”Ë娑™Íf±,+N-&£aä>Êå2¦i¶½œb~0ýS¦–VÌ f¢ŽÊD¢Z&Ñ’ËåbG¾¦i±_c¡1“¶­8wAUƒì`ݺº "s§~[)‚ù¾¿ Ï»bþЖ rñųnݺ1xsØû‡î|Çl7E±À0HD•%GîãeËhONTÈ?Š8á„Ë&gž¬`Õ?²ž‰G qÀtÕ—óHœ¬ý4ŽˆoW ies×GJL”\.©52†½>ŸÑõÖÜ‘„–vÉfE¤Œm'õŽÞþöÙ>ÚƒY¬½@’ŠOÖ‘¢HžDpÑHú«ŒkNË'E«þ]Ö8©Bô(8ïÿpàw bBô°ˆ)ý´_ƒùV!N¯ƒâ¥$éÂn®£å‚vD}¿‰è‘¾Gy/3^ æ»Æ87ò:OEéh Õw¤ú@Ö;€ŸB)팶uÓE×1¿PHRæ¥ÑOíßDÄKø½ 8Ì0¾öiB˜‰^Ámà~*wÖOùmbûa˜ÔIR( Åôãâ2»#èÍú¿Ñˆ¢?e|ÊÑÁýýýA@.—C×uLÓIJ,J¥¥R Û¶ÉçóT«U‚ Àó<ªÕ*š¦‘Ïçã4br›†a088H©T"ŸÏS,ÄqJ¥Rœj§åбF¯O$ ŒV.܃MÓRÉÉû’bò Õ†¸õ¬;yà‰0ƒú}ܶ…C%…ã8*2E1'hKPq]—¾¾>n¼ñÆxÚÆY¿~ýœÑ¿þŸ—)ç€bÊÑH|o«Ÿ|’Óöì™í&Í;~ô£Çؼ9Ã_þej¢¬YR@#©QÝ8ˆˆ•þ¦ õ××óQ)ã˜26ܦ,ª>•,‡çhi·Ëˆ’T*âÜD‘¯˜!dĉ=e„‡KäoZDôa“X4)½ì2hYŽ÷P(úˆˆ²‚ßï,(¼ 2/€u4ØŸ…òqàü5„'@p36ô/†ìÃPüýÄ@4:P©ªy´RÇÀ0DÔG[·=×´~LÌëA5¸÷‰ö„!p¶˜T4­uÿ±?lçóbó]Pþ,àCá1à|âôhn òBå*È^®'„ªè¥©€ …B12úDBSÈDö/#A@8mÛÆó¼XȨT*d³Y|ßǶízŠ_¯aýJ¥2l»R\‘Ž2YDÜ4͆ú í.§8¸‘ÂßH䦦 xÙeGKdò„  Ì¤ƒù4=,yt ß1?8û‰Ï§Å¹. èºN>ŸŸí&+r&\”þ†n »»{N *!pØöÿ#ÿQ¡¢˜zä­ý¬³–Ívsæ ò5' áG?:]#R „óÑbx!ø"#{/õúò&Ãë­L%Å6‘£¾§šÉˆsÉØ§Ò ¬ib;a{ö¼|¶iáÑT‡#®s"û°œçˆ4Њ"U•µ¼ÅBpþÂUà] ú¥ÿh—€¾J…ØÃ~`ŒEàž … [vƒç‚õà.( :ÊÔ]i&XÃÐ0’:=c/<Æ|L ø{°w!î7KÁ8¿~zõä>¢i£ì7l¨ëiÂä¾Óû÷ìAé ð¾Õß;ØO÷y0Žû‹"Ðï„ÏŠþ5ßÅ\…B¡˜KÓb´Î@»›2åD –) j(A@WWWÍ"b ÅtE~ÕUèÔëwÖ§$ÁÕ.Â|²Hª[½òù1EE¦(€ø¦˜"àùj/½HÀ=t?×-Þ'K%ñâÓÛÛ°¼ŒŠl%Ì+3É„•ù@Ÿ‹Ÿ9• .xÍl7E±€\Á,¡ÍB=°ë7»8ñù¿ üè@"„Lй $鄦9liœï|Q”¤Ñ™J”Ssl,Kœ÷»ï»þ—bø‡Qÿ¤HcÝ¢ ¸_£ ®?_wÎëà…~‚û ðŸ‰è˜Ïƒ™;ý«öAá}cM"akGoãà‚é» 434Í­‘ Ö@_-ÎcuGj¶‘HF£ž»BÓF¹çèĩԪ/í• •Á¾ (€þ8”~ôÀ﫺? ì߆¼'ú•i‚¡APo“ç%5] …B±ði.ôEQCû0 ñ<MÓ(•JqI±X¤X,âû>®ëÆéÀŠéàǯx"ÉA!–H“U#1eË$ãø²$¥7Óø$AØ …¦iªvÇË‹– á?ïóú¯i>J%ñ"Ô$^U«U<ÏÃuÝ ÕÍQ(¦Š+¨DÀbžxâ'ÀúÙnŽb³rå.à¸ÙnƼ"ôBŽÚu6æ¿ÔI™ËÏBƒÄ‘l#R’¹y¢>_«O“u#óLá|$ªOI†>Éú/r¨”Yÿ.Ó„ÊýH,ûR}™G,>Iš%¶-ì°ÿüÏ·ÌvSÒ!ÉP>Y㤞ڪTO·&£°«U!H!ÐóD´ŠtÀFjà‘¼Œ×Öw7Æõlâw^(ï4ÞV°û“z@ Þ!Ú7–ð¢'Ëèõ˜Ø»P=‚` p;Ø•¥Ö9QünÑã~œ—¶ÌwŠ{RÄTö …ba†!¾ïcš&Qáy^,šäóylÛÆ²,2™ –eáº.AP­Vãõ•ŸU1<ú†7pãá‡ã#ÌÕ2ÃSuÉ’éïÉ+–CÃX%¨(†EF¨âè“çYÖ-ÞÇ]Àƒ'<ÈùÁñéû /aâ8Έ©#Š™dÁ *ðÜO^à-oyq¶›¢Xà¼þõ¿â´ÓTʯvšÃŽ#wðó£wCayƒ=—…a‰Ëú ëZÖ{щÓéÄ´ËnGXãBŒ‘u%|„µ.‹p—BŠF2LJÖ‘ðH£.EáÈöieJõé%’”h¤Î³ŒºIÁš@Î\%&I1…¸$5‹¤’ºfÐnê°±°i/ÒÓ©ë­˜AÐàÖ´º "s!ɪÍi²Y±Ýj5™'GßËã)•’ýJç´â-²²Mé¡ßÒY«ëâÿbQ¼¸$‰¬Æè¡A4¼ …¬Ý"Å Y{¥DR¥Q¦=Ë‘¤ “)äh3ÃI”ž>ybmBÚ´õîEâ²ô}aï³yeÿÒ4á—XVc?íïI+2A 6˜îï¦)ú…Œ ‘ר¼7ŒT¹]NO_ ¦)/i.ìaBàH÷q)ÈÈ>ÜbÑ*ÖóDÛÂP,/£pÊeqÌŽ#¦FCû‚‚ï‡àž±ÃTòy±­ ‡ §­Âò#è7Ñ2qØÖ€þáÀ-༠6âç}ì±%SÖf…B¡P( IßóÏsÍá‡Oùve K…B1uìà•/AöÉ®¤ çHïv¨4kŠ¹Ã¸•7244Äu×]ÇÆ¹á†æwvvÎÅð…§°téã³Ý …B‘"ÖêP}ùŸÑ2xZŠrÄy6›¤åiN¼oY‰sµ•ç\&í/‡§àÑu±¾¬ž^?Äz©ãÉD‰#)Ä8N"¦¤ÖÓuÄr®[÷4ZÞçjU¬[*‰¶º®ø;í°•Ë·:NyŒ­ Ž´è⺢ÍwpS_irÛ8)'s³ƒXþ\»ø˜ ËMQWEF,47M')^^¬/'ÓÉé².bÎ?Ò¥xV¿ÌÒ—²®EঢJdŸ•ÉÓÎþV¡Í×n:ZDÒRµaì²Vó ctÅ •‘.ÓÃh õH‹FRnj‡ÜuôìÉ}/ŸOŽÃ²’…d”L:úFÞ¿|_Ì“‚MºM&Jاl¢u‚¥~¤¿° 8” \F·˜F‚ã`Û‹ÇLy`¡B¡P(¦ÇqÐu=.8Ÿ¦T*¡i¶mã8¶m7ä³¢ˆR©§oiµŒB1]ìZ¹’u㬟Ò"¦‘öUÚD•cí¤­.ÇÖɱ†òµ:Š’yrYï›rMó¶l;yíÕ4ñ]ú¹å«µ O·Gf¶•5ôl;)MÞôë¾ã$Óäòr;r¼‘ÌŽ+_Må8Á|^L³¬$Z^¾¢x•÷¼$@¼·79NÏKÆ;p9„¡óä8É9Ô4±}i:F2+håòG¹ÿþxÓ›kL+ÆfoKŽ€UÏßÞ¶dp]Š(ŠÃ(Š” ¢˜3´-¨\{íµÜzë­ Uww7×]w›7ofË–-lÚ´©­m ÄõWº»»[Γu[&B}ÈnÎ>wÛLŸO…b^3ZßLÏŸhÿ €£þb?뼿õ2}Á=’ƹ],Žì”VåHNÕf‘%½^±˜´)ýR(-̦mÆ‚J¹,œ«­öY,ŠÔGéQùéãÍaœv°¶j¯ü_î÷:<•ÍJ¬Õ(×iŒ’¤¸tÔš&è&\ëÀj ̪x³ÈeËU×…˜²#ÏTŸDH‰€C|¨˜‰°"#_òá&d|5f¦»6#_–Ÿƒ.‡ä¥•b±~‰åømËÙº•¢¼^Z9MÚ1€ÇS`c¢Ž{œùèdý”Ñê£4cšI­HÞHåß-¶cïú šñQ ¯¿=™_.‹ûƒlƒD¾Ñ¥£èäy—u]ä¾Ò5hä›äxÏAÄ/óC@Â×Bv^‡èß6`‚õ3xÏÏV,(Aeºm[…B11fúÙ¹H‹&iÂ0ÄqLÓĶmJ¥¦iÆbIEd³Y È_ÍË(0=ý3ŽÚ¹sÆEf‹†Äd“Idv[)4g£ ‚$«m×™TA¾jÉì¸R,Ig—Õ´$»­4 £(™&Åü-ë÷5¿;N2&Gn»RI9È€m)öÈÄÍã–䨠þ~±žLl;±åÉ´p"Åù:†Iä¼4ÇÃP,#“UäóIÂÇI²ê–JIr‹B!ù=2™dŒ¦l³ÌæÛJÄ’u#¥ÈÒß/öÑÕaYŸáî»ÿ‚“Xœš6rÊ 9ä„åøQ ¼ÝNÒ…Q–j>/D–—B(eàĬ/Š4`EàŒ>’­§ Óá¸|Å€³Jðœ !—$•Ø$#XÞþöë'·‘9ÀLõÏ4²;ú·ƒ]OÛöónøKŒ®]hÆ ‚k¯%\³È¢¶|3›suÔQy%IÇy,þG`„ ¿ð ª¢¼?´WÓÓÒN¯ôùoƒ¤Ø’É4 Á¹Ü¤*ÆË—ö¸IK@9X ÜQŸf îuß;Œûz×Mx_s‰™°m Åø™gçBC×u<ÏÃJÙåžç8B8-¦”'òÜT4LWÿ €Ãõ+Œ·¿}RíKGhȈŽjG’H )žx^bNÉl¶ò»4áäGÖÜ–þa™!Wf²•‘RÛ” Ls¸¹&ùÚÖj\as·•¥åt½Éô„ÆìØ2ò¥ZM"Väütòˆ4i±C&‡cöšÛ˜6ie©Ãt›äù‘çW¶O¶_¾Ö6›Ë2RF¶KÑG¶½Õí¬9G.'“h¤“NÈ"é«Wïà‡?\>©ën®0“¶íâkàìŸü ÷¿t%«ìZf0 MÓ”¨¢˜[ÔÚàú믯]yå•cNËd2µ­[·Ž¸Gy¤vê©§6,ó¶·½­æºn¼þwÞY«Õjµ­[·ÖN=õÔÚ#<2jÛšÛP«Õj…Z­vì)»k…B¡Ã›=ªõOÿl7¤ ¬Z­VNµ¹ýõe2®¿þúøº¯ŒÕ7kµñ÷Ï;ï¼³výõ×Çß«µZÍ®Õj§­~¦¶é·¿<|…þ~ñQÌ ½½í-gYµZ¹,>òžjÕjµæÕ“ùƒƒµÚÿTkµÅz­ö±r­ö½µÚ`­VûÙ`­¦WÄ2¶]«}£·VË÷×jo°jµ£V[R¨ÕÌZ­¦ÕjµJMÜÌ[5s°þiƒVψùÆtôϱÎK¥"~NÛ®Õ¬7×ÄoQ«Õ~¯X«W¨Õj–UÓ÷î­Ù5ѯ©‰Ÿ®PÿÆÑõÙØë”S X«Vk5sªOb¡ôÏZMì ··V3ŒZ ’{¯<å²ø{vˆÕkµZ­øÑZ­rcm¸}`×jðáZÅ®Ì̉FfʶU(feÛ¶¦Ù¶]èµb±X³m»aºaµb±X3ë+ V­Vkƒƒƒ5Ã0†-Ÿ^F1yÂ3b:mÛJ­V;ñk_k»-Å¢0ƒ ñÚ£ëâS,&¶p¿øþ…ÞZíDsz^YËe±bQü­i­_×z{Å«Ö|¢Rçq¡P©4þ¦iÖªÕê‚yF̤mû©þZí½Vë]ñ©Ú}G~^œØÌœò—#ÅÁÆtض.J¿~ýz†††¦uvv²{÷î× »»»!Ê墋.b÷îÝôôô°|ùò8”líÚµ¬]»–žžžq«°è¹çænn½1[b Ò¨ÌDtTÿŒw_b¤¸,6 àÔ·#SõêËÉÚ "•ÏlFvË6¦#Õ}â´5 Áh}˜’þ»}X¼ÿ9N~ë1ÃãhU €™¥Ýûc±˜Ä™Ë˜ï"Ãûuºð‚¦Á2öéð —õ+ë#å¨ÅwA.í‚‹Møð)_l/]{E.,Á£%X¦Ã̉{˜GÌDÿlÆuA_Öë ôà÷ÄôþvØ~dÆâÅ„ˆÛ}?âñP2ãØO€øi'EºÆÈ<Ç\ö“é¹6”I¶eÞ¶tÒmCî,K ÁsœÆ<2Ä(ç\n¦*ËÔð.Ãöžílë™ÿ©YgʶU(ãc6žãE¦ ‘†¸õʺÕª¸ §‘©fä¨l92>M±˜l#½|«ý4—ökƶmºººâh“tûtíT™E‘ŠLQŒÉtöÏxþG?‚Ë5×ÐQ ¶-"ZE%H áFX_÷Fs?œhÖ빈¬u²PXHÇÒŠ™´mïðAïãåCô>ø0h:ì#Š"ŠÁ;¿bþÑ– ²|ùòaBIsž¼¡¡!úúúFÝNwwwC¡!¶lÙÂÕW_M__ß°m._¾<ÎÙ7Û¶m㪫®âÆ“”.÷pÌÑO¢M·ƒ%")Ä,T=5­„H_S©/+~^ýoù ,Â#5]q!¬·ÏNµÃªÏ3Þ°f\Á'}ë­·;j©e³õíèˆT?Õút‹)ðœ«ÞY§!¨OÓ¦¦-W]uÛ¶mk™óu>1Zß&Ü?o¹å6lØ@¼~?|ô…#xñÐc“"îårû5 3ôŒÊkhï-´*DÙT ê)ÂZ,»£_ôÓåÀ{ ÈÔ“àþ® ï,ÁP : „¨b×?%Ä#A>~¢ú´ˆDßÖIGãf”ëóŽSO¦A'l¶‡Z9»dµÍô:Õz:¿4ùüˆ)åjc½ìoÞ¼™Í›7sjýxç33eÛ*3…²mÛ·m'ËH÷úô-v”ÛmL«G`;ëµ³Œ¦i˜¦§ýjNÿ%Éçó J¥®ë¶,d¯˜}}}lܸ‘mÛæÿ`„é´m?úQÖyä°ùa(JYì¼\nÛ§^G“á?ø÷Þ{¯²mG@Ú¶6lhjîö °úÿý$:ŸmýÞ¾ïÏÝóŠ9ÏÆ¹å–[¦Ü¶=¤….ºè"úúúزeˈ˸®KGGGÛ Ü²e —_~9ÝÝݬ_¿¾edK;ÅN8ᄆÎ8Ã]w'/¨xg¼ô%”ƒ[ÿ?SŸïÔ—-!¼C^}^€J'Ÿ__×£Ñk$£ý\–½?aÇÜÒcɦiЇŠ0&Ö¯__‘¾mY*õõõ¬]»–uëÖ±víZÖ¬YãJX¿yóf6nÜ8lY}}}¬[·Žžž®¿þz_€©«˜¼©§§§¤Á … ìKÀ+ÏÏ»‚™%ïÉÑ‚7ê£BY¹xÂò¼P³£•°‘&ï‘&?Poåþ.Öz”GG}R ï‚¿þøkਛàÈ—Ž°äÜÝ|òãÇå ¢ Þ4¨§Liþê6E¿ŸÄHîŸÒ·Á{E÷¤Z‰öhÛÀý÷çN쇳U•Ø>(^¹®÷wK‹÷3WÆT›@Vé¾­ £cBÛÎIL$!‘HÇK†ûü>²òb‰Åb´—ã#LY*eŸ{÷î¥ñÈ /¤d2…щǂH…B1º®£i‡ªvUÆ íÛöÙtœð<3>ß_òë'‘H iñI2N˜<”CeýúõÔÕÕ‘Éd¸é¦› ÖÕ×׳iÓ¦²¼S®½öZV¯^=`æ]CC›7o.XÖÛÛ[–ÚYÌöî|´ülòB…èw)Œ/öÒPƒ¥¦æ–ê;j¹ƒ5âÁi¾*NŠò ˆ@òypßç½ö¾íEÎvŸ¢ýØ[P7h¨&E9=*GÍ4…¯ýÁšÕ¤9ä5uõÊoÁ{­x¯cõ1«œ!5¼fQ5åJ/WMf¯ÙPš E–Ák:²¹²T¹…MÏD2^e㎦yS;ƒ¨Ða*n…éV¦ Ñ·aäLhÛ9‰Qa¿b±XIï”bÒé4¤R)¥RöùÜœ9þwR6ëÍÑõñSLÆàQ-LZTÞ¨ŽŽŽjWeܘ¨¾íB^úÕKœ?çý42ù3V>ƒ Œ‚%¥_»v-k×®-xQÔÕÕ•­FnÞ¼™¾¾>.¿üò‚2êëëijjò“555ÑÕÕEOOW\qňNÈÞ…œCo¨¼>”§Co%…7ªb‘EQ¢ÅDlôUâú ‡EáF·ÂÀ`ùJm<%p©÷«‰JH]#åÍ£îS¬Ìã zese¨piÊ‹EEPRåO¢ïƒ¡ls¼ìÓfÜÕÏ—ö½Tµó´m›l6‹®ë˜¦IKK ííí¾x‘Ífq]ןu§rÇô×?3â ŒqòùUÊAm§r©¬Ê-sÉëåÊñP=M‰ÀïÊq”À:^,›+CÍŸhÌí×ø]9‘*Tz1‡¼#j6·ÚN‰>ªÌ4y§ËbÎ༠õwñãlš^Êíè}£ºwUÃ0|´ y,V:_Ë$b"ú¶‚ Œœ‰n;';JP)'슚„ÔÜÜŒiš~µ¹¹y@™âÅ25©¤}.éëóO¥¼_!œÇ'¡e"û¶Ï3ÝýÔ–\oY–/Λ’èH#T£MäÒÓÓCOO­­­Ë×®]ËúõëY¿~=ëÖ­cõêÕlݺ•õë׳páÂg÷–W¼S!¹ ÃNMº$Œ©¦jG Nan” :Ð_ôw©ðfå „œ(ùo6=j\¼‘³jL]®ÃÙ&0.öùü‹¯p̼éïÕ…„   ëzAˆ,Ó4illD×uß[#úBŠÊUF±mÇqhllô·ÓuÝ/_…ãR‰ú9Ø»H .Êó#=Ä ãhC…Ã0 $“É‚k§Ä%UŽeYþù–Mðú &bÏf‰Ç½4üêåQ]»01Qö鳘íýªÑÛÏÆuÏ.ßÓ1‡ å5’¹Ao“RV`×ÜeØu:ù×¶z½«ôZÊÃEuTs "K6ãå{±É 1ù¦ÀÉ-S©ÇâxbŒr8UÝ5oC‰5J¯WsŽùæG‰Ç¿ñ[ Æ«s8× ´d2ž·J<î¹ÛضgÇ“t4c¢ú¶‚ ŒŒ o;'!ýýù¬âб¦iúƒ[Áí‚ëƒËKm#L]*eŸ.^È/oâ›7h’v?¡bLdß¶384›§Î\Ì›J¬w‡H$"bŠJF%¨Œe|ƒ±fÍšššèééñg'Œ”=<ÜqˆKϤåÌ’Ï¢¼T„p3R¡±¾kƒ¹Zì!Öç°}袻©¶ò3œmÂøØç‚9;ØvÒIT"•¢?”P‘L&}Õ+Ï Çq >•‡EqŽÃ0üІa‹ÅˆF£~|è`˜®‘’Íf‡Q*òÆQçœqì°Ø¶®ëf$*±F‰,¥DŸU«VÑÙÙɪU«H&“˜¦é‡+”Ôò²C‰•ɱ{­Ú5/&Ê>v+¬8î ,«–—u0:c)”à¡~/f°}ƒMÐù±ø4•—‰ò^±É§Se(¡ $•F9:ª9¸6ž¨ÒN>„Ysnûo]ñÏœrY~ì|¯‡|š±45ÐmÑuÏ3%õÜUT$Ëò–Ù6d³,íï‡c'¿}ާm ‚P>ÝvŽ•¿]Ó¼W¥iz¯QÓô„UœJy¯ØHÄ{•êúÔ ±(L*eŸ6°h÷n_Pé<.A&¶o;ïè{ö³4\ÐWr}pR¨ „ TÊa¬ùGN=©·ô §šZªrqˆÈ) ÅPÏH`ªó÷–|&FçµUkŒÅ>Ÿtáu½½¼ô–·Œk2™Œ/v(¯‰x‚yOÆÂp‘3mòž" s˜òÚÉ{Ø(Ôœ…J–öÍ™ƒ»»Ÿ'š¯æ+ä›ÎÜúXàœU˜(ž7N,·}ÕlÕó¢–›f~t0‘ð–57³|Îøä'«]Û A„A/mŸŽã‰!–åýŒÇ=¡<Í9“ñþŽF=ᤥ%¿ax9!‰|‚íl6ŸÆÊ² A¨uFcŸ³àþû“N‹-B¥¯¶ó¤Oï§û ÝÌ>evÉõ‰DBBC ¡%t‚ÊX9ìÂÞgžA;#Ðzªx -xq8B?½³ö)w€Z˜:Ìù3œ<% /½tÜÊŒÅb~x)•<]…â2M³¬8Ï@ÙÏêx>Óétº@H˜hÊõ¬Ë9+QDÝ×u}$‰`Û6±X Ã0ümvïÞMcc#íííd³Yb±ííí¾¨“Édü÷‹ÊÛ2¨§¼‚FŒ}+\ñÛnÃ}üqX·®ÚU’`rÐJÎ]2È{‰qÇ÷x|ÑP=ûÊ“%“Éäb2M³ 7’ CöæU{ˆ^µŸÏŸ¸˜ÝŠ7qòQï\ò^.1òÞ3V®Ž™Ü¶U›Ï íXrù•èìä¥Ï¾ZµJáxLäý9)•¸I˜ÇÓ”ãqïg$⽓IoÀ78o¤x¾Kñ8’iæ=ZtÝTb1¯×ÅsT<"‘ð–åÒùÑÖž“ÍzeÅãùWu&ã­K¥¼ýÔëÛ0+n’I“ó¢RX–åçŒp]ןEﺮ?K\å[Ðuh4Jcc#étš––?_‚eY´··ë´D-%Ög¹«ö çª£¢\·Á`™ÂØX<Œ%ö¸]ËT*…mÛ˜¦I6›¥»»Ã0ªæñ1já¹ÏNŒëº~þEPLQD£QR©”ÿiii!‰øùY4M#•JFý÷¦i%íºëø.Nçôj_ÆšÁíé ñ뮃Îα8Øc/b€'”Ê1ä‹–Å+_ÌU;vÀ¹ç’H$0MÓo3MÓ¤¥¥%bÂÛ/û¢¯eY~èÁl6‹¦i$ Òé´îÎ4MýÃ+ÜúäJæ\œS‚u³mÛo㒹Ѳž¨¢rÆÄðÆÃ×8À sæøÎ–¥R‚M(ÁÑ4]gûG? D—Â8àR®T=Ò^_Ø"ï}«ç~Ï’›$cN%1Òs«øz*NœW¹çœ\YéÜO7p õªc)¥Q)¢z®ŒL®¾Ñ@½]òžåêáÆìsÈ‹@ªŽJYT‘r1OiTq•ÑSuÍTl¾xîg:W¼«Z"·mù¤Iê"õÉ\Á„P ò9ÿZÈ»ÚE˜/L‰]A)t™KÊç–7ç¶IÎÏÍ­Ï®‡ÊHþÞÍþälfìtŸ‰†ãx¯»LÆ 2™|Äîqˆü *žSâ8ùã[~Ø£dÒû»³3/^tvæmۋШšBÃðD’ ø¡Ž‰xë\×;V$âm¯ëù´Yš–h”'M0´Y6›÷¨Q‚N2ém£Rq)Ï×õÖ«ŸŽã/ˆª‹êbªý”ø^}§P¼ ^Kuì È¥iùðjªªŨãF~¿lÖ;¯Rd³ùk¥®u°.ê8ª¾ê<„Áq£¶<ÊâÅï¢RQ‚ÔmPMªèÔ‚0r k>mÇ8Ž”ÞN— àºåŒ-DDI/÷ixîBæ+HoìÓ¶½Óà3¥žõL¸®Kcc#mmm~Þ%Ào/t]÷Ÿ?Çqhnnöó.íO¥hÃ; z]µµµÑÜÜì·ª-s§ MWÒé´Ÿ)•JùíóâÅ‹™°èx|ÏÝzˆ¬ûsßó®¿¿ßÕöªí‹Gn¾ómoC×4RÀwÝÅ÷fÌ`þ¼y8gŸí‡+‹àÃv’°É}—š¡Ž9f‚£qÂøáâ âŸï‡“4hpáÞ”78Ÿˆ€kx7·oôts·A£gÚð—À»s÷ØÀë?'È (jÄH ÊýI‰:ù|‡üh“ŸoŽ4žà%Ÿ”H‰1Jd1sû6ÊÒrÛfëuòbªK,·!Rð!WɂޡV®nJ;V‚:%Rèx†£Ä;·O°k¨„ëò1ÿ”˜‘$odê:ƒg˜Áî‹:V,WžzœÀ= êÝn`šòiæî·B•¯Ä°¶\½Ô}Sës¿KcKyõ²WGùPN]rM --ÞOMóý–ªS&ãý 挼hdšÞzUOðD %¢˜f^¨°í|h5ÛöÊTå¸nÞ³F Ž“ßÞ0òbM"ámçC·)1Hå¸ 9ªåM¤Ï.ü0:AE…†²mÛ÷žun !ÔwœÔl~%˜)[WaÓ”M' _D–gct<Ö\n÷ê ÷  —•ʉ'¶mû¢&“Á4M_DÅbD"_(‰D"X–E[[[Wf&“¡»Ä4âl6[ f¨Ÿª-S”òì >×ét˲°,‹d2‰¦iضÍ-ËŸç\îŸãÛ²,âñ¸ê.NÓÜÜìO8P“nÙ°[6l ™LrÆþÀ%û;ðÞ›;ÿæoxª¹™/OŸîOD‘T Ç0°Mol·“¹dÔ̰Z𨛸¹ÿÝêÀ6,Ñá;&LËÀÕÀM9÷„¬;\¸¾Ù‘SÏŸš&OÀÛ’°Ý‚:ð¯ o´®­-ƒÎráZ ¦C[®Ï@Ö#™,, ÚrhZ~y"o4àps #Ì\=Ô6: Ùàj`çFßb®œ{‰¦C$:0 ™ž«¹r›#0×Î^©)ÝzÀs%¯ÈÌ=Ë‹É Áfç¯R{õJd½k—Ìí“À‚‚M*å•Û–›:o‘ÿîH&½º>=0ÂçZ`¸ù)ýAEÅÈ@4­<Ïzåiäâ %CuO#¹Ñ\Û¨7“Û9p|Çáàœ»ñ"¡\²YOHI§=3Ò´ÚÓ•WÉDOac‹!Eð3¸ø“X $ñxaùƒ‰BÊKD 6C• …uliñîµút&@WÝP5ü æ1ª®…ãxÛÅ/åÑæïC"á Lš–÷úÉOæNÜMª1l ç¶zœHåìÏÄ{;¶á½=³xú´P”ùÈóª%^-‚PÄ‘ýúQî%?›27~k›èÞÜL{{;w=ôg^r‰Ì²¬6.°8K,دé:üØ„fÖžOõ¬Î¥pTPM_Ÿ–€÷ë ålAÅ$Rd2ù=ñx~ÝÖìÀWÕ/ÔõÂiÁ‘|$?Žä¼>Xµ*ß·TeÚ¶×çTb®{žLÓû§®‰L>ƒw4 š ±Ü”nRð[fšùÑËöö|Ü%5\eðOCØ£¼mZZ¼þýW£Íõ÷½:·µA»^8–HxõÏd¼õJ¸±¬üùEˆÅêÑuoÚ9 ¼žš Ë;¯D&?=ÞuÅáSFjY…"’zÔ4x×õ–½ßGÈu9ÿÎ;y©E•‘ ZR&º^Z„ e£qÄ (C•¯<‚©K=#¥æq›¼¦ASÓw€7WâòMzOª¨ 䃷K9êä;ñÄ–ò†ê«ô~‰¯ LUÞeÀ©Ú«´­ý)çR(¨èº>î)a¼™T‚ ÀYQýaÝsi§MfaÆ»`/¥¸×ü]õ~Tv¿€!ïhjb¹a°cÖ,–g2üì™gØò‡?L&¹äž{xxçNÞ±s'îÁƒÜhÛ¤Ói6mÚ©çlßÎÿæ7|lÓ¦‚äÜZî8ÿ|ì±ÜñðÃÄ–-ãÜœ`ÐØÒ‚ùÎwúƒEmÑ(d³´··Ó»m‹-ï£+•J7 ¾™Û/ª¦º´´ä}”“É|6C°6˜iPË9±º®÷ñ›´ñ¯“ÊB˜cç~Äj5À­<~ÔÇkàCQωSG'“,W¼Á^¯ÚW-òÆùüç?©ó-‹z×õÎ)85Èq¼ß` Ýœß¸®>¤s¾Ô†aäÃe2˜*3¤º'š†æºèÊ F£„°2©¸7¡ñ†/[ðWãó[v pñ'?Iww7¯Zå%oôÑ|’䣿åTŠg–/÷¼SŠÊY|¶ÔqrV_r]Ö»®?ÓTåzM@~°'88¤Ö hh•M$’ÿˆ5ŒÂY„ÅÇÁu¥‚}|½O×óuQ`½J ~mKõ,5mè §%îÇ€ë¨ÄŸâwŽã}Tæ>À5MóB›¤Rùç`Ù‰Dþƒ4ø2on&š›/3àËÇÝ]ÇãÇ?^ööÙlÖßä8ííí8Ž3>±ü…I‡²Ež¯³³Óë'”Gâ§ðêšCD·>«WW¥JÛPó£{_dIÝ+œzÁ©eï£ò¥¨Ðk#<¦&Á¼Ùl–ãŽ;®ÚUª¾Ó ±³oFŸ{Ñ„SåýRyKTž-Û¶ýpXÊûH…r+n#'Ó쥥˖±gî\V÷öùÅTW屓H$p‡7~ðƒ¼Ë41sùÁÔMÓ8Ãqèß½›¿ß·ÏŸ19ÿ…È.\èçäV¡+ &l0Ôý“I#D ÃQÉ2x×vˆgÂ&×=ˆÊ+¯ŠUMUNb Ã@Û¸«Ä:Ý0ü}T¹:øádUøîÄ lùg(˜†kþ:’ÎÉ•g–+_éhî…±ëu¼0·êoðfgí‹_Ä9ï<‚_ 6ù<ô™Üï‘\¹ÉŸÿãï$StTÕµöÓËm'„ÓÔD*WV6Pw=P/u\M£íä“ÉæöWÛÙzº­­ýý8‘ˆ·þ´Óˆ&´|â0k:ùxþ*¤ŒŠ¦rØ'½©‰f•*Wï pêúõ|áàA„¡qœÂùj‚ TÛ¶y÷ 7Bó<ãLB:Bi:“ÜUˆx¯pïgpœCMàTNñHpr—ãuˆ‚7±Ó¶IÂ3¶àµ‡lÛFvÑ"˜5‹ö»ïÆÈdhnk#†÷¾Žá͵HÚƒ’\´ˆìÊ•8äÄšï|÷ñÇÑ/½4ïŒ*¢&•*ÇâëJy?ƒ“dU²ŸRû¨è.à-WÞ›ê¦Rùím»ð~¨|dŽ“¹ŽdL)óÊU÷D…øx?ý|k9ÔÕDMHV÷WýSeʸĘY Á©Ó÷Qjú†S<9ZBȤT¶Z°tîóœöÓïÀ%7ŒK™Á¤ñj@×4MR©Éd² ¦ûh8„ D5ÈÁ†UÓ¼ðC5ÖmmùŒ…êïXŒ¹]Äþ‡fÁ‹/ò 'TûìBÍžçæpöчÊÞ>‹$–N&à ['ííí´¶¶V»5ÃKËúIÞz+\sMEÊWẂBÁâÅ‹ý‚†7¸åŸ©–‚d€Ì×¾† ´]k?‹ßÑG“ŠÅüsÊ._N"™$>k–í•õ6“O ¬--·ÜýÄ'h'/¨¥rõû«={`öìáŸÑ)Že í8/ÂÄò«_MãéÙ‚¯^›Ÿ Þ@x*å}÷ÅUÎÜ`ÅàDL&<-#¯@g³Þ‹`•¹Påñdþe}Ä€íY¸ x£ w:yUܱۜ?‡ïä< “I’xíZzÎâßùÚ/ïö^Üñ8~X×%öÄ4Ÿum_þ2Ó¤±¡ÁoóÞñ´iÓ0î¼÷Ê+qçÏ÷Ûwî\"Ó§cjVK Æ/~æ88†³oæ¿þk.ü¤6PXRž›–å]Wu•¨¤„•â¤Ršæ jÿâqâR•$+Œ‚R,þ¨°öñxiq,›ÍßgMó¶ ?÷Å­‚ÜcàW©É¸ÁóÊ•ÝÐÛËŽsΩ¦ Ô{{öqÛ±fñ‹‚åƒyè BؘT‚ÊsÀ1»ž`×_céß|pÌå©]×uI&“1Õ'ÓŒØ)O93ŠrBÚ» ƒï=ø «ª}!gÑ©ó©[~¨ì†Ñ¶m¶´ •Çú),fÿè²²–‰ëº~.5€ßÖÖ†mÛ¾€Ì2yóé§óægŸ­è}ˆF£Äb±‚AÜbÏÚt:M&“)xg¿gÁîÿÅ/ˆžsIÃÀÂ|Õñ}3äÅ•7<È£[¶ðþ£ŽòsØÈL³‘ãÞóZ< p¼gP–¼EÞ¸L o0¿Ü‰òjÀ¿ÔXð`ÁZÕ`|)Y,¸LüT"‚Y´Ž¢cá¨ã%ö1‡ø]m§›`JÕ5³>ˆU‚o¥ÔgøáV‚ÿ­’ «ã•òâ¬Gd’÷RÊ«HÑVTV£iú!b‚e·S衤öOêiʼô¾ûXÐÔ„08¶íÍÉ|:AgÏóïû] Ž+CU9¥T¿'«C{g^½Ïâud|—Âd>ÆV"·M:÷» ¸qˆÄ½k7p«ã½L}WNlÃkˆl`E ¢YÀŠ‚…G¹_õ×mØ à.s÷/A^ÅotäÞGˆ_ôtýè ÞHêIHÈ«›ù60žX ih¾új¿]J=œ›ˆñÐ,büúà?±õçùdOã‘™dÌwa]ÿopp:ú+à¾ìÌҖk:8ç›Dþ²«Aïc)¸wFÐ/ôÜ5W³.ÀŽB¿§Ûp0î©ý‘Üz# D±—{ç¨}ôÜŒ÷0hKã¸ïú ö¥‡1¿÷ÿà¸ÌÏ•›Œ\‹®QÕÈ+qëÑl^Qî¹JÜrÉ y·T5sHg`®·„·)©\9‡tØ—¦û[O±óÏÕ6šá‰Î~6>~ò¯|T„ZaR *¯è°wÙïX:ãkcŠö¥r7è¹Äå*î¸$8J±óÄEP†îß’Çi.£at‡d2‰[<+E„бÏ9'.?¯Â0¨™¦iúùP4M#›Í‰DüA}Ó4Å-H0,B…(G¬Vù‡‚ýžE¼WÓp, Í00‡—V®Äœ>ÝËs“ûÊf³t½ýí¼|Úil|úi~Ë÷ÕïŸ79ÂGÏ?¿Ê¹vhÞ÷’6ð_ÞØ€š[‹]…¥ ÁÿrÉ 5ŒˆÑ¼QF³OzûÄG±Ïh$ß‘¾á”4’qzƒ¼ÇL)J m:£»n‚‡x§Bø8þø¬XñpÉ@5¢ Eóî‹jнï…›Â{)šäâ•ë-6N¥ƒ(ù‡›y (òñ'ƒ¨F«ï…kÐo™~'¤ÛðÕxCÕ;íÊu4m.¸7€¶胔éÁy2k ó^ÐΚI¬ã´ÿŒ#8Ïy¢Bó{aÕ yœ¸"‡ {%°œ0+w™÷€6´ó!ºì/€³ËÄè6±ƒQïU1ûNà50ƒµôÃà˜y²g{ëØ§£¿î0ëÛÈÚ|Ð5°^ã D^€È °sQÇ2«A¿"Y02m¸Dè‚q%XçƒqGCæ0˜ç€5ì‚vm5AÛ ñÿó`u‚6 ì# ½¸ìyÞÍ:jó.xâåJ=Þ“Š; <‡_=<`mÛ2$ÔUTúúúèíí¥¾¾¾`yOO===Ô××X7Ïfá$Èû²§¼dH¢B˜J f›0zû|òQXºû™a·K$d³Y’É¤Ø ” ö À¹pÁë´qËl©ò% ?±¼¦i~‚y€x<.³ŠÑ4/eUÔKe8T®¸ ê¾Åb^ZÔL&Ãák®aËý÷ÃÓJ¥ˆD"^^œTŠt:MìmoCÛ€øÂ—¿ÌïŽ>š>F7] ŒwßVë…[¿ût>\“05Í8ýdµ«ñ m§¦ÿkÚ¥0—Ñ`óû E0äŸ ‰§ö3sËUYª|5Öô:SË‚áꂌJ‹•;†8žÊ7%?Q¼äu&Ÿo)JÞS¯Ôvn‰eÁœP¹ñäAQÓãäBÕ{(T÷)蜠B'¦Š¶ æ¬r)+xov϶w^5ªÆÓ>úÓ},Xp ïtuÌ¿Y¼"ø¹T±ÕÃSiëwÕà‹9Ê;f°}“䌵VyPbx«“—xëÒWÁJàmž}X@raà³¼-‹½êéä‡.ÊyÅ̂ĞÖcŸ™ó¶òá-³sráCöô.ûlÏûÖ™ÎBˆ,ôŽÝ¼?\eÂÈybÎØŠœsѹù÷\f¤>‘83svþÁ|8ÑÄ»¼ŸÊîÕ¤ o¿Î^pê ö]ï8Ö; ;;g§ï äkn1áè]ÞQ©ç¥ TbÜàÕ— ¹ï~zæ͉Eë4M“ÉìBMP5AEÍ~\¿~½¿lóæÍlذիW³uëVÖ¯_Ïš5kÊ/Ô‚ýž]R©”?Ëg‰05)e›06ûœ³x¹ÃøÔ°ÛŠˆ)ƒS û¸ùG°ç¤ñ­§eYD£Ñ{þ.bÊ 8NÕÃ0ý‰Çã¾§Ñ]/¼Àü‡Ʋ,Òé´ïa˜ÍfýýÕ@Ðô;xiÝ:¾šN“]¶Œó—//k°–Ͼm&ûgAv?<Ü;ò¤×*ʉúݲ¼2Tˆr>\å–5ŒüdÞTÊÓõ¢Ñ|ÞÙ`„”`U¸r•×Væ©ëùcB>̹ ɮ°+‚¡ËUx{E$R¨9šfþ8†áEsQu·ŠFAÕ+G»­Íû‹å#¨ÜÄÁ\½ªÞ‘H¾®jâd4 ‰D~ÿæfo ¯ÎOƒaxû«\½jP>‘(¬k<î݇\Ú>?´.¼>ÍÍùëä8Þòt:Þ]×óË!2>x]T>^ËÊŸ»ëze>ôЩœqÆä d0Þm§²©±„ûR‰Á1^=ð{Š|¸<%„¨‰õŹwFPQ JDQÑ‹TäuZÁœK*7‘"(¶¨õf`»âð€VàÜ‚9›šÉ{Ìs;ËiÉ-W¹’Ì¢í4ò9•´¢cÆrõpUx¥ÅÛ©rZrëV‘#ØBéð{Ũk "EAÞÂÔWå*R÷ºTK¯B;’»Ê;QñÀþý#¼ãáf<íóðÃûyÃ)G!¦ÈLÐ%oª}jŽc—r(× ÿs²èw%p˜†öLÓ Þ® ‡¬‰'²%Ž£l5h/J½«8œ§rTÒëòbS`¶·}œÚÕá]Ïñà)ËÆïb‡€ŠŒÛ*^{”ç]4`±úÎoE!ìLxOyóæÍtttpûí·³víÚ‚u6l`ãÆ455ÑÕÕÅÕW_MSSSYЧ,½r?ŸqZ½tzH6›õc} ÂTc(Û„±Ù眅/rLÝ€ø˜A‰º®HF-Beí`ϳ°hŒÇáŽ;î`óæÍ\pÁ´··ûƒê®ë’Éd0M³`Y*•Â0 ß3Ty±Ftª-Ë*HtžH$üI*_‡Ê ,S…ô*§‡Ê÷¢Ž«ŽcÛ¶Ÿã)cÛ¶/¨z¨pgº®ûëâñ8–eùõQ®ìfE“Ñ¢B·9ŽƒišD£Q´x¼àý®®…šÙÛh+WâÜx#o™1øÞÒ¥|²Ú'3NT¢oëüù Ï~l6ÿ>´•Ã×ÁuóysUNWÇÉ‹à Àkš7HŸJyya»»½AaÛöþ¶moÓÌ 0à•‘Hx?³YoÀ_åõuÝ¿ µæˆUùêgñLËòÎA‰ ê\7/t˜¦·¬±±ð\U^×óˆBK™~"‘7Ôµ1 ï˜*ß­*[‰8*?¯šw¥~O¥¼z‡Y·,ï8ííÞïJÈQ‡JÚÛóçÞºh4_¾º¿*üûîÝ…×:›õî_ðž ŽJ‰+àí“K X‡ù÷¿‡ ^ë¨.•j;ƒù™¬ËýS!øƒË‹w1ñ&–5XÔ•x0Óþ‚_»ÁTåzG=PÔÀgÐ¥\‚ç2Øx9u2ËX6\9¥Ž_îµ꜋i‡+s¸ë÷ƒ?ÿ¹ÌZ…›JØç³/ÔsâIûJ'ЪF0·Ùx0Ø'K)ÛQö×9È>C½‚Ç‰à‰¤Å¹Õ‚¼å¥—˜ýÐCðÖ·ŽãÙV‡JÛ*æœ ëλ†Í}ß°.‰Ôä7’0õ˜pAeõêÕÔ××ÓÓÓS°¼££ƒºº:šr hhh £££,µÓê~õ+öŸ=¢^œã8~(‰å.Le³M»}ÞÿË“aW÷ ë•JÒbA(M%í`Ñùûx“6˜;äv®ëú‰S©º®³qãFlÛæ„N`úôé,\¸þð‡€'.X–…ëºD"š›› <LÓô%\¹œà‰&º®ÓÜÜ쇡Òu½ Ýniiðó‚(¡Âq?lU°S®„uLÛ¶Kzcضí‹6j;5éÂuÝ‚ã:ŽãÿL&qÛ¶‰F£X–Ess³ÿŽSç§›`ç>òߺLÓÏç¦ÊliiÁ4Mt]/p…·,‹T*5À¨Rhšæ{£¨¿Ë‹{Tº®óÙLMÓøõ[ßÊKuu¯ïDP‰¾íó¿ý-K^}Îh“Aoå ¡ëº7H_ÎÃà6ʃ¤”W .ëÌd³y¯r¥¼1‚ûE™âí#‘¼7J°†Q(F×U #Åå;ÃÅh4_/õS×AgkF"ùý=O;÷L%¶usÇÓèìô¶÷úaš¿üÌ3j?)}¥ÚÎ0ò^&Ê CÍÂVéÊ ËUЉRÍ|ŠRÞ2üUˆLšJÙçùŽªö© “åÝ7¨Ô¸­¢; ÷ì>Ì©'œê/K¥RþwcgggÙe Bµ˜pA¥¡¡€º¢è®®®Šf]]]É6ÈöíÛimm僛6ñÜ“uüþŸs±qñ°õ°rþîjv©ëºtww»Ÿ immeûöí~ƒRË f›0zûܲe ‹{£,>cðX|–eI>a\éêêbÆ ìܹ³ÚUÆÛ>wîÜIkk+—_~9kÖ¬a{Gyß"TÇÁq?Á¼i𾏲dÉN8á"‘HÁ¤F³½½ÝpnÒBñl$õ·^¢Ñ¨/F¨B%pêº>høÎàq m5TØ+  ÏôPîœÙl–––Òé4¦iÒØØÀÇÛÛquDc#étšl6˪U«0s"‹¦i¾¤Þ™†aøîñê~)¯šRb‡ëº$‰½w]×õ1–ØÆjòÊ3ðÈܹ£*#lT¢o{䔼­®ïõžÈÍæÍ†á ôG"Nn`@÷9õ<(Ï©b‚¹‹ ϼy'ÓÒò[ÿTÞ_ÅÏY^àóêS©TAYÊnÕ{B•£ë:=öÍÍû†½öêœÔ;Àuu¿¯ÄJ%l*!V—ú9˜ 8Žã{¦…ÃlÖ%“ñÎEí«¶Q«}•H¼j•5à8Áýƒ«s±mÇqÜ·RuWcJVËTK½Tc1«`ý<À¼yó¤o;[¶lᥗÞA$rªŽ*‰'š¤)-NHïVTßvûöíծʸP‰¾mݾº÷/b©¤_*ÀPïòÍ›7³yófN9å”jWs\¨Ô¸íúõëihh`ÏÑ°ë »è^~Wp@Á· Œ'6l`Ë–-ãÞ· MpÜÞÞÞËÊq[±b›6mâl˜5ÿ5L§¼¹1±X Ó41MSÔOaÔlÚ´‰ 6T»g´öyå•W²~ýzþý÷¹òP„ñ¢¡¡M›6ÑÚÚZíªTœÑØçÒ¥KÙ´i“ÿ÷Ÿ:_‡vÒìÛ)l6‹iš~è*Çqho÷Þ3™ ×]wÝ€}Ç3™ò&QókUˆD"´µµù »wï¦9—!“Kð®ú)ÅÄb1_XÊf³þ¾©TÊ£fèºN[[›?˜¬iÞà¶mÛd2™"W04YT*å :cùÐÑuD"Á£·ÞÊá³Îªöm¨(céÛþô—\×G¾å-Ëdòa°4Íò‚`x»ææŒ/TÛ•W‘Zøû)á±xÀ½x°$ضM*•òãn~,lÃ0H¥R$rn6êùSϦw"‹=Ê‚¡ÿÔ»I•×ÖÖæ{ÓÖƒ+•J‘L&ýk]ì!6J,J&“d2ÚÚÚ†Ü'è©«Î%™LêýU|Ç¡±±‘ÎÎ΂û6˜^qƒ×Ûu]N>ùdöîºïV댥o{饧zB&^T!ÿÉ ÆSƒ|Ì7€—GløZ;lÏ]ï8ˆ&9ŠD ]Ãþ-ßÏÀqÜey/à{Ûq¼qPèâtÅRëUÒ¡ÁÜ¿„P#}Ûáû¶­Kþ޳ÿÒS¨C…-[³f õõõtttT»še¬ã¶ ã½pøÛ÷ôsÔ>•‡SÆ‹â]ãEh•R3zzz|et8^èÙÇûç¥eåÅûU!9dW†g,öi}OÌGÿ@éžm"‘À¶m ·'£d¬í§²˜~ÎEfÕªt5ñ 8ØÙÞÞî{wªÐUÂÈ)àÕ4 ˲°m{HA*Kz f²«ðg®ëFýwj2™$‘H¸Ð+QLmøžGñxœ–– Ãð3EpŸ±ÎÓu·ööòø7¿ ïU\«ŒÖ6Ý»—×–ÌÀø!ØZ>ÌT:mû÷Gy(¥Ói‰‰D‚îîîqÇRŽa~¾R ÕÞ3»XŠŽƒí;–þÅh…aMÓüã–<èm6šë ë:»‹«À"N°ŽÅ˯¼òÊQ_³Za,m§Ê?”:·mƒ?þÑ*, þ¥ ~nä2!› u‚®î¢½SãÁ×?ÈŽÇoeÙËËøÕg~Ňt)¿=ïmÓ{ v>N[¶›–ÏÜÏ«¯¾Êßõýçl¤wúõ,Ù±gáßà~%ËôtšE‹qÿâûY¹¯Ž«v¿GÍ`úk½LŸÿ_¿÷_à,ïþâ»|â¢Oð¡m«è;f;³îý½OÃO÷üˆ9ß„9çP÷Þ:"ßrÙëü¸G\溇Xân'“L&±m›D"ÁæÎNöÏYÊÞW÷Rà0ížË}gŸí_“È­Ë^|™Å»žâÉ“W²å¨q7˜Ó0‡³ðŸÿ‰ÜçØ¹üDæ½°“g¿ôêêêXùÚJ~sóPÿÿƒ;Ó³ƒ“éã–ËÏgDze¸®ËŠ]+xzÇo8~öéÌÞÕÅ£ð'm+WžCsc3uuuÌþò:êž}‰£úbæÌ™ü¼nÛßó6À¤{ïÿHïI'ñW¯ÎâóO§{æ"N~ÿÉØ›Åžâ…óiyúW¼4ó½ì¸è4žšö÷íºËž[DÝò×Xôò"N{e+ަñõ#G8üØaNŸ}:+fa÷¬ÂÉ™{Ñ4Ó^> pÙû^Ç£þG–Ö-åàYïà™w,àž¯ßÆéüç½:½/ÏààQsèZô!ºôgÁ€s6oæä¾>^ž±Œå‡ñÒâ•<Øø~ž{ê¹j›OÅ­}Þ¼âj.î˜ Ÿ¨ö“q|ûw§â‘|™çŸÿ*×þêûþ2Çq$j‰PS„FPihh`óæÍËz{{ËNltðåYœuK¯|aÈí2™Œn`>åT/Î<óL,XPíjT”±Øg½«ðâZœeÿ·ŒO.ù$¿Ó~Çî~Ž“53çàfž<“7Ÿõ +n^«¹Üró-|åé¹¼î¨ÏpVÿYLÝB¹f'—Þñ4÷}ý>˜þÿuíÁî¥,8´E³–ðÒɯqâ%/ðæožÀ/.üú~ƒýK9t♜ü“gùä›ÍÓ /gyÛrv^¼“¹Ç|•—÷~šåOÞLïÊKØùƒüúÀ¯9åéS8úÔ3xõÿý´ÍáÕã^åà 'ð·?>‡¾üç§ÎgçÅ;9†vŽúÝw`ŽÉ´/žôž\üÇþDZ˜}€ÞsÞÎ)3?Ìþ3frðàA>xÿbvÚÁÒß.eΜ9L¿â›ðÝ,‡Jóü§8õ ÿÇ>ý;þcÌŸy ùÓ_}+Ï]ú7œûÜ1ì¸j_êü¯ýæ}ì<<ŸEÏÏçïE_pç¾éu¬ü•`ÃËø G-ŸËÌ-3™¦MãÕW_åå[>Çw®úçÞ{.Çm;7ù&Î:ú¯xaI=3Ÿz=‡ÿôoøÓ0æixמ°WðÆ–2sæLÎ]fðÈ´çѾ¯1÷¢ÏòbããœyóÍrÚ…\²âhÿïD"®ëÄÈ' L¥R’w¬(•ñþ˜hoo÷C~µ··ûa‘?’Ê× ¼_b±º®ûõ1MÃ0ü}•S4%•J 54 ,à˜cŽ©ö%¯(£µÍ?í}óVNà¼ó¶ñÐC×ñÁ¾“HdSÉí5M/1A!ci;/L in'l…gf>ÙXŒfyBwÒHbY_í,™çË'àð·’•eÕ½îœ:êÎÉÏ>›³óÅy^ÅUpc‰B> KYÊgùì€U‹YÌiœ('¿`ªëG½¥×p üW Î7§sRÁyýGî¯KÑ€•ÀÕÅ#ßÿäý˜Ÿûó|Î÷ë wzáÍt²p¬ÇêÀªÏðë€ …ù²ÝÃß|œY {g’¿nk!Ñ Ñ(ÇçÚ±¥,¦·ýˆãs[ͱüR#07è á šðq>À¾ÞÅá~³³_á/r@¾¥\Œ†Á E×ÿ44øxî"ðOœXßÚÚÊø@YÏJ­2Zûj1ÖïNxÍégÚÛ› –•ÓOÂHhðâš­[·ŽÕ«W³uëVÖ¯_ÏÂ… ËÚwGîx®“¿×Ot›L&#.d‚0JFkŸ›Ÿƒ×½\RÄ &QaôŒ¥ý|qÉ|>x¢÷»ã8ض=¨×˜ÊCÆ•_b´ ß#˜Pòž0ñxœL&C4-H`FýߕNJò„Ñ4U«Vùû;Žã‡ Š1Ág(“ÉJ¥ÐuÝ%öì³ÏVûrO£±Íg½ÈÙ¶À³—‘N§e" T€ÑØçO¬`Ë}ðÓ(…l2‹mÛžWgwç ù¾„q@]Ûr>Š/½ÆÐí¥¼Èhìóü%ç‹ T˜±|wÙ±lGÁßÒf µFÕ•`B"Åš5khjj¢§§‡úúú¹íì„%5¤X"@‚0<¥lFoŸó?̵'= '¤P!fDà„òoûøãOàë_ó~O¥Rƒ†ÃÌd2ضíš ãOq…J‰D|Q»ø]»ƒÏD{{;™Lf@ÂÈl6Kcc#Žã`š&‰DÂÏW§OLŽÇãâq-£`\í³}øMA(Ÿñ·°€Õ§ œX¥<ß¡V•‡ 0*ƒXù/pê_ݼuÀ:žD¼SalŒÆ>ýù,ŽüiŸ¾ñô‚åjƳ|| Âø0ÚösïLxÝY^[iYVIÁ$‹aš¦ˆ)&èÁf¢Ñè€%žD"\×¥±±ðÜ÷Õ»>™LÒÜÜŒ¦iœp ÜsÏ=Õ>• a¤¶9sÿ~Œk Ñœ‘|‚PaFjŸ½¯.`Ñ‹/bE%ö¾ÉdRDOA¨£íÛ ‚PYÆb›{˜q~wAÛ麮|g 5Gè•ÑòL|>;ŸWr]*•"™LŠ˜"U`ûy¬Ð@Ó.,XÇÅ­SªŒœsmP? L“¿Mn\Œ„¡0 çkšF[[Û€¼uº®“L&q]—Å‹óûßÿ¾ÚÕ-–eˆÝ BÈxìÅ¿à¬eOó³F{G»|_ ‚ ÂxÞ†%?{+\q§¿L…¡–˜‚Š ðÚkì½tà鸮K2™”[A¨žA÷}¿ÖøËlÛ&•J š§A„‰Áyè9^øòLìÕvÁ€¸BåÊèìì¬vU…£ÔóùPbœxâ‰Õ®fh±,K¼S!„}æaÞðÀ^¸|†ˆ)‚ ‚0BwáÃý» "•D£QiS…šczµ+0¸€Æ^æ4 X—J¥$wŠ T‘ÏÌ㔓Žõÿv]wȤׂ LßüÕtê翌eY¿-ËÂ4MÚÚÚ$4Ÿ L0¶mˇ¥ „›~•àÚŽ?ÒtUSµ«"‚ 5ÇŒ#»éYðõ‚oÏæææjWKF̤ðPyâ'OÓÏ<–¿syÁòU«VÑÝÝ]íê ”fÏYó™·ãQÿoÇqp]·ÚÕ`÷>N8zŸŸç¢˜h4*ž‚PÇ©ª ¢ÇqÐ4Ío·•¸ê8Ž_G˲ˆF£d2’É$‰DÂÿÛ4MÇÁ4M,ËòËüßUñxÜϯ–Ífýý‰„_nðg6›-(Ïu] ÃP~$ñÃÿÆb±‚:& ÚÚÚü2[ZZH§Ó~]-ËBÓ4ÿD"4Móíº.Žã`Ùl–t:M&“!‰H$hoo÷ë£Î­¥¥…d2‰mÛ~Ý"‘HÁù¨c«oj™ºêz577ÓÝÝíŸZžJ¥ü{‰Dhii!L2Ó4Í?u Ó4Éd2Ìž=›¦& J±sù'ù³ó$ÈyÛ ‚ ‚P>n^È¢×ðÿ¶m»&rH B1“BPùÓYÁEç½ÌÙ—ž]°\’ BõY~赂A!×u%6¦ „„{Ÿ9ŽþÅ4Ò÷Ú‰ëºþà  Ë+¯¼2f1EM^p]×dÏf³ø™L†h4JKK mmm¤R)?T®‚ äE‹ ª®j¹išhš†iš†mÛhš†aþþJ˜Qƒúªl€X,æçmÒuÝ÷’‹Çãë¡„† 7òˆ5 ƒx<ަi¤Óit]§½½×uioo÷ÿü‰XJÈ(î¯d2 à ™L,w]]×ýóÖuÝ0b±˜_wÀ¯6›õó išæ—YìÉ«¶ ^k%€÷÷÷û¯Iq]JM0sÇ¿>j?ÇqH&“ÜrË-x²'½Çôróqwðþ®ÚUA„šcÆGØ1{«ÿwKK‹L„j’I!¨taÁãÏùÏT*%!J!<÷Óéhëò¶¨f°Š} Bõ9[ÀìÝåçµP¨™Ê‚ L<{÷î-Û3L%¯W?Ê3DÙ¶ò¤p]×ÀWéAA-WÃH<ÔÔ`¿zw¨Ÿj𨲂ÛÚ¶]rû¡ÞI¥(%(Ë ö=Š˜rlBHðXÅ?›uY,Ê”*k¸ëV¼ºªžÃ]³âë&aæ†ÇÂbYÓ²jWCA#AOÐ ®ë¢iš?©DMšü‰Á2‚Þ±¨öi…§§‡£çƒq–w ÕäA¨E&… rïÍphÉݤÈââbbr›NàÂã/¬vÕaJ³}Ù2fßÇÂKÒB }öñÁÄ9ÞÁÅÅ@B B5yí&øýÞï„ûJ$Ààƒ}‚ T–cŽ9fPûSž---ž ‘HdÐw5X Ê,tW„Å{T aæ™gžáâ‹/®v5AÊ{S „†A*•ò'#~¨G‚Q…r,‚2•Jù^˜Áw5(ŸN§I$~ÆÎÎN_åù W©ú³Ùì€ã©°Ž¥B_êº>`Ê2‹‘N§ýjò‚"&³øü”'kss3étz€÷j©}ÕqS©”_çx<>høOumÚÚÚhii¡½½½ Lg$)‡ª~O¥R~èÎöövš›› öQÞ¹ê~Ckf³Y4Mó¯kðßo6›¼þJ0Üé¿üË¿ðÒK/Uûñ5w?ØÇ¢isÑu 6=´‰Þ“zYÎr"DÐs“äml\<Ïe3÷Ÿ „iýÊW¼Fimm¥ã䯳Õ>¾¦ Mwmb׊]¼¶ò5"DH"ƒBB娰aMMMkºˆŽŽ~ú›?ñçËyðŸÿŽgÝÈ·nùg_}6àÍð31Å>…ŠÒÚÚʦM›ª]ÐÑÚÚÊÇ6mâ ¡þØ|¾±`ˆñ"*IGG¬_¿¾ÚU ¥Þ[*—‡2¡’Hß¶4üâ¿`íÚµâÍ#T éÛ–¦µµ•ë6]çÈ~ØE•ßJååjkkósL©üV* ¦òNæ+îr$óm•Z'}îÉômG½·¾íÂwÓO3÷CÇÜåsyÇsïàMsÞDÿ¢~2d ö11qqÉ’ÅÆ&JS&å £¢}ÛIá¡òÒ1O³°ñaâüÌk¨æ+ \\R¤XÅ*tôó±-OGGCCÏýg` !œ Œ”îΠãåí¤g݈ḻ\¢ägÀ&Høö øv¦f# †²Éà,AF†»o¿ç5VÍÎÌ& ÃÁZ¡âì±—³%,Âp¨<(Ùl–h4êçÕ¡:sÌ15#¦(6•‡GÍÈW'Ôúâc]×ýmж¦i³¾ƒyšÔÀµš¯fz›¦Y°šÅFý™à¥f¤+oàL|UF4%›Í˜ñ_|<˲ˆF£û*(8+½¸®Å?Õù•ªkðüÔ=Pû¨w{pÖ~ñó,#òøãWûÑ -)Rhhœ¸óD~ûñßÇI&“þsmš&@ÞkSå ¬¤gvqÞ¯âu‚0U¸ù;ðð6W}r 7º7ÒüŽf>Ôù!€A'ÚFˆàâ’!CŠ..6vYÂŠŽŽ›û¯š¿ÎÀ((×ÀÀÁñÿVã ˜‚ÊËß;Â9'¬‚Uø®š†á ¸&sÿ]ÆâÄKŠ$Nî?ðfÐ;8¤Hù늅E)4 MÔSaJ³oΫ¼üÚ‹DøY;ë|)”}*”Ð9”Ý([¶°ˆ+X®„–`C7”ŠX*Le~¾y;3f<Ã#Ÿx„ ´¬F4õBä:ª¥PöT¼^u:‡DËEy±•Bc¼íWµóêçP×a$ç\¯ÞO*ìa°o¢ÖÌ®ÌõI‚ç:ÜyË £X´íõS×g,\wêu¼~çëÇTÆT ‘H ëº?àø†ýQW­ãŽ'C½W‚(» ž«……ŽŽíÛª*ÓÀ KÖßw´¨wÐ`˜˜XXD‰˜Í ž]kh88ÅÇj€á¾‹ï£éUñN)ÅKu/#æß#ƒZhàСC\tè"Ö?±MÓ ò©ù`8™t:í‡Ñinnöó©~A‘BíS*¬ÚN‰°j0?™LúƒõÁŸª>Åû(Á¤Ô>Jh)®Ç4MÖ®\ËK.`…»¢àš©c¨ãàà²J‰þ7}`?æP×u¶ýí6i$izßO\ýïZþ.þéõÿÄs Ïñ©K?EÒIòÉ¿ø$îE.tÐñÙâGâ¾Ç@0w”R4Mã[~‹ÿjý/¾¼íËœ¯Ï´ÅÓøîç¿Ë=3îáÙÏ>Ëšþ5|÷óßå‡3~Èß›ëºÌ½h.>éÃü÷ ÿ¡yõ>tÍ!Œ×|êìOñ˃¿ä#W~„Öí<òÉGX3{_æ¶«·±âÈ Þ¿âý¼oÕû8uß©hŽÆYq]§uñæãÞÌôõÓytá£ìøÜŽj›AhI’ä“Ï’ö™íÌÿê|´¥ùïB ')Õçéî=h¾gÝ/Sп 8ñ!·qq 5¶«úEÅýWõ§AÁ²¸})î3—Šü˜ Š Ás ;xnjº¶Ãµsõ™ê|Ê}‹;Áö|°É Áï ?üEq=Ô5 ö‚dÉ:I ¤o;ü¢ëœ»ö\ÿ>_þàåì;uÛÞ¿oüÛd³Yv|n3fÌðÛÔ'>1ní‚vü»xùhÊJ–]|œâí_À® î?_½_‚ïÕçoVs–,&&Q¢Äˆôí‡;¦-ÕyG‰!B† Y²D‰¢£“ á©ö)®S”(Y²~ NÜ–$°±I’ÄÂòëªlX]×?ÿËŸùùç>êûÄ£ÿ߉d24M+H®[m†zÈGÛ Î˜U†4lŸR@PeU¿RågÎ_ÜÐ;ö#í`ŒfŸjqÛc·ñõ—¾>%>:GbŸ|ì³;¨ox‚¿ç|Ç MÂÛJ´MõUNc:’raðÙðÃÍjU„ݾŠäÔ¹©ŽÊP‚rñ9ºY—ÎHgµOiB‰}¶¶¶ÒÎ?Ó{ù?±wÍOùÂÆ/ð¦†7:Ô—‹Ë*V‘&=ia|™J#íÛ¶¶¶²âk+ØöMo€6Èh>j‚³îÆ‹rC-µÉTÊ¡2Ò¾­zo©$ÔÊsDÂöÔjÂc-÷U¦R•‘öm_ÿú׉DJЖú&+ži^Añ>øÝ7Þ›AÁ¿oébÊ­S°ìR“èÔ7gñ¤Á €Z<qªÒÛÛKÓÏ›øÊ‡¾RíªTœÑômÿsÓ&Ž}ï/ùŸ“vÐ’h©ødx¡<‚ßå ±ÕFMbRãÖÃ}—ØØÜqßã.¨„*ä×æÍ›Ù°a«W¯fëÖ­¬_¿ž5kÖ ¹OÏcÇbìx ×u‰D"¡3È¡±Ñª|Ú€bõðŒôcy¸íË-oÚYÜãÝO1E˜ ŒÖ>Çñ“TKαÚÂÈý'„ŸÑØçP Þå¾ •¦£«ƒŽÕ®FÅmÛ¹ñî{9ú…%4Ÿ:±X,Tá§2Áo‹Z×-®g9ãÚGýö¨q· • ²aÃ6nÜHSS]]]\}õÕ455 ©x¿ÿ0»ëX2™ÿšô³ß¡šŒÆ>/ûóëXúÁ¥ôì¨ÚÕ„IÍhìsÉ y絫ill¤½½}̳kEL„ŒÆ6_yåéÓ Â0û¼çž{xâ‰'ÊŽû.Âè}N… |‚PmFc›ßº»‹e‹ë8²ðâñxè&à ÂH™^í (:::¨««óÝohhh £ch…wÙѳxþ¤ŽÐdkkkµ«0$lذ¡ÚÕ’°_éÀhíó•_¡³»3´Û°?[6löW“ZxLFkŸ·õóæÍ e¨’Zx¶äý! ÇhmsæÌ™D"µïZ7™žÁ°Û{¹L¦{2VFkŸ\pAhûµ#Ažéð1YîÉx0Zûœ ÔB¸\&Ë3=™îÉX­mvuu±cóy|ãO+YûïkC—7%ìmI-<ƒa·÷ûî»?ÿùÏãZfhüÛ·oõƒµoß>öïßOWWWµ«2(a¾†]]]?ûÙÏòÙÏ~¶ÚU„IÏhìóÞ{ï­vµaÒ3Ú¾íCI˜LA¨4£±Ï|à|à¨vÕaÒ#}[A'£íÛÞ·åÖÜoï¨ö)¸š_uuu– «r ‚0!ˆ} Bxû„p"¶)áEìS‹ا „±MAÈA¥¡¡a€!ööö–¥v ‚PYÄ>!¼ˆ} B8Û„ð"ö)áEìS‰ئ ä  ÒÔÔDoo¯Ÿ¨««‹žž®¸âŠjWM¦!œˆm Bxû„ð"ö)áDlSò„&‡ ÀúõëY·n«W¯fëÖ­¬_¿ž… V»Z‚ ö)aFìS‰ئ „±OA/bŸ‚NÄ6ÁcZµ+¤§§‡žžêëëÅmLB†Ø§ „±OA'b›‚^Ä>!¼ˆ} B8Û„ *‚ ‚ ‚ ‚ ‚ ‚ a#49TAAAAAAŠ*‚ ‚ ‚ ‚ ‚ ‚ à ‚Š ‚ ‚ ‚ ‚ ‚ Â0õ…/|á Õ®D­ÒÓÓCWW—ŸŒi°õuuu#^?žtuu1{ölfÍšªúõõõaÛ6}}}wÜq#ªÃD^?¡ö‹}VÛ6Ë©Cµí3 õj—¡ì3LÏÖhì³Ú¶¶k(L*e·Õz+aß}.•j§åQ[Tò›4Lö9Vû›Ès©ä7®ØgmQÉoÒj< •øv SÛ9ÖºŠ}$ פ¯¯^x!´mGØ¿»ººxòÉ'C?n;ácký¨¸á†úû¯½öÚþË.»¬ÿ=ïyOoo¯¿þæ›oö×766öß|óÍû·~k‡J“VãY¨Ä·k˜ÚÎZ¼'a§Ú×äæ›oîÿ‡ø‡þSN9¥¤ Rí{öoc%@*§T}ÃbßÕ[“*£ §§‡¦¦&üe—_~9½½½tttPWWGSS 444ÐÑÑQÖúñdÆ 444°zõjYê×ÑÑAoo/k×®`áÂ…X–Åå—_>l&òú µÇXì³Ú¶9\ýÊY? eŸa¨ŸP» eŸaz¶FcŸÕ¶Ír®‘ا0*e·Õz+aß}.•j§åQ[Tò›4Lö9Vû›Ès©ä7®ØgmQÉoÒj< •øv SÛY‹÷$ì„ᚬ^½š5kÖØa¹õ›ˆú‡ýÛ¸§§‡5kÖ°páB?™Œ­yˆ 2 šššØ´i“ÿw__·ß~»ÿpuuu ˆ{WWWGOOOYëÇ‹®®.n¿ýv¢Ñè€åÕ®_OO«W¯fóæÍ´¶¶²nݺ‚‡v¨:LÔõj“±Øgµms¸ú•³~<Ê>ÃP?¡vÊ>ÃòlÖ>«m›å\#±Oa4TÊn«ñuAe”ôõõÑÚÚʆ ¸þúë¹þúëýu¥ÔÏ Â5Üúñ “ÉÐÐÐ໊õööÒÕÕEWWW(êÞƒºqãFšššX¿~=kÖ¬aóæÍÃÖa¢ê'Ô.£µÏjÛf9u¨¶}†¥~Bí2˜}†áÙ‹}VÛ6Ãr …ÉI%ìv¢ŸÇJÚw5l«í´¼#jJ}“†É>Çj}.•úÆû¬=*õM:‘ÏB%¿]ÃÔv޵®bŸ û5 Ë= ó·±¢¡¡M›6qË-·pûí·‡fܶÚck"¨Œ’k¯½–úúz,Ë*PèÀ{ØŠoBoo¯¯t ·~¼èëë㦛n⦛n¢§§‡Ûn»Ûn»-õkjj  ÿªuý„Úe´öYmÛ®~嬆²Ï0ÔO¨m³Ï°<[£µÏjÛf˜®¡0ù¨„ÝVãy¬”}Oô¹Tª–wDíQ©oÒ0ÙçXío"Ï¥’߸bŸµG¥¾I'úY¨Ô·k˜ÚαÖUìs a¿&a¹§aþ6Þ¼y37Ýt“ÿ÷Â… Žû®êØZY©ë…n¾ùæþË.»¬ÿî»ï.ø÷ôÓOûÛ466öß}÷Ýýýýýý[·níollìïíí-{ýxsíµ×úÇ Cýz{{ûû·nÝêÿ}Ùe—õß|óÍeÕa¢¯ŸP;ŒÕ>«m›åÔ¡ÚöYíú µËpö¶gk¤öYmÛ ã5jŸJÚm5ŸÇñ¶ï‰<—J¶Óòލ*ýM&û«ýMÔ¹TúWì³v¨ô7iµž…ñþv SÛY«÷$Ì„åš\{íµý7ÜpÈëWéú‡ýÛXÕO•öqÛ‰[AeÜpà ý§œrÊ€A½ùæ›ûû¯½öÚþÆÆÆ‚®œõãMñƒ†úÝ|óÍý§œrJÿµ×^ÛÙe—õ_wÝue×a¢¯ŸP;ŒÕ>«m›åÔ¡Úö†ú µÉpö¶gk¤öYmÛ ã5jŸJÚm5ŸÇñ¶ï‰>—JµÓòލ*ýM&û«ýMä¹TòWì³v¨ô7iµž…ñþv SÛY«÷$Ì„åš &¨TûžÖ·±²uŒ0ÛNôØÚ´þþþþqõ·|zzzèé顾¾¾¤ËÐpë§BýÔ1êêêhhhQª}ý„Ú&ìÏVØí3 õ&'µðlUûý1–¶3,×P˜\Œå™ Ûó8–ºNô¹TªÛ=ÆÆdyÆjy.•üÆ Ó=ÆÎdyjé=#ö9±„ýš„ýž†¡~]]]~(¬°Û÷D^CTAAAAAA†A’Ò ‚ ‚ ‚ ‚ ‚ ‚ ƒ*‚ ‚ ‚ ‚ ‚ ‚ à ‚Š ‚ ‚ ‚ ‚ ‚ Â0ˆ "‚ ‚ ‚ ‚ ‚ ‚0 "¨‚ ‚ ‚ ‚ ‚ ‚ ƒ*‚ ‚ ‚ ‚ ‚ ‚ à ‚Š ‚ ‚ ‚ ‚ ‚ Â0ˆ "‚ ‚ ‚ ‚ ‚ ‚0 "¨‚ ‚ ‚ ‚ ‚ ‚ ƒ*‚ ‚ ‚ ‚ ‚ ‚ à ‚Š ‚ ‚ ‚ ‚ ‚ Â0ˆ "‚ ‚ ‚ ‚ ‚ ‚0 "¨‚ ‚ ‚ ‚ ‚ ‚ ƒ*‚ ‚ ‚ ‚ ‚ ‚ à ‚Š ‚ ‚ ‚ ‚ ‚ Â0ˆ "‚ ‚ ‚ ‚ ‚ ‚0 "¨‚ ‚ ‚ ‚ ‚ ‚ ƒ*‚ ‚ ‚ ‚ ‚ ‚ à ‚Š ‚ ‚ ‚ ‚ ‚ Â0ˆ "‚ ‚ ‚ ‚ ‚ ‚0 "¨‚ ‚ ‚ ‚ ‚ ‚ ƒ*‚ ‚ ‚ ‚ ‚ ‚ à ‚Š ‚ ‚ ‚ ‚ ‚ Â0ˆ "‚ ‚ ‚ ‚ ‚ ‚0 "¨‚ ‚ ‚ ‚ ‚ ‚ ƒ*‚ ‚ ‚ ‚ ‚ ‚ à ‚Š ‚ ‚ ‚ ‚ ‚ Â0ˆ "‚ ‚ ‚ ‚ ‚ ‚0 "¨‚ ‚ ‚ ‚ ‚ ‚ ƒ*‚ ‚ ‚ ‚ ‚ ‚ à ‚Š ‚ ‚ ‚ ‚ ‚ Â0ˆ "‚ ‚ ‚ ‚ ‚ ‚0 "¨‚ ‚ ‚ ‚ ‚ ‚ ƒ*‚ ‚ ‚ ‚ ‚ ‚ à ‚Š ‚ ‚ ‚ ‚ ‚ Â0L A%“É`YVµ«!äp]˲°m{Ìe9ŽC&“©ö) £Dlsrà8NI›û¬mÄ>'7åÚ§mÛ¸®[íê #@lwrPªmI»*¶>Ä6ÃÅx~“‚Øg­#ö.FkŸò]:y›œ¼L{œ‚J6›­YClnnöƒà﵊mÛ¬ZµŠT*EKK ±XlLå9ŽC6›­öi £d²Øf©¿§ ‰D‚ÆÆÆ’6-öYÛLûœª¶9娧ã8rýj±ÝÚg°¶µÜvUl7œLÛ,õw­1Þߤ öYëLûœ ÏÖhíS¾K'b““—Éb3ª]ah,Ëòg¯¯UZZZˆÇãÄãq\×¥±±‘l6K$©vÕaDÛãd°Ï‘â8©TŠîînt]Çu]/^L4Å0ŒjWO˜ÂL¶¶³ZŒÇ“ Œ±Ý¡ÛÖrÛÆ›ÉÖï­æ7©Ø§0ÞL¶¶s4ö)ߥB˜˜l6)”fRz¨d³YV­ZÅ´iÓˆÅb¯R»/^L"‘ ‘H¨…¶mÓÒÒ´iÓü7xªb&“añâÅ,^¼˜L&C"‘`ñâŬZµª@9ɶC‘H$üŸ×^{­ÿ{9ê¦mÛ4662mÚ4ZZZü}[>ܺ¡(÷|Õ‹$ iÝÝÝ~Ã¨Ê ÞU/u¯T™ƒ¹‡©íFºŸ01 e›P;ö´MõœÿŠÑØ`¥m³[)eŸêþišæÿTØÁ®[ðš‰m†‹±Øç`¶ ÕµÏñj;‡ZVû©ÛOõ·aòZH¿7œýÞálp°~ïHÚÖb»UËÄvÃô{'¶]-÷|‡û& –3žíªZ&ö¤ßÎ~ïhíS¾KkéÏN®þì”ÇíŸdtww÷ýÉd²¿¿¿¿?÷ýñx¼÷îÝýš¦õ·µµõïÞ½»?öýíííýýýýþzµo{{{¿¦i~™ñx¼¿¿¿¿?™L8†iš~F²ípëü}¸k ÎSS×õA—µO¹u,ç|Óét¿išþÏH$Rp>@4íß½{wggg¿¦iýíííýíííëÔ}QëTùÑh´ß0ŒþÝ»wû÷o°ý„‰g(Ûìïï¯9û,¶Çrìs468¶YŽ­ fŸÑh´?‰ô§ÓéþH$Rpý³O±Íð1ûÊ6ûûGfs•°Ï±¶C­ ³}¦R©!÷ªýìììì×u½÷îÝý¦iŠm†é÷†·ß;œíÖ®ö÷÷Ú¶e·ýýb»aBú½ß®–{¾Ã}“ªrƳ]íïû Òï o¿w´ö)ߥµôg'_v*ŒãN:A%÷G£Ñ‚eº®÷Çãñþd2Y`»wï.x¸Óét¿aûF£Qߘêÿ.6Är·ŽÑb2™ìD"®Ë`ˇڧÜ:–s¾ê:ªFQýì|;ª£© ¨Ô}VåG£Ñ~MÓ öj?aâÊ6ûûûkÎ>Góa9œÛ,ÇV³OÕh«ŸÁ}³O±Íð1ûÊ6ûûGfs•°Ï±¶C­ ³}¦R©!÷Ì>wïÞݯëzgg§_V;°‚‡ô{ÃÛïÎvkWÕv¥ÚÖ¡ú½b»áBú½ß®–{¾Ã}“ªrÆ«]U÷Wì3Ô>ã®ë´µµaš&Éd’h4Zp‹ï‰¢Ø-ZÓ4Ç(p½+voj?abÊ6ajØçhlp¢l³[)¾'·Þz+Ùl–ÎÎN’É$ÝÝÝØ¶M*•ò·Ì>Å6ÃÅXìs2ئ:ÇÉdŸåìWÊ>S©†aຮvÁ¶mI¦R¤ßî~ïp6XÊn3™Ìmë`íªØn¸~o¸ÛÕá¾IaüÚUû Òï|ö)ߥµôg'_v¸ý&Ã8î¤T†‹G:ÔMÐ4 Ó4é÷‡²³ÑØíx2[9å”Sp§`6›ÍÔm0ûÛ c±ÏÉ`›0ù쳜ýJÙg2™¤½½ÝÿgÉdrR|”LF¤ßÞ~/ŒÎvUy°¶u°vUl7\H¿7¼íj¥¾IAì³V~ïä³Où.­m¤?;ùú³Ãí7ÆqgT»ãM4ŶmV­Z忌#‘ཛྷ#‘èº>@åÒuxå»´¶‘þìäëϵßdÇ–K"3é°mÛµ§”/×u}×!×u1M“iÓ¦±{÷îq1ÇAÓ´ªw~T]TÌUõ{9Š£ºº®(úƒ-nÝxŸS¹×ײ,R©íííX–Uñý„ÊRÊ6¡öì3h›*¦c¹ö9¬¤mŽÕV&ʦ…Ê3û ‹më2žmçPëÂhŸbgS é÷†¯ß;Ñm«N¤ß¾vu´×VÚÕɇô{'}Žv?±ëp!ýÙÉÓŸ ß°“VP)…ã8466ÒÖÖ†a¤R)lÛ¦½½½*u*Q’iš%]šF»ßDÖq¼ ÔDì'T±Ï‰©c)&ÚVÄ6k°Øg-ØæxOÚ@a´„ÅnU]Ân»ã},±Aa(Ä>'¦Žã‰ØôÔ!,ö9–ç~ªÙçh»?a±GU—©Ö^Nô·h-Ùä¤ ù5º®“N§ýØlº®ÓÖÖV•º¨xwCÕu<÷›È:Ž7£U$ìd ûœ˜:VÖDÚŠØfíû¬ÛïãI(Œ–°Ø-Ô†íŽ÷±Ä…¡ûœ˜:Ž÷u›ž„Å>ÇòÜO5ûKÝÅ®ÃMXì¦f{9Ñߢµd“SÊCEAAAAAa4L¯vAAAAAAÂŽ*‚ ‚ ‚ ‚ ‚ ‚ à ‚Š ‚ ‚ ‚ ‚ ‚ Â0ˆ "‚ ‚ ‚ ‚ ‚ ‚0 "¨‚ ‚ ‚ ‚ ‚ ‚ ÃQ_øÂ¾0Ñíëëömúúú8î¸ã ÖõôôÐÕÕ@]]]µ¯ L)†²Mû„j"ö)áEú¶‚N¤í„ð"ö)áEú¶‚04.¨tuuqõÕWóÌ3ϰyófž|òI.½ôR6oÞ̺uëxæ™gøêW¿J]]«W¯®ö5„)ÁP¶ bŸ‚PMÄ>!¼HßV‰´‚^Ä>!¼HßV†gZÿDÐ4MÖ¬YÃÚµkéëëãꫯfýúõ\~ùåœwÞylܸ‘¦¦&߀-Ë¢¾¾~ÐòÞò–·°bÅŠj_ÇAÙ¹s'K—.­v5åàÁƒåÙ;a¶äO •°Ï°_y¶ÆŽ¼?&î<¦Zß¶\Âþ Ž„©vO&ý›ª}Ûr™jÏt-Pî=™ ÷n*ömGrmä=.ʽ'“åÞU¢o{ÞyçUû´†$ìmI-<[a·÷H$ÒÓM7k™𔾧§‡Õ«W³yófZ[[Y·n€çRV¬hÖÕÕÑÓÓ3d™Û·o_…iœQ3,ÂJ}}=MMMծƄù¶¶¶²eË–jWcÌ e›0zûܲe 6l¨öé J˜Ÿ-€¦¦¦!gzT›0¿?ºººhmmeçÎծʘ©„}îܹ“ÖÖV6oÞ\íÓ+I˜Ÿ-…¼?FÏæÍ›Ù°a»víªvUÆÌTìÛ–K˜ŸÁ‘v{/—rî‰ômk»o[.Sé™®†»'ªo»}ûöjWuÌLžm¹ÔB¸\&Ë{¦œ{"}Û¡ÛÎiÓ¦ÑÚÚêç] aoKjá½f{ß°a;vìàØc×rgLäIôôôÐÑÑÁÂ… Y»v-´¶¶bY½½½¶/ç^±b›6mšÈÓkÖ¬©v†¤¾¾>Ô/÷5Ü´iÓ¤ø¨Ê6ëëëGmŸW^y%ëׯ¯öé J˜Ÿ- ôf˜ß lÚ´iR JVÂ>—.]ê¶3ÌÏ–BÞ£gÍš5Ô×× žÔ*S±o[.a~GJØí½\ʹ'Ò·š°÷mËe*=ÓµÂp÷Dú¶µÝ·-—Zè—ËdyÏ”sO¤o;4§Ÿ~z¨í3ìmI-¼ÂlïªßVÓ‚ xÂÆï¡íëëcóæÍÔÕÕ Ø¶§§‡†††‰®¢ LI³Íõë׋} B•û„ð"}[A'Òv Bxû„ð"}[Až ùÕÔÔÄÂ… –©¿¸‰õöö†^…„ÉÀP¶ bŸ‚PMÄ>!¼HßV‰´‚^Ä>!¼HßVÊcB•Õ«WÓÓÓãÇÍëëëãöÛo÷ãÁõööÄæëééáŠ+®¨ö5„IÏP¶ ˆ} Bû„ð"}[A'Òv Bxû„ð"}[A( ùµpáBÖ¯_ÏÕW_MSS===455ù±ÖÖ¯_ϺuëX½z5[·neýúõ”QAÆŸálÄ>¡Zˆ} Bx‘¾­ „i;!¼ˆ} Bx‘¾­ ”Ç„çPY³fo”uuu±ö‚ëj!éŽ L&†²ÍâõbŸ‚0±ˆ} Bx‘¾­ „i;!¼ˆ} Bx‘¾­ Ï„ *ÀF')Õc8ûû„ê!ö)áEú¶‚N¤í„ð"ö)áEú¶‚04šCEAAAAA¡AEAAAAA&1®;~eY8Ná²Db಑”Ķ!“™ØëS."¨‚ ‚ ‚ ‚ ‚ B 3œ˜±jUùe '¾8N^ðp]ïoÛö~¶occ^8qsÿÀ[–JŠ4ÙlNT Å•ÔÄ_ÚDPAAAAA„!›¸¬±qà2Ûö„ ÛM+;\b±Òå'C{ˆl±à;ŒLÆ+Ï0Ööáß2ÞOEOiž1 õÊø­í-ƒœÐ|ÅöH¸¼j~]*…*‚ ‚ ‚ ‚ ‚ ‚0¸îÐÿ®[(B€',¨AËò¶O¥¼}Ô¿·4{ƒei–§Dïx^#ð<¢CÊÎ{ $¹:¿sáON¾UV*/êí8ðŽ¸Û„x<¿ÜÅEº°.‰Á ¹ãÙxÂ̲áO.<ë‚aA†•-ð¹ÄÀë•ÍzÇÅJ Nã…*‚ ‚ ‚ ‚ ‚ ‚0¤RžH1¶í A %Âhz~»ÿvÀÖ`vþ5­ 8¿b6¼ª{Þ$?³zn¬2àç6|$ïÏy€(¯‘ã.€¯Ä ÑèÕQÕãÓ9’åQxÍ„og½2¯ŠÀ“|߆~nˆEK Ø’€vGà È4Âk.LÏB_Dà.žÏ•lÈ:¬¶á° sã°' Ïdáž²ŠM*‡K<ž—**‚ ‚ ‚ ‚ ‚ ‚P Ï#ã{E9N”çG•‡à;üÜ…Ïgà—9O‘·Åá2`¹ð) À§cˆfÂ+&t9žXaË“ðºNø“ GðŸ6¨(_WÆà ¹v|NXßú:Ø?€Çß±oÀ²8<ö8èó¼ãß t ÿ nø|Øb×2°Oƒ#|L‡vÎmô„˜½/Yˆ?ÏÀ¦,LÓ %Š@$‡ Ø£AƒG,xs¢ðìWaÞFø4àfá]€®Ãµmð37/He³pF1àQØo@²BIígTùyAAAAA„Ðãúë[Z ™ôý– ø¼½Í ‹Áï8 ÊuòšN~¯Ãs9õã?³ð7-°à8t.¬4à à5 núOؼ~ß ;€ó,èÑ¡÷0ãÓpÂypðžÑmû.ƒßî‡óWÁÖÌÿ4Ä» q|ãWÀ›@_-‡+#ðÐ×¼}ç< Ñ p‡ ·X0Ç„þ3aî÷Aû8¬C»‰fXþAˆ5À…Àï]¸#¯œÓ6ÀÛ×€™„7»à¸ð¦ŒçQ3Ý€Çth› ‰ÃÞ50Œ\è²ù`èÓ¼> ?È€Ñî W§?ÐaA;¼tSݸ?â¡"‚PÀ"£RAAAA¨>žç‡ƒ7@ÞøMh&ŸsD­ÿï@¾æjU ¼íQø/z]¸0±¬' <íÀÑq8Á‚¯:^H­?8ðõ¬WÂì…°¦Ìx¡¯<íï„[¢°Ò†v.::ÓpÎ ÌBÃ.xë,°ï÷<×lƒ¾^¸Ê€÷GáD î´á’àÆ{á'Mð¿»a‡?z7Ø}@Ÿwr‹vÀ¢ÓÀ\ Gt˜4ØëÛÛ 8Äó ¸äOpd——«% ¤LXÞ ¯½º÷ÃÛ Oy=ÐðzH^æ-€§jpê"04ØeØ€±Ú¿æùÞ¾® ú!âÂnàTÒvNlÁ;n!ÌHßV‰´‚^Ä>!¼L†¾íb¼dåÝ¥ÆâÕø†K~ŒE›¤2°Íõ¼FlÛ Á•ÉÀJ²Iø~˜ñ’Ƀ·ÜÎ ‚\´"I/\×¶NOh9Aƒ¥š—÷Coí0˜÷ç*hçá Ôäf°ö›`œwáÏzÕbxƒ0JRƒ5|ºÿÓœ¶¾ó·8`Áœ»ç€ ™L†÷ßó~æ\=‡Ý¯õ‰Dpt‡«Yf|ã½= t¯XMeqWòƒ`Þ@O*°NÇtX‚|Ž˜f ia n¹7rŠ1UìSjéÛ B8‘¶S‹ا „—ZïÛºä#i´Ïk×âÀç\Ðmx£››`êxÛ¬ráHÆó@±mÐ48ÉöB½ßcyË¢QïçÏ¿;þ îVÐîÏE¡Š@<7»õ#Io[Ï[%³7W •ÀE ¾èxê^>·ýNÜñmÔ@“ ‡æ¢Ån(XŽÅ¶ó¶A=ˆ¶î6× R©”?`õÎw^ëºüî+¿ã½ßx/Ý‹ºÙqÕn»í6¨sýA£l6K6›…Nèí}€ÿýß8ŽƒëºþÅs]—çNx.W!ǯ—7;Ø‚i©BA%•â¥ß`Úk{À Œö8À»WáârÏ ÷À"—{W¬à/®xÏódÿÒý<¸ýÁü ìîJ0}Ûtn|æFÇáÌÇC{^£ëÙ/pîŸîæ/ö_Í#×>‡~ÿ!Þ×ÿ>^ùÃÀ4Y¶cÖ¸?g*¨ôõyÒ>÷¹Ïqê©§rÞyç±yófºººl]]Ý€¸}Ålß¾ÖÖÖ‰< AðimmeË–-ծƘÊ6aôö¹eË6lØPíÓóQÉÚSäúÕ?Òq7…â„òi!ŠRy”Ú*ZÆ6C¡r›”“£¤x›$¥Å•Ÿ%èõœl &h& ×ж vJ”g‹M¡ÇŽÚ_¹ÑÉâ{„úÛ”YFCWW­­­ìܹsœJ¬•°Ï;wÒÚÚZPŽ L*TÀ®]»ª]•1#}[a²!}ÛÚêÛ Sշݾ}{µ«2f¤o+L6¤o[^ß¶««kBÎAA¨É´*Ç¥v~L'¬¶=o’-1Ï㤹Ùûy©ßJås¢D3[mÒiOlÑê º¢gåD–m@ ô œs† oÓÅOv›ž…W 5S7J~V­ ‹¢ÁŸçü™l6‹ëºÈ¥—® rhõ!Nš~¯¾ùUž_þ<×í»ŽíøÌöÊ:ù[ßbéÃcóçï}W¿ô%‰¶mÃß5‚ë 5 ëpõÄbÞ9$½{çý„Ýs‘î÷¦·´´pWOGM»…­'.Ãr]2™ ‡ßüf¸55n=t+÷Ì¿‡Ç¯|3GßuOŸ¹—­§ýœEé4Ç,ü&Çžr,Î{\OÌyí©Í<ú®GùàÌ™\q×]Ì¿çŽzãùL›ÓHß\¯vªÝÃ-{7pɃæÿ÷å8žbÛÞï®ëýnICÔc8xå»®—^× mË-¬`8Ãˉ¢¿B>1KÌ¿'êD JåJlloP% žñ(º®“ÍfùÎÖïJ¥ˆÅb466â8ÍÍÍd2’É$†aðÙ>KÝÊ×8é›'ñ÷ÿü÷¬¾f5^ü(¶mãº.š¦õw<ÆqûöÑÞÞîø¯-\×å¨íÛ¹ùŽ;8ð¦7ñê‹/²xÚ4>ûÑbY,›Ë³?™Ã5«WÓÞÞÎìãÁóË—{-À#0çàÝ<|ôRÈxÞ.š¦ñXk+ ô¿ ï³Ÿõ<]€Ã÷ÜÃ3÷~›WfÌãŠËöñg½È±‘7Ðó›ß0wùr^yôQùËì8f§>ð1^þÕÛ¹û„»innfÛ¬éüvî·ùâ¿È‚÷¼‡ú?ü{^û0svÀîôF?C÷Œ×qõ‚¯CƒÎüüGNyëßѼª8^ÊØ™PAEu”{XSSW\q…ï6VÌp*§ ãÃP¶ L ûÌâ‰ÿªA“÷žT“CÃUtj%¨£ Z®ý y!I•SìÝ¢ò¿¨ë™"ïͪú V <¼·Œêc€ŸgMÂå˜ ö)µŠôm!œHÛ)áEìSÂKØû¶J0)CPdñÆ!fæTèôãÏûD‰&ÊŶóIòм°¹¢Dû r´´€û¾ªÓ}-Db`þ5˜ËA›™«`NIþù\ÈË´hÎ4{•*ˆjnnÆ1ÐáÛû¿ëº†A2™$ã8Éd’H$B[[‘H„L&C*•ò¼H .üd¦éÔ¼pÏ †íÿõÿØÝÝM*•ân»H$Bç¢E<±p!uŸÿÓÏý 瞺ˆ­ÿðvÚÛÛ9á=ïàW4 Çãô_vm;Dýiõ\xá…Ô%ÿû.½/¯Zé4§¿ýí|fÏgØ~òø{wN¸‡J±‹×Â… Ïh‹ ±··7t‰a22”mBíÛ§ŠŸkA“€bQ£q …”Rb“ “ü;¸Ü ?#$8ù¼ŽªƒN”¸…³Nl ÂME&»} B-#}[A'Òv Bxû„ðö¾í·mã¹çž+#Èž*GxÅÍOžÕñD”hR)ïÀwìâmo»]÷„ënÏ3E×½Öø³=ãïööÑ"Ÿ0Ö½ Ì `?Æ™äc¢;}/… lu0 ƒhÔ›Òš5³Äb1,Ë¢¥¥…믿;jã8_þò—Ù²e --^Pt˲H&“D£Q4MÃ0 "‘»mg/\È•û÷{JЮœ» °òßVrÿ´ûÉf³^ˆ0×büqU†ãÐð¦7ñ–û7êþøGR©ËfÍâ?zˆ[?ñ Ðuθþz.üЇˆÇãü±®­»›dÒK ³ðÿ—H$Âõ'ž®Ë·çö¶ã€ãpʳ·pÒI'Ñ‹qÒ¶mþu‰F£üÝùçóÂüùp— é4Wþô§hšÆìãçøÙ³Ñ4Íó¸f¬8…¯ý†97‚û¯ÜÏÒ~tMÓøX×34ÿä©q'TPéèè`ݺu~L¾¾¾>n¿ývêëëijj¢··×Ÿ•ÐÕÕEOOW\qÅDV1”¸®KLŦ¥LŽ˲¹}0÷Š[?ÕßF“Õ>a2 }[A'Òv Bxû„ðö¾í®‡÷óÍéù¡l›¼WJ x0‹sâ(,¶ Ù›!“ƒz‰Ï»ºŽÇ²r"ËIž C|èsðm.´E¡}MnY?v˜ÏtÐÃ×¶}Í‹%¯ÐɇFÉ%âÍf³d2ž”J¥Ð4 ËòFG6nÜÈ­·ÞJKK ùÈGX°`–˶ùÂÁƒ†QxB–Å‘ûîcÚM7±êG?ò•tR)úî¼Ûµ9ú¸£Yýüóì9ï“Éø^{{{þ Íf±mO5ÕuÝWF‡Âqœ±Ô9(ãuìà1]×Åuݲö2œmBøí3C~€?רªæÆA¼SŠ)×R¢”—+¦XxQÞ«FàŸÊŦrª /nàXÊsE%³Ï2|h¶ÉÊd°OA˜¬HßV‰´‚^Ä>!¼„½o»ÿKÁsqXñžü25n`K-x¯ýÀ\l77ÎM>t§€IDAT¾Œ°uÙ¾÷½yìÞ=›ÓN;ĪUÿIü•Ÿà,‚èý ¥rÛ·@ûM@:ÄÑÿ~4Ó·MÏg´OÁ>ø¸áÎþÂÙôõõñwü„ ÚßåãÌ«D³1ü©9sæ0oÞ<ÇáŸÿùŸùõ¯M6›eÍš5´··³gÏ"‘©TŠ™3gz;Y³ÿ{fk8»Óiß?{V­âWO=ÅÕ â^s sÿë¿¼í ƒn¸=|˜]»vñÚ/~Á±GŽx"Ì™íܲýÇ<ùÞ÷ò‘L\—ÄÛÞFô¯ÿ:—Æ_µmÓ4Éd2´Ü?‘÷½Ï¿ÞÊ£æ7²0湃™£Ä]gQw7kÖ¬aåżjÌVoë:Kö3Î}ßûF?ž›.í3 £@|zò‚•ÿÔ\N8á„q}'TP¸þúëéêêòÝ‚®akÖ¬¡©©‰žžžë¦Ùl–l6‹eY†ÁîÝ»}Ð4MZZZ0M“h4J*•"“Éøê]cc£¿¿ëºD£QZZZü‡I)~ŽãÐØØH{{;Ùl]×q]—ööv_!U ŽŽãø ªëºD"lÛ&‘HøIŽ,Ë"‰ˆ,ÊØ"‘‘HÇq|1Fí§ŒU©Œ®ë’H$0 Ãß^Ó4’É$---hšV ¨d³YR©Äb±¢‘03ä½O”Ge0‡;ŽÁ>ùdºsÛ®bp‹©JÎÛ´,ÊÝN£Ð³ò“3Ôr›|~‡ü} z è&–S“J2ä=`¦"µdŸ‚0Õ¾­ „i;!¼ˆ} Bx sßöðáÃ<3g!Oà'¨±„ ÞXÂk. œÇ ¾±û“\|-DëÁüh*D—†70õ¿]ÏW·|Õ;šªÃ–W¶ðØŒÇXóÈÎ9ç»ÜwŸåuF£( xþÐó|%ñ’É$ÿùŸÿɶmÛ¸üò˘1c/¿ü2Ï>û,«V­âá‡æ™gžñ'ÇëÍÍžWFNlxþúëyì‡?ä‚ãŽãÖyó8²p!×_t­­­©«ãÙø¼í6þéw¿cîqW]uïØø/˜®“J¥ ÆW›››q]—îîn~ÿÝïrõ3Ï@@P±m›¿ù›¿áËŸù ?»ñF’Á ö¹z>öØc¬,šP¯Æ ho‡TŠ‹L´ÊLŸ=fÍú¿w0¾yT&\P/îÞ`L†Æ²äCB¡† Ì"7*˲ü‡9N㺮ïÙ¡D×uI¥R¾ZØÙÙé{~†A"‘ðźK #ÍÍÍ$ âñ8‰DMÓˆF£u‰D"466úâˆ,ÇÁ0 ÚÚÚ|QCÓ4ÿœÓé4‰DÂ/Ãqb±ííí´´´øÂˆºÊ«¦­­U«V‘ÉdˆÇã¾0£ÊU⋪“ºê¼mÛF×u_LR.tÊ­Ìu]ß‹'( … e›P}ûÌ’OvÞF¾mÆkÓ>uóÍÜßÒÂM}TÌL!OzìE”Ä(ão—ùY‚Þ-Qòâ‰]´­ÃÔ&ìö)S™ÉÞ·„ZEÚNA/bŸ‚^ÂÜ·=°7?”íâùXxN .€;,Op9/o @ËßBò>عp>ÌëáŒÙ'òÓ=G8vï±`C‚HhYüp^GÛGCNúõI8þsæä¡Ò`µX˜oò¾B{6K4õÇ0›››‰Ç㘺Éó«ŸçÎ;ïäÎ;ïdÛ¶müñ¼øâ‹Ü~ûíþ„öD"AR×y×'?ÉÏfÎ$‰ð /Ç!žN3­¹™ìªUüóÏrÌðجY¼üøã}Î9ü¢«‹Žµk ƈ­Õ«¹®¹™Ýçž‹išÄöìáúçŸçóÏ g_7éÞñFX’É$ÙlÖO6MÓ ô½»ï&={6oùÔ§øõx¹X€gžy†«>÷9ȉ)«V­¢»;7­Ùqx›úµÈ›Ô¿{÷nÿXþ¸y.ÊR*•ÂuÝq³5M“ÿ{ûÿ1ŸùãZnU•ZG…Ò*…뺬ZµŠ¶¶6ßCÄu]?t—ôW#A±À0 ,Ë"ûê  LÓ¤¹¹™h4J<÷Å %h("‘ÑhÃ0˜6mZÁ±ŠëÇÉf³~ùA4M#NÓÒÒB2™$•J‘N§}Á"xLbL‘L&ý0eA• ðSŠd2ép2™P'€––ÿÚ+¯uœt:íçšI¥Rèº^°­~”øR\ nÉ­Ë—³èÀ/†R¯båý¥UH'IÞ»<±KMQØä½cÁëéäÝx ¦fè/AAAA˜ŠØ¶ {OöRxyIÈO M±?y¿Gñò¢|ÿûð¿—î‚.Â>rø%Ö^Àѳ÷ñâ‘Ì?<,¯Œ%§öqä¾y¼øžIýÿì½y˜Õyïÿa’4£‹ò€\Ãb°±jŒñØ/Õ1˜xÃî–o îK_œ\ÅÝ7 ¾ÆI~ÝÎÜkçÚé&1^âØê¶‰í#»+7ÁŽ'¦¼€lÄ"ƒ@bQIƒ„Ä&ýþ8õVU÷tÏô¬=3:Ÿç™gfºªNª®Suêý¾Ë>ÃgØÞ»¯¾ÊûV¾µöZð`×â]Üû;÷bÙl–D"Qá!ä¶Þ³•ãî:Ž—º_â-oy ×]wO>ù$玌`y8éb‘R©ÄñçœÃêG%ÏC.Ç?ž|2kÖ­cóÆ\ïº$“I>rË-¬üÎwH¤Rø'ŸLþÏþŒÝïx›6m"ŸÏ‡¥\ ýñ‡}2 ƒB¡ÀEﺈ·¿ÿíx·îªÚó¼PX P(„Žüïtþí¿,Ëâ©§žbÇŽ¡Í5ž‰ˆƒÄö,Îú–e)¡'“ màõ¶æédåÞ•¼È‹ÓÚæ¬¥_È—ß×uË$“ÉŒº`äo)æ#Q===aT‡ûë±,‹b±H±X EIÕǶíP@‘ßqaB"VâEçEa¬Ç¶íð/—Ë¡‚8Á!.zŒ70’É$¦iR.—Š)år9새6 „)‰v‘ÈAÒœY–…뺤R©0R'N¡PCÛ4s ø£çŸÅ‘z‰0•Jñ¡5kxî#᜿þëšeµÆwß÷I¥R5c Ïó¨T*¤R©vú‚CR´5:û"SKT‘¤ƒ° "aM£Ñh4F£Ñhæ"‰D"Ìœ!4³½Œ‡ïû“ÞV£™ïäP¶€¿>å8ïNú»#œ\Qè—Uàb7²U†á-ëâþµÙ«óÔS/ñ\ÿsdW©å=/-{‰W=½‚·,>½§ßËÈ%#üíIOðÃÀî“w³ëÇ»Xüìb>wûçÀ‚¯]ö5e°ðàŽåwðýeßçÏþìÏÈår „Šëºüíßþ-Û?ñ ®y×»¸þï¯ç{K¿G>Ÿ'ŸÏsÖƒ²uhˆ/_x¡ªiàû؆Áë{L©@® =ùgŸÍ9·ÜBµZ%ŸÏ³rófœÅ}ßǶmž{î¹ÐÑ]„‰z»f2(ä~ã}7FË,+T,Ë¢T*…ŽÇí’N§qƒÿ+•J˜uHìßRúTðA.—ƒ ­R©”J%ŠÅbh£ròùÐþVoËM¥Rd2™¦6ø‰°äÐ:ïéœÖëR * —Ë…‘!Èd2¡º&µ?R©…Bjµ€|>Šò7î6Š(‘´\ñuš¥‹oSO½Ø2V¡xPÑ'Åb1ܤ"k©û2ÝØ¶Úø¹³m›d2‰mÛaÄIwww¸Ü4ÍP¸©ÿEìŠ 5šöãï;r„_þó?“D=Ãl¢š>ró¿æ²Ëȇ￿f{©$HôRý÷œÉdð}ŸJ¥N~Ç]€ð¡'·Ã@}¯&QÊ/ŠL ÓÛDa¼Ytê/F£Ñh4FÓ~ …ÝÝÝ5N²@˜#þ>éº.‰D¢Æ>QÔ˜­GêÒj4Çbpƒß‡†W°bÇSœnÃJ.ráóÈ;Jƒ°VÀýžÉoîúïœrâ~/>ƒç÷<϶_ÄÁáàIùûÏâ#'?Ç-§ÏEø—Cÿ‚}’ÁÆ•ùÞáïQñ*¬Ê¬âÃk>Œã8¼ñoÄ+„÷tÞûþð]¼ð 5u¡ßW.óðÃsß}÷qÁÌ;ç||î?ó~,Ë"ë8üùë^ÇâíÛYyô¨jÏuaÕ*>ºx1k.¼0ÊQdÕ¹ò·»ö¤ÂMÜÙý¡‡ íº†a4´)[–f’šØäóØG-˪©¥bÛ6CCC¡#Ñ+bã•,K©T Çq˜R©Dww7žçQ*•H$a™±Õ&“I†††Ó¤Iv#9& Ph<§èñؽv7Ï­}nZ¯O-¨4ÀEåð¯G³z@j{aJ®jµW—”W²\.YW²&Êtq¥¾ª_]“ú'íFú ¢‰œßb±H2™¤Z­†Æñ¸ÁÛ¶í0%š Pˆ„‰b‘¶ÇÐ4³Cx÷¯ÍÎ÷¿Pu õU*2™ŒºñR›ÞK”r‰«T*är¹0üR¾W\J¥R¸^¹\¦Z­6Ød‚ëû~(¢Æ'Ï£ú_(„íêkI!w%”ÔßÌØïú× »ÁgF£Ñh4F3›ˆÁp``€ð}O¼­¥6¬ÉdB{…8üuww×x_7òÆ–wظG¸p5š…LeŸÈ)çÊ={öÀŽVüb„U6ìζ»ð£ÝÇ éAŽ=Ê9/O¸ø…tu¾À›^|¿îùî= …x=!µK 0õˆçŠ tCh4F£Ñh4ÍÄÑ¢YÝ\ˆ²%d³ÙðýSjÝÆ ò>X*•Âì$†a„ï¡bÜ‘Dö/ï…²i?—Ë…6×u ß)ëm/ºF¬f¡°¯n\±‚•8Èί¬²áé@Ÿüáì_Éþ3ösÏÑ•Ü}õݬ¿í',»à"¶Ÿü,»~ísÎ;‡ ¶_ 5V'Wc´À‚ ì (=["m§Ã±j;vìàÜsÏ­éÓE]D*•¢\.‡¶©ÓN<‘S¿þu¾øÉOr`x˜—~ðl‰©TTŠ­@,Q}0CAÓTa”JrŒs2– ¹¾Övý²F%,Ë×ÎT/¶È=Mlâñû¡:Œô˜÷Ñx[rŸ2M3Ì*#v8Û¶Ã,C"^¥Ói\× £¥ïí"©Æ${ÑÛÞö¶é¸kЂJê¢uò÷_ÌW¿÷=z¯º Œ<•ÓÍ2®‹½reM[­\8£ößbº)Û¶) ã 1ÍÂEããùê5/ÊåXƒ^jªÔצ1M“jµJOOOX€ihh(TFW­Z 0ñˆ„R©D>Ÿ…Çqfd`ëø¨<™RCüÿþ0O£„(:ŽÓ0ýœLPmÛ—K4ÉÀÀ@x½ÈuQ.—Ãq†>ÄÃ¥¸—i D s¬T*aÿä.}QO>—Iu<<´™ "n:¦§§'ì£išMï1òj&æÎuD@ñ¨^‘o»þ®W@]+Et:0F£Ñh4F39|ßE ±Haæx šx!eA>7 ƒR©zu‹`"ï¦ò>*ÅŸÅH(ήë֤БíÒé4ù|>\×¶mzzzÂú¼ñwc±] …1kÔj4sq_}ügûxvè(]ï=·ïe•½ŠX&x•jÐ#¬‡Á˜ÌƒÝ°nô¦M›øÞ÷¾¨´ïG÷î q¥¸ºã8|ô’K¸ö?þƒ®¿ø ¨V¹ðC"iY\·nø>$“JXÉf•x"÷IˆžcÙzÆr쟮¢ïCC‘«Ôúž¬ý©>ÚF²ÆÑ"™¡èéé £eDÐB¡Zj½”J¥•µ ÃEyEçQÆÜï<ȵ• G-‹;/½”Ÿ_|1v¯]UMÓ„l–¡:1e2HA¡Vie 8Ž^|@hŒfÊà:"®ëÅ’øò±è¹ÙH®A1rW*ªÕjMj0 ô8ѵVfŽAZ/à¤ûî ϹLh%„º"|T«Õð³ú0C ¡xQߦeYa{ù|×uÃh¥ø ^ vIÄŠ¤ñ‹G»$“Éš:LRH&ÁríI]‰¤‰§“¼—’Æ,îy bDèx;ó ¹³Å£Wâw»À™¤&Z¥Âè,F£Ñh4FÓ*¹\Žt::¿‰£Z.— £VR©Õju”½AÒÿH*0yÇK$£‹Å"®ë†ëÄß-s¹\˜Þ&™LŽr¢‹¿³JJq¼qEê´H݃ùö>¨Ñ@d£øõcKXúT#¿^ÄÊ•{€U,zÌ]ðîgžà['ÏŽ;Ìý¿z˜phÍ!zŽë!¿m)ì†5ç> ÖJÕ ¨4U°*µã¸‘mÑ-•8©³×u9ùÿ‘«wìàÄL&›á˜ô<~{ÃÒPI䘩VRë MO>©d-™.QE˜êý%Ù"%3â}”¿%šiš¡ˆwxŽS,1 ƒl6K&“áСCÓzÌ Š„2–ë5^/&Ž´ÑÆ;‹P ~uŸ§PQ) „ñ$:Ý—F£Ñh4F£™¹\.´$“ÉšâÉñâÈãO= Ô8Óµ‚¼ËNäSÞ•{zzÂìõõc%X"‘ëÉ ’¥CÒš7b¢ÀÍt°{÷nõGNðÔ8zõº‡xiÅü¥pæâÃ,a «8ŽOÞóFþô3§Aνþ\^Öÿ2ì•@‡Ò5Bò4.ÎÚÇqZ¹’7ž|2yà^ñŠWйn‹wíR+ø¾ú‰×F±¬h‡AV£¹ÊB×q;W#{·a|ë[ßâ±Ç›ÖýjAxמ=lßµ‹ÃgžÉ3ÿõ_üø»ß Ç—ã8œqÆبqwíOpÁg>ƒ•NóôºuÓ"¨ÀÄ/äÉz H>Ιb&ÛŽ#féÅDtŠ2jµÿÍ òbÄÂÚ™;V)¡ŒìröwmßÎå¯|%EqM&Òdªxž~ßí@&ôq$Í÷}ÊårÓ´wâi%0©TªfÌHú0×ukB%»»»ÃÔw3‘Âo*ɳ¨¨Âú©¾ôrþO 4F£Ñh4Íl‘ÉdjjT&“ÉÏuI5Ó*õõ['‚¤»™Èv’'›ÍŽJG–ÏçSgË»£dâÈård2‰D(¬ …ÁÅ÷}zzzæmý]Íüå‘=NŠ8äÁÙk^â÷^ûï\üÏ/~ÑãâUOÑ×ñÏixåË!È gš&F”~QW¦dCÒ4MÎ}ÛÛxÕ“OrÆ—¿ ®Ë)ÇÏñ›6© ©QQùl6,,?×i§kº¯ÿétšÍ›7sæ™gNë~'$¨ô÷÷³uëÖðÿÁÁA®½öZ®½öZúúúfñtM`<ânÛÆÏ=ÇâÞ^ÿøÇ¤R)•“ ¸lÏnaÉ…Ê÷»gŸÍÚ7¾1ôŽž®K/^oa¦H§Ó”ËåY‹"™iÄ <7’‹O¨œ²O`ÆBÇŽU*Ô¦w’BR Ä¬½{÷¶åÚ•h¨v›FæE,ie¢-éê²Ùl(°€ºçHÁûJ¥B&“ ‹ ¡ã8žç…ù|§ƒ©N/’D‚Їr0‘)ÿì&Ôh4F£Ñh4óy?š+i® è©Ú*ù|~ÌBÔCCC „©ë¥N‹ã8 „ï¼¶mS©Tèî§'ŒzÆ™?|ߟõ”ïšc¹ÚN¼üp`uÖ]z„Çœ“GNà[/“ëäýç¾?Ê+7áY`vEÁ#csrÏår8ŽC©TâÔ·½üÊ•Œ¼ÿý<·v-k Óz‘N«4_® *óŒùžy'n³•ÚTõËO9å”ißoË‚Ê7Þȵ×^Ëðð0ÃÃÃ\sÍ5¬_¿žmÛ¶qà 7Lh烃ƒŒŒŒÔ|6<5Mk´sn«Ñhš£ŸÍÜ¥Ýã³P(´% ÂXÌ´#ŸaضM*• Ó“I†|>OµZ¥\.300€mÛär9ŠÅb]D¢X …Bí¢Yx´kn+V‡NËçô©´_+,8î¸ã8ï¿ÎcÑK‹X¶ìy^öÌEjƒ&sy]Ê/ÙGP‹Vxá=ï ÿþ“ø†ªUûÿÀ4M¾sð žïóàYgqÏ[ÞɤSÄ.X­¶¨ÚÌ š¥ö›ÔÛlg˺%Aepp;Ûn»-[¶°mÛ6:;;¹ùæ›Ù²e ·Þz+Û¶mky@‰ ³}ûöð³­[·rõÕWsË-·põÕW×DÃL7>ªŠD–iò¶SO ½µåºnÝ:Ö¬YÃêÕ«ëEΰŽQ+Å•Çc¦jš´3e6"I{4Þ:S¡Þ¨/ 1DïØ±cÆs6i46aæÇgµ ÆþL&3g"©$ìz®ô'Þ¯VÖ‰{ Y–†rKÔŠ¬“L&©V«¡g’Ô’ú1Éd2bêóTf2<Ï '$"й®K.—›¯%‹ÚBôã×e™ï´k|j4šñi÷ÜV£Ñ4F?;5š¹K;Ƨïûär¹°»ã83Zcv®bÛvX°TÚ0±qˆàQÐt:Úx$}X*••:Z³phçÜVª¼nÿöý ƒbpâ‰'rîȹáz~ñL^ÞsTyY&]Å€ôGkÞw'?ð€Ú_&Ãþã‡R žX¾œMû÷ó?_óÈå¸è¢‹8ûë_gÏe—Í9GÛ‰2W—çûñœØÊJwÜq½½½¬_¿>ü¬¿¿Ÿ+®¸‚ŽŽºººèêêbxx˜®®®qÛ¼ñÆG}Ö××ÇÍ7ßLoo/ƒƒƒ\}õÕôöö¶ÔÞdÈ¢ ¸)ß'¹lY(ŠÔ)?ÿùÏóÇik:¾¾V¼Í'J;úl„}Z–5nÄM£Âó“AŒÌqï˲øÁ~0ãÇ9›4›0³ãÓGE¨'H­U©Tj÷é¨)ê7×håžO &÷„¸àY_ø°X,†[–…ã8¡ð„ MÓ$—ËQ(ÂsI™(©Ã\× …–d2I¥RÁ¶íiyi±TŠTim~OmƧãS£Ñ´Æ\˜Ûj4šÑèg§F3wiÇø,•JadE¥R™sÑ)³E2™•ê|<ÛŠ¼7V*ªÕ*‰D"L]?aJ¢[&’fMÒÏwcö|¢s[ CÛ^dõÅ‹I'¡ð‚²½îèØÁ¿¯ÞÄõo<þ¢#2ÊÖ›þ²Íë·v=ñ¯:|Pãáþï|‡×á ¼øâ‹œ~àÅ"+Ëe(•èèè —Ë-ˆŒ? q É=}6û…–S~ÕŽþþ~6lØPó™ˆ+ãÑ××Çúõëk¶ïïï§³³“ÞÞ^@¥[¿~=ýýýÓ~Ð’"&8%åß,âJ#/ô'–/oØŽ‰òŽž.-Ì÷ýi5ÚÎoú™V óù|Kçl*ýˆ‡ÕOLÓ\P5TM˜ùñé=ä\×%™LR,œr>ݤÓé–Æ¹ã8áz’,^³É4ÍšÉl|LÉÃV¾ ÏójR®ë244D6› Û‘åò;Nã8‰D",€(Þ`S^-Ô}¼~J³p‚Wki×øÔh4ãÓî¹­F£iŒ~vj4s—vOÏóH&“”˪rõ\uœ› &jX5M“R`CÆ4MÒét1Sœîê#W …¥R‰J¥¾ ™LfÌ4DÒf#š½SJÒLÏΰ™3sÛ;/åÄÎ#à‚·X ›vnâ5{_ƒqe˜d€Ôã?Î]w݅뺔J%N¿ôRþcÉoßÎÞ·¾U…µjÄaT3·¬*¥RiVò–•ÎÎΚ²mÛ6€pŒŒŒ088Hggç˜m ²mÛ¶Q­ÁÁÁQ¢Mggç¸)ÄöìÙC__ß„ÚVíÛ†zÆä{÷î­Y× Öot[O?Óaò5MsÚ ÈsAuœ }¦T`n,ƒõm·ÝÖ0ßë|¤ÙØ”e“Ÿwß}wK! .QdDjËÛV‘ ìXHÍ‹ñë9>>ÇzðÄ£¼ê#\âÑ/B©T¶ípÂaYa¨8»ÏdT0o&“ 'çq$¦õ½–£ûÉãó©¿ý[öíÛ7›_ÉŒ1Ýãsß¾}ôõõiѦ-ô÷÷S©Txæ™gÚÝ•ia.Ìm5šé¢¯¯»ï¾»ÝݘÚ9·Õh¦›ááaúúúسgO»»2-´snOo<™âïÇ2R{S¼ô%]¾œÏL&C.—ÃuÝ0·¼Ë‰€R*•”bŽãP©TÂÑ"šär9@9vwwÓÓÓ¦‹‹'…B!\G>—vâËë‘´ÔSAÄ!ß÷yë[ßÊ7Þ¨ç¶M¹m+%"*DõSNª¨ïôä‹_ÀÜRËž?ùy¬ûƒ•'éKÞýðüáïà•ïyù|žGÿàø¿]]|xÍönÜa¡z±½Hêô…ÂL ޳‰mÛ …Q…„­[·ÎÈܶ¥”_W\q¥R‰o¼‘ÞÞ^J¥½½½aDÊÈÈ}}}tuuÕ¤«gdd„n¸›o¾yT4ËþýûG­ßJÈØ²eËj„VpÝ·ßNá¾û¢[ÍA¥Ñp±›|>LÓÔÞø3ÈLEëôöör8œÏŒ56aòãsíÚµ£<Ž!µˆ@Mn¤0žffh$‚Œ…³5‰–‰D£vDÀ‘°ï¸˜#‹Å0\»§§§ÆCI‚è5 *:°ˆúã™+Žð“EîCÍì¾6là§?ýé´ï·¥•®®.¾ô¥/ÑßßÏ 7Ü@gggXœ¾¿¿Ÿ×¼æ5ô÷÷sóÍ7ÙN©Tbýúõìß¿Ÿþþ~öïßÏàà`ÓÈ–VÔËåË—O襳„TžúÁjÒàL3_1DÓ.šÝ4{{{9ýôÓç½'ÂXc˜ôø\»ví˜"«0§Í$0 cB5›êS€ÅÓ5j£Q4L™4ƒš”g2ŠÅb8A—‰7¨‰­a-:4ˆ"/^ÌŽ³ÏfÉ’%í>ÝSf&Ƨ~éÔ´“®®..¼ðBN:é¤vweÊÌ…¹­F3ôöö²víÚvwcÊ´{n«ÑL7ôöö²¼I:òùD;ç¶•J¥é;ŠäPvå)·ñÔÿ,bÛ6M °–e…Îs¥~®T*˜¦ *¶mcšfØÞÀÀ@¸¾¤b{8AKMOÉrP.—©V«†Š9•J…J¥B>Ÿ'—Ë‘ÏçCF"RDì)‹á;§ã8¤R©PŒ‘te‰D‚D"A2™¬ÉÔJ¥(‹$“I²Ù,õWÅòåËõܶ 2·mµL„ ¬ÍÀëξçŽÂ ƒÁ‡{s K–å/.‡¥¨à0&‰¨pÊ-·ðáw¼ƒSßö6Î}äÖ\xáèèÃP? ƒ Í~.”‹˜*RÓ·ëׯŸ‘¹mK*ÒF¡r6làÖ[omùÅodd„[n¹PïŽ;î`ÿþýôööŽ ŸÞ¿ÿ´{| C`pûÉOð(™ äݳZ­†âiša„‰ïûáºâÈçy^é’Ïç) ¤ÓéP˜‘÷NÙ¿Ô1h¡Òî¹íNž®ÀSÞËs׋;¤cÀCàáqÖ)'òø‹-6˜ËA™è»w³ö¶Û &—Ëñ''œÀ·oç3Ï>«j¦´ÀBTZ¤M;ìˆ- *ÍO‰V¨áÚk¯eóæÍáö¢€ööö288Èðð0W^yå´¬£7‚”5­ „V.³¹h¶m»m7ù©šž«4»VÞþö·sþùç·»{Sb¼±ÙÛÛ;c㳸w/ÞqÇA¼'&sIÙ5Ä;GjŸ4’ÎKÒ…¬ êžÕÓÓNe,äÅL¥R „áÞ5uaˆr®ÚÀ3§ÖîÓ=eÚ9>5ÍØ´{n«Ñh£ŸÍÜ¥]ãS´âï/.JL) %ñ„ðâ¤5€W4g2ïžòØÈã¼Y*h³ÎÆ'¿E(©ïƒeY <Ï Û”L ét:¬µS¿M.—[Ðõ^çÊÜöIØÿÝ5ÍÄ™í¹­F£i ýìÔhæ.³5>Ç¡X,â¡ÞC ¨Èmë™YÒéô„m)“1ZKН‰2Ñ}5+~ýë_ÿzŠgjn2Ûs[¸çŸž`ÿó¹àð2ö\ ôæ^eÛí¾¸{Ìvþ{<- „ >øÄ¼ü­oåG?ú¥3ÎàÐ'>1¡þ-¤(ÍÔhIPéïïgxx˜{î¹'TmÛfëÖ­£ÂÁ¦ÊLNf]`ý/ 4V¨›ÿÔ›‹ÅvwaN0ÝãÓß?ÞÒ¥MCz5S§~biFÓ|µ­’Íf'å2Ydâ*ÞGâ!Jl‘ôa»ž}–_|ëó2ÕÆ fn¢Ç¦F3wÑãS£™»L÷øxßûȘf˜¹$¶ó̦iΚÐ1Qâé§[¥X,.8â‰2SÏN‰czòÁYñŠƒ\ÿD?X‚RQqRkßµ \îûàûà8œpÅÜýüóüÉ«^ŲÛog}¡À’B%ŸýlËý³,kÁج|ß§»»ÏótÚýIÒr„JoooM×W\Ñî¾·Œƒ˜°ä±Ç&|ÓÔ ˆ&ÇB*L¯™~ðÒKà8x†¡ÓªÍ3ZI™8ÔßOÒétM¨j¡P‹ z¾Ï‘ÎÎvŸ"F£Ñh4FÓF¤¸ùîw¾“U== jêjæ4³e´žL §fbÊ™gž9¡v4µ8Á¨:-—ÿþÎ4î΄Ÿ¢ÔÏà)åÜ9Vªá;ïdÅŠày¼ñF^iš Ý}7ïY»–¿ºàò@6† ¦½’ú: ×uÃú¸Çº@8YŽowfUÅD]4S½XJ¥æûÑD,ÄÂôšéÃ<ˆˆ›ú&>ÿ˜-A¥‘ÇD6›Å², ÃÀqœðe©R©pêÈK￟}ûöñü²eí>MF£Ñh4¦ T*ÇáÛ‹ñ»;vh1ež0[µ*òùü´yç¯]»vêhX¼æ¯~Ç™ØFðݬD\ÏF¥ÿ hæ&`x˜Ÿ,]Šg,yì1’É$Ï.^LÇ–-Ø’­è·WŠCs6›Õ¶¸IrL* *ÐÜp›Ëç…aµÛW”R*^æûp‚ÆhˆŽ8Ð4Ã6Åè+•оV4cÒ,âMîçâaQ©TXºt)§Ÿ~:¿úÕ¯xzݺvw]£Ñh4F£Ñ´×uñ<=Ë–ñþK.iww4͈©õ7°ÙŠ àµ€Ö"Tú/”˜ÒL [ÜÛËIø§ìßçyX–Åç>ùIÞù‘DšiÂÓ Ïwt=˜©Ñ² ²}ûv®½öÚðgÛ¶mlÛ¶­æ3)\?×òW¡¿h\zz”(R©¨1U((qÔß²žã¨×­3 ør þÍ…Î,Ÿ@YRI‰8Å÷U?„Y.eÐ2z€jšáû~ö3,ËÂó<­ŠkÆÄ÷ý1E7˲0M“J¥BGG«W¯æ±¯|¥ÝÝÖh4F£Ñh4mÂu]–]s ‹¿û]ý¾©ÑÌaøà¶ÑöÔe™øõèõ-êÊ3¸n˜NÈó<ž¸ãüùŸcØ6IàÔ,ÕÐ1Œvjž- *lذ¡æ³ùTÀï±C‡øÈîÝ¡z¿h\l 0 Èd”hbJTaÅ÷!†r’Iµ]"¡ÄÇ^ žJÁß§áH°G$æÄ‘qžJEû«_îûJè‘ý ¥’ú,‘ˆDϋڪ__£™Ë¬Ü»7ôÐ7sÍd©T*a‘z€7ž|2K—.`÷îÝíîžF£Ñh4F£™e|ßÇ4M^|Ó›èzâ‰vwG£ÑŒÁƒ.PS£¥¢ôëׯçÖ[omw_'ÍÐÞ½¼ásŸ£‚X Æša(1Å0À²TtJ*CCj†O@ýO­("H6«~@‰+É$|´ÿæÃ (Tàõ%x‡­öiYJø¨VÕþÒéÚR CµkšÐÝ­~—Ëj]Ó„bQõÁó”È’ÏGm§ÓÑg•Jt pœÚãÒhf 8ô£a½÷½€T4“ömr¹¶mcYÉd’%K–`ÙÏž?úþ÷ÛÝEF£Ñh4F3˸®Ëú7¼õëÉÜ~{»»£ÑhÆà.±‹º°ìüp§‰(‹Q!)cK#´~éRîÜ»—GN8‹÷wÁ4Éçóí>Ä9ƒišÚþ6 ´$¨Ä¦¿¿Ÿááa@Eª\yå•ttt´ûXšr8ðTv‡r¹ (ñCÒf D¢C°‰­TÔzò9(Âq”¨G„•—[ðO%ø™8ðŽ<<\»€ ¦Ú_<ÚTRŒ‰’N×¶Dâ÷€JEýxžê‹@™Œês.¥*K§£¶MS-±E"sŠEµX4³Åã?ù †a044Ôî®hæ8c=ð]× 'Hår™ã;°h4F£Ñh4š…‹ïûüꢋøÈÉ'“ãŠF£™“<æF¹ðàs°[è-4 5zzX·kûÞÿ~Ü÷¿ÿ˜/>ߌäXž÷š–˜PQú¾¾>lÛ¦¯¯ÁÁA¹ñÆyë[ßÊ-·ÜÒîci~;w†Å(gšQ„Jœz›i*A"‘¨]G"ZÑmÁ× ð8ðÉ"ø¬ÌùyØnaB‚¨àDý°m%šÔ‹5H§Õ1”Ëê7¨m«Õ(J%›UËR)%¼HJ°JEEâäóѲxÚ0×­­ÑÒ Ïk^ÆŸ¡—Nk¶0¸û¥—Ât_“ÉgK‘©90 £áub¶mGÅå¨Sž9í´vw]£Ñh4F£ÑÌ2®ë²ãÍoæ¿/Y¢SÛh4óHÁ³ëN…}€ÔŠ>O5Í0¥ÏÏ>ËiçG©TÒc¿ Zdž:-G¨ôõõ±uëVnºé&6mÚ~>22ÂÖ­[éëë`óæÍí>¦âš@| 9NmÔI3dLÆÇ`<X#®I‚[—Ù`£Òú@È¡î P@-ÏfUš¯%hHú®Vú–N7^fÛµ?Å’JEËËRíärª ¢fJ%%ºŒE.§Ú–íâx ”ßWmm'Q7¾¯ÎM*¥Œç"2ù¾Zg,QK3÷9}xxR7lj"°t4Õ±E#AŲ,ªÕjÍg6êÞoÏ/[ÖRÛF£Ñh4fáпa+E› 4šùEÿ›VòÆx!úÝ@#ÛO¡ ~g³‘qÔóøæªUüÆûßù‹_èH ÍŒÑR„Êàà ·Ür _úÒ—jÄ€ŽŽ6oÞÌ–-[(ÍAwq8rÏ=8ŽSc¼m5x²”ñ~"éö àWeõÛ ª£dý© ÄU‘*Àò˜]y:RÙIÍA¢XŠE%VÄ÷!Nü³Ù(µ™ ,B¥¥%«×NÄð¹cGGÍ2I¡V©Ð”JEíÛ÷£teêó\.JkT‘vs9Á2p€åO °Qëšl$…ª]Ïóȸ.n2É9ßü&žçáÄ šÍ4ÓÒÓ¥¿¿ŸÞÞ^Ö¯_ßtÍ›7322B»©èzâ ,Ë üõ‚ÂXFë#‚…÷b*~>3ƒuL”a9Ü7Kç#“¦«Yú3ÈÖóõ©‹H$¢ôa®«Ö/•‹Zž§Ö±,µžôU"…$âfïÞ(JÈuÕq ê³xƒfnâî½wÂ…°J%õ} Eõ …æiç4F£Ñh4FsláÇÿüç¼|åÊimWWcÐhf†;s°8îw^À~È)Û©XÄi½†Àøçy¾ïã8…BÃ0tZ+͌Ғ ²ÿþ–ëíími½ÁÁAúûûµ¬¾èýTùî³Ï²êg?«‰Nñ¼±SvÕ3™±,ÊCºžbðê¦ Ö=j(! ‘aØeúܦ9vtH)dŸË)ÁÂ0Ôg®«Ú9zTýÎfU‰¤+`ß¾U¸®Ë¦M;Éç•!<•ŠŠÞ{žªK“ËÕŠ+’ò ÔþDµxmw C-³,Õ^µªÚ,•Ô~zzj#k4ÍklÂôO8ø£M8å—\?‚a¨ëOÆïG¢ÔŽ)É2¿I§Óà³5>5Íę͹­F£iýìÔhæ.39>+ÀY>8í}n¡Ì¬F³ ˜í¹íþýûyad„%'V<®~Å-FYêJ©¸nè}þ¢E‹E<Ï#›Íbš&éf54ši ¥*-‰*ýýýãÖP¹ñÆéïï§««‹ááaz{{¹é¦›ÂZ,6l`ûöílÙ²eTб‰àÏ>û,W^z)®ë†Æ8)ÖÞn²¨ˆ ø‹´'ºÒÐ ”‰TØLp,C“ÛM † #­¬f1Mõ3V–¦|^‰0¿üåkñ}ŸÇ_J2Eâ‰=´\ŽÄ“RI‰ét”jLöçyÍÓ­Ùv$ÒˆPdYQD¤ÓQjEMsÆ›0½ã³ÿ¹çXÿøãޮѸµíHøPjî¤RêÚÈçk#Yl[]+º>Ùüa²¹OJQúÙŸfbÌæÜV£Ñ´Ž~vj4s—™Ÿÿqè«~ö³v¦æãСCíî´Ў¹íé¶Ï¢'Ÿäð¿_À3òáxþ”–æ…ïzÓ›pªU,ËÒ…è5³BK‚ÊW\A___˜ú«}}}tuu¥288ÈwÜÁ¿þë¿ÒÑÑÁðð0¶m³iÓ&Ö¯_O__7ß|3½½½ rõÕWÓÛÛKWWפ®,ýÉO°mÃ0”_’RªÝDiÁÎ ~?a@Hÿgƒõ,¢H'öyœQTL•R¬Þþ,Æç–úD~¤R­ 0 Œ×–ßþ¶ú÷îµ@$ÌÈyÁTÛÚ7 uolv/4ÍÚˆIQí•DBÓõýtlÆ›À´ŽÏçž{®añ8ž7ºÞŽëª¤8¦¨qͲ”˜V.«m …HX3 µ,ŸoýºŽ¿ Sg¥^çEר9ɪ‰R_F¶Ÿ+÷¹vóý×ðéO·»Sb¶Ç§F£iÙžÛj4šÖÐÏNfî2ãÓ>|æ™í>TÍ1Æ£>Úî.L™vÍmwÜvÏ ¬äô_R\üxœòyÈå¸}íZ®èè˜p^f*´”ò«««‹Í›7sà 7pË-·022.¡¯¯[n¹…-[¶ŒÙÎðð0›6m¢££#lThW?¡ ³~ýzÖ¯_?¥š,ðÌ¿ˆeY¤Ói Ãbժɥðšiö:ʸº§¢ê¯ìEE¤äˆrVPB‰¶S$ÃG‰/%F§ ³må¹ßªÀ`a§Iq饋ÂýÆ×ÙlkÆlÛÛÀ,†si_Dé·i*#s±¨ŒßRWE×W©e¬± Lëøô€/¾8¦×@©¤¾¯D¢y*¼8r=U*ê»Îç#‘-ŸW×G2©Ä𺻣ë¢PP×¹¤“:<’–ÔßR?Hêöd2*Â*^ïL¶‘¶‰(rª»;ú,“Q¿{zÔú’šÎu£6J%µJ©Ïr¹¨¿‰„ú)•`Õ*µ,•ŠŽ«åïÆý·¤ÖóçiÂàO>Ùî.L™ÙŸfbÌöÜV£Ñ´†~vj4s—™Ÿ>°lÏžiï·6ÕjŽÚ5·=øëåtw‰>kЉQ/Ÿç?þ1×½ôR»O棥 KJ¥R²ÿ~FFFèêêâæ›oæŠ+®³+®¸‚+®¸‚‘‘¶oßN?ëׯ§··—[n¹e”¢ÙÙÙ9nN¾={öÐ×××PÌñ€ ž}¶æ³É{€Ï$§'Á¯@GÌ£Ü@E«˜ÁïLð;‰Oâz„¯D°Ø±ÏÍàóñ& ”pSŸak2øG޼šÏ}îvV¯Vÿ7*xß åòØË-ktJ0ÛŽŒÛbX—È¡PhžJl"ôõõq÷Ýw·\?h®2ÖØå¥0™ñy÷Ýw³uëÖšP87&ÊÆ‘º7RW'™Œ~r¹æÂŠ|—q±4^o'þ]KÔFw·ºVd_%މò·Dwe³êsqJ¥(½\©‰x Ö œ&pœÚëUÄ¿x$I*¥öW©¨¶,K­—ÍFmÚ¶^²Yµ¾e©~È~eI™çºjýd2Fey¼Ÿ²ÿ¡¡(=šD½ÈyrœH䬦e}9Y·] ³uëVöíÛ×¾NL31>÷íÛG__½½½óþþÕäAë¢Ö­Î+|ÔMðëïï§R©„/jó™ÙžÛj43žÛN|n«ÑÌ2·Ý3BÁl3ÓsÛg{{YþÄÚ[]3kô÷÷sôèQž­³?ÎGfrn»iÓ¦¦‘,'¾x"¯_ý¯ñ\~°ØØ`EI«Ÿbš&«õx×4aëÖ­32·mYP%ª¤ÓiúûûÙ¾};@hŒnùåoxx˜[n¹…áááP„iT£¥•±eË–5=)O¼ðBMZ¬DB ç"KMØ„ÿ¨ò([ª«§%®ˆˆ’F -•`;HÙm*@ÌÆL)Xß ¶5Q¶¡¸ ã£v>‘ŒY*…Q¦ùvgæ#‚ >b´ŽßS+õ¹¤«T¢ˆ†É¦ëííe×®]3{€³H£± “Ÿk×®eÆ 5ŸyÀ#<«œt7Òiõ»^ôšN1t`@ý–ZA¾¯…%(¤RêÚÑDÒ{%“µ‘SqáF®©r9ºÞ¤†K³þÇ?“ô_²ÓŒ„‰41MÕG×"psœ(u_¥Epyž[äœ[VT—¨ZUëJ;"É:©=-“þÉù+ÔýÖ4#qHRœN— 9â9ãN6¼n2ãsÉ’%:­‰ü˜M–%€ÔÃRBE…T°¬‚z@fQ!¥yÔCÔ¨[?GôÀÎÛÃtuu±~ýzžxâ‰vweÚ˜­¹­F3Óè¹íØ4šÛj4³Ìmïºë®vweÚ˜©¹í?/íØñŠW´û5Ç]]]œz꩜tÒIíîÊ´1sÛÎÎΦëôxî{èB–Š¿ÕyMV£‘e±·Xäg‰¶mã—ÖDs̲aÃ~úÓŸN{»T:::BÅ2Ž ¶V•õë×së­·222ÂÕW_MWWWÃ5<<æÐlÆòåË›¾tžöÌ35…èçbª/a×'à@šš‘föcWrÁ:C(qDì4bljëG ”1Û Ö«릂ÿ¥Í ‘ÉÚ*6èƒO)SßÏ@(ž3Ä£$íY¥¢ú8ѧ··wA¥h467mÚ4éñ¹víÚQëxÀêG Ǧ ÑÍDÏév8ˆë9r­Ê¾óùHd€Hp‘ÿ› pM#×·ß*==µçÁ0"!¤Z‘VÓpÙ6ìÝý-H¹¬>ÏåT›Å¢X,Kýeâ—ËQ´JEõC„WÙ¬jW¢V\7j"‘G*ÏSë=×Tjutt„^4 …éŸòÒyL’B=g%wf\ ‰#×_õ ³P70‰H1P^Ë (ѤDôPÌÕ`_éà·K”—3KëÑ- ˆ®®..¼ðÂA&ÌÖÜV£™iôÜvâs[f6ÐsÛÖç¶>°èÞ{±>ðv¢æA•Oœ°‰uÎ2ÛsÛ¥¯ØÏÙ#'D<œÛ`ÅBA²Yö 8LJïû‹E4šF¬_¿žµk×N{»-ÕP™.¶nÝZ3èèè`ýúõá¬Û¿ÿ¤½gãvF1îO¥xôLs†mX7ÁíòD…çíàïf™DÄÎÊveª‹î@ð5ø[JCˆ`ã÷Ÿ']«%îÞH'öcíÎb–ºr], öI3ÖØ¦u|úÀ’C‡j>“Âñc [¶=óQ qâÏcI{5ÓH”H³H–l¶Vd˜Œà Ñ5Ùl”žKR–ÉqWßHÒŠy^¹cê·¤K&£ôi¦Eú˜f”>MÒ•ÅÅN©#5`2µ®DôJ?A}v,ŒßÙŸ³ÆL;%‚ßF?l jsdº¨‡šƒzÈ‚‹H1PbH‰HD)íxÁgV¬=7øÜ ~ŠÁ¶i”÷B}[cQÿ€-?ÝDu¯ÁzšYa6綦uä³S£Y Ìôøt=¿úU»S£™—´kn{ÜÈñüñ,ë Æî¹MV´mð}vžsßìQVÉì\6öj,³*¨€œRÔ~dd$ÌÙÛÛ9•7sxx˜+¯¼rRûqUç£ϧâí<üaΞÂ} Qý“8I"ÛÍDì.’ ¬‚m2DÑ-y¢š.q»j€^¼à÷ªàï\ÐN)ö¿ôiÊNT Ö™»›ëªï_"Rl[yú‹áz"…»*ÍÆ&0­ãÓÿä'5Ÿ9NdŸ‹HÅL(ê‘(é Ÿ¯M¬IÔspœHâ‘4"–ˆð"¢ˆ:R;FêÅ”ËêGjçÈù–4e’†M"|E\I¥Ôz)³P™­ñ9mH:-b¿+D"Fý=·B1Ò3nëµäbûACD‰*Dè°P/Cþ®Ôm“C=ø|¢<™Ê{¡•Õà~†H41ÁY îÕÁzITDŒ´ Ú7ˆ¢d\F +ÒO(ŒÔ%zûDEÖ<"‘%ŽŽzŸ5fkn«Ñh&Ƽ{vj4Ç3=>/Xµ,4švÑŽ¹í“§pÖ"ƒ‹öµ¾_.óô‘#¬Ü¸‘J¥B©Tfš™Õx´M›6±mÛ¶0\lûöí\yå•aQ¿-[¶pà 7°aöoßΖ-[¦T°ôÀð0¦iιôSÍxÁ€E3Ø~<;ÉDN‡E”þÝ&²‰>•EÙ¿$•|5øÜ¶á[9ä&bÛ§P¶ jð¹C”>,´Ÿ >÷‚ϧ¼÷¨×¿0Mõ“ËÍ]cþl0ÞØ„éŸ>À£†Eãèç>j HÎ;l¨°Ð #QõÌôõ9™úRêÜÄ#{¤f‘¬›É¨å¾EªHD ¨ß‰„VâÇ[ŽêéQâŠiª¶R©(Õ˜ÔG/Âf¾1›ãsÊHFõ@AAj‘Hº,1öKú-PãN ½ƒõŽ¢ìÇ‹‡Iá°Q¾JEây.%‡%êÿоÉg¡° òêÁ”‚U?‡½/Aå$à"0=(ýœUÀÇ ûYð.‚ÊÏ {;T@Ö¿2ð'P~ äëOCî AŸKêú.|Ò?3‹JòD÷ñR–…Ï€ù)HžN6zvQ Ρ þ!H% ÿX‰A l<Ì5f{n«ÑhZc^=;5šcŒ™Ÿ¿~áÎo÷Aj4ó”vÍm—úðÀ< ø¾išd³Y’sƘ¤9–hIPéïï7—®¨—ãqë­·288†…ÅCÃ6mÚ¸¯_6QÄ!Ö4ÍÐû}.c0Ú¹t&°ˆœ€[EÒË'cÿ×÷=ž^~°2ØÉQòvmäŒØ[Í -LDX‰;Ë‹ãn‘HtÉe7™ˆ;îÝ/÷ÛxÁìc±Æ&LïøŒS ®•ü¤Ïƒ¨¨xqJ±eb@xj?¶}œ‘úh .²Yòô¡‘ 2×îaÙ¬3Êãµt5ÍÄ™í¹­ \ðž'XsÏËác Vøð‡áïÇáËü YÓ¤R©`Y¾ïãyžóšY§%Aexx˜ÁÁÁq×kµ€æX‹¦s@v>ý4tt„E‘ç2’z}¦»iÙª[Å 6B¤Ñ¶q‘Å6›°XÓ¤B:ø±Äh²®,¯Ùì$Æ ²¥5sâjVQ((ÃVÜû] ŽK ¢øç®;‡"'fñЉM‡Ðiž)žW!)n=¯h€ˆ‘U¼ß3Áo?¶}ŽH¥sQ5 $Ô2¯ö¸Â(9ììºþÌ¢a~¾DÔ¹Q¸Õ{«aÀÞ½µÛ7‰Æ;v‰€‘õ$­X<ê¬PPÆpÛ†E‹–µûTM3=>'DSˆÚ-ⵌ?L$B"DÄR·e¢›:Ô &~°\ÈAîçQdcéà¾̯‚ñ‡þx)(Æ(ü#÷‚µ J«!ù6HÒAÔT¡©u„®WU"ðU*P,]ßHœ7,)HD†ˆXl™ÀI >O&Õ2σêPùkH¼ ª¿•W@.Å[jŸAñÇQ.§öižÉN(œÅ‚³Œ/‚±J·Õ™ÀÀãú”mf-âîXb6æ¶fâÌÙg§F£™‘ñé¥~×h4“g6ç¶=ÀÒêð2àvàºhY0<Ìñíº.Žã`YV¡¢Ñ´ƒ–•M›6Õ„_Ξ¼ë.ŒTª&ͱN½ñLíc¸* n‹^õ`¡ìp3ª{¹¤?¦¡¾—’£ö9×"â4F£ÑhZåÀð°öV×hæGŽ£?7!zÁÊç±+ à —ËQŽç×hf™–•‘‘†‡‡Çõ ˜Kˆmܲ,‰ÉïÚÑç™$‰²MÍäôBŒEÿPWJÑ•°FÌOi¢”ûNðcÙò$ŠEêõ6¢¾°w>?º˜µxÏK*!Íô §Ù¬u†DH±ˆ"D|¢£VDÑFß“l/¡Lˆ‡A¥šì«À¬Õ!˜/s‚ð»kc N¶EÎT&šßP39$"Ôø‘¨1“¢†»ÔÖ2q!· ²+Á¸1ØBÑÅyX×3þ.Aj-Ø]0°[E£w€q8?ã\¨~>ÙŠ~±H¦FH$c±8ñÈÖtZ¥ýšÊyô¶ÿªNÁx¢†ï× 8Ñ=,Dq~(¨!æAò2¨¬ï.ðÖ+ýØûE(­„ì‰yJµYÿÜ+ÔçÚAE£Ñh4Í\Fò Ú;D£™?8°lÅbŒÇÁhô&^“¦I¡P ŸÏ“Ïçõ8×´•ã[Y©T*Ñ××WóY__ÃÃÃíîS<àÈ=÷Œ2”ÏU,jmR3…²1Ï´üÊ*ìqáe8ÿ&ÊQ9žá©¾„…ˆ$ñ ©9,‚J’æ¶ó|¾±W½x½Cd¤ªT¢bÙqݤ™8.pÒ}÷…¾T*fô–‚9òÅNgäf+ÏÙ$AE°î©§>Òî./|¤Ð•(ÜejNƒ(–Ô.B­ë©]Ȩ“Ì?ªOAÏMPò¡gŸÒ`œ µ îƒü÷Áøo`ø*ä¾¢ömoQßÿTæÕ¾¯D¹É2•¨-l(=˜QÝ•±°,Õ×PPIçXR"±e&Xß3 îÈß ¼Ùà­…Ì·*Aªòê<ärê†Ê—Àùp¾3…cÓh4F£™<`ù¯Ýînh4šq|Xræ¬7ƒ¹Z}^óJ–L†yû«·|*•jw×5Ç8- *¸å–[æ´ â'ŒŒàºS4pÌR§d6²Ke™yáæ` ~Uó&°£"* Žd[’4ú4XGêŠÛ([R2¶¤ r¹Æ)TâžÈ®‰*£W´ 2y–¿ð¦iR Òª%FYLçBjµyp¯8֯ƌaD5’~ýëËÛÝå……D™Ä‘”]]5Æ}ß9*«!åAÂQÏgËR‘YÖ_Còw`ï(Ê÷Bù›ªŽI± é  |è`€õNð|ðÏ›š"˜æäÓ<ÆçFã”cQÑ&© ›aAòzuΪ éG xUó`_Å#ÊqÀÿ.¤_É¿…ê;À\ •?ï»Ð}ä®Ì5àÝ9õó®Ñh4F3]ìÒ)¿4šù„/¾í±¨8fÏ‹<&\N½ŒVçC"Í‚fÒ‚Ê\gdd„sÏ}…‚®Ñ–šp¼ïž §pÜs¬ ‹™×¯S¯kä‰D˜ªtFÜÉwÐ7Nq)0,5êÓé¨ÂÉãûwîdÕ¾U¸·]ó}¨EG§L—î¾›/߈wX’"(OmÍ…¹F%¨d‚ߪVA!¶Ž¤2ª Š”‚ÿ±m@y÷{A[‰àw\´+mW‚í*ÁÿRã%Û¾'Öv)Ö\lúzÕL'¢šG’Æ«î9[©(ñ$—S5EJ%õ¿ïCùïÀþ¸ ¦K¸(—çG´V®&ÿœ{qMJ4IÅVÿ¬¾¼=`ÿ¯àÿ U›¹²•çUz5ëo ™‡êwÀx2è> Rï‚Üû£HOF£Ñh4šÙÂöÎàÄPûÃiÆâÑGmwæ€ 6Y!–“Ùu]r¹étšô|HE¤YдT”~¾á=Øc¦†ÑÌWYðÁi³Äî3Ö×è3Ú!×B¥Á¥„J¶³¯iàÝ.i^Û²eK» ؽ{7g¾°~ÁYæ Ó‘eMœg!²ßÕãÑØ~$i¿j354á^Ê«`yÇr’ojwo&ˆˆ>ijk­È…Y¤öb”t:ñ‹¸%r ÅÖA£B$ÚÄ÷GV|ÿ²~5 ²±ýIôJ• ²7‘S öY Ú-ŸW¨ubÄÉ&²cËêï³BÊÚ€ŽôŸFä†/znªûc*¥Ä’döîm|Þ§$¦H¨ƒXñ –bjÙx_´ï+…¢Q'J%Õ®„#ʤ!—Sƒ¡¡æíº®zHHÑ×UÛMD-¯(Ð P³» x}ýòâ·ê>mÓì»ÌÞ4éBÖïfpïªàþ¹z®¦Óê”—JðÆ7Îêak4F£9ðS¿hÚÀùçŸÏ®]Ó”‡øäÄ# ÌÓ¥RÍûžïûxžG>ŸÇÖ^Κ6Ó’ ÒÕÕEWWƒƒƒág½½½s¶(½ ¬xðAþäO6iAeSÿÕ5šI@ÀXÁ~‘Í{Ïj¢%¶f“ sS!2 n·”íжG *…Bd?ÓL ùNû~v*émwo¦ ƒæ©Ê⋉)=÷¨‹x2s‚&FO’(E>Ëÿçˆê&ÄE VDˆ‘¨)z-‚L&8ÞîØ¾ÊDéÏD¡BáãƒSR“Í’iY°bÅ“³³³cI5莣ôƒlVÍu=¯®HútàºJ±1Œ(´Â² §'(¬bGê¶ç)$™¬U zzÔÿ–¥¶ñ¼HŒqÝ(¿£eEJºëªv$dQ¶1 %èX–ÚW¼ œ„Fá8ž§ÂwòùHrul{÷ªÿS)ØûwÀªÚm¥ŸÒÿé¤HÃȴɼŸXqñ0å~² ̇ä.ÀƒìO¡Çƒîî%Ó{,F£ÑhŽyN~î¹k[›–4c±bÅŠvwa^²Ûðye 5n†a`š¦S4s‚–•M›6±iÓ¦v÷µe\ cÇ2™©-4ó†¸Í5î g¼”`’• ”-ø5yu}HÔŠü °) œTF¡ã€Ÿៀ ð¿Ų”}M31ä{ð<oäÅi³Ð-‰f™Jh—\σ/—‚ íAŒ×€mDûŠ >IT–µ*j£d$FêÝD)Ë<¢”bn°ŽÔñcíH$N–Y‹`Ù¹ó5³³£…Ž|÷©è£\N]^’.±)¾¯~'. 3òùÆQ¾¯D†rY‰Í‘Ï.ÂâyJèH&k·/Jy½ðaYjÝb1ʯ%ý’}˜¦jÔþA ."lÔG¯¸®štÈÉÈå¢~š¦úJ©u u>â“tšüŸþðùhûlVµ'Ç!ÿ˹Èd¢Ï'à ߇½}@R¿ Cl0(¿Ê÷trÚi3»F£Ñh4Ç'<ˆ5C…tÅ×Wf¦¹Ï‡ÅŽrŸyRí‚RiÔ;¢ã8:Í—fΰ ‹Ò{Àöïn×é^’i¦­æ1•hqÀ—´` ìÃûLe¿’ô`Ê)ÿû%ød.ÖNà€¬™’ýÊ0 ’¿ÝîÞ4AŒ¾¾¯ ¨¹ÜäÚqÝÚ"®Yë—y<Ð ¦Fç¯K¥F_l~,ù].«V©Ÿ\NM:„R Ö¯ n„• l-¨} ¿QW1ú ŽÝ.pÁ$–÷Î$}ìØo©ï/R^!RE]Ô`ÊË @O°ŽÔÑ ‰ç$á%e Ä”àû— ±ã'“c͉DT^±Ä4ÕoP×™¤Ú’Ðî%`Ô‹.õ^IŽ£:_O®ÛúüŒ–U;ã"ÔF³H[RüCÚk$` ¨mâÂL¥w6«ú˜É¨“•Ï×öͶÉ=tŽûX„RR„B!~âç5N¥Ò¸ˤ ´Lœ|üSÀ<žš{‡õüøÛgpÚ¿¾vÖú¢Ñh4F£Ñhæ.ð+^þðq£ÊûN†6ôjæTúúú¸ñÆÿÏ?ÿüšŸ¹v%FÛ 6è´LÇEjËQ4Bl¼”=Ø&J&ËÒÀ/*ðSW­G°¾ \Ö¹œú›»frX‡“ØOMCC®« ‰==Ê@ÇqÔ2©iÐè K¥ÔCº~»J%2ê½›\W†µ—H@w·ú](Ô-+ÕÇžž(-P|ÙÚ4¼«.WROÏ躥RmŸóy•.h`@Õmˆ[´>Ÿ†ß4£¾gíH™ÜZˆŽÃuaG;ªÿ†‡rêÒ-«.¥¦D• £ ©4k¦EyÄ—ËøkõžËEÂI«ÔG¨´‚a¨ãšÈÄBNRý¤Œ0õd¡'Ê4fYµBIÜKDV2 uÎD釷¤Óµû–ˆ ø½*•R÷2I+ÖH€š"¥dÿ<~.<|îËø»ëîFuú™œÛj4šÉ3ÛÏNFÓ:Ó=>}à¤ûîk÷ai4 ‚Ù˜Ûöám)¸õ'Ûº{€8Ž¡ŠÑT*•›´FÓNZTÙºu+·Ývëׯ¯YÖÕÕÅ–-[èììäÏÿüϹí¶ÛÆl«¯¯­[·²aƇ‡éèèàK_úlݺ•¾¾>6lØÀöíÛÙ²eˤj·ìÛ·‘‘sk2ãhŽ]$ûPÜ>+vÀ¸Ùè ¡B¶ì`=%,1`ÀƒÜíÀRµû f€±Æ&0åñéç=ó ‹–óÊWµ¸QÜE>n½ÏxjšÍ«cKéÉx¡§gzŠ4e³à50°Æk>Ä÷OCÔêñ×{ãKqìøñÁOÜh+Ëë­çuiŠÈd"ãn:….ˆÐ%]1“àYQÑœ©"r9ØêìRiÀúK°Ø…b>`¤N‹Zçm>\l¢ËLÏFXT?Æ`P}&ºÜ¨àŠdR}(ž j¡ÁØö}Ïó{#F¸™hÇÃÀs¹Édrô¶MPÏóð}Ó4GOØì¿Ñ>+• ¦iª}NЃÊ[¹Ç|è­£õ}‘6ù2â©…èÖ§MQ¢{K©¤¶ ÒýcH—“ Þ{^êxiÒíÎ5fcn«Ñh&N;ž¦5fr|Î…Ì)íÂuƒ α)èd}e$aƒï«©¢L5m»¶|§ï«©£m¾v^mÉDiÃ÷£é§øÉkaüµSÏ #zµŸCñ”í¤Ýú²¢²ßús2ÌmÛµÓeéìW²„‹Ô’%íûÞ§›ÙšÛÞU€ø¼3w.÷Ô/Œ½·$ lÛ&«Óiæ- *wÜq½½½£Ä”8›7o¦T*188Øt½ááan¹å–aƶm¶nÝÊæÍ›éëëãæ›o¦··—ÁÁA®¾újz{{'¤x:ÀKO=Å¢Eçs ?G5uŒW¼`%pØ‚**J¥DE‘‡ *‹À#>ì¶à½øë" ‚ñÆ&0-ãóñûïç´‡/þzœ%5ï«YV3qd2˜æø‚ÄxLÄ~<Òiu±µŠÔihå8ãÇšæç Þ€ÛÊ4nÜo½x} ùZóyåR¶.X¢Ϧáô¼ªN²`e5–·Ï…˜PꆓŠÐŸ\ÐU"gk|ÖSø-0•P ‚’LS Éð2! Ôo¹Î #*¤>Á·¸B¡@6›¥R©„G©TbïÞ½á:®ëâyÉXG*•Â÷},Ë¢T*aÛ6®ëâû>ét:J‰É@€¡¦T*‘N§C1Äu] ÃÀ÷}|ßÇ0 ²ÙlØÇq0 £F€<ÏÃ4M’Édø·ã8ضmÛ”‚·4×uÃ}JûžgbšPø—×SýÒFÜt7è›ëº8ŽƒeYɤÚЮ¼éò¦Û,/޼ é´ºïJ­ËR,¹œ âo“Ž3FÑœÃh¬í`Áàg¡Ò—çœa6æ¶fâ´ëÙ©ÑhÆg¡ŒOÇ©õI‘i¯äE@H§£Òvå²Z^*©éV6«–U*µNKŽ£¦e†¡¦a©Tôº•N«ÿ"‘CêÊ~EX©T¢)\>¯Ú”¤ ®0çóêï|>ʬmÛÑ블µí Ct0½O§#áÅó¢¬Û¶­¶ËåÔ1 Q©ÁdRõ ¢ò¢ñr£årTZ1VmŠbªŸòÚÑÓS;í•,½"¸¸näO™ÉD5 ŇHü7ÅײRQë–˵}“ïÐó¢©v6]Ž«Vm¾ÓîËrÊÌæÜöUixßyCüüÈâÑ c_l1xÇô&š¶Y£™AZNùUϦM›©Ís×ÕÕÅþýû›n3<<·š9„Åèzßõ¬MÇÒÒŸ% RUц^p¸¿Þ~àWîÚÕîÛ2cM`Òãs×®]¡ÈêKŸ~žÓž= 6ŽÓ!˪­«0טî|‚RØg&÷=Vаf´N;‚—ü}0S}{LpóðûyØžÿáÃw ð‰,\–Oåá§iøRrIøm®1áùë¶oßÎáǧ޷63ãóðáÃô÷÷¦ýK0¯7È:%/Hé4êxaô:<ßgÝÓOs|©„ŸNc‰D‚|>_-R(BQADŒB¡Š ¶mãy¶m“Ëå¨T*X–…çyxžÇÅù—œ ”J% à ˆG ÷ÑÝÝ뺡˜‘ Ä˲ÂÏÊå2ŽãP.—Ãþ¹®îÏqR©T(œ‹ÅQÑ)"°X–E.— û-m …ð%@úšÉd(—ËxžG"‘àôÓ¿ˆm_ÎsÏ=G"‘ÀuÝPà‘cˆ·#b7e˃ðafFãÂâæÿî¤6‹ˆd–¥ÞàÅ5P¶ËåF×vªQÙZ»¦ï¿ÿ~žþùé$md¶æ¶ÍlÑßßÏ.=·mÚn|n«ÑÌ&##jn{àÀvweÊÌÔÜvppçž{ŽŸP©à êm¶¦ '!‘‹>÷¼À7,È|+Ž$2U’HñSá£XŒÊ~š¦G¤ô§yK†éDBm°.Õ¶}‘N«vê£0dz&ýPÇØÓ£ú^­ªýU*Q¹Ãdrôô^^ E¨ˆûéÈß"ìÈ>J¥()‚øëñ~Æ?—¬¼"¬¸îhB™žBmn™¢–Jj\Nµ¥õ}uì–¥²[Ë9)¢>e³‘`¼oñé¯V’¼âŒ3vñÙÏÞÅC3©ko.1“sÛ 6„QhßÎÀ¦×.áèùGjÖ¯Ï%Ëå¨V«º~ŠfR ÎÈܶ%A¥³³s”PRo€apppÌvz{{k^GFFضm›7ofpppT›aξf=„¬ëÉd’D"A©Tbhh¨±H˜Á$?{ •vZ·ŽÂõ×óï¿ü%—ç<žR,NsÅ’Ï—óÒ‘#d³Ù0ú¤R©ÍfCA'žVLÎ_¥RÁI§IõôÔôOD•jµJ¡PÀ4MõY6‹UŸ«þï«7úú7SÏS÷î ä3fpp°æ…j¾2[s[f¶X(‚ÊlÌm5šÙDæ¶lwW¦ÌLÍmøôÓìÞ½cœñ)’ŠªTRS1¤×Gh uýõ°^<…ú± 4Œö1¼Å‹)A–¤T›¼«fˆ„x‹¨À¯¯¾šÅoxïY»6áý`=/èÇêàóg O ÃU|1;÷²Ì÷}r¹\˜ÞL–Y–E"‘S¢†¦!«owÌ"òf_ÿfžN«ûw¡ \üÄ]o d®Øß¿r~Ř©¹­F3›lÙ²¥áµ;Ÿ™É¹­F3[HíZ=·mÌÊ•+Y}Ùe ßy'Ö‡?Üp Ä•O©”šÆäóÓ›Ñy²Fôª3YÁC3{H*0PsÛ{ï|gþ§üŠ3sÛŽ§w°×R˜¤RêwìÄqÇ©qXÓh&¦M›Æý&CK‚JWW›7oæ†n`óæÍlÚ´)4R°~ëÖ­Ü|óÍã¶522 7ÜÀðð07ÝtSøRÝÙÙ9jÝááá {ÿøÀ¯ŸÅ“—ž>í'kFñ˜ûê>áe-rP 7øiÝ9uÖ1`Ü(’ß4À‰Ùq“±m—špNþ<˜ƒ‹=à±%Oqó ¯½°TRqËðpž-*•JX#Á²¬I ’ŽGº ¥R‰|>ON y£ š†aÉd”GRïA ¦ÒV>Ÿ¯Pd²O $u$@¥)’}N1ÂÎ ãí§am dªÁºÑ†' ÈC~®ßT[g¦Çg .x;¡úçÑG• d+=lxàr½½\»†äÚüÑêÕ /[FùèQN¼â ^\±‚פR|fõjÌ|žåÀðÙgsqG‰Å‹q< ê~[!z¬Ôg¿³ƒåy”b=Á2sÍ_ñ ŒÅ‹qˆ¥v°®ƒº,L”G¡ ¡DUÆ'CLp öo9"QÆRW]E6h7‰e¶IÛ ÿ烾øA_lÀ_´ˆÒÚµdQe“Œ`›B° ð¡¥_Å4?Æc\LÁ41cëz(áÆö¨ÕmÛ&“ÉÍfkP÷ Pd,ÇïRïEDXùNmÛ˜Bp¯±b÷õ%˜pôh”N*ŒJm¥cÀ 0Ós[F39fõÙ©Ñh&ÄLÏEMR¢ jªR.Gé§Òécb𢙤MüÕµ££ƒU«F–œÙœÛvn;ÂÊ¿Ä<+pˆ¯{ß—ìÍ\£å*[¶l¡³³“R©Ä-·ÜR³¬««‹[o½µ¥è”k®¹† 6pë­·Ö|¾~ýz¶nÝZóÙþýû'UØhxø¿÷{çMÿÙëJü¡+.®¡Åe!/T0‡²Šd w#CÁöãÙ-}”åÅ ²èHª*Ù¿Õ  ‘%f2ˆÅHì4‘Ì@Y}ÒÁ±‰"Q ².É6î…bA³ˆ¬Y³|Ï”¯Pˆ›ö}ÀÌÃe±u>ä@<!è)MÇ&LÏø4ßZò$ö»,¬T”gs) $“ɰ`´¤ 1B„ˆú´@bx”bØ"ŽÄ Rg2™°Hµ¤æ£æªU«Èçóa™Lß÷Éf³aª1t …P ¡'•J100€aär9Êår¸iš¡§º´aY™L&LÁT¿Žïû$“Izzz Ïž˲¨T*c{³O)j>$™/Àw’÷á‰øC|dxÀÏôø¬! å³Ázô‘}ÎN8brû©§âÞ}7 ]U T(P=z”=×\Ãå;wrïÇ>F’à°j 'w¿ð}«V‘>óP3%FdP"DC_u‰\ð;ȺH6X–yá8ÿ|ÊÁÿ²LJÉUš –‹àR ~7ˆú¢Ç–°7ø-Q3‚œ‡úÇwýû¹<ò‰õÉþÁçÿt}Š×–àðé‘SÈê1KÐgèñkå6MÓ4GÝ£ J_Ç¶í°®M6›Å÷}º»»I&“$“ɰ†L¥RÁ¶mLÓÄó¼0ݘԡ Å©ø)I¥“Iå*y$É÷|!š¹­fvð}¿æù9Þ |\ˆŒ‹‘Rë)>î¤]ÙFƪïûá³µ~›ø¶2e½¸³ƒôÓqœðÙŸôKö)Ç‚qbVŸfBÌÖø¬TÔ;»¤ ’2q ÅÍä?¢l6šÚžþù<ýôÓíîÚ´0[sÛÕI8÷S'°ûyóÁ#§¬…B!|Ñhæ*J¿yóf6oÞ\“¢¡³³³e5rëÖ­ŒŒŒpÅWÔ´ÑÕÕEooo˜´··—ÁÁA†‡‡¹òÊ+'t@>°nÝV>ô¡«ZßHì…i"—Ö*µyBâ Éõ‘Öc X§@”G$…²Åï q7ZP–J¬‡ÈÍÕ!²ÀøDÖ"É#âmÉgâj+ËKÁþ+D–˜!”%,[)X^&rƒ5ˆ,Câf遲²N‰ø!îµ²/jUŠn@jKnÉw"Ç*Öµz+—‡kÃ}TNIüPGMÐ^ýêųߡif¬±9ãóÖá+ùP3¸1~hhBíL–¸10n|°,+ŒqA¢A$*%þ‘!^,Ûu]ªAB]:$:$.Ž”J%Š1Ñ _çéµé¹2™LâZ%ìehh(4Š–Ëå°b©7¶Ègb\ÂbàÉdÇq0 ƒ£G†êbXêéé!›Í†Q2qiš¡È#ÂT2™lèQ2fÄËdÞl,K 1¹œŠ×/d!—…|¹·—7ÍÊÕ5sÌÖøœXÁW”σÿ¿¾oHó…B—>ÿyV'?÷7ù>w¾úÕZ³†‹~ücªu"›Ü3åSëÜs¹>ø;žöJ%ceÇ/“Ç¢”¿ÿý0/‚A$„XŒ>䪛ŠØ,Úq21\ñ>•ó²«ÿî~>“â_ŒÞg#Ñ0)"!ÇŠCCxŒsšf‘:+b€µm›U«V…éÁöîÝŽÛJ¥‚çyá½ „盦Éw~ücü .`­"¤$QeVÓ„O~r ßÂÜa6æ¶í@"mÛäÚ¡­X,â8Nè 5z,Ë ?áÍ÷}Ç¡X,R©TÂgc<…ƒïû ,ËÂuÝСAžg¾ï“N§©TÔD\®ME¨QB„ q åì Çê+2?qCžÉ‚eY¡„8KÈó3¾O9ráI§Ó”J¥0¢L¶1 #ÜÆó<ŠÅ"©TªF±m;ü ·1M“Ç!“É„çBžõ‰9RËÊó<²Ùlè !ßA¡P P(pñÅÏû>³ýìÔDâ`|Þ×ÌV/,Êÿñ9z=rO’ñ=åwü ëÉ8ЧÁiÜÜÃâŽr¾šŒK×uÃy³‡ü–ùö¼IßÛ39>|ðÁðoÇQ¯Õê‚ôçд×zs‘ٜێ¸°ç™ÿÄXñ!X±.¿¼f¹Ü絘¢™‹LHP&;Áfxx˜k¯½¶æóÍ›7³e˶lÙ 7ÜÀ† ؾ};[¶l™pÁR¾û/Ç_1Gdé)¡¬"˜H® Ì·ÊÚ!†%šk§eå‰)“ÜqëD“˜±~ØAÛ.‘ãÛ‰ªä)å@ñbí'‚õêó‰È‰©¢Ä ÉWµŽ´'ëK´ˆ¤öÁE’ÓÛAÿ«Á~½Øÿ>‘ aåia‡H’ÿãÇRo òƒó›f´Ûð, ÚPÉf²olSŸÄtûqÇE‰k}¿q•¼)"F1V*,Ë 4òB’H$jĆd2Ä*•J؎뺡H"Ɖ CF"‘ Z­†…¤e¹¼e³Ù1¥žF/JqãMñReM¥R-k“—8ù-F˜|>_ã+FUAŒ­b’¨aâ/ŒñôdõçLÖ‰ @ÓB¡Uw”¾OM_óíb¦Çg߇ÊC`$j?/-=Œáyüâ’K8õÜsI;ÿ÷/þ‚o|íkéíåù®.¸ì²IŸDšLÇ™ð½Ä¤-’11€“_qóÞüÇ=}BÓõ,¢{ª…z¼Šï‚Ô‚©ËÊ”ÅB=¢ËDÓ–úôõžñét:ŒV‰ßŸä¾(bJ2™ ïUÏ\~9Ÿÿú×yûÁƒXé4K Üd’J2I:ŽÆü‰›¹íd#œˆ¹ FvÅEœˆßŸE\—碈$òµ,‹l6>7‰Åb1×%Ò)‘H„Füt:M*•Â0 òù<‰DÛ¶ééé Ÿ"àø¾O¹\Æó¼Phçl6›­Ù¬#"뺡CŠ ñãUàTžE¥R)Œö,•J¡ÃDµÉr¹•J…B¡Š;Atm.—ÃqœðAæ2ÏEæqgŒø6bˆ­Oá'ó‰ø6¹\ŽîînŠÅb8ãÈyÎçó¡°300@OOO˜ 49;00ÀåuùÈl>;gß÷Ù¹s?_ùÊ ýèá¼àÀEüô§w„cÚ²,vìèà®»¾ÎgDN_‘èЃ²R Ôµ‘BY(¤ŽˆGc×ոБ 6I<%žª+ÁÒCdý‘ÏÇs?•7Ö^9ø_’º×§+KÅö#iȪ±mÆsé§í’ãt¨ü(â§^l©Ëv"ä|O $¡""JA”x¿‘M­Ðäó ZOüÕq”Ãí›ß|7ñ/Î{O¾V˜Èøìïï§¿¿Ÿ-[¶„_çw—íâþï< B{òùñëeLÇq¨T*5† ˆ"IÄV¼i…V=¾äE§^hê_Øæ…B¡æœŒ‡¼\J„Žçy£yù”ï%›Í†/æb“õä¥Ó¶íQÑ@-§K$T¤Š¼5%àãçÓßüt»Oï¬0‘ñYÿìJ%p¿ ù¯‚A”¢iù÷¿éû _y%›þþïÙ;0\âf[H$”ëáàœ¿ý]®Á oyˆÿøÐë®S@=îʨ璤I“o@ü=dS" •ÔicGM„¸!=Î×Þýnžºøb®ÿÅ/H qÁUW…Æcñ€¿ï¾ûމâëSÛ¶Š¤œŒÿÄOa)‘étº6m[°­D=Ö?çV­ZFiÔ?ëš=ÿº»»1M³&‚#]dß"ÖH*:ß÷G‰²^ý³ÊqJ¥®ë†"Hüxâ)* …ét:` 0ºöDÞåÙ¦T*…ϺFN"6E„á©~b4#¢‰ïû£¶A´¾oõÛÄ¿ÃóÎ;¿ú«¿â}ï{ ÉÎmg‚ï~wŸÿü“¬\9ÀÓO?Ä}÷}€½{WòêWÿ<õÔï²wï©ÔÏð}Ÿ3Ï\ÏÖ­×ñªWÝÅöí½<ýôV–.}§œòÿX»v-Ã×r 'ðøãKyÿûáöÛײqã^.»lo}ëÑP ¸à‚«8ÊM7]„ç©)T¡P T*‘Ífñ#b"(±½Õ¹™D€†1¡md¬Ë½"ñÝŒVçáb “ñ\ŸSî•ñq#‹ˆ:rïg-ùlÛÓi&ÊKe`œôÆžç…}’sÕÈñh²ÏˆùÈDç¶Þz+/¼ç=üû?ÿ3•ŠÊD:Ýþ{ jýg5Ç&b Š[Sgú1—˜®¹íË6¿À£+Îÿî¤ðG›F­\.W½§ÑL–¾¾>z{{§Õn;©•™¤ÕÙxâ—ÏpÖYO6^A*¿¦POA‰QÄ£±hÐè‰iÔ}^Ÿ[¤Ùö"¦HZ.y‡uƒþHôI¼­d ûh´ÏxÚ/;ÖFüâï\ñ÷¼øûh«ñ¶Eø‘äðE¢ˆ‰ò‘ÊÀÍ"秉JǶÿ–JÅ>Í•4‘à3 /‚FÞÌ–¥<^þôOW»&Þ轨§ÚDÌzÝÿù?d2·,®zûÛI§Ó$ R©¾ïóÃþð˜I­3c³bxon%$RêƒI„„PŸR0 £©ÑO¶iô¬köü“{vü!ÞŸø3(¾~=žUâÞè¹^oÄ•íëûUO##æxó†FÛÄ£šŸFçR¾ÓVö!ÛÔ§ZŠ/kÖ_‰ª_ï½ï}/+V¬àX`&Çg=¾¯ ¼}}#<ÿüóüð‡|àŸáûßÿ>¾opÊ)¯á¯xßýîùÀ%›Ý‰m_|>ð¶·Âiôš5*sb:}5¾¯zÕïñå/â߸®¦X²Ê¾xÿóB¥²–ju-7B¡`‘Ï«tH]¤œ*|òù,¶¥T"Y,+Éòåïæµ¯ý"¦™GöcêqìyÊk[_Òi#p¾h|N¿­ÎÃÕk‰2s§åyóX÷Ôz$:¨íóª9ÄdÆç¢±6ÉX *4SDî{Ç*Óõì<ñŒƒ@ÞÔüdÎg‹fa3ç•©à§=~˜#K–Œ^èÕ)‰'u—÷ޱŒìÓ"ÚÌ1Ç¢õʸ­ }¶ˆ ×Ï&’*ÍŠõE&4%¢ü.¢HšúíÅ¥V¢hÒDQ+Òf‚ÈM¤'hW„)ˆ¢Z*ÔFãLæù§Ú†ó;Ïð§xŠßXõ¸2zOñtCQ&“ ½À$5H±XÔß9Bü»ˆ'’»=þâ(≤Fôb’A L’^”A×÷ý0SaHî¹ç’èÓ–Ù /^¢þ,­XÁ?<û,»N<‘³ŸzŠÛ׬Q·Þ •Ïœ¡ã\ +¹&ušê=KÅ»*îíšJ¥Âˆ9g8ÀCÀÚýûGí+LÅBíÔ¥ÙU^eÚaĶ‘T` /ÝÑ£y*Ä‹o‹1©X,†Fÿ«.¸€³Ï9gÖ¿³…„¤ aàõ¾žÒ7D‘ÖF!êjÒ¥LYþIDATYðEÇéa±ÌÇâiZcõðÜñrŠÃKp¡^¸äB7Wˤ`’\œpëDƒxÄöÔDzøQ[ìOÅ r[ž?áñË6ñ~ÅÏ—;:j£&mv(Z>ªÐ|¼p”|‹ —E-lcç§F¸©û®ÃÔ¼¢!Ù‘˜ž77Zÿ”SN9f•™ÄuÕ㨟?øƒûø—yŒÿú¯_²nÝÓ¼÷½/ãÉ'_…iþ!—^º(œ" `Yç`ÛÑ=Ò0”#W# .½tO=µÉ,^ žJ{40 ŒËrYåóJ)Á"›UâˆèãŽíÏqÔ2Ë‚ßþíE8N†TJ –•Åru¬é´úLBOúíyJ¬&V¿A‰)RƒXö_*©>W«j½B!jÇ÷kË0Î6“c÷1áÊ÷iã╦9###t ®™™:WSJS«Y0è±8u\FîXÄóÆ·´»;Í„YP‚ KsöÙ;€ ÷o<…”NáBçÒœ9$‘{#ñ"Mdá‘¿ë ”ˆ cYu…‰Äc“DiÔD<Ëå8ISëÆ+/»r´øÒ^ÏË^¶gÖOï|Ã:{‘g—-žr[y¯¦Ói à\.Ï-¯¦†‰¾xf2™0=›¤©ñLR…I>øR©D&“ sþ×Ôœ1`ÝÓëÚ}øó ÷^y?|ýÓŸÆþ­ßâá'žàÔ›nâCø‡s÷‘Yœ¯IE$õD(‘Z R/Hòœ—Ëå°6E©T¢Z­’Ëå°,‹D"æAaAÄ1Kº<ùmYæwòŸ'¿‚³‡wP©<Ö!ïóøX =YM'È·^-ÖÌOCê°x¨Çh‰(•˜Ô[©‹*R?)^¯*ž;ÿÉ'ŸœJóÇ,ÉgÛ6Õj•L&ÃÒÃKI% _ VÊ ’â5¦ªýåSÉm¿¸ ³ÇŒœ_dΕ!ª'(uÿ2pý ×óºÃ¯«­3(s'u!ecûð©_ŠêʪZ/C”êÕ¥6z9…|ÝÓ×ñàYªô³M-ÛÈ1åƒþõ²Ž<}„-/mòVRôJ$zÐoÃ1È“gsy³šˆD‚¨Ž ¤ìuàïðáãÅ×Ö<4cû¬E”—àÍ/½ßóùèw?Z«TJÿJDBGŽ÷âo\ ÀÙOE`Ë\Y¦:’N8à‚ . àø³ßÿ³¨Öa<2aùÕ¯,þäO’$“sûÉxÕ7[L³qŽÛVÛˆA?n”rtP+^ˆ’Ï«åqí3™ŒÄ¡ZUç TRÛŠØbšj¥’j«~ ŸN«¶â}QFêbHæàJEý¶m%P êü9ŽZ–ÍFQ0rŒ¶]ëß%âŽC¦Y{¾¯¾Sé¯eER|=Ñ›‹Eµ¾œ+I=åûêXå|x^´iR1T,ªå"^¥ÓÑ>O?}ÙÄ/c„_|1¨Ù33Ñ)P¿ÓL øŽ+Î{–ãï?šøpÄëci4s%¨¸ÀîÁC¼©{UôA.øÙKôb¥o|3D”ŒgG;X£ ˆ,òB;YT” DBJ•Úy™——sIKæÿ—cÛ·Hqî¹kgã¬Îk­.fªŽ’;\Œ”’ûÛ^ˆÕàŽšåÓ/öT*¦¯‰Çñ¿¥Ði¥RÁ¶í0_½¤!ºgÝ=í>ÌyEö•y˜¿>Ê?þ8ÿßÇ?Îéð'ù—íîZs‘A"–âׇԂïuIT_LWŠü¦Óéš"º"b†AOOOX¬vhh(þ†††Âöåº!F¢V$¢NŠàÊ>äú—Bgìÿ.ò¿Ë‹Ç‡e½6Œì‘P¢¤€´Ô'‚(¡§§‡t:F{ÉØˆ§zéî»ùÑ™gÒµz5,Z$ör<à(jª”~¾s'_èìØÔý;?FDâqÝÝü¿C‡ø½v_?óŒîîn|ßçÿ}ëÿqñÙƒ _xè üåþ%ýÑC\´ìWpÈ×€¿°á›QêU e¡óÅVÿˆMÉMp· ž;°|0“µ žë‚ï³+ûW{*Whà ñ†5oàŒçϨmOjÿ¹DÎ:’E'Y²<øªyÛ—Þ6ºÁ&šëõz=÷¿ê~.µ/­u"Šp–þË«ÇU¹ï÷qyõòh]ˆ"yDJø`yœ`Y”+sèõ‡à–&_jHðNýÒEŠløÜøH°o€R£°HMŸßa½ ‹Óï<½¶Ö DÑ*ñµŠª‰“Ý™åò;.Wß³ÌÛø?ÿ ô˜È¥©!ŠF1Meç;?G&óe|ßUßg¶C}#&;}N&G{g7J#bN.‰&q›±"MêáñãÈ唨’N«¿«UUË@¥+‹!Y_R?…ÁX®Ú®RQÂ…Qz³Hð‘èÓ„½{•`#û*µ}<³—D×xžê‹øeŸ¶ÝØÃ]¢t¤=dYÑ÷uíµ§vQ,`®{è!îÚ½–~pæ"tþ ¨1©“aL¸ð;OâH×:8wô:’\£™«,(AÅŽ»çW­Sx¨y‰€©»[. ⸖Aó|Ñb j´Üó<°›çynõ‚™Fyðµ‚|¿)j‹Öçc¿K¨;x,µA<5>Qê‹øþ÷/ã#iÏKÒ|â„ÓŸà¸õßþǤ¶w]7¬™R,ÃÔ^š…‡x±7*ŠÜl]‰Èd2cq5cSúepÛÌf)øý+¯œÙV ÍŠH‘J¥°m;¼G$ ,Ë"›Í†â‚”•6EÄk”»\Š®§Óéšçš50úYYIRÿwýóÑ0TŽùýæ7¹ù—Gy~Ã÷0ÍÔ,·+¿“Éd(9ŽC&“a``ÏóÂã–úñã=á¿à?/¹;°Å @=~€ žy†¿ø"ß2 †ˆ‚ZacÕœèééá‡?üá´^' Çq¸iÙM|àï_߸8<Ž÷qÞ~ð·¸è¦‹ÀÙŽ†§§Àµ!™òæ®â–…öqŒ°AYê@åæÈeÝó‚ÈSvŽý«…MI6Y›”UÐ ªñ8$ÅŠO”ÛǶyù“ßãÉU?gUâÞÈ];L™å+ë$(Ë—iB2É×Þõ5–^Êåm.m6r9ö}ÈÀUÿç*Ü_®Þ’#j#Ø$©~`ý—³–qÙ)Ë€K£í\7 +€èÿJ,‹;^ÅY¿÷¦¨ÍBA­“ÏC16®Ke Íç)áðw?·4Úú’Ëù ŒÈ’zn‰Wp'ÿÍÉ`.ðžiÒÁ˜2bÇ亼бƒUÝ«àuµËT8€}äXÚÓ¿‡ìÏløN7T‚skeÁ†ÎßëäZP™(¾ÍìÂ0.ãÙg­QÏŽùÎD§X"DÌD|_‰†¡>sœÆ"QýéC¨DÌ4;¦FÖM&GGÙÈ~ë÷Ýê”ʲjMkœ;2ÂW~ýJfÒ©]gzÒÓ$LóLg''ýNç¨Ï=Ï£»»›l6«g5s–%¨œtòsœwÞ3êcV@㓵´,‹T*E6› óFË:™L×uÃõÄ[W¼kÅ8é8N! Þ¸bÌ”:Žã„9œÇ{yâ™bÄ‚ZãËÈ #,»n'üüÈG9è-Ë ó²K¤¦†iš<ÿ«ç¹pÓ…¬3×Þ©D§äsb‡ŸC”ÆÂ#JÇ Ö£&‡³téávÝs8}ûþûñ?›t’bGÒñ¤Û™@Y3+ŒU0XˆE7M“l6K©T¶íñsýkFñÈQ8{©ú[¢¿Úm’( )²íû~X;Â4Mp]Ïó( a”ˆaض]cÌkBÞì8‹ÅbC‚fNÍhEè;ñÄ9ÿüóyqÕE-·+Ïáø±™¦IµZÅuÝp|tww‡ À†çžcý™gÒÓÓCµZÅ4ŒQ^—–çñOW\Á‘C‡è^º“èÑwvŸ ¯yÍkxᅦбƒÌËJ¥÷Ü¿>´ž±àçE0à¥w=EéáIŽÖæê"÷ëÀúxÔqøQ¡öŸG®ÜAT  –¸ø‘LròM7q奸 ë7:m;ta7¦cÇøÇXq!žëFŠ6ïûøû8û½ï>­kYJ¼ˆç¿‘ö2žX“ä‚—C÷ï¨vT%ëÚ~uw«e{ø£…§îsÑò\N-‰ ªpîxìf>öø"àõáyÁ4•{|2©Î‹ˆ6`šœúÿÀò5]µçJrùÆh«éƒ§.¹ 웠䪶eÛt:²Èær¡`²øüãxúßïaõÐ}ð«£ï_ª„ÇóAyôôpÞâî/ .C|‰•ŠO±XÔF &þžŒ·x#ÁC3ÿÙ·oÕŒ¯ñZ`Ñh&Ç ^vÎ!X·´áòjµªŸ£š9Í‚T\àù}?£«ë•Q äÿR©D>Ÿ‹ÌÖ/—Tñ‚´0~$ÈXˆˆ‘ËåH§Ó¸® #RÄY ;;ŽSSÜ2—Ë…¡çbl‘:ù|>4¸HžnI-R­VkŠkÊñʾÄ˶T*…}t]—|>¤x¸*Rà³T*…iVJ¥·/»ÃKswéîpŸbH‹Éd²¦¹iš|ôž’¯DÞÃétß÷I¥R‹EÌ´åÇqÔuc£"cJD‘*âº+ùºcB݇>ô/ÀÆ™¹ØðàÀzžýoLxÛx$U.— ¥š…Ïd"MÒét({žÇEµn˜>Öq¿ Ú°EþãgµØïû~(ŽÕ§·%t¸®Kwwwh¸’ºJñgídž¯qfSP:ï÷~¿?Îçïzˆ(‡åäûïûÀÀ@øL.•Jœ}ÕUü¿/~‘W˜&¹\޵Ÿü$'žˆûÈ#€Š‚9õ¿àÙw½‹ÏïØÁî¾›ÕøI¢G¡’Öû&h¦—ëû7:ÿ©“¾üÇ=÷yøÑ@m [Ëâ[ýý£74ŒÈÂXçB]/ÂI;€²'“£òñ,¾ê*.â‰Ñë×»î–|ö³µËâ÷”&…L߇NÝ·|^‰ ñgCg͇?Ìáïþ ÿ»ù‰¬s“ÏÚv$ê@mTJýgÁ¾^sûíœçðñGÇ*•¤ã…Dh>ÚÛËIgœ1ú5›ÏXWK[Rx¢r.óyVæàÏØ ßpà3v´|^ IRéZ\ùóyNÈd óÞè;ˆ}oÝó5ìhÆGt­/~q˜žž7‘ÍfµÓFÓ&\×eß¾Îh*&ƒ(Mªdkô‰ÊgII,F36`é)/Á^&¶Nf.³ €ÿr“XÖr•a†²¾¤R©0¯9Dé¯r¹Ùl¶Æx#‚D:¦P(„ž®ñ<èžç…¢„´WoÀ‘4%ñ|ðRÌÖ4ÍÐ{Q å&• {zz(‹5ý,˵eYáþ¤íx*Y¿¾¿AR*•ÂÜð’_^<‰¥=yéˆ{B†ÁgÜÏÐ{Ao¸Ž,F"c$Z!Þ‡d2Š'…BL&ƒiš¡‡s"£R¡\ò‹K¸úì«¡Ÿ=ã³¼õío墼(*š&*®j£®«2QÁÏ |õßÞÁË^¶ŸÞÞ™¹Þ‡Çiy2‘Aº°†Fu(L“¥?ÎÒ‰Š§õ¥…1î'½êªÆç ~~}.xöÙÆm6ë¯mG)ËÆ"î’oƒùY`EtÞ$Û’*Øõù‹²Y.7 ¼ ñ3qäøë8ñ™N4ãã8JK¥~‡|>¯ @Mñ}Ÿ“O>yF÷·–$‚ßâlâÇþ–¨Þ< Ë…i4Ç40rœuÝqÀèH/Ɉ£ÑÌe” â+V<lT#r]%Ÿ+Æ{QâÑ"’$ lÛ‹(‹EJ¥CCCaQ[ 4IŽw'⑦i†í¹®FwxžÇÐÐ…B!ìS3%N¹\&‘HP­V[¾AM4­‰›¤ “cñÜïŒ_qA$.®Ô LñHÇqp]wԱNj‹Åð†ìºn(|Ù¶ÍÈkGØ9´“ÓN:“?v2Ëìe¤R)Òé4ýÑE|æ>ƒeY$ݤU,”©‚ºÆ\xå+ œ¦9‡çŠ˜J0zêßà„Lœ.Ïg³³“ÍŸû\Ãù@.— #]ó±z-…B˲H÷cèFäí7<ȫロßyà.ص«mÑNóž ’óKô2ýÁ"ðí†Ö».¿œßxøa¢”l`ke1µˆ¦Æþ®]Ø‹S ò¬•u¬×½÷µ¯ KÑ…eìl›|ݳØGù˜˜Á>=j öÊߥ`#ÖG‹ÚvÒïì'? 44O?™ØvyÀÊfÉMÕ$€G<ˆ¥t^xü@öÔSáo$;OñýÄËé¹Á:ҦtÍ5aß¼Ø~DêqPSEi/ýÇLéœsÂcŒ÷M²Ð±sçÙë¯ rR/Þõ3æÖ"xé2“U·½…bðyBÚ Äú×"×4ÉÆ¾b}pÿ}•{F36ž§…\שIAªÑhÚÃáÃKÙ²epɬì/î&Ÿ¹UPÏñÃôƒÏ|Ôý<þ\–ç <ß4šc…ÕÏ÷ðr,j¯y_Ñhæ2 JPYìÂÃàl¬}+š¹\.4èÆ‹ØÆ£NÄ‹V ¾’^J"0â‘år¹aú1 Éþ$â%NY˜YRhµŠišaª¯™D"G@»&ú‚QŸª¤Å+Å úú±*uoîÀù…Ã;~òlÛÅ”oþ8_îúrdü«øÆÅßÀ.Ù¼¸öEÎ0Î.}ÿ½œ¾Î3=OzuËÅ\N³‘($íÕ¬™qûW¿úÕvwg~àÂâåGÁóøY öOwª+II „Ž’âQоË3µ˲Z¾ßÏg<ÏãæO}Ь^=cé³âB™8ÔÏ1EþHý4I–ÍfÃâõ&„i7-Ãà/^|‘O^}5ßxòIþæÙg¡XägŸþ4TÆL¬E\—J2ÉeXaÔµ >‘0!S^9b°‘(" ¥ÃˆÇœ+(|á ”‰Œü’¾Í}×»Â,§>Q–SXÛ‡D#ÙÁÿE"aFÄñÞ•d["@ȱH?ãtŸqFxmÅñƒ>U‚¾Š¸¼t8J­@㵌º¶z®¾#è[|Y%2 Ô}^Rï{Æ©§Žj/œIýR&GºÏ9‡<£Ë:ºÁ~ŠÔ¦‡q€ÄÕWS ÎO.蓤™‘ï:Œ@2—€•þMÒîñ¸—«õDèl–’/ì?î=-g©~“Ãë×£iŽ”ÊÉf=2™Â¸Nb<2.&B$ŽÅÇ|/û(ë†ýˆµŸF]gÒv(ªyË×»  Ú‹gôi|Ï–±.ÔŽoÙ¬#÷‰¸P*ãe¬úá>ÑX“óÿ;.âš±ö jï•òYýñOÄ]KîŸržââ­ì¿Dtß”$rŽ]¢¬ÒrÏ•~Ubû1¨O]jÇòƒozÓz}l±{÷Zvï>ë¯oo?ââH5«¨k¦;XV¤6›¸8ˆ#@u]H 1'Ø^žÕñ`ÕFc[£™ËÞ |.ù}x9P[›±•ZªM»YP‚ÊRÎ<ópô´™"’¶Êó¼°˜» ÞFÅ×ÇšP73P†A"‘¨ÙO+'³!ŽLÉm?=‡%:€4lÜ¿‘÷}ø}|ÇüN}ô³‡¦ÒMåÔkOµZÅ5]Nà× ò“3ÂÛÿíí\ì_Ì’CKÚ}HsžW­‚·.¾¸pÜu¥¾¨ëH?L5Sá¹çžkwæîKpâòCðŽ$®ãL«x!â @¡P£‡¤.—Dec: ^J–iò©k¯¥óé§geÍÄêFÏnY$z°R©D©8!Œ0’¨Ú×f³xÉ$%àìßù.!Š øZw7ohT÷Câ^ü»|îSÿÈ‹ýoâ‹Ôæh7QFš¸hÐhôÄg’"~xû÷ã>ú(öë^W³~ÜC0nì“ÿ›WëÛˆï¿Þh,4íEù5 #ÇO;ßVÎW£¶ÒÁ¶õûÊÒXèI¹®.ò‹5ÝFŒáqo‘Æ^Ç"tÕcmÉÛD<ƒq3qÄZ ©÷½½ûT¿ãÛ4û¾Ä°ï›üôíßflJ%•qM"÷ÄÀ#À\"‘AŒûrmÈ8£‚‚ÿ³D€C­pé¿E”‘kMă "ºNªŒŸ´ÁabÄœzÑ$¾EȨ¬r ŽCİjEÙowð[Ág¹µQ!£å^ïÄúy¿Ž¾žâž ñ/6®œA¤Ê—é„è,¡AZpiÃ6`è `®Qíì…–c¡›Å À½ Òy#ôkì uªº¶%ú±˜#µÞRH?ΉàwB~˜¿„R7ØÛþ9ÀN°žç¤9Ï®¯À8›÷·°®x­Ç#¼4šÉræ™g¶» ó‚»ÿÎ[s@åØw&j^D3HD`*•"™L†)2E,•Ôš×eÉ¿ü ;Ï<“‹ÛÝ—&˜¦I6›¥T*áy^ø=Ë÷(bœiš¡wnøTG{>õ)ŽÿЇ¨¬[Ç)K–°ãì³Û}8sšÍ¿ÌÑÓq/vÖiaÄC#,&n;0»º0»ºÆ\ÇhðÿDm“Ùf2 >'3Û+¾»YŸ‡-ó8ÍX&“<±™¤=–82ð0¾Õú>,jÓÕh&†eI¹‡¡¡!*D{)T¤6ºb,;_½°ÿ]ÿy£kÊ V@m•éH¨›lò™¤©ƒ(Rc&ß EpšÈ±ÖÏx¤q±H"ð꩟½´b_m4ã©oÛft4g¼ïÿ©•¦>üÞûÞ €u‘*QȦ„pJ¸Ÿ([ñ<Œñ¼Š)š¢¬É`5N¶ubû‚èKsÀþ ðWƒùø`,o8¨–ób°ü%p±ì‚ñ ’`ÿÌà<^7¤÷C!Șž-B!öXw@å2ðÖ@öN`'¸ç€ñ˜À~Hn.€ÜÕjyòN¨\œ‡W€·8,Vë;¯ã1HߥT_‹€ÿz(û¿”ØäÖ.ÕŽ» ìõà<¢¤ìKP:å©ï¼°üwÛœ¯Ú~ —ß;;NQ ž=y´IÚó¼0ò]£™Ë´MPaÿþýtÕ½Ì 3<¥ËY°× ¢./ ¢ÆÎ ¶Y«DXH>œ …^0o‡â ¹Ju'½†°¦Wº#Š6«¢„ˆÂ(;à‚ÄåPÞ–Ý›ÀØ CG!÷VpÀÀ.p–Bf©J·é=™ Z$6Ei(»/.…¡]3£¶¥ËÕW9k¡çõj“@'ûÿ*×û | YHm„êÏÀy*; ´òy=X{¡z/$:•À4ðÈ} rg@ñlðAb)Ø» ðv°~Îë »r›¢Kêú‹òbÇ>Þ1î•:˜î¹­°ãdXüüK9þȨeâ¼¥ÑÌuÚ&¨”‚7 -[¶„Ÿmݺ•¾¾>6lØÀöíÛÙ²e ›6mj¹Í½÷DïÙ‹kTòf×¹\.LK÷˜=ò¶kjÕäóùÑÆ`2¶åw·pÉŸ^‚÷¶…“–ªÑØ„ÉOXýö=l¼ýÛÀuc®ë8Nèí|,¤÷Ñh&ÊtOá³÷ÿ îwJB‡D¤H!yÛ¶kîŸs1jqN2Å&q@¨¿‡ríZJ‡qpõjÜy'x/›¥Ôf³ÅtÎm=VÂ'yßì½bÜõ}¿ÖÐïûÊhžòÆ”ËÊo?™TÂA±-Ñ$ŸWË\WÙ+•HˆI§Uû®«ÖA!~ÙŠa^Ú•¡ošÊxïyjÏSm‰ø!ëU*QÀœaDb‡ï«õD‘ÛK*¥ú,Ó8YO„é³ãD¿ …HÔõå꧃†¡~zz"Q#þ¹iFmȶ¶ÕÙc—öeŸ–¥¾–J%µ]&£ÚM§£sbÛ‘Ð#z¦ˆ3¦ 'J²Yõ#Û”JêüÄuPÓTÇS,Bµ}—É$\uÕaV¬X0‰ ¦ýÙ)×ѧ¿ùMø›¿¡š7Â!òj犋‡;IÉm%­!J=$9´Ž%ÅF³`˜îñ¹|ùr¥Ä DA­€1•b:í@ 'p“Iǿ٬2LÓ˜¾²²!µ·¤|]»‚EgÕ>[«vœÌ3¢t~°M”LÆ þ–þÅk§eAE™˜„: ¢”˜²ÍÞØ6vð¹}]P·© ,QmÙ€µ1¨ïöFH’ïTÑ(öZBÉX. `)XY0 J´q.SÇdEšÀ›ŸzŠí ,úz&ì¶/<gžô Ç|rÃ}Ú¶Ý´Ž´F3W˜õ™òÖ­[éïïgÛ¶mlÞ¼¹fY__7ß|3½½½ rõÕWÓÛÛÛ’âék¯{ˆwþåk µo{Åbôfâû¸óNþõ›ßäk×òï_ü"O,_® ¹ššzk§áíðvþÖý[6®ØØînN™±Æ&L~|úÀã7,â´SÆ.n*µÆ+ê©Ñ‹ÌÔøžÛïù ýëÄsÖJ­1Û¶ÉnÎñH?ͱG£4n†a`Û6.pÑI'122ÒînN31·ýô_> GNåå¯ZÜp¹¾‰ ¾_+ÄKíÅ3×V*jZ\­ªõ•Ó‰Oâ‘nÞyÅ€ï8µ†|é{\@‰_2¹œjO~ZAü§âë7šNÄ÷#Ñ2q¡Ch¤iŠ@ÑhZßW}Ÿs9µm³Û¡aDça` ŠèÉç#±¦¾íøgÒŸ\NµSÿý4;Ùlí÷_çÍo¾èmíäÏaflnëÃÒ¥‡)½þõüÓ‰'ÒÅ8ZF¼ƒ¤’ æbŒ§* ,€R‘\)@aäïµ;ÌØ>âî˨´ÅRœ#ëÁrÉ_–ŒõA*c'cmJq\li¢â"RôA -xumJ!IÅ$'±ˆ²ZJu÷Q‘"7¶œºcȉNâFŸ ÚW…·c}–¢4r~ŒØ1H›™Øù—ýç‚þÅ÷oÄú¯.ß‘|ïÉØy‘ã‹£ÈÇþNÆŽ5èï²ç—±˜‰ñ92r.æ³D…jŽq¦2 Ÿê髟*4ëK3±§‘E@j¬5k«Þ ÚøÄèã±ãxHDýŸ±Ö·?vàQ_Ë,ÞÿwíÙÃiwß —]6ų×~fÊn+,:^ü/†ô<‘!=MmÑ“ø˜ïzޝ+ß»ˆõ×h£ë"^kTÄÔxuëxR +‹¤ï~lY™Úb1’GHÄÁ¢±%´ÑñV‰D‹H¤‘}UëÖ­ç[,®’ÚÉ¢6ÝS%Ö/w¤ ¸lcYfÍà|ùÁw'çSò»ÉþýXE0‚Úb(v¬M铈:N¬-Õ¤?Á±þ›Ã<ýݧ9pà ÿ¿½{nãºïþ•_’l‹d[ÈŒÈQƒÍIZëƒö$i fÅ<ÜF>ͦ% l½Ù0Þe ¶Y9>JzJ!m˜ì¶!¨DN6íÄ6iÝ:”KØÛ5â4‚ãÄD•[BdY¶"¬—ecÿ€îp0¼Ìðûññ¡ðœ;ƒû›ûœ;fÔm/]º„÷ç€ßìà€JjV ¹Û-à ýÓX:ÆOúS\¼x±õÆfõÛvww£££'¿\üµ+±¦òqÆh4ª,MÔ ÉdÒ”ºmËT\®Â,õÎÎÎ’ÔŽhvvvê°j¯½öâñ8οӃ+Ï]Dê÷Âpõ}¹¸U!®™W€×ëEjÓ&øÿüÏñÛzGñ`C*¥ÿžDbñz~¯·xÛ±Xa0G,D OS ÅâÎáp¡e,ˆköÅšZb@D´LÅà… Ò¦^÷@=°—.­N_"QHŸúøLL·(Å4Gíó‰Da­ qìÕ­çññÅëåÅ~Š÷ ¹Ý¥Ç4\œr§Þ¦øNq<µÇ(¿p¸íÔè,›€ñøq»÷C;©QL^Š·+nö%&ë}¿v2®zÍKõÍÜ´¯©Ó¦>êmßé,{õÆÄçÅqiW¿.¶_®,->W‹ûr¹¿Î¿f ßÿ>°vmQ߸b#£5Úo+¼õïcõáÁ‰[”çDÿl,+¿ì>‘ƒƒƒUýŒf@EofB:VFF«9àí¿z Xƒªƒ)‰D™LÔñf©uh»N/ôûKxNž¬í;Œì·Û]~Áï|~±$x½‹WêßC ´ø|‹ ŸoñN©©ÔâQ…`°ðüÈÈ’éÙh4>ïÜx©ìk±X ããã­‰G¢6Ôh|Æîk·¾Î3Ϊ•×D"¡Ül>•JÁápð’l2dÕªU¸ùæ›­N†©ŒÆæ-¿ú.üòj\ãºÑh¡Š VŸoBDµk¤ìüÊ__B×O»‹ï’¬ Hh®ä_lïè­”^¯Vm9H‡c±P\©¯ð'VM'í bPFý8(NËæÍ…ïƒ/Åíª‘‘Â6ÄàX—PH$J;TE»K‡'¼•o@$Ò«NƒvÉníºƒbtZ+Ÿ¯ôóêÎn±Ò…^§¯ mï‹48‹7‘Rÿ~bõ ±œ¸¶--òB,¶xé%¶$²áøœN?¾üoõáÀÀâ$QѾÇ×ï/½™p«‘¸ÝÅy@ ‚ªW ÑNÐôûŸ×Ưñ8£÷šÓYÈûbÔÛƒ°¢¿"+>Gˆ~1pªLƒ0b¿´ç‘¿ûú'¢Ší‹Ï¦R…}W^âæi@é@”×»8€•H”ö͈ã,¾W üâü"úg´iû-VgѾîó-ÆøÈHñ*)Ú<£MûåßÅ™É_ÿzéÊ0Ñ(Ö8ÜtÚY£íNáÕÀ›ØvϹ¢ç¼^/2™ SÈ6¤Pq¹\ˆD"EÏe³Ùºnl´.—öT^tx``N§ÞZïrI•Y9T­a¡-õ~fg u~ï©´o³³¥K¥µ±†âóEà¦ÎòãÈÈæ—ÈÀ‘-?#ÇVbýÍฺúRSn·ã—;CõÜ´Hå-oyKÛ¨ÍÔm·á†Cçp}×õHüýbŸ$/#jžFÊÎl>ß>y²°œ×mA ‘6«:5µkòiïã©VË• Õ^w8ªßDÇï¯Ü)_K›îСť¤õVU˜šª| râ´ïQ/U-f¡ ꥡõV“Wˆ%mg¯¶W»¤¶ú÷p8НüQF¯í(ˆ1¨¢ílÆâJ튱Øb‡ýÄDÛ/ªÇp|>֩޵X¹B=À(òÞ*‚ú÷Ð[¤Z>¯—[ɤÚ*'zK¦ êÕ6ôÔ²ÂJ¥´‰m‹@mŸŠúszé«4¡XýšÞ{Äy¨\Úľ•ÛÇjû®þ~1ؤVé<ªØT§_,“ÿ'‚v׌~Û€«/\ÄiÇuEÏÇb1.O¶"Í€ŠÇãQÖ¼÷xWò¼Óéd¡Id±ÄYàík ‹é–‘ãããp:L!j1N6 ’Ó g×ãÝW?pžQÝ~ñoÀíÿÞ‰?¼õVåBÏT*Å%¿ÈvÚb@nêÊÀq{içl&“áMè‰,tþµkйº³è¹L&ƒX,fuÒˆ–¼gž¹€—¾·€~®ÃáÀÀÀ€ÕÉ$ZR^zé%Ö[‰$µ}å?âÒÏrY!""":œ@÷µÏÀ Àù¹T*…‰‰ «“FT—¶PYÈW¾ñν÷׋žO$‡Ãé$²ÐUÿ¾ gþÃiåq&“A0Äìì¬ÕI#ZòNý¿SpÞðªî}Q‚Á `~~Þêd-)7Þx#•Ëd25=GKϽ±'°þì «“ADDdK©øyì;ýñ¢çD»“ÈN¤»‡ŠO'€·åsXqûŠ¢çpèÐ!«“G´¤uýpû¥ ÊcqÕYï'—cë+ÇtT¼^¯r#z"jk®¹¦eq—ÉdH$àv»•¿bkõ•¤©T ^¯™L™LFy‡á÷û‡111‘‘øý~ŒÃçó!“ÉÀï÷c``>Ÿ©TJÙ7ñïh4Š©©)„Ãaø|>Œ# ¯¯ÀÀÀ¦¦¦ ‹Åàt:•Ï‹‰S±X ~¿_y^¤UlCl_lCîññqå¯Hÿìì,úúú0;;‹‘‘LMM)ß ‹>'ö[l;‘H(is8ÊñÏù|> `bb¢$ ###ðù|‡Ã˜-J›ø ´ÇP,Û(¶ è‰t‡Ãa’mŠ6ÓæÍ›1;;‹‰‰ <ôÐCV‡‚”YÙ-;¶ñ~ôDDD\Œ7Üq‡ò8rÙR[ ¨¬w=·8àvߦ<—Éd”D;¸i^þÂr8¿¸ØìŒF£º·DÔz™ã+±nYn÷½EσAD£QÞ;…È&ÄàA"‘€ÃáPC¼^/R©ÜnwQÇüÔÔ”2X (Ä_Ñq/>–ÿ‹F£Ê‰Ãá€ÃáP^EG¿ÏçƒÛíÆÔÔœN'Âá°r/CuÙ/eÜn7ü~?2™ ¼^/Ün7&&&àv»‘Ïç@™¥M“<¨ey4¿ß_ôx~~©T ³³³p8J›Aüõù 7È8yòdQÄ “Ø?ñþJçJõÀŽzB‰øN±-íw¢ç+µkÔû'Ò¨÷ºø+¶)î1)Ò"þŽ7ž)ÛÔOÝçÑ÷;ï¶:DDD¶”?µ î»ë)ì"»j‹•‡ÿ¸åç¯cLõ\0„Óé,i@Qk]yébÑcõÌJ"²–£9þáѯ㋎Ï*ωNNÑ™GDò‰F£p:J}7‘H(N§@@Y¢J\!¡í˜ç¢ó],3VnIN½«Kµƒâ¯(çËÕÃEšÔÅgk½ŠµÑ«]ÔEÄy±ž{܈Á§V©ç¸°£~ïz×»x¥5ÕDLtPŸkÕW:N¥,Êd2p8H¥RJY®½‚Tüuu1‰Bûyñš×ëU>#®dWNªëµlOï3zÛ‹ÅbÊvÕWjVÛžø¬újK± ±Ú+@µŸŸÑn·Ú1RoW¤]|V<_˱zã7pîÜ9«³Ü2¬|Ë•Êo’J¥xï@²¥¶P9âÐù· õ,7"²Îu¹nzÏ•Š¢Xƒ&‘õ2^ú«7ðMY •ÙËD$—¥C¡ÒýÈXÖ-Rp¨—~EG|"‘P–‰t»ÝÁüü¼²äš5k0??¯Ô™Ë-5)–ut:Êò•âjQщ¯Þ.€¢–`0ˆ©©©’+I£Ñ¨ÒÉ/Þ¯8ïõz½%Ëeª$ÄçÅàƒv;êí‰+^ÕŸ)÷^‡Ã¡1ˆ!Tô¶'&‰hÓ®]&4‘H]‘«~¯ø+~Oõ`“Þ2™ÚÏŠt¨ÃX,V4¸"ÒžÉdtUOOΞ=ku6—Úß|ç4–¿¥Sé«ùŸ}·dGËòâzz›Æw?ø7øÄ#_Ç‘½ßC<ÿüóØtb¾wç÷¬N-¡PÇê¤H%㋞ÂÙƒðþoþ bˆáèÑ£¸°ñ|ð!€`g™kxxûöí³:ÒÆÇ÷íǯËã3ÿõO•™éêe‚ˆÌÇÇ166Öø—µ½óÖÈȼ^/Ô¬Ûêãy‹dÀº­>½ã’H$022¢ÜŸjvvÑhT¹ç•Ûí.Znˆ«(P#XF”'âó2Àg¿þ$¾uÏõØÙ¹ù“y¼°æ8á,êJ!|ðÃ'ïZFM`Fݶ-®PÁÜkøÎ羈 LàêǯÆõ¯_˜7†ÍØ /¼%¶8AFù·¤‚——+;’ˆšáÔë]H]À*$ðgÏþ™y‰‚b36ÃâN!«">(…«óòn¸9CÔ©ô |äSg‹Ob±˜îÕ)dBJùw3¨Ëb»pÃ-ß®8êmÛ §òÛè½–¹ü_5•¾§Üûêù~±â½§VœÂ¹\¡šD"¯>ÿUlýäVø¶b3uù¿JôâK[™—ÝpCDúDýÛ(Q/Ç£Ü9E¼Ç 7RH!ƒŒRiß”žï´y^¼?ƒŒR‰!VöX‹m ‘VQ·)—õ6ôÒ¡wüœp"†¼ð*û í  ë%@&–Ñ]VGtìŠÒ™LÏ^ù,n[w’ÿ”ÄàbòŸ&ñ;ÿƒ™™¼D¾Áàâ›ÉobÆ 8vì`Æ xøá‡q÷ÝwcïÞ½øÌg>ƒ§þ÷SøõOü:~øa|èCÂ3Ï<ƒ 6(àØ±cذažxâ ÜsÏ=Ø»w/‚Á ø½09:‰{¿v/<ò “ÊÀ³¼Ð)ñØ•|æ/?õ—øìg?‹ïú8öîÝ‹{î¹?þxI;†÷½ï}xð¯Ä_ò¯1:9Zò™;¯¾/ÿìe‹³ÛÅÌ{õ}¡DÇùøø8|>Ÿ’®Jûð¹O|_¹ï+ØöGÛpè䡲iiÚ»w/>÷‰Ïa÷Ðn|òÿ|333غu+¶lÙ‚Ç\ùÜÁƒñ™îÏ”¤³§§G¹ÚÁçóᡳáôéÓØºu+žyæ|ðšb29‰àHß|à›ÌpÏ=÷àóŸÿ<ÞvèmVgcicn¸qã³7âïùcLMMa~~‡(Zn²ÚÒ”DÔ|3ÿ 8å8‰u!€Âãä“%ïË ƒ(¢ÁˆRwÓöiéÕÄgD}J¼æ…n¸•z“x/ëLT¶¸Båo aÇÿ3·Ì(K ‰‚RÛÀÉ ƒJ`‰ÆŽh¤ˆˆè p |%n¸•Î]± /¼EIKgñé‹Çãøïû®ÆVþ+Îù¾²3ßH( ~uG°¯â¯x¿ø«.TE‡#€’¿zpT-”Éþ8‹Oßðð0ÎÝù?ð³ÿuïùaË—/Ç¿DþkúÖ`Íš5JGœÑQh4~Ô†¢âÛ,•ÒÝ êóU½Ô§õ¦_ÔMô޹ö¼©}M}nÔvÖªÓU˾iÓ¡þþZò„z»eƒç!¾ô‰/5í÷iÃÃÃX·o"oF€°víZlêØTR û[‹e¤v CÍH ëåãjy[/ÖÚ8Ö#öY=`QXçu(nh÷C/êzŠ–:v´q¢ý ÌÌjƹõðáÃxð胬ÛjÄãq̚ſ~â_•v¢pîÜ9\uÕU8zô(Ö¬YƒW^y+W®Ä¹sçðú믣££çÎÃÊ•+qòäIÜzë­8zô(6mڄÇcãÆÊgÅûñ=«V­ÂéÓ§Kþ®\¹·foÅŠ+ðê¥WñËk~‰÷¼ùüèŠáË߉óÇÎãå/ãôéÓøµë~ çÇúõëñäÙ'±åª-ØÔ± ðôëOã–7oÁÙåg•øeƒz0O/†Ôùmáè.l¼ ßO:…Õ«WKí9@ý}Ú86/µ–×âûÕåe­ŸÛ8þ<¾ñoà÷ÿ÷±bÅ ¥±ŸËåÐÑÑQ1Ús–Þëßÿî÷ñ“þÄÐ1igÃÃÃøÔ¾Oa$5‚_®û%Æ—ã®kïâìvj^¡Ržh“ÿÆ~ ‰1$ïújî}æRH!†üð=õ"÷åÿÄóêzu )¥ßI¯Ž —•ÚfÀâ¤í ¶m&¶#¾K[· æá*:^ºýv,;pG@™­¢^ Aopßî¿õ¤Ba%€ÅN^œbYAPþ–û>A¬80‹YŒc¼îJ£zFž:Àõféyá…~Œ`¤(X+ jéÒÛŽ^Œc¼bzµÊÍ-×øôÁ'œÊ1×^}¤N¿¶ÃGÛ‘¯ž¨C Ë÷çƒgêãqpÓAxÀ§žkÆæC"‘@4ÅÔÔTÉ{ÔùNïŠÃz±ªÎçêÙ¤"¯”ëDªÔÁTÈ+â{šÕ!¬×ˆS7ðÄö´ïUw,ÕÒÚN³.¼ð*íq¿ï¯nù•ÕÉ”Ö ?¸/n¿»üpÃwo}7î^sw[å’W<GüxÜêdHë¶×nÃﺢ0£¶ƒ1I­ІÀª­¾²7`³…ö_&£Ü‡AÜAÜŸÁyk…‘—ÿÞZæ¯1¾²¦Ìß•>{‹æ½âñ Íû®nÒAÚ¨y¼ºIß+³À—F¾Tù=5}SUÃÑaàƒVï°œÜpÃöbd|³«gч>xáÕm÷Õ3€fÑÁ«\ïwõ]=^ÏgÄ„áF©Û­FTJ‡úêS£ß§<ÖK§zÚ÷¨ç×åqýŠë>^íìèŸÐ}øíp‰žÌÎÎ6m@Å §2˜¢÷X+õ}Àâ7ù@Qþ}M)¤”~Êz&»¨r´ƒ:¢ïC;9Ñȹl³Jz0Д•#´}½zK¹•›Œ ¤/·žíŠ>Ûˆ"Zòž{ï¿Ás©¹•[éTÒé4Òé4ºººÐÕÕUõýrp¼Œ÷t¾Á¯›~N'œ˜ÀDÉóÕbê5Žqô¡0yåùj§ÍÔžüEBdì0ÂÀ|—ÿÓ^¡Ó d0ŽqeÛâ qr…•xN\–§åUï¯ú3êE `à‡¿dé6QHŠøu'µzŸ+-¡!~½ºƒ›—šš¤Uo|¿ Øœ¹ L¹Éµ:6Ôy£ÙñY‰új6¨e–¶úª6A;0,ækuž>½÷VŠáj3÷«Í²¨‡vÆ´H»v{ÕÎkÚã£HRGñºz@ Nßtºáý±‹zãóÐÕ/À¹âPX&ÃçóÁñvvÜ5[½± ï=þÞ¦62‰H_½ñ¹òüJ8áD__|>Ün7æç í7Þ㈨yêO±ŒÚÛV¿ à‡A‹:Ú–Î4›èœmdÕÑ&¬g…ÑNªöÑÖ*7é´Üwk¯ôÛ¾µª”ÑîSO¬÷ûÔ}Mêå ÔÛïWÄhûœœpâÉOâæå7×½vd¤n‹LG>üüÉÄEÄb1e9>»Ðˆ1sPÖÌɰãGA¥OXLð¯¶mí@¤z¥¡RŸ•ø`üêS=QD±›•8žÀDiÿÓáLé„I5 ‰D …ÐÝÝ……Œapp°âgŽ^|¿q ˆF£p:¦tÚ¶B¢Qq¡Z€ª –r#“ê×µƒCꢙ'QðLaª$#éì.÷1ø¢ìÍ\z­Re'ôÄÒ˜Åg$>wž;Šõo¾Á`³³³5nÉ^´ù¯– ±^Þ¬ô9íû+]ZÚ®ªÅs¹×‡8luÒ[ÂH|žM®ÄÝ×Ön÷ù|¼=‘ ŒÄæéÓ§Ñ×ׇC‡Y|¢¶f$>Ï;‡p8Œ©©)ÞÀšÈDFâÓét jêõ¨kÀ,Íè«0òf.O_î»ÍÜf3&RVûõëÚ}Q?î>Üx¶ý¯¾6›ðWßù>®z×õ¸ùæ;|à^LMMÙj@¥ÕÌ\5"€Â}ÅŠBS(^I¦Ü¶µù_¼¯Þþ­rŸ1ª–ïzöð³í=  …099 ǃd2‰;vÀãñTñt½|üX‡sVïB‰d2 —ËUõ}õŒª7S.—C6›­}T¹FþËÿ5C¥cتŠï‹c,>7g6ã†õ7À÷~9:kO«¤Óitvvê®·,³ÎT?#ñù»© øÀWîÀÇ>ö1é:ní·xþ Z‰ÍU«VáÀV'½aí”e÷ZµÓoÒ FâóÇ?þ1>ðØ~0…yZ>íò›4‹‘øl‡ÌÛ¡\«vÉÓíô›4ƒ‘؉3WœÁ¹ÏŸ³zt?~ÃÃò.9sþüyœ?ÉdÒꤔ%ó1L&“¸xñ"¶lÙbuRLßÏzãó?ø¾õò·àp8¤ýýdÎ[pêÔ)$ LOO[]2Ÿ?Μ9ƒÃ‡cÙ²eV'ÅtFâóÈ‘#¸ïÂ}¸ù雥Œ™ó–Àó‡qÇÇñãDZuëV«“b*£uÛçž{Û¶m“z–W-d΃õ’=ÞkUËoºmùø|'Nœ@S¿Wš•l6[ò\-—3µÃ’D²3Ÿ÷Ýwî»ï>«“NÔöŒÄç£>ju²‰Úë¶Dò2ŸwÝuîºë.«“NÔöX·%’“ѺíÏŸž»ü¯ÏY½ DM#Í’_%ÏUå$¢Ö`|É‹ñI$'Æ&‘¼ŸDòb|ɉ±I´Hš—ËUˆ¼ñ‘ŸDòb|ɉ±I$/Æ'‘¼ŸDrbl-’f@Åãñ ›Í*73J&“H§ÓM_㌈êÇø$’ã“HNŒM"y1>‰äÅø$’c“h‘4÷P€±±1ŒŽŽ¢»» CGG‡ÕÉ""0>‰dÆø$’c“H^ŒO"y1>‰äÄØ$*X–ÏçóV'B-N#N£««‹—I†ñI$/Æ'‘œ›Dòb|É‹ñI$'Æ&‘„*DDDDDDDDDDDD²‘æ*DDDDDDDDDDDD²â€ QP!"""""""""""ªâÊxà«aWétÉdR¹S¹× ³³³î×›)™LbÅŠX¾|¹TéËårH$ÈårX»vm]ihåñ#ûi$>­ŽÍZÒ`u|Ê>²¯Jñ)SÞ2ŸVǦlÇÚ‡YqkU~4#¾[½/f•ÓeÊ[FâÓêØ”íRû0+n­ÊfÄw«÷Ŭršç{1³M*S|6­Ü3Û¸ŒO{1³MjE^0£í*SÙiÇßDv²“={öä÷ìÙSwúZ‘~ÙÛÆ»víÊ÷ööJßokEßT 8räH~Ë–-ù……å¹ÞÞÞ|8V«È………ü–-[òGŽ©ùõfC±dHŸú˜e³Ù|ooo~nn®¦4´òø‘½4ŸVÇf-i°:>eHÙSµø”)o‰O«cS¶cHíÁ̸µ*?šß­Þ³Êiž#ìÃì6©LñÙhüµr_Ìlã2>íÃì6©yÁŒ¶«Le§ÙY}LfffòŸþô§ó[¶lÑP±ú7•½m, Å^ze‰o+úÖxÒé4<\.—òÜöíÛ‘Ífñxðx<—Ë—Ë…x<^ÓëÍ …àr¹ÐÝÝ­<'Cúâñ8²Ù,vîÜ èèè@,ÃöíÛ«¦¡•Çì§‘ø´:6«¥¯–×›¡R|Ê>²¯Jñ)SÞ2ŸVÇf-LjñIF˜·VåG3â»ÕûbV9Ís„½˜Ù&•)>¿Vî‹™m\Ƨ½˜Ù&µ"/˜Ñv•©ì´ão";ŽIww7‹â°Öôµ"ý²·Óé4ÑÑÑÊrdì[+à€ŠûöíSçr9ìß¿_É\Éd²dÝ»ÎÎN¤Óéš^o–d2‰ýû÷Ãï÷—íÅÌ6i«ó‚YmW™ÊÎFÓÊø,%Ã1q¹\ðx<º÷Åá7•½m¼}ûvŒ!—Ë!+bB†ø¶²o* Ú¿?vìØǃÁÁA‹£ujê©ÚëÍËå0::ŠÉÉIe4±Öí·"}étZµÜ¹s'ººº0<<¬dÜJihEú¨=ÔŸVÇf-i°:>eHµm|Ê·‰O«c³–40>©QÍŒÛVçG3ã»ÕûbV9Ís„}5»M*S|6­Ü3Û¸ŒOûjv›´•yÁ̶«Leg£ie|–’ý˜Èö›ÊØ6Òé4¦§§±ÿ~e0¥Zdo»7#P1(—Ëaxx¡P»wïÆîÝ»•×ôF?Õ#\Õ^o†p8 —Ë¥\*–Íf‘L&‘L&¥HPȨ“““ðx<Ãàà "‘HÕ4´*}d_FãÓêØ¬% Vǧ,é#û*Ÿ2ä­FâÓêØ”åR{2#n[ÍŒo+bËŒršçû1«M*S|6­Þ³Ú¸ŒOû1«MÚʼ`fÛU¦²³Ñ´2>KÉ~LdùMen .— ûöí÷¿ýmìß¿_š~[«ûÖ8 bÐÐкºº‹ÅŠFè€BfÓþÙlVéªöz³är9LOOczzétsss˜››“"}§dQý¸RZuüȾŒÆ§Õ±Y-}µ¼Þ •âS†ô‘½•‹OYò–Ñø´:6e:†Ô~̈[+ò£YñÝê}1«œæ9Â~Ìj“ÊŸÆ_+÷ÅÌ6.ãÓ~Ìj“¶:/˜Õv•©ìl4­ŒÏR²Y~S™ÛÆ‘HÓÓÓÊãŽŽŽ¢íÊß–ö­Õtëz*233“ïííÍ?õÔSEÿ9rDyOOOOþ©§žÊçóùüÂÂB¾§§'ŸÍfk~½Ù†††”íɾl6›ïééÉ/,,({{{ó3335¥¡ÕÇì£Ñø´:6kIƒÕñiuúȾªÅ§ly«Þø´:6e<†dfÆ­•ù±ÙñÝÊ}1³œæ9Â>Ìn“ÊŸÆ_«öÅì6.ãÓ>Ìn“Z•šÝv•©ì´ëo"3YŽÉÐÐP~Ïž=u§ÏìôËÞ6éß){¿m«ûÖ8 bÀž={ò[¶l)ù_ 333ùžžžüÐÐP¾§§§(ÃÕòz³i3– é›™™ÉoÙ²%?44”ïííÍïÚµ«æ4´úø‘}4ŸVÇf-i°:>eHÙSµø”-oÕŸVǦŒÇìÏ̸µ2?6;¾[½/f•Ó,D–ˆD"èííÅý÷ßÑÑQx½^KãQ‹ñI2kUþ ‡Ã¶zw‰È£ål+Ë?žch©2Ú.e|’]Ù¥m%[Ÿ‘ {Û™ÈÎìr~’T–1âøè£"‹¡¿¿£££V'‹hI …BðûýˆÅbøá—ËÅYD‰Çã¬XÙ˜ìå,Ï1´”ÉÞ.e|ÒR%klÊ^¦ÑÒÅ‹„B!är9„B! #‰¦§§1<<¬¼Þ¨\.‡H$‚±±1tttvî܉íÛ·+ï‰Ç㺅’HC³Ó¤—ÆP(Ä™$ 3ó~.—ƒËåR÷÷÷+—/—‹EušÌ>g襗ñI²jvþÌårÅØØXÉk²Äg«Êf"=õæu+ꘕÊÙz¿§Ùå_¥s Q#ªÅ” eX-íÒz¾‹ñIv¤—w«••²Ç¦Êt¢fkuÿL+Ú€ìû©T,2==ÑÑQtvvÂåráþûïÇŽ;N§ár¹‰D°k×®†·³°°p¹\EëNª+ŠåfâLOOc×®]Èf³ðx<ˆÇãMŸ¥Ëå044TRPYÉ̼ßÕÕ¥Äa.—ÃÜÜœRY­4+®Uç 5Æ'ÉÌŒü¹k×. ê~Ÿ,ñÙŠ²™¨œzóºuÌJål­Ì*ÿ*cˆQ-¦d(Ãji—Ö‚ñIvU.ïV*+훲—éDfhuÿŒÙm@öýÔï*«°”mß¾ƒƒƒ ŒîÞ½@¡àØ¿ÃÛ#–;vìPžK&“ؽ{·²í±±±²…eWW—òZWW—)ÛÝÝ­ì7‘,ÌÊû“““R*Í]]]øö·¿  r,­9gŒO’™ùszzét“““º3ßdŠO3Ëf¢jêÉëVÔ1+•³µ0«ü«vŽ!jT¥˜’¡ «¥]ZËw0>ÉŽ*åÝJñi—Ø”µL'2S+Ûâ;͈3öýà uuu=Vj_âñxÙ›äíܹ³¤ ³ úûû±sçN… c(B¿rIg9Gùw¹÷Ö›&ahhÉd~¿ßÜMd€y?—Ëa×®]èïïWfÖ„B!ŒŽŽbß¾}UÓÔŠs†Àø$™Õ’?ëÉûÉd‘H“““†ÓÔÊø¬åüDd#y]Œå,Ðüó Мs Q5” vh—ŒO²/£m+»Ä¦¬e:‘™ŒÖ‰Íj²ï§µ8 b3¿øÅ/êzÿôô´R0…@ …BXXX( ÈV¥Ièîî†ÇãA(‚Çãa§ÙN½ynnétºhVÍää$¼^/’ɤ)—V2>©Õ’?ëÉûsssèèèÀÜÜæææ”™zâû›QVê1ŸDK…ål³Ï/"]VœcˆÌdE»”ñIvÕʶ•Œ}FFÒeEÛ™¨Ìj²ï§µ8 b3étZ¹Ù‘–^…¯³³@at_E³o\Tošq)Ùþýû‡y@²zó~:.™© g³Y)Ò(0>IfµäÏzò¾U%Fã“h©°¢œmöùEÉ®ZÙ¶’±ÏÈHº¬h;µ‚Ym@öý´oJßæ\.ººº‡•çÂá0:::”`ŠÇã…B–¥q÷îݘžžVÖ$jWýýýH&“EkiNOO£££ÝÝÝ–Ç¢Æ'ɬYùÓãñ(ëW)Ë ŒISVÙQ«ã¦Z9 ‘H¤lcS­™å_-ç"3ÉP†Uk—Ö›ã“ìK/ïZŸµôÕŸÍRK™NDÍþŸúð ›Qß„¨VâF^¢ Êf³xðÁ•×ãñ8¦§§ BI“šÇãÁàà víÚÅŒ‘­Ô›÷].vïÞÑÑQ¸\.är9d³YŒ¡£££áXlFµŸ$³Jù³Ñ¼¯%c|É®ÕuÌjå,¥>\íF»­<¿™M–2¬R»´ÖØŸd_zy·ÙñiFŸQ=ñÙ¬tÕR¦Ù‘Yåû~ZkY>ŸÏ[2_.—Sn6ÖÝÝ]R…B!V<‰Z¤R<2‰äÅø$ªŸqS­Þ;<<ÌÚÒ’#KV)>›´TÉŸ²–ÕÒEDd^¡²D¨/×ÔŠÇ㦬‘IDúÊÅ#c‘H^ŒO¢úY7•ê½ÓÓÓ Í°%²#™Ê°rñÉØ¤¥J–ø”µì¬”.""«ð """""""""""¢*xSz"""""""""""¢*8 BDDDDDDDDDDDTTˆˆˆˆˆˆˆˆˆˆˆˆªà€ QP!"""""""""""ªâÿoÃu‰ôa0í%tEXtdate:create2020-03-05T16:38:18-06:00n;×+%tEXtdate:modify2020-03-05T16:38:18-06:00fo—-tEXticc:copyrightCopyright Artifex Software 2011ºÅ´1tEXticc:descriptionArtifex Software sRGB ICC Profile †2tEXticc:manufacturerArtifex Software sRGB ICC Profile\~=Ÿ+tEXticc:modelArtifex Software sRGB ICC Profile1(‚¡!tEXtpdf:HiResBoundingBox1584x864+0+0û8²ùtEXtpdf:VersionPDF-1.7 7ji»IEND®B`‚blis-0.9.0/docs/graphs/sup/dgemm_ccc_kbl_nt4.pdf000066400000000000000000005117131422157504600215230ustar00rootroot00000000000000%PDF-1.7 %Çì¢ 5 0 obj <> stream xœì½I¯v;’7Ï_ñ3yDro6{jÀ °­¬™ hU.@•e—Êÿ}3b­Á}îw›L4Ôä=üørwì®hþÛ§|ÕO±ÿÃÿýó?ÿîßýÇùùÇÿçwõcÿç_ÿñw¬W-Ÿ?¶§|êºgù<í*Ÿý‡ßýŸ¿ôOµ<íëz>c•òµÆçŸ×új_O’¿Dɪ¥ì?éG¬¢ ñ‹þù·ïý~žÒ>?ýÿøïÐf–Ôþ5íFþôn8«¬²ú~3^£÷õU_íDÉÑËÔŽþÌvZi××ózÆ(ÉvTÆvâÏ£{=_óÕN”í°LíèÏlÇÞÕzÚøüô?öÇÿoûUxÇàÿüùŸ?ÿÓßí.²>µ}þn1üãþç}I{§£~íw÷ù»þÝú}ùÃÛ¼÷‹¼ßí?¿®ë(ÿ¬kì?êïëÏU8ëöÙ¿Æ<ëþl»mÚßÿùïþÃïþç¿ûÝÿñ£nPË®rtÇ?ý¤‹Zÿë«Ü¯Zjj–zõ;›RÁÙTVRSg­hªµõÕêÑ ^ME¥hê¨MÝwýZëhН¦¢R4uÔŠ¦Fï_ýxW*x5•¢©£V4µÆóÕ®£)¼šŠJÑÔQë“»öñ®Tp6••ÔÔYë·öêgì‹Ïú»ß•ýõ³WGçúãü´úu¹ø÷û_¿÷ã¨XPo¡Zû•jªwýZs7êÝ¿±½ïãåçê_LÿéS‡½¡ÿ¼ÿßßÿ®}þÃošî2Ë~›Üÿô suTùÑýÖÊ/|ÝëË¿¯}Û?ÚG^>ð,÷î#>ð¿ÿC+_wkó÷ÿËî¯çZ×ïÿ×?´=ófÖüš¸ö_u|f-ßz{®¯±ëìöx7×þ°ÅêìOöL”¬¯ÞvɵG™¿Ók?Íþ·YûeÚJö¾gËYÇîø•}È}‡uÝ ¿ºö[±%ÓV0\k?ñ´:s÷/Ø 6[/ïýùÐÌ({Dî{P4³×‰juö– ?²ÝÆþ{?&îe_±Ø2üø|c%û° áïéëØµ¿ žñÞû¢=@§=‡¯®õÞ½cÏ[»Î¾7¿Î½g”Ëê\û-âW»¿L«³?¾Ü}u[èwÇîÁJvû]]»Ó>~õ»ë »äa/¹û´Ï:íaqÇ÷°Éi—Ìý½ ÜûÜVg?˵ö[{¼Nç×¼÷+°EüÚÿ;|œÝÏmÃuÞeXÏÜ%½4®»ýÅJûŠó®þª­¤î!½ l3ëï¼·Û†ë®2ìûXÉÕöpÝUlawÁcÃuÞûíÜhÅ>¢ÕÙ=}¿÷Û†«×¹¼ô½}¼Îþ" %׳9l¼î’Û>¼•,ïe{/4ÑúSm¸î‚ÛÎK®Ó^?¦œ±_Á°:ûµO¿øØóTñØcÜJötdÃõÞ} Ãjì› ×{ß(nyØÙ»è>XÉ}Ùp½ã{ŽýO6\ïyó­Ý ßMçç{¢jÞÊþÐhev®÷ÔPÜó¥Wï %ˇëuë V²?£ ×{U^jÏ,>\ïÝž¿­=Ü}´Þû’˜÷ Ük#~ÔüŽ÷hòÑzïÁ…ñ»»°V{†Ë_òîD>ZíWxû?}¸Ú-ã ÏÞ}¸nÈÔ¯öب¾oÝ·Œ–÷¿Ùﱎg˜{¢²{_q;{¼`©•‡ûá=«`4Ú¾ÂFì½g'•LŒØýœ%{žò;šJö¬æ#v¿[o«`ȬÝ1`'öC™;lÁδ®½ø€½8ç¬=rm¼Ö¯ÆK>^÷›½ü1×¼}¼6û_üj‘*v'-,ñåu—ht®Ç—×¹‰å)¾¼N[0%ÚJfôþâ˜XŸêËël{Z{üvli³y~÷Ct®çòåuî)Ëfn+¹}yÝóüà óܾ¼î’Å/þt__w›|£ÏðõÕ׬”Ïô±×¦n]ÓK¯ewV¼Ògùú:Ë~í˜PžÇ××ý«ëW+Å××]RÑò.Ù³ªÕmì×W½Aø,ûN+J.®¯{†ºÑò…õu?è@•›ëëžøø£Žõu¿u_‚[\_wÉ*ƒëë¾¢oGZ™X_‹õD/XX^­ÊíG)åÁòjpY+J°¼–=ÇúLÕ ÒmÀ–=Uß(Ù'°eÜî·³÷#>`mc1P§ayµ‹W¿Ö^N}ÀZ;>®š}ìÆ:>ÌÛžý}À–=œÆ__÷&f×m^2lÏ÷¾óiÖÑlÀú âRËWXkOµ{;°ºp‹°÷F¾ÄûôÅëìoeÝa_©ó­ïG·w°KнZ/ñ%vo²†u+i¾Ä¢Ž_¼]¾Äî–>y»}‰õ:¾è6ÛQt«3ú.Õ}…õ*xmø kû,{»ÄWXo¯Ý7Ê^ºN[¾Âëã¾—h¾Í°:»ß^,ñv—,öÒË>€5Ü1ÌÛU}…Ý÷÷`²ÊVXT©(ðÖ¿ƒÏ1ͦÛÛµñº®ÛWX¿^»ï;¼Ÿ¡¼ÄWX¯ƒû³ÓwÄyÓWX{ÿÓ¦ü† ùD¿Kl‡ êðÏÀvØ^šßÞm´¶ðí|êÚ;?Ÿ²üãîêë«—øâ¾çB__ýfвm 4Œ/eg —¿¬‰™t—Øúº£1tw__q7þØ÷ðõu×ñI×J¦¯¯»¤Ø'ô__½tõ{ùúêw3ð«Ç×Wÿ•OŠ­_`çìÅX/ñmMëÕXÿª4__7O€p÷!,j„{v¬ SáÚÝ û]áÚ³#~D\{‹]¼xÐÖyìšÅƒkb°§xpÙÖ¬t ´‹‡Ê{kw“þ|½¶Àv<8Vb%xpØV  Šóà.hbHðà°­¶äÁM¹Ü{±ï"ŽçòGIÜͰ7 wÎ&î®\EmÀÁ]rùB(Ü<­-iðühÐ ›u€ƒûW…t@ô~êƒX8x–Ì®þ÷„>{aC ôIß…D¸§³[¼U¸\Ù»÷×E"ÌÕ@Dè«Áo5.WÉ„@8l{C$»¹ZÙÆÎ/N Ü%7}ÂR8ðmS„m €°ì¼X ,¶áÿ`ÐöÀóƒör:~E,ø† Ú>¹±0hÇX˜Ôƒöäl‡0Xö¿àd‹0hO…éE0Xöx)À µ2„A{9D+Â` þ –‹Û§€AkÝK0hω!´–ò!hÐ~5ÑiÐJ*®N´o~þ€ƒ6@€ÜÂÁ²¯I\%–ÝÍÐÌj1ZÑÛEƒF9¾w 4lKÞ‹øƒö¬9€AŸ!ý‘Ä‚6¹ ‹m"Ãýl‡¯dA€Ú ú¦‹T7yÖª ½X0·ïbÁ=¯^˜3‰‚»Ìc"AßlÞ' ú”~$èuÆI‚·}/Ü_N‚¾Ïn®¬ûƱß î›ièZ"A?÷íøÑàʺ»7¯4¹´îÿ%..­{Ú^(y¸´vžÍ }ÙÄʼn‚~u`Q0>žHÐo‡0Ö¸´êÀG$è?†$è[ËNîãÒjü‡K‰wì$E‚»ÃcûNô'ï¸ÔÂÒjË2sqiµkãG"ÁýP … ÁØ ZWB‘à¾t‚ ÁÝOø+‘àn`$h%Ÿ¶/üF ¸ &XQ h1ð¤@pz2§@ÐÞÍçäÀ½tƒ¼‚%³&òè:00¾w`à®lî°E`à~j‹îÝ/*0p?IM mËbà¾áîºxçûW¸aàî³@¦ÁÞ1»$Ú‹D ÷sv”÷¬ôŒ ìÜÓÚúöAî3ƒ÷O€ðÁÆ (â_N”œ‘38P+Wrà7AÁ¶¯a 9pÿ Ÿ38Ð^×7,‚< NHûO@°óØ-Ap×£ wfœÁýc à~moÔù£qàí¼×üÿ?ÿ›èçKl.ˆ,¨ï‘,hãçs àZ<Ü|*÷KBÁ=mPÓ Æyb  ­€N¢àSh/‘(h+Jˆ‚αR4É÷­ îèX¡ Ú¦d%m°t)mÒwË…tHm°ë~Ä‚N*ƒŸ(BÜS¯Emp¿%lBÜ/­HÔæ<¤Áµ¦! J 8¥Áy²à4e\%e°pöeÐ>' ZÈ Ág­“m¿}Š‚þ+ìªã–÷«ÆV2PðiÜ Ú¬‚«‡(XÅ¡5…@Á]BmqÅ)+iQ(8¶ë© ^Tå‚vN ¸®ï’àâ´ hÝç›$x á‚&+¡‘à¢5J¢`he© Øx% Ò‚ IpMœO% ÚHK‚ñnm{ M’`²‰wÉ›÷ôP€c! ^"6±à,†øPt  i*@0¯, øN=°vR”0$¨7 ¸« ë§"%¡Ò(Ap_¯<Á¨CÜwEzZÏz+‚ó; š} .AiË©òÔúP'ŒNEð‚ª)Ô‘Ì)û‚f¦Ò APçA‚œõApð‚ã1ƒí0 Λs’8Ð&`h†â@éÁ2e| ‚v!r`üßd¿ov¡{ÝXo°kÛ•ìWy&+ø›!× þæ#©ðg'tøàoW!¢ þœ)t@}€Ã0ô‘z(ÐvÊ/Ãеß.vx¡JNO!PÓH ØŠþåɸ©>ÔºBÔ 2à”…]È€Ö.€‘2 ºkÈ€öþƒ­`ô°B™ù–1" ýäø5Úù™ŒÐÞä×ts"?;§VGò+a‚'ò+aCä··Ðê~e/84%ø•0]ø™ñŽàg­P’ø™/Mð³»’ó`²²k Màç:5@ßA¡ó üìÒÂ<€_‘µG€Ÿ]¸-ð+:b ð3%‰Ið+: L0ì‚C´£"¤DÀlG"àÞåãÄ=TÀ››””%o‡ Øe/*à~×`/Š€Ãö•ïØW‚/BÜàÝ„ØÅþ!  ŽtÀè¡Æ1Rè€a¤:`§22à¾8 ]%š®ðâ>W±P"P°)Þ__Ê€öc-pÿî/eÀ! ’2 ÕÄo$ šBÜãn½LBM|’‘¨dÀ›ÓlÊ€²»Mœ`Á9å¡j¨¦(ÃÜÐwgÆÇ 0n/4ÀKÖÚ¡î)ð…}6sàëJlšùBl"I€{[OÙP ­«@$p_î¡Å}.½Ï“û|Ë€Ÿ—ê~nwõ¿4Öøaó‹v~¹øå6AàÉå$¿´Öù¹|2NôK±ŽäçË9~Dòó*ðùlj&ÁÏɆ”ƒó ~ÇÙ#ÁϦ±Ô…h‡à§=¨ŸjŽÓb1gªaTà¶¡î_aHøYIÔqU‚ŸÍc(‘ h’3hK* äãT÷^Çô"¿=4¡ Šüt.ä§·$¿›NI~{|ô·xI~B¿&$ ôÛŒ)ôÛs ‘MèwÑ2<ÑÏæ`”ýl»Ä¢ßž¿hÙ)ôÓ)\¢ßÛ â@?òD¿K¶ŠB¿&‚ô»è‰èOèæ³Á~×›üÐ@`ßžITBì»D?}r Hì33qp–°O[—Ä>©õ‰}23Iì«ã»)¨ÙÛ¾@à[@_«ßõ¿Úda*è“iM@Ÿ,Øú >óU:$óÕG¸&æ +ãÀ>'õí‰^Hêk4OêË›õ…ÙqPŸÎÛ’új® û8å'õÕÆ¯Ô‡õ÷¤¾&£Ù ¾¸¸¨oÿˆÆ£¢>Ú7ô5™fôµò]þÛ¿¹ÞЭˆùlUÄ…Ä|uñÕóY·úWi˜ÐWàSÐ'y)¡Ï–&2©o¿-(A}2îKêÛ£¤¾Í@ËRˤ¾²d)Jê3ýk¼Ì@µˆ&õ:küºüW~*ÿáq_X±ø.¹’‘íˆe$@ž  Mòã%ÿ™@è6¹0(•ü·¿%ŽI€~²9Nô-£ì>yF¹;5ÝA€³V9•ýK= po¢´ø“§=ÌEgÁûʸz¸Ú·(PŒAvÄðí`‚è( Œ¹,0pʾ00Ж7ÜŸ0pr˜h` Œ Ʀ?HpH ”MU’ ì®’u" hFJÀGà(2 Úk{‘`ÈSI‚2cÐ0V cЛ='ŒAäÞÆ aÁÆ Á?i ªÏ`“Wnƒ†Æ Úd§1¨€7mAåª  íy€†’+íµcP™µÆ>A±~…¸ç,yÒTÖ+‚º¿4@ùn% J †Óp à°XÒô–£bh€%ÀOæ U`¥A«H0¦¥”)@¾ìAÁUAI¨‡9è%WA ¹K£ä0%PÊ´Óx1ÍAu¼.œ#ÜeZdü)Ü_õº†9('‚$ÁÝÚéè6{ ¸ Aùöæ aK)œSÎyaJ»“$Á‚uðž$h[þÏ ‚fBøÖåM >ViJÛ™Ô‹nø4 u2v˜ƒjãœæ Ü'ް8¬Aµ± ¯°iJœEæ¢a : &‚ûYáPÆ ašÆ r}KkPYÊ ¢ ipH¤ †ílzêe 5Í'j ?ÌA¹i<ÌA…³Áƒc|÷ ´A 6 PŽdi*ÈÜ÷sÑB”<8h„u8ªåÂÁ 00ÞN:6¶@¨h éXA¹é(ï8¡¬tÓ-P/ô4­osÐ1£Dæ KÒ¡€p”ÏIƒ ’ÍÀõs ,¿]G Ÿ`0Þæi :Þà~$–„)¨L„Ó'°„ }«ìGÃ'prÐ uœŸ0hF°û£Xs—y£¿¢ûì=¨CK†RIÄ€ûù±Š*Ä/2 Íý•èq?m;K2ÊÚëY刲vÙ®i¾Ú‰’£–©ý™íÜuøjGœ¿U†\{«à{æýÊ€û ¸¡¥»Ðû¶—øÔ2Ö~9n-pµéÇX®†ƒœâv/1 3Ó™Q¾ð£Ç·c)´Íu7«ë¡—ä~†m3]÷SºÃK f»db×,7Îýâ:wÍ<Šß´ÙÎÍQÊ/ ËÓ´~êrYä9<Þ(ý‹:ºï´öÙWZ·pÚ¿®U>npÛPaMHÑn÷ºìÜΆ+6p×m¯Þ­†+¯|¿)7>ö­îu× st3ö–ïæçˆn«ïÔtÝv`fuöCvÔ±Ú"ú8v^êÊBß4ì”îîþÏsÃ16œ—¨zí¨™U6¥ØiÔ#ÕWSµß Fáîhí!Øx7Ócaí½WÅAÿ.q:ö güÕrÛ¡y—Éw1l˜XÊx!×´ó²…vvÉD¤*ùë]³z«ý+úÝïÔYÎ|ÉüZçm»DC~^NY^â:ÿÈî‘å.ž _³7D–»+Ðùš>©ìÆ ‡Ð4³\Ã5=\Ýwák®†¨r7îwɃ¨rû¼“ý®/¥Æ#ËË‚‘¬Š0dxçjQå·š¸<€¼Š\fÝh#õ’[ïµ®›Qåè‡w­ÛÏðö¥«q—xïðàj —²³²!ÙÐù×pŸAi×ð«éa~v©«Ï‡aå œ<®µ1t!8 ;»Þ+·ß‰×0¥qâfÐGlúõ r“g¡—‰ÜÃÏñ|í2³*'©ý²€ ¾¡T(ºËmKÞ±ïÝ.;¿ñÑÚ§®ÕÝ©êüÕðxŸû1¯/¸3Þl“Ö׃øwƒ‹”;†Ûc^TÊ.;-¬TëÓÎ7à÷ØäBv»w‚}¦n³yôßðpô6k'¬æK=½ä¾Tî¦!þíft égµ·›z'¾ñJï2|YÝÏY€×·G÷l6/¬™·)m6X[¥9Ðí{Vg¯"hæñ +1ÓW¿Û\M|¬ŽŽÛü\.ªÉ•à6o·åËIE_¿ÍƒÆ½äŠv×ËçF÷ òQ´‡z£Ooû/wô*4ÃÛsˆ¯«vœˆ `ÝWÍϨ÷òWà)äÇÚûÏɈr´Ë¿ë²BÙ].«6ë·­r‹Žs>ëß­pY½/w{òâ²jahQ§qYmð6ØO¨²¾‘¹n ë5êÜ\X+`îÖ}½w#·ÿÛ%\XµºÛÀÂZ!"XÉÄÂ*£ÛTzuüfa]­%®ýøÂjÛ ?ˆ¿­ûÀ)“.q·E,u?¯Š#¯Ûúœ2uìbû\'Òè"×……µìI½úº±°Ú^=Özóš¯vLXnð‰ò%ò¶0§eoœPß×ÄÂj¢ÉDë).¨¢Ý…eµÈ[}om°¬…gÝ«–US+'K|Yµîï§§·¯V²zÒíQŒ\åö+[dÈÕñè®=’ "Æ»­Ueñ™n„/qiÍ·g·­c@hgξä¯&VUS+îoaU-šU÷"R|¤ÚµðŠï«jÈxw/XU‹Ü!ödêá®\ªÇÇë «ªNÔiXU‹âOì‡p§ô³å˪ ¤û²6»`r Ì(ƒw÷_ä½L¬«E1}wÉCË\úVî9ëjQ`„»?XWMvôVGi4Ì]Xv ÖÕ¢Mý^¿°®ºñ®73š+¸ÓæM|Îqa]µ-ûƒ–/¬«EN{•s“4·ç½Q_|W&1ÅÛáÕò=7$ì]òXw __i÷’ëëªéÊntµ»ÖÕ¢ô½¹ö…Õî]t‰°ÀVð@À¢è1€.òƒæªÖ*FÙ ´Gzè8p"P¡ÙíG˜T…€",КA`‘u -4qÃ…®A€Ö§qöBtƒ”qF  Eç†mI  Ù–\øЃG‰€éÔ(LÇa! xø(D`E\ ènÀxëdÀÝÅ€þ«›Tè è%ä'¬|nèrôi Ë80ƒáÝ&Û""`†¨ú©d?Е[Ö†7¬ÐeZìH€០@Ÿäo–`] ‡! ¿ãy" ¬.üZDÀØ…€)| C=¢ðvãd5ö`$À4Y fÛ9#‚•#`ÆlÂ"w²¸®–© ?ZW÷zD@£± &ú2Š–‰€î“-,ÐEm<5ðø d@¯3Nô%›( ÌPTb@×÷¯“Ó@ èwØô=,ળ-B`¦†9½ÐÓYÂuõfA Ÿ¤ã+ýÚ1@ šº£ÉÉ€i{-t ÀÐ/U@—€@/A$úÅQè×=6x<!ЫàðèapIf @ß‘º@Ì­ƒÌ@¹iî’‹ã™èuÈs @8ó€ AîNƒNA „û ꀽÎM.œ¬{±xQ [¼ã,†è%x¥¤Àt ú0*ø(ð¬ Ä®÷ @ÿz?)Ð÷´hÆ÷øG ?à‰è‚1 H€îŠ„~Eô36ˆ€îk2NLg! ]T@@ “À×0TKB@lÒQˆ;Dì³áér"à°Å·tïr£ ;ja>'ú•pˆ< èŽQ8!:Ux WÁ¡Š”ÎGA«þŠˆkÁ€—³Ö fÒø9ðQ¢–`ÀçæŸ+œ¨úK|“5Ð|è®—ø(bm èþ’cVJ 06´¡î_…BŒ³ûÐåj— "Û…¨(UI€q-´P£P1ÏI€:ÊH¤ëe Œ¦et˜hvk(šUé›e™h¡ð+ ÑX.F¤²¯¿o&P6q>âÏ À>`¡Ìh?̉é4—¨ð$I€òõHÜwŒ`Fƺ/-šé\¨”9Bx<&Ð÷~8ý fø ·z""¸ ®õŒtƒÝ20CØ a³L$ÄRe3Эq©’k 0ÍšE€ŽÇ~„-ôÅ" {å“ýRdÍÉ¥jÁÙWˆã¸öâJ•÷÷p¥Š×EtƒnÈy… •Y:ÿüBÔÙ€þBû©"rЩFâ`ú< 3( Л­§ˆ°@à»É?;q¯…9:F ÐKÐ… €øüà´Â•Šväâ?çHn•ëÔú†I¿Œ<,þ;usR´ñŸ¯S8{ º­9Ž—€(Žݤ£˜ñŠ€0Òýÿ9ðo.S™“„Wø‡ˆÆÂ‹ë”[¼Šý`{ʾHôÄ~y“ýúõýv' UŠý²Dìg›P¥ØOÁí’ýlÙ€¸'ö‹}©à/v^Y…ðw±Ÿ%üQ°Lö‹ýd°_ bûÉ]<áOpŸð§…9áïfŽ«„?1OøÓÚœðw1¦uŸ‚A&üYžKüJðÇ?…~J¸è'óD?~ú5vÅD?e2"úÙjX ô«<þNôcùD?áN_cÞ–$?yy'ùY”ˆüÚ-Ôù5F÷Iò‹Íc_lƒüBÑ òÓž.À/6‚~f·B±멜Žü7~ž ~…!(“üŒÞ䧘ñI~•¦èI~æ— ù1ô|‚Ÿbê%ù5¡LŸ'3ýœä»æ ?º&ùU‰H~27IôkErÑOîÖ‰~!FýÖÃÒ‰~qí@¿˜~¡ÜúÉG;Ño¿@\[ä_3ÈÏö츔ȯ"ªx‚_¥[n‚Ÿ²q%øY°ÜSþ³’ÏI}¶§[‰ú”I5©¯2“ÚA}Œ®Ô§Sä¾Ê€DÄ>ìÏOòãûŽ7±¯ °¼$æ+<ªNæ³Ä@ (1Ÿ|Ô“ù*Ã4%óí_³Ä|r~Oæcâ“D¾xq‰|·..æ q]ÌWºäD1_¡gE0_AàØD¾¢C¨@¾=£­Sôó¼þ`>¹ÜýJtµä¼aSàÉy :–bŸÍŸ´íäºTnÙmŠõÌÿuÄzE'öÁzeq—¬§S„d½ý•È_b½ªD°že¾¥u'×¥Ê ÿÉzÖ1\b½Ú¿©}1ÖBí{¸¸&ë)zk°^“ŸjÒY/oE¬W™Â!a/m9öl H Ø+²Ÿ ØãšrÀ^ Pr3®°ÇLd {ìhWã‘@°×d[*Ø[ˆ¡œ¬÷\bO²ž¼4“õžŽ-»PïaV”Cì2±üE±"H ^\:PïéÂA±žr&ëÙüùf½ý… ¦$ëM¢X/¯%Ö{¤%ëëé8"Yï~™|f°Ùd½‡•Éz4E9XOï"Xφ~¬a°ž$ô`=óÃ=Õ¾ˆZ{°Þ`· Ö‹†ƒõÆ7:`oJþí…‰ÝI{Ä2ÑÞÃ3Ѥ½Vឬ}÷ã ÷§÷§+q¯œz_*=‰{ L¸§0»‰{2ÉIÞ³‡„E¥€Oi´øâ#O°™À§#³¾ÅD© |Oáë à‹Ã>æ²NÞ[ м§ðdÉ{Ÿ¾°˜â[í-øáä’›ˆONËI|K„Ð÷Mí3f˜’Šø¨·%ð)|j_ðsŸâZ&ð)Ucß~ADI‚¸œÀ×iöÀ'52/,|aÆÀ7¸ýK±¯ Ô| ð˜À§7‘Àfd©öÑq3Oμ‡ÚÇlN |a`À¶R©ö5™Y†ÚW„‰¡ö1c2_ØS‰ù:ã+%óeÉ}UÆš!÷1m ™OÇ®É|!‚ó)ú[2Ÿ,b¹1 ¹oÄ}q¿)÷1IË!÷iO—rŸ4£€¾0ÿJ¹¯J$ô1c@BŸ‚j¾Ô><„ / ìún¤Iµïâë èS»CîãéÇ!÷="±ûô)÷…$r“9'õ…†Ôwß’E}Ö2Ozß–†Þ7Ä¢¾0óMÁO»)øqÇ‚_Ò…à‡`ê¡÷ÝŒŠ~è}\Ô½¯¿­>¡,~þò–ûðFSî»d<rßcˆ`¾¸!_>‘˜ï¦KK2Ÿ™Yƒ’Ä|q|̧¦ >¹D$õ)`RŸ5ƒQßÍU4¨/dΠ>岓طh’žz 1½oqŠ ðËF~*ø%ö³ŒÛÀ¯Ðû¤¸ ý;ôû†¤¼ûa÷”ûÞä'õ*ÑOÁüýåqLô³’ÏA~ƒÙ'ù)JŸrÀ$úaÁ8ÑO–A‰~òõJÇF¥eý+"¬zlÀ““€§Ü§0I´ÑO웿€@ÅMT4°„@9–=Å è6²XëÉ€žm‡6 -}°§ Î:ªt¹‹¾ ¶…ÿ$¦ÇÐÖpö,¿&·:ü]J_û_x†ìæ B{P:ü¹³5~B‡?oëÀiÁÒ\tø3´ñrøkʉ—²C…Ãߥ:áðwé^þ~—2‡Ëß~c„Z¹üÙnüŠ.æÒŒ*ôø»ãcËãÏ&íûôø»›v”òø»¯)ƒK¸üÝ >î áòg+ðMäò×eëÆž]ÙŽÂØÓVö`ìiñ):aìÙ'+ÃÖÓb†a‹.[OûßvJ}³ãiÿö ²WÉÔ³[`——©g—T%KÏž´ô…Œ°ô´§ßÐÔ³Ë+L=í:q¦ž#Œ®eêÙ»ìWeêiqÐ0eêÙÆ SÏ“2õ´×Gˆ¤©gµG¦ž]ª—,=ÍI4ôô¨!/CO{5Цdë9¢WËÖ³‡hL[Ï.k±°õìÊ«'[O[y¨ ÒÖ³+̽ý”ê=Ýý¹T¶ž=ìeëÙ•Z3ÝýÖå$m=-¢]Ùzö›v_aëyË"ýý¹4ÊØ³7ÐO¿§H”¿ß–¦ò÷›iÛI?[èH¿Öå7H?¥I¿¦“røkl%þjc×’µç¥,Ðaíi©§ÑÚó‰ÊØóR$šð÷k‹¢Qøûµ°¿ßž­éðGGùûµgŠ_éï× :üý,&º–üýÌÝûRùûÙΛúûµÊxAáïçÁ8cOw£f+ô÷«Jþ~UaÃß/ìäïW•?#ýýJ‘-*ýýªlàäîWøNî~‘+ýý”´8üýìQ w?²}ýŠbZ¥¯_(jrõkU¢]ý: <ýÜ#ëÜçîM4ê”§_aw€§_ú ÉÓ¯ˆêÓÓ/dyúp…§ŸGL¯ÉÓ¯\’íäéw­7÷!E4}ÿ°žšI>I®~Eæ®áé—ƒôô+²–£Ÿ¡l'G?ÅtNG¿³ÂÓïÑ¥ÃÓOF²ôô+aÂ+O¿"G?ÓÖ(þÑÓ¯rAx{ú²èégw)ìÑÑOGãáèW‚ÇÃÑ/œUÓÑGtéè÷È_4=ý&mEéég„à!yúYÃ0™ O?ù‘¤§¸ÓÓO8úU¦JO¿°9NO?æyLO?Å7KO?ù§¤§ß !Rž~q6ž~Ê–”ž~1FÃÓ/à;<ý”äõðô“SfzúMIjòôSÒ—§ß:m<ÝuîÄ>¤FÀäèíÊÑo"¸üü¦4üüBS”ŸŸæ˜pó+:& 7¿4¼”Ÿ_€aøù)ÎeúùÙDŠ’ŸŸ‘Jäç74ÄÂÏÏükcòó‹Ó—ðóSæ‰ôóÓ^-ýüŒÏ^~~páçwrŸ$ÅDN~ñáäw1‹X:ù]ï3œüüù¥Ö}ˆºñ°*e1uTÑ~þG¬¢ C(µŸ¶%rìu¬r„ë Ï´%G;,S;ú3Ûvº¾ž5J²•±øóhg*T´%G;,S;úóß:”Z7J°wúÃPjõçCž}¥öƒ˜hÿ&¡Ô~Ô –Kg¬§ï}Õ:âÝ‘P*k©­Œ’¦¶Î0ij+k©­³V´aÒ¢­#NZ´µ¢­£V´qÒ¢­#PZ´µ¢­£V´Ò¢­#RZ´µ¢­£V´‘Ò¢­#TZ´µ¢­£Ö12*Mm±ÒbúˆZjëo‰¨fq,Ÿ½•øqDµöKÕ~ÒQíçª}¨ö³Í}‹¨ökí}6?Woüâ˜úiDµß2ûÿd²ý6×ÿé¦ì¨ò£ú­•¿:¢Z7®½0ÿ0¢Ú~ÿ˜ÿùïìת½‚£åÿüWX; ÿég{Ù/ÇZëïç¶6s<ú§mk·X4¦¦ØbÒQà¶Õ~\ksW¿‹G K9zº…Sjîï‹¶E`îσŒn\_/Øù Ë3Œ…‹Þ÷ Eö;ÝâñÜ´FäEúbêâj·°C÷!¥u;…èé§ý^Öਲ¢ËÊ¡ß0Bp÷TßIîç…õM£†ÞË$£it;¤éÜmââ}cLay—³º/Ž”ÕPbñɬøaÝ.YÀ^‘q·³3r£tÛÝžq¨ä‡V~*7oÙ\nºp“’yEÇÙÏçGT:ºé¶ç©~àÌ»äùbª†V6ÄxH*rŸãÆÒ}Ñ(©OØx4¬Žûoÿˆ‘Å÷LjH¥¸ÿunD¤Ò y·ˆsââè5.£Y™÷UBR™ÞâW_̓âø1Ûƒvìmá©0>Öõ $•èt‹ŽqÛ¾òßìÎç&`81ïöóxbXw›<$Uá¹Q·ÙÁ>T¡çi·`“ÝïÆ…?ë™MØ×= Ð@ä-7nì6‰Ø`m˜ÌÎFªe˜q®ín²Ûp0‡iÂŒ©oW;󭻦fu$&ué{4¹ ²ðvä¡»,lÎüîÜÚÂ5F[ìž›öÁá¦$óNòª„PÝ,„ì*ÒPt·+ë¨ágÅ{àÚ ¡È!ÃÞmœ¶Á´–Ãüæmœ6W¦—´ÕGsÆ0ÈôxTóÏÇh/2J 30=ÍJzG<*f¿N¸6©-†cvhWÞ«±d2Ð#u•aáŒ<•ðÝ^òx4=ÿP —zz¯;²Zåz<<Óƒ¬E™žŠ©ãíø,6,PÖÄCùÛòLLVCY ‡TÚc/ø>ÌJ(dŠCÜi¹nüf RÝ G5xºgnžñ OÄ4qŠyáîà©4«8{x"¦‰•ÄÇòh8Êó³Q\Ë1yð.¦F çH~°æåháð³áG—/ª™kx¦ç“Á¥†çabB"تóÉPÃÓ0)dËÃäif*?Jƒ”ŸÅ¸­Âpe±~24Òð4LÌ&‹§$ÚúY«ÏÂÃÓ0qME˦G"Ày ÏÄäpUù–‰éi<#½Q²aÇáÔKn¬©ž¤ít¬©vÞá'YÃ21yŠ‹¦ÕÃ31=G(‹q!ÚLž‰ OÅäÁ-ðP°>õó¤‰ ~ÀÓh;nù9 >“Ï´G_~Ê6< q£ÐÒ0ù1U¥Ó¸qOžjÊâFNÆ AϺajãá0 ÚéXR‹l¸c΢vÃâ'væZñ•dx&{ŠB¥rX¦ÛÍRéI;nØ`z —ª†¥aºh>ŠWái˜Üt6ÃÓ0Ñ Ô/ni˜h¢‹y̳01s Þ—¥a¢õrA³÷¤“S÷ “T»‚V ™QaG44·˜°yÓYŒ¿šƒ~^$üá²ë7`x¦ #Ì?–‡©5ð¡‹z&š]áÁ-S¥i–ìÏÃD[#t­Ñšý1œêð‡/ú÷Kú»8oýÝ<>ð¯Á ñÀ¿Âƒ¡Ä?½‹Ä?îáÿn:…'þÑ–>ñOæ6‰ÔhFøg{\*ðOÓ:ùæÉص¿ø¯e’ÿâBÉ<Â?øÜvðŸÞzð_–ˆÿ¢w%ÿ5™àüæ0k‰€ˆx" ¢s&æ}Ë" Ï·@@g€£ÐàxG´sìÌ…€îk ˜“ Kèm¢)'úñÔ|É€Š%ôö:d@ŸN×)z”óo2 \‡C”Áiª€û°¨Z•"ëðN*àb~èTmClâ¡*ým `S(ŽCÔ–9T@Ù ¦ H¯1à¥))Η ehi†X%H…¸Çþ äG°Ñ†3EÀýØ@€e|h)ÔóBº:1ðNê#ZúUÈwâÀ[ç-Á·ŽnƒïÉ@Z)êŒ+eÀM¬#°3aCàýį¨ù vå° Ðüæ! ’Í»ç!JŒ ì·º›H°Î"‚]>.‚½òÈ-Pк”Ï‚~uÔ! vù ²C(è9W!(íZào¡ yù gœBàõ¥’¤h¶Íh†J æ½TCð ^¶äáGdÁëz‘`dÅ ¼„!A‚—y ^X~¼t^ 4¯ñÁ«ßØä š—Ó‹“/%- ´T]o¼âPŒ,x4CÜÉ%ÊYðRЦ`Aû N=Å‚×]¤Æ‘ͬºƒ¾È‚—ƒÍs‹" ^ ç0x]/ô=:0(hSÇz¡à¥ ‚æ¬G…QB –å±(Ø·1PÐ,ÙqÐ-lòO 6ùü :}þòRë‹›"H ¦,hÑ·ßR ÙÌCt Ê /¥@ù VÅÅO)0ŽÂC ¤X*•#‡ÈhdÉ‚ rH:ÎÜ·U^,¨8“É‚ò¯ T~‡dÁØc% Òièл(J,¨mM² |xd4úÔuИ,(sîdAù5$ *­b²`er¬dÁÊuô`Áò] TrŽdÁÂ))ai´O¬' fìÁ — Š…¥N šÝ€L4¨IƒñõË#q0†^à B±&.š‘$Ò¿$ipÏÚo”MFÒ 6IƒL°“0¨œAƒ“wjŠbÁ,8´@LAÉ‚KWäII¢ „¢`Ae|KL¹P0¸Kî·8pP›,8`*Y0†G° Mž¨#T®©—jJ%P<+ì –,(÷³`Aíy“ƒ\’iq“,('ƒyÐ,¨@ƇØùe‚æâ`Á!áO,¸Ÿåz³ NP)°sh& 2jr ­OTþƒ’§•*aТã!ô@'Vƒ ÕŸ0ž0¨fï!< Ôc& ê(aPÒsÀ ó:& î‚«ò_ ¿vðŸG[xñ'ÿíáYH„O†Pô=H💉$ÿ)uLòŸù²€i÷…Ò €òáI´¾KUv â€JuqØj, pLÁ§4À1ô#‰€{BpI´lÀŸ¿`"¢$@ÅHþ«—ì0à 4,EÅʘV :xHþ3¢F‰¬@ÃÐ-ùo}·-ô’NþÛ‰çe*›ªÀ0Î,…Èvä¿f¾’`)òŸù.j~࿲â¿&wñà?Û3¬—hS&Ðà? ;0^üwÕÅNV ¡«‰ÿšb«¥¨ð4½tÔ!þ3ÆËÿ…›oðßUyüü×ä-þ³*xaâ¿dòŸ±Ê|Ù^Röƒÿ 3ðyÅ—lD‚ÿ.%½ þ»+øïbœÀ¿+΄WœHÿ²aáŸýj½ì@§„²-Ò‰fÿx¿”À¦üªÂ¿&=!ð¯É7^øç{I+ñϬÍ>iÚÃâT† •á£ÒTÉJ_¶ ,‘-èÍX’i JÛ4Uê4½u\¦ 3Òt08BÚ‚ÞŒœ–¶ i*[P;+þ$6Øc‡!¨…ÉN%°ÅIi‚^âŽ4m2û”!h¬»¢¿{ÑŸÝÇKlŠoðg6§Mò_cl¡À¿¦X8M9¼ÿ4a&þµª†…LšôksПVÇ€¿K»]Á_e–á„¿ÒH¤¿ÚMÚ®ÐeJoФ?‹•/ Aë×[¼˜Ã3áOvÖ‡Hi8…ÀÕEWc0…À0Ý !pÙgŠþ,øÚç„¿Ø‹üµ"NÂ_“Y[ÀŸyó¾à¯ Š5UöS ¨šðg¦âoCÐ’8ÈeU¦‚?DØ| šùS¨øËð€‚?ÏHøCÊ ¢^Á~R6;‚?òCL”™êPð‡#ðÓôØÙ_ŽMf&nüÙ˜B‰àÏ£Ó'ùÅù_ØHùñx*Á/†X€_ìIüö¿€®ü -Á/¶ù~¶[ùœàÇèb ~qâà§œD ~ [–ä'7Ä ¿›‰ýŽ Ÿ2·$úÉT!È/Ž‚üš/Ð/lýlrÀ#ý.ž'ú)!t¢Ÿ–üd?š/%úÅèw1dQ¢Ó%ù…)sßÅ$'A~» N‚ü®KV¡R¥Åù]Œ¶™ä§pûI~mž’ü®&õNä·…Ñäâ{6'ùéô;ÉOYJ“ü.ùù5HòStü$¿¶t-‘_¶#òSÊ‚$?[úq?Ï™é0eL $?eHòktNJò“¿M’_¶,ò‹òk²¦ò3§¿ÏI~öáÓú›£¯%âaO œ©ù‘`>)ð.ÒüD:‚H œ·¸P¸§ËEÛÐ'FI1(ðæž1(02àøf rI~ô½)dÀ;\ý(* ùBNš‰‚-ø F‘HðVTÑ A›Ym@A‚—‡Žy$A‹Âƒ3,¡ ÍP Y¡ Ì)BÁ;¾¨PðfìÊ A „®#¼•H0HÐáPЄpp¼hð–y7µÀÄDƒ·Ò Þ²¼i½0h³9“0xÇr-¼/©G¢Á;•>Òà­¬ƒwXØ ïÊX›ƒa— ’ˆuÖ˜4ØÂËN4x=òÄVù–Ê2 CÀ„ƒ…ùš%:'*çƒñ+á ò(%Ê»ýŃ4m•XŠ /%Z0Yðàó-ìšI»P$I”…tâà~\l2m“ 8¨ó€ Aù­Ÿ4H“Ï)WûÎ incŸ„A_×ŒŠ‰á° ä’x…Ê>,Yð"Z% IzbÁ$6± ",X©ì& ^Üû f‰X0¢ÂOþ³6 ˜1×viû ?C|¡ñ…~ÚAœ¥l%8‚=}ëgöêlëþª£–2TšZ:C¥±¥¬Ä–Î:ÑRJ‹–Ž@ij)*©¥£N´aÒ¢¥#LšZŠJjé¨-E´hé’¦–¢’Z:êDK"-Z:B¤©¥¨¤–Ž:1x#@šZ:¤iÀG%¶ô·Q³pÚkOfÿ#ˆÚ¯Qû sõŸÞ³ï÷©ùO?›¯éú‡óÝÆ_@mvse~þ»PÛSÓ@mÿõ£j»xÿÒœÒæk†ü§ú‹ÜÏP›½z‚·½>Ô÷|åË»ïŠ=uÀíîð<ãuãìµàýî±_˜ÇÇwï÷’îÛ®±êç6V‡ªÝ.˜>*xŸÑTwuoÐd=þ@vH6òøá¬çmø‘c”g¯ôÍöåÆ˜É ç¨ ;àÚ!®î·êÏD„s´Éœ¤Ìë°÷Y7}£nØÜÌq7j"ô÷Ú%X¤KîInÒ(ˆ˜1ǸiGÝ|îyÁ zê {{ÆW˜c ìi‚8’êe:±½ï«L^Ç­Ô.y¾¨ú”=§…`ñ*Àé9ÛýEÕqâ'W¥zI»¶]òP½¤GÓœfèÅŒm—†çá[ØÎ¨V¬xÁ»dÁt•^ÞsÎËUÁž¶GX ZjC+FÀ‹®¨ó,:1B*˜«¸—¶Û¿Þ(©ƒРs.;ùò87× œ=`0în]´Åõ}ö\÷FÙÍï³/¸/®Ò=2ŒG·FW´ì.‹vÀ.3/İ¡½ä47$acIP°8Uæz:"Ø(JÄ´|¤¾‡˜ø³„¯Qè¡i9q†)w”˜ÖkoFbFW0EkQX¯(¹ÝÏ¥éé} líçkóC¶‡Bš¨3üØÂm¦y-‹!ÐQ‚Ajæc-žŒ7)XoÓºŽÇ­ï`Ùi=ÞÆÌX¶¬[ø¡R)à€Uw_ á®W±TÓ?ò¹iyX¢‰†ý«¬rMž)Ñòp¹?®×¡b»ì£Âœf˾*,Ì™Qmw³ùUXÇw-›‰nD`n•eoɃdÁccÔ-×;Z±s F¡÷ÓŸåÁ«ð'ÎeØ ]øRËœ¯T JPlùp™Ý…+6:‹\®îüî*ô²b¥ÂùÝo¦âÐÙôãe™¥>Â72̲×D O?@XYæøå†{R‹÷:yù(5Ïv¼¾Vüüò(X Ï=H}ep—~<§E{ðaº=n§ùç¾”iy¢¥ŽØšµ¸E°PÅ¢ÙY%!Z–ii±ï|ËS-1t€Ÿw,Kµ4©€U´³<õ›_ ïÓbéy\€ÎТËs-M83àëZ.¡~zÂ-Wµ&ƒøÕí$`à°<Õ’¿«†#‘eÂ×uÁ“Â… uá#ã€,O¶Äà^϶äu( ,O‘äA)Ô‰/6fpñå ªGŠ@ŸEj¥øû¹1Tãy-º·ù…|¡YžoÉëÀ;rÝÈÛ ŸþLžniRRD B.ø‡qƒ ­©ðyzÝF7íXº¡¤ßªvÂ坸F|!ÄL@ệ²{pËs`¬Ž¦‡X7ë^{ñ=áÒka|˜ïmV}Í]žpÉßCX-˸ä±@myÆ%ZOM–`E­Xå­ä”W)Ü®~cE5?LIžqÉÛÁu:–S ?žoiâcV°TmÑįìÈ‹/÷²°žVòþòtK ®>h×Ò- v¹~ð½<ßÒk^?ðZoö•¨-O¸Ä:˜¾LX£f,O¸äay¶,áÒ /ª@¶ð6è²–n‰S‰o¹v½†µ8â,ÙÒ÷‚»·\K ³P`Ò°ý¤`;ây}é^̳dq$1×[ž¥‰˜­˜fÉzÆÀß¾”ÖgBtZždÉ2´ð¦–¯£öõ~ð¼¼K°Ä0ºè–_ɃIònYà+SŸ* Ç—AÎBWÄdnÉ•T#?BX‹‘£7®åLjxW \6ͨ ÀèD7´€Wwá¼°,©Ò #Ír*ÙÛ^•}™)•"¸ç²”J> ®ÁŒJfÛXYðèÆ êÀëžì]/…ÞM|óÜžo»àùd’¡å>(ŠéÒ¼=ŸL:´Zÿ–¢&MóÅ'Â*ñÐøWi\tŠCÐuظãýòÜÃ<ë:Î?[L´Ä¹âÙ‰sÊN“8§Ôx‰sf+ ÊÎ)wVâœâ@&Î)þNðœ"&ÏÝñœòn&ÏQÎ-î‚æ–<éç–,¥ç‚,EsKæÕAs¶iÓÜâ’0·ä|0ç½Íæ–œþæ,‚èC0g›ìèsKácƒæ\ý÷–EsV2Xâ4gÁOÓƒæVìà‰sKQ~…s>î:qÎëQ…sVÂkçv G¸pn,í«…sc)M»xÎëŒèÎ Š:/!(èœ×çItì}$ºa$ÔQ¢ó_ ˆtžQÓ÷-Žtþ““èÜï‡g‹Ïþ[½†D‡üDçϸPD7žÝçÐmˆtðlâNÀt»„Nqb:/éÀ08xRWÁ`!ÕyGª¨ªó‹ã,Tç'xRÝð©n}’êÜÔ ªó:¤CPÝ.y ºáwÁ’éò£BŠêޝªóWqó½PÄÕyìIuþan@°n¸ ~¬ó·SQ¬ó8Õy3d-P¿.¨Î›Á.…T‡ƒŸ“êüWØëüW˜Éu~ƒ÷Éuþ!€¯à:oë¹Î«L”s]ôa7‹Õ…Xç_ªâ*Î^êý-±Î¿6äºthסܸÎ?'–`r÷ì5Èu»þÄu~u¬±ä:¿ ƪâoˆë¼ ¶ä:t./ÀQ›.C¬ó6ð €už,Mëüþ±+!Ö휉êP€P—ðöAu~m"\¡)*Áu~dÓ!¹1° LçUÀk@:7hÅ ÓyÉ‹éÜää”s‹ÛVÒù€D:·¦'Òùg#O:ÒÁŠWÒ¹Us=Î –1Ét™GYL—qrÄt©X êÒx[P—©•u^cNJæ§„:¿ÁyB—t´3xH*Û*Aß!QpòT‘uþ¤àxB¿Al™u0}Hž’ÆkÔ¥½¹ †Ù(xh9^¹ƒ%Óy+xd:|¿4™î¸bß ˜X—f×Â:¯3N¬óØ"×¥A·À×òvvþXèë;ôIYå²*k|×ÁùÁÎ?è vió-°óKõvÞÌ:ÁîxË»c¼ìÒˆ_`çsÉ}ÝÑAvÞsP²•Ó%˜dw|·P²óçqó+¢?1 íà€6íÜ„$6å=zÐÎŬNsžÉ_ˆvÞPÄÐî¼¢£FŒ+ Ýñ\@»Ì–N´ó›Ä€Ú¹©Pï‚ÒEkq’[yà` dçmb¶Y}ž 8Ø7 °ó ƒÏSºcµØ¥ã Á†øà¡Rå,ó˜Ê£ÛÆ|°C€.»t×&ع) ·Ç§…Æ,»ãmìŽ÷ °óGÃØ`ç5ævÇ´²Ãë$ê-ÍÕDõßí,àÎ^Oi'ܹÏpŠpçã(wi! p#ÜÙË*`.Â]J]‚»'´ Â5Bp‘ wOg”–€»GA˜B¬K˜“X×—`Ij"Ë¥Z§P©Öi–JµÎL‰s\ˆd.~¨uŒžjÝ5¾ÞbLÏR¬»ö+Å:ù{¥X§•2Õº{r{jÝ.J­‹Ïj¡ `‰rŽ1ƒï٥߅™`Êu [|çös¸6ùÎ>&ÞEpˆÀ;7ÔCâÝ"¯ð.ìïìv pïòuÞYÊÛ7Þ‰úƒîîEÚÝ)ŽTâ]§«DðR$ßÉ">øÎê€OƒïBÀ ¾S¡ä»Ý‹Ù²ø®35vòÝÍ`g xR ð¬CV”ðnê xRèHw²TÒ²*$ÝÅ» º‹~t£CtG "áÎFæ î”8áN3áάDßp§0) wG á®O¢œØN Âî”!á®5 îz àNÆ wƒÉUî:Ãu%Ü)ŽUÂÝhRÅw]CÀ&—€;F_M¸sÏ×$;}ü$»¾D["»˜‚ìdMdBU|Ÿ“ì$)'ÙÅÉ{Í€§b—=+ÑÎꀖ„v²uN´‹.¶“‹p²Ý;‹íä$œlG#ëD»¸Ý`;³!Ší:Óy'Û)ÞmÂÍx$Á]_<1ºcàÕ„»NU7à.>]À¡&ÜÅÇ ºë—~%ºÓcÜ)ÎoÂÝnûzÁ0$Üéh3à-È.þ=ÈNÁŒ’ìh–`§°± v©» ì:“æ$ØÅx °Ó<“`'³ö»xê»øÜvC}€Ý¾!R`—W'ØÅ@°Ó%ÀNaüìÄ'ÉNQ‰“ìú#þÙ)Û_’¶:Ivš»“ì,9nPdŸ7È®3•_’–Ÿ$»xËAvÑуìâIƒì+ÉN¿’좋ìâõÙu†ÛI²‹d+E]tì »¡³¹ ;@O’â{Ù)R;É®ó8ÈNa²‚캬-DvÑ ‚ì²)ÈN¾°AvŠãh×y‚h·ËÉj³¿.J´ëŒ¯H´‹~*´‹+íbˆíb¶ÚÅwÚiÚÅš*´‹á"´‹•hg9Ñ"ÙNAðƒíbÛuiªb;ÅA ¶+šÅv6³ÈvqY±yîx£b»èíb;ÙOídkh'g @;Í»";xªþ%É.¶("»~IÃ#Ùiódgþ,ÙÝ%vÙAs¾Å;¥ºG[ç 9‹ÈH¾ãÊ£/IsJg“4—%¢9¥A ©N1“æE+hNqÓ’æ §é4½äþà0½dzÕ¤¹BÉ;iŽÉŠR¬{®obÝ#k¬„9ÙD%Ì)•fÂ\aº¤¹B+K®<…v6‰rŠ|šRÝsI\Ê)£M¢œèåŠløå˜Æ#H®pòM’Sæº$¹¢w*u7i>H.4« 9…PN”+ÚìÊ•.ÔÊE”Ûuê7¥N-§RÇlv‡Rwc;”ºŠÖ¡ÔUÕ¹ºùú&ÕU‰lÒêèwhu4L­nÑ®*Y®T©wb¹‚`¸‰r…‘åvOèo”ÛÛ*ªeB¹´Ê-¸¬%É-Ä9IS^”d¹}ÃÔÄrüès¢œ‚ì&Ê-+&É-ZãÉ™¹¨R(—"Ê=U˜)”“ép¢Üz$Œ åä=œ(÷ðð!Qî¹i)”³ íL(÷4ÁPî¡Ó]¢\4#’ {ž 9MIr ¡‘$Çä‹ r,äž.ëFÜC_¾9iØIr Þ”0—íÒú²È·9a.ëÐü²hîN˜ÓŒæ—VçTé<;íEi}i—Â2,ëËHÉ’,'+ù0¿´:à2Z_Ú•pa}©ÕÖ—E†õa}YJ•Ù$¬/­àe|é¶ã/ãËRø',/‹ÆhX^Z*lždyY8jÃð²(0E^Z %9^Z34ŤáeÑ„†—–¶z²¼´:´³¤åeÑ$–—E†ayñ½ÂòÒ~E(£å¥]‹’,/‹2"„åeÑ &ËK¿ªÐô²(Õ_˜^Ú•Ê)Óy3ØlËö²hrÛKN”Ðöòh™¶—ö+Ü l/-°4Œd{©~ÂöÒÚA§‘í¥Ìüæd!¦—¥Òôò¸A˜^zÊ PM/‹BÊôÒ üïV3p¯É—AÛMY^™o„å¥-/_Ñøò(rfÐ铌/­X ãËãW´¾ô:à=š_–06ù¥Õ%óË¢]J˜_–°ù¥ý ÃYæ—…yÂd}é_“ª]œ'¬/í7Töh}YÞ>¬/:´¾ôv¼€Æ—GÃLÓXƒ²`}é7{‚”ÓúÒZ(‡Fç÷ñÐÚÒ­/­…S£ó,44¿ô=HÎ=Rú!ÒŸƒö—vÙsö×mÁþòhÒì/K}Ðþ²È\Hö—vI:ÂþÒVWšBÂþ²ÐNIæ—`Pæ—EHd~™Ÿ„æ—vWÄÅÎÇĉÍ/ý¹ñ˜_ÚM@¨¢ùe¾;š_ÅL‘ùe [š_æ“Ñü²(‹Ì/³Ðü2?:Í/‹’±ÂüÒ{5àæ—Ö$–xš_†ÇÌ/#9Y°Ü’!Í/­*È×Vߌ旑x:Ýsy†ùW#K Ìg½]dÇ’!qZ`®)+HY`j›˜“^¤¦¬[“ê.æ…Ž™êÏ–Pç«è†Pç©O0w.jm…kP»Ê5ènRÖêž:ØôêvþêÜoè9-0Ý1g §2|Agl§ ¦'$‚ I®›çåO‡ì†ŸÄ:w‡¢[ÞCóÙŽë<ªè:,0‘áâô§s vþ¨ÑüŸá7á®*¿w8Ô¹ùÿ©Ð¹›Ô"9ÔUE´ ‡ºÈ'uUѮ£®†5ª\êä¼uácuUÙÅÃ¥®ê\2\êlKx¿\êÌÔP)Ÿº¦y >uÖžI>u³h‘â ¬¾«ÜîèT×Z(œêª é®)\xÕ5eP ·ºf©4^nu–‡–ZÝêj°Ê³Îv±÷)Ñyæ·g½â HFϺ.|ò¬³dW÷iƒéñ‡ÑGåYgöìè(ò¬³-1å@zÖYH'Úr³®õù¶Áô®~ Ýlf½¢G¾N´óˆ{آɱ®]rZ‘g][ ΞuÖµ=zÖY˜òë´ÁtÓöuÚ`z^›ëd»iû|LÈò¬³àæôÇ£g]SŠŸp­ksp³'ߺ¦{á[g±q-úÖ5Y…o] ‡ úÖÙÇ#•ѷ΢2ÑL“¾u*úå[gŸ &*ò­kJÚtwÑÝ5|ëšÂäÜE0Ä »&î »kßÖ}*uÓØŠ®iô­»hI´³ìBX«ÅvWlSÄv1¿€í®0ØÛY'¹™ÎsÍS¦óøØ/LOø´^žuÖ vâ»K¾âÁwJÿ|™™‚ï,…Û<0=$$hT|×Ò•|gÄmx×tpxgw\N+L›Ö^xYµï,ˆÿór¬³ˆøët¬kqB/¼ó»:ëšÏ$Þ¥F¼kµàO¬«—"RÛµ§ÉCŽl×tžl×L+G–ÕËlæ íì{aìí =½êä(°³ðåèTgãÍ ì&CØE`sõÖû4¿D:/×5El °k m;KÏð¼\ê,ÒÛÎg/üÄR»Àñº¢ WœÖNþ¹¾Î³Ù½E+µÕýF/Y=áɧ«À`ÄŶ]°ä êPüL‹È…GàgؾU9<Ë`þãž‹¾ÓÝôÕôÙë1_}úøáA×Å )¾ý{6LŸ…N4»`Â`žVϦ¡¯ÓýYfýq[D¼soŸðx,Ámµ|2~–/üi{õøq5ÌÐ|;¸÷9å0!{Ü æãq£}û÷¸gîÇ­±}Ãøøu¡¦oJ¦ñ˜G鹡Ïã~,Ï’t£ÀoØ£ Àöm ?~,–t=TƒÇR~ šoøßn-³‰ç1+ ïhoÓÞó‰8k{¶°h(ð[Ø%vNzH§V«!%gß%mHSño¸K.jœ'wÉMÍdBÚ·’ç‹ÁØœ vI§nÂ)»dPÞ)¬1©›0²•,—V„£»dA9±Ä+ÙI=Ú½ñ+ Ååu–Z¶ÈVö rh´Íéðg¸nH¥»Ä²{[ ìsØ´†¦²’åÏ óÇ]â¢ì]ôþìd‚qß¶; qÞ×bçP!XÃzÍ'#Ãï’uùÝYîR^Ù#Xø.ɤ¢ä¯ìwàWl§¹L¡d‡ûï…S@f% 2Ê{1‚¼Qcà‰hÎ[éxãžJåãäøÔ¢?ðîڀΩõ»dBèÔéÈ.YP:U©S1}vÉãêÇÀ¯û BìTR+yüþvÞŸ)}< ßÕÕn¿¿Éø|»ä†ôhùòT–v»²åÛX;EcËÝsXIÓ[¢F{å µŸ“Ô]ⓤ¶ý÷‚ô9>p<>'“¾Y ´Ï…`›` ´O[Žð#KùÀÐyÍ–ÈŬ9ÄJ *LÑ.¹°§¨ghýSrÜ.éØÑ+§µ•xs¦ÚØ3 t—]2¡.&ÙÚ%L´Û]¼ÒrfŽdè»äÁ`V^îÍzB¨ÃÁCY ×㺺¬åòÐ~<‘Ú%æ›û‰ »À\|?ýã§ß¬ÐYã^þ2¡lÃ’à2ë–h¡U>бÿX²ºÇÑ‘Ò.a§riƲ@Ô'K<ÎßЖ+ƒFì‚Ùðçâ•ÍüÍ|&ËÿãO°°÷Ø%Ï'xÔ%,ÿŸ€Ëå¢b«H»„1 LÉD[I›»GVµÅfmùO°ŠºÛ.p9…³ÿX¤Å›- _M«¢§ìœZu–¯¦v³ï çV&s^4;Þ>WÓ§`5•°Kê…ûŸz%Ã#?.þ¹ðvc;ð¸T«µý÷}᪃Zm®´’…êζI[¯ÛµÐö|€‹×^ðàäÍJÖÃR^üÕÓ¿x?^¥zÚŸjA`ùwe¬6ÆŽ´Œ¿Ê,ÚÕF<RªÖêûð'¸ªÚðò'PöA+AܶF+âjÄð®jP[DÙJ°˜>HäP­<5îvƒ… ñТÊ"ÉJ½`ÌDq$¤x¬¿5|X"œË¹çѽåˆp´( ‚«Ð"à”d/ÎDWÔ ÀÙþ¨D€3•xF€k •§@pŠn§lgpÃæà¤ nŒàbà–Ž‹pë>éÍçÜèmɯXôf5êIoÅ ôfà&ÀÛ’%àÍÚ{ÐàmÉßLð¶:WYÁÛ’€ x[ýæ%ÀnK¶‚·¥X›‚·5 ø‰Ý–<7ÁnyI²›M~¾9»­ïìf?©'°ÛRœk±›Â]à?°ÛRRY±›ÓÅÀnKÑñoGàm)èmÉr@øfÊü¾ù50ý‘ßì” ‹ÖªßúdT‘à7+Á, |óß¼Ê:ñ ¡àˆf'÷‹fàÛ.iÚ¾!0oÆñÍÏ,¢™ã›·ËÙøöºÇ7O‹Év€oçµo…LøæAÙ‰ À7¿çtàÛX>! `á ¥j#[oþ„:¼y«ÜÞ2žèÍï·Ÿøæ¡õ—ŽogÃNoÞÌ:éÍÃæ•“ÞHTåqþÖ¥íèÍϲ<ŒÝºßðæ?©'¼y~kÀ›Ÿ$o~a~7ÀÛëÒoîØÂý=à íœðv>¤Á›YonQÈ/àÍKØo~7ÄÀ›—¨.èÈ÷…’¾cA1€7ÿ÷€· 1(xón˜o¸:qÎ#4ÏàðæîFº’ÓÛXŠj.zónÞ€oy^'|ó:<Ú¾ù÷ À7¸‘³.œë˜Oü–Žjâ7EdÁƒFÖ‰oˆÇÈKO,’r½¾½aa™\K/øëÏßü…Š*VJº¿ˆÞvÁÐí€ÞÒ¡LøæçÑF÷àšÊ |óv,—Š+€{Õ™X1Ÿ) —üh%(XX5™Oø†kt –Íý…UØ*{#ð .i(€Ë¯{Q’Ì.,žÏÀ¯èÍ›Q³w×ûÅ“ôæíèfVÐ|yCn”‹ÓàÍ Ø?#ž> ÕàÍ©‚9,£ÿ¤7ÿ {ç¤|–`%}Ma 7?…æ\z;:èͤKÁ øèä 7oFà5n=¯=é¸Jˆ½ùë\'½áåñîˆf³ ·t×½ù‡âÌz;úÌ’¥¤yÒ›ühQòè#p‘Xt –çðÍ›mü }‚KÑY"Οš“ã¢W°ÜGEpÞŽ®M¿àÒ@àü1y.‚K_F\&5ÁÁqšuâ^í„å qçýâÎï ˆ{µâ—Η‚8/áVQ7çÃùíqîÃY‰ýéOLñZÑ'ÁùÇîüMëºÿÉ’+Æ2iç]zÝ,t,"Ü«þ4èÂïŠç%-Î=[_ç%•¿q„;Ÿ ç!•8Ãù¯~’ú­g5–Ýâ„nÊ€è6™ò!ØMŽÔÁnÊTì&/Á`·IOœ`·™F“€·‰)’ìf–ƒPÑÈnæLØsv3!ÿNv›õ‹F•8ÄÈ(Ãí ý´¡4ié…nV0(Ì1 .3s„òUqÎÿ‰n)oIˆ“î*!N²SqVðâ&lqxoRá&‡Y¨p¦u±‡³H§£ —5¤Â©ãB…Ë+R…˪pö‚ˆ`RáRøJN•*œl&%Ãña_2œêP†1“‡ —Rd¸¢oÊp/|‹G8d¸,‘ —%’áÊOd¸£2܈ý”d¸½Q†±I g+Á ߬ß)t8k…²…¸ã7´¢4X;Í(Ö®oø¦³û ·8X¤ç?b3IoÒÃDoq{¤·öõ¶¢Ìf oWh‚·ÂmE°[»ÝZaƒÝj0`²[û »oìÖu°ì–,ù0‚Ó}êp¾FL•ݦVå`·¥û v¡‰Ý†:u°ÛP‡ v#”%¸Iq nãž,¸mj n³¨KoʃÅmEÄÜÖµs·•0·Åg¶åë¶¥½œ,(4!±Á¥’Ú·RÔÆw dË—-dËHle’ØŽ±ÏŠØ¼+‘á¨d À dkúB¶¢s([°b[×8­‰¾Ùòî„l—zK [}©o^Ð_Ö“þ®d+Ib‹Û ÓÄÄV5{ˆØä}[Õ7b«ÒM‚ØŠ$Å@¶é@¶¼!›*ˆ-ú¦ˆMqºÙâ'"¶*aZÄ–Ã<ˆ­ê LȦ|t‰lyÌÈG lq{B¶œÏÄlŠ©‘ÌãÈÆ¬ÓIly€ÄV¾NõíÅ"6Å&KbË“3ªoæœ1NãIŸöÉB¶ü¸B6…‰MdKeȦܞ‰l YšÈ¦ÓçD6EKdSĺD¶Ò_l…Ä.bˉTÄVºŽSEl1*lyÖf+q ,ñ-¤`joÇQª­<‚d![*J{³fX‡È–S²-—*‰oñYˆlqÐÈ‚ô·È¾”ÈVð9ô7±IÚ"²ÅÔVä×ú›´«¤6LLj «ëÐßÂú[<‡þö´ä¸Gñ'Ñ‘BSšÔßâxZúÛf%Òßž°6—þfNFtéüÍ1Àá–ç K„{7÷ÈbZ÷ˆŒ…p(Wç0zêoe áYÕ á,åQ9=áëÂEj-!œç]úÿØ;»]O’åªßóûò Ò*¿³.A„0iü–AÈÇø ÏOEÄZ+²vwÏtŽ,_øjzçÔ?ë»2¹"VDC0œùAþÿ§Î΋žœò›\É• GáE™pðúP"ͽ•'j`"óI”Ç$$­͸F$Â16 ‰prõ‘w3„HòÛÝIhßX1Uò k%¿ÑåVò_[0œ¦;Rß(äçoã<Òàr¾‚ó· pT+'2ýßüMŒ§(.²Ø¢Ë8 CÃOè¼q¹„ ˆ[2ÄÅ2^ˆkîqÉ¥@\fš⎕ @Ü+Õ ©p¹Œç»ÁœF©pZFc*\¹QÄT8sÌL8 e&\Í8NÏ„³÷”‡L¸³«…›Ãž2á6Çmf±$_f¡¼c&Âå”wq­M‰p—t;$Â)’\‰pM‚‘Gó®#®sZI„{Z&5¹|àó—™p,x–wdåA€c ´D8VÃJ„c^)®!Žnd83q²ázáÕ$ÄõÆÙ)!®wI€88%Ãuå8‘á2Ý ×•ãD†ëÒNƒáºÂÅÈpôöO†3´w"\W¬î™À“¶Àp¬" g³À3–Ò·ÁôG—ºä¸ãWà8ËÔÅ1/ô»À~à¸Á bÜФLǸa\gæ)Ž_üÄ8ú<&Æ={"„㺢âˆqC:.9nHý ŽcÉ¥D¹Á@¡Üé“åF£âE–š`“åòWd¹¡ÙYî¹›¢»€¹¡Ian` sG‹Ó£ö“憸ž4Ç&IsCk¤¹¡À.ÒÜкq.P‰s¹ q.Eç†ÖEˆs,˜“8gUosC’ qn\|f‰s‚Aœ‰…À¹qƹ!ž<7$‘ç2i6xnˆ%t Ô Ï á¥ sû€Ìåó@˜Z’ü6Þ4—7 \¸¡hUâ\^Kâ\^**pãJ/ä6¯/x ptR%Í1f-iΰꤹ8m0hŽåñR€³÷îMstËHš;Z Á=ƒæê—47é[ Ž%¨ÁM¸E§×’!šcm eÄ]Z­–wlŽc”4¸A`N _‘Ãý«”µÇÛò¥U$™(Z-²óúö° 7ø=`µºP¦žñ÷a¸å-4¹‰?îj&ÅûÕ[Î>¢M½àÏ£ŸV¹žçÈ–£´±þù—6+æ2\~¯Øþ§4ûÊÃQìŸåãeöé)óGh^¯çîõµ{¯èk&`èëØ }½¶b_‡Áú:mÀØWnž^faèë°øB_§ûÊ­Ø×Ë. }&_èë´c_¹ûz†¡¯Ãæ }f`ì+·b_/Ë0¼Ã‡ÑWôõ²㋟[¡¯ßcVÌjÜìãÿÅì7üÀ¾ç»ýËû;üÅWú—¯¾«¯/÷7^Ôw/?ì ö[9÷åiÔ[(õBü¹Í¨Ñ€õiæ=Ö áçÖÒ¢¥b…ÆkO ÂÏéaf-X¤.˜ˆ×ËÃÏ“c«Q»ûž!ÙÿiAøy£©ÎÓ ÕmáòU³‚ùÙÀ6;–ªŸ_Eø\u?ØæBÏw¬V7züT³{ñ [ͥĢy\®ên$^S~âWуtji±dÍZÁOK$ÛyƮˈekz±YK$>uübƪõ@Y°§%‰­€;®¦•©ðÕvÖ‚:à\8ªÏSó3êŸÇJ­‘JlE âÁªfOž%¨íïÅ〪æÖ{GZGìÈ ~¡àFz]ˆ,ôù´ôHy.xÇ®òG¨îW÷PŽžèg"ƒ„1ìÕ>U¨àÛq8‘I|“?keí‰]G±ªÑ–Ú.e‘ÄI¶È"¶BÖøQ«…g€Ç¡UTg,z5‡ø³èûÓÒã]6[…8˜6PÐrãÓ™$“!¡µÍÈ$™ôk[=¶(8˜ª¦\ryZ"•d2ú÷¹â!Ñø Ô~E*Éä2{í‘Eì_Š‚–H%™ŒÁ®=ÒˆÍÛ2"„jo‘J2|Z{GuîøÐ<G"Éd´wícðø‚,kŸ!¢Ò ðiYOl_‹tô³·Y8š;TÔÅÐ:®FšŒXZ"…QŽcu”PQø4Ôöî¤]4+,héHeÕ ÷à ÐiÄ·ªÕíyßÖíYP÷ž–êê?cרÆú4àþ[å?þÆï˱Úâ¦×´O]\—YâM68¯h‰ FÚc>-5â^Ÿm°'«Ü³c ψUîñKsC3©V¹§€‡Ú*÷ÔÐå:öyÄÖó…žWÔ$~>Kxf¤ÛÝeÏ{E/ø²L$¯Íj]Q—˜%<­%’¹‡,"°/¿ÄѰ"ëZ|;¬tÏû6Xéžú‘EÇŸ–°½)û´„Ú+³É§r/ë­XËGÜÐ ß]x%_Ö_yZ ùæµYÐ|é¥þŒ"È$¶¡+¶ÙP}wás#“xk|Ü~Y³èiiþwåв!ü>ý⊲"«™sL´Ä˜jS¦8âLb3 A äß]ù®nè¿ö8£g(À¡–{ $`ŽÔðFÁŸ§"0ý9ž†·RîX\®7bò,o(ÁX«°†¥ÀŽ!Ó öiA*±­`ˆÁ¬ke-K 5vŽlÌMÍ®²&ë¦B×.wFµñ¸à拏 HÈܜŴ ™(Ck 1¦Òr°]ôFå»Û.š£.µÐµ#°¦]iºq04H¥J³¢=ãCªOÃfÜÇzt‚ÄLU”Æz¬yJ‰™ri,È*3ŒV™¹QÃáiÁüøù&ƋР²3åÒ Ò3aâú4 ;s-\¬âÙ™°|}þDr¦•äÁHÎdí[ïŠ՞ø …É™(éóàâ#*KëZ ’3icҬξ„)­"9óø•ße-û;FÔúZOK•Ot«ÌÍ,È–ã"Ó-g–VÜ{tƒàÞ烺üò=bùyØòkék‰£@~ õù)„Pä‡z’ ~EëÝ¿D‚+&ø±²O‚ŸÒ_~Ê&øY(öð3ÏC¢`€_Ѻt€_™xƒ~™sBð;¶øÙÐô¿­l7‚Ÿ·¼ÀÏZpž¿³%Ào3?‹ÜgÎl-KîÜ7IÞmŠ÷mækû¶9ˆ}ÖBÊ îÓˆ}çû¶¢?ˆ}ç6}[P}çß}[ñ!ľ³ßÀ¾-ßCbŸµ`èöy?„¼X†=[P8ƒÉbľ³%°ÏZ¢cPŸïWßÝ‚úü'/ê;[û¶—‰}箃üÎ_ÁBªhF ò³– *……”²ÛH~[6$¿ãWN~ǾA~çA~g/­ò0“úûúG ô;[ý¶2ÿˆ~[©jD¿óW0‘:~eì·•¼Fö;Žìwœàïøàïü,¤rO€¿óWÖ.üÛý-AÞWÐéïü;èïüMÐßqÕA[9n¤??šh€…Tàïèðwœ&à϶i@²^^ÝûåËôó_2ýÎ8H±~šÐï<º@¿³%Ðïhú§ ô;· ô;[j{íì·•BJøË³ûÀC*O ðw\*ÀßÑM°ß¹ t·£›€¿óøà"•¿rø;ÿø;Îðwnð—ö;vö{µÜ<ØïÜRymÀ~çáÀF*w¾×ûèý¬e¤ýŽýÎm ~æ®~Ç®~ç¯ýÎmP=䨾G ’5ó˜×üt|H×<¶@¾f^> ßù+ú¦ªèwüjÓ95[ýÎ_!m3ÏÊÑï8 ßù˜H¿AîfebÑïÜÙ›Ç6[ï³Z6ÏË@¿cï@¿ãW@¿ãª;û¿Ag àïü 29Ï–¥ãC ’9}ý-Hç”ã4éïì ÇñÜŸÞÅ ¿¶HÙ ñ/÷Mü;{AZ§®(0¯0ï9ðìÙG Ò;×K<÷µëûˆƒÏ-îO+ ðØð8+à¹Mïû@<ö|µÜïg‰x\ gÀó7«üü¹eº€Às›»}º€ÀW‹FV¶=»çxþ žy€Às›Ñ>C ô­ žû^ãõ¾þ€Y‚`ˆn'²ƒ8ÐéNP‹ŠâÀµ¥Êéö*\r¿&nºª‹×-jýMhëƒoÐʸ~¹R%4PÆ)Üï~ÉfË 9 ˜¿!ÊÔV˜ç@Ôú 8P+}âÀ<rà³/ž¹(Ðih{NK ¤@[ÆÅo€ ‰%‰Võõ%ÿå%²2lr —_„ó œ#KS9bàäÌ’x4À#NFœbBà± p&:gò pÒýEh‹©û\¸ß¿Î-ݘkà¤À¼2¤À£H€¤À<Rà$ä‹ã²<|Rà|¦&C œ7סISÜJ Ì«N œIo]nà YR`êJ¤À™ <ö œ Q²‚7)0¯:)0÷M œ\Ë Ê&\˜—˜‹˜!ðhåÓƒNœŒ˜æc˜·8ia#LiŒx~€À¤À¼¹+-{ÀAÇáÑ´ç ÌÛD Ì–˜û&æA Ì»@ ÌžI9”æñ‘=óˆIy/IG?K+Rà±ÍÖÀÊã£OR=Xõ˜“¡ïæ¡s7DÀ£‹4óio\_ `>5DÀ<\" Üe„€ùdóòu£€€r­[|òõIÔÛ!\,`#Ô õ€ WÂÛaðóF@¾"À•lI‹Ÿ =xl‘¥6Æ›óJšü´7扗4ùrÑãÊ"ël|AyÒ% ~°ã‰ç¡¢À߬:Øô÷\•ô÷!®þ”¿!øËS$üå þŽmXfCÇð§Yà/ŸÂ_ÞŸžNÁŸ>,‚¿<§¿a[–À÷|Îw}_![ì| ð͉ïy®6€ªê¥XdÀû=‘ò)øHȧ¥Œùø œ1Ÿã|š4ùæLùôêùtñ€|š§ ù¦DF"ߤ{Ÿ/÷MäÓíòÍd1 _^ "ŸÞ¦D¾Kž³¿¡DÔ§)¨O–¤>Ý)R_NF®4­Âª©/碾ÜÔ§ØÛÄ>}˜ìc(&±cš°/·˜Ÿˆ† ~˜­ üR®$ø ðÃP"ð[ `_ŽïøíWЧ×bË~ ÁOŸ’ü c°W‡Ø—WPØ'n!öÑÛïÀ>Ý`ßÒľÆë'죕mbßPŒ$±OÛû#)ì£-Cbmœ…}–šuŠ_D~ÊQÿà¾+þô[‡BècŒHBŸt }LècE³„¾gªv€>ìšÄ—»ñ1­VÄ7h;”ħ^ßÅÀP_›€ïbDçTù5ü†¸—GÜSÂfâÞÅ)«pOÜ+  î[€÷X"ìàË_‘øtH|y4$¾¼o"¾lñ-7±@>^Ÿ.‰ïl¹y‘M@âË'“Ä—»&ñýùX:‘/{f… ]@"_^Š@>¥ ùŽ–¬²]“øò`Xð^‰/Ø…60"ˆøhí–ħSâÓ5‰/[@|yJ">Þß± O³>Õ«Nàc·€/ûðé€ |Ç6eŸCä;~BäÓÁùΖõéðˆ|y£„|º6D¾c_@¾|{‰|Çßz°+jp°!ß±k*òhù„D¾£ Ÿ,„|:s!ßÑ3++fÏ,­˜Çæ;~µ?õæÓy‹ùë$ó1¥]̧‡B̧;#æË}úòøÈ}f‘ÂHÐ[ç€_ûôøåy üò7?Ý__Œ$I}üð&õéH}’út(¤¾ãWíõ&ˆúlJô¦>ÖÉIê;¶!õ±¼¨/O’Ô÷Ü(_Êú׳ƒ§Mf¼¯þ)öÓ-ŽØOK cheàݾ@Ë„b\g å\¡ÆÐ2ªe€öv_¯¤¿[>à¿{À”ø—ñÿÀ?·å"FÂïꙣþ”㟙ÜîSñ;JBÿÜW t·«Æ”П;äœzßáÎø[×d1ÀߺTBðwØß(áO&±JøË*V‘ð'ûS%üYúá;áOeB”ðgý#;Aî†Êø£ÓªþJ‘ˆ„?Õ1QÂß±'ü]7WW™ð§rJøSD±þÌ#-Hø+ú3áÕ”ïçæ0Ñ© ¥ŠÙî'·Y¥ûÑjSÙ~ªÐŒl?E*+Û¯Ð\DÙ~*O¡t?±eº_i$füMȘñ‡kÉt?Y›*ÝÏl^rŸQ}Ú6õL÷³àëøq7ÌõS‘%û] ÙO%Y”ì§Xl%û%Æ1Ù¯ŒäÀ›)­LD²Ÿ¢¼•ì§$Wdû•¡üEdûåµd¶ß³ .ÓýTpEé~ŠWº_žÓýò¬˜î‡"Ù™í§â)J÷Ó'Cé~,`‚l¿ãx‘í§Ò.Êö;¶A¶ŸJp(ÛUe”ì—§Íd¿|\™ì—7É~Ç6žìwìÉ~ ÆW²ŸBæ•ìW„­Lö;ö„d¿£$ûÚ +Ù/[˜ì§²'JöË~˜ìGcCfû•Á%fû©´‡ÒýòÎ1ÝÏl•ð+äû={ú”ïg¥êѰð–òÉbº_>YÌ÷;v…|?å(ßOw3ÒýÊ”’†t?{ô؃©ËxE|OÓýrGL÷³ÏÓ‹ün¥7(Ý/¯'Óý”Þ t¿|N˜î§º&H÷S!¥û­¾1Ý//ÓýŠI™îW¸þ«t¿<+¦ûåÑ0ݯ(H€é~v‰ÑÒýŠ&™î—Ï@¤û[ÐßUé¼L÷S¢‡ÒýŽ^îW¸:®t¿|F™î—ý0Ý/ß3¦û©î Òýòj1ÝO¥o”î—Ï>ÓýTKFé~ÇžîwÍÖ½‰ƒSó¬î§¥û…Ñ0Ý/ïyäû©ð’þòþ2áO9/JøSU%eü{BÆ_>µÌøSJ þT(J Çá áOYDJøÓá ᯰR¨þ åeü©eüÛ åOŸ?åüé;Ìù³O„9äüÉæA9ªÆ¥œ?ÕŠRÎß±/Oú+”ôwô‚¤?eˆ(éO—XI…‹ãJúc¡-åü)»G9ú)çOé)ÊùÓ÷NIÊ BÖ_îYÊëPÖŸ†eý)·GYê†Iy,LúËΤ¿¼4LúËËIJÿQÒ_áò¯’þ”¥¬?UlRÖŸ2¬”õ'Ç]eý±ÔÖØU·s¶OØ3„Í¿ûIî2•F2ÿé§çcôÀÓý‡_òÿ¨ñÿü_¹Ï¼g|Fð|“ÿú¯þÕ_ÿëßÙùßüÃWìqþßOlf¬Ûšïƪçnþ}vó?ŸÝ Ÿ¯ºóü¯÷á¶×áþWß¿þ[þëëçõo³õ—ŸþXž©!÷}UþËáèóŸ?õô-ïê·Ï4Ú]Gíƒ8‡[ ÷´fËd²/ËðÜýì -?KÌîæòéñÑZ~[f6«¯.ÐòcKì®[Aƒ× ¢åm1ØîÚÞR£CR’Å ZÒbð›?¢Å 6ø=ƒýÓ|uH}«å°öC½³øçaØ£YöŸ}X‹zð?Žß ‚vž#[Ž>ÐÆ^øç_Üb°_„xy ~Ó°´g‚Þê·MŸ ÌÌç c³oû~yÇÛÝöq}âj¼» æé.}Ž€Ñ×Ëp¨˜*·ô€>ÝÑ×ሾNG@ö•[±¯—» ú:Ñ×éȾr+öõrD_‡# ú:ÙWnž^î‚èëpD_§# ûÊ­Ø×Ë]/æá}½|ù6çVèëwù¶åE¶þÅ7ð7}¿ãcüËûãúŧ÷—¯¿«ççøë/ê§^~Ü7°=Hxõ>¾þZGãù6sys3Æb2ÆëÈâ2íî!˜\ƒ!yæ:æIà’:îé9R•aræ&äN‚ƒ!‘7"̹ ¿Ù“[€ºvc9øQÌ´­¼‡[Äm¬°ô ëÁŠCêV EªÐPÃtý™FJw«Q>Öó`’ß½äÂÓ¢¸™~õç;ck³èÄ—ƒWí4 éî]þ´°jÉÓ2ÝðÙŠÄôk¹çz“tÔ¯í†Ïͪ·£ç-XöË÷ºl…1Vz¹ÜsÝlüc±±/§´†-ÃN´¸ëúè,AÔŸI‘ýÍ’:½ø¢ðfƒ~›>Õº^7]Ÿµ#²ê9.7|îƒåšzñEá§¥c±üi¹c:È¢°½ø¢ðòÂ;q½ÊvÓõiÎløÕíâμY<èiqqgZµˆØW½¼ß‰…ã^‹‹;¶ ÌÙkuqg*žíiquÇêï„bÑksugY}ì©ú¢ðZ*BÕëpyg5&x=-n¼¾žj¬aõ:]ÞyFT>JuÙ}ËXéu{…iEp4¾,üü^.œÇ=Ç?i¾&üÊ…%·ÞŠQX²GZ¼ˆÂêôfï?ú ÌÊFùÅBYž§¥—¸À•7³u/¢`+oÛ ?¡ÅǺM/¡0e¸ÔÛrãõeKHØ÷ò" vpÉ›/ ûWüêözë3VÝ{÷5áeGÈþ´x …i¾Bhñ5áµT+®?·.ž#êH½ûªðš(äc ¸zxк/ ûí5›§Á}×gA¢[ïóŠ ‹q=-+n¿5½¯OcAzßn»n•Ÿð¼öûЧˆÎ9OËŠ'¤#(®kÄSD¯¤>|UØßT<åãÁœ5&sŸ¿W\àÅïÜh=ž¢ý36ñ%a¿xøØŒî–ªy÷áKÂËŠ-à0¦WPXJsîcÅK¸ožæðÜÎóŠŽ/ós¶‡ãWÿ9©èv^¾Æ¿<ß|@bU¯ÏâõVÓ½¶OL‹{½ÐK+15íXå~ZîøÒÐá¿Ï>ã-­ˆTêQì˯/Þíéñ<~ÚxÅŒ{üíÅ·nÈßþ(øåw;ÎÙ¾Jþˆ\|£âײýÅúa’_þÀ`݃Fó¬E¿ž·²ñŠÛ=\ñÐàóu¿ÖÒ*c·Â_óuÈVùËa÷v¹-æÓróÒDí/„¹ïåE«èõ(þµl–Š«gå¿Z|4ðÜGý/ÊcOVÿ«Æ J~`ÏûÄ’ƒÝ<ì ‘L"`ÞMDDt«¶¬6Î:ê€=¯öP/^ìiч{{ :~å¥ÀÎg1²ž'Ö·=j=r]àMƒs.Úö(¶æEOâçUËs™ávÔ›ðú]ìoW{þŽš`V6%$¿îÖ/•šŽª`öJàVzÜD|}6Z¢.ØTQ…~Qm€Æ¾£2ØÄpº`Ó H`G+1UÕ¤£6˜};°Ém+. E¨ 6;+sŒ+B%ì±Ø&b%feĸ"VbÜ,5Pl6Î,°FðôÜÔs”÷­½G°Ä”:>¼4Ø|Ʊ=­Mc JƒÍçf_Ø“K,ûÀTô¥Á&ËR T;º)+±zEâÉ@e°.Ud”Úx±ø>PÌ®–Z|8µ£‰¡{xe°|†F1œÚ*~•Á¬ˆŽ·x¬„_Ï£ {|Ó)xÇÜóx]h‰Ò`ö4¶Äx*{ 4˜}¿±÷Zb<}F˜è›*16¼8X× 6PlHà(fgs¹QÇÅÏe|YŠƒÍ ²û¨-á ñ}(6£ôͨ-á×·`ƒ¨ fÅ–"kT–xΈŸ½Ú`SŸÆÑŠó+…'•Áì]IÎh0á×%æm•Á¦fi£yÀ„?E¿ŠÊ`V,ƹÑ<`b5…Y T›ªK:Pìx[Ż-žâˆ£6ظé.þ|Ö«ýÝ1ÓÐ’‰áNôÛ=`b ÕÕââȰ¹×x¿k½8¹ï²3{qêæ$ö1îJاš¢À>›¼½±O"¦°¯Vv êk#/ÂäúFN o³œ™oÓ›È7½:À 1@½˜Á|‡³9˜/§ñ«'É@RB_ÖH%ô™À‡é( ï¢O8™ïRb™¯äÄ Ì÷Ì’9åóYÔQœ$¯Ø4„€µBlÒAôªZ”!_½ùHùŒ8ÔâT{îpÈ×äðKäkƒõ—…|³˜ äë…Ÿ"ŸMüq A|]ï ‰o\EÝñÙÒ/ ʈpÌñ UÒ&ñ=£1o7ˆ/&ßÞÀ7ì)~ßh¬Hà³ 0n€o0¢™¼7T¼gh@º+üú€ À{ck> Þ›…A§D>ëRòÙÈ Ⳏ1ÏñÙLòñY1@t â“0‰on=GN|SõÅD|÷õ3ñ.€ïÕ0?ðÙ¼‘h ໚vÀ·ò,A|6Ñ@ø†Þ8ŸÍ¾¶ð--@ø6Ÿ4'>› “ï:f‰‰Ï< ä3HÁ|È7åæLä›Ï»ˆ oÉ_“È7UUšÈg3[\Q"_)º@>gRК!Ÿ¡.1‘O!*‰|ºè`¾¥"b¾Áðd>VSóU&“ù–׌†@¾§a¿Ïn¾‘oÑ™SŸ…™@}²2õu}HH}ÒàI}+tPß²LBüŠÔ7‰¤¢¾QŸž:õõί.¨ÏVbpÃI}VÑ¿ ìó+³ ì[–@ç ¤¾®ï0©O×з´øAæ›"&2Ÿ˼ÈW´>æÈgœ‡ >o äkSÝùTá”Ìw¬?€ù–B›É|«³– ¡o©¬¡oiöKè[6àW}Ë& ¸†=á5ô-¹\úÎ=ôÙ"¨ з«:úŽ5Pß²0•¸— ¾uqNOê[Œ ê³¼š‚úlï€&‡>«÷‰Ÿú’‡}ËgQÞÌç_Ðhä[ Õ"ò-Ù¹ù–¬Ùˆ|öðàIõÑã!õù2 [î¸ œ÷ŠÅ¤ØBØwƾÅPlQ_ƒ&ê³Sè`±†5TÆŽ“úìSSÈw HI}¹œÔ·PLê³{ Îõy /¨Ïî6:¹±ŠÊrµ¤>{]/€VPŸ•#E7À¾¥PvaŸ-Ðáû–|ƒ…} Ìö-…yûò®û|Q Øg'p­°ÂZð˜ïüI0Ÿ=4` 0ßJÞóåƒEæ[Œýó-ÚÁòÆNlа†Êg‘Èg³ãú¼ Ocd>ÿäÆƒùüöc›À>»•û…}vç©7FTíØçÓ bÞýV ]`ŸÝmÜ%`ŸõÒ€t #*ý„}VÙèØgWO °Ï&6×ûd@ì³yLÃC±ˆjì+°Ï®W;°Ï»‰²À>Õ  öÙ\'fëÒןïQ üûC{D~@’ßó bè§B"D?Ã+„:úÝReˆ~f§è; ßö`?Ïm‰¸`¿e€·©F×ëD?/\_ßr ¼Jîk'÷=ï‡}j}6yÃuÄM€(ö5–RØ7$ô€ûªJ9Kì“¢Ä>K‚Îàמ™–)öÙpŽ ò³ZÖ„¤ ¿ç;Ž@}’_·pPlcäg!gßT 3‰}Ï÷÷Â6A~ƒµÒú6KÇü¬œt.B뻂Jðª@Nòrü%ùùÈ‹~ õÙ”Úžk}Ï0…É7ÉO…2H~6çÜTÿnNÙdA~3e&’ŸQv©/×öA~S .D?[¤Å¸£_.<ý¬\!®'¥¾&íŒRßÅbxB?û0’ôbœº%§RíÌ”ÚWnÑ ØO¯ÙÏVh€ÎTûS&¡öÙ‚+~Cµ¯q.øSý‰}‹ƒƒØÏVÆÐö»˜'ö³+–©,Pç­ö)±ð—ƒ8á/+@îÓGTrŸ…å¾ä¾¥|)ÂßÎåê}·æùÔûæ”Òø{¦¬…¨çC•å?BæüYb@ߊKþNØ»âhƒ>TmÜ’Ÿª.‹üž[ ùÙÚ-ÈoÛšúùÙ‘Úȯà³Lôó™;`0ÐÏú¡< ô³MhŽ~]k @?+IY.Ðo§öHô{(ì~£Ÿ§QFƒ“ßÖüFä÷\øþ&?Õ§ù~áð&aÌéA~[é"?« :ù }×@~[“¢Ÿ­Š‚‰~ÏtO Ùo¼Ô¾ý[‚ü6çÚ"¿ÔÁƒü&×ÛE~öYEKŸÉõ&¿ÅB8"¿¢O ÈoçPò³’ߤ)›ÈoÒ‹ˆä·Ÿ×·ägÇC…ÍÉÏâô)î]$kÜ%ßÎÁœäw³VM’D~•ê_`Ÿ­:¢Ø—kJľ!$öµ%™.°ÏV¯1n8÷­¦Ð/¸oɼHÜ÷<¿ä3ˆ}ó–ò{^ªö&?­2ü¤Â ü¬2=~ð³1ü&“>~V.óÐû–ê ü–¦¿‘ äg_wÐ"Àos¾$ð³ZI /€ßÑq€ŸÌį~öæ:üäÆ#ð{î1à×%Œü6§§"?O´þÓ~CzÁOÙ‡¿)êøÙêÕ$æ.“ ¢`†Ï ?;Jhp¿Te~}JYø)Šàg|@Ùo^:°_ªš@?+Ø è·f'ô“ÍC¢­¼‚ý––Ä~² ûÍü د3לì·zdBïSzØOkÏb?)€~m 2~“å?{lV~Òû¨ˆûÚMY–ܧ96¹/CVÄ}†‡ŽÁ}…Îä>‹÷à΃ûVm:`p_¸Ï&xœû¬ð.¸/³È}¶ïˆ„ȸêÂt¡_ÏÁH•oÙXúb½)Žë±ªT¾c4HO Y"½t»'éU®ÖˆôžœõPÚ·ÒTƒ±²­ÊØN~(¡óY²>‚Ôù¬$Ø :ßVàu¾çÃÁhÏîH™ÑŸà½ þ"ï))W¼WnŽà½ú\1 Óà½ú|xæ+¸³Ú·úÜyèoÁ{Í*––‚÷,Ýýb‹Níyª0:9ïÙƒ¸ð^«„t)}žï {Ý“X½¸g~Ñ´gˆÈÈSÈ|7¾:„½n” µ2ŸDzÂ^7ãI°'d>[œ‡´æ2ŸU3Œ?©òÝŸXo«Aԣʧ\ÀÞÑM°Þ3‰Ñ&Áz]%Éz&1b‚N™Ï?sÞà¨wѤ]*_Eõ&WÐN‘4Ò\—é Õy$é\BéÙ¯>©|J¼”ʧÌ$½¡Ûä gs{Ì\zãyQ0ÏèÉ”T’žeRÝ/•Ï¢YÛ‹ô,ÒS’^Õ9e¾¥ekÊ|Øõ"=‹^a4(d¾ç&°—ù´O•ï9U"â:MžEì';Y²S"_*­ùT®\qúdKäË™3E¾dJpž%Ùã¶ó.fÊCä³~q^äôlÝ_ÆuZ½ 4`AU3Éy¶câdpÞœÕÕiš.¶ÄwÄ‚"ªsÞŸ¢:çºàœ7u¸À¼ŒÐ"æM|Áxv>¸p’÷Ä ’÷ô¥"äÙÀQÞ{^a<´½ë–JmOñ1Ñ)É„—B(µ=›Ö¢ î]ô{#áå QD'ooªvÏ6)/uoæåÆËµ2ž ,SÝü“ñªâÈx ëŒè|^TöŒˆÎ­})¤s3B–Œ—×ê^Á´:#:Q<":µ64tPDg¿%"¢sÒB!#:7¡ˆg8ŽÍ5r Ætæ¥"ã¥ZJqok’ϘÎIÇÅtÚTõy!­€< [éï˜Î Ætj@ ä±0½ ¯M s€¼ºé ðqMwMi‹€<³‘ÁÑò2R‘wÑúVœ'«$qž2tÄy.qwB8oCv'çÙKWÑ Â:o.áŠó ðÈy–øCb熧„˜g žhå±¼)ïP‰uú£S^†ç’òJÓòžOm«{¨Éø#Yò |©p_å ˜À×XQ[Ä×éUÈW‘ħúS"¾´¯'ñ1]8‰Ok%Òöž'F!Ê{²^¤¼Wfš…¾çAçBâk ŠmBâ³,;ÄÎ8òu7šˆ¿ãÙîMëi@>§ lÈgB¾á@>‹a<ª†d^"Ÿ…9cz䛞Ÿé-@>ûv z1T5…°ùl6y¤ó­,@|K¯=‰Ï^" 1@>[8æ®GçRØzI|iQ7 Ä×µ Ët>Ù8+od¬)%¾NÞ„Âg¸‚»V|=^Èæ[Œj—Âg¤ôŠí\)t(›oó P6_ýÜi£"ãJ‘Í÷|æpï˜Í—+ÒÎ}‰Dʃė $$>Ë[}Ew®œR0¡oÐN]Ÿ¢Ö%ñ=g΄9H|ÏUì/ð³?J…”ø2xß­5ßøülÕõÏ—…»SâÛ?¿Óùn…¸Qá[Jð#÷e^`Ÿ-&1Â2°o·"0°Ï}´Þ_ŠÇŽ}»Ñ[”Ü·«„ pŸ§ Gô½çÎ÷™BÑ_ù|;µcpßÎ%é{L˜¡¼çƃÖêó†õmÅBPÝ“ /u®zľ]¹ðêÛ™HH}* ì´ÿ@i ì3}j¿ä½ÌÍ–¼wtLyO™OÀ>¤)éòžlàï÷äÛ¥ÈÎ{’÷EŠè—ÖB?æedg—”ôC úË;ôw(u ¿žGÃÈÎöÎç[È ÀN”";oä½”ŸÚ©¤0ÅvJndlg.:Pâ3oâWpgQ('ð/ñ€ø7–Ró€™nFüúð1¸S!4 îÌA•y•ÐwÑÁ*c;—~„ØÎqIÑs…O–Ç©ðéUflçPŽ'¾l¨ðMZxJá{>v¸ÄÄ¿Cþf½c;3ÿ"_WPc;»Ò!BäKež"_=+¸óR/ˆîìW×(ò)ÿM"ß¡ÅAåkMÇ•ï釺T¾Œ…¥Ê—)|ù*oLàŸ „9«Tt'cË…†'Ñ‘Ï2ÛßÑæXö)ºóÚi½!È~ºT`¿•Ø …ïù""Õ ¿°ÙySš¡À—9d?­ƒˆý’pÀ~6õgÆàïÈÖý)ç_ _YÒü<£OñRøêRÞ¾ª,5Ò_ÆÁRá³Ìì Ÿæ‰Røž£¹Èƒ›AÂ8Ew*OŸe}½2úŽ+úÓ½ý¥tHú+ÌÖü)T@ð÷l²^ ßÒRªàÏì#ð+À_ã Tð§;NökUòØïi™GNŸ_làÎʸù”’"ƒâܩՉ|šÑ§È—A¢îLºgpç3?/üËu#‰|G@jw*§SÁ:õ܉çø§§í´5»n?Änì²’_nZû<þlù“Z¦½x>Iøï¿ò»ÜŠÛœ¿û³/ö-vód?ïãï–´Ùø ‚8úRËÑÚŽ¾Ô’}¹ÿùý:sµd_l˾²åè«o掾Ôrô…¶£/µd_!ÿ4ƒg»ÆÏ‰×ç}L*›‡t9:µ4B‹º+r¤úbƒs[Ë}›ëÜö›ý†ñPOƒµ/‹bqëÇóúËϰ=ÓM—έÔUXågOñ÷«#n¢~rvó|V/,‘D?l8;ÊØÓ¹•ºêa§]uúk]i#uul¥®Üú¸Nlxu¥ÔÕ±•ºÚ6¹®ÐðêJ©«c«ãåì¶P¦®Øpv•±«s«ï}¢o[Ç[å¹óÏdjÕO®jý×\Õ¾x¿îªö­ÍØ]û¾îúolöÙTí·v;õ=úŠ©Úw _ûà~ùáÿåW>ÞçV_{M¿ìëWn´Ès«í6ÿÑî÷3ò{m¹ÁµÞq¯ÿãOÕÒ;êúÃøÉ&ñ»ýá¯~ò|ȵÌÔÿó¿=ß%[ÙÓýYñÏó\9 +ûóÓŸ©C»ÚþA?ÿß?y\çUþð·Ï†–羆.ñ;ù_cù°h§ßÎp-áš;ÃÍß4…knè6ÿð?Õ}6VpíÝËüôË?çßé׿Ãî ©Æisé“Qý‰`ÔO‰åÃnëW¨ËifP6öqr]ª¯{w[šBQÐfs¤îkÑ`ë5ÓZHöÅ$`Û¦2µÄ’c·5™ˆ0ÿÝÛ¶é\3(¶úºž–ÁЀ²‹­t3Dn¶‡;7²êŠ‹V¬ô…ènK¨£a5l›ªRTÅË <Ä·U+ѧ—Íq½¶˜SxaŸÆ™m\·¡ÈH-†=ÃÇY Ýã0žÇŸE_ª-< 5+šyZÆÓ¢˳)Ìâ`,BeZK—í¹G&?$V°6f¾8—m³è©Õ.¾t Cp‡ºao>ܾ«{Ä »ó±’ÔŒšìW¤Zó\Õa÷‘_} [uƾ,èY v৆]~h¶”âÛÐå©Ù¬ÃToæ® >3û¢Y‡ÖKSÔÙŠaÛÖï¹Æo‹?ÃB¶è£Wí[õl£õ{»Ü¾ ­^]†v‡*Sè팇3ÂÅWÓ†™zƒÜÍl¦Úµ8‚2ìEv_Ên‹M\«©ö »Z½1–v)Õ¯˜²xñ‰X}°÷õA¢¦ˆ]{yŠbäѸ<ŠÙ© éœî…6, ›TOdzZà€5\#~O¤hwl¸ÎÄZ˳ Ÿ›1üô]#ìwzüó+ùÉLÃæ~OÒXžú÷l³©þmwTñð”¹=4kQdííRÛcLqš‘f3¬xK(Àî…c—b1lÒ|Œ†]­Åî¹pǯ‚ ÍǨØ{Ÿ¹ù&t.°¨K{]Ý÷µG‹­@ø&qž¦¾ÚëÚ&õ7³k±¸ìgÚe™qVÁóî†çÏ2í}mz’lÍÀÞW;ó¸î[f×ksÑÇÖmºm³XùÁ³‘í³üWèa~æñ ´µ({_ÛfÄ—-tV¿^Œ”¶µ;{_í˜CM³EËâÛ¬xv,ˆÅŽXŸÄþbÃÞõx«l °—óù.Ç÷Ø„{][g˜ŠÙÑtt{j‘«Û? O…¥¿4+Vv¬r<Ý0p7¯J5¬VЈ†/ëÅá²3ìeµ£‰/¿•/ó—µ²F‚ž³7±2‰G±1/¶Y¾Ôè·ø X3{[­„A,CY³ÝÏÕ¾}x&Öù‰[i°å7 WÀzžW0–p¼dmRÀq›‡£m2ñ¡° fÿóô"³h[{_Ý›fD‹®Ï—¿#šÄ*˜Ý>^0Ê*˜Ùûjªl<£VÁÌÞ×ë¢7Ò:Ö0cœødÙûj5Èâi»o^}ñfö¾^-€ìiðì áü<½„™½®VvÃ_²¸¯OúÇ×k˜u:‘Ïç5Ìî8¾›tŽ®ðfõ"f¶§ )aÕH]/,Cy 3^sß‹ÃëÂoŒ®ZD½nŒ®õb77F×-Ò‹˜ùèZPòÍ‹˜ÙÛjWÂÏÀŠ˜ùàj*[‰–\íGþ¨{3{Y¯2pRöI­-Zzô3bp½ <@«=T¥cÛX‘v›œ@‹¬eÅàʉ†×1q±®èdÇØê—æö–;ÆVŸ¿ø­³2fö¶š•y4ZþÆpáuÌ.ÖŒ–C«íʯ§U2{^Öçè7é1²z°À-¾Zë€Ï¦ž^bhµ›‰_ÍZmÆÕ£çHöÞѲbhµ_EÇÛ‡Ö8b?ñzûØÚÍ%ÊÛK™-ŸÛ!8¸6›.Çõôߘ=Øô…ˆŸ¤êî5 ÀÛë˜ ¿ð[©6¦ÚLغW¡Å|×'‘þmöBf·÷¯3/df3a{ûjìjúØúü Óp«df÷¹ß‹÷Μ†×{›}ÇTx#ƒ×k™ùTøŽh›j^P—mòtçV¯eæ3áì'¯eæ3áä¯eæ3a+࿲ٲ5@b³Rfö®úE/h±¡µ{xIô2|híVä'v4}dí7?³Õ‚Ï‹]­x/e6Kì)^ç)ÝÂWâU°RfÃ®Ä ³1¯dv¯8ƒ+ª—¬Çy[%³íÇã«dfïj·Pšx ­–ÙÚñ ød š7Umq°VÛ}`}vη×ÌÝJm|bäµÌfœÃŽMYýpâíµºGãÓÕ\›—ýnc¸ë|£ ª` ™K\ 0 n./—¦DAKô -(hÀ<¢àEaP(hªˆ·BA~ m*¿"  ‘-1UÕÁ‚.€Rd`AS9YŒ2XÐZPÀ ,¸;…@²àÖ¤‹,¸!$XðASŠ&`A—=Y•ÍF«nõîQA1X°[±W–\óÑÊ ¥Òû¾Št­4â˃ݢ½Bb v¯#È0Ø­ž|ü»UEÔXÀ ÿ …€»—ö B t¾Þ' :_—Ÿ&_ýW¨¸µb¼ÒD 0Øo‘^À`÷šµÉ‚Ýg@Lú±Çµ[¹1†4ùxõ´\Œä¨°†|ú‚û­y,X°Û¼©ÐÂ,F¬çžÑ”ËG,ßÚy°`¿'m+‚ýÃ3i`×Ö Ù4Ù‡Ë?WŒ^± ® `ÐucˆˆG,úaƒ½Ÿë Án3´}Ò wC¯K YŠLl²&2;†¬M à`ü*¨rbȺkì^ä-:^±´ôo9ÄÈ A?¾sà r0' F/' úyGFXÐ[â• ú)„J,è‡×,èsÆ€u3J,臯YÐÍ%£›ëff#Xð¸á`AÓüÉgF,¸L´©ÄGr ?Fñ¶€ý@t ÃÕâ+ô^ãs ô~â€}*Ü ôÁ2®^€ _¼XÔúWô!.ïÆhµJÄ»×xÌ |Þ'Fv€ý "zK¬N}ꆅ•¡[à@_¹Ñú«‹?à@_Œï#8Ð#<£Áþ«$p`7àÚ'z x28Ð?7ýÁna»7¸ÏÇÖÜ9@°[•°@:çÀüôýÓ(``·Ð_‚aŒ¬^â:`-F§~k‘øtÌ”``·ªŽ`xÇ‹Úø˜}ïñú»%ƒÆü ˜ý½Ÿ¸V°ÊÊ1HÊ­mÓap ·Œƒ}\ˆ-:Öð ``·â•W4ö;ñ20Ðxè-è&8°[Äõ-Áݦcâô}¼.¬œƒûÍe‚ ï+¦’ÁØ&h¬q`Å| Ãhô<0°6ø‚ãFį‚ïAð<ÀkABIÐ&º½1°Ò$zK@‰HðhÁÀZá¿@ôŽÁ^DÁ Ç1¢`ìë#IÐÏ»÷ ¬q3þ‹“s6A ô«yG 1ðŠ<’¤À ‹¤@)ðIûkH‹kø£&Ÿ%VõM¬¤A`%+ ò$VXŠ$ê`È€&ª½°LR!Pç$,KOÔ%Þ‘)ñˆ+jË&ÖÖ„Ÿ'V”O,›ðIÔMRàI,7Y“X›Xa¬ŸXávžÈ©­Ð&ßÁ„$À²¸ °^1J$V,'ê$H€—û&Vˆ+’U“ÍÇNüG<âf‹{2àæc 4î ~ši÷ý’-Ü3 j Í’ã'T'íw¥NÚ'…€“ÙXBÀEÿH!à¤5’pE„€ÚFhÏQ´'= $VmC9°rJ.9ˈ)Náf  -ÿ€Ý€€>ÁÊT$6ζ¤ZúË[lœ£IìÒÖ¨ФZ²I´P„d1Ð6(§èóúyòß!ER 4¯>”ø‚hÙ8!^6¹|‰¶üŒœ¥¯Y?‰V/Å”C ´ žqà°Á|Ðã!,EA-€|1Ðó~îKIáÍapž¡­/1ð²d „ó‡hµ‘—5ð H>¹@î1–,ß<ª—4ÊÖ3‚%¡^{S 9ðZ™Óèràµå 9ÐŽ¦#|ÑõÀë¾²&ôJ`Ô-`·¾ô@;˜õÒ/!õÀ«Ñăz 0L~ Zº¢\¡Úñ z éÑ,¼éF=ðÚt¡£hJ7BÌ‹C9ðâš%åÀk¹m µ@»zúB ¼R™„h hü'à§hëå-¡z\u´@ ´dµ,Hö&V_Hv´'úW!XžJàÕyí¨^ñ­JôWs@ %ðªt?£(õCJàUiË )ÐBÐãi¤hâL\H¶2/¥@“1&”¿ æãqê%r}<Pª¨ÐLÃ,eœ¸q"Ü4šê‘JmNš} µ2$œLµv†È 'ÛL@O¤ ")P«[‰ÔŸÈA'1ðÂÊ­0°‘úÖLé " 4ÜŠ_¥s íC'.Lv‘¡•h¶b± 1°#;àÀ@X¾ ;u’ïÉŽÁÙ‹8°²r %íã‘yÙ“sràs•cJ'ìQ?ùÀÀ 92 e*úœ4pS¡#6ØU%¶FŽ Øáæš Ø/Ò¥Kv'ÆôR Øã)|v´.Ä’C"`ë$("`»©¾íxO1Ða°Fl_N öRyN4·©Âû @2SbࢮG ÔB1pß ´I lÈ„>0ü. D Í°46Œm ‚©i ‚-’°“ †äÀVÈxâ@‚Urà¦ÌHÌ~‚MÒAP*m‚ ¸[x!séàÀ‰÷;9ð"+ 7d< G‚ƒ‘–(H™Y(H}ç@A,)' 2xí@A”wLÔÒP°DžÜ‹†A­˜ !Ap t$A‰ç"AÓí?^ HÒ,œ s‚`çb‚ ÖuM¦¡øk¦q >ÖœôgÁ ¯`PãAÄV‚þ*#EÒlˆ•ÙÂ?.»Á P2ÿ*}Ù„|Æÿl’óV«4KâŸ-R|Jd±"á_E¸žè¯ÒD N\ Ýô`2 €•3 €•Å`(V,LKÿ#ÀKÿ«,n"ýë@©ÿaÑ$å¿Ê=”ÿnÍ´)ÿÙwy¿å¿ç³s”ÿ (ù¯³Æ‘ðO1¹’ÿl¨ £ü§¥ä¿çE¹„ä¿Á2M’ÿ:ÍØ)ÿ &zIþ{¾óíÀ¿C¥“þgÃü'ýoÉöcTWuLé4Ž”þ7*S„ýhGýOçúß%Keèþ+3î”  €ƒ™rû–;Q—¬ÐÏpPÿMz0J™‹ócFyg‰¿¥F}ñ_$¶" £”ÐC µéÙ/õ¿ì— §L)ê"KÌSÔ„R  4àß¡§HÔc PO“$@]dI€ö`|ü)ÀN7*)€eN¨Ú›ýV;+*sžš `§Ë‘ÀNƒv)€Ôw$vÖŠ•¨—Z"`SX'EÀ†5i€•QÒ–R´‚·±sj€fUqÆ‚úÌ´"ö3Æ©vG)2“ `e&I€•YâÒÍdàŒõoGˆOâ¿JOAñ"Ðÿ>±_¡šØÏÈãÍ~×ý‰ý̵@ûY*n Ù¯”w è3 ØÔ#É~ßB±ßµ!ŽŠý.šý,‚£¾Ùï‚ &ÐÏ:ÃOˆ~/D~†?!|’ü, ò³mây%ùY¨H|kH~nôq€Ÿ5ÜgèÓ°#î³ghL‚¢À}{ŠúìÒA€ôYzGÌH }›Ò3¡oo*$ôÍÆnú6—}{a^Kæ³M^È·M!äÛ;žoŸ…æ@ÎñYO1?¢>Û5ø Ôgý@|õm.>Šú6"¯}ö®ôù’ù úìGÁ:€¾­P4BßVd¨Ï6 Y„Ôg÷ Ä&À>kŠû¶â׈}v4Ä>[f@Gbßf^„°Ï¶‰9>±Ï^½˜Uû6ÔÅ}¶¤ß^Üç ¯Ayà>“ÏÉ}’û&¬~voýÏÝ,‚£üöŒpâ¾=EZÁ}¶Åõâ>;˜PrÈ}yÀ?;¼ Ì+R@â^üì`€p¿ÍhŸý*.ÁÏ~5  Æê—4$J€ŸeZ#ü6§Z¿ÍàŸ™J÷ /€ß¶œÐÀÅ ?ë&¶øív„ä>”jô î³-@pà¾ÛpnÊŒ@ædF ~´PdêRfÅ…Rœ˜Æ¥(á`ktø£X Ú)6šˆHdøJª€eª€“±šTŨN¤«I4•·˜å!"t¸h_-pøtÁ©´@Iœœ¶Iª&Bð9¨rTíöÀQ à`ár)€CÎgT¹$š  ¨U àè4Ŧ8XÞŠ`S) €C.ÓÇ| wÃÚP»Êh@4Á¦1P¤TEºR6&,PAµ‰Ôÿ¸¤—ú_Âõ¿„Dê]1«Ôÿ*Ýs¥ÿ Ü(ÿIo–üg¾`XÔÿãe¥ÿuV^¦þÇ„-)€V¤+me%¶Nª¤(YN`CP«ô¿B#1é¶Èû¹”`ei0)€LJ°²~ª@D#¥x±FŽð玲µÀR`Þ%ðâbÃ!=É›>½ÀÍwL¸@Hh94Ÿ‚@Ëg\KA Œô?ƒ@ë™ èý\oœ¬C#œtß”h‰Ío¬L~Î(PX*Kÿã´'ppÈIý æŠYÉtœšº<ùÂ!ÿñ…OùÙ’ÿâ)ÿmœ÷ ‰òŸR¨3 ”Qß’ÿ+Zd(âRþ“`ò_e<§¢@Å4Êúxfæ¾^Q oùoÁ¨\ò_™”)ÿQšÈ(P˜™¥ú‡eÛ#´BeøÇå„#Ïhª…ñ3´Ù€®zÄð ½_(hû †£þWàm•úŸbä¤ÿUd Kÿ»8!•þWIuŠ]1/Iði¹Þ `ÑçÊÄ/)€LIPG,ÐVV½¨”J° (@z)¤X ‘’ "ÿ„‚7¼”9L´ò'o Ð*¨Æ¾¨^j€6|k€é P9¢bAFΤxÄ‚öÍx‹€ÔwR¼ %˜¥(+˜Ñ Ó)fÄ%aðFÕèTáM"à…zh)š%Ìgp#üË«Jð% ÒOãP+„l©€ÏÈñ) ô‚AeÒ S.Ž€Ð‹YT•,£^Ò S>%^(v–0ˆìƒ#ôú8IÐrÛcj€RC¥^!¤Ð¯­ü@ ®ºÝÔõ–¥XeEO¹gJ½m}Üðt”ÃHˆ-§7Ü·—[q›ßç)÷å²%ýÖ>ïãï–ô[k6Z¯¾Ôrô…¶£/µd_nŸ=^g®–ì‹mÙW¶}Ùܳ½úRËÑÚŽ¾Ôò—ö”kö%¶küû<åú×<åÊøôÏÏžrOëøÖ¶acTecôµÇ¢{äé|õù!¶ÇÓØàµ‘º¢aœzJÃ8uÄmØOnÂnÒ.Žýœvqì(·BOçFêJvqêê°‹SWÚŠ]©+ÙÅ©«Ã.N]i+vul¤®d§®»8u¥­ØÕ±ÑñrÂ.Ž]vqù)áVèê÷xÊ5+ÐeÃü¿xÊýº§Ü÷ _ûà~ùáÿåW>ÞçV_{K¿ì뇭٬$^{ÆëBk¶ç[uþòÏÙl¿üùAý‡éÏVÛŸí¹rfáø5_d¿¸` V‡O²ûÚ0±mÕÖ‘_?b4ž.D>-QتUû ÛlÒæåÛ[¢pRßLPy&¥Wˆ,ˆ­{ÜðÊÍØ|¢ßš­ªíXÿ÷ùÜsŠ5&ÖÌInf2Õ.æ×§esŠ÷\º«¢çqõ5SøýÏqý ††³jØÕ÷+Q[>èž-ûŠ…œ?W¬WMm`Zf‰˜{Ÿ¶~ùrŒ‡¹ûÄìiñ•gF÷ÓéÅe©°¥öCéՙߗ’{tè;JGrÝÓâ€0lÑ{DKÄ«ңçç“7|›”Òº-¨Ýa:äÓѧţ,‡!aÜ‚¾Ü…gØòõˆm¶—wµ"÷YåßÕÍC¾=†mT®ƒZv¸ÍéŠzÑDs¯ªLÛ k¦aeô3MÇïáb¿²rŒ0÷ŠgzÖþUv;ü¬¦§†ç•_¾Ù='È}±|šÖfäñºs–£a³*1î_µ6&2˜‡˜óÚóM÷ÂËÃÖ¸[l³<“hô µtšÕ™2OœFý¾Yá¶ËÁî‚}­ËsýüWñNYµ·›+Xgo^=Ü·1j7óßîXËgÉ|¹m}Ùì«ãGÍKŸ { œo›Õ]°ãcT3ç~[^î\¥lQ{t®5¯s`›td?WÉþ¼°ÒÝìóf/k¯ˆ¹o+ʾ>Û4<6^K|F'~$(ž2ìe‹ï†¾°—µcݵYEåG C—f!ˆe…÷]œùQÚ»ÚÅÒv÷°w+sÐj&áÙ«j°¯˜Kxv¡¾Ñv<…Ï®íß<#Í6©Ðø›­54¿ ƒGcö€ÖKÁ‡Ãâ-ªo²ð4Z¬‡’eÛhðh•abE\_ì*±ï8<,ü=OÈÕÐ+HÅÔràøŠ>:#𽂔;ÍXvx){Uí›ߟ;ªÉÎõ /"eïª ,ØW”íòmâ³ê–;î&ú¹K¼«%v½ˆ”¿«7ʺ%–ø»z#fÆ‹HÃÔÎkHù»jêĈ–íï*…/!eïj%RY )yÍíèw\ñ®¼òÝTw†\00ó"Rö®VF¬wKÌqgÈÕ_¼†”½ª•k‚ÝŸìUµOº?^Cª¯ðšóÐkH¹×\à/!eoªÙÈùÛì%¤¶m21¨Z ©°š³è¬øUóAu”çÊnã‘í» ¶Á‹H¹×ÜëØÝL7Kä;8–`ÙaÇtÅŽÖ^¡+~±0¬Þð-ðúQ1¬"#ÊëGÙ›ZðñúQö¦~h¬~†ÕXãôR>ª¸<<˜UmOwü¨Æ¨z1{§×£ªÝ¿+~ÕcTµy¦û^@êvé÷½µRö®zZŸŸ¶²wõ²àèègŨj‚y<5VBjGº[Üã\ âÚ•WZ‘·æRewãÎyU¾˜å¤&2ëZbXUŽœȬóñÆ HÝp÷‹†£êÅ(¯µW\_0´úQþªšI`ÜK®B±E½án–î3‡3¯ 5=÷)çÝ^6‚bø¼„”½©cYz¿bT5׿I^C y›>{ðR7R;}öå%¤úGf z©í› ÖÎ*H…h;°àê5¤(ÚÆW¥¨}gd/"51õ«±óÈÏM‰Ö‹H¹ÓçlÏ·=FUååz©¾BÆ-±÷;FÕ ?^EªíØdFKñ Óq1ÌÙªHA´Åz€×‘Zš|´˜uÃ’§e^HÊUÛ†êÖ} V]«Ñêmâ_ð>&ÔÍø¬Y)YíUŠ V «¦¤ÄÃfU¤|ÜPÅ׫Hm˜Çžç㪧Öh‰Õ.V\>ƒ2])Úz©Y㡈;>[Œ¬–èlu¤dðx9­ŽÔí^ˆP輎TÇÕŠO±Õ‘Ú°…ŒÐj·l¼À^ÔõÃëãôhØ=–é䕤\®FRzŸ®‹Öà«åJ»}œièåH‰Õï3eKþóЛÿáUKþ[H0Oþc>oòŸ­xÇ6@9v måc´øúÀ‚RÓ €ë€•ÓA ‰¯= ¸;ªp M|Y8ÐÉ$ƒ-ÎÕ*1à­zìeM‚}ÑE/úÚ}LŒÀ€O +2 /¢ÇŽÁ€‘Žs$¦I!PéBd@—&ã&`²ëë@Ë,Èc'Ð…Ú¸`@WjÁ€ž#W èù Ç`À̤ FFƇ0}ʈ€žIÐåè™`® À~3f‘ø´Àù•6eI€®ÂÇíú¡ÄC {©µ @wI¸OÔê+ ÐÝBñ£ @wãl'zžpP Э_ƒ°@€u4 …C 0aŒU.šH^/f‡ /¦À -ø%Ö€žüì׆xÑìDx1ÇIhA±@Ô$Bx k€úW+F_ ÿ(æh€™!Cô/R N ôh`ÐCqjpZ`Ø(ů#±æ@‹ÅùHü‹šØ ðÏG…˜ÿ2WŸø‡b„‰žt·þeâñÏäAÄ?䞃ý"á XS¥à/C‚$wÞšOü¥­áÏctJü$àÏÃ(ö .vCoŒ§ÆÀ¤?>Û‰‘ HV9 XÅ€J‹xâ_&Ïÿ|­¹œøç=_jƒ'ñÏc„^øçs€˜þ…çÛGÒ_ EË#ªÅ']Q-p!èªùVõ“þ¼åŽm*†T&“þÂô+zîR9ÿ2¸‡ø—q:Ä?Ÿê,Ð^‘qÕîxQëõ‘ðw^ÀŸŸf<$€¿Èy‚¿0©úHöËP°Ÿ'®ÄÅûyðȈnƒý<ìÜ9²Ÿï(z°ßÙìgñ. ~øƒøeÔ9ÁÏ#-0´D¹/¢Ž’. ¦,~Qš4ø,À/CP~ÞrŸàçÏH<?OLêh~~Ä忬‰nލ ð;N àçBÍ-~þ«v‚_†Œü< ,0àçÛ%ü2àçùpñ,üLÂs¥’þôœô'5RôǼú¤¿x³Ä¿›?ñ™f‰G ƪ±ÈmÄ?&p$ÿ1Ý$ùop/þc¢8ù/½‚ɾ/Ò†+†€ƒÿžMPƒèóWpš ³10­c¼²0êàÊ@ï˜60^M”ð&ú¯b* Þ‡&ˆ!‹‰Œ@o ycÈš|í€ÇÆ#ø@:týšÆªð8 ßõ¸Ê€çÎýÔ×!zC ÛĈE¯|ç?ÿóíaÄbþùÏïvscÄ¢=3ùÏÏ1ž$ð_†‘“ÿløKÃÂ_PFÈrÕù  Ã‰ðw¼Ï࿈ÌmÈ}Oƒÿü}#‚ÿ8çNþë%FOð_ø>_‘ÿÊ'ÿÑä*ùÌåä?áY| Ì>HøƒÛlÂ_E~Â]Lþ,Œ)p•ðWàó˜ðGû"Áßf9Á_A\CÂ_C þ |Ùþ°¸“ì§U_±òîý®HlJò3A+0Žäg•ézXP}o¼áa¿‚?O™²#üyÉ߃þ6“þ4½ý]øÂ'ýiÊEÔ ¨9ùïjÄ;òŸx%øeuÄöˆâØÄÈùÿYøs\_òŸ·“ÿlv±ü·é:šü§+LþÛ7LÚÄŒÖþí;òÄ’þX}Iôg—! ˆôgýƶ®'øÛ,ê#úÛôø$ýåI’þìFx’þ6ë!ˆþìxãBþÌmdúÛ’Iv8ÀÁP7W›5W‰„?»Ám„?ë8€ü·Y Hü·YBü—SpðŸý(O Œ/ {À}ŸÊŸ÷ÄøÛ\3ü)[Xð'«ñ_^òŸÏÚãøÁn þÛŒYÊÂAhßï€2ð_.…ÿÜÊâÅrçÿÑ—"ñž Ä?ˆþmÖtü³?/¨|& •P üÛþ ô·iK,ú³ã_`=ÐßBÞ²èÏû 2ÒßZøì‘þ´+Ÿ5@­üÙÎÑÀ~ÖËUb¿Íø†d¿Kô£6Fô£‡†ÈÏÖI~æ†r­ÈO7Vèggä{úÑ-:ÑZÉo¸¯%îù²ï‰{LæîÙùÅðKÜÛšh÷l¿÷Kês‹@9Æz.޶Òú´\,­o!=?µ¾…%°#ØóÂzÄ$ë J&ë±ZOÂÞŠ(±oÿ|F{f"ù ÷Àiä=ºO'ïÑã#y¯cb™¼÷ƒ„vRíã´KÀWQå+Õ>dübß…Y¸Ô>s'ï1 y!ʉ{~ìÜc}™Ôû¬ïìÙU/y9½À= ;)÷ î€{¾DðÂ=Û1NHrŸ¢+)÷UÔôL¹e÷ŠrßsÓãÂHà!÷!Æ:Q)÷A{”Ö'ÝŽZ_å„ZŸ™ıb_ìZ_jkÔúÊüù{*ÓR_AÈó!õ@º`uãSê{†­¸ ’ú ʨ¥ÔÇ\ìC꫌ëÄxú\ù˜OKé+—Sì+‡C±ïZ$9‰}X‹L±øCíã" `ÏæÅz)þœ¸†”؇”ýCìãjOŠ}Á¾©÷a¹'å>Ä9¥ÜWÆ;Îóø徫Rq£Ü— å>Úr_¶`@…OVª}ÞZ½ãGPûh8™j- ö1?Õ¾§!§‡Ú7%Õ>\§Ø‡L¸w_XÀ>ľMù¸gë))öÁuåû6cC%öM=¤Ø·ˆw>»Qí%öé&ðYÇãòÕ‰œ‹üŒèË`¿qq¥Šì7 }[É~£HZ öÅÂßÏ8Oÿ‚L#ׯÐnN¹~…•Y#×Ï¡"×ÏNbŽÄ\?3+y¥ú-ò3Õ¯Ü8È\¿YvÈõ«Ê«b®_Å·L©~ÕOôSø”ò×™9¨”¿>!é1ãI¡Êø³“=1ã¯À;3þ:ü 2ãOË!Êø‹þœ0¥üÙ»u‚ ï=ÄL¥üÑWV)¬Y™)´Ê2/)Sþ,ã3å¯-ò$Sþ÷«”?~¸2å¯TªzLùËôB¦üµÆœD¦ü1ª,SþX€9Sþ†‡Ìù³ôá“=í:C?=‹ L£ Ø+å^mÉ‚÷dÔæPEGò(X ) Ð8Rþ¸B£”?û¢|$ zBDHfüÑ513þÌöï#Q0+ùeÂ]ã2á¯^88%ü1M&þ¸æ”ù~0Ì|?Nº“7¢[2ßïb¨òý14PЉûÿü}a óý ”½%žÇLøc2©œ£È0‡íÚ3g½ßÎ7Ó F×áµÃ–Ó>íÛ¿Ë­¸Íï³]ûrÙ’–dŸ÷ñ÷GKZ’ si¯¾Ôrô…¶£/µd_Ó,«ËëÌÕ’}±-ûÊ–£¯ñìK-G_h;úRË_ÚvmMØ5þªíZù¶=ÚgÛµ¯ø§ýEl×¾öX»¯ýÖn篾N_º¯}ψðµïî—ßÿ_~å~nõµ—õ˾~Ø}Í|M×3tÕ}í¹ÿ#ÿù·òFû- ¶—‘Ú?þdïýúß?hÆv4þÝ7¸_÷emù(àÆlÏ䂯“_wÄv¹÷’‰06®8ó>-½Å\”ÖŠ$ŸÈ<“!wŸž)_‰»6b…Â}ˆŠWÁGlt[{óš*°ïr¤«¹ðn!ÔÄ8âWc«Bdl2çÏ.ÁÑ<<»ŒŒ#¶ð™Op¼yvX sÁgt«´ëì…cž)jC 3jDŽ«mdNãý§eG}+ç u “}QcøHév/0£{tëÓôž§eDz5¡1Æc’ÊÓaíÁä>Sæ+Öµ60äiÙ>õ.,ã4ƶ–œËTcÜfïë ´>{óºba«!ŽéiÁ2ˆÃᘑÿæK­qõf­± }ƒµžƒsõa”èsǧeùܻѸ{Ìpvwó³Û ·Žvc³¸Ä3ByFë¨:ò´øg4Ž c†‹ÄÃP±Æ´x;[X]€ƒ§Å}7žÏªeŽy»øóÈG¬çêuçds-ó-Vq!=ÍÆž÷a~ZPâ¡ëÐÐÝ?ÙpZcò=lTFx~Å3¼úíf§”‰Ÿi‡¹ýT\‰5{Œæ6àç½V «êa/©U±iÅï +,Êï/Öt]/˜tþºÚg¦EËŠ×u@Gî=0cµxG‹A9Ö}§­ëÕkþ¸M[èY%–Àc“1 ò¹‡¾P7¯°=¶¶6c›3=Ó°|½l^€ê‚FÜ=¬¬füy»Û’+;~b‹nwHc¾B9­¾Sú«ß¹é^^÷y0^ß ²ˆ‡ÚO[óôcÁmš^ài„ÄàïÝ4·2;kÍM/ð4ÃÓu’iž| š¦œÓ <Íø\_q4«GéV˜Ÿ^àÉvÎtâé*@ θw^ài…[X\>Sèìe½ø©^àiÇ€‡lž ÖTg´Ô¥{84L{æ}Y‹†&Ó <¡ž“‡&L/ðä5Œ0Oó–CC‹ÏëZ¬=:ýEùðº7¾R3køBúbúÝZYflÖ›cëP¯/Gu´`leåÎÙ WfÏËEn±êGcõn,Õ”hبÝGŽiå6VUgü(ÖAÝ7cůL¤nÑOŽ×wºci8fÅÈz1†`z}'wÅ€åÅôO#~„û’ÃC¦xÂʘ§#ápc™zz'ãHúfLs}Ü(5ãÕôO3ZJlÓk€‘ãôúN+6éhYá@pz}'¿œð_™†A^[€‘æÓ Y+B 3½nzy'\O´D¬zØ:DÏÝUÛôyÊ\1;Jï’éõ>^ßÉ/|Ö¦xòm.áʺŽïºÛy…½¼‚¿Z–Jùž½º\D¢«î´‘Ýf¯î4VZ4,TíÙx\}ñʼnühÍ^l¼&®ƒÖšXdë{­ÙôÑø…€³J! KÈ$n( BÀÅ%! ab`„Å@/ ㉀´bK¬›àHD̪póq"ÊvMh¥K|N€&]ƒ÷@€6¹qtA€«³i `¢!zÝ Â LŸ52`±Í5 S4>%z<´Ç“ý›¹¢ç`À v#fý02`81ÅÞÁ€ß>2 oÝš€B¼Z@XHˆÿ]qX„?sDø»è-ø3ßÑú‚¿káEü],Å,ø»˜p'ø+tPüÙlo¼àÏf{3Žðw1JDðWžÆ7!üYÁ©ý¢¿Âšé¢¿ÂÊ뢿< ô³É_‹ ŸMAZýl&{èýlîˆDô+;ÌE~ „ù°Šü ÝòE~P˜äW˜„)ò+ºÀ$?›TÆ3Oòó(´ CŸ…A °`_¥ÑˆÈ¯0IDäguWì+ȯ0ž^èWžîâIú|RE~…åƒD~…ö¡"?‹#ˆ%’_IÒùÙ3—‹äWhv!ò³žÁy ¿ÂYªÈ¯ ƒZàWà (î³ùz\,r_á î+ô£÷•¤Åà¾Â€Zq_¡“¸ÍÄ}%¦Ï„¾B/„>F• ú.a ú.j€‚>;X` ¨ïÂ÷DÐ猛ú,F$&‚>ºë%ô]ˆBHî{®7vî3¯ä+ð ÜwñÁ÷™«pL Ä} ã ÷]öÑwXÔÇÙ=¡ïb¨” ïÒ›Ðg–Â%~E裿† ïZ°¸ô]Ì,ô]–tLEècfB½ûú:‘XÐ7°VÐgþ-~„‚¾Šµ¼„>.Ÿ úrBsZ}ôALè£OcB_¹±Ä è+CMèc²„>†µ'ô]ÛúXÉœÔç#vL&ï '¨Ï¹ -ƒ)뙑úܾ3&@}n?xRŸW3õÑŸšÔ×oú:õ9x­7õ­(ݘз&Nз"1#™O˜Ïb3£_2Ÿ•ñCôÙü(vEècfcBóÍú&j&ô ¬ü$ó¢,™o,̲Å|–¾øFæcX2_¬9ø„…¾ÞH‰¾Æ«)àc‘ç¾ç ]oàk|yøÉw0_Ák(æcQË„¾ …âúZ€&ô!ù%¡¹% }eàx} lä>.î&÷ÕÏ‚¸Q¾÷Åž}Ï[…A_%LúèoÔG;½ƒú"8ü€>dÝ$ôYlT ¡Oë7 }„ß„>õ#èC>gBßó!ˆ]BÞ1æCeÖd¾<1ÝÈ|¨g™ÌÇ,¡d>:&ô5Ęÿ*ôÁ˜1©¯¢ÐA}üÆ ûx–¢>†@ý€/›ÀoGaÏü šjÄáüdì"ðSž¤ÀOÖ”?UûøYÔm ø¹ RÀÏ–bÖNð»%âüÌ6VÃ¥ýmÜD‰§SücJ³Ä¿ŠJôó`³€/‰Ì®Kõo.JiTÿœ(¥þ¾(’ÿ ß}É…îY)ÿÁj(Õ¿«ñTÿ,„58ê_e@œÔ?_Œ¬ùÕgç5úúWD,õo ¢9Õ¿¾)¯¹ú§ë)õÏŽ6)A©þM¹Rÿ$äJýëHKIõÁð©þ­ñzÀŽô®ÿì#‡þë´•ÿu Šÿº½S!¦=7&„<Ê)V)ÿÕ\"ZRK,„PþËŽ)ÿ=sͯ(ÿÍpXŽ«°ª«Ië ´G¬Ä6TÿV„ -$s¼Å¿{Iê R‰€ƒ ´HÎ* eØÄ p±¤ýí‹`ìô ;´?¤-=ç*T; ejÅJÐJØ„nKl‚%"`k…\ lŒó¶g+!`ã’®°!‰YبˆˆM޾^Ø$Þ­ò|ivVÁ¨dÀF?Z1`C-! ÄÉ@ÀF{O! í)–Š+Y„€áá¢ÀFï3Q éòí%ý5ÍHá­¢ÀvUªx @k©Ñ30°%)í @?ÀÀÊða`e2“0°ÒþBXY–Xi*# TV™0ЂæÏ‚+g…•Ë ©þa92Õ¿ÝyTÿ¼5Sý“¾EôÜ–·ú×&{¦ú×:0Fêßµ> F˜Á½¥¼—Y¤&A^% ‚šõ Y«L (á3A+éAæ¤ ˆì’Ãtøà@”_88%ïÄT„èHw¿9+Î’‚{’ ‚»ýüæÀu|aà&>$RNM¼xä@=:âÀç“–½±À"8ðMÀtAú×$ZE¾øÕA‚¡—‹ꮿH°€û@‚#›VqÄ6ù€Ô¤/êÁÈ‘Jì¨â— Øá— §Ùä@fÌÏ ¡`GU›>&ÒþPÙóÐþ Õ@¢ „rq  Ê& RÚ ¶0EK¬“ûN*{ÁAì#6j°ÁÖ±zê9%@”;@0†lq`C¥œä@AQ°Á³-QÐR9Þú‰#õ?ª¿"A ABÁÊ@ ¡ v%¤-Æ‚¨’(X7N(ȤÔÿ`Dr  ´–dA¤?% J` êK'd°P€(Èù÷‚\. * B(H¬H|zÞh! „)5' Äæ$ "â7|ÚÿÂ.àÄ?¾q¿ÍJfÂ?󋉴B?7CŸ„ U$þ±´lâ‹4&þYÀèÇIµc²(úc1˜¤?+¿bèç h¡ŸÁ@¤¿vcêªÐOZÊJø³D`u?æø¥îw´@÷kR û£ä&zj¡Ÿ7ÃCúI2ÎÐO|$2ôÓª}FÇ ýÄb†~®ÁmþŠBÛ,ƒðWvgX'á¯H dè§Å;õþ*¯Ù¯úGé@?‹H A™èWùúU† ý*¹Å~Õð0ŽìW­²^ (ØÏ,$B²%ûUJb?ËzD„&د>z±Ÿ[Q¼Ø¯2¯—ìWYÈAìçsâSÿSå^Á_c@êŒÌü5šß þWD y”‚¿wŽäמcŒC!ùÙ|'ž{’_£¶ÐϦMë%þY"'ð è×8+ȰOÖzHôS@3Ã>©“)ì³ p<Ã>Y2,Ã>¯¯Â>iÜ”aŸ éÍGØ'Ln°OŒºöÉ8’ ûl…Á¢ÿ—„öù¼ ñ‰RØçó¥[/ùÏìûöÉzö™Á¢ ûd5b…}2«2Ã>;u¯`?[@F'Â>Yü)Ã>9K úÕ/ЯJÈ!ú™³À|¡Ÿ]ôXd&úéÆýªf¡ßE‘äwÁÌ!@š±$ù]ƒ+ð³Su#ù1J;ɾLGàç3ðóy¸z üä2aJ€ðwHôcBv¢­¥ýèË“ èAàî1©JE’h9ËRÔÇÆ™ ý *ÑB ðb ѯ+\”èÇ`Gà'>/D?—’‚A~ôá&ùùâì<$@OyŽ©!ÈÏ…0„†nŒ«tá'ú9Ý'úEÇI~Q®ïT³dB’õ$?fÜ'ùÑB?ÉoðÉú™û=Hì÷´Ô3ð3]Q“ýPR>ѯaOC̺¥ÞðV‘èJo p þXj€æ0ÛPÜp(J ðžˆ>²D8гƒbŠ€ã¦ lº-ä@[„Å‚ØèkDl¬ù"lŠŽult?¶‡¥ö+°Ý¨÷(´c .4@°³ø¤HЬOÞ)€%iD‚}*M" BuI‚i "A­6âB¡>:¤L @x Ž Áë"Á‘©y ÁA?ÑC$胇¦ë$ÁÁ¸t’à mKÊ€­#& 8èW“* Rf ‚nR÷ÊL÷ š§Jh‡’>Á)š$Ep¢pê€5]SäLL0hGˆˆRê€ôò Ú§‘  š¢AKg`×% þöÞeg›ÙÖêss­“LçÁö @ ¤º4v!¶÷/1áü欪YÅìÆîTÍÏ¿ÓyxóàÇ#bÄ­ ÓàÝ~&V†©hð–C¡ið>©*¼Ï¡RÒà}¾|ÐDƒw±iðöº—h0¶"‹’cº‡a ëį%¼å‹j ÍûÝ“£'!%P¼ ÁëUæŒhðö ÞJ`…dJ œ|)c+è;ÂÁÛKáà½^ŽÌÞ“8”;a%б’ÂÁèƒ)žx𒡘y0ä×þUIb%PÕñ¶D@…Á•ÈUËâAåš× ƒ¿º^L˜N ­³Ÿ‡Ûˆµ ²ÑàùSü‰‚C±ªBA«B…‚‡B)…‚%»9ξ Þ¸ÓŠ›PË$¸6VŸHðü¦&ŽQL$ ª~i‰€NÔ‘¨U¯BÁI¿®BAFÝPParFA­?X‰ybÁgŠóÄ‚2¬/dሠOQ§QP3≔FÁ.\ ÖVBÁhüÊ€Oûzó^ †Ý˜I,¸µ÷*/»bAÇ8šõâ׎‚23 Z3 Ê”¡P¡_^N“ sáL‚4+ [¬/ÆÚô1 õ1ƒ ¬ å[f\]ÈkAIÅAyªxz óÆ ‚®46=ˆª@èAÅW”xs’o4J—(…§BYÎc e¦Ñê>mÔ²‹ûÏ€Ðß'JQ ªjêJ[øMd©-&tŠ):~*JÍÙ‚B»pL0x*¶Ã0Xùƒ†AœØ”@âVP¨ÒÕ ƒJ*%ÐË †Á“溃n*)°2'Ch±¬Z™€Ô Oç—¨5K²%/<›$EIÒVŠ$*t¢²…@íæÙÖ#Æëã—3"xb÷¶bÃî¼ö7·ªNêò¯¶õ˜ñŒ}ÕRffj+ã j)3³‘.ÕŸƒuK¥¶«Z¶±rÕåsÞlØFBÓ6þ£ Ö"ÕòŠk²¬ýô|ú{¦iƒ­Ïë¿ûÏ3<6Z™±­Öö'6ƒãÐkÇ¡ßß2ýëùnõãæ‹kSúO$5T.jG]4LõÐ(å ¦av5ŽS8ÐÞÇ#Ù?Í#mþiÉ4ÒÖÇ#Ù=Í#mîiÉ4ÒÖÇ#Ù;Í#mÞiÉ4ÒÖ§žc9§i¤Ý9Í¿:q¤Å]-¬¸ÇñüWwµä®ö'ÞÝùÝ{ø^ÕùÇóçëûÎßôO;«Å'y,"üÿÏYm½¯þÈYm5¯1bÐ?/ÊÿtþÝ÷ÜßtVëÏ™©±™ ÎÏ p6(!ý ò µ>£WúÇÜCõMús?(ý¨jÁýAy¬{¨†EÅ—}´z²Zz¤ØÔã säpZËŧþdnqV&œh˜Ù[Ök«¥gmÓˆlÛ«/ÒGÈr—û‹Z.ÙÒØ’YÌY6'õý% @ë™-×M£ŒRHQ¼«Ò–V >Ú1½L|íïÓi”Aéï{3TŽ‘¸}=]A åŒ±Z&Cå^áxé•Á’§ýiQVEÅÖ¬ðÄ9Zæo*Ûž‡ÓÏ÷7öNÊXÊýÍS¸Mü ´ÄŽÕ2 ´œ÷Ö ¬F?±ï''ü©š&@ôþž¨z3˜ ´Z¦ÈƒÕ&zÕ±ü汬P;o0<»š'Ó‰•=VüÓÔ&V¬r˜«cƒœž[ó¢W×Aúhù½Hº¿±2ÅÒ8(gÚkß´]ÆÑ ø¶çÒþ}]j: %ʬ†Krü´ã}‡,ÅjM¹.ä!_8¬qÀ+ –1d¬ d¦|õ¨5œYÈXèZ-¡8eòúä%„ö¸Ÿ†k"Eô‘eY$¼/ì .°vdbmÓVwfX®Vè±JYÈ­~z¬ ´ C.Uô¬/I§{ŽÓ,;Åš7Ž9Œ³¢‹+=£^m U¶·Ì¤™M“%IŒ›Î ¥BÆ‹p‚\»a‘†äº_Çc¹Œç8WÇÊÓ``éHûü¼^Oþ¶#. ÂÏi}5xzþfÛ™ak Ž8.DŸ3ÛqD჌>, ?¢÷•yÝ úã7‰\y¢w܈œtF¾c›H—‡_Õ¾quŒ´xÐ¥½u˜§2"¬‰]LÆç}"ú|ÝR¹²<¢$Åq"í|¢Ïó¢ÜÇA;&/V.ÒŒŒ´K³Šæý_éö#KéÐO/ë¡äµê¹Z4"^æÌ. Òm”ÎSëyh93)8ƒóõ¹¾žÑκy£¡RdF. æ•zyŠQ»iÂq·C–nzíò`?–O%6zLâNŠ]#æÒ/@¾#k7QFÕŠâMi롵ª‘Å›zù(Œ f™%—OóÈÚM4ÒÌ/Ôˆô”ô 8±Ð7²tÓ€9HC—+o§,š‘+Ñ#K7ÍÍ`dé¦á•}žŽ²¼†ÉYùÈòM/l2p†æpñŠæ·gdù¦ŸŒ}®ÆD:œŠpŸXÇÎãîl›x9²~S¿bJã¸ß†G5T ¶Ì,Ë?D~¬ÇR'y<g1ò“š"è…³@¶`ºUpïñ¼ýÊJ.¹>„Fd ÞQQÁ©mv # 8½øðô¦ž–‰5ÌYÀ‰QZ¸‘Ÿ;?©iäñ .iÏ×±Õ3 ÀFxd6¼/UÕtQ¿)žÖX÷ÇeÏúMìƒËõ›z:¢ºÙÈòMqµ"ï,‡‰òMïµ…ž,ß”Ÿ=zY¾)ÃyYgadý¦ mÏ^ÖoÊ€5½œ£€ÓDFn¦¬ß”]èè5¢~S>° LGÖoJƒY¿#ê7õÝÍpdý&ÖÃ2QÔoÊöapÜxKü¾ëzFBä«!ůÕ0ö ¢tÓÂ#•›&ðr*4¢rS\(ÔˆžU…æ¥ ÕmŠóÄNcvŒë†ßUe›| EÙ&°â yÏ¡ÜDü™¥ÚóªâT׬áWæ=-%RôÁý›&Ô}Œ02)>ãDÕ0ó°ï+†#ª55Ä9âÒ q±wD­¦sK;ƒ¾Aë;ñô-¤`D™¦™6j°‹Ûi€Àv *°SµÁN‰™EvŠz3Ù…qºˆìÂ]Hv­q×&;IƒEvª¡[d'I§È޵„ vÁ ðG°Ì›2× ¥V™ë†|—ÌuC%åÍuC9eæºõ¥¨b®7ËHšë"ÜsrqÝú"ðÌÉuCy¤æº¡Ô9q]¸" ¹n½“ñI4× Õõ6×År<(B\—*)\7¨ÙëÖF¿6¦ªñn¦‹ A¦rÈÓÝÁK€E1]¼˜nHiÓe˹3Ýjé\œÍÖiÏ(¦Û;$Ô¥Uû`C~~2[;Öe ±nuá=D°[ M°«œ#]ö¹@@»ÕBS`—gÔR»Õ§óg#إ㠒`—ÙLØ;Á.·Bp]v9Ð\—ç€KN®»×ûRƒë²… ™\— ù×áâl\·ÆÅñêâOÎe uyüyÛ êòZå¡ê²Á P—Wß'B]ÕbÔeŸ‰}êò sï ººzº¼ b]öyѬË>˜në²_Cb]±(¹»ÊÏ ¹.…›-ó7žÃ ú×å/‡£!×U£¸®ÅuÙßMr]¶LP¸.GÆw‘\wž írä±£]?üÞírdÌVÈvÑ<¨rúØe 1`—-8ñ†å6 ìö vÙŸ\‚]¶Úv÷U À.×ñ@[»ìƒC×mgH®Ëð[\r]n´×a\¸n;Gr]FÅž`¿Æ•ÒÙÕ`‡¨X´Üü N~5vû8;ÄÛbﻌN>6°«@^]v¹6°Ë}cFB°C˜v¶ì*îX`—aÙD"€]Ea 쪀¸Àå£_´p­4 [»Ü èN°«˜kÞH8€]^/L’vµš+°ËXi¼Nv|&×e¼”ÈuÛÕ×m—˜\—Ìx~ÈužÇK¬Ã( ¯›+¥>b]þTàbݾ«—_ÕÉš¢âºÜ9v¬Û. ±®\^ÅuG6ë*2_\Waöâ:Ü9`?p®Cþ,¶J®Ûîlr]vÁÝO®Û‡×eKÎ~ÄuA/®«q]ŽŒë°'àPþÎ9VK:J ëNÖU±.ïNr^b]^K¬¥ë*¼ƒX·ÝâÀºŒ•ÀÅÖUÍpb]Ž10FWÆCþ•TWÆ]Iu•VAª« R]5žP]öÀʨ.ÏoQP̲òï ¡J2ï Ô¥îP·ÕxúÌA¨Ë póê`»Æ†ùã}úu¾‚7 ®ÊÂê²GÛ .{à÷Ô!ê uy``{@]ö¸Iyz‰æNuqõò¯$ºíÁÑájñ†®e߈.'— tiú¾G@tûQC°ôsýO˜¡êÖ/Þ=Ìà`hSÒjJ­SÖ…¡nrýÑL7Ob0ÓM™4‰é¦\}ÌtS+bº)³Z3£ÕÄt6f7Óeè2`ŒLg93ÝÖ§é tŠ¥Ö)G´Ô:-è–ZEqíbv¹‹uZû,±."­‡ëTÞ¶Ä:9¾—X'“úëN®0X¬SÎY‰u )³Xw²ú@‰u¦d‹uŠ +±.Öf±•ĺSª©Åº0¨þµkuà uôr(NKš%Ô\1ÔÙ评º“VÓ%Ôµ&B#ÔÙ%ÂP-PÇÅûêDB]´t søöœ‘^P—˜Ø©ÎFý¦º¸gú®×¡åƒui ±ëuÛý)¬«ÃÖÅÛØ¬‹­  ël@b¬‹‹Ž«%¬ËøÙ_ÖÙ‘ÄX—Ɔ»\—»ê„¸ƒ*S2…u1 ÕCbÃQ…uS|&;b²›²Q2Ù9¢Ödã¼d½ÉGuH2#ÙÙ;Æd— W²³ñ©Én^æ8’ÝôšºÈNu vö½4ØE æ“;[¤ìüSìb#vØ9ŒÙ`‡G¡`·õ!ع ‚Án*£Ä`W—T`7µf°›Jù6ØÅ…5P™ v¾8⺼¡“ílïi´³«ÑÎ3@»©ÍF»©‚ÑB»ƒ ÑÎ.:F»ØóýA;§íò´³h7å|h´ÛN€hWG#¶³™‘Ùn*Ãl8ÙÒù´—ØÎÊØ.o`d;› ™í¢eì¢öŽ­ÀvÙ8*¶“Å»ÙN¿¥ÑNf…vzwÚy£]£Ý¥Õ£Œ íô:)´óí¬D íââà‡ÚÅV8œ®(#²ó/c²»hdm´Sà¡»ítµDvuÿ™ì@ í”_hÇ׳ÉnÊâ±ÈN/c“Ý6 ÉΕ võHídôQhwœCí˜ÚZdç›ßdwâA‘Ò ÿZdstü.";åïÙÅÛåKv~›ì$Uìü–7Øù¾1ة޻ÉN%×MvídüP¿#ÙùÙÉù×dç«"²k, e²k\ã4Ùù“E²Û6yýEeÎ¥ªñA;)D;?CB;榘ìü)ÙE–Ц×m·¬ÈÎoo¡_³B;Ÿ—ÐÎ/ ]“†%´óKXhç\hg™]hçÐÎ’ÐÎ\¡]cÄžÑN†áF»VòÜ©Ë]dg1Ùiþe¸k‡Øp§¹–á.Þ=`¹ÎÊSÌj0Üù¾Ü5&9Ä[ÿÀÞlºÄ¬ 袅2˜â/eèSD×éÎTñ—} ½$ÓY÷°L×5•L÷>Òö$ÓÉ Å2£-Ó)åÚ2]€‰ßf‹¿ä—²TºnÆ“J§ú…%ÓŧîCtÛ8ÒéTq±tº®ˆ;ët]qqÖé,,Y§óµ±N§º¥Óy_ÖéT`Ö:Ù:]g"˜u:_.ëtÏqét¾Æ¥ÓÑw¿tº®)½u: [êT»¨´:¥3–VçëUbg:›X§»«ÄºGf±Î‘Žë\bí )Ö½She±Ž>Ú%ÖRâ$Ö±ÀD‰uï)ô“X×…2VëTׯÔ:`µ™N¾tÅtá(¦{á[H÷ Å< é¢úžî=¥ï 風ƒ2Ét²´-¦‹¸gŒ,¦SFi1ÝËד™îí<>!ÝÚæÂ(Dº—•< éÞ[4$¤“‰q!vTH÷Ҭ_HW‘’BºWËsFºÕ‡Òœ®Z„tòš-¤{Û7åÅ>bÝTMÕbº—‰€f:U,¦ëðÕ6ÒuÆö™èú)ND'_ˆ"ºê#¢ë\Í(¢‹uÁÄ®ǫ̈Š?‰sNæ…s‘ù€a…sŽ×1ÏU4¥x®Óf©xN“â¹O &þ&ŠçÖ&Ç.ÕMU+ž“‰cñ\§Uiñœ>QÅs] ¯®Óè­€N•z èº!K@ç>ºþÄs>IóœC€Ìs27+ž““cñ\7Šçøù+œó¾Is++Esª:`šSBᜊóÎE4€J8×§Â…së ç°g³œ>ÅrqLà=±\õË -7˜åV n ³Üž攘Q0¿Ñ0§/¨a®³iÁœ,¬ sƒöªEs¾#Ls1³V&šFµ»RNÂqN¾Â9Å}Îó€™NݸDºLøÚ#/³ „òçNŠàÝI¢[ ,s,¢+ÝÞD÷ÄXŒ7Y%ž±·º<–F‡s"¾!úÿPÉPœT1€.òÍ´s]•±Ðe Õ‘•QÎOÀ7]fka‘@—Ñþ{ðeÖâx¾ uë@Ï-¡îz%ž)¡N×ΨS±½Ê¨{u:©NsêJª‹R+ØJyušñW^&œ•W§˜ùÊ«[ãŒo^]—ö輺HøUL—çÈwZü*­NFy•V§éZ¥Õ½ÒiV×u‡:­®¶bZÝà’^¥Õ­g“¹L«‹ì­]§Ë„|8­Î \N«SÅßJ«Ó®*­Îß§Õ­]"ôÞiuòf¯¼ºØ1yuC95N¬«q”XæwÐûœX§Å'±GèĺÎï—3ë [;±îpŒ”ëfÿ`b¨rN¬ã2Ä–X§pÅJ¬c)'Öm£Ä:­ÜUb]`Ø€™—‚ÊsëðàUjÝd-çÖEJ‘Œ¹u'£>*µ®’à”Z÷: ©u 6ØR란Sëa£Ôº:k§Ö±”3ëâØðk;³Ne¥¶Ì:¥š8³N5Ž*³îTÞSë²·§Ö±Sëº2é˜[?Ý몷sëâû„`fÆN*·.â7ТÜ:Y€:·î¸ŒqÌ­sz RëhšW©u2tj]üÜX]qj¬Ø+µN>=•Z'u§Öeê'PJ©uÔªÔ:ÚcWj,Œ?©uÜ»Rë†V©uN¶Sj]¼a?©uñca‘@©uQ/|×éò´HrL­S`SëêeâÔ:K)J­‹äÙ¹£]ÌÀH¦ÖÅӊɳSë†oÁÜr%[á€=æÖEFðIØcnl³*¹®)9ÑÉu2†ªäºpH$î1¹Néê•\çëîä:G*0¹.+w°Éu=³Ku¸·1°’ë$¨äº4üƒr¨ä:Çð9¹Î1{J®k‰̬;Š¡íTÀ×™urJpfÝA!Ê©‹ØÖ-ü2o.t@JÝ!Ë{§ÔÕ0¥N†ãN©Óʨ“;¶3ê¢åŒº“uPœQçÄĘ̂;¼$§Œ:„2êâ¾q]ynn¸ü› u%ê1¡NUPwj‘— u17p£±ïØ|#okó’Y—ãJ·wZv±¿¹Yub—Íwl½ƒµö¸¥¾ÔVž:ÕR_ëù€Ÿ±Ô²…¶},µlc­îsTü{'[¶Qø÷´çXTB þ#˱¿k#––c÷Ÿ·;Îÿ·–c¿»Yæ›nŸ»=ÒÏÛ.猪ËE[/$;1 TvbG]h¹n)‰%«å†®¢*ÃÑ2óøµ²Zh+«OâÒjAuà"_÷µ¸¤-# SIP«eä4üHžË†ˆzÄâöã_XÔï“-!çF/ûÕýJ4žB@¥¡Æ>¡QDzDËø6c¼grý žRZ·`Áž'•Þ-¿²´Xã6Q=b[|_-§‘ΖP11òÁ­"+þWúÛ¿jÉŠQ~àÄyFM¸÷Ó§ÁðžÙ«ëïN¾i:-tmã~¢Ø`:²‘¾V˨|(hwµ<ÉÊ1Ó¸n¶$,{Ùµ¼I˱^ÏkÕzòò!›˜Õ2Ìò[‹Z»1yhµÌ8ÞXì ÕÕ!K´›-3ïå:Éj9“›= «%+ݦÕ÷í/´ÌÉ–¬wpPÚ[ w‡/|ßWÃsk…œËõ6œÁ‹·f´ŸOÝ}W.l¯ŸïÂYG-¡Ëüý£–ÐÄúÎr£ép¶`&WhsA‹7cÔºÐÂëΕ?E`C’tÐúà0×ûÛûm¹ÁÒa±‚³ŒZBdü‹ã<‹¸!PK(ÝÖ\Ì»_ZMáC¨bBõ¹úÕÛ'ª ]¿ÊnýǦ֢áj9ÏßöµÚhM<ØVKF£Ï‹}E™g£ùÕ‚zƒT®âï¥.f­–çÑ’Ï*j ]XäMµ„ú\'Y5¡Ÿ·Ä“Â=öÍ>Xª:¤³®@\l<…|5g-¡c\zz¢˜×Úø6z¹`¥ìŽÕÂ.Vø\F1¡ÉU.4„®û+Æ4ðÓò Ö⣵„v÷¿héyk4mJׯ´kâÃò,?+KiµäÚÕÕëo,?_~¿w®^1H5ä¢Aú/ñ¦î\¿Š'ÅLê30 ¥8* 5Þó²ÞPWÃ7{µ„²û«\«VË‹ê%* ´ZzŽBc†ø{âIzv£’ЄÏ?kQIèF Ÿ¨¨$D{³k°‹Ïë0ùV\Òz.ík@ÙÍÊ)Ø×à¢Vü¨7[æoÔ?8 ×µTXkµ<4ÓŽ¸®õø€cR˜®i‡˜K[V˸ä*vð¸¸%;®h¸Ï/=/‘ÎSà ™I¾¿Êtjµ´fXÿ¿ÑkŒïš²n[q S¦‡ÂÛhB×=¥-EËЃÊß)V~ã3¼ZR¦K+5>–Ô•V^‡^¬![ñr†Çkó8Ï3‹(Þ“Ÿðt{©FD ŸB.‚Ÿñy„]ÓzÏø áôÍŠ7<,Ò¨ŽD  ·}?XîÌÎ;ãµ—´‹ßïxÊp\^|Sc+î}ЭóïIƒ7J!Ñ2q|úÇ0¿±R6v”ëœ8`LZ´”qÖŽTBH!ý^9•dõgMÆLsnßiŽïbÒœBwDs]^7¢¹®i«h®ËsS4~Ô˜é‹ædPbš“_„h®«ê¡iN¦9MGMsò/!Íœ(™æÎƒg"š;Y†×4§lÓ\T…Âq’æ”ïmšã¼Ù0§‡aN9¹„¹À¦Q0W é¥uÑœ·Es?Qn4ì7”)Ž‹(²`§_÷õÛŽqCi;¸¡êèÀ¸P7^0.¸›Œ*@+ŒJ(Æ e ã†|±…qQ„MŽ å%Ø%È ~ãÄq±¼÷ 7T—æoĺ両ˆq\ôà§‚7jOŽ‹½\jAvˆ 7äélˆ*†eˆõý#Ä…\'mââ·å‡!!nÈÊSw‡ŠÄ1 î*Z.ˆËs¼‡Iq9.§Z ¸ÜJÜ”W%8EqéáÞ?—®î;ÅåÚ ¿Æ ¸Œãå;3—åi汤¸ìÁ³Åå’ËAÒKŠË–{§¸Õ‚X A\îš_?@\v™j8¼×¸•wG°a ôãã ·í¨eÍÆ^Épyl"­d¸„ßY0\¦²6îÓ'.û8mÃáà¸Õ€í 3U„p9ŒžÏçœp9ˆÐ+.û €pÙr‰áÒPpüár×— n"Ëìäê. ÅZÏ-›ÞE`¸¦‰êðÓ…—{棄Ë}G¸ìÃi*.wÍ3ÃeŸ‡-'LÜÖ8”” —‡'@kpq{_í—Ë}D`@\Žsp䄸ܪÄ!Ō۠"llÃG—}^’Þ8u“Lµ`Á3T|ââÄÃ\S6P\Ž,&:OfPV(¹UÃw2>v$½ JUÛÅ!‡ðâß\ø,Î{¸òé+ ŠÃñq«~èw vP—JMÅåV\JÅíw0.a¾ãòxyçã*•NãâÏ _MÅŠá²…· îÓçÁçs]ΈË]wa> Z Äå8H%\6½tƒá²ŸÔWù–Mdžð+èÙLb¸ ÖF ßÑwêÒá>ÃÜø’ª„.ûðGÃe˱3°.OëY`8d½²ÇÀµ_úÙÀpûµÃ!ë• øžöS÷".“ù4J·¼v„ÃVä³kêGà‚á*A —»æW¯³Z¼ÃÁ›tg8\>n5ðIUú®rÅpyùø&ÃeaÒ‰Oêj!S‚ápß“ÚÐE.ŠËÃナ˃aC%[a>¨µ^ ˆÛ¯0 .…Ï2 n¿z€¸JaÄÁ¨•À£”\Ú‰/j¿ˆ”„8ܲhhø¦®AðÒ ÃmL†ËŒWqÞÝõ#4òÙƒoj§w”.Çy¹óŽo*“¸„pÛ”·]"œÜºþj„Ëßäf<ÉÑõ¤NBÝyëðxÞT퇊bˆáöÓ¤,9”û÷OØŠ ãìO ã†Ö€€qCKÖå4W´(w?x‚,ÊEÝrªtC“I)î~ ââoH]”äbÅÄ%IîqâTpÀç1“áª?î~q[šád×l†«ƒ íÂ'.J¹ûù¡È™q²‰&ÄÝ”e q2<'ÄÕ¿ân+z„8É8æ¸u»AÙÊ©ŽQnÞ"K¢s5Œr5Qަ©$¹ùü¶ëq©2B #ÈUAnR0Èy@r\†ÓíjÜä-$9."qzÒã¤MZ£™¢õ8eP{©†Ôã8I·‹ldÊq1Å•ø9î=9ZrœœôKŽ«iˆä¸÷ÐGÆr\óÈ%ÇiÊqaÆKrƒ7m’‹m¨‘ä"èŸÓ-’Üä•6ÈÅÙ¶ȹ~’A.ú‚Àqq¼Ò¶¨Æ©B–9.â¯øÑ!ÇE”ÝU÷*ÃmŽ›²Ä,5®¤ ©q /5.dh4PŒÛ¦è;Ç¥ Iè¡'·Liq‡ RZ\¬æ’®R‹[Ï0—a¥ÅÑ;±¤¸ÃT$)޳ép§ïépê@NKG%©¸­C*p*¾R \̈ˆ:TàNc‚¸ó™K;½"+î4´H;= —§rç¥Á)y¨48Yq–wN­Cƒ; ÒàšçŸÒà”¢PÜ9õ³K„;§®D¸æ9ªD¸õ¹v€Ë‘ÛG…‹q:±*\$Æé Â*&LîïŸe¸£yîKno¡ ň$Ì¥ wÈÑ2\^ VáŽÓŠ*e¸Ca–áâ)™;ÀåÈæ Ã…ŠÍ;2\ý¾”áŽæ))e¸Ø÷üÈp‡¬» pÓÂ,U¸Md§ -sç·Ü7Ép%@†kžéR†;šgô”áŽæ(e¸CîL–á²…\îPµmëpÎ,NE ­ÃmÔáÙŒZ‡;T¯ˆ:Ü¡…Tëp‡LÁ¬Ãt>³wÈ]®t¸vY-ƒwÈËÐ:\ 12œS-ÃmgIîÐʯe¸C ¹”áy:Y†Ëß PárT¸ÃÊ'E¸Cy¦áâ¬wÈcÉ"Ü!‹*‹p‡ *Z„Ûªpч/ŠTá¶KEn ð  wÈÌ*Ü!§*«pyh€·ï"\Öá#XA„;.E1Pƒ;d×h .ç j:¾R†;ä¾i.¶¹>2œÓW-Ãmá0”á¢4BÈp‡Ý-Ã2¤³ wHJ° wÈ4‘2Ü!ÛGËp‡JSY†;TË2Ü!›3Ëp‡\Ì,Ãå/E) 2ÜÞîN`î1œe¸ÌOåV”áZQ'Ò_ÿÍìÊð¬ÛŽ% ­ÁÅ&á "\TxÄ%———ódËÔf—‹U~~þs˜™ ZÿÆlò—#³éõafÓícf“!­™M f6é‚HI;Œ ¤¤']RpMmòì4µUR[íåá¿3*’ئP'c[£7бM–©Æ6Ÿ‰°MUÝŒm> a›wkíMZ°Mnš¥½!OXÒEÕ’Þ˜wZÒ›.„¨Moºà$žZ€ST¤¨­7)p49Þ¸¹)púÎÜô"7¸U‚ÛÖp“ù¶É­Æ WášTà ‘’ÜÔa=;º ½Ô-ÁUüæhûo, î¢+%8]œ’àš—¦$ÁéÐK‚“a©pÚq©põq– ·í‹*\}¸¤ÂÕg *\|‰IwTát ¥Âm-ÃO˜F¡ Wû– §«[*\MA¤ÂéÆ(®fuRáÚ«¯T8ú£K„k¯Ô‰põi£¸ Ú„w‰¶‚ÆÃ:¨póúšP…›:#HpóšBVJp³bŽÚ¹×P¶7·HË4ÈŠ$n .ˆ¥B nÊ©Á\ôùHpSj°%¸háÌ\® Ž2kç}£¼ãaa—™!Í¡ÀÅGÁdTàj pÑåCp«¥ý&\C†OœÁ úÛÔú‘¸¹æù¼í(ÀÅÁôà0°$¹©>\»Nn–ÌLnj-Ì ÜÔº ¸ðGàÌ‚ \Í'Š2[¤yA‹+!ȃã™ ÀE çüTàâ©yQÛŽ9¸8>^-*p³Ät*p±0u)j«'Û¾¡ÀM®UˆE¸íjQ„‹aÈ}Ðàæí¥DjpÑ…t“ܶ mŸ¢É \ü¼š”àòÚQ¦ƒ-|ÝP‚›*tk nk¡·ý”àbï7¬†Ö/G n»gSƒ›W:©ÁM¹¹X„Û~[ŠpqWs‘„"Üvi(ÂÅ5§* ÎNÖàf¥Pƒó…Wg$ .×Ç÷8Ê<£—¢4¸:ipuOKƒ«_A\lõrßÐàòwùhpu=¥ÁÕ•7®NR"\î‰= ÂMÇI„ËO Ám'®ÌY1Iƒ›J«tÛ(¤ýOº†™çÖ,ò“—Šx%ÆÅÝ ÀÏ ÎÌsÌsJ2ÏMKj‡Ë½ )òÜì¼ÆòE´?Ï…À¹'Æe!lž Ž@ÚTòœ+\ˆç¦£Ésñ…`ÎÓ¡~›h` žóËL<—&K¿ ç‚;ú®ÂME*çlË+œ Þ«B)§J ;1Nõ'C^'ÆÉ"͉qRž'I'ÆÉQÚ‰q?û«pnÊ!Šyq2Xt^\ø(¼˜'cçÅÉÙÆyqÓ©tÌ‹›C‰rTâæPØæƒ5ÄÃ:Úƒ%D§ J‰sÄ-pIb8ð49:š(–> œ«áDÁÖ#[eǹ\˜Þ•¸çhŽ,Íí‚hn¼Õ¼½|ø‰©Äbû¤ZbUþɼ8™UT^\ÎȳiqªšPyq*Uyqáì¢L9¬^NRyqïµKK¸ŠŽd^œœþ+/Når¤Ä©|åÅ]£Ðˇ¯T6¥Å +‡J‹+º£W«ÇRâîÓ™J‹»ÆH)®R4˜ç-§Å9R\ÍŽs«e`ÝgK‹Óúµ¸ûÑiKŽ«TÉq÷k‘ŠœáL‚ÜÖ…š\}ƒ¡ÉÝPçé½$9ϤȅYÜP™™~Æ7¬ÖÜIŠ\|ë UTäT£¾¹ÇIšRä¶=*rñ½§ú—ŠÜ³ÇSî …’ãj²*9®ÂS%ÇñE\jÜjx÷pÊ<!Õ¸È!?Q«[©qÏ#Ò÷\ZD‡÷ +mTãž¡¹”Ô¸PêÑ@1n#@ŠqŒ$Æ=Ss)‰qŽi•÷8¿UZ\å¶H‹«˜iq¯"'OüМ Kˆ‹øÕ=’2÷+9BÜ«ÓáŽÊÍ‘· C!î½¢I!®²l$ÄmT”BÜk ZBÜÏ@ÊÕrkuMB\|0”!  ²€$ÄUx¨„¸:> qôép²²/.f<êpNÄ¡WÑÊÒá*MU:œL.Kˆ‹ëºSæÁðã !..B\¼Z¾J\EûJ‰«¨r)q[˜&1nm5…m GÃK#%ΑçRâÂÁ’]¨Ä½]ú·¤8¢YŠ«–÷ZY—·¾} q¤'oû’âe¦J‰«Ã÷Zh—§©n)qNé²'£ÎRâ*8URœŒêKŠ‹€zr¥¸-Æ‘Z\ŃJ‹ûK™·è(Ëçr¸ J€£ÛÉ‚¤¸·é×Q.)α‰–ⶃ¡W!Ø’âúåPD8öµo0%RÅvýãÄZRœC-ÅõF•JJÜÖ€©^?ÖáúûŸ4Á2R‡ëÃXIÎoXêp[4(u¸Šœ”×ó×ásœ£”¸þHð“×a%®?Öï(Å)b³;ÏÈeûØ¿\ «Û寖ÝíëooW½Ôç_t kí9÷ñù÷æÆ•-›ÿÞ½Z˜Ï(jÙÇAÛ>’Z¶±®‹hÛ«e‹mÛXnùv ;Û™ë3ÿšKØøÿÒ%ìn—3ó¿>a?n½¼©Þãs3þ¥Æ*0µ9…i$÷Ñ@»›ÆÙ]À0ÐÇ+Œ#m½8Ô×QŒcm>`kw ÓXÕKc}<Å8ÖæƱv¿0U½4ÖÇUŒcm^`kw ÓXÕKc}|Åô8—Æúx†ù5à^ë_ñ ;#K:¼çÿ«iØß7 û3ïñ¿üîüGoí¿üáÃúóMþ7ÖßõO‡­{*)ê¿lç°íÕùŸþó?a¶.ää'ãDjB½硜E°>¥\#‹Ø…Ç.&a-ªh-HÄXÃô“ÈNi›é2gä†`ªÙ¨ŒØhl@†–2WË‹4 ‹Åç¨ÜbŽ2Ú¸fN !Œm¨Eë13¡Sž çdhCd¤âp£v{æÂ(eòœ mÚžQ›’5Ú[Ùi8º\Rý•I,¯Z¦r¾:·zÚ¨µÐÕòÞJçy¸ó~*aж‰êƒ’üO|Iö<œˆ>Ï%í“+]í`dÃ`M´`É:æúladƒjœ¬–vÉ :P;Ù°ž“#_Ck~˜ ¶#CP5 ÿ~†¤…ÒÕÂüâu§áúµ˜rßXb8nG,Ò"LKÛ1Œd¯¡6C¹:â‰p¤u‹ÕÂo§si[…‡Ç‰L’[8ܼ?Z8.X¡×£´ žÃÉ㉴›Õð .Éá÷ídŠqˆ8©øŠP8ìÃã©ò¶ž:œ‚4úv2ÇØ¡ÿíœL*™ ÓÖ˜dZ†N“„–•\÷¿©o{b`C“ÓeT‚›ò®Û``CÓêfÔ‚·‘)G6@ –½Z¨‡ nÃȆ:àIY¸É MF6ÔÑL ÃMLm2²AU7V ¥ásê=¢j®ñ`±E®©µ/Æ6Ø0ï:à›J7ë >ìÄ¢ë @ÜX5tµÈ9UëŸ×A‰Ø—â:¨7®e^5bÙÿ¯¦kªòB´°¶¸ÔÎë LÌj(«¡ß:>Ü}×1Ú~©®(Üp³˜³Õl°Ü¦B®Nÿ¹NælªFC´°Â8«•­æl6¥â_'s6›¯¯“9›NXºNæl6\'s6£¶^–Ç¥;™±Y—÷dÆf쇛0c³1ÿ:™±ÙXðj±âqê¦Zð1•‰îj9Š¡uô«1e³)±ýB)W(€Wc¶fÔÂÀ±©«Dì«1]³¸0ÔDWcÀ¯j¿Ôj’n²?k(V¼—«ýŸe/–ÿ,ÜS%Oâ^¼þ’p¯³xŸi¯«ê¤i¯³ £i/´‚i¯«ú•q¯«v„q/V4ŸîÙÐ̼—«žDMð^±°Ïì›¶y¯«€yoïÞÛû4®Õ* YÀ-7·ðeb€¯)ó_7 øºi{GàË>l˜ø“‹¼·q:y¯ÛuU¼W}Ä{Ùòá½®^æ½½¼·oÞ‹|óO!p/Z p¯ËJÛ¸·÷îíã÷öàÞ~xÀ½­q/Zør'îÅ'›ÈÚ‹.c£½ýoÐ^–÷C`¯+´Ç´×U9Ì´·ï´·í°—ãrÀÞÖ¬· Ö넽œ„¦öêpÉz]u®Ìz]nåf½}°Þ¾XoïÖ˃!£õ>-S§ ëí#ƒõ¢…¼’¬·`o…°· a/G!=örnØÛÇïí}À{û8ཽxo;BòÞÞÒyÄ\Ÿ ïu•2ïíGÞÛöDÞÛÆ!ïE I‚¼·í›¼·]QòÞÞrŸŸ£!ðmçMàÛûøö£é‡ŽO C§ .@¾} ß¶+"_ CâÛŽ—Ä· “Äg KßveH|û6@¾mG ¾ø"ÄOßv$¾}W ¾}WTݶ]M.¡ÖÈÓ"ÇIäÛF!òå6< ß6 ‘ooòÕI‘øöøö€|]AF¾íĉ|ûáù¶]ÏïFàÛN‰À×U„ÒÀ·‹äÏ­¥ù)ì"¼ÓgÀq®©3ÐV,-âÃ!óm ´NݶyççJùö3 {j "÷T_º.ûTu!ðmû!ðm]Ú©‹KZ&ïm§˜¼·yooy_^îè?RòÞ¾U¿~Ü ä½}œ1~žÂ|ô°oëCàû´|Ç%ðmgIàÛŽ†À·]_]>òÞ>ÌÛ~Ü!ä½OK×áñn$ïí;Ÿ?Bð^Œ€¯¶ðÕi øöQÚüÞ徺8"¾½åißsñí}Þ®ŸA-ýÖ9è˜Gûî{Ìï%óm{"óm[‘ù>-~ 9™o;2_]u1ß>Î=œ™oß꽿=úù}Šúö>ãõ5æ(óò9|°oëCì˳"¯}Úõ}_û¶£!ùíÛÜÏ÷m(ôÛŽXÑÛ8ïÐ9\{ðKíûŸ0"3þ=»džòYÿðŸKóHîsæå>Ùx•ÜçÄ:Ë}·të}·ô ë}7õ ë}¯ûÀáŒ3ë}ëíG?p ~ÊJ²à·m•‚_äçåŸÒûîùSïÛ[¦ŽŽ6üÖ0LÅ‘àA¿þ‹­‚¿ø?¢¿8à¯àwKr±à·m•‚_¤?'ZðsRŸ¿»ÿöá¿ú¬÷9gÎzŸTë}aÔrßmX‚Üwÿä¿ØäùÊ}kÓþá¿}+Ê}— ¹,÷m{¢Üw=©öÝ~Kí»äóeµï6 Kísýª}u0Rû¼#‰}¾ ûd¯]bßÅ2Û%öÝ„ûn¬Ä¾›Y%%öEÉh Å>g[[í‹qÈ\ñüç¥"MQí»½"@¬SØç\`lÄåTà¸=Ã%î}Þ¦SÔHCá[ßmò_^ÏÖ·ýrÉÃ%7Ķ7ÿmgMþÛ[Ú©Sx?üWCüۻܷºÊžSgp}ä¾í‚ÿ†ÒÙAñ'·§îñù¿}Tº ×r:á/~þöû¶£#üÕ)‘ý¶ëKö˃cËMcv©`¿íÚ‘ýömÀ~{š ßÅ€¿ðŠÔ)þ¶ç‰ð—}>zŸ.Lã.ýE‹±]ûiþö†®3¢ý¶s"üÙÛÒð·Ýi„¿í¶'üÕ¯Kö‹ažûeáûm'ì·Ýäd¿í$ûÕ9ýbX l×­ß@ÃÞM¿¸îž?nr²ßpö¸Ø/Ç¡úØ›NáúÈ}þ€¿íz’þ¶kNúÛŽô·=í¤¿ÜûÐN¸Î“ô·Ý¤¿½å~õ3ˆí˜îYK—çªæuà¿}¹®ÒëAø—¯åÿE—›Ú¢|W}âÀmà!ïÕ¸÷ùª¯hàv´Cæ«þU€Ûµr`õ=LÌæ¾åÁú÷}ñã Ù°ú¾™òaõ=1eÄZ}Îñ9§)+Ö&Q˜X—fÊU¾â¿íeCÜNЏý.À½ý„·ºûÔ‰ó KéïãSÖÑë ¬ŸJ¸·ÐägÛŠ.?÷†{íû0÷ãQ­êÓoƒúŒÏý(Ü·¡Ù¯„°®¨Ð‡ø/ÍjØ¢Š>Íóªçù£ùí}Tqëà†Ïà|ïý¶þÕdHøç’£Æ¿á|Fáß6ñoû5› nè.þí-´úñ= ü«×¬ðoûu‰û¾éõ£2*Æ?? ¢¿º2„?×<ù.f|뵺u¾&|_8‡n‚ßph¯Ù[À§ óžmB+¾ÓÅÄ{µ |Ò½Í{Í–Ä{–¬Í{ö 5ïÅÀ<ƒä½HF!É»ÊÛø-üÍ{Ž2ïYÝ7ïÕÁˆ÷šª˜÷ê,Å{¶(5ïÕïY©'ïm{"ïm{"ïI»7î霌{>mãž÷lÜóÅ2îm}È{tÞÛþ&ïùèÌ{Û¸ä½íhÈ{ÛžÈ{[ y¯NмçËiÞkJ!4ïÕÎÅ{50x¯F¼W§ àÛ¶!ñÕ‰‹ø¶qH|ÛV$¾íˆI|[Ÿo6_,âÛZ’ø|Ó˜øjO"¾ºB¾¦ŠF¾:!ß¶'"ß6‘oÛŠÈ·™¯®©˜Ï7-oûsúè¨ï‘øj Ÿ7ðÕÁ øêPD|uJ"¾†ÀWg$àÛ&ðÕâ;§UC"_¼Oñ‰ÓÖ‡Èçw®‘¯úùö|œ¶2_{'Jækï—ùšŠE˜ùäkä³ã¯‘¯ºøløkâsl‹‰ÏÁ0&>ÕOÛˆOÙ€&>Õ4ñE ã7“ø|0">gùšjƒù꜄|5 ‰oëBâ[ÃpÝHÄW‘ø¶Ã%ñmÃøš’½I|uB"¾:_䈒‰|M5=Œ|Û¸D¾­‘ok!òÕ !ä«JÈ·mEä«óò5–B4ñÕï/âóµðUyÏ–Ðæ=š÷êBˆ÷êb‰÷¶>e×úˆîNýÚ×Ë£c £x¯~8ß¶ ¯)ÃÀ繆¯.§€¯ŽOÄWç â«#ñÕ¾E|õ£ˆø¶>$>_b_ýn¾m×Ã3ïGß60Ï¿·x¯ºˆ÷ö–ñ¹V⽄¸·u!ïmƒ÷ê–ïÕ%Þ«³ïFÌ{ÛÈåæª­f=‡[€gýp潦g󞯧yÏÇgÞó¾Í{Ûžäꪔó^•xÏ×˼·y/Þ Šélû»Ð¼g#Ró^+ÞóU7ïÕoÀG$”·«RÏÍ{µsñž¿Pæ= |~ïøê$|¶J5ðùy6ðm-òvõÏ àÛ[†Ïá湸€¯ŽÀW?€Ïö÷>w |þø¶=½þªNFŒöçó°þ¦g…{vüë7Þàëâ‰í’þ¬SšþÖż•ï‡l„ã0oÿ¦k¬ ÿ"W†ynÄ¿È<‘Ôü‹,õ!ÿM9ÅÿÅX¿‰øçª3Æ¿ððPèLÛ¯[¬Ä¿¹6e‚"ñoºÐšø/¼è€@þ›Ê°cüò!Ë?Â_Vá ÿào«„AøK¬û .ehø‹’ƒ{v_ÕWüÙÛÂð÷:õDôgWãß{Yr#þ½ÎžþÙSÆøg[ãß«lN⟽jŒÛ(Ä¿5Ê«.¼Moüóyÿ\dÒøã|õ>;ܘÿìpcþ‹|íO¼g´HÌa_##ñO†s…¯j„1ìÿ¶>Ä?ÿ¼Æ?ï6þm}ˆ[⟠cŒv¸!þ½O €]=¸p+ü«#þi²_”ÚüÄ{æ£È>d¿p/é±r¡hÄ~.wiö³+ŽÙ/jnó`þ\pÒôçrœ¦¿×)A¢¿:>áßjaB¥ð/¾–l!þmãÿlýcþsMpóŸ„EÂß¶£~NQðW§(ø‹M?ÁžÃŽ=†¿Gð·úœ_ø«} þ^ç5 þ¢Âèì¹ï‰ðçꡦ¿÷gvßv©„.µiü«ŸNøçÒíÆ¿×_¿wZˆ#þ%yeéÏM¤¿:áßë0áŸ+·ÿê`„Û¸ä¿ð_‚ÿÖi>ŸpÏÊÖ6Ö%n}€vî": Ühc, í– €¯ª·q€Î87ÖY ·qTAÉš¢¿úUÞ* ÊT(Ð_]<áŸæ¦¿×V¿îü.ñ_ #þ[}ø¼‹ÿ¶>ä?W35ÿÕ‹ÿê€Åu=Áªkü{½L#üsZãßëeá_”ðÏ~[Æ?;šÿxÁÅ~½Rõ®í÷ø©²¨¹/~÷¯Ò÷tÆqˆû^§³‰ûºÒÄ}Û‘’ûl8fîë•‚Gðë["ß¡Ë?v¡¯FøÕO&òëJ¥3ùÕ‹üz%>.Ì÷¢ÈÏ5iM~ñbA|Kcîä·íKµCÕ‡äç#6ùm=H~[’_wÞ^›ßŸÁà×+‡àç_ßàç7øù¹0øÕ®È}ÛÑ ¢N´ì£àïm ˜Ý~ÎX-Û8lÛFr˸CÚôãEÚßô/;¯ Õö·=ÔV‡ ½ß™3ýmÛ³ßßW”ˆé¿>®L?"¬*ò1GãXeiÆ¡6K3ä>h·FÃ8»¡úšq¤­‡úš£q¬ÍÐŒcí†f«zi¬9ÇÚ Í8Önh¦±ª—Æú˜£q¬ÍÐŒcí†f«zi¬9šžÑ24ÃXÛ3?Ûîűþ%Û³«§Åȵ=ûG¶gâåü—ß½fÿèUü—?~X¼žÿøaýýXÿ¼íYÜ,‹Ùþ‹±=ûÏ4ÆþWmÏ®¬–€‹6ç÷=è$û,b-]Sš(E‘yÛ*E¹@>Ó>X?êŠêtFc`ÕT€ƒœï¯(.a?¬}Íé ?Âó™ýŸ÷õ­8FÊ Œé9©8óûhð“¶-Ò®òr ~ÐrÁQzÍ¡n޳þÿ9mrr§ új±kíá«ÅζwzB¯o¼ÑÒÓOzM×¹†tYaá¹\´yµ¤¡ôu«ô}Ìô‚¼Â± }Î# ¥/;ÍÝç™î×PLû»^ÕWwK‹¿=ý_/ñ4”^]׿¼ÒÊv]Òß8l.q=áŽõ·{=6q qx<à3—¸ž«.Åù¦•í3N²Ñ}æ×ó¼¸îs¤/ü“hî{¦/ü3ÙÁ–4”~•Y¸ÛÃÖY·óÆ'DÕîÖÒþ½¨¶ZÒOúu Ñ»]i ÿÚÔùn¹Âõ„¹7÷Ýž\±îá®u²%ý¤ßÁ ³»½¹`õO°t/ÞŽSœžÞm¤1ü³·¤Ÿô{³<½ætëÂàÏ+¸žX$Àjú½°"Ž¿[1X-i ÿÖu¸ZšI‡C8ÖîëJcø¨Å-â¾2ûéíнwÝé ßCá8Oü} oó¦/ük7…u7¥™t?¥­–4‡‡B ï+¸òhn¶Ì4‡Ï‰Žïή'6Æ`µ¤;|»wìýήu|*®zßin²ÿrw®q=±„ò¨eào>+w®p=áÁΫug¡ý<ï÷@ŸSïûM?éXHÒ8=ÝáÃþà9Œ4”~]fî¾gºÃ¿ñr`Ÿ™†ÒoT²À¾ž#íá£\s?¹Æµ•v]xÄ}®rëï4”~½žu?YÂwÝl—žæ'W¸žXãµy2_l=ƒK¬÷“+\ëås?ïG•×ñÞCžVKzÃ?ƒUQWËà³|Rž»Ÿ™ž~qIk]ÏØM¤4tþó³¨ À—Ú{¦9|îïm9«‹3îã!x±ð®ys…kÝ5’cï7+Ý­3=¹8u£€Ñ³^Þºk¢‚QœÂú½_µÄ®ëÏp>¨§¾ (bôÄÏ×¸ï™æðëptÅQÆh½eµ~£ŽQ¾Q¹ïžþfk+¯Þ¨dô¬ûIï¬(e”çpKoÔ2zn'ÞQÌhÃVÿly²Ç­_;Ê=hÁJîzFk›®»1 ÅÝÃ:âãP–¸ÕHwøÛ ó7j­­XÃèć;ö%o‰eVÕ}[-ùU †ã#¼aM»èÑ~Gi£çV‘$äà nŽšµV% ¤iô±ôq-ú¬wtŸªÀ傼 ø5Ö;º”Õ#^žÕ‰–7/¨ Zdƒ<¹B>,x÷æYÏ‘ØüÜ.Ãþ°âÑíwÀÊGW,?l˜)œþaÅ£6•(úœ©çÞ_n…ŠGqà?gªÀùëá«þdÅ£¸ÇMø¹Õû‡nÆž3Eà¼è77¢ yÓäs¦üD©›É¡âÑíÊTÏ™"p ~ð‡n×>ZŠÀO|“ñxXóèšzŸ¬ytÙ’æaÍ£è)ÇÚG—ë¥? “ä5¹§îö°æQ¬<ÜSªÀuï?,yú ÷”ð…E¾¢¥cú+3ÔœQó 0IzXõ蚪æú\‹åò ð{Xô(%EìéJ 8÷ÁôaÑ£˜¸<%eàÕ"ƒÜ‡EÚ%ï­çJøi®Ëû°èÑegå‡E®õ<ò6¾0GŽ«Å[”•bƆÂ%uµìqi™îĽ'¥h/â„Cj´üi´þ> (ùÁmPð§wƒá/Îë¿€¿ø=Ém ¿²&ýõ˜&~é/žò/þõÍÁ¶¤)Æ7Du¬ÿ•Nþ»GÍEÁ¯¢q.:.ªbZò_†Òôÿ² 7þ¶”þެþE­6€þŽumšx0¿Tg¼8 è/¢.>ðëùü~þâшN€¿X›ç¬-á¯½Æ Â_‹¾ZòK§í¤¿ëªÒßÚaûÒŸƒ`D¢ü’þ.‹'¿xi–‰·+¯ÿ®©ºkÀ¿»é¶þݯR„·0„w/Dþ=MEi„1×8À¿Ç†…kV®,ùo›&ÿ­÷ ~:ñß<… ä¿PÔyýÈš€“ÿ¢¤• ü÷ª©fþ;TÏWü%­:[ÈöÁÿ½®?*þ{ãMΖ'ÿn õ2ÿ¥Îš À¿w Büs)TáßkaZø÷Æ' ÿÞWf¿Â¿7Öq Ŀׅˌ ‰ÿ¸Ú†ï39ÅýE‰6\Ò_Þõ¡¿`n°è/Þ#‡ôçZG¦¿z EE'¢?‡šþ2* >'üÀ~Ùo2·Íè7ô-6ú /„ýúº øìý"`áà8@¿`.‘þú)yUô·¡2é/0‹¤¿,XF’ ú{çÃ…Â_·Q²à/†ýÂßkozÑßkQô×ÏñƒþÞuL- ¿X{ ‘þb_|õ%ý˜ñeDú{# ‡Gú‹#æDŸô×Ö5üu{\ þâxš„¿×fu‚¿¸Â·p0á/¢9îü½]E5ýPÉAÀ_üÍ7,á/ãþâžx>ð—¿®PïÀbÓ­ç’ð—˜Oá¯ËV^ì×íö.öëçaJûõKµàÅ~ñû¾üõCuEq…ø¸“þzD°èïjöô¿.Ù™ô÷FUGµä75Ö ù4“þò‡ç9€þ"‡71ñ/Ì®–®s`CÐ_¼ÃºX¯i)ìüÐß;¼ŒDú‹å(^sÒ_¼Z¸æBü‹ßÎ-Ϫª ÿÞ)wáß·ppIUñ½Â¿gxI(ñï]×ã"ìÿ^Q¹èï]ïyNIñpZOúËÔú{ç ú{íG)ú‹”ÓdÒ_œ&q0àïõ2¼à/ÎH ø{½ö$ø‹«7‰¢“Õó7‘¾©1#ný^•]6û½ŽqûÅÎyNd¿¸|χý"p¬qœ`¿¬ÉQÀ~±*GÈ ü½C€üb7tÈ’QÖSD~ùŽ@À/^ºý~ï­"©¿8Ú“-¿8:BÁ/_wø½ŽiøåÊ2À}ï]¬øp9U q_쨑áÀ}Ý ¿×ÅcE~ñb&æüÞ¡Š­¿÷QT®À¯B€Šÿµ¸/Ët’׿¨*Ä,î{× iòÀ}ùý$¯û^/p‰ûb+î Ø÷6YB ûRàF˜ÇÇMˆ ì‹™A?¹/>m\?tþÊý[Ü>]ä¾øîŸò¾þ³þgF¿ø~‚†æ%"¿áʾ"¿ÑÇo›êi 6€_`M ~S®@â¾(Q9¨N€SJ‚¸/ª•‹à¨û­û‚kaà¾Ì&l¡îçÕGÉ~ñô !ûE”¼»;_}g)ûµ, Œ¨~1Éà~¨ú9ÍHØëØ\u—êwýä¾+‹Ýf°/âúpßs(˜SÜÉ?D¿Ûđܫç‡ûžG5`Ä}Qøýp_*KŠ÷ÝW1'¸ï=jßTýüÊ·êWpqßG„e?';ˆûBGk÷=.N*î[§%)ŽªŸWî¬ú=ÆqbßÝUwÜØçòVVýNÿšRýê£*ÙÏ‹µ ¾¢]R_÷:˜¨/æÌ”¤ú­øñ¿k$ü…“Z<ç$j‘ûâI ±‘û"¬ŸðEî[ ÁUºß©˜jrßú„Ž/÷E ]ö îןRó3ˆA‘Gºßz¥s©[à·^ T~1Ç_Ý/HŽJu¿£”6‚ßú1&ÉŠº_iâÐýr¦œü’S¸#‚Ÿ&æ¾xÒ¸¸¯G@€}1I'" û¦ü…}‘BFpõÅ œw©¯7.쓵!°oJª÷Å(|t ~q0\Íøùk-ðëÚñJüºs’~½D}_¼a¾à7üRøõf•’à·nôS2_#G §®0ŸB‘ß{ ~ ]˜wŠš„‹¿’p ~=œö ünÙ]üÎ×;Oðòëøõº­~‘'ARàwŠÏE~19!küb®¶‘ü¢øöüÈ~Ýe©L~õpüúkáJäwù­@òS¶‹Éo o’_ˆ` ÉÏSŒ"¿MùÙmÍä·Þ‰‚-¢_£)¢ÉïPö˜É/¿ôÙðëöÚ$ø]LøÍGð‹"ëÙ¯ß^€5ø†ü30Áo[ øÅïû¿îM_?>Ôimþí†%öu;qû4çõuãõEÁvÞ!¤¾À]¾kD}‚úâWâµ"õÕo"è[/!>§„¾·_:š™¿ §ˆùâL¾ ôÕ¡/²))»úò—D˜¯»J˜¯[‹7ó¹–¡˜/†QKB_¡¯nVCßðœ™Ð—I1Å/¢G¤ÝŒ¤9!¦¾ÉS ôÅ Íy?¡¯–%}µÜaèëõ~qˆ A|ñ"šB<|M½dfèªà)è‹„ª&¡¯—¢Jꋇ@‡Bꛇ ‰Ô×UžEÔ—ß¶úœVGêóPÔ·ÈøÈ}Ýõ„}±Õ$ûü…5ö…@Îq€}õšöÅïM©ÎÜ7,’ûœâ)îË«#ïÀ½G¦#÷ůÁMÈ}QFêƒh|0â>>‚>¿¾ }ÎÉ7õy9ÖÔ!’±ï}%{ ú¦R¼ }qxlŠ—VÁQCŸrÅ|ñ Œ?c{VߌïɇónU‘è5­Oôþ*ÐýCyQ‚•Þ îìºá,ïiQÛê^ÄÛ|Ô½¨_Èõ7QÞyëu¨èÎP?ê^´H©£ºg«d«{—£Ú¨î9\ÉÑ—0Eœ÷¼Òû€y› GÌ‹täñ‘÷â)}?Áš¢rÞÛ­„ó"ÃW8¯­w'—S¥ï­£â¥ ¾ç/¦ô½þRhØä=®°KÞ³ª1ï<= 0/²XlÀ¼È²%}ón[Ú•¼§õ Ë{ëμ>Ñ!Ès"MyOiY–÷bð‰î\þ R÷.S²0/l*ÐÊ»í/!Ê‹@Šó#îfŒ¸·žK‚‰y]ÅQ€y±¨È²Ä½˜«|‚;3É–±›GŃ¡”÷Ø0J”÷ÔL‘˜J#3ˆyÏ«rŸÂ¼\ÙeÃ<ÉI_RÞã¼(ﱋ—(oBIy«é‰ò"ØïÝùºú_É{ͪå½Ó‹Ü’÷Ö;Œ×†”XÁ ')ïŽqJÊ‹}óN#æÅ6ï'ºóµ=¡£;­ óž¨=ö‘÷ž.ÏuqÞãTRqÞ³i–½'ç=Ñ u¯¢šÅyµÜByï´0G}ï© |· !›óÖ«ì+ð½žÝXà‹§À÷¸|Z…wZR'ç½^oçÅ/E‚œgulœÃ? ÷Dx§WòÅyïúŒǨð]ZÇ3è½ò¡1èµé­¨ðE…êO|g¬ïòž è½ —zB&¾Š–$èÅy_Ћ£Q$)@ïÅÇ1Z$ñEþíWâ[?¿7½øLóÑ$èÅÎ×·$¾Óñ¼½XóÕ8VæÙƒ w:ìVßz Ð{ßÇ}z©ús\€^< \z"èÅ/Ã_ ÷nèÒ ¡}~â;#i^1•ÔøÖÈ ‡LÔ‹{TJP/žMžQï]Ï;i|§—ƈzñëñŠ õÖe”2Ô‹HLïžÆAj|^#’ÄwziD_À$•¥ÆE5¾Ë¹ ‚½õJ>?´áŠù¤ÆW‚²4¾ºD{õñ•Æ·.?ÙÒø\zÕ¸;`áž§@Ôønc5>Ô-ò9¬ß¼!OT)ò]‡ÁŒ"ßzF§ð"Ÿ×JäcJ±5>ÏÈ{kýM‘OQ'ƽó5±RãkÍ£ÔøŒåù"ü™EÜë·YŽ"ߎ€j‘oðx¥ñ…‹Å7i|ªÇMÏ‘iÖøžæj|ÏåmH|Ïð¸”ùBƒþx†ºÕ>žÏl>M_0`6øœàd™ÏÁÙ;ð©!yO1zVù,J[æ³p]2_3G’÷üïŵz¾2ßzi+(”2ßÛñ Üs†¾q¯+ÈÛ2ßc„NÜ‹©ÖÅ{6ì7ï­ßïúÄw¾ª¬S2ß#½VÄÑŠâëõ3ñͯÈ÷ªV¬qÏ-ó^hó<ˆ|]ªµxohaܼçé³j6óϘžü¥‡Úß黫àO3ã‚?…*“þƒj™ïúß9]¤Ç:ßYi„Ôùn“×{ç– ÌWßéÔùNnBä;]Ò^*_ÐÔ³ãߺ<‰L•/ŒúGå»cYS@ˆD—Œÿm‰俈íV‚ÿžš ÿ‡Gûÿ=EBþ{][üðqIùÃwj½¯ÏÙTÀM€ñxˆñ•Š49øÊ§IÄ¿u±$BÿbÌ/$ñ/t?N¿ˆ¯—ý„™À$M¯é+ (Qª|•#”øÏÿâ{Ão±d¾×QÉ|Ž+prß| wLî 3ŠƒJî;u= €[Ú0×—·èÎW…|Kæë¿)Ú“*ŸSш!ž”Þ甩|µœ,•/æüßô¾ÇHò_¬A>þël-ó=‡ÞWé”ÀmÍß2Ÿc%óÝÝ ”ù^Ú ãh¦p2Ÿq €£tÉ|Ó1¶ÀÐ?ÎŽS.\À·„Ôù×ïô¾~YPFèxÿ¤÷…É£’A€a@DÆ&öJ³$ÆVêŒ0õþ‘ú†ÓA„€U­›R_cË$õøü7ÎÇ”þë^¨´ÎWâù/.ZÀñîæå”Îç(!ë|¯3„¬ó]Î>¤Îwz• :ŸURÉ|a£ó•ùº£y¥óÙö®t¾á¬AâŸCĬóEä#G¦Î甡=Àóøx*×X2_]OÉ|ëÊüŒïäj±U¾æA©|*å`‘¯yYÆ"ŸiZìWAìù¶¬AŠ|'Uj|§ã§Ýyÿö•ø*XZ_°ÈàN¹pZâ«xoI|çcéMÑ£½ãÇ啯Wîù*"_eKä;‡íèN‚Áoú‹ o %øEªìü<=³Æg¢4>9šü\c}î䉃üæm¥MÑŽ÷·Ì÷ê-,ïðrt¾Z‘Îw<Å‚SÁ{×Wç‹ïÇ¡ÎWâ:ÉoK ù)­Œà·ïý‚Ÿ ` ~[(ÁÏÑ ? Þ?ç­üÆë¬<ß°öGò‹·è¥O‰|§±¥1*ºóµ8HòS®Á¯réÈ}~äÌ}7÷m}È}[_aÁ/§u5÷ùg3÷9(×ÜÀ—ûÆ)À$ö9HÂØç„à ï>:bß&Ñ‘ûm^áÃò›Â;5Þ„>’Áoõ`t¤À¯Sa6÷mÉä>O¡Í}k–Ç„7qß¼<°t>¹€ì:Ÿ”?‚ß4 ‘û*÷ᯮƒ¸oˬ“Îçs÷YnøÅëRÁÏY+–úÖM) •Ôwê [êÓëÝìw+•­´¾îxÓÉÇé‡ÖçUÇwzµ@èÇÅçÝú옹,²&¬w@Ïÿñߤçšl¨å¯n öÁMö¿ýíª—úìÛýÖg¿ÛCµ<,(û—ßíãÿØZÖçtÈRj]‹ó3–[¶±Ø¶å–+ÍççÌÝRc©­Æª–m¬tOùŒå–m,¶mc¹¥Æú²SKkñµÿ¦îÍ–*¦•·]ž®òEÃ¦ËøuÚ¤êwö¾áûö½ïßDwù­ýþ¶8øÖýú—ßÝÃqw¾Ó¸÷òPAÜžm(6|†r'µõÒPi®ˆ ¥†}¨ê¤¡ö^*ØéÝFÂߟÔÅãTó„6¼]'5|r'´õòPãÌÞ5>C¹“‡Úzmgˆ‡RÃ>TuÒP{¯?{GG&ϵf᥽€å‡ÑÚ½­ÉÊìç=ìŽl´ö·ºý4ZûÃÝÿ ÛO£µ´Û÷ï>G`´ö'>ôÂýý‹ÿ/çå½÷ú£Çô÷cý:øcýÔñ3ÿ·ñ{‹¿uFÜ>ø­ÿ‡|j÷ûoÿý¿¯oû}œÏ¿ýÿšøýOþ×ÿy½˜Öôx½Èþí/õŸÿݺt”ÿö¿üû{­¹Üú¯ÿÓÿ_ÿ³ú5Ïþ·ÿuu ^é¯ð?o¦a-û^_ŠAÜUqWĽÿÐnõ G¸0w{÷ÆÍîú޲Ý2¹Ñ®¿Ë îþfpGÌÁòm»½ÃZÞZè³íñÛ?Z'=#¸ ”±s¶T£[.eÃÓ£‹Å£óÎxÖç“õ8[£aƼ³˜²Là›T‹•¬PœXVoYuû©É§E4f2çÈ·a Cw•ŠÏ¢u2X "J‹ºª6—rBKìhIõ6UÊ-i°Í÷RñÖ S‰@8}¸3ÿ3¬”]ô9@ç:Ò¸ð¯i±óÛuk^öºÖ®ú=ëÅ^^têNÔºŽWbj {£E8ßft‡²¬Ž []³èW&ÅGOe çc餯–&É+VÏïøÆeÀVWVžO?cŠ¡³äçRg¸ÆõèÓUnàZÄ´fàW;®z½i÷|EŽ K¡¾¹Bt(á¨8ä˜v‡ÃëâŒ+ è¢<ƒt®øBȪ"#mÓE¸i?~ø+ì]•UG¯¸J áI»´« 'T´\뻲ºWMsEà ðàºôñ]W,Ó* >óÖ“vØž«Çûñ ‘ÅT®r]×­%åž–'WTS¸”ŽsŠ+DöŒ™EÊN(žÓ+ë)(T7v±úÜ^ HUüÂÊ-(t=Žëèl}Ò²ï×ñF­õ ë…>ÎxP³eS2튟ƒ OBâ•N2à(Þ’ã8ôM×Ôuu†áö\*½Òxû^ÄÔ¢Kdäcà™BÆëÞŒY§±®–¤ðŒ¸ÈY–"8"òà˜û¾ˆlº‚¸€‹™‚³úDÄÞgk¸ª`"´éèa y¹"T"ž×p§ÓeHÍj8¦/–>¯ô6¸ël¦Ua\(°Wì¢!³ ¯¼ÇÐe¦wà‹åX| €Žçõ¾äh‘+ñ=Z蕱¾wtiLÍEËW~]×V Ìkñã· #OôyòëŠB -ùuÍĵ‰ÂLqÄ£©¡ç×µEá°-”€MÞÅY–)‰º³fF–eºãJ¼\åʲL#¯¿Q–)n˜µób²0S>añ‰––_×¼Æysea¦·ãpp½Ú_×,ƒ1Ñf\9 ÃÆâÇ—âæ§=K3Ýq¹^š†ei¦™}&ᅵONân–f7Z°’~qmâ¶PK~]ópp£Ä§-Ž/B:s˜˜=¼î“Lr\'Ÿ×Ï~˜(ÍóàиѕŸ×¬‚ÛíBÒ}^lôä/Ý"˜W4⮎pâ1y4 å‰âLx\/Igy¦Î>FÆG4/àƒqæ‹©ð=°ÈÛâyDŸ‡‰¸Yž)gÃzdy¦œ ßL%ÉòL÷³O|W'2ª¥Ódt¹8§ÉúL£4ìûyñ¼^ŒÊòLx^ظîŠÏk̪Ñ0ð¸Ö0ãÅóz1›+«3åóÚX,«3å{!•4‹3åóÚNuAdF–sÉ×oTgÂózòÛ”õ™òy¹×…–çõÔÍ¡ãù¼F°¶z.<¯–Ä³Šš>r«1â-¼sà«x>`ïÔEÅ™¥ 2$öxjmZhû``èü˜@ £„ §ӎ°"Žóv‘9€`L8Î}ß‚«åqù²üR…:Úwl1'AH°Å´……†@‚YÛSj¢`²mßQ°E}@ÖÚ ¶H˯W“\‚‹‡]w_ª1˜N l¡¹¾;¶ˆ£<00k( -ªW"ꀘã0ièå‡êT@ 1pÝÖ2‹H \£è‡#&›Ó*Ÿ©s8¦ŒŸ©=Fñ3ÕfY&à3UðÖø™ºäö×ø•ºÌ~ñ+±;æ;õܰ…ÛÅ£ðûxÎó½qËÀŠŸ©ÛÛüL=§óõ™rŸ¡Ï”æÏ„À±x…R~¦âíÏØ\}¦Þßš_©þ89_©Wz6 0‡U¿R] «Åy€¿R]H@ÌêR”ä^~¦^9’sr@Ñsð3Õã Ì‘Ê<ù™ ‹ Ü)°¦<¢@L_UŸ©¡'“˜S§k§À¡‹5æF˜ï“sN†›Øæ`)`B` «Ð!0gm¸8„ÀÜèM Ì)~RàÚøéà7jHš$¶ˆ uüHÅ|%†˜Ób¼/ ëÊÈ‚˜[ayˆˆsÚ!0O›<÷ò#OlÕñ•2Fó¼±§ÔP¬=0o-¼èÈ€ÛO@Ä(hbî rf¹³ggÀà‚W0o-¼wÉ€ÛÍFÌq00°E,;"`Nz¹s ¦Á¿Šó©ⓚÓÎ[†àZ1³†%ÆóWñ_‹è\ƒÿZ”BÁ/@þ[/$Þ‹Ä¿<|Dÿò uîø—¯{Ç¿|…âæ#þå›ÑÆ¿(€‘9­Â¢ñ/_¼˜zÿòõ}•€«e`@ø— ²ŒBíl\Üþ­®Vÿfíþ…ï5Z€CYñ߉®ðï`æŒñ/6ÂÓø·nBž”ø¯ö$þ;Txв¬ð`€B ¦}濃&-ÅZK-þ‹xh´ˆÿF1ÿEBƇÿÊ5æ¿¡'ÞüwÜbOò_|Àtÿt¶,þ;8Ë3ÿÅÄogþ‹tl%þ;h_üOúˆÿšÑfØéÎZr/þ;¸Tü€OñßÁÜ#óßЋ¬øï`­ùoðÕfü;X•Äø—U$SÄ¿ƒÎHÆ¿xà€J˜þ†VL¸ÒýÅ(¹jfú«›Vô7&禿¡ºé/nüš¢¿Ø9®¹èoÌSχþbï¸8¤¿hÀ#ú‹«E&ýåƒõHÛF¤¿:Ñßв£ñÏQã_œÕÄÈÄ¿YøWOžø/úäÝ&ü‹a>ô7ðBúÅŽ[€~1Ä1ˆ~Cbô‹ óX4 ûÕo ö«KEöËm™d¿¸0I_ÿŒ3œñ/ª ßüÊmþÅ·ùÙUÀ‰G“s 0Ð ü"ÀÂ'à¸\ã^Rà¥LKþíRàõ•oeãX ¼/ZtX ¼åâe¼•PmÔâAA ë‚@£Ž!pÊ@ßQVTÆ šcEilràšVÈÇrà)ïë§üö¬ê]Zz`Óœ_zàaQBzàá9€ôÀˆ¥©;õÀÃWGz`ÔuÅJ< VÒc 3é±/–¥ŸlèÒ·èQÁ‹S<|½¨Fu؇ ÐãÃßåáž Ãa”‘Ë£ †Xûî²K!òäž9ðèà¦S eYCŒ>ÇŽ‚)Õ2jà±¾¨L™§xôJ†j.óV("”¶@ðŠ™‰Ò?¡–£¥fvC]S<ºì%š­S Œ]ÕA€x”ìH50. aP ÜúP ŒkÎãxheÞrà12?BZ` ò옛|(0Ïh‡À­‹¤@Ž*ðèŠ!xh9Ý:àá%(ê€GÑuÀø©'™0uÀ¼èBð(’:`Œ; |'…{Î#-ú‡•QÕ8é€9Qýè€Ç« ] !Õ`í@Jà¡€ Y74G!0w…(¦l 1 ÐWB`ìê ò¥x¼ ø•œcƒÀµ'™›K<®ã ùøï ¸Æ—³Kû考4?:`T¢Fþ‰tÀH¼>:`¼ç€ÕÒã}INŽÉ»\:`&#âx¨‡2âLþe¤š™™%™‡ Ûˆ‡ÜF ‚‘"‚~¸ ‚]yï&A¯A˜»œßM‚¾‘M‚—äu“`„û|IðQ13“à#uS xk’h¼)h>ô#,4Æk"ŸAð>­O-ÞHTn`+¼„À‹CŠ/Þ)yi>k'K$–¨Ëe1PËXÒý·¤@Ò?23~Ââã¾Ó8ŠuBÀpBPõSox‹øˆ€MI¹FÀ&26™Ä%½nÑ Ò Œ€M5?Œ€íü *íÈXž"À¸¥Aw"@éM€Mi¸&ÀÕçøÊ€ü” ØTH*à)1Ä*` t°TÀS•N­žJF¶ ©¤¿þº‰€§fã«ÞöxЊŒ± XòtÀ­…À ðãIœS¦ìçTœ•ù/V½Àšâ¿ÈðŠÿbáãH\ãÐYžüwÈêÃüwÜ.A þ;UÄÒüw8"Süw6{1ÿ;“ÿ"Öh—s˜ùå¿ÃE’$NWZ–8_Ö¡8ºí‰ù™š—ò‚ù•šv—3‰ÿòwP®+?S¾êÀÃ&¡ÀCåw$®‹Ä* Àc³SÉÏ”VÁŠ,m)0R$Ñ")pºÖ‚P‹£E€‡e$j¸ P+¾=%Í€~+Y œ²Ð´èˆïRUª”@9Ç—¨`;+2.³ÏxSJ iÒR T:`WŠŸuÀNõcÓ¥¢Xôbƒ¥ÀþXøã'ª«¨˜¥À®"Ÿ–_e)–(#KÆ_K]¾–£àZ$vyUH |åIf)ð•Ñ•´ÀG‰ Ö•õ°xÓÖÏR ãv-:xÖR`̨°•¤À¦Šž–Ó[䯛sAt‘J v% Œ/1¶’xªd¯¥ÀS!¦@….–è—‡)ðràPô±!08p!p¼¬slZ!6Ž÷UÌ(!0N¦¤ÀºîÖß&t$F ŸÒ_êÆO|²$rNéJ¢BêKè¦}q÷¨å@­åÀ‡n£%¾"˵#É/ÓðK|X¬ä@°åÀ( æ’øŠu-z_’µFXrà `«^ ±ø°|{©aCÜ£øHt·¨ÏP©ë”ø"î¯ÄÀG‚ºÅÀgüŸGl'5P%Fi»_þ eú”øpVz ‚>¬>´×/=ð‘z.=б«’ÃjÙ™ÞCÎ,ˆÌö¨„©bÁ—t#¼dñi|õ ÆÌ|&òÀ5 FÈÆ‡#Ä¢„X0ϘdŠÌ^8T5˜,xEé^Hi„Á‹Ð‡0¸)8„Á\†¦j§ÌÀ~bïÜÀ)ѹÎs©ÜÀ¡D?æž2Õtr XÕ¹ªf1Pˆ›85ŠÄ@ÍsJ Tœ”µÀ¦²bÖ›”¡Ò/Á—´ÀK%3J lÊà“xÓKÅ(¨øüBÁ0pÄáX TÂ^IZÖ :KÈ(x3 xËñÄx2{§ÀðØ¾œheÀ xé‚—î ‚·u%:±ÍBàecl —m¥.ì]0•À˾´R¯^õP Vü©¤@ïË$xÝ®°Hô¯i¬Ú $Aç±I ¼\QD$¸ºP?”h}ßZ`¸ b`‘à%Ûp“`´üúë&FÙt^´å2*÷ÍØdÌg1°éíb1p= ¸Ñ­Ê ôÀÆxiËM:Šä@‹C–¬'9°)¦Ñr`cé7«ñöA©‡¬è¬:²Ùr åËNÏ´¨ô‚’+¡Ï1¡ª¬e=0®Ú¯§â-†cæÎÙBÈsHèT ©BBÅÕæÀ–ÀFJvN9öVL¨N*&Tq"Ú¾z`ŽŒ;ß è¼íŠ íÒªxm“ EN“à#Û­ Umª •eE…ÊStT¨3 ª\ËŠ ½ÉñŽ Ub¹IðV Jé‡Ê“˜•‘³E†ê§Ù#Cñq³ù¢y|ªUËŠ ½ àt®´õÀHNù ‚ú~l‘¡,¶E†J”° ¶¡ÌÞ÷­(žüÑK<ÏQ‚à©q%6§ VdèC\@H`†²¢hÉ¥*=PãZ<²_rà)’°¸µp™U+üVÏWY€Ž Ê&´È…ÍM äjOÅ…ÒN¬ÔÀCynROºí–X*£ãB¬Sj siJ tŽg……Þ”/-ž§ˆÎa¡ºZO¡¾Å@ïJZàyH²sXh—6)-ð¤9‰§Ó :†…žb<‹‡8@bày*YOb ƒq- &-®×ññáÀ8¦J <”—j1ð4ÂI \»âV7f1ðpR¢Ä@Ç[ <èþYbàÉJK%:¤Øbàa²’x2‡¥ÄÀù)Öõ˜Y ôÁH <輿IUKÇ£ØQIñüµ`Êø*ÇóS 5 N$K LOØëÞ·1½_%ðH[ ÔBö–ø#ty~”À¤þ„†Öók)æ„[hè°š\åÖ¬þøû¤ÝésnVBjÙÝáþövÕK}þ5W¹ßï¡ZþöÞ%YwÙΜÊi–:a$Aâ1ŽƒL ¥ÌnCó·¢ûz8¸#"32ëšJÛŠØ8 øøùÀ‡å¾¼×~îãm-å¸Öh¸å–m,¶mc¹¥ÆJ÷ìçsæn©±ÔVcUË6VÖ~ùŒå–m,¶mc¹å?ÛU®Å;>®ñ¿ç*wÿ‘«ÜùüøßŸ®roëóg}ádtÙÉèn‹;­zw﫟7qÜž9ÑÝ;y(Æy¨Í0ÎC¹—†Ú:i¨2ŒÓP»aœ†ª^jïä¡dç‘Ê2ΩƩ.Ɔqg3Œó@¶Nʆqj3ŒóP¶NÛÃIÃ8 µÆÕ«D½8Ô¿ã*×Þ÷àúÿr•ûÇ®råSðG/Üß¿øÿö^Þ{¯?zJ?Ö¿ìÎÖâåø~³ÿº³½ïª}Ëÿ¨æØè·—tæÿ3«±,Ú®nÑö^¹ÏLü³伸|FÛëó'rïDÚõNF¦ÚS4€EÖ‰Ÿ\®k×Èüî+êAç¢ä{årÚx %½óÒ‹2ÝZXöƒarïíx ±¼?cΣޓ¼ ±HzÏôˆIu¦’5ôA Ôœ\ç”7mx0¹fpà{梑!¹"òv9€ÂS»zCc¹*?BX—óIç—7RÃ{ß“G¬àqÍâýs`ÕªwÝXµŠK“}nT'xÏõ‚bö¶d©É~‰ZÎ Ü{Ï~€åßãO§ñvrv ;§è‹hZ2n¯Ðult§¯^;Œ‚[KŒ.‹.líî HíT(ùÛ’!³¹Ñ‰abY-‡¤U·(±ØÒrˆËí^a3—wOaeâf»dðò^𘨷¨‰‰Ÿà93?ä½XŸ±=ˆÝL¤\GhQm$®ZÐ>ú´ŽOM°Úsg0ç{hßOµ¸°výdÂòû“ŠÞÿé¹l+Íö42ì#ûà×|f®0äÏ~ ÏÌ¥§w#f¿¼Ÿ·žḴ@Ñ(-JW=i§väŸç ŸÖÁX̵óŒ‘*L‹â°ù¡VœD˲°¥Zh¸³œpúáæŒú±Ä|+j­e1®tÒââu‹r)× ã¬œö·0žî¾c ã¼ûˆ%æXÄF—™umÒ[+×®[–׋Ë…[ò:D‘äô²ŒyhសÖs! dÙžñ-üÁqaV,[X}㩌zÁé®sŠ m¡‰Þ7~¼©SM§Ùî92J)o`Y;j¶MW‹ÚQù”žŠaÎòQãf6úD’c|Á¸þ›å£ÒqîàDâ>Ÿ'e ìˆc3Kè¸#¾¦ñ¶áŸúš²ÊR–ŽZÌY<0êâ×ôà×4KGå×Të]Q: "ÐÉb'Y<*žÒC®HwÔ\>1ˆ.¾¦¸Ð¥ ºÍ-µÜøœÆ}€.jG­‰ÜñÃß7´nÕñ9=dRµ£ )"=ËG¥dÛ Üé0ú Î5Ü0”¥ójµã¦`ËHœ,• Uʸ¾ãí _–{ÏâQ'9[µüœfTfî)<4a7wógˆÚQ3UreEé¨xJS6Ç5âQ¹N5XöùޝÛEG:t¹Ì•ÒLÞfÇ2U,úã¤V~L³%¥ÿûF=–Z&Üæ.Þ7âæqÀ9p|$¹M~g²rÔ| ÞäË(*GaU¹S!ËÚQ0a9©·¡aUùfmð¬Õ™,51NŸ&Vþ²vÔÃËãÌü îç°² DD{BÉÚQ¹¬<y˜µ£½kpÌQ;jfVKŒÚQ´ñáÌ7«GåÌ7UÔ; >ŸLÆEêQ˜÷B"½ŸÁÂÛ<ù9ÍÝàðÀö‡‰„Y8êæBÞNQ8*”;K‰dá¨Ö±º¬üš¦‹Iª?Q7Š>ôÌÒQ¹žÜ¹¶~Gá×søt¢nT¿°üÔQ§¹`HÊͲQOcì'*’æ…dÄz–ºiÛ‡÷W”šTÜìªçÚ}åQeå(Z”ðpçMé‡Á¬Y8Š.O‡·V“È€ Zûá-=P=óN´héH×᯲ó=qòæÓ‡ÙÌwSœ(æ{ð2,ä{†6òI-äëLã7ò ™[ùbþtòEñ2B ‘/üÕ‘ï Mx!Ÿ2dŒ|a€i‹oÒÍOÄg§4ß¼i¡ â‹ÙÖDˆ/#Ð"ÞÀ#ÌÔI|×T¬´ˆ/ƒAq$$¾RD|¹f+Câ+QKÄ— ñ¥Ì‰5‰i{hñ¥!¦ºD¾”o1É"òÁ, äK úÄÎ1«¬›]È£Hì+‘/U`üD¾|=f 1‘/Ó0"_n»øR` ˆ9¡;ñÁÞàW^hyø’«öPÀM _¾Ïq%ˆ|ñŽýU¼—ß,ŒÜ«/Ÿp/?t8#â^mH|ùIÅK⋌ LÃE|™](ñÂ{_Ìb@¬¾C‰l¾˜Åà'ðÙÚÖÀwè•dà;¤Ì›øbQôþ_–G˜‘øŽ‹ý&¾ŒÐÉAÈwH÷4òÅÄfð€|q<ƒä;”u$ä‹îj!ß¡ÌD!ß¡|1#_èüh²øÅ$¾PýŸñ4½6ðyeà;¤ÿøe)ø¢¯ßq2šØÀQH7ñîâ\’оø°#æ;”©fæËð óÿðòPð ,0ðÅdëy>$ø2SxGà‹û79/#±¼Câ˯71Ä—}°€“B@!€©bhðeŠÈ³_ÎÌ>À—-xEøò#ŠÀ—ÑÆ–‰'U×BÄ—I"ùóåç:¿ðD¾Jå&ò¥û#&$D¾m…|™vÜ1,¯R3…|"ä+{31_Ì&~ðU"«€/Os_š÷`6Oâ+?6´~P!/[0}#òÁGíWŸÅu_zXå‹FÀWŸ4_©Å–7#viàè^àKQú|°NB‡Éé,ø®¨ìØvàCŽI-/]PØÉédZŒ¥°ˆïŠz  Ä·]N,NÑÄ—ºþB_ž&iÄí âËUlPˆï=-¦c‹ø®ˆýÂ6I|™‚ù'‰/[ð#ˆøæDÙL_\­….>gøf§Õ‰¯†!ðEf¤">¹Áør"D¾;™OÂh_l„gEÄ7åÉkâ‹7Ûõ!¾8‡lâ›2D1ñMÅâ‰ø”0aà‹â/CnP"/ú/|S¶£¾©?_&à€ |ùÇȾ8bܾx¥¯ðE |±~Ÿ“ |‘¨´{ üUä¯à/ßQxYþ²á¢üÇÊ“µ˜ûõrµ(øó[×ðǰق¿ÚHðw´Ÿð§È䂿è'ø“‹mÁŸÜq þŠW ¶K5üÍRï@5µþMÖAý!`$úËt (u¤¿˜~Ý»à—³ÿƒ<ÈÏ* %þ¦åÁ_d÷]ðKd8wÁ/ a~ùOÎŒæ¿)KJó_€øoZ«ÿMâ é/+=`X⟼×uÂ?9þþuÆäÿ"Ë•À(ücBdÑŸlðŠþ”ÿ[ô×¥ÓšþTH¨èO©»EV{L „)úóäßô÷^Ìö¥¿A´¢?k£¦¿HðAÑŸò¬M&ÓŸg¯Â?ËÆ?•l(ü“wdñ_§ûtñß³ÈvÂ?U(ü{é_ü×ÝGü§ê@y[v–Ó(|:`?0'7ÿÅü¨$þ³º$þ“ádñŸJ*™ÿ¤iF1®_;ÿ™!̃lŠÿ†?¥jü½-ìcø£EGÁßÓ„Œ‚¿‡7óê þ´ÆUð÷ÐØ£àOˆPð½g‡?ƒ…éOµNM¾L–fžþýSôw/©“¿Ø3ŽWø÷ÞN<áŸõSãßM'¡Â¿ûþ!ùÅ85áßÝ„Â?Ç,úSÞzÑ_íJøŠGئ˜Qh½N¨Ú±E€!„  ðݦT¿h™?öM€ï(ë é)øO¬× }pÙ¡ÏkÓ†>­_nÐGƒ¥‚¾H‚'ê‹»óßi?‡¢¾G³Sq» ï™‚5‡wÒ}²ô(èÓã_ÐWãHëÓš‡Å¾ÚHbŸe%‹}¬‡PbŸUNˆ}^S¶Ø§û¬ô EBZì»(唨Çlû‚¾·EÑœ„>ÚÀmÐ'MÃÐgµÇÐçZC_LÙ°ÕF} ™û†”¼Mì£h(ì{·ûXÃ¥ÈO„Tbë nä·ªiòc^|‘ŸÙÆä†¯{€gnµ¾rßÍ©Y‘_@ÆŠüôj)òSÍ¥"?EHù©êI‘ß;ÂM~Þ»ÈÏ‘Ì&?½ÅL~t¨ÚÀO§iðÓ;u?r•¹ÏçdîSfpqŸJ°÷ñíSØ'§„â>_sŸÌ׋ûî¦ÈKqŸ/ŸÁO»2÷ݯž¸O6ýÅ}²F0÷é¥[ܧ’⾉…*c_£ÓÓ†}ÞBØ+/a_sô¦°¯q^Ø'c× ûŒÂ¾GØÐÉbŸWA û¨?›úª‹¨¯ÝŠ%õ-ù§˜úênêÚO^ …|2<(ä ÃDT ù.ødñY-5ñùeä“A!ßÉT!ß©y!_–6 ù$bmÈÇ9þ†|Cò£‘ïTIËàW F>VRµâ§ú-›âÇôÊRüŽCœRüÎ6-ø‡XMÌúZÄ|‹OF1ßÒd¨˜îÅ|ïýUv3Ÿ|dŠùÖ!ÂóiIvc>aja××Jõc„©©O ²¦¾Ñ¾Qž€Kì(©o^?E¿ø/ŽMا‚äÑï¢ Hì“ya õ ºÁõYI2õ¥Ëb!_Ô-ØC<³bn!)ÕÄW]D|Q*  ˆo ß”ÜGcÕ>yæøMG øäRÀ'[·Mð“ŒlàSí²"¾AÚø$b›ø|ñL|}Jª³ä×j⛿ýPüè]»ãKðS_ÌTˆ€>™DðyuÁ‚ÍK6Åï¡ÖTŠßÃç«¿K{²âw+XSÐ×™½)~Ì/è3ЗâפH úTeSü¤†ôY»³âwP;2ô™ÎKñS$eAŸ¹ ÏZœ ¯S¿3óÍâçß?j„B¾‡eÈ>ŠhÉÈ€ 2òÑῈÏçЛüXl~#?uZî»icò“ke‘k§ü–¼“ ~K‹&¿Å<:a_T³&ä! !ÜÑî=Ä3­ºÚžÕ‡"=¿Šú2c`ò2 át|©ï}O^JóKêkñ%ÃäBI}gwg$õ]ñÂLê;åÁ餾Ó;VRߥ 'õ…ܽ‡x¶øh‚IÔç´4gõ¯Ô×ÂóO'õõFPVßÕ™Íାë8„kÌê»­ˆ;«O«>•Õ§R¨ÎêSI4gõµÈûeè{, †•Ô§¸+'õŠßrRŸƒu•Ô©€à_gõ)®ÊY}?ð•Õ×.Q ²úŽK<§¬¾³‰•ÕךøRY}ÊÈ©¬¾ƒ6+«Ï7’û.®š;±/æ‡à7%öJ2Ubߥ¹¹û—ÖçÙ •ØwÒkÞqž1eDÆyÆcÃÀTÆyÆyÎofßÁmeö9^Й}28ªÌ>G_;µOEçyÊc³Rû䊳¥öÝŠejŸsÚœÚNdļŒólCVœç¥ z^¬¤ç8Ï8Zã<›Á@ž—JD9Ð3™}MñwôŒÓ~>ž—ÂÃèÇ,D¬gdŸ!²—±ž—Š:Öó’çŒb=/ÍáëyM–¦q¬çULî»8­ì¾K–¾Îî»T¥ÎÙ}1õ¥NÇì¾+|<±/f÷]Åd÷…ÏÒ7»/úô]ïk—ê×8»ï’ܬ侫YcvߥÊ%JðKcNHwJðSü²üŽ©˜L&ø%~™ànW}g¿|‡Ÿ;ü½ß‚KЦ?ñ€üTO¸üÙå¿{rªá ¿G©dÎðk‡òù˜àwÑ5Ù~gÅ]2Ã/,Æ0°2üΓñs[‚¹Ž ~‡Üøœà';õJðSùw&ø ®U‚Ÿ™Ç ~7ÓA*Á/n•_E~™u¿¾ù}¥ž)¿O“‡-¿O3b'øiÍ®üTe¥üœ]è¿÷ú‚3œà6Ø—ü¦¤D%ø©P¬üTÞxKð;´ÌðS~ªüd%ü{»°VŸð/#ÖÙüËðî{Ç¿,©!ô·/éæúsÑ_öi»Þ—F³sOñ«xtá_•¿ÿeêð ø—ç97üËÞå¾l n1Áo=JÌS‚Ÿ¤{Â_&x{¸gž#M•ßçUç÷©ÈZå÷ÉSð—¿Üõ¿çú„{ÆV ?U~¿\•Þ§ÊŸ•ÞçÕ§÷-¬WvŸrМàžX ~‹ggøEY8 €\MIh¯ÓFwš3üT'¶2üTn¤2üT ·Rü”Jê ¿Å5ùÊðSuáÊðS»JòS†¢sü¼Tå$?/U’§H•ä7XÌtKò[ÚJI~ha’_ †Q’_ŸJûc’Ÿ'ùÉ©¾’ü¼Èá$?/°ìI~6G¶W{çÇëëpÓNPž:jÙmÒþ|»ê¥>ÿž½Úï÷P-e=ösÿkk)ë±'áô3–[¶±Ø¶å–«Çìüœ¹[j,µÕXÕ²5h^c¹e‹mÛXnù϶W{‚#âÿ¡½Úùç6h?íÕþÀ'í?Å^ín‹™v±» ÔÏ›8nÏ;—â÷^ËÎik³NóXîå±¶^«¬Ó4Öª—ÆÚ{y,¹§y¨²OóHêãªÇ±yšÚÜÓ<’{y¨­—Dz{šÇÚìÓ<–{y¬­×öˆÒ>McíþiõBQ/õ︬…ãåzg.ì²vý#—µß݈ì²ögÝ~º¬ý“áîÒí§ËÚ?Ûmÿ‡Óï]ÖþÊáÞ»¿ÿÿí¼Ã÷^ô°þ~¬ÙeíÉëöÇ.kïÕøõ¿ÿÝhÿÌjííü¿ÿ[¸À¿·Í:mûçÑtmküŸzÃýcÿµ'¬zVGêý]f~E¸xü´•áúù]IªÂò©e^ýÀ¼ð¹ÌywLÀ|âÚ…î2TÅ÷ ·¡^˜Á÷6¤ž)ó9KyîXsË”ùIósß7„—›êŸûɨïZw[&•—ë7M,:ÿªAÏýÎhríYÅž;V!†b dOg|óƒý¬N¿fÆH¾SÔ†™÷Iü}žŸog4¼-fÇmà#ü<ï'gÞ±:ŸûÎ/% #§ò¼×/¦½i¯>±Õ=é¬Á°ÙçyL½ß<áæyù”6 {çÞSû“sïÎkñÌ\¶ÍYrCËjIÉrzúq0sùâÀ=!”°óôóaª¡OY•¸²òÛÁÔeÆý¼-ƒ”|ñ‡ëwÆF&Ÿwì94‡ñOï(¹úôô…©jOImöYX>xú¼@É L|[(ù¾uNk êÇÂïÕ»AÉ2£F\?éXoKj 镇.×`ut.O>#,ž0nÇ6wªiY5|±eýÆRèy!±$$3æô!öÅ…HõdõÒìr¹e¡ìÇÃb”ïÝɲé‘(ìcœøsžì'#ÌÞ–@¸]…({“„4ý+ |<èÒ'!™œú¤ØŒåƒG<k?Ry"œB•Ñ/œçšxT…‹O:‚³VG¢Ö“nßÙ‡ºË“e·/Ü×)~<r%³?kvá`ð*Œ¢Fîk¥ŒPXôBËÄsª"ˆOrÙý« q<ñ.Èç4ÞKØ×‹–k'¶ +£_U[≋ôБ!'[ïƒKâÌ÷J¸¹È“ŒßÓö€Ö.y,=ŽA ƒ´ Œ¬|×k_WÇ9]Øê0%WyªwjBòjÚª_€äÐ-Ïlœ¿?aÎèz¬¼={ñ‰÷Msƒ’åîÙÄ2Kµ>\'éYʼnW+OôÄŠOú|äÅêYĉaI¹*ßO˜ThX*NIɼ‰{qbv[¢,ϯªîÚOԲțã>Dù6öeÓªpt¡µ¹4Ù³ˆÍÿÕ‚¯êb¡«ž5œXz"?³=j8]®_®ôô\*fæ|aö¨át6„N%ô YQH¦Ç8ífZ×¢{qZŒ^bËÄêRå=ª8eØý½zVqz°Xkkí ÁKøí²ŠKOäÒD*N;¢ÂسŒ£´r…ÐX‰0ùÕïYÆ©ãøràûŽk‹êYʼn…ú4|V#9†Ã´‰"ezšd¶ÏF¿ªþa¢ŠSÖ~œŒ2ì­ó«ªÊ =«8Ý8œ#φZZ¬yÕ³Ó³EE½-üåò¯¬âô ŽêFËy1“*LÏ*N}ôÁT)/ »¬âÔ#Å­îË2¸·g'fîOŒó <¬ªOÛ³Š3ìñcÞásœ|]÷¬âDë[ÜlQÅénŸ>ëF59-öõ¨â”O«Ÿª¬âĤY¼²ŠSÇryªG'&åb~Ï*NÙeaâÒ£ŒSGì~„¬âÄ´0\¯¨â„Ø#šô¬âÔ÷ëUœ²ôc\eì{tÄ)©·G'¸ ÃÊokÞ´x‚¯_e%гÓd\^‹(䔓`¹Ÿõ,ä4÷߯_Ëv }ZÇ$˜«®= 9e`œ^wQÉéÆžöýL&†Ñù«G%§†{=+91x®aÜy2/ìæÏ™•œú¯2^èQIàÜÝ.zVr¢žúqž $ô¬ä4]–ÃD!§|Z£´q6´†ÚòfèQÈé"سÓÜGyj=x YÇiýª"=ë8Ýx sNѳÃã2î©\ýJ£ëIk\?èªBÍZm¶è©Ñ³ŒóìðÊ géÉ<;ÜHYÆ)û`“†ë”ã–..]Κz: 0Œ?¶8ر‡Õm#À\ëß P±2jng|ø¢/ôÔÓ¨ Í&À¡PL#àÐå0Ú}Í8drZ¨/Q! ›Ì€ÞГŀ‘B2Ø€U„}a2 “ÌÌ€Ž z":tÑ h”bÀ6 5é*TRp!à}p# 2»Š=y7vÖ^,T™î"@™ŠszGž¦È46TÊBÀ›Y! £ê‹™P(ƒ‘@—Pµq åÉY €] 'cÐ €§|¦ £îÜãÛ ,#ÊÒÜüwž_Wóß©Ð!à©äsà)Ë`àÙ˜ú%t˜• ðTî©0+]å c~‰H€ç}²x*EÏxÊÑ xÊÿ× x*êÓ xªJœðThžð”Ë©ðŒ(T´Oe׈S¤ÿ0`Ä`ß@À÷Gh\ò!ž2ž3žªhÌi?NØ)r…€rå¾wÀ䮄€çA1ž*;e Œ`5)ã`dPà»w&‰ß;Ûì( ”€- ,“¸¢@1““αöf ”ÉzR îjÐ)ðTEQ້¾ü¦À÷ÆÁG’˜k - À|6ñ‘$füfî¤Àw«ñ¥Ày¡˜&Ê<`P`†e`jB Ì7CÛ)0O“Ç l‡‚Ï…íP¦»00C3ð©'æÒÅ ®ß«q€&¹J2?¨pFa`®`XP`‹r|X•[EùŠLìV-WQ *·îX•H…ñI1Ð59E0ÄFx=aí$ Ì”¶S`!0À,€Àâ_E€ÉǃÀ\ó'.&J*¬PŸ`¸,cšnœLW2.U‡7†— îb!`bQ`[˜³™cu§i l—ˆ“-h*Ù̸²"Þ΀RÌ€ÎG3Æ+GCŒÅBpIC®ƒŽQêÕ&Œ–/¦ñú—‚s6¤ }1 Ì€©8b2àRÀíÆ€\/”øÆ€¯?3 ¹Æ ß|ŒL\*^aTíðâF:ðl¿b@UTÞèÅ€*O[ øîé&ñNÃe.ZÜÒŸ³0Î oþbÀï(#àÔ=+¬ë \ªŠaÌIÁ‡kåB ¸#G”¶] ¨PZ3àÂËOèl>࢘bþ‹†‰„€ø4‹ÿ¢£jÈKâ¿Õ1+øœÙ GÎL6œzíc×!`¤.…€¶q1fŠá£sn!àbµf`ˆj˜¸‰c)m}0^ë#.UåÆëîþ }ެ>\óæ÷ìøÊ€‹¹ßBÀÔ¨vL ’Q8„ÌYº€_jhÔYI€ (ï@€í4eßùôÉI$0ë'A¡"f ïEY0?U-æ ˜»‘ ²‹€‘°qDÀKÉÉ@Àˆ‚æ ¯‚."`S‘3àµná!°5¾ MÅK ÏùkcÀˆÅ6DÀö۾‰€·Òd€­a,0j¹ºH€ù¦à¼}c ›rPŒ€ñùO’£’ŠüýÞJýó&Vÿ"Òš¡Ô?žÕ¿Õ$÷™þ´¸cPÉ­%.š·mxbRòOœÙ úf&!îÐ×nÇy ú\— ú´nès0£ Ï1 ù©àˆ ýTŽMQŸViŠúÞ–ûú‰‡°Ï¡aB¾óü!úÅÃþ ü<éßY‘ŸH*Þ‘/>.Õ/"q¾ª_¾á~ò!8]„|kšùºÞò½‡y|‘ïT€ž‘ï¼*ä³Fa仆"J‰|1/µùÞ­1{'òÊk5òë–°–iýZÌ*äÓkÏÈw*Í­ïÔ~„|—œÀ|×ÉõU#ߥ$<3_TkÅdXÐwÉÂÐïâTÒÇCè‹_nEèó„ØÔw=L­6õ]òÌ4õÅÞ)Ç‘ú._uRß%‡Sß5iþ,ê‹ÌIìšÐ×¢î+øÐÙ΃2 ïälÐ(Ã&õ5Í}M}™º$"õ9½ÝØ“$ð¹°¯á~Þ°¯ÅÍÿQþ.½¿}ÙÎ%üÉ»¶ÀO’þTî¤ÈOd“ßÉ‚E~i×Â_<´Vàçõ_´Œùz—ð7ãjá/êPBi#ù]Š`øÕâ‹À/föØ·¸ïøD~FVñ½G~¦s%óäGÌw4"™ïô+™ïT¡‚’ü¦bÅ|± &{f¾óT ™/~‘þ‘üâÐ?Ìe_)’ùâZb æ;UåÓÌw:2KÌwÒ:ÃÈwÊÉÖÈe‰|‘¥½>Èlš#ñƒ•ÃL|g¼>~mÀçpR_c9a_x·bXé}Òs‹øNš9•à§ %ø-I7ü.¾"Šøª^Ä'kÖMðc1‚"¾÷É ¾'âcÕì û”ùz…}®)µNaŸŽtاW ö9Q¢Â>UÔ¢ŸÜ§ŠøÖ®.âµq/ ›ú¿¨÷-¸îɬ³p/bx¾¸wòÇ5îáyÞqï2# ÷.:CîÌq)ÜS·-è³)LU¸§NÓž–ý ÷ôÊ%îÉq¾pïý/xиgMÕQŸžZVÔçñ3êSÞ}[Ô§$tG}*ÄÀ7ýÄ;ê3}v6Þ›*¤¼}®AŸÚê O‡Ø‰÷¦Ê³UÐgDh€™ô){† údÁ• ú¬ØL}JƒóM¯×8èÓ¡¬ô©Hô ú<ÅŽüæñÛ½ïâõ+½ïü¡÷M•Í-½¯6Ç|.ÅfJï«OÇ|Ò³ô¾Ár|ô9hZd½O9ç¥÷ίõ>­¡XïŠh7÷ X*ö)O½ô>Mû·˜Ï‹ï1sŸß{Ì'$hƒŸrη¨O­/üÞ­³PQŸœ7ø ŽÙÂ>oR“ÁoÜŒ§¯°Oo%ðS¶½Â>é²…}j-Ëà§8¨?ùø *X~CAùùÉâŠ~ãäcU‘ŸÞÊ‘ŸÌÖùLÚ ±¤û•¿»»EH×Mù£Ñò¦üIr2ʺ³ Y6fí˜ÏC1¤bÀÆrw…¥;|ª‹ÃÔ…:£TK´ ‡Ž˜_á¾çÿå÷ýa¶”¿S±•¿ór1ðTQž’þÂ,ãOúȆ');b॒'ÆÀ+Ò&ЇxÝÖ*¥üu% /ÁÃëú``¨m‹á ¬AN$¶ÎbO¥üõÎAR`Ó“UŸBßM·V©L7=~ ÑÐ?Êß­)€!ð¾žx;–RxË»”¿‡~t†À[•ìJús¤ 0¾’ä.B`œÖWúÔ*­üi-ÊŸ’/JùSÈ)“îF¥üÉݤ”¿9ÅŸ’þQ(|§÷YúÓŽ Æy>2™2>ò*úH¢B0`|Ö)ÊIú³X)lŠ`%†”Ú>ê_[o2`›VÉ€MÎ5†À6fJ +EP•Ä?9øš›“eÅ€M_X3`#¥”ø§H3`ó2а…‡ å@@ a ]äŒ1§L÷6Õ3¾wßí/ÆÅRfr`ób·806A„8°=|Ñ™[&ù„~¶þGÆÀ&;+c`{&…5aàû³àŒÍÁdÂÀæÜ4a ­KúëS‘¨âÀõè´$ýéeXh&1N>§¢8I‚"í"A#‡HðâÏRÚŸŠÇm$ÈUŠ"AG  Þê#| ö1 ^ 5 ^fžJæ3 v…h›Ô@§~„¿RN,üŽ 5 B-ý½;ï ²pÏF‚4ÀÝòÿ˜‘P((k¯-ÿkd[úßTZœHP‘ù[úßà„ÙÒŸw% þ¨qÄ?’ êÞ ¾ã>õoÒÿ«@ЫWA+Ñù©•“àºèsu©“"Áø8ƶÈO¼iM‚ëP §#?™µE~ À÷ì?œy¥ÿiyÊéçï"?RY i‹üÔS à!RuèçâM[¡Ÿ“GS¡Ÿâä ýTÈ·QÐY—¥*byþl?«¥¢?Oôg¥áýn+ ðP(ªPp*:º2ÒºwJ}Ï(¸ ‡BA©å•(þ® À›¹2;“à|¸B¹ç~APAºæ@]‡ÍªmÄDîc“3c p·´bÃn¸ö§[U'uù÷|ÚFÆqì;¨–ò0S[ùUKy˜Ít¥þ¬[j,µÕXÕ²•ÀŸófÃ6š¶ÔðŸí«©‘-®Éî«öÓêéy¥M¶>Ý~÷¿gq^åÁö¶^a3 u ýþ–Oáü8@ý¸ùâÚÅŒþÓÇ#Ù:Í#mÖiÉ4ÒÖG#•qšFÚÓ8RuâH{$ã4TÆiG]4Lõð(6Mó0›išÆq' ´õñH¶LóH›ešFr'´õ©çX†ii7Lóã¯Néß1U ëíy<ÿeªöÏLÕþ»ûo¿{ÿÁ«úoøpþ|}ÿáÃù»‘þeCµø$Ͼþ4T{ßWd¨ö6¿[Æ¢öø¼(ÿçùßsj¨6¤gbüùyÿ ÇÓr½.Ò-ðg֋ʉ ÕHÅϪ‰0BxÇJÇúk,’Øxzê>é¥v²eäôX‘#Þþ'Sâ±ßw6³Œ‹kæï×,Õkjòm¿1E>ç°ãå|ÌŽ•i6úyav|Sgz[²6iÖSIkôk°ªÍ…ë;»1;î{x¯Æ…Éq'@½-ø\»èÎxçÝ”I,CÞoÊ$,@4úÈÒœƒå4òmYL‹¢Ùè³sr|é´VêHÊCȾAdÖ@ËúÑf8Ïñâx¶þ±dº(½¿èI’ebÎÛ²§‹V{OÿlõdÜdâYû…ô6†«t¶L l˜´a«Ñ²ŠI1S˜¨yá× ”eDåˆ;h°øw~EFx(œ*þ·ßŒàIVcÌpÅ:“d+d½-WᦹÜòî;ãQ¹&2²ˆèƒeú„èAd9ÆâU} Ïç‚ðÈÒÇ'öÓ0êhÌb¤Ä]-YVQß#%FÊÄx:ÒåÂV80+™ù‘©øŽdðì3y–i³”}¸aÄ5I–½;°F&q‚ï%J#b3Šõ¡¹Í<ÖXÄ©Gpr–tTnõæ“Ë$¹®8R]ÿ•[¸±ÃûÈÀ`}Œ•Yrå”5Ò¨;7¢!ØŒÄÝû܆™i…Þ7i~†E_£Ës>®3ŒÔÆø´DZM:2Ïr†‘^¹aœðùjès`«gñye>ûLø\ bÐNû¹ð¤¬—÷vbáIŽz3¢.sm;öµ:%Óíyæ‚C“Ú<Ï“Qç$g,Ð]h8Ðåêx^µÖ8OT1Ì>h¸OÆœS]z[×7ÖÅ:ô¥†­ !à4Ñ'ÆÆ¯JVž'ô€4æ8Ð2;W˜'Ü{òÄ1r„O샭2dîæÞóG¿bmL–yq®«áy}/ÿ…qòŸ,S3³\S®ä¡HÃŒº\<ò¯§áYå:ø A q´Ü›Y©‰ùÙ¸¯2çÄêàƒC.ä('9/ðwv9ÑÀi?¹vF¦|Ne§7³TÓÀŽò¶Ÿ X†¨tô¹ðQÌGnF œ|Pe#2³VS^%Èφ(Bì=Ï©fCé¶&8žõ…VöH-tFµ&6àÂd±¦Ž<^Q¬é¦·_¾fkb>Î)Š5áGcQҙŚÒruUgk‚A þ˜‚—ÅfTkB¹oõÜŒ:µ÷ŽÏjœÖbËB½,åAθò1ÕÚÐ̤4Fá·ÊjM7.à‰­Ö‚òÊu©™ªSúÜØšQ¯‰þûøûâWU×<Š5!3¤a¹pf±¦¼ZÀ¬ùÜü¦*Ôef­¦ÎC¹ÑÂoª/ÍÓùMÕzáŒbM“3°Õóf§‘n*sÂH}ÀL$º)¿]p=°%‰Î¥aMtiއQAtñŸcè&ŠæmD}&øD7›c¢›ra0ÑMÚc覴r],:ÄÈsSIæ9—c5ÏM…Z›ç¦ £ tQ‚O€.V3€²º¬w‹½èœe ›tôÏe3ÔÅÁ€âEu1Lj‘êâ` ŽX}°²!¬«XX}0 ©.‹·¨nÊáÞT§‰'BT—aÝèCª«>¢º)3FS]^ °©.nÀµ¨Î5­Mu6ŠÕÍÎ9©Î•íu±+B&±ÎáõƺÙYjÑXW·©°.‡H ¬³±°Î1æ‰u¸×€}Àº´ÀQë¦êS ëœ ¬st¾°Î¿±Î‰ º¸úφuÙ=Æ@ób]>$Ž:¸nÊ“\·&¸®ôqÝÔ”\\=°¬®s¦„°.È ëRŸÀ³K¬›²ÖåI`„ĺ·&±.zuñ¬Äë*»EX~ìB96²Û^ $»éA’ÝTA ’]ö…µµ¿3v•¤!°‹Áê ÁÎÉ»ðhƃ©)ýËuSu†ÈuHU!è%×ÅÇpíþ¢ï™é. +ïz~¦À7énÊFÑt7%¿šî¦æEw1'#J°{¯Ò„ÊGÁî>ÔE‚ÝÃÜ0+vÓ~K±ó\ŠÝCÜÞ;©¥Ø-<ñ…wªW[xw#ë«èî&…Þyºj¼“Lá^7›bw J±c†MáœÔ ï"ð[ ï”»Sx§Îx§T¢Â;½uÌwºŠïäŽ]|§Ç«ønÒÞÄwúFßY‡4ßén.¾ ïp°¤øNŽyÅwzjŠïä¥_|7~JvN:+À‹ rl%ÀSÖOu ðæÁO€§|Ö#žìÄ ñ|» ñdëWˆ7‡dE"žï$#žÒ´ ñ&«Šâù×5âM)¿F<Ë$F Àtt´0UÔ˜ÍȧLÖ¬ÌÖ~`6’c`²8FÅ_6MiÙšb"Ù4Áqü¥l¬Ìs9ZÙnE[*þRþæ©úUùþæí©loÇ_†+>xIñ—²ÅwüeLmoŠ¿Ta኿lš":³i¦îÌpE¬)³ N{€Ù˜(X˜Rà+ó>¥2*ó>ˆvKï’ Àôµp¦Tú Àd鳊¿TÍjÆ_Þ Ásü¥žE`*½b0 ]A˜8G`*X¿"0ïKᣊÀ¼påLÖm«Ìûa\¤B0õ†­L¿C0câC0åbV!˜7Ó©¯F…`ƾa Á¼¿ñ—ü6:þRïÉŠ¿Œ íOü¥^Éy??¤ºÚÈñ—Z°­øKŸ¢ã/õqªøK|^þ¾Å_ê›[ñ—·B yÏß>J]„¢SßSøeÎ-ÿ¾E_*¢½¢/ßñŸoôåÍ*ØŽ¾tƒ£/ïɰXE_Þ tøåM¯ÄŠ¿¼–èøK•ÙªLUW¬LÍs*ómy¾˜ºŽ¿Ô´¦â/o¦œWü¥OÜñ— f©øK ã/½•ã/«Eñ—Mˆ+þRŽ¿¼§Mñ—M+S6¥€wZ€éÓrf²0o×r¦ z€©‚Šà¸%yÀ˜þ €© `jáߘ¾ À¬MyOÁ$#0ë°r‘‹4tÓamƒ ·í#C0ër±ý½Kuu ÁôÏ ̸;ÉÅÏrB0}÷‘äb/Àx…`úÄ‚ùÐÁT$—é®ÕE„C*S÷3AnI‹q¦êÜ9Ó'B’[ ¡r&«”:ó^RÉ€rq@·¶öî¹øW|F©jrŽÀ¬y)iC˜RÅ*ïÖ «W£"0oV‚ù|Ê êPb‡ºq Åt—ä3Ý…œ…BºFI³®q ¦N RFºÉy‘.}Fvny.¤ó+^H·JN#Óå•1ÊhnÉoPËžŸ0L§Tˆé²4ë½§Ö½-´ÞÓµpúÙ‘.ÝC¹+ ];4óÒeùÂk×é²^±H—å yZ@ºþ@÷Žtéj³%Öe­ DÐ’èrÜsCº¬¿Øw™. u€CDº´Æi»L—îÚmG:X«àò”e1(é²…€ ¦{Ç¡™¥ .Mw@·„ºíâê²¼gÛ3ëò˜ J€º,OIÔe1J¡îýÍ—T¸¬Ë9/Þl¤º¬$Å´¹»,~Ëü7€]ÖX%´ìÞ>veM+°Ë­Ø`×Îãbø)Á®Êؽ-ƒ 4Á. – w vï8'Ÿ!‚]3´Z‚]ššÏ=3ˬ~RëÍžŠìòx˜×²k‡¡DvïVºê »ªº"²ËÃ!ÇeFÀ©Z™»·E±S»t}Ẩ`WujvY۶푘ïÁhfG²{§ÔZŠ%ÙåeÇG‚d—eˆ²ÞBñÝóV‚ìr É.‡ô²Ëqæ®ÔåyHv-ܲ挙÷ÅÜÉîí‚¢ë»kö»< Á®~_]Zk}2ërÜcϬËÚʰË{àbìe‚]Žƒ“"ØemµcƬºi»üùú®Ôµ0ë{f]š9ÎìÒü ìÒ²ìʈ_`—-Ç&Ô¥Ù4 \—WïÞƒ1ß.VØ€vyü9 ÝÛ"P&ÚåMÛzyÀ‡»Ñ½[l‡ë¹+uoÉ„„»í·#Üå¾>J]³òwYé™*è.·:é®ò§Ýå5Ç<Ž€—}0 áåù Æl§ÍkDx¡ì`^B//<®aѳ+u¹'L„HxyëSaáeêi ¼ü=¯=Ã.=ãžð²¦G$¼}_ŸW9° ñ`š @¼¼EwÂ{G¡×¤/»àaáå‰dIxñs柉wÛ­E¼Ë·™x‡1öôº×‰ùò%áÎ vJ~ë,Ñá|—ïân.Ïz˯ËßéÜðOÀ+ñ•Óf‰woMÔwùH®-s{jwùA}6n{ î8E×2Áîô"Cà]Þ´Xëb†]ìanx—¿Ëbàåõ[Û7Þ½ÇðˆæaW“2|XOUÀV†]ÜŽç†wYYåp(f>ÇX'b†]űá~UôH¼Û^*̰‹·)1ù.k¯7âÜ™‡Õ˜àÌ»“ò¤»üwò_â]¾3ê2ÅÎ…å’ïòEÂGŠ]Üæ»PD¶6¾Ë»J)w3ú”2¾Û{Ð é`½MeØ*ã)›¡˜ÛøPÛlõXoÚ–Z¶±ÞÉÄç¨ø÷6N¶l£ðïÿlï±x ÿ‘õØ?´Kë±û¯[çÿWë±ßÝ,«GFÌÇ&éçm—wÔ•ëF[/dS1´™Šy$wòH[/ŽT¦bi7ÓHÕI#í½4’lÅ4PÙŠyuñ0ÕG£ØTLÃl¦bÇ<ÐÖK#ÙTL#m¦bÉ<ÒÖËO°LÅ8Òn*VϽ:i¤Çz,¾úŸ8õä<ö»;ïÇþ¬ÛOç±2ÜÏíg·ŸÎcÿl·ýŸXZýtû oí¿ý|ÿÑ;úoôlþxmÿɳù»‘þe籨ðÎÿÐxì½ÿ£þ÷¿Û쟽ÿ÷{_µÇ ó›}ØöÏn<¶ýµåæFöï­þä"pÌÕfß_Ê6|"ßü©åZÀê#Íœ£è;þyæ,!Låsîù^¹´r“*ðÛ«À‘[žóÀ5Ž\Ž¥¯œª¬q"œç”¥È¿Æ…pÙÆ¿ ç FÍ¿#R&þÖa/cÑöÄÓi×{1ìÿýsf‘bVdÙs w¢GdÖDkC¯‘ž6°Às"bäÆTetF6töÈTø_™A›œ²fÐÑ¯Ì Î¹ãÛ0ñï^ò0 å/eDÓŸÁ%¿2™2_|+bp˜TœW*Ys ®&­ø—LÍã:ÇJc4DdlÊ5Z8ȈCf ƒ\™ðÎ|„äåœm…ãöói8Ç2 +Šjì6Â+¢*Ò˜a=+4÷ôIãÇaå¢÷§!TŸ_åÓ¼¢¨n: XPZaKDë½DPÙ¯*òN.Óhmè°Â}øWÚWŸ8ŠÕCeH,¢½Õ¬°—.Þù#¿-çùí¶s}'Z ‡ª\ÓÛrA[ÑÙÛÒ ‡j5ým¹!¯\®I´¬T`âbqä"‹õm§WÞ¿D–‹©dÑ2ó®¡oË„Ì"×ó·%*~¢'kªÙ…InÑ2ó.æ_ÄtµÿÆØ‘\í[®ÅâÀŸ/Q0 â¹Ù2ÙÂõÙ· žxÿ~Z¿BÝÞ–N‡7,lEÃTHHg—ȋÎpÎa½Ï+…寝ò‰‹–ùƒNüJáû¿+ÒoËI9êÁ®£( ƒ8î…À®¶¼7*¡´Wy[nH¡ Ÿx[žÒB9îc1ôä8jè¶§qIWÔ¾¦õÐK-Dî‡+kØ<—~(/ÏþQ¶‘Ær g%)‹òNŒ*.s“°ß–véGhƒ- ZóÙß–›“Ù¡'£=xß–W§uˆ£ïg…¿wÔÀè‡Ýîý{BU*ýÛ²¨²ri´@ ••ÂK2$RýyÒ×íÄ;êm¹ ö[¿STºxl¸zQJ¨£Ÿ¿û†J©áhx0«ïM—ü~èCÇ å:BÍÇ6€Ò¨—”-¬$«ïÜjB,Ýú¬Nkºü3*¯ { CÔ¢[ÜxصTf˜oËÕqüKSÔzÐgrœ[ÖuÜÓ=Qºïâù<*RA©·¥7là*Ii~.£z‚¬íÕÞ–™L[à½-ŒDPá‡óˆ2B4Î;n¶Ì_U¼ýýû||8àÎhå¾-íÀ)4ý*QHh¡…¢ýÛÄ9D!¡ü _Tâ9ðév÷­Æƒs¸õ¢éTvG×Õé˜0ºÞ­Â®*RžÇ`h‚òuß,*l×o08aës œC¾ß†'(æûm¹óCº½-x ÿ¶<çPûê·êørãÂ6|ÅœïA ?za1”ç°|| ŸSUúx¿2>§µï‰XÝ5üå™ UPÁÛBÏTé™o £”v-øœ* ãmaÌ‚’‡Þ–ŒÔ\£|ÿfÌ‚’ ¢ŸÓ¸yy4ŒZØö4ñ9•œþ¶0naÛ÷Â÷tžz\³¤;Æá£˜çq| [Å—?ÏkÖÑ‚OjPÀý¿Ò3U9]ïß7>©Jky[hšª•hÁ7UioKÇ7uvy<<¾ƒ{šø¨j.-ø¨Ê:êmYø¨ªÚóslÃ%ºˆ1xÐ#W£Ï¢éÎ1Ûoú0%.«Mk:·ºñYUb߯ªß®ï¾:>«9cȆ¯ª/`ÜÉz\[PžFs”ø~£Í¥v´ðUõãÃüF¯LpÖÞþž{ä -øªŽé­j‰ˆ+¢ÍvÌ,w§ÝóÆròU"Ë…ìðkC¹(UQ²œŒaÍrú6›ådîb–c‘\¡ÜP²”Pn¨®®P. g0ÉrC)¼b¹­!XnèJ‹å‚Ï,7”¯#–̺ÊEøEÛQn¬ã‹rc]_”´ É #N’ÜPÑ‘\N™µdÜ¥ñ@r¶O3É)HÇ(w0òÌ(§0 ¡ÜP¹£ÜÁÈ¡Üà>Éq…CÉqÇýãdwgŽ;XöË÷ž|>+渓VHæ¸à%ô ÇIÛ0Çço7U¾Èw°&˜0.ÆÄ=“€O‰q~»äâˆñ¹E–Ù4òÚ3ÈÅŠÐñ9ÿä¦rM r±gÞ$¹Ø7‰ —•908nª¸§9.†ÑÀÁqq0¢-p\´t‘ÝŠUy’ãö­Àq1.§ä¸HXâFÀ¸ÉPS\èžüÝHqÛÅ"ÅM¦Ïââ”ÆFq‘ÁƇ··€âb…!)nJ§6ÅM ¡¹y á AÎÉ~¹©Ôƒ\fÔq€\z´Ar³yv“$—>Š’›Êq1ÉÅ(ê’Û·Ém”$7•äb˜›Ê1Ìí}s³–WsSåH sÑg‘±2Á¯uÝŸ„¹©°DÓÜT¬‡iΞ’¦¹øe´§ÁÕÏK71i.$ ŽLޏ²hn*.‚4g_ÓÜTàŽin*ŽÄ4·7inïš‹‘Û‡æR¿g h.3ßÄwC¿Ã—æb>x]©—¡„¹´ÒÜ1ñÒ—†0·]PÂ\œææf­>榋 sΡ4ÌÍûÒ)梅ë2„¹©4Ü“ sù7ÿ\ÊåÑ妢7ŒrÑ…o¢Ü¬¶©´ËSM”sš¥Qn»õ‰rN4Ê9Ò(7• E”Ësä¾™GLr'Çå ìÀ4bš㜺iŒ›µºGŒs"©1.o4Â0.o‰RÀ¸©0'c\ô’µþùˆqS‘ÉÆ¸íÚãf¾²³7oŠÛ7Å)ûÔ·]]B\´\¤$äåvÜòb8!„›Ìö2ÁMåm™à”l€ËGK-øœÆ*(÷ €s®±η¦n*éÊ7nG€sš³nßnªž¨.ÎÓ)\¾ÿÑ~Ë¢æƒ-KÀss#ð›Ócÿo1#¢L7„S¸5.à€Ú†sA1Ü<$1‘ábN`0\MòÉp[ƒô¸Î½lz{P+Ž‚\5P‹J¡€´‡ÿÞù'>KÕ@AÎÚŒ¹r§¸mH rŠ ¶ wtBõ¸ˆeÜ)®:œsß^rÜÑ?r\mN9î¸C qZm7ÄEp.´4Bœ ½XÓ’½!®6¡e¡Ø‘ãs%Ç=1]Ƹà)qu=¥Ä©ö™”¸RZ¥Äu/ûY‰;xâj×âdE^B\¬£:œ<ÏK‡+%X:\IÎÒáälU:ܶs•»èpt±wY«£7¼*ŽæÏ%ÃÉ“ºd8kÙRáTt­T8Y+— 'öRáÞ­ø­‚ ';ìRá†s¤Â]‡·¡ ·Bnx)X*ÜÐz¢D¸·A²!E83‡E¸qñ‡¢7˜ŒW"œ Ç”×§"œ*•§§ÝœÊÈ•7Xi 4¸®åwkp¾Âá¶TáBfUH„“A{‰pΰ÷¶àýe†ë”J„“)‰pÝGlîÔYI„“Å?ñ¸Mäg¸eÈò/sÛ{§Í·ÅDýÃmJ.5·©–§¹ídÁCs›„sÛ9õHn;‡¢"GÙz©@ÊNt·©ö¹í|$”‘Û|œâ¶óþHéS·Å‡;%·7Þäæ¶ó–¸Fp{  ÜN–Ã%¹Åõü›rrHn¾Þ"·“…VLn‘?éŒäV=HnÊn1¹§'InQ¹‚Éídä’ÉMµHngû¡À,¨aróQXã}dÎ#J€ód·Rä$À]Xw/îR|'Ù­6)Ž’Üä¸Ån5‚D¸ËR™D¸Kp‹pMË…á<›´wýöCƒ»~§ÁÆ.jp§c̬Á]¿}$¸Ëò%8À&ÁyÏTàÞirTàj#+pžSK‹NR ÜáP5)p‡9@ ܶ¸­ÏÝý‚É¿©ÀE"·!»Õj±ØM¹kÅnµz-v«µjÁ›lï¶XÊfbR,e7¬)–òþK©AÅRj‰Ù¡”ó‡·¼@X¡”^~¼ÝwT¡”TJ©eR±[ѲØ-ŽŽ%»ÝC!=‚·~óÛáXFò[Ü€_~«“2¿’@Iùè×6¿NÄo÷ÒTAüöœz Ìo‡¦¸ˆôä߸í¬Jù˜Jù(`Ì¡”·&É¸Ç 18™ÞÀ©žwœ²Šà ×Epµ–@‚k"bÜã׆n;bœï‹àTú«®¢UEp±LÆœ HÁ©(V‰pëÐ:€nësó,Ÿ/ÂÕµÂi]°ÎË"¸øâŠé@p*DV§ ]EpõSánNApu,B8+„‹õ„o@åÞ2ô+PÑŽW˜Ap¢¸÷uLyR%¬¹wR\-òˆâT]­0îé"`Ü»§ç‹quVÂ8Õè*Œ«£ÆÕ¢”0N^+…q*ÊQ÷nEXÆU\¶0®î6aÜ3ŒŒCÏ‹,—î#inĸsæÑã”QRwx•OWç)«¥6œ’Y äêiÈÉD­@®^µ¹º+rÛ¾ r·¿\9Ù¬ÈÕs'’{ßÏ×—äbñ¨D”«_F(WË­B¹zWåžntk|‹ ö¨Ä-+³B¹ºG…rñ­å(D9YÊÅòe¹zϋ垮5 ±\üÄœƒ_Öþe9™ÉËy}Ø,Çby…r>`³œL‹å¼¢m–S-¿b9'Q˜åžá‘ÉròË=ÍÔH–“'Z±œìCŠåÖ±)–k´²/–k¬‡[,wï‘å®[y¨ÙBÌ\‡¢¢×iŠB°Ó»ÁNÏŒÁNWÇ`§Šƒ»wäñ;•£3ØÀŽ«ˆæ:Ö“2Ö©n±n]RðëXëYT·–§Õ%Ÿ T·¤œê–£øuaÚ„`º%31]Ì'9ο8˜ÎnqbºÈQºJ‹öÞ“ãlá+¦[ÊgÓÙßUL‰D÷ž·“$¦[ŸxÊ%M^@ýOjoªOj\‚î!•KÎaºUÊÛÅoÐbd(‰Î¯P],XùžKQö 'éDD§´gÆuaä¤\ iŽ_m21Î++Öâ*ïE‰qµ/-N#+1N5K‹«¥^‰qµH.1Îk?ãb®@-Õ8/CKŒ[¦o)Yã” Yb\%fHŒ I1NÕJS¹R㼺f5N•ÒJ‹ðÿ=7.óCtуkí"ºd&›‘è¢Âu?]¥ˆèäìVD§4EtQÁ€ðE¢ «ªY'S¾@§ öºxð¿D§*EtëÐ[Dù_¢›CSÝt„šˆn*ðÂH· $¤›ŽåÒÍõÛ77n9¾JD÷#1.æXŸ€ÊµÚ€Ê팄sKÁT¢¹Õ´cÂܲÜ,˜SÁ킹å0.ÀÜr —`nY¢Ì…߯W{ÇUa®ö-˜[Cç$˜“LÁܺ)¤ˆåT½XŽ7¯@îí°ö¼¸5G'{[8È-ò@n¨rkörÕG §örË“N€\ÖvW6¥¸m‚Üò2A€\n£œ6‚ÜZºR¹ª\_ · InYšÉEð¹-IîçtFIn9]$÷öqâ&Pn9‰(—=Öž—-ÌÊ¥=èÜQ.û´åÚq˜“äò4ÇL™írÜÛP@˜ —{âõÈÕõ Û÷“—£r> ŽËAöPÊýWÆe—µc\‹0áë-Š›¼pü¦PÜ~ ¸ì#"KŠË¥Î Û8@qÙÂEMP\×"Dq˯RPÜ~À“†§G—ì ŠË}saÒñ´Ž×ÂfRâ[R\ŽCDƒÑSÜi ·„uèpnœž¶M’á²A‘ž°zŠŽ]ŒË…Nž8¸)m —]HZIpÙ…ì ‚Ë=)|1 wÞK™Ãð¶_ivzL­ŒIŒ[ î#ÁaObº‰3ðá‰àêqÁ•K®.·s&Áå«#N‚Ëã¥gßÑj‚Û~[Ή}’à¶î3n"\º¾NÆe&Âm÷'.ÏA<™—-΀ãÇ”öþB¸ùÚný©Ìs¸w„Ë»‘ñʉ[а%Âåñ ÆKá–b†‰pÛ=P9q|Am.aç9æóu€i¦DeÆ–ÝðëÏ·«^êóo…]W&®y|þ½reËæ‚ÿ7S¯+lŽçgµìã mI-ÛXíÄÛw;cµlc±mË-ÿÙFaçuæ,ùß3 ›ÿ'Âþàv9#qîüõ± ûqëåMÕÏÍø·k³ãX»Y˜Æª^ëc)†±v#0Œõ± ãX[/Žõ5ãXeÆ¡6Ã0ä>h7ã8›Ú-Ã4RõÒPc1޵Ùq¬Ý4LcU/õ±Óã\†`ëcæ×€{q¬Ç6ìeE˜Ðÿ—oØ?ö û+ïñ¿ýîüGoí¿ýáÃúóMþ'ëïÆú—½ÃÞ{*çDÿw›‡m¯Îÿùÿ‚cØ{!?W,>íïÁ˜5â >± iáX¥8ç™)Ýf.™üŠœíƒ=®…,nšüœ™(ˆ”jŽzßHãæZÚÛò\Ê ‘À|–ôwLSÒ Ñ'7[ܰÈHgVŠü•y©œ¦L8ĺ*[“:±ÉbxC;5ƒ‹¥P¦r9}Ά‚:r†wÁÄê0Wîãn!ü™Õ1~Ué¿hAz£µÌ3pDйUÇBµŠª¿-+ÕýTˆÕÊ¢±€Í£™X«~¹üà( ‹Õï; ³³ë`„ƒ"*¯˜ùÆ)Ø>æ:à -..Vëím`pƒЮ£q¹Z*×*è4¾~ÿ~°^=”2{L/fiíh@$’í4®¬mð µµo´LÄ"ƒþõ"G¾—Ÿ®0E¾°–b®pfíÌ}¯°¸=UÊ·åB@ÒRÔÄÛ’ã²òûw{ä’v±ŒìyÂ’–òòÞdD-Vˆx[:“Ö£ ~2ÃxÑ9üm™MzÐÍu2Ã8fÕy!8i)b㺘cl;™ë !dy âýËÙf뺰ž}(6ຽÞä‘õ¶`E[9HoË=œ¤Á–kÚÕîëêˆRò‚äuqEL oËÀªö!áõº¸&vȔ꺲4Ô!)ûý{IÚŽ_íèÒ6x!WÄN…á¿ç„X¥©¬Ù·+bït‚7EkXÛ–oÁÛrÓôíÐÞÛƒµí¸£¸¯kÛ硳z¿­8áìÕ-èp­ÚD°ÒbFY´`m[êËÛÂE1…ž×}`m[1po ÅÞaýàmA´ÒºøF½n.Ь˜ò¶4¬mŸ —¼îL1Örçû'¶ŸÝ nØ6éòS¯š÷Ž €¤À®·eÊV'uOL€ù¶,,m‡¹ø9ݸÈó¶L^…WêØŠ WîHòÂe€Z’½®¨tÿÚ<þ®‡Ñ çÔÛ2ê}ŸUÖZv¸‚]®ï8\³kÕ€N0ßRªd÷ÀwJš+€öŠB@êq²)Ž‹þéoËõ^öiXàÞÆ½Áãö~¸¢ÐøÜQ èBŸ‡#3ºáR@ü•€R﻽/Æ7Êθú<ŽËu±(Ú€m¢Pjz2¦ºXÚ5®ŸZı'| /w~>F÷Ý3®(týráñ·ΗŒ¯õ7kòpèé|u½MFçmÂS€—Ê“¼-P€£eð€—Ý›Z°Ê}håÉ–¿6‡Æ œhÁBIúqœh™j™ÒTyšYÜÕ¢ë™é­TUùlNÅ©³Ö™Úôýy]O.ÅK[Q¾†^“’°œ%²`û…ûš_è)Q˜uNN¼Ý¥fË_jQŽYÃÅ–ùùâ, Ã2 Ë¢¨¬EÆ'hQV9‚Á¸·øL-ÊÃ6óH}”¥du|ˆ] x=n}5Ub™Ëž—+¼ž|ÃÄ2Þ/Ôn½ù7Ÿç›«gí R¬zjo ¥bp¶ƒZ±?P¶ @ÌCÛAµøÝ÷äV”‹›,×ÚA½X~YIêÄ=ªø²Æ®.´Ìk¿4í˜K‡÷°‡ìTõ­m.ïÊ:èo Uc›‹4×wEiƒefp0<Þ“¢±mA²ÜBÇ0ø@·“¢qTÃåÎ)wÞyÀ¼Â'Uã:…“ª±êùÆâ¿¬ËãÊMUP»ŽSï›ÆGÙ©ÊÛµE ün¼oÚEÑø”ãcCuWçÇßü²2:ÿmayWÏ9ÚEÑØ1Ô^$:dÔ.ŠÆ^&öÒÒÁ0¼¿j2Vø‡âå;þ9ÀÕø÷4ÁðO¸ÙÏ1Yf?Çþœ jú{¦{HÑg~è/ú0¬ˆø œçÿ†­C…ÃQv¿haÌUâßpV¦ø/Z{'ÌÓ¼ÌNü‹zÑÿ¶p_§ÁÃi›‚¿èBCÂ߆ۄ¿aÇTÁßÞg,ü͈,Â_´0dŒð7øU%ù ;¨ ý†‰Rè7œn#ú³‡œñoß øW»þÅ6œ§ÿöàß ñµñokýEé…ô·èïÓ2uÜé/Zø-!ý®¸Ñß¶¯¤¿ü›üú‹~IH9ʇþ>-Cǧ}ƒþöq@£+Zô·úù‚¿mÂß¶«„¿½Ç9Ôƒ°öÛöCöËN¶,ZÀ~þµb¿m`°ß¾o°_nİß> ØooY/ŒXpáð|©È~{ Øo8Yì·Ù/ûëÀ~Û¾È~CAZf¿}+°_öù°ßvžÉ~ûÑþö#üí-«ûv€¿áh-Áß62áo8OOð·áoo¹ÏÏy“þöqŸGǧÐß~4ãÐñ"{Àß¾kÀß60áoëCøÛNŠð7œ• úÛ{€þöqA{ èoß ô·1éoûaHÛCúÛ†\ofÆuè4ò:B¶$ýmGCúŠ5ý §ê‹þò¢³ô·úû´,ƒFýíã€þ¶³"ýméoû­’þösZ÷kLúÛ^ ¤¿m+É¡u4¤¿}œvêÔ§ý|¤‰Ûyÿê&*ŽáŸjôõVžªÕ"SÕj‘«j"[U0éoÛŠô·8é/¸³eþ¸•’þö¿é­ºmó:>qýU·=õçû´þöÛ~ ƒS§À•ÒßÖ‡ôWþ¶þ¶‘ð·áoûáûŽîñãðûžº?¬ãÃ9É‚¿íF'üí#/?Šœm'üÕ¯ øÛ{œ÷÷ûV×ò9|௎Fð·ü\þ„ƒë{—ˆþö­Æý}€þ>óÛªU6Ñ_ÝÅ¢¿º“DÛžH{Ëåo+ïÔ4Y¿ƒðo;âß>Îão+úýí0üiÕ ÃŸVõ™ý{›ˆþ¶Ò_Ý8¢¿mdÒ_=1¿ºq€û6ŸVŸ6ñoßæñ§•7…â ¶ãëþ¶ªÏx>ïÌÁ£¬ð}šßy×F€ö3N¯{ƒm)fœðD à“ Ø†R\ûç)‚²X|W  øNà!Ã8I€‡œ{,FËW Q€}RŒ]“Þ¨¾Ûð¤¤:^ÌàY@G ÐùËÖe Š«–XG, p;j€ÛÈÔ+ö `“4@™+—¨Jâ¥úúY” t‰€[ uÀÒ(D‚Œ5 .Õ! F”1÷Dt±IPUÊ ·qÉ‚«kÕ],hã0³àâI—R¨ ‚Žh6:bØ ¨€ c« ‚ªvU2à¡b0ÁÀ•/:Ù èXiƒ }Î ‚È ‚KEeL‚òa+ð=ž)ÙïøŸH°.°PpM zDÁµLcDA-ÜöMÜÆ! ÊÎ,ÇC)F,¸¦’(X0Q07a¢`žP°NJ(¸õ¡ èàn¡àv0BÁº‡…‚ÛÈ@ÁØŠ³PPvy…‚ÛÞç4bç²PHŒ“£V¸\\ÐDŒ³D¿óÇ)ˆëW :Vß$XdÀºkH‚û¸$Ám’`Ý"AG cœëƒ‚ûÈDÁº|Òëxˆ‚ÛVBÁzb€‚µo¡ ³…‚é±’ ¯°@P¹u%–l.|÷Ä ³@°~:`Ý6ÁíJUòL èxzƒà&úQtµ@p{<‚õ çÒ¾ ‚y…qžÁº~Áú]‚uVÁˆx?8ò䵡$¬k#¬·Ap{¤‚u4Á¹¬èëh$2Q0Ö[T Xï}‘à6ŒYOÎ]L‚õK‰·QH‚õõ2g=¹ªIÜÞ@Á¥A°v%¬ ¸õ¸ý]]_¬Ã›òhõÁë.F ¦g\Zåša¬ ,|¯_7Á:¾uòÂPn£}0âÀºkÈÛÁ¬*»Á{DX÷‘8°.9p{ÈûÈä@¿ýÈ>%q ëw˜ëÉ4ú Ö{MXO”8pªðvqà69ÐwŸ8°žs o$r /º9p—^@±oR8ÐïPc /±1°†!Ö. ¬gÁX§ ôËD§mX?8°~:s otq`ÝâÀm+q §7æ@ß8V#ÆŠ'7 ½äÉuâÀºZäÀºiÅÛO'ôólô\ZèŸêŸØœ™ý²ðê'øs,S«=ø³l“Ì~Á _ö;•Èdö“kØÆ~·Ì·Û8„?Ù“}â?Õ¢øÏæ0RŸ•ׂ?{Íþ†bø«#6ü)h§àO EÁŸBi çå­7#Ä o YÙð§@Í‚¿ÚJðgw<Ÿ¯ŸáO¥j eø“]ðw;žSðçè.Ã_7¤1 Ôûrèù蛉(PÜU¨\ß* ´£úŽÂÙ„Â@·#f¨þd ¨oÇ€úçv èÛ¢ˆÏ³<éˆdŒ­`4Āơ!ºõ üÕ…Q èÖ‡1 uJŠÝú0Ô5hĞ¡ûœŸb…€ÖÕû·ƒB“ýêÒý¶ƒ!ûU1%‡€ÖïDö«'Jì7]Wì·÷a èÞ²>†…f¿z¦yVdÈµÛ þ¶{ð·Ý{„¿í®üÕO%ø«Ÿð·]Âß¶wÁßÞ²ìºÈ‘{×;“óï„¿X<pº ±à/XØÂ:3Jú‹·‹â.I^¢rèi¡Ÿô7bú‹õ<ñ èOi†EzŠþ\ÖÛô·÷a™½e*¤_²Ÿè¯ö ú‹–Q Ê#.øóF„¿mW •; ø›Î_,ø{‡ ú›rJ1þåÁ"…7?9¿}dàß~|³ªµýÀ?ùˆ ÿ¶qÿ¶Ä¿íˆ¾XÆ¿Ú ø·]⟠:lø÷h%Žø·Ã:3t‰1ýí]DÊ ýÕJ±èoÛ5éÏ•6úsT7éo*gYð·] Â_TÏØ þËGøÛÎrÈڵơP2áO±ìCU9ªƒÊr ­E Õå¨>b¿[2†¿G•ªÌáÈ~Û]<«6ñ%ÙoßFµ9ª…•fê¬Í~ÊÓüm£:í9ý0‹)Å~µŸ*Ñán©H‡†Y*ÒáÃ#ú9`©N‡7a©™mT•êÐÑšüjT‘ŸL½D~{z¾Öž~þ‘ ~µïågì…º‹Ïï¸OjHqŸ7¡ïëÖ°tü1AŸÜ újG´~­Qhýês.æ«À|ÛFó;ˆoßBÄçC1ñy?D¾O ¾jò©¾C!Ÿ÷Eäû´¬ïPȧC!Ÿ¯·‘O'EâÛFÄçÈZŸ‡!ñÕûXÄ·câÓí[ÄWã´ï \ÍÓõ üÜ[D|5J?¾·¯îç>œ÷¿`…V쇇ùÃ~·IŠw¶ƒÉ~MÆCf¿xóŠ«髹ÉEìw_Þêq)&Lö³3¬Ùï– dö“ɦÑÏ„.ô[G…³.f*Ñ a©,M³òô[…”KeiÎßÈyWW½ˆAÍÑ"ÎC’Â{µ¾ÑŸË•.E~Ë•+õïv„(Éφž$¿gþö þœeÙçÌ?ç üøÝõ9hOÐ÷,S¡Ï†¥†¾îɦ ¯†IæsI3_w²‰˜¯"5Ä|ÝÓ1_@Æ—ùœîhìëžA û:ÝÍ ûú%.öÙ?ÞØW1{À¾(üüÑübÜç«ùÙOÍØ×í$ìëN'öõé>Ä>Wì0öõ^É€øDEÆ9ÑÜÇ*Í…}ÝÉÀ¾ðüN¯0ö¹’бoœr‰úúв³¨ï½!ÇGñ›.bê³e¨©Ïu'L}ÿ¨¯R;A}®ÈaêsÕ SŸ«˜ú\SÂÔ×§É‹Ôõ‘übµúÂ'‡B©ï½1%’úÞ­®ä)å^P®W‹ú\ÅÔWWTÔ£PA#õ Už0õEݲ©¯®Ž¨/*X°©/Šg(×ïÜpA_ž /æ†ìCèÎôUB° ÏÎ|†¾Ñ©=ˆùlðgæ«{BÐ7Në{„¾áL+@ßPýVCŸSÓ }£Â/ }•(+è{ûœB¼ãÇ)ú†R@ }Cì }1ÎúÞ®:OBŸ‹šú†ªújA_\-b ¡/î"¡o Ý7‚¾:sA_<~Ü¡oüLýËqêyéNçyŠú¶sHês SßPÝgS_”#‚ú†_[¢>W1öÕÑûlÎhì‹ßŠìEì«;]Ø÷Žs±Ï³bßÛC¡¨ä>[NšûT˾¸ïý}5 ¹¯Þ⾺»~Ã)o¿ñ­d;¬Î5Þ[ý ~ï5îÑ/Ÿ‡¯èÖ|ìCðs“ßv4D?×Ã1ú Uà6úUÖ¿Ðïí3¿ìW‡ ?‹²øˆ~ùžb¿¡ ‘Ùo<¿}Rÿò¼Izd¿z׉ýêœÄ~uN‚¿z>ñ–çþ¼/ÒŸß/¦?šþ¶>Ä?ù/®ÞWõ*ínÌIîß7þ‹kC¹Ž8”ìiÃá @¿îH€ïÁœ_|;ꈀQ¶è“ú7í¤j|ǹ¿è¢IFÀA«©BÀøpd"`¼Sˆ‰D@ÿœF@ߨD@ÝX&À¸Âjá—µ›b‰€ñub ptçÖ§êÈ}Ÿ=ï0ªÊ Ðί&Àú D€C©¼&@ß|&ÀØê‹€C•P³{©µu!ZÈŽ8ÝBËK-/µ?ÝnóRcŸÓKí¾â)¼·lÞelÛÜܲù ÝéÙ½„¿÷q¢eoc<3õêŒÕ²Ã¶m$·ü§{©ÝgÞ3µ?u:;[Ø\î¶övˆÏïlœþÜ í÷÷@ Ÿíñëãßôã~Š+BÏÚÇÚ¬Ï8Ön}ö¸,‰z=.f²Ù¨a¬Ýú c}¬Ï8ÖÖ‹c}mÔ8V™Ÿq¨ÍüL#¹ÚMÔ8Îf}Ævë3T½4ÔÇFcmÖgk·>ÓXÕKc}lÔôŒ–õÆú¤ùÙv/Žõo¤µ÷…ö¾ôþË íŸ¤ý…—óß~÷šý£Wñßþøaýñzþã‡õ÷cýëiq³¼ó§ÿk Òþã Òþãß5Hkéú€‹6Ÿï{Pë[ˆ.e% _™φžÙ *Û²ÚëÛRÓÆ¥(÷GÁXk6 Ý\^\ôz€«Äa:œ‹JZ®º,z-{ùÞÇéš`Àª÷Ɇ+‡×ƒò ¾·íá’Â}4˜O¿ä„ÙzÜ&ï߯ÝûÈE¯w’7ã°OÚÞž^Ö¾ž¶·áa¿Øg¤õtÇ# æ>fÚÞ^^µy[Ò{úòBÄ},XY¦Ùq4œá€ý6tÍsïó„¹e—œÿ¶¤ûtsðìýâ÷¯vŸò±»Ï\ója‡Îs|¯hœÂ½‚²!×¼Þ†A‚¿Ï'MoŸC‰Ó÷™k^í‰5ÛÆ–4½}œšþî4ͧŸ˜ø³ÏLóéçÑ2ÝûÍÒna ¾Øg¥ýô3Ôl¸Žvú—¼2@¤Å ,$îë Ðn=,9&[Ò{º«üåÛVb«æqrÉëí£‰á}E5—·åÝîµ·%½§ûP û}õíþâX®¼ß‡àýûQ€ÇýÞ½qãÔÿ¶¤ût–^á¸9©{[pt·\òz÷­Ì‘û…‹<‡¥ìœ·%@» Ë÷{Ãä9,-=Þ-,F¢EòôýþúqQb‘‰oKZÉX'bŸ§ÇŒ7œÂÜï÷_ã†ÿÞ–í…?xË5¯·å!ÛÞ-ê¼-¾‰ï\ójá]΃yoý<y¿ï\ójQx†»z½ü¦Ê6Ýw®zµXb¹9N‹]Ÿ~¼ï\ójݼù6¤ýtöã¸=çq©öïÛ2ð3Èd¸rµÌ —Xu‡n<;­ÛL§ãVâñ:õ”=a·{»êïûí=Ú‰e‹÷Ï…;ä¢Ît÷3ä‡}fî~å´nØ+ûîíÔO%çmYyS߀—ÒI~²l»Qè([xÅãgpÉ-'!(Ÿƒ›{w¹ÂÉn;Ê£¹xJëÔOÀçåŽÞ•‡¾Q洞¯?;îèžOªŒþnT<Ê<|ç[©L÷ªGù¶™ìs7ÜFn‰¨{´_‰°ŠyÐãâž²ôQ>>X¼£öQ¾mly£úQÞ7:š9q'ùVC¤Öë1/ñ;øë‡ Hù 客ÐT J”@z·Páä;j µÎï * ½/e¥Þ(ô¾ýµ s‡ÔÄP¯`ho-–ž5ÎÈïéã´ÀeÞ/– ìÝ6Ìw|{xp©·ÿ—½wÙÕ$DzôæzŠ˜ ¨\v7 M¥‰ ÈGJ=¨ÌTCè÷‡líu!í¸G¸G(!iÐ5¨ŒC·Ÿv7òãÚ{íç]õÑí½û«ÂzHû‘õ÷£¯õ·K笇´£|—wŽòìÂ6^u9Xéùìºî×ÑK~¶±u×ÁšHO‹›Žª¨„ñsñ-aU¤ç<G{°.ÒÓâu裗 üœ¹‹,,ŽôŒºy•Ÿ âó7f;µ§“µ‘ö3±çR‚ðÓâÉ“µ‘ž^”|.%ï§m¯NVFªãå±h­à9翞¬Œôôâ øs)=x?SâõDe¤G.ðK©ÁÕ‡õdi¤_¿K½” ü´8cédi¤Ú7ïÜÉÒHO‹Gšs-Møé¹ënž,´£´ ‡Æs-Qø™ I{>Yi? p®% ?Âáí' #=Dzú% ïgÊ{œ¬‹T7I}”"\óÖ~e.˵s-Eø9çi,‹´Ÿ® r®%ï¨ùÇɪHuSt ¶„wèQ\Þ;Y©N‘ ‡' #=»^µè²0<µ” ¼£– wãÔøHvÈɺHõœéºl¥?Ó´¨y².Òó+N>ÿVcéQ_6Ü<KÏ„òäÄrרw²2RMYù­zŽ}Áߎr:Y©vÝô›ÒƒqeøgÕEzÞQ+ðç^j0o›:­ÂHuø9÷Rƒë͹ÔR†NÏ´Ýþ‰'+#=Sn³{Z83>ò?Y©*"Ìó4á*<ÄM[pµãHÅó(5¸zá`•õ=¿lŠ6#ßkÙäiñÈ3ïRŒ‰/ßO!_Jßùbä»<èùîèÌF¾;_Ë ßs— ooW1½ _Ûe‡iâkcü"ñM‹ß"¾ŠÑ§Ä7ù‹ŠøXKZ¨vÒYuL‰|U[Ä€Gä[â÷gä[R«×ȇÒ%÷ ùÖÅ5uÍ|«ê$ùÖ˜kùÖÔ#òáù¶Ä'ù¶çêñRÌ·§,Œ™o¯éy5ùöà4òíòÁÞS(ÓÈ4Ðò©ŒjäÛO³ùŽÕþF¾i¤ò•~¿«¥Æ'€JÈw¤ ª‘ï³ !ß9Yȇ‹n%¹ú„|øÞß/ä;ûªÛ$âúªßCyß™À-Êf©_$uM… |›-¸|Ï“²ïVÎÁ2½ð]{¦„|W¬v |T›ð]Ïs«'BÀwmÎF5ð¡¶g ¾ë¶­¼‰Û˜–D|‹m¦B| ±šˆAËê‡Ä‡é¨0 À4ÐcoàËJQ€/³ïºíŒà[©€o?üøâ–à;]{)Àwl_6‘˜€ï·?y£«'Þ»ŽÜoó^Êäk^Àò ¼k!ße-Èw{^cä»îÝÌ*äC?oä»n—T4òÝ Ú$ó?´ÐbèK†X /‰††>б1ÐWì«~}w2’ }8aŒ ËëúbW"èK‘,Cßåâ†a¾çíÓWL̇RnzÐÃ|¯0óauF¬˜q ¦@2úNˆù®ñIš˜¯¿˜ï^œ~hæ ›ùRH1̧{+àÃ1j¡ÀÀ×ämlÞ»ZÞKÀHx/n€#tWK.¸ˆÙÌ—:¡b¾~hצ¾;'$êÃs¦‹)êÃwDC¡¨åÅG¢¾+5L}Óª‹¨Îõ¢>¼¨ç‹ú®”C7õ˜õõ]ϽÒ³¨5õõ]‡§ ¦>бQß…QKýú.X·êW¤¾‡ ý^Šú® ‚¾ëÌ¢© B }عÖC úð~Ü$BØ|}AßåÚÐ>¬n®‚1RúÕÌZ؇ï†<ªø(èWÄ>Ôiäkì»NSTQN@{&ô]‡ úpt§ð’Ðw DôáFñÑ2ôÕÔ-ƒÖé3ôáW‘ù®,’ú°Ji.Ü5¦ºr7© ÃM;"öရ~Cì«ï»€MÜ5[{º5¦:ÒÖÜ~×m÷áâ¬&A­¢ÞzÎ ~Wf}¿¢„‚?¼Z (ð«sb¿?¬Ð´øá¬vµü®Ì‡L~WXà‡Çüx.…ˆMàw»‰²iH Ô üp¼"`f6º¢~ø®žÀçt¿Á¯y™Úìwmë77ýüeô»â¾nôÃs¤÷Gè§Õ-s_ ˆjáôøÊ²`¸¯;¹Ü7ÿ†Ü‡¹gæ¾+ëá>—ø#vhƒý®wxÁƒd‹s@Ä~•œ&Žð×ðò[ßS˜¹¢œ}d’þz Ãð‡o§¢{ØaÁ_‰FïsÁù¡÷¡*Ž(Mzž!˜ô¾$ÈFï{NW“ÕÒûV¬"3ùhoYDŠà×Z:¿LfD{¾B¦¿}¬E[ðCu`µþ¶¢¿£ùÖÿŽøçÿŽ1Á)üÃ<ÜLFüÃ’Ûm ì\Ü[¾iGRü†¸#ú›eBâß•ª»QüNÐà·8 Øôw\Ž˜‹àw9ªÎô‡—OwŠ_BÑgª#DñëH­ø¶"1þø2 #‰Uù¥øa®¥»iÅ`Å/ù3¿göñJñËG(ŠÊ}KŔ○eÁ/…UÌ÷XMÿa’©)™ùïr8\øosˆi¿Ó üyâ?ˆ˜úÛüç*4ü†hiÁõEDâ¿,»…ÿÎÛ”&Á/=Œ˜Kk~Á/o¯ñï°õZ¿!ŸQðÃ⸸Mü—äá?¸Ó¿¿ç¸ šä?¬s™öÈèù ÿéÚ þîvùÉ~XøÒs/ö»Ÿ»¥Õ³b>r%ö¹ Q´¾ÃÎSf?Hp"g³_sFä¾[ì‡û&þû¡€´9Sì7LË}m‰(¹ï̧Æì‡òÕ@ôëNW ú=—« Ç„~§í¢÷áv¾Ð¯Vá¡Ð/°b¹ïùLo¹oËåù]cý‡ä7ÄI©}L~¨æ¢“ßÅRä÷|ÁÞäw{¶±/å4ø¹òyľç-]^à‡sSüîÈ~H´ü00ooðÃR½ZÄ~ãsö»²oÁß©R×f¿û ÷ûáÜÜ"ökYM1û=Sy¸ØïŽY Ùçñ†¿fŸ$ÃßmaÉì7½Úf?¼g/ůÔô¦–›W8K;b¿»Ž©ˆ~÷$ ýn)2úÕ°a=_+“ª…[$ùµ„Ÿ˜üú-ä‡Bï4‘_ )äwç&ˆüðæêœ„~ÐØM¢B¿~GúÝVYˆ~¸Ò1„~¸-Æ:¡Ÿ!=ä‡ú–¢C’Ô|Mp'ò»ÌyŒ é-Œ&ò{†HïŠäW¯‚„Ë ;ÿøùÃî»ý-5÷áßu´=z»aL܇‰‚å?¦Yo7÷ÝÉî7øávK 3øEŽ2÷Ý^&÷áiÕ…÷Ý© îÛœ·bî»Ödî»ãbîÃ]ßÜ÷ÜàÝ-ä¾Û¥†Ì}XFûj=I4&ìk^Îö=W^jì;½üjìÃrÜöü*ò@L'ìKn‹¹¯V™txâ¾¼Êá¾¶]~É 0øa•I ÀïŽ+šÀ¯5Ý's_æ8æ>$wY$÷!çR´EðÃR¯u7ßîÉIÀïR}ÃpßgÍèwyU,è—¥£_¢gD~ϱ½ÉïrPŽÉ´¨gM䇇ºOä÷›h¡½gâû0ØL{5Jü}†=†öŽØÀ ö\ǰ‡T+ãŸ2š/»a%¸ó9C™Ò9¸ó‡{ªÒ“1Gv^‰Ñé¥îXHŸÄ9²³ rmsdgÕ s?‡˜Rð¥ÀN^¶ôž›m±P wA?‚ÞÚ¢9*°3.v἞œ—Ø?Gv>ß!±‹8oË›dÎÛ’ñ,™ï^*•«0/Ìø'RùŽnð楂a;‹¸Æ¼gÞî1]œAÛq§â¼mO€¨T¾HåQùž¹•e³’ùð}Ë|½_‘GÄ&™/ëF‘ùðÉJæKÁBsÞ‘šæ¼#ë9æ<é¼d¾ç§&ArÞ5&Öù®+Ç'¡ï´ŸM„>,˜ Ù$ôa~ÿŠì<3ëça¯Eqv%$çc/ÎC,&àÅygkxä!:ߘ‰ôžÝGÐ;S|× wÖ$† µkõæ<ˆ­Û[çË€oÏ,Sœ‡_™(Éy'òÙ@Ì;‡j&Ò«˜f!%Q﬷ Vù')®é)Ö¹ú'RùÎ=ªšT>d‚ŠÐDz„«| Jå{&=ýEzX­5³‰ôðqx«|§‹ Få[jÒƒâ}O¨‡çÊèDÔCgÒ\56­ÁA©|#Á¨7fíF½k•ï,ôôYå{î‹n¯YïÈœ·Xc½{‘ÊöÑKgØ;]:Ͱ‡WWÂ2ßóò­j‘Ì·-_i¦an¡Ìë×È|“"§ÐÎu„`í¥`àù=ÚË"’#;ñ%V‹`_‹ì]cõÌJߺ|¡½kw'Qï¹sZŠL\g®°e¾Ê€­†Rù†ìkÒC`ÂKæ;Û=QÁc=&2ßá[`ÔÛœ-™o„ XæÛ{@%óu³Þ‘Äz§¾•Ôøc¨@ïDõR·ôÖ<=¤½;¯ Ï,œ:T-‹«ìl®oÄäô}‰/y”ø «J2“ÄwE½1ç®HЋgO$¾m|'ÐÃ?¼$¾+“‚!ñùÁ›%¾mŠìÄM2¶‰õÚ÷†=Üüà |õlïù³†¨=UtL}…/ê;í½gê;R‹ÏÔw NÔ‡‰£(UÔwfýÄÔ‡ù¡³÷VP·Çî¢><Ç÷ û¦L7až~°°o ÷]ç úî”(7ôÍyyz® l¾Þ¿fó-™ƒ÷vÇ7úPr½ÓùFl¢Å½§—´ô÷:MÒùF ŸÓùÎk$ï­^j2®IÜIv÷ðµUK¥óÝ~æG:ßåàT2ÂÙ4óÝñ²6óÝcîcqï¹·ÎøS6þç}ðû1;úÐ#9©íí6×É|YÚ`2ßžì9'ó¥hýÐö¯GÛK®¦“ùÆìÂÉ|Ï„áBIÜ{Þ Ã™Ä=”#x‘ùf¾{ħZÜ{&äº\÷FPœ ï¾˜-膵½Ôж×2y·¶7KAßáÏЇ ý•ÌwwW\ˆ¾—Sßí…¸è{G0KßH%²À×®ôKìCxüúÎçë ¥‰¾·¥è{Ï®ÖWl'võŽí¬ /úÞæO¬õ=XƒM±P„ÌøÎDîFàÛBUø2„ϱIñ#õõ,â˜úÆêAú¶0¨¯/Cóëä£þ¦¾”Œõ¥œK¨Ï Å#¶3 ‰í<ü$Ÿ/¨‰/«bÉç³Íc /aáQøÖ„ˆžŠ_½^¡X0÷®É|ø6›@}Ï“Ûßé|ˆ~+|‰# ôõ$.úúñ]xçê»iîA澑ëªðÎË×<ŸWuß9îœã;ŸÄiφâ#¾3/ŒÁ¯/Ñ~-ú·Á/4D¾l8¾³ïÑÌŠý®|Ù¢òÝ£…Ãêu~†¿æÄ©Àß·­ò]C T|çHû4üáÛ¤~mû˜~¾àï´Ädø{¶ÛšÞêxëuŽïÜôPþ8þà¨ÁßsþŽü=†í ü%h‘ðwº>eà/4ð7Á©àïðHàït†nàïr]‹Àßå‚¿{ _þ¼èø»¬Uþ’Û/úB …)ï;ðÏ©êÁ¿˜ÿ¦d?ñßå™ðßå9Åñì4^§0Òž^©}Ë1ÀÓ“ÙàßH4 þ):,øw§Œåƒ ô þ]顦¿!¶ÿΞPRñŸ^ƒ8Çs.| ,µ ÿRdvÖù¾È|Çøìт٠ø»†À(ø{¶¼Þð·]îWìw.9M’w›þÆõíÕ‡Ðïh_Ã;c9ðÎ[êÅìx z^KLOámúÿ®,9Ÿ»åïiÙ–Urîÿñ;¿›ùwÀñì»=¤eךÆß¾ÛÅ?¦̯m$uÛO]¹eêJMSWi]•Çs·[FWn]–©«£Õp1uå–©+5M]¥etõ/rP4?—èáC…9å[§}¡ñ?Ëe|_ãJõÝó¶gyÞÎÛþf¿t:†ÁÚ÷ĺ`Oêß¾{zñ\^ÅóVîª?Üðü÷èÊ sWc#w5oå®ÖžSWn˜»¹«y«tµ#úñšºRë«l”®¦­Òt¯õ˜ºRë«l”®¦­ÒÕÝÊÕut¥†WWÙ(]M[¥+,ØóµRë«l”®¦­~õ™îˆôˆ˜Ž»ÿvW;~Ï]í»§ðÇîj¿µÙWwµŸtwüd³¯îj?Ûíõ»ïÒÜÕ~a øÑ÷öûÏþß~çÓ=oõ£Wõû¾~çFƒ>æÏÔ/ ¹ù|ÉälëkÿËç¯À~_ùŸë±}[®åœ¯¿n¨añ|›þSÚÆ¿þ3ÿú}7ë15þÇÓˆ…[Žwëçßp|°"ÂcøLOžùôÆ£ûŸÿŠåÉí¸þò?ýQÉ3üåÉŽþ×üëÿö|7ñµë/ÿù?`OÏÌ÷/ÿû_ÿíùíÏýŸùñÿõWÐÆÃ‰ù÷g3xÆÜúíÖ¡®ŒÏaPÓŽ·aÝ> ëö2¬»~êU·Ó«Žÿojœêöw/ÓÓüOìῌ¿‡9Ýñ æt 1`Moóhój]|]kZ ¡Eu)6@øœ+bëVe1±lÅÉêºcÚVöv*'qLÔâRM*Ÿ©)&†ãœ®gIßXc98—^YY ªõr¿wɲàì]Ý´šü‚¡wÕºhå Û‚³k¤–ÜûÎÖ§Ô—ª‰XÆû.º·bY ƾ‡¡×rZ.ÿiù£oµÞÒ×;-{Mbª<‡êE<$w;¦úÜ5âXž ž™zK­­gê¼bö¹?Bžë ÷ƒ~¨¥¬ÆVð&¯ÄÖ*éf]`%/êÒ¨Öeï)ÿS¶kër9;jgR˺ FþÅ'Èz…i‚K‰–óÍ R”*±WíúdÉ”™aÍußµ¯£ÜéW°™,˜Ï²#XQ²BRÁ˜¨Š)¨ܶèÛ1úÔý’is«\jT=qR¬x|Pþá›õ‘Ñp;ò !¼ÿ¿Ù¾œˆºÉ&©K Süd»ÔÏëny·Öð^Þ9Îs©pé›3Ò±5ª8㬠F«'D£hvÝqœªä~x]'P¡cá鹬¶û.ÓL|ÖY]ù¡µ£|«ôͺ—Ç7Qïi]g븀°g‹ ZĶ‚¼DÊÍ๺›p±þ\ øKwFD}m³ ÎÒ5èÔÊŽ¯Š—~å°þó*Eí­AðápºW·ÏVÉnn,>öJAƒ¼cnÄJcÃ6VÉ*.¤¶q¦h)×Û\ Y«ÌÃçr!ßjQK¥?AÐM¯¤Ö¿rÆ’_?Pô¤@7ݱÉá܈(8š]ŽêÅùØŸDþæ.ѱ6¡pR±Ú×§ž2Ï`a/+*€ðmÀr^Vœ8oâ‹ñ²¢ !­‹—õ€{ýÉ–R[!7hAéxYñ¢pÉÂ^VØAsñ~Îæ®Kj5I2[]®Sä ¼¬ˆ.¤„u_µêÿÜb[`m‡¼Z‡‡¾°ÔŰiôñ¼5K%ÈÏÁ {,®ì]E ëÑq9ÔŒª7¶91ªŠõÖõ²N‡ªQxcqù ´½’8Vcr¥U£ðÆ¢Ê …”‚»¯ÎÝCÕ¨zcû½¡6ÞØmwÞ>xo,†®•Ï=>€§ó©P6ª¨ß–ƒ-5²®ë®ø’Ök`]¡Sò[‹ºQxcaˆÊÓê+FÖúˆsqe£.Œ«¬=õ cëó›¯=¢rŸë—+Ÿ~ÔØº.)¿†ªQÏ]¬šN[Q5êÙºCËãà€ªQÏ ‹¯UçÊR¯b üÕóÂ?/l¯Ñ‚ûj5¸öªÌÃmz ®[-3Wá¨ç…Å.kõõi(5@G]¾ª…±õ·‡×:dÉ m«ÒQZQ‚¦Î³JGa“M»Fé¨\QbãpÏž—ìèâà e[½\5¸BÀ?O¶Ü5¸ö]óŽ*õ<ˆ¸ŠçÉnz­¸4ÇÆî5¶ö2{¯_•‡í]ç´òøP:êy]û••$<. (‹TŽÂÛ éž{B騻U¿:<ò†Mðmâ6g¬Ø¦žó ÏåŠË ï0n‚Ç¢¼·Æú”`­œ³™*uÖoÚÂMZ ®(„á^z ®©ZÜ…£žwÁgœ(…wµŸJú­ÊQ÷5̶ÕàŠëÙø›½ÆVܧŠIÚ¶£†VÔéXxÖ(õÌ, ¬<^Û/{ݦ}á6W ­¸¹ºOåÿËe =55~®Õ&k¾ªÕ°†±ú6!ºaë¯]õZñ£Æ§±åÏñí «ªºQxOwÉžÏa`-ÙƒªFá=Ýý&?³ÇXñ·5°âpuðÅÃ{º_zO«jÞÓ}ñž®W{Í ¸«»ÆÕº¼)(õœ jÎñ9Ã@·´ªÏ±ß^Ãjc݃ãù|à-Ý”!Z5£ð’" œe¼¥p ç¯ÑŠWJç÷Ùßt^:8®á-…8¿òGxæ>ˆzéúÍY£j¥ ðÊ o)t‡ÆnîUqxz€–XéëØw«Qµ#¶´®Hð–.y€á‡·‹|ŠP4 o)tǛ۬5¨âjJ„šQxK[ƒÉ´×˜ŠûíŽ÷ò:(€Ø¸ÍQcj/÷ƺæ0Ä{Z…ù«R zÕjUC©½*±òG(jR›Ü¼|^—[}Ù§.ôwÕ«9Óßsð*loü³3‹éoÓ“üC>œÈü‡ ÎÍ»gÓæ?¸H¨ñ Jô#ñߣ]þŠˆI×x¬! Éï„ùs“ã˜ù¡*òFü»«ÎÀŒH´5rÿ0q ñ¯y•Ùô‡¸Ù‹þX€›Ûþµ2ªœù¯¡0Ù2ñÚ5¤ŠÿZy8pò<Û/×Wªe5U‹ø×ÊÑmÆ?TÚ¼`Ä?L‹Î™þªb£Jýþ)Eˆ¤?ÔÛTÕÂçýhYUÚ…ðÇê†Ü†ð‡ÍRĨ§œ§Â¿ª’ÿI5³R'E,󣺡PÃLØ.ük0„’4Nþk¬ˆ£¡ZE583¥†(8¨9i£†¨gîñÍæºä?|´ ñ=…òÂ?¼ò»Ý»8F­«˜×­ŽYàµÚSô‡¯–n‹è_¿euPqQÛ9¢x9D-Žë\9BÝÞà¯W4ŸXc¢Ë$ÉiŒŠã,ٯ朒ÓN QI½¼4B5?yB?œW¡ÆX·ý¦nH~˜Íµ>“_Ÿ‘ߘšüpNœ&šüz… «…ƒTv%ðcŸÀ¿áÜ]܇‰´Ž—܇£’ûzyþr rß˜Ž˜û°}ÑÄ}XBÒ“'îC…2­ƒ‰ûp0[Ì}¸ zÅ}}Ï3-îCÏúÒˆû0>î¼4â>\>=â>l£ã÷¡…‘°£5ƒFH}ñÁ }*\½ ôõÕqÊb><Z@óa® ùPŽg(âëc©Oćqo5ßñÁþ¦ o¾¢Ä{èEû!îa¨Ôð&Üë‹A{ˆqá$°|±’õª ]ýÕ8ÚPªQÇOØk˜o̬‡hÎÉÄzøé&ö«a5¿ô®õª”Ÿ1±^U@äUëµ²Y¯Ê‚Õã.ÔCš(o©H¯ažO˜H{â$ä‡mô¬ˆôÚ5EzÕÂ9H¯Ê– Àˆz؆û2êáˆùÍ6ëµÛ“S¡^Õ…¶êU%Cñ!Q¯m£¥PO7k:Ñ W¤WÅï¸ ÷ˆ+ÃyŠI¯Šç IzåqKx%èU•ÇÏÀ<55N …y5n3æURƒGQ”ÊÔ6=iñÄy£u‘ÐÈyUðùqEõÉm ôPÈyÕžzØ÷~N ‡]û`š†ÑA‡½Vc4¹‰ Wkæ× zU\ðEz8¢9¯”á ‡‹e#éUiKÁI¯Ês‚Þt’½æÕfs^Õ"c’óÐË=s^.’óªzíª–ÚºE•çcçÕ)qÆNÐCñg‘ 9¹Üü˜óš×Oy¸¼¢<„ì‰nDym,ó¦‹)Ì›…˜W§À¯QLñÄVâ<ôl’"èÁØY×W¤W{çb†H§©C¤×*회V¤7í\¤‡²ã‚DzUË»nŠ@¯Jyß3èᳬ«aå ¹º!Λî’8¯ºáoÈyØ„kPÂ<ܽ:Â<Ë2S^­HP˜ÊåáàÌ^¤¼ºÛÂ3RúðŠò¦«IÊ«Rß<:B^Víäµp!¯¢:jñëžtæ<äœëÌy§‡qcÞí…1s^¹ã¿8ñ½÷¬ó=½kš$΃±¸¦ß½¶øá2èµ%Ô!ЃA‚&8VúV_è(}‹?lQú–®+¥i¶ûKéC•"édRúÖ(r$½ñd„ôÜðúZ-÷Ψ‡©†æRú0qÒž$õá±R•èB=,Ü-.`ÌÕÈË&æ"=ŒÇ—kÿr1òÎ$]¨×ï+Œ¶h5²ùV õ¤ÁZ¬×;}Ϭכ3¿„z(òµ©‹‘‘pDze¨Â´$½Þí(Ðë%ÙÍ ‡`ã!…¾eq¾©…>ˆ Ü‚:þnB? }˜OœN-*Ý¢è>“^mã*UTú”4”G•¾¥‰>ƒôž[}Zé«%”SéËñYèÃdF úð#å¿JèƒFk£a }8œ$ã–l°lvá–ÎW®Švˆ-Ù›8‚˜Bºq”l }ËvÇw”B¦V‡ÝZJ6Ø®(ú–ˆfú–¬*XèCj˜â%ô-[bŠE{·e*ë|u4ŸÁzÕ‹ö$™oÙ]pÛ2Xô$™¯Ž¦.ºe>¤¥Qš´Ì‡–þ’ùð ¼`¯Bð‰\TùpõxÀVù–¨BRù^ú{+Ê0ï/™™uülXæÃ£µIø#îÁŒ_Ë|(ùÌ6îá£Ê‰e>L¦%š ÷ð)àôܸöâñ÷0}|ѢॠŠönË›†=ë½k1¤ˆö2&÷ÊÐ9 ÷Ê÷0ë9%è÷Êy–ø°À{ ¡|p›$ øòÄš÷6û¹™÷Å32ð  5ñ­Yx2ñ­·Á8ÌgTQ Pa%b>`¢6!òõºIì—ȇY.3ó Å|Èáb>˜§“6Å|˜¤ Å|¸Êë›ùœÊlyoqÔIÏŸö ߢiàŒ|œ‰äsL¿‰Lt¼ˆ%륞™ønÏ&M|F:á½*SIïµ(.><9Ú†Àך:îaÔåtX¸‡±PpGÜÃ¥Ý%õ÷U)D4ïÝ–WÌ{]±!Á=Ü]¡x¯9È'欙ãE|H×”Ô'âƒÿ£ä@²á„s"¾pxo\M#nÜõB¾vøù.™`‡øÊŸPJ^r^ÞÄ÷t"ê2ñ!¯ÝšøàƒMp{ßÍ·"ćùËý"¾I+ÄwZ¿4ñÁªk#ŸÅ(ßíEñ|.…|·–ª‚|»ƒ­òmF‡ ß¡³ñY’ñeÙÄw·€D>äÖŒ|^|Ì·éàÌ|ÈŒ=ßÌw›.Ì|·ÃÛó]¾ûf>¤(ŠQÅ|—¬êòyÍ9Èwäþù¬’„ø6X«2¾q! |Jv ï]d;±Þîw"°wùQ0ìá¤( ö.ýEÒ;•‡7ƒG‰Azòפwû0Mzp“Z'Ô»,Ô ÔÓTwF=­’õ`Ãب‡CÒ Ho¨Ÿ&=/ËÔ[rxB=GA½sô¼ß3¡3Þ¡X[á]ÂwW÷¨,¾»¿Óñ²Îb¾áÖñn'\ZÇË´Ã2^Vx"ãaì|ÉxY2:^‹ø'ïiÙ_t‡_‰{,äa›s¦;´˜%ä¡ç6Çq¢E£²ð®ŠhmÒíj@ºsß„w÷5‚?‰w•Z,&,¼›{!ÞÁBKùâ»;¯¸ù®:Þf¾«¡ƒt$%¯Ý()yc)yùäGÉÃxÆiƒ•¼n£%+yø&¶—’×£¸ZɃÛ÷$!eéTƒLB^ß}=¥äÁg“ÓUñfOê¥ø®´4×¥æ€o&»¾3ÖÙˆJ•’סb¾Ã,B»Ö®ˆ…vcúd´CË>‘~"ýGd‡YŽ`‡q“ÀS}Àv˜Xë#ØMÚ´Ànè0âº1…1×Õ ¿¤>r]¦0ƺÆgYL<ÑçCLWÊ÷B¦Ãt@” ŽCª€n¨:ÿsã`”hÑÆ+ÝÑ–Çé(ñ#OC0‡‘¹X®…4ÅrùõP榯¯†`Z†^(ÁFr‹s„9Ä=è»,˜kuø+ x‰Œ‚wN|GïÈCjsSƹ#ši.LÁ¹ãxGk¶Šç|á|GxÂ9„º…+¤CR7Ðaæ)’ÑíÓ6ÐeñÆ<çeã”ñ7Îíkâ…s[ÔãÜ•Ç@cpÊhâ¹D…çä`žƒ¦°JD7âÂDt¸„b1!Ý–™­‘– œ·é6+¢AºmµÊ'¤«—mŽÕDÇšzé6¿ÐA:¯‡èV‘BtÑÜCtÀ"b èVϺt«Jî„çVyVçÖÌ_Ísµ¬9+xãØ„s«ÂúCskäÓܪZ˜¡¹E„¹ôj˜[ÿi˜+Ï¢æ py:0·4-=æ¦Ñ¦1û‹æP€ü¨‰„cš[d}˜[— `I”ˬß9h+4ñÁ4—Ø>ÃÜâ¯N`n1 ™åÖ°a®–õ^0‡o†,sË‘PNÁÜÔ"˜+ã(Iz=anÅ æ`J9L,—IPXýR×6Ìyd˜»Ë˜ E˜[Tø 0·è/Œ›w&%†¹ºñë æ0î­³rwgRg »ÇB‰ˆîö\Æ@‡~wMt0\ÑDtð»y~å²Çî—x·8ÈX@wÆIüF »{B•Et÷XV"ÑaG’wEtwfI"º{¬f9³3BÙq›‹xW±Go¸ÓÔÞpS#Ž‚„;¼ºˆw/œ“Wp‡qÒ½H¼ƒ-Ëî C3Ý@ Ó]Õ ªqHp×ÏÌÛw}LIw0·ãà%¶«µs&©ˆíji¿6Ú­°X9ÔÂ=$­ˆÀ”¢wΚ=‹vGà@¢ŒqÔƒD»úøLT×§\A‰v^”ˆh×Ö/ᙽª°E¢"Üÿ(Ñ®lJw“h7r=,ÚÁ èx‰v` .;[µË"WÒó†€àô¼¨"ÎÎ ‡u»±Øë½%áTÖíV[H ÝÎ¥:vÍ.‡n·Ä‹PºÝb¯xb]ÏK¬ÃêdJD•ÐS"XT¯*ÉmŠÏÄ@fF ÐÓkhN”iÙnqé?hVâÓ vý¶3šâ3aŒd»#ÆgæK’øÌî¶hŽh.EhNè§ÍrWä&ŒÐÌw.šCJqˆæ}‡hv/–'F3±fíÀ Ñ|6QÀ³C4Ç]0Ú•UÕÌvHÿ1¸)FóéGììÍñd9F³Ù¶Ú!šW¢Î-Ûµ¼ÛŠÑL¸°c4o;@+DórެC41/î³f‡×RæÍD›D³sFN"4£Ñ[±Ãø(HS€æn¶b—ð v‡kÆX¯;mÚg½îL„õº#K-ìF»RìÐýýRìV•I°ƒYžº•b·yE>Šz!U9@ÓcZ;Lþ·W„&‡›H°[»Ÿ²(vöÇJ„&`±Îõ<™kã݈91ÞÁ¡M Ÿð.±jÁ»¤’›îP-ˆ©é®%¸Øš¶NŽX·x½At—¸!Ö5ÇZZ«Û½¦j¸ÝŠí.Õ霴:½ÐF»àô$Õ"wÈÃ㡉íÐË›í† àÌf•"bÝá›áîÔ~g*Èo„fjUÜd·zU6¡™þDvY¦±™~šBvP:öÙÕ3ñRëà¾Ì=‰ìFüfÂ3Zg²KÊbÐ.ª ]V¾ƒv×™HK±–¨îÛ uÂp7®¹è.1Ø#>sÉ*>sË&»ëÅvÈs• '¶ƒùðýŠÍü^ªƒ¯2/°ñîìŠÖtlæš0K)ugÚb37?U†;xÌm¯àÌÓ‹»;¥v¶8:3Q~¦»ÕËéÁ»q5wgr¡ž¹„÷Äw#ÙP|w:µ#€w®Žéßyž¾Ce»û%Ö 5Þ 1(ñ™Kv$¼ƒÄþÒê"՚.¹ù>.b&ñݸ/ë|NëNc­ðn\†g:Þ‚¬G_ix#©(Œ‡LØãUðhŸ‹kdn‹vðö“P(Ñî\ÌØVíÆcdÕ.“õ ¹8bS¢]âýÂx§Œë#Ú%±8šW¬Ù—±’¦Ì"IIvðýzEgÆQ$’Ýs8êN–rÏ”}yûú”ÙéóyNBn™­á~ûwc+oóç,å¾ßCZ†ãÚ×]ücjŽkåWz¿ºrËÔ•š¦®Ò2º*÷ìóuÞn]¹it5Z¦®0±Ü_]¹eêJMSWiùW[Êí˜ =—îOYÊ?²”[Ï/ÿùÕRîi=k[úmñ úÑÁúë³éÕ×Ç&fý¯ÜÕp‹sW³[œ»[©«y#w5ÜâÜÕìç®ÆVêjÞ(]Å-.]Mnqé*[¹«i£t·¸t5¹Å¥«l宦ÒUÜâÒÕä—®²•»š6JWq‹KW“[\ºÊVîêOXÊÁLcy†÷ÿf)÷K¹_~ô½ýþ³ÿ·ßùtÏ[ýèMý¾¯_·”Û+]iŸ-åäwÿÔ ®eÃÊýÀ™îl?èèi|[Êý9·½Fïÿ7Üž/îüËÿ2šáàöí¡³ö\£4·íç6nϽ‡'2\ÜÚô<+KŸ+Gû†ÞçQ@i¥ƒs¤±0)ß eš‹|2¾ÑþúÎ$qßZyÕ£üg:Ï¥Ä4¨Â†º&[¨MHØ÷å¤Þ£žç Ëk½Å©ã9Í*hžiØÓpS‘µ²»Ãûj›âÍv[ÝGIõ5J?,ߦ@ŽŸëJyvb®=Ô°ì~׬œNŠÛ÷¶L ;¼‹j5íÊ»ï ™`Œ~ÙMJ¡ß _äŠý¯ ýXoÁïNð@ªH™ý¨òÀ~ìeö «j–?-‹ÞNŒÝÖ·^Ä'°ŸÚÄ3Ì­ª²XîƒÓЪ`çSøOÉ;ç.³ŽÛ{5  ƒl%)VKùì? ›&›G¯õõʇÔŸp¡xVÖÓ`Äòp“Óú~²ºýóƒ?-UÝæù‘*Çíç^Žo4R«ãEe¼Ž~\U#m—Z†·tSKhQ„çöïµî½ime?+ÄPªj‚be4º²Xµ±î þ¬µº*5vvš¸f²ö̰6¥ŒW¹$Ì+ðîÔ‰_ÌXQO„ xÏ0…hº]Åʱª´½r­.Ÿ«üæµòs¨ hiÉj¨1tÄUT«ÞJ'&%T«ã(+óUçªuÒðÒ¡¬Ê~0þ„ß”7j%]njhÕc››T¡+Êá—ΩwFy\Š¥å" /„sÔ°[¸ ? ^ðJ’ůšµMŒ9dbvô0^ã<]|7ÜZÌwàL‘²ø®„Þ[ÄWãQ¹À°K¤_ŠÁ¼–¨^åWðR 𡽠ð†{–Þ‚Œù1àõX²ð:åŽÁw˜çQ7àõ•dYp‡I_bÃŒ"¸ë‰!5Ý•:Mt‡ ¾¦»á¸iº«š©;[HwpÓâÜXtWQ-ê†t‡`ZCÝõ,îzæå‚»~:ìÑp‡`ŽKÛî˜a¶ë1ç0Ûõ íÕHä w£]O£Ø®"Àø|ˆíê#É=‹í(ÔsG„;Œ º÷‚»îœ Ã]ONIèáS$XãÆz‚…ñaY•p¼ÃÈÞjÂ;Œã׌w#ºÇxWW ðN: á]¯•ð?¢Zf¼ëñäßU/\–ßa.¢¾C§Œê6ß¡=Vâ;\ Ææ»i¥F|‡±@Ï•ø®'%Û|7–Ìw=qæ»ÞíÒf¾Ñ\æ»éÅw˜jèßuçïF˜“ñŽs ¡]·u—É®'KWdדÒl²«‰¿ "»áãl´ë— ŽCRÂŒux­õ ë*ª“›êàáÜÄpõOø©ÒDuõâó6‹êÐÂóÔõÄŠê°†7#Ý0¿3Òá7çDt8K ø":\~u-#¡hšùêº%?3ÝH@3Óµ1ÁÓùhMtø›s2Ý tEÒôQ@‡±„³Cñ\ÕbäŒZ<‡®ºšçð€¸…<‡££¦,œ+{3ö[4‡p:s›æê±¼ø›¢9l²‘îsívÄYÁ\K žan¤$™æ)#f$Í•é/¤hnêF4‡ ÎþsåDJš"Ëð³\7^,WAe3ÊUôÒ6£\Ež¸¥†ÎV‹®ì†(‡ø NŒr•¨,H,”C|GK£\³Ë¹H ï4Éá`¤ú åF@‹Q®b%8OÊ\%£ÜÈg2ÊUYPÞG¡\!LrÕŒ$‡+ì$É!¡)-Erø¶ñ‚ 䕱èør#OÊ$7 QkûËLr—à'ɵ|;LríðLÐ$‡/¯¯H®ÅpÓ$×< 2É•mDÛÕð9R«Œs膋¢94è¥Ε•.!C@×bn¢kSŒt• E¤Ó³Ó¡_¦™éð£63]‹Á©˜ûtˆé0ßÕÑú…÷K¦C4&c¢ÌtÍfºfSq#]¥ ðú‹éÐï›éÚ6ó$}]Äsø…t-޳&º‘ d¢Ã6â.ÝÜ1 wX@‡'W,Y<×2/5Ï$5ñt!ÅsÈ%cŒ«y®m‹V„s_:±fuÕþ€%›iN²ÓDsÎé6ÐUœ-ÉŒ<‡{¢É xo‰™<‡wOšqn˜ ˜çZRÌsøTq0Œ`‡ä6óúÑhRìt8‘ì|É£C{3\ t·×ÒÍs‚ŒsUê…sð¿áü¬p`~èOŽIq" Ò5»!éÚ®Ëm¢‹QTˆ“R!”‰î šèŒ9ˆÎ_çKžèÓ%UO@w;ÝH‰Dg/¦S­ u‹ª¤„éìZd¤‹_å"$!]<éƒtƒQtËîÛj¤[ìä¦ÃJö¥2Ý’ÇÌLGÅÉ@·Ú#D·:2D‡‚Œ‰n±[_+8"ÝjóD#¾`ÔµÍt66Òébݤ+¨z!]$tmBC1ÝâŠfºbõY±Ã®x#EtÓMÑõdšèð4˜ªDtC>1&º<Š:¿ëG:{5˜çÆIšçœôcœÃÍ-¾#Î%ù‘8'åÀœsÍr ›Êe ‘\KzŠI®,x."9¼‹ú.ˆäZÖùLrÃÁ$‡ÑH®%!É$7ìLrÍË×&¹6!"I®eqU47(Ä87Ì`„s­*mÏ87\¬ŒsÃÙ8‡o™n€Íæ–Bºæt] rMt-ÕsŒt40Î —`ã\…<÷Y¤CŠü¾¼xßl¾Â"ºòÔ¥ E ‘þ"ºrÍằ"g s3ó\ Œsåæ*L$Ï‘0<—8êð\âæCt§?ùAº”¼ ÒÎ ÒÝú•.Uf‚tMŒt1Û Òe¡5L—aØP··ð— n .k¼¡:L©©óê²ú¨;<êð‘Hu‡SNuñ; Ôá+»’DuW—l&¬+ïÖiçÆºÌNu1QÖ#6Ö%j;X·7ßc"Ù1©nפ P·9%ÓT·;`?T·g¾mªCæŒøLT—u÷PWBu’Û^P·Gp0ÔeA%T·Ûñ$T7ÇT—ú@¡º€ˆ©.ðb¨«ƒÂêeêöè,¦º”21ÖmtLu˜–sG¦ºÊã6Æ:h‡ê¶žcÖayJ»Öm6» ÖmkZÄuãh„u®cªÛ.ïÉT—ú¢Á:G³„ê\&)T·YÍ6Ô¹äÔ€ºÃ¸+¨Ëz~ Îv bºÀ‹™nµaV˜Î@Ât›íÍu«s€uö|L·­Äu«ý¬ÃuÈq¼f¡ÝìýÅuã%6×Å-#`—ZC»ÌOvÏ£eê$Ù­‡Ù`·9b‚] vñ ØÅtÝá_™îRæ'6lAºVò„tc¤¶H÷ šwêÆ¤×P7fž†:Šb.Eu¹à¡º5Ó`S½{u°Ø}Ga:6L·©ÚAŸ«ý…t®<¢Ë ­‘n“+äènÍo…tuÅN…tS n“?@ˆÎ/Y€nz€Îšsˆ.•†Fgù;Dײjm¢³wª®Ò>—Y¢6¨&:¤Ç/‰âŸè8Dgï‹At§Ÿ†htKSHwçˆÅtkVë uŠÑ2Ýæ‹i¦›8JL7@%L,1ÓÅD"L—GaºÕIca:ØrK$4×é[6°Îö‹ëvƒª¨nÍDØT·ÝÕ1ÞT·Ê®"P7qŸ¨NÖ˜ºÕþý:`Ó912¿šA:[J‡èjÊGÏH76Òe?&:Te½g®.·d0]†Ø=BtëµMD—‰™‘.YAº˜2Ó­ö Ó­»¹ðæ8gÔÅj? Ýz8ðST—°dësèS|&}.΀ÑçpáÚLu=ö;Ñç–¥Múl'úKŸ‹ÃPô98 ­3Õ;õBZ ‹.èbül¬›ÈOXgO‹t±“Õ@SˆÔ]_¡.κ¼êà ¡~EuøÀ ãuƒ¤ v‰¡ ص¡Ü ìâæ°sq€pÝ}E/Ø%7<`§'"`wËÒÛ\‡ ŽÂ»x6„ì*oZºœÈî2/ ìâë2À.³ƒÝÕ²+ÝåoYÀî’YW¸ÓM*€;× ×¥ö]¸.a×Er ×1ÛT—ÄæPÝÐoLu[3ÔE )¨CƲ@ñN ‹1PP—*«¡ºs÷,ßTå~#Õ9­yhu6Ø Õ ™ÈTw¨RõÐên¯¿‡ê Í:Û‘¨k?AÝqgß‚ºÃ®û¦º˜‡ë†f%¬;lo1°NΑ¡:dý_j!Õ%HÕP7ÓT‡ê‰o©n@¨©.…/Cu‡ ÆCu‡«’ ­Î¦ C«[¤»†êšÓRÝâûª ?šê\MzhuCü’Xž4Öív—Xgï˜u#œÓjÝ1(Ž\·;lÒbÿ¶Tç…ÿ¡Õ­­Õ-‰Å”T·k©(J1†T§ê¤C©[li©ÎT¨» hC©;Íp„: YfºÔÔùÛg¦›•;1£ÌÔÝ Ò áË2Ýõ™qîL¥eºK«ØC¦ËrEdºK×Ã4÷l©¸Ú¨t‹ãÈtJ Ì þŒJ'³è°œ¼»‡H—ï¶EºÕb 5ºBD£såÝI¤Ó*ŽIΖÀ}ÍP§b3Ô-‚ ÔÙ /P7âg u»+ç ¥.+цºØqêR“ÝP‡Éþ+µ®GÜ5Õõ+l(ª[—µ9QŽX×S”ÁX‡¶Ï€ºJ àñêÊjŽÉU¢ºg“ý›TË©¶Ü3ÖUr3€u+»E”ÇT¸Ó³R·®®Ë5’ë Ì1wMÙukMƒ?ìÊaή[]b&ÙuëúJ­KBDRëVWù©uµºúX÷ô1‡]®Ûóåv^ÝF›œÁt+“9¯nƒY㼺«}É«Û}%X·=³ù%±Î©#±ÎfìSbÝâ9%ÖmŽ0™u.42ëœ7?2ë*˜á3˜î9)VDJf~´¿2ëÖHjά[ºêq&³n]¹3ë–Þ W̬ÃÔ«½2ëVTñüê*%rVêž .æ±$±?9g¥îiéîV™uësLœô:µ¿ê<^E_ÂU¨½¢/W—¡Jôeù ½’ëÖZÜý ²›r6\‡Ü©jJ®[]æ)Éu˜b2#ËÉuxîù”+¹n­bàŸv•tâdºÊ®[m•ìºUö€L®ËåunÝÒ„íܺ•ßÞvÏ6J&JnÝjûÀäÖá3ÝM©uh€)µ >!N­÷À©u«óY‡MÈ_J¬C/¯¼ºÕ…·’W‡K¹©…yu¸µŒ‹T^]=3ìFyuسrÛ˜W·Fqw^ÝRVœŸvÏÓé›ïĺ%r§ë–vëqpbÝb¿ö$ÖáÃRN…I¬ƒ=לX·TfÝÚëAlW–›;Y™u+ŠÈò•Y·VhògÀÝóÝ»¾½Â0Ÿñ`s¬#3ëàÁ¥Ü5eÖÁ#´‰÷*¹n½ô,&¹nÅ$šý*¹n)¥á3ð®ö$ NÉukÅ}ß=[PÍÉu›|6’\‡Ä4Nò\‡ÿU¨“ëÚÆÏX’ëpo^Á˜+öpR>SrÝS4ò ¯Ç¦.ÉuËsÇÄxω^´ÆÉuûåðK%×á5ÿ Æ«ôµ9·ÎÏÄÈ­ƒ}ôg0^÷˜ù Ä« sn#ÄCÅiͲ„x“—r#ÄC,ò:§ÖPd#6 Ñ­Là±!š/Ux=Õ‰x= ëB¼^Î3âMi@ʬ»‡*§Ìº¤þ›ñºkð&³>ps4f9²¶ñàÛøFÿ¼7Û ,zf ?ôf{îìÿùïqNû™AÛ³ñý+Ršþkúç?hÕ65þÇo¾<¿ïÚvîÆÅ§š5ýi@¿BtνêµWÆ>)ëiAeÅZ‘æ¤õ¹^•rvgÒz •M`³]ó¦îKW+“6®›?-Ìx§úßyìµÞR3MÛ ýšÑWÌ>:̃{‰Œ¶zZõ!Õ8¤R—<ÈÙúy`Íò¤u¶zAêÆÈT|þn.”|òP°þ³ŽˆøgŽ]Á#=~Ï,³æ R2àÓÒª6‚­ÊÏs«Å `"Õ³ý»29•=ñ´õ™Ñw…µÂ2{QŠÊùüñžKh)V*;šúö\Wjèi)·›Z¨yéybýçàZ‘ºEÅD,AÉrë¼–…ëpXóbCãúi­?[ðï§ {œÕ,G»ï~9§\€zZn.Äٶ뼎ªPþìørÏU» -·ö|•9˰°Ht&jÜä.¢÷Z&Ö ÀÓÒË8gsU²óêµXµbù VüŸkwpÅü`zÀ3×ŠÒ —Ç‹›`¡›œ+ÛCÝZ2?i‚s¢ìàdÊwb&·ž\¢îìxÈ5tÞ·¥åÐri‰õ¼¯ƒ+æXÎæ6÷J‹«³‚ù°A„©–vq¹Ü‹çÍ…Òukrö;QVéÆ6½s¡æ¬ TØÆ¹àgUkt™«E¤zÛŠk7 ºz¥ áz>ŸýZZ8ñÞÑàê  ž¾,Õ¦ê.à]ìÇ´€v– < ¬ø¦#¢¡Öáv­RžÇÁßð`Z=Û%ÕÜ<`¸‰ÕÃwRü8+­â¢¥·AÚÈZrÎÂɳü$.®øñFÁr¢ÌŠ'^s¬Â­X[©žAÓxMñès_àçZ0/m½Z°@€C¶A䉋­qÎÉGfA´¸ZiFvb™oêZZuµÔB~Õiqt–E¯ÅÅ•}дÉóêî<ÞZϹ`èT¯ªK²]X‘«WcÏV-ˆ*Æ•8%~\ Tló|Ôêú] Ëçݸ£ãæ«ê3¸\IûºÊb¬dšÓ^øÕ|ܯÝÓrË6Rêëó±9èrUémÕÒ+Z­VCÖ ;{®%½ ÿµ\ù?Ù‚µÂΕÿúz_UêœV³¯zŠ$Ô!W5*lâÄÀ 7ë”·Ö¯ªFU®`²–»PŽªÖÍáb·WËuqÝÜþ}êQ¡”É-…üªrTXÜ´s¡ÞW裼ìUêfÙ"ž8>„+º”nvU=ª6I]¨Gµî“‰ÅUõ¨¸¸ÉÕ•kÛš‹xü¼ª(U¯0.Û\U”ŠËz«/T¥:jqqW¥:˲±‚ªRíµŽ³ëo ©‡® jRmdÀ¦SêS÷EñæöžTÛ«jR]ÓjÊUÖ™[Ù/,úÕVƒjKŸk¯HR©¹vyUM*æþ1öáBMªÆ$HÎ6®*JÕø«“{‡Ž>'J^U”ªÇp᪒TÇ(j|•¥%7àÒÙU%©ÎŠÖ­Å× ×ùT\¦¼ª  ¿è2 "UgÑbïU©®a¥p¡ •üjx¿ª +£¹ßcc!ÙÃ'X©nVŸWCp-n³WÕ£º«…AçêQÛTvýªzT­¢Ûj•ú:(!3‹W¤j•A¥ŽO–M•Q®*HE;]®_Uêd,[c Ttz.ðÁ«‚TU-V:¤bÍ8]¼ªGu±`,_&Ô£:×Q&ýªrTs$Ú…zTÇ:ϸªw}èèÚA/_Uêž*\¨GµmS©‰«êQ©d,·A=ªuŸ,®ªGÕX_§—§¥FÕT‰¸ª lè<«ý‰½+̇cÅuÑÆ·ÎxR(Iµ×±èž8a¬\lî§­Ìèn~hª Õ5¥b_¨™°r-YÞ4㫚µë{]™Ñ-¡ýª‚TwE¼éK[°Îú ƒºª$Õ]½¸ß£FÔªgËMê(*”NOLÀî¹ïU%©zuÃ÷­BeŽùèî ‰BÄ›«*IÅØE=ywç~y)«ÖøÈW¥MFã1>üª<ù‹©‡<ØJí_G½Þ«‚§SF¹™€Ï>‡Q…÷6›n…÷ö=(ÞË…÷×÷ ïåõ1ïÝqT1ïÝN¼4îÁ”€ãŒqïN„xÑOúpoq­q/N á=§™˜÷†Y†/o†y/Ž&ƽ§4î!É_×E¸W¹Ü„´×RJÔ´×S‡Ø´WU˸ a¯&¥œþ‰÷†×‘y¯ŠÂ©ò^éwÚyñÆlž´p¯D{î ¼×á•ÀîaaˆŒcÜÃD¥®¬io M™ö–]ŽÑ¡½ªäÅmD{˜nªcáÞâifx¢=)ïì-·ÌÀ{¨åE®7ì!ŠL4%Ø[îàŸho©'ê3Ñžª{M´‡Ð‚‹(GÚ[]8´W‘0ý3hou1æÐÂÆ¶í­ÔûL°WNºÜD¼÷0¢ÐÞ¼·Úˆ8¼‡mÖï*µ÷0mçmÞ[mNÞ dÞ[ó˜÷âÚ;xÏQAá½Ås^óÞROà„{Jéü qo±Gxxo+Þƒ“o¶D]ì/Þ[n%;†÷—× ïaç›ZÈ{¢”‰÷ÐR£HxoÉòŽyÀü~™÷g¶†÷–[Æ÷á½å:ÞEp@¼·”âü™x¯è„hTUCEPaÞË3ÞìÜF¼ãõÅ{ TêÏ„{Ëî-¶Ó îa5ŠÃ´qo©|èÏ„{K•¨úL¸‡—³{^xáÞ¥â^]–q¯Ê_~&Ü[*¿ü3ãJä’¹ˆ{ða>߸—Iqï óÀ= \ü‘qo;̽ži¸hU‚߸ç0® ÷¸:poÝu…{e—ÌicxÏ¡üƒ÷N?xÏV—ƒ÷´^Üsuã^ìùŒ{·ëÞÜËä]¸—j„æ½^†ßÜDÀ‡…X1¡€oÌs |0-[…€¾12ð¶U4ðõTúð%Œ À‡P¦õ|»}“|˜[o/à³¼oÞC€šL|Uz“h#äëÉ*7ò»˜qwÌÆ3óÁRU·Ṅo“æ±b¾¾Šo¦ªÕ“(ÚK6Ÿa¹dFFÂ^³•iŸH]lÑZDr„½JR#<öP’h¯<\ø#Ân‡n½a¯gR.Ø+wC¡`/¾'†½îl›À^sЗiïn & íÝJÌ ìÝ×سÁSXqˆ¼ a=§L…õRqf=-;˜õ²'£üÀ…qB½§›¯¨gŸ¢ Þ X³žˆ ÞmkÜ ^ Ù™õ‚´f½‹Âõì£Ö«©·ëÅU0¬Ç•5sâžN½î»hÒ»mâÒÃd‡›ô°šÎôÎÛwÀ¤70Þ¤—ܼÞWѨwçM3ëá­}¡îù9Pï¶õAXoÜiÃ^EýÊ{ à ìM-¢½Û.¡=|{y±Œ{+ÊèáÞm«…àÞ5á_¶y ñ)am"¾æ°'#_Òã|-Õ¹|X™d‘øF†¦‰]$¾Ö®¨€$>Èj\KˆÂ×½ …¯;}Îȇ¥d4I|œ(Š÷* û˜ä=ÔBædN¸÷|¿²é{·}5Ì{5ÚS#ïÍ MÉ]3|_Én<ßÈ'úž«˜DßCìý[ßKnKô½ VyI|HáYYâ[Û¥Yb$¾k—N ‰ñ؇=I|¸$Cãƒ>F™ÐзÙû ЇڻÒÙD}›ã„C}U¡ˆÛˆú6 ;aLÔ‡l â©°ÄXSÒ8É6øíûæ} ü}*æø¡| ƒß^_¡Ï~á—̇`Óõ~ûÞê]?º¾T>„¨vþ†Ü·w弄ûð¬7îZÜwXÓ#õnõaV@ ô!‚• †¾ÃÕ=}¾/Ÿ‰ù*Õˆ¢š˜¯Â^‰Yb¾Ãaôa>Lßf¾©1ߎúå$<1ž Á™¹hÇ'èƒ J>ôm¥F|&èÛÎ9AßVùÏ}ÛÉü0ßvKÙ óm®%æ{ÇÏ|^On àÛ¢Iøp,× øªæ´$?¢ÈIÃ>TâY_ßöðmLkÀ·íÆa߯Jå¾­ÌÃ>ðm’ðAýî$5ßæg>À‡$BNLM||퉉"¾ÍÖÚ!>Txä”Ïć±óE|›ã0B|¨ü½ðW">|ŽÌw$>üï|† ¶¾µ’D&ÞÃJ 'Q‘÷úm˜ðU w©y¾çp½ïi!½øPÚú3óÞuZ@#ïÕ’˜t9ò^ì’÷ÖJk©s﮳¾÷ŒH]ëá¾2ìWϾÞ<%2ðÕ\‰-¾¬mø09×&>׌ ïÕdž`$ÞËÔÖ¸wÚ3¸w¥N¸wXJ í)æ:°—8í{vÕŸaÏÛ Ø“4cÚK†th/å$íiíxÀ^f{ñ± ì­§§t†½u÷ä6°ÇB÷6CŠ‘/öŸƒù"? æû̼g7‘Á{Ñ3|šÄ{¨YÝ fu¯‡Ñ|¾E÷º”àÞæ'ʸgÅØ´#ÓžS‡{±®í5û÷b&Þ‹1Sx¯Ù ¼ç BÁ=XZª´Õà^´‰à^¦ÀÁ½8ö÷ÚJI ´—÷ì¹mÜÃJ÷ý½;ªp£$"ÜsM³A{.ÚKU™ÐžO|CÇ5ð¥:É>çøøââ»O¯1™ø&šñÝYF ñ½t½8yÚÛ|gC{{$Dã^äkâžRñC{qˆí]vk´—>B{ö´gë€Ð¤êõ%î]^4ìA°àس¯ÞOLßxèéÃÙe ¾[l3À«b•D&Þ~¢Dx)» ÿð°ÌJ*TgX‰´YÔŒoèC¡ìeõz¬Ö#ê-–’}ÝáËÑõNÇ"X×C:âNI}•&Á™®¨¯ šsŽaåaHZVöì×i¹qŠž÷!f!{YÚƒ ö’öV¿XCÚÃHý’ö0ʳAÜ&â•0øaj PSßfkÆ€Vò©pYÙø%ðCŠ×9”½½ŠP~&òÛk\þLä·£ŽÒ+ž#-9Ê^En&òÛ%Qöº“£¢ìÙŽ+äWƒ$Gä'7½‰ü0$.¯Î>þ¯ü½Ã¾z!?<‡‡t<){È ’üŽCßâ ßŽúÁGFÙzRöN)#&? ¾Ê ´²—')ÊÒ_!ÇOi{—dh{§Öh{^ˆ´×Ùµ½^ÖöšµÜh{÷îm¬íE*‹¶×œ:m/ÜbîƒGã+6BŒ 4÷áGJú#÷í×+{o¯P˜Ï}ûóý9^Ñœ{"”M}ð/Ú^ÊZx¸¦>‹’ãD}pgX^âÞþ¼ÊÌöᔸÈ`ìÃÞÔBìÛ=?öÁs‰²²±oxpïÂ>l³ÍØ·o›´|cæ¼'1ªÄ=Lµ>õ塾]¾iPÜDÔ·Û55Ô·»TB¨¶Rý̹ÃéE}û*q2Ô·W‘¶ÏD}[sÈe¤=ä’KÈõ ˜¨ïv^ž©Ï¡#˜³’Ï>3õ¹a´=ñùLз4)á‰å<åü8 ¯­šGún£ÙHÝ;øèCÒ·IîÞa-2Áœ ן‚9ï oÓå2ôÙ}@ßm¬ó%ê'Ì7¸Â|‰šR÷DtD¾13óYôoBŸ È„ùRÅÐWôb*A_Œê}\(Ûúî@–3÷¬ŠùFZ›8çü?#ß’Q#ß–pÐ|V…|I}KâÞé];qïNÎà>±OɃ÷º0¼ç<¸×FTg÷D\#qOIÜs‰Õ{ÉösâÞ¸sâ^Ô“$î騉{#¹Ï™{×;–³¤›õ%í 5#ß½¦EÈ7¢0I|·Šø¦N|Í÷5‘œ«"ÆÍ{S¡xï:XÉÛ»ðlà»m =b9£BùÞ9{¨¹Æ>È™pçà^3¨‰ö†H”8NWªqœr=îœBñ*Ÿ;‡¼‡°k¾Z}rN?ñÁqYY|"¾hÐF¾ËU,òÉÒ`PŸ?š†¾œ´™ïLZm"9ó51óW3ßéø#߈25òM-B¾ñ#ß¹‡@E|c“ÎNß¼7âÌ{)¢Þ;{Ì×Ä{çe™ÚÀ7b^ |)Éà«Á”-&¾ž_‰øÎ/«øÂÝçÒÞ®< Á³‹–fw·ßüÕØÈ›ü9S¸³›6ï -Ã3ÍMÃh´ Ï´V±c¯cuËèÊM£«Ñ2u…ÁóuÖl˜:bËÔþÕ.n@îý9×ÉÅí«©Ôï9³5µžW6øî?k–µ Ç·§uû…ŸÑèŠ Ð÷OË}nU—wöšúòÜáÊaæþÚÆ= £6÷4µ©§±‘zš·qOæÍ=Í6mêil¤žæmÒSLÚÒÓdÒæž²‘{š¶IO±hKO“E›{ÊFîiÚ&=Å -=Mmî)¹§i›ô{¶ô4Ù³¹§läžþ„…ìÚƒ8ÿÍÂí'n¿ðéþÛwŸá|©ÿöÃôë×û‡/èw=ýº}Û žÙÏÙ¾mv[û‘Û?ãÕö{^lý|¾mµáñ—ÿþù×grºµuú×ï\âž¶v³º›ÅÞnýÏ{»aÁf¦^ÿßy»=çy»=Íÿü+’wpa§Qá?Ößý¨ÿ¦·Û}®Eo÷ƒ‘Øœ¾ö0Å®™Ù}RÄ»³$þ´Ü˜þc†F=í>Ÿ©ÍŽ”üEÔùü[ó¥Æ~®2±¿|ó´À0+]µ8yc¸{æÿw·]Â}" çƒu­¦ŸTã¥ô´`lTÍ|Ž¡¬–P““³ûZË …N8­}Zª¢AÕ–½Ù²Ý.ñªsºöJqǬëÓ÷㇭Ć·>-5ñ¨ìþZzº´0p®{_W©ò•[´ñæZö´OCgtŸ¢ž«v9¸±|÷…Å>‚'1ó™û–‘ð•_§¥Û'?›ï•4·zßæšÊËÝ7s:Jc=ÔRAÁ(6HD¹o‘fsªÆ7ü–µÒk2ußE+UíN;BïV[P¹of%ØÓ¢¶MF>Ï£°ÚÄ€\pWÒòÃÆ_eRÞï®Ò³Gñª¨OkÇ À“6ÐÔ±žÝÒÀ{C¶9ÎaypCŠêÕ§CÜÍÞã»EJëJwì:L 0ân¯Ë”Ž{¦ì7–`S‹û¥ãèåíÔ Àw%GÞ•(¬‹† ŠÈ[X[ñft,òÁÐîØ7–`jy:_êF°rk\Jª8˜»,—ö ÕÖ Úé~Ö»ùä.Ÿ÷£l‹­o\‘«‚ÂïoܼÌhnhÞ•ÓÌÀ·;B˜ÜY™ÃTünëŸÊZæž{çH ·µá¿7±r‚Õ°,Ö®2åçÑ5DGìr•¨¥ø†à:.¡-ߨ „aÍqc yÚ×]1ë|r[%æï\›[ÔÒñW e©ú…»Â_çÎ÷ÕV†ÇãRw¶€â>åiÁsèí \צ¡Húu`^C_ISx;[zÊ-Ôßø4_LA¯ç¹•œJOð VÝ(+]ýÈ´dÖ|­@6”Ĩ’ {jŒ³•5Xç&Xâ«tùW´ŠAÚ˜€pò ÚÅ€ÄS–cmíµr÷NgüO«2Cå°!¿Â§¥Ñ»`ëœ}|ªÌÕÁãéüÕyó]YðW×)¯ºSO( ]Éã‚÷wo5šVÊÉʆ»ÞÕKEÉZºª%ñ:GT¹ªõPðR+]®68é‘×PåªîœWÑ[U¹º¹MEx6èrLdQ«~]*R¦ZŽ «ªëp°Æ·Õª•½v\ßTèÍl¨¨izÖ%G©«zQ/i­J]uN©¿­j]i›S-½ÞTǸ·ªuEoú"ø§Ê=ñh«Ð•lÿµt¾§(QÇ_…®®ÑÇqð%Ň£Εïè½êUB‘«Š~¾ƒ5¬´*ruÏÏ Š\ÕKÚ±ÕªÊU½È7ƒ×ª\Ý;3N¹PTU®¯n5 ÈJÁ½†‘*rÕõ44¶4¾£ý(©U‘+™àð9¬*W*„UcvC«þ¦=­Ê\É'‡ß”¹jzyRUæŠÏ¦¢èyqv641:Ü1‹Õg¿Š{~žQ¾£¨quò&•"ù4”•äÎÊ[Õé]ú6”Á7¸Ø€ù!¯>¿×…ÀŸ*ÆGR¥­tq¿þ™e­ño ¹UÕj±ßjCY«jP<Á3%\øÕÙyPº?åKÄT´êü ñBA«7„‡€‚VŸî9ݪÆu³ŠÜ8KŽð[yü67ŠÜ‹Cà[cÍ¢Û=`ÒËG›Ï[ÙL^Ÿ­ÂÝøÝÙ¥ Yù9AZ¢áÙ:V²n•"®G¢”±RR?¯˜mÖ+¦êE ’øøtŽÙÖ@ UGTdì`æ|&øíêŠf¶òÙ¹ÖÊ…3ÎÖ̼núÎj…e©y]5`žË-´.ÊÀ͹s…é×ÌÚÁÑ#d"8„GÔ4Η ¶&Ç à—‡ÀaÅÙ©êá5ܹI@ÁÅA‡§~’àî‰àPBƒ[àäá÷Ìü† MyÅo·s?ŒowAÑŒøS8­ðí¶M¬é­$‚u¦·;•ŸLo·ÓË owTCÓÛíxÓVí‰ôû9³é xó¢7°.C$Mo(©¤7@ÈVôÖ×M2½5¬ ñžˆÞ kèÒˆÞZL_Œoh©qßøÖªߌoÍfç¦7“vLohi3¼¤ ÏpÀuÕšà€ëb+¯i‚Ã?è,[U—•e•®ª óZ’઄+û$À5Ç8à°Ei¥¸QÄÖ‡U= "¸„Ëàš]× pU-÷ž.¥oÍo-Cæ·ZzàŽÄoØÆÔG~CÕ] |æ·VŒÂ~ÈoˆÞ9Dg¸Vú·!Áa››ŒWWUu„k¸Z,•À³¿¼0ó~s ªÈo؆±»æ·ŠetKñ:>g8œåª~p¸µ·öE€smaã[n­é ðy7½5‡*ÞZ o)ƒlxCW o£¦€á­í.Þ&xkŽþ7¼ ͆·Q=Ùð6L% o.(mt«Aye/D·¿)³[î«Ñ Ýr‚-rÃæZÉ O—ªLn-ÙÏ&7t£Mn©8nn«²ÔB·%„ùí3·aÇ|ŸÅm-KŒæ6ìwQä6X©òY6¸¡…†¸­•Å[ÈmcUÏ܆m¼+r[«ŸÌCnÃ6\R4·µ”ø2·aÄÏ¡¹­ÅKÌÜ–ÊöÆ6tÃ[ jÞ.a\A[Õ åó!hk /²a=tB6„ßñ#²µr á±Ù†‰®©­´‘¤HmUZž;µµÃËA¦¶ßmjïô2ŠÚ*hœ×NÔÖ2I0µ5;"Úp]ZŸ© ÈeISÛðÉ5µåʈÙjfª^ŠÙšóýlèC'@jÃü:›ÚF­yS[ã|èï¶c9s[ÉùüÀÜjO|8nå&Ì7Ià†ãÕEà6˜ nóÜ$nnk¶Ý0·M{·åJ‰Úæ-ˆmM±á¶á¶é!¶Õк©chü°b[<”MmM>Rµ _bcÛôx ÛZfšâ¶ñŒÛêXøLÛб”Ø6–å…m#¬BØV7‹Ø†.úDm1·U&Ã*N[¾1Â_>Á [ðŽß÷ë-$·M§ð`[K•LaÛ0Ƕ•6wHlKÒ‡¨­­9|’ÚðZiô!µ ?.Q[ìÁm•DÁ h±2‚¶éÕ%´ôAÛHôU* Ï›ÐÖRÈSÐV ¢£‚¶ñ9 ³!NFo™mdˆˆÙFÜO1Ût3Él•ÊrOÌ6(™m$”ˆÙ0aqC1Ûôi#³Í?)fÃn5F‘Ù0’\ŠTøeǵ`œRŽ6aÛ4¹·é´° !Ü’„m˜+s*flkeW5ën˜êrâNjÃÔžËü‚¶ú *ÉnÛ P²[Ì+-»áÞ/ÙmÛ"…YvÛ"bIvÓ¿Kr[« –Ü6[5Dr‡bÉ”0)nøª¿·Ì"¸eøŽâ–HnHeƒ·˜“GqóR¼‘-ùNA¶Œ«F¶|ƒl•„\Ã_ò›p Ò’º®%y+¸–€ÝðZü÷Ãk(Û"X°MýئmDl@‰õElG7K ر`Ëë`KåU›_ùÛéª6œ©èKÄ–À¼ ›¿ˆA¶”² #¦Ð|Ìlö§³=™ÙÆÑÚ’ehsþ\˜­² ø#1[Ê<„ÙÎM‘-i…A¶qéŒlÓ¾Él®Õd’¦Íé‹A6'†ØrÒ!6”æGÓÄvÞþ‘€ ¦6 l˜àÀf`;wÏ” l–hClyÆ‚l>Þ[ŠËÙ¦ ÙìØdKT¦‘íÜÍc"6œ5AÄæÌœR@ø•7±%}4ă⛠üÙR)$È6.¯‘ÍQøA6̪tüb¶ø^…Ùò##Û¸‘F¶„«†Ù.hcA›-ZÂl1 5³åÙ’®d‹¹lít(˜ §(:³9"7Ȇ R…læáÙÆÅ4²¡…‡cd›~%dË]2±eµ2Ȗɉ‘-¹¶a6Wõ²¥ì¸¡m ×rR¦5³·aM.fµ”± «yÙA¨–•A‘Zy óIjYîý‰]šé 3Ýç&8CñN¸g·ÞØ™Î8…ζ¥>(a3VšØÌu ÌfK{‡DbŠÍø*¡™ã™9“)‘·ãºÙh2[[8Kd¶ÚQ.t¶\ºì¡³uVÓð‹‹ª—ÀlµqHÈ Óõ…fÈÿ<_h¶#:’h¶^’fLfË‘`M¡Y¾&A3Ü ad³ÈJF3Œ'u%Ef8c¡$‘_R×8°Ä`ÖÒ)8Ë 1›­g8kigº›!hUüf1-‡k--q­ÓNßF£ÙâYÄÓ|4Óìµ6«""l›­k9Ár¨Íb5¬`ò¬ˆIÁ߉Í–a š¹òDÈ N¥íEfð®^f2ëCÌ4š¥Veâ!‡JêxÈÅóÄC.!<¢Ù¨’pH Ä÷,§ÁYH*©Ã!—od³>DD.ƒ‹ÍªV·P<ää+4K¾«Ñ !¹ÖÎÈfèT_eGCºŽ”Ñ,»1š ?Y£ÙÈ£M0dŠˆÍ*j×°VlV—™_s±Y÷'Él†]i‘Wl6bˆÍfs á ¿ô´­l:n¶¢3BIÃ"a 5¢³¹…t6ŒþMghV€†ð¬GºN0¤¿¦³žWÔx†Ž5çžáGâKÒYO|§è ½Db+:î¡H8ˆÍúHê›ÅËlÖó~ŠÍðÅ&’Ͱ×Ã$¶Ð(ØVÂf³žï®Ù Ýh¨›¡Q¸à¬gÒp†·P³4ÁÙ8±Yo½Ø¬Gâ7›uQÌf}ɬYl6]KÁYwí4³Šâ‰ðÈf=ë£b³ž±Ðl†MôÄ“ÍFéX³Y¯’³¢V×áš5Öá1™ù/r~¯;*.ó¿“ÉpP÷ú8“¬—%D&ëš\˜Èê W²ù¨Id83ëw$²T‘Á-C!"áX¤*"뎜0õŒû2lÂ÷M<6x¬okZÈcøgDZºU<8Y¯’³„Ö˼“ÇK ›º!ë"ë1ŽM ¤1ìÇìE«‹}ÎN@ØDáh!†4Ö333¡”n¢p “y¬'ÖÅ<†‹g~$Mû&Žõ%AëžWŠÆFñ©¢±>â5HcueïIBëYwÕ“qLÚt{ˆcuåù‹Â±áæ$ëŽÊᨵ@p×“Ö D²žH”B²éy&’Õ“¸LH†cÔC&Ë;B".lzÚId˜Kì3‘MwŒD6¾0 ²ž\Y·Ô" %½dµöXD6]E"Ùtkˆd=šˆ [èé$’c"‘ÕAo‘õH3Ed½‘ÈGEduÝ$°’Í?(&›®”‚LJ•P6}ä•È;ÞpbÙôPîïºhñøØ›ÑÐ|½2×\d;ˆæd!´eõ´Û„–©¢-¥Í‚h»}6Ìh»¼ÙÃhgÒ£iñŠ¥]ƒüHi-qW¡´à£(­Fþ}ÖÏà¢ÙgH+ϲ­'¢ÄœÖS`P5_ j¨h eH Ömó`NÃsàMÈi£Þ»A ÒÍjý ‘ÓºëD:gíÒЗ”5û58c-õÉ“±†`ÚkŽy¬½ôYDë6çMÂZ_B\ÊXkIøsÊZ~ä\ö»ndå\vüºsÙ²þ?u.ûî9é×µNp¼hï'®&LÍ_[©§áI¦žfO2÷46rOóVêix’©§Ù“Ì=ÜÓ¼•{Š'™{š<ÉÒS6JOÓVî)ždîiò$KOÙ(=M[¹§x’¹§É“,=e£ô4måžâIæž&O²ô”ÒÓŸp.ƒü3×ù±qÙõ{Æeß=}?6.û­Í¾—ý¤»¯/Û×;—ýl·×OŒ¢¾—ýÂGûo_¿¿?úDÿíGïç—¯öo¼ŸßõôëÆe`Õ+&ß²Ú'ì?Å:l˜ˆÍ¦f?ñ»þh[¡gJóCײç~ÿçñŸÿ±Ÿ¹–=ÿ׿bµá™Nÿ5ýóo»–MÏÚp-›¬Ìþ¬kY¿NL…°0õp|é“Rû4ôçOÍïûãâÖþkÃDèvÙ3Y¥ÄÏÕ§ó û²ZÚo ¨ôšp?Wºì.o' ÷:ŸÛvÏßå¿ç¬ñ^©öUm‘‡t#¼¿V¢)}ô&ÆËâþ‰;%q?ó° ¿]Ç¡2"£|6nÑ`zÑ¢= íÛœ#ÚkïS¢fDz÷:e"wÄ71r‹Ë”OC›"»zeÐ2V°óßw†1Ö‚dGÝ1âk{¥W•áp-Âö aç²xã\(\Þ.GÜt2Ód™AfÖ¬`D¹Žóµ|½ÖÚo­d=Óº¥œÕxìpNµ;VÓûTÞ±—ÈQ[0ºc¼U±XTÕµ*pÝl”ÂbTÊÁ]"Dqª—Û±zÍŠ+¿”ù.ý6¿Á¥ægÛ^ÿŽBx¡ç°×')kÇ7† ð°°ô´–&ãˉʹ®5G°ÒŠv×€Áúh-°ç¦£JÉEÇ&] -p‰é)­ƒÅœ’Œ’sð@d/ÓƒÉJ2Jæ ZZùªÙÏ+ %Íý¢!­é÷j€È^‚¥(´4œÂéÀ4LÅQÔ®”ˆ…ݬ@ݪ Ãg¨»~ã7’ËëhAÅB¬wÍZzÀš?±[„ßu©žÑ'к^:´´o´UK ì–ja|÷~†¥²2Óå\¡QÕJ>½¹Ñ‚ê5‘iÜû†‡KCÏ{ƒDÓ ˆ…šÙ¬²ÙB KÄu÷±s! ¾#ÿw{g“­½#éy¯"Wð‰ÿ–Ñ'—QäþG- "ðÚ®tfW÷©AMl_X/EI”ȇX^—u#á#·^ä‹1 ölÓ€¿Ü `>YìÜL˜dTíÓ¿ÙòÂ~@céEÛÑpþz¶ÏÅÔpôÁ3Ë[sÿÆ(»¶Ù5`±¤ØïÀ ~l (ŸYPòÏrV²á=nÅÓQþa0— m+pk€ÅéÍ‚½9µÛ¶€'ÆÙ¿8­¨RMàf¿¾•ïèá¹7ö¤FÙ6lÆÊAh)̰Cð²>¼Y°E`¯î³°ð¢¬¨’'Iâyú4<Èfa’0×V¾¿½ž’§ ’eb›à›4Õ¨WTòl‚‹[Ø(P}˨4”0k sVRÉz=ên¿±W Ê–fAÚÕ'²{4”°¶ŠJ‡pÔô— Ýø‘³zJž‰ÿ»c[}-ˆ/VÁéA"!n¢p_ÞËÆ¾9‚{"«F‹M èÿd;܇Sa«yýbÒ/¾^NéÊoŠÕSêÈjÄÑ0”SŠ9¨l^žQèÚ:·ÕSª5}­lpw$¼h`7 y¾¤ï¦¾lÙ¤ê¿!¥W§e¢JjYJ§î)±$È|«=ûoè°}9;wÓß¾¯~³¬ŒeŸò¹[36 ’"u$€2 ¶æl×CÄ2=hfӂ͹۷ºÜ`b5ÎÍçÂjJ·íéc„Xr¡›'g3ƒÕ;Wœ|6ÔåÇÉrÌò)ð½>Àn¨8ò<,ü•絺3]w³ßà:δ°MwkSÚ2Ïù¾º}ñìÔÝÏ…¤yfÙHLvé÷˜wÊþEKg¥SµÂ¼SR”̲üÞGŸ•Ñ•f·ÿñkð °0÷Ô•TšÈÍÅo€/LP³Œ]óÌóŒWo³;ƒX;ñµô´­8†÷t{ÉÙ—™Ç,­Ùã×`ƒ×°¡Yßùµ´¹ÿA-ÖÎvM´¶cM V;€ýãGÁtü‰¸œ´TG÷}ô~8š…ÉØìþ×ÚC7Ô;bñIùœ·1¶þ¦u\ÓÎÝ>[yÅ"Vüº‘Õ ôØsññ^þªw\ÃæWÕ¿þŽZ¦Oªö+/7¿3£‚›¹Y]¼n#7û[ì t›ñ‘$¹Yo.XAnöJE_œÜæVJ‘›£9¸Ù>Mt×ÁÍûM®°nåÜÆmî„(H»¸õóŠÚòç<*´eÎ{A›C hK/EA›»Cr…hs×FŽ@›ýJÌh3•7Ì6#_6˜mETŒ˜-<&…læâ¦ÞÙVD´ÙVò³Ù1Ú³¿rf[\#f³ð«Y‘ÍN>IÅ@6ûo¯›í¤ñ)ØìC©q `³Îú×ì'\÷ƒÖJ 5ûuKÒÚRT`Í*VV[j#VózSjÅqmÝW &Ã5 ¼Ò» \[wît×ÌÒÅf7ïl«°fÚ¹>6€5kw kž’gµˆ–ª­ˆßªÙ]˜|_Àj+"ƒÀj+zÄju°×2 L¸¶Üч­8®eÑáÚѲãÚR˜ŒhmÅ›h-2XÖVÔ9¬Ù¹ù‚Öì}çk+ª Ö–JˆÕ2MXÍÎ¬× ¬fÙoÈÊ“û\@5kfÑÀØÏ7¶°ŒÔ–;"òˆ±ŸBµE¦•&AiÞ1ò–CZ=AÊ÷›v€4³,n·ÒÌrs´Ò"†SŒæ}ç]2FËÄEb´z«Áh)tF[ -¢eô«ÍÑh¢­ÜdZùùp´ƒÐê}¡y’$µ|ÇæËêïÑðYf3Ÿùy8&Ágö+}“Ág+BZÄgG_œÏ<Œ–ýŸÕcÀgµðÙñ+ç3ÿ°?ûE2ŸyÊSµÂØÏ/#ø,ƒzÅgæÀ¬MPðYªâ3o‡¯ø¬ÞðÙRðÌD#V9žeدð¬<âYy¸Ä3kö’ÅñLqÙ‚3;¢‘»œÍJoÉfÖ,Ÿ.Ù¬|Èfþ‰$2] ¡Ù\—Í–w„fùº‘Ì" \dVF8ÉlEt’È̇qd–oÁ¿›Ltfù¬{ų¨4 >[Êç)>[Ê·%>‹]fñ™V¡Â³ðlžíFo^!ÚgÀƒ¢…ù-*„„ÆÖBð¢me\¢í‡NˆV @4Of_- ‰Ñ¶Ò Òìˆ"²ùBsWF‹•²m+ã-¯œŒfeeŸd´ÍŠB´­Œ RÙ^qd¶gBf{ÕGªlîñZ myáQô*[$»Êæ o‰l‘ÉR*Ûû!Ae³M‰M(kLD“"›(ÀÙLk$–Ad³DÙ–13ç´¥pbÚÒº›”¶|GË må=¡™Aò›Ú*|D‹ó‹ÐVŒ&!Úªü匶öˆïmÅKu퉉^êÚÚÕµ'wqíŽÏ½Äµ®¥ µ5%ÁKimj¾¢²ÉOCZóR懴öL‚´Ï%¤µ·€¤µ…CZSfJk=‡ÒZ$* i-²>…´Ö4¨¬õØe-²æ„²f;qSÈæÊZD) ÐÌùQµ+k6­ Èܽ6ŠÓRX=pDÛ#3ÔÕºª Ѭ T:¢mÉá"´=rB³énƒÐê¹ÐìG\Í mÕƒŸÙYDQÎgVž@— >+MÏvlûÏì•Ú-§³¨f%8Û3W^€3³L6ëpf·IoàÌÞÌ^ô4[-ˆcgfÑJxæÍr5 @ó_q•BÛ±‘%D3‹Øˆfž©:ÍZŒÒìWZÈÒì\Oi&$ë;`¶½ÊÏä¶UçZŒ¶Ã]D¶9Ç‚*+(Í\pÅdi»%ùÌ#*g%3(m{zZœÒlù¥ ¥Ù1zrFiÖétiµ+€´í•xhqH³F´þ¤Ù¯ô´iǯÒ¼e]•K÷@iv÷8ŒŒÒvìï‰Òì'Ú(¥YŒ`à•SZí(mËCG”¶£8½(Í~$õìòþ·Ø¤mظÁÍ.Qà VÏcAËæU@ÐÍšÐ6ÍáƒÒ¬ }:€i™(NÛQºB V›qN³C^¾øà´Ò7`šÕsÓ‚ÓÌ¢ ã4sU#8ÍÎÃ/0m3•­[ÓêhVÙíp€´†u*`Úʯ4„´tÇ¢fëÎM†i«¨‹”Ò"5ƒ8m•ùŒRÚ¡¿AI+—H%­¬¨¤Ùu ¤•VÓVY»¸õwCH+WL%-œ•CI+wŽJÚZá´!-g[ ikÄ “BZN®Òr-@!mÍÍ £¹ ÌCLH+¿€–«êh+½'!¤•u •´}é,TÒ² ik z(¤•# ¤åDBÚZÉqÒÊLG+K7êhK~BGËUu´â¤K!­,b)¤ÙJRR„´¼B i;7w¨¤Å_(iû!‡JZlRI³ÞÉ Ò…´Ýô ¤í+†6…4ÛZäR“BÚw"(…4m/†Ž¶o 0êhŸA÷:šKß2!­ìqQH[[¯u´H‰:Z¤; -»B­ôŸ:Zýt´âÐL!m¿Ù_i;\×(¤íð­s­¸PGË_PFKQŸJšE KÏ‚”;¿¡¥•žPL³Š¥\¦SLÛ±ÓG-͆ù`©¥•sCKÛá*èRZäå)­Ü&JiVØTH )íû'?a”ÒÊÞ%¥4sà!PÒè$H­*ÿBb2šI[w ŠÍD¾Žh&±R|¢IŒ$ YÚ!œZ¤#ŸYõ<†qÏRú%ŸyMÇ‹8v3ñ¸oÙϲ¤ñÌÞ¼‡ââÓ…v„§åRœñic†k"âÓË*<-}æžÏWái¡ï0:-u.G3{IENŽf#ųŽÌªD³Ìjçl– qÉf[ßD3KÅ7«n¶Cô%šUƒ£Y¦-%šY5:mGÉP’ÙnÚt2ÛÝÂ?}70r¥“ÌÌ@ú™m%7'˜Ùßr.t0Û‘íœ`¶•Eái!ê(<-ªx)<- )<íÝ¢sOSe=E§}‹¬]ȬF[18-ãf›6î‚jÈüvÇ:ޱiãɈ6Ħ¦Õų"ÍP<‹XÍÏÆ«Å‡‹g=]Ä(ž•g†zVÄ Êg“ZÁÌ3[± Ÿ­“õ³ù¤ZýlÎàêg^ŽþÐÏä[#Ótò›©êâÔŒM{SùblÚ•Hí»4ÍùTÐrë–ZÑ224Mg†~¶F¬D©ŸåâÎå³oÉ¡'KýlØYwý,Š*‡€VvN) Åî@h*úYmZY¢S@+;ÏÐBÂ-wJhûòÿ¦~f[¸¯@-öþVIË,q¡ ­[†+‹"ÓÒ협iW:Ó*2Ͳ)ÕÈ4»7KñlˆLû¾†¿$ÇAG‹"O™æy«·£ ®ä¶‰kØ¿f•Òj°*#Ó,À•û™æ÷O#ã›yº‘iÖ¬ä*D¦Y#]!¦í­¡ÏÀ4;„Q] L»ÜaD¦™…­(m”B8—æ½-—f÷á’cÖõ ".íJÇCÆ¥ùê¿b\šõe‰ÝîíšÚ{YJõ(’ŽqiÖŽPŒ¤ÌK¬ªi™ 1âÒ"aãÒìo³HÝŒ%RXš |ši¤î¦ð;†¥Yüð#錉¤šÃÒlÈr`XÚåi×aAXšuçUÚÇ0 /ÂÒ<Á) ’~¦•vݱbØÊ¤:±Ç¨4ëÌ`³ˆJ»Ü™D¥EÞ»ˆJ‹<•VÆ£ÒüVŽ<'àMʹåmëZø 2Ÿb„¤]²©´Ke"$Íb­«šæ£¨Q•ë óÎX·‘aÞUM«Í0 ÍÖå nwä÷Œ€´Œ0W@šç6Ã0 Í^Éø3D¤ÙÍ$TRM³„Ò ?C@šç]e3PÓ´yU²Ý·9,©ež†€L?FKM$öç¿Ë£tÌ¿™€¬5“¾²}ü]R}¹¡d×áß%[X³Ÿ¯£Zj30Õ†d)M=·uëõÒRš¢©4–ÿêdß²Ù^è+Ùúÿ™€ìFÊmñ8÷™‚ìǨóñ4®cþ=ÚªéÅÐÖ‘„Œm•£ØÖ™ª mÕchëHCƶÊQlëLVƶJŠ1¶U‘©­õÏ£•Ò‚ÓźÙmQXó]J6`eλ„Óåù³ØºÈ"¾¹Â±]Þ×E|mÐ{µÈt@ù ÝóWÎûü^.ؘé˜pÛFm󂇭0‚9äÏÛ¶nï+a÷¿ˆëŸÅ*ì@Þò-w[‰-„‚*gÃE>#ÃnÛ€]¨÷G<äo¹Eßæ?³†\6~aom7êµÑïÎØ³=`îBݶ«e±6;4ˆm•=žp{½}‡Ê·Ú%vØÉö½uú¥7æÏþÍuyôÃ-‹ïñ-m¸~Ï”²”Lù3øŸXp3¨YöéQB&>Ëë•I£î;ð¯ Ö~ø^D¹O³ø6|¿ÈŠÍÒï Dì«C–oÄ¿S÷¥]ÛwâÓ[ÿ³øV¼e&à¯>ðJª*l‹°ç(MúYT୻ςŠÀÜél–ª¤g­êÏï‹HðY:RÆ)þð3 Æ« –¬q*»öYà}a{ µ7.‚þ>‹ëI#D¿¹ Û­Á£G´jû®ÙèØ»v» 1¿¯¤§å“«{Þ—‡hl>ýf÷ñ—‚Í׎ç®×fçëÛ¡¼“Ϻuo9:žåZpúA7ÛÅ/ÏI‚cÞËÅàLÛÖ^¸`(‰…\ 6Çtöö…Fmæq5ØòL`›¨ÙÀ/—ü¾®[þv¾G/<0LâñWƒ¿cô _x`„“¢Y\ ®í,—ƒ½ø »·áAuÅCê×u>~¹"lJ¼+‘4¼;”SZoktܨkV!©û‰ô’tø`„§n³ I¯Ÿ™»¬­Ãc=ú®6+‘ôøýå†sc‰$ûöð-6k~rJÜE’B"ü,ÛUa{r¼7ª’$‡õo…ݽwt(jV# è­F8UfE’ÞêÐÕ¬J.á¡á•ïŒÕHš~ÙœšÕHjÞ 7xÛ€FdnhV# N`À~åþŽÏ,©/Œ¼@+´ýº‡7²ÍpRûÊì!µlíуõé}Ó]°"Iø6ðK0=ýn½u³¿ôÁÓ7hB»Néã³ìzÉâu¬,Ú„|‚E›Ð¯3!b›P°S˜j ¾é Õ4ìðk‹¾ÿZ<úß¼8á.è×é`ØXÄ6½®Ú‚ˆm+¼‹~y¹‹:¶bÚ ›ê][²C kkË… +š¶‘hõ[Pé“´‘i5å‚ϲü!c׿m¤ZÍt*mÓ#D§¶‘ouG$aÛðÄHªí.*ÝÙMOŒˆ~hñ )ˆ5F²ç¬þ" 4¤¶éŽËÛç² Psj™üsò@hy.…¦¿Ðs!*4£ž q¡á¥ó\ˆ ]‘¯ô¹"û*ïÃs144næs16TÑÏ…àÐp|¬(ÒáÉó\ ¥°üXI$ø!é'ˆµO¯‘Šƒ×s3H4»‚’HÅßä¹$cê¹#*9ì¹_øQÅC{î~T,äþ\ä^ÄõÜã­þ2Ï=o:Ãð½{î¹'¶çv‘{EÈs?vD¯›cCçi×âè¦8ýX5¤;?>ƒKÜ+2?>V i¥õ´gщsÞƒbHÅEõiý¡+ÒP+ã:#pŸçcûžð¾Ö÷[ßÿJN²D:_]¢‹Ú¢tMA D:#:)‘é<‡ ÓY‰,¨k±úÔ='ªk:'ª«Ç€êžˆqÖ±4T@6nƒéò€==m6D#ÝT) «‡4ì3GxÎHøŠ9ÑÙ1äZÝñ#':û‘ü¿@tnᦲ|+ƒÀE.ó èÌ"Ö3½Õ÷yh@¦¸øÀç¦ Ä窮ôOx‘狹Ò?1¯çÌ Y8gáp®žÇqÎ šúsf†玆÷bÿõ+àœ[0!æffk&Í™E«£¹ão§¹ã7ÈKõ¼I€ŽsÇ©çŽ_9Ïù¯8•€çŽcœçj‡‘—*“T窱Ù@Î+o‚Þñ«Õί}Ž’^m¤WéÇÜû'$=³û‰zµ7`½ã˜W“j´ÜÇk0Ø;þž÷¯Ÿ–u¾¤½Ã²Ÿ×Ü«í÷ꯀ{õ‚÷ê5ðí>ëüÞøü7‚¹þœc]޵7CÓjœiêÞTÿr¦³`>”€(Ì!ãÁ|¹a æ gm!_T°äË,'B¾Y :^$ !oGà ¾ÜñÍEMß÷î ùæNQ‘qÔ[hꛩýû¾Ÿr/ûrûSÜ·.åæ#÷Eùôà>³Ìƒû¬/’à·nîïˆûJÉ}«èt?c‚»€Ÿ]5•I‚_=à—yeD~eŸèåD~^X˜ _žJì7¶˜_ìçÞ(…ý”#;Ø/÷ê‰~ òË@k¡ß¼~ä7ï_‡ŽgG$ "axD(ü2®AäQê¿rj?sô÷ ixiàgÚÎ>À/»Kîû~ßMaߨ)ÈûŠzEìË„L⾉Å}Eö• ç¾ì ±¯Ü(b_>R_5lÞ\ìœúJ×}åvò^öž¸7ö¯ÜÒ^¹Ó¤½¢Q:íÍ«(v‘¡‰ÿû¯;IÚ+C´‡4'nìåE“õÊ­%ëy'ªf`=k…CÙY/s‚‰õ¬r¼ ¬ë½Ó¾a¯\i¯ž´—2+i¯ÜÒ^ùJö2˜hϺ# p/vÚËaIØ«¿ì•‹&핾öÊ# í;ÄÒ^9`/UT²^9¨7”¿U¤—#ÈA¯t– Wž˜­Ë!†ÈV~b+?!±A"[Þ"[>h![ý‘-Ïb+÷…ÈVî‹#[þ„ÈYElµ [yˆd¶¼"2[é™­ôŸÐV´•΀Ùr,‹ÙòÕ´( j+ޢĶlVØ–@l³ ˜¶•Þ‘ÛJ3ä¶.á\ÜvX6¯ ¸åç à–YnžãúéÆ+F‚ÛxbW™à–)Dn–õšKF¢Ûx“’䈛àÈõ,ä!ù®s}•Øvº^ÖFƒÚ‚“Úx– 6]¡¨-NDhË®ˆÙ’Ðþ ÙÖ¡Ï•íˆD¶Ã鲨äíI^Ën®é¬Äµ[i˜À{)àµD¼àµ`ž?ãµDc1[à@2[´Bh‹{Mf+÷%™-~̦î Ú’ǹQ’̦®²æ²é‚ˆl±×˜Ä&„#°EïÅkÙ3[vÅÍ–†—Y|?—{ŠŸËº"ŠŸ‹H…ÏE’U…Ï…g°Âç +„gïdÅÏ­ž'BüÜýä1yë"j ñsž¦¢"œYÈø¹¯Ó§ê¶îžŽ‘ˆŸ»Cbø\=ñsw„=*€îŽèÆÏeQ/ÄϵXš0~îŽrŠŸ»3èŠñs-—„  Ëêa  k±¦`üœ%‘Ñ!ˆŸk¹bü\^#Ã粘ÂçZ*fmÕþ3x.J…)x®…&ÂØ9U1Sè\9‘s-Ê)r®‚À¹;* œk1ñ1n®¥†¸¹;Öž6—m2j.òt(j®ÅäÊ ¹–«u͵œæ4×r{—As¥]Ä̵¢À¹ÛKñ s­ÄÐ!d®icsvqáqénÿQbPs­ˆi™k9‰3d® $ÆÌµ‚›5£­sÆÌµžÇŒ™k¹^`Ð\–ÖSÔ\û5—%û6×R1DÔ\+º¢æZª,Œš³´”B9DÍ5%|°¹òH6—q¸ ›«Ç¼ç0n®¥ªÂ¸¹U7×"Õ»âæÊS`Ü\>I†Í•;Á°¹ö¦Î…°¹r+7×"±»âæ2Üqs-²¶+n®EêwÅ͵Œ¢dàœµòTˆ3KxB"p®<εHƒ§À¹r+8W[Fà\‹Ló œ+÷Â#ç,)€è ‘s¥7ŒœkO|Æ9×ÞtŽD䜅YóQ1t.¯;מŒ·Cì\¹_Œk=ªW.€ásm„/ãçZOI 1tÍ‚ ºróE×¢¾”¢èZ9”Qtå60Š®½éA‰(ºÖ¹¡0ºr™ £³J¢èJ÷F—›Qtey]é ÃèZ3Š®el-£è>KÄÃ!Š®Üc誅i$"Á¬¢è¾fn¹Zn¾üÔ+Š®tfxoñßóèÔμèÚ ÌC]¹ûý>ßo¾»>ø÷ð¬ö£=ÑÊôLØ–äàñY<¯½iñW Zí= e{^û÷{¿³üû´{&l«ÀÞØøiè̓–_ßxûz<™wÿ}Ûƒk˜ÑŽo½ÝÃ0~Ó²¬Ç3Zñ·{ÄþôgðdØÃ¥7 •GWb·Ï2u |¹ßÙý)xµ7X–'Ã¶ç ªþ.ïÒ%lY&nqŒ`†7AËÝwÞüŽ­n:™o¶éoφ=‚öÞþ¼¸VÇ´wÄöݾñpLt«ÖbõfßîÛn߉púxÑËü‹ï¹ùá·ÈÞ€qZÞäo˜r4vK ƒÞAy½oKûroX|4ú?îþw–>xíðé¥åñ´öÝRìwZ¼º„]< øïÀ5¼êê-ùUñ+b—ü‹*8Ÿù â×ßJ.u\%Ÿª.ÝV'ÚžÕÞ®„óê.}— %èEá%ÿ2þ¿Vyi¡a”ºxQzéFi|Á<ì#…Þ ø’=¾–V}iðã1ÝX¿xžî)ímp¾ü‰<í5§E/!jo÷Í™%˜>ÃÒkj­qÛ,ÆB¦ÏÒ5¥¹ v’_bº}Ȳð :ËO¼(Æä(즼VÉ¿i|þ(Çô=ÛÆ¬ð/ 2ݶ½=iéþ*÷ozáÔŽ’LŸE)ö_KgóiÎŒ(Êd{ò±‹‰¦­˜ qú³,€Òý½ÊL=ÝuvÔfò>óÛþüÞ;~‹Pšéîß\ÁoÏvúköÖ«êLwGˆ©[\‚ö‰äÁÓD&¿(~¶kÐnáèC‰&ŸP%àE&¿9¼p¯D„‹â7…šnS'xáßÒ°L$uš¾K`~¹ýýbq‚í¨ÓôrñAõ«a:µúO–‡Ó© w2>ˈ_ùîÛmeQpMýê˜RcÖ­RÓ×îû‹¸ý÷¾; 5yg6»·0£v v…šü¢1tjò‹4ø»ü}Nø­ì¨ÓdŸ.~îûí"´ ˆŽ:M~/ñýT¼&+Ô¤eE¿]ƒöùò®A+‘Í:ý˜N­·ìž¿Òíô÷#I¬Uš>Ëɧ߮A»“SG™¦¯aô¥¹}÷øjw”i²!ÊU[·2M~†sG™&|\7u”iòþc€÷ÖùÛ¦6-˜Km]Çv\ˆ¾QÇ ®CÛÝâ;Л ÑvË8¾;Ê4y÷nžÊ•hû²ñCÙQ¬ÉøÔ÷Ç’z½Q²²£T“,çÇÕh\‚u”jò‰½þ¸mÏWµšîÇ+5Ãârômj+àÅš|Ä¼ìŸ Òö] šþ=fL§‹Íºm«Kü¹m ZÊο}"µºKXíô×Õh›4ts¹ÛòÚóµžýåŒg…ólgúä<l‹óî%=78/¼…œór ˜gõ ±SMÊ{V¸•ó^}•Hy³ïØ#å•RÙļiâ¸|ç6$è™°Åo‚že;æ* gsÄ•œçÓ§.pÞNçrž}“Ÿ]9oð…çe}*Þåδ æ‘+/nçùG ~rÞÝ&ß&qžÕ:ኇœgˆÅéÂA¯E ^s±Ÿ˜Ú:±ž}mqËÅz¶Xç©Èz^p  ži“¸n¡Þ÷(8ˆ…z¶> ÅQï›Úù „zöá%¦%êñ EÔë^ù°^n>ˆõ<;",Ä=ó:aËÄ=+('î kîwT¸7ãi÷bà‹ö¾Äm¤½ï-‘ö^Õí(–%ÚöÑ!G’ö<=,¤=û"ó줽܄íYÍö†´§eeÀžQÁI{sÅFH{öi&¸‘öF@£hï{ÜŒíõxÇ„{|pd=ŒBF°žÕÃÛü‰±ž_–þ^èÿ£Ý+ž9ãðŽölG〽‹`ÁÞ0P‚¬7|Öu YÏ0_S²Þ0¡‹LFÖsç7õ†W…åñû¤‚B=»$¾ÙD=»s:¨7¼¬1,@½Õ „zæ¹Dîé w炤gŸ~DzVW¸Ò+û$=û‘ÑîŽÖAz¾=ÀF@z†ñ/y ¤Wv¢Hze'Ф7ž;h¤g×Äí ’ží’ÞÈ\’žûpɲ±¥ß='½áz¿Ò³q} ž]´PoÄ­PÏöN„h@½‘ u¢ž?rPÏÚ!7õb¤ç_bPo|ãk_¢Þˆ²qB=»3ƒÜ¹¹ßrqÖêYgÈW@½üÎõr›Q¨gÍþ€z£ ×ÃÍÓ-†|àÊž°gýåE öÜ ñ·d=ß’%¶õ¬Îfã{Þ_Z6§Ó‹o»`¯ôް—›¸gI Ö8›K8î LJߒöFøWíYfj\¤hÏKØî  `Ï– í ½q+Ñ’hoxîSZ0›ÚŠ÷—´gCæ" ölÕCöqÚ³¹…OŸ´7¼øåo {6ó¢{¶é}ÀÞ‡YÁ^¾^‚={•š€½n¾4lìfP9êu±*PÏFÃËÎíV×;¢=[q+€´g'Á|"Ú‹ïÅ¿’î,€oÙÔRxï}R¤ï­ð'ïeÑÉÎÏô·øV½&ñY5 ÆGøVÖ$&òf)»Ïª«ŸÈ·ÓË.¤½(ê#m¯7¡£´½ïfÒ 0ĽïÚ¸åæâÞÝc'ŸâÞ‡Yš(î™Ë÷°%î ù¥ úž(@êžÍçº÷½Jä,©{Æ­‡º÷-еÏMê{£ª¦¨ï‰¡@yïÑ #ê³-”[–Í‚)íÔ÷š "-Ô÷J» ¾ÞYâSÐg:ý”÷ºb­}¯g,‡Ð7’ }öþ ª úº­)©úl©"ÄÃ$õhNÐç“ 9‹òÞw%Ï)ïYua!&©(F$èD‹Ð÷bóúž¹’H©ï­¦¥1‘ÏVGÏ|#©UÈç¥ÚaòM«‡MÊòÜÕ&ò$æ@¾W‹V"Ÿ­K)bKàü¤ƒøì»Kvðõ×Dà›C æ( æyH|ß&‘ø  HÃB¾ÕÄ(ï %+ äË ô@¾¥u,‘oÞŠ!ò­ù¾w™÷áO‘Ïí}Ïüù\#ó “goÈ|ÏŽkóÍ"6úæuŠ{–'çñ=’BœøfŽqŸ¿ n ð™kæmïN‹ÏQVtšwœÀ7½ü,>ûÔòT¾Wó·€oš Àîøæú‰€o½R||îùÿ7poFóÀ½Qà¸÷½˜’é€{3WüĽi+‡÷V×î+-vîï£@‰¸g7†JXð^Ó 'ÞûÀ¤É‚Wp'Ë‘÷ÂB¸—°,Üû^;~í…{öZQ$ñÙ´O#ñ™TÇ–;Ÿ’„EŸ½b@Ÿ»Ö»Àg!Ù0ø^m—ð¥¼/â³\ nðõî|öIå1¾¯òˆˆÏ²¤¢ÃA|I_¬æ‚øÌËÿ÷ìÜ"¾G±Œ"¾ž¤.ä{c—HÈg§do€|¶§²x@¾¦]ó@¾­ââd¾1‚ÕÈ|}Q‘ùÒ?AÌ·b×EÌg‘Ì—ûOb>Ójuφ„Ú!óåbCÌ÷’&ù¶ô| _l ‰ùŒð‡ï–;E 1Ÿ9GÁ@ä çˆ@¾ž8Gä{5òY,iÈg‘>ÄÂÁ÷‰|ñHä[|WùF‹cˆ|æ-E†¢º÷ ­÷d¾ð°æ‹`0_—ûI0ߣŠ?!ïíû÷l Sô}£{œ _|=“úf@*©¯+¿MP_ì õy¥Z–¸•íˆúº<ûÞNJõ}Wr“´=Bìë¡~û†4?¬‡ƒÓo…ùní–óõ©gÌô̧ª@Á|ߺ` Ÿ½sì­˜ÏËUÁbÌgø6O…/ö‰ú´!Л„}W<B_¥KBßÕ4°}åúÌr*|ÍT‰I~ö5$Å9ùÙÊø9t¾Qè"¿tk©ä×QÜþ?O’&Úk íí_×{™f1`ï eÎXϺ%é°çë[þ°×Z2$`¯$û¦gD•§ñì¬g%G¹Ð£º7#âNê^¦j”º—¥ý$ï­¨ªC}¯§vG?έW6ü8m†;Qï{ªí@½ûQq?¡ÞíA¿´øÜt÷w¨§½¡žE7‡œGÎt“#çõp}¯° õ½;ò^ )ïy¡:Xz=ViräLWTÉ{¶ž%ÅQÞ±Óò^ 2IïIw:É{ŠSÞ“k^žº¶¨î}ƒV?èY;CÐ{R>#è™,ßä¹éS“¡iE¾œcJ©£¸g®¤C÷"©Bˆ{}ý:Hïݱ|%é½QsP¤g´ML轞•ŠøtUxè½3ü" zF#‹ ÐëQtK g¿bÃÝÿ ÿV’ž©žëpä|MK99ß–""9ïç× z’¤í…#—´={eˆV=Û “’GÐ{ûš g‘Ô¼¡zýVú{ž¹šð½ 虿©‚ ×óîIÛ{Tv0Ä=sjà™½O–î'AÏàØNÐ3•~¨{îíE˜빋huäü¦Ïv:rçIÀž;¹°×=-ð>ñ< °ölŽ{gNûÕë&½¿†à^êÞõƯ{ÝÞÔÙ³·p6vØKwñ^oª(Þ3o¯ûà½âº'ÞóŒ´@Þ b‘ºç‘·°÷"&P¸gÓ?¿Ž{=ßCâžíiðKܳõàëáÊžºråÌ/|9Gªeôå´ß´×½^2,ôå\á²¾œ;Î-_Îç§/ç7$8øäËù5§_É—óÒ7J¾œéS/Ü O6â^h‰{ßù%q÷Â]:¼9iäÍé…1`¡7çJÞœQþ#¼9mê?xÏ,\Û3Ø8Ü9½(-ð™Wœ)Ý9éÁ'wÎØ ೪ÃB@ŸX=€Ï›a‘È÷&øRsð…{ý9·ö‰Â¥3ö’RåëÒ²|æ;N$ðå“‘O§˜ðªèÓŸºð霩‰Ñ§Ó6“à³’)¾»$frˆoIwñy|üoø<» ,d¾{…ó%½:¿•U²úîþèÖ™è#ès=Z!¡…~@_,¶úz8zúÊ߀¾¼r댥@*}¯è8 oK¤ÐrH0_ìÖó=ÅÏóªe"‹dk—î¸B>¹*ø®I„V nb­€¯iéÀgy†þšÔwý^ê§úËj¿Qè¾{å1 +”^Nb_¤Ë ±/r«ÿL¼üÛ+’"PëKJ}kHe$ÿÝ–tB1zηezPLžóŸå¨yPêk¶¼$¹½îæ{¿ä?‡ïÁö E‘à¿'øÏ"šæÁ¯ÄCê³E·XüçžÅ¤0ðŸ/ñHX”úÒA‘ü×ï;ÂFWCEéQê‹í` -Ò½0_DðÍ )}^å•NV¯¶Óo©ØKÚ©"ùÒOKR_ª^’ú,w yé’þ–)})gIéûžåu(}¾ïHÜ{Ã¥ýPúf %•¾Îg$ÀÜ󯌿)öÍ`$ö'AŠ}3|€ˆ€¾§MÈÚ1CÌU6 Ö(öyqXžØœÜŠÝÃ\µGÊûr×Â!ÐÔ“u@àðaé©};\@©öy%nXÀ€&ŸP`‘gн¡öm­r óçMœßÒÛ7„À[‚¡öåuœéJFœßS¦Ô¾¡ÐPûfÍRûbQ83X†8-åˆæ³¬¶×©ö}¯&ýŸ ó;¥8¸xš/»œ@³8b0ö–eê`@¯3õ>;Ï€3ý¬‰€vM|a„€¹Œ”ÞgÛVT €3w^ ˆBÿÃö¤9 ñ|ž]ëˆç›žé " mAñ|–ú›Ï%<ÜüÂU¸H~\ñKòËA ­tÈx^¶S/]/R’ŸEPš_Þˆ"úMY úYžÑSô+ŠU¿¡);T?OöGËÒ7Saòó¼µCCÕïúÒW`’ªß÷ÑPýÞPëäç9õBËÏóû:láÔªLíHõ{õÅ–ê—¡Rý gQõ3]²˜«~æ~GRÆ®SÄôE”§T¿ï®ËTª_¸†„êw§ïgÄô½š6ÃÙLªŸ½ÚUñµZf6½èS( ¼u¢ôôÔŒªß=”²_ä8 ÙÏ¢ ¾ )û­Lyz&Nz²É~oú~bfmbïôôÔ*.d¿6‚Äèé™:èýV!°É“ h;©´Hô+–ˆ›(8"b?ÐbA¤ð!lÂëAÓ‚y5âµ5¯†æ×V*|Ôü¦ˆ%<=µ¿šŸ­OWOû~Ÿøõ',‹$qúz>oÈ‚dÀôÙ-ºß<…¿Ñƒ3RÂß#ëþ¸ ©ÈVH€Ùๅ®ž&c*Ðo†‹A²_`-Ð<¶tÀ­½¡<=»ôe`ßzM3ç1ÀKÛ±I€MV®D@SfOÑÏf XÄ€ùæŠG÷ýïÿõÂÕá¹endstream endobj 6 0 obj 166225 endobj 4 0 obj <> /Contents 5 0 R >> endobj 3 0 obj << /Type /Pages /Kids [ 4 0 R ] /Count 1 >> endobj 1 0 obj <> endobj 7 0 obj <>endobj 9 0 obj <> endobj 10 0 obj <> endobj 8 0 obj <> endobj 11 0 obj <>stream 2020-03-05T13:49:57-06:00 2020-03-05T13:49:57-06:00 GL2PS 1.4.0, (C) 1999-2017 C. Geuzaine gl2ps_renderer figureOctave endstream endobj 2 0 obj <>endobj xref 0 12 0000000000 65535 f 0000166542 00000 n 0000168292 00000 n 0000166483 00000 n 0000166332 00000 n 0000000015 00000 n 0000166310 00000 n 0000166607 00000 n 0000166707 00000 n 0000166648 00000 n 0000166677 00000 n 0000166771 00000 n trailer << /Size 12 /Root 1 0 R /Info 2 0 R /ID [] >> startxref 168512 %%EOF blis-0.9.0/docs/graphs/sup/dgemm_ccc_kbl_nt4.png000066400000000000000000006561651422157504600215510ustar00rootroot00000000000000‰PNG  IHDRTjûF¦Â &iCCPiccH‰••gP“YÇïó<é…@B‡PC‘*%€”Z(Ò«¨@èPElˆ¸+Šˆ4EE\•"kE ‹‚tƒ,ʺqQAYpß÷?¼ÿ™{ÏoþsæÞsÏùp ˆƒeÁË{bRºÀÛÉŽÌß(ŒŸ–ÂñôtßÕ»­Ä{ºßÏù®‘iü常¼rù)‚t ìeÖÌJOYá£ËLÿÂgWX°\à2ßXáèyìKο,ú’ãëÍ]~ )úÿ†ÿsïŠT8‚ôبÈl¦OrTzV˜ ’™¶Ò —Ëô$GÅ&D~Sðÿ•ü¥Gf§¯DnrÊ&AltL:ó5204_gñÆëK!FÿÏgE_½äzØs û¾zá•tî@úÑWOm¹¯”|:îð3™ÿz¨• €è@(U  t0–À8à|AØø $ȹ`(E`8ª@-hM œà<¸®ƒÛà.L‚—@Þ‚°¢A2¤é@F²† 7È ‚B¡h( Ê€r¡PT UAuPô tºÝ„¡‡Ð84ý }„˜ÓaXÖ‡Ù0v…}áõp4œ çÀùð^¸®‡OÂðø6< á—ð"Â@”]„p$‰BÈV¤)Gê‘V¤éCî!Bdù€Â h(&Je‰rFù¡ø¨TÔVT1ª uÕêEÝC£D¨Ïh2Z­ƒ¶@óÐèhtº]ŽnD·£¯¡‡Ñ“èw †aaÌ0Θ Lf3¦sÓ†¹ŒÄL`æ°X¬ Vk…õÀ†aÓ±ØJìIì%ìvûGÄ)áŒpޏ`\.WŽkÆ]Ä á¦p xq¼:ÞïÀo—àðÝø;øIüA‚À"X| q„„ B+áaŒð†H$ª͉^ÄXâvbññqœøD%i“¸¤Ri/é8é2é!é ™LÖ Û’ƒÉéä½ä&òUòSò{1š˜žO,Bl›XµX‡ØØ+ ž¢NáP6Pr(å”3”;”Yq¼¸†8WJ)Hq¤"¥öHµJ IÍKËIÛJGJJ·IK”aÊ8ÈÄËì—é”y"‹’Õ–õ’Í’="{MvVŽ.g)Ç—+”;-÷H–×–÷–ß,L¾_~NAQÁI!E¡RáªÂ¬"CÑV1N±Lñ¢âŒMÉZ)V©Lé’Ò ¦$“ÃL`V0{™"eyegå å:åå–ŠŸJžJ›ÊU‚*[5JµLµGU¤¦¤æ®–«Ö¢öH¯ÎVQ?¤Þ§>¯ÁÒÐØ­Ñ©1Í’fñX9¬Ö˜&YÓF3U³^ó¾F‹­¯uXë®6¬m¢£]­}GÖ1Õ‰Õ9¬3¸ ½Ê|UÒªúU£º$]Žn¦n‹î¸CÏM/O¯Sš~°þ~ý>ýÏ&   ©†.†y†Ý†iñªî¯&¯v\½mu×êׯ:Æ‘ÆGŒ˜ÐLÜMv›ô˜|253˜¶šÎ˜©™…šÕ˜²élOv1û†9ÚÜÎ|›ùyó¦é§-þ²ÔµŒ·l¶œ^ÃZ¹¦aÍ„•ŠU˜U•Кij}ÔZh£lfSoóÌVÕ6¶ÑvУʼnãœä¼²3°صÛÍs-¸[¸—í{'ûBûªƒŸC•ÃSGÇhÇG‘“‰Óf§ËÎhgWçýΣ<Ÿ×Ĺ˜¹lqéu%¹ú¸V¹>sÓv¸u»Ãî.îÜÇÖª¯MZÛé—ˆÿ2Â6¢,b&Ò*²4r*Ê*ª4j:Ú*ú@ôLŒMLyÌl,7¶*öuœs\mÜ|¼Güñø¥„€„¶D\bhâ¹$jR|Ro²brvò`ŠNJAŠ0Õ"õ`ªHà*hLƒÒÖ§u¥Ó—?Åþ ÍŒ]ã™Ö™Õ™ï³ü³ÎdKd'e÷oÒÞ´gÓTŽcÎO›Q›ù›{r•swäŽoál©Û m ßÚ³Mu[þ¶ÉíNÛOì ìˆßñ[žA^iÞÛ;»óò·çOìrÚÕR V (Ým¹»öÔ±? ìY½§rÏçˆÂ[EEåE‹Åüâ[?þXñãÒÞ¨½%¦%Göaö%íÙo³ÿD©DiNéÄ÷e̲²·7¼Yn\^{ˆp(ã°Â­¢«R­r_åbULÕpµ]u[|ÍžšùÇ‡ŽØi­U¨-ªýx4öèƒ:§ºŽzúòc˜c™Çž7ø7ôýÄþ©©Q¶±¨ñÓñ¤ãÂÞ'z›Ìšššå›KZà–Œ–™“!'ïþlÿsW«nk]£­è8•qêÅ/¡¿Œœv=Ýs†}¦õ¬úÙšvZ{aÔ±©CÔÓ)ì ê<çr®§Û²»ýW½_ŸW>_}AòBÉEÂÅü‹K—r.Í]N¹<{%úÊDÏÆžÇW¯Þïõê¸æzíÆuÇëWû8}—nXÝ8Óâæ¹[ì[·Mowô›ô·ÿfò[û€é@dz;]wÍïv®¼8d3tåžý½ë÷y÷o¯ñy02*|ñ`úaÂÃ×2-<Þ>†+|"þ¤ü©üÓúßµ~oš /ŒÛ÷?óyöx‚?ñò´?'󟓟—O)M5MMŸŸqœ¹ûb݋ɗ)/f þ”ø³æ•櫳ÙþÕ/ M¾¼^ú»øÌ›ãoßöÌyÎ=}—øna¾ð½ÌûØú>|œZÈZÄ.V|ÒúÔýÙõóØRâÒÒ?B,¾“sMT cHRMz&€„ú€èu0ê`:˜pœºQ<bKGDÿÿÿ ½§“ oFFsF×j`` pHYsNNÆÊ/¥tIMEä&>(Ê vpAg´¨“ÁQè€IDATxÚì½}œU•ÿÿ O $ΤBj@fxêàÒ>kµ$ ˆùR=øS²Kªaw1îî¬U_]£›ÝÕ.]Œú•íÊËt!Š"»XuÄ0…ˆaÊÄ&@¦2!ÄùýqûVW?N÷LOwMÏy¿^ýšé®§[Õ}ꞺŸ{ÎY2=== ‚ ‚ ‚ ‚ ‚ ‚ ¢"G´ºAAAAAAa‡‚ ‚ ‚ ‚ ‚ ‚ ˆ A… ‚ ‚ ‚ ‚ ‚ bHP!‚ ‚ ‚ ‚ ‚ ‚˜T‚ ‚ ‚ ‚ ‚ ‚ f€‚ ‚ ‚ ‚ ‚ ‚ ˆ A… ‚ ‚ ‚ ‚ ‚ b… bš&lÛnu3ˆð<¶mÃqœ†ìÏu]˜¦ÙêÓ"ª@öÙþ¸®[b×d›á„ìqqR«=zž×uËnoÛvÙeÄü@¶ÚþÌ¥ï$[m-dŸ ƒVÓ²ZÚ?Óu°mžçAÓ4€ ‡¢(UÏÕqÿ;äû¬6£'ø}׳Ñ8æbŸ•l ûœOûœÉ^*+ÿnAðÿŠ¢XòyÛ¬åxDãX ö8[[äç&{¬Å6Ñ_í$I‚ªª$©`=Û¶!dYöד$‰f”Í‹ÁVgZV°Ù*ß3ûN€lµUT³ÏÙ>wµÿÖe›Á}5ª/ ¶ú¹³ÒùÎö¹¨l›¼=dŸÍƉªƾt¶ãDôº°˜~´Ýí²Ú²Vû¸•ηíÆo§ÛŒñññiÓÉdrzzzzZÓ´iÓš¦MOOOOOLLL ‚0N§§'&&¦UU0Éd –óí3™Ì´ þ~ù~’ÉdÉqdYöÛQϺÕ0­ªêôÄÄÄôèèè´ ~[«-«v}øù󶈢XñójÛÔÚþZ®C*•š–eÙÿ«(JÁ¹T:×L&S°Œ_|ÛL&ãCUÕiI’üõªmGÌs±Ïj¶9=]ŸÍ‘}Öwf²—j窪괢(Ó©TjZQ”‚}–³ÍZŽG4†Åb³±E~}ÂfµØÆlúËjöD–e¿¼ÅßOñ:ÄÜY,¶:Ó²j×'l¶Ê¯u3ûÎ d«Í£š}Îå¹szºößZ£l“ï«Q}éll0 Ï•®ƒa³zî RÎîÈ>›-̾t¶ãDÓÓôºP˜¯~´í²Ú²0ø¸•Îw¶ýhXí²íMÓ¦UU-øLÅ‚EÐ&&& 2•JMK’T°½ªª¾Qsø|_lµ®[ ŽP™iY%’Éä´¢(%׬ÒçÕ¶©µýµ\~}yÉß(Ê+7¤â¶ñß?†ªªÓ‚ t”Õ¶#懹Øg5Ûœž®ÏæÈ>ë»3ÙKµså8ÿ;“mÖr<¢1,{œ-òó›=Öb³é/«ÙcâžrÁßÑ‹­Î´¬a´Uþ3ûÎ d«Í£š}Îå¹szºößZ£l“ï«Q}éll0 Ï•®ƒa³zî RN(!ûl4N´0ûÒÙŽñmé94üÌW?ÚÎvYmY|ÜJç;Û~4¬vÙv)¿ÇñÃú8¢(úÿ{žWj[¼®ëºpK–,ñ_­%*nc­ËÊáy^Áõ€d2YñójÛ4Q‘N§!Ë2’É$TU-¸ö•ε8tZ„‚œ³Áð¼`¨ÛLÛg.öFÛ,nc=ËÊfûœÉ^Ê«iš°, £££H&“‡ã8~þèJ¶YËñˆ¹³˜ì±^[äçF{¬Å6fÓ_V³ÇJ”;ÙiãYL¶:Ó²r„ÕVæ÷õ\S²ÕÆPÍ>âsg¹vÎôy%fcƒayî¬t¾³}î¬Ùgs q¢ê„¹/Í8=‡.Ú­m†]V[·Òù¶ÓømÛ *åò’Sí¢óü¥Ó,zÇÍÇ0,ضÇ—ý¼\ŽÉ™–ÍY–KŒ­Ö›Mñ÷YÜ.I’J¥ iZA>Æ™¶#Ï\ìs1Ú&ûfg/®ëBÅ[–eÙß¶’mÎöxD}=ÖOìq.¶QmÛjöX I’Êî³Ø‰'æÙjý„ÁVæ÷• [?f²Ozî,d&¬×ngC+ž;«AöÙhœ¨~ÂЗÎÖ^é9tá@ýh}„¡fo'í4~Ûv‚Š(Š0MÓ¿¸Žã(\Š¢ü˜Š‹ )ŠÇq|%Ìó<ôôô\ÈȲ\p}lÛF<ÇûÞ÷¾²ŸóT¥e‚;’ÁënYVMޤëºþ÷È·ãEý€|‡«iDQôg%Ì´ÑxæbŸín›@x혽p»æmãÛ‹¥¶9ÛãõAöX°Úã\l£Ú¶Õì±Ú5ò<¯ @¡ëº…}‰¹C¶Z°Ú*Ðü¾³Ú5"[ªÙ'=wÊuÛ`5»m­xîœé:‘}Î?4NT°ö¥³µWz]8P?Z™°ö£Àìí¤ÆojéÑçUUá8zzzü›hБ$ Š¢ ‰@ÅUKEhš†X,æo/ËrÛ84ü\øõqÉd²âçÕ¶i$‚ ™L"‰@–eÿº«ª:ã¶¢("‘H@E&‚¦ie×åÇX³fM]Ûa.öÙî¶ „×>úìŒÃ à÷-I4M+q†¸mòï“ìsþ!{¬NXíq.¶QiÛjö8Ó¬±d2‰x<^p¾vØ;d«Õ «­Íí;ÉV[C5û¤çÎúm°Ÿ;É>ÃU'¬}él핞CÔV&¬ý(0{;i§ñÛ%¹b1m‡ã8~¾½ 3âyž*äydYÆ’%K011Q’sÚu]‚PSxèBƒ_Q ÔýJŸÏ´¬QÔ{ÝmÛ†aÈd2°m{Þ·#Ã\ì³Ým3x}ÂbŸsµ—fÙ51;Èk»>a°Ç¹ØÆ|Úÿ̧@­Öz}Â`«@óûÎzöI¶ÚxÊÙ'=w^›zl°ž;ëmÙçüBãDµ]Ÿ°ô¥œÙ^÷°Ù9QêGg¾6aéG›=V»l[A¥®ë"‰ NC’$†ÇqÉdZÒ–j“dY®+„©Ñû ˱ª4¬flGÌ/a±Ïùø}/dûl¶½}†²ÇðÙã\lƒìª} ‹­ò¶oË ›#ÚÙ6çkŸa8V%Ȧۛv¶×Åf«sì<\]6ÎVÂðLÚnã·m—òk&DQD*•ò󰉢ˆt:Ý’¶ð¼wÕÚÚÊý…åX3µc6ÊdXM¢°Øç|ü¾²}6Û^È>ÃÙcøÚ?Û »j_Âb«ù¶Åû#›[Ü´³mÎ×>Ãp¬jm ›n_ÚÙ^›­Îµýdçáì2œíoö8lXírÑE¨AAAAAAÔË­nAAAAAADØ!A… ‚ ‚ ‚ ‚ ‚ bHP!‚ ‚ ‚ ‚ ‚ ‚˜T‚ ‚ ‚ ‚ ‚ ‚ fàÈÏ~ö³ŸmöA§¦¦à8¦¦¦ðº×½®`Y6›ÅØØ ³³³Õׇ Õl û$ˆVBöIá…|[‚'ÔwDx!û$ˆðB¾-AT§é‚ÊØØ6n܈'žxÃÃÃxüñÇñ®w½ 0<<Œ-[¶à‰'žÀW¾òtvv¢¯¯¯Õ׈ Õl û$ˆVBöIá…|[‚'ÔwDx!û$ˆðB¾-AÌÌ’ééééfP–eô÷÷cóæÍ˜ššÂÆ100€õë×cݺuؾ};¢Ñ¨oÀ¶m£»»»âþÎ;ï<¼éMojõuœ3À²e˰lÙ²V7eÎìß¿'žxb«›Ñ´óØ»w/6oÞŒ}èC­nòœ¨f›ê¶ÏO~ò“¸çž{ðÆ7¾±Õ§6gÚå7½ï3cccصkW«›;gmŸo~ó›qÖYgµú´æÌáÇqøða¬\¹²ÕM™3írŸ©õ;™œœDWWþýßÿ½ÕMž3öm/¸àôöö¶ú´æÌbìsÂN­ß ù¶åíóþç°cǬY³¦Õ§6gÛoz!@¾íÜìóÝï~w[Ø&ù¶áƒ|Ûö÷mÃÞ—,„ûBØí}^|Ûé&òÓŸþt:‰T\öž÷¼§à³~ðƒÓ7ß|sÕ}®[·®™§0o|ñ‹_œþéOÚêf4„«®ºªÕMhêy´ÃwWÍ6ùòzísÇŽÓŠ¢´úÔB»ü¦Ûá·Ê©õ;i‡ïn>ì³]úΟþô§Ó_üâ[ÝŒ†Ð¿ÕééÚ¿“vùîæÃ·m—ßÂbìsÂN­ßI;|wóÑw¶Ë}kzzñý¦äÛ.¯×>Ûáºðs§ûL¸ ß¶pY;ú¶aïKÂok1~ÇG5SÊf³èëëÃðð0vîÜ‰ŽŽô÷÷ûÊf±¢ÙÙÙ‰l6[uŸK—.ŦM›044ÔÌSi8ýýým“{p`` ÕMhÚylÚ´ {÷îE4musçD5Û0+û\»v-ž~úi .øßÄBo?g1ÝgÆÆÆ088ˆýû÷·º©sf>ìó5¯y 6mÚ„õë×£¿¿¿Õ§8kúúúªÎ†ZH´Ë}¦–ïdxxÃÃÃmÁ8¾íÞ½{É· íbŸµ|'äÛV·Ï;î¸ÀÂÿM,ôösÓ}†û¶{÷îmuSçÌ|ØçþýûÉ· írŸ!ß¶q¾íÀÀ@(#UÂÞ—,„ûB˜í}ppwÜqGÃ}Û¦ *###èèèÀæÍ›122‚M›6Á¶mLNN–¬_ËæÔSO]𜵞ëB!Œ7Èù:¡¡! ¶º©s¦šmvwwÏÊ>;î8\z饡¾±ÖJ»ü¦Ó}¦··CCCØ´iS«›:gæÃ>ßð†7´EßÙÑÑŽŽŽV7£!´Ë}¦–錄¿ÝÝÝiusçÌ|ø¶kÖ¬i û\L}ÎB¡–ï„|Ûê\|ñÅäÛ†ˆÅtŸ!ß¶úw}â‰'¶EßI¾mø ß¶ý}Û°÷% á¾f{Ÿ/¿­©‚ À~¨Û·oD£QLMMaxx¸¬˜ÍfCý¥D;QÉ6È> ¢Å}Dx!ß–  õ^È> "¼oK3sD3FKT5þ¾···$Llrr2ôJ!A´Õl û$ˆVBöIá…|[‚'ÔwDx!û$ˆðB¾-AÔFS•¾¾>d³YŒ¦¦¦°sçNtww#brrÒ‘C6›Å† Z}¢í©f›È> ¢…}Dx!ß–  õ^È> "¼oKµÑÔ”_ÀÆF‘ÍfFý¢aزe úúú°{÷n „>OA´3Ù&@öI­‚ì“ Â ù¶N¨ï$ˆðBöIá…|[‚¨¦×Péïï÷²³³³ ×^pYww7…D©f›ÅËÉ> ¢¹}Dx!ß–  õ^È> "¼oK3ÓtA@U£#ƒ$ˆÖ1“ý‘}Dë û$ˆðB¾-A„ê; "¼}Dx!ß– ªÓÔ*AAAAAA ‘–D¨AAAA±ðÐu½à½(ŠP‚ øËUU…(Še·7M¢(B–e€ã8°, TUõ÷E6(B… ‚ ‚ ‚ ‚ ˆš0 ¶mÃq8ŽÓ4ÑÓÓ×uýåüÿrX–Û¶ýuc±˜¿Ì¶í‚}A„ ŠP!‚ ‚ ‚ ‚ ¢f’ɤa±X ¦i"™LÖµ]בÉd ö•H$`R©T«O“ ¢ŠP!‚ ‚ ‚ ‚ bÖTJï54Mƒªªe—麎žž,Y²ñxžç`i‘.|Ýo~ó›Ðuº®£«« ===0M³Õ—‹ ˆ E¨AAAAQ3ŽãøÿÛ¶ Û¶‘ÉdêÞªªˆÇãP’$AQ”Šâ ¯µ’Éd ‚É’L&áyžŸF,¸~WW Àªª‡ã8ˆÇã5\‚ ê‚ ‚ ‚ ‚ ‚ ®ë¶¼†ˆ $©âò`©‡T*Y–aÛ6 Ã@"‘€,ËH&“%Ç^AN§k>ž>L–e¨ª ˲HP!bV BAAAA!Áuݱ¢Ùˆ¢XUP)®¡bš&b±&&&ê>–¢(PÅ?÷D"x<Žñññ’õÇAOOa¢iÚŒéÆŠÏC„‚‚ ˆz A… ‚ ‚ ‚ ‚ B‚,Ë .zBź#TlÛ†®ë-ئi%õP8ÉdÉd¶mÃ4M$‰Š©ÆxDKq´Ïl"i‚ 8T”ž ‚ ‚ ‚ ‚ ˆYáyÞ¬Rh‰¢ÇqJŠÄÛ¶]v_º®ûB‹,ËPÅKAðÛ°ú)AA…Gü̶­AŠP!‚ ‚ ‚ ‚ ¢fŠ#HxÝ“jË‹#IDQD*•‚®ë0M‚ ø"H¹ú(ªª"‰ ‰øi»ø1%I‚$IˆD"~ 0žêKE$ ˆ¢×uý(‚ ˆÙÐtA%›Í"›Í|Ö××‡ŽŽŽ‚åÝÝÝèîînõõ!ˆEÃL¶\‡ì“ š Ù'A„òm "œPßIá…ìsá3===§åAaEUU¨ªêG‚P±v‹(Š˜˜˜ðו$ÉL€ÑÑQ@±m¢("“ÉÀ¶íªû'È·%ˆZhº 288ˆ;w|644„h4Šááa ¢¯¯»wïÆÀÀúûû[}bQPÍ6}D !û$ˆðB¾-A„ê; "¼}å¨'Wµug»Œ`oK3ÓtAejjª £ 288ˆíÛ·#bll 7nD4%Å“ š@5ÛÈ> ¢•}Dx!ß–  õ^È>‰fB)õA¾-AÌLÓ‹ÒŒŒ”5´‘‘tvvúÛÛÛ‹ÞÞ^ŒŒŒ´úÄ¢ ’mòedŸÑ:È> "¼oKá„úN‚/dŸD3‘$© ¶ Qòm bfš*¨LMM¶nÝŠÓO?ëÖ­Ãðð0`ll¬Ä`;;;Kòö³wï^lÚ´©™§A>›6mÂwÜÑêfÌ™j¶ ÌÞ>ï¸ã ¶úôˆEÈØØ6mÚ„ýû÷·º)sf>ìsÿþýØ´iSÁ~¢YðTÏ>ûl«›2gÈ·%Ú òmÉ·% ÷m÷îÝÛê¦Ìòm‰vƒ|ÛÚ|Û±±±VŸ±œßvÖ)¿¦¦¦°{÷ntvv¢···¦m²Ù,¢Ñ(6oÞŒ¡¡!ŒŒŒ`Ë–-èîîÆäädÉúµ„Œ­Y³CCC ¿0Q CCCmñPUÍ6£Ñè¬íóâ‹/ÆÀÀ@«OX„ôööbhh¨-%çÃ>O<ñDê;‰–ÑßßîîÍF¾-Ñno[òm‰VA¾-ù¶Dx!ß¶:äÛ­d¾ü¶Y *ƒƒƒØ±cø†¶uëVlß¾½ª¸ÂN4ņ ü°±b²ÙlÍb A³§šmF£Q²O‚h!dŸ^È·%ˆpB}'A„²Ïö@×õ‚÷¢(BQ‚à/WU¢(–ÝÞ4Mˆ¢è‰w–e`5OTUõ÷E4òmkÇóËT•½w] ÂÏhCêNùµsçN chhÈ7²h4Šþþ~\uÕU~xX9²ÙlIˆWGGf´Åab“““T؈ š@5ÛÈ> ¢•}Dx!ß–  õ^È>ÛÃ0`Û6Çã80M===p]×_Îÿ/‡eY°mÛ_7‹ùËlÛ.ØÑ<È·­ÇtÈýŒ‘H0Å0X<¾"»†êmj%€Ì¤%Ô-¨ŒŒŒ ¿¿ß/BÄÙ¼y3º»»±{÷îªÛnÙ²Å]¦¦¦°sç΂ÐN"766†l6‹ 6´úDÛSÍ6}D !û$ˆðB¾-A„ê; "¼}¶Éd™L™L£££$ ¦iÖ½]בN§‘L&ý}*ŠÃ0Z}Š‹òmg&‘b1&¤È2U\pl ¡æD•OÆgØúÖ?ÖW ÷aYl›1ÄbêÁFy±ÆrˆycÖ5TfC?ÆÆÆ°qãF_|éïïG?–×lË–-èëëÃîÝ»100P0S ˆùa&ÛÈ> ¢U}Dx!ß–  õ^È>Û±ùŽ4Mƒç•Ÿ®ï8‰Ç¢(Ð4 ’$•,“$ š¦AQÄb1_¤ñ<ªª"™LB×uˆ¢5—·Éó<Äãq¤ÓéE™rŒ|ÛR‡¥òâ?×eBŠaé4KýeÛ€ @ý2`üp¿Øi@¾°<@g‹¢°}YÛoÒ0@ÜSQÊÔ À¢VL°x"¹mX§€ &®è¹ÿ&´”Û†¨‹º•h4ŠOúÓ% äðð0²Ù,úúúªn¿mÛ6ŒùaaÁÐ0ù’ÍfK–1¿T³M€ì“ Z Ù'A„òm "œPßIá…ìsflÛ†ëºe¦iBUÕ’¿¶mCE?5ÿ¿QÛØ¶í åp§ ½¶m#“ÉÔ}®ªª"CQH’EQ*Š3®ë"‹!•JAQ躎x<Žññqxž‡X,MÓ0:: Ã0H$ I’Þ£££þ>dY† þù,™çy‹RLáo[ˆõW€x ¦Ø{_PIÒßÂ/€®. u! > h < /¦¸{ñU&¢XÿÈ€w.`»dÀ2YâÛä7ùI0ÑÃ>0…‹ XTŠ &¨pá$ß`‚Š˜{/€ 2ã¹Ï‚¸c3R· ²~ýzìÞ½ÛW+'''!Ë2&''kV&«,Z,Iad¦bbdŸÑ:È> "¼oKá„úN‚/dŸÕE‚ @à¿ø¯$Iþ:üÿµ ú¨D° §RTI5R©dY†mÛ¾"Ë2’ÉdI,Ë‚,ËPK;Æá…î5MÀ¢\‚Åî“ɤ^|¿ªªB×u¸® Qg‘ ‹Ý·M¼Ðþ‡E“8¿ÄNö¹ã’Ä^£_„?eŸ«* }€—+Lÿ'l‘"|pºí½€þyÀ9HþÛgü*Àù1 »€öFÀ9x_ù”]"€ ˜p"#µbƒ $øq‹·©¥=²,ò,˜¦ EQuº¯…„ã°—®Ïrû³ÿ]ˆÝÈ ÎÛ6€@rk.e9`ð4_ @úNnòÑ ˜XÁëœ8¹— &päD1¤‡±+·‹­€ðï€Ü H'Ò%€$Î7sûârûrÇáâ &ˆðh5°,'âøÂ ÏÆ§!/ü ×ÇrÛpáÆÈ½ +Ð=°Ø„á$æí«u *ªª¢¯¯ƒƒƒ)yAAAA±8ð<ÏOÇU¢(Âq˜¦Yð¹mÛe÷Åk½p¡Ä¶mÄãq?҄מ©§MŠ¢ø©Áx” ~,+ÿš â{”‰(Ƨå% }=Wp€ $“€¶PßÈÎn@8ùÈ °‰û\B¾þ ‘Ù{óåC¹Ïs$Úëe[GºH?ÿ#¼øâ—ؾíܾdÖ&_TÑsíà…éc`Q&È}žÌ­ŸÈmãä¶q‘¯¹Â‹×s$™Û7_ÆS‹)¹m‘ûŸkŽ:€8 E.(™(ŒØA`§Ìç^…ÏËQ›Ö:¯ÔòË4M vìØQ²üÑGmõ9AAAA1OÄb±‚÷¼îIµåÅEëEQD*•‚®ë0M‚ ø‚H:.9&¯ŸÒÓÓI’à8ŽLI’ ª*"‘ˆ¿LQ”.Æ8ŽS· D´ÇaõJ%_Û¤ôÜC,"E\É7Θ8ˆgž9Êá£d/É[ˆ€òòÑ <*…ˆ˜°aƒE„ðÿ€l;¡p=?«W"±È•Ûî¹ gÿl¨iÿïÐøëù×âƒZ~;È€6þê7øáWÞ@äE £^à,ÛÜXö‰Hó¬u.ðäQ‡pÉ›~…o}é6 (€÷=À»+§ñtbÉ\›cÈ×QáçÊÏ×@^(I‚ ü/–ÑÁ.&O3–D^´I#ŸÊ,…|J2žºLG^ÔIäöQ˜á/ß!Ô"êT000кAAAAѦ§§ç´<(¬¨ªê×/àޝD*•‚ªª~=•`M•d2 UUý"ó|Yq{Š…râ ^<‚wÀ0˜°âºL\©÷@;¿Ÿä$ð¥[vओV@^{uaZ+>ˆÏ£Cä… ù´Zbn] lÀ?(ÈÀ+ÿý î{ÅÆ†7oÈG–äö³lÙ2€ð^àMÿ5Š¿¿5ßü¸ððAüÌXI²ñ¿Ý§âÞŸƒK¶ÄáUÇÂyøÄãÀ}?{G‰CÎr¨'ÞÕ€y`‹ÀŸ?cœ…Ès5íwæ-@ò þ4 ÿH~ ùÈ…©ÊLä^«Å[Ò¹môܺi0A&&†ØkÈÅ y!… 6<²…Gäð¿6€ÑÜ:&òub¸µ• ccc˜œœDgg'z{{[wAAAAA,Hꉩ&¸‹,DûÁë§Ø6SxÚ¯™s}.hä<@œ´ÃŽ2ÛgïzKî^‚µ[‡°ù4V*ò¢†|Qø`‘x.Fð$üç™°ÉLT<³û¼î¸!hÆüqå±#¹q=ŽÇ^} Ï®y··"¥¦ ¥ïÂo~ó5èû*޽óüð‡'à®ìZüïÿNᓟÅ9ï_§~ücÜwß_âóÉ ^Üý]¼ÿöÛqxÍOpùOÞ€Ÿ=ú3ttœ‡Á×ߊžž qâ‰qÌ/ÏÆz÷A_ónú¿}Î>ÊGý‡Yá@zìBiì|¼À`õ] €‰fà\ƒ"SLPQd¤Üþâ¹ÿ50áEA¾V ×4yZ2¾½‘»Ž:ò5]Òÿ9žÇ^M²ýºk¨Àðð0Ö­[‡7bÓ¦Mظq#dYÆØØXSMAAAAA,.¸ä£S*Â#L8¯>ô ¦§'ºˆEƒl±ïáÃÇ|Gî=²0º„G‘páȧáQXÛ¹õrÚྯïÞ,0õGîq‚Ïó°ë¼]øí’ß"‘Hà±w=†úÃØµk\ÁÅ]ŸÀI'íÆÛÖý/"/A6{::>‡ÑQàŒ'nÚ57à’KöáöÛ/Ž÷¾ˆSÆ3ø‹õëñÚçŸÇ÷ÿ ~uìA|ìcoÁ»Þõ*6n܈sÏý9¾ýíÓñ±Ïá?oùKhÿ,ãÒ•/Aíf©Ò”€œ‹“ˆ¼°¶±ÿ ôÄC"2=;»#wÞIäk¶$‘DDä#Zøµrr×ÅF>Å—œûŸ_ÛHîZóÈ•u@ñp¾ xkG ì;'ÖX vyaì‡Á#‹‚µ]æº#TFFF088ˆlذÈf³Ø±c®ºê*Üÿýó×Z‚ ‚ ‚ ‚ ‚ bQ¢ªLH +£S€û§€õ$ð÷7XsÌ-Ø{`/ ¤pï½÷âeóeÈ’Œ<þDÞÁ)£§k€óï?[¾´ñ[âx:ò4Ž}øXœtÿ‹€í’ÌDù|•’KC¥ë:¦:¿=ýÏðü}üãUWắ^Ïð`Û6Ü .dIƶmÛpï™÷â s>ø ®»î:lÛ¶ ¯¹ñkø¿øV~ÑŸ­HCˆ"pèýž9ñDŒŒŒ ¯¯Ÿÿüfüe6‹gž‰×^ mô,ëœF‡˜šöî= ]]]MÓJ¥ýðxÇ‘÷®éŸE|áš/àžëÿš¶·|õŒµÀÊï®ÄÞ½S˜š²±qãF¸7ý ÿö9Þ±ï€rö#~ášïÜó^ye“}äy€¥»H¥D¸Ëù!ºx ¼3¯BJZ ÓÌ•aÉ 2:ùjÀŒ‚Ö}ðöŸéc»á=÷6|Î~'¼îHœxÛx½óz ž8_œ½€ò@:Ân.ðŸ.Ëw¦ø¬‡—÷Oãù³ç”¤«„º#Tvî܉þþ~ô÷÷£££ÐÝÝmÛ¶¡³³### m AAAAAáÀ4Mèº^ò2M®ëB×õV7‘hc öW–™âºÕ£T>¾õ0>ó™á>üÝÚ¿cõz\à—¿û%Nøpï÷bê‚),?{9VZ…={öàoßð·8að<üðÃxÛÛÞ†{î¹ø“©8òÑ* X$DNXñ<cÛ6èzCç~Gg³øæ7¿‰K.¹]]]ø×ýWȲ QñÊ+¯À²,†+¯¼Ùl’$ᵯýž¼ômøm?ÇñÓØ=zÎ9x׫¯`éí¦¦¦011Á”¥dG_ù—èèèðÓ Àš5kJ¥Éd ª*DQÄŸóßxê΀‘[13žÁ>pűêð§.t=ŽgŸ½ ¯¾º ¢èA9x#¢gÿ _ÿú‹°ß¿‘ÐÓ\qÅ|bàxË9Â4¯~u?–.ý.\0Žì&±"҃׾ü]@aÁ$ªÊ¾GÏópàÀhLàÅ¿„ãÎ{?sWž„Û&ÎÇ)çL@íÝxçôoð»ßý%DH¥€Ø~üÇßü/^/ŸØ÷qE8ËeßÓâp¾Ó‹GYÞÐß`Ý‚ÊäädÅe\`!‚ ‚ ‚ ‚ ¢ý°, ¶mÃqœ‚—ëºp]†aÌý Q.ž¨j.e•’KûÄ1Y”„ëÖràÅ'÷A,<ù‡U8ú¡£™8áÇ>xø+cý×20:1Šûι‡Î:„%–àNþ(Š‚ßóïxqopÜüØÍ~Нx<Ž=ý{pÝõ×Á²,\rÉ%¸ì²Ë I~ýÓŸbÉo‹Ÿ½þõÐgŸ}6n¿ývwï½°mÛqàºK.ÁÁO„çyˆÅbH&“ð<®ëâЪC8_;Š¢@QH’Ã0°ï»ßÅ3缂ן>„N¸Z;Œ¥K?Š»n~ÎÔkal~¿úÕ½ø«¿º «W? Ç1¼Âà ߿ »¦'pæc7àšk`éÒÂóüô;Y|èC?Äèh]]ýøøÇûpÞÈ.¤_¾ ¿øÍ?cùòMxôgÿ›bçàÓǃ_ýêF¸n®_áÑÏCðËéáÚñpßwâwÞE^V ÿú¸ç¾8OÀï^Yƒuë&gúYÕEÝñ.Ñh;vìÀ†  Ñ#›Í¢¯¯o¾í† ‚ ‚ ‚ ‚ ˆ‘L&+’Ÿžžnuóˆ6¦¸îx2 ƒ¢bÈ9A弇_ÅVLbì ï…ówGgçVr€§^~ /¿ýeœqÇxãùodàŒÏÀIß; ¯üã+øå/~‰·Œ½§l=ßýÒwqÿÊNL-[†}êC8÷ãçÂük¶mã³—~—]qþöoÿK—.Å#<I’pñ1Çà+W"vê©ÐþüÏñ¹X ™L¢("‘HàñSN{Ä÷ÛþÏwÝ8Oxî9|áøãqÏÐÞò¾÷áñµk±áÇ?ºº`n»í6<~ù嘸ã8FG·à®»ÃöMÏâöŸ¿û'á…é§áyA<}ßÿ>ÐßMÓàº.$I‚mÛð<¯]ÿZ`) äò¨)Š‚èÒ¥XúØcPUñx«…å¸`| W^y`šøù¹çbì `l; ªúv_ðùÛÑ?Ã=÷~Ë—o—ß÷:|$µê{ÿÀñ¾ƒ7ÂzìÓH¥QdbÏ×µ¯ã“O_ ìóØ Áùg—¼k<0ç<ËÂyï‹àűñ§[þw}çeX·\Œ©Þ)wu@9ü./^9ý#ˆðäÛx ¡¿Áº#TúûûF±qãF¿(½,Ë~]•z¢TÆÆÆ055UðY6›ÅÈȲÙlCO” ˆÚ)g›Ù'A„²O‚/äÛD8¡¾“  Ùgûá8b±XÉg===èêêòÓƒ9¹ÇqDZdÉD"X\E±X ¦ilK40ú¶¶ Bé犒Jq¦ó+lÝ<ùGìY·ýè*|iÛ2@N›: SSS¸÷˜{qÆÅg௼«V­ôïéÇ-¿½’$áx'N=õTxž‡¥g.Å9wœƒûÎ9ðû±cÇ(Š‚»îº 7ß|3àío»ŸZK¿Î áQ"Žã`tb—¯\™? ×ÅóG•Æ>Œ¾ç=øáÔÇÁØ“Oâá\´Šçy$ ÷¼îuþqEëÚ8nÛÛÑñ“ÿ‚rÍñxíÚû‘L&aš,O™nØ39 ¨*A€°EÛ¶qÂ'”´aõqÇá„k¯…(ŠEï[ߊ N8š¦á­O=…O=ø "o> ¶ÍÖ—$ šçáG?ú6xè¡!œÿƒà}wAþÐ!I®{çÏqùJ ²œ¿>—^y)dYöÅÚO áSÀÓA`"O2 \¯ã¸§^‚ Ø=ÑeÐ;þe@ìÕuŽx¶ ¸G¯åe<ùä“ ýÖ-¨À¶mÛpë­·úQ*›7oÆÝwßþþþš÷‘ÍfqÕUWa÷îÝþgÃÃÃØ¸q#vìØ7bxx¸¡'KÄÌ”³M€ì“ ÂÙ'A„òm "œPßIá…ìsaÃ_ƒ/>ÈkóQU  ¥Ðøø8<σað<Ï_&I¦§§‘L&‘H$àær:ñ´b£££Èd20M³`ßÄüFß–ëiªZºÌ0XÚ¯»îz å­Ld¹à¸)ˆKñ€ œxá‰XâÝ«œ.—ä‚­\ÁÅѯ;¦iâÑbåÊ•0 G儎ÿþïÿÆ•W^‰x—_~9FGG±ñ]ïÂß?ôÖ­[‡Ïþó$ Š¢`Õ¡C~8(ŠH§ÓLõ°óŸÿW|ò“ЂQ^ŽƒÇÊ*(ŠMÓ|›yËG? Q}Ñᱎ_e’$‰¥ä¸ëŸÇîǟ÷¾5 UU}›µ, ÿ¶vm>ÔÇq€DÏ;׿ø"àå,L#Ëì•c׫¯"žûÿÈ_ü;î¾¢ˆò¹¡¿ÅY—¸ïíí-HùU/[·n-ùlppÛ·oG4ÅØØ6n܈h4Šîî4A•)g›Ù'A„²O‚/äÛD8¡¾“  ÙgL°B×A2xàG…°°Aa1°]@q@‡6¨ì”Y¿ø8RnàuT v¯(þLsÿTLÓ`P0Sž×‘Ð4 ›½¯( LÓD2™ô×’$AÊÍÂ'æŸ0ú¶–Åtƒr*]]ðØc¿Ç÷¾÷$Þ±¤íy笽ÊqWã¨SV²ß½ @Î~älìÇ#8þ[…u5lÛÆÒ3—bM×ôJ½‚ i'ñ_Û·C°,\tÑEøÖ·¾…gŸ}ùÈG¯»}<‚ß:ÄRjåXuè I~¡zE’€HH&qÁÞ½€,£+hCŽƒß¼æ5%ç¦( Aðí`Í^~™í/wLÛ¶‘L&aYÔø|ë[“øþðjô÷ïïíEö†`„ŸT Ðu¼ëæ›qäW°ú0«= cÂEÎ>‹á6 gŸ9ÍŲØ+wn¶ƒú®=ù°ÿý]ô­oáùw¿'Ýx#SÄ g­Yí‹_ôï#Š¢†¬-j³¦±c0 'àdœ¼ìd8ŽáZÆžÄ=ÿð6\tÑOñï-xÏ4ô·8«•‘‘‘ÃÆàà`Ù0Ír ¢··· ÞÊÈÈ:;;F䛑‘‘†ž0A•)g›Ù'A„²O‚/äÛD8¡¾“  Ùç ¨`ÂFð…Àÿ\ì.Om'•Ù‡Ø.9Ãqªˆ)LÍd2/µLèOKÄ 8»® Çq°dÉÿ4.^Ÿhaõme™E©×P€§Ÿ~÷wŸÃ£Þ‰UgüúðSp½ðN¸â&ä^çJ&qÌ=÷àƒƒ,ZçFLÓ?†ˆX‘$ ÿñQP¼FUsß ?¯"!fãÆ8‰øï-ËÂ\{m~ÝÑQyÅÐs©þøq )À² yÞhš†~ì£þ5Rïÿ[ñŽw|;wnÄÊç/ÄÖ-¨ŒaÓ¦MŸuwwcddW]uUMÛïܹ³ä&;66V¢hvvvΘ“oïÞ½%í!ˆf±iÓ&ÜqÇ­nFC¨d›|ÙlìóŽ;îÀàà`«OX„ð¾jÿþý­nJÃΧ‘ö¹ÿ~lÚ´‰Ò'-OÄyöÙg[Ý”†@¾-ÑNoK¾-N¸o»wïÞV7¥açC¾íâ"8DȲŒééé‚Wpæ{Ø!ß¶6ßvlllNí2Í|tJ9mÿþýx啯béK[qíÊ pÚÔixîñçðí×~+ÎYáG§@:ý!1u ²§ŸÎ6e,ˉ>[¯ß UUYŠ®§MM‚€“N: e³È^|±¿ìû«Wã—/Çymº÷Äáy^¡€‘LLPöž£ixêØcD˜ŽãFiI ŠHæÖ-W­Z…ÑÑ•8pàdYÆÙ_ù þwj güêWþ:ÁzG<Ÿã8p]==ØuÞy@,Ã0 Äλï¾W\tQI=ÏcªJ: ¯h™íy ˆt’$A„|Ý$Q4 ©ÑQ¨ªšq àÅ“^¬øÛp]===ð<Ïv“$ ÿò/ÁÁA "¼oKá„úN‚/dŸíC,+HÕÅ_Åðú)‘H±X z E¯Ÿ‹Å‹Å‰Dü:*Dó ³oë8,€¡\¶*ØÀÀ]qÚiS߬½z-V}t>ø†âÜsÏe‚J@óXѽkï_‹}ûö`ƒýñx¦iBUUœ°w/;`€Ó¦¦IÂÄÄV¬XÁêŽXàº~ŸbfSó‡G™”TTU-Ýg•h®U«¡£ãÙBQ'·>8Ç뺰, ©T X\×…,Ë,ŠD– Ú#Š"^}õUýº×á+O?íG¹pÑÅq¿>Rð8?þ8$IB<‡ã8þ>¹bY"‘.ºè"H’ä 3¯¬x±®˜º®ûÇò<Û·oÇõ×__’&ó‡£ÿ€eOÎ-Bª˜º‹Ò÷õõaxxýýýJäÎ;ˆ355…;v`†wçwbrrÑh´$/¶5Ó4}á@ÙHb¡G’$?bD?u0ã*A¡‡‹§|[™¢i À§Î?ÿ|wÜqþ1ïï¸ûNÚá¹¼ ¢ª*,Ëò…Ÿ«¯¾ºâ%Ú{ÚiX}òɳ»¾¨[P€mÛ¶¡¿¿wÞy'’¹}ûö9«’زe úúú°{÷n ̘FŒ ˆæÐ®öœ\`Y¬ÐY&ÃúPÓ,žô¼üÌ‚ íjŸ±Ð!Û$ˆðBöIá…ì³½E©Tʯ¥ ŠbA±obáÐ*Ûô< Wk¼>( /¨¬Ê-äuS¸„/¨ˆ¢üÁÅO>ü1Lþ÷ãåsÏ…píµla,Æ"O*¤J‹¿§R©¼HÁEÛÆ¡e¬úŒQ'¹âò³Bñï§ž åÓ„­YsWiÝ•¢sñ<ÏO³'Ë2âñxI=’à5çë% ȲìÿÏ÷‘L&¡(ŠÿÝð¿Á´  ÷çQ-Áe¢(âSΧ¼6‰'= ˲ I’¿=TøqlÛöÛᵟjT†‡‡1<<Œ 6`ýúõèîîöC1çBqÁÍþþ~D£Qd³YtwwSH'A´ˆrÅpÛÕ>s>’IÀ¶ó}Ÿe±ešV8QÀuÙçäÿ­b1Ù'A,4È·%ˆpB}'A„²ÏÅ¢(TeßÖ0˜Öà8EÅèuàÈì~q7ž;é9¬y` Ì'#ŸêË‹\‘Ñó°çˆ#pøØc±÷Úkñöþ¸öÚüAd¹l±–Jƒó%B†¢°W EVUªµR)æ·¿í¯º/ ‰4Mƒªªe×÷<ÕUÉ¥9ã/Ïó T/I’ü69Eõhø5ã©Å&ªX–U"Vɲ ×uý6:ŽI’ Ë2 ÃðÛÃÃEÏó`\×ÅE]4çë[LM‚J?6lØ€‘‘ìØ±Ùl½½½Ø°aÜE•b¨³$ˆðÒŽö™Km € *ÏT•õ§Á~Ô²òëD˜hGû$ˆv€l“  Ù'A„²Ï…/ ä‹ÏÏ'zѵ(ŠP¥`V×u¨ªZ5…˜mÛ°m»âz¼FÀfÕ«ªZ2лXi¶mš&TŠÇ÷>Œgw= I’ðò#/ãÞƒ÷B}JÖ"/¢Hÿä Ó{NíïÇÜ´?ÞÎ Ë*_õ^×qÚÔÔ¬¢¸0ŸÌuÿ©¢Â4Z¹p 0» .ãEëEQÄÄÄD]mä‚ ·?.œ¯P(Æ ‚Ó4}›—e¹¬Xc«­“[>‚ʵ®ØÑÑõë×cÛ¶mò‹ÓoÚ´ ƒƒƒkxã‚ e±(ŽãäßkûŸ§ôâ³ ‚Ø601‘߯qH`!ˆVà8U£° ‚ ‚ ‚˜'<ÏC$)8t]G$);ÀÙ(ø@)¯×`š&zzz bù¬ô™öc†/š/‹Åbþ{Û¶KŽA4Yfa‹µº/þ2N=þTȲŒ®ºðÂÑ/ kI ‚‰'Èý傊€|ú/×Å/~ñ hšÆ.ªÙvyAÅug•Úl¾…”fSœŒ§öš Òê–AAÄâ#C’$Œ#™L"™Lb||’$!‘HÌ뱓É$2™ 2™ FGG!ILÓ¬y{×uý™öå]בN§ýóÊd2PůC4ÛÎOz-fåèJ¬}|-àЪCxþ¨çqtöhÀÀÇh‚*`U–eÁ‘$üìðÓVù$“…µL\—=x–ä« Af%ÄY³˜µ;ŸBæ\¨Ö.Y–ýë/‚/ÎðkV&I2™ŒÿyÉ÷—CUÕ‚¨–Ç{¬áç5kA%Hoo/pë­·6<AÄlá"ïÿ …â8¬Î˜a°þRUY?É£R,‹ýåý¥ë²W<ÎÖ•¤ü{¾Aóƒm]]LÄä/EFG÷'€sC«[HAA‹Çq`ÛvÙB×Éd®ëÂ0 èº]×ÑÕÕ…žžžÑÃqÄãq,Y²‘H¤`9‹ùÑ']]]%©¾‚ˆu>[–åφçE­g¢ZM b~‘$V#¾˜¥û–Ž=|,&ΟÀSÇ>dªïKE_T)[¨½8:EÙ Ü9Ñ M¯•`äF}×jþ#b*Õj)ÇL¶©ªjIÔ B)G°¨}r‘3ü3QqèС†_‡šj¨pFFFÍfÑßÏ ÚŒapp@^T!‚<%“a"ˆ¢°ÏT• &ét~p6•Ê÷žÇúKEa¹ØÂ#V¸•N³—d2_gŒ‹7T°ž 掮3›3 f£’”‹û@x€ ÈGÞoZÝR‚ ‚ ‚XÿFÀ‹J ޹óA‰D£££õ5"X_e#/j;g±ào½Çšo<Ï«ù|f:‡râ?¯Aù½%I®]»~jŽPÙºu+6mÚ„l6 Èf³¸êª«01eçÎØ²eKÃH1xmÓdp°ˆ™çåûBÇÉO:˜’Nçß—+~Æ?çý*÷ç'_ØžÒ«Äìq]f£ŽÈo”œ*Ü 'JÓ­n-AAAœ`:žT*åVUÕB±, ¢(úB†,ËP¥ Š%™LúMpàÕ²,¿ Wj|åµWø€pñ1V ›×e0 ]]]ˆÅb¡M©ÔÎð4íA<ÏÃ’%Kpâ1'ðΟ¿Gý2/ €‰*Ám"ÿß²Q)óˆ(ŠuG6ÍViÆïS’¤¦ÕšMdO¥6?ñÄ o_M*ccc¸óÎ; Rzíܹؾ};:::ÐßßY–‘ÍfÑÝÝÝð†AÔƒ$å£PŠûLEÉG›Ô’ÞUYäg¥”©Áþ„ßïãqvÜrõÌ‚(Ķó‚d*Ål*“É¥Ó³ÄÁf¹`9p`ÞÈ ™AAm…i–Έ/ŽÂÐõÂÑfI*|øuœ|:Ž¢Î¬å8E‚PUÀð<Ç|É`¨ þ ¯ëºpK–,)X')Ri`9˜Î‡‚‰X,†‰‰‰/«eYñxÜo+oK°½Š¢ÔsH$ˆÇãŸù»#F¹Ÿ™ã8Ð4 gãl@ÎøÙ8ü‡_ãÓ¿º° ÀVøDÑÿ%Ib¿ž`–ße=‚‚(ŠMq¸èXOTK³„`öbO#"nDQ¬éÞP/5 *wÞy'¢ÑhA}”‘‘¬_¿€îîntww“ BDË ¦Þ*‰¨ª,¥Öšrž—OùU ÛfÇs]¶Š &ˆ™áÏy©³!ÓpH^æ sßKTÒ°™GK\àÚVŸAAA4U-Ÿ*!ÈLµ’4£8RÓqŠPº®—ˆ@¾àû×¾ö5¿D'(Âð¨•zRuUBÅš#Txº¯  £ë:,Ë‚$I°mº®¤…â‘4±XlÎm%êÃu‹&©Æ€ýË÷C¼87Ø"çOà¤_ÞŒ¯¼Â„ù”_¶íäøb 0§Ášf µë9zê¡Ì Ã(>kÁó¼ºÄÛ¶Kê¢Ôº]9N;í4ÜÿýˆF£uï³5§ü*IFFFÐ××WðW‚ Z‰eå£PÊù˜<Å—,çS{UÃóò©ÁÊÁ?·¬|š1IbM ¿‹ ÊÓÓÄMMc6£i9§ù@Ì)Ö¹s¬êÒòVŸAAA,¸ÀH$ —]×E<‡ªª8í´Ó l=Ïók¯l˜§ßâË{zz Ó×Bñ~«aÛ6\×…¦ieÙ)ŠâWE8ŽS’l¶¼ÄÜ(§]õË£Øw‘û©ûÔ±øÝÉ¿ÃäG°›àX¿ã¹4U¾fÛµ U uJšÁl΃ÛÀl¶­'}—,˳®ÊµíÿüŸÿƒuëÖÍöR•¥¦•ÎÎNÜyçþû;w@²355…±±1tvv6´Aõ,?Óz¹Ô¨Uá÷ãJQŠÉ$[Æ'ðº-<²¥NÑŸ žÇl'8‘F’˜0™O °¨@‘]›& ÿ ¥ü"‚ ‚ ˆf’L&¡ë:zzz IA€mÛÐ4 š¦Áqˆ¢ˆD"1—r)X3%õÁë2pqc&Š#EdY.I«TnQ¡(JÉ€+¸á¢I*•‚®ë0M‚ ø»étºÕ—}ÑQ.┉SJR[ûðð@×Jœïy¬P}ŽÛžx¿ß³ïüùÏáÝrK~Á"TQ×# HÈZE±¤¦ÑL̶¸ül…«f}?5 *ëׯ‡išØºu+¢Ñ(LÓD4õ#R¦¦¦088ˆîîî‚´`A­ ¯-f­÷g~?®´¾®çg×ù¨RÓdƒÆšÆfá+ ¥#€ ñ8ˆ¤L@€´ ™"‚Í.ÒÁR|UÀþ ¯©*AAÑD’ɤ/žLp‚Š¢ˆL&Û¶ýâòA4Mƒ¢(p]·dùôôtÁº<5Xñçå¨e ¢(l£ª*TUõ£kʵ˜*MLýÊê¯àÞ7üH”C«pñýÕ«q~î÷×ÓÓƒññq|uÿ~UñóŸç¿Cž®„˜õ ‹ŽãÌ*º«Þfͦ¦”_ÝÝݸñÆ122‚-[¶ ³³Xê¯uëÖaddÛ·ooõù±ÈqÝù-Š"~ $&˜(æý3PQUæ Ô½Lm‹a°è°‘Òf/ÅàRªˆ£¾­ÏnÒ AAAs€×B‘e¹âŒrY–+ ¢(V]ÞJøy…±m‹²™¹à}‡ÞÇžuöQÇ»:ðìÒÜ{â‰~z/þ[L&“ð<ÝÏ<“Wh$)ô‚J½µMšI=…ïÙEŒ‚P· 2ÛÂ÷³¥¦èíí-û…öõõahh¨®Â.ccc˜œœDgggIDK6›õ ÛSqûêð`º®CE‚Çq ( ‰„¯ªD­T³M`aØg.EfS‘å|:°`1Ue¢Š(é4«¥¢i¬ÿ»¿» ×^»×w b&ÚÅ>ãqV³@ ±ÁÒ{9`"JÑc¢¸í¢EoKá¤úN‚hWÈ>ÛŠêXØ„Á·•¤ÒɲO<ß¼æ7ìù1÷̸úÒÕ¸we~/€nÛ6,ËB*•béBtíp3p›5hÏÇvÛÙ¤îª7 ¦umjT²Ù,vìØl6‹ŽŽ¨ªŠÞÞ^tttÔ%¦lݺ###èîîF6›E4ŶmÛÃÃÃD__vïÞô÷÷7ý¢„™X,æç|ŒÇã…ã8~q-Qý†ap]·$—$A”£šm Ç>çKP‘åòî|Š/€Í à÷r> ß²,¸®‹+þÿøçðóŸ¿>ºº®ûŽ&åc%ªÑöéº@"Ál¢À‡õÀê¤LQQsĉ ò»L´úìˆÅ ù¶NÚ¡ï$ˆv…ì³ý©·ÎÂâÛz^éØÎq#ÇáàÆƒ¬ }à™òÏþÇÀv4×ʼn7ÞãsŸK›Õ7ç6Íj„ÙÔ6Yì´âZÕ,¨lÚ´ «§222‚«®º ·Þzk]j䨨î¼óNÜ}÷Ýèèè@6›…,ËèïïGoo/±}ûvD£QŒaãÆˆF£‹v6‚ã8ð<žçÁ²,(ŠâöX^G+—C(“ÉÀ²,¦;ŸõÞÓÓC‚ 1#3Ù&€cŸªZ{m”z°m&”+ŠÆéy À¦i¹ÐgÀ¶ ض Qqüñ_ă>ˆgžyººŽCGÇm¸é¦n\~ù{ ë,^5™Lúù>¹M·Bm'ÂC»Øg"ÁDÉ‚€¬Xí,BETαëº0M³l_&€· ÀÊàúT«ˆhäÛD8i—¾“ Ú²O‚/aòmM“µ9´ìû§èyO0çÿ_p 8û¦›`_uäSNiH{DQ„ëº ?ÏbÚqüg¶uTÂLM5TFFFÍfqë­·b``·Þz+:;;1<<\×Á²Ù,úûûýböÜà&''122‚ÎÎN?Ú¥··½½½iõ5j:<„Ì0 $ †Q‘H$ü‚^Åá_‚ @UUˆ¢XÏN’$Äb±Pçß#ZO5ÛzûÌiØ í|ô?ªZ>òÅu]ض Aâñ8ÇA,ËE“90Métš¦áÖ[Dw÷ß`tTÂÒ¥gbõê·á¹çÖBEض퇤º® ÇaÛZTxeѳÐí“S±öŸ æ«`…%¤ü²mÛ¸ìééñ£2MÓ„ëö˜ &zÆb@OO¾†Q|^bC¾-A„“vé; ¢!û$ˆðvßö§'ÿ”yjȧ|vüÃêÕ~”‚ øñ™g≠/lhäB½µCæJ» +íqS“ ÑhÔ7(€EªÔËúõë100€©©)ŒŒŒ`pp½½½¾²Y¬hvvv"›ÍVÝçþýû188Øêë8g<σëºð<ñx‘HŽã “É “É ™Lbbb’$AQ¤R)¿fJ5…TQ? X³ ô,±k×®V7cÎT³M³¶Ï]»vÕ-¼ÎÇa$¼ |£0 Ãÿß¶#|]]]ÐuŽã@×u¸® ]בH$ Š"2™ Òé4DQ„çy~}#Q¡ªŽ?~zz ‹ÖC:yRH Ùlƒƒƒ8pà@«›2gæÃ>8€ÁÁÁ¦9¿®[:»OæßçH$°, š¦!‹`)ôø `Ñ(‰oæ…ÕÑQf_†D"L`Ñu`Éfs¼=DëeYxþùç[Ý”9C¾-Ñnoß– Šá¾íþýû[Ý”9Ó¾-A!ß¶6ßv¦õ‚¸nù±s='/lð¡ÏÃG¢Q?£®ëøÈõ×ã²—_^¢„ Ð4­íˆV}ÃÃÃóâÛÖœò«‘ë±pa†ÏFRKÈØòåËëªá&ÇA<‡ þÀ«ã8H&“PUÕ/¤TLqÚ“j?JEQ ( ººº`Y–¿o¢1D£QìÛ·¯ÕÍhål˜½}®^½}}}óÞnn‚PaÐvض ]סªjNlÛõ#Ãb±<σ,Ë~j>^…‹(¦iÌbÐ4® Œ±A`.¨ˆ¢I’|[nCBèìà3gÚéú5Ò>—-[ÖÔ´ ‰D‘m:`yo ‰’‚ò¦iÂ4Mâ@&“ñm$‘HøëÝ~û?@’T˜ûVA²™˜°Ô|\Äq]&ªd2LXáQ+ããL(5Mf‹Å)uùzm™ º»»ÑÛÛ‹gžy¦ÕMiäÛíù¶Õi–oKÅpßöç?ÿy«›Ò0²oK°Ak6i°ôÜ0 ?‹ _—gTáðtÙŠ¢À²¬’å òm«Ã}ÛÎÎΚŽíy€e•ÏrèÐ!6n"€¥ŽØC]à·“N§á8΂$Ú±þP³ÆeÊ¥ëëëÃ}÷Ý×ðcµDPéííÅÐЦ¦¦°qãFtww—5¬l6ëçЬĊ+ÜC'ï8ÇA*•*H R«zWËz™L¢("‰ Ò@¢Ñh[Í‚)g›ýýý³¶ÏÕ«WϸN#ð¼|„JêŒ`ºMÓ œ›JÏÛÐnê|ÓÑÑh4Š;v´º) £‘öÉ:çn›ü÷îã€Í(â5SÀÒçñÜ·†a”ô\ÌL¥Rp]–eaûöïø ¤5…‡(æ}jQR)¶ÜuY;,‹E¯h{9NÞqçλ(²(—ñq¶œL°qtww㬳Îj‹2Îb÷m‰ö|Ûpø¶Q ù¶áðm‰<Å¢ ‡gpàÏÌ|]Y–ýgcÏó‹ÅüãH$R°|¡A¾mc}[þlV®ô+¯¼’ þôõSt]÷ëL7švš°  i5aøøV3(#ïííÅêÕ«~œš•Ý»wû…éø¡Zcccë UÜÇðð0¦¦¦°yófÌ)èííE6›E4- ŸžœœlˆÁŠT³¢Õs›úZ)Š¥˜â”B48K©f›»…Ù>yV¬Fü¬]×õS}©ªê§÷:ÿüç°ÿ!Ë€g°’=¹®[²L’Ø.7ÛH ì¥ë:4Mó;j^øŒlvñ²íÓqØ«ÄæáÙ'8‘HÀu]?²²RÿÈ?gi2mŒO y|ä$*Ÿó‚Ï{¶y,+ßVMc-\HI$Ø_QrAháC¾-A„“…ÜwD»CöÙ>ðTÕÁú¾–eU}v Š)©TªÕ§@ß¶(àü uo=ôÖÒ <r^:ö³‰Õ™É^ÏÀÔ,š5vVS •ÎÎÎ’ÐæîîîY 7N˜ššòsðE£Q¿ÈÀ„šl6‹ 64åB4˲ ë:,ËÂèè(2 ˜J_¯š(Ë2¹&ÊRÉ6„Þ>§ÎšÛ~ Ã@,ƒmÛH§ÓþXÓ4¬Zu'TšÃuݲ¢f%!$™,ÌìWøº¼ãçbM»Í‚ êg¡ÚgÅ.Ê+DïðõX 1MÓül3¡ª*R©<î¡úÚ%ËL0 bL`‘e`z:Ù¢i,•™!Q‰ÅìÛD˜Y¨}'A,È>ÛEQJj~ ,AHLY´Ú·UÕ¢ìÈOL¿éì›J7H¥à‰"b±‰„=Uéw8WÚe²k³jšÈ²Üñï™h¦hÔ¡ÂC½æJ?vîÜ釋íÞ½6l@?```[¶lA__vïÞttt4õ‚Ì'º®Ãó¼’Ô@s¡^C–$‰Š\%Ìd›@¸í“›Á\Çq`šfAȲ$I…®ëèëû ^z©°Ã©&vð–™:©j3ÞyzÃ0ª:¦D{³í“§ÎÅ¢$.¬nŠ8žÏöH$L&KDÅjp{åÀ{ení•$&¨”ëžù}¥Müf¢Á,vß– ÂÊBì; b±@öY¦Éüé ™ ‹¤˜ßÊ£¬9Ž$•÷9ªª¢§§ÇGø$©rãN\Lñ<Ĕߖg bÛ6Þrè-¸îˆë*n—ÉdÇé÷U#¼Žw»Dåê§Ì'u×PÉf³ñÃ1»»»±aÆš hhhccc~XX0Ê¥¿¿ÑhÙlvÖ0aÃó<ôôô ™LB–åy1ìz~ü’$5%G±ð¨f›@x퓋г­q ë:A€eYQ)Aæ%2“ ¢ël<¼øâIËdYöóʆÏó ªj[uzDm,4ûdµ˜Hák”XDŠ ÀÜ”‹H$AN§}çg”W–¯¶sÓd¡#Ö®†ÜÕÏö=K³„|m£JäG%,6ß–  ­ï$ˆÅÙç̨jaºZNp¢w%ß5¸]-Ãg:N%x{>ù¯Ú$ÀD"áG£Od$ÂE+}[þĶmȲŒ3÷‰gž{gâÌ’íx=ÚŸ%‰š©ÒnçQ— 288ˆ;v ££ÃO¶cÇ BUU?ÇÞLT+XÔn¥eY‰D"t†MQÌLÅÄšiŸ|ÖÌLA‚ŸASïýÓ¶m8Žã+Ù•DŠj7æjBKµ}r$‰åeé†úrŸn“J¥àyž?øœH$0>>Þ6Qa²Ïjp½#“ÉÏzÀ„xúʧñûŸÿ7™7ù›Á™$emÆu™‘ó~Ô²˜Á«*&žz+ŽþçqŬÛ,ËÀÄDõutE”‘ÙåXL¾-A,$JßI‹²Ïö@–eضí *üÙµMÓ iDQD"‘XÐEè­òmËM”]ñO+pÖ;ÏÂigŸ†%Ï,)ÙF×u(ŠB¿§EN³'×TC`bÊðð0¶mÛ†ûï¿CCCÂý÷ßUU}±…ÈãyLÓD&“A&“™—/w6ª¢("#‘HPú/"´pA¥‰ûkÛlS×k›AS wüdYž14°R>FÏó*vܵ¦÷s6 ËÏW„Ûš¦!ûiÀ"ŒXû= B‘ êPÔÊ.{ä2ضí?XÕ´SMˇ’d2L…´mL½´¿ÚqЯÇ2_ˆ"ÕQ!‚ ‚ ˆ \H ¦û*ÿœ?'øC=A(WþOîù\²ï\|áÅxû²×¢µm\92â—X˜oš]§ƒ/5 *cccرcn¼ñÆ‚¼–ÐÑÑÍ›7c``À±ZÌD"¿C,óU÷ùÊã6–^¥Ói$ *RO„Ûfƒ—ºÎþçðÙï¶_g¶ðÈ”T*5c´V¥âó@e;¬UDµm6ðÔ_Êm«ª*EA:&1”-i¾‚h’À÷~ò=¨Iµ¾š@\uä 1M¬=bú„—òËr)Å`ÕkáÚ£—{Í’Tª¨ AAA,rxÚ¯D"Q³ŸJ¥àº.M$JåÒg®‡{§öŸÊžå¾WZ\è¡\IŠfD¨Ì6<Ñ~Ô$¨ŒŒŒ V ùÚ¼y3¦¦¦022Òêsj®ëÂq?'d&“ihúJÔ{Ó$ étŠ¢ “ÉÀ0 œ%Bï§Šû«\–?‚¥RnÙ™ð<Ï.©%Ò«\$J#„RîsŠ"¾ñ_çγ|›Òé4DQ„$I$†¡Ãu™\Ò-¹ÀÓ#O#‹ùÑV3F¦°§t§’¤Ó8yé>±ü[ì3=÷rrm0…‹+:€òŠÃÚV Åâ.A z&&‚ ˆ¹LûU ‚ •JA×u€:‹aÉ’%þ+‹µú´ˆP.BåÛ¯ý6{ž³œ(±‡Î‡~òt¬YÓ”±W"ü43‚¨&Aerr²¦E£Ñ¦5<ŒØ¶ UUaY’ÉdSêÔ’ª¨¢(ú‘*&*µ&ùº ’”V©Ã0`YLÓ¬ÙvA˜·™‚ÀÎ…ŸÏI'YÓvŠ¢J„Ça‘ØbÀ=÷܃T*…L-ùù\·pæQ:]qÕ OÇä#“L(1(âd"€q0ÑÄ äÚõ+ð?o£¬È"$¨ÄB£Ü¼]/üßq žË ‚ ‚¨ééiÿUU1==ígYe¹À矞ž.yö–eÙßfzzºäUÓ3Ñv»xž‡ž%=,Û`¥X฽ôôÓ8ñâ‹›R?C–ehšFµ¨CŠ$IM ªIPéìì¬ITYÌÑ)+@¯ª*2™Ì¼¥ø*¦…¼DQ„(Š”  |,•O2tð¨žaÐu Sh΄išpÇ@ka>;g×-,r<×jÇå³€",x^á@¥ @zá¡òýU±x0Îp«b Ô—à©×ÌD4˜³= ™û`"K€”ûkèÛÆ‹^áâJù(sÆ&Ê=?Åã…ÿ;N~"†ã°—eåk³AA­£x^úc7? ›(w¥ I’`Ûv[±pául›ýåã­Á"ô©T~<¶–e¡§§º®#N#“ÉÀqœ†ÜhAhÈ~ø`(²óõ<à˜cΘq;Y–}1— Z¯g$ŠÁG~í’‰é lûæ¶Â †‘Ÿ®(@&ÃÞë:Û¡$ÍlÜ9$IÂo~ó8®S_aKyÁE0x/HåÞ§$ñ©2µa‚h(žWyba°å–Åþç‘%®›Ÿ˜Œ›6  P]ÙÙ£(J[e*jV¦(NM‚  ¿¿¦ibݺueë֭úuë°sçNlß¾ëׯoúk5¶mC’$¨ªº £S8.%‘&BRøu>»T×KÇX¥|„Šã8ð<†a “É “Éø6êyÞ¬ìµøÝh›ç³fMpݙӑñšMÑJx `j^‡äÅë^ĺë (J¾=Ý ³$±©åŠÂ ¡ŽHIA°4ºO_ú4LÓD$AOOOãN0'®ˆ‡¨ÎA4ŠJ…eåÏ‚õh ƒÝ:‚¢I°ßä+’Än%<%¨iæk®YÛFòÚ-?.‡&Eš»@A1¿”Û?æ‰cð†ß¼½qœ‚Á×u¡iZSêW·#ÍŽèhͬ½T³ 0Qåî»ïöÅ“þþ~ Á¶íE)¦X–Ã0š®‚Í7T—h5¼äÅb=/?ÖZ\¬¾ÒDöX,†H$ 4-—$I ë8”’Gsƒxâ¸ë®¨4&ÕR!Z·¿“ò8ÀÞ½{!Ër¡ð´âêõ•ÔÑ™p]\ÿ‘KpÉõ— ™L"•Jùéð W›ƒ"³s²¾ÙÌ+Kí F€ÂÈž¢‹‹Á>ßk\—Ý.d™Ý2¸8cÛyá„§ åâ ?–$ú ©{‰b¡ ¢ë,z´«‹mÛF“÷‚ ‚ B Ÿ,ñ, /î~k×®e þضMc!s$™L¶Ep@+¨©†JŽŽ¬_¿¾D@Éf³^4i¿ ÀmÛP¥áª­¦B¾ˆ…GqMÑ©ª3g2MÓJEªªeÏ‚ ÔÝiT`j-l_+’Äo^÷ºãðôÓ«‹'a”YŸ¥ëk7a—X8°ˆªÂ|·¯>û*~ýÔ¯qà¤Vç 7g†ÌGA…ëúam¼?ævÁíÓ¶m躎Ñë²”E`º øÌú…›å“ Z‚벇d¤&I,e—$±÷ŠÂ¢P&¦ðº&Ám‡ÝB­›Læ×áuQ¸€ÂEÍ"Ëùm‚ûH§Ùñ¡´fЦ±ÏƒiHƒðˆ˜6›ÜGAÑ‚c>Žãàš?¹†e 5ž©C+žqKÔE»g7“º"Tª‘Íf±cÇŽVŸOSpŽã ™L6|0µ•¸® I’¨Ž ÑRøÀGóÕ°m¦iÂ4M?Ÿ$Ie…†t:Ý0A¥Ñ¤R,ÕÙÒ¥/â”S¦gL1$I¥ê#ZŠç1ß6Ø>ÿ»ç111ýîG,›Fh’`¯( Ãðm^#lN¶¢Ò•4°ª©@5ÁSoÅbL€åµPl›-ã&¼„.vv_)®‘"ŠìsÇɯﺬïTU&¤L(áQ'\@˜’L²ãñ®OÞàmQ”¼þË…”r~ˆ®³ó¡”`AAsƒO¤å8Žƒ•+Wæë\àÙ:¢U4LP©‡l6‹‘‘ŒŒŒT\–Íf[}mÊâº."‘Çi«°(QaÛvÙ4)Ä⡚m—ϧ}š¯Ußs]²,ÃqX–µ ;WA¾ýí?ÁM7­ðÏŸHC"èâ! öY>XékŽ& ¾GÅsï~×ß{=ë+-«p¤s¾H$Ë‚$IH§Ó8fëVÀ4á8¾ù ûáWÜÔó<|ýK_*44>â `?ØX¡z*_DXȾm£¨TÄÝ4Ù{™bÛìvÀ£;Òéüçét¾VŠ,³/DÏýƒ  ŠùLºÎþGºl²B:]x ’¤üC{q”Iðx–•¯ÉRŒ °ó³m¶^qš²fÁÛVI³æ?Å£€Ú•°öA}D˜i…o«ë…“T\×ÅÊO¬ÌG¨àã—Ñ*š.¨ bãÆØ±c¶nÝŠ7bjj 0<<ì/Û¸q#†‡‡[}}J°r5í$¦LPñ<Ï&Õl˜ûä³U!?;µÒŒÐrpA…×k˜Îµ™¶ 8唕þ°©Ô.BÛ›VÛg5 ºC€ Ü5€Žðpâ½÷2CžïˆN>"HûuÂÞ½Ø÷™Ïà¹ÇÇ%×_ãñ‹Ò4€†¸.ÇÁKý×øñÇ>Æ>7M–¦Œç pÜqOã±ÇcodÔ]Xø¾í\á‘%ºž¯ÆSr!Å4Ùm 8¥'ŸÈž,“aûˆÅò· ùòì\ô~Î…Iʧ ò"o'P¬¥"Šù"özQTšç1¡†°ç)Äâñü:<Цå>wÝ| ˜rÇã×’ûŽÃÎ)c‰Òm‚ßIp‚ W†Á¶ Š2Ï=×Ù¼Ð<澓 ;dŸ^ZéÛçÅþù«ÄÀž¹Š#ÿ ZMÝ5TæO vë­·¢·· Ë2†‡‡±yóf bûöíˆF£ÃÆFÑÝÝÝêëäã8R©TÛ *Q!Š"LÓ„¢(,U ÑöÌd›æÝ>‡ ðœç\L©uæ¤ã8Ð4 ’$ÍËïv¾Dš™PU6â8ìZ”›à_\/‚h/Â`ŸÕ(®-xxßøTº2€Ó¦¦æ72…{Ýñ8›‚ΉÅðÂé§ÃZ½Ü~;à  àŽM›Ð»e ý³?CÿGøùƒþæ7_¾ׯ^·ùB±ÛŸãàÑG_Àž=/âÚ‹Žö뀓fé¿n@1GÚÁ· ¶Íäym>ÐÈWöÖÏóIºž¿$yÍUQ …Qd¢…m³OŸœtQ\¼žo/¥ÂE0õ‡;/ϯÏ÷%ŠyqBÓò×Áóòµ^$‰íOÓJë½( ;gï¢xTÇóò¢M°žŒ$•Fÿôôä}^S&¡"ËùÔk™ ûË£uxJµ]»ÎÅûßÿ‡Vÿ¼æDØûN‚XÌ}Dxi¥oËýE€ïL? $Ü®Oæ:>™– ZIM‚Jµ0LNp6A%²Ù,¢Ñ¨o”°~ýzLNNbddˆF£€ÞÞ^ôööbddýýý­¾N0r3TÛ-ÕW9Eišð< <-ªÙ&€¦Ø'„á™ÌX?„Ãk#̧Ø*±‚Ïx­†,Ë~­¢ýƒ}V‚§·ñëÚÀžS÷À;ɃàâcŽÁ²÷½oþ/oD°v]\4>Ž‹«­üüçñÂ_ÿ5î8òH\±gLrB鯻îÂÞÓNËÏvâ'•ɰ¿ºŽ7ŸñvÜ|ç;àB„¹ï/‘Òî$ ‚½ˆEÇBömëÁ4 S_qóp]6@Œêà÷†‘_?΋¼þ PZÄo¯ëÌô$©P´UÕ¼™]T^뤘âT^££…Û…¾O.ÃÏ9ÉŸos2É’ññ|$ß'¾5ͼ¸ÂÅ~ øµÑ´|„ ¿î|.¢B^\â×M kÎðíød ^wÆ4YûùÄžÚ,UÔ.s3ÂÜwÄb‡ì“ ÂK+}[îkÀá_ÆÇžü x@ÄÊÏpJ3D ¨)åW6›ÅØØXÕ7ºjD£Q ù罹¦°sçNtwwcll¬DÑìììœ1'ßþýû1888ïÊó»TËDäev¥|`‹”l6‹ÁÁA8p ÕM™3óaŸÀàààŒ“%f‚Ïöр˿«¯\ øÀË/×fÄubÛ6t]‡çy,M¥¦•FÁ”]~ÕU8 ëøÔ­·"!Ë,cW®P¶K/Å¡Ï|ÆwÐ=ÏcâJ`ÄwíïŽ×¾ö_X­„gßwß}¬H=Eœ×ÅÈÈ,ËÂóÏ?ßê¦Ì™…ìÛÖJ<Î^×(ŒžH¥ò÷EɧÂò‘35ÞŸIRþä ÀlP?(tÿ¯äš· ÂNp.N”£\Pmç…’â‰Á^6Êó˜ðÂϧ@ ŠR𯮕¦±Ï%_†o—L²W:¯W51ÁÞóèIÊgÿó‘ÎüHÝm“§ó“$É7Æs" ·{UU˧ãäS±ËÀk-Åb18Žã÷sÁû‰ã8…¥,ãü/|â›Þ„­[wcõê>ÄÞó1x?~ ÚÝ,°h2¿éîîÆYgÕdÀÂöm+¡ëy±CUÙ@|"‘¦å5Rx†¼`j*IbËyÔD¥‰Õæ(ñš"ÅSv©t,™QU-½E‹×—ëJ'?{’«çÛ÷å§A ,+¾E 7Áå¶]˜Ò,Øæró&âñ82™4É_}/&\ÄÕW«ð<º®#w Núäujî»ïìÝ»À3Xè´Ú·%ˆFB¾íüû¶1[È·mŒoë§|w‡Ž~ï•Þ[Ö‘T¥­'Ô¥··w^•š"TʱcÇŽõÊqÕUW¡»»¶mToooÉþ&''C3ÀÏXm÷•àÀ´$IþÌ`c¦"Ä‚§’má´OÓ4á8΢Ju•L²Ù¨Å“1Xtš¦Áu]²×6$ŒöÉ *ÃKyåæ1:Οs"~Ïó`Y,Ë‚ ¾àQ©ø`ÙJU€õwš¦ùb ߇$IH$¾˜ã#IPV®„(Š8!IÀÄ# Å…ã> \à”)sQ²P}ÛJØv¾Ž ×FÂ:)ŠÂ–¥Óùh.ðW&Ã̰R—‚(JåÛÇlž+í‹G‹ábQ¥^·„ HüÚÈryÄu]\wÝ‹eÛ­ªåÅž`ÚÓòäÃ0‹ÅàºnÁýŠ /ì3Ï3`1èºÓ4sŸyH¥D¼úê«׿ßéz+W¦ñÇ?Þ_ÿ…!aì; ‚`}Dxi•oë?êIÀ ¯ÞPqü5·úDm*bxxSSSX¿~}Á¬þîînD£Q¿ÈQ4õë²lذ¡Õ×xE±í•rçmYE©´9Õl³YöYkz¶. ’É$âñø¢ú}Êr¡ Â£… Çãq?§h»Gî,Â`Ÿåp6˜ €L0G*û©Ã0 Š"’×d…ÑWY–g]ó+ÍÅÅÙd2‰D"×u!Š¢ÿ—GÄ ‚Û¶ýãÞtÓð«%k1¾4 "—„Ü‹h{²o[ ^ä]òÑ’TØW'“lY2ÉîÉdù¨“J"H#E“jû«ÓdÇ/'Žð\‚Oy‚Nø"€5s¿ -$¬}'AdŸfZéÛrðٞŵG^[vÇqÚ¶~.±°hª ’Íf‘Íf±iÓ¦‚Ï7oÞŒ `Ë–-èëëÃîÝ»100€ŽŽŽ†¶!«?­mÛþÃÈb +“$ ®ëR~Â6g&Û0ïöYÏØ?Ok¥(JÅëíŒeåóÓ_|°—øRê¯ö öYŒŸZ'&8€{Û/‹!•JÕµ/>Ø8[Š·å)qt]G"‘€(Š0M²,C’$ضžžȲŒßýîßpòò?Çüf9ø5Ñr/¢í ƒo[®Ë™ÒmÉ2 ,«PàÎ_P”üûJnb2™¯2Ÿ( C*E½Ôƒeå¢b ö¹,wÜñ2€cüZNš¦ÁóÓÞ¶m†QÖ®‰ö¤™›‘0žËbó´ƒ?Þv9v:„mÿñð¬÷éy\×­˜Ú«¼¦ŸáÍë ɲìbv]· ½N-(Šâ4ò™ã|`“J¦Ói¸.ðöÓöÀ³ârµc€¢T͵Íjë/2fÃÓdÂÇè(ó‘ ÖÏð2DÜgæ…ßËQÉ´ÊcŸ$©lÍÒâñ8TU…,Ë©³¸PaY¼Žóz,_þ2‰ëašfàÀu‡}ûöaß¾÷#‰ø÷Ã00:: ×u‘H$ TUõ#@EA$ªªÐuš¦ù,ÓÄ|P“ ÂellÌÿŒ+’ Ëb[õ*†aø¹ˆF0ØCË·À”]b[ǘ±X’m…Üzs¸©”.%˜^`1Õª šjµIÇq0P_ãoÒ4óƒbœâA®d2‰žž¿þA4 Þ—ú}•gâÎ=ËÏ8cÖ}¥eY°m{Ö`2™ôg»®ë§Ãáýš H&“p§ìà"O×SÍ^øLo˲J"ãDˆþŸµøÉOþ?üáßàü÷ž‚ÎOt²ë³ønQDái4=°¦Rì3^ÓSUYßÂûd.NMR+‹•L_–KkÌ7¼Æ¯WbÛ6,Ëò£C,ËòWI’üÈ’‰‰ú ~üãýX¹ÒökðÔ\¯ý¾ÿý ººD¼ôÒj¨ªêGÇY‹*á÷>‹§ì˜Ð!Eñ‹ÈsYQ?X"‘¨;â¯ÞÉ%l}½ìv'œp^óšs›÷¥A±¨±í|ÊÕuG¬Vþ¶dVŽ 4a” 5 *ýýýèïïou[çŒe±™e<7ôLðA™ñññúdàûç‚Gø¬U€ ¹ÜóXa_@ L\‰€ ÆX¹ý™¹ÿÅÜ1øþx:†`\%p|ä¶™ªªúâA4Iª=ç¹W)×È"C §x”J$ æægKˆÅb¡@„âð¶²,·}Ñ8$)çÛšÎððê®]Ø:5…Ñ¡¡º÷•H$ü´6s4ã3¹ù€dpÀ’/ãµ ,ËB"‘@:öU-Ë‚®ëÈd2%¢ŠmÛþŒqþ,÷ é4pÍ5}x÷»_ÅÐÐpUêl²„Ö·D á¾/wã\— (ŠÂDÏcâ _Ž`´J=Ç/Mßó<ôôô N£·÷XÜ~» Û>ä§äãé¶xZ-MÓ|_6™LB×u?(IW¯¾·ßÞ‹ßÿ~£ïÿ÷ôô “ÉÀ4MxÞ½øîw?†sÏ}<²Ümƒ¢ ‹ü˜ðÛŒºã÷ž‚«ø>Â#py„K3(wUµpòÉíBAD8p6®á8–` p¹\âDÆb1?Å9A´š¦ÖPi%ž—ŸYW)]A1U‹Üº`ƒ$\İ‘*‰ƒ‰%|ö®…ü€Š“[¦ä–Çrï“`‚ À"O¸¸Â/äö“ÉýZø X'·–Û/rŸ)¹uç€,˰,ËOU@Å®‰F`ÛõE¦ÌfÆf;"ŠL æHKÕâ8ìeÛLpáƒÈ<Ý?o;O9âyž}v ®½ö‚VŸ±@Ðõ\Tráˆ"”ÓN«yð§³Ø@ž ˆÅbõO^¨€ªª~š€9ÞS•×N)‹&ˆ8`.¸`Â#I¸­+¹÷AHBa*~(@L< ¶U-ZW(ú\ì#¸_@O™ýÕI*•‚išiTb.Bå4!ÅðT$¨”F¨pøý-a˹³Ás»ót'<Å ÀŸ‰ ðÃÆ!Šâ¬êW‹ ÏË Âê2>4ø 2_üâŒÛq¡‚§Çáio4<n°ïN¥Rƒ†š¦A×uÿ·Î£´¸É‹Kót—|ð–G¼ð} DùÕk®™Ä_õ¿/%º!Š"nýß[ñ/ŸýûÙc›ÿe‹.”F>ú“ ðAÿ—§âjFà±ëÎn;Çq‹Å011Çq`šfXÇ‘N§}ñSŒû6*I’o·|@²\ÊÐ`ê×N?ýh|ä#ו´GE$‰œ;¿×®¹ÁA¨X£åœsÅÉ'?ïm ˆ…FÐà~ ¿ÇðɆaøÑf‚ øIDQôSh;ŽÃ0|8™L¶mxžçû!üI<òÎ4M<ÿüó­¾ Aó†çy8ú¤£q*N-øœ×Ÿ#ˆ°P³ ²uëVÜyçéÑhÛ¶mÃðð0vî܉íÛ··ú|*âºl°QXJƒjÏ)\4H&“P4ÚË#PøJ2÷¿øŒG–§ßª1·}µqãz&ª¸¹ýÙ¹WªÎí¨ª +85ž æ€ TN-RŒmÛÈd24K ÕÓ®S\— ¬™&pþùc‰Øœ€IDAT§À²L$“Iv/¯7ñê«ï¼úêy°¬ÿ€¢(0 ®ë⥗VcëÖÛüA#¾?>öÄî¼Üqé{Y¸€;ÊþBLË„,Ë5…]Çãq¿s°`20¿¿Ÿ`Û¸ BŠEÄT*]×á8’ɤ?‹Ûu]&;ráý!/(N§±bÅ+8Ip!ìg3ãŸ:ù)<û¹gñÜ;žÃyï:ož¿ b±cšù‰ ºÎD]/üg3kK;¥>A…GNº®ë‹¯º®û>¯}ÀO«¥( zzzJ".ø3K=3=½ÊÝ’x{~¿âÑ óA³f_Ò)b±â8<Ï+HÊë)Ù¶íÛ K¸ â8ŽßÿsÁ$èS(Šâ‹"|⟔Á· À===eñxÜ¿ïñt¤|Ÿ×~rï|ç;[}ù‚ ŽœËðõ/ÿ'zRÉrUU):…5 *cccÆ­·ÞŠÞÞÞ‚eÝÝÝ@gg'>ýéOãÖ[omõ9U¤Ö™d–e!NCD–Z‹GƒÄre”F—4L´iT­¥à~<äk³H`‚A´ÓdgµžÎƒÏ'fFQØÌc.$ïÞý>xÞ5ºmÛÎ ŸÀÁ»Þu®¸"é§H9ásŸ{×\s>8‰]»®Æ+¯¬ÀÞ½_„ëž Ód‚ ‡$IÙ²HðîÄ•LÀÓ<£r$g‡ýPü×a¨Å5Ó ¢¢(¾Ã¬yÀ·K&“~DJ°þK"‘`bÌ~ [ á?3ø”ñ—xiø%X¦E‚ 1¯xäw]VÓDz€D‚½—庞¶]{ ܹà×\*ƒëºˆÇã~ßÎmЧ¨ä"¥ã8~m£JÒ¢(6$Ÿv5A…‡ ¢²( ‚ Â0ø‹ ›0 À¯›æ8Ž?ÑuÝ,Eét¦iDÒòH6žþ³xbÀ"\yÔ ÷‹gzvI¥R¹hñDYšGÆñ4¥¢(â‘Giõ¥&‚h8¶Í&­~z5ºÑ»Î¥^6M“²•¡¢&AåÎ;ïD4-S‚lÞ¼¦ibll¬êz­Â0ò³ÈªådïÉ⢙{(S$· 0wÒ¥€» På\­ywžŠmŽÎ}eѯåb‚¥lá'5¦ æ¥æ9¬ b68ÎÌ*º®¤ã!fFØ@Z&Ãþ¿ì²×BUU{/˲ŸŽÀ4 .Ø‹‹/ÞQûlh[·Î8XÀLRÎÛrí æ1—e‘H¤DL’e9WoÁÃw âG¤pÞ÷ÆG®9W\r>õÚOἯ Q‰h?l›ù¸¶2 vßÅ€ééüºì~ßœvyž‡D"Q¡( ,ËòëɲìÛ/ìÎg„ó7µØK£IªîÛó(˜âš4AÌžçÁ¶m_Pà5x´_&I’IÂݸªªªÿ Sý•£ÒsOåUiO«[ë$0>Q£R{‚é{y­§¾¾¾–}AóEîÖŽÇŸ{± b,Ä:•rcŽ4“³.Jßßß©©©‚Ϻ»»199Ùês*Áq gÀWJ=pë§nÅ+ÿý ÞóÚ÷0Á§óï¯á=€åå‚UblŸ¦É„ËʧOpÝü­¦±Ïx A`Ë=/ÿ°ëºìóßl>Òx”V_%ÃÎÑ/jŸžaóÜC0¯5ÃS.D½äúÇŠð¨F«^,ðkÚÓLLßùÎ1H$R°,$bõêKašT°í°,v¿²m6H亀¦‹Ï~ö6ðè£ÀI'øÀ içcåÊÞøÆ$ÞñŽ¥¸å–èí=„#Žø ®¼òJ|ík¿Ç=÷œ¯~õ°,Ó4{ê©-øÒ—–ùĆaP¶€ð<ÀÈäR¾‰À«_vÆH^º„r‘9¢ð¼¼O äûyÈâhQ¬92[xnëàŒpÛ¶ý럲x^~¶4W>ƒøí¬ûâ:Ü{ñ½¸õ'@X ˜±¼X"Š…ûà$“lÿ÷u°ÖD.ê­jJ‚šà÷"îóEÀ"XlT­ßÂsÅòÐiNM3ЉzI$ª×3â‘PDýp—ÃS¾°Yµ"®¼òËÐuv_‘åüýÊqòEü^&Iùb©Ô…ؾ}âñ¸n¢Qओ®Æw±k׋°í$.¿üq|ô£/bõjûömÅ׿î`zú1XÖ#þLeÇqðÔS‡!I*î¾{ ®¼ò8¬Yó¬/ þ$ZO$¨çÙw³öœq›Åøò”@¯ýëqÛm·áÒKUÜ}³‹ïܳ —ýz.¼ñBÜóW÷`ê‡SøÜ]Ÿƒªª‹î%‘`÷iQd>e°ÛL§Ëû½@c#,x!^ã„× àE›y="]×˦ʙ+dCnìÀƒqP,àg=àµH‰dYF*•ªÙ¶%Iš—{K½LCDñIJ…í»PI$òõ" ‚hüvñ¯.f“½B„‘š•õë×cpp;wîÄúõëË®cš&:::F[}N%èzåA[^ŸAr%x«T(õa˜f~ðQ–ùLíÊ;’ImâZ€ ‡—£bd9/€} â‰÷–ÅÖ N®ÉdØ`§ äÅ×ebKß“8õ¼:0…Ã'Ûê`‚‹„²âŠçyP¢("Ãó<¤R)ü&j†ÿ¦+aš¦ÿ»"꧸p}2ÉîŠÂî‰ÀhZ^Ðò¢p*U8óV–ó®([¶<…OZ‚a0¡˜ Êl>ˆö…/¸¸úêñÒK.€·AÞ†G¹ª:õë÷`ïÞÿ@&“ħ?}4LÓÅÒ¥»ñõ¯ßîîgpÖY_ÂîÝgbß>ÿõ_?ÅG?úèºNÏ-Äq€Ìâü½ƒ7­^SkØv1æºgœqžxâ ¨ªŠÿæoðŸŸx+}ô1hš†Û~v~ÿÿý®¼1+†ÑÑQªEÌ ™’JUöUù¤ ¼ðç\°m¦iúémTU…¦ipǯ3‹Åü^²,ÏXs) Ô2VIã™QLLÓô}5^§„ ­ó5MóÓû$ˆÎ]Ÿæáºù±ºìÑ\, Po<êl 2P«Î0 "BGM‚Jww76oÞŒ-[¶`óæÍèïï÷#TxÁúááalß¾½ÕçS( ŽSÌ•eø©v>üOxÓ›ÿX¶@vE1Å0 G"ãq6²(I% B…Ácžï+·°ÒŒÞ¦d’­Ãg•G"¬üÁÎq˜cšì³YéI0¡Å«¯â"Í‚¼S—N§ýô £££~ápš5CÔÂLâŸmÛ-O,X¹Ð(¾t<Å`,–VøíŠ1æ‘qÅb Pxÿú×½Ðÿ_Ù€y,+8W×\ó$IÊÝknèÄÇ>ö'¸ë®¨ê_û‘1_ûÚ¼éMoë&ðž÷<Žûî‹cÅŠnœvÚjlÝú¬Zeû©cxÚ‡%KzðùÏžÇREðTK‘HÄwJÓ²‰º‰Çq€˜/ºš©¡ƒ±,kQÎ(RUÕŸW^>'ÿ÷0ÞuóͰ% «V­Bæü †aùéË‘H$ümË¥@"ˆJðAŸ`º¯b*uc³,â÷aþEÑÿLUU_8ÉcáHÕb~|BA,FxßfFA=“ ýóIQ\@)ׯ5ëþÀ'5–$wÝÂôÛAš×£â¶Î3D£¸ÙõÈ?×÷Ï÷]|¯ð¼|ä7ŸØÄïãܵâéÄy]CÇ¡¨‰fHä'ÂÑ|ÇÁù<Ÿ½ ¤¢g#"ŒÔ\Ce``0M;vì(XÖÝÝ¡¡¡PF§×OòžlÛö6¼õ­ïŃg|«ÂNZYœØ`Þ÷’È>Q\ž?N.'سkÖà„O~@¡3Å'úÅãl·é4;ܲe‡à8Çâ·¿}§œ2^äˆ&¬,b%¸(P˜W’$d2¿Ð¨iš F3R­ +¨i•˜ÁÏk|èºîϪÕYx‡_”Òó¼•ò.“aÑ&ÁÁ7~O,w¿ä¤Rìv„ 2ù÷JÁuøüçχë¦!Š—§n¼׸€ùgA“ÖÀqüõ¶¿†ú*†Ô!üÈA¬Y³7Ÿwó¢¾nDýx»¿Æb•ׄòikk… Ú¼ 8uÇŸ\‹ÅÊöÙ¼~ÊB‚žÙ‰ÅŽçy¾ÎSùñg?qÆýß™ê²zIù @>„(æE þ¸Œf“vòëòhiÏË§ÜæÛqñûªŽÃî{ü=O{ËÅž"‘OÙ$EUÍOVÅ| i²ÉJ<›?F:?†ª²{1\ù±t=?HoÛìžÍEžþ;•Ê¿çÏ÷¦™÷ÏGGÙ`¿eo}ëÚVÿDÚþûäuÇX×E ÓÄÕÀÔ§0±r]èò§%ˆ°QWQúÍ›7cóæÍñ?ëììDoooÝžššÂäädI-–l6‹l6‹îîî’e³XÂë8pðླྀùæÐSe'ñxé(£ ”æ„Ò^|äÐó˜Ø’N6HÓÃÀ×^ŠÝÝHŸó2 äQFGqà _À£ÿôO8ᢋȥVà‘ ‚ à+W]…K¢çáé—^‚ç©°,¢(âß0Œbݺpê©{ð±—]v_Á¬ÿšB­=°H•€&Ã׊+Š¢ §§ÇOû@7½…I%ÛkŸÕÒ˜¦ÙÔôqü¡×l‰ÇãÈd2Èd2ð<Édñx²,û¿m.¬ð|ϦÉ™c±˜Ÿò$̃¢ªZø ç#ßÊÁµá`ä záy¹È„…îæßóýsQ§8Ýu:ÍÚ’J¥ Inºi9E,È-Ë2Lxì±\xáµØ»w=b±TU…ªªð<`Ïž=øÁ†qÓM7µúR7”fÙgÿ¡R×ÉEÕ65{±÷ÁÙT¢¸çÁ0@ï~uõé¿Â]Wß…³—Ÿ—^| W?w5®øÅ÷•VGêµÓ,ß–cšlà/™¬™ÍÀçy°mÛŸ\ I’_H€?y¦Z!fMÓüßóB!eˆÓоs¡à8Ž?aŶm¿ÎŸ4$Š"R©îºëU€$Ve®ëùÿm;/³%]gŸç£2æëe2ìyœ lÿyQ“‹'ñ8»Ïñ‰ƒ@ÞŸäQ×< %˜Ê–‹µÂ릦R¥Ï(ªš6)^ôsÇÇÙñc±ü~‚bŒ¦Öf n¬Å—ëzþžÄÅ¥—^:®Å¿šÆû4 öýðï̲fîW b1Ð,ßÖ²€Ôù@öÇÄ'& –ñ±‚u *œFD¢ð‚æþgÃÃÃD__vïÞô÷÷Ïé8¼ÎHËb¯îî;qå•O³+ù$¬W-?Š83Áb|p5ÿkå<7>€,ww#Ø\×ó`­\ mß>ĉÜ`¡‡]7Ü€·üìgÈ>û,®9é$ܳt)žEÄb1|ò¢‹°Ñ¶¡%“Ð7ܰ wÞéâƒ<_ÿú:|ï{Šýû·aíÚƒ,³F’$UÀVÁŠBåfÙø7³¢âõÜáñxÉdrQæÎ_蔳M ñöiÛ•gÌò4róa¾8¯¢(̶ã³qÇ)(°]…ÅN¾­išÐu½à¡Ô¶íPDoÉ2{Ð 6%.œXn›™ü˜âÁ4~«+w»TÕò‚OwÀï^ðMðá”Õy9¶},N8á“øýï×Uýâ̆±±X¿ÿý×[}¹J³ì3ˆa™[|°\kÆû:¯«†â°a#•bƒ?‚$Ë‘LJ¸à=xž‡gzþ¿GqäÞ#‘H$üh^—@Å´)D8h–o °{+¤›ù¶mC×u?êx¦I•RÕ'ÞD«hEßv,Ë‚ã8°, —^úeHS®¿þ |p [·ž„xœùëª ìÝ˶ãÑ’”á鲸{ôï2™¼ÿ˜J1Ÿ‚ûzü‘z¦yÁÚ¢Å.H9“¯ÞqÖ7—÷Q‹ë Î´.¤ë[Íæ^ôÕùö_úÒëêßQˆiµ}òȧào• F³|ÛdMàuŽ„—ßþrÁñmÛ¦çJ"”ÌJP™ ÃÃÃÁÎ;±yóæ‚eƒƒƒØ¾};¢Ñ(ÆÆÆ°qãFD£Ñ9)ž±XiÐw†,믰ó¼1 †ò‚Jnz#–:ŽƒÓ³Y¬øàa¦RpŽã`tt–eù¹hEa,­Jn –¤ˆ@äS‘Ì”®ÀŒ³Ä‹Ó²,û¡Žã@–e(Š˲š}Sþ WØþ™«-/£(ù™„ÅT \à³9šÆ ãñ|t¡,ç£[døò—/Æ /l`¹ìŠŠ8ÎJŒŽ¶Ç,¾fÛgL]dÍð\eƒóZ aŽÎj%~ÝÓDrù~˜×]†ôÃgû}û;ÎyÞ{Ú{ñÄ÷žÀ#§=‚?û³?ÃÛÞö6xžÇqü(ÐT*EBD³}[ÛÎÏúnä ZÃ0`š¦?‰@Ó´šû«ÅX+‰?­ì;[M0µªë·Ýv¿ûÝQxõÕWñÔSßÀÙg/ÇÁƒŸÀÙgoÃÖ­Çà5¯¹Ë—¿O?}.¹ä8ž(Á§œXüY9ß®ØçµûÂÀÊë•4âd¾uÛé: öÉÓÀ%“$¦Dfú¶®ËüÚŒ üÅ ÿJü[ ëUµåc'Q‰¦ *}}}èîîF6›-ø|dd~ôKoo/z{{122RUí|á…022R6j¦\á9€‡³ˆeö2& ”ËFР™äñxÜTu]ßøøÇ±ú„J>E)¸Yà–!ŠNÐO¯"I¬ý†AUýSaƒ¦G@—ÁqΆa°Ëžž$V¯~ _þòoð7ó&&Ò…3a|vPØ„qž Œ_;~ÄŠ¢(ÐuÝO¡ë:Çñsîjš×u‘L&ôÌÅ‘‘ìÛ·¯ÕÍh•l“Ÿçlìsß¾}+›°ÒØKp6v#q]¦iBUU˜¹ÔyóÙ9‹¢èÛxð|¸-¸®ë‹.Ížq!IOiRi0­Þ1_IÊçœæ$là0™Ìå·:QÎ:k*üMyäŽ;n7N;í´y¾šÍ¡ÑöyøðaŒŒŒÌ¦ÍÒSš8p ?ÛÜq؈HA…×W *Ë9*ÿ«ŠÄ»W±'ÞI‹Àû¿ˆŸÝñ3pË-äÛÎÒ·m&¶OÉÉçòh‘|dþþïÂë_ÿî¸ã^œ{îðÛßÚèë{)W)SâkoÛöö¦´[–ó“cJps/ìù2ø|.ä>w<`ëà68à—Hìs,ƒ‚–ªÚpØc¯•"›$ÈŸ_¥ÜËÈ­ëâR@ZHÿ”ÛVÉ-çûÕríã~ªƒÂŒ I&ûL¹þ5·\Ìm§åÞ›Òü¢ä>OæŽçåÖµrÛy&XêéÔïñøãojÊw5ß´Ê· "åS¼?‹ÄLo[›oÛ××‡ŽŽŽ‚e® H=ìwxÍáü„mÇA,«iò+ATclll^|Û¦ *Üùììì,9Á⎯³³³läàÁƒ:«á4M·ì¸…¥³Pg«¸ˆü°mÛ/Ô¬ªj~éÅçï"s‚‰X9žQäåóƒª,”z)Lól8°fÍopÙe/cïÞÏáÚkô‹Î»® 1#2ç.æüñú*˜c˜ Á/VÏáç,ö‹ÅL&áyÞ‚TžÛIP©d›Àìísß¾}ؽ{wÉCg™‰í>Žã4|¦+¯k"Š"DQliÚ­LQ2gY–ýz,ÍlW3f¸Õ“1=J·áéÆxAÒâÚ+åÒŠMNNbdd‡žÿm¶OþÐ9Ól"×”ðÓ¾ŸV;yªG„@ßœùàM^Sà‚übÏ/pÊ{NTàØØ±èOöà‰Ve5þ¿_þP¯Uý¢Á<ÿ=¿¿±C(¡Nµ”Íf166Vò@µPi¦o °ˆ=ž.g6ðHaÃ0ày,å\"‘ðýÕ¶K«ÀEN°H÷ûyx¤ >ð©“ž—¿è¹ˆþgÁõ-‹uTA‚}¿óÿ³wïqnÔõþø_J[hw™RlKY[f¡\vÅÊ,‚Ȭ¶€ =f—£ -ÚDâ>tÎAh•)Äáóæá²¡!¼Zƒõò|“Y·HÑhöã f¢ë}8/÷>ñ‰5hl\Õ«/‡,Ë8é$ëó i×ã¾ûã;'°®—7˜À“:p¹ üÕžW€…’uŸÀG‚ÀLÇx À ŽÉÔo%´M'#òâ4àøï8°6`%7¢š `OxÊ^6€9pV8Y¶ž¯ت½p‡©/xÏù¬ûßi6À»^ÐTŸU€ma ¡a ¸¹Ø©* ¾ ´s¶âµ^èô(pª0BV‚°®u¤Ì¼‹ €¿èÀ2˜¼d˜€Öø€¿ÀyÈ ðØmL{Ã5P­FD¯c«™}ÖaÝ4û½³±kñ.··>¦üªVÝVkÝj«(ùt¢¬Û–W·mjj¶T[íp ò;¹×‘uW'¥ªèëë«„ÊH‡ÝVΉpþüùÃæÛ¢Q«¢™Á©idYÆ’ÝK€X½Ar0ærˆžïbÚÀJ$ k„ªÖÔÖÅÖÓù|VeÝï¿pÚi_¢E;qà oà¶Ûnüyã’K·âW¬ Ÿ¨\VB%k µm€lÊVÃú"œ¶g‹†­+·âÌÏÄg¼ŸœY?ƹ¾Äܹs!I¼^oá}ç"]]]èîî®öfL¸±ÆçòåË öT±™Ï0 hš6öé‚D£If¢c±†ÉuW\VÑ›>¾¢¤iZ âBÓÎH¹ÉÖ <¦i¢££ÃÕ5UIÒð!÷αÜz^ézˆÅbøÿø a×®]Ø·oü~¿pçQ±ž“ˆDA2™¬ö¦L¨‰¨ÛŠÅžK­9Pø¹âñ¸½>išèíí…$IÕ›ŽÕ9ÇcÞH Ùă8¿G"¹_úÁ`v§Ù•°¯)2Pbx£èÆ/ˆ) Gjl 1„R×­º„aÎl´ªµ (¥WÊŠdE)ÝâWªÂyrÕu»3ÙâPÝÝÝÿŠ™îVéºm¥D£ÖGN×­¤I,–’Èù‘¡bš&Âá°×·Ýv‘Ý›·à9YŒü‘ X÷wëÀ a`±¼dÛ  5,­ÇÚ~Ô¼W.ÑE^àã2ɺ&ŸxÕ–˜Lܹ*¼Ù @þ"`¼ó@vÔ½a`çΈÇ㮹~¡ÚÕÙÙY2é7®I¨ê™J¥ÆÕûÇ9ÊÝIŒ)j”ÓgˆEýEA<·Gc¸®wh,fUК›G¼à׋ 5 mÀþýÁ¢E/ࡇ¾UÀáìÁ‚?ÍÀw ß=b6þ``LQa%Utؽi ’)YH8Ë< ø €vÀkzáU½€xìªÇpûí·ãûßú>Ö]½mmmøÝ‡~‡õÍëá÷ûqÏm÷@‡Žë®¸?MþÔ^L<‹A5ÔlÏ(ª¸JǧhƒÈ'F.Z4 øýxcÑ"ì™;¿Ý·»?ÿykZ/Å $u«‡œ? Ì€â@WÂúœêZ<,˜ÀYn‰S³IÂW à¥(ðGønø’½°ûDxÊægæ!HKÀVG#†˜“ALvŸß“!þµž¢Áï÷Û£¼¢Ñ¨dœê$iøggª×±*~þ fÐþ, ~ˆ…€¸n-^›“ìÌœ'Åb…cŠÝ)NU³ÓØÙ˶ýé|Ø{ÁðgÚNÆÉV¢% xðzßëø§üÎIŸƒŸ¾¾õ>„Ãa\qŸõÖ[qÔQGá†nÀ+¯¼ŸÏǵ.&ÑDÔmÅBô£!F1‰©&‰„ÝñGÔSÇt±jšÙnòÖ‹äžß‚Áá÷;ñ£Që~!?[d‡(…ÏŸ>_ñ)z¥p÷ãü×(Æ^ü(³=ªjµÆ‰ ¡÷¬5¢#ɪgLD|Ž–˜­MäEGÀ@À:/ÄbÖßùýŒD§=‘ U‘HŠ¢Øk«ŽëLDdÎ3bŠ+èÈæ&d¦DÀN¸¼Ðµ° <׋¢./ýù=vG\~ Ù¤‹3ÞÄߣUNçñEZèš_– /Äã¹ß7Îçæ1‹ï 1B̹Mb-:qÑ-º`-˜e67Wí"È5 •––ôôôäÜ6888®EÇt}¤ºPÜjø £ðbôeŠÇã$ Á`¡P^¯wÂ×e71Z(TxÕ½LÀDBµë}V§›+1w®šéE;†G4ÅÓÝ^ó+/–%ç ùkðàe_ÃŒ7¡££ÿ¹m±ÝPœ˜ Jö|¿H²kx·X|ìbÜzÞ­øÂ¼/A a&ðÎÊw :¾âa|å}_ÁÃ>Œ7×¼ y@ÆŸþ»Ù…õÿ¼ËÕåØyûNLÿútÜñÂxmþkøø¬ãéÅOã™%Ïàƒ+>ˆ#w‰ßÝü;È>mµaèÀ!ì|}§5M 2=¯Tk{^<ôEèÐqúé§Ã ›Xòµ%VE_Ìë Ø£o¦‚JÆg8œ;ƒ… ëúðÛBâtk=‡†»ð¿ƒÿóA œu'N9ü¼¶c—¤a†6ú`lP¬ù•ÏCîÚ?ö5‘ ´8À—27‰û¯–€ a`‘xÀW`õ¢ 88|Yv™À'À%k¡¬i þ,ï*ÀÙ™qå¡Pî“è}+Ë8ä…à¹í6øƒA$ <ø½ï!88h÷ÔS²(ŠbWìˆ*~þ4€ø§ßN t£uS¸-œ;äÚç$ ñxÜž’FOLÝ8zBí'Ï#(ŽÀ¥/@úþ·X_¢Ç¤,¾›ÂÀ!o‚¯êë€(†õźéµM8ôC±àƒ pëŽ[±jÕ*Üu×]¸ñÆ™P™DU·M#®ëèèè°×6‰ûŠ|ÚÛ³‹¹ˆÑ#Îz¥×k}ÀEOìüE_|¾ÒÉŒR…­Öy0¸Õœ‰ˆÏч­œ¢ÏWx0Q¡Ä©®ëƒvBÅëõBUÕœ Ùõ4aÕEJõ¸—Å'™Kr"Rá>ê²(\f$½}o$•3qpœén áå5kª½«&ÜDƧß?GèAž/#‘HØ‹\Ws]†1ɯà‰îQ†µ7wˆ³˜2DÔÿüþ0B¡TUE‡ÖžgõžÿÒ—ö¡»ûŸ±sç«8âˆÿÀ±Ç^Ž={æâ¤“ñ›ßìE08÷Ý7+Ó „a0cÆ ,ÒA"Ñ€™ßúBýoà4c‰¹€ ôÿÏBlnl„ôéùH&ß›¾?8ïl|òïÿŒ›äøâ#_Ä’»–àêË‚ØzÑæŸ†/ùüã×{°ø‘e8òÉ#1xã1x<}.<óB|~Ýçqæ¬Õxyï'ñöá3à}ÕÀK'½„û~;O}Ú±/¼ðv7îÆ{»Þ‹þ…ý˜wÚ<p͘þ?Ó1ý›Óñî÷ÞÅ[o½… fà̆3ñ¶çíjÍ Uéø,tÝà÷û‡Ç˜–@‡u1±ÜÀ;ø'¼›Þ—ß8iy¾õ ÞøîÙ¸ýºÛ1Oš‡yÒ¼Ü ³Bm5#µßˆ¹™3S'Û®–€Ç"@·8ZÊ.B© 3§²ãÁ¢‚.¶û'2 g¦¿ëõY ž0¬d âÖÔ! <|kÙ2\pé¥$ óöîÅ·ß©¯ûgÍ‚”™ÒAü$ „Ãa{Þ{Ѹ-¾ç8D~D;2 <Á ^xáøÈbcE±Ï±æÑ” A z><„€a]üàýÐ ÐõÐõLGrgƒ›£çÐÕ‡°\[ŽåXD€5?_ƒ}qÍ®Á¬ß͇<üàöóĉ£9žâBÕ™ÜÅââT–e÷Ö$•>w¥„h4 Ã0Ç‹Å&æ|H¯/‹÷tŽ0©õT–)j"â³ÃÈÎ'ú× !Ã0ìQÊ"¦E<—ìT3E:}UÚˆýC4­z#¸vF” \1u¾w&*>Eþ¿TµD ž¬ÕK)çè ; C$>Dç<‘Ñ2SùŠú›˜ÊW×uûÚR̾"FsˆDC0´Û×D¢Á9ZNÏ,,.ꃡPš¦AUU;É’H$ìçˆ÷kŒæ¯?*:Š «_:*NbjÄBíuápØÞf'¯×k'Q€Ü‘øÛ¶m+X·½üòËñÀTûðO¨JŦv#Ðñ ¢fgdý¯wßµ{H’ÄkLr=×$Tk=ŠuëÖ¡µµ}}}èêêÓ¢NbäBó^F£Ñì¼|@á„J‰À_î½™VañÅ_ó½ÅÅüÒ±Xî…¢aàõ;1cÆ ûö^ÇE´ò(öëÙgÀ¡0ŒÏ!þ^ye1wà _Ø€o{&Âá‡pè¡OàÊ+½eÀï__¼'¤áK_ú ^xACâ½{ñƒË08x8/~3gÎÂwþ çžû’ɇñ¿ÛŽÇ2%… ïÇ}ÿX‚Ï®|%çßÿþhpÀ#غõ8Ì™3ÿýß2¾øqàø¨xòÉC1ïøßàŒÿlÈ4HÍÁÅŒ'9K;¯>{~>8 g­x §y0¾q7ðåkZñùý÷~㨇j¸=°‡vv½Ò‚¯ÎÀiïÞˆ«pqµÞ„«D|67[É”üú‡¨ôÙ±…•t¬CV¯:YÆýËíQ’$a`ư¦Ž/%ó¾…*Ï¿r|/ˆdH±ÊxfÐ Ùþ8¬0È&[:`5fÊ>ë· \êƒ=ŸuÃ/~±‡ñû¡ªªµü~À4ñØ 'àì… áÏTJEÁ¢;îÀ1»vü#n{ä4­Yƒ@"aﳜÆMÑãÇ1Ô™I˜Ú4Þø ‡üÐ^4ÃÑN*˸.‘Àš¦&«‚ë¸ 5îs)k}èH’cvÎà÷aþ×hßñ#èÿ“‚÷³³ß±ñx¶Þ#‰é/3_‰â"eú§ãµË_ý}÷´‹w/Æ÷Ïÿ>üsý˜uõ,œpÓ XzÐRëI2ð—ïþo¼ñÞwæû0·}. W\|Î\}¦="é²Ë.ÃÊ•+í‘…Á`O?ý4¦OŸŽ]»v᪫®Âúõë …p衇âˆ#ŽÀ¿ýÛ¿AÓ4<þøãøøÇ?^íÝ<á*U·¬cçu’Öa3Ä(ZvOLÑs}¾×Í̹$ëó&!w$ïˆAöü)¦r®ã !wz"9ó£`øy×ÈKñûa'Ãóså‚ápØnðë$Ž+=¦&F¯Ðò)fÄf€Rm"=V&€Ë«¶[ªb¢â³ÜŽ æXb¨Bœ ‘ÔÉ Û“_LS%nSUÕ¾OŒ£+$I‚ªªðz½9Sd麎X,f_ ŠëñŽŽD"‘ܶ³ÌãEB%Ÿµžÿ]å÷û¡i𽾓³¡Üù:ÎkŠ‘:++Šb¿N¡÷/Ä9B7ßHSkÐé»xΜ9˜5kÖhwÍ©Dlšï±ê³Ú< à»ê*œ30`'®ÛÛÛíöV"·ªZBeÓ¦MÃnëìì„ÇãA*•BSSÓ˜†tšfvJŒá³Y™ˆÇãxè—YSòˆ†Ú"Äž‘Hš¦Ù'4ç—k @8FÍS”ácÎ3ó[_êóÉ$°~½µc Þ“ÚëõZsI‡Ãٞ˙«ùÓ7ýùÏm8úè>õ©Óì^,Ãßþ¶¿ÿý|D£mˆÅbes犋Žå`_Px½ÖÉÞïÿ|¾á#×-Ä×?Áyçý’$ásŸ;÷Üs0N<±/¼°š¦bÙiï`îܼùæå™¹0­íöûƒ8ûìËqÔQ· à¼ónÄõן‰/ùutý®Wþh1z?›ÆÞŒ÷÷ üáå6»ÎÃM7}?úÑIhiÙ‹û·Õêg„J¡ØÆŸá°u<‡Õ?L`¨{«O\mÞÁj( QÖž¬Àï÷#äV–*¹lƒXÿ§”±´á˜:ó;«!%³¾â°AÄ(шäàsÄRæjü}Á Þ§(Xî¢ Y¶ºU©*f=ù$²{ö„Ãa¨†%3ïÞ+<]’°ãòËíÊö¿|úÓ@8ŒæiÓðó§žÂ'¿û]Ü}àðù|Øþ·¿áÙ_ÿgžy&>ð@,{礦OÇì“N²ßß9T—*o¢âŸÆ7_ƒß¨}KþÑÜŒãóÎ º®C’$&à&˜¸ö³¿7C!H! WסߺÀQPÕìz¸úïvÁ8 êÉÀ¼y̰ó¦Öࢯa–ñ5\~ÿýøä'ß‹TêQ\÷ЗÐv—‰×žÃ{÷ÿ ß}þMüý¡¿b÷«»1wÏ\ìüÍëøô´•:pŸÜòIÿÇãxíÆ×ð“Ý?Á’-Á o¼€^x§Ý}¾rÜWðÛ‹Oð)<Ùü$v~c'þgÞÿà™=ƒ¥¯.Å–®-XyêJ:x(ö=¿¯Ú»¸¢&ªn+ ì…u>ÉL— §±ÿ®Ïß…Ÿ½ø3D~)Ÿ"!^G4è‹äŒîø¿èí.÷ł֑ÌãÄTš>d“$¾Ìcœù±Ìö›È&=$X Ѩ/Ê'’ FÞH&(™÷É 1j+îØö(¬µ$|™m V' ›¬ u;§t5a]3ˆvæ1!ØÓÄ"œy¼¨Cˆd‰x6dë*ÎdŽXk0àxñÞbý QûÕD6ùƒÌc4Çvˆ×êpÜ&ö—î¸_Ê“pæö„õÿ>úQìõìå'Ô½&ìÜY‚if:,Àªº9§yÌ'Nãñ¸}Í#IRît›"f ä~ˆºkf­t;¦F«½¨è>¨•Léè(<ç›Ó>;Ä—Zý™¬øŒÇ­¦É^l>ÃçóåL]%¦™ÿ`wz“$Éí+f³H’d×ÁÅö´[š¦å~gdˆŽ‹âzM-0}]~áØŸËb³ Œ”€…BÙ)੦LTÝVý% |ˆnðÊ+˜»q#¾è"¨™Ï(G§P-pÕã>YF£Ù k>15NãƒÖ…P‰íbŽH¯×‹ææf„B!;¹âT×kFvq¯7»bb¾@Àº/µ¿E¯`0»Št¦wU!øÀ|àKdï÷ùò×$ÌΫÇ¡ª*Î>{Iòç¼Þ'>!þgÕ˜¬a¥Çäümš¦}, £Š¢ ™”2=+¬ãÙeÅÅŸEÙjW$ þš¦áSŸòãòË/à©ö‘šcŽO ð> H>X âÂÀ»»ßÅË{^Æ…/^\ ëZÁYÓumïön=¿ŸÄ;ïoÀå3þñ‡3ÿùR<÷2pñ‰*ú»½Ú{rRŒ»!(3RC> Pß„u.²™¯Ç}?Ù‡ïžõ]Ì|g&~rÆO¬s¬èµ.ãÅH ÙĆVìø¿«q]$ú d“$â<&®qE ‚ìèN5óZ‘Ìß"iâ<·–jÌ÷—Ó(\jZÏrG_8ïë-ñ\ñÞÎN­‰¼û m_~»§è !ðþ’ãqŶ-3’5ç9ù÷gæ —Tk~{9 cï£{ÑøÃF üq ,ÀŸ†,ˇÃÙkQïŠûgí‡ sžŸƒ©`")bÔ ¦Y¿ÅÔ^…–à0MÑhÔ¾¶ …B#'CE²2‚ÜÏe¥°“ÄäËL·]tÁ“àŽ©Ù=ÞøÔõìr•ª:qk£83`OÕgš&4M³$bT‰Å!K ¦‹u’Ä÷€:Šu{Š%:ª½Ö¡HQýolÿxßÊŒ{ãeüøˆ#ð™L‘d$r;×%TÆKU ×Å<ÒÛ¶m³.&‹ÔEï±p•ªªöpÇ‘†6Öm5rß‘NêŽF\D£¹Ç¶¶ìw¡£#7k"&+Ítå 9‡‰†ÖLÏû+O; O¾ï}ÊkkͯŒäÿ-tõ²,ãºë²çWTUŶmÛÐÝÝ=¹Ç¤7þ^ ñ ¬‹vGü]ÔqTUž‡=Ï4Mþq(™yTàÍO|ï<ð¦íÙƒ>úQ<¾n–Yó Z::²côë5Ñ]añÔ“5àuêw΂lh°.Äù11ÙÝû¨<ª YUí¯‘Pxøô%¡SܦÃ+IÀ™èõyŸÀùÖ¢Q Ýp2qµ± ¸hûvôõíÂm·u ¡¡÷^úm{ÆB¬üç@;n:nøÛ·ÑõÏÏâŽ;Z¡Ý(óv@:ñDnÂÖ¹—à ç ý@ödæ.? øÃì=˜9s°Ú{ÌÝÄhŸD×±Ì×sιJî‹ß‡§ßyÞ+½VBC$#â°¾ßc™×êEá|ççD$ö÷ç7Bƒ¹+8Fxl©é1 ©äy8¿3ÃDâ€Ý°.êÅ"»ö´›Î]•™öW4†K’ÝÔ¡˜J¶Ã•’ûØh4š-]ƒH oø½‡Å4¢§°èIÜœù-$œwûyøâ_Ä·.ù–ÕË1kzgÏײsÏÀ´?Lƒ¦i9•{Ÿâdë»sFß À>êvË€ Ü‘Lâ3ç~žy¡]ö2Ï ‡Ãø¨Ï‡më×Û£Åe›Ï: ?7Mî»›&´xF†a@Ó4ÜñÄ8ïŠ+°ëñÇñ/©¦²Á¶ó7€¾÷ Džð½½P×nÁ`pXlŠ5ÄTU­ßŽu¤àé»T Ÿ×‹UÍ9gß’WúÀ—Ž·Z+4 ªa@Uà‚.¸ ó€ð-Àw5D Àrî¹]Ó0øoàvÏÔÝ9&qXßå1Xß³AÀû!@Z3ü¡†làú7®Çm±Û¬FéPîµi 䢉Ñ Uh]± ¬HHˆ$F<G È™G°:ˆùå}>ß°†-¿ßoO¿âœnE–e´··#‹Ù ™ŽŽø|>ûD¼&›]Ìk¯ëº=5±(‡ØÃ0ìéN ­[%¦## E£èˆ²mÛ¶ìh%ˆHV,*Š‚ææf 8¦xÛç÷ûñꫯVû0»žif™÷ù¬>¡õÝ[¬-TLí%ŽmÙ† Œm*/r¯rô¸Ü\ÐÂCò¨övgcíèŸ/ËV|‹EÓÅyC|ÿ*Š2ªØ-•Lqš²íN4uh€ïCÖeÙ:':(ÑhtÄ)çˆÜ¤î*#NÉée;Bïžhfd…zÌ1öÂ_<¡UPκ™+ çhEyÞ^kž­ìßÎã"&D¯oEÒ4«7¥H¬ˆ†À¶¶ì(šX,÷ÔÞž‚m¯L£¦zàÍ%MÃÖ½{Gì}ÐÖÖ†H$Å0êc ‚‰ú*ó‹×ɧmÈÎ1à­íoá«;¾Š“>9;bHôâÓºˆùåMëõÞ÷ÿ½‰ãVŸ˜Š,3_¼/ìË.‚ê“­4A  !¡$¬ÞÒbê˜Ì”0)`%·€— ÉÖ—²,ËØÙY“/ È vÍÚ…ÎØÝ¸Ûþ>eZ,B°ùE£„ï±Ç¬iN2=ŠÿòÕ¯Ví×í!@=ö à로+N±ŸÓz‰}ÌCuÎ9ÝÞHJ%ÓÜó°³C¨*ú9/&“Õ.­{Åa%»3‡Á0€È¯‡7 …ÃakÄÁÕ —Å1ïî»1¸r%^r,–+:&‰EmE"<¿!IÌÿ.’ιáEr°’bÁ]1‚B$Äýb”†)Fáóù`šfNc—ø-¡PÈžvE$_œ câ{N\ˆ¿E"¤PBYÜ&®7Ä4·âvñÛym!:{9__L“¿-âþ|âþ’ {í°¦,³û1É9ɧc=sæL)¿ÆJÌPjšÖ¥…¢½½Å{µ‡Ãa{ä‘¢(ˆD"£ë…>Ñ#T&j>$Y9uª³dà}£b1…†uY?ÖKwÓ4qÏ=Ïá·¿}CC_„/3R¾··wX¼Šêh20ÍlÇ0¬ß¢Ï§˜ÑXU­¿uÝú¿Xk^’²ß'ε— #û ;1H4šà”?C’Ï—mñù¬×Û$ËÙ÷ÕuëoÑ„"ÊXÕ¸ü×Û©ëÖýÎþ¬@ö5Ä廪fŸ‰X}jB!«‰¦XYÅò ÎÇ‹} XÇÚï·ž—HXï'Ê%ö§H~û|Öí¢YHìPÈjúQk;;:Äg!Û§·­-Û, fßùíÛ··àøãwO§¼¶¿´_Þ¯oW·€º]NêN]%Tâq«"›/fG§Œ°F‚èyíËœ-|œÎdb‰/ÉÑŽ~)Dô¤鵊½G"47[gÆü ­ø D£Ö™Y$äD¢EQ*³ýõN¶*Å‚a«Öeš€ªâéÁA(ùˆõ8ÓÚÛñúë¯cýdçíí©¤ÜŽjâ;/Óˆ²K°¤}IvñR ÛsÙŽïÓé˜9(g§uÉŸÒEEö"?ó˜ƒ=à ¯=:@v‘^-ó#ØÍ,@|ñ÷/Æ´=Ó¬Çe*ô ÿ¼èÑY’¡ÆEk€8ð™ç>ƒ9%Æ ÈŠ ¨€*©8ó}gVû(¹šù ^¶ ð.˹=gTgF0vQYxa4zÉâV‹GàìU¤åÖU|¦Åbûöíh€úûß[çKq…/®ìEËXßNQ²-"–Ås2-ï,^Œ/¿ÜNzhšEQìéJÄâºï¾ôþøÔSv¢C$6œÉŸÏ‡`0ˆ¶¶6{A^‘0‰¯×›3­•H¬°çš/§go~²Bü.ÖX-.ØG3¥èhzÅ„Mo*vû‰U„sZ¯Üõ ?^L$zµì˜ ÖÂë¤Ù:—˜âÕ‡‰]—œ&ÆD$š‰bñ½æM'èŽD´ªª9½³ÅÿSþ@ÓAoáѼ^ÜTX{{á6¡bâñ84M³ø§œòï˜?¿ Ç»ÍNVˆµzóε’œ÷Î$B4š=ýZ£^r ù}ND#¾ḦS´h~ï)> ΉH"ˆÄ®g—³u¾Ÿxm‘°†9×}r¾†ifûÕä¿¶h–ÉfIÊ6¡ˆÿgGÿXÿO$²etîq?;»|(4r³ `%?òFn¾Øç¾tQ:ý¡e"÷ôùJ&û‘L>àã£ûN1Úí÷B:ò û@Šú `]oV{Í¢rÕMBÅ>Áˆén»nAß\2÷«ñ·œ‹ ]×á÷ûsä…mɽ2ÚçnÛV¼Á^ŒáÄ;¶ºC\tQµ÷€»…_+²5CG ä{ÍÍØvË-Ö™cð÷9sàõzIENÏç²x‘;Lþ}õ•£¬^ÖÎð²w€Õ`(ÖƒÉ|/"bÝ.BÚ™4êȼ–s ð§ÕÂy·ŸÜ«¡!š¹_Î}ìÜ*îh÷“žÔ¼¯0MÓ ëzÎÚ)ííí\7…h’Lá8Dû |í·^/ÌãOCðGïCâr¡4U…ßï‡×ëÅ7>ö14ˆó¥Ï—]ÄA´¾È²u»¦e[`ën誊6¿¿ü÷ÇYg…ën¼ËæÍƒ®ë¸þű¨·‡pÔãŽÃÖ/} Þ¯~ÕJVtvâ˜L‹J86ªBM¢PC!§¬ 2f¢òƒÖå@9ý}ü~¿=jÄÏsr×<ÊL·j¯£$êYuZ%v&Y#Ñœköy½^;!¦Ü¿ý~?@NrÖ9ÕŸø; ÚÓò)Š‚`0ˆH$‚ŽŽûù"‰,¶KŒ€s®¥$¶G$”EBE$ ÃÈYILÇ'nwŽâ#äÄÈ<±î«x¾¢(ˆF£¸éí·íÅÊug~Ê!F}Œjà—aä,oí{ë>g£¾³Þyj+Ô áL´jàw¶Ê‘9_³Ði4ÿ9"©’¿ â¶r&])tÉí|^¹·ä'hœÇÂy›óöüò»,9ÅBecCõè/Á>Ùþ;ÍN&Ž©VÔMBE’€Ð2Xs2ìµLÓÄOÛŠýó¿f¬Z·‹ìg$É Z^¼M-åÔ¸ Õ„Ä”&\”¾(ýiïÍüáˆ-1ˆÓwÞ|g}â8“'щ7_sÅ’0€õ=í+𜑌0•ªj¨8øøƒ³¯).j¤ÐuV£Î›€êèì(btØ´´bî¼x5‰•p8 Ÿ¢ mÚ4lÛ¶Ín<|÷#Á<¯?¸üòœç.püÿ¤Ì”^rZx‚Á ®µ€—7ñÜsószu$ÛñU2>ÄzxÎc…•Pqt:™Lb ?±öI!Ë2Âá°}»e¦(нns-£@ €ŽŽD";ñ!¯Ãá0b±˜½þ +]b„‡×ëµGýˆt¢c–xœXì;‘HØÓz½^û¸ˆ©×âñxÁyûÅ;çô}bÄ]9S¶4ºW¬Ã$’I’$œê¦áé§ñ“o|±Ì{.]ºtò?5Bô'(G0D8.¸J¡dà‰*@ôôbD.YhýéyÇÑ)Tkê&¡Ò±ˆœà™ÚÛ¸ CÓpË»ïæt)0MÏ]w.8ä¨âvM˦ݙP!ª˜ø@>aøíápؾÑ4Íš~ëÖÑÍ%Mà„ëN°§Ë¡ëøðßÿ^íÍs¯¿ÀœCˆ Ãȩ؊ޗ\OŒhr‰yÇ3’𦉶¶6x½Þ’1©ëº½ðµX'$ Ù éÌÜbI9#A$I*ø¾¡Pˆçnš2ž{n>:;7ˆ®ìŽ©ž‚Á Nع×]qZ/¸ ô‹ ?VGÁ1Â7MÓ>‡‹©­ÅÈÑx/áp×]qnþö·Ñì÷##@Ó4;"I’=¨ªªeÙNVˆE»C¡=¢C4Š™¦‰D"I’ìNŒùk‰õÚÄuXHÜ.':{äÿ-¾—Ä÷™HJä¯_ÀN®8‰¿‹MkšŸè¨Ôÿ⻳Xìƒ^}K–,±ËõF¦ë€o¬õMX±•Y£!`ߺ}ؾ};^}õU|~îçÑõŸ]xæ÷ÏàÔø©VbS†•ÌtìÔĺõötÅD4z& ¨Ùî:ÎQâœBT+ê&¡b¼ÈßsÜH@óû¡‰ùœ _꺎Ӟ{u”•hW²Áˆ¨â”Ÿ^ùŠësn£SÄpvÀºˆaƒ ë]cbþâ1Äšžðuû¶ŽŽ»A"Û ÑÑä@œ§EÑso¤i´4M³@Å´}â\+'b¡OçÔgÍž \½õäNòXk8Ê2ð„L—xs;õõEéq¼uÝl¼}õË€Ç7l°GƒèºŽ¶_þ»~÷;ÌŸ?O<ñš;:pÉÎötWç-X€Ã/º‹öíÃ’%Kиs'^ß°Z2 UU‹Å ›&Ný—Áì;î@¸£¦× ¯×›“@‰ŽüÑâ{Å9U MLä÷4fCÙØœ|òÉÀÀ@µ7£&„^»rì& U¦™@\Ö93âçÏ~¡cdœzÜqVì.W1ïr%wzb3 h:°=s¾ô€³’›2€n¸. `?€# `ŽX¢f§ëÛfd^t‡¬õC™øöøjܺö›À{|&–Y? ֵ͕Aà…̨ÐÃdÀ«d_C…5ç÷Q`¦dý|Ø œ§Z‰Xè4 ° wbJå8¬d“VrÈDö}¥Ìö…óþ/’MFæy†ã61Ý22›°Obzñx »>”’¹]lK@{æv=ïy:²ë~Æóx"ó"šïBŸ~¼9‹Ì™9£SÚÛÛ&¤‘‡ˆF¦ýf/ôC/°gH‰N1Ï7Àõ ˆª%?? aư©ƒ ðGyŠ)Kœ–“qnåô 4•ÌØ¿8äS€”›xñ¤±ÿ™ý¸Ù3N˜qB¶QÈ6І¼9³êñ`OÛ ¨2ÓYE£Q¬>óLìmû(;ñûï·F‹š&¢Ñ(B¡•<ýú×qïÉ'CUUœ˜™~J|CŠËc2¿CÎQ3Ñ(f†½º4“£.ÅuSÊ¢œypÇ€®åœHÅZF¿Ùº‡‰Ç ÃZ1>È'LUsÿ–¤ÜÎ[¿kq—Vk:¬Æ{ À,pG&ËÐŽðŽx=ÿ¤»2۷׎•€Ï—œ*K½Àl Øeí2°;ó2€ó`YxÀ³:ðŽȪcŠ@x,<àXئD¯l%1dwGíp€^8Y¤@6Q0hƒQ À:ðž@fõy? Zßm‹`%—øBÖö']×M7€7,”Ïgw1amëCàp¿”yLȺOÏ<æºÀ”€E’•Èš&çe®Q™cù¿Q`€)øfhÌÔ|þ# ÄÜc™³G¦íPÏN¡jdv¨ ; 4èÀ’•‹›@$ød@ö¿³o<÷ÆäðkHüEÏgryëOqFª5u‘P ÿǤşÌùn ‡Ãðz½ö…d4µ‡Ñä8îѽˆxFÎm~¿>Ÿ’$Ùó®óâ&„$aÉîÝã:¥¿<ÊYÛÇãqû)¡glUŸßouó½ÃÅÂÉbоX,Æä'Ñ$™–ž x”l£¥œi¬o ò›HÑ$¦²¦ÚŠ£ð†¼ö¨Ðp8Œ€°¦¿ …쩳´ã5œ©úáL£æOo5îØçw‡û©ªÕðO¥‰öñLœ˜¦‰ö¶6¨ªšípôÑÙÇúü—3’êë%~¸$4òý—8çÁuÎm+µªºRà¡2 '¬i u¼Àò^g•˜bùLEBöûÍ”¬ˆý’¾ÌŠñ™÷‘}ÙÙ^€áÉ'Y¶Ž…š¹Ï4«ÖgÞG–à DTk;M3ûþökå§ü÷‘$àü¼c²DÊyô95w[sŽ—x›ÌûÖ¶ÈrîVªÐûP’²åQ·“ocÿ¬ý "VfCLLKFaš&*Tsê"¡bìzÞÏ.Ò Ñó¯ŠÌ'”hr öÍ„<çUûoMÓ`š¦=/s¹‹9‰¢àÁ%Kpbµ·Ã¥Œ¡éP;³#8؉ÎÞÞ^Æ&‘ ƒV—öH$b¯Í zò4õMœz1§mO$< -程!7`ÿ-jeYF[[‰“)D0–ø|`Á<|ã ‡°zðqÆö:F¬ÜUÎXâS$SÂá0TUEGG/<‰*l,± À^Üú¢‹.¶mÛ`š&{ïUØXãÓ4MûšÓëõ" BUUhš†@ `¯ (¦Ñäh2¢Ñk|ŠdÊdL]k†45 Š¢@×õ‚¿ À$I0Mìÿ˲ÌçŒã9bÿ»aÛžþyìÛ·oò‚¤JÆ›ÚßÞÍéÌ·nÝ:œxâ‰ìd@5ËU •îînlذýýýXµj<Oь缀O_3ßžáŒ3ΰ×K©¥)K’Éä¨{^¸UOOOY_¨nW/å¨”ÑÆçË/¿Œ÷¿ÿOPÕåöbº>ŸÏ®˜Ô’zù,ð{¦~6>_|ñElÚd]tÞpà øâ¿hwF¨%¢w”Çã©ö¦Œ[½|¦ëé˜TÂXê¶o¾ù&V¯^oûÛ¸÷Þ{­Å¨kpŠ žsܧžŽI%Œ%>÷íÛ‡ööv¬ZµÊžÊK–e¨ªjÇi-4ñ3í>õrL*e,ñ)’)7n´g+Ñ4 >Ÿ~¿±XÌ^»¨££^¯×n ó²,ÛÉQ1‚»½½¡PÁ`>Ÿ/§!€Ýè.I¢Ñ(B¡¢Ñ(€=RMüœÏ½õ5MìY³pÓM7 K8Ÿ#IRÎsœ¿Ýôœë¯¿×]wÝ„¾HfOdyn½õVìÙ³½½½EŸ³oß>¼þúëÕ 7–Ø<ôÍC¡íYµsü~?ÚÚÚpõÕWœ.³Ü~.©…ë«©x›–N§ÓÕÞÀú_uÕUÐ4;mÕªUèìì,zP–-[†††üýïÇ[o½…¯|å+8þøãqä‘GV»H£ÇÑÒÒ‚O¬ýÙþ»»»ÑÕÕUí͘”r<þøã¸çž{ðÙÏ~¶&;Ê5–øìîîÆOúS `Μ98öØcñõ¯½ÚE“zùLO¥ï™×_Û·oÇo~óüîw¿«öæN¨±ÄçÉ'ŸŒÙ³gãÉ'ŸÄÇ?þqœqÆ8î¸ãª]”Q{üñÇÑßß_=÷ëå{¦œcòòË/£··o¿ý6¾÷½ïU{“'ÌXë¶+W®ÄSO=…k®¹¦æê³NSéœS+Ê9&¬ÛŽŸš¦áꫯƣ>Šx<ŽçŸ¾&ÏÀÔúL׊rë¶¿úÕ¯°yóæjoî„K|^xá…xöÙg1wî\\pÁxþùçqÊ)§`çÎ8þøãk&^Y·uÖm³ÆZ·=÷ôK𷿇÷~àŸ°}ûv¬^½^xaµ‹csû¹¤¾Üï;vìÀæÍ›+^·uÍ•þþþaÙÀÆÆF¤R©¢ÏkhhÀ“O>‰óÎ;---€íÛ·cûöíÕ.Ò¨444ॗ^ž={ª½)ã¶téR$“ÉjoƤ”ãÀîÝ»1mÚ´joî„K|Î;Ó¦MÃ!‡‚5kÖ@Í~.êå3=•¾g^}õU<ñÄx÷Ýw«½©n,ñ¹páBüãÿÀ©§žŠN8»wï®ÉÏø›o¾‰†††šÜö|õò=SÎ1Ù¹s'žyæ¼ï}ï«öæN¨±Ömß|óM´µµÕd}Öi*sjE9Ç„uÛ‘ãsÚ´i8ðÀqá…â±ÇÀºmµM¥ïQ·}óÍ7«½©n,ñyÐAáÈ#ÄÒ¥KñÖ[oáˆ#Ž°Ï¡µ¯¬Ûºë¶Yc­Û¾1óy¼Õ° p,.»ì2~øá®úl¸ý\R ß nŽ÷'Ÿ|;wî¬xÝÖ5 •ÁÁÁa·•3Üêž{î©ö¦Õ½±Äçe—]†Ë.»¬Ú›NT÷ÆŸwÜqGµ7›¨îµnû‡?ü¡Ú›NT÷ÆŸçœsÎ9çœjo:QÝK|þêW¿ªöfÕ=Öm‰²ÿKTFccã°ÛJe9‰hr0>‰Ü‹ñIäNŒM"÷b|¹ã“È›DY®I¨´´´ ÄÁÁA×. D4•0>‰Ü‹ñIäNŒM"÷b|¹ã“È›DY®I¨x< Ús®õ÷÷#•JaåÊ•ÕÞ4¢)ñIä^ŒO"wbl¹ã“ȽŸDîÄØ$ÊrÍ*ÐÕÕ…uëÖ¡µµ}}}èêêBCCCµ7‹ˆÀø$r3Æ'‘;16‰Ü‹ñIä^ŒO"wblY¦¥Óétµ7Â)•J!•J¡©©‰Ãƈ\†ñIä^ŒO"wbl¹ã“ȽŸDîÄØ$raB…ˆˆˆˆˆˆˆˆˆˆˆÈm\³† ‘[1¡BDDDDDDDDDDDT*DDDDDDDDDDDD%xõÕW_]í«T*…þþ~@cccµ7§è6ŠE›R©1cÆŒ²ËQír ᥗ^õ¶¹±\…Ê2ÞcTíããFµ²OêáØŸã¿É.[©rŒtŒÜVŽZP+û¤ÖýXϥsgµÊBã×ßß™3gVìXOöç@¼ßÐÐÞóž÷Tt['£,åœ/ -[KLjƦPlµuì‹Å§Ûë¶åœ÷ÇŸÕ.UÆXâÓMÇ~<çÎñ–³ÆŸn/•6‘õ£J«t»R††† ëú„ÔkZºFÝrË-é¶¶¶ôêÕ«Ómmmé[n¹¥Ú›TЗ¿üåôÒ¥Ks~î»ï¾²Ëá†r^{íµék¯½vØíŶͭå*T–ñ#7·©¥}RǾÐgz¼ñW²ô=Sì¹±nWKû¤ÖýXΥsg5ËBãóì³Ï¦ÛÚÚ*v¬'ûspíµ×ÚïwÎ9礯¼òÊŠmëd•¥P<æ—듟üdzpp°&M¡ØL§këØ‹ÏZ¨ÛŽtÞO|º¡\4~c‰O7ûñœ;Ç[ÎJ–a´ñY å¢â&²~Ti•®cWJ__ß„Õk]Í&Tœ´¾¾¾ôÒ¥KÓÏ>ûlµ7k˜Õ«W;qަÕ,ç-·Üb7˜:ùÛ6·•«XYÆsŒjås8™jiŸÔò±/ö™oüMfÙJ}Ï;Fn*G­¨¥}R«Ç~<çÎR÷×˹³e¡ÊDÎc_+ŸégŸ}6çõÓK—.M÷õõUd['º,#Å£(—³çœsN:ÖÜ1¢±+›étíûRñéæºm±såxã³Úß;Tc‰O·ûñž;Ç[ÎñO|º¹\TÚD×*­ÒuìJqî³ÁÁÁô9眓޼ysYÛPïqP“k¨$“I466ÂãñZZZÐÒÒ‚d2YíM+¸­…†••SŽj—³µµhiiÕ¶»±\¥Ê2–cTíããFµ¶OjùØô™oüMvÙŠÅf±cä¶rÔ‚ZÛ'µzìÇzî,u½œ;ÝpŒhlº»»ÑÒÒ‚ÖÖVû¶ZúL ÈN7ÐÐЀ¦¦& Ž{['£,#Åc*•‚Çãɹ}ÅŠe•ËmLjƦPlµuì‹Å§Ûë¶ÅΕã‰Ïj—‹*c,ñé¦c?žsçxËY cO·—‹J›ÈúQ¥UºŽ])ÉdƒƒƒX»v-+þ5MÊ+JnÃTˆƒƒª½cÑßß?ì"¾±±©TªÚ›–Cœ|®ºê*$“I444 «« e•£Úå_<…æ¹+¶mCCC®+×HeÏ1*UΩ¨ÚŸÙѨõc?Ògz¼ß+“} ‹}Ï;Fn+G-¨¥}RËÇ~¬çÎR÷Wã{g"ÎåÜOîÓßß-[¶àÖ[oźuërn¯•ÏtKK :;;qå•WÂãñØIAq¡çöºíHñèñxì2V|nٲžø­¥cD£7RlŠûj娋Ï7ººn[ì¼?žøtÃ÷ÏXãÓMÇ~<çÎñ–³RÛ/^7_±øt{¹¨´‰¬UÒDÔ±+%•J¡µµ===زe ÐÙÙY‘ºs=¨É*"£è4R/Éjѵk×â©§žÂ† ÐÝÝmgäJ•ÃÍå,¶mµT®ñ#7•Ã-jiŸÔë±oü¹©lÅŽQ-•Ã-jiŸÔë±϶»©\õ\¿¡á†††°nÝ:lذ 9÷ÕÚgº¡¡Á^˜4ÿ"°ê¶[¶lÁªU«àñxìg­#*_±ØjïØŸõR·m|ÖJ¹¨°ñħێýXÏã-çdÊÏz)Y*]?ª”‰ªcWJ*•²G›¬]»MMMX³f™êqP“ •BÙe7f¹ZZZ°iÓ&;{çñx°råJ»Á¡T9Ü\ÎbÛVKåÏ1rS9Ü¢–öI½ûñÆŸ›ÊVìÕR9Ü¢–öI½ûñl»›ÊUÏõ.¢¥¥Åžcppýýýèïﯩϴè]wë­·¢«« 𦡝¯7n÷¶Vû3=44„5kÖ »»ëׯÇúõëËÞ67#b± ÔÖ±/Ÿµ^·k|º½\TÜxâÓMÇ~<çÎñ–s2ŒŸµ^.²LTý¨R&ªŽ]IMMMذa<=#AOOOÉm˜ qP“ •–––abppÐuÙ.‘ÁwrfK•ÃÍå,¶mµT®ñ#7•Ã-jiŸÔë±oü¹©lÅŽQ-•Ã-jiŸÔë±϶»©\õ\¿¡Â†††°qãFlܸ©T ›7oÆæÍ›kê3J¥ÐÔÔ”óYõxÝ^.*m¬ñé¦c?žsçxË9FŠÏZ/Y&ª~TIQÇ®Ç3läL=´™UÌ$,|?!ÚÚÚÒ÷Ýw_:N§ûúúÒmmméÁÁÁjoVŽ[n¹%}Î9çØÛ588˜>çœsÒ·ÜrKÙåpC9W¯^¾öÚk‡Ý^lÛÜZ®ü²Œ÷¹áø¸M­ì“z9ö…âs¼ñW²*G©cäÆr¸]­ì“z8öc9w–º¿^ÎÕ, ßêÕ«íc—N×ÎgzóæÍ?·Ñh´"Û:Ye)ï»ï¾œŸgŸ}¶æŽO~l¦ÓµsìKÅg-Ôm‹ÕeÇŸn(UÆhãÓ-Ç~¼çÎñ–³’û´ñY 墑Mtýh"T²Ž] ƒƒƒé¶¶¶t__Ÿýw-¶™M”š\”ººº°nÝ:´¶¶¢¯¯]]]禬&±xîªU«ÐÔÔ„¾¾>tvvÚsö•S7—³Ø¶ÕJ¹Æ{ŒÜR7©•}RÏÇ~¼ñç–²•:FµR7©•}RÏÇ~<Ûî–rÕ{ý†F§V>Ó+V¬@2™Ä9眃ÖÖV¤R)´´´Ø‹“Žw[«õ™N¥RH¥RX³fMÎík×®EWWWM#ª¼Z9ö¥â³Vë¶ãO·–‹*£ŽýxÏã-çD*ŸµZ.²Ltýh2T{ûÐÕÕe¯?#ÖѬ‡6³J˜–N§ÓÕÞˆ±ÒÔÔäêaCýýýöЦBÛYªn.g±m«¥r繩nQKû¤^ýxãÏMe+vŒj©nQKû¤^ýx¶ÝMåªçú N-}¦Åû566¢¥¥¥¢ÛêæÏt-#ª¬Z:öÅⳞ궣ٶZ.•V+Ç~<çÎñ–³šêµ\”å¦8sëöMdݹ–ÕtB…ˆˆˆˆˆˆˆˆˆˆˆh2Ôä¢ôDDDDDDDDDDDD“‰ """""""""""¢˜P!"""""""""""* """""""""""¢˜P!"""""""""""* """""""""""¢˜P!"""""""""""* """""""""""¢˜P!"""""""""""* """""""""""¢˜P!"""""""""""* """""""""""¢˜P!"""""""""""* """""""""""¢˜P!"""""""""""* """""""""""¢˜P!"""""""""""* """""""""""¢˜P!"""""""""""* """""""""""¢˜P!"""""""""""* """""""""""¢˜P!"""""""""""* """""""""""¢˜P!"""""""""""* """""""""""¢˜P!"""""""""""* """""""""""¢˜P!"""""""""""* """""""""""¢˜P!"""""""""""* """""""""""¢˜P!"""""""""""* """""""""""¢˜P!"""""""""""*aJ%T¢Ñ(4M«öfP¦iBÓ4èº^‘×3 Ñh´ÚÅ¢Q`|ÖÃ0 Æ5ãÓýSC¹±hš& Ãñ54Mñ~šXŒÕú3žs'cÕ]ŸîUÉkÏñžK›ÕÇXu¯±Æ*¯Ckãrê¨Õ¸œR •x<^wÙÞÞ^±$DµèºŽææf„ÃatttÀï÷û5 Ã@<¯vÑhŸõ% ¢­­­`\3>Ýñ85”‹áp¸`%7ÚqÞÖÖV“áZÇX­/ã=w2VÝ…ñéN•¾öϹ”±éŒUwk¬ò:´>Ôc\õ›•V«q9¥*õHÓ4˜¦YíÍ—ŽŽ$ ôööBÓ´š &¢|õŸcaÂá0z{{í¸ŽF£¬8PUMÕxh4ŠŽŽ„Ãá‚÷ƒAÄb1$ $ øý~ö°¥q›ª±:žs'c•&K=Äçd_{‹OÆ&M”©«¼%·«‡Ø$K]'Tâñ8š››1mÚ4øýþaZ‘ñž;w.‚Á ‚Á ýE«ë::::0mÚ4´µµå|q···#bîܹ˜;w.¢Ñ(‚Á æÎ‹æææœ,êh[Œxüí³ÝÅ躎¶¶6L›6 9Ïé¾bÏ)g{K•[|™€$Iضm¼^oѲëºnïñšÅzô8ïhžG§X|‹Mq¡ø¬Fl:_«ÞⳜx)Tvq,%I²˲Å}µ|.-uí9™çRÆfu°høþpã¹t¬íD¼­MS%.Å}¥>Wn˱Öqëµý¶n*@ íóùrn“e9çCâ †ûƒ‰DÒŠ¢ä<×çóÙÏuæ¡Ävþå>¶93UUGu¢ …Bi¯×;l»¯ØsÊÙÞrÊ-¾(Å Rü-¾üF*{8NK’4â1ïáóùÒ’$ÙÏ8Òóhr‹Ïb±™N§‹Æg5bS¼V=Æg9ñ2RÙÅ \üv>‡ñé.ŒÇ\c‰97ÄãHå.ö¼‘b1_¡žBκUÞDÅj:]þç°bµØ}nˆÕbe˹Ӊ±Z=õt.éó)î«åsi©kÏÉ<—26«ƒíD¹Üz.k;¯CkÓT‰Kq_©Øtk\޵Ž[¯í·u;å—®ëö0?A–eûÿ¦iæ »u>Ö0 躎iÓ¦Ù?nV”_žÑ0M3§ü …ŠÞWì9•$Ë2b±TUE(‚Ïç¶¿ •=Ø´$I9sÎ:‡ã9‡º•zM¼bñY,6Ƨ¸o²â³œxÉ/ûwÜx<ŽÞÞ^„B!lÛ¶ º®çÌÍøtÆc®±Äœ[âq¤r{ÞH±XJ¡÷b¬N,Æj.ž;Ë‹WÆê䨷øOlŠ2»õ\ZêÚs²Î¥ŒÍê`;Q.7ŸKÇÒNÄëÐÚĸÌ忏K·œçÕb\ÖmB¥ÐÂùF:b.Ó´5‚Çþ™ˆc5[ IÓ4ìß¿TÏ UU‡[¹_<ùÇ/»EA$A È™ƒ±Ôóh╊Ïb_ŒÏÉ‹O`lñ²k×.Ȳœ˪ªæ<—ñéŒÇÒÆsn‰ÇRÏ)KQ¥àëæWä©r«¥MÕsg1ŒÕÉÁø,Í çÒ‰ºödlÖ¶•æ†séXc•סµ‰qYšâ˜˜ëQ 6ã²n*²,#Ú;[×õœŒ—×ëÍùpåß§ëº3MÍÍÍ9 ÕUUsö‡¦ièèè°¿| ÝwþùçøœJI美ÇãeU$ ð›xžXÔÈžpdY¶{%”zM¼bñY,6ÅýŒÏɉO`lñ²téR†ao›xžsÛŸîÁxÌ5–˜+Õ4Öø(ö¼‘b±œýdšfÎ"…†aä,J•ÅXÍÅsgyñÊXŒÏ\n=—NÔµ'c³v°(—[Ï¥cU^‡Ö&Æe.·Æ%01×£@mÆåAÕÞ€‰âóù ë:š››í/cgåDQx½^´µµA–åœ,—,Ëhoo·Ÿ«ªª++7²,# "‰ÍêŠíûC×u;c;Ò}ÅžS)’$! ¡­­ ªªÚûÚçó•Uv¿ßY–a†}Ü ï±xñâQ=&F±ø,›ãs2ãS”a´ñræ™gâÅ_Ì9¾Š¢0>]Šñ˜k,1çæx,ö¼üF=‹^¯·¬žb¡P9e®t¥²«¹xî,?^«ñ™Ë­çÒ‰¸öϹ”±9ùØN”Ë­çÒ±Æ*¯CkÓT‰K±½¥bÓ­q)¶¿’×£…ÔJ\NË,S·t]·çÛsVNLÓ´‡™¦ UU1mÚ4 Ø3 †a@’¤²ªAlc~ùJíY–‡e÷Gº¯Øs*]Žr÷µ¦i‡ÃH$Ð4mŸG£P|–›ã³œçŒ×xãe²âš*ƒñXxŒ&æÜWb¿Ndr1V ï©zîíë2V'ã³ðþp˹4¿n8—26«ƒíD…÷‡[Î¥ùåàuèÔPïqéÜÎrbÓmq9Ù×£n˺O¨ŒÄ0 ´µµ!‹AQ„Ãa躎D"1éÛQlÁ$UUË>U‰×™Ìmg`MÆóhò¸%6ŶŒ÷³>ÙñRÉ÷›ìxa|º㱺ÛëÄóSo±ZÉ×™Ìms4\½Åg­Ææx0®§·ÄëT?—N6Ƹ»1.«¿ÍÀä_º=.ëvʯRdYF$±çe“e±XlÒ·CÌWl;'óuÜö^Ŷa,™I·e4i8·Ä&P™ÏúdÇK%ßo²ã…ñé>ŒÇênoþëñ¼G#©·X­äëLö{1æ(_½Åg­Ææx·ƒq=5¸%^§ú¹t²1ÆÝqYým¯5™×£nË);B…ˆˆˆˆˆˆˆˆˆˆˆ¨\T{ˆˆˆˆˆˆˆˆˆˆˆˆÜŽ """""""""""¢˜P!"""""""""""* """""""""""¢¼úꫯžì7‚®ëÂ{ÞóžœûR©úûûÕÞ?DSJ±ØŸDÕÄø$r/Öm‰Ü‰çN"÷b|¹ë¶DÅMzB¥¿¿«V­ÂsÏ=‡žž<óÌ38ûì³===X·nž{î9\ýõhllDkkkµ÷Ñ”P,6Æ'Q51>‰Ü‹u["w⹓ȽŸDîź-QiÓÒétz2ßPUUtvvbíÚµªU«ÐÕÕ…+Và”SNÁ† àñxìÖ4 MMM#¾ÞÏþs,Y²¤Úû‘¦°—_~Š¢à¨£Žªö¦ŒK±Ø0êø|üñÇñôÓOãˆ#ލvÑh Û¾};>ýéOW{3Æ­Òñyûí·cÞ¼yÕ.Ma¯½ö±|ùòjoʸ±nKõ†uÛÂñùÜsÏA×uÖm©ªX·eݖ܉u[Ömɽ&¢n{Ðd ™Lbppk×®444@Ó4û¾ÆÆFx<@KK ZZZL&ÑÙÙ9âk†B!|ö³ŸÌbLˆx‹-¢E‹ª½)ãvçwâÜsÏ­öfLZ9xà¨é‹Îb±)îm|þâ¿ÀŸþô'\xá…Õ.Þ¸ÕËgz*~ÏÜyç5Ñ9ñyÕUWáâ‹/®vÑÆmçÎØ¹sg]\¸ÔË÷L¹ÇdçÎPóÇn"ê¶?úÑêâ³0Ï9nWî1aݶp|꺎Ÿýìg5ÿ½L½Ït-`Ýv|ñùÃþùÈGª]´qcÝÖ}X·­ÿº­ÛÏ%µð½àöxŸˆºí¤&TR©Z[[ÑÓÓƒ-[¶ ¡¡vf3?£ÙØØˆT*Uô5§OŸÇct­êîrÖðÀ®®®joƤ”#™LbçÎ5ßS­XlŠ}1Úø\¼x1æÌ™ƒ•+W¢¥¥¥ÚE—zùLO¥ï™¡¡!ôõõA×õjoê¸MD|tÐAðxË9&¬Û·sçNÖm]d*}ψºík¯½VíM·‰ˆÏýû÷³në2õò=úmåê¶…žïn?—ÔÂ÷‚›ã½¯¯oBê¶“:B°‚mÆ ¬ÅÐÐzzzÐØØ8챩TªdïŸùóç»þƒEõ««« ÝÝÝÕÞŒŠ)6»ººÆŸË—//:ô“h¢455¡«« ýýýÕÞ”Š•§’ñyØa‡ñÜIU#.Xê!i°nKõ…u[ÖmÉX·eÝ–Ü‹u[Ömɽ:;;'$Ù>©#T<ϰá]âï–––a¬éášDµ¢XlŒO¢jb|¹ë¶DîÄs'‘{1>‰Ü‹u[¢òLjB¥µµÕ Xó€nÙ²MMMðx<ö0VÀšã,•JaåÊ•ÕÞGDu¯Xl`|Uã“ȽX·%r'ž;‰Ü‹ñIä^¬Û•gR§üjhh@WWV­ZǃT*Çc›îêêºuëÐÚÚŠ¾¾>tuu¹rÁ"¢zS*6Æ'Qµ0>‰Ü‹u["w⹓ȽŸDîź-Qy&} •ÎÎN;(sæÚsÞ×ÔÔÄacD“¨XlæßÏø$š\ŒO"÷bÝ–Èxî$r/Æ'‘{±nKTÚ¤'T :$Qõ”Š?Æ'Qõ0>‰Ü‹u["w⹓ȽŸDîź-Qq“º† Q-bB…ˆˆˆˆˆˆˆˆˆˆˆ¨&TˆˆˆˆˆˆˆˆˆˆˆˆJ`B…ˆˆˆˆˆˆˆˆˆˆˆ¨&TˆˆˆˆˆˆˆˆˆˆˆˆJ`B…ˆˆˆˆˆˆˆˆˆˆˆ¨&TˆˆˆˆˆˆˆˆˆˆˆˆJ`B…ˆˆˆˆˆˆˆˆˆˆˆ¨&TˆˆˆˆˆˆˆˆˆˆˆˆJ`B…ˆˆˆˆˆˆˆˆˆˆˆ¨&TˆˆˆˆˆˆˆˆˆˆˆˆJ`B…ˆˆˆˆˆˆˆˆˆˆˆ¨„ƒ&û S©R©TÎm­­­hhhȹ¿©© MMMÕÞ?DSF©Øt>†ñI4¹ŸDîź-‘;ñÜIä^ŒO"÷bÝ–¨´IO¨twwcË–-9·mÚ´ ===èîîFkk+úúúÐÕÕ…ÎÎÎjï#¢)¡Xl`|Uã“ȽX·%r'ž;‰Ü‹ñIä^¬Û•6é •¡¡¡œ¥Sww76lØÇƒþþ~¬Zµ ‡O¢IP,6Æ'Q51>‰Ü‹u["w⹓ȽŸDîź-Qi“¾†J2™,hÉdvÀ¶´´ ¥¥Éd²èëíÝ»·äcˆ&J2™ÄÎ;«½+ËH'Á±ÆçÎ;Ñßß_í¢Ñ444„d2‰ýû÷W{S*¢Òñ¹ÿ~$“ÉaC¹‰&C*•Âã?Ž7ß|³Ú›R¬ÛR=aÝ–u[r'Q·Ý»woµ7¥"X·¥zºmyuÛ¡¡¡j¦ þþþ ©ÛNjBEÏUW]…ãŽ;§œr zzzìælcccÉâk¯½Æ‹Nªšz¹è,›ÀØãsçÎèëë«vñh ¬›„ÊDÄ'/:©šR©úûûñÆoT{SÆu[ª7¬Û²nKî$궯½öZµ7eÜX·¥zúmyuÛÁÁÁj¦ ¾¾¾ ©ÛŽyʯ¡¡!ôõõ¡±±---e='•JÁãñ`íڵشi’É$Ö­[‡¦¦¦‚Uαùó磫««â;†¨]]]èîî®öfŒ[±ØôxMªŠ¦¦&tuuÕE/Ò‰ˆÏÃ;ŒçNªÑ«­’¬ÛR½aݶ8Öm©ZX·eÝ–Ü‹uÛâX·¥jêììœdû˜F¨twwã”SNÁš5kÐÝÝd2 UUKžÜ[ZZræáóx‰Ü‹u["w⹓ȽŸDîźmù4 ðû­ `%H‚A+ybšÖýá0 ßH3¬Ç:£iÕ.Ǩ*Édv¶RX»v-šššŠÎ)+†Š‰¤ËÐжlÙ’3´SôJèïïG*•ÂÊ•+«½ˆê^±ØÀø$ª"Æ'‘{±nKäNäj—œœFPñx<¸òÊ+‡e {zzJ¥ÐÚÚZôùëׯG¿=,Ì94LŒ|I¥RÃî#¢‰U,6Æ'Q51>‰Ü‹u["w⹓ȽŸDîźmqÁ •T‰Ço+àõZ·Å ²È}4 `Ñ{¬äÉÀ¯´[·©*`~ÀóÖëFMÀ»ÀÙVRFž@±^Q±ÌDø l˜+éÂÄˤuBeÅŠèëë³³•ƒƒƒPUƒƒƒeg&[ZZF¼oª$‘‹M€ñITMŒO"÷bÝ–Èxî$r/Æ'‘{±n›þ'@^xÖ߆a%C‚A@þo@ºØ©âõÃJj($qX‰ðí$ €@ÍÜæ‚ß´€ï€´hÿ_ öY@~ÐnÔK2ÏÑ3c¢pBE<.0Â} ¨‚FPéé鱡O&“ö¨Ç3å†yQý‰j€ò8޽½@,fMÅXHû¬Çø|°RæIâo0}.˜`VBEË<æ,Àû€5ý—²PZë³È eF®À„•$12?bÔJ&1ƒhæ~‘Ìɧè°­DAEÒ†‰—²ŒzQúT*…îîn455¡³³]]]X±b“)DDDDDDDDDDT[LkíÓ::¬Mäƒý%kÊ.ðF¦@è|äŽI8^+ˆlâ@è3€ò:¬$Џ]B €ŽÌbôÞïÞõ@ìÀØè'YÛ„ÌZ,ˆf~ËÈ&kÄíFæ±ræ7`k¯DïÈÜžOs¼•4ê*>ŸCCCèîî†Çãv¡ÛˆˆˆˆˆˆˆˆˆˆˆÜFàßi%N+±JéüYë¦(Î&¬Ä`%V¢° ²#=B™ÿF3?*²Iò<wÊu_Û5öe–BéÈ<(k핬;ÄíÍ™ÛÄ6°7þÌoÉq{ Ù„L ¹$Œ¼þ § fÔ •h4ŠžžÀƇÝÿÔSOU»LDDDDDDDDDDDÃèwñºÅú»c'ø5àÿ7k$J"È2`þ3 ÿˆ%€ðWé!d§àRbÀJ–ˆQ"qâ‡5Ý–xëßÞÂVi+TIµF„H€|ÖßåÖsäësàýœãµ$X 0¬„M€ ;„µÁº]Ð i€ìöl܃_þŸÇ糯çHè  @/¬¤Œs:1ä=&Qàv'1%Y±Ç S¥4btKzʯ®®.<õÔS#þ¹‘ös@ÿÐÜ ¿¨'êI€× ,ZôÂá0dPΠѯá›uØÑ½Ãjð÷"Ûð¯"›P‘a%8¢È®«^ùÜ+0$Ãz\&!#È‹2Q©÷?ãÖ‡œ ;A¡0~t|^èa ˆ`61¡X#h榀è=@Ç=ÂÀ¡wŠi‡4[£UDâEμ¿îØ>=ó^áÌßak›íµY´l9à‡•D Ã%c"wÊ0Ö(1rF܆ÌãÄífÞcœšáê)ÈFPqêïïG2™DµËADDDDDDDDDD4œ™ý¯¼Ð¬ÿÇø–{Ý‹'Ÿ|ùãÏqÈõ‡@Ó4lß¾¯,~ǽ°òB@¹Îš½ééÅO[‰1¥](>¹Ý„•ÈXøÙ…Ð4ͺÖcÔóÀÀÖ­[aägå.{š†ðV ü+àpVôMx÷¥a¾` ð×{ÞÆé‹Ï‡$¥Ññ$`H’•ú¡þ.ßÚmð›Ôt\þÓSpô×ßE׫oãÛ»¾ ó_#+™!ÁJŒ(Ží£nâŽ2ˆÑ""±ÏüxÏûAw¼.2··en7ïG69#^;ŒÜÑ?€5ÝY{îñ«¶1%TzzzpÊ)§`ÕªUX³f V­ZUU™X!""""""""""WÙóï{°÷7{ æ‹@è- äÞyëb<Ô—Rسç8ÿÝ™øÂàDZï·ûð‹¿ÿÓÿú(bŸ4CÃ;¯¼ƒ’/ ­¹ ×4_ƒ­WnÅ®]»¬7‰ ;²"ì|?âñ8 oò$É2@X C– ¨*°§yLÓÄ{¾íR3<3ú°|ù­øöÎýøò—/ÁwC¿ÀÓöãàÆ+àóØÒø66=ô|ðƒ ëØ |áeÜùOcï¿Á%3÷á«_} ?Þƒ¯ú¾ð…_AUã¸yÆ~\½á[ˆÝ?€‹?û q ðw;v’ ˜_´7€è2XIÐ~·ÃJ¬ø2·Ë°’C¬‘+‚í"FÏD‘²LŒŽ f^ùŒHÖ˜Žç‹ûd4QX –|†a-~3 FPI&“èîîFWW|ðA<õÔSÐ4 «W¯ž”&""""""""""*E×ùí«èþχa€? ø¼Ö‹÷O_…{_¿ÿØólÝz.ÚhÆôã¦cßo÷açë;ñý{¿o½üe(Oýã!œ;ÿ\,ºc¾Ðù4ö4bñ‹ f2 :²£9¢À«?ú¼ûõ¯²•PQº¡ãÿ€×ëE0Ä5Í×`OÛÄãq¼óÚÓxl÷ÓøÒóŸÅç>÷ ^}&.¾ØƒCyk>ü.ÔD€IDAT¼ð}ˆF£8ä#?ŶµáÄ÷áîåw㪠Mø(Vœy$°|ùøáؾ÷@\zi+?üoXó¥Ù¸ðŸášOó»‚ù/@P|ç·_±¿ùÍ^˜@x+ ™€´ðß4Ÿ„Ÿ‚ ܈l¢D,z¯dÊ0@Ðß@6Ù’IÊÀŒFf}ã)@S€Oü/Âø‚õ-è;­çšÇÆ¿'÷ÿÁ}&Ún²Žc0Ÿ´›hðû­éΠi@æ8„?œÍ­Ìn~Å?O£^”~Ë–-èììDgg§}[SSÖ¯_d2‰d2 Ç31Ÿ~""""""""""¢RÚà" }Ÿ‰öOC¨^‡•0ãcÇãÓßü4ÄÿqSzù¹Í0¶H (ÀðʲWþc¯ÿžúÇSð?àÇ[o½e½_ÖÔ]ñý¾ïã£G¾ûÈÇ×ãxwö»MÓ`J&Br±X †a@’$\*]Š'ZŸÀù›wâ¡Ýíe+3£( $IÂ2ß2,Ã2†Ã0pÖY §çüøÇÿ Y5aø¾x"dùP ÅÊ|Ȳ UU¡ª@ °O=õÞ›^€ðš#°Í´òŸþÄAøð‡ñoOÌF¨É„÷F º®Ãw«‚Ó/Áïþ|3âŸ:~(€t©cÊ1ä«ðÿ38x¢ï |ÿ’PN°Pæ>øÌŸù´y0ð~Ðo>óÜkxðù¡þø<˜7ŸÃ;ˆu¦1]šéHàè°ý/§`û‹ƒxwÚƒ]Ô†ÌmÄ£ )|Êÿ^üï‡_€ºæHè:àõù€@3¢÷ÞíÖ4hýÕG±­c[E?V£N¨ ¢¡¡¡à}#ÝNDDDDDDDDDD4iÀ¸NÚÞØƒ³$D£ADZC€ìûì>|dþG0{ölÌÖfã‹K¿ˆüý€\ˆ ñþ¿¾=ý¯xå±W¬©¨$ uj Oßõ4”3Ùr$žúîSzjº®Ã0 „ÃaÄb1<±è pÄ‘¸üÉ'@ìVò$"Ø›('pÍ/ÿWÜ{/VíÞmߦªjN‘dYÎ$I€[oÝk?_6MÀñZ‚$Iök´·7cîÜ;qï·@jº`šqlÝ*#ã°Ã>ƒø›ß¬ÐÑÑðz½Öï¿ÄñÖôÏ¡kíFD^¸ŸøÄ[ØúÙéØµË€¢xßé÷ã¸ÏŸ‰õŸy"‘(TÕóƒ@¼'-ߊ´þ-K¸©w&ÌG%\|ËcxòÉŸá’ÏMýC›þ4ý (»¶àŽÖé¸ÛZœõV¥oàÝw¿³>º×ÝôQ貎Áb¸àðƒvß‹#Nÿü_;xýù/ò»2ÚW¼ïÜ;ñÍW{¬¬èÇjÔS~y<lÙ²eØz)===H¥Rhmm­è•" ¿øÞ ¼ñÆØ÷Ήh™Õb- /€Ã0sæLëÁ*ð±c?† fX÷ëÀîww£¥¥ÿ×ðxçw§Í?  ( ¼^/¶þËV²Çáp‘H†a@Q|yÓ·ðÒìÙ…B¬ä†\ é!\¿z5äL£‰D"ûǶң0DÂç'-Gàÿ€öövÄãqȲ Ã0pæ™÷#‹!#²FÐȲ ¿ß}s~‚ïžèdžíX¾¼@¿ýíã¸þú ñ ‹ð¥/ÍGSÓ[˜;÷躎x<Œc_» [Oû |²†ûv;fþ34MCts?Xö5÷ìlÚu¶tüÊ ”†(žˆ@Uýxø©5øÄ‡çàôOÄW×|·Î»‹>´áp§_r:vÿ~7¦]ù5œ÷©Ã M¤¥³½q'¤CmüÌWB_ÛΊÆF=B¥³³ýýýXµjZZZÐØØˆT*…ÁÁAtuuj”J?šššrž“J¥J¥ÐÔÔ„¦¦¦Š˜ˆJ+›ã“È ŸDîź-‘;ñÜIä^ŒO"÷ª…ºm4 ø|¹·)q4 P ¼ðÿÓh·ÝŒ|)8æHðÄ!Oàù<Óø Žíx뉬…Ï}°æ³R€½{÷ÂëõâÆÛnÄ.ó><óûßãg½åXI²¦ÅÒ4 gžy&î¸ã$ „Ãa†a YýÆdY†$Iðåo°Ãì—^Ž>:{ƒX$·]…¬Û2‹Ûš›ËJ¦ÖhY–qÿêû¡üÔšL${¼^/¤Ìë†B!;ñcš&âñ8nm9³N›‡‹ßw/¾ýíÏÀ4MƒAüêßÀ¦·»¡ªw}ôJD£Q¨ªŠÇŽ<O=ÿg|É·K~wfÎü˜™2-[µ ‡Ô4{Z2œß¿º¡·^a˜ýÜaXy×× ïºï¾õøÜ;¸Ë¼ )Äå‹wö¼ƒ_\nâ‚C.: þ›ì^ýÛ¯ñ¾Ã—ã—;üX…w*ú¹õX¿~=n½õV¬\¹---X»v-þð‡?䬫RJ*•ÂêÕ«Ñ××gßÖÓÓƒU«VaãÆXµjzzz*ZX"*­PlŒO"7`|¹ë¶DîÄs'‘{1>‰ÜËíuÛpØZÜïϽ]Ó4Ü‚³á_ ttúpø¶íøÔ§ð¯ÇD€3ZÎÀüëæcèá!Ü·ë>Ì,³hyfQ­n…išØ÷ç}X¼x1Âá0f,˜…ÿ ¬$KêO)„Ãaøý~|ðÁèééÁ·¿ýmÌœ9Ë–-Ãy XŸÌvåmhf%õ<ºne‚„xÜ*d8 Öëe^³àã2 ´ç¾¼Ž`0ˆó®8 ËpÞÎvÒÆëõÚI ç(UU‹ÅpÚÿü‚Á î¸ãB;™ò¿—^І¯} úO¿’ó>¦i¢½½ O_ˆ@ I.¹ät¨ªšM6ù|€×‹}þ3‚Á 5eY«Œ†³–eŽqßüéû Ü±Cü#ÿçÂçóáê3Î$P=s~‰w¤UxòÍŸáá»fKÐwÌÀ——îÃïžþ8/8xmnÅ?£¡Éd[¶lÁúõëXFáóùÊ¡rÕUW »­»»6l€Çã±GÁx<Wd<‰¦ŠB± 0>‰Ü€ñIä^¬Û¹ÏDîÅø$r/·×m5-;xCÓ±ÌÈÓO7àaù-k@‡r0£oÎï:œy5ªááåÂïú!®^œ@,S’~Ãï1Û˜C犼ð„þ;„`0ˆñ,~wïãhZº¾ìÃðù|èíí`%®¿þz<ÿüó¸ÿþûñÈ#àRŸX´º®Û Ä |íkX~íµÃ æõf XIð’&’dÝ×Þn%WDáó*á°u[ ›ÞLŒê±÷‡,cáB+éY¶·WUU;i $,É<\¶J 1sgoÄ;‡þ_ßvÞT@Q4ܔܿü?°ïÏûpékû+þùõ•þþ~¬Y³&綦¦&$“I¬^½º¬×èîîFKKKÎz+Édðx<€––´´´ ™LV¼ÐDTX¡ØŸDnÀø$r/Öm‰Ü‰çN"÷b|¹—Û붦iå‰l^AغõQø±?ð¿‚åˇ ÿÍÄïwÿÞ!P€“fŸ„·ß~Û*Ç-@fÉ]×ñÄê'0óù™‡Ã¸í´Û°òO+³ÿ†—ššpüñÇ#ä,,¯( dYF,Ã_ÿúW´¶¶B‹ÇE$Iºûn „a€…ýýÐÓv y‰ V’A¼—,[I1úD$[œ$ÉÕ"¦3ÍœQ-³O: Ë–-ÂóÎáwÜ‘;}X8 ´µåŽ‚±÷»5*å‰dhkÃ3Ÿú¦¯\™»ÍšD£XöÎ;øá÷¾7¼,íí¸jÁ{¡{ø|@&yI²Êq×ÈS£!³üŸ¿áàïœÀ»Ï¼‹`0¯XÝy&à€í`ÎaÅSOÍ®ØçCBeóæÍèìì´G§ÖBõ7Þx#†††JR?¶lÙ2l§ˆyùœÄú,ÅìØ±cX‚‡h²¬Y³wÞygµ7£"FŠMqßXâóÎ;ïDwwwµ‹FSHþ¿øâ‹ÕÞ”Š•§’ñùâ‹/bÍš5œ>ª¢§§ÝÝÝxå•Wª½)Áº-ÕÖmY·%wuÛ;vT{S*VÖm©^°n[^ݶ¿¿ÜÛ[¹pØÊ)äç#4 ˜9s~ˆÃp\ÿ^44| ŸŸ³Ÿ¹ò3ÖÂTÀô™Ø·o_ö‰™Aáp÷q¾üý/#‰dýY†Ï4ÑyÌ1¹û'‡c›cEQpÌà ö47C–e<ðÎ;Øqà ¸ýüó/½õö?þ¸µÑ£d×TQ”áIŸ/7Û$IÖNÓu»ÏùË8êú뉓xÜJ¤‹ _˜&„išH$¸îâ‹ÃÀôO?>âë~ðÊ"I@<Ž¥ßü&.úØÇ nþôŸ™’ÅN¨@|bÀ¼_̓¦iP O\èÀÖS·bÖ¬oã¸ãöŽï=óŒ:¡’J¥ NëÕÐÐPrº¯¡¡!¬[·6löØÁÁÁa/gÈØâÅ‹±iÓ¦Šî¢rmÚ´ çž{nµ7cÜŠÅ&0öø<÷ÜsÑÕÕUíâÑÔÒÒ‚M›6aþüùÕÞ”q›ˆøœ?>6mÚ4ªµÏˆ*¥³³]]]˜7o^µ7eÜX·¥zúmq¬ÛRµˆºíâÅ‹«½)ãÆº-ÕÖm‹uÛ–––qo_<žÍ ˆ\Ï— á÷wþòBÄgšhxºš¦á˜cŽÁ¼»3Ç&ó¸Ö¯´â¦EßÇ™$u\ŠÃ4Mø|><³ä<¸ûAH’”3]Õì·ÞB!rÈ!8:3Í—­À´[‘Hï™>‰Þ^ûu¾Þy8oçNìºùf€µ>ߟ-T¹$ èíµFsŒ4Š#oª-ÄbÖ¢2™yÒdYF(ÊeƒX ˆDrŸköhI’ ­ûUO74àèsαf§°ë³ŸÅÀa‡Ü®Sÿû¿Ç÷A™4à fæØª@oo/$I²þ6v~Ôú»ÂFPimmÅ–-[†e ·lÙR0[éFÑÒÒ‚ÁÁA$“I ¢¿¿ýýýhllöøRYN"ªŒb± €ñITEŒO"÷bÝ–Èxî$r/Æ'‘{ÕBÝÖ˜ ‰m´ŸÚEV[þ˯½¿W;gàS‡}*ûDöH(@÷Cÿ Ͻ÷âðÃG8F8F4E(²fwÚ;}: (Ðd3ûÛlÄ4­ÿ«jvã2n¸ürèºI’‰DpÝ7âÆƒÆwܨªâÓ¦YÓy‰ÅéýþòwÄh“Šbe¡ Õëº]”Ãëž„;8|>ȲlÌ‘e ƒ,ËÙ¤“¢dŸŸH`ÁUW܈D†OQ¦iÖº0Žm+J¼n<`ý’I´œtÒI£ÛWeõ¢ôk×®E*•‚ªªö¼y"ÀÖ¯__2;944„7°oóæÍ„Çã6ÌHk›ˆÅäE%gJ4UÍ90’$N¨"F¶[3¥’Û@î¾ûn\zé¥Ý•£N¨ÀúõëÑÙى͛7°zlذ¡då^³f Ö®]›“˜I&“ðx<èïïG*•ÂÊ•++Z`"®Tlz<Æ'Q•0>‰Ü‹u["w⹓ȽŸDîåöºmf¦©œÁ^/`žøWë6?Žó›‹Å‹/Ç99‘} Žì:‚ ¼½ñm38ˆ» ^¯’$eÑhñÆ}Uµ§ÎÊÙ(¿?›€€•°ˆF£9ë­¼ç¸ãðÓ;î@ @8¶ž¯(§ ›Ž„¯œ†$Ùó«ù2£TF|ÜX§ÖÊ,L?ªçç*üºÖ¯‰˜ÎvL vÏJêêêºuëÐÚÚŠ¾¾>tuu•\—…ˆ&ã“ȽŸDîÄØ$r/Æ'‘{1>‰Ü©š±išÖÀx<»~ ò#ÀØĺBhîhÆNe'¼=^(†b­¥áƒ5å— º¤ãÀ¡iˆÇã¹#)L³`Bå?_yCÎDòÅù\¯×‰Xo£(ˆD"9kxH’dô02I3€=!1IÊq2ZΑ.å2ÍÜ}_ÄwÞYñÄ_Y •žžôôô`åÊ•X±bEņså/¸ÙÙ٠ǃT*…¦¦&é$ª’B‹á2>‰ÜñiUš clõ.¢‰Äº-‘;ñÜIä^ŒO"÷rSÝVÓ¬ëÀhtøræ^à½ÓßFË®´NkÅ¢;A‡µv TXS~ö¢ô€ßý!®<à$ÜEËÅ^y½ðBnB¥PÈZø]×x’,Û—˜QÌ{ªªŠææfx½^´&“øñ#àyS†ÑF±Ÿª6B¥³³+W®D2™ÄÆ‘J¥ÐÒÒ‚•+WV|” O–DîÅø$r¯©ŸšfUœÃa«Žªë£ªGUÅTˆM¢ZÅø$r/Æ'‘;MvlƒÖ5Ÿ®[ׂ…qÄ'¼ŠeG/Ã)Ÿ‚! aöY³€˜J Ñhªªâ¿vïFï‘GBÓ´ÜuDt}xÏ=ÃÀ¾™3ËÛàX,³Qñ‚‹¼;×ñù|Ðuš¦!nš—/‡a#O«EY£˜íÑGÅÑG}ìc{ûÊ}`CCV¬Xõë×cÓ¦MhmmEOOÖ¬Yƒîînô÷÷OîŽ#""¢ºgVÅ0¬)i£Qkµèèã÷W{ ‰ˆˆˆˆˆh"ˆÎtšfå9%Ó–´“È À‡å¿ã”NÁÜis±ä#Kðéù4 ÁZ?E 8ÑÓ4í)Çs ÎùÀl/¾x<{›a`ç‚™»5”¥Œ5>EAoo/€ìñúD/L?{î¹8å”S*úše'Tò9“++W®ÄæÍ›±jÕ*&Vˆˆˆ¨"LÓJ˜†Õ3)³z'‰uñB¡òÖ¢#"""""¢Ú㈠IÖß’+Q’Ém{GŽÛ;·[7È™‘ Jæq&€ °ùç›!I‚Á öL›f=Ö4­$аm›õÑhö6ÓÄë3fŒnÃG±Æ‡¢(ö*µaT‹Ò'“I¤R)tvvúûûÑÝÝ ÀZ¤þÖ[o­vyˆˆˆ¨Æ‰õøâq«Âœ3­×\½™ÿË£éKDDDDDD5DQ¬Ü†˜I˾6”a'U¤9À܆=8æGÇ?ÈÜÌctë¶ÃWŽS½§â€?þû<2û&~¿õââR’¬„H8lõäóz±Uסb ³bÁÏP(I’`¢ÎDNžææf$ ;éâ墢USö•«®º kÖ¬A*•¤R)¬^½€•LÙ²e Ö­[WíòQ ­Š²¦YõVÀšÚ+BvÞ[ðÁZT0ÀoÆæ("""""¢ú"kˆY¸rh¼ÀG¾öÄ> ÌÝ3oÏy;÷ÚQ$]lß¾7ÿîfH’„O}ï{ˆË²µvŠ$YÉ”ŽŽÜ×O$¬~EEå-F_Œ˜‚¬ØÚ)¦iÂ0 „ÃaèºÎ‘,UVÖ•þþ~lÞ¼·Þz«½ý–-[ÐØØˆ 6 ¡¡PU©TŠ ‡Ѩ†U_M$¬ú¬]—ÔaÍ+ê-ÁJ¨¨Öo£0ä‚ëýQ2M+ß±m[æÙÑ'`{øcP.’É}xâ_ŸÀéý§€%Ï,ÁékNvôÑø×ÿý_¢gž¢XÓsE£ÙDˆ$Y§Uî½g À®ëˆÇãE2ˆª¦¬„ÊæÍ›áñxìd `MÿµbÅ 444šššÐÔÔÄ„ •EŒD‰F­J²ßoݦªŽ‰+©bÂê…B¶·Ñ£Õ.Uš$åuœ š±@àxà(P0t쌤õ!¸ÝºÏé¦ÛoBç¬N\ô‹ìÛdYÎä.D/6 J‰ Ó4ÑÖÖfo£¦iˆD"e†aØ£Z¨:Êžò+?I’L&ÑÚÚšs›H®cV"E×ÞÌš(b Xéq°’&¢®€Uyö9~ï©vIˆˆˆˆˆˆ¨ÒL3/¡b";¥Wxâ‰'Gow½ÝÏìÆÀÉÖµc^ä¬5gáàù3Y¶’*EhÎÅë'ˆ5‡áõz‘H$H$àóùì…ë%I‚išœö«ŠÊJ¨466"™LÚoÙ²àñxìÛ†††ÐßßÆÆÆj—‰ˆˆˆ\L×­dŠ×kMï%:×H’5?®4kZ¯8€vX£QTdG¦ €=Ù¹u‰ˆˆˆˆˆ¨>hš•TÉ‘I¨ aýë±jÙ*À®Y»pú%§[I—<ÿ÷ùÿÇ;šÀƒÁjmDf¦ÀbŠ/!‰Ø 1j¥££Ã~+{̺#”÷À`Íþæì¬Àð©½Ê ªê¤”×¹6J¡i½TU…Ï烮ëöÚ*4ùÊJ¨455áÆoD2™ÄºuëÐØØˆ®®.ÖÔ_§œr ’É$6lØPíòÕ £Ê‹›UƒiZ£Sz{‡OG«ª€: ÖZ)™yqƒ5µW¨ðëiŸ¢×T»TDDDDDD4¡¼dkê­Y³fAUU 6€ƒ^?³ßz+ûÁ0ðØ7Z#:ŽÛeyoê.’$AUU{ê¯ü„ŠišðûýºxN=({ •––hš†§žz ›6m²G¢´¶¶bÓ¦MÐ4£SˆˆFF‡%PÚÛÛÙ›€¦¿„uý¢4 ±Vï!1½—ˆ;z9cÆ0 àiT»TDDDDDDTIñxÞµ£ l%T^9ûÀîÆÝØyÞ ,}õUûab¬7Ü€w–-Ë]¢ë#{q‘rÚŠE±GªÖº+~¿ßN´ÄãqèºÎäÊ(;¡2’†††œµTÊÑßßd2‰þþþa÷¥R)$“I¤R©jï¢)§XlŒÏ‘8%…Fhš†`0ˆp8 Ó4ÑÑѹsçÚ÷•£Öã3·~T5o­? ÖâóqaXÓ|%`%S$+™"*€†a ­­ÍîqÓÞÞŽé[á;°Ú¥£©Žu["wªõs'Q=c|¹—궦 $y¹€ ÈšŒ¶´À¢;áïsædžgÚí-}7Ý„ãN=uøš){ø•6™b•Û(Iâñ8ÚÛۇ펈¡P¡Pápöíœ%¥r*÷©T 7nD*•BCC|>ߘF¤\uÕUH&“hjjB*•‚ÇãÁúõë===èîîFkk+úúúÐÕÕ…ÎÎÎjï#¢)¡XlŒÏ‘ƒA˜¦‰H$Ó4ÑÜÜŒ@ €P(;?‘¦iöÉ,B–eôööÚÉY–áõzÑÑÑP(d/0F$ÔC|F£’)Ad™7D»è<¬ø1Mº®#Ú±Ç!Ë2þëç_Ã-óVåŒà&šL¬Û¹S=œ;‰êã“ȽÜR· ‡­™¹|>Ç ÐÒÚ‚Y gžYò v.؉ï7Ÿ€Ÿd&®?zÀ˜~õÕ@{»ã5”1'T€ÂëšTZ9‰Ñv´mÛ6†MÓì…ë­bZS‚‰¶(]×ÑÞÞŽ@ ŸÏÓ4sÚžÂá0  BÓ4Äb1øý~¨ª /.Í•.Ó9眓>çœsÒ×^{mú“Ÿüdº­­-ýì³Ï–ûôt:N÷õõ¥ÛÚÚÒƒƒƒét:~öÙgÓK—.M÷õõ¥Óétº­­-}ß}÷Ù]ºtiÉ÷X½zõ¨¶¨Ò®½öZûs[«JÅf:=úø¼ï¾ûÒ×^{mµ‹6aÒ^¯7­(JZ–åt:N'‰t Hû|¾´ªªét$Iû>I’ÒÛ¶m³_'¤EI§Óé4€t"‘¨vÑêJ=œ#&">«±_2a’ étZM§Ó¾Ì”N§{ÓvìÄb±´,ËéP(”öz½v¬¥Óéô¶mÛÒiUUÓò¬t:I§U5…ÒiEI§&½ˆ4 õrŽ`Ý–êë¶…ÕË÷Õ¶z8GÔKÝ–È©^ÎnªÛªj:íh:±¬kÅçg=ŸN¬›‰Dú/ï¿,-š¸#‘ˆ} éóù¬Ér:‹ë"1‘H¤UUM‰<i¯×k¿W¥ø|¾´$Iöõu¡rȲlï/ÑÎ%¶C–åô@}‹ÅÒ½½½ö{x½Þ’Û"®ãó LX{ØDÔmËšòK åºõÖ[ÑÕÕ…[o½èééUò&•J¡³³ ¬Åî`ppÉdöôa---hiiA2™¬vΉ¨î‹MŒÏ<"³¯ª*z{{!Ë2š›› !˲Ý+ ®ÊP(„@ Ó ÀÙÛ^˜;w.‚Á =ú…¦¶zˆOÃaÝ?Ù) ¬uSkä—˜ó5‰ÀçóA–eÄb1û©²,Û½ƒ”}ÖPðHĺÏç³FăVϦxÜÚ¢JcÝ–ÈêáÜIT¯ŸDî妺m(Tà2nµÇü²ã—93õâv;ËòcE €ªªˆéb±ìÔ.'Ërŧ†—$ ’$Áëõ"‘Hä´I‰iµ½^/4Mƒß(PUèèèÈ9F á÷û1wî\{ÝÓ4FÑÑÑ1l;Âá0ÚÚÚìòÅãq{F 1µw!âuݤì)¿<P°bÅŠQ¿ÙŠ+°bÅ ¡¯¯Éd---ðx<ظq£¨BcccÉ9ùvìØ5kÖ`Ó¦MÕÞ—4­Y³;vìõ:BnS,6kþ̱ÄçwÞ èêêªv+B4ðŠF^±°™¢(0 º®çœ˜âñ¸=U‘/3N53ßìçƒA; #Ë2TU…¦i‡Ã9Ó‡QyúûûÑÝÝ_|±Ú›2nŸ/¾ø"Ö¬Yƒ+VLÊô ’dUˆm¬µSTXóàŠ°P`WÞ¶m[Îk‹õ«nìõZSŠézvš\M³¦óz­ÿ˲µ=âqñ¸õÿX—°nôôô §§K—.­ö¦Œë¶ToX·Zu[ª¢n»cÇŽjoʸÕCݖȉuÛòê¶]]]e/aÖõ\"^gÙZ#åƒ|Ø 3جýû!·¶Žøô§Ñö•¯  f;´*Š•T©!¥ÖP ŸÏg¿ž˜r^$5Âá0|>|>Ÿ½FL$®ëðz½v»—išðûýðù|Ð4 º®£··íííˆÅbPU’$¡££ÃžN,ÚmaÑhñx¡Pº®Û?†aÀëõÂëõÚ;ÛÕ‚Á ¢Ñ¨ý£ÕÝÝ_ýêW¯ÛŽ{Qú±ë±lÙ²Å.èà”¨…,^¼˜œT5›6m¹çž[íͨ˜B± Œ=>Ï=÷Üš½à4Míííö(1*°NFÎ/r¯×‹X,I’†%Y ;!ä÷©ª Ó4¡ªªÝ›"^=(ܨ¥¥›6mÂüùó«½)SÉøœ?>6mÚ4iœùk" kzVBE‚q«w‹¨P†oQnýØY÷ŒD¬û|>+i"IÖè•¶¶ì¨•hÔZôÐ0¬ßá0à÷ØnªˆÎÎNtuuaÞ¼yÕÞ”ŠaÝ–êë¶ÅÕrÝ–j›¨Û.^¼¸Ú›R1µ\·%rbݶ8Q·Í:܆1ò2'º®£aqCÎm‡fÿÿ¯—]†–ÿý_œÑÒ2¦øz$’(N"yb†ôˆD"vGF1JEƒÃá°=[‹$Ièííµ'F‰Y&œ#mÂá°‰F£Ðu‰D@º®#@Q”œ60Ó4ÇrFµD£Q†QpL¾Å‹ãé§ŸÆ«¯¾ZÑ}Zö•J•¡¡!¬Zµ MMMhllö¸T*5¦…ï‰hl Åfgg甋OÃ0ìÅãŰFUU¡(JÁ^ò"Ó?00`ß&IRNB¥¯×k'`âñ¸ýz’$ÙÃ=5M³-45Õb|Š Ã*Ä:¬dŠ€ög_ôbíçü‰Ö'pNȹÍë¾Þ ˜L–­d‰×k^1M+©bÖï@ÀºùL*ë¶DîT‹çN¢©‚ñIä^Õ®ÛŠ™ò=ôÐCˆq|æ3Ÿî·nkxúiì›9€ÕÿÀ;ïà#çŸß|3ðýïWx»´ŠŽ©gœIb+á"¦‰sV±Ð½xmñú¦iÚ 1:F<·½½†aÀ4Mø|>{”Œ˜^LÌê"fy ƒ9ítbú°P(¯×‹`0ˆµk×bΜ9݇ePéëëÚ5kìŸ-[¶`Ë–-9·­Y³¦èkôôô`ãÆöß hii±0˜Øàà`YÙΩÄ4Í‚óÆ™¦™“™@¢r‹MS*>ÅÈÀ:Y$ ø|¾QÏ×(Ë2 À¢(%OJbŠ/Y–‡½¢(‡Ã0MÓ)CSK­Æ§¦­ªyCµÛa­—2`ý6%ëü …ì©îJÅŒ“¢(˜µkÖ°Û5 ©ÃŠ× ˆÅ$É¢ëÖíé´5=™ªZ ˜¶6 ¹ÙJºåcÝ–ÈjõÜI40>‰ÜË-u[ÓžP1 Þü0 ‹Ï^l]S:öX|õ¨£2Ï3!Iûáñöw¿[íÝ9fÑh´hÒb¼œ¯=š‘sÓrˆviMÓrž ÎJ!F¼x½^{*pI’ (ŠÝNÐÛÛ‹X,†D"X,MÓÐÜÜl·•E£Q{:}]ס( ?üðŠïò*hÍÌE'455)hzzz044²çÇôx<ö"G€5of*•ÂÊ•++^èZ¢ë:æÎkg ý~¿á–ŽŽtttØS‰}Âá0Âáp΢ØD#)6L™øŒÇãhkkC °3Üâ„1ÚD†h.'¡â”¿‹8qˆ¬=§›šj1>ýþìÖš)QX£S2t]·G¤ˆ‘ZbÚ»Ñhxº!çuÑ-B¯(V…½P]2³’/ŽÎ5D9X·%r§Zšö±m'k$ÌD&nDGcñ! }_±‹è¤ ±X,gô‹¢($ÉžFLtNkZ¥’ÊšòK õ¯ÎÎNlÙ²Å.Ö×ׇ•+WÚó\vuuaݺuhmmE__ºººÐÐÐ0Îw­Mb1jÃ0‰Dà÷û‹Åì ›HšlÛ¶ÍþÐôöö¢­­ †a ä$R8US*6úˆÏ`Ðê…îì-/ÓC‰Ä°/\Ñk~,œk©”Ëùþ"¡#N"cݪ]µŸ†a­[b ÃZŒ>À›;L,@/¦Ö­¡c‡0ssnSU+ÞË¡ªV¨Ðº÷"ãñÂ÷ÓÔÆº-‘;Õ깓h*`|¹—[ê¶…šPž¼ÿIÌ™3Çž*÷ñæÎ;áIˆÐ$\:;çÖº±´‡9ŸFí$ÊHë¬æšÑuªªÚÓƒ)Š‚;vT¼l£^C%•J!™LÚÃ¼ššš°råʲhÓ¦Mèïï·‡…9G¹tvvÂãñ •JyL­ ƒv¯\Àšä÷û!Ë2"‘ˆ1M~¿¡P¦iÚë*D£Q@"ÓB¬ªª½ ¯˜“>‰ ££Û¶m³_Û™Õ#ŠÇ&P»ñišV£ª$Y¿UÕZ#Aœƒý~?¼^/¢Ñ(B¡PE³×"‘Yî ¤P†^QD2 ?ˆa‹ñx|Ô‹vSm«µø4 kÖZ)†ãG ñhÜžÕùÙïíí-ýѨ̲Œ¹{ö`àä,‘–äÃa«íUQ¬é‡dÙZ[°†ŒªªZV/ƒ±dÕE¢³Ü^ #(œ•‚X,f'hj©¥øÔ4+‰ ÀšŠ+ @ {š÷ WëE4µÏw£[?á0°m®¸é&¼xa8€œû0åpXIVb™í( Ô©Q’¬rq°'º-‘;ÕÒ¹“hªa|¹W5붦iµÝØâÀÓ‹ŸÆGù¨um™ßlÒÞ(¹®w­˜¬†F»NðXˆ)ìó§¶/w?„Ëœw[LÓïœÝEtœVwß}wÅËVö¢ôÝÝÝèééÁúõëñàƒbÓ¦MØ´i|ðAø|>;ÙBå‹Çãö‡Kü8?¥˜¦™³¶ƒ$IvS’$; dÖ¨öööI ¢j0MkŠ/Ÿ/»ø´×k5ŠŠïqMÓÊ>Q93Ý­Ø6‰5&ˆÜLŒ MfHB@,C0„Ï特·2 Ë ìq¢(€ü(¬d`­á2Ž%Å8B…ˆˆˆˆˆhbF^'6x!ùŽ9ü«³\ž¡¡!\ôoàœsΩö¦×±œÄDíWc¹ö/·½®Pz¹§Çª¬„J?6n܈o¼1g^KhhhÀÚµkÑÕÕeO?Eå ‡Ãö(gR¤ÜdŠ˜‹®Üe<·“-Á`Š¢Àï÷W{7M]·Ú]ý~«a7‘°~ßÿسç!hšMÓF5ÒÃ-C.eYF8ÎY'‰ÈM$ɱÀ{€ìX¾¦bÚ#Sƹàãz{ÑÐÐàšöšZ!Úž'r­–ÑL_è¹ãݶ‰\„J2™„Çã):äkíÚµB2™œ°­Á`Ó¦MƒªªöÔ^ñxܾ¿Ü/çH”RœÉñaë±Õ ÃÈÎdšV¯†üïîÿú¯[ðë_¿ ¿ßo¯MR½ÜÅÆ©Üø7M3ç{ƒÈMd9oÊ/辡e¹¼ŽÎÞ2VPÃ;Ùwâ‰8èíW­E’!nð€¬aábxxsæqþÌOVÒÇ€•Œi‡•„Éë#¢ëV垈ˆˆˆˆˆ&†aä%Tó·c°èEÃlš@féÉšQ¤^LVÊ4Í1'UF;Âd²Úí€2×P,ëÅ<Ϥmx-òûýö‡(NÛ·Od6P"FÃ0‘Bõ(·= #»‚óáE'ËrÙÃ%Iš´˜)gAn±°0ºiˈ&š¦YÉ”xܱ&I ØÑ½ês*^”^,/‘išÖð21__¡ZuÆ3Ÿÿ<4MÃéæùV$À„D()Ž€¹S‰DK@ÖÔdm°¦*σõö“X?#"""""šRâñ¼õS2íð<àð?çÏY3îûÝïðâܹâr£Y\~¼ï3YícePill,+©ÂÑ)#3 ÃΘægØTUó0¤rç»™Z1½‘Hì0±BõÄç³Ú]½^«-6¿ 6ãóŸÿ<y¤¬\²m2¾ø…rzUȲ ]×áõz'eÎK¢riÐÖæ˜î šŸ=ù3ì»db±Xy•]Q“Ö´c¾‡;fû1V2%@^¸ô…œd€l‚D…•T‰ÀJ¾„2ÿf#Hd^+k´KÔ*ÓNÁJDDDDD4¥iZÞµ¤ÜtÂM˜Ö6ÍJ®<ÏÎ\àÄóÏDz_ü±X¬Ú›N#”'2é%¥ŸLe%TV¬Xþþþ¢ “îîn455q”JÑhíííˆD"ˆD"gǺPŽªªe}(eYÎyœØÃ0 ëú˜‡_¹I8œ];°,Ë—ï@4Ess3dYÆúõgbß¾}“š$™(^¯—±K®!ê/Û¶9få2£pëŽ[qÑ7.Ê>Ø4³a]·¦ôrV€4-›P1Œ¼Zuaw-» ÍÑf£Aœxû‰ÅìC6¹€•DñÁ‚Ì}^d.™ï.[DDDDDD41|¾¼*:°ÿæýèˆvXëaÞÍI¨„Ãa¶‰¸œ$I>[5Ú÷ÊJ¨455aíÚµX·n6n܈¡¡!û¾¡¡!twwcãÆèêêšô¸a‡Ãèíí-9ìh¬£EÊý`šfE¬ßÂ^îTtÝjÈõz­žä^/ðôÓ_C<·šÐÐð_ÕÞÔŠSø¹8…I’c@Iøíó¿Þi Îf'Å V‘T1Më·â˜k«ÈynÖ®]ø[¾‹@,C4…¢(£;¯I°+…Ȱ¦ 38åÑD)ÔmæÌ™8ìèìpûÍœkC¯×˵SÆa2Ú“b±Ø¤ Òu}Ò¦+{Þ‘,‰F£öh”ÁÁA ¡©© 6lÀŠ+&e£kI0D (ë€NôYL÷•?ÔŠ ²T/D›­sAl]×±M¬ÃqÐAÝøÿÙ;÷ø8ÊzÿÊ­7H:åZB,N¸'UdBÅ  2‘ÐÂnð BvW9‹Ùõ§pº+9`åxÙ-Zäx”dÎáxŠ;ˆDèÉ(Bå’²(B§ ·–ùý1ûÌÎnö–ÝÍîìæó$;;3Ï33ßy¾Ïó½)ÊØ4ÏÔ*QUÕ‘[Y–g<|’RÈHòöàÛøÕÑ¿Âÿªÿ›¹AÓlAÕu@UmƒŠ,½½ÀȈý_ (öwòÐyï½X>¾_x0EÁöíÛÇ3ê Y–]×qpÚø„¥µÞW™B!„BfãûãáC¶ÿ8IžOO8w^vÖŽŒàÆ{î©w3–ŠæÈ¥VÑ*%E¨úûûqÇw8Æ“¾¾>¬_¿º®Ó˜âÂ0 ôöö:°NeÞÂ(Š2mËj9‹¨4 fåì³_‡¦…!I¶ñwΜ99 {ï½wÓ D=B¼@¶î2rù:ú ©_²- n9T ‘È qmt)À¢w¾22 ž>Ÿš¦9‘ŸápÑh´üŽ`Gªì†S‘B!„BHõÈNlðìÏâ½¾×þãQè±'œ¯Þp^ÿíoqöš5õnrÃ" ÍáSëáÓ«Ì  ¥¥+V¬˜b@I&“œÕi¿,ËB0tþ6M³dc `G¦»È[΃¯ªª#8’$A'ipæÎÝ Ã0`Y¢Ñ(¶oßžS¦®ºjTuY½›[6î”’$1g(ñ¢Ž<;EVXܺÒþN¸X:|,Ÿ×Höç¥ÔS,Z´(c<”$ ¡PÑh¡Pº®—T O(aS¾#ˆ>vñzëB!„BHÕðûíšœ‚9OÎÁöEÛí?D¡Îp{Üx#~þ‘àÒ&‹® åcšfMCÓŠP)D2™ÄºuëjÖp/¡ë:‚Á ü~?dY†¦i0M³f‹œ•„3É²ì¤ "¤‘A†a8‹¨ùNË)ä¥"öŠ¢8õ`TU¥A…xÓt–¤rßÞ±øŽôÆÞ^»vJ9.2F{î¹S>Q*š¦ÁçóAUÕ‚uU,ËBoooA'YLá'Ñ Û¸B!„B!¤b²§}Û¶mÃ’%K2?”$lÿññ‰k¯­ws‰‡P¥¦kcU3¨L‡d2‰ááa çÝ–L&ëÑ´²ˆF£Î"M$q¼â-Ëšñš @ âsРB…dÓ½Ýkòiš@0¼÷½,©VB9{­R„¹‚ÜJ‚)¿f^–OË]РfÄÄ“sž´Ç(I²Ó|éúô-šñxájð²ŒC>ñ ûw¡@™&$]Ç5ûìƒh4 ŸÏŸÏ‡h4ê¤þräÆ49sðà]w¥þ̯„éº-£Æ'`G©TEŒ4ͦÛÒ,xyì$d¶Cù$Ä»ÔK·ÍåÇ:Å  áâë®ã:&™B-ëÁL;åW¥ `pp]]]H&“hiiÁ 7Ü€–– b``]]]Ø´iúûûÑ××Wë&N Ó4aYFFF2R…ÔjñµZáL²,£··‰D¢&í&Þ£lð¤|†½Ö Ÿþôã¸óÎß;FÆF­‘bYv¿J ˆ‘e™*³¯Ë§aÊž°)q`ó²Í8¶ãX¨ªš6¨¨*‹Ù¹Áªél ˩БTÌØ˜ýÀÎ?±Þ^;ÂÌ4‘H$pÚ '`Þë¯ãûÿùŸÂa Âm÷݇/¼ñÞñ›ßØÇ);£Q;—™,C–íw޹ JÀˆÛ°ÒigI™4›nKH³àõ±“Ù å“ïâ Ý6 <ÿüó8â˜#¦lŽD"MSû£ž4ÓZR­×³k¡"Ò‚Ýpà N1û‰‰ °…víÚµX¿~=n¸á\y啞÷FÐuÝY¼Íf/{‹ÅfI’2ÒÑÂ;;)&›€÷äSÓÒ5Î8ã.\rÉQ°, ‘HdƬҵ°§{‘j°¢¢Ûij4‚|Ê2:€€ÄÅ ë:Úž>ýEE)­.ŠÀ0JKfšvÂ]qì¡!ÀçÃâh4Åé÷C2 üpéRìüÆ7 I^<ï<{[j¿c?ñ ünþų̈Ir,·€ýUQ†uTH3ê¶„40v2[¡|â]ê­Û* l‡µ°ýó®ƒîBÛ9möâOØÎ+mY©ßIù(ŠŸÏç©ôöDI•ááa ü¿aÆ¢ÇI&“èééAgg§óÙŠ+0>>Žááa´¶¶¢§§ÐÙÙ‰ÎÎμáŸõÄm(1 #gÊ-EQ<ûPºÛ&~ʲ EQŸ‘H¤a³»Ô›’ *Éd£££ÿ ¡+DOOÖ¯_ïü=11 6 ½½£££hooÏø~kkkQKç–-[°jÕªš]0]×ÑÝÝ ]×aYLÓ¬ZEQjþ «ªê¼ˆ$Ir¨DIaV­Z…[o½µÞͨ˜B²  lù¼õÖ[100PV›LÓ^#õûÓŽâÂpáóÙ±Ö*ê•jôù¦WGE×HdÈ^4Î:…aØÎÙX°xqº¤C)ˆcŒØýëîÎ}ìl„ì6S¸f¥ŒŽŽbÕªUضm[½›R13!ŸÛ¶mêU«2<ËA¤¨3 @} ¶â+ÛÆ Å4qþ¢EåY0’„]]]Ð]‚§ë:âñ8‚Á ¢Ñ(º»»í†ˆ]ùi¼¶oÇÊo} ªª:…è{{{aYVzöù[´È%ÉÞÏïâq´]ò^<þÝÿ†®Ñ;ýÃJS’F¤ xñÅëÝ”ŠiÝ–7ÔmgN·%¤„n»eË–z7¥b¼¬ÛRÔmKÓmGGG ~Ï4SëØý±Ý˜;w®½Q×´ÑñxZ) %„ÀŽªš ݶ¤*gœqººº2,”•²aà  §§}}}9ÓlAÍÅÒ¥K3„}¦‰Çã…B‡ÃPUµàf9Æ‘Z¤ 9Û¦(Š6ÇH•ÒX¿~}ÓMª²e€ã-ä¦ù<óÌ3Ñßß_ò¹£Q{ÍÓç³×05Í^'‘)¢ðu ¶éÐ4ˉL)U~âqûÙ¶Pa0‰Dìó‡Ãö¸-Ëöš°¦Ùû†Bé6D£öqÜmTU{?E±·§2êŲì}$É6ªˆ¾CUUhšUU‡é­Û[fýúõM·(Y-ù<øàƒ«2vŠg>v€ßØŸ™¦‰“—,âq;:*2¨Äãq|ø•W  … IâñxF~TŸÏK’PtÄÍÑqœ`0ˆx*­—$I°üöž{Òi0G oñEüd×ù­Nv?X:à U|9g }}}hooo:OÓFÕmIócšfÉ:uÛÂLW·%¤ZP·­nKH9P·-L©º­eÙk!¨Àë7¿ŽŸ|î'ˆÄS:Œ$9N팪 ¥2Sz[I•x<ŽÑÑÑ p^ÓabbkÖ¬A2™ÄUW]åDµ´¶¶Nùn2™¬ª§†¡¡!†`0˜wrâÕt_ ¶YUUÄãqȲìÔ‡!³ƒ|² ÔN>…Â4ÓÆI²?Æaœ…àDQM7e¢d888ÄãöùD)ŸÏ>Ÿ®§0€mhÞ‰„m„éî¶·‹cv&!Ë‚Á´‘¦’”Y?E’ìã N>dY†ÏçC(Bww7 ´5^Ï\ÄãÀˆH 2°xñb¨ªŠvpøái+ahšI’°õCùâF‘H$¦ÔHÞI¡P‹†ªæ-PävPÅ©G$ÆBEQ …BÐ4 ·œs êâ¿ ô©ßÂúü¿"Ü H§ê]3~ɉitÝ–4/–e;ƒAø|>ç)t'7~¿CCÍSÊ«c'!å¢iÞxãz7£*P> ñ.õÒme9•µY`Ï÷,VÞ¾øërgA$ Â0 ŒÕû2‘YNÙEé×­[WVá¡‹/¾íííÐu=cÐìììœr¼ñññilfŠh4Š`0˜Q{Ä0Œ¼†aœh$D¡¡¡â S¤éÈ'›@íäS¬“Æã"Í–½* nÛÀéö*/Qj!¶ë±ttØç²Ï'IöO!ŠbMt„ `ÿ."jÆÆÒFe" $ªjF¢Qû\îz×Ùd¯÷ŽŒØû™fþôa²,;¹/}>#Ìš/Èg6š–’—€0°sçNȲŒ$áÓ·ßži&–e9QW§þùÏðù|É)çb‘°(E *â>Ÿñx@Š¢Àï÷£»»š¦9Qª‡þ¾÷›Åÿüð~\xá]–ÆBþ½äÄ£4ªnKjG0Ìù¹išéH¸†aLùÌ®ëò–e¡££º®£··×IK Øó—h4 Ó4‡‡§°îîn'}±išÐuš¦5UúP/ŽdöK–DÍC·®.Š+‡Ãaøýþ)õZÃá0æÌ™ƒîînƒÁ¦H)P> ñ2õÒm Ã^+ @&¶L eiKÆwB¡ë~OPR„JµÄÄÄV¬X‘ ×ÞÞŽžž§ÈQOOS—åŒ3Ψ÷5`+:ñx<#•N¡03Y–ÖC\ä–_/GÛêPH6k%Ÿ¦ižCC¶A"¶>ŸmPpGxˆ…±! ˜ÓT…‘&Û±A–§¦Ù’$»}†‘6¢oÃÈ4‰~ˆta¢>L,–6¾öuöq%ÉŽ‚ s×ÙÎF{eYvjËÆÆ ò™ ÓLAe>àž¸ê<J$RZHVâñ8t]/ÙKZ’$ôööbdd¤ì¾H’„@ÊRª( EÏçƒišðù|Θ(¶ß|ó8~ÿû÷£mëxbôY<üÚ‹X~ÀžY`Åó‘f¡‘u[RLÓtŒ±bn jAI’I’ ªªS ®»»‰DR*­…,ËiM…IJ,lß¾ÑhÔ™§†¿ßï¼·„qE–e¨ªêDÜ ]Aä wëOÍRCÑ«c'i>„AD8be8væÑî,¢î¡pfôûýNJnI’2þŽÇãPUÛ·o‡$I‡Ã¸ûî»ëÝ务|â]<¡Û€sv`ìË |üÌ›ÂápEó>BªEM *ÉdÉdrJÞÏÕ«W£¿¿ýýýX³f ººº°iÓ&ô÷÷£¥¥¥Ì³U1á4bJ©ˆ4'½½½Ø¾}{½›Cf˜b² `ÆåS¤à)®ÜçªjG…ˆù¾¨õ#Ó1þåsœ‘%Ùø|ic‡,ÛíÍ—†+ŸÑÃýý@À6ªˆHA.Ci¦k¸3¨È² MÓ‡§¼³HcâùÌF<•(lB0t#-Ó4¦ˆÅAMÓàóùJ‹8qQí¨JQ[ÅýNq×myÏ{Zñž÷„`=÷ ~+"¾;`+AÑL¯ù¤itÝ–”‡aÐu=ãÝ#¢BÜz‰ˆø$ Ñh@ÀñPw/"”J+èóù ë:¢Ñ¨cH1 ÃÏ…¡×0 ôöö:‹²Á`‰Dªª¢££ªªbhhȉ°Çìw¦ˆt1 ûÝmYB¡‚Á >ô¡Mño4¼8v’Æ%;ÎîyEQyÖ4 ~¿ªªª*b±LÓD4…,˵LÃá04MsäSà÷û¡( "‘H†.¯ªêŒÖ­5”OB¼‹'tÛ8ðØ«°bοG ='‹•™jSSƒŠ¾|ôõõ¡§§ÉdÒñNð ¢vŠ{q¥Ù ?Çã-P¨€ixŠÉ&0óò)RmE£v„ˆ[¼\ë˜Ð4 –e9‹›½½½5‰Ëv–Ñ$åÚ+D~Ðh4]cÅm4ʾ6ªšidʇ¢(΂ S5^Ïl4 ˆ¨4ØÑ 0gÝ“xïŠe/:QfÙ†ÒR‹‚†a8žÙÙÛ…çg>,ËÊX´,é_??ÝüìgÏ㓟|>ºé$7c™8lÎ Y·%™ˆ÷„0Œˆ¢§bAÔ=×4 š¦9‹ " Ų¬Œï‰hZaÌÇß¾};‚Á LÓtêžE£Q 9Þî"¥Eoo¯³0+ÞQ‘HÄñ€O$N1OqçWÅÑ“²S†P(EQœ:+ªªâ’K.©÷í¨/ޤ~ˆôvBF,ËB4E$qÆaøÞÂH"Þ "%(`%%IrÖLÓ„¦ie±X,cn"R|e/ªªŠp8¯eÙúX[[}ôÑzß>Br"¢µr!"OÂá0::: išcÈŒÅbÐu###B pj¤ !‘H ‰ ‰8Nâ=à®e”ËYIÈu¾…¾\ÎMbîŸk[!g(:JBš]z{ÓQ*·M<ŠE矟ñQÓ’/PR„J__úúúêÝÖº!Š<ÎVDØòtS¡R ˜"æ>_~£‚(Îꥸñg:ˆ´^…ðùì…± ç¯ùØiûz{{±xñb$ ÇûN¤1FRÊ6™†ÈÏ03dbäÛ>(;·¢-+bµnÃF"‘¨X®eYv¼»ÅBˆxÎ݈´8"%ž¦iÎø‹Å2Q³÷i9²Óo ìÞ HÆþz€íˆÇãè<»Ý~Ž<òH€âEÈŒÇC‰HŸÇ¡ë:4MÃo,Ä»Þõ_¸óÎßâCîÆþû?‡ûî{š¦aÙ²Ÿã¹çÞ×_ óç«8öØ¡ª&n¹å*ÈòP*"´†ÂÞ{Ÿ„X,ÁÁñk×EŽ¥¦sæDÑÓs?8à˜æ1ˆÅì÷„ßD"RÊø!ã©§úðúëKœjŠbÿL$ì±Ü²lãH[Û9X°  ñ¸¹Ú}5 û{ªjÛ5áFFìm¦iŸ3J·MèY¦ <ñÄg°{÷¾ðûOº€„‡žïÔÅëË—G}t½o-!Ò‘Y"2L8ú‰T\¢Öˆ0€pÆkQä]8 Štx"ÊÄ0 gÌwëÂ… ùœ E¤W®Ïóí#Ú‹|ë‡zh½o !„T¡ãXðÚY¯ao=e$ß{–zPÓ*õÆ4‘òÀ*}á½6Û…VÜ#¤ÚFºÀ5¿NˆÈî•…ÿz•PÒ4[¯‹0ba%;í— ‘H8×.‹Áï÷# 9Æ–t"Ó.Nf'†Ä"¾hq Ç+‡ã”«µÜ`DºQ'ônÇÀ AÓ€®®6üþ÷;1oÞ|ÿû¶ACUí¹E"±ÀéN}µÞ^{›,Û㳈B]²ä Ìû, N4‰ÏgËmиôÒ_C’ìýÃaûCCéˆÔ¡!{[|w}q*"M…îï®i266–Q÷D×u§f‘ÛâN­çFUUÇ‘"EQrÎ9Dª¾\ˆÔ~¹öÉ·–P¨N)#Q!³HÄÖ—^þæËPÞ—ù©X ñ Ó2¨ `bbW]u°nݺŒííííž^tÓ ‘¥¢ëº“yư`õÍõ¹‰tê:"IÒ”B–„TŠ0XVá‚ë“ÜçóÍêE÷µéÁÂát´J>#(z ‰DÇ!I’“I¤H×¶»»‘HÄ™dú|¾Œ"ž^KMHê@ÀXª^‰XÙ+%222Y–sæ¯I’òhB¡B¡cXŒd ,Ëðù|Žçk8ÆÐÐP†§«aNÍÃ0pì±g¡åç`Iï¢ûã“Ë'°é¡31>~‚Á ¢ÿž½sQ=î!ž&ÛàÎ;'°aÛxôÑ/aÇŽ Ž>z=B¡¾óÿÃõ×KX¼ø·xíµ¹¸þú÷âî»ÿ¦)aîÜ‹aY¿ÆÜ¹sñþ÷wcÞ¼Nüþ÷ÿˆ»ïÞ‡¶ sæ|×]·š„ÃË¡ª&LSÆ«¯^ˆpx;$i.½ôX–˜'ìpøx(Šé¡i¶¡âÞ{âúë÷ÄI'ŸÏn{4j0 #mÜi³B!ûw‘]PU]»~ŽåËÛ‰ ð ->Ÿ½¿®Û‘&Â̲ìq] ¹’d÷âz¹#[ERŸ/ý}YNWTÕn®/À#Ü Y†‡Î=rÕ|zýõyõ~4H“Ç(Q"ôT1þZ–åW²£X;::œ¿…nêóùœ5ˆ\é¸D4J6’$åuÔÊ]­q¤Ðeºzލ¯B!³Ó´õI¶>ö&ä 3ß›"í"!^¡dƒÊ•W^‰Ûn»-Ë¢§§W]u±aì]»¶Þý)ˆ!3ŒÒŒ*ÑhÔ)W±B#Œ#:lOUéÜêQoÒt}Oì'ÃÎS¯¤>—Sÿkˆ;¼ÙKi—Hc#&ûÑhþõX˲à÷û§”ž­¸ÓŒÉ²ý> 8…“Ma@‰F£N¡[Y–(41i‘D 1± ƒNÞxzÎÍ>œñÓ„“j£Ôñ@DDɲìȲ0¨ÔšB5ËÜÅc‰¢Ñ(,ËrŒ/¢ð¬0¾üìg[ñæ›÷cÏ=·  áÚçâ†EçÃúëIðù|ˆè,ùÙœý©³9v’¦&µí³1Œt½HÄž0¿ûÝ»ñïÿ¾7ÂaओîÂ_þÒOúEÜtӋضí0>¼ýöíØ¸ñSJਣþ†åËظ±}}{ਣ^Æw¿+áƒ|76l8K–<‚}÷ƒ[nYËZ茉ããóð•¯ÜY^‰P˜˜˜À§?-C×]_ U] s^ (™Q³ñ¸=ÞÊò|êSK0wî}lcˆˆBq‹¶Ï—6„X–}]„ú¢ªº3vF"é]ax …ÒÑ"²lÃ}M%wšOUµ£bÄ6W{ø|éö)Š Ãˆ t}nÎt£ÏŸÏIÅQïE‚bʸÛy$Ûà#Ërƨi@gç»`škÇñÀÁãÍí#ºv"7¨8äÚCðƪ7Ðñ Íê(;Ò<ˆ¨ñÓ0ì1]¤–ìÏDý‘šòƒÜóÏߎ·Þú1¾øÅ¯@–MÜÿýxÇ;¾ï}ïÝX±â@ÜvÛ©X²dŒý+V¬xøÃ…¸ÿþ , X¶lnºi.àÜs߀¢xíµ³pôÑO8"«¶X+6lXé´û[ß²ìÿ¹å̈O·qbîÜ­8óÌ}¤#FÄñ„geö±Ü7îùˆªÚÑ)Ù×7{¾RÈþœïµ–ÝO1ö‹H˜\|ò“¿ÅÑGÓšBÊ#:z¦HÅå6šˆtšÝÝÝ ²çKŸ•­CˆL ¹¢SÔ;ª¥˜fẆ¥böÿXŽã·?õ–,kZÁ„ÒPtw§t!¸ý­ÛñÃá`ÁG¹ª÷ü‘lJ2¨ÜvÛmèéé™bLq³zõjÄãqŒŽŽü^½“áWŒh4ê(}y=±5ØF¶DƒM„m(™L}7žú©ße×g؆Àö¬óøt¤ÎI}ÇŸ:¾˜XY©ýgpFä¶ùfëáULš ‘^£ñx¼,ï±f%Û®$&V¢–Цå^$r{äû|¾) ‰Ïçs … –(ÈéöØu/û=)Iâñ¸S°½ú…šQ,̓aØ  € ¼zà \uUÑýÄbJ³Úì;ó`Y¶çío^{ {ï÷KôHØÖ=ÎéÂ]/ß…kÞw ,;5\81 ^&—’iÚ^a$‡í1'²'Á’dGWÀw¿ûÎ8ã@ <»ïþþë¿ÞÀ›oþûÛû°dÉ<÷œŠgž9;e¸ŸÀµ×‹@ €+nÆQG½ øáÇw¿»€}ì+¯œë´Å=¾ü[øÈGŽ˜ñkrÁ7ãüóÏšòyv”J!„ÜgÕî׈~™Î+¢@)†œd§ù"¤\Âá0LÓD pôEá”Ç ‹Åœgߪ+—Ó¢,ËNšÍlòÕ9æ˜3çx‡Ù—´Œjšý.Ñ[†‘v¾Ô´´Ü‰5ƒ@À6 ‹l" Ý;ºL¤ð3 [Wj±;²Ü4mÃg8œ®¡d§âKSDž+Š‚{ï=Á ½]´OQ€§ž:±Þ·œBªŽž¿îyyÀ‘¶9ÛòÌ ©'e¥ïëëÃÄÄDÆgííí¯wŸr"˶¢bšv.a··Y6º®Ã0ŒŒôº.¡·7åµ¶0®|ÒI@\t%kRA:¥Ëh©ÜÊr$¥àeŸXƒmɶSHÈ4²¨Hm©íÑÔÿIÌ‘HÄñNïîîvŠ R.î\ß¹#>g¥¡ªö¤Ëß=È—dª%K–e躞Ó{_Yw´Aww·ãy¨iâñ¸S4.‰@×u§ˆ§¨ÝÂ…äÆÃ²¥€芎KöÚ«¨ET¤ûhfÖuQÁ–¡¡!´··ãàƒ¿Œ/|á2ìÚõvË»ñ_—¬À’^‚WþåDwG3ô B¼€¨Û!"O‚ÁthÔ~Ö% ؾ=mX±÷ üÇWÐÞþ( ;ýÎêÕ€kˆK/•qÍ5¾üå@+¯Ä;J¼§$Éž; Ê¢‹ïF(t ,î”y²lKØy„\™¦}<±ˆç®÷‹eÊŸø=ÛÂÛ­o»9¸ÓŠˆrñ¹;U¯Û`,ŒÙw_N?}ÀÔû‘ „ªa×¶³ßuóž‡õðÿ(Ã3”i“‰×(É ²bÅ `Æ X±bEÎïÄãq´´´ Ç£Õ E.P8åW8¶ å…U˜r*‡¾ Hûk¤Œšf+D±Q’l…©£ÃÞ>6fŸ¯·7 !O«ìèH{’G·Ö@D±Pá©"¼U¢Ñ´2&ˆ`G© ÁŽT‰"]´¾Àf¬x½,Ë0 ##T»ÐbP8®[ñaâ] Íéu]gÔ4iD­‹PÈ~dž­ K(”ž˜‰b¹†Ü~{?î¸ã)çxñ¸½_,üüçGcÞ¼ï9žâý'<ðÄäÙ0$Èrï{ß«¤?#gÅ|>:::Çw†0¸ˆ”þT¾I’044Ã0 ëº³H­ëº³]¤ObðÌ ¦Â°%2 Gu”RPÈq3“êÇU§(žÙ~æGøàæÍ¸tþN,ܶª¥b,6† DGG‹,’E8åˆßÝN=¢þ–Ø& ¢»„Å2&ÂáxêýÜ ŸÏçD*Š´‘'ŸN-à@fš®ÙøÌ«%ZH„‡}µÕf1n’M†ã€ßüf+n¾ùfÜu×xî¹{±ß~`¯½ÎÂEýÏ>» Š2ß1>ø|À7~Áà#˜œL ÆÆìcF£'95U53]­ÛÀà6(ˆÔY’”i¨ˆÅÒëkî:F«W¿ÿùŸçB– 3ú*_0hvÚ;%5¯¥ˆä›>ªÇ²Ï>¯Ö®„RD$ ìÚµË^' (Ò)¤ ñ%TÚÛÛ±zõj¬Y³«W¯F__Ÿ¡" ÖbíÚµõîO^„_Iº÷ò‡qÖµWB[°áúý@DÌÏÚ|  Hy˜twÛ [YsŒD2½øÜÊŸû= Œ,ÞmÿTÕô§püž‚b¢ æ& ¶ P%`¶Š »F‹ˆZ™!û…0¨,^¼@ÀI$Š]g§1q/†¶Åý7™}ˆâùhä<™õ,Ήdzµ&éT Á`Ú€+¢YÜ@†±t]v¶ @I¾úÕ§ñµ¯}À1¢oB·Xäþä'OÆ7¿9'žøn¨ª ¿?1£(À\`ðq\vÙ7ÐÓc碀ú§Áï÷; ðº®Ãï÷C’$¨ª ]×3굈”câYQ¥éïë…®§¼0M ªEíë\¤ ™HŸÙìÊov÷ÜÏ` ˜êaÀ#çá†o-Ã{v^†Ñy£XX„}ÖïƒbˆÄÐìv ‰¬EªˆD”¤ô‚©;}M$bëœ##i¼x®…‘Þ4MèzðçñÈ#Ï㡇†ßôõ]“NúöÝw_(Š…Å‹÷A$r/EÍÐ!ùN˜r~±&&p¿ ©lùì­ù^)’$ᡇ~]øbXHgq0`;‰¶C"È€´/ú È°*ER%õýÔ¼ì©îï©H×MNcâ<Šë8bžŽÔ>)g§žjv¦ 9uÜìù½ `XøÆÂrBñ$†‘r"±€ïv7âFgð2 ƒë†Ä“”\C¥¿¿­­­ˆÇãX·n]ƶööv¬_¿~ZÑ)Ÿ’:,™L"™L¢½½}ʶrJ£PúÄ:»0ÝËyÿüïïÄyg¾„±ß.° n.· C€Ç1%ÚÃïÏ óu;¹Ãг·¹qÏiB×Ú“X [Ulw¯¯8…*¿˜¶'ÃÑhÚËFÓ€Ðçé3°•²Ò c•P½½½ìÂÔcccèííuòéº *†a@UU'…“(P˜½ð‡áóùœ‚÷" 8F£.®7ùd¨®|ŠEý|Ôz!6ÛÒÑÑH$‚x<î¤%‘eÙ‰¬°, Š¢8Þº®C–e„Ãa(Š]œZì_k@’Òïáeì·ÞÞÌw  éÒiÅwöÝ·o¿=7㞉õtw:E{â>_ÿ:Ër¶‰tCC+q÷Ý?Ç“Oö⟰?Ó4`Ë–ÿß¿¡PÁ 0:úyLL\‚dòǨ qþù—cÿýOÄk¯Ýïÿ°,+µØ§§j»ÔÖ»°–ÔJ>Ý8×3 ¼~ãëÐÕ쨣<‹rBf„lÌæÅ;Ç{V9þÿw>wÑvü2ñKÐszá!lÛ¼ ÿâÿüËÿ‚eË–AÓ4„Ãa'e^©ÞìÄÔR·-„aØïUEIG¥OqMØÝ6ˆ ¯q £_ˆ­Ïg§±³, †a8ï[ÀÖÿ¶oßîQr´%I¢þV&ùj UB©)ÇšzŒõÂ4ÓQhñxºv¨¦¥ë‚=1´ßúÐMøÉO¾Š––¥øõ¯ûpê©÷aï½ß 7ܘut CC2|¾2Ç&Ý9Œm(Ò©ª…‘AøjRŸÅSßõ¥~È©Ï$ØÆñTºnÇÁ0;£ƒØGJ}¦»¾+ $€×ðwÄ@ª ¢»Î‡ Bf„±ÅJí£ m\ç’”øž•j›/Õ¶3¤äê‹Ø'‘>÷ù#çWý¹©'³I> i4j¥Û ãÿCW>„ó^:/c›Xg¡>I¼Æ´ŠÒ¯^½«W¯Æðð°óYkk+:;;§}b±ðÞßßï|688ˆtuuaÓ¦MèïïG___E4Œtú,7–•6^|þó[ñË]b—¿Œ³/·û22’þnøb ôhæþ3±>äNÁä_lvÖ˜? D7’LNÚF#‘Ž'¾\ X{²P…'M֨ř0|ȲŒ±±1†íµ¨iš:MUÂâ ”‹/†,Ë$ÉIëc†StJ,Fûý~Œ9ßãËtæÈ%›@õåÓ½XŸajkÑ_‘6JDO¥¬¥>Ÿº®#:)LDš)QëC<·Š¢8é­Äs,~÷Rš 1ÉÎN òM+JÚkQðÿ°óæe~_w³-дtÊB±°¬ëÂó ç{†!Šöî è!Dæã¿_JyVËNNÿ{î9o¼ñ.ºh¶nÝËòá£ÝŒ[o= Çó Þ÷¾WñÒK/ÕûrW•Zɧ‘J:pÙÙ—!â‹ä5’¸ Õ*ŠBƒ€‹Ð×öÆwž‡eçÌÇ3G¾¦ñ>Ö–ßDïWzñÔwŸÂWú¾‚ó/?Ñh¦i:ãål]m4j¥ÛoG:ÚyñâܹûE}aq¿»}>{<‡ÃÐ4Í™Ä*ŠMÓ°}ûvX–北@þô]¡†LPÈÖëg‚Ùø.©ÇØYKL3]ëH¤¬Žy##n'¦ ::‚xç;LJ‰D iöükddÄåXÌs"À§øÒÆ a"ywý­#–Z \Ñ Pt¤~†`'|©Ÿ½°ÓZ‹ ¶B@ŒÔq#HGyadÎwHG—ò¤“ü€¶Àdêƒ\>QÂØ#Œ:ùûfO[%×OwPª[4ó´àá_>Œ⃥< —äS×3ëè2Û©•n+ôу~uî÷ýÎçbMˆY(ˆ™–AEPI”ÁÁA cÆ X½zuƶ¬]»===ÅÊ•+ÑÓÓS‘ÅÓ²2'â31Pþà»±dÉ·pʼÿÀßÙ#÷AvÑ}l]ÍMµ*ÙÎøEÓ)@ä癩ĄÂl@8å‰äë”§Àr¤Ñ*¬q©ªê¤wpš”š‘ûý~(Šâ¤æíP(äxë‹4a‘HÄñzìíµ‹Z–…X,†p8ìxü‡S3KMÓœE:ŸÏUUgµtµ($›@õåÓ÷8¿ß?ãQñ¸÷]Q” /ú\ƒµxÆ„Báóù¦õ²÷F!¥"Ë2ü~?b±˜cl¬‘HêÝà˽-î¨AvíˆlÄ»ÈíéœëžÛµWìwXGGf;Î9§ Ï?oÿî~GÚÇžë®ûžzê)ìÚõQp@+zè,|ñ‹>Üx㳸é¦Á‘G.©Ûu®&µ–O7š(ðê1¯Bÿ¦^°îA4u¢+š‰=F·`bâgÁ;b°íg–}qžžó4 ‘H8*!à.`ω…w¨µn› Ó´ )€ý¬‰wm(”?­Ž;Z i|>{¥PDý©ªê8È$I*© ªåaöýä‚^eÔsìœ)„¬«jÚ9PDÇãv4š(î+Ò÷I’éêM3ä觺®C×uŒŒ ™RÚXâFD¨°ØFaÈÑ"핈:†‘!aªcŸ8§8›ˆÔp6ÀXVÛza·w騎\LÆ84”¾®y©³Mòÿÿ¿ú6 JxQ>ÝQú„Ìfj©Û:޶Aà·Çýoøm{C8 =å|Mˆ)Ë R ]]]hooG2™Ìø|xx­­­Ž±¦³³®ÈÚ©(é¢ñŸÏž¨ø|@"ñ5üè3c›÷È{ õTÀz2ó3Ÿ¯e«"%ŠHs%¼ÜÝ)Žt]wR~ˆ(‘fA’$tww§\¬T:¢Ì~jšâ-¼–C°½{4¤s¹V€»Ðtæ5Wï~˲  ëUöuUU§¿bq:di„QfllÌ1ÒŒAÓ4H’MÓ`|>ŸS{!‰ ;‹Onƒ”eY|!ç!Ÿl3#Ÿñ8œ•nD¤GµÓ}‰hNZ9!{¥µ7>­v¹¿'~räZ´IUÕºD\Õb­;J×’òÑÜ FÂ0ì&ß%Wà†Aw÷!PU ¯ï)œp‚™2ʆ±t©‰ûî;tæ;Zj-Ÿn ·<òéEüìêµ)€#k|×N%±(¦™ò@ÿì@]¸Ìw^ûÞk8ëkgaþóñ±~ ÿøÏÿÓ4qÅWà°ÃsŒ³îú4³ÑÛÜkÔZ·Í&ÏLÁXj1f÷6ád "*[ž³Ç2F›ÔŠvåÔsì¬" Ѝ…$æµñ¸ý¹ptÛ.% xüÏ·CÿÓéƒØç™}à;̇÷w¾óžø€]·ìBôgQüô¤ŸÝHGc‰…´QC¤µr-r©±n[j!³TU!Û˜"ÎkNã%§S#’™Å+ò)Œ‘¡=–F"vzä&/HHAj©ÛFjÍ@¾ƒï ñíÔ:c<)£ñ,57¨ˆô`­­­ŸŽŽN±h¶¶¶æ`ÝlÛ¶ SBDºn gv1<1IéÝ1Ë¿º¼`¸®ú9û¿›bõr!&¡"µ`LÓö‹"°bFFÍ‘î*  "‹Á4Møý~ç8Âs^UU$F*ÊÅÄ¡‡~ áð<(  þÞNÀ3Jó ¾Ì·É1ËÏöv‘²,chhȹ☪ª¢»»ºn{MƒÁÔý±¯Eoo¯cˆ9ý…ç´¦iŽQHÔv1MÓ‰œÉöªÌ1400€7VµåòÉ&P¾|nܸƒƒƒ9Wwát7"j¤šˆÔ9ªªÂçóÁçó9FÊR …Bèíí­ÈÐ#˲³¿0ú‰¼ôŠ¢Ô4]-& ùîq!Ê1ô(ŠýNÏ{ÇÈÈ$IÂ×¾ö5 âå—_žùŽÖ€jËçŽ;000€žžž¢ï/I”€×÷ÒïhQ¹:«^V4eQõ"hW=¹« 0_Dd¨¿{cÏÌ,¸l¶Ü½Ëï\Žÿ}å8eó)0N1pã×oDì·1§†“®ëÎ;IL4Äéu†‡‡¡iZZZêÝ”ªPkÝÖaØN3"5_9º©ßïwô$Q/,_®êFx¾<…0@¹½ ²FQðF–¢UŠ"ç/Ø-B$ÉÞG„xº-0ÙùÂÄŠ»;” °÷q+†;ï¤n[€Bºmµ ÓóX]·£'„XæÒã„AôÊ+¯Å{ÿv ¶ìoáüGìõ·½pòÏNNG‹˜À\y.–/Ç _|¡pÚ*`FæˆÓ&—Ñ íª!ÉdƒƒƒØ¶m[½›Rê©Ûºq§‚Ï•™R n[šnÛ××7eI¤]À¶…Ûà;Ó—^o“$ÇJœݶæ•|ŒOù¬”±… ¼(ît3Ù躎å,·½ffÈ EDh˜¦éDR†‘QìZ,Ò‹ÅUáÅîö<ÛD ÒÛÛ‹D"]×mÑhº®Ã²,ÇHð¯ÿú:LsâqÀXD°½ÂHG¬P•ú*ÕD’$lß¾@îœÏ’$!‘H8žþÂP"Œ/âzkš–q½EÑßÞÞ^çXÂp¥(Š“·Þ]'C¤ƒiš‡Ã8äCðÚk¯Õû2Í8åÊg[[ºººrnË¥¬Š{UJ‘é iF\…‘Ê1Z£^µE¿ß]בH$ 144Ô4ç²\›H˜@ ½f%î­ðœ1Œëê}fœräsÞ¼yÅC³SëqÒãÀ‚7wNA [F"œ…E9d+¤‰Ç€è­€Ïu니~b;BoTùË_ð—Ö¿  pðúƒq¦t&μáLÜrÕ-ØqǼrÆ+xrΓA4E8†išÎ=Æ[/ÕnrÓÞÞŽÎÎN¼ð õnÊŒ2Sº­Q«JÔÀ*†HŸ …ÇZuÕŽ  Ãî¨XùÊž`‡ÃS]õ…aA ¡P¦áÁïOGÛ™¦}L÷µ‡í󉋬ª™ Œ(Ö(ŽoKo7MÛÕÙç³'$â8î6ˆ\ÄÂ[KUaJ²mƒÆkIÊl—È•)®IödG[²#ŠÄ±ÄÃâÞÏ4p=ßø¶nÝZï»=ãÌ„n[â‘°,ûq·SÓìÛ,Ô×b*¦i:óšÏ}îzÜ}ç±NNMœšwŸO+Ÿn캔îtaÕ:¤šiÿôB·½ÿþû+?˜Ç™1ÝÖ…x½ŠÔxâu T–‰„ÌN¨ÛFè¶¹ ¨ÒŸÀ¯€¡f®ƒìnoGâ§?­w—IÐÕÕ…ûêÇõŒA%—`%“É¢ï÷Ýwß‚“ÎB‹y†a «§«,#B©‹„ápØYÜÑ#º®g,<¹ëEdEvtD>¯ÓXÌöVu窋(BAQ@Û¶ýÆžëññŸL`Ù²7põ5ã0¾9ÆÁ2|oÀ΋«ÀöTj'Dq}Eß³Eq®¸æ²,;Æñw8v"VD= ]”\Äܹì-ËÂO~ò“¦ñ‚ÏG¹òÙÖÖ–÷;á°’ÎHÅUÖäÎ4‘ª\X¾ñŸÿ‰×SUÔ·mÞl{€Š ]uWp^8]î4€—üg,]sH×S£JîóŠbMe,\Š4u"2JÓ´ ƒªHïCÏŒüäº----èééÁºuëêݼ§ù“ΜaÜS9̵-û[æ»ÕµH'ê\ÅãqF§”@ä“£°^Ÿì‰  þûÁðoCès7㪫®Â+¯¼bÅîg;œ= øqàù®çñ³Oþ ǪÇbݺuØÿý‰D ˲½* 9Ѝ–¡¡!O,žµ··ã¸ãŽÃŽ;êÝ”e¦t[A8lA±XfÐA!ÄX#"x‰ÄÌÝD˜¸xæ² ºnÍÀTCFwwÚ16fwP¤Uû”=.ŠŠÜ##iC¢d†•gëÒÂø!çgSÌH¬(öù„‹s®6¥ƒò’ãŠ{ÿîîÌk#®c¡ö|•B†³T©žž £Ù™ Ývº„Ã鸊’)¹ÒâNÝ?œ‘å ‰ØsßJôþ¸x /Œ!aFœ"½zY¨ÛV ÛfáN¡'pÅT`Ê72}¨Û–©Û@ü€²ؤo‚ONëQ[¶lÁ²Ê"Rhkk«úq=cPéììÄàà`Ægããã‹F§:«vd‡®ë_>^Öq% öè>¶mÛ†}.¼ÐYx—e†aL©áä/ÐÉöhË7¹s‘kœëøÂаx±Ž—^:K—^îS#ø§ÛîC2)Á IX¦lÃm×í‹/ /„tìt`"-˜÷œ\K&ÛsZ Ü‹Ôîš0b‘AxûJ’„`0ˆ‘‘hšæ¤Ä€=÷Üûí·_½»8£T[>…ƒ¤Å5Ùx<Ã0‹Å°ëª«ðúo‹û,Às{ÎÇgÎý ÚþõðýøIòûÀ£?Ž6€Q Ø×¾à#°‡aí2°& ´Æ€*€ö$Íðs8( l1€wD€Óéœ/jÀNxÀÓpˆü9’Îé¬ÅÓΑèZDQ Or‘’N¤‹F£Pʼn”*%@fU?uÀ±‡8S¤ã€ÿXøXë[›þŽ+üSÔ›NM¢ÙŒôõ5þ €Äý-ÐuðËñ»_|ì÷yd¦ `PÄëÑ¢‚Ï /š/⦷oÂî×wcÓ›pü‹Ç#<`GanܸŸûÜç Ë2n¸á\y啸å–[ê} f 3¥Û $ÉN”¶ðÇáóùœ\áàS6¢Ø€ßΰ@ypWÎç³,[‡ŽDìϲST ·üÞ^[ŠçªE5-ýÝb΢=•Ž«’Tü\Óı‰ø|U?vNâñ©ž.MÌLËg.Äc/üLÓ¶·¹³¾ ò=’š¦!ãê#¯Æ{}&“i 0œz'ØöÅYtK«Bö} õa¦å3L§Ðº–$¥ªœ,¦¡ª²™ª›‚¥Â¨if¬eŽÿ÷#àU 7!ðA¥§§ãããFOOFGG‘L&qÆgTý\¢`îc?| -T˜ãPUñ̵×bïĺM›°è„ðÎÉI|â{߃ÚÖYT F»é"GCö"r0ho‹Fm;š:™ÊS8n«îÅ/Ļ޵_A<ÜyçqøèGÿßùÎ<üë¿Îƒö&0NÀmj‡´¸÷Ô‡qú“GbïŸî=Õ (;eØìU¡\ki:€8le?‚†ÉwëŽ ©ÓÄï³j˧{­C —â}`ÁxüýG÷ã¢?¶!ðInÏí8qkðزϢõ=­hnCË›-@7ÐßÒ›/ºuEÒÏo¶!Å€=MCÈ[53Ž‹k†€kU{‚m4AÈn—àB¤Sé©ö>#'«À‹ÈSå5‡BñùÓÄ¥=媫e" y×]ø§TÝ$Q?I¤iá6©š|ÆáÑ…Ó¸iòûÃx8óYK-ŒƒA§Ö‚áÕ ‚úÑ}þ—÷†!Å>ë'7£÷Ìýá;{'´m§óç;))B!@ ssÑfµa÷ÀÂÃâÌ¥gQ` c€ü©óOxrÓ“Øô½Mxk¿·0>>Žp8ìgÝŽÂhËwJõ˜IÝVÔMREÄ­Ûq¤*ㇰèˆHÍìIo! IÊ\éÍ·z5]Ëç³_`MàÍè¬)Ô*ò/ó®kþ P˹§ NÛÝâWJæ‘Éà¼ÿ;¿úä¯ðêŸ^Å«°çY€=¿rͳü^(ª-jýø|éy¯ûe%Ýd; ƒ¬aØï™ìÐñ¹8¶È¡æÞ_¤íѵîwiÚóî);b.·ož8~$2u»ˆ ³,»M““™ýèîNŸÈ} qõ‰¤RaY8ñÝï®óyfzüT”©¯»p8=ÑIHnª&›:`œXÀ´“Š8ëmks’ÆÀ3èïïÇš5kÐÕÕ…M›6¡¿¿¿â¢N†1U/Ó4 >ŸGâÈüi­4-í:¤i¶B“#Œ?¬i/¾UÅåÂC¢QÛ˜"”H·b§(öñÄ(.V®ÜÁ-+­”‰sæú¾®çŒp¹æš÷9¿Û-.Âöíá?þclçU_ùÌÜuSï˜û<|æµøõÇŽÁA»ÏÀqû}'þóG|êA|àùàÛê·ˆ è $Hؽ{7öþǽíTj°ûÒ׺ö¶XÇ1a/@«©ï‘.Ž(š/ö5R¿g/X˜Ñe’$ÍúÚÕO‘ý#W±r‘RÍAƒýlXH{Þ™À‹w{?s ^ØsÌ=ªsã-Øqág°ã+;p’|Ò”s.OýË@Ì_J ç–<—®Áâ<»nE\Ëeô±kùÒéšEFêï@H€÷ÇËØ¶p¡í1,ò@HÚC!{!̲ utàþ/xÇ;œ4"²EUU§p›0PY©É£išP¥ñÓ;œT*ŸÖ_h0Þ $"€žšHJ’mìüÀ# 2sï«*,ËrŠXƒA>[UBI¤^0ßZ‰È{·Bûνñu¨;`©±Œ4² @¾~Ï©…€ìwN8Å:§\t ð<øö3߯‡ñaìóê>xõàWqûí·ãôÏ씋î±Î4M'=”XxÏ6ºˆûî6†www;Ï‚$Ióx<Y–‹¯lfB·ìá¡­ˆrQ(ٵɪRóH¬ϤìOwE8—“)Yè04Sò馷7s:vLÓ4t¸š¦áê ®Æ±ÃÇâØ«Ž-iÿŠn©¦e•2åQ*Dº;Yv LNìíÁ`:Òʽ]ÔÊvØpï/æäÂ`’]H2DM¡P(ÓBåN‘—+óƒ,_9wGȉõ|ÛóáªåXôâúº¯‹¢ØéMg._ŽÙÀLÊg.ÙÐu¥'¤ª!›Ö&Àÿ  ^˜ „¯^j|HÍ7ª]W—jS7ƒÊúõë§|Ö×ׇžž$“I´··—Òiš™)›§:ºØ EáU]Ç]É$NuçbŽÇñüð0¶^z)t]‡ªªöÂA.í¸båž|N·j³$ÙJ™È í¬ii¡À– vØ2—SŒË¯î=w>6n™‹îîË¡þ3`ÜÜtß·°ì?ÞÂõ-ÇâšÉpùåßÂõwí¯î³'6n¾þÅÛ‘øá ¸rt.N½h_|zäï[?†ÞÞ98W^ˆ·úßÂ[¿…_û ì5ýü(6Ü¿ÿOúؼy3ŽÑŽÁ®»°ñ7Ñ}G7^Xõæ-™‡ùߟ½_ÙÛNÙ†ßø÷èÛøî]{/NžwrÚè¤sÐ ½W^Äåi™rMn 4L4M5É%›@uä3;µ¹]×íAS‡}ŸÄ=SÌ”|F¿aGÀTíŶ {â”úæ‘Ø²8ï<á8ôØýÌËY€¯üýpÔY+°ï‹§â§?Ý…oÁ¢EÛñÒKçabé·ðÁ=îÃÙg?‡ö%§â¿þöìû«øÅÑ»°×³ŸÂù矆¡¡Ó‰¿„'ÿGŒ½2‰åW‰g_ÅŠÛ?Žo~/î¿ ‹½;ÎÚ?^ýG,Û¹ k÷½§OK¶ð®o¼ Ï~òYHš„%¯/Áxß8ùÙ!xàôpøïÇÎO턦kð©>Ü8ïFœùùˆF£¸zâj¼¹áM¼RJbå€IDATýå·ñ§?ý ùìG°ï»öÅŽïî@ò®$Ž<ýH<õ‡§ÐúåVlû¯m@iõïžJäS9%1Ù (ðÈUàš}®I/,D‘}k÷ÿ É“ ¿ß‘‘‘Ìõ[´zš·)°ë $c©ß£H/ŽÌ²ë¸\ûùì‹rR(Äã% ½Á Ö­[‡Ã_zÉñfÛçøã¡¦®Q Hç¹7Mœ>2â¤f ƒ¸lÁœñÊ+h ‡‘°ñG?‚~ä‘Pš¦aâãÇñK—â°ÃÃØùçãg›6Áçó!#‘H ··¡Pȉ0?-Ë¢TcÊ–Ï0€m@`½­Ãº³åüè­· ï{89k1²,ø|>Ç“ˆ©¢jOèß‚õÕ§ÑûÅejÿ"+[` â”­P—mƒ¹éMÄbmÐuál,C×ecXt>pSè—hyãvüßÃÀä>ïÄ‚·¿w¿ôŒ/º'|ð÷Øñ⓸¦åóXÓ½ÿ {îx'þ6¸þ|Þ˜|èì÷æ~>ÄŽìÀ_–=‰Üý|ù_Æ/í<Œ¬ÁâÏ.Æy‡Ÿ‡§ö| +­•ß{½¸zë!üù]®÷e¬ Õ\Š~°FÈì…~é…px`â<¾ùqüéûBÛ9©â‹b!]Œ½Zj_ öâ¹™úï68ˆ…w=õ»ÛØ !6S¤} "mð‘ÄÂ0@ÚH!òe«©}F6hH©vt§öÿÅ¿ÏõSßrÓ‚=¾ŠˆP¡ˆþú\mrG•ŠßeØFálãKý-ÒÖŠk-Ž+®—èŸp؉¹ŽBîÈkq]L¤(â¼®ãˆ{ ¥¾#ŒPBGRésÝS±Ý}ïY×'ŽÌç"Õ¶£;šºmhZ:ÁÁtêq†á¤öRUªª:5$IJËe‰LÛ âöH,f„u ™Aª-Ÿ" *nC‹[HéˆYȤýwöçnLÓÌ»­Ù)ˆEmc÷EœÛý=á–«V©H“ëÞ×4Mç3EQœß÷ØcsÌ1õ¾5¡RÙ”c@è:@>N,aè{ê)`î\L\}5Bo½Åº±ÄóxΠR)ºn„ªjgÅÊÈ ¤i0M1%5ÓÉž„daTU…¦iŽîûïÞÿôâµkM¶r›­ ôöÚÚ}<ž. KbR0|Sö"b:›l/W^ù výe>¶Ç¯%Udj.üþ•Xºxûmû8–u*¶löÜ8û| ¾~'–´½gõc<ÿüvðÑOªz ض°¬“}P”wcìïÛÑo¾ˆŸ¾¼¡k¯Àãðƒ³NÅ~áÿÆg?/|h_à}K|ˆ¨À©k'phÛ|ço“hùò"h¯òÖK±ÿS»±ü¯ŸÃßþœxägñú¯ã[nÀ7Ïø(Nxðì¼h'þxÔßж­ RÏ~° wMà¡Ã|2ˆí/o)@À—ØZØ ÂÓ2åIúàKâ°«³e2L¹4 üyóf¼ašS)^¥Üùeö5PgÅFÔ ^°âØF0íH“ÃßóžÔyóœXh0)Fô@]v,ËÂk×bÍÎØ¹s'vìØCzz¦&9atÙ9²tÞêZy6`ü¯LåuîPÖ Iv )MÓ0’•¦Â0 ÄãñŒr"¥©!Š‚Ð/)¨¡¦ ŹDøS[P, Ö¾íˆ&ÿ7ÁÔ²0‰cóŸÿŒÿܱK¾‚S‚aüèG'áïølß wÝÿU>»öìÞ}?;l!Ž=v.Nýï?£­mï¼ç‘I{’ "‹AO¹1¨ª üïÿzÛ˜R "—‹È[«(öÄX¤‰¹»»3/æ4ËÚÛO…oló^~Kö¤L–íÃgGwG£éÏ4m^J_s;ž¬ƒÀâ½ãÀ?/†ziºdÌÅ/ÄóÏ_„N¥»ÔN§­ø€õÇ ã^àòë–BÝa_c  =»7¬å{C=÷=-®»î"<ÿ<`š­P·°Çk pãÛópȇÃú:`YK M¾ÿYœúʾõ¾«Þ&ø#ç8iÙ‹ØQc–e!öÉ©!ý–eᮾŸ¹øâÙã§æø[E:uˆÛxiJoJ.EÝqm…×®;•‰&M|÷³{à÷ÿ÷{[ÁtÒá).c œ§E?þ1èÿô§¡úýùñíw„®Ûï IÂ1ï{°~= I85Æ©>Û(+I¼ðBì|î9|å•Wpx,†D"§.¸?ؽg¿÷½xïÿˆîŸÿ‘HÏí܉[Zðð>ûà±çŸG÷Í7ã¿ù œsâñ8†††°äSŸT¯¯]‹×—,ÁÏ/ºÈ©ñ|ðAì‡m…WL N9¥ÞwÔÛè@üÀÔíîí…¤(P?iS¢Ñ(TU͘dD£QD£QD"‘ŒºÙÞ_¤6H’k|Ìžèeå‹wù9æ˜cðå;°kr^4‚ËŸ 8ð݅߀52†…`nOæÍ›‡yßû^*åéG]‡õ»_"xûJÄNÿ#¤ãv¾c3ô$y‹qÚ{’è=éyÄoiƒï”…_‚“ýÏb÷îGœ]ïËèM ¤é©tRÆ2@îH]^·¸)Àæ…›!©"¡ˆý^w?îÅ#±Vê®O6”>NN”¿ ¥«’§\‹ZùÒ°V÷B’ˆ¨‹<"5¦Û{Vüî®1$I’c\¥)ꉴ›€ i‹ÃX¤-ÂŽÅ;‹Æ (JN]±X$R?‰¤ÿyà°vÉZ£㤠óáÀà~/‹~‰Å Y–¡ªªSÓH¤üôøðƒøðÐâ‡ðU|uæoD“Ú"‘/½m6ÂáD<'E‹ïŠ(°ÈU¯°¤i"LÓ®¢ÑôRF¾,qŠR#ŠX ·Ûg:ò/Œn€xç»Æ1æä[ìÏeä$)cmËQ x."ÀçÜkt›Ìn{œòø±ìFàÙg€u_IÃÐTQ³N`G@Ø¿›¦™®ÑЋLo±,^üö·ñËÇC,ƒ,Ë‹FMáõ,Êì~e×ZI$Ò•ÝÊѨ­™ÐJxrr.;「Ïs¥Êu66Vx;v>²›î|]@(Õal‰Dìï¹›žZçEt­½ÝUÑ( F€¿í 54”¶5íøÛ¼ÿúãðá[æ"»dÎ7¿ù æ/9¡žwÔóè“€zöÔÉ¥eYÐ4 c9n|8†¢(x×îÝoĬ"åŠ;s½-ˆ´'²@<ûñÔçKÆâ¾ ÜsÐ=¸ñÞÓùæÅ?Ò©N¢°'î`éyKqÕ§¯²½›w¨€Ž Ù)×|¡tÄQ(’Nà¦í-øÑ·!ÙõÏÎ"ßá7Ý„ÃÀኂ‰;ïÄÐÒ¥ÎâNoo/EA䦛o¥&@~¿Ç|0:qÔu×anO$]w&`¤êZ=|è¡xöõ×ñÒsÏÕûÎyë^@ˆ!n ®÷¹ˆ0r#Ë2‰ÄãIÅÅ­IíqYcåûÊ÷þ’ˆúrv<Æ’ibèäÍ€ñú”ü2ãÇ$à> ´?€%* -Á‰'ŽƒN|µ/Dš*š ¨Çg~Ͳ,t‡»¹ÀX(5––²R©á¢È«Xªö„X,.¹Órˆßãñ¸Y.RS ƒÏçsŒÄb!ÊöÃçó9F±€“Ë6 f[ÔûZ–å´Q¤o’eÙ‰t©Aö~folÞ†‡Æ‚¢(އ®ˆmÇ‹D"Îñu]GK¸Wüê @N/8‰ŸbQ^´?”’sñS|.Ö|>FFF‡ÇáóùpÀ€”†ßo‹C(dÏŠÕÏ‘ˆòù|øáÊâÈ-GÚsTwZ½pj§ìTxnÇ™"HRêsEEWñ¦™öÿI/{øýù&ÀôeF7„QDä³ö@fê(¡G‹÷±0n ãˆ;•®Ci4 Ô–^N´, &“ÎæÞÞÞœëC„x¦2¨F¦ Hÿ-ÂÞ¤s§ž\ÐÝÝßuuáÝïxÇìò¶u›‡ÝŸ%ö,A\ ¡kFöàÛ3 MÃâ–•¸ôcÏÛù) cŠ·l¥ØõZìuâˆkÎ+‚iòÕ9Ìå9d:Z û’Ø.ÂÉocòTEkþüµ¹GŠ èûå¶EŠE R‹w΢†$5vÌuµ(´^­ m<Ev£H/ªeíûöŽ·qŸN¶cêÄÜ­»ˆÈ?°ç{âÌ?™ÊÓ/‹dàEÅ>Èߤ û}ºÇá{ ¹iO¼qȹéš0 È -Ò‡Ðr;œ<ùbQ ¦},EUcÐÐÐPÚó:ˆ%bxrΓNh·ðöýþ÷¿_ï;çiô%€ïÓHW¢O!<™³£SLÓœ¹×Ä›ˆ—w®÷°;wF>/B>/å¡#ã}+ÙrWO£j].Ô,]‡¢(Øó`^pnO½EA<G$q¢„Ó„¨³%¨ªš±‘KÇ/–ZB[–eÇØ,ÃÄõó adN$Î5“ÜIXxÌB¬ìß½`æ®O•ÝŸÏ—®!S’$eÃC¡sMo¾ùæ™~”žp8súä®?–Ã0£`?'ªª¦ë‰Ô{@: ® ˆ¡&Ÿ¯ õ¹ɬ'U62çz@¡ 0·¼ˆu®ëi² ÃpŒòbïzñ™H‡Å:ƒ„dbÝ ø7c)!º`W8×$BSTDšl ÃÀ}¿¸¿ºëWö®ÁRD®/°X,†CÂaré¥ôЦº7e¼ÏEG ª8aé¹°y04ÛZÛaDî›$Šeû|¶æã˪ß"RJ¤Šmg+úb-GÉ2¨óË5_pw)Û¶¤ª€´ˆëúeaú³@B¬µ™¦=ëÔ4¼oŸ} ÜrKÆ×w{.¾°`~øØcö³%ÕWµÏv=dÑå‹ð©ÁO•v,iƒ‰x¨B®•>‘Ï;ë•)VÆ®{wá…»ÞcO6DQßTñd¶‘Å;Â&´,÷>:ÑÔ߉ô¶Sþë̹rä «@º%AÈø¯ýÿ«ÞwÄÓX?ÔïeZ™Å¨ {2!ÍÈ/§òðE£Ž#K´m'|¾¹€nغ“ibëÖ­h]²;î°e3NWÛ:“ãÞÞÌT¡­@†Ö›bbÏ=H7=þ8زÛÇÆpÔQGáúë¯Ç×׬AT× …жu+–<°q#$IB pŒ î(6‘ÎH×u'ŠD¤ Ñ"*CD…»ß3¡PþüFÂ"~Šó‹ýÅ"—;ÍU¥”c¸Êi¨QP0Z¾(3´î­§î/)L8l/¶ºç ¢Žg.4Ms¢•b±ØÔÈ­ ÒÆ“*©½e©ÏH¯3“ˆè6) Œ¬îEo±H.Ð4Í1à C±0 c°Hó'Œ’Â9HD,¸#äĺƒ»ž…8ž8Žø)Rç¼Ó²Eøw–;…´, ccCزeOhÚï‡M”™M½¹vä«{S¬ŽÀ–¤t ñ·ÒÛÄq #­N¹÷{ë­¦Z^1âÿ øŽ¸ð_(Šm<5.úý~THÃÐ4/Öäa!n&À<ñû'pÛ›·a~dþ.¹"BóÁ‘:¹)?.´UEÌdù`83ƒ\“PñY4š»´¦¥‹ó‹{”ªúSÀoØçvïï÷Ûß÷ùÒ#c™š•¢±x½/~ƒ¢±O§›xÜ©ög†BXå÷cÄu϶.Y‚]]øV±Ò¤2d`qtqéé^Š­­äy].º|Þ·è}éí’ë»âgv4o*º%g±_ 3ç~êUÐvsº¿Ò ¼„tí€ |ôSkw]‘-ⵘiLq{܉É;'…„Ô@|Ó÷ .ž}ÁePFbPRjh’d/Îù|™‹:îßÅ*€À&R”Ȧ‰¸¦ADƒ‡išðÞ÷¾m?lÛ†SÎ>°,$Äqn¸¤œ‹ïnO\±],B‰tTâ}’m!õC’¤ôý%yyýõyÐõ©µÛse'1 Ñh–eadd$¿—ºW2mU)ÒÍ];Hëâ=#¶‰ú³ß]€ZÔ5iîBÖÙFS÷~âý&"•ÅùÝÑmâ3Ã0Cˆ¨‡3"íÄyÅþb»0çŠ&“$)#õ“8¿ˆZpÿQa"NwDÿD %NÝ#’Ó,¯~P<‡®ëÎý>üðÏà•WÞo|ã=°¬Ì‰Ž,ÛTÓLŸÇ4ÓîiÚ¢$n•ûwªÚß‹ýâ˜ba^dá íïD"ö1ÜYùDÍ—Ô£†HÄ6&¹q&ì¥âû¢mºnÿ…ÒýÐuûØ’dûÂöö¦#~DšCñÈ ¥—]DêCÑNá/«ªö’Žø¾ËÃi›8wv¿ mÄbéc¦’¥T|­Ä9ÝÇ5šÅ9³q ûãÀ§ùÐÎ6L@ñ)ÄÞý_ÀUvŽ~­£##=)眤Q˜3999YïFTªU«°~ýz{VGÚóY ùï¿ ”åœ EgJÊ¡p8¿‹ñ–eØñx:²%Û #’§ÊòÔ”cÁ`ú²l¾îgA×Ó#7¹¯ÐxlüÑðæ¿ýzzzê}E<Åðð0†‡‡qüH?´Ý@ì2· O=áíiYn]µ ^xaÓ{È‘ê2¸z'þõDÈ#YÊ×eaüéÖ‡pÊc·”wà&FŒ‡cÏdnëèè@"‘pò»kšFO!RuÄÑßß_ï¦xŽU«VáOZ ¾V,\躎p8Œ¡¡¡’'œîhìÞÞ^ 9ÞÖÙ‹y„ÀÀÀzzz¨Ûf1<<Œo}ëM,[vJÁ©¢X¬‹òE +Ç‘é0RCÜQÂXáNÁ'¢+Äû" ¡££###ƒˆÅbÎçîzE‘H~¿¡PȉÖ?EÔ«8o.£„ˆ¸ëOi㌈ªÒ4-#š£™ßgB‡#™¬Zµ Çc_—Rí4MƒžªÅ¨ªjÆB®eÙKB>Ÿ½ï¶…º!â1s/¼Ë²½ŸøL$Ûp#Rй£!²K‰ýÄ„ûw7B,Ü‘ùÔ¿ß6”“ˆÅ½,R ü~ûg#ùYR·ÍóÞ2Žc¶blÛ 5îƒA$ '%&lÈL0ºmÓD¨D¿VcŠWs(Êé='r`æTpiLi DôI¡IŠ»N6±˜­!…BS¥¶1F–íŸb›x¹K’cTÙ±x1ö­÷µð0Æ^€üž©Ÿkšæä ×4 š¦aèW¿ªwsIÒ÷Ù>;2%›PñÊn­wó¼‹ÈolÎá/&•îÅZÕf „¤ Ù‹¢z!cŠX 5M3#M$IŽ—¼0’–š¶„bó¡mħO;%]3N‚­ƒ¤L8ýüäã?Á™Çœ‰Ÿöscc;úÅSß ÀŽH1Rûë(»Žˆì† ŽQĽP,"8Ä6á…oY–“žÊmœpG‘(Š‚P(EQœZEÂSèñâó@ 锯¨ðH±ÜÌ@NƒˆÛà"t“ì”dv£ëÀÐ?‘*lyÓà8ÜnýÞVlݺ]ûuá”ŧ 6z‘Nq¬’‘ÊžT%ua)‘]F‰\Ëî5áRÖ‡s ë¥#;;{!cI%ƉZÛ(EÉ^ÒdÄÈ5mŽüˆºœt°„4 McP‘Û0%-ˆ@*Ât‚Á`IÊirÜÚO¶öQHãpEÃ<80úïåǧǀÕghw>Þ"Ô]QzÀ“ò¡ÞUÖw!vèï|Ëù,:²(Ò”pÁ•Ú“k>F0ÙˆÔ8baT8 ‰ú$ôö#¤:üÌÁ·]×Í„m I9ô âGýÿ»ì!)Rz1WBzAÖ@º½ðHϣǘ¦éDjˆX"zD–e§.‡Hq%~ C‰xˆÈ aHÉ™zÌ4í÷„Ë‘B¼7²ëe“ý=BêEBð ¤ë;Šÿ*L&ñ¥| 讌\‰cÛŽM3EmF vJa!Û"òDÈ0Rß #ÓAÚˆãþ] Þ"“ŠÛÈcå8†™ú=žu~9u-õ!ÝÈL‘HÓBºî¤’Õ¦@ª"mÖì:Nî:—ºë8RêúøS¿Ç\í”\í5SmV]ýs¿j"° WJªºë¢’k¿ …³Ž!Ú‡“úÑ÷"äºpGFÚÈæsõg$ÕOq-õ_¼¿‡\Çö!ý>OqôÛGcøŒaü¿¬Ë\§Ê.Äãñ çB¦0¨Xw1e0Ÿpf –eá;—_Ž?]{­ŸèÎ_Jc !3ÏÁÏŒà‹2§¦)º®Ã4MÇ{Í0 gÂG©º±ÆÞg;óQ;E–eÇ[ˆ9l ñÑhº®g8†Ã0œ:bÑÕ=¥!…ê²Ï®W³¢pVBuPBjq`à§ü)¤xÔžHU.NÕ€âhYv>EÁÆÛoGÛováÍ} /®\‰h4Š@ €½¯¸‡ ß–-Ørçxp|ûþÇÀçó9ÅÉî?–eGå»e>Ut!½½PdÙŽÐw#riZ:E2!JS"¾,ËrÆÐ‚)øÜ¾8†’ã3À^L2k7º3Ì+Ge¥Ž—½vìÞ/_w0V®äý°c©†}>á|¬ªö±c° 'À÷]–Ub®ÎZ©cˆW‡`HÉtF5 @¶Ò×P’€2õnÕˆœ–cö÷Ü×d$ë}¤ë™idäh«ÛÑ:W[-ËõɶąaS†\×Lœ+!#rÚ¸$Šõ(©s*ö9~ =¥ Z+ ¥7·#¢(ÔYIÃÑ•è矇üÔuÓâT‚Á ._½ûÞwð‹_`ÛæÍØµ};B¿þuæÎápº ºH^ÙØeeñ ‡>½Öže|&ò0†ÁH12³È2F—,Á™õn‡G1’ó |v!€ôdS:ãñ8†††hè$Ä„Ãa躎D"áx©‹ú’$1ŠŒ2±h °h Ø ?{PU5-‹n™Ôu Ux]+—$ ÚÚ0ÿ©§pÂÇ?޶Ë/‡ßïGÀ²œ”[_r X²¸OžÏsWU3‹8¸?…©EDû€t*eB™xØ6¦Š˜<ßÖ†“ï¾>ŸÏCMÓ®°îÆçK§7ŒÜÕÊݲO­Š®fYP²Ï¡(™ï³„ó„ÃSå:Qà<Š’2–¤ &€p*<Ã]EÞ½hðç( »Œ²œ™2]Ôœu#*Ö De{E±ß3²<õ}•} UjP† Q &{]¤d×Å}ï{?qÑŽ\mµœýtæ‘RQ3fºª½èC¯ HræyDuzI²×Ŭh& ¼ S·5Ãçó¥Ó¿7RÁBàAƒJ2™D2™D{{;ÚÛÛKÚÇ||+|_=-`{À[–… þßÿsB£ë×Û CÙÞ¶‘k¦R"Ó•Ï­ÝÊ¡i—h4êxφÁ4_df‘e<|è¡õnE͘®|šoî _ß2p ÉŠÔ˜ N ©åè¶‚`0H$NMUUéÉGH•˜®|Žï¿?*8l†Sx=»†‡0|*Š‚x*êÄ0 œÑŸÙ I'ò“Å_¬À‚œåž+ê”ó`âa¦=~F"Žñ069‰{~û[ ¥#7¥ðÂw±í@á­‚X,eøRÏSŠlŠc˜fÚ€™æ1~Ud[–‹'²ÿçC’Š£”:HÅÜ]iÙ ¶5g‘Š R¦Fòe£ª³>š¯,ÝöVú/A,v»DÕW^‰¶¶6® ‘†dz7ÀÍàà V®\‰uëÖaåÊ•,ºÏ¯ìム\aS„×{$A8†eYNq#¦.!¤|Ê‘ÏÍûŒC:®ãf,C0„eYÌ‘IH•(G>­NN9’Ù9Úûúúœ¼ë„êPŽl Â)ïÕP(äV|>)„TJäSS††† ë:Âá0âñ8z{{\ð²,#‰@UÕ¼ÆBÈTÊ–OYFPÓpÇ“Oâû÷Þ[Ÿùf­å\¤ëãû…Ô€reÓüyæÂNö ?ÿùÏaY³"†ÄS*X»v-zzz0::Š•+W¢§§§°Åó…ƒ º;eI0tkæŽ&¤Z”#Ÿ-“ñ•¯ãÈæ…^ˆp8ŒX,ÆA“*RŽ|†¾>'„óÏ?‰D‚‹=„T‘²t[Ø^{·ß~;–/_!Õ¥\ùtSDd§(¯(Ê”hBÈô)W>…B±ôA"u¦{1Wü. ¢†a@UU'ÚLüßkN¢®‘¢(ˆÇãŽso p"KE­Îﺮ;ßá>q„B!§Ž”HedYvêʼnßUUµ3Ѥ¾[É>Â(^éy^ýu¼ôÒKõ§\ÙÔ˜eåŸñx𦡣£†a ££ÐÛÛ Ã0Faš& Àiš¿‹òzª‡ø[l?Åg@Úã^ Þªª:E·%Ir~—eªªB’$gŒWUÛ¶mÃ^{í•ñ½bûˆ¿½¶0üáã‚ .À‹/¾Xïî8x},i„ùÕlÃ<¡2:::Å¢ÙÚÚŠd2Yp¿—^zÇß‚––H’„-[¶`ùòå¸óÎ;qçwÖ»[%³qãFÜwß}hkk«wS*æÖ[o­wjÖ7â¹çžÃ‘GYïæÎ(åÈçÃ?ŒD"ƒ:ªªbáÂ… '—‚fy¦gÓ{æå—_Æ#<‚­ûí×ôEéË‘Ï_|ûï¿?öÙgœsÎ9X¸paC*A[·nÅÖ­[‹ê @³¼gJ¹'[·nÅæÍ›ñŽw¼£ÞÍQÊÕmŸxâ pÀ¸çž{0þü†”M`v9B)÷„ºm~ùüûßÿŽ[o½{ì±$IÂé§ŸŽŸüä'€x Þ]š³é™nJÕm·lÙRï¦Î8åÈç“O>‰»ï¾’$áŽ;îÀ믿ŽÃ; ŸûÜçpçwâsŸûpúé§ãÎ;ïÄé§ŸîÈ­[~xàpÀ¸ùæ›qÀ``` ãïR÷àÜ«Bï‡ìã =êæ›o.yŸ\mòÂ>?þxIïÈrÎ#Öj±¸'Ë—/Ï»uÛºí_ÿö4^šóÎ9göÛo?$“I¼ë]ïržzãõ±¤æ¼^Ö+6oÞŒG}´êº­g *ãããS>+¥¸Ñ?ýÓ?á¯ý+>ùÉOb¿ýö«w7ÊFXx›féK)ýX´hvìØÑPiåPŽ|~üãÇ[o½…=÷ÜgœqF½»P³é™nŠõåµ×^C{{;víÚUï¦Î8åÈç¾ð<ÿüóxÇ;Þw¾óõîAsÉg1þþ÷¿£££]]]õnÊŒR®në÷ûÑÚÚŠãŽ;®Þ]¨ˆfz¦›¥/ÔmÓ”#Ÿ"W[[–.]Zï.TÄlz¦…RuÛ\Ïn³QŽ|^tÑExë­·pàâÀ¬wšK>‹Aݶ0+WŠûî»_P°lÙ²zwc ³éY)¼| ÛÚÚpÌ1ÇT]·õŒA¥µµuÊgÉd÷ûÒ—¾T煉YŒ—_Õ¤ù<î¸ãðío»ÞM'¤é)G>W­ZUïfÒôP·%uÛüòyØa‡¡¿¿¿ÞM'¤é¡nKˆ7¡nK‘™Òm=SC¥³³sJøÒøøxIÖNBÈÌBù$Ä»P> ñ&”MB¼ å“ïBù$Ä›P6 IãƒJOOÆÇÇbF£££H&“ Ÿ*ˆf€òIˆw¡|âM(›„xÊ'!Þ…òIˆ7¡l’Æ3)¿ ¿¿kÖ¬AWW6mÚ„þþ~´´´Ô»Y„P> ñ2”OB¼ e“ïBù$Ä»P> ñ&”MBlæLNNNÖ»n’É$’É$ÚÛÛ6FˆÇ |â](Ÿ„xÊ&!Þ…òIˆw¡|âM(›„xРB!„B!„B!„â5ù¬TþjÝ·býÈw¼ÖF Q®I£ßûrÇÎbÛ›eì¬W_H匎ŽbÞ¼yU»×µ~Äù&&&pÐAUµ­µèK)ãe{{û´Ûæ¥{DÊ#—luï ɧ×uÛRÆýrä³Þý"Õ¡ùôÒ½¯d쬴ŸÕ \ùôz¿HqfR?ª6ÕÖ±«ÅÄÄ Øݹ¡™lPnºé¦ÉîîîÉ‹/¾x²»»{ò¦›nªw“ròùÏ~ò¨£ŽÊøï½÷–Ü/ôóꫯž¼úê«§|^¨m^íW®¾Tr¼p¼F#]“f¸÷¹žéJå¯}Ë÷ž)t¼Ø¯ÓHפÑï}9cg±íÍ2vÖ³/¤2ž~úéÉîîîªÝëZ?W_}µs¾ÓN;mòŠ+®¨Z[kÕ—\ò˜Ý¯}ìc“ããã yHyä’ÍÉÉÆº÷…ä³tÛ|ã~%òé…~‘Ê)G>½tï+;+íg5û0]ùl„~‘Â̤~Tmª­cW‹M›6͘îÜè4¬AÅý mÚ´iò¨£Žš|úé§ëݬ)\|ñÅSÎéô£žý¼é¦›œ“\ƒO¡¶y­_…úRÉ=j”ç°–4Ò5iä{_è™®TþjÙ·bï™B÷ÈKýhéš4꽯dì,¶½YÆÎzô…T1!rßûFy¦Ÿ~úéŒãOuÔQ“›6mªJ[gº/ùäQôËÝÓN;m27Ü="å“K6''çÞ“O/ë¶…ÆÊJå³ÞïRÊ‘O¯ÜûJÇÎJûY)•ȧ—ûEŠ3ÓúQµ©¶Ž]-Ü×l|||ò´ÓN›¼í¶ÛJjC³ËACÖPFkk+zzzèììÄððp½›–³­¹ÂÊJéG½ûÙÕÕ…¾¾>tvvN«í^ìW±¾”sê}¼H£]“F¾÷ùžéJå¯Ö}+$›…î‘×úÑ4Ú5iÔ{_îØYl{³Œ^¸G¤<ÐÙÙ‰®®.ç³Fz¦'&&¤Ó ´´´ ½½ããã·µ}É'Éd===Ÿ¯X±¢¤~yí‘òÈ%›@cÝûBòéuݶÐXY‰|Ö»_¤:”#Ÿ^º÷•Œ•ö³”+Ÿ^ï)ÎLêGÕ¦Ú:vµÆøø8V¯^ À–]×±bÅŠ¢m˜ r°W½P£££S&ñ­­­H&“õnZbð¹òÊ+1<<Œ––ô÷÷£¯¯¯¤~Ô»ŸâÅ“+Ï]¡¶MLLx®_ùúRÉ=*ÖÏÙH½ŸÙéÐè÷>ß3]é{¥Ö÷°Ð{¦Ð=òZ?Fº&|ïË;‹m¯Ç{g&ÆÎR¶ï1::Š 6àæ›oÆš5k2>o”gº³³}}}¸âŠ+ÐÓÓãÅDÏëºm>yìééqúØò¹aÃgòÛH÷ˆLŸ|²)¶5ʽ/$ŸëÖ­ó´n[hܯD>½ðÞ!•Q®|zéÞW2vVÚÏjµ_7›Bòéõ~‘â̤~TMfBÇ®Éd]]]Ć ÐÒÒ‚¾¾¾ªèÎÍ@CF¨‹¢›|^’õDXDW¯^G}k×®ÅÀÀ€c‘+Ö/÷³PÛ©_•Ü#/õÃ+4Ò5iÖ{_©üy©o…îQ#õÃ+4Ò5iÖ{_IÛ½Ô¯fÖoÈT&&&°fͬ]»---Ûí™niiq “fO›A·Ý°aV®\‰žžÇÀÙh÷ˆ”N!ÙïÞç“ÏfÑm§+ŸÒ/’›JäÓk÷¾Ü±³Ò~Ö’lùl–~›jëGÕb¦tìj‘L&h“Õ«W£½½«V­rŒ"³]Ò ’˺ìE+Wgg'Ö¯_ïXïzzzpÆg8 Åúáå~j[#õ«’{ä¥~x…Fº&Ízï+•?/õ­Ð=j¤~x…Fº&Ízï+i»—úÕÌú ™J<Ggg§“c||£££m¨gZx×Ý|óÍèïï‡®ëØ´iÖ­[Wq[ëýLOLL`ÕªUÀUW]…«®ºªä¶yé‘éQH6ƺ÷…ä³ÑuÛråÓëý"…©D>½tï+;+íg-È'ŸÞ/b3SúQµ˜)»š´··cíÚµèééq2 mÃlƒ†4¨tvvN¹ãããž³v ¾·Õ±X?¼ÜÏBmk¤~Ur¼Ô¯ÐHפYï}¥ò祾ºGÔ¯ÐHפYï}%m÷R¿šY¿!¹™˜˜Àºuë°nÝ:$“IÜvÛm¸í¶Ûê™N&“hooÏxV{zzºFÖm/¾øb´··C×õŒô¥´ÍK÷ˆLŸ|² 4Ö½/$Ÿ®Û–+Ÿ^ï)N¹òé¥{_ÉØYi?kA>ùlô~›™ÒªÉLèØÕ¢§§gJäL3¬™U¾Ÿº»»'ï½÷ÞÉÉÉÉÉM›6MvwwOŽ×»YÜtÓM“§všÓ®ñññÉÓN;mò¦›n*¹^èçÅ_½Ð/R¦+Ÿ^¹÷•Ž•ö³š×ºòÙý"ù™iýh&¨¦Ž] ÆÇÇ'»»»'7mÚäü݈kf3EC¥€þþ~¬Y³]]]Ø´iúûûs榬'¢xîÊ•+ÑÞÞŽM›6¡¯¯ÏÉÙWJ?¼ÜÏBmk”~Uz¼Ò/Ñ(פ™ï}¥ò畾»GÒ/Ñ(פ™ï}%m÷J¿š]¿!Ó£Qžé+V`xx§vºººL&ÑÙÙé'­´­õz¦“É$’É$V­Z•ñùêÕ«ÑßßßP÷ˆTŸF¹÷Åä³QuÛJåÓ«ý"Õ¡î}¥cg¥ýœIŠÉg£ö‹ØÌ´~T êݾ––ô÷÷;õgDÍfX3«s&'''ë݈rÒÞÞîé°¡ÑÑQ'´)W;‹õÃËý,Ô¶FêW%÷ÈKýð tMšõÞW*^ê[¡{ÔHýð tMšõÞWÒv/õ«™õ2=é™çkmmEgggUÛêågº‘î©.tï Ég3é¶Ói[#÷‹§Qî}%cg¥ý¬'ÍÚ/’ÆKræÕöͤîÜÈ4´A…B!„B!„B!¤4dQzB!„B!„B!„ZBƒ !„B!„B!„BHhP!„B!„B!„B) *„B!„B!„B!E A…B!„B!„B!¤4¨B!„B!„B!„B!„B!„B!„"РB!„B!„B!„RT!„B!„B!„BŠ@ƒ !„B!„B!„BHhP!„B!„B!„B) *„B!„B!„B!E A…B!„B!„B!¤4¨B!„B!„B!„B!„B!„B!„"РB!„B!„B!„RT!„B!„B!„BŠ@ƒ !„B!„B!„BHhP!„B!„B!„B) *„B!„B!„B!E A…B!„B!„B!¤4¨B!„B!„B!„B!„B!„B!„"РB!„B!„B!„RT!„B!„B!„BŠ@ƒ !„B!„B!„BHhP!„B!„B!„B) *„B!„B!„B!E A…B!„B!„B!¤4¨B!„B!„B!„B!„B!„B!„"РB!„B!„B!„RT!„B!„B!„BŠ@ƒ !„B!„B!„BHhP!„B!„B!„B)¬2¨Äãqèº^ïfX–]×aFUŽgš&âñx½»E¦å³ù0M3§\S>½åqvPª,Z–Ó4óC×õ¼ÛÉÌBYm>*;)«Þ‚òé]ª9÷¬t,¥lÖʪw)WV9m|(—³‡F•ËYePÑ4­a²···jƯa:::Fá÷û +>¦išÐ4­Þ]#Ó€òÙ\„Ãatwwç”kʧ÷¡<ÎJ•Åh4šSÉÇ㎜www7¤"ÜèPV›‹JÇNʪ·hTùlvÙ¬öܳ’±”²é UVæ–×re•óÐæ€r9{hT¹œU•FF×uX–UïfÌ~¿¡P‰D###Ðu½!…‰Ì^šY>ËÁ4MD£QŒŒŒ8rÇ©Tš@y¬ñx~¿Ñh4çöp8Œ¡¡!$ $ ƒAzØ’’¡¬fRÉØIY%Õ¤Ùe³ÖsÏBòIÙ$•ÒÌòZެrJ¼@3Ë%IÓÔMÓÐÑÑ9sæ  Ny …Å{ñâŇÇÃ΋Ö0 øý~Ì™3ÝÝÝ/îÞÞ^Äãq,^¼‹/F<G8ÆâÅ‹ÑÑÑ‘aEÎw󇟆a8Çt·½ Ã@ww7æÌ™¿ßŸ1¨äÛVhŸB”Úoñ¢ …BI’066ŸÏ7åXîþ†áÜ3qÌB=îû;ýÈÌQH> ɦ؞K>k-›@sËg)ò’«¿â^J’äü”e9¯RAù¬?”ÇLÊ‘¹zËc¾¾NG®Ä÷Š¢ @Q”)ßÕu’$AUU绊¢4¬'Y£0² ”þ6ЬÚVoYu«c'@Yõ Í0–f˦û¸Í0–›{Ör,¥lÖ®eâű´Üu"ÎCÊe&^”Ëruܦ]¿lRÆÆÆ&LF"‘ÉÉÉÉÉP(4 `2 MNNNNnß¾}R’¤É¡¡¡ÉíÛ·OI“‰DÂÙ&öM$“’$MŽMNNNf'‰L9ªªN;¦óÝBˆ¶‰ßÀäöíÛ'GFF&%Ir¶º¢¿âܲ,ÜVhŸRÚ[J¿c±Ø¤ªªÎOŸÏ7¥/¹úF3>÷Hì›H$œsIEQœïÚÔ†BòYH6''' Êg=dS«å³yÉ×ß@ 0éóù&c±Ø¤Ïç˸ž”OoAyœz=¦+s^Ç|}-´_>YÌFUU§‚H$2å¾äú©3%«““¥?‡ «…¶yAV õ·œ±Ó eµ~4ÓXên›ø»YÆÒbsÏZŽ¥”ÍúÀu¢©×Ëci¹ëDœ‡6&”Ë©×ËrY®ŽÛ¬ë·MkP …B“@ ã3Y–3·0lß¾Ýyèc±Ø¤¢(ûg_·JÜ`÷ßÙYêw ‘-n%MUÕ¢T$™ôù|S®Q¡m…ö)¥½¥ô[¼(Å)þ/¿|ýF£“’$å½çâ@`R’$g!€ùö#µ¡|’ÍÉÉÉ‚òYÙÇjFù,E^òõW àâ§{ʧ· p(¯Ž¥å®qÚ˜P.3ñª\–«ã6ëúmÓ¦ü2 à óȲìünYVFØ­û»¦iÂ0 Ì™3Çùï©°¢¬ö–‚eYý€H$Rp[¡}ª‰,Ë‚ªªˆD"S®w®þf‡MK’”‘sÖŽçu+¶™y Ég!Ù(Ÿb[­ä³yÉîï-·ÜMÓ022‚H$‚±±1†‘‘;šòé(™”#s^‘Ç|}-´_>Y,çºRVgÊj&;K“WÊjm |fâå±´ØÜ³Vc)e³>p(/¥å¬qÚ˜P.3ñ²\–£ã–²_#ÊeÓTråÎ&ßM¹L'íçÿL<Œõ¤P¡$]×±sçÎiíSªªN¶R_6Ù÷/»]Š¢ ‹! eä`,¶™yŠÉg¡$å³vò ”'/Ï=÷dYÎeUU3ö¥|zÊcqÊ‘9¯Èc±ýòÉb1EÉyÜlEžTÊjqfëØYÊjm |Ç céLÍ=)›׉Šã…±´\Yå<´1¡\Ç r ÌÌ|hL¹lZƒŠ,ˈÇãÎÅ6 #Ãâåóù2®ìm†a8V1˲ÐÑÑ‘QبÑPU5ãz躿ßï¼|rmû‡ø‡¼ûT ¡Hº¯µ¦i%)’¦i:÷Mì'Šúé7 A–eÇ+¡Ø~dæ)$Ÿ…dSl§|ÖF>òä卣ނišNÛÄ~î¶Q>½å1“rd® W“rå£Ð~ùd±”ëdYVF‘BÓ43Š…’êBYÍ„cgiòJY­ ”ÏL¼:–ÎÔÜ“²Ù8p(¯Ž¥åÊ*ç¡ å2¯Ê%03óQ 1år¯z7`¦0 ÎËØ­œ(ŠŸÏ‡îînȲœaå’e¡P½½½Î¾ªªÖU¹‘eáp±X¬¬ýEûÅõ0 Ã±ØæÛVhŸj!I"‘º»»¡ªªs­@I×$ B–e˜¦éÜ·\ˆs,]ºtZû‘™¡|’M€òYKù}›®¼œrÊ)ضm[ÆýU…òéQ(™”#s^–ÇBûe/ê Yôù|%yŠE"øýþŒ>W[i'i(«™pì,]^)«3O3ɧ[6K ráÕ±t&æž•Œ¥”ÍÚÃu¢L¼:––+«œ‡6&”ËL¼*—¢oÕœæ¢QärNªhLÓb†“oÏ­œX–å„Y–UU1gÎlß¾Ýùžiš0M’$•­LV Ñ–ì~”{=dYžbÝÏ·­Ð>Õî_©×Z×uD£Q$ èº>ãû‘™!—|–"›å³”}*¥Ry©•\“ê@yÌ}=¦#s^”Ç™–+q½gRG ™PVs_Ù:vN÷¸”Õ™¥ä³Z²é¾^K³ûè…±”²Y¸N”ûzxe,Íî硳ÊeîëṬõ|ÔërÙô•|˜¦‰îîn AQD£Q†D"Qóv*˜¤ªjÉáSÕ8N-Û\ nÁªÅ~¤vxE6E[*}Ök-/Õ<_­å…òé=(õm¯Ž{¤Í&«ÕU6+r={ðмÎö±´ÖPƽ å²þmj?õº\6mʯbȲŒX,æäe“eCCC5o‡ÈW¨µ<Ž×ÎU¨ åX&½fÑ$SñŠlÕyÖk-/Õ<_­å…òé=(õmoöñ8î‘|4›¬Vó8µ>eŽdÓlòÙ¨²Yi;(׳¯ÈëlKk eÜÛP.ëßfq¬ZÎG½.—³6B…B!„B!„B!¤Tö¨w!„B!„B!„B¼ *„B!„B!„B!E A…B!„B!„B!¤4¨B!„B!„B!„aϯýë_¯õI'&&`&&&pÐAelK&“´¶¶Öûú2«($›å“zBù$Ä»P·%Ä›pì$Ä»P> ñ.Ôm )LÍ *£££X¹r%žyæ â‰'žÀ‡>ô!Ààà Ö¬Yƒgžy×]wZ[[ÑÕÕUïkDȬ l”OBê å“ïBÝ–o±“ïBù$Ä»P·%¤8s&'''kyBUUÑ×ׇիWcbb+W®D?V¬XO<k×®EOO#Àº®£½½=ïñ.¸àtww×û:VÌË/¿Œ¹sçbŸ}ö©wS*æÅ_ÄPïfÔ¬[·nÅÇ?þq,_¾¼ÞM®ˆB² `ÚòyÓM7áü#Ž8âˆzw­bšå™žï™Í›7ãú믯ws+¦Úò¹zõj}ôÑõîVżñÆصköÛo¿z7¥bšå=Sê=yùå—ÑÞÞŽÏ|æ3õnrÅT[·ýÌg>ƒcŽ9¦Þݪ˜Ù8æxRï uÛÜò¹qãFüò—¿D[[[½»V1³í™n¨ÛV&Ÿ_þò—qðÁ×»[CÝÖ{P·m~ÝÖëcI#¼¼.ï3¡ÛîUË c||«W¯´´´@×ug[kk+zzzèììÄðð0úúúòó±ÇÃç?ÿùZvcFÐ4 8î¸ãêÝ”ŠÀ9çœSïfÔ¬š¦abb¢ÞÍ­ˆB²)¶OW>Ÿyæ<ýôÓøÔ§>UïîUL³<Ó³ñ=sï½÷Ö»©3òù—¿ü«V­ªw×*æá‡Æèè(N?ýôz7¥bšå=Sê=yøá‡‘L&ëÝÜŠ™ Ýö¥—^röidfã˜ãuJ½'Ôms˧¸&Í Ÿ³í™n¨ÛV&ŸO=õ>ö±Õ»kCÝÖ{P·m~ÝÖëcI#¼¼.ï3¡ÛÖÔ ’L&ÑÕÕ…ÁÁAlذ---èëës,›ÙÍÖÖÖ¢/¤½÷ÞÃÃÃèïï¯eWfìÚtvvÖ»)ÓÓÓãé—e5û100€­[·bÁ‚õnnE’MeÉg[[víÚ…d2Yppmšå™žMï™d2‰ÁÁÁz7³*Ì„|Λ7ÃÃà ÿl·¶¶b¿ýökè>ý^J¹'ÃÃÃEKKK½›[13¡ÛîÚµ‹º­Çhù,åžP·Í/Ÿ ,ÀÖ­[©ÛzˆÙôžºí®]»êÝÔŠ™ ù|óÍ7©ÛzŒF¿ê¶ÕÓmûúú F²Ô»Ï^Ká½àeyœݶæ•ááa´´´`õêÕƪU« ë:ÆÇǧ|¿A{Ç;ÞáÙ›6])wÓè ÓéGOO¶nÝZï¦VL!Ùloo/K>—.]Šw½ë]M‘O³YžéÙôžž3†aÔ»©3ò)ÆN/*´ÓAxE5Íòž)åž´··£³³/¼ðB½›[13¡Û.\¸º­Çhù,åžP·-L[[u[1›Þ3B·½ÿþûëÝÔŠ™ ùœ7ou[Ñ,ïê¶ÕÓm½ZÀÞëcI#¼¼,ï]]]¸ï¾ûª~ÜšT[ØÖ®] ÀVØ'&&088˜S°’Édчfß}÷mŠI'iLzzz0<<\ïfT…|²Ùßß_¶|¶µµyþÅOš“––ôôô`ݺuõnJU¨¶|ŠI'!õ ½½ÇwvìØQï¦T­?ÔmI³@Ý–º-ñ&Ôm©ÛïBÝ–º-ñ.3RÿnZv¢§§gJœø»³³sJ˜ØøøxÃ{Ò’M€òIH=¡|â]¨ÛâM8vâ](Ÿ„xê¶„”FM *]]]H&“`öÛ°aÚÛÛÑÓÓƒññqÇ#jttÉdgœqF½¯!MO!Ù@ù$¤ŽP> ñ.Ôm ñ&; ñ.”OB¼ u[BJ£¦)¿ZZZÐßß•+W¢§§Éd===N¾ºþþ~¬Y³]]]Ø´iúûû›¢¨!^§˜l”OBêå“ïBÝ–o±“ïBù$Ä»P·%¤4j^C¥¯¯ÏÊÖÖÖŒ\{îmííí #¤†’Íìí”OBj å“ïBÝ–o±“ïBù$Ä»P·%¤857¨((tHBêG1ù£|R?(Ÿ„xê¶„xŽ„xÊ'!Þ…º-!…©i B!„B!„B!„F„B!„B!„B!„"РB!„B!„B!„RT!„B!„B!„BŠ@ƒ !„B!„B!„BHhP!„B!„B!„B) *„B!„B!„B!E A…B!„B!„B!¤4¨B!„B!„B!„B!„B!„B!„"РB!„B!„B!„R„½j}Âd2‰d2™ñYWWZZZ2¶···£½½½ÞׇYC1Ùt‡òIHm¡|â]¨ÛâM8vâ](Ÿ„xê¶„§æ•lذ!ã³õë×£§§ƒƒƒ@WW6mÚ„þþ~ôõõÕû2+($›(Ÿ„ÔÊ'!Þ…º-!Þ„c'!Þ…òIˆw¡nKHqjnP™˜˜È(Ý `íÚµèééÁèè(V®\‰žžZ< ©…d |RO(Ÿ„xê¶„xŽ„xÊ'!Þ…º-!Å©y •ááᜂ6<<ŒÖÖVG`;;;ÑÙÙ‰áááz_#BfùdSl£|R?(Ÿ„xê¶„xŽ„xÊ'!Þ…º-!Å©©Aebbpå•Wâè£Æ‰'žˆÁÁAÀèèèmmm’·/›mÛ¶a`` –Ý Äa``7n¬w3*¦låËçÆ3ŽCH­H&“ÀŽ;êÝ”Š™ ùܱc¨ü’º0<< MÓðòË/×»)CÝ–4Ôm©Ûo"tÛmÛ¶Õ»)CÝ–4ÔmKÓm‹}™`pppFtÛ² *ÆèèhÉû$“Iôôô`õêÕxôÑG±víZgПòýRBÆ.\˜7L”™¦§§mmmõnFÅ’MeËg[[ºººêÝ=2 ž3óæÍ«wS*f&äsÞ¼y Í&u£½½˜;wn½›R1ÔmI³Aݶ0ÔmI½ºíÂ… ëÝ”Š¡nKš ê¶…ºmkkk½»W3L°¬z·‚@WW׌è¶eTpâ‰'bÕªUŽ`©ªZÔ¸ÒÙÙ™‘‡¯§§gœq†6–M)ÖË}÷Ý—“NR7šeÒYH6”-Ÿmmmèìì¬w÷È,¤¥¥¥i *3!Ÿœt’zÒÞÞŽãŽ;ûì³O½›R1ÔmI³Aݶ0ÔmI½ºí¾ûî[ï¦T u[ÒlP·-ŒÐm[ZZêݽ¥»Ðu ü~û'wÚÿ 0 \jEgg§7 *6lÀàà Ö¯_õë×°¬¯¯_|±–‹d29Åè"ª³³sŠ Žs@$¤’M€òIH=¡|â]¨ÛâM8vâ](Ÿ„xê¶¥cš@G‡m±,ÀÜ „ö±€r i@ü‹@øŸìïk×½ŸM^2˜þ5µ¿ã|®Õ»·$›iT†‡‡Ñ××7ÅsnõêÕhooǦM› î»fÍÇè211 6 ½½===w¼FGG‘L&qÆgÔûÒô’M”OBêå“ïBÝ–o±“ïBù$Ä»P·-‘ÖKKEœöF€ªêþ€o ”ƒkèíŒ ÀzÕ6–h€n×à ûWi#€[ĉÄëÝ[’Í^µ@?Ö¬Yƒ®®.lÚ´ ýýýMFˆ(&›å“zAù$Ä»P·%Ä›pì$Ä»P> ñ.Ôm§‡¡( |>_ÆçºDúY¶#¾7€ÏàL Œ`^ý@d€^@>°Î$ €”ú¯Pë%WÀŠ„Œè„Dr44nï ¥ÞWlv0mƒJOO®¸âŠ)ÈÁÁA$“É¢Eú®ºê*ŒŽŽ:aaîÐ0ù’L&§l#„Ì,…d |RO(Ÿ„xê¶„xŽ„xÊ'!Þ…º-lÆjÿúÄõçáíQžÛ‘'‰ùŸ‚A ôнŸ¤Ø€P@5DEb€Õ@üG€ù‰ÁNë5’:ýf@ygª-ÒÓ>Ôtû ²ë{h\™A¦mPY±b6mÚäX+ÇÇÇ¡ª*ÆÇÇK¶L*ä×ÔIˆÇ)Vd“òIHý |â]¨ÛâM8vâ](Ÿ„x—Y¯Û £€Í/†cþïUè: I4MA"„/†$ ä l#`d‚° ûcå©í~@ýн¿ˆH€ï]@÷1€ïÀÚ °žH/ž:ž”Ú7€´áÄéúކ´AEÔ` ¥¶u«÷n|¦]C°C¼t]ÇêÕ«Ñ×ׇþþ~ÜqÇ!š„B!„B!„Bˆ§éMÿ¸?öà›û¼€ßZKpöÙ¯ãcûöØã)( `>H‹˜€"Á6tR$:lƒˆ–ú/Œ& D.ÆnðÜ Œ}Ðn¬]€¹ojÀ6Œè° )>W[M×ïÒÉu>vš0¸¾çN!FÊbÚ*ƒƒƒN1"P!„B!„B!„4 l#E*rÃÔíÿ`½¬øì8üÇoAÞ݆—öÞGÊÿO|âüå/:€Ï`ì§H9tØF q¼ˆëoÀ6ˆ,à¹ùÏaIl  ÖOíñ8_ È{ ìp„ý}+dÁ²,ȦœŽTÆÃunñ»š:Ÿ¶Q©6Š4`¢&‹øLÔo)D¾¨-uœY˜ZlÚ*Édõn7!„B!„B!„2=,8Ó‚-@ðb ~7g'þåˆ_£³ów8wÑøõ;æâŠ+.ÄÚkŽÃá/=‘Ú ¶A!ý±yófÛ˜!¢Q|°8•í#ÛqÉO.±w¯ìý tKÇê½·cÃþýX1°ÊÞ@ä`» ý[?z Cò¾þþ¯cçïvÚÇ•RÇ–Ý·í¶£bÜ'¢M¾Tÿ,ØßÆ”ì¨ÀNKÖtdK.\Q5¿kÝõ¹¸‚xžã¹#i˜iTººº000€ááá)ÿ !„B!„B!„/ò»Æ÷ïÛ‰põ=ÀÐ]^=äOxÿ»ÅæÍßDÏü× œ¨¯?;{¾v××lƒ€ ¼òï¯àÕ‡^üú׿†å³2ë›D„¨ÅîGwc÷îÝøÕ]¿$`rÑ$þíÿ†°Æâ¿,ÆE».ÂÙgŸ=¤§ -· Ý?¹ãIyÀ‘8餓pý®ÇcÃÇ>‰_?ókìþ§Ý8â¾ÿƳK_· ¢p½0d(H§÷²`BÂÈ4Žic‹¨Õ"ˆ"JíØF"qéè-µÍtíoºö1\ßëu}.ÎYj*2³ÄïÍ0ÓNùÇ188X·nÝ”í>úh½ûD!„B!„B!¤É1M "‘Ò÷¹éÛ-øí«{ãH&óþþî þçžû^¬1ŽÆ{9r—Œ×<H: ~øÔ#—àFýFÀ.¿ùr¶ì0|ì–t]‡/ì†R'Ñ€-›ïÄðó?ÇIm'dY†né8öõcxëö·p÷Ü»1ÿÐù8âˆ#ðÜú¿`Qr/ì;ùw¬›hÁgž€§ÞµnøÛ¯ñÚî½1öÂ;ñùý>´õC8 Ëðo{—mZ€Ÿ¾v îßý&îܺ¾½Ï[0Î3ð?åx虇ðÛþ±¡˜€Ý>icIéˆ#õYéš-"E˜žÚWKý.jÄDN…Aãló§Î+¥>“Ò×'#…Y0õ}Q‹Æ€m° §Ž'¢qÂ(žªl™v„J?}ôQ<ú裸ùæ›±~ýzÜ|óÍÎg„B!„B!„BÈLcš€aäÙè‡_„?hëósñÏs“ˆ]|ý²{qïîß¡kA&î¼ÇIó°`× ¡õòÖtú¬(°ç{QàÀ 'œ€ýÿ°?î}î^>†a`ë![qýõ×ò,@öùû øÙÉ'ãšä5xmîkðù|ðûýxs¿7IY€¾üÖ—ñÂG_Àµ×^‹Î·wââÿŽ“·'ðÝÝPw, xsåK1¶`—^ºp=ZßjÁGî… -Å…?ˆæ¼€ëy ›öz ?~ûm<õÔðß lùΑ¸ñÆïá”/<‚Í} €ðè—óøÔ5ÒýNÀ8'u­4ØF ¢¦þ‡SÛD˜¡ÔÏŰ 2!¤ - ÒÑ12lãG4u¾XêsÑFÚ#¾cÀŽdû‹ˆ—xª-â{ubÚÀ.Lâ‰'båÊ•XµjV®\ UU1::ZßÞB!„B!„B™˜…R@¹ ¦ï~s7þï±·ÑÛ ,]º‡ïü=”×€X(†|÷#P ®þÃÕ˜ûë¹ö"¾»ÖG*ªã™÷=ƒmolÃøÆqÖYgáõ%¯ã3ƒŸA¸; ]ס[:æ?<áp†e`﹯`ÑöíØãˆ=°ï}ûâñÇG,ÃÛßFww7Î<óL´Ó†m 022‚‡î^Ñà?ìVÜ~í_8¸á†Äã‹a}äÿ³wîñq”õþs§\’NAZ„`­¶`aB• p8ÎJ Ç[³ñˆ Uº+^NÁ“ã®úµç¨;…zÎwªïdG9àŠDƒbFAn%5”‹ÖNZZ ÈïgŸÙÙÍ&MÚ$»Iž÷ë•WvgçòÌì>ó<óý|/_ýê1xÞ>¬]»ý^óM Í~'|ŠÍ›Ïà`÷a.<è^ا›ææòÖw>ÄIÖ ûØ­¼êUæ?çì @ÿGpï„d´´@øÏ`? ÁAXáçâFàAð4ø'1´V‹_¼.ñº,²vL q e”IªøZF®xa%GI€IQªC#k·8Å×Rl‘uiâõZª‘eø:.ãÀ˜•îîn:::hooç÷¿ÿ=<òžçÑÚÚÊ¥—^:q-U( …B¡P( …B¡P( …"ưé¾÷˼oËw¹æšõ<¹q.ÏÏž{¾‡iüŽÞq4¤Áð fçgGbÀç>çyE!à¢M›¸©ÿ&Î{ñ<Žþç£Ùuî.îºë.LÓä¦Snââ;/&®üù•„oÔéÿð‡yýÒ×sî ç²xñb|ß'ŸÏ“J¥¸÷Þ{ùñŒeYû¦C™wü|}–³¿w#™¿ˆ4a'œ0›B1•˜¦i\zé¡|éK—³xñ}üïþ—üÿæ8é —eo½—{nÂ4M¾ýí£ÿýâXÄ»Þ5È[Þršæ‘º>Ôß0X¶l3‰¤‹(ï!°!mC2 Îóø øÀ~د«Rö¡$xPü/S„IAE}&_ËZ,¥´`%qæ¿ÓðåPˆZr9±ã˜bÁwÁ½¾¸,‘€?UŸ€ò:.ã̘k¨¬[·Ž¶¶6ÚÚÚ¢eMMM¬Zµ**LßÚÚ:1­U( …B¡P( …B¡P( ÅŒÇqÀu…`²eËÐσ]  ¯góçÏç¾gº±^~…ýN?Œ?­ý¯{Ýë„¡_¦©a¸áòÁË õÍ ›8°‡sŸ}–Ÿ7ý%V|a¯t¾ÂýûßÏW2_á‰'ž $äâ‹/æýï?Ÿj‡öƒpÑE±ï¾û†!º®£ë:¦ibšfÔVMÓxó²#àïoûBÎIÂCß»®ëüîw¿JHo//ô Íwý ˜iš¤R©²u C„ë¤ÓiìwØ„/ÿž?þ‘üws„¡Ç3ß[HW×<Òi(|Yl—ÍB!†!^³:ŸI ‘CþÉú&€ëÙ#ÿÅzóY`+°xrÑ,&¿ÏÇÑϹçó¯Æzð6‚ïÂù1èYq,C+n–ô¿€µÜÍàÿêrïÔ¡ÙÁ¢ÈfÃé;ÃŽ8 ÆQ®³ 200@CCCÕφ[®P( …B¡P( …B¡P( Åxaki±Ô^þ¥ ]-Ri@Ïà,…ß}¶÷=‰ën¹Ž%³—pôÉGÓ|g3Ç,:¦¸DTƒ,’î‚ã9„NȬ³XyÄÏ8ø•Ù~áöèX𦱵m+÷ßv?¾ï†!+V¬À4MÞ÷¾÷1oÞ<,ËBÓ4ÚÛÛ£º)¸.ºe•Ÿïà hü¬Kj—d³âD+·)æ<ÛÇŸÑ߯‹ÔcžGWWšVªÜ®ëzÔæ»ûßøÎO¿Ã‰Á‰ضÏ{Þ®ûi®¹æj ã²Ù,¹œ…ïûèºEÎôyÛµ;¸öÚçyúé,\ø{VJ[²–çA*Ö ¯ðšÏ>Å{>ñg4ílB !ø+¸¼ðÜ x—Âüùñ™Ïìà3Ÿ™…ëÞNܯļ ׯW=ÆÝwÃ[Þ2 Ûûî³Æ&p¶wžÎï²àÜ f;˜´ü¿±õøpú¸ýîÆœò«µµ•uëÖ ©—ÒÙÙI? .·Æ) …B¡P( …B¡P( …B!q]ñ§ëÐ×™Lé³Ä·!ûQaäOÿ¸™Å‹ï£¥ùqæ´ÌáÉ›ŸÄÀàÜ·Ë1o=Fˆ' ŸRÔE(¢9R©;ÞÁ¾‡ °ïÀ€ˆ*±¡¥¥…0 )œYàƒŸø ¦iFBÀE]ˆ}$ l;VI=DN­J2™ÒÉ„”jÀÈPœXDK„ï ¡åP‹‹Þ>Ÿ\.‡iš8ŽC0L™oY$“IÒé4†aà8š¦qÈ!á8N$A€ïûüö¿þ‹£N;ûîä'7¼ÌWÌâúÇ·sþ»_â§ßyŠwÝ·Ó´ÉåÄ©}ñ“OpÓKïáð-Â0‹¦±³sVËÙà¶Ÿß×ù7 ÃcåÊÏbš>\0ˆ·©‰|f;†™LÀÿø.,¸‚0ÌbYbÿ?¿÷>÷š—Áí­Ðø`/ÿºk@z3' MÊùü¯iØzÏ,;f\cTÚÚÚhmmeÙ²eQQzÓ4£º*c‰Réííepp°lY?ÝÝÝô÷÷ë‰*ŠÑS­o‚êŸ E= ú§BQ¿¨¹­BQŸ¨±S¡¨_TÿT(ê—zžÛÚ¶ØžWŠŽ`_poïϘû7î¼Ûn»ä¶Ð —Êqâ‰' ±Bþ™%·z wn»“‡}˜û￟––t]ç ƒâ ùóñ<·à¢ižç§ÿàض¦i‘ai¹TŠU—^ÊŸN=µü\Wˆ a8üI†' Å ÷ô”N8Ne©%§‹(˲p]—––‰DÙê²}´´ÐÕÕ…a˜¦µ C à ™L’Éd0 ƒSx€ÁyÏóÃÎkoäo_ïcñ;¿É¯~·?üå¿ÐÃ…Ï<ƒmgÉå\NúܧØÙë8袋‚€õ¿þ5[,‹ïÝú6´àÏ»æqæábÛ6©T ß÷¹í¶Ï³ñ¥—8`éK$ ‚ à+^È—×®¥}Æ¢PdóÑ•Ÿf¿Ÿn'¤Ã™/¼†Ûw.A×Á}ìEŒ×ûl”š+jl¡P] ‘È`Çi¾4Mœ|…@‚®‹ ¢kÃ0¸~ýú(ÅXL LÓäÜÓNã°{îáÈÁA ×eŸÇç“wÜÁ~ìcÑ9­{ËýÚxïxÇ‹®z€Ô>k0 È%fq×S«Çý78æ*’ °`Á‚=>ðÕW_=dYGG«W¯¦µµ•ÞÞ^–-[Fkk+MMMã~â …¢:Õú&¨þ©PÔª*õ‹šÛ*õ‰;ŠúEõO…¢~©÷¹­i ¡˜]+Âó@»ô&p‡ /`Ÿ“÷!ætÍ)E¢¤.JÑ)EvîÜÉ%—\ÂqËŽ#™NÒÓÓCŠ”@r9pLÓ$›Í’Ïç…€âylºè"V¯^÷¾÷•væû¥ô]©”ˆ2ÉçÅûx-•‘èˆå33Œb.+Gì3¾¯|l»tšxíkY˜J¡û>¼ÿýè¿úºïó÷­[‡oƒë­ÓR<=€ƒÚÄ‘gŸ wÁIüðoäþÇçaär i¾‘JÁ•6Ì/·Ñu~þsþÉzþñ–ÿá°w. NÓ××­÷¥/D"‘(]_Ù–BÂë:d³¬¼ãžlmåž+¯dþ{æó…7Íb`` æG΄f ó—ðÈïzxn¿7ûïo"Tº»»Ë:Vgg'UÃ4«ÑÑÑÁ‚ Êê­twwÓØØHkk+Plº»»Çý¤ EuªõMPýS¡¨TÿT(ê5·U(ê5v*õ‹êŸ EýRïsÛ0‚Ši–}x„À˜äÁ÷}æÎ‹fj|`Ñ [\Q–.ÉdäÛ, ~º€ÍÇmÆ0 zzzJ;×40Œ(%–L“%tÌg?KÖ¶£Âï€TdJ*%Þ»îð'–Ís–í†\Nˆ3»¹H Ë–Ð’ÍrÄÿÈoÿñ Ã= 9ñ‹_,µ- …@#aߺW\qŒ(åÒÕEØÕEëEEQ.äóBôx²§L ŠÓýL7z¡€mÛ¢æLDíÐ4 ˲J×7þÈë›Ëqä~ûÛ¤“N§9øà§xòÉk¢uO:èÛ|ô˜VNذûk:FÆ,¨ôöö²|ùò²eMMMtwws饗ŽjûuëÖ•.tly¥¢ÙØØ¸Ûœ|Û¶mS«¢ftww³iÓ¦Z7c\®oÊÏö¤nÚ´‰ÞÞÞZŸšb288Hww7;wî¬uSÆ…ñîŸ;w¼·Š™I?>ø »víªuSÆ5·UL'ÔÜVÍmõ‰œÛnÛ¶­ÖMÔÜV1PsÛÑÍmGë„?¤½?—+Úî06yÿ8æÐ‡ 6Ü»9Îæ^8— ¾tA”‹XìD"‚¯ùѾeÊ«áÐu˲xã!‡Û £üšAIXtu -*ïûåÛŒ”¬Ôµ!¡järQËìNà‡ïxGÝy'ºóN±<ÞñâºåmÃrŪâú‹UB’Éd)¥XQxÚý)èäóyR©étZI--àŠÚ4¹QDðÜré¥4Ýs®ëFµ`\×Ŷm¾ØÒ 6000À÷\¸Û}•1 *·Þz+mmm¬Zµ*ZÖÚÚÊõ×_ òÃ188ÈÊ•+Y½zõâõCÖMÈØöíÛÕC§¢fL—‡Î‘ú&ìyÿÜ´iÓ|¸ Åd0000m•‰èŸê¡SQKúûûéííå…^¨uSö5·UL7ÔÜvdÔÜVQ+äÜvûöíµnÊ^£æ¶Šé†šÛŽŒœÛVÛ~oˆ‚€5Wd„Ê_ ?ùõOØqô.‘â+øQ~DEW’É$žçEu<ô„ŠT*…¡ë|ô׿.ê¨ÖÀÊ|dš6T0‰«š31ÁdØãÇŽuõ5×пt)Ï_{íÏ¢õ³Ùò6ø¾XfÛeÂO,;†aDµdÆ‚¦i8ŽƒmÛBQc§BQ¿¨þ©PÔ/õ>·u]¡A ±…~ñ/„mwnãÓGšû~sË–.+­£SªçaÂ>ûìçžÊ3_ûOœxbd€ ²Wª®[nì—©­²ÙÒòT Òé¡‘)#!#2t½T°~‚Xtþù\ÿOÿÄ]<€eYåQ%²ð{–Ÿ{¡ Òq ˜”Õšõi†A"‘¨šþq,û°m{DA稣>ÌÃʌߵ³ ²bÅ úûû1M3Rÿ¥b¹jÕª;R¥·ÝòåËY±bEÙ~º»»imm¥··—þþ~–.]:~g«P(ª²»¾ÙÚÚªú§BQ#TÿT(ê5·U(ê5v*õ‹êŸ EýRÏs[׺>|V¨§ö4O?ý4ækMÞößoƒxmu‘öËtè×ú¹õ<«$¤H|¿úªEƒd2å)¦)"M’I!²Œ%âd„º-ãIOOº®“L&‡~âü¥¸BH‰¿g ÃØ£è–8C¾Ã víúguݸ¶{â]V­ZE[[·Þz+ B2W¯^½×ªd{{;+W®dáÂ…¬_¿žöööݦS(“ƒêŸ Eý¢ú§BQŸ¨¾©PÔ/ª*õ‹êŸ E}R˾)íüŽ3T{Øq÷f1‹{¾wm»‹‹Ò‰ˆ”ÁZñ}÷C)|Ï#‘H”GXTK9åyÕÅ]º¼P ‚Ñ *cHq5ŒXëD§F@Éf³†eY„aH†åiÕö™¢k"9餓Æ}Ÿ£T:;;éììdéÒ¥,Y²„¦¦¦(soX»vmÙû¶¶6Z[[éïï§©©I…t*5¢²o‚êŸ E½ ú§BQ¿¨¹­BQŸ¨±S¡¨_TÿT(ê—zšÛJ% ‘Ñ'xöágydÑ#<üðÃ4moâèG A%@¤Ó«ø>F.—#®æ‰ã”оkÚØ¢MÆ’ÂjŒÅÜÇ‹!5TäyîfY¯Äq<Ï£««‹ hii¡«« Ã0ð}ÔEê÷4Ý×Xزe˸ïsT‚J[[K—.¥»»›5kÖÐßßÏ‚ Xºté^‹*•¨ÁR¡¨_TÿT(êÕ?ŠúDõM…¢~QýS¡¨_TÿT(ê“ZõM϶ ¨AxDÉïÿ_·‘Á®AÎ?ö|! €Hï%5ÒrDAs×u…@ ” !¶-T™cl"…lVD…L¢¸2¬àQMh‰]3Y@><Ï#‚ @×uÇ!ŸÏ“L&Ñ4mHmÛ¶±m›B¡ /ænRIág´Íp<õÔSãzýöíŠ ,Y²„U«V±víÚ¨8ýòåËéèè ··w\¦P( …B¡P( …B¡P(Š™ï‹Š (R舺(ÀýpÎ9çpùàåwÜq¥R”‰(Ïó0M“T*…eYB8±m¡ÚHòy!tL®[“H•ªÑ9#¤ ÃÓ4q]ß÷Éçóضçy¤R)<Ï+‹N C‘cͶíè½eYxž‡çy$“I²U®q"‘ˆ„ÇqH$Q[ã‘5étzTç9)¿F-¨TW–.]Ê­·ÞʲeË”°¢P( …B¡P( …B¡P(ŠqAÚþ …â™Ò xñ‘9jÛQ×p§žzji£bz‰çyd³Y6½÷½ßÙ‰®ë"BB^÷M³T¤}"qœ±¥' è.¨T¤àÊf³xžÕKI¥R8ŽS\5‰#†a ë:®ëb¦iâû>ÙlÛ¶ñ}ß÷±,‹ ð}ŸT*µ!NGâŠçy¸® ­çû~$®HÇuÝh›0 «§1› ö¨(}%ãQOE¡P( …bw„¡p ÃRQBú­P( …B¡P(Šé‡Ô¢@¯ô×÷Jm‹Û  p†ß‡4üŸtß}œØÖVþa*54J$“‰m™ÀÛMÚ«‰BŠ#…w]7Jï•J¥0 #úÈçó$‰HDq‡B¡€ïû¸®‹çyd2™(=˜iš¤Ói‚  ««‹––lj҉ÉÈ!¹>¥ Ã\.‰-ñõ‰aV­—rÒI'ñêW¿z\¯Ý˜"Tº»»éììŒÞ÷öö²|ùò(í—B¡P( ÅDà8ÐÒÞEàÿü;„‘ãìý¾ …B¡P( …BQd³Â™nˆ¦&ÜsË=ÌèƒÿL 1%– é´ŠX–…eY,jhZ€]×…Ç^Ë[ù=Á4kâ!˜)ÓßMÍ]×) är9ô¢ª•ËåDª4À4Múúú¢}öõõa–eE)Rh‘"ŒeY‘£ë:¶m“Ïç1MÛ¶£H˜t: 52FFµÈ}ƒˆnÉåreuVdš1€ï~÷»ã^CeÔ*W_}5¬X±€þþ~.½ôR.\È‚ X·nýýý¬^½z‚¾j…B¡P(3 ßs`÷Ðs3h+À:p¡¹VÛ^B¡P( …B¡P(uˆmW×:ÈÀÍÜÌ=ÿyÿõlý²SÒˆÿ2èÃuAÓ°‹)£úúú†Qhfš¦¡iZõ´_EâõPR#Kz•”e•Eé3™LT€>«Ó"£]4M‹„y,YsEÓ´²HšL&S–ZÌó¼²Ú, R•É4d›6m÷•Q *½½½Üzë­ÜxãQj¯uëÖÑØØÈêÕ«ihh ­­ Ó4éïï§©©i\©P( …bæ†bâì8Âq(ÿeÈ<Ú× ¡Ýs »S¤¶­AÚY…B¡P( …B¡PLÅšæØ¶â0BDô‰dá¦Cobõ‘«Ùÿ¥{áJ"JüÙP×Ù¶maÒÕÕ%– Qgf&RŒ¨$Nãºîˆ"ÊXn_qqEFUû,ŸÏ—íKîÏ4ÍH¨Ñ4-J&ë®ø¾Ïé§Ÿ>î×nT)¿n½õVZ[[Ëê¤tww³dÉhjj¢©©‰þþþqo¤B¡P(ŠéMˆ sˆ)º}}Phóý ÍCLœu äÅëps©@¡B¡P( …B¡P(¦¹œxÞ3MDJ¯R&'žÜþ$ ›`Ž ]]âYQ>3Jtm7ÝDQ1õ Oã5EÐ4-Jù•Íf™3g®ëâû>]]]8މõJ\P‘µV‚ ˆRŽ…aÈI'4îÇu •ʨ“îîn.\X¶LŠ+ …B¡P(£Åu!™BJˆ4_©hi0î+®¤.¥IrÑ;Ië«uë …B¡P( …B1Þø¾pºËdŠ 2ˆgÂ"Aˆˆ•x\ÅNt;w’J¥Ê"B€e"ò#›Íbš&†aÐÓÓSV—¤ÞÑu0 ñ}Ó4£•9sæŒû±F%¨466ÒÝݽ_·n­­­Ñ²ÁÁAz{{ill¬õõS( …B1°m1Aö<(DŠ/ÿÒØ !BBHéAˆ+r‹:Öß-&Ù …B¡P( …B¡˜^”Høç:à¾ËïÃØb¥Èó@Ç„“ðÎö<4M㤠. eÍ:Oe5Yäóy²Ù, "Tòùü”ŠJ©$.™¦Y3žŒ*B¥©©‰ë¯¿žîînV®\Icc#ííí€HýuÖYgÑÝÝÍêÕ«k}ݦ52l À¶mlÛÆó¼(„)PIäŠIÇ÷}lÛÞû)3ßBJ>/&ÈºŽ˜?Nøíˆ:))JE‡q(²~Ú¶ZŸ‘B¡P( …B¡P(Æ“!¶p QGÅ…Ù…Ùb™ì“¹£“I’É$ø>÷ìÚE>ŸÇ²¬’HàyUv )ŠrÂÒiQ70š¯Ù`l{8 x !¨ì¦ ùóÀ»rçÕú¬ …B¡P( …B1^hZ•@ð`ó†Í¤ ŇÉÙŪõ©”xÐÔ4ð}N^²„y†!ŠÑðê C•â ‚éd·Êd2QTЦi¤R):::Æý8£T†£¡¡aÌbJoo/466IÖßßO?MMM455û OE‚ N£ë:…Bd2I.—#<Ï#“É`š&A`Û6š¦ù|>b*½ E5Fê›0ýû§çy8ŽCWWŽã ë:ænÂ@=ÏC×u|ß/ ‹L$„aH__ß”Ê9©¨_¦Kÿ´m1íé)Îc„—‘FzèÏ1´˜àHl­õY)f:jn«PÔ'ÓeìT(¦#ª*õK½Ìm‡Øù] ýôÓý“n®Ð¯(_1•bëþÀ'Ÿx‚‡zˆooÚD‘Ö*ŠJÑ´Š_19váÛ6„/ƒ~)euRF¼ Lotë*šÛ*õÉt;ŠéˆêŸ EýR/s[Ï©¢Ëð ö}×¾%çþŠô]]ozðƒœðúèGKh(ÛhU”jìŒZPY¾|9 Ôwwws饗rã7ŽIìííåÖ[oåöÛo§¡¡þþ~LÓ¤­­ ÐÑÑÁêÕ«imm¥··—eË–ÑÚÚ:í¼\×%›Í¢ë:º®ãºn”²«šðáû~‘¥ºÜ¾===‘×ó<²Ùlµ¢¼å•ì®o3¢ʈ¯D"õ9)ˆTC¦à³,+RóeŸëêêÂ÷}²Ù,¶mG}5‘H°eË–ZŸªb 1]ú§ï‹IqWW,Â:lD”Š º+Rà2†4§þ~½ºb ˆ5WVLjn«PÔ'ÓeìT(¦#ª*õK=Ímƒ J„J‘'ž`ñß‹7aË#]ŒPè쌲‰(Á¨•îînúûûùýïOCC¦iÒÙÙ§ ýýý´µµEûn``€îîn#…qÁ‚,X°€îîîÕÎmÛ¶ÑÝÝ=%j¸xž‡¦i‘'{d2ZZZÐu}H$‰ïûxžE¦ŒMÓDH[q?ÒØ›N§) µ¾Ó†îîn6mÚTëfì5#õMyž{Ò?7mÚDooïE³M$²þ| ¢Ÿ˜¦E‘X–EP,ffYVU!Ò󼨟årC󙦉a‘8#Ó€9ŽƒmÛeý]F´(Ás|dýúõìܹ³ÖMÙk&¢îܹ3ò:šÌÓB¡"]m3BA±(€åŽmŸÆùÀC"úÀqÄ1ÂrcI¦˜4úûûyðÁÙµkW­›2.ç2“綊釚ÛN͹­bú#ç¶Û¶m«uSöšé4·U(@ÍmG;·]¸pa´ßÑ`šUJÂvó˳~É9ï>G,Óõ2åÅqœâb]ÙWF‰aÓ&åW%½½½2·u„JkkkÙÉ’%c>Ø’%KX²dI4èîîfÁ‚´¶¶²fÍš!_cc#ýýý#îsûöíSæ¡3N†!–eEFXí™L†t:]¶¾ã8QtÊÞ`FÕ’H$¢å•5cgºŸ¢Ódª± èéé©õå™È ßtT&¢ʇÎÉòô QpÈÏ;Dˆ)9Š¡)Ûƒa)Øa1úŲÄ|º8ÆqÄd<ª4TÔ„þþ~z{{Çô@U¯Ìô¹­bú¡æ¶Ssn«˜þȹíöíÛkÝ”½f:ÌmŠ8jn;º¹mSSÓ˜®Q:-RE—i"9áØzà…BõD"QY…x¦ÅÈ躎e!MÄbýúõ2·Ý·'#뱬[·.4¥7BœÑ „sçÎS”L­p'ò~¯L”ÏçÑu°"ïŸïûôôôŒ9:e$d!{ÇqhiirLÅØhoogñâŵnƸQ­ož÷ÏÅ‹×]®[é­àû>‰D"꺮WS©¦iâyåEöDÌårär¹h°* äóyLÓŒöçºctÏWT¥©©‰öövfÏž]릌ãÙ?gÏžM{{û¤lƒ@ˆUçgDAú½t2[D]AY_PÓ„¨ÒÜ,ކ"‚%ît`Û~úŠ*´¶¶bY‡~x­›2nÌĹ­bz¢æ¶#Ss[ÅÌ@ÎmçÎ[릌Sun«PT¢æ¶##ç¶c;Ãphʯ+wìÖ#KTÚpÃcư©î§:mmm2·u„Êx²`ÁÖ®]Ëàà Ë–-£©©‰ÆÆÆ!ëõ÷÷OyïŸ0 innF×õÈ#~¤u%¾ïOˆ’ªë:étš 0 Ïó¦­ ©;Õúf[[۴ꟶm“Ëå°m;4v7p躎ïûe}Å÷ý1‡ÊãTF¡Èt_ªO*Fb*öÏ0,yECZ‘â:ßãÝG¤t†x(YV¹ˆ“ÏC2)¢Tt]´Mê—¶ •¥d=åÔ¤ 3in«PL%¦âØ©PÌTÿT(ê—zÛ>ðÀðjÊÏeJ]'ººº”]E1¡Œ:Beýúõ,_¾<ú[·nëÖ­+[& ×Ggg'kÖ¬‰Þ744°`Á‚¨V†‰ LùpM×u£è“Ýy³Ç×uÇ52Ebš¦ÑÓÓC.—SÞð `ä¾ L‹þÙÜÜŒmÛQ¤ØX"Lª‰›£éӣŲ,r¹\TÐ^EŽ)âLåþéû"b$êB>¢½|0l¨öX06‰ãŒ¸Ž!RŽé:xž˜wçrBT Cñçy¢ÍÍÍBR]Q±;fâÜV¡˜ Lå±S¡˜î¨þ©PÔ/õ2· ‚¡õS‚ à¿ùï¡u¡]4 pGE¦(&…Q *,\¸°lÙžûêììdpp…Õd~ÌÖÖÖ(/(ˆ¼™ýýý,]º´Ö×hà °m›B¡0êBðaÒÒÒ‚ã8¢¦jšÊ–^ñ¶Êy¢`ø¾ Lùþéû>a–‚·,kH‹{¬Ç©V ËuÝ ©AdY–:C˜ªýSFyD耤ÂÊ$×4Ñ4Èd„¸†"‚%•Ë\W¤Ó4!¼tu ÑEuGÅî˜)s[…bª1UÇN…b& ú§BQ¿ÔÃÜÖ÷E†8]ù.þóÅÿ¬º~†QJw˲Ð4m¯ëQ+#1ª”_2ÔkoikkcݺuQ¸ØúõëYºti”‡¶½½•+W²páBÖ¯_O{{û”,ê;rX–5êÔ]š¦ÑÒÒ‚eY‘Ø1ÞHc²Do³Ù,™LfBŽ©¨v×7ajöÏx]’ /\Ë¡‡ÞBê¤Ó`Y4MP CVeMËÆVdžVMÓ†¤ä“Ñ^Ò¼H¥R¤ÓiÇA×õh" úæÌe*÷Ï ó8Dš/)à""Sjô³ÎdJõTR)Ñ×eÙ–%î ¾/–OÓ´²Š½`¦ÌmŠ©ÆT;ŠéŽêŸ EýRs[i—‰2¥Ÿ!÷Û¸_õcº®ÓÕÕ¥ŠÐ+&1×Péïï§»»; ójjjbéÒ¥£î@k×®¥··7 ‹G¹´µµÑÚÚJÿGÀÔ2­P*•“T×u\×TÕ4MlÛ&LÓœ4cŠ©ÁH}¦^ÿ´mÏ|¦—Õ«}<Ïãå—?Çü6²Yaõ}!š0’f‹_ß%“ÃOeJ>éÑÞ×7~í–q6a’N§‹m3†ˆ¢Š™ÁTëŸ2ÊÚ0@?¸â"j¦ˆ:*cÁqDçnœòSÄK¼Ë{B¥8jšbY:=¾Â©bz1æ¶ ÅTdª ÅLBõO…¢~©õÜ6*ùšlÛ¶Á“™Ãœò tl6‹išJPQLcT:::X³f Q °5kÖÐÑÑA*•bÅŠ£ÚÏH‹¦ú`éº.®ëÒÓÓ³Gåµ4d:$ß÷• 2ÃÙ]1±zWH::Nâ•Wæ“Íž†ïèú~Ñçù<$â¿eAK‹Ø¾§§$¦ br›ýö[\ŒRѸîºeœþ"®ºJl»/\†Cs€î)žÈ étzÌB­bú0•ú§ãÂq ÏBÔK±¢ŠÅØ#SÂP¸)IAÅó„ʑˉey£ú>ÃêÇÒ´ò‚õò}µ~¬iâ~H”o£PÄ™Îs[…b*3•ÆN…b¦¡ú§BQ¿Ôrn«ëâ1/Âú_üìg:‡òÛ·/Æq;OôÚ0Ä6¦)„™L¦ S™t´H¡Ó²,lÛV¹@uï ‘#ZñÿXÄY€E×EK¥JUâMS9‘jhj‹ˆN©ô °p)„ #°F¬½#°'¨B¡P( …B¡P(F‡LÃù{k@°àà×±ø›.Ÿ–¯ÇB¼õ©§>Àá‡?ʯ~µ?Çw\Ù:¦)¼Ûe&¢B¡í’J•Ä™BL /2k‘뎮=š¦ÑÕÕ‰Ÿ E=ây©³²c,BFŠŽ»;á°«Kt¼sQ¬ÐZ€dñsY·ECD«ø@±nœôèš»_O¡P( …B¡P({FÜ x÷ï†?Pf@ Ôš¢FŒ*Be```T;kmm­õùÔß÷Éd2S¶þˆŒ¨Ù²e AL&Ñu]yÀ+¦a¦)¼ÔŸxâçèúe@)µ—Ì´§˜¦Éw¾À“OÞÅ—¾tAÙgÒxl°e C>“0¹\É>¬ëBÒõRª2ÓÜ}-]×U™¢®I¥b¿cŸ±×KÑ)F;麘X_K©F‹…MŒâ2Y€>QüÛÕR\Ç2”¹TÃóªxK) …B¡P( …b\(óS/&"xâÄ'xõŽY0Ï€Ÿ–¼áöýä'YvÞyµn²b2ª•ÆÆÆQ‰*3-:% ClÛÆó¼)+¦T¢ë:™Lˆ$¬PÔ/Aýèúb:,ŸÆÆ¯—}žÏôñÇçðÿðÒnE8º^² ÇíÃ2'h*UŠ^I$J)ÃFB *Šz&‘@Ô*!TìIßóýRxØîH¥à?úŽ«ëp˜&„‘ÝB‘Q)Rpq‘,yDʰ øß«kZ•ðs…B¡P( …B¡PŒ Õž·zæ!t]§éÿ¦!Œ'©h‡>û,‹Î?¿ÖÍVÌ@F%¨455±bÅ V®\Éš5kŒ>¤££ƒ5kÖÐÞÞ^ëó™T|ß'•JMɺ)#¡ëºÊC¨¨{ £T³ÄóàCBÓ4Â0œ>)Rãqĉz^¦ ¯¼"Ä]¯>¡0 ×u±m{BÛ¢Pì 2ÅB°¨PBÍfËÃÇl{ÏT £x¬Ñ¬§!D”žâk !¤X”¢XzŠËäòD1uïôî …B¡P( …¢n𼊌|s¿o’Éd8èÉõpañÌ4øãQ–KE­• ÐÞÞN[[ŽãpÖYgaš&guguëÖ­cõêÕ,Y²¤Öç3éèÓ4ˆUõNˆ?ÇÎ /¿|/©Tj‚·o|ã1“fT5Œám˾ïãyžê§Šº"‘‘øˆˆáúŠ® Ï¢0„LL ‘ùïÆŠÆØS‹U =ñ`Óxí)Ö¤‹ÚO‘2L¡P( …B¡P(ㆦU¤üòáÄ_ž(l¯AP–Åà÷¿ø§^uU­›¬˜¡ŒZP!ªÜ~ûí‘xÒÖÖÆÚµkñ< ÐÑÑQëó™T¦³!S¥ýRÔ;ž'ÄY‡$ C4M›Ðßm&“"›Ý}“ñB *R8’èºN†“ )£'Ä8šãÊTZߊÄ(†kÇkɰ³±àûåd"0²ï¥TÄ^¡P( …B¡P(ãJYÉØæÍ›'^G©„=Öñ}^¸ä’Z7W1C“ ÐÐÐÀ’%Khoo§½½=ª™ÒßßÏš5kj}>“ÊtN%¨(êi—•zB†1a)¿âLfÚioö}‘ ĽÇ4M4MÃÛo~…bpœ˜7Q‘*+>v]‘Òk$ cì, 'GåÌö*J)”¨¢P( …B¡P(ã†ë– *Ït?Ãsû?'ÞÄBW‚ •J¡iÚ PŒcT‚éî®ÅTÀ4¥Ð%4MÃ4Çš÷§¾1 1¡Èå„Ý8›…ýö;Ã0¦]ý&ÅÔ% Åä7šãf«¬”Ɉ•š›GÞYÌóh¯µ'‚ãpcŸ]*¾ÖÅê'80F¡P( …B¡P(fqdçÎUÓHKûBQ+j"¨ô÷÷ÓÝÝMww÷°Ÿõ÷÷×úÚT%‘HÐÜÜyÃOWd •l6»÷;SLFê›ñÏ'«Ê:)sæ µqêºh››·âºî¤ôÇ\®¼~öd¢iÏ å²ËaY¹â5šÞ⮢D½õÏJ …b@J\dÅçAüˆ …Ф¸ãˆì 2œ+›ŽÄ÷w/°„¡hï0)IJYH&!.T”Š"b*ÏmŠéL½ ÅLFõO…¢~©ÕÜ6²ûdüöôß²iÞ¦!ëiš6­m²ŠúgÒ•ŽŽ–-[Æš5k¸úê«Y¶lƒƒƒtvvFŸ-[¶ŒÎÎÎZ_Ÿ2Â0$ ÃS°½¯¯×UÖ¢™ÂH}&¿J›¨ãñ$nuøÔ§>E&ã3{vŽL&C¡ *Jkš6až ²-µÄ²„°bÛ`š&a¼&…bÚRoý³’D¢Ø7Dä†ÔL\·<%—aŒ_Jσ–qã0 q<ÏEbÛâ¦"ûŒlWkHêhåü­¨5ûf¥‘¼$ñÁo8d•o¼‘  ØÙÙÉŠ+èèè`õêÕ´¶¶ÒÛÛ˲eËhmm¥©©©Ö× Ïó¢tB¶m“›£P!‹_«PºéÍîú&0éýS-edFÄà`=t%]dâûþŒï¯½½½tttðì³ÏÖº){ÍDôÏgŸ}–åË—³dÉ’½ßÃPdÚê룙×$Æ¡èP†QÝ2‰bLÊf³hšF&—½pO6ZLj\Nœh@&CO ²çünºë;ç‰ ¿GÕ‚‰Š¡tvvÒÙÙÉÉ'Ÿ\ë¦ì5Syn«PTCÍm'fn«Pì-rn»qãÆZ7e¯©ç¹­B±'¨¹íèæ¶íííeB͈íž>ø«øþËÊ>Š;º+»£££ƒ[n¹eÜç¶£ŠP¤··w\¼nݺ(4¬­­-òFˆ3š±ãŽ;nR8}ß'Uô\Õ4mFD§€íK¥R*BeÖ®]Ë…^XëfŒ+•}Øãþyá…îѧç ;¬a” ÃË3صëŽ;îe,ËŠúådPOåJ C\‹ÖÖù žL[Û/yé¥ÿB×u¼ÝÞž,X°€µk×2wîÜZ7e\¯þ9wî\Ö®]»×œžWÔ$BDdJW(j’ÈBô{IA€ëºAÕ0K§Ó$“Éh2NFL¬¶Š¦~ÉñwÌ!ñ> O©nŒb·´µµÑÞÞΑGY릌+Smn«PTCÍmGfOç¶ ÅÞ"ç¶Çw\­›2®ÔÛÜV¡ØÔÜvdäÜvwbŠaèˆTÒÀö'Ÿ,s‚Ëf³´´´(¥bÔ´··OÈÜvT*ŽãÐÛÛ[öp×ÑÑA[[Û˜óä ²råJúûûYµjU¤566Y·¿¿ôê¥bB0 ƒ|>Os¼h¯bZ2\ß„ÉïŸÕ"A ’Iá ï8ÐÞ¾ÃØ{ï÷± ë¥zõ‚eYضÍe—σŽ÷~€'Ÿ¼Ms&UlRL,õÔ?ãø>!"åU†’Â2QœétMÓð<˲H$äóyLÓIJ,‚ @Ó4lÛ&‚‰ÿ½ÇSƒ!D_ß? ã÷žU¬!S@ÕR™¨¹­"NŒ¦Ã0šÑp"Ž3ݨױS¡P¨þ©PÔ3µšÛÚ¶xÆÒ5D:iàgox++&<–e©EÍU„J5Ö¬Y³Û°®j\zé¥455áy^Ù ¹`Á‚!û¨‹¢cžçÍøÎj†R€§9ÃõM˜üþ©iC3ñ˜f©¶µïûè5°"T«W]k4M£¯¯Ó4¹é¦¹,^|$>úZÜ¢'½bzPOý3Žïƒ±¢~ˆ/ìÝx†!žç¡ë:¹\Žžžt]'“ÉDé¾t]GÓ4r¹\MÆhÀ‚Æà]òŸð¦@ÔQÌ8¦âÜv¦P-`ÓqD°™ÌÓ-ÿ'“¥×A þl[,K§Å6Ò©" Kû‘Ñ«¾/Ž×Ò"–§Óâ½ÜWüøÕ"^=¯˜7¼ˆm‹erŸ¶-ö_æûQàA j«e³bÙޤ߱ãàZuãB½Ž …BõO…¢ž©ÕÜ6š…D‚J%òq"S½+£aT*ãEgg'ƒƒƒ,Y²¤¬hQSS­­­Q‘£ÖÖÖ¨ÐýÒ¥Kk}p]·Ìˆ31M×ug¼°4]©oNvÿ”FŠJáBÔ H§mÂ0¬‰ £/¹P ¤à£ii\÷GµnŽbœ¨§þ)ñ}a|Ìd@÷uS, 0öºnJ†¸®K>Vëdwi6“É$}}}v¾#až öŸÿ•ð¹H¸¨ô_3ˆ©:·ê„¡øÓu!4†x†âÞ$oCŽ#îS2e(ˆ×®+ÆË0„¦ A"—ïS)ñÞuÅ~5­´Ìþ'Å”LFÇ4Ų\NÜ#åö†!Ä£x{”BŒa”"Oäk)ŠFiÿò•⠈슚&#æJ×BÓÄqdР<‡DBœƒï—æ3®+¶C±}&wܱ˜7½é¥ZÍ{E=Ž …B ú§BQ¿ÔrnÅ9\^x†ÿûü·†Ø}‚zK¢˜±Lª ÒßßO?Ë—//[¾bÅ ÚÛÛioogåÊ•,\¸õë×ÓÞÞNCCCM/mÛxžWfØ™‰X–EKK ™LF)ÁÓÝõM`Rúg6[ªŸR‰çyضSzzzj}Éêi˜ùØÇ®¬uSãD½ôÏ8¶ …BL‘Z»±çJB†ø¾¿GcnWWaÖd|2/†àÆ?<øjìã ã •ÄTœÛÖ‚Ê”Uq#¾ü, Å@Ód4j)¥•$2™’`âyB¼Ž¾/ÄùY_Ÿ dú)tu‰ûW2)ö_(ˆcf³âA^ÓJÂD>_rðÇhi)‰RÐÑuqN…B©½©Té|r¹’ÀQ(”æ:R’ç)ŹO)ÆèºhKKKéæó%ñÇóJçoYb¹e‰ó‘¸eIç”’ø®‰¿ŸÔãØ©P(ª*õK-ç¶q­ä© ŸáÙë¿¶re´, C•Ö\Q7Lª ";ßp´µµÑÚÚJäPK<ÏÃó<ºººjÚŽz@Ó4R©---ôôô(Qeš±»¾ “Ó?eV¹jådܧºB`^zéµ\{í·ùõ¯/âK_:RåYŸÂÔKÿŒ“É€¡#R\ÝÀë³Å…{ÅØÒÒB>Ÿß£>î8aÑhY^1ÏOn µ\‚ ‚±E¤š€©öÂïubßô˜çA3Ð…ª§2˜jsÛÉ$„¡?yê8%‘CŠ!²nšãˆÿRH1Œ’²e‹X/‘‚„LSÍÍâ$#KämÄ0Ä{9•—‘,P:†ìòrÝ û©ÔuS)!nÈåòy^ #²= Ú"#UZZÄëžžÒ¹ÉH˜ û“)¾_˜¤8äû¥ýJÇ0ÄŸún:;zÉçOãñÇ?HAºÎ*¦%“5~Êú†ŒLù›S²ðí…BaÓJ¦R)ÇÁ0 lÛ¦«««¬î—ëºø¾?âä[Ó4<Ï» bŽöž‹ÐÿõpÏy`#ReF¿+Åô¥^æ¶ã@d4½®— ÷R H&K†,Õu! ˜¦X¿¯¯$pˆ”•¥Hiü—uPd¦ì¢ñ‡n)4ÈcÈךV>¯ˆßb*o2í—L5òâÇ®lÜ·<žŒ<‰o—É”Ä$¹Žï A#o§o*o•©TI¸R¤Lüºæråm—×RF¥HË÷áå—Ÿ˜P2ú§B1ÝPýS¡¨O&¢oÊ9)Øüóͼræ™´Ä&=²®¦BQŒJP‘¥··7Z&É銌LQÆÛrr¹étÛ¶ÕL1®„aÉàR T´Ø8星óØc—qÚió«_ý‡n'›Íb¦iª{›bñ}°® Á{TI†Ø¶ïûèº>.Ñg–eEû‘ûN¥RÑÇqH¥RQ2žN§cçç+ì¸ÅCÚZ´àºŸƒñ“MèÉcÐú€lñ)S"#&t],“Q%¦YJ7¯ë!#>ä#»ŽiŠ1?î³$׉ R|‘ˇó ?ÃâMWÃFuV¦. •ç?ßÊ[ŒZI¥ªo3œÞ[)Å©v»’û’C²6 ˆc_ýN&9‘B¡P(ŠŒœ3àÀ~Ýû{_(›üضeY3¾Æµ¢>ÕL¹­­¶¶¶Z·uÒEŽÆÅà(s©ËCøVáÁ*_w×ó‹!»Õ@x»êÅÏk¬cd2’ɤTãŠÌ^™Óu]t]W‘bcdÖ¬§yöÙó8öXƒÇO2gÎÛqÝåºëîåK_R¹G{ŽçA>DŒ_]ÀF̱Y3Óét$î麎a{Â[©2ú$“É ë:¶mGѦ‰D×u1M3Yäö†aDi¿ªµ%›ÍbYV”Z¬ÚQx÷«(ܦª¥¢˜H1D¦³ ‚rçÙíæÌ) ²^ˆe 5ÖÇ®Ë×*³§L}å8ÕSÂð‚Îîö;V&+“E¡ DÙFM×ÿc;èÛ«}+ …B¡PŒ–²G¬~÷âáüc… (•JíÕ3£B1žì[ëL6ñbŽÃaÛöØŒ ÕE#Nñ/Bä_H×O·Í?K-Åý耆Z²ÅuíØ1„Ø2în>ßK¤a;žNE¡Ø[†+FŸÍfq]W œcD^¯ X±b 'ž¸/‡ºŠÁÁ_rÝuÇÕºyŠ)JÔOC„X 3fË_6›%•Jaš&¦ibÙlvÜÛjš¦†a4nåóùhY&“!Òé4aâ8¦i– &rœó<ß÷Éf³8Ž3ì1õ×½Špû¸ÿq/ÎÞÄ~' ÅDâ8B, C‘¢j¸@ÑxT‡e‰õMSê§JškY˜½–XÖž‰6{ƒWå5kÖαïH¡P( …b1 1×¼|ßžvXY¸®,? PÔ cŠåîèè`ppU«VÑÑÑÁš5kÊ>ojjŠ ÁÖ#²ØcYn¾ d‘£Q×É"Ä—’¡# M"š$@'~ñ3)˜HúŠËâŽ4,ËeBHñâJ@)šEzòyˆh– Ø¿x‹qjÉçó$“Iúú”÷šb|Èç‡öKß÷£´@ªnÏØ‘¡°" ¾óeüá¼å-ÔºyŠ)ˆ,tLš’ó²>ºkÏó"¡/.†QÖ¿G“RÒ¶m‚ @Ó4R©Ôˆlñ}ËH––––(µ—®ë‘E¼ŽJ2™$ Cúúúp˲Ð4 ß÷ ‚]× ÃMÓ¢TbÚüydÚžÀ»}nñ€ˆ±Û |ÜW(jÈHi«d!yYô\F¤ìΧ¡òójcºb÷x^™Ì §2[œù—_ðÜs¯­õåP( …B1CpœRª×ç>ü§¼õ”²ÏÃ0TÅèuŨ•«¯¾š[o½µ,r£µµ•U«VÑÙÙɺuëX½zu­ÏgD4­Tr¸‡¼d29úÂÍ „xay„ˆ‘¢$°Tîf¸ËÑ„ƒ³Œy ¿´7߆@#nÏ™Œò"ÒZ \”Ñ€žR›!ø¤‹ÿâúãÐFÇqpGEª(öiä©´‡zžW––G *cCŠœò\°:æ˜CX½ú`L³¼ø¯B±;<r²î׺¤L%ë!ÉZ%‰DÃ0Ã0Šéëë‹¢DdDH†QD‰axž‡ëºQDÉXÑut:ã8¼òÊ+eŸÉ”_ñ>T #k©äóùHX‰ŠÙ7lÀ:êØÿô7üÓŽ&uÕ\Í büUÏŠI Dm²|^Œ³ñgR]sâ0sbÃËd±ù|^üÍ™#RåÆk¦LgÂP\—ÉN¹UÉd;_f³Cùú×ÿ‰SN9¬¶B¡P( ÅŒBDG¼ôÒKèžW6- Ê‘[QWŒJP¹õÖ[imm"¦ÄY±bŽãÐÛÛ;âzµ"J)\whák ò4 ˆÿî… ½ö0÷EðWƒõØ_…Ì,á͆¥<ÓÒËMÓĪrâÇöýqðâ3F±Ì(þ¹±×YJéÂö  ÒÁ¨R´(ÕðýRžõ8®ëF¿)•îkìÈþ)‰‹& <͆ ›éê:€DBªE )qL“R +€drDëc†´´´på•WÒÕÕEKK Žãàº.ADcnåø÷H’©ë¬X¥êT*¥ü‚Rz@MÓF-¾f2™ªõÒ¬ŠŠØñuägf¬Ciš†¦ie‘5™ãž~Ç?æïÀûù;R‰œÀiÄüB= (& BH>/þKÁDNqÃPt]Mƒ-[Äü4ÄçñT`²¸üLAFêŒÉ>H‘k2Éf'7͘B¡P( E!ì8Ùý³à~*2ž¦Óé¨ö¦BQ/Œ©†Jœ¶¶6Ë–555100PësªŠLkSl6K†Ü~{ a¨“Í""9^æÁ¾ÂÛ ëbèºaèöÒË[æ–Cq3ð}ñ§iâÁH.Ÿ3§ä1(·‘9“e¥Ð¢ë¥m¡ô€§iÃç¿éU,mC>"˜LC²‡q™L&2"©œ†Š±Rí^z|×ZHñ}¿¬>ÂX="äyÄ=í'k =ù%2)À9缆ƒî@vzÂ𭷾ȇ?|¿ýíy|úÓçpþù xž¸ï(g…ïƒq*b¼0–ÖQ D‹-âúë¯gŸ}ö‰Ò{e2™!ÂÅX‘"Œ¬§"£` ÈÞ{žG*•ªÚïÇsº°áÇ´,+ºOØé4ÿ‘ ØòÔÏø×_O¤ÖËID„¨zPL®[rì‘sÉ8šV>ö×ðºÒt&æ‡0cµr …B¡P(j…ôÑó}Ÿƒ>zü¦ôÙpÏs E-• ÒØØ8D(ijj*{?88Hooo­ÏgX<¯ôÀ·ùû¾Ï 7400p`aÛ ÏýC Ÿ/2ºÞ>ò¾e¿Ž‹²˜gü!U3e”L.Wú\zÊך&ŒW2“‰®‹Ô º.ö“ÍŠÿù¼XgT){,J) „­âQŠÊƒ&" Ä2§¼çyQ±^SåRŒ‚Db¨¨âûþ^[÷Û¶1M“l6KWW¦iF¢¡¦iX–‰,²¾B"‘ˆ ¼R„‘ƒ~¼ƒLAÍúˆ®ë¸±Ü‡òþÒÐ0ÀóÏÏçþû_Çe—màß8‰ýèïœpÂl¾þõ¿sÊ)âå—Q(ì «˜òø>kÁz;BPqÝ¡¹úŠÈš"«V­â‰'ž ‘H iÚ¸F2ÊèYcEÖVR½ù:™LÒÓÓSÑrÇwð¹Ï}nÈ~ÇÁ4Í1 ¨š¦aÛvY4‹ìëŸL§ijº•«¯>–ï}ï41ö&©9U?RŒ#a(ÆTM+uͽÃeÔõL¢Ö©Tmê¨(§ …B¡P(µ" KѲço8ŸY¹Y‘ "kmªú)ŠzcT‚Ê’%Kèèè`ݺu,Y²¤ê:ŽãÐÐÐ@kkk­ÏiA i¥'Öþ©OmdûöpÑEwðú#þÂÙ×ÏÁ8 ¡²;TVð” ‡Ìñ·›(LF¬Xã2òuÜ£\¾—HrÛ^2™®ÑÐ)Û Ÿ1 *AÉdÐ4\.GKKKTàW *Š=Åó¼IÏ)jYA …@^*CMÓÊj)AÕÊf³eÛQä–a$“É(z¤¹¹™B¡0éÞÒ-ή0þ]<ûì·x晓NÃO~ò’É îDZÇËÀ€Æï~÷;l{Qtÿ’†§0÷#™.FÞã§Uë*н'À<Žò±q˜/Õ¶m\×¥µµ•÷¾÷½\qÅÖ.Ã0"ñ$’ÉdT£E¶ÃD"A*•ŠÒ…mذ!ÚFF²€H7(k½Œ9j°¦i î¸cO}j0Z_óÞ×0ËžµÇ‘¡ E5ZZÄ}x¼D™k&QëqªbŠaÔæ¸ ÅTDf‘éÄeý©8¦YúÜ0ˆ¢½åzòsù™aˆgyyÏ•éà …b¦/…ðŽ¿¾cHzäÔL ™VL F%¨455±bÅ V®\ÉŠ+hkk‹"TdÁúÎÎNV¯^]ëó©J\L‘ÈÄ_ÿz>wßý gœñ6h¾¨-2’}3›VCÇ)=¹¦Râ/«T5bwˆ € g ºóÅ¢…Ê,Ï©à8¥YÕ0Þ¿2vˆÃIaEÖq±,1A C!É Ý°˜@aÜÉßk#_YX8þ¾§§]×innžÜ/Y1e©¦?ú¾?©ƒf6›DÓ4«Š22E"ÛWit)íŒÜ’^ú–eEéŠ&;"Dz,’É$…BLFã oXC:½ƒŸþT|'¯ý|à‡så•gâysçÞ̱ÇÞƒ®73kÖ,Þ÷¾s°¬’€R(ˆûŒm‹ý»®X&‹Ë(AË*­L_(ŘjŸ)j‹w¤§4.ŒðåxžÇêÕ«yßûÞÇw¿ûÝ mW|,Òu=ª§"û”ã8‘ð/#Ëä:¶mGõOdZ>™.l,N»«#vþù |â#OóãÕ÷‰6=ípå=W2xÜ ‹/_<¡×G1ý‘SÏ®®ñdÛ™Æd8ø¾®ëhš†W G7M“­[·ÒØøw`NYÔ›¼'Éû“ü3M3„MÓŒÄeeçºn´Ž¬1%VdDùÕWoçÜs% KíÙ°aC]:É)¦'²v” |òu–j.JaÂ÷K™äc³ç•AÌgeŠm¹N.Wš«¦RâµÌ !SmË}…¡8¦Ü6Þ&ÛÇ—í©œ¥Óbÿ®[:Ÿ (Õ¶’hZÉiÒ÷EûÓi±A;w_ë¯L¡P(Æ™‰' C-`¾6?ò‚w]W¥ûRÔ%£®¡ÒÞÞNcc#Žã°fÍš²ÏšššX»ví˜&Þƒƒƒ IÖßßO?MMMC>ÛS\zzJï Cø6nä¸ãnãŒ3®舔X•6”tZôpi,‘Âø“«œ ÅsḮ˜É™`q}ÃkŸ•fm®K`š¥4Gqq¦èö„ᣑL+&<æE†ë¯¿™w½k›7o «Ë —+pýõ­|å+§pñÅ¢iÃÐÈÔ_2‰[¼#DÕUóÞ•ËdФJ#q´´´Ïç£|÷Òÿ–)ž%†ë›01ýÓ¶ËkZKÏòɈP‘"q1e¢©V|;ž*o²Èåreuavì“”k¯Ÿëúy¼ýíâµïëÆ•Øö.’É$–eqÌ1_$—»¦x_‚0ô1 BA¦T·½ææ’6œH”@§ä†%QÆóÄ:2ÕŒ¼$©Téáv„èÓžÉîŸ×sôý(¥©ªòEø¾OKK —\r G}4ßùÎw†DmLÒШëz$žÈñÒó<,ËÂ0 \×ú›Yweš°l6³r™L·»ñIÖJi²ÿêÃã×÷Škž÷ðÂŒmoã쯜=)×L1þLÖÜ6Žm—Œœ3}Ê$¯¿LÙ'}&ÅÕT*ÍÂ0ŒÖxüq‡tZ<H!UÖA C!8hš¥( ¸®‹ïûôôôÙl–B¡€®ëضMWW†aÐÒÒ‚ëºeiA+Çâ hnn¦¯¯oÄq:ñÚÕÕͱ+I$X–5dnétšBá<>ûÙ_††A¡Pàä“Oæ©§žªõW:nÔbìœ*È1^íãZ²Üž\&ë€JBúÊ{OÜqOÓÄ㳌H–ûQ"’jÔñÏG;ÏîÑ<žq¤i¯-Ë*st’¢ª|NÕ4-ïã‘`ò3 +ç³g¿B6Û9ÊûGŵ*¥Ê–¢§8Ž.êצ©±ß~ioÿ_ùÊÆšüV& Õ?Šúe2í¶úCpNçiüéÜ?EË¥ˆr¾VÔ#cT${ÞÙÙIww7ëÖ­cÅŠeŸutt°zõjZ[[éííeÙ²e´¶¶î•â)Ó_ÅÑu±ìç?ÿ×|ô±°Zî`é ²§Å†™Ê ™®ë$“I2™LdŒ‘d–e‘N§QØ6©ëxž‡á8h¦ šÆ¾O`šX–%&d®Ëìlÿ¢‹8ïÍoæø3ΈŽy÷ÝßÁq~ñ‹ž‹8ãŒX¼øÖ¯ž¯~µÃ4ÐÑE„NH)·»|ßRüï!ÄM^Ï¡³SÃ0Èd2$ òù|dÌr]—žžž¨ÍÒËNæ·—ÆXé (UÎĉg¤¾ Ó?«áyÞ¸ ¾ï—aO¥Ru6ªiZtÎADý¦ÖbOµvʇ?)¬HYù^žCsssÔ·mÛŽ:³Y!ÂHcTss3–eaYç÷"+V|¤ø ™+zó–,„®›&•JqóÍÛÉåÎÅqàŠ+vríµ—µSÖ•šNÆÅZöOÛ¶ïdH§mÛebøOúS@Œ“yß–u‰ª<“¿5)ŠAJ€Èp"ÏK¦Æñ“#;3gòÉ >É…'_È£¿|”‹O¾˜;¼ƒïàÂ/䎧ï ùê$¿ÿÛïüÔ ¿ÿËͅ]Èö[·³~Þzn¾úfŽé>€]§íbí k)¤ ägçùê!_eÞ¼y¥“³`ëš­\ÿ“ëùÜ?pÿÿÝÏË×½Ìovþ†x šgKç²sw10÷ÜZý”ÆÕ?Šúe²ç¶A¦ÿýæoðüüçË>«'»Bg•½aáÂ…455Ñßß_¶¼»»›ÆÆÆH¬Y°` , »»{¯ÔNÛZ†DD¬¸¸®ÆÂU a¥”Wq¤ûÍ8!£2<Ï‹jDÄ……¸'¬®ë …2ÏK ˆQ67-'¸Ä÷áï,OIe{"ƒ™É—¾4›O|âq¾ùÍýøñÉg¸œ~ëé,}÷ÒÒ~µâßy]Äßîô¤Ñ:NÓÓÓªª…ìišyõµ´´ÐÕÕ…mÛ$“ÉÈëG´[®U<åÂd¤jšî ×7aâúg%c­[0Zâ)åêu@ŽŸwܳ¶ž½1â^ÿq¤‘FžSKK ŽãDFèøúR@Íf³,]jbšy²Ù,Éd2^â)J¤á,•JqØa¿å›ß„›nZÃâÅGÅHŠ\龯ï„Z_¦q¡–ýS×Áz!¦ËŸiò›ŸýŒl6‹¦i‘ƒÀW\Á+¯¼RU\¨'äo7Å’Ëå¢49ù|>c¤á&.®ÈñO:AHøji.ezˈâ¼"‡H‰—ù‚bgŸ0›­™­p<ý›§£ß¼ŒÚ«÷ûÁLf²ç¶×-÷¯7¤Ø DÞØ²¯È|ØrÞ+ïóq§#™Kþîå¶]]]„aHKK ™L&š3ŽFÈÍår‘ÀQ)¶Šÿ#ŸÓÞöÁÑ ¤ãéP1š}ÉuêÍ‘co©‡¹íx¯%"#ER©RÝ9™bË4K©U¥s¡ÌØ SHÉz›RHÿÆ"ž51¦ÍzÃ,7à”£NáÐseçWwòðÃ000À“sŸdã~9õÉS™ûÀ\vìØÁ¬Y³˜3g_øûøú–¯Ó7»‡–½GòCÝãŽO Òа7¿¹ÆÆ¿—²tÀ K±Ï!&ˆ:brZœ@Ësñ}?2¨Ž„®ëlÙ"”›|>OKK ===QŠé‰/*,«Ò;Ñ÷ýÝF8HqgoY¾|97nœ…;‡ë›°çýó–[n††plj c-8&#›âQP’l6cª}^ÏH/;Û¶£´ISÍK=n¨êééÁu]’É$}IþeÿÁâÞ¼¶mÓ××G6›Òš¦I"‘ •Jñÿg1þÕ¼úÕ_â;ß9˜\N >ö±áyO=ut­/Ÿ0ÞýóÙgŸeùòå,Y²dÄɯ,ܪ…”G§ø>Û¾ò•²{í7ÞÈ–-[&¹ÖM&{n ÂP¯-Pkdte&“‰úK\L”óß èà##IâQ"2}äHý)>ìéé‰Ö¬T™u M’E üaGZ×åC,8Q ùÌC)RHÍm÷~n;ÞȱXÖ§ ÃRÔI"!>+JuHL³º8XÙµ¢!DŠŸÈØO€xÎKSª7êQxâ¬'ØqôæÞ5€¯:ƒß}7Ïîs ›ö›_ÞÌGø×Ûðuþºß:þáà×òÜkNfgÓœ?—“N>‰·\óžZúS^}â÷ihj€0dÓ›Yõ__æãá´ðPNs6A—Ç1±ñïï!8íYN[{|à‚ f1‹9qá² Nêˆå3ËçK¯Ãü¢ ’õJ4^ôEw •Ý×ÃqÄ_ªXœE× Ul“å-Œ<À,’E¯ŸøQ<ö7Ów¡¡z ·7š\uñUl¾w3úncŸÇ¦‡sE­æ¶ ÅD æ¶£›Û¶··W-až ü7x‰X¶ß'¬H³¬Pì ÜrË-ã>·tAe8†,MÈØqÇ7¢˜R­x±ô6Õu]Lˆ Ä„QöS9k£ã8Qúyc¨‰aWΪ 1,NBËC±›ÉçûÐ4X±âEöÝ÷N;m×]woûÿòéOšk®¹‹åËOço6hÂ#ˆ!ª8Åk(çxÐ_>àË‘ñs,ž}š¦EÆWé-lžç‘N§£‡ö0 £\ØRôq§,ÕŠ,¾íºn”ÊE¶'žŽe¬µ[Ö®]KGGÇ䟓̞öÏ /¼°êg”~Šq€çyei2v‡ôØ–BŒ¬Û#ÓK™¦IOOOéû”Õ{eî0Z÷H&¢—ƈ¸°*“@Ë\¾?ôétœÐu|>ã8å÷¬)ŠLµ4šsˆß# Å›x¥±¬§§'z}å•džŸ¡«+WÌÕp×]wñä“OrÖYÓCP‰=éŸsçÎÑX+‘ž®Ø”Lß¶mÏ<óL$„µ´´L9á²q1Hö99öÈ(u˜*£O¤ã„`dÑû!*EägöOÇüàùèé4SY×[‘Çì~OìØkløö¼íUoãðççÇ¿üq4fMµÈ•¶¶6šššÊjòMG&bn ¢_f³»¦˜(â5d¡tÎAAD¢ŸL±†aYZK9X–EKKK´ýXǸ²ûãˆq}8‘Qæ:’îø¾_^Ju%²Düét¹K|Ά¢˜®—Br¹òy„ã”B ä1bã¾/ЄŝE&S~^®[:_~f‘í×' Ë%+|=Ÿ¢çs¹œšÛŽÀpsÛñBNUS©ÒÏEÓÄœ9þxR­ÿ—u!)z˜ˆç4( Å?™Ò9aa³<ø%p”Æ–Cú¸MÛÀþþÉl:h‡ Æüo­ç™ŸýœÍûm¦éŹó”SØÚØ‚v øx>ÏÀ»vðÀ«^…f,¾x£¨*›ô`}«4§6ÿ¡ôû>nØ,ŠN㤜U:qÏÞ[r‹ËtX¤UÏ÷ïGr./‰ ‹ CEH”N—úR*%úX2)Ö•÷×ëåó¦°Ð€Úp\_«°-$Ñ}é¢çŸççº.¾ƒtQ-“ý\3!€#/8’Yâæ ¾üÇ„ý뉜Û*šÛŽÌHs[ÿRÈ= Ýë1¡{ÇŽSÖyLQ_LÔ¼­n•jž ýýý{Tð^"m£•ºˆ,4‹‡ø3(/D{d$u]×uI¥RQ¤½¯9–UНrc’J‘.çÄb>Ý‹ùÌgvðÄi.¼ðNvîœÅ½÷>ÁÍ çózÉçòâú”êª4# oE#\ëA­üüÒŸsvêl1qwŠëJ<Äò ÕÒ2”§0Ó£u|ß ë]]]¤ÓiÅGÓ4ÉårQäB:ŽRÕÈ›·4¾KãY|ß3•ñÐx6+~’©ÔØÄ,)Tú¾l²Ù,k·oçÅO|‚>ö1RsçÂxg®äE÷l=>lòá æ[p¤Qÿ5„#Bx&„ƒødªä¡§#À¾çÁ_¸§x•FŠtº$¸T>ÐIÃêî/©TŠl6¥K±,kÊþ Õîq •JÑÒÒRV48“É`YË—/¯õiO81~BÑiòÈœŠ¸ÇÇì¿øÂ8þøã¢¨Ë©.¦ G\¬ç(s2’E¹Îf³e5ÑâÛĉç‚Ï}ù¼ð]¤2ûA"A6¦ Ó{ÉM xrÓ“é€7ñÍÝ}4 {rßÃ÷1û ³I§ÓQ}éé_Í¢˜|&ªo¶´ˆqs²2 ø¾E}ÆkÈú_ñÂÍ•är¹’˜AQ4‰U½ßz ÓuKM0T¨(¦ã‹ÞçóCÇÒø> £üÀ0ÊÝú¥ÓD|ÎQÙW*¶©TIñý¡QšQ˜Cˆï£†±û}är#;}lÙ2ò>â××¶Ñ=pÊQG1S˜¨þ¹§d³âkM&ÅôѶKiL÷hxu(eÓ/ ñŒ–/¥äËf³èÌzp'‹n»ýŸ{ŽÃ_z‰Ç÷Ù‡Ï;_¸÷c]bñü¦M4äoãŒUæïÅ9À…o{ùqs¹(¢³ï¦›†¶k¤h2 °FèRب웦9¼˜ ¥â0’Êíe1ªøú’d²Td¦òÕúk3‹yó>Î '¼“?þq1×]·ó¿û5î¹çJ¾v殼ò!9ä! ÚÛ—Ñ1oö[о4Ã}p6gCÂà 8Œ¸`±&KBî! J„w•Z¨‘2Rb=[|fzf”¶Í0 þð£?ÐøX#hˆ;ðÇþòÛ¿pÒ»NŠÄ³¸Ç»ŒˆçøN§ÓQJ± èëëbìÃ\.Ç÷¿ÿýZ³Êx÷Oß“Õtºô[“…ˇÅBزe …FR_LÁÓ!¼! µ3ÅqŽc¿_î+èÕ ¯‰ßG<%ÊG,ð‹9â ×I–)ÂõÃⲕÀÁ”r!çMxÞ„]”„D?¶ŸxÖ„þ¾ià \žŸCŽë–E‰Ed„§eYp[þþdZY€w¦#…¦–––(2`&]—q?m €–ïC¸hÿIɃH§wþ®]œ÷ÉOFi~úvgœfHA_¦ÿ’c¾ÿ¥è+À₇ë¥à‘Jéø~1¡½i¢oÝÊV[#{é3ä®~>šÈóÆ…¬8þo\òÞ££ïiQ¸Þ W_s5s¾8˰X¿i=ŸúЧøÚº¯E)ɤø {˜NT±GLÔÜ6^"o¼‘i¹dªV"H.—ÃuÝèulH&…ö'*ïžWú ÄÀ«Ùqô–-¥ ØÕÆÂ¸{¾ô$¯\owiz5­ÜÐY±ˆÓI@Îd ÈýüçPi Ÿ¦LDÿ ®+~†ÒFdÛb™üù[ÿˆÆn™&YöïÐ #ñ?žN€þçèµ,}~Y|¿W\±ÛCg2™ÝÖ33ÙlIP™L4M|!{Òçu!Tq„f•/UŽÇšÆcÇϰ£³œÂC¡°øÏ&»z^©F‘m üS잸c…œçÆ… (9EÊ,!žç‘Éd°‹ÎñZ…¦iFsX™]D¾ÏçEÍM l=y?óŠNqG\.Õ~”ö Êv!çò²r2¢\FáÊÌ'3•‰xîôï…ÔÕà8A™=è¶E‹X9Þc‰B1ŽÔ ÒÚÚÊÀÀÝÝÝ´¶¶ÒÛÛK?K—.Ýã}V‹–¹š5Mͽ˜“¥Ó騨|.—‹n¬²JÜ‹¯®ˆOD-«äÑ7¬aÇŽk9ï¼ýX¼ø$þýß/ç‚ îãŠ+6rî¹§qüññ­o]Ì·¾µ‰Ü¿,iÂõfdÀMíD+!»Â^È¿ ¼ã‹;×!ì†Üg€›!ü,8ß‚œ[ü~Ào=è @O#ŒßyÄ$SþîSÈ)hôiÔ…‡Oa0”aîˆ÷©|ª”úMÓ2Ù¾};ÛÖnãôí§sÓò›008uû©ƒgþûî¿ÿ~¾tä—8üðÃký­N(ãÝ?=¯”îKd¬KBgÙŠˆïÿûhB1ÞÆ;€Ï ŽÔà0 ý}©R:¢»c¾ZÿŽß¤]Eþd”•\–‰­W,”–eÍ ?¶mØ–ø¿<x¢ývq~š4áí÷•éâ‘-±7]×KuŸ(¼t]§¹¹™B¡€ã8Q­•™h0•Fê™hÜ÷ñÓWshçm!üÈåÿþ>üÿþ®ëò‰ýˆ­³gôõ)MßtB‹äCbOOOdˆ–‘°2]˜ôÖÕ4-Jdšf$xôõý‚Oú`ÞøF1˜¥RðÑeëXñã-¼ï}ÿÇÏ<ûþ`38ø;à<ÑyÊÁ1oþ?|ô‡\uÓU¥“˜y·ŠIe"æ¶ÙlypÁÞ"…@é AyÊL†IY+=»ƒ`øêÖ»±JýhëVìÝ=0Ë ý ß&]gÓAñª}¨Ö-™4&¢ŽD–¦z²`¼| ëé)ý´÷ÖN纮HߤH4'¢ˆEùœ*U]whB梩Tm•½áNŽÖ)Š4WE²ôä!ÙŒuè¡“{ jÀd÷O)tÊnQ‘qZOA+MÓ0 #ºo†Q–e%îp*Ÿ?¥£ŸAd v)zH'I¹y Ú—Œòö}Ÿt:9Çe³YLÓŒ²‰È”¡2R¶P(àyÙl˲¢L2Z6‘H†!}}}Q¶x6‹\.‡eYض]–¶XÖr‹ÏƒÒé4¶mÓÕÕ…¦i477“ÉdH&“‘ãž®ëeiçgãÝ7ÃNÈß(ƾ†nà,Yÿ(—ã7É$+k} ÅÔ "¯ÙÊ•+Y¸p!ëׯ§½½†††=ÞŸï˜u]w÷žË©Ô°“'-ëw€PÚ«MJ3“•‹ao0 ñ×Ü\.íy%‘Å0X¼x?Ì×oÃ0àßþí3˜¦É¹çîà“ŸÔó…/Àå—?Á 7œ†¦å9ù¾×ñ¶·=Ìàà|ï{Á{> ‹<,ÓäG[çpÔKyôÑßñâ‹Mì?g¼YoÂÞr‡§B‡-…-œ|òþÔý|„H¦¹ùKWq.o#Ù|ðøp5D^é‘0†yoRn*÷c™¥ueÚ…LÁ…ºHg"Ä3'¶»#„ͱ<ï® ž‡QLUº8ñM¥R‘x ½âãÞ@š¦E“Ò™€alÙ]š“iʸõÏȉŸjæˆô7®ÆæE‹øÏßþ–Ó òùÌåóylÛÆ²¬ÈkN *†a°uë8þø-ҸモÐõ{þ¼”yG›«¯[Ä9‹®ãÍo¾Çñ9∧žÐÇY§Ý¿]uqÑëØ ·w+WÎuªóG Aãñ‘hrâ'rÕÙWqí{¯åò#/ç _TŠ5¡ÿ€~š^l*EßíÅmC>DϤÌáï¹-Œ¦Õð±m2™ÌÐÈ“± ½#öè\”@R/ü÷W;ãŒZ7cR™ˆþY ×Ï™ÌÐ`ª½ñ‚Ã0‹]×¼§[ç·òðª‡éûÈ4r0‘µ ';Y׿|Oç:·ºð‹Ý *#:DÝç)1.÷ôà~ìc\8¹W¡&LFÿô¼RV·øW\ëG§xš*±!#:äs |æ“õþâóMYgT ™L&Š¢–ÛÉýH' "Åt: ”ê£É´Ó---ø¾9BÚ¶M.—‹¢Ö3™L´ü]777£ë:…BMÓ¢y‡ïû´´´D™^âΕñš„¦iF¶5MÓ"GC™z4Ž|.‘órùZÎÃå9Iâ‚O|›ø<à•W^(»62ú\îçØcR"OgÆ£o†!¸—Mþ2—<ó Åëç8ΞÏKŠI¢f‚Jµ‚Dmmm´¶¶ÒßßOSSÓ^…túþЂôrÊçó¥TRÕæ6Ã<Êí¥÷)Ýà§<• zu]Ìø“Ièë#ÿÅ¢aí&d2âæÖÒ‚ÙÕåÂÖ4hlüÇóZðý{‹./ ¯ï»‘‡ô|дC Ã3¢A*™Lb)¾ñù§úÏ?»v=Ë–-=<ðÀ Ü~{x#/¼ðèºEOO™L3×^{ýèó¼ðÂ1üßÿ=Çk/z‰ŽGGø“Í›7à&u^|ñÂðõhóà°Ì_øßh,]*Š^yÅ)dòbŽžÍÂë¯èç¶ývòGàé;gñ™#ÿõûßÌÿÛÿ>÷Ù²Y7^r§ö,7Þ¸‘wÔúûG†+6^ý³Z¤ºã8x-´ "@d ¸b¡ÌÛÄ÷o¹…[î¹gj••Ä'åïÖÀ³ aèô4Å:-èV©‘eÁó!\–Eÿd!òH7\—×Ü}·èŸÅªáñç ¢÷‰D" ‘ÎçóQHó´¸oÍ@&ª†!4 =GÓ ¹\cIՑͲøßÿW>÷¹hMÓÆ?¥Ç4A>°ÅÌd=5ùàj™L¦øà Ùì>ô!áUçyÂKðÿüKÐ?èŽxØ=nóq\pßÅüßÎÜ_\Á£=œ¾×/eß}O$—;ŒüÇ—øóŸŦMÑÐð †áðªW}Š9sæðØcqâ‚Y¼û±oq|ëÃßâ‰;Nä÷®ì"qP3ç~ž¸%áÅ_äÅÃ^ä·R:¹âž•›¯¿™DK‚CÞx¸pã}7rï¢{™?o>'l9ï~—wŸòn>Þùqþß—ÿ_äQøÀÍpæ;ÏäÉ'Ÿ¬õW5®LôÜ6 ÷<:EÎa¥ðBˆ¯ŒB5ñÊÙ{4)jÏt6\LôÜv8Òia¤•Ï¥{c¤•ÑdÇVs¶m›-[¶”ÍLÓdΜ9ѾâÄSdA)ÚM¶!½Qºžz$°Ä?“HÕž‡s‚6 cØ´[Ã-·,kب¼¸£t³Â¡1~|Oo¨ë:ÿõ_ÿÅæÍ›ÇýwRK&jnþlh„®7ðâk_Ë‹óžâoD¤EVÏ™Šú¦®"T€q,}_Ø+³I/<ÄD³À¨Ò]Èœ³Éd’\.GOOOäa:m¨°¤·¡ë‚n)rG8ò !Äz@¾øÚ°, Ym<¢”·Ú U(p]—löMüþ÷ļ>^¶ž -K –ë×{Üxã÷Ê<'|¦y\qà‹“;Ñu«ŠÞ "§^Ü—QLy‘Â÷(_æþû_NSÓ#Á Qáô‡Òyæ›Tª‹d2É[ÞòJ9Ȧ7ãÑ?ƒXMFÀ'žx‚7½ò&f÷̆.†Dyôßy'Û{ŒÂ¯~…ëI 6•°ŠñÔbÕN'º)a¼´Ó¥µ³ÞÀ?„p8°Á4Cãÿýßùå~ûA¢¥Rô d'ò(J¥RQÚ¡L&‰Ãrò.'ÍÒ;i¦D·Lö¦†!¤[ÑÝŒûƒKè¹®üs×uÉÄút,˜IµjÆé'û•|P3MCÑ7Å<¹\N¤-¾‡ÒC¬·xÇýå¹õOÿÌ–Ã^ä©õÿÀ /èüí÷-¼gKÇ̳ùÅ_e˯þ•{ÿ{é%žyææÏ_O˜´´¬çó×=Ìí·?ʼ²uëEt¼ôCRgíËüãâûGßý÷žÏ>À;6ý§ôÅŸ×?Çc?ý;ÿ|ÜþùÿÃ_7¼–×ÜôkÚ’'òSØ9°€E‡žË«¿1‹E§½Œ~ŸÎSw>Å%d…o[ÈmÜÆÓóžæÍ}3[®žÍßý½Ö_ɤ0^† Û.ù»ŒÇqpŠã@&“Ÿ~âo<‘5õôŠePL›ÉÐTž#§ï•©\GƒœÚWÛŸOÉ@]ÙÆÊ¶ªÀ¬)ÅD)PJïµ»Ò=»Ãó¼(=äÕ½šóž8}.܇çç?Ï?/øgÿÖXJC+köéìYZëzŽ*ÔõÚˆ 2›Ãž†{ßîAàHiÓRP‰‰èŸ¾_ªG6Òô1V¤h Ÿ«„si*ŠÞ‚H¤£iWWWÙúŽãN§éêê"hÈùwåòx„ ˆyd"‘ˆjKVs¦³,+ªGF‘T›/¤R©aŸ«ÕœÊjVR¨ô‚.2’åpâÈHøá>nN4’ãX.—‹®g\Àù§ú'º»»™ ìmß †üÿ€~èî×¹óodÓy"­±Œ¶T(êºTÆÇ)Õ®ŒE§‹—ïîK†Ê0Æ®®®È»rÆxw[V)ÉoåDV†@çr¥G–*¹Ù¶˜± S¢¦iF¤ I9x}õ«:aøÖÈãWîÊ…™Û~8c¼ô–á£"ú`†±¨Ì¸,ø¾¾>:::jý-M¤íÅØ†¨o³ ž¾÷i~°ÏàvÊú¤Œ¶˜ûÀüÃÞˆï|¢s>O8{ò”OÁ»Mxâ9¤‹….MÀ7¢úAÿ=ûž=Þ™€$`vŠÁYƒ¤r).š7cº»! qÂ7p_üÑ¢ðñ×uß~;ÿ÷ç?cNqÂnBpŒO†eÿ“¡æeõ©Sû̓ä_1iþýç–ßê+¿[é 7åûb!Å)¸È|ÒñzlÒ“O>°_zé1üÏÿü…GÉDu[ ùÅs/îOôôo¡}ÛKqÄ›·ßË-¿‰Î_~™³Øç‘ah3+ø ;vœÃñÇ?ÍóvÀܹ_äÑGßÏÑ+wðÄÙ埦yý±ñÄqÄ”k»Ã‚ NG†™œ1–†WY̧T[°XKŽlqg)Jbƒ^|ý„ºXÇ TÇN zl]YO7$JéyYçeœ}ðÙ¢Ö˜[ü\ )JuÊôâþÓ”êæåÛÙÅu³±íeͳ4¥âÜòsyÞ9„?ŒÜ—[?\Ô¢´“ ÷”žùåu–uK×®¤5jšx-K±0!Uš|¿¼œš<†Ü> KÛÈï8^S9¾žfÜjÿ"el®üä¨ZQìløæê»Íç^ùy|—ÊSïð¾ ÙCÏ[ N?áEnzáföí;{ÈúR³,‹ã‹×>^\nÆqž. FÒH% %ÒàÓ#–Íe®0­,€Â!:_s€f8æLjµã÷<6¿éMO[ø]&wç>õ¸w=ù·šd=/òv:³«‹?ß?üâ™gøc[aò‘íÛܼ™/æÎ;ïäì /ÄGxEËïJ3”ýHM’êÿ7öÂ2ô˜‡Ͼ#‹©KÙqœ¨öÂL-F?ÑTó8Œp³æçaYV”ÎïÜØ>äÖòÁ8•J±í¦›ØçÑG9óMoâéä}¾ÏÁG]Œ^»‚ë.|Œ·ô2÷à^ØÞËŽ³v°ó§?ŒgqÏ}øÃüå‘G˜sâžûëõÜtÊ)Íé¯9;Nºƒwö¼“Ÿøcf½zç/Ú)yìøöÉd¹ˆ’É”–ÉcW~×étI³•éÉ¥©)•*]·LF+›ï-Kü—mÊffÆãjýŸ„ƒ ¿³øFÓ¸»·—ûô§ñ죲 (¦ÓNPI§«‡oJ[@<ÌU‰ “¹i?¾k§Óâ(FÀ4w?I”Fʧ 9:kZi”v]1Be2å¹fåHíºb=I±`w1WŠíân r4÷ýê¹k¥B¹+vÉ•A (ãŠýȽ¸š(Jã/ëËßxÌueн¾ ¯®?°ÆÆFÅ”¢_ºä›âaL»Á€Œ!j¸èpäID‘-ÀjV™ð‚Ÿ6@ƒœŽ0RÂV9Ë?ÀŽÆƒ¹wÝç¹úUqˆõF¸'à´oÚ0¸‹E¯~5»^~wãFºººp]—E÷ÞKÓ_þΫŸÝÀÀ™ é½ûn>=oßøÒ—øÅ;߉™Épíµ×ò?ßÿ>//Z‰izû¨|hQ÷æñÅýÀ}˜s+%~5ÅË+‹ÜÆ :r‚«¾ƒúC /£‰ =ìíoçÌâë£ ƒO¿÷½Ñg¥ûUѲYÅ¿hÿaHãÿ7ÇÆÆÉÓ*R\ïõÿgp…ïƒv hZ$².;ÿ|î½÷ÞZ_¶)ÃHYcÂ0$›Íâyï{ËûøÝË¿ã€PŠj0)E;Ȉ ÷v9=ÛÝ”§råè`hC¶“ómÛ¶±°¢ô%C2ÌŽ®¦W$hhZ¨E)̤Ô̵-S¡È4½ò¿4‚Éôyú.]Á®(ß<µUÑM¥RQÛåy­õŒŽk»‘‡²¦‰6ÉõdÊ—ÃN?ŒÏüÛg059øÙƒ9ìôøè=q¤q$—y9³Ùœœ9ŒHñZ: È£Å,‘iÕx0.1À€ïð²ë´ˆEàÃ{Œ÷p1GŸÍe.„0?œû^÷ ‹/_Ìùáùl7ã/ó9î'Çñ‰‚¥K—Žã/xú"½¥?˜aŒ>Uã8QêUéµ.kkUE ¢ÅLŸg×+ïÍÁw}õl:N¤ÓCSÃWâ8°ß~yùåëp]—^XÈÂ…—0þI§ßËWü†yóæ— !W\ñ]*¿²QzÐË´sº®G…hm×%gd òù|4‡–mÒc×qœ(…® |ß/{p–Þ¾2’Ѳ,²Ù,¹\Žl6K>ŸÇqÂ0Äqœ²ôxñèÏó¢”"ù|¾,݉|0¯Ì/—WF!•¬iZ$À”jú‰}ÄkÅ÷Qª•TþyeáÞ¸ñ@.‹·uÔ‘Ò#­óµX|ùb@̯¤Heu[|ãÈoа¡.Ý!g"žWúËdÄcÇh"SD½Há"-Óí„aÈü_Ïçg)Ÿ›A)ª+W\>‘AÚ*g}}b'ÖºÓ) ÿ¹°ýíogðƒœÎ~œOúj^xá‚.º^yå):è` ”Õ<›…õëç3o|ô£â¦Y*A ËøÜç†o8›±lgµÒAñmä°0\F¼øçÕüK‡Vä1˳uŒ¼\FúL×ŵª¼ÕŒõñ¾ÖéµF:þ¬Y;kÛ¸)@pyžì‰Èô¯ýÊ‚ ˜2L+AÅu«+Ê—ýËe̺£‹ËØ P†n†aXª20PëS™TŽÆÃ¤ÃͪíC®?’ÛI&#þâ‰8ãÕ骵£«Kˆ4--¢-±ãž{Ë-pÚi(†ÇõÁZx´|J\»®.<ßçxßæ½ï½L¬dE£‰¬PIf*æNž(öÔi#¢j´PùRIñRíëˆúÊR»XÅ›ó*8˜ëÁ\ Q ³†k>‚Æ“,=~)lÌ“àÔ%%Áçã!Ÿ=ævܾƒ7ýþMì÷ÍAמJÿú;¹ÿ0ŸCß _Õ¸â•+à{ðòã×1ë€ñ/4;ð7‚¹|?´f—-—i dŸK¦Ê[H¡˜$<º|ø?BHü†¾õÁ÷|8 [v½x(¼ü$¿mìæÀðT¸Ñ‡Î,¼^‡DÑ{(˹Ÿ.‘sŸbÿö}Ãó¼ñF˜Ép[1zÈu]V¯\É 7ÜÀ»Þõ®(®Ìá.z¥€Q)&äóùH„‰ŽeÑzñâ½qÁ@îWþ—‘M•H\\‰3œó…rʨŽüNt]NÝx*›ÎÜTëfÕ-ŽS*Ze&ß÷±m› †¦òr€c€…± dÚ<“R$ñ–Ñk¦Oí-#}$òþ¢iZYD[<LÖÀu¤È+‹ƒg2¢N™,.___FÉÉ(8×u£ûŸišQ4\:ŽÄbY-^_B:ÉtRò¹háG/á×Å׊Ñã8¥ÈŒtºzâ é/¿×T*ÅÁ?C*uW_=ˆiÀ4réÇY¹ï=rj-L²6Ít=?ÅèpoÙ…e šp¬ŠgJ§ÓÃÖ R(êi%¨ÈÁ9 mØ4æ|Sä–E7£@† z€+ +S•éM5÷ ÃØ}ìo>?´@ërðŽlS…u‡'k×,.ÏÅõ“&’0 I$CÒ|)ê”á´­øÜGÚÞ«Mš«6‡Ÿx8Yñzr±¾(Ó•iÀã9pPx|`øÇÓ”5i2ž›4Û0ïg'1ë–k}¥êš0©‹*–=½{b÷D™nM¡PL×¹ðK þ³@x±ŽžDÜwSè]|öŠ+øÃí·sÍÍ=¨é ›1 ½P^Í5þ@jY<ýôÓl¿ë.vÜ}7Ø´‰‡9MÓp=e—^Êœ?üc.¾˜Í+Wbf2BTuÎÙµ >óÎÑua9ª¸Œt¨ŒÄ¨D=4×Q?)+,i|„Ã8¬Öͪ[l[<6Œæ§ëû>Ùl–0 ÉårÕ£<Êëýĩ㡷2âKŠRˆ§®¢ˆ3Û¶£H6iÌ6MÛ¶ÉårÑçRÌH$ ²Ù,¦iây–eE^Ͳæ¢4ˆA@&“‰Ž'ÿ{ž‡®ëQ @)vÈ{SQôœl[eûÃ0Œ ‹{Å:ƒRP–¢M.—‹¶—ûËçóÑ]×#ƒ¡`dTu.—‹R߯ӦÓéè¼}ôÑZõuM–’QÄ˶VÖ!“×YŠ[=»³Œ€L´¡Ø=3±ª¢oçë(|¬¥.käú¾O¡PPÏœŠ)ôT‚2—ƒ Ä”#<èÓùÏ¥m|úíÿï­l–&·•u@õÄŠ  u§°,~±q#­µnWÜÙ;¡+žh¢(pUxç̦ñŒÆê3qñ¦ZDô«|ñàw'üŽsk}bõJâÜ~ ™wZ¶X6 TÏho2 ÅØØµëPÒýÚyà^™‹%äŠéšÒÅH“ëﺫdÌ”÷IY‰–¢ãPÌ0gYöêÕbìýày«®sI´}ìFëû˜q§“TªT•5Ý«˜VD†e^xê%¨ ÓOÎR‚±A”àGL—9A]JFdHA R¼”ˆ¦i <ñ…|ž¾W^Á4ÍH‘©àâ‘Pš» ‰DT7ϲ¬H¨(«©dY‘ˆJ¥ÃæææÈxfšftd-#˲ÊR÷Éç)2T:fù¾_Í^á&#Ú†‹l‹#÷-×IUä(’¿Êõ*÷-ßËëVù_î'n@”)#<‚®Å–^xab~0Ó„D¢$p A–Íf£èÉB¡ "&%<ÍpÂàåÑÎo£ÚvºN2™$•J)AE1e˜6‚Šã€~_ò8[¬.Þ=°‰£ï¾v숒5ú¾ÏæË.£ë¾û ¹¹tWWÆ\…bÜñ¾ö=Œ×½§l™|8‹¿—Þ` ÅxrÔ¶mµnBýây„ûœñÖRbî ¢BôÒSS Ÿ …br8ðÀí„Ï€ÈP/ø––LÓŒŒtq¤7´4,JìB¡ýF•¶o8Ã’e©¢ÕÓitÆ„Gî{„Vå.T•'ŸœKÛ?> Þ¥Jϱâ)AÐ}é¥là>ùº×±È²ª«/Åh ž.7(ñ¥´ï8Õ,‘A€†l¸í6tMãÆ†Db|ùÿý?þëÿ7J3%Ñu 8ï·¿%uê©ÌÎçI&“är¹2ã–aebŠŒ®Ðu-ÅÊÔÒ(-ÿ˹~¡Â%]~.…’Jc¶Ün,Ïñ4¥ÓYßc×®]µnJÝâ,¹cýsä2‡€[¬±ë7_üàé¿é&þùè£É WUVw—uUcŽ @©x”ªºWŽÉžWÞ‡u½¼pH–Ö‘ï+÷‘Í–ß;*Î%Ú¿ttPã³b ¢ÑõËÒ{)ÄË<%n*¦ÓCP CüµdþõøbŠQsã,×¥«»»Ì“NÍäßP©½ŠIÀtÑ®+ *2´_zÉð}UèZ1å–Z·¢~ñ}RÇK¼Ò©Ìí­i¶m£ëú¯L…B1±¼ê¹W±6OY­¬0 £ñ²RLñ(7ìf³b½þ~øð‡’2\tjet…bˆÕZùÆ7¾QëÖÔ-^Ã2rmëÁ^袦X7ò­ç¾Å?í:ž3|ûn;¾^,üh D¤Xðqžð`pž%ú®W\w« 80¬.È@Ip‘Uå+ûJŠ~L¤x#1ÍÒ~`¨0âsMûrœ¡ÂÍÍ¢¿Ç«Ó—ç=+Ï‹VM˜ñ}Ѷx;âç†âØ –hûpÇiaX^Á¾"Rk•öƒx[e±–J!+ÞVy¼x[<¯ü»ðýò(^¹ŽL¯bÊ–1*¼åàï„Üyâ½tüq'´TÂÏ~•üÙóЮMGˤüp9Q ÅÄ3÷É'I>} =±ùŸ û—qqãB1®Xî-·pa­ÛQ§x·Š÷ÂI‘ÍVæ·, ÇqTȵBQ#þzø_ËÄß÷I&“X–UæmÛ6aFóÝøXªú®B11<{ìi`äÁEW‚­³·rýO®å„WNàþçXxH¬º¼´!êbý§Ÿ~šxãÿ3ǶmÛ¸á†Ø2{}¾étYˆÙÞN:¦¯¯sb"†atuu¡é:çwßPü_fŠ2ŒÝg`.'’¢~ˆÓé4Ç{l­[T·t XfAt†ÓÁ1lÛ&ŸÏÓ2Ü3ç+±×ï¦O¸:Øz)հލƒ ŽäDí^Ág:B´1):Ó:¥œÅˆ1ß-îC/n㘀)^‡ÅÕ³ˆýæß„ÀŸ@¾ø™¼7Ù@¢ nràëœ<`½´¯-l) §wøàX"Ų[<îc.¼ÂB BU«Qjçê6…bÿ×80K/‰T öõc6"„ªã€&ž‰Ý­v„pb(ڷŃó‚R[%Çûyp?ðZà6àÄØ÷ik]qŒy@#ð“âyHòaIH;σG€ý å< àà¦â—wp'%1¼øÕò^NñÄ5Â);…¿ó·=øåÎüûÁø÷âëb¥´)›bª1-÷GÚ%Ñ$ó½JïéÕ—J¥ª¦HP(Ãñü ö?(z/Ó õõõáyÙlVÕfP(j„ÿäÑèç½—E`eº åÙ®PÔž0 I§ÓäóùÈ;9^—AÖ?P(“ÃÜ'ç ca1‹•ïû$M‘ëm™· »]6›Š©¸¾îGý6õùTY?–ÎFò}åX,½w•h:ƒÐ´¨’wOOW]uU­[T¿D:…ÌŠàû>===ã7VZ”gèÓ)Š(”•¢€:¤]r½.„‘^/þ±íŠõÒ(—±}™BÓ,®ëÿ„°‚<žï̉ãkÇìBˆ2F´q1Flµl6K&“‰B:Uz…bükÿ ^ŠUœ·º®pß’Æ[5f*ãÇžÌmAôÇD"ñÿÙû÷ðFÎúnüoBÎÁÎ,I6aã&“„ÄÆá J(ì¸Ù -4ÛŽÌé)»-;ú¤ Ô A¤°ýÑJ¬[XBÍ6Pxˆ%X ^xPÜÐD©÷Xù¤ÖrT ÔP!‹Õ}C—‰ª%‹á¸ãŽkõf4Í¢ËÏbþQ–Ÿº®¯Ìõ¦¾ÀÿÕh5–™/ì•YÏéóü‡¸Ùo v²`övÎÞ&¹¬9ÏkÔ²×hƪ¬£œ`rÖ2ÕÖ5{Ÿgÿ/—«·¦ºÄçzM­¯p 8úÔQ _ç6¶¹%Õm?›EôS¯ÇX A¾x<Çq8Ä4µ¥P•Æ£££Ø¼y3vïÞÍ›7ctttÁe.xì1Ø¿ûè;Äÿ–eÁu]†ÞÞ^˜¦ÙñÔ5ÃRâóOÿ9ÔW¬€ åap§brK"Zž¥Ä§óÌzèï7„‰ÞúÖ·BUUNBOÔ@K‰M)‹ „ i“)D ´œøL¥RAMÓÍf100Ïó`Ûv¯º®crr’qK ‘L&ñüç?¿Õ›ÑKÏòÆ«jt’ÙÉ—f¨gº æˆ;ÎRcÓùæ£PÏmúS©t]‡%ç´!jC¡ê¡222‚]»v!‰`bb›7oF$©™ñô~«C=k-‘Lùìg?‹7¾ñp]WŒ-ËÊ+QC,%>ŸÙðcñžà†í_þå_cØ5Ãûÿë¿Z½ M±”øL~U\tF£Q|âŸÀw¾ó¼ñod¹IÔ@K‰M@ôè|öÙgaYr¹‡Ç$ZKO˲ðå/6lôööbll º®CQNªK+f5}¶–to¨,™"[¼ËaôÇ z{jšÜÐu]·bÞ]UUaÛ6LÓ„eYH&“Áðñ‰D"–HÎ*—Éf³Áks¹ƒÿ èú>íºŒišÁü²GžªªAOƒD"¼VþŽÇã°m{Î2²1tµe’É$²ÙlÓ–Q^qRû¥¼ïûxê©§Z:+n©egöÿ=Ú_®ƒã8øîw¿ øú׿Ξ™Ô¾ü8pà€¿aÆŠÇ®¹æÿ¦›nª¹Üå—¿ÎÿéOøñxÜ?ãŒ3ü={öøétÚŸššjõ.-ÊÎ;ý´z3bË–-­Þ„¦îG'»ù,%>wïÞí†ág2ýúõþ%—\ÒêÝX²NùLwÒgµÞsrc$ÒêM]qK‰Ï+®¸ÂŸœœô5Mó_ýêWûñx¼Õ»±ä}ß¹sg«7£!:å{¦ÞsÒIç®Ö>.¥nû–·¼ÅWUÕk»úl¹ÕXæ„]½ç¤“ÎÝ|–Ÿðßô¦7ùçœsŽÿo|#¸ælÇ8]mŸévPï9é”sWËRâsË–-þ›Þô&ÿmo{›ŸN§ýx<îg2_×ull,¨ëÆãqrrÒO&“þää¤?66æONNVüËåü©©)?—Ëù¾ïWü_þº©©©àoYfËe–³ïR?ê”Ï*ë¶•û¸”ºíûÿâ/|í¸_ú·Üò3ÿÜsÏõ?ó™Ïø™L¦Õ»{YÒŸ­°ÇûJœãÐôP™˜˜˜“ÑìîîF¡P¨¹Ü±cAÓ\pÁ¸è¢‹Ëåpâ‰'âG?úQ«wiQ>ŒÛn» »wïnõ¦,ÛÁƒ±uëÖVoFSöcbbÇŽÃúõë‰DZ½É+f)ñy×]wá?øöîÝ‹«¯¾'žxbÛ~.:å3½š¾gŽ=Šƒâé§ŸÆÛ[½±+l)ñyìØ1¼èE/ÂsŸû\lÚ´ ‡nËÏøÑ£GñÄO`bb¢Õ›²lò=SÏ99|ø0~øa\tÑE­ÞܵԺíwÜN8Ÿþô§[½ ˲šÊœvQÏ9aÝvþøÓí¢Þºí±cÇZ½©+n)ñyçwâ‘G¢(xÎsÄm®›o¾çw^PžÊãûOÿôO¿«ùÊW¾Rõw=óÚÙX· ÖmK–Z·ýÙÿ;§ù·ão|Ö­[‡}ûöáyÏ{n¾ùæVï€ð—%íð½æx?xð }ôц×mC“P™žžžóX=“Ýyç­Þt¢Ž·”øü×ýWüë¿þk«7¨ã-%>ñ‹_´z³‰:ÞRë¶ŒO¢•·”ø|ó›ßŒ7¿ùÍ­Þt¢Ž·”ø¼í¶ÛZ½ÙDo©uÛܽ™â_omõ.5Lh&¥ïîîžóØBYN"jÆ'Qx1>‰Â‰±I^ŒO¢ðb|…c“¨$4 •¾¾¾98==]W¶“ˆVã“(¼ŸDáÄØ$ /Æ'Qx1>‰Â‰±ITš„J$Áôô4òù<16_¡PÀ¦M›Z½iD«ã“(¼ŸDáÄØ$ /Æ'Qx1>‰Â‰±ITš9T`xxÛ·oG?ÆÇÇ1<<Œ®®®VoñIfŒO¢pbl…ã“(¼ŸDáÄØ$Öø¾ï·z#Ê  ôôô°ÛQÈ0>‰Â‹ñINŒM¢ðb|…ã“(œ›D!L¨…MhæP!""""""""""" +&TˆˆˆˆˆˆˆˆˆˆˆˆÀ„ ÑŽÿÈG>ò‘VoÄR LLLº»»[½95·QNÚT(ÐÝÝ“N:©îýhõ~ÎÌÌà‘GYô¶…q¿ªíËrÏQ«ÏOµË1é„s?_|.7þš½o íÇ|ç(lûÑÚ嘴û¹_jÙ¹ÐóRv¶j_hù&&&pòÉ'7ì\7ûs ßoffgŸ}vC·µûROyYm‚Øv:G´4Õbh¯s_+>Ã^·­§Ü_J|¶z¿¨1–Ÿa:÷Ë);—»Ÿ°Ôø û~ÑÂV²~Ôh®c7ÊÌÌ ÇY‘ºs[óÛÔM7Ýä ø[¶lñü›nº©Õ›TÕßýÝßù]tQÅÏêÞ0ìçÎ;ý;wÎy¼Ö¶…u¿ªíËrÎQÎOØ´Ó1é„s_í3½ÜøkžÍ÷=Së…q?®ŽI»Ÿû¥” =ß)eg+÷…–çðv®›ý9عsgð~6lð?üá7l[›µ/Õâqö~]sÍ5þôôt[ž#Zšj±éûíuîkÅg;Ômç+÷—ŸaØ/Z¾¥Äg˜ÎýrÊÎåîg#÷a±ñÙûEµ­dý¨Ñ]Çn”ñññ«;·»¶M¨”ÐÆÇÇý‹.ºÈàZ½YslÙ²eNÁ¹˜ýhå~ÞtÓMÁ “j…O­m Û~Õڗ圣vù6S;“v>÷µ>ÓË¿fîÛBß3µÎQ˜ö£]´Ó1i×s¿œ²s¡ç;¥ìlžPcÈ ¢òsß.Ÿéx býÓÓÓþE]ä7d[Wz_æ‹G¹_åû±aÃß²¬¶;G´tÕbÓ÷ÛçÜ/Ÿa®ÛÖ*+—Ÿ­þÞ¡ÆXJ|†åÜ/·ì\î~.×râ3ÌûE [éúQ£5ºŽÝ(åÇlzzÚß°aƒ¿oß¾º¶¡Óã -çPÉçóèîîF$ôõõ¡¯¯ù|¾Õ›Vu[«u+«g?Z½ŸýýýB__ߢ¶=ŒûµÐ¾,åµúü„Q»“v>÷ó}¦—ÍÞ·Z±Yë…m?ÚA»“v=÷K-;z¾SÊÎ0œ#Zš‘‘ôõõ¡¿¿?x¬>Ó333Jà tuu¡§§ÓÓÓËÞÖfìË|ñX(‰D*߸qc]û¶sDKS-6ö:÷µâ3ìuÛZeårâ³ÕûE±”ø Ó¹_NÙ¹Üýl„¥ÆgØ÷‹¶’õ£Fkt»Qòù<¦§§±mÛ6"þmÛÆÆ܆ÕÏiõ,ÅÄÄÄœ‹øîîn …VoZYø\wÝuÈçóèêêÂðð0†††êÚVï§üâ©6Î]­m›™™ Ý~Í·/Ë9G íçjÔêÏìb´û¹Ÿï3½Üï•fŸÃZß3µÎQØö£´Ó1içs¿Ô²s¡ç[ñ½³eg=ÏSøLLL`ÿþýØ»w/¶oß^ñx»|¦ûúú044„øÃˆD"ARP^è…½n;_;¥n»Øøl—ý¢ê–Ÿa;÷K-;—»ŸÍ4;>;e¿Hhtý¨QVªŽÝ(…B!èm²mÛ6ôôô`ëÖ­ARdµÇA[&Tªe—ØåêëëÞ={‚ì]$Á¦M›‚ íG˜÷³Ö¶µÓ~-ç…i?¢ŽI§žûåÆ_˜ö­Ö9j§ý‹v:&zî—³íaÚ¯N®ßÐ\–e¡¯¯/czz˜˜˜h«Ï´l]·wï^ ömŒc÷îÝËÞÖV¦gff°uëVŒŒŒ`ÇŽرcGÝÛ¦sD‹S+6ö:÷µâ³Ýë¶KϰïÕ¶œø Ó¹_NÙ¹Üýl†ùâ³Ý÷‹„•ª5ÊJÕ±©§§»víB$ F$]pVC´eB¥¯¯oΉ˜žž]¶KfðË•gÚ0ïg­mk§ýZÎ9 Ó~„E;“N=÷Ë¿0í[­sÔNûítL:õÜ/gÛô_\¿¡êfff°{÷nìÞ½…Bûöíþ}ûÚê3](ÐÓÓSñYD"A ºv®ÛnÙ²===°m»bx‹z¶-Lçˆo¾ØÚëÜ׊Ïv¯Û.5>þ_´°¥Æg˜ÎýrÊÎåîg3ÌŸí¾_$¬Tý¨‘V¢ŽÝ(‘HdNÏ™N¸gÖ0M˜ø~E øð}ß÷ÇÇÇýzzºÕ›Uᦛnò7lØl×ôô´¿aÃÿ¦›nª{?°Ÿ[¶lñwîÜ9çñZÛÖýš½/Ë=Ga8?aÓ.ǤSÎ}µø\nüµbߪíÇBç(ŒûvírL:áÜ/¥ì\èùN);[¹/´|[¶l Îï·Ïgzß¾}U?·–e5d[›µ/óÅã*~xà¶;G´<³cÓ÷ÛçÜ/ŸíP·­U—]j|†a¿¨1Ÿa9÷Ë-;—»Ÿ<þ‹ÏvØ/šßJ×VB#ëØ0==í øãããÁÿíxÏl¥´å¤ô0<<ŒíÛ·£¿¿ããã®:6e+ÉÉs7oÞŒžžŒchh(³¯žýó~ÖÚ¶vٯ垣°ìG˜´Ë1éäs¿Üø ˾-tŽÚe?¤]ŽI'Ÿûål{Xö«Óë7´8íò™Þ¸q#òù<6lØ€þþ~ ôõõ““.w[[õ™. ( غukÅãÛ¶mÃððp[#j¼v9÷ Åg»Öm—ŸaÝ/jŒv8÷Ë-;—»Ÿ+i¡øl×ý"a¥ëGÍÐêíëêêÂððp0ÿŒœG³î™5Âß÷ýVoÄRÉééé u·¡‰‰‰ kSµí\h?¼Ÿµ¶­ök9ç(LûítL:õÜ/7þ´oµÎQ;íGX´Ó1éÔs¿œmÓ~urý†§>Óòýº»»Ñ×××Ðm ógºÎ5V;ûZñÙIuÛÅl[;ï-¬]ÎýrÊÎåîg+uê~QI˜â,¬Û·’uçvÖÖ """""""""""¢fhËI鉈ˆˆˆˆˆˆˆˆˆˆš‰ """""""""""¢0¡BDDDDDDDDDDD´&TˆˆˆˆˆˆˆˆˆˆˆˆÀ„ јP!"""""""""""Z*DDDDDDDDDDDD `B…ˆˆˆˆˆˆˆˆˆˆˆhL¨-€ """""""""""¢0¡BDDDDDDDDDDD´&TˆˆˆˆˆˆˆˆˆˆˆˆÀ„ јP!"""""""""""Z*DDDDDDDDDDDD `B…ˆˆˆˆˆˆˆˆˆˆˆhL¨-€ """""""""""¢0¡BDDDDDDDDDDD´&TˆˆˆˆˆˆˆˆˆˆˆˆÀ„ јP!"""""""""""Z*DDDDDDDDDDDD `B…ˆˆˆˆˆˆˆˆˆˆˆhL¨-€ """""""""""¢0¡BDDDDDDDDDDD´&TˆˆˆˆˆˆˆˆˆˆˆˆÀ„ јP!"""""""""""Z*DDDDDDDDDDDD `B…ˆˆˆˆˆˆˆˆˆˆˆhL¨-€ """""""""""¢0¡BDDDDDDDDDDD´€U™P±, ¶m·z3¨Èó<ض Çq–½.×uaYV«w‰–ˆ±Ù\×­ÓŒÏöÂxìlõÄ£çyp]wÞåmÛž÷yjÆjgXnÙ9_¼2V[‹ñ.¼îX–vÆk¸,5^«•§¼m_ŒËÎÕîq¹**Ùl¶mrpp0(ÊÿnWŽã ··©T Ñh±XlYës]Ùl¶Õ»EKÔ)±YíÿÕ"‘H``` jL3>ÛK§ÄãjÅ…Ô©Tªj%ײ¬ ÎÚº"Ü :%V«ý¿Z4¢ì¬¯ŒÕÖë”øì„Ølôu'À²´Ó0^Ãc©ñ:_yÊëÐöŸì\í—«2¡ÒÎlÛ†çysþnWÑhñx¹\ccc°m»­ŠV¯ÙñØ ñ¹X®ë"•Jall,ˆi˲Xq ¦ë´²²Ù,ËB4E*•ªú|"‘@&“A.—C.—C,cëZZ–Ë/;kÅ+c•–£ÓÊÒf_w²,¥fb¼òZ”§Óâ’*­Š„J6›Eoo/Ö¬YƒX,Vñ!–™ïµk×"‘H ‘HT|á:Žƒh4Š5kÖ``` ø„eYX»v-Ö®] ˲H$°víZôööVdPóÚZ‰Dð{Ë–-ÁßõŽã```kÖ¬A4 –™ïñ…ž«¥Þý•_(ñx ( &''aFÅz(Û0¡€IDATÊÏÜ.y®ä:çkÑ#_·Øå¨9jÅ&Ð>ñY›òsVþ-K‰Á•ŽÍzb¥Z|Êó§(Jð[UÕy+åç”±ÙzˉÇùbhm<6ª¬¬õ\Xãq±qU^^jšÓ4¡iÚœ×Ù¶ EQ ëzðZMÓÚ¶åX;bÙÙÜX­w›]vJóÅ+cµ5X–†³,]躳|],KWÞ'ê¬ûD‹)OyŸ(¼—áŒË…âdUÞ¿õ;Üää¤ÀO&“¾ïû~<÷øñxÜŸššòEñ3™Œ?55囦éðs¹œïû~ð¼\6—ËùŠ¢ëŒÇã¾ïû~2™œóº®Û°˜×.¤|ûÊÿ^èÈý”頻ê¼×Z¦Þm¬gÓé´¯ëzðÛ0ŒŠýà›¦éOMMùccc¾¢(~.—ós¹\Åsò¼ÈçäúMÓô5M󧦦‚ó7ßrÔ|µbÓ÷ý¶‹ÏÙñXO|.%››õÄÊ|ñiš¦o†ŸN§}Ã0*Žß|ñÉØl½åÄc­XôýÅÅØJÄãrËÊZÏ…9S©TÍåj•—’®ëÁ6JÉdrÎy¨ö:Z,;›«õîo³ËÎÙfÇ!cµùX–†·,]èºS®‹eéêÁûDwŸÈ÷ýyËSÞ'jŒËðÆåBq²ïßv|B%û¦iV<¦ªªÇçTd¦¦¦*>äétÚ×4­bYÓ4ƒ –ä‰.ÿv@ÖûÚ…,% “ɤoÆœã2ßãµ–©wëÙ_ye)ÿ/¿p(¯Ê‹UHÕγ\¿iš¾¢(Ë×ZŽš¯Vlú¾ßvñ¹”›BK‰ÁfÄf=±2_|ÊÂ[þ._f¾ødl¶Þrâ±V,úþâbl%âq¹ee­ç©TªærµÊËòõÌÞŸjåç›VËÎæÇj½ûÛì²s¶ÙñÊXm>–¥á-Kºî”ëbYºzð>QçÝ'’ËV+OyŸ¨=0.× ÅÉj¼ÛñC~9Žtù“TU º–wÁý:×uá8Ö¬Yü„®‹Q<Ï öYJ&“ó>^k™FSU™Lº®#™LÂ4ÍŠc<ûœH³»N+ŠŒ9[Þov7·ZËQsÕŠM`uÄçRb°Y±YO¬Ì>'ßùÎwÍf166†d2‰ÉÉI8ŽS1vô|ñÉØl­åÄc'Ä¢ÜÇNŠÇz–«U^ΧÚû0V›‡egçÅêrÊÎZ«ÍDz4Üñ¹Ðu'À²t5á}¢Î»OdYVÍò”÷‰Âqî¸\(NVÛýÛŽO¨T³´\­“!Ç5õEOžàg%>˜ÍfÛ6Ž;VõñùÆlnô$Jº®Ï ¸ùp¶Ùç­|»4MC:F<Ÿ3æb­å¨¹ŠM`uÆçB1¸Ø¸]ª¥ÄÊC=UU+âX×õºâ“±ÙZˉÇNE ½ã±žåj•—óÑ4­êzgWâie°ì¬®cu9eg-ŒÕæcYZ]âs¥®;Æg»â}¢êÚù>‘ëº5ËSÞ' ?ÆeuaˆK`e®IÛ9.;>¡¢ª*,Ë ¼ã8AÌ0ŒŠÙìÉ… Àã8A–Ìó<ôööVLØt]¯8¶m#âOÿôO«>.¿ˆæ{®QdE²üøf³Ùº*’®ëçK.''õ“ÛÇ¡ªjE ¿ZËQsÕŠM`uÄg­8[JÜ6ÒRb墋.‚ëºÁ¶ÉåÊ·m¾ødl¶Örâ±bè¼x¬g¹Zåe­ãäy^Å…®ëVLìK+‡egçÅêrÊÎ…Žcµ¹X–†7>Wêº`|¶+Þ'ê¼ûDr¹ùÊSÞ' ?ÆexãX™kÒvŽËç´zVšišp½½½Á¬¬¨hšÃ0000UUçd»TUE<Çàà`°¬®ë-­è¨ªŠD"t:]ñw­L®Üfy ÇA2™œ÷ñZË4’¢(H&“€®ëÁñ5M³®ã‹Å ªjÐ!ÏùR•ë—çl¾å¨ùjÅ&Ð~ñ9;ë‰Ï¥Ä`3bSîÏbcåÊ+¯ÄáÇ+Ω¦ió.'ãóüóÏgl¶Ørâ1l±(·©Qee­ç‹]®¼¼\¨uX2™D4­ØçFWØ©:–«K-;«áò4¼ñ¹×Õ0>ÛïuÞ}"yýZyÊûDíqÞ¸”ûÓÈkÒvË5ÅÉc:žã8Á˜{²¢ây^Ð…Èó<躎5kÖ`jjjΘ¶®ëBQ”ººr¯$¹-š¦Û_¾OõUU+²ûó=¾ÐsÞ§z¯mÛH¥RÈår°m{Å—£•U-6ö‹ÏòØ”c;ÖŸK‰Á•ŒÍåÆJ³bšo9ñ–X,ß–F–•µž c<®t\Éc¼’õšËÎΉÕÙÇ‚±ÚþX–†/>gïËR’xŸ¨sî-u9^‹†ã2|qÙìkÒvˆËU“P©Æu] “É@Ó4¤R)8Žƒ\.×’m©5a’®ëU»6-u¹fnc£•V3–£Ö`|6g«iv¬06ÃñØœm¬†e-cµ9ÛX cŽ–ø\Îç¾]ãs©׫SXbUnËj*K[qÞ—ÍÙÆù4ûš´â²ã‡üªEUU¤Óé`Œ6UU‘ÉdZ²-rÜ»ZÛÚÈåš¹¶ÔÌd3š4?Ægs¶q¾u53V›áÇxlÎ6η.–yT/Æjs¶q¾u1樖°Äçr>÷íŸËÙÆõê–XV_YÚ ŒóöÀ¸lÎ6ÖZ_3¯IÛ!.Wu"""""""""""¢z×ê """"""""""" ;&TˆˆˆˆˆˆˆˆˆˆˆˆÀ„ јP!"""""""""""Z*DDDDDDDDDDDD 8þ#ùÈGšý¦333p3338ûì³+ž+ ˜˜˜tww·úø­*µb`|µã“(¼X·% '–DáÅø$ /Öm‰jkzBebb›7oƃ>ˆÑÑQÜwß}xík_ ÅöíÛñàƒâúë¯Gww7úûû[}ŒˆV…Z± 0>‰Z‰ñI^¬Û…ËN¢ðb|…ë¶D [ãû¾ßÌ7ÔuCCCضmfff°yóf cãÆ¸âŠ+°k×.D"‘ €mÛFOOϼë{ùË_ŽK/½´ÕÇqÙŽ9‚“O>'Ÿ|r«7eÙ>ŒuëÖµz3𶇯;ßùN¼á ohõ&/K­Ø°èøüèG?Š[o½ø‡Øê][¶NùL¯Æï™ƒâ–[niõæ.[£ãsÆ øƒ?øƒVïÖ²;v ÇŽÃgœÑêMY¶Nùž©÷œ=z\pvîÜÙêM^¶F×m_÷º×áüóÏoõn-Ûj,s®ÞsºmõøüÖ·¾…Ï}îsñYXmŸévÀºíòâ3â´ÓNkõn-ë¶áúmç×mÃ^–´Ã÷BØã}Eê¶~8pÀ˜÷¹ 6T «±Ì »zÏI'œ»•(;;å{Ë÷Wßgº°n[ùüb㳎‹Üw~Ï„ ë¶•ÏubÝ6ìeI;|¶Vã9nê¤ô…BýýýÅÖ­[±}ûväóy¢KÙìŒfww7 …BÍu®Y³[·nmæn¬ˆH$R3£ÛNd«’vWÏ~lݺ7ß|s«7uÙjÅ&°´ø<묳pèÐ!ŒŒŒ´z÷–­S>Ó«é{fbb[·nÅáÇ[½©Ë¶ñyâ‰'bëÖ­mõî-KOO"‘H«7£!:å{¦žs2::Š‘‘<ú裭ÞÜe[‰ºíÁƒY· ™N‰ÏzÎ ë¶µãóæ›ofÝ6DVÓ÷Œ¬ÛŸÇÖ­[aÛ6¦§§ç¼¾žô¥—^Š={ö4s7VD؃c1†††Z½ MÛ={ötÄEU­ØìééYR|žuÖY¸æšk0<<ÜêÝ[¶NùL¯¦ï™¾¾>ìÙ³§#nJ®D|^xá…Qvöôô„ºò»ò=SÏ9BOOOÅÍ“vµuÛóÏ?¿#âs5•9í¢žsºmmW_}5ë¶!²š¾gX·­Ÿë֭눲“uÛðaݶóë¶a/KÚá{!Ìñ¾Rõ¶¦&TñAصkñ¡™™Áèè(º»»ç¼¶P( ¯¯¯Ù›H´*Í›ÃÃÃŒO¢c|…ë¶DáIJ“(¼ŸDáź-Ñš:äW$AWWWÅcòÿ¾¾¾9ÝĦ§§CŸ…#êµb`|µã“(¼X·% '–DáÅø$ /Öm‰êÓÔ„J? …B0nÞÌÌ öïߌ7==]16_¡PÀ¦M›Z}Œˆ:^­ØÀø$j!Æ'Qx±nKN,;‰Â‹ñI^¬ÛÕ§©C~uuuaxx›7oF$A¡P@$ ÆZÆöíÛÑßßññq ÏÉŒQã-›ã“¨UŸDáź-Q8±ì$ /Æ'Qx±nKTŸ¦Ï¡244ewwwÅX{åϵä;D¤VlÎ~žñIÔ\ŒO¢ðbÝ–(œXv…ã“(¼X·%ZXÓ*j’¨uŠ?Æ'Që0>‰Â‹u[¢pbÙI^ŒO¢ðbÝ–¨¶¦Î¡BDDDDDDDDDDDÔŽ˜P!"""""""""""Z*DDDDDDDDDDDD `B…ˆˆˆˆˆˆˆˆˆˆˆhL¨-€ """""""""""¢0¡BDDDDDDDDDDD´&TˆˆˆˆˆˆˆˆˆˆˆˆÀ„ јP!"""""""""""Z*DDDDDDDDDDDD xN³ß°P( P(T<Ößß®®®Šç{zzÐÓÓÓêãC´j,›å¯a|5ã“(¼X·% '–DáÅø$ /Öm‰Öô„ÊÈÈöïß_ñØž={‰D0::Š‘‘ô÷÷c||ÃÃÃjõ1"ZjÅ&Æ'Q 1>‰Â‹u[¢pbÙI^ŒO¢ðbÝ–haMO¨ÌÌÌT”åFFF°k×.D"LLL`óæÍˆD"Ìx5A­ØŸD­Äø$ /Öm‰Â‰e'Qx1>‰Â‹u[¢…5}•|>_5Ðòù<º»»ƒ€íëëC__òù|«Ѫ0_lÊçŸD­Ãø$ /Öm‰Â‰e'Qx1>‰Â‹u[¢…55¡233¸îºëpñÅãŠ+®Àèè(`bbbNÀvwwÏ·o¶ƒbëÖ­ÍÜ ¢ÀÖ­[qóÍ7·z3–­VlKÏ›o¾###­Þ=Z…&&&°uëV>|¸Õ›²l+Ÿ‡ÆÖ­[+ÖCÔ,r¨€G}´Õ›²l¬ÛR§aÝ–u[ 'Y·=xð`«7eÙX·¥Núm}uÛ‰‰‰Vï­B###+R·]ò_333Gww7úúúêZ¦P( ‰`Û¶mسgòù<¶oߎžžLOOÏy}=]ÆÎ?ÿ|ìÙ³§á†¨{öì鈋ªZ±‰D–ŸW_}5†‡‡[½{´ õõõaÏž=qSr%âsݺu,;©e†††ÐÓÓÓ­ÙX·¥Númm¬ÛR«°n˺-…ë¶µ­–º­ãšÖê­ ÙVªÞ¶¤*###¸âŠ+°uëVŒŒŒ ŸÏC×õ³² »‡E"lÚ´)è66ÛBYN"jŒZ± €ñIÔBŒO¢ðbÝ–(œXv…ã“(¼X·­Ÿç‰DéÿÁA ?±`Ys—±m±Ì|ÏKŽ#ÖOáµè„Êþýû1::Š={öÆH$‚¡¡!lÙ²%èVM¡P˜“téêê ‚vv NOOsb#¢&¨›ã“¨•ŸDáź-Q8±ì$ /Æ'Qx±n[?E‰×ÿg2¢‡Šã¦)’'Ž#'Ù¬Hضø[×KËU“ÍŠ×Rx-:¡’Ïç144d+¥mÛ¶¡§§ããã5—ݾ}{t™™™Áþýû+ºvÊV ( Ø´iS«QÇ«›ŸD-Äø$ /Öm‰Â‰e'Qx1>‰Â‹uÛúY–H’D£"9’Jñ8`"’ɈljRrE=P<±¬ªÎ¿nE?^KžCe)†††011Í›7É—¡¡! ãšmß¾ýýýÇððpEK"Z Å&Àø$jÆ'Qx±nKN,;‰Â‹ñI^¬Û.ÌuÅ]ª $“¥^'R2  8\—®‹ßšVìqr ÐOPü_ӪϻbgåYz«÷–æ³è„J$Á‡?üá9ÈÑÑQ ô÷÷×\~ÇŽ˜˜˜º…•w “=_ …œçˆheÕŠM€ñIÔJŒO¢ðbÝ–(œXv…ã“(¼X·­-+%A4M$VlPî(S ý¥Oʯ[œ¯ñ‡ÄEïïÔßÞ1 éHPï×€ûmà°Å2‹N¨lܸãããA¶rzzº®czzºîÌd__߼ϭր$ ƒZ± 0>‰Z‰ñI^¬Û…ËN¢ðb|…ë¶%Ùëm ¾FüïybX¯ÁAÑÅqDí)ˆž)r¨®âou €;èGŒY|¸8Š}Èþ;» @ °¿ØS€ó0 _¶˜P ™% ù5<<Œ¡¡!äóù WJ$Yuݼˆˆˆˆˆˆˆˆˆˆ¨C8нPìoÎ/ý1„W:-z¦€]$Yô#R½LLˆ^*cÅõé@\ ½¸^Ð׉“C½^Ò¯I žÔS÷ñâ²YˆDMÙ6UeŸ¯õj˜E'TFGGƒÉˆÊǸ$""""""""""j+D"@¢ð|ÑSÄ{FôH™œ“Ìçr@: èI1ì—{"éñ8TˆDˆ)þOf †îòÄúuÐ/´3åE@âF@}Zôx‰_Øëôd‘X©•,q‹ëÖŠ»(ÍÁ’-®ƒæ¸Å.P(022Òêí&""""""""""Zž˜˜×IJ€Ô]€ñ1½ó0€{E¯Ç)›DÞƒHXxâqe¢w ’:D‚%Vö·[|ΠöC€ñ4`¾ PÆ‹õxÀý þ2ˆ/fq½^qùµ ¹ Ñâßå=X¬â{ ¸L¢l?]T—-[/-hÑ=TLÓÄÌÌ FFF‰Dæ<_í1""""""""""¢–+ïÅáÞ7€ÔV “‡€øA1GŠ÷e@? P5À¾ О(.ï¡”€xPï‚Hb¤‹©(%5dÏù¿Lã2^±7Šƒ ù`ߘ¿G)IQ^K=PN.þo×o_#“(1àÉ'ŸÄ½ò¿ðƧ߈'ÿêIüÛû‚ÛŸ=/ùÎKðãÿç º/€²Ë…zþù¸ùo¾‹óÞs%>ùÉßâuçüîœ<þß'à·/~Ç{ÇÃ9Ð2Å÷T íåÜ xèYàá»Ƴ'=‹õÖz‘ì1‹Û5;¡b—O£”l’zdÊöϨ²ü*³è!¿†‡‡qÏ=÷àž{îÁÞ½{±gÏìÝ»7xŒˆˆˆˆˆˆˆˆˆˆ(Œ²½1¬Wâ@¹Ð‹wÉÍ—£4|V±ˆò( Ú»ŠÉ€Sï%z» ‘pˆB$&Tñ{úÓøÑÝ?½ÏÞ‹SŽ‚‡z·ÎÜŠ“~{Ž{Áqøñ¾ãÙ¿x8dÁzÙžùñ3¸ÿÂãpýõy¼ïöÃø?_?ýêS¸íe¿,`ð >6…¯<ý|ëÁßÂQ Ù〟uœ»€5kðîãß{ÜgðäñÌ=ÏTöKöÖI¡²÷|­L Y(ÍS®|ùºªó;¶B{¬»áë\tBÓ_qÅؼy3¶nÝŠÍ›7C×uLLL4÷ˆÕà¾HlÖ®ì¯Ég€Ün@90þ@qŽ÷'¨¼é¯Êm€ú(Jó£¨Å¿U ÷gÀç“¥2±  ”|ЀgzžÁ§?ýiÕñxªÿ)L_1 ÏóðWçþ~ÚûSü|æç˜™™Á“3ÿƒ¿ºñ•Øþ?¯Â—Ï>ºžÅÇ¿yž:çT|åïŸÁ›nú:Þû‘§pËÐ ¾ð…ÇŸèøß€ë×?…OF>‰ÇŸyÿö•ðþ=‹Ïï>E×qÙ÷ƒûxÜ÷ûû{3ðÎw vÏq ’@i”z¯È¹^\”z¤Èd‘|< 1GŒì‰“+,þm—Cyl”’-å»eË"±#c´lù:çzI$D² ¾ÿý—ã'?ilReÑ •|>‘‘ ã'?ù î¹çضH$‚-[¶4t㈈ˆˆˆˆˆˆˆˆˆ–Êq€Äã17Š=è'Ê}ÀÔŠCvH¾ О‹`’kŸ¸_úõ— ÒgB$R¢I @˜ùù òßÉ‹¤ƒYzOW/ËÊh@Ïÿ¿gu¢Q1“¼iš0 ÿòÒÁ«O}5’É$~û~tññ>;wž å…@:†¦iÈ<¼ph¾ùýzùCøáóEQpǬÃ{zòØûµ#øàÅpü]3PU·Ý÷;Üú‹—áÈ‘¶n~gýìåxÙ_€ëžs_=î§è ÍÑ(H‰ýóÞ¤žìw‹M·×±Ï‰«!jñ·S<JC£¥Šû+çx8ŽAo³ø\ñ˜ëDbÆB)Y#×Uìá#N$*zÈ8e».`4ÙléïÇëÆWL7ôó´è„Êþýû144„¡¡!tuuzzz°cÇtww#ŸÏ7t‰ˆˆˆˆˆˆˆˆˆˆ% x·Š„ó ôâÄíJ ¥¡»LI@=P^`”kn»÷ýþ>qC?‰ W ¢À½7Ý+’6àÁƒã8b9p]éL?–Ç'/½Ó2;N¼GŽa8鎓š¦aý§ÖãŽï€çy0Ò{ïø«ôÁ0€tºl_âàòË/ÀMß¿ÿóÀ—ðÚ×Þ ýŸ€?;)kÿì=È~á§èþ£Ÿ@××_=õ$à­o=›·ûd ï‚c¸ïòûð’Ó~ÇÌçæy€w°‹=OœŸö €ý|Àýû`þ=àüˆ>XqðV@y¿õ ·A¼nߺGàxÞóîÇÏOÞ‹ïÿòqx9P".rÛ€+ϼ[ôüˆp€T ˆ€ÄéÀm±Ã€1ìãôW=ÄûÞó€Äã?Fêg€“RO©Ã@ôÀ?~×Üøc¸¿bÞg†3Xߢ÷¾îÓ߯àvÀé¾ó›§ñ¢3OÅÎÉi¨gɤ‡;îxœòXÐ%•œ= çËwA¹Ð‘$:û¹¿iøÇjÑ •H$‚ýû÷Ï™/ett…Býýý ßH""""""""""¢ZœóDÏ…T ÈÞ h¯LÐNE0Œ”þ:ˆÞ%ˆÞ'r ûÔ1<ç9ÏÁI'„_óc åà¿ÿ×ÿÂÞÏïÅ׎| ùÒGð«#¿Â£]â”SNÁOúSÄb1 "›Í¢û‚n$§s¸â¸ãÐÓÓƒOúÓèëë«ØV·Ø½bll ¦iâío{pñ<‰D‰D–eÁ¶m¼îòËaYV0lØ-·Ü/z–hZÕc‘LŠ"’HÖ·œ @>øÅàʯF4Åô;§qô-GqÞy7ã¿ø N8÷(çŸß…]¿/zÙyp¿¹÷6œ{è£H¥DÞ邛œOîŸ*…§~ñN9壘,<{x¡×Ýs®yÅ·qèñI¼êwá+w?ýÓ¿ÃWþßÓ0Îvù'cbâRDßøqì:é>ü/?„‹Axwç?ç`~o†Nÿ&^÷ºÿ¯Ïý5®:ïxŒ>Ý÷Læ100€çýì]8ñ_ÄÿùüÏñ‘·|ßÿáAx¿ï†ò¹AòßX€yþwñÑ'®køgì9‹]`hhؼy3úúúÐÝÝB¡€ééi /ª—ÊÄÄzzz*–) ( èééAOOOÃw˜ˆV-6Æ'Q0>‰Â‹u[¢pbÙI^ŒO¢ðj׺íàÀúÏ€r& Nú P“¾Àž8ñ LBO¶¸jqaøâ«¾ˆS?u*Œ» üúU¿ÆÁƒñÔ9OáÏÉãÌŸÿþAߟþ>bÿÃøø86^¸o{ÛÛp÷Ýwãmo{fffpÎ9çžÊçqJ_>ú·‹h4 Ã0àº.¢Ñ(^uî¹xþýE¢(0Mÿë¿âM—\×uñû °öª«0uưm~÷»È( þÁq`š&<σçÝmýÉ¥„ŠãT$WâqÑ›EÓ4x^ix¬3Ì3pdíär9ü‹õ/p'ôz¼àïÄ#ÿûd¼ÿªw~ñ‹à½ïÕðÌ3ÀØcq¼dÃ…8Åþ>õÿ»æ{Æ›ÞôgÀ_ý¾²õãÈdâèErWßÔ>ã?<þä–¸ãUOàî¾+ñ3‹sއ'Nýw¬Á“Ï܆ ƒ×}à/¡þËÉ8:N|â \øôÿÅ¿å,¼;þB¼ïŒ«ñî^†‹£o›{N‚ò÷{»~‚L>ƒ“„ ß}!¾ðä>±÷MxÝéGa^$¼ ú[ÿæã‚yù^>ñõ8ôë“ú[tرcöîÝ‹M›6¡¯¯Û¶mÃ÷¾÷= Õ½ŽB¡€-[¶`||3cÏ?ÖÐÏÙ¢{¨H}}}sº)-Æu×Íín322‚]»v!‰½`"‘Hh3žD¨ZlŒO¢0`|…ë¶DáIJ“(¼ŸDáÕÎu[€þ‘_0_àˆa½\ˆa½²ÀÌÌ n¹Ò?$ƯRÛ¶qù¯.ÇwÏÿ.ž×õ<<ïÒç!¶&†NP¬XÎýá“øøÇ?ŽÉ«'q½r½xXÓ033ƒµk×âÜsÏs®"»cY@2‰—Ø›HÀ4M˜¦ ¸ýýïÇ)ÇŽU$TΘšãs¸ö›ß€;ï2‘!ò<±^]‡ªªÿþìÏ\$ÞÞß©SNÁ•燺®NÌqpÉo+&twr¢xÀžL½¶ÉÉI¢‹e•æ]I¥€\A×–îË/Ç>÷9àŒ3ðö‡ !ñx|î‰øš \n—‹,Ž:µîI›qëG¾g¯òqüȬeä¾áµ6oþ.Ä+ñÖ²9g (ø™?„ko¹88ù’]0þ.hw^†¾¿;Š¢`ì›ÀµŸ¸W¾úJüו.n?y.Ãe ýŒ-©‡J>Ÿ¯¬ÑÑQŒŒŒ`ff¦®åGFFÐ××W1ßJ>ŸGww7"‘€RÂ&ŸÏ7t‡‰h~Õb`|…ã“(¼X·% '–DáÅø$ ¯v­Ûº®¸¯nôwŠÚû z¡¸À³·?‹ÂÑþ¹ëŸáyžH°Øbù|¿üÝ/ñî—¿ccc8mËiD¤w @ùõëqå•Wâúï\_ñÞ¯½÷^hš†]»v•œ5ü–6kž“ß<÷¹X_LJÈ8²vmñOW,ëû"‘"¥ÓA¶CUU<ôÐXÖ EÁ«þîïð»—¼W¿ð…H&“âGU±ñ¢‹Íf¡(@*•(í÷Á,`šH–­p0Èç"ÙQL=bäD5R*%V ÇûØ_Jšçþâ߿톹'0«xx<^5Qóõ¿?ýåïE‚ìaž~pðŠ?, ‘HÀU]œwåy0 š¦amñ˜6Ò¢*غukÅc===ÈçóزeK]Ëïß¿?ÈÆ•?>;£)çg©åðáÃiø!ªÇÈÈn¿ýöVoFCÌ›ò¹¥Äçí·ßÊ. Ôù …FFFpäÈ‘VoJC4:>9‚‘‘‘PU~iõÈçóÈf³xüñÇ[½) Áº-uÖmY·¥p’uÛÇ·zS‚u[ê$¬ÛÖW·]èu`Û€õ9‘?ABÜó×Ð(ÀôqÓ¸ç™{ðÌ=ÏàÚC׊Ä€G7?Šh4Š}ìcxࢠÅ*Èd2âÇÁ?<^óš×T¾±ë±2éteÒÄqJ]=²{H6 ¸.ŽžpN9V6•çáÞâ|5å½Væd8ÊLNNbrrñx†aàÅ7ß\zÏX p]¼òßþ ©T oû]°í‰fμø# PUضµk×"›ÍB?óçH$Jë×4@Q\$²Y¸³zŠ “©H!ÿg³Å×ä"gŸÅ½kð¹YûäºbUÊ…Ù4MÃ3[Ÿ½lƒ™ôO¾ëBÄãqX–½¸­¿ÿýïqÜqKêORӢ׸oß> aÇŽÁc‘H7Þx#fffj`333ؾ};víÚ5g±ééé9¯¯§ËØi§dG‰š-‰`ýúõ­ÞŒe«›ÀÒãsýúõsZ5ƒl9sòÉx¬V">O>ùäPvͦա§§}}}8餓Z½)ËÆº-uÖmkcÝ–ZEÖmO;í´Voʲ±nK†uÛÚdݶ»»»¡ÛšHˆâïgâ>¾r*  xDbÄrgä`Û6î~únœþùxÕ¹çþ`ßàÔSOÅé§ŸŽ¡ŸaýŠu!Mü(Š‚«Î<P\pÁxÓ›ÞT¹1²'ŠãT>n• Ï=8 @Qpà ^€;^øÂÒóš†^ðض½¸Q|}:†¢(b;äã¹TUÅ‘¾~û‚¤Î~д`~•L&ƒ®þgl?#‰‹/þ¢Ñ(ÒŠ‚Ó¾>xeY(mŸ¦U$Œˆ¤Še‰}MUK½Wª=—N׵ˆa ç™ VÚ å=òp$ЉãÞßß¿"uÛE'T …BÕB¯«««êãå,ËB__¦§§‘Ïç1==‰‰ LLLT ¬z²—§Ÿ~:/:©e:墳VlXr|®_¿~Ys--UWWWÇ$TV">yÑI­ÔÓÓƒK/½'žxb«7eÙX·¥Númm¬ÛR«Èºíé§ŸÞêMY6Öm©Ó°n[›¬Û.tÏx)dþÂý}«¸±>ù%ˆJbH(9gH¸åþ[ù§òXwÇø‹ÇC6›ÅºuëpèÐ!üìg?›÷½žû»ß=EE©|Ò0İ\³{’–ÉåD·ªï£{ŒÌlÛ¥l¶2i#×ï8¢IÑ…Ç?¾í6¨ª Ã0ðƒW¼ˆÇáº.Òé4tÛÆ¥ø³û~‚÷½ïÄãqü鿈ïŸôIär9$“Iض ×u‘J¥àyR©œâIp±X k{{ñÉ“Nµ—\2g“êë«ÙÛfQT»"U2M³¢wO__ߊÔm=)}?FGG144TQXíß¿¿j÷¯Ùfff°{÷n"ðöíÛ‡ééiD"‘9ݧ§§§Y 5É|±)ÇÅd|µã“(¼X·% '–DáÅø$ ¯0×m Ñ!BQDÎ@NßáþÈÞ¤Mˆ$ d!nºízo9á-؇}¸ù´›±å¹¦¦¦ð, _|1öïß_ó½_*'‹wœÒÌíås›Ìî©1Ÿtº¢÷†7«'‡2O¢eM¢QÑ#¤Ú2r–¢s>ñ üÙ¿ˆ'|OÞ{oÙËÜ`}7¾ð…0ßúÖÒÐdšäóbè°bïÓ4á8¡ë:¢Ñhñ¥t]G:†mÛ¸+›…mÛÁÐ[¶m#ö‘ NCó<(ŠÇq (JåðfõR$«?U÷1\†E'T¶mÛ†B¡]׃Ös2c¹cÇŽš4<<\ñÿÖ­[±mÛ¶ŠõäóyD"LLL P(`Ó¦M+~ˆV»…b3‰0>‰Z„ñI^¬Û…ËN¢ðb|…WØë¶Ù¬È[ȧL³8Éï@-MJN6¯П<öœ·ö<À ×½¿ûÍo0~Î9øÑ~„Ï}îs•odÛs$7¼àxž¼ñ/+ÙìÜ^( ™•<ÈZÞsê©"R\—ã8U瘪 (ÀÔTÝïE¥ª¸öÈÜwî¹ÀÁƒÊ*†·jÚÜdD<.*@0É»išH¥RÁÄ÷³É$J,ƒišˆ{Â@*•‚ëºÐu=H¸¤‹É¯˜h)ïlð¾UUÉa‹=K´è„ ìØ±CCCØ·oÑ%s×®]ËÎJcûöíèïïÇøø8†‡‡W¤K-ã“(¼ŸDáÄØ$ /Æ'Qx1>‰Â©•±);r¨ªÈw†xÌ0üHž1_Š üÃçÿÓ?Vê¥`úgÓ8ãoÎüò¹¿Ä±GÎÄ%—\‚ÿ½iÞö¶·U¾Y*%Þ¨,)!‡à z”d2b×I‡Ù ‘ñ©ÑûBÓ4è¶‹ÿó?C‡‚$ŽmÛA’aÉä°_e½T´dë wÙv0TWùÐbU{ŠÈÉçÄËös¡í+ï­ˆÄM2™„ap]–eall ÁÐa2‘äyt]GªØIQ” Iu%TFGG1::ŠM›6aãÆÁ„KË?vÏž=ÿ !‰ P( §§‡]:‰ZdvlŒO¢°`|…ë¶DáIJ“(¼ŸDᦺ­ã”’)ŠRœ>C,°¾ ˜ÿà=À×Ý®›º€Ï@$Xt17Ìùêù8÷×çGO8НxžÊç«¿™¦‰DI•ƒLD@QÄ_åÑ»®˜t^v£©–h™Åß½;H¦hšUU—6 V¹*=GªõÞhÆðX@eïUUƒž-²÷ŠaH&“ˆÅbArE×uhš»˜R¥jÏ9çL³ö¨3¡244„M›6!ŸÏc÷îÝ( èëëæM›>) K¢ðb|…ã“(œ›DáÅø$ /Æ'Q8µ*6Gä0\Wü—=VtÀù9 vÈS…â0X ‚!¡²Ù,nü蘹u&zʲ,ŒiÚüsŸ¸nÕ‡+zJFå_ª LNŠ.óÍm2ûmÄJËV¡.<Ü×2•÷þXIªª (×u+zÃH³÷UžÛ¶Ç¡i‰Eçy0 #ø;Âu]xž‡L&ÓÔ^,ÇÕû®®.lܸ;vìÀž={‚Éé·nÝŠ‘‘LLL4m£‰ˆˆˆˆˆˆˆˆˆ¨óÉÜG6[ì8¢(Žh \ Àþíè¿áÁ«CMiÀýC÷Ãó<¬ÃzœtíIÈf³xòÉ'ÅUŠR1A|@×ç$TÞ1:Zšod!ñ¸îkIû©U ­ÕÎÊ{Ù¸®[W9G ?Š¢=S ÃæUI¥RÐ4 “““+ž€ª¦î„ÊlåÉ•M›6aß¾}ؼy3+DDDDDDDDDDÔrÞ×-vü(&U<ÈÞ]œ*$ l~t3^òÜ—ËÝö™Û‚¡®äÍøgŸ}Vôœ0 1׉œå^¾‘ªV™å88å”SêO¨P@³z‡ã2M¦ibrr2x,NW$T\×E6› † +¯ÞÞ^ (žm,9¡R®¯¯ÃÃÃØ»woÇ#"""De9úç€e±˜èI½fM«·ŠˆˆˆˆˆˆVR6[AKUØ<@õ÷ˆxüþ÷ãœsÎP¼‘vþlg0”œPþª3Ï„)'lÏdJ •lV\hÎîµâyxæÅ/nõ!hKªªsœÔC×õ9sÈÈeåïÁÁÁ9½xlÛæb‘ï900°bûU×*R>ŸG¡PÀÐÐ`bb###JI"""¢FÉfKó¦R€> dÆå€nˆç‰ˆˆˆˆˆ¨sÉ©J2™â”#)Ð_Š`°îõÝ8ë¥g!ãf²RÁÄæ–e7éÏ;í´RvFÓŠÝ[ +étéÿY¼jÃт“PYH:†çyëÓu] ñV$*€è•tóÍ7#‰4tŸêî¡rÝu×aëÖ­( €B¡€-[¶É”ýû÷cûöí Ý8"¢vÀnŸDåy"‰bY"‰¢i€óu ~5\ äÎÌsDY9½ú°·DDDDDDÔþ\·4o{*UÌ…ÅÈÅÄïû~.}òÒ`9Û¶aš&<σã8Á½›õ?\ýl»r’zÇ¥ž‡©—¾´îy@ê%çédš¦!•J5lÂxUUçMÎÈó«iZ0Ü—œ3§ÑêJ¨LLL`ß¾}Ø»woÐ eÿþýèîîÆ®]»0<<Œ={ö`ÿþýAÂ…šo%dž#¢ê²Ù,R©ñåmYVÅóÑhŽãÀ¶m¶f ªS,Vêi˺ $»ãGtˆ–H)ñcô0¡BDDDDDÔ©§4*W0mFÅv²ÀÑÂQLNM¢ëü.œõò³ÍfáyTUE6›…ªªÁœ§>õTeâDš=¼ªŠ!Š Û¶+†¢j„FõÜXŠfÜ£J&“˜œœløq«Æu]¨ª EQ‚*¶mã±Çkø{Õ•PÙ·o"‘HÅü(ù|7nDWW §§===L¨¬0Û¶«&NÇÁÀÀ“*DMVÞÊ!"•JÁó< ‘HÀ¶m "•J Ñ\‰084B.Ä@±Xâfp˜•çÿfB…ˆˆˆˆˆ¨­Y#*šÀôòûòĵ¢|ýþ¯ãé7> èyM ÃzE¨ªLL¯( Ž=ÿù¥!¿Ê™fåÿŠ"’,ŽÓ‘½Išu¹É”ò÷’I*]×áy¦¦¦þ>uùÕÓÓSñ>ŸGÅc2¹B588ˆh4 H$ˆF£Èf³ˆF£A61›ÍÂ0Œ u¼çyˆÅb­Þt¢Žå8<σëºpÙlš¦Á0 BQX–…x<Ž©©)Äãq&<‰ªðïàòÑQqÿÅÑq?TÓµ¬Þ%é4À4͆ÍÒjò¾T'ôº‘÷ÝÊç7Ö4 º®Ïýú׿nè{>§žmܸ–eáºë®C$eYˆD"A”™™ŒŒŒ §§§bX0ZÙÚ]¶x—ÝÊb±r¹4MC.—ƒ¢(H¥R°,+h×u‹Å‚/ Û¶ƒaÂlÛî˜À'j×uƒžaccc°, Š¢}ÙZ!],lË»˜–??88Ä0Ñjå8¢±ç{VÇèÅ¿mˆ1qQü[+þTi<£ÿ+à2GIDDDDDÔqL³lÞÙ A‡¹׈–‡óN9 EQà¬^ ÉdŽã`fdfq>ð%+Þ×iå|'ÖIû"yž܃Ëd2DÂèýï?:ÔÐ÷ª«‡JOOn¼ñFäóylß¾ÝÝÝÁäôù|W\qòù-KL&„Q¥ æÑ ¥|<Ü:¨/œÿ×ê=£ÕŠu[¢pꤲ“¨Ó0>‰Â+lu[E)NF/%!Ý9Tq݃‡/û%¼R{%q?G6^ÿØsžSvñ)hŠR%KCíNUÕ¦6R®kغu+òù<úúúP(°eË …E½Y¡PÀÐÐP0™½ ¸ééiäóytww½]úúúÐ×ׇ|>ß´ƒÑlÑhÉdÙl6˜kÁó¼Ee'5M[ÔDBlOÕÔŠM«*>å¼)ñxŠ¢Ãïɹ‘t]‡ëº°mžç!•âD4W'ŧmy¢uÑÄp_&•LD;s¾ø;›“Ý5 ë¶DáÔIe'Q§a|…W˜ê¶®+&¤¯+þVdKÃ<]wÇuXûÓŸƒƒÁ|·¯ûýïqâ+E’¥b¼é²Q~¨s†Qunã•RWB%ŸÏ£P(`ïÞ½ÆÞ½{ÑÝÝÑÑÑE½ÙÆ1<<Œ™™äóyŒŒŒ ¯¯/ÈlÎÎhvww/˜´9|ø0FFFšvÀAÎe¢( LÓÄÔÔTE‘ÅÞ´]ìëåÐbœ{ùFFFpûí··z3–­VlXr|Þ~ûí‹þžh•T*ÏóÍfç ë¥iZÕ9¤–K®×qär9d³Y8¼Ü…B###8räH«7eÙV">9‚‘‘‘¦^˜:άÞ)AкYˆÉç—`àbý²XëíD@ü¶¬ÒcÔZù|Ùl?þx«7eÙX·¥NúmçÔm©³ÈºíáÇ[½)ËÖ)u["‰uÛúê¶‹m”_õúÍ)ëä÷ß?a4¸m ixãûÞ‡§®¿ïºát}ìcsW³‡J2M³j'‚ÑÑÑ©ÛÖ=äW$ 2”€²¥*>L®G¶F(WO—±ÓN;mQs¸´šeYÁ°[Þ§Úäõµhš a$“*‹]•D":t¨Õ›Ñ0ÕbXz|®_¿ýýý­Þ­% ضl6 `n’RUUd³Ù†÷PQ%H¦*Š‚t:ÁÁA(Š‚ÉÉÉV–¶&[ÎtR‚ª‘ñyòÉ'7}Ø„9ãßÚR •*‡þZ$m‹É$ i€ Ÿl¶4\®ªŠ2sZ9QÓõôô ¯¯<òH«7¥aVsÝ–: ë¶µµKÝ–:¬ÛÞvÛm­Þ”†i÷º-‘ĺmm²nÛÝݽèí˜} &þÒ8ÝA¨ŠŠ'Ÿ|º®C×uÅFëH&±ÿœsð¿ví¿ù͹+¨¶ÒUl%‡M?~üã7|½uùÕH}}}سgöîÝ‹ýû÷ctt´j`Õ“½<ýôÓÛæ¢Sé“Ë傉¨›Mfë\×E.—[Á³’"‘Ö¯_ßêÍh˜j± `Éñ¹~ýúEϵÔlr|Í\.‡t: ¿WN&RVbȼd2$55MÃää$t]bÓó¼`2ª_WW"‘N>ùäVoJÃ42>›}Ñé8"™$3²ݵe1¸Ìâ0¾Q´^š54M¼g&#’-®+z®D£b›Øc¥5zzzp饗âÄOlõ¦4Ìj­ÛRçaݶ¶v¨ÛRg’uÛÓO?½Õ›Ò0í\·%*Ǻmm²n[ÞH¿r„ƒrqß_ˆF“:p×Sw!—ËÁÐ4œrÊ)Áˆ#Oz*ŽûéOÑÿ†7´ú0†^#ç «¾¾¾©Û65¡2::ŠÝ»wÿwuus²Èß妧§;¢@t½½½ÁD׺®cll¬¥ÛäÇ ô8v ¡vlèèø´, étŠ¢@Ó´y{¡4«§ƒ¢(0 ‰D½½½ˆÅbˆÅbË_1µ­NˆÏlvÖPµ6Ä\)qˆ‰è—Y‡S6ˆžÛ³©je¯U‰ÃÅó•´«µnKvPvu*Æ'Qx…­n;ûöÌÌÌŒ¸©Ÿ:åSâA×Å«þîï*FA‡' ÅuÝ–4öïu'TÆÇDZuëÖàgÿþýØ¿Åc[·n]p=£££˜™™ AŽÁ‰D‚IŽ1nf¡PÀ¦M›Z}Œ–-›ÍÎ;7C+8ŽÜ4Ö4­£†Ä¡¥›/6tl|:Ž]×ÌÈëºÞÔ̽®ëH&“H§Óp]º®3NW¹vŽÏlVô 6Ä0_Iˆ¹Sо@ýRõ„Êl¦)¶Ã0€©)`lLl["!~©°v­èÉBTÕX·%jí\vu:Æ'Qx…¥nÌ’PÌ‘”7 wg¿âlñ„ëâÈ‘#Áýó£Ô¥ÑCÚ¯6uÍ¡ÒÝÝ=g¬Ø¥d ‡††°ÿ~lÞ¼===ǦM›044ÆöíÛÑßßññq /ºKXÙ¶x<.&NZàu͸a«iZð>ªªÂ¶m¨ªÚñݼh~ Å&Ð9ñ)‡øJ§ÓÈf³‹*l›™¹—Û566†T*Û¶Ùr`•jçø´,1·I.Wl$äDå_ªÇÙXô<,ÅavФŠaˆ¤‹aˆÖP–%,²W Ñl«µnKví\vu:Æ'Qx…©n;8XLª$¢AìúõëáºnECqè:¿øb¨÷ÜÃ$Á"ððòÔ•P‘cçb|¼|>tóêééÁ¦M›ê ={ö`bb"èVž˜B$A¡P˜ó\»J$Ð4­®ž)š¦-˜tiù%£ë:¢Ñ(TU…Á»E«Z­Ø:'>=σmÛA’BÎ_²V̆a`ppžçÁ4MVV¡vŒO×I‰x|Ö„ôc‰•Ep§"¡è8\×-•[™Å­o6]‰ŸtZü/CLöhdB…æ·Úê¶Dí¢ËN¢Õ‚ñI^¡«Ûz®éy$H¨ׂªŠ{\ªª²w 5M] idd»wïFWWWÐce÷îÝišØ¶m[]ë©5‘_'–r˜¯zçK‘s84“®ëH§Ó•_F´j-4Éf'ħã8Èd2XÔ|­ìÅ¥ª*LÓD*• *Lª¬>ퟞ'’éti2x$ z‘Ä!æO©“eYH¥R˜œœ„ëºèíí…¢(Pº®#•J!‰¤è²Äú³iŠÞ(ÕB\ÎÃbYâuDÕ¬–º-Q»i§²“hµa|…W«ë¶ž'®#£ø¿ðº¼Ê3 lÛFZ¶†ç¡æ«;¡222‚ÑÑQìØ±£¢+æÌÌ FGG122u'U:™ã8Èf³ÁäÒaëF¥iZEÖ6lÛG´’dA;66¶¨×4Í–Ðñx<3´··wÑÛOÔLŽSêÝ{|8ÅŸE~lmÛÆ‹y¿?ã ÜsÙeH§Ó0 k^ðd¢Q¸¶ ÄëëiVK­¶ñ¸¨ÔÑÊJ$M?辯}õ!m¥aYÖœeØè”š©®„ÊÄÄvïÞ½{÷ÎÉRvuuI˲˜PæKN$Æ^º®W|ѨªÊ ¯©£d³óÏ#?û‹MF„-–-˪h‘A&¶]Ö¢HR z§ÔYÏ}è?þOß}7ÇÁúûñÕuëpåÍ7ãßøEÁÑÏÑ͛玃è©âÌzo¢»øz™¨ª˜¤¾Î§DDDDDD´Ž#F8nwØ4ࡇÂÚÁµX«­­¸²ë”SðžcÇBwφ:Ûqõ¼(ŸÏ#‰ÔìòµmÛ6ÌÌÌ ŸÏ·zŸZÊu]xž$)Â8~_µ„ Q'pœÒ$ÒŽ#n€JrΔNè‘ÕÌù–ˆËóDBe@r¡e=$ X–…Gßÿ~lýô§aš&z¾ò|óÄq$ bøô?ÿsû«¿Â¯_õ*Üÿý¢¢íB$M,Ùâ{*ÅÇ¢¨œ»Å†¬ÎPꀯ"""""¢P󼲞).Ä›ÊUm÷úsÎA2™ìˆ{=Ô>êJ¨LOO×µ²H$Òêýi©ÁÁAD£Ñ9 ‹vÀ*Ôî\Wüd³"™bÛ¥‰¥ÇeYH$0Û|×uƒŠ‚eYŒ] Û.›€^r 5X–…(Š‚ÏýË¿àŒ©)\õ¡Á4M¨ªŠL&ƒ}ùËËœsã¸îÐ!L÷Ý"*ÛQˆž(D2% Ñ+Æ.>ƒxmV¾1*+‰êÛÊODDDDDD+«ü^ià™¿ƒkŵ[™{?ûY<ÓÓSu0Zï'-]]C~uwwוTÉçó«rÈ/ÇqH$ˆ›†a ›Í¶Õüí´­D³yÐÛ+Z1xž˜ï › –Oú0î¸ÃB2™„ª°,ñºvm¼Ífƒ¿mÛF"‘Àää$[cPh8NY‹"ÉCÍ¡¾<ÏC*•ÂØØ˜˜lÞuqèž{Ç|¿C眃uþVü£@$M4Tù¥¢ÔšI…Hªä ’(½É—JëHŸŸµÝU÷ˆˆˆˆˆˆÂ4Ëî׿-Å÷üñœ×>þøãXûüçcò‡?lõf·Ù«‡÷ƒ—¦®*7nÄÄÄDÍá¼FFFÐÓÓ³*{©ÈäI:&Š6MsÑã÷išÖ²›¢š¦!‹-ED-ÍŠ$ ZÆ{žøyÙË~Žÿ÷GpÏ= 5 se9‰¶" :MÓà8<σišH¥R­Þ4¢€ëÎê¡’B)Y1‹eY8ò«_á‡×^ Ã0‚2PS¼â _¨û=§,6úÈ¡4é½Vöw¹xñu@©7KµÇd—„ø-{ÁÑÊˆÅæ6€½ùE7ãÊ»¯œóÚß|õ«8û¯hõ&·­x<ÎÆ¹KTW•žžlÛ¶ Û·o‡išBWW`ff–ea÷îÝØµkW«÷§é²Ù,²ÙlЪVRUuIÃ~µj¨°d2‰ò 'ˆÚH6+&,‹DáÔSï Ãq€sÎù"xà|ÜvÛÃ4K½WÂ,‘¨2™wÑìï@€H&“õ¬žhÅÅãe`¢[v•=T×_=¾uèžÚ±×:„o~³ôü">ÏëÖ­ÃOü_âåKíLÙßiˆ*rû5ˆÄJP¿+z¨pè/"""""¢Æó¼êØ®»ã:¼õð[#.`—ZðÝzÕU¸ê=ïiõfÓ*TWÆÐÐ,ËÂW\]×qÅWàŠ+®Àþýû±k×.lܸ±ÕûÓt©Tªc&?RU•ãçQ[Ò41Ææ]w}±X º.n|þà?À©§~/~ñ=H&EÒÅuÅÄõaUï¶)Ş̌¢ª*<Ïkõ¦!›õN@ôþÐQ™PI¥ðçÿçÿ “É kxÿtå•XÿÞ÷ƒƒ‹~ÏßF"xèìSª÷FY,¥d , æ—¶J""""""ªOEÛ:xøá‡Åhßð€›‚ ÎN˜#—ÚW]=T¤ááa˜¦‰|>ññqb"úÕ8ÌPšz±C{…•ªªp]—ãçQ[qœÒ„e2©H$pÒI×âƒ|',ËBW×½m3gŠªŠ¤O=ՂᑊC€ésf'jÛ?Ž#ƼB$9f×q]Oåóøøà ®W¼ý=ï–Ѫhê¥/ÅÔÔÔÊî ([ç7óª´É÷ Q»ˆF\®ì øÒ÷¾=¢78Àe&àÚÁÓ­凨î*RWW6n܈ááa É”B¡€‘‘‘VïOSÙ¶ÝQÉöP¡vT>Šã80M–eaûöÿ Ó4Ûn’-ÇÃ~Åb¢»k-2¡¢ª*¢Ñ(‰D«7ŸV©TJ$“ÉâXYˆ¡¾ª$~þó¸ñ‰'på–- yoEQšRvi?’—@Ì “€H¬Ñʰ;~x‡è‰r®\ öz{qYq* ¢VXtBe>…B»wïnõþ4M"‘@,ë˜Þ)8lµ­ò|‰œT+(>77™æ¼a2)’DŠ ÌÌ-(Z¾_š¦1!J-åy¢gJð±Ìp †úšå³Ï>‹“ÿñV~Ήñ•ŠüÄœ*.Db…ˆˆˆˆˆˆbÎ¥œ ¬9²Füý<x›ŒÁN&qáUWµzsikXBe5ñ<ÙlSSSmÕò}!º®ó†,µE)ÝĕɆ\.Ħ¦i7nu½2&Ž#†Mò}‘Xû×Û[zj(uoÕ4 cccÁþ5“[šPHAÌ›’A0¯I6›Å?½øÅp¶mã o{C7à܉ ñ·ãˆLdy×µåã˜i/ƒÊL…HEWè ­2sîÕ”ÏÅYvóÇqœŽºKí§% •B¡€|>|>?ïs…B¡ÕÇf^¶mÃ0Œ†ODÇÇ[½{쥲ŠÕŠÍòçßò¾©eYA‚¡|MÃ0æ´afÓó*+Š"†ORUñ\yE<_ù$çR¡ÎÖøtÝYó¦$Š?‚!¿îþô§±mj †®CUÕÆ–Ÿ®‹×Ÿt’’hÈdÄFɘ»L4*ÆÖ“‰Ò2’牱÷Ê’3é4Jú‚„Q»×m‰:UXËN¢Åò<Ñh?þx«7¥aŸDáÕªºmÅ­›ðô§Ÿ.ýCNŽËû–Ôj‹š”¾FFF0::Šþþ~ tuuáÆoDWWFGG122‚þþ~ŒcxxCCC­>FX,´7Msù+œ¥Ñ š¥Ðu=HÑêR+6´,>³YÑú½ZxÈ éÇeYH&“u¯sBxÙ4­z²Ç4Ë*IÜpà pÁöœ×qؾÎÖøİtA["áPö9žþÙÏðºŸüç|ë[pu} ï°°çwF?ð¼âMoÂùeå—§(P4M$Fâq@Uq×—¿ŒKd¶RRU‘TÑ4pÙ¬ø?™¬ø²°>u Îý#yÖZhÖMÀË ¥ˆ9´jµsÝ–¨“…¹ì$*'çfõ<¯âšÆqœâPÆ¥.±Ï{ÞóZ½¹ Áø$ ¯VÕmçŒ|àÏÞþ,^øÊÎzË{–Ôru%Tjµfff\œgeïÞ½èëë nàŽŽbÛ¶mÁ®]»‰D011Í›7#‰ §§§ÕÇ €¨Ð†T*…L&ÓêÍY²…;¿œV—…b@ËâÓ²Ä=ÎZ ˲`š&ô:oÖ†ud,9ä×켪Šû»â¦µŸþô]ˆÇ?ˆîîÇæ¬ƒ •ÎæøD<-‰4ˆ¡¾ÊâõÛÛ·ãëÖͪ7¢à‚ßÿѯ¦i" QÉv©T Û6l@ìã’Ixž‡_þÍßàÈßþ-^YÞüI&QdvÈ4qèœs°þ oÏ;J…¿…sär(÷~8c 8Ñlƒ •U¬Ýë¶D*ìe'u&×u+zÊKŽãu“d24ÒT–e!•JAQxžMÓH$Ç188EQ`’É$‰lÛ^–… ã“(¼ZY·u]q?D×XTàöÏÜŽ™ÏÌz Û¶ë¾ÿC´êò«P(`bb¢æO¡P@$Yp=‘H$Jظq#¦§§‘ÏçÑÝݬ£¯¯}}} &rŽ=ºàk)#—Ë5íýšC-N>ŸÇ¡C‡Z½ËV+6å~.%>:„ 9·ÁÙ¶èQìibÛö¢zµ[>TÓÄ}^‘ŠãþÝÝÝP”Ê ¶ÙÓ[–Õ]K133ƒ|>cÇŽµzS–m%âóرcËî¦-GÄ+>à@LF¯AôPÉfñÔ‹^„üÃãßû^Ëçy°mƒ‰žûÜçBQ”àóžÍf‹Å ª*>þµ¯aæ–[H¥ÐÛÛ‹£_ŒO<ø ‘H ¢··G, ÈåF‘H$på{ß[z³böÖ¸øˆÿýïør¿Ì»ûµ…BwÞy'ž~úéå¯,ûÒîu[¢r¬Û®|Ý–Ú›l°áyÞœëæÞÞ^¤R)¸®Ô1ÍfaY\×ÅÀÀ100¬+—Ë!#“É N½ïMÓD<G2™ÄÌÌ Î=÷\=z´Õ‡`ÙÂZ·%Z*Ömë«Û.Ô?¸ïãB\WºÀ#Ï<"+»1¤ªj(¦K ö011±"uÛºz¨ 5¤ W$©HºÌÌÌ`ÿþýضm&&&æd4»»»,Ÿxâ äóù“9Ë%»áèè‰TU *€¦iVmaC%rÑY+6,9>:„ñññŠÂx1l»Ô;£<ìR)ñ;wÑŸÓDc^Ô¶«÷ÄD£y¹ßGž€X¬4D˜Ì%ÉøíííE&“A"‘€a«²å†¬ðuBBe%âS^t.§5Q*5ëó…¨ü¦Å¿w=õ.ǺíÛ—5q‘ëºp]·âsœH$à8t]G2™ÄïBò©§`YÖ¬YUU‘Ëå i,ËÂëÞÿ~xž‡L&MÓð‰ÁA8Žƒl6 Ó4¡( ’é4âñxð¸¢(¥–¦Ž4]‡ ÷kWº'2&ÄÜ1«/Ì–L6Ô‘Ãz´³v®ÛUúíÊÖm©½xž×u‘Íf¡ë:t]G6›…çyèíí Zn«ª Ó4ƒÆ‰²~¡ëzPgI§ÓA”x<ŽT*˲ iTU­¸ž‘½YÊ{àOOOãW¿úUthga­Û-ë¶õÕm{zzj#M+öNq ®¯\À#¾S)qHQ‚^||o–g|||Eê¶uõP™™™ixKœýû÷]Ɔ†ªV ê)×­[‡ááᆘÙÇY5ÉUU‘J¥ØS¥ÃÃÃxÙË^ÖêÍh¨Ù± `Éñù²—½lÉÉXÇ™;J*… ‘à8âñòdçJqÝæ 6ß®¨ªH¸.¼p&8FÕ¶Kv5MsÕöPéééÁðð0Î8ãŒVoJC5*>Ï8ã /ë†mÅðt.D¯¿ôüŸþã?ÂVœ{é¥ËÚg˲‹Å‚!1‰D‰Çã°mù§ž‚aH§ÓA/Rù½`š&ÒÅd‰®ëÁÐÑhñxer@’!—HˆÏ½Ë?rªZê â8"‘"ç Ë=S–Ò‹*™‰‹DBÜÉ’TJü/‡øÒ41á¶,¯5 ˜œIŸhT û‹mJ¥Äút]ü$b›åÜiÅ)`šbyE‰¹_€è}có÷€q ·w€xò^;žxžZöZ§âÂζíy/ô(ÜŸ傰R=3dnBUáÄã·,\«i f¬¯_, n>4ó¦½\:nªÈ›2¢×îÿ±cÏÇe—Ý?šœF’"påâL¨¬¬ÛR=R©LÓ„ëºßkåÃ"‹Å‚ùž<σZÞB¶ //Çg¯KŽ).‡ *O6+Šl‡äº.¢ÑhÅ:²Ù,ž|òÉV²e cÙI+ONþ®( 2™ b±X0äV.— b =CR©¦¦¦‚”¿ç«ƒ”÷d™MÆílKMŽtrñI^­¬ÛVÜ‚|‹ü8…Í>Ê …RS*…B…B[·n­x|Û¶mÆðð0¶oߎþþ~Œcxx8“:É!GV]×a— qBk¡ØДøt]‘ (6¨je2e``®ëÎÖ§^š&ÒF)qâ8¢ÑC=¡.ïEÈë)]IL¦´2qRl¤Tª”,‘!•L–’*€HŠÔºvJ§¿þë_ÿ{žX—~HnÏgü!ŽùUp!&ç‹ëHs(¿6–ø,—Íú& „VìŸË!›HeæbÊNÇq‚›‡‹ýŒÊ¡1ä®Káy^ðþåäúâñ8¡( þâ/.ÀW¾òF<籿ǙO= ˜×‹Ë^;D²)^÷ÛS›j׺-Í%‹»‘)“r¨Ïó (JÐÓD&dåú]×…ëºÃÉá…dÏ<×u‹Å‚9Ÿäðƒ²U¦çyp“““ð<ƒƒƒ0MŽãÀ²Äp¨òµò=äP‰òf³ap]·bØD@Ü~Å+^ÑêÓ±la,;iéÊ몪s(f³Ùàó ˆÏ¯ìQ¢( &''±víZ†UUçôp-Oh–“½lg“ÐWÓÈûr^–NÅø$ ¯VÖm+¾zéàð~„ßüñÉz Q(øuعs§¿eË–ŠÇ.ºè"ÿÀõ,¾(<ð€àÀÿ¨ëõ³·«Ñr¹œ¯iš?55µ¢ïF™LÆÇã­ÞŒÐÛ¹sçŠÄB-&>8àïܹsQëÏå|_ÓÄO-ªªúªª6tßÅ÷湜ï§Ó¾¿ÜI§}ß0ÄïzŒù¾ïûº.~äß““â˜òßïî¾’ë¼·\o&“ñÇÆÆ‚mI&“~<÷Eñu]÷u]÷ãñ¸ŸËåüx<¬ç /dݶŠÕô½Õl“““~&“ bS’ŸMù¹6 ÃÇãÁgØ4M_Ó4?™LúSSSUËqÃ0üd2Yõ}3™L«w}ÑVSÑ̺-Ñr­¦2b%ê¶SS¥ûþ¤ïûßÈùßÅ+ütÙEÖØØïQÒ’¬Ä}Ûº{¨ ŒŒŒT<¶ÿþŠ.`‚K%»y†…eYH&“«²‹™®ëH'‡-ã:¹ë1-l%ãÓqDÏ=9æ#{MU›ôq9&'kÏ_2w;ʆ=Z9Ñ}½J-ÿKÇ©¼g‹¦ â¼óÞ‹[o…ãˆ×)Š´ÈÓu“Ôw¨f–Ÿš1WHÀްI|£ÑhÐòz!žç!•Jó£èº¾äÖ¦iV´P5M3îF¶dš= ^99?Šœ ¶Z™/[{ß}÷ÝP”â¿oºë¾yÞùΟâ´Ó®„»çH¾fŸè~¦CÌ-³ú:¸Ò,a«ÛvºòÞÕÑh4ÖÇuÝ ÆåkdëvEQàºn0D–œ”ZöÑu‰DÉd‰D"øŽCÿÈ–òrèÀT*|︮ dYVð='{«¨ªl‹aÁ÷–&H~·Éž+²7‰|Ït: ×u‘H$‚וÏå84M æT“sH -àË·YÓ4ìÝ»·Õ§±iŸÍ3_ýÀqœ`¢xÙ[4“É ןcccP½½½Aï,Éó< ¨>Á{­kXöÚ7Æ'Q8­DlÊ{Äuæ =<üðÃsz¤Äã€Â¡®„Š –‰‰‰à±H$²¤IéÛ…œÄy5MF?[ù %yAÈ„ ­™ÐõÚÃ^Í?¼Q›3-j«ä0c"aR¾ ÞúÖqòÉ?páœåä°EL¨ÐRÙvqx¹4¸ÀÛÀ“Á06åÃiÔ"‡Ã‘ÃK.÷¦Fùò2qhÛ6lÛF&“ Ê19´N,ƒaÁÿ2&R©’Éd°l2™„ã87E|O) ðÕ¯nÆ<ŠÏ½szn¸p~+‚Ó4ÄÅ@@}‡„ˆIÎq "KƳŒa 4LO¢8$¡LfÈåñíº.R©TpÃ6•J!öí !!× H²X–4öÃiÉ9Qä¤×Š¢ËÉÄŠL~Èï ¹ åó<ȱX,Øw¹>ù^å•+OT—'®5M ¾ïä2š¦!™LâSŸúT«O-uˆT*Ã0Íf‘Ífƒ¹ÕdbSÎÛ“N§ƒyƒR©Tdzëòs_NÆl9Ûj½–'"j'åC£Ã`jøì³Ïb¨ìÞO"‘@:^• Þ)|êJ¨ ahh¨ÕÛÚTrüáÕÞjEŽQKÔ rB÷ZÇ E«Ms¥´jz¥ò°,kˆ\TªªHøÌzv ýÁÁA躊cJíÁuåˆùS “Éßõ”›Žã@Q”àæãJÜì0M³"q([˜Ëâétžç=¶R©ÆÆÆ‚‹³çrÑ4-˜AQ¬_ßlö¿a®¹æw¸Á¶qçŸDLï…zíµ0L)£˜x"¢Åó#”_0Çb±à;Cö ‰ÅbA‹öòyCdœ›¦ ˲099Ôiå…øš5k`š&t]ZÆËžå‰L&”òæðì›¶åó¡•“PËDPù]W>¿‰\F>.×  â½ÊGy¯uµdˆç‰ {ór’èßþöd³•ÓΞؽœaUëÏÕz“Hñx¼êw¤i&çíÅ;ßæùêLóMÆM´\©T*ˆÃt:ÁÁÁ §•f/NCKW3_o“ù躔ãDDÔ~\·t?èþ[îP9¼—1 3»Å(Q‹ÔP¹îºë°oß¾ŠÖž‘H;vìÀèè(öïß]»vµzBŽa¬iZë.€$^åP,ó]ð5ÊBÉ Ë²*†öh5]I•ZI‹V3 ‘(Ï„R%EÞ VU5˜#ʲ, “É7_äÍ!^œR9÷@y*ʨh4Šd2YW™‹Å‚ßÍ&‡é)o}.oÀJ™LŠ¢ —Ëó©Ìž£Eι266Ü4ºîºëpÿý÷àØP_~p¹ \^\i@"¹BDd#&ÙpB6l’-Û³ÙlÐãìÀ;ÑÕõUär/C, †­RÇÿ.ÆfnºéQX (:Þö¶O ‘S•SUãã×cvg³r¸ ¹ÜK‘Hˆž¨ª*ê(Ù,pÁ—ãk_‹â;ßg³²w­Hæ$â±²÷Èd2=F離 LS½þñãºb½¦™Äà ¨ÐÛ+:¦Râýl[¬Ï²,o¥}0 ûü¾/zÑyð<ñZ™_™Ý£Ð¶m¬_ÿ†àÿ{H¤Õj#®ëC{%“É`¨:]׃úfy‚OÎw6›ìm²ØzB£çW$"¢Ö8åÎS ]­U”åóÂ…A] •‰‰ ŒŽŽbïÞ½èëë«x®§§ÃÃÃèîîÆ‡?üáÐObŠ ’Z÷-ËZ¹›=ÄM(¥Éjc7ZäÛyã®"±¢CLü[ÎCSn̨ŖÇD+MÞ˜¦#l]<[ÕYÆ0Ä1«ÅuÅÍyGUE‚åá‡ûá8ß †9ÄE­¦iÁÐ$²'ªª¼@¥ é³åÊÒÿrhžZÉNÏóÍfáº.r¹\K“tŠ¢ÌéISþ˜üŽYhÈY6ÊÊ},Ã¥—ž‰ß¿°7?ü þêþðÏ(.€Rù®¯0¢–H$z'Þò–ÇQ(üúúNÁ½÷ÞM3qß}?ðÏøú×7¡«ë^\}Ùìµxõ«¯ÇÞ½ã²ËÎD*¤Ó¼ä%Ïàâ‹_×¼fn¼ñ*$€m+PU%H„Äão‡e‰d„aˆ$„ãë×ÿŽY Çe¥¢ˆ$D: Äbk10 –/Vóä“ÿ7Þø(žy¦r:UE°@$AÅcñ¸hxá8bÝŠ"ž·m±¦Yz\ÓÄcº.¶S–Ù€x>›-MØZÞ`BÎA'“1®+žs]ñÜÍ7¿W^)¶Éó€±±òäM½½@&£PñÅ/^‹ë®ã_´0ÙC¬|ø.9RÅìëèùZsä""’§ØÀÖ†¬@o¸D£Ñ`Þ9¢0¨+¡²oß>D"‘9É”rÛ¶mƒeY˜˜˜¨ùºV²,‹±ØÜyJ¯±*Z®.Š1ù¬ ‘±‹ÿ«ÅßZÙÿò¾“ ø¥"â—ÏB$Z\ˆ‹Yö>kŒA$UVðæŒ¬(3±B+%‘ç|!—ÍfaÛvEëð°heÇ M[8™ã8â¦Kùë’IàòË_Žãÿâœa@4MC<Æ’—úÊVúD°ÿ&oDpçOöêœ/]ö é”ÏÒìøI&“øÅ/~w½ë]˜™9†¾ð¯ñå/Ÿ!†2 Êô(DÙMÔæäÍ{U{”¿nÇŽ§ð›ßüßûÞ×ð¼Ÿýl}4Ž[o½…«°nÝüò—i¼øÅÿM[×Õ15õRÜ~{GƒãhÈd€;ÿ >ú^ùÊ'ðôÓâ}7m:ñøkH¼/zQ©§«¦U&.t]l‹Ul°”Nƒƒç ÏõöŠ2=—¯±¬Ò±¿ñxiدÞ^ñ{rR”½‰„X—ì‘’LŠ¿-K$5ÒéRÆ0Ä6 ˆd‡m‹`ɤ|Oñ|6[Ú?ÓûŠ÷t]q}#z¡Š÷”å¿ã”¶‰%™ˆ‘É‘214t?<ï\}õÕ¸øâ‹[ý1£ŠÅbAÙoÛ6 ÃꊊE^‡·:áRv/hø%‡”Ï•ÿ ”·2i)«<®+b;™,ý-—·,Ù3MÄt<^ŠwÙ«LÎ-`YÀ±c´ô¸­Uà<\<= ây‡'§ÐYÔ*円†033SñXOO¦§§[½OóJ¥ÄEÇà`õç=Ï &¥­FÞø•Gª d’7H€RòÃ,>æ@LF«@$ALˆVª‰âß³¿ ¢É‘LÙúP|] ¥ž+Fq=ÑâscXÑ+Š¢@×u8Žšù+¨s”_TT“H$N§[rQ%ç ’ã=ÏÞ†°wÜPÕêÇõøãÏ„ã¸æš×à_ÿµr¨µòãòB¹··ccc°mŽã ™L󺮺D­ Ǭ÷êŲY ÆH¯¾Œ˜/e5Œu«( þú¯ÿ¿ýíoáyÿŒuënÁö·}¿û÷ëðæïA”ÝD¯ÔwÍ–H”nÊÞ¹œø-oÚvé}$òEœtRÿðÇãÙg»03sN>ù±{÷Oqüñc¸ä’(n¿ý^ìÙs<¶ly#b±X¹ñÆWâU¯:ÜT”‰‹.z€†-[Ä6ÉD‡ì!bšâuñx©§|®ÚW¼á ˆe=¯Tf–÷L1ŒÊrR¾¦¼è+ï5ªi"1"_'o”•sÅyž8~òm2LKG™‘½VÊçGSUñ>òïòmÉ¿s¹Ê}Ó´Ò¶F£¥eÖ¬Ññúׂe]€|8ÚIrØ]ÙèÆqLNN¶í`(¯FªÖ°±<!-â1™Ô-ïÉ%‡À“Ÿw×-%åc†!þ—.5­”‘É ™h15{è¼D¢4äžü,ÿ>ŒÇôfK&Å6Éáød"TnGyoµD¢”•=Îåë<ïÒV$ˆˆ.@Ànöv\uÁÁsrHÞ‹¤0©+¡ÒÝÝ='QÒÓÓSñÿÌÌ &&&Z½?5Õêt’J¥‚–6Õ*…ò‚ÇÚà ÷î×€Ô÷çb@y‘™ËS¸€r"H[‹UÜkšïFŠÑSe6âFL"ybA$T ˆ3ƒ(͹²=àäñpH§ÓÁ„DËåyâ"¡ÚýX™Àkv2ÅuÝ`9Pù¸’¸xÃÉ^žçU½œ½l3È‹ÎÙ^ýê§à8¾ð…‚ªó] 뺎x<ôr]ƒƒƒÁ¼+rïx<^1Eù°aòx¶º¥!-O"˜/ÔW—K.ì\mcÝf2¼îu¯Ã«_ýj|èCÂ?þýà׿8Ùhz: %©ˆr{ì©BmCöªóG뺸([[ßyçCø·;÷ß¾øÅ?-Î#Òþþaüö·ÃI'=б±¾ýíÿÁG?z=| ® ôö®ÇùçŸ  ”€+¯< ¦y€Ê¤Å{ßû"ìܹ ªº€¸é(¿~âñÒß2)!ÿž/Ÿ›N—^W> `y¨ì}#‡Ëšmö×\y¹¼Vù²š&nØÊ›ÄåI—ò}›=¿Ü|åuù¼-²×‹ÜŸråǧr䌜{n†üó?Ÿ àwõH¨#Y–…l6 Çq ë:bÅÌ€L¬ÔÛ ÆóJ=,;¥ÊœÏ’(LêJ¨lܸ###Ø¿?6nÜXõ5–e¡««+´“ÊîõÀÜÛrÌ9ê& Z“[£8ì€ô€ò Q¡R!*BbÝé40˜*µh‘9Y“-βÙRe)›Œ§åiÀ³ä˜Ï¥Ö3jJ µìq¥øc‹ím$™8‘“ :Žôäá—-‡la&[{;èÏf³M½ /çyPU5hu'ÉDByÒU×uX–ü–ó(ÈI­åß®ë“v{ž$$å{­Trr¾ûدý!|ò“J0»¼@“cµ—ߨDO•¨ªÌ3aš&Ǫªð<ƒƒƒAÂENâH$055ÌË"‡…Ë•%¨( R©’É$4M ^SþSþ~å½åÂ6¯N'’7# Á•ÏÜs²®‹Éò»x³ÈøX-ç(›Íâì³Ï†¦ixík_‹wL¿{×}çm-nyÞN|ö³ÿ,Êp¢ç©l0Á¢”Z ›-ÝÌsœRÂÄ0J ‰2™RoÙÃ;“^ÿúkqøðõˆÇ=\sÍ›ñøã{qäÈnlÙòAhš†7¼AC*õ-\rI~ûÛK i‚¢(8vì!¢Œé}íqÁÿ’ì >›¢_úÒóƒÿË%ÕnHJó±µ·íêÏ5ò«L&MªíëØ®åÛVoÕ©üÈ!Å5ÊAë·³Ôä¶mã©§Öã±Çºñ†7dqíµâÔSû‹sþôbjjl[|æ¢ÑÒ÷ȬáöG|ÎåÐu²ž)ç.’õUyýë8€e]ô:qñzÙ«Ìqæ6Är]ñ%«$²^+{®iZ)FdÌÉÄ£â•=^¬ïŒ}P~ xM¯@<§€ž†¸æ¶]C0¼w&RÙ.4©€¡«NvñyÁ5»©C4ŽLC4¸ÐÄòŠ\ª½УÀ_\ðW·úãBDÔPA}(V¼Y¬(yž‡X,ÆùS(têJ¨ôôô`Û¶mؾ};¶mÛ†¡¡¡ ‡Šœ°~tt»víjõþÌK¶|‘­NÊ}êSÿ¿ù›Á0 DÿH^ ¨Q z#`$ïý€{. ˜w^ P_#–UÕÒ¦Y»X¶œ‘C ôöŠ ž#Y¶‘ÄLˆ¾ À“€b—Z®d³¥a²Y W¼È ö¡übÐ…¨ˆe *_Å ÙrÉŸ†a70‰Dpó“h©äò†þlÙlvÞ!øEö¨ˆÅbH&“p]¦iÎIä¨ªŠ±±± JªxçIedïæär9D£Qd2¤ÓiX–Ïó099 Ïó‚Ö~rø,@$fÌZwƒLÓ4\pÁ? ¾‡ä÷Š/^½"ÆuV‘ËåªÎ¹ˆ›0rÿd²#‹U§t:`N™´’ëÇ=s7ÉsS>—“LØÈu8Žƒx<|•ëÍ„oãÈ¡&@P™žžF|çΚ˙¦¹j’)€ø¬ž~úéÁgOUU<üð7pìœ÷ãÐìÅ'/þ$Þóž÷”Êf¢áÐðÆDÕÈ!lÒiñ»¼Ž)ü$¥ÞÕå-³e}×qÜ|ó§‘Lž‡XÌÁÙgÅÃ?ÓÔ ëñ ÕºLŽ»îψx(¯79r\Õm¬• hÆ“².ß,aùŠ,ï}~óÍWâíoŸ\æ)ld²#-}Üzë R)““SxòɧÐÓ³  üä'¿ÇŸüÉÓ8ãŒ3ðå/Ÿôl2ÍIØ6°fˆYM·mñݑɈº£öJ¾§¼/o×;h09† ¹¡â×’&D¹é“½ÑLƌܠ¥í€T»¶ø‚â:sÅe]@Q‹o ¢Ô0Q÷äßЋïY‰Ùâo¹/22P\wvÖsrŽÕÄÞJC{§PjX/®ÇEåܬ€H¸¼°oÞûä­þ(5”ë–’ë333PT¥¢u(ï;R(ù‹`Y–?00à_tÑE?6lð8°˜U5Ì–-[|M&ãûªêû““â]÷ý©)ñ÷Ô”ïŸzê~OÏÓ~<îûú:ßϼÑ÷ýŒï§Ó¾oš¾¯žéûéWû¾Ÿ[Ú6NM‰uÍ·mº.þVÏõ}ãJñw:íûš&þÎåÄvÄãb?âq±L&Se…c¾ï+¾ï¾ïO®ÜqŸššòUUõMÓôÇÆÆª¾&û““•aš¦?%þ"¿³s9ñw:]ú>Ÿœÿ¥º±aT¯cNNúþž=G}Ã0üx<îð“ɤ?66æzð]_.“Éøéù*Á䕎{«éò‚Ä÷ý¿ønÿ _ø­Þ¤Ði×ï­©)ïŠ"®!å5e.çû]]¿ô_óš›ýw¼ã^ÿ§?=|WÌWÇÓõbÝPþLù¾Ÿö}?éû~Æ×¢¦ï}Æ÷õ—ú¾~Añ9øâZZ/þd|ßäcò£ø“.þÖ‹ËNú¾¯ÿ÷‹eНKß[nS‘zAq™¸?÷Z~ª¸ma•óEý XG—÷]Ft jµv-#ša¡ø4MQöø¾ïç’¹à^…ï‹û¼WC«ÓJÜ·]Ô¤ôÛ¶mömÛÏçƒÇº»»Ñ××·èDÎÌÌ ¦§§çÌÅR(P(ÐÓÓ3ç¹¥ÊfEkÙLND§ªÀw¾sÅÆ÷?v zÿjî›é40x àÜŽ%·-y¶h´4n³þg¥V;² Pê.mš"I»vm©U¿lõ#[™k ŽP÷Í€ó¨èeƒ($[¤g³Ù ûÝìÖàr~9Dã8ÁäÞòÇq‚–ùr\Ä ÝÌVû$Ì›@ããSNY­u¦œ~¥XÅnkr¸¢F»µ˜ž²·E³{|É÷rÝÒ8Ó³Í>/r|jÙ 1™,µBTUñ˜Ç>›lÛD4ºòËÓ4ͺbº¼GÃìùšª}&d¯9$Xù2‡nÚ1m†fƧ$'sU²æýã©Ï'›ÍÂuÝU1ýlåÇ¥|H¿üà-8÷ÜçáàÁu8¾p 6lø>øÁ?mÛøÌß|Êëÿ¦ãK­V©í4³n» nË&i–½B“IÑsË!qÊëåáJ¥‚ˆŠ¢=Mä< ‚ U;Z3z”´³0MGX>”Æ_þe_üÒVoRô¢ìly +[ú&¥k^M£%ìØñd³‡d2‰ø‡ ¡ë7ãë_ÿPåŠ\@7!zR”÷Êp€\¢w‡Q'½Dd €.z™$ÿˆ½¢—ÅJ£'¨e¿Ýâ2óõÔš]m,︾Àe‚mê 0ÿ£²WHXéÅŸ²¡ÊÄ*­Þ°ÆZ-ñIÔŽšU·•sPÁNøÏ n_|®ërþf ­ã–²P$ ~–’LÄÍÌÑÑÑŠÇFGG±yófìÞ½›7ožóür”ÇŸ:‘þöoÇ7^õ€ÉëK‘r®ÐÎÜ%©…©j)¡"“"@iâ=©üäØ˜¨$Ë{¯Ž#†è±,‘ É‡‹ŽÎQyÀWfû À®ëX»vm0´€à¢;›Íe³YÄãqضÌ!çšPÑhŽãc$Z–…D"5kÖ ›ÍãúÒʪ›ÀÊÄgù8˳­TB%‘H ‘HÀuÝÐÜè1M†aÀ²¬ ÑÓ,ò&ÚBu9vµœ S×Kó<Ùv)9fYâ'›t]ÁääÍ¿“¢â{wíZñw,&^ˆÇåþr^ñœç‰×ˉ‘%9‘éÁƒW7û:}x©fÆ' Žw,V¼ÑZ6×G6›·b+σ®ë«¾òkFð=“N§œÒ‡GïÙ‡Ÿï:¿þõáy"áòùã?wœÿŽ`¬tjOÍ®ÛÎÇqJsbÉ!s9ñ#‹½x¼ò{¿üoÓz{E½NÕ(ÖëTÌ/VÞx Nwü÷ïjrÊ)ÇZ½ Õì²s¥É¹Jä|"rˆh9ñ¹lHø¡ý™Œø_×mXV ÿýßÿÓ4aÛ6ººÞxùF1œg@´øSœ$H€¸‰‡Éâc9S7ú3sz¦!’&D}Á×®W|½üŽ)’Z+¾v…¾:d"©­¹Ž]<>ÿüNí¬Óⓨ“4«nT!m pBAÔ)‹Ã¥ËÆýû÷cÛ¶mÏŒŒ`×®]ˆD"˜˜˜ÀæÍ›‰D–•ñ”=;ÊÉ–zþð7qûí'CׯR€lX'çB‘0¥PެÌñs¬ÈñšjØ.çJ“øyž¸ ™É”ÆÀÎåÄßš&’Aª1®k¥A "[) Àq¤Ói8ŽÃ0‚Iª]× æÃP%˜÷(µæ•­ôãñx0gK, ÖÑhñxš¦ñKµÁjÅ&°2ñéyÕ{§¬]»¶¡§ëºp‰D¹\.”Ÿ¹¿¶ms‹4s…rKrrO™È• Yåÿ±XÅ0§Á÷®L{žH~ÄãâurÞ™ Ö´Ê0bî–ÒMAU-=/{ÅÈ$ôOüo<òÈ ‹«®:±Xiü¬¦ÕԊø”’ÉÊNŽžçÕœß(‘H@UÕà;~5“sâóšÏŸàƒÀà ^òKÿ“97:‰àõøØ½Ãëþúu€ œðýZ½ T‡f×m«‘ f9ß‘œð|jªôšÙI“jm,Ë‚ªªA,“ÉåQ*• êc³±G1…Q+ËΕày"ÆS)Ãr¤LFÄ}ùµ¤eYðã>z×<Š›¯<ŒWþð•¸ä¤Kðþ'ßãÔãJ½Oþ¢g‰œGÅßÉc rP˜IDATå!]^ XD['Ï+Í±Ò ªZY7mKe#MÈúr§è´ø$ê$ͬÛVT-mà†GnÀ÷õï½½0«Œ„CMO¨ô÷÷£§§…B¡âñ|>îînD"@__úúúÏç1444ïúŽ=Š|>,7›¼)WNVD¾ò•Oã†d7Òó³[k›¯l݉DñxoûÃ8þø§ÐÛûÈårð<½½Ñ E«išp]‰D¦i²,hšLÞœËåH$ðú×Gà8§p¡iÉ 1‘̓±âPf[€t¢‚,7¨€¢(Èår°mABÄ0 BQ” 7Ê|ݺ®Û-“,³‡‹q]±X,JFUÕ ÷ŠláŸL&ƒ‰ÀåÍ,×u‘N§þeœÏçqèС†®³Uæ‹M¹ŸK‰ÏC‡abb¢jO6Ç©žL‘Š×{sfppÉd²jKxÙª6‘H`ll,4=RªQUÑh4˜L}pp°¢×J*bp>º..Øç“N×^^ön‘äéÊåÄÀÙ7ödò%ë.¿(6 ñ¼ì%ÓÓs?}ô«8í´áøãßEFGüà·øÝï®ZÑc×,ŽÏcÇŽ!ŸÏ/ØM[öÖÔd IMÄÓ¯¸J*Uq§Âq¤R©ù®í8¹Þáºøö¥ßÂßúoüòÔ§ iÆÆÆà8Þšz+ ÃÀù—ŸžøBL¼j¯¼ú•3q}¡PÀwÞ‰§Ÿ~ºÕ›ÒÍ®ÛV#‡‚1ŒÒ÷æBf—ÁžçU$DgCÇÙSx`ÝvéuÛFK¥D#9<®l,—Ë•âwvuÙqX–…óÿ¿öÎ=>®ªZüßò0m¤S m-‘r*å‘ Ê£ (ý9©°­?;¹^…‚¿èŒhêUg$¿ ½à#üð¢mF«È£Å *2ˆ’:c¥Eìi}Q`~œÙgÎLf&É<2g&ëÛO?IΙ9gï³÷:{í½öZëÑc¹~íõlþáf<¸€úçë“å5¢þ.ÑþååÚÓSøµ&,–éÍ1ǼŶmÿdß¾7ó¿ž(—n+¥@tÛÑé¶ÔÖÖ¦œ3× tسgGŸ}´qB×iii1C´ B¾ ”D·wƒŠR>ëêê†U0}à«««Ë8ÀZÙ½{÷ˆ“Îô £±s/Jk«ŽSsBc÷GŽ‘GK0$‰àp8‡Ã<ñ„±½§§Ç\@U1Œ5MÃçóát:Í…U·ÛM45 Éœsp88N3lV(JxŒø  Ô \ÿ ž¹¼ÜÇó/ŠuuÔ4 ǃËå2cªÜ£‰£ïr¹Ì:äºGOOLÅñw¹\„B!ü~?mmmx<óþÊ«§©©ÉÌW¡î¡ <Á`ÎÄêC 0ó¹è Kšú==¤P5M:³É&ä/ŸÛ¶m£¿¿?ã¤3Û®1Õ¦#… R»gÓû›j#•³ÇëõVLÕ—•̇B!t]Çãñ¤ôÛb3š…7Èl+MË|]¥7©|Qé}ź€pî¹Lšôï¼³›o<‡,ø'O<ñ 6mzXX’ç6ž[>Õ¤s¤ÝDÑ„%AÀ‹Ù'?£&’½Ôœ BN44øÈÍ5üæxuàÀ~ó›ßÞœŽ¯ìy…ƒo>˜á¼|ðË<·ô9¶ïßn+ñyÇb1†M¨*•rè¶ µ`&Ãü¨Üz#¡6Ÿ„ÃaSßñx<¦” ;zxÚµû*›û­B%·±Ê®Jt‘N8l\ÏåÊ<Q±ŸŽä}£ÑäñL"6>¨míîfÛ?þQî§YÆ[·Í9Aé9Ê %5æ¬Ê²çäTD"ZZZèììÄqÃUpéU—a£¬ÝËAÁó¾Ñ ¯‹â2eÊ>^{m€={v—»(E¡\º­ ”ÑmG§ÛÖ××{F‘èÏ@4å–]·$uP§“îŠw3ì@uT²1888ìØh™3gÒÞÞžõ|zbM…òø0ã•—h×§ZÔµ†Àr¹\æKºcÞï÷›á¬ÇÒ±.ªªz(ŸÏ‡ÃáÀï÷›†—@ …'ž¸ÛoßÃìÙ{ùÎÐò2tÿZ/†îÿΗ1ë"ì ²†8Qž)£¥g”.}*¹µÊÕb%f 5£ž¥2ò¨öimm%š‹Y*¬…ÃáÀår‰DLï›¶¶6¶nÝjÞ³½½ŽŽŽÂšÍÉW>Ï:묬;ZZ2{<(ÃØH(ä×륭­H$‚Óé4ÃÌy<ÃH¦ Ò¶¨ø(“0cëõ¦.XXÔ¢„õ|KK2#;$ã¬Xï1†Ù¤µÞÊ@F ƒf°ÎÑZ?ªˆP(wȆ¹s_ÀïOv¨Ë/ŸÉå—¯`ûöåÀgË]…’’|N›6-çØ ¸>aPQ1Ò†×W¦…Ö¶¶63§–0zÎ?ÿ9~ðƒ ñx¾Ág?{<ÜußÙ¸‘¶¶6zzz’ÏóJcìŠ qíŠkùíµ¿åÙÛŸå‘ûaé­K©i®©¨…ne(èíí-wQJJ©t[+*5$‡›ÑápØÜÄ`•ß\9’Æe°þîñ¤Ž­>ŸqNÏš–ºò¬b¡YéîNƘlm5¾£ "Öíÿ`ŒõÖ‡¬V¹­÷W†]7Î[ÁšÔFá÷'õ…h4™4¬¯/yo¥§hZ2‰˜ßŸ:±±–]ÝÛjL ‡‡O„B¡dÝ5Í8¯ëF=ukN=ôPªc|vJ¡Û޶+0º‹êF*\uz7ÏE(2ç›ÝÝ݆,[»\™†‰X\ÚÛkq8.á _øq¹‹RrJ¥Û B©Ý67¹tÛÈ‚ëexø’‡9ï–óL}tÇŽöÒI…ŠeÉ’%#ýòÁ6•L;b±XÁ»|¾á±[Ub#ÇcäÉ7¶k4šL*`Ñx­‹òÖÐW*TW6òIà›n¬H_Uq°?õ©AfÏÞK8æàê8fïlŽÝÌ8±ƒ?ÖFÓ†SñÿoÀ‘4.e+Jú.§"2Öúg2¾Œ·_JÀxæÁ`ÐôPaÄ¢Ñ(@€p8l懱†0³z¸<ùä“c ËQ‰[>Ó’Ç££Z ì{u7_{3Dá–—öñæoåx··ÓÍÎi;™þ.øN lÞÆX0ø£3¹#o 0¨žN4‡á±æÆèÿ_JìÀ?Âoà‡~ÐÉ‘‹½°Y‡m:ÌP• )jÛ°J2ƇƒPb¨¯¯Ï Ç¢¼ªFcxªtt}äÖ= MÑÇÏ Dz!}F‚Z/èc'{§ZùI ’TWÒ‚¾]p8¼óÎyùå"øû¯ç”Ûp×ÍýW]ÅßÏ9ÇÌMfŽ]߆‘à„îì¼}'»®ßų3Ÿeãqi.¶OÝÎ埿ÜÜÄ!”‡Ré¶VB!CÏÍ’ÚÄ$›ùQBã‚2¤XûI¶0š9‰D’žVÚÚŒE~åÑ–¾ÓÉçK;TÜ2ëØ¦ë©Y˜Ó76@ÒÕQ×3Çt¹Œ•]åb5¾¤'šÉÄHñŠF‹UŒ¦l´´×HŸ#hZîX›£)[&”±'N\Ž” Ó¾‹/ûu+ŒñÏL„ÃF—WÆe[­È©(JïQÅ:;;“r[¹ÚXÈÞWȉô,Ë%Ÿ‚ ä¦è²íbp,†þ`?n-¹á|ßWà^¼¸ÜU„¬ØÆ ÒÐÐÀúõëSŽ 䮩bΦ£¼E€üܤ?¶ÅÛçóqÁïOóOðÜùçsþé§ó¡Lnö€1¹T»„Àáp1é#‘ÔxÏðÝõcÀêãr¹8昇9ê¨èú 6múCGÜËÏ~v]Oîâñ{w3§qŽá¹ÓƒáÅ£c,21ŽÖéDMð‰ïº°…‚oEÅd´>'MÓðûýæÎM•`ëÖ­f8)ãÅ_,wJN±åÓáȼƒVyadcï-{Ùvï6®ß=‡Ì?¦éŒ0{ç<ôGc7ž¦Oš‹¼àöýU³ü7ÑÈëOøNø›ß˜”F ×èÏjÝÞ<ã‚cTá=‰Ÿ^ŒŸþ¸1Áà6Î9ßõù’Ù%Ów»Zðz½Ì›7¿ßoUh<ë^Níœ#&_¬@Ù?ã˜Ð;WŠ>~!ü7𜠮¹ã€‚`²¹\fÃLã^)p:\pÁ–d”ž³.å»5xý»\¸s'ǯ[ûóæÍÃëícÒ¤]¬XqwByqÃtÿt¦3€ã~~ï®—™šÉsÓžc¿o?Ñë¢Ü²æV>¸Ò¼§0>”B·MGRr5«Ú ¢’Ë÷õõF‰F£ÇQ%@ÒƒBeÃN7f8IOåéiÅïÏmMVé‘¶Á«ADý´[˜¼îîòdšÎæÆüÏå—SÝ[…ÆG>3aµF£ckú@ À£ëå²^ÆâSsȇðÆÙoÐéO(ÕJgUúf™Q6Î’ß’rÍ;\}­Þ\Öw:¯Üþ2y+ƒmzœ6E0˜¬°Ói\Ïú~ŠD†¯XÏ«ë‚qŸt²ò„›”C>C¡¤WüD2^U2j#³u“­Ú ©Bãæï¡PÈ £¯Ös´´ÑÖßU´kHq¦0C¦ªè'Û¶mãÔSO-÷c))E—Íð¼ñºSaÜ_|áºeÞ"ØÛTš››4ã^ ‹ÅX´hQÞ×ÌfP1wت…ÖL„BÉì‘Hê059ìëƒDn¦yóèììÄå÷ƒ®s¶R¨Tö@ëw½^Cár»3'xI\#%&rS“ñ½±øgáöÛ?d&7TÜpÃRn¸n¸a·ì~?þ± ÷§{ø]ËýÔÏYÎ)ó#úpëà¼Ã8¢ô¿6Œ…æN å]-F÷aìl&ñY hI|®Ã@£ 5`[ÔX¨tÅ2ÎyÓ=YB¡9àZ_ôÏ<óLù 9N[>[Z†{Ž1QT9„LCÀBìÿk/O_qý­{h ´Ç}hˆ€×oôŸLëc 7àJû© 1™®m]sÒ1¼[º?]²áô@§'iŒlK|¦V3…üY‡ÿÓšº=Ñç3·-:4-%›Çã¡©©‰­[·šýR)„JÙ³æSªôÅSõº²SlùÔAû<¸$,4vÀƒÁ¤|&ú^0šJÈ5)S*‡× ÷Ü£óCÇ-tl»ÑH‰‚‹.úß|ó›:_>*È…«á¼ì(þßÉåNsBy•®‚ï¾Ç¾¾}Ü|Ï͆û®¸ýÙÏ·ç}ç߯Xí%¹è&N,%¡º­B­ Ž„ =ët:S ŸN§³ðñÁëͬËZ‘˜?#Sáãt¥RJùÌD[›¡Ï¨éŒÜôÖ…:aaãÛ©YX“Ü´öÄu­(Æû½n¥ÂÍ©ÿL–¥œY½Ó¬ºPÇŸ†íÛAÿ•q-«BEzp8’Fˆô F€1—¶zŸYuk8½hÔØ­ÕÒb\Çê݉$ë“|¸Ã *Vúô9¼š×™Ãêš.—ñÙHd¸ÁR…ØSªÒßÊ€¢ëÆ} µ¾‰P}î‘\«€ñ–O0šÅë5š.–á+«¡Âáp˜Æ§ÓI457-+/X«QCå‡ÃóïH$‚×ë%œxŸ¤_WÍqÕB»úÛãñ˜Æ+*ï­Š8bE×usmG…*v8D"‘”|¬ªìÑh4¥.¡PÈÌ3§t¨`0hÞ×étòÔSOU½A¥è²‚ÀkÆ’ê[ ñ²ìŽm *`ä£X¹r%ô÷÷ÓÞÞ^PR'åä‘z,i©Î™ˆ=4.®¸\è‰h(Âív§ºY[¼N†¡¶%e{9X¯¡> É”R-¼*¥Ðí6þç ×é;î˜L8ü~úúþ€~ÈÁìv~žÔ>É6ÖÓ8y*çÅ÷pô ¯qíA'sØõ÷ó\ý•8ô(MmM¼|öSÎÝÌò×>ÀcÙÅåßœÉë§¼ÎßÏù;6àÍϽ‰»ÇÍšûÖ°rçJ#ÜZ"´Ò߯ù;G­>Šš{jŒ…gµÃÊ‹±Ð"¹¸îNü­ßM™@¤·«úNsU·Ûm°•bËg:÷Þq/·Î¹-¨#jÂf‚øµ¯UˇϹ€¶«®M~©T»â•qp,8H:¼t“4°(Oõ.r'Ž«:ÀÓgôéFŸ÷û M>‘hÆ¡¬ Z8ÌÖÄäJ)ÇTü‚Á ¹ëXå»m^;¢6è ¹)†|úNÿapσ{‰™!ž=évš?-ì]ð&bNŸb’ÌÕ•òoºiˆŸþtùHR•˜>}7Ý4Ï%>æ®~ÿƒÇòÉÃïBŸô7j?t?ÿùÙÌžý?ùÉ’„c«‡gž9˜è±àPꈿ†O꟤Õ×ÊÝŸ½›µ®å“ïù$3B3 û·ï'¾0ÎäÙ“w‘z§ù¿+S'ɰ‡: ¾4HÝ¿êŒÏ8E?¥麎ËéJѵFÚ±Z(ÕØéó%3Ÿ÷™aº»»KçÁ8ÚR¨>J­ÛB2ÅOgçØ¨Üê}êv»P( ]²ÔNÉja¿µ5i ±Ê»ò–PsÖô9ª®ÃÌSp,8ZŽ^qk®#—+¹‘Њכ}N ©áôÚÚ’ iҜΑ“K´zžkþn-ïHÏT%ÈÉ„òäƒÌ/÷Äæ«ÐŽ\Nõ3ò Ã÷Ϫn_)µ©FéWjì·4Ô<ÑšÖj¨PÆeQú©Ú‘nœP^!‡#ÅÖçóár¹Ð4Í 3ªBVkšfnîP÷r¹\´µµá÷ûÍû©9«Ê ÜÓÓc–]UZZZ̼¶ªŽêþ*©u³¡®ëŒóaŸÏ‡Óé¦'…Ãa|>}v¶µµ‡S6•9~øÃ–»;Œ E“Í„Þ÷'Œ?ʳ/ 5­Øõ aâ0)ÇË]+±XŒX,F}}ý¨ÜÆ–/_ÎÚµk‡W6«î¦ë:MMMtwwÂ$ûÎó˜7ožyÖÖÖ1%^3ÖP é¨.J¡MÓÖ–'zV^µñÆ:¦è:<ðÀ|ä# X°`*ýý5tvEÛ¸ñŸûÜ¡¼üò5558aîþÞ%lhxƒ¾Ù=|ïÏ‹9òȃXºô¿™:u?>ú:ŸÿüåtvöñÊ+—qØa ioþñhn}¾‘Ÿò2SÏY͉'ÎäàQ|û=ÿÆÓÓŸ&þÑ8¿îø5WÜrÞò 7͸‰×¼Æ?:‚½WìeÚqÓxýõש¹®†Ã9Œšm5´ä üèÏ/xžù‡Ìgïä½ì~Ïnæ,î®]ìjÛEM ³¯ôˆÃKg¾ÄÜÓ绿4Rƒ”a¥æÞ\p€îîn®h¨ú<*06ùìíí¥··wXò±hÔè–)›Ú#ðõå_gÅ+˜õ¡YIo¥š1Ķ'NfÖ³ÏfÌ™S±4aØT¢‹–Q’†ÃHâÿ‚Ì C¤š¢ðÓ˜å€Û-IiÕªš%¬€Ê¤»Õš¦i¦²ªŒ„Õ®¨d#ª‘±Ègús‰üZ—C÷/IdÂÂavöô‡ ´´‹‰Ü>‘H¤êûO¹P‘@Ô+/H5.ê|‰ÈïphÝ»üep9sæPsó‡¹÷¹+é?èv¨ç­wÿEÓÅOQSó!z{çà÷Ã]w=Ï®]Ó9å”Ã8ôП³lÙ1|ë[u\tÑi¼ôÒÝœ~ú\¼^—©R\uÕrnºô³œuÖY‚ÇœCþýÎ]s.8àÎ9wâ »8éš“ ;{vò´ïi\>{gïeãò\¸éB¶¼¶…÷ñ>öîÝKߊ>&uMâä“OæçGÿœUkW•ûq—œbé¶V¦OOF„µŽ§jÇ§Ê W2”‹ŒTª’ŽŽš››E·M#›n›‰`0é€aq4ÎI86ÿ«ðÃ)hkèØ @ÙHÆå5&ÃiUù®fÑm .*‚›Z*ñûS»MSSæh ÅÂEÀJÜú»5ç™2$X'Ê ‘î‘¡™Þ[,[ö®».é¥ÝÓ~ÿ¡‰¯ÖƒÏ÷!>³|?}:?;ìr~öø¡D"ð•¯\Í'?ù~ýëÉüë_yöÙrÅû€+q»gqËÀ^~´ûug¿Ë/}7«VÌâÿ~›M¯ÂÜ:“Ÿ=6Ÿ·.9›/|ÚìÙü䟻ÿà=|Ƴ—¯N=„s¯þ+ï¼ó‹/=–|w5+¦~‹×?ËŒ•ÇsÏÃïáâÚ<÷Ä“œwØ{¹íÁ»9~ÛMœù÷9Øq0ݶƒ/Ö~‘®—º@‡]çïbçv²wö^þkʘ`W`öï|nºé&Nºñ$~€Ùï̆+JÛìB1ä3SÔ€]]»8xè`fÝ3+åøà·yé¡_Qÿ×™¥LŠN /µaNÃðN±2Ï<®kð'7¼ì‚¨+aìÓ!…nüž¦išaLIl¹ò']wKo¸h4Ê¿]r ïÎK$1w“[w)WfµHýìMAòy/t®‡¶eûñzk’›D].–x|¾a»%ŘR:Òç•éã²ãô¹¸N7~¿@¼ò\{Aÿè:A Y®Y÷ÅZî9äî{k³¶Ìäù#®¦ûÏðÚkOð¯¹9òȃøÞ÷Nãë_ßÁÛoÁé§?E,ö}>ÝÅ•/ÿ÷ttýlšîÞÅî·u| vñݽÏf×KwSç8-§¾Æç´EüàñLaèKѾy>¿¼|=Ï­˜‡ÃŒ7ßóvxró£ì}so¹õ¸PŒ±S¡"ÁlÝ óæ O[ZZÐu½ô¡øÜÙŠôäØjÇ‘8®ˆ#–óîĹ(ÉÍ.N ï΄g”é5¥r›¹H†ò [ΫϦaR=œ‰Ï*µX•YÝÓm¹–UI¯_(qÌc)›Ûòh†ke¥˜ò ÉhY*ÈÁHꫮ봴´˜sN]×éëëˬ÷ª¨¥²ø|EõþWÕQå[ª¶ù§Øò©hm5ä³§ÇèöÅ´Á©P}Ê@†q$›ùË 5ÿGzh#åmÑÓÓc1:;;M#‹òöÈt_u-ëb´õ÷ô{¥‡UXCN[ßGn·;«×k¶p¿ßŸ5ÚG6¯åª›ûW…ÊføFÐ>*Øš[~ËÒ_„­[ …â& í *Å@Ó2ï ‡ÃÆKÞA2üNIUƒ‘¦i455™.ƒ*‘gEaõlQ1]­´´$Wù[YüÒ­ÞÙé§Õ¸7ÿ¯ÐÁñÌ×tœÎ#!ak‰DŒÝáp §óè”A[Ó¦ð_}yï›Çà/!¿æD‘æ3¿ tý=<øàl4 žw¼8•¹Íÿä˜cN!8…ÓNƒšš¸ïp]r2¡oe> ÁOŸ½„»ÿŸ>âD¾úžƒ™^3ƒú÷àå—7pæ‰÷qSÝ^ÜñÑmNf5Õázk|ågC\þÌ?Øüæ1œ?øCf½ì„Ç#‡òÛïNæÊr·s…ý!ph½Àt ^ôuôë\p×Ã>¿â[+p»ÝœZ±‚y†rá|n8ãå±Èg+u€7aÐõa^”ˆ·Ïið®® ³”í@BimiMÃ344Ä÷ÚÛMåzÝ7¿ÉÇvïæ=¯¾ÊïžÞp–Iìv6‹ž0²¨ÝP*„Õ\ 0•CøÛØ =—éÔÆéºµB¨b«‰“ƒÁ`éB ù“6IVªŽš-á ]çÅõëÙÚç㥓/áÂ+.á®»¾Á¡‡ÊCÛÿGß¾ú8±CÙÖÜÌ÷Þy‡/}©Ÿ}ûöqÓY§1sßy¼»ûIùÙÛ,=p i|ÐHK”·¸2^X7=I5†„,×p$¾ãMüT×rXʤê²”Ëgî•0¬ ~{Mïn⃿ú ÝOw³´w)‡¿v8‡s˜ñ™nË}½–û¹1Æ`â˜/qå…š0öìÚµ‹iÓ¦ÞýһħÅ9xè`£|=ð£/P¿¥ž ü ×/zé]Óyéß^BsjlÿïíL›6j_àÄ{N¤wN/'œp!B|ðƒDêìž¹t˜2e ³'Ïæ`ʾ)ìܺ“‡íàÄsN4óTx¿ó'1dÔïÙ˜‡ ƒD"<ÏÈ;q#ý©”v+=i,À £@åÙUK$™öÆŽÆÀ¢tbe$QÞ"Êࡼ=”AD…¸Rù6 sRuE6ƒH6ý;“aÆ.d«c5ò /”»Aø7 ]˜üûµ-[xõSŸbZ¢¯ˆ."TUgPikËì´¡Ü'N§1Éq“uwÏï§^|çÍ7Ó××g& ªŠ˜ßéuèëK†lHW¢Uâ½,8™Æk§S]òxþ×™}ç$óœ5½‹'C#i<þ‡£éü´ñwú®.ë;U)ìšÊ£‹ßaþyGáñ$sý9ɰoÖ¹Ñ(èÛá•_B4¦®(°$áú{(.W³eM•ëä£á¿p2Ï-~‹™ï@àF}¨…ÁÁ3¹²} Ü-k{ô ånð®W;0pÀ“ß|’÷ž÷^νöܔϫ8§U!wù¢x2½«2‰¥ZŒrb,ä¨Ð†A<Óm:t; ¡ž Àÿí£ö*^Œ]Í‘H„)/àØçß ,>! ëÖáîéI „ÏÇþoàÕóÎãøyó¸ç¿~È?öþƒóŸ{ŽY'Àû÷ó¡k®Áçóá÷ûÍS*¯‹Z´™(ʵ u‚ç cK­óÙž”¯5t$“âJ"ú %1¾ßåâý–ÃÖ1¹1ñsêßþÆÛ¿ý-ÞÙ³Í÷ð“ëÖñæŸÿÌAÇ:x8îˆwø#a"¿Œ˜U¯ÃAÍãÛ˜Z[Zéìì4>çôr„p{Œp+Û©é¯á¬g±æù5œóåsƒÜ}÷ÝÜzë­|ù÷yuË«|ÊÁ<3ô úwøïžó0Ô1Äa³㎙wà›ìcïã{Ùr×jþ³†}ûöqþ®ó9õ¦SÑ=:»/ßMýÆz¶oßά=³8í§ ¶ïÛÎÔýSyíû¯ñæ o[£æÈzŸé¥ö+µÜsû="ÜW±ÑõÑ…÷ŠF£´µµ™;Î5]3dJý”WT€¤,†I†Ä-e¡ÊÑ´‘Sê¨}¨ÖqVå©LCŠ2nùðŒ ¹[Gã&ö<· 9á„Ê]„ŠÁy,h×$ÿ~ô…øÆ $‚P TA%Î<@ú|¾¤e_…HCíZüä“\tÅ´¶¡ªŽÝg Òžn!ñûìÖ ¢ºnüí÷Û°²¼èøø+3øaì¹1INF£_8°aÚÁt¶¤V![ÊU\kjEº3•%Ÿ8ˆ+¿ÿ*w|v6.'0ü?\pà ¿æµYª|÷ƒgøÐs à4Ë>ùÀ°ÄÖ*ñœ(™Àh×­U‚Ò(FwT‹_žÄÿ`Ÿ±0æ4LöÃWëììä‰;ž`é9Ká“$wú~- v»“Ý€ÛOÍüRgîÝaøƒ‡›âàÀÂïpÈþ­Lšjl›>{ölq8ðûýœuðYœüûxï†05GÔ0õ¥í¼¤¿jzvwwsχ>„¯µ• CC,¿ê*Öþüç4_w`x»ø|>#dcÂ;ÆêÒ.€át¾Ô6,T† ý¦äPmJCƒiÇǹÇ—rL»é¦aŸ[’øiMþ©þC·ò»\ÃúÍ– /dÿk¯•»šEzä=·-Š1iÒûÐ4Ív:®X×t2;F2VäŠ*kñH  ÷MOŽÙ*DtIEÓê*ƒ»Z¸R oÕ5ÕwT•ô¯VïI5f@2½µjš†Ûí6ŠjqLýTýV}ÇZòWå$‹žå$çIį1ÒSªE5åÝîɦw-kSÎÿ좟f>;ü 9ÓB '¦%þ„µê,Î2¤¹KOOüã˜E"¤ê< f¹gAÔþ¤œÆâàÆmdé—Rûh-ßÞÈ«o¼Š›P(™ÎÒé4ö¡å fàóùÌŸ­2—:CCë„B÷™IÚÕxFñz½Ã6…ɼDF‰úÁ–Üc~4=¢Ž ؘª2¨ƒ™½&ÔŽZsË"£jpœññS»`=«W—»JåÇëMõ\q8Œ‡ ›ÝÚj|6á*rÚI×0kÖI©³ —Ëø;˶3ò(Ñ4àбÇèiWJ:×ß2™ûšmÜDZÈèNdz1¨ä&úe¿ [½ ""ŒðÎ÷¾‡Ëº@‰ðâG?Ê”)SðoßžÌù# êèÑ0úgº¥OÄU8€ÌY6‡S÷Ÿ ›H.¬éÀ2 >M" ‰0&š1Ñ÷;XyÂ}|÷Ç?Nx»ÁáAp0C½Ô^ú)8ÃAãí:ü>3Í­[»·Bœ§< GDh[{?ñ‡ÎÇæÌdå+ñ¸=|úÄS™{Á¼pÐ Þ;ugìßÏÓ_þ2[·š!ÚæÍcÇ#púܹlKd„ì„×¹û“ïçÑh”P(”â‰âóùÌP‚Nú¢¶ú=Û¦”·¯¾š#ª1œc)ø^ß}.\W€û/ÁÇ^„9xgÇ\~òÀÃ|ÿKßgÞôy8t‡ñnö0í´ÓÌp—ŽÂ¸êt:ͰF^¯—eÒNc”'‡:® 3-Nƒ®5ßc±¯›…îînóùnùÀŽ<âÈr?Û¢î¬óN¯7sØéP(D Àáp¤<ãÔ1¶ðx¥¢Ä!V¬`¬(Ï1å–þSW­„ÃaÜn·Ö[y•)ãEkk+n·ÛLæ­6XZÄjî¯Â{+c®2úªïZ¾^¯×4þ*]ÉÞVÝÃáp˜ù[­iÇc„ïóxÌz©ÐQÊ¢­­îîn€é‰§ôC¡½½½åî)C(”\ð‡“ +ºn„TTF-¿ß߯ÑÒ²„`0¹Àïñ$Æõ¬ÆƒÄôÖ4´dЍn=–n€QFU>‚\a”gÑ4 ©`#Ê ‰$*JdÔßÊ¢>ãr%—VÜîÔs*|º ©®>o|‰&.ê;éåRôô$ŸQ¦ˆÁéAO2½GwZÂŽf‰FŸò½;‡Ÿ÷û“åÎtÞÚÆ.WªÜZîl)$ý~hk[ËÓOÏ['€D~6„ëÝ„%Ðë% ó„J`R<—»…°|ùrÖ®5\åM§ •d3ñxœëk®çÎÃî4íÔ.k-5fÊ.·––Ìo{aü …’ÙUöU5ŠÆy‡Ã|›#i8œŒë¥4 ë(ßõxR·‘ä@)IétttÐÜÜ,±¦Óèíí¥··—ö‹Ú ]î^’Û\¼^B¡ápØ ÷¥ë:---²h;Þ(/»Ù°TòdëßaR˜Ô—P¢_‹ÀsÎd¼qn»í6¾øèË]Û¡ÆÎÖY๠\×&Ï…Ãa€é¢Â“Hz¡˜˜cD{{¹‹b;–/_ÎÚ'žBÔ9ŽzCeI†-5¶xúýþÜëöL`×ßþÆš5k8ùÜsÍ…¼P(dæñx< ½ü2§=úhòfÑhrû«Ú+GtÛÌôööòØcOsÏ=Ÿ1WJ$1uÝžžžÜ²êÕ,XôÓ@ …Lϱh4j~NKÕ<[…àSe€P•¡ÁjpP÷S õ}·Ûm<š¦ÑÖÖ†71¿Prʳ#’X©¶æðSm¤Œ ê>J×±_ÒÉv|,¨2eó8IÏÑaźþ!$QÏEy)£@ºA¡¼Q”Ž«ÂD*YMB… ‚2då#âßúÖ÷ùÅ/žàw¿»¿ÜÕ°Ö÷–ïðÇÑ.Ú‡çÁKÌàê},áó„RP ݶjè|X…X)~[Ó¶©Ýj2:LYå¥2P¾¥™üB­Šn¦öTa0²¡i†?©®'ý>==†ÁE2ýË_Êý$lMdûÓ¸¯:˜lS»Å\.—¹«Mv¿ ‘eÒóÏ#Ä ’•Ÿ‡ñÏîn0©]§j‘D×u1¦Â83gÿT.pפ;×F ƒY7èºnæ8 ƒtvvš œéIÖó"ß-›‚PEsÌ< aMÃ$£è°gÖÚ¿ÛÎ’#—pÃâŒ/üøIƒŠ†±0šøédT•ô\ʃÁj LÏ eiii1ÃK©Eéá¥zzz@×ÙüÐCf~•¿HT|>Ÿ©¤‡åË´6£Ã„ á'ŒÁ 1ÍÏ>ÒÒÒbF&‘¹§PlÎ<óL8PîbØ›0xîÕLƒ¥š{Jž(¡©ƒŠsh+IYT3ÃÁ$Pƒhww7~ñBr¡&Gæ@jâàñ°££CRÒçÀñ½»ñþæKÀ\ó˜ŠA ÉüE2x Âø¹wá]g§¬ã„B¡ï™l ÂøóÏ#þÉ·’z,‰˜!mÒ!ÃápÊîs¿ß/ =¡D8íà“aPÓL§“H4jê´8Ý’û{'ÌÀU.xÂeæfoÎAØ1͈ÖâuÆžP…·š`¦bxG‡%=°Þ•¬Û‹>x'±(ä€yÛg\#”¨ÏæÁN&kàÐáP7¼ßŸ48,ÀgZ Fƒ¡Lv@}7k}ß´B8”üsº â=IÔh›d7 oép¬æXÞ{!4êý~ v8à ‹'½èmƒ(Äu˜ªÃÛNx«;yŸ¥¸¶ 溌ÕпEà8/ÔyúôÂKã>µìÓá˜Æ3ïZ€ÇçÁ)šq¯LwÑpÔ—ÙÚzzzÐuP(D$‘^‚PDò•OÀLlÝÓÓc†ÆŠD"„BÆ.l•#PålHÇëõŽé~‚0ѳ|zœDjæÙ  õ#é¸é²š)I¶:–Í`©Î¿8]™ÃƒYס2]Çá0®“+I÷HçóÅ”ËÖ:›-d7¦dB^ÕÃÈkìüZˆ–?ÍV’yÿ”AE6ò •ˆ­ *ëׯ§££ƒÆÆFúûûioogÉ’%9¿sÔoð?ï¼íu@"Ô—ÛÃá`Þ¼yôôôÈxA(ùÈçoê–pÖ%sðù|œwÞy€‡ÙU åO&(ùȧöñ÷£iÉÅŸÚÚZ~úӟʘ)E$Ù„ä¡[o½•H$B8¦³³S&œ‚PDò•O0Œ)f¸‚Ïår‰ž+’¯|ƒAÓëºì»ÞeïƒP…ä+›‘ /àœ}`¬Û~ô£ñR¨XlePéèè`Íš5477300ÀâÅ‹innÎiñÜ[€ûƒ3C(Ãa# Óé¬(cJ,£®®ŽÚÚÚr¥`hhh(w1¤Ef¬ò¹gϦ^ô0î¯Þ@0ä¿ø7ÜpPyƒfµôyÏT/c•Ï7ß|#¬z„«¯¾šÏ}îshšV1c¦bhhˆÁÁÁ1ï*¶#ÕÒ§«©MŠA>º-ÀÅ_ÌÇ>ö1î½÷ÞŠ5¤È˜c?ª©MŠA>ò¹wï^ššš8ï¼ó˜Z[[ñz½D"Ó+ öîînZ[[3Þ'šÈߢr*y½^|>´µµ±jÕ*¾ò•¯pÇw˜‰º³}G]ßú3Ów”·Üxçºë®ãÎ;ï´eÙÆòööv¾øÅ/rûí·çüN<gÿþýå’“¯núë‘8o<†P(Ä£>ÊÐÐmmm¶˜Ú},©„ùÕ„Ãâ6aóæÍñ… ¦»úê«ãëÖ­Ëù½3Ï<3î÷ûã\pA|Μ9ñÛo¿=¾sçÎrWgÌÜvÛmñÍ›7—»EaÙ²eå.¸֣šÚ.ùÈgWWW¼¥¥%¾`Á‚øYg¿à‚ Ê]¼©–>]M}u´mR-m—‹|äóÌ3ÏŒßyçñÙ³gÇ—.]ïîî.w5ò®ûm·ÝVîb…jé«£m“jj»\uÌG·ýÄ'>Ÿ1cF¼¯¯¯ÜU(ˆ‰8æØÑ¶I5µ]6ò‘ÏÍ›7Ç].WüØcoݺ5ÞÙÙYîjäÍDëÓ•€è¶Iò‘ÏeË–Å/½ôÒøÒ¥Kãq¯×ïëë‹wvvÆwîÜïéé‰ÇãñxOOO|çÎñ­[·–»šYë^-úQµôUÑmSë˜në]ôoqí ÅW®¼%^[[k»u[»%•зì.ï¥hcÛx¨ ³¶ÕÕÕ‹År~oß¾}Ü|óÍœ~úéœ}öÙüéOâ _øB¹«3fvíÚE$¡«««ÜE)˜;v°|ùòrc\ê100À[o½ÅüùóË]Ü’’|n۶矞ݻwså•WTl¿¨–>=‘Þ3o¾ù&/¿ü2“&M*wQKN>òyÐA±jÕ*Ž>úh&MšÄ#<Â#Ê]”‚©–÷ÌhÚdÇŽìØ±ƒ3Î8£ÜÅ-)ùê¶[¶l¡¾¾ž»îº«ÜU(ˆ‰4æT £iÑm³Ëç믿ÎöíÛ™={6_ÿú×øÝï~WîªäÅDêÓ•ÂhuÛwß}·ÜE-9ùÈç+¯¼Â믿ξ}ûLý_£JNï¿ÿþ”ŸvDt[û!ºm’|uÛ'_ÝÂndݺGinn¶Ýº­ÝÇ’Jx/ØYÞ_~ùevîÜYtÝÖ6•ÁÁÁaÇFãÎôç?ÿ¹ÜE„ª'ù¼ù曹ùæ›Ë]tA¨zò‘Ïßÿþ÷å.¶ T=ùê¶}}åÊ+‡|äóÊ+¯47 ‚P:ò‘ÏÇ{¬ÜÅ„ª'_ÝöWüU¹‹.Eç r@QWW7ìØHVNAÆ‘OA°/"Ÿ‚`OD6Á¾ˆ| ‚}ù{"²)IlcPihh&ˆvOº#‘OA°/"Ÿ‚`OD6Á¾ˆ| ‚}ù{"²)IlcPinnfppÞÞ^ÀˆÍ‹ÅX´hQ¹‹&‘OA°/"Ÿ‚`OD6Á¾ˆ| ‚}ù{"²)Il“C ½½•+WÒØØH?íííÔÖÖ–»X‚ ò)vFäSì‰È¦ Ø‘OA°/"Ÿ‚`OD6Á`R<—»Vb±±XŒúúzq›!ò)öEäSì‰È¦ Ø‘OA°/"Ÿ‚`OD6Á†AAAAAA»a›*‚ ‚ ‚ ‚ ‚ ‚ vE *‚ ‚ ‚ ‚ ‚ ‚ # AAAAAA„8ø–[n¹¥Ü…È—X,ÆÀÀuuuå.NÎ2ª¤M±XŒºº:jjjF]r×shhˆ×^{mÌe³c½2Õ¥Ð6*wûØ‘Jy&ÕÐöÙä³PùïºTlmd·zT•òL*½íó;G:_-cg¹ê"ÎÀÀ“'O.Z[w?P÷âè£.jYÇ£.£/3%ˆ­¤6ò#“lBeµ}.ù´»n;šq?ù,w½„â|Ú©í ; ­g1ÈW>í^/adJ©›bëØÅbhhˆH$Rݹ¢‰W(ëÖ­‹755Å—-[ojjН[·®ÜEÊÈõ×_Ÿ?~ÊÿÍ›7ºv¨çm·Ý¿í¶Û†ÏU6»Ö+S] i#;´Ý¨¤gR mŸ©O*å¨[¶÷L®6²c=ìN%=“Joû|ÆÎ‘ÎWËØYκ…ñÊ+¯Ä›ššŠÖÖãÝn»í6ó~ .Œ¯Zµªhe¯ºd’Çôz]}õÕñÁÁÁŠl#!?2Éf<^YmŸK>+A·Í6î"Ÿv¨—P8ùȧھ±³Ðz³c•ÏJ¨—›RêGŦØ:v±èïï/™î\éT¬AÅÚÑúûûãóçÏ¿òÊ+å.Ö0–-[6làK=ÊYÏuëÖ™ &™Ÿ\e³[½rÕ¥6ª”~8žTÒ3©ä¶ÏÕ§ •¿ñ¬ÛHï™\md§zT •ôL*µí ;G:_-cg9ê"5!²¶}¥ôéW^y%åúƒƒƒñùóçÇûûû‹RÖR×%›<ªzYë±páÂx0¬¸6ò'“lÆã•Óö#ɧuÛ\ce¡òYî÷ŽPò‘O»´}¡cg¡õ,”BäÓÎõF¦ÔúQ±)¶Ž],¬Ïlpp0¾páÂøÆGU†j—ƒŠÌ¡ÒÛÛK]]ÍÍÍ444ÐÐÐ@ooo¹‹–±¬™ÜÊFSr׳±±‘%K–ÐÐÐ0¦²Û±^#Õ%Ÿ6*wûØ‘J{&•ÜöÙút¡ò7ÞuË%›¹ÚÈnõ¨*í™TjÛç;vŽt¾ZÆN;´‘444ÐØØh«¤>=44$à ÔÖÖR__Ïàà`Áeºd“ÇX,FsssÊñË.»lTõ²[ ù‘I6¡²Ú>—|Ú]·Í5V"Ÿå®—Pò‘O;µ}!cg¡õ,ùʧÝë%ŒL)õ£bSl»Xôöö288ÈŠ+CþÃá0—]vÙˆe˜rpH¹ Ã&ñuuuÄb±r-5ø|ík_£··—ÚÚZÚÛÛY²dɨêQîzªO¦8w¹Ê644d»ze«K!m4R='"åî³c¡ÒÛ>[Ÿ.ô½2Þm˜ë=“«ìVJ ’žI%·}¾cçHçËñÞ)ÅØ9šó‚ý`Ó¦Mlذ•+W¦¯”>ÝÐÐÀ’%KXµjÍÍͦQPMôì®Ûf“Çææf³`Èç¦M›ÌÉo%µ‘0v²É¦:W)mŸK>»ººl­Ûæ÷ ‘O;¼w„ÂÈW>íÔö…Œ…Ö³XåW×M'—|Ú½^ÂÈ”R?*&¥Ð±‹E,£±±‘õë׳iÓ&jkkY²dIQtçj "=T”EÑJ¶]’åDYDW¬XÁ–-[X³f ¦En¤zعž¹ÊVIõ*¤ìT»PIϤZÛ¾Pù³SÝrµQ%ÕÃ.TÒ3©Ö¶/¤ìvªW5ë7Âp†††X¹r%kÖ¬¡¶¶6å\¥õéÚÚZ31iú$°tÛM›6±xñbš››Mg¥µ‘0zrÉ&T^Ûg“ÏjÑmÇ*Ÿ•R/!3…ȧÝÚ>ß±³ÐzŽ'éòY-õ Š­‹RéØÅ"‹™Þ&+V¬ ¾¾žåË—›F‘‰.iPÉd]¶£•«¡¡µkךֻææf-Zd.8ŒT;×3WÙ*©^…´‘êa*é™TkÛ*vª[®6ª¤zØ…Jz&ÕÚö…”ÝNõªfýFN0¤¡¡Á 188ÈÀÀÕ§Õîº 6ÐÞÞN8¦¿¿Ÿ®®®‚ËZî>=44ÄòåËéèè`õêÕ¬^½zÔe³S c#—lBeµ}.ù¬tÝ6_ù´{½„Ü"ŸvjûBÆÎBë9d“ÏJ¯—`P*ý¨X”JÇ.&õõõ¬Y³†ææf3"ÁúõëG,ÃDƒŠ4¨444 kˆÁÁAÛY»”ߊÕê8R=ì\Ï\e«¤zÒFvª‡]¨¤gR­m_¨üÙ©n¹Ú¨’êa*é™TkÛRv;Õ«šõ!3CCCtuuÑÕÕE,cãÆlܸ±¢út,£¾¾>¥¯677›;è*Y·]¶lõõõ„Ãá”ð£)›ÚH;Ùd*«ísÉg¥ë¶ùʧÝë%ŒL¾òi§¶/dì,´žãA6ù¬ôz ¥ÒŠI)tìbÑÜÜ<Ìs¦ÖÌŠÆ8$¾/ MMMñÍ›7Çãñx¼¿¿?ÞÔÔ,w±RX·n]|áÂ…f¹ã .Œ¯[·nÔõ°C=—-[¿í¶Û†ÏU6»Ö+½.…¶‘ÚÇnTÊ3©–¶Ï$Ÿ…Ê_9ê–©#µ‘ëaw*å™TCÛç3vŽt¾ZÆÎrÖE(œeË–™mWNŸÞ¸qcÆ~ ‹RÖñªK6yܼysÊÿW^y¥âÚH(ŒtÙŒÇ+§íG’ÏJÐmsé²ùʧê%‡±Ê§]ھб³ÐzóùU>+¡^BvJ­•‚bêØÅ`pp0ÞÔÔïïï7ÿ®Ä5³RQ‘IéÚÛÛY¹r%ô÷÷ÓÞÞž16e9QÉs/^L}}=ýýý,Y²ÄŒÙ7šzعž¹ÊV)õ*´ìR;Q)ϤšÛ¾Pù³KÝFj£J©‡¨”gRÍm_HÙíR¯j×o„±Q)}ú²Ë.£··—… ÒØØH,£¡¡ÁLNZhYËÕ§c±±XŒåË—§_±bíííÕFBñ©”¶I>+U·-T>íZ/¡8TBÛ:vZÏR2’|Vj½ƒRëGãA¹ËW[[K{{»™FåѬ†5³b0)ÇË]ˆ|QR__ok·¡Óµ)S9Gª‡ë™«l•T¯BÚÈNõ° •ôLªµí •?;Õ-WUR=ìB%=“jmûBÊn§zU³~#ŒJêÓê~uuu444µ¬vîÓ•ÔFBq©¤¶Ï%ŸÕ¤ÛŽ¥l•\/ad*¥í ; ­g9©Öz Iì$gv-_)uçJ¦¢ *‚ ‚ ‚ ‚ ‚ ‚ ãAE&¥AAAAAAOÄ "‚ ‚ ‚ ‚ ‚ ‚0bPAAAAAA1¨‚ ‚ ‚ ‚ ‚ ‚ Œ€T&ôöö244TÖrÄb1:::Êý8¡l ÑÛÛKooo¹‹2 ‘OÁNŒgÌ&v•UA’ä3®Úáý¢ÎÉ;F¨vÆ:µƒ|Šl Å ÒæVvY3²bç¹³ T2•ö~²“âñx¼Ü…JËÐÐ+W®¤¿¿Ÿºº:¹çž{hhh(Kyz{{Y¾|9[¶l)÷£„qgýúõttt˜²XWWÇš5kÊ&éˆ| vb¼úc,Ãår¥Üg``€•+W088H}}=÷Üsµµµå~,‚ XÈw\-çûä#L ò‡Êø/T •2·²Ûš‘ÂîsgA¨d*åýdWÄCe ,Ž=öáp˜E‹™J¢ ãKGG‡p8ÌSO=ECCƒì „2‹ÅèêêbùòåÃÎuttÐÐÐ@8æ±Ç3 ‚`/ì:®æz¿¨rË;F¨vì:•ñ_R±«¬ÚuŒAƒJ™èèè`hhˆŽŽ–/_ÎúõëLÅN/”¡¡!Ö¯_O{{»¹«fÅŠ\vÙeægz{{3Jª Å.S¦2vtt000PªÇ-c¢”}hh(eGÍ¢E‹L÷ål²h-S©ß™Ê+ò)Ø…b÷G> }×i,£··Ç@mm-‡7¦|7ר9²:^ã´0qk.‡N™k\ëuÆãý£{ÇÂHä’+;蔣™‡ŽåZvÿ¡2õårë”…Êj%Œñ‚PlÆ{}f<æ}²ö36Ä R&ºººX¹r%uuu444ðµ¯}Å‹‹Åhhh`ýúõ¬Zµªàûô÷÷ÐÐÐw²½½ÝüLoo/]]]˸jÕ*inn¦···è»†††X¶lÙ°RÊI)û~}}½)‡CCClܸÑTV³É¢*Óx¼3¬ˆ| v¢ýqÉ’%¬]»6eLcAH¹O}}=CCCæ¹\cçxÉêxŒÓÂÄf¬ý¹:e®qu´ŒçûF÷Ž„‘È%WvÐ)G3 vÿ!_²õår딅ʪÝÇxA(ã½>SêyŸ¬ýŒCÊ]€‰Ìe—]Æ’%KL àêÕ«càØ´iSÁ÷PËÅ‹›ÇX½zµyïööö¬ƒe}}½y®¾¾¾$ÛØØhÖ[ìB©úþš5kX¶l™©4××׳aà ·,Âø¼3"Ÿ‚ïþ˜iÑD)–±XÌ|?d“×ñ”ÕRŽÓ‚cëÏåÐ)s«£¡ãÝhÞ1‚0²É•tÊÑÌCGs »ÿ‚¹úr¹uÊbȪ]ÇxA(%ã9çS×,…œÉÚO~ˆ‡JIWÈÒwÂd¢··—N8!ãÿLn¢j·Á¢E‹Ø°a6l ½½}ÔîaÍÍÍæïÙñµLŠeË–100rA° ¥èûCCC¬ZµŠE‹±víZÖ®]Kmmí¨Âñxg(D>;1šþ˜o_/ã)«£yW B!äÓŸ3aÇq*ïý"Vò*a "ŸBõïܪRdÕ®c¼ ”’|uäRÍûdíg|• £¹¹™-[¶Œéó]]]¬X±Â<¶bÅ :::èïï/ŠÀŒµLŠÆÆFš››éèè ¹¹Y‚„Šc¬}ãÆÄb±”]5kÖ¬Áår100P×J‘O¡MÌ·¯g"“¬v•jwj1Ë/•J9ÆÕñ~¿@yÞ1‚P(嘇N„ñ_˜ŒçÜÊŽkFù”«sgAJ5ŸñE *F,3“¥ÓÜÜå*ÇÜYƃRÍûdíg|‘_UNCCõõõƒAóX0¤¶¶Ö¦ÞÞÞ²ºC¯^½š®®.s÷ T+‹-b`` %–fWWµµµ466–]3!ò)؉ñêõõõ477§(¤ëׯgÑ¢Eæßv”WA(7ã-#«`Èn¶É¥•ñïFóŽ„B°Ã5Ò> stream xœä½K¯/9’ä·ÏOq–Y‹:Šƃ± 4Y»Á ÐêÇ,Ô5¨¡¡¯/ÝÌÜyïÉ›Y´ú‘ÿÃË` ƒ?šÓý¿}lŸûdžÿáÿñ/?íøŸÿþ_~Âßûsôíãݶíã¿ÿóOÿòeÚõlŸGëw÷ÏçúøËOã¯çsßò¯ÎÓÏÖÆŸÿò]–¼ˆY¾»âúø~Õ<ßw;>¾ÿñÿÃOûvœŸç]ÊtÊ»½Ÿ/ÊùÅi³à¿”?÷ó³‘å|úçýÔ‚”R bš òŸ¥ ·Ÿý­)¥Ä4ä?³ 4³¿Çýñýñ¤þÛhÅ||üÏ?þåãüÓOÿÃ|>öóãOÿòS<Û}<³Ïó¼F+îçó¾ï?ýå§ÿôóñ‡?î×çyôóçM?{ü<¯Ï«ý|~“úM†ûçû×3ôÏ£_ÿùOÿËOÿÓŸ~ú?¾)WïŸíyËHùåË¡q÷Ï÷Yr©¬g®Ïí)e)¥–•¹TVÍå²ÎQáöÖ²˜²”å\.«ärYÏ9êZ‹Š„¥$åqA™Çã;F=RRjI™KEÕ\.«m£ˆ³–Å”¥,çrY%×ïkçñ¹µ O¶·âбæ1qcLü±£Üv|üéŸÆ?î;÷7ù¶%ÛñÙ¶7òµßWÜùû²]¿–mìÿô±ßhöÿ÷O¿kBüeྛþ~ùêeY§Ä¯ß”oJùÁãÍÁÃÃú#žÚhî|bO»Æmžxbÿa4öó8¶ççÿùÇýyõ£ÿü¿þá#ï9^ÿŸÿ7ÿóÿþ‡}L*çóþü‹~¹{âÖ?ž¨Ú2xîÏv?cR¾ÚçÓ{TåŸPîÕúñóñ¯ö¯¿Œš´OÔ)ýÙÿú_ùë)¿þì_ÿø‡?¶Ñ {¿~ågfUáíÓÞ÷eþÕ¿þ¯¼ú¯_Üò_ÿðÇþùÜo;Ý®ççÿûßßðßüë¾Hû?Ç£õ9Ú^ÆbŒÂŽïåìÏñi¼ž÷³çøììÇç£ÙäÜði¼ÇØ™_Ü÷ù<ßããÙÚ;žßH¹·ñÄ̱ø"aØŽº/ÇÇsíóÂär¯ç3>ŸOÛïñqAJkã«5.j÷ýÙ1™Ýc.xÇìðœg³RƵÏuŽtü5j°u¤Œ¾íH?ö{”q½ã›ÚfÊûy\£Œûiã5D ¦°6î|÷ѤY*pŒržíül(çA¶qÕsŸŸ&èg4cüyöÏ-zF0ÔFʃ¹n¤Œ<׸y?Žè™g4 Æ=}7Ÿy®ýß‘2 žyЈ}ܼc G´æÅUçx'gÂû¹£Ü“½9†öçîì~ e4¡È3¾N'Êí£ gC)£¸ùRw4aW½£6®êhØëGÊ…;Œ”цÑAãªñÍŸmÀMG/=/…çÔGúu!ec1÷6–$ã¢wß?oôî¹m¤Œ¹Í«Ð†Ñ“ãª7ªÜG#öw¯)£Ǽ×x®zG#æÔ‚rnôÅ‹éçÄÝǸyp¯w4â:púU~шw?ÇZi–3q¿(g;⃄ÌOÇݯwÌNH­è÷,gcÉ7.ÇUc½òÎ<£c®)ã7‡ú‹V(g\>;þE+6Ü}LB/ê¼o£Êyæ )£ ÷+ª£Í”XNŽ«îxû6š‘ûŽ‘Ë4£E9³W÷ ͘­Õ¸gÊ=k?òœñ)ï'é{cò)cؼó^#%ê3š±ÍvÝ1Þdzƒ¯Õ«v´ƒå:ǃ›)hEdÙg#öш9n,3gJ›#\t±éûhÄ>cà³YûhÄ}ÆÜ"À­ö7×H˜ƒ¥Å{³ï£ sÚ)ãöÎaxÆðÙ÷ш kšcÞýÀ”ò{ ¨ñððÙÂUꎔcN3OÔù@+0zÞxƣ树rª˜Qùë‰*ß‘g4âæH=˜òâ¥/WÿŒ‹Ð†£¶á@"+óÞŸ1r>á6š°Í;5|²‘2ª>_ìñþÍq:æÝÙ5ÏhB;¢™w”sÎ'ûà%‹„Ñ„9Ü·Ñ”™0ZpÍÿ,£÷œBz¼5{MKˆ/ï5›€¥Do‘g‹{£ Gi7> 㯓µK<øyã#2ŒúïO\µ “1‘#eÿœ·9Ïù*ÏWz‹,¨ÿQê¢þ³…c Œ,£þs>Á„÷úšý{ÆU£þÏ]‹Õïg\4ߨkL—o+9.4`¯9Pÿ:<®6_âòˆ®QÿãŽî}úÏÉÅ#ñŠI¥<ü àŒýĽрùŒæ_£ò÷¬Ïwൟ“êH‰÷í×ö;†jLP÷xcÞ9\:¾ÏóËàw ßg°GÖßç}yïk¾ÓsØM®Ùï{výüXD‡ß£1?|(÷hÁÕêÛ~£{|tÎȃVÔbtÀ¼Õ_ýö>uŠxƯc¦¿JÀw}0ßd|£÷#†Q¼·øFu0>£ Ç|)Ç'5Þ˜½ýXž§ÏÙ£3ÆüøîÎÙ»¿Þ¤ŒËçìíAÑц=Þc>Ì>Ú€Ù5ž÷Ñ„øw4)cMõÞe¬á ½]Ѧ=²Œ̹ÛãŸècieGpÑËÉ k‰öÆEw3šp>åµE\W}+1 ï³VæYî„çÑ÷辘‹¸Q1{bŽ’÷ÜcæÞ6ޤù-¸£˜£ü¦Ô‚ï7fî¼ mØË“zÑ„ú޽ø—^&€cM¸žè‰kŸ)£ ÷UË1Ö2sâvߌü3·污 e tlcñ¾z3|˜cÚÞãkyàÃÓ6]3å霶g4 µ,Õ¯/á1–1iû¾ã ËYûŒù߯˜µ5÷X˜?Wy{Ž1 sÖ~1&‘‚úËUVëFý·^ëoòþÄ'/úßä£.׎ñØbÞÅÎÅÙÀÀ+æm-1Uߣ }–3Áá]RFnN s92>Û{LÜ£œ¹`:Žk‹™{Ìkgä¹Þ˜º1AÏF᣼íËUhEù’ø(ÏÉû˜ßb¤ŒFw™ Ž61'ïñÕë‘2ªz.=Ú‚~Ê“ihDL$O$œ;çï=–]GÃrô)3ñHycþÎ[a¿åô(Á79–õœŸ¼qäoî/Ø{Ø~ô¿Ú“ bÛ¯Ç+ôV¼ÑcÌÈ÷|Ñ'†Åº±¶žCEüwcI=!þëô->æ¿m|ºf/OþÛÌÅ¥ùoÚ¹ð^­{²øo,_ãƒiþÃzvRóßX šÿÆ·)¨Qü·cûQðoÜsbÁ?€uŸy„c™Ùø7f¼€2ãßxh1;ÿÆÛlñߘ\æ¿cö¥áïÀ¸-ðw\WŒ4Ãß1fêY;Ãß1Ha~ GßYᯡcø;Þ_GÃ_Ãp˜ þ0–·ÀAÂ_C“fŠà¯áí·üµ«Ú¸ûE†¿v<ñ>þÚÝb0üµvÅ01ü5ìOLŒüµ‡sá¯O<Ã_4_zÃ_ëglYþPçÙRÃ_Lt~þy áoíõ|økÏ{ †¿«Û€6Â^nBá­hqáïߩΔ€¿’‡ð×М¨á¯Ü‹ð׺Hð׺HŠðwâ |Høkc )øË¦ þÎ1!ÏÍÃòÜD½€?àoEøkhFð×.­®ízâ6üeC »:ó^‚? Ÿ¹Acøk}~pþö»" á¯\Døk_0Ã_»µDü•Ò_ëOô×°a ¤¿öh•+úCMÂô7I,RHÙrÑ_WÎÞýy0ÿZ¿ã{eþ;±aÄ”à? ƒºâ¿6fm’&ùï_Ÿ;òÿ'R&¶Îà¹qãLjÁ´`ÃÌ3› <Ç6œÍŒ,lÑ‘‡ˆ{FWñÖÄ#âèqw2 nt— p4%Ô6S ]A —X2³¡Â@4"^Paàì‚B% ))oxÎÏÒGÁsçn–AolŒà9¦ÓèR $ÄÚÁs,àöH!žmg— Ï1½Çž“@ÝL"Ÿ%v²@ð<¶˜` ‚'>7qAð ‰xXA\;LÁóh„(à‰ù~,<Ç%†­@0o%Äó$PæÐ"%zG$xŽåZ¼"Á6p"¦‘à¹qƒ×$˜s§H.*(Ä»  âI Olß.,ˆF\qYMÙT,ˆaú’' žƒeb›G,ˆ[E#Ä‚¸1½ ó5 âÙDY½s»Xðܵ7*<ÇÚ:·`yâ*DÊ”I<±±%óµ æ¨$ žP¬âV¤Ad™ßKÓ`I! ⪶РçÓ ^ôù Dƒ~GLƒíBu—yƒ}‹rɃ(7ˆƒ™@ Äì8·¯ „ž „Hy#ðl ¢7çÃ5 zf0 žcúÿ¶Ò—¦A\BÒ# ú=4 žm‹GkDGÍWÊ4ˆ«ÞH! fgŠËU¤ÁóÜÈì¢ÁìMÑ 'Ó ¦-J& f’Kip¬DÙtÑàèÎxÇLƒ˜íæØ3 ž¼y•hÐs¤h0Ç•h0Çžh0‡‘h/x<¤ÁÂÊGáA ê+.’I‚fðà9¹ï˜ÿ¿þܧºh‚–Ñ ¨ßj‚˱Ôv€5ÁÛ‡Öñ'$J°ÛÍF£ßD>t¡¡ÆHØÐ°™"$lAp AsYc$L1RHhŠ0¶ñtÞ* +æ%Ü&fb@ä ;61`6I XRÈ€èˆÅ,4»S>VBÀR]"`v0ËâæÏ‚€Y2Ђ¿0ûSˆ”kAÀR00{GXJÌî"e_ð€‰áG!À¼·0‹⢠]`)˜˜ û&É‘ˆrbÓ^X®"æóf;Ïx.ºD˜—ˆ³‹E€¥ {B˜ ä¿¢â¿l¶ø¯Ü›ü—Ý'þËîÿ!e[ŒC}sâ_–"üC ÂÊ“ô‡„Õ64+,úËb %KÀ_æ ûåcûemÅ~ÈCƒM²ßXa¨ û!OàÑ/ úeÇýJ¢Ÿ7€~øÊ†ŸÐ¯\Eô+ ôË‹„~¨1 臔PûH~XÔüpÃüüÉø¹Ù⾬œ¸¯¤û²ºâ¾ìsq_¦ˆû²ûÄ}Y²¸/K÷¹‚¾L õe_‰ú2K@_)•Зý èË!èË«}¸*ÐZÐWòúJB_ÖOÐWòúJB_ö /§#A_ÉÐWªCèsŠ¡Oo™Ï¥˜ùÊEd¾’Ìç4ó•,d¾R0™Wm ó•gñe÷‰ø2 /Kðeò^vƒx/ë+ÞË‹ˆ{™´—ö2¬—5ëùU6ëeUÄzåª`½l³XÏwêiÁgÒóçÞ¤ç%ªI¯ä!éù{úÛJàö…xäYê0…½ÙJ}°¥™'êÃk1_Na߆ü i¾í9bßÄä·=-æ´}‰ÌaÚ¹’äÃÄý°€}ôÛñ(–Ó¸ê^Nî1UëP|_>Šq(Œ¦^gëÐtF?¡n‡ºX‡Ú Uä·c¡úQÀoÍ„2à·ƒ0æ5¿¹æž((ðÛ¡#Éom}ðÃ­çÆžÁo¬N q?Ü{«ä‡,óoŸkgðÛZ̘ü0å,ä‡Ú]‹¨Vü܃Ÿ²˜ûнm± ÅC¹ðCžùh ~è½åT úa9ˆïÂ}îsŸ[`îs1Â>g1ö¡fûÜJsŸûÓÜçfšûÔŸæ>d‰#â¾R ¹¯ä!÷•<ä¾’‡Üç[ ûð(Ûùe‚Ÿ‡´Áÿ²-âŸ;Ôà—Åû²³~Èò,ÚŸúÜÜçÁܗňû²6â¾’‡Ü‡[•û²¯Ä}y+q_)†Ü‡<7mDƒûJ9ä¾Rà¾R ¹/o%îËú üôz›ûJr_f!ö•,Ä>Üé]°ÏÏEÔ—¥úò±ú%AŸK9·»þ»˜/;Ȧ‰&Ôj1_ö‚˜Ïó•¡/ë/ê+åúJR_ÉCê+yH}Ès/'³¢¾¬±Y_ľR ¹¯Cîú/ª_)‡àçIVàWŠ!ùiª6øùɉûòFâ¾°â¾l“À/ŸƒÀ/ûOàWòüJ9¿ìc_)‡àWòøe»~n•¸/Køe)"?÷À/K îË ä¾Ì@ìËÎöå#ö!ϳ`_>Iaß~È~YØ—åû²Õ¾’‡ÜWòü²Ë~%O_©É/«,ò+yH~î_føe1¿’‡à—µøe~%Á¯”Cð+÷"ø•rüJ‚Ÿ³üœÇäç‘dòóÃ2ù•]Ïû—¶õ„ßBx_ø‘õƒ MÙlìéC&<Ÿ&2áÁÀ8DÞ9J»¸&¼z&)Šð·’  ïì±ñ#Â;;¥Þµmtä"ÂÒM‹ïÂÞÕrþï‚«£BxX¼ â]x#ëñ¿ ÆÎ‹©çÕH¾F¼«Ñ ЈwÁ3©JˆwççrþïÏñYœ¿`Ñ1Í: x×Õ¢ÿMx,Kß/×EÌ2á]×KR!ÞkÃÅ÷ RÞåøß É)•‰ñ29KŒwÁ¨`1ó¼0@×/p 4‰ârúï‚K iø)Ê{6ÚŠ›òî~Ñ€T”÷l´97åeŠ0Ïåóžm“¡%1ÏΆŒyå*bòôEÞ»q^?®"çaÍs.fž¨M8ÉyÏFÃtsÊY]¿àî}qýòl|Y z7ŽU3ÏgßeÂIÒËFˆôl±/§ÿ§-fžÙB½lºPïÙxòÀ¨WòõJ9d½ù*/¬‡:ï‹ë”LÃJ²šÆŽd½®_" YïÁáÈBÖCž8o$Ö›ëÑ@F² ¦ÀHÖC9Æd½lƒX/o.Ö+)d½'ŠöòÙö²å¢½g§g-Ó^VP´‡<ÁåÂ=<Ѱï=Ø~Zx÷ c/ñÊ¡Õä|0˜‘/°€/+#à+)¾ìc_VXÀ—ÏJÀW*CàC‡øòÉø²__¶‚À‡žhËé?|MÚ"ôáéu øòY øJ߇)‘À÷ÀëK$ø²/D|è÷¶˜y>Ø1 mȇǹÿ6‹™'nNÓK"_VGÈ—ÃBÈ÷Ÿ–Wõåø_©‘WÅGäËêùž£s´‹ùžƒ6@f>LãP2>ã‘…Ì÷À ¥Š}O“;Qî#[Ø÷á÷ÀÔ‡,m¡¾¹:ˆ;‘úP½s9ü‡Ê¬FžYލÕi õ‡…¨/«,êCyjÔ÷à 9pRnÃVÔWRH}¥:¤>ãtÄ>¤ð¬±W…Ý%©ï9n‚Šú²6¢¾¼ˆÐ—#èCÃy0˜/ûḞ”ýd¾§ÒÉ|n™OåùôxM|ªœÏwð¹ |>܇6¡>\õÆñAßÓºDðaØÐ¿ ÝÙƒ¡|n¶/[)àË» øÆ2[,FâCJf’øP=•>wŒˆ/›-â+7&òùùP*Ö‘ùžÖyPṀ”8)æËrÄ|®Žõ_þ•‹ˆ|x.çrô· 0ˆo‹ÚWJ!ò=íiÍÌ—ÏRÌWRÈ|('¬?ùòo_¶Zć&õåÜ. rñe³…|ù°íAXWý2Qï#Îó^}½ŒIö‰,Õ–œ™"KÎ÷ 4MKÎN`IKNŒÇÉ`¶äì¡Ùó!¥!çCÁφœò”’†œ°9^ 9®„Òóá÷? 9o.#lÈ)PNCNͼ• 9OÕ§!>ª'p¬vœX™®Î^eÕÙ‹K±çõ~ãë¥LÇiÈéRlÉy‘_Ó’&È«%§ÊIKNT™)¶äÄ©©ßÙ”SõISNœMšügSN—cS΋®6Ó”ç©>ª)':,°ÿ9sQ˜¦œXìÏ‚mʉSq>N¦œ£œ…õŽk=Ü8fÚŽNfŸö$лñÅ 3>‚Þ’2A¯¦èÕ”½š WRz5e‚^MЫ)z3¥WÐ)'Mòzõª½%e‚^M Ы)z5%@¯¤ôjJ€^M Ы)ôjB€ÞH¹d¨ Wóè-)ôjJ€^M™ WôJ A¯¦èÕ”½š WSôjJ€^M Ð[RÞpו)z5%@¯¦èÍ”XœŸëƒ!èÕ”½š WSôjJ€^M Ð[R&èÕ…bÈ”½š WRz5%@¯¦LЫ z5%@¯¦èÕ”½%e®Ûkʽš WSôÊc èÕ”½š WSôJɽš W¯ Ð[R&èÕ«ôjJ€^½j‚^I è•‹z5%@¯^ WóéÕ”Iz5!HoI™¤WSõjJ ^M Ô+)D½š¨WªLÔ«yõjž@½š¨WSõ–”wˉz5K ÞLÙêy¾’‡¨Wòõjž`½š¢&¾;Y¯–°W¯ Ø«WíÕ«‚öêU“öj– ½LíeÁ½,F¼W¯ à«y&ðÕ,|5K_½U_½*€¯¦ðÕrøJ ¯”Là)ÜtðÕ<|å^¾šÄWï5ˆ¯ÈW/ ä›ý- Mùjž÷^çr!_M ä+Wùjž@¾R=2_½*˜¯^ÌWS‚ùJúæGÿ¬çùê­ÞÛsùVÏó•<„¾š' ¯Ü<¨¯Ü›ØW‹ ì[R^Îå¾*°o>ò§b_®\ðà ²_2^ÓñŽ•1jïh çóÌ­Æ ;¢<Žªôm–¼ˆY¾»â·ã05ø‰ºjø$§”¨GJcü“ü3£µ~Ç·" RJ-ˆi*ÈfAç€ÑÚÄùg)b&ðzþþ{Ç^jǘ*~-öÒó:r’~"´Òîè4¿’!c/½3è'BÔ< òýè8`Û{®±—¾ƒÛ¶¾FhbY%ª˪Q•TVæRYK„&••Q•TV‰ªä²œËeÕM*Ëq•TTÆUrIÊã‚J|&ùŒªÄ‚jT%¿(Î¥¢–M*+£*©¬UÉe9—ËúwÄ^†̓¯ÿ—±—®Ä^Òàr¾¯c/ýZ¶oc/ýFqߎî_ÉvýZ¶/b/ýžIð—uRûnÊûåË—e™¿~S¾)åo{„Í­ S×Wa‡=zöh‰GT~þù‹ÐD¿ÀGý¢Ì¿îþE࣑øgÿŠÀGÏvtµl$~øh¤ý›ýÃi|tü8ðÑH(ó¾ÏH|ýæ¼S?ÞŽ²gƒ¯HŸài©ƒmA¼Ç §´Ó5Uµ G¦a:˜m,¬Ïp­÷Ììßaw17TB+íÓ^â 6½`Ã@ár1×ôýܰ—ˆ[Á–[ÄØ¥ˆ<˜BÆÍïF‡ãc–8)ºQŽ/c Ñ 'MæÝw4b$ÛΙ°ï!º]4Þi°‡è†ØGs/¤¼!ºMõ½í£3ò‚NÌ„³‡âörW°íhÂÝᳺ tŒÀ 7´=Ü?ý¦C¼¶÷ØSëÛ?mFD^À)G„ xz£qTÃaœyá¾bS°áHñŒ¼ÐÂ\ªá(ýŒ¼Ðéài,àÂv1–æfm;N†ÍQ8”†]FìHöç¿Áw]„^ ƒ›6·#0ÓYFfè9·op¯=C/\t„0æÈƒ±èñ¸µðª9ÊáðkØ:Ø V3öfˆÈÓ6‡!:œ\½³¡t‘ÕàO"Âæð,lƒ[lÎ÷—ÎåJÏà ½7xžasLªÁU/¼ÒCï›ÁtkF©š`ÿêÅ[iplx—8/ ^ gì…*hg ˉ¬ÌyNË Giç–c}sÞŠšC—£ÙŒš£í슚È=í·˜álc¬Ç4GÑKÚµ‡áDïô9Ö®ƒasb¤„áD?öØÚ˜ü"lô±Yë à l ÏWêº5‡ÞãÛ5ËsËw~6G•댚ó1†¯WAsfkîˆ~5Š §Ávïa2á0 í>Âd¢Ãž«GJ˜L`œÅ«}·0™è£OcœÝg˜Ltôàlò}…ÉöbØßw˜LàîWäyÂd"_¨»O“ li÷&™ÆCP"¥MûŠ+êsÚs„Å^ݸ7ðÙª-Š™ïyyOŸ3,&ú³søbv{ž:ŒÙvjnŽ©Öðí~Ù¥‘¥‡ÁD‡#—HyÃ`¢?Oìñ7ÌU˜»ûXÓÏîë{ØK¸”~„¹æÂ‰#%Ì%úuÆj¤a¦ÂÌ9,. ¯wóFs–ë×4–@‹âÅ&âŒûlœbûÆ9õ® 9{è7 ïÙœºŸ; ^™³ÎÏ ñ*Ž=òÄ;‰—qNÞžVèmNÞŠZ×Þ¦°9‡Ö{2lN|Ó íæ\ 7CædhATe’m{;C挈º½a)M%éÜ6†ÌQ«Ï-"®Ì¾›Ò̉¯2æmõæHˆˆ9 çÖÂPÂ¯Ó¹Š˜ÃðBçv1dNÞéfȽÇçö„¡„^Ûsëͳöża(ÑÇ"6 Þ·0”À#oÓ‰òvG|Ä9êÏ=œd?˜Zæ—ðÄG³¶ßîso ™sSh;M%æÈˆ„ëæ¬}èV7cæ@¶ŒbÆÌáûÜ‹˜…lqɦÌplÓNÂsʉs­sÆÖƒ=ñEÞæMΈ'>É{eN|’3º®GžpÙ8»7²\a&‹âNw°¾0Ñ@DÀ˜Ýœ£‡•†ó)oXIàešïß9Vr1awº>ÛfyöæŒ]‹ÏñÖ£‘W\ÒÂNo]‹Æ{Y„œøÇŒ­VãcM{ˆ<¤$Ú³GVÑ‚íLcDÓž½Mšö§&Öû¢={€4í!ÞÍ·"íå³¾àž=R÷Î&ÖêÂ={‚6îÙß¶qOdô™÷ÊÝß»§xÏ>n |öÍlâË¡#è³[WCº" Ï.! }Ù]‚>û5ôÙ¸¡Ï~- }Ž´eè³ûvA†oNèËÞô Þ ÀÔg/ç¦>ÜjZ¿šúìIXÔ—µõÙ囹ÏÞÉM}v6lês,.c_ŽRa_–#ì³cs_¾ ¿œA~XâÅ'Bàg·Ê&?taÌ_D?û‰7ú•,D?ût6úåàúe¡ŸŠý²:B¿¼—Ð/ǶЯ”Cô³§Óžú´œ5þå+@üËyGøg‡øæ?óŸ«cþó“0ÿ•<€®±óδþ5–<@{•5ºw €åV$@T ìšÑ¬@ ÌÀæ"Aä È –< Ál”HЫ“`VX$ˆ`!a)‡HXò Qε0aö»˜0óˆ ³>dÂ’…L˜ã_Lèà4fÂ’‡LèÐ8†Â*‚Â’‡PXò ˽H…ÙÍì³À0—À0»`˜=(2Ä­öÈB4,Å s€ Ñô=nN4´ßú¿!ÜQ*aq“€øl77¥±p/J Œéc[RJ ‰[ <±„áOJ 5Áh’ÛÅRK:½l@¼Îû›ÄëbÐ[â…cQâ…ò)Ðç«Mˆ°UÝ*!âüwl‹¯‡“¼ ƒ}%ÄëŠDd¡hG@äú5ѹMˆå""âõJc"^XÚ.j &¶ïÍ2ñz#› ñz1Í„ˆ•2¹’„ˆså×BˆWç4fB¼w ."Ä{{(É’ïMâªñÞ¸qdBÄR>ƒñÆñÎÐÚHˆè‹+Dˆ×Ëb"ªë2"ʹƒ+Iˆ^±k!B~Ü‹xaC=J&!âQÀº±”„˜E„ˆ‡u†ÜFB¼ú!!„˜O„ˆ‡ãV„ˆ<¡j1•Æ@!bì„p#B¼:?&Ä+ÌÂÃyjQ»E ¼:C¯™Ñ”õH‡Ù{¢Ã W‘ó5–rH‡¸yŒõI‡x!r‹³¾¢C„ÇCæ¸æK%:d7 óÅâ(XL%BCÜ(0^hˆÏÛŠ†°WQ-4D9Ç¢bˆÄvÑÝ@¡‘hˆÇó¡Ðp¶67¢a>l¡!òÄ|(4Ì!L4, ѱÁŠ$Ã+ Ú ¢Q±·$2dï K刅h@`½°0{FX˜W ñ6˜‘ /@ó"f_‰ 1Ű"–;‘ ‘%¸LTXò ‘3±¨0Ÿ“¨ð‚°øQ 0{FPXS ³~‚ÂÂB<§àaAaVYPˆêĨ&â°DL»‚Âü& = …$†BWÙPè K1„B$C¡ß1Ca¹ŠPXnE(,)„BOY†BO»†BC!æÄ" ƒ§^<o(t 1¾®(9 Ð}j(ÄE‹*˜-úY™ 1P¨’ ý„Å„Ù9bBI3¡ß"3!žÌ³hƒžÍ„ÙbÂyô5Ê!zb0f#Ä„¸fB¤© ó9 = ó aö¸ˆ}En#æEÂZ¬›€Ðï¯Ð aŽk¡Ÿ®x0ë'Ä͉ƒ9d‰ƒW„óÖÂÁ|(ÂÁì;á`Žá ?‡ÂÁì^á ;K4蕃i0›-Ìî –<¤AMv†A/[ ƒåV„Á| ‚Áì Á`æ fÉ„A÷¹X0ßK± Râ¢`i¡`)–(XòK Q°¤µ"2 j¥o¼îÕ¢C:S^Îßc‚ —ŠA >ŠˆAî ‚Y= QÉ ¨ïèo„5Jö£ó³D¿“#Z臮³Êè§(iŠöTm°HPB?y4ú寝Ðo|’eÏIôCÀ{Þ‹èçÐðF?HÂúÁKÚ¢ :R³Éo¼VŸÕô<fÉàw^Ò~çEo#?8V‹rE~xÇ÷Åô|¸-'ò+ $?¼ôQ‚ßÙe (ðÑξ€ßÙ¾ÃàwÆ9Õ~'TÈH!ùãÅ}É‚A~H µDä‡rBŒù/ã1™ü€±×/ò»à+òùXÿ~ðƒK¹Jr<Ê…à)î;ßW6–â¾í"‰ûηËv”Ü— ÷eÃÅ}¨Í¹p® Ä÷•’É}nƒ°¯Ü*°ÏžóŒ}¸&†’°€ÇØ'ïzƾó½HÂ>\uTì;û¢ æCó¡.‘…ȇ,±fõákkIQ_VNØwv:Ñ7ö¡;c5.ìƒÁÀ aßÙçÉØwb=ë#ìË1+ìËuE!¾5±ïìŒedìÃÛBcSbÞ¨x(¾³ËbVØ—·ùquL~xÉŽ…üp÷}±åCö¡ÂaÐIêËUÔ—YúP“s>t&E:BòÐæ“З5ôe_ ú²U=MÜèÃÌBR$õɤ¡/{JЗYˆ}ù„}n¤¨/Û$êÃp À‘úr&ö•<Ä>,‘h)JìËFûp«xm…}¥`b_v¨°/ƒ°/«,ìsÃ…}yoaŸçnQŸ{BЗ9È|"«èWÈWªÈ—ZÈ—Ï@ȇRÂ\LȧrM|Eâ» >¿_">¿Ç&>=ŸÚhàóX4ð•b|¥Ÿ{ÓÀç·ÇÀ‡ÏSH~â=,•>*îÝôQdÜÃg9®!íÁE©,h/ !ìaÆœj¶iïÄVk”BÚÃ~6+GÚó÷ß´‡‚á‚öe~pM{¸U[À9]ØÃ ì•Â^)†°‡—‡"!a¯\EØ+Õ!ìÙ9¬a/Kí¹‚‚=tΛ– ¸MEI{Ù¢=¤ÌïŒi¥• ÷J q¯\EÜ+)Ľrq/[ ÜË«Ä{Ygñ^6JÀ—=JàË[ øJÁ>L>!Ç øüòø'ìý|9D |9"|þžšøò.ėňø²:">.M|¸j!¾ì_¹9‰ÏÓ®‰Ï‹_Þ\Ä—-'ñe„|ž½|å"2_>1_¹ŠÌ—íó•êùJÉd¾l– ãâ NRt¬E}ÖºL}çsÈÈ3¨/ûTÔ—¯ž¨·ŠR}ù úr^òàç³–¿!ÄQà1ªy¨ÎÒûàC+c# ü<„QÐ!‚Œ€G¿?ñá9cu%^ìË9@¼œa+e¦SÊF[\%å§Våâ~Œ€·$¬üÁ¥íG!@thË™=&,üÑwzê~r¯.Ä5ûªûA€;I÷Ûd§mÝïäÉT+…QL ›”?L¡wRþà÷£àtE&¤ð³‘Gè} ~ºþ®<8¿Yñ¯Rý:KÕï:¥Jõó}­úÁ8dÁ¿ëÒ1` ðI ¤ðw0Üx y•„¿¶ 5%ü»€OŸÌ¬û²J–îçWźŸ-¬û²YµîwÈpÙºŸûºߡSÇÒý2AºŸŸ­…¿¼•„¿ƒNSøS£,ýµSl)é‘–ƒ€h-9%ýÁ©ëGa@Œ/Q!¥?:òOåÏ£ÂÊŸbXùƒErd‘òwнb*žj¬ü«¶/ì%.G¯˜ä¬û]ôý™ºŸ;غ߸õb Š÷v=x…kÁ‚€x‘EªŽ‹$"ó`ÞGšŸtöÔüMrSóká\3%?!K~í’ 'É^©ƒ#%ù©çRòS̆”ü×!%? ‡”ü\)~ã]îsRü0÷-Ï“çW j=fŒ5`eÀ“îÊÍ€ç.äâ¿•OúðNä¾q"à^•“ÃxÑiB >h‘ExÑ t" 6’o:ÍM¼éž90ï%¼é‚:0ï%¼xn§  P×hQÕ ¨®İ]Ðaôƒ3úÁ];#àµÈ}è†ÅüO- ÜøwÑst⟠Ïÿ.º^Oü»x=ñÏÏIø§‘ ü»ÂÑzÒßMÊI×#Ðý¹gL7½h›þÜ ¦¿LýÝtlô§Úþ`‹fœ‚¿›N”þܦ¿+|$üùáþÜ醿k%¿›þ§“üÜ"?y*JòÓ~•ÁpÉ}Z9'÷i9¹¯oŸß`ŸaQاíÀ‚}Ú2öM œ°Ïã*±ÏLgì;•‡ØS¡J}Z%õ©•¦>õƒ¡Ï;éø‰Oí‹ØFEÞ›«–¢ïí{9ø÷ŒEª‹ìð2ðÉáŠdoÛ"¡]ßã´È®owø6ØÁ—!Œ`WRì:f꽞û뎪Fž»Ž %Â»Ž©ù-âÞ(Fv}Ïâ¨`×áyï¬V§jÖY ²ë˜Sƒ3ƒìF1tµ,²ë8bÌC²ëp® ’]?n"Úu8êÉ¿“ã·:yådn²]‡#@º^ ¶ë &š‡Ûu8Ê'L¸ëðqͳ€wã*ùü Üux$¹M¸ëøv°:w^þbAM¸ë0ðUá®Ãé`«'ÿ:Œ™£:„»± ¤©¾èn6ôª'ÿF;5 Ñ»<Äñ^8áƒP2ÞûÐI½¯¤òÞ‡îV yïÃ0@†<\µ*}/|3„%)Ã-Î.Šòð>ÄË(ÌË{ ó²WÌÃ͉pļ÷a¨,cªó.žðzø-ÌËaJ~Òƒ÷ÝÕãK–,ÒË2Qïí²#êe…zYg±^v*aïí ÈdØ+·"íùsiÚÿ< í½ð6ÅC~{og0#áž 6î•,Ä=,x¤¸WnNÜà "ÖÆÂ=l$ÇŠU¸Ç­}9ö‡–Se#ïáÙœ ïÁË}€x[ÉS‚÷òîâ=4=Pˆ¼÷¾]ž`È{HÙO¤´ |}ÃÚo1ñD÷Ü‹ïxÎ; ò‹NÙ|òÍbžEôË›ùêU|õª@¾‘"Pòa€¼Ë±¿7°.‘o–sTä›÷ŠçGäës®ùàœ7´B"ßÈÃø#á…ÄÐóÁ'Ä*û•2†N½˜Ãë¨Ì7›¹ûëðkýT+ÏZarîu-Ügcæ>¸mzªìWîEî+ÝÜ7:_#r_GHŒ¿™`Eðë[¬ÓüJ‡üf³Î~¥‹ ~£˜MŽVüf ðø®D~õª ¿ïñ8E~˜eúrìO‚eýÆU²L$úÍÆ,Cô› s¤¿RÒ_錠¿·äWèuA³—ã%þ•^&ÿÕb‚ÿfCiTü7R¾ÀŽx%wÕýf³bXk}€ýxdÉIì=tg§ÞõØ_é°ÀYØ¥!–[‘gi"X*Hœ}Ú«ð7S(ü9ØQöf}ªmgcÍlÛùЗño¬•¥ÑéXÈ3t<âB>Rÿn8 ŽGüÛ6šJÙS+ó_?yäÃøw=‰ÛÆý-ëzø8óp u=|óöz¨¯oMÆj¿í§êzÓãpõï9(r“ãMâ¼ÒÓYŒðïºøýþm—äâß¾Ñ˦èè¹W¿/}Ça¼z¨¯#€M,8E;$›jÛÙquè¢?\M²#ý!‚ÍN­/èo¿åþÐô·<Êdú;O9l!ý¡ôòBúÛû»ø}éøÎ…ä"úCàº%ýí\=˜þða $#ýã Ó;‹èïÒèýÁÿ>AŽô‡«²I#E¨BüëX4ìUÛq*…ø·C[{Oâ‚ UÛCŸœÿfœ PåˆHyóNG¬7þ9¹ñÏ1®… hmúsøjÓÆæ¾Xxî‡Îl‰þö¶qu)úËÑ_I!ýíMKEÈCf$ý!ϳxùDÄÒùo§e&áOÞKUE~¥$¿r ’_ÞB䇔0Ÿù•’ß Ý´8|AJd!ø!!ÖÜ¿ž”B•#ø!%vX~ nîÛ›ª‘ûJ¹)}1ïDJ˜¬‹û°!ÕèÜ%¸)Ákľ½é±ooÚ ö!åZ¼½`3}%…ØWRˆ}sÆ[¼½ äEÚƒ®Î}¸æ¥1çF§]òÑ%èC<Ž{ñõRòú'Þ/B_I ô•‹}ȳ-¾^Ê­}˜Š·EÛÛ#2\>\E,„>ä9_/HY˜Ç»-æ+“ùÊÍÉ|û˜w÷Ê|¥2²œ‹«ä #òe‰Ï¥˜ø|#_I ñ!åY,<}k_¹ŠÄWòøJ9$¾ý¼Ä’$¾Ì#â+)$>\µ-Ž^²R‚æ|墾ýÔA;_^CÞ+·¦À—Yˆ{Hè‹§ûœŸ/‘¾‡WSBßË;KßËêJß+WöäϬ‡ ~”÷J1”÷òTÖ+yÄz(§WÖ+%O}Ïwê•'êe’Þ\&-ž™…â^)…ú^© ¾¼ˆœ—YÄy¸“Լ༼·ô½’B}¯¤„¾WŠ¡¾WR(ð• |H ’ÀWR(ð•”ø² |ûI¤ u¯d º—eHÞÓ%ÔöJž2ïô'e½’Ÿ²žÇ"ë•*{™"e)±ùBe¯d¡²‡¸K‹²‡,}1éÌKÚË—^Ò^)˜Ú^)‡Ú^I¡¶WêG´Ë©í±û(ìe]¤ìå}¤ì¡ kRÚ+¥RÛ+) £«J4£«ÅɼŒ¯ñì÷4·Í@ÊãØDßfÉ‹˜å»+~;šÑ5ÔhFN)„”ƈ"ùgƺçRÿ-9¥¤4”–‚šQ ² ¥Ô‚˜¦‚üçß;²ÜÌ ë—‘¾ˆK‹ÎßÊð»#}?R.xÝ»ÖÈF_ súø«¹TVÆ,RY5f‘ÊÊ\*«ærYŽYä²JÌ"—å\.«ärYŠZä¢2j‘KR”y<þ³HÕ˜E~iœKEÕ\.Ë1‹\V‰Y䲜Ëeý;"áÓp".Þ—‘žD6únì|Ùèײ}Ùè7ŠûvtÿJ¶ë‡{lô{&Ä_Ö î»éï—/_–eJüúMù¦”¿9²,êLc_D6º»"_ÿì_?Œl4þý¿~ñ+ÿõ÷F6Zoô×/ÊüëW‘Îÿï#]p;ã”nsW“¯ßŒSzÆ ¼ ^_g˜ÒNòÂö&¬â±+ù0%¬â±+77¯ÂÑ ]=wï¯s ³xÄhžö×à‡ù1Gpåi.p%zøf“·Ék¬‚§ŸM˜ÉÎêœçtï<½(Ïí€ fó€¶"Þ™rÓgò¨ÖW=abÕé<-›Á §ïæ »+v]/mžìd2xÁ:ÿíÅ(óš¶Ùô¨2K¹ž‹æyº ¦¡Ó(~ÛÂâýºÎ4Šß¢Ü‹ç¢yŒf¬=i?fݹkwÁ1ÖÅóß=òtZÅÇ.àL¡UüIµíº^šÅ»8{‹±òuïr‡Åà ãÞ<!k‘ÒhUõ¬ñ}Ê#}\>Õè1.VVØâž†ñò*7þ‰†ñrótÝ–ñ!›FŠ\bÑøC.±èhîÂ:dZÆ_q^ft ãÏ#öX¯ç¨6®§Ñ6þnŸQÄIÓx9»ž‹¦ñnÒsÓ4^®pÆ™ÆSˆ¼ž.ŸXô;7Rhïʽ²Œ×E}£e¼6tÃÿËœ½ÝÅp¦^Üpχš®8Ìqãë<5ùÙá38gï,æ¥;,Þ¹Ïî°t^æÆÉ¾˜½)KÞçAwXš(î³ëì}Oà»öŒnŸzâè†ùÿœ½õæósúöPŸgs|˜çÜÝhµzãË»#nÒnmËCAæÜ}„UíòæÔ}ì!àÞðš:§nXºñºëA˜Þ‹ž»öÔtKzÖöÐ[yø4DZ&õ>Í{4j. n|™÷^ Ƨùxêc£:&o©¼Ç ‰ÉÛãê>é &—qÑÞ°xZfð5a¹Ýìy¨‰3êH¡7,#ºïNoX.æ¥3¬ƒ¦uÚ˜o÷\Üø.ïË€}zÃÒÁ§ûiô†¥Ãe÷XÊqòÖ\8~òXÓBÑýÜô†•÷z–øóЖŽjÝֳѣ™y6:Ú‰oóvÖfáÛy.tzþü-Ÿ›)ŸÆ™Ô“lluðÔßW]qîmì‹?Á׿/Þ‘ °¿gÙÌ™`™‹)#àNó@!àŒ‚ËJ"àF±'ÞXÀËÞïM3à=Wka$@<þ àvРŸOH4&@X¼´H!:r’ p{^ÆèÈI&ÀÏ'Ê!î»`DHc•‚€Svû(ˆÇëS1à~©b@Ä[Ú‚ ƒñ$Ÿ…AòG2 ¬;ž…±ŠŠÞÂä%–Âb@¬«‚É€X/ x€5„IÈ‚€Xg²¡¼-ˆøÆm!@ØËÄ0bUÃDˆ]€±8{£` LkˆsÀiZ)$@çTö8ô“‹ÀÙ ÀƒHIúƒ †3ÈŽôw¼4û4ýÏÍ{þì]Þð7çGÒ¢cD‹EXGƆ…è'Fî 4ÒŸbbþ`ªUø;:MtMŽí`úC¹-îDúsDãtÎÆ†Êiti/ü;àý-àŽüçð À)²Î† ‡¦µÀ¶Ñ£Ð1I €È3 €8`³ ìŸXy¦¼¯{!Àv2¬ ÐQ@D€Ðkç´aDT±;."âAÌ‚M€ˆLŒ%l!JDè„y‚Ñr^DDÄ–=nE„…á)$Àv0Fœ!¡¡ÎH!f•8môFB wÑ ØÉo» ÐÃÀeú’ ÞŸ3¶“†‚@ÄJ»Ì[ —Sº!Á'z¤Q¾@ ¡qó;èØ [ÇU¤@tü´e2"òØKæS¨ºÝ7f7‹1œHty+a`ktðo t3c`ÉC ýrˆç.{ä DP±è q`kŒ™iÄyÅâÀ’‡èpæ@4"ž„8•ˆþ¢œâ@T+Ö­â@4&V»âÀv1h¹90ûTØ®=Dáà@<Î]BAGG2 ÷C( wAÍ‚è®9ášQ™#x‘0ˆ{µÀC ƒ“s :šaݵG9„AÜ+Þ5Á`N„A‡è2 ¢'ŽH! bèó óæ¢AÄn{â*Ò`JÒ`ö pÐꌃ¸UÌ‹ÂAŽ3æK#œ+ÊÙ;âA„9‰×H<ˆG>¿æAÇw3:y0Ÿ„x÷Œò`‹þOtXBó`ö²xÐî‘̃˜ÐâVâA”/¨xÐ1ó̃9œ„Žïf tT8¡ƒ¥™ó}:RŒ‰pšE9A„¥¡ãá ³:BÂNBBG4f q«˜„„Ù*!¡0 ýÑHèð|FÂËBBÇn3º#¡Ÿ¨‘³Þ F$ÄÓ â^$@2¡ª˜Ð 5¢Yóël&t\/3a;öxÓ …YeA¡»GPèán(ôp7z| ýÚ =Í ñ@ið»#¥2xÏ3£• _>Óp1R( Âþ")†4xìtji+í½‚á\iß‹4ˆ¯"óH”¿kKƒ° I`xî´$MiðdXnƒ¡]b§4¸7Á£¥AÚIiðˆÚ) ÊI¶¹Ð®¡SÔžAjƒÁ?Pï-¬‹­ ÒG ƒô–e&´X3¡ý‹¦.¸_ß0¡½‰Š íg5uAmÒ]°‡Ö)&„ês•ål(eÁGñS”›µ”%d¤,˜y$ n¯J–,hÑDz œ€¥.¨Mvê‚Vì â8VÈ€N).‘0¨£] ƒ–g- jW8…AzKaÐÅX”Ÿ½å­-…AœYØ{F1`% Êã¸ÙÐîºSÜîP}̆ö€m6„Ó¼E´?7¡ajÙBCË7FCŒóꜴÁ‹†°ôŒ®°68z4F¤ÐÐÞKŒ†Ó>4òHôsʧˆÉp¾ÔÁœ’åÎd(§"C︥4¨]9ƒ¡=  í@>¥A 7ƒ¡_<¡ §4¸sëÅ`¨çb.´ó­nŠ ³`qaÖÏâ …Jq¡=¿› }skƒr˜Ú ‚nEiƒ[lZ´JaiSÔã6Ú!ž¡0[ (Ôã.Âà" Úw¼ÐÃ>eÁC" ´»h¡Ý¼YPû嬜€Ð‰Ô%[Š=¤Íƒ8šÅZ”ZF´?ã`¶)eAÉÂÁ’‡8ˆIâ^eÁ‰ƒ9Ê…ƒ%E²`Ê‹ÄAÇ*HYP^ýY0ˆÂ² Tü€)ç Sl´(Ø¥ÝQ0n-QBÑcêIIPÊlJ‚ú˜þl»”’ nýñ’øŽ Á?&¾“á ñ”D|8/«QßÝ’À‡@èak)[З^#øË×À§èéi гM‘Bàé§wQ 7 ø¶‹D"àkã[~­À·ó4M߯C§I|ô+ñ  |æO1߉-ý°ýóÙ‚”È×èåÅÌgÿ }Ø9]¡ï¢ÿC_¹JÐg“WAßM߆>»oOè»Ïo n×Í|i&+æs@3Ÿ9VÈ—ÖB>G[0òÙ¡‘Ï~â|òÆoâS´Š¾ä\_ò²€Ï®ï |v}oàK¦ð9x€Ï^ÿ |%‰/Kñ9,†‰/ë#â+W‘ølÈ"âSÔ‰>…D0ðewøä)1Áàâ*Ÿ”ˆÏYL|‹Å4nõëÖ rähàËgeàÓª»})øý¥Ÿó˜øôôD|޲-2…|Z ù^¥ŸÖêI|§¨Ä—¼aâó*[ÄÇÀY>Sv>_Sˆ/–€"¾Â€2ÕS!>n˜ø|s[ƒŠÃ’÷ľ>ïû,À‹lòØé<Ïâíù(è·?²75úIÖú‡d¡ÌÍxšðR€Ô‹èbô³‘šÐϦF?LÞ±4úµ—³ôãa<¢æØ¶žÑ?ùÐ7øÝ®QüõOäç¡lò{6ú÷Ìc€Vå| ðÔsù=íÐùB|xŒRÇ/ºë3ù=8¤ÌFòÃWŒø¥c€ðñQÐo´¶›Rûë:Õ¾÷ùFí{îø0™üîí•Á'Éž0ÂBRä÷ܯì*I~7`;ÐŽèwãH@…‚wžK§*Å~7¼ñ-bßXMq@ˆýð‘ˆA#ö»¯–„b¿<óì×OÇÂ~÷C?[f¿ûy¾9Ø7ýpUXºŠýnDðŽ«È~³¼Ê~w§ÏüiÅ+%ø{^îþr@ þà$ä|Áßóêáïîô&eø»ßM‡úÏ«s©‚¿ûÕ‘àožÁ_Ž>Ï£C}¤¿gÓV‰èï4åþ:¼:.rßsº;éïiÚŸýõ£Q|ý!O¤þà6lÑûz;¤Ü‘þ2 áKBáË€}‘ûž“¹‚?$ð”鯟»À ?xH „$üa°£‘ýúI[³®¡¥(Ùïü³Ð¯Ÿôefö{îS†¢„¿ç¦ŸÃ_‡ÇÃÀAÂß‹…ýž.•“ì×ï9ˆ~¸$¬ä„~ÏsÐFOè×á0´;¢ßÓŸýð²ÆBì‡ñåýò’_¹†ä×qö–â^ ßóê,ŒØïy}vð×áH<È.àãž*á/µ<Â_¿e^&ø³÷OÃ_ßtÜMðW® øÃºu1ÿÄÚbþ‰.ß½//"ý9Aü×áãö£à_ß^æ#þù…3þu<ìÿpÕ¾à_ßù2þ¡z,™ø‡Ž üþë›MJÉý–]³ø/‹ÿ!%pJü×·…þž‹æH¦¿öÃÏœDù„Y[áZtÒ4ð/› ü뛎Bÿà¶/„¸ˆúˆ<)Hü+WÿP៿⿎ÏX ptÍ7ç³~À~ÑõšN ‰„$Àû„…ý¾‹ñ¥{ÄÍc{BØãõþá#In#þa\Ť¿œŠH}“™£è/_&Ñ_?o%$ýá+,Eøë›%;Â_ÞIð—OEô—7ý¡ËiLJüËþe…˜Ë©üý•‚ƒþòýáët/‡s6þ¡-<½Güc‹ýòÝ&üáÁ†M&Ùϳ«Ð¯”Iôëû+qè‡÷¶-:®âE¢_‡µJÑϳ¿ÙÕ»–ó.Çì7Ý`.çÿ€§-Æž·óT©/ºÁä'4%ùù˜ü°ò:"É+ÁEè›Kà ´ ¿Au$¿~ðt™ÉSÏ~z“ ~hó¢óu÷!å‹àF xm~üðøÃŽu®o‡žéû5kN8z áN€×ÂUs¼£Ëq…Žΰy&¼=y(îÁÛo9zQ´$º•O‰Ïn‰Ï½n‰ÏãÖßÉÈ')ñ5F5)uV)|y$¾¼“$¾;;¥Â×¼%¾vû¨ðY–ÂwrE— ÞÅH‘§ð„©ðaD-×^zöN‰ïˆÙ,¾­‰uÚï¥ÛîTøzxL…o»eªÓ~X°G)|2O…oc„#Ÿö{OÉlRøÕ:%>|°×Ó~ºUJ|»ÖH>í÷ž:XÈÓ~š`RãÛIÒ©ña ·Òi¿—ÖSãÓ$”Vn•Oû«žôÊU:í7¾Z¡“ø´Ÿkh•/¯Òi?l"ðlOû¹¡Rù¶W²¤T¾mØõZ¿vrù’ytÚï¥ø<í‡Ù;´A²îÐno£ô<í÷Ê#o§ûë<í÷2$Cžöë— @I{rqˆK§ý ,Rúb[h_ÄEéÃG“*ûåE„½º]œÛãa?½FyØO[”¦=oQæa?¼Ë‘¢Ã~²I½o£Sô´îÜ´÷àÃ~Àå8qGàÃÃêëa?¨ZAf:ìç‡e½ok:F¨Ã~ïC9"û½Œ¶`àC5ßøÐÇb݉­â¶_Þȇý<–|Ø§Å¼Óæ=©øm›(P‡ýÜLK~·>ìçaáÃ~/Ã6Xò۸͖‡ýÞ®ã:ìçΰ䷽¤–ü6îæa¿Î}IöÃD¨uýü€}ØÏSE?&‹~(¢`ösÉVýü6ú°Ÿß=öë© /;C܇{û°ŸŸŸe¿¼W€_ŽIöË‹tØŽãÌ û= &’‡ýü‚Zöó ´ìçáÃ~~èÖý6òA žÝ}ØÏ3®ûåÝuØO_Cö{¯8ènôó*Ô至—û¹¡_¾ú>ìçïšûùa ÿ² >ìçW‡ýüÿå'Ô‡ý<7ù°Ÿ¾#yØOÏ/ûÉJ/û鞇ýÔ=yØOSùrØïâãa?!LöÓQÈ<ì§ã®yØ/Ï ê°‚ZÄ)=öƒ±ÙrØÏ5öa¿Q¿¨û=¢ZöÓ’‡ýi(ûé\a‰oTô½ÕÇ'à&d:ÛuÊu„ÙŽûó ߹ɨÐï`œS£_.Í…~217ùÝ}ˆü p¬çø07„p#ò{p.nqñ‰¹!¬ÐD~½ÝŸôçà‡°m±êìí¡Þ"ðó¦˜Á›Á‹QgX…ûÂÔ܇ø©×r’Æ´Tî‚ûÕ1¼aˆûÞ‹®ÛÌ}nAX$÷a}»‘ñ]#¹0¶Ê}x]ée“Ü—‹û4Ñ܇€ÔÜÈ}X’¿Ëa>ÇÏ3÷½ÝFü2•ÁïíW¼¿ ,zGà‡rÞÅŋëü­ëN}ÏÁ" ~Ù[¿_A×r˜6ÍWõò9#ŒMü0+-à—1Ú ~å^?4“v›?Ç5ø¡™÷~ˆ²øeWü Õä瘜&¿÷¤Å…ÑïÅ@^}:^ªÑÏ8…~oãJÄè÷R?…~^ÏbÜ™úÁ'æýöC6Öb?D”ÚO/ˆ(õ,úžcL™ý@Êì‡rÞ…ýœÇìç Sb?ĘZ½ìÇ#ˆ#ú!å\¬;K¢ŸSýPðbÝéPNF?Ǫ2ú•bˆ~÷´œçË‚ŸB`™û2ØçXÆ>G®2ö!ϳ`ŸcYûö¦°¯ä ì+ûÊØçVƾ’‡Ø—Õö•«ˆ}Ž`eìCJ_Ì;°Šú"±¯ä!ö9w,ØçÀW¾’@ì+)Ä>Ľ¢%¹ÏѲÌ}%¹/oNîs@-s.âBr_Ma¬œ‘B2ä¾L÷•rŸÃn™ûšËÜWòûšËÜWRÈ}ÖeîS°®À¾òïľüwyûtUìíÓ½'êÃE÷r¦Ï!ÀL}%…Ôç¨`¦¾’Bê+)¤¾šÂp9Š%fê+y‚ú&ÌÔ‡”ÕÐÓÁÅL}å*R_I!õ9˜˜¨/k#ê+“úÊÍEÌÙ>¡/^…Ìa‚/ï,äsl1#_ÞHÈ—Åœ ›£„KQs´ó$àË,ƒæ8y/stÍQi/ǯh/KíeG‰öÍ´çˆj¦½lµh¯ä¹3g—‰)i¯äy3Ç÷ê ›³ËîóUØeí•Ò^^%Ú+yH{Žº&ÚË–‹öÊE¤½R0i/[%Ú+)¤½RiÏ)¦=WÇ´§ÇgØs'ö܆½’‡°Wn°—å’õ<ˆÍz岞¿€f=w—Y/Ë!ëùM5ëe…Åz¥²^I!ë•«:FyJÌ£AM"2òÆ çg ñ¡<Ž`ôm–¼ˆY¾»â·cuø^lg)Ó)%ÂÒk$ÿÌC½ßß„*rJ-ˆi*ÈfAï¾–K+•R R Ê?ÿÞ1 ª¿èŽßó(>Ø+Øþ軼?ˆ„ô«±c¾JÏsÂô¢‹ùjèÌ%ê8‰%•`GQRu¤’2KZÂ&©¤ uÄ’J¤#—äL*©MRIuÄ‚2Ò‘ËQS&éÅÈ0GQLrä—É™XÐ0I%e#–Tb¹$gRIÿŽ@HÓÔ÷~ÿÿé÷Ì’¿¬³Þwsâ/_¾ Ë<ùõëñM)s $lX\ÿ0Hçv—_ö¯ß Y¿ ƒ´–Ùýë»0Hë-# ÒXÇ6¶ ‰ß†ABÚ¿ù×?|‘¦0HÇûã0HãE‹m¶-ÂXéÕÃÔsÑ@eÆÏï;öÇçà¹Ã2¤ÿ¹+;RèFY§ýŸN7ÊØŸ‹‚ç¥å—{ÓòkîåÜÜ C:úP»êa!´hOoa_aÿ}O?c› ®ïb½ÑcOiz±‹“%ýŠm6»|ðœN8Ÿ]wn:á”Ûò>]?âÏ7¶Ùr“ýݾÂrßóî±ÍÅ!è½GØWä†>Œ‘¦}…”žç=éO9ó„ËÎ)f‡½÷¢?å,ù¦}…´»±Ò§}…4ÞØ”kE>›€Ó¾è‹”Ž“-{\4W®s{rX쌒Ûá…|:TVCûÖha¡[uì¡ÏÏÎà¿#…Ç[}»ÂÂbgð˾ݴ°8Z€ó`ZXÀ[KܪËÂ"¬'úöò5v¾fʾÑÀbgœÍ¾ï´°ÇÌ‚±O¶óVÑì¿„…{ÇZsÊrltÄ露Üe;&Øi`Wo‘å–•ë¾?q„Z&!}ï4°À¶[Ôæ¥v|f1ÇÆ3ÔØA›µÁK< ,dD5^ž¡v«Žg¨á:$²œ4°À–Ô)4°ÀvåL¸x†>IfÂMó 7®¾§yÅAÏífmó,¼qDž—æ_ŽçÕS“s£àoû½‹ý@oÍ+ü|[‹}¶| íä!j·jž\Š!pFÂEó ?Í©=upAIšæ;c÷öÖé7K65ŠÔ³ŒQèáôPO¶4Ó¼l¤i\áA{_±Í–Ãdr\µM÷Cã -š“¸[‰S>×^¦Ú>H=Œ+\ò@á0®Ð«øÐ1»àN« ßúåaj]ôn*TßrÜœÀw†Á~·p½›t4{ó ~DSËääÝÎ8L­ö»]t ŒµAd¹iS‘å>[Ñ3…¡wM¥Z†°F˜ª¡4BmdP›E”%¦lh‘ÐZžEBÉ)J\ùH˜y¬Jx°JèÍ`©„ûKèþ‘J¨MðT µßn•ÐUN•Pz‹TÂLJè[Y%Ô®SÊ„–8R'ä¦hÑ µŸ:¡žŸu”ᬪ/¬Êñ|ê„:Ïš:áNûÄÔ -ºI'Ìb¤zÄU0úý:¡˜uB½$©*¤ZÑ i'š:a¦X'ävê„Ö¬ê¢wˆå¹tBmŸ§Pè*[(Ì …~-ºÃ¬Zü—RèÉÀJ¡[•J¡ä+…î/+…Ü@M¡0kc¡PãËB¡…B òU'ŒgÐOÆ:¡v]S'ôôB¡«k¡Psr …ÚN¡Ðƒ+…B™E¤P(×B¡-0„‡i‚a¡Æ’ÁcR Õ}V 3J¡v*…77®¤ÊïD*…R R)t3­zX*ôвTèÙ_R¡‹±Tèn©°¤P*ô¸¶V˜y¤º:Ö ³:Ò ý<­f9Ö yš'µÂL‘Vè´Vè†J,”Ç m cµÐ’­ÕB/«…2çIµ0S¤÷8”¯…T 5ø‹ZÈÉ#ÕBõEª…ZK˜ }vZlèó)Z5³\¨3Ï)jÄ¥\¨NN¹P}a¹P}œr¡ŒR.”ÕMÊ…¾¹õB}CR/ôÍ-n<5b6´7 -õ¤`ÈC|fC¯S0t/[0ôÝ%úV µ„KÁP® R0Ôü›‚a,ÅÐÝ#ÅÐí´d¨±’¡†iJ†²UKÉÐ[2”—³¡̧d(w-)jàZ1t¬j1Š¡GŠ%üUÌjSj†*Dh˜#Û¢aêŠ ý>X5ôÓ´jè¾±jèžÚjÏh˜rªÐÐŽNŒ†y•eCù6°lèÁnÙЃݲ¡›nÝP8º¡:ì7Â%%†s´Âƒuæ–æAœ¿+RòàaZÒdô•f„+‹Hî§ÔAá`,y+bñªžpð ‡ÍÄA¬×WIJ:”?á |GGŠpšXÜK8ñhÁÁ£ïºjâ`Ûeã*“QÛ¯Údž©ìd2šyd2ŠjF qp.xW“Q¹‰K“Ñ,G&£Ø& ø#–â`I!¢†Ô8‰ƒ g›*â4gì~  óÆÁ^•? ¢ÜFûРA·Ê4èÞ –[“qïØö 6X1GÁ¤Aµ7 ¢~±® "åXäB0Ä)¤Á,Y4ˆ»ƒˆ³†¢ÁvÞáÊÔ4ˆ<±ö ‘ñ‘0ؽ-ý8 ƒ­Ñ…„a.V’‚Ao¡‘B /`ÐÃØ0ˆ¡~‡¦Gl­…4nÄ89#…0ˆ<{”ClqR°À`¹Š0ˆZ`qyŒ0x<ô¥i̦ K a%‡FL, „A4´/j!Љչ`)!G ³‚A<Ï ƒÙï‚Á¼J0˜/ÌŽ æS f‡ ~°ã ƒÙ,Á`©aÐï¹a0Ÿ±`}8#ÌgLÌ6óñ k r5:¹6 "¥/ja¹i°”CÌ&Ìç'<|,d=â`ö p0»G8ˆAÔS-DeÎÅnóí±¨…¥Xâ`ÉCÌ&=o‘6 ÂÁœ „ƒÙ9ÂÁ:âÁœ „ Ö±‘B œkÁ¸WaÉB ,ó™ óy sx ³ „øèÛ„YcaŽIa>*aæÝ„H¹ lØð Œ$æ;" ÌÑ. œkç€=¡ Âlº€°¤–‹„¨Î¹a>Pa> !Rö³O„9„n–‰ÐU¡˜‰ˆe´ˆÐo–‰Ó<9’D˜·jd"ôÀ0¢Ygä!zñe"Ì’I„ž/L„%…D˜·f;E„žÝM„Y¡{9MH5—›1œZ¤§‘L„zùM„þ"™³—I„&Âì¡¿}&Âr‰°L"ôì$"ôËf"Ì‘""ô»o"Ì<"¼¹ˆ0[."ô'ÝD˜}*"Ìú sT ˽ˆ„þ& sL$ô›o$ÌBŒ„™B$ÌA $ôjÕHè7ßHè×ÑH˜ÃÔH˜÷"âÅ¢6($tW ýF ³d"aVYHèO‹‘0“ÐóŽ‘ÐOæo©”G 1;·E.Üä×Íx¸¿ßàaÐ\åÃS1†Í‡æ:óáFûŠr¤#’FH>Ôš>ùðº%ó‘SG3æqAË…Í3ŇÖ'R.”ÃR)Üe”*¹P»¯E.ä~Y‘ -óI.TÞ” µMžr¡¶”S.”£ç” %d¥\Èc©ÊÏsª…üU,l-=Y,¼.™xJ,Ô¡k…'ý¥VxÒ¥* pj…x»­PÇÛS+<›xQZáùˆ¥Þ]ê¡´Âë¥î`­ñ2"EZ!¢¥¬ ¯FýÂZá(çXè^úÞŘñ‰C®°V(Oí©"6ÇGÒa)WRáur½e©p\CÝMRá}èTŸ¤BEKN©ÐBã£TxŸß(„ûŸÈ"©P!‹S*¼yÞ7¥Â»}®J¡ó¦Rxo:ð(¥p´3ÐKB¡•…B¬ðB:”PèFY(­ çj7ÑÐqÊR'd¤æ” ï]ç%ÊŸyʄϩCˆ’ Õ«„7í±S%¼û·§ 3TÂQ«8Še•Ðe•ð¦Fª„ãÅ YU*¡¦UB$«„n§UBt«„)¶ª„® TB·Á*áÝÃYª„î@«„y+©„®²eB?+Ë„òÜž2á½}{žÐ#Ò:ácËMé„™G:!¼}.tämÊ„~É,ŽqNsUÉ„~¥,Ž<<¥(™P²S&ôP²Lè‘n™PcÔ*ácsP©„Î"•PQÊS&ôÛk™Ð“”dB¿ò– ‡n• ý,*J@Ê„~¼– ýBK&ô»j™Ð…eB Ë„pÑ)’ ³`É„~2– ]eË„~-æ½$ú™[&|¶‚„ùx­2x¼%Âç!v["t)„®‰B5HÐCÄ¡§ „𬲔ÔÕᩪëRÌéƒzUò8áÃ>N¨þ6 úÍM}ÕKyP#$åAµ)åA=˃œÍSTϤ:¨œê ^§Tù Rì» Nâ ÂmF15>RT${£`¹¹Njä¥8È5µA?iƒ7O ¥6¨Þ³4¨/|Jƒ£¯öUtõ, Â<.®¢4øp!Ò`x„­Òà³ ³$ jÆOiÐÊÒ Ç„¥AM) j^Ni³pJƒ}–5I¤4ècip<¼8-Ò ^Ó”Ÿã™§ 3‹”AF+ƒ~NV5A¤2è¶2¨5qž'Ô‹éó„£6«0Xª£ó„Ãʦ0èQ"a0j¯‡‡Á×·ÉzÚfø N¥^Z ´¬YOH‘¬§¹$YOc YOoY²^^%ÖÓ\œ¬§É#aO9µÀóå¡ÉÔJش篒iïöñBáœPGŠpÏ+ ã^I!î= jÜób̸— ÷2pÎJWÜ{îÏåè ®•ö2E´÷„„°ç5œa ¡ÊzØ}X½Ç$Šõ’í{®XÏ Êd½Gä$Öë ú›¬ÇÉ-Q¯o”%…z^¯%ê±&=8>þ¨ çúô²‘^ÞH¤—)"=/òŒznQo¼—ýwù¢Q/0BÀCêŸcs÷œ°gnîžóÎ ðÖùÈá’€‡&çæî¹…t·Æø¾E]³3¹à)”v¸Ci·° îPûô2¤»Ì|,¼‹JŽwï&‹q5…wèÓŽwìBÁ»"!ÞY§6¼»‘Aé[¡»wë(–#ÝÝãP¬Òò91ž éY—›_EºCÂú˯"ݽ/12$ݽ¯;!ݽ¯]nÚDwÑï¯*Ñ]$Ï ºƒ¾»«çû^“c'éîÁÉ#¯Ùé©£-DwÈÅãN2¢»réîAV:—î`wõ„V¾­ÞE*«À»÷iýˆ ƒñwÒßáïŠ ðÝêÚ\=K=<¤¢©ÎïiÌÁ„‡¦(!á嘊ð$UwWJÞ3túMˆ°„x˜1φx‘›)ïi“ýä!=; yÏ 9> ïÁ°A^äG ÈCq!Èôï[dŒ ÷P§LßÁxH“D$ã!#/rÆ{Ö¥zÉxÏ»y6ƒÞó*CÊ{îÅÙ.Ê‹ÜZAyس«HyHе6ÊíalRž=…^†”‡¬gdCRdÝtþtÊ‹ÄcAyxvGµè!Ì}?IyÏû û„å=ãP㤼TK”‡¹ã“[”‡ô[ ꔇYÐ7‹Þ»?PôORwGQ:¸[ô Ý8‰yÈEZ$æ•«ˆy‘º-0wË-3Â<äÞpxæ=þ|ÌCÆ^EÌËÇÆ0/»'ÌËV˜‡´\~hSœ÷¾íåAJÎCJ…sã<,Î}sõÌΈób„63rÞ3˜U¨÷Lýê¡ÌIçχéÔtTL¨‡¶x‚ÐQïÝ„q]êåc$ÖCò´=0LαT÷è\b=„‡s%ëEƺ`½ÔJ¬÷\]nœd½ìŽX†%ë!‰šk%؃æçæê‰»unF=äz¡w*a ‘›«{ù  öžqËG“°-­Åa³T¾ŸN{XüÛˆhß¹Ñ^N'ÑÆÔŸ|Ñ^®Ó¢=¼ŽÍÕ+.-n¤=¬Ó÷&^ A{Øh ÷¶$í᪃ΟN{§9LÚ‹WhО¥ÅóÆI{xÙ›«g¼Z‚ö0+Yq/=^î¢&âÃT!t‘øPæâQ?G>Ü⾆yºN? ù"__ V"ºƒù"/a _ìùЖ»q ùžkЃOȇ{l‡ÿâùòat:;ùâ¥ȇW €D¾X¯ù0ûá¿§­ýð_i›Ðwßü²Їeb;û‡{>Ý“ÐS0 Ï“© /'¥ ©EÝÃPЇMù¹Å…Á“ʶ}±u èÃããCÐ[4‡>¬^ô£$ô¡ÃnÑôa­âûòªæg«[ówþ+Á@~˼e¯„:à«´ë0_LrkŒ',ØÛLŸ0A¯øØ´úáj„X÷qŸé°4‹: ÔÆM uˆ±YUï1gÛû°›V­ùwØWrMÓ ù¼ï®FZ=¬Y:<š‘‹:èœí+yuXÛè,¸nOÐBøDÓéý¹Ãëm7?~g¢Ç7uPÎŽWBRóûÕÁ$ŒðùJðIj»{÷«Ãðz¯š—k•½¡çí ôJ¨CiëÕáÞîçý<~¯b6½ð-ø¾¿O­Ž» o»D:Dÿð èÚÆïÁ$oûaͯc¯gñlõÐÂ︻VuÈYðH‡ƒëÉ»¸]¢2xËÔ;~Zªªçi¡°ëó€EÈu8¸òã1×®z`º­ã‡iêZi.a¸VZç1Èš>:Pâ;âú«—¹Ã?L½’ó®ëß uë[ø}¿:½ÖÇû‚×s«c~"#âõ-ü¾i#qJîŸÑð¹¯ï–ípbÌÏçñõŽîßî~®:V³³î2‹³÷¹¹´s¾¿/Fžé®#ÞÏçÖ²“lY{Ï6/­ qì úÞi£Ù¤Þ0'²O7 7oQC@¼’s}èdÃý-ÏŠ¿’‹o‚ÉÒAïÖÓÜaö2æ€kwj±¥Õ¾_ûU·Ÿ©Î;Ž™c‹K:Ĉ"2Õ>¦ˆ/W#>¼’6µÚqæàpb=~ÿJ<‚@ÌØNâ-~vêsË|í¾åùßWrû¾(Þ®g|_¤ó¿<šþ.=‡tXz‡tÍGã¾Hû l¹·sý˜ü¾/ÊޱíÉN¼£ÏúÖ>‡tàQãWBRóñºWkRòèü;5ŸwF)9}o§Ô¯D:0ªÎÐwovßÅ.ìœÃwF ÝóJæµÍH¼£ÏmíÀ;zŠ&uP€HÝ+Ö»ßÅnô\gì.J÷Fq?×å»;ù¿é­/ê{µyry°žk×Zm{¦ñŽ®Å_Éãû»ÔsI‡¦çþv<”†Kü3FMÁ§.ß)vÔ+¹|o¤XV¯¤ûþN°_ɸ>îÌMJë«Æ.xß¼/í<¾3*-?¾3ʹÿ¾»Ë9Ê1eF>Ô öµúzwá¦VNsû¸ë÷/l:?¡GM|¸å[$8ñ¥™»qGAKÇtðCÁ ËR¯(h²–£à„áà®(hIœ®A Ö‹‰ ƤÄPpâû"Õ nê0íŽu€Û2Žš°~PO°à„Iõ¨,h%D~Æ‚¯„€IõYØç Ì®£ƒ`\â¸0 ̆€–Tœ# ]B8ºÔõA¾¼çôçp´?sŸì¸•04Épík™®®Ó~ ´œZ·j Ÿjã¿ /îBÿjÃ?+ÒX‹+@“ãßöwC§ZÂño°BF3ú³"œµNµ'CÝ‚Õý[sÒéo+cô·•1ú«ümEnöÎ&Â_-áðge„VN–Hn™þJCÎ~ÛEÆ~›$5`ãÎ~[㦭Œ±_ÕÛÙo»ê9·î­Tµ¬TÔëì·IŒ›6É5¥•ê1öÛÚJTæ‹Î~vAϰikÊЯV ô«%ý¶T!º¿¨àèWËÑÏ%Ú¦ýê’ãè·•¡ ¥ u(æ­uæ*úUýêíuô«=~¨C¹Ê°©jîè·µdè·I ý6‰¡ßVOê ¶¨C”!ú•2†~ÛoC¿ÒÑo+CJ™Oˆ~›ÄÀ)§Éo+bä·5eäW%çN©@Ðk{~µ€q_m×¹oÂWƒ;Ý3»OÁgïú¶kŒ™¶¦úªÄ©¯Tãзik+píu:óm8óC¾Ú5G¾ZD½Av^‚çCç½RÄq¯ Œö¶k®­ÒK?µ!vØ«Eæµkã¨WµqÔÛ$†zõ"õ>Š8éÕ¾9é•‹ôªàÒ‡‚¾ßò®Þ§DÝOÉjŸ’ûüÐÈ1¯6ô<³k¨ÿ)QÿSÒæ§äò­O‘tßúÉØšvÈ«÷hHƒº‘¨Ìs|‘<wÉ!¯–qÈÛʤ *#ÔAg¼­È¸>tãm¿W“R¾ &ãme¾¨àŒWšvÄ«9âÕ"mJ%1ß5>îÊJ $ù¢^­xµ½Úûü¸Ox[%R $wjÀ«ð¶2m~Ü'¼MÒ»ÞªŒëc¥¾¥AVü¡ønûûs|Ü%ç»zó]-ó¤*“ °fZUCò'’#¥­oØÇ¦ê–p\ú$.[ò=Tcßõ»díë§>¬ÓÚwŽÆm<}ç84ö¡ÈC»[ÊàÕ¶h_sc߉-˸±ïœáÄCkß9˜Q&¬}µfª0nuÖ¾sÌ`ÇÙ=,8¡Ð}¸D¸éƾZ‰T¸ý(WûÊU4öóþÒØ -nnë+:ÑÖ‰¬rnë«j·r˜“N™4õ•¡£©¯–pSvk3õá†Þ‹’ÏþÓÔ‡ši* ©¯ŒM}E%šúPϵ™ú ™¼ÊM}Pé¢d]Ûˆ›©¯¶ãf²¢M}¥šúªÄM}ÐûäUÔ û2¤A^åf²Ò:M}¥4õalXÄ-}EàÄO*†v¾,B3_¸•¯t„V¾r³iå«’ì>;K+_™S´ò•ÛF+_•¸•7‰ˆaV¾òÔ.i-ÑÊ—s•F¾R |©%m|EÚøÊT¤¯¶D ÊUn«·•ñ£¯Ü³ñ•´ñAËF UˆßÒ€þßaâƒäò¦iâ«»‰¯–q_.E·4 G}øj÷Ü8Vzc¾¬„ö½rßhß+ãKû^yhß+£Iû^­Çí{924ï•Å–æ=\TÏæ`½R€EdÜKݸ—ëŒ{9º2îÕ2R@Ý•q/o¾Œ{9­d܃2å¹q¯öÆ{9â2î¥ §TÐ@¸m¯hõF˲—7Z–½ÒZöªDÝÏVÔý¨ØÍbEàV±ÒyÚõJ-´ë•¡£]É4~ñŠ>fÖ˹-³^•¸YZLJܬ—SAf½R­ºß…ÿMý—B4ê•–hÔË"´éaç@« mz¥3×5·ñ¿¤@hL›^é mzåŽÐ¦W¯r›^­Ùmzv;7›^¹Š6½Ò?ÚôR)šôNëÕ ½²?r‹^i¹§l¹§ôr€iÏÃ5¼åö¼2¦4P-S ÄÓœWЏ%¬ôŬy¹‹•5¯èLk^©DÝ)Mc^:óò"ÚòŠÀMyEà–¼r—ºkÁRÿ5P4äÍWßçÇòFC^©DÝ‹nu?–kÚñÊ ¢¯ÌVÚñj™Þud×ÇMº¥B ç½ÚvÌŽW ¯¶ó<Oíx¥yyg;OjÀšå®þþLGÉvÝܯªçýh— ¶».9‘í¬¹°Ý’k§ÐN¯îßA»ØåírÇ-´Ë{ ]–!ÚÍ)2¡Ý\ê¯Ðn>ßw²Ã+­#øh‡‚;Ú-&åI´[—¶eB»‘Î&‘þHF8Nç’ÝZô;²CÈSìJ-R`rûä`‡ˆtìÊo‚]i…`w²N ìÞ«hõØ­G[p]xñŠë²)q¢†SB®+rÂëì\—›ùÓ˜hñ(WR]ÔÝ Œ—P— êò"öþfÔßd:DÛr™(;/¤»›ü΄t¥m2ݺÅDuÙ2ûŸuØ·Ð`F$Ê[$¬ËÎë¢bQÝ}È.-ªË"D¢R„H”C%¨+mêJ™‡ýåw€•p4u1•uY­ .UÕåE„ºœ†‚ºœª‚º5„g‚ºxFÄt:'“L·Â/Ø™®þv¦ËGOL—뀠.ëÔ­ðE¨ËµBP—Ô•«¨Ljôö”±R ëp˜‡¢,âT·ÂiYX·ŽpìÖ=ú&¬ËPXWê!å2*¬ƒq‰W‘ël:ý(XWº—Ìë¢;v±¨ì´¤×iëRýçk÷ÈþÓ&G*Bè?b©(†* ®TC¨Ë–Èt!ÓECŽtY©3]Œc@]€ .F6 .;"¨ƒƒÂu1‚êàÀ¶ˆE8?ASÝ o/Q]‘êàRA3²iǺT@XW® ÖÅ„ ¬› âX÷YXWbÿcB×ÅEºSÖB.ŠåAX—ãàX—c'¬ËKHu“ lërŽ ë²·ÂºÔH\—Ã+°Ë›+²Ë¹'²+WI…,C. µìB]>o»xÿÙÅè ìR ³¯¡µ¸.û/®ËzÅu9âºÉ(4ÉuÙÔjÛ`:ÖåŸIu¡¯ .ÔÅÄÉݰó) Ñi¤ÿD¢¢tÎVn¾™³é̉|3ÓGÏ}3Ó1N¾™éõ&ßÌtý‘ofºþÈ73tä›™N<òÍ ï*¹f¦ }ØøwˆùqÒWÓáyY:U èa½ún:ÝA"htº«§;H6çÌ]òHÂñ$ÞU‰óÝqvá(ù®JðêUÒ!%®C^³®ýïNxµ„$}#¼R¦Kƒ,# RâT%IµG¼ZÆ’µÒ«e{ÃS?yõïI¥RÞ&y¾ïµòª$5$5P=NIUâœW%Îy¥‡ä¼Zó‡#uè:“w|Ü)‚^•8èÕ«ôªÄI¯´=¿è@Ô«¥Z£^-ã¨W%Ï®ÃJBò|Ì6²^©…¬W%ÎzUâ°W´Z_tX©ƒÊ8)Õ2NJUâ´W$F{Ûïçc¾Ý©[ºSI•ªÄi¯Öã´WË8íáµÎ~ÑáNt•³Ò&y>f á^©—¸W%Ž{õée—jÇ¥*qÜ«W9îÈ{µŒt(’Ä{YÆy/ëðU‰_•¤’|ê æËy+æË§QÌWË8óÕ2}¥Ì)´F;ö•k ûêoǾZ‡c_•8öÎÔ@õ¤φ}µ/ŽMµç¾R†ÜWê!÷•¶Z[{‰k)r_•8÷U‰s_é ¹¯–‘Ùò ~¥ ɯÔCòË·¸È¯Ôs]{½Wêðl§ôªÄÁ©^åèW%Ž~µ7Ž~µLê@ Ù¯´Eö«eÚü¸S„¿Z¦ïs¢§*ñEÂ_½ê>÷7“àÏ*OVþÊ}©k_t ü•š ¥uÂ_™£e üÕZRIRµýûj'ú+Ò_ÑŠôWZŸ©ÃÚÌzUÒû§d|ìŒk½«}Ü+`•¤!y>$$À¢ °–ióc¾‘«ä‹+ud~ìëïûc'¬e¾èp§’œëSÒæ‡V¤ÀR3)°JÆõ1ßîÔAõ¬}Ô ëÏñ¡A°H‚åþ>©ëy¾h@ ÉOÒ‹Þ‰²Õ¢7"ü-zÇ›·æ±tÈQ=¼ é°C“ÞÏÞ¼Æmz>ó*"ÓŠP´é½›:ùÒ¦‡«èEG›Þ±–"ÇЦw¬›[ûV„âö­G)„}0$ð*C¦ò›Ø;Û&ö•2Ò!êöÁª!‰/ °ÝÔcyµa_¹ŠØW$ľ"‘gc™m2•¿ûJ b_–öeï„}Ø_Ö£yµa äšÊUľ»äûJbß}ñc ±æ3Úþ ™ÞßÂ@"S¶,ìËv„}y•°¯HR]% ² ‘©´EìËþ ûŠ„ØWjþÐa¤‚3"S^#ì+eˆ}9V¾r±/{Øþ£`_öXØW$ľR±¯H¤CèyÑAØWÊ™RâØ—:û²a_‘H‡¼ŠÈ”ýö•2ľÒ6±¯ÔLìË{%ì+e¤ƒÚ ì‹¶ˆ}qM`_‘ûŠD:´€³ÔA-šJBS©‡Øcõæ¿Yë!öeÏÔõ8öe-Ž}å7±¯\Aì‹9Økx`_)# ²fBS‘šªäùÐIØW$ľ"iÛ»ŒØWþNd*%ˆ}ðؼ8K_„}¥Œ4ÈzRŽ„°/ÇOØ—ýöe[¾¬Ù±¯”)!2 ‘©ÔBìËþ ûào±9rÖþI‡(#ì˶„}¥ ±¯”!öeëŽ}¥Dê Z¤CJˆL9¢Â¾¼3¾R3±/ÛöåèŒÔAeˆLY°¯\Õco§2c{ö•©ƒj¡Eò3PØ—wFØ—=öe=3uè[p–Z†È”#(ì+’¹íîûJ-÷ù¡Õ|>vw}©Õ"2 ±/¯öe;찯H¨C‘™rûJ½Ä¾-a_é_êÐ7ÛF‹A|„}¥ ¡)GTØWÊûRsa_¹Š:”¶ÖÞ?Ǿò›ØWj%ö¥Þ¾lGØ—c%ì+WûtUÉ]¸Ã{ ΋°êO¿²°J*Ðæ°ø//Ä=¬eŒ€BÜ»ž¦£!Ľ~Nùi÷@}ý~ m’ˆ{à Æ±$µáê¡÷q¯7yÙ ÷"s]à#™ÿîu¤“áoÇ=\36+_ïáaEÜÇ(€ uèáÍEÜë].¤½Ha´ù¯‚ö"OoÐ^7¼ø‘°iQ {{™°‡|_Šê°¹ùö"KXÀd]ŠÌâýgš­`½ÈĬéƒõ"1`°^éY/òlëEÆ9²^dë"ë•q"ëuÐ$99ëEFº`½H‡¬yì‚õ” /P/ò°ꕱ"êÕŠõŠD=eA&éEV» ½rIz¥Z’^¤( ÒS"¶½2¼½r'§4èšó½Èk W†œ —÷ŸœÉÉyå>.iYÒ`È_•œWæ 9/’‡çEÅà¼ZUˆ&æE¦ÍÀ<¥¦ÊC:¡{£<åó#ä)Åg0^dÙ Æ+ÍñÊÍ'ã¡„¥N`"^¹ýD<Ïî|‡NOJò]™ ä»ò´‘ïJCÆweq ßEN»à»R ù®L!ò4¢ç5ù.’ªßå„!ÞaüÙaâ]¹Ä;¬’:Hb¶ ï°( ¨Î»¬¬¢;d ÜCobɦ (wbÀVþ±ÎC½jÙÑ(_±]mÉÙ‰0äÓÙ#Ìó{d;¤{¤¯¤õÿJgJKEo¡]¿..TB;dz ·ú¯‡å^m› s¹ãÌ•5ƒ0—=#Ë•¤Ô)]GEÄrñÍ|+LU[³µqX¤ŸL}ѵxÕlD,“Ùˆ>ŠäEÊFôyÅÈFt™ý®Ö)IÍÿC™’}ÄÏ3“½4cN ¥"J¶Š\ég©¨7¡W´¤¤VD™*ŠŸç?:+‘1ãü»²Árûÿ>+ÑשÔF³K5]ËÏæÎak)ÖUò ±®-ßë*¥X×VJue¾!ÕUó ©®,¥ºj)Õ‡TUÉ8¤š¢Œ**eô€d¾!V´åÒS•¥XÕVJue¾!ÕU³©®,¥ºþެDïþ̲"ü{ÌJôVÌßöðËúøÛÏ–ºfþâIÙkùóY‰ìû\ûÿ1+Ñý³¬Dý7•¨ÓO´&X8ï‹»‡÷_W éþ¢‹?¿fºqî›ä6æ¡/5“¯Ä÷“øÇz–í'Ç1¹onãöÍjn.y|3ö(¨t›‡íÆÆ9CrÚnlœúBܦ¯jHCL&t@Ç#mã@:T×`Û‹9yÔ»Íi{±1˜ýèØV Ÿ¿NV²l+6ðY‹]q¾ °bWy‹Ý5¦­Ã6cÈmÌÆ×i›1hïæÐ—ül7†¯d’˶c¨Ç·e*ÜÊÓU(µLÛ‘GY;^‰íÈloÏZ–mÉÆ£ômݶ%›‡¢¡·õØ– _èüO»©CÖs»óPn€v·Ë% EÕî˾©ÍCQÕÛÝí£Z• {æ<åTÕn×÷¸Ib: §ó dÙG)ã¶}ÛG)›+,óØG5Ëí:<‡í+ß§Š9#Þ-Š}T«ê­#!9$í¢ZCö{¿jØgµy*†{Þ%x–ücQóXÒVogo¨МêPê}¦Kt¤û:û²6› òÝFíßu´ËµÒôë ÑÖuP‡&G—ë‡Kt°þB,Ch…\2,3¿Æ=X/øvA«öð´Òûn¶kµÔ!ûwR‡Ðó:ÏîZ í»Îv¹Vr¸N#—W"ÓÑuÚþÄÚò{~Ò!ÛJTó¼]¢³õ×¹n¯ÅQézÁǵšüˆxÏt­Bóv ¿3²]M:Üüü¾üìûÔDÞ ^u5׊Ir_I?]«èq‡k5¸¼’ǵê|fÞ¥™:Lž?»šë°øùáj÷ÚÛy¦tòÌ ïÞdH'¶Œ4G—ŒÃýuQƒ›Kd™~ºdñäÛuÃuŠ‘¸Æã:¥dÚG6ä`Ÿ¬ÇbIØìá½¶z=sÐÎmŽ€bÚ¦wo—ë£ ÞçZ—“«æÕ¥A‘<.‰¹†ïÒË[÷Uóêké Rîé÷©ócéÕ]‡èÍ7O ^x=ŸÛÈ`wL­–¹šž)ŽÍè§kOâ,Ò!FgH‡ÅÕ÷kiöñ™Ç çÞûü ×*ÆbcÓrR‡\¦tˆ€Ç¢m3É™¶Þá9Í?÷ø~%k½™óÖjÇ5rR‡"±Œ†[Ÿákx”Y–ûØVhϬt­soïh[ÕÍåZÔáT$ŒkQ‡xW]ïvÇ%rÊ}%¯:*~­yû›)%Ë>´á ÇYº¨C©G:Ī~Ý%¡Ã}^þ¾U6”ën—ÿæ¬À;šZñÎàݶ'ñ¦¥écäÖ\Õ^µ–´ò·â»œ~¯ôN¾îg¸VÊ'x=Ò!Æô¡§‹_OkÒŠÏçû–Þk±/þv WD¼£›÷ï’äù¾Å#²¥µ¤'Gç¹}o”cü<õÒXôãèºWî)Ðí(F½Ãý ±#èǵírúôé©cÇÚ$:OÞá;£Cî–/ Ü»Nýƒo¡~HV?ž¡;åÑZúypg¤{×Ï“;#Ýß~6ßݽzO–¹|woöwA>ë¼é'uÈqÀz›Ýœ×îi›óöÝ]<ý¤‡òõ&4Û:‰wÊWÛÞwFºãï ãü¸S­sw§'¯¿ïèmüuÈ{…7ô®Õ»ñö{¥ÌJyV/סQò íYY3?Åäþ¸_ÔáPL}¿AÍ·ùƒy‰ˆ‚ùäû(Xr –7DÁ‰Ç‚{|GÁùÜ; ¢à„©“ûXGÁ‰Å÷nDÁWrs4ˆ‚¯DŸË‰‚¯¤‹€_É¢îDÁiFT–q<™bñH6^ŽÂFúáoç¨Oц‚¨cHâŽVÇÅg\,ˆz&%΂¨‡dE„A—:‘<Ÿ¤¸“çká-YðÀ,%/: ¢fÂõrî :éõNž°Éz'OØ"6² ZìßÍ6oe±`Æ –šïÔagÁ¢Y0cˆ3³`F æ96±`ž. È‚E²`i‰,XÚ" æ‰G±`i,˜§Ä‚U2Ž­ŒËø‘kKÒ![ºãü4õ$ fKbÁ< %Ì3†bÁlK,˜m‰³-±`mk<ûIcgÁú{Åùiµ}óüôÆLØÒ™:ôKÛdÁÒY°JzœŸfëçˆóÓlý”Sû_²`mkÝ{½÷ÚO…‹KKdÁ*‘)i<}m“«¤Çùiö†,Xî0Y°ô§Í3à΂EocÁúû™ÒIduðütô…,XúrIƒhç’)é§$ªyºS!y¾ïý! ÖÖ×ú¸S×½ƒ±`i™,XFœ,XÚ! VÉÕtWÄ”Ò ZîÒ ËŒG:©­yÌ>²`•ÜS÷I­?{-#uÕ<{½! –Þk=ýü¸SdÁZsê ‰tȶÖú”ÜSwJ­?Cwª,½™Ò!%Ò!%Wû˜dÁÒ?²`-3Ý+µ=ï{5¥C¶uÏOÉ3>æY°Jνm²`•¤l{I‡).& –¶É‚EO²`­y­­Vê «R–! –zÈ‚UÒö1& VI??ž¢[:d-Ò!%óþ”¬õ¡Y°öøZ=Ò!%Ò!%­}J®ý>k‰q|Ü+²`•H‡¸WdÁZÏ=?ž+²`Ö#LÍÅ‚µŒt˜Áq»΂َX°Ö:žýN‰kiõJƒ”<ãCB¬’óÚï”X°J®s¿/΂õ÷È‚µ¥yïwJ,X%÷Üï‹X°HštHÉyI+¶N¬’ëüЊ,XZ7Ü~?ûl bo~o,X%΂Uâ,X$dÁÜw‹«D:Pògr…e0ŽI¸e;ÁPªáx-…nlð0&ƹeÖÄ[ðg Fë?È2'Ƀõ¸e°!6Ë8Lµ™é0õâÛwÒ•|¸iŸsà .9 Ö2¦ÂL¦IÕ¿;I5ô‘=§Á6“:ÛJs£Ó`½J Ìï¼Hý"„Á*qÂE„ NiÌÍ0X¯rò7U°“?’KÉ‚ Á7» ´$É1}iù" 6x«üR…gcAø²ÒôJD[Ä1GAt‡s„(ˆ_¬fœ~É#ð£ äwª 2ŽQUâUšv,z“³A°(ð¤çf¬‡¨¢A°6¬×8Ök¤îÜ#š¾ÈsBˆ³q`^%L¥Äõ*ª€í8Ë8C¡Ì#ÉãJõ°øÍ§Œž0°œëÒ@·IXzG ÌÛ- Ìáæ4Æð «àÙoŠ0;lX+u¬ ; Wµ óÁV‰T•8V‰#`m˰–¡ —²;6Ùïåϵ{1ˆÿPèÊù’åÇ¿ÒÆõ¥÷—zÓ…øWË8<•q!þåb*ü+$þ¡fn½.W•>³®Sb?ý™à?úR7B_.k‚¾*a¿cMôae¾7è«qè+ºúªä™õõ#è‹·š˜‚cc¾z‘3Nœ”8óÕ«œù|U%Ï÷Æ¥B–q^ªg>HÎÍþ—]6äkæ>ü#‰½s‡\_é/‰/ß»"¾†4,ãć·ùÅ2N| 'ûÈ€N|L–¡±•ñ5»øG_î-|h|ÌÎîÝ»6à«×H…”P…hˆ¼W¾óI%‰{¹eîᢶá^â^)CÜ+j÷ i÷0T42÷ê5»·à[*Ä÷jÛŽJµ%ǽZææî'ô$î•þ<©Ãfù+Ý!íÕ‹®½Ã¤½ÒÒ^CÎ^ã´×Æ•z¤ÂÔ[•´W[rVÊ»IØËÆ{\›áŒ27Ã_½ÊUX›á¯Öá ”* öRÁ^vW°•–‘Á^³³a?’õJÅd½*qÖÃE²ê9땊Ͼwø” Cv,²^•8ëÕZœõªÄY¯J¤BHšt˜ß‰dŽIys…z¥q¢^Q“¨W%@½¢v“ òœêÕzõÊ] ê•Á!êÙYmïQ¯ôø’YF:¸š+‹QÐ6&½Ð€Þ˜@£“˜A´‹HÝ"» ".²Ë(î"»Œ‚/²C&ŸFÏ›¹pM_d‡»í§„v‘ÿGd—FDv¸¨’]¹¤·½ÎÁPêJ%"°ƒdn`—SvU¢þ+—È.3¯ˆì2 ŒÈ.³Éˆì2ŒÈ®^e:DÒ‘]mɹh“D>]µ˜G§ì…vµÌØên¯TLÆ«ƒñ2A“¯^3ï#ÄxUr3/`¸°’ñŠâqôW*\©‚Š|¨ðgò‰÷ŽÞ±ÑÞËxÑÎ{˜܈ ùìýQ~:Ôçk|V)ð¥â<Û)¿&ÑøÎ%öñ!\yȇcL;òµCäèȇC,a¼ôŽÚÅZÉK­…Û&™¯J|¡@µÍ˜wâ ¨@ Øÿ¼Fćãtœ$.áØùŽÄ‡c;;ñY4–|ùSý_Šm Þ«_'Š„¼‡C%l‡¼WZ&ï!>‰ Ä{)Pÿï8HTÊ–„{í ˜#î‰á~Ð' žp•O@#Yé:îKEBÜK‰p¯Hˆ{Ùáâ¹€¸ô è?*Ü+â^‘îÕß¾L”¦S•IØ4)Šñ ‰/Æ&ˆ/š â -ƒøJ=¦*y¤T±ä•ŸD¾r‘/‹P˜"A|QDÀ—ýð½E…¾R†ÀWʨÿg€cö_eÈKE²v|EBàK‰€/Tðeµ¾r)/"𥀼—·M¼—E²ÿ|tßq¯Ô@Ü‹G)p/ïˆp/¯º²÷ä6v¾TCZŠõ"h¯TCÚ‹U&h/Ö‡ ½xúI{8[ÎÆJh¶ã^¬£Á{Ùñž–ÉÀ½rÑ„{ïÞyQ©HˆJ¯„»Há^‘÷ÊUÏÜJ÷ô¶Ú‹7AÐ^‘öò"Â^ Èz8f·9qBr쬗‘•ì™ûQP¯ÔBÖ‹wY/.™Ùý¹æ+ ‹õJ%D¥"!ìUɳ½WöJ‘T€GÆD{¥ I)z,ØË"{ÑŽX/vÁzÐŒe¤@ÔJN*EÈIo5<&ÔËî õÊUR ËHF6rRÖ,Ô‹ÍQçO7ïMl&‰Œ¨WÊH‡¬E:œ4º õJÓD½rQ//"éát¶ zÙ^ìÞô²{zY 9ïÝŽÍsEtfœW’Y†˜T$Ĥr9wéƒIÎSwóâ¢à¼è 9//éçö“„ Ê‹Q Ê‹pPb}l–<ì¨{BDÂaÐÍ”W%¤¼sÒ>(/:(È{’µ¯ï>S…ÍW/!äÅ~? /5䕾HÆßÆKy×öGa¼¼†ˆÌñ²!G¼RB ¬M´# $âåìâÂ⥒B¼"I xsÅxªçgùŠÄrô£ –ës–».H,s”Ç©-5Yn4ÑË+|! sã’gP„lqV‰07›Ɉ'%¸ C¶ @ˆ-ð¡©![‰Êâµ¼èKß8ׂµ“Žœ vòÒrÉóx-÷)¿RlA”'J°%ƒ±(`ËýˆE°å-Ó6ë‚&r`~°åéá©i:< ñZž;QñZn aQU鿯¥E‡æ.8‰Ž\… _M7ëÝ,á‰Û昉z»Ní™hûÜâµ`ȹGœ«ýsœ»0)yÎqî¤'¼9ΕzˆsæÕ暉s¼Ès(£h,ÎshÚåŠyx½û=ìqÛÆs\„Ø6u€? Ïy(ëÐ]#"I讑QUè.¸–ߨ\@6 Ë¶t\Ëtjïq­"Æ‚]mÛ‘î‚« ÑÑ‘Qî;ËH‡C{»S:Dou`¶M¨+õêruWOûuÍá”§„PW¯Z÷^¡ÎÂÓ²%‡ºw›Í5^Pwõˆ•ФCF^q.‚2·9!J½Ê8Ö]=¾“ëÊXë YØÕšM‡±Œì®ë÷Q';hMö#ÙÌŽìJ;—4ˆz‰vÐ{7ä¡Ì’K¦‘ÑuE4¢ÝÕ@h÷¢—ö¬D;\Å=•¡ÂÓÁËÐuÛ=h96´+½#Ú¡¶™òPfngô®®Mb»2~d»Z³£Q-ãl‡¶èþF¶»zDèÒáÙLy¥^Â]Â]½Êá®JœîJÛÄ»MB"Æñ®ÖãxôÞ 1#à]—â ðÊ1À+÷„Wæ9 ¯–q@ÂýæsGÂ+£EÂ+cLÂ+½!â]ÕL “y•$ô? âe61Æ‚TjŒW´$ä]CIByå9$äÕ2NHµ'¤z•S^¹W¤¼zuÈõ…”WžWR^ÑŠ”­3¥í3‡”WV2R^y¢oékæ-mD˜WVb^½Ê1¯<ä<è97‹^Ñü‘ñ|ôj™«mÏ4Im_:‘w|Ü+’^YÕép~xm–ûIÒ+«Iý£q†¤—k™P/g—P53¾Èqm£î¬‡§áÞ`W´ ö0×vFzß›Û&®ÚQƒXÕ{9“{¹Vöò,ØËµK´‡zN–q4æ¢=Ìâ8µç;£˜³Â½œ³Â½Ú?ǽ2:gêpnñZrþ‰÷ÊU¾ÒC_Îc_w#¾œ">¬š:µçÄ—3]ÄWF‹Ä—s_Ä—k¿ˆ¯Œú%ÂÄxIŽWMU^šî2UÎàá?i6¯ò›V;ØÅj÷Œ0ÉÑj‡­Ýn¶{Vÿh¶Ëjhô*Ehõz”O&¬vrt„Õ.ª‘ÑîèÄÝumúÞYÙìJ´Ù•*h³ËJh²+e÷×v¯Hd´K…d´+eh´Ëše´+Wa}DæD š@e¶+×Ðèt­v) Ñ®ÔB£]‘Ñ.«•Õ.‹Ðà…H;»föWF»¼hœû%Ùý[N›Ý—É®\D{W‘Ðd—™ìŠ„&»"I v“]öF&»rMvEb&»úûù¾kù¤ »‡f)B‹WHÂd “])C“]‘¤ ’|ª&»*y¶ûD“]iš6»"¡ÍNOJØì²Ö35„¯"¡Ñ®Hh´+íŠä‹gj ^E²îMíbõ £]–‘Ñ.ki_tÕ®Hhø*šíb„e¶+Eh¶+’TAÝY%îµUJ»]Ý.u”Ý.Ö¦°Û•«ÔÝ\Ùí¢%™íÊ54ÛÅ’f»R†f»"¹÷Ap³]4#«] h´‹žÉf—UÈh«zíJ™ì>GVF»§Ë‚(£]¹ŠF»lœ6»x÷GøcfÿÝfgßÃf:Êd— Ëf÷tùQÒf—רû!PïãÆËdïݰÙå(Èf—½s›]ùý¿wÍ쮌v©µŒvñj£]tX6»rv©ÂLT m^p6Ú]4³Yíâ.¹Ñ.Z–Ñ®\!âFÊh÷(ãVXíªäÑÄc;3¶>×ݕѮ4.â*í¢Ç²Ù¥ÀLvøBÌ+h²Ë{"“]>ö2ÙEwïìÿ½›ìrÊÈd3Q»ì¿Lvy‘lvyÛd³‹jd²K¥ÝdW~Óf——ÐdWÚ¡É.û"“]ÞH™ìJ_î}ó»¸(,v1xa²+e¤ºC“]h@›]Üú0Ú•:Œã&6";ã¸Mb ˜ä¨±V¶2Æ@Uâ·IŒãj=Îq[ã¸MÒÏý·é°Õ2žïeŒã6‰qÜ&1ŽÛêI(i©ƒ$çõ¡•sÜVÆ8n+c·•y9n+‘:•ã¶2Æq[㸭Œq\-Ã/¥Ì•:¨Lê`ejž"äËùþÔd¹!ïš§ˆe2OÑG‘¼HyŠ>¯øyоvD’-+P©ø_ÊÏ’^h€„·ôB’ÔŠ(SEñ³Vt $Ù*rYT¤Ÿ¥¢‰c–c.JjE”©¢øY+úÕ¸ï•{QoÍ?Øf¼&yp«¦ôèΚJÖ´•RM%5’ÕT#©¦,£š¶$K¬)S#YE%1’ꉪ¦&XâÓTÒ"¡š-)’fS–aE{‚%ÖT’"YM5q’jÊ2ªéïIœÔW·gõß_Þ¤?°‚]8÷õú·ßY~³ÈßZõÿž¼I}™GÁ¿ñ¼IýIý»ó&½Äü%odÿÿú§ŸÈ”7éš#oRÇõ½I–Õ’Ož¿ýâÄÉÓ|“eyÙ]À}¢¤ÂôWúÓ}£‹/Ï.¥Á’oš`}A¦¥áYžÌ[Y6}3ôyš{ÜÜDÂqö•9'Ý…zXÍ&,éÝ›o‰“6«WbŸùüà .ûF=Üü4ŽnÉä/L£ô t¾UÇ´Ï|ÏR˜q¬n«Ûs„ÄT¸‘¹øaͧ“ër†çMâ]²«9pðä}š0ZnJg;p ƒ¡ã·e8<ísƒ L…0X­©pŸ·|cƉp¯‘ؽ{'Bâઇ¾\ÃC ÜHULÅÏÛÒ;¶w%®®rKæhTá}É»Ãßhîþ^…ž”<¾ÌOZŸF{7÷9xLr ÔÓ‰††}´ŽmîøD“e\D§pãØh®B{•â}AT.Hµ—en|è»ÑÀÚŸæo“¦à.”QÈqQ…wµucÎ+1°Cç}¹ÚmJqg®Ë®yȾÚ,¶û ‰mÀË£áš+êøÐ÷ö¦Ñ =.ê0Í’«!yß"|`ÆË­¦Õ[Ô ïâïÄ&ƒèèˆ^þ–y'¿Êœ¶ £?e¤CÌÈ`’ô3J£wÔÑ®¨ÃÂs܈$å&¬làÍÛy(±—ìÛΠùqt×52ºk€þºûÑ€otÂÔòñ|Ó©Ëõi Eš%Q<4µNxë¯B’X¿¿WAÝ8'Ƙ>vº± |Nö'ÝÑ;áœðpŸš ¨YÉì>)0æ˜Ò`i>N× ½Ë˜Sÿ@†–é÷ÒŸ9dì>)gܘ×rÝËÙ§ß§ƒPÿvµ\ öcºIŹ6W7ÉÛMµt_¦ÕqÑ]j̧ÙzÛö˜_cÁSùŽ…\Ðü¤»Ô+¡ñ8/×Nóeé}o$ü¦V KÆByêÇÞ©GžŠã]¼÷–¨ÃÝ4ÆK:Üüæ4ÖÓü^É*¶2žõ–nçC=—V“.Ψ§«­ÛNнÿíÒáv®w}¹Yï,o3òLþ«É=»Ý«Ôâ^ÝçGë¾/=Cîû9n×#á_ÆCÞ1æ¬}pó!Òê9Ý+w|§ämZJb7xÒlOÃCÎ;$®Cm~y‹Eç¬Wݳéù¾¢QËÐË/hÞ+woœxA7_Û|˜uˆ«^ÉãkÛâÝ›G»ímû®ó~Øa>þÝøJ5XOŸö¶ʘ81ìÝ:µ˜uˆµk®C{pÍã¶½+Ò©6öé9ÛP²‰7ôY_“oh”A:¡›’Çž¢létÐÒd=°ÍûÛáf™>mµ ùnó†ÍÀ®¨móœÝž¢©dq Õ©&ó¤¥?¦>ÅÚìšï+Úkõçnâmo[e œxA7KrdðêƒN]Œf£]Ïf£x/ùØðc¾†Q`Aõ¶"˶Ee ìéFã¡iïHtw^®‚öó] 1,ʈ1ñz>}dzX¢Ù®¨!3#%—íŠ0PpsbðÞuJ¨ÀÛò`ÍÔ`(äã¼<éuë ¦7¯ÛvEÐþ¡ä9}ò n+g?|c÷î¥|ÉžÝtÀLéüm:”Æëùô2þú˜È€Þ¼íƒWun‹õ¸ßu…œÈb:ê¦rvê€íËP, ¬çñmQlÊæ8|[Ôþñ•ø¶¨+Œä|_ѾIó…cê0—ÆoP‡·¥ÁZÌÏßF]e†m‹ðuP2}[ôNZÞ+$)uÛ6ß5ÜïU<¾ƒ:Äöo" èò2¾™ÓéÇ;ø! ">p<:/1ßIŠmú­ù‡W4æ*J¤C¶Dúe¦oŒFטË7FCáYç¼}k‡üƒ>‚üÜ=Ýêåi×!ç ;ú?œ3Ih9N Þ0HàoäJ¥À1ðP4bàDÉIIwsÁ«¼Pq¸¹ñ%]`h¹ŽÄŽÎ Iú1‘a²x6<Þ'@Lc¡s ‡//r`;²Â@¼ë…ŽÎ×u|p Þ“®~®ï8^O£aàê˜9.p°qå»Õ)ð-2yV’X²û’×z¯SÔwØážò –t—ÄÀµN%p"®…¥ÖÃ3t­%Øp \Øg œ׺d_$®™)qn—óš׺cÓãø ”Ó‰¸03Ø:(ð½¦G ÃÀ…ØÃZ _ÄoÚ¬;¾HøOWàÆ­!~?½Djwå ¸°¥âÑÐø]Œe ¸°9j">SBî¥.*€ŒÊ”8?aª°Ã`À‡ž‡%Œ ‚$|2 &ycg@Xò¸3¾¨Ã’qF ?›Ézœ 4‹»g2à1åÜ(Äv‰O„‘=îÒáæâ óQ¶Hñ3àñ.HÔ‰ x`ïÌ–±åâ4"b_ÇùI4Ÿd@¸ýp:’1Ý9óÉ€çÁïBÀ§ˆoŽ€¹^;"vÎQ+qŠˆÏ7ì.φx¾jO–q< æ{AˆC¡¾žSž¢B@\ÕY# L£$5'@t‡% bñÙÀºµg§Û^âì„O5üÎAþƒ]”OùïìWHœÿ°ÍÛI¥ÿÂöª¼±„¿wùÖÂÂ۰_;ãù[ê?_;B¿Z+± S“ 娣ºo…~æ–5(1ô+ß°ˆ~Xè¸2ýàtÅå•èWkvl‚k+?Fý° ìV¯z¡Yâ5Ñï|ô¢úÅ&Zä‡íÛ~'f+ÎÁÀ!\tð+cCð¦ðAø‹CLî+Có|2“s¶0¢Pç¾üü(îË{)îÃÖöÚ¸¹7¸é"÷aðÚÆ}e+DîÃ?R ¹¯]Oð#u¸ù²öáéXđ鼟25-ì}ëOû²ZQ’xR" ¦È•Ôw¾ë"7›¢>|A`§>øÜ;õåöNÔ÷Ö,¤ `v–1ð­‚X%dºUN}Pš½õ½µrD}9â¢>|÷"MJƒ‹ñK苇' /ï’ Ö@rA¾ŒØŽí›0¡/fž ¾’¬UÐJ}oËWú’}¸¡l™äÖ]ЗSDÐו  ïR”ㄾàe:\+!ÐuHÂèÓG÷€¾„Ò€>eQHèSXû€>ø¡ð*êPP‘:\ŠÂÐ7”¦§BÇTÐWÀË¡¯Ð úž1êÐtÂ; /¡^Ð÷Ž…€“З°&èëŠ8ŸÐ—=¦9‚¾©D‚¾®„¾ò Ä ¯|Ÿ!ô!wïL>]CA}a“èËÏ‚¾œK‚¾©D’}Cûû€¾uø|û3É‘Ä}¶9¨æ¿ÁEXÿài%‰§äš:¨-ó6ZŒHó_æžûß’å$ €K»E_9ôBðMÇm~öHR~e øÁI•»z‚_¦ù ì]Y‹sÎWpMòÃôc#¿u(ƒ‡ÐÏÜI«ð-LAö›—¼!Å~«…U‹ì7§‚§ûሺXé™=£b¿»,¯‘S ±ÂSâà´°™Âß [DÀß!~!üÒ«Tøb¢ß‹/2æ98­ÑÕ’¼CE‡F~I$¿õn<YÐÉÃÀ½5ɯÒ!xûH!ü¡%îÑ æÝÊ;üÝM3©$ÙÕ²>nlŽ:û½×ܲÁûÝgP<ÙïnOHŒýl¬JŒý^~=ù~ûݧ>&’ýÞ2]pâì÷Ö¼‚ëŒýÞÞ,Íg¿uŸŒ~Hô«Õtª#ÚM¦â5U\B-'¿·•G7ÒÉoáTm$N~o%-l}ì?¨Ø5êìÿd, ‚ß[D!Ó~V ÷ä~Ö[Zà ü–íºy‘ß[ ƒþ÷-8û«Þ¸Ï‰äÜW;ëÜW«0ì{+Q¢sbß[MX3'»oªÿê«·Õ©ï-rèÖ;õ½ÕÄG§>kŠÔáØgõpÏ>Mƒ%(šT7¦Úý|¨E‚NÖ_^dØ·pĉÛ|Ǿ:7û¬¥§bß‚»6û»¨ÁjaÀ3n²æ×9'?»¤$'¿·ž¥eè·î[A‰~¯ gô*`I‰qSg?ÓjˆôÌÙ§½DhÆ~uF8ûÕpS‡õ 9ÕÑqöÛÊû™Vüdö{µÒéO²ŸÝ©ÃJSu˜1ßÙï­¦ >~§â³¤³ß‚G<­w†~Ë´ýòÛÚaÿñ’¡Ä°©Žž£ß‚ªÔègíˆ: ýlNs{ëè÷Jâ»øAð±à¢Ä5X:COôËå€ä÷6¥é$?Ó‰¶1'¿Òa’Ÿ­³ZüÞzFØ›lÊr ô³d G?+qWô«-9û™RdÕ“*<̆@ô«#áè÷Ñw¢_™D?cnoýìYPãTáÖI^C?{6:ì€Ø0ȼwøÌÓBIô³iµªÁ¯ö¥Qƒ[gˆ‰~XŸü§q“é,æ4n*ÉÏަ“Ÿ 9N~µ¡ËX“ ‘_½GN~u 9ùY÷É©N~¶2ÒxæäW÷¢±à’ü¶¶–þ^#˜òöÏßÏ5?¾‚?yÌȯêÐM‡™Nn…G&ù½åŸ!ùÙ­&öùñ49øÙ$;øÙÓæÚ©Â#÷ ‚_~¦g‘ƒ_½Q~õ†üªÚC*Ä7¨‚ÞXä¾ò"$÷m’é{ ¹éû^½‡¦ˆcßÛ’ŒPÄ>«††³Ãw@ñÒ õÕUÄ©¯>< ¾íšËwqñdO*0õ˜ÐWïCŸ=qDd‡>{Øòí{ \Uèj»=eÖs ?õ¦Ä5h%~ö/s$ òìv…¼¦€NAyïj·ª“ç:†^ áä‰s&¤3:yâL:Mwƒ§™åëåasɶHy8ÉÊšéæyèK¡(/i‰òL@.0çwÄP À9äá°âÜÌ{؉ò;¬ ïˆÝ !otå äÍ6£‡<„­Ñ!0vm¾yÆ[‘‡»)—MB^Ós#È,P ƒ¼Õ] y÷¡$yiàSJ Aö@*CÈC-" d.K+ !¯‡Ç¦,|0Ñ.HÊ»"0OƒìyÎy…âd ;ÃÙœ—¯IqŽÀsÇHλûõ}Ã<ìPø‰\6¾[ñèÓÆ§ï¡Â“´QÂ7Žv5öÿ T•‰ Es ÙaGEëÝðcØ,|,"ä6(wìÅR …7)md°Qo6¾c!¡¯ÏÀ6·ñ¡é%N·ñχç1™»2L|=ø•V> „Ü@iåçk:gº•Ý¡V>¬@1Nœò†™_263Üqè@I+:'®s+L&¸‘/k¡‘ïx”AF>dÇØm|o-k·ñÁ@gN·ñÙQ×âÞyÚöÇH_?iâ›ñb¡‰¯hM,E|eÉȇ"–q#ðJ#¯¶ÍÈwÞîA lÖ²Ò<6qH&¾ò三®±•óîshïB r†ÉæÇþc·×(q ß¡ïDzðõ½Ü‡ÜRòÚt :,M·ða€™Tá|&ÃÄ7>8ÏœºèÂe&¾je£‰o(´Q˜ø–ÎhËÆ—·_6¾4‡6 ¸ JñÓ½L|=6•4ñcM|¨†;\™øÂVì&¾¢¶›øN­‰aâË–iâöŒ—¸…ïœÉl´ðÙ)&—H(è2ì z%½·»WxŒÒÆ——´ñ#*m|pÓ$اW2ôªO¤ü:óæ‡_g c›øðxñ"ZøÒ—¾ê*ÇT™êeáÃj •KdØTiáKGYø0z±ða×%Ô¢…/­¡²ðWXåÙÃVç>˜›[½r¾D¾rWdáKWZø0%H¯áÖ–WZøà‚P9¯š›ÍÀ‡\hlZ>ìŸ(‘ 1X2ð¥ñ“¾2Ä2ð¥9œ>.`aÝÃâÄK¼ÿ¶C%7Ñ2«…ÈÏ]:ña’ehÝÃI"Z»·ñ•u/휲îÅù¢°î]GØݺWÖY÷pÚŸWѺ'ÿ0îåÈи—šVA/M³&W’¸¯ãvUî;•¸2ÏöÝ;÷Íç‘e5¸ÁÒ)!÷E"q¶Y ÔGî3ZÙ¬{X¸öã}x˜{˜Ü—™Þ‚û°zÐ.ðÃÙ†c³î!xs  $lñY“à×yŒ„_g>øÝÇF}x–h!õ¤¾Î=-‘VEî÷ˆ|_–Ž|ŽÜ®wè»Røt[ ÷‘»·£}köð´#òe¬qíC”®{³ëMø»RB»Þ¥;둽·È)Rà–ø¨£À-¹.ˆîÒ/™[ò tDnÑ×$EnÉ'&"·ÀªBj¤ XK)Qä–¾[ôì3´\9zz_qºîàÚ¶ÒOó¾,oÔá}¥sÀË"·ÌøÍÈ-±ÚéÔ^~Þ’E¯F„¡=NmFä–#Α2 -zØ<œ•ñj¹e¥%u_yFn‰8 ŒÜ'."rKÆ·Pä–8í‘[àˆÅ3zŒÜ‚ãS¼Š‘[ΨEDÂÖ†n–Œ{òÄw šôòÄBDnÉ!<¶‡zdö³È-§Ü˹64¶Ã¨'OìciÒÃ)24mzí?]EnY-„<Ä¥X²àý*rKöF‘[²¿¹%¢ÑЪ‡²Zä–3Ö:EnÉûBÈ˸‚¼kF‘["fGDn ¾PäœÃÚ¬z¥-Enɨ"ŠÜ'R"rKF’Qä–uoW¢)rKÆ "åÕóø^Fk"å•y‘[úåA+•aä–'au|›½ óÊóJt&ß[áW‘y"rKX`¹%6Êq|/Äù½;ÌيܧØý_ÆÒ¾|òt€/#:é:ÎÓxŒz‹Ëð_jå¬WZbä–ÜÛéˆ\çõŽ]«°ïŬˆ|q{Xÿæ~‚oõ8zÇ|Ø!m°—«PDn‰52"·äÞÍa/æ‰`¯´¤È-±Ä¾©ÄŽq†/bdEä–dâ´âž_‘[âígøâ¹3|9‚ŠÜ÷“gø@$5ý÷N) #·,ψ3|©·ÎðåèÉÂÛ2%Öx~øâéŒS|øþÎ2´ðÁeexŠØ,|å¾ø)¾XqH|‡Ä)¾XÃćã™òåû/l|c,Nñ­øD ߣO;qŠ/âI…/ç„Nñ~ã)¾{FhÓ!¯óá ,ÉŒ¼ %޲¼›:Å±ÂÆ×^ÖÃS|pŽg1ߌÀ1Ò!˜ÈÆ—Ï”Nñå,–‘/ÞU<Å—wWÌ÷Þ«µŸâË‘ óeD¶8Å[+éF¾ˆS§øŠänŠ)F†Ò)¾|æeçËÔ)¾ˆåv>8ùè˵WÔ—±Â·£½»/gŽNñó)¡/ï¹ì|9»"R­b}Ä)¾¼Ÿß–kdMŸ$Ü›»/ÒPë]a}#ë]ÒåwÎèÝa¡Ìfrð$ê+0ÎQo h” Hz#R+Dça};èÙ­„W$½<ÿæ¤g_EûvB¯˜[¸ÄS±9o>/uèdct^ލ‡W¶ {B½;<‰z3"?õòód ^úÿõ.{|éÁI[¾œ Ñ©ôºAzglcHzµ!Ǥ⃤‡psD)‘^¡AG½ª†<¼Eå—é†<{¯Êlw¸dhkCßMH¸•0K¾= ÚÜ’É]QoỲ"}º)…ítS ´Šz&ᘶb÷Sª’ VEY©*$YÕ?&·LËý­îû}eXb%ƒ¹{dºïÈW4®Hï"éGù—ùë«3"µÇ—Yón[ÞÉÿä¬ùígsdZ¼RFõ {©¶R‘$µ¦,¥ªj©¨ËRa÷Z%[]Q*ê*¥¢®y1OIÔEÉVW”ŠºJ©¨ëÁQÍUë¢d«+JE]¥T0_kú»†÷ú{ßpÏþn[ãÆ ¬Hl„;÷_^¥_ä?Ö_þólðo÷_þëüOØ’¾«À_þ[üù¿#µÏ»xþò›þÃô§)õ—Yçz×çù«&RzwGL¤„ýsüKùzù×ÿˆ¿þoþkýåÿ¼7_OkñçõGó(¡hÉ£4C˜Õÿ5þõ%„Yó(=WÅÖ×Q1<•L0ìØ©à^Ðøî…—ýš2sƒ q7Ñ”»7!ðôƒ¦:ƒ¦áŒô¥†b¸…Žz%òúÀ3‹Ç_ÊÜŠ W[™<€aç¥îÚxÄöå ¹Ÿ ¼Cmâ 9™ŸÃ²‡¼/€þ·2GÎÓ+аý\æ 7p²Æ?ûÂbò ]ut ¬þÓ%nCÂ!?¬!è‰[3q|£Õ±D–ˆ«ÞÇ¡HqM;è¦Ïq<_«-êOŸ±ü®¹`Zr€œx'œCÖåsÈg Ò· ¥Î%4 }3|ñ0âæ?9¡Oš ói:-½ŒMÙV,9)©< ×e.CvKüÛ"ÒLuhyê›ó5lu{%3²|Ûþa+×é’ÇîxZ]}Ë(ò=¶÷U'ÑåÁÿsÖw»)ˆšæ9ޏýV2¡B³Ç®ð/eݪs‘;{·(ù‰Çý+fæ\U†¯O *<â‘ΠÓ,G&ñ/º$¯ãWþå®ß€âÕ íöõm`}VðM XhëU›Ø¦|ñ¥8Ÿ®qY|]›ÒŠZhQÆËnbS‚îQªH–®äø¨b·ûP¸¸ïvOt”sÜFÜ&9u&ÂîÁf;þJn°3¹ ác¼#ìIWd*; \J¼”ϧ>Oxç´{kjZ.2[CƒxÚ1†²ÌeéQÊÓ<=.Pm JÔ¦ܸîzfómoI—fÜÕóf2ñ8&ÇaoBYÑ1úxçâàþè;¸¥^Ë<|ÝFpÓå’ÇîˆÃ‡ÞÎçЭ•8âg w„_]Rbφ¢rÜ~ Òž+‚–¶p#’— Úåëö’3«…–DKSÎx1ÛÂ=åÆW³-ÜñÄãÕÜÚ.y¾såsCn»ŸøþîAt&[¹/ņÆÉ»1ªš8¦6{Yû¨Ðj5ˆ€ãk·Îƒñ#EÑ©çmùŽ{‡7³­SŽFx3ûò­WËã2ªÄ²Êcö@‰:èˆcë·–—†#]£¾¡Œ×¶€<ÉÞp~ÈðÃsº4Ø®mý– ö:(…¯ú.‡¯ß“wš¤ÖvÑ||×k YFˆ^Õvxø;{“±žgú®7s³Ì¿àíÚ,²Ë]–ëv¶ËpMۆ̚¾€óÈZC,û*ÏkCþy[À5€µ6ýªpð•ÿ¸äUÁWp®ò ¯ç6Ê}i8£i+øÅã^ ÁÍ{+“«™õY–Ȇ@£î[s‚¼Á9ÌÀ×ü*äª+xƒc­­à:JÜð†¶%*úu¤Ó1$sòëwgXH‘_G8Ì£’_GØR3y‰ü:¨À‘r`òYù½’ǽ"¿;"YÐѯ#“×Aôë8踣l‚fô ôÙJûâ'ôÃaMƒÐ@?ØvÍöè÷îÜ1ýÌâeÐ&ô;nzÍúᵊE~8 ×\âä‡c v‰È{gÛjùÙŽû[?µ²×q‚AØ×ü ¿ÓÌâ}H"bœ°F:³ä÷¡ˆÓ£¸! ¼q_k·$ä>D3±]~pß»RTÅ}8„aÑà>´nîÃÁ}XÌŠÜ×”™9À ìà‡Ã6%üšB¼øôo…üïáØÈç¼u‘V&[‚üÃwÅ"¿®jB?Œû2 ýpÂFè‡s6,CôC·ňý¦ƒÀHök¦Bì-|§$öƒ¦þnüá*·Š þ•Ãm§‚¿¸§‚¿fßÚ¾úùdߎŠþ`­õîˆþp¾Ä¹Lô‡\,äL &ËM‰`ª.Õ9äŠ1ðkc@ ª;2ˆülÀÄ€ø¿Ù1¡f–ö"„ÀCH°é»Q`Ž»(³Ð=UDH¿1+¢ˆOQ`LÝÀ@¼Ö„9ÊÂ@tÇÂÂ@œ)rì0ÓÒÁ[ˆz|a[wþbb0‰x»#ƒ0öwwö¢?ŒƒrÌ:»Ä-|œÄ8{î7XˆÈcyä@tØmšâÀQq ž#&s ¶ð¶¶ðÂpÉSÔv8.¢´έÇq‚ Z¿*"K†œùœóî‰[qïrlé¤C4?ÄÑåSѾÏú ‹ÑvwD5‡%Ø6"µ –2„A¬z‘lÆö¸ÁKÉ\ í9“µÁ`¬•ƒ-ü²ƒ ú¡¡mÛ„A{ž¼ŒÃ ÆôÜ`0GP0ØÂÙG0xŠ­)ÄÙ_"Dƒ˜rî¾GÄÔöÅA4˜Ï¹h0ï¹hÕøaÑ`>X¢Á\6âÁR„<ˆ ¶¼fãâAÜ> „9„©„€SÅݹ„¨Ùua˜€+š/ËBÔã¸, Ì™A ÌÙ$ Œ9@ËWa<´„1`A„hêö2N„M®wA„æ—ä‘ãA "Œ‡$ˆ0¤ ¸7A„›å$G"ŒE.ˆ5;`‰ÑÃåa<~A„e‡0a“{–aê-"Œµ ˆ°É?/ˆ°É+2ˆ°É»2ˆ°É0ˆWÙDX$$ÂX<ƒce "Ìá6y/¢fr¤a¹ˆDØäÂD˜÷\Hˆ³§ÎüBÂØ_æý$âÍâM ãõH˜£,$ÌY*&lòi &D™éÌJ&ŒGäO$WJ›`³mtÁÂç`H£4 Þt¾M£`gb‘VÓ)Œ‚§í†QimØÂ('DÃd3 Û„Qð|øu<Œ‚hŸûÂ*ˆ^‡¬‚#qnhˆí¤-+†hËM~DCœávûžÐ;ξ¡!vš6[ QÆ–ü@C@ѱ¡!¬£Ö`ÃØXŠ :ðÜà›l‡YÁ!*¶¥:è0è&è0ê :Dãöæ@Äsgj ê .&>O@¼¹¹"±)1ê @Ô^8Q”€Øxö1ñ¢Q7Q5' 6žyN@Œ«•¢¹"U/€(¬ @l4½@¤ˆ˜<„-bLËDÝõˆaÔ Ênž€xê,r⩳µˆíÓ8÷¢bHˆ‰§Ä`«D] g 6@l:´+@Ä‘ sÄ¥œŸˆ§ .ˆ§,wˆYF€¨ù€x*¿s¢…' †¥N€€EˆYD€¨';QŸ2õ±%1Ô" Æ£€ˆh*÷f'Dã~³£ƒˆ§¢ FYë™ cOYгub– Fëý˜ÛOâ¡ì‡ˆY†€ˆ((<H@Äbþì€_ ÈÛ'@Ìšˆ¡fböG€j žº]€÷\€xdp âˆq¯c¢ ƽ @ E ˆ˜(Š'à€˜+Qbô/ñœyTÀ7ñ` Æ, @Ô».1k êå’€ZO%u@<—âä O™œˆ!@Œ1 @Œ1% Ú'a ¢öô€£,@<ø¥>1+ üB€˜eˆ1wá›åÐ&@ µC­Ä˜•ˆYF€˜bL§Äè!ÖØ †x´üña¶->ŒÉ|mƳ|7ø0¯Æ“|_ö‚›Ÿg‚ãNfëäÃXÿƒ5ɇêNða샋D|¨Æƒ¥gòáÖ@ña‘ó*ñ¡åäCNòṄdâC}÷L>ŒE9ø0–äüD|˜ÝÆPê=—|¨å"ù0%âC-;ɇÚ$%ž a‘||¨‡&øPS'ù0&Jða\$>D$6¢ùIܤ|wX|s)ø0nLða‘ó*ñ¡ÐäC-ÜÁ‡ÿ»ðá¯r1&´¤‹¿Ï„73™ðàÁ¡`BÜã91!N•žÂD7ª¹ÐÎÄJâ$£ý7Óko·ísA !²@9z -/”• káÃðei-|ÜÚ)"Ä×Ek)ˆÐÏðm¶BOy<˜×ˆÔMŽa*<¹/m…Šy¶BX LÆB¬a››hT“ÖBZÓXx0±c •& {áÁð¿ÂAÔb~/‰ƒXè¿UÛ|+0˜ ³Á ÊÜ ÆUƒ°½>›—¨¡É·Â‚! b® q›ÜûT(ˆzÝ(Q¾TRÜ·RØ—: û¢ˆ¨/õåMõåE„¾r¡/ÇNЗ‘ùBk!_ªDäK„|¡@ _4È-¯\Eä+G¾R ‘¯!ò…N|14|å*"_‘ù²-!ŸÆ&ˆ¯!ñÅN7ˆ/ñ•«H|Ùe#¾l‡À—ðeò^ÌÅà½XE‚÷²+â½"!ïe=â½"!ï y/o¦x¯”!ï•¶œ÷Bá^é1q/%Â=„ú Ž¸‰CiO3V°—¿Éz1ƒƒõ⬗õòõb™ÉSÏz£þ‰TL‰}§i¶dn•ôEØÃ/9‰"ÃŒKè%úb÷ /Ñw‹M”—($öI!¼DßÌ˘—è¤{Qz‰.º°¤—èbî ô½iO/Ñ›®â>Dp„÷Y8ë Á¯!øu0ÀSɯ#‹} úå·F¡_'øq@¢_Gî·êýÒ±•èWŠý:Ö4·:ý¬b›‚~ÄΜ<É~I\Ææ(z<ÿGô˶…~ˆÑ7««hG¦-w%û™â¶øCÛ¶âþJÿ©•à/ËþLOg0ŸépWú³A¶/4¿áŸÕÜ«%Ð%ï9þyÀzHÐzhÐ%,=$–þ³?‚Àòš˜õD|ЍG˜vA M¹«ºŠæøSSA`G2ß–ížSSA õyT´'ÉßåNÖ"žS U¼Ym0ŽŠö‘ȇ‡hÎÞ³ºŠZ—ý#/90Ÿ6q`G,|7s­ƒî¿F´2Wå@“¸+9°Jœ­uÿTíØ‘ó÷®çMâŽqäÀÚ”s Ý¿ÍUÔV¿ëA“¸?–ƒ`®3"Áb¯ vÌÆQ-¹¤‰_IÛ]EKI‚¹|ŠKwH‚¹|Š«ÄI°Öã$X% –»Õucèâé$X.! V‰“`Gb-Ÿÿ$ÁWBë½HÐÇûH‚epH‚¶ºzdÐúóTWÑÚº“ IýÓH°<$ÁrÏßî(Ì*IÐF«WWÑZ±“ Ý=…P7|¯ÊÇà$Xk6´H§Jök(hoCš!í¢ÍUÔºsÖsƒez‘K ƒoy­f%Ð4,Ïi°Q‡EQ§C«æ¨xX4'–Ɖ‡Uâ|X»ã|øŽ£¿G¸ ÄÌ6£öO7%ö ßÏ«ùoÒ•N8&³oqbIÚ¾ÕGœ˜Å,²'FÎc'FžÈaþk læ?䊱ùö?lƒ<ìWg6ذÿ]Ø;ÔÓ‚/Ù]Keÿ³Üºf…“ýïZŒk#à…W¾ñ› €ØáØT `?ÿ‡øæö2‹½=ñ¦~UoOmº{"WwOÕØÝþ¬óNv÷”ðÝ=¯OÚC*ñ³j~iIwÏ‹Ÿ4ÓßpWÏ‹ûþô÷Ô½ìïy1ymú{6k:|¾Ë"ÙNŸø´ÿC™c¡=œ÷œº >u4>ÛŸGÒáS7OϹÊVOœªŸØfO ìêñé[ ö~nÎ {°ÄÑCÁn¾/°·ã¥üªgÿ€ á䩳ø­ ¶"ë½»kë!kC¸õv¬¯qY¹îzö¯Á‰bÅoþ>3\L(~ÅBůX¨ø•z¨ø¥EŠ_±„âW TüŠ…Š_ÞJŠŸý¬ø ¨S$»PüÊUTüŠ…Š_±Pñ+*~i‘âW,TüŠ…Š_ö‚Š_)BůX¨ø•‹¨øUK(~å**~¥L(~Å@Å/-RüŠ…Š_±Pñ+*~ÅBůX¨øe¥ø•2TüŠ…Š_¹ŠŠ_)CÅ/-m[*‘âW,TüŠ…Š$úlRñ+*~å**~Ù<)~¥Œ’8¤…Š_±PñK‹¿b¡âW,¡ø¿b¡âW,TüŠ…Š_µ„âW,¡ø¿b¡â—)~ÅBůX¨ø ¿b¡âW,TüŠ…Š_µ„âW,TüŠ…Š_±„â—)~ùˆ¥ø•2RünþB¥âwó÷ÈŠ_¹*¿R1¿R„Š_±Pñ+*~ÅBÅ/k–â˾(~¥ ¿b¡âW®¢âW,TüÊUTüªå‰µ¼Ó£BŠ_±Pñ+QñK‹¿b¡â—Í‘âWÊ(ñIZ¨ø ¿b¡âW-ÏÇZ.ůXBñ+*~¶Xñs“­ø 8,TOÐj¡âWê ÅÏÝŠ_)Bů܊Š_)Ců” ì«e¨ø¥EŠ_±PñËöHñ+*~å**~yw)~¥ ?¯ÁVüŠ…Š_¹$À¯ÞšŠ_Z¤ø ¿b¡âW,Tü²ÁRüòîRüªåñZN ¿b ůÆíµœ*~i‘âçÝ?ø•«BñË^Iñ+E¨øUË㵜*~¥*~9:Rüü¢—DNÇs͸»ÎÒ+‡’•¨DÍÈôQ(¯ÊB?]ö牜ÞAˆ]–*¶¡¤L’-“§¤%S&£Ço†«’¡VE[©Ê–¬ªÇVú:ÿ*•LCÖÀ?ÿÝÉ›2wÿ£äM÷ãÔKú'"NîÎoó2yÓs»€þ‰˜Ã·ó‰|›)Tæ¶$oúa^€LÇ’à‰õ”´L¬¨¦eRMYJU-)žTW¦eR]%-“ër)×US<©®LˤºJZ&×åR®«¦xR]™–Iu•´L®Ë¥\WMñ¤)Ó2±®š–É/ K©®%yÓ1p²ùþ9yÓõ›äMš[.÷sò¦?*ö™¼éOªûœÜPìú£b?$oúóõðß–¶Ÿ–¿üô¾|®ˆ?¾0ßkúÛy“Ÿæ~Ì›t;oÒí¼IK>£òÏÿñCj#eN:÷ÿëÌIÿùCõ#þÕÇ™“^ãÿð¿"sÒ½C]{ß2'½¶ÿò¿þç6gN:~Ÿ9éÀ©„ù£¾Í¸„| çúM/€cú·~5|ŒŠOñp°ž§?ßž[ÈéÀ£ôŠ™+鞟 ND¯Þ§#Ã_©Î­Í×…Øra¹&õ¼–¡;õjœTŠÙžñ©í:ïÄqÝPã(ûœ8“:Õ¸·åQGÛñMúb…G¼ïš¯èDÈ·™ÈaãGÐß´f"‡,—¯{ç©s~ª›)Œ®©vœø>Z“Èœ{gž=¾âžøÀ;ó8\ŒupÎX&ªŽ´Óqë‡ xôýDPâ™Ç:ßQDX˜y”|æD\àû)y9N„Éš™ú£2'3ðàSPXZ8U ÁÖ÷º˜‚§3âí‰PƒX÷±‡˜rÌyÜ‘‚gÐíÄd€76žWxþ™ƒÇ <·pª¸ Ï÷AD&‡›ÐÞ5ix”äÄ>bìE…?Ï“NWœå?‘d~ÊqAm°\áSÑ1»æ£:;ñ\ ‹qž7ñt†{ëU&žH…qžO$âÁ<œ%ÚÆD<íŒ[s#ç´,g;˜‡‡ UÎv0 OgÜ·³LÓնHÃs3¢ð‰MÓLãp1þË9]€æöíí4óð0ËÍÙÓð(#ÌÙž“YîÐUÞýÓðôšÇyíLãüJçu0 R9½¦áÙŽ˜ç×É,<ž#‰…󺘅§3^õyÍ:”åá}FLÿڰ ¦áQN˜súL\uhðZÏ$JÒq¡d&q¸é3xBa$z æÎ$ÈÂ2ï­©ß%ÃÅÙÓðôýW\t1 OcØ›)æ# ŠÜÌ£ç?s—ÕW®?Ì£T$'Fq& ó vïÌÂã>!÷ÓLá0×ås¦c:"+ÅŒ„t"“C/Su&i˜‘ÇÓÎù¿pdF›Äܽ>ü¿HÂÃ@¡'^é­æˆ:ï‡IxzÞ{lL£N9x”¯ãsð<Œ—üZ‘"P̳q2O´n4&ày[9;=®È¿ã¥€¨ãÌ_ïï¯Òïh¾aŸ«Žÿx‹Â)*Îgcþ¯ÏgŸgËH=óï ºE½æß¹@õ]˜ç-óDÅùw¼¶?óï(ÇÌùtæß¹ý|f²À¹–ÞQd0O§Ïé‰Ã5sÙ¾í¼ág9ðÄ`5ü*ÏU[íkøUžùwÔ«×ùwî'd³¶Ì¿s?±¶­1ÿΠ{wÛ.æßQk6±jß¿¢ÈÍü;â¶ æßŒ+Ýf¸‰ç+3µëdDûfìŒ6#¯ô"·ý "ÓÂü;zy4µ¹jß ;ß ç±}O\t1ÿΠktƒ´yÝelûÍü;JÏÒö1½2»NÛ&àáÌy{æßá Öci.Ü7Ãg7ü,ow­…ñ,K-'Óïxüpz.ÜïøE½³ï zJ·4ø)oØ»Ùböñ1˜}ÇSàx˜}Ç-~÷s±pßO|7lç®ì;j1¾äÜð“<î±ÇrÕð“<îm ?ɱnëÎðcžëvÞ§3ù6uÓp3÷þ¨f0÷ŽrÇ´1^–YÓ¶p£À"í{§Ö\·ܤhQî#Ÿ†Ÿå3tþÈ5ü,ïÑë{þݘzÇ/~•çÂ}3§FÃ~v.Üo;çûÝú³åunm0÷Π3]kOäÞ™k{»6&Þñø^;ïxF_;ï †AoH)¯Ì;³¹øIž ·g=~’çÂ5qðÓ;§ £.¿º¸p3÷h{bbáÎ;3’§ÝMW=G,Üžä}ØË@ƒ/&‡jú&4¸ÝÝ£ÌzìØçâ=ƒ«M›«>~ü"ϵ[KlÃO²Öîx“ñ“<oWƒv.¯`g¬Ýƒ§FZ{€µ{lt¬jØ}cí.MHhÈû9×nwáÞ®ÝZ@‘ÂmÔcó=×n½Ø‚ÄÒí"W¥{0ÌG»#êl>´xJüÕ”I¦>ŒÆ}-Ô·mü>Ð7]/*ô½ÛÇÂ%æsŠ]!_Ãoiü¾ùä•ép#æ{a² úÚsñƒŽ /3 úò4²¡oCÚ‚:BôŒù }Rµ/зuú: ú»ËÐçhS†¾wÁo„>G7ôÁ;&º.èC†#ÖÔ‡ð¸±5õíï¾$ J؇[#Êû¦ ø(¶ò)#öáw§Òûº8ØAØwlbNaŸ3³ûÐØçŒ*Æ>ÇT4ö­­Øç°ÒÆ>G7ö9h³±Ï)Œ}HÙ³‡…ØçhùÆ>gY1öá§0&†¸ÏÉdÌ}ˆç{2qŸóY˜ûRßÜ—Fðs€ƒ_Ž…ÈªÌeˆ~ÎaöC™éikösH}±ß_¦0ýœÛÀìçÿf¿R áχ èg|=üw—…ð—ÏFð‡ÍDt]ðç!¦?< béÏù?Lάôç<¦¿|T¢?Œ_ÌÑfMNÓŸÓu™þ°ŠÉ$úsr ÓŸÓ3˜þž$¾WˆþŽÎ˜Æ?ç¥0þå3ÿ9»†E|€Îé`ijŠñbDcü€ÇÍДf@'×77>†@'¸0¢L¼X‚ÀR !ÍáÍ ùl8õßÐ9½Dy/Q <-Œ­ì7Bè !AÔãNtþ“`¾5BÁr+¢`)CÄtŠ_¡ no¾XÉ4ZXÈ‚Ù-± n˜K=dÁ|gÅ‚x³bˆ˽‚³ÉbA§#1 zò˜]Æ0èz ƒGÜ2aÐÝ0Xª! –jƒNÞb,õwÅ4ˆz®¨™4è—Ö4ˆ2ó ™iÐ?u¦Ag°3 úÒ4‡Ýà`Ò i˜ý‹i´—¯i¹5b),eWæW&á þ3—ã Æ½0:i‡y?ÿsU6:¸ð®k ,÷"â^±§‘!&€ebw/ <™¬áì p‹Æl fƒ„Ù`aŽˆ0,"tÂF#a©‡H˜OOHèèÔFÂ!¡$ Q±‘HXÊ¢È|«Í„Žfl&ÄD‰y+&txv3aŽº˜ÐaËÅ„Y°Ða’…¥ÌžÁ•Ï p{*\èPâæÂ|ÀÃR†`˜M–2Ã|~Ã,#0Ìw„`è­¨Á0§“ÈÐQ·†Ùd¡a©‡h˜ï‘Ð0(6Ä«{.lˆå!V"±¡øÍ†°Ä„̆Èé•lè$?fC§2¢91‡ð=º¢ ág⻉èÐû¤¿‘<)eÁp·)€ˆ°5‘´+q‚Òô’*oê`´MùwôIX¢àyòëCùéÆªàÜ\¯YðÚÄ•”qΡ ÛòE@ôÙob뜇Ä6vÝœ€ˆŠïEDsb؈ ‰Ñˆ „ XbÒ’ˆ×fø# â,:ÉŽ€—ŠkDpŽè‚푨B@ô""|•É«Ć3;_…ó"ñaÒሇˆ0ßã!êïÂÃö0ã’ñ°Ý"cáaÞ›tˆ%/’ÁSñ€E‡¨&Š¢u‚Ãvs1âF1Û‡˜” ‡¸*ÆSp˜OŠpØbš‹ Ñ’xÉD†9ÕD†h]¼@"Ã6ÊÐd˜W‰ ñ ‚‰E†ø¥Ú(f="C´2."6äf Ê#¢YDE‚a’u&fŸ†»}CôéYÀ°=’ÝÈ…9]Å…è~¬-âÂ|ÅÄ…øñy%.ôÔÎ_ìED®EĸÆó¾?±«æ«+,„_?å9b!:u.º T¬¡ÂÂ|tÂBœˆW—XÈI#&ă ÛÍÍ‘‘[‘Ðà "Ìö‹³%"Âv3æ‰m‹i%"Ì¥PDØú" ¢¹1…ƒÙ:â`¾ÂÁ\§…ƒ¥-ÄÁ†Ïù_…±_‹Á æE¢Á¬X4˜óU4ØbÞÄD;e0Ç\4˜M4ˆ93ª2ˆ‹â…h0W4Ñ nµ…‚GôU¦AõÜ0è ¢Dì5ƒ~ †A¿a†ÁR†0èá2 –ÖËÍ ƒ ßB# â—x[¤A¬éóKasžEtÐà ñ]aÓoQý›oÄÒø*D‹ƒÄ‚ŽËbÄãÒ,èÀ,èÇ Ĉ†À Ì"$A/Ÿ&A9Ìá ú÷È$ˆzbÿ,ô5 zFšý[hô»$ˆÅq,$ˆ9”,ôÏœI°Íé]@пÂÁœlA80ŸŠ8ÐE„ùø…­ëc€0Ðo¦1ã0?qµ€½ªsN s ¸õ¾ƒùP9‰¼0sΈóNbÀR 0Ÿ0g¹íŒ/b@o%Í€XüÂ@ èÉ ˆ‰4GÌjˆ€þU3f¯„€¹’³BÀœžBÀœøBÀ\…€¥ °´‡øe¹/^  Ÿ˜¢½“Ȩ‡Ðs!5õΛi™Œz'Hé« *ÍPLÎD½Ô+õÎÁäSF½R†¨Ç³À…õ/†J¬wb »°, „½3Þº{¸y)ÉõðKc'ÔÃêa¨ÂuDàƒžÇMœ÷âSP‡03÷Yô?Ü$ÄQqž|=ƒórz‹órøÅyå*‚^¾=Œ}F zØ{] ô0Ízî¥8µãß}ŒØí:ø²MD “/(b£ßõ`õÙ4÷ ){?'‡2øíÇΟqßd€€C‚_z7üä°`ðózlðÃâ¸L‡>“òCÜ…ü$´ ‘NbßÁЉ~@Þ@=±yRJ_cŽa“ßÅ´n…üº~H¡ocðò$?oD~þ”è'Þ2ù½7ö<Öùô‘'u¾}ëþ€ã‹#h¹“t>üœ\I胈 }út™ø÷<|ÞÆ?HSq•”>,ãa‘Ò§æ©ôÁÍfÁ?}úM¥//2ýµåüß»ZsªYéÆ=°LJ_t®Ð_JÄVúàLÑ„§ðÖ¤ÒGÌå *þ @¸6E5û"²Q!ÀTËM€¾•Å>ËvÒú6ùA[ëÛvÒ¿µ>„3]Î&ŠYìƒóIÜJb_{ b„â-´Ö‡ð¿_¤=°ØRüÕƒ¨¤õyÈ­õ]‡=>©õáa¬Zß~‹Ý¤õùAYì;ìñ)±O ´ÖwÉÙÛZ_¼¨úà! }×âü‰ÍYO*ßÎ<*©ò) }ª|DZÒ_vÐBŸ¢Ù§Òw0@d*};£¦ÒÇÖIçSXÿÔùv&QIÇÆƒ¶¤ó1;@Ê|ž?–ùè?•¾ùQRéCì;*}x]ÇÏ++}~­ôÙùÃRŸ+¶Ô‡Ä¡¤Iêk›Ä?I}x_þòí·Ò÷^µHèóøYèóó¶Ð‡ø¬_ œ@ù6fOI‘qÙBž“ȧ§Ÿ"Ÿ¦wª|øöº¨|#D¥Ê·ïT%ò!vä*ò)­CŠ||Ø©ñaç¶j|òâIogÆÔø”ç!ÁïÝ;,þž'Bm.þžˆµûp” j!öÉí¨`_D NêìúªÐ‡P—qAßÅÙI}ç##öÉã)±O‹}Úãûàðgا/Á‰}Þ´û¼“6ö%P ûà{gîHWð#¡MðCˆ¯Ê}Ék⾤3qŸ>'÷Æ*÷ñ*qŸG"¹ÄcìK´÷yómîã·ö‚}¢|cßèºHØ'†3öi4Í}~ºüHu"?ó®Éo0ÄF’Ÿ˜Íä'r1ùéCO‚ŸMàçgdò xä'¢7øiošä‡¸_Ëé¿Â‚"¿¼•ÈOÛÌ…üªÀ— ~£ókG‚û”ܧù`î‹©šÐg 3ôiRúÆâÜY.òLÈ‘Èט`A>–òuÆB7òùC["ŸÉ± _P¡ˆÏÏ(‰ïYÅ=~Èu”\‡#0{áºw_w1ùõ¼sµrݺÖÀ.^ Ìu÷®ßuq¢b’¾Èuèÿ³zø‹-…¸nŒ-ü”Íuã9t÷຾µò±î¹wé#Ö¡w‹ ×mâÜÄºŽ ­úp¾[ÄÁ;ë:~NÆz™¿8ï$=E¯o÷¦zì:âfßÅ…³#UTøâìÞ‹˜ÉT`×÷Θå»ì%¹®CD½ªg‡òVÁ®ãW)ŽDì:Î2.‘]:‚Ǧ‚`W¯ ²ë›¾$»y¯^øu?$ýM²ë{—G.É®ÃÇ< ˜d×áüL²ë8ïcA²ëèÞYÉ®Ï0É<ô7É®4d×á!}/¡]5‚W‘ìÆvKê#ÙaJÉh‡x¥ØB;œz=!Ù_GO…l‡¦›`TøìÖ‰€h`tTˆ2×"üÝ¿››ïš–)0‡Yˆ»·J¥)7×Qˆ2Ïÿ%g¥00'¡#ínt),éøw:t|ÃíÐÙÚGdÏÅÛ£s~ä¿ÞšhüwŸ:XaþCÈüE×s €÷ÓT3ëßzˆižö€“éiI]¿¯m‰ò‚$<4„¬‡ßæz„ïÈ›‚ÇPØ{°ù®.ÖOíOü··Å¥³oýÐ CêzÈQÞ«Kç ¬Œ(üÛ.Æ¢ýáðå¾xy!·èáü)ô‘þð3Ì2¢¿}ç™)ÑûÜÕ£³ãa<Å©³CÇm™èoßxôSðçˆýæó«>O},ìÀðû¡š«FõìHIpTö{»y)òg°_G$ ¾¨zH½ûF²_{šŽg‘ý^‹ƒNö{ òm%ûÍ‹F ïR‘ý¦…çþ‚ý2‘¸Ø¯ÈçÁ~y¸Vì7-±ë'ûMK@ÙïµèH$Ù¯Z‚ý¦å®‡øv¡ñ–‘ýª%ØoZÎ*ìMK<²ß´D( ²_CDè½ {Ó’ìW ûMKðÙ¯^ìWÊýª%Øïµ .d¿öDâ“d¿Y&¦-Ù¯Z‚ýæU¡å’ýj=Á~ÓÂ01Á~¯E‘Š‚ýj‘`¿R„ì7½*¾3دZ‚ýK¤Ïyº>éû•ö‘ýÊÍÉ~Õì×"yØW²_-ìW›ìW,d¿i¹ëa¾Ò@²ß,³¨|ÕìWkö«–É~™ªÝ™Ê̓ýj™`¿Yæ©úfr%ØoZF ï2ëyHz‘?'»Eö+÷"ûÕšƒý–ö£†w©5ûUËd¿Zq°ß´Ä*CöËŠÅ~Ó‚ Ù/ëû5Üò,ì—‹ýª%Ø/Û'ö«· ö«e‚ýæ­bÓCö«Wû•2d¿j ö+M&û•{‘ýf™½†w)÷ ö«†`¿j ö«7ö«7ö›F ö+7ökØQa ö«–`¿ÅésòVd¿r+²_½*ØoZ"Ô$Ù¯Z‚ý¦…ÄìWkö+5“ýJ²_©yf ÉÑ"ûÕK‚ýjµÁ~µL°_µûÕ«‚ýª%دZ‚ý^ËMº!ûUK°_ ²_-ìWËLö«†`¿j ö›ÕôÊ~µL°ß,Ã01Á~õæ“ýŠì7-ge¿r+²_-ìWËû•›“ýª%دÞ=دÖìWïìWë ö+eÈ~¯e,>Ÿ¥b²_µûÕj‚ýj5Á~ÓrUö«e‚ýª%د4™ìWËû•öýª%د\Eö«–É~ÓŸ}È~¥Éd¿òb‘ýj™`¿Z1Sl¸LItm"…óoÜÈãzž™îC%j£ByUúé²?OôÂZì³T± %Ýl™~$-™t¨ã@àx²*JU²eUi)UÝ[¼®J†Zm¥*[þÝ©®~ÏD®?¦Bú!‘Qd:jVà/§Bú6k¦}-©~˜#Èq°”Q=™äHÕ$Gª)K©ªZÊu9É‘ë*IŽ\—K¹®RÊu9É‘ë*IŽ\—K¹®RÊu9É‘ë*IŽ\—K¹®RÊ/•“©®šäÈ/£K©®%~3v?¥Bº“ éÛÔù9ÒûL…ô'Õ}Nî?(výv^¯©þ|müÇ·eî§¥ð?½/Ÿ«ã/Ì÷šþv*¤ëÀóóc*¤>” éý×ø_¿M…ôþÿÿí)Ò~–ÿýWS!­wúϪÿÏŸR!µÿ÷©Þöίn )N¯S¯áLvzÒ“dúíD²S:ØÆY7l&^Ëã_øù[}O¸Ó{a»^š_wISñ˜™3€[£óõîåç×]„†›Ÿ€®v2°2ã©ÍH_ŽPËóëÎô Ÿ‡òŽ®‹:+¿8ÿÄ­nž¦Æwí(3èOï5´ÐŸ^3bÖ<”ŸëÙ‰k£?½ün¯kçqjÄ‹žõ\G÷¡¼É“×{“pÎ|<ûºšêéÑ7Ó=µâZõnMéQÞAYócótÏä…ët¨—øk¡C}£:{]Cg!Õ¼ªoáP/_ó«ït¨W˜‡÷ÖŒžµÑcáý! CýÁ¸Êó³vD`a€†™S("°0¼ÆÕ;ê‘B',·¢gEŒ«:ÔŸ;Þ}.°¯†‡.ð[œlH}Íç7ÜwhèOàÓpô¯ Á4?¹Oz|ŒK£C=£—\÷Eú¼¨kø•ãÛô=ÁÌC±#b¿ÙD§y£E¹§Ë@*ÓCçf(²ykøÚLgzE˜¹Æ!oz~ÛžÎ$Ó›^±´¦?Éô–>ùÂ5c:Ô7ê¿ÓaÄÉ”_Óeá¤ÿJÌx£µê  ÷tîÜOÍEZ¸ÓL©gúÔü‚¯Ÿ÷2íŸC'ª)/]ÏIŸz9ë_XC¦[½;/Äûž^Ô¾-M¯z¼ßq«›^õžÓÏ [=>³ÅUƒnõ;SFO™ Brt:¢zL·úËÖKmáV¿QM‡çàt«×ÛÒ·“nõoûæÜë[£[½œºûvÑ­þÜÂ!ijáV ÑÞ—pŸ‘å=ÞPDNõOÜ{Ы>ïýЫ^îú/TÒ­þ¤¿HßwºÕûªý [=~BÃr¶ˆ|¨çг?¹ï}ë5€Ó‰múÖëYM/Àð­ça¾úÖï=Dp†«ÝùÖÓã½#Ài»Ëâ×k«ÖqèŽõ~:×o”m:"ôOïzH°³æ£É»ž'«A9qß•Þõ:DÐgøê^N&tdÍœ'¢trâµ0‚–;Šãq3‚–è¹E-ß ñVâHÔ6׊wûÃZ ühtüšŠè*sýöF0•¹~óœMG`”§ö~Áqjü Ã`ø,ª•?Ïsñæi†Ž_ç£Õ9Œ®žõ0Fo;£géŒLÇüiåPDo'ƒgéÜDÇÉ’Î F ºÊa–޵sœå§¤ããY^†÷×yiÝ`ð,½Þ?ÍX½·›áh:~š±|oƒ>*ýÚ=Ëo6‘sùÖÈ ]â< …DÏQMcô,¿WäÉ_Ù~u†ÏÒ‘¯~Ý Ÿ•·º>ËŠßæç…ö¸×ñ³æmèøiÞGYŠ;~›»ÞêÓ±€¿ |¢ÌÉZ“xwd…ºxˆ'^Ÿ~E-Æíoű~»S/åóLǦߌŸå…¤ÆÏzûtEµãgí-ä-}+˜Í›S¿Ì¸ö a­ßÃgéàT¿O†Ïò\CÁV÷Žlt×YïTsÃo2²%ÞuíAn™»¿êÈÞµœª~;)ïzúÈvü:oåOǯó\»Å;~œ½ö^¥sñöÓžN~õˆYcgéhRÁ³<ûàö×—^Â-e.Þ¾ÀÞ]óGžîcžGsí†þ:-ð8‰sQW¼©øqžK7cuü6Ï•[ÙŽßæã(Sªðü¹ŒŠýyÛ?×í¼bO¡EŸØúå ³×òĺ­½Ä;eFì¼ûRfž›á0è7}o[w £sÞyú°s¾ñË<—m Õ_æÓsÄUíô²=×îg}çî (Oî†?×íjËkybã Å",_{ÅI©+Z†ó•»÷­ÇÁ(mnøîÁÓd<ñýòžq£Ÿˆù5%¿Ì3 >{´iigDÁïÜ ßøež£„.þ肟ĩýÕ´HI€ã*u@€HŸ'à®@x‘?‰@¼óÕ6Ìú-8-ðµ\ñ€ ;Ð@`ƒoØ(Øà74*N—â^`ê2ÀF12°a£ÔClÏÃÜ­À 'T£ pÛè dÜ.Á¦pCý!,¶1§—žpƒöeáå´GþÛ7'3ÿ!•Sð•p{‚õH˜‹E¢?ÌÅ p¢‰†þöÆý„áo{â¨Ùo?è\döÃi¸‘Ø,?ìÈ~8r……ì‡]c0ƒà5Ç´üÁ«(ð^ôÏ£¶ÐŽbœa!ýMï¤YÏÄ?D†xþí¿Î2eþÛoQøhL#ñßôqŠ«€À¿Š³›"@ì|c(D€ˆfß„€ÎaÄÝÇ‚€ÇÁ@ãB@$Ø $:wƒ Ù9ËD€Î„`܇àXˆï.1ÍI€ØÍÇ­E€Ç~ °H€à„˜"À½ó¬ g ³™˜ Äx€Eâ*" ÎùÄãÈŸDÀ ! ók]Fˆ1ž˜mÄͯ¸ˆx`Seˆ€NmaNá úˆ+„gîsu"³Ø¹ð`> ñ šüÄUäAÇÂ5f{„wd tž.aÎ7¡SΙsùbuŸ &œ*BBoÊ̈́ȿ ¬˜Ñ—Ú„èk&: ™°ÔC&tj13¡“KŠ ãÍLx\‚c1¡ƒA s%NÿçÙdQaÞŠXèìvæÂ째0'˜¸éÉŽäB§3†Ì…~'Ì…Nui0Äö 1‚¡'ÁÐIÕ †^¨ †î—ÀÐëŒÁÐÉ/ †È‘tG‚!ô·-,CLž¸¹ÀЫŠÁP¯D‚á{ѳ‚¡ÖûC̓¡w! †úø‘̆ðBÝVuð¹¸ÏÚ§Ppxáèy¯p˜"q0wѱ™$÷QtšS‹ƒR……â 2ãYœŽö_ÿ,Úà<'a¾¤œAoÁŽd$…A,³GO©›âBˆ‡!¢XlÒ;- ^<°·ƒçÂ…pâ (aGðSÜU#a!#Ì…ˆÎ{j ƒüm2L¹†h訴© îŸh¨¸ÕFC¥­Nª e‘!”ö[ÜLRfvMYPq’RÜè­º >¨™ χǾSÄþ>Ê5ÌS ƒ›&°…AÅKeÓ*Ê çÔþ*`A7æˆÀÐ#naPѹRÜÎNa!ÂÇÅŒ" ÝB…pþ 5LTˆ·*01 Ï$¾Îˆ Ï ºB…gìi fD…©Q‹ ò†üTèèâ¦BÌè@oë‚ü”—²`;øÊ q#f´ ÝŽ©'(ÌjÈ„b&tpC3¡£š ý©ÑLè17¦øD&ttë”­F‰ ÈÅLèp0) *Ü™°\Lè¡H]PóÞLè BfB‡,I]p£+©™Ðca&Ì~Z„ñWABE6Ú—!eA9  ³WBBÌÚ‡–-Þ =SôÇz!!~.ˆr‡¢-‡ºGô¤HMÐ!Dëúƒå*i‚-ă9ă~?Š&h 0xÐqžÍƒóØ,Y´,$T´Eã`Þ;UAF{:âq#cQ0ž½@0A ¨µ½H‚ÔA„ù„„9S”^% œÞê z)’ ØBèe.0С¸ST8Ac`ÎLa äUjy’-ð[´@j‚›ÐLš …¥Ô©ÊZL‘°H‚I‚GS”.I06K‚–ò$ ZQMIP·²$h—„”Ùb+‚’û¬Z{”"¨ Š µ½5áST-U$ËY¤N“Š`êV% [Ìš- ÚbIP³Ï’ @+‚¾7Ð{` Ÿ–5X) ªyÖ=…­ ¦X4Áhž5ÁÔû¬ êéZÔ¨[Ì[QÌ;IT¼Î”Ý)k‚¾Ê¢ %@k‚ì·4AkÏÓ"QГѢ`ÞH¢ 0'ÄEÂ_:þÜ߯JUPÏnQþ4|Et‹‚l EApŠ‚Z¥Í~Þ›ý¼(Q¯Ù¯‘óüò Ÿ]O ~Xèΰü²-?\5EƒŸ§ÑŸ$CJØÛççßÃÞÉ$Ïö⬷Y/ý> {W¨çf½¹“‹AŸMZ¡XO‰µÍzúøšŽ Ñ°ç¯É{ý‘ÀHÞ;ð»·ð,,CÞÃÏùêzÄzWyo;ˆ°æ=ÈÆaïq"%Û“õ¦ee½|/Äz˜¾ñÕF¬ç¤zf=XWÄzå*Â^ÎzÁ^~ëì•»ÅVv={IÏ‚½üŽ#Ø+Â^~ ìåçÁ^©9h/¿ã÷J‘{sÜ[²'y/ߟ×ñž¦p/#Ü;WÖó"ÔóGD£^¶M¨—-êå¤!êeKn…VÖëfïϼ“¼?=.B½l¿XÏ êùN"½\âDz9CDzùZˆô<–½ì’H/W`’^N‘^¾€"=¿Æ=·Wœ—r^8AÏ}çå‹"ÎËN‹óÜ!a^i›|?³ù~j±-¾ŸCú1ÏWóÊUÄ<¯ëæ<ÏsžŸ­8Ïï’9Ï?_éüiWTù~j;`ÌKÿÕôý´%HÏSϤgíǤ—ÝééA¥ë§fQžV®»¿‘ )¡/¢§J2óí×.%NŸ… 3ß6¸©7óɯÉ̇äÌ+ò!øèâúyàgvA>2_]?‘é t7_ëò%òañB#_jsD>+/B>üÄž^ȧƒ"yôy0¯ããÍ"ñÉoÝ'ÿ|ôKÄ÷þDÇOmžü»Í2Oþ!¦Nxdúú)lúÍÉ?lSó“܇Ÿ™x¼ÖøðD{~Øu-ÞŸý²®Fð»¶GÎ?œð>’üzg¨,“ßµŸr‘ßu’I~h&‰äwÍù]8Mõüú­ƒ¯"¿ ¸w'ùa±/2~_·…ü$Häw]úä òë÷-K ßí}A¿ëîlŽÐ¯é±B?lYèŒJô»n& 3úõÁÞb?ÌÃ}a¿ =ƒ{d¿ŽÐ¨Azd¿k0d´Ù…ý0-Æ¢ôaBÇDû]¾’ˆýQìZØoÎq:„ûõMgu7¾¤þúξ¢?„bÙ–€ìBѸ„;œèWÑo“ô7w; ý•2Aؾ-'qÍEKà_?B×ø‡À0áÁ*ü»q*/@Žø÷"Ó¯Åù·>¡ïn»xô÷rA|¨1þáå>çO„[{–€ý2Ü‘ÿÞ­¢h4øïn—Cò¶ ‹Ð×û&oPâßÝqñöÿ` g3áv‹<íGþËÖˆÿ:‚JüÆ’~ž}È_Nø×‡\Ö„w—)ñauÂÓ’ô—µÿnDd\„>¿fæ¿wÇݧøo®=Q&øïÝQþZü>a Hü»ßŸÉ±àߌúõÿÞí-ó‘þîÛž–Ä¿þðŒ¯ùïÞÜwgJ!Ã–í¨•ì‡PB,Bü»ñ ò_¹ø¯?û‡ËçYVù áÆXZŸWóß½ñûµù¯7ɱâ¿Þéçnþ{·ZñÐü‡öÄ«,þ˧$þ»/ÆÖ4ÿ݈Tw'ÿa}Ü+ÿåë$þ{7×:ÉGþ›œPFþ$ÅEÄ?Ì¢x3„ž"¤?¼‚á´*úëÏů ¢?<„sQû0‹ÎEîC¤¨Ø½ ÿPÏ¢öåÔþ½4ðk9þ—]ÞÇßM€¨wu÷ÄUçB€¾p{'âNmq÷ÄCˆ$@ ¢ÿ' } #f'€Ø4„ˆ±ŠD"ÀOà}>¤F ö8<"HÌ×_ˆÅŠI€ù2óMÞï®$Ü& €3èW` 0kæª,DÅ1aÉ€9Ë÷µé !!Û‹P+˜{±0(Q;ã]bmä™@R ¯2Þpü#z3âîc9ˆCø#ιõK=A4Jt$"Êé¹xzúÑ­kQûÞÕiÎ6S [uô¼¡r¾‘û}’ðï›ôU©‡Žåô–¬pxuø¦ÎS#?$GJÔ;j$¨Ëí+ê]؈ìõ2R |ƒ*‹Hï@ºÞ@' |ÑRàŠ×!Ø+A[(ð›‚ÁHàÓIŽ„=+&†½û&¥ö:“#ý&Ò ~úéâIÚCºŸÀÑž½k“ööØc܃ïÈW¡=;©¥¾wQ¥ìíÚÜZßÓ§¢Ô÷”@/¾ãWJàÓ—¡ø,JàÃjõUhÏß—ŠÄÇ„T)ñYm´Ä§/Ý©òµGž˜RùÂùÌ´ùìk•ÏIäSæ÷ù”[0E>ìv¿„zÖjRäs,òÁyùäW–"ŸÅQ‹|Ø/þœpa¿Ô+5KäSëRãcä¼Ôø˜c1%>×b‰OI ­ñ1¹cJ|pŽŽj-ñò•Äç·Ä÷ÒDL`K|“3XãkÌÓ’Ÿ]­ñY¶Æ‡#¹ 祯¶5¾£©fi|«…ó°»þpé´n?Ó‹Kçñ< !#‘‹ë*òÁ§+ ŽÇü ‡D©|?H¥Ê·38óÃ&)®’Êÿ—õ˜ß`z*óË‹$óÁEfÕù:ªÑ1?9!¤Î·©z:æwóèqóÃs9懫ÈuÒù6fiÊc~÷úö!N)}[û<懟DZBéÃÙ‡UéÛ~ê©îõPqŒ—•>©2:æ‡-c”‘Ò·_rÙ”Ôç!ô1?¼¥>œY]µ¾_Lò˜ŸòŸ§Ö·ó3†µ>7ÙÇü4Sìs-öÁO6LÇüp6ÊHíÓoŒÕ¾_kò˜Ÿ^­Tûè>*©ÏÃç3~8Ñnš’ú|k}nÏøa[³8wž8tÊœÄ>¸×‡EgüàNÇó¤÷íLÕ‚_Þkžñƒ$øñ‡Õ¼gGóÞ±Ä ïeŸ¬÷ÉI'øy"Yïsë¬÷m‡ô鈟ßë}Z»RïƒÇR”Ñ?¿ÁÒû¼YïóœµÞ·m<þe½Ïƒn½ÏØGüžs=â—o«õ¾´HïË[IïÓa˜ÔûäÔ”Gü¼pZñóXøˆß;ß∲øy¦[õóâjÕÏsÉGü<îVýò*ª~~?|Ä1 ãæ:â÷ìЮm=âç&[öãY¢”ý6¦ßKÝÏÏÜºßÆÐ©ûy­ð ¿‡‘1ò„Ÿg¥…¿m,ò„Ÿ_+ øþU°/[ðóhåÏÎü°ì-ü (ä速ðó‚â~8·°~)ÍÑ?ùÞå?Ä„ ÎÒ¿gû<à‡î‚}¨‡t¦~Ò<à÷l±È~úåñ¿¬FüTûLyÀË×~c'ú€~\‚ÿ0ò‹´<à'Ž*‘_˜â3øå‘¿rÀï ös>¤"ïx3«¼wÑ“"}:•Î¥0g™oßyÊËÌw2e‚™Ï›y!_Fíò]ù€DÔåˆ|}“O¢ÏŸQ|úÒj⛫N#‰ÏŸìM|X-xoÖ˜Ø¡Šø0Zm!>¤9½âGS„"ßW!,d>¬£ |@ï±øt"kahjb¾ï1‹Sgï§Ð‘Ì7î!ßP2RFÍd>¹è›YA³}NøgèÃ÷¬À(A_ÞJЇ Žô%ô9§£©ÏÿL}Xá¶åŸó’ûò*a¶ûœ¤-¸Ï‰Í}ˆRÛîCÁ[Å}N$hîsÂKsŸ©™û v3þ ¹ÏÙÍ}LÏRÀY^B#ø $ ª#ù!Cn<‘Ÿ3–Šü²ßB¿\ÊqÑIgîå,"-1º ÑÉQW‰Ïr…~H~K±Žè‡D»„/¢_ÞJè7s×D¢VrÊ€D?Xâú!fRDœúÁ²J|ˆÆ·"ùex&‘_!ø9“Á̯~HC9àW,¿m?è˜Iîƒa_¸oÛOÜ îËkˆ}¥±–±`’§-ò ä7R~é¹IêË‹}èë¹@,‹s' ÏrŽ–¾xwnûýÁ|Õ2™†Õ»3-b>äâ9ïÎmb52_±ù6ù*È·ÇGtOXú¢îÁ|GâÛ~6ñUK~ðbS)âÛŽ®›|y#jYå=\[?ê¨ >ŒDhÀ¾Rs_1øŠ…Àç^ ùÒ@âËæ‰ø²Û">XîEÞs5¾í]BbðydÄ{Þ-˜÷P˹8x¢ ùn[þ?q/Êá=Ý6‡÷<Äâ½ì‘xo4£y’÷Jò^©‡¼çÖ ÷Ðk9sîù3¸qÕ,ê^ö´‡c¡½lžheA…´WÊö`2V Ñ^v´·‹k§Û&ÒÛq”H¯Ü˜¤‡2ÇÌÅÕô²^Ž”@Y¶ö%–KŽƒ@¯”!è•2½r¯=ÜŠAC z¨æY@¯TLÐËÁè¡âpŸè•2$½b!顿ôòæ=\´åC*Çg9ʇ4ƒ»è•«ôʽ z¨¦/¤Ëz–¯gù¶óT4’~ÝŽzš†køŠ…¤§^½r'‚^iAeÆr˜Ïƒž*6çylÌyî¦9Ï77çyŒÍyåªà¼r9¯\DÎóؘóJsÈy~2æìJôþÕó 7^™ùk?xúù¾ûüØæèÅ7|'g0å+â%Ü÷ˆomH™@÷Ã`Ê86¿ Pdf(Û Y÷ˆ¨3¬õG|kƒenòßÙßÚù1vT£Å·6G#}-ñ­ ‘ã;ô¸â[[±ôøÖæCó÷¸ã[ʰ=3îãà“ßÏfN@ļÉê§<'7œñº§<çOéOà^½êŒom>U?>p.:ÂßÚò;>2W÷ª ßHO9,6íøž›Á”¥OÜψomÖwîç¡—¾SÁ2¶m~k³ˆ6ðYFòÜt?`Ö£k`9å9ù#¼“nÒ€^ Ý,/àš–+Ü,$´­ÓÍ‚j΋)ô²ØOÝiħ6Å@ïPçøñm ýv}lì;½,¼nìORKPã}ŒÅÒèe±ÓI÷µð$µäœevzYà{\Ÿ–N/ “cÆÒG‡'ªô²;ÂØyYD2¤PÌóLž”ó1ƒ)¶z'HqŽnT±…¨e>ß×à¨Âî@¤ˆs¹ÓųÔGÄ\Ð^®¶T{ó(u6fð(uZ¹XðË9è¶29j`h%Î]Qæ‹Å/Þ8O¹X<ñadÀ‹)¼äÂ7}œ¾ÓE‹#~»Æ<õ‡áˆ[ßt°p%ƒþû£¶<ÁrÒ¿Â7G‰c Ät‘“ÃÌhÝ+ü2´îÙš›G©å03Ú {…|™ÞµŽîøŒ3+~*|ä'c\;½+|Ñu„wÖ¦Y/vT-1…ß’ð®À‡‡+,t°PŸpFgºÈÉ™q ±éyÖÁ‘œé_ƒ%Qfð0µ|Çõпâèñ…sôþžl}çajùQ~п"¯:7;ÉÍ]ïèm«=˜©Õ×iô‹Á³ü,q|jzÉylpdâ¬Ï´Ó¿Bn‰ ÒàйxC_‰27TË«ãÁ¯ó^½œü:ÏÅ[ncϾšjð³ï‡ÝãæBüà¨ë\½õK÷ì'Us"½ùUÐ%çÙUËÍéAöŒ±çsyi7œã¸Æ>ûÍ3ÕnÌWE‹‰õà—yoeb=øi¯ ~„}°i=ù“?—óa³[©Ým”‰ö vúu×g€0ÇáÇ-ÓƒËw+¿çÏÑy¤Úê¸ãHµü½ž™ï³®5Ï<½;oE÷¾Ã&︹¬=çÎ3ÕŠÊô`›«÷v†sÆsž[ì¿å„òÀ1¸ÑŸêŠšßN\Ñ–ë¶wëé=VoÏÄÎ ï8¢8½¯]+îˆ~šg.øxžÓ×–iÎHf³—=®:·Ø~ûÑ!UfxÇÑŸéAfÄk_êÁ!­g)Ó§óx.»O»/zǺj4zÇiŒ‘´ò9k¿ñã¼íuZà×™^–SÕxðãÛo:„ÍïGuÍ{-×o½šþ„˜j×-’!ø5³á Û»5c˜B`Ãâ=–Ø ¬GpB`ƒBF lãŽóX‚À׉M@lð &B`³Ü_ËI†!6HáED|-ô ¶g£g„ °Úî ÂB K@à,áÐïŸOÌBA`{°ÞÍ[_ Q3yS|C'VK@àk¹øåXË6|1‹A'¾–Á0 „Ài‰GEÌDQ‚Ài‰ê„À†ß¾é½Clhhü§e<¾·º#æ€ ð-s† ’ ðµ´xz‚Àj™Ø Ô´¸U@à´L:NË· |-¿§¤Àr)°”!¾–;>Uˆg™WVKPàb™8-±S#Ö2AsÀF¡ÀyÐh~¼΋®°–2ÄÀÙä;è,0° 1°^51p^´``vb`/r`­8@p^uE=‚óV^Áñà¬gúTŠË “Ëk¹ÛC ,ƒ@X‹Öj‚ë̓kƒ˳"–ŽÎècñÙ€HX‹ΊGTLXnE&¬õ–J-5–Ž’ k™`²*“ ËZN&,¿dÂòJ–—†TX‹–‰A,,Ë2±°Œ)±°– ,¬–ÀœºÂÂaa.§Âœ„âÂüÝæ‚O.¬E‚ ë­‚ ë­‚ s0Ä…ù:Š óÝ"æ¬VK€a½(À0ºÈ0Ç]d˜o¾È°Öh˜SEhXk6Ìßk±aéÙ°<²a¹W°a¹á°<Âa­8à°ZË`óÝ"Ö[ÖÖ–KÏ ‡¹¨K“ ‡sîÌó΂Ã|±‡åIë½k™€ÃZOÀa-ë…þ$–KH‡+QtXË–á"Ö«‚뽂Ë’3 £è°LÒa½{Ða±K=A‡å‘“Ëø‘Ë$ –©#5ÖMþ ‘ˆJmTUBäñ Ö£JèðcV uöÝ*¡“Y&LN2¡“ù¥LèdX– ;3ئL˜bždB+s– ­Ì¥L¸©ŒdÂ÷ªô'™!‚4%f=!†³³LèC9– •~)eB}—L™Pß;R&L P2¡¾e™Ç£,ú`X‘ åƒ&™Pß «òÃ…T¢ Z%äç·ßª„RÏR%äG°T õµÈ*¡¿·¦J¨¶– -¹I&ô'/Ë„VCS&t',êx`Ê„n eBz¶L¨/4E&äGäT ­R%ôe«„¬¦h•ðY&Ô7÷ßÉ„M`G™Oã§B(YÖ a´Åò`ÊÒõiÝú ›kP=¶>¸·x›Š@ÈOh)ê¢Ô%O§>¸‡#xêƒl˃Ñ|kƒy…ÄA«<S¡8èãÏ)êtŠƒ~“,ª)Ö-¬XL ÅAOB‰ƒ>åâ _ ‹ƒ8@·’:è—Íê`ÞJê û`uPß—­æÝ¥bvÅž^ê ŽºRÆ“:è^XÔÊê \«ƒ>Aku0]ê`ªoV³ZɃɃ)Iôqb˃–~, åÁì¸ôAuM}pðàŒôAf°>˜ýËb°4™a6Y aÞœ a®¸Rý‘Ü a©†!*´À8K„Ô<‰0OI„ÙdI„ù´$¢ë1™,z0,~Ù¶DˆnõŠƒåîÔÑäX¢$æä‘H˜óÖ*¡»%•0C¥úô¼UÂrs«„ÜO¤J˜jžTBËe©JVLˆF_dBŸŠ–LènY&ôL™0+¾u›°LèÁ°Lè-Pʄԅ­æE©òWÕ:aª0)Z¤P˜Z’„ÂrU×l—±R(¹ÎRá³Å2m©ÐÑr-úå/R!W=I…žÜ„ëK,ô/³Åœí)rK±P1,z•±X˜R¥ÄB¯h ³9 ½N±ð4 >\Ë5~ µõü“4Iql¥à¾+°·ÐùL€ý‘f(?ч²Sq¥Œ’y;Ü9E€[£ç£pá:L¸3eàÁàp €PÁVÄD9Rx<Ÿ~¢G÷;Nß’ÿòÿ‹ÿô†%ÿ)wòŸ¢¾%ÿ)ê[òß9<Áü‡së´ÿN—N7Qe õü—Hm7Qe±OTºy ïe7ÑX^ ²…úGÄЄ¾%t' €Î$oDŽ«à`¹Y‘Ϩ˜8A&*–Ÿ¨ü€•KÙ˜M ͉-‹0›,D·B bÚÆ&FèÌÕ&@ü²ÄÆ‚˜âÐ/YI€NcoÌ&‹s0D€9$@Úâ(Z."–‹ùhÄÅB,W‘³çâÀ,#Ì® st‚~' ‚¥² žÄMÍðùÅ©|,¾¢ù°Ä‚9ƒ¥ a°TLÌn‰sv‹³Ñ`˜p0§¥ˆ0…ˆ0‡GD¸#>Mp$‰Ð³RDX,$BÜj[ÜE1¦¡™ ³BÂì‘0Ûg$Ì"DBÜŠ(G$Ì%DH˜THè…ÇHè+FÂÒd!¡›,$Üoúv$úîBÂl³°X&âGŽ ý¨Œ„~0FBO&!¡×W#áq2x"¡»`$ôj$tŒ„žÜFB ‘Ð˃p¿ ÅHè ³9BB?s#¡~Z =½Œ„ž‚BB±‘Ðcj$t¯Œ„úÍ2æ( =™Œ„e#¡'¥‘0ë!æºc$Ä÷îYÆHèš„î—ÐËH˜ ÝQ!a6ÐŽ£žíFBOK#¡º‘POÔHˆu?ö©BB¼YABBß=‘PÝ2bòÐÝ”H¨ù•H¨ñ2ºÉ‰„:Û“H˜W ]†H˜}0f"¡h"áÁùFBO•DB­2‰„ðäXœGQÏÚ#‘Ðãn$ÜFBmíÒ{ôd({#¡Ÿ±‘ð`\}#avÂHè15Âß=,DÂl²Ð/­‘¾}Ñ>#¡ÆBHˆïU!,½2ºF´ ç¸}U"ôÃ2zpL„ys!,÷â=ZʈQ&– ]b"ôì7z@M„Çì‘D(DH"ôh™!~ÇU"B[K"Ì{‘÷ûˆ­L¡‡ÂDè{™]ˆÐM6zlD„ÕB"ô$"öÍÃÿr>¥Bè×ÒG=ä>B¨dÚy„Ð]ò¼Jg½(ñªŽâ2: 1>C¨ÜÙyˆ°ñ9Âf=D¨¸#yŠÐ+‡Núñúagˆ‘DèÔú –]˃"ÔÔòBìó£QÐwJu°ÛÉSê rƒ¤:x1i"d^ù@¨ $) ö]bžDA½oy€PCåóƒz²â?´W"!út—|zPkQ*‚ÛyzЃçÓƒZö¨jè„^òòô ÒäéAåÙ1þyè|xP[‘<<¨mDDRËÙÑ_¾(¢?ŒÃÇáAŒÏj™É³ƒZU|vÐ]ðÙA-h)ê¡øè –Ò>Š#þC"¥ToÕN ³æ«ú€*7ïÀv/(P> ö§4ã!Te8ŽŠñž©ù{¡b²ÌJ€þñ6ãá(?½KÉx`’¶ø€â _‹¨ xXp·¨Uˆ÷ÎòÏ;!#ž·Ë‰x¢ #ž—ÓD<>Í$<ír’ð®óCôÜOÂÓZ“ˆ§=V"žYÄxw‹-ªO l"ž¡Êˆ×u˜ÁŒ§_X#^„ &<„šjEx˜Xaá¥E„í>˜O„§½¦Õ¿÷§üYÝ?o~”HÀs¯MxÊe”„ç[™ðÞæ„“ŸÕ?ÄY áé•7â½ï›#ÄëÏg”7Јwóln"žw…F<„¿^OtiÂóøñ”º;±Ò¾*áÝ7Ÿ· /(£ÒÇ­ExøÕ bá©5¿<Ͼü¬n î·¡ŽWÆsûÌxXÆ¢1Þ}ÉUŒw?ñ¹(O ·’ñ 8…EŒ§üè y³^–nóŠ…˜‡à»˜÷|DйÏÝóð:n%ÌCbç?ažÞ_Sž{eÊ{+nÁU¤“(ÙúEöó†")Ï×”—LgÊã˜òL²†<¿¾†¼·O!%ä Ç yã3PŒVH3žB2ž”Ï7ãáwæ« ž\"^³Ó'O·6áydLxiṓ&¼´òü£dÈË òÞ;ÄrmÉ/‚bWÊóU¦•ä%éλl㺓x§aÞ™ïtðNaļûcÜ0Þµ¡à4ä;cLòxÚ|g¸H¾»2F|gÖIÀã”$<}f-„§»ñ’…xþL`Äóè$âù*!ž>˜ü‘Ó§¿u&ãùA™ñL—Éx&CCž†"!O 6äé»e<×,È“ú’Gù !Oæ„<}ÓµÂ÷¾é1 yüŠžgœ4å9My*SR&%ݵ^à ce§—ï¸Mx‡ôE÷"á!#ÁµàÝuëô™ð®ï›;âÒË¿ëé<1'¼CZ€`BÒ]Ç F– ºsªlÓ~Q£áÎùµ w÷ÌtQØî>PeÂ~qWýîÞtØPp‡ÜéqcÁò1ï‹'2¥E¿».&•1ÜáIÝTô‚îî¶+œ(éî^Å»»rÜ$Úݱ'v÷­ ªB»™õ'+Ðîmwíb»k(6™Ø™öþåÂŽà¬á_ÞŠ™Â×p÷^Î=0én Ñ|Hw¥Ò]¹é‡)DwG›¼Cž¢±èwÈäsÕð/3µUø9 ïú¡ïÈ»—Ïä¦I¼Çй<âÝý胹ð»–øÜL¼Ãœã±Aâ’]‹‚çôWÆ;$ *ávL>â])x‡m_Î÷õ“ûá]?¨/‰î:$žåˆ,ô4%Þõ“ûmÑÞÂk9á‡ôd&Ht×O¿ð–å„_?ô¥^t7.Ýåð‘îÒ»/tçÔR¦»qŸ:HºÃ&0>Í‹îÆØ>;ÝMÁ“Mî0äÏw#ÞÀw;Oý ¸C¯ˆ„„;dÄFÜõ÷gƒr\ÀÝèü$e¸Cš­£F~¹j#f’à=Ý eéÉÂîJwãôÁ>â&d¼‹â;„Ý–ª|WnE¾› DBÖ#ߦ¸¯â»ñ³~™ïámI¾C’x⻾ u!ß½ãöáÖ™£3ù®7}Cß®˜©â;¤ãÙ?òÝ8º‚ºïœ·Ì|‡Ì4¤Bò~yâ#øÎôÍwï@~œô›¿Wtâ ÀËŽ ðrŒxøùŒŒ¼{ÈÕX€‡jÆ¢â!mK°™Ï ÐLxøŽï"< O¬âD”YˆÏù9M|?:Z’øú©À>">¯Ú&>Tž•">ï…L|ï~~²">'5ña^“">ÿ>ña}ê ñáí<UËí½¨zHVS]ÄçL¥&¾-Ÿ3žšør®‹ø¼·5ñy‡gâÃÖ1^F!_vSȇ%ô*Q_ÞÙÆ/_F>¬©át-äÃñZ³$žñqìµÌ”’×+ÃûwŸŸáyî‰^Ë Ùó¤û2ókyé^7pˆ¿ÃòìÓÒ"Ìö¾ánpÌ9CÞ‚Ù„/Ô?·¯eŸŸápÞãáUø†LU&%ä:žÛ¸×]ØÇðUà8ë0RókÁ¦|»½±–ûœß¯7†§{-ã˜g‘ñ¸…%º€fna9£H¢|ÊòLË~Ç®íµ¼}¸âpÎíƒÑ‹Ðk9ãˆ5öVq÷饹Ö}ð©©×Ò[9/óþ=?…Wlyß¿G|“×1œ×òÄùj|" KÛ¶8¼Æ8°<:å5âa6ö@gÍ_Ëü@—G~^ËÙõróµ¼=¸ãª‡–«ýâñMŽDëg¸^‘ç^ËM¡S«-g|ß¿Ÿ}ö 3¢Ö ‘EÂ}‹£ymq¸:ÛrÍ ³^ŽÍÅí£-—zpŠ¿|ðŒ2-î~½=¸×»¿=@Ÿ „ðî÷1ût4^ËìÃÕC zÿV†ž\ß¶°<šÕæU—fDûpF™#^)|&E¯ qò*|‰šo^Å>H2~-[V $ð¸ŸKŸÞ4³|¾}ÄáêrÕ³ÇßOÜûV<¢7ûÏáÞGôªÅÏùk9îèï^ËÙãYµø²øZÚ½Ê2ìþëa 8²=8³-xæà3Õ¹Ì|೬ùj³WÅòö¡/£3²åÁ>”«Þ>Œµ=ˆú²¼Ïö,ó ø×·q|åÍ{Øù†½–¹vg€×‚ÏëúϪiÕ|îCÏŠëÉóö‡¶¹b?êƒgÊ£>èY½‚GBy¦}ǯL½÷>3]ו K¤Ö;YØ9rîxÍ1„B¼ixÂÂC˜;¦i¬á=Ç4˜½òJŠAþU2Ãòüâ‰ã˜¸,úÀŸ¯euMùîŽs’1z;~ ÷µD»~Õ³²¯êóWØ~-êVþ}Wߘ}þ„Ö5|ÇÏawÕX…v¤1¹—‘@èTöi§e÷Ùb9îâôúþ­($_<Ôz°XP[û„óŒ<´ßYæ>ôœâ·`?ØÅÙx-ê~av0ÎÀ;¶ˆ=ƒtj1m¿cÁ?¯åè¿j ×r®‡ª_K«Çú1µÜ•`ʽïØåshc×;oïÞžØ!ê¦,ϯkyæû ãǯE}8¸oÛ¯ƒ¡gºêy7Ý¿ÆÒž«q_Ô¸Ïx÷«õhûûw½]Îë‹}@"ƒ­K}à å×òpgäwèz­ |Âx®eÔû>÷v;Ö¿¸ªGðÚÆ¯ÃûrÎ>ìØ…¡ÅÆ('ÁË¿žåáõÎO'«½Å?ÑDzxtuÁ“¿?ºÙÂroc9ÔÿZvnî?kGlòe¼ÏØÜåÔ¹Õm-ìƒþýî±5ʉrÏøPZYbì ?ÑëÒp«ž&ƒ}Йt¬m· .Èj¼…×rÆÖ('ÁhMËÝÎz®sýaÚûà ó>îcé÷ˆh;ùÿŸØy£¾ãúX~Nžm(†ž} œóZÔ?_~{qÍ5›’IªÜ½|ï+Ë-r`›G bÚC"9ù÷$Á626TA‚ ß{¯J‚ÓÂ"“¢Æ:Ö’`!;ÿÓ$Ø 1‰Æ& 6|Ð_H°Aáâžá`°Gev{@2椨†Íw> Á†çÛ©Á×À|Áeƒp¨ îåÉ.\·(9@pZvâØÄ¨iÀM\®š 8VŠ—«Ô…,3»zμX×£ö6èqKL„eþX 45ß•46ÿ-3â¶AYɨ¥ÀDÀ -vòA€³§Tà,BZj³ñåï™Ò+«˜ð4 ;¡l`ËI ¬•–j.µý_jþ®a þ›e®èPðßr«ÉK™ÉK=ãXK° ­Çzñ_mMðßb™üWë þ[ÊLþ[,ÙY&;-õLvjÀîôƒÿ–2“ÿ–zž=®aîo}¸Ù‡FÉRü7¯ 8ü[ª9CPÉ"“þ–"ê‹°סO ³ˆðt‚S½h²_­ìW/ ö[,ŸíÙ~™ØT‹Lò[î3ɯÁ±ãˆÑ ò[ʨY&; 2“š–›Ojªe@~µ– ¿¥Ä$¿ZË£.4=· ¿¥Ì¤¦¥æI~KÍ“ü–«&ù-eÔ‡¬ç³$¿RÏ$¿åïI~Ë5“üJ½$¿ÅòÙ’ßRóä¦2$¿å^“ü–z&ùÕ«öo}Ø÷¥ß“ü–¿'ù-WLò[,“ü–«¾õ`ϨÌä¦Å2¹iµ<} ò[,{dW,–>€üê(ù-%(zË$¿iáž?Èo)“=PÍÙ[žKßbÙïçäWïu~ôáÌ>ÈrµOK?Õ+YîããIù-e&ù-e²â¨m|ô*Èo±]½ÒUç¥^©L»ÖßúвlMßRfì½ ò[Ê<Ïdzº¾õáÊ>ˆóŽþi9c#„Ó‹ahM ~KµýT§Tâ[®o]ð[®zž àWë ð«WuuA îê¶.¿²?%øM Ñà·ü}ïP€ßbÉ.Øò|t*À¯v!Ào±ý£S~‹…}ÈçfJ=ýøXý~K-cÿxT~«åùèÕØÖm¹¯Þ:¸o±œ×Çô î[,×ùñ o]÷:“À}ËßÏöÑ¥à¾Úà¾Zë“=àUOö@–óZ,#ORŠ€÷¾Š€ï6šÁÀR<t\"`cú߯‹ÜD pÃÖž•„½UÜún’ mëtÿµûJ~³±‚`Þ› œöÇ"Âqc½!ŸMY™ef>6ì6 =`')¢½(Æñ€üj'©¢%U*€[çŸ!ÿͽ-!ÿ•.Rþ«eØþ~Zîë­T:3]õ“xCé¯ÖÒßÖ›ä#J(Cá eÓ)p65}#½Sù+CBå¯4•Êæ­¨ü•æPù«7WTË8²{”ýÊì¢ìWnBÙ¯Ì.Ê~ªäRÛ¯pl´æWÚEͯZBós%!ø•†Rð+O抦g µÞ7¦à·múCÁ¯< ~ÕrÐ{è’”m†VV[ZYy–ÔûJ{¦ÞWîM½/‡f¨ YD]ðS ÜW-!÷•.PîÛ®.r_-£.¤E]ЋMµ¯<ª}墩ö•‘¡ÚWzMµ¯ZØ…œTûJ§¨öåØPì«·±¯Þ<Ä>ÌDZˆ}¹¦<êžœ´¾œI¡õå“”ÖÇ·RBŸÇI:Ÿÿ¿š®wR"_½EHd¥ŽÐørA‘Æ—?WÒøJŻڮ _éÝÔøJ­ÔøJï¨ñUKh|Ù¸=Û¯"jÿö!ñÁ2xUdø¹Ú%ú=¿îº Kâ+5Sâ+cu|taJ|eX(ñÕ+Bâ«×„ħGD}/×é{µ6ß‹›ô=UBq¯´â^~Š{Õröe(îÁç)\$¥¸WšKq¯ZBÜ+ãOqÓñ¬ˆWk¦¸§.QÙ+ÕRÙó $a/w.!ìÕ¿Õ~÷‘Â^úuIØ«eÆþÑ# {µµÏ³ì¤ëƒ:àk(ëy%U¯Lªz¥1SÕ+µvïÖ8¶—ÚŸ¶»(´QÓ+¦¦WîLM¯4—š^™=; Ý=@\Šo!ˆÕ«B˽bˆzõN÷ñÑ)Šz9T]]È[‡VnDM/‹’^ÖBE¿FœfTôJ¨è•ZÔþ,bXÏ)蕉GA¯6.½zMv€õŽìë¡ —= žWz^¹õ¼2àÔór‡+=¯–¹×æM=¯Œ7õ¼„#éyÙ8Êy9tòûÎZŸoí—·¸ÀáOÒ%ÉÁat,îœcÓFS$· ySÉ!µåêÎÇ]ÿYP®ÐQîdæ¶D¹s—‡˜P’õâÏ K§%YnîZÿYPaúi!˵]ø$–+²E³é˹µÃ~š¹ðÏr𠛟Erí21‘†Z7ƒ‘†Ú­½ X®Ý±\{4Àb98Æ‘ÎÔþ,3»w;–˜0T® ÏáÜHÉsYF«ˆç²q®ÔBœËN çr^ çr6 çr^ çÊUÄ93‘»æÓŒ.ŸÂ¹¬E<ç‰*œË #œ+ÕçÚóá½Y:%œË!Î »SQ<—S<—e‚çr@Åsù(Ås¥Œúàö‰çòNâ9Ï=ñœ¦p®´…8WjQün?Ÿ=0Ϲ}ä9÷ÀȹÔÝHuðº%’ê<ÓLu^Žuð9›ïß S]Œ©N]Ôeãusc&Ôù•#Ôù§ŒP—7Ô¹mbº4éÒ@¨ó/¦¡®]ŸPWnD&‚K3¹‰\W,äºl®¸®”9?jÉÈE“\TÊ‹´U0Öµ.¿^a]vJX×.°°®5¹› 늅`ä-‡ÉNDF®k§p ¸Î;s]¶¿eûÙ\q]ޏ¸Î}Öµó벵⺼•À.¯ØÁwŸ|u^ë¢m²óÖ‹d×βsëviPûó6¤¢ÒÜçY_$q]×yçh®Ë×å4×µ]DF,ÊÖÖå@ ër „uYIv@•Šrœ„uÂ&B]ÛE&¢º¼³¨.;-ªË¶ÜÙ~•!Áã­b]Î a!c]©E°EXç¼±.ï$®Ë9/®Ë-®+eÈuù*‰ëJ™ûXmp]ÛM‚ä:5„P—UŠêÚ!ÀÖåM„u¢<2'÷ßÈW”>šʱàBãlU¨{-CîŒá£ù:Š"M¸¨§õ^K—›|4Ÿ[û&9i¾–¾:i¾£² øBØÇcf:i>Ì¥k'Í{{*~DÔmÓÁ&:iÂ"e.<Ÿiž¤Õ½ŸU«[,ᥠ‹`3ú ]F饹Xž°r"¥—&,­×[,á¥Y-á¥Y-êCZz[ÿž¹§¶Cg&é¥YK„—f)CGMœàÜêq½Å¢¤%œ«%œaÑ‘¾ðÕ¬eÂY³– gÍj¹Ïõïq¬‡«c©•Þš‹åùè½5K=×·\ÙYÂÕ±^îšµL¸kVK¸k–pu̯o} »f¹Ý5k™p׬–p׬W…»&,}q׬–pv¬W…·ci!Ý5k™p׬–gíí>¸–û[è®Y-áïXæ(ý5«%6«E}H‹ú5‡Ãc-åÉÐe³”™.›ËßÏdzßú0Ô‡´„Ãc :mVK8mÖ«Âi³–Q²Œú–px\,zu§ÍR‚N›åiÒi³ZÔ‡¼*«%«%œ6«%œ6kÍá´Y-êC¶ø³rÚ¬–}é·œ6k‰pÚÌ'.§ÍZF}8|€/\«%\k=á´YË„ÓæbyÖù&§ÍjÙ—U>œ6ëßá´™¿0rÚ,= Óf½*{ û|ë6«%\k=á´Y,tÚ¬–pÚ,Ïá8îõïs­•N›åÎtÚ,}¢Óf­%œ6sÖÈi³Öœ=ð¾çÃB§Ír6ËÓi³Üý¨–px¬–px¬W…Ófµ„Óf :mÖzÔ·N›¥:m–«è´Y˜׺څÓf-¡>¸ßM}HË}¨WªeìϪ=ÛÇD§Íb¹¾õáR\6k™óc_$¯ÍZæZG”^›µDöAõ!ë}¶gE¯Íb¡×fi1½6K=ý[zöA–Ö>-×ùÑ«é¶Yÿ¾­ øžUÕ{-[|Jì+W±·cûnÇöËD¦ò7±ïý=‰}·£Eûn†“KìË«„}·ãû_¥ºiΚyPØW®"ö•2êCÞ«Üi"Ó}Ú;”؇<=´ûrô„}9¾R&{@.abx®Øw;’†°¯\EìË ûnÇ·ì+õ>ƒ{Å>K¬ê^-#ìËç$ì+W©î·°ïÎH.D¦ a_±û²—¾{T§ÍÙG:" û²—¾|Ú¾Oa_ÞIØW,ľr•úàÑö•«ˆL9:¾aßíÈ}ùÖ ûòšû[„}96¾;£«ûr,„}9ê¾앰¯XˆLù~ûò öeÍ}9¾l°/W)a_ް/ÇBؗ¯Ü‹Ø—3EØwgõ!ÛCdÊ•UØ—O8°/W a_¾‰Â¾?a_ÞIØ—+¢°¯”!öuÅä0öuÇföåï…°¯ëHº±ÏÏÊØç»û|ocß}êë°ÏOÆØçžû¼Zû¯ƾR†Ø—-öùYûºƒöy>û²Â>ÏcŸß3cŸg€±ÏsÀØ—=öåHû²a_öIØ—5öe-}¥"S©ƒØçaìódì˱ö•2êÁÿ!ïorvÙ•dMl*»™·QdüN Ô g…ÛZ[@vîüænfîüÖÚyN&B ÕZßËÅ` ƒÍé®ï‰±¯R„}-…ØWÏ[ØWÏaεg„}Õ*a_õ§°¯¥ûü–ûÚ½‰}=å]WAƾê/aŸß2cŸghc_Õ9±¯žœ°Ï_&c_õ„°¯Z%ì«‘/ì«þöÕU¾z[…}-ex]Ä·UØW½#쫾Hìû~oõˆ}-‡Ú`羪±°¯zKØwÛ/”°¯Z%ìó×ÁØWó–°¯JöÕHöU_$öµ;ûZ¹Ä¾ê-a_õ…°¯úBØWs°¯æa_:§ÿ«a_õ—°¯ÆŽ°¯ÆŽ°¯Z•ØW5öÕ˜öùËiì«R„}Õ;¾'¾–‡Ø¬ËÑ;/¥ûbÄY[Fœ˜„¹®Úw†ÐoeúG+1ZqÖÇ@VœøJÈ 3­8ý”dÄé`¶âœ¢Ã4‚lm¦ §c@Ú†3¾=‹ g«m8óó-,Ñ+´9 Îz‰eÃÙs¤gëmZqÖC£g¿H à×[Fœ¨¿Ž¦d»ˆFœÚJÃUq"(ý\Œ8[«gÁ-y-€]Ür8¯ß) ô…kFZq*ž»8 ¶ùÝ´ËÅ©l6¥LHÂ,¿›øê/5m8Ûƒ ÎVýCÕ÷c¥ §Ã§Ú†)‹ÏÍ6Ú“æ"E ˜6œ lÎ6viÃÙZDNôGÒìL™±>ÃE{&Dà¾=ër³í’kË”W—\±DCÀˇݱDÃ>f°÷K4Ī,æ%Ú]¸LyØ<¤|üpÈm ìd¤ s2•mÊ8Å‘~ùã^Ì‚›ØBås}Ø‚v ›àgž;6¨pÕdõžØ :ΞFNàËUï«Ìã”w†o‘[lhfBÈxÕ„W}üÎøª#Ùð÷ˆ ªžrnÙ¨ºê›…—{_±Ç†”“ר h¼lC=„Ù›ÙÎxU&œ­ QˆÅºgÊŸØ#&ÆÌ6É@vnlÁT䯹±uѹe‡Í„/7òåù–ˆÑB9„û´O>§ºÏsg‹4 ¾/`Öê ÓÜÕ˜šIkð¥º4÷1³I/烹G û/nL„w¸—úílBÕpgÀcÌs=™â:ï÷“6ç´ùP¶êÈYeîï•ò­ÇvæCÑ(Ÿ£šÀ„13ÁåFÌ…>bçˆÓ‰1ö^ðö¥Œäš‰¹öY³°~NãfÞæáƒ~XÂ{es4ȾUÉ©a—å„Ö4sð2‹jï'2Yû©£g¨v.ϋϫ÷D”;þ‘ דƒìáVïÄ\Íç‘3çœÑwä|¯œ©R™ûþÌöh^úêqd{ôÒ|h=³=.3f º>_ª°úU¹ã|5ãeýëùó^ouß?Ðñ\šÞØwG4ááê<Ù¿{øs Ì]މñX^’3¾1 Sßšç±ëEâK}ž›æl%°~N¶ ¦ó¾3erÞü¾¹×ŸÏ2¼Ï÷\¦ìymg6)Åßy©•ÂÔ pÍ‘)eI±}L]ç–ãÎ}uo6Éu¹®çÏ«¿#P•{®l‘¾‰ó[Ý­“Û½Ù ×÷Þ^(>ÅœÛrnÞª¾ÒÍú×#¹ÏMOWïÝד-ª«î[óµ®b jßlß-„y–bž}j²ËݳùŒÙ?Ißâ}™Éð-Ëð}Ô?·ç—&<×óãôÜ·&·üL=Ï¥¹@żg¶É~Õµée øÞ¼cè!ñ‚9–NÁgx_&||†9W¿,ä|õåc{«öƒWÝ\ý<Ü0üV\ý¸Íï{® :¶íÐèbÊ>5Ìòu;65Mü–žKõŽíØ{÷é7¥5òØÎ\ûøö-DM×o¬èÛrlj€ÖPÇöæÚÇÓþ±o\ûð¡ûþcéó­‹¹zSÏûÜÿ\–ßô»÷ôØO/ß&^µ)×X¾Âk›öûþs®·~.=”›å¨œÞŽ¡¸v`Ÿké¾Á­’]çÒ„óY– ½K¿qÔ%—×>Sî{]£ß²5ÛTW½¹ö©îxŒ_¨ùçò¹Ð¦Š;ë_ŽBDÄ;ž¡é…xÉf/Ä;Ìž íD¼/xÞˆw<0«dž+Ÿû”<ïˆwžåÞé¿ýÕÞ>/®ºo:?¤4ñâ´}n ñ¾r¤ñ¾”©ú\Ñô,<}ÿðŠ3]Ÿ¿š­ÈxQÆËû\éú¼•r§ëóV[à3û„¼vfŸwÔy|B^;³OÊk'²HyQÓWeꚓ瀪ÜkÓy§Twñä¼vf†œwÔùgrÞ¹XĦ6¸ää¼v⎜×KNÎk§qÈyí„b€Þ÷tOµûQ4§ôpš°î~Ö³i½oD¾\ôÆ]þË %§|GÐë÷zÕ ½H¹XÎÁóÅ*z˽®m½ÓõªUìÑWm¨{?<#ív&èµ;‘ô¾ÃK’^¤ð Ÿ¨×îEÔûzypmÕ†l'Y¯µ“°·¤\ïZ››g¤«6ÏHWmÔ†‚)µÁ÷NØëwJØ;`ô1˜gòŒtaÛÁ3Ò¾×®6\´{!ì-)×£VÍ‚½åÞÏHWŽ÷R«x綠%Empm÷zË÷¾}Sˆ{ý^‰{KÉç«V)Emp«Æ½¶Ä·ü~yFÚwNâ[RöãG›¦Zà6Mµ RŽýgʹéIñîÉ|KÊÅ3Ò^·%ô-õyÖ~õõû$õõI}ý>I}KÊäébEµ RÔ×%©¯ýľ¥>÷­ç¤”'ÛÜò„Ø×'öEÊCÐÚŸ)#}Ç´”9ÖÙŽÜ·¤œئÝ+ÛÐS² =徕òtð뽓à×{äןC’_ï‰$¿þ’ü–<ÇþãY%úõ{'ú-)×£g¥”ûþñ%ü-÷zÏÏ*éoIÙ×{'þõúÝjCåQ*åÜ~¼U‰Ë®GïJ¾ï?×Ñ~« ?ð¯_•ü·¤ìóÇLþëå&ÿ-)ÇþãÉ<Õ§¸ *÷z~¦Ü÷g•¸¤¼ç™á­6°¿Þj\5×Ñ•¸¤œÛg•¸¤Tt§ûþѪ¤À%Ï{®ó)pIÙçú‘Û[¸ü>–çB \SÞõ­".y~¶€¸¤¼çú¤ˆKÊ>´)9°ß+9pÉó£ »ÚPåžïú¤‚KžûÖ“,>×ú¤‚½œ¡6TÊ>¦Œñ£UI‚ýîI‚G­Íƒ—¿´!QpI¹ïÏ*QpIyÏu¾“eAOQ*Em`Ê&2‘¿tÑfÅo{d2ŸŠß¾½’ÐRðʃRðûþ^FÁoG(j&Äv.ÚYLê}ûP@Ué}ЉÔûp(ƒz õ>Œ3Â*õ¾ž’‚_O‰L†K½oŸ‡É/å2¤´¨÷íØõeBl¡ Âõ>¤HFTý_aÔ¥úßR©÷¡`ÁWÊe(‡*'¿ñÊ™'?¤îl‚ïDÅo»ej'Åkd*h”üú½Sòk=Nɯ齔üPñ‡’ßvÉ`L’_Ï“z™£mKñC‚.¿Ö¨üúïj‚Še°]È””Ëú›£‘’ߎaJ6|ìF梒üç^$¿vwJ~­“)ùµ’)ù¡>ÔC)ùõH~ýš”üÚƒyÕ÷Í«6TmR2«A!ÍVÚG'Á¸wÁÖLi~Ui~(8÷[©ùa˜ŒEôCOl,øzó}‹è»í±ˆ~H«èWáŽ$úÕ{'Ñï[êSB•è‡i‚BE¿z%úµ»ïjƒ¶D¿zÍ$úyZHͯU˜š_¯ÞË€7 ´#ѯUx¨ š¤úµêQõË3g™{í(úUí(úõrÕ×oÜÏÒ1!ûÕ»,Ù¯Õ„²ßŽÐLHÕ¯ª6U{E^•êWU£èOß–íñ¡ê·ï›Ç”ýZ›)ûµ{gý«7 U|dÉ~­n”ýçYd¿ÖK”ýZORöëy²íISö«o‘t¿ú‚I÷ë)©ûµá{d§Zº_}­$ü¡Uû"ü¡U‚»É°7:¹'á_Xv0…¿¯Æü™ Úוì×oªY›S(û!ÏÁ«Rök7 Ýåžþ"åéôwn8ùÅ<)œíaqý—á¯À”îתGÝwö[êrÿˆ{#᯵›Â_Cá¯MM!üµ )üµ{«þ•Â|« s^®‚p6aþ‡2…¿ZIøkýIá¯ÂåHøkw§ò‡{‰¬R7ÛÇ!õmÌåÖþöýÖûEᯖvþúÔw'…?ÌÔi».á¯ß+•¿V™þZ}_µà°&§¸ÿ(þµ›‡ú‡܉ ú×ËMõ¯çIõ¯Ö«RÿúU)žõ”ÏÚX£úWÝ%õ¯®’ú‡Î¡¶© ꜔ÿÜ5©þµŸ©œõRükYRûë·UõO냪~“ÊY=7iû íœ´¿z&ÒþðÏÖ™/R^^¥lÔÕ‚CB$Å¿Vн2)þµÊ¤ö׳¨®ÌP |sŠ=OJg­:ÿçêÈ×âß>v*rC-¨bSü«Q%ñyæ"þõ”÷Ç*Nâ_ë›YM`e¨þ‰¯þYÐ"CT yŽ”WÞ¾Ey÷*È«àU‚¼ ¯$Ê«Ðe¢¼ ý$Ê«/—(¯ÂljòwOWáýy‹(Ým.q;“ò6™|’Ú'âU@:1^E¾ãµz¨òUU^…xµtâÕçEˆW%…x=%ë¯è¥F¼j1¯—{1h•r3(V•ó0žiåyK‡ð ñlzû¨ •gL¥(Ïd@ÓJ9Ðô‘BŒ‡4w}Ô†GvŸj‚Î+ ñú­­ ñ|¯Ýšˆ×ó¨ º9 ¯Õ„×/:7µI)×¶T„×SÔ„ºFMÐa>^ÝÛ„çrDxÕ(!^•,Äëyª J97=)•|¾jU³ëô)#^¯Þs«Q*¶š ëK5ÁÕ#⵫ˆx­d"^uޝž¸¯_UMн.F­«îgÍñÜë+TŒçrÉx¨ÍdŠÚpÿ`¼Ö_d¼voB^ÏsníôÏ_Ey½ä_Ú0îg½æéa…yõ~ òÝ[W“‚(¯_¤úkbæõ<¢$÷1¯_u1°i¥Ü lª¹89¯&Õä¼öÿä¼V_r^Ï3Ø´R&c›é¾Sã<§¼þ¸ûÅð¦•rßëçHœ×SÞ•Ïjûœ×®!çÕ³4æùÖļ^Lb^¿U5A« u•8©J~.5J)/#œòó— ×~ª hlÎóGUœW¡zzõ™èµ;ôzÉ×ó㱘ôê^â¤Êó:¢{&˜ôœ°Ë}Hz=¥ZÀûÜjïCÒkm"éUt^‘^/çvLú÷éUžjÁ±Øx¶»“ôZ9zýš9Ô*–KÔ«P¯B½%ÅË9¥\ϺÀêµ–õZËÉz­œWm¨µÁW‘õZÉÁzý÷Á‘¹˜¬×¶EÈzýNjÄ õZ£ˆz=å傈‰ô¸¾æUU„yíŠÉš óê⼪»8¯ç¹žµ5½ž§*¯<ï¹.¹zª=1¯gc}@¼v£ýØ[UûñzþëùÑ"^ë52^ë¦]•'†©æ.„€Wlx­ò¼~Õ±©9‡4¼-G— 5i ¯—{ßë[$Âsu‰wÕ³>ßëïz6rgžþ×#ɾó8Zö/Þ,Josq++ûÎ÷9e#HûΞ’öïó–Æ—ðaCfLûΞ’Ö‘/ì2 i‰÷‰Gißù‚r±ïDŠNä¥}'¼ã”ygàì »,Á8‘E–`œ(ºË©".oLÞƒq"oCÞƒ!$¯"ðµ<>¼ÿ*ÂÒæ³j¾–BàÛäÎÀ§0Ùä½ú©8¤´ÉLØ´×RH{ÕnÚk)¤= ®¢=EQ4ìÕE‚½/åY½žBØsÔcÂÞöXšSê5¡®!*µ«ˆJ-i¯òˆö*h¯åQNƽF馽/a[i¯]´W—öದžj³¨•… ä³^K!ë©£^ËRõççn«(…œÔ®"'훾nÉzu#¢^%ô*á—úï¿Ô_ WU赂^»Š ×Rª÷²þ•@Dj×Ük“…yíÎļJæm>4§èE1åù…3åÁX)o%Êk)¤¼žòêÝá­Ô‚Ê’-Ðp&䵪ò<¡˜ò6´#åáífŠê¯¹Ë”§YÆ»f!"y20äUmyÕ1‚¼VÎs¯9ÞkùA^åäÕ}y-…×ÊQ |¤H·é@º!/÷Cÿj÷¥ðô’ ÏYs†6Úw¾k¹‚<v yþ4òÚU¤¼v)¯åIkÎçÄ}lƒB¿4A×nNÈ«F ò*Os~7¢Ö(cN mÌù¥'eÌÙ®¢!$ŽJ¬Æœ-9ñEb 9qèWјï+¡Ž†ßÝ.èÅ¢â%~ј³êœÆœuŒ9½È°1gÕXÆœà^ECÈv !«/dÌÙÊ¡1ç듆j‚Ÿ¦l9áõ‰E;Ⱥ¹l9«QiËY’-'Έ½hËY],[κ·8¯ÞÙrÖ£’-ç{HÓ•-g«m9ë1È–³ê#[Î*Y¶œÕò´å¬•-g+…¶œ_mD‹´å¬N—-gÕX Wí”-g« m9Ý;&=¿2¶åô½lˉxŸ¤»lƒú†¶œßïWÐÒÏŶœ­ Úrº?mˉ®_m9¿E1ÙrVÙr~k÷½Ÿé‹<[¾¶¾·-'€†J_¶a³È6Ô½eËÙJ¡-çspn³-g»Š¶œ-Úðü¹p_#ÛrbRfÚAbµÂ<´å¬6È–³î•¶œvkm[ÎêÙr¶riËÙJ¡-çWcé´å¬Ë–¦•yÕ¬6lýª­HrÞ~Ç9NËyß’Ë*[¸8¹O½K9¯99¡ž÷=faõ<¸RÔU©ç5çÔóp.|µÚ¬£´Òóš#êyÍm½·\=xáxãØ[¦À^N°Üfôrrï.ˆwÀ¥4é¥å~dJ)7-Ï&{<¹iiyØ€g±Ù<à¼h±ÙŒõSè¤å+K¢´`lw/-*”•oÐÁÉC¿àvÑÕÌB-N„BºhAèaÖ$ñnàø+%·¬ÿ8SB|7ŋߕNñÊy¾ëyÀwå…S|·¤D°(~ƒÍX8³6‰GðÆu-›¶V4L¾CÉ$sòݘÚôßõ”ä£p•Ϋ’PŸmñÑ2`ûÕoùýf«-|Õ×øUv@%â!Ï\y¸ KÄ0”¢ê–Œ‡6ÐæiS^úãáª)Í@¤^r2\ÕRÆ0äX )<OÊCoÉ6”mpÿ ópïm1ÙD9Ûb²9`{BüJ̰ž ­eb^x¥Z0oìz_Äy4„"è¡dš§èýÔGŸ tã„ ×ÚIÐÃ×bëG÷"eö£{½Æ$½3"ZS&é¡wtà/IyˆJ$=Ü€‹¤¡6¼2ø ÔcÓú;Po„ï®ü¨‡Ô‰zH‘ß•d=ô—†³Z [O¶ êBØCÊ.´Û~<)Âú˜ HÂ^«!a¯õDÀ\'ut/jÇQMØû1aoì¯m0öÚÓ%ìµ;jÁæ#wlAµ’°‡’…vIJ½œ„½~U*z=%Û°kS°×ZIØk­"ìá*¾á„½Ö*Â^ëaJz1,I¯=Ò^¤½^NÒú]Ö¦I{m´…¦×FÀ¥6<²>½Ô†isΔÄ"(å¹”ÄZ«(êµ7‘¢^{Ã)êá½{óM<1bJbýª”ÄZ¿SÕkotÈzm,QÖkóá]mØÏ-èã["^ú­CìEÖÃæl,N8#X 8[«nµáø!ëµÑDY“ÓÕîõ·<-8ñÉŸ©êáÁÈ3U½6h©ê¡2*¶šÀAJU¯u(U=¤Üöú¤ª×ÊyÕ„Wgd©êµáOU]Ê=”PõöoUר^3Öu½ÜTõÚtGU¯µ\œ¯ðÃ$ NY,81PÄvI{ÕNI{èåó?´à¬•Ú^†±8p©WSÚ^Ï“Ú^ Zi{õ¤í¡'¶~r/RDe©µØŠóùáÁe`?‘Ä•ò^ È”÷êE”Â;ůRn^C+Î[ÎX¨ðÕ, …¯†¾~ùzJjdõ&JäCB-E>t…ì:SäÃàj÷¾ßC]<ÔwE>tlASäØž#Ú¥È×ËM¯=*ê|(‡@H¯uúTŽüF÷E¶Ù¼G9×ýÍÁ< Ã’ÍæsêÔm6…̰Íf+„6›_Ê»xâlÅP±/óZÁ2Ù±/ˆ·=÷Ÿ áõ,s­Kªx@_‚508ŒYæ!Ï*âUõ%â}YîÕj³¬ú;E"^]%óÇ*ⵊxíªhBËQMð1¼ÁÚ5ÁZêx-…:^u…t¼W¡B¬ãÕUOµAy(‚U9òZ …¼vÕ¹> y=ÅmÐ5”ÁZê`-…¼Ê#!¯òHÈk)¿´AB^K¡ö2ô„…¼–%„¼þûU£t£j‚R~i‚¤<§XÊk)”òTKy¾¹¥¼–R-P1TÂzÊ»>)Jyí7µ¼–B1¯¥üÒ„ý—&HÍk)TóZ Õ¼–B5¯ZµÿÒÉyžK¬çµ«îgýM=¯•B=¯R¤çµ¶Á–"ôZ bu/ zÏeóO z~ƒ-èµr~iøä=ìQŒ1+zÏüi·YeHÒ{†Žë±Ø@\Nç!…«OIzÕIzž(,鵫(éµ<”ôZuž{Íñ®ƒZ’^å¤wO åõ<”ôªM’ôªÃjîE9¬]E=¬å¡¤×Rh·ÙR~´á¬6(…’ž?–ô°L-Ž’^»Š’^µA†›ÕrIzúòZÒ«î’¤WS’^»9%=“v›u‰ 7ëiËp³¥Ðì±Z)ÃÍzQe¸Y7¢Ýf»ˆv›ÕHÙmÖÈ—Ýfu–ì6ÅJ³áfµ2-7«\Ynz%`ËÍ–¢&¸~²Üly¨†i‰aÃÍvkn¶6ŽìX°š0Å 2ܬ[ÉpóaèÚmú¿í6E)²Ý¦Q¶Û¬G'=Ïë5ÛmÖ£“ÝfUXv›Ïf«QÚmÖ+%»Íº—ì6«†²Û¬†§Ý¦ç,™mºÕ²ÚlWÐj!ߘÂÀ¿ëB5ï+—R¬Ì6ë±ÈlÓí¶š÷(Ú‘M7ÝJ›nºdÚn¶RÂôQ+[›nb¯¼›n6ç‡ózJŠyH‘ßÏózžÂZ żr(1¯§¤˜×¯J1¯§ûú;ż%åý™’b^OI1¯§¤˜×Sª sqÌÒòPÌë)cühżž’b^O˜×K©6(GŠy=%żž’b^OI1¯¥PÌk÷šÕ†…ï¬{ƒ {ü"ÄÎùóm11.DŒ|Zü"æX⭙꪿è7—ý ñ‹~©Ž–HAkÑÿŸ–Ò‚EÀ´tH ½(¦µ¢œÒ‹Â%=’–¢2­¥”VÔ5ΆÕsLèE1­å”^Ôß<„µ¨õÁôGõßUéÀúà]£*mˆù±#6ê/qkÚŸˆÍ9þ£L™ág¨šžñ.þ£¸L?,ý:ÐÞ}_ÏüÚ½×N{¦,ål“PÌÙÃ&±œ–‡-¹TR ›%õ I*©ò¨¤%KjA“¢¤2I%U•´„_bI-dR”Ô&©¤Ê£’–àK|?[À$”´UÒ¸¬<,é¿Té¸Ã‰äÿõb*ýÓ ý·è/ó÷?þ~.^2ýó/Á%¦RØEÌÿ³ÇTú÷ß”þïÿå˜JUÿS iÿËýÏߤ)¦Ò¼þIL%øÃcËóý‹¯ã«œÇ;ré…ýù“)\>Níµ¿3mÁæ%«©÷Èõ/Äy–srGpjký½R߀²Ü„~ïŒÿç¼×ÃèÑÚGþéß{±"NÓÔoŽBP¥™)˜1|0G´áü!Ævàý(„è¹ÍØK{¶›âË·\޽´ûÖI˜p.ð5 .¥Ó|,N,~Mz®ƒòÕG±øÞü™µ§L¾æg¸¹¯_²Ï}‹4XbåÂ,Ü}ïÓöÞ$ŽsÛw›qQ L'˜K_šG¥C¬/åëƒ|Jçž À.áÉrÏØICÈëeÏ=Îr~õ“¨xîwlâÙ¦0pîOìâ„ÎË’£ ×¶¿¹aâÃ÷nÃÌ9%œ¼‘rèu(G_£àïé`žÈ­£6ß8ÀÚ÷»fãñ†sXû^èÅ|øçˆ&\–M¸°C™ûç¸Hù†p*"çˆY肟>ïñb3ð‚w>¹¹íѨ‹»çd`ò¥”hö‰¾úD£°{Âbæ“O!ùMËÆíÐañÊ#KÉ¥yD£ŽF1ê÷9Ù‚Cv6çÇÚÙ¦©!ý‘l´éÚ¨<ÓÇžm’÷¦ó€?«¥ÿŽðÉqâ/^Å&|SåùšpÁe]jå0ŒÃàó`ÄBî|ˆÌº1劭@8ÊÏ×ÿÌïìùÜ:5jhÁ%=%ÌÂNÜYÂßù½·Ñ¦ïûž’ñù½Ñ&„Agžý6½ÏŸÌû$4òÊ‘ソ³EKùZ-Rç…spSàûyÆCºµÅsž÷éõ+w>3¶Ø™çÑ¢S1{ÏKõßœ’õÇáöÔâ¾”7Z´ÑµÔy'4©¾~‹­;[tø"¸>ÁEô6óUe|-˜¼D-Ð$ýÍuØÀ¸ä¬ï…½[ôå£ñq½Ø¼à7†£áÆä–SOnóž÷¾ÅSr¹ü¥d ð~ä¹³ ðÒÇqÏØF{Ï›&Ð_‡ÆFà‹,ùŒÀW®s™­îlÀv{¿Ù¬û˜òŽHÙåûOlÕ*÷ÀúfTDlä‘£¹·x(»¾)O4 ŸÊƒ¸JÎô¾7 bIb =L¹ŽxN˜(x¯oÞÿ:F± bbÝsåÜù° ›|XÅ&žŠß¯wß²Qž¸1ó9 8›âDå¹<]|uÖùàe¾Å<§û—M¨ ¿8©ù¨ûžID:…A;ðû(£Q7ÕîŸäxT2õ¿ðIí-½65A>ãóqä“ʾ¶»h±ï83eÆ>à3õ\.8º²9Ïû€Ï!‡tצ&<¾ŠMøº"-2®Ø>C£¿Ì_]ñEÓˆÁ/ú:íBh¬î †3å̵ܡ8èßGƒŒe„rl çãëx¸=¹`¹`ÐÍ%+o~n[¢¼B”~)onTÊŽßCoûÉÌ—«ÿëd °EÏbÐD! æ9CE¤õ—y®ÐDkµ|}_–h“á×ùŒlÓ¦7ùdvÙ]ßhÈfÕçÊý |RR¡¹®=4Q7dß|Ãóûùj}uá³¼#EU®+›ýb²ØlB™ðA}™2åVï;TÑçQ,¬ëzF.ºŠC›%°@HKÈ]¢ 9’«o±|ŸŸ¡ÃÿR%1ßÄôØ¡ï[’ ßúî×î}8ž” É|Ï7Oì$¼#%ƒyʨ(™ïxNû¡Kæ;ÐxúCHæ;ðlh5–Ì÷§ñOæû²j¢ó•ö˜ÌjãwŸÌB—ØU€Vb_L û`<%ºLì¼ öÅ>|~‰}ó1Õ‘üRcþ«ÀoâT ¡n[ã™’ûb]y‘½À}øsÕGì;w¹ãöa™9˜'pÁ—¸–صvòû®“Ó€¨ïÜ/4õÝ›Ž’ú¾ÕßnË|Q‹¼Ä¾o=¸ñ=#ö}K%yN쫟û¾÷š<Ì÷-n­I±u—ß2ß [%"i2ß·,¸h Hæ;!kò¾|ß‚L^fˆ|'b‹ ¦dýXwvæ‹¥!%™/²Wc¾g†µ`¾oZPÔ(2_Í»D¾˜ŽlÁ}ƒ˜¾ItÙ&óº•-™/>/„µ=gºomq1ËÎibÐ>•È÷µ`ê"”Æ‹¬Ä÷xL‘ø ¦r`’øÞxþ*à{Oz÷&ï}79ôJ$ï8<¶ðÞWÊ-t#.ae®”0ýhûÉ{ßE:Y'àßDÀ‡EÃUÀ×*›¼_rÖM¼‡U?ó÷ð%cžà½3Œ¬Haä½q™¨Ø|æ”´ó S|óÌ‘÷ðç ïµ­>0̳ß.cQ_+6q©iâ=t̾òÞÜ8M÷¦ßj€ê ÷Џ“öbÕÆ©6iï+WçQH{qoòÝu&OÞ™õ?†‘‘ ¸d)`ÞÛ´úï¡g8¨Ä{_eî…÷@Øy¾M¼‡i[LHÞÛä [¼×KNXÂU+ïµ­¦ä½IIµxÏÍ&ïîÙ(ñ^§»„¥Kò¾*$~ñ^ã´ä½¶m(Þ3V˜÷6:çî5:îA÷³×¸‡íSòUâžæ#ºË&5Í{ÆZòÞk‡œÆÉ{Á\äŠä=<»ü°è~.°‡ARdÖ.ŒÈ/d=ØŽpឬ·Ë¡ºX›i¹¶"êm÷i #ê½õjH¨×°ˆ¨·}kFÖ—¨×:/Qïí\Y‰ôÏ©ò—$éi?ˆ 7µnÐ+øç]œ‹ó._$Ru¿ˆó¼$Îk4KÎëtHÐÃÔÉ< zØ;aW ô¬{ï…ùî]avÅ|×ÃhAb¾ª ‘ï{M‰)$>r2!ªÝ’–°è†÷Á’÷ZeÉ{hâÖ5¾3äüU¼‡÷œ5I`ÂZšBqÄM½ƒ¸wc?,÷.ldR‹KÜ»±òÎÖ—·¦À½GØý{ÕG¤½SÉ-ivÏ"ÂĽ{¼â?Ö~?,²öÇm*KÜ»aÀ*1/ åïC;uâ=LvïÂ{w,Eþ2î}·Òô¸÷5H§g÷nxàm’÷îïS¨Á{ÑÆÙyïK—¨MÜCÊ„ë(.qïËã¥Ä=ìfˆ5÷£ÈÉ{íV‰{ñXϽ/ƒg¥‹-B+ÅX9º¸÷Ýå´Ü°×ú-Yï»ËnÀ Ø‹ž£~’õNXÅst'ëE©}lÀ5L‘JÑȇå(¡ÚœJõ¢©£¤½¯!§&ÙD½/‡Î…’õ¢3„NlÁôì¬÷ÝHÞ ÈzÑYB²`½/E'ÚÉzq/ÜôÏBÒûrÌ?»°•áÈLÒ‹ža©ÏÌ®ëœ×^,rÞ‰c 7IŠÕÇáªÁ”¬þ-‡$Òõл£sÞw«ýÏEÖó¬%U¯f‚^ $½0ÑáÚ9IïË£ÓÅAz'NDtQ¯7)I響|ôÐQù“µ¿ä¢ƒ˜wâ(†ø1^²ï>ô/LÊû.º$/ˆò<èˆy½²;«OahÔþ”sÀ¼ï¿eKBÌkƒœW¯1/&›Ù1/бúøFwÌûòÈá01/^j‰yÑÆ«ëygž!ýË”šÊ(Ê‹ WÉy1äDg©†ad˜“òÚKDÊ‹éq[ômPI¦{-‘énlð°”$¢ë`¤c1† e1Ý<\½Ç3œDG2ݳ/¶›}%&¤»ä!«D<ÅeM¦k (2T;ŠLd:,„Ù3Òñ.[­IÇó,X:ž7øÉtX ɶTBž6¶DuÐêßn¼zàb¼Ù¦i yãµüBÞ¡8–òyØa{‡m°’·Kª‘’wj³Ih÷¼¦x)yß%‘HÉš¯ÄvÏù”=gLÏ{›Ã² h'w4îÞGþrîÄ›kIiyXê’÷h½ Ã桘wË!¨Õ¼mêÕ”šW¦ÍĻ羬ª%aåIéHrŒªºùf”s,|‡3 UR΃(í5Cγ¡‹õ¼[.OÅwÍ@Zz^ ©çÙ„F€÷~ËÉnl°ŠÂ[I>9^k% ‰„÷b›¡ zÃÌJƒ›‡»[pžpizwEo¹½]«|B¬µi›@È+C&A¾|Y¥èí¶q°ç+MRœyXœ6JMoƒ A dù¿¶¦‡G×ôÂ"ŠSº4½¹«³Èy/V74›¤¦·9Éy(‡¤ÔôJÜ$æµ·C’Þæ/9Š:»"$½í›û~Hz›çfiz¾1X¹BIo;µª±¤·‰œ$éANæEIy½Š’eNþª§Æ„$½aLN‚pÍçŠ^³¬•¢ûR 8a·ÑI/žÜÍ„l€mÉ-èÆô€w*˜‚ÞvXLM2/ïÄì‡è’Þôb“ ÷†WŠ¿Èy_¾]‹=)zS-éÁB—’ž†UÏÃøØºíf ð2Ý ›e œ·)Ž­ä¼vÉä™}IÍC}Å‹©æ5••j^Š‚l ˆ±ç°(˜BXÊ×å–ë4¶m<ÂârBÌÛNiÏÒò¾žT¹éC8Ô¯¤åÙ CZ^YXË++bjyаÏEËØ8:é]8+õŒ:XYaSËk£„ZÆÙo<Ùy éu©–RTxÑ!¥¼’“ô0MæOêx>,!Ï–P'Ϻî"!o·Q¡oêÌ_ß± …|˜†¸h”Ñ&üí/ÀÏF2¸Làƒ–ÊÍÙ´ÚøóᢗÀw|ÎŨNë鵉ïÜ´…!â;óÌý_E|'…HEh}¤è ùꔥOSÃ+†µ†·‰ºÉ{åi]¼Ñ‘÷ÍúŸ·-‹tTRïK ĺjx‡-r%âa„P‘#²Þò“ooS<>ÕóT—´SUÉm”ñ¼/jï•á T’¤×̶)è5«f’N4‹h¼¹ýPôꈊ½f^MÔƒ‡Iëw!‰áìŸ.=xÇâLÖ›6¢2ëÕ®%=ìÔÁ©é=¯IÔà TN†¾îþ,GÔ$ë½#®”õ`Ù#JË6´3”õ^Lb<0GaÌj•­7§$"ŸÖÓö”Oë¡ïY0›v[t½÷Q$ãÞ” -8G$.òž6BŒ{ÞŒ®‡C$ï"íá˜4¹ÔÆÊ¸ß‡õ.ŸÄ¡¶W8mÜÛ­±QÛÃ-ÞŠ-À‡ŠÕyGžc’œöX¢tÎv„VÚ" -Ú^úû«ñVæÄ²”öpì^-8¯Ý§ÉKá÷ê/ó^ìâ/?,—¢ŸìßÛ |6.šx½ßÅËsÖAºbÁ„BT¢+–­´tÅß·à®íÒîboŒ+B¹béJ‡»ØtS¹ÉFmo§“÷Ç™¼:ÙL¶ë{ÈÍ‹Ä;ºb¹ÛÍ®X`@Ù®Xð fÊxs'‘;ðtÅRöÛvÅr*.³\±ÀF^˜MhghÈwQñÅKy²'–S§a퉥|”ÐKóR@W,å<À®XnÔœ‹!»\±ìðÞÕ¼~ò†®Xva6áôª›€oúRüˆGx黡fûúÉ ÎhpヾXö{óQ=¶Ÿ^…6à J½ 8ò‹€×Ww xmS€×Ìþå‹eÇw–)Ù‚p}I½Œ|tj“ȾX¿áôÅžµ™’ÎXð-æs‘7–Ó…ððý-5/ ú¥öåÑ6,¡ˆµ<×ÜhPÍÛo-Ÿä¥ÕW„_ò½’-¨£LòÆRåðt^­Ðñ¼&U$1ºci÷Š6¼6¯æñGȤ"¼KaB쥸EþX.wó„^;-ÆzuàA'ôàŒU–ž×:xD¯×m¸³$èù؉]²\vØÅ#z;Î}éy^ZÙ% ö·YÛðh m—,ߨ’»žoÃþ6Õ;ºd©w*)‡«˜#õ<Ì@bE¶á1–ꌞ_Ô½ÛÄ.Ÿ,˜·yURÞØl›"Ÿ,ø„ñ*¶¡F©Îè6å•O–š)tHïcÊŸIyX[ówJz˜äyPF‡ôüþúÞ¥¨†>¤ç [šî-î#æù –¦‡wxï˜ÏüàÝÙ,Á©á± p§Õ1¯}˜ˆy¯];È)‹ûÏNYÀ@óbvãa9eñ¨°S[sÞ{¸:e¹†%;:e©Þ‘S–Kçí”åY@/¾KGwÊò*Ät=Ô…ÌIi¯õ°ëUÏè°^!0¥=,åeIÔ{íÝC‡õüæù°^=Öî×â•¥åÉÃz·y$뽊a&q£æ]`+öƒëݲ)ña½×»:¬Ë2b¶Î?ß…öðtu|ÝüNù°žßÖ{µ)ËÃz,4„{¸“47ÁÒ#Ò$îaÕÅ]Ö»oèãa=!Ìñ°Þcÿ)>ŠâèÓa½gP“–ð~»%gk>ÔGÔ‡õ0P¼Ë6àNû|0Þ»àCÜ!ù£:V=JàkÏA‡õžrè’ć˜Bò%ÃÃzÕËøj¬ë°^½­:¬÷*"ë‹ùíƒù° ÌÃ6¼6§&ôµ‘#‘¯F²ë=Ïê›å‚‹«ÛröwQ*ßûH嫨I{ßW‚á„{·ö¦ {»¾è†½}3¥ýÝi¼_iï8“\ÒÞ˽•ö,Ùåæe«-Òž-½ {û«…*a^'¤üÑéæy­*^×/{ÍŒPN7k‡˜°WÇ’õºû„¿c½vBºXoØ…f²¦Z9A‡Oí¡ßÉz[Ù’õ6Ísb½rîUn7w­üÄzvÕ`¯›rîcÖ+(êxØGõNã³w›Rä 3u0¤HÙñÛ6(å!å^¤¼mUfòýeÔ‹Á_ aH¡8I)¯“RR¸Ž¡”WæÆ’òšdL)¯§¤†>»ÐòúïÔò"J©-µ<¸— ±Å<¤Ü‹lt‰ìR CŠlMS̃I Gżž’bR¨-RÌë)jƒ…ÚcþÈqÜùÿ”O(æÁ`LÖŸ)æõ2RÌÛ™j€…œC ð9 jy=%¥°%%CðT9ÔòzJjy=åøqÍyõøëÒò`Ú)ãÏÔò0ðe¦–×SRËC¹GóZ³/5ÀÞ[¨åõ”ÔÁšË(jyíVÔòzžl‚Ü·IËíeEš:X¿&u°ž’Z^« µ<¤\‹á&R„~ÙÐSw¼y ̢äm«Œ£g9˜‡ùÙÄÉ<ìÛÊ^”Õo×°ú-%e°v•<ìOîwó„u )ól®z¥’ׯR|Ú–R^žHÊëyRÊCÊV¿9ëQÊëwR|Í«6¸\Jy¸JžY2xMË’góN|+©äm»ÎÆRÈÃ'ñZçõ{§ Ö.J ÑŒ Nçµ )ã!áî€×.‘Œ‡!Ðò¤†º¼ð–<©ãùæ’ñªI’ñú­ª ß})»Všq<¯•ÂóyÈAnäùîØ mE9¥Å´*J ½(Ø|“a+Ê)­(¦UQJhEý÷D$Â1¬ã{Ù1§~‹‘Œ#¢.ÏáAÏã(CçtT¥þÈpýÛõ÷pît$Ž_G͉(Ã÷ÛFÍ?~;H®Ê{.—õž1µ²˜²”å\.«åRYTôy[YJéeU.•Õs¹¬sdh• KIÊã‚*Ëy¶8oÑ bÊR’s¹¨–ËïÔ–hU–RzY•Keõ\ÿêXûàòco9ÎûÆI>¹ÿÛ×èo¿Ýÿö¿ÿ¬ežãø·ÿûÿøßÂÃÛyüÛÿÃÿýÿüZä=ÿíúËÝôŸ|n¼îo‚FÀÍùôÀGß‚ˆð×ÿË)ÑÑþú?ü¿ v4c}=åÿ¾ÿÕ¸GÈÚâ]N¬2ÿÝý÷h½%ã½ópÃî_ã}iÿËýÏߤ9îÑþÇ=úöû¦ø ¿†©àؾ/%̧Cïùìƒñ „粯ˆ‡×õ¢Kõ¯n0‹âlT¿éÄ–ØgDÜ´r¿”¯°Pß#xÕ7G jt®™¾õÛ7uÞôþ­Žþü8 )4ó€ Íþ];ãÔ{¦|ñáûŒm¥¨&²ùÝùønûjÿé<ºö¼QûíÀìJ×ðtÆ”üäÖZøLúÚâî·„a;üQ-òð¤ÖƒNù^á ×SÑòþXkÂOlýÃAõó-jgXàãæˆ"ÿâËÞnPAœ8ÿØðK¹¹{ îý›i'ü`Ä—ïÁföû}‰`(; qZûî_".ÇÌr#Š/îŽ}ýoI‚Ó@0Fe¥8Ž8A6!B%dŽ3Ü„ÍЩ¢•ãŠQ_:ï€IÞ‡Gæ#MÈ'¶Spª#BP'!"’<-nžõCÈÑ ·Âûš)_â~F!áFTySÐíN¿N^ˆÖ…eÂ"=õ¼yÆ>RÜa£¿F`:»ßé8á/¦ð ÿ»©‰Áå}æ½r#5ûÏöz"ä3:ab'”þVâ¹l2ñ‹s[O^ÂHzðqƒ}Ý´Øœaq÷åyUÈÛ\ñ¨è£å IøK9dÄyÅõ1ÐòókÂùæ‹—i݉31ùŽ ó;qÈC>ZÂ]ÂDt¹º ‡sm¼{ý™˜A)› H¸íF?ì´&l6éÅ2=hDî‰ç©à˜+ìLäÛ—^îþ7¸5Ýá™[ÂŦ.†â—@Ó™¬Ûmp@í‰éæ•53vŸ£—Y«1µÉ!ÑaÚሻ|†ó„h£Ìƒ7ŒÞªÜ•þ ÚÓ ’3ßyn]>Ô ½øDÅì,w¶÷vg¾—²ÃáRñÁÛqŸ´CÀÁ¬ãó<9Qà+½Ypîtá+ð½É ¾Ò‘ Yo1ß>sç(˜À‘’¦‚ðø„ <œlfž'Døq ²àtu3ÃÃaäy¶ø†~):ãŒÑ‹ˆÆS¸>¥;NëÄ>žýE'ý…Á9 ˜Ä+eLOâ9/pÓ¢”ð/òäË™&|¦c²ðØÓ~¨¦u|¥c¯bî''ñ¡³|°€_^_œ¬8ú›8àâŒW„–:r &q¿Ð#v»gÝ{p/l>“#dÔþ> ¢Œ…‡Z0ð‰Þî|ÑÎ,7=íô«îXƒÔªb0šÞ„6þf9i3E|dF:|[ÿpPþ´—zÀ†òºÚ¬4`“zŸÙˆ-S°9]Êx96½ïèõ¾~·æâ~às8Þ™ò5!æpÍ0ßè˜ÃOšË=?Z­œ±9‡ŸŒh3FÆ&BÉñ3m@¿Ÿiýýý9_é¨`k%¦ï‹AÇ8·œ¾Ï7EáäcúÆY¥¨>Ð1}ÃMæA°0Ùâ97´ø:ÇÜ}ÑfqÌíäÜ=S úàêȹû QÆÀq蘻5¿ÆÈ¹{g|¬ÂÉ›†pÑ©sþV÷Ï4GôdžëÉùΑp?9}ë+Q[?“¶Öÿj¤bÀ;Լƀ×C  y6zÐ ˆy9Æ£ðž6bà€s·§càÀ ‹©M80Fw€fŸ€#QàÀë3‹(pà͈ç- XvÎNëÙ»Sàx^.‹Eg¹¢“I6Fñ8E‘%6úEÎNQp¼¨¢ÀÑ4VŒ¦@èûñnˆĢ&D›¬ŸLaO±P`(uÁs¢@ÐDXÙ˜!:Æ‘S æªøœ˜áë$ª# ¬O2s‚À ¡§âA B ćÞˆíÁøÜqš#ÞVC ì‚âÉ–$æGC ìûcl„™Q¼F†@XrÇw݈Y1V«¦Àý õ™)óä½Pà>x|ÌæJÁ|¢@Ì¥1O™!¯æJ]kÑ”¡E˜o˜D`óû+ ŒP\ñÂÞûZ(õÉÅœ0l®Ë…rńؚä݉°’\1ý)8‰aë›–äÀݧ«Ä8šËSq É0"NYP 9"Á°%K% "o®E‚0Åı„ì‘ º'k(ÄaÔž…‚0Æ?Ä r^¢ FXž ÂÊŸDIÜ/yB â$Ež Âü-פBAtXÚR1,á„‚Õr¡ ú4×wBAK£ æ‚](XÃI(ˆvæ^(ˆ‡žÃ@(ˆ‘ÃR(XÏX(ˆg”Ì+„¹ìµ `54P0 Â>4ß¡ lµsÜ k a÷—p-D3sx wÆ Ö ¢™i(¬÷H(ˆAõ.(kÞ¹  ZÁL‰‚8Þ@¨# ÂXÖGšb9÷ˆÆ{DAŒÖcAAä‘›…DÁ–’(ˆ…”ëÆrVÕû‚ƒ•"ŒƒÖ$‰ƒ°ˆW˜ÒÄA´œ!<ȃ°–ÚŸ<!RvÖɃ°~–pòà°I”€p¸ D‡] Æžubdá°‘Ÿ€fßi# ²J¢6¹=&¬;‰ñh²Ƀ±¢Í,äA ”œŃèÒ´¯bèä;,„Ájv…xëà•kèˆÃcl"y°† xp·½ x°F“x÷¤¿äA”/<ˆ‹rZVïˆ[ÁäÁúˆëAˆñ®åL)¬b䮳[ò` Jòà°y xУÔ<ûöø°˜q§$ñ ‡ ý5óªÂ!Û>!²$¶ ÝÉÂ0GÏ<Bw©ÝE„%úÅ2úµ6¢¤2á ‡‚¹ÄƒH8³òà eVâ çãà ¹¥i°. V² _p³à‘™Y0ü)'¤]ŒppÈ ÎìL„•GDˆ…v S¡ÇD¸‡`þGCBCY!¡@ÉHèeµ‘°®2<žc$Ä >>:…„€õ Êe…„#úúªBÂ+[QH諌„°ú’„BBƒG± «2ž:&$Uç‘¢BÂWŠžÐHa$¬q'k„Ý}—FÈ;•D¸-V¢h]úàNGhÖ]¨õAìÕüÑõÁVÆÁ*×ú S¬~ŽGotO•>¸1ü®a°òÝU†AWÙ0˜Í6 bÖ…I))ü‰‘²Xˆ¢¡O+E ˜÷1ºÔ¢ÀJ!"%ý̉ugC`ËBÄ rƒW¨ag´¨lÄèÍO®p³ï|1`¥ˆqÕÑoE®Ä€pš«2à€›VÒyrS_ è·Ë èmD;ÓJH ˆfå©V1 [.D–$m!`u—Ð#ÀˆbÑj§P»U&@ßZØ’ÿª?ÅÕlò¶. ¶ÞÿUï‰ÿªvâ?¤¤ù/ÊIs)ò_¤¤¢%þCÉ™…øWSø× &þµâ_K!þUã{˜Q Ë¿êá_ Yá_=máŸëKúk%ú«ˆþZ éÏJðײ$üµ‚ =%ᯧüµ.üÕóüµÂ_Ý\ðW\ð×®Jø«.üµ‹þZý‘ÂØ Žlå+à/RxÆxæÉ¹ºˆìW7'ûõ[%ûµbý¦Iz5Jô‹,ô…”è×. ò‹kÒ&‘ä7°ˆOчäyüÂÂ&åK‚Rþ(êk÷Mêk-õÕ3!õµ’úª²„¾öø}õL}-%¡¯LèkåúÚ›KèëyúZ#}=O@_¿UB_µÌ×zœÌ×îMæë)É|=%™¯ÕF'^}+"_¿(‘¯U˜È׋!òy ñUB_ýNÞ«V›÷”ŸW ¤=?Ñ^Õ´WUíõ,I{ýÖI{îÁ^¿(a¯_”°×nEØ«!,Økåö<Ô{­dÁ^Ë“°×Ëù`où•¨Ç&Ø«6‘õz}“õÚEd½šxÄz=%Y¯_•¬W·"êµ[õZ–$½ž%I¯õ^’^¿u’^ÍV"½vI¯]EÒë)IzU›½V‚^ëa‚^Ï“ ×JIÎk=CÎkÏÖ'ž_Ÿÿý—-50¼Y-§Gîú–eèM—2¥ú¸óÁ,9uf>„¡ˆÍ3Ôä!C3ߘÍ4 ˜æ¾K1]¤ý!MFÅ}—" ›ûîAƒLsìíÿèØwOÒ™±Ï½eì«bÄ}8‡ºXƒ¢œ¹HèÑk±µÑ´¹O&Å}ð – ü`îøG¿[ÁvL~—\à›ü*ÉOÏEÂß–jêóC1õ1ƒOCÚ’ßf·™’üàJ>1ËÈçhxf¾Ê#æã|·Ï ønù–7ðy|„Þ‡Á÷ø<8 |.ÄÀç'oà{tQz_=Uß­0Ñ&¾›QÓ |UŒˆïV¤É}°s:ñEÇ -bD” ÊûZ_eñݧü‹øàD®ÐI|UŽˆï)gäI|~p&¾gÈ{?å¾Ê#¹–- ñšr_ËC¹åÐYpª}6™)â{ä¼_j_õºÔ>˜ÞlùÚx”ÚתCµcR_5IRª›Š¡¤>^!¯Ú#¯ºN:_ 5ê|n²Ï͑̇椈&™¯å¡Ì×òˆø<ÒL|Ï)é2ò\ËQ@cÝ–£€Èó.GQÕ8Ê|5Œ$ó¡œÔ‘)óµ,”ùe•ùÜRù")…KåC–œ8¥òÕƒ”Ê×R¨òµª|5Œ¤òm±@û£¯l± ùs6óU9„¾*†*ŸGcQßóHÁöUqßóHÓ£ÊçG,•Ï·²ÊײPåky¨òµ”C„£Ê‡ ¬÷búéÞ±Ê×òüªª|îåTùª2Rù<­òµª|Hykª|ÕÇRùê*©|-…*_•#•¯¥PåóKc•¯§¼œÂ9“Yåk)©òµª|žQ¬òyþ°ÊWWIåóì`•/'*I|øÿc‘øZ©”øð ýRâóé+K|-%>¹,ñá^éÙê—ˆK¥êÍØo„‡sÃs±ó„;îm!méi[år#‡Æ¶ôWnóÙÒîc5lKÏñêС,='ZÄ&UoNâ„0o¹V°¨‡…RL™¦¼yÝ?ÀÌ›GÝMyóa£Myp—<0ˆF+IQÞ–þh”wl ¤gÊCJL¦<¸¾9]ï˜<›hʃ¿¤s9úw(ª°0o<ôUbÎC1c1ô„ûÇqƒÜ?®`àœ9Ëè'-ô°T»ÐCäc9û—ÎanЃ×õÕ xïBz¸ê]ä½ãad)“ÜQ¾‹¼‡r<…zÇ}þðSåõŽo=CÏãQÜP¡ÞñÈ?®P^§W0ÇsÈ`”¨w”³-n`ŽWQ~õl~ó*+Ϫ‰¨¯ž¨ÇI}¨mCI}õʈúpoDêC?ðH!©¯å!ö¡þ©ü ûð:Œåà_ø¡]þUï ûê*bßñÊ#­°/ˆ|à'öÕ˜ö!cÞûêíöÕP'öa&g7b_½1¾ê/aâ¢SZ#öÁÕ½˜&öµ<ä¾z‡Ä}HÙî;7méˆûj&÷ÛT8$r߉ïïbå‰ú,Vžçvý8øWú¡àw±ò„‹àmñƒÇ˜3°èïÜ™ôw|ë‘mñƒ,?Ã7ÍèÈcÞ´·ÝÈÎ^îï‘\ÝŽsôâ>¾ÈÇåê冩r`ðÞÀµiAJÞð°ÙÏõE‚{_õ_¤#îµâ^K!î})Onó÷"!ÞMá^ôKôp¯¥÷Üw¢½ê^ÑÞ—r¦|HؽV°)³«z-…°)±O$ØsÁb½Hˆ¡)Ök)d½ž’¬)£Ëz_ =‰õZ Y¯RÄz=%Y/Rf—õzJ²^¤tÔëYõZ–$½ž 7à).1… ×SôzJ‚^K!èEJnŒ'èõ„½H¡ÔFkΖ'A¯çIÐë) zKJ€^ÙôzJ‚^OIÐk)½ž’ )<¿— ×óèõ, z=%A¯§$è-)z=%A/R’ƒóÚoÚsÆ*´c^e!嵄„¼–@cÎV9[J2^OIÆ[RÞœº+%¯§$ã; Åx--Aø31¯§$æõ”ļV,1_EÞ£9gË“˜·¤¼9}W Ã2´”ļžB{ÎJ‘=gK¡=gKI{N$œÝž³§$æõ”ļž’˜·¤æõ”À¼ž˜×ShÏY)²çl)´çl)´çl)4èl)‰y=…-…Hóz -:[ -:[JštV‚L:[ M:[ m:[ m:[ Í:[Jšu¶„ļ%åå¾IÓ£YgK¡]gKIÌk)ļžB»Î–B»Î–B»Î–B»Î–B»Î–B»Îžòþ¹f¡]gK¡agK¡a'R»ÎÊ"»ÎÊB³Î–…f-…vuÍ:+V-áå ®„¼–|×~Ó¨S ¢»–pÇu­È.&›38Zt"%åZtê šsV‰´æl /çm%И³hËY 4åôœgSΪ†L9«ªDº*F–œ­˜œ´Ty™q¶2`ÆÙnB3ÎVÍ8ë&4ã¬ZqÖ5²âtqVm8+&œ•@ÎJ 'R)“ gK¡ gµ&œU -8Û5´à¬Yp¶ZpV¹²àlyÒ„³%Є³]DÎêo™p¶<´ál)´áä3”§»»Å]ïyGÕëã@ØBL -¢<-‚ÒÏLu™3ýæªwéë\<¹ÜJ©GJs¤'´Gó¹ò{PE9¥Å´*J ­¨cŽ­75V!‘àò×{¬¥ ké~)I¸8Íßd¨XKïí ú!inGÿøu¤À&6¦œ„æwã ["2©¬Š¢¤²Z%—å\.«GdbY-ŠËêQ”TVåRYKD&•å8J*ªâ(¹$åqA-“Ê©(J*¨EQrIÎå¢zD&½GE‰eõ(J~ýœKeýWb- h•øÊÿ6ÖÒùÄZÒàr¾ßÇZú»l?c-ý“â~Žî¿Évþ]¶ßÄZúW&ÄüœÜ~3ýýã·/Ì)ñ÷ïË/%ý§Ã'÷Ú~æèv˜£ÛaŽ–ðCíÏŠ¤@Gsÿo tôï¿ tôä_×ó›@G_âÿá¿2ÐѽGMû tô¥ý/ÿõ?“æ@Gã?tô}õÃr0ü™Í©÷ðäg|œaͧ6ÛÀAÅ8”±§Mœ††æÀãäò¾ŠGê3â¼Â¨åû°‡‚5¾1<³1”âDàïpÌvó tXºïaB»à0݆Â6:x CãmtΜ]–4Œ%`f˜Õùš Ûž— {n ÇVcÔ»ËÝÁÏ}ßS^ƒ%mÔe»c"^el¦$̫ϙH,?ó4®L'Ë64ž´\¿´H¸hù’îd_D:J·{s¿ÓLá(¼æI3‰ë¡¿ƒp!yF #º¯'xP×Ý xfÇ´æ·"Í0 8[ñfJZI܃{£ñÞ#̤õÇ÷)I+ ìÔÞ™r¦•&ã™å\i%bŒÍøï!†•€qäE0î‹`+Ty¾oZIBFæ–V¿2çÎP9Û–J|˜+E˜ÅÁ™XDD˜(ªqó9+‡3&"¾g¬œ=UÄù=Ú ³°óÔèüž Ã,04Äœ7ƒå@uÈrËAdÔhÅ|gÆYa"5±rTA븉PÕù2#$ø(l¾”4’Ðf;ÉX9ˆëž)GIÀvNX½\ tõy\i$ñäæRî4’hW=i$‚ó¢w2Ìf…~aTcè‚ñ¥G¸ñhÕ™/"%_"‹0 ßú>Çí9ÓFâ9éÃnžGÚHÜ7•öyž •sS!ÿÞÂ+ƒhÝyë;Í$î‡Kšï…K3 Gûùø!Í$²è{MÓL±}òÖמfŽ,AË ®Ý w¾”4“¸/.Åæ5ÓL£Ÿåi&á,ß››fîÌs¥™„ƒ•L| ·=Kcïe3 ˉÅ÷þduòq"˸³é±îޏ*3bžÐJgÂñÈ1óÕ #¯x™¡¯aS?gª{†™8È1¡P@_«Vá]Žg“›·ºÒL¢>â˜Ã!Õä°½Ÿ4“@Þœ˜ðêî{Ÿ { “8® )^¹ñdL¥LaUyõržŒB)Ù§ûpÎ¥ä#Í$ZÊf¨r¾3Ÿ¸ùÌ,7æ\4=™8[s.Z°ÌçM3 pYÁwcÀËwÜ­‚0ˆ9Uë1îLÉ{½“sÊ·ó=1Gáæ{2bŽBWÍ÷bĘÔD÷ÀÇËÓ§Å÷aÀ˜>åE/æèæ¾Ó1“«3|§c&פ|à;3ùCÓ€‘g«ñSvó] >ÒL¢|¦™Ä}Þù%<â\Ñ‘ýU>⩾՘ɯ=íV|ªÃJâbÀœŽŒÂJ"ÂB#áH#‰‹Óö—òa$‰)ª·_4’@5³27$:Œ;àèúæ­·,8cH~)´@>ƒí1IÜ™°§•ÄuÍ4×=𩎠gXm™’V÷ xwàSAÏN4ãH+ ¼Ö1ãL+ L;Oæ¹’Ù0’YÎVxk®¼êI+ ÌM1~Ÿ§´’plÃã[ãq&癲cîi&á×16 ú%#Í$«êÀ‡z¿Û+sàC=Î^½y¦™ntf9i[qÛŽ™1!k¶ÿ¾žŒ™³m*ù Yª¢´Ç–vþjßèÊ™\/ãCâwþøTo á˜õÁ§zoŸ£_ê˜ÉŸ‡ÃŸêуØ0ÊçróôÛgOZJ´«Þ°”¨þ¢‰XÜêÈ”=M%`oí ƒ˜«}j˜?ÄLþÐxæÀ§:frßŸê š|rXàS‘Ï´ôúZuf䳯G–|9“¿cļ¯ÏÍ]„¬ ÖÔOä98[ 0ü{ö*ãc¡ÏNvÏ•ë© †và=Œp–˜3Ï}dðÊoEygÊ33xåv«ÊïàLÎØ @1“?´¡:°ôŽ™ü{CCÏ>-fr¬z¢œ­h–ãþ3ùMÁ²Îä´TËm³ƒXÌñéóFŒ—×ÿj䣂B€XgB´™»§ …°‰ e1ᆠÛT ó$¼0>hq&~v*-š«rRá@Î;ù.©°‰ ?ÄØþLpL(ü •v÷‚Â}%W3äÂñž‡00¹Ðþ’Ä…_ûÇ.DÍGҹн̅:Nm,ô™va!>¶of!†Ò’÷&n/G·¹'i™‡\è@æBO{͆v˜m0Ü^˜2Ú±­Á’Lö…ÀÐþJ †{~ÏÚ©¢Àо¹ †öŠl0¬ a9‘]*0¬ Ñq'Qñµoͼ—ÀÐÑW †pbër!b­ä0V#†Žµb0´¯HaeÚ¯´ÉZr5(2t€"“!¹>"zM.{I†¡IŽE†;¬ÃòV$CM1:œÉ°å!¢¿’c„†Ž c4tP£¡c­ «O…†ˆµ’CEhhç•FC ü\å:ÖѰK4Dÿåü!4Äsxň†ÕBÃý¡ôm4t< £¡Ãâ kÀ Çhèè?FCŸî2Ö $:"Ñ}Lò":ü‰Ñ½u+tγ áޝM–“hˆE*y’hè8/FC‡$1îöÜ„†Pˆ²…†ÕBCä94¬† ±Dν¡a n¡¡A ¾ÆhØÊI4t £¡c¯ †Ìù(vÎ%R%V‡ pÄhè°3FCD³ ¯ ÏQ§ ùl„†°óÊG!4lyˆ†ˆœ‘Ã’hˆè 9º…†Žc4t1FC“kX¡¡¢Œ˜ }'‘¡ƒm˜ Ýë&Ã*…`è¨3CÇ*1:ÆŒÁ°åy9‡q= † _b.Ĩ؈t’¬89Cò1zt‰ =ã™ oÊdè'n2TŒƒaà`fy+p/ÁÐ/ˆÁplÜY2úE3:RŠÁ°•s(pDZÁÐQP †5(†¨ÖÌ«Îáà2:úÁÐ\\Xí .ôsâqçXXˆ,¹Ž:±ÐQ†Œ…~…P’I…È›–¦BgúÁ‰ ÐÆLXYÆ9GDX„8Ä›/†€°žš€»È•–‡@ˆrrpñæàŽð „#W ‘'{\@Øò1à‘o¿hõÍ$¬ A4ˆBf¦=:ƒ•E0X‘0ˆ,/É0XÕ âÝ9²` B£™‘%7»Ä‚xØ9Š[mÈ‚õÄ‚xPÏ‚0¿}ÇÈ‚5ÊÅ‚Õ]dAÇ32 ú»atX=³`±`+G†ê‹ÿDÌ£¦^+ú,¼p^ȶ…ß“ÌâAtXN¸âA ñ`½#Ńâ/ñ`ËcÔd%lÔf‹W¶ñ ¯*n냩Ȋ ©‹ {Ƀí"óà% ’<ØÐÎ<(RvüòVÂv°¥Š¥Êán"DJ®åD„® ‰°øJDØJ&z¾0:øl!!QÂ+ó玄Úp3¶r„„_FBÓBB½%FBÜÆ„œ Ì„žgŠ w ™Ð/d1¡o%&ôpoLÈWËLXUzº2¶»“ «ébÂ[1¡_~3aK!V} «Â¢Âºµ¨°.*lW‘ «2¢B‡á5zmc,l% =Áš ý¢ =ï «sD†5p‰†žĂ5’ņ-Ù°Þ±aKyTUïÙ°ê'6¬–‹ «~bÃ*XlØRȆž¬Ì†õZ [âa5TxØ®"Öœ">¬«Ä‡µ!C>ôg>¬f‰[ ùÐs°ù°¥ë¡ k8 k Û½ˆõ† ëí V9D¯¤ˆU°±zP€ØòkËH€X=(@ôxÿ'q …ðv-PˆP]qbCPxÒ@PXÑZÊr”~^›áè+‹OްĄ;,TW&¼éŠ«˜Ð+1a­’Å„Ž m&4ý› ÇM–˜ö‹Hh“{3ašM#ö”dÂ3Á?bZ>S$ŽKÄL$Äùžw±·l<…„ã¦Sq#!R²K…„rg"ÄTž$."8šã(SH„÷M¶#âtQæ>SêŸxð¥!Ná{°”äÁ‘‚€`ÿ¦Rj|èW¼`ðá)ö‚AÌ I_‚ÁGr´aðá¡ú‚AwƒaP-2 ¾é“ Pð±A¨XP¾÷ŠÝ bA7A,ˆêå·Y°òˆßC6¢bAßÜ,X)dÁ*†,ØŠ! ¶‹Ä‚ïÁ1#l$ "…|&ôà ¶² =ë™±j ¬G/½Â›q†#7tÄ‚²vÞ= yx<Ù,X#X,ûò´ ÖË"¬Q.¬‡'¬a"¬N ¢z‹Õ(ZÛVBAŒZʇDÁ£BÁ–'Q°Ý›(Xƒ_(8žt‘`De(é‘«sD‚Õ$A”»ØŒâÖiÜ.¬f ëé 1¶ÒÂ\ ˆw*ç, ÊI«e`•caÐãO ØòHÄâ/JVZôh#âuÍÝ ƒ®²@SIU _"`½öýZ «Ý`uªAÐ&¬×Ê ë#ôÔ%]Я«8°•"]Pí4¢»ÒœÑº !U?r Ë±0X +E 'Ò_`ZÔ$^ œ þÑ(°$ ¾2ë”*ˆÅkÚl’«bÀºˆèb- ¾ƒj^ Mi‚W@?ÚÒõh €"% b]˜4•èqU¢ o%¬îµ(XWÛU5Í–(¨fZôã·&è,’«\I‚z Kt1ÖÝ© ê{S¢ t‰‚爛cQð4¤µ(ˆÅo–#Q°Ê‘(è®±*èaoUÐ%[ôs±.ÞÊ<ÒÝp ƒðjøGÑŸ{Ï {ÆÂ ŸŠ…ÁJ‘0è [tøéè¦ÁRâ T _9 ƒ~å, VŠ„Á—ÞžJÔûciÐniÐm°4ˆý¤Ì#iЯªµAw±µAWYÚ »ÂÚ Ÿ‚µÁ*FÚ m9% º.VÝl+ƒug)ƒlV±a¾€R’à$ :‹…Al Í?÷Õè“0èÁgaPÓ§uAjë‚~Ŭ Ö¤ ª¯þa Ãt9:¸­f¢8G”A–¥ >—ÎY„Gì?"ËŠ€Ý“×H„•×½%m,l”(—O™Gxè0†PZj‰‚Þþ6>éLÁüwÒ5]ñŽ&¡Éð©°ôòÊüwgÜEãßW0»ŠøI¹.1þiLÿêĤðoŽ¡[ÿæÆhIæ¿ðÕ°Ä4|/Š æòdcñîµ-6¢í*àÜy@Â8qF!Ž×dÍD@\”¡„@xqÊ¥§ ðËóç"‚óHsdÀªžð+ŸÏR 8÷‡Æ·%Ë!ÎÁÁ&œû+CSBà<œ3£öçØ‰‘Éuñßœ4ú6ÿ}-û£Á\±OJƒ sÊøWð÷õ¨ì7þÚE„?ôÛ‘)„?Ôm,†¡çrþhì7aâœÕ%ûáN[âÙoNòûUmÄ~sç¡ ³žCš‹ý&1à‡— ǪÀ*•¸?ÔÇ ~ðM’Ën†÷¶€žé ~u#_]%ðƒüEüòˆÆÈ}¸(­¤~¨ï½€ŠI{ß<‚œ¨}¨_n új0 úê*Aß<Þêß —JùxÁÌW#BÌWﲘoN•2ó¡UO?'ˆúeeÈ|hfjÔb>xåYµ?ßȨ́bŒ|hÓÉ”@>{#¦§+³ùübšùOÃæ¾ª¯¸¯¥ûüR™ûêùŠûÜJqêG‘܇Z$øi›û¼ö0÷áN+÷yªHî«Ê‰ûjˆûªgÄ}~9Ì}íÖä>Ï æ>¿æ>Mƾª¯°ïûLR_öù"Q_=KQŸßxa_õ¸¸¯ª'îó”iîC3áÄ}5ªÅ}õ"’û4]ûÐ’±+°ILì«wLØWíö}_è?êSpS_u„¨¯Ý‰ÔW\Ô烩W-‚_%$óUuÅ|5‰‰ùªóÄ|¹H3ó¡=çr2}™uÅ|U[1nDv$óÕ`óùÛlèûÿ’÷6ٚ㸺ÞTr±$QÅqÔܸËlœŽçox@í¨¬¬ZÇöõ:­ˆ›" Š¢ø£yñ6ì¸9¾„>O|@Ÿ&™Ï ¡Ïk¡/ú—pNèóÜ#ôéªßd@2Üe4ÈåÔ'\ ÿÂÀwÜŒÎB_XœæháóILàO *4ÌuâP™bÃð£ƒcÃh§¢Ø0‘jx-è;­€Œ ³3dïlt•"àE„V-|gïŸSŸ‘<#O[‘ðâáÚqáaŽ›ÕñâÉÁqM0Þ]¯&>º¥ ñäa.Ä»Æó±ð]ƒ[x…‡Ù¹ÛRx˜ÃEĻô¹Ä‡¹á†¾»OZ‘ïîw¦xwŸ<Þ º»¯ñk»;Ôóžg±ðÝj'û¸›Ûbá»s /t1T&éî~n !à.âèô¬p»çžwÇ—¡¤=À]<²c±ðE¶ç´*ïâ*øðbË;N^l¹÷ÅÂ×÷„„1׉t yý !/êÉç‡×#4~ÖœWšäõ.o„¼r /šºï¿'{-¾~ÐAÊ›1àSÊ‹ÅêÓ%å9‚)/Ê´å´go<©À0GgȆiÙpfn8¸&(0Lã¹?†iøÀåÀ0±JäYJ†Q÷¦ñ0¥Ã4žT`˜ÆóÐ Óh"U`—a`˜†¤k sž¤A†‰=GJæDÀ}†i7¹a·qWFM)0ÌI8†áÙk†á¦À0'ül¦ñ°Üô¿S`˜“ç–Æõ00ÌɃ sòìµÜü2¥À0E‚À0–00LÄZè? £ñR`†Êp`˜ ™Ç†6Ä{÷qÓ€ÇÀ0×É“œ £h@ £šæbè0† ¨[Œ|¥ ÃÜHåÀ07Òø"–MŽ»ÃÜü0¦À0‘†;0ÌÇLQhEŒPhuG¡a4‚ ól<#ÊÐ0 ããÐ0êCÃ0öV £š&îQZÏa˜¦Ä‚‰Ð0÷A¤ch5äÐ0Œ¯áÐ0¼ #¥Fh¨Ð0 hDìsœrŸWh)¥Ð0 1£Ð0ºç ó›æ!s:4 G]¡a$Þqh˜‰ŒFoFñ>†ßRæþœöŒ2ðdhUãÐ0 (SBÃ\ËiÏRì!]àösT‡†9ð¨94L£"CîÔéÈJîüªõÌ)f¿óÈ‹®,òäGµŸ}³š'?ªÅE9û¸õS5j¿ßµ¥gÏojšçÈojЧå7µq"´åõÌï•edž+¿©ÅÈŒ,rgžêRMÏojq_F6õä75gZ~SóðÅåÛ‘Ã—ÏÆ¸ò«šï˸ó³Z‘ôü®æ!O~XódO~X+mü°F¥îmËïj¡÷´{¾ 6¿«ihîw§Añ9|÷–ɯ\ï½ù]MmßÛ•ßÕtïíÎïjz‚Þ§p&©.M=ùYM“ö•ägµRfäg57¾oùYMxÏX‘­^µùYMsôÞ[&©ÉÈzòÜíœ\óöݬ|Üe¸"(Év-Mõü¬fÍ#´öLÊ;s‡ßZô ‹š¤ä¬Oâ=· Wyîãȯj媖_ÕJ™üÈî¦ÈIîðqçGµLËÝý¾èr?óTß=ã0,:]¥[¬cä7µ:OÞm›ßÔTËôïzjÃûf.ߪ%Žôß‹–qµc°æsǹàgѲÝó›š8΄ŽQuŠt®ß¼—ñ‚Þ뽌÷óqÖ)qn 8/:÷ 8Gâ<ôU:œyDlŽÄ–eΆ\e® ¸$w~Róø}î2϶þXÀ%ùImlyüŽ—ó\¿%Øo,ßÐ:öçQíÔêcw «7Û¹®«7/ºw¬Þ»È£ôœee~%«7G3^Í\½!ókZ Â<5vÇ›y_tŒWó±ÜÉwR#/ü5X½UælËê}ßÓŠZ~ß;oª}÷ü˜æ{Ržå>ÞσÕ[eòœn‘ð{‚„x3ïË3ØK‹w>qΰ-M…Aê\–š0_­zØ—ïú:¼ãÀÔ2XaŽïÏRäy°z«šÑ±zó™{2h’uˆ—ó~Ôኗó±/µ«·Êœ «7µšÉ ï¥Ì½kõ†¤oX½uUŸÕûyæ×5Î3ºïÔsl7oŽÅ `|Õjâý¼·:•âý|õ½/üºzëÈÕ[Oî¸w¬Þ­ÇÖ–{7úÀâ-É«ÁºxPa/ëZß^¬tûìïÜ–öx9oõ¥ßã國7vD=^ιxcçÒ·ëÈÅ›¯ô¾… ±OAø¬woØ|c;þJF®Þ;R>ôíyrõÞq´o !êÙÓ¤ï¡Ah¹#ªq¬™^vËWs<0£$œíñfžk÷†TùÍ#´ÜàåÒãÍ<ï¡ÛüU‰ûè¿›ÉØ{ùª30 ¶‰4$ÀøH˜›S!`ôiAÀ¹ÿ£ Lß"@7ƶzž!Æ1®¾à†sg&À§€D€aE5 Àȵô$Z‚ŸÞò|˜ðy”Ÿ¥w›ð‰Ø‰S@>°&@^$|§Sû ¨Œxáð¨P[pà;è#Y“xåOÒ_DNhTúK0úÍO‰‡D¿ü;¸oCš‡ô ~ö!¯HòkÛX$?'…"úÍzæèƒüÂWæc_‹§ª§$±ï-€æÄ¾ç–eû摨yúƒØ÷–A’-bŸ[ꛇŸæ™~Rß[GzÛúÞ®À ŽÐ×b;ÞR’Ð÷J:Q1©ïm¾ÿ¤¾¶EnéçSßÌW•“Ô×â[eÎ\`ßÛA¸¥ûfvª+Ë$ö½­ÃŸŠØ7}9‹ûf(ù‘<™Ø7ye}-"§°o†›Ïûìka>²©1“ã[iâãä¾·È•gúÉ}-¸ãII‚_©à÷Jp*à7}¥rüÚ–¢Ä³¿¢ÀïíΙ§4~ÎÂEð{%pÂ!øÍ{“à×öœ&?ß?ß<ñ6»Lò›Nµ(Ò3ù@*m’ß;W]ˆ™Üî0’ß,3ïȯ6õ dr„jÈŠ„LŽÇ.%I~Só9:$¿yïIÔÚ2y¹’üæ¹½3¯Jò›Jàª1“]æBÌäcÏÕ‰è×öóf™Ž˜É‘"£ýaôsÚ2 Ÿo1Ù¯ûµxUî m;b&OÚýÈ~eÜÁ~󆿀ý^ <­< hø›¹×ž,Óá8}>dÈŽÓGcÄLŽUrî¤@³õ¹Î€þÞj¶|؈óþYä@Ìäˆó1UþÍ2yGo=G®Ä¿©ØîΘÉqš£âßLö0ò¢1“c¬ø÷–ÙòÙ'ÿ½õ\J•üW¦øÏQeÈsvÏo¸ä?'%#ÿÍ.ßyÕ…˜ÉŒWCþ«­wÄL>áó6ùï­¤ãÿÍä½òß;ö+ÿµØ™Í¥œX4:—°è œù¶,“èl{dÀy;As!“™I è¤xdÀyƒ{aÀ™¯íLvÛ2ù„'p&'™ä8+¾’†œsòÌ2W†L¾žÜ‘çè\`>„Lf¾BRàlj¡ÀW‚Ø=¤@'K$NµFr׎É.s d²ú t–l Áò€gSÕ$Á2»A‚3ò‘¨•$85¿’Øç$ܾ’çÙ+ ú1& Î…h.•dÁùÜôlk²`-’,è[L|÷_ÛÁy ¿ýaôf‡ 8_ÞgJ&ÎÍØ“‚Á¹7L@‚µL’ ·$Aï:e×¶ùßH‡dŒ‡a5ŠÐƒ[׃1ûrÃE º«=°m;}’[l¼òË?hðíúÜ!ýV Úáž(8¶ÜÎ.›(Øb+€ìȯÊ'€(ˆô_ä@Gá&¾Õ>ù¨ è@m$A'ò# ¾›¸óý $è\i$ÁÓºUlÇ‘ŽædÁW°³–ñ“ã vÒ!p0NSžÅØŽîc"œ7D8£{'|+Í„ ¸+ -Ó°K"<®‘ñ3… Q-(<ÞÕõ ãÈFN5B¡‚Þ Ù´…ÑVª5©O… .(œ»Á¼P¨ÀŸ‚ˆOžÜO(œŽ 0ü!x2C• #†yÆ]Y0ÚN*'F÷KàŒÂ—Æa"aÔH&w£ÝH§`ïj t@u!a¨Û 0šJ5‰„qvv/¦ÀnSK"áN·Õè!&ÆV>ï ‰0Ê0õ½œ$Fè‹(zTæ‹ï–I„>Ã$¡/âý±0߆C˜b>±š˜O æ‹ÀDTäcï*ñ¥ÁNÀ÷+`lÿæÈ{æAŸhIÀwqøÈO>a˜€O4/às[$¾Ø($cù.xÓ,È—Ö;_|h\‰/¾r&’øX)M|n¬ˆOÔmâÃÞÞÄ'¢ñaS)à3Oø"hFZá|šøLj$>níM|.Câ#Qâ»yŒ“ħ¯&¾ÁC¤$>‘­ˆ¯oxýñeÒ/_äìN0#ñ!’½ÐjàóE>mÊ |ŸËÀ÷7Ÿªð –|üxP€¯a#à‹µ21ŒÄÇ/8…ø+ÊÄ÷^µˆo€±L|©ħÑñ‰#D|–ø„’&>†Op)älù˜ª òÅù\³ÃS‘/Äç’ø˜ËÊÄÇÜnB>}ð2ò1/•‘™D|™1N¸§ÎŠ÷˜3K¼Ç+{L¡eÚ{ú@´W$¤=õU´§±$íYCãÞõk1ü¡/D=›PÏ’‰zº©B=iÌSŸ±Dæ‘cûŒà­i^$íhE{z¾H{nš¸W$À=?Ä=&Èîyö÷ÊEÀ½Rqâž‹÷0Rd=Ïežg.aOßjE{E’´ç†I{Ê'Úó“öÊUÀ½rpÏ+qÏdOÜsÍĽ"îYQâ^©¸gµÈ{¥žä½rxO7мç@ÞóƒNÞó$'ïùÑ ï xOYôÄ{Ñx¢/‘¯Ô ä+ ŸÇ”ȧ…ÄçoO$>Ç$ñ¹7$>?U$>fððùƒø4|>}”!ðy ða“ö|oI{^ðH{zó÷ôž1îñæ÷¸Ü÷ ‘i·À´çj’öôŠö4óE{ú'ÚÓV´§—œhOojÒWFÁžî¤a_{ü-ÖóÐÈÛ‘#ÅQ±õÍHÄûb±ü£Pߌ|“¹þm4ìñÜç¸ÈŠ8øû´ÜßÊõÏ>{tý{`–þ kß¶ÃÔßã¦ÉØg˱/6TydŒØ·Åù˜¼ Ø×Âeˆ}4Ñ ûâà jÀ¾Pf¯'?AYاc¾ó¾x®“ÜGûÈÏ Jò‹ GuýóƒcòÛha%úE?[‚*ÐO_Œ„~m# ýÂ9‡9Á~ʼQ ~d#Â_Ä×È;Løk‚ÇšþøÂý]IÑ_‹é›m‘þ††ÿ®FÎ!ÿµ‡'þ€úÔ˜¨ÈãBÀ6pòK©£Zõþ{¯:až;™wú&’¯ç¢o"ðŒ³|Ë9PEãF¹€çƒ"ÀvëD'0§_Åûï½G¯D€$&-Ð$Àë¾I‰ Àóä—`ë<¯LŒi— ðŒG |@ÀxüϯŸ…€çuò &0bÖ<Ë1И‹Í/Ò4דÏG‡D€×@B#àùt6'¶Ñyšxo'^a$À¸*·í À3Â?çYM `Ä–O ðøÌ%Œ»‡«À€wØð£ßµã ð¼pZ@ xïpL¼ö“fB`Dá9‹_˜©¾ïEȈ þ;ïç=Á/äÑRþ»â$âºuâ¿úÿEåh„îõè}nì0ðï:aîþ'wwÄ¿—˜haþ]m¨Ä¿kCbáã÷‹þ®‹‡jIgGNÑß ¦ó^Ò_¬Á9\¤¿Ò<¬Eü»#{E5øM:¨îï̺ÓGAø[òDFÐ_Dºr’þb1†ø9r׌À)yä‹xŽ 'ÇH€1~¸ýÛ“ßu î­ ðÎé$À«óS= ð ?‡”€gä¡? -x5|:FœÁ<ÄF¼nâ&–fÀ€7p„Å/VÝc9úyũɅ#qDR0Â6î‹ÁïŒmÉrò3Þ“¹§%^ñA*¯ÆÕyª™ Ä9O0`ÄŠZ°\”xG÷? ^'} WF?+ÿæE`Àë^Ì}WFš5Æ+ÇK€±8 Ý×3Ÿ¾GÀ÷ Û#øOoeñßÝnÚàÀ1…k_<üùDÿft«åÄçÕiÔ"þ…R×bî‹«îŠqÑAâŸçùÏëùOo9ñ_ìkòÈ8ù/vEc±÷ÅP¤=ü»½zþ9”¾øo÷L[ø/âŠæaNà6`ÿ4‹€q§Ð4ðïŽå~9ïéõ‹øçÅøwpêÿ…R8šük{Î$àÝ(J“ÖF`è4à ˜ £ŽÆÁ€šJDÀë& #^év9 `<…×bñSÊ !àaá ê‘Æ´(ž-"¶-žÚˆÏ8I’•€¯ÈO»øœè’æ@€@ `L€‘ `<Þ‹¹/ïœI‰ Àx‚Î,Œu{±öãdh® Š…o¦‚ùËcá<{hYøbmýXøà0j ŸœŠþ¹…/NÔ&õxAÊÂ'¯Yø¶ {f¡ÞA¯DYøxæÝ>ž½öÁÎw¼zõñ›§‚¯õâˆôù9ÛIG£ö$F½~æÝ²…O†5ŸíTà°^¸S-¬§ »f½ÁWŒzˆ°m+Ÿl?²òé|Qo{¾g;uJOf¾aIDzâ™ù®/émgT’Þþ‰ó2mgÙÍ|á“Ez;ý(eç;oåhè‹ô¾Éq´ôéª4õé\Ÿl}±,üQ8ïØ3Ŧ>š%eê;|W0èí˜$2õE} 蕚iê‹Ãi££©ïl”ÐÔ· M};ÔÈÔwž´ÂÔw a‰M}4&ËÒ×NúÒÒ·Ó†/K'– }ñ>Ɇ`é;è•*K»+CßÑxH“†¾8Ú°PÞÞámC߯ðFļýaˆ&9ûu¼ËlèÓñi9ûéù!æí±n§„Î~ü*#ÌÓUröãin;ûÅÑÉ”ÐÙï9á!g¿_±ììZǜöùÞ¤³_¼¹’ éì7’ÉÎ~nŠÎ~É'…ôfŒÝõ"onåìÇ´³/ØÙ¯cQ·³_'óÊÙol¬‡Î~q ¤Æyñ=–³ß8°M“³Ÿ:(g¿kÀ¿MÎ~½ÑIÎ~¾ŠÎ~±ãJ§A:ûñ”†ýÂ"!Î~Èìì7SËÎ~\Ãíì÷Ö³„z™m¥ ýžƒþvtö‹Ï. etöÓt’³_<„«³ŸFPÎ~ ×´gÍåìÇs.vö /pðœý:¤ÚÙOWÉÙol_g¿øÖ›:ûi¾ËÙïA ;ûÅH.'<ýÈÙ§lìì ¡`/åVÉÙOƒNäÛg„Ï? òÅŒ†—½ýdJ°·ß³Ó'Þ~©êìí÷ðS‡¼ý|½ýt#äíÇõËÞ~ñu~õöÓ°ÓÛïA {ûÅ©„”ÐÛ/Î;,¦?/òöSåíɨ*ù•jèíDŸzûű‰Hzûq5µ·Ÿ%ôöÓz!o?MyûE ß,Co¿ŽÝ¹½ý4™äí§É$o?µ.o?-ôö+xûÅ0%ôö“£œ¼ýì“Go¿Î¯bòö{éÂÞ~±ÏL¤·_œÊ«èí÷œ_o?­Mòö“7½ýè‚'o?-Ôòök0|ËÛ/ŽŒ§•ŽÞ~º£òöÓUòöÓt’·ß ÿ-{û5,VòöÓ3,o?ÍAyûéõ#o?­¯òö‹ïÑY3½ýbg\ã¾LOÌsÁ?9ªÚÛÏnzôö³G ¼ýýÿèíG>·ß½å ÛÛï·\ æ€òpFSY<þè5NÜcÓ¾{@Wc?9‚#=Àµ`8Ÿ·¼ŠñrŽ2%ã‘Ño»JPâ´òáØÌ×–“JdcßÕðM^Á].up— IÜ%|‰ªGŸ21¶Käz–Ø.QïSM|¯¤ç®•¡]¢¡4¹0´‹ )´KÏÐóƾÒ4B»Ì¥žëœ’Q=úfn£<ÆØ.!Éc›íYauCh—ÜÅÀ7y採]”EI¡]B‚ƒœH˜sã“–‚»„ä¬ö½)©ö½*@hÏ"Aˆ—"ApÏ~ã;Ž‚{ ¢{ ¢{ ¢{†ádݳJ3ÇD÷´„Ñ=‹Ñ=‹ä@% yîib{Z€Ðž ²§ˆìi{’å܃FDÄõ´„=‹=‹=‹=‹${{ { { {V ’åX’‘=-`dÏ"AhÏ"AhÏ"AhÏ"AhÏ"AhÏxe/¶½Z¡=‹¡=ËUíYÊ ´§Ê(¶§Ê0¶g)‚Øž¥b{–2ˆíYÊ ¶g)ƒØž¥LÆö,EÛ³AlÏR±=]†±=]†±=KÄö,eÛ³”AlÏR±=K÷,eܳ”ApÏR&ƒ{¢{ZÂèž®†Ñ=KD÷,D÷,D÷,„÷,„÷,„÷,Ä÷¬ä̱ñ=-A|Ï"@€Ï"A€Ï"A€Ï"A€Ï"A€Ï"ÉŸE€ŸZjà³”A€Ï"A„O;#|º #|–2ˆðY$ˆðY$ˆðY$ˆðY$ˆðY$ˆðY$á³þZş嬧%<ëY$ˆñi¥ä³Hå³Hå³Hå³Hæ³´…0ŸU2Öµ\a>‹$Ã|ZÀ0ŸE‚0ŸE‚0ŸE‚0ŸE‚0ŸE’q>‹>­}V ÒæX‚@ŸE‚@Ÿ–0Ðg‘ Òg‘ Ò§ûÃHŸE‚HŸE‚HŸE‚HŸ¥æŒôYŠ Òg‘ Òg‘ Ò§«a¤Ï"A¨Ï"A¨Ï"A¨Ï"A¨O·ÅPŸ¥ B} B}VÉø,æõY*F¨Oa¨O—a¨On]é³A¤ÏRMFú,„ú,„ú,Äú¬’ñYÊë³HëSÅú,û,Dû”ŠöI=ì³\„`ŸE’Á>‹ ‘o‘ ìÆÕ‚}–2öi £}IFû,DûtÅ ÷YÊ Üg‘ Üg¹ á>©xI„Ô{K”PòqåÑçú`™’Òè[È—©Ðo®ú׉žð¯ng©×§¢L©G$()‡žçþd/²¤T™«¢ T5â¥O‘µ•ÄUQ¦ª$øoO„ôìÁ†çßN„äÿÎ|×û_åDúQö/Ò#ýÓ„2?§UïlxÉ ó»IÔÂIoɦĚœ 5•HªI…XSÍ¥„šJþ£¬©¦?bM.„š–LJ¬IùP‘Ó©a5%‹kqî#TSR©bE5‹5g>Êšjâ#= *„šþ“ìHñ5eÂÿ¼ìHgÅüÇwõûÍúøß>$Ÿ5ó÷ÉšþíìHý}çþ?™éÜnü9þ÷73#EÑ™‘Bè:ýïGf¤µÉÌŒôîpT á73RÈþ/ýïÿøŒ™‘Žñ×™‘zä!œoüôkà> ±É˜/æù­3"H_8ºØ#uzDBëˆÎÙ_É|ãGîÝ<•ÔŸü÷ #z4oüØÚe´ñgCv _öû“'¼æñœiíÏô:;Îd÷§!½NdìoìçDz–™Ù—fv†Û:²ëÄ—…lüFv~òýéÈ®³ŸùIóÝ[ÏœG0õög »NÄsžý²ë'¾ˆGTô™!>¥ä@v_Õ^'>jLÁ‰ì:,ì}†™Ÿ9™zzúÄ a¦g8pð°Ùu\oGv]ô ¹Nœœ‚Ü:‘8z÷l[æÖ‰¼ÇìÈ­Ãt6Ïv ·jyÂÇd&gp-'Rë¼’ùQù• µRH=Û•©u˜ê‰`~3;CD<§¤3·Žš~˜[gÏ[òDé™Aeö ¹u˜¾êÙwäÖyWŠyâ «Æ>jÿ"ŽìQcß?á’ÓîÚŸÄ8Ó3´<½úÌH–m¹èFn©5 8?г?È­ã"¹u¤Uœ*™Ù,Ù‘[‡ÑúŸ8·3Ó3¨æ8œ´ NäÖa‡©u¤wqšÉ46áU4“3¸šŽÔ:êq¸ õEÍp]ÉÀŠˆññ@Ïù>jeܵæv ·ŽZo ¹uTs;‘[‡J´3Sëè¾´ ¹uÜÒÜ:Ò³uäÖÑøµ¹uTï@juæÜZG>wäÖQSïë ¹Ñ$iÈ­ãzN$×Ñíˆ#—¶:EÇ I[+ïÓó©JD ݹzOž%ljä:®øBrÞq„v©õL®ãz$×Á´3’V}Žx7ïõAñnÎä:¼¿í`rTÓÚ†Õ›:µ6rõÖдWƒ¹z«{íê¹zë6´H|Z·‹£Å飥©Pá(S úøŒ3㇕ŠóÞɱcç:ÎøLPךW2rñVßÂïÚkÿÏðV]t<ßþßÏÒ·ÿ}y ÏçÄÖ›:ž£aïÍç0^ͱz‡¹zžÅ×L‡äaˆó¾<†ñf>ê³qÅI›«^ÃOHÜèüÝœHf¿íªàæŒôG!øÅ‹èÉo£ ~=•ÿQ¸OgRÄ}ý†÷¡¸¯G,ÖI!ä¾yõ,Cî{ÿƒãQä¾pÊ¿ó*p_X<òh¹¯ I¯È}=ÎÏ£E¿èEÆ›#ø…$cÒüú€3x‚ß‹ByîVà÷l|V~ÏwI_(—Áù~Ïv“ê~aÉP|$¿ø*–g¡H~/逿‰~!I¥ˆ~‘*‡è÷ì`-ö IFð#üÅ«¼%“%üÍwûýG¿¸W²à/ÏW$éïÙá“$ú É<ú#ú+’Ä¿¡ÒKøW$À¿g‡?™ðïÙ-^øg ñ/$s ÿB2OÖ ÿ^KWVá_‘ÿB2'œð¯HÀO$ʶÀ¡Å‘e’ÿJð߉p²)ð_”™§žÄQfýÿ¹ò_HæikòŸ+&ÿ•‹€¥ °H€E,ÝÆ®oÏš€.C ɵ G‡e¦‘G5ÏçFXjN,E@€±JlYX*ºË$À¸êÊ2@@—!†äLÄú*"`¹ X$@@÷™èá!ú–Æ€¥0 %ºqB ›"–2 ÖŠX.z”I!y²P ;H |˜˜„¥-``¹ 蚉±Ì3ªÂ@÷‡míIlÀÀ'¾Èü¶Ú‚ ;C,Mߌµ¥†‚å*€`)t’ k& ºÃ$Á(s$°ËU A·EôZ ,ƒ=Æ$ÁR1PÐŽ,è2dA7,° 5' –2`Á" –¦À‚¥ X°Ô ô% Zu ,Â`¬åO`ÐË)iÐË2hÐOi°–j€ƒ~@‰ƒ¥ pÐ#qЋqP÷F8¨2âAõP<¨!jyÆä™þRBuY@X*–2ÂÒAa¹ @è.5+„®˜@¨ÑVÉÀZ®z@„E",5ƒõ°‰KÍ BM¡Ç”DèzH„E’DèÆI„ a)",M­‘°4•HX.–‹À„zHĄ֜L¨GKL¨GTPÒ–õ = …¥f@a©Pè £LOÉXn±0 Œ¤.`¡Ç†XèJÈ…VŠ\èî‘ ËUàB­DâB)¹P»Sqai \h‰¸Pz ­Á°ºË$Cw™h¨zþ$I¢Ãwµ}^Ä‘1H‡§,a0ápÄáþit#ŽÞàÖ:lq*c»‘ã°T…÷"å[ÀIƾ’˜×|õ€ áðåÖ¼ÉWT¾eàù@8|%ð ¾’ ®2ÏLúÙ64˜}µ¥Ïáð•\¶éWÏJ†ïÏ&ÈpÆÈ| ÷̙ÞI$ÃW²€A†31l™Î2W%ÃYÏHɃܫ׆‘N pmËÜ«‘0¬’áìòSÉpjyd™†Ü«.s"÷*£" Ý8Èp¦»M:·Épqnê@†ïU;éq ÷ª*Î2)Ø‘z5fn²Y‚áÌœ;R’`X.J.ô} ΖZ^”\XÛ¾‘yõB(pa-’\X\è¶…ó6¤e.©pVÛ²HRa•L*|WÎ`RaÛ@L…s rW*,7 T8¯Ê" …ÎKL(,(,@á¬8?: KS€Â9ÄiªK&,C&œjÞLGlß90¡s+“ k5É„õªdÂ2~`Â[ … çPäW0á‹j,M ‹â@ÂòP Ë#$,P"á\Yq"am*‘°V“H¨ŒÐ$Âù=i›K"ôº",ˆð• K ‰pÖ»W"œ’;¯J"œK1‰p6µW"ôšI"¬e’ç’˜ ˆ°Åª’D"tno¡@ᔀ·ª€ð}- Ì ¡—gá¼™•=ÀÀÁrŸ€ƒåVËR,ÏpЃk5IƒeÈAƒs\YͤA¿*HƒåvƒˈƒË] –¦@ƒsÄócQÒ ^À`-‘0XÆ0ˆ÷!I°¬ø Áò ‚çdÄUI‚Ekà,Ó³¡$Á2…A‚EI`éHÐ:%Ö ‚¾MàÀÒp`•$–û,÷È‘º·„@ßHB`•$ºZB w „@' ÐCEt µ; ži„@e«'–j’« PNô$zy"z›Eô<"–î}[ˆ€^Dˆ€^ˆ€V è½ðËxK÷€E) &ù¯Œø¯ÜËä¿r»Áµ3N×|ÿ´.ÿJKÀ?¿Xˆ﵈ÕEü+wøWfð¯Œ9ð¯v'ñ¯Jÿ<ÄmÔ‡‡ôWú ú³J€¿¢àÏÉÏà ð+#ð+£ ð«’?¿™~e üÊ|ø•7Á¯ üʨü<*à¾2‡xöZýû¹‘Äz±ªmÇÂzƒñ¿{j¸×¦£É¤à^Û"ršþˆ{ˆY&q¯ÍýÊ{0ñ^ø§$ƒ‘÷˜>ɼ÷àû§yÏeÈ{£±-òÞ±›÷ÆI"yOð6y/–¬må½Ñóe`ÞK÷ÜÂ{{˜ºˆ|Ñ&…|{è’‰|ã¡Èë#̃@¾R3/êIˆ|Q&ƒ'ù¢ @>µNäÛ÷‡f= _4ž[!ŸY È1íú‚|áÕ»Ucà,“ßg|{Dì^/íªgAß2m)äÛÃî¸ _Ô“;u"Ÿ›"ó)螘Ï]&ó•«}áÚtÁ<ˆ\aÈ2€>÷ÙÐ×3ê(¡O·FÐW$€>7Eê E÷j l¡^Z4‰}ûŽèàľèÍÓ"pEªºj ôÜöÅ쾫1ð• ˜#È}¾侨öKp_܉³ž-]6÷‘¢È} (ð‹®à’œ–¿°¨¿ˆ(Y~~¥)‚_¸`Uc`©YàÇÄà§«D~M"?µ.òóU$¿A›«ÈO¸Còc ×“ßÀP“ŸCèÇ|âF¿dSB¿AãƒÐoØô‡\¢\ ýŠ„è¡†³b¢ß@£ß@¡ß¾!дÐÏ7ÝèGš&úÅ´Ì/@D¿¨'?Pý\ód?O²ŸVJ³ŸºGö+üE=y’ô9ª1°n‚_Wtæ³: ֦ȆŒ¼l6d€]³¡FYl[ ?°!ƒ‡š ŸŽDbÃwYt’ ÝÙá1͆ãXŠÖî Ggn+>H $6T¬|³¡Zªu±!#Ï’ C­T‚lMY1ØPñ;͆¾ê¹”CW Fg¾xxlèIH6 I¾È†tÏ2`C…ÏZ-²¡ÂðŠ KÍ7¢3#ª¬Ø°46Ô“.6T@b±¡GlèlèÞ ÒÙlȶfCM0²¡À‰ bWlè‰*6d,Z³áTUbCß ±¡Ö"±¡ÚjMK6dh³!ƒ‹ ýœ‹ 5-Ću±¡æ¿ØP£.6Ô'6T÷Ćz²Ä†šLbC†|Zq²¡Æ†lèEOlÈ€ÄbCÅ»z‘ ­Ø0&Ê]Š–ÉN6ô|#úÉ'†$W\²¡'%Ù0¢çš"6ÔƒN6ôx‘ ã®'ÛK^p¨·³àPÁ ‡ û,8ô‚F8ôè­(áÐj ‡~A¥ºà0Þ(Ó¡ÓpÈðß‚C=5‚C­2‚CMTÒ¡b1‹õLˆŸ\t¨uÇtÈWèP éP¡ÇE‡š§¢CÝÑ¡›F^Ød8СQÑa‘€‹tß³X µŠ=¤CÍÑ¡6&¤CÍeÑa¬îwVC:äfAtXš*ìºè°”FFáì èPaþE‡¾¢CõXt¨ŠE‡º7¤CkN:Ô¦Ht¨[t¨xÛ¢C-{¢C÷™tXZÏõ‚³‹tèÛI:Ô‚&:ÔËGt¨èÐéPY$D‡¾Ÿ¤C½%D‡±ÁXŠ–[C:´š¤COeСÇt¨5Etèg„tè¦H‡êòoÒ+ù@h_®xE*æ× ´¡Ë`Ô¼-.ƒå*¸ >'3(ÓeÐmÑeðÝ ‘è2ø\;\é2h-è2X®šÎ (|‰ó\HÌi—AKè2´,F—Á8%˜G—A_E—A_E—Á½G—Á°DU¬º ¾³¬J—ÁH\’eè2x#Ÿ—\Ù¸]1+ 3˜sâ]ïÆtŒÝ $pdãrdÿì2誕ðˆ”{+¹ ÞÈèh—AU,—ÁðZM:£Ë ê‘Ëà\qvŒg%A©]oäõ³Ë`|X]ãõŸ­Ãe0"â®.ƒ7ÂêÛe1˜ì2ȉa—Á©›í2¨!¤Ëà}ÒlH—Áù9í2xŸŒC—Áûâ9Oº ú*º ^FP.ƒºér¼ð½Ä.ƒº[r|Ÿ¤«’`™`r¼nzÿÑePó”.ƒš§r¼/„¡Ë`œ)Íjè2è«è2øvŒt¼*Ó.ƒ²‰ã«ä2¨I(—ÁûàIOº ªu¹ j¢Êe0N÷Ö¨1žrÔý“Ë «¡Ë`„œM<£Ë %tä'—A \Õc¹ Fª Hà2Á<“ûè2x7lŸå2èÆé2èzè29RB—AuP.ƒW§; ]#/pb]Õº\µ^¥Ë †X.ƒQ¹ jDå2¨'K.ƒ÷E»!]¯3“¯ØePõÈeP–Ë ¦Ž\5ìrtº ºfº ê©¡Ë F].ƒu¹ ºº ºº ªŒ\õÈÒeP7O.ƒšrtº j¥”Ë >¹ ê1’Ë FP.ƒ×Eî£Ë ËÐeP“@.ƒ ¹ jÜå2(Eé2(µä2¨ñ’Ë ÆK.ƒZËå2¨I(—A_E—AÍv¹ ²;vä”³Ë ë±Ë ËÐeÓÉ.ƒÜàÈeÐÑeŠÚeãn—A>²väûÑ.ƒTK.ƒj[.ƒj\.ƒ×É3œtä µË ËÐe/$» ò¦Ûe¯:» rÚe;O» òŽÚePZÈe¯:¹ r“k—AuP.ƒ|Jì2¨.ËeÏ]Õeº j,ä2èŠé2¨Q–Ë z,—Á·L¢\¹)²Ë Ú’Ë æ \-¡Ë &†\Ý:]Ý:]ùˆÂePsR.ƒRS.ƒº1r Ÿd:º òq´Ë Ô”Ë n¹\Õa¹ jþËeP÷\.ƒn‹.ƒjK.ƒºÃt”rÔÝ“Ë ×{» êÎÈe—,K¶^Óɮƌa"#ÇŒa¦ ÅŒa’"¹™ï×Ac:\ 3†…Œ‘€c$`À˜[Žy c ÆÜòîcÀK.gêÙª°ÖÓ©g“°V2œª' þŠdw²ž–dw8[O«gD«ät¾Jœ°’Ë { ¹°'‘±;_OµÁp¶žr>ÔáÙE~.q|rõü\ätªžûÊ5ך©GØW$ý“©GØW$ã“©GØW$À¾"9>™z„}Eì«’O¦a_‘ÜŸL=Ä>EÀö•"À>Kˆ}¾ŠØW$À¾"Iì+ÕûJ`_)ì+eîO¦a_‘<ŸL=Â>Kˆ}Eì+`ŸûCì+eÎO¦b_\ŸL=¾"éŸL=¾"ŸL=¾"Ù?™z„}Eì³ZľRæüdêöIb_©ØW$Ï'S°ÏbŸ¯"ö•2‰}¥°¯9?™z„}Er}2õûJ™þÉÔ#ì+’ñÉÔ#ì+’ý“©GØW$í“©'±¯þüdêöÉýÉÔ#ì+`_‘û,!ö °¯HŽO¦a_•|2õûŠäZ3õûФ2õûŠd|2õûŠdW¦ž…ú,ôÁÐBž Ÿ > |¥YŸ‹i¯x%×ùQéz˜i½vnB¯~¤J.3UØqñýMTâÞ¶Rwü1Ë\Dð¥7÷‘û‡R¦ÝT CqSK"6Ú2÷«C_ëyux–a¿ŸÌdzo¿ {*õä}ëPaßø`uª ¦û«ÂªTUhKC½Ý©Žü¾’óÂÔËŸì¿ °ÿš‰3Žvf LÖ\´ŽˆücÏgÛ–z#žüzŸ* –*Àiô¼ýÇó÷@òöÕhÚ—q˜²âž£÷@…Ò=ªàz"©À¢Ô°Ùz›‚·¥’±?Ô ÉŽzg4ð|aò×úT¾°6uòE¯×zQÏl<¾#Ât®e¬Š°ÿÔh›Ëãï”?œko%{U)–Ä_G}(cé¡N(BøTÆÃ³¨““ûò*p×Ç4Æ—wI’ÁGýÝ©ÊìûS×¼—åúÒÿx¯ÅËøÐ3°O»µ ô^“cßÑ}ö>B—JÞ¾ßk+c|´9¶ÌÂãÑ>öÎû«ŽãsM»ýã%¼¼È·¥³ÇÝÖ9÷Éñë¬OÄ~°ûRú ®'&ç•"©~N‘&!E=%€¼(òÜä1ŠR&!/Ê\9l{‰éØ{—IBªe’òª$)¯J’òjR…‹_#.ê  ¼R (¯_(ˆW $â•jxUb(IDªõ$"©¡ä»Z ù.$gŽæ<^ÐÝu´Ñ×®íô3±H?êJí€:øÑãÎ[’DçøŽ¼u€ºÚ«„ºRfB])¨«vÝ’µ÷@ºZ ‘®JétIò\éýÃÞû’½Ï-’ÁÛɺ¢€® -€Ž]ì½/IRD!ýL’«M&ÉUI’œ.a¿Ý„û½"Çá’„8_@ˆÓŸ“àô“=fÈoU’¤KjIo*èVkHt‹KPfg§Ufߟõ÷±Ötc#à¶Z Ñ­JØqKÔ÷ü™à£ŸI=µ|r Úôsïuäö7fâšþ˜ Sê«UI²ZY°š*Yû{üè/(€h¥­4F«eÚ½èÑØuÝ=0ššIº©•&¡©@âY-x¶HØuJ€g¥gÀ³Z&ñ¬JÏØôd3ýP¿UZ]ÏŸÉ5ú™PSË'”©@B^ì±FêúÑc Y•´ëótÉTíUšŒÕÒê´$î7%cû!¼'Ætœ[0Vúz»÷¼Ê½g™óüè«’{í h¬Jžý3©î:€ÆŠ4V®UÉqîp¬J¬¯ú¡pŒ7f²˜~<ûG€X­Q½Ÿ?w’½×É+5€Áê%çùÑV%ê·êékÏ&„Õ+Æöë+Ÿ9+³g¨û’X^Õ®Eòo$)‡=ÇŒ©Vmô‡´±mh2A¬|*ˆ}Ð$Ç…§1å ˆÅŽ`µµvþ¢ ?ØÄ™Æ¬ 6^z{SóùŠÃbX,v©À“%  †ªv“RŽLÝ1À°Ú2,m…¸ 8ÂFª$¿×DˆõÀVõÁWošÚ‚-!©­”©ÍÕ@ÒÒ}®•L[U„=‡] –¶Xq,m~ hh :]mmŽ&0öÿ™ ƪRÖ*w†æ67k[DXÇE°¶¹çGƒ´¶^£R˜ª\­m®ƒÖ¶W¬m1¢¸Š Üérhs[‘ÀTåÖin+˜ÛJ`n+ýI4À4·y¨hn³Þ4·¹^šÛÂe`n‹h‰(s›'Ím¾u4·ùÖÑÜvÖ`k+•ÀÖ¦™˜¶¶a Óúßá´µYGÚÚÐ mqê.°³yvÓÎGˆ@\è»/B×ýÈÒÒæÞÓÒV:KÛIÛ– hfk˜&S›všÚÜcšÚ\MmÖ¶6·N[[)CÔgÚÚ<ÒÖæ›K[›ommºS´µ¹iÚÚtwijÓ¢¥ÍO-m.K›ZÚ\„ÝgWö¾U;[éìlÖv6 íl¾ÓýG½´³©'4³±È¿HGdªk[¦ž5ÕE€·åe9Ö•TY®óULª;:w¸¤:‰¨N“GTçm©Î›^b7sĺ0E­Xw¢8ž[ß2Œ¹.lM¨Xv—Êu×Áþì"\jØ]7 ‚P!b¬G(ヌZ£kpçL°ƒå†T@` º ¬Mu¥ôÿÞx˜)±."[á÷„¢R°.±À@¬sËäº-À#•ƒ§û)A÷ݹ.¾+¸€EsçýgÁ: ¹. p¸\±ŠyMŽä:6¹.>Z.¶Ò¹.ÒæX›¢ëÂç öŸwšTç¡"ÕYiRûGª‹00Óeg ©î•Ø@E¾Õ¤:×Bª»’)©îÞ¾‡(‹Ä:°fQ‘<æ»Ò:À®”«$;_C²ó½%Ù¹m§4鮔ݕ2ÐÁzï®ñk¥»R ©ttç2 x~~xž<Ï2žŸ2vž&ù®ÔÀãì¼  ó¥ÀQÄñ¡$áȳ3ñÎ%ˆwz.ˆw×Î⻇gˆw^G‰w×ök[ñîÚ°ÛÞ¹)à—lâWâšÞ]{~ôÞ±VѺ"º /\¤’ð.ÎH ÀQ¤MØ(Ž6¬t9’ÐèNï%Ñ]„ݘÂ]ºYÿ)¸sïîôúܹ °…l§wØî¤C¡ØN#E´s÷‰v\°Evqº¬²Ó-Ùy0í4ƒ€vîÑNCË3”}’]‘ítßIvú &²ó¸ì"}*H dç2D;ëH´Ó.h§‚b;ßg²o+ÙÎ7’lW®ÛéÖí“ì¬6ÉNßT…vZ.„vÒ›d§åBdW*¾Îe&’ìÔ;’ç<ÑÎC´ó#Úù®íô0íJ* »B´óÐíÔ?’§Q’W3’ûK²ó0ðeiz¬ûg=Áν#Ø ÀÎÝ#Ø•z¨‚ºC°“–Éu¥pµ$×UÉøèD°s=$;ß9¢o ÑÎ7ÙÎs‚l§µ†lçé™pç5.á.‰ñÈäF•xàN£@¶óRD¶ó&Û¹!ÂüßH,dW¹vÄ1¿zŒ² ëx ñ€í%QžÃîc”>¸Ès”>ÜÈs”á4Ø<…xÒ9‡}¶‘ç(ïÌöãs”> És”©ÁŸæ¼ôÏ9ʈÏQ"D¾ÎQöÌFôWç(%ð1ÊäD ÔŽŽQZ‚SˆEÂc”®Ç(‹Ç(O„–÷1ÊRæ£Až£,Wàe)s”íäQLž£ôUïìp޲\…ƒ”±š¤ç(K5©‚/yŽõ7Ž!º»O°¯H€}eþ j0>G6k™¶îŒJ b¶;ã˜âb¶ë È@³]{èØžv»6èÇN»]1õ1þ‰Ì6²Û)”‰ìvnB³W‘( àSP,aKÅî¶_ËùÌ"¸Ïå'­vÐj'»¿€^Œ€/ h±“€; h¯“àÛñ¶vƺís,³J`¬Ó%²ÕY Ž©NEh©“€¶. h§“€f:×J;ŠôµÏÚOÚ¹TŒtE2V]d¤“àÛóË=g%´sYB+.¢•Né|ÍóéÚîËNW$㣠u–ÀRW$´ÔYòCšêŠ„¶.Khª³„¶:KÆÚãþC‡þCYë,¡±Ë˜ëŠ„æ:K~èÐè {oŒÌu.Bs‹ÀZçŸc}ö÷wš»$ ©Nšê$ ©N‚oÏ÷º,ŸÛCÓRg Mu¬d¸ï,B3—ŠÐÌå"´Ô© u.BCЏû,òí¿ít–ìÏú›v:Kh§³Ä Pb ^4t¹ ]–ÐPg uª†v:Ù­°ê£ìtþM;%4ÔYBC%îÿBoµí\–ÐÎU$c}€l§³„v:6u|4€™Î¿iå²fºpÏ€f:—¡NÍüèÿáþ/Ç0«iŒf:Kh¦³„f:K>´ÈNg Í\ìÌ_Øé,¡¡®H¾*ÈPgÉÞ×i';‹´ë£ìtþýCƒÓPÒ¯äÙ?JÉPW$ã£ÔõC…Ë*PrÜ_I»>ZÉPgɵ¶-C%?t¸žu«f;‹ŒÏ–Ç–:KöþQêþ¡ÂýCYê,¹ÚG)Xêü»6m¶ÔYòCYê$‘¥Î’½´’¥Î’v}´ê?tè׺u³©ÎEúòtÈR'ÁølÞl¨“äÙÖÝ›ít÷ò"²•ΕœçGÙét‘{A_»+϶Çf:Id¦³äÛûñí½Œt)¨É}Žk›sËy#ÎH­Økr”©É}>…|™“ûü¼êo$÷iï–-ÚõJRRé@æ¬ÔŒÜ5ûÉïfÑ6w´µërúÖUÓ÷°.—b]µê*é{P×’¾u•R¨k)ź”À‡U•>¬IeXQ)Ãzœ¾‡Õô=¬É¥XU-ŇÎé{P×’ä‡ÏªK¡®ÿ$ÉÏ»Q»fº³ÿI~þÆêùïJø›µò¿`ÖõóŸPk„PŽZ¯H¿:%a'ÌÞ¥3ê+‰½Y‹TÄéYõNíØ›µøw¡åÔàÚîH³8%©A|sK7ø£o×”œ-ý…޾ŸsÙ=7œßy9°ÍÅÚEÚ1ëýf{hpEÀüN ®ˆT:ö{›’kƒÃíLãW]8£|ôû³vuÚaŽþdZ··Èɸó6¼‡ ܰC¿˜š\ŒÛ}<1^ÉÍRÇÓŽ©S81g—ŸsŸJ¹õçŠ÷÷¡i š’Gµ@…°þ£–þLI¤…OÁÓ§RahC‘qO¥|Q„hûÔOìÿÆ~NÚ‚ "Á(Ê´|=º73lBL K§¤lªAò®Áïoäóßcê”!Þ¥;»ÿ\¿(AÿßNoŒø>ÕâciÌjÛ×^É;AÛö|U=5zß–]pänú?sKNAvÿëµíÚ¦äi°l¼’1z:6Øm»GKCËýÉ›ÔðÔ¶- ÇóÇX'ïëojàám{jƒ™Ží¥è)‰]_ Ž6Ušì:í˜*E*/\sî©Ò€‹Ü»JmÔiP 6D,h/K¦¤Á6ÓÞýcÞ¤†kžž7Iƒ·;ïÓ†Hí˜É.j™ŒN-£¥N7–Òw<æãÔo˜Óæ6í^Æü}›æÔÛ8¢ïB˜÷…Ç‘ÚAz¤vž’©Ã¸°Î´÷Ɉ¿?XÚ;ó¦NaüÈ:Þ››Ó¾ö(uÊÙ8uÜ•W¥eÖ´—Ok§Àx7<<¯dä‚°å’ÖÚýäwÁfþ¾-ú\¶#¼Cv¹MbaÇïqç:™uÆ‹bÏ%:Ÿû95z—&Üëóh¹0Âv‹½Ã\⎶ý¿yXóíCöR0R@sÞ» fÖLÖÑûT'¸:Çà|îy‡2ó”ÌQŒö…þ_<,ÛâU’ðÌM•cG<ßCÞ›ïL.xû½¥÷Tˆ.‚sÍŸ =\8µ½SéìË…îß g:×ݾŒBLÛ¹dŸœu1½F¾ð¼½ïãúŽi74CEjp§^øÛÝŽ”¨ÞäØyUC™¨r¹K÷5¦Rºý÷ýÌÍÁÅäbí† 1×Ðøsã.QÍw§—J1é@ëÛ™JuxÕ¶÷¼t8ÞÇ{vø‚*¼·ËL§ 7^2mfjHI:Ѿ’¹ ª5ßOÞ©Æ¥²÷žwʽ7ÃÀ¾Û*è€D/VÍ=Pò0Ïž{ ‹cí}%/jÇ yφðÔÆ ùXš~¨çÚC NNÐiVÏ>pQÏM{÷äÈCycw2;aÐàÄ$©A™%ã88ûr¡|ßÈËïãU¥xÏaW™+·q¿I½‹JjLˆ2ý³ jã™» P!ßëm ì‚:ºwn›vAùÔÛžû8 è¹Q…kܹ¥¶™çûRÎO¡3^É{Žï…+®Áǧ¥àÎm\)^•:GàzüÒsn€ü}•ng>O™wÛ{ ­,ç~ä.Î:¾¯Æ¼M\„ß5x/SæÜ¡€UŠ7ò^ž3ÞÈG!çÞs¤þîÏÍ!Ÿís‡º'ç‘øi:î2eÎß8ÜöÑöåa:3÷paBC‘k‹W6#÷tä~8óRÇ£w®z–wïÊå€Ý¹ÒÖß·´dø+ÍH%ÿv¦‚^,$ïU-‚÷Ößã£Õ n‰:X2îUä+½òM  ™¯hæ+­ú–𝒻BßRækÛ=OU”¶Ÿ‚€¼s§VwžU2>÷êø¡ÃÑW½û–ßãþè”ØWû›ØW[nÔ@í4j`ɹsþ±æ+O'TÉà3Ķîg}†À}K™g½»Á}µÖ¿Z"Á¯Ö‘à·HÚñ¹O§5 Ä wI~K[w°5X°÷ÏìKø[$Ô-]ÔÁ’ý¤m'ü-’v|f_Òß"¹¶Ï}¹¨ƒÛ¢–ôþ•<7µ¢d\Ÿg*ð¯¶t[J¬%íøÜ+Ø:«äÚ>÷*ño‘ÜÏG«›:è^%ÿ-eÆõÑ*ùo‘ìkÛÉ‹Ä:`$ºu äÚ>÷*ùo©ç~>OUòßRæ‡ý‡ €‹doŸ{¸”hÇG«ÀÚãÇ:°Œu`½÷ó•ôþ¹W‰€‹d\ëÛ¸H¬®J\$mKÉ€‹äÚ>÷*p‘X¶ÝûWòÜ­’‹ ¸Hö¶Þ0`i}2àòû\ž!0àRÇ5Ög¸H¬%Ö€-ë#I ¬­'Öz’ËÛ xÄ—ÉÔá9€ÀÀ¥Ä•;£RæÎQ‘ôÜ=ŒL\ê¾ê€.“¸”Iód-Órgä¶’ɵ}~j•nç Á¥¥Þ?Z% .mܹf¨ê ¶šu8ÓÐÿ÷ó Éì—ŽŠ¢Á8“hŸ4èì'¤A‡l% ÆÓ³Xþ^ÉMchp¼¸Ð!épÜñÝ“4GhiSL˜áìÒKñå< ƒc¢ÙŸfÁì°ÐM ÞßwaÁñl˜¶dÁT³ß{Éày" `H®…k5è~Ü”A÷ß»S&X°J’£Æsâ[Y0ÊÀzŒ2F¼Tá@l,²àxLY@Á¸¤Q’áñJÓ‰‚µéDÁXãÚ‚‚Á&4¾Quæ± `v àxòȈH°C€93A°´üPõ÷¡ª$jÌmÖŸÆÀZKb`é0°´ Œ«häcÿïÕì7Ç38¶’‚¤À¸˜ô“Ë@kµ_ 5p Ü_B`•$VIB`TœnS„@ !Ð÷–8žÁïÀ@u0°V’ ¨›Bó\æŸ&@ °J’žÜ 0Fw«v¿ª#°è¸³ÿ]öD÷Ÿežj™þ¹&°( ,ã É^í~µ o70´z,Z=à¿2‡UÀ;úz#'ÿÕ+’ÿ\)ð¯\ü+ýoî?.r÷Q/è¯J’jÅIEEÐ_HN4•ôW¸=}-1îÚÀ_¹G€¿è ì·€¿ÒÀ_™ 'p+€qü•ÎþêU e ¥Ë©ºwQU ö«’ä&-2D¿2§€~~A~^ªH~¥÷ŸEšJÿ~µL‚Ÿ5šÜWnÁÍþ[ÂþK#p_©ÜWæ¸Ï*ûjʼn}±ÊÐzH tQSYe@}VÐWº7¡¯þNè+ãݩ߬„>¿Ž }cz.ýiæ‹"$É|~½‘ùj5ÔÀjÀ]™Ï»2_éòd¾Ò6˜/jyÌWzóPì(ˆ|Þ–ùjŽS)Jm(Iä‹Ãz<~¨0¨Âk‘¯tp"_ _ Ÿ7mD¾rÇ­m[ê ÏwÄg¥H|U²7*5 – |Ö ÏãBà+U\ØIp?Ë<#íù&‘öj³ í×{~P{Â^Œåƒ2m§>4~ú¿»ÿh°WËÜØ¹¥„=ß5Â^ì•F5úÕ2€=oÙ {Þ÷öL„½¸å®JØ Éƒš¯mé1`¯^“°W% {!9`åKØ+ãØ+=æéo÷¯ýÐgÆÙÖ¿J=$Àϯbís*òÝ ñ¡¹EwÊi!º«’\”ôÆtÇl%¢;å3Ý1K‡à.Î ¦pçkHwÌ:¸sà w; ä2RÑ]˜*q èÎ%Ý…ar¥;%•ÝEĵ•îâ\D @Fáà Ü àÎM%ÜÅ1ÀT(%ÀFÓéëÏw÷õ…;Û…¿-hlgµÉvn‰lçÞí¬á.¹å@wåªIwå75(¨ á$Þ•zAG¨ýß¹ò]£ƒ© |W$Ôž?Ä;7E¼Óøïts“î\à.,×+Ü û"¼p p¤2¢;}MÝ•2T ë'àȈîJ= #*ºÓðŠî"6x§§G|§±ß¹ò])ÀãpŠïÜ;ò]‘Pé½[–•¦&y„Éw¥øÎµï\†|g¥Èwº¿â;-â;ÍjñU^©‡:¸?}Õ;¯ü€ç$¼"áiÈ xºý¼r øÈ}#àUÉà}ÂÈð¬#O 3¯”ëÝ'á¹/$<·LÂ+^©Ç´•ðÜ6 Ïw‰„ç‰OÂÓèð,ë¸ð<.<÷Ž€ÇWžÏÝ%๻$ÀWúòe°š?A}ïÏ[–¶p„Û"®Na¦#ÜëX=ÞÙ"ºÍŽJÓ•o{ÇaG™tåÛú¥# P ß:8 ä+õÕzàËW®‚/_ôÇcáÌ·õ®Ó™¯ôÎ|(àOQßÒP:ÂE‡q Î|Ñô^wN ’¦3_éÞCžõxgUÎ| ÇáÌ·Å·Å™o ˜w¾¿Þ8óE‰‹>S‡"Io¸-¾ÒU»^‹E7Þ|A#ûâÍej¦;ßß´!¡–¤;܆˜ñÒ.jîÕ°7ËìF¿Aè›—î|!¡ƒt(èáÏêñÎ)9q 2ýáª$=ú¢8À¥o]-àÒ’«§ï\ʤG\-sÏß Nôé IÇaÎôé«e¨ÃI'£:Ð+•>}Q¾mpê‹WÔ^­{³ÌUw.5S‡‹N;uè:8šq!áÁÑþ¬%Ò«¯JÒ«o‹Odõxç,ÖÔÁeÒ'®JÒ'®JÒ«/$<š^}‹d¤VC‡B©ƒ%%àÅ3½úêßÓ«/$£ï|oÆÆ­¼úBráÈejP%ÔÀõ¤W\”7¼úÉôêÛ·§øéÖWkžü7Ë,\C¯Ã±Ö ¿¾R~}¥øõÕ2é×WËP—I Š–pì+½ƒc_½jòßR&}ûÊŸã^®¹¨ƒÆ¾}ûvàÍJß¾ÒcøöUI:÷•¶áÜWæœûª$u=áqï¾òtÀ»¯< ðî+e¦w_©Þ}µDêPf>¼û¢ Ž}û¯~î/}ü¢ÌVwÖ«àäWÊÀɯ´'¿¢7œüj=Ô¿©g½üJÿàåç=½üÊØÀÍÏ{%ºù•¶ë@ÉŽ÷Jôó‹z:²agdI:ú•qŸŽ~å^ÔÁפ£Ÿw„ôô+:ÀÓ/ÊÐ q`gÄ}#=ýBÒ@~ÐAûQzúÅžõáñÎo¾"0ßÜž6ó½û,ºq#zKô©:õµ…4P"¡ïgEÚœ CHàVè;ž¦Hk }’’`˜Ì4ÃVÖcœ-FdTKß+aˆkB_Ä [œúÚ5” ¢˜S&õµ™“H}ÇC'SR_é¨/¢T/'9ß2rfõUIj0chÂ(—È»*VIdªe’úÚŽ`„¾w§Mï©Â âAƒ±1æKòRLžÑL^ŠŸÅd¾7»žãl1™”IæÛÃÖ‡0+©ÀÞ72>˜oójë››êKæÛã»øÂ|{Ä@=Á|{ 7õLöàÖ%€K”Y\ú憓̷_—BÅ$óEXP ˜o¿OÌ·‡Ae¨ƒ%ÉK!¹–.{¤>_˜o{E á²Gjðf2_ÑANœ.#óÕ«’—¢mÒ[òÒ®ó ó…æ<—™ÌË+v¬`¾¨™'>©ÃÉÈ `¾ÐŠÆ»ä¥¸ »ÏÉ|c2_-‘Ì·Ÿw`¾ý¼a7&óí'§>™oÀ¥õDgÕÌ!¥œó’ùJwêÀ$óÕ2ÉK¥‡“ùâÒ»ºô½%6ñLæ É ¦Jæ+WùöÈŽ£˜ ¦"Ib Í%’KŒÎ¹0_é˜/ÆâZ"¹ÌÇ>Ò9Ü?™ï}0ú˜¯Œ9™/‚©,‘\ʘ“ùâ‹$ԀɂÄ|Ö€ÌW%É|‘žy åRƘÌט@ÌטüÌw2-‘˜¯ÝŠÊæk]QYÀ|iVÄ|ÍÖ;j°ë4&5`Ú$1_©Ìg È|'SH‰ù^n[ýÞÉÍ8Sb>·DæsoÈ|o-ûÏåÎ>2_“¡Ì=ÞPÆ:Pb«IòR¹S`¾½)☯ôy2_y:À|ï"ÌòMžOD—2“À|å~‚ùJÁ|å>€ùâ~â)ó•{æ‹õߦÀ|QÏw%óEËéÎ:ÿÀ|å©ó•±ó•'ÌWëM^*ýó•þùâ~’¡CétðLó•2`¾èa+1]¢7}a¾¢˜/$ÛÂ|1oÏ%¨K-^:å® æ‹YJI2_A0_è€3îƒ:hnê`IòRè‰ãÑ“ùŠÞ`¾²Z€ùÊ ó••ÌWf˜¯Ì70_ôf[˜Ï2Ÿç$™Ï«™/ú¼Û2—’ù<÷É|¾wd>¯/d>?‹d¾èÝ@½Ô€3’Ìç‘ óUI2_iÌÏ+œËÀ|‘ §C’:pM'óyÞùj-É|ž³d¾XOHŠÉ|¾/d¾¸jTó_YÝÈ|e¼À|^‘É|^IÉ|E‹É|elêÀ§•ÌWÛN拱Û‚ùöã&ó½›&ìÈ|žûd¾2ÛÀ|Òª&+R—8~ÙJ—È »p¿óž²Ò+|Ëyê „o‰Ç¸š÷¦d!½†Aý$ê‡ÁÑO,aø–X*éMɵ†o‰U –¸ÔÀ¿Ï%¦¸Â·É­0ê€Á{M£è-°û°÷›"ªl×W²+Š:%‡¢¨SÒFö´ÛÝJîí‡D‘Ô)銤NÉ£Hê” …Rß«qo‘XJŽö•4%Á¡äTJ.¤»zþoòþfç{\ÉòÅn%‡UƒN胤$xjO Ø@]ÀAŽ'ÞnÔ¤ïßZ±ÖŠ=ofîÜålÀ“Ìç/E‘EñÇøê‘:¿ö¡I÷¤I÷¤I»¥$ŽÝÒ$ŠÝÒ$êC“(îI“(îI“(vK“Dì–þûùÑ«ç—><¿ôÁ±[R’±[šD±[šD±[šäg2vK“(îI—<ß^)vKû­Ø-™¬,c·4IõÁJ¹êƒ%Š{Ò$ŠÝÒ$ŠÝÒ$ŠÝÒ$Õ‡”d,QÜ“&¹~\£Ø-M¢Ø-%qì–&ù¥ŽÝÒ$Š|Ò$ŠÝÒ$ŠÝÒ%Ï^¿ôáøÑÆni¿»¥$ŽÝÒ$ŠÝÒ$¿ôàü¥ŽÝÒ$Š|Ò%Ï>9vK“и³K~ô±[ê·c·4‰b·4‰b·4‰b·4É/=¿ôÀ±[šDqOšD±[šD±[šäGæ/}pì–&9νrì–&Qì–&Qì–.ùÙ‡ùK»¥I»¥I»¥$ŒÝÒ~ÿÒ‡õK»¥I÷¤I»¥Kž½rì–&ù¥ŽÝÒ$Š{RÇni’ý{oÇni’_úpýÒÇné’çG¯»¥I»¥I~éÃõK»¥I÷¤IŽok»¥I»¥I~éÃýK»¥I»¥I»¥I»¥$Ï/}x~éƒc·4Éùm±c·4‰b·tÉó£WÏ/}pì–&Qä“&Qì–”dì–óI¥›b·´2?û Ø-í÷Ø¿uÌíÛ§ŒÝÒ$ŠÝÒ$?{±[šä™?$ŽÝÒ$ûù}R»¥I»¥IÆ·Åû/}pì–&Y÷^9vK“ܹ»³ªñ—>¿ôÁ±[šä8~ôʱ[šdl?zÅØ-uïã—>8vK“\?vF»¥Ižù£WŽÝReÎ_úpV‚^%:B’ߟž;c!§äÝ©LOtô£P]V‰Ž~½êo$:úµ9)é)…>UW¡Ov¢ù~oÿd'JI«J²ªÊ‚OU÷ö#gRJzU”µª$èU­cÆ4lgI«J²ªÊ‚OUö ¾U}žK{PÿëÓ/!_Åñ|Ó/mÈ ²#ò÷/ùmÚŸHàyüUª&ø™Ò¦€)ê_%pú‘‰é&Ú³ïß50Àë‰íø'[“jj–¢¦ž_É5U×ôÉÕÄšz~%ÔôÉ®¤šZÕôÍÔ¤š*¿RTÔ²+¹ž,ájz–&ÕÒr+E5=³’ë©2®è“¥Iïgˬ„š>Ù—$™a‚ÓìCµ¬0¹Ço›§úp:ý×|‘’{³9ã<Ÿ0Ÿ¸¦ã´¿+H|dÑ*ƒç‹dÑ«åÔc¯DŸfUÏ¡>¼eNÕƒ> ¯«K ÔÕW¿g€Ü‡Ó¥Lä);8V4@šüÖÆ±€*e®Ç‘«æ` –kÍ|ßÜìNE6ßW#ö ÓÙ“^IØ@o@Í|ŸotiÙ"i" ö(ï{9U]ÀÙ‚º4'j=lF‚”°ÕÕŒtBèÀȶÜaÿq#‘Úò„ýGè'(YêÁs¨ÛËÈN®=L'îw‰¥6c®#L' ÄPóÖæ¨FïÏaþqO›é¼-~ky¶|s©ËBs]a9q¿o÷£Ýa9q_¶›ë ëgó*rmaüqÇ‘@ö°ýxöCþÒ¯„¸l­7/vSÕœa7õŸÇþïp†ídz?®x†éŠhdÞ×ú-p\Z¥/·æÙ~Äåè^OM¼_1UJº:árÈa¹ã{s" Í#ÁýyÁWÃaõñl¶Kt´eز{,vðò{~GJóVÏ{…ÑÔCš†÷ûé;ªç}‡Åú¯WñVãG.]ZÿöOŸË3*ñ8¢T»ßž…ÏÏ2WÏÐKÝ’¨ÃV óQÞáÖ·‹žÀq/-“ÏÖÏ»ýŸ*s£5KQŸæóü¨MÁ?¾Æ+á«÷¾ì{ôþdûñ¶Jr„¥ÎçøDÞ/ÔÅ-)Y×6ÂÚzµSefX{  UkcûïËöŸkcûñð¹,-8BrÙs½_c<ûSßâ…oñþ©ßb¼5ƒ½’°ö¨õdíêÃfÏs‚wâφÏfשÛÇxnž¬}Åö“àR×éºÛßïóÄ}Ê"r½ãßxÊZñ)ŽuáÑGkáSý±¯äû™¾ÝŸ¥«ÔzdegŸvà^ÞÑéø!®:Uf vÉ6¦ë¸N¯ïã>اº×³ó) ×snûgtßOñçáCŒX%9îÏB°ÎóâbýH׿αøâlœ¼ïÎIí G2×HîúR#ý#µXjðc²©Ìuò£zgÍwìßj=^“=h¯:òUjͦIÛ+áÞ»Iö›köÌ«Ž»}>ÄŸU{-v¡=•Å.„ÆA•Dn¬˜š5ë:½Æé¢ûàz`g‘<ﮊŸ¡—™ÙƒÍ.T>Xq5;÷’9/ÖñÎyж0€€8íZ–ça‹ 3_sÞvþ.$æ]ÇüýCye†#Ì;°}”-1ImļbÙIóŽ{Ù~S˜×btæüÔý#)¯…a4æm‹D$ÆÛß÷@]1^y¤™ñ=SüFÆÛß=Ó£«ÈxXÚÖ‡ñp¿«m„¤ûÉñ€œ»$D<Ò šˆwN¿-F¼[f~~ÅxŽæUZJcÞ[Ÿ&hbžéQŒú8‚!¯2Š%ä½³a}!oœ²;$äÁZK4,È[@E]CÈÜz$ämöëHÈÃ&Z÷ a‡£2„<s’òð2 «yØ´±Œ!ÃgìSœ2×wãªä="C6ðº†× JטÄw9ˆKBÞér†¼{ËóA¾%‚bAÞ­Êò°„е܇S_]B’¡k‚6;\%ä[Þ‡pñ5‚¼ü™òî©Ìe y˜Ã,bÈ»–6‘b<,|C‚‡ëžwõ&¼Æo$¼Úçð°aÕ®ž„W7=vœ3àa ;Uj`MNø^ÅÖc%Ô&Y„ר@„UñüÞs&‡‹ðê£aÂ{Æ‘Wá=²¦4á=a¯ò<´Eƒ ÀCÐÐ¥:x0%ã´áµñ°åý Vs §ï±5¥êo=|#Þ´¹ItVÆ 5¶V4AÞƒWû y—“¡‹ò@B/»”h>°¢/rÞûÍ$ç…V]gjæ¼;—ArÞ’¸šà¤÷*»í%è½ßEM`‚Þ§æ÷mÛÙ<±ÞÛ7 –YﱤXï §’ëøŽYBVÂ>RÀ¬(‚çðmÍòºò¨g’‘õ¢êè`Ȭ—“‹¨÷Vì:zßC7™õ{AŠõÞjmÿ+Ö{‡âP§„{­1½·Á§1‡¸÷–ñA¸÷Öì…Z¸ó†DBuáÖ'Ö´WSÝ´GÉöÞ>:o¡aÁövQa;W°ÞÛÜÛ›°Ýð1ëaëq¨â ¥öTŒ{EmïÈ{o'§R¼7Â^S5«ÏÖy¯× Þ‹aQ—Ä{˜å^ò^¼,§Êï½áèHâ½·-·“xïÁ†Ze¨nÆÜ»TOðÒ[ó£3rñÞû(‡<Ä{aË¢‡KÞ{¯ºÜ§3úPõži 6K¿N=G…ïÅ’ÀCTßÀžï5ð…Dœ{ª»=XE|o{•ÂÆÄ÷^唀"¾˜ÔS÷ âëW‘ø¢æË„‡>¼ þT‰èÃÀ¬Ý:ñµ÷]Ä/ÂR-A|Q«öN|¾1:?!ñõñê>mªY}xwškD¾·æás"_ÅÈ|ÑOÝ Ð÷)¡>à[* TjÔ }1~zƒ}ï½/©h}m¹ô ¬ šÇ„¾O‹Õ‡a…‘ /FùéÐã¥gE苚U ¯1©o`Aш.õáÝcéÍ\êÃpè/Q_XS-]Ô÷J’ò‰}ë›f©õÙÓÇÁ¾èçÕ±o D×ñ¯&ZúÅ:ÒÉ.æò»ö Ý.ò¡MQÉN¤72Z½‚ÒY×zSÅZg¿³C¾,Vñ!Z$Rñ¥/‹U|å:/ß±'RÅw<¹ü†E’Ó‰8h’HÁ·©I”‚o+è$ü#ÏêxßEm‚¿s8šáo¼“Egæ¿gÿýü9o0áoö³6üé5/áo·—£áo<ù¥7ü½·Ö>Ãð·í ž„¿HmRéþâuWÍêÂÊ]…ùïtÞ óvøºJü—i¨…[꾄M=*üÃÚcm»ÐAS]€šUXItªœôÆ¿ —-Iˆ•ÌÚø‡5Ëv!PÀva$Ü ÿæãÝ ñ¯©b…­5¿°@’„ø+–Ñ}ØòN„§w—ÒÓ»ûƈþ&”Gþ*M½á ¢9+ø{÷Ñ:* ö{÷1F¡`¿Ö‘ÿ(ô{÷„Z€Œ~ó²C¡ÑïÝúx,…~hÚú(øš[ì×jüaM6¸‘þª‹¢¿wãI#úëÕ ë°’'àom>˜6ý5}´è"2Ñß:}júƒ#™µplÿÂæ@ÄåöïIˆd'4FOQô‡æj5ý-l $!ýá^V%F†Cqÿ0âZÅh0_ü÷î­Ôÿ½kÕˆï~ô«àöýµCÑŒ tH#ú[±]þGÁn$¿à¶é÷ŽQøSÍß1Òè· NR­ä¦¥·Hê= –¦®¸• “`(øà j~èÞO)øVh•¡‚ ÏÈFð{·`_ð‹'«#‘ÐðÁÄBóCà‡(ÕzŽRòa.>Vém4Õ°Ìà÷naSíG%_=GéøÖa£©øðŒ\‹z€o£(ÌÔžµT|­š;Ø‡æÆ¾w÷Ÿú:ªøê)YŇ.Yó¦à(E°H <8t’.-_=LkùP³ôÒòÕÄ3öõö¨ í^¤¦ê8µ|è•`ŒÜ‡ÑÔ&UÜ÷nÁ­ ’’ïEšÄ3uÁ3$!ø-iu¤äÃ}DZ¢¾Okù ¹;õÅȸZµß›J¾u¦ ”|­RA檴€Ôña1RLJšçÔø•:U1ß‚ Bº9êÈ`¦#“Ž­•nC:¾zQ¬ãkƒ)_Mqêør1 Šoaã`”yÓ%ý“4|¨Sûm©øêe³Š=’¢H:¾—áLºÒñÁkWã _oõcxý¤µ”Ž/­­¬âíÌw—!˜Ú¿œ¬Ô ¾5€Ñ ¾zÌÒïá¾ÇG¿×Z+ý^»“šÿ¥°Cê=ÜIúH*ÇÖ¿wÔ‹WO¸/õ^›Û¡ßÃKe½œÚ_ÓEú½6/¥ßƒ“´Ž'¤ß«>J½WgùVïµH½‡öŠë¤ÞkO_ê=ÌLëû¸ï©KÚ=ôéÖEÇýýMõÄ´˜H½·°ãWõ ¿'VïõÆP½‡NéÜKú½6Òïµ{I¿‡ŽkºÚûÖÁÌ?K²d¸ ó‹FwÐg˜ÜDws9À¸éîôÃOº[Ž"’twù(7é®ra‰î*’‡én‡.çkÀy[W’t‡ üÛ€óZ]³÷ÒÝå˜ 8ß5ß&ž¢»ib¼ÐUF€‡ý€ê1à9n‡ïxμ·ûCéûx_å¼*c ÎíL»IYpn>+‘çfî6á½–TÂY½—¶¢¶âÌWÌ„7GIe¤«-Õ{çJÕ¢Ô{°º‘ P¾º»ï„Jx´g¢Ì8Óèfœ9©ÓŒz.ÁšÌ8óû\fœNI]fœ3ËXÃ÷¤¨4|s¤îо+ 2‰xðÝÔ¨[ÃwúLÕˆ‡ý´èÁ¾²¤†o¬Ÿ¾g¤PfœÇ–w²†OÑ.RÁ÷6ØElùüPð]gZ/[Áw:‚bZqÎ;-2Éx­9¶âħCeŠó]d&_š3[Á÷®>çGÁ‡|Þ2³‚ïJ“a+ø6‡”M ßpøSTþ2l³'æåGÇ¥ˆÒJ>¬†3Îë~üBɇ‰®¡äÃ7^ç¡ÏÚ²[¯7ìn”z=X߈ ­Û}o‘^k±õz˜CÒÙI¯×îmÝdN ¡æ´ËH'vØ·É°×æ¢õz5Ê{Èk“KõáE%mX¯—ëFêõ°QùÀtÆzÂÖë3[#½^Í#ëõŽáwY´ ÓW¯wÚI%õz›§Zo·?™l9ë5µZè©kÔ…´zHµN¿j½mȈÀZ½2r°V¯VkõJmcÎ{ê ÊJ=O“%Õ’í9o<¯V/ãÈ¥VϦ å·'eBšs"¹ÍÇž×nƒNlFN™8ÐöœÏiŒ5õÁ|íy”ÞËù)S§·iÔ‡Ðëã¶w œš®!õU$FS_ †Ê˜*º´©¯)D¬Ö»¼HèK £ÔêmÆCßîð’©ÕƒžAàEèƒo—v„>„q¬ÉmïMväô-¯áiÓy¦1^ªõ®ÄKöóòÁj®{¶ôÝOÞKЇ7@p&èÛ“ }Û‘eL8Ø›^[ʯ^Áå¤5ôi…*èÃaŽÞPŽ– ö×21´ï^ó ô5†ô=¹Ó3ô÷ß½v¢.è{†3¦ú´N èƒaåW¯wá€úcÖ‰`<â.QßòmLØÉœÍ6‡wLHâK£Tߕˈ/Ö|eÒoàÃCü*öÍ¥ß^ª*M|›³EˆøbO!¬µYgº6%ñ‘Ê5;î%ý$ôŠ=ø+êuôÅ—L}°]gîwúÞù°>†ðC±©=÷ÒvÝÐß´$ó½*»e—]gNFC_ÄúGc¾š#†¾-••¦>´¸›u¦=T™u: q™u&&5ð³²LàT€&ï½"|›u¦YPšu®ó÷nÕÖx?Áoþ´êLg‹$¿wêié¡U瑇.F¿2ëMôKR5úí[zÕ‰œ°, ш~ò K“N¸¶u“ÎN®I~ç/î{{:ë ›0ÒÊý A#E~؉ …~p]X ýÞ |}ÑÊrÍ”1”Ð#´ý°é<¬¸0úµ{ ýÒÖÒä—³¦ÈO7Áo{üðå–s^€_lýmhà×MÒ ~ïUÆ<Áëµ ¿BLu.Ûü‚m?*£Î÷Uø~i'à—f©¿a?žµy-Ë^SàwÞ ‡¿bvé÷°}üÒ@;m:ßõÿÖ½DNí^"¿´oNòCô,IlÓ¹¥æ-ÐoŒô’‹-íåœ>b¿`[gŠý0?¾ˆzúÑð›l+*ö;¯ôTæôØØ¦³öçÉ~Or¦Ùo¥5&U|e}-ö›¶¿Jö»÷´×´Mg‘žÙïòè™ýŠnÌ~e¡+-æýñe?þtöë}0ûáUŒfö{ÒáNì·YdöK.6û=[ÚbÚ.5­Ó¦3­*mÓ¹Ùl+ùlcnE_º'ùÝ{¤é5¹)É/-Š¥è{`%úÕkHôƒrVÌ&ô«;­¢W=;£ßáø…~ɘB¿zòãËÊäwÙÄ-í9Óú>ÑÏæ?ʬdÕÞŽÍÛGµ7j݈@²²ª=@›”td<\l'¾Á îXke:™¸«Eb¡jïÀΗiöžCü"tsjö·UÖˆb< ‰ã£€ñà¾æ(+d¼¦sã!Zéý1Ý\ë§f¯”Óf¼òr6ã!è‡ÃÀòàKõ5ݼ¶Ä*A À1RÜärrCꬷäA•ñÕì•“ïšg†saÚ6KŒgoóù#m¾$ãÁIx}{uÞgƃsïùa<8ÿ;Ž ùè9OŸ$“ñÂÅ,vD'§Õ´d¼pN°êŒ‡I÷ÑëÕ «zd_téDÈ6ÁF<8r8„ËÃuá,“K"^§¨Öêp7îˆ5º;/>ØÆµóîë„ûÁ×@˜/ăÇÅÐ–Ž„†7_§ú€½¨ê½¹0\©;ÅHé Ê ÛtÍ~R^œ…M«ú~X«‹òš'AP^|F)öÚ÷E”WÖ⦼X4‘Hya™.íÏPj$Lyx{{|–°^?ºùæ@&f©´ˆym½æ ¤ Ö“"æõ»æ!7©¯ Fš¥@ FØýi\ÈyÍ«@œ×ûMÎ{ï“†Ãæ¼'£"-õ`¦öœœ7•|ëœÑoÙ6’óÚ¶Sœ½´ë]ô!wVâ¼Ø—h~’ó–!YP“óÞ2{ep^xXh#çŽenÐÃWÞê>öa9—´@o Câê1Zúèô2þi%é äùMéÁ‡Z”t©—sŠô">¬ë•ßr†ìtà»mó#Ôþut%_ìCäëFÔk¸éÁw%ÉÛƒFºJÞoïÚ¡³{ð½=7ÉëÝ6èëÅs8;ëõµÎnrƒ[÷àkž.‰{—s§_Í@{ðå¾2=øfa"î5I¾Z_ˆ{·Í„{퉧 _íVìÂ÷ޱö¢ÖôeÏÓ…[oÙ` ÷rýK¾œÉéÂ7mb+Þ Šq=êìKTÏÍ(‘Ãé"|U‹oœ%EÀWþOöâ{œûp¥>Nв·™†Bß2Aøªç¾Û1«Ò‹¯|òvõºvµÇ}G‰/ßè$¾eì$¾ËYGÓ‹o&t[Õ—ß;_÷.2ñ]ÎéÄ—ogßu¥_Ÿ¼ø@Ž*#âÃf^}À™•µ{g–½æDKo[Æ×‹/׎ôâ«>YÛ—«zzñÁiSõà².!‰/ßÄ$¾üR¥ß:“Ÿ¤í«zèÅ·¼£-â+cKÑR¾uI|åg/¾zš&¾ËGü©íçúñ¥¹¢‰o=ée(^§ïëÅ·g-‰¯f(½ø®´›5ñÝiôhâ«™o⻽ËMâéµPÚ¾Z¬í«'óe¯Ì|а™ïr°»Ôöµ2b¾AzñÕÚ–Ìç¯k2ßJÛq3_½ f¾Z_ }—ó›§¾ï:Rm(ê«{™úÊ7ÑÔg¿¾ž[éO 9‘~æˆóXIrRèr“Fo­dDEh¹lƒ–!Z®'MD¢åòá·Uz(cC´À6ltCÎ&qˆ– õÂ-ý·úpåfuS®Ô÷õéÓKÜ ‰ø…¸w@ëbƒÐÅHîMr1’;ÒUè*õaÝ ¨ÏaÉÞuzÉÎHî0‚¤àØ>•özêA·â삹,°ÎoÍ="ë}Ê܌⾶¯>¯—9ÜþëËz}<Ézm–눪)†$ëµÌ^b½úªÍÅá>¤ÿäá>øHO°õô(-L"MˆSô¼Ñ=Y/$[g½øl‹Mua¿wÔ 6Å@½^€qÞ¡¢Ôt éEéHzÌ‘ÕM8C¢§MÒû”y˜Þfê”H ×/"èE[VîÌÏ3S…6Ôƒ|›ôâ·l\ßß“ùyœoMœ÷©‚!¯[5øPX˜×Šò¢ˆ£ìLmS‘òBb¦;˜œ§IN&çiõ°—Õ ¼Ï¿/&¶ö%äuÁÍÔ<#½bÉxÐÅQ.Ýþ•Ú3·¿Êì%.s0­M“œLÍ32fï#™ëûÛ=° 0/Šè-!âõ"óTÞG²31O^tU\ÄÈ"çå¹È`Zž*2™•gÌtÚ[ßÛ¸ù¶äÝ}.yKLnL„€4v¯Û™”§•Ù™”§•9˜”§•qÆ×M¯%Ý}®ZLÊÓÊ\ã[Ëͤ<­„û’ç—>îB’Ñ9•ªðG|–ädRža Ò§ºà"îBYã‡à:Ý¥ Î)õ%ÙU]+"°ëEÜú*rÜîçåîtûÍÏ5sº;¸ñUÄ­/É}ü”ev%Z,‰;p~µx-›¤ îSóœî”Ë,å),ÉuºW®¹úà2ìÑдíŸ'Ô}%ûdÉ¡L‹UË/=8ª–0]H¿jq÷Ó$—2-_¨ûÔó(Ób–9Ù‡ú ›´Ïon~šäàî§IÎëGŸuGeôÔ}ÊT\æ:ô‰P÷)ópÿ‹«éz‘á.äïì‚%Çm‰*9/÷©Çeù\3§»Ô® ªùTë;Í5aî#xÜ öïÏŸ-Ÿ?[NŽë‚9Ý•‹¥ ®óÔQ׋TË?›­îSd¿ÝKŽOoIpŸ?[¿ªõ.²ÆOÉuºC–ÜÇ)õJ“\ÕÀ•¤åLš07|—ó÷{ÿâÛû×…"3NZýoïëóEû|JTù*ñG×üTIÚj©ÖüuÃmn°Á’¹Þ*ul*‰,WqP=þÕ둬ÕcI¯ñšïÇõøW¯G²V%­žÿ5¹ˆ Ñæ¿ïþéÿÕ’·Ü#³Ýwæšg¦c±ôGõoëÏ ÂÞÌß9‚øçõhŽüÇ/3b…Ÿ¥ÿÕ×FR½}µë-éuT)×ÓK¹®=2AV—%½®*åºz©¬kìÊ!’uIò©+Ke]­TÖu1L«ërx˜VW–ʺZ©¬ çóéuIò©+Ke]­Ôß_ù^9®¿Ù…VÏ.„4X=½Ð½~t¢ŸñÍ/ôgå~æúÓú¾ù…þI±ùgÅþ ¿Ð_­~ÿñËZöGëÝü|;~Yÿ~}C~­ã/ž>Î=™Ð5æL[ ÅçÝu¾ïôoÿ¾£Òçþ·ÿÓ¿ÿ7(‚qXФï;æ»üÛÿ–ÂúçÿñïÐÖîÏ?¯èÿùÞ>sçØûoh"Œ1• ½ÖÉæý_Þ²¿ÇvýÛÿùߨBŒñoÿ×jÈÿ-ÿùÿŽD@ïfbþÛø¯|pÿrÚ%´n]ï÷á€ÙÓÙÓ.½»/¥]Â_ÿGþålH£ýõ¿ç¿:éÒñùÓÿ~ýÝ´K(ÚÒ.­þüë?ó¯_Ò.AXõ(íÒsŽìÙõkÚ¥Wö?ó¯ÿþ²L»´ÿuÚ%bÂÛ=c{¡Ûú Á FœE° —'þ+Ô%êóÒ÷op {n„ðyaÁi¯€VÄíxÿ}¢§bL ˜Ñ‹Õ¯äyø1EPLøI,ã¢yü†´ö„Q„Sxáì7¤%ß¿»žß÷…~S ô…SáùV¹pf„tQçùÞøDt¬š/7Ô³äS„pÎs{¯SVͰdÂÇŽBH›ƒ©†óG`]pÙ7›{~l¾Þ‰ÿŽ Èo8fÃN<ȃ<7nû«.*ã‘ h{Þ«a$GÛ;*ÆÍÑâëíÃñãŽ8x¡«@ªšsD™§•0'ªAŒ;\u£ûjìÿéW‚Xt¨áœß‚D‘¨ï·ŸCªÄK¾çDÅ Œ~¹ñ1Ü¥ˆEV…í8_É)Õ1Ì€Þ'ûJ.…¦Ž¤2>ŽÈ¡Í×WÜKá½M>–œ ź ³èwcôJüÁ,zÑ@úöÁPèEéW‡À¨äó<¼(s°‹¼nÜÏQñÚ´È.…W@lÖgàªG¦„ásvâæö Ÿ¸wöî?Ï3<×6ÜŠÍØ÷Ã|ñ@=·õ0:ã^KŠBmlw¤%£* ^]˜¸Ð?ðtæ# 5ã Ž’¦JÑ *†¡tÂÆ!|ÕJ"8xòåгØ*Z¡LÛЯËÉf>Æ0£¨í[•íÈCEÚa¹ö+CÀ! bLØåP‚žÑQçƒ?'còì3,@PÒèíèn5mÍO«x\ün¿Bo¼ãTŠ dµn6™Þ ûÎêÑujôŽ·XPg¶0ý¾j²¼‹ÍÀ$Þ/u;Р̯¡¡8FÄWÞq#q r ºyÚdø€ú#šÞKp »p£!Kê=@/3ªÅ Ä!'$µy s¨åÜ"~Ú½JÜú|ÛwŽGtïjiü<ÛdÄ^”Œ°„Ü‘ ·:g¨Ævwà“:WXÙÆS •ö¹Bó£Çc ½ô6Ò;ûdêÉåäÁ݇uº#ŠÇaì‘/ºD½ð€wåÅ©O…Ã8ãØçmï%Èá‚Ï@9 fxCìÐÅPï 7µ¹ó5“br…\<)&I‚{Äå`=wØŽ´Y3ÞܸÒŠÉò3|ËÛˆÎ=,1Þ·a³ z"Ë.M´`|«)ç¤pËŒimíÅï\`*׆Âm"!t#¾ƒÕ«‰>p3Ö̇vXÛf45®ây¢÷Ý«O?$µßp»VǃŽÉå$3'fÙÃtD؆öf"ŒÐq*^aCûŽÍž†Ç¿Ç"O4Ö{EЫxäÊnr‡ž0Æt£Ç }ó/ü&ƒ $~¼¯v r.D:ïðcnZ¼5$³ÅÛ/Ôo3o.P¾ÍšCOü¾/.ÝÙI|š±tß›²0ç6¹vYB¾l5´vóømíÉ¥;»t¢½)çØ¹tßò =ιqéÎ{Ãk!–nOqž>óðeŽ¥û‘ïfžÝa²ð÷2%®>ßxM€óUj šXÏJˆ•ø‰ýµ ÁêŽx M€Ø n£ ŒîØ™‘ÔtÆf͈^ëé…òŒ ˆ…ظšÃÎ(>†&@L¬'Þ â1 ªà+LùL€@¦;f– ¹_ŽØÊ˜ëHÓx¿ 6âu7‚~ÖÙ ªßAü$ÆrÌŠE€ Ÿ;V5 ¢&mñ94Â96MÀÈÙ>:"(Ï„j„‡ïŠb]'kþ{Âzí5ÿU…‰ùþ|ƒ´'þCñ˜ÿÂZ+¾ùɈ‹qv„§Ûèk„„s Y:ÂkшøW¬t&@øwmóC€0êŠ~%Â…*ž° ß‹ëù >ãC€¸;k>‘—šT&„áù!@x~2V… eé~b„!~L€p¾ã>Ä· ±œWÓ¸EXÏÂXýJ„/(ÍCL€ø²Œ w§­þTrš¡¿—DˆjX±Ο4­Âzãx Ÿ0×#îñühÕ#þkƒ,þƒä&y˜ÿjpÄO$ˆÖˆÿà ·h‡dþC¨/%büj×€hÍ:>Û†æ¼H„ÓÍ@€H‡¡zˆ€(B6BB{2# Fýü0`¾6É€[æ­3Âl‚¦f@\Å15V'Ì€pµâÃ2¶{‰á±Ã4bƒ4> ¸U–>»áF¥D{‚@¸§^Äû)RA ùn¬óMÜ*¨¨ e¸U7buØdCJD§®ÆÆPV„@<ÏÍ~g¿ïuûZQDV…‚@49ÃÊÇN¢ÆÏˆ2-±b+Ñ$¤@¼Áv&!VÏMXQ¦b+CV™S‹”ÉÁ³H5áLp'±[01«Ž»‰¸*Õìí^âÀš”æ@̹Q‹áÐ+f‚à– ‚õø ‚Õ@‘ bLò#k¬u’`EE‚õ™ñŠl¬Y`Ä(Ó¾Ó(X¯šQ°FÇ(ˆùÎÑ1 V=FÁHIB Öt2 â{òEÁš¹FAŒ2_G¡`M\³`²YMæºh¬WÔ,ºñaÁºÊ,Ø$bÁšº†Ášr†Á& â^\ ƒÕfÃ`~ä ƒ˜M\q ƒÙä„Á¬8a0W§„Aüÿ¡D4fh”aUÛDƒXxvÞJ4ˆ”cÁ×Iƒ˜¹'« âµþ 1^Ä)a•1¢91ysUI Œm%Âꄉ/öbÍ"Bx9ݬD˜o~aη$B Åd!žCÌÛ$B ÑÓDˆ¤;!a=#a ©‘°îe&D§L€›ÖòIç£dBØ ž&D°<Ò² Mž,"*l ÖÓ3n›<æ’ sc•Xˆç) ±0×ÅÄÂzœÆÂüB%btvJ„…èg©±0_µÄÂ\Sþ…„M¥Ä ·wå ¬ñãKåà¹Åv¿Ðç$4)w®É°–f“!’>ßÁ&C¬/g>Èë9Æd#׋t)2Dy¨Èð KÚ¸Ðë Éhf:â0>aI¼F4„kÊ;£áÑ¢ˆÐ‘UˆHFCƹö®ÄFxE†±ŒQó'4þlGSbÛ»ÅA¢a2S¢a^”hèMx¢!–Ǹw¢á³E;bÙß›n° ’ ‡Æ8Ùp ªzH̆¹uO6ó*³á3£»Å†U&ÙðQdŠDC(™¯®LlHÝ`±¢uƒÅoI†~eM†¸÷9¿dh0Vk†…] †óÔ DȨH0 ‡%©ô†Õqƒ!Þzºj°QŒÀaŽ!E`|¼ ™™°VZ3!$§ÜÉ„mYbÁ9ÛŒLˆ«¸ò› ñ†o™’LRß 3a;‰¶uALØÎ¯Ä„u„D$Äï‡#!$lÇCBB,RƒG?BBè­njŠ„„]B$ÄgqoDˆßQa¿‰°KH„¸÷>ºr°-™"Â&¶UTDØjâªKI"ìeH„­ç"Â.!öz‚+JOD)3ùðD„­["ÂÖ a«XDˆnW×¶&‹[×E„˜pûÖ‰°MAa;ö»“{ÍA„5—„µï1¢È~É„Ox˜R_H „„‹°ú) ¬Á1öŠ „ÉÃ5Ü]0v °†Â@Xï•°N1 „]B lwv °¾äÂ^Ï „ᨭK„DÎ- °vjÂ^-0Œy°¶=æÁZ̃]B¬#_ó`k¯x°´æAH¸ô›Û´ ¶¡ö"äÁêƒpŽvœêÆADèâ¦Ð8Øæ q° ˆƒm(„ƒµûUÄÁ6#…ƒµøkßøOÒ:‘Ñg¾Ó½! Nï¿ö¡±zk¸uõ ”“¡KĆev„MéˆSc3 Ò¹¡!Þðüeb@ļ½|D@ä#¡âÒ(Ù‰‘B@H¨è3"JWS;ˆýOlU­¼»m(" o{· Õ¿[+xsÌšVúÓ8Î-­à»PÅ]jñNÓšTZA|r?ZA9BlôCz˜'T‰F¿*cökeÄ~·®.ö«ŠýnàÄÞõ‚7˜hÿèáäÌ‹Ä~pa½y•د5Gìw;>¼Ñ/&?4xÇhôÃhQjô»ï'ø®ØW­»Û…Ös0û5‰Ø¯t±f?Ä7ÞcWeöC$åûcŠ/$§•á5ß4ãüÕ½ H…£,¢‚¿ªÙðW“ÑðW-4ü¡žç»‚¿~áïŽ0]+ˆ2C–«„¿;b÷³ áN9Ã_;F'üáÝØ·nz_+Ì"„?äjâä6ü݈)Á­ªàSf¨bÂ_k à¯Kíœ_ô×Uô‡©ÇÉô×êýA²3®‹ð¯— üCÏï­ãFg1îð¯—!þõ2Ä¿6`Â?Hλá_¿ˆø‡>Œ,$üCÞ*Noã_­RÆ?Äm¤ù£è¯Ý[ø‡ØÒ÷ìø×–ð·z¦Lø×oEüíæÙMCQfñ ÿZ™±­^@øWíýµûˆþP„+Šé¯õIô‡ÜTB‹þÚ` ÿ ášbüëõÿPæt„šÀ¿&þµÉ.ük5ÿМCüÄ¿6 â¿Ödñ_/ClFغEì·"¶1¢Å»²e’ÛBrÜÝ6´õSØë!¶Š[{D€¸j9€R`¿; °—!öö¶"BÀVDØh­à¼<^Ö ¾›'½zBÀö$Ȁ홋Û£¶Y)ìW‘kr Û„v °M&!`—Û° {"`{BÀ~U `ë•°Í! †tì])Øæ…°=!`»•°—!¶š…€íAÛ˜ ûUDÀ~° °½5bÀj °.2VGÍ€5¦fÀ^&° È€Õb3`¯† ØË{=dÀ.!¶zÄ€õ˜ÛUbÀû"É‘ÿê]4ÿõZÉ5ÂÁõ(Íýò_où¯uQü§†þêm6üµ¦ þÚ]Bøküµ; þº„ð‡{Mö€ð×oNøëE­ÑxdPá*úëÒ_MÒ_›y¢¿.!ýÕ«júëeH5ËMmtì“Ýú=ý…2pWÊ?ƒ 2,“"ÒLaMB 3Ñkéø/ÍDáé ˆ:<›J3QœÐÆf¢ØÔñ—ÍD7ŸW§™(|2e8*3Q˜®ÅAAÚ‰îï0…ž=íDSbŒOKÔ#Ä×ç˜á@G5‹iV«„uáu»M„ÜÑ !|`6:ý‰áù6Ù!Â+ñøÃDGŸóêDXúX!Ò×>aFe"¬[™QfÅ×ÊD¡œÂúCDˆ‹8€&Bœ ÐÂ×DØ$"B4‡§Ø&ÂÖ!|“øx„5:fB”áƒ06‰˜ðÚN€˜ 1•¤ÙÆ>€´)&¬»› kª˜ ¯÷UÝCg&¬3âQt#a¹ß ¯íÖ­Œ„×6d(m$D=ÇG÷Pá »„HØÛC$D=×ÇP´K »þ–ï ‘°FÐHØ/"bÃÊc #!Öî˜D„hÍ×P´WC"\8õ’W"‰+ ä&ÂÖ+!(5„ˆ°…ˆ°K‚[sD„íш‘ZºáGDØë!öæÂX@/"\°ÿ]!ˆj¤Ñ¶æˆÛÍ…„]B$ìõ Ûã¶±BŠ{5$ÂÖ+a»y|@ÚOa!aë“0"éÉHØ%DÂ^‘°5FHˆoÓN½¬°·‡HØïN$l3PHX#!"lƒE"D-›Å¶7XDØZ#"ìa{§E„¨g{¶‰#"lGDˆÛrí B,Ž@!ž„­5B8—ŸÎ.@ˆïèæì,„m(„I!bZIH Ä;-[aoOakŽ€passt !Jñ. D,Ç“§tÂ.!¶I@ „€&BÂÖa—¬Aº•(T(ÛPk*‰W,ïÝH´KȃíÞâÁ.!â*>á ¼sniÛÄv q°_D„ĺ=â`îøLƒ­1¢Á~i°KHƒ i©Eƒ56‚ÁÖÁ`—[k‚{cÈ‚uY°—Ì‚ØÍòXÊ,Ø%dÁ^O°`õÉ,X77 Ö,6 âAíR4’{ÅdAŒ„Ô:bÁ& ¶zÄ‚­±`Ító`—ûUäÁ.yy³„yÂAv"q°·…8ØÆF8XÓÚHXï‹‘°Õ#$lmö«ˆ„]B$ìõ {=DB”yž†„]@$ìÕ [5B [Hb£°Kˆ„­"a¯†HØÆKH˜/´‰°×B"ì‘»„DXsýò?¥ð ZùpFWÞ˜8A–&?(‡¨Úú==ºè»[\ôÍ1;¼tàŽP™§ÑïÝúÈ ƒÄ·b°d™<;ú½û‘ý÷ú½{¥ƒÏ 1þ­« 1øÌýV1b£ñꂱE¡“žcÄŒGY¹2F 6G'¿ØÐ¯Ð1b°K  ªcÄ`'1›‡ âëýÞU‘üû'B öq‘bæ ?ã ƒŠC‡‡™kq\2< ²ò ú;–>fÂ×»›€"œ0A†‡YˆÜÕ8V ¨çce¨ê’{`5ÙîxÏfW¶Š ¡y¯nM?>bNX±ŒÄ4‰Ä@Â=¬Äœ·Ã~ÛAð¼ÛbÎ{8ŒÄ >;VÍŠƒ¯;ÐØé÷eÁ3³ÒÙAÆ%°ƒàù8Ž«[rDèØý#‘Ý¥Á“ƒàù8U—O¼\ûv„??Abƒöë ønEäÙdAÔ#›S9v QÏü‰9Á¤<9"p×õqŒ4Å4èvø^~¢Ä ›w7Ê4T‚ùΦƒ`»J‚]BÁjž1\ÏÇA°Iä XWÙAƒ#QFúè X£nÁ ;Ž-óÈAp¼TçÔÍtl7—ƒ F]–žtÄãtŽ*:¶öÉA£¬Ü¨rl9ŽíªÌ=áTÉÖUÑ ¢¾ÛUr¬)hÁê¨ÏmëªÀèúÞÉ/$ÊÛBA\4»*0*~>‘bj‚Y×È~pøtÚ¶`»ˆþõì8äu(çÀñÞŽ6“vŒ, ”È9#svSÐ(C»c;Ví8pdE圜Ñm¢—|Q„]²oàØO­Èö DŸo`5Y¾õTìXoŒ}ÛEò Ä­Hèö û¡·Ó¾¸ŠóϾM"ß@¼ÿóãØ$ò „„í±o žÔ%ÛPúbó+gßÀ±ß8CßÀ±;·Œ}S’¾¸h릠;B‰OjëäxJš¾9ö D5OWÆ­>bÆ¡¤¯é˜ N×ÀÖ¹æP¤k`õÁ®¹OM×@HÕE®‘?±bОç,¦Úc×Àjs¸æk—®X*åX]°k`kž\ëFv Äή ÉÆ2r ¬ŽÛ50§ºæ|K×ÀŒõ›®Õ»bp( gàØ…‘c`•ÂPþVÜ÷~áåן~‰%éXý–_`Í#û¢¹««[ìØ$ò ¬ég¿@ÔÌx<Y7o) RÕƒÙŒð'µá&u}y@“º¾uÊ@Ðʾù~9)°²‹ÐÞ£‚–‚к¾<Y“‡GÒì øšDÀWÇ*¾ªT¼Wá^ L{8% É­po å86íÕmL{ÕTÓ^á´iïí„ ÒM{ê¦=\%?Ò^ŒE\#Úƒ@®ƒÂ=䦊q¢›€ÚØçãó×$>Hèx$à+niù¦ü¶JË'½–yLea*Þƒ$Æ×¸Gϸ‡ˆ¦²¼î¡ ÇÓ¸éoŽŽ{ ®½£Gƒ„#lÜ«ÉjÜ[ç"–›öÚE¢=á0í­sèÄÇ´×®J_iôþLÇWõ˜öº„´×%¤=H®½›}âît‚5íõ«¤ãCuò8”ޝIH{½fÒ$£«øÚE„½x]?.í²^HÁ÷8Öƒõ{% èõZ z]"ý6ÿÜÂX¿‡ w#½v•@¯K¤ß««¬ß×E‚óZ§Åy]"õ^«Eê½. ÎëW‘óºäo«÷ZÇÅy]"õ^vÁÚ½òú5¤¼.‘r‘¾Ê½&!åõ«Hy­ãÖîÕUüfÔOR^»D”×%ÖîíÎhå^ ÈxÕG!^P³×î,Í^“ðÚE¼X¯¥¿SœS±×$Áwíâ]»õzíéõZâ]«†t×Òê•ïÏ´zíF‚».‘Z¯I¤Ök©õšDj½&‘Z¶ò!”Z¯K¨ÖkWI­×$Rë5 Õz%°Z¯I¤Ök«õ¦œ J­W©õªRëµj¤ÖëªõÚERëöyH½^»Jz½ºÊz½&‘bf:ÝÕ¯‘^¯I¤×kéõêæVìµ2RìåLIÅ^I¤Ø«ÖH¯WÝ´^¯êµb¯I¤Øk)öšDн&‘b¯I¤ÙëjöšDš½&¡j¯ ¤ÚKIªöšÄª=Å1,Í^ ¤ØË¡°b¯U"Å^“H±×%Tìµj¤Øke¤Øke¤Ø+‰{M"Å^ÕcÅ^“H±×$Rìµz¤Økeþ¦b¯Õ!Å^“H±WµZ±We¬Øke¤Øke¤Øk)öšDн.¡b¯I¤Øk*öÚÍ¥ØkE¤Ø+I*ö–<’J±W)öÚUTì5{M"Å^—P³×$Òì5‰4{ç.S‡Ô쥤¥ˆ:PÛTú’¡¨²L’âëéžz‰*_%þèšž"êÔÉkÍ_-%“e•®%%-%Óy3‰²êñ¯^d­KZ=ã<6w1þl5„ .çÏÿåi¡N¤ïý³´PדIüg@È,:R ÒB=WðŸH¥seŠï¼x ÅRãä9?gÁŒdž™4J×¶„Oº¾'|rUÊõ|’G©®–ðIuõ„O®«J¹®Oò(×U Ÿ\WKø”ue©¬«'r]•ðÉuµ„OYW–ʺzò(×U Ÿ\WKø”ue©¬ë¿ê@üë÷;ÿi¡æ_¥…òtÊ‚’êÏÊýL õ§õ}ÓBý“bóÏŠýAZ¨¿Zñþã—õëÖ¸ÿøåíø¹æýú†üZÇßO …¼”3âß·µàïgsºÿ:-ÔßÏ/õM õ_KÜtàÄ«í%nº2qÓ•‰›>ù”ÚŸ•þÈùšÎ½ÿùÿiê¦ÿüƒÔM7ÿZ÷¤nz…ÿ{þÅÔM×vÜîÛ+ü%uÓ+ûŸù×ÿY¦n:þ:uÓ€ ØpÀ¯ûÌEÄ­ ùVÄ ù éö›Äzšˉx¿ MÛ±sÛqäÇU4ŽßOĨĉò­oÎ-”±¢ÄAyÔ J“xnã¦N+û’÷• œïï¬PÍ#w659ç†EË5ŒR(©ì96%‰ד°n@Îëˆu~Fr2Ø’LÚ›œ;NVîfor¾m•àš2x%²G<ÔÇ¿Sóaöˆ©ŒÒïžîà‚.ŒeЇ÷­Ü0ë],•ÿgW\éó%Kåÿ™4‘9÷›æ ùXÍCóމ'¼àÁì‘h‚]ÙŽ‹êÈóÝ93yı¨µy%Êþ3üüÝr*ûÏ:¨n|igÿa’ó˜´í¸w@;EÛ„gØ)¹”ü禎ëNòðÅÔƒ_Ãw¯¢ä?S0ßuž¶"ÿý’ìJ¡D*ïâ­ä?N›qbÓÉ#Þó°žSÉœâ<‡’ÿ8ËyN%ÿq¾¢ó\´í`Z…6‘:BAÿOØ|œ ctþ†qÁÅ8›'ÔëÌü£p“ÞnfVˆ3t_³r¼%þq•sœÊüó6ˆ7ƒ™œäS™®ãwÞy9ñϤNøí±3ÿ¸ƒãvæ¥U9üZ”q$d¼ð Ì?Nñ®ÛÊüãü<ç<”ùg(*é+¡Qüd8…#Þ[ŠÆseþŠAzΩÌ?sÒ䜑¯Lt§/›FñY‡±WÏŒuÂ$+rG¼áØÀhŒ©õ =z=ëPê¨Ð/J”újl^u*õÏ~Si}"¥]dØïßYÍTæŸíÒÔƒ­x$ÀšÀŠ/eþ9N7çfæ'Œ:×£Ì?Ø·G5ÓFÄËÌÖ`½ˆ#ct®C©¸”†„68 s–Ik´l„]À‰´J‘?™áN¼ú‘?bWØñs(òG@3Êj.¥þ9&NNFfá2ËÒO0•©L:O¤¾ˆÔ?Xû£ÅÈ:©rDaNqjâ„­Ô+Qî¼TqóûTîŸíÐTB@,ßXT9 îÉä?û¤)ƒñ¬Ú¿ÆÈýƒCÙè&b`ùFÇ9ß"zÉè’gSòUA>@¿Uʹó9”ýg_š]Ï¡ì?‡?\Ï©ô?9 žA³ŽL­w>“fxz¡à=#éҘƙùù ìøÆ"·²ÿl;5Ô'¢°Å¾\O>б€CϾB²+ûO•9”ý'ú=íõl¯ÇØNÚtdãÆ6”ûg;ù?Ü´éÀ;–c[´éˆ„ä¢MǺ¥-ÛM›å¼ê¡M²zÄwuìm:àÐqR²Ó¦cžƒ_ìïó®â& m:Ö%[ ±Ÿ´é€‚7^™±°é€ïÈ¢`Ò¦Í %Ù‹o´éh͹hÓQÝï0 }%'­<ÆþЦ’x‰Þ…?l:0;m:–ÆAë„Öσ{‹9½Ã"bà}¨Éaé6ŽA£H6^5iÔQcЬ˜ãaÞÆ’‹Fðwy(¹iÔ±.åË|?M4ê¨ñ:7u¬KãÜiÔÌäl3Î6Ú ãû¼Ý¼$ï3VñVÉ QKvêýÄ*¾.sѨ£šw^4êÀU|z'™6tœØ°{„5÷Z2b0(Ã*ž)¾ ©îHúu0&ú€©–q,çñv|¦·ÃûÞÏôÎý oޝtäá\²áøL‡mñ’iã‹vk-M‹qÑ®cá«ÌŠoÚu@Âé5ž°ë€íBìþÞ1í:2Uç˜;í:М°Î~%´ëÈÍè˜í:`LÀWŸéHð™MÆgzßY3Ÿ>Óûó‘¬ë8ÒÓo¬'ÜŸØ-ÎÿyGžÌ¨y±ÌÆÜ•Èq j¬ãóÔ»¼‹‚Ø ø†c‡EÈXz2X@)y?’±Çç=(þûð¬x.îÃÇÐâÑb!_C–Î#¦ãëøÖàå=ûžàÃBÓÞ +o,ä8Ð2á쇎bË2‘è·P„ ¸Eß¿Y3Ln^Äç‡M$òj`ìÒÑQl¡(Y‘¢W¬ó\uòØöïåqJD…Ùh{.Ú ˆmÖS4¸Ž©ÀC¦Á21 ÂeŸÎ ¦A¬NCì[¸PŸ’4‡i†q5 b«JrÓ z¼‹Iƒe“iŒw¦¢Á{Á‹¡Ó ”cè/pÓÔ+á`Åj0>Çž|4X)ŒMƒH„tªÒ .ºvAƒÏµK}m„–‹¶'¦ÁŠ×mDXhêÒ“3nµqð¹ìËž<¸í7ç“y°"Ä&"»G,=æAü»EˆÃ¹€ä’@˜!Ÿ¡éâR@˜Ysñ\¹Ñ3¢Dcá6åw‘@˜)J·iª1fèûB8 Ë „S?p{?ì–0³$bžql(le…¨†Ç†Â Cá¶Lµ¦B$xx•°06LÑca( )!bŽ«baa+".ÜðŒ‹ ±[㉄¹p»§›#.Üæ4«‰ 7ÄŒ‹2æÂmí:Á1B y}¸ã.v†ˆãe.¬á1b÷+*¹¹ø8Í…?ᦸ?ykqáv)¯_ra˜AEµæÂ qf(Ö„3â9p!2bpt•¸°„ÁpCdeBŸÀ°„Á°P`ˆ"ì¨Á0] ñHœÃm™ó †XéÖ kR ·[I/ 1^¢Ia˜{Q"0Ü.¥éL0Üž]£c0ܰð°9"CL ^e2DbŒÉKñ— ·K©“ QF„)2”‰Z#C´‡oÈcz~ÈšñXˆL†õdL†(ÂϑɰÂßd¸A?dˆ×ˆóËdˆ2BE%BäOBŸÀ„Ãge0İ †AA¿5.Äæk..D Nsa½gæB|ÛÆ‡ óNÉ…;>#¤3qá÷&ÒÑp‡ÿ YQhˆ1x‘Ц“¡a Ý [¡a+#4le„†˜„(£á¾y'e4Ü`ÅK:¢"8¡á¿2J„†­f¢!Á-¶ÑÖŽ$&£!ž'·hFC?ò$ÃVDd˜3Çdˆ„{S“!î´ÄÊä—1Ép‡Jð·†èåE‰À°¹Á0—úCTÃn óN0ÄXÇF+Áσû}ƒaÝË`ØÊ 1q¾`˜s4Á°¦ÁpCÙÖ¤0nð\ú­qáNª6b47^!(„™*‡ÊP˜u˜ c+8kLˆjN¢›˜p‡ÓË óé ¡Áã%" În,""D·‰°•­yRB"ô’@ˆÉÇR „¹&$îx0„Fa=4!ê‰Ã¶Â\¡[=Âv/á¾Oó`=Zó ŠŽÍƒµüˆQ$Ž“«ó`µØ/J(lõ ë*Aa‘PBaÁœ )è …ûC…‚B'‡.(ô›TPXõ õø =Oë …%I*œ¦VS¡×¢BÍ‹¢ÂâÄ?¥BHn✱ðÙ´C5w%"lÈG_XÏ/±0§±°°º°ÐGÆÂjOa¡ÛXX•t,Ô%ÂÂV&±P39±0_ÐÂÂl°¹°]e4¬{ kÂ%–DlXl˜-4Öä6æ¨ëæE‡Óa«8é0ˈ[=¤Ãê§ñ°ú`<¬Ge<¬Š‡u"c<ÌÍNâa»JxXçÆÃv•ð°Ã|XÎ|Xõ˜«âÃzèæÃ óa®É‡u+óauÂ|XoŸù°ÝK|XoŸù°•Ö«o>Ì_ñaNbuÔ€˜Ý2!6‰ 1Ç˄ت1!æi” 1Ï’ÐÉTXÁÜŠ 3ᘨ¦Ç_*Ä~ü$sÉj®Ð">Q¡¦Ñ(VèSZAZ–š$¡05 …Ð7Æ—:¡ðZ‚¹„ÂY<Ð7îHd@­œ€p‡Jäc4ºCwö1E+h…k Ü1´ÿ¶š„ûms0!$Ä?òà•ÍGGˆÏåÇfŽc¬;›q ·ù¦ÁÆ$! V5†AKû­±`«W,¸_¶Š3 B2IbÁª×(X úF&A ÂúhñHeþi̘qÝ&A4&Â%š«&ÁýVHŠ$ÁðÃûà(a¡`k P°$FAÜëù°`lt( î„mƒà~+ÜD‚ &îó1Ýa»Ã2Áš"‚˜­ãc2Ú w([)bþÆEæÀ*bÜÉhQñ& 9ÏéàUâÀýJ«Rq`½*æÀý²E¡9°žœ9/_Tq ,! L)·æ›«ˆ °¢Og‡Àšã†@=5 ® $ ýVè¯zgúøÍ>ÓÆ¦¿|M õRþpÑó1meµæþª5†¿º“Ø/W%£æåù±ÅKÂÙaôË…Êä‡W–6%&¿šð&¿¼S*¯´-øáN‹+ß—˜$(î«[KX•ûZs­ ôJ؇2Tn¤.Ð+Ab_6&u^ûÚEÖzôû܃Rb›ò±ÅEÔá¤*Ðã™Ô—Õ¤&Û(êÞ}¹ú&ôy°’ùrê%óá9Ín#škm2_+"æË:™Ï7‘¯z`äC5Q¯ˆ¯Æ×ÄW0ñÕ§°$"¾V÷²OÄ—ës)=4¾jžÕ€žGÉ{õ¸S ˜ƒeÞËwPjÀ|´æ½jJªs2š÷²q©ôÓ7íå×£´€9x¦½š‹©L‰i¯/5÷²¡§h/ožŠÀ·‘Œ¬W]JE`ŽY¯UkM x‚eÄzh- SX5KHŸóÆzUqª³šTæh¥*ð¾~ªA¬Ùª@ ë±*0Ÿfª««o¹D”.0;šº@`ª³Væ“JU`±*ÐÏ%59ïSølæCksõIM`ijïûwšZCíßçí°“ûØ…b×-KQq^¾P©t{EyõpS˜½6åÕüL= ?,Iy­ëý¢þ ‰›ÊOp„ecó<œÿÕ~‚'üñU¶_eÎIâòÑùîwÃG_n#ß ë°ÙMCÛy²ít=D¾ˆöŘ‘¯ù$Zxn®‡Ì‡À]S hæƒqöo…|…’©ij$ùžG[èd¾±¶K 8JúFiÐw>ÖùY ˜ZCßqî¿”€û”ur1Ÿ­.’ùø¨}ÿ€ùv™|'óëÎ/óåÖ$™ï<¾Ž‚Ç‹¶ëã(¨í¢ïXÒ)ø²G|Éa&¾SŽI|ë·ðyÿœÀw*ˆjßq:Oäók_È7äÁŸÈ×®2òy/PÌ7WÕ̯\ᛡ/÷h }S!!ú—Whèóˆ'ôMûw ú…мd>ùêNb¾c_¿0Ÿ‡"™{5’–˜ï@`SJÌ|‰©É|ØòQQ'ìà û8 æ×ªQŸ2L}h 2H}^±‹ú8½õ!jÛWý‡Åöú„VŸŒ}˜I÷Ç âÖÇQPSØÌwò|HæÃnnûèþêÀ̇Áû2ß±Én?™Ït`æC ›ã}¸æ£ùËkBßq^ªÖÐwìòH5ó=›NjÌ|Ì!HyÂ>L+΢ä>Lm¢£Ðï8‘·Ñ¯fp¢_^eôËÞä‡Eéø¢Ÿ>¾I~¸f}Ô~Ç~Ø|Ôäs‚É1ú8ÉM~˜UÄ¢D? °ŒØ+ gÍ~uU²ßóX"ø;!1ê1üa9 fÄá2ý!,ÑöQûpíÿ­Á¦?b¦?\ôÑúøñNÂ?„4¼>ø—c‘ø‡uíã!xÀpH¬Gú‹˜†$0ÒßqÈK=éŸrœà­£¯Žá/Ф¿ŸúÃð±^Á_¾ÿ Ž'ð—ŸšÒøa¬º‡àóLUþ<ù’ý0Dƒd?<¥ó㈱“+¢ØKÚ×4Ÿmºt|¬@ÄÏ%o‘þò1%ýåÞhžj1ýyHúÃ:1>ô‡8ÔPšþŽ­T}5F¿œ¬‰~è;wÍF¿êÙ{%©1bl‰à¯“ák»”‚¿\jþp¯óþ^%ûaŠ<+P,±[·­Q0ýµ‹D_úFxƇþrýLúÃŒ8;ýU§Lø&lCP,ÌÛ‡þjË~¹º'úÃ.¯F¿ü2&úUëŒ~ùÝHô«>ýMµ¡_~¡’ýò“jöíxtbö«á3ûU X=IA†?<Þç㨑0ùa>~»øÇe_C‘_5Îä—Ë’ÞÀíãXã ö«Á3ûað®G`~E’ý0DU³_­Ff?LóÛ?R4¥V´q|l=±ág|tiõ#/ÐÙŒ×|Õ¬ÕƒZ÷êZ½f™j=[²¦Z¯4kf¼}: „ÕzõA·Z¯¶­f¼ÜLñŽyÿþ±ô<.ý™ðŽç ñNd ÊNˆ‡ÕÍ@GÄh<²ý$âEüÜ^ïv 2ã3ŽŒ‡}_ÅôÝû¯’í$ä8ð# ò§†% yÈeó| /3±$äeš†„¼Lå‡D ûÇû/S9$åe$ø¤¼ ¶oÐsxûä¼qL)n zã0*ôÞ¯ŠM?zï7ºSƒÞ8¥É1ç½k»TÆæ¼1¤±0æÍkÉј‡¸ÒÄTcŽ<¸93æ!:ãó 3q¢Ç2Ä<º _Â<`ÅüXy®ÍÓĘ—)ªó !|óÖn{GaÞB.nk§ŠˆóZ5â<0Íùᜇ¼Vëc扛Sçn΃×ïøèö´|}8÷Z;O\µì<×.ëª=–_T²ÿ´ó\‡_!ƒ$×G½‡Ó)«A/b<ÿZÞ:l'hÐCLú’™õZ=b=”Ÿ0ˆ.@Ó³¾P<30ëµ{‘õ<~~|[ʰ—.ãI{¸Šδ‡OŸp†„±ƒx†„A8^$ÜCïd@*܃/úöQóáûÀ%и·ÆrØá^»¹p/¾Ä;OÜýúhúêîÆ.ÿ |¸»HMÀ×êqLÄêžÕ@ŠlàƒC½xTÀ - | vþ*_“øàù_Æ$HàÃU÷Ç÷/#TP˜yè]Ë 0sÚÍPÄ—q'2(L D|ªÌÄ‡Ø ²áñUT#’w7Œ|k*½˜‘‚ëcçY(Ì|¸9í›2.Ì{óë£ñ[ëÐ)|Æ…YÇ;OÔLZȸ0d"ã ñLԇз *¿ D‘qaÖ£0&Æ8.Låȸ0G$ãÂÀ"€Ç…©2Ž ³.{:.Ì¥Œ^‡•„1Ç…¹–ñÌqa²šŒ SÇ…¹ô©®¸0Kq*.̵ýŒ ƒÐb,“qa²ÆÁY*.ŒŽE*.LŽiÅ…f;Æ…Éè-Ž S—d\˜Œ“qa<8Æ{øŠ £˜­-.ŒN{+.ÌåÝu 3>vžÕÂŒ s)AQÅ…É¡¨¸0÷×γ æzlùé¸0ù¬2.Ì¥üg&Ç8ã”DqaîÓö™Ž sïæAÇ…É[e\˜ºÊqaJâ¸0y«Œ s™¸2.Lv+ãÂÜJ—Tqane_­¸0u/DžɈK&¯r\œ,ì<Gêø(ÿ2â\Å…¹o{ë9. öl;O4™Ó ãÂd·2.LF±Ê¸09̦À •qaîÍæ˜Ž s/Åáʸ0HÐ5€ÕœŒ “Mθ09Ê&gwÆ…¹•L­âÂÜRû´|MI|ä>¾qÊiOô×2M;öËRÀš ý‚ʾ¡_°R*4¨B¿ a…-87æ¾SéFøÃGf ’suøëWþ an{Ó_¥G7þu ñ¯Iˆ™%ÜôWyªL•–Êô—Ù  •òÝðWyœ•ÆÉð—£Ì~ˆY´Žù¥‹Ù¯2;™ýº„쉆OìÉ&N²¶|P±_æƒ2úU®'£_%{2úa§v÷H Ä-±ŸŠýZ±_—ý*E”á/SDþ*ý“á¯Ò?™þ ‘bXô×Ë,åþ)É¥Ü?%¹•û§$“ÿdÅ¢¿Ê"eú«Q¦¿DÉJr*ùOI‚þ trýAÂ妿.¹”ü§$·’ÿ8–é¯òS™þZÑ_—JÿSWJÿS’SéJ2”þÇÙ¨L•*诸”þ§$·Òÿ”„ô×*ýuÉ®@%9”¨I”ÈI®L™ŸÊð×S€R°”(—¥àfþ§™2øU q_+"îC‘]Lw(ÿO“(PI‚ûº€Ü×%S€J²”¨$—29•¹¯7ðQ ”ˆû*M“¹¯—9”¨I”¨$§2•d(P¶‡ÜW‰¦Ì}½È¥ @%!÷u ¹¯IÄ}]Bîë’C)€²£â¾LÅdìk öuÉT ’,eªŠûºà>»Í’çpî¶Mñ77e*É® @%96'oKÉóû·±¯K†2•d*PI–R•äR Ž©¯ žÃéÛt ¯Kv%òEb¾.PúŸœ÷'w›€¯ýžÊý“‚•©˜Ÿ׊ö*1—i¯ŠöÚï]™Rp(ñO ”÷'+éµ–ˆôz™©¼?YÍRÚŸ*r gm»º†¯y”õ'%â¼.Ù·oÒ¶à¼ÏO¦ýi’3Óþœ%_/3•ö§$k:m›%×pÞ6Kîó›¸Íœ×$â¼JyeÎëeöÇ©Û,9§n³ä¼ß?Ռ뛻͜×:*΃d“3!9¯_u+íÏÉN“óZq^å¾4çõ2ûóÍÞfÎë’óþfo3çu 9¯×LÎëeÈy]BÎër^“ˆóº$8ï#x¾ÙÛÌy]BÎër^—󺄜×%ä¼.!çu 9¯IÄy]BÎûH.Þ% Îër^—󺄜×%ä¼Ê=eÎ+IKÛ4OF?ez‘k_aÁ$&þ·ž‚©—¨òUâ®ùçi›&’,§mÊ_-Y’e•N%%-eÒ:f|XOþjõXVõ¤¤×ƒPãï”W=þÕ둬ÕcÉÿòNo+"³ì¦púƒLÌÐ4þY¿Âé;Gæ»Æ‚êD7?gÄõ¬ÿÕ×Vr&_ß“3¹Ž*åzz)×UÉ™\WOÎ亪”ëꥲ®LΔuµäLYW–ʺZ©¬+“3e]-9SÖ•¥²®V*ëÊäLYWKΔue©¬ë¿Â _…wqþ£N×_¥púe¶üI §?+÷3…ÓŸÖ÷MáôOŠÍ¿œËßNµúýÇ/kÙ­wÿñËÛñsýûõ ùµŽ¿ŸÂ kЉLÚZ€|J°þÚæ?M½4þ^§1þiMÿãßÿŽæ6ÿëIœæ ÷ó‡IœÖí$Nï_ÿGþõ—IœÞwæ¦ýìÖ¿ÿÝ$Nß[Un¦ÿ‘ýç%qÿßOâ4aLòn?æýYr±ý@å`öy^<ÿ󙿄éÈ»9ÀAÂuñëÇñ_ìBFž8ý»#ïgH^6Ãîã†GGèwçØãø¹Ù™ jÂzãÝ}<§HÍSºˆ½°¿³-ò~?8Ô\¬x*Ʋð>!Yqü3¢{Rr)Æ—cCÏq+Æ—Ã¿ÅøUšs<Šû|Ê–gÎM1¾lÎ]1¾`@°‡äPŒ¯¡t1sžŠñ…–òª¡¸ÏS‰h朌ûìqï¶ùGŒ¯‰ÐêdÃŽÇ‘a–2û¼Åør¦9ÅørÌ™‰Ü²Ïo>zÂî"¬üæo†iÁÕB€Lœ‘õx¡ÇÊaäïè•ï/4tEêØ¡¨¨;¯ºdäo[­ Ã(XÒ„R&Ã8œÌD†¡¨ûl6&ò§<=$Õ¼Žˆ ©hüéqFÁ+^êP¯gòû<‘LêP˜IŽM$²’¹™ê¹~ùš×-+ÿMýW¢ _0¦ä‘s·¥Nä}ºã’wGF, •ŽÞ‡œ»óå"9wÒ5Ï{ŒO`˜wÙW/«›÷Š$àkm"ÿÚÙƒ!Ïû®_$rïVL‹‰Øô«ù³)ÄWNÑgWˆ/Çg{©M!¾æ­>=§B|9ìòÄ˼õ0tó™ ñ娆óYñåi‚¨÷GG5ûƒaa<ÕŸ[!¾Øm>B|9žÝÚ6‡øRÜì…ˆ!W{‡b=^ŠXÛ©_ŽÙ½¶¡_° <Çpˆ/™Ûjmx×7…øÊÁ8®=ƒ5òGrÁчð¸÷Y±ûÖñ(Ä—£æ¬sSˆ/?‰sWˆ/‡|Ü!¾döµÎÓ!¾ùgãÔB®=ï¬_9ÁÎÅ_Žñ¿ÎË!¾ÜO|ª¬Qen…øÊɃoõ1ú”›C|ÉÂlaùyg™C!¾òî°«œ=¸àû‰Pˆ/XdP2â«îµâK&ƒ é=ѰXïÇš—,ýtˆ/1¾Ôï¸!¥ö¾Ô‚Ä^4©Zsw„/ÏŠy8—ïé öþ¨jö0jëý¾+Z£b3®÷û©_­y)ÂWΓwýÏøýì7¾ÔÛÞ–Á…/uö·ð¡Þ{ä¡…/µã÷ǹÁ‚=ä© MËœŽð¥øœ úÞ© ú±R.è‘WR¨á×gæÀ€‡Ñõ™[a>±>͹á«$"|9zº:Ú¬ˆLgŸ™ƒÄpG¿¹®Ó¾ü~^C¾²ë×T„/dpá½ÖžK9ŸÍumv¸}$P„¯\@®[¾Ö¦îzáË­9GŸøV3—ßX|«#ÂWvâ>á+ñ=áËßµuOEøª2K¾œJaÝ—"|åtº/EøªznEøò‚‹`YwG»žÍ¾ü]Ãç:–ò|?ŸÃ¾²Ì©_¶À_:ñ[l:/š‡âîúæRM}^’çí—rGà'½Fͱa¿ŽO™çâRî^Û¶”‹åârm/÷ÆRî|>×[{m¡dÍ7¯‚ Dôbç¸_𦎥©}FHÐ Þê¤êV«Á#‰ÀÎ;ú…ñ“‹åÂ>ìêôBäîXʽoQjrOî>`ƒK¹ãÚ^øZÇRN5Ø?t޳>¿}ˆ¥ÜÉEòô'ó{üÝ„N‰†oÕѦï›Hhˆ“†Å ØkY¨…Œ†°5¿â…3–E‚Ù°ì5̆°ù¼U†l\ø°a°A¬sfà ÎêÎfÃNÏ[gÃêÈ“eȆÐLs£K4¼OÃ…Èûóõ!ß¿) 2¼ñÙZbÅ CHæÍ2$Clë úßøEÁð9— B¹}†3¹ð|³¹Iªh a.ÄBB…”¹ð ËÎ…Þê“ Ÿ]&öÆÂ'vw,B,|`-Äö q^@“'c!Žn6Xå÷ÃÑ>°nRbá³6ßHX%ú9ÄB´W³QXˆ-õÊÆB0È#"%‚e¦Ê |d ¥ÂÂe>oa!2xm’ ŸuçU èm&¶ DVäMb!°iIB.ìeÈ…6û‡ ±sú ÁcÜ| +ë—Á°²ÀßõJ`Øš“`¸+×­Á°—1n»±”`ø ÿŸV‚!¼d„ІíÙ$úˆÈ`ˆ¯Ÿh‚á¦T­†›NÒ ·‹>1ÃŒCÄ! á[L;ÂCðVC8–¿u0„ë`|v†è9·ZÉ…´¨ê\ˆCšh_r!¼ ¿\¸+_oq!ŒlXÆ\£´hNr᩼ÎÅ…ÈMòåB'OH.¬ŠÍ…Ø“ºÈ…õΚ ±;89ìÉ…È-A‰¹ð¸ÕÀäÂìhrá©\ÏÅ…Î Q\ècÅ…qÂú[çBr’Í…>L.„æ–sá>é„R\86íÜ“ á[·J.„QùÒ\X·Ö­Ì…¡ ø­s¡)‹ ‰¦¸ð,1Ö­ †HLÉæ ²À0§`‚!Nû‰oCÇT/0Ìz s¶'b `ÍC8þE{ t2Áp¿t—`˜F`ˆEyã[-0ÄúÊíE!”jÄ7ƒá©è†ùf%æ{”`ˆsq–1 ” «ƒa¾ †°‹® ͲÀ0Ÿ_‚av=Á0—ÊCgª,0Ì¥Û`ˆ`"ѾÃqøVÃ1}+ƒá©†s×&Âú˜ƒá891 å¼/0ô+0ô7¾ÀУ\`¸Mv½ÀÐßÙCG–.0ô»o0 ×ÖK.|pØtðÞæB¿}Å…~4É…þÊò;^\ˆa¨´âBOsaìžÄŽäBl*é[ñ/¤v*­¡ík¬4DÌ%n™E†×»¨îÔ'Xk¿Œ)=b aS <nc…†Ï.¯“a£ ‘áûĆ˜SZCްÁ°æF) }ªa0ŒÏÀÁZ¬4ŠSJÃçÑ~4•†˜#ÄI+ }º•JCú&)Zgèˆí¥3tÞÔfœ²Ôf=ë ¡ ‘öO:à õ:Ã}—wgê ÷ÃfXÖ: qª ‡|Q‘G•aö 5†ëà¼La†H+á©ìï¥2TLáÒ:NCj уÁ2×þ ,š C˜ØÞ…!ZÃ.Ya˜Y_ˆã`}!î}±Ì±Zô±Ô"ØÙÁpßãõÿGS:~eª 3´zª wœ |Õ…æ™ê³òM]ˆì®ÑœT: {© §¢ ”ºpʬ¬Ô…ë´’‘êÂnº¿FÐ?ˆX[ˆ{¯º°.’¶nITW§¶°nDua=I« agCݯՅP£mua8I‘æ¤.Ì „I…hGÔêÂlŸ¡0cÕ§¶qèÉŸbÂs+ k6š ÷õüÞ‘°l$Äyho$ô$O" bú­€°ž[a@OMaÎNaÆÝK ÌX¹ „4dú­€°"è%fÄâ$Âà$œ|I„4‰°FÂDˆ¡ÿ-G…æ[˜@˜qÑ3ôž0ƒÄ&ætLEa º……š<ˆNqD̓¹H$fÄçäÁ}mf=ñ`uÓ<¸s¶4ÄÔúò`ÎýäÁýQÂwó`ÎÐäAŒ#÷ÃæAD…óÃäÁ|Y“«£æÁv+ò`†yLÄÍYB8¸?ó÷ Ö¤0 ÖH˜qÑúÐ`5Æ4X#jÌø¦Iƒ??i‘ûãP4i“clÄ»¹± hpòèM̈¦Á ¹oleLƒ;_2£`F1NÌÀ¼‰‚Õ#£`+#Ì6 :]‚ Jð¥3†ËqÍñÑfµæÀŒs”˜72¢_c`F6f ÀÄ@Ä6ó)(´#[&†ÊG=X ë"Cà±éˆ9!°FÓ˜3ÚeBàNBkˆgÀ[‰1…X/°¦¯i ¥ÌÁ³j0k5îÜD5¬æ«^ ÊP?f¬nsôÌuoá_½Æ¿á_kŒð/«5ý•@ð‡ûð-6üUµ†¿ŒRjø«GkøËPr í"Á_ÍhÃ_+#øk5 þr¬þšDð‡±™TÕ þ<|É~y«d¿¼U²_¾,f¿v‘ØÏï`êóMN`kŒØ¯ê5ûÕ½Å~ùj$ûy§JµP­iôËÅ?U‚\ÐÊâöO´]þË„Mf=„œúª±HgØ;°HtØÃÛÁÝ´Yo¼«6™âÏYÇHÜ<öÀŒ¤?Yˆ^ p Ô+Ô-Öó n±Þؾ¢¥£-Ö³š´Xo¦H³ž­Šõ¬Œn¢›m4öN™•ìÙø. Dá¬ÁÞG$ì)QÁ^Ú&ì9ísƒ½Ý¤iØÛìí/hAVë´‡H¢ä+Ó#|hoåL{Ï]¸wÞ¶35î#÷’{“÷Îe{UóÞPlŒâ½¬9¯°ËÀ7Žß)8zpî⽡ Å{ãV¿øªV_’Pß”5cߘfKßPˆ’>D³§VÍÀ—õð1^ñž7=Å{Y±yo(FHŒªYÄÀWÕ4àÛÄwE|ÂO_"uŸ¥Ÿi8‰/Û—Äï–Iâ3×&ñyÛˆÏô^È—¼iäK*Lä›ñˆ/ÛöÀ—fà+¼3ðÕðœ |>I*àÓáGñÞ[ 5wÆ=(Îy§¿à½’÷J¼gHÞs¤õâ½ÄƾD†¾¬ÇÀ÷~¹¨ûLໆAÍÀ§UÅ{Î{Õx/Ô¼WÍ1ï!ÀV· -\IÞóáBâ^1îÁÔê‹{Ù…Ä=Ç»OÜËÑJÜË^&ï9ÅAŸ“yðåU |yó¾¥H’|¿ä½¿Î{³ä=æÉ(Ü{‡»ÀÂ=(qÏ©Û ÷œºÍ¸‡uÿ¾ºòþ´»TkÆ=dñùœ­ˆoMó‰Ï.¯Šøò¸Áć×c~‘Ϲ ùü’‰øðò² |ÉÓI|¹Œ˜øêF‰|ùÆ'òe¿…|ÕíD>ŸóU1_½òÉ|¹&ôåÍ }µ:&ôå”ÐçÕÅÌWÍIæËæ$óå»ÐWW‰ú²}I}u‘¨¯Ž:ûrMîËE ¹/kNîËe!¹OGí…}ù²&öec_¾uÉ}¹P$÷UkÄ}9ÄÉ}ΆXà—Ó/É/Ñ$¿|WM~õ¨L~ùL~µ*˜üZ5"¿|… ~Ùïä>/ ‰}^ ûüñ(ìs û<ÂÉ}¾SaŸg@aŸZgêËDŒE}^¡ ûªcŸæpQŸßÌ¢>Ÿ‰›úrÎõe—ûüq.ìó–©°OçÝ~žÿB§Røa6œ_dcP°t„ùó.æc˜0LŒýc š1ÞÒQ0AQxá«ýñ¼`>B¬Ôø9m¯0ðÆë¹u[ÐûE¡‡ö™ÆÀÌt—~‚ÍÝxGìò¥0ð`ÙÂÀ²Õ2â}²A¦0ð„Ú­Û‚†â[&šÄÀØÛÒ$ΈøþÑù•‘X9¦Ï;íE gé'¸OZé$Æ'½[ƒÖj~‚¶¦IŒÁ&‰™*,9°\ÍcØ^ИèËQЖßÉXÀ«ÄÈ)ÁC†ä@;|ÇT²¸äÀÌ…Þ;¯Î³Šéxò¬Þùa”r¤ÃKÑÊó~VÎÉå³óT~˜JB¢0@]Ôa€´åŸç‡é«*?Œ²0T~˜ûÀÃSa€•› ÂÉÞa€}‘òÃè籎¬ f•g¨âï,Xùa*Œâ+7AņÅ>+^¦rÈ(PÑ÷X+Xq€•£òÃÈ#£óÃt^—ʣŨ8@íV–æ0*°Ò)TàÅ‚h¨—ßòÃèVT`˜ÐOå‡Q ÅÖEx<ÂU`%Ñèü0ZžŠ”ÃJÇÖ‚U~˜J<£8@ù«t 6BË£ â+kQç‡Ñºw~e›¨8À°KMø÷‹ü0õ¨T ’X~˜j£8ÀJ™8ÀºyX9ž„õu,üë £Š /ÈÉù³óÌT`§z‘)PQ¨¼T– F™.*PE,-AŒòýT`åƒQà`=´Ž¬TL F¯lÅÖPž †WU‚ÝsÅvÅŽ…?úüA‚%ë8ÀZ‹Š¬ÛYq€ñsKq€µÊØW)ð Ï'ˆQV¥Š¬ÔP8ž">Ä*{ZÇÖ V‚˜ÊU bÂ$7'ˆ©«*P‰ã:ð]ŒgNSo_ÅÖCXq€¥VÅÖ»Vq€µ„Xi*AŒžÁŠTö»Ž¬»Uq€•ö©âk‚Ø)cXOSÅÖZT`eÛª8Àzœ*0~êûÍ °Ü ÔE¨sS‡jãî0@mÊ(·½ÔG¢ÃŸå#?L®0@}Ñ;?ÌÉ;?L§™Q`M°â-æÆÖiùaˆ F'©Ž¬\9•¦Â&+?LØY@‚UØ©Ì~‘ödöýŒðBeö«"eöS ’²úUµ›N£Â Fua*ÌΘ˜ÊSz”F%|„žGæ¬Ú@̦AüëC¿.C$üëREÂ?—ÿBB3 ñ¯*‰þLøë*I¢?—€þBrËÿâÐ_—_ý¹ô7IPÈ$ ¿.ìDúsèÏ% ?—€þ\ús 诫J‰þ\ús èo’ 4I@&!ý¹ôç’mê„ôFäþ¼ àÏ%€?—þ\ø›$¨ ÔCýZ@ô3ÈÏ?€ûLØgƒúLè3˜Ï@> (P øúoòž €{&í™`g= UNìuÝ+Áž·¹XHÕ²{Þæa= “°PKë©Á^½²d=o±±PKv–jÉÁr@-9YHc‹õ\’¬ç‚‡Õ€LÂj@-,T²žKV–jÉÆr@ÚJÅzÞæ`= –œ¬¤rYb=os³PKÖªÅëy“Áz@%!ë¹de=  ëy›õ€ô¡ëy›“Zr±"PKnVjÉÃ’@¥:Y¯³˜‰õºHYÏV™¬gkAÖ³¡Èz.ë¹äda –\¨ ÔCÝ, T3&ëùE‹µd°8PõCÖ³6d=—l¬Ô’ÕZr°<Þk±ž·¹X¨%÷2uKÖë2~b=Ÿðxæ¢nb=넬W'¡ž_´³:PKVj PÏ%«UÇ7‹)²— ç×`ï{C-õ—õ#Y÷S’{U§÷Μ¢µªSÿïÖñõ <}µýƒZOÿ´TÎüÝw±UmœÏ'fæ]ŠWZ9'\íÕœÔC7b/Sa(ödŜГ×rRO݈=Me¡ÔS—rbOVÉ©zªFêÉ‹B©§.äÄž¬ŽSõTÔ“—„RO]Ɖ=Y§ê©©§¡ÔÓ}FÕ“ñß°ÔÓm‰ÿøÚà~µ þãëøÜ¿_‹ï>þz©§çœs¡'+ÏÄêMW•dzÿïÿ÷¨q®Ãe,ÞôžEn“>]êþ¢£ï‚Rÿ´§ãßP*JžÿÉE ôÏÇrýÕPÑô«TÿwýßSÿ÷U*„Ýj@½góª…ð³TÈþ¿ú¿ÿõ ™j@mãk@½ûHþT5%_ì®eOž'ýÿîØ "Wtœ¬‘Á òeó´¹3]öÈÜË;òÜðm‹ßf@÷ŽTØ‘-:¸q* ™é*šâŽÝ¾e¾Ü-mO÷³ÑQ¤å=;E”óŽÄ'“ý-hsÐQDY ßïE”âíŽ/Uvé~nä‹®J/¤½ÛïgÐQDmî±ÐQ$~YÎ6c¥£Hx›æÐc££Hå’;E*Áû8è("“ü+‘£ˆ<ÍÆIG%ß¿#Ãsåñb EÊzé¥Ó¸ØmƇ£ÈÙó˜Ü ­O$PXisKÕŸpï‰|Ñ‘3ïIÁN?YtŸL]ë¦þ'Êi¥mQ–¨'VÎ=[ž´O¤Í†µž˜l‹´>adyh»ÑÍ Ÿˆ²è=‘÷¶EÚlž¨þ´®fÑz"©Áê•™žÈj°=>Vä€m‘Î{ODƧmQÖÏ'ci;qÕ…tÑáž“Çî'ÒyÝS“G~"5åA?™1ŸH—2NW4ÞâÅóE¼ïýDJ­m‡Ÿˆò>ÛA?ÙÀ_ ýDZrÒO„¶g»è&Â:QÏvÓK¤Z"‘ö]ô©• gÏ´+*„ê ÑËKz=ÉâVøXè#"Sös¬ Ïdù¾>ǶV18¶ÙUCHwü8+βiOzºïjà¢36‹Š1?Ç©Ÿã¦‹HÝÞãÉŸ ã§ñô[}"º%Ò‹Ž>ÌÅ ÷Ô{·ôµÏ¹æ¯†ÑfÅÃnÃöÚ'Ž‹±‰/ã¸èX^”‹¯ —?.Û>áÏŸ{øN¢ í> ãy””?Ó*øLEÊÿ¬qžOEØ#åK"ëLäüªdä'¼Q#ç?'×–?v ý'êZÇ^ óŸ——óOÔ4~ÿÌ ;ÍýsH½°šùs]È~xfßeÍ”ÿ‘Îßõä†ý5{®‘?öbÝ ÓDËñêýžÒ=DùAŸH›s_fX~"kêC/¦•º‡Èá‰oôû„‡Óê€Úy`ÿ­ýžøD¯îúÄ7î!tË|úv¯öD‘ máxˆŸEî!êçYáò~O°>ÝCTœêyvº‡täÿ¶Ûû iŠÝ™øDÃÕo…Œà¼ÍÚO|¢×iMŸGõƒèéô<#8ì4ßOÜ7”‚£gØ3VÕÒ'/2]^Âç;ëµ@î!ú*Æç¹}ð,:uN_ª¤Å7ÝCTÙæÝCä•ðŒ¡úA},‹êñNŒ8©\ž±Fdá>ëyÄyç¢[Ú…«öüáp\+x¾g¸‡èþ8»ÀÕn#N*Ã+‡ø¿ðÚ~7Ò;íy#ErMé3Ò'e3×…‘ùj]‡È`”ÛøµaC‘¯èàK’ÓˆÔ³'ÃÒËdDÎ ¹ú±Í¡úAôÆ!Û¸ŽK#âªáêGÆÙáêG÷¶ŸéwÂ#wäŸéôÑ]ñ™Þv{Pßg‡þ!:¾ ”ç¼íùÓáˆCW¾¯„þ!òoÛ!ÿ–çÛ©úAz ¶Kþ!t"[(‘¾èøå|lýC´…ŒøR§Hi_j¸úéNÄ—:ýCêöí›êчdì{ÆîŒpYÀ#Ô-vòzÇ tÛ¦¯òØQ=¶ß€±‡oý9Iî³Ü¶qÿ"˜qlöª¿¯½Ê1™øNã4N§Õßéõößé<·d_x×GäÆ±Ù¦7"<êäx Íys/ׄW…ëñë¸Ó“+jÇÀåÝîå5z|ú÷ßÚ7xœùMq5ãS½ZÕ•_ê¨ÞRrò—íž.Šð>:é­¥âLÚY¾ÿJõ'AágûY. ßÌÎ&(¼öMYÅ…ñ[ôÆ&€Â°3ás-(¼b;ð #M>ׂÂ+¦M^±±  ð Ð@i0BaWˆ^ñ".…ñåFÝAáõžP]DP®&ø² £ ^¯„ÂëýaÛÆçû© ð ®ƒ ¯8è#3™ðªâ#&¼âwíÅ™0~DÄ‘0÷æHxGA(I$ ž!aœFžø $ŒZYˆO"†ë@"¼—S'6áa(8?’ï%~ݧ ÃÜÇ#%‘ðN»!1ŸØôÓa?‰„.Þ‘^"ã5…„!¹–  ‰H„w”áŹD’3cÑE„÷º°tŒˆ0$iDdÔFÅë#¡_"ô«@„¡OÊ Â.œ-"ÌCaþê'" ª‰í*¡K@„.I"ôn@„6‰0$ Ö‚DxÇ" GBïL’áLèM…Ö ¡°/"ÚSA&Œ‹ŽÛ™Ð.ÞëÁwˆHè× }h ¡K€„Ö/ˆÐ–†D#í`D¡µ!ÚlH„Ý10ƾ3‡›€0.ºð¨“Còð*¡=Ù BSDèÝ€}6@°³Ÿ„0 ¡ E$Œ6»#aÈNDBo$|¿ïÖúU`B¿ LèÓÌøtÀ„ÑóM ZÏdB{óÈ„¦:™Ð–‡Lè’— m 2¡KNækÉÅüaÝ  ÐT z@¡IH…Ñ3‘•Tx¯ŒýÚj mE …Þ  0¶| …~ ÐfL(Œ±ñIÚ &F›‹N(´ž…Ö ¡ÐP8I MB¡w (t  °—‹L胃 mÉ„öZ‘ m×$Úê ½M2¡m dB—€ m_"Ú3J&´Ç‚LèmÀ„öâ“ {½Ä„µé [!aw,$ô6@Âx­–˜HØož° !¡w $ô6@BŸ1°o ‘Ð."öƒ"$t Яz a/²°&!¡÷$ô~€„}lšZDB[0"¡$´Á‰„¶DB»5DBïHhS&z?‰„¦‘Л MB$윉BBÓŠHhš ûè#$ôž„Þ3ЃHè ¡$ô6cš‘І&ÚÐDÂÞ΄„~Ð"ºHè= kgÚÚ}Ê Bë†DhÓv¿B¿@è×m$a?£ìS ƒ÷ngÂ;è9d( ×ÿÀ—Løß»’C&ì$kbÂ'KdB& §tT´†WúB# …q|}ÜPØ9Ä„Ág;\šÈ„á«ÎÑÉ„ïÖʱb±*ÚCLÀ›ì„‘ÔdHÉÌOö$LW:xa ß×93©7¾¯ªŒŸd‘çF\&ŒXëp&ôž…‘Èî¢P_;$€B PXÕ}Å„Ñ ~mŽ(¿·ƒ± »ä® 0Fø­ZfÂÈ'~9Žp…уPèm…ц?¯ G·¯@@@áØ•OPP+§pQaHæ(´~ …ïnÃßúÉ„&ÆÊÜ€M"aׯÆdNIPS¶LâBÂZá²öH „>9a,0~úÆ:àP@´‹Èƒ1þŽNŒ60c“m¥Èƒv ȃUËY8íì8¡´ppDù]JÀƒQÝ™w›<ý `p0ORó ]DìÙÈD¸±Ú…pÐ&ŒN¨5qÐF ÆÈø‰J4Ï8E…ƒ¶2ÄÁ~„ƒÑñ…{Kì¡Hƒ}÷Iƒ!Xa'# Úm" Úë$û I’íþ“ÃI†y™û5•}°5}0B‡v‡ÁhÙw¥ë,û`?²ö»-aOXBkCa¿Ê2ö3,a/— „µÏ•0 F9{t{“°jÂ@ž¸´õÑ@Ø«%¡ D áû8".¯,„ Ê”°u’°w²`o DAS€,h;!YÐÞ² é a/XÐ/ ÚFô‹À‚¶«‘M+² ½T`A{pÈ‚Ö Y°³¯Š#‹ë€‰]Âz§ˆ‚öLí" ÚcL´§VöÁúŠí*² iEì$YÐn'YЛ€mÙÉ‚ö“mÙÉ‚öm½È‚µÁû! öƒ,t X°5/ó`mndA (X;ŽH0´™É8h`/¨Hð ÿ&Ø0@‚­¶H°‡&šØÏ£8Ð4"z¿à@› 9°Xèp ÷ìéM ´Ù€mÂ2 Öv( ì7HØ/«(Ð&C ì=]†Áz°D.ÚP¤@Šèm@ý —aP/kÙ{6„@ÓœèC}(@ Ý*B _5_>B`¿˜‚À˜/Nù‚@›!ÐYB ·ÆôVÚü¶„ÀÚÓË,X{€ °3b@[2 Í†VÁVJVÁ^+B`?}dÀ~SeT‹?)%êc†î†¾ (r ¡¯?…òÐ,à¼CÏûgLΡgÙÔ䙄@1r «ßd÷ýa ç2ÚÉ|aeGðY1ß³ó«!æ  šÑÄ|]ŸYÌW%’ úêÞú¬Bß#¼.è«ÔôÉG¨˜/Š?a¾b¾rÔ*æ+÷©b¾ÈXqMÌ׎³b¾rÌ*æ o=¸ä úz:d¾@f|ÞÉ|å¢[ÌËä92_Ÿ$Ä|í&&æ«BÕíº03®˜Ï†"óY7d¾vZó…iõž ¯¯ô…Ã!@K®¡ Ó’·k(ऩo]Væ5n×P%Õ+êËX$HäÚmˆ}Œ<¹†.«mä#ñ‘kk-´±È€uÇ…€µÚEDÀ¾(=É7ÚMŠ[m`?$"ÀVRØ/‚°6`ß\`}7‹û¾‹ŽE€68°WXØÝûF–ÈÉ1Ô/"ÖZ‰ëÎýbPB•uúC3`xgîæf@âdŒ§p2¶ÑOfÀø…c™Ì€f$¶iŽV@kB"|äŽaá‚ ("lFT¸àrþLD¸ÆæH ‰0ÊkؘAj¨XÑ‚¯¨hÁêµ¢ãj8gV´ ³Ïv´`'¦)Z°æÒÑ‚7C +Z0àm-Qš_Ñ‚ìGÑ‚Ø~ d| F!ô<˜Sºn_ VlŸ‚k-*h°ž@ Öt*h0b¦œ;é» 2œ­ˆð^„‘3¨ ËŠ,­*f°Ê*fP Å 2²€0Î78WÌ`dNó˜A‹oSÌ`T3E“ŠT¬SÇ V77SJWhØÄ V?ŠT‹ä>d1ƒL=Ð1ƒÚ-fPÓ©˜A,fPo3X+Ø1ƒR‚Tèñ‰ŠìxÀŠTÄVÅ j{­˜Aåez< Å ÚW1ƒÚ;fPq´äÂ~Ïÿ0fPm:fPZ‰ ïC ¦ÁådL±ÐC…hh!ƒ @Q!ƒ:ÏN!ƒˆI­Áëø¡A±BÉŠÁŠ­ÁŠ ­Á¬Ažo-dG Tôd‡ *ò¶BµXÈ Ô$ÚóV!ƒÚc:d°#û*dPÁˆ C»1$C3TÈ` ^!ƒu”Bªv¦_”†*OÐ?2†ïËéFÁH­ŒØ0"`×ñÞ±-‚ˆ€~ð[êâÑ!Aw! ·†¿‚ˆ]¼#ŸâæVÁ;ü”PŒ èmÀ€!9˜h è£GDƒ]4 !Ð%€Àûˆã¨‡z@`,þ ˜1<0Ä>wœŠ77 FšÌeŸ'ããPv;ÆX܈›¥Á .øß1@°†ªÁȧg&†wÎxÜŠhP|à{R½yãk-xe9d|`M¯âãɼ§A»Š‚µ\ X‹S‚­•£ìØévÁ˜òñ¸7¨®Á¨b&U€` J‚ÁÌ "D€`0=‡b€`ö†n æ²ÍB­ƒÕNw5% hM T±8Ú*+@0òîMèÓa€ ]ÅÁðžE4§"c×8‡Öã^!‚=ºB–¥¬A»!‚ý0)D0¨Ñ~ ì{¥Á~v#Øë¥Á@Ò)kŒi¥Á~Ü#Ø£+H0’ó.S K$ÅN7 †¢ëbicü" Ö†[A‚ý|)H°Û(H°ûQ`O™A‚QJÀ0nù²O1‚ýª)F°/bˆ  ÍÁ^-…öQˆ uÌÁ–(D°öñ ìÇB!‚q†îó¡õ3C#uÿI'Q„ö# Á~í"Ø…Bû%Wˆ`ßL…ö«§Á]!‚½é(F°_Åö¨ÁÞt#hW!F°'¨Á~§#Xû¸Bã§ŒÃÝBí6(D°×‚!‚Ö„!‚­¦B{I"hm"ØOŽBëV!‚Öc{#XßòЬoyÅö“£Á¾}Šìù0F0¼qOGÀ~ú"د™BûåTˆ`*DÐÚ0DÐúaˆ`I*DÐ$Œ¬g½bk¬Š¬[\1‚‘Ìœp‰ÁZöŠ´n#XkQ1‚&aŒ`u*F°AÅÖ³S1‚=”bµÈ"hM"Ø#)D°‚ ¬7¤B{)"hW1D°G!‚õîUˆ`=("Øý0DÐ ì)+D°ÞØ ¬“W…Ös[!‚}³"ØZ)DÐfÌÁžŽBµT„`_¤Áz÷*B°Îì!ØZ)B°o–"{(ÚE ìU€`6 ØOºëËY‚}à XO’â{dÅš„ñ½VŠìV|`ߘT€`ë¤Á¾á ìÑ ؃+BК0B°ŽÚ!ØO‰"ëÞYA¨2ý![»%…©ú6•&·7˜õ¦’wR˜UùI*)L§‰aR˜ð ½Ü4* ­4¾1)Ì©ËÊ Ó¦„yJÜ”0'£Š*#L ˜¦ÌsåOÊ|0&‰|0ö'óÁ„éë˜òÁ˜„ aL„0&aB“€øBWŸ·ñyŸK@|.ñ¹Äן @|.ñ]§¢…|.òMÔ2I"Ÿ €|.ò¹Èç ŸIˆ|.ò¹Èç ŸK€|“†Läs Ï%‰|.ò¹È×·XÈgmˆ|!¡/‘Ï%‰|.òy7@>oäs Ï%@>—ù¼g Ÿ=*D>»ŠÈgWù\äó«À|Þ&™Ï`>—€ù|:`>oæó6`>œÌgW‘ù\æó«À|.óMTêÑÉ|Þs2Ÿ À|.ó¹Ìg2ŸKÀ|.Iæs Ï%€>›1¡Ï´"õùU >—€ú¼PŸ÷곫H}v©ÏÛ€ú\êsÉK}öª‘ú\ês ¨¯¾‚¾þ$ú\è3 ¡Ï:&ô¹Ðç@Ÿ÷èó6€>o“ÐçM}ÞÐçm@}.õÙU¤>—$õÙE¤>oêó6 >—€úü*PŸK@}.õ¹ÔçPŸEê³6¤>—€úüª¤¾I€2Cv°Ï%À>—û\ìs °Ï%À¾–û\ìë û¼ °ÏÛû¼MbŸ €}.ö¹Øç`ŸK€}õ"‘úìo@Ÿ À|}ÄôY0_T¥¤s ™Ïšù¼ Ÿ5ñyŸ5ðµ€¼gàžuÜspÏ®íyОK@{.í¹$iÏ = °×²ž]CØsÉÆâB-ìY7`=õLÒ3HÏ{éY€ž==û´=ôú rž €y&æ¹``Ûuˆò|Pž]ȳÉò\Ès ¯»!ãY0žµâ™„ç‚¡›³%àU«µ.ëúü¨hɺ¦÷7 Ÿèß¼®“·èöÝâW×üy-¨°r¾ßõª¿¬ö’d]‚¥$V{éÝ*Bëšÿò~(³~$™úyÒÕKþÿÔGH¼‡üûß^*²®µÔñ7j@Ç¿TêãáyÉ0ЍjÎ×£©—ú_ymxÒõ^áI}X+ö3µb_]âI}y'õe­Ø×ÔJ}U‘§ê˪íÇÉ€T„z%ï©»#>Þ¿¯øµð‰Nò¤ñJÂ[©s¼‚gûñ¬5¯$š[Z€uÙ¢2J—: Á{ þm„»lÉ^ÉŠ°qÅ¿’w^Ä‘¡@GŸ¿’QŠ y%ïk3,V:b2ŽŒî€Á÷ýûÕ Ÿ¹ñ£^^ ,Še±MªóüáU{ªó”ï¶É\A¯$rÇý–Þë;ÛÄ?¢ÍÎ~v ,pƒŒÈŽ3}0ã÷$ö“:„.?\õ=]ÁÓùwúxGò#þýÀsL¾âÑå„ÂĉqŽe+=Ã;B ä‘Þ­Ð l”¼S?ç6QÜ÷·Œ?Y( kÄ|Uü‚Ãæs„ñoí8ÎðûÜ |é4½­©“KâÿèÄ‹ < œðÄž¯Çoÿ ›ðþ5'vìµ'$'ãÿŽúÚó =_ žYro? EXØt óqŒ@v8«†êòÃÝOÖâok®¤´¢Ÿ¸2:€~ºáª|ýœævÞ~¥Ã =x§.^õêp›£s¸,n“pÃÀ •ð5\k‡ýð4„Š… tè^îø@Ì’x ~ë@œp|¼R«žqصιgêð®w›:(’)Ü…7Ü«.®á¾¹â^1Ü#viµàªgYÌ—6þ?täèå¡Ö†:ôÚ<¯ûowA:çCMøž=q³ký(T¶K+Þó‡:Èg3ª­A…EÕ¬åç™uˆ¨µéª±ÌOd䳜µŠŒY›¹¦F!+èÐ÷êbhUïC”Ó;fÉ; ¾W æÅ.®y6¯÷¤Ã ý6é {þnÍÞ+­{lÍ¿µëøšêêýÆùà³ô7_s3Ü}ó?s)=êfM_àÓ¼‘׬sùªgi²Ûïp–&c|uâ2Ýö³®ÏtͺÝÓÈñy^}/[ãûÌw_ªu—½žÐi¥Ö/50IÔ#2ÇçWòjpMk¾Žñsû~²n bêÍ[·õÖ}aÏÛF/vì/ë†à ½ k|Ÿ×iÅçƒóJ.Ôú.ÌöqW6jÐ÷r£6V”‡óçqÝ—÷‰Á¯d½qŸô&®ûvýŒY"t uPPÓ+9:Ùwa¿öy§X÷{ÃÓWkµ?«´â ï ý[‡¸„dÌ{øz,χžGdH÷Ýn=¶kþ2­ÇŽÀ€Ú³×ñŒŒ ‹Gëø¸3‡tЛ¹7ÎE½ǃs‘=p.R _HÆÏé_òõ”5¿S:Ô}n8õÓî8µæçqüxèß+ÉèÅúN®ñž¾·ë)úéP3>Çò±Sœ'£ÖüZív+Êè\Óz]Ô¡öÑõ’Œs}%Çñã!K¯äÄɨïÄuM{ïßèuZ¿øFÏwæ’ug²ÍÔOäÍ?¦§ ’QŸþ={7ž¸ã¾’ýœÂZ_‰tÐùi½¥CÝ«ûÚ>öð;ƒtúYoô:­V|£·iǹ©C,×G:ÔÝ{ð{ˆýl8õ=vœḛ̂>Ç¡'c=ç®çïÌs}œïÖ:Ô? åzÆzV/¾Ð$úˆÊŒ©Ó¡}`HƒêwHƒê‡¿U?µ ”@ðŒ$Óïral…yH$xE&šƒö—ÈL~d@‚×úÞr² HðÚNfä ^ÛÁrBÁ+²Ê]¤±ä¨kß™wL,xí+½Ä‚WàÍJ€L Éà),§àƒgm°`HV1er]~' ^AªT( ÆÅ¯ ’*4³¸X t€  ’¢B uz“ÄÀpº$N×`öÖ„0!óžn[;… £…n" °­f‚@ïåàì­ §2‚ pj“5µI¼Â³úp¼ÒY‚dÀèi8R»$ýÎìïä'¿ mûR 8µIô~N*pëW‹“ó·&‰OSlj€!AêP!àÔ&pjC®ËIú  ·Úô@€S“$Àhr¨A€~5hA²ÓÔK²ÓÔKòßÔ&ùo’Œuºæ.¤Ò] T›d§I’ìdÓþù@À¿é"ªÐ}iú oÅE|šää%üy“€?ïð’ûpø›ÚPë%Áij“ð7Iþ⪋ø›Ú|©ðP“$8Í’ñ¡UÀŸøs­Sê ²‚¿©M‚Ó$Iø›zNø›$ “äK‡Aª áo’¬Ó5„¿I’ð7I>u üMm¦‘&IŸÝ+ÂßÔOŸµ–ºj]Ÿùïí¶”ì75Hö›$É~>¹µ¨6¥@I’œ¦«’œ¦6É~ÞìçmÀ~®ö¶Ýs‹ýšûHnšZ$ûM’d¿©×d¿©ŸÒ ®* ªMr“·ûM’d? ìg·aÿPa/J’Ø4u’Ø4µIô›$‰~“$ÑošÞ— @¿I’Øäýý|>@¿©Í1í?D¿éê`’{û”<ëÇ­úMóKôsÉIúª“:˜d»>´úùœ~ÓUç<6Ðojñ¥ÃIl¤±|ì@?oôó~€~S›/®Ò¡®:¾TÕæÜ?îU ßô÷½Q+Íè7µ)j¤1>$@¿I²Þ÷ è7µÙÏ­î/nêÐ3úMmîù>ý&ÉX>¶†ûK‡‡:t¿@¿©ÍvÍ_[¢Ÿ}߈~S?çþñ¼=ÔÁzþÐ!Ðoú{,w èçm€~Þf”„¢ßÔf?)9‡¥ûþ+ŸDárY4Í øòÜAKèïŽÄŸ·Ù—w™§¿'Xï!Ù%ý=‘Èœ¿ƒþ"^c§åô‡¤õtú{‚ìhaýELÇÁ_¬AOäô¤Mô7ò|œþžÌêL™‘þqCà$¹ŽœÌ±““þž´\Bð7ͼ ¶R²Sƒ°ž‹cȫ֕ä–õDÔŽƒ-ø/¼àsìúMù AÕáú%÷>ý™ü÷Dêêü=ŒÓù/Úì¼êàô[ŃÓ7IâÓÔOòÓ$Iþ‹óïý“ÿB£Á› œF§ 28Så1 /0$2Z} ¯åI z䓘$ù)48eLLœÆJœzNœÚ¤Ö uè•z/ @¿ ’m¥¡0Ðn80Ïâ6@W Ž×z+Á€S›dÀI’ èR0 ß¨ûK…ûK0 ß<0 ß*@`Œ´\nô½©C)~Së& jšNÔÔMR +è×€§TáÝ’ør?T¡ÕúH À;²€ž¸ã @Ÿ1(p:ôR<Ô¡o0(pº* ÊŸ® @ïèóºƒ:ô# œ$IPS?IÓØI¾‚ ÀIR:è±Ô¡´"Úþ’h½'IR`?&„@[tB )NœºI†šÚ$šâ„@Sœè’•*´R+U`'Á€¡áu9ÚîGŒ‰¬tÉ€>Ûµæ¯^9}6ÊÖ›è í©!z?@@ïg£ºG€Ó¿'?¹Ž@ÀI’h:‚§nKMwûRhëôÕz“ä?ŸÌ¾_ó%P ªNéš„§©MÂÓ$Iô¥N#%úÜ©Aë ´“Ð üÇÕÈqÑ%£ÝÖ¸ÜôçC¥‚¦þ›Ú<+=îEä¿iÂcÌòß$¡ }ø/¢…NšSÁ¦&ðÏŽ$‰Ó߉~NªÐJNsÕf,óÃúóÙþ|(Пw ús-/jÐCþ&ɉÓP0´áÏ×ô7ô¬óŽp•5ô³N`?¬7ÏÜzD€~®6Ðo’P~îR@cýüÉôóÅúù&ô›fC z©žRAKôóž~ÞÐoêç8æ÷äçj`#}hà7ýûÀIÈ%ãcGøMο_ËÁù÷Hô•¯÷ÿOê<ýì½¢k#a/Òo {¬¿ó¬BØ‹¢'»;}>QYÀ^ éÀDØ å{‚½(åYø—ûÃúü̬10ôG#ëmïáè!¦õ"Èj›`o;Н{±‚íô¹tþ"ëÅn¹¸¥Ï¶vÁ^å7/س6„=Ä:þÞ¬.Æ»ÛúœƒÉzQ¯O„Ø‹LòB5âjótžÿ}ÏtMÜóÀ½¨bÆu!îE8„PŽ ¼×r}‰{á´ÊC&qϯ,…×/M©Ä=—÷ ¸‰{ÞOêpêö'í5ÄöbëœaÏÈŸ°çÀž_Åù[οS ì™Ö„½žYÏ›€õ\òlóÐT¡à ëY²žM†¬ç°ž_سS{~@É% ¥H£%öìyÏ€=ûe$aÏZö¢ŒÝé?ד°gcö¬_Â^/1YÏ”¬g÷ްg“¼ 8ÉgÖ³6Éz¦Yφ&ëù5¥ÁM'ëùUÉzþ"õìN‘õ\BLBLNò9ƒ“lE“õüo°^/QÏ›P…^,¢ž)NÔ35‰z.êÙûNÔ³‰¨çm¨BI„z½Kõj[éõ¶&ÒóN¨BGÓI“*h§éõÎ'Òón@zµ|= g’µ(ÉúÑb»}ëéõB‰ôlþD½^’^E„zýè õ\R2‰z6=¢ž NÔsÉöqM’)@Ô«2…z¶ÞD=—€õ"ôád¿Ð <†ÈÑd=Ÿ HÉfCØ³Ñ {ý]íE½àÝhÏÿ.4Ò^§E{Þ/h/c¾Ir ½~ô{¦aÏ:&ìYžÝpÒ^T]ÝÑs’çÜ/Uh5I{uXìùE %—ö|z€=“öì*Â^„4/ìÙt{¶~¤=o´×3Ñž_zÍ {ïôô3aÏš æŽÉËÓyŸ°ç’M§9½Î„=—€•:²J°g«•°gÏaÏn%a¯­¢=Ÿ XÉâžDÞ³«È{½Ä={5ïR¡PŽ*ôm!îyÇ7¤Å }~H{öþö¬Òžµ!íÙJö–CT Ú³»@Úó«€{6òž=¡Ï=Ï/yÏž=ò^¤É¾92xÏ®!ïÙ8ä=[NòžéMÞ{åøào”tªx¿õJÇJsóŒ¶ÙÍ3¸ˆ!8éæ¹í¬[nž_ ’›ç!×Åöò”€Nžá Oó\$'Iz¸Nžæ,J'O—Pƒ“çËÉÓ%p“ô«ÂOÒ[ÀËÓ%ðòt uhgVºyN’ñ3÷LGOoGOoOO—ÀÕÓ¯¢Öæúûþ˜|=]_O“Ð×s’ŒŽ/ èë·Ü6á+éøzúUðõt œ=]ò¡C:{úßð”4 =md:{ÚJÑÙÓ¯úÒà, ª |%]oO—ÀÛsÛYñ´¼=ííHoOÿ›:ô5ôö´6ôöô6p÷´ÓÝÓfCwO—|é@‡Oïî’.çKàðéýŒù>Ðás’|ê@‡O—À_²7 :|z8|zÇ¥BI¾T Ç§Kà.éWÁåÓ$éò9ý=¨”z¡Ë§K¨‚Ià.¹òʦǧw O¿Ÿ.)ÔMi |%ýøJv“t÷´t÷´ðö´¹ÏéÓÙÓ{£¤5¯§ àêéÝÂÕÓ%5ý–ÌÓ—§§ Ögú~ž=5ùyZ“š=G‘›§_/Io/Io7Oo7O ^žvÑZó/ÉúÑb›EnžÞnž= ½<½IÍ¿$_ó§—§ÉI2æ·F^ž.—§]µ}¨^žþ7\$[:yz§pòt œ<]R ”¤hÉøÐɳ§§ àâé×ì}”%¤uríóM¢‡§ ààéÀÁs’|NŸž.s¤K¶ëãÑÁ³OÿNû³¦_WÔüKroŸ’gý¸Itïœ$ãC§³4Ðóp~i@÷N—ìç‡NtïtÉ9M÷N—|é@÷Î`ª]q|8Eà+uŒiw“w§ Vá$($øš?];­É¹Ï7);íÏ{›Ÿ1ºuzŸc™2zu¶€N&XïYºtšþté´&ŸS§C§_gH›[:tÚ%Ï:kCwN¿¢&/ÉS³/ÉzJ¶kVˆÞœ&€3gÜ"F‚Ó™Ó%˜ÀíÕ6=‹8ƒ3güž´ŠèòÀ³¯í4 gN»†Îœ.ÁüãW1znbú&€+gŨý¢2SYñÖ5S˜˜¯êö”/"¤eµ +^DŠ«E’Ü}³j§@îŽì.ÉÅiJ¶6 \´‘cPî¾+.åîÈå'SZ¢ÜÔ&Q.$·2¾0ùÌû¹“û%T¸+Hnº(òüG¦îÉcsj‘$ŒÍI.ÚèIrwÔi]h:KЧ¶LgÉA¡øM;)H.ÚÈM$wGj%sI’‹ž¯iW ƒ:¼×\\¬ ¹éŠ$¹©×$9ï$7KƇN 9 $mä\™45I›$ r®6@.ÚÈL—ô|ƒã\#pœw ŽóõÇMm’ã& çoW•wGÉgZÁq“$9.÷(>žà8Sé|>¦Gzyq>=`œOçKŒóÉã& U°±’¦6É@>C`œ+Œ3¥‚ââO™^nªÐÝ¥‚”ÅY'€8× 7uœ7I¨A?E75°6‰@ÓàÉ@¾¢ 8o7ÿ=R©^‡‡*˜„:ôl@qSºlö ã¦6‰q±‹Ü:©C¯ÎC¬Ÿ$¡Y2>6‰ 9ßÖ@r>c œÝ˜Az±€r>= ÜÔM²Ü4tœ«˜óETÁ%ƒ{õ!cZÒPï6Is6✠Dœ³é‘ç¦n©‚]•<ä%™NĹ©ãĹY2¸w몵4Д×õ£ÅvûÀÀ9$ÍÙ$Îy̾?O¤9{ÎHs>YÐÜ4µ¤¹øð¡0“hÎ>…¤¹ì²®m÷ü÷>}·Is“$qÎ8çsÎMWQkSp!@s~hÎW8ç*ç&Iª`©ž³ƒnºêÆQ¨—H7IéúÀB¢ó& :;?‘è|p]k.etÙq2IÔ«ò¿©‚D.9`‘éüî‚é&ÉX>”ÓÙ!‹LçWÔÁ$‰DÓUÉDv€"ÓM’óðåÒù«pR…^¬óù8éfIž…l2`ºI’Pgƒ_Ô uº¨]”häÓÖMm®}n‘`7I’ì⦺¨u’pä7h7I’í|9w“$áΊûK…›*ô#¼ó¥¼óùï¦~ð¦ù•ºêùÒ€ç3àM’$<¿¿@<׈çïøó¥ÃsϯG ÞÔk"Þ4ßD<ˆçŒÒ ÚPk“×€då—ÊLÎÎSaO¥A3%FH3…èÓLéløK:Ít(æô{Á]ÔlÚæd,UÅ©ìt“$âq ìt¯D©`h§‹L>œv:—@—ÀÆõJކ;ÿV:ÀHgο4ÑUª2ѹ.—ÀDç˜è\Kjú%¹>Fº1¹1§cq Lt&¡‰n’Hƒ’”%Ë%0p¹&:—ÀDç˜è\ò¡Cšè좉ÎZÐD7IƇN4ѹ„ôcv~i@K`¢ó«`¢«ôúe¢ó«¨C]ó¥MtÖ†&:oK`¢ó«`¢ó6_:ÐDçØ·\K`¢«Rj4ÑY šè&ɧ4ÑÙŒi¢ó6°ÑyØè\BTê­ltö¤ÐFç=ÃÂåýÀFgý¤Î¶ÚèìÚèl%ž/h£³ÙÐHçé\#mY4Òùè_:ÐL)Àf3i•v:›ítÞ†:› u¶¿ÐRgcÓRçm`ª³¤­ÎÛÀVçm¨ƒK CÍGƺnkÿ s_s]ÏXö:—Pëö®ž±ìu½‚²×UI²×yÏ0Ø™„»^wìlì4ØÙÈ4Øù0Øy¯°ØÙìÖÒ $Ô žYìlµh±óža±ë'R;ë™;ë'-vý~Àbçÿƒ—iI“iI“·ÉÎçRhõ¶Ò %c~§d²3-i³³±h´³»›F;oAz=i´ó6°zùH0ÛÕBf;Àjçó- ´â´ÚõE4Úyíl!h´³ŽÓjgÓ¥ÙΔ>¾ ÙÎn.Ív>Òø8ÉlgýÐlgcÑlçm6Ѝ&­v¦­vÖäœíìá£ÑÎæK£Í—F;ë6;›v.Yï'íúTàÚ?u2ÛÙƒO»wsÍ-wÖí£S]uKZIšî¬ mwÖ†Æ;—ÀzçXï\BLBLû—jªÒ|ç“ýΞ+ðleîRzÓ~g˜¿ì= ùÎF¢ýÎú¥ϯ‚Ï:¾>Ît°ß™†i¿³›FûÝ6ÚïLBû]#ó]eƒ,ûH–ýŽ/¼´K<^¬ýqDÕË[…—øoSá%kÑí­ðÒ/®ù …—ö÷÷.0{Õ_^ìˆ2«u"‰LÚ#å^ýð¯©ȼJ¼ŸcËœ´ä_ÞeÖ$ÿþLI׿T€)r‘þç`š¢í W¹.SóùÈ,q„­åµVZ‰×O¥•؇µb?S+öe¥•Ø×TZ‰}Y+ö5µR_]ZI}yi%õÕ­Ô—·R_]ZI}yi%õÕ­Ô—·R_]ZI}y&õÕ­Ô׿P€é=‹qÍÃL°=þãk³ûÕ†øï·ãcƒüÅòÕÇß(À´-’ùO˜¬0Òn¦®ôôg=ÿŽLÛ‘ºþ_X€éùU¦ÿø/P€i;׃Á1 …í%²|¯ Û¹ï¿Åéö‰Þ^ Ë<ïÛµ²îÏvæN±F9NØŽß[žyÞ£ìåͳŕ¹ê£>åÂ~îÌUæÏ )x2ÍûqfùÖ”ŒLóø€ÜtÛµdš÷wNLKþN#Ó¼Gÿø…|»°?ž±ó¡Ÿ+T¸–ðµÂßÇ;Ý8hÃ&½å¡,$×"‡·ëÊ$ïqôFŠþW’IÞãPÈãÒug’÷+~Aehå•5;hP;úK¨K&y¿óׯ¬™ãýÞT×é…ØÌñ~ï7>)¯dÏï÷ûú?”„ w”(çßPá^/VØÂÍ*$g)!È$ïïÓÅTr[Z"^É­¢![f\ˆ6C³™ã=ñÁ#b{¨À­Z/bCƒKYê·ÈŒ’·ÄØm´:³‰T¡ÒÈ ­)9ßé>ËM§¹í!ÁI÷•¤QçùàÐw¿‰cÿÍ~Ÿ,~Õ¡ÛŒ,àó¬1`Æ’YêM°fùž'×=˜ÿón£&3ö ’øi(G¾±Ù3‹÷˜ãý¶ø%WÖ«20ýÓ‚‰wœþþ°fÌõSrS¡}Y²vO0 ~WØ—5?ö‘öU¨öeËÚ=2†÷m_¨Á®z]ûBâN°Í™uobôS’¬{ã=_ù÷øaƒ;K÷DF›Ý>YºÇ»¥ Ç›¿¯Ô`Gìëz@§‹k³¿ÇèôÐXôîùY¹ç9/ìûzdáž8L÷• œ7Ã9ö• ÄkÀ«®’…¯Êþž†c `óüó¹¡Òࣹ¿Ÿ¸T鉧ömɺ=ñŒ‚îöD‘^t»mYõæ¹TWcßö¬z,Äv¬PI{Õ¾Y¶'\Ÿ·IÛöMì|<÷-58Oݶ÷ň¿«Ùßg*­|ZßÍúÄ]ª^ßåÄ]ÚY´â=CA÷Þrív*ðNre?ǪGóÝÏ,zë¹óª3Ëö<\—ýz P=¿û}ã)[tÛög~V÷‘OóÆ÷ýXN)„ztï<(t±>Å~lY³'2¬ìl³oÏÝÁé÷ÛupúñóÇ:$«–÷¸Ù㤿¡‹“ ö *Å–‚#ëõØlÏsFõ柜ÿºòúŸœ ÇŽï¬uÓ›×~>6¸¥'6¸“ï_øY½{ïmt¿0ûØãy_/*°(Š{7ã ½rUÀãS›sÁ†}qS%;öÅŸAöëÊj=ϲñú_Ò ûy.HVž]ö÷|Jr/>C›îÁû=Ž‘t¼Ç×8ïÒÂ:2ûMÞCgsS‡52˜@r.ìº ñ!>°z|ïëV‹Ö+Löt @*duí”P…¾u^üàKŠ‘bÐÐ)~úF7ï—mº“Buàû•™¡¦§õ‘‘>’Ô ŽpïÛŸëdÓËu9ùm½ØæÁ(j¾³ŸqâtpIïAžA½Ux\¬±mó×u?ɘÌÃGò4Â炇­¯9¶C/î€ ñ q÷-5yëÆƒCPüÂKÉ8q£Vyލ{Cqì§Ç²îÓ‘çX B¬næ±@…w<þ}¬~$:â{¼bºû8qˆ{;Åóù÷x.^%ª},R %ÕŸÇÃsݱ.‡TÂ3q¬+NAï‹sè±nó)îX÷wE/Ô» ¯~ú:VªPÑ‘,áÛÄ_äͬã½óóÃ÷å¥>XÇJž‡ÏȱA[Р ËŸ€cã¯.Ï¡oû ¥ô$Û±LÝñ~”ñ`©[¨ÐÑ#>Éë´žÛ}ëá[ØíƒcPíÇ{f„RƒŸSýldÞ…*ÔŽT?ÅF×þR•%Ò^ÔTzy¦hÏBí“ö¢‚Ñá°å}®ƒLv®Ì~ ÿ.ÊNCØ»¢æ˜ ñ†)äQü;iÏœ"H{qÕ†8i/®ÚÄI{Ig"¬¤½+h”‚Ð ,ƒ[ÃÞu©0Yï%le.'ëy‰zÑËîõBB_'¢^t³hj˜þ+a¤ Qïzy‹þOd½ë%ššÈzñ5[g=ŸàX¿T!>ì%Q)úela/$ÏÉ«ö¦‘öBBÃi/ô§áƒ´ç3~JÚ(H{Þ3h/$|Ž@{! q$ioˆ* YwH{!yPŽ´çÝ&-¹€=´ç÷& 4¸—z„Á{“$iɧà›ÆzÏ•ñM#Që:øH‰K!9ˆ\‰K!à»Bà Éà1Àgø& Tè¡|³$*lðkÌC'ðM’¾I ZoŸOÄçCƒølhŸ ø\Pó×:¬5ÿ’$-MÝÏÔIòž ÷\!àÞ$©ékàÞõY6}€{S›ä=Ÿ xÏî¹ æ_csþõ÷sÏ£$íùL@{“$iφÙ9ýîv¯é—$iɇìÍ’ñ3O¼7 ž¼7Iži÷¼ àÞ$IÜ›$‰{“$qχ9¨€I¨€KU’ÚÀ½©çĽ©MâÞÔϘû=©ÃªL7Ľ©MÓ$Iâó‘€|> ß,Z_:ù¦6‰|“$‘ÏçÌç³¹¨C÷{Q“$0M’& Ð7KïUÐ7µ¡6Ÿ$¦©M“K}“dÇôùŒoê`m¾tôMW%2M’„¾I’Ð7õó¥Ãý¥¨ÏWØ7I¶y6À¾©—ľ© u°^¨ƒ]•Ì4Iû¦«û¦6‰}>Ö(Ôf”%Ihš$û6î›Z$÷Í’ñq¯u°Ù$6Mm›&IrŸNî³6侩MéPêðlD¶cú¤ü¦^ül¾¿©×O ~“$©É%?ïàçóøMW%ùM’cõ<Éoj‘Ø4I’ü&É}hò›fó¥ÃV:”$±i’l8ÒEêêɾ~hò»" æ&¢½èwÝï“+~¤ï V^s=Zý¢ ¹…èýî'Ç8ÓõH@¿ë>”xˆèüêLò F ú;E–÷ù>Á/èþ‚Xo™íö=Vã·Â_üŽ»Éfw"±»I.dv”Ó’ð¿E³öá/6–Km’žÒ»šþžœr ц‰¹ OÐÏ妾øYžIù“þ¢—ñÐ$÷²Sü$ÏüåÄ¿ç,&Ð_ž•Ô™øç ÿb¼40JƒNü‹~˜î›ø\ÃLùÄ?ôææÛ#ýÅETúþPð ˜àžðsÙi¬üE·C#'ü…„  ÓìþÂÁœ©þ!a½ Â_¸º1ý#á/F% ®èoêù\§ùþf tØ” ’ôþà×\ê5áÏGüùÈ€? ð7µIrê‘€~éz¿ãýB2dÊ{ÑÏ×è糜¯æ ‡R{ýjd’Ÿ]Cò³;Iò³•"ùMW}j@ò‹±×áä7µ¹†Ï%Áoú÷¿IRó×\VjÐãüº_`ßÔ"¹ÏV—àç#­œë¸rþuH~“ä~æ¿ý¦±“ý¼ ØÏÇÞ¨A=Cd¿éª„'{ªÈ~­7ÈÏ5úM×PûþhñÜó¸É~>7°_ òókvξg²×ì5.ÐÏGúÍ’Á÷Fwè7Í&ÑoºêCƒ`?Ÿ ØÏçö›Ú$ûÙ›Oök­¯ùœµHfòÙƒû¦q’ûây¹%Iî³^Æ´»úl¿&õ¹Æ >Ôç:ƒúüõMWQƒ~šÏ/ @}¶çú\oPŸÏ0¨ÏgsQ‡^Í«tÐü@}¾ ¾I’Ô7]•Ôç³õ¹VWéP’$¦i>IL>¨ÏŸ‘ ¾þÔúì£Nè›$P¡?È„¾Y‚P)}“$¡/®bÕ$B_H¬g@_ È|vêHæóÀ|S‹d>è)Zn•©!óM’û¦RšÌ£#ã¤JºfPVi”¼Àg'Á¾8ãmÎ{vè#ïÍœáº×¯é÷\iàž‰{=6iÏ {v aÏ&“°gÇÉ„=ïâ\~>yôé“/Qoꓳ¯U"êM3ILò«€zöÔõ¢Íƒ|ÔD½éªD=ŸÏš´F+UpÉø”$êE/,òAÔ›$‰zq+íõ|6u€ŽÀ<¿b£ëxϘg´A̛ڼ˜7ÿù›$1oê%1o’$æ…_Kqó\"Göîy§&*÷g%•„vÏñó íˆÈZ@»Î^lWUd‹íªŽ[±]UÁÛuý@±]×ÛÛuu-±]iÛue<±‘%ÙùÊÁv‡Üg€vþÏD»ÆL²]× ÛY'@;—ó7IÍ_Cí"Á9¡q0ÙÎÛ€í"‚`.UŒ3)¸« ‡‚;¿`djî|$ÀKwváÎÆ"ÜÙU„;ÓŠpçWî\rÎ:î|ìÒ¡ÚŽâP/?SÀ‘ÏxgüO¼‹è¨Ã]9ý*âݹ©&ŒðÎûÙ x§ÎÀw6aòK¨‚u ÎE%@ÄwÝF„×*ˆð\ ;*$¼šž¯5àEX@›À7IƇV>Àç#øê»+à³6>[AB_}6A_ëIèó6}Óߟ:ú|6€>[BŸ_è3Í }Ö¡¯Ÿã‚>¾À§®’;#OÜÖŽˆ&7³Àˆ{n‚[`Tá=ÈmÉwä5?ÉmɘÆT—ä¿;‹¨Þß‹ÿî(¨xÁä§;ªûΑbc`ø/$òNÿÝQ”K’ä¿Èôt/Í1’T|ÿ-sÔý^Ø$äÙÙ)äÚÙ äÚé’ç#Å…\;MB×N—¬JûU¸vº®.9æùѵ³“Dȵs’Œ­èÚéme¹(ÉP–‹rÒ\”ö«$«²\È¿rSÖ¯ÏNkÏNœëôgÍ¿Êø%\"Mð(W–pêl}:M°*a™AGM]Mvåúª&p‡t <:]ÓßcÎà#N—ÔüK2>òdÉ¥Ó%pétɶÏJÉ¥Ó%Ÿ:È¥s’ŒY+øtúßðét |:;›‰|:­Íú¥}:í*útz›]¹¾ª ¼:]ò¥ÃZ:T¸Eºä~æ¿á×é8vš„Ž.ùÒŽ.Ù?r}ɱÓ%pìœ$c΋%×N—|è®þ7\;MB×N—¬¹¾äÛé’/ èÛé¸FN’ñ¡};]ßN—|èÎö7;ínÓ¹Ó%ÛG®/9wº¤4(IiÀ¸úvšn‘&¸ïiƒ“c§ ÆÔÃY³ç)·N—À%Ò%û6oÙrëìm]n“dÌÙ×äÖémîûSò(ÑW]·N“¤[çY)°äÖé’mÎÝ*¯NÀ!ÒðéŒsðàÓùžqpéì,²réŒ_‹KG—N—À2€~Šã›$áÒéÃ¥ÓF¢K§K¨Ià9IÒ²U G§7G§5¡w¤q€„¼ºN|“ÎqÔÜÌ¡Óÿ†CgDNˆþœ“D Ô@ð…ôŽáÏéøsÚ½¤?§IèÏé’/èÏé’}›ÿ†?§KàÏi3¦?§iEN» ôçt ¼!íA¢?gKäÏéøs†ÑC>”ÔÁ$©Ã©€¶t猼s+Q ®aIQ ¸sºîœa7¹£GÞ½{©À®ªArç4 Ý9]wNë‡îœ‘O…Q{ðæ|›°œ¼9ýoªà’ñ)7§KàÍiÁ™Ó›”’Й³/¢/§7#¤KàËéørvì|9­[*°©.˜\9ý¸r¾]±ø¬\9ã[³:®œ1Ù•Ó%TA’_UY"×ðYwKÏ26Lbz–[Å›*=K»a/³:Ñ Áô,ïµ?î³€ÂHegyÏûŒÈWz–÷Àÿ³;×Å ¸Ò =KR6Üžeä+ôÈDz–H‚Mû`¦g‰å s]¦gyÏj•®¹M"᦮@z–H’-oQ¤gÙDìâ\óø9¦gÙwÕåRz–L­«˜žå=“h¾ÌϲG*:\"?KH8:ó³ì±óµeoú›:Ľ ÕéMBrÊ‘3c{C¢H?$hÙOE§+A‹K¡eÙ*c3´,»R;(C˲)'€2´D:ÜkÊвìJÿ -˾êŽgŠ–%òüp$è0IR‡%RÇÓŽ‡'Ë~ÿ왢ÅGBŠ–È)9Z–HÊDó’´„V—#^äAÿ‘Ó%rœD›Ç£ö² c9™¦%Öâi×MŸ ó´x é°ÉnÌ<-KÔe$9Y¶Î¯‚,'.Až–»{ÊÓÒz*OKHšÿ¨C$i’%oV•˜ƒyZúN O˲…¥#QËo‘»ošJÔ3>œñ"þÏ⌗:¬4¸!SK¦VvÆ›Ú U‹÷Czu˜ª%ôdÐ?SµØ 3UK?ÇÊÕ²d4H«%ÆîÀõ ~hPe®–¸AË”«ÅÖ‹¹Zâ*®1“µÄè»bõ2YË?B9ãE½¾ÃJÖ·~X²–¸†:e²–ȸE­™¬eY•'HÉZlvLÖb:1Y˲¾; rÒ઄.Èvâd;‰Ù1 “µ,ïdgÏÈ×b0_Kh©œ.Òai'N__æk1­™¯eYôÍQ¾–e©,Ì×i½y <¤A|Hƒ•ûŸòµØ=å÷CÅð åk‰±ø&2_Kœÿ¡šùZ¬_æk -ù2_Kô2ܸç:0eK\%Läl‰‘V9n.Z1gKhÎ7¤Ççs"½\ÁÅI/ï/³51g‹I2i‹Ý™K:Ô}¸¤CÝ+fm±'€Y[ì)aÖï'aoDTúÀ—W­nàó7ˆY[–eå>¯¬-Ö3hoD©/†ÑfÖ{þ˜µÅÖ˜Y[Bs¹J‡zc˜µe‰ú"’ÄÉhÄyK™]µÅf̬-Þt¨ç¼O Ã}”¶ÅžðžßáÌÛ³áŽÍ¼-¶6ÌÛb÷ó‘ëÏâF¾W²ýLÀ7I·Åž~æmIràó5ð…Vc£‰[b>¼3LÜbzf⛉[¼_$n1­|ÓHÒ¡GBÞ[&n‰'‡ï=·ô³¤Ä-ý\(q˲,ÅsÒá¬Ì,û4?dné}@™[ú.(sK–(pâ3½•¹¥ß_T:à“®Ì-½3(sK¼“‘/çCññ(q†R·ôîÔ-½zD¾¸æÀ7Æ!›‹R·˜æLÝÒï‡R·ÄŒiÀ[¥C%Ëaê–¾›JÝbëèQMAt }±:‹$HÝbw&s·ô›¨Ü-1öÃk’ú|m˜»Å{Aî{J@}~¨o’|éÀÜ-õ6xÙ%YñøûI¥g1CB¦giˆT~–÷lÍíIùY¢@ÊêÉ8#ÝåF@`~–ý¨ÄÌÏb‰_` kLLÏòJÊP†ô,¯D¹A˜ž¥k+=‹K2ÃÌV9Q2?KW=–Ï%0ãM’üùÇ%0㹄˜„´„f¼®Ž,3žK`Æs Ìx.9¶ùoê`’kù’|Ôj–Ï%0ãu…g™ñLò”%)Jc˜K`Çs y.9×ùïÒ¡%Ò¡$°†¹Ö0—ÀœgÚó\ƒžKJåÅ¡EÏÛÀæm`Ñó6aÑó°èy‹Ò¡Ú”%5¬%²è¹=—À¢ç’Ò¡$Ÿ:È¢7Iµ*É5¼¦¼,z.EÏ%¥ƒ$kéPXÃ\‹žK`Ñs ,z.)Zò©-z.¹g½iÑs ,z&¡EÏ%¥CI`s ìa.EÏ%°èM’ñqg¶/¶Ò¢çâgZô\‹žK¾4Ø¿4 EÏ%°‡M’ñ¡-z.EÏ%:¤EÏþ¦EÏ%°è¹=—À¢ç’/ ŽÒ@ÏMz.MÌ%0ê¹V=—Œ¹—³t( lb.MÌ%°ë¹v=—À®7I>u8¿t ]Ï%°ë¹v=“¤]o_Êpr}é@»ž·]Ì%°‹ùU0íM’ñ¡m{Þu0 ,c~,cÖ†¶=—¬óØ´íy‹/hÛs Lc“#“À¸ç÷\BLò¥­{.iÌ%Û<Z÷\óžiþ|éð|é@óžK`Þs Ì{.yÏ$ãK‡ñ¥Í{.Ùçû@óžK`Þ›$ãC«ñ¥Í{.uÌ%0ïµDæ=—À¼ç’O`Þó¿hp\SºoûžK`ßsɧ²ï¹Ö1“оçØ÷\ûžK`àsÉ1ÏxýÒ>Ó“>oŸ·…Ï%_:l¥ƒÚÐÄçØÇü*˜ø¼ L|Þ&L|Óߟ:ÐÆçm`ãó6°ñyØøLBŸKJ‡’”èÙK1Ea Ÿ¡* WÂ|TЉÿ6•b²ÝÞJ1ýâš¿PŠiž…þšJÍýv«©„Ò¹‡‚úÑ_ÞeÖ$S?‘J¶J:鯩ȼJ¼Ÿk‹dèµZüËû¡Ìú‘dêçW«>÷3ß »7ÿþÒPÇ“?L¥¡–¨õ޽çW%ûßðMØþ¨Œ|ÖÞñï1õü£âRU¢>ž¬±®]IçcU¯Gí® …+½úS\=Õ~bÖ†½Ìu¤Ð“×~Šž¦ÊOìÉÚ°§¹Š{²ÊOÙ“×}ROÝF=M5¤Ø“Õ}Êž¼ê“zê6êiª Åž¬êSöä•¡ÔS·QOÿJe¨ãùoXê6ë_n‘_Ûó?þÉV;µø“-þo†:#Ö`Ÿ CýÊO½´ST›Šj çúÿ£´S”øygû_¼´Óü¢´Óü[K;½/Ë8Åÿý¯_ÈTÚi¿þ¤´ÓŸøÀÈHÁ½!¿Ék3¶<ò…å™y×Ǧ´Ñü¹ö{[ïøµœ?±##‘ÂÚÅ”ãDæ°³â]ÆuÊx¤±n˜Y¢kJž4R¬1<ûé‚OPgüJ»n¸²Ü¬¬z3Á¹¤q䥩ã\R‡¬EÁž6ЬózBr¤"a·gÚ(â·wus¥âò1:—éå£80¯‚ ñsôEÉÈß÷à Zçº ½|þl–‚ÙåßS!Vý\#ªç²^Œ|]Î}A© åÖƒ´S…çÖ’îT¡rïŸû†B;ùƒp ö\‡EJáûNï¡oÝ»M\*Ðp°“ë„R»ÔÜ¡‚_õ ÒNTãH#7¢6 äÝ/P+¨§w¬é~Òõ^ Î ïRÀh{T¡*^œÇžµ‚¶êå¸ñPÑä<²¾R–Û)¹Òýä~ÿƒ‚,'¯—–ókõ ºÐù¾¼)©z6çûv¤Nçö#JÅÓ=7T ZŸ’ì¨TUªÎHúÞ¥Á #çyÆ#}nÜÎ+7î$Óܨ¦Žû¤ïÉ&¢Œt=‰jiÜi.̾ ™œfßeÎ^ JítÇ×öà4uži­ó gx{½‰3"ð¬JÑyµºQ)¨ê¬¼;=jí¼ÛoÒ5X,èæÓ»øüêÄ£|z¥WÂbGrõ8ohÐůÎx4R§“Õ9ÞõLÇ“X ¸zœ‘gtxi˜ó}|¦ÛxC…xÂ5U¨â@g\žei«³õ¬ÎÊ™õs¦Îæ(ÏÄWûÙÝ8Ytè2IgĦß^d茴BY.èÑN9ÇJJáN=÷ñ[—;Ÿ'ÝNî÷ˆ}si J&ç u[ÆŠJ;ñ³›¬¨ÔJŽ µ‚ú£1vÔ ªuç UäëT *`ã:ð6É·çý¾íúq!Þó´AÄgyE=!¸^ñYÆÂŸk;º(`­£‡Ëp…{jK¼¸©\é>í×r¤ÇI|3JNT Š;L ç_åµ`þ]®çZžRA×2²ÊÞÃwåŠoòjul®ø&o¨³„§õ• ݼÉï1 •‚¢r#¯Ú¤Óµž<¹Ó½G;T ªõZ/T ,–k½wÝ<÷×JªÀÌ»± ôHqÊ=ç‚R‰U[ê• Ý$(ù~Œ±,ƒ  @<Ý|eO) ·ö+~'Ú¼2Öõ~¡R÷sáWg’ëý¤@¥›G¸ë|p„ëùRîøÝ†~X“^Y¯ÇŸk¥7ðu­yü‰ƒÊBÉöx­Ò+>ÇÜÝ0— Äǧ”÷ëËÜÐM‰‚B;Ê=ñ!Š#õá· êÂæËtòÓ¥^ºXÖu/<ÀÕÌŸkªjÔ_®íDÜ»ÓÉÇp/<4.ǽ8û0ŸqïýòÉ5ˆ¸vDÆÍ÷Þ=JÎBÄ=s"îÅ™DQ2À½û}Œ¯ÛqïWn–LîÝ‘üsqÜ{îMY÷Ÿ…©ˆ{qÔctqodO2Ø^>ib¹„¥ñ.3g#Þ ƒËÅ~À{yº ¼·Þ@’Äú"¿åĽ5Ð2¤½-žI‚p/¶ ÷™€G.âÞ6ä±.ÜÛck&”÷ŽØ0Ù/Xi?õ ÷޽ÎÁĽcåäÀzGx¨q*˜ÿ1XïW¨ @H&ÅÞ Ü&…ãz±åðpJÔ;·:ûõ¦I´D½8T“2ˆzç¹h.À¤8Só^“ôÂ9#ô®H¿‹^zïWI¿!ôÎКüE  Ð1A/2R âaP’ MÒ »·à¤·î56Io)\¤Éì˜tǧZôbs€ôîø AX‡}â}yé½piãÝ?¤ÂJ^‚^•Žè]AÉX^@ q½UxÞ¨ÙQƒ¨P IµAšœ>o;‹œ×äAЋ=•/ A/öÒ¬@ÇLR^ºü^W[}Q^•ò,ÌÛÈ#Ìë’«ÅyñÁ$6‘RëŒOÌëCPa^U°æÙI›˜×_ò¼½~‡ç=Ú_ˆyqX¡€”Wgˆ¢¼KÎŽ”w^¢aÞ{•`Œ˜—GŸßòT‘¹ /Š™O™õž òžwã?'ÈëâÊ€¼Å4Ù 5¨úºyª\Œ7ô™/\tQ@¼`’ƒÜEij6D¼ðmeh¼Å}Uˆ÷ìÈgfØD¾ý]Pš‰|áæ-Ëo¿Ÿä‹÷—ÈÀ£~AL/ªè\Bæ;"÷Ðw¤ƒþïÍ|Ç¢Ÿá‰|Ç»sɶw¼”$à¥ã.3g"ßÿò‡bÒ„|GÔH›ïˆ/2R ©ÀÜÄ[Gä‹Ýž†d"_ÐÖ=!_ ÎÃ6‘Ï8›Èw®S…@I^ÈË lò?5!_|‹xû‰|GÜ8öJ ÂÆÙAƒ3‚IV ¦¸˜G`2ßž“óå7 æ³_$È|¶‰}纗Í0 )V@Aî;"„#ƒûŽ÷µ¤±„Üw®[Íܪ=÷+÷q^c`ÓNÄ÷ÙtÈ},pð*pß»ÏÊ>Ü÷¾Ó²Ü\¥þ4Ål× ûb*ØwnKYÏ€}ñ[_Abß¶< jþÛÄ}çZðNî WC¾侘rß¿O‘ ¯h­~©Âû-äûFî;ã=÷Îàš×@Mç^$?óÔ ù½{‡n.É/4’@‡Vœà—§ 64y7¿è†lÜwÆI•dî;㌠ˆ­ “#öÅËP¦¼÷éù™¨/h~WH}çΟŽ}qoeÈãü÷­Œ}œ?Š„¾¸Šï6¡Ïn\B_èLNóõË%æ‹7•?u“ùÎ𜼆Aê/ÅLÌC=´‚ù|,0_üLHÙÏG§ ó½ß?²’ùÎøÕ“Tæ‹õ\eÌ[à´yùll2ß»]ë\Mì;ãwönЍ[ÚtÈ}±+ÑÜçcûÎÜ¿oì;#• ›¤ ›< ~ñèæ-?”«~¹Ò2ðë—Pà*±Î?Œðšâ7WNŸØ×ï…°/øšì{ïkŠ?Á|硘z0‚£~ò)ð0Mä«çPħ‰{¡É=özcîÕ%œv?d½~‰Äz1Ï}b=ˆ¬÷~×Ëþ–“ï瘬þ•ÇÄz~ 8)fÃ_Èz1@½X•c2ëõÝ"éµc˜HÏgJŠ÷ƒ¿]ôìá"éÙýIÒÓÒóÎSIa„yç±Â‘Lib^<æ4oóÞ3BæE·bÞ{~ÐËqJš.1ç” Ü&ù9 ó¤B2ž CÆ §vþÊ@Ƴ烌gO/ÞwQïL_XHÀx>0Þ{pQ2žÝ%9†?4üYA'rÝ–eçšëbeÖÃÁ.üÏB½v‘RÉÌDv@vNd×åšþ©ïf|MTÛYhwꇷF»r¹Ú…}•l·–›‹ðî¥S™î„w—N°Â»GésÄw[$˜ ª‰ïÎÂDò]€&¯àÅ>±QBÀ«„vxçVF6Þ£TB¼8úP|Ú˺7pÄ^²æEy.J躕©b•!‘hñþlBcÞ¶ÔEÀ»Hù (¤=¯OêÄ»3ý‡!­:vÉ¢;<¡kx}ÎÉ¢¸V²èõiC½÷*»dÑ»ž7Ê¢·~øn¶³®,zg-é.6“e»k­Ÿè‰w1c"­ak³[ôâ¿iлõk’èî ¨ù0èš„âdÑ‹ÐÖe¶è­Ê!X½U9o„w±ä‹œ9aÑ»ëÑ'Þ…š«¹n†l5¼ Xf‹O´d»  @Êœ÷è 'ÛÅ.&¥=o«ßOÈvÖÙî> Èv1™k¶çY?`»(åÎ:’íÚOˆ6½½öÙôâ'$Ž ¶‹["Û¢\7ËÿO6½p–K\7sƒÿ½Ñ.ó¹€Fá^´Oh¿‹MdgfM’]!àk‹^Æ™ào)p Òí±±w÷û%’c)mzëáÉvÌŸEÈvíö&¸3OnõÌç’ž›µrÜõËqs¯Ÿà¸¿ÈÐEôKÙô¶ú-Šl7Ž\,«Þ>ä:)¿Íö•¤QÏ<0vá…KX*¿Í³Ìs`£öc+£ž¼µ„váÀÌ ~›ñÃÉä¸þ\l@“Þ~”£$h´2éEUù†<›¶ îâ“K«6éΜÜå¸?%Ó\'ÏSùL•I/ f¢;{bá¸ÙnÐ2éÕZ•IOFtwÝ\&ºk›” zÛYΜ€»~$Ê ×Îd„» áiP½ \OåèÜ®›t,Ms˜ÙËdÍÛËÊ&k^ cŽ›rÊ”5OÖÙ2è•¥ìyï¾xM`×îµå·yïÕ1 zuOÊ W†jùmÖ)®›m“I/n8 Œ&½{-&ÙE8ÏÚ$»0ûÁeÒ ï™Ùw3Þõ‰íÚ¢|7Ÿµ$`;»'2éÅgÇð.´–Y-ÍañSÏlÒ{_/9fÒ¤÷,&½GV7^ÅÍž›ò(ÇÍûâ³+¿ÍÈÌËNiÍ‹ÔOlCÇÍs|^wÇÍ &(cÞz”S&ýûŽðlºrÜŒC¯¢1¯ À$¼è‡?]Èq3"Ø3U(oûòÜÊò^®›—þDÜʳN~›\YYñâ×F¶çäÂÊis(t¨œ6¯M6NYñ§›:àÝsŸziä´)WŽrÚì×SF¼6hʈ׫"#^¯J^¼üHF¼6;^RaÓddÄ WñÉk3Œô‚@ñÚDLÀ‹ïœJé¶ÙFF^˜áO9rˆŸ4ÄÔþõâM„=ÔÝu#žyeö–ígb½8¡weWž@ ^œ­®ÅQ/NEë`¿‰z‘Ñäd–BúmF‘ôÛQ/"Šv è¶yªc‘^lAü;I¯“Šô:¢Ü6#1ÜDza½.wÛŒ[úˆâ@zÇ»é­á>ßd= <–ï9Ëv&;^õCØ ¥Öö*üH°g¡È„½øÝdLAz×¢zòÚXÎØ›ç0½0¸N©ÃY!ƒ2å…Ïõ§fe’°ly‡ræ–çV?_ ÷*ÆG¸wªˆ Ü‹]D¾¡€¥xPÖɃ3lOòòLÎÆ™ãô:ˆ†¸wÇoÓ8º÷"Â_ñsÐ!’¾Ñ À®X›¼<åÁ)OZß?+NÀ·zl|6ÎŽ¡B>ò”€—òÀçœ×Sž–|<š ùô㈈/ª[rv«¢ fj/[^ì “-/Òˆ]³gù*òu$!‘Ï{¦ •€Æ¼§@^œOÙ„|áèNx#òu°¡Âõòœû{_gñ]›BXʉóÝAÕ†ÌT%à‹ß[ç`½Ø ±z Ö ¬ -«ÿVIà{**SÑzKÙIdÑ‹…×ø":…d¾ýºô ‘ù¢Ï:ûpž’XÔ7Ê”ÈT?s‰ú"œƒO9©ïk CäB‡xãùtûÞs…¬mľ÷>)‚äT?æûùb3–“§¬zeË•ç«ö>3_+@æëßûÄ|ˆÁàA…ë… 7CäÖüuuÕ£)ô»Ç‡e/<™Ïɲ÷„ë* v«ˆ‘_D–Üä eÆ£ÿæµÕPB¿»¬iĦÊÊ ô;2UóïM~Gfàû]àU}½Gð»ô3sŸá#Ù5Œ•ìöªŸ½ù»Á/rŒ)^/þÃ]DÞ›ýDø=“÷fDIl²ì}Vq*kÞ;ÆdÍ»i/ßu]’¤1/Þ¢…±zIx„²žŒŸKÂ{aãäO”$¼pØ}ÔŒykXBy±Ä ›Œy[¬Åä§¹-u>"âEq]ù]â…àå‘yyXó¡œQŒ7'b)ã©ly²F³H}^ž‰ðâ\ų /ž]¢(ËUÁ*´åEsQ3±Ô <3÷ð,4Ÿ„w]•f„fk Í‹Àª94¯ƒDxö“4 ¯‚Ž+K0 MlP¡£™+Kü¤11žEz$ãÅOœ0¯%ãu‚ "Þ”âEÖb×ÿéìüVì¶0~Ÿ§èåžB[²-é2…JSBIž ¥”B¶ „–>~ýi¾ùçÝ%l¯’󭬣ñ‘mý<š"vü–„xþLÏ·V["É"âõ™Eõ£^qšðð hOÂë}·>!¼°Æ#áyœÏÞÑàyù·æ%¥aA\DO|‡KMjå]a àáÔJHxˆÊP,ÀŨýN<Âý/¥aA`ë’¶jöÑõÔ‘ðüœÞ¼¡6i ŠXEB²%<_v)á…ñ’ðÆfé:ˆxˆå OU¯[º¡‰xøMö”ˆ)×GB¼0^"žï´WÆç=ldÆZqEol¦JÆ}³À>A$¤ï)FOíY0/Ì4Á¼Q/iƒÿþÄ<$‰×ø@a$œ«%añ\ÏóÆaqŸŠyçï[u§Ø€[Kré¡GMqz8;ôJ’óðØWE8e¶Éyc1X¤ ðS²m‹X)œcr^˜[ä<$ðåMA9ÏGLÎCÎZÔkæG%çͶ7’ó0–6lâìèQ“ó†mÖ çùjA98å3ÚàóœÎ9o–  BÎ ýçù²Î"õº½%çá^ä<¬¥ù(ÓH=,ãè蛜7l/;9ë’’8otÛž¥‘z{ØÇ)64[Ó±‡H˜’{aeO΋m©‡˜»”“× Wz½€q½±«³’ ‡ÌZ ôÂJŸ ççFI/Dáô|V(éùuå¤çß%¤‡…’ºé­çk=’^ˆé"éa¶Çm›¸ª”ã„ôŒCIz>C•ôÂx5^o×Dn¯‡¸Ð„z臻UõK„G‘”Âh¯×4ÞÂâõü“õü9Äx½Ýø–¬wݼfY3Ky‘ñz¡Æëù¹Óx=»ãëµÍxPQiSÄ%ëá®®G1^Ïã¹4^¯J¼žÝ{õÐ!*ÙÓÖâõüzÑx½s4 wtñ5MžfñzEì>jñzÍP^ãõºaX¼^³]į‡b ÷ÂŒUÜÓÄ®¯ç£Ñx=±ÆëöRF=}pw&ÞÃŒä,PÞë¾Ù“6øu§®¾®5°”÷ðì¬)? Úp„¯çׇŸC¬ÆëÙ*Í\}n•Æë–KJ]}àD¶a¼ž=cj\nªÖx=ÿ.uõéU+8=Cz9üNrnBb@^(@£Î¼z˜»Or° ¬éI/Ô7×,H+²FÒ;§…Ö“#éaÓh×<-“ô¼œ=Auõ°­(_Í/& Enb@&#…âöä¼PNžœ—”C Akùxb„M»áøƒ2 z…ò¾XR^0zR^jQÆ}ª8NÊ •ÌIy©Í.… ­R8)/Ô'å·,)/”ç&æ…ZæÄ¼¤LF ¥ª‰y^ú}R^üX¥”µU?'ä%Å,0…XlR^˜h¤¼¤LÊ‹gB(/)´à0o¥EK"óB±í‰y¡r1/T7#æ%åØyõ茭´a1ϲ€^R&&ÅïЃ²¤|›xÚ®V)±õ9O¶ÚóçÓþs— —” zI™ —± âÅyŒÉƒrÄ<•'B8/+RÿnÒV‘ú?¡M•ú?¡ Lð¢s“óðyßâ¶Í¤4©ÿƒ­\1$/µRÿûâbÊMLÞÁÈyYTzÊÅâ·Ob^ürÁ¼ØdZàSæ >­„ò’Òëeê åE „òâx…ò²¢è4o´ (“0ºº'å%eR^RΩ‘>ÓËÜEÊKÊ(E(JÓÝ“«Tÿ‰Ê`N0SŠTÿ ŠØ`E yé«v)œ:¤øOhÓ¶ÔI—Ú?V—Œ•A ‚².-ŠÈŽñ 0悈›˜Ö„XMD^RšÖD,ðÒçQø;±_^¨ÇHÂKmhAh3é+3f|#á§è\˜GO”J¦ƒGº+½™ Ö³Ù`J/TvÝ&:Ò¯@ µ IxYü]L)V™Rëy“ŒtvIx©Í!•B›Vï{îÙl0eäñðÒçu¡MÚ«^RJ¿¯Y1 L1 ¬ç}¿*‡TÍ)–Á³UšdMzÉ“€•z1€—þ>á(Ü6xI™€—” xIyd@¥Aiõªôr±I/˜-|…iAø(5\(ý2ñîb“M*þ¸°KÁ©÷c•KIvIáàƒ2Ö‹"d:°‹Âš?rô.Øà­Ïí¸*û~_³rl4È”Vi‘vÜKž`»^wG.ËU˜ ,±×˜%)åÒb]Rÿx4~!º¤´z±Hˆ.)c½üFÍLpeðåQÙ‰¾M¯\—ºßÝ îÉåî­WùñönЭowïõÏ߸öåooú9#Á®]Ü©?¼}õáÛÿÕ÷oŸnXŒ>îþòƒþA l0e$æUëßò½vóçM{ùÃý=÷çCÅ63ïäá󳋸”UoT{{ péÇñÄùøù4Cšý”úxnP_ù&þ燖ëmm~&ÞÝàð;Ÿ<è=}´Sã'éWïôß/7ûîá¶b¯Êº_ ¤àÁ‚bÛ9Ä#ÿp*ÈñÙMyA Xö5kð5ô¥ÊË’ iwHê~Ä¡©òõ8Víb.èÒˆ¨¼l§´v‡àË–FDåiÿ»†GTO£ ’_âhó²L?QhNÍyõä{z endstream endobj 6 0 obj 209410 endobj 4 0 obj <> /Contents 5 0 R >> endobj 3 0 obj << /Type /Pages /Kids [ 4 0 R ] /Count 1 >> endobj 1 0 obj <> endobj 8 0 obj <> endobj 7 0 obj <> endobj 9 0 obj <>stream 2020-10-09T14:31:29-05:00 2020-10-09T14:31:29-05:00 GL2PS 1.3.9, (C) 1999-2015 C. Geuzaine gl2ps_renderer figureOctave endstream endobj 2 0 obj <>endobj xref 0 10 0000000000 65535 f 0000209960 00000 n 0000211473 00000 n 0000209901 00000 n 0000209768 00000 n 0000000266 00000 n 0000209746 00000 n 0000210053 00000 n 0000210024 00000 n 0000210117 00000 n trailer << /Size 10 /Root 1 0 R /Info 2 0 R /ID [] >> startxref 211693 %%EOF blis-0.9.0/docs/graphs/sup/dgemm_ccc_zen2_nt1.png000066400000000000000000012634521422157504600216460ustar00rootroot00000000000000‰PNG  IHDR¬táÂgAMA± üa cHRMz&€„ú€èu0ê`:˜pœºQ<bKGDÿÿÿ ½§“ pHYsNNÆÊ/¥tIMEä !0Ÿœy=zTXtRaw profile type xmpH‰ÍVI’Û0 ¼óy €€ôY$o©Ê1ÏO”mylO2UsˆTÚHÝX©ôûç¯ôG¡%'ÞyØbY‹²^´šPVÒª¦«vnd}\.—A†ñUÅGªq•ÆYšeaÈ.º&Yl3,¬l›ô*Š'2cîys0‰‡ f‹ËÔT¡z7<%c K‘p%ÙE‰®*lá ­Íùj¡ìߺk7ö9ç¨%]qx›7ñ0æ®c—0k‘V3ù÷À¹ƒýêîHLÔyÅU¨qa¦ Æ–Pi:ð~¡ŒùÎ c'Oå üü˜N$ç¤]LpfÞÀkXÔ BÔC±Ñèê'Þ2È 0£M%x²!Vnš-p&0m^ѵ.Ïp)„û)&i0´ÑðŽ “²{ìÑ(‘"|¯îÁ„íÀ< ’@÷(âxŒQ~m¾öôŽÏ\r0â#†ùp±Ã«F¹â„¯,ˆ”L('ˆ–G´ÂîàOŒKpì׌‹¬ú’³Bxp·gz(Ú¤¹q ¡¶‚[qFäÙqOJ¿Ã¤*xÞ˜ñÜ0»Æ8j÷Ì{@Ý”¦³Ö©tVØ!â¨sæ.ñ 6}÷¥Ò+lú ‚¨G9r‡/w¦š´|¤×%bL‹0­>zJKA³ { EQ4¨ˆ˜ÇÅÌל]&½Kù™Ÿ—Å9qÒ?eÒ@šë‹Ò¸&Oú[ö@a»6¹›Bç6À¬zÏòn!èÙÑÎÁ¦Fkßà:cft1\èÐø&^¼Ù`¼À¸ÆI®HµðgÃ~¬ÀU¹zÃÿ¼¦Þ•Tzç™PÿÜ-3äI÷{§t9Ük›¥pÜôÍÑúCÙ꾨yØçŽaÞPv0ãH…`˜n'Jr.õI\{”ÃÝÄâ{ØyÄ•]íHñYzN÷N-Óp?:v]d8xp‘’]cSôË÷p²6Ïü=áÌl}æ2}ò‘³9£‡Ä?S¯ÞHËGcPƒžC^¶z§^s¸«¸rx†;1†¡é]}”Ænz}úðlÙh ßr~“¢¼ýoŒ hþ=ýüEÒEŠÚüoKœXt¤cÎcaNvPÏR¹7€IDATxÚì½|WyïÿvÇvlËʼníc3Jp;—àQ(@€Î‚C(´áŽL˯¸Mv/ôÒÖí.¥Ð6\Ê.U ¹´Üjï ¿z/Ò@.P’4…†AããüÒ`£ÛÄÑØrÛ±c}ÿ˜93³«]ý–v%=o½ö¥ÝùqæÌ™ÙgÏœÏyžgÞààà ‚ ‚ ‚ ‚ ‚ ‚ ‚ àœZW@AAAAAA„™‚ ‚ ‚ ‚ ‚ ‚ ‚ LAAAAAAA˜0"< ‚ ‚ ‚ ‚ ‚ ‚ ‚0aDxAAAAAAaˆð(‚ ‚ ‚ ‚ ‚ ‚ „áQAAAAAA„ #£ ‚ ‚ ‚ ‚ ‚ ‚ F„GAAAAAAA&Œ‚ ‚ ‚ ‚ ‚ ‚ ‚ L˜Y%<ú¾ã8µ®†0‰ø¾ëº“ZÞTÞ#Žãàû~MŽ=Qê½~sõ\„‰ãº.žç•,›Ê{d8;0ÕÇž(õ\·¹|.ÂÔ0ž{d,}éÔ³é\„‰3Y}‚¹` ê¹nr>Ô~¬`²ìÀxŽ=ÔsÝæò¹µåý3¬N½×o®ž‹05Șá$ÕmpÑÕÕ58ËNiÎÒßß?hYÖ 0 †1ØÓÓ3ár§ú»ººjrì‰Rïõ›«ç"ŒŸžžžA]×#;bšæ`ÿàààÔÞ#ÃÙ©>öD©çºÍås¦†±Þ#ÙlvÐ4ÍQo/}‚ú`6‹0~&³O0WlA=×MÎgnSc“iÆzì馞ë6—Ïe®3Q;P­_ c†Õ©÷úÍÕs¦3œœºÍ*GaöËåð<þþ~ÑuB¡Pëj ‚0ƒhmmŲ,éïïÛ"‚0VÇ‘~ˆ Ì`&«O ¶@jO­Ç ÄB홨±A„©ç¼ZW`¢‹E<ÏCÓ4 èº^×uLÓÄqÒé4t•{¨eY%ûçr9²Ù,Åbß÷1 ˲JŽ—Ífǽýpär9òù|IÝUG³~´mN§Ñu}ÔëGÚw¸smûø¾O±X¤§§MÓ¢óMxž‡ã8X–uÁtÚ‚ñÚä¹+&ãù`¦÷ †këä:éTn3¨Ïçƒ‘Æ &«O ŽUn &Ë$Û«ž¤O }‚JmõÙ'˜è˜!Œ¾_ c†sÃLטáx¶3ÿóÁDú2f8z;0£=›››£)ŽãÐÚÚ:¤‘U#ضMkk+¶mP(¢í}ß§¹¹¹äGJ­÷}?ê\¦R©è‡¨P(”̆ëöÃQ(Èd2ÑÅÏårCŽ5ÜúáÈd2Q›xžGsssI<óáÖ´ïHç4ÚöQËÔ¿ã8hšVrÃמçQ,ijjŠŽ—J¥†´‘Z® ÙXö ÃÝŸ¾ïÓÔÔýpÙ¶M*•u[&q'º¯S©TÉúÖÖÖ!÷uµ}“qîÓÍpm=œPm2Y¶`2í€Ú¾¶`"vb4ç4Ú6Í÷q¸6Ð4­äá!ù#™¤ÜL¦€ê÷çTÙ˜¸-˜mv&f jÙ'PÛW»ÏkÕ'Íú‘Îi²lÁTõ ’ç9–‡¥JÔ¢OÃÛ‚¹Ø'y>¨ÄLx>¨UŸ ¼¦ÊLĨsO2™Ï3ÑÀÔ=ÌÖ>ÌŒçƒ‘Æ &£O ®{%[0vêïù@úÒ'PÌ„>ÁDÇ atý3œ¶`:Ç Ç³ýpÈ˜áøŸ&Ò'1Ã1ØZdž/íí탚¦ öööFËT|ïÁÁÁÁÞÞÞA d½®ëƒ¦iFë’ñ¿Uy `°½½=úlÆ`:Ž>—Çôëöà f³Ù’º•k¸õÕèééÒ&¦iFe ·~¤}GsN£mŸÎÎÎ(ƺ®ëƒº®jšVr½†ko8ŸÏ—¬ÿßÿûƒÀ`ÿ:Œ´¯Ê3Òyvuux–ÇDîïïîÍÑ#I²íÊËÈf³ƒ–ejßáÎ}4õªõõpv`pppÒmÁdÚUÞtÛ‚‰Ø‰ÑžÓhÛh4ßÇ‘l¦i‘ Ñu}H>§J¶`²ì€Ú¯Úý9Uv@]“ñØ‚Ùh'l jÙ'PåU»ÏkÑ'ÍúÑœÓdÙ‚©ê¨m Ã÷u«eŸ@]“j¶`®õ åù 3åù V}‚dYSi &bÔ1’LÆóÁLµªžSõ|0ûƒƒ3çù`¤±‚ñö ’¹ÝªÙ‚ɰªœz{>>A€ô fFŸ`¢c†ƒƒÕû#Ù3œ]¶`ºÇ dzýpÈ˜áøŸ&Ò'1ÃÑÛëñ¨Üâ“3R’mYoY¨´º®ãû~ä.­>'g¼$÷Õ4mDWÖ±n?IÕJ³éFZ_‰JmÒÕÕÍ nýHûŽ†Ñ¶OröRoo/½½½¤Óé!ªþHmtMW÷Æã?Í–P÷Ähö­Ž©#ÝŸjy&“‰fguuuMxæ¤*CÍDpgÌ!`*ûhg¦Ô‚áÚz8;Sc &ÓÀôÛ‚‰Ø‰Ñ2Ö6éûX© |ß'—Ëaš&ííí´··£iÚY8ÃÙ‚‰Úþþœ*; ®ÉDlÁl²09¶ –}þ»>Ý}‚Ѭ “i ¦¢Oày…BöööQŸS%jÕ'±Ézƒ<Tb¦<(jÑ'˜[ v`r™êçƒÙÖ'¨Ö.õø|0š±‚ñô ’v¤’-˜,; Ê[0õHŸ`öö &:f8š~ŒVg6Ù‚ZŒŽgûá1Ãñ=Œv_3}›W²36Çcµð8ŠáËó¼’X´Š™—z¶cš&…B¡Ä(e³Y …ŽãŒû:% •a˜¦I&“¡··wLûކ‘îO]×éêêŠÜø}ß'NOøAF…PFk¢µã9÷éf¸¶ÉhŠ-˜™ŒæžT1Ð;;;£eº®ÓÜÜ\ò9[0žïÂp÷çTÙ˜|[0“íˆ-˜­Lä¾MŸ X,¢i¶mcÛ6®ëây¹\nLaÖjÕ'±åÈóÁìc:úÓa ÄL.ò|0{i¬`<”ßÓ•lÁdÙ[0]HŸ`ö2Ñ1Ãáú¯}ík3 3ÙHŸ`v2Yã c†ãm7ÅŒu]¢"' †¦iU ˆa‘JœÜ×u݊ɦgåmRž\´ÚúÑì;Y w³å‹ ¯ª÷Éú···ãû>¶mI˜:Ò¾£a¤ûS%ŒU³«\×%•JaƸÛÓ¶mŠÅ"½½½‘ÑÊårcžm1ÑsŸn†këáìˆ-H2–ïútÙ‚d]ÇzO&÷Q¨ïErÎp¶`2¾ ÃÝŸSa`rlÁl² ¶ ý®Ï[0š}«ÙÉz ¬EŸÄ$ÏA!Ï•™ ÏɺNwŸ`:lØÉEžÆÇLx>˜Œ±‚‘îéJ¶`2™ÅLÒ'3¡O0Q;0\¿ààÁƒ€Œ޶ýfº->AufBŸ Yש'3œh›ÏØP«–e•$¶,Ÿ`YV”dX­WI2MÓ,ù q²ÑÙL:Ò&™L&º9†[?Ò¾“‰aèº^r=s¹º®É°—'“Õ4-[¶DËTòéB¡0ĸҾcyØéþLÎVÆ<» y’ÇÐ4­$¬T¥YŸ•ö­vîªÝëy6Ïpm=œ±ãù®O§-PŒçûX~í‡Û·š-˜¨Põ¨vN…PŸ'j f“PëÅ”2ÑïúL±Ãí;RŸÀ4Mòù|ôRý“|>?&φZô Ôç‘lÁ\ê¨õò|PÊLy>PÔ¢O0¶`¢v¦îù`¦Ù‘ÚZú•™)Ï“1V0;Rn &Ë@ý>HŸ@ú3¥O0Q;0\¿@Æ ç–->AefJŸ@1Ùã2f8üþåç>œ˜±†aÍfimmÅ0ŒH9Oæ]hoo'•JašfÔYT›ÏçÉår‘ñð<¯dÃl¤R›hšV;¸Úz¥°WÛw²éìì$•JE×Ç÷ý1_ÏóhjjŠö¯äŠlY–e‘ÉdJÊ;Ã1Òý™N§±m›¦¦& ÈfËT‹Ÿ$NGåú¾ýPZ–E±X¤©© ]×£{^ÍdH§ÓU÷MÖÛuÝ’s¯÷ïÅpm=œÄŒã»>’™ Æó}4 #ª§ºß‡»Ÿ“¶@…]›¨Põ¨vN…Pç2[0Ûì ¶ éŒfýT0‘ïäDú¥}u>#Ù‚¹Ô'y>¨ÄLz>€éïL—-˜ˆ€©{>˜‰v`¤¶–>AefÒóÁDÇ FkGfš->ÁèÛ¤OP‰™Ô'˜ˆ®_P.ŽÈ˜áì¶Ò'¨ÌLêÀÔ€ŒŽ÷ù`Þààààä_òéÃó¼è&NÎlQ®Ïªu]§X,ây^Ç[m£­ÞãROv›AåÐAíißÉ$y}Ær,ÇqH¥R Fêüh¯ïDö®­ËïÏäñ€ªë«áº.¾ï£ëú–åõVÉÕvÃí[­Œ™@¥¶Hn7ÓÎy²Ú Æþ]Ÿ[0ßÇd=ke’õ¨ô]Ÿ ;,w¼¶`¶Ø[0š6ƒñ}×ëÝLÅ÷y¼Ô¢O,·’-˜K}çƒÑ´ÔçóA­úSÁTô `jŸf¢y>˜H›A}>(Æ3VPO}‚d{ÕËóô ¤OPÞfPŸ}ÅxÇ +ÕUÆ eÌPúÕÛ ê³OP«q3¬¼%f¼ðX ¥:÷ôôDŠq*•"›ÍN©Ê>IcUñÞ¬SYv=·I0YûNÇ9Ö[;ÎÄLnÙÓ}܉|—'ÂpÇ[03[0¹eO÷q§âw½Þαǘ‹Ì5[PËûh²]«>Átžc­Ž1טkv`ªË®ÇãVcªìˆØ‚™‰Ø‚É-»;ȘáìBìÀä–=ÝÇ­Õ8ŒŽžju$’®½*T‚r­%Õâæ&ïL€©,»;LÇ9Î…vœnÄLnÙõxÜéFlÁÌDlÁä–]ÇNÄÌ\æš-¨å}4îa±3“¹f¦ºìz<ît#¶`f"¶`rË®ÇãN'bf&b&·ìz<ît#¶ ”Yëñ(‚ ‚ ‚ ‚ ‚ ‚ ÂôqN­+ ‚ ‚ ‚ ‚ ‚ ‚ ÂÌG„GAAAAAAA&Œ‚ ‚ ‚ ‚ ‚ ‚ ‚ LAAAAAAA˜0"< ‚ ‚ ‚ ‚ ‚ ‚ ‚0aDxAAAAAAaˆð(‚ ‚ ‚ ‚ ‚ ‚ „9¯Ö˜>ó™ÏÐÝÝÍ’%Kj]•qsøða/^<£ÏáÙgŸå¹çžcåÊ•µ®Ê„Ø¿?ëÖ­«u5&ÄsÏ=Gggg­«1í´¶¶²xñâZWcB̆ûOìY}ðì³ÏÒÒÒÂm·ÝVëªL+³¡O0î?˜öl6œÃáÇù»¿û;6mÚTëªL+7ß|3/¾øb­«1­ÌÛ1VfÃ÷t¬ŒçZŸ{î¹Üyçµ®ú´²gÏþìÏþL¾s±£CžfîóÁx˜‹¶`6ŒEŒ‡±^ë¹:føº×½ŽK/½´ÖÕ˜³á{=¾§³¡ßñôÓO³zõjvîÜ9î2æ„ðøâ‹/rÛm·ÑÒÒR몌›¶¶6ZZZfô9twwÓÝÝÍŽ;j]• ±}ûvîºë®ZWcÂç0Y¼xñ¬¸v3ýÄžÕêæ³¡O0î?˜öl6œC[[ÇŽ«u5¦_|qÆ_»±2[lÇX™ ßÓ±2žk=ŸŽ;Æ›Þô&ùNÌÄþy>˜¹Ïãa.Ú‚Ù01Æz­çbŸàÔ©S3þ;1¾×³á{:úwÞy'ßýîw'T†„Z!´´´°víÚZWcB¬]»vF ÅÖ­[k]a3î?±g‚01fËý7ìÙl8aî0[lÇX™‹ßÓ¹z­…Ñ!߉¹Ã\¼ÖÂ虋÷Çl‹sñZ‡+VÔº f6\ëÙð= ýŽ‹.ºˆ5kÖL¨Œ9áñ8˜é7+_º™n8¶mÛVë*s˜Ùpÿ‰=„‰1[î¿Ù`ÏfÃ9s‡Ùb;ÆÊ\üžÎÕk-ŒùNÌæâµFÏ\¼?fÃXÄx˜‹×z<Ìä°˜ŠÙp­gÃ÷t6ô;&CxGAAAAAAA&Œ‚ ‚ ‚ ‚ ‚ ‚ ‚ LAAAAAAf9¶m׺ Â@„GA„:ïuAAAAA˜u …ZWA˜ˆð(‚PªÍ-r·Ö•AAAAaÖáºÃ<‹Åa?ÄX· ¾/î3…ój]Å®]»èèè²|ÇŽlÚ´)úÜÖÖFGGlݺ•;v°víÚZW_„I`.ÙУl¹[a™ Ì5æ’-¡:£±bav#}A@l 3ÛxxèèSR¾ëºÆèFǾ®ž‡mÛ¤Ó銟GSÏó†]ïû>¦iŽë\ …–eú|…ÚQ7<ò}}}lÚ´©äÕÐÐm£ ÇŽ;¸ë®»èëëãÖ[o­uÕA˜$f‹HÎJÎñI2ð ¼Ë©þÓ,s‡Ùb A˜#Ù±‚0û‘>  ¶@„™mŠáßT1RÎÆdhUåíXÉsÐq\×-'Ç“—¡mÛÃnoÛvIùc)Û÷}ŠÅ¢x=ÎêÆãq``€––vìØQu›]»v±mÛ6¶mÛÀwÜišìÚµ‹­[·ÖúA˜ ³Å¨Ÿ{ƒ@Ht“@,ibÑ1[¶¯ Xµ>A¨1³Å‚01F²baö#}A@l 3ßxø)¢£c2:/ÀrÇj¡S¿ÿÐC¼ñª«( d³Ùx[ËÂuݯCß÷¹å™gØöŸÿYr ÏópõÀS³X,R(hooÇ0M‚1LÐÂr¾²w/ÍÍCêò­GaÙ²e8ŽSRwÛ¶ÑuÓ4#AÒ0 M2>Z(ð}HÝ“ø¾¦iµ§n<ûúúJf(”³gÏúúúhii‰–­]»–M›6ñÈ#Ôºú‚ L³É(aÑK¼÷ DI/±dË$¿£ Ì.[ ÂøÎˆ„¹ô A±‚ Ì|;à3Œ 6ΨË*÷pܳzu$>&ó+æ<Ïó"±Bá±B˜Òoþàì»ð lM‹¶ÿ΃‚iây^ä9Y(p Æ5ÿóر(›çyظ‘¾‹/Rþ'œ›¿ó\Ïcω%碼*[[[I¥R‹Eì°ü¤¨Z,Ñu½¢Ç£:Ïæææ’õ™L&zŸôüª3YÑøêFx|ä‘GèîîfÆ lذ«¯¾º$nó±cÇJŒÀ²eËØ³gϰe?~Û¶+Æ„¹Dww7mmm>|¸ÖU©ÈTڀÇÓÖÖFww÷”ž‡K, ú” q~G=ñYý  ÂtÐÖÖ†mÛ?~¼ÖU©Ètô ÚÚÚj}š‚PSúúúhkkãÁ¬uUª2œ-˜hŸàèÑ£Q(&A˜ËtttÐÖÖÆÑ£Gk]•ŠLõóÁƒ>H[[}}}µ>UA¨)ò| Ï‚ c†S7fèVq3pq‡õ„¬Z^YŃï{¾ïãû>™L&Ø\·.ð"Ô4ÇÁ …H²Ù!eîzúéH`\õ™ÏD¹:÷\Î}Õ«( <³lù|Çq¢1ÎÿñØcØ Ñsþõ×s4•¾ðÜs‘èê:O.[–Å‹Xèè:.Ëå0 ƒL¡€ëº|ûäI¾}ò$ï¸ývšššÈårhšÆÕùHtî…BÛ¶ñ<Ã4immÅó¼H|- ‹E\×%—Ë‘Ëå"!r¬c°3yÌ6We¹WeÙ»ûú&¥OP7ÂãÀÀk×® n\ÇaÛ¶m|ü㟔/û‚ Ø´i›7o®õi BMY»v----,^¼¸ÖU©ÈTڀŋÓÒÒ2iI¥‡‹(®æ©bµ­EëQßgÂuEÄÛQ˜>ZZZØ´i ,¨uU*2}‚ò‡A˜k,[¶Œ––Ö¬YSëªTe*mÁÂ… iii‘çaγyófZZZX¸pa­«R‘©~>X³f ---,[¶¬Ö§*5Ežäù@dÌprÇ GCŽ\ÅÜ©TŠ\n¨\¤üõ|ßÄ7žô©çžÃq4M#—Ëž‹†ÁÿúêWYøW…ã8ضÍeø?ܳ‡¤ÿß}óçoÒiÜpŽãP(Xø¶·ñâUWño=ÆË>õ),+€ú­ð€ï¯X³½³“Ó×]ºÎûNœàϾó^úÀ;ÿöoyñª«À²h,@×ùòÁƒAM“-âË—\Â;n»ŸÿþïÓõ[¿Å‰… ùêOpàCâê|„B¡@:æç×_Ïþ+¢°¯™L†T*ÅéüGÇaã{ÞC±XŒ<4çÿÇ`Û6…b‘öövŠ^ õ¶†ç=š±XJ®’¾*‹zj,¸Êb_¦Êö¹pûLÙ~*I{áò¦Äö¹p{;,'YÇTxþªü\xž?^»–sÞüfžºüòQ´Nuê&Çãc=VòyÇŽtwwÓÑÑ1áÿóÏ?Ÿ+®¸‚M›6Õú4¡¦¬]»–µkײsçÎZW¥"Si–,Y2©.A sƒÀ0[ágõc¡~””°¨äw´Ã}ÒÆß"öz„é@}êÕ»a:ú2° Ìuhii™ò(a8[ ò¶Œ%< Â\G=#ÏÕç%< Â\Gžäù@dÌprÇ '‚S–ÃQñË£Gaùr\×òú¾–Å®;ïä× b…ùÛ¾ÿ}°,:÷\¿ë]8þ0¾ïsÉ'>ÁÀ£‹³çÔ)ŠW\A>ŸçÐаcûW¬ÀÐ4 ¶ÍÆü€½@ßõ×sŽaàËÿùŸÙN`õÃüw¬^Í‹÷݇ <ô\u󯾚WoÜÈÝ7²fï^ž»ürú—/gÑk_KÇٳܿnX'‡«VñðæÍü “ßçð•W•W²èZ¿ž ¯¾šÜ²e,Z¹’ŒmÓžÏc͹¼õ­¤»ºèü­ß‚¦&š››ÑóyÜ뮣ðOÿ„ÖÓƒ©ë`Y‘p—#‹í%ãõàÓ_ƒ?ÿó`¼¶=lw5fë…ÿÕØ¯Šr— ÿëáö…p›¤ŠO vá:¢Œžvxüt¸‚qäbx7±ÖÛñÁÓ‚:æÂuvâ¸)bñÑ v|1õóÂí|âè}*;æÎTŠæÝ»'t×Çc%ZZZ(YVÉ5ZEA˜½Ô³H†Tõ d¦I,6?F¸\ýP¨ ø ~IY‚ ”R϶@„é£Üˆ„¹‡ô A±‚ Ì;0$ÜjèUXηä+{÷D!LøÅ/8¹h=/{¦ib9ìd<·r%ï¸é&\૯`ÿe—ñHèåÞÚÚÊ9W_ \vo»ÿ~®ìîæŠcYì_±8†+]xÇÌ;z8yë­\<>°ö±ÇÀu9½v-lÜÈ­'O’kl$5opâÚkÙµt)ïzËÁ49µy3E‚±Òð–ï€ N ÒT™&F¨8qŜ󵯡¥Ó¤ ƒ•ßøŽirtÞ<Þ{ÿý ~êS,|ï{ixñEhoÇ×õÀËQÓ¢ã ò~l¬åÐ~Kð¹Hì%h OÛ(ïA•2K‰w¹ðÕLœVK-s‰¾bXF!\ÖL,fÂWsø¹3ÜW9¼dºjüxI°ŸòÜøÌóÏÐC0ÞÜ  ¨F¸½Ö±=<¶G ¡*ï'˜–¥.„Ç]»v±}ûö!Ë“IcÕŒƒòd°ÝÝÝÓê-ÂÔ0퀚ÑV3Q 6ÚJltˆg$g°dÃmOQŒ ¾Â\f&ÚA&Ÿ‘lØA˜ýHŸ@[ Âì¶åy]×]çd˜Qåk8~Þy|û ŸB­þç9¼ó“3g8qŬxË[oIå1irÒïüã?2ÿ?þƒ‡V¬`á‰õ[¿Å¥ûöñggÏâ{f,‹³Ë–ÑJ .^¼˜<±×áçÖ¬a^&Ã/-"ëû i˜„c¸…W½ø"ù°fX¶ <¾pâr”èxÙ¼ä_‚핚^·.8vL)†å¼ú¾À{RµesXÞ›ÿâ/ë=y@*§”,ÈØÖ)O :—O Þ«åí€ß W°ZÞ Ü±iýcÎíÄB¢®¿)ÌßÚä=øÿ® øÈ¾}Q²ãÖ¿ÕÛ þpIÆF¦.„ÇM›6E lÝÝÝìÚµ‹ë¯¿>Z¶mÛ6:::¢™ ;w¡¡dAf&3Õ(áQÅ÷NæoTÞŽY —sBY2)<šÑþ>.Æ(+³•™j A˜\Fc ÄÂìFú‚ €ØAf‡pG•M0öd¼?ô^³m;Ê÷8pÙet<ù$h¿9}€§—.<5°-+ •ðxïâÅœ^²Xÿä“ml Žgš´ ~Äi¢<â¨mÿ%<–ÃLÛ6ë|¼iò‘K/ÆAU¨Ñ·>÷&ðæsÎ!黩ÆCMàí\ÀÿyÅ+°€ß9}KÓH‡å|ûÃæ•Ë–ñ·ë×ó׋¡‡ûöoyè!2G¢ˆn½c¯±°Ùô}ðƒ¼ÿÔ©h9…òãc…ÛäÃý:ÿwÐ}Êë¯xëgàÉOÁøa¿ö5Ìp}ËᢟÅb]:,sÉÿ€Uß*;‡¾ÿc–ü_Ðn×Ip,Õö¾ë²óرèØ_øÂå<ýɽQýÔqðÁó‚öî ÷ýò—¿Ì¾}_ã3ŸùAÐ>™Lt/èžÇG.½”|xžüT>ø"¾çñÏŸúÅÆFZS)²@1—càƒäÞ{ïÐ=_9×®]Ëí·ßN[[,[¶Œ¾¾>n¹å¶nÝm·cÇnºé&n¼ñFèëëcÇŽÑÌAf.3Ѩ-*¦wšxv‹š¥Cøþ•8¬eE­bY.fô.s—™h A˜|Fc ÄÂìFú‚ €ØAf‡ð÷˜ëº·bW¿ð²þ~ W Çì$ΨÆ-Û Æ9_½b??psÍš ´hSó~ùK4ཫWG!G!ÄZƒijh‰²Bí”|>¨‡~þù¼ìüóq]¸ö% ¤b/@…WM ßùêWY¿d ŸºôRþ+”Œ¤v†Ÿ³‰}mÛf°³3:ŸŒï³úĉ¨\Çqh7M4ààÁƒÀjtô°"pô—‡À[ÅþäO8þÌ3üûßsÕ· ÿžØ!E±æH8þìy?ýéY®=/[JYÛ¶1M“L&C:æ•é4/¼°ß*rÏm·qîÛßÎßøF:;áÒKÑÚz º®£¥ÓÜzë_½ìÞýE<ï%¸®‹çyÜÿýüÅ_üétšçž{ݶÁ²°í° ß÷¸êª«¸ÿþûY¹r%­­­8ŽÃ-·ÜÂ’%K&tÏ×…ðÁŒ„믿>r‡V m“444p÷ÝwÓÝÝ ÀæÍ›ëÂp‚09Ì;Pþ#qLo‹8‘/?`êGg=çTËC+Â\f&ØA¦ž‘lØA˜ýHŸ@[ ÂÌ´jœ¯¿ÊòJø¾Ï¢E‹èß²…õõ¡i¦i’íê „GÃàùA×ùâ·¾Åâ+¯dÓ /ðàÂ…@œêÉ6†¢£¯T¢ÜÎ¥Kù7ÏÇ}—^E_SÞŽŠƒÞ’%¼}É’È[Ñ0 4-5ˆ#»‹ððÃïæã?Z2~ªôTˆ#ÅA HFp JŽ‹ŽA9.ÿû]ïB£t„5—ƒt:(<ŸØVÓ4\× ÂÏ‹<ûì|'hÎb±Hg(ÚþÃ?ü؃¦ŸU[9òU`/ŽD²3Âð­Ï?€þ°XD.“Áó<ÚÛÛI§u\75u]G×ur¹/¾˜æ§?]\'Ç êD©wb¡P Nãº.]tÝݽÜtÓ·øÒ—¾Äg?ûYÞóž/𕯼ŸK/µY²ä lÛ¦P(pÁ›9ï¼_áº.©ÔítuuQ,iooçĉüÏÿù?ùÔà ÅbÏóøÈG¾F.ÍÍ9Î?ÿ¼þõ¯ç_þå_hjʰlÙÞñŽGߣñR7Â#P’¯e8F³ 3“z·‚Â,ñ¹Êëh‡XJ¦ރ•˜Ïâà ‡>¾‚ Þm ÓÃhlØA˜ÝHŸ@[ Â̳EŠxxC„Ç9ttœ!ÑÏ<Ï Â¤>õ½ýý\yÛmèÏ=‡í†¡ZC‘láW3 ÐuÞxÁøAèêr°mDʇzÈòå/ä½ï] Bð=÷ìÚ±,Çq"AóóŸÿ>gϾ“L&‰Œ¹\]<,ÿñÿ‘3gΰyóf¾óï°lÙŸñ|"„î÷¾—ÿܶS§N±jÕ*Ž=Êð}Ÿ÷¾÷½<ýô·£|ñ‹_ä{ßûüàéììÞÏo~ó_¸öÚW000À‘#GøÆ7àúëÏã׿¾‚Šëº´´´P(8@ƒƒó°«½¦¦&2™ ë,àÿí|öŠ+øêƒò‰«8üÄ#?~|Ü÷½¢.r< ‚ Ì$ ÄžŒ*¼jÒ˱ü÷Ò ÿ’ØØÑ2õ?Èó(‚ ‚ ‚ ‚ ÂLÇÇg_ä²/S¨1Á£GŸ=«W³ïØ1_º”—¿üålúíߎGÅÕo~3§6oæÔD"áo<Ž…0‡cÒ»P9®>q‡×^r P96›òôýÀ[Qéyª,ÇP³+!†¿ü˾ŠmáVIsYIxÌå‚c$ñ<£G3,Y²6Ü&y vuÅ•Š×¾ö}Ü~û=¸®Koo/¿þõ¯yôÑÃÑ6_úÒ—(‹‘( ðÄOày^´|ñâwÍvbŽãËå8ï¼k8ÿü§°m›;3›×¯Ç·m¾þõ} 0ïèQî¹çlÛæo|#ÇŽ]ÍéÓ§ñ¼@5 ƒ§?ÿyR©›7oæ¿ù.\Hcc#¿úÕ¯þþ4 .dݺuÜöú×ó ]gá¼ýí§øÖ·¾E6›å/þâ/xñÅæÏŸÏécÿÉÁ_ü‚\.Ç;ÞñÞÿþ×°ëö{áØ÷éééaùòåܼt)Ÿý«¿ÏãòË/çù_,bÁ™¥X–Å׿þõÑÝäUáQaŒø@kø>‚ÀÃÃ`èÌ•@Zý÷ñ±±qÂŽ‡úŸ'3dFxZAAAA„™A¹3ÂÏ~ö3 Ìñ ë¿è"Ž_s ÿzíµ i\õàƒÁ*àþYü |o`Xpà¶~=PMEf3ˆ%t]ÇὫWGÛúþP¡/¨OœŸq4|úÓG¹é¦S£ÞþĉxÀ¡Jƒ0¤^¸j›¯ý{@à5h‡¹.S©@`ljj¢µµÛ¶yßûþ€k®Ù•ÓÐÐÀO~òR©·¾ï}Ѻ… rÞyÿ›üà3477GaI››S˜&ôõÝÇ…^H{{;?ýéOY·n§N½Ž;vðÎw¾“ãÿñܰ`O>ù àsñ}÷±sÛ6t]ç¿ÿ÷ÿÎö‹¿˜Ø¶ÍÞ½{yê?àgÎðîw¿›®®.¶ôöòµ|„E‹ñ–·¼ €+þ“ÿó;èÀ;}”W<ú('Oä+_ù –e‘N§Éfƒ`´+çñ§xüpÓ&zzzhooç=ïù çîù5.ðhÜwïZúù葯!h‡—ÿÞïñ¶‹.â׃/ã‚ 6óÖ·¾uB÷¸‚ #à{8º?Öê·X?àFbùDØ×߯. ­êãcbâáqŸ/Ò…cAAAAafQÉ¡@yè%½v?óLöSy6j§×®eùòåA)é4.¾ˆ…Åל>olh@68-O *?¢•X¦ë:×=öXÉr×…TªòyT$-+x•ÓÝ]Yt4ª„xÛ½{7ßúÖ!í£ÄHÏó¢p¨¾ï³víiV­ºÛ¶±,‹•çŸÏ·¿ý vîüù|MÓð<Ïþó|ò“;èééÁ4M–.]JooWX¶Ï¿¿ùÍ\{íµô÷÷ó±]Îàà ÷Ýw1›7oÆ4MLÓäÌ™3<öØiþéŸþïvtpùå—óGôG¼ô¥Aù/}éï’Ïç¹ù櫓±0X¹ò \»z57¯_a æŸ<Éz üë_ÿ5/?~œkŽçâW¿š– ‚ö‡¦i¤Óiؽí‚ShÏ<É#«VÅ÷ÀÁ¸çÄÛøÓsÿ.pSu].xÝëxáUo î›T†UaXØñ"£ ÂxPAy4&ãžk¸U…BŸ…Hhl¢‰"E <<:~å-,ñxAAAA„Y€‡G¡PàÀCÖ½pú4¹\Ž-[¶ B¥®wùr<`ÁóÏóʳg1:à­O=áºDšÃÈ9"[v¼WoØPqy9Ž+W>7d¹mWö„¼ä’X½ú_GÝ&«W/¤¿?È‚Y,illĶm<öíÛ‡ahš†ã8‹Ež~ú ßüæ7ñ<MÓXxÇ|âÿ€if±|Ÿöövr¹—_þïÿ)Î9çN¨žþÞñã466‘NÃòåËY¸gO>ù$ïxÇ^^|ñ×¼æ5œ:tˆ½_ù Ï<ó]xžW.YËÃúŸøÄ'xñÅQiÿæ¿}$]—ó.ºˆu»9|ø6Ö7c¼×¿úÕüõûÞGqà]<Þ5üëÉ“üïë¯à ÿôO¬ùÜç‚5Í(~­öüô†#äóÄËM“…hƒ/ Ï÷oEÏÃÿÁÃüú¿‹ã'îŒÝ»14¿_\r »wƒã`ì¿› «÷ÐwÉ%A9¦ †wj WÜ}7«*ܧcA„GA„ð!’]b/ÇÓáì$8V&:º¸‘g£‹K:”+säÐÐÈ“Ç ÅÊ^zɆ?õGñØF:º‚ ‚ ‚ ‚ ‚0 ððp]—½{÷røðá’u/ýëñ4‹®¹¦DPTŽïïîÆÐIQ Iñ“7Þ”Š‘ëà‚¡Q您ëÕ÷9zt^Åå¾?tÙáËùÕ¯¶A(TÕuƒc477ÓÚÚ­?xð$ëÖ­Ãu]2™ ?ÿØÇ‚P°¹çžÛÂ}]ŠÅ"ù|ž“'ñ¡-À÷}²Ù,o9÷\V¯^ Àå—_¹gf³Y^|ñ*¾øÅüýŸwÞÀGöí#µþ•‹àîÜÍÆ¸øâ‹ñ<ã¯àâ‹/æ…Çù̪U|yÍ^ÿúÅlhIöüÏËAî—™`¹çá.¼–s ÚïG/ ½³“ôÏ£'ï`YçªóéÝàºx?þ Þ©58©»iø_ÿ ‡y¼çΧñ­O¦+ðÍçƒêì~'-šÐý.£ B\JÅFõÞ'˜-ôZ|ÎÌB1³ G—)Ü0üªŽŽúGÚØdÉb„]-ü»‹…h‘G¤ ‚ ‚ ‚ ‚ õIŽ)Rr'Àòª¾ïsÁš 8~üxÉòÆÕ«yÉç>ǯ®¹†r ÐÚMsˆ·c%‘q$FσB¬²8©^•!ÈuëžàÔ© †,·,hoºýÓO¿”6à8N‰øxäȲÙl”—Ñ0 Nœ¸–ü34M£··—¥?Žeš¬Yó~.½ô¿‘N§iooÇ÷ý¨œ~tœ ÓóøÆm¯§½=ˆŠmƒï“ÏçáàAÜy4ªßîÆFŽí»0ø°t)Çöí#•J‘9ûçܼú_Ù°r%ïúîOÁ÷ñ4o}q{¬ãe«¯ÀöM,Ãà3«Váì»”|ã§yë±ï± ¥|Ÿ%k×òÙ½oG_p÷à%8O¬ƒbÿ;’ݶ+ægühÐàqcÚv †"¤ûÕ'Èù$ŽNÏrÜïMC¿úBŒÿx<¶~óÝØù^0MŠ{®%瘑ª›í„\oÿ¹xGp]¸l`€5‡Ç™?Ÿ'VsèÐÛKïå\ÐŽ>w—­+"< ‚ TÀ‡’®A2Ôª\‚Ëé„0ønԙȑ‹<]ÜHt Êõ±Ân‚½WŸ_A:ôªÔñð†tPAAAAA¨/<»,Íì³€kY<¿ñy/.õx< 457³wÍt`Á\õ丹*ý“ÆÈÞ•r3Ž•Ç?Sq¹méË™?~\×0wà>þqöîýwß½Û¶éêêÂu]RaRÉk.û 2™ ¶m³þ™gØzÑE8°€+Þz?‚išlØðG¼å-o¡S‰v†{Ï! p¾z$lt|ý/£ãÁ£FÊêñ—¿œ³ÏÎǸêEŒ­qbáBÞuÙeäóy¾zì# ,XÀùý†¿sýNñÆ]±ºêËûq1p[ é4îCç’긙ßýÃ^sëû`p0n4ÃM ÊM§·Ãƒ1×?Žsñïƒi¢ü=˜o[È ÑLúý§p¼¡®ªéà£å¬ZE6¼ýåñ²èäIH§éú“cÞ¼OÓ×wñ{Ænï§•Nöýfí„îAªPþûœœµ´|˜egÏ¢•¢ ¦™T*ÒÇ"T„Õò0©¾h_åìÝ{ªbٕ¬:ŽÃ¾}û"añcï~7ü¶·qàÀ‡‚V0M<Ï#“ÉN§ù×þ+?Ñ€išQ8ÔOúÓ@ –‘ËA¡@6›eÉãðI¿ˆ¦*kpð žî÷â“hnÆÙw)ÌŸGŠZ¨Ä®9ñk܇ÎŽëçXµŠ7,]Šåºœsê/9þ+_XŒ»ðÚ`{M£§áM´ç~‰÷ë…xg^„ŽC–ºÞŠW‘+hNã&]]¿çJ\ÝÂûõÂàDV¯F_sŠ\‡çUh?Ó ê¶ùÜ7éü«=ÁµNƒ{ñõø~â4,‹üg`šÁçt:ö@õVàb`{î%¿ë÷®½oçÀªUÁ½ñÿâùçWqâÄÂo×lô+í´æÐ(ïíʈð(‚Põ ~£=â{µ‰Ðª66&fjÕHÌAJ V$0ääĂ ‚ ‚ ‚ ‚ ÌzÏ9‡ó6ô•- „²£ãiOÆ•+W²íÒK«†TMJ­$0*Ê.µ]ùö*cùö‹|?m;H;¥Äªb±HSS¾ï£ë:¯zÕ«¸à‚½QÆÅ>ʽò'@ ¿¥ÓiÒé4¦iâû>ùÀoóþE_ÆuÝ@Lt–,Y@.ÝOò`ÆË“^ðErÞ¸\úþï“^sƹEž‡÷³ãhžCzí¿Â^.ÇS+WrÁ`hîžãïÞüfú—/‡b·ÿeÌ_» ÿä"¼/ý<æïQxàµØ/¼·wy vf³¸)òù@øSí¡D¾b1Xµó—¾„¾qAt½ …² ešÁ+$7ÿïi½óÍ„M‚ã”]çlM‹×Ü3\…¿j#­­àÏkŒ®ë«_}?\¸0¸/N.|º€0åfTë=A=/»lÿ„îwA*àBI†EÀ2)<*/G·ÄCÑÄ,„c¹ð8‚ ‚ ‚ ‚ ‚ Ô?~Éûr·6‡óV>\¶,3<~ʆKÞ¾f ïºì24qtÐq*{ B‰–¡R & £¢†¯X•œ?¿×½.ð|s]—L&ƒ—p‘ûæ7Æ R(xÉKþ‘?üà …B䕸–·¼ Ê?×#K}âÄ#5Î=÷U '‚ʆõqwÏ£xêýÁΞ¼4 gÍû¡¡!XžÏÇ'yèî¡5d.º;:¹þåËùί߆ëëøýÏóáÑ÷ñO/k®ÁÜÒx2®¾6j(m]P~ûÎs\ó8ý[ðý e)3#çÅÈ 11ÈlY±>Zr’.§6 ]²HiœÑõ)Ÿ›ÏUôýøºš&x'/!Ÿ'ze³ðÜs+ùçÆTx-\úûƒT“©‘G%À%—œä 1DxA¨€OjÕ'þáWx YÒÅ%9ððª :z‰ 9cÙVAAAA„éÇ G“Ž„%é“NœN76F‹Î{~#ç>}6”Óƒ ³j2v”€T)Ïc‰'^ˆò–;xð Eõ8z´™ûï;wîF×uÒé4žç¡ë.—_þM®¿þzÒé4MMM¤Óiþý;;øÜçÖ00p†a€ërùsÏEåùŸý" |ü†x×e—…mg²¼¿?u<¬S_ÕVJ C­ÒЈtMMà8xWÝHqïë°º>XošºwÕUÁçÆÆH@<°j‡…!DÃÿV­ÃÀÜxíeËÑ›éì w EÕ|zz µ5nSÓ Ú2t¦ŒÄE%êjZ³µ5X—Ï"_:M‰—aEV­RQy1ÍøøÕ„dõ_  é̼/É|æÏ¿˜Ã'®ˆö»,l¥í&½0ßô¦gÆqו"£ Â0¨ÄÐ:ÐQ0T7üóñqp"ÑÅ<Ë…Æ,Ù§¸… ‚ ‚ ‚ ‚ õ„;ÜÊ'—yç½ØÀ‚³gXH©g£ALŽªðåTÊÍhC½!«ašpÅ¿ŽÂ©|ç;ßàå/9ÅbÏóH¥Rìß¿Ÿ_ÿz5ýh†a`š&©TŠcÏÀË^¶%ÃÊt}øž ö,ÇaMw7 aÙ@¬˜µ·ãfŠäÈã<°(©jšP,b,ÜC>Þù—ÇÛ'•¸þþ¸}L^ñŠHƒLºy®[÷U²Y0t?Ü4sj,xö·í |iÒKSµ©òrT§§œÃÔÑõ0Íà°¶ˆz¹\°N…H­Dù5Ö´XX´íàØåÞ’É&Pë”'d’Ë.àé§ŸàòË¿É[ߺ²d?å5©i°aóLA†AÙzõCo{;*ÑQCÃÀˆÂ­*2¹l´ˆð(‚ ‚ ‚ ‚ 3R5Ðu‡“ co ΜáÜsÏ`¥‘Ö”–˜Ô˜l»ºðX.>*'Ár–-{È ¥LzzúùÅ/.¡³³Çqð}Ÿ-[náÕ¯¾Ó§ÿt:M{{;===<öØa`àU|ýëß ³³“®®.º¶d)®ý6.úEPp–´õóo>_vYT9&Kàf篸,VÕ–.E»àÖåêYWÎý (ÁúÆX‘ OÜ4ÏÉL&>!ëC«JC”† ÝþýïÂuA»úÒø^ÿGzK”jÑ4ƒ¢ … L©¢½=¨’çëÒé@¨´¬ø8–TÍ4£t@,ªe•ÂãÚvàÈ©öOŠŠ¡é{@i°å÷®—†Õݲ¥Ÿ#GŽÐÛ»œ·½íÚh[%TZVðÿê«'fDxA‘ )zx%9U®F½$/£$AAAAA˜}”çrô}§$Æ©^²uý¼kX®)—c5óäJç>Ä’ƒcuîÞ{É.¼çà&¼×½?r'ôÑpú·ÄõTžfžT«FáÐûKÝ}Å@œ‹0tõK§OD%šUk£ ªÆ‰«Û™<ûì||?(C¡ÀrÏP&Õq†æ[4Í@S­äijY¥õªä¹¨Î%ŽÌòò+‘Ì)YiyòóÅoࡇV°qã¦Aª çwLÎ^rq10"Á1Z5)4Ž5̪ ‚ ‚ ‚ ‚ 3—î7åG×ü € ¬`Õ¡Cp,b„c‡ óæEûœÄ•Çc%±JåL¢°ÇKàÚk¯`þügyöÙÒ~ûöíàŸ¸—C‡Q,I¥RlûîŸqÿs¯áÛß>I&“×eùòå|îskÈåÀí>5¤>ÚÚ%°eK <:~O/Þ%¯Å}¢ÿ‚5À˜N£ác^wšL¦T8<ø<_ª¦­_gÎ`š7£o£òlÌåSíŸÏǃ*äêw^}B šœwÞEtv‡i-kÛdÒièí­~}TˆÖJ匆T*‹+íSILíq5 öï_tòío¯]…&€‚ Uh'u‚ðª>>iÒ‘È(£ ‚ ‚ ‚ ‚ 𯳋p*Ï{î9øîY£±¥ œ9ƒ¬.&Îñ¨„´Ñày•=ì|¿²‡ä®]ŸgÑ¢“üìgáy¹\Žb±ÈÂ… Y³f/ðÚ“¬:p Êåxþ‚´46ò¿ÿò/ƒB\ï±ÓÁÛã/Ô­T*®ôÒ¥xk^,/ðO.Âö ¬‹þýâgƒ:iÚ7¿€õûóÑõàœs¹øœ:çÿP|¤%UÍkŽ“ýð)²ÙàP꼓¢«òZô¼ <%Æ…Q\éèXÏÒ¥»¢õ qùåçS--g:è¤ å ÙÓSê!™<~¥ååÞŠÃ ‘Ê[µÒ6ù|eá±Z¨Ýd¨VÀÁÁà5úмãG„GA„*h@襇‡‹‹Q"6&ß+ïljàM¸AAAAA¦‹0qÓ³K–pvAÊòÅ .`ùÙ@p\ý¯«£m—.]ÊË_†~nH”ãºÕ…¡r¯6o˜ADM Êimm–]yåm<÷ÜùìÛ÷=lÛ¦X,âº.==ƒœsÎ¥\ÓÜ ®‹¦i†AþºãK?ÉÆg:Xû†7DЦ׿pÜ·/P ƒl¬?XŠnqÆ-[0®zŽ!sàã‘>é]°ÛŽÅ1×-S7“¹í‚X\ºV¯Ž¼•0—ôlô¼ wb*—£ª¡ÊÞ¿ÿ\, Nœ8èQYcôŠÅÊ’º^Ýó0)$êzõ² £ºÀ8ܵ®„9ñaêqS—ÂãÀÀW_}5ÝÝÝCÖµµµqõÕW³aÃn½õVúúúj]]A¦€ZØÈ%Þ¤ fy¡èãG⢎^Z5~u"ˆð(1Ò'ªÛ±‚0w>  ¶@„úµgÂ4M/Îÿ9,:,lhàœs fÓÁM¬æÏŸŽ^u±n½õÖZWW„) vÀT~âdhôtB ôï5´oÇò‚ Lé‚•mØA˜[HŸ@[ Bí퀤*,¼Â²yË–pÝo®C ¥‰d׫æáXš5=¾ýí“d³YüpÙï¾æ5<¸ˆÏþqr¹ŽãðêûîcÖΞG£¿á¥q…® Îkf¿fP8ç#‘š×µú}ô_õ&ò7ܨ[–…÷wR(‡/¡è™% ¾ö4敇+Šdét ¸‹± X^ˆ®Û*Qi¤J5Í@`Lî§Žgðì³óŸ‹/žÏ¬!Žݱˆ‰Ã‰À£¡X¬N7Öu,L¤.SEÝ ;wî䨱c×íÚµ‹mÛ¶±mÛ6ZZZ¸ãŽ;سg»víªuµA˜DjeÊÃy«ß(/òdtpJ¼«…\aâHŸ °9‚0שf æŠAú‚ ˆ-¡ì@µ§ôg+,<÷\Þ³ñ=¤Óé 9,Tò‚ÔuX´è:x6 è:\uÕƒ<ôÐCضM*•¢X,òëP¹Ü°aù|+t\3>ú™ÇÑ7_$0ô}p]|ô—žõëñ–ü—à ¦Iêà—Èù$¹¸8Pì, í™'1wG¢ŸÝ½tM DAM×0®8årT!T5-ðT‚£iƫʗX,Æž‰J`T©%“â£Ú_y?–‡>=p`7ܰ‘ÿûodóæ5‹fI[ŽU—‰ +«>'¢âÎxêJxܳgÅb‘O|â×õõõÑÒÒ-[»v-›6mâ‘G©uÕA˜$êÁ¨ßñ¤ð¨:>~ô¾<Ôª “G=Ø‚Zãáac׺‚PSªÙ‚¹bA> b A¨W;àF® ’¾œy„Î ¦ibšæèicAyû%ñ}X¶l=¿ó;KhnnæÈOP,ÂC½ŠU«VÑÓÓCWWš¦ñ±ßû½4ñÒ¯¾ ¯¹9ðÂÔuò¿ùôÓâ¦aÊŸaຠ]z!þ…—âsi‰’§oZ@Ñ ê›‘]ß…Bõý`]*„CÕ6®ÂxçúHpÌf?åíh˜gÛqGÓ Â¯f2(§¼u=¨¢ç ðTÙÉp­Š+Îåž{Ö¡`ÝRÃJáj‡#:u¬äó±¨ÝGnås™©Ôð800ÀÇ>ö1Òé4›6m²^ÍdH€eË–±gÏžaË>rämmm´µµÕú4¡¦ttt°}ûvöïß_ëªTd*íÀþýûÙ¾};Ãn§¢¨Žƒ‡WQdÔÃ?A˜JF›óÓåvÛ·o§­­#GŽÔúô*2}‚íÛ·×ú4K(24Ɔƒ É<³‚0ìÙ³‡íÛ·sï½÷Öº*UÎL´OpøðáÈ Â\Fý&>|¸ÖU©ÈT?Ü{ï½lß¾}TÛ ÂlFžêïù@¦3ݘ¡"9VSí9}ð¼‹Eec‡]t¡ó½=¯²÷i Ïùïÿ¾›C‡.೟}ß÷Éf³¬¸ûnNž< À7¾qÅbÇqÈår|û;o¤‰^žºä¯± ptr‡ŽÛÕlÛNcâàí;‡â=kpÙ¨s†AöÖ“¤?ÞÚë"OE·ád¼,žÔµ§'(F‰i*Dªï¯\.8¼òÌfcñO…N…È¡²¤Mt½´-ÊÛË÷ã|‘•Ðõ ~ñZœHxSuîåuª–«q:Q:ÚDûçÕúDÅb‘eË–qË-·LzÙ+V¬àíoûÃ#s n ^;ÔSiÖ­[Ç]wÝ5âvê7߯ÆÀÀÁ!M:øW¤Qvu2ÿÉúGu.Ç*9{‰} €Ip½]‚œ¢>±xèíó⚀4”Üi. Ë+†e'ýâ  '\žJÔY £Ýu¯?|˜yßúV­›³"s­OàáQ @šôå>> ØØ´ÓNtÖºÊÂ,`Ó¦MÜu×]u-¼M¥-X¹rå¨ú‚0ÛÙ±cÀœ}>xë[ßµ Ìeîºë.º»»éîî®uU*2מ¡ȘáèÆ #—ðvpYüìž[xž—^”ÑIŽ%Úv˜W°LüRâÜÐ6êewõÕ—²¦ñ,gNnÂuB±X$¬þÍŸ²zõq¬×\ΟýóNžþÓ?eÍë^ÇãnúõÔþýmld¹ãj—Vbï^p‰J~hPÄ_¬Suò}p÷,ÄqbïDV¯F_Þ4bš¸æ8Á9æó¥y•ÇaÃÊVù•(Ø$EJÕNù|åð¤å!VËQ^™õ„ïWÏá9ìØ±cRúu!>..&fäy¤:“-:e S‰OÐÆ.A'Ñ"šm±Î—«ë?ÃuFø^ ÙĶv¸N Ë5Ã÷aèú¨ ÂåáÐ%îc*aÐ ËÓÛ‰õqð#ܦ'±¯:¦:—þĹ©vøÖ™3µ¾©'[0¦àyx¸¸%žÕ*§l.¼¢)RøáßTØA¨'æš-a(bA±‚ Ì$;àóÜ™Ç FaÒäKžÞóäG,¥RøP%Òù>%.‘?úѽlì_Á}+yõ³Ïò½¯Þô&=ø>¼†Ž»î࣬|ê)>ôüóxß¼£7?AßýW³`ãFxà@ñ Ëwl¤é·OÐûë<8²˜ 1Ìqâ— …šÍ†‚Ùe—OÁr× –»n Bª°¦ÊsSåbL¢iÁöå£*+I>{BVò5*xw´·CSÓ´Þ©$Š*OÐÙBÝË–-ããÿxÉò¶¶6–-[V2Û`Ïž=CÜ©+¹W ‚0³¨';à—†¿¸.n½ý&ÌVG‘â˜ì‡LŠ&›ÙÒ'abˆ-¡ží€ŠŽ¦¡!W—÷—¬7[j¨ <ú>¾ŸègÛv“síÚëpX͵ësè¶·c¿úÕ¬ÓuþèGÀ5\²t)ÊÀ¶)êÐýøKÑÏìgÑk_¡ fY€ãà,‡L§ƒÝM“ÈË⨹\P„¦ëÖ‘ÍÆŸóù`}RTû$s9&Qù“(‘3)Ø©m,«rÈÔJ£ò5jrÎ0¨fw6QÂã¶mÛ†„4èîîæúë¯ ƒZÿÈ#”‹îîn¶nÝZëSa‚Ôƒð „87´WB€Ž."àÓDp Ò b¡ÒTÿ"9ÉIuâ bA¯–ÁuU¡M{ˆ…º× 5Já6­do¸ozÅÓðïD Ýï`ÞÐ@úþ/BþËÊ©iˆ·?fàé†í·d1ÌBþ5—‹=•ðgq.Ç®®ùQÝÓéà<Ê6µ­eU-š¯2ÖÕUyyºÊ[¹x™<~g3ØèzõúÍêBx\»v-k×®²<9¨‘éèèàú믧¡¡;wÒÐÐÀõ×__ëS˜T|ßG ¿¡®ë¢iº®ãyžçaŽã ë:F­åyA˜$êÁ¨Ð›&pS(<24 *´§FÐ!qˆCˆ&‡•÷žØ6G,â)/@Ú?n«¼³áz³ÂqmJ…J=Ü? †Ë”Wb’|ÇÌo—<Èeøÿ£¯À… Ò×;ˆkf‘ÓqàÌ´‹ozž¡çÙ Ÿz>ª“¦†Ij·É`˜›1—š—á/B˜&CªŽ”c±XŒ7'Dµ\•d“t …‰s¢TÊçXù'“)ûúúسg “šœyÇŽÜtÓMÜxã444Ð××ÇŽ;hhh˜¶›*’bc¡PÀ÷}òù<¹\Çqhoo–† ’===‹E4Mò,|ßG¿mÉ2a¶0v@Çã@( $ÃŽ)Ï£¹ŠÊX Õ’y !Îoèx/æÃÏ™p}ÒÛÐ"õM:蔚% ¦*tuš42èè‘çyV‰°©òçöÓO)RäÉãàTm·ò\¼669rtÑ5äz(\-C ²I[¬®Ùp¸¸è读ڿÚ}1 ,fñ˜÷«æª-¡±‚ ÔÒœMÇX „ï«ik*o¡^Ö tœ²Ð¡®‹ûíƒär«1MxÏsÏñóo|ƒµ×]ÇÿùÁÃìcûGòêõëÑ­o?ï?øÍ qO¿ŒmyUðF¿òJÜ%ו§P€öϬ#½æ\÷†d4×]¶÷ýR¯D%üU•·¤B “óæMùeB¥\µÀ÷‡Š¸¦Yû°“É„„Ƕ¶6víÚÅÖ­[Ù±c%ñ–7mÚÄ'>ñ‰1ÇR~ì±Ç†,khhàî»ï¦»»€Í›7ÏšD¡PÀqººº°mß÷qÏóÈf³d2™HhlnnŽÄÅT*…ëºèºN±XÄó<|ßÇ4M\×Ų,ÚÛÛ'X;A¨ µ²*Ä–šé¯­¦Ós¨Ö¢‘Ê—¨ê’œ}¥ÄEˆ…Âr|!Ñ&Ι˜ sš´JªUÍÄûÑŠ~Õ0)§ƒØ[SµY-ë2Ó™I}šPÙ å=“&† •PÞ#y®dÿfšqqI“Ž50¯¼(=<44R¤01Exf,å¶ ^íÀT£¼¤ËE43ÿ\\,,ši¦öÈþ$I‘"M:š¡„/ + ÷\Hüšª0Ðí´ãàÐJk”[õ”©¡ÑCó˜yZXÑzˆC´êè¸a¤‰vÚ£pÒÊ^ªò•=SŠÊ³Os%è)ñÕÀˆ¼Î!7•§£O]‘ÍU^™ªnª]•÷£Cûé¶Q“;2dè¡§¤} ¢‰(I”g¨²Å•&ŠT")ìªÏ %p;ícî³:8¼ƒwLÏ Ãl¶6" _>%QNÌÅb FvMÔ¡N·ðØÖÖÆÎ;ÙºukäÕØ××ÇÇ?þq6mÚÄŽ;àcûmmm%I^'ÊdzQN7Žã`ÛväÁ˜ËåȆÓ\×¥©© €žžr¹¦i’ÏçÑ4-òflooGÓ4 à •J‘ÍfÉf³¤R)Òé4–eQ,1M“B¡€išX³=h°0ç˜*;`„ihÑàÙt3¿*Ô©O ,vQêYX ‚N‘M1™q¤~òHÌ$ÊI«ƒ G“†j«Z ȳ©-G¢žújà79Ȭ¼“Úi¯jWF#:&QåçÉãá‘!ƒ‹K/½Ñ@¶‹ HKžZa6ROv`4(±l4žiJXRß]塘›iŽÂ++ÁNyzx´ÒЉ9$¿¢ò0LNH01)R$K6Êë˜ôÄV¡QUnÚ.º(PˆO5B•›ô´V^˜*·­òàÓÑi¢)ò†Lz2Bœ;WyL–{6ÚØtÑ…~50袋&š¢|Ý66yò‘€ØCOI[XX‘ÐY €‡‡AŠV$%"ešttþª<%~Bìý©&¥¨åí´G“J´­„Ê \.N&ÅV -ʬ<#Õý2ÜoŠ:¦Ï ‹_˜¶ïÀT1Ól SƒØA¦Ú¨1»}‰e¿9眒mþ912£D7³Ê㸚0WÂÀšè£~æqÒé-44aß9çà‹N“N÷ÓtÑïÑ~úMìß´ |ŠEvg ôþô,®þ` ¶iè'¶äu¸^ëP‰€é4šˆ`vYŒXöI¥*{æUË›hš•…Çüø3LˆzëÁór*—ð800ÀÎ;Ù±c·ÜrK´¼££€;$îò­·ÞÊž={Æìõ8[p]Û¶Éçó‘g£¦iQ¾FÛ¶Ñu= •ÀØ™ø¶f¾ÍI±+”À•7¤By9zž‡ã8"< ÂIDÕ2GÚÉ“'aa`GÆ’ÓÕ%ε˜?7ˆ*o`ós¶ÍR=¯àXZÂ$èŒÙL¿×]=™VCƒµ¸{fyߥnQƒÃI›¡Bý%—¥I§øŠ(1B…×Sá“Ê;HòÕ B} ¼éFóTâa'‘Wµò8Lzª¦@”K6O>:VŽÜ¨r¿*;–&yNªº&÷Í’<“ùÕqa¨¸ªö÷ðJ¼Ãè¼TXÖòý”ç¸Ê£kaEá©óä£c©<½ôÒJ+í´ÓDSúº—Þ!@TY%¸ªØM4Ežž2QU[çÉ—ä¾T¡j•MVmq˜Uõ^y¯fÉÒHcä¡q_T]c% &÷WuRâ§ÚÞ¢‰¦H<-÷tW"©úÝ8²îÈßù‚ ‚ ³5ÞóDB,|vÉ8µ™-ÏÏîÆÝ%ÛW•·c¥‰É¼öŸ€¿ ð_õ–,Y†õÿÈÀ~ßçòË/çÇ?n ™>öª‡¹ñÅ?`ùòåè/Àßý.®ßÆÂøõîŠvÝ@DL¥`p°,4/ç’áV•—ž®=$h½H¦žgñ¼ ¼mR|MOÞPQ]0.áñ‘G‚„­I”¸˜·nÝ ÞsUx´m›B¡€ëºQ¾F:5ŸÏ“Édð}Ÿl6‹iŽÍa¤ަi’ËåJ–UÀ˜iø¡eœkù-mÛÆ0Œ( ¯01TX/õ~²)‹X–Uõ>íèè€mðÍŸü„¿ú/>¹\ŽÎÎN~þì³üîÚµ‘xظ{7ý[¶à‡ŸUDùødˆ‰j2O2˜¾¦êŽQ^Ž6L¢Ì2:jmá’ǯå7Ò­ƒ¶˜+äÈEÓåŒÅƒq¬(¡QQNÑȊ·£ ÔÊ;ZÙj³\lSnY²QþB ‹‹-ª¸m5/»JCô¿ñù¤»ßNîÿ’+Ü€óùàü»ƒH‡­­|éÊw°çÒ'È=y3ÿnkÜþÀ41|Эìu8‰ã¬_ F"¢ç õFTX±XÙS1Ö…Y,ELªMkå :Ùœ3žTœäòÉÝÝÝU]™ûúúj}®ÓŠã8455‘Ëå°m›l6‹a´··“N§Ñuß÷I§ÓQÕ©MÓÄó<šššÈd2ضM*•¢©©‰B¡@ss3n˜ÉTycd2™ŠåùSè‹ìû~ÅòmÛ&—ËEõT¹/s¹…BB¡@*•"•JEçç8ÎX_$Û@y«:ŽC*•Šju¾™L†ÆÆFšššhmm¥µµ•¦¦&ìr?xaÔ¸Ñÿà ·:¨ü«ÉÏ®;4g1ü•¹çž{8øÜsì»æ~÷Ç?Æ1 >pì7>ý4ð[ýýx@vË<àÁ$4„7}ÕÝw‘?ʇð4¦^ë$>ëdbÓ´¡îšÛ÷<èý4á'Nœ¨uSÌz”‘ò¸©EþÄäཉYâQ©Ø%¯£ ÔJPTž2Q˜L*Så440È’„&ªÙÀ MºÄÓO¡D¬ò‰*\§ u:Üd„ñØ N:KöU‚dùv•¼=UŽÊjž ªO–ÌU[IØ´°*ž[2ük5”ˆÙIgIyÊ–*ÏCV'éªÂÀ&뭶롇|ø§ìuR4U­šü¦î•¤7£ú¯öS9»èмܭðOyfªü¿*Œ¬*Sya¿èø˜¯¹ ‚ Â\¦tÄńïgÑ¢ECú¢¦Y9Ìj¥<Šº÷ròÄÂxAW\vYô±³³“ÿöæ7óé7¿™‡ŸoÁ›¿€C/¼¿'HýR,B.xÕ¹nð ÿµK1ŒøØÉu M‹C¯Vº¬¸LsÁoh\---ìܹ“H|ܵk$mM¢ǹæí¨Â©*‘,›Í–x6e³ÙH 2 ×u§ÄCOÓ´èØŽãÐÚÚ Ÿ¹\]×Éd2˜¦I±XŒØ‘L=›Å.H§Ó‹Enüä'¹û£åó½½UÉFó t¦ßÛ±ž¸ÿÀ.?s§õ¸§OŸæ›÷ÞKïòåÜzÝuµn†YM2Ç×d†P/•&K(ѧL2Ž?ÀyÞÜè¼ 3•K:žÓÅ¥™f Œè»êâF^~JäJŠoå’I”'`= :U=¿Ë·Iæ*T(Ar´¡`‡;÷jÇM“•÷w²| ­ÄóSy\*OEˆ½Ï•‡a9IïtµOR܄أÓż!«å}T!TËÛOEìPy5MÌ(ìn&üKž‡*ËÄäÿbÄvAA*pr,4á°ñ‘!«m;x^-–vÝ@äK¢Â¯^ù’AêÁ0ÈëÖ­ññ+·ÝƇZZ¸ùÉ'ÉÍÿ,Xí뾆i¼ ¼ '8†8››ãð©Ê³n,Þ˜ ÏÝ“A¥6Ty8g 㕸X,Ù±cçwT¡Ujy¹ 9Q¢çyèºN:ŽºrQ1)€Mµ”­H6›- ³šý¦[[[) äóùÈ£NÓ4 …B$š&÷Ïd2‘¨DABVå¬L ^ˆŽ¶mãû~$š)ÑM oš¦¡ë:MMMhšÕ¯³³˲"!R‰rº®iWÃ0ðu'—ÿìþsŽë{Œû¾ñ >£ë‘×/}g•¸y÷G? ¬¯ÙÙu]r¹\”Ö÷ƒP®*7¬09,zàæ74pò¿€+¯œÖcŸ}òI:ÄéÅ‹9yð ¬^]ëæ˜•(û ³ëU·dÀzb¼‚¡ãå©p]…ú¦H1 ‰ 8–"…¼T^ŽÉÉpIF •ZM\Ë’ÅÁU®Ç©¤Ú±G# NdRØH¢èhê U«® ·ZíÆ"v*aV ˆ*„­ ‘^Å6LFëP­•'§ŽŽƒC†L$z›˜üAAÆÅó!tPTý«$Õ„½|>š_ó9¾»è]`<ξ}û(~÷»üÅå—óÆóòw/ü /Ùý8|öÚªUdßñ(Þù—£ýÖ–( —67Íà8*”§i"¨ï¹5­r~Ájþ ³-á¸ñ ÂÓÏ©««ô³ç2$m‘Ñyyd`‚?b\ÂcCC·Ür ;wîŒÂ®îÙ³‡[n¹%ÚfÏž=tttÐÑÑÁ-·Ü2$,ëlD JSBS¾B`Þ¤°¦D®é )r*ÑNyÊ)!¬X,ÒÕÕE*•¢§§§dåᨄ:5›ÍFáY•8§iZÔííí‘ §°,+ÊK¨ÄÈj$Ųjb­5s¹­­­‘çc&“‰êU("ÁǶíèÜS©T‰ç!‚Ž®ëѱչ&ë _"H&9q⹿ù|ßÇu]lÛÆ¶í!ßËrT=•箸ս=\^Õ‘¾×Ü“J€Wyi“^â…B¡ä^./?“ÉЙXÕäÉÀqœHÈ žçqâÄ N\{-/üèGã>~!ôd«GüÓ?Îå—_ÎÏ/¾˜Ý»wóÞn˜”öJqp01é¤sÒÂ2Ï6l{ä$ò¶ϸLn_(ÄËs¹ÊyT÷I…ˆ©—„õ‚D‰<@”ãO… UùWUnB5A@ FSE5áj:P!U+Qž§¶ÞP¡cÇš3w,ýIå¹èâ–ÜÉA¬á®_?¥!Þ 0Ã?ˆ…Ð,YZi%MšGÿîQ¸«Ö-,‚ ‚0sB­ÌŸ§Æ*Ñ®ª=§ærñ3¯âþûpÏÜÁV8ó“Ÿ`Y7?Áú…«i¦‡Á×dÑ0 ÷(\s þ²õ¸N©È©†¤-+8V2³šaÄ“wM3xþ.æ®"¶¦dr:©G‡ ·”ú_ÎhEºJøáq¼°Õ>±èè%Ž›|Œqa¤G€T ƒÿ–Vè•‚†z”æÊÊ…e«ò›®²ãû‰:aH°?lËN¦Œq ;vì`íÚµQˆÕ[n¹%ò~hkk£»»{ÈòÙˆXW¡ •Ð5Úoå1WK”€ i]]]†AoooÅÁn•«ˆ¼:UHW%F8ŽƒmÛ=¨ª…wœ¬P³Ép¢ê\²Ù,º®ÓÚÚŠiš¤Ói\×%•JÑÙÙYây6\=’£ %ø(ñ0_ç`-ËâÞ{ï­u5ê¢Á°± |)ïÝòû[y+шþ+ïT%N*áPyª~­ñk¬_¿¾Dôjoo'•JÑÞÞ^²½úBpO*ÂI¦ÉÞ½{y \¦iZ”74yº®—xëª<£j]òÕ÷[ Ê YM8P½½•­TBc2§¬ú¬ì‡Ú¯X,Få‘çºnZYyò*âT*U5¯¢\+}O•gvÒcXƒºI[­<¡Õ䄤íq‡5§N±À4ñ$—ËE×Hy§ª¶V!“•­l© ›¬Â4+û¤&jxžm¯BY«s{ôÑGyÿûßÏW­b÷×¾†³`At-U['ÛU*Ô]=’ׂ¤`˜“aQ“8N¼½ãÄÛ'EÅòíÕŒMµ®<Ç„ Q¢B× ×%›ˆ§ät†BIk¼Ç-evêtãáÑJ+Y²¸¸äÈE9ó䣣ʎ$ÃwNIϺZ r%Vb¬‚Þt£DÀ©F ê½…E‘b”§s´õ¨t½uô($Œ­Ï+‚ ‚ £ƼyÏ¢ 3¶¯< + ŽSª—=» —5ÁÛæÂ}ûØþØc|nÑ­<Ô˜ ¹jZ䶨t?¼i}$*ªçå|>xÎU/õ í8À€,¯äuY‚(Ýl!«\#\ç3Tì+†Ûš‰íLÒ -x–/Ï…Ç´ oͰ¼ èÖJ,¾©:yáz“Òzúayíá6Zâxê³îÜð³ßI¬SÛávVøY •épy:,£n›’̧Áÿhw‡Õxo¢bQµ™ ÍDüÄ>zâ}.ѦÉ6(„å©kh‡uUBê$/·ð°mÛ6¶mÛVqÝŽ;æD^G×uinn޼äòù<†a”xߌ„Ê¥X/$EÈÑ ¶+Ϲ8ù㪡BH*”œ¼.†a”ˆ£ 3YÍ{QB—Î>ÔÀW¥D•Pâ\2<¯ ­›²,ËŠB¢*Råë„Økײ,¾zä«,_¾<:†¨:;;£Iš¦EÞÄI üÃÏ?xøaŽ?NWWWäõ«B,'ÃðBà¨D5%*¯M%š)¯m%R‘¨–ô¢Tž¼¾ïG^ÅJ¬S"žòÞTvTK‰Ž–eE"™ò@Tùh•pšË墺*Nõè”f¡&¨}Ü2¥¢\x5M“öövr¹ÍÍÍ%¹ZÉóP6P-{aš‡Bx>j_%êºN*•ŠÚ(Ùþétšl6Kkkk´]2O¬*GÕÍ÷} à©©‰U_øV­ ®ý~@êãDauÿY–Å;ßùΚ}Çf:*Þp9Öê‘éÈó˜ “0•„Çä¶¾oﺱ˜˜|¯”ÔC“Ú^y<ªíUþ ×´ª¡Ä8]/õ¸H—œZ.¸Vê2ŒWäôý >ÙlPvR¬­$Bªv)?–j3]¯. “‹ò4Ë“ÇÅÅËĞJ^Ó!ÕZdN0«uÝFÃtÔQµQR|TaTUÖÑÖÃĤ@aH»«p±3íwLA¡Öôã(7g.¸€7ï{<ÓÑAº«}ÔÏÝù|à‰˜äà=÷ÞòbCç^vWœ8ÁÓ§OóëS§èÚ’ÅÙwÆšSh†G\t=ÎãèºÁ³c¡ííÁ3ŸaïU°3ý_€ï- ¼oŸì*O?›XtS8áK§TŒK'Ö{Ä"œ e—g·2ˆÅ0+ü¬¼ûÜð=‰÷êÅp›Öðs/±ðf‹–Z¢<%*&…CU7%<*Ï')›ÃÏJtM‡ådÂeb!OyaºÄ¢¤Þ6¡™]~;hóÀõÁo}>Д8Ž–W—‘hëbX7#ÜÇ ©¼“ž IAØ!ö‚Ì‹¥ê¼ sa>x¼LHx¢P«Ë–-+ç‚èqž65஄©± Q"\ B}P.4Žvæ}¹×²òhS¢c2MkkkäuX)|«[U¾[ÕÞÊKR]£t:‰|꜓ájUÔuIæûU¤òô}?òÄVëT¾Mu•÷y2Ltggg$X+/Æd›;¦õß2©ÿœ¯®ç]wÝÅSO=5Ù_¡9O3Í‘ÊLb´“)&B2rs˜ê9z_îl¬D4õ>)$VòxLz9ªÏåÛ$…G%´$°)1N •*ìÌHBaù¹&CÆ*á1YF2õîh„Êòs*¯ò\–‡çQõR?Jœôý`]:]Zwajpq)R¤—^ 4  Œ5h•&¥ðñÇdËU_¶\äVŸëÝËTA¡ÞèT´@Õ9{Î9¬^½š³š6¦t•Q­Ù°€74E%䑸ŸSÄ"–›I,ó¼# ÏQyp:£%UÜľª~íeõPuì!!K•¿“û\p÷÷à~ôUàŸ Ü ¼3Ü_'ݰ=“"oŠ Ljkø?—¨S*q,%gÂòra[eÃc¤ˆ½(•WV|\?Ú;¹2ã÷ìÙí·ÞJ___´lÛ¶mÜ~ûí«Ñ Cå$ËçóubS„ê¨.Cù@ÎH³É•g£ã8‘7 išØ¶yà%,åѨ&,(ϳÑä¯gôÏŸ}–“'OÒ°fM´L † %„uuuEž›ét]×£º%먄Kåu™ôTB*@sss”OU…>†ä-TÛ+ïÊÖÖV²Ùl$Þ©6ìíír~º®Gâ\:ƶí( +À¡C‡è~ì1®ÓuÚÛÛ£ö/Ï«ª®[¹ ™N§#oÓJ¨r”øgYVÔžjÿä9”_Ó®²lÒåójbŠÚ¿R½Ë?''ýóŸÿyÅò6lØÀ3Ï<3úIˆ(P@C£‹®‰6 ©ö4)*ï½jžz•<Ëßëz,¸iZ,¤%ÅÉÑxªp¬¦ €†k¸ý•pªöUÛ'=!‹Åà½ýÔù%½ …XT8NPž “^ŸÉãW ‹Sîi ±—¨jsuÞçž;ù÷À\ÁÇ/é'$?ûødÈ&]³\ŠÕ¨·ú•Iz;&ï3µ|,"öp¢·‚ ‚ ãA$®l«WÏcÁx‹²Y¸¥ö9ܳûg¬XáqÕ‘ï°èµ¯å'OrþÂ…Üñë·1 x€óç…ù$_õ*ØÝ=‹ªgAÓý ¨¨ò ê=`MT_‰x.˜¦„;Uy/.SžŽÉg~åa—!öÌ&öU€IS ùÄ6Aî«xû¤À¨ÂŠZÄ"™4&ŽÝIà騼)³á9©}Ú‰Ãd>HÕENÙ)O…-UïU“žŠ¤—f’d>JÂ÷i 9Ô^/ohFpTœ4m„禎£‡çk¨ê3á²ÁľJhì­P®ò€L “çqaá çŒwǶ¶6Ž;Æ-·ÜÂ]wÝÅÖ­[éèè ­­mb5š!8ŽC&“‰r•Áäå(¡¶Œ4“ôèSyUNÎSy&Ūl6‰c†a”¼¦šC‡±téÒ’eIÁJyò)AN €ÕP.’¡–•ȪBN«—ò\LžçHör¬“9ÊE̤xxòäIÎ;ï¼HàK £åçT)äòX¯Q=„Ïš©ÃãHqÖ„¦+ ÇB.?Ô$ßC v%E6…çÇÌå‚ÿ¶?9N,ò¹nÜáN†`M ’žÌäô¼R¡O jjûÑxö•{LªsPï …¸œTªt]RôTy%“å„Îä%môôL–•¬‹ãÄû– ±*GHry.ÏlM.//¿Úral¸¸´Or)R¤™æHpl¤? gYOˆ§[ý““BqòýXB¾Î–ß,AA„z`_É'0°†CK§Ë"Ü ÑCÝ ‰–.Çám/]ŠaÀgiç_øC~ððÃ^´ˆkV>d*g£ÿŸÿ|éƒ`¾*8ަÚ–·ü>b8Œ£á±”€¦žƒUþ@ˆ= •7¢ÔÔsµK d¥ D/å)©v]BVWxƒØ+0nŸ%¼Ú×!ÍÄçÎp;å¡—' ·K‡/•ÃPy*ÁOmk„å%—~®”1Oy&ß[‰W9:•ã´*e‡ÃÉHO Šê¨:• §Õ. ºfzÙva™+ŸZ9Š Ug\}}}twwsûí·G9[ZZ¸ñÆÙ³gÏ„*4P‚´¯e.CA&—‘ræ¨|ˆåa>!$=Ïò¬’í’(QjºDÇ'žx‚C¼tÑ¢ªÛŒ5/kµð®å‚› ¡:Öó,÷:+ù|>m s¢8¹)bcãáa`&=ñBë%< ÷Íå‚ð,†t„³Ùà}¡΢Ôã÷•¼ï’â_”Ìž¸ƒ4J„Tž|•ŠªyJ”KŠŸ†¬Ïå!r´áD]7®§®ï-+ùZ(ÄaK'8ŽÊéûñûB!ØO Éü‹Éc$ÃË*¡TµG.äßP¡^]78¶zŸÜJ=+}?ø\,–W]_z'Šõ¡‡¦åV›Uxx¤Háã“#yA´ÒŠO=VU7…’žL€††3Ž_ø™\Aa¦ñ²åË«NB/Ãg²dh?p7›7º>pæ/ßçÉÞ~~õë0²y–-; ºÎªû¯1*ÓqÀég9˜ÇÀ‡½ú;!—‚ÂÁPWTžˆ.è½Ä^‚bQÍ%ŸT¸UfbQOåBT9Ëůò.§Ê±¨ÊQ¢YùÜLµ\‰ŒÉðªjûJVV•òÔ~S¤ª\¸/i0Šñsý”¥Cí#iÙ­{à=XÞ¿|B‡—Ç£ ¯ºvíÚ’å---SÐ:õƒÊQæº.†aÐÕÕÅàààK¡^rŸ3Ç÷ý( çyQnG%Ú¹®K:Žò8ç5¨rýM5»wïfáÂ…444L_c†d³ÙiW«!â›0Y( £caÑNûÄ ¬Ês&*ŠÅ¸Ó[(Ĺm»t’T•¥ÂŸÆP>%ÖA Î%EFÛŽEµdyJ”ëê öoo…3Ó Ž¥ëÐÓ‡;ÍdJ½$³ÙÊç¨ê¦ÄFu¬tº´NI¯@%0ªsÕ´¸­Ôr•_R•¯ÚM‰·*Çb2œ«:NRTÛ».47—¶© …ØSµi¡ ™JèUçÐÚ_ƒ|>Ø÷ĉ fŒŸƒØØ‘=(P K–~ú±°ppÈ“¯kÑq,žrBíð©l¸\\¹†‚ ‚ õBbài¸Iô…ñƒ_8ƒ5šÿ¿t)œø‡]pì‹.æï¯ù·Ýv[äì°lÙ2æ?3óÊàÙ¯XûWà>ºÆ D!RÓJ²¹™8,jŒ J£pFáO•ØgxÀ…B%ybÑ/®Wÿ“â› gZŽòFÔaTÙ,ª{Gµ®qý>’ñDnÃ& ×S0Í£ÍGYðü‚ •1îP«s ß÷) xžåuaæãGˆ=è«ÿ2¹® Åb×u#qMÍljoo'N˜»±š×àd²äôi®»îºzÿ½&>_²xMyò³.?ZÒÓN…ðL†U^„ê½Ë4-ö:„X@+cAêE…þ,cMyè)¯ÁdGljóB*ïÊBššâ²”yÍåbGß–+C•BU+YWu ÕÙW‰Íͱ˜ÏÇÏ… |jå©„YÏ+õ6T"­DÕçÖÖ`_%–ªp­¶,³í`ȯ‰:~{{°½òð4Í mT¸ÛòEªºe³Áûd¨ÖT*NŸxb]­oÁ‡‹‹þihQËløWï!LëYJ)¿Vê÷G®¡ ‚ B0ŠüC† |£é(]_:…΃òãÇ£µ§Ï?óþô'Ÿà•¯¼9HÔ;6^…©ý@Gø|{n˜†p¬ÃùüŠà)ß°ÕÄDˆ†:HØ™X®B•Fõƒi’ë“ÇH¢r$ 1Íx‚µšä\/¼Øð"§.85¡2Æju.¢B( ÇSî1Aêàwy´ßhß÷£W1 ÎçóQ~G?1²=ÞŒ#a—Ý|3^uU­«R3Nž©T°¼«+¨CSSì­©ÂÆ¦ÓÁv¦9TÜSU•'¦ AÇ(™±¨<‹ÅXTí˜ÉÛäó¥y.=/ngÏ‹ÅFÏ ê¥ÄH5NÕYy€ª}Uù*DmWWé®Ã§>5±YŒs \Ü’Pª>~ä}¦£×eNÇJtÑ%âU£ÆrÏÆÙ6ñEAa60b¯zß>:?v<žýšÍBO…yà~£ O݉¹.}ó›qï›Oá…?೟½–Ð} #<ÖÁ@#,ÙWCá~à2ໃAÐ>÷2‚p£qØÓö²J'EIE5!Q˜T’ÑŠ:;ëËãñÙ ÏòØ3ñÛüö¸ËÇQâ8º®S,ñ­)¯“Sê 7’y“&«<Ÿ€•÷cR‹[3Ï ×:%HA’S½WË!ª' øÙÏâm’ù¦UšV*ºõô”zþYVìe¨öW9•G¡mÞ„J,UaJ;;cHåͧò8öôÄy•gŸ*[ v*w¡òöå©ðýÀ;1)~æóq]T»©úU*£#ÁP¢ãhÓúZVp®“5%)Ï´.ìhlÁTÚd/êˆ7š0]TËñ8—¨·> µAl õebµhÍ=÷Œ˜lÁ;Òîç7q¿3Ô=àâþÎ<‡ sŒó¬€M¼æÄJ œ^0—€ùna1 y ´wÆ©N"T@ñ‹¨{ … Ôx£YÕ;ãòx\»v-;vì˜ÔŠÜtÓMÜu×]tttpÓM7ñïÿþï44_ζ¶6:::رck×®¥­­[o½•»ï¾{ÊÈ÷}rሟ ‚0µÔ”O,©jU „WuÃ0Jì‚a21¡NYtð`­« ŒzëT›0¸nÐUÞzI¡P‰‡É܌ɇ%ªåóvp[²=Ä“º±_¡ˆžÉ|Œ*—¢ï’£òbTyU¨Ð\.öLL†NM†Mv±F+Ð]½4ëÝTOvý’÷ÄLb$[0•vÀÇ'EŠ^zÑÐpqÅÓQ˜VfK^á‰Ro}AjƒØAêÕ$#Ÿ%ŸÁ+¢ÂÚ8üààõ\·ôçhóÎà´ôóÃËrý£Íl8 ޼ÍÀî`÷ì=WžaÔÔ÷•cz®‡0qÒé`ìd¶2¡P«Iº»»£Y›6m¢¥¥eÔûîÙ³‡={öp÷Ýw³iÓ&6oÞÌÕW_Mww7[·n`×®]lÛ¶-ÊWvÇw`š&»v튶™lR©]]]BQ¦z²Õß÷1 MÓ*ND¨×É gg}ÖnzXµjU­« Œ’z²EŠ%žN“‰UÎÂ\.ý’”w=”€” ‰jñ 9å娼“aI{i,&M³ÔëQ…2UÞŠÉ|–—ošAXT•QKÓ‚åÊ«.éá×ÓS*,Ö FµPÚγlvhîÇzg4¶`*í@‘">>9rxោ·ê}Îä笷> µAl õl’ÕÒ[t}þ üE—ÀMéøa{p M'gþ™@¢yí£ï£xËÀï«ÜÏ% Z_¡ì®‘£ðõ‰®—F_šmŒ+Ôªb`` r_Þ¾};mmm´µµ±}ûv®¾újÚÚÚ±œ††n¹å–ÈpTbÏž=ôõõ•šk×®eÓ¦M<òÈ#SÒ8žçáº.]]]u+(Âl¡Öv`y⽎N¡Pˆ&@àñ¨r8δ<¯’ÖK˜IÔÚ”S €=ár*&˜wƒÐŸOz,'ijT§´œd˜Õdˆljg[ tüUDJŒrœ@T!NUØÕd2™ ¼dVÓ ÎÁ÷ã¡åõ¬§.T²ÞB}3’-˜j;`cc`P$PÝ*9 aª0¿ræRžÑzë‚PÄ‚POv zäö`ÍÞ5CÖWŠ2“úàeþäÅà9Ü4á]½ðÂj¾úÜÇ‚ Mo=¸/@þ¯Àúp°Øz}õúȳíÌ&›­¯1“ÉdÜÜtÓMìÙ³‡mÛ¶ÑÒÒ¹5 ÐÝÝÍÎ;éîîæ _øB´®ÉЭ{öìáØ±cttt”xN;v `ˆ'å²eË*Æsž <Ï›qƒ ÌTji4`^YˆU¿,»¯çyd³Y|ß—pª‚0…ÔSŸÀÆÆÇÇšpÈ»B!žÉ¦¼“É™‘®x¶·Çb¤Z¯iÁ{ËŠ…Eß=“a]\·Ìóñ l"ØOÓJÅAjµX ʶ¬8Gc6¬Sž’Ž34_ ò&¬wÊÏ[¨_F²jð`*ì€þõÓOù³¶ÂäSí¾K3wŒX=õ A¨b A¨';=r{p¢ñÄõ¾_e?¿!zîæ cí—ùãþ¿á§oã'K–EÛéÍãÁgc h+Â÷³T šËèúÌK‰2ZÆ-<¶µµÑ××Ç]wÝU1¬êÖ­[Ùºu+·Þz+mmmÜ~ûí£.·»»€;v +XŽ–#GŽÐÖÖFKK˘rS:Ž#Ã,¤Hœì@Éð²r@QË’!+=@·QËõð¥Ö{‰íìð}WÙzµ?aÁ šä:/¬C:±-a™zx>NbUïb¸ÞöîÝË‘äØúõµ¾ Ã2v`ÿþýlß¾­[·FaÛ«,»+ÇÁó<4MÃó<ÌP%ð}ˆ0)Ô»w׺ uËöíÛ9vì/ùËk]•a™Ê>Á²eË¢ÜÕpp°°h§ŸñçËÅÃT K—+ÁP ‰¶wBUT•gâp­ÊJ誜‹IÚÛã²\7ðRÌåQÎ÷ÏÆ¤°hš±€ qîFM‹½$gÊ-ñvŒÙ³gmmmìß¿L)jÁT؂dz}ûv6mÚ4äùÀÁÁÀ@CÑQ˜õ´µµ±gÏ>\몌XÏ©x>¸÷Þ{Ù³g;vìÖ‹Bf;ò|0ºçA˜Íttt°k×.öïß_ëª ËtÇñãÇKµƒCàUp®ì"…sÞÛпv þkŽuâ½ôzæ/ØÂkvqðl˜È*BiëÁ|XáQ˜Ôwl¢}‚q }}}tttpË-· ;PÑÒÒ¶mÛØ¹sç¨ ú‘ïîîfûöí444ŒúË^+Vðö·¿}\ƒ*bµöø¢šrIŠzZøRœno%¶)»Ákáû"—ü’¤Ãmí*ÇÕ Âdð=È%Ž£ê¬î 7¬— 4 ‹ªlUç"P÷W‚¡š×ì­‰å^¸Ÿ®Ë‡ÿ“ûçûnܸ‘âÆ¼äÞ{kv=GÃTØ€uëÖU}8`¹Þn¨8ŽƒªÊxÞô/uq'^ÈçèÑ£,_¾¼ÖÕ¨+îºë.º»»£Îz½Rë>‹K–@µO>­L&!ö  #ðÒéà!£P(Ý®Ò(Ç ÊVݵMOOièUˆÃ¼ ðõ¸^žìŸÉbœeÅf:,S¡I“$…Ìü ÓdDtŒÙ´iwÝummmµ®ÊˆT²k×®P™+W®¬Ú'P“a. „÷í۷׺*Ã2UÏo}ë[Ç49Yf+ò|0¾1CA˜M¨ÜˆsµO0ܘa5NŸ>]"<êZ›±œ]dÏà{`¡Ç|ü_™ôpšs^Ïžç¿l˜HÁ¢ž]×ÏêóæI>GazرcǤô ƕ㱯¯`T_jµÍp±”ûúú†¸<·´´ÐÒÒ2ä+¹FOÕÌD•Óm&1YrH¹_‡“X¦då­×.+™*uòÊÊ(/Û&3áË'òš€Æð _jù<!/C ¶á~…°¼<‡aÐ ô €Ð ýá6=Ä¢`6\Þ–“NìOø~0üß¾ Óîד8Fg¸–ןØ?¾zÇì —™‰}zÃåíaYù°>íaý:çªêœN|î {âùÊ&›ZÛ³U¾=žçaÛviGB×#ïÇz'iÁæâ4ŠÝ»wsòäÉZWCµ¶I\Ü åt+KCŸ*bBß@Ï+Ý^…6…àÁC…<5Œ8äi±¬ëê Öy^Uy@öôË-+Øæ³Ÿ…ßü&(³Pþ+S¦ê“Nû©ºÎS'ÌBFk &Ûøø88¯,ÂÄ©§> µCl õgü`à9UºÔþè‹ D^*²x‡_‡\´%>¯~yç.?7Þ¾ÂÀB··ÏÞœÂìd\£úBf¦±Úf8…t×®]ÜtÓMÖ£f• ˜ÝÝÝžñ\ Ïó¦ÕãQ eå(Ì-û¯Ä:%Ð DÀ¤øç{j½zßn›"íæy¹pycø^ |)JE¾¤è„Ë Äy¹²ýËËPå7‡Ë‹‰rÕ¹5†ÿóÄ"[h&>+ñ¯?ÜN‰k½b[šX¸3 ¼³áþYb›®…ëp?µ¯ò^´Âí•a'±d¹ÝWǪ$[Äba¥õ ëW£°~¦Rk;àáa$~á•Ç£ònœ©a—“µž÷0û¨µ-P(occŒ’½ •ª<•Ç  š"U®D%>*”÷!…JüK¥‚ý•§¢¦âc.—­¶µí@„Tï X½- „EåY©ò@*ÏEKœ¼„:a$[0UvÀÁAGów_„ɧ^ú‚ Ô±‚ ÔŸ¨¬œ}‰ÏQ.,cþpašŸÜ¸”ç.|ŽçyaÉÁšÖÂÐFJšP’a¦0.áQ}‘•çãp¨m† Y°uëVعsg´L¹s&÷Û¶m °sçN¸þúë'½a<ÏÃó¼i|ÑPM˜Pb òökN¼š>õÞ&ö´Ã}•H˜ôHL…ïóÄáB•×_6\§xv¸¾Üs¯—@ˇÇë¡TèÓç£{õ%_*2›Eì-ØŸx¯Ž£Že‹‚&±øhÀ|Q„z¢Vv )öáåp´m›t:=c…GA˜iÔKŸ |2ÂhIzBð`à8±×¢ë‚¡¦Å¢ònL§cFÛþçr˜¨LPgg,æóqxTÊ´¬`&¤;]7'n¾‚2 #Ø_yQ B½1[0vÀÅÑQê„zé‚P[Ä‚PÏv é´dmß(ψ—Î; -/,Ö?q3_Þÿ>³`‹š4ì”NJ„™Ì¸r•Ëp,µ7ˆs Rö^­W¨ºYeÇ0]8Çt…eIO?‘xæµ²Éð¿å¦iâ8†a`‰ÐŒfÙ²eµ®‚0Jê¥O0Ñ0«IÔƒƒú_Å]y>Úv°Ny5ºn,X&s>:N°mËU¾ÆB!•ИÏÇ"c: _¿¬‡ô™—›Q˜{ŒÆL…pq%̪ Ô õÒ'¡¶ˆ-¡ží@2M›Ý¾) 8†y¾vÜõ"?Z¸ÿwÅÏxÃÊ—ò²·ðÀ3¼B_Ê£QYÁ³»<¯ ³q *iëÎ;Ù¼y3[·n­¸Ý®]»Ø¹s'Û¶mñ ¾mÛ6ZZZ"ɵk×qƒnhhàî»ïŽÂ¶nÞ¼yJ ‡ëº‹EÚÛÛ'½ì‘P9 ÓUÖ—KÉ!Ñ|…²¦…ɤVvàP"D‚……£29‡èº>ãò½ ”ÜË—/¯uu„1P}oÔÂc*<¨‰ŽÉÿŽx&½ •G£ïë•×£šë¤¼}?Èͨ„IE2¤ªëÆe›f,<ærñºb1ð„œÿ,üÛ/† Ÿ‚P¯Œd ¦Â88ä‘'}A¨ê¡O Bí[ B½ÙW]ö*t >äDÆÆpå÷‹ð‚ ¯ê‚¯º<;ÿ)~oA?¬{+¿ôóƦy|ëáœ=§ ߇ÕW»YVjUÄGa¦3.á‚<ò·Þz+[·n¥¥¥%ú²÷õõÑÝÝÍ®]»Ø´iÓˆ^‘ŠJ£Ã…m R©–eM»‡“K 8¦'Z Ì`jaN–ø=$½EtœÙ \vY­« ŒƒZ÷ |üQ‡[T òhT¡O•ç¢ã¢b:‹Ž€ÊÔ¤Ó± h&œ­R©@Lô¼@„Ôõ8\kòÉ|Ùlp õY=°,Y—_.y!„™ÅhlÁdÙ'LÀ"¡V¡¾¨uŸ@„ú@l µ¶.qÕ†'†Ž> ùFàˆ \Xïà;­ü3ý´¼ôyÖ»ÿɇùƒ×¿”+Þt}O_Œ®Ãù/vWiXa60nᱡ¡/|á ‹E:::صk×õ·Ür étzFÍ0ò}ß÷kâí¥aTA˜–R:Èè8º®Gâ£1àùaš³-Hæ..Úc¨åŘ\®„@]½#• ÐÚ¼×´@lTy …Ò2óù`Ê©r9–£<%ËçPiðHË 'A¨ˆ„YAA¡åš`4^h rE‡S>Üiã¡óŠy{ùÏýýt?z-7½áJ–ÿ×åü¥§\Y½:(Ʋât)‚0Ó·ð¸¸cÇvìØ¹0+fê #×u'^È»"ÓÏeÀ¾P`p]—B¡@OO¶rKšáÌõÉRgΜ©u„ÈX<“!R“aVË>õPá8Wb¹g¤ee©0¬Ía‚ùt:—ª¶WÇ3‡ÑG4m¨èAYA*3–ï½ ‚ ‚ s‹{py†`¬°ÄI!ÌØdÜxç ¡1ýEt4>¹¼_}ò÷ùÌgøÂü€»þ?+zÆ7 Pºt=N½"3 IfªÐX Ó¬ÍLçÚJž‚0wÙMœÓѶmLÓÄ0 lÛžñÞŽ ÀÅ׺ B…[ÎãQå\T‘UTjX•Q=DtvïUžGM "”ˆhYqŽÇdVȡ뱤 S‡‹‹Åô¦ZAAafð6ûÂY–†B¡þ…_’¾¼óW£ï·à)wÑu¼Íÿ,|Ðx×»ÞRîв(IÕÞ3ÂL朩>@[[6l¨õyŽÇq&^È8ñ'^„ ã$)0¨«º®O|"‚|¹kˆLèÆËH^O©T쩨r,BiÞF× DG…òjTžˆÙ0þq.ШB«êz°*ײäáC¦G<AA˜øþø*|ß§˜|ÐÇþ‰8çyž¸„ 5¦’£‚ÍJܾü‡Ÿ‚—„¿s3[¶laùò~î¿ÿ~R©àù_¥a)-7S„™Ì¤y<Î&jéá$C‚Pôpº‘ïûQrèôd$B³ ’·ŠEM8³ti­« Ì@œó;ªçdß ŠÅ@$TáRÕs°ëÆ¢¡ãÄy!/o½õ$ž·0*WÓ‚‡]¼%A˜TbAA˜ ¸®‹ïûU'K»®‹ëºhš†eY‘P¨¿d´'˲( Ñäkß÷qÏó¢òUD(Ã0Èd2‘ø¨¶×4-*[×õh_Ã0ð}Ïó( hš†çyhšF>ŸDµORTuWeû¾mÛÑþét]×£uª,MÓJÆvչ꺎ïûQ»©vQëÔvšÌøFCÈ'>§b?î¡Kñ9–ëMøƒàÿÂ#ÜÏüù×sàÀ <ÿ|06 iaÊyf!"<–áºnM„G5ÏH~Úazq+ñX žçM® ° fXáÁtJ¿è6`†ËÜðeRva"$%ÝA=cÉ羽õ•°¨ÄÈt:xår±·¢ëËt=ØöìÙLóý‹qHUk˜‰ ŽãÔ,$¼ Ìf<¼'‚ ‚ LŽãàºn‰xW,#OEõ>›ÍFË”¨¦<MÓÄu]Z[[Ñ4-ä4M#›Íâº.¶m“ËåÐuMÓ¢÷ê¥>«² …étš|>O.—+GµÂ5®¢Ê6 ÏóÈçóÑq …™L&úT9ª~jÿB¡PÒÙl˲¢ö)‹ÑöjߤG¤ljÚ@Ó4Z[[KÚÛ0Œè8ªðlY,Ôq ꫪ:øŸm `€ëÄa¼6п,÷×€ö @ >æTXVHƒ‰‰;’upVQ4ˆr\ÏénÌúõëk]aáâŽJxTÑÙ‹Å lª »ªë±°˜ËÛ46Åu—0©&ò>ðÀ/ؽ;Õ~ÕP®"< ÂäããËLcAA¦ ß÷iûþ÷ùä7FË …Bäi¨®¤p—ôHL§Ó‘8—ÔÔ+),9މa•Èår¥ùê´··—|N åëÆB{{;–eEbe%†{îißÑ^%T ²Ùl$†Ú¶ ‹I!W‰˜MMM%õlnnŽÚݶíH4 ãÿgïÍãä¨ëüÿg€„À$5 bL¬peŠ©!ˆxT‹ ÂWÜž°ëüº×]t³v¯ºº²ÝÊ®x¬Ú +¸ Ýê꺸hת Á®ˆpOáP˜JB !|~|ê]UÝÓsd&ÉÌd>¯yôtuÕ箪O}êýz-iA[w–£Bö¥ R9'B€JYrþä ‘†!ÅèÅSˆÝ|>·E íÒ¸”%×—Ag<–Ñ9h9 ü]dždúµ[U.¾X?ØâÐC×ÑÕõÿ1gÎû9ýô9¼á õº!x ö}â± ¢u2˜Ê¤€ÁxÃE/hG;xïûe`_þ'À¶Àþx'Cømp³P½ —ƒu”¿¥o }´k†á&ƒ0JSò5€]å!‚¨Œ€„¸ ¢µÃG“¢£—WtwwÓ?Þ0˜´ØUBGÇÑ®R}_ÿö}ýûë_ÿ)¶½‚ €cÝB±xp”¯N¥R¦Ý³s½^ð"-î’Ú!ÚÏãµ~10Ø0¬¢Á(¢_«½h{õÆôÏË~›6ñâÂ…\1mZœVÜŠ›bBd•J¥å„|Nq±S¹ƒawk 6žbÖ¶í˜D¬MiP±M»ºʃ^ÚšQÈÎáJ%¦¸•ËËN4íŒÕj•J¥Ò1Œä‹Ñl6¿WþêW¿×ó2Ñqà‹s8øçûkYZ}s¯¯Âì¨á,| Ë:LËÜXó?3èî®râ‰×P¯ÿ=۶݇ñæk0`ˆÇÒÚã£cm`0>xœÖ äC.¤Å²Ñ‚ð‹À\°ÎðFŽûŸÁ?¸ì „w IBÀ?>rË€&)Â&XUô$ „â`Ó—8=EZݸ&ILèò–­.a«Ñoék‰„t¢z"ëÎò&Uоŭl¶­ Ònò,Éb-í¯§ú%cDåÕ£²ÃTùRn4®„ºO3žš1øyù²å©FuV£c—SÚ¤ÒŠòŸ}ÒeÓR*¿ŒŸÚ–¶ј¹Q~©GÞ äÜRí”ú ö<< M⥗ ¶­-ëuíRU¬-K[7j/>¿£RYA¡åò?áº%-zˆk®ùÃÒQ\ÉËŸ¸üñ}?Ö€-Ô´{ƒ±ÁX<ŒòZWö¿óN¶-]Ê]ë×Ú6sûû9îî»yâ‰'Øö›ßpñ)§p×±Çr‡ãÐh4€Áe‘¶mà €öóÓ.7JŽ”&å{8Ù³Ï#A'BÒqœ!-R%OúÚâû¢‹.Úãã9™1ÿ¹%L߯_˱§gØpdWì—x2²`Ë–-lݺ ‹ÔéX––!Ò`_ƨˆÇU«Ví““P'낽#.40?ñ˜D>(zЄþ€Á½üE`/º!¼üÀÍCXo&¸!øÓÁŽnvßOˆ‹rY[Døÿ Žhÿ|M †Ñ¾ P#!ì,]gLúèÅ¥m¦Úž‰Ò[hòJ”«hRKÖ›B–&({IH/ma)na´Edž„´¬’„âó^ˆL7Ú&jGoô¦ò‡Ñ8CBzV£zÒm=õ-$e¥)ÂìÆlf1 ÷à©>ˆÿÙfTWš$”÷…Þ¨þbÔnÙNû®­¥Æ¢ABÖJ;Ò¤°år¹è“Æ6‰*¬œë4¡ìGéå<RcՈν¡isÏjêœzQ/À` E@„¡¶ptý†št´íÖcŽÛà“ÉÀG>Òç•i4Ü–é—J±l ‚€jµJ¹\¦T*ÅéåxµZ¥Ùlj i``0rŒÔŲ$‚ yõs€é7ßÌovì`ÖWð²'Ÿä}®Ë_û–eq†mS¸ürmñ†~å3a &žÁçPu 3f´)ºo×dPü\7öŽÛ°ßu*Žög39í´ ¶2R2-40Ø1*âqΜ9,_¾|¼Û¾ÛQ¯×÷¸QH"öI a|vÝS¢Áþ÷.;è²d§X¡¥‹ Ò*ð~¥ÙÁíz;x,ŠÓfGÄáÄV‚b”†:þ›ëê}²]½*Ñ"äñ×]$¤ž§¿C'ÑŠ °ûhµ*Ìw¸÷7ç³týThµ”‹âI†V›q¤¤)DõÚ´’˜ýè ¬Œ&¾ $D¦L£!­DXÄ,©42ÎBäAb1)^³CÞTü®ÂÖy[ybítèÑp#ðN³2fVªlRõK96­îo©ãŨ}ý©ãéëEHÒÒ íS¥öeÛŽ;me6HD)_Ú䤯¾—äí«M±ätayÏr6ä6`Ð /:1‚»§Ý§ŠkU×ÕšŠžGl¹X¯ke‰å(± —,yŽLf5ŸûœŽß"Z±í14D ¢··ß÷)•JqÌqËS¯×ñ}Ÿb±»^200 ñh``````0|ôëV€~U{òÉ')Í›§_C«Uòù<…BÏóh4Z±9ÇÑÀÀ`òÁÇÇÂb!'„.~~'ÕBî h ‚{˜o?Nñý[ðÿë8U›6ídzÏÎcåÊžçaYZQÙ¶Á6ž¬ öaŒÉÕêÊ•+Yºtéx÷a·Àó<Â0Üí~ê#nÄ;$Þó, ñh`0>ˆÜbqÇÞÁgv|&±°óHˆ·z1ÑgÁŸ ¡ YB¬9ÀyÖ5᚜ȾV—ãuƒL1¾ŸXDABHxMf\U€î£Hˆ©:…r1±¬V“íz=*߆b/4›Q½+¢üYÈ—A¼m£rüê©rZ îFSð}Ý?×…zdy™mÓÙÈ- ²Ÿ„¸i/_HØèÄÄe¤ó¶¤i‡¥ûý\s¶mÛÆ¼o¥•ØLc09sÊ5FG CÈÆÁÊnÒ츴«Ô!lçHüüÔ “×ÐU·®âáUc0ƒ‘ÅbâE^ªUý) Ÿ‡­[·†³Èd VÓ÷¹&þá~Çþð<¯Å‚1›ÍAìZÕq|ßcrxž‡çyär¹˜t¬T*äóù¸}ÃÅ ±^ƒA!ƒN(¢_ ‹$ƒò½½xõ:~.GÕqÈçóƒÆÔk‡‘L„„±’òlßæäÒû¨?¹+ˆ¼€• ÌSþç©ýÅá¯ÚŽïkÝ/~q'÷ß,®{"®ëây‰³Á¾ŒýF“iÓ¦M¬ZµŠM›6µì?öØc¹òÊ+Ç»O£BµZ%›Ííbq¤e¡ù‰ÅhC *‰gÃ&š·hDŸ ±ñ‰Á¸ üÏ»{ï8X[鉥^MÞdÐ7ª¸½ÌFäâqz; ˜ äô¶x= ¨?AL^U«:Ÿ I !=/ÉûÀйËô}b‚®\NÒ—Ë É)qå|?)ƒ×%=õŽLÜ>z^²íû­ÛbU.'e¦Q¯·–ã¥Ú¢cÙéíj5I#(—“¶¥û†I?òùÖñd2‰ËL&I#CèéI~÷m}\ˆ qSêy‰¥TOvšŽ!p÷Ýà÷'u‹ÅŸ†âÆQÈ8!Ã0r½êÀi[aÖ¬¤Ý¾¯I;ÇIÆl6!î'Ù¶¬Ä:RÈÅ ÐnYëõVkKÛÖéËeM²Bâµ^OŽg³I=²_,=]WW½®ÉNÓrYçKÊJ%©+ 5AY(èO¹¬Ë9î xÛÙoà X7ÞW›Ád?(ñ†iÍDŸÓN[C\ßÚ*×áæ›§3wn?==pçcÍšÿŽIÄ0 y×ïbvv6õb³n> ‹ÿíDZB‹J¥20^c5çæ´ô#åæ×²¬¸ì Èd2”J% …Bì’UŽ‹W‡|>mÛ1yY­V Ã0 [ˆKA&“‰-+ƒ À¶mÂ0¤§§Û¶c×°BòA@½^Dz,z{{q]—F£ÑZhXºÍßûÜ÷øÈ×?¢÷Gý[÷»u<ü7sÆmg$±^K€Û¾³™ÎL¨ÃÆÿÛH}<û£g™ö‡iœþÓyøßfÇwpÔÕGQ.—(—ÝöáÛ8ìèÃ8úü£Y}õjö;i?-ZÄWßðUìœÍ Îàšk®áÑã¥P(°ñ{YzÏRf>?ësÐu±páBîûÌ}ùö#ÙqѶ_¸é9ç–ÞÍ60Øë0Ä#‰öùHݬŠ÷EYˆu£Ñ‘60˜\ˆìqèŸÛÏwÞû>ÂG†Ì“&ÓÖŽµZBÐ¥É<ËÒyÙ¬&,„@+•kÂl6±~tMžÕëpðÁÚÕjzŸŒi²QˆJ±½?îÉèr¦bt H©WˆGÇIúbYš(³PÐe6›‰Õf.§? ;ŽÞ/hh°ÙÔãË%Ö…‚N+ññêuMÜH Ê ÐÛž—™ÒælV—ãy:M$Û2÷­‡×ÜÌï+Í`²a0âQîµ¥K~üã9tPr¼?ò|Ê)7³eË¿âº.…‚C&s'v2÷üæB?äÏü3öÿÐþ¼û­ïæÅ_¿Èû¦¿3~süXM‹ÿ™ÿ?ÚBí¶¥ŠöÓ^¥Õò/q·Z­V)‹1éè8ÝÝÝ …˜h ‚€ X¼x1 ×?¶mS(bímô^ï—8Ø®ëR-WµKJÛæs‡~ŽŸÙ?£T*áz.~Ö§§§×u)—Ë„a—éy®ïdÊå2ïýÎ{ùÔiŸ¢¯ÙG}cÞþ^N?ètιñ.ö/Æ ²AÏó˜ã|¬ºÅU\Å¿9ƒ¿YÀ‡Ö~×sqqÉÔ2|rë'9rÛ‘džÈórØØ,þùb [ФãÍgß̃>È‹‹^$çE×߀=Í&§rÔ¨qÁŒ 8ýó§l øŸ`Ãí8øšƒ)¿XfùáË™9s&Ÿ/ž%6°µ3×râœÈß}ëïøûEÏ›¯x3s1'v2oøÖXrøv¬ßAXéÙ¿‡¯|ø+<¶õ1Ž{ö8œ[þíà㥙—ââ²ê U_ëJ¬úÄ’±PÐd]½®‰¼4aY,jÒOܺJÌC)¿TJ¬-ÅÒвQ,.-+±¨Ìç²Tà8 áØŽf3ŸL&)¯ÙLê—©µZbAV*µÖ/Ê£®›|¤nÐÇ}`;ĪôÇ×À¶?Ž÷5f0™àããQ®Õ[ny6Iïƒ3[ooÜ8 ÐîVÃ0äÍ+¾È«-âK|‰|ë|è q,DzÿaûCsÀß°ß_ïÇÊúJo ˜áÏÐ Œ<ú[\,Hš"z!Ò¡™âî)ŸÏã8…BjµÚ»1—ËŤ¢î—­½>„Zƒ»\.sÍÉ×p÷‘wóÅê¹ýÄÛùë‡þßò¹÷u÷ò§¿û~úB.¸ÿ..\¬Û˜Çuh4¼áïßÀI/žÄ"¬à±Óã©;ž‚[rùÀ’pÒ~'Q(˜ã|–\µD[(r ŸZHfq†W=õ*gS @ŽÕj7tÙþþ„aÈeó/cûéÛÉvey{ýíØÛl|Çç¿}'ûmÚóO>Ÿ—>öRNýé©…c~y ‡Ì:„Ú¢^Îó4¹šËå¨n¬rÇMwpôùGã…ž&ô,›Ã>tÅzë77bÛ6µ\ Û¶c÷ZÅb‘Z¡[‚æ<}„¶ß­ÇùÃ/û0Íf“o¿ÍÙîÙd³YÂ0$¾a#¶Nͦ³þ±þGêõ:®ëÒÌ5cËÔoZßÄ÷} ®ž(«Õ*ÛÂm<Õõ>þ(•OWøÇËþ‘¿¼ö/!€þ¯<³óJªÄó·òÒWÀ G³ãŒ|û¯¾Íi_< 6{<üÊ¿àï{ðB@s“f0cá *Nª|9 4¯ÿ§Çá³¹ÏÒS?ÝwvCÞ{Ú{q'ÖNwÓ§œü¾“õfÊÆŒoÎà— &iÓ×Z™Ð|+ c·®¹\Žz½»¯u˲’ôQ]âê?^‹Š»Û(®gì&6 ±‚+Ò~IO‹â ù>oèÚÉŽ{7_mÜÎ÷J¥‚뺬¿ùf^õúד'O6›eñ+óvÞ¾§o­ {ÓÀÀÀÀÀÀ@£Š^gÉZ+“ÉÐh4âðýýý#ö˜6Œ1ƒÁäÀÀìèü í1óÉ™äÞŠ~—¶¬$ÎZ~f/…½ô9ªÕƒØo¿uLŸ¾h¼»``°×±ßX2_tÑE{ì±ñàꫯnÙ—>66oÞÌå—_ÎI'ıÇ‹ëºÜtÓMÒ]yå•qšK/½”õë×yÒVà=蹤C:ì)ŒÇ<0í^횣®áñ·?Þ1çµ’sX=ŠU`£¡¿ÃÜu×P¢Höœí1Q‘{ó:øØÇpV}™Òæ¿Áý·w‰«Ô½ôö^¬/ý#¿—¾Ë¿ÅÑGk‹H§ëA*ÞbúÎÿ–­ý˜6›:o_# ÷çýP,bûu,_ ­m[[Ö®ÞÇ•l‡m'ñ‡‚=J_Òba9.8Þ<<>ÖÂ&6:„å›Ô¯5A9`N»\Ìd4ù/K…Þ^øÄ'¦soö2vìØÁ=Î “ůfûé/燀w.z'Õ^ô"‡+®Ü‰‡Ç§R_ŽV¡n@½;Ú¶ÁÏM ¾íªDº¤Ñ¥+EŸ ªGO×Ѥ`^ÿvË. ÅCÿüK_¢UÅÀ[øC6,¼~!VÙÒ•,*?[‹ÌüÖRx{–d êk¢³|9„%Ýà÷À·ºáoz`…—Ä¡lÀ’ ßâ#•3Ÿ-ç=ò5ðêºbÁùí®è‡z |¯ ïö™þ·Ó9í×§é¶œ‡l9GØ0'«ë—øgÔaeôfà-=pÝbè…îÝ– GoÞÌY7ß”¢°\¸ÃÕ„«­¹è;r¸Â‚Gøsö·àpó)7³úàÕ`Ãù?ÌñÛ·Ãg´ŽW>ßj.|¢Á*ÁzaàU*%þ¨%0šx,—Ël}ì1^wòÉ:Úü; ñ™-íh_ŸV*ƒ›‹ úúb?ßÃo.^Ìû£ùÕ‘à¿}}ÉEíû\úøãrÈ!#»Iö2†› v×< ±2'2êh|¬ôhÚÈ9*)!kªž0ª;Kgá¨O2_ U§F¹âÓõ£ß‘.Ä^‰Œ³»ê‘õ£3‚“&SªÁ@Œ§œÀÀÀ`â`oÎÉs°Z­âº.žç‘Ëåz™000Øk˜k‚ƒ6nfÁ!Oô-j‰ÿ#F ¾G±•×¾v‹„ï/Á÷¯bSj`Ó¦Mê˜cŽQÿû¿ÿÛ²ÿïx‡úà?ÿ~Ó›Þ¤>ÿùÏÇ¿y䑎ùÚñùÏ^Ýzë­ƒ/ ªP( Ø_QJ¡”*(ƒ} ^xáx7aöô<ЩߥT·rUA”B©_þ×/ãcýýJ5›z;—SJfKídU©Âëï‚þíºJ©ZM'.•v˘4TC¹ÊÕí¨Õ†IÜ輿ÙT#Þ£,ú•rÝ1A©”tÈqt'ÒÇ•Òt]¥,K*•Ç!9ÞþXéëÓù …ÎÇmhï«”]*écrb•Šwùv¥”RgÞ Ô¥ìP©ÆÕ×'ího_©¤Û!ß}}Ó4ªÿÚª¾|½óX ­Ÿö4•JrLÆ3þ~½_>Ž3p¬e¿ëªÚ ŸVÎáÆC_*)eu½ ìY©ìì•;ý—ªÿç¿‹›oYJ9ÇoÓéçìTÎÑ›ÔG>òP˽4Q0žk‚†j(G9-ûG_v†R””rÏPêüó?ª^ùó­j¡½^-é~TÍ_T¯ù»mªFM¡”ê{R÷é5D¥©Tãj½ý®þPÕ¶lÑû¿ÿ}URzã±ÇTåûßW(¥úÿßÿSµJEÉRQJYÏ=§¨¾sÎQ…ë¯p7¿ÿ}UI]cýís|­Ýg®B¡Ô279Ö߯óå J]ZPê ¥ÒÓ@ô©(=i¶Ýª ”j»%;áŒg¨þöù%]GûmÕ^fC)•¾žö¶=rä_ªë-RJ)åww«ÛÎ8c`ºö{~7¢Ùl*´q¡êÛƒõ @•J%eÛö i†['F2ì®5«\URcvw:Ãý*y—((¥ÚŸæ ¥o/Ië*¥œ(í¥[õ·«ô\1÷E}k4J}áY/§”²”Rvô]ˆÊ³£ï¦Rjæs:6JÓŒ>Ù¨lyç‘zˆÊíO퓲e£íxC)UŠŽ÷EeºÑÇŠ>ýJ©oÿZ©/|3™fúú” BÝg”R‹v*uâMJåä]svêºÏߤԗŸˆÆ Êü¶dü”ÒÏC™j:MMÃ݆ýÑøêüëåBÜ7yä+¥Û4TÝ¥Ôgÿ¤Ó5­Ë™†ûú”úäUI9é¾*¥ŸWÍ!æãþþ˼4¦âûÁ­·Þ:!×Bã¾¶,ý»©šª_u¾xú£?ƒ}õžØ›ï ¥Ÿ=J)Õß߯,ËRµZM•J¥Áײc€<‡ &¦âš`¸~Ÿ¡ j‘*¨û•B©F$ÆR/ÀD¼U©(µhуú]i1UaäjBÐ4J©Ý³&˜æëׯgùòå,]º´eÿñÇ›C¯]»6N'X°`K—.eÍš5±fÃh ¢Ó¨£-L˺¹³áÆë_¸)›ÅöØÕÅ+_ýêéFëKzp‡Z­†ïûãDîiضçyãR÷X1Ü\°»ç]qµš¶Lï«¢ }Ë´ö¦Ÿ_÷ÿ+ÏÃ!Ûác/ƒ9¯†MëÀu`ó÷áŽ.8ñØüðð÷á[¿BÙÖáúŸÂ÷¯I¼oœÿ;x£˜©FÈå´C ±¾¬ÔàkOÁÿ ßü€¾>ßx<·ê‚Ýwï&Œ·œ`o  H7ú«FwWŽ\l‰-ÇëÔ©RÅ¢B‡:õxþrqñ¢?)/$$ ˆÓqY²T©R§—à¡}ÅU¨Äõ‹;z ‹…8Nrž<N#;G.^KyxØÑ$q´‹)PÀÃÓîêÚÆc¢[ ì}ì͹ m¡_.—±m;‰·½‡`"M ñZ„è{ôÉÈoÈÒî!r  Ÿ¸mî-lŽ=ö®øw»øÇÀ`Ê`¬ìçõ×_k \ýõê /ìøÙUlÚ´IõôôÄÌê­·ÞªŽ9æ˜éFRþg?ûYuõÕW«5kÖt<*¥,”šJkåî›%ƒ‰ƒGyDÝzë­êÏÿüÏÇ»)#ÂRêÏÿüÏÕ­·Þªy䥔Ö.\´ÝUµ÷×T“VñZ-1JC¢¾>¥ÜeO«ÂÌ«”uàåοG)•h§ïn4Tc·i<ƒ¡Í¸cÅ¥f~^k¬^ö?W*‰¨#:Žþض³BA+¯5›úz-µRI§QJŸûlV—cÛI:×M,²Ùä·m'†•…Bb¬ ‰á¥hÄÉuØlê4†>fYC_s…‚RµR_G#UÕ×§n¿é&µøˆ êÌ3>Þ§iDØk‚N^UPY•mÙGI©s¯Óã=£±S½úÌûÕkøµB)urA©÷²N[U”jÜY mÛ¦ ·Ý¦-ˆîºKå”¶>r^xA¹wÝ¥ì¾>åô÷ë}J[Év.úë"±*DéIJ¨åQ*±8ê‹Ò8qڌݩ§EùËSNQ7Ï›§»ïºª±'&ë ×u•eY={lÚ´IÝzë­ê²Ë.›ž ƺ&8ÿüóÕ­·ÞªÖ¬Y£P¨†xmÈ»@ÚjQ,•Ûa«Ä2ÐRÉý*–„J)uÁãJ´-Ió…gõ}[*)õoêwÇÑÏ1T–yܶõ³à­_ˆ,ÔÏyîXVb/k–lV—Q*%eØÚɃ:ð‡ú؉oPjÖcú»PÐir9¥p”:u½R—~ªÍqAMç?ï&¥N{N7çÕú÷ÜWèt§½G©g$Ï6PjÑ«•ÂUjÞ=çݤ”[QêG*µäݺ­Ž£ëV*2Ä.+õóß)õÑïë:~>ùþÂ7•:ówJ]ð%m)ˆRêðG•Zñ¥öÛÑõJѧÔé÷è>N •ºøúÈzôéäü¤õdß ÷*uâí­ÇW\­ýJíÿ»Ä’ôÔÕeÏzL[gž¿I©n_©®ô|âMJÍxT©³·(e5tÞÃUjÿMI]Ó‰®•þÄÊÓí×}=÷:¥Ü¢ÔG¢6L uy—nÕ}=øy¥È)õî[ôØÎ|N©%·(UêSÊn*5ó*¥f_¨Ô—oLõ¹/Ù>rëó ¥”Sø÷½{C»sMž7mÚ´[ÛÙP ÕýåTNTA¹Ñm®r•­l…B9ʉÓTAÕT­%]MÕTI•â}Žrâm)CòËïô>Éc)+Þ_Q•–´²Ý§úâ÷'úË©œ²•­úTŸÊªlKy–²”£UPÕP¸Ž’*©~Õ¯le«‚*(*§rqýª_YÊŠ­-ûÔ|G¼ûÑw«…Z¨þæßÿf¼›2"ì©÷ƒôúY¬÷$\e¼¬L™a«ÌP)ýîm)¥)W-RõÙó>«~rÆOT–›•MŸj.ywœ6-,•J»ìñ…ñ"`0!°fÍuõÕW«Ï~ö³c*gÔ›7oæÂ /díÚµ\rÉ%¼å-oaýúõ¬ZµŠK.¹„õë×sÓM7±téRV®\¹KeßtÓM\yå•,X°`·øOß¾};k×®åC !pRÚ y´†“QH0Ø× ÷è³Ï>;ÞM»{xöÙgYµjË—/gÁmÝxH?°óz饾8­Äσ$&€·º÷#ï!üÜlJ?Z´ZDNTLBc—1cî àE½}ÕUpùr}«U}Îÿ<õ×½m™XÞìN ðƒ?ï<@[DÑš”éíÚ`% ‰m&±Ùê©ßbYe¡-ÄÈ%èŸ÷écbq0°páBúx`¼›1n+ÓNšú›6mbÕªUlذa¼›9"´ÏkÖ¬SyÛ¶mcÕªUz=°tà½/÷W}/‰åbµCY^t¬¥-¡ïÉøô½pÝ|  îxŽy;øØ%=¿¿]? ,+±v—0Ì}}ú9²Ý‡w½ þüðw^4Ÿo  Úa@ÜŸ ±Þ^ö"Ìÿ>|ªÅ >¬Ÿëtbm¡ô2à“ú·„þïÃá»áíÛà¾#á‹—ê¶VߢËn7 ÎåZC9‡³õ¸äÎLÒœþ¥cš.ç 'ÂWôN×c—]—œ¨Ó< äækcéë%ãŠÖ2{€Ÿ¯ÐiÜn=/;D1-»a°ÿÑpâNméx{Tv(vë´?»X¿'ÖfEqÀ>ßy~}Dte©ŠÏÔuô¸ð£ pÎ|ýιý ˜±N=nC_8 Ø< þȽK?ª³õ3àšupó±ð3Á©ÛS¬ÀuèçˆO×cõömpíƒÀ5pùþpö³ð¡Ù`…ºã=E8îï×óÇGòô_6¦{jo`O¼lذ!ž ºººF]NúK[‚¶Dt¢?€ll,¬x™rl1X§Nž|lE(Ö‡‚B›´"  N,Ù¸l±|ôð(S¦F ‡€?¶8´±ññãr3Ñ_@@!ú³° Yý¹¸Ô¨ÑK/}ô‘!ƒ‡×b™ÙKoG»L‡*UllÊ” É’ÅÃ#$Œ­>Ë”)P ÔÁ½B@@/½4i¶ì¯R¥L™&Íx­v´®LC,C‚!Ó¥ÓËxŒdMU§Ž‹;î믴E©‡_×Í¿Žžÿëá°‡×6Ž{òýÀ_¾\?|Ÿ0 ÷¸µã|M7˜À02Ã2CÐk×9ÀáÀ[~ù–n[ÊÍ3~HxÄ‘XßýJœÎ÷µ H)ð<w‚B?ö*``0^X³f k×®ÓÚ½Åã?øAÕÓÓÓâ#ùóŸÿ|‹fÁš5k¤ <òˆºð Õ1Ç£>ÿùÏ·hŽEka¸Ø5@¬_QI ƒÉ‰þþþ=â{o#­S©TbßàýýýªV«©þþ~Õ××§†êëëS…BA5 Õß߯ÇÒªc"úkì©y S¿QJ±ÙV×ýÓuÊj‹¹'–hªÙŒµõs¹$VOs1ÍÆŠÝiñ8±â7JÍ‹¬$¾ýXbù!¬b螎¥”VHk6[ÃMöõµ†„l4«D9Þ>õÄñž:LIb‘2šÍV«Æ]¹æ$¶ÀPy&j Áx¬ \‰ùšJ©ùW?¯þý=?ÐÖ!%¥–½+²i(å\(k˳¬í;UI%‹¢P,ûT+­¤’Xd•¬CÄò±O%RÔ¶Ä?Ko§­(ÅÒJ¶gÕ –]û*î¹ì²8ÆãT´x”uÁP˜¨1ƒÍ»sMÐéY+÷”ÄK”X…²¿=­«’¹¾RÑë…¾¾ÄB±TRjú/•šûu¥.¸L©®7$¡‹ ^¬ÃÅ-ÆZd»W˜¾¾áCQ9¥ãcv 5»+íF îÕFæL·Ã±þTþÑÖo«ÄR}Wѧ’Ø›‚‚JÞY‡ºËûû>ÂôF똓ߧÔ1¿øÅ([·ç±§Öc] Õ¢?±ÞkA‰ÛTÍ1Y퉵cs$Á”w3úTŸ*©’ª©7wû~±rˆu£ŒCI•TATS5[¬Ñ_VeXkZÊRU‰­(Å:Rò§-&¥=é¼buÙ§úâüY•UUPU‰ó‰%ªXtŠ5gŸê‹-A³ÑŸ«Üø|Šõ§ä‘µ•´#=>i+ÏœÊÅçs¸óÚTÍŽk¶šªÅýk¨FK9ÔŸX§–TI5U³ÅZ5m)+ýϪ¬y?PÉz»T*)×uÕžFA‹Gƒ‰#3L q_)W©*ªAC=½ìiÕìzŸ²~¾Ef#kz¥T,ÃÝLµwuƒ‰q‹ñ(ÖŒ+W®Ò?²X;~âŸÖòÚµk¹ð Y¾|9žçµh´§k·ZÌŠqW ±oêhÍæ©a0ñ†!–eF¦f–eáû>–eaÛvK<Î ð}?Ö@ Ã0 ÉçóضM¥Ru;v|ß§^¯S*•¨×ëxžG¥R¡^¯S.—i4Ôëu‚ —ËÅmw]—|>O.—‹Çömòù<–eQ­V) qÞB¡€ïûT«Ur¹ŽãtŒçT.—w›&ОÀxÌp}O‹Õ3h ¶|²ÿñOÀQ©è}A€Áy((ƒq¢×ÀÂÍð$pÈ!úüÕjÃp¦•ÐÒ·ã´žg9–öÏ?XÞô¾Ñ†Ïl¿Ævåšs]þd½NÇsMÐç-,ØñªøŸÐ'r¾G‡°Øoñ‹¼ì®{q¾w Õ .ˆã¾eú~ûáD¿{IBJ<7 ¶]HÛ,”HÖ!MôºÄF[ÀT£2ĪJfs/•G¬"Å{ƒÄ˜+åƒöÎù›HØðÖ·rÍš5¬€xm1•0-Û‰„‘ÌcÄ GPD߇#µíãA }ɽF´Ýß½+´Õ¼xJ¨VáÆ*p™þ½p±þû[ðó†Þ×Û«ŸKµlܸQ¿ƒ„sÁÒ–uͯáe'¼Œ¾þ¾–uq£Ò`Μ9|ìß?F.—cnÿ\öx^»íµÜ³ížyË3Ì\;““þá$ŠÅ"¶mëuc´¬);Å`M¯»Ó9KÖ¹…‚ØU'krÉëG¦Ž–eµ¬µêõ:Õj5î ¯{ƒh±å8aR­Vyòe/Ã9õT²Ã¸pÃr¹Œëºø¾O.—‹ß%ŽÜ¶ N;­£y†8ÑXmû-Ë‚0äW_Mî#Ùeë‰ñš³,ß¶ fÎÜÅôµÖêV–ÕjU¿Yõzß÷[Ωei+Èþ¨?rQ…aH½pÊ)ÇòÕ¿:˜¯|å[ðú×ïrÛö4Æ[NÐ =ôÄr ×}ô °œÞ•ر%K˜Ë lìV•‚öýY²-ÖVl]Ùž^úÒ —¼b¡¹˜ÅÔ¨áààâR¦ÜbYŒfæÊ”c O±Ž )S¦J•— <¼ØÒ3ÝO±ö+ÕÅ,Ž­ b L'>&V©66Y²ôÒK‰yòdÉ’'[žV¨Ä¬uê-±é±I[iJ;]Ü+Ei·”Æq6%¯ä“q“1“>88ôÓOHH/½€Žéy/÷îõkm¤ØsxqªïŒ/ÆcMŽÁ:}ËKÉAÕ+þì]„Û§H¿cÇ‚`},Ó50˜Ê5ñ°bÅŠaÓžuÖY\~ù屩ò`¸ôÒK9묳øô§?Ýñ¸ä]³fMËd±jÕª1Œ——aÛ¶)¢… µQ—f0ˆùy¹\&*• år™0 ©T*äóy²Ù,Ùl–Å‹ãº.Ùl–b±H† ªÕèeÀq°, ×ucn8¤…*é<í$§O¤½¶mãy¶mS¯×±m;àH;DÈY,ã}Ò7Û¶©V«±ÐEÚÄ}—íBÄt‹E²ÙlL4Š@Ñqœ8´·§§‡B¡²Ò6×uyæ™gÆû´wÄÞœÒbÆE?[ÄSöS-ǃŸÜo}+Ü  Çb‘ή+ &,Ä+ÀÁOôíK°¬ÉÀ|¼Öâ.«J$䨽¹[fÐ|¹~©˜µäEvÌÙ9/¦WìǼÿw–}¶&öÐÂ]ÁÛhv#UGsíH‹-…'wHˆJ'ú@Bt¦ÓJaô-ùÄMä Ño7j³›*Oà§öy°O8{)ù>Ý«WO|ߨ1†š v×<þŠ{U-|”ûº~«2GšxXðG¸Å×d£¸ÌC(4yYkh%„÷΀ӚZ)ÅqÀ¶ëlù——rÇ·ñ±;?Æ5û_ƒeY<ò’GxÕ¯¢l•9yóÉœûü¹\±ð N{ì4v.ÝÉ÷ùoêÏÏž·<ö–¾t)?ÿÔÏÉoËšP]rоù§oR^]Æ¿ÆgÆ’¼¢ñ ®Þx5…Š~H¼zΫãuìÅ‹.æè£æWÏýŠ[ï¹5VžxžG.—ömÊå²^‡6aY»F”ul׃]œ¼ùdÊ”9cÁ|ö©ÏRßZçŸþ'ŽýÛc#«Î?žó\ûÃkñöóXôâ"¼²G`iñÎùGŸO±«¯µÇ¡÷Ý_à×~‚ŸÜö“B³¯ÙÇ´îi8£…ò–V¶âu·àŒÛn£çÔS;^ ‹|•bó~Àâh}. ~Bè¹A¬ z­.ërYßÛ¶+ʺéÛßÎïî½—ž¯R©„ã8qÒÏ\.G†d2\×¥P(P,©×ëdk5zzz(–J-ïi%ÆÞÞ^lÛ& CJQ:Qjèéé¡V«Å Aãýï_ω'v†Ó-õx­ €˜XÒ'íFU\šŠ[Î=åB³“›Ñ‰†Nåpd©ÝÂ2þÂÆŽÝÌJ=BÈ98äÈÅÄaºN7&‡eÿP®ëÒ®VBBlì¸| ‹,YBBêÔã2嘇Gž|L~æÉÇÏ— œØÍm•jLªzxñX‘)m©QâL9ngŽ\G7»âÚV\õ¶CW©Ó¢­TÇÛ ìpØsA¢B£çåZÍH &ÆcM Äc?°åÙg §…zçóȲ'Š·âûZnøÇ?þß÷i4£ªÏÀ`_¨ˆÇU«V ðóºbÅŠ䢤Y»ví ÄãªU«X¿~=Ë—/ËÌ™3'ž,V¬XÁ 7ÜÀYgEWWW_}5]]]œuÖY£yôI {¹5|Ò¤Vš´ÚuuÒŽ®×ëd³YÂ0Äó<²Ùlü2-ä]¹\Ž Ãjµ“l–eÅiA ²Ù¬~ÑjµZ A)ÚÌÙl– ZÈ=h%ÅÚϲ,ŠÅb¬ ÜÓÓC¥R‰ÉLÐ׋/ŽšBøÉË»h_;Žƒã8±f¶hV‹¶u³Ù$ CŠÅ"–eµJ¥R3Àa¾´ðg(+ÑfÂTêÉård2fÏž½G®‰±`oÏ"€‡îz+Óz-û¿zŽÜÉwb_q1‹µ1 §f¬Dƒ½‰ñ\ˆ «Ž&Ýž[§÷ÿáÄýy[×QkO¾îuö ~Òýkoƒ•J“$o§ý#©74<Õ0’¹`wÍ"Œ¥¤Þè[®{è-k«Ä €Y³€#ô¶ïC˜…‡ÖñÅ ¬TBxè#Qä(®?ïA¼M¦°š Íg9‡ƒî=ˆ€€E‹^ä°ýŽâ{+¾Ç­ÛnåeO¾ŒÜÁßöcÎ~çÙÌ¿q>O¾öIýÒ£¬;tïÛȲmËø³OþΧðan}.³s³ã ̵B\™2ÿ°‘ûν¯|ë+l9{ UâéeOsö'ÎæŒwœ›à»'|—eµe½ùh–±Œ×Ú¯å]ïz?)þ„å‡/gnÿ\6Ÿ·™zoŸña.l^ÈçŽø3ϙɜæp•s?[ô3Žyä^±ãÌd&_|1G}ÿ(xœæž½à—}òäñÊËjËøÀ¦ððGæÈïÉôMÓyjçS<Øõ ÇÝq›öÛĆooà´OŸœ›s7S?¸Î­ÜʬÇgñÌïŸá„'Ðo÷ÓM7«Ë«9æ˜cX¿e=]]]<ò·pjx*¸ðƒýÀ;O=×u©T*lüÞF–Þ³”fðƒ“Àù6°ãŒ3¸ðõòÿ­YÎûßÉ1 á¾OÝÇ»^ý.p ¹MRô;ÑûÏ~?År‘À bkÔr¹L„¼í´· ßþÔ§âµy&“ˆ/;è2n´n¤\.3çé9Ì}Å\Êårü¾‘Íf «UÜ|ž;P*•bKNQÔ ÃÇq¨T*ôôô°õÇ[¹uÖ­q]וA¿/\pÁñ\ýNÖÞøk9aâ)&Žçš H1¶¦«Q‹-ØÄzÎÞkOyƒv¤ F9ˆÎtüÌá i;¥Ï¥V2Bîµ£=Öd{LNHž5iâ0M†fa:ùlc(MšllïûDÇÞš ôºUâ;î-‹GìEìóÏ5ÀfBúûû™«æêGEõzÈþ•Ök Cýn0gÎC±7»fs$jÇû.FE<._¾œ«¯¾šõë×·˜5/X°`€™³XGeÒ,Æ¥—^Ú±®k¯½€•+Wrá…rÞyçÑÕÕÅúõëY¹r娂ÀG/Eôc¢éÀ ¡5Rbª··˲Èf³äóù=J:f2šÍ&žçÅn’|ß'ŸÏÇŒB ‹E‚ ˆÉ»\.GxžG__år9&æ2™L|\Æ â…_{pï´ÕŸ T*Å/Ör\¬Åý“çyø¾O©T²,º»»i4A@&“‰‰MÙ/$£ÔoYÖã+„§eY-šri+L˲:’·»ƒµ­¯¯‹.ºhÔ9ìíy@¬‘àñÇç½î{ñä‘o£ÉÅzäÍó`«­ï£àß!̺^¼ Îùöv~pÈÃdÃc`šN¿‰MÌü—­üi£yøð;yÍC‹¹ïûøÌŸáãÿòñ–5ì" lä{ô×ʳWbÛ6ÝÝÝdß›ÅýTÔÚÈ :M„¤×—s_1—wÝõ.ž¾õi®[|åÕeø Z}Û‡w9ïJ.¨œªƒc9œ[97˜sýs ùÃÝ`Á‚,ºq‘ /è<çr®¾€—Y8*< ®Nõ£ºuÑÜÜÔõFþ¤²~‡•ã0û0>´êC¼yÝ›9ë´³âióþ›Yè.ä?þ'K®Z¢÷¿Që®vC–ùË Kœ%àÀü³çëÔƒ3ï>›¯-úvÝÖ7Õ À‚ó®8¿Yß—ó~9ÓçÏãtÿtÎ|í™àÃEÓ.Âòõ egøÚœ¯±bÅ ž½ûYfÿd6wžy'O>ù$gZg²±w#ðò¯¾œ™wÌäžgïÁºÓ¢2·B£Ô¶½wþè@v¾r'/.z‘t ÿuüq^pÜ Ïø,k®åäÚɬ{ß:>ô¿‚-ðK~™LÊU}±ž×u¿¨þ‚eY†Sux¡ëö|ž?÷yü×¹æ£×pÉ —P©T8q牼üö—sø†Ãñ¶Á¯fAvû Þ²}Þn»wÆsMP§N… UªôЃ‹K?ý“‚¤10Ø×°·æYú‘›Õ=%«100ØuŒ·œ|xæ<½™š|_¢øö·/墋Jfþ00M`ÈM›6ÅA\‡Ãç?ÿyuÌ1ǨGyd··¼õÖ[[È× ÝŽB¡ Î~ÿûJ!ìûžC©TR¥’Ê^©TT.—‹÷ …¸ÙlVÕj5eY–ªÕjªR©¨f³éü…BA5›MÕß߯\×U}}}*›Í*˲T¡PP¥RIU*•–o@5¸Í}}{o¤ûúúT.—S®ëªþþ~å8NËo”R¹Ô¶}g£íôï\['*¥”·¢´R‡“Ú/û\•ܯ’ßÒÈG~;©¼¹Ô>i“•ª¥ÔÑÑ:æèf3nc:©6Z©|n´Ïm«3ÛÖV7;Õöôï¾Ô§ûí¤Ò’úRõIÙéúÒc m”4…aÎNékVEmêWCß“cYTA¹ÊUJé1,uH[©èõA£¡T6« ¥Îú†R}(U°úT÷¯7©wd£ea©3œ¡ÞsÄ{Ô9ÇŸ£úúú”«’k@)¥lÛVÀ¨×IJ- …‚¾Xúw=¯ëº ˆßOv·õvuó'n6¬cÚQ*•Ôcß~L©QvÿÞîÕ'ºÖv ¡T!Ôç¨6HÞ«7ª=¨J=¸èAUq+ú¦ÊªäAÐPú&k*¥ J=½ìiõ©YŸR×/º^åÈ©{æß£oàôM+7e.Ê'ŸF´¯¡ëøåô_ê:›QÙ(oC—óý3¿¯Â|¨óÔ”>¿µ( Jýò”_¶NÊ%¥ gêk»ò¥þþ?ºA@ØÕ¹`°µPMÕ”¥,¥”R}ªO5G{ÁL2Lõ÷yoÌår±ÜhOC Ff˜ yWC½æûï‹^³ªùóMÊq”*”êëÓß–¥Ô¼yw)˲”ëîúB5ŒôÊ`‚`w¬ FeñØÕÕÅ%—\ÂÕW_Í‚ õxà 7põÕW³bÅŠA¾ŽCÅŠÜU„aÈÎ3ÏÄfï¹Dë±îkwŸA¬%Q,c9â*´^¯S­Vc·Fƒz½N†är¹ØåhZ“Zb¶£X,Æ®<ÅÝ©çy‹EjµZ\h·¥FƒL&C­V‹­øz{{i4‹Er¹¹\×uqgH× { +´æwÚÌ]Ü ¤}é<c|ˆm ||í’öÞ'€Ãí&M”öf¬¼tlÑ4Òq:s¹\Ëý*ȵZL&ß›¥R‰z½»2ÞÓJQ³Ë8ÃÚw±»Ö^ls§üN¼ëX¨ou²dÍÖ=úrž{Ùþ-1'–¡ €ÄÕ©…6œÉFý±IâHzh Èmi'Ö}ârU, Å¢1OÓR,#-´Qäy2vmŸ#q³Úk’X?¢2ƒTZ;JSŽÒK™>‰»X'*³<òÓŸòÙ3Ï$tþ¥ÙäþžrQ™~Ô¾ Ê+nsÅ‘¨m6ÚS¬‰òŠ•d9ª3KbÙYB[•Šå¤X@–¢4¹h%¯ŒwúšªGå§c…ÊšUÆ&HµK¬DÛ¯ËrTF5ú-çÁÎ9sÏ_t{cžÔ–}hqtW¯C6 Á=`w«Á~Nv>ý"‹ÙÓþìSlœÿiŽÿv>V¨´„;øbá‹ñ31=ÃHˆ€‘z4iGiŒ.Æ’ßq<ϵû¹“ßwòˆÒ ¶–«7—ãî:®óÔkÊ`«˜9¯žÃœÕsèéîÁysd S¼øCö|ªçS¸G¹||ÉÇéÚ¯ ¾Dç…I§åZÊŒþßzÿM¿£È$×–î<Θ?›?Ã?C畉 ûApÏÛ~ÿ§1íDÀî\HìFãRÕÀ`òa,sX<î)ïaíp1®V öv'w xɽGð›3~Ã)¾Oñ=ð7tá8úÁ¶µ qîÜù‹•؃¡ÁTƨˆGÐî"×®]Ëå—_ÎM7ÝÄÒ¥Kã›zÕªU¬ZµŠµkײtéRV®\9ÞýA°Ù¶;ÆáÙSHÇF”mqû).J%µã8q|ÀF£A†äóyFœç–oÞ‚Wõxæ™gpl'ëh‰R  ž×*LÒRâ‹W­VÉf³Ôëõ8c6›¥P(ÏçÉårôõõÅnUÇ!—ËaÛvÜŸþþ~€– º{Ë/þ`ïúG…ÁW‰tq"úð›dðSÿrâ³'r˜{výËÀð}§É÷µëÕ=×Qî;¹‡òù<•Je€0Rb‘æóù8Ž©ã8T«U\×% ÃØ%Œ¸5☣Ñ’7 ÏóðÜòvf[½Y„6‡§çžÄYßÞŸ÷}trÇÝ{kj[zœ–a§I«t¬J!#-ZåãµT>!1¡ÕeešÐ‘t‰Qq¯*u²mõˆSÌ´(¨BB¼5IÈÔ°ú÷¿çGMÙ¶! ùpÛL u ±((µ•/.Ty´ÆblosOÔ¾>’8عT=àD$Tzìƒ À¯Vé/•Z–žçQMÍÍéôûï¿?Å…š-Hâ Q+s>ÕÞ_œ|2ozá¦2îBÇ{—1‹šxÌö@ö6(À¹–ÿ·ôoföì9üú×ßfðºE‹â1í$¬L %¤Àd„<¿ÇC¡p÷m$‰,­°æWG&”–µUì¨ì`¾;Ôí…ÎQw®CEXfÐ q³j``0õà ß+G«4HÌsQˆsÐkÝtˆ;:¾7e—­øË_ÿ5Ç<³¿~A¸z+¹œ&ƒ@¯©‚Î<󗨶½O®• v£&»ºº¸öÚk¹ú꫹á†XµjW_ñX°`—\rÉ„&A¿n=öØ=#@¬Óª–îéØ$Þù(Ö§-6|kwm¹‹³¾qïºü]œ·õ<à w¼ç0‡™Kg¢¶*~þšŸsÄgŽà…«^`ñ¹‹ùøôs†wÿæ`úÿ¼Ÿã?t<Ç[ÇëÕJ†‰a (—Ë”ËåØêI&?±°”˜ŠF#&3$&¡“BÄ"pjÕÑ«.¯m¿¨ò{©ß¢ÂŸ%‘¤y$Ò‰ Ð$Až@K.3$æ#ajè•§õKV£¢µÜŽ´Ô #BàÓ}ìl6³ªUìãÄíÖ ‡žèï׋‡=MB8¥~ Ü‚–浿!GþÎÜÐ¥æÖ¨RI!0‚  P(`Y™L†l6[+¹– 6dû³zõâEuˆIAšü’ñð£zKè• ©mY ‰Š–ŒCBÌB«·^´©€K²ê’|â#ÌA¯¬D5,C¢&$^ƒÄ§Yû¼/fŶýÙ¨^‡6 jQ‰Ê®ÒJv¶ç«Dm¢t ’• X16hõ{ÚD"¤U¢%¤«,ŽêÉ’¬RbÚ mˆÎÇß<ô7#½Ò÷IÈðõêsÈ ‡pðŽP­Rw´í [–½;!Dškb¹×ÓÓƒeY±‹ä\.Gù†2\¬­[d¿pÍfÇqb‹dÛ¶c‹dЂ•J%¶b¡¹ïû‹Å˜ÈRÒq2™ŒZÛvìþ¹V«Q.—ã¹CˆÒ¾¾¾˜È ÃR©D.—‹ç™F£ã8±…f.—‹-¨}ß­!Å屈BX:ŽÓB8™*¤¨õEè/ù¤O¥J…Góæ÷%g0 °9²Gò`Ì|ú^2‡çú^ e˜öMY{ qŸ8Ö—¤ÞÞ^šÍæˆÊ ‚ E9JP¯×[¬¡…¤©V«±%vz>¥±—º?tÝuðÜszž<Ïò¬x’uhB¥^¯Çó¢lg³ÙXY£§§'^Gɘ¥û sž´MÊ‘ëk±×÷a’ÍfY¼x1¹\.&Ëå2µZ-žãŃ…(’d2|ß'›ÍR­V©T´KŸ…W\Áñ‡ÂŒ5køÁG?Š¿p!Yσçž#¼ã2ÿ÷¸®“–‹^|‘#?ó™ñ¾üÆ Gv´­–´ÁGõòêºg¶ª|ñ‹K9úè¸üò÷ñ‘_dÝ¡‡r~ÆF8›á®öpi&Ú•÷E G<Êœ1Ò¹R愉¨ùî8z­;Iyð=‚*UC:LAl˜1`L®ÐGP©ßB&ÖÑâ! ½> Ñb+-Šò¢ßA”FÖ"ŽiQû~;SDz´Ú3ÈúHÜù‹˜+`jzÚ:þrÎv×Q®…}a½9‘öZ²…-0 (¨ÿõb¬èE@dˆ® wß½Û>a¼›m`0!0fâQ0™ÈFçyP(ð×ûí7²‰YÈ6DŨHBtyÄclyçÃÆî4Ã&nÉågÕŸQüY‘‹‹9ìû‡Q­V™Ç<6¼{ó?¦U?Ö1ƒÅÁÐ~†;æèö9U‡Ë—\NÁ)`Wl¶}i3›©Ûµ¿Ïîƒ<œB¢^%*òbh$Á• Ñ6èOžVßgVªm²2Ä•8±—UŽ|Š%Kê\pA>»Ÿ=ôß}òI<Û »6|†±CýI?3‹Q鮫?‘eíxc_….¯9»¢h0aYÐhŒ½œ}uêøøãæfµÝ’Vbº‹…}:<ƒÁÔEz2ÚÉ3 e1¡æû>¿ýíoÇ»{ã ‰ï¸7‰ÇNw´ÄoCÕHlÒ«õt<ñ´ÎºèðW(âò£²2©}yZÅ’§œjƒŽ¢;_‹Ž‹(OÜü ¡éÒ;]ˆT!ðD (mJÛ!Nƒ@×íyúw6«ë´ìÝh0"6 uÛ$ðÎ!z„I`is.‰#µü]ŸôCÊI{~)—ËñzFÖ+Åb‘z½N¡P X,R©Tð‰Þ¿hB4ŠKØ´ÒV'‹?!O‹©ã¯<=6y:C¢3 ‰ZHå•vˆå¦Gâ”LVErdI,HËÑwÄ"5“J/¤¡ŒMšÔtÚb²ŒµŒ¥GÕŠ‹\Rå‰Í„8¥âÒ¡•x¢X¢ ©,ã"e/N½8‚»‹U\€Á@¼ä ZÖˆ–¥—l¹œ^z:N@—Q~70ˆ1¥‰ÇŸÍ™Ãa?Œµpa²STXäI›VI©‘¨â F<¥Ö•år9¶öáN©TŠtµZ­EP#_ðî ÞwÍû˜mÍNvÔRå©3Ò–yíH»ÿµÙðH·1mih0å°•»ßæ©Gž‚S‰¹\z,×"TByIJxÜþ¢3×\–eÅBxùÞ£±Y'–-[ÆÿlßÎøã}—^zé¨-ÛöE<lÂ'`:ÏsØwŸæ€W4QëOˆeÛ@±KA¥(ÈcõêÕÍ E°$ÄŸ¸,•mqu ÄnFë‘ËÐR©‡âŽYÈNQ´j·Hìíí¦i²°X,Æž”#ƒb‰˜¶ôK»{L[¦…xµZ-Ž9ëû>.pÄGptÊb<=ߦÔ!ûG3wÊ8ŠÛÖNâáÖ~£]ŠÀ³}| ZೌÔ1ò_¶sû¸®Ç½÷®âýïÿ‘&=/6<Þh#Š¥ôðÃzñË%„R‹¥1اŸ§ŸÞª-ןmwöw™Í&„“ŽiGµ ùüàþá»»u{ÒeFë˜Ð”6—Jšü%ù+ÝG9æyº~9®TkÝÓ¦µþv]m^ºÜl6)#­í%ý,—ußlÒ×o¹œ“ííX‰ï"ï6Æ¥XH˜vwëö„¡– µ“ÀRfª˲ ·Wç’0=¾ù<ß¾õÖ¤Ýéñ•¼‚þþ¤ï–¥ÇE$Zù|2F½½z_|µ”)ĶŒ»ôÓ²’4¥Òä{¸íAøø¸»„%†9Mâ‰0¯Z­ÆRH„zir3h‰ý˜bvRÈè4¯;}z‹à¥§œ²×ÏO¹\Fµ2{ bÙPK!p–^,špÕ’çøÅ5'óÓŸv'ךƒa?LD¸”µí„ll]Ÿ&eB)í‚+ŒÁ&¡f“ØO|§µE_ßàVBF ÙÖÞvéS$êÜ‚4)*Äå`å··Íu¢¬S>ÇÑŸR)i[¢!V© ´L”>ƒ&ÞÚua˜žím­×u;ûú–ÙlBOÔë¼uÆX`ÙBwzö üã¬Y÷£±BˆPIÛ×§ÇÎîðIQ»eg­ÖL¨Bªú¾®'=¿öõ%¿»f¦0<< £p¸+±Ñ…\e‰C..¶Ó!Òϱ4±åû>•J%~Þ¥jäyÛîÒ[¾ …Õj•f³¿¤• ÅÅyµZ¥V«áº.Åb1&Jåy,®×Øã(å"«_iwÚ»KÚÚNòKŸåy$£´_ÈA!Î$Þ²´WÖ¹¢°Ôh4¨×ë±õ§(xJìæ´+u©3M؉%¢ôQÊ2XÐÛÛ $^„`l6›qÌ{Y[µ¯gÄ…zÚëœñdãºnL2 *çGÃ$ †­r5›Í¸lyç”õž\BHf³Ùk2¹®:aÕªU¬Zµj|oÄqÂý 0acòNDØhGböË ¾}$Ó.HÛm:Úm³Ø ’¿D+ØiVßUgd£y޾NG©êtGÚÃäéxÀÀq´HœšÁàX¬ÆaúÎOÀm´“¥à 7&ér¹\¼F¯V«„aH___¼ÎîþÁuÝ–µ³Ô%kïö5…ïû-ŠT²nñ}?¶l‡ôIÎ_úí®=MLK{ÛÉDy÷09,À7ÔŒlR_óüšx_£¡—uõº^–Ý}÷¼îu9n¼ñ:.»Ì¸ª50€)L<€š[ã—|“5ÂçBÊ—•ÉýeŽ`A _8´½ýe^aR.—©Õj±/ýÞÞÞØ²1 C:Œ/¶À"èºû NøÌɱG¼¢…+n‘ÒÅbÁ“Íf§”»–‰Ñpa€€IDAT€×H"ta†Œ$V$Âqk%Ç弦cÇI´knÛ¶+¥ˆ&²hHçr¹–˜›¢Þh4âX éß•J×ucË1q5%B:¤ÉR‰Vz¡Pà‡?üá”u¥Ô>`tÃ̵aþéñ‘‰rû‹EÊå2ýýý±Û-¤‰».ß÷c·¤bõvé¾aÃn¹å¶{Ûc‚Z¡ib³V«Å×M:äI ‰Õ8\|Ú=‰o¼‘*zY··1žk>qÏ7Õb€ >„ ·àß!/=ûÑ¡ šö¸z»Š6w¬#†m'.8G{O‰ÅÛh®‹bQçm °¡¬3‡ƒïë¾G<†0Lê J%¨V™ûŠWìR 47íÖuÚ4MˆŽ¦ âËk4yÅìDy M@øø#Ší(„˜d–eÅk²‘¸9Ýp]·Å¢^¼×É¥©çy”J¥˜ l÷$n¿mÛ1±'ωí,ï=Ö¾éüíD*ÐÑ _ÖÆ#…¬™Óu ¶ÎH{LHËeÒûÛ1ÙF…Œ5r§]Ñ۶c ub``°ïá |fn{/pg¼/“ÑQÄâñ'?ù ú3¦ùc,îÞ &"¦,ñøýçÖÀAy*TÈzYÂÞ⟊,^ ãw²J”ð-g„Á Å-  y‡ryg``0¾°þÏâtâ™cŽaZciWoW¹çEsX^REËŒ¢ÁD€'íçB„ƒ} vEÀ(hw=ÙS®]SY¾¥îöüí®‘ÒqcÒ¿å;­®O~{ì±SÖ•Rg„œö{›`ð«ûyê©eãf’ ‚rÊzB¬bA_+â>L,sŲMâ3J¬!¹.^úÒ—òº×½µ]u$£ÒD8$×ÓXIÃz½>®Äãý÷ß?}ú¸Õ?ž0¤ãàðÐJ%.€;ÿTáœ/P#dÅ—.:³ïﺵc:oOÏÀ˜ˆ#ÅXÎihII6;zâRÜ—Ž–¸tÝÑ×=âQÖ£}7ËåtûG›_¬hF›?r-»°ÝT«štMÞ)Ÿáßû}ß§··7¶ÞÅŽöµØxAžßƒ‘fi×èí–„ƒµ½]–!ÊníùÆ»ï­/,Fµkxâ‰'Æ»  !ð'åó¯>–u eaÛq™f/»ì\wÉx7×À`BaÊ•WÀ“'›—ƒùä½_¿ÁäÀ;î\ÔÃ϶ü;Ï=öí¡Ó‹åÙhï—z}l–gù bù6Ú¶ÛöÀ˜ƒ»š´nì¤Ïž7ºö§cGŽ£µ8”¼c™Ó1"GÓ÷bqôc7iñ˜Ïçãø{i¯ûî?ø`Ž|üqcíh``Ц…¼ïk¯äg>ïO¿ÂW«UÖ¬©3>þu &.¦,ñøðìŸ0wõ»ántLÇÔ;C–, ØØxxäÉÇÇrä°±ññ)PÀÆæC_þßüÀ7)—ËqL-ób`0ñ±í”û¸ ›â—瓽LËbF ÏóâjÄ1˜X0: F‚Û ‹Ò½•Û^äjïÍXV ìùC{lF va*–Ób5!ÖõzÛ¶i4q|Òl6ÛÑuf»»°\.»X¼x1¹\Ž.m0˜à°±ï¾ß\Þͼyï>ËXˆ7ÁXîAÛ=ùÕ)îßÞª[ò§ÖO£jÿhɳݡüÐ×7úsçyckÃh­L¡5®¤AGƒ*×ëõØ}¹yÏ7˜ ‹GC¢íž|òIÆ´ZôвÅôT¢c=9è—Ó:ÚÕ‚í«Gû³Ñ·¥'Úö¢ô’_Ê$ÚçEé%ÐÖ¦P¶Ý(MÕo§Ê•6Jý^ª ÙTÝntLÚ/ðSmê„ Õkˆt!Ëžq),ë£ç¯þ*Þ+®V³600S’xôñya¿MØ?™ ßC?ˆÛæñ«,D£MHH‘"=ôèÄ€¹Ûæ2ã›3xåK_É…Ï_È󳟧L™¹8PýH]¶ìy<±Õgæoó¯(' w4Rˆkeqµd¬ &/¶ÎWËœqÐë¹ú—o¦ÖÐVлëÖ®V«-ä[½^o‰¿Y¯×cKê ÈårÔëujµÚ€øKÐéXúH\´žöÁÓÆ{¸÷:f̘Á¢E‹øÊý÷wS &´a³}R¬=¶•óÏßøŒ®;6òͲƖ?›å8£Ï?Ö¾‹ÅäXòVî8cw5:Vòr¬c7Úú-kì×Ý>-JÅÒ±T*Á¢Á>Œ7<õ›n¿¹ƒÝçšÀ²Î"!ýìè˜o6ġڪh™£¤uSûê@¨Dßaª.уð£O)J“F6JëGí±¢ßaÔ+ÚN“†Õ(Ÿ‹ibRúT%!!…Lí¾] ÓÖŽBToÚà«ý–i5Ýv+J×åkDe¦ÉÕt™…TÛ ‘ß–€bªõ(Œƒ›êƒ”)cÕ~šei¶Õ‘ÞgD>S‰dã¿ë¬ùïålÞ|'žøàÈ2g³#K× bµ7–ücÁX畱ä·í±[{NV÷é®;z7³ Çm,coÙh$ã& bQœO+V@“`.‰µ L'ƒËEi‘&½$º3ÊIçëëp¼}IÓÉQIj{°Õù¨ï^TF…„¬k/3ŒŽ•´Q,1eÛOm 1¦Ê¢U>RŸ”¤ÊÐdgú• µ;dp’´FB¶6Ñ×BÚ²5‹&=å¼»$„¨À(_•'Ë@!–è#ׄ®aêwšØ¸šj{>5FrÜ'!ÝT½ésŸ&o#Òùì»ÏÆ@à1ëøáÍ?äo?þ·zOÛ8Z–eÂûtÀ”$ÿpù‹_£'ÙQ¼ûú¾ë¸ä?’Ç‹fœF¥;Ãå›|3NÄ®Y==ýÚÒÕI›FúÈyÓA“‰ésÑIäªH½&­ä¥B|JßÄòR D«¸È•~Ri…¸M¡2^i‹Ð íXÚŠÓé¯ýZÒV<J:W{nÆs$˜µ`hê@Þë Z1%‰Ç5øü‡^N¸ï¸h×ó‡aHoo/}}}±€p0ÿùbèDcA™2cÐŽ600Hð"¼øü‹Ì;Ð è#‘çT«UŠÅ"…Bl6Çf300˜¼xä€f¾r9~•­°yó c3HJò,Ç¡Z­Æ±³Ù,ù|žþþ~*•ŠyQÙƒhx…eËÆ»OìØÀËŸ}ùÏaYÙó;ÎØâŽã-Œ«›ØÉбZkŽõ¼Mæ±ÛÃEà–}¾O±2Ád‚±¾‚ `áõ õ>‹3£û?2¤]œNt´“s»’gW§éÛ0=.®)‹ÖXŸÆq(ëÔ‘\§ÊLç‹db¿¼è—\À»ÐÑ}ö¯ìÃaÛn•A@h¼ë À~ãÝ€ñÀÃøÌ~R±º¸zX7« ÊsW]ŬsÎÁµ,JÙì@Bµ Å"ÔëZz9í^W­cÇ“s|f÷ÿ' Ý„mü­V«8ŽƒçyضMaw˜CŒ+ßrÀö—ƒm³zu7]]]øþè ’:)#ȼ–eQ(°m›Fklw[6‡©ªÄ´º»{¼›`0Á°˜ûœÍÓG_Ì5û¿òïÞ¼÷*oòÏÀÀ FHØbñX­Vééé‰]¢L68Žc®ÝQ æß8?!b²h™FocdpRƒ]‡Ä£âÑ` k{×ÇÇ1Þ :`Êâ²tÉí¯gYmÚïå2d20mš&ÑÚc¹\Ž5Ÿü$38zzô§=fG±¨™ŒjU—Ón:Q,êr/ÖÛ½½ëÏdô±|ûsß‹ÛÃ÷5áéyºŽvæ$t¹™Œn§¸"’_>´4vÅìCÚd0qàûÉù#¾¯`ë!‹Ÿl²è϶’Íjùßp ÍaR*•¨Õj1a```0ù±í€®iNäÕ#Ÿ×ÕhÞÒÄc†±µ„X<¦_HÌËÉÞ…±z4è„—>8¯yòóüXý9Îòã݃q‚’òÖëu …B›ÙÀÀ`ê ÿŸû'‡ÅÞDEeìELiøh«QC9ÞÝ­Ëi‡“OµÚz¼ZMÚ’Éè2³2µÓñtÚQ,&„¯|Ò2WÆKHÝÁê‘têR8“Ø_ßo-£··3¹þtª'“Ñ礷·3>A±'ç´W5flÚŸ[o}; oס”Bëõ:ÝÝÝôööíÑI‡ÞH &öìš@ã‰C|ŽØ¬_.|A0úlõz=ŽéX,)—Ëôôô`Y•JŸl'<ðÀã݃1b°¹`,óÀ3 oó\Þ}Ü7ɾwÖxwÓÀÀ`ì©5A»W!ÏóÌóÚ`Òc_&Î÷Ô\#Ǽ[æÜõ¦Á@½Ê±ÁA“·†ü{TfA>Óvn÷yžÍŠˆß²,jµÚhŠ70Øç1áb<^}õÕ¬]»¶ã±+¯¼’n¸•+W²`Á®¼òJ.½ôR~ðƒìb-.×p ùÚW‡N–Ë!¦PõzÞ7¾‘J¥»H‹É‡±úÎjAØvÌ%CŽ"<œÕU.—̆¹ÜÀ¶º®&?‡kŸã$„U;é2’2d,…Hí„ö¾´·Õq4é'qq"B¶Å$Eö‰êI.•Jk™ÙlRv§¶´×ÛéüÊ>×ÕõwÊ“Ë%åfÕbÛɘ´K¸-«5Ÿe {Ûnµ`ìTãè1H·ñ¶Û˜ÈØãóÀV`:lÿíNX6²[¸Z­’ËåÆ%›‡‡kVž» ÷Ý`òbOÏueÒ£;0r…ú@OÉ»ªc VÑÝÝÝ4›Í8¾Ž`ŽVww³¾¿Û(LZ 6ŒuØŒÏa¿Ók§Wj)Ö«wW Áž^HŒÇz½Çf600˜xØSsÁc=¦ç[+#XX„ÑßPt#AHÇ”µ°ðñ ±£?Q‚pp„F<‚ôq9&åË>ÙNËÒi$ôc0ÑŸ‹ÛR~ú˜=`¼,¬8ô[úìàÄ}÷ñ±±ã6ñøÈØHíãíá ›tÒf‘£ÚL ;Ciû`cšN'íLCÚœçt-rÝè· ¯«jæ’ëÂ` öwàÙƒŸæ†E‹XA"ŽQsµZÅ÷}ãÍÀ & ñxà 7pù嗙榛nbÅŠ¬X±€/~ñ‹¸®ËM7ÝÄ[Þò–Õó?ÑÃùvï³­ZLÕªþ4Sbê”…¢ã8±COOýýýã2NÖ€Ôˆ1Z‚T^ºÆB¸¤_Ü+g¸ògx¿w2óþ´—9Üoh™ÚÛš,N—;” 9]F§t#©g$qÁ&‘¦ãÞš¼.½à Ïë¹P*•Z ööÖ\ðÝè™úÌ=wñíj•“O>ÙôÚÏó(‹8ŽÏ•Šñ94ž(,[†ïy¸cU3Øën.ë<ð /pð³±›ÌóÝÀ`‚bo¬ „d-@4ÊB{z.ذaÿQøüøT©8ž&:‘‚!ሆÛÉ«V×â±·§îXzß`ymlб¢¿áP¥‰ím¬Ž"Ř,Sn!"Û!Äešh¬R‰JÉ—n«ƒŸ/9i’TȾN䤴Aê”ïáÆLÊOÉòHÒ¦ör€¸¬8Í'П\\R ö®œ µnß?é$V IGmñØOµú²Ù,…Ba¼‡ÆÀ`BbÂË—/çÚk¯ࢋ.p|íÚµ¬_¿žåË—Çû,XÀÒ¥KY³f͈''pð-?Yxžve9„`0ŸÏcÛ6õzf³9n £í2BØöØ-Q ö:öÖ< Ë@5£¹ÙÁxoq¯\­VQÃYöìì­¹ Öl `<ºc>\ðž{îÄå+è4\×¥V«‘Ïç ‰1ÁàßpäRÆ1z.ØóÀæà%ÏîàE¾ŽëÁDÄÞX„„XXxž‡çyôõõ½áb1Ø{i$ÒKQ®Mža˜xñ´{0*u:ñ 亭/5A00œG{šj•ØÇüîP860ØCØÓsÁOû1÷u/oà 4hŒÜãP$÷¥ç ¼Ò¡{$–CZ¡^æŠtHœö{]îSxØxÞÀ:íetšÒëâ‘”áûIH#™ßÒí€4œZ«™tšv/_iDa“B‹B°¥¶ –E¸i,Z”‹Ûáìº;9·ésÜžD,Û›=Wv!ú%5–"Å!I穆½'3LÐõúС̰u,x×ÕѶúûûéééÁqr¹ÜÙ€Á",XÀ‚ =¾iÓ&€–É`Μ9ƒšW žzê)®¼òJ–/_΃+}^¶áDÖºN¬×5éX* iÞÍfq]— ŒÛƒI‹n¸›nº‰‡~x¼›Ò{rxøá‡õâäÚw`9Πžår™z½¾OÇÈ0˜z¸è¢‹Ø´iÇsÌx7¥#öÆš`Μ9„×^ËÚ™0ý…7rïocúæ.¶oÞ¸’øOi‚±··Çq( f­`0á±víZ®¼òJ~øá÷ÒDÁPsÁX×O>ù$¯¹u5‹þç/Y²dÆxwÕÀ`Üpå•W²víZž|òÉñnJGìé÷ƒŸüä'°f®‰çyär¹ØcÁˆQ­j¹‚„ CèîÖBîHxN©i‹ˆ|^³,7›m%…˜Œë11‘–YضÞ_­ê4íÒä€á;õM^ˆO»Êô<&F£õ^/±Óç?U†…5²22™Öù ­ö½Ûñ7x™–¤i³ÞÞ$ì” ]i~Ú´Öß…B똵ûû'¨íÞ’¾å-oaÅŠÚ^v¿§y¦5‡u6<:֮ϊ\×5ïþû®¼òJV­Z5æ5Á„!÷$;ì0Î9ç–/_οñSæ†'ñø‘÷ëƒÕªžp1‹.‹„a¿„LŸÍFÛÅ`´w4ƒ¦.\ȵ×^Ë7ñ8ùwgÐeMQ¾J¥b\.ìS¸öÚkYµjÕ ÁØ÷e¤×àñ>Ów*füç_6rydÄ£ïûø¾ëº‹E<Ï#*•Ê® , ö(Ι?Ÿ_w#& –.]ʵ×^Ë•W^9ÞMÌ›7?v½À]ϽŒ­[ß6ÞÍ107¬\¹`ʾý¾£ù¿`éÒ¥ñ;ÿ\Q…GhzZ¸›ÍB†Høõ:ØYm¢ó&ïÀ±|-€ÐÕ–,u"ç+ mŽŸCï÷ÐV.’&ë@¥¡÷g£ã~”&@©Îå’íô·%e9PhD’û(¿ŸJ[‚dsº-aÛ'@ïWªU¨Ý¾Pr¦ÒV€m@Ó‡¥¬‡|àÎnªÃb+!ý:Aˆ9éó%¤Gi²! añb½-ÄH¶Ê‚Ò„† -À÷}M¸nBê¶[¸n‡ô!—k%«ªÕ„t"#Ä’µXH4xž®C¬Ua á• !¹Óã%ã€ïóIÇaÕ9çLÙ÷ƒ3<ƒi÷·‘3r½ f ,²D!;Y 'CÌå†ñ0\š‘„é®# m”ž÷:¡TÚµvñ½«eT*ú#¤pûØ !ãméK½®Ç®“5¤ë¶Þû¬ÃP+jضnK§2šÍDIDƹ½¿r¯·“Ò€½à ˜w 4R÷s{; …Ö9³iØh´*T´—‘Ͷ\¿×^{-S‘J™¡À6Ïü'¬ŸÁÒÚn¹¬OÛ7®ãž{ª”ËeãÍ`ŸÃÊ•+w‹ÌpJi<Ïò'þ?fˆfó_ß÷©×ëd³Yc2m`°O!dç [@¯ÞÂ0Œ-™ éh0Ñ ñ$† 8Äq'$ÀÚ9kÙ:sëxwe dÁÆnúpø{W‘É Tˆí!=Ïò,r¹–eÒq⬛oæÅ™39äCÆ») þ ›9åùxÍk¦Ü+‘A 66aÆ E|̓ý]Møe߃〇³°¢¿uaÐzÀ… ,øVÔCp-À{’ OÛð4 ©èDÙ®FÇDVì£cB€&&% Qº<´„ +Dy<4QèDùíTºFªŒXÕ'íÚÊÈFõÄp é@OTn ½íJ :O•Ñ›*Ûˆˆ„OEcêE唣mrúÓUWò•¢ô¤ÊhFùê©þÄu”’öå£6öɘY€Òý.¥Ú¦Ç¸n%©®Õ/Û¸UºyE,F}ÉIš 8me£ôPH$'Õ~9G¹ˆD¬õ4q>A4^v”¦y!ª+‚†®CÚPιÊDÇ­(_–^¶‰U½SxØùÔN?èV`Y²s8Lãžxt Ù9Æ2îíDüpèôŽ—V(¬-ù°ÌUpðÁ@÷Ð}É7Vme<ûÝïŽ|l¦þ´snüž/ôÅ/âÈ#g4ƒ¡0éÞ²×®]ËÒ¥K[öµÿ Û9à™èŸÛ?lÚ0 Éf³ÊÅâ¨|„ìcë<>¼ð¶½bPE¸z½N±X4$ÂÑ)zûñö`ö0~¨|ÃÕ™&ã„h³°âX 6v\l $]'¤Þ <<,¬8˜}:ÝÞ‚ƒ³KÖð66ÁÒ€Ü=“[©fìs,z–†¯ ÀâsŸÓû†{wó#ÕjµJ½^§¯¯ÏÌóçÏç’K/å ƒÚ#å{x#Ž”&ÿw6ö.ω.n¬ žcÓón@0éÆ:l|ñv¾{ÅÇÆ»cÄXæ‚,Y|ß× DŸ‹,Þ^Õ§ÓÀ­ir¦Nb˜%!¸ô¿5d«-mƒl—â´¢Óò,o$!(;‰0ܶ2†[º¤Û!V’}©í&ÄË]?ÚçDõ©YhË/}±IÀNë.!S¶¾åµ£zì¨ n*Ÿ¤É¥ÒfSéÄ*Ô¡uLÒí°RiHm q—nK6uÌIÕéEûܨ/ŨM^ªVªœvøQ]‹Ü$MÐV¯ô?Ý^7•ÆïÐ)×I¥‹òo9v “c™ NúÓà-1D¢Á„‚ñz·ëØr‚4õ·aÛv‹á±x…‚vµj``Г†xÿÌkÖ¬i™,V­ZµËÁaßS{#3Î>]nqpððÆ^Á$Äî˜ä=ñð'÷cûöãñhÛ6ŽãPÎÈ$@z΂l0á÷`óË`‹]—¶v‚l8a½€ÒfHˆÅÁ1Ú-Aœ„¤­è/MR )9 íÆÅÅÇ[¶Ó䥇“–#­³ýÔ©S£¶KyW­ZŪ‡'§FóîZxÀ’->‡nzZu¾Ð¢¸:lÛ&—ËQ(&鸷˜Ò×¾_ëí$šì+Þ‘®u‚–9¨# ÿ¥{qºƒ¿èióˆVìéµÕPÄa»²C:­=@‘Aæ‘ÁÆ 2× *´x?¼iÕ›öhÿ÷vÇ<ðÍ“KüC©V‡7j000˜˜ë\pôÃG³’•|î{Ííû½*ex]nîð¼Â1ô23››õÎÞÄ®.]ìÔ·l§»:œØÄ$í`Ãe¥Òu*{$svníÁꮞ‘Ô™NÓN†æI,YÓ鲃䮽ƒµ=ýj"e—IÛÖö‡W= “óõ`ÌsÁ/ŽþwÞ¶ö©ÉsLìM…æÉŽÝÉñÛÓŒçiÕbè\*•öˆ`´ ø“†xŸî†nଳ΢««‹«¯¾š®®.Î:ë¬åËÆg¾Ì_–~ܼ½SúHë±â_\h{žVˆªV×ݶ­‹—p¥Òà–óƒ•/Ûü~ðAØ<ü[Ýv‹+p!Q$_:ötú¸ íJ\ÚÞÞeÛÖ}sݤ ÏK¶s9}\Ü¢·Ç9—°*AÒ§!!$H¯e%a"Òá$Ÿë #áºIÝi×å’?ôyÈçu[ í›;Ö€\.#‰É-®Ú%´Ã÷“2dœÅ=¼Äi—KÌó’1–v‹úX©¤¯“0LÆMòIÜnÛÖÛi¤Ëv§Ï¯Ä¸—ÐéôO>9y]‡Ž}ИìÇÓÛfu GP.—q]·ã°·áGi+@q¡)‰Ð|0Á÷`ä_š°“m!.+CˆÈá\€NTdÙ3÷†…Q»…§ìwF$U!M§Æ:fmz†c6ìY¯å´ÓZŸ_ƒ! CÇ¡§§‡\.Ge¤lå€Ü—iå!½e^iŸ_i2Læ¹×wU a°9"MŽ¥ ù´ËàNýIÃÅmIë=x ¼F—7Ø|×®@¶”v 5¯‰5u'±UäÞžCB2‘º~úãv¦Ûzå•WÂò½Ú¬Ý†±ÎógÍgGh  &;vÇšàØ›ofÏÂ'jðéQN ¹\çØZX 6Ç»!û.Æ2¼ì¾ûØpøáÌßÅ{Ø÷[åva˜ÈªD^‰l*›Md7Âqv s(a@K%ò3 ‘ÍIÙÆÀ4é}…‚~Çi—)¥Ó4›ÐÓÓz\ÂWŠÌ3]ç`õHút[ Ʋ’¾¥×^…B’Gö·ËiÒò@ÙNË;EîX¯ëzd[äs²OÎ×`§9-í$wLËu'‘îé”Âî’l}!€à·‹1#’ùJĶL&C£ÑÀÙÍÊ †x4Ø—0©ˆÇ•+Wrá…rÞyçÑÕÕÅúõëY¹r%]]]#ÊF>(=ñkž|Ýëâðàû>Ï=÷n\÷ôø¡hYúá–&ƒ„`òHòð+—u^‰c.—_ù¼N›~XË¢%ýÐ×ãÕ¨ôô$$˜,Hj5èíÕÛÿÚu5ÙdÛú¸Ô'íh4tž´kõ4Z($çz]—Q,&D$}­Võ"JˆL!℈•‡ý`gËJjƒÅENÇö–EG:OZ`ì8É¢#º}q'¿åœJ9Ò©¿ýY"c–ÎûgÛ­û¤žöô²°IÃu“T»0ܲôx ¡)ä³ôUÆ:ÝNYpþÏÿü8{D÷ÍDÃXçðÀyéK§*l¬T*‚t(Sn¢‹U\–l,Ä¡ùp„ië£=©H€ŒvÏ\zÉjùÙëØºõ´!ŸQ‚L&ƒïûär9Ƥ²v”£?™K„ØBªÌ+¹˜°*QàYÒ aØi>Ø·¤» îQ߃9âGläH·$ÖÙƒÁÆ&Çø¸5¶°¨Q‹Ïí¾æ²w̳fÞí’ÁÄÀî˜ î|êdÎÞúQøô±£oÈyw0˜ pHb-šW¦=‚±Ì‹ž~š‡/f~‡c"—Ëf™Z.§÷‰¢ºÈgDv#r%‘ÿ¥åKÙl«œ'-“yŽxbp-·“2$ ´zkPªUŽ%ûD††ZÔ.×êïOdvROºÍíèä!B©„œ¤ ;Ǿ¾¤¯òú$29‘™D4}NÒùƒ 9"“ßÛNˆS‘]Eú6›Éù–6¦ LFBÆ–JÛQ(è±MËj3™D~ :|d@¹ì‚j•E r9-Ï C]†È‰åÜÉõ5‘†ºž4),F“ÙXawÉ ¶FﺿÚðŽ Zï‰\.·ÛIGƒ} Ó”Rj¼±«XµJû~8þøãG4q\yå•,_¾œ?.ŽwPFMóô¤m‚‡íK^r' >E¸ñ‚ \N&a!Ó¿ƒi΄¡N›¶zËåôƒCH"Y ¤‰®vî®—z¼ãà 5 ÎbQçÉNÞçƒÁ^ÂE]ĵ×^;ÞÍvu~¿ëÚk9û…7ñ–käµ›ÈܹËÄ÷}Ÿžž&áôh`0b¬ZµŠU«V±råÊñnʘû»¾&X¾|9Ó˜Æ[¯ÈsÛ¿ä¸ä’eCzIóO£ÑQ¹#E† ¥ùö60سØk‚Ieñ(­`äzÚTnR­âºð¶·Íäæ›ßD¥’L๜ž\ÚãÄ·ÿLÉѲ¦í”¿S¾t™Á iÀĦ1˜Z‹€ôÍû<ÖÅAt³hQë±jµJµZÝí ƒ=ƒÑÎi§ /yêN:i޳lȰ.ÕjÛ¶) ÷ðžÀ˜r„£ÀóŸêûF=„!'œðçã݃݀ÑÎ÷üÏ=\3û®ýçÉM¼LpXèX‹FÑec4sÁÛ¿ým–/_Nµª­Ü -',´r¿‘» †Á”×Ú½§µ{×IçNÎqC\w À9ýZ*e UV§cé×#Ù¾è¢_“›xÜ=J•!/i¾ž?¡9ƒB!™&£ç#ƒ½II<Žs7wqˬSy]ô[\ ŠöÒW¾rÇw9APk!ü&Ê|bÜì<Ûó<ØßÅߨºßqr¹®1}00ا!Ñ ½ûzè•Cz (‹fn˜ì˜(‹9ƒ ƒuëŽâO:ËxG40˜â˜ý•Ù¼å%oÙUÜ»£ÿ4á!ÞÎ\×xC0˜8Ø“ár †‚ÏËž]Ãþ‡oà‰'æ·Ì ÆÍªÁð˜RÄã@צÅܸ䨘x¬V-í^íY‚ ;aûZlƒ½ Ø:+àAXÝ=@]­V ±``0e ‰Ç‡šÃ ½$ò<¬ñe>9!ÁJÌË¡Aüq¶m›5ÞÍ000g÷ûo¢?¬hÙ’p‘>‰÷¡ÎžˆÒéˆ} øÒZ´z_HÃò†©2ÂT>Ÿ!¥=6Ä~žÜ¶2ÃTš0*#l«§ìTùn”Þg| m—¾8©ñ²¢vvW+•WÒÉw2®é2ýTÝéòÚ¯;u,HÕ×^‡ÕV·JthC˜ú–üƒ¿Cëµ7¶í˜½x1KÖ®óyš¬¨×u¬<³d400yö™Û_ÇO´Fõ<`W‚’Na„„1q.ÛŽá7¦¦ñø0>;ÕËYÝý åP¢Í$æäåryR»P300Û4ñxe^` £eYFsÉÀ`Šàè °p‡‹·n®ûæŽi‚  ^¯S(ÌÜ0YQ¯kW«æü´açÎyÍk~ œ7ÞM100'ÌÜ:“™ÛײùéÔ:š¸éDìQ ªHi2(M&Úmù†‚ÍȈ¢‘b4ÒŒ4 &H“•NÔ¿bô»Ö!¿•Êï1Ø´RûZ 5'U†ìO‡"‚QÆš¶cícÙžŸ¶¼v‡¼ƒ•9Xkˆ4irWêè´Ïjû–cÒÏôyJ×=¬Û^xƒ¶oa ûòyâKS6TÆ8CÏ«>[8œ+Öqà ‹Zæ†Ü^ áD#ÝŸ´?òx%JôÒç QrphÒ¤L™b¼"èŒ,Y,,ªTsqi0¾á­‚øÞ’±´±Gß÷ ‚Àøj70˜"Pø<3ífΜ‰ãt~ö/^¼˲Èf³Æâq2#—3ñ  ¿眳h¼›a``0Ž˜÷èfaáã³iî&Ž;ü¸1µaJý„tmÜL÷ÆT#Â=-ƒÊd2d³YC:ìËX¿ ކƒ6.mÙ†á¤P:000Ø=v„l~f3ŽãÊIU*²Ù¬™&3,KÌúΠ A`±zu÷x7ÃÀÀ`¡ökR,•xÒ¶i2`4OŽVTÆ»{¿ýíÓÑÀÀ †¿s›»î–ñÞÓâ׿Öûƒ  R©ì‘M%J1q¶·Ü‘fÉR¥J…ʰN66eÊøøCZ,º¸±]{™BpæÉÇ$ÞPV†Y²-gš€ˆ¥^Új"SÈCãÞu×°jí*VÝ¿ Þ>ú2¦ñ¸ùŸžÕŠyǽ‡Ò§µµ£ X,â8ΤˆífnƒÑÃßö+–,¹ øv¼¿\.ãû>Æøšûìh½²g˜÷ûm¬Ûp9õ:´{Z¯V«A`HÇÉC8 ‚íÛçsÈ!/Œw3ÆiÃy{ð<Çq† ƒ ˆ¹‚ Àq|ßÇuÝ–2‚ h9žþ–:|ßDz¬–6†a»¼Ã0n÷`exž‡mÛq›:õQêI—ÝŽ0 ã~´ÿ–gDºÝRg§2¥Ò–ô˜ÊI™Òî0ŒPQYÕjµ¥Ütƒ{§ß’Wò?óÌ3{ïœ@XäÁTs9¾sï½Ø]]ãÝœ ³"2ØWqÿýsÒIãÝ ƒÎy{Ûæl՞ϟe]$üm½^oYîN8Ã:gßýpq©Rm±J Y²”)S 0,7‘%Ûb͘F)úm{ƒ±žx˜RÄ#€õÄ<¾ä½—f3‘Cù¾OµZ¥¿¿¼›7"ŒÇDd`°¯ þvîü«–ý{Ë?»ÁÄÁÖCîgÛ³!úÓË;Ær1ö”F÷Rc°ïÃq\V¬Ø{õ %s‹^ž§#‘Ù¶çy1A”Íf)‹4 2™ ¥R‰b±ˆëºT«U*• Õj•l6KµZÅuÝb϶í˜KïK×&îÊår\—RŠiÓ¦Ñh4èíí¥P(´y®ëR¯×c˶m,ËŠ1Åb‘f³»¢Êd2Ôj5òù<¹\Žr¹/•Jd2F|\27Çq¨×ëd³YÊå2Ùl–z½N¥R!“ÉÄeU*º»»©Õjq»¥Bä éfÛvLÔU«UJ¥ù|žJ¥B>Ÿ§¯¯žžžxLÕj•\.ÿÎd2T*•–±Ð×–Ÿk9‡½½½d³Ù¸Îôx÷÷÷(Sê ­^¯×[ˆH9‡ ÉÈZ­Ö2žÍf“b±÷KÆLÒI[äšxüñÇÇóv7<ªôöòîZmì…LZ|æ3÷³|ùòñn†AGì.÷‘#ǯfI<>›\êubå°Ú>´fÈ’%GnDFN.îˆHCÇSxܸöDV¯înQ~Ãf³9ÞM300Øxzny%óæ=Ú²»§§‡Z­fˆƒ©‚u0‹‡ùãÿmä/þâ\÷¨–ÃAP.—) £+ßÀÀ`ÂCb¾"„¢¨\.“ËåZÈžv«:!½ä; !“,ËŠÓ ©è8NìþÙqÇÁ¶mJ¥R‹•\.—‹I° Èår19æyµZ-&°díSŠHz¥TË·(gÊ|ØÛۋ뺱ҖX¦­ð$­x’²¤/RWûñZ­†eYqþ4A*}h4qŸÓy¥¬f³‰ã8-uÊ8ø¾O©T`QY*•âócÛvÓWÖ†J©ø<¥Ë–ï¡ؤ/âº[0ØxVæPz¤,9&eÈ;®|·{·ÝvÛH/ù} ÏmØ ¥‰ÃãèÕoãÁÈÐq´w YïïK¨ŒÐ‘ºûÿ³÷öñqT÷½ÿÛÆÆ6زǜƛ„0Âáš§élylhWÎm“&î…Ýš†¦ñÍnpZÒæî6nÒÞ¤ÒŸ“¦M#mC¸€¹;M‰•„j‹'£©plÐØÂÆ6ë÷ÇÌ™]­¤•VÒ>}ßzé%í<œ9çÌÌwÏœÏ|¿ßà§âÄE0ZGx¼ùƒ<å\0*n»eYE¯€¸Ù ÂÔ8>ÿi^~þ\Þð†UEË3™LC„Zaš8x½W=Þ»ˆëÅ¢£šD7MsÌÐ{‚ 4>%ºTE(ÏAÏóBïÄÎÎNúúúÂÏJÐSb`4ü§®ëär9<Ï÷ÙCÙµ¯Ôg5áQî刨¸ 1Jm«>O5Œté[ÞQt"¢ÂÛxíëóDû—ÛG¡ëzØ'å¶)׎èØP×õªÞp¯¤îãQͳª„ ŸÉ<Dß(ygÃËò#+†ÿrƒãþ×uÿ7pr&‘ð·’Høë]—pÞBmÝFíWZ†®RÏäqÔ±fº=¥ÇÑu¿œ‰Žãy£_.™è8ÑúwµÌ4ýãE¯Mƒx|âã¨ýJû°Òã”Ö/“tºúãäó+˜;w)Âô¢^ *¥4v¹åP…EyÓG#(ïxåÁ¯Âv—†T·m›D"zù§Ó颓Êí£¢ ¨ãDÿÆãñ¢0᪮ê9ʲ,R©TøB–ÚWEPˆ†Qî£">d2™Ð“?ºB½X5^ÝJûÝuÝ¢òs¹\øÒX4ºƒŠF «í·L&¶Oí}©)Á"Úç*‚…ŠT¡Îg42E.— ÓÓÓÃ3÷?Cû¦vbñ‰D"Ü'I£4RF:_~SõPט:g¶m‡cUa4—جíÿ5N­~ ¸ˆDGkéôL“Iý͵(´.-#<.\h|—õ|$ò<éyñx¼êÁÙFÞ„©q`™Ë项¬YsF¸,™LÊ`KZ w™Ÿ×maÿÇðJ-˶í–~¨Á'¦TMh©IåWêq×Õ5þ[ÃöÜ!ÍÌš5k&¼g£d³þ_Ãí(™É„L¦ è” `¥Ÿ=¯ *©ÿÕ_]÷ÿ/÷¨¢¶Sû)±Í0 ¢S!½L¡ÞŽSØOm¯i…ãŒu¼Ò:{S˜’(kÇ¢œGzTÈUǶ_]÷ã8~;TDÅÈr¤ê‡h£ýV®ýÑöD름æèùŒÖ‰îmƒêÿr}«ÖGÏkévÑu¥å—+k*çPðQ˜””¤Æ *tx4/¯ŠLP–¼³³“žžž0ävgg']]]a(s˲¹K%œE…$ è”øU*‚EÀ+sÒ£û”F€*}'ÊX‚jé6Þ8Z¹ý£/m‘J-«l•Ã8Úþh~åÒÜÕ¥õ(=®Š28QºOôóXõŽ– Ÿ®¶×u}Ô6Ë–-+ÚWíý?Ú®‰ê£Âã+a¹\¨ý·¿ýí´2?Çø›ËùŸÿs/pºííad A&fÎÈÈTÞõm,¶oßÎýö2þùÕßdÙÊàï¾r êyß²,²Ù,µ®fÅĈ’ë±Po€¸Œ~S±°Ë­«t;=\n` ¡áàðýÏ}Ÿ{ÿ×½µnþ¬ó±ßýÿç_CwCoÏ…±\.ð¡Uèíí¥··—­[·Öº*³ÊöíÛÙ¸q#xñ‹±’Ï¥ëÆeYáß^õB­›]SðXì­åÔœ9|ìc+ß«Xæar´ŒðøÊÉypò\Î8ãá2˲ÂxÞD<ø„©²%·ÞYëZÌ>¿Zò+à>^¸,úC„æcÞ ó8¤9,yúozÓóár.HB¬ Bk¢B™¹®;©Ð‹‚ ´¶íçÑk `I‚ L×uioo§¯¯¡¡!€0÷»„Kf3ø™MZuÎPñðË?cäÔV,>¬äåA˜ -#<žqôgZÁ…î6„IŒÍÛQ„êyÝ.üŠX,ÖP¡–A¨žy?y¼^ع¡(TŠã8d³Yy¨„Dy5 HÞgAhA<Ï ??£çù9ûT¾@×ëo<\×-Ê›¦>—æçÒu= ç¨Â4ªñˆ ëͽ¦þWT޹t:æ–‹†zT9ÖÔ>ñx<ôÞRÇQùèÇÁ0 œ ¹¡ª›*¿§§'Ü6šû üq”ʇÛÕÕÖ+‹‘ÉdŠBV–ÖËq‰Ùl¶èÊÛ,Úª^jŸt:Ö/úW¥Ó(Íu§Ú_«}ÆjÏLÖMmëº.¦i†ùK·ÿò—¿Ì9çœSëÛ±¦¨—м%¼¢ ´'^y…¶ÿz¯k —µ··‡9ÞA¨Œ–ŸÑñªçŽñ»¿{&àŠ§WsAš†_¾þõÀý,_ÿÀØO¥R2Á(-Æî×¾8à­'ÍÒét8É Bk‘ÍfDt„%†lÖ5ÍÁÿÿÕ¯>Ê‹/ÎÅ4²`Áy¼øâ÷°ís‹B2;Žƒiš¡0§^lT“”JxS9¤K…Çxu]'NÓÕÕU$Ш|XÑcE…0uÌèÿªŽê˜@XÕïÑ}âñxQ=MÓ ËÒu=ìWÕ÷º®‡Ï€ªnê¯*#šËKõƒaá¾êxÑãF÷‰§Üßè>Ñs4Þ>º®cš&Žã„çIEëP¹ÉÇ:NGGGX_Ã0Æ<ÆÛÞö6žyæ™Zß’5Eõ©ˆ ‚кX°Ÿ³F46½ï§À›ñ<|>?æw° å™3222RëJÌ4Û·oçÖ¾Ë ?»šüfø†—x B«¡&··þÖoñéoÝAÇŸ|šîŽŽúúúÄ-Ét$ŠnD¶oßβöv>úîóº›ÏãÉ/= NðÉÄÐjlß¾7²qãÆZWeV‰Ž…Òé4¦iÊý/´4­ø|ÐÛÛËwöÓÓs#]] L€çy¡¸ÓÑÑAOOäóùЃL cPÉ<Ïk¯¨\.z*ÏÆ¨W¦P_TznZùù`ãÆ|á _À4M‰~"´<­8&Ûý±œµ>ÆË_5ô>õ©+èììD×uÉý.´Ó1&hÇ_ÿ»%ÿ-7˲$6» ´ÿÕÖÀuó߆¦id2y8„ä+xyþ ¼n( ø“g*Ä¢ ­EGG©TJDGAhQÎ9çHQÎFõ"‚ AšÏç1 #ÌóÖ*ÂâDÄãñp>EMÄÊsUý"ç¦2 Ãñ€ ´:_`³è™¿àu¯[F6› CŠ ‚09Jxܾ};ÝÝÝlݺ•;v088ÈÍ7ß\Ѿ}/¿™3Ú–àº.¶mË› ‚РTcŽì}-dS|èCWËD£ 48ÕØ‚y‡žaî®·òÞ÷¾…l6K2™”J‚ЀTc€ð%$y.„ƦZ[àº.àÛ‚|>/cAhPª±k×®•ùAhªØÏ<ÀkNü^˜‡Y^R„©ÑPÂãÎ;Ù¼y3›7ofãÆÜvÛmô÷÷³sçÎ ÷ÕÎÏrÑ»¿æf7¡1©Æ¼ê…ƒÄ—X,&9H¡Á©ÆüüÅ#Ì}¢-ÌÅ”ÏçkÝA¦@5vüP2É(O5¶àù矧½½D"!©X¡Á©Æ¼ímo“1 4Õ>ÜÛ¾€ÍWžK6›%NËÜ¡ L‘†ûûûdãÆá²U«V±nÝ:vïÞ=áþ¿ýç¯ãš÷^†iš ùVsww7ýýýµ®FUô÷÷ÓÝÝ]ëjTÍöíÛk]…–¥Z;°dÉR©©Tªaßdn†ëOì™P-ÕÚ‚K´€+òíd³YlÛn¸‰f¹þšÁž5C•jíøaVíþ¯†f±“¥ïÓV:×ÕÚ‚sÎ9§åÒ°È=Ñ:´Ò¹žŽqA«ÑJׇ¢æ"¦B«œëjíÀ¾}û¸gÓCÌ9¶Œ³Ï~Ó4ééé©u³&E3œëf¸O›aܱoß>üñªÊ˜WëFTÊ‘#GŠŒÀÒ¥K+º¿ÿýïÓÛÛË@4s|188ȪU«j]ª8räȤsmÔ#nü™jíøaÕ2™LÃ¾ÍØ ןØ3¡ZªµÿýÍWóWõWü[ƒF@h–ë¯ìY3´¡Q™Ž1A«Ñ,¶c²´âõÐJçz:lA«y:Ê=Ñ:´Ò¹–qÁäiÅ~i†¹ˆ©Ð*çºZ;°ôLã˾ÀÊÿýîøö¬Y³¦áæ šá\7Ã}Ú ãŽcÇŽ1<<\U #|Çq¸ýöÛk]•)sâÄ Nœ8ÑðFðСC {:tˆçž{Ž%K–Ôº*5áé§ŸfåÊ•|ç;ßá'?ùI­«3%ùúSˆ=«=ýýýœ>}šÿþßÿ{­«2ëÌ™3‡/~ñ‹¼ôÒK|æ3Ÿ©uu¦D£_Šf°g܆£G²oß>^~ùe6oÞ\ëêÌ:ÇŽcÆ ,^¼˜ /¼°ÖÕ™šÅvL–F¾O§ÊdÎõ¾}û8zô(«W¯®uµgU«Vño|ƒžž.¼ðB/^\ë*Í rO´“9×­þ|ðñœ¹sç²nݺZWgÖhE[Ð sS¡ÒsÝês†ïfÞÆ ýŒËÞúVî¾ûnî¾ûîZWkR4Ã}Ý ÷i£;öíÛÇáÇyë[ßZU9-!<~ò“Ÿä“Ÿüd­«!BùÿøZWA„#cA€† ›$Âô³jÕ*|ðÁZWC„#Ï‚ üô§?­u¡©h˜ŠrJq+½‘$‚ØA|Ä‚ v@[ ‚ØAÄB}Ð0£ŠÏ\š ¶···áãþ ‚PbA±‚ ˆÁGl  ¶@±‚Po4Œð°yófº»»ÃÄ–·ß~;mmm\wÝuµ®š ³„ØA@l bAð[ ˆ-Aì€ ÔsFFFFj]‰Jæ#ùÃÃôµµ188ÈÖ­[Ù¼ys­«&Â,!v@[ ‚ØA|Ä‚b A; õDC ŠÞÞ^Ö¯_O[[[­«#B ; ˆ-Aì€ >b A±‚ ˆ„z !…GAAAAAAAꋆÊñ(‚ ‚ ‚ ‚ ‚ ‚ B}"£ ‚ ‚ ‚ ‚ ‚ ‚ U#£ ‚ ‚ ‚ ‚ ‚ ‚ U#£ ‚ ‚ ‚ ‚ ‚ ‚ U#£ ‚ ‚ ‚ ‚ ‚ ‚ U#Âc fÛ¶m\y啬]»Ó4Ù¹sç¨í¶oßnsóÍ73888©õ³Ùž+¯¼’ÞÞÞI·¡ÖíØ¹s'¦iVujÝ¡q©Ä4Òõ7–-h„6L‡-¨u„ÆdºÆ•n3íiÔ1Ll ¡ Bs2›c†z¼†gÚ¶Ô[›gËÕ[»…ñ™Í1C½^ÕØ‚F»'fk®¢žÚ,TÆlÎ)Öãõ!c‚Ö9×3M#µùúë¯oÈgìf˜÷ææ›ofíÚµ¬]»–믿žþþþI×±^®·Y™³jÆG>ò‘‘ŽŽŽ‘{î¹gd×®]#ŸûÜçF.¾øâ‘{î¹'ÜæsŸûÜHGGÇÈ7¿ùÍ‘]»v¼ÿýïyÿûß_ñúÙnÏÅ_<²k×®¢å•Ô±–í¸çž{F.¾øâ˲FvíÚ5rË-·Œ\|ñÅ#O?ýtôAhl&²vý•³Іé°µnƒÐ¸Lǘ Òmf«=8&™Ø4B„æe¶Æ õz Ϥm©·6Ï–-ª·v 3[c†z¾6¦j 힘­¹Šzj³P9³5§X¯×‡Œ ¦®¢ÞÚ=4R›-ËjØgìf˜÷TÇÛµk×È®]»F>þñtttŒ9r¤â:Öº ¥çd¦¯'kÄ‘#GF FFü‹øãÿxøù7~ã7F>÷¹Ï…ŸŸ~úé¢ý&Z?[X–5òþ÷¿¿ì[IkÙŽ÷¿ÿýEÇùøÇ?>òÍo~³aÚ 4.•Ø‚FºþƲІé°µnƒÐ˜Lט ÒmfšFŒŒLl ¡ Bs2›c†z¼†gÚ¶Ô[›gËÕ[»…ñ™Í1C½^ÕØ‚F»'fk®¢žÚ,TÆlÎ)Öãõ!c‚™™«¨·vÏÐæo~ó›#_|qøÛhÏØÍ0ï¹{÷î‘‹/¾xd÷îÝã¶«QlËlÍÙH¨Õ188ÈÆY·n]Ñòõë×3<< @¸bÕªU¬[·ŽÝ»wO¸~¶èïïDz,>ó™Ï”]7QkÙŽÁÁAúûû‹Ž pÛm·±yóæ†hƒÐØLd éúË4B¦ÃÔº Bã2c‚J·™iyLÛ‚FhƒÐ¼ÌÖ˜¡¯á™¶-õÖæÙ²EõÖnabfkÌP¯×F5¶ Ñî‰Ù𫍧6 •3[sŠõx}ȘÀgºç*ê­Ý³A£´yãÆìرƒ;vL© µng3Ì{¶µµqã7ŽjC”F±-³9g3oÖZ%±nݺQcxx˜{î¹'üâ8räÀ¨/—¥K—}錵~6æ–[n!‘H”½ù&jC¥ÛÌ*þðªU«Ø¶mƒƒƒ¬ZµŠÍ›7‡í©÷6ÍD¶ Q®¿ñlA#´a:lA=Ød¡1™Ž1A¥ÛÌ$>&€‰mA#´Ah^fkÌPo×ðlØ–zûŸ-[ToçZ˜˜Ù3ÔÛ=¡ÚY-¨¤MõtOÌÖ\E=žkabfkN±žî ÕFÌÌ\E½ëÙ QÚ¼jÕ*V­Z5å6ÔºÍ0ï¹jÕ*¶nÝ øÂÛ‘#GèîîfݺuaÁ¶Ìöœx<Ö ;wîäúë¯gÕªU$‰ZW§b,ËbéÒ¥Üxãµ®JU\ýõ´µµ±nÝ:ùÈG>RW_2Bë ¶ ¶ˆ-ê±µGlÐ4ª­˜,Íd[&‹Ø"a"ZÅ@ëÚ±B%´Š-hU;b „æ¡ÑíÕöíÛÙ²e ;wîäºë®£­­­ÖUª˜Ù¶¡âñXcÙ¶m½½½Üxã$‰†¹`{{{éîîæŽ;î¨uUª&‘HÝt¦iÒÝÝÍ­·ÞZëª -‚Ø‚ú@lPKÄÔcÙ‚k¯½¶ÖU„†¶“¥ÙlËd[$ŒE+Ùhm[ Ï'Âx´’-he;b „ƧYì•òÞìííeË–-´µµ…žæõL-l¨x<ÖþþþðÛ¶ÙºukÙ®Ü,Qw؉ÖϽ½½,]º”mÛ¶±e˶lÙ”ÿÉ´¡–íFˆk¯½6 gÐ(m—JlA=_•Ú‚znƒb:lA­Û 4&Ó5&¨t›é¦™Æ0±-h„6ÍÉlŽêážmÛRmŽ2[¶¨ÞÚ-ŒÏlŽêåÚ˜N[Ðh÷ÄlÍUÔS›…ʘÍ9Åz¸>dL0;sõÖîÙ Ú\ïç¶Ñç=U®Õ(7ndãÆôööNªŽõ>w[i+ÙF„ÇróÍ7sÝu×qÛm·•Õ¬bå–&æìííeÕªU®Ÿi6oÞÌ­·ÞÊ7Þþ\wÝuáÿ•Ô±–íX¿~}ÙcG¿¼ë½ Bã3ž-h„ëo"[Ðm˜[Pë6Mµc‚J·™)šaLÛ‚FhƒÐÜÌÆ˜¡ž®áÙ²-õÔf˜=[Toí*c6Æ õvmL‡-h´{b¶æ*ê©ÍÂä˜9Åzº>dL0³sõÖîÙ ÚÜ(ç¶Ñç=wîÜÉG>ò‘q·©wÛR‹9kDoo/ƒƒƒ¡2ý*Æ›7o¦»»›ááan¿ývÚÚÚ¸îºë*Z?“¨›&ú %V­´ŽµjG[[7ndûöíá±{{{Ù¹sgQ£znƒÐØTb êýú«ÄÔ{¦Ëˆ¦Ât *Ýf&h†1Tf ê½ Bó2›c†z¹†gÓ¶ÔK›avmQ=µ[˜˜Ù3ÔÓµ1]¶ ‘î‰Ùœ«¨—6 •3›sŠõr}Ș`æç*ê©Ý³E3´¹ÞÏm3Ì{^{íµ sûí·µ«··wÚÇ!3E-æl挌ŒŒÌxË„Qlß¾½èb²qãÆ0^ððð0ùÈG¦­­ÁÁA¶nݺØO´~¶Y»v-;vì(º`+©c-Û188ÈÍ7ßL?ëÖ­£¿¿Ÿo¼‘­[·6L„Æ¥[Ј×_©-h„6L‡-¨u„ÆdºÆ•n3[4â˜&¶Ð¡9™Í1C=_Ã3e[ê­Í³e‹ê­ÝÂøÌæ˜¡Þ¯©Ø‚F»'fk®¢žÚ,TÆlÎ)Öóõ!c‚髨·vÏÖæF|Æn–yÏîîn¶mÛF[[K—.epp°áç gúzá±APñ‚ׯ__6fûDëëJêXËv¨c¯ZµjLçzoƒÐÜ4Ãõ×m˜[Pë6ÍM#ÜGÍІ‰lA#´Ah]¦ëúl´kx:ÚTomž-[Toí¦‡f¼'¦£ÝvOÌÖ\E=µY˜^šíž˜Ž6OW¿Ô¢M3=WQoíž š¡ÍÍpnë½ ƒƒƒa˜ãfŸ3œŽs!£ ‚ ‚ ‚ ‚ ‚ ‚ U#9AAAAAAA¨AAAAAAA¨AAAAAAA¨AAAAAAA¨AAAAAAA¨AAAAAAA¨AAAAAAA¨AAAAAAA¨AAAAAAA¨AAAAAAA¨AAAAAAA¨AAAAAAA¨AAAAAAA¨š¦=ÏöíZWC¨ÏópgÚÊšÉk¶m<ϫɱ«¥Þë'íªÁq\× ?‹-(O=×MÚ&Ì“½.&3ÏLåØõÜ/D3·M¨ŒéL—-¨÷ë±Þë'íjm¦sž@•7Sch\[PÏu“¶ P-(¨òfêºhT;Ðõ“v Ӊ͔̎ê7Ò„äóù‘&mZ]]]#µ®Æ´3444ÇG€`Ä0Œ‘¾¾¾ªÊœékÉçó59vµÔ{ý¤]ãÓ¬v ZúúúFt]íˆiš#CCCb Æ žë&m« ±“c2×E*•1M³â²Ç³“=v=÷K£ÑÌmSˆ(Ït ¦ÓÔûõXïõ“vO³Ú‚™˜'™Ù1ÁÈHãÚ‚z®›´­2ÄŒf¬1ÁÈÈÌ^j¡~Ò®ñiV;0SÈœáØL¥~MéñØ*är¹Qoè4ét×ubdd]×Éf³µ®– Ô%Íjª¥³³“x<ÎÈÈCCC€o[¡Y[03ض-c¡a;Pžéˆ-‰fµµž'; 4b F#óB«Ñ¬v@h æÕºÓ…eY¸®‹¦i†Qv®ë˜¦‰mÛ$‰p½mÛ¡«h</Ú?N“J¥°, Ïó0 ƒx<^t¼T*5åíÇ#N“ÉdŠê¯ê­–år9LÓœT?$ t]¯h]%ëÇkG¥}ây–eÑ×ׇ¦iaLÔ'®ëbÛ6ñx<t˜¦Y¶o<Ï#›Í†ç{2ûN¦ŸË]ªžç¡i‰D"lk%׃¶m\×-º–£ç(ZÿJöU}RmÛkÉxý]?Y[PK; Ê+wÝÏ„˜hýlØJîÇñl*Cm¯®‡raXšÑŒeÆÛWÇf°õ{t}9[ c‚‰×U²~¼v̆-˜ì½\j Ô2591^èÔÉôué5Y‹1Áxû·’-1Aq?Àì &Û/ÝÏ35&ˆ.Ÿ[ ϵAÆõk ¦sž`¼~iö1A´í y>¨¼ß£ëdΰþŸª™3„ÊÇêXÊhšÖðó¥çHÆ2g8Q?A}Ž ª3luý`*c‚©Ú‚¦ðxìèèßP±m›ÎÎ΢S‘Ëåèìì o8€l6nïyEƒWµÞó¼p°‹ÅÂ/¦l6[ôvÌd·l6K2™ /†t:]Õ›8Éd2ì ×uéèèËo]%ë'jG¥}¢–©/Û¶Ñ4-¼èÇë×u±,‹öööðX±XlTŸ©åÊMfßJïzô<öööð‹*—Ë‹Å*îÇ(¶m]˱X¬h›ÎÎÎðZžh_`ZÚ^KÆëw¨ÎÔÒ¨í§ËTs¯Ï–¨ä~œ¨O4M+z€ˆ><+šÑŒg&Úß@u¶@Æõ5&¨ÆLæ^.g T;'+¦”c¬k²Vc‚Jöov[ cŸZ &Û/ÝÏ35&ˆöCµ¶@žjƒŒ *£ž&š'¯_š}L ÚEžŠ‘9ÃÊh„çƒjæ ¡²1:×Q[Ðèó c™3¬ŒFT;gØÊúAµc˜¤-¨u|ØjéêêÑ4­(^±Šõ=00þUèºÆäW룱ÀUy `¤««+ülÆH"‘?—ÆøŸìö㌤R©¢ºE÷5MsÜBQúúúFõ…iš#©TjÜuí[i;*퓞žž0κ®ë#º®hšž£ñúDÅÎd2Eë‘oûÛ#ÀÈÐÐШãO´¯Š÷>Qóùü¸×cô8Š¡¡¡Ó4+Š·]z»–^K¥å¤R©‘x<>á¾ãµ½Qâ€OÔïÕÚ‚ZÚUÞX×ýtÙ‰ÖϦ¨ä~œÈ>æóùMÓB¢ëzQ>§fµãÙñöm; êŸ¯úÍI ,G½`Ûö¤ÂÀ”k{£ÄŸ¨ß§ÃÔÒÀôØ‚jîõÙ´ЉîDZúÄó<Òé4¦iÒÕÕEWW𦽅Ӭ¶ •퀪ëTmŒ êoL ˜ª-¨dßr¶Àu]²Ù,]]]SîãhYc]“2&˜9fúù@ÆÕÛ©ôËx÷óLŒ ¦ËÈóAm1AeÔÚLç<ÁDý"c‚Ö³ª®2g81ò|PÍœa%c® Qç Ô9iU[ s†•Ñ(cE5ócíßìúAµv`¬¶e >ÇãXnñÀ„çºnQ\ZE#Æ©nLÓ$›Í¦T*E6› Ý‹'KÔP†iš$“I&µo%Œw=‚o8òù|è¶ïy‰DbZdTXe¸ªýÒªvÿÙd¢~[ÐTzMªè===á2]×éèèà×~í׀浭l :[ v q¨æº,Ý·œ-°, MÓÈårär9ÇÁu]Òéô¤Ã¬wMʘ`æçƒÖ ’벚1ÁtÙy>¨ 2&h.&š'˜Ê¹‘1ÁÔh$;2&h6ª™3oLHŸÌ\A£Ì@kÛ™3l ¦óš–9éõ[) /<êº>JQVCÓ´q‡a¡bÝ×qœ²IfÒ¾P BÇ[§”ë‰ÖOã]¬•Þ *éªú?Z÷®®.<Ï#—ËJ˜:Ѿ•0Þõ„ cÕÛUŽã‹Å0 £ª¾ÌårX–ÅÀÀ@h¸Òéô¤Þ¶¨¶íµd¢~[P¾_ ò{½’}g¢®S¹&£û)Ô}qàÀ 9mA«Û¨Î´’(í¨Ï1A´®S½.'Ú·œ-˜ÎÈñ®IÌò|P4&PÇœìuY͘`ºl<ÔTN#Ø‚™ž'LµßêTN#<Tc ÆD½uÆ›+hÄy[ s†•Óc‚h]«¹&[M?˜;0Ù¶7|¨Õx<^”è2úB<“ «uÑ„™¦iŽZ¦’6 •^؉DbT_$“ÉP1kÝDûN7†a ëzÑ[$ét]×+6æ¥Éd5MãŠ+®—©ÄÓÙlv”+p¹}'ó°1Þõ½©Lúí‚è9ˆ&wU7½2Êý¿’}˵]õy£¼½3Q¿7»-˜;0ÑúÙ´Š©Þ¥ç;º3Û‚JìÀXû–kw£Ù¨Î4ºPí©„F(ª¹+Ù·Ô˜¦I&“ ÕØ$“ÉL:´Éx×d-Çãí_ÚoÍf dLàÓhc˜š-¨fL0]¶@žjƒŒ šËÌÔ¨¤ß›ÙL—˜hýDvb&˜êýhFXWuÍ«kºtÐÓL¶ ;0ž-ht;PI¿g Ù@óŽ  ºû±Ò}DzÕ2Þ5YË1A+Ûø4Ú˜¦f ¦cLP-ò|PdLÐ|¶`6æ  ñÆ ÏSí÷f¨ú7ãóÁTmÁxc‚rDm ÅÚˆóª-2&9Ãf@õ÷c«éÕŽ T½'c 挌ŒŒLß)¯®ë†µzËE¹=«ÎÔu˲p]·(¦·ÚNu`£Ä©Ž¶o29F¢oñVº®’õ3ѶÉ˶mb±###¡:_éù¬fßñú9z=–sýX8ŽƒçycžóÒº«„ÇÊ…{¼}ËíßhŒÕïÍl ¦ÛL´~6ìÀtÝѺ¶’-ÏL´o¹ý‘jlA#ÚÒ¶5˘ ž¾×«e<[P‹1ÁTöoDZíù Ç0=÷óTÆÓ<Ô4-ˆ¶m2Çj…1ÈóÁD´Ú˜ ´}Íò|PÚ¶©«Uç ¢åʘ@æ +é'¨Ï1Aµ÷c=Í34âœa¹2Æ¢i„Çr(õ¹¯¯/Tc±©TjÆßȨ¡‹É\´Ó]^­ÚQ-Ñ›:÷vÖ[_6b ¦V^­ÚQͽ\-c[ì@sÐ ¶ YìÌÜ÷z½µ³ÇheZÁÌDyµjÔv\0[m¬Å1ZV°µ¼Žêé–10­`f¢¼Zµ£–Èœas#¶`jåÕªÕ~¯ÏÄ<ƒØò4|¨Õñˆº«)Êm´–ŒC7ÊdÞ ˜îòêý¸³Íl´³Uú²Vˆ-˜Zyõ~ÜÙDì@sÐ ¶@ìÀÌ"¶ ñi;0åÕûqg±ÍA+Ø‚Z^G­p ‹-h|ZÁÌDyõ~ÜÙFlAã#¶`jåÕûqg±åijGAAAAAAAf‡¹µ®€ ‚ ‚ ‚ ‚ ‚ ‚ ‚ ‚ ‚ ‚ ‚ ‚ ‚ T‚ ‚ ‚ ‚ ‚ ‚ ‚ T‚ ‚ ‚ ‚ ‚ ‚ ‚ T‚ ‚ ‚ ‚ ‚ ‚ ‚ T‚ ‚ ‚ ‚ ‚ ‚ ‚ T‚ ‚ ‚ ‚ ‚ ‚ ‚ TͼZW`6xàÈçó,X° ÖU™2/¼ð ,àÌ3ϬuU¦ÌK/½ÄÉ“'Y²dI­«RÏ=÷çž{n­«QgœqŸøÄ'j]YçóŸÿ<¯¼òJ­«QÍpý‰=«NžhÜ烩Њ¶ æ"¦ÂdÏu«ÎþéŸþ)Ë—/¯u5ª¢îëf¸O›aÜqôèQ:::x÷»ß=å2ZBx´m›+Vðú׿¾ÖU™2¹\ŽuëÖ5t}ôQúûûyÇ;ÞQëªTÅöíÛyï{ß[ëjTÅç?ÿù–Dôöö6|»›áú{V<úè£Ø¶Ýr Í0&h†ëšÃž5Cr¹»wïfãÆµ®Ê¬rçwò‡ø‡µ®Æ¬Ò,¶c²4Ã}:Y¦r®ÿþïÿ¾å„ÇÝ»w3<<,÷D ö¯2äù qŸ¦B+Ú‚f˜‹˜ “=×­:gxï½÷ò÷ÿ÷µ®FU4Ã}Ý ÷i3Œ;î¹çvìØ!ÂãDœy晼þõ¯oè •ÞÞÞ†oÀáǾ K—.mø6Ü~ûíµ®BMX¼xqß»f¸þÄžÕ‡®uff@s\Í`Ïš¡ ½½½µ®BMX¸paß»©Ð ¶c²4Ã}:&{®[õùàüóÏo¹ëCî‰Öa*çZžZ‡V´Í21Y&{®[uLpÆg4üµÑ ÷u³Ü§>îxôÑGyâ‰'ª*£%„Çf`ëÖ­µ®BÕlܸ±¡o8ÅŽ;j]¡…i†ëOì™ TG³\Í`Ïš¡ BëÐ,¶c²´â}ÚªçZ¨ ¹'Z‡V<×Bå´âõÑ sS¡ÏõTX·n]­«P5Íp®›á>m†qÇë_ÿúª_Fš[ëF‚ ‚ ‚ ‚ ‚ ‚ ‚Ðøˆð(‚ ‚ ‚ ‚ ‚ ‚ BÕˆð(‚ ‚ ‚ ‚ ‚ ‚ BÕˆð(‚ ‚ ‚ ‚ ‚ ‚ BÕˆð(‚ ‚ ‚ ‚ ‚ ‚ BÕÌ«u;w»{Ôò­[·²nݺðóöíÛéîîfxx˜k¯½–­[·²jÕªZW_„i@ì€  ¶@ŸJlØAhndL ˆ-AìÀtâZ­+!4=uãñ¸{÷nY·n]Ño[[[¸2[·neÇŽ róÍ7×ºê‚ LÍhrµ®€ 4 Íh A˜<Ù±‚ÐüȘ@[ ‚Ø©`±\æ*…Ù n<‡‡‡Ù¸q#[·ns›;w²yóf6oÞ Àm·Ý†išìܹ“k¯½¶ÖM¡JšÅØ€üï —l3ÖÛEn°Î¨u#¡†4‹-¡:&²b¡ù‘1  ¶@„ƶ ³zÜ…ùÉ(6”­‰=ÆöB}Ñ(«uãñ888Xô†B)ýýý ²qãÆpÙªU«X·n»wï®uõA˜šÅØø‚#ø_ê £lð /2ÙVíëMtAhršÅ‚PãÙ±‚ÐȘ@[ BcÛ§höojX“Ü>7ÉåÙÙì”)2V/6Bݧ‹NŠç›ÁßdÉòÉö=ÉíÇ¢n„ÇÝ»wÓÛÛËÚµkY»v-W^yeQÜæ#GŽ€¥K—Òßß_ëê ‚0 4“P_â.…/E›‚±w( ²‘mÜŠJ„榙l Sg<[ v@Z‚b Ah|;àNÃŒßdKðÊì3–pçD¶-Ý';Î>åê8¡\ÇrÊÈŽ±ÎcùXí«/Ç:®=FÙ2û¹c”oÑ7é1¶Oå&#å»A]rÁr7Ø.´5ÇŽ”›¦¸~¥mñ‚ß\°o’é¡n„ÇááaV­Z…mÛØ¶ÍæÍ›Ù¶m½½½U—ýÜsϱ}ûv¶oß^ëf BMéîîfË–-ìÛ·¯ÖU)ËLÚ€}ûö±eË–²É¨§ÂX_RÅFÜŽloE¶Q_Šê C-„™fË–-lß¾çž{®ÖU)ËlŒ ¶lÙRëf BMéïïgË–-Ü}÷ݵ®Ê˜Ì¤-8tèPh ¡•Q߉‡ªuUÊ2ÓÏwß}7[¶l©‹ IA¨%ò| Ï‚ s†Ó;ge:DG¿œ±­Rì1öËñ!*<&K–%º•Ñ¢Qàª!ê¤1QùªîJxSx@ŒòÞ¥âZŽ‚ÈG™uV¤L…ø¢ëÕr5ç[º½ª£`ÿlÉñÔr6R^:Ò¾¨¨˜Å÷‚Ô"å$ƒÿ“%u²)xL*³#RF6Xþ»Gò×­«êÖMŽÇ'žx¢èóÖ­[éíí¥»»{Ô› “åÜsÏå½ï}oÕåB££âœ×ë€z&íÀ…^ÈŽ;¦­¾ê‹­4þ¹¬‹þU_ô:…/ Â['Á7ø©iîWA(eÇŽôööNÛ}º‘1 Ì<ëÖ­cÇŽu-¼g TÞ–©²bÅŠiB£¢ò$µêóÁ;ßùÎqsE B« Ïò| 2g8½s†Q¼iJª¤æ YžÃÏÙÍÑõ^´ñçK—ë‘2ÔòRﻨÐݧ4Í”Ùf:„G+(3‡?Oš Ú¦DÄh›”ª"Í%(Ì¿ª9×,0üÕ)"•ø‡/½ €3üeZ¤ê˜¹à¸ª\Õv7òw,O5G¬þFÃS¢ ì¯ÇCv‘¿>êé©úC¶eeðÅÃh©k":íÛÙ‘ÏÙàØnP^îíoç-wÞYÕ9¬Çrlܸ‘ááá¢eåÞD\W¥ú*BýRov :TP_¥¨e¹Èöê“8þ—‰ÿE¨þ‡ése„f¤Þl µ¡Ôˆ„ÖCÆ‚ €ØAZÏD¢ƒ‚ˆ©<ü9T'R'¼ª)+‰/¸¥(ÌÃ*o>(•ÉHyÁܽ…¨JPÓ+ôòªLÇ6‚_/X®@-ø5‚m_ü\òˆ¿Ú_ýŸêÛ‡/üõlƒË~RØ6”ÛÙ ŸêóËÍPph‰Å T2»'hë@°¬/øûá“'9ý©OùBfp|‚ÿuà£Ór¹.„ÇuëÖÑÛÛ[ê©··—;wrÝu×…Ë6oÞLwwwø&Ãí·ßN[[[Ñ6‚ 4&b¢oEÿW_Ñ/Oõý’3ð ¸úUŸã‚c A˜Y*±b¡¹‘1  ¶@„Ö³1ŠsBñ|c4w`ÔS|q¬ƒBØÎè¼¥ «Ù¶gOQHTUžš›T!NcAyç?öX(4ªP¬.…° vd{åÅ—¤XÜŒŠŽ?xè¡p¹òT‚¦ƒ/´uËõHÝ4`Åw¿ æZøâšª{"RF¸ëŸ8#ø«¶WžŒ*ýÕša8ý~9JHÌoüìÿZAàÔUýÒð“Ï„FUïK¿¯<à×1Cáïò?Ίû“>«¿¹4XÁ$²éC€µ;†ÞŠÑåk† íp]Û·DQÖÏóÂ}Uùî}Œ\Î+ÚŽHYO<ñÏ?ÿ<ÕP9W­ZÅ­·ÞÊöíÛéîîféÒ¥ rã7ríµ×†Ûmݺ•|ä#\ýõ´µµ188ÈÖ­[Ã7Ah\ÅD¿èÝȯùUîñêÍ%,F]èÈÿêmõf‘zƒGZ‘F±‚ Ì,•ر‚ÐÜȘ@[ BsØw”áxÛDC5XšÐ+Yž+ù«Ä:'²_*(¯óŽ; •ÂÂÊrøs’&¾§ÒDiÀªS§8ãá‡áÒKC±N…êTuÔ"Û›ÀÀÐ._z,*añÜax® V/^¶5I!O¢j¯ ªÒTeƒ:éÀŸý,æ5×Ò4\ ›Ô2AÝRÁò¯ñ‹|óóŸG§àÕuþPáMãÀ/n‰§4Ì[87<®üÎÃðû ñG°`÷n´õë8qâÇ¿uÄ-«‹ÂÊ| –<‰ ÅçuÞ¼_°ðÎ…èpyÑrgŒø· |׿þ2༢åžçÿFyøáAæÎ=‡»îú1¦ù.b±ñxÃHð–·<ʾÐO:&ŸÏcßûÞ~ ï‹’ZAÒÌf³¤Ói–,YBGGGÅ×l9êBxÿ„ë®».t‡^µjÕ(7è¶¶6î¸ãŽ0ÙõúõëëÂp‚0=4ŠpÊ|Ž~IBAdT„DdûDd}ªdy4/¤ ´*b A˜Y&²b¡ù‘1  ¶@„ƶO{')ýY ×]/òTè2ø!hu`Õ³;é; ïÃÍåxæþûÉ]s /¾ø.îûÎY\—ÍbÛ6ù¼/aÞwß}¼üòa4V•íº£…A€‡>Ê9çœlã¢ë¾Ÿ¡a€Yââº.‹½‡»ï~’O}Êãñ8º®3þ ßúÖ+8Î?bñxœÏþ~NŸÞÄW,ò,R©Žãð/ÿrÇ¿‹Ýáþ##}À»H&“Äãqâñ8{þs,Ë¢§§‡¶¶6yä‘I\壩á(Ê×2•l#BcÒv@}©«øçêm#õ¡BªF1/'õ1ÊMQ>Á² ´"` A˜y*±b¡¹‘1  ¶@„Ƴö³|Vœ)Qä¦PL÷SOñö‹. ç] ¡R£œ8qî¼âñÐ#QåT(F°áQÕLåfìŸã¼ü¹ç¸÷ë_G»åâ@ò?àAË"›ÍbRˆì–¡àí¨œ14`ïŸ>Ï3ºˆ›Þÿ4<ŒÝÖF°-û,ç|r 'üˆcï|'.¾GáùwÁ{ú ñéâp¯mȦӤR)Ð4r¹`òÌ#ÏŒê¯ßû½•|éèb7Å|aÐ4¹ûî»sï½_æøn‡Ô0ŒPìÔ\—x ÆY¼ôÒûxàË{ؾ=ÍeºNò_ÿ•µk¿Í™g&›Íây¶m£i=ô‹oU%:f³Yt]'÷[µtéjŽ?@:F×u2™ Ž?þ8É仈Çã¤R)Òé4‡÷pèÐÙ¸®K:íßZÆÙgCoï¿ñÔSGÑ4 ÇqX²d _þòüä'ÌÀÀÿç¯þŠ—ÌÞÅ—¾´“¿ýÛëBóàÁóøå/ÒÙÙI>Ÿgÿ‡>D××NÿØ[õõ_9A…è›E*o£ZVš y5^(2æÈáàTvAAAAA›,YŽ—,Ï‘3ôjTªTéT^Ũ(çx1 gd\—ŧN…ë£:`§Óaš'×uÁ.Å¢àýçyçÞq÷õ«¼÷äIþßÿûOÀ-Ô_ËòsªRjùã?Îén?!¶ ¶—ÍrüÎgðìûÿ~– ‘Úºº÷EË…·ÝƵ, <˲H&“üÓ?ýsæä|5žç±|ùr,Ë öùË¿ü#~ÿ÷˲صëÏ<ó Ùl–M›6…øž›ÉdÒir¹‡à3Ÿù ===†ÁOú ^zé}†A*•"™L‹Å˜?>G· ï¼@qÔuß‹|ñQýÝ¿?ë×?†çyÄãqLÓIJ,l¾ûÝg0MÇq°,‹w¾ówxó›ˆeY áyßþö/8|8Éùçÿ%ù|MÓˆÅb|ýëfÓ¦SxžÎÀÀº®óo—_ή]»X´èW\qº®ãº.±XŒÿøÿbÓ¦SÜyçm8Ù,W=Ê»,ÀuÇý:YDxA˜€RA‘ÈçD™u¾¤ÃrœÐÕÞÆ.K? ‚ ‚ ‚ ‚ ‚Ð\šB|³ÃË—ãà Ž¹àwð¾û˜»w/‡^z 8°hØ6kCá1Ì éy~®Âl–?8z;":jA¹f°m:öE<×åÒý×uÙ»÷ Y (Êupâø¢æáÇ9vÿp]ž»÷^6ïÝ‹eY ÿ€3îp!—cÁþý¡—墅º~ñ/ÿ’X,†ã8üÑ­ã²ËþMÓ°m›ŽŽúûû™3ç0{öì!NsÖYg‘L&¹á†ü~>ôÎ:ë,^zé%’É$—]v?üá<.¼ðBŽ;†çy¡ç£ã8ضM6›¥³³“}h%‹?ËH¥RhšF"‘àê«}é8ŸÏ“ÉdˆÇã$ .¹äw×uyÛÛÞÆe—]†ëºìÛ÷ÿôOû°,‹mÛ¶‘ËåˆÇãœ:µ‰'žxÙl–\.‡çy¡¨ºaúººÈçóضÍοàÎ;¯Æq4M#“Hp48›6m ë××ׇãh<üð|>ñ‰÷¡kx o»Ý»_äøñ…ÜrË-˜¦IWWüÛo¾ÁžãŸ³#©G¾ÿ}æ9‚ë‚qé‹,~â Ö>üpU×½‚ • ‚"øÿ«à”ðøªÈÛK9rA¨UŸ4é²Â£ ‚ ‚ ‚ ‚ ÍÆDäî_|áÑßsTs‡î¾›¥§Osº»›=AîÊËx<Žÿw 8ýS6›eÃCpêž{Bï@(äjÔýן`Y:¶mûžq¹¹\Ž5kÖþò¨WÀ©S§Èårtvvây¹\ŽóÎós&“IâžÇ—ë·ðÀÊ•_#›ÍrÍ5×`™L†gŸ]ÌÑ£óY¹r%‰DÏó0M“¥K¿L"7“É ë:¯;ñõ°ŸŸzê)öïßO{{;÷ÞûÏ=w!—_~9ßøÆ7èìì$‹qùå¯pèÐK¾ˆ˜E¹H‰Éd'Æša®¸âŠ0§$É$×\s ºNQ}t]‡£GÑG×X,t[¼5žÁ0|/LMÓÐwp>Þ饼ê‘g0€%¿úO¿ùÍdLç±³8ö½Ý\ü‹_Tu­‹ð(‚PÑ$Î*¼ªù5J¶sq9‚‹NAtT£……ƒ3fXAAAAA—R‡›BŽF‡~Õ(?}öÙ¢P¨=##ô§ÿó?Ño½‹açþÙŸ¡¹.ˆ†øà/ø‚Ø÷ÞëÛ¶Éårhš¶ÍÊãNj§þøÇ¿R¸®K&“Á²,,Ë⦛ÞÌâÅŸ —Ë‹Åp]—3Ï|„}ûöá8N˜ƒÐ²,ÞøÆ7²hÑ"lÛÆ4M4M#³bÅ –.}6l`Ñÿý¿á<êÉ“ωÿ79øÃâº.sç^ÉEᡇâþèèééáG?úQ°—ÁÕW_ÍW¾ò¶mÛF[Ûå<ûì©°­<ðÇŽ]À©SO¾ pï½{8xðÃ=z”—^zÉÏ#‰ÎµWÿ’O|â}a[;::xî¹W°,øò—÷à8†Áþ—ßÏÅgÞÏ÷¾÷=^yå¾õ§Jlùr.¼ðBzè!NŸ>ÍÀÀ©TŠ%KždÙ²PÜ_4L¥ q*Çã\~yñ=Ÿ…¡!H§ýÄ‘ŽÃ _ŒëBà(Y¸Öþý¿p,ÂJ®¨Ù,è:ÇÎ:ÇñC㾫jg'î§0_õ ®ÚõE’ÀK?ù ûÎ=—ôW.àÀÞ¹9眪®A& jÕ£·Üˆü=…‡zoÉÄ¥º‚ –z°\ Y²èèxxnUAAAA ‹ô( q4ÏàU6 ñJ<û,@ `þ.?þñÕ<÷ÜsÜ{ï½üÍßü ï|ç;9}z)Ë—wÏçC¯ÊT*ŧ?}œ³Ï~œ§žz ð=ø.¿üzL3æa`óæÍ,^|Š“'ÏâÃþp(öÝÿý€ŸÃñ]ïzóçÏÇó<þó?O³s×:þã?ÚþúÖW¾Â#øíY¹reØ·±X md„áW.äàÁƒüùŸÿ9ïX³†× áy¾*h¸.'{{ÑuD"Á~t)K~õÚ@ä,ÐÙ éOž*:ïÎ}GI“Á~p¹¯f³àyÃ? dwˆÅð|ÁÙ{xÐO0iJAàÊ}÷ùjo÷×8st-ö©MÄóy~õÚ×òÄâŰz5 ,Ö~äîç;«º/DxA¨€¨obœâ¨pË"ƒá„ƒC"` ¼ãÄqqI“ÆÆÆÂHAAAAAh \ÜŠ v–lãQœÚ) |/Šæ=æl|ê?ÿ3ÌÍxüŸÿÓô]"ìßçy¡ðè8žç…yÕ²x<Ž®ëX–ÅYg½ÈsÍ¡ChãÁÿƒÃ‡—ÓÕÕ@WW©TŠ… „ÂeOOŽãðÄÏrìØ3xžG*•"ŸÏ“J¥âå—ßJ<½&U}ýןcÍš5,Y²Äï7×e``ˆ¡¡!ÞùÎw200ÀÝwßÍüù÷1<|Žã„žŠŽã𗹈cÇþ·Þz+¦ibßùÎ-\r‰ïá¨iš¦ašðÆ7¾ ˜lÛ¶-ìç0t)°fÍ:„çyœ;×—Ê.\ˆiš¤ ýñ3þ|¶úÓ¼å±ÇÈd2þï¦{8øÊ…¬^½š?}Ç;8ûñÇyïùç3<ü}6mú)pÕU\º?®ë†y%Ÿ|ùaNûˆ€}ß|èèð½]Ói¸ï>4<ÌÕOùÞŽ® ©¹ïÌ'› *ŸËùB¢ã`¾t7‰Ë€E‹ Ÿ÷](  è»þ³$~úû…x«]]°z5îáå¸oøM²Ù,û·mcÙWH€Óöë|ïÛ¯ªú¾áQ¡\Š&þAà‡Z݇Í2Š=—FàÕh``c“#Gœ8&&..66éàÇžB²iAAAAAꨓÁýÁßBGÓ.ܳ‡³œ%O>ÉòÇ8gï^,Ëòäær¾Ðèºìü뿽 Ç) ošÍfY¸ð ˜¦ Š›6màŠ $k •÷ѯgÔ{2•J‘HÀ%—|—\p\Ó4Ñuƒ‰p{åiø–·œÅ±c—„bg6PÉÎ8ã!n½õ,îºë.yä\×EÓ4Þþö‹xùå—Ù·o–eÇéééáÕ¯¾Š… b†aÏçÉñHW­Z…çy~à; :N÷0TåÀþÎQvíZÄêÕo ½Á÷î4 Àó8y×]¼üòË$“IbWÍç“óþ–ï~÷]<ºk8ל}6ßùÎ%¬_’ë.ºMÓH$¤ï¼šËçý‚ï}èC¾è8\}ü8G^Åâ×¼‡kÎ>Çq°, ˆ³ý_Ë‚övF˜CjÓO :, s÷2;1Þ<ïÓ_ðEÃT ÷­¿ï_W¶ë—áºHà_ gž ozýþ!:îøS’tù©è:ÚonBÓÀ]µ Ã0p]Û¶}-ôåײïÄkª¾öExA˜5ÈE–™ø‚#ø§ƒ(íQáQ…RÕÐ0ƒ­66qâhháàÃÅ ·=7QuAAAAA¨#Ò„ÒRHTx<€/ï ã1,ó‚e*ÍÓ›øCþÛ3ÏðòË/sÖcqÖc±öկƶm Ã@ÃùVŸ>Ížo~Ó_ pN*Õu]Nœ¸ÐCñ®¯¯Å‹ÕO<ÏcñâMƨ&ñOÿ´C‡.Àó¼ÐS/³lÙ2€‚÷¾ãw¿{?+WÞI<'™L’H$°,‹3ÎXÃÉ“gqñÅûíö<’É$¿úÕ¯á7ó7I¥Rhžç{àí_Àk^ókEå+>õ©e¡àŲ(ÊÉ“OðŽw¼#\doXüS¼Ãs¸¡»›7­^ëºl9çûÌ=ë,~;–ãÓýý`Û,Úµ‹Ï~¶ <ý¿þƒó{¬PþE±á½çs¶ãùÇÇÃ\›ŽÞ›¯å­/¿Lgg']Y ð=-½¹ËßÀ0°×|”9ŒÀ²eØk>ŠwÛ?ƒç‘îûmbû¿J¶{5Ù7ã&2 i$¶GÏ-'WRÕÝð´ÿv ù”4­€IDATÎ/êÏ ÛÚÈÙZ˜LÒ4!W©#}15“Éày ·€ckÖT}?ˆð(‚P!.…«¥Â£‡Ãp$´jœ866zàéáa?þ¾™àÇÁáktðU:ñD€AAAA„&ÀÐÔlß Á_'øU~zû¿÷=†÷íã—ýýhÀ5gŸ†TU‡o¿è"ñ8ñxœŸÿ|3ǯ =£^‹W\ñÛ¡0i”S.¾øâhŠÁï/žgíoš&—]v6]]pÝu×…Ûj𯆠àÀ÷àº.™LÃ0H§Ó8Ž?/ª„ÏÎÎNºººxàËyùåã+_ùŠ_Ï 4ë† Ã\vÙÙEuñ‚Î{¦ïŠ"Fü¡àØßŸ‹vÆ0Wìý~˜3ìýÿžöû~`Ç.ä §NÑ××Gú¾ëøùòsçÊ¡ñ8NïI6¼òÃg¬¡í¹çX·h‘¿ÿž6¬;ÎÅ5âþöñ8Âc¢í›è¿}g<ÉϾô%ºR=a}ßøT(<±Ùï^BÚKá\þ?üP¨Ë–Áùç¾3eÐ$, r_ úûçó ièÏÃ;¾9s¦úõHøNŽî’7ÒÙYXžNûÍS—D.—ã÷ÿ À*ùË…U_ñ"< ‚ ”Á¦ê|qÑ¥ 6‚Ž€`ÙVë±±±Ik]ÜPdÔÐ00ЂRÔç‰P¨8ŽK'‚ ‚ ‚ ‚ ‚PßLÖàPäåñhPðZÄuy¾»›‹ŽaËÞn«ë¾c ?£®ëtw¯Æu ½£Þ€7ÜpCÑq•^÷àƒË‹–/_þ À(ñño|cøÿ±cÇH§Ó˜¦ÉúõëI&áßøíííX–E6›åÙgï ›Íâ8NæU•ÿ›A[ Ãð‚ÉÎ;ƒŽôøðúõüú¯·ÑCX8O--¨k–…sûƒØ6èmÏ6"—ƒ#GÐ_ÙƒyïÿòU¶d8kÿþ°¼ýçÇšáa_ô\²–/Ç{až¿}.¦IâÊŸóÃëùê¼kyX38úï€m‡B(×\ã‡7µmÐ4RÉÃÃ?€ÁAˆÇÙpÆ,?y2Ø8†ñî•þöº›7ûýqé‹8Ï]ˆóÄb_- –g2¾è‰žŠ®CöÄ;jY¡N{6[*Óé@‹Ý¿`”G«êßsÎÙLGGš—_~k(F¾æ5'xþù¥“º¦KáQ¡ 6…·lü÷’J_ü±iR…V=‰Ël$B±ÑÆìF=K?ëÁÏIp=¡·¤ ‚ ‚ ‚ ‚ õ‹ÃhwÁh˜Õy/¾ÀS@9,"¤q±›…Çãy©T \ÇqXsî¹¼nÙ²0\ªÊsXªÉ8p È 0¸®© d¦ëº<õ”/PªÐ›Š{ï½€Õ«oàñÇóþøÇ+Ãã$ \×%‘Hð;¿sà{Eª0©¹\Ž‹/~D>pî¹ø¢©j Ä uw].}ñE²Y_÷+ªçCÃØ˜°h‘¿Ry7>ø žîð¹¾úæ8¾Èxá´g’%å/w]lMã­{¾é¸gCË–ñ†Å‹Á¶é¹ofçrœ/źð¯}Õ/‘À™¯›÷4 æïÞûYû籩äá‚8šÉ„îƒÎÀ2r‹~Ü@O/$8 6Äq๠/äè«_ +Wbš =v0l¯aRVærOsÓ©¢¾QÝ‘ÏûûEd]÷« ëA2Ÿ÷=!=º»o “YÆ®]‹Ð4¿«žxb1{ö\XÕ=!£ ¸‘ÿã@*0‚/(ª„\¸¸88aXU - ­ªÐ#Cåñ¨01¹œ‹Ð10Š(‚ ‚ ‚ ‚ ‚ Ô/Q‚è¼ÞœW^ö†ñÕl…ksÌ?ö]ŽÝ!g£eáy2×—o¢¹Kik{ Hx¼îº¿ ö+ÞV O{öì‰,‹ä¡QáÑ4ýè­®[Ø?ó·éê‚?ýÓ}œuÖùáõ¢ið…/ôsÕUOýF@„GA„qQvÚ~Sáò‚wqˆVU¹UhU#ô~_„Œ ]t±0ØVGáQAAAAê˜RoGå˜åÏc>Y( Éz.mÀYO?ÍCwÜ1*£ç ÃÀ¶Í²yÏ=÷Œp…Ê¥Xº½¦ÁâÅ÷pÆûÂeËŽå×>¸zžÇg?{'Oþ \ð±X ]×éêêbÆ;0ÍT(ЦR)æ?Î ‹¿z\âº\·vmQ]Œ lëƒ_cåœ9‘ÎsqWm óž]~RÃ@Õ/9“ÔU÷‘9~³¯ÆyxÎ#gúûûn|÷¡{äâ¿·ˆüÞ5±hypùrúÞô[hs£ ïã©Õ«ÙÞy¾:GA¼ƒ¢t‘ü£–Àzú&ÞúÖ×úm3M¬‡6ÐÓãïOg§¿¿® „Íò.ÿu¼…+ikû,žçð…¯ý˲|OMþàŽòøãÿÀßýÝ«qœ‚H¨ë~sR©B®G]÷C¨ªœ*ê¬:ýºî‹”ííÅ^’*léuñÀ7°ÿB6oþ ÙlqX×jáQarc,w‚›\( º¸¡Ð @‘И eL"Ûûhh"< ‚ ‚ ‚ ‚ B ´ ‹4é¢u§OŸæÑDN‹€Ó¸ÌŽ<ù$‹Ÿ}¶Èk1*$& §XHRøâ˜=¦Gd”áá‡8zt>'Nü-/Ú»—óÎ;€×¾öµd2™ÐëqÓ¦ÏðôÓÆÆH>ŸÇ4MÒé4==W°bÅ#?þK2™ ™L÷WK˜{ô(ñx0ç™L²ê?ï£i‚óƒá¢0±‰ù0ÿçåOò2‚ŸkˆýÅÕU`ýzØ´‰Ü_+¸&˜Ø$töÄT ýÔ¸.Ä:µÐñèüù_±wh.:CË–…Ûƒ¿Y>ï×Õ¶!™ôW_°n¶íù}c˜ç? €JÕ´Àkðõ+ñι(¬ŽwåÛqŽ®eÞ¼íüÙŸ}€Õ«?‹ã8üã?>…ãÀ³Ï~ƒááažzj5–UðnT9c1Âü‹ªŽŽã×Ѳ ]ä_+Åݦ.‹¨¦½Ž2™ ù|žgžùÝ¢í«E„GA„2¨a€ ¡Œ£¢#@œx‘g#ò6*J…ƨ@YŠŽ>éÄÔ‚ ‚ ‚ ‚ ‚ ÔŽ½{÷rüøñÈ’¨c!ëüàï6<þ8¿øÛ¿ Óêº>JHtÇõO0GyKÂèP«Ï<³0>#\ö†'žà ýЫ۶}•G¶mÃu]²Ù,Þ _Ë›nº‰ºé&ÀªÎ?ÿ|-ZÇE]Y\ÇÁùX$pÿýÁQ•0 ÐÞ´šËÛÚhÛ³§Øí.ö´Œ½ß"³üoðN,ò—Û©p£ÎÙ×øÊ çù*ÜWÀ¥—⺠àÒgšèOÜæ`t|·AàpàáÉš5…|–›c©×`iŸ¯ =ãë ë庅<‹Ù,¤þ÷2â=7/Óµã×|±wΜÃ\tÑÛI¥R|å+Ÿã©§ºI§Óhš0¥¿êzAÈô¼âp©Ê3S‰ñx¡îšVH9©iÅBb¹k(N“N§RÑe§AÆ@À`V‡ÝÃÃÅÅÆÆÁ!Ž?(P¡U ûçpOh,EG/›˜ZAAAA„úäÀñãüò…"K4Øwî¨íöbd3dÙ²eèºz<êº>JHŒÇÇóF3ж×uÿ·4ÔêÜx;öLÑò†‡÷qã¿Íç>ðPôüŸ[_a€vþcó9ÜzÁàº\úñ344ÄÞ½sùàÿ°¨œüš›0±Ñ ¤Ú6h#‰¤/ä]ý!î:ÿ|οë.ÈfÉÀý½¿ð+«ë8ß~šôЧ ß­0•B×Áøà¥þ²`{û²Oàì?:‹Üûìw}>ôM&)$SÄ%•ým«8qbÉœIjuw‘w íòyÿ³ Áºk×<4’÷^O"¦‚ÄqüíÔ¾ÊѶ éõ×ïáŸÿù™ŒF*•á–[>ÆÚµóéêꢫ«‹E‹Îš”Nûe©å*—£a‚lä\Úh¨Ã‚/F&~9©TA¨Ìd2Äãq®¾ú8‘ôžU#£ Â<mìÐãÑÁ EÄèÿ@‘ð£C­VŠx< ‚ ‚ ‚ ‚ Bcñ‹óÎã™¶WXtè2æž> †ó‡s^n{"˜û[¦B~â Híí±¢°«à‹K¹1rB½óÇŠ<$ƒô‡¸.¯>àá‡ç³páq^÷ºàx¶ÍE{÷rìØ Àá–]ÍH_ŽãËåÈ}á<Úàß¾°›3Ÿy<ó{ŒW-Xà lÙt!É Ûó%Ìëæ£_ÞæW88Æ« cýIX¹’û^ýjÎýÁ°¼yrWàzZÔ¸ôE_À¾>_1{òI8}ºÐè@åÓ7ž‡±á ¿¬ˆÛŸóüê°?<Ýàøñ•,[6D.Ö°wïE¾cå¼7‡E'04Tsê ‰~;—,yc(ò©¥Ê;1—+mÍטËÁí·ofãÆK‰Åüî¹ûî˸ðÂë‰ÇãhšÆñãýá~Q!Ñ0 §jb*5Ú£1JÔ{38 áq=ð=s¹‹-b:áQ¡ ÊÓ1tá J´±COF'uô"Ç ™)_ ˜âõ(‚ ‚ ‚ ‚ õÍPFõØâ'8µ°€SÀÙ¯¼{÷†ó‡gŒŒ„û æýTŽEðu¼eË>å‡ô¬Ã€W^ùõ¢eQá±³³3\¾téRNœx Oßvü—¾¢QÉÒ÷lÂ9çía’B;ï·W;o® ûõVž|íkáÀ¾ýí£x'ᮼ=nø£³H­î.4Ð0àèQܽsC=S¹FEuQÏAǽ{7³oß?äèÂ… ¯áĉuØO­.Û·JÀûÒ—®gõê§8Ô ‚b"á{F‰Çýð¨==£ëäy/E%š¦ XèºçÁk^s ¨ªQARåL¥ íŒ'tò >›fk3RF&“Á0 Î?ÿdèÕ9Ô¥ð8<<Ì•W^Iooï¨uÛ·oçÊ+¯díÚµÜ|óÍ Öºº‚ ̵°. <ÊÀÄu|±‘p/6jhxx¡H8™PªÕC!^B«#cA`l[ v@Z‚b A¨;ðòüù…ÿ-bΜ9aª¦3ƒÏQ,X0a¹™L±¾çšãÀ²eWZVè wøða\×Å ’ûûÄ'1pXýÂ<~âlùÌg¸ìÔhœÕv!¸.º®ÓÕÕA®Êx ªŠÕÁgcí};î/^(¸ô©ó¾æ u+WúÛÆ[Î"C7<õNÎåW/^Ê¿^pÏýôÉO.ö=ûƒaàý·wúžšÃk ñM5 }ýYô}éB;ƒÎÈåü¦ùoÕgZÁ‰Ççž+h_~y ¿úÕk1ÍÑÂ]PýP°»é¦7sÅ=¼þõ Ën“HøÎ™Q¡±³Ó¯›içÛìê*<È‹Åhk{€›nº)ôVU¢fé>‰„¿,“½Î0Šë¢¶S¡`Ã#ær¸®K<.êRx¼ù曵|ûöítww³uëVvìØÁàà 7ß|s­«+ P ;àéÈgeƒœ0§£‡‡‰z7Fëo¼z‚à#cA ¼-; ­…Œ A±‚ 4˜hkcÞ¼yþd_&õì“'GmõxÊzž¥Óc‡Z]¸0"†¹.šæ L×^;|> XóWƒçžXÌÂ;ïĈÇùÂyçñäËoeÿþ°o_±B¦X¶¬àª—Ja¿ Žõ—Û6¤Ó8ë?\µL\wåÕd{/ùs>€÷È3lÚ´ Ûóضz5P(Ö;ë|д <,ØCWýÞ¥JÓÄšwé¯^úgI=cï_\”£På4ß#0—ƒ“'ÏbíÚ‡ÃåCC¾`«r0–¢êæ—‘âþû/aÇŽùFA¤‹V#óÅF…%Ë †]]£gš&‰D‚~tW\q¹à„;ŽM,C× *žçyzæÆº8"DsPÚ¨£iž7½Î/u'<Þ~ûí9r¤ìº;w²yóf6oÞÌÆ¹í¶Ûèïïgçε®¶ ÓH­ì€ Eþ…z$´ªml4´P`Œ Æ´y=úÇ׫/D‚cÛ±‚Ð:Ș@[ BÛ«kñ‚2¥Øö„›JÐ*ÙØuC'ĻX,F6›Å¶mÿáÐ^z‰eCCd2¾³v-¿zñÒÂþ†¡’C_q?©Í{}!T¹Ýe2hkÎE›{{õ ¾ç¡ã@6ÖÛq•?Ï0±w-"öÌr‡®aãÆóÈçóüÛ¿}‰x|´§ j^ºû±óCá‘¥K¡­ ðEXµZŸÉ@2äsôüm\×/?‘(ˆ÷ÝwPø¼råñP;-%**:ŽÃ¼y/ð óTsÑ´b‘¸T³U"ŸëŽÎÅhš£½X ÃBŸÂÅ_Œã8X–E,Ãu]Ž}8C=:::ð<7¬[gggèÙ:¹\|W]ŸÞyèºûûû±,‹Ï.¾¥ëÙ¸qc¸lÕªU¬[·ŽÝ»w×ºê‚ Lõ`Ô÷Œ^õðÂpNø¿Q$êèa¼öé@„G¡•©[ Bíˈ„ÖAÆ‚ €ØAêרôL–®xyIÑGÇqXt`QÙ2VÞ“e÷îýÌ{_<ϯ‹m‡n‘® gŸý>úúúü°©@êÝ é"É'_þ’¿M.ÇÃ?ÌÅ‹“8ÿ.rޝLYd³¸ïý#X½ÚªL3tó3 ÐÚ^µk ±HÕ-Ó"*œ¦‹…õÒ4-ír9ÓR/Oã½¾è¨ñŸ¿”LƯ‚!ê‘XÈ_˜Ž„´K$ B$À‰‹°m_h:áv‚Ðì ÒÛÛËÑ£G«/l˜I;pôèQz{{'Œïî¼0¿¢ƒz2ZXE^ÓfUÆúªŸè…7bÏ]¯äUnoo/>ú(/½ôR­›Z–Ù”ËQK²d'ÜFr¾ ÓÉðð0½½½ìß¿¿ÖU·ŽcÙ‚jÇ'Nœ ··Wž„–§¿¿ŸÞÞ^Nœ8Q몔e¦ŸöïßOoooÙpm‚ÐJÈóAý=Âl#s†•ÍBñüÊx,˜{%”Ì®8¶‚•ÇWŽ»Ÿ1‰éÅ#Gærúôj^Úý=\× Å¦îÿssææöÛÿ„\.G6›¥3ãÎÁùlû7¤ü!/^z)¦ë¢{ó^|kÿ»°z×ûÈåÀ4q_Ès]°r÷¾léå$¾tyAY <æÒiŠBžª6o|(öTT¢›¦ùaJ-Ë ÃUØU«{)¹œ¿ç<£!U•³¦Ê«¨ë¯Cσ«®º'…åž8ñuÞõ®ý˜æhÄÒó¡ë:{öÜËŸýÙ¹¡'eé~åDH•ÿ±\øÜ±Îµ®Ã?x)š¦ÇI$Äãqø:†a`]]]är~NHÃ0H¥RضM2™ óz¦Ói:::B¯×rÇUù<`aÿ´Œ êFx´,‹¥K—rã7N{Ù'Ož¤¿¿_ÞrZ5ˆ8vìX­«R–™´ÇŽ«hQð?#øñðŠÂ¬N·Wâôjf_ôsñ *jA H¿ËƒÏYŠÃúªü¢é`› "c,XÖüæøébÁö‘ò—û:Á~‘rç›ÛÛùâºu<ë¬Zw[YfcL0S î$³´ªü±Y²ãîëà$9#uZ“#GŽÔ½ð8“¶@ ò|03È‹ÃîÝ»ëZxœéç%<޲MZõ2ÎÉ2yÇêF~>„FAæ +›3®%]vÍÙ/~5#tr®/½¼]× ¡VϾ˜ûó‹À9T)cEËìê-^)¡ø`Ûõ,Ÿ3‡¯dÙ²!>ô¡•üʼn|壥÷}ïcþU¿Ã §—²kÞ<Þ½?8ðw^’ÄõÏùÇÿò½aŒÒhNÀR‡¸l6ƒ¼×¬Ã\ñȨz«|“™[ŽÑ÷¥ÊŠm*W¡eùÛÇã…¿Qï&°°ÈPeº¸¡ÍH“.ZçáÑI'qâxxÄ‚37À@Ñ6669rØØÓÒYh]V­ZÅÖ­[Ù¾}{­«R–™¶Ë–-«hL L -B¢AÔ?›7ohÙçƒ 6ˆ-`ëÖ­ôööÖ¥øÖèÏ‚Ð(Èœaes†P˜¯±±K^ Îqòås!²ìÁ|À¹ºŽmÛ¬?µžeË–§zÕóÊ‹`¹\±°°xñbî»oÇÿC¾ý d{ïý-.½ô«tuðù«ûxéÕ¯æ’ï~—…7/䢋örøðøÜÎïCG:žÿ·pèlR¿y뮫Èj™Þöœ{n˜32Ê(AíòËIüÜpé´/f2¾P¨ëþº*à“aøë•w¢7£§ëúyƒ¯@Aˆtœ‚×£ª‹Ê½hÅáXÁn_ÿú‹xõ«ïÃ4ß,ÕX¹ò¸ßÖ „G]×I&“ ¥ˆÅF ±SÁœ`z'U1žžž¢Ï©ÈÇÑ4|>®ë¡ð¨ÄÉ9sæày^æ¶p}oIÃ0ð<¹sçò /ðÔSOUÕ¶º—.]ʶmÛŠ–oß¾¥K—²cÇŽpYÿ(wêrîÕ‚ 4õd`i 8ª‰³¨Àõxf%jD>u”X§á |.¾ˆgSxÍÁ÷<ÔðE¸åÁÿ |ñO Êsð½ûðE<%Þ™‡;Õ‚:©0CÁ²è›onP5–P/¥ñÇZ  xá/W!ÞÍȾDþ7ƒ2ºJÊ-'é%åÁïùýýô>ü0¼ýí³w+ žlÁTÈ‘ ÅE—1zèÁÁ!K¶HxÌ’ =«$ÂýUØU“$I\Üp?FŒ8qzè™dÍ¡±˜È¨7ëÑ42*ÊÃTˆ¾h¡>ËXI¨†F‚0=ˆ-¡퀟êÆŸé54<\^š m…íþ À fy¶í߆y©<÷·1wîÑ@€, ëÅ‚™Â¶G{È=ù/Oœ7±å{ySÿóœsÓMœþ“?áW}‹{|eóŸgÑk=ô Oœ`xø\Ž9Û¶1ðçµôåËÑ=‚½í¿p.Úì»Äe³$³LÓ?¶÷¢9£8Ç_O¬{ ]oóE9%n©ª‰DAT‚£m<•w¥*_ÓücdK2Ó¤Rþº\:;ýrUÝTß” ›ªi°zõS<ùäJl['É7öÅ^€åÈårAF_ÍNœ1gB”@:]  7 ƒD"¹`Ç)ú ðõ¯Ûn» Ïóð<\.Çk^ó~ã7~£ªºÔ…ð¸yóæQoõöörÝu×…†A­ß½{w‘±èííåÚk¯­uA¨’z°.¾hä¡V£pFÑ›LÓííØ (Πà]H°Ì¡~T ƒ:¾0gë•P§<£åø"œò_xTåÇñ=•—btßrg2†¦ÔÀ ¥/#ø`¢¤Õ–±‚gf-8*âA™^¤ ¥(u<¦7-ôìP¶ TèÔ¨hØIg‘íÈ’ PttR¤ˆGC#‘®$Ðа±`',/:Áoaáá‘óŠ„Æb"[PÏv ÑPc ‹$ILLòäËzX—Ú……EŽyòE寉Ox|abÆê÷f§ÑÇ‚ Lb A¨G;P˜—òg ll˜s€ùaÔ´ñçf,XÀñ’e®[^8K$F/÷õ—3øÃcüå¸îÔ§xª»›³~í×øÅ]÷—sñ•¾Bg¼ÒÖ?γÏ^¬â=A?¹@*vgß¹X½ã"Ê*~J Ëå`ddtGÖ¬)[ÿ¨§dÔKR Œj™ÊÃ躾°§ò?*¯F周<#;; õŠ µ‰„_ýööÑ}xå•{ùÅ/ÞŽ®«öôáy¯ÌqÈd2tttJ¥Ð´âªS%6v:ÐJ.¦µÜ:¿ï¾úÕ¯rÑEáºn(Lþìg?ã oxCUu© áqÕªU¬ZµjÔòè¤øF¦»»›ë®»Ž¶¶6n¿ývÚÚÚ¸îºëjÝAª¤ì€GAÀ²"¡V£c+NúTŠÊq¨†%)@…aÏá´”w`)&åÃ̦¡(«]W¤Ì±ÈåEêP£P•ãXôP)Ç#>F9QÁq²þ*Ô«**¸Ð¶êÁLõ¦£š¬·±é£4iºè"FŒ9Ò¤I‘ 'ôÓ¤Ã$BQ…y¶?[=ø10È‘+,,tôq'úKmš Ô+•Ø‚z´†‹Käɇá Ó¤ñðÈ’ÅÄ$G. ÝI'=ô`c“ …U6GmôíïR¢vÈÁÁëy驆±öðÈ‘#A¢*oщêSƒfÉ6ìK)<&aú[ B=ÛQcÞ ý<‰í$x?b.²ÚT¶¶¶6NŸäw¿º•½g./l£<£(1/ÇWÌt4›,‡_ÊbcÆ‹6oF;y’í?ÿ9_=ñ ¼<'LÒxƆ Äí±çÍÿă‡Vsg?J¢uÏ ÞÓ‡ðÐ x•Ð0|1Ïuýú%“þgÇñ—e2¾€62ä‘Îja8ÔtÚßF‰tJûò¼Ñ^]]~Ù…0­j›ÎÎboOUµTª8—#øû©6”†ƒÝµë=ÀÉP䄉GE:&‘˜hV²~1J:Ãó<’É$+W®äСCìÙ³'ôzüô§?]õñæÖºÁ“AÅY¾þúë¹þúë±,‹­[·ÒÖÖVeÉ‚ 4 3m ¦ûýo¯(§c³† ‹N–«’ÀüФË#ÿ')„/mÇãøâ`’Âà*l׌Á_õ›§àý Ö©ífóë]y]VºmTÊQWIÔƒs²¨>˜ªDäNq¿F¡ÇÊnD'à òäà mõP’!z9*Aü‰å.ºBü«ÑЪqâäÈáâbá¿b˜#‡‰~Vy!KQ롨G;0[Œ%ìy“xåÄà =¬cÄ00BJÙ4i:é$Mš$I\\’$YÎrÒ¤‰=£uоŒµ=êå%ic“,zÍhjý=n©—ùxý’#GŒØ˜öÑ‹Œ s‘i#•›7K–¹QûÛØ“:•´Mw2䊦ºš“V¶‚ [ B-í@é|á²ÈÿÑWƒ•×Ù¼yó8õÄ[8xð½~ÎÇJÓ\×w@L§Ž¾òÑpà 7„ÛX´ˆ³{Œ³Ö¯çØáå¯$3|“¯ÖåóÉ&Ã?{#GÎ'—ËÞ{¾ØèÍYDD¼ˆ"§ŽoYÅ"ŸmD>Û†Ž˜_ñ R+Ù¬¿<.n$KÛ\Ún剘ËÊRäóÅ¡YK÷)׋½&'CWW–ÕØs*nÄýÔq<ÏãßøF(¨jš†®ë|4¸¾ªaF<éïï§­­mÊÉ™Ÿxâ‰QËÚÚÚ¸ãŽ;Âd×ëׯ—„ 41µ°~'ˆÍîaa…“pƘoïO73}õ=mRóøÂa_ TuHEÖ{Áo"X–Ã÷,ôðÑF‡YïG/Ø?ÚÏ•R[ˆ©¡BöÖC¨ÓfÊeL &‡Ë ~P><³Žæwè¾q⤃•ÿ EŠN:É’ ½(û"‚sä¦e\jE©-¨G;0¨Ë2EÊë¹RϽå,GC#Ož1ºÊðÎ’%A"|ÙAab'Ž‹æ®UžÞêE %Ø©ðÒ@è9©DOeÿ,, ŒQö0F  ™Q64I’8qLü9ê%Ž:È“A ‹N&“×Å}ñKÑã×BTb§ø¶Í.Nh#Üq‚ÝNGŽE¢Uy¥H¡¡¡£ãâ'N‚DÑÄz+„Û„f¢4TgT¨S¨û½\žÅÉPîÅ*£È³N½ˆ5ÖK ÊþDQ“ʃPí i¾MS‚šòTeeÈŒ eª<ÕËJ¸T^Fèj`„m°±É‘ ½+³d‰íg†LÚº´Ÿ“$ÜŽyò¡'¢†FŠT‘` þ‹%}ô…û•#Úæ:мÓË…YU9}•#6fè]µLýÍ’%I2,7I²HŒAA*çp…ÛY¼òÊÿ(Zv×ew±¾7 xQ>²ð6N>ì+s*¹ãÑ£áú‡×®eéÿú_8ŽÃþüGÏaéÒ7ù•±˜¯ì]r ú¦UÄ?qA‘2—¾âÿñÉ¿¸Èyï)AÑÙ㋵¥^„Jàs]_´³m_L¥üm;;ýv–î£Âž–êZ*_¥[æÆóŠÅÄTÊ>Õ±KË(ä~œˆw½k?{÷î*ß|oA}**gPêqëº.š¦áy^‘'ät1%áqxx˜Ûo¿­[·rÛm·…Âcww7@¸ìÚk¯å3Ÿù ½½½Óîõ(‚0ÝDMlt.š{mº„GÏ›¼$”Å÷H´(ˆŒI|ÑOþOá‹… |±0Ú&=ض _˜2‚ÿõ’m¢A™S•I”xÙJxPèÇxüq†‡‡kRæÏóXĈáâÒI'.nÑw9ª¢Ä‰“!†ÔÃ.F˜VM [XtÐ!aV¡ÁÈ‘ =۔Ȥ§h4†¨ ¨ÔÆT*4U Z'>*\«ò˜ÔÐpqCá¬%ªÒQ ºè*ÌTèS%ºaÈU#ø‰öSiHZe#uô²^ç:ú˜}TÒÔ ~$被('¯:vœø˜å)ñ8Ož©ÐS³Ôk=êM¯¡…¹+•ÝV]+66Fا* ·Ú× XAAarÜ×Þ€ÉÒÓKÇÜ>êUf`°nQù9Ưž¸™ ø \ ¶Gïb´µ}–K?øAÎX³˲XÚÖ†÷ÒÙ<ùäL¥¢zÇr´óà¾raqáË—sÅC\zéÃÅ©TA싊„ù 艦ùbcÔáO×ýå®[ã%!ÏtÝ_Õ¼âqÿ×²Ê ¥^Œ¦Y8–Vå{ܾ—#|ï{_cÁ‚ÝôôôT¼¯®ëSšÏ­'¢£çy†æuœn¦$<îÞ½€Í›7-ïïïgݺu¬Zµ*\víµ×¾7¤ B=£Lo©Çãtˆ–e}9Y–5¡{þq ßñ=øÛ‰ïE8€/èõá ƒ]‘ÿMʇ>Õƒå³çy ÿÅtˆgŸ}¶&Çv€ãÇ׺ šš4é0¼Ÿò Q“ç@Ù|ZÓåu¨¼KCFó»ihĉåyl6ZÔ´ N©• ~Êm§<UN +|¹ ZVž|&´Z& +?ÖK *4« kª¼ ËÕ×ÁÊ^ ‰åP^“J0óðŠrB*qRý¯ŽW>V¡„CåµXŠŽ¶Sy³+OJ6Z–òBK¨Uý2:z("æÈ…¡ª‡‡Ú% *!Q¡öW¹+•·©¢‡ž"É ll^xÕ Õ]8‚ ‚ -Fô5óƒhpü8Wν²ìxzÕªM£rè÷<»ùµÿVp-´mz_û~ Ïã\Ïü[naã‚Ü80€¶ð8CC}¾G[0×hþå[ÐußirΜⲳÙåFšÞÞóÃe*‡c>_ým}áO‰å"rªå©T±£iúË]·¸­ÊSr,ººÊ ’Óç”góÙÏ®æ/ÿrý(/ÀñP¡I™èü¬mÛaûë&ÔªJÐZ'¹··7ô~,E„GA593áÃ2]Û¶C2—ËéÆnà‹Œ»ðߘòðÅÆ>|ÏCõÝlR,.–ël6K.×z!8ÀÂyü?ôÐC<øàƒ-çm:[¨Üb XXĉÓCOMÂ1Gm•òú‰¢£ÓGߤsIÖc=`8ÎäÊ„Zc?*²Êï§lJ’$t†ž*d¨‹‹‰ n¥L§íÑÐÊz%*T½Æ[¯<ñ¢v§\(Ö(J¼S”æ,TÞ€9r¡È©„73þÔK * j´ÆóXš Žãà8–e‘N§q×uË r |Qñjàà„9U>Æz+mw6›‘Xá³ÅTë~¼¿Ÿ³/»ŒÃ‡OùØSõ]°?÷Þ{/ÇçÄ™Hœ Ò¤É?0ÚV”›pVve"o¢j(7 ]ïD/skŒ¼îå–ÛvñCM›¡EpqÃP™*¯ž êá…¹ UÍÒûY‰xcÙÉŠ3i‹ÑI—±êWêA£ë”§Ÿ ªPb#@]áq”‡bi›KÃÁVÚ—QÏ͉úºô; R»-?*ðF[u]D…×èqU(ØÒ2K=m£y‰ ž»ð¹Šê(‚ ‚Ðê”>íÏyvÕ„û”›Þ1Œòž}i2Ì?~>L}ް&”\sQÑ4$UbjÝx<*qÑŠÌ©üŽ*´jéòRAR¡1ð'¹Ô[òc…üš,¶mcÛv(>áÿ¥!WøBã"FOÆÍ”è8S¡PÓé4š¦áLÂ-©ôK|þ|/_ÎÁƒËî›ËåˆÅbc†ÜÍår´··¹Þu]ÒétX×uÃCÿÌUW]E[[÷ߨÎVô< T˜?B0üD©4Út3¹hg’èm½,Ë™ŠñÌ“Zç8âý(Ô?*L(ø"V’$9raÑ)2dBñ¬œ0X*2Eá•'ÃxÛNu<ÊåÈ.·N­†ü¬äøqâ£<•-.%†Zm_ê9¥áöÕ_uœémK½@Õø3*<«þPÞœª/T^ߨ£‹[ö{ œ·iTx|~õóÓÖ&AA„VÀT¯qjáBÀYnæ8c?×–.WsbqrŒ,[ÆßýÝß144Ä?~ýQnœ{;s¯¼\—á|÷è«ñ^i ö-”“Ï™zÞhÏÂáá3Š>Gñº®ÿòo¶$„•7¥B ‹*c¥”ær¬dûjý ½G§ž'²ìüat‘ ÔS:5]¹.ÇÁ¶mÒé4]]]£Ûàé ËŸ€) mmmÜxãÜ~ûí\ýõ\ýõôöörã7†Ûô÷÷³mÛ6n¿ývn¼ñÆQaYa¦ð<¯®Þ>˜Œ 3Ù\x®ëNº|ab¢ycåê™ J8r]×1M“D"çyضŠESa²¢›ÂuÝP¸r‡d29éýÃþ ¼7Gõcðe–ÉdƼ'Çaùòå$“IÚÛÛI§Óttt„}–N§éìì,zÑEõiggg(Üe³Y²Ù,–eÑÞÞ>êZ?uê–e‹ÅÂõ¶m“L&‰Åbär9²Ù,Éd2ÛÛÛ°¸žç‘ÍfI§ÓaYê7N“N§I&“¡˜û÷÷}SqT•ŸL&Y¾|9¡X¨~—/_n×ÙÙ‰atvvÒÞÞÛó¼°~–eÑÑÑÁœ9sÂmÚÛÛ9xð o~ó›Þ°ûî»/lwgg'Ë—/gΜ9\{íµ<üðÃS¾öZ•¹ÐKDM@wÑU4é=aš±¾v¢=êÅóÊ{-:Nñrõ4O„ç•K½"¡VxxE9^$ÂâÄI?Š©PÜR/;€?6™ ¯fgLás¼+&òpŒ.+g+'[ãÄC¯Ð‰(=þdCŸFE¾¨à8™—;Ê Å¥” ‚Ñð±¥ç:*2*áQíSÎËq¬ú”®71Y{ßÚŠÛ%‚ ‚ À) æÍ›À¼yó&5Pš s·9â<û™Ï°âcCëéá7^ûZŽœ^ŠÉ²eËÀ08ïƒD?ñ(*J¦ã€³á£¸®Ÿ³Ñ¶}¡0ú\žÍúÏÒÑçêRtÝßG×G{dŽ'NVH,‚5d¬©ý4Õ‰{_çåfgz4ôôðÝ^-ŠEºPnŠw¬Ç»Â¶Ä‚2Òc”¯HFÊËEêØQèOÏóèìì$•J‘0~ÔzU¾Å´0%á`ëÖ­Üzë­,]º”¥K—rã7²uëÖpýöíÛéîîµ\`ZO__†aÐÑÑŠ‚¹\Žt:a `¹\.ô~Tâã5\@0ƒ ”mòìWÛ¶‰Çã¤Ói\×¥¯¯žžLÓ —Û¶ÍòåËÉårôôô000@<'ŸÏ344D>ŸÇ4M>üáÓ¼q~ÌöT*E__©TŠ>úÑrþùç#L•‡m¼ÉóÒ‰êV&ú•} œÉïk,*0ªr¢Kc™Ðè6•PÉû9ÑvDMs5ïû,§N¢¯¯¯è~W6¶ô~,ý¬Dbµ}é=ŸÏç‹>«{MÙ’xPâ¢*·Ôö÷ôô„ËUùÑöGm¯atuu½põo_úRÑÔ©:Gï{ßûèííâÓº(OŸ¨gÒXÔcÈÓÉN¼W}¼ÈáÊy-–z$–£âáè·A'Þ Ò<éÙ¬ÿ ¤iþZ¹ýr¹ÂC–e¶±,ÿù¯”tº°Ü²Ê? e³å÷Ue–z} õ‡òhŒ†]V‚a–l˜W0G.Ìݧ¼Ç¢œ§Ê71É–yݵRAq¦…G{”T¢òàŒ¶a2BâX¡U+a2ÇI‘"I»ÈSp*¢çdBÔ– £Âc¹²Ô÷ÍdΫò¸AA&Ç)< q55^ž?ŸU§NñìüùeÇøž7vxÏÒåýýßcðA æ½ð™àañÑe¿ÍâS/qôØ™þ†Á¤½úø©Z5çÙUá³±š‚Š>צRÀWüçKÇ)äfô+ hþ:MûN°w~Vu¾ ö¡’çeÕ䱆—~þ¨±žÍÝ`½”¥„³T°N s=|qLÕ9ì§ÊVÇWÞ„é`yÆßÖò×á mÁ¶ÊÓ/”ÓYØ=XgÀkÙåYY ê”Âý4 £ôá €DÚ• ¶'(?ÚÞDÐ&=¨is"Ø.G‰™z°Îꚉ´ßz çT ª›ôMlJlò뜈´AÕ98þ²¾eðkTÅ”…Çþþ~n¾ùfÃe›7oæÖ[oÑq ¢“ôQ”ŒšXW“ûQ!I‰^ñxœ\.‡®ë$ ’É$š¦áº.¦ibYV(r@Á3NM|+aRMÖçóù"!D¹ÜöôôŒš`·m{”¨‹ÅB‘µ>J.—#™L’J¥Bï¢|>¦i¡PDWÞU‰D"ô&ÊçóE^djR^m¯¼¶&w•`ª<„T™JÔQB†êÛŽŽt]Å å1¦€\.WTwÕÏJtˆÅbaèD%L „Û'“Iâñ8º®ÓÙÙI&“Á0ŒQB…òd³,+ôÆ2 ƒX, ‘Ñ}”š‡‰[¶l™Ë½!™L. ¼•÷¢¾•¸}‰@ … uîR©Tè1]ÿøã³lÙ²Ð0šÏ/•J…/tvv¢iét:¬O&“ ¯•Á£G9xô(îÞÍòÀÖôõõ…÷‰²)êºTy•0™H$B/ëL&Sä= ¾RõRÇTžŽÊ¶¨kÙ¶mR©†a‰m 员L&éêê ï/%îE_>PhšÆPðf™Z744D$<=‹- ×)q.º´ÌÒωDbR/h$JTõy¬2JmÕDÇJ$&ÿ-aúÓC·.ч‡©ˆŠ3‘l²Ì¶—“eºÝr9ÿE=à€ÿ0õfT—.çç*Á © ûÍ™aYþç®®ÂÓDuTe©òMÓÿ[.TŒª¿aA][x, +[z Gû#JTlËsSµ[Õ]…ÃfŸ¹"‘&MŽ::)R$H” QZ‰ õvœ & § L)Ü«Ú'KvÜñ–:öXu˜ŠýJßuœJÛµ·¿Rp¢ÜããÙx kTè×éÊe.‚ ‚ÐJ aã+9¾j£sëÙgóÓýWô2…®;¶×£ã€qß}°á ØeÓÑÞÎe vãœ48¾re¸ÑÆw¿žóÎ?³U¨äÁ/+<Ç:NsñÕ…ÍÔK°±˜_cõäbÛþo*…ïýÖtƒy èûÀYŒ/„©fÙàõç–4$‡/bå—¤ÄÃ81Œà_”Óƒ.UœŽ/©íô ~Áñ ¢š,Ó"õQe¨S¥ºÌ ÊËEŽòÛFWÐ^åYÙ…/Ðeüm½ÿ¬¥ ‘öDÛ¯#‘v¹‘mUùfP¾ÿ}eþW¢£FA˜-ÝGµ/ô[t¨Ú§ü42ÅíRâ*øËßs˜j™²ð¸}ûvŽ9Â7ÞÈÆéî»›¶¶6 ­Zåå§Âø•zªð}©T*ô’K§Ó¡§®ë¡ õRRDQñM…÷T‚Z2™ Å´¨w•šàWËJàŒz1zžzQ 娄5 (üa)ª™L†T*ÖU 5j_ ŨÄ%þ©ül©TŠl6Ëœ9sB*%þ”â8¹\.ìOr±««+z‰íííaŸjšöA6›ÕÏjy4¤£jC>ŸåešÉdм “Éd(ð(Q5êAÙÙÙ ¦¨·¥Z®Î› ã©ÎI*•*J«–Å+uùh!ÔK*>'Þ$&´TxQuí)O@u®ÆóìUB¤Ú/*à:tˆÍ›6óÍ¡oâº.íííaYꯚU8Ru½€]tO>ù$O¼ð+V¬(òÎS×§ …ªë:ù|>«Ç)ëE«¼ùlÛåõ«¼úJ¯5%D–óú+ÇXÞÇ“õÐþÎ}÷±`É’IíWÍ1ë Š‚0Í88a>¶©Lb«}šÑÃĶƒDïšÿ “ÉŒ~°*—CB‰rJ T"\THŒŠrѼŽÑuQs jV d³…·<ÕñÕ›m;xpÓ‹ë¯EÞUÂø¢iOO±¨èºåCÂŽåÉ-o,ÇÒúN$<Žåq)TI„¡¼utzè)Z7™<“É«ŽW)3e‹4´1=9kõâEµmî?ᱚm•\3ê{ªåÎI=zæ ‚ ‚ Ô;/„±ÅÀWL/fÜy×r/›f2~„ㆃp|9Ø6ßw_=ùLÓŸg~ËYg±À¶ÑëàYß³1úü ÀãþµÜó‚—h»a`À_žUá;ñçAÍ  ]XxN5.r ß ú~¹Æ9D)Ûÿkýø}=ø“«Na}á <•'ŸÏÔT©šVWy|4NÁ Q‰lê‘kˆB.B% ¹ø¢Zt?3øÕ‚ººÁ¶9 ^„Ê3PígR,öE½45˜ÿçóýmTžG3RÇ8£ßþ/7%lPð’¬tª>:lößXëûÊ”¡ÚfínŒ 8ï£ç±ð= ©†) ƒƒƒôöörë­·²yóf6nÜÈõ×_OUjFTØÀx<Žiš¡H¡ò‚©p…QQ1‡9Ü” ‘H$Èd2¡¨ &ÃKE|>O, ½§lÛ¦§§'¡ÊSåms'ô˜Sa!­ ´ú«<–ThWåÑ¥<5M Å8%€¨0©J\QuQõŠJ8‰Åb¡¨iš¡w I¨ê¢ÄÒ|ŽQqNyWª¶)H%|FÑu‘‘‘ð³eY¡Ø§DÁ(¦i†BŠ:žÊI§L$ eV"È ãcc£¡…ÞQÁÏÆÆÄ$C&ÜN1•îã…cŠ`“‘ªñÜñ<&+Oë Õ–éLÕµ¡˜náQÕ¹Òv ‚ ‚ S¥xgZ…©¿Èå@ÓH§ƒû?ß k†ÁóÐÎÝ€mÇ0M“Wþú¯á½ïŶ‡Ï¿à¿è>ûý¢ð|¨<"À{Ø ¦ ‰N˜¬3χÔÿ€´ë?3{ØÊk/G…º /@üzº/õ¼T‚cÂL }ÄÂñļ€pW «Ñò+Ú+u&§ŽÆ*Ûº&ÞýìÇÏfÅ›VTU…) @˜ßQ±qãF#(á/—Ëy˩Ф*´¢(Js$*‘R {¥¢Äx9KC§*A¡t½ 1‹ÅBq°««+\¯Â‡ªÜtét:NK½•¨¦ÄGåq§òÃEÛª(÷Yõ[¹­¥Ëʉ$êxê(H…–,—³ÊËRy‰Ž%ƨ¼‰ªTN¼R¨”±¼BKÛÛ××z£M$)qU š¥9…ò8À™¸¼ŒW‘§€Æ•P¯Î!£!TÇ£œHÖ)˜Y^¸°ðvIÔã6ŠóJs *ž|òIŸy&›^õª1ëÍIX •„û¬'-ZTë*Ì:³›É¯5pqÑÑ'•««°,_¨*ý Rb£iD5Móÿ·íò!N£â¡z`RÿGÅ¿TÊSCŸ¨h§¶Ñ´Âƒ–:ž³Ùb‘Ry.*ÒiÿꘉD!ߤ*Š…ÌhÈר¸=N.çG ©ªß·H‘Õ² ÞŠª\%"&“02R(KÕ_ýf³~YCCÅ¡d£Þ ªüL¦ØË1ÚaêXX$I0ÄPèݨD$%N5`)“ ?]”º&# NäXn½*_yMN·9•±Õ0›/¢Œ×WÓ-  ‚ ‚ ì æ„£¾¢)B•ï#›Øæ8göÿ’oœs¿ó|žlv9f>‘ Æy{ E8ĽàY/ ÖsÁ3î#àÞ o%þäPÉB:AãE@=#¿ƹ -6zñéï> F_$ë ¬¼Ýà¯AApSb\>(Gyõ©í”à—Õ¨< ¡ØkPIJ(+f«ÓËI&) ¡X•è×Ó:<žÌ£K˽ï'¨ªŒ)‡Z ”†ÔTËTxN`”ç›¦Æ '„ÞRJT˜l¸?%Ž”?ŠÔR©Ô(!!ê]Ý>™LâyÞ˜"ˆª»WUÙêóxŒ%8N†ÒüzPxŒJß<‰ôÁdQ^¦S9^9*õ@SÇS×–x9VŽœ‚s7)£©T¡ Ó,Ô[ Ñv)¯D>U…‡…B{À(UØØhÎGMó¡¼KQíS¹2LÓ/+Ú_¥}0•@¨<=3¿ŽJ\,†VðûLµ;Z.ˆð8U<<²dÉÁÂ"EŠ9’$±±é¡‡Îði¼ù$‡§¡ ?„è ÓƒxC«°Š•2Ö¶µžVZ)é´¿<“)!£^rJÄRË•ç¡ò>´ iîBoDÃð…°lÖá¢e'±Ìq|QÓ4ým £~Õ4ý}òy™er3zžÿWy†ÿÙu †¶]›H?>UÕ[å¿0M¿”礪“¦ù!mr¹‚p©PÓôÿZVA¨TõQÞ›ÊR}M(a0“)ä‹T}¡„K]/xhªm;:нDs9ÿAü>RÞ‘ª¯Õ04zî“Éò×Pžlð„y54Ҥ颋xÉSëx¶b*á5KÇ&cÙ‘JËV¹&kÍly ÖÚîŽW‡‰^Ri´—XAAšƒÑŽ3a.‹0šOôÐu±cÙŸêäGò`ÇøÈ¿¼‡.à S²áõ¿²»@› ÖŸBÆVû¿™Màœ÷h @?š þ•l0¶@ö6èŠ1p_Ùƒ—pU~Æ. "bŠâpZ)н ª ¢CÞx°"ø«†µ]r:Î&µüiþr! W—ãqn­ÑèDóô©Ï@‘è¨B/*‰CCCc†ETèº>eáÊ0Œ ½§J&“™Ð+Qå¥,—n¦Q‚¨ …©BÅΉDbTî¾Ù$K^Ç)ЇËA\Ü …Gu_+oçx<æM®ûͶ§'ïμyóX¹r%—\rɬôc½2"n#RûiÖæ@yÝ 0PÕ$¹šä¯Å¸eÁCùÿ—†Uæ&úu‹ĸ¨Íó ƒ†Q,:ª J<+“ÂÇ)ä“pþöÞ=NŽªÎû'á’pIR%³Än1 Y J·Zn» ¬=qW² 5»«Àn´ûç>¢âºvKöd®Ýñ1¢ò<¤{½àO0Úµ*(A° W§„@‚0•„@Âõüþ8õ­ªîé¹_z&©Ï¼zººê\ërêœïç{ñb¬»;nħkÄÎÎFBMbJŠE£ÄŒtÝØj2—‹‰È¤¥¡¸ºÉfuž|>>ú˜ IÑ|>¶È¬Vu¾ÎθÍÝݱf’\•º¥årLÌ ºÝÅ¢ÞNZkÚv|}Äú±³So{ž&JÅelÒÍ­ôMêle!Y.7ƧLÑ?<<б°(R$G‡¥aYB2^4“„ã9Ž ¥ì‰vY:°±ÛNâ5Çë ÆÁ1úpå©xS¤H‘"EŠ)Úf¿ZƒÎžwïÖßB<†‹7/Ð9s¹/¾éMüñíÿ̧>þ)º='öÄçOÄ›3Áû çAvØ×i¬‚3²ïÔ<¢ÚÑÊ»(lOH0šŸ ÛžE»•ÎdÑD¢ÁÀVˆ}ÝŸ&áYWö™¢¦«Imçoã¶snU£²x\¹reËý­,kyä‘ <5×u#K'ÏóèêêŠb½™¦o&¾ ÃwBNÈ‘‰&þ€(¦e;È/9×®ëN(ᘬ_â2¶©¥ãÈðRh!àã(°i~®ä“gz¤÷œ¸'Nb,âΞ=›ÓO?}BÎádÅž={˜7nkSì›ðñ©R–Àº¿t5jC*cÄíõcòM^C¦©I²çŽ‚Ã‰-ú ¶Î2Q$ª„\”}®»õ‹<©Kʲm]§‚Ù¬&î,K“bbèºÚ‚Ðó4ÙY©ÄdcÒ­©X8JùbIšØ F# ÊjUçKzLPÚ$V‹¹\LzŠEb6«ëéèÐýKL©×4cW°¥RüÛqâþË9–üù|# (îW3í†6Ÿ×¤¢‘õzLzʶœ‰=ÙÝ­Û/ÖªÒ/±ä7­±•¥\s¹¾§œ2®·ä^±¬P!OžB¸ú60úŽCµ8l²¸%,2æD`D㯴e¬:¯Á:v8ñ;Gc¡Ú|N'ƒµkŠ)R¤H‘"ÅÞ‚ÁfÏÙC~ŠË-ã^ä­ãåÓOçg‡ÿŒo=ø&ÔOGÇnºéE,!¿< †^ï-`<üMNæ T„òIÀ]À‘Ä„Ÿ ÆÉÉF€}x?µôh§æ©óŽ}#".\È¥—^Úî¶O QŒ«'„£mÛ‘Ë͉&ÀÄê*‚¶ÉK8^h¶4mÇ9H1ùѬg>˜ÀÐó<‚ ‚(–£À¶íQ=oA“IÐÂgÂâÑ÷ñ’K.a_5jÙµk[_~K´ËR¤&ºéŽÜ* tG#¼—§bÕ&D[’l,—cëÁrY}”™ /²ÞI®{„P”}Ž£‰8±¨bK<ÉÈ6Ä®V…(L¶O,ŪÐucBPòtwÇ–‡¹\\ž´'óÐqbK=I 1%o¦“nB$&‡]ÉŸô–](4’r.“^ê“é›<ïGçÆ¶5y(eÊõ”þK›¤}]]ñþ$ÉšDòzÙv£•¥|‹;XˆÉXùT*ºžÝ£tŸ²/@”’LÌAÇHnLÇŠøJ Á±lÃPHÁÁÒ FZzÛÞ µ˜½l6+Ž^ÁAþ%gò.aËõËð_³ ÌÞ < Ì 0]{,ÍÍE[,Z@¬÷êï„ëÐqµVÎ[ÒébŠQbÄÄãªU«Æ´!;wî䳟ý,ëׯ`É’%|ñ‹_dÉ’% éV¯^ͺuëØ¹s'gu«V­báÂ…m:}ÚªÎ0Œˆx, ‘•_µZȉ‰†í&ßÚ˲p]wŸìûTF;ÆÑ3ŸIì*A„3b¹,ÂQb¨ær¹WË£½ß’®™=σ³'îÜï­xæ™g`Þ<Ÿ1£ÝMI1 L¦9ŽãáŽN\np]’$Å5¦xj˶$Ù˜$Å*h‚îS{àc6ú~L,J™2ì (±“¤_2^¢äkB±„8Ö¡ÄwÂPHÈZMo÷öÆ}n>Òž¤AÿHŒû¥]b½)q#‚ã4‹c‰$¹*u‰;ÕæØ‘rÎ’¯™þÚ%nVÅÂRêrÚ04á(n]Ÿzêˆñéà`(cÁDŒ.SmF[p¨DÜ`é†bicOŠØŒc…þÎÉX‘›CyOMÅó9™æ)R¤hÒ± EŠ“kˆ½V,¸ùf +V œúù…¯îˆ{Å"'¼éïqÿxÕÇ}JÊÄÅeÉ´Åçüì€o=¹oúÞÎ#À\0Nã|(_ÞöÐûÎ%Ä–Y0–µhDx¼92˜ó¥ñ»f)ömŒYŒÇ 6°fÍÖ¬YÆ †ÿâ‹/fóæÍ¬]»–µkײpáB.¾øbvîÜ¥‘cÕªU¬]»–Í›7sÙe—µåÄåóy¦M›†ïû8ŽC¹\Æ÷ý†¸~¶mÓÛÛK©•úûÀ0Œ1‹7Õ –§íг˜bdh×8`sš÷"h+'–U«UŠÅ"†aD±MÓ$—Ë ·ºÖm¥ßù|>rÓ{Äc# va޼öNÌŸ?¿ÝMH1 L¦9A@0"A­Ä€±âv4Q'ÛIë<±(„FÅ¤Çæ$©ÖÝ ;ÙZ¸],ê´¥R#¡˜$ÅŠ±ZÕuȱ|>¶H,]·&c'‚&Är¹Ø5©m9Åb“–ç$‚¸µòUÎýH Ö£²-na+Møf³b;ycB6LÔ80 FšõáH”†; Ç}çPû3\ Åêq(ù§ªež…5൨Ròµε˜ªç¬?L¦9AŠ)Ú‡t,H‘"Ådf=óÌ 3µàõCð‚ ‹zãnþîõÿàÀ7„^¸ä—ðüœx»â²?݃yp˜¸î!à΂Üzp>ÖEýTVˆ×­ì#&ëZ8ÅÞ‡QÅxܹs'år9Ò"HböìÙ¬X±Çq˜={ö€ålܸ‘7òƒü ÒR8á„x×»Þņ 8묳X¿~=+V¬`E¨Epíµ×bÛ6ëׯҌ'’q‹Å"•J%" ŠÅ"¥R©ÁÍb;\œ&±/[ýår¹1#„RL Ú9XÀB§«"¬iv{êyÅbÛ¶c‹Ä1„<§®ëR.—ñ<÷Ï|ÿÄœü½‡¼ú*>ú(œzj»›’b˜Ls„x, =†L„`TJ¯EDoÈóúŽ!“iÄ:Rö ±çûpÌÎx^"CX¡ ‰AÏÓ¤a½“šI—«R†¸ñ ‚Æxˆ²xwŸµD(µZM—ßs±zY¶­ÏOœQ B>ŽIW³WSb>& ß«¯^ ,vù㡌1T©b` ‰øI>ciYfb‹x ú8’"'G‹ÉîÊÔÄ$Ç)™aP¤Å6CÉ;T çœNöó?™æ)R¤hÒ± EŠ“u˜Û;wÈ¡¶¬7¿Ç üçäŠ^­‰¼ÿ+K`ÛvÞþì_Q8ª¯ïÿ"Ø@ù_ €­ˆ\ &l%•U $–$‰T\žb¢0bâqçÎ\|ñÅlܸ‘+V°lÙ²ˆ`ܹsgd¹aþýíoH>Ξ=›K/½´it7ndóæÍ,[ F.\È’%Kxà&d!ä¢çyض¹T—‹íp©:jµ¾ï·Ýà¡õ䫯?VxÜÄÖï.±Ëì ܶùâ„^¸-1…ËáoYaþl˜Æ ?­ðÊÁ3ÙÐîqà(àý8QÌ!‰åèy^äNÙqlÛîCJŽ5ŠÅ"¦iÉO|Šþqì /p÷®]ínFŠa¢ÝcAÁ˜ e3™F2âE€xI2ùêNÆ IÛŽ·“d£eéýBðåózaQ©À÷wÀóh²PbŠKT±lììÔõ$ãHŠ'˜ZM×[­êEŽlçrqüD!ö’°í‰µlr.÷µ©‘¸Y,×a(l,˜¨q LyÒºYªõd‘"Y²˜h÷M04r²¿:jÀ4Ã!][õAâiNrÔIJ"É`3  N}BI¿fâRêžìÖ‘“iN"EŠö! R¤H1)Çæ¾1wHrwç$àÞÿ 0ß„ý Ž`ù´‡ØóÆA°`»î¾Ü”y)TÿÆ[Àþ‹ÆC²önÅ}Æf ›"ň1bâqõêÕ‘ysòœuÖYœuÖY\vÙe¬^½š«®ºªß²’1#7nÜÈŽ;X·nK–,‰ÊÞ±c@ŸºæÌ™ÃÆlësÏ=ÇêÕ«Y¶lÙˆcSA@¹\¦T*áû~ƒ¡a&éÓڶ뺑bCŠÑaéÒ¥3ˆ¯ý}+W®dÇŽ{ì±ínJLÔœ`Μ9¬]»vÀ´Þ˜ e“$žëÆñƒ ¶>L®WZù|L¹n£Íb±¯¡mëtAƇ–_¤Ó'cÿIyQ¿=M>Іd6«ó yÚÕ¥ë’ø™Œ&6 cò[ɾïKHÆ’lܸ‘Õ«WóÄO´œË·ƒ<ð0ò9Á¶mÛX¹r%K–,éw}àããâRbèæ¹nø7VVrÃ……Ež<66~â/Ož:u2d×,,jÔ†Xc_ FÔñÙŠx¢ÏÇŸ’1 ÂHï‹…!½lì!Åæ40"yõêÕlܸ‘mÛ¶µûôôÁD¬n¹å6nÜȪU«f¦H±·#] m}"ÅÞŒuëÖ±~ýzžxâ‰v7¥Ú)3ì>l›5´ù“±Š8”Š&hÀÉ5–>þÿñÔ´[xH)ê‡ ðƒêc`eBoHûƒ÷ X§4–)Þ’2™FoG)RŒ«W¯fÆ £žŒˆxܼy3ëÖ­ãÒK/PP±lÙ2V¬XÁš5kXµjÕ .W“†œg0~øáœwÞy£ªˆ[E×u#˧}1QÄW®EZ!ðœ0‡&|‚ÄÇGiÉ¥±—È+¤š›¨K¬e‰m…u˜h’®Œ&õ<`1H¢žîÄïN D#)ÖŠRW9,?î/…¿‹a=b‚Ò û$¤¢IL@J¹Ò· ,³#<ÖJäã$Ò7ïÏ„e ‘Z ˉ°x1°üw¿ƒI¸ ŒÇ8pÔQGõ»hÊ3ïyÕj5rµ šRß²¬È•k.—£Hqô…îØ7o¹b‘}3ÒíÀX»v-6lQLæ‰D»çceñ˜tƒ* ¥´µ ¸Õ,—õq!!eÛq £#v§*û=/&0ž[&‚&*ÅÍ©ë6ôöÂgMV*šŒÊå‰G‰¿X,Æd§m‡AëíØÝªaè¼årì^u²[¦Ó·K–,aíÚµ¬^½ºÝMã1qă ]ÜÈún,1Ü8ýµ¡UAù]¥ŠþåÈ1yÙW¢D]ýöËÀQ,Ê¡b¨ÖŒcei¸7`¨ï¢c¹š!B¼•+W¶»›b¼ÖçœsΈ•“S¤Ø›®F'3L‘bo€¸(ÝWçÉ ûÃîÝ»N ’‹›Â߸)Ãã^¦çï"Ã9\±0€Y›´w+ð¸Nn`žÁoõš½Ù‹ÈR¤K¬ZµjLæ#&!±ÿB<>ðÀCz‰Ë¾aÃV®\ÅŠl7ÜP"'Ä£½ªøh‚/éªS6Âc²tÿ)Ö~bWD“sN˜?IY)®Iú’o’ßLÔa£I»"±õ ,¿…*2ˆÉB›˜à+“uBvz4’›~¢¾21Y£‘¸“r’ĤO#Ø‘HŸM´/)ëL–™ù@}ë4Ñ—ÑÏ>«Z…sÎFI‹vŽI-qÏó°, ? t–´tâÑ0Œˆx+$KÚûF­{;Ú='ððFEšÀÂO¼uõ*üô„ira]bå(ˆ=h"O¶{ÃO-üݓخ„é’ù ‰|ò»H'$_ó•Iþ¶š¾[¥q}hÜ6Ãú+-Ê‘øŽ kß““a°±#÷`â^U\ªŽ%Ø ØzR¤˜Ì˜ cAÃ%óùFR0¹-V‹®[3Fcˆ‰Ah$'“šŒ¾¯I?2òù8¸¼œ‚¦ GÏå-(«U½XqœØ*°Tjm!ØAJ(¦h' Ækpq±±)P W—£ ?1C«øµ#A.?S¤hÆdš¤H‘¢}HÇ‚)RL¾qÀøPHòÛ€ 5jÇ€Õµ”é3ãÕƒŸåŽŸßÁ[_ââ+.bÓ3óØ¼¿x[ÓJÆIE`¶’Ôj­÷§HÑnŒˆx<á„tv0HÉÓ gu;wîdÍš5Ñ>ñ#›$,W¬XÁºuëØ¹s'kÖ¬aöìÙœ}öÙãz’ªUMÛ LÓ·øŽb‰ØIlØnw  Ã<0F‚±M<Š;R!“C`!ñ©£-ÅBÐ÷‹|Ñjú=äÂþäFYÎH!b•v(|ØÄ1+ÛÑw©I<¶kð€­-& ɸ®…BaB,ÓØ±)RLž9è‡"wÝFB1­ƒ ŒÍÐÏKÁó4©hÛñ"CbÙhš1±(îZ £o<‰ïhš:ŸÔošpãð‡?„ýóãøŽ)RLF e,q@\,çÈQ 0l‚n(± Û…€ u¯šbJa²Ì R¤HÑ^¤cAŠ)&Ë8àÒ—rl°xKqGø€ ·ê™ÇÀÛ•â…ãþ…®3:ù°5Û†]»å™Y>ž§å bå(E˺½•½‚ÈR¤˜lQŒGñ¼fÍN8áÎ:묖éÖ¯_Ïš5kX±bÅ€^.\ÈUW]Å•W^I¹\fΜ9lÞ¼™K/½´ÁGóªU«¸øâ‹¹à‚ ˜={6›7oÓ ²±p¸®K64¨ÕÆ76†C[1éB4ŒE‹…¿2aúÞð·A_ëÁ é[0JYâ8‹û"š-ëÛ©vîÛ=$‹bíhš&¾ïcƸY:§H‘¢í :ÃÐFÒLF~²ëC!#}_$–¢ Ùª¸G‘´Ž[4Ê$q‹Åx_.§Ó‹:o.§*ž§Û”ÏkÂrù9pÛ+ú¸a¤Z‘)&7†2ŒÇ8àâR éĨ;ˆÚ›ÝòObK¦ÄcŠ©„É2'H‘"E{‘Ž)R¤˜Lã@³¼·ÁP!t­Šòa[OJ³PX°þò¾¿dƉ3øùOjÜqè[áè“xæ}8Ÿ—uÙzŸëêµ½¬ñS¤˜ ñúA~à¸ì²Ë8묳X¶lYd¶¼yóf6lØÀúõëY²d «V­´¼+V°lÙ²È5ëÂ… û˜AÏž=›üà‘ïæN8a\&år™Bh&àº.år9"ÇÓÝ¢&‹$âJR˜S ´Å¢‘ø=ÚA€µ"B÷XýlO’–®SQ¬ÔÎq ‹I¬…xœÌ1]S ©ï4Å䘸¸ÃЋõ¡iêm±r,—ãxЦ»U-㘊ɘ ®Û¨±(CmÇ1“±$^$h+F±¸Ìåôo!1}NÛ ö¬q¾€)RŒ Æzðñ †Ûu8h—‹QsR[c¦HÑ&Ü EŠíG:¤H‘b²Œ2£>íÈÓ¸Ûû&°€[Ëð¨o¶`&°Λóæ;ó½ußã¼SÎcÖ©oá¥M‹90‘UB¦Èú^<"‰2qjÙ˜b*aÄÄãìÙ³ùö·¿M¹\fݺu¬_¿¾ÏñK/½Çq†ü€·0Za x‘c7!ýËd2är¹ ‰½&†Cu¤ãÌä†ÄÔlÇu]š©ŠvŒÉAàºnÃ3?Õ‰GñðÚl¦˜Jh÷œ`8äƒ(8š¦Þ.—c—¨årß´ž§ã+ úx¹¬óf³„¤mëíJ%v—*ñK¥F‚2›…z=vÏ*1!v¿ê³RÒ1ÅÃPÆ‚±ÄÍêHãвÂd_(ñ+S¤˜jh÷œ EŠ“éX"EŠÉ0ˆÌuÖ3-×6ÚMá"à% f0ß禙/qóŸÌ'8N?ÿtæÏŸÏŸ_0ŸÞ zÿîãá‹èµ|¹¬¿kµXv\ß§H1U0bâ4¹¸jÕ*V­Zi¦ò‹Þó<|ßÇý¡‰õãD`¬ô«SëžöÁD¿„ÚEOÕíÄL<^ ·«Õ*år™R©„çy Š)R¤Øwàã“%;¤´ž[;ŠëÃh­X­ê…D.§âF¥XŒ-¡1~cµª?B(æóÐÝÇ—­I´?}°§H‘BàáÊiêÆ4EŠ)R¤H‘"EнÍþCú*„¡R8Ô‡£L¸Õ‚ùóä~¼ñÄ=œô7³ióZŠ)bœæV½Î/VZ¬lÜP§‡wI‘b*aTÄcS™hlÏó‚`B,«qþ VAâ&UັËÕV¤`¹»HÍdb-Ƥ~ƒ’âvô"Ä4¹4`kŠã‚áÄvjH-S¤H‘"EŠ)R¤¶ãsPH<žpÝ 8ÉÅ¿…6‰,„Ÿçò°Ó#xñ<{è1œyæáÜwߛٴéè- £1ŒŠ—:-J1E‘MHZ<ú¾?án÷NQG{±/ŠYªínÀB<Ödo<––Žþi=µÃ5BrKÇ—)†wP!}ÄÄ¡ãı$¼¸Yõ—gžùK|?öžäy°k—Þv-±¤ØCe'§S•)DJ<¶@6›Å÷}|ߟ0W‹ã¡¼*Dì›qÙ¾H¸ŽÍÏÉX<÷ÞM@¼ÿþéír9N“Ü´à RQjŠCÃP¬žšµÅZQ,Ëåø9Ïçá÷¿ÿ=•Ðw2.£eÅ.U-K»S­×õv¡ Ë5MýÛu]|ðö>mñ}Ÿò¸*)RìýØ[­S¤H‘"EŠ)R¤H1z<˜”"–Âï|ø”ÃåóZhàûpä‘<ûì?±eË|ž~z7A+[rˆÎf:kµÉ¢$Õ3N1‘Mð<Ó41 ƒz½>aÄãxEqKÉÇ}"2K‰ÇáAb¹ù¾?jËþÏÀ½Fo{÷€¿=;¦k# aðøãÓèêêë&Å÷] £¯cµÚw p]7òÌ„¾^]×M-S¤%<¼}ÂÚ1%WS¤H‘"EŠöÂE/»»ÐKî)RL¼ ¾öñ ý ˲½€È>Z+‹‘@à±cm(ã´ÓŽÄ0t’|^“—\ÒX•NÙSìH‰Ç°,‹ÞÞ^¬ ~ÊÇékÊì{(5R·š£Á Ï¾Ûb_9üxàÝŠ&üªÀrö>¿…à-€ îo¼—õq¼p_è‚=O÷ëýtOjºˆWw¯\¼ðw7úè®I´QHÉ. ¶·+,Ó ÷ ™ Ë©¢7LßÖU÷ ‰$ò$÷d*÷“·yU6 ÍŠAEÉAØ÷æïæúòáõ‘sÐ Éë5åÇG¹çÊaùD™ñ=Aâø@ç73Âvì#ðð†ã4)1…h”cb­°mÛ¸®v’ÍÆq«Õ<==P*%ê÷¼ˆxô}Ÿb±Hø¾OxžG>Ÿ'“ÉD1©ƒ }ã§H1{uD!÷r5EŠ)R¤hdÙ,Ëé 0-üÌC/é§/Ý ^¶¥H‘bòâ¨;Þ?ôðAž(c þ#¯êD¡lñМqÅŠo0w®ÂucYAz%^Åqb—«)RL%ì7’L6l`åÊ•ínû¸Àu]r" œ@Œµ¸0ö]¤„ãðq7.k°$êyô*ÁFPP ·A_€Eàn» üã‡!ûYðOïÈ!?u-!¸{4Iáíÿvm±zoö?#,Û¿sè£S×ë*°3a½Y Ž&–raú¹ÀN`6zåã$Úl“V…ðX=q²Âm!:= 7ìw9Ü­Q„û«aÞ|ئ11™ ÷á1üÊa:±°ôÃö;Ä7µ«„môÃz¤¯Å° /Ì—˜Äõy.üð¸„Ò&ù]HÔï…¸áq©OÚ‘Mä—ó„û+a9Ç’Ž°œ*qr9NøI˜Å°½~"_¸/LôJVÚm„Û$î;ütëã_é`ãâƒßóû # „X”Å€¸Y5;Áß}vïÞýþío_åÛßþ'¶m»ŽµkobåJ,­…xô}Ÿîîn\×¥\.GäbµZ¥\.cY™L&¬'µxL‘b4öjRnoî[Š)R¤HÑ.ï zº‘*ÐK5YXÄËÁæ<)R¤˜üØ>Í{Ú£tý€oön¼9]{öèƶÍ[gl㢋þ‹ÿøضϵ×jYƒmÇ É‘’ ‡n)„2r¹QQ9EŠ©‚sæÌaÙ²eínû˜#ŸÏcšæ„Z:†FNc>ÙyŠ)†‡ _ÿb' ½rp‰É§¤õ™þ[À<¸‚"°è„ÀŒ5š’ÆIÁ~ü ¸ ‚2øÇ€Y'~G¶¡Öéh_ïÙärß v'P€ªºk,…$H ¸-¡Ø`‚ï€YHô'œä¸–žô1A…vkü7>˜YðÂ>X¾Æ?BC…íu‰]Mt¢:)WÈSˆI²š¨óÃo!Y«‰}54W 󈊨|—u—»€£ÃznþCŸ¿ˆ8MˆVX® V¢œRxÍ“çÍ!¶µÃ4n|Þ"B°¶Í ëÌž$¾b¢S^۵Äñ1i+ç(¦«†õË+LÔm%½«ëíƒ?{0s˜KŠFxáB¢ñ˜ÉÄ ˆc8–ËúùqݘtÌfõsX­ÂyçmâöÛõ[oÝŸ¹so®âÊ+¿ªëô0‰ ‚ °°Á¬‚ÿ0Ð ^1&%• ð(x§‡ù³:¯hJ‰/yMŽˆÕVµªÉ×÷Y(Ôt{½ŸÇûƒ@Ï¡ªç„M³¡Z&ŽU'ñêÄ¥gñ`äÄçÀJg«†JŸ“ç_Ê!‘Þ!&Ödè®ëk´{šxì¾ lF¾&šÌ3ÃOÂ…Iƒ÷J"}+TÂo±tL·r_Xa› b+Ë$œåùDI 7+‘^ çܦÑl+ßËÜ·à>žØð)1µ£ïÇ–Þá+”BA[¶láå—DéJ%ø×Ýxœyæ½<ýôLŽ8¢ƒ3~ÉÏ~v+†aDŒ¦ibÛvoÚ÷}*• †aËå(—ËAYÕ³Ù,žçE.W-ËŠæ1âšu¨ URþDÅ·N14±ÜßüÔu] Øð{|ü½>þaŽÜ^íN6EŠ)R¤oHt½\K.s‡‹¡Hƒ LÓ$ªÕ*†aÍf©V«ÑºÁ¶m|ßoX ¤˜<˜Ì ¢²†L10<<||¶ãsüöSyù•¼rBÔòA­Õn¤BAað w3kÖœwÞÑüæ7»¹ýö¸ÜfB±ñ˜^žS#"7nÜÈêÕ«YµjK–,iwÆ"´IZŒ¸,b/x&±ìW ]*Äòî‰À¾(^H#]¥. ¶ß½ì !{#²¸¼ÿ)⎳É®« j5=)‚±\ûÖ úº`„Ð]ãw X®Ë`¦Þ?>¼º†‚C¶}?öñîy±”XRF^c—Æõ¹o·—4Ao'‰GObNú¸´×÷ T´CÈO ¶$®W†ÙrY×Ó<©*—ýÙ'Ïq¥™l3ËŒ…¿™ø},ðÃøX„õ$Ëp58غ!Ûô{¸ƒ±3ÌôÍuW‰]ê¦2Šïh1é.Ïèo!òzè—üú×ây°iÓ&º»§&'t#'`‘ËA&caÛvD:†¹N­T*xžG6| œð¡°m»a®"„¤Ä}´,‹R¨]P­VˆÇÁq7í8£¹ùRŒAàº.^xS†ã8 Ät­VˆÜî ù,×-ŒþˆƒðNúhó¤H‘"EŠ)†qbÓM¬û*^GŠ(¢H>O¡PÀó¼h^ŸËå¢p †a`¾ïGd>Ÿ'²Ùl´-ÈårÑÚ"›Í¶Tbo­æý®ëbš&åн‹eYQ݆aDD¨ëºQüy˲¢µK¹\¦P(P,j"Æó6+m yÛ¬*çOöKÿ]×Ae&éD1°\.ãº.ŽãDD±´KæúŽãŽãDíЦiây^´®S”L¥’FÒ ¥…B!j³”cšft/d³Ù¨m>úèø¯÷™¦Þ6ÍÆ¾N+}–|¾¯Ý_öôè<És|ïópæv`7pL»ï³ †¸TœJ•“YŸ„žçEîv¡/ÉX­V#AKŠ‘#uµš"EŠ)R¤H¢ ½¤*GÂèCïû ¤“IŽãhb¯R‰”Ì„H4 ƒ®®.Ç¡^¯GÞM„”óöØcÛûàMRTÑëë£þ°ˆàµ×`6Z}‘ ×µÞÇÃ3àn>Ñù;ìýüás¹0Ù©?ש²ÌK.ý …¾ û)RLŒˆxÜ1R¡T•8¼[m\b39d½Þè‹H‘b¯FøïyÚÊiÖ{fÅÖb²\#zÈ}_oZaL½$áØj)•4iX«Å¤…„IkÁê,pŽÕÇG“¿ `Þ¡àõê4bå˜tw*X '"IžÁóÀ±`ùOáÖ³C׍ը%«å„d¹“‰ÉýbÝU,jBPˆÀ Пb1¶Š¬Vµu¢aè¾äó:o­ko‰[Wϋˢ2tÝR®më¶›fÜ6©/i=izA»=<·Ýw[0^DSA_¡bW«>+V<Ç™gž‚ïÇ–Î{ö<Ã?x\p2¾LŸþ}l[kžº®Ëÿü‡ÿ èÅÞ{ö¼'Ö6vµ†rr‘<ȳ³³³A;×uÝHÀÐÕÕÕ)Çd±™\pƒ^ċࣙø§Æpc€IDATììì¤P(D$¦5ÄòR\> 溵a–ˆ­{÷Wîfé§C³m‰‘ ±bH@?v×vñì#ÏbæÌPãTïáÇPçx"8mîr¹-ô‡ZFùÚ,C«zs¹9'¾ÖH®V«|ùÒ/sÏŽ{"¡À’YKø—ù—¨Ÿ;¹³ÁÕ®¤K¶W„ “ÕÅS»á¥³æ)R¤H‘"EòÄ íôÔk(¤cµZH®îîn€ÈšQæ™™L&šÖëõhŽ˜´¾“9tóT'XD‚^Ôëõˆ ”9¦¬C,ËŠ”“ó]±º³m;šOJñ¦’Dó_à„€ìêê¢T*EžåD¡R¿$*dl.—Ã÷ýˆ$0BD&Û 4¬™„Üó×ë«V¡^‡iÓt>!%ÅͪôÑ÷u9bšÏëýÒ† ˆÉRËŠÏ­më23}—/~™×¾È}å¿8níq¼íÒ·aøFt>n¾âfüñø9Ÿƒ¾w†oð¹ùŸãSÏŠ=ÏìÁ3=z^¶oßNÑ(BNÎih“eYìüÁÎÈuöÅÛ.æ¾7ßÇîÓvsàõrÕAWqäÌ#YÚ»í*©Ò[á«ó¿ÊÁ¯ÌßÁ¡¯Ê©o>•So=•­ ¶Rµ«¬ü?+¹{ÞÝ\yÀ•|kó·xø†‡™«æ²ø¥ÅìùØn¹áœçîÿêýÜ·ÿ}¼ïïcÓa›˜qø ê÷ÖÙråè¯w ²]Y²dÙràt.À*Yú>)ÂÙœIþÎ×ùôôOó3ûg<¼üaý|»wïæú¯^ÏEç]Àa÷Æc7>Æ)>%¼ t^,˜óüœ6>q“A:kN‘"EŠ)R$PE[8ÖŠÅ¢ôUú $¤mÇÖˆårì*U¬E‰Ò÷uZÓŒÏK&·³TŠÏ™«Ùll]™Ëéóâºðưu°³ÝwXŠ©„€«ñB¹¬Ýú®^ýãá‡çòŽwÀ[–@õó°t)œgý3¿|úc<óÌw8¾çx¼cåu§—Ï×$˜ãèÉD" ôE]¤ ¥ Üg¢ý:ÉX¤bÝb­Ý¬õœ´œ,—Ë n‚ÄÅOra.}âÒó½ ÞËâspÏÇïá}7¾\.¥Éçó‘ ÅqfÜ;ƒ×Oz®®.r¹™LF–ÝEº»»Üý‹Eοá|Î}ñ\,,Üi.V§Å;ž}ßÚõ-æwÌÇÁÁ™æ`uZؾMŽù®<§ý§qÁëéÎpçIwrìníhþ–ùXXüI÷ŸpÃ;o {s7FÎ`úÕÓ™wï<N¸îÎyín¼÷FÎ<üLοë|¶œ»…ÝoìfÚúi¼ý¨·ó»E¿cÑ‹8òíGrÊŽS˜}ãlN<ñD¶nÞÊñÇÏÒS—ò¾o¼Ÿ÷üœ²]Æw}~~ëÏyÓçßÄIwÄ9óÏa»¹'ÿóInÚt÷õ¿# à__ýW^øÄ \wÝutuwñÌ…ÏðÊ_aÓ=›xü’ÇYñÞÚÂÞïšþÞö_ÛXpé½ßC»úîÌãT´Vü¼ióø¿ø¿¼éÅ7ñÝÿþ.ï›÷>Þ|ö›Ùô™Mp…¾æ—p ½?ë…hÂRÔö»áRÿRî¶în÷£×v¤nVS¤H‘"EŠM‘È18éèy™L†Z­Y–J%ªÕ*µZ-"’Ĉ`²‡h'†ã­$ÅБtÕšbø˜ÁNLŽ}áX¦=`i™û¡¼âAI VNÉuaÆŒÜvÛ½\ý+,]º˜•'^½ú£"RN8ÅÞ€”x$|z±•Ñ -J_)Rì-ÐÌâ¼íóX±i…¶nL*ç5½ìÅ=h¡ ?Bâ‰õžijB®ZÕ±ØBM8ÇÑ ±,ò.›c${,Ìš[V«ºœR)Žw(±3½-±K%]¶xâÊÁ²4'šUÙ0Ve“B"¢D(iÄ’3©\˜œ¯&µ±’d¬ŒÙ¬îs2&¥L´²Y½Ý¬@(eÖj±ËU!AçK*3JÛDaÑøwØó –Ží]#äjêµpïÃ`.»»á°ÃÇ?–µœß½ø<œxâ ¼²¬›gºßÀÝ5ÌóP° äçW@qZ‘êÅ-.ïƒÜO2òh‚©€&!=âÀÅÕp»#LS"ŽEëÓPZˆGÑNZ&žrÌ)œtÒI V”…Bn:€g>ö »gîæ‹¿ý"û[ûë2;àþOÜÏA—^¬¾ç-ïá´§Åþå/jP«Õ  µB Û´¡v¾ƒÍ÷mfÑÒEüóëÿÌÙÇÍ9/žÃƒß}ßÜÁÜ[çòGü#gwÆ5OÝôwÞy'³®™Å;ž}—_~9æ5&KÞ²„Íý ¶.àÁï>Èâ-‹!¿ø¯_°íámü™ƒéÍõês8–í‡ßʉwž]pó‚›¹ø•‹ùÒ™_j o„‚³9»ášßrÚ-|ä?Òx#|ÎG—¾ïS0ãçx–~z)Ww^9C®‡½ë0.úÚEœ÷…óbéOÃr–Çå&'˜á¹›m:.®§Îüþ™œœ]ó̦ ß<ì›\rÉ%dŠjNMß+~xeàçõsyË!còüLUøø£/$EŠ)R¤H±W  =îÏ®N,}ß'“É`š&™L8תÕ"w¦I¤dOŠv£9¤FŠáa;p÷crئÃX —‡Ða@øÈ‹Ìϲ෿}–{ï °íÓ9÷Ü£²d8¢ãÅ)¦,¦·»‚;wrå•Wò®w½‹ãŽ;Û¶Y¿~}Ÿt«W¯ŽÒ\vÙelÞ¼yÔu6ø éXbhn&RňSí4ƒtÀSÐ;··e !!¶mYØÕ¥'å²&Ñòù˜ä“XpI¬¹\ì5›Õ„Ÿ}ô&üµ·ôªÈÍh6 G §œÇr,•ôǶ5É&䥴KHBùôôÄe%ã!BœOÊ #Q84 Ý™LIŒFÃÐd¢´YÅÊ Òá`îÁ°ç5à~`c!låz'ceFwJâ:Š5§ìHœËfT›â†dÚþò¹£0i÷'¹Œ½shmùäºDÄÞž={غu+¾?|áY6¸çqkfrä)ž{7~½oùR¸çð{˜[›KñËhêTßNL4–Û9´Åc½ˆ)‡Ÿ1áØ‰VšôÐ’"šPª.E«j‘ ²88Ql“nÏì¿ý+޹ò—L+NÓí°€ó¸$Ï©w–ƒ_¸\xfÖ3üàÌ€ãÇ«ç úpžóçôÝéûÑƒÔ¯Ç ßçòƒâ™lˆi$}ë¸nÿGs}‰IÊšóoðÑ#ÔRw7FèÚKÒüüŸƒÇðþ’E%Gßy矔ñÇPÆ‚±Râ1EŠÉ‹vÏ R¤H190Qcèó D:vttD@,ËŠ,…t¦‚|1ÅÔ‡iš{ñØŽ9X@oÅdÎk9T¯âÇgo!ÿMb+„B:¾øâ‹ôö*æÎË/ùtPC¹ƒ “]f“"ÅP0*âqåÊ•wÜqÑ`Íš5 û’ÇÂe—]ÆOúS¾øÅ/²víZÎ:ë,.»ì²†dõêÕ¬[·ŽU«V±víZ6oÞÌe—]6&'¢¿ÉA-w+)/L ¤ÄcŠ©ˆvŒ‹Ð®VïÞ~77œCË4årl™X.ÇDšïÇ–zB¢ $î eiÒ¬Vƒ‚§}†––]uLìÿÓxãy ‡ü+=t`ýë!“!—õ9昸Îà¿ï†bÇÔê\N—kš`—»¨8ZxíX•JLðFB›êœãŽHÝFìæ”æ‰hµªM)'bÆãûqÀÉæý¾¯ÍÌ’A3“},Ÿƒm†Øö"Crµêy±ëÚP~߇‹HÆ«LrR5è|RN«¼A 'Éká=òùØz¶³3NÓÙÙxZ„+ÉdâýR†ìon»ì‡F7½“íš´²ve@K^…mÛ¶>›6­À] æ¼LxlËQ<ý¶ilúôÑ|zëRÊï…àvn†à`x}öQø Á› n¼DDc`¡‰F;2Úª9ýM>†ž˜(49é„¿ôÊ(¶ôõЖ’”(ñÊ ¯Äý(UøgW§Ï£'E4‰ù³<<=þGÎñµ»Qÿ¾>Å8¾ ÜNXëéý2Tœ’Ǻ`¾ÇyÜ÷ÎýYøÈBnœ}#¦eÂ-e¸-ÿ’‡‡l¸ª»u€GmèµàH·?û{ðŽ@¯øÂ¸„ЇØpz3-0-WÔÓ7wÁ#U¦¿1ÿ °kÿ]º}A ÈŽý€utô}h¦Mƒyóâïæ±§\Öù¦MÓeÌ›Gttð¡zþú×ù»oäœh<ÞÝû’îèè3>“Ïëò§MÓÇ%°-š¼¬V«ìøÅ/¸üå—c?߉‘iš|ég?ƒ®.ßÇúÞ÷úÔñÑk¯e¿^Õ³3^l,ËqÀš„¢¿þÄCýqåEâï¡'ç£Wʱ2ñãé#D: n‹|­öM}qVŠÉˆvË R¤H190Qc„VêOçUâ wuuáº.¥R Ã0¨T*#rš:ÐI1EɡĩœÌhÇœ 97~ƒwí4±°8è§¡Çœò2Ë‚»îz;áÙgáõ×OjPnLù>5N±·`D®V.\È¥—^:fعs'6làÚk¯å¬³Î`Ù²elذŸþô§Ñ¾õë׳bÅ V¬XÀµ×^i7Hš‘@\U5ÃG/¶§éØŒÉ'FÿþŠàcj¿R÷-´c¡™Áû¶¼?}ëŸö›Væ¢Ì$„O­&Á¢!kz˜3‡'ŸÄ(o VIø-—#­Vþ 8è!8#áÏ´VÃð¼Ø?«i>ûïÎIwaåÎÒ7´RLú<5M-¸6Œ¾Ç}ŸàÊ›žýG²ÿ±¼‘• “®›äÕëqÛÖû;:b†µV‹ó ##"%¿Àó–¶û¨M¶¡££ñÛvcbZ(,n3Êe-¼—öI K`þÁ0gÏ«ÜeM‡çwƒûÛðºÛ9ÏŒ—à~åiÊå¥8NL,»?Ú…û«ý(—gF±8-KW%îl»º€‡&xú(¼g¦QüäóXç-Ðù]žÿ¦7Š÷ÛCèúñËXv(®;;ο{7víó¸½Kñ7­ ˜q)õØÑqË ðnÝE€Aéø¯’}«M÷_/Á¬³yÍ$òRvG½yZ“tãîy±§ˆþÐjhÚÛÐn9ÁD! ÀâÊ5  J•l膡L™,Ù>ó—f¸á_UªäÈ5Ôm Ýw·š%Ë­¬Q Ý'XX˜˜ý*pxx¸¸Q,m'|ù{x“Rñ#ÅäÂDŽa8í–‚€r¹L©T"ŸÏS(ú÷|‘"Å$ÄTŽÙî9Áv`.°°«ñ€ç̓Þ^*-¿™=ûuþüÏ7që­ó‘yK‘bªcÄÄãªU«Æ¬›7ofÙ²e,Y²¤aÿ 'œ™Coܸ1J—lÇ’%KxàF5xˆö†}èu–©M:î‹H^Ét\Ÿ:hÇ83CÑàa›ƒïèyú#¡’¼Xuݳ^f’?ÿ!Ê¿^ŒmCÖvqþ³ØðQ„ÁÙlhžhÇ…6CâMp¾y †WÐe4¹q´p:—‹¥OI+ÓÄÜ~7lÞ o¦‘°ô}MꙦ6{l\†˜(–ˆÍjWR§HÊšÛnš:°^Ô1 ™¤I0Êf qpÌVpœø¼6ᨥ°ç±g ŒÐõAð<¼À¤l×°íÄH‘É`µ£!ó…Ã2|J%3âD ïþoü^!‡QÈ” 8çn!—[ñ õSþžà®]o=ì·á?{:åò%›ýó^J;ÿ‰ò}çR:âQªÓWPþé{Éý?º AΊëΡ¸i9¥ ¹ì(::bëÙrÙ V|ï¾íäoþ*çß@þ'E|o¹ Ö¼CqNù9ó¾pþ«p׿F¾¬Ë/•À½aµMËp±©üß³ôÌg‡õÌLÚ9'ðñûڶ̇së[}æ;`¿[ïçv÷»¼Ó|'O/ÍÕdÞþï>š3‡›€`1x?ÒùÝ?S‡|l°jÞê‰'Ü{/îI'EÂw÷nª³ftwkå„Ч² ¹®.ªW\wÀ|Ÿ²ij÷P®KõŠ+0æÎÅþõ¯yà±™T~ù1:è€ÅÀ¾^Ç év([`9±ÿf•ø¶]?Ðt"›Æ‚CÿùP¼<>þÍ3÷msámÄu6‡­X‹˜1ÉÑýÉ{rpëÖý¹{KlØ0ß“1§Õ˜œ4¦Ùÿ˜ŽŽçãær¸žGî¼ó.§ÕØÏ~Ã00 ƒZ­Ö¯ÀË4M¾ýâ‹|äC¢»R‰b Ò”î¾SOe“ƒc9Œµà[ŒsëhO uÅ 1ô†ÝÖE`ÎPž[)V€G^…[÷ס‘ØÃ+P^¬É­,úð€¯??8&& `ñ8ÿ|xêG{«®ûÄ—áÀuY.š(=€±Q´XûÀW¶Ãõ7ÁËé>fÃ:-b’ÍA{ne%i†íWKaÑà^$bSZ#<‡Ë_…=ß…__ Óˆë-K/ŸÏÌŠóYÀãéÀÇasƒD{ÿîFøÌ‡uÄõ±™»á'ï…3¿× /GÜÛNÔmjvÈ/J"‹€ ßÓSžO? ÆSz(Ç ÉáD¼*ÈñJŠT²ÐÙN >öxÛ5pû×bˆj6\çnÛÐB-ÇÑõŠ~‚xW½ˆäð .Úm;žÚår±uÏ+ 5I±cÇÕÙÙ©®¾új¥”R·ß~»:öØcû¤»øâ‹ÕÅ_<`YW_}µºýöÛû=žËåT.—‹~;J)C)e*¥zÛ}"F”R¹ð³/¡¦”²ß)úb°gf²`,ÇVý¶”R'*[åTNõУýú£Ñ±\N);¼l[©l6Þ¶ߤr3¯Q%UøÈ} tú(c©4&ý¯©š²Çâ.îíUÎ{“6M%œz“R‹¾¢ÇÂÚ£úÚ JR==JÕjñuý;‰RI)ÇiÜ×Ó£T½>´ú{z”2M}KôŽàeR¯+eº¥†W†i*U©èïl¶o?”Rêk®Qå|~ìOü8`¢æ9•ëóÌQSêÌ{ôý±M©Ž÷?¥æóm•Cß7Ù¯)”RÎJrú~³•~÷¢”röÄÛö+¯¨ì}÷)3”õâ‹ÊVz¾‘}è!•+J©J6«œT(¥JJ©ìË/ëíõ땲¬èbfÃ2{U8oyáÕûùÏ«lX¦ìoè J¡Ú3õ»æs׌®€^5¢IY¡PPv8˜ß¸h‘zðòËÛÒÿ±F¡Ph˜»ö@år9eÛ¶Êår*+ƒ^ˆR©¤Çpž<™ ÆrN`+[•ÔðßÝ5¥ç=J?ç¦RÑ3˜Ü^ôºþ®‡é ¥Ÿßlø¹äF¥º‹º¼î¢R§þJ§›ç)µü½ÿ¢Ë•:þ>¥ÎHK ¾¶¡¦ß½½ú‘Ë)uùO”ºìóúýá8ú] ︛žRŠ^¥Sž>(•ß92µ¥œºRsŸ×ï–dšJE×uÑÝ·¯ß¿o{•Rg~_çý¨R3vèvê‰s“SJö’R'­×ùm[¿¿ó´R×mÕe£”šþ¸.ï²Ï+uúUJ]ô5¥>rŸR”:éN]žãè¶÷A¥ÞªÔá;”:ðÛú\J9”Zñ¸n÷ŒJQ×ûg}^©£¾¤÷Í+ê}¥’R+Ö(eÖ•:åûú<Î}^©iR3îÑÛô†åšJ½F©·*EIÎ}J÷éˆTʬ)µøE¥fß©Ô_Rʨ)eô(5û ÿ”JÍ|I©yAX^RÇ|\ï›ù’nÓá;”:àGJ-8O—kYJÍ}›¾Ÿ¤}g~__ÿ oÓ÷‡m+õáÏèó`úþB)5çu¥þä·wæñœ0ŒåœàöÛoÊ+ô¨Õ«z•¥,e*S¡P†2”þÑâÏQŽB¡²*«êª® ª r*§jª¦rá_Ve£´Jéu‚£Õ«zUMÕ¢¼J)e*SÊP9•S%UR5USuUÖUP½ªWõ¨e)+ªÛR–*¨BÔnÉ/m¨«ºê _ÆuUW=JOR{UoÔÇšª5ôÉP†ª©ÆIv]Õ•þÙÊV¦2•­lå(GYÊR9•SŽrT]Õ£ú e(Q{¥­RWob’ }ë }‘?iOMÕTEUú\Ãzøg+[ÊPUiè¯@Ê—kÒê^Hž«æü5Ukh÷Hï·Ü ¹G’õË}ÚŒñx&Æ ã±>èUªåLÙqÕÓÓ£ ÃPµæEã(!ë†)Æ@´. ©Ì0FEéqa‘²Õ"•S•JE)”*ñG•=ñ!=ÙMm[ÏË@©E‹^×óã‹ö¨¡œzY«—JC—;¥H1^‹9Áˆ,“X·nsæÌᬳÎbݺu-ƒº¬]»vÈe®_¿žÕ«W³páÂH;{4xî¹çX½z5Ë–-ki©éy^dnžGk8•`:q“¢‰œ"=£O<ñD»›2(Æzxâ‰'X¹r%gu+V¬ÀNy æoŸ¯5Uf –‡ô*âX|® ö;ñ½û¨Çp¾w"Ù«ñ–’…“†AᦽÜW Ì9~²Þ¾û…c´eHV_×j5‰–´fM¢Õm7¥VÓ„žž‘·ß²´%£Ô9wjçÓqô§9ïÊ•+Ù±cÇ{옜ëñÄxÍ æÌ™ÓrnÒG«Ý„›a×®]¼ºüzN^ÀIÿ½Œ—g¿L-8Õ'üŒÃñwÃ!z“ý#×àºG|õU¼W^Á|ýuœB|¡€¶¸©{,Þ'?‰ùÌ3¸_ý*î‘GFîÝÀÊgžIöÌ3\µ‚¶T©Á!‡PüÜ稆u‹X1™@p!mÃeŸe¬­a–eá†f>ÇìÜɬgžißICd³Ù!iÙ›¦…0 ƒ pãÆ|á _`¿ýö㢋.jw—EóXðÀŒª¼mÛ¶±råJ­5½ŠA-Vªh«¸b¸]G[å@±±®X¦µ|Xò]ø‹Ïéãfž»wCîA=ÖçïÑï¥/_ ,…ëï…ǧÁ‹óÀ+Cy­Ë×ýö̇ùï¿= Žì8úÝ&cýõKy]n¥{^vøðNøåcðáRüììŒ3H8Q±˜+—u¹”3°è$ðwÆér9ýN-—ágaæŸÁ¿|A—×Õ¥Û$®Çw0{6l8Þ›ÓÖžtÓûá§Ïêsóy >^ÒûÅ›¼8N˜« kžî“ãÀýU¸}¬Vÿ^¨þ@÷=—ƒ-?†w»°ó¸ëëP½W·éˆÛàâø†nÛ±‹ám߀ߟçÎû} KuØ\Û†Ò\xæeؼ Îßk€«ž—NÒÔX«wzpëfx÷p„£­WoÞ¿[„ógèû©| ÌçŸÀ/À fèué¦mðáßÚNxú:Ø3C[â¬þpÆsp€ ¿: ¾SÏo&ü8x,~vУß_} :$ÌóWÃßÿÓn¦ñ<Ó×= wŸ<ÁOöð0ëƒ[n¹…7²jÕª>VA,ö‚ÈŠÐÀ H‘€€,Ù+>?üË…¶T66eÊØØ˜˜‘4ÎEì„ãÞ¤uþ5o88äÉãàôÛ’é ŒÈŠ0—°ñ²°ðñ´BL¶ÑÀ NÅ¢m‹8ûųGö0M Æk}ðâ»ßñ©O5ó}Ÿr¹LµZÅ0 ì4øZŠ)ŒÁ\­¦2ÃF™!4z*šÌþ·ÙØoúþýŠàÇó1,+ò¥ŸŒÖ±dÉ3”Ë °í‡ÕŽ1êNŠ#ÆêÕ«Ù°aÃèe†#e,wìØ¡>øÁªc=6b?¯¾úêè÷'?ùIuì±Çª~ðƒCÖ¢~òÉ'ÕÅ_•±cÇŽ–u¼,mÛV•J%Ònª¨½(­m½¯iO¥ƒc2k/×8ÐÜïº -ž·ÕMݤ²4ZärZC\)­1±µ\.ká'ÆÌâqÅe[•šwGh)`kE4±±m}]åšZV»[;¶Ë”Ê/´É®ÑÜŽ9Z@'RêØŸ¾®þëoïÖšŽ_Qê–ö©_¬Ø¤@©Cÿß] ÖK¹{îÑïß P¹;îP(mU ­QJÕŸz*²‚ì ‹…£”%š•’Æ?u[;Šå”æêJ”ã$ʱÓZ”ÃÕ®ïVêÉ…ß|ç;êã§œ¢”RÊ›7O=¾bE»›4¡°m[†¡r¹œªÕjÊ”[@qÆ“ÚⱿ±`,ç(úXä$QS¡u²Š­-ÕhíØG¿{z{ã÷ÏÚiË6ÓÔÚÌ Ó†NÙnmõ‡Rjé§c«õî@©ó_- m´v´¬Øá‚X"öôÄVóµš~çõöêwƒ¼ûJ¥ØZѲB«F'ööôÐÓÓ÷w6«Û-û+Ý'±ö—²z{õ·aè4–¥ÔìÙ¯©SNÙ¡,KŸ‹î@©¥Ïë¾×šÎa+ÛŽ÷Ë9¨×ãv·zÊØ¹èu}>¤rnâµ ™OîƒÁFÐRxª±båžSe>*c}w¡¼dV˜l«¥”*¨ÖëØþJ—™´´•÷…¼‡j5}¾öÅõÁhæB¶²•¥,e(CYÊŠ¬ãú³~›HôªÞA­àÆ –²†mAÞß¼¤¤JªWõ¶\‰µc³aÒJEdšDN唥¬¨l±št”£²*«jª¦,e©¬ÊFÞ0$ü.¨Bƒ%dÒ:Uê–û…ª¨Jƒå¥ôÍQŽ2Ã?É×ê|ô¨žè^“²Me*KYQ݆2¢²dN+RŠè˜ô£þUTE½kû»T¾k6ÿ÷Ϫ“NÂqJ¥ÖפTŠûX­–ù÷?ËZH¥B¿ñëèéºßržrM½LSŸÓ (—ËË5Œ—!K[2i“ ÷%ÇG)Ï ÷›”)é’×Xú$q@›_ûX×SEÇõ´ÃmÙoÛº¯7ÜÀ¤D;ç‚2Ú ŠƒY¦‰…™Å K&bå×Ô¨ ûô—^,k‘yã1±bL ÿäZ´ŠÏX ¯P! èSŽìwk-¬ÈJQ®½@bp¶j7ÝQ¾æë’%YR(P¤ˆ‡×§,±`¬S,l‚ ZÐq;ëÔûí·…E™2Vƒ¥+À‚ ذcÈ®ýxc"ÆŸ¾c|µZÅq‚ 3«ª$Re)& c“´hçœààÐ]DZ}û#zÇk»1¦mÇØï…8€6zN©e….>ø`æ°"‘‘I,ä. 2ì0ýªþ}+±«½bø!ìs>±_¶…ì$ÌWM¤×3™ÄvW¢­±¸®RvØ&Qvó~/צϵ‹ëlÆÎ¹s¨™&Ï._ÎP1\Š.EÞñ‚mÛÔjµ×`ânUHȧžzªÝÍìc=XƒˆþlbÒFž; M~çÛ¶\Öq_*ˆz=Ÿs9ýû ·`ŸPÈA¡àúºüá7t®Ëù|žn»-ºÏ2tttð/ý/\wñuø¾Çù'žÏʬÄu]¾ò?¾ÂÇÞò1>xèynÎsÜ{Ö½¬üÀJÊenýÑ­,8è –=ðk<æ\ó œ¬ƒ“uØpÅÅtLë ³³“½åc\rÉÉT«UºººxßûNæ?xÝÝÝtvvÒúQ1ã^.ºèe|ß'“ÉP.—ñ}Ÿ|>O¹\¦»»Ó4yç;ïäŽ;þƒÎÎN\×å[ßújµ7þ†ï}ï:Ö­[Ç]Ï=§¯ïâÅäóy|ßÇu]òù<ž;»*‹äó]d2æÍ›G>Ÿçƒ|'ù|ž®.½¿?¢=9†$Ë¢s¦ ÝÝÝäóyŽÜ½;ã‚ ÀuÝ(o uUËe ×¥ÙŸMk×Há#tå'í’gU¾³@+&zÌè6ÐïŸdþ"±€=ª<ýôÓCxR&í””)ÓI'Ýá_')R¥ŠƒC%â ×d Û‰:Bt¼™TkÕNq}Ú 3"1¡ÑÍ­Ûïì&Ffâ/èg–bc·$‚¸æmΓ#G‰R¿ï3髇‡?if*CÇDŒÍÊs¾ïãyÙl–Âd ©’"Å0`š&Æ׸nçœàU 78cö`BíЕs¾9+ åž[ÏÓóþÓO?‘™3gbYzÞŸºOM±/bD›7oˆü„³Ï>›+¯¼’ 6D@36lØÀæÍ›Y¶l64 ÿçÌ™i%¬X±‚uëÖqöÙg3{ölÖ¬YÃìÙ³9ûì‘û —EbÙ²ðÙ»¬m”8EŠÉ‰Äâ`ÚSÓØzÞÖÆã¡tÉÿîí§ü¹¿ÓSÕ‚l_Äܹpô\Øþn&÷vLÕð#íœx4  ÝP„OšÁ;w,"É¡ï¥ï~èßyúMo"÷WEî¸ã¨š&Ö!‡€mGó ôôGºÔ!HÒâp ´Pg÷×ù#¶ptiœ+xhrч(^dî÷Âý×NâGʱ.4!#e8hB²nK=®>­hA¹l‹ue),£ö[ö‹e¨q\n!Ak‰íP>ï<ž9õTþ øJ.ÇÆsÏå'a»Ì0MWØŽÐnKÛí0œ¾ Iï$&|»Ð$UrÈ©&΋X5_'7¼.•°Ì2ôEʹÊpÖJ3ßó×ô\¡\Ös×Õ‹å²þ®Õô>ë }Íïýð½ø?ð1/8*¼ÚŠ¢RªPÝ^å™5o¡{w7ç¼û^½l9›V,àçë~N±Xää9'óÂS;øÃé§ z7{Gÿhfí™…½Ïó/àÜ'Ïåßô¿9hÁAüÇ«ÿÁì]³¹ã­wð£?þˆ÷ÿyÌãú_ÏW_þ*>>sêflµùäç>ÊÁ_<˜7æ¾Á#x„ã¿}<Óž™ÆžY{˜yäL}#á¦#nâåð«þŠ%.áðÃ×7drÙ\ü`Wõ‰{脇øõK¿Æ±0`éÒ2ž—¥ä”"Ór!Å]ô3ðíO|‚®_ÿš®®.|ßÇ4MÊå2µZ-"èÇÁ², ÃÀ²,Êå2Åb1*/ŸÏS ̓  X,rðUWpÏÝuý× Ïad³YÊå2år™\.‡ëº|`ùøï»ïãþÙñácŽ¡X,j‚Ð+kEd¡mÛØ¶M>ŸÓä]ÿýßtù˸®‹išX–…eYAµ7ÞzÅlÚ¸‘bHк®K¹\ެ•óù<Ùl§TÏ£«XŒúÏç Lêu, ³³Û¶Éår”Ëe\×Ų,r¹†aàºÚõo¼+V0ãÞ{Éßx#år™Å‹·ñ‰ovÎ ªT馛*T"KG±è›,Öû2&êü Ñ(ñ‡[·1 Y™´H Æd(1B’dLáf2a¢Æ‚f«ôjµŠeY{…¥XŠ…BaJßË휂 ` œòµSÈüË÷qožMmÅ!zt×]® ^økn»í >ûÙ:žGjñ˜bŸÅˆˆGyÀgϞݰÅŠ}ÈEI³qãÆ‰GК ÍX¶lk×®´ ׋/¾˜ .¸€Ù³g³yófV­ZÕ§Ãïû,\¾œ2±»¤½ ûâr(õ€9õ0Ñã€G,Ì}é÷/aÿÏÆ…œ÷›ÝäøÖ×ÿŽÌOBÝ ZPX« «ª)R íœ@£«Õgî†éÁ«¼aìÏþV¨!iƒ›Ü?ìbcG¹M›0¯¸L³_奱|{ ]Iª¹^M|| Mމ%¦¸zµÂ4b“Ëqe±1ù˜#&Íb+I)/i©„éËa:I$ÚH˜¦;ѱªÌ%ÒØhÂO\vóàùóÏç·Ü¢[7/X¥ñÂ6 )íó‰ H?¹…ó¯:Ÿ¹•¹dÉbæÌ¨Sï¶ÞÍ»y7ø°iÇ&®XzoºîMÜÿâýä’>Fß Óíé,f1,ÓåάÎÔ7¢ðÿù¬Y±†åÿºœh°Ì¡þbœNnòÅÅÅ,vGÚNÎÑl}'±X ¨‚µø\Ø– \Úõ|sÃ7y}Ùë\þ…Ëù·û7:;;1 ƒ_|ÿœt×IºŒp`Êù9r5M~n{x÷â~n›—﹜;VP¦ÌqgŸ Ë—óêïžå' ~Ÿ|öO8øôƒÙù×;yî±çè.wóà{Ä÷}~ÿ5›ßÄô˧sþËñ‹§sã7¾ÍéEŸ;/¸“ÃýÃÉ{yž:÷)¦¯˜ÎÚÏ®eÅ/Và˜÷½ù>>·ô ï9‰/ýÏ/±ó—;Ù}ínþóøÿäã÷~œŸÌú çuÛ;¹¸z1't¯xœ]?ÚÅ7>@®'Çþ_~0ǽó8VVVò–Y_àÚï\‹c9ÌÿÜ|ÞùÚ;ù¿çÿ_+à¯ã×¼ˆëÁÏÿðs*¥ ‹ÞXĵo¹–üøä?É‚óp×ÞE÷¼næ~c.{~¶Špÿ¹÷óû'?Q÷ÑÎ9A•*¹ðh°l„Ôºq_Aò:[XC?Ã%íZ¹OmUÇxßWBúõGu™–R^þ êµ{õy³Âó`(õ“Ë¢û¿ÿ¯ô9”Á.ýæ1åýe *TÔk'½¦¾wâ÷t™ŽR;~±Cõ=ª&/4[©Òƒz³TR*èÖíúö²oîX0Ð\ÈP†ª¥3ÈJÏP¨ºªGÛÃAI•Š!­ële«Šª´,c¬Ö…Ò‡V÷÷¾¾>Hγ{zz zzFñÂ’ó¿)& öu™a2ÝB¡NüîEê±E)U‹e†µ¦¡tÅŠÇ•iš*—Ë©Þ^¥†3„ô76§HьŜ`D'œpëÖ­cÕªU¦]·nÀ¨})'ÑŸåäHœ{î^åbU`±o»ZM­÷nŒf‹’çC݇ïÄ0 |_»G »\í—}¢1p‰14UâìÙ³fΆæ’0ÅÔÄXÍ šŸµ`&lzçËÀLænz þLNúé½ð“_îóÈ¡¹<Œ8=üNiIÇ\â:´5ž¸nwˆ­-ÅJO,%½D[²€ÞD=A¢¾R¢N±Lƹ4íqÛÉÈ:ÉsßÜvA ¸uÃ>¸|yÇòã‡Þp. ýlKùq\¿æý=‰í\‹rä|•‰]¿’È#i-úZ±–ˆ­ Åõd=Q–X£¦ J±HMºª­…i=`ÓŠ¼úÐCQ=¦iNz—«CÁèæ»‰-_“­¼ìýÜ_À§Cõ¶Ã—¿üoœ´Žc{;ëz'¼~&Ë^ñ068È^œ%gå,%JA ß÷5Λ^PŽã`šftÏ&G.òî|Úzæï˜ìGÒ\DpyŒDÉ—m,^¤ýÃ?>ø°œåæÄ•ì þšþð0«{Ÿ>ùÏù `\HŸ÷á»ø.³˜Õ`k£ï³Þ½3v4õ½Fìpûpø¸þ}°u0œOdBóõ~ß8§îpEÙáø°Þ^l,Öo™ø¡.À¹œËŸ}ÿÏøÊa_ÑåÉ€"æéëÃ…Tà]­›°`˜íœ~/BÃDÞñzægÎŒæH-Û'ßÊVc¹gÿÃÙž=¼±®°žw}ÿûøRv–8ˆ¯§›õô¬þ›m7Œà¼î¥(RìCü¤Ø·1±'KLÅ}x ä*M”›Õtš"ÅÔÁIw¾—éGkâ1”q*NKWªõzÏ›Ÿoy¬Z­žçE}”mÏóòe2ÊeeÊ÷}ŠÅ"AÉd¨V«ø¾å©V«”ËeÊå2®ëÒÙÙ9è9–òRhxx,¾w1GîŽÅðÁãÛñü¥d³š|@†8ú6 a2At¿Ì›7jµJWWtttP,©V«tww3oÞ<ºººð<ŽŽº»»ûÜBzžG&“‰Åb±H>ŸÇu]2™ ÝÝÝÑÇ÷ýè>îî£ƒr¹ÜwÞ¼ytttÐÕÕEWWóæÍ#“ÉP,éììŒîûŽŽ:::"’4“ÉÐÙÙ}Ëy)•JQÙ™L&:.£ã8Ñù“ü]]]QþE‹Mð•b*c5>/aà=ï ¦mgæÆm¼–Ûƒ^z ó‡SÿF“>©¸F“2£=ý½—ú‡³ˆÛÿýÁu €w !_wwwËòóù|Ëvvttô±”1úÎÑdìMÎ $(NÈq×uq]—À÷1=Oÿ®V©†ãôgî½—ÿàZSÆ÷Éçó‹ÅHYÄÎyñE|4q\ ¦ Å"7œx"w‹|ç£Ãàé§ŸåUœÚèÅŠbhúO—CùÀ‚Ýsáˆß*ª[့QþAÐÁu×m£V+pÏ=§`Ûö€¤ãpaÐúٲػ…”“}\Mû,ËŠâƒ$)7îÎårý*Ê~ÛÍÅZr*&ûùnòä úÄtœìH×xã;"éFq8ß@ääd!.÷VŸÇ÷ý !Ó«š"ÅäFre¸è¡ÃY´nüÌÅ÷ŠE­¨ØŒ‰?R¤˜ì‘Å#h«ÇµkײfÍÖ­[dž X³fMt|áÂ…\z饓št”ÁãŸz ãøã'¦ÎPpÔ<ÉĦR©ô›W¬†LÓÄó}ôÑ1¿·§"þä‰?aÚ¼iØóî¦Ø»ËÉü=T*òX”ÆHöàºnÃý%×É4MLÓ¤\.“Íf)‹pÎpºTçóyjµ¶mÓÕÕ…mÛÑ}Q.—£{¥”h¨Œ"Ì"yÒ‚qÞ¼y@l‰Q.—#KB¹Ÿ…ô¶m×uqÇq"â¼§§'º×ä•ûز,jµ–e‘Ïç£6J:¾Û¶i–ÊØ"ÏìïςӲ¬ˆˆk’ç×­ãîÞ^û—"Å@x$ta<œ¢÷홵Ãèáÿýdÿ÷ ýS8êhØzžCL´÷å¤Íd@‘u]ñ´nž[DɦVk´µ¥›äþäü¨÷­]Káúëq ‚r9Ìe¬u]7'e“ÏçqÃ0ð<Çq¢±º»»Ó4) –áår9ò< ïyQœèííÅ0 2™LTŸŒµ¢H!㵌±¦iR,£±Pæ&ÕjÃ0èîîŽÆÄ£ …ÈB4y*}YØÙÉ÷>ýiºÃùœY.cº.mÝ µAo/}ùËí¾Ú†'B3ç*`¼ þ€ÞO!x~yøNvùç½ëöÿÉü÷ÜwQÿu%œÄÆÆ÷ímÏq®ÙÛëPa6}û °¶¹uó2x'÷…{i¸¨R¥H‘:õL¹Î¢(H\×%—ËEÊ/²~O¾gš×´¹\.Rn”µ¹@Ö²ž”÷¼k$Ÿ´CÖ%Í京ѲöžJž{,¬qwµ:\4¯/‡ÒžÔÚ±/vΘÄ d•J¥-÷e€^g¤ŽžS¤˜|Èzá˜p xXx^kg:Så–"ÅxcÄÄ£àÒK/åÒK/eóæÍlÞ¬Ý.\¸pÒºVMâú-[ࡇ†5I)dÒ/Äc+ÈD_ÜŠP>IÊd?“ÉÍf£BsÞÑj\g2™H¨'nEP&$[±X¤§§'Ò°/•J\ê‡"Ùl–jµ-º¤=ÑâHkÝÝÝär¹HÚÕÕ|µZz½N±XĶm:;;qÛ¶£`¡P \.ÓÝÝM½^o& dšfDB% j¹G•R}®UòZ'ﱚ¡iÔj5 Ãà†öm_Jb›âá±ß›öãMÖ› p?÷k̹‹à˜c€8¶Óh'¹'š…Ó¢•,ïL&ƒeYxžY¦¾óp8= twwS*•"w¹Öòœ4+™^Ë·¸*•çHž £rM-…¤4 £Ax ÷ŸìÈïf%‹æ±IÚ-ãEd…”ÓßñÈ5]B¨ñ /°{÷î1¸cöN<ýôÓ<öØc£/h/ÂL,X ³„o‡–Y̹O?«¿¾;pFHJ†!»&ã»99ç D1©9Oww7¶m÷»à’±$©À#ïól6u2oÅß÷”'¤™ˆàS”}lÛæÀçžÃm5èû¬[·ŽÏ„.˜»ÃïJ¥Š2ç±[ÒÕj52™L4Þ‚ž+•J%:;;5¡ö×4M*• ™L¦a,µ,‹J¥õ_æ]]]Ôëõˆ,”òeþ¿e¬“>÷ööFe[–E&“‰,ï¢z/gÉ`Õ‚æuŽÔ?Z¥‘¶Fÿù¥þÖV2¹j•·y.㺺ý o\·ÿs9zÐn‡= ŒÉxß_ß[¡LkÕ¾ßò|ôo‡PÍÐñï;ØziY&Š0²Æ–u/)zž¥iödÛvô~ÈçóÑzRæÿ¢+²QÒ“5¯@¼Šˆ%¾¬™E±VÞ·Åb1Z¿4[ávuu5¬q,Ë¢Z­FmN®å˜(^V*•è½;ÞD¤Èä],JºÉ:E2›Í‚ÙH¶"í’á/úÃpî«æspǶ;x÷ïî“N”Ÿ{zz-'ZÏYFŸ>$Ãeì˰ "Ù'BN(pÑ®ñ-´¬¢J7]®J6ñ;¹ƒŠÉ¤œ˜"ÅÞ‡Pf‹ ”Áõ±Œµ¢ï´÷”SþÓüz»œ"ŤÀ¨‰GÁT!“¸ódÑóÏ_aœ(Y ˆ)$aDÇO¹÷f>#$åóyzzz"MCìÉ$_¬ÿda ®Ád¢ÛÙÙÙÇz ßf†“îÎÎN*•J4áM/i¯XtvvR«Õ"á a‘KD€R©DGGGdµ$ Y¼är¹ÈÊ@9dI+„&|IbCHÙ¿¸æšèø³Ï>Kñßh°ü’EXr'çb2´\.GÖY²¡Ÿ€I¡¢l×jµb(Iµ"N’‹ dÄ,ß4M:::ÈårT*•hQÙ¼p‘°l/‚ˆä‚— ×p-Êe¼ÎÀß>߇ž-Û©TF ZîYØÊµD@^(ð<¯!.ãY«Ï4y)Ïs«ça …¹ÜsBh Y^*•"zò^áu3ú‹K5ZëêñÄÒ¥K¹¯Ý˜ÄزeK»›0©°[¢6Þ ûý),ºãlz÷›˜¾ã l;–ûÄÞïÚ¡Ç8œ:eŽ|v î¾ûn̹fŸ±£X,j•„( A $“ 72‡X9@,…x4 #zw y(žlÛŽÈE3“ñk…ÜL¾›åý- <Üz+ï ÷Wi3fà8¹\.öÊ8˜´œL~™L&šˆ`W,e_ÒR[ ŠÅ„ÿæ±Ô²¬aa²ŒV %‚æw”™œ“ˆÒ”(‰ ²Ù,{öìá7¿ùM$äÞïÉ'§Ü~¬±›NÀ¾þíl½¯¸®žþo\ÿ ø6Ìíù Ô¾3pAÅ"äóà8zÀð¼F— A™Œ–P4Yó2ož>æ³r¹Fͧ| CïèîÖi“i\šC4Ï2=¹Iî—v'Q¯7sIïIE8×ÕmIžÍy»»uß\W×[©@¹¬÷†þø>ÔjT’í’|–¥¿m[÷·«+îg6«ËKö¥\Öäœ ÜM“9³£CO^ƒ|^çM™‰ãÖ¦MÔ®¼¾“¸‚@çKwœxÛ÷uŸ³ÙøüærzµÚZ»­ZÕížüL«±MrΤž„ÂCøìSO L.'ˆKtZù¤ÆÇ:-Iø‰¢°(üuwwGî¼mÛŽ,HÙX¼üˆ²®@d ‚äºz(ŠÈâ§R©Dkó¤ÛÞf+I zw´Z§ …è˜ÌDùXú,ïr9â½H~<Ï£³³3R²"¯>òÞ•w¼„}÷xÒUºÈFDá8I¼B£^¶“í—Y<.yË[¢ýR^Òú ˆÜÛ&ë“…Z²ÃÑxk±'îß’‹®ÔÄ¿xyA8Í5 ¬w¯kÙKww£\m¨ÅoÒͨišd2™H38ŸÏS¯×#!»,lEp ÷ß¹çžË5\C¡Pè— IÍb Áë¾@@oÛ¶ ,hw3&%êõzJ>&ÐKÀ‚×ÀÛ ûø³zŸcÎ}NþݳXÖ_Ɔ>´ÇÚô”c8I·ÜBÈYXÜ}÷ݨçUËf\%Çqã&‚-y§ˆ›Qq.ž Dp(B7QºAaÒiÒÝ[R[¿V«EÞ’nÝ  6ïo†Ì[¶¾ü2Ö5×ày@…ÊHÐׂ:Iô% ?ØÉØ)ÊQÉ6õ×è‰@yÜï‘D2ÞËÜ,ùùèG? h«Õ£Ž:Šw½ë]ãÞ¶ÉŠMø,z Jû{/Üë ¾óùí¼qòÜhnï¹nLN ÖÝ­I6ŽÅbL8%aššK’crÍêõ˜„keubZ²á81¡Õô ã8ú3„ó¼8¿ãèvÉ׊ðîéÑû… •4¦©ÉÕ,MSçqœ˜à’¶Š‚B6Û7Oî³{2§u]}³Ù¾ž ÛóZŸ ÏÓyš4“ç …ß,ã7°¿û]øüçÉÒä9•¶%ëÍçc’XúŸÏëßÕª¾’N!¬gO¸É7¹bå)$ibü‰îšLFŸ¹¦MÓ笻BKib¢Óu9øoþ†}Þ˜X;Šûl!¶:;;,“ )ò.n¥øÓlߌVû†ƒäÚ¼ÑÒjý!DY÷P²mÍnÓ“u‰…~GGÓ¦M‹db‘™$Å{P²ÿBrŠÂ’´[ʯ?²>nvŸ™Œ±,s ²íèèÀ{‡¶|ì®vc•-f3;’‹È;^¬L¥LQ–ë÷ã·ÿ˜ëƒë#¹ Äs Q—vÝÿý˜¦Ù`‘:Ï›ÇMß¾‰›Š7EkCQæ…é¤G)!t³Ù,™L&:ï†aPH´EFÙ.‡íkm¯;|øág¨3îj¢/Ò®dŒm—ÆØÚŰ_ò»›Fçeö&0É*×VŽ7·%E{q.p3PÆè.r(æW`{Î(´G©cF\Ïduóž"ň¡ö\}õÕêöÛoï³¥Ôu7߬ꪮr*§zUoÿ…ô*¥œð»¢”ª‡Øá¶þ¶”R9¥TI)eè¬ßý¸ºó‚;ÕÖ붪û>rŸê)ô(¯è©Ë/º\1û eÛ¶êííUª¤Ôƒï}Pݶø6õÔ¹O©_íÿ+eYV\JyEOoJ=¶è1uÏ™÷(UK´¯®ë~é´—ÔŽÿ‘n@I©oÌý†ZÁzõàå*G}à¨O/ý´ºêô«Ô¯~ø+ec+¯è©z½®Ö¬X£v_¶[år9¿¦”êiqNj‰oiÃ@èI”SKœ§P ûÕ¦—æÍ…× ö½®T.—S„»Ýx£êéééÛŽZb{¸¶$ÛÞ;Œ²¤Ov¢í½‰¾ aµ¦<¥pÛLäíÂù—vV”ºøâ‹GÐñ©éwN)uŠª+Ê›ç©RI_ÌRI©ZM©\N)ÃY…BAU*U(”ã8 P†a(Ó4U6›UŽã¨\.§êõz”§V«µ,«¦j µO Óã‚šÒ Jé1v/DŸñmøâ¿¨®ºêªvwaÂÑÿœÀV‡¼^S¹_)µÀ{IýMGI½÷½ßUÝݲm¥LS§«©øõßZì+•JÊqœ¾i eÛ¶* Ñ;ÝV¶:æãÇDé+•ŠêííUµZM™¦©*•J4^e³Ù†ß¥R)*Ë4Mý¾…†û°§§GÕëu•Ëå¢ç.—ËEãbrìK¢R©ŒËùzá‡?T T©TR@¿ãípÐÓÓ£Ë ÈçT ©»P(´<¨~ô£-Ÿ‰½2'@¡NßÞ9¥¦oWªö jšÿª:`×5k·žr)¥ôD¡RQ ôdÁ²†_q½®ó[–.k¨èéÑùl[ç¥Fòn³mÕ0¨ Ù¬Îߦ{Z)¥'k#í{6;ò¾ËùNß{{õ5ïïXïñœŠ×+Iôô´ì{oo¯ôXS©è‰lr¼³m¥§ÿ .¨¯¼ÿý#;/S·ß~»ºúꫣ߶²UMî=‘Íf ,ËR†a(@Ù¶ž5”J%ÕÛÛ½ ÷ÖùéHQ¯×U6›U===ª··W9ŽÓç½-s–fŒfN,å¶*£R©DõÉ\¦¿ºd^$s ˲¢¼Éõ_¡Ph˜C†¥»nëuŠš^ÿ•J%U«ÕT½^W¶²UÑ+6Ì£z{{£¹•mÛ*›ÍFçDz¬èþªÕj õõôôDõ•J¥hŽÒÛÛ«ªÕjÃ3±¯àꫯV>õ”^;ŽÑ|q"Ы´l¨è ÓáGÄZ"r‘”©ôZÇRJe•?á>9&Ûòº’u·|*cFÛNXfsº\x,›¨'«´èUÒgíXM鵑´[ê‘6a~KÅ"4Ù&ë1‰üfSûzT,ò­«xM("b;ÑG9×ÉW¹´OÚ^ û$Of©é|æuçm—·F%‘WÄÁÉÙ‰Q¡¥Z¯#ûþ.3LÂVJ­P55ýõ·©÷»P©ézŽ%ÓBˆ§–¿øÅ=jùò[F\ÿXÌCR¤+4Ï“G‚}B¢ÝJÈ(/‰¢WT(”¡ Uèo®¨˜X”7™mòV0Ât!ÖÛÛ«îüúJõ(U3kª@A† È&·²i@H6ær¹˜T“7F] N2å”ê±{T.—S÷}ä>µõÄ­êž3ïQß;ÿ{ 3€7æ¾Ñ@l6¼mkªñ˜ô¿–ø]W}g2cm†åÊ›XÞœv"ŸpòÖÈL§'‘&§ôSÞÖ¿™Ã6H5ó'ã<É~˜Mý¨5’”¦ž–ŠÉÀdßí°=*ì³¥g!…0ÓÔ™IÈŒKú.eH٥Ľ ×'ÛÔÆJ"®Åq[©¯¼ÿ+j_D’x\¡jÊzÆRÞyŸ¦ã¾Y7 ¶mGk‘¢WŒˆÇ†4$Œ !ãT„9¥Æt¾8YQQ‹{ULôIºBÓïVylÕH ÊvAÅkó¬ŠÅwI1^VÅâ3»MéDl–o‰ØËQ1±&6 •D>Á%‰ÊzSr‰¶Kû+ª‘ÀñšˆK‰ö‹hØLä1é­¦¶‹˜YˆC!{EôÙ,µšÊpTlób%úP˹2›¶³ayBf&m:äc“RèdGÄ££JêèG:Ôî³ô\°§§xÔ»z”mçÔÑG?>âúSâ1ÅdÂXÌ öYW«>À¶å|ùäûÈ‘ÃÀ üb™Ü+9mÏ íæm´=}í4]lçÅÞ]¼Ûô†ß¡×b¾ˆ]´éýt/§í>?ò"•‹+‘«q3fF×#€¶ç¯AÁ(hß9b›û¡x±aÆŒÌðg°ë7»xø= ÿQœlÓôFÒ¥¤øGpÃíf? è¶Eþ šÝQ@ÚoA•؃”‘túÞì²Ö ‹Ï‚±ïƒ§©Á¯ÇÞöàh¶oßÎ!Ï;³·‰ýF±ÿéGgâ:×í4{T“²¥?óÐ÷‹”^Küðx×Oüet;èOž·þúžkC2<žC©O¼Âð÷þ=)À˜càô:‹*.’®† Ïó"—©â^Pž¹VîüRL,òù<¶mGñP<Ï‹Üår9ŠÅ"žçEñY$†®\SA2¯¸°–6â6Éó¼Èc.—‹êbú˜¦ÙàöV~[–Õ»N¾mÛ¦V«EÇÄmt2Ž®ôAÒ$‘ŒŸçy×\s ¯¾új»/Í$B“»¾ƒbæÌ™ÑO9ɘ) ‰‰T*•"wÎ#Qâ-‹Er¹\tʽ/÷ñ–-[¸õÖ[©×ë ®¤lێܰK %ÐnÌr>”R×VîÔ÷ðÃ3xK‡Žá¸·k§[kúsV*•X½zuÛÚ7Y0s]àó ¼t$›…ûµßã¼ýdÏü7Œ_ü¢1C½®]VŽÔ}©ýÇáëâF´Zíë*t¨°íØ]çH‘tÓ:\HœË‘´ßót|ÇžQ8ek_s8y[¸aÈB຺ス#+O\øöw݇ï¸cüû50ÔÕ0Ψ¼gÅe¨¸'­ôM1¥1Òuž¬víÚÅì£f÷=N‡u¼ñÂ~û±uëÖv7cB0XKƒF1Ä"ªòÔÛÉ5SR¼EÓ¶¼î’m’í¤kRI_€èièo&ã´(k ØaY"24›ò‹ËÚnnŵkò|õ$Ú'mײ>ZÔ˜#Ýá¢Å¦nX¶‡šažBS[dÅêÒï³¶©îó¶ÄbHIº4º÷¹Éòo9øà!œ¹}»aË+g¯ ì·Þ³Ìx¬·m==ÿÛ¿ýgÞxã¯xî¹Ù£¨,Eн û,ñø«÷·Q¦‚ W@þ«yŠ~ï6Â÷ ˜®“o±£õ!À¶mÞúð[ÙïÉý¸îåëøëKÿš…˯‘etýòöL8ªx_Ê~ choÛ†€É·vó[¿Œ08|¯Óøæ6›Ò&ËʆŸyáoq4? ¼õü·°gÏžû0œÿg;GoîK.ì{&ìÇ@3¬æ¼Br–[ô}(kX™]Ȭf¸ò,›x¦P£q&–hëêï®æs|n˜…ï]ØŽ[ÀÆæèo~Lß7)•´,m¨kF‰á!q̺»»Éf³ ±SS´r-D鈛ä~‰Y›$S„¬“8.BèI)CˆˆdlhM:ôGD4“…’NH Á¾+• óæÍ£P(P,©T*T«Õ²ÓcRÝ~ûí\qÅí¾4“ Õùð¦7=ÈC/-ã<Ùk5ò ão#Ó©OYÈ@‰ç#dwOOOß0 …Õj•jµJ.—cÞ¼y\qÅX‡4Æm’xKÓH ÷¹ÄC $.S»1ºHXS¢“¢5Dk…J‡Ö]K8÷®·¸Ë)¿Û »=Œ3úf”a¤çv$N cöv^aÛqŒÂ‘ &°ƒÄX ,Kçéù³mMÚŽ…‚Ž­8ÒsW.ë¼Ù!,nšO¯eÅ羟úÕ@ÁɳÙ8VfŠ–ðÃEÔ`Äc>Ÿ”Ó 1~zŠ#Aò=ý裲óô}Òq×ã„§gÎdæsðã¡õw¬Æcf;ЛÙA‹è$ļÌлRÚÜ,&´ù ‰tRo™86¥‰­bUš4®A› ØB¸ÝÕ"m2M£h»Õi[µ çœ3gzê!xžžáò¡»MžŸ;‡oÖW¯VÓS²ÎN=E_±â+ÜyçŸpà¶»É)RLì³Äão§ßÛ瑾:¶@é‰Ý'vccÐ=·ë*‹Ü܆ÚÄÃó<2™ õz|>ÏÏ]Àgžø vÒŸ Ÿt„˜pI\kMZ ‘5\8hµ—ÆhÉCEýöÕ¡áBÞ¾#0Ox|ÚãÀbfΜ‰õš¥ßØÃiCMxŠêÐHú.*F#í» #^[Ão±6mM‡maá{vàsÈN˜ƒÁóë\}*>áÃQdw]ß÷#r§T*aš&A4ïS´"ÚìÏ:)IBB_âOŽ5§kUÆd€añ$÷Ò¯ä9ð}ŸK/½´ÝÍ4øe8à; üÙÀ£ogéÒ^ c†¡Iˆ!þx¡\.S.—©×ë†AWW¹\Ïó¨Õj‘e®eY –l†aD÷°Žãà8år×u¹›»yaÉ pHëºÇkܪÔÂhŒ°}ûö¶Öß.ˆ2EŠÖA®± p`å¶ ¸ë_ƒ÷ïâÏ¿µ¾¹’i4÷´mÌjOÚR(ŒŽ@…"A I¬‘¾ûªÕÑY[†.c$—¦94Òo är#oµŸ¿‘ôÛ04y9’¾[–¶´MÑ/||ŒA´}»»»©V«8Ž)ž¥H1ð¼Á-»?SŒsž>UØJÑ&±3¶$ » 9bgiͤå`w¢Kl##ÈÒšüL1rx³µ€øÔ å¹yw² œ‚g2ñ”¬\†Y³þ§¶ox¤HÑŒ}–xüãÌÌùí|xÚµe œ£LL¬™ïíÄŸîãáQ£F7Ýxx”(aaááa5½ªÕjäÊ϶mÎ[vWüõdþ.3²FŽ„ôˆ9ÆÉ»¨~›‘KWQôA, GP÷‚­ mñ8ÿùùßvQ-©w#7Ëó5\²uƒ,ë^?üu~Ï\=ͥךK­6tÒQ‡ââÒq<ÏK ÇI†ÚTLiÉÐl Ùœæ‹_ü"6lhws'~'VOÏ‚;¨Âgÿý.ì_¶>žC¬XvuuEBÍ®®.€H±!I* ’–ºÙl6²n=G±,‹¥Ÿ^Ê‘óŽlÃYnpòŽínF[’ŽC»€l{÷6Þô¦صk_>'ú¬ï£cA@>Ÿ§Z­R«ÕRb"Ř²¬hm¹çö=pI?éÒþ¸âšùñÜîf¤˜¤hõö—7òhžLƒ8RS.‹¥NqÙšDv”mJÑ #·™ÿØçùæŠoòÎ7Ãò寲ÿþŸÄóú*-§H±/cŸ$`×~¿¢ã±Ùð #µê…ôLï!  ƒ2dðñ±°È ËÈ‘£@×u±m›eŸXÆ+O¾BfY&²8™å|Þý‘w·§£5bÇÝ#A+Ûü‰Â(Þ’/ø0;ŽÍµ/½qÅwCžÑ×ûßµ˜£¹…Oýùl @&£ÃBɸ~bYV(âXªc€tq™"ÅD„i[Xú›—¸Û?†~ðl[Ëy›åÌ¢‘:Z”Ëeòù<µZjµ‡™L&ŠÛ˜Íf#Ñ0Œ(Vç`hv±Y*•èèèàÄ+Nl÷‰n 6mÚÔî&¤˜´°°Ã篼r gµ”÷¿ÿݱKÎTz0¶`Ú£É?Éà¡b4„ÕhH×Á`š\¿lÖ–“29àáµ´(Ëçó‹E,ËJIÇã‰!ðâS/!ƒ‰™Z9¶é3ž¢h¶tôX›ZSx¦4)qä“›ÜÌ¢KEûÄ †eÁ¢Eßà‘GÞe-ŸPà)RLì“Ä£þ?ìw§ÀsôKÐ(ÐM7%J88T©b„2|ão°ÃµèÀ!o>„öœ@æÀ •\…"E||²d£‰£Ýdø. ¡³LFæ&uŠcÖe³øýïÏr–·»9ñÓ0JORûí9”»§Šrÿžú0Ð%Vž¸ô<¯Á%çX ]h¦H11ØEÀ¼Þ7aܽŽõÏr7Çອ­ Çj-aÛ6Žãàºnä UÆ‘ ð}?н(–kbe=\˜¦‰R*R Ú×0wî\2´×ákŠÉ†Çdãy\ûî»çqî¹oמ0óÞÈc ¦è¦9:òÌ0FGÞµ¶=:ÒÕ0† ŰàáõY£‹’a¥R‰ÞÇ)RŒ5Ä›èp+6­`Ñ¢E€Vx÷ñÉí“‘ª'Aã1Å0`5}älÚßšÎÆ>Ì30Ù–h¯çiòÑ4aåÊ.þôO_àž{t8ðtº–"…Æ>I<~34b?ç€s´Cî\b Ùè„ìd6ÁæôÐÃO¶ý„Oœû >ýéOsÌŒc°²eÊØØT©Fšj66ÝtGnZLL²dñðpq#¢ÓÃÃǧ@!µx欛'ÃCï}/§=õûÜm¾’Í#Á4|ÀäÎóasÈh]k¡ïy–e±ñÚ¬x× Vÿýj …&f´`±±qp"ò°”`„¼ð¯J•€€^z)R¤J3ü뢋5ò䩆³ ‡¹±µŒÜK±cútžyc °°ÝMI1 ñòËz†ýêŒW-Š|±Z­âyµZ p]­È)RL]l} f½±ìÒãùÜ+ó޹KÉdô˜ÐÛ;úò=Ï£\.“Ëå‚€îîîÈuªmÛäóylÛ¦§§§!_a´±ÈR°.´H‘¢{€C_Ø ‹lªÕ*¯¿ž vFë4EkÆèˆÃ©,Í­’Z:×7ˆpRéW¬K¥T«3ÅøC¼èHŸíCËó_ºÑ¤]Mâ¹Äc"§"4˜œB”ÂßEtH¤r˜? ö«Y ëIê˜HX(þ% GLæ ™™¬Ï &Åg§B`‰IGiŸ‚A" a›3aæ9“ÈšõyͰŸ5 óÿgïÝãã¸Êûÿ·ã8q.–=ÊÅ6F‰%1Ž“2JH \fKm )+ÓHÜ6»…Rúu»Ûþ¾„riÙ%n!…/t7iÍ­k[(P‡ !X„  X‰sÑ`£8‰sÑØòÝN¼¿?fÏììjWZi%ííyû%¯4sæÌ9gfž=s>çyN¾í"ù}Ñ|›õ©FϧPQcÄ\‡ÂÌÏLÉyÕë’È‹ü¹µ|} ke8rç”8„X§$/…jŸ|¹Š<ÝÀñ5~]ëT?ÑUzsÙÏiŒñA=þûe÷ŸtÒIþïâ“ ÚRxÁaɯŽçu¿züåÔw]—¾¾>†‡‡ýÙš¦)3 µ’Ç¢‘ÿ ô*JgXvçÿ æÝ2£DI“—V(O×Ó": 8š«±lÙ2¶o÷f+U‹eYD£QÅÓQZ€Ã{`ÁÑn0 }ô0'ÔAg'̤ƒƒ £šN§öCj麎išem‰Lh˜î<ç˜ Ùtì}5‡–.²¾t-MáQÚ «è½Ý¶m’É$𦉷£0'(±KDÇúâGéÎoã Xƒx—‹':½ u<1*GaÙ›à\ wŸ]@MntÎ’üÊ ÷iùcÓùü‚iÊ9Ä+ÁÎÆñÌ’tÊ;S ”Ñ|ºL¾‘ü9Tù‡ñÄF'Ÿ¦Ÿ‚°§òp)oF>]2ŸV•Eµ‘ZJ<.X6òuŽQìMª|1ìÀyȧ#p.E*ÿ·ò çë<˜?o7žHªÄP-L(ÿ»PóÛL0òí¤Ç)ˆÊù}$òå¶åQ×7IAÄRì!›^ÎÍŸË ìWBtÞÖ¸¸*po*ñ4Âx!YíWí ”/AAôÎ »§9¡€þü”K.¹?~˜Ë +ˆD$`Š iKáñ06K¶žÂU÷_5­é!Žã°øØ1Èdõõñðw¾3Þ+Áq—HÄóx¬&òW&“!•JùØ" 4.¥Ñc¡õîõìq6gäÅ@P¨ÛžžcM&“7Hé8Žïí˜J¥Æ­;ׂ˜…Õvý ÝuùÒ“OÖ»B²ìéܽüOY±â7,[Ø!Bµ ´Aá1NûaÐAhǡ㉎‚x•Äc”Ø£¨ùº\÷:ØPbE0€™z%PÂT%4 !X«é¢(ÑT‰U•ËÆ¹JÍ`:å5™¡ Ƥe¼6«qk$µEö¢z—F˜³mž8ËfÞKÏ’=òNÿñ›h|1™LŠpЄ¨.Bs2¶ÀÍ{‘c£¯Àu]V®ü, ‰é-§¥„FÇqˆÇãôõõaÛ6ýýýEÞÒÂÜqÉè(ppáÂzE˜&•lA­v`» æ½Çû=›-n÷PÈË_å­iMuwO¤-Í?¸–g:]œÆ4Nj̥e,×*$¯"‘ߥ׼ÜyÔuU~ÿÁ{4òDdÛæ¯^ñ ‘¹²ŠÓ^>ÂK'ŸìϘHÐul6+ƒ‚0Ì¥-p€g;‰vè9þ뿎‹ÐõéEYt]×q‡P(Äðð0𦠅*®-Ì>É$ ì\¶ŒsjÎM˜K&³5Ûc°p‡÷ëK/-ß=—‰‚PwæªO B­Z–…iš²œ‚ 4³m ¶mÛÆ7SßÄ »èè88¸y—9õw9¬€4¡Òéè¸ùETš¡:±s¸Š4ArU¤QáA+```«EåÌ’%D(Ÿ…YÔ^ÒiÒDò©6µ±Ñ#z!ß<š>;g£¹Ú©ZÙö75ÇupLÇoÿ0aOØüÇB:r`µüsXX81Ã4pV9˜ûMttÒïMûy©r¸¸„ cÜh Ÿ¢ã¬qH’$L˜(1BþÂ…z¨úgÈ`c£¡&ìOrQm Þ=dcãâb`ø÷ŽA¢‚ ¢Ò±gÖµÁ½çzÌP±ê±U|¿··âþïÿBh½Ö€)²Æ¼Ð:4ŒðØÛÛËÆX·nݸýCCCŒŒŒÐxлººX³f [·n­ÚxÜÅ)/Ÿí­mô{JàS“òFÌ“I& ‡Ã˜¦IOO£££UoÚhZAà²mO”2 ¸øbàåñœB×=Ïu=qP‰jÁý‰I¾IJ­RS Â(AS•-Èèhñq¥/nÊãSm/-§ºº^,È•Rz^]ôQp:#ÏzõQb\i=ƒâié~%ÞF!giË ¥(UËu½º”Žj¹nñ¹§|{©c+ ‚©íñ¸—g*U,’&Þv]ç¶O~’4seÝ6¤²g”½=‚¸®ë¯Ñ&Âì3W¶@-mpÒo^áCÛXV´ÈÛǺî¸AI7!À¶mýmýãâ7 s‹ÍÈD¶`&ìÀèq°¢£pùÚ× i ŠH¨UA¨;sÑ'°°ˆåÝoÊ­Õ,Bý™m[0pÁó/™~8J1ÿOCó ðÄ"Çÿ;6‰ë^P„ÔïÒqouqÿ×E?µpâàdôáI\¥âxâÐ`•¢º@óð<K† 2dH‘òêk{y† _GG§Ÿ~2dˆñ—в°H“ÆÂ"B„4i„½ºâ‰’)REb­é„qqI|2󔃛r}!OaåÿYs‹ _;ÿO_©ãtÄHu\lAÌ¿1bèÏèdì ‘¬K,lÃ&qOýúâëàâ’!CfEûC6ú~OàTuTB£R]\_”ñï•8qLL_hTeT÷U†ŒϘ˜dÈL(<Îj˜R…’mPæzÌP1r¤8T«iB"‘¤§'ƒ¦i†A"?Ö^ë¼E…V¢a„Ç®®.ººº*îß³g@‘ñX¼xqE÷jÅ‘#Gxä‘GX¼x1‡ÖÀò]k¼Êd2‘®š¦ó`˜3 ½ 5ëfB”•›)ϬR«iÅÛÊYÕÒ•vËíŸÌó£ô<å('¢: ïô„GsÛ9ðW”c²2*¡©R:]ŸÜ~²ë`šÕyÀN†j‹J²a022ÂÈÈûöí›<¿:0›v`ß¾}^ øüñ œ¸w™+]˲èëë“YÏBK100À#<‘#Gê]”²ÌEŸÀéí…1:àÀOóï<ÅÛÞ¶¦ª2&“IÿåBáº.±XŒh4Š®ë~XUY#ªþœòÆ7rÑÿw½‹ÑPŒ±uëVvîÜY{f³ÄD¶ Ö>Á¡C‡8ëéѾýK::–ñ®w]Vïê B]bÏž=:t¨ÞE)Ël¿(xæ¾3qº~xô"TؾZ¸xî)*tàT_/\¼á2ÇÚùŸ0…YUFàœ…õåÔºa*Ï`ú`Z#ÿ{p Ô(“¿Úïà ^«¿ÕûUp 6;pžJíC ?½Ìï¬Ðîï^8@,#–/$†'‹Wª&ª—3P뺸.ìwÁváÔc²=Ž~&ž°ãLjÇËç~ë@_Id3u5i_EöJô?7Á¨cº^8*¶ŠüfÛ ëèšF,ø¾c¹8æ÷¶ÿГÄî½ã1#’(*«™¶00ØÞÉ‘Áâq3K©[ž2LÍ÷ŒôÓ êy»å‚^h_Ó50m<û|.`iä#ÅýðK ìÕÛ.}–ƒù :DNŽAHƒ¯B9c& ÿbAÌôÂÅ®ð<ãÄÉ’ÅÄ,ºOR¤Šk`œ€èäÿ™ø¦ÁÐßiÒ¾0;ë8ðüYÏóÄÀm?fX|‡Ý/å¿Ûg2^à»óÏÿ0¶§¿¿¿hÂ’  ­ÀÐÐÐŒô FxœM>ÌÐЋ-â·klÖ친;ä.ñ¾Ìúònñx®Ù¶M,öíº ÎÉ—M³£^–.®G½KÓPŒŒŒ000PX¹ÍØ¿^xô<šlÃÀ¶Æ/Ñ$™Lb†x, -ÅÀÀ;w££ÞE™sTŸ`÷îÝÐÛËŽ“¼Q®Ãïåâ‹ßÌæÍW•mÛØ¶]´fc<Ç4Múûûe-ÇâðŠ|ô£•·ÀöìÙãÛ‚väСCüö¿äÜg–pÝu€B{²uëVFFFVxœméq4W#sw†×®|-zZ÷Þ'5SuPÛõ|›ôQ©U›CAÜÕ¿Þ\°T›k%çqÛòy­Ø°‚y ç1rÝíÆáÇyGü\ôÜEÅ^jùM+D¦ ŽZÖø¥uJ—øqœB4°£@Œ›Å°2ÿS %(.Õ`¡‘¿'&èתh]•^GtÝBóÑZÆ=ÿÁ÷¡K±['üÛ·çIŒŸì‡¥eò·íâhnIÈY%nªe—r%qaûúàtž°!n(³ÂþtÚû†\xÑ(,Y¤Ö¬ŒÇ‹£œ•F,sHå—ªú\~Û÷cð¾Àyâq/:^Ó+k ÏƒÒ %ÁîóÎmÛ^ÄŒTª :–Þ'ùHtz¸àªê£DR=›- ùJg§—VÓ¼65Íâ墂KZ©ëVn§L¦p?—Ö2à7¿aÅM7±üŒ3hGÔ˜aooo‘ðؽíTºOõÞlÛkÞÑÑQÂá0}}}ŒŽŽŠ³‚ÐRlݺ•¡¡¡šÇ ÛBx\´ho{ÛÛèííå¸ íáãùä…ŸäÛ|Û3ø¥!)8ù/AµnÓà`µ1 „º!¶¾"½½½ôööV5Ó§Yºt)ëׯç¯òo¨Õt ‰º®K'Bh)Ö¯_ÏÀÀ€'Ä·Á>Á=À ¼Ñ£CO½Œ¦Ÿã/—;YTrÛ¶ýЪñxœL&ã{<нh,NüÎw&NІtuu±~ýz6lØPï¢Ô…%K–ð­CW±r2OAhaÔHíú~ðÊ7¾ðl¢eYôÓ_ •À¤VY‰ã I&Ý@­+O¿˜.oèË÷ß”gÔ[ôÂõ2;í·'OðýÐæåwª>d,ï5¥êMzMšóuø`þ`AÔvÓŽÃ/4póJJ* Ûô„`S  ×{£º÷æå=·”sV"z¬P¦xÒ«‡z!î0 3X´±è…XzË-43Óµ[—måÌÅ#ÀÚÂÆjÖ{ Þ¯ÕLt«e®“òä›i´)ä›O—štáÈ9¨°­Ú9‡F r!°«¹¦Õ,55Ù;H…eœŠD›ÉDáj–‚š¨‘Bš3~ö³*°1©uœ@¡¤¸ßyàÛÿåý@Ac>xð †a`EçF ‚ÁõCKqpÐÐÊ® i…(O–,!B¾w­ò´U"¢Zu˜aÒ¤I’, #¬ŽUåQë–ª5Kƒe- /,´6M#<ªøÌ[·n-2S^ö¾¹Šÿ =ökܵmÆ–Eaî©ÕtîîÄÄä»û.Ûço§#ÕŽí…¢+¤ì8°Bƒ±ˆ'NF!„¦b2/³‚G‘FÁÓ2è ää·ßL[a[¥MPxÁQbéûNi*½ •š› ¬¥õ©¸Hë^èO#Ÿ. ¼ŸÊaËôâqÝ‚÷Y©(¤Ý Ãù‰Ê³É”—T–ê¼³&óÐRB¤hKÿU”-uϤàXu8\¸×ÒéñmbÞ9TØÎr‚Øè¨·Ï4LJº ÖC…·üŠî ÓäÁL†]Û·ÓŒÔj 8ûÒÿùŸ`ýÎä÷}-Ô*<ÎS©nþ65Å'®ÜPíTÛIå›âqsR½:ŒEk+_|±ÞUŸ39f…¨ÖÒÉ%¯}­?G&†M›˜•÷ÿdþ_rBŽî ƒ*º_Ô¶Xþ¦60ÊÞKt’&‰I–Êß…Ýx“[ll"DÆ­Yª°°ˆ÷=uƒé2dˆñ6kTÔÆ Ô:®JÜU馂zÇ/'6O§lö¬ÙÃkw¾¶¦¼›FxÏÍsÓ¦M\sÍ5tttpÇwÐÑÑÁ5×\SÕñªÛµáô ˜ÛpÞ=álx<ަid'ëˆ GŠ×ÙZ†Z퀇ÃÉŸã¼3Î “)ïôìºî¸E¢ë…  B™±pâQ—%9 È𕯘80ùäfÃ0Èf³8Žã‹ŽÍB=^^ml2d|;æà`c—í(+ñN•Õ-È«Ò9 0ì8»¸8 mß ³âŒÐrˣʤ^”ЩfmZXþlO†¦TU+ÁSÍ ¢þV³MÕ6UG%f¿* œ‘üèP°½UÛ˜˜èèüåÙÉÞ{gáÊÏ>µÚ-_ÿ;¶ü^{†—„V¢[pÚžÓæ>ë>vœ»ƒ ­Ÿyk`©‹A"oÐýòžpDºZ1ñÖê+u"Rkû)Qr2Ô: åùSmWÅšBÚÉÐóåÉPìQÓ?G*…¿±XyÍ •Ùšë<âá‡ãăó[ƒÝ' ™9‘GSPL6ŒÊmä{±'ï:ôŠW@“ P›-˜÷àƒœtèÐ슎PûÒ@³!>N¥ÊöڣªN— ØØ8þ&êsï|‰ð‹ûîãüzW~šÌÔ8Àp¾ís‹rþÒ¤©”gn7mò–"Õ„9®’0a"DŠÞgå•›DuWï¤Vþ_?•4Ô;¼1nÓÄô'×êU3åñi` d¥ïé¥éÕ¹‚ïæÁôêý½R>PÙ›´tr°z§×ÑÉ©I Ž3¸¸Sšä¡&TÛ7x=*µ{¹m&&_Ù÷•i×CÑTÂãúõë¹é¦›¸þúëéèè`dd„õë×W½Ðåó#úDçý=ÏbLÐ1œIã!Ì1*n~0ìÐÔj–=€Q´ÖxÛ¶Å{I˜™°ËŸ¶Y´çr …iV\¾ÃǶmÒé4š¦‘L&‰ÅbM%<½ùJ;ßj;Œø*uº+¥/E­¡0òÿÔ>u§¨s­ŽS‚©:NužU™Â„+z=êwþžy%ìÛçy>–i`=((VûB4¨v*7e²É)½¼îøÚõ6çzN3aN>ù þìeAš“™°ßxéüå9G!zgÁ;­q<¯ÂRoÇZPƒçÅaQ}o´*òÐˤ5ñ&äVûu6“_{z™üTÙjSUžƒ•¨f⨎×Îõ” [ïïj¶…¨Å¬>p€Î>›Óë]‰ÁÏàÍO¼™ã7ŸüÓ*Bâ „3ù¾©<Kó3¨~2m¤Ìñ.LiLOyÎå¼-5jÝfâMµw=PרÞß=å„á&a6lÁûÎ?ŸSÏ=·ê2¨W奈D¼±AWEÇ —HxŽ»àEúU¿+”Ón&Sˆx§ ‹y犈*q4êý=8X<ÿÎq Ç©½ºî3˜¦¿¿p\8ìÕ7˜Æ4 õq]ï<=ù%O µÄlÄ;‡ª¦› è×Ç0¼qTåx®ò £Žã•Ŷ bªj§d²à°®®ÑLéBªmKQcêlªÌ Ë*D@VBr°LjlXÝ'¥ål‚g»2Ûãàé+·<ø`Ò¿¾à]¯/|ᢦš€\õþ[𨣉y¡¼öÊ¥ ö×® .?P^yJä .3¢ÖŸlTAo®¼T›†'CÅlž*‹t½|7{>ü*™x<Ž®ë|ä#Ÿ _}}…/ðtºðåáºÞv&ã}9ö÷:ê Eu6T"öö‡Ã…YK™Œ÷kY…uǃ¢ˆmC¿tv–_ )|ñV³®p9A4x¾†šÉ4Rx^ÍXv¡*¦k\€1Øwü)¼þÊ+yúéâý¶m“ÉdH§Óâõ,MÀtmSÛµt?çîÜÅ•W¾]ÿê„/¦Éd’H$‚aèù/ÇFZº"Dü›m%¬UZKh ¦kÆÆªd¡±™®-Øûí½<½ðiV¾¶ÊA£ñq&»ãF HL!Òã§*.éÔæX.¿rbj½ÇjëÝ%0  Z˜éØ‚ýW\Á+KB1ºnA ²¬‚ð•N{ãdýý…±=(Œ”æºã» ¦é tj¼-¸Dh¥ñ·rË•æªóô¥¨f©rC ÁãÔ~Õ6ªýý…1Èàr¤J”S]q% –ku]/‹Á±SÇ)ŒÃ:N±x™N{e°,ï'ó>ƒiLÓ+K2é•¡¿ßçuÝ‚g§@5ÍT3™bOQ%èÆãÞqå„ãlÖ+ëzi“ÉbOÒp¸ òªzÅ\5¶›ÉÀè%@² ÊVZn¶g–v£–÷PsvÆöÍŠÇØ-ËâºëBäªyµ.d5ã*2P5^™ÁeBJ™,¬k¥‰Î ³®¬0%šRxœ.Ïb³h_Ž—y™¥ï}oÙ4?þñCœp³bÅ|èCËøìg âa,VÕ«ú-]Û\͊ǽ´J˜T_ô¡Nz{=£\B@}iª/ª‰¢|¨YLŠÒ/ÎÒ/æÒý¥‘l6ÿ¥˜‡H¤ð 'žtÝBX‚à—c"QþÔvMóòT–ª<Ѩ÷™JyǪ0 ƒƒ…CÊÓ² 采½stw{åöòU¡Ôì¦LÆËCÍR"¦º$‰„—¯ê¨giZáKUÍPR_¦Á:þbíjö‘ú" ‡ y*‘TÍŠRmJU•¿š•Hxurœ‚‡ª{Ux µ=™ô>‡‡½vQ×#›õö)A8+t”РųçTG)xŸXVa»j#U§L¦Ð9 "ÑC=~éü’W<Õû½³sÞ„ö±»»›þþþ¦§Ò¶ÈL#¡ Û¶íbíÚ;Ñ´?©wQA¨KŸZÊI‡¶ðÊ wmw(ŽPjäÿv)hi.…ˆ«“QN#¼ÊW¿­T£¼Ô«œ|Z'p=¿M•Ïô¿(Ô%(»È»R½•3¤ŠÞ¬»Ž§Çós¡È[Ó›Ÿô™œË”Ý))“ÏK•Ý ´½hWÊQeUÙUù,ì¿,.»ª'º¸tfõéæËî·o Ê;y·¹@2!ËΗKœ/x- ްÁžŒ‹7.äö©º•‹lÜ–¡øž5çÊ-]Ê´7jüHçÉÐ@óSêàü½\@”r"jRѵÜßåÄçà²J”œ(—‡ÆGò¿G"…ñ\Ó,,í¥ÆUxÙ`øÙ Jp¿1ûû â¨r. ‡á?ø"ð™z_ººâËŽÀ¹öoxoÌ6óÚ1ÎÉdÈVãFÜà$ª « ¡Mê­L+â£m&<º¶_Ì)—n-Ú®Ä!€ùóñùÏïÂ0:nösQ ðüB§ATÈ(|é)¯Keƒûj¢T zŽ+ñ1˜‡š…™A…øíÙìøsªÁ]Ç)’AoË`YÕlâÖ0”ˆ,›:4ZðÊU^º*„Ãöí—ÎâÚøœ:£6üú±3¹±dÅì¾¾>R©¦„䛵ÀùDñÕ´ü?…ŠÓîâúŸS9§‰é/€­ò¶°ÐÑË.L­¶+O/kF®©\wŠBÕU•µ4äD¥rÏ6{Öì¡w¸¶ð#ÍÎÑ}‡1Ÿ5ùÕ¯&b‘I ML ¼ ³ÃÈÈ™<òÈ{kÏH„¦åÐI‡p´8=¶€41«Úµ”H½TÏ·´—kQ¼|¢FAt £ ªãµ’Ï(ÅÎzž §ÄÀ §¹Ë ÂTpY5OÔeSB–/ÐΓ̟_aæÔñq bio[‰u`i…óëó¨%.•hJI>iŠÛ4¨«ºfêïàï”)»ÄxŸ™@ÞJ€ ¶“MA ηo&PÎrKGºe¶™K ΨJVm—.¹ÆŠZ'PNu]‚÷\œâH²J¼´éÔƒ·B'~öÙüÁÙgÓ®X–76VºFŸ ÔC7ŠDÐà¤Ùàö ¸©Žó†ÃžÀ‰;>Y´èùzW¹îØÀØq÷ós^Ç%—ŒÒÝ]Ð LÓl™ ÉÕ®™hN!FùD¡V…ö¢­„ǃGÎrt^ lSÞwÊ“-™üN<1 ¬®wqkBÓ<¯@%ØÍ$å„ËR ODëî.Ž)_JéÌ#5S¨TØT” ·ü²U‹V+±.™ô¿Â—Ãøs•¢ÄA•w¹çDmÚÙYe ¾È¡P%z–΂RÛ;;½c“ÉBÝ *´‚Š l“x¼ 4Ãô–ÒÓÓÞóŸ=˾ÊÈÈ‚¢Î˜ëºô÷÷7…¸ c.ÅÉÿ«æx%†98¾@¦&4Tç”Ø7Óâ]iÇ$(*–+{ð³t»:^m+—>8q#Xoõw­ V«üJ…×`Ù&Úf`àâ–½–jŸúW©­Ô±Áº©ûÃÄdè©!ÆöŒÕTÏfÆöγ9ãØ1¶oßÎùç¿¡lºh4ŠëºèºÞtë9 ‚S!ÏÑ£§rþù“ê]AêÄžÓöðÄê¹ñÛßæž £<ëñ 5KùÖúíXMP%Þ©9½S=§‹'Â)Áo*Ä(x'N·îªü•¼W«9–i|óRBi¶Ê²ÛùãÕÐÃDQ^ÿó׿fûŽS,]ëÎΚ ÔÊT&lWCp¬R¨LÇs8Þy%»vB(Th³¾¾>"‘Hˈ3†&k2 @› »¸Œú‚oúú Þl^|k›p8L¸bQFÁ»­v0ñÚw¢5g‹ÒË7Õú«p­ÓEÅEWž†åò¯4v­ižPª¼-Ë¥›èöT!V¡8Ìo)^xÕ½¶îN8²ÂåDöq¨dhÛ¶‰F£ O¤–×%˜)?—4^ ÝJëµ)o»r ]J¸ ZÁ êø`g7AÂ-ƒ{ÒÁhNÞs2‡ê]ŒºsÆoÎ@Ól’É[Êîwò3YDtlrDxÊðÛß~›OúmÀeõ.Š ubáÁƒløøÇY}ô(ßB–Ý›Mj}CÐ Š•¥*[ëµ­¥üµÖ=Ø{QÂaµ=š©,óùŠC‡Ø^cY›•§Ÿ^ˆãÈÒ4BãQë¤èrÈ}>9îa8tü‹Ìw^ÁêÕ'úK†yŽK '@- B[ Wýàa^¹c9¶í 4©”Zü×%N£iZà պ7Çb…p§õ t‘æ¹Ä²Š…žKÔ"ÍÊãpªTŠõ^ ¦é7ö„çz^ƒFÅ9ê}®¾ïÑ¢íétÇqH¥fkñô01‰÷W 2ØŸ=%~»Ð”üÛŸ9Ìyç}l\XkðDÇp8L$2Ýa.A™={Örï½gòÔ»$‚ Ô‹ýóçc™&_ݲmÅŠzG&Eƒ*Wä¦Â/~±XB¬ I#Œû´#Î~xv™Ã‰D‚žžúûûýs<þøãõ~êÂüN`uO¿+ë B[38¸Dc ‹xÕ}÷÷ˆÄÞåG—Óu˜¼W BU´ðøØ©§ûXÄ÷ìá¾ûŠ©T*ÕR¢£¢];N…:m r¹Úó™.jýÈwÜ­ŸqàU°«³§h»mÛâÕ$m„ãÂîSwòøƒ»9묗ÊÚL×u奢H$ŠU„³1QL‰ƒÉd’p8Œ•õ«%Ó4q]—L&ƒëº†á LAÑ,›Íú‚—æÔdˆ h¨"·¨e#¢Ñ¨ŸÇðð0¶mã8¶m“Éd|ÁN ŽJ$ †ŒRé‚£iš¾èi†aø"¡ Gíº.áp]×Ñu½Hès]Û¶Ñ4X,æï/qFü=‹aY–/²)¡Nýd³YLÓ$›Íb†ÿ©Ê©ÚH ˜Aá6x}ÇñÅJ]×1 ÃC¡ýýý~ƒù«òª¶PÇ©ï‘à7µ]×u u~u‚÷‘*§®ë$‰¢¼T=t]gxxMÓü4jírÕê>R«º¸®Ë“O>9—^ÃðÔSOñhþ¾¡}¹á†\uÕiõ.† ”ÅÆ&ܦË%Õ «Óësþ+à½3X–E__£££õ.ž 4m#<ŽÍŸ@§}._|5ñxa_</zéllìªC®¶ºî‰oJ€k7æÚóé8|€“ž8Ÿ¥K÷m¯&Ah/Ü=cì^9ʃ,'vÁŠqâƒã8d2™†¿.Âô©e’š§ Ãð½ö”X¨¼É”W"à wAÁ1‘HŒ›ø˜ËÏ^SŸJ\šÊ:2j"•Ê#›÷äRŸÊ#O•M#‘èÕ§²ÙO°‰¢C…µ`YTž¥Ç–Nú*WOuŒišEÇ«´¥y—~–¦«f¢Y~½‚Ò6QmªÚFå,·ú½´*œ¿:¿Ú®òª4 VíWBäD”^ÓÒÏÒs˽hÑ¢IÛ¥9xð`KN@aj¬Zµ¯-£…ÕŠŠ®Pn»šØRn¿šŒ¤&\5µôÇñ#'”Ë_EˆŠö«}“Õk¢ï ½AM*=¿ªW¹<‚ùW*ƒêª(Áóª¾B¥v F(8V©Lí‹Ë‰ûNápþ/Móúj¶<“ 42m#<¾xÂS|Ã5ØÍ¼¢h[Z±Ä;2ê{ÒuÛ3̬01ÛÎz–#-eõêýmétÚ=&B›°/§?´«ä+Õ²,¢Ñ¨¬Û -N$R}_Q­­~O$þàòŒSÞeƒƒƒ†QqâÂtÐf0iNÄ#oö˜è™´mï½2ø{$é´·-ø;&¿š¦·F0Mpžc"™Œ·M™ Æ-˜FM˜þ^(·gÃÔqåÒT{µ-h´x¿izuš‰óTSËòÎW®mc1/_ÇñÊåºÞïšVøŒÅ¼¼]wòvÓõâôj8\8.öö©ë9Y} c|;”æY.pØ«Cð>)=®\}ÔyÔdÃ(n·©œç/þb o}ëBõTšŒv <õUz%H©¨}}}~¿B…7 ëìëë#‹¡iš¥@…ÒN&“ãlX¹Ùl˲H&“eÃ’«(‰D‚ÎÎNúûû …B~˜nuõ» ÏÞ××7.¿`¹Ô;¨Ï`(ñà1ª.¹)„K§Ó$“Ir¹óæÍóÏS©>ÁvÉårEáÛ«=fªç¦»»{Òc_5Èio;y¯š7®ÝúûûI§Ó~ä%8Z–U4).ø©Â¼OtÞW¾ò•õ~´êŠ÷u`aüðlÞúÑŸ`šo$ÆVA¨Ž¶?ewùfÌ‹ Û]×%™LÊ x‹¡&f‹Ž$”ràd‡y¹ƒœwÞþ6ñj„öÃZó,óç¿mœ·£ (Bk3ѸšùL&ýC´ÔsNÙ‹éx' ‚P_Î=÷\Ö¯_ë¢dÒû=ó„œRÁi¢è:žGDùsMƒZÃ4 éÇK£òU¦Ê"‘âs«•op¹ ×-Ê<—*Si=Æ÷‹ çWçŒDŠ…+]/,ó¢Î£DDµ]•Oå‹yå(-‹®×/XŽ`ûêzAlTË£~J룄DÕž¥Çªs©:ªó”kÃ(”;¸_µ}ðwu=ƒ"i°|êwÕ^JèVí¬ú]•O¥SûUÕ¶ÁòÏ£îmU®U«öqòɇ*£Äx<î‹hjÍÜàÚºÁ5€ÕºÄP¼p0$w8ö½ÝTïh4J$!•Jù§ Ó +®Êy»©~J6›õÅ<59ª4‚ Ç­„HÓ4ý}v µš¬]  RĆrT:fp‚ð]¦iÒÙÙ釟ì9ŽSñ<嘬>õ¡lgXa*äÚ€Ûn»-÷Öç¿‘ë|Ñ̽qÕçsÙlaßððp.‹Õ»ˆS"’‹ä¨âŸ‘3r±\,§å´ªÒ·Ò¿ÿÉu¼y0×ñÒÜ×]Ëi¹H.’Ósz]ênæÌ\$™ðº¿bèõ¾ëÂßýÞßåÈÅr|ÙÌŽŽær¹\.•Jå‰D½‹&sΖ-[r·Ýv[½‹1çÜvÛm¹-[¶äÈesó÷.É-YòbQ¿ ¿¿?§ëz½‹)s†z&Ú›nº©ìöÑÑÑ\6›Í…Ãá\8Î û}Ahe*=­Œê ær†‘Ëéz.×ßŸË æròØ íH»¿”288˜Ó4-—H$r†aä‰D(GÍŽŽæR©ÔŒö"‘H.ûëºîŸ{ªŒŽŽæ€œa¦ÎéºÞ°c¤±XÌoïl6›Í úŸª®ýýý¹H$RïâÎ\½s±²ãzÓs4sfÎÈþØ¥ø̯]Ç U_(›ËåÈ‘;Éøn.•òöýÅ_üOÃ>‚0ÌDŸ m<÷¼ô§‚_ïúÃÀ,?ÇŸÔL¤òÿ&ÂÅ%M— "L¾–ÉL¢BÁº¸èÌíl›·\bìin<áËó§îÍêàM œNÙ3d°±‰äÿiL-,’áNµÜi¼¸*ýôW\ôÚ̵ð±i5oS³ý´íÀ~x¶ç_Í@¡}8~ïñ€Kǯ—rÃû¾‡iÞèïS!†Ah?”‡£eY~ØTAZŸxÜódH¥¦¿î« ­ƒã8~xÓD"A8Æu]"‘ˆå@½/¨q…jÖž ±XŒt f®òœNØmMÓªò¨Saã5´·®ëtvvú¡\UÈÐÒ0£™L¦¥–ÌHäÿYx.Ê:º?f T÷sq±ó¾{jŒ±Z6~q#|¡Þ5¯wæÛú ý{~$w¼ãD\W¢šÂTháñðügÙ=ÇQF#‰´d8$ õ §Ä¶©Šn3Á/çâà`ž8½õ;kKÃùµ”?ø9Õr'˜|Àü´í§M»|ÍËéùµÝ3ý’ Bc3ôÂrà[ì>¸„k¯]áo·m›P(Äèèh½‹(“ÉdˆF£ úë( ‚Ðú<õÔRl†‡ë#:ªuµTh@µ¦Yé§®ë~¨Å`HÅJÇ8ŽS”V+“N§ ‡Ã~¸Çt:í‡ïÝȲ,½9µ®m<'‰…„BèH]×+“N§1M³hÒg+£Âs—‹ÅH&“e ¶Ÿº6ê3ˆZ÷nªåS×±ô\ÁëL›N§ééé™û‡ ÁPV$Á4M¿?0×u]/:ç\õKy|4‰øc7*”kV­³ U'‘ÆjÆ,5´¢c* ”åø÷ýÿ^ïêÖ•CÏ?޶ߠSû šö*ߦ ‚P=m#<î~yKŸ~—½c'ЉmÛôôôLiqb¡yÐóÿ!È‹+WOñºg¼—o«tÑAZžS~sŒSƳðr̘÷æ8¶m˚ςІ¨µ‹R©”x9 B›ñÊWîb*ó”|‡ÐuÓ4‰Çã„Ãa2™Œ¿¦›¦i¾]‰D"tww‹Å|ð=vÒé4ýýýôõõ1::J(ò={”(UNðÓ4h4J¿?0ªÊPšÖq,ËÂ4MúúúH¥R~%žÅãq_ s]Û¶ý~’ëºX–勚A! ðב³íñž5êüÁòE»r·WJÓ”мÁí•^Õ®ÉdMÓÐ4Í_p:Ûº”©–³ÝH&“òN mÌ¯Îø-'ì×xãEÛOxT¶Y„ê™—kåmÆ ܶ¼u%Ÿýí ¼ï}Wúè‰<„Veݺulܸ±ÞŘs®ýøÇùÞÇþŽKnþöÿÑhÔ_œ]ÚX¿~}½‹2§lذãÎ?ŸOŸåHæDöýùÿÞ ŸmÛegÍ B+³aÃz{{éíí­wQæ”`_( I˜e¡íiÇ÷ƒÉúBŽãøï }}}ô÷÷ûeJðOȉÅbÄãqb±˜ï™¨°m›h4Š®ë~¸Ä™F-#“Íf«~· zz‰Çã@ëz 5:ñxÇq‡Ãèº>§híü~ÐÛÛË}÷݇a2N(´=íØ'ðëýOyÕñqüþx›I,fúÄãQh'f¢OÐ6§íæÑm¯áÊЕôôôHGZÚŒW?ü0ߺáÏ•K‚Ð~NRÁãG?ú¦iúk ‚Цä¿/ûæ›øÀ·Ï%N㺮h‚0 Ž«w¦Ê† ¸ôÒKYµj·Ür ###U7ÖÿÏtí÷ªÛÝÝ-bƒ 41ÓµÏY Éo}kNÖv„`º¶€Qïù†Þ€mÛd2ñv„&eÚvü‰âí(ÍO-¶¼Ë¶m3<<,ƒ‹‚ÐÄL×<öØc2IZ„Zúö·Ç‹±ù?(ZÏX„©ÑTÂㆠØ´iëׯgãÆŒŒŒpË-·Tuì/Nù§]´L&C*•’— AhRj± FCÜ ¡‰DdíAhbj±??éX—ñæ7_,/‚ÐÄÔb@¼¡U¨Å¾Ò»€þÁ©M÷®Ð ׺žÓVèw8p€½{÷Ö”GÓCCCŒŒŒÐÛÛëoëêêbÍš5lݺuÒãßò–·044ÄððpSz6lÚ´©ªz62[·neÓ¦Mõ.FÍlذ¡ÞEh[jµ'œpÉdÓ4›Öë¹î?±gB­Ôj n:ÒÍ=¿Ã0šÒ´Êý× ö¬êЬÔjÚ‘V±S¥ŸÓvºÖµÚ‚ÓN;mZk#63òL´ít­¥_0uÚéþP´ÂXÄth—k]«åÑË¿À©_{7þçïÅuݦóvl…kÝ Ïi+ô;¶oßΣ>ZSÇ×»Õ²gÏ€"ã°xñâIÕügžy†/ù˼üòËœ~úéõ®Ê´xàعs'õ.Ê´Ù¹s';wîlz#¸cÇŽ¦­ƒºO?ýt½‹2-j±O<ñ/¾ø"?þñÙ±cG½«3-šùþSˆ=«?<ð{÷îåüóϯwQ¦E­}‚ûî»Gy„… ²cÇ~üã×»JS¢Ùï?E+سf®ÃÞ½{yôÑGyæ™gÆ=KÍ@­}‚;wÒ××GGG¯~õ«ë]9¡UlÇTiæçtºLåZoÛ¶±±1vïÞ]ïbO‹ZmÁw¾óxàV¯^Í¢E‹ê]9Až‰öa*׺Ýß>ùÉO²hÑ".»ì²zWeÎhG[Ð cÓ¡ÚkÝîc†ÌŸGçæwsÒg¶ðî÷¿Ÿ±±±¦{FZá¹n…ç´ÙûÛ¶mcxx˜“N:©¦|šFx¬…|ä#¬^½šSN9…³Ï>»ÞÅ™Í8 Ôª4óµxþùçyþùç9óÌ3ë]”ºð×ý×<÷ÜsœqÆœqÆõ.δhæû¯•êÐì,Y²€«¯¾ºÞE™sTŸhÚ•V¡lA3×áÀtuu5}=¦Ë§>õ)~ýë_7õûPíxO…+V°ÿ~.ºè¢zeÎéííåÆo`åÊ•œ|òÉõ.ÒœÕ[h¦r­Ûýý@…al§÷ƒv´íXç©Ô»ÝÇ oùè‡ùÅ–_Ðõ¡÷sÁÔ»8Ó¢îñV¨C³³bÅ .¿üòšûm!<¾ò•¯äOþäOê] Aê̵×^[ï"BCÐÎ9é‚pÙe—µ•Wƒ T¢û€ô !O;Ûy?¼1C7„™ë4ÍŠr®ÑkÖ¬©w±A˜CÄ‚b A; ‚‡ØA@l b¡QháQ)­¥‹‹ øa¢AhmÄ‚b A; ‚‡ØA@l b¡Ñhá`íÚµlÚ´‰±±1î¸ã:::¸æškê]4A求 €ØAÄ‚à!¶@[ ‚ØAh$æår¹\½ Q-cccÜtÓMŒÑÑÑÁÈÈëׯgíÚµõ.š s„ØA@l bAð[ ˆ-Aì€ 4M%<*¸à‚ èèè¨wqA¨bA±‚ ˆÁCl  ¶@±‚Ð4¥ð(‚ ‚ ‚ ‚ ‚ ‚ BcÑTk< ‚ ‚ ‚ ‚ ‚ ‚ ‚Иˆð(‚ ‚ ‚ ‚ ‚ ‚ B͈ð(‚ ‚ ‚ ‚ ‚ ‚ B͈ð(‚ ‚ ‚ ‚ ‚ ‚ B͈ðXGÆÆÆ¸õÖ[¹ôÒKYµj¦i²yóæqé6lØà§¹å–[™Òþ¹¬Ï¥—^ÊÀÀÀ”ëPïzlÞ¼Ó4kºõ®ƒÐ¼Tc šéþ«d š¡3a ê]¡9™©>Aµiæ¢>ÍÚ'€ÉmA3ÔAhMæ²ÏЈ÷ðlÛ–F«ó\Ù¢F«·01sÙghÔ{£[ÐlÏÄ\U4R…ê˜Ë1ÅF¼?¤OÐ>×z¶i¦:_ýõMùŽÝ ãžcccÜrË-¬ZµŠU«Vqýõ×3444å26Êý6'c69¡nÜtÓM¹žžžÜÝwßÛ²eKî¶ÛnËwÞy¹»ï¾ÛOsÛm·åzzzrßüæ7s[¶lÉ]wÝu¹ë®»®êýs]ŸóÎ;/·eË–¢íÕ”±žõ¸ûî»sçw^.Nç¶lÙ’ûèG?š;ï¼ór¿ýío›¦Bs3™-h¶û¯œ-h†:Ì„-¨w„æe&úÕ¦™«ú4cŸ —›Ü4C„Öe®ú zϦmi´:Ï•-j´z “3W}†F¾7¦k ší™˜«±ŠFª³P=s5¦Ø¨÷‡ô f~¬¢Ñê=4SÓétÓ¾c·Â¸§:ß–-[r[¶lÉ}øÃÎõôôäöìÙSuë]‡Òk2Û÷“ubÏž=ã:¹œwøÃöÿ~ë[ßš»í¶Ûü¿ûÛß7Ùþ¹"N箻7l5e¬g=®»îº¢sçr¹Ü‡?üáÜ7¿ùͦ©ƒÐ¼Tc šéþ«d š¡3a ê]¡9™©>Aµif›fîär“Û‚f¨ƒÐšÌeŸ¡ïáÙ¶-Vç¹²EVoabæ²ÏШ÷F-¶ Ùž‰¹«h¤: Õ1—cŠxHŸ`vÆ*­ÞsA3Ôù›ßüfî¼óÎóší»Æ=·nÝš;ï¼ór[·n°^Íb[æjÌFB­Ö‰‘‘z{{Y³fMÑö .¸€±±1†††ütŠ®®.Ö¬YÃÖ­['Ý?W ‘N§ùä'?Yvßde¬g=FFF*:7Àí·ßÎÚµk›¢Bs3™-h¦û¯’-h†:Ì„-¨w„æe&úÕ¦™mš¹O“Û‚f¨ƒÐºÌUŸ¡ïáÙ¶-Vç¹²EVoaræªÏШ÷F-¶ Ùž‰¹«h¤: Õ3WcŠxHŸÀc¦Ç*­ÞsA³Ô¹··—7²qãÆiÕ¡Þõl…qÏŽŽn¾ùæquÒ,¶e.ÇlŽŸ³Z E¬Y³fœÁãî»ïö¿8öìÙ0îËeñâÅE_:•öÏccc|ô£%‰”}ø&«Cµif ¸««‹[o½•‘‘ºººX»v­_ŸF¯ƒÐÜLf šåþ›È4CfÂ4‚Mš“™èT›f6iö>Ln š¡Bë2W}†F»‡ç¶4Úwø\Ù¢F»ÖÂäÌUŸ¡Ñž UÏZlA5uj¤gb®Æ*ñZ “3WcŠôL¨:JŸ`vÆ*íZÏÍRç®®.ººº¦]‡z׳Æ=»ººX¿~=à o{öìaÓ¦M¬Y³Æ/S3Ø–¹³ÇaóæÍ\ýõtuu‰Dê]œªI§Ó,^¼˜›o¾¹ÞE©‰ë¯¿žŽŽÖ¬YÃÈÈ7ÝtSC}ÉíƒØ‚ú"¶@hÄÔ±B3Ь¶bª´’m™*b‹„Éh;ík ÄÕÐ.¶ ]íˆ-Z‡f·W6l`ݺulÞ¼™k®¹†ŽŽŽz©jæÚ†ŠÇcáÖ[oe``€›o¾™H$Ò47ìÀÀ›6mâ[ßúV½‹R3‘H¤è¡3M“M›6ñ‰O|¢ÞEڱءžˆh*Ù‚«¯¾ºÞE„¦¶S¥ÕlËT[$T¢ì´·-÷a"ÚÉ´³±BóÓ*öJyo °nÝ::::|OóF¦6T<ëÈÐÐ?cŲ,Ö¯__ö+7ƒ%è;ÙþÙb``€Å‹së­·²nÝ:Ö­[”ÿ©Ô¡žõƈ«¯¾ÚgÐ,uš—jlA#ßÕÚ‚F®ƒb&lA½ë 4'3Õ'¨6ÍLÓJ}˜Ü4C„Öd.û pϵmi„:™+[Ôhõ&f.û ro̤-h¶gb®Æ*©ÎBuÌå˜b#ÜÒ'˜›±ŠF«÷\Ð unôkÛìãžj­Õ ½½½ôöö2000¥26úØmµe¬&uä–[nášk®áöÛo/«YÅÊ-]˜s``€®®®I÷Ï6k×®åŸø7ß|³ÿpÍ5×ø¿WSÆzÖã‚ .({îà—w£×Ah~&²ÍpÿMf š¡3a ê]¡¹©µOPmšÙ¢ú0¹-h†:­Í\ôéž+ÛÒHu†¹³EVo¡:æ¢ÏÐh÷ÆLØ‚f{&æj¬¢‘ê,L¹Sl¤ûCú³;VÑhõž Z¡ÎÍrm›}ÜsóæÍÜtÓM¦itÛR1ëÄÀÀ###¾2ü *Æk×®eÓ¦MŒpÇwÐÑÑÁ5×\SÕþÙD=4Á haÕjËX¯ztttÐÛÛˆ üs °yóæ¢F\¡¹©Æ4úýW-hô:Ì”-; L‡™êT›f6h…>Tg ½Bë2—}†F¹‡çÒ¶4JanmQ#Õ[˜œ¹ì34Ò½1S¶ ™ž‰¹«h”: Õ3—cŠrHŸ`öÇ*©ÞsE+Թѯm+Œ{^}õÕŒqÇwÕk```Æû!³E=Ælæår¹Ü¬×Ldž ŠnÖ ½½½~¼à±±1nºé&ÆÆÆèèè`dd„õë×û.ö“íŸkV­ZÅÆ‹nØjÊXÏzŒŒŒpË-·044Äš5kâæ›ofýúõMS¡y©Æ4ãýWj š¡3a ê]¡9™©>AµiæŠfìÀä¶ ê ´&sÙghä{x¶lK£Õy®lQ£Õ[˜˜¹ì34ú½1[ÐlÏÄ\U4R…ê˜Ë1ÅF¾?¤O0³cVï¹ ÙêÜŒïØ­2î¹iÓ&n½õV:::X¼x1###M?f8Û÷“M‚Š|Á”Ù>ÙþF š2Ö³êÜ]]]]œ½BkÓ ÷_3Ôa&lA½ë ´6ÍðµB&³ÍP¡}™©û³ÙîᙨS£Õy®lQ£Õ[˜Zñ™˜‰z7Û31WcTgafiµgb&ê©—P ¶mã8Žÿ·Ø‚ò4rÙ¤nÂl0Õûb*ý‘‰ìÀtÎÝÈíÒL´r݄ꘉ>ÁLÙ‚F¿½|R¯öf&Ç T~³Õ'€æµ\6©›µÙ‚Ò>Êo¶î‹fµÍP>©—0“Șae¦U¾\ ’Ífs­PµT*•®w1æœÑÑÑ\8Î9 gFnpp°¦ÁLÚ‚F¿½|í^¯vµ³1NËÍnŸ —k^[ÐÈe“ºyˆ-˜º-¨Ô'Èåf÷¾hV;Ð å“zµ¯-˜ d̰2Ó)_Kz<¶ ™LfÜ œv ã8£££är9t]'™LÖ»X‚P7ÚÕÔB__áp˜\.Çèè(àÙAhVÄÔ˲¤"4b ¦ÎLô ÄD»Úzˆ ±S·2N ´"íj „Æçøz`¦H§Ó8Žƒ¦i†QvŸ®ë˜¦‰eYD"¿eY¾«h8.:>‹ÅH§Ó¸®‹a„Ãá¢óÅb±i§Ÿ¬>™LÓ4‰Çã$‰¢úë1•vˆD"èº^Õ¾jöWb*mâº.étšÁÁA4Mðë¬òªÔŽã`YápØït˜¦‰išãÊäº.ÉdÒ¿ÞS9v*í\î~Tut]MÓˆD"~]'kÇD"áÿmYŽãÝÁk,5Ǫ6©µîõd¢v-¨—–y&mA-Ïú\ØjžÇÉÚÀq?½ºÊ…aiE[PÉLt¬ºŽ­`&k÷àþr¶ Yú*ÿÙ²Ð'¨ÅLõY.µj›œ˜(têTÚºôž¬GŸ`¢ãÛÉHŸ 8O˜»>ÁTÛe²çy¶úÁí3a äý >HŸ`jíù~0Ù8ÁDmÐê}‚`Ýò~P}»÷ɘaã¿Ô2fÕ÷ Ô¹”-Ð4­éÇ J¯‘ô dÌp²<¡1ûµŽ¶»~0>ÁtmAKx<öôôø3T,Ë¢¯¯¯¨ÁTcd2úúúü‡ ™Lúé]×¥§§§¨óªö»®ëw6C¡ÿÅ”L&‹fÇL5ýTH&“D£QÿæˆÇãSÊ+úmá8===~^í«fÿdå®¶MÔ6õåoYš¦ù7ýDmà8étšîînÿ\¡Ph\©íÊMåØj˜è~t]—îînÿ‹*“É …ªnÇ –eÝË¡P¨(M__Ÿ/Ov,0#u¯'µ;Ôf ɨã§k jyÖçÊTóÁTÛe²çy¶ú*¯Zm¼Ôé4¾-˜Éq‚‰Ú ž}U®ÉlA-v@#ˆ¼1C3¬¦O öU²Í>N ®‰ô dÌp"š¥OPë˜a;ëÓíLV÷JåjzGå&œ¡¢Ü?3™Ì¸}ápØÿݲ,t]Çu]ß]Zýœ<^Ó´IÝZ§š~*ÝW§2Û®\[d³Y‰Ä„û&;¶Zªm“àì¥ááa†‡‡‰D"EªþdmtGW÷Âã?àÏ–Þ“[)ìB9&ºƒåF£þ̬l6[óÌIÀÏGÍF°,kJa`ÊÕ½Yb„OÖî3a ÉÀôlA-Ïú\ÚÅdÏc¥6p]—x<Žiš¤R)R©š¦ÍÂiU[ÐÎv@•uº¶ û0ó¶ ‘úŠéÚ‚jŽ-g Ç!™L’J¥j¹4~^•îIé̳ý~Ðêv`²ý3a¦Ó.=ϳÑ'˜)[ ïõAúÍa frœ`²6>AûÙUV3œœfy?¨ḛš>LÁLÙy?¨Ò'h-&'˜Îµ‘>Áôh&;Ò'h5j3œ¨OHŸÊXA³Œ@{Û3lfòž–1Ãéµ[)M/<êº>NQVCÓ´ ‡a¾b<Ö¶í²‹Ì6;¥m¡hŸR®'Û?SLt³Vû0¨EWÕïÁ²§R)\×%“ÉŒ[0u²c«a¢ûðŒU³«lÛ& aFMm™ÉdH§Ó û†+Oi¶E­u¯'“µ»Ø‚òíÕ?ëÕ;eÎ=Au4ËûA-¶`¢>Ád¶ x®Éެ Ò'˜{d̰:š¥O ¨õyl7ý`&ú¥uŸÌ4½Ç£aÄb1úúú0 ÃWÒmÛF×uR©¡PÓ4ýŽcpvS"‘ ûÆÃqœ¢ õDÅWp-”k MÓˆD"¾‚^nßdÇÎýýý„B!ÿš¸®;¥kâ8ÝÝÝþ±åÜÃá0áp˜h4Z”w5ÇNÄD÷#xF:“ÉÐÝÝaþì˜J1£ƒD"?_×uý/FUŸt:Mww7º®û÷ºšÍ0ѱªÜ¶mÕ½Qžƒ™hw±Tl‡jŸõÉìÄl0ÝçÑ0 ¿¬êžW÷ti§§•lA5v`"[Ðìv švŸÈ´‹¨ÔÚ'€ÚžÇj­d je¢{²ž}‚v¶Ò'ðh¶>LÏÌDŸ Väý >HŸ :šÉÌÅ84_Ÿäý`ºí.}‚Íô~0][0QŸ A[ B±6ã8ª‹ô dÌp2š©Oµ?í¦ÔÚ'P垊-˜—Ëår3wÉë‡ã8þM­f¹(·gÕ˜º®“N§q§(¦·J§°QâTË? Û Æ‡šh_5ûg£îS9—eY„B!r¹œ¯ÎW{=k9v¢vÞ¥ç*mÛ¸®[ñž(-»ZðX¹pOtl¹ã›Jí.¶ |;ÁÔŸõ¹°3õ<ËÚN¶`";0Ù±åŽoFj±íb‚íÙ'h¤ïõZ™ÈÔ£O0ã›y?¨¾ 1û03Ïótú3¼ÔéL­ qmA°îS9W;ô @Þ&CúSk'hÌ÷ƒÒºOç\í:NÌWú2fXM;Acö j}iœ¡Ç ËåQ‰–Ë¡ÔçÁÁA_=…BÄb±YŸ‘;ACU‰©Ü´3_½êQ+Á‡&‹z6Z[¶b ¦—_½êQ˳\+•Î-v 5h[Ð*vfï{½ÑêYs´3í`f#¿zÕêÛ/˜«:ÖãíN;Ø‚zÞGtKŸ@¨D;ØÙȯ^õ¨'2fØÚˆ-˜^~õªG­ßë³1Î v  Œ§···ÞE˜sFFF©w1¡aèêꢫ««ÞŘsê]Ah(äý@3jïÌËår¹zWb¶ùØÇ>ÆØØ+V¬¨wQ¦Í<ÀŠ+šº;wîdçÎ\vÙeõ.JMÜu×]¼ýío¯w1jâG?úwÝuW½‹1ç¼ýíoç-oyK½‹Q­pÿ‰=k vîÜIGGÿøÇë]”9¥ú­pÿAkسV¨Ã<À_üÅ_´øxÝu×qå•WÖ»sJ«ØŽ©Ò ÏéT™ÎµÞ²e ßþö·ë]ô9e``€Ï}îsòL´bÿªCÞš÷ý`:´£-h…±ˆé0ÕkÝ®c†_|17ÜpC½‹Q­ð\·ÂsÚ ýŽ_ýêWìÝ»—ÿþïÿžvmáñ¸hÑ"Þö¶·5õ€Ê† èíímê: 000Àúõëë]”šj‰:´#K—.m‰k×ìu{Ö¨:´­Ð'h…ûZÞµB6lØPï"Ô…%K–4ýµ›*­b;¦J+<§Se:׺]ß.»ì²¶»?ä™h¦z­åý yߦC;Ú‚V‹˜S½ÖíÚ'8ᄚþ™h…纞ÓVèwÜyçüà?¨)¶[µkײxñâz£&.¸à‚–ßÓÌFCh~Záþ{&µÑ*÷_+سV¨ƒÐ>´Ší˜*íøœ¶ëµªCž‰ö¡¯µP=íx´ÂXÄthÇk=Î>ûìz¡fZáZ·ÂsÚ ýŽ•+W²zõêšòá±Ihö› £££%Ö hÇ8çBãÐ ÷ŸØ3A¨V¹ÿZÁžµB„ö¡UlÇTiÇç´]¯µPòL´íx­…êiÇû£Æ"¦C;^ëépê©§Ö»5Ó ×ºžÓVèwœ|òÉ,Z´¨¦<Ž«w%AAAAAAAh~DxAAAAAA¡fDxAAAAAA¡fDxAAAAAA¡fDxAAAAAA¡fޝw›7ofÓ¦M㶯_¿ž5kÖøoذM›6166ÆÕW_ÍúõëéêêªwñA˜Ä‚b Að¨Æˆ„ÖFú3‹ëºØ¶ €®ëèº^ï" BUˆ-Aì€Ðh8hš÷IJÀ4ë]ºúÓ0[·nedd„5kÖýtttøi”áX¿~=7nddd„[n¹¥ÞEa†; ˆ-Ác2[ v@ZŸvê„B!æÍ›7î' áºnQºP(4a^ñxœyóæù»®K4¥³³Ó?¾»»{\ނШ´“-¡ÖÊT»håÊROÆãqllŒÞÞ^Ö¯__1ÍæÍ›Y»v-k×®àöÛoÇ4M6oÞÌÕW_]ï*‚P#bA±‚ xLf ÄBëÓn}Ã0H$þßJ0ŒF£ô÷÷O;ßd2I&“!›Íbæ§à[–5#y Â\Ðn¶@„ñˆ˜9\@+³Ýô2i3@¸LúJÛËå¯41•¿Úoå·…+”i®q˜J@§ŒjjÛå=§š·eA8\}úL £|>åÊSi»3CJpÃx<ŽŒŒÍP(ehhˆ‘‘z{{ým]]]¬Y³†­[·Ö»ø‚ ÌbA±‚ xLd ÄB{Ðn}MÓ0MÓÿ ‡ÃD"2™Ú| Òé4‘HÄLÓ$‹U•·eY85ŒB¹®‹eYâ])L›v³‚ ŒGìÀÔ©ô Ÿœd{ðÛ:è‘Xº]9õíl ]¡,Và3¸ÝÉc—lŸ‰^ÃT§â©è8•Eºrù¤ÓL‰JéÝ)¦ÿÒS«kÝNŸ†·nÝÊÀÀ«V­bÕªU\zé¥Eq›÷ìÙPd</^ÌÐÐЄy¿ð lذ 6Ô»š‚PW6mÚĺuëØ±cG½‹R–Ù´;vì`ݺuec B;±nÝ:6lØÀ /¼Pe.úëÖ­«w5¡® ±nÝ:îºë®z¥"Ù‚Zû»víòm¡ ´3ê;q×®]õ.JYfûýà®»îbݺuU¥­'µ®Å¨iZYá0“Íf+—L&ýp¯ÝÝÝôôô‰‡óæÍÃ*µRÛ,ËbÞ¼y¤Ói?¬kgg'ñx¼ÞÍ)”AÞäý@d̰yÇ +éDÖ$éƒÇÙôÉ’í6žØ•,ÉÛÎç‘)É[å•)IoŽ‹ã‰N~[:Ÿ^m+(•DSÕ;)ÕÞ¢“¤2‘X®­«I_ÊDáPK³Ú¾~¹}|ºž|ÚÒ:¸ý^xÖ`>.pw™¯7×…»N¿Ý²àk‡žœ‘>AC…ZíêêâöÛo h3u>q¾{"ôÚ þúIø‘æµ…i.÷ŽÓe¼ã7°õC9læ‘Ì·Mxq%Œœ}éÐúšû #<>öØcE¯_ïUnÓ¦Mòå/m‚ØA@l Ùµn‹ ­M»õ lÛ& mÓuM«mÕ£D"išd22™ ɤ7‡‰ÅbeR’jŸ®ëÓZ 2˜,Ãq2™Œ”h7[ ÂxÄxÂP¹oO%ÖAA  „AaÒä¥DB§d{P`´ðÄ*5.U‰{¶EMðÄ´ žØæÎ1“Ï+(rª²ª|"%e°(‰ê¼Q kRj{pÚù’É$š¦•)';o]×ËÖ]¦Š¼‚ÐnvÀž`»Ãø©P²J·?û(Éçՙߦ<÷  $j{F)œÏJå!¨<ùÔþ0ž7f8¿=–ß ä­8%ø%¥û÷“Éÿ®<Ó%eOçë”–}å+Øùý¡üöd ]0ü¾°õ†â¶uw> Wì+ö Œßüc¯É@^}À pÆo eRå9pbއ.óÒÇóåÈ¿ÚÛoP,¶»ù8öŸCÔ'“oìe;=¯Fð¼ ÷]7=ù6´óŸ†Õ_:àØ±côäóøõ*>s˜£Gs\66ƽ ð¶o}‹ëïãöÀçî»ÿøÇÓ¼S=BxܼysY7îࢱjæBéb°3nI„ú"v@[ ‚Çd¶@ì€ ´>Ô'Èf³ãÁZ*…8-E…5M§ÓU¥/E…L b±XŒÁÁA\×­˜÷àà ýýýèºN&“¡»»{Êk4–zkÖê½)´d A¨b<”g¢U²M}úqŒ÷´ðÄ® g#ÂC‚ªýa<¯BõÍ­Åž0¨SðZtá|z%0šùcS fþÇ  B*q2–ÿTç5òeìÉŸ¯çŽ;ü:§îüþT~›Ý"Àß¿ðÏÞtF>?'^¸ü^¯m’ù¶‰Ÿ}5<{#üÒ[.”8žøú‹•pôþB}£ùs^ÿÂaNùËÜøl!ß0°âû°ü¸ó!XqØKoËßÿ §ýr/‘@Y†+n€³_ðÊœÂûóçÿ|„,ðê‡æË;wòÅ'¼íw…¯äû æÏyξÎÞû±úÿæ„[Ë´,þºÿž¾=Ç‚‘ýä.»Œ•O>ÉÆÆXòÓg9;‘s7<Ê#7ÞȲ;YßÑÁþÏ>ıaäÏþгþèjº_Bx\³f EkÌ °yóf®¹æÛÚµkÙ´i“?“áŽ;î £££( ͉ØA@l ÕØ±‚ÐÚHŸÀCy#NW°s]—d2I&“·o¢<-Ë"™L‡I$ ‹Åü0­•µ4Ÿ ŽãLÙkRhoÄ‚ vÀÃe¼cPxTÂdéZŒäQ!GƒSŸÒDD%<Æ(„U‚¡úÑðD¼~Š=|A1Ò¤Ö²@³ ûü5'#߈äóòèÏçËÿþì׿ιccd)Œ¹|~1 œ_t1|`þ|²Ù,Ù|º0^¨Ñ0ÿ_ e åÛá'K½†zãÉžà˜Îç³öN¸ñû…r¹ù||ø7\ø³_ðŽûà‚G½ý)àk+`l|ü/޲ü§/‘È·Ùü‡îãø?;ä ±±ÀuxÓ7à‘ݶÑðÖÈ>ýôo±ç¶§ÁuÙvÑE |þó<óµŸpÍåûùÜçVó‰›>‚ëº=ÚÅn4ýüE|ò“òÕgN"Nóþ÷ßΞíó8ùñKMã?÷ìá/} 㦟&Cø©ûùßÿûÙ²b–e±mÛ]œ¸s/®<“ÇŽ^TÓýÚk¾úÓŸ¢/_N4ç'i¤ò“ž’Iz‡þþAbß%ù!ÿ~äÚ{ßË ð·w¦OƒñïpÍå^½€óèî†Þá$’¯ïÐÐBvì0èëƒw¾óŸýïøý·€®Ã½÷.`õs;‰=²Çq8í´K±v–a T÷Êqà„ÍûùÞý'±|¡‹®»ŒË©§^Ä»Þõ(™ÌN†‡‡yï{ùÇr .»v½“Å',åùç_"rÆ=Ü{VŠ«~û-,aáÂ+I$–322Âý÷Ãâ]ÉGn@·,Òé4©Kÿ†/Œ®äcwœÉ }û苲áº6ƒÏÌãáǼ›j¼£qÕ4„ðÞŒ„k®¹Æw‡îêêçÝÑÑÁ·¾õ-¸à‚ šÖp‚0±‚ €ØA<&³b¡õi·>mÛ„B¡¢m†aÍf‹¼Ë¥Èåreóíï璘¯oÜ1º®Óßß_Öó1‰ÉdèééÁ0 ÉT*å§Q–eáº.¦iŽ? à³³Ã0°m›H$⇄ji7[ ÂxÚɨ5 ƒÂ£[²ŸÀö Àh~á‰J`T…j:‘.•·"„GåÝHþïH`=<ñ§?=ÈMï<©h»]aÊWqÑE§R:wª¯Ïæ‰BX–Å¿üËJ^~y Wýí{pûúÐúû˜7†‡=aòʃxÇ;>D:}'ô ¶ý=À×2‹Ý»M\×å;Ñ(‰+®@×uþôYp–±ïÏAA, ¸.ɤW“tÞx"o÷Êó ¼úÕûyøáS¹ï¾D£"•JáºpÎ9ÛZÊ3Ïœ@&“Á¶c,]ú0}}‰@OÏ<‰×^{wÞy'‹ýßÿþ‘N÷ðÊWÞÄöí×ó¹ÏÃ;qñ_æªûï§ÿ}à³G\þìgpÎËOpa×'Ñ/ég`àZ¾{¦Á—þ_¾wÎß`Û6થK¹hÅ÷Iï|Ú’CÄb1^ÿŠWð½/žÅ«WÁwçÞÔC×p?„B8K~Aw7<ñ¥cœû®Àô½FxŠÖk™ˆjÒ‚МˆÄ‚àQ-; ­M»ô ²Ù쌥K$E➦id³YÇñD`Òu&³Ù,¶mû!T Ã()‰áp×uÑ4­È3Ryd¦R)"‘HÙ4‚0ÚÅ‚P™v±q â`©gc†B¸Õ$ã…Çtào3Ÿ&BaA% ýÁÞ€K{ZÉþxÜóÔëï/wïÞÍ®]»•UÕõ7¿éFÇm·mOxTý Õgyæ™ßãÑG½¾I&“!ç£1D…â„à …H$ôõÅÑÉò¥/}‡w¾ó©TŠ_}5?9ý2ÀdƇxäk_cY¾oóì¶m,;þ¶}Ñ(„M’I'A8ì•)“5Ïk÷îNvïN²q㟳nÝ®¸âíØ¶'åþâo%}?CCù»¿[Î+^¡ñ&ÃåÊ'¾Çß]È¿þë·È Ò—L’ÉÄ€w0þ1V¬¸–?¾þÚq.'Ã}à %Å·6=ÇeºÎ÷¾³ŸÇÇÎ%qÕÝpï½X?üSÿÁq€C‡øÓ'cl¿ðS8ßy¬uÄl·ë"bÑ!Bßø#Œ/ì"üÙ¿ãïNÿ%Æk1üï¾òChß|Ý0 ó Z§œÅE=üÞ´ïã†XãQAAAA˜=T(³rž‰•P¡ZU¸ÔJû'«I#‚ ‚‡]ò$êT…]Ub`P4ŒQ…j¶ø]­ÍXµþ ëVöV,õÝ»wóÔSKÇm¯ÔíãÔS=ÏÕx<î Ë–ÝG6;J__ét:>‹Ë/ÿ5«WïÄq†‡‡¹ì¡‡øÒ—¾ À±c¯å†Þ^Âá0º®“HxQÞvÖK$óáàM×å®»¶qî¹cœyæ>ž_¿Þ_¿ú¸£]\ùò=\pÁa\îùÂÏ8²m‰„:UÍÝúÜ羂eY\xá.¾öµk¹ðÂm€ËÁƒçÓÓàóù dË–¿cp0ǧ>õ|ð¦#<>v.ï]ó?üùûAOô–ßÀ8û~gÏñÄÖ¹ñÑGY}`ŒŽ’]y3‘«ÃÞq:è:¿wÆØÄVý7‘“èü ==ùk±r% >ðômwiÒG?éÞ/£g1_ýö¿oÃv¼þœùî%è:Ø ¯¤ïÿ;—Ð/?CŒ$æ{—rͪ_sÙ\Ó},£ ‚ ‚ ‚ ‚ ‚ ÂSªë¹x£òlTk:§ÿ¨5ƒaR•ˆ¨SXûP…NÕéÀƒaWÇóbW6ÊDwÇ0´”+Nàû÷OšÆyí Kã¬ç “ñÚèë'{Bâè(Úgþó¯ÁÚ~™Snâº]I$:íC7ÐóÀ±mï:é‡õ®ÍÐýõÊ¿¿L“ðŸ/Å>õ*zÄyò˜ ¸ûù³‘E›?Æ¿ùLÍ÷µ‚ ‚ ‚ ‚ ÂŒ¡Ö¦Aab žŒnàS ’ñüþ`˜Tb5KÁ{1دˆ•|*”ˆ©JǼãß8Ê Œå¶<þø›¸üò{Çm·,/ÿþc&“a×® Ù¶íØ¶M8æK¿ÿû†ÁË/wpòÉÏÒÝåûß–¾¾>–/?€ã?D"A$ᄟü„ßüä˼ýíû½s|y)º®‡9ÿüåtk./¸:þJ¯_hóÜ·yuxòErÃÃD£Q\×¥÷Ú¿àð‚ÜóÿÀYg-¢ë¦¯³âðaö¸gŸý2ן³»Ÿ{ÿôO#¬9z*ÿñôûxÇÎäR)â˜óÐçÿç¤ÿMƒPs哸<ÃWþ³‡+Ïû_^õçWšg‘üÆYDOù:‘7ô¡Ÿø¥ÿóP§9B&éÃ7bw'©T ×óœí<ƒAšî§þè:«W®DÃÅ~h>7œzögÿ—h4Êÿþï^FW®dáOŠãdX¼t)qâgq÷œÆæïàOV À '°gä~øË¼G ¦.>õ9F_^ŒMæ…7C8 ®Kì´;‰<ÿ÷¸GOEïxó?ö1Vö³Ä.¿kôœE¯A_µãå@×±÷œCäâˆß{ é—ÿØo×T bsœ:¥O,á›NÁÂÄÝ· p]ÓI½vW"±®Ãà ˜WÅüƒ3FÀ7¾ü¡Â}ašì[µŠ=§6Ý[áQAAAAAaÎ Žn™}j»K!,ªNa-Ç g£ÒÔGiUÊó°b™J„ÄþçCô÷çÆm·mOÈÚ·o¤(têéK–ø¿Çãqâñ¸¿¿³ó3Üyç/ùØÇNôC®^u•·¾ã?þãÕ„BINܹ“µoÿ(Û·¯åᇗbY‹Åxãßè׿‘GnÁ¶áÈßȹ ÎÄúñ| F÷äLbýçn¾5r&»_Z„¶`ö¹ïá3¡‰+¾C?}Ø;—aí¹”Ï|æAVÞ»«¯>ƒ¥«ÎD;å ¤ÿßQ¾;ÿ=˜vÃý²ÓùõöÓØ:v.ƒôxc8 ™ ÉíkaÅ O™Õ4°mô%yOÄãçÔw½ €ÄEÿAìmaí\ ^c†Ãdß÷UŒ°Ž³»³¨½ÃaO6 (]2ÛxϹ¸h¸ç^Vt@&ã]ï P©ëù³$SK(ÅÏ×0ØõÎwR+"< ‚ ‚ ‚ ‚ ´8®ëbY–e  ‚ ‚PìÀ ¯ôX´òŸ âcp-GJ~P¥Bb©˜¥øùÏÎîÝópÝñáU- î¼s»ïÕè8ÏíÜÉ߃ãÀSOÀÆú',Ë«ÅáÃ$xÍk^ƒ¦id2R©%¬Xñ,££KX¹ò8¯íîö¼òÌâr™X䘇qâV^ûêýÜýØc8¿ÞGäå/ð–SïÇ}j?>ö1^Þ²…Wìü.±œ×ñüj/±TЍã?þ.)¢\qÊ¿sâ‘›¸ó…o°ì±ÇØÙ¹¬;åFV¼ˆa“ùÉ2"Ð5Lã/&rÙCØÄ;¾XtcõÂ7žì5N^%4nX @øÒíE n¾Å[gQÓðTEÓ„Dó=§{×ò߯*j.9M½ãJM¨¿u}|úrD"Íz DxAAAAhrB¡óæÍ÷ …p#}¡PˆP>Y%âñ8óæÍóÿv]—h4Jgg§|ww÷¸¼AA˜;¬’¿ãx£҅”æfâ­ÑXºŽ£^&Ïà¶@W`¥_ÿɤ§“•ŠT_øÂ©\~ù½h|ðƒcØ%Ê×óÏ/bÛ¶ /Ìú›–>Å–‡æó—y„§Ÿ~ç<ÈÝÿçÿ!ººîfÙ²\|ñÅ$“Ib1¯6w,|?¦éðØc§‚ã ™úî¢áò†ó~‹%ó½-'ñ†yƒ‡/äìÇþƒDb”OnÛÆÂ•ÇèÄâÝ þ›ëŽ}š½?ø'>Ìü­[ý–]öâ[9÷7wðƒ<ɶC‡¸èªÇxܲ×qq-&yÿUl%‰DãÍ$~ývzzTƒ`Ûľq1æÂŸÂ9çxê^8ì7žñ†“±ž8ÛÛ‹yÛ#"p.¾¾Ðpá0ÆÍ—JQ,jºî‰ƒåæˆUŠbo^·hܶJbr¹ë Þ¶™Œ’/£ ‚ ‚ ‚ B1 ƒl6ëÿô÷÷cÛ6Ñh´¦|“É$™L†l6K.—#—Ë‘Ífq§æ¼AA˜>ÊËQ…]Íà‰‡åÖrT?ä?Õ~o=Åòù—zÈå#z–õz³mÈ;/ú¼ûÝOò«_Ï×¾vˆ_ýj¯?ù)‘ðÖ øÕ¯^G&“!“ñV¢¼rÅaöï?gž9‰sÇÆø‡?ù K2ÙÍg>³=/p™8p"YB\3œÅ4u¬»òìŠlÙsN&“áËý£Èå8pâ‰ü|÷n¾¿ñ׸ÀÇ]Áæ£ÅíVóåM‹ÉÏëf^?è;Äxû $p/iÞþë_cƒn7Ú©Gø½ß]è­QWçL3ß&¦é‹‚º¬] ‹b_^€Ô´ü~Ã(ˆ’º>þúhšV¼Þf‰DÃrâ ùŽ˦—‰½«iå·Ï4"< ‚ ‚ ‚ ‚ ÔMÓ0MÓÿ ‡ÃD" oº¤Ói"‘ˆ7–Ç4Mb±XUyÛ¶=Îát¿ £Vi¿„vAÚ‹ñÞ b ë=By±1HP— …ʇà„ñ‚¤ëzÂX%¡Òu!-döº×½Žƒ¯äË_>±±ÓI$Äãq>øÁ1Þò–¸çž‹9zô(š¦¡ë:ÿñôûØöÜ©œ~úvíº\—Ÿþp7×^{Ë—_I4 Ñh” .¸‘YNùŸ3¼õï[½šá»ïfáÑ£xv€ýÛ÷ð†-·ã8./¼ð%Vçû‡3‡åÏ¿ÄûÐØ¾};Çì㹟äÙSc籕Ė,áó¹0o>÷_X»ö4”ÏèØØ{X±â\×Å._Nä_Î7l¾eMt½ 4Æb^,RÕþïX NÓ¼ð©<ËyªÓ•ë"U+ †•¶Çbå·—+§Š‚1S}6AAAA*N§I§ÓX–E:ÆqâñxÙÏ`ºÉŽ©½ÒhU•hšVö|áp˜l6[ñ8Û¶éî§‡žžº»»‹HÛ¶ý}¡PˆÎÎN§yóæ‘L&ýãUhWE__}}}ãÎ7oÞ¼ ENAAh6, ]f[åñ¡ *¯éd²µÕ| RÏF×õª–›/Ãå—ßK&SP%³ÙQöì9Ž þ×u±m›;w2þ¦éòï¬öû=úIÏpéª}\<ÿøÆ»þW½ü·¬½“ßý.ÝÝ»èïïgÛ÷¾ÀÎeËXþäøÍ‹‹±,‹W<ðMLâ|óž{0>ÀÉóÄCÏý%®¾(°úwÎÁ¤é½€Á‚sÎÁÞûÞ+pÐ õe¸’A½þ«hšÆ§?ýn>úѧüÖûð‡?†‘_ƒqûڵ˟.nŒ¼[ ò`, MŸ?tS oô` žÃ0Ê{¥VÊß»æÞE öù £°=8IÌ4=OP…Š‚aYÑh”½{÷rðàAjA„GAAAA„:ãº.–eù?ñxœt:í¯4]Âá0™L†îînâñ¸?ð¤<,+Ñ×ׇišŒŽŽ2::ŠišEb¡ú}tt”\.G,#ú^étšþþ~r¹ƒƒƒ¾,Sp-“É`†7(‚ -BЫ1HPWRûÄFåí8ÙZŽ0ÞkNyê•z6>û죜tÒ3ãò3M/í‡?ÜK.w‰¿½££ƒeËv²|ùAÎ<ó"‘üæ7óº×}›7¿ùÆÆþ?zz¼>…¦i|úÃCœõŠæÿ¾*Çü÷Ÿñ™§®àoœ·oúFþéŸÐzºù§¾ÂÝwßϯ‡×÷#=|˜_<;À©˜ühø­|qþm¼zÿ~v½ò•ÄHr<:Ç08ë¬7¡é:ûoaɼÝ<ºëBÀà¼Ë.#c|úÓ7³páA,ËäY Bx9©TŠW½j ŸøÄ…\u•Rõ’K.!›Í¢iß]¶ ½H¤ æ„~ÂØØX‘H牯™üyŠ\M+ïM¨ëpæ™ûж%“IæÏßÁwÞ‰ã8$“Iò•ŠöDõ¡‚eüè}}}¸®ë¯áL&q‡¾¾>lÛö?{zzˆÇã~Ÿ0’N§Éd2$“I,Ëâþè¸ë®»¦u¿+ޝéhAAAA„&ïWH$Ê~–K[é˜RlÛ.ò ÏÛQ+7å} $ LÓô×_RVáp˜X,VVèËd28ŽC"‘ðÏ‹Åp§ègxx¸h&“)UÞ†a`š¦/J†Ãa4M#“Éømü]AZ¥xžfþ3^Uí×)ïñÄ4ˇëϳ1(„årK8xð§ìÞ"^âEu]ÿ¬## XÙ¹hôoˆD"t/˜/.fÇòåÜ{ïåØw<Èï}üãüÁ‘ÃÜöæ`É«FyàˆDRhšCw·ÎUW}Š?ܾW¶‡ä÷®ä’Cqþ‚_³od„%££|þßßȑܣü|!:v ÛuùÁÊ•lÜÞÇ:²Ü g.äìýÌëîæOŽÿŽv¿•úaË–æâ‹½þ…õÖ8v8A:áÖ[#¸n MÓxúiˆFáâ‹_À0NGÓ qHW­ZÀ½÷z¿«ð°®ëòâ‹›xî¹ëI§Ó~Åu]~ô£;Ù»÷ÓX–åG¶0 ˲8ûì—±¬‡üI\Žã`Û6á2qO î¸ã‹=úªüßétš7¼ád|ðQ2™Éd2~™‚}?˲0M“d2‰a$“IÿïX,F__±XÌ•÷¢ê÷ÅHõiÛ6º®ûb¥ju®Ÿÿüç¼éMoªé>GAAAA„:cš&¹\®è'Ó××Wóz;¦i’J¥fppD"eYþT)¶mcFÑÀ—®ëd³Yt]÷gø—†5M30[ßd"Âá°ŸZR„GA¡q€xþ'I!ôjPT ~£ªíÁoÒx¼üZŽ–U´ü w>§¼ùïÿ¾ ³mÛ)øŽsé4–åé dûè%†ëºìϽŠ+ßÌNü.g/|–/çgGÞÀqÏ>Ë›Þô&î^ø{<üðwøNÔËðô±1V<û, O}ŽÑ±Óyq^'ó^~s¶oà¬Ü0;IpèÐ!V¯þ i]çÒßùR'ü9‹NØÏ ^uÞ^^³hç½îuœó™Ïpæë×°láB—aj8ØvÇÁŸì¤iHÀC>® b±b¯D%¶YV’OÜI&“ñ½3™ [¶|ǟŶmâñ¸¿?“ɰcÇ}q/b¿åM˜Í¦H§ÓÄãqzzzp‡ûîûO<ñ%ß;QǶm’É$®ëÒ××çG”ˆF£¸®ë—EMXK&“hšæ÷ßT Û¶}QR}ö÷÷‹Åüˆ‰D]×éïïÇ0 úûû¹á†8í´ÓjºçÅã±…p]×WÝ5M#‰D¤ã.‚ ‚ ‚ MH"‘ ™L’N§+zJN„š¤©ò"TŸj-o5‘+•JNjһ®‹ã8~_Ç4M,ËòB]×ý‰Xš¦ù‚¥:‡Ú¯&€©ãS©ÑhtÜg6›%™LúÑ+"‘Žã‡}¯LMÓ‡ÃD"4M#•ò¼Fo¸ájºçÅã±IQ z__Ÿ¿0}("“L& …B¾ø( ³ ‚ ‚ ‚ Bó 5Ýã“ɤ?Xd¢<ƒ^Á¼B¡¶mûÞŒ¥Þ’–eó‚¬D0Üj&“)šLAšàȼ“ÿê¨) À÷€,·Æ£izûc±Ñ¢}/¿|1ŸûÜj>ü¾÷qô¹çxç;pÙeó9ñð³h öqÖY¯a×®]\xà>–}Žåòúƒ?å—ÿsˆ—æÍà’½¿åûh¸l}d ÷íz'‡â{2ÿÀN·ˆpÜé?à[—]ÆuÝÏßð,i",]B$!³áýÏpÅ'pà Ë8éõ¯÷ÕS]÷Ô.ÌKFÇÕ3øYº½4ø‚®·•ò’ÔuýûÆ0 Çñ=>½þŽå÷YT_Å4M\×õûK®ë¢išï¨&×cT_$¡¿¿ŸT*凢WáïU„ uœòXT‰š¦ùBb,#›Íúy†ÃaßkqppÐO ^8|MÓèïï/j l™@<›år ^'_ÅöÕuÁÁAzzz0 ƒl6K(ò]k…Ö@ÍzP/h¶mûñ£K… ‚ ‚ ‚и®;NìS¡³‚‘ŒÊ¥ƒò¡MÕ€–Ê'(Æãñqy+Âá0ñxÜŸ9¯Ê¢Bx÷ÞÇýýétÛ¶I$þ:“‰Dürˆð(‚ 43Þú¥£ðJ/Të9H£œã}Ê+¯Ü<žÒmJŒ,íض'°¥RðÚ×¾H2Ù ÀÓŽC/3†Áå—ß˯¿÷S:žx‚xVœ¾Œÿó¾…XwÞOww;w¾šã¬çÑp»ê*Â÷dè?ÐǹK¸¸ã›hcПÉð§draã’%Ä·Î=—m»vñž…£\}ÒWùÞ3Âòåç“\ï…ô|÷‚X˜`ÁWÝ‹aÜì:ÆÐtø`^4Í¢ Û{ÎÁY~RQHZUïRQ¶Ò¨r‰®ëÄb1þ꯾I*•òû6ñxÜ"•ø§&W©ˆ“º®“ÉdH¥Rþ:ªÏ¥¢K(¯J]×1 £h G%:ª<Õ“ÉdÒ_+[ –º®û£ã8Eý>Õ›,Ìý\"Âc‘N§Ñ4Í_@TÝ`*ôŠiš†á/3«R õEÍTUÆK¹W›¦‰®ëþKa"‘(&Gh=ÔÌ™X,æÏ`6M³ìõw§ê™Ç‚ ‚ ‚ Ì=¶mûkõ(Ô¤âàäÒrér¹\Ù|ûûûéëëwLpö|)j–|<÷EN×u‹B¶';kš†ã8EãÕ‡I&“²DŒ ‚Ðô¤ñ¼³U¤Q$K‰Ç=¬4º®{‚bpžŽ®{ë;:d2ù}™ .a, ¢Q;ן8ô÷׿ÀüÏýΆeø_q^äàƒ¯cñ 'ð»/n"üª·²|Q–1ŽpÿýÏ1âFXH†í‡‘#ÌîÜ ñÐØÞ¿|9_}æ† 3»ŸEûÎ$Mýz›Ó‡µGãС.–åèÑ‹‡¯@Ó4NÕ4ÞDVßÇ+;çUFë»ã‘âþD%™C׋ç**uG‚æ¦iúbž {ªDÆT*…ã8¾¤WUãòÞ¹ub— •Fã•ÙðÏ£Ž ¢Å`yb±˜JµÔÉ(èÁØè4¤ð866Æ[ßúVn¿ývz{{‹ömذM›6166ÆÕW_Íúõëéêêªw‘gå’›Éd|\Åÿu]—h4 àßøA‚7[é×,¡VU=KÅ%¸¶ÒìÇJuïzõõõøžÊm[Ó4²Ù,®ëbÛ¶ï’ øâS¥õ9švµ“aÛ6–e‘N§}—µž«aÄãqßZ=û–eaÛvÅAhdÄ‚•mØAhZ½OÍV3LY]ºD"Q$ª÷H5x¦˜L Tqê½BÍîW†Áðð°¿?è PîÝ£\Ù Ã÷aJ´º-aršÑhxB£ø;8Ò­S¼žcµBšë<$]7/<Ú6v>÷'Ÿ<Ç#¼À']®=Ñäw†üçÖw²è™“Ø·`Çöì¡ûåßròã›Ùvt1þÏ!FFþ€ŸÞ{/K9‹‡_}Û¶Åxë»wÂç?Ïï†5Œgîᄯ.ägû.ÇÌ‹q¯Ö4=òúópÐõ•EeÏü¦í¢.J«¥iåëj¼þ¤²mkå=+ •¥m«ÆÑK½•×b0ÒPä¡Xr¾Ò˜|¥è„¥Ú€ê¿EÇf¥!…Ç[n¹…±±±qÛ•áPcÆ ÜrË-|ë[ߪw‘kF…ÌL$¾¨‰Dü0©Ê¥×4M_ŒªµÈh£¢^z‚ªz˜Ãá°¿]¹$|%Ü5²WpV„ ‰ê8Ž?#tppÐwµ†b6uUhU5s´ÔÈ)”[x2™¤§§Ç%ÕùÔ¶JôltÚÑLF:&ú³qÔ¿j B&©gC¹ä7ËA(El PÞˆ„öBúµ3÷ç`xÖéì„™Fl ÍdÔ¬jÕ©®Tb*÷uNä”ð¨ŽqÐtOx;räqàþæo>Âïþî—ùÝPˆ“²Yz|Ë_ZÆüù¿Ç¯Ž?žå‡_¦ûØ1þçÐ!¾qh5;t)ðœ—ñÒ`¼÷M¯aÕÿZüâÐ_1þ¾ò•Œ.YB,fâ8:¿ûŸ'sß-ô \—…ºŽý¹N s\}Œó–m‹‰<Ëu9*um*uO*Y¨¤·L•a¶–;K”º»6! '<ÞqÇìÙ³§ì¾Í›7³víZÖ®] Àí·ßŽišlÞ¼™«¯¾ºÞEŸ6Aq-‘HÉd|AA I@‘U-J° ǧ•W­u´,o!Öt:í‡}Tb£òh´mÛ_T^yý©…U-ËòÛB ±XlNDÇqüµ*‚b {ªÊ©ÂŸ*ÁO•Y¹e§R)¢Ñ(ÝÝÝE" iš¤R©šÂÌ ’N§ …B~{«™©JÔÝ´iÓœµÙthG;0Éd˲°,«ìý|ÑÅbþ:.AâñxÑz,‚Ð ˆ-*Û±‚Ð>HŸ@[ BãÛRa18*¯¼Jµ²ÒQúÒªA\Wy8zÑÏ]¶“'ž]ãÀ=÷<Á,‹È œ}öüõ_wóž÷äoÜ@:fßÏ_à<ÄãÏ?‰ÅoîË1tð {ÊÇ™¿ÿa>ý í¼ÈéGÃ8îƒÐM+Ù·3€IDATò›ôϸöïÞÏ·¿ýotÞ×É™gZ\òîwóÂK/yõÑuV¬†Ý§¿]ï(.lŽGgwÕm[IHœêö9”DÚš†‡††H§Ó|ùË_æú믷odd¤È}º««‹5kÖ°uëÖ¦ìD(!A‰–eùBU0”jP¸š*Jdèéé!‘Hø œªÅH犾¾>_³mÛ7Œªžj-ˆ`—Òp²*à‹™L¦¢ð¨Ìé DÓ4‰ÇããÚTÍêTuqÇu©â0;ŽC¿ïuX*ø¨cƒõž‰™¢º®“H$|q6›ÍŽËw×®]5Ÿg¶h7;0Éd’L&ã{<'‰ª„Ãr÷‘®ëMáé* ±‚ @e[ v@Ú‡vé„B¡ £©p¤óæÍ+ûŽ'­N»ØA*ÓèvÀ¦Xx,=¦¼a¼ð8.¯2ËFG k9F"ÞØ÷²e½üñ³_'N]‡¿þë¿æû\>}ËwþÏ ÂæÍ{yè¡G8ãŒïóŠ+þ™¯Ü3Æÿyþ!þƒùÅMNe÷î±–ŽcY³†ôÎ/ý7¾øó͘fÇq¸êª.ººÞÇîݧpï½®súßþm¡~ØvGq¡'Ð3Œ7wÛ^©‹3UÏF¡¾4Œð866ÆG?úQ"‘kÖ¬·_Íd(Û¼xñb†††ê]üªq]×÷hŒF£¾0<-z‰Üу¼÷´ñÂkzxrÓ}=6† ØùÒÛÛ o¼è]8C_üù„iâOŽÒuÞ^ؾýìq囩 „ÒÍi FxL§Ó,^¼˜›o¾yÆó~á…ذa½½½¬_¿¾®õ z0Syÿ©õK=ýj”÷`__±XŒH$Bww·?0­<úR©”.%¸•Rn0Û²,úúúüŸÉdÒÚLÓôC?SëÓÕŠ3UÈÖD"áç\r*¨õ5‰„ÿ;0ç^¢³Á¦M›Ø¼y3;vì¨wQÊ2›v`ÇŽ¬[·Ž«¯¾Ú»ÐX–E4õ' ¨ÐÃÙlvÆB£jšÖ”£ò n¦ÝÊ&™¦9íPЮëÒ×ׇmÛD"LÓôÛ@y®Ã(Ca‚ƒšð1<:J(-|rÝ:öìÙÃyçWïæ*Ë\ô /^ÌÆë]UA¨CCClذ;vŒ{9ofÓìÚµ‹uëÖ±fÍšº¿B=Ù°aCCC e¶ßîºë.†††X¿~}ÙA̹$8.0åú—êb"ARMž(ÿjòZ“uò~ ïBÛ#c†37f\Ë1ƒçݨF”ÓEu*¿n¡®Pª‚"¨OÛöú¿úÕ¯Øìÿü“+¸ñÆgùÑþ™G¦óñ/²wïÓ,å Øñ[v.y+7 ±áÀvâ²òå—¹ ˆù%»ê«¹þ‘%\Ñ» ÷ Ç­ÀÚ¹(vpqX°`Á¬\U¡~lذšû !< °iÓ¦Y[èõôÓOçÚk¯­û ŠòdO€L¥REúX,6+k/ö÷÷ž°hš¦ÿ2“H$p]—P(à‡> ®¥¨¼"ÁÔN&“ŒŽŽúuH$¾pÙÝÝa ÎÙ:rꥫ¯¯Ï÷°T(Áb*tvv…ºmv¡±ç|ݺuõ.Ê8fÛœ}öÙ ÷"ÇI&“þx,›‘­ÜàZoU­Z.¼q½H&“$“IÿŽD" U¾J(›ªì¥*»ëºþ`R2™äÈ)§ðê¥K±m»ì5×¾ÀØË/ëï箟ýŒÏÿûœµ?¯?tˆ;·o§ãÍoæ’OšÕCCíêâ× °å¸ãèxáýéŸrøöÛ¹j×.^º‡B Þ »ÈÆ íÙÃ?øA½›líÒ'„z³fÍ6nÜȆ ê]”²Ì¶-XºtiÃõ ¡(á½]ßÞþö·7Ýäƒ`¨UÛ¶ýwaðÞ%Jû—jB›òTÐ4­hÂî¼yóüI·*Ó4Éf³õ®ª0‡lܸ‘ê]”qÈû Ì 2f8sc†^˜Uü15.£~Ïd<ïÅÒaÀL‚C`Þw¸—(ƒ/|ápŽã°páä O?ý4oyË7q¾q6GÐYÍB®X’â¢ÝÝÜÿä“|Ÿ~öîÝ Ø¼üòËì»äxVœ>ÆÎ þö=ü»á½WðçOý„Woß‚±é»@±^1SžBc²~ýúé4Œð¸xñbn½õÖ¢íåf ›‰XՒN§ÑuÓ4ýp«AfZp,%Â5ø¡^JB¡º®ûk1&“ILÓô½ 3™Œï!©Ö¢ ®eÇÉf³³^rô÷÷“N§}a×q\×Ŷíª×yÌd<xµv†0·´‹ïå_y?ƒwÿþÿìý¼$U}ç?/¿f€áÎÔUùéÖˆRWÄ!Jbª#hü±ìÖ³ù!¬N÷ºŸ5˜ìÄî5 IpMºã|³aW“íÔ×éJÈ7íZ#f¹QìBDFD¸%p%€Ê­áòc†Òß?N½«N÷í¾¿Î=ÏÇ£]]uêœSÕݧÎ9¯ó~¿t>ˆ0Ÿ$ ¥R)çE “Ø ýÿU¿…Ýñhûŧ®™ìöEcDQD¡P I<Ï# C,ËÊ⸋ÅÜÕ3sð“8‘èq i¹Hçjû䛊¿¾ýv.šœÄq]^õÐC<ýÐCœò®wQÿÓ?¥Eøéý=þôÓùé«_ͳq̱ñ<·e _~øaž?é$n‰"¸åÎ=÷\&N>™ƒpíµpíµÜàº\zè÷ÝwŸ¸àÜ8ÆI¯×Ãð€·§uŽN; €?ÿÀ¸g˪qLhÛÙ5ÿÚ¡CÜúðÃü·SNáÙÿù?žšê­|•ØHmÁ`èÏlm¬t6í€Ápä²Ñú⡤WœGqÃÚM·—B¡0ÍËÉèè(I’0>>ŽmÛÔjµÌÛŠˆ“¾ïÓh4p‡(Šéðþc0¬&­-0 ÓYoí€O:GÓã˜þ4ŸÉn§RQql®”¥ãSOG«yº¡¡G8ãŒÏpûí‡yà)þþÙ«Øò£ y3›q_ôù…ƒ·óäSòŸø"OùœrÆ|á!¨Õ 4Ë·E<:¦ö˜–å2áû'8~Fg4,„5!<îÚµkÚÊ¢±±1®¸âЬaãwÝuWGc166¶æƒDGQD­VË,‹ÄmÞZA)õz=€´Z­qÔó<ªÕ*µZJ¥‚çyxžG©TÊÜA¶Z­U½×u)•J”J¥‰Ÿ uÍjXŽôv@‹¸$I¨V«™òr#®œƒ èøŸƒêÀÈ‚‚^“ Ò~Ék|||Zš8ŽŶmêõ:…B!sª[*ʪliS@MH{"î™õz8ŽC³Ù¤R©0::šýO‹Å"a2<<Ìøø8±m3 4Q+ÈòÕeº‹ '½t;Ò¶CrŸûðÌ3Ïðô¦MY]6:Ä_=ðÏ>ú(· ñèEA±éé§yá¾ûb`ï^†Ëq(ÿóMob``€ÒÀIZ§"œvðþƒ9ñÑGÿÞ÷Øt×]œóÓŸò¿Þópœ¼CzüñpÁj[³^íîü‰„èÜv£££T€ÉÉI¢(Ê„Ý$I¸ÊuyÕ«^ÅÔ³Ï.ûoo¾l”¶À`0ÌÌlmi †#Ÿ5Õ'¨0}ö°šîïÞ¤c&R¯+M•ŽÙGY8+‰tzY Š{ýF£‘'êõ:###iÂ0ÌDGÈ­"}ßÏúÕžçe¦ã8¸®».Ã4ŽLÖT[`0V…õÖ$¨ù%5·ÔO_Œ¢Þâcµª„Ço}ëq¶nÝ ÀÃßÊÙgÿ0ÜÅàà½|å+ÊÕé©Ï}œwó ?¾€÷~íkX/ý®á—9êù“xç.ÿéù/p%1/yÓV¾ð—ªA­FɆáaÔ|“ÌQZÖYm¬c[Ñ{g8rXÂãöíÛÙ¾}û´ýú¤¨Ffÿþý\qÅ ²oß>¹âŠ+VûfÄ÷ý˦¹ÄmX d¢¿û½;¸d”ëX Ç^ضeY™Õ#0/W«aš«È‘Þ£££€ŠïºÒÿýªÕj‡ovÏó²"†aH¹\ÎH]-ËbhhÏó2AQ&HÄš[bÃ4›M …–eEQG\‰+“!òÿÓEʵJ¬x©øø—?ÌԪϼr™‡þäOø…^à_žzŠ—žx"ȾîõâEÔœO˜¾lTGPÄÈjz<üJ…z£}Á<91Á;Þñ¾tå•|ᤓxá²Ë¨†!Ÿ?÷\Ýuï»çž¬ ‰QK (uT¶­#sQw¿ã$IÂÈÈžç-‰ËmÏóh·Û g‚cEضY¦¯UWJ¥-0 33—¶À´Ñ͚êxˆ‡³›<,’¾­—w«Gšn:æãâ4‚iñ»­"E<ÔÇÈ0}œ¼ç' aMµƒaUX/í@÷¥˜|î§½¦®+åRõ¿þׯó¾÷½™(Š8ë¬+9|ø0O=õÛ¶©Ð9ñ}oâ_8—Ór ObóéoÿÁá$ž<æÛTž‡^4 ·Ã™ÇNPy®ÊþÓCçV@õ*²0Êq:”P¯4„õ…OX‘ûg8²XÂã\Ù³gW]uW^y%ƒƒƒLLL°gÏW»j3år™8Ž×|öÙ„7˲:“µ": ²:SâNÎe•f’$ “$‰p­Ök;$ •J…(Š_ñÿŽëº3º–ÿ¾ïû„a˜­¸ÃF£mÛ™ ("e·Åb½^Ïâ2Šx&§ëº8Ž£Ú@ÛæºÏž_Ù¶M÷ÜïÜy'OþñóÖë®Ë‹õ¡Œ¦û >í4ÔÜX)þøßý;~ògIÂÿïŠ+¸ç²Ëð˜Ùåj‘<°w7rÂ0¤¦Å¿%H&qÌûS‘³ìºjþè¥/…‹/ÎÒéeÏ¥Õ·,«§%éb)‹Ùw²’ñwW‚õÚ †¥Ã´ƒV¨-è×…rûlëØsH³@fSô[ˆ›õË †#Ó/0 «Ýt?u%”>;­ÇxteõØ‹fs’^€‡~˜ÓjñðKîâ±GÎà§?}5ÿ°ÿû¸À}O=ňøŸßý.!§có4OcqÅ1ÇÐxNÿÀøßÿî/8óŒ7òàý044Ôa>æÖŽ)¶ Åœ°"÷Îpä±,ÂãÄÄ`pppÁÁ™ï¹çžiû¹é¦›2 óÏ?Íw deaµZ—õÝZf­‰:bQ†afM5•J%såhX[)í€X³«u6lÛÎ„Ä p‡ ©…!öE)k=Ç!êžG\ö±qß /pÑ/ýRf©è•Ë™hAqZâ%Ôëï` P½ì2| ºñF>š‹qÒ´Ít»šæ¡ÄÂiwopRêBô‹Ÿý,õÔq¡ˆàê8ÎôX¼€eÛ|fµ¿°9R,³˜šëYtÿ<·2Lç .qa*çyiÙ6JPtyŒÅ"ÊóT¯u×Vš~¦âõz=‹_ÙK0œAP¯×gêÖKknYV&(©¬§¶À`0,¦0 °þÛ˲ˆã˜0 {w§c,!aO*•J¶°Ré 4éº.¶mw¤‰¢ˆR©ÔâÀ`8’XïmÁ`X<«ÙØä–Ž¢+ZqâÇž>·¥ëzù"5;65u_øÂ—¸xêàØÎ Ïn¡ŽÃ—mÙBü¤Íä¦àé/1ðÚÇá›*‡û¨2qö~ÞG¶†U‚B­Š³¥³–¥yXížaX ÷îÝ˾}û¸üò˳?óÄÄ×]w;vì`Ïž=LMMqíµ×²wï^n¼ñÆÕ¾Ö¥V«eÅ‘>é»q]—(Šf´2 ‚€$I˜œœ4¢°aÙ¨ÕjA°b–Ž Jà‘Oº,¹ûR%ú‰ #’Á–-pÎ9¸Àuäah*i:Y©U>ã ì´Œ0-WòëG·ûS}»ÈÜ\’΄Ī,•Jxž· û-í†gVt ƒÁ`0V uP(zo6›¡Aô˜ê*¡W¶Ñh0::ÊÐÐP>¡\./j¡žÁ`0 †ÞÈ\œE¾h]ìbº%‚çž{ŽZíXä‘,aÚ~…QþŠsÿý÷°ï¶Ÿð ÞC•Ù¸\ò¤Ï/csê…—~ýO¸ï5¯áÌnäu¯ÿ‚ÏÇ ãÀ'€8ÛÎ,,gtˆeæÈ KÄ‚„Ç©©)öíÛÇž={ؽ{w¶ÿþýÜpà _¯¹æ8°¤VkqÓ7>>nâ&¬"3Y+‰T,èhX6â8¦R©Ðl6åæRÄD™F¨¥û$G;ý¦/eå¥çø¨ÎŽ.Ã;é±2sCïu‹‹s UÓÝêÿ¼¥rZ­V3kó…Älõ}߈ŽƒÁ`0 †g®^xô¸íŽã0>>žÅb·m{š×I#–”¶mwÌSôŠo< ƒÁ°0ô˜Ž³ÍuýË¿"ŽåÿqŠŸþt8Žù»¿{ˆoPäµGÿ#ßüéY<ø×Ô€'qBæ÷,¾ƒÇ( csÖY/"ú:\qÅXÖ×)ã¶;þ€·ìú¼ejI.8š©pÃJ° áñ®»î`×®]ûE\ÔEÇË/¿PÖGºð˜$ µZ P–7Ft\„aˆëº™$qU“a9 ‚€J¥‚ëº ÀtÄ%©=r— 6*~"(°ÊôŽ”‘[6ZÌ]t\NüÅg1 Çq²ÿý|ˆãß÷ÍD‹Á`0 ƒaÍ“$ CCC–µZ ˲zöƒ;&1 ƒÁÐ}±¿M§«U˜Ïà¹ç~ R¯7x×»ÞE’$uÔs܇Ëe/ü5CœÅ™¸|û%ߦôcOËù»ó‚»!ÈLîço_ò¾þÎwòÎw¾߇øQ®faº†•dA£híÎ:66Öa©311±Ú׺ìÔjµ¬£oâ%¬ $ž…ˆžçáyårÙX:–•R©D±X¤\ž¿¼'ŽbÉ£:>ÓÝ•ÎéjD <9HŸÅôëtÍ/þÜkG3)c0 ƒÁ`XëȼC¡PÀu]’$!Žc3a0 Ã*Ð=׿’ÏßÙvoáñÔSâþû_ΜÃ÷¿ÿ}Â0ä]ﺘ25þ¬í°õ¨Çyò‡{§ÞÌ/6mbàÙJW_Íÿø Êcóæá’KNf`à²|;l¡ºæ¸ÌZ{ÃJ± áqçÎìÛ·©©©L|¼ùæ›8ÿüó;Ҋฬ}ßÏ&¼%ÝÚ Z­Eõz}Q®. †¹EA`YÖ‚â»–PîR…eŸ”ŠË!ö-%°.õ?ÓqœÌât>ßøÒ7 ƒÁ`0V“8޳…tŽãô]4[,3ï>³¥]OH¼K˜îÖ`0 †µL¯Y¨ €^RÁ׿~—]öEx`Š¿ý[µïsŸûeŠL‘ðþ—|’øGrçËwaøµ?OdY|û‰'p ùÉ+_Éö¿ÊÛŸ>–óßóž,ߎ)ð®‚ÍZ{ÃJqÔBNqQ ñŵj÷þnAòH#lÛ¦Õj-Hl0,žçQ­VèhXvÂ0¤R©P(âD†ž…Ò÷ÕIO_-Ö†KÔåd©§FÇÁ¶íÌõõ\Yh\HƒÁ`0 ƒa)ˆ¢ˆB¡Àðð0…BB¡ÀÐÐ¥R‰$é½|жí,¼ÃR‹Ž…Bi¯B¡ÐQ©ë\±YÜIýX©Tbhh(ËSîE¿ë7 ƒa¥ Qa‘ñ¹5ÓS8¦ï;þø‡¹çž yôÑ7rÇw¤{mj”9‹×=s7ÖQGqÜ#Àcçà„Nࢋ.«ǼùÛù¡_#øÁHÇ|–t,‹.Ò`X9$<²{÷nöíÛÇ•W^É•W^9ÍÍê¸îºëØ·o»wïžæ–õH!IFFF:â‰ÍUp0 G•J…0 ñì54 ƒa%Ñ1IšÍ&ív›v»M£Ñ ÃUßÇ¡Ùlf¯F£AE”J¥åI’`Û6A׃·V«AÇõ7›Mâ8^pyƒÁ`0,5a×ç8Ý×o®Íq:]­†aHÇœwÞŸðÈ#gpèÐi>|€s‡ˆ÷ásÔS§ð§?ÝCòì|ÿèóÃ'žà³Ï?Ïå_ýjÞ ^³åœs¦¦•ÙnÍqU˜OWm¶´þ<ó[c,Hxسg×_=[·neëÖ­ìÞ½›={ödÇ÷îÝËþýû§í?Ò¨Õj™kEc)c0l<‚ C¢(¢ÑhÌ)¦Šr© ªSRG‰ŽuŽlA°«ë}Éó·¬9 a2::ŠeYFx4Öa8óñ(š=Mwú^Û:zS¢Ï‘jÎ?Œ€i0 †EQ©T°,‹f³Ù1· ã8¦R©L;/IÂ0œQ”Œãxšu¡NE}ûÍ–ee•®ëâyÅbqšh8Wd±¦çyÓòð}?s+¸®K¹\^pyƒÁ`0,úS3fzJ%IçYyîÞ~{SOýT–‹eYÜ Êžž>BÅãSZÁO÷ë÷ éÊK+Åb2Ióªhùév¤å¢ÄË‘¥¹‹ÆÆÆãÀûwìØ±45\ƒÄqÌèè(µZ$I¨V«4Õ®–Á`X$žãL "rßï TÜÆÕ’¸l¦?£d¢hö«¢(‹k0V]PÓ‰c¹Ó8î-öù~žFßÃùY<êó›qÜ™¿ÐOHÔ÷÷³xÔóÑCÏêsÃzýÞH>ºg’äåv¯œ5 ÃúDú¬žçõM#ã Ýr±V«enI«Õ*µZ-FGGI’„ññqÚí6år™R©”åáû>Fƒv»M«Õ" ÃŽó!Ÿ•W¥RÁ÷ýYCKô",ËÂó¼lá¦~=b9<<œ…²ÌBoƒÁ`0¬k&''y÷»Ÿ!¢("Š"íùçñÏxì±é¢žˆ—¾ôc\tÑE<¶u+ö¶Ižþç8÷Ü·tˆŽ®»JîTgƒv›ŠÀ%¢\7>âšg‘v®£D±š¶¿–æ1׏b]ؽÖJD¸‘4¯(}ñ¯–£O3ŠK»ˆ\ø Q_M+o%.út "Rƨ¸[r¾ƒš8®¦ÇÅúÑG¹Ì¡RDÂaíž×ºŽ§Û…4MHÓÔ´º´4 xÑW^4ÇÚŸ Àu]®¾új®¾új®¼òJ®»îºEWh-#ð8ŽI’„J¥b¬ † Œ¸F¨V«=E+yNPÏ ‰ãhœy® Î{_Q™6Ü`X&zx„ë£ĸ" ad$ß/"ïƒÖI„6ËʸnqRÃÙÝžv‹Ÿ",v¯[Ϻ†y}â¸s[¯CwzÝʲ»=}§kžÞi ƒÁ°LH㯿ºé>Þm¹'yi »½¬…^†år9ëó–Ëå¨2©Ùh4²sËå2žçes"‚ê;»®;ÍâPbOÊ«V«aYÖŒuí‡ïûxž—+u/%Õj5s5…BFGGç´ Ð`0 †•Dæý`æ0BÏ=÷ccÏ$ F‹ç$}® 'ó Þà—8xp(óØc¿Í¾ÛogËe—ñîw?‚½ãxŽ?þpæbUgEz·'bº;Qq*ÂYwzkäB¡¸%K;é‰Ðf‘[àébä‚_%Ðù(-ÔÒTÒ×¹(¦Ÿ t „~º-‚çpšfTÛ¶Ò—^N)ý´ºˆu¡•ž DÅ&Ê%ÑêÖLÓIÔ.¹Ö%:z¨Id%N—›ÖYÊzú¹‘æ_Nó‘<¼t3M;´Óô4}L¦¯Îú³³ý³9f¡'îÝ»—ǜݻw³sçNöïßÏþýû>¾ ÁÓ`0 †å@7€óèot÷ÄOpÿý§pc<üðÓüæÄ1ðÄ)¿Êgž~?›6MrÛÓ;ù¹ÎÀ9á ž}úiÞñŽwpÝg?Ë7¿y>»vJr8ÍÌq:ú Zwbñˆà'ïÔ¤f-}×]‰z黸V³È-]r±ÏNó‘:Š€–[ʹҥî¯iõQÍKßË(Ao4}‘æ'nF¥|½urÕ¸¢ÕÓF‰r"ަù‡(Žô³ˆŒÕô³X-µ{!פ۩8izK+×#Ÿ-’[? RŸ’¶¿Îô‰æñ´þrOÜô%´Ò㺠>KËs¼³ž›ÿeºÈ=_$|%wÞy2÷Ý÷×÷áò¿~üqÞ°u?Çu2óø;yùÿ»Ÿ·}lú ÿùàa®ø·ÿ–ýHYžEQºž©KÝ\ÐcQÄ)%´ÕÓwqó ¹@¤ç‰’ •Åôx“ÜrOŸð±Q„K鲈ðVKËi ,EÄ+’ yò™ô]Ü’’Öw$Ý/“²µ4?±<ŒÈ:‡Ü°¤½·ÓüD”«vÝó2¹x(x]Ç--nÊÚ1‹Nq°ŸÕŠE.|öCîµXQº}ŽÏîü‹;ÙüÃʼn rµ:11ÀöíÛ;öïܹsQ•YËH§< Câ8ƶíS7 ë‰{†aæªHGÜk[¨g‰ÃÚ±.\‹,çý‘IŒááážÇ}ß§V«™É ƒ¡º U(äîJ‡‡{{—êÜ/¢£eMð,+źOVh:Ît1RŒCDˆëÑÄÂR÷|'ïÅb^¾.nv»WÕ PúY"ŠÐY«)W±’W­–‹‰ÝnUm[ÕMÒZVGR„Ên«M]x”{!ûõcÝõí>®_÷"æ– ƒÁ°ض o½H’ß÷§‰’ÝâaÇ™ˆ©»W•ÐÕjuI݉¨9Ÿ|ÄÍj³Ùìx‰{Øx€Z­–¹ŠÕ1‹ ƒÁ°‘0€ æ·ú­÷¼å–+8á„»9xp€¡¡!ž8í4žza+•WÞÈŸüè?ÿŸïò±'~‡?óû¼ò’K(•J:t(óÖãºtzSfYŒÚALî¢M‹=qmiimrWžqz\D3ܽh-Ý'"ž“ž+érkòv®›–'ÖIzÌMÓWÉ- Åz¡š¾K>¤Ÿ[é1±Fl¦yŒ§ŸEtÔqÒóŠt ˆrÝt#×Þ©·ÃÌbŸ\ãR³D]¦³þì,^ñíW,*ÇxÜhÈŠ¼8Ž3W«ƒaãEQ&<ꮉô8² f-²‘Z.Û¶i4™;ÕnÂ0¤X,ö]Un0l4*eý×½ VƒºEŸo”àåy›¤·mõòý\Ô]¯Š¢ì·íÞ!²|ú>ÏË-]7'õºêbª^/I—$njŠÅ\°+—§Ç7º%£î’UÎc%°Š("b©ý"zFQ§…¨”£ßƒ8VùŠ•§.vŠ *yõ²ÜÔ™-ö¥Á`0V–jµJÇ …·ªaR(H’dšua­VËú¹2N‘1ŠëºnM%M©Têk Ù‹$Iðã5::ŠeYýè^éD¢ˆ8Ž{ºv•<î½÷^\×ÍܪêùV*•iå ™~c\9V«Õ( 3.f˜O;ÐM¿|¡·[hƒáHEþEò«ïg SSSıËO~2ÀñÇÏéÛŸã?œø1lÉá©§H°xú夲Ñhðž÷ fcÔ(¢3VˆÐs±ÂÌX(±QbŽ¢Cq› ÊêÐ&c(nBIß#:ED‹\H,¢,ôí³Xº¨ISý\±"”ø…r^N!­[Të¶#[#‚á|¬þôX‹ýÊÛ@<Òól›Ü¶¨<Œð8GäÁ)à¹ÄB0 Gaf®;³X,¨çq|1Ž·ð"–•ôÌ´mÏó°,kZ¬Ç$I‚`šÅªÁ°ÑÐÆn ?Ït nº%¤üµd€%B˜ïO¼t‘Ìuó…šz9"˜é¢&(á϶;ËëÈ0„ÑÑ\¤+B4ëõÜE«~-"l a˜ wr r]" êqeŸçuŠ|"|–J®Uet µú=1P“)B¬\G©¤^A >‹Ñ¶œrN÷µÉ÷-ÌÅM«Á`0VÇq²XŠÃÃà 000@¡PÀ²,Z­Ö4Ë?Çqbdd„‘‘<Ïë'av¤)—Ëóð¢(¢P(t¼’$¡ÙlvÔ§WºB¡änV{õ½mÛÆq|ß§Ñh`Y…B!»þ¡¡!Â0ÌŽ µè T*MÛŸ$I&8:ŽC©TÊ(”J%|ßÏþ«AŸUh£££T*FFFzºdö}ŸR©Ô«U4T*†‡‡©T*õ Ñ‘‘Õ¾mÃ’u½Ë0Ú÷;Ç\â^ü—NþcÓà—\r ŸúÕ_åÄm/ãÇOÂYg)Wª' äÙc¥ˆÏ–—¼$‹s¬KÓƒ2ž èt*ñ +äŽÊE›¸ióQ¢£îNµLÒ)0ŠàXGMx¶ÉÅBAÎ+’[úIw»2])L7#ãðé‡ÙúØÖEå± qYb&ª †KÇÄqL±XìX(±‰eamá8N‡…j”J¥l’Ã`X/ˆp¶”‹ýuM^\£B.|I—§Ÿ£]¼MwjÛ¹õ¢¸CPO±,•:݃J^RŸ^õ.—ÕùµZ.ÔɶÔYâCFQ§[ÓR &'U¸­ÑÑüx­ÖéîUå(iDØ“ãbý(î^Ed•zÈõÊ>×Uåê1+õø²¯XÌï[·õ¨«ro=^¤¼w—•½Vã ƒaõñQâ”3†y©×ëÙØD_©ç7>>ž‰z^ív{Z~Í®”ÍÙâVÎ1¸yíG«ÕêÈKÆ]‚Yøm؈DQ„eYÓþÿaRK]fÈ8W,žƒ À¶íl¡‚X=W*•LàÕÔj5ŠÅ"¾ïcYVfY¬·=2n¶m› ²³år9 [222BÇ™Y¯× ‚ kÇd¿eY=]F G ½žÔ²þÓßûL¶ï¬³îÇq¬šÏåø‹wËÓwÞÉuÏÔ©ÄJÍ+¿þÊÿMyð²m V ìït ±ÅMªÄ€LP‚¢ŸîŸ°r¬N.8‚err·§úã×îÚîuÁ"6ΖΰæyìMñÈ¡Gx%¯\p‹¯¾úêžû_ùÊéºçž{Vøö,-ò`¢Ètz † J8ŽC±XÌï ê9Þ¢÷âµÊFzî;Ž“ žd5f±XœqòÃ`X‹ˆkÎ…ŒÕeÕe÷Ï^b-ʶÌWŠ TÈËKï!}_‰ÍfneX.«—Ä>ÔÅF‰k(×ã8¹R©‹ì·mU¶XŠW©K­–»@m·óúŠ% ^ ©G­¦ö—Ëêš=/·T!Qê&‚]£¡®[êW©äq+«Õ\ Ô놹u¤m«sGåS,梲¸zµm•ç©4A Ž‰p)VŽ"²Š*V‘ý¼_‰•¦|¿QG½:¿gƒÁ`0ôg>‹ãæ’v½ÍaÌ$¶ Gâµ×˜4IFGG³9‡r¹œ ~bU.—3QOÒ‹Eêõz‡±D±XÄu],˲¬lNò,†‡‡ à :ò,‹Y»2::ŠmÛDQ”-rh4™[ä ˆã˜ÉÉI*• årÛ¶3A³T*Q­Vq]— 2±s©‰¢hIâ×ÎÆ‘$œÆqlÚÙ%¦×ÝÌÒäÏá³Ï>×ÝJ„ÏëÎy€-—]ÆÈÝwóÜ–w0¸å9짦 ƒÓßt œ*J|#J@tQâ¡„2ÞµP–‰Aº —„(A±Bîö4 ɨciU>2~ò†yòä+ŸäÎÇîäùÅç± áqûöíìÞ½{I/fjjŠk¯½–›o¾€;vðá˜;vt¤Û»w/û÷ïgjjŠË/¿œ={ö°}ûö%­K7²:AVô‹GƒayXëí€ ÇÉ:â² h=‰Ž°±„GYÍY(ˆ¢ÇqŒè¸ÆYËmÁjbÛ=\«»óá/Š”`¥‹ý,Ûtk¸J%w*"äâ›m+÷ª"¾É˜;Šòý{pdD‰”®›Ç0”zV«ª~âTêíyê%B¥eå×P,ª}’^ñn` ·\l4r«Cqé*eH~bÍ)¦G«Ç¡«DÉòk‘ëö¼\(,—Õ}+O¹o"ÄÊw82¢ò,saV®[b]ŠÕ¢\³X5Jý]W•Õjå±#Åìèh§¸«»Ç‘R¶“^üâÕþe÷g.mÁFk ††é 8òÚ‚Z­F­VÃuÝla€‰b•899IET*jµŽãàºn6'Q©T:„È~c\]\Òç3Å3P†4›Íž Fßkp'³L¶,‹z½38Z±XĶí,_±š¬T*xž7m°ïûY0ç*ŒU*•,/±ô”Eã@&°Ê=!VÄÒJ¥‚ëºY¬Z×u³s}ßÏ®SÄV±ò. ÔëõLœ¥Ùlâû>år9 ûR«Õ¨×ëÓÜSËw7Ûo%I\×Ík¹-XiÄm©Xê1ãX‰W¾¯Ä¤f3ß–Ÿ¹.8ö2ˆA±×~ýÕ&ŠTY]ó AnmW©äçêÖ‹"pÊL³JEåW.«m±f„\ÔK•&IÔõê]2Ò*•\T,Uå~Öjê|ÈEP?-+·‚kCqé*õMuL¬E0Ó¶U^"K<Ìf3ßïºyYÕªL UgP%Oy—ï^Ü´Ê=“:õºª‹ÜkÝ«|?ú¶mÛ߼ڿòþÌÖl”vÀ`ØÈ˜>AoôxÃFàHj Dtt'%6c’$8Ž“‰T®ëv¸"Ö«j¾è¢ÞB,ßdnt¦²u1SÄI‰;Ùjµ2¡O,¶íøø8@fÙ).\u·Ô²O·xŒã8 %oÏó2R„Z‰w)éE(±WwcÕj5E¸ή/IFFF²º¶Z­,ÖíÐÐPv¯[­qS©T2÷¸"€†aˆmÛÙ¼…ïûÙ5H}<ÏËDcÙ/¿¹ïr_u÷¹–eeB³œ¯1ùg~æg–ð¿t¬ÕvÀ"µèyâF}I’d⣟š&ߺŸxø?Ÿý^ž›šàéú'^tÂ{p/{Žð–!¿WwS*®Tr7ª6JHw«"JÖPº¡¥—î—m³.ß°L,YŒÇ±±18¨;wîœó¹àÀÜtÓMÙ*…óÏ?Ÿ×¾öµŒqùå—póÍ7³k×.víÚÀ 7Ü€ëºÜ|óÍYšå Žãìai¬d †åa­·²êN¨‹ŽëÉÚq=Õu©p]7°Ö>k½-XJ$î_w×" •Õn«AK©¤¬»ÓDQn 8—X}"BU*¹¨[ý5¹¸%–„2W ÍŸîæSòL’ÜâOÜ‘J¬C9_ÄG=c¥’»hA,I”èJ”7¤"ŠX'B[»‹¢"B.8–J¹hØ[Ò²rkCÉW®U„H©äyË=òýN·¨rîÈH.bç—º¥a©”ßoWå]¬(GGÕõ¹nî"µZÍ­eP+×aYñ\¨…ÎØ›º%äZçÒ í€Á`èÏFêÌÝBÅ`8ÒYm¸RHæ+• ¾ïÓh4°,+óÊS(21m>Æb·öÀ²¬LY¨ËMÍæŠŒÍE|ô###ÙýqSDOÛ¶3Y,ÅE®¸Æ¢(s—+–”®ëbÛv&‚‰‹]¹6±tÕ㉖J%¾úÕ¯.è÷°œ¬åvÀ!ƒ@ ëõ8s³Ç1§Rã ØÄØDSñ çcÿÛKiÕ¹ïûgsÎ9çP)ŸDø?%žöÛÈEÁ牴°"JH´Éݰ…¨X£éç"Öõ>°‘\¢V”E SSSø¾Ÿ™/ë ²k×.ŠÅb¶ê ƒƒƒìÞ½{ši´Î˜˜˜è4·oßÎŽ;¸ë®»–µ! ¹Á`X>Ör; ½3ÿëMÈ3öÚ†µÎZn –±¼›iM“.¦uï×¼¶tXþ‰E›y‚_":IìC9W¿ññN¡ ”*†¥’rñ)ñ EäAQÎשé"à¬l!õ|%&d±˜‹Š§“wq‘*"tÆ3q1IT>rïä½ZÍc9êb¤.ØA.šºnÏѲ”¨ßs‰íØnçžÜs¹¯"ÊJ>ºË\±LÕ­e¯mõså^t_kä"%¨ûÜl梵ĵ¼ãŽyÿtW„ÙÚ‚#¥0 ýÙH}ƒÁПõ؈U£L"@Öj5žçeVfb­7_+fÉæâ®³âZs!è‚Ö|ñtz-îËNÏóÉ?I'yt»­ÁOꨇñÒ½2‰p)×.ˆËT©—üŽâ8Æó¼LÔÖ¯¡ûzôÏ"Zʶ~m²ï“Ÿüä‚ËÅZl”‘¡¼ëˆµmEÙýêMŸâÎgÎ'Â!>ù¢ÛÎâ¾ûþ¥É3rð ÖkÎÆ³ z?¥eš[0ò¸‹¹8©‹÷±»Âà rÔBOœššâª«®bß¾}\qÅÜpà ÜxãÜxãÜpà \qÅìÛ·«®ºjš(ÙîºõÀŒqíµ×vXN>þøãÓ,)·nÝšYZöãÙgŸå»ßýî¬éz100­j1Vš€é/Ò}³·Ä¨gQ¨¥½ë¡‡ø…ÇãŸßñŽÕ¾´i,w;ðä“O266ÆÄÄļê&n4¤S,sÜf9‚a½266Æw¿ûÝ5»a¥úccc«vº$DQ.Ðéc÷0ìÖÏË-Ùt±Kò’ýºx%B¥¸ú”´ÝÂf·U ŒãE¬Œã¼^bí(VŽ’oµÚùY,EèƒN¡O¯ƒÌ¹ˆëT™qÔµw {’FE茭¨»bÕc%J>ºÈ+û»…OýžËùº@*u‘{'ùˆµ©Ð}N÷=±UÒêûõsõót!Uÿ~$gÃé§æÝï>Ì?ÿó‰¬Efk Û'8|øp‡Çƒa£"ÿ¯Ã‡¯vU¦±デzˆ±±±Yç,V‚B¡ÀÀÀ@_! R©000@EëH …ŽÏ‚ïû d±â …BæîÏ`è…,Ýø@ÜbÖëuÚí6žç1::J"—ˆI"<ΗźJí%:͇¹¸ZKÝËå2F#s7*è1¥<=ŒJ÷uÌ·|.çŠEÊ7¥ýî+ ÏÝeë±1å½ßuˆp)i»E×ù"Ö‘½ê>11Áàà Û¶mëˆM¸X‹s†r]:½—ÊÏVÜÝ*Ê\èÂoœöišHžÛBÁ1ÇÃ릦øü¹¯WÉ"¨} üsQº#@5Aœ¤û\”kÕrWÁò·ègÙh0Ì‘,IŸ`ÁÂãÞ½{™˜˜àÆoäúë¯çòË/gçÎìܹ“Ë/¿œë¯¿žo¼‘‰‰ öîÝ;¯|¯¾újn¾ùf®¸âŠY­%çÂ3Ï<ø뮻æuž¬~©×ëFxÜ`Èã5D¹Ô¬»ÂîN'í~¤SC‰SÔ3bPö•P–ï#Zš‘t)Ý7œnÚça-ýù3HO'ï–v¬¼ùE/âûÏ?Ï wß½Ú·xF–£xê©§æ-<Æqœ­Fj¬_ÑÑÁĤ4äîÑŸyæ™Õ®ÊŒ,gŸ`¥…G™+GÈE#](„Üå&tŠ[®«„4‰/¨ÏÊ9â~U±»>')1 …Zmz™bí'åJÞRG±ÞÓë&›XpFQ.L ÕjglGÝ ©tµÄ ´Ûu¨>' ƒÅ «^WÙ–{-1Å-© š²­ï—±x¿ñ¼Ä^Ô‘:˹r/ºÓéB¢.,÷K/ß©þ½èûõ2u‹ÎVK¹\•ïCâSÖjêwpâ‰rï½KóŒ]N–£-áq¾ãƒáHã®»îZ³Â£ÎrDx”Éʵ@¨?¨4æj™äû>¥R‰z½n<7æŒ,Ýø@\‡ÊÿOb8–Ëåž–u usþ|\».R_Ðæ;ç*÷­_{9"¾-¦þ³/רýÝè®[—âÞ-„0 {Þó‰‰ ¾óït,¼_‹¬¥9CP: öìÙ3§†@ÄŽqõÕWg.[ÃI'Ä›ßüæyÅ„<¶£é¬¯.ú‹NW‘z<ݘ¼}ȃûQ‚_Œj£ráEæú$>¯´Í¹[lW«‡Ÿ¦+£ÄÁ~¸iz/}Ùižr¾Û7ÑÞ嚢t_9ý¬×½šž/Ï9æ¤å„äVõ D27}ÿÍ›)nÞÌo}ÿû«ö}Î…åhN9å”l…Ô\ñ}Çq²•wò½/Ì‘Éêc1ÝÛ‚aã±gÏÆÆÆVÕêo.¬¥>Áb1M3Ý j·8Çn7eŸˆ–½D,}1­ïçÖ2O’\XK%Zꞇô1»”[,ªí Èã Š5 Ç‚”¸I’ \[9ê×dÛªŽz D]­T”8ª—Õ]®ž—nE)עϡȹž—Çf”Ͻ,0Å«ìï5îî7?ÒÏ’SïNv[#v׳_™ýDP±h¤î…B.®ÊuKÙ¯zÕf~÷wÏâÓŸ¾“µN¯¶`ûöí‹ÊsÛ¶móî G"ò\]ëÖ¿Ë5>¸øâ‹×T[ .u7{@æªm6ë#:Š,Íø@âÿé–{žçáû~Ïÿ¤ã8YœÆ… [¿Í—Å ŽK!LõÀæRw±$[h=úY,ÎõÚÅÕél÷§_aÎÛÚR/;év¿2G\×íi‰ dEµO0Ÿ9C1<ìæW~å;ÜzëÅ™èè8–e±ëëÿ…mÿm¿ú«ðkðÀ3§ÀÃ?ᢋ¾L’ü{ž¸í 8ðÁîAMh[¨ ݪ:–¹S5–‘]»v±}ûöE÷ dñ(Êÿ\þÔ’f¦ÕÄÓ5iìº/°Wã7“çÅ {× "Bù(Ál%’ˆ^ ¥+¥iEpÓ»)"Ž‘¾ûi:½œD;7ÔöÍôØMßöÉ-ü*Z¥>ÊRoX{U´í¡ôÚ ä–„íš‚´~>ª]n =Ig§¯:Ð"·TwÈ»fúj¥çJ›_Ú=^ãiúqÔsA,ß«iãiyôXU{¯¦Çšé¶•ÖÏÕÒHHëéiû4þð“ë‘òÖjŒ¿µÚèƒùÍÊwc0–žµÚ,„\÷–‚XŠ›Ä$~  £P.ç.I+%jécÏ0Ì]­†¡Jï8¹»TÈE ëõÜ¢”P%ÆѶsW­"Jú~V‚†9»…D±ôËAérõr7 ùý’ýºH§Ÿ+×§»>º…>ݪnM¨×Áóz‹€ýæ ú…Øé5Ÿ4Ó<É|BõÌ$Ž:ŽÊK·²”¸œ® ÿðoä_þeóÜ [!æÚ¬õvÀ`0,œ#©O0WÄ¥^·uc³NPÑÑp¤²VÛ‚Z­F¡PÈ 8ŽÁ²¬Žÿ«Ä/œ‰ÅÌ=.ô\9o¡ç‹°¶Ñt¡çëu^Œ›ÚŸ™‹+Ò~™ý¬!ç[öBïýb®}µX«í@÷7pË-'gÛ¶msñÑGóÖM›Øýä~xL}ßÍ&üÂIã<¼˜Ûo¿×uù™ïÿL6ùîö+QÄbÝ(V&ëëk3lp$<Êz.+%ÍL éÍ7ßÌUW]5c>²ò¨[À[ôŠç~ôóy½Rˆ[NßJ(1­–¾DPWš#äœjQz\>qÍ©»‰–sE¬,¡½Bú.B¦îÚS?.yDZùºÛÏ⡜/®C!·—:Š`ZB <-`’<^n™\,ïzµQ"[µ8D†lb)(ñxu±OD;±PtÉ­‹\$KÊ^¬]gk›µØH hé̉=ÿ5iƒa®¬Å¶`±„a.v-å(aMw»*éE4Ô·GG•5›œëû¹˜Y,梠œ'–‹qœ»ZuÝ\¤‹¢NKG=Îb½ž×S„;´D¼Ôó“:ŠW«)ËF9_èîbÉ1] „NOß/u/s¥z>õzçþ~åÎF¿ôs±xÔé7_Ü/ý|æ!tÁµWÞ–Õié)V©^xÏünÈ 1[[°ÞÚƒÁ0ÖRŸ RQÏ]ýE½·ååû¹kôJezš~FJbõ¨ÁŒÌ":‹E#:Ž8ÖR[ ÄqL¥R! ÃÌâ°R©`Û6­VkÚ\b¿¹ÅÙ¬âfc-»Ã\ˬ„k[ùN{¥]Lù‹ #V®&k±èõ¯½óÎcxè¡Sq]—‹^ö2^rLêp2Õªã7â;‡Nಓ.ã½|/›žÞ”MæW‡¡øj-S5Amï†uÆ‚„Gù#ÏÅ籤™ÉeÁå—_ÎÔÔûöíËö‰‹ý¼]»v±ÿþ,ðû¾}ûäŠ+®X–›³P“ÿ…ÐéºS¬÷tk½%Ú‰Ÿˆb '›tUrË;Ù/Vy-òXoyÜY+M«qO¬ÿÚi^“ÚqqÚJó•Ur+@ɳAná'y•É-(Ëi'­[1=¿HÞî‚j›{5ø"¾:]ûäþôCÒ÷zÓz™îÝÒ²Û0 ±mÇq:¬ Ãò±Û‚ùP©tZ&vÏ!ˆ0¨»…\dKBÝr0Ir2r+Ä^ˆÐ&îT¥†ÛI¢ê*nYÅê2Š`dJ%%>J<@/E€Œ¢¼ž"zF‘Ú–ëï·°[,ùº»Xº;T}ÎTÆÆÕjoq¾x^—¥«Á|,ç‹n9«[¤ê±3ßò–¯qúék/¶Û\Ú‚µÚ †¥a-õ Þ¿Ç9½Ø¾};×_=×]w¾ï³uëV&&&ؽ{w‡;×={öpÕUWqå•W288ÈÄÄÄœcGÎé¬/çJÝ]iEû,ÇÄ-èbéÕ6Yä£\a÷‰^Ö~úgý\P 7¦7ºÝwÐî³-Ÿ]òØ‹‹øäÜî®Àls|rßû}ûF|ZzÖb; »Y­¡þ#æYo0,/k±-˜ƒQÆÝx’D‰s2)Öƒz|CÛVîI%Öa¨m±šìÎSÿ\(äù@.‚í¤^ú8Õ÷U½d>Sâ1Š0©[\êù†¡ÊS„PÇéŒ])‹½]©Ê¬ Ûâ TXê1±Ôs­°œÎ5ºãMÊu¯%áµsi Öj;`0–†µÔ'è7·¬·§ýÚVý96—ö×qlÛ&ŠÅb&pÌD«ÕÂq …£££=-® †õÊj·"þëÿ)‰ã†a&<‹Å‹9 =o±Îõz}Qu.—Ë ž7]¬èº¤Î m'%NâBÏ—Øž‹œÓÆËsf=±Úí@/úÝÁ‡ÚÉyx û^÷ŠWðÅûžàÎÿ}'oüàxr€×w uð8ÇÌòÉ'Âõ¯×ÃÄ{2¬K$víÚ5ë|×®]ìܹ3³Ü¾}û43èÁÁAnºé¦Ìmëù矿l ËßQ܉êñ ¥‘²Q‚¬£Z˱øfº¾¥À&¹Øo@º? ¹—ó[§fX ÖZ; +åÿÚ\l†ƒaN¬µ¶`6$Æ¢ŒÝÄ:°Ýš1ŽÕ䣸@…|*!Râ-Šh×+DH*‹ÅJ%?nÛê¼fSå#u©T:'?õ4b)u*§[dJý'3¡3Že/’D¹†mµ:]‚ÚvoW¨+ÁF™‹•¸ž²ÝËúq-3[[°–ÚƒÁ°<¬·>ÁRáyaR,gµ¢*‹ÙÜE½^gdd„Z­Fuµ²Ã2°šm¸S±Ê÷ýÌ YDÇ0 gãØ ×uñõŽõ ³ØyÏÅ´3‹]aÛvf¾YNau)îÝzd­õ zÝÅ{©—s2ST?7Dóõßàgæãç|ŸWójá”çžâå«X äÖ-Nº£{­Ñ:· ½XðjÁ]wÝÅ5×\Ãå—_ÎÎ;³?ûÄÄcccÜ|óÍìØ±cV«H¡WƒÑ‹™Ü¶.Q-™ð(ñA aIúw¦ „Èn«Âõ†X<.½á^жա¿åâL×Ù«ÃZi$®ŠçyT˜îéÀ`0,/k¥-˜ [QÐ-“D‰<ÕjîÎTF‰ý$–~":ê¢e³Ù[pô<•ë*+Çjuz ÁBAå-ù‰x¨Ç^ÍN‰×(±»Ç£òY\²ÊÜÊlãV±‚Ôc8V=^¦üþdÿza.mÁZh Ãò±žúK…çyŒŒŒd‚Äl‚mÛT«UJ¥Ò’¸!4Ö«ÑÄqL’$Âc­V£X,fî*kµ¶m/øÿ¶R!žÖ®ë.ÊbÓ²¬E p¶m/ÊâPŸ)M¿‹u³ºXW«ëõù°Vû"‚+¯>gÀ࿆gàÛ?ØÆÿ7ù ƒ÷2 rõK~ÄŽÚKøÜûsó‹&)ò •ÉB'° †5Ê‚…ÇÁÁA>ùÉOâû>û÷ïçæ›ožv|÷îÝ‹Åu¹Úp±Â£®”èXef÷žës­IÎRw“D ] ìe¨ŸáÈGoLlGƒÁ0Ý–dòî8J  A'»]¥vÓl*ëDPâa碢.v%Ö¢nåªn­–ŚѲ:…À0Ì]©ê™Rf÷µÊËus—±íöôë‘øV†ÕE! ƒÁ°¶7xµZm΢£P, ÃÑÑQÆÇdzÉé$I{¬fZ¯“ÏÃJ ÿÄÚ±œvnE<šïÿTX¯–gKã8󎉹”4ß˲h÷øÌÏó5ç¼X‹ö*v/'y|eÏñ›%vòØQ%z΂[àùŸyBx"þ6þÊëxé G³òL\Œu£áˆbÁÂ#(qqÏž=ìÙ³'3aÖûjÃ(вŽÄ|Qñc”ðXA ŽGú|›•^ûR=º–²u–8?ÃÆÁqRˆÆÖ`0ôED@q±*ïQ¤?‰Í(8N§kVÈ]œ‚ð3æaçÖb JÌ‹E‰»Øh(2”%d­¦„LÏË]»JùïP7Å媑½¬äô8–s·ooƒÁ`0ÌÏó¨Õj ëõ:ÃÃÔJ% æ8  Zc1“çÃ‘Žˆ ò.±WEÐg¡¾mÛFZ ®ë.ÊÕêrßw×uû¶¯–e-ªüÅ Ö Ê 3E›žù% ÈÓmðþó6¢1HWºÀàmƒð \½åj8Þ~â3œñ"í7bÖŽ0%<ê¬w¡Q§’šÌ÷!P!Û˜ „8ØX–RK%ð-嚯#]ô5,bñ0ݽºÁ`0t#îGA‰~2÷ ‚Ÿ¼‚ ãX}ö¼ü³Œ!ëõÜb”8¨ÏJÜGPiD|”Ï•JnÉX©ä–’ºëU±Žìž'Ñ»?">J™’Va³j ƒÁ°dtLJ«V«Ó¬ZºÓô‹)gY“““³¦3 3EÅb‘(вXŽº•ž¸¼4–ëÃbc !ê±OÜ2oêã<¿©Â“GK¥r ¾ÿ;¼ÔºƒC[_ÏÔ±S Þ;—ÀoìØÌã/fµ/Ç`X6ŽZîöîÝË+_ùÊÕ¾ÎyQ«Õ¨×ësz€ù(‘Ñj@h¤ÇÖ¿ Õù²Të…lŒ•¢auI’„o{F¼6 ³#±E„ÓÝÊ~]D Ã<î¡ó½…ò¹Ÿ'¹ÿ01;8óèCDQÄÇù8íñ6µZMM6šŸ±áÆ]Äq<§‡~Œ²p¬“[çu,ÜÓ¸Áx¸7¬&I’@±ÈwN9…ÖjWÆ`0¬I KQÄD‰…¨ Q¤DGJ¥ÓŠQÞÅòQ\¯êŸ-Kå#¢`)]ñ¤[TvçW(ä±$u®b1ÙÞõ1cxƒÁ`0 ÃFG¯€=Ï3.U † NLïùþ£8;±y û¹àäwpÍýÇÀ“‡ ~-1/æTó:ÇÁu],Ï2߆ Á²»Z]oè‹~À0JlôP±_{³ñÚ‘¥º^ ãjÕ°zD©™Q³øÈ`0ôF„º0T"ŸŒ¶­Ä¾(ÊÅG==tÆv,•;Se[Η¬C²{mT·è(õÐݨꖙÝîU…fS•m0 ƒac‘$ a†aæj%ˆã8+7I̲mÃÚ#Žãl~°^¯ÑÑ`0£tî¹Â—Eãü*Oó vñ…ˆC„ÿÐ/=eS|5öŠÍ¨Ç›¬×sQÑqrKIƒÁ`0 k‡B¡ÀÀÀÀ´W¡Pèæ ……BaNy&IÂÐЄa8íX©Tbhh(Ësxx¸gy½ê%u›-ÍÀÀ@G¹Qu”U(¢T*Ò°¦ˆãظó4 ÓÐ…Gyn½|ê~.ádµ³=…E‚Ó~€{žxŽ÷¿ü!êõ:FcÑî™ †õ‚qµÚÅL‹Zúò€ÙB?Û¨˜‡enÏtÅ GpôÑGo˜ÿ¯Á`˜?b…( ë*±Ob3Š[TPb£¤QRæþt±Ð¶s7¬º˜hYJ,K•)ÇŪ²^ÏÓ¸noqÔŒq ƒÁ`X»8ŽCUsA â`©T¢ÑhÌ;¿ ²ÅÕAtXlÕj5‚  ÙlfûÃ0œVžeYÓê%H˜š™ÒèˆèhÛvG¹AP©T( 4›Móΰ&Ãry¶Ù?ƒÁ°‘èö ¥ƒñ㦎bˉ[à)ðÚu"*Û¿pËø±üè„S8£rq3>>¾Ú—a0¬ ÇÆÆ¸úê«W»îËB’$=]­ú(ѱÌ좣ÎFé.[l‘ÕpäÓj·ùÙ‡^Ö@gah¬Ž †õŒeå1Eø+—•°gYùÿ[ÄFq›ªÿïÅú°VSÇÊåÜuªÄb¬ÕrkE7‹ÅN×®½0£Á`0 ë˲¦¹sŒ¢ˆZ­¶ üÂ0Äó†D(l4:…Âb1ÏGÊ uŽ\³|ÇbÝ&ßq¥¢î¿Tå²:7ŽU^•Šz—{6:ªò—{ë8ê“Då#¿59.b$¨zŽæ®<N;m+÷Þ{ÖjÿåÖòÝÊ÷+ß¿†ùïÁqòßr½®¾ûjU}¯®«~g–¥¾ù_5›ê<ù¿ëÿ}Pß§¸v5 ƒÁ°rP¡T–’&Ó½%IÒ‹1 C|ߟՅi/‚ À²,<Ïò,lÛÎ, A ŒµZáááÌâÐuÝi–‹"P†=V$Jº™ÒˆVqGçuwлò«Õj„ah,Í «J†Fx4 =)Ñ3j[ž}·ó~.`ŒÏž¤ü^Lp­M4 Û·?ÇI'ý;àŒ+qÆbAÂãã?ÎØØ?þxÇþW¾ò•ìÞ½›={ö¬öu-é$K#£0_G¦{b0¬O¾øÜsœòï`]pÁ¬iÃ0!DŒÏ¢j5æ'wÉ("V¥’Ç„«ÕrË(ËÊ-Ö$­—|ä\ÇQå‰ –$ùy^.Љ¥]µš‹q¬Ä+BGG•°!B£ìƒÜªOH9§ZUe4›ê½TR÷DÎA¶RÉïWæ"éèh.PŠˆ)«穗ˆŒb…)eI\, •ŒåžËõJE$*•rQG„A¹.?¡SPŒcU¶nY.«2m[¥‹ã\(’ü$.ŸmwŠžúœ’Ü{%@ŸÃ‰ã<”#r’¨úüõ_?Ã#\í¿Üº¢{žÌ÷;]§V«ês©”/01Ô~ù}‰x ùoG~S‚nIëºy›c0 ƒaeY)ï>QǶíMTú¾Ÿ‰Ž Õj˲¨V«¸®KA¹sõgsoî¦Æ¹TÓIŸâÛ ù>¼÷Ûßâ¾ûŽáçÓ®6‹²x<Ñ;º” ÑÅD0ë †õÅÄÉ'ó²ÉÉ9¥•½"î$In 'qÛÄJ¯RQ¸ÒWiEìQÁórѬ^ï´@µ-"›ˆ•вø‹9ëÄbQ,EÔëÁb†‡U¾ããJ iµrq³ÕRû¤^"®9Žú¬ f²íy¹0"–…"–‰(âŠXvên#å^tç%a^¤lI+bj³™ß£b±ÓRLê-biµ:Ý5¥ni*s!­V.äê}Ã^ž§D@ôôúü‰~ÏfëovŸ•›^¦ä#¶Âé§æþûŸ{¦†L8”ßh÷ïC~² ê÷¢‡e’s õ¿•}ò?Ñ…GðA½‹®¡ ¦ãe0 †uˆt:•J…ÑÑQÆÇÇç,̉ë7Û¶©¤’$]éÅ´S*VŽ DÏ0 3‹ÃñññL$ìU¯¹Ô]G2û‰ñlñ †"Žã­sœ/j®±Ž²¢^ú ÃJpÿ·á¼óT G››.¾ ×ràK¨A{`_\„)8ñ¾ ¸è¢Ã8Žc¬ù ŠÅxýt†ì{<Šra@b쉸Q×â–Q,âD@Ô]‰Š&®2'Åe¨ˆjÕªE€˜põº,ŠE%–•Ëꘌ“ŠÅ\tÑmr2ÏO\µêŠXd‰Õ¤¾o¶ñ—\ÝB^µšç/y˶ ÷Áæ2¯"f½únÝ ®ÅÕe/ŠEuºç@Œ C/DÔÖ]ûö†åw(ÿ/qó+b¤ì×Ý)ë⻈îïóˆGÝ:›O»Õa“´Aí~Ä]eéû»·c`ðÓ¼¥ÌD+'ÖŽƒr™!éjév¢¯¤¯™Â|Ìå: ƒÁpÄ#nVçJܬŠ%bEÄqŒeY„aHÇ™ )8ŽC¹\¦Õj‘$É’Ç¢á1˜!¹XEš‰YÃj³W«10€ê º‘Iº_ºw£é«²  Ãj!C¼3Ïü1wß}Ï7ÌÇØÎ{ï{/|½HóÂ'óø+.àÀcÝÇ“OÞ¹,‹ †µŒ±xÔÐWÞù¨•G 5,0sÕÃú#vÿfÛ¶¾iÄEg½ž»N-•”p ‡ źI¬âDp´¬N±«ÑȹV«Ór°ÒgqœN—›B}+'Äõézf–Å×™Kƒa©ñ_ȼ¸ ‹gÚÅRX{$"¾´çT»­m×4ºµaÞ±}T@ P#6¹¶ PMó( r!o¦yÇ ÍG–ŒÇiþaš—×#}’æYH·«éyQZÿ =ÏÒÊ÷Ò4¥t¿^_EK¦×#×å#iÝ":g•äÞH™£t Œnúª¤ï¹¤çÇi=¤ýînÇå~xé9ùŒ—§ÕÕÏ÷xhçCKó;0 Ã’#–Šóq·*nVë]‚J¥B­Vã}ï{µZ Çq¦M„.Wü)Û¶q]ß÷3‹ËîëìwÌ`X æâQïöJ÷¬F¦7d]Æ!ÉÕ- Óc>ª;j0Ö[¶<À¹O<ÅÜÂO“=$oü …[ ­[ï{ð¡Ã/æá‡Ÿ[í* +Ž5’$Q×Qs4Eäµ^æ CNE\¸}{çþ(·ö³m%2ˆ…“eåî!$!wO yºe”e‘ù[u´AÿœÅ@1¥¥³AÐhpÅo¬vujµæA`«/Í—v‡ÐpaÊ‚ÈVeŒ’/!o’»EA³ÎtQ˜ïŠ1ÝÚ°û\·ë´^®¶-Á€»Ï—í$ „'PµsÚî‘wüUÇY¹µå¸–¶Õç»N…Ó;/¹“ìœç 0 ÃrE…®þ©ã84›ÍKÄ^éÚívæfµ—K7Û¶qß÷i6›ŒŽŽNËǶmƼ,Å¥k¯:4›M\×Í®¥R©0,ÁæS\×¥Õj-›Å¥Á0WÄ(T7«„ꊉc‹ yYÖˆÉ9éÊuÏ'ÊçHÛ6M †õ‰ ÜñȱüÝÁ‹(NíÍö';?AM$ ¥Ô­‘çy vÝl0¬g%<^}õÕÓöíÛ·}ûöMÛÏ=÷̘×ÔÔ{÷îå‹_ü"SSSlß¾={öpùå—w¤Û»w/û÷ïgjjŠË/¿œ={ö°½Ë:i!ŒŒŒ$ gÿÙŸá°xW‹³˜46"«ÝÜ>0ÀÏ<3mæq}_½‹{UH].þÁç rG‡Èçy\õ›ðwŸÊÅ;ݪîcµ{Er½ž‹p•Êt“¨z=÷íªRÆÇsk½î¼Ep³íÜôªÙìô Y(¨òåxwpÇB!p§‚DH”í.AÈ-òDPëîˆÕë¹™©ãL?îºJùíC³ ΋öQÛ6Ñ?NÑüÆàôó[­™}YÎæÇµ;M/ÿ¶³­Ú–kœÉß¿@–‚n Ù QÇtÆÆf¿¶UbµÛ‚~H[ OÑÆ£¯CxKúõFý$¢“Á{“Jsº¼_åã< ñV(¿ü³ ƒ{5³á’‹x23á+?ánë·¾Nß»:j´$3'¹;ÑÀ+kð5v¸pe±“[nòá|ÅW—Á±T}dÉö%¸Ä‚Fc¸¬ •rnøÉQøç޵ÀNÔq¯œ‹­gÔà£ÒþýµðÛ?VéÂÏ‚ç€ó§0òb(ÞFÐWÛñ‚]¾ÃUö_Y„G¡f(ÄÓoGpiñàíÜ"ð® \ÃS6Ü|WžÂŠ!l^‡²H´ÜÜ‚ïB¸#õÃù00æ€ÛR¢c õþn àÔFꀫ¬çJÀ6láê2œlÃeŽ:¯†²BôËpQÞšÀ‡møQ_%wÛj×Õ5¼AeK UJúútn/Âß¹j¦ÇI¯ÙIÓ?eÖôZï(çÝN‹B}À'®‘u¤aRöuS­æyõ²R–€ŸºÕ·Îøx.|Ât÷ÇÒÆÊ’î:ˆØ)–óÝ‹$°h(1UÚuAÌö-‹_<ê(¼ûÝ‹ý{, ³µ«Ñ †•e­ö Ž$VKô›Kü<ƒAXɶ Žc,ËÂGu«¨nª8ÖÞ£Œæç.»÷ƒ.NF Ã̬fŸ@¢|ÈÈîÉ?†ç$â¿“œùS Æé1‹£^ãAƒa#Ð^<þøãíW¼âí/~ñ‹ûÿÕ¿úWíßøßÈ>ÿÂ/üBû£ýhöùÁìy^7ýèGÛ·ÞzëŒi€öŸ~ãmÚíöäj߃a™¹êª«V» ÓXîv`¶ënµÛmÚív¹\n·Ûív³Ùn×ëêX±Øn{^»ÝjµÛÒjNNæÇÛããêÕn·ÛÕªvÀ°š¸®úõ¯Çsë­·vü—Ö k¡O sÑÛíFCm»®jšÍvÛ>­Ý.—Õë’?Smƒã´ÛÎçÛm÷¢vÛ>Cµ)¥Ýn;ç¨í¶§ÒÙ¶Ûm»ÝnºßoÓn·ÇíZ»M¹=YMÚm·Ýž|Y»]üÛÿÓnÚí6´ëø@»¼ýŸUû3Þn·?Po·m»Ý>Áj·m§Ýª¶ÛN»Ý¶Úív±Ýn_Vn·/rÛí!·Ý>Ên·ßØTÇêívû«ãíöYN»}¶Ûno*¶Û›­vû¢f»]n·Ûnš³Ýnߨh·?ÔR¢ñvžÿx[í»q²ÝþÝj»ý§Í¼ã4SÓçõÙßýßœl«¹›V»Ý®ÎóÇäÌPîF¢ZÍÄ:­V»=99ïÿÄJ1—¶`¹úÃFd-þ'–»O°VûBÃj±Vÿ+=>(‹ím=Ö¦=s÷v) ­ºÞÃZb#ö f»îf[ Gå?Û¼ð¯Û.Íôõt»yšš7t]•¾^¯·ëfnаŽYŠ>ÁQ«-|LLL°sçNvìØÑ±ÿüóÏgjj €dé„íÛ·³cÇîºë®E•/иøb<:ƒF †•aµÛØt×]®…dQ’xH-À:öI¨T°,-¡nYاаjxžúZ|?—iXû¬v[ÐÍ oRïq /¾8Kÿz6ó‘—8gAôv<^üZuìøs¾C”ÜFñÝüí· Þáë&zÝgßÉ{ž¡ô›Û a Á[>T$¼åür÷/.áÒ_ƒš ¼ß%þÈGðÿòඈ~¶LÐ&Q–‡_­Âp“hW“øOÇá¸Ô:°üWÞׂ4á»uø—qÕº¨åÖ.p•qT§ÈF-Ï–¸p•¿W†÷¹yÇi¦¦¯ŸÿùîåÝ3²‡ÞKÄg¢Èüc7‰”˽]9;ÎtkÍ5ÄlmÁJ¶ƒauXk}ƒÁ°:¬t[pÇÑGsphˆ&ËZ]0–ŽÃÜX }ÝGÍÇzmŽÁá§$'O¼MÍ!êÑ4Œ qÃFgQ1öïßÏÖ­[¹üòËÙ¿?7ß|sÏt7Þxcßð,”·ÕØNݸ{,a¹Lˆú|ÛWáðÏ*¯¢eÛ&´m| øó<ªÒx¨ÁPØeN„ä\¨—Ò5”À(~¡lÈTÃ:#©n–{Öe9ð€¿  /Êmó‘ÊÄÄû÷ïç¶Ûn›ö_Z ÌÖ,¶OpðàAöîÝËöíÛûŽ †Àþýû™˜˜à`n`-±ãƒÛn»½{÷²k×®uÒ`XJÌø <øº×ñÆGÅ=å”e¿6#KÖfΰÿœ!änV]à¿LÏ&6q6ÑÓ¿hæÃNã^Õ°žÙ¿?_ÿú×Ý'X°ÅãÔÔW^y%×]w]¶j`bb‚±±1vìØ‘ùZ~üñÇçòæ›oæÊ+¯dûöí™?äŰiÓ&vìØÁùçŸßóx’$œxÕU$¬Ïy5ƒa®lß¾;wrâ‰'®vUfe©Û€O<‘;wöœTø§§Ÿf[»ÝðYV+I¡^‡ä”ss‹F£f­iDt4LGV nÚ´iµ«2+ËÕ'˜«Ðò£-ðÈéîyNµ [-À…ø1uhâ‚)~òŠçxúh2K»[Gß™mÇÅCr¼úÑ«_›ni*vŒÄ Óý_Þªê£<"HÆ„çæik¨°ˆ8j¿: euhÓÛ P,$,à‡‘Z(Êl]LV lݺ•;wrÆg,>³`©Û‚Í›7³sçξãƒa£pþùç³sçN6oÞ¼ÚU™•åœqÆìܹ“­[·®öå100ycÒ?‡aÈÀÀÀjWÏp„cÆùøà‘7¼‹&'WìzâÅga0, fΰÿœ!äcs€kùKžâBBÎÀý7S„žçáyFe0¬OÎ?ÿü%é,Xx¼öÚk™˜˜à†n˜f1°gÏn¸ánºé&&&&2“çÙ˜˜˜àꫯæšk®áòË/瓟üä’¬¶:î¸ãxÕ«^5Í[ˆ¢ˆ]v™q³jXQ’D™–Äqܱ&NÍìä8@©TÂO}EV*•l;Š"|ß'I¢(¢V«E…B¡g™Ò‰Ø²eËj_~_–«زeKßND Øqg—?I zç‡)¿ùGyª+QK˜êõ5í¢Î°:èÿ[ÈÿÏý‚€$I²÷Z­6- Û/ïÝi滚nçμêU¯â¸ãŽ[í[Ö—åîÌUx|î98||úÁ‚‰cÁ>y àÂ_Ý©Ý{âOxòLåHâþŸSiw}&¶Åi¿¡´¾pÓ&"”PË(½/PÙáC–FßþÑ…ð£ËÔy>¹8YIӸ鶓st ¨ ’›lnTL»188¸.„Çåj Dxì7>06 2Ù¾–…Çåˆð¸­¼Êå²qÓfX1Ìø@Ø6ï?ï¼».#<Ö fÎpˌ£ÎÇž?“Ûgpà§Zø¤+Š …‚±z4¬[vìØ±$}‚¹Z˜˜àæ›ofÏž=\~ùå3VrÏž=\{íµ3¦å‡ùª«®bç΄aØ÷O~àÀi‹08|üñ<úÆ7b¢²­.2™>×ÁUEA@µª|ÆÅqŒeY„aHÇ”WÀ­ZÇØ¶M’$„a8m5‹ïûØ¶ëºø¾OÇT«U*• aÒjµÃJ¥B£Ñ CjµÕj•Z­†ëº8ŽC’$ÄqL- (fYÃÃø®KEÄqœ]·ã8ÄqL¥R¡Z­†!ŽãtXò­UV«H€ƒCC¼á„²}QöàOˆî$¶_•ÍU«L œˆQJ5Ãñ~Y‡1‚üoº ‚ ã?T©T(—ËÙoW~Ó"ºU*êõ:q“$ ¥R‰V«•ýïž}öàAØõù™ç‡8ë¬9pÿi€“äñÚjµ¦Í/  Àœâ¡\qÅ\wÝuŒÍh]pÍ5×pÅWpýõ×÷<.çÞu×]ÅØØØ¬¢æl8í4¶MNâ -òv拸Ž¡ È„]D¡¢V«†!Åb1*• QEQÇþ8Ž)‹=z}¾—"“üÍf³càE£££Œ†!£££´Z­l¿¤·,«C ¨Õj™P(²z Ç¡ÑhdÊV«…eYY,Ë¢\.g†ˆ –eeNZåšF&fÔjµL€ê\°Ú_}OV«ˆ€cŸ|’͇¥;"ªSNôü&‚ Ÿèkó\á¡ ŒbÆTK_.JQŸ\)Mc§ç5ÉU…ª–W ¥>Xù…ߌErÑ2QÛüý#œúÉSg3—奋a¶m†a&¶²àõ<¯Ch+—Ëø¾ïû\4y/zí‹ð~ÖÄqL{² ÀÝ7ÿôÐ?aYV&âË¢…R©”¹¨šœü /{Ù;°íS³ú‰¸ïºn&&ŠÕ0 ý@–ã8T*•ì?çû~æÊcxx˜$I:Úš ¨ÕjmLéùJÛ'ù™©·eQQ¯×õ¿1Ó÷}\×%I’l‘´Ò^Ê÷aÛ6###¸®K‹E¾üå/sÅW,ïc¬fŸ`.œr8gÁ ¼øEðÈ‹žŽãk/;†Wÿ"œö$”`Çñ;8óù3¡yõGxaë \rû%„·‡Ä¥˜mõmU~ÓŸ½‰¯L}€»ß}7“ÿ}’ž÷ANÚ~Gßw4Á}ü»̉œÈ/ïý¢¨Äm·ý)_ùÊyì±ý8ŽÃo¿æ·¹½y;~ÓŸóÒ ^JrtÂïŸñû<ñàüûÿùïù­í¿Åþ€ßÿ…ßç²Ë.ã…­/ðžÈ+'^ÉOø ÿùöÿÌÙûÏæ{ßûï:ç]lÞ¼™£Ï:šsâs †ƒÃÙ|úffÛ lðF½ì·PÊJP_˜Ø‘M5¬B®çÂ(¸‰«~‘ú.Š!ÔÇëÊL.R¿¯¢W„"x¶Ežþ§§9áî †GŸ}”ö#m®8ù ~ö~–Ûwð­CßZðÿf¹Xí>A/¾ùüŸï—Â×O†_9öî»ã¥D¯>;Ž‚K"àøÞkáò»¡qžZ?pÙõuËšÎXÒ m[ßßkåóÛÏ€·§ÛE-½nD-MHw~BñXŽÍ…JY¿ »jÑRšqçZN?P‚¨£í·èlB­ü *]iT“)Í`¨íÒkÕ‰Ó4²ÞBš°~„ÕjÖ„ây¹*Ó‡(½Žµ²ú\¾«È\Ú‚•l–1f²m¨Õ”¨Ø-–JP­ªc…‚:^,ª°¥®«ŒyGG•7x×ÍÙ‹j"ÄóÔ¹º89S}Vsø Ý÷å26 ÃÙ=!Ì%Ír\÷R_så†Þ«ý½.„µØ'XMjµZ&.ŠhÛ6Åb‘r¹œyÿï2>o8õzb±HÇ …ÌÓŽàû~&ŽŽŽR*•(‹´Ûm’$addß÷³sæ›Þ`X(+ÙÜóÜsœòîö% †.ÖJŸÀ™šJF—WžyM§Nç¡{Uµ,«cáÁ°QYð¸sçNöíÛÇÄÄD‡YóöíÛ§™9‹uäL&ÍÒ`\sÍ5=˺ñÆ;òª«®âÊ+¯dpp‰‰ öìÙ³h_Γ]„wðà2ÜÞ•G,wŠÅ"¥R Û¶3K™¥@·Ô­~„(ЍT*4›ÍLø“AXå‰N¥RÉ\ Ñjµ‚€8Ž©×ë™8'Bc?®_áz½Îððp6”ˆ'+PDŒ©Õjxž—‰„žç1<¥¾£]»v)‘0^Pïçw.<œ \ ­²Ùæn`s˜ÆJs1›\T–ï3N_bræ›ÆYt*S¢†8ä¢u•Ü 6$7eKïÉ œ™Ô✜jŸ !¼æï^Ã÷ŽÿÞ‚ÿ7ËÅj÷ zñü‰ðð½é þjð${꥜ö<ìÁ¦¯ÃòépÚ¡|<±úM·-f~y!犸(ˆ ÖõóöÉ«ý4M<ž¤nP?ÍZú¹jRꨟç(ùO³–æ/–œ>¹åçxú9]/AœîËÍùÏ^b]Š+Z'=hyGé¶üUëäM-@)}þVµë+Ò)6ަûÊé¹bÚï~’[”Š(ë’»âÑu Y—Ò¢SpíG¨]ŸŸ¾äoæÒ¬d;0’D Wž7}[\0…¡š³(—ó~Fµš "$:Žúy>®«Òűz•J*Ÿ(ÊJ%]­¦ö…¡*¿XTù7y,šjU¥†V«Ó3qæŸÃPå=×ù”(R¯™,0E|aµ\V× ª,Ç™›§ä8V÷¸_Ú8Vùç"œˆŒ"ü…¡º7ͦJ¹p+ßo­¦Ò‹*O×U/ù^E´”zˆ˜$ù¶e©ï T>²ÝhäåXV^Ï8Vu±mu~ª}ò’:Èv¥¢Ò¤Ú##ª_ *¹ž X»Ö±k©OP\YÄ¿lËøVÆ»AP©T2üºëS cLÚhLÉXW¶õ°&ºGž…¦7ÊJ¶ÇËñ?¼¢×g¢À ³³ú`M‚zÀɼ•MgœÄßõ\Wõ¥'ÞçŒËqƧ½üñö+^ñŠöG?úÑYÓ~ô£m¿â¯h?øàƒ )ª'·ÞzkûÖ[om?þøãsJÿÑ~´}ë­·ö<Öj·Û´Ûí¿ýêW—¬~KI«Õj·Z­iû«Õj»\.gÛÅb±=>>ÞÚår¹]­VÛŽã´[­V{rrrÞåŽ÷ÜgYV{rr²]¯×Û–eµÛívÛuݶeYíz½ÞnµZír¹Ün6›íz½Þv]·íy^»X,fû‹Åb»Ýn·›Íf»Ñh´'''Tǹ޿F£Ñ²{éºn{||¼=>>Þ.—ËËVöZ檫®Zí*,šù¶3]÷ù‡·ñ¼v¹Ün[V»=9Ùn—Ëí¶ü :þ‚ãív»Ùn·ëívÛÒÞËév}a×Óh4Úí¶ú?·Ûí¶çyíÉÉɶmÛíV«Õw]Fš€IDATn6›Ùÿ«Ýn·-Ëj»®›ýçFÛó¼6жm»].—ÛŽã´í´_k·i·›Åfû»~оþ‚ëÛIœ´k¥Z»Ùl¶Çi—Ëå¶ëºí\ù‘öõo¼¾].—ÛÅb1{yž—µ+år¹mYVvÌuÝv¹\ÎŽ·Ó¿S½^Ïþãz{"ÛËú¿›TßGùí¶ë¶ÛÍ¿m·'ßÝn·½vV¿Ž´­ùe¤pë­·Îé9¾ÖYÊ> çñ¶ê#Ðn·ÿÇMíö ‰Ú¾ä¯žl_ò÷ϵªú\‹T»A³ÝþêÒuw–»Ýn;é5Òn·]mÛN¯›¶ú»xmÕ¼Ùé¾bz®§ë¤ÛVúêÞWLß›é6Ú«œs´ó¤Lz”ïtí·´<ô—¤Õ·ÛÚ¾îüÐöËû¸¶¿ÜVM…—^‡þ;‘ë(kå¹]õk§çÛ]éÑò«§õÑ›$¹_-íþHž%üMÌå?±ÖYÊ>Ábh¦_h½Þn;é¯\VÏ"ÙN»Áíb±Ý¶mµíºí¶ç©}ŽÓn7í6äi,KõE\7}®5Õ>ÛVÛò>>®Îq]•¾ÕReNNªü µÏ²TúbQ•cYê¸e©ôå²ÊÓuÕv½ž—gÛù9®«¶A•]¯«|\7¿–ñqõ.×Ðj©}““yýÆÇU¾rŽãäõs«Õ|¿äY­ªW½ž_»eåçÈý–ã岪Ÿœëyê*\sµš_§ÔÁ¶óúÊg)ßóòúB~®ì—}ÒÏ”û×h¨ýRùîä»—ë‘ï:¯MêÒ]Žôe‹Åü¾èß§¤•ÏŽ#y/e˲:Ì·-Xk}! Ýl6§}n6›m`Zÿ¹Z­¶õ)IçyÞ´¼ÇÉŽU«Õiãýî²%/é÷/$½a}°Öþ‹¹Ž…Žh·Û»öí[±º–ÛªŸ×‹V{iû|Ã\1s†Ó)·ÕøÌýöÛmh×ùqÖw•~z¹Ün_tÑcÙ³Ö`XÏ,EŸ`AƒƒƒìÞ½›}ûö±}ûö¾±÷ïßϾ}ûصkW߀¯ a¦X‘ó%.\£_ÅBÏqFF”‰R£Ñ R©P.—³ žçeqÀ$¾W£Ñ T*áºnæ~t®èñ £(ÊâˆÙ¶Åmó>ž­¸ÔÍÝÛ—õËR¶wmÚÄ«}¦î I^M‚;5ƒq"rSqm ÊT%B™Ã,ò§$ñüô¸~¾ïcYAdñüô…år×u©T*Ù±ññq*•J‹°5©–¹û£*æ§eY×8Žp<äeÉË:¬nÿqêá8°“<&¨`YV_µX,fÿq“Ükt/ôإˆ¥¾â$ #ÿ š»ÀmôI»6›ÃYʶ@ˆžŽ¥#’Óç_'?÷oƒè-'â|Ü¢R–#g¶ì–®Ë³äˆõ^™Ü@V<9{(k?›üo1LîÖÔG5uErw§â~U,#k(‹¾˜N7«¥´¼&ù}-‘[Òýârµ–nûäÞ¦ýô]që‘{¹OϳÒ|Å¢SŒÖ£´|q[MóqÈ-.Ϻí6þhd„‘£Ž¢HîRVʼÂëøCü—¾´ãÚÄ’ÑJÓKëøÂ /ð·O?Ϳڲ%kzĽm%M?¬}/1`' %ËÊ®/>ûÜsÔŽ=6»Ãò´ó% sK3±ð ÃÜZNŽ—ËÊÍqÔ1±î‹"õ¹^WÇÄâ0 s HݰÑÈ­ætgÝŽNä1¯7MNªw×Í­“DÕE÷H,V†A êX,ªm)×¶s à P×U,ªcÕª²,T½k5eqgY¹Ë×r9¿/Ž£ê.+Å%?ÛV×'ÝßϯC¬CåžF‘*·TRõ¨VUz±è„üW*êZ%f©¤Êñ}•g£‘7òýØvî¶Õšî5ŽUÝ»¢# à qy[¯ç–§]ŽR€NW³òÉwÑË€L\¨‹¹e«euZ7zžº©s÷(Šàÿð›ôvÔ½~X mÁJÒÝŸ–¾»X8êˆw! "ó fz"§ï8Û²©V«Ó»ÑÑQªÕjæ2TÜ ø¾Ÿ¹lI’„0 3ñöíÌj$I’  {PܦڶͤÌh°2ãLX–uä5ø9èÓ#îð®{ðA¾uðØö«‰"5qS•€lâPüýɤ^wÀ¶9AG¼Î0U9EØ“ÿ ¸¶,‹(Š2—½²ÈÀq …­V+û¿‰(®“tá°Z­â§³uaf±aĽp±XÌÊ×EÎb±˜-p]7«ƒ°–ÿ_þ©ý7µíœºÚµ1¬'â'€!Øñ‰ðš`Ã}ïÀQÇÃs6œu¯šÌ=ç&ØýuÞn_íšÏŽî6T\”ʶô@ô§v<Ö£«m×É›¿Ô‹_æ˜4¯–V¦ã$ï%¬UQmRËu ´:ˆF¢/aÐ'\ô¦W\³ÆqLYëGšëf.fÝ$¡iY„A@âºxiû%å ÿò/³û#áGï|'¿±y3Ä1–mc11ÁÄ“O²}˾þÙÏR,¾ðB.¸ûnÞ55<qÌG‰î¸Çq8(}à8À©ÿôO|öãç+ŸøŸä]wÜÁ¯:ÄïìØ¿ýÛ\ðÒ—òð5×ðæZMï?$ ñ¥—b7\|ñÅ oÝJ½^çÉT©5›÷µ¯ñ›\@ÇLsŸúÔ§¸î­oåw^üb~28˜ÅãìG‚a©W¨zlÀJ%­$.£¸^m4Ôç(Êc:êëE0ì×^ªîµ”Ù-`êZ„^¯îuEò—³í\à\«×ó|Ä嬸7íåšÔó¦ x"êyHùz½’$ÿ,±0õû溹Y.«<ä]¿n]ð”úÍÁBîA?ºëѽ[%÷`¦5²úwЫ~sYê8pÒI?ž=¡aU ð£Çq6ÖN’„R©D½^Ïâ?Ѝ(ãúr¹œ_©T¦Åx46:27pé«^µ¢åJßZâ¦ËÒYä7šÖMÊÂ<èÝÏ+£ÄL‡¼ï.‹Ú$¢GD޿בp2f!Ô`ب„¨ÿ DOºàégQÿç²Åa² OõõnÃu=  ƒƒƒÜxãìÛ·ýû÷366ƾ}û²ãÛ·og÷îÝkZtLPþÛ·~ó›+Zî­y+—þÚ¥éRvU‘¸óè£b_kú!ÿÌßó;¯ø¬ß±xèÔ‡øÒ _âJ®ä¸ãŽãËýe.zïEûµc9êåGñ†±7€ »18žÿøDnnY,3#I’l@"ñ*• aÇq&BX–•Å,ÁDìèñ#—<†ƒ˜¸äÁ› Ä”h/ÕûòXÖK¤Ê%šªgÙmNÑÔöÉĘtH<¸Õ9²n‰sî¾›]÷ßÏ·v½û±tµý‹É—J]‚Ÿ-â~‹Ð(ýÑÑQ ð‚ À²,\×Å÷ýÌry||œááaZ­VöÔã¼H:ºÕaÇø¾Ÿ-Z+èr¹ŒeY‹Å,žªü¯e"CþÛË“t9pO‡(]am^íÚÖñØSðð·„³w@÷{pö½0R†—\ ïz lyî-AtåÒ‰ËM÷¿XZ —tT׳ܛa»W¬ç^¸ä–Šz¹Õ´Liãôœ¤ÒÝî„aˆïûT«Uâ8ÆqÕ§Iû0õz(вÅßûØÇØyüñ—^І<ùä“D[¶0::šµyŽãdñ©Ëå2Épèšk(„!®ëbEAZV¶K©\wÿ˜$ܤYšÈb’óm›7^uõmÛøô1Çð{QĽŸû®eñSËâWÂû;ßÁö<*• ï9î8âŸü÷Ÿþ‰»j5­¥R‰jµŠÓngψv³Éëo¹…?>÷\¦þûgÿÙgóˆãpÔ¯ÿ:O|üãÜô¡áë÷[¯mݺZ?ÇuI’¨UÍ岯â8·œK:±6“ØybÝV.wZ³­³ÇêŒXÖt¡°û{ Īo!åõ[÷4“Ð&e‰õ¨.Úõ*Ã`XKˆ×yÆÈóÈ<IÜÅB¡€çy8ŽCÇ™‡ý¹jb0 $Àñ·Þº¢ k%6üL]ñê!FÿnzND¿Ý!Ÿb,¥Ÿí)K¥S‘Xä}t‹| Ds€“çÒ)ŽJ¾1ùôTH>Í‘/`Ô§öæç—mîøä"Ñ\Ðã½£ÝÇî4óí¶õÊǰ>Ñkþü?Ê”éìçʶx \m#ƒa-°`áQؽ{7»wïfbb‚‰‰ @‰ŽKéZu¹ˆ€Ÿ}–×¾èEË[ˆøñ²à™«žáÒ‡.…C¨Þ@ú„Þ¹i'ŸyÃg`.~àbÛþ?9ø.~ñÅühóà œùã3ùé«Ê«¿üjˆà²ËÔù¿Oï§âüúé¿Î•?¹’_®ür&ÖëõÌê±Ùlfbãää$ŸùÍϰ³º“—õrþpÿây^Öéšur±ëZ;Ä4¿+­K¾”KO¯?ík]yË’,éµ”µ{(ùÒòÄ*­FgIò’‡ƒô¨<:#z‹ Ù- ÖÈ{bªQéªCwdðzzýIZŽø¢«“÷àìô|Õ«”üExmiuÓ|rqV„IÝ:O“•¼>^´¾Ý(-%1pæwpßÙgãýöÙ¸IêºëqrÿÅôå1XÊj'±6´m»câÈ„Æ (—ËÙ¢ëõzÇÁ|V(»®›M>4 ,ËÊΗÿö7ùp𠹫]Ãz#„y¿Ï5ØìÂI0xù üèxç:]ô!n—»ÿóbí<×A’L€êùÈ"io½µ ÃÛ¶©ÕjÙ qÛ,uð}Ÿ ¨×ë8Ž“y`±1 ÃL«ÕjX–•-š÷£|ð¢‹ø¹o|ƒ?¸ôR¼(âÃtûíÔëõÌÄu]…B!³ú®V«JTL’¬$“½ŽãP,¢Ñh0::J£ÑÈÉÇ·nå¦}ˆ‹§¦8tà 4þË¡:0@¼;$“>ÒÕH¶m[íŸäº" •¸èº¹[%±r”yÊF#w ¹•1Ë`0,ÇqÊž‹¡V«e!€,$C©T¢ÕjQ, ‚€‘‘‘Lˆ„ÎEăAMå:thEËœ‹˜% öºRÒòÏo"–öÒëIݹ“›–¥‹p2WJß=ÔTIœ–!SljªKÒɈBDÐ ù4UDºA¦í<­^ºU¦¥Õ±™¦—2å¾DäâPE+_òµÈ­@Et•Ez2}æjõò´ý"–Ê5Ký-[ËO®©¢ÕYÒADÏ"y¸ ý~Ê=rõk‘XBeèÖ²JBÎ9ÂfzV ø™ÿs3ð¯(`ÑŒr·øB·€Á°‘Y´ð(¬±Q'^òàƒK—™X~º]&Ò$@nþ¹›¹óÎ;¹Ö¾–Ï}äs|í“_ãO[ÊX² ³{A‘¤ïnƒ*•Ê´ô"°‰KfÁ÷}j5Õ)xÏ¥R‰ÉÉI¬ÔbPD7]øÁuÝ×ó2i*õ—} DO‰ß, 4*• QeBÝøø8?ýÒ—xþ#á#¿õ[ľÏñ¿÷{ :Ôá–Zh6›™d¯ØÔÝ´Z-lÛÎÞ¡³}q7 C¾–.$‰¢ˆÑÑQÆÇÇÝ[ÀÛ´‰ˆtÒeËÞI:A18Hí‡?ä;Œ¯f/iÛUT·ç”SNYüm âbúóÎ\«‹ª=}x•£7 †uL»ÝîûY¶õE1ò|”‹:Ý Åë‰<¿Çéxu—íºî´}úB˜ù¦7Ö @­z(¦ù0Sor¶«¸ï3YÚäâžÛõ®OQ Ò¿ìÕ{î¶( ¬'ËÚq™¾[«¨i¯‚v¬B>)S^R¶> &B¨LeŠmO¾Î_,<ÔT]…Î)»"¹ Úrš‡O‹S·O8î4݈V¾ÔK¬Qe*RêhÓÃ^·é°µë­Oޤס‡­@«KIû>â®wW+S¦²ÎþÿƒBŸ¦¶€3¿óÆz^(eiôau¡Pè?f0ld–Lx\Ĩ Ñó^‰ ;=˜þ„í6P†È‹øÒ|‰?Äî<>Jâ$Üä߯† ²ÕòQe«ÇÇÇ9Å:^OþDœi/ã÷.ý=å¢ËqØmá.€—¦d8ðò]/ÏŸRï6ù“HÆ ®¶On <5å ®ßJ}»×˜C¬…¥ð³Ð½ LŸSœ¤³'c§õ’û:—ŸÕYöõû)éy/Çøk.÷N«çW_ñUÞÍ»—¡"눾ö5>ðÿ#¼ì½À«ÁþG*¾¥’ZhEÐj©Ïž§Ú€ZmŽEQî›u9Ã<ÐŒÁ`8"YŒ…±À0f&H’#ÏÐ1×)É~éôH,ź°^×ùbã!Q–ô)Ý2P/K¦*grVÓÝ:öª“î–V,Cõ2|r‹EóO°ùä_‚Gz§_Цц#àéo}kî'¨§K…NÑMìæåÉÑ%DE~Ä?Ný#âCŒŒŒd+=Ï#I‚ ÈVíO³hJȨ/prSDG©OÇ{w}u¤¯åöØ×½ÝçZDœÝëÚ ’ 0·Ž{ùÿ[,Hç€ü¯£(Ê\ Ù>±ä)—Ë™u“ßѰ´Øç³ÁŸr†ù¢»è9;|˜{~î4.¹ ïR–NÎÜ]âZ Ù$Iæ‚tÚ5EAäñS—¦–e1::šY!J;T*•2—lâµÕjáû~æZ,·«Õjf±í8N+Ѳ,*•J‡EâèèhÖþI{§»GÕq]7³’Эõã½ÄÁ^“Dç¿ýí|flŒ$IøA­ÆEïzת~W–eM³´\Nκ÷^>rÁX(ËÕrêós”|õôO9zhUïËZ' Ïœ¹Xêõ<ž# „ÅZM)”zÂ0T&’A¯Vð}µŠÁ²”iÛùré0TyiB:ÝîÕ}?2Ū( atT•ÑkU„& ƒÁ`èËCO?­ž­†AòæBjÛ‘áôIÓÍR9•ž©®bª ¹ýòž‰¹ÚGtž$ß^×õ¢ûï_äÝ:BÙ¿€OìúÜð»Ó‡aÈè許x4R6ô”l\ôðÃ8##3'GÛâÎR¬u!k\×¥V«evâv«V«e“O}WTÉ’q£¹ÌÊFƒ¡7bñaE$0r74? î¥ÌÛ5§X:Џ7 ÃjµÚáIëÃ2aCó‡«] ÃzB¦ø‡Â§Ù=Ïã.ÜsOgy\‹N°\è~³Q*•ðc€# ›ŠÅb¶ ¢X,ÇqK±Ñhd1g}ßǶm*• afÂ_¡PÈbA7l”z,hÈ]»éîGÇ¡Z­Ns7KÙ6FQD­VSnX?øÁeúÆÖ®ëû>ΕWfû‚  îº$ÀŸOMÁà û Þø¸Ú®×•ðX.+í®U a´–t%:ŠVÿ¢HeT,ªLôE†é"%l»SdáQú z[ *h­¦TPýU­ªsJ¥\dÔËZ-7ÙìÕ¾HÀJÇQÇõ~Kªë\ȸ"IÔÍ“û¢ ¬b:*÷ »(•T¹2\,ªôI¢îŸl'ÉtQUêEê{‘û†y#ÞKˆ•{,÷^|êêÇå|]‰NU–mç±çM¯L_½"ùÉwoYe úïB/ú‹Êý¾;ý\Ó5 î>á„ծšDºúz)ÝLw¦wõx‘ǧtwÛÎyÐ;M±˜?n]·ó‘ªž—Ÿ'®ï»ËDZ<õÇ´þ(–ýúu Rv¿.ƒëjÝòuì†#O|‚§9·þ6N«wþVâ8Îæÿ ƒbà 2´¿ýþ«_챕—Àeú[v†aÖàŒŽŽfîÄÄ5˜Ä —[3"‘‚ k é¼t/Vz}–ôúqÛÎ;HÆ£ÇÊ[æ² /Ì\&;¿Ä‚z‰qÇ1µZ Ïó:b¥õsÛgDGƒaí…"þLrýþ¿0üzxðûʘh¥„Ľ©ŽÄD,—Ë™•£eY‹EŠÅbfi-ÖŠÒ÷°,+‰)îžEH”6«ÙlNsW*ñiu¤ïÒ¯Óû6zlÆÕ@¬Ì7šÛ¬$I²ïµT*u¸·¼òJ>wÎ9¼úK_âŽ7¿™'ŽÙ°C‚¾ÈDUi4!I,ŠÅTò}(j¶K:wB£‘‹ò›Oub÷$D–afš°a*ŽUÝ¿kÏS –ïO?ÖlÂð°:xôxlµšz‰0EJu•Žj©¤ÞëõÎzGÈ"NËôú‡! *_¹g‚¾/òúëõ–û+})ý~4ź´Õ ^êlÛ¹@ ¹µiç÷±»ÎµZÞqïGGUÝãXÝ#!ŽÕ1}ÖRfF»óî.³VËgOåZõr+•§. Êý/:¯»û;ªTrÁ¹{Ü)Çï‚ 0 †Îe[¶¬v挬+Î5:òÒ×Ñ€z|T*jÛóÔ#EódÝ‘<’ËåÞ9¯ZU¾n#Ñj5wC/kƒä%Ý ©¯<–d^MGº;"zJBŸW,+/S®[ºb²VËq¦»ÇW]"PݤZ­ó¾uŸ×lN¿'Òý‹"8û^¸ÿå@ éz.ÛV÷MºÍfÞ•d’¬=ÒEUzå¾Êº§ Èï¥t;DT•.Y/AWïnÈïDïz9<öØÙKñ=ò¸ð"NHAÐÝݪd!AŠÅâÂò7Ž06ì,ƒ<e¦ƒrçázüÂy.Zð}?›ø“€ïâÒL\Í ‰&¼†ãH ½: Ð)ºu‹oòY¾é´H§BÒÈKn›™bÛ®^£¨s&Ñqz ^ nôlÙ~ÇEh”~¯{¡‹‚:z[ ¦ ÝeJc/ =½ãä׬ã809Ù{@$ˆ(šþ5 ¨Ïâ NúCÈusYÔòî{Ýj©YÕ P³¥b¯‹µQÄ}ˆ·`0 “Ù¼€cŸ|rIòë6PŸKz}~L ÈY磋e‚<»Ëªû1Ù-VÙöô97ý£3MELö{¼éÂ^iº÷õ*Wï&ô³)ÑÓèÛrod•\³ÜsýQ®Ÿ×ëžxžzDÿŸ— À®]ð^'ÿ^'ï~èÛ½R7Vп'Ùî^+û¤+¦wdNSò—íJ¥3–Q´LñÈ×9înbŠ×¾î%„]sôår™jµÚ±ˆ×`ØèlXá1ξï>^Û=Ð P"c„r©ºÀØŠaR,³XIúDž¸'Ëꢉp=;&s°Ó׏ŽËIÅ5Ù/®J%_á$b—ç©ùÙ/ŸËå|u’ïç ´}?O'c~q¥«¥ä¡-iÅ“’¾˜XwŸP.w®Ì‘°7¥Rþp•ñ»pòÀl4Ôê!ý\y¨‹‹,ñ̆ê=Šò⎓ßÝ ƒŽëªŽ‡\¯¾²¬ÕÊï‹ä/õ9*ÝJT^2g"ÇõúËâo]hM’\Ä7ýVqµZùª¬fÆÆÞ=ÿõHrø0ç}ï{õº_$œG¸×~ˆà(. ãnŸ#ƒaMΩÀ7¡v'8gCôquLo——2dCÓ„G±2Tå&™8Y,)—Ë”J¥l`†aGŒYÉK„F±ºWª’¯¸†ÖËìź¢ˆÚí·3T­òÎ|údÿN­V£V«áºnfA« °–ÅÏ}ñ‹œqòÉ«]Õ5Cí}÷SýòEDIƒâæ¸úÜ÷“'޵t’{1Ûâ¡!Õ9]ˆ )y/Ô“tðg«c¯ã2hUvå²zŸ)øm/ŸÃÃêúâ¶U¬{Y.„™¾ƒîº‹ëÔÙÚ‘~«0õû6ßk·¬é‘ÝÌ”§ Êú¥q¾{úé‹»—ƒÁ°ŽyhÓ¦E_«å‰B¡sˆ<²eÞ©[ì©Vó9¬ryºëREX³íÞâ×\лý¡ÅIˆ|?½Û ¹nCý½gƒ{öôã½¶û¥éÕݘË÷§ ¶½ûz÷µ_=~ñ? Ü8ÿ›p„ó̃Ï0ÈGØ~Ùöi÷dd„ññqîÌ`ÐØ°Âc<~ÿýÖŽ£(KGY%3϶Â÷};§^Ï,ŸÄârK:óA§Y»XSızÏ:"'@ôXA¾Oª-s##¹h¥Çu3|YÜ,ó âMI¬õDÔqTÚR)·ÊÁQƾõz^o=l‹\š&ŽsÏ@"‰ŸÔòΚ¸mó¥>Ð)¤Šà*¢tÈăœ«¯(šÍã[÷Ãw†1zÏô’¿<ˆôR÷Ф~yêôëPÈýÁV:¤"ŠÊ}ïî˜þÜÏý)¦ñãsÜÁãÙöÅb7¿ù?±Fr‡8Ž3÷ɺظÑÜú 뙄Txüœú„wƒóvuL,å—š™,ƒ Ȭ“$axx˜$I2ï b­(n\*•JÇêJÏó:ú8Ýî^Ö½ 8WÒv¸,‚É£ÑhEQßp£Ñàö[náô·½mµ«ºf¨í?›jµŒ}ÇÅx{ÜÞ}@é¸.Ô’Q•Å =_VÌ-´ ˜œœîl>È@e¡çw»-YI$VçB0H}ëõ…]»üæÚ·”Ÿ¦oj0 }9û¾ûæÔG–EùbÈ^¯ç‹Û-KÍ=‰ƒÈ]ú¢rÝZM ÌÆj<ú ócƒŒ°6ú:€ŸNý<.êØÝTH85ƒÁ³a…ÇH¢[~bå Š©hÛ6I’P*•xë[• p¨VUþ¾Ÿ }wPDì“yGYù$–|Iî ßKß)+·šO¬e$ ;…Aç‚@YÀéžëõ|n·kYQ#(Y=#âZ¯±·>¿Ù}\ÿ¬»FíÕ>÷r1Óñn!p£Ì«ê‹Íùlž{ýIâÔ>Íï<õbþ¸ Þ³s?7HÿŒ"<Š{CƒÁ°>ù/Nþ³_ôþ²™‹KÑŽJ¼Û¶³˜Šâ2µ–𬋰hÛ6Åb‘0 gœq]wš•õ†gbƒ?}ßÏâ€ö"IöíÛÇÛ6ºð˜ qa¬~/•¤ŒuÖ úXúÍW@’ âKð.é %ý,,ºÿvlY…—î“ó‚4Õ°éyÚZù¶ú—NÓ„¨E—Zƒ˜žWLß} låqz¯ó¿ìD4ßsÅ­ÉBò×B-§u?v 9Wwc3_dEªy. COZÛ¶Á¡C3 ". å^¹Ä{U·rèïâs¡N kénìÈ‘…î8õ„‡Þžm×jù¹V«õï  +<ÆI’¯ת l#’~û·Êïÿþ'ùÊWþ†¯~õu|íkù¢^£Š N¯‹{OÈýpË"ä,Pô©JtK6=x´îß[öõ‹³¨‡ZÑß»ç úÍ¡˜qªáH#:óL®¸ûEXÇBé·æ7‡&‚#ÅMó6˜ ?ƒáHÃ:tˆàoÔ>ݹ˜¥\^Ü*ã ¦ Djµ¾ïS.—3wªòî8APMG3ú¹½&DÌ g6h¬ Û¶g|6yžÇ—¿üåÕ®æêS©€mc—ë™>3ã#]ÿ¿ä ­ô Ä:P‚^%–Pƒ³mŽ:/u…O=Mç“ÏpTÓ}NšO˜ž T\úB̶Ayq1ÑÒÊ5fUž…ôx‘\ä”þ¾ì+§ùÚõÄ1ü¦ ¥õ–ú&i]íôžÄé}Õj˲ˆã˜B¡@½^§X,F#‹ÇX*•f‹Œ%ãýôÝ#ŸÙ‘I]}rçYþÎU÷­¬]ÏHz¼J.øÕÉÅGˆÒ ÿ‚iÙ¶–¿n=ZJ˯¦õ®‰£2ÒÏQZŸ\tkUñ ãhמԕ€(¿§Hû^¤|©EAUŽYZž²-âiMû.»›¼ˆ«pCzN‘\ðLËÛñô ƒa#óÂcMÛ'Æ®«æôL7Ü0²ÞÇpdá·ýø§ÀÑ´·µñýŽã¾ïáÑ`èÁ†ï?ê¨|‰‚ âæh¬$±“þÓú·Üò`—\r _ÿúe”ËJX”xâzò¾s8c£o0,2GsB2ÄÈyY ö¹"ÿq†a_7vƒaí#sÜÎÿý úÌ&~zÃ+(üºz–;Nþ<_¨ÑœÄf‹Q¬Ð …BfåØl6±, ×uOƒ¼+ê%B:az°cƒA <Ë"I:ã•gˆH&š^"èI¿>JWÉ-Ú&»Ê³?°!v;ûø"Bvãu½Ï§ë]/[/S„=K{/÷ÈG?ïoDAÕè·öJ·¡ëË6œ ì!Q‡Ó²äsµë<Š ×ÛpY×~q1Û} nW~CüP»1ý¼åêå6QŠ}4í\°ýÿ³÷ïqrTuþ?þ H ™¤"šÄM¬!\ Râ à¥z岂àöÄÝÏ*àGºWV î'Úí ×ëvK¾«¨?µÜ(êJ¦…v©\dDœâšp1L™8„$¦’I áZ¿?ªOuuOÏLÏôÌôeÞÏ<ò˜îªS§Î9UõîSçuÞïN;Ò(£ò¸tUˆ††ÏU¨û¦Ò»¢u  ·¬|£‘¢èA9Lï¸ô.æâ*2Ah=ž˜3 d]lÛ†HÄïŒ7¸0ýç*ÖBÞÿµÏ²~Ù\N=ê“Cæ´êº.£ T`Z Áò*šæ¿€eñ_ÞF™–’Lúé4üÏÿ¼È¾}3qÝÓY·îY2™;ùÊWæñï…F]÷gDAadºŒ L +yóŒ…8£úcâñ8Ùl–X,&^Ž‚Ð"¨÷†ÔOÞ‚u„/:jZ©—ãX—r “Ëå°m›t:®ëhšF*• ¬Æb±Š/*"< ÂZÜ\­‰>äqtð…›(¾ 4œ=0^ô £ëÓsýÑ(5 Æ5´},Ý)Ó„³*´]µær¼vU>aB_®ò¾Ñ¨örtßÔº&Ø4¼åAªåí»vaÝ?ZÄžËùc€jÉA¨ù¹m=4ÀüÏÿäþYœýÀlè Íó,kÔH3‚0™–£¿m›ï±¤Bð’—ûÖNôí÷Í^„a¨µgÒ÷¾Os×ú'yÛ†\ré;àí1ÞþvÿÓÍAW®8‹Ú0†® L?kZq´#8qÎ1W‹BÂøLÛöÝ4 CâBBk÷n^ã8¼2&Æy'Žž¾{-‹áº®„:„C;´ðfà®âO²«}ämÛ.™)íº.º®cF°à¼Z·Qy9Š=„:ŠX‰@÷{Aÿ*ÅõÁwð“Q¤‰£\tËëM­‹jÕ:¡£–Y(‚ BÃrÁÎ|õ«_õ;@<îwDKÆŠLm]Ö/’ŽÃü¥ÚÛ% Ž ŒFC ]tkÖ¬¡³³sȾµkײ~ýz9ûì³Y³f K—.Sþpضmþ—,ÃÎuq'îgÿ‹®7‘8ùˆ`ÍÆ¾>—=ÿûÜûå켕E*¯r4Í+ÅgSâÁùÎåŠâcP×ó¦J]/ŸRáwŠÔȨeùç ÷Œ’I?庑H”  ¶í§±¬¢0™J•¾T'“Ųªíå"j¸®[ºßqü2„ë›H”:d³~¨…´€!±/U;¨¶ŒFK\·´œ•rÃb/øÇ‡ó°¬ââ>ê–÷4³ÙÒ•„u½ôº9Ž£¨ã«9O¥6-?O4Zz]T»ªó¨EBÃõ®æ< ÊdÛvïæÔ»î¦û…‹Øy/˜ï9¹mÛX–…mÛôööJA˜"&Ý0žÂ÷ºq|Sþ9‚êǺÓé4Ý*ÜÐÞÞŽišÄb1²Ù,f(#C°§†HdhßFh:†³5ÛÂï¹ëæé]„ï ÝMq@¡5¨U¸”Ðúueªú‚ 46“m r98JºŽÂx¨±§!TÉTõ l€}û8ü­‡c?Xº?<ÑX„RNx¼öÚkÙ´iSÅ}Êp(ƒ±víZV¯^Í7Þ8¦sØÀ¬ýû9ÉùðüA…r’I:Ò1¢§ÿ;úÒI?ø.z¯S·ϬÜNèñÇ“øþ÷‡Ž<£Ö0uQ¹Xlä—[Ó,Í#‘Ú3ŠF‹ Õ”¡†¢h×Ê•jÓô{g¹ ~²ÒHnøxµ}8Ѱ\ü,s-ËUl<úúwhŸŠ„˦ÎgšC?×-й•ÚGåïº~šòAÇZŸJe)¿fá´a¡UÕ_]ïòú¨tMâU3%vॗ8æWqÈ ¯®*½ 8\HDA&ž©°PXãqKñ»¦ùfSÍíP?•~¾ÊQaUÕÿX,†S8ÐuÝáQ˜",ËïŸD"00P{~”3œ-˜(;NºŸ³A{=þº ÝÈ"=‚Ð@LUŸ@„Æf²ma˜´·ûÃZS¢#”¯¿;lü™ðZÌj˜¬ÒЃßÇÑðÝò\|g _-s)®5¬‡Òªü4ü5•]Šë*Û…ãÝÐö`}+ŠkZP–*+¡ãÝÂqN¨nªìá— hO<Á‚Ý üuZÊp ó_ÐÏXLöQÞ^¸ë®g‰D–Ò××øâC¬f¼Ž6€î)Uê5iÚè!‡ª©g"á§SâW]ÝË®š4£ µa±·’§_5yTS׉¨Ëh¢r5ç©V¼n"¦Ôt§þáIÞôº>ÞX9júl6+!VaŠ˜J[`ïØ³÷ÁëÆ ¬@ Pvu$Tß@Ù‹D"Ø Y³±ÎÈ,Ô¦c4[0Qv ›-–8¸¡˜ê> ÉdÛ‚½{÷þäÃQ‡ÉÂCM:¾xgâ÷ Á¯ÁMõ)²—yʆҸø“º Û…íañN å­ÒGBûm è(lËÒ†…8U>«pN­‡NQüÌ„ò͇>+bI«g6t Õ¥?t}¸-Ô¦ªK¢†Pù²ºd)0£…r¤ËÊ­ÚZµ©*y›ªöˆñ²ÏååPBkX Õ BÞa3Mi?2ºÞa!V‰À™P^aÁ—Ð6•‡Ê;,«6µ éÍÂþp9ÂçV÷¬Q¨wø>©b¢m=©[Ÿ`ã)€Ç¶EÉÀFüîw³hk³ˆF£²¾£ Cì[·€K/½tÈþM›6Ñßß_âB½téRV®\ÉÆÇdA­¨e?ÊóÕ2j{­”•–üPKq¨È?*V|¸,ŽSüC#ä„—óPK›˜fÓ,Ù!´.Se ’I0ÁøJaÙÜœ¦AÔð…F5ßÞ² gAÂô?Û:t‡ž)Û†t¶t©-æOØW& 0 *X¦G׋Ë)ñ0).ùcà”-±cg¡+]ÜC£c͘Q´ŽãG-SQ¶t ›„xÎO£¾îë+Í£½Ýß®–r çþ@j2é—Á¶+Géêêò÷9Ž¿¿àRÒfñxñ<0tFh$â··²M¦YÚé´ß®Ên9Žß¦ê<&þ94­ØîjÙ"eêœ,¤s¡rUhÓtºhoü¸­öïßøQd9&A¨LÓɮ]»X»v-œ¼f :pÔãGñâeæ%þO&š†¦ù¿­ñxéo_2™,ÉSš‘õë׳aönÝZï¢Ô…­[·r饗²äâ‹ÑÎ|s^œÃ¾QŽÉård³Ù t‚ÌbZK/½”={öpÌ1ÇÔ»(SŽêÌ›7/˜-É_w0ë¿-L³ø7–q¶d2‰¦iD£Q"‘½½½SÚWp§é_x\×ŶíqÙY×uq]]׃¨A{xžÿb_){–e¡ë:º®cÛv°¾o½P×µ–¶ŽM›6±víZ¶nÝ:äå|:°sçNýÕ¯°ç] ø“ÇS_®w©aêY»v-›6mbçÎõ.J]¸õÖ[Ù´ikÖ¬aåÊ–_pÝâïˆè“L–Š~±XQ<_2©Â)ùÛòùÒ|".矯|P?™ôºÕ`¹®— ¶íê«þ‡m°O&ýüMÓߟ˕¦«ð°°°WåTB‰jðÊ®[P1Í¢Àþ=UñìU{D£Cg{)áb8”£ë~~±Xé9T+Í$SB°YFú}U‚q¸Ÿ¥„µHp¥ÈO*ÕÞáãUÝÔ5¨±I•_WIа¬ëCÅêP}þóŸgß¾}|Úic;G °k×.~÷»ßñªW­â•—Àø~Ì/´Ã#.œ¬Ã}6äÊžIÛ.ˆ‹éâ½ÀÔ5S×M¹J…QyÆð÷»šD D²ò{E-÷3Òý‘Ï—NŒ(/G,6ú„ˆòè-åy˜¦ïÁ1‰DÑv¨þyø¼åK…ŸE*åoÏåŠç SÉžTJŸßòýêEж‹ö2ŒòX [é]L×ý4á ê:éºßîÊÞ*›Æ0ŠE†£|‰­áÞ ÃÛ‡)ëc=ÆŸÿ{þzðÁLGÔ˜áÙgŸ„jp>r}k6·Ür ·Üâ;)w|ó›.‘H„îîn+Zеk×ÒÓÓSó˜á´<òHÎ?ÿ|:;;ƒàGí<Š}'Þ‰öæ(d2¸.¤ ýøLfèD–ðšMfUhVTœóJ! ¦Ë–-cݺuXÀv‚Sˆ‘1ÒX½Š×Þìú‚fݺuôôôÐÓÓSï¢L9á>Â^ùzvÿñÕCÞÕM³ø^\N2™$‹B— ÅœJ¥ˆF£%¢£ã8d l*d»·Ç!Ux¹Îår˜¦‰mÛär9¢Ñ(VH,N|R! U_Ŷm ÃB¿˜¦‰aD£Q²Ù,étºP?ÇqaM§D7 (£àlÛBÏ«ôVA/–¤)ÇETçPÑ&Âç+‰D‚T*EÒq°::Æ•GXÐÏþ‘ŽS¢éhmQ¾Mµk¹8ªØÑÖY¹r%ëÖ­cíÚµc.w+°páB^¿x1O/?s?h§‚üÔ Ó‘5kÖLÛ÷ƒsÏ=7hƒaQK³¨Áa×õ×ÿoQx^‡‹R°Â(®„Á‹B"Z רB(ªõÕ\ Ý€‡€33°Ü„…}j­¶LXeÂf K‡ÝŽ¿6Zÿ¯aú`šbø@õ_#Õí‡ÜÓߺ°É-†ƒqÍðÅÌò5¿|O øT7ì±áOÀq:œP¡Í4­à©‡ùXùÒöR٦‡  ¥yVò® ±*Úû×Ký>‡…^ÇñEZulyÞñxéb߆Q ‡UéÜåÇwuEMꡤ<² (j„ûw–åßsa2™RQKy})L³´ mÛO£Êèº~Â×Aµ±¦ñ9×eÛ¿ü ?9òH¦Gy$gŸ}6Û¶­àèøë Æ=$º«6 “Hï¹J”‹h•m¿:ÏHT#xŒ–¦’0=yŒ61³ÒÄŽáò.]µu)÷謔‡šTP~.åµ2Ú9ÔqÃ-KÞ^)ÍH‚´b´{¨š¥¨ y_øŸ›¦}5fXNîû[¸‡Å‹gûöÙ¾siî›Á»¼8' ­Æš5k&d̰é„ÇM›6 ™‰8âÌÄ2\ü>¶öb¾a·,¿ß‹m½ã8¤Ói,ËÂu]R©TÉž õ¡V;à €…Åõ׿]_<$˜VžK‚ 4µÚ…}ò‰ùuHçKÇsÔÄâJd³Yt]'‹aÉd’sÏ=—\.ÇÉ'ŸL<'—Ë¡iŽã`š¦¡ë:©T*°1š¦ÑQô1M“\.‡ëºHF1M˲Ð4-8Våå8N ò©4†a”ˆ…Jøt]—x ûuHÚ0Š‚¯¼Ï„3Rð¢ ÿ¤ƒ­ë®f7\iÁ……æÂ믩íõŠ÷F§ —þñª<ŸÉÀ€ LÿúY…<´Bæèð‘nØiú×éd’e}‚^Ï¿f/ºðÀ~Ž…OýfÆûß?4eYär9úúúÄÛQŒ‰²Pp˜ nžâàY5¾ ~ÿ5Mã™gžaÏž=¬[·Žï|ç;ìÞ½;ÉFùÞ÷¾‡ad2™@H*·#ÑÐŒÖj“Ã}Žáú#y¸ÅãqâñxàÅ=c}i —EÓ´à{y£ÃÍò­O¥ö*'¼¤¶ {~*‘v¬6½R{‡Ïþ\)ïrw¤²Vªg8O%P ×ÎátñxÃ0È—‡ñ‘N§y衇˜;wî˜Ú¤˜;Ï“~3Ø{ ?ޱD˲±«\Ì ?×¶mžÎÀ¤DO)¬¡²·¬¢\çï« ˆåKP4cñ:.ouìpÞÅjbAØÃ=<ñ`¤vkt]2Ù¡<ÿ±œ¯RZÓ4Éd2´··—l?ñÄ'àJL=Ù'|O´dÒ†4|,¡Á·R¾hõ¿øÂ•úYËS\«­ÒO]~Ô3×û_€i?ø‚]9áãò£äá¾›#¤ñ*䥸þY¥î‚ƒ/ú)!ÔЋb™^8§F±Ï¥~ÜuÀÉõ®Ž ã`¢ûÊ$ÿqïb@/‰ˆžè)BešFx?Läúõë9çœshkkãÚk¯¥­­sÎ9gLùœþÛǹ’¢Â˜NC¬†ÑuÞÞÞ’Ù´¹\NDGA¨#b€þÄKÜ‹6ì’_j@.8h+B}˜¨>ý,ƒZj$¬å a°”hg=ö7ß|3÷Þ{/³gϦ»»{Tam$¦âe%“ÉÉd&dp¼™0 ƒ;fÎä·ÿôOœ¿dÉ´™H’J¥ˆÅb´··—^áú»®K:æÜsÏmJá&ÈÌã #'q]—\.Wâõ§iZà±EGy§)OAåÁœH$†®?ÊðB»òb 3ï»ñ¬û:kÅ*á®ü]*¼½’÷¯ºåÞÓj{:æºR>j"Bøz©<ÕùUÞjj4-5+‰œåÂo8²*‡úöð ¼*ÏD"Ü?aÏWUưHZîiö‹Ëê|–e‰D¯ýLáØ0 þýßÿ}R¯ýd2Q}’Iøfè#ê ?Ý”ŠŒåa3þ¬(‘k<ÇD¹ø¥0ÊÒ„óÒ*ØšÃ|®”” rÑ i”7§UÈÏdôs”ÏÑ-MXX­´?\ÏòúF+¤×Í èùX.L›ei+µUø|•ÎÊsߎ}xæÍJ-¶`åöítÐKþœñ=‚ 4Ö'á</÷™J¥Ðu=/a(M%<®Y³†K.¹„‹.ºˆ¶¶6úûûY³f mmmUçaýßnþ:Kç5|¦$Äj¹–Ç1M3ð 0 ƒX,F$Áó¼ªÏ)ÂÄ1v€çaÞ³Ïrð¼­$þµr>P:‚ИL„-H¹]»0™K*ñx©ðè8ñx×u‰ÅbÁ­ã8tvvÒÕÕÅÍ7ßÜT“‘&*l`31wî\^¼ývRK–Ô»(SŠZçQÝÃaÑY- i§Ÿ~z½‹:n&˜·S¾¯€mÛ$“É’PºÑh4€lÛ.™ 8ÑÔ:!a<åš a~8¡5¼}¸º‡½ªË·§*¬oT)Ÿ‘¶•ï ¯•Z^æ‘Úª|_y¾ÃyŠWªWyúJí7’]ž·iš˜¦I6›Å0Œ¦úý‰ y?°m6òœ<äÍG](ÍB•\[ÙãrÏãpšà”‘9^\]cåM­òQÂyX”®\ÕâÐaÊ…ûpšðšÐᵡË×mMæð1*­ÙÃÞ¾º®—LO·Ÿú›þ®Žÿîüï²À^À_ø"ÏòlI(e•çh*¥-§®Ö¾O4P¿·ákS¾nv¸Þ*Ê?ãfÐmõË×ó÷7%^íà¿·ª°ûÃM0 ‡Ê{l«sªzüñuÔQc»ÑˆZlÁŠ¿¼€ùáz×B„Z˜>Aˆ¶/³å…yä ¦Y\ž­££ƒ|>/aVaRx|â‰'*nokkãÆo ¶<á„Æe8V>t'ÿݾ—$þû…®õv„âì…ëºtuuÑ7Ú‚ ÔÌdÚ{É\^7¸•×¾öÃ.Ó ^èRÕ,ö.¤1™¶À´Íb¾„Häxz{}áQ;%“É!¡*»ºº°,‹X,F,›”‰ÂIJ|ùrÚÚÚX°`A½‹2å¤R©À»*“ɃºÙlÛ¶I¥RlݺµÞŬŠJ¶ f;`ûv@?´¸Éu]’É$Ùl–D"A"‘(ñ^„fG #ÍxOOê8aÀûúàízÕîNŽã`Y–e•¬Á[Iü ‹|J0Sý %‚•‹àÃy×*ñNM’{džϭÖù {Á–{ +Á2|¬í”ЧÎÞ®GX U¢›šàÎ/Œú= ×; ¾\¼ ·Iø¼a>¼m"‘(©Óÿ}Ãÿå{}Ã:ã)÷©’vPB`ù°(N[zÛ†A6› ŽQ×$\§°·r%¡3|½Ã‚¨®ëä²9®8ì f1«âïQ&“)YX•_µq¹GvØ{<\MÓØ¸qcu7™ [päögÙpp?¶­ ÎdkàGÂ>ú¡ƒ¹Ø»÷Ó8NÑi)ŸÏ7e_J¦’†GCÅl+ª©;o8ë[€ÿ~Q.<¨°:Ùl¶DdT3§K˜.AhdÆk˜¹—¼ÌÀÀ«(P/b«]šƒšl`ZÑãRÁCWÄ㻈aY½½½%é à ‘H ™á/4. ,`ÁŒ0M¯W>Ÿqmȵk×Ö»ˆ53n;{!˜'ø_ÕZ®º®ËÒ BË2šgi3SSŸ ‹/:–9.ضˆ5Jd CÊs´|-fæz*ÇÆc³T¨ø©¶wÕœ¯–0öCΑ^Ÿøî'&¥>µ–u$vž¸“ÿv8|á.Ð/¨úü㹦===Á`}33[pÓagçA&ïªwáA˜j'_G˜yŸÿùùç/n/L*+¡”¦Ç‹š/÷ÊŒ7²mÑ6âqßã±»»4]6›ÅqœŠëºu—'¡ù8| +~†Ÿob9—Ë‘L&e°Q¦ƒƒ¶Û ‰„?)•‚Tj=.ù|¾dÀ°££#X{Kh"¢Q?®þ4Eò°ÀÞç´m;xÆ%ÚÐÊ„=Ç„CÖ't]—H$ø¶4ÒÝÝxü©ðË•w‰C§8 Ôd,¿à?÷v(o…SÈ @½¨¼ |Íð2µF!»l›*‡úG uPŸ• —E ý×Ma2Tß³)µaåm©Îaà_‚l(­Sخʨì‘Ú®‡ê¯Îa„Ϋò¥8h”Û ”¯ª»²¹jõI¡v6|¨ö-ÏW£²½UûÍP{AÞϨ”Û÷áêh34š°:ïÓóæ~¢eÎKs8õuÕž‘ -ƒýòË\ý›«ùÒ!oŠúÁpëé ‚PÊ´@{ö0À`ç 3д⢰ Ã0†¬í(Bkaë°øåCY¸ðY4툒}J\¡õqæÏ†ã¾ë„]N§Óüë¿õ`ˆD"ôööŠ÷X³"ý:a þç>ˆ¦iãÕ ®Œ¶Bÿ»ñÄ•@è)ŠƒØÉÂqá»S Ç ûÃÙj@+”^ ¢+q@E°Ì†Ú,U(ƒ¬B:U¦°ÐªÎ£„¢8Bèx5 î†òˆ†òÎR*,¨<ƒ²ôF(ÏJƒõ#áP€ô±*ß°x¾‡Ô}4œp¡„©p•¥c*•ÙV]{mð9]¸Óš‰ÃQ:~K$“I~ä#¼æ¿ÿ㬳üm ø Td3 é t²A”âó>Þ¢xÿšÅ-õÙ,;W®ì{ºð_=—:þý­ÎËÅBBÛÔþl(¯l¨åu†¢¥(„R8NÕ]Ý«aÁµ\| yVYTÛªç¨\TK†ò§·ÊÒY§#,õn“ðñ•œ$ӔЅª+¡ÄhUo­l{ù5©$º€}}é³<œÈ.{Ø—¹• 8ÐÞNtáB¦#¿Í ¼ãôÙõ.†  ‚ ¸Ì{Îão/,)qZ1A¨Ži'<¾4ó%âü‹Ÿû:•&yÆãqaðÇÞGøîw³ê]Aêˆ~Æ ÐHóC­»®K"‘ö;Žƒã8ôööŠwˆ ´Žçž{ßú–¿ž«`VƒÊJÀKá¬'ñ…+â€wå£<›Ú) ƒJJSÈî¦8H¬îûðÞs…ãR…²D(Ší…Ͻ…´I|±O•S‰Ê«ªƒâ ¼òŽRJ‚¢€ mËÒFCûU•W¦j%hª6KSêÝå¶)qT£(fËÒvÒe)Š}a¡Â ¥w(oUYÂâj{µ-ÊK•M‰/áë8a¡&, B©0”Ð ¥G¹äT8Où¹UùÜaÒTòœ ã|èC¬í³€#¦ó;p}aŒoîØÁþðžþèGqV¯ž…~{vã·¯‹/æ 0TØ«$D$îÚøÏ_†!KLŽˆzÞ2 /|Muç¸øÏIªÊú¨g»êú/¯CãTYï8¾í­wO³çþûéÙ¹³ÞMRŽ=v†1}=>A(Å´}Ï2ÓmãÕË÷¢iÅI¹\N"! BL+áàèûöpøá‡óÌæº_¨ B‹ã8 ëìt>À²e[JvÙ¶ëº".Â4B? , ¶mÛF2™$‹•Ì`loo ‹‘Édê]\a<ض¯,‹×£P†ãÀW¿º€ãïÚ@{èþPÿqŠ^@Pê˜ÂlWGe ûz}<ÊP Ø«¿:C ßQ£(Pª·•Lá?¡|Â"€IQÐP½›¥B7•§£VV†¥Tò´IP9Œbùq„ŽUÞBÊ3K¡¼‚*åUî-5\èÂJçV^\J<®”G¸nn軎Ë=©”W—aUn¡ Ãí” ¥…¢geù›§Ê;Ü&ª,ªªÌ*Œ¦!âq¸.Eo×p9U½¾{Çpî¹U´fk1kÿ~ìv ó[oçÅ;nG{ÍkXqúé|¿ c”zÄBñ™TŸËïß±bàO:«xhà‹¡­‚F©=›.õ×Z¤Í·?¼•ÎÎ%õ.†  ‚ ìNä o¸gŸ=º¸OB­ BUL+áÑq]–>|+<“H2™Ò1¨l6‹mÛÄbc™g(B3aïÚºÎLîäo,z;:Ž#A˜F¡³ î%®k‘H$J¼`]' ÁÞÄd³¾ºœHøë= B|~€ç??‡-§®$OÑ“)ÂRy‰…E‡J› Z f•Û¨2Õ³HÃCÄ«pºjÃmVšž5R¨ÁáŽ3«LW©ìÃ}í܉ û† %ËÿVb´4ÑQ¾Vÿp9Ëïµp×JÂu¥2…Ïc?þÛßFkÆ–diß_ÉÆ® ýÉ­¸W\A___Éþòp¿Š‰ö0” m‚ ‚Ð8ØÀsyfÆ|Þ|ÒR”3¸ãøâ´$£3­„G×óxÃ3!wÄyh‡CØF¤Ó~ ³*­;蛽ÙmŸ~lÏf³8ŽCw·Ì7„é@0Íà–,§~`;v|“h´ôùÏf³är¹@|šMó]Û§ö¼„–â/g? o?Ea&<øöÌ£ÂöfÁu]Ç)‰èà8š¦á8º®cÛ6†a ù«Ò©ÉY*Ûö§o¨}*Ó4±,+økFŽÊuÝ -øëjëºx™—çeétšX,”3|lyùT>곪³*W2™$‘H ».:GyžªýÔ“ëº%u-/‡Ê£¼Nª ËÛK·€iš²p|+`š~ˆ ™•*”q×SóXô¹‡0?ÿ†I=Šª Ä0%6?Á!‹ãñ8©TŠ\.ˆSa;¤ëz ä%“Iòù<‘H„,X|O$8ŸÕy”`•ÍfÉçó%yõöö‰DÈçóär¹LÙI%<*a/‘HÐÕÕEww7‘H„¾¾>ÒétPժΉD"h˲Jê–J¥H§ÓtwwaðÓétpŽD"A6›%•JÇK„Iužò¼”H§iétšf̘Ô9•JÂ_yÝb±]]]ôöö!¹»ººðŸÚ+›Í–*¯d2Y" '‰@4Ìf³Á¹Ôþ°jYVÐÎ*oÕæJÈœ®Âão‚ݹ‡ïþèGD˼AA˜ž8/€~¼øüIuÔA†ßËf³C¢#‚P™i%EB° Bë²wï^.¼pnÕéÇÁqœ Dh<<ÕÂáBS©Tð½\ÈPišèºˆRåÃaQË GiWöHy†Þj¡q§Öš¦åWíPm{†QSÛÕ*jÕrnUw¡2JTAApf=ÏsG?ìC-¼à8ŽDK„10m„Ç'æÌà÷h:£‡ Ù/±™azà¾/»pæ™GÛâq?ìª ‚0}p_:„ý‡­à[ߺ•§žúÏ=wh°/—Ë‘N§%„Š ´8/¾xdzoÄ4ÊÃOMHPÞhÑh4Ë…¬ÑÐ4MD Ah ”° ‚ €søaÌÚ°ŸE‹¶Û²Ù¬DD„10m„ÇÁƒæïþú2“‹C“MU¨#YÇI¦Î8þ™>V¬< ‹Ÿîþ)nÊåß^óoõ.š SÉ!Ëyæ¸âŠe,YòW^y‡ëîàǨíjl¯¶|*]ù=¾Î•¶Ùؼ|æËt¾Ô9îëÒÌ„žØØ¸¸|çöï°ë¾]œwÞy<;óYÜýk’%[ïâ–P~ ŒàÞS¨{°œò{t4ÊïWu¬‹ü Û;u¿ç9/ª,cÝ'yúõO×»uá©§žB×u™H BE”Ø¥¾òµS©AèõT*EWWW ª(JK§ÓÀãy^pŒ‰r¹\ 0/X*±-™L’Éd‚c”èCÅJÇq‚c”@§Ò*áQ£ÄPÓ4ƒº‡QÿÃk&[–,S¡Ä¶p+‰yª^ª=U[+ÁU¥ßË,-Bå§Žu‡l6[Ò\ÕGýWÇ„QBkù»_ù1•Þ]×-zÕ1aq0¢?ìU.W8¿JŸ+µIøz©0ð†aÏç1M3XC:ŸÏaýÃb¶ºn®ë’Ïçƒc ௯MÓøÕ¯~UïG¯®X…¿?<…WÝ|9IngÅæ<½ÿi>ÂG†¼[%I’#GŒØþx%*õ•£Dƒ>v™%4/3<µš} ³víZyï{ypë«xr÷ûyî=7%Ê»·¿›ÞüQˆÁ—'‰I’$iÒĈáà`b#&/±BSr饗²nݺz£.õþþºÏÂöÆb °ýYw–n‘#7j.nÐ901ÑÑ10dv“ÐtôôôÐÓÓÚ5kê]”)eíÚµtvvò¹Y¼rÏóü棳ð<‡›Ÿ»™¿÷ ‹®X„††‰<ó..iÒè…аMc`È$¡)¸ï¾ûøÒK_¢³sz‰ª/”%K’$..m»Ú8ú £yñÅY¸p!@ ž‡Ÿûj'!B3ñÀÕpûÇo¯w1¦Õºè¢‹j^ƒ³ÕPƒÚj°z,kŒªã`øõ3ÃÞ]•òW‚BxûDˆÃªlá¼Ê·)±¨|>\îro5UfU%Єӆ=šTšðyÔguLس-Üa¡$|}Âe+?Vµµªª£.T¯¹æùìg?;)÷U£²víZ^õ÷¯â¶“n#F “\.WÒNš¦‘N§Éd2X–ˆjÑh4æÔµ­t¯–ßÏBõ¨gKìôÔ1Ç ×­[GnçN>÷ÔY?`ùÇsüô n\ËöùVcåÕ$ÔÑ&û*±ÒÅ „F5Πt‡ð¾1¢Hˆxar™ˆ1Ãiãñ8{ëV¼­6Ï]|3}ô¡¹ñÕqÜî•$ˆ'Mš\á_/½¸¸XXäÈ‘%ˆ@09Üìt€„FÀbÞ®ÃÈ/Îã:.íí +ü«> §ð/I’8ñ…†jf)‰„©ãí/±'q§}ø4ºè"GŽ%/aÛÛ‚¾@’dð\khtÓ¼ ÷LËŒD¡ÙX{×Z˜^šc@œ89r$H`Ú&ñxœ|>¶P& ÓK½´ÞE¨£ fÛ6h¨dŽãÿ7 ¸ûîmlÛösæÌaóæÍtt´së­?æŒ3ÞÏ-·ÜB"a’N[œuÖYÜyç,^¼ÏëeË–£yÛÛ^âÞ{_ä˜cŽá÷¿ÿ"‰D‚÷¾÷+|ë[?æø?ÿùg¸üòïqæ™gòðÃû8é¤9,_þ$ù¼Ç‰'Å~ðuÒé‰D‚Ÿÿüç\xá…äó "‘4ïzׇ9pà‡,Zt»w/>¯_¿žoûË\~ùZòùn"‘|ûÛ¸üò7‘H$¸÷Þ'X´è<öíÛÇöíÛY±b·ßþ®¸â&¾øÅ/rÇÿo{ÛI§Ó$ ®¼òJzznáÍo^ÈÝw?À[ßz8?þñ |á pùåiÒéA;$ ®¿þ?øÖ·~Ìë^w Û·ogß¾}¬Xñ;vÜÂßø¾þõ¯óóŸÿ3^˜.9Ïÿ¸ž£>•GyŠCÙË߸œ?þñV­ZxX%é´M"á{ð|úÓ7òº×ÂæÍ›8ñÄ£xòÉ?rþùWÚí3\xá— ÇvñÙÏ~–»îúË—¿ƒ'Ÿü#³goçU¯ZÅæÍ›9ï¼óøâ¿Èõ×ÿø@¼ÐöI®¿þ¾þõ›Y±bEá<ݼõ­‡s÷ÝÏÊçÛßþ —_þiÒé4ë×çùЇ–ñÄ¿dÆŒîºë.ÚÛÿÌAý=›7oæCú×]—çsŸ[ÄûßÿR© _þò7ùá?Ïÿù?ÿÅ™gž À¾}û8úè=…óÌ ‘è*œ'Íõ×_Ï>æÛßþ2ŸúTŒüÇÿdïÞ½,_þ$W_ý›7oæÌ3Ïä®»îâÊ+gsÍ5IR©^²Y›HdA½ɺ0xð ]tñá?Ì2w‰Dð…Cr=óÇ ”íPâúH!›Et?²6¶0ÕØóæÁ£»8(þ>yÐṎ̼JËÑÐH‘Ç™Š¤Ic` OPڃ¢‹®’sWG,Ÿc`©ò‘±L¡ÓÆãñæsΡïåG¼²‡?|7ŽãL&éîî®xŒƒC¸¸ôÒ;äR³ÂTš½ f,Œ5ÜZXµ°&u ³<Ì’*¯ ¥TVI¼‚†F²+„¢„éÊtônP3¹ßùÿ—´e³y3ìÝ ï{\ý€Å{ Þ²r'[ŽÞÂ3ÏøE^yåPV¬`çN½{â‚ `ÆìÜ9‹Å‹Ÿg`àP4m®ëñÆ7Îà°ÃàÎ;aùòb.¸nº ¶lñ·ïØøŸwï†7½ öìñ·«}'Ÿ ³fùûçÏ÷·‡9ë,ÿ<Ç[<^±h‘¿]¥yÓ›àöÛýüfÍò÷‡óX´Èÿ;ÒyT=;vøûÃç>öXxè!ÿû¢E~].¸Ö¯÷?¿ë]°s§ßG¬ñäzƒ“×XÌšUÌCs÷nÿÿ¢E~ùŸxÂ?Nå§ÊᲜ~ºÿ}ËX¼øy.~~ÿyÙÖ硬á¾Pĉ`éþ»`x\g"Þ *Í ‡rzñ7¡L×1CÕêèù"Ï.üožnÿsIèãF¡|Ìʪ8>\‰ñ,µ;YKµŒ5ªÆ[qìF-¥ÖhÆú[#T¨ãÃ÷J¥ñÜmÛ¶qÔ­GÕÔ'˜6ÂcÿQ+ùÿ½ûŸø°½†ožù’É$¦i6Ì"òê&šŒÁn徉Æ: =Qçm6Âkà(q0<¤• pùºVã‡[—ª\ø ÇîGgç­;yøÜ‡ëݼSÎçÏ?Ÿµÿß“¼výÜöÏ—ÑÞÞNoooCÏ>œŠg5L¥œzŠpce¤õÐÂëÌ©6UÏöpL•ýRåªv}®JLJÇò /•lО={è¼¹“¯¿ÿëSRÇFaíÚµ¼ê¨\yöô^ÇE/¿‡Ÿù³ dU#ÛA˜ ¦³ð¸nÝ:Ç ÂŸ5Ò`‚ L5ÓUxüßÿÝD:‘À›ï²d‡ÁÂC5fÌØËæÍÛxík_ËSOý™•+ÁΞβe³g¿€wÊC˜Z'³fí|..³hü쇹/iœðV¿¯öÚ:7Ý+ßârø’Òþû«³hlÚï°äyÃU^‹^±c‡/0]p/¢)L hà SJl»ývÿ˜‹/ö÷©¾åx¸Âë1—¯«þŽ´î³ Oà ¿—·i¥1‡Í»\,nÏ’- S7\~áz<þ¸Ž;®´l!@•×q¼„Ç+Âmöl)_ºÒû’Ú7ƒŒÍˆê Ý|³/´$R‰`œ¥Ú÷ñð½?ÒúÞ‚Ð L×1CÕêÞÙÎ)·þ÷^z ]]]hšF&“©w[õ{¥œrš 5VZîÀ ÆêË×ò,w*‹ÓQ=˜ˆ>Á´ µº<÷u^~×A|áÄ(YظP Ñ&L—æ.…së]Š©çO7—}+ã[Ò¸®K___CÙJLõÌJ6HìRkÒ³©‡ž=õ.F]xò•#ðžý =q4?{ÇÏÈårÄãqê]4A¦˜ŽŽR©TÃ÷A˜^õª=|iC/ŸzŸ‹ ½½D"ã8%•­7€U˜‹—:¯†΂Y7A"AQ’˜__UݱT+v.‚ï¯.|^>B~!2õ.p]j”Áˆ#K¿&HŒ}RôqÕ'mz¶öгgz¾€ïͤëz°Ö» LW¦ë˜¡ÂÆ‚…Qï|lÛ&‹ÉåIBé!Íè´Tþ;þ^ƒs¤õ8y­Î‰èTïJŒ•µk×rê©§rì±Ç²zõjúûû«:îçïhcþ¯;Ñ4xâ)ö.ù!+yQ°-ŸÏ×»:‚ ŒƒZúŽãÐÝݬÕ$BóR‹-øÔût:::H§Ód2¢Ñ(©Tª$:’iB*åÿ¯•TÊ_3²ÑhÄ2MX݆YKh=Æk ¾óï`ÛvÃDEaüÔÒ'°'d߯ÿûà;Éårär9YgTÆAS k×®eýúõ¬Y³†uëÖÑßßÏêÕ««:öÀÎã9ö¶¿Àu]¡I©ÅÜ¿Ò :Þ1#T¡9©É<}Øÿ~Òéd³Yâñ¸Ì`„&¤;‰D‚5[Ah^jµ¹\ŽD"A,Ã4M\„&¥[pì±ÇÊø€ ´µö º·ßdYü½Ïáº.†aH$ê]-AhJšJxܰa«V­bÕªUtvvrÍ5×°iÓ&6lØ0걋¯ù'ŽèhÚÛÛ%œ’ 41µØe}øÄ'>eY2¨ ML-¶àÐï%XÖõ_PXC ···ÞÕaÔbÀ÷t–AFAh~j±Ï<óL0IÞ ¡¹©Å¼ãïoGAhj}?øå¬ °Ãà´WA:&›ÍІ ã¤i„ÇM›6ÑßßOggg°méÒ¥¬\¹’7Žzü©ÿï¼r iC¬®]»–žžæŽµßÓÓÃÚµkë]Œš¹ôÒKë]„iK­và©ãž"×#•J5팥V¸ÿÄž µR«-ؾô¼îï~Àã?Ðtý‚V¹ÿZÁžµBš•ZíøÏþtZÅvŒ•éøœN§k]«-xÕ«^EoooÓõjAž‰éÃtºÖÑ/˜nL§ûCÑ cãaº\ëZíÀ¦M›xléÿrø/ß;c~atww×»Zc¢®u+<§­ÐïxôÑG¹ï¾ûjÊãzW¢ZöìÙPb<æÍ›Ç¦M›FÊë_ÿúzWeÊ˜Ž¶ Æ"ÆCµ×zºÎ^:oÿ3œœà™ãØ·o=öX½«5æ6hö纞Ófïwlݺ•ûî»^x¡¦|šFx¬…SO=•x]×›ö‚·µµñ׿þ•Ý»w×»(ãæ…^ ­­­i¯â˜cŽiÚ:lÛ¶mÛ¶±xñâz¥.,^¼˜óÎ;×u›ö6óý§{Vî»ï>^~ùå–˜ 7VN=õT6nÜÈ›ßüfyä‘zg\4ûý§h{ÖÌuØ»w/=ö/¼ð'œpB½‹3å†Á¯~õ+ÚÚÚ8î¸ãê]œ)¡UlÇXiæçt¼ŒåZ?þøã N˵ŽO8áùÕ¯~ÅñÇÏܹsë]¤)Až‰éÃX®õt?X·nO<ñDS¿£Ž•éh Za,b×z²i¦:_tÑEMùŽÝ 㞃ƒƒ¬^½šc=–c=–‹.ºˆM›6¹Œr¿Mɘ'ÔK.¹Äëèèðn»í6ïž{îñ®¾újï˜cŽñn»í¶ ÍÕW_íuttx7ÜpƒwÏ=÷x^x¡wá…V½ªësÌ1Çx÷ÜsOÉöjÊXÏzÜvÛmÞ1Çãe³Yïž{îñ>ûÙÏzÇsŒ÷—¿ü¥iê 47£Ù‚f»ÿ*Ù‚f¨ÃDØ‚z×Ah^&¢OPmš©ªO3ö Aµi&“fïÀè¶ ê ´.SÕgh´{x*lK£ý†O•-j´k-ŒÎTõí™Põ¬ÅTS§Fz&¦j¬¢¯µ0:S5¦ØHÏ„ª£ô &g¬¢Ñ®õTÐ,u^ºt)K—.wê]ÏV÷\ºt)kÖ¬|ámÏž=¬_¿ž•+WejÛ2Õc6âñØ lذ‹.ºˆ¥K—‹Åê]œªÉf³Ì›7Ë.»¬ÞE©‰‹.ºˆ¶¶6V®\I?—\rICýÈÓ±õElЈ¨?b „f YmÅXi%Û2VÄ £1]ìL_[ v@¨†éb ¦«±BëÐìöjíÚµ\zé¥lذsÎ9‡¶¶¶z©j¦Ú†ŠÇcéïï窫®¢§§‡Ë.»ŒX,Ö47lOOëׯçÆo¬wQj&‹•;gÐ,uš—jlA#ßÕÚ‚F®ƒb"lA½ë 4'Õ'¨6ÍDÓJ}Ý4C„Öd*û pOµmi„:‡™*[ÔhõFf*û roL¤-h¶gbªÆ*©ÎBuLå˜b#ÜÒ'˜š±ŠF«÷TÐ unôkÛìãžj­Õ0tvvÒÓÓ3¦26úØmµe¬&udõêÕœsÎ9\sÍ5c5«X¹å söôô°téÒQ÷O6«V­â _ø—]vYðàœsÎ >WSÆzÖã„N¨xîðw£×Ah~F²Ípÿf š¡a ê]¡¹©µOPmšÉ¢ú0º-h†:­ÍTôéž*ÛÒHu†©³EVo¡:¦¢ÏÐh÷ÆDØ‚f{&¦j¬¢‘ê,Œ©Sl¤ûCú“;VÑhõž Z¡ÎÍrm›}ÜsÆ \rÉ%#¦itÛR1ëDOOýýý2þVŒW­ZÅúõëàÚk¯¥­­sÎ9§ªý“‰zhÂÿ’…U«-c½êÑÖÖFgg'k×® ÎÝÓÓÆ JB5r„æ¦[Ðè÷_5¶ Ñë0Q¶@ì€0&ªOPmšÉ úP-hô:­ËTöåžJÛÒ(u†©µEToat¦²ÏÐH÷ÆDÙ‚fz&¦r¬¢Qê,TÏTŽ)6Êý!}‚É«h¤zO­PçF¿¶­0îyöÙg388ȵ×^[R¯žžž ï‡Lõ³™áyž7é5†°víÚ’›5Lggg/xppK.¹„ÁÁAÚÚÚèïïgÍš5‹ýhû§šc=–uë֕ܰՔ±žõèïïgõêÕlÚ´‰•+W²iÓ&.»ì2Ö¬YÓ4uš—jlA3Þå¶ ê0¶ Þuš“‰êT›fªhÆ>Œn š¡Bk2•}†F¾‡'˶4Z§Ê5Z½…‘™Ê>C£ßã±ÍöLLÕXE#ÕY¨Ž©SläûCú;VÑhõž š­ÎÍøŽÝ*ãžëׯ窫®¢­­yóæÑßßßôc†“}?‰ðØ$¨xÁ'œpBŘí£íoª)c=ë¡Î½téÒa]œ½BkÓ ÷_3Ôa"lA½ë ´6ÍðµBF³ÍPaú2Q÷g³ÝÃQ§F«óTÙ¢F«·01´â31õn¶gbªÆ*©ÎÂÄÒjÏÄDÔy¢Ú¥ušì±ŠF«÷TÐ un…kÛèuèïï·ú˜áD\ AAAAAAA¨YãQAAAAAA„šáQAAAAAA„šáQAAAAAA„šáQAAAAAA„šáQAAAAAA„šáQAAAAAA„šáQAAAAAA„šáQAAAAAA„šáQAAAAAA„šáQAAAAAA„šáQAAAAAA„šáQAAAAAA„šáQAAAAAA„šáQAAAAAA„šiYáÑu],˪w1„qàº.¶mOh~“y/X–…ëºu9w#·K£0]ê)”bÛ6ŽãßÅ O£—Oê)L$ã¹ÆÒ'iV[ÐÈe“z µRÞ'€±ß eÆs‘Ë&õ`bÇ ¤O0±mÓlL‡:¶*µØ‰èŒ•fµ\6©§0шžšÊçµ(ù|Þk•êe2¯¯¯oØï­ÂÀÀ€F=À<Ã0¼ÞÞÞšóì{ðòù|]ÎÝÈíÒ(´J=+=÷­j j¡··×Óu=°#¦izbF ÑË'õ,eºô &‹±Þ‰DÂ3M³êôÍj ¹lRÏ¡HŸ :†ëxÞØî…‰´c=÷TÓÈe“ze:õ &c¬@ú×6ÍH+ÕqºØ‚ZìÀDõ ÆC³Ú‚F.›Ôs(ò~Pb†§–òµ¬Çc+‘ËåJfä”o’É$Žã000€çyèºN:®w±¡!¨ôÜ·ª-¨…®®.¢Ñ(žç100ø¶EZ…éÒ'h,Ë’~ˆÐHŸ :&¢O v@hd¦SŸ Þcb „FfºØ‚Z쀌­Ž¼È!õ.ÀD’ÍfqMÓ0 cØýº®cš&–e‹Å‚ý–e®£Ñh4È#™L’H$Èf³¸®‹aD£Ñ’ó%‰ Ÿ±¦¯¦N¹\ÇqJ¾›¦9¦|b±º®Wµ¯šýÃ1–vp]—l6Koo/š¦J¥Èf³%ù©mê:Æb1ÇÁ²,¢ÑhÐé0Msضq]—t:M4EÓ´1;–¶.¿U]×EÓ4b±XP×jÚ2•Jß-ËÂqœàþ _£òòw¬ºŽª=&¢îB-¶`8; Ú²¶ Ü˜¦Yq[µùÀøžõ©°£=ÏÃÙ…ã8AZuý+…a ÛÃ0ÆlGªmëJ÷àxmÁhv üUj·‘Žn¶@úã{ÖÁ¨ü&ºOPþ›­(F ™Xm[O¥->A)Ò'=/hÌ÷ƒZl:¾š>T¶eÂí5QïÒ';“Ñ'PíÙ¶ ™úcm‡ÑÆ F³Õö Z±OP~¦»-1ÃÑóÆìÔ2f¨Úe<}3l=;ny?>/hL[P˘a-}3Ÿ-hÇŽŽŽ`¶ŠeYtuu•ìO&“Aãär9ººº‚‡ NǸ®KGGGð¦ö¹®t:#‘Hð#•N§KfÊŒ5ýdǃº;ŽCGGGp“´¯šý#1–vPÛÔ¿eYhšVrÓ§Óiâñxpþd2ÌxÊf³´··çŠD"ÛXíS†l,ÇVÃp÷¡ëº´··?N¹\ŽH$Ru¾å³¸,Ë îßH$R²¿«««¤ó5Ò±À„Õ½Q¨ÅŒdÂû›ÑÔú¬O•-í™Î(4M+yw˜åv šóŽ…‘îÁZlÁhÏòH¶`´cazÙéŒïYo; ÒOtŸ ¼Æ:ˆZN=lô J‘>Áð4ÃûA-¶ªë¨ë[ÉL„€Éy?>Áؘ¬>Ax3Ú‚zõ ÆÚ£Œdªí´bŸÄ„‘1Ãái†>A-c†0þ>Œ¶–y?‰f°µŒÖÒ'1ÃqÚ‚zlj2™Œ§iZIÜb÷Ûó<¯¯¯ÏJöëºÄçWûñÁUžžçÇáÍd2Á>Ã0¼X,|/õ?Öô£ašfIàòï#ÑÛÛ;¤î¦iz‰DbÄ}£[ ci‡îîî κ®ëž®ëž¦i%×(9w&“ ÚðR©TÉ> dm·!eíØjë™ÏçG¼Ëã! x¦iVk»üQ ·]y>‰D‹F££;RÝ›5x-¶`4; Ú²^¶ Òs_­-¨õYŸJ[0Ú39œPäóyOÓ´À†èº>ª¨æ¼ÕÔq4;>b,¶`$; ®Ép¶`¤c§›->ÁøžõF²*¿‰î„Ó†1®ëSo[ }‚"Ò'žfy?¨Å¨ã+õ Âyg &¨|&ãý@úÕ3™}Õžb š¥O0Övm¬`4;0Ü=ýóŸÿ¼¥û꺈-1Ñh–>A-c†ž7þ>Œ¶ŽPå—÷ƒÊ4‹-¨ḛ–>ŒŽÏ´„Ç£r™ÏV »‚ær¹!û£ÑhðÙRc°ƒ€IDAT²,t]ÇuÝÀeZ}WêzøXMÓFuqkúÉ¢RÝóù<©TjÄ}£[-Õ¶CxöR__}}}Äb±!ª~Ø·|vRØý\]ÿðŒ&5["|í«=¶FºÕ¶x<ÌÌÊçó5Ï ‚|Ôl˲ƦRÝ›5x-¶ ;Íi j}Ö§Ò(Fz&‡³®ë’L&1M“L&C&“AÓ´’Y8#ÙÑÎ[ £Ýƒb ¦†‘®ƒô Æ÷¬7š€Éé8ŽC:&“ÉÔÔÖõ²bŠHŸ`xšåý@1[PMŸ*Û‚‰²*/y?¨/“Ý'€æ´õª+©O•ïé?ýéO@ëö @lBÆ ‡§YúµŒÖÒ'PȘaiy›Ñ¨rËûAešÅ(Æ3f8Ò±£õ ª9o5L·>AK¬ñ8œ‹¼b´Ft§$N­¢âV7 ¦i’N§KŒR"‘ NcYÖ¸®E¹‘2 Ó4‰ÇãôõõéØjé>Ôu|>¸é»®K,› @®Z¤êõ#7Ôb Ä46ÕÜ—*zwww°M×u:::xË[ÞŒÍT{Þ0£Ýƒb ¦†‘®ƒô š—ZîÉjûÙlMÓÈårär9lÛÆq’Éä˜Â¬Õˈ("}‚Ö¥Ö>Aø¥¹’-˜(;ò~ÐHŸ ùm¬`<„ïéVí€Ø…Œ6?µŒÖÒ'3lNäý u™¨±3_» GKº®Q—ÃÆBÓ´‡a‚>޶튋Ì6åuW „Ž´O)×£íŸ(FºY«}Ô¢«êsyÙ3™ ®ë’Ëå†,š:Ú±Õ0Ò}¨ŒU³«lÛ&‰`FMm™ËåÈf³ôõõ†+™LŽi¶ÅDÔ½Q¨ÅLW;Pí³>U¶ \Þ±Þ—ácê¹Ø¾};0²ïyËÏ7Ò=(¶`jé:HŸ`|Ïz5ÇNFYÇ{OŽ·O0Q/Žõ°bJ‘>ÁÈ4ÃûA¸¬Ù'ÏÌ­d &rIÞêô †§Yú“=VЊ}[FÆ G¦úµØZú•ò1Ãæ´ ï£Ñ ¶ \ÖÉ+1Émó–µFK½,ŸFƒÅ‡Õþð⯦iÙ¦#mÊ/fµ7v,R÷x<(æÃííØ‰Æ0 t]/¹nÉd]׫6àå ôjš6äeA->N§K:Õ;#݇ᙠÀ¸f„¯Cø𦕄¨4ë³Ò±•ê®Ú¼YgìÔb šÑ ·­œZŸõ©´Šñ<“å×7|ì)§œlÎŒ÷¼åeé¬Õ ÷,Wc F²åuoe[ }‚ñ=ëÍbÆrl%[`š&©T*ø¯ú'©TjL^Nõ°Ò'(EúÃÓ,ïЉîŒf &ʨrLÖûô ªCú•i¦>ÁdŒö~ÐÌ}õ]lŒO³ô j±µô ÂçíØÑ1Ãú#ïÃÓ,¶@1Ñc2f89}‚–ðx4 ƒD"AWW†aŠz8Öz&“!‰`šfðBžé˜J¥H&“q§dC=Q±ÇÕÃ^þ}$*Õ]Ó´ ŸáövìdÐÝÝM$ ®ëºcºŽãÐÞÞ;œr4%ǃ° Õ;#݇±XŒ\.G{{;†a3b†‹]N, òu]7ø1ŒF£d³YÚÛÛÑu=¸·ÕL†X,6챪̶m—Ô½QîûñP‹-h6;0ܶJŒö,׺2Ï3iFPNu¿«{º¼Ã¶ák\«-í¬ÅŒô,Wc †;V•{ºØéŒïY­Ï0Ôò<ާO0‘׸¶@úc»ÓµO0\Ýõý@µýDö *Q[ }‚©Aú•i¶>ÁTŒ´RŸ@ÕGlAu×@lAsô ÆkjéȘaëØÑ®ÈûA³ØÕö“9V c†Ó'˜áyž7×»!p'¸¹Ã3^”ë³jX]×Éf³8ŽSã[¥S Ú(q«Ãå/\«¾¥m`hÈ‘öU³2ê:–sY–E$Áó¼@¯öúÕrìhm]~ªó÷†mÛ¸®[ñº——]-r¬Òtl¥ã›ZlA³Øá¶UÓ.0¾g}*lÁD<“árÖËŒdÔù`ì¶`¬ÏrØŒvl¥ã›J×Aúµ=ën&ãw½êa ¤OPŠô FohÌ÷ƒzõ &ƒÉx?>ÁØ>ÁÈíÙ'¨Tß±œ¯‘úò~PdÌpô¶Æì”×u<çj„q‚p9d̰~ÈûÁèmi ê5V c†•–‡C©Ñ½½½š‰DH$“ª¾FØX ÇH²ÖãëYö‰$üðOä±SQÇFjÇ逨‚‰½&ã¼µ<ϵ ¶`úЪv`¢ò¨WÙÃLÖïz#Õ±^犴ª-h;õëLu=ëqÁ§UíÀDåQ¯²O$“aGÄ´­j d̰vdœ`z!¶ ñûõ+[0>Z"Ôêh„]~•{´r'¯'ÃÅÖ3Ò Z¯gÙ›©¨ãthÇFBlAc•»Y[ÐZ´ª˜¨<êUöFGì@ëѪ¶@ìÀä"¶ µhU;0QyÔ«ìŽØÖ£UmŒN.b Z±UîfAlÁðL GAAAAAAA&—ƒê]AAAAAAAšAAAAAAA¨AAAAAAA¨AAAAAAA¨AAAAAAA¨AAAAAAA¨AAAAAAA¨™Cê]€©à'?ù 7ß|3³fͪwQÆÍîÝ»™5kVS×áÀ8p€ùóç×»(5±sçN.\XïbÔÄÁÌu×]WïbL9úЇxùå—ë]Œšh…ûOìYcpàÀÎ?ÿ|þéŸþ©ÞE™RZ¡OÐ ÷´†=k…:ìÙ³‡k®¹†¥K—Ö»(SÊÇ?þqvíÚUïbL)­b;ÆJ+<§ce<×úÈ#äꫯ®wѧ”þþ~V¯^ͼyóê]”)Ež‰éÃX¯µ¼4ïûÁx˜Ž¶ Æ"ÆÃX¯õt3ü‡ø^ýêW×»5Ñ Ïu+<§­ÐïØ³g§œr ŸùÌgÆÇ´·mÛÆW\Aggg½‹2nÖ®]KgggSס§§‡žžÖ¬YSï¢ÔÄ¥—^ʺuëê]Œšë0yùå—[âÚ5{Äž5ªÓVè´Âý­aÏZ¡k×®¥¿¿Ú »víjúk7VZÅvŒ•VxNÇÊx®õt|?èïï§³³Sž‰i€Ø¿ê÷ƒæ}?ÓÑ´ÂXÄx뵞Ž}€¿þõ¯üò—¿¬w1j¢žëVxN[¡ßqÝu×ñ«_ýª¦<$Ôj“°téÒ¦Ÿ‰9oÞ¼–ÔZ¹re½‹ LcZáþ{&µÑ*÷_+سV¨ƒ0}hÛ1V¦ãs:]¯µPòLL¦ãµªg:Þ­01¦ãµsæÌ©wj¦®u+<§­Ðï8âˆ#hkk«)iáñØ ¬ZµªÞE¨™•+W¶„læÙ BóÓ ÷ŸØ3A¨V¹ÿZÁžµB„éC«ØŽ±2ŸÓéz­…êgbú0¯µP=Óñþh…±ˆñ0¯õxX¶lY½‹P3­p­[á9m…~DzeË8î¸ãjÊC<AAAAAAA¨AAAAAAA¨AAAAAAA¨AAAAAAA¨AAAAAAA¨™Cê]ņ X¿~ýíkÖ¬aåÊ•Á÷µkײ~ýz9ûì³Y³f K—.­wñA˜Ä‚b Að©Æˆ„ÖFú‚ €ØAÄB³Ñ07n¤¿¿Ÿ•+W–üokk Ò(ñfÍÖ­[G?«W¯®wÑA˜ Ä‚b Að͈„ÖGú‚ €ØAÄ4;à>»µd$4 ãñ888Hgg'kÖ¬6͆ Xµj«V­àšk®Á4M6lØÀÙgŸ]ï*‚P#bA±‚ øŒf ÄBë#}A@l b ȱÂg­°ÝÆ£eÛ­Ðg 0+ä§…¾§D…óæ yÛ€1Âñ «Â¹„©¡a<ûûûKf(”³iÓ&úûûéìì ¶-]º”•+W²qãÆz_„ @ì€  ¶@Ÿ‘lØA˜HŸ@[ ‚Øñà ³=;ÆôÉ Û”Àèà‹„ «°ÏÆ ÃéÕ+´=]Ø–-Û^ž.œÞ)”)ì9ÙUø>§ Ä+lŸ(ÜB9«Åbø6VùUCºÊtõ¦a„Ç7ÒÓÓñÇ˱ÇË©§žZ·yÏž=%Æ`Þ¼ylÚ´iļ_xá}ôÑQÓ B«ÓßßOOOûöí«wQ*2™v`ß¾}ôôôÐßß_ïª B]éééáÑGå…^¨wQ*2}‚žžžzWSêÊàà ===lÛ¶­ÞE–‘lA­}‚ÐÓÓ#ï´gÓ¦MôôôpàÀz¥"“ý~°mÛ6zzz¬wU¡®Èû¼‚Œ6ï˜áp‚Õp£5Ìv%0†Å4%0–o·BÿÃçw Ûr”ŠlåéÕß\á¶,/•6|N%ôeCûŠ"e_h,/C_˜t)Šv•ÄTBeHVØ^©}+µ±eùÿ˯M.ô¿’™,;O6TÕ¶ªli £,Ÿx(]¸Í"euN‡ö•—Ѻ\wBú juéÒ¥\sÍ5¬_¿ž«®ºŠ¥K—1cåùçŸgÓ¦MÌ;·d±YA˜n¨NijÏ>[ï¢Td2íÀ³Ï>KOO²°´0­QbÃH³ëÉTô vïÞ=!vEš•={ö4¼ð8’-¨%<ªYЂ0]Që%5ªð8ÙïJx\ºtiÃö‹a*÷y?3lÞ1Cò´%ÚeËöç*lWÞ‹à TùP6¾8•2¡ôj_¹À¨¾k¡s• m.E!Q jJ$Ô(Š“v¡ŒQŠ\6t®8 ‡Ê­Ê™.ä£QÚÒ…ÿ¥¡\µ²ü…r§BçË޳Bi»àÙC!3§´nŸ »wáüuàGÏÃ’çaY[1L¬A1Ll¶ðWC•1ú«ÂÆ*Qyzê…2Î>×ς޶t!?%Vjeí”*lï¥(Ìæ4¶6ô—_¦Fx|â‰'J¾¯Y³†žžÖ¯__³ñ˜;w.ïz×»¤!L{:;;éììlØÙý“i.\8b,xA˜.¨g«QgõJŸ@&Ÿ¥K—²fÍÖ®][ï¢ ËH¶@­Û2^æÏŸ/}A€àYš®ï§všØA@Þäý@d̰™Ç ‡­ ûÕ6%ì……Gå9Xî§Â©†Åð¨Î×Á·Ô~%>”zN*±Q­×¨ŽQ‚¤ÊÃGm×) u6¾0§„µla¿‹/”vΣHå˜.”-ƒ/ÆÍyœ™¥á\màÁAØÕVü®Ê3k6²ºæ”®q¹é480§(Š:À¡/Áæ6تkÕVNáÇ=éý}JUb±U(w_ŒÌ.Â5e²«¬ýÂâ«c$^˜pöžœ?¿îêâ°»î¢&Ôj%:;;‡„<©düd–² ´.bA±‚ ø”Û±‚0ý>  ¶@„égœQö‡Ã~–‡,-ß®B~J§ò(µªÒ«¼”0§‡Ò¥ñCzêøB˜:Nm3) .¾Xhâ‹‚)J=%£…ã”ȧÎ+lWÞŠ1 »p¼/Æ©¼û ùdBç5) {ªJ¤»s&þØÐý/½³ï)¶*Ç[¶Ã¼_úªö|Ý}_%°êÀ«ï€EÛücµBYºñ½ c¡60 Û^å{0¦ Çwþ>x9\÷ Ÿ®¯P¿^`~ ï÷½UíÂöß ÂÁ—ûåJÊÒ \²óyf½ûn¢øéþyºó¶ÁsŸzŠÓï¼³Ú[³" !£Ù±‚ÐúHŸ@[ ‚Ø…¶ì²íJ” ‰vh_ø{¹§¢ûܲôá5µPº,Eï»(¾@§Bj¡ïJhÔðE±pZµ?…/¸%( ±Â%H*!Q dÑÂÿX(}´P¶îÂg-ô7›Í–ä—*lÏ„þ‚/à}èIxîë~¾ŠÂÞÇû¯/ ªN!# ;¾à—+_Ø–æ~æ}·X¿h¡Ž î‡c.Ö!Søkg!jùiP}îüœö ¿½·Pž |ò“üô§?­é~máqåÊ•ôôô”„zêééaÆ œsÎ9Á¶U«V±~ýú`&õ×^K[[[IA𱂠€ØA|ª±b¡µ‘>  ¶@±ŠpèÔrÔ‰å^‘¹Ðþ0J€tBuJ="» ß•· QØ®8% *ÏGå¹§D>%¢i¡Ïfè8… SÐßð±ŵ”z]ªÏ©PžÉd2Øß]È+AÑ;RyLêÀª-@¶XöîÂqGúÛS¡z©üqŠeTžŒm›Á-4¤IcÀ»àô;‹¢«*o.JCTiï¹÷¹`­Êp]ºººññG?ÚÀo¿w ¹\ŽH{;ñxœ}ûúyä‘›8üG‘N&¹®ðlüéOàÎ;û‰D"D£Q¢Ñ(×]·…t^ÿú38÷Üs©…†XãqéÒ¥|á _`íÚµ¬_¿žyóæÑßßÏe—]ÆÙgŸ¤[³f —\r ]tmmmô÷÷³fÍš†]üZ„ê; ˆ-Á§[ v@Zé‚b A;F­ÁèRº–¢Z7Q ˆá5Õ_µF¡Néz‹&Åð¡YŠáM5ŠráôaÑL…„º^ô–Pú_*U̳%êD"‹A4ZêÕ8cäó`š•×µ„Òí®ëâ8º®¡ó©²ûiÁ0ŠÂ¦*»ã€¦G%ÎîÞ½›Y³f)ƒ®—æ °g×fî½w90sHzM+-»mû«If2}\|ñQd³YÇ!‘ðåÖ]»îÃ4‹¹{^/¦ÙÉÁ¿ à ‘H`Y¿øÅà ¾¯}-ÁîÝ?%‚a0wî\^sÈ_øÉOn ŸÏcΈ—¾¬æSŸú_øÂ™ÔBCàÏH8çœswè¥K—qƒnkkãÆo »>á„ZÊpÂtGì€  ¶@ŸÑlØAh}¤O ˆ-azÚ_z*¢/‡¢`öPTi”èX.0*11†¿~¡:^¥‰…òU£Z‹P‰šZY™”x§DºlÖð2™¢‡"øÛÂâZ8½®ûBb¹iÛEá1ÌæÍ›1Í%Û’I_¨Ìf“¤R©BÞY-ú>š¦á8 ”gYV à†NËòËF×}R׋ëK>þøã¼öµûp]3¨[1_H§ÓhšF,æ×à•w³Y{xè×^+d8cÆ,Ë"—ËaFAÔøÂãóŸ7Éf³X–Ew÷Ólß®ÑÛ›¡»û“ôööbš&ííqà<.<—oõ"nÁó•Þ^^xù$~ò“ œrÊ| MãGgžÉÿ{ë×Ãå—_ÎìÙ}UÜ¥ÃÓ0Â#P²^ËHT“F„æDì€  ¶@ŸjlØAhm¤O ˆ-aúÙ _Uy3FCçŽÒ”NÑCP”©P¨°W¤ò$”'øaF c¨ÐW å¸wï^Àö|@H§aåÊí¤Óib±zÁåpÇŽ‹ùä'¿Êe—½“h4Ê‚ èë+ jét:³Ù‘Î]UùßøÆyÜyç騶_~åQyÅÛ°¬%üà9ÿü%¸®‹mÛ2ï¼nÞ¼ .‘H„T*ŶmçñÝïî'‘8šd2„O=ï¼á÷¿?Û¶Éçó¸®K2™ä”SÞI$r11Ó?Ÿ¦i˜¦A$_ùÊLõ÷ÃÃm·Ý˵ü„oz(¦i²é¹›éðNâ„ó¾O,öwËqÐo~Ãúës朄¿Räøiˆ5AAAAAA¦3*lªK©ÈÅ0«á«åû•GdxmF%@*EµÎ¢:^­gà UXQÇxÜO¥¶ƒ/ªð©:E‘Q׋Âcè¼}ppTlÃðÅ<…¦i,Z´ßüÆ—´’ÉdAŒ„E‹~À '–l]K6›%‰pç¹çòXOO>9;w’ËåÈf³˜¦I&“á–[®äÙg ê¨ë:¶msÿý (4¦ibEÙ÷Æo.ñÅXÇd’}èCœÿ†7°dÇÞ|œŸß‘+>Œ…ÉaþsáF²yñ=ïá¾{ Ýü˜SOÝ3æû¶AAAAAAêLß#Ñ mSŸ•Sž Ä Ÿ¿ûnÀ ÃN{á5Á Õú…™Â~ _tÔBiŒÐ1Ž·Ür8òRbfyhQBé+ẅum;÷ ~¸ÒÇO*• ÄÄ_þòpòù¼z5¦»Û—ˆm_ýµË¤ç;ý‹`Y`Yí»é^xWÅðʼyüâ#!—˱}ûv¿ï}"HÛöö·óÐOæ’üß3¸é¦…5ßÇ"< ‚ ‚ ‚ ‚ ‚ ‚ Ô7ô·<”j8…/4îúi ÔÃ|¡0:Æ,¤q'ð^ÌÒÙ6D"~:-tÜöíÛÙµ«¸N¦Ò‡·lكٮB³ær9r9EJ×uyýë÷óÄOÐÑÑAGGÙl–+¹õÖtwwB¢ «úîwo'™L’ËåÐut: ÀŃX,’ñx’}ûg±yóæ’ð«·Ýö?œrÊ®ë^†ß¿î7œüò},[¶×u9â÷¿ç…ßÿžtÚåòËWpÉ9wp߇>„eYÄãqf=ó [¶¬â³ŸIoo/ÇvûSOÝÂÒ¥/rÊ«añÓOcY–ÌcWrï!o"ÛÑÁQ¿ÿ=Ç?÷_ýªïÁ¨ëº/˜Ú6är䉸×dÁ_L&1tĬkˆž¶ÕïZhKmó}‹¶a œâ»¢:ÖÇn¡kç7I~g­Zź|„T*Åx%±÷ ÂñÇûùضïbzúé8¯,Çùý 5ßÇ µÆ£ ‚ ‚ ‚ ‚ ‚ B+ 4:½Êô6¾ÀgþG‡ÉSåëþæ7,>ÿ|ŒÙ³âz: Ô›À²,b±XɶrÔößýnÏ?_ÅŒzè!víº`ÈöööÝd2ó1M›Y³fùõ´mž¹ÿ.øð‡qÓ4‰FýÚÆãmÀw°,‡¾¾¾ \é%¯ùo¾ùÍçùå/ýu Ÿ»ûnÎ,ˆo‹-¢ -â8‡¾÷X¼}{ :Æb1~ó›ƒX¿~}}½¸®ë{GÎ};_™ÅÓO¾ÂÁ7¦ùð»ÞÅÓŸý,s)°œ7tÞzâèÙ¬ïÕëª5ãñ8Ùl–;v`arÏÏöðæGaÎ_ÿÊÌc¥­ív>ø¶?±|Ö,°,z{{IÅb\Õs>w<óþyÁæ÷õm3ó3Ÿ!—+ȶ˖m£iZ n¾~å[8âÌ3}OÅh\—ü·7“LBÏÇnl, +mc žFbÑÐ>ðîÀƒÑ‰øvíGgûÇ<$­»ÅÞµŒÄÅ;ü˜¶–†ùÍ H]±ÌçwøÍ0 Æ<˜ÜïÓÑQð^-”/gAw žÆþý³Æq×áQAAAAaãº.]]]ضMWW3fÌB:ŽC$¡½½3f‰Dèèè ǧÓé¡a¤óÂt£RdÒþzŽ•P²¾ ©ª¼ 5ŠÞˆ&pÊÀçmÛV"2–{W*¯IË‚ÁÁÓ†–¯°, ëº%ÏõÍ7wâyCÒ–ÂìÙŸçÁýümÛÆ²üõÿüg?œh6›¥£££ä<Ç/9!ð<4 ³ j>ÿüL|p`` !·<ø ©”¿Zåawß͇ÿélòyˆÅJË¢Íy‘×´…×uþ‹ïhÛCbÄF£Q‰š¦1ç-oaþüüõ^Nܹ“Y›6±äüóiÛûiþûŽc`÷îbce³°?ï~ã“Ø¯óc` \¢¯¬Ç|ïN~Ùß©ë¾H78ˆ‰EôMñEÃt, Ïó8bÖï0>|š/†\ÛòÉk¡MÉf‹Â¨¦ùùhZ –&ºýÔWù^Œ½½pýõ~Ú³Îò³Õ´7ScÕÑþ‡T \—Øî¯’úÜ~t½´ÉÇÿÚ ÅZî{}vw—ꙊUÿ¶Ù³P ²Æ£ Bp]×uƒã‚ ‚ ‚ ‚ µL&/#]×Ñ4X,F2™ ÄÇD"A.—#N¡ 5M#•Já8étÃ0Ñ —Ë•x!) à _°×uL&x,uuuašf Äb1r¹\°®\:&›Í‹ÅaQ‘¨ó)¦t:ã8·“ã8¸®‹aÕ6˘ÈårÁ¹a"ÉÇׯ 5†_2¬ùi€ûïÀEùŽ<àçcÛD£QÂOi$}}¾°¤ä¼¿üå!àø!çøÓŸþ¬`ݺ;ÿ¹3M“Cý>/¼àá‡÷¡ësJŽÑ4‘2•Jáº./¿|2%™tøÎw¾Ã<@6›eëÖ­hÚOyƒ{ÏϘ<Ç®›ä¨ÙÛ‰´·û ™®cgœ±ŸÏ~6û7mb¶eiróÍøàkÖAö©b|Ø+xúéýdãqVΞÍï?ù“‡¼×ùPPÞŒ'.~î ˆÙ,ñh”©º7Ý´™ÇÿîYw¡)áñxp¶ÏæÇ{—á¸ÕuÈfùóß½÷ùÿåeìo܃aÛÕ˜óéÇ_ ·n€hH§¹÷g[€å~¥BªqáeËÈî8“T츠mO;mw½ ÞñŽ6H™ ëþº‰`iÇàBd—û›KÈd Ü©\×ýÿácô¿? šh$â;H†ÓŸpÂ3Ìšupæ¸ï{ñxl`F = ¡ ¡y ÏAAAA 5‰¹œt:MWWW æóyz{{q‡d2I"‘ “ÉÐ××G*•¢¯¯Ïó¶Çb±@T"£®ë$‰!¢£B«»»;ðTŠF£ôõõž‘Á9‰‰D‚‰Ùl–\.G>ŸG×uâñ8š¦‘Íf±4—Ëá•f<DÒ®®®a½%ÇŠ 3;Z¸XA ê9ŽòÕRÜ?à ’á}oÝŠï¹<ûÀL(¬µjràÀlÊŸT¹¿¢'ÞÃïJ·lß¾p¹ÿþ_‹ÅÈf³¤ÓiV®\ øÂ¤ã8ضM.—ó×C,d¡žcÛ¶yñÅÿb,XÐÅ[Þò:::ظq#®›àÕÌÚ´ Ã00 ƒ—^z‰~ÛŸøÄë^¸ç¥L“ÏÞ¯Ï@o/|ÿûàºÜzë­,ÁÂvü5 ïýÿý‹sô‘[馋W?÷¢ÀîO~Çq¸å–[˜1c7KŽÞù¼ï¢©ëØwîÃX¶KÅ–…ÂĆ]¼dzÑ4Èûö{,/¾ø"o]p?_»q…o—b1Ðu:ö}„¹sÿ„낵­(:æó`¼w9‰•¿,®iš<üÌò!×^™sí¸…dï8&Ø®i°sç·xùåû|gJ#¤¯¸¼î›ÞÄSO=è«åit½4ʬ50Œ¡kuªe 'Û¶K\ƒËQ³ ÍC2™ ÄÆ\.'£ ‚ ‚ ‚ UÓÕÕÅ‚ á ü1D5ÞH$H¥R˜¦‰¦itwwÓÛÛK"‘ ‹UŒºo¨¼jõø«&ºS,£¯¯ÞÞ^ ÃÊ—Édèîî&›ÍÒÞÞŽ¦i˜¦xs*/Éööö «šÜ=𓆠A[)ZsÎ0ŒÀ˲œJÛÂÞ¤*Ÿá˜¬±Ü° mÛöˆen,*‰ÈXó$±sçN=›,íWk7†×qtð…ÊEÛ¶¡öéøk4nøö·9íÁ˜ùðÃè¨ë™gÇŽ%ÀPáѲ|»¡P!UËÙ±ãæÏï\R©ÑhÛ¶Ù¶i?Ê”Íf¡æLß32—sÈd2èº^¸\‰·Þz+Ñh”[n¹…9s¾Ä‘GnåøãçØ}û‚‰‡ òÕÛ΂\ŽÛ?þq¼ürß5Xµê:–<ÿ<ÿýóŸ³û“Ÿ¤ï¿à#vrËA§òÔqÇqÜ]wqÏöí|õ‚/ðÿHñø¯â²ùó9~Û6>ø¶·qÊ)§0wîߘ5ëw ë¸Ýݾ»àœ9Ø[ôÕ¹XÌMjÛ¶i/üõ¯¼ûÝøÖïàï>øA’É$Ï?ßÃÏ_ømm7à8þDGÞüfîøGî¼³Ÿrs‰'ŸÌkïç—¿,„+5Môƒ~Ãyç}½$­ãÀgìÇüæ™ì{î9.»l=ŸúÔulÝzZ!mѹÓu‹beX;Þ<þø­…翘Fy;š&œ|òí%÷EXzRyiZñ\µ"Âcƒ2š(¡~(…æÄuÝI¹~ÃÍ|˲ˆÇãØ¶mÛcÓé´\[AAAAhq”¨ÖNO?Û¶éîîÆq:::H&“D"‰½½½AxR…išc^â%‹MZÓJ¨òE£QR©T 4öõõÑÝÝM>Ÿ'’H$Èçó¤R)b±©TŠÞÞÞÀÛ²½½=h£ðø˜³Ù,‘H„x<ŒÍ„ÇY"mº|>aÁZ˜Ê2ÓÞÞ^2ž—L&I§Ó´··ã8N ˆ†óu‡xøàV;ì0"‘_úÒ—xõÁï4Î8é$þý¤“Èd2˜¦ÉààoøàçòOm›ÑðïaMÓ¸g¶ïÙhÙ[|ß~;î¹H³~ý‡pйûøãÙ}íµœqàµl}öÿ°wæüì8ðÚ×2ø©O±ü/aÏÌ×ð8QD"èÀ?¿æ5üï{—sÆñY¿þCX–åOÚH§Ñ/?ÛÕÙwúé¼xÖYì9è R$Ù?o=Ï>{<²X,F:æá‡ÁŒ»yùåÛ¹øâ{Èf³œôãóìü4N=uϱN;ÿ­Üü—½Üpƒ/ôþ÷Ó³xî•?rË-W–¤Û·¯Ûö'Y€Í~´ƒŽŽÖ¯_O[[[!5ÜwßæBXl_DÔuøâ¿Ø·Ûo÷EE˲˜3çE>þñÛ±m›+¹þúL&yðÁƒ+Þ'ៈ\ÎC'ÂÈu@ÅN¯D6› „ӨØìêÇ8—ËU sÍfWåjH§Ó$‰ªÒN7Ƕsæº.étº¤CgÛövW“®ë%“l6‹®ëôööNXyUGCÍl«´_÷‘G©wóNKlÛFÓ4âñ8À¨ÂcWWWð#gYVÅ5AAAAh lÛ&‰ž‡a!+“É`º®FK<ËÇZPáV§šð¸'•ÊT^ßL&øã¥JÀ3 ƒîîîÀÛKµ¡iš·¤Zü1š¾¾>4M#ŸÏ“ËåˆÇãD£Ñ`\V­—™Ïç‰ÇãX–xg*±¯|Ìв,²Ùlp.FÖ4M¢Ñh2V¥ÕuÛ¶ƒmê>ÈçóA^áu7Õú˜jLز,lÛÖòŒÇãwY$!am• ©Êæ8N L c'‹/"Žô4Vò)µðÅE¸ïå—Áq˜ßÖ¬ËضkÑ#$~à ¤]Ó4yö¦›ˆÿþ÷†mþ}~U5žíº08x0O<ñ?~Ù²YLÓ ÒýéOs‹e²ÕJ“°råJÒé4º®så•Wò‰U¿bó+ã…_ÝÌüÇÌ›7Ïó˜5ëë€ÁìÙ³¹ä’Køõ¯Íw¿û]n»Qƒ]pÐÃûxÿ»C2É7.¾˜×[ðÕ¯.`ÆòKxë’GÀ¶±l›ýû¾òÚ4Kfýé4kÖ|››oÞA$ò7Üðs"‘«0 ƒ¹sç°jÕ¹ärÝlÞ¼ŒÃžŽŽ³™=ûwìß¿’{îI),ËÂ4MÂ&õºë¹é¦¯‘Ë=Í /|/~1Ë!‡ÜÁsÏ=Çš5kÆý<ˆð8Å(·ýîîî’íá™'êC¥WB$,úìºn0»%ü£¬f®VxôÝucC„ЩXH9üC¨Iì+G…?¨¶C”Íf‰F£C]ðÄUÛvuuaÙl6èp„QŸUg@Ó´’xÝj¦ÊWu–T™Õ §°•Éd‚¾•€¬iZp-Ô}N§‰F£†A.—+¹g”QŸ]× Bn躎ã8œx≓zm§+#M*°, MÓ‚k¬:Žå¨ûJ-®®Ò—^AAA„æ'—Ë•¦D¯D"1d¼a"ÅÆfGƒ™¦|N&“,X° øÂŽjMIåé—Ë冴q426êº.íííD"\·’RÓ´@ð ÄÂØøcJø‚±Äd2I4¥»»;ˆ’å{8阦” üÉ骜JøÌf³˜ÚÑÑAWWW 8ª±ËX,Œ/…Ej5&«DÈD"eY5 Ó‡ÊÂâþýû«:`ðàƒÁuÙýç?cœvmÙBÏwâ¾õ­àvþ˜qT׉ë[$ ¶mÛVX£:::Èçóüú×3€SøéOïîx<ιçÊ­·ÂÝwßÍ'>q àß íífæÌ›8ûìcX²Ä Ʋ?ð_ý—'Ÿ|†¶¶6Ž>úhvìØÁ¡‡ÁâÅ×38ø[:.»ì2Çᤗ>È9dYˆÃëg¹Çã¯{˜L›vpÿiíœvà l=ø`æÏ¿ŒÏ>ÝÅ-³/æ;okã¹sÙr÷Ý<õ\'7®¸œ“?úŽèóC•Z6« ‡îLÑÞu>úQ¿ÑÎ<móë²ì"Œî¨kôÀN8Îå¾ÇOâ•Wæ‘ÉdÈf³ô÷ïÃÞ܆}Êe´¥çyžiš%iÂ×ù’K.ó=Ü Lf½óù|ÅgIQþì«{FíS÷¬®ë^>Ÿ÷R©”g†—H$‚û[]Ûðý­îÑ0êþ„‘¸çž{¼«¯¾ºÞŘr¡O Ät}&¦k_H†c:>Óµ/$Ã1]Ÿ‰Fé cMÂÄ000àåóù!c„•Pc/Õ ÆîÊÇc‚mº®ãzš¦ã•Õ”7<Ú××çõööc~á}½½½%ã}}}^___ðÙ4Í <š¦ã•£qÌ1ÇùL'&¢/”ð<Ϭ°|ÞÃó<­°¿Ûó¼¼çyxž§þ…¿xžG*å-¿áì>Ÿ÷ޏä/‹y³gÿÎÃK¥Ržçù÷™¯xÞi§}8Ð4Mó.¾ø xð2™Lpß¾óÿézèÃÞ¿þë'‹åN$¼Oü¦7c†ë-_~ƒ—Éd¼X,晦éýÇ_á­šócoΜ÷xmmmÞ³_ûš—ïðïô ÏlÞ0 |}í%HykºÄó ÃóÀóÀÿk"á‰ö—ï´Óöxàysæ¼Çß‹y·žt©žg’÷‚¡Ö¾>/æTv%ÏSïõ Ï3èõòßþSq;†÷©Omñ Ï‹ÅüŒ/¶=ð¼ü‡nÆkïŸ;¸®xÞ™g~¡0þ^ÔÔg_¿ðÓªcýÿ¦F½D"áýæ7çI¥Ÿ÷t]~¤º»»+þP*#¥D”@tN«.Bt]/Ù¯~°üÁ „>%°ªãðqêÇUíSâ™bßú«þ— @aWÕ[é/•J¢.•šJ¥‚öWeTiøÁDÕ{Xá1ôß,¤K„¾‡÷/zê)oÑ÷¿ï™¦éåóyoæwx«®½ÖÓ4Í›9s¯·lÙ—ƒñ`5¦žwÊ)ŸÆ ÃðæÍ{£7{öÓ¤¼ÞÞÞ`rÕWþÒÏ{ÛÛ¾äy^Q¤>㌻=ð¼³Îú½çy¾V‘J¥¼+OÞà-9èÏļx<îy‰„—Ñ4òx^òu—y^&è½^|ù Þ_sQi3MõÇÖz{=¼?œ|²—X~ƒwðÁ{¼“OÞàyѨç%^þ³wzàyQº½ÄÅÛƒvÌ_ùKO›ó‚W.Oôõy^&ãy}'œï…‡Â3˾ì%žwÄ·xjHV×õ¢ð˜÷Ç[•(ož¸#:óy_lô<ÏÓ4ÿ{o¯ç…%ð…@ÖOsýõ¿+)ŸÊ',<®Xñá’ýÊœ„?+á1|ÍÂiTžA]3^IÙÕωiú‚fø>ñ<Ï;î¸_x‹}¿àÌä¯ÒäóÓ'P«S„=Ìb¯á𘚦ñÌUŸ¯wñ„*íZ©e­ ÃÆëÉHã“ÂÄâ–}wÇ_w°€ZMÑA­ª ]øüê;î`æ£ã„KÞøFÎ~õ«YïºÀ/>Ã8 (®}ºbÅ §`Û×…B [ÀbæÏŸ„ÍçóÜ|óÝ,\¸x€3Î8ƒýû÷ÓÞî/vçw§“H$èêê"úšÿfÛ+Ëw¾S‡l–׿þõ~ßLþåR¸ì›ÁYè4Ž:áõ¼ùݯ…8 i``Aì‘+°ßw5är¼pÁœvÜqüög{Yºô¯,[¶Ìªë Ÿ €¾è9œ?½TlÌóÎÃØé" —󷹯úW¬¸ÖÀYþlÎ<ó «ÜU+WÛ¢Y\ªt 0M¿XàW#4´ ÀܹsI$Áš‰¶}FÉþ®.èîöóñ<˜={?ûØÇ*Þ;!™!´ÍäŠ+Îãë_W÷“ÿWÓ ÷)/“_ŽâçðÐðöíÛÉf³lÙ²Ÿ‹/¾˜ht>ŽSÚ¦†=VÅÍ> "¥ú1µmMÓH&“™J¥J‹ViUÝ¢Ñh°¾¤aÁ£Šm®ê¬Òg2™ƒ¡D˜ò¶WñÜU¬üj~pÕùÔâÝ@'½’˜£DÄ®®®àúš•,F(ÿ0ÃuB2•¬Ç0(17,¼ SƒºßËQbxù½ ktªûL-ò].2Ádõ|¨{]¥Së„ó.CULÿL&¬û©ò›Šu]AAAaºbYÙl–|>Lè·,‹X,†ã82y¼ÅPc,²çô¢|ÇráÑ-üw _|T{M`Gw7/.øØ»1 —E‹qÁI'Ç¿éMoBÓf•œcóæ6` [¶XÁØ»/ïê{N†ïõò Ê[Ùqº»»¯gÃ0X°`A0iAyÈZ–%£ ‚ ‚ ‚ L *8 „ÇûÔ»¼ˆŽ­‹83÷íãÅ9s_t´ñ…F€—7o¦M×áàƒÙxóÍœxbбmßI@7Û6Ìš5kÄó¨±Â3Ï<“»î‚hÔ ±‚±Êy‡úBÞ ‡ƽ÷ÞK*cß/~Á·ßÃûÞ÷FN9e>$“è©_»â âß<k¼iæÐÞ¨Y¯6ºÀþp  \¥RäóšHø"V,†iän›ƒ¹útôè™[Þ{ß»œlbQ õŒD``õ+ÄÞø20³P7_Ëì耢@‹)gÉ9¥¢d¡­LÓ?NñøãG”yúm–Lúbž®—hÅCP‚^>O( ¥¿]9x*R) §ÿýôÓg–{•èYÖÐíšæç‘Ëùóyÿ<Ѩ¿Mµ"™¬ìAùÃþ_¼ ×=/8‡iúÞétÑ[t"8hⲚ89õÔSééé²oíÚµœzê©{챬^½šþþþz—œººe(ñO…, {ùY–xåóù@ Na¯Äp?\*„§Byb•{\E£Qt]Dz,Òé4ñx<•gd¹H§i¶m“N§‰ÅbÄb1òù<Ñh4"•x¨¼%S©¦iŽ(Ø)ªõF¬–®®®Ae"fÖaˆF£$‰ªê;˜¦Yâ¥Ù¬4›P3Á•ø +è)ÁQ]«Ñ^4R©T¦x4”Çc.— <’MÓ¤··—ÞÞ^úúú‚ç<îu8”p™L&ƒú ÂTÐl¶@„Éa8[ v@¦Ò'šËضMGG@0Øìc5‚Ð4ª¨4ª¦œŒ^¼÷^ÊG”•·á—_ÎàoË“ë×£i .ü±DˆT¶Χ„Í®®.,X@WWר¦ZWhmšÍ‚09 g ÄÂôAú‚ @óØõN¬"…år94MGA˜šÁüøˆ#H–o,ÃR#t¶eaÛ6o™=›9÷Þ²ú±vË yphk»H•,£¦Ò~øÃ[9cÿþ`´;îøož}öPÎCç­=Æü²í܉áä0žù•ÿ½àõÈ“Orè!¯æ‚Ç¿‰»ò-þI ,@Ÿû7ôÝ÷—..X@Ó*„5 ²[ßU"Ü©õ ÃÃÙaÏFÃ( d¦é jÿöÞ>NŽªÎ÷I LR#+‰q$Tˆ ˆÔqP¢kÙeí »Š{MîªÑÝ\»utåçÝnÍ]A÷ºÛ\Pñ.3½¢®‹Âvù•p YaDR†HPH%!õûãÔ·êtOÏd2™™žIÎûõêWWWŸ:uªºûô9çó}¦ÕU=伞—Š„®›Š‡wÝu2¾ŸÖû³Ÿ-”0'õJŽE©§þžCmXRÛVû-Ky' ®›æPÔ=7uô×…‚-«V”®žW+T‚C]w¨è*mo´|Ú(œl¦ù#ǃ)%< P.—¹ú꫾788HGGG²¯­­eË–qß}÷5­Í*¡Ñ~eñ_A×uÇ5¬¨Ž hÂ0< ø'!XG#~X–•$£‰‰¼¶Qß63¨›^L·~ ««‹îîî!¿s×u'Ô¸`´H.×õ¶mS©TèîîÆ²¬DØ«V«5á  …½½½IîÚÎÎN:;;“\’–e%!ŽePS©T’>±»»›ööv:;;ÏÉJ¥’°…B\.×Px”p¶"r.Y²„ LØ×ÔéÖ †‰a¸¾Àôу ˜>}A5©‡²Ù,¶m³yóæ 5<6ަK?ðßôGIÕŸÿîwjgàÇíÛ¨üŽ;vìHÖ¿/^ÌE]”¬-Ξ={È:^½!Àí·ßžxJê³®®.zè!|Ö­SíXç;Ìå2üóœ|ðíogAì™Yhû¿Èc?ö¥rÅ TfËÈtîÀš÷þ :Û¦põ ¸]­pÆ©"·]ϼ0ŒE:ÇQ¡Y5fÌHEÒA%k@=ž|òÉf7¥!Ù<ùä“lØ°ŽŽŽ!uŒÔ$œowwwò½›*‚·Šžçh Ífñ}ß÷)•JI~ÈF¿c˲p]—b±ˆçy5ÞÒ¶m'–¹\Ž%K–$ýa†IÒ|>O©TjèK–,I¼.]×M„K¡Z­&ž’A4Ì}9šþo4ŒW=S‰ 6°uëVZZZšÝ”†LƘ ¯¯õë×7ûR †¦188HOOwÝu׸ü'N#õ‡:&رc6l ­­mÂæÃt §§‡ÁÁAvìØÑì¦4d¢çwÝu6l`õêÕ´µµ5ûr †¦aæã3?¹,¨9+¨9²D ëÕÝ` †)†Y3¿5Ãm‹Ñr×]Àž… ÕÎ|žB.GÏà [–.ÅöîÝK¹\Ʋ,, ûÇ (qèᇠY[´í¡i žoµ³à¹«‡§O|–79þð»×Àðº—^be>ÏÚÛy匙\2ãnÞ¾®¼‡|Ïëð[ÖãíZAö†¥†yA`Ãüs¨þlû"°. R†àñØKNcYd^}/Žs&ž§Ä°jU bEÌþ¾5=OíÏAñTÔ½ø²Ùôµ¾ô©i¡‰ æº[¶¨]wÝu\tÑEÜrKš—QÊ;Žz çëШ­’W±~ Qo_±¨ÞQ6†–ÏÆFçTy*k÷çrÿJeiWr>ަÖóÔüàŽ;î8ä1Á”ñx,—ËÌ›7µk׎{ݳfÍbÙ²e,_¾|Üë‘A(.Íâ°‘ÞD‰}ú9€#ÖH®ûp •¶¶6:::8þøã›Ý”†Ld?püñÇÓÑÑ1n‹ ‚4“É ñxœ*è¹”o²··7Éí*֙ÑÉdÃ0±ÞÇ¡Z­&¡–ÅûyóæÍär¹dooï°ah%µïûIý…BíÛ·EQ%¥r]Åbß÷±Ò÷}ÚÛÛ‡|^­­­I­÷"bŠ'¦„|mooOòõ6‹ÿ?ŠñvärüàØJ]™ŽŽN9ç^š7¯©×6“1&˜ªB‹Á0YÌ›7ŽŽ-ZÔì¦ ËDö³gϦ££cBæÃtbùòåttt0;¶‚ŸjLôü`Ñ¢Ettt0oŠŽ‰ †É¢££ƒeË–1kÖ¬f7¥!Óe~P,c[·&ä Zõ5kT†©ŒY3ß5Ã]»vñëÝ»¹»µuÈ~|ŸÖ»ïf[߀‚Ò P}„ç5ܵëÔ!}F½7€ï{œÏésÿ‰_ûgïßO¦«‹Ë.û4O=øZ{â ^hkãüóϧ¿¿Ÿ—s ¿~z1EoãÅ·¼E)b® Û¶á´>¢ê|êdUy?>N’ò±«K?oƒ‹vìùÛG.S‡äkΩQ·YÆUÄI¨õÚËçkïW}{žxb/_úÒ;)•††/å1èû©( µ˜õÔ‡Œ$¿¤6Vhäe˜Í6}¿± )u7:ÆóÒsú~zßIF¶­êX¾|ù¸Œ ¦„Çc__===Ü|óÍRÿ±ÇËk^óš†Öãïûär9²ÙlâùØ 1B5aNI1d¢m˜Ù#¶¶6ÚÚÚØ¸qc³›2„‰îæÎ;®bƒïûCŒÂ0œR‚¿tEý_rFû›‘\Ðûœ\.WFu´ˆHy ¶nÞ¼9±*-—Ëd2™!ùÃ0¤\.S,Éd2äóù$¥0ÿ”SXýÁ2ûvνðBž9æ¾÷=öŸ}67?úhâAÙl6s­xD±ëž{8¹¥…GO<‘ý--8€Œ™Düð!yÏŽß댷3(a1äN(q1¹·qâ:ÂøXÙçÆçrãséã¶@;.ÛÑÁWV¬àÍ}}£þL&‹ÉáÑp¤ÓÒÒBGG}S°€‰ï Dx4ŽtdŽ|¤ÎDx4Žtäw0½Ÿ§Ëü@æÕjµé)W †±`Ö }Íð…^€™3Õ Çá§÷Þ;¤Ì‹/¾H ð»ü€½¿y+ ÖñõÕ¸0„“Nú)¶ÝØHR̵êÜ—ÿ_ü޽÷^^{‘òH¼ðuÌuÿy3gÎaæc©&VëG¸íNá–?8t¾ò¥Får„/Û‡uú"\Æß·À÷qð±mË*Üe2u‚¡ãP¼Ã¢€±-ëÕ/%‹iPÕl; ?ZïÝØH`Ó—aÅ+² SkYsçÞÁ‰'¾ÄÞðy‚`1Å¢:NÏÙ(uÕ{:Ž3]›äy¬Ç²R}×ó†÷¢Ô?ñòltŽF¹ÅR?f8ñ2“>ï£ëªùÁÎ;yL0e„ÇyóæqÕUWÕìß°aóæÍãúë¯Oö 'CPñt”|fº‡ŽˆÍp”Ëå¦åZlrßýјU¦ Ó¥ð}_…@&1üTÌ9˜Ëå&ÜËz8&£ÿ³m›(Š’W|éßàÚï}€M¿þ5¿w/§ÿÛ¿‘¹àNüÔ§øÑ–-üåi§q÷ŽÜ·`¾eÑ ”€ÿ%ÒåÎ;Ççxõà /¸.GmÙB·Ä5¨TÔ?µeÁÙg'í9z×.NÞ¿Ÿ7w?›5‹˜¿};6ÐÚÚÊ?=ÿ<3fÌ`w<½|ß>ÌšEžÂºãg¨NÆQñ|, ‹âé¹ø9+×— â‡x@^ýÀ¼p×]pþù“÷…Ó¥/0 Ëú±t6ý€Ápøbƃ¦O_P©T’¨?ƒa|™.ýÀ3Ï<âáhY|û±ÇÀqpPë4a²k×.-ZÄÀÏÞB/^Œmת@Ž·Ür޳ áyòù|ºùëŸùÿH¶£å¡‡˜{ǼüG?ÂæO9ç-;€Ô‹³ü›7qÏ^ÅI³f1ÿ=ïQ*šeÌ<çì¥8gƒ\Øu±?uj"œ5ò¶ëì„íÛcÒ²°ŽÛ̶UùzYBÏuªŒˆrz.Gú%~Ç©Ý'aX¡6_b=ž§œ%.ºè"/>Šlvqê4$ìÈç¡Õó†žK¼ûû‡?‹~:ò~½ÿ†ÜŸF¡YõóÔïoD½È*÷q<ÿ¦„ð¸zõê!}}}\xá…IÇ ïßwß}5E__«V­jJ»%üžmÛ„aHWW¾ï'ƒ Çqš:à¼hGš×Ÿ.i×>™.ý€ïû‰'±„@¦r’øéú[1MˆòüË¢<õ±N€Ò°måIhÛ\ûéOç?M+0{Å 8í4N\¸"œ|2öÉ'ó~À]¸%Îyñ9l”˜œïèGåG[¶ðÉ;ùÑÒ¥lÞôüóô_~9{Ÿx‚íÞÍܶ6îºë.æ¾ð¾çñ/öglš=›K—òÅ|„_|ó›<tårxqœ° zã·–eñÔM7qÁ©§†!ÝÝÝA„·- ”êFòO“Œybc˜šï©˜Yúvîd*ú9M—¾À`0L,ê L?`0þ˜1Á`€éÓ4Šˆd0ƇéÒÔ³eËŽ;ë¬Äh¼°¿iéRz<ȱ`Á̆!U—.3ì:cø¾ã8,]º~ƒ/¾ €7¼á pÇüÑþ¶õ2v<=_N®T´ÂxúÔSÕþXYˬ{öò¡¢^宓±ßÚ8ªm“xBÊTïwÓðœÕqj…®z1O„¿%K”ð'ÇIÈÑÍ›U9Ý[R<%ÕýHŸúvÊk×U‚`ÂâÅH§&íî­ %«¿WO¡ ÚX.O+•ZÑO±ªç{”{Q/JÙr¹öšÅ+ÔójÛfYCSÙ¯ ¿z;:;ÕëƒNwÐL áQ\¹ë©±¾zõjzzz¸ð iiiaãÆ´´´pá…Nz›õ\Ž®ëªŽƒØ5:þEøk™LfRòINUÂ0œÒB¡–éÒÈŸ{£0ÆŽã$¿ù#1ÄñÁ Þw‚Å’Á©Ÿ—Í2Í‹ßÏÅeE ìÚgÌàòßü†ΘÁiŸü$Õo{Ä6 k&ròÉê¼`ñâô=mÛY±€ËÎ;…Å"•J§ZåûÿôOô÷÷ÓÝÝçy”J¥$Lm†‹Eº»»“ЯŽã¿Îår5ÿ3IîL˲¨T*ø¾O©T"ººº‚€¨Ñ¨CîÿóÊÕ™.}Á`˜XFÓ˜~À`8¼1cƒÁÓ£/ÃJ¥B©Tjöí2K¦Z?¢Ö©êWþvíÚ•z<¢Ò;y¶ýÂs¼ímó‡ì+”Èvô=Góø½÷â8=Ƽ;8gÆÝÜ>ks^ñ ÎÉf9î¶“ézñç”ï¾(MhY°r%Ù³àÌ3gÔ¸ÛŽƒãÔyyþ9ÎP˲R¡R„0ýXñ”ô}%ƉG]½oÄH¯-KÝÒÍ›k½%%Ï£.ô¹®:Ÿˆ’™L­@×Õ¥®ASryx¡±¾koÎF²ƒ„t­'RѱXTB§~-®¿Ñ}9¿˪öøCeB„ÇÁÁA’Ü1ãÅúõë¹âŠ+¸ä’Khiiappõë×ÓÒÒ2i7LÐÃxŠØÐ('ÙÁx<Àx~öÃå_;R8ÃÌ 4»‚Ïó‚ á÷KÄ£ÃQôöICxV:ÈÊǯKq¹0ÞçÆûEL´ã÷…ú|ˆ>©WžKmžÂ‚öþpè!H/Úº•Yž‡¿{÷¤Þ+×uÉçóI¸Çq诵IîKÉéû>•J%1©¯ X,âû>íííêþÅåÚÛÛ Ã0És–e ÉïY©T‚€÷½ï}¼ò•¯œÔû2ž4»/0 ÍÇôƒL_`0Íê |ß§«« Û¶XÃaª0Yý€JS­ò©ºó,¸è"¶h¯õj'ô8O?}Ž3oÈ9¢hþ}’[°p×]xgŸ W\Á¾W½Š%¯{‰S÷?Ï’³»Xð‰O€ça—‹pÁ«q¿ òÿ_÷ô·¿Å»÷Õ8Î;T¥ñš’H#ùQHAÇQâ™ëªmñà«÷¿Òëû÷ ¨ ¥ªK'Õjvµ>i½ý|µÚXø“s†¡:F¯GDÁ\N‰€"‚f2©—e=…tw×zJÉF²O4¾‡¶-9&•Pª¦<‡äÏÔîïX%ßWísÝÆ‚çxsHÂㆠ¸õÖ[Yµjëׯ §§§&Þò²e˸úê«:–ò<0d_KK 7ß|3}}*8ÜòåË›6™ÜnZµX,’Éd†ˆ #vUËR,Â勱¹··Tâ…îàã?‹Ë.[…ÌßÑàºx¿ÿÙWã,ê!¸øãرjå†*\™ yñÚ¹„ᬋZsÝÞPA°>t¨Žˆ’Ž“æCÑN/#HhQ¥Õjm˜PHEØFKnâY/ærª=å²zHˆWãtAP¿æz¤Îƒ SšÉ¤÷w4~RâÙ¨=åòØB¤ê_³JEµg"ýÖÆ,ªsªÿ~U†Ùo®ëÖäÛ4~4«±Ç¶í)çÕ(^Ó”øV&õ>¬ Eñ¬††°ãgñR´ICœãmñJÜ—Ó½ëÛ å›M³?ŸL&3¡ý^¯xN ¶mãû>AÍfkÞ–/_ž Ƨ3Íê ÃÔÁôƒL_`0“ÕHÊ‹ÞÞ^³öd0L1š9&سgOCw8ʼnÁ²,ž~zNC/»åÇÞË][Ï„J1Uö‚€RIyßý¾­ N>Ïó¸÷ÞcÙºU…s½vݺT½{õ«ÁÿÉWâmn%ë8à87=„{Ö¼¸=zÎÎN•±^„ÌåRñJÄÀ €ööÆ93Õty4BÏÕ8\¹ PBYª6Jùá¼ŃQÂÁ¦Ÿ̘‘ "¾úþÈ!H‡ óù¡"ípòP½À†i(ÔÑúMår…ÐÑ¢·a2üfŽËA»víbãÆ¬_¿žk¯½6ù1÷ôô$ûV­ZÅÕW_M__5Œät”o®ëR(p]wÔá<Ò…|å-$û ã‡eYT«UãñhWÄÛ±T*5œXLôdC7¼ñ%¤!K½øõTÄÎø½Öøµï+í¤}ŽüfP!J{ãíͨ<‰¥x_ü,‡ÃIz6SCtLî“ï7Í µP(P­V›nÇqÂ0L„rƒÁ`0 ƒÁ`0Œžç‘ÉdŒèh0¡Œ´–ßÒÒRåkûvؾý-^èHk5'?ÿ µ! - ï¾twÕWþ”;_ûZþ~ï^ŠÅ"ÖÑ{ö¼„J™ ²Y%j9{~NðÄ¥:Ù6Á£G׆-ÛQïí'àŒ©ØeÛéþÎÎ4ì*¤ÛºW©¤^’£Ì$©Ö, OZ/JÊëB¡V”Pªr96:g¬ÉÒhùn¸œÃ}|…½‹Å´Î|~ô" „º+âé©_ûD2&áñ¾ûîTÂV–-[V“ìuÕªU€ò†œîHά%K–$1™…‘žR¢n”7R1~¯‚a<)•Jf±Ý0îø¾Ÿx7”Cu"ï% v¡ú wÚ‰2`èFyL»(¯ÄþøQ {ëÞ+Åï—Py³¤¤?2ñÆ7ídgRu˜cYV’ËÑL„ ƒÁ`0 ƒa|ñ<Ï̵ ÃP|ŸE}}ÉšM*(—•¨e}àÏðŸ^¬”8ÇÁ& F‡[R!±ÉèûJ÷Ôë)ï#Ô •ºð¨#ž“Ã…h­ï,K £±;"âéé8Ç7mÄ¡„(*~RSRx”Ðlõ1’ûúú†uežîÂc†„aˆïûضM¡P¨ ãWïÑæ9O¤|¼]@ TçÓ‰ ãG³C,O|ß• =^Âc™´oþBþG]TëÊ€Á%%ÿ¢…#u¦–GâD¢GÚ„Ðqœ$̪é ƒÁ`0 ƒaü¨T*„axÄÍ3 ÃYÞ×Ç¢[nI^»À‚­ð skʹ®ËÛÞ¶}ØzžþCîú_ÿK©g§žš¼gçóµe ”˼lÑr‚/ã䓟"”sÄë@–ÎꥵbÞ‰'Pp²¬Ô›PBªÂPÑPº@ñH„Z¡/“R©V|tÝZÀÎÎÚ÷,K‰zõžëÖz<6*£3Òò­~¬ç5Îíx ÅóP¿ÿcñ—8”Àjr¾ú0´Á˜„GwíÚ•ì»õÖ[•3JGÇeË–Mì•L0ª¯\.cÛ6¹dõQB£?2¤"BŽÔ3©Ÿás¥ †©C‹ÅI™X„¨p¨Ý(ÃÕdQÞ‹â©hÕí3Ô"‚Û‘èõ(2¥’ùf ƒÁ`0 ÃxR©TÈd2ÆÈÓ`0 ¡cÁ‚CøðÚ;aÏž…@bÕ²,¶m[ÔP<{ɹå–ï³ô(%ßܼeKòþ}Ͼ‘y==üŸ™3yéÎñ·-bÅŠ•&qCQ—ëÖ…?õ¾†=ÕE©b±VLn‰­RQç«_†*ÕCð}å¡8Üym[½¯‡•÷r¹Tìô¼Ô»²P*4·–Ë¥uÆk1—šÇQ}~‡&ÜÉg0ÙÙ¡ä³MÚCeL£ˆ‹eí ù%´jýþzArºr |Y¾ö,!U+(á1GêiT õDêƒaê"¢ãŒÆC˜”<°›Q}†xEgÐ2E<ô§$â©~¤1ƒÁ`0 ƒÁ`0¾ïS©TFL¿b0ŽÈÖ3ÎàuGïâgý €ýû÷C¥ÂÜ^à™?¼¨Î%aJ¨Iííš×akkÃöëâ¾´)9Óö©g}ÉIò úþÐЦ"~(ïaz‡sÕ½+ëi”'q8/F)§ç;K¶6É¡9J¥TôÌfG/JXرúW¸nê-Y©8 í¡rÌXjiiaíÚµlܸ1 »:00ÀÚµk“2ôôôÐÓÓÃÚµk‡„enxÚ7~8‹&•­€s(ÑQ ôïq½kcGwKTƒÁ`0 ƒÁ`0*ÝÝÝd³ÙQ¥a1 ‡7eTºµlP©TÀqp]W9.Õ•miyˆùók]G @º€%Q»"f@5â²U«hݽ›ßßû3ÎÄæƒ|™7¾m)ô„Ëá—NÖVr¹XHª¨3ëâaÍ’XkkÃ0¥ù|êQ(2ˆÔ!Ý]6›Š^ºÐ'9=¯±ðX,ªú%lëH‚x=ÖûuxžªGöëï' iΟ5õär‡îix(Y¶Dð”ܘ#<†áØ=ƒ`âÅF1y<¬_¿žÏ~ö³Ì›7yóæ±víZÖ¯_Ÿ¼¿aÆDtÔ÷OgÄMz¸Á…H“Ýñvåɨ{)ä uäùä SÝS®\.ã8Ψ'‡*r…˜ðËãþ9˜I¡ÁpøáyCïÎQ£ ƒÁ`0¦Aàû>…±º¹ †Ãеž_©T’5D×u‡xDû>¼ðÂY5!X“:ê„ [·0ƒˆ¯­û7µ´ðÄ׿Nkt ×îû>[[ÛSUmÇhmŲ”gcxÁ¥I½R·ž§‘™3)—Ó0¥£A–×äA0Ô+1“i,jÕ_r}¨Õú`]rëêërÝ¡y å•G«~íºª¼ã¤¹›éÀ®‡¡ # ù‘ ‚Tpmž6aœÖYÆ,<¬^½šë¯¿žë¯¿~ˆ¸¸~ýzxàÃBtÂIâ#§¿ § ±…ÊÓ”w£ƒ £j0LGŠÅ"ùøŸð`“ÆÛ‡böcd²CÇqœÄãÑ`0L_°±5¢ž>Ÿ¯MJ?Ý8€ªO ƒÁ`0 ÍAÒ/™ˆ:ƒ”*Ìê¶ãŽKöÛ¶Mº¶ç80sæÌ!}‡ïÇÞZŒÒŸï{ÉûsæÌQuÙ6·œ>§.Ú†ƒ×r‰Rô2²ç ÔxúûÏVmÓ„G=gbµ:Tì“6Êrf6›†ä¬÷œ/ÍúeÒL¦± ã¨s6²×h4ׯTT[ ¹\zŽFâ§ŽÜêú69Ž:¶XTâ«ruÂãGj﯄Ou]Á Þ P¹»« sõ‚–xþÉü»^Ô½u¯Äúyw©¤D³úýAÐXÀ³,uN=ç¢>‡­ŸG4ÏïêJç½zWìºC½m»±ÀzP†"Êvý{õx¤Â]7J,òQ‚`9}”Ëéý-•HÉšG—'Íå× Ö~àjRqÐZã2NüÜM*Xµ§m²ÿ)þN„À½ÀCqý]Ú5YªÎÙ¿›}7ª1cp]—5kÖ°fÍ.¹ä®ºêªCnÐTÄó<|ßǶmrñ7V¾[ê3 Qß õùlN63l1¦a&qÕuçQ()ìÊ!¬[†!Û̘ ÃHww:ÐEEÙ¶¬ÚÉ…L<–,QÛa˜NL'0èôz¡M&Uù|*TêÛ:z¸}»RIÏÛ(,‹Ô)¥ÎÎÚk•ëÊ石‘8©·ŽÈp¡VåX½þáDP}²g0 ƒÁ`80ym`'ƒÁ ì˜1】ς@ õ† 5s¼8¹â=_ý*WͺŠ ¶¾ð‚zÏ÷Y°à"¾ùÍ3q7—ðë&'uêÂc}·UîÔR޵¬tžY/Ô…¡ ·Z¿_ÎÑhI´¾©R·e õœLØ"…¥‹…Ÿ‰£ÎŠxׄ꜅‚v<$‚Ž~ß]Üe(¡N„¾|¼]D‰r­q½]q¹< k(¡O<Et,ÇïI=r ¶ò Ó2zWßÝ uK–ÔŠzz;õk•ë)‡Šºwg¤ûõãut‹Q=žÛR÷„Ô'ŠÃ…1^‘ƒÁ`0 ‡ïû‰arÆãÑ`0¤!Vãç㯸‚ã¾ô¥±W¨M’Ͻâãübß›±¬ ôGϰgáB¨TX¸p!sæÌI„ Ùl*öù~:‡õ¼Ú9¡œbÄÜ~1Ž4™K×y2&óWmk…½òC­ØG,.îU7Ìž ¹nu¬„nMnf®´y©ˆ{ñE9p;©ÉeX¼6¾" å¸Î%¤^„òùÝoìà>þ:>O>¾&ñT,£D;%þØuuwÇïñ>/~X(ÁOâíæâ÷Ý´ÎððÛãú ZÝrý’Ó¯ŠòpóU¹(ŠïQ|¿’÷Ãøœ½ñ³ï/Äç­ç£] ‚}ÀE@\ÞËYꘓ¾{‡Ê˜„ÇÁÁAúúúX¿~=ëׯ§££ƒk¯½–eË– ¹:™1cF"8‰àhÛ6™L&ùîuÆÏòª6»áƒaÜoÇr¼º;™9Ì4f|pÇx; ãL½§‹‹ºxV/Ö s‚„Vñ¼Ô RÞwœ¡‚œŠÅ¶k½ý&ä¨.ö¹nº]©ÔZcê–˜rÞ ¨-£_«<Ëûž7ÔTêÑ÷7js¥ÒØ»SÏmCïg£ýõ÷Ð`0 ƒÁ0:|ßO–e™üŽƒzÝíøóÏç¹3Îñ˜ƒØØ‚´*b‚6¡¼ñÊäÜs7E§pã·°eõjÈf¹è¢‹€ÔCPêÓ£éèó>ÛN# U*#DÜyH=‰'b¥UÉ(Ü­mËœ6TeüŸ[©Í5X~|%¦ü-ðߪLpC§îW¢6—‹ò”Ÿô}°[”Y Ö—ãÊ=è8Й#ÍsX¿Ñ Pb_,4ZOƒs"µáF»!w?vƇüŠwÄu>×SÑêrÁk…`µ\\üœ!Et½üWBïy(ñn3JŒ â×R^†Pý:€÷à OÖÅÇå¨ë!" ‚õû³q›]jÅ¢‰¤Õ¦Ö8_{¿Û«kÕÕ¯“©{=Ê0œþoÒïACce­Ý'?tòè*†1‡Z=\ñêV§‚ À²,lÛN<ExÔEîñ¬ SÇq¨T*“:¹0Ž(ƒ¡YT*©ÖÙ™†óÔC´ÔçgÄ;Q®årœgÁiÞEB'î —"#›%± R/ïyjâ&¡f*•ásFèç¡4›­mS&SÛnÝëQ÷’¬÷ÚQUó"FÊ=Ñs-ʤQ¼9ÅZU_¥~ýþI»¥íõ¢b}ûä8=$îp¹ ƒÁ`0 ©A²IÁb0Fbïœ9Àð£Ì´ o¥÷<ú(‹Üsâ‰Üþ÷Q*ÍgïÞÛ¹í¶Ûjêyný|yXGìmê©><«Õ7T¤ÌÎ6”8Ñ¥Ž‘T!TQ¢`8W)Í+²HÃú@œãÁ$ù$¨-Þ~ý`mˆ#½@œœ4$h ßçŸIC…JèR7~Ä¢¢õ,”ïò›HE:G+cÅ7®§ï?„ÏCÅfÊM!{ÄXríI[âÏÒ¶Õsâõêhå&×…íÛÕv}Ôªzv¾~''=~h^Fx†P»ó¶mã¡~/]¨ß…|ßsÍn¨Á`wdraÛv’ßu21[ Ãx çd¨ÉÏ ÑÙY–EàD°Ó-á‚ Ý/¢—žÓPÂäœâý'uIh—FÞ‘Ù¬€ë‚˜ä¬°m%–uvÍ·X©¤ç®TT~F¡^؃ÚðªP7 ‹ÛS(¤÷¦& óRÊq¶­•ÊÐû&¢£îõ©çkÔCÇÊ}AQ¿g®›~.r¼.òê¹-ës{ÈþJÅ„]5 ƒÁ` YÐC­ C=÷¬XÀÌ™'%ó3Ê5[qŽ»¿6DNP­ª—Ýye™:°p!VaríÚSjÒɼÒùqÂõ”ÍÆÆ³´ [Ó"¡»ÀºìÚñt^¿Š€ÎÚûyT˜Ô °¬Y0#$ é¨÷³Y(¼4<©xð‰hhƒýfÈ-D‰*§ÆõçH½¼2iä $U,H&ÄbdîGZY^/®ÆBN&£Ú*‚ð$/ûj Â÷iø}™(<fÌPÛµj8vŸ¾›½söÒùŒð8 ¾ïS.—“A¤¿¥ ©=Z!Ü`0LÂ0L·d¥¢îAªçzoMAæ®#å4 ƒÁ`0¨µA×u ÃÏóŒÇ£Á`‘½{«‰n“°g埑N’‹E:;!»è>üá÷²oÑ"öÌžÍà‹/pË-· ™/êéBä=×÷~µDÐÉCç› ï>¸èýW ήXßøÊ»*@‰Šh¯m°¾¹ùñ~É5 wå}Ú~ÑF]°óà|!~m£<3Ú5í|(€»¢~í>Õ‡†óüZ¬îÉ®yA-—KõßLF=&yÙ7¹Æ; ôûÔP°ÕxôCòës}Hç;æP^³fMÃý§Ÿ~ú}<ðÀ8Þ¦‰CµšÏç±mÇqðH½ËLŒGR¾ãƒ¡A$ ]€œ BŒÇ£Á`88ô ˆ¾ =ótêèž§„©rY ÈA=K¹l¶Ö‹Rê¨VSÏBÏK­uA1 Óº}?H‹ÅT4”ò"š¹n*JÄSÐqRcÑ\NÕ'Þ…B*Øé¡Hå~ÈDÃqT}"ØI{Ä“3—SõɤN<ÅÚT®ÁóRVð®;ÔÓPÚ'bªe Í/)ç–û&í·¬¡ž›õŸs±¨Î+^¥Ùlíug³Êc4ŠÒº.¸`ò¿³ƒÁ`0 ÓÏóÈår‹ElÛžt£dƒÁ0½8ꨣŠ9ÕOþˆÝKk'ë…‚ò$ܺ•yïÿ(;Îlå‘þ% /ƒA8æ˜gxôÑ“▕Γ“eÊ jñnÀ¯Û0u:Ëпø-X¿C ŽqNÄHBæQHÂE½?~-Y>ØCáݤ¡OCu=œèhðlèlWóÓ± QÆ]æÜúÚ‰nTÆ`˜ }Ád†iØMV„ C5(OÏ(èÝ”ä„Úò"*Ê$¨Ñà6—kœ P¶õœŒ–¥&:Ýݵ!=eПϧ!IÅcR®W’§ËµË£³3 %*ç¬TTýr¼<:w©”zEærªMºªOÒôð¥ÒÝËP?·~ŒLbººÒ÷‹EuîLÚÛSÑO¿2‰0¯¥Rêá(Ÿ_gg*.Y’z+ʹE•û("¥ŠAÞƒînU—xdJ¸×úÐ-¥’zÎçÕ=¸çžIÿêšõ‡C?`0FæH †‘iF_A²`Y– †&3ÕÆàCbk>šÎ³jˆÛçU#Ü%ÔÕãóÐCªß¹{÷éüå÷ÞKÿOàyñ|®^<ŸÎf¡ü—àçjÌ!ø_T¹#*Bæ `3àSà\Õh”¿Õw¡<uáNB§z±“c}(Ð ”;$zÒ¡p°]sýùPÏ( —Þf"‘u88Áv,Œ[ŽÇ¾¾>6nÜÈÆéëë;¨càꫯ¦££ƒŽŽ®¾újvíÚUS×­·ÞÊêÕ«Y½z5\{íµ pë­·ŽÛ ‘œŽjÑ-•’†|¥q;[ƒóO`ÝÃTfªô•J×uOçÉòxôIò7áÑpD3Uú‚‰D’y‡aêµX>Ôs*êÛ2X”|„²­‡ôu£œPkõçºCãÿË1RTr'êT*µ^â±)…™Lº­·½Ñ}6T*é£Þ»³RQ‚›\Kgg­Å£îEªwç’ÏQ®Y<%¼J¥’Ö#uH(XúÄRRÏ+Ùß_{O¤mR§ˆ’â!)¢¢.ÞÚvj…¨‡¯mt¯¶oOEX#圮›znÊ=[ÊtvÂÓOÏÝw’M_0ûƒÁp`Ž„1Á`80Íê <ÏKÖ³Ù¬Éïh04‘©8&¨w;ÐZ^µŠƒ@½ð}ÜÖ»™?g/§žz*ŽãðØ_ýÎ+ç`6ýýñ|ݶ›P9`;à‚{#¸e îÕñÉúÁßá↹êÉß¡Ní¼ ücPÞC;Æsã‰ðбO溇B6{påG#óñÎÎæ€Ðœóê†ÐÍ! »víJܗ׬YÆ ذakÖ¬áõ¯=6l`×®]¬§¥¥…µkײlÙ²aË 088HGGG²¯­­eË–qß}÷ëMÑ-šú×®%@‰ò;›Hbó‰ SŠ©ÒèV®ëN¨ð  ‹ZvTvÉ×l0©L•¾`¼±H<×`äÁžî©(èþFžlrœž{Q»*ÝY½'£”a°þX¨Ý.ˆˆh¶]›{B·¦C)£__µšzãAêE((ÑRꈢZëFÉù("¬ˆn²F$Ïò¾ÜÃBAm—˪þRIíÓïäŒ,—ÕCŽJ5›UåÅÓ3›Mó%Ø6lÞœ¶§\ÖBã ’" f2©jÛ©G¨„¯õ*• µ5¥­•ŠºF™Ä‰Ç©¼¯ËjUmoß>ÿ ¿Ï“Áú‚éØ †ƒãp †ƒ£Y}A†‰Ø˜k;Ñ`0LSmL°k×.~øáš}àÚ9µsÚ„»ïV×_ükjɼ|ö[fϦÚÚ ÀûÎxkמCá倯¢î”Ë(ÁààÔBâ þV•)¿ÊçÆeâùqðÏ¨ÅÆSãóÛ¹ ÿG­Mø>„{P ¹á×&$úP=‡NÖGtï»ÉBRÒ4#¯£ÎdævÔãæ±æÕ<ÆjÔìŠ+®``` ±"·f±6ïÇn¸!y¯zèÖvîÜIOOË–-K:‹;wÔtóæÍkÏùPÈd2‹EŽ}õ«Ù1c¨ß® Ãá‘æØÕ¿+qÎ]B”Èä ,LÄXEŽ ã}‰!JàhÇg´º=ÒܽB6®£Bmxmi‹<üñ;eC˜*ý€ïûdÖ\f”¨Ï+dÜà¢'sFƒaú1Uú‚ñF·d“°§úà^O*®¿§‡?­C*Bb&“n×çz”p¤ D1ɨ‹j²_B§f³J¸²¬4/aw·ò®Ëfk=å<"̉ǥx J~F]¯@½ÏK½=/m³î1(÷AD´3” '÷@cEð”I…x êÖ}Ž£Ú%b£ž‡RB·ŠPX?)ÏÎ\.ÍE™Ë¥Â§Lbäsêêª`E ”Ï]Ú.sP™ˆI¾Kñ¾ìïW¡]-K‰Žr­"ºê9=Aµ¥XTlj¥¨âu9U=ÔÈâÁtê ÃÁq¸Ž ÃÁѬ¾ ‚$¼ªÕ¬bƒÁL½1ÁïÿûÄÙª¥¥…]¨õVïF¸¢¨æÎ:™“~Š¿ç5ê…LÚm›ÿW¹Œ––?æ´K/`Qß"¼Pü=T°Ÿö¢tÏ£ç‚ÿGBr.F…hÌ€]/pFm¬/B{kƒ‹ÉA¨Hë —?Q_¿˜nd2jAæÇ“ènbÌ·~O,”XÕ­µÙޝGÚ¤‹›Åø|õŽ)Ç>û,Gÿíߎï‡7ÎLD?ð裲fÍV­ZÅêÕ«‡¼†afy<‰Ã±S$ý|ŒØhh&kÖ¬açΜvÚiÍnʈLä˜`Þ¼yInˆÉB„3 ‰)Â(ñ¨·w¨ÅŸxø , óyUg}~H=têpV„"XA:qÐóHêí ‚¡¹%3™ôzÊåTñP2ñº“ð¤RF<ùD°?Ï«õf”¶U«©…žx Êuööªçþþ4­ˆ…BºmYé³\‡Ô#¢¨xEê^™ÙìÐ$ôÒ6Éç(å-+õ<¬ÏQ*©|ŽRg¦at‹Eõ9J.GùìQLD_ðä“O²fÍ–-[6î¹ë †éĆ àÉ'ŸlvSØÎ‰˜|ÿûßg``€õë×èEa0î˜ùÁÐùçyÆÓÑpDÑÓÓí·ÞÊ£>Ú즌H³Ö uöΙÃö-[h}äv­X 50‚û÷Q`¬TuìÝ«Žo-sÿýª.Bà!TÕ d¿, ýßÜözÈ}åÍð0Ÿd‘1÷f°Îçù:qP3x•¨:ÂÁzÊœ}¬4³kÍÇ‹ó‡êµy¨ø¾zÈ:ÆdQݪò;Ô1Á˜„ÇÁÁAzzzX»vmCÑQèèè`õêÕlܸqÔüÉ÷õõ±fÍZZZøc?'žx"ï|ç;Gl+@wlV/a÷Ιƒƒ—&ƒ©œ×M¼ëô°Ïº7Ÿ¯=\”P«K7R‘O¼øœǃê'Åk/ï—¾L@'>O‘ZD +Åïw’ Ž.i=©ÇÛ&^†Nüº;®G<Ò¤]z]A ‹ ¾#n|®Ní}%BÖßK¹†F,‰ÄÇÖ ©åx_¡Añ5fâg¹—ºfùøãùåßÿ=|þócý:L8Ñœ|òÉ# ¾ïcÛö¸Y3ŠàXA}fýÏiÃÔàú믧¯¯ï s27£Ðœ1Áx ž„Ã…&áQùJ¤‘¬‘à§çpl4Ðî\:a¨DÂRI=‹5¦.̉X¦O@d%y&2™Ô³Q¼%„è’%C=#EðªTRÏ>Pu‰W¤xï‹©ðÖÛ›†x‘{$ŠUî§xærêü’»1ŸWÇI¨Q ã꺵‡U<@%¬«„`Ñs&V*iý3•°-úÄM¼]WµEÎ êZôЮr¯tAXþ–ô b©”–ñýÔK´Þb3ŠÔ9%¥„Z=þøã¹ñÆ·ð¥/}c|¾ðH£¾ ­­íê<餓&ÝøÀ`˜Šˆð¾fÍšf7eD&j~ðŽw¼Ã ˜ùÁpó»Ù+ÓÃ$"¹Ô1ÁÖ u¶-Z÷ßÏâºp«ÃQ$‡ƒó>œß?Àí¿Á–E/ã¬?ú žÜóIûÙ¥áî¶»€NðÎï*èu ¼ŸAÉûCÀÕ¨Åè`Az.g=Ëé\W§PPÞ~2G–¹£nÀ<D4+r¼Ì'Y_¹q3ºz1––T.“I±8LHà˜õëע`L9Fõ£–2#ÅRâò,‰bë/°‘kôxY&–ËeJ¥RšÓíK-_¾n{*,tå…תíëD‰t"Ðõ¢ßÊqÙnÒð’~ü,¢ ˆp…øá‘Šo’ó®eìQ@‰|Ö´ DÚ£Ñï´_ÐÊoŽŸå½^”X*a/Å£°¤µ+¿/’v¼¬ñék}Ã…çµY|Š=ã)ÑØû3¿?šog}¾@+¾Îþð‡Q~+&©Ðèù…%J·¢¾Ã9Òï­Á`™©ÐŒ"Ї]ý°"Ô`¿~ОÏ Èûâí'Ûúqºe¥.†Õ[\Ö×ÝÚš–‘og§zˆH'Ç9ŽòºÓC§ŠX(aGeÂRÔ¬ƒtÁTÚ&a\ëE: U*íìŠÃˆØ¨ kº §#]¹Þ¥ëÞõ÷XŸlØvšËQÚ+"f£{¬‡­• ›ž/SÄ>ñ–ÔëÑES}Ò¥¶õy5tAZ¿—R¿„¸u]%Úvvªû\*¥¡rä3 C¸öÚË˜ŠŒ¶/˜êý€Á`;‡Ó˜À`0ŒfôA<È2£Á05˜Êc‚ùóçЙÈ]ô0ÁÌÓ ÙžÇ«ž~‘]À¯ÿðÿøÄ·ó׋榋ñw£û~mº¬ÓIŒ‹{ÁÛ …Mv¬åiôzÃd=e‹.4êјFC&shb™¬ˆð7™ˆA²ÌÛõµŠÉD7Fnõ†âÁ˜„GùAÆÒXÊŒ¤Þzë­\qÅ#Ö#–Gõf__ß![<ëd2Êñ7~öìÙÓR(œB'Jü“G{ݾn”À(ûýx»;Þq­%Ø•H…»%–H…;ÌÊñ£—éëªÆÇoŽ·{IÃNŠÈX÷õ“Šl©øW"õjÔOÉCA<&·s`¡È¦ŒxrŽÅoNÄϱô=Î^Oe¦B?ŒÆUhBÔïFÉS麵fßOCŽ–JµÂ¢ï+oIÑ*•Ú܇Ùl*Ò‰@¦çÆÐïYoomx©Sõ‰LĤ½B¦ÇÖ&r]ú1ò9Éõêy7õvè©x‡êõÊg¢ŸS?F„\i£^æ@“"ñ>…T´ %@êíօΘz¡VÔLå~À`0ŒÓ}L`0Ƈfô‡º6`0Æ—)9&ð}lÝÊìÙ³kÖ¢³ ò*9oZŠ5ëyBËæÞ{ï…}6ßøþü w%Þ¯í$ÜŸõ8/G- ‚ã²@VËçžVäÿw­ˆ$óÕáæAP;ß„ƒ÷<CÖCER¨L&µip$…Ëd#FåÍûûÍcu´ŒIx”²x>Ž„”)¤ÙªU«Øµk7nLö‰;§~ÜêÕ«éééI’·nܸ‘––.¼ðÂC¾¡ö +‹þó?y¤µu쎑 Jü“G>~´’zÊ~Ô ±;~̈ß_BmÎBñôë'õ‚A1 #j½%„¨ô%"þHÜËzN—Çn¤:܏ޱŠ5b´q(CűžÛ& §Ú,šÐ_2S¡Ɯ߱Bú»+Ñ8L®Á`80S¥/+ÃY 2À¯© –ÙlšóOr'ø¾ ‰ÒÙ9t;“QBœˆu"îI(N%ÔJ±¨)ñlÔÑ…3PÇW*Ê+R¤V«© è8©—£x?ºnêT‘Š×^>Ÿ ›õ¢›_­¦§®®tâ¦OàÊåtrÍÍS iÈUHF¹ß"¸êág\7½îB¡ÖTÄE=$ª„kÕë±,%ÒÖ_Ÿ\—”•$îú_Ž^>›M…Óú¬ºªîm)ím$fÊyä¾êu¾ã?å„^û—~‚M_0UûƒÁ0>L÷1Á`šÕ¸ÍtE1 5LÉ1çqÇ[ÞR³KP¤Sì`w+þŽ% \vÏ,ýs^±ëM8³à‘gg$¹µ¬óÀnG-ÆŸÁ³€ åÙPîIë,”‡Ìĸ~‰³¾}zT¢CÉÙ8Ñ €'›ƒ q;^HžË‰fL9—/_¨¤³ʇÐÓÓSsL#ÚÚÚøìg?ËUW]E¹\fÞ¼y ²víÚšp®ëׯçŠ+®à’K.¡¥¥…ÁÁÁqK"ë×ɼÏ]tŸŸû<*ô!ä ”VHE ÙßEš›0 6‡\;iNE½rê79,s¤Âb3Å—fˆ"<ÂØ¼=_ætb*ôc¥›Ô»×¤ž7éÜÔ#âŽ.Bù¾ä9N:¸—¦.äÉd@Ïï8œáu(QPÄÅîn%Z‰¨†*<ªï§â”î9'‚[µZµ‘'¤¹3™Ô‹Nër ![(¤yõ$æõÞœR/Ô‚%ìi©¤Ú«‹r?ä^BmNMÉ))bœSÎS(ÔzE6ò”ý¿èIà‡›¨è÷­ÑÚÕp"d}ùŽèu蟡Þv=t­.FêB¥x–¼õ­wñŠWL|ÎÓƒe4}Átè ÃØ9œÆƒaì4£/ðŽÔxƒaŠ2•ǯ½óNÖ®\ Ô¦©çôc±íy<öØ1\pìy´Z›a;8s 23.´¼JlÀû%µ†ï." 4dÝ@7ˆÕßó¼t@¨OE"†¹ÐñM";5“f ÍÊò7YámÇ$ñT¬ÏݧOÄ P—º»‡në¶S<ED`”z3µÝÝ nâU'Ç iÛÂP‰’B·ê÷BÚiø”LF ƒK–¤÷¦XTûDœ„Úû¨ç. ô=ºØ¨OìäÜõè¡NÖx=7Š?óáî;‘®|£‰ÐpçÔ=ë…J]ø)‹ÔL¥~À`0L ÓmL`0&†fô&¿£Á0µ˜rc‚xBýžsΩYÒu`óÆ_Ä>~>Áoçº!ÇÝy?ÕÍíØC°Âu`å!¹Ÿ¥Övv—†÷‹q]!¨QØS}>N]Ûš)4 ýýª-¾ŸQO&…‚Z#ð<µ¶ÑH¼ êÓçLÒÿLcAYÜwß}¬[·ŽU«VÑÑÑ‘üØéëëãÖ[oeÙ²eôŠu)lë¡ ‚ƒ…Œ*!Ápð8ÃlO.©Ð<]¿»Íî¬Qö¼>Jt%:š)‰Á0¾4»/8:;SKBñ¬QO„2ɹ(!O\W p%÷¡ bZ¹¬ â™¦‹xž—Ö§ }z8P=¤«žËѶ•ðçºiž?G z¸X 3*ÉéE„Ó'1r­ú€¹P¨õº“òêSò&Š÷¤î§×S/Þ6 %#–z†×&ªp81ó`EN] =Ðþá&("ן_«Ó,Ëʱ0š¾`*ôƒaâ˜NcƒÁ0qLf_†á¨×FÂC9È£>•™ËÄD!3W¦Ô˜ Á$41ØýÕNì—ø+¿_ÄIýÇr!§cmÎ;Î&TÛ!{„ý`½IÍÉõyoñ»à~xèé%c¹<úy§ž¤™sB=-Êd“ɤQJ%ªY4Ó¾eJ ---Üpà ”Ëezzz¸õÖ[‡¼¿víZ²Ùì´°6ÔG;(ñQoj0 ’Ó·ߟé™ãqª0Gñtt0ý„Á`¨EòêáQET¯»»v†éDA餮L& šÉ¨‰ˆÔ‘ɨ‰†ˆQ¤ñÅb:OA߯õhÔCœÚ¶š$•ËéÄEÎ](¨:³YuÎúp¬¹œ*©÷£„Z•ëÖúÊõéIäësMÈýÐC¤ê蓱áB³ ·"÷ã%<÷4\›‡›¬5ªG·jœ, GƒÁ`0 †éH Ið´ç jí@RÙ¤"£—é<Ø †)M>¯æ»î¾Ÿcí2ø\žÿ:þ2~øì7`ÌØ3Â8¿ßV ö,ð„¬f ¬ëÏ:úüZg´Ý—Ì©§BÈÓÉB7¼–4/GÚÜXÖ—&š1  ÄÅõë׳~ýúÄ…Y˜nÖ†"<ê¿ÕÌØªša¿—)…äxlÖg0]s¢„7•‰C¥’¾WŽ“ÉˀѶaÆŒ4ç¢ç¥žr⹨ws"8ЇœäžÔó1JHVËJëêÞ‰¹œ ï"åäÚ%DªeÕ ŒP.U¿’ëPÎ+Û"–ê­Ñˆ‡Ã•™L«Â‰žÀLýz8àƒD ƒÁ`0Ž4ÜQ˜DdtqfÈqd§ 2Ž)üô§j‚üù<,pxû³ß`;pÏù»8÷[çjý8·p!ô œOÃEÆÞÞáç}¥Rš‚E'“9pøÐB¡vmArBN…Bí¼2ciýÞL§ˆ@ã¬ÙL4GWE5éˆÄo?„„ú~Ŭ/M.㛯s¬ßãÉ& ì+Z‰%Ì=6 )º`(Y=a#DlÔÃ¦Š‡d}¸ÑF!2G“Wp8±Nò.êb'¨ @¡†BÕ½5×U‚c.—ZcÊÀ]ϱ(í!Tʈ%¥xK6º—ÁÙìøXaŠ7瑆ISd0 ƒÁ0:¼F.D!Ð?ºPaT«@„JÅRňŽÃáŽ'Œ–y‹w(uí¦YûYã ûì±jáþ<`¾*fÛÀbæÍ*Õ¼»XjÌ,‚a=a8Ôx¸z¥üd"’$]Ídâ8êzÃP­/Lv~É©€ãLÎu›ð86làôÓOŸø+9D¶,]štf]fzÓìµD ŸÑÛ„sëë´æ{<6† §¢ÊY ‘Ç!ú¿YW0¦)²zhYÖá1xlå{Σwå ¸'>':ðTVxöÎy£Ëƒ»^¥:“Ó€‡¤®t]A¢ɼZº£ÎΡ¢¤>O?X$mJµÚ¦†aìThÃáŠñxÔ¸÷o$äð±:òQý˜áÈÄ b{˜› jr!ƒ¡Üƒar‰A}×Q.§¡;$_¡ëªþ@šJnEɵé$"ŸOájC¹B:Y²DÕÙÕ•†wÍçkC†‹©ˆ(aZëÛ^ŸûP!ëC§êíª/_¿ß²Æ'7£Á`0 ƒÁ0ÑÔ%Q¡U]`3ã#: †é‰ò|(•Jô‰nà?ô"á‹sàÄóáiÌ‚£BÙ¶Í#¬fż{Ô¢íB`Ž:TæÒÃyö÷7ÈD°K*‘úˆD“™Ž$“Qç×#@5‹ÉÎoy$a„GWìÝ{Ø…Z=Ü®Çp`Ä.ïpÐ'‹0  *‡ÃXC(™³Á`˜¾ÈšD&34ä‰ ^ÅQ&2¸®ÏÑ(õIx)é ZMîV«©˜)eôЫ²O·ˆ´mõº>ü©”“cs9õZÏ3 Çd­VÓ6(„Á`0 ƒÁ0• Ã'Üv£„Ç PbìaU ÃáAHêäcYVÒWÏCw7NëVrÇô`?Žê0ZaG»Ê ë8^øøåË^8—BáÚÚúƒ`è:¤ÆËõÈÜ{,N“)46¼—ñúE3ÖM³Ù4â“'#<¢D€ÏÿêW8˜„az“Ayåǃc¸P«y Ë¡ÝO©º\nöU †ñB¬=Oy–Ëjr ‚ ¨ß~¹œz* J8,•Ô¡»»v]?¹¨Tj“Ìwvª:-«Ö›±TRÇʳ´£TJ¦W«C=,å,«¶’vËõÉùõ¶èb£î)Y(áÑ`0 ƒÁ0} ‚˲ð2PEy9NÔ‹Yó6¦?ß³§ñ–…ýô¯^< ïT<{쳜9çI|ßçÆoäÞ]Ç‚]kx Ê«q81С:ã_1žlÏCI-Ó uïemÅ0qŒ)Çc__kÖ¬ivÛÇ_ïÞ sçrV[ýÍnŒÁpˆd½Š#§î¾Œ2L¨b½b=s¸'/Ös¼MD´1Æ‹ÎN5¨¯I*xž w*Þ‚:–• ~ºƒt;¥’zÃÚÉG¥’æS\²$'+•Ú|Ž£„L©§³3ÍßX,ªGÕæ†¬V‡VÍdÒmÇI' ºWçpÞƒÁ`0 ÃtF<˨õ•‰v òI#W †©ÏÓ@Nټ¦rÌÇðû™M`¯ŽzýQüÕ/v³$“áñÇ¿ËÅ£¼žêÖóùZá±>úe5^ãkZ½¾ÉžßË:C3ÖI+“k²“Çã¼yóèèè8¨ÇTæî»ïfæàà°ùݦ#&̦Ápp4òxô›·£V1j­xYôL„•Ïx‡*‚ÚD×þ¤‡ ýp°è¢Kw÷Á•¯o¤¹ö•C©C?v¸zöÞ WÏhn‡»>A­E ˆra˜ZÎår©C?ãjz{ÕD¡»[}gÛÛSÏB =âyJtµ_÷vìîVïËå`~ûù|ú;±í´}v”Õ¥ ƒÁ`0 G ¾ïóÄœ9”{ʃÁpø²{æL n~ÿžüI–Ưݒt ?yî1>Ø¿Ïóhkk«I—¢‹†Ž3üZe©yÿx†ÕEÎryr£´e2Í]g5úô2†ñeLÂã²e˸þúëê1•yðÁiݱ£ÙÍWt¡ÄˆÃèÐ=C ÂØ&úb¾>(ÐÅ;]((kë+ú€a4¦” ‚tðäûµZ²=\ v=„£N±xpƒ£r9­GÂTÖß'[‚@Õ_?8ÓsÝù~z_Ã0½7AÞc‹êÑÛ­Ć ¡óù´Î|>-ßÕ•nëõëû%ì(‘IÊÉv*!J?—\S{ûÈ÷ÛóF'膢ÿ> VxìîNs%Bj‘(÷Ú¶ÕàZŽ÷<õyvu ý­W*µßI}B0Z©áÊ錅BÚÞÃÈöÊ`0 ƒÁ`8$~ØÞŽ‹ñD4 µÈ2ÐÌ_oºfçAxØÇíf«}6¼xÜ«’"Ç{R²®Tj5›9j×x ®•M¶ ¬› Ê {2qÝÔ¡Âq&ÿüGcX³f Ínÿ¸ð›'ž`Μ9ÍnÆ„1…"N&N¾áàð}K‹9XFE>­p/^I0TÄ’íáÄ-Ý+RHèeuA²þ¼‚sõçÑ»F .$5ƒ ]Ó¯OÊ‹©'–.þéÞ’¯~»XLY"ºù¾ªßqÒó‰øØÕ¥¶¥½Rm«m s)÷SR¤½•J*Š)×ÓÝnK.½r9ŽÄ“UÊHÛ‹ÅT”cõ2"ê"g—Ê-N{»Ú/uKοÎδ=õ×® YRFÚ)"¯xωà)m,SÑô—¿œ7Êo·Aнg³ÙÔÓPÄ;ý·,÷_Êf2ÃOhNca8§Ãø3&áqçÎôõõ±sçΚý§Ÿ~:6lhö54µ´ÐÚÚÚìfÆ‘'ß`-a&á–C œhè‚îW*¥ û"¥çQϵ®R¦ÞSO$¡×!Ûõ¢§.*ÈS±~»¾ŒˆšÙl*x‰ØR(¤aù¼ËäzEà“ëö<õ,BX¥¢Ê[–ðˆ˜™É¤bZ¡Šo®«Hå²zÎfSOÉîîÆ¯ˆÃº0'iS¼ å¹RIET]ˆ¬TR¡PÄÅÎÎôžé^‡Å¢:VÄ\N]£ˆò™;Žz‹êú‚@ÕY(¨ý•J*Nµ·§VZ­­ªŒx€–Jé5Ê}-Õ}«2ÇÿøãñÓ9¢Ðsê}}XßúIA¹œ í…‚úŒ¢H½'yå7© ØÚªÞ—üÒ´·§çô¼4O£."f2ê!£ˆ–º¨¯3Ù ƒÁ`0 ƒaªd2ØLŽ·£‰Pf0LOfÌØ?tçO‹D,!wîO°g=¡~à¸nÏ«’Éd’Hkz”+ËJ׸½7ÞˆAsýådЬ<‹Fxœ<Æ$<nìÝ»—Ö3šÝŒqÇü† †ÑÄj‘yÔø {Àã{6Ѝ%ûô$õ<‰"éu@­©—×"héíѽòD?Ù§{6J®:]üÔ=Ëe5豬4 ³ˆ®A ®/ •µŠx"ŠÀgÛJH‘°”²Ë©2íí©—ϧžbR·4"Æ”Ëê}E€ÓC´Ê5а)9ë$¬ƒx—U«©xØÛ›æ¼«VÓû/å³Ù4C&£ÊÇÆ±T«©è#ÇêÛR®RQ×#méíU0Tû{{ksêߥ HÛ bäæÍéëB!½VùìJ%UçöíªÜûÞ·•_ÿúô¦þö¦ò½’ïw}ù.e2iÈz‘OÄvv8Njd†i®/E<´¬ÚЫz_¡ ºè)¿íú\ ÓÞË1h°Z…ue ƒÁ`0 †QÒÚÝ=i¹ÄeÃáÀK/ͪõLü¿­ð|È 6Óýðåx-ïP?ð,\wÝu@]z§aíŽQ¾Åjuü=»ºš#ºnºþ‘=Ðâ«aÚrL³0Up&Âl ÉøñÑ` A$aV%·cï(Ža ÒDÏP+4ô÷§ÞibÑäºi˜Fú'[©¤Â€xÊ~H½×tñ@ªúP­¶î—nN¼õŠÅÔËϲRoB¹ÄKJB›ærª>±ˆêîVÇéxÙ¬¸ô÷§^в»;õÞëìT"˜e©m;;U=®›†,-•RñÔ>ñ”m×­m£ˆŒ‚•r]"êJøK9VŸ)I¦¥½òyˆ·%¤÷B¶E Ò=Çd¿ˆ›²ÝÛ›¶d°'e¤~)JXÔmÔÁqÒó ©`© e¯xÅ^Î:ëàOÇùux£‡2ÎçÕgQ*ÕÈ÷^Ddù^ÉïS.m»¶ÏïÆRI=º»SñXŸ*ß ]„¬³\ßGÀòj i¼Ò’Fj£ê¤ ¨p6ž¶ ¬F*qý#¹­Wâó»ñ9m”µIž$$eT¢_è&5{ÏÄÇËv1>Ÿ¿ÎÆÛR^\è¥N'~_Î §Òî .ÆÇãÄ×[Œ—¶8ÚñY혂ÖV¹îL\·ƒYí2 ƒÁ`Ðð}Ÿí¹Ü¤ ƒaú1{ÏŽ:ê¨Záqw¯¶à·Àñ3áØx¿+W®¤§'-Úß_kü?Z&"Üj}Z–ÉÂqRÃ~˜|ñQ_×3LG¼ðè7˯w²®¯Ù 0¦A$–GúZt#$?`µª ò'­w%Õj^³½=(åU÷LÏB]¸ÔE°öv%lÀМ…"Z”¿´káìD@¯ÂlVÕ/"U±˜ gæS„Pñ€¡DrŠp jPÐÞžŠZr âe%Œº7Ÿ„–”sˆ€"å\7ÿ'€Ú/åôý…B*¼&9êÂêçV$ba¡PúRBÁ‚ªW¹' Ú,Ÿ©Ü?ɉ'çnp2\plj?tìšAœÓ² {é.\·EÕú*Å8©³RQâx7sȹDI%ÙóÈd³É7¹Ñò„^<Ä_ΑIýçïûê·UÊT„G É«{0ŠXîy~U«ì§PùEú²~"¢Ÿ»Ñgª‹ŠúÀ]~ ãÂp‚¡Ž.º '$v3ÔÂÕóTêzî“n~ƒÁ`0 †Ã™_½ìeÌܽgîÜf7Å`0LA|àì»îbÉç䛬­}ó)—jÛu8Þ>þkÂð,|ßçŸø¿À·“bù|퓎î 8YȺÃDå‘l„î„0Ù¾`º‰ab9â…ǰQ2&ƒÁpDAfÕ‡Q[7Š˜¨/ê{ž!2™ôÏ[<šÜ3¶bŸð<ïì$l¦ÛSxßCøüñd—ÝNµz^âeYq½W_MõcçPüÂ2Ü^‹RiÝݱ…ά­”¯=ŽÂß'·ò7› ݾ öìÁ~ñAÊ÷¿çìý¸Í’%©G¢äH!Q¼³YðïÚc=Šã¤‚™ ‚œ3žÃ²ŽRñâ°©Ï?‰"ìﯩ#Q»ÅtKÅJ,ZHÜ2¹ä’ üU¾È­u5ëî …ôãÏçSÁ_Êê¡W‹Eð îþx²¬ç}µy^Å£UB®Ôz9ŽÆRO  Ó@‰ZY”xÕG:gJ0³µcA w9R¯Eȹ/híÔ­gý©m&O|탼Œ—a0 ƒÁp¤óè©§²ä‘GàÌ3'íœ&R™Á0½Ø¶mó? çä§ <1‹½Á&_=ƒlº¿öVny7çž{:Ÿüäjvíª­#Rg}éGÖë#iM$qjÛI÷»ùÉ–eÄC– Ç”Éñ¸k×.®ºê*^ÿú×súé§ãº.·Þzër6lHʬ[·ŽÁÁÁC>wKKK³/ß`0м~@µê3òzºxÓAú,ùÿÄ[NB“ú>äÖíŹïk„7|—Ì£p¬ ýsÛ²…ào¿J¶õß±Ž}–â‡)—ÓÜ…A½táýþ,Š×̤•®÷Ï®ÉÉXºÿ|ìwÜù2‹I©¤¼Ã¼»Zî}–Ìýûø'ñï9šLFÕßÞÙ·oIå$yµ\SnÆçqîù*,YBö¹kÁKrâyd®}™b;tu‘ ‹É`)›÷Å[¡½L¹÷Ë+Psßʼ÷X¬K/€LëÜÓfw¶®ûBêv(‰óê°^}’õ÷«ä…ñç˜ .½”òö÷¿niãTFtâ:Yï&¸¸W6rsåVZ­j7H#›Um“¸©º`7ÖŠâċժ%ëÍÛ k5ŠT™ú¨‘ò~©T;‚rÝÔ6Ž¿{Ì3ÏÒïf"i映žÎÎÚðzîTî»»Óü }¶©ºD?C°ç‚µÜW‚{8[!Û—ïvÅÞÉ3Ànë8` X³kë5d}®É†”IW>Ф_™4|iE+·5ɪÄÛõåò¤áEåu¸Ù‡Å¡Úa°BìÍÀUü@¬9HE»—áK`wæ:Q\üCЏÌSåK¤¡Xå§Ðò²,Ïp´÷ÄÕ½‘µåxLF²ñ¹ëë/Hì·Ã¡n¯³[>TÙ¶µvÖ' ©M6Ö­[ǵ×^˪U«Õqôôô°~ýzÚÚÚØ°aëÖ­ãæ›oó5„aÈ1­­Ã†Uœ®n×s0˜~cúÒÌ~@÷x¬_°Pˆ=ŽbÄS0 ·ºñnò·½¬Hó .Ù‹{ÚcÿàR9á­8g·$B‹ãŸ÷Q2ïŸC¿ Åâ¥Öæ. œ^ŠùXÀœ=;qZËdbOª/÷QzãItuuã\Ž–ÒóÀ>ê(Ü›®¤PIÃ=f³ÿèsXçœB‰ 2ÐYÆ)UÓp¢ó·Søö`n•ÌÞNøìK@v”r€µúí8™LâI§ÿi[»>v9®ˆ†O6)`¥±)‡Câ·7"“x•#qþùð<Øg…ó†¾_­Ž||ìe9"z_nêÚ{ k9ØrõmÐcØ{ûú`Ë–ƒ¯khV_0ž§n{¹œzýŠ7¢Ê×óÀ= ¼'ãé§Àð7ßUuÐ Ö™`ï« 2ó¡½Êÿ¹@œY±ögAð_àÌžƒð'Àèp™ý¤’ë”—[™ÚÐœŠ‚â!¨{6æãc6°Ï‚¢U¶Ó¥6äh|-Ì÷à÷ÀßðÊ\G5@¼¿Z†çcwÍ8Œ3éÝ8‹C(wCWü Ž­BÉICžÔ ×x@N¾÷'"L>éì Ü_ð•9˜[P÷DFqóóÒíÛÓû"Ö"úïK’½ b)Æõ®¯âY¬'ä¬ïÄZêÏdjûB1Òë’\®¶Žb1õ^u|¯³ÖóRëPõlÞ\{|>¯úUùOaÔLf?`0šÃT †æ0Y}Á3§Æ©=ÔìË5 hƘ @Ùë«R3wïæ{^¡^|9÷Çáyâ©¡mâE}|ç;‹xûÛm^zéu5v¡a¨¦lÕêÐéØd‹a2µ¬Ÿ O2-Ï4!©n}0ÃÄ0&á±­­µk׎åІìÚµ‹¾¾¾šŽ¢££ƒ¾¾>~ðƒ$ûn½õVV¯^ÍêÕ«¸öÚkë)s°ø¾¯ycŽ´@²麫éC¦Íîr¹Ã;ŸèƒσàW;Éçç%ƒ„¨P$ÿsñ~9Ðs6Î'{ý•`/ª %à8P©Ì!ÔŸ½ç©u`ËJc¾KÎÆìG•‹S¥’êWÅ"Øo<)ɵ(Ž{z.¹®®ÅnRÛògžÉ€ç¥íd‚€ŒeAX¨ÕØ …DÄ·\—!¡.ŽAÞk‚)‘ž·ÑX2MšÙŒù­%ÞËû•7ãæÍ@Q9ÿy7‚ýµX{ËBæ.p¯„üF`7ð[(¿™¯ƒ'?§,p ·A¡ ÖßÛ€^°n6°òÀü=À%äÉŸžˆ„AV†ðW9(ƒÓü÷“ð±cáy¸7€=%e© !Hçu*AoÀ‚s<8§v¸Jd\Y„›Ëðµf{l _yðuÏy°»ûlxÞ…9qZ7ÿ+­6| ø¨–Ú–<ƒWð×À“½ðLš³ÐB]ßò–9ðëçÀ[IðʟþG«i.ÉØÂ9Àó\ Øn*ø52­”ÎY܆¡š ê³/ùàÅë°~†$^ÑòÇ åô>RïJ§Tߎ\.3™¡Wooš®ßDîÅÏa?¨âÈk‘F•08kvÇ‚$¥ž GÛ5ÀºE@Ôÿä]7Ö§ï×>Ký–Uû'­PJ¥Æ÷âHð,G—æìH¤¯¯ßüæ7<ÿüóÍnÊ&kLÐ××7ªöˆÑôÕ*‰—²x6{÷Æ…w¨§ÜÙqtÏ À=Ê÷@°8jY~†ãlÂ]s7?ýéOÉþcÜ\ÜŽ}ò8Vü¨“ßó{•ןãÀ¿–bë”æGÀÆ;Tãúûá™í” gõš _x9P…-UøPV‰z9TYà§YøÇ ÜP‚[³ig˜N±à×½ðt>ëÂ[Œš¤¡óör`2Úsoƒ:ÄÃq´d“ô×YcÒ(Ø6».½”¾}ûغuk³[Óõ‡:&Ø»w/}}}£*k0Î Ð××ÇÞ½{›Ý”!LÆü`ëÖ­ôõõ±Ë †#3?ø ߘô0ôf-Ò0•0k†C× °GØþ³³Èò5|˜Vµø$ö¡øÀÿæ+_y7®茴&纓'†[o½•K.¹„¶¶6²£±ü>ûöíc``€ûfØtúé,غõ°Í 8É}†aŠ#ƒˆgŸ}¶ÙM9 ãÝ<ûì³ Žã$–K²î],ªÐ‰‡:ÍÆyÝ^zÝÏ}‘â?JޓЖ•¦ø‚4¨Œâ,SŸBL%eð¡;ÎèŽ8º˜©ß–áÆ9ßÎH>#>EÛ÷íÛ×즉ŒVxõõ}%2J¿pœq–{=qÁGÕ“ÿðÄì3€»•¶gý؃7QæÍøúÿð¾ý 7ÜpU:ÀïïÇñŠzmBÇIRð!~Uˆ],kC|V*~öÜsª£H“xú>俆 7êpä$Cv€³™üÔ4açÎôõõMYᱞñî Dx¬Ÿ G÷Ýwß”뙈ù²Xi0©˜ùÁ~€ïcNa€ †ƒÀ¬]3”™dI‚ç< ï&˜}|È¥ê-‰¸uÙeç±cÇŒaÏ5š€;“e5oÍLœ-Æéã3Œ#÷Ýw߸Œ Æj”UÁW\ÁÀÀk×®eÕªUIµvíZ¹õÖ[Y¶l٨òrÕUW%ud³YZZZùfp \pÁC,|€‹/æÜM›`Ñ¢C>ÏT$À„5¤tttÐÑÑ1¥­û'ª8餓†ôGa&ÞŽúz|’¦+ á©ý”Ë'ªÜˆwµ(¡pñbªÕ8²`ŠUaxÑO’§—ÑEH]WÐç=ÃÍÌÜh(â*kÓ ù^ A4œK¹áÞŽõë×Ó××wPâÛd3Ùc‚‘hdøüØïŽ¡x-l¾Â_@8¼…ÀIà}<æÃwz(d/„‹Z°ß Vw”€‹.‚å+±›8úè]¸n 8ŽŠ$ê„äóyJ¥Ò~D>ó0 ÃÛ¶©T*#ˆk–_ƒx8iL²åútAR'lذ¡ÙM‘‰ê æÏŸ?®©# †éŠä@:Rç+V¬0}Á€™\pÁüGGxž G,fÍp蚡̲umβ,œ™PžÙBø¾Kà½><[Ûo 9žxb/0»á¹dŽ>D·fM—%ò[¹<ù©‘F“%åHfõêÕ´µµò˜`ÌW^y%ƒƒƒ\{íµC~”ëׯçÚk¯åæ›ofpppTaK¸ä’KhiiÁó<Ö¯_ß°ãhÔùÕÇw>X:ãp«‡#ÆÑÇ0hF?àǦ=RoGP@¾äóTþÏc5ÇØ¶òjììL=¡ÄBHM.ùëÑçf2iùllÍãQò|˜;ï„ñMNH©Ä.¥e‰WSÓ²˜»ïÞ‘äÖ‹%™?‚ÙWø¾Ÿ´Õ÷ýšòår¹áñÅbÏóÈçóxž‡ïûI]•J…ÖÖVòùûÙÏ6|_<î»ï¾šÎ¢¯¯ï’öÜtç,\8~wÔ`0Œ™fõ{.ħ6¥Xòäûpæ™.LEEÇ©ø~­£ˆ–Ö]¨Š&$Öäc”?ö|ìmY (TVÆ»å)å Ë—H•z!A޳†zÎ5?W3\;òù<ÙlÛ¶ Ãöövz{{éîî¦ aâû>™L†®®.6oÞœˆx–eaÛ6Åb1®¿þÌž}³gÏN>Ÿ (—ËI½"øéç×½ÇDü±m›L&C†‹E|ßÇq,ËJÄC7þ`=ÏÃu]Êå2a’Éd¨T*ضã8äóylÛ¦\.' ëºA@©TJîS{{;®ëR©T¨V«‰¸ÔÕÕE6›% Cz{{“cå¶m'Çuuu¥^½ñuú¾eYìÚµkJæn€æõ¸äs$!Tòë¡êÁÿþç.ݲNo„[`ù6Žßßõòw1óãï…¨ãn¹å^ùÊç)•>A[ÛùêWï¾Í¼×½.ùn žç%¢³|GK¥·ôõá]]]xžGoo/Åb'þ‚‹ï8™L†b±HXVµÆ+Z¾õÖÜë9;^LäyCÛ&@uþ=÷`Ÿ~:–mÓM’"3ñx·<ªûuâý.C#ÓQ®Emd‰É§ÿäÓÌhÁÎ-;ùÈÙ¡ïË}¼-z­«[ùÙs?ãÔ£OåÂç/ä³·|–'.‚ÍË7ó‘?þïúÕ»x`îüöë¿åá>L±Zäe¯ÕÍU^óš·²wï^~ñ‹çim}˜0Üžx&.Y²$Y¨õ}Ÿ÷œó>wöçØ¾};7=zŸ:ñSÌš5‹…{²gö.ârÚ?ÙÎ /žÀž3÷pÓën⩞bß¾}\²÷–¾g)7?z3g=p—´\¢‹±tÎR¾µå[¼å¹·ðÁ×Þù½¼Ûû)ØÈÀÞÛ÷Â+`÷É»9Ñ>1UºÁÅå’Ï]Š›W°gáæTæà.à3{?Ãì…³•á]àXŽë€ nV  nÁeð׃´ý@%_¿ãŽ;˜}ólnzò&>½ðÓÜôÔMœÕuÖ¤}7FK3û‚FÜ|"ŽV¿ùO[ð÷wCþÝðŸK—Ãà±ká ÈýÉj*ÿ½€›v>ÁÃg~–àÎYÜt2¬<ù!àTpÏ¡TªŸà¯û ?û“k¸åXøµ¯Qy×»¸ãxôÒKùäÎôüò—Ìÿ—¡»»›åï|'ïüû¿WžŽ®ËW]Eðñsí÷¾‡}ÞyT]7'E„,—ËJ C,øƒƒ‹•twwcÛ6¥R)ñ†Íårtwwã8N"Ì Åb‘l6[#^ضX–Å??ô—žx" õ‚DH*ĉ—y¹\&W(ÄI¥RÁ²¬D<%üKÞŽk¾ö5þíÎ;¹ó+_I ÇaÇ •?ã”ùókÎÙÌä+WR¼ôR¼7¾‘l|~€;vÐ3o3fÌ ‹ê>ã.”"pô®]|dëV¶žq!°dÇJóçSDuËݨ®×‰Ë{ñvƒ]˜,ÆïÙqDÀ”sÚ½±âí~í8¹£~|¬=WÎ)â'Úót ½?š¾`²úñ$ ÕXÁó<•c:ÜͼyóØ¿ÿ)¼Ø²Éq¾úÕ£¹í¶›pœ &@ww‘ßþöäóùaQþÓd[7l‘}bS,) É"ˆŽb´  Aà8‰Péyýã4Ò¶„\C³Œ%…‰jó¡Ô;ŒÔ†cª Cs˜Ì¾à¤ÇŸôë3ëvÙ*c‚Ù»ö°âèܵÿE¼'[)Ÿ¢æ…z¾$Ý ^ÄÇr™š(G D·femz{¡½¢¨9çŸl‚€4*”aB“ð(?ðzwæÕ«W¥ÌÀÀÀˆÂ#(Ë…z:::¸þúëÂõŠ+®Hܪ‡u«>õ.Ò‡#G²ðh¼¥§Íè„Î:‹¡A[ùÌš@pÜòÄB  «KýwuAn5P‰ÿ¬~ øàÜÞo{ÀYÁ¹(‘°‚úQ:`y¨Õàéê²¢V=ÔŠµî“¡vå8R‚@ÎÉñÐCqÒ«Oâ™ÿó ó¾=¹sç2»s6ßàÜõÏwñ·7ÿ-Õj5]}®ÄuÇ'®}‚…?_È“¿}’ã?~<{¿±—ãŸ<žcŽ9†™3g‚ °ø—‹Ù·|Ì}€“:+°xnÖs„VÈ'g|’/mûÏûe·ÌÇnù_á+ðqxìüǘùøLÖ>¾–ë~x—žu)ó?7Ÿ™ý/Ìznw¬¼ƒ-ÏláÒ[.åîÖ»YxÍBüʃ\z쥜ôƓػw/üPååzê䧸âËW0¿4ŸÅÁbÎÞ6­w·Rì.B²Yþªåî¼óN~ûÛßrÒ½;X~ÔëYpªÇÅ÷!Hïëýkî§õ‡­üþ÷¿çG¿ú”aÓ¦Mlžµ™ .¸€¯þ137Í$ B¾þίC[ïÛʬY³X±rXpé/eîsUË[à½?}¯ºß|â}"U;,˜ýšÙÀìSg§¢³î¬°VÀ£0'3'ýX0ûw³a þÞ”I=^+¤ÊNQ}Îm™¶¤C<÷ÜsøQöGÐ +¹’otLž(=ZšÙ4Ćï}œÿ„¿Ïyx)x‰'ÿn!‘7ƒükneïŠ3xÍ`ï ²¯ç˜ÿ;Àå—¿Ž¯-žEφ/_fî7ÿŽ•ÿã«Ür¿ ¾rÕǸeüöÌ3xýE±iõjþæÝïf÷Ë^ÆÜÿñ?Xþýïsõ7¿ÉßÌ˧_z‰kgÏæþ7¿™íýýTP¢W¿ea».'îÚE(•J„aHgg'K?ÿy–´¶²õÓ_ãþû Ã&‚ˆð{Î;c{ŒJ{;¿ûèGñþó?ñ;;ÙýwÇ_¯\‰ä_|ÿû\ÿŽw°æûßç»W]…cYø™ wýÙŸqâÑGãõöò—]]œ½?~ë[¬ªThéêâÄo}‹Ð¶ù·–ÞöÒK¼þSŸÂ èí¥å¦›xé?àٻ嶺·—»nº‰–Ï}ް\&_.³àª«°Âû}Ÿkž{ŽÓ¾ýmnÛ±ƒ½_ù «n¾™Mƒƒì}Ó›˜ßÛËìÙ³Ùvù圻iO=ôÏ›ÇüíÛÙÑÝÍâ—^àŽÅ‹9îúë)».³¿÷=ŽÚ²…ÒUWqü~À™ÇÏ×–.…/™“[ZøÇ~”Ù_ý* ,àšÕ«9ñÑGyñÖ[ñººxó7²è碌¥*n|ç;)Ϛū¿û]¶s å‹.Â-—ÙzÑE,kmåÚ9s°Q?Kºº˜û×Í÷^ûZ.øÁ¸¥£ƒ­ pî¦Müó²e´âCÑ[[Þ}ø¤G–eE6väâF97•œRô¹“?e2™è;ïUÇØ¶mºrStË—o‰¢(вÙlÔÛ;´7êíížûôsꈢhóæÍ‡þåè¢È¢wîŽ,¸!úË?Û=øš£È¢ŸýçêýäfFµ¯ëîsÿ(N8=¹ïšû¢/|á ÍnÆ!3c‚zôoêÒG¢èÌϪßõLï¥;Š^¾':¾ÿÑGõïØE+ßE޳9"Š¢¶5·GØêgvÖ7ïMz®Úßö|]ð-µínÞ"µ}ö‹/F«y$"Š¢Ë÷îrñþLE—îÜEQ!Š’ý²mEê«Ü¿þÑÎÑ;vH}ÍOüÔ§¢÷~ç;‘mÛÑÙwÞ-xüñhõÆÑÙ/¾Íé¥ÈÎå¢ÙÏ=EÑßúVDElߑ˩í(Šf_sÍía­ˆËÏ}þùhÎg>Í}þùhösÏEKy$šó»ßEô÷GÇíÝ_×yÏ=ŸkÑOD§Æ×5ÿé§#'®¿åÎ;“íYÏ>Q­ªý/¾û“Ÿ¨6<÷\rŽÚ±#:ûÎ;#¢(š³gOtÑãGg<þxôšo;"¾DQô¹Õ«£l6•J¥¨T*E_ÿùÏ£O_sM”Ëå¢L& …ȶíèþp„a´yóæˆB!:ã}ï‹z{{£jµY–ÑÒ£uŸùL„eEd³Q6~`Y‘ã8‘mÛÑqûXÍ=+ ¹®¹®Í?唈l6r'Êd2Ñ—o¹%ªV«I{æŸrJ´òûßæ|æ3É>Çq¢\.9ŽÍ{Ý뢢ïGÙj5jyë[#Û¶£Þ(Š>÷‡?DÝa9‘ê^å~¿m[Ô?.ÿÒ—¢¯ÿüç£úMLuÆkL0ô¿¶|ࡨT*E¹\.êïï²ÙlÔÖ¶2r'"(Dй®}öѱÇ~'Êf³Ñòå{£åË÷FÛ·«±G©EýýQdÛêÑÛ«öEQuwãñH)ªV«‘ëª1JooY–z–±‹ ÇFQ¹®år¹ˆr¹ÜAÍ…úûû# *•JÉï ù/•ÔµD‘zvãAùöíiyÞ¾]µ]†@¶­¶—.ÝtÒ‡£ùóO‰ÀŽ>ýék¢•+ßA.:ãŒ÷Åí¨Fsç¾+r]7:é¤MÑŠŠ.¹äQ.Esç¾+úÜçþ-š1#ŒÀŽŠE?¾Vü(EÙl6:óÌÏÆûíhΜŸG®[ŠÀŠŽ?þŠdÿÅß]rÉ¢+>A6:ùäÏEÝÝaôÜuw£\.-Xðx´`Á Égé¥ŸŠº»‹Ñå—)úÉO‹V®ü~Q´`Á ÑâÅEŽ£îÃÅßµ¶# ºøâ£9s~µ´ÜwÞeIŸõÅ/>årªì™g~6:ãŒ/FË—¿3:öØïDgžùÙȶû£sÏýIQtöÙwFGý«¢hΜÏDï}ﯣjU}þ‰À‰Î>ûÅøÚÜhÅŠoEñ5.¿‰fr°}Áí·ß~XŒ… ŠíÛrâeÂáò›ëü€(ŠÎùÄ'&µ­fÝÊ01k†)2ß$Š¢ËŸx"rq£È"—‡"ˆ¢Üº´lµ*ë†Äs5¦­VkÇれã›ë¦cõ#Í›ãµ]Ȍǘ`LË—/ §§‡õë×X¶§§€¶¶¶qK‡óœœZ…ó8¯¶¬EMþÍš·,ë°õˆØùúÐwèõ4›ñê t$—ÀÃÃâ6pþíã¼î“WðŒûr~|ý‰<ë¼ 2Ê3çû.,¾¶|J}Ï=TTzž¼Øë”×Ùþ~ø3áÜK”§šoÛI´äòÑGsôâŸÀ×fÍ"·¥8--‰µE™Y~5Ýñsx--I.À"püÇ?Î7>š–“Ofûë_Ï’3øå>@ ç-˜E¬Š—\‚ \6{6_(pöþýýÕ¯â¯[—8æ×­SùçÏÇ»är€?s&Þ§?­B}ΜI~ñbJÀ?ü!?sÎÿÆ78éÊ+©Ì™C|Å ¨¢ºÑbk+½ñ5W¬ 7n{ù¸ã¸þÙg¹ûvînm¥ºr¥r Ÿ3‡ÐóÒK„'œÀ¯V¬  gÏæ?-຿ùþæ-o¡8>-[·²lÕ*>uŵøyµý‚Þ'3>%Ë"ó¥/%Þ_Û·o¯)ÿÑË.«é»²ÙlÒwäóyn¼øbÈfyÏŽä>ýéšú%Ln¡ÎÛH¼Êå2å+¯ä£®;$.¨°¹¹Ø«íSñÿA±½]y¢YlßN0çöÛYü/ÿÂO/¿œŸ>þ8Ø63.»ŒÛ¾û]Îùñ'äw4™4«ý<²ƒO}jž÷<õÔÉÜ|ó ¾õ­Åâßñ· 0ŸcýGªÕù€moï:·äî¾òÊïpõÕg’Íž‡çeç¹øâçY¼øý|ãÿÁ¾}ãÙg¿ÂÊ•w°iÓ&~øÃlÝú[^|ñ/¼°9s–rÝu+9ýô™ÜtÓ"Ž=öYöïßϦM?`Û¶wòÆ7~‘_ýêƒìÛ·ÓO¿™?û³ã¹çžœ}ö[xýë¿Åw¿{ ‹÷0þ|®aÿþ{©TÞÍ[ßz2§žz?þñ.ž~=o{Ûv~ô£òš×ÌäÒK'Ÿ|9çž»‰'ž¸\_Ÿþôb¾üå'ùÞ÷^î]UæÍ{‰;/àôÓÉfO>¿Ÿ»î:›ßÿ~üæëÍbº÷e£AÏ>ò—ðå’ã»\.'ó Çq’Pp’Úó<‚ “É`YVâ É3+ó ᬇ•“¼èRZòÁA@>ŸOr Ë12בÿG™ëxž—ä/—¶Kèõl6›x?g³ÙÄ‹[rØJèyÏó’hú¼F<Â%º´E/çºnr¯2™Lrí’CWÏ¿+ת{ŠË\i¸|÷’¿]> ÉÇ®—“öÈçíû>ÝÝÝT«Õ$÷® לÉd’y£ÞÏ—ãûpäPú‚cžy¦ÙÍ7 ãÀDŒ vìØc;@á+K)ßÌNßwøÈG¶ò±mNúÚb1 דÉ4?Ô*¤ëŸG &Çãä1&á±¥¥…µkײqãFÚÚÚ†ÍõØÓÓÃÆY½zõ¸ ãEËSOÖƒ®ih-ƒÁИíçœÃ£ºBçá2öRÀ¡Rà~ãõ8÷‡œ íß„ÍXGmÔÆ­‹Ëޤ9V*•šP]2¡A1›Í&“r™¨ÊÄ>“ÉP.—q§Fpô}ŸR©”äUëîî&Òƒ³_£No¿‡¿¡6ÆC¡P ŸÏS*•èêêJ&Õ²@ÑÛÛ[3ùÕÛ>ÕE¹òð¿¿XØìÖ¦ÿ±ZŸ„Oœذkæ øÿuwÝöZÎüÝóôýç6 YïÛNpE+[V?‚YÏ=ϾìÙœ2ÿ÷¿ïåÜwüQ•/À¦™à,M£ãzÄ¢_ü(¡ºÉ è£Ä9Ù–ý]ññ²Ôí¯ ±€ „'žˆíû?úV\¦Õ–B|žìŒäâ¶d€usæð%àÒ£&—ÍÒ‰Š-ù ÝøÑ—ÏÅ畃r}nG¯»é&¾óáJ •¼ºžV…² pÅÅi„älüøäQG%!Ö qýÂ9çœÃÿýßW®ä¤Í›9þ•¯<èïƒ,rGýXRïs¹^g'þŸü ݼyȱŽãŒØ—f³ÙÏ_*•ARRå?!Þ÷Ýïò\g'{Þÿ~n×ÄͼeñäóÏó½•+¹»\æ³ÈvP|ðƒŸç_þå|ä#7ðè£F†|ÿû¯aÅŠÜyçv^÷ºý M6«„7•ÓÑ!`îÜc¸ë®õÌ™ó›7ŸCW—áŠÅT„ ‚T( Cµßq”(×ßÿN;íðÈ#ª¼ «©B¿Û¶ÊÑ’Í*ÑÐqT]å²:> «œqÆ5€G%ïûJl¬VÕù*µ¯»[=oÞœ s·Ýv [·.zù¯ÿz‰ 8Š|^³PHsÅd2êÜ¥’:¨sxžÚ§¡%Ôq]]ê|…‚j÷’%¯à‚ îäï˜AÌ`Ë–ëX¼øaî¸ão¨T ض˶mr¿\ŠEUÿÀ@¿Ç¶/Bz×O|b;Ÿÿüżìeן “ÙŽm«c+uÜ’%pæ™gÒ߯ÎßÛ •ʱØ6ìÛ×ÅöíÿÁå——¸õÖ×ò“ŸœÏŒoäÏþ,ŒÄÚøÚ×^FW×FæÏ_Ë¿ÿû ¾÷½9ñý<žï|gsç^ÇÒ¥×á8çŸ?‡;îø --7±wï ¬[w×\óiÞøÆ=,]z/½ô|á %<¯XÉܹwß½„/|ŠÅ7P­Vãñ¡¤p)[) qŸ±2ù¼¾ô¥Ëùò—g°fÍg¸öÚ=<òHöö€|@…[±âh:ޓܫ0 Õ·ç%¢žÜù  6µÜoýår91 ´N'ELÕ‘Ï%h°"*⤜KÚ/×® ¿bØZ©T’¹¤|¿ä{!uJ{$ [[[í<òäìýû'õ|.&UÁ0]Øû›ßðæçÁî<ù¿,àäÔøWøæ7ŸäÍoN…ÇJEKéTǦ™“†çÕŽõ †ñbLÂ#¨…®ºê*n½õV–-[–XôõõÑ××ÇÀÀË–-; Wd3€={ö ±:›.È`t$áÔfjåòi”+f¬×>ãáÚåy^2Q‘Aý}1J&2ù”²21Ëårɶ”¯T*¸®›L0FZÀ¡ÊPËköìÏûn ÞñïÀÿÈÌŒó7n÷i({`/B­Øçcñ ¿Ò2a•ÏV&‘ÝÝÝɶeYlÞ¼¹FXÌårAÀöíÛY²d ¶m³yóædQÂu]²Ù,™L¦ág,e¡Z&£"nf³ÙÄÚV¦-³Ø1É>¹Ù1L'ž|¾ÿ$¼g¸ ^´öÉpï¹ÇrïìïÝì[ÔʃïV‰SOxðYžqçUØÇïç¾Èc§½œ·>§ÒÅþæOáÜ™0%ðåP‹ ET?’!õ\”ÅÙ–ô°’§/C*NfH®3(!Î'MJ|.©»²d üÒK¼ý¨£°âòqêФM²?S· jLakõÊ<© ¯ŸÔ¿ï³m›-±‡ì·´mHY È„!ݱQ„>–iôïŸÑÎßèý÷ýã?ò–•+)~ó›©ëÖ$aYýýýc»ˆqŠx¡Èkñ¸°,«ÆƒRúsP ŠkÏ9‡mkÖ½W„À±Çr¢El»ývž¹ûîI½/ÓÏóø×}k×úlÚ´‰^ø½½½tvª {¥÷Üs4¶­,‡E ÌçÕ×﨣¶ÒÓ3›sι†óÏ¿‚çžSõJ`ÏK=]W-Tˆ€§öÝM¹|°„Ri3¶­êÏdRKåjUíkmsRçRñòè£oæ¶Û.ö9žzê6$mcW—ý@‰—™ŒjCWWêÉU~÷»…œ{î&î¸Ãçþád.¸`årz,¤ÖÛ² ¢¿W©œ3›Uí“2õ?“K/=5Éû’Ï?ÏRïŸB!=G±¨Ú»zõ¯ñ̪ð­o}·¾µ•Ÿüä/y饧°m+iO¨¶Ø¶j‡ï+‘´ZUןÉÀŒàºg[Y°Àãâ‹ïÎÔØZåÈ„lö8,Kåºüòô3S×wGÍ‚ŽòDý5ž2s&üÉŸ(Ïë5k R©àyj®çºJœÝ±£Ï[šÜŸôw®×YÖPÁqfÏÞç-ÔxC »v=:i¿£#™§‰‡œˆr@"&ê¹R墽½=ñjM7,?ýs”ÿ Ñ9^<ÿíež¡ ‘b€8–¹£mÛ8Ž“\ÌCí·;Ô‹¿‘× ´Oºòù<…BaÈÿ`£ö6:—Ü™{×£×S, ÃR©”|^bjYVR¶\.'B`¡P “Éh9dò›+—ËÉgYÿYés3)Eh•ïEWWAÐßß_“¯¶T*Q©TA¸T*%yk·oßžÌå|â*×ô«_ýêˆðnÄsUnÞ©6ÿ•&SoÌ`8ò8æ±Ç˜¿`)ôø¾ßR3Cؾý\÷”ä×UcÔ©Ì÷)0LcÆ,<¶´´pýõ׳qãFzzzèëëcãÆÉûmmm¬]»vJŠŽ „Ç^xaJzìèsÃ!ŠÙl6±H”ÉÆHaW&£ížç ðKHþþþaH 5Rß~4‹W©TjB‹¸®[3ñxÿg>_ÿú˜Ú_öRGD=Ô‰Ld2"ƒ\.—XЧšÔ-k2±“¿L€DüÑI&¬É{ú¤Ô'“ŒB¡Lzºººj,D}ßçé§ŸnÚwdªñ‡NP• œ} á=Ǫ0g[À»üߨíðÝ(å5x‹EnI¬[˜–J¥äó¬T**¼^ûC¬\Ù”9õT7içh/Ëz¡Qß–ïy£Ð„õ”ËêºõˆÅÒ8ŽÃ[ßÚ@KËCA­È ái3™4Vý4ÅueÜWŒ= ÕÑC(J]z½:"2é×ä8N26×Ç^zøKÏSmÚ»w¯~õ½xÞ“ÃÞבú0=|£{<çÄÓ•0 “9ÌÙK¥5ãxùêííM¾¯òùˈ>笗ësfý;YÌF2–y©0\Š„ÑR¿0Úï×h×1ôùÏ¡`iFQ#¡ÿ‡Ö‡V×i¥`8ѳÑïµþºôûQ_ÏæÍ›k¾Žã$ãˆúvèuŠ(ª#¡r3™LâDp$²ë裛vî¹Dx"Ÿ~žÔ(Q Cj½$e¿`Ó8›H'ÙF¦–Äj0L}žxâ ^zµ.…ý_£â|¤æ}Õ%Wð}+éÃs¹4ÂÇTÅuãÌ”Gfè;9ŒYxÖ®]ËÚµkdpP%4jkk›’¡UëÙ^·(ÖL$”‡FâCG÷rÔCiH~ »dÐ8èV€úäTzHÉQ'ƒ` …"“(Yd, ‰H©‹1½½½tuu%ù òù|bIhYV²'Öÿ"¼I•…o{O4¸–b±˜ÔÙÕÕ5ÄòPÂȵJ8¹is>Ÿ§Z­ÒÙÙY–R#ÇqhmmMü2Ñ’2ºè(Ö†’/J÷RÅP™$ʽ’‡,’JûÄ«R¾'ÝÝÝôöö’Íf“óÈdDò´àÙceaìñXx¯K° ì™àßáJ(nŠ Z`ŸžF«ÉÉç!ßñZËbH½bå3•¼’cE¾G…‚²P¯_œ®ÿ½7ê×t±²žé.0G`C±ú¿Á°y ¡B­€¶íå/`ÿõL¸ à˧ÌàÔ]½mû7ïå‘`dÏ`æÃ°gÐo< v쀟'¼˜ŠuòS¤6µ¨ŒŽVÎÕ¶eQ!S·hedD y"ëËgµ2Ô¸!‡?b,!626Ñ·ÅZ_Ï/$ý¡ô}•XQÑ tÄ`¦«««fQ­»»»ÆÓ[ *êC¦I›î›5‹ÛPÂj¸ÿþû)Æí’1—ä¾ÊårÉÿ¹\‡îIP(’s‹q‘öÈ"²A@gg'Û·oOŒLDp•û'¢¢\¿Œ $¼œŒ}¤ß¯_¼-—Ë´··×ôï²À(aÞäµ¼èe À†'ŸT1& ñ<ÎÎ<--ëÉç[™=û ä‡?|„­[ÿH=K¥4d©ˆUò3K‡õµ¡ùêqUO§f0#ùêÕ=q¹Æl"PJ]BíÏ=ˆ…¨2_œ.B‹‡¦eÕ†~ª?UKËC€sHb•ç)Tî0¢ˆ$>Q.«G‘ôKõ"¥ã8C¼,K…Tµ,%ðyžþY) u_ç΋ç}§&\¥º·×—ê÷MÚ8œ (ízÙËæ0cÆåc¾ïÒwÕ·Aæ–Æ0ñÐ\™÷Jíí퉛ŒóujÅpå)?Üûceª¬{ÆñšÃ5Óp}ªÑòÐCM9oˆ2ì"%§» It¡Ö±›¡"¢ ¤Bí|­nKÛo‘F[‘6H{$ÝB5·´ bP9Ü·ÑÇLÅ Ó}4ùàƒ2ëí³ài—¼wYgèÚàêÕ¯Çu'¯ƒ@Q‡±54ISa˜xYx¦‹ØXÃpA–'ô”CmÉ⤠yõH(FÏ$A¡PH’¯ë9áÆ:¹‚ þ$܇f²€邉,ÂÉ‚¡äqqNıÞÞÞ¤"ÐÉÄZB†lŽó‰¸†a²¯^ð+> ;*÷å]ÿôO5×# yž¤»»; #)‹21ܼy3¾ï'¨äYòÎ2 CªÕjîD_%ðÕ[ŽJÛõ¿zqYôëmõïéçªß'“ÝÞÞÞd‚[¿xóö·¿ýоȇ¶Í9sæ@.G¾÷O Ï+ËÂÜb`SZ4“9°ð¨çi ‚ }ÅëU'!OÅ&“ÉÔ„’ÅbY¬ÿN,…ƒqG88¡ý²#ÏzËpð¤^ÛϘÉ}/\|–—?ñ-{‚™»ã¡›f2û²V^³žØó{[¡ãø.°ï~xÏ*”å©»Ò‰¶Lî¡Vd”÷²Ú¶.7Z„ÈçUÝK—^ÄÃ'9¾þù@H›]Gý\Bÿ|=V®\Ξ=ÖÌÅ=G Žô–eñä“Ot½ãZ™×f³ÙÄxDî­ˆ¾¦Ï5¦6Ç<ó̤‹ô6Ê8ÎC(V©h"Œ4“¯ÿ'D;~ÎQÝ$$Í/W+QS$ÒŠ¤j¨¢æ#z!IÑEm~z™Oåâk)jíÑ"e^$¢d#MÝ;3$ûˆ·§Ìu䜂Ô#ž¢’ŽjS[ G¥î\ú·A-ÛÍVåó2f“ËîÝ»iÿ‡‡¹K%(‚äIù÷„žžs¸é¦ô'q§+“aÝ%–ô²È#‹k€ú— àÔ£OeÞ’y‰µ½Xø‹8¦{ÈšlK8YDK{Û¶¡AžDH«L9}RVÊoÞ¼¹&|ªž÷MÎ-–ÿííí5–ýõ¹Fä~Ë>V…cÉšw¤E„+ßøÆdPä•Ë„±7¨ä4Èår‰Ápu'Ÿ©XS/"JþÿöÞ=N’º¼÷²Xf·Öud©œUqkD¢ˆÖ+Æ ¦g’“ÙÄí‰þ‚kÎo“îc9ÁÄÓ­óKÂIŽÉôæõhÂLŸxe=ÝGEeTœBTAØB×e¹Lí ,0¿?ªžêêžî™ž[_Ÿ÷¾ö5Ý]Ußú~ëòÔ·žÏ÷y¾å^ ë5jPÎ[&“)Jå¦#\çÀ4yø^«üqÈœç/²ÒŸ)8àJOk9?°8ôå~’‚@xNÄi$#ž£×R¹Ô„zþÉyà<[ïJ(Í‚¼ÄFo󹿷˜úÞÏ¿å$ºƒý<³ž~Þ¾êDnÅŸÇ1fú/Ù›Ž^>_n!‘ü}ÚEŸdQsR)íiÔØ%¿—:´çBžéÒWF $B_iÊïþþþp°Óððp(އƒ'ÄJ·eYôôô„ÙÁÁÁP`D"óÅVÊ «¹KD—ÉœK¥í—yޤÍqàꫯžU–<Ç£Y¤¬ñññp0–²,š‘A?E‘y—¥¯$6_æc¤îr…R!µ²L""e^.ÉÆ uJóe¦Óé°)"°Rés¿óoåöÛ s8nÙò\׿}ïû™Ìu$“ ]ÇjnÃèà»Rf=ò]«¿ØõÒ‡±‚Þ\F$ŠÅ|á1Ÿ÷·›Kù,­Ò­VËb…G K…G©3‡G`¶xVˆÖ”åÑyïæÛ¾p^çÌ,­/H¤gá˜-4âQÞéæªG4 ktßO>y>ðpÅùèª?ö³#+å÷ûî»oÑå¶32ÐFÞ…¨Ÿ+ ®¢(Áø† pèPÍSOG&Æ`Qs9–öæ Šß9(³|œê±ñßIòA=ûƒÿ’âÕ¾KÝ%ÃK.ø›ÄÊŒ €2Dÿ,:Ó¥ñéE~ó‚ߥç£ À,—9éÓøïTƒÞó¢bÝ01UŽ»¬/¥ 㓈Ó|ðûpЦñ ŒD¤"û“6ZDØè”2 ‡\qNÉïÑvEV‰<•s/pJEWYWÚþg"û‘XÄ]èN]¦,z-‡çqâ#ÿWŒ‚»6ÌLá Y¾õ­§Ù°a °±h3ËòûØ*>6šjµ6´­ðø½ãÇW®p‡¢'§ã8|ö¿~;kó‘g?Â….äñ÷>ξÇöñމwðÌÚgøõs þÏ<ö¯ñÀ {cŽð"™f¸þ¯çýxpÝO®ãµ§½–T<ÅW¾ò>ã|†;Þtg¥Ï"oæql‡‰_Ÿà‘Gák3_ «ÔÓÓ¦i”y%âÊó¼Ð9%Ž@NÄÉ}YŠvÄÄñ'B\ôûàà`˜BtÑHCò>È“[ž²ÒS1ŸöQÈÀWð‘1)¹äzEŸì !Ú[ŠŸSA›¢y,ÒrW$‚eÒî~oЇpÁ¬4œ³Ð‘!?ÅóÏ¿,ðî‚W??6LÁ»_óJn^·f¦€)èë*Á´bE/þÑ'P51ÈÕ ;èïï'ŸÏÏzæ&“É0*/Š VŠF¾‰ fÛ6]]]a™Wypp0œo*‘HÐÕÕU”vTQ”sÖDç/rÖŽŽ†sÍ Ñ9g«¡4Ã@xìQppp0ì=z”uó”WNÀ”þQ±å•RIA/ý)9¥åÏ5 6˜)ÚËçóôôô033f©s!¢©išÜ}÷ÝU—ß.H„­ôƒgu çypÚi?ãÅèèèÀ²ŠSª“Î.T&jŒd6éëó òþŒþÑ›1ûþ2Ã& ãÈÏ!ù?x÷£ú“Hšf¸­ãøÜpÜž>?§S…¼Nï]¿žðâÈHø ”¨ÁxœÂÄ•’3¶¹~ --¿Käíáÿý¿˜Ú¾½(£ƒì«T[ ûð®ËÚgž©x¯TBŠx‘yÙaîT­Mö¼ÙÍ•r7mÚTñÌGiÆ¡’ý*,÷÷ÿ³ŸÆÌÌ>eÐñàó`É9’Œ9‰HŒHYò?NqTªˆ“²îÓ=¶|O á<ô÷à/ øÁæpŠ‚lÖï®ÿìg?cÆ)J…Gí"4¦©Qµ¢m…Ç'Ÿ|r酈ņ‚E+/y†á¹ûžãÝëÞÍûÊï|?ûþÏð^ëað_SÿOŠKÌKxqôEžøþ˜¦É»ÆÞ…}µÍ»ž{—ïå<>yÞ'YóÙ5ð\¿š«¹Úâ\~æBÞüÝ7³ê'«ØÂ.xø?Y<Áçç—ã¿äî[ïf||œ¯Üø.ü Ñø ;á·A’Ëg >¥mDÚ+½¢ ƒaÄí8䡯§ÏwÄÉPñÂÊS4þŠCPBî%OãRŸƒÿ´ žöozç›ÂE_ù†7X$bŸämá?Ù’2E»ëþÆ"ÇFžÄi ½¿WÒ,“€É$1Ñ >ËñáaÒË Ê—^‚ÙO2X/Ù^ö1ì¿/X/üõ¤Ç(ô*Þ¼ôË¿ÈíßÛ·û_òÀZàXa¹eIÊ„ê˔ȕx<Îàà ù|>LË›L&KæÒÞÇJbÛþ¼M:’I©–hÜÎÆÿû$‡ßò"¸¿ðÊçaU0‰ðk_ ÇFá¤WÃe`®²ðb+(úÈŒºýKÝ÷åæ1ƒÂܯ”Y_"yd¹¤f<¡/‡éBeél6Ëððp˜f<‘H°qãFR©ƒƒƒ$‰PLëééÁ²¬YÎòx<®˜O“ì †aÌJ1.BÂJe 0‡üGå÷O;7¼ûÝ /c ¶Ú¶í0Õ|-l~Tµm›ñññ0¥j4…£Dƒ¦Ói®¼òʯW3!Sá5ÛÓ©¸K2µøoLaŒ}Ažâï´±í ŸÐ×WÈõ þÃ'*ú‹—ÍBä|„ëÊr y÷1â÷A0 H¥qïKàÃ~¢J~ÔˆXï~ë—þC0™ô×ÔãÍÿ÷XÀÀ?ýà]¯}m¸L„U3=é aã “0òï·ßÎ[€]££|þÕ¯æo³Y2™ ¯Y·Ž““¬¾ðB¬Ÿþ4|MØyê©|aÕ*@³,N<÷\¾yëyÂ0IBªmÛ\÷™Ïpl÷n>òÜs ïÚUtnäúëŸüÄ]ƒ6Ë¡Œçw¡ï äó|óä“yK…ˆÇx>ïÇñ'p °^qˆ´{&n,¹ñ.åT yùxÅ+ž‚A™ ¾é&úž}Ö?÷2Ydô|‹Ncy^èÜŒ\l|üÅ9ï®»üöƒ@Âz÷÷“:«—ÁŸ~“OãºvÁ^:Ž¿´£TdîëóÏŸãðÑóÎóІÉ$oËå˜r]žyæÎ=ýtÜ·¾uïªÖ@#ˆh+sè.eŠEQ‹©\N_«@¢£$*|ž« AÅJ¤ðßÓ¢8m ïUQט¸Íȶ¥ˆkÌ–K€DeF‡?Z@Wð›E±˜)nKqÿ•¦f…b!´šß£îPù=^Q÷itÊ qEg(]EÀtðÝ•õ5)Ä7ˆk2šn÷?ó›ðþ÷Wq&Ûˆ7>w‚ÿƒgaþZ![FðºÍöíÛÉå¦gm¯If‹…øx•¥Ñ¶Â#À©‹I'ãP2Îäiáâ p‚ÿûË¿üržûîs\{ñµÄ†cŒ›ã¤÷§É}:ÇÕîÕEiM7Z¹„K _È|ôï¤}ë6îïs kàoËWm³µ¹ Ve`Õ!DìÝ/»›«_ðS‹Ý~ÉíœyÝ™\÷Õë`µ_ßD&Qš§×/ÂD,“'³$mÑ,ü&"†7ø¢¥K!·ˆfÑ|v’ MaHTÿÉ7ì·#Ì•%ÚQ-;¾Ý.zÓyo‚;)<¥­È>£Ã™¢b¨xž%*QöïF¶³)ä(r¢ ð‰\'2 ,:ÁWÔ¿*C•¤ÓE!½ çŠæÿ“^UŸHø¯:–®Ëôyçqø®»°€c›6aš&Ï>«ùéçBíÄb1úúúêþ\Seyyò%mímhªž(î°¨‹¶Òzé’rcÌŽ·ß7J±ûPÒ´Šû5ºn)"ðUû»QRNi™¥²xiJÝÑT¾¿`FÊŽW(K)FÜä/úäHçºyñ¸?ØöÏþìÿã×~í‘YÛ«°±Pá±v´õ“uëgT·¢Ö®]ËûuD3Pýÿ×ûß]]0:ŠcÄè©íÄöƒ‘Úσ۷“øùÏyÓç>WˆŒ>ã+=©¯ûñøÑæœì¥ôr çCt¾tï½ÜT6ý©ß‡ µÆri€M“x…<ò¶íkY¢Ë•Ý~÷ôÉóÏçX žšÁĈ'=ÊG€ƒr=•س/¿œŽ}Œ'}” .ê`͆r¹ÉdÒ·q|°Ã@˜øÈG v'“ 笼nõjÖ>ó̬‰¶ #8hqÿÀmr—^êŸÇ œ áqjûv6–;6ëüDÌæû.-¾.‚ɾÀ§#'èlËâ^x+ËÙ6ÓôëçÞÀI§ýW*9ï†ÁW¯½€+#õ‘ù`û,¸Çߎyèï¹ëç?Ç“‹#a)Bjé ¸+Æíë Ë\‹‘`æoþ†šjuNd¾`™{WçÇU”ÖãWÑgšÒ´D“ÒUBžŽÑ§¦¸xí9Ö/·¯f磺hTe6"<>³º›UÇü¨ÿeš~Šë¯ÿkÖ­{3_øüáֻƊÒœXï Ô‹ŸžrÊü+%ñE¤ é-s¢ÈJ|p®ë2¤ÉÉçó|í¢¯qâ‘ql‡‹ö]TÑ©W‘a Qj íûˆ¨ˆ_çŽË Q€áP‰°‹SÁI°m?…äâ¥Ht_™ãæ^”DíÑh?©CŠÙ‚›,«¾åêÞÕ¬‰Ž$_’£@æV\ ’ä}1>Îq*÷ùÈÓè|JEà‚‚. Rà¼à?ö÷Ö©ä§–y^’É$ýýýaª%™3µÜŠÒÌÈ ·üvXû4<Èÿ¾ê—/NodÍ1Xÿ„ïG~ñÁÂvŒ->#S>ŸŸ•Â|‘Ïu]²Ù,===8ŽC__®ëbÉd’T*E*•bÿþýŒŽŽ‹ÅŠ¢Ÿ$j<Å'×uÃÈëD"±béM˵G¢kN°Ï§žzеk×Ö~ÿu¦R*_!—Ëñö·¿½ÞÕlFS)>xÒI\ý™ÏøÑbÈ ÷øð0`üðŸÀVŸuÖÂw2—CfCŠRɽYÙ¶™®–rÉä”…±öùßõ?”¼FŸwÞ4·ÜrK½«§( GÛF<[³†Ó~ö³Ê+äñ#Ö$Â±Š¨¹hª X,ƺû×qä70ðìì]dE%ÉøB‘§I>(cÿ·—ù%šq¡ˆ˜¢\èö¥†U2qép)Ï<ó û{öÃö®…·=GA ](’»`)þÕܶ•Üʼ<¸e ß{Üö;0 VÄi%ƒÈƒlZ³ÁÀqlÛ¦¿¿–£HQ”æA̦û½C;z&|Ûÿþ’'gè¿NÉûQަ k&à¬Ãï8N¬bÐRH9Hæñ’èE™—Ñu],Ë Ó§Z–Åøø8étº(z1Ji:ÏÒï±XŒÁÁÁ²Ñص 5‡È±¢X£çœÃÉ¿üe[1M³ÈY^J:fÕªUõ®fÃð‹þgvmØï}o(Ì• $3M“—¯];ÿ_STpnFÙ¢DoÝ->¯{]Ùuæô™Ê|’e°mØ¿n]ljÃ2@÷ÕWcnÚ„aENZÈ—DTG9tê©|iÓ&>ð'Û‹~±QÄÇYs`&“a½õ«”#(kb<¯øä™&W_xá‚G‹Fpª³7 ?$48Ðï¯2û°Ê,«FÀ]·oãF~qòɼzAµ/ðÐÀ[dÞIüçBLsÒÏI2™$ŸÏcšfýžcŠ¢Ô„¿˜àÒLF'ckb¢)DçC⥠àÕ·~•“ÿ?¡>:%ìÈÈÓÓÿ…×¼fα}ŠÒv´eÄ£¼j_²ukùzð£ÆâøÉ¼«4âÜéë룯¯£[²ùÙÍ‹½·)D.fÛ…yŠÌ (ó3.38†‹MïY)ÇA5Uw ݇®ñ®Å €6‹%5j=z1²ÏÒdíÊ,Dd8þ½—Ò³ùá}fY~GA&‡†òóŠ@J¥Â(¢T*¥s½(Jc½ðîÉ¿ô¿ÚÞ¹çÀ²`íAÿ»mÃé'ÂûÞá¦äš™7%ØÌaFIDATNðzrÙ">}ýõ<øÞ÷µ»§«§ð5e‹®ÛG‚ÏÁ$–gŸ=ÿ±N§ýW"ÎÛ‹Å–ÍÑ9Z)„ª 8çœsøƒ+®€›nªwU˲8餓ê]† *ô—RVJ$ŠHƉ8…¬! @Àï|d€šàÅý¾:Á6É`ù0~ÖÙ&ð ÙãÀ}A¹ß2 oׂurÀFÿ£•n Ê‘¹ÒHe*ƒÒfŠ>&}ž4…té¶×\t œ¯»˜ß¿â÷ývÓCäòyîà³ôî|3Lja&“÷¾ø^Žœx¤Uf#l06"Ež<..ÿvÒ¿ùAcÁñr-xižvÁÌù¿Å(L+!ßå7è±À0ÁKeàwò>5^h[¦ä8¤)Ì?…©#ä=“€‹]øxL%ü6¥)dj‘Ÿ2xíÏÆãqb±X˜LQ”æÅ¾ué^Àþ'^Á«ÿgz¿}ÞÐ÷iÈ›p–tPøB!¢̳è8N˜!!‘HÍfÉåraÊ=Çq4­Û2’H$–åÔÂ$ †††ê]úâºûìgÉçóìß_277{0àwR)¿¿•&ˆb”ò‚ßFñûá12…ß76-xÜ*8.bÏ{/쟬¿APž\n§ÌâÁãÁ¶¾h'Ñ“F°,/0Á:"BŠ@)ó²»øS4ˆø%fÈòëõâÿxÆaê»S¼rÃ+áÛÁò‡ýƒp_âÒôûüíöeÿϵÏå™/?SÆöûíºä¯/áw_ò»|öØgyqý‹þ1‰u5› 8Ù,ˆ"ª¦ƒãçEÚ¶®S8¦2ý„kÏw/‚œ39'&…èS9®‘8Šfa€f2(ÃÁ}Ë)\&ü|ݹì;÷•ü¿rnå½SÈGê%u4 eŸø‰?`ýk_UÈ #çR®Ÿ|¤îòþgßG-ÿ]÷o-è¥0ЖB“žúáSóÞ.í‚<§‡5墢´:¿ckP 7äBÒº*­Á¡5_Å}ß¹˜//\a¤ðÃ~”gŸMÑß¿z±31(5džéî•e¤-…GèxàÂýøO¦ N‹šÏçI&“d2Çaff¦ÞÍ+`ÕØÿöC{?óâ'=Ê—^„GÓôÄWÒ%í’eYÄãq<Ï«j~EQš€oÜøÉOÎä¯;À½ÜÈÑ9‹[äº.¦i’ÉdÂ£†A"‘#¨ÁO/(щ 3©ÙI&=ŸÒ¤ÓLßwPìpÌçað`^Z²~䳋/ðHŠû ¾ø4L!O(}¹±‹`ûr·{iê|Ñ@~ßš­†FÓíb^(.ɼõ£{ʤ¼4…ùÍEhË•)8jŽÝ δÎäL΄ߑƒæÂ-à˜Nq½KªºÆ^NATLÁ_:Y8öäÉ%rÅÇÍ´ Ç-Zvi†û~fÞ.>fÕš€ÒwÁhù9übð‡fa¹ˆ”-Ý—mûÇø'矊ÛTJ¥:âcŽÛÛgS»ÌöÑϲ?Û†\™ -8¿÷ʃÔúäóyü£(mˆ¾Ó7?µrÊ•¢îÖöá÷ñ̯‡Ôì³þ©Oý>ÓÓðÖ·Ö»–ŠÒX´å.ð’'ŸôÓ¦ ⌕Q· $›ÍÇùfïÌ­n• Gaôs;q<ã`½k£40ŽÃ‰ÏùfP¢—Dx¬„¤\’‘Ðúr¢(͉ØÖgÃß ÿñJ0 ¶a®Û>_Y's8æóyÇÁó¼PXLù=D„TVˆtZó©(•ÉfùιWÌJ§è~Üc`v@|~*Ó~|ƒ!‘r"0Šø˜À™ªî¹’à8óÍÕ*u‘H½,þ{DâY‘å&¾P¹“9.¼°º¾‘DóEí¬r“TÚvõD@]/Ni±˜&D£àLüã›-³î2GZ/yqKÝ£Õày®ë–¿EQ”†§VÖ[ßÞÚ‹Wò<'=]˜¢":“I?—_Þ1k&EiwÚRxt€§¾õ-ÿ‹/Î%¨ÞI $“ü·ñqR®‹‘É`—¾\BWôôø£íË ž·ü/ÄíNä4lºpS½k£4(ÎÔ×<÷O¼ã ÿ»ѱ•| }}}äóyâñ8¦i.Ý ¤(Jã€UO=~FBG×û÷WöKT£ÐÕÕF1júÔ:âyšOE)çñwûý(2×%ŒB4‚¹òßïf|Ñ.OaJ†qšc˜{ŒÅ œe0M341 ËbíÚµ‹HaY†a,ŸØ“Þ4¼üÞÀҾŸCñ‹…ƒUÔ¡\jÛ–<@E_T…ã8†¡ƒ ¥Í¯w”e :µõJ£ž öâD~Îæ­›ÃïÑ×þX0(PÝûŠRLC ×\s ccce— ñú׿ž­[·²{÷n&''T¶ø~ùË\øÅ ÃySHQþéäyÐ×狈É$àG9žp üí¿ÈÞ»îbú¤“üÑô¥/ƒ¶í{'‡‡ý¯¥Bõ÷ÃÆ¾8™LúeDq¿é´oѲå†Ò*³ˆ¼#zwëd‡ÍÊJÚŽç,ç!N¿çtâq߇Ô×WX\êSJ&“ôôô„ÑÍ*8*JmXq[`„Ž~ÎË_>I:]xq°mÿ_Í‹D6›ÅqÇappX,Æàà ®ëÎ%•²I9•†¤’-X’ NL¼ ˲è~d£ ùÛÁÚîðÂnl±±”áå«÷|(¦Ï;oÑ‚kK|¢igkD–ãF®Z ²¾}‚L&3+ZQ”Æ¢VïJó!ɔ֧–v@z§\^%öȉY–ŠŠ¥áæxÜ»w/e— 122ž={èììdhhˆÝ»wsë­·V]¾t?Τç±ylóÜs:º®¯D†ÿ?¥jY‰D‚ÍÁ÷ŽJéŽäwQ5JI¥üÿ®[>ì7›õfžç¾õõùÛ›faYt_®ëG\ŠÃ-‘(ñŸLúû޾ˆ–¦Œ ×°N±Xñ‹t&SlY cöˆÚ|Þ_ÇóüãhšÅe¸îlë\úÂ'mrJË"?utv'Þñ£eÂVJ&Ñs Ç;z,eÿѰË*>vŽSìÜ,].Û;NáœÉ1‹.w]ÿ·J 9çsQZ—&z^i;ðƒuë¸Ö;ƶnH»¾þ¥ôðÆb1²Ù,ýýýìß¿¿Þ‡HQÚ‚ZØ~|óѧÀ>——½ê/9ÿü?婈ɔˆÇj|¶¦iâ8N8oc"‘`8HË—H$4¥ª¢,‚J¶`ÉvÀ¶af†ÇOðE/ï?ûB* ™Ã0 öíÁúÍêɪUжٲÈô¢ñè8Îòµô<šøód–ê±%}yÛ¶UÐZµèd³Y²Ù¬F>)J³’¶@#› xljæ'¸óîä%¤ÙÉ^!nïèû½m/{¦}EijFxá†n˜s}ûö100ÀÀÀ7Ýt¶m³oß>®ºêªªöãçLMq²iúO‰è»_:í EÑÂX  òŽC2™dØ4I§ÓÄb±0”zÑH§¦Ò¤r¦9Z0‰¦„òÃ*2¿ìÑQ_ˆ*Mñû/Å•"dŽJÓ,~¥)†D4”ež7[xŒFsæóþq–‘ÍÇ©{LM—±qcñ÷R5.ˆ¤33œdù·§ðÊ{Óé±´íÙÇÊq !q" Ÿ;r£uYP;J£_s¹âý ïǶ‹ãl֍гMà訕8rê©<ðÔA~r:ð¬˜æº¥ûúúH¥R:ß‹¢Ô€ZÚž<'Îå§?}„ÓN{9ūȸ™¹‡¹D:ŽF'~M³Z/r9ÿ™É”¦4,óÙ‚å´>ø^Œ_?Šeý )±]À†z…&Ã4±á¸§K«¾×±V·{¥¼n% G-ûŽãǵ¿¯( H-lAÓt(~yTÈè¬k0;J_Ê4qåð8Ô/óƒ•Y–ó;F¤ý•º#n°Ü‹ü]„æ¬2uí©¹Ÿ `ã]ù$û‘Y¾]>ŒãìÇó¼°'q6Š¢ø4ŒðØÛÛËÍ7ß ÀÎ;g-Ÿ˜˜`rr’ÞÞÞð·ÎÎNº»»¹çž{ª6.pÂCqé¦Ký4«òBšÏû¢Ñðpaåˆðgš&†aÏç1M³q^FLsn'š‹PÞcjšsÏ÷aš³# K©Æ‘:_‰ÄüóŽ” xåʰmøÇ@å¨Ó…Ô1¿¤2ªi‡D "üVÚO9ÁÙ4}±y©âx©•™ýíüúX—û‡ª\6c×uq]—D"A,kÞ—Ei"je „ü±ç`íZÜ`‚·Ë/ïÀq|³/f´š[ßq,ËZžÁIÊò!CO³Y›Œ¹lÁrÙLšÇ×¾v6[‚¹ Òçõ”ßun”.Ó/*ÀRÞµ<Ï[žˆ™w±ΟøûÑ hÉÔ²Oà8Ž ÄŠÒ Ôúý`"V9ø y ‚Ut®ß|d]ùÍÆO©`â?3’ÁzòìHýÁ6)|_¥,—2Á:þ|Ó}%õKõÈë[ø£©¢D·+WFŒB¿LIÕ7GÑ} vÐÆþàû pÂ"ê:…Ÿþ^ö9 ‚ã$sX§#딫«³D°½SRÎhd»ýÁ~¢¢¥¬/} ³¤½íÍ”Y_0#¿´7CÁ1%íñ(AK]}¸~–ódDʉ^wQ¡Ù+)Ã.ÙGtŸ ,œÕ˼ò__ɆíÂï® ÃÃî!‘Hõ]Õ  (Fxìì줳³³âò#GŽ€õë×W ¯ž|òI²Ù,“““xœuÏ=lß°$´ˆŽsˆS™L†X,þmš ÍRÏå²`Àô¿>Pï -S›æ¢Ü9®à)cllŒC‡Õ»UeYI;pèÐ!†††8yÇèîæâÇëmþ!¬4õZ:ï{•VahhˆÐQÖ× Ô¢O066ÆÙ{öø×> [Öãº.ëÂ1=ɤé˜JÍÂ/%™Lb±XŒžž,ËjœAJŠR†ÉÉIFFF¸óÎ;gÝKÂ\¶`©}‚Ç344Äx:°“ÿôŸÀ|ò/€ó“¦HÑRȻղõµj™kM†MÊÈÈ“““>|¸ÞU)ËJ¿Üyç 100€ã8$æ »Tòø×§8w£×©8”=Ê_Ã^d(ÎÞ”l#‚…Y&Žf2,ŠÜsE ò¾$.‰Ƕ”-m“ò£Žø…ØV'RNµnÅìGôýà[ßú]2ÿŠˆSyà¥Übùß?åÀ‡‚›Ä^ãAg~š‡Slø±WÄ o^ øFrá8ðcàï;å a8ð?’pp–_®‹Á¨U¸/Ý üeÎÁÿÿ—Àþ\ñ}Ñ×&\(If fâ~ Ÿ†t¾po¤ýÃÅþ¤þ~È:`¿å-ØŸŠDB:þ ’/ ¶`8^\F6ëêºÐçÁx®Ø¶$“Ðtxp^–|&^8ö÷ºðHÇ1ïA.؈~ßÈÀ ná8º‘2ÀW†2™âì¿nCÜ.ØJ™’)œdúeÄíb;ûOI8 ¾gÀ¥6xVÁ>váø>ð p7°%ÌB{¼,ÜêÀýÁ6—"ÇàIg/7àîDa'\xwn”ñ`³`÷®ÌÀ3naðÃD¤=.\†¯•¿xΆ»Š&mÝË®ÃkiDjå3ìíí-*ãË¿öeêxhÖú¹\×u‹-é;„Ò ŒŒŒð½ï}oÉ}‚†W’Õ«WÓÝÝͶmÛÈo>x­G{ ¾drÞÈ?Ã00MÛ¶‰ëhùÆÆÜsýÏ›ê]™Æ¢³³“ÞÞ^¾ÿýï×»*uáÔSO¥··—‡Ï8ƒÍ¿ð{tæ[ýŽd.%‘H`Û6^¥tÄŠÒ„ôöörï½÷òè£Ö»*5Gú¯zÕ«ø¢üøü3ÇŸ'ŸÏ³zõïÍú6!›­Ü5H§ÓÄãñ0B'›Íây–eiš6¥)X¿~=½½½8p ÞU© kÖ¬á}ßùÜ÷ þ…dÿr¿±ÿæßû:Z¹É)—FN)˶mÛèììÄ)×n6oÞLoo/žç…Ïñéþ‹p£øºŠŠlI Ñ&Ñt„óE¥ƒý”[>L!òI¢‚2À:&ƒíÇwàKyÝ#êã›]ØŒ¾³<ì'|µqáS.|(P*£û¢ûŽEê,mwð…K=Ø GD#¨WOð}48Vn™òÓÁú⥢ÇJŽOŠ‚›”‘ˆ¬–"(?ì7]Ò¦h„PŽ‚“^Ž“D Éù2ƒ}e‚c%׊EqDR*r¬ˆüÌCŒâè«Òuœ å¢ÒÜ`ÿÅÑtn°<ÙOtŸ¥eȵjÁ®Ñ]=z”/¼ý ´«W¯æÔSOeóæÍþùêÁ?®N/¶ ·Ú0•+Ü“® É,X¦/ì™&|¤äå!œàK‚ï2í“`ðpÉëÏ¿îDÀÈ›pI°ŽmY±J‹ùõ¹ØöGN†SîËXaÊ Ïó×-ìcÛþèKɺeš…ý˜€kTÉ¿Øl\n“ À£¸®²®ç„¢E—G#õœÈÍUš Ìó ívn¢xPBt:&¸ÈÙщ=_ôë êú‚Ñ9$x)þ±qøŠÏOÒ× ‚$‚º–&Kësà²H¹¶U\׬ãÛÙ£P÷›¼âc› ŽËÁTX§[P4e± I÷ÓÑãÙ—v8ãŸ'9cª=;Qâ3qS®Ž—Ý÷ïìÜ2ÛwÒLÇ•Ëåš'@IQª`Û¶m<ùä“Kö¶…ð¸jÕ*^õªWÑÝÝ À3rΆsàÌ`…y&¦ZÔÔ+M€ LŸ×Õ»2…ŒÚ»wo½«RÖ­[Goo/ߌ=ÂÔ†)²ÙatÓààìmºººÈårš6Qi)dô^£F7¬$Ò'èííåÏ ü-ë/ãÈ}¿ ›ÍrÆÿ æg¨4Ö(™L†ó9d2™¢— Œd²º\¹mFGG½½½Œ-½°&dÍš5œùøã˜òG©¹Ó྆ë÷4Íj“£ç®jä¹]ßDx”)U Ã(:"<ã H’ÒÏÄÐz(¤F´o¸pgÖàG­<èÀ§Rp±å—7¤“ð ÖâG-9üû”¿\fä8!ÈK(ï&‰Da*ŽÌ@:¨ŒˆŽ2‡dh0úá°ß~iú‚B*˜Vf?°7‰@ÑúP°M.ä™ÚÕ×çg‡ÊSø†g ¡ d#9ï~-3‘iC’Iè‰äPì>». ´.ð¹$|ÇM.t›àÚKœáNeu)p øð)ß1/Ï—“П Xþ~ÆsÅ¢ßíó£Î,_é0a4ÒÑ;èÂ[²p»çGk]| Ò¸>鋟¶ýHµß¶àÍAE ਠ«\øqöÓ&Øñ‚M2Ó“pšwyð,ÐgÃv» äžèÂIy¸Â…¬åGŸyák]x$¯vá]1XoÀgMØdÙ{ópÜ7Ä‚AöÀ]yø¦O{ð¸ Û,0­0úuý%òÂÝ㼸þÅ庽š†U«V±nÝ:Þô¦7ùb²‰/ yÁ<á"j‰° ®ËZúÔD‘)ž*bÛÅaTåü’óHÌ7MS´ŒJ~Ïjê‹Í?zk¡í«®•¨æÜT3%St:®Åîg9¦§ªæ¸V$3O]Œ`¬;wróü¥µâ3äòÆ_|]ù[³Ö—4«ª(­Fww7GŽY²Ï°é„lj‰‰ðå(z0·ܚ+þ¤ªÒþþþYaÓJðêàïÕõ®ˆ²,Õx‡sš÷?¹à9ü~:ê`tÇqÈårzÿ+Jƒ²}‚<`œ·†{œÊ*üÏà¿ë†Ÿ¡§ôýÌó_HãAºÙxÁ1'úúÍNåºþÿ )Þ¯ƒw”¼³•ÖË "¹<\±’h¡<Èû‘eO8~»K_/ êðÝ@L}EÉ:™<|7ƒÜ¸Yø×Xñ1Ü8y¿]g°Á-.#…òð¢áGÓ¹nAX¶ƒƒ6¬6àºþ‚dGD±Œ G³ð¿3ÞDE±NnÍûŸ‹ÄŽOÿ1ë·ÿÍÌbmÁ?øAúO8~îÁxp¾ä¼i$“¢4Ëá'ˆòøLG‘°kYpõÕ‹çy jfDE©@Ó2âàž{î)2cccUO+÷žçq½eÎõ3™ žç1<<¬Ñ M†µ¸Œï×Õ»6Êr±v€Ã‡¹ôÎïrß›OÅÙ{Yøs4¥b6›%NcYãóDE+ŠR[–Íàû»²¯ã›G¹n0ËÔÔvœÀ×ä8åÛŠ}0M×u™šoH¥þ¨’Ôr,‹Èç9™óxçkŸ%ÿôjŒ×ù?¯ôoJ PqÛ°\}‚0Íjø yÉ¡ÍLÓO©h[`—‰‚±¬ù£cæ‹Z2ŒÚLUÍ~* ¤ªvNH9f•Ú/Ì÷|®¦®Õ<ã狪&úi>Áw9Ê"Žª*£Òõûmíê*äŸïÖ¶¹sß>5i&„¥Ú‚­[·rjÿûàÀs°[EEiF–ÓOåÖéŽ_ùÊGH¥Ò Ï÷ÜW”6æÄzW`! 022Âôô4ৃéèè`ÇŽUm/£‰ÉÙ#·À'’s®oš&±XLEÇ&$•„ÜÀjÏi‹Zš¥Ú÷䵜4³™mÛ¶º1únÇI¥R¹¤( ÊrØð§J¤áɧOå®»6 Ì—t«¥Ø¶JÊÍ—GQ”c©vàñk®Áa_ܲšØï~WáQQš‹ey?p]®yà8ÅRŒ–bÛ~'!‘hï|Ì2¯ ÚÊÆÆ0|Á±ÜµÜ¢,ŬùÕ¯à@¾V]ŠÒ´,—Ÿ ʧ½nÖo7Þ…mÛí¨(sÐ4{öìáÚk¯åšk®¡££ƒÉÉIöìÙCGGGÕet?ÎÛ¹ÈÀ®¹G|e³Y5 ÍÊ8þ(LíÜr,‡ð?É)Þã³N³Ö”Ò××Çèè( õ>*JC²¶ÀøH‚ÔM]¤1yä²ËÈdüe–U~`øàà ù|žX,F>ŸÇ², Ôè”K#§´Kµwðƒ<÷…WÂ3*6*J3³}‚|>Ïg®ø0L½Þ›?r±ÝÑ®OsÐf×ñRlÁé_ÿ:œgÁÍÚgT”ff9úQ^ù‹i~cÝx(ò›eÁöí£˜¦¾@(Ê\4¤ðxÿý÷—ý½££ƒ[o½•± õömÛl8^ö䓼‹ûà2»ªŠíÔ¤ Û«ŸÝR¬¤àDxÑùf|'œàOÍRz«Çãq½ÿ¥XI[à<~Ço|ÜàðãÛ\rÉÜÛÈü޶mã8ŽÎÛ ¤RÁ¼\Y籉)g –j<ÏãÏÖoä7.¨wëE©†•ê8ŽC‚/ÿÀ¯ÃÇs‹ŽdtƒÿàQȸT;²þb÷s³•Ä.F°þ²ŽÉ=ØLÑH!ó*AûÝ’ý{eŠ0#uŠ;y+Ó³ƒßÊõ¼ò‘u* )_i~V¬»ÿ~xÀö/u(Jó¢>À¿Àžxâ‰3èêZUïê)JÃÓVÂ#ÀY?<ÀÁµÝlš#Ú²,RšŠ«¹Ñ©9• „‚)?ø%†èƒX,F"‘Д ŠÒâ„#çÍ÷=w7àmoÛN6ëÇ•²qãFöï߯¶¡™Ñs§”àº.O>ÿ8Xïš(ŠROÞ{ÛƒüÉ?]Ée†/¾ì§²PUÍ£¶HçÙ@ƒ|£ÕXŒݾšmWRk•²cU¬«°íR{øaÆžyf[ظ¬ùÕx}½k¡(J£ñÖÿóUî=áCEÉsvî¼Ï~v°±ÞÕS”†¦í„ÇG6òxÇãlª0´9“É`-rNEQé+²žÌ&?,KåëäËìÇÁØÀÐFƒõ²‘ßy[‘r$]Ÿìß ÊHãë™ào_¤ü|°<š2Úf;ó%û¡4*Tzω–.Y/Y':œˆž¥ó·Eç “ïr,dÛÒ4„¥õ“€,'R/I•)"¡©CTP 9Vv¤^"êÊ9(7‡ˆ¾Ñ6Dë"ºM6² ‘2e"ÌÊy!Wê)"môšˆ—¹F$¤Y.ßÓÀYoy íʳOæ]_¿›Ø{ÞXïª(ŠR'Žn=:§ îy~Æ$Ãð§fÈdüÌI:.QQZ›5ÎÉŒx›Ã{ß4¡««?È”XM|º¢´/m%<¼zbоïE`tJΗ a”[†‚°˜‹ì/lãPñDôô‚ýç"×Etß&Åb¥œû¨P)׆#²?Bô¨D•&(˜£ëÚÁ÷è5,Ç׉,Š·¹àû?NL,àJhº&ó×_Ão?õT½«¢(Jáº~rpÐ÷Ý ñ¸ÿ{: ÃÃ:®MQZé+MzÛ8ï¼iÎ>»ÓôFGGÕ? (UÐvÂã;oûWyÙËfýî8®ë†ÑŽ’~Ñ4 ‹Ÿ©Kr:[–ßÁð<¿Ã‘JùÇñ—EÈRA2™ô;(é´/6Z–ÿ7ö÷eÛ„sL £(Ê2âüü缄ç9¯ûnlû²PxL&ý±üÃzÓ)JÛ`ürŠÇ€ƒ²eË‹À‰Äb…g¶ HŠ«G¡¹Ñ—B¥ÿœïbüm§1JA[Jl³Uá7kŽïóm_iYµ¹Œ’õKEÆÅÌ…l+é¨1Mœà]ÊLÓÄÈç±mÇq°, Ïó|!42@êUN<5ð…Y–…ã8˜–…Ùv8Ø?îÛ0Œp3øÍqLÛÆÎçIE˜–žëT™:˜‘õlÊ_r ,Ë P;²Ìóa¡ Z±Éd’áááp›d2I*•"NcÛv‘¸•Ïç‰Çã8Žƒçy8ŽC,#›Í’J¥Â²ºººç¾N&“ضçyX–E6›-‚¦ |R÷\.G__333ôôô„ßS©T¸¯t:–„Ÿ‰}}}á6û÷ï¿g2âñ8}}} “L&ÃöDM´¬þþþ¢ýËïÉdrÖ¾r¹étšX,{ðžx<–_®­û÷ï§««+ü><Š/̲ Š¢´ùGà4ï$ÞÏ7Rã¡oÛ4MF%M¡¢(sÒV£w œzø%<ÙUñøéO?EGÇód³'…©QE“4©¹\A¨«Ó,î€Dµ qhÆb~§Æq "§ˆ’º ¹äEDL§ýß ¿N²ž,“z†¿N__AÌ“ÈJ> ïƒä§·m½þ~ÿ¯aøb`´þ"v&…ŽY6[,<† ]· LŠÈ#¿‰ð˜NûËs9ÿ{6[3ùÌŒÿ=qª(‹bõL›t¯9·èçt:ähW¥ðžšâ{Góö÷¬*J±ê?oÝÐA¯49jÛ• \½¸pyÊ*£âñ8™LÓ4q]·HXAÑ0 ²Ùl(ì‰x(âXTŠFÄI"fÉ )‰ø‹Çã†A"‘£ÚDà‘É0 b±±X Ã0”҉DÓ4Éår¡cŲ,†‡‡ÃúzžG*• ÷g”ŒÖþÔLÐ/ý+uÎåraDž´Íu]LÓ¬¸­´Y¾Wc£§¦¦Â¿"øI,Ëb||55UÔ6I/õO§Ó†A.—«ØÖJõkD® ù=Ê¡C‡–çfh2VûÛðáCpœEi_ AÕ‹ùÛH¢(-Ä3ðÚï?Ï7Æuen× étšýû÷×»vŠÒ´•ð°i|=ë#=‚l†‡Ç9ï¼ûI¥üèóѲ.: ¶]©XŠs]!©[Áÿ."¤a¶ŠÇ ‚%"1 $Ò;™,œ®ë‹‚"Ѝéy~Ý$BQÊ¡ULÁq ІQø.uò¼B{¥ÍROiK¡­Ñã 9ó%Õl¿*‚k&㯗L&ó•cÖT”ùp6nàÅNŠ :‡›¢´“‡1]—ô¯®øá^òyÿÙ…Ô}€ÚEia2™Bß³ZD|2 ƒL&C, £ÝÅqœ0ZNÄ>ø¢‘ñx<®DdQi.q)¼¬ˆ˜$eÈßùìV¹ì²d€(ý®–JTŒ+áæË<±”ýGÅÆèñ’ïóe¿óXz̪e®õ*^d–Úv¥2¶*ŠÒöüêWkÈçýªÕ"þ5ñë)ŠÒ:8°qýAdb?#¢¥ÑŽŠ²ÚFxüÁúõ<Ȱ ÏóE,ßÑØ tVÜv1¢#İ|¾|ŠÓôŵ(Ñ”¨²M6[œâÕ4 Ñ…Ž==…ˆÀJuŽÇet†o,E$”‘Y–åÿ&u•ù'¥¬¨)*¥n’nÕóüQ_²},æ——Ï‹ RN<^.óù—‚l/Ѩ’6—+?5 A©Š)8ºÿ$Ö¬Yþ”N§Ã4aŠ¢´ ¿:Ì ‡×áygu[¶é¼ ŠÒxÞüYx% OÄD‰”¨¸hÄœŒ~žK4„‚À¥(JýÙ¸q£f7P…¯ýôpûBˆÇu¼¢´"Þáôýûç8a`–õ€p EQª£m„G€ÎCÇybË@!ýèßüÍp“åFÄ;‰Ú["‚/¬•àÚ×çGB–Y%bœø5DÌç‹#:ehºV‰~”t¨¹\!ZR" E°”´¨"ŽúuŠÎÝÝ¿‡’>VŽQW—¿”­Dxz^A¨íëó—õ÷ûÛK{e>¼µp’û½±³ ¿sæ(ŠÒ>x/ÙÄ]kÞÁÚµÿ•xM™/snI*=EQZ—¹„GÇq”˞çljÇãØ¶FžéüЊÒüœ~úéz+ŠÂ“O¾d–¯¬$Ø ^îIQ^ú›ëºEsGG‘ìÑtߥóMÛ¶¸’L¥ÛÈÜÅå¶‘9 ›aÉvÓLÛ”þ•Ôþ²­lSî܆Î#ÍfÃù°å»išüêW¿ªÏÝ@8æf®yl #û>À-·ø¿IZ~EQª£m„Ç_­Yÿ8Ê‘Óð;?Ióà‹17ñ¼gWÔpˆ·˜â%Êf;E Ãÿ/‚_9$"1*ZŠU"%£ó:&“…ô«Rf&ã—‘Jù)I þú"ªÊü“®[H¥*B¤”'ñÊwIÙ*é)²Ù‚¸)Y‹·Ïf édÓi;‰ˆtÝBŠÙDbáb¯Ò8›á·ø&}ýo!Iš‘GØpÍâëHgEi'ܳVó˜ûÇŽý9ƒƒÑ¹…3d2·AQÚ€hFÂoNøß0 „ (Š¢(mÀ?ø0½½›«ZW„L&é§^ËÿüŸÏ`Û„⎤[αìº.±XŒd2I"‘ ¯¯\.þÍ£ée~g‰J×§§§‡\.G:.ž$»mÛ$“Ép›ýû÷ÓÕÕ~O$8ŽÎ_£z||œt:mÛô÷÷“Ëåèéé!‘H‰œ®ëbÛ6étšááaúûû™šš ÓΆû‘¹¤óù<¶m‡™#¤þÒ¾t:Ö)º9Ö²Žì7•J188¦Ancšf‘¨655nÝO©øZZ·rÛ”Û¬­›ÌùËí§t›è~¤ýòÙ0Œ¢¶Ëüà2·¸l½VãñxQù‰D"D'‚§Ìñ-û:zôh½oɺ"G°kßÏÂßÒé4ù|~ÞÌ&Š¢háñ‘Oä„ç=Òÿ’Æ=ßåÔï¥Ù¸Ê{ÉS>dÎÀ Nœ4ibÄðð0ƒó§q1ÈöåD´\ÎÜÊ-K$üm%¥j)¥Ñ”"b&¾óUDBÙ·ëú"¢´EÖÏå 9í³Y_ Œ¦n•}åóÅé[M³°½ÔWÒ¯ZVa´X_ŸŸFVÒâŠkÛ…¹/-Ëÿ]ê'u‘2%j2Ÿ÷ëT*²Úv¡®RvÇ)¤~•t¯::Zˆî”å¥ç#:/¦Ìg)ioS©B}M³xîËè5Miî”yDEð­$pËöŠÏ¿>ñÆOìã<¶ÝÊcç>F]³Ö³©Ð®®Â9“tòY"SE¼íêò·³,¿ì(×^»ðë±xîÔSý{ûX½¾x8OüãäGƒÑ…%/³å‡‡G–løÒ'Ú )£ÜK¢(·¾ñoWpÃÎÿà£õËf³ †/§KÞ^èðŠ1*QɹWi TµˆR”K–$IßA{pžŸDûü¥ˆCÚÅ ö‚ÜßâÄ_išÝYuÖGÅùý\³H`€b!%zlÄ&G—Gׯt|£ýr‚‰ü‹’&ÚùÒëc¾Ï¥¿Í·žÔßÁ™óQº¬´¬§Ïxz)§²©qpÈ’ÅÁ)gW‚K]ÊñãÇ9vì:tˆ7ò裲yóf8ÀæÍ›qpxfí3œòì)\ðÔ;vŒÉ3&9zòQNyöN<ñDŽž|”mÏnãžÕ÷ícíÁµœ°ñž^ý4/~)/{òe;vŒµk×òÓÍ? ã^ýŠWsÇÚ;–­m§<{ «žZÅᇗ­ÌÍÏnæÀê—ŸzèTNzéI;vŒãëŽ/z?/tpüÑãœ|ÆÉ<÷Üs<³ö™ª¶[{p-Ç6[¶ö.õ8u¼ÐÁôIÓ oÿ|óäoò‘|„ÞÞÞz7§.|áÌ/ð >Aœ8)/E&“ #eN7™Ûyjj Ã0Bç ýŒb0ZQÁocÑÕ„Ï%›™8áÿ[.g‘NC>¿%¬“ø{ÄŸ“Ëùƒó£ÌÞÏlÿOñ~öCÅýŒû~¨è÷XÌÿ.Ó.I0AÛ.”!>·hv‰ÒíR©ÂúRŸ•hOéqÿf4Ð#:È_ÓTªp¤®Qÿj¹ö$“Åuï¸É~¤®2ÕTi"ôÊ~K³vH@HtÒ ”èvÑõuÖ¡Ù8pÑý¿âð+^€Gý~Â'ßÈñËŠŸ3¢Tê?D•ëkF}2ؤÔíWTbÿ¥Ñháñg«×òØk¿Í)Ÿû=û ̼I²?9¯s1A‚$IR¤fdËaÁŠÛv~Ì䛓ûI;yMÿ)"Ä<ù9GúŒŽZô¶™8æ‚ •¼$c³ÌÎ]!ïX¤ ƒÍïtÈ—™m‰aó·Ž¥ À ËÚ_óKv(Êy¦C"¤ÀóGÝÙy Ó •*Œ°µ¬ÂK¾<ÄEtŒþ%*Ί`)¢«D&F·/E¶ ±žWˆŠ´íâ´³‰Äì¹3S)ÿ!/Ñ‘0{4|Û.n—ëú‚ßÔT!ÒRÚ] )c¡ ¤F;fAÝÿ|™ÿdîK‰8!²tß;wÒ–<ù²—qæ¡¿gêÜøÖêŸãðóæKz yP/ô$:{ªU\#2Úñ‚‹q,FGËJ™â¤,©ÝÈHëèˆëj·ÑYt4¿¢”rÿºu<ûâ¯èÜyœA9tß!¯;Ì;ï}'ýô9𥰒,V<§{œâÑPÑhš  bFÌÎe·\Üp”§Ü·bgäž”ïr_Ê}]IP•(èˆÑ<ù¢íä{é:ÑöäɇöDì ,—>D#Éþ¢Q$Ò9æQ›TéÅ0Z{Vô‘RG¹Î¢ ÑöËï²W¢BKô4jïcÄÂãísЍæà'N<§LÐ[$Iš4WÞ}%¿ßïó›ÿæ¬y’e1dÈàà0Ló¤êÝùÍðþz×¢ö[sŒzˆ/²Û@ÆÍðþ÷¿ŸßÝý»¸kÜP+´m;ìgEß×-kn¿‘Pê—âí* @ÑíjµŸjf(` œ¨”‘+º]5‰f–£=¹\qÆ0Ëeˆ‹vExõ#B b¬ü.¦Yø­Ôw)âžlgÅÂa¥`‘è:•[Ç!ˆ0-øEì”驤œññ”YåDì¨`ûò—ÿñü'¦…ñ6oæéÜ<ü›_墛~²¼nýëøÇ#ÿÈ–õ[æÌpå#ÑË!ïžòŽ(ï€2˜˜á;¶&=ë=Úà ýqâE ²dg  ‹n›£pº¸sj@YŸ@5Ù¢ûwq±±gÕe¹³ÊD}åÊ.—m¤´®R¿rû¢>ñ‡”~—}–f_˜ËŸS¤ùDŽM5Ù"‘ffªyl57CCC|¡ïJ¾óÚ×ðÇÿçKü—׿×-äM_nä‚î£úrË‹{¡ñppHוKt®‹Ë½=Ötïç„|çlŸ-ȺâPŠ:§xÁeúOäì¿uq/tx”Žê-ýîá±î=9:×üôõ,ø¬9fð»™âþw§¹}GrÁÛŸù­oþûQÆÞ?È«3 ÞþÊ[‡ùÔEqº¼°*Àèhç(ƒŸð{Yÿ6ÐÏãg/ÌÙ|âÏM¾öà~î¼(ß¾tpAÛ\tgœ{é0]ùAˆ/¼ívf”ÑXŒî5]\[~´îËï}9^u`%7?ñÎwòÐ¥?àoÛÎdïç¹jádœï!ºa#ꀎ¦ç‰:µ—‚”MWTŽhz±¨ƒ¿\ûJ;i+=º\)O<g8ÖÁí·ßÎöíÛ9ãŒI}´“ÓN;Í›Ÿ xšóÎ;(d ‡¯mGäSF‰:£ë âègúB÷#åG·‹FÂD÷3_ÄM5íÑýøâ@2é‹2mÌBÊ0ÍB¶'©_,6w]EŒèï¯ :˜.ÿÅåñÇç¼éÃüÃÇÿ€vBúB«W¯æ»‡¾ËÎÿ§Ÿ{ú¬ˆóVKµ>߀ëFxG_J¶–RD¹æÒ—Žö¹š¹j¾4Ô‹%*rWs ¼È¿è»Séçè v‡ Ÿ¶8¸Ö¥ç„€ɗ|ó%Üÿ–û—­-Í‚ô…ú€S?Ÿå ¿ÝOŒ?ùÉOx×çߦ¢mD$› à‹ÀWî>d©pÀ±TÈ÷jü‰¥ï´•®ÿRÿ‚øG 뢫êk]öäݶœíŠf¤qp˜bªH(ì§¿h½•´÷qâEƒ»èª©­ÝÏþð\eɆm/[×%ú Û&âñ#»ùÎkáį¿ã èëëcxxxE„Ç0·³'Ï@,K‚q,,bÄæþ þò ]¼ð©AžïvȱAÛäIIҦ˗ïðxÜv‹n¨jxÇA¾=å§Ópõ8_Þ¼°‹Ì8ÖÅ­/Íðü2¤H…Bk5¸¸t½¹‹§ïÊsàê ãÁ±«–w?×φ^c5`:EÛ—¦rŠ·Ÿ;7i¦5ÿJ®ê8-]}iž?ý^–÷oKðé³RᲨã3© õÉ“gðâA>ü·1øH†QFgµ½ÔGGP|èî ®w¸ýÇ6/s‹Œ‰¬ãáñ÷Ÿü{h/¿vwZç°æ{ã]è‹ÅjÙPÍ50RVŽJé/«]e1‘•ÑA"Ñ—å~Q™±±1Æ«Ùþ‰ñ çðè†aV=µžq~€ë¸ Κã¢IѸ/KL4J´4b´)}žhêò˜˜ôõõÇçœGQ”Ö娱5¤͢ȗ\n#SSçqõÕÿ‹cÇ6sôè¥Üz+ÀyärJmSêESé ’šP¢R¢)…jRF#[J÷#"S"Q‘ffüÏш›Jû±üè¦þþB¶œ…¤H\H{–’бUö“ͦr‘Ï -ÃqŠ×¡q®ºÊ”1¹\az™BZF01þ—´+™LÃ0Øûö½5ÙßR2Í•Z»cµƒžë9}ÌR§˜Pª¤Ììcÿýöÿo©wÅêÇ8Ï¿5É+nÞÃèÎO’½/‹kì¬(s¥[-gc$;޼7fÉ’ Q“w]7ÛdNtqÆkÕ·‘EÚŒd+Š ¡+Ež<}ô…™5¥í ÕmK=dÈ„~¡ $Êú‰–ÃgØ6Âã/})ämb1'™Èy%±±ùÎ;ù5/†eøû20ªrþ¼ý' ¾y~ž®Ž/øâ³°8ëê4?ÿfž S&ÆÆ…mÿ›ãôü¦éø£Uä>(apcŒô_ rÒ´±`£eb²åA›¯|¤-ÚXç.ì<­ù•É¿þÈåÂS°‹ŸèçJNþÝkãüî5}<Žv¾géÄøOÇÓ`ç¹!2‚¡\‡-º“8qnøI–}¿×Ï–mbçÎN{Í:“Ï¿"ÏW~épòQsYqíÈS«VñSû»\ýN:^q 4&ó½<-äåj1÷Ti ¯Å–£,žóïþ1Óoøð8·Ü"va30JÁJDשfýÅî'šÇªšœVåö…f¹R$Ö*c³ï§VuëHd¤âóõ¯Û¶k:i!Ñ=¥,ePYµ~ÉzÓ ulU>ÿóÏ×» uÓeÕ³Ó|lãGI&“xžÇðpkeв°d0LïâÖ,B2-uEæûl<µ@2‰‰ÕbßÙX—¶Ç‰‡Ñ­à ¡+95DÓ CCCŒŒŒ0==ÍUW]Åž={èììœw»oœ„uw¿ó÷=úúÃÉ¡W’„#A Ö.nû»8 ˆŒbañÈf‡¯=î°å€Eäz®zûÏÌqð ¼{ûÂö œý€ÍiÏ ¿y>½z˜ïßåò†—-üÆÝ‹#¯ÈóÝû\:°à¼…mÿ¾M6ïò{òö"Ú7büÙ“i¶ÞǼxáõ{õ°oô:¾íÀ¹·œæžçól~Ä‚s\DS°X;ðäËždu&ÎÀ^ÃÄÄ7ÔѨ(MÎbmÁ†#ûxáÙ“Øqô?‘ÍfI&“ì¯f"EQŽÅÚð3 Äb±p®gEQ𗥨‚áaèïÏðè£vMüŠ¢¬‹µ÷ß?GÕ ŠÒ,¥O?tˆ“6~sä÷¹6a?µ5ý†1bEb—DàÕŠèü’µ¦4ýlž|M¢…qê—i+N¼HdM‘ZQѵ©„G1b0†††Ø½{7·ú9Oæäµ‡‹Žl"ýxšñññš¥W¬&&'M<³;Í™ß[œxù¾M6lZÜþ >xÞâóe&—u.îÙ¦ 8lØìðk§-®Œ?Y„à(|ð<›.adÖRÒ-ÚØ=Ùãëó¼þ€Ý’ÂãRìÀwlåMŸü+¾Ä4Í–·ŠÒÊ,ÅŒ»„3¯äþèTöï7z®EQ*³;í¨(­ÂRlÁOŸoÙ)YÚ5ªØÆ¦Ÿ~’ø9óe*¤v¡–çýÄz7v!ìÛ·èíí妛nbbb‚}ûöÍ»íö5ÏsÉU“Íf›rTóØØ“““ ÚÆÎ§<œàŸ/iŒ¹ˆ&''[ùùÄÄX|æé,SãËÿò822²âmX §üÔâ…‹~û‚Ö4šK±ë6çK»ŸÁ0Œ¦u46úõW ‹±gF­ì™R™¥Ø‚G¾º…7üÍU$q²ÙlÓln•ë¯ìY+´¡™YŠH$m%4´ŠíX(íxŸ¶Û¹^Š-8å”SˆÇãme ôžhÚí\/µ_Ðn´Ûõ­á‹X ít®—b:ľ3ï„oǹâÒû±m»é)·Â¹^éûÔÂ"N'ø·©N[¡ßñØcqàÀ%•Ñ4ÂãÄÄ“““E#:;;éîîæž{î™wû—\üMþõ[{Ø¿Ûû®‰óV6dv!Ôò¦;姘.¯Y·ümoôNë·žgÊ›áÏl.Gz5,ÕL"‘hº hë¯ìY+´¡YYªhGZÅv,”v¼OÛé\/Õ¬]»–Dbq‚š½'Ú‡v:×Ú/X8ít}­à‹X ír®—j_ÿ"G6~Ží×ÃÞñv<Ïkº …V8×+}Ÿ¤H‘ þ¥X~ŸP+ô;–CxlšT«GŽ˜•ú`ýúõLLL̹íÔÔ_üâ™™™açÎõnÊ¢8tèßÿþ÷Ù»wo½«²hŽ=ÊSO=5ïùZz ‹§Vmgjêì<þÝe-ûá‡nêëèñÇgõêÕõ®Ê¢XŠxðÁyñÅùÿø¾ûÝå½.jE3_‚Ú³ú311Á /¼À•W^Yïª,Š¥ö þýßÿ'žx‚O<‘U«VÕ»9 ¦Ù¯?¡ìY3·áèÑ£<üðÃ<÷ÜsìØ±£ÞÕY0Kí<úè£\|ñŬ[·Ž³Ï>»ÞÍ© ­b;J3ß§‹e!çúá‡æèÑ£¼ìe/«wµÅRlÁúõëùÜç>Çèè(gŸ}6ëÖ­«wsj‚ÞíÃBÎu»¿\wÝuœtÒItww×»)5£mA+ø"CµçºÝ}†Çï;Ä˯ùcŒý5;vìà«_ý*_ýêWëݬÑ ÷u+ܧÍÞïxøá‡ñ< .¸`Iå4ð¸>þñóñ¼ÞÕP¥Î|ûÛß®wE©3Ú'Pà+_ùJ½« (Jéîîæî»ï®w5E©3ú~ ( ÀøÃàÓ'ê]Ei š&Õª¢(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(KÓ åBTÛ)‚¢(jEñQ[ (ŠÚEQ@m¢(>j EQ; (AÓ’Ÿ¹t2ر±1:;;ë]=EQj€ÚEQ@m¢(jEñQ[ ( ¨-PE퀢4M#< 022Âôô4{÷£ƒ;vÔ»jŠ¢ÔµŠ¢€ÚEQÔ(Šâ£¶@QP[ (ŠÚEi$N˜™™™©w%ªezzšk¯½–ééi:::˜œœdÏž= Ô»jŠ¢ÔµŠ¢€ÚEQÔ(Šâ£¶@QP[ (ŠÚEi$šJxÆÆÆØ¶mõ®Ž¢(u@퀢( ¶@QµŠ¢ø¨-PÔ(Š¢v@Q¦EQEQEQEQEQEQEi,šjŽGEQEQEQEQEQEQEQEQEQEQEQEQEQEY2*<*Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(вdTxTEQEQEQEQEQEQeɨðXG¦§§¹á†xýë_ÏÖ­[±m›}ûöÍZohh(\g÷îÝLNN.hy-Ûóú׿ž±±±·¡ÞíØ·o¶m/é<Ô» JóR-h¦ë¯’-h†6,‡-¨w”æd¹úÕ®S‹ö4kŸæ·ÍÐ¥5©eŸ¡¯á•¶-ÖæZÙ¢Fk·27µì34êµ±[Ðl÷D­|Ôf¥:jéSlÄëCûís®Wšfjó5×\Ó”ïØ­à÷œžžf÷îÝlݺ•­[·rÍ5×011±à:6ÊõVŸÍŒR7®½öÚ™žžž™Ûn»mæŽ;î˜ùä'?9sþùçÏÜvÛmá:Ÿüä'gzzzfn¹å–™;î¸cæ=ïyÏÌ{Þ󞪗׺=çŸþÌwÜQô{5u¬g;n»í¶™óÏ?&“ÉÌÜqÇ3×_ýÌùçŸ?ó‹_ü¢iÚ 47óÙ‚f»þÊÙ‚fhÃrØ‚z·Ai^–£OPí:µjO3ö ffæ·ÍÐ¥u©UŸ¡Q¯á•´-ÖæZÙ¢Fk·2?µê34òµ±X[Ðl÷D­|Ôf¥zjåSlÔëCûËï«h´vׂfjs&“iÚwìVð{Êþî¸ãŽ™;î¸cæÃþðLOOÏÌ‘#Gª®c½ÛPzNVúzRá±N9rdV‡`fÆ¿ˆ?üá‡ßßö¶·Í|ò“Ÿ ¿ÿâ¿(Ún¾åµ"“É̼ç=ï){ÁVSÇz¶ã=ïyOѾgfff>üáÏÜrË-MÓ¥y©Æ4ÓõWÉ4C–ÃÔ» Js²\}‚j×Yiš¹O033¿-h†6(­I-û x ¯´mi´6×Ê5Z»•¹©eŸ¡Q¯¥Ø‚f»'jå«h¤6+ÕQKŸb#^Ú'X_E£µ»4C›o¹å–™óÏ??üßlïØ­à÷¼çž{fÎ?ÿü™{î¹gÎv5‹m©•ÏFS­Ö‰ÉÉIz{{éîî.ú}Û¶mLOO011®'tvvÒÝÝÍ=÷Ü3ïòZ111A&“ácûXÙeóÕ±ží˜œœdbb¢hß7ÝtMÑ¥¹™Ï4ÓõWÉ4C–ÃÔ» Jó²}‚j×Yiš¹OóÛ‚fhƒÒºÔªÏЈ×ðJÛ–Fks­lQ£µ[™ŸZõõÚXŠ-h¶{¢V¾ŠFj³R=µò)6âõ¡}ŸåöU4Z»kA³´¹··—›o¾™›o¾yQm¨w;[ÁïÙÑÑÁ®]»fµ!J³Ø–Zúl^R³V)EtwwÏ2ÓÓÓÜvÛmáƒãÈ‘#³.ëׯ/zèTZ^ ¦§§¹þúë‰Çãeo¾ùÚPí:+…äîììä†n`rr’ÎÎNÂö4z”æf>[Ð,×ß\¶ Ú°¶ l²Òœ,GŸ ÚuV’fïÀü¶ Ú ´.µê34Ú5\ ÛÒhÏðZÙ¢F;×ÊüÔªÏÐh÷„´s)¶ š65Ò=Q+_E#žke~jåSl¤{BÚ¨}‚•ñU4Ú¹®ÍÒæÎÎN:;;݆z·³üžìÙ³ð…·#GŽ022BwwwX§f°-µöÙhÄcƒ°oß>®¹æ:;;‰Çãõ®NÕd2Ö¯_Ï®]»ê]•%qÍ5×ÐÑÑAww7“““\{íµ õQÚµõEmÒ¨¨?j ”f YmÅBi%Û²PÔ)óÑ.vÚרPª¡]lA»ÚP[ ´Ín¯†††Ø¹s'ûöícÇŽtttÔ»JUSkªufrr’n¸±±1víÚE<oš vllŒ‘‘n½õÖzWeÉÄãñ¢›Î¶mFFF¸ñÆë]5¥MP[Ш-Pê‰ÚÆ¡’-¸êª«ê]5Eij[±PZͶ,µEJ%ÚÉ@{Û}?Qæ¢lA;ÛP[ 4?­b¯$zsllŒ;wÒÑÑFš72õ°¡ñXG&&&Â+ù|ž={ö”½áÊ`‰†Ãη|¥cýúõÜpà ìܹ“;wå!m¨g;€Y⪫® Ó4K”æ¥[ÐÈ×_µ¶ ‘Û ,‡-¨w”æd¹úÕ®³Ü´RŸæ·ÍÐ¥5©eŸ¡®áZÛ–Fhs”ZÙ¢Fk·27µì34ʵ±œ¶ Ùî‰Zù*©ÍJuÔÒ§Øׇö jã«h´vׂVhs£ŸÛf÷{Ê\«Qz{{éííelllAultßmµu¬fëÈîݻٱc7ÝtSÙ\Í’+·tbα±1:;;ç]¾Ò pã7²k×®ð?ÀŽ;ÂÏÕÔ±žíضm[Ù}GÞÞ¥ù™Ë4Ãõ7Ÿ-h†6,‡-¨w”æf©}‚j×Y)Z¡OóÛ‚fhƒÒÚÔ¢ÏÐH×p­lK#µjg‹­ÝJuÔ¢ÏÐhׯrØ‚f»'jå«h¤6+ £>ÅFº>´O°²¾ŠFkw-h…67˹mv¿ç¾}û¸öÚkç\§ÑmK=|6*<Ö‰±±1&''Ce<ú?ª 022Âôô4{÷£ƒ;vTµ|%‘›&ú(šXµÚ:Ö«ôöö244î{llŒ}ûö¥0jä6(ÍM5¶ Ñ¯¿jlA£·a¹lÚe1,WŸ ÚuV‚Vè@u¶ ÑÛ ´.µì34Ê5\KÛÒ(m†ÚÚ¢Fj·2?µì34Òµ±\¶ ™î‰Zú*¥ÍJõÔÒ§Ø(ׇö VÞWÑHí®­ÐæF?·­à÷¼êª«˜žžfïÞ½Eí[ö~ÈJQŸÍ 3333+Þ2eCCCEk”ÞÞÞ0_ðôô4×^{-ÓÓÓttt099Éž={Âûù–ך­[·róÍ7]°ÕÔ±ží˜œœd÷îÝLLLÐÝÝÍÄÄ»víbÏž=MÓ¥y©Æ4ãõWj š¡ Ëa êÝ¥9Y®>AµëÔŠfìÀü¶ Ú ´&µì34ò5¼R¶¥ÑÚ\+[ÔhíV榖}†F¿6c šíž¨•¯¢‘Ú¬TG-}Š|}hŸ`y}ÖîZÐlmnÆwìVñ{ŽŒŒpà 7ÐÑÑÁúõ뙜œlzŸáJ_O*<6 ’/xÛ¶mes¶Ï·¼¨¦Žõl‡ì»³³³bˆs£·AimZáúk†6,‡-¨w”Ö¦î£VhÃ|¶ Ú ´/Ëu}6Û5¼mj´6×Ê5Z»•å¡ï‰åhw³ÝµòU4R›•å¥Õî‰åhór—z´i¥}ÖîZÐ mn…sÛèm˜œœ Ó·ºÏp9Î… Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢,ãQQEQEQEQEQEQEQ”%£Â£¢(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(KF…GEQEQEQEQEQEQEQ–Œ Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢,•¶fllŒééézWCQ”:¢v@i5ôšV¥ÝP»§(ŠÚ¥]Ñk_Qeq¨ý\YTxT–‰‰ vîÜÉÖ­[Ùºu+;wîlø›wçÎÜsÏ=õ®†¢4-CCC¼þõ¯ïûn¸¡áïûRÔ(­F=¯é¡¡!¶nÝZïC (J“°\ýµ{ŠÒÜ,‡/Aí€Ò®´Êûl3ú¡5|"ŠÒ®´ŠýlTTxT–…ÉÉI®½öZ:::¸ù曹馛¸çž{ؽ{w½«¦(Ê 144ÄÞ½{àæ›oæÆoä¶ÛnÓû^QÚ”±±1öîÝ[ïj(ŠÒ$´B?B힢,f÷%¨P”¥Ó¬v ú2Š¢(+ÅKê]¥5Ø»w/ëׯçcûáï»wïfbb‚îîîzWQQ”efdd„öìÙþ6==ÍÐÐÓÓÓE¶@Q”ÖfzzšÝ»wÓÙÙÉääd½«£(JÐìýµ{в<4³/A퀢,Íjš½/£(в’hÄc‹044ÄÈÈHQˆÿîݻÞü¶R© FFF¸êª«ŠªW]u÷ßQAR'ŒŒŒÌÛ–½{÷bÛ6[·nåšk®abbbÅc5õS”F¥Ö÷N¹Ž´|?rä°°{¾^ö«µJ«Q‹kúúë¯gÛ¶m\uÕU‹®C½mA=ûв–r¯Ìw/Öò>¨¦±XÁî)ÊJSÍýZí=_Ï~xµ¾„…¢v@iWJ¯ýfè‡/§h•¾Œ¢Ô‹zÛÕZ[„‰‰ †††˜œœä¦›nbÏž=ìÛ··½ímE¿144´ìûèííerr’½{÷²wïÞ²#þŽ9ÂØØØœ£'&&allŒo¼‘›nº €k¯½vÅáµ×^Kgg'+º/EY j}ïìÚµ+ÜøéQFFFèî³¨þž¯—ý*WµJ+Q‹kzïÞ½Œ…6§Í` êÕÿP”…²”{e¾{±–÷A5ýˆÅŸF°{вÒTs¿VsÏ×ûÙ ÕùZ®Ú¥)wí7z?|¹í@+ôe¥ž4Bß@uÖ@S­¶áÍØÛÛËm·ÝÆôôtÑoóu6ƒŒâÙ·o###tvvräȆ††¸ñÆ‹nÖÞÞ^î¿ÿþyËœžžæÓŸþô¬ cccôöö.û±ã²cÇn¼ñÆe/_QjE-ï={ö„£„ÎÎNn½õÖð{µ÷|½ìWµJ«Q‹kzrr’L&3+-R)Íb jÝÿP”ŲØ{¥š{±V÷A5ýˆ…ÒHvOQjÁ|÷k5÷|=Ÿ½ ñ%T‹Ú¥]©tí7z?|%ì@3÷e¥h·÷rõ® *<¶¥7ÞúõëY¿~}ÕÛ=,Ë1Wgå¶ÛnãÖ[o Ó Üpà Üpà ôöö.x¤Oooo‘q™«3¿ÔzOLLÉd˜žž.ÊË®(ÍH-ï¡¡!ÆÆÆØµk½½½á½$/ ­w”ZÛ/µJ«±kz)÷ÏîݻٱcDz¥«·-Xˆ U”z²Ô{e¾²kÑ—XÎ~4¯ÝS”¥°Ï­å°'âKP; ´+Ëñ>[ï~x3ú—»/£(B½íê­ JȶmÛ¸ù曽}</ʽ¾gÏFFFY𻦥Ö{hhˆ]»v±wï^2™Œ¥©©Õ½311ÁÞ½{Ù³g»víüŽAww7;w»»¦© Ô(J1 ¹¦{ÿH ¤x<¦’9ÆÆÆX¿~ý’æfZ Kµ*4*Jmú+ÑhW»§´7òÜj_‚Ú¥]i„÷ÙF±м}Eijù^®þÀÆE…G%¤££cQáÊ2â¡´s]«— ÅÖ[ˆvöîݦ¤Q”Vg)÷ޤC)½ï¥¼•L‰ºÜmµJë±kz±÷Ï‘#G˜žžf÷îݳ–íܹ“ÞÞÞ%½,†¥ÚEQÆRì,o?¢]힢4âKP; ´+ð>Û(v Võn4Ÿˆ¢4µ|/W`ã¢Â£²ØÐäîîn:::fåY–‡ìr¥}ZîzGëþèª}ûö144¤ùØ•¶`©÷F÷VúÞ,mQ; ´ ¹¦{ÿìÙ³gÖhÀ¡¡!öîÝ[Õ<2+ÁrØ5EQªg©÷Ürö#ÚÕî)J#Ð(¾µJ»Òï³bjUo¡Q|"ŠÒHÔò½\ý‹ JÈRB“ GÈÀŽŽŽ¢Ô qÕUW-[Ê¥†T Üxãìܹ“¡¡! ­VZž¥Ü;2ÏB&“¡»»›ÎÎN¦§§¹þúë‹îû•¸ç—»-QÔ(­F5×ôrÝ?sÑl¶@QZ•å¾{ÏUÛaß¾}ìÙ³§ªô…b÷¥h†çoµ¾„…صJ»RîÚoW;°Òõ^H_FQÚZ>cÕظ¨ð¨„,%4yÏž=LNN0èèèàÓŸþtQz„#GŽ066¶¬s,gøvoo/W]u### ,xkEi&–zïÜtÓMìÞ½Û¶‹ÊüØÇ>Þ;+qϯD[¢¨PZù®éZ¤AiF[ (­Èrß‹K¹çªéG€ñ066¦4«†F°{ŠÒ4Ãó·Z_ÂBmÚ¥])½öÛÙ¬t½«íË(J»ÑL©V£¨?py9afff¦Þ•PZ‡‰‰‰°C³mÛ¶²9ÙÇÆÆÓ‘ŠÒ"Œ111Qñ¾×{^QP[ (B£Ý‹óõ#ÀOc¨ó­(Êâh´{¾ÕøÔ(ÊâP;°²TÓ—QEi74âQYVº»»çE5==ÍØØ˜ŽP”b®N¿ÞóŠ¢€ÚEiñ^œÏy899ÉÄÄDÃ;K¥iÄ{¾óùÔ(ÊâP;°ò4šª(ŠÒœXï (íÅ‘#GèììÔ\çŠÒ&è=¯( ¨-P”F¡ïÅÉÉIn¼ñÆzWCQš’f¼ç+¡¶@Q‡ÚEQ¥hªUEQEQEQEQEQEQEQ–ŒF<*Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(вdTxTEQEQEQEQEQEQeɨð¨(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(Ê’QáQQEQEQEQEQEQEQ”%£Â£¢(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(KF…GEQEQEQEQEQEQEQ–Œ Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢,EQEQEQEQEQEQEY2ÿ?áˆÇÖj.•%tEXtdate:create2020-10-09T19:33:36+00:001W/%tEXtdate:modify2020-10-09T19:33:36+00:00@Íï“!tEXtpdf:HiResBoundingBox1728x900+0+0×ì&ŒtEXtpdf:VersionPDF-1.7½8;í(tEXtxmp:CreateDate2020-10-09T14:31:29-05:00`Na6tEXtxmp:CreatorToolGL2PS 1.3.9, (C) 1999-2015 C. GeuzaineÛ©AJ(tEXtxmp:ModifyDate2020-10-09T14:31:29-05:00ÔërXIEND®B`‚blis-0.9.0/docs/graphs/sup/dgemm_ccc_zen2_nt32.pdf000066400000000000000000005057241422157504600217170ustar00rootroot00000000000000%PDF-1.7 %Çì¢ %%Invocation: path/gs -dQUIET -dNOPAUSE -dBATCH -dSAFER -dAutoRotatePages=/None -sDEVICE=pdfwrite -dLanguageLevel=2 -dEmbedAllFonts=true -dOptimize=true -dDEVICEWIDTHPOINTS=1728 -dDEVICEHEIGHTPOINTS=900 -dNORANGEPAGESIZE -dFIXEDMEDIA -sOutputFile=? ? 5 0 obj <> stream xœÜ½M7»‘å·×§¨åÕB5|K&skÀÀ0`{®vƒA£Ýo ·Æš6þúfÄ9'‚YõèêJ–acÐ=ÓOÅe2“ùÏdò'"ø_>Êgý(ö?ü¿ÿð‡ßÔûŸû—ߨßõn«|<¥”û§ßüóm×]>[_s=õó¾>þð›ý×ýYkXþ5Ú¬ÑûþóŸ¿5ɃØäÛ×Çÿõ›}™ãyJûøþÿðïp!ayÊóùX??¿;þÃñgŸ«y“Zûú,çÅ…åèH6v”Ýåú¼Ï+ ËÙmê(þÌŽZ»ûçu·K–£#ÙØQþ™ÙýZO›ßÿ±òÿò›êOÃÿÏ?üáã¿ûýoþݸ?êøøý?ÿIý¸úgñû:ïÏ9çÇïÿð›ÿøSùíïÚÓÖgýéúíïêõ9ÚZf<þÙʾÛOÿ©þ©ç?ïu}¶mï'úÝÿ,_þ¹>ÛºþÓïÿÇßü÷¿ÿÍÿú£'a­Ï~?Ç#ùóŸÁ¹>ŸûÕJ}Ým¶Ï6޾d9ûÊVêël}ÍÞ>ïW_´¼úŠVÑ×Ñ*ÜRúþÇÑ—,g_ÙJ}­¢¯¾Ÿ˜»}Ñòê+ZE_G«_û öYúe¿Hÿœû^ëÂo9í·üÝúè÷gOûøý?îÿÍüÒ°°ÝD»öçÚ±¿þgÚ­…vãOµó‡í?~ÔiCúOûÿý㯚 ¿MB_澟a*‹&výÅŸbÇ~ û!~g¿È~oý׸ëú¼û_ãßïÁ~¶ýÒþô?ü¶ÍÏkµõÓÿ´ßâõ9ê5~úŸã?ÿ/¿­{"ûeü9þõï~»»j׳~ú‡Ýîù«\?ý¿í»ŸúÌŸþí·ûk³^?ýÓo÷ôÏ~•|q¹¿°~?ý[úìŸgðéZœF™°¬Ç>ÑÏýiïÒ¶Ø«?Ëþiñ±ã„·/l`·ÚØÓ-Óê}šxÐSÍ2ì~æýT,³\ ù 3gý,Ë-㳺e¿u.Xü4ûâÛ5`ذ-6u?ñþ¨ØÅO»øÖ`Yvµ·]ñ£æ§õ{ïË÷ jÿí_Ø{_¾=eÛ²r;Ó½/ÿ¾üÔ Çì«_Ã;y>m8÷U?íëêûoÀ¾ðýåÞÿð^öÊ3`i°ì£}•°ï“]î~¨?›ÝËgÏÚ~»ï} }x›ñÙíTk`tïæÚ³—YlÕšŸ··±!?ù~"ܲ‡°oYö=²s­=†ûÆÊ¢x“=†åkº¯ØN¾¦}Çí Úp?—aN¶eÿ¢~”¡šebMïgßJo3÷ZjøQü±ž=ˆ=1nKßýì6ˆVayìù|lÅÎîón-{ íñ?q'jÙcèv"›ýn·ì˲aßDü µìÖöÌšåyÜbc°nGÙ®[l vê=ßµå–=[Ö˜e ç=ÿ9·eâzîÝ£ë*f-{ 傆=¿{þ¼ì…©ÕÑ`ñ‡ V„öÏê×W÷ü¸lrËøÑf¢Íƒ?9{¡ÐÑfaÚ8÷k0a±1Ø©öj²Ñò|úOuWüœu¯mÒÙ£ºí4ËþØ=vö{Øè̲a”ýf—ß¶aSɳ ¦ýÃ]Ÿþ”^·,Í_ïgy?ÍFa±É„¿i{XMö .¨-^ÐfbÚ@5;nË~†ìT{‚ÁÚl6Ð=×ñmfxk³¹Æ,{ñëKöÚ÷ö,qÛrÍç©Ú÷ü¥žÓ~{³ì1ìw·¹ùÛô=†ý[ßö,úÜU» ÂÆ¹Ï°üIé{ƒgÇï×÷ l6{Ö°3¸åñ)Üžqµ±_»ì×h²±_mÙÏ«?*ÝFágì!Úûrì oUÝë‡=‰ãÞà±{Õ†¹ßEöš§s2«cÀ§·=“Â`°ÓŒý¢_@5Ëm/[{`ö¥ØgÃ-{ÓÎT9“nþÙçô뫺>»I·Oÿ^žØÜlvóg¸l v.§!·Ø¬›n÷Õ { {ß§ª:h¡MžÜÇyíAtgás|íA ;Õ½Ç ÃƒÓVÛ°ØìÔöYsôa^“Ï͵‡pßø|ºÛ¯ÙeOø>ÓͧmVîî²{'Ͳ‡PìTöµ÷~ì m0Rö‰YȾÐÕÎõpö˜{͆i¯6,{ÝNõ4jaÏâ÷žçÔÍÃeÃÜ?gñÛ5mÕÚܼÓaMŸ#²±Ÿ»úÏyÜÞè3ýïÿsáþáųÏt±qÚzÀï…}§«ßÒÎÇÂ>Ô MðkÞ{ ÍVÄûÉéh²ÇÐýTO×}ûÔwïÉ‘oô½Ç°§ñÝf韈ý§Á³¾l>Îbý™eÂ(°ì£qöµ±Ïqï÷–ÓÒÚì÷عö· ×cêb÷t=ü.Û—zÏãû¨›¿„}©÷­ó{Š&6\&äuûwßÇ눺öUŒ›m`Ùc¸ìL{ÊÁÄ`kŒiãœ\TûÌßv¦9°ˆ©Oóà¶4N0ÏÃòq~öžQmÇoŽ£öl¶ØÕæ·LsRØr…RíCÝlûïÕsûµî5[ùÄA6Þc¸M|ÃÎt_¸ë­ì1\6Î=‹/Xª? Û2üÕkö.ßMüçÜúfoؾé¼àVlèw¡É¾†Ç,ûez.·ìØ$nŸ1ÿ‚4ûLï;yï3`LÍ>Ó6‰ï[¢ëÛCèþk{wÌbc°Qjo{M`“Í>Wõ—±ÙÃp™»Âfc7ì!L;Sã2l@ó)Üþ‹ÏnmOÈ>…Û7Þ'Ûf÷Ѧðý}䨌rýqÄiöõ»›{¾øïûúmßÓ O¼/ßfp»6Ù—½Œ»Žø€š]~óÖÿ¬þ\ܶlÀ•µæ¯õ¶LÌÛÐ|þ6[C'ûêmþÞßL³­í«_¼—ø‘6‰úüm=ûª­Ù÷Ùæï†ÉÁ,6»Þy³Ï³ÍßûùÇ+×ìûÜ&rÔ÷lþÞÏÅÍVÃço»EþÂï+î>Û‹pùOÐmv¿9iµ¾Ç0ýËú³y,Ê/ý¯<'ÞßÐ.à@ÀJ|K ¬˜ÄO ,v/ ôåÊ‹}î8(°až"6Œê ÀF.L lx  ìXÉØmž|a ïûüŒ'v¬XäÄqpà Ó% ò A[ Yü}Ê íï:È~è{FÍâ«ðÀ@³øç80Ð&öòÂ@§_ï‡ès¿ ;0Ðøã @ã8¿ÁA‡…è¬çÐ' tŠ~a ýÉ)0Ð,þ  4ÒöË 4 Žkè„fñQšåza ºŸ+0°”“õ-I´U¥w X|.:1°p¸›`¸›TЛ(ЖI@3Qà¶°cQàÿú¦ÀBGR`ÑÒ8(°hµXDP{Nóß*1ÐÖŽ/ Ü—Œïu``á÷/1Ð~EX„åÃ'–›LX..Éc`¸-ýÛ‚Å^``-\ñ–)6î•Ü6ÄÀmÀ"-0pOÚø& ¬Mì( ¬t®'ÚŠßhß \ 1Оq$ 4Ô¾Ýr¿1°bªzÜRà¶ø'à¤ÀmÁ2<(p[nUP yr®“k#Ü’½ èŒènÜ/R _@Ú?Ù (Ð<; :Pà¶L"(®?sPànBXz7€èÎ ô£à™ º…— twÞFb [€ùÄÀéB׉nýáCB` {Œ*à è–ëÄ@´ña½ãÓE 4§°ŽnË%àz¼¯Ä@wF€!0Ð-X_½ ô6÷‰Û¢7è+¼Áä@´A?à@oƒI8ðÊ·¥óǺáÄ@ïNbà¶ Y€Ûrñ­'z¼ÀÄÀi߉½ÉRú¹-æñÝq?1~9¿íÄ@·`Ö&n‹À¸-Àˆ£Ð8ŠÀoÀ@÷Ýá)%z?:1p·Ñ$M <|à@7à•&nË Ž¸-½ äÀm9!Ð Ö€£$ºåè¼ „@¿7'žÝ€Ý‚Ÿ ˆŽA…`@wîቺ¯‘p t à¸-H*t ± ¸-ãz?¾6«éKsBà¶pI+tË]½ßsÑï Þ¦£ Ї N¿I¤@· ´ºÓçMa [€MÄ@w}. t_ãàÜèîÜ…Ýy‹A‘çƒÿ’ èC¸†A¿8AÐ-ÏÉ‚n·’ý±^4° ¿¸<² ·G‘1ãœ,è3{ ºGA?w?QÐõM€‚»Íe¯z¢àfŠF¼% ÷‹(¸ÛLŽ(¸ 7;& zà#HÐ 7IÐÛxŒI‚8G݉N ãç¾°æ2Ž|Íÿÿó߀Àêòê[ô/èAƒ¾zµ:hð‘Û4hЖy¾8 úšÎ¹M4è+8?H4hFÁ Çº¸Åo¡-ð¼OÁ Y|0hK>ç<± wá„)´&ã% šÅáK(è Ç$AûÛ'¡ A•üã$è2“SžHÐV#>« ÚLèsbj‚û3}¿HÐæO€©4Áýir¿Xj‚{Æv3$Áý­òkJ‚Z-¥$hŸx§¸Mr: I°s…’`¿ñOI°Ã¯˜Š`ø¦"Øñ3¦ ¸qK ‚­c“Šà¾}×[´%—C]*‚“j_(‚ì(‚¤øCl˜Ep`ÝŠ`ç´™(h+*ï'hp_¡ßÀ¤ÁFÙ$ipŸ«ìBŸ`­Ð®æ‚÷ŒµeÐàžº€© JkIM°QO Ü¿ç"J”?hpÜŸƒ¶æBÁ ù’Ác‚A“ÁZÒé×:4AqgÀà>ˆ:`°C3O y4X°Ëñ,صOI°ˆ)Å‚öLâäbÁ=pøÃƒ‡¸3XÐÐèãDÁ±¸š ]M à^raY(x Bmàh#Ä|~¢à`@A ` B  ­#NEFðY(‚ƒKú`Á)õ'Xp·Á:,XðZŸoÜßrp@ àÔÃ(¸¿qå‚¶D@ÇBÁÙE¯BÁyqa‹/‡}ß‚à%༒,¸†ùfÁ›"²àþ ÎSܟʪ£Ä‚“J²àþœ‚“ƒ÷QdW±à¶€Ø„‚«‹á„‚·âBÁ}54¡ànBµO(g ¼õ Þâø`Á»ã‹,8µ4G×›—|T! u,¸oNŠ }å~BÁgñ­E°Ti’ ãmŸBÿS  ¼É) šséã$Á%÷“Hð > Ú¤%´% Úµ†N\/} ›J$ø`Iz Íä'ºêŽßRr 5!õ‰åüN9°šo1´À²×CàêÐk( ‰²ÒKÁò&п`/œ_ðáÂ<ð–ÇMZ ©ð˜¤šÏ•´ÀÒÎtÒMÂFø´@Ã$Ì}¦ü¡´@sœ|$î/’­¤ÀbŸýT“bàš‚>J}À“C ´‡Z`àC5?1ðn\-Ú:ÿÄ@?yAŠv/b E-LtL1°(È(Ä@Ö <10niˆ¥Q)ÅÀbN´®*Æ£h‘ƒ׃ePÈ“¢Jß9Ð"(R,òtB,  =Ж#P«¤–Æ>ÁR…ÑM‡0&AÐÞ€´4ÁÒ+‚ÐË^vP7¤&h·–B5A‹ ¹^š Yp=Ò-‚J‚¥ þœ”‹ù#¡5R,•.šK%|$Ú«Ž’`¼! –A•[’ Ý "%A‹à *R´•â"B,X0’ =o~}R­c^A ˆÚvŒÿMöû j+ï·ø`9v°_õ›y _z$úu&úQÉ8ÐÈÁ~T)È~Œ˜:ØïÂâ;ÙÏ~Ê„¿‹‚cÀŸ}ŸþtTÒŸµqÝOøWAøg–“þÔoÒ_¡>—ôg¹†—¡õ2 TŃ^ø9âA9wñ ¤ûw<¨‹| t½%üµ§„?³x? xLøk”aúëx‘ú+Tùÿ”Ä¿€Múë|V“þlÚs úë <èoù—9áoЙžð×yÅ XðgŽ"×þÝT C ð7øÓ$ü ÊÎ £+SôgÓÓú»øéMúŠ ú[tÈ&ý…%"BµúIú»É3I‹¼¤¿K’¢èoÐxП¢ÐDãáš#é¯ð{¡…+¢ ¿±¸HüŽþÙ«‚hOáV²Á~WxŠý.éÁ~±÷f¿ë‘ðá WV“ŸÇ€¿ÉЃ„¿©_*àojð7åãøÛó3FÁŸ¿*üYØëþ¶^7Ý, †'ûíeÝõÖmUmNì7îðg_<@[Dƒ–ˆ%ü-ºEþV§¯!ào]Š!ü-ñ4à/‚3´+\Tð÷Ô¯ð·?8À× ½‰ºWÅQñ ¦Áã"Tm㉸jâ9®'âAoús"´Ü’ýj+€ãA÷"‰Ôñ oCƃ2Ð?ãA÷’¡¿ãAµäȀнäXýmÃÍ»¡«¦# ”+´¤¿mÁ" ÔVë@;á_“Ø¡!Àþ5y1ÿZ ¢"B›Ü]Š-ŠoJüëC4ʈP[N?ÿݶÌ.ED¨­YOþÛ–É+"B‡žíˆ½šäBE„ÚR=3"ÔrŠÐDx1ó$ð’ã%pÏ:xÍj–yJ{Ñèƒ œMJ›(p^ŠeD¨õõ2(pÊ˨ˆÐ"ù("B-ÐøÆ€Ð2‰,Š-Ô…€S¼@ÀyI*Úœ Ì%Ü »ÂAË-%50ÛˆoRw à>±€ëk4h¹CP>zï…€† ¸b…ƒzÑ"Ô¢¡+Ká Š¢I|.YZ$ñ(´2é ãAË£QŃ–%¼#š2Păš>ñq 5i§èa„ íT8h• ¦xÐý ¥~(´Ï÷&T@hÒý" ”®ñ ­”ZL~D„¼ º»})ˆ3ʼnH€vn_„„îY©BTThhNE…î6¸¼ˆ °Üˆ µ#ØMQ¡•qjgm÷‚‚M´&©hsSh>›SL;9ðð”’ÝBÒº‘9ÐF8Ø÷0gx@|9XNYdèˆÕòGB ¯NÙˆõê;-p! AxäWÝB}O¸tgˆ‡#\ø.<‰¾ÞÇê+0ðQ8TfNÉyÀÀ½-Šõº“0®Ô±~¿)+°3Ì%1p#Ó<ãA}ñ ÿAp ]ÎGb Ö”€>`à¶\t°ª2 ô,;ˆ0‘8«ÈH \’•xIOFR॔'bà¶<ïpP_àBXˆ¬Àù%+Ðô>²¡>R„• h3Ìê`8ßh7Î% Üs`Mxs™”¸ÚwVàœx Ϥ@¼˜Vãm3bHûùÃo»'.^o@ઊVN‰æ÷d˜d@ dŽ„Àª˜Ã€ÀªÈõ€À» Õæ¼ âGÌìBA`eXUBàžY¿@àRh!Жå¸;+8,Ò9yšj ‹° %ï‰÷äÑ𶉲žá ~×1Ì`ÀHò \MÂ`d*¡9Ц§3\‹°U¾CÁ€Ñc™(÷r2àž…0çÖ‹ž»€@_(|Ø‚ •hÐòqb`„Y®KºŸ0p)ð40pOKשz¦åýVmêFVàÃûh@'Ú> tdù8 Ð2Cë žÓÜ6ª’™غ/ ð¦¶I¶Œ«I\Ez"uÀJí u@“‰ˆ|Ôí;G,¤8µ˜ðž:J: ……¿’­ÍzQ`‘Ç7)°tÊa¡v†PXgÒ»nOè€ûÝy2-Ðó|Á|Ò÷WC°¤J|nÁ¥(0è÷¤@æô"\%!°I…‚ÀB_mÊ€hÿ†ÀB?lÊ€½b.K4 m5ºŒ'Nþä‚@û˜Á'Ж`§ ØD,LŸK°‹QC|ôp.,SœÊm l… dÀ,ùsÖ~kB}Ö÷íI‡YÅHm¢BÛ×&y›|;B¥gþ|m·ï–³Úy‚?f´~5Ÿ³£°ÉÆŽòÏìhØm[Ï9ZYŽŽdcGùçÑ‘}ç<;’åìˆ6uþ­k»5» »¯?ªíVî?]„ ÅÝÚY°ík•¶ýÏçþQq·'ûeƒóŸüqG½¢= 7âß [?z/wC½JÀ±¯£lû:˶©¯l¥¾^%àÔW–mS_GÙ¶è+ZE_g 8=¹Y¶}eÛâõŠVêëUN}eÙ6õu”m‹¾¢UôõWwkû;xðý°¸ÛõKÅݾUôûÅÝþd»/ÅÝþT»¯ÅÝ~\Ið]Üí×L‹ßf¡/“àÏ¿0—E“?;•þü—×HÛÃÚïïúq´;j¤ÝQ#íU¼ìøçßý ŽÙß®JÚÐç¿æúA•´mü»øª¤ÙÚH#ÛÆoUÒ¶í¿Æ¿þþ¶¨’Ö~¹JZ3ywt&Äëͺø»ÁÕoogö{ó0«‡¹îÖ¤›ûéÏ hÒ%.VEƒeµe¥7·t_¦! ý‚åaE@†íwwµÆ‡Þ¬$ šùº¿·‡N5ËWõÛÙ c+aúþY_øû÷¦Èú XØEÖë7èÑQïC‘õÎíÞ/FWtýÞ}*²ž±Ä½ßЬï¼9})´þÒ%? ­g~PEŶu°×¿ZïpÐG£[ÍJê4XZO¼Î芋tãVŠž¾q)´žI}/«Z¯·c£Ø–+ª},…ÖSÉîÃŒN‡±®Â芻À—Ô¯ªèŠÁ&MÁt lKWà™Ýsƒ+£_ƒÁ¶d÷1\WWàq»P¯«!úbÿN ®@µ¦~-ÆV,VÙð Ø F7ôY[Á¤æ>«b+.¼—³É§Æh¾mQheØ>»|jL,îs(´âQÇ}j†V~9sÒ©ïÔ¼åTcŠÁž¤Yj«ÁÇÑç#¯s?ûþ6? rÙ/ç®YjË«ýn%â2ñøÝ^µF'ä^ýÀ«¦<~zÕ:—»-”œÇÒÔïI§Ú˜ð¯tû|;Y¡>Xjû]ðŸû~èS»XBŸÚ…ª;}UUÚºy#V£KÍ"˜&,t©™Ž6.µÉjkû5¤Km2v¦¯ q“9u}MºÔ,™Ñ/xÝŒ«˜Ìlëkѧ6/ê¡Oífy©îy£kÎOeêW£?Ïaº{€‡n£ j7£:úÓåTcòQ÷Z€ýà¶·N5}Hù"Ãýä¿Þ@çk€:C—œÒ1ëÛË#Ÿš 7þЅ¾ÊOoSƒ¥±Ò–‚{†=Cï&=}j–ÚêœÛ†ÇŸ°8“Þ†ÝÝ)·ÕpËÍR[‰ÿÃî—Új¨'мݩã§rÂB•$÷ ûB{¥­Êd”a_h¯´¥¥Q½j îëae—ܫ֩Œl…WMaŠ£^ ­àƒ<¬–—{Õ:#F½éUüÆ «|t{?üVú0´Âܲ~s¬ÈÒƒSù µ¦ò8ÛÂj[…åÆÕYñ<ðûB{µ­ªßÛ¾Ð^mËf ´±¬‡Wüšî«ßGià×íÁ~·=¼>ýŽkùó²-žþq=ždy›Û?Õ,·çGaVšž¹ì×0¿ÌêZÛÍ~Ì=†uÓࣚ݅–ma<õ°´Mâ­38yØGÚ&q;·Ç‰ê|~*žÛ!猞÷¼^¢2äÇ|ê%Z–šu_Ý&ÊâýدœOâ­±¬Ó¶¸Ë|_XcÜöŸìïŠÕ踻/½2ZG¤›Þm0»î §µ‡}¥moŒMH?Ï~Å<1¿®VÚ ïo$è®óÝE{‚ Ö9'v@Þ‚ã 2bôA:áì\&v.H™ }€`çú-Apày:@!.%‚™ºtà =ŠB1t‘ -óK Fî@A#U¬uˆ‚f¸yDÁ¨6(h`Zq}DA¯6è$ ZQÐáõ…‚KÈIƒ%' ‹µ$ 2)&Y°Ð0X¨ä' Îöƒ¥ëòƒ6[á Á`¡’0XX¨7i°h4¸ß>×’¥Ä$ Ï& Ýœ Á†¤Aóë h°jq4X·4XYE/i°²²qÒ`EjLÂàn 4 R0X©8 ZÁp?uÀ`cDpÂ`+=Áàn´µÙÇÉ‚MÁÆÊD ƒM¯UÐ`cÝÖ¤ÁFå9i°±ªZÒ`g.vÒ Ò#Iƒ»ˆ"h°3~5q° þ;C@ë…ƒú…žÉƒQíA8ˆ*+8¨3Íz â`šõ`ЊpÉ »É<ëÁ€á ZÐóBžõŨpá ê&Ú€ƒ™S"ô¸3¼DÄA‹;ûHDÐ,IÖª¢$ô ã„Á¨ $DõpœæfŽõäw[,ˆÐ5õ0Ézrý)tO™­²ÞÖ͘$Ñ g±²Mc’õÍÈÑ '¥·“‘0ò0ˆ¼`¦’¬ƒ ï/IÖ‚A„}$ ºû‚äW”dÝxÇÉ‚HI‡¥±ÞÖÒ­ zL@dA÷iô“‘ur² {BÖÉ‚ž‚L¦tôÔáy² ûFn4yXnË>sÀ±ÂTkûR}$ z“Š&M™ÖŒM$ âb>’Ýå‚e,Iñz8†$hWPG´ÄrIÐ. G‘ û\J„‚&Ƀ „‚–¼b# FîJ`)Œ ´áE,±Ž% Z7ý…‚'„&DA«€Œ šËs¡ w €$ •p ÚÕÌ Z€Åx¡ '”¯Í” U>´6À/± üF² µy^,hy2lC´X¬RÅ‚Ö,4?®Y,y2`A‹À˜/ôh¸XÐ,”XÐ]_/4G\bA‹äðˆ-^ä,´`Eð¶X°Xn£ÿÂbAóZÄ‚· þªŠ°`eÊ`AKA®' ZvöBÇ„AOì…0hÁ@ô8ôK,*ï0hkâë¤Á¢O`Р犃µHƒ¶l¾É‡L´z$Eƒvså¢A÷~0hw ”.´&xïƒEõ{=¼àIô9ýí®¶ƒ¸‰G’0èYò`6 5Á³.t0’ÍåHf# Z¨$xL4h‚?ÈX4hQ@Œ¤ÁàIôÀRÿ­ƒ‘¾0èñO°=ªŒF´ü¤° Ú¹ñ;ˆÍ‚7X4hÓne’í§Ák$,}¶ƒæ³ý Ë¥@èÁ˜>…ii"B¯ë!D"ÂGÑA„¶p¥ðF"4ñˆ’‰ÐóІDh""€Ð?®ú‚"$yÐú¥,I´ƒ°8z ×z‘RœŠQa:HTØ‘¡%(„gš,ÂÜ)ƒ ý3ØNyßN@«bU[ Zaæ&q’Tèmž“ ݻթ²üV›'I…¨Îé++P¡@­¤Bw€aiO*D MXn–ßj¬ÿ'*DØÌI…¾ÁzTˆ8š“ a"×J¸õh`æÊ…… Ð-¸>B!Ú@мX}K«.A¡[0NB¡¯²(.Va®, (ôx!ð^aæÊŸ˜Ð—…ÐJ á=™0· úÚ¼L&t ~:2!ÚøOG&t ~L2¡[pûÈ„Xµ~$Âi{ʃØòŠ\e æÊZBBø‡!þ5Ö`®ÜOHˆ& ËÁ"ÌÙHèP™»4€oa6 N¾X„¹ÒK&Ä©a…E˜+KôŠ a9Bl‚é''º…ÜØY…¹J¼'º…Z 07ÓÂW"º…(ÄQ'ÂrB!<ìÐö ÝPH‰æñJEBPèYÊøù…nÁû@(Ävh(Ì 4…°|$"ý Ý2N…ð° ±ù詺÷‹Pˆ£À€…h‚ƒ…¹‡© 0«9 q…Øm™ë»£"à÷‹§$èñ•/äc$X¸#ÎA‚…k·$Azyl¢Å AEÖ$ hTA‚–4` ’™ó›(¨}Z«üÓ‚•;u% šø" šB PÐÒݡΠm>¤XH¬“÷"P°ÎÏ—2èç>•A?†Å ‚µH§ŒÑGq¤"ÁÊ|ö#F”oÝ#ÊŠW˜h“`e ã+Lt~ ½¿JƒU$(XYÔ3ãD A%ãDñy;ÂDY-ñí_I°)&9H°)´+P°é– ¶ =¡`cTp “]mºÿƒMcÀ Î#Ôc”$8ØG’à¥PÎ A†$Èdì$ÁA7@éYɃ>´äÀÁ¯@rà`õïäÀqI‘Ž*!Nh‹Ô7o€`(_‚VÜÍž Èoí[rÕ&Täæ© õÎ%*ÚøAF€ ¨˜P ë² ‹Å² Eòä@º¯RT aŠ‚M¢à¥~‰ƒ¹Ù‰ƒ%6ÃrSÔÍKM°…Rì‚>É‚ül²`aœfP`H”© *¾!(ÐJ^£(ðbrvR eˆ#,Sh–3J;S$Nf˜'^¡è‰/VçO ¼.…€’/…GN =(ðZø¸%^  ¼X+%)Ðæ ™(ðb¸bRà¥ð À9E“¢À[hxK ¼'Ÿ” Àû% Þ„¹DÀ›•¡o-eïKq›BÀɲv‰€·”!àM¬N\tX&®®KG‰×øÊ€‹¸É€ë¡ ˆ ¥“—Ô§`@N\Zï>ÌëH|´B> ´N|ŠÂFÅ€”Ë`À§‹øÄ€–ˆ‚6R •ß`ÀGÊe(ƒ*íšÊ ÕõAt§”ÁÑR-œý%Z´ƒÙ¡ VÆä¥2Èš8© n •¡ 7„2X¹l*ƒAL¡ LB< Ê ý@¯(Q_ž˜•SlAxR+Ý‚© 6N:© VÖâOe°1j$•ÁÆ:¨© 6¦þ§2ØP)…AÅñ‡0؃9¥ 6¦Œ¤.ØèèLaоx8‘„ÁÎzz‡08©†Il Ra°³îO ƒåôRì,òtè‚Sìº ƒÐaPïkƒöÍ;Я, “øai ƒÚî%9J,©wƒrV¥0X9¬åcapʵ -OxM•|…‰}öRšòB¼˜%r(ƒ“1 ¡ yŒRäÜÊ 2òST¥•TµU*ƒS© >oD6‡]Î_P?íBG¨W¬(=Gg°(*Ld°(ý%G°(kÁ¢tßÁ¢Ô’2V”eGŽXQæŒÚÞ Ń…ûe%Zá(´ºô’Ë-ùPEœ)Ôæ»ÂAÿ63NµvOôoásĉâ ’+,ÆUøH"ÄîT ㌠G"D¦ÚtãÒ–¤DBÐ9¥A”¶=‘ÐckØ/öÁ§Kµ¸$x ½Í+PÔçA 7‘У<Ö© "¾\ÖXŒëbé!¡ÇÁËB$Dhøîb1®Y$ýMV êgÚ O¸x5‰„ž†§‹Hèµð† =ýë”=k ¦´ÁõÈÀ¬Á[×YƒªÈ|¸a}f >ôòfÖ %$ƒO™5X¹a‹’ío4`Πe;‘Ò˜3èû²$¢Æ ä<¦ Z6–ña!Oå¡1eÐÒ³ð³)e°Z¡{¨yÌ4 Þå Úl1[9ƒ–q4Ï8Ñm‘¤«¤Áª ·"i0ò”"k°Æ­¬Áª$B¤ Z½ŸrÂ`ÖŠ”AÏ9é!e°öK!SkW ¦Rk“d¯”AË#02eÐkИ2XÖ)ƒ ˆdÁ==ʬ‘§©ŒÁªû‘1h·üªŒÁ ¤Jô„­và  ¿2-ƒ N­È¼¦rÿ”1x+¨12'ïEf ÞpIFÂàºDhJ¼u ƒ‹U¼3ap) 2—¢±"ap)4÷UÈŒÁ§q‘ƒ“‘™1¸Xs 3•у‹!û™2ø\ï”ÁV¸¦W˜h«¬wa¢–YuCa¢­±(S„‰ZÒõ µÌ/Ä‚1L´i[å€A«ç¸^0èA„Áf¾C $aÐÒ‰˜H4Ëõ µì!Ž-Ñ ?V¤ j¼Sm‡¥”Ág‰¶”2¨xçL´@å± gú1hTƒ7¸J(ØTy9PІ‚àmËšúBÁ¦9PÐnÖÝ‚kQÂ`åž°‚­Ü¡ÿ[»$ÓEÂà”ŽH´Ê_¤8°`k ÉŒÁÆM1[LD¥ Ú¤÷NlðHlÜGG0h?ÝzE‰Úó L0XCC ÚOGöSÎ`S,bä ZTCå VãËœÁ¹‡ÊÔAƒV8Œ‘3Y¬¢AKÖ]ïœÁÝFð‡œÁ±>_0Ø®.¬# Ú;‰3 -c± ‚ÁzE›*gЊ ôƒ5‚_ƒínŠH% 6Uil““…XЦrYÐ&#L‘2Xg"¬ÚÄ&sKÖ z78H9ƒS>‚ÈTô@ä îþYq)ʨ]}(ÕŒe|ös ÎzAjEѾ6ɃØäÛ¿¾ŒÚ÷ ËQkìu‚?f­±‹ú×Ñ‘,gG´©£ø3;šc•£üytáÏçÁ¾ ëVÉrt!{É?ÿÖ¥Ó.Û5ÖîåŸ)ö­ÄJ§õ³Ú×h“Òi?úùm[›wé´=€%ýn¥¾²(šú:‹¢©¯l¥¾ÎVÑWE‹¾Ž¢hÑW´Š¾ŽVñ´FQ4õuE‹W*Z©¯³UôEÑ¢¯£(Zô­¢¯¿¢tš}B†©~?,vÿRé´o?úŸ(ö'Û})ö§Ú}-öã‡í]:í×L…ßfž/ßÏ¿0E“?;}þ¥ÓŒº›•müAé´¹T:mÿëŸâ_¿X:mÿ÷ÿüƒåýµ¥ÓÞ'úãúüãJ§Õ0–ÿí+WöµïË—lò'ôõÕoe_7O`Ø‹(¸Õ|;‰ Üjî!Å—õ[Í,€×(p«yB»w<*Üjž‰Ž6ˆ[ÌM&®ÑÝ­¶´ãµ—¾Ï™yQº¹àV3/ª3Ä5&ÜjžAþ¸åVúuQÇKé×ëúmQú5!ìÒ¯¹Áu¥_c§†ëªÊ¾¦ôr]A…Á×ÕdQ¶]ƒA…[c\×ÅìkÄìU¨²¯«,·²¯™7}]Ké׋àmQúõà-½¥_ssâkZì+¿a¨Œ´HKc¤E¥¯ãšýŠ@M'–k¥_#Äl¯’•~ÍÂ5g¦_ãjæé×¾´¿æRúõ€³k[”~Jù×|”}MÕéº ã,v¿à»2Ì¢1oëº}onÄyÝQô9",ЏdQAÜ×=dàˆë¾cÁâ×½cÑÙd)Öžñ=×ý(Ö¾ó Uc j®UjÏEþµšBí-½ùB¡ötù\k0Ô~‚/.›"+“4°1èšÜàZËõkÝ µ_üe×R¨=ƒÀ·E¡öÌÔ¼ìÕb ;~Y­ã(syȬBíaijï rùî“Ìew—ÊåQ%D¿ðedÁˆ”뙌±Ø† Ë­H{¿W–­ì‚È@ÙÂË7ܽpă&¢ìYCerï84ÝReOÕmz:ézÔ_a˜[ã+JÝOËÔs=d0âkú íe¹±»57½ŸV¹¼q[–ŽkY ®t„M+-*YÛ`ZMô‹gò¥ô´êד£ôeÖÆàŠA™bšÏ’}FÓÖK‹Ãô1Y=§‡AU §š-¶¨lèøf|…­üÞÔÅøŠÁÂ]³.ÄW(âgÖ‡ñƒAÓ|®ˆl nq«Œ¯,[7ÍK-*'Geî…›§z`Œ¯,7ÛÅøŠ¡ ŠŒjFt9×Ïv3¾b0ÙgZíÜÊè1ö³_1Èõ³=Œ¯Ì¨š½ ¾b0÷böÊøŠÁŠþ{ÌøŠÁÄÙ;ã+w–™}tÌÝæ!E?cìc_fŸˆ¯¸(DÍ~3Æþª²,ÆØK¸˜öu®Œ‘Â}·¯³ÏÝK¼ÍQd1pŽÊ û‹Çs4Ù_Œ°ž£3ÈþÒ 1ƒì/ƬÌq1ÈþêÜxLFÙÛÎ}~Íãf”ýÅ8X²èÅ]z§}›}þ¾.uû0ÊþÒ£cßæÆÊ”xt®Ê(û‹:Ï´b⃕)=Xu´eoñPh3e±"ͼ°S¡ÇCá±ØßLLá“i;s“0‡O8'¦íÕåS¸íË‚ËYŒ²Ÿœçõ Ê~²Ç´o³OáX…ù¾ZŒ²ŸŒ¶ÛUFÙßôzÌÙeë隃Qö7·¶ŸóB”ý¢²Xûl(È0²µVJ¬ÂE¢à`®DA¹=GW7BÁÁBÙ‰‚öAk í"|à‚#€M(8oW à` ¤DÁ1ð‰KŒíHˆ•HK§rÔnjI‚†ßþ( f«$ Ž¥½Šƒ±ºK üN,…ä@î^zp`幃/VJTé§ÁK¿B€àÅ¥Á‹¡ ‚sE·e½AðB5¼äÀ9u8ÐÂ’^8ñJ ¼éO¼´à¼+QQxkâ ´ðŽ7ÎÉÛ¨BÕ‰7#«UJ;9ðf˜XràÍl×äÀ›õ`‚o31°à㕸Xb49piÆ\Ü69PÛz&Z| 38pq åäÀ%¿Rpàºu”8p¡þ0Л°aàzt9 ©Ö[†+~˜j­Ü#a §ÿàþw}ù" tº…£‰èé?˜±nó±ã.è‡NŽ­4<˜¿Í€^Á€H*ò_*°°²¦ ›'ƒç¥©M¼ù8!°p_ƒ„À‚"@m:XPï< ОdÀ§ÐwTÿ8 °\˜ð“ óD“ ª @+oþ&@…N$ªêb ‘/€O¨¤éD@ #ÿ ë¦èÕ¿ ôªÅPúî̸î/|ˆßÁ¶Îˆ]Nzq ª¤ºá…¶°Å‘èÙÕ/ t‹¯Å^r–©Ò[,$›Z`ç~ò©vA]hã¹J ¼Úç‹mj]o-­ zŠ8ÔAiua˜Z EsB¤+ú Á¦À¥ A-N´Û›m]†“‹Óê‚í —H°É…"A[ó‚ÅD‚­Â9‘$¨Šl‡8¾’ ‚µ1û½$ ª´V’`ÿF‚Þ§$A¦Žj`§ÚüÑ}H5P*dp`c’Er`{¾ÉÔÁS¤JsÈt§z ³ =Ù.‡ÈÝCäf‡ È䃗 Øß‚ £ÄAPœ‚`Ô… X¿¢`¯ô2¤ ¨·*AnÛz‚ÌÅ;P ‡ ÈìÕCäþ/Aðù&vXfÖÞb¡ =%èG(ØY`:Q°/Áa  +:$ §¼X°³FÆÁ‚øJ,ˆ¨d ŠéãJl¬o–¢àü* jå–¢ ½/Q,vˆ‚ÏQûR¢ UìC,Sj‚…RJ‚ ôƒù™;8p…˜x¡›ä@âdpàÄ“tp Ö© 2Ö÷Ð/‘Ø¡ ’èBDù®Cl:UH‚US,Bũ֞ˆeY*‚ÌM ìL M ÄÝ ÌbÀ.a*ÐrR>NìB£@À‡*^" ëñx‹P™Qy à¢ð˜Èåsà%Þ„Ö$@Q9½þ]‚¹À¿!Y/øYâ¿hüÇ%ÉÁŒ•8”@NŸÿñ%M!P×’ü‚b ž²@ú@˃ÿ*‰PüׄšÿÓ‚ÿX(áà¿JbHþ«‚»à?ZJTBZà%¡Rx3ü @ú¿o=€“Žüƒ/:Nü"Þ¯`ûF€ÊÌA€Uº_ –^ò“p`$,t5ÞUd)´Ýëqî @îùRŸ·h96°.ÑÐr‡Ð&äpàT› @9Û/RX" ÝÓ‰€o`"àà{¸¸SB"àbÝüDÀûš m›DV(\>J ¼¡Ö°N%°(*%”À®ƒú6Hn¡ÖvP - @×Riâhð0èzÀ@çáÄô~€c AGÛF鯰bƒŠ…‚Ø|bà—ö+>£‰‚•5y+‘>Q°2Zð@AúA¤"–(Xù£(ÈÔþ?S,íÀ?({ោ¢Ä?Å)&þIAIþcàÏ‹ÿ  ÿô€Ó€Î—Yª-°+d3pHà ”nØ"ÊTØ8¯'*ä0ø¯]êFügiF'ÿµ"ÝOü׊‚/þCà\Æ‚ò›üWéïÈXPƱ RU24ÂNWnŃ~#ôf@^†‚.Bm„‚2 ë ‘/BAé~;BAxøW‹D¾É÷©>dã ?¹*’þ*#å’þTJðÐ…ó©ê§J{ HD Ë!NÉw!bõ}¨€)S|ø4¦ ÈwùPùAIü ŸÅ©öw8hå&p‡ (A4ð¯QÚ¡>èGB`á¨ÿ*B_’þ øÓCìW§zûÉS#ôãÜWéyMî³¢¸ÏPäÍ}v^Hwâ>‰£}•!¼A}uˆèD}!ÃõUîP˜ÔWå êk¡Ô…ÈŠI©VE~Šúë $öÙA'ö5>ω} ÛÐÔW…—¤>ý¬‰}­ 8…}iö5Ö¢IìÓƒ—اxíľ*_q`Ÿõ[ù ·&¸a߉}%Kûš–À¾6¾b_Ã. I} Õàúšbãú“7úäíKè“§,©¯)è.¨¯ nƒú÷ZI곉×#ì³ÍÅ>Nêk,ƒÔ×èKêkCj›À¯)˜5À¯±œM‚_㾪I~Vèù%þÅ ‚ü‹Â&ù5-ñ‚üš$à ¿Öã)òkt2'ú5¦h'úµ…~¶vù8ÉOÝ„¿¦¥lÀ_ üÙglçð§ý2þÚ”¤(ø“Ÿ1áoß 0PÀ_ ý5I“AÅc’þâ½ ú‹ûô×´¶ ük¬6šø×ñø×¸kJàŸbÿÚ¶ ÿš„À¿öö„5¾ÿ´‡Qà_ÈÆAÜÁò¦%ÿŃNÂä¿°ÿÙÃðz‚ÿ5£À¿Pÿfù*΢Nñß,_A•é˜ü7¹àÁ7]XÁfü7›"8Å*½•ü7›d9ñßd†Tòß”Òü7Yó1ùoríšü7¹bKþ›M±¡ä¿k PÅ—ÄÐà¿mo ÿ.oOü»4”ôg߬—x±èz*€3GR¼E)Z9ÐSà¤ß:éo*f<èov)~¢¿IM5éïbÅ„¤¿‹µ7’þ® ÓxÒß`ɇ¤?EVý âiÒßè (ý]\\‹þ¼ã èÏJ$ýá>BAÝq1#á™ÄA ?×Ñ, ?o3Oú³»ü‘èççéa‰´¯#x2z«ª3%ë· íd‹ _0Ðzf‚]„ƒ @2ô†;ãeŒÀÀBá>1°4e Ë+!Ðâ‘d– R£2!{|$VzÓ¤3=)0X#(°rݤ@Õë~©€d³ À‡«æCü.Â" ߉CdÕ¢¤À¿Kð–z'ûH%jÛ¨C,ŸïhÐNoä¡6Y¡væ,%ö/ @S䆇(þLå±µ­°?”î„€ÕˆY:p%û Gð…ø…€ƒ54µk" Å{½#AG ‡œ€ª@™È=´ƒ¦•8XO1p°g2àæ88X>(pHüÜ?.Ap\JÜ  ºC”w!À_òC¼S)7½L 䮋GV wš>Òt¤Þ_QÐtpžÒå¾È ä~GV Ãx¬ÀÅA¦r'ì#-pq­ `œ:$À[¸ T¢”u9)ÊÁŸàbHZJ€‹œ  V])j ™Ⱥ.É‚«ÅyÔÆÈ ä›0xÑkär†?òeï…(¹1pðR†IààUˆh¢ÁK±mAƒ—Ò ‚í žhð*_ӯ…YÐàUeZºŒ8˜YwÂAËÕû8iðb Å++²EÐà%6ÍPЋŒ: ƒPkËS¤â: à0D@¾/‡ø|EÁÁRf‡ ¨§$UÀ%/T@Ég(¸.t@=שrƒJ¢ …Þ¾u@Ûz „: â_ûó5#p zþˆÕJ8Hp°þS’ ¥aâ(‘ jÿ& xÒþ¡S,_d@n;œ2 rSĶ«‡ (2UÀ% P‚^D**9¢@•´x=J<Nf²¿TÀ/8«tKQàÔ”* ¸!U@¡lPàä^9‡ (¶H·")¡"‡ øHp” øˆùŽ8PˆZJÇNŠ€\Da l’ w¯>4@~W(Ðë[èÍ(Ë̬Jã;4@¦þI”ÈŸà%2%ÀçúÈ•Q "ÛŒ¼¾Œ•žQ ôëDè-½/¢@ù}Ì PÅ“ŸQ Ï‰€.bÂTÀ"×J†Òi“¹€åV_„N¥èE(«†É€ý€:ú• x1x”‘ ñ·"A+Ýv ªÂùmSþ3ËÇKýcTa¦¦7¦úÑ£‘ XyîL¤ªt¤NL†G. VGi´ûFW–éy®±X›~Sµ‰Bg_›äAlòíˆ__mY‰èþ}‡å¨%& åŸYKlY>À¢:’åìˆ6ufGOÁSÇhe9:’åŸGGö=«#YÎŽhSGñçߺLÚý>ï2i_kNýèŸF:ýî?Í_Ûv\?=¿¢íXƯ’j_Keýšêjßéû¶ç«ÂÕa W|W`cOGÕ4ôtMSOÙˆ=½ê¯©§¬™ÆžŽ’iÑS4ROgõ5½ZY1 =ÓâuŒFìéU{M=e½4öt”K‹ž¢‘zú+jªÝû—ª^=ÿ¿©šj¿fýù='~›1þácûšEüÐ~éå/®©v_ÿ¯ÖSeò¿Ú¿~e=5kú­žš³ÏÿúVOÍŒå'G=µ½Üí£¿ÖS3Ûýýlª§Öž_®§¶_&8à<¾ÆëÅüv~'/8àÜy ‹'c¹Á—C÷¶8¿¹7Õ—÷‚Î,ð[ß˶“™<Ïã†Iç[¡/dYIÿ›¥t³è|+UG=t¾Y <»3«:ß ynY5~§·Â*@ËŠïcªû«v:ßTr`ÕQb’moÛâ?ö²ù{”ð_V{”0p~ÕηÒuТ÷m[*NõÐûfmü[¡÷­0!oÙ»ëüV¸‡Ý²êÓp¬ã·Z‡ó­0ŸuYmñÆ" >›o o¶ÍŠ_rfñ¿‚6“ηr±ß›¾·ÂÌ¿Õ}o…*Èjo…úÀê…ηÂ] ÷[Jç›UhpC£ï­0hqõNß[¡H» ”¾·ÂT“mïÍ@ÄoV¿è{3¯¡_qŸô½Y7hsÓ÷fîx_ô½n¬²úCß[amž=ÐùVàÙ‹YúÞÊâc2}o……2ö'¾·ÂºEk úÞ •ðmy¢œ¢Ã÷׊rŠî…ZcÂ÷V˜ñ½ÆMß[a6ʲ•çÅjÅxŽÇCç[a"ñº o…þƒuU:ßlñî†ß›ö±XW§ï­p‹™u úÞ*“ ¶…¾·Âº1ëºV„Ðáj®©m¯ æáuÝÚöšÑB{Ö¶×…?ùõhÛk&-¯YzÄй÷jÍÚ¢–†Ï˜k6í{Íj/kví{MçÊš£àÏ í{MYcÍKû^3ome4î’ë#˜·¶½FêûšK»^3äoÍG»^7x_Ö]´ë5kƬ»ÒýV¿î–Û^ã ¿{n{í2ܶhÛkfá¬{ä¶×þ+øb•WÃÔ®×™—}šµëuÃÕ¬Üõ㾟ÜõÙ*ÚõºóÇ\5v½vòZ-w½v?ÙZ]»^³¤Ó¶h×kF»¬5r×ku­ØvO±}›µï0nòºgÄÒ¹²¹ÖҮ׃3Ž-K‡©Ö¦XÅÒabõJ+Œ½ÄwÇõ*,xÉ!žÝtízÍj‚Ë}Ålƒ 4ç£-ŽýÚ'ºPDuAlù’¬Â‚gòYÚõúBpËzm{}!Bì1êgäìcù´ƒá‰>¬ÇwÄSÅÕµíõüD“®]¯YÄé±½»Öq5mÝ¥8hŸž2µë5§ÖÇ>ÓÚx½,mzÍïÅc_éÆaú—|¿¶pÂÙÕ=n¨t™¥¹¥Ñ ÇÀÎÇjï_<‘ßôÇ6k™¤ÏêOŒÃ¨œÕs±,a5‡¡b8íÞõp˜—³‡¡’³}¤+ëÚàì­0#Îe»=tÆ'úLú´†8ŒÊš®í$‚8h¦o ã0*s¢ÛKa2r7Ðvïºyr‡ÛR ¡ý~Ùî]ÏíWl»w=´,œüQ×gÍǾҪ‰ëž÷§WÆaTº:ŸÞŠQùMyº ¢¾úéãé7þô±8‹³Ðc»wMžËç‚ÇvïÂ,άøÇvïZŒlhc£`|)†Þ†‰âç´taˆpå” é†VOÇ/Ó3Ì0Îëýa<]XÆb< S=ãº#š'Ÿî=Gø&,È&ò6>ù?¶yâéü6ØÎ]íûDžÈáä¹ükƒ÷z!ŒQ­>ûF7ïÒò0˜®ªcr·¥ü‰_SMí€@¢^XÑ× áù= …¾+2™ø€@F¾Èr²FÉ ŸƒU-!1° È…÷Á€¬ù}0`'­%²žPv,ŒìD· @$îØÉˆÁL{>øoàt 7¬<p „—ƒ‡˜0Ɉ² ®Ði†@@VG t `èÈ 4#šåM‡è[YâT¤ÀÃB 4 V§¢@'w')Ð9¬F r 40'ó‘½_²(ÐkåIÝ…6¤@·  )ÐݺW'š,It78‘(ÇA0 ;^ hœZ hÜuBàbý’`@7¼Ð{ù8н8ˆè–ºÏâÅ€nAÇdÀ¨ §E ïS #zX Œèm|Ô"@/<ˆ£@€n’͂ŴÐý8ˆèÞEt NE´£`ޏqv  µéÀ;" kŽhm°Æš¥øˆ€ÞØè%ÿ‰@Àt½Í‚A€  ´&x²D€~,$@o ¾v‰€!‰€‡Eȸ“DÀÂpÃDÀÂz" Šã$ªJd"`A(o`¡‚˜—X¸‰g`á·˜¨’;I€%xOhq˜o S `a°t2`ij#,ŒäH´ S}ÜÁ€…Ù©É€6LXÄ€…aªÉ€Ö,bÀ"€î‹•hù–Ž5FB`aÄwB uüq2`a’w0`ai¿dÀÂÔ¿dÀð‰ª¬o2`aæu2`é|²ƒ­ç ‰ 7*H, #HTzo"`áÖ€‰€ö— ÷ÉL,Ü);0œk€…Iü‰€Ê6N,,@™X."°0 ÐÚø’1P‰®‰€…iÕ‰€åÂ/œ ˜ý͵÷fÀìF X¸™\2`aØzB` r–KHEÜM°²,Ÿ³„ÀÂj&I…EE’-JÇq)(°LLCIE¬¨Ê¯Iª••X˜ŸXX«1)°Ü:Q ½†–sîWˆØñ­Л °ð«œhÎG𜠰ÜBGB`v#”Ç2!°°œFB`–û+ûMŒË ,·PMXXs?@Ðý)¸¢¤l1‰Ýuþ"º{ÀÖ•”}KØJʾ%!%e£Á¥Œl•=º{¬x+#ûâõ.¸1ãG)ÙKB_QJ6³=;²`”(ô6è‡0ø´—臼Ô@ˇ@¡ §[â(² çL€—²ùš šå¥¶›ô#ô4?ÿ6…hð™Áv %6¦ä§ ظÇk‚þ¬Ë*¦ Ø8m¦ Øpž‚`ãvA)6ЧØmšz`cmóÔÛ¢/9ôÀ†B)¶ÅeuÈESl- 5°ñ•O5° 0B lذ4Å@Ûø |&1°I> 1°±²H¨Û§hõº>4~•›tŸÓ"5P{˦ؤ9…ØèL50j`£:r .0ÔÀƹ.Õ@d 50Æj`ã¾_©6zS lâ¼PãÜ»¤«#sS ÄÞá úQ°H Œj`{¾ªõ•S ìE J5°3™;ÕÀ^tr± µ.J ì,u’j`—¶j `V È2áÉqšà@•WLT ðä@• OÄý89° ˆâÀŽÈöÄÀÀ&´‹8Ð:Š» 48ÐÖ¿6çÀÎMГ;ËÉ&vî“hcLŠóÔâ@;õ›U‰09P›´%Ú¹gâ@m7œØYÆ79p[ ÷Æ0Å*z˜Ø¥‰r‡¸ÄÀÎ4üÄÀÎÎ’ãúĽ~Õ;«N%öÆ9*8Ю'ì¬ÄØ¥ëö&!R Ø«D`çÖ ‚ñävf3$vzó;ËNö*Èv:Oì A ìÜš*A°Óž Øg»ÁÆàœà@½DÉzt’;÷|ITQ‡ä@=É^­à@{Þ`êeLìÜÐ"9°³dYr`¯Ÿo-i˜Az[“Û#µPȉ!!°3"-!°ÑØ+¯. °—“ývI€MÂj `ç$À^¿ê€qc‚5ýÚSóq`güB`—صøìÜ÷) °3 &°Wi‡"@KjÅňã1 ìÌ®Iìôƒ%j‡$À“ÔÇ}wê£ÛñÀ¾°öñJâ¶Q }ýôuÅwô1Oû€>†ÊÐÇ›ƒû:>û÷u’TrN´ØÈ+¡O–„¾ÎZ}qý}µ‹Å}µ }UJdp_¥š›ÜWùL%÷iàä¾Ú?ߨ·!°OÕÚ‚ûxLbŸ*ä%öU&€'öéV$öéf&öU ìÓ½I쫬¸™Ø— ûjç¢4°Ïî Â,…}ú’ûÌ‚6⾊"Û‰}•‚pb_å&ÐÉ}ºÅÉ}•¯mr_ÕâGàggO ü*½ÙÊrWGhã‚>£@›P+¢@¹·b†6EkF¨./Ã@»º‰0PÖ/9Â@ûWò §xÆò9É0P&Ya ê8Ã@Q7ëeMí# tˆê" ”eG2 ô¢Ä‘a  ÿÊ0ÐKAŸz} ½>¿D^   eXø*:£@§¢7# ”!OG¨„㌕ܜQ “2HDNÅ|Fèå…x‹B«ˆ¥§øˆE„yJ€·b>C¼ôJ¸Ž‰‹!Ò§zH€ÜùYxùF› ‹  Ú¤(‡Kj€‹Vj€¬}h€t§P”Ÿ$%À¥(Ñb¦(59%À‡<ž ¼4)JeM ðQÐg„JM PÞŠ åî G( }Q ’CdŒoFÅ|FhQFhe,iè‹q €K|&P±Í)j)>÷B|¨Á¥ˆ ŽPf9úSá‰Å‡G ¨†™ O•! ER^„€* "B@¥-§þ'µ>C@åmÉP=B@åôÈÐ"ñ1B@Ûœ! b¤ ­Œ=ÌPVv9B@ËWîS-Ò#T1 ,ùpÄ€²°Ë*¼ÉPÆyA Øo鈭â<Å€jÑœ1 Mø1 (?yÄ€6j/Êð±#´}¿´D ¨ (c@ù±=b@ÅÚ¤äE (k¢1 ÌÉP._ŽPî~wÄ€6Þ‹Œåñˆ@d (×&Úuîˆe†ÕʯøJ=çˆåÖ{G hW¤fÄ€2I>ᯠÁ3´‹¸ˆE6W²_å&aÉ~u¨¬õX"ð½©)ö‹óüA™ ô³ }bGL¼~u0`5Ð/O$ô³‹e ýLéÂQB?•tMô«,O”èW±ìHåïRÀ§È¯2.ɯ²‚Q’Ÿõû–þ—þÔQ{¥^ãʨŒ# ˹ åu2€ýŒÄÌ ÐûóÍ^â%þy¼Ö—L@xíPn‘XJ€á¡DŒ%–ÊüAQ ݼ)°ˆ«–Xp„8°p‡¡ä@³ ÒRX.±¢8PAɶ$ÄQâ@‹\`n 9PÑ Éú'Æö\Áåk6 ¯sÐF XeÜ ‹ð,HPî$Anru \|Ê«› ÈÝY˜å‚”×0 ‚,¨|€à ÈZ(r÷¬'a,@ rÿÏ|™ 8uªAî™ È‡ÞÊ J|NT±½$ÁÊ4I‚Vïû%Vî’’$X ¨¤†Áª%U€ ‚ý+—©²t顲BÖ¡*ì/@°rÿÊC¬ŠÚ °ýS¬Ró$61]H€rþ§¨§6%@‘=$@nž(¨ú͇¨p·ÔEäÁ‚­Iñ ;Ý ës& 6åd 6ß ›¼)‚m(øS(¸¡L(TéãDÁè'P°‰ŠÅ‚UÉ“Û`Öe°`SBj° ÄF±`â<±`S|w° ˜þ8Q° I”O–f†F( j׿DA«Ø÷mWd²6s{‡ƒ6~—’7‚HlüÄ& ¶ùùFÁ6ªO–fƵ 6M'‚fyGƒZ©hpžP°Í€Ã,Í …odeæ7 6¾ 6ÖïOl7½4Á‚}ñ†AÕØL´x °aÐ} #.!`°‰ô›¢ÍµÏ^Ò`HíAƒä& FèGÐ`{¾†ƒ6P ¶%ü p ÂœC,_ƒA³,Ø%Š#t!%ÀB¡5%@æ% Ú¹ß,Ø™‰›,zÙ©".0X°Åy†Xz‡ˆn$òãH€Lc}I€ëع©Ã!"˜û™êŸ`SܧP°7*~!6¥ú “ö„‚¡ ºë¡6 íT°CòIi?/÷TÀöM¤¯;UÀ&ì  ÔCäz¨€ƒ9˜©vrÊ©ÞľqÒ©^RøBd!å— Hè õÓP —*àE™š*àÅg8U@ìÁpˆ€c€`¿$† È„ßC¼¾É€—BEÅ‚Q㇠ÈÌ©C¡¥ –Yûu…!NÅ…† xÑa2 ÝÔ ƒý ªñQQ­–ê«Â,ÒS«_@Xþ5ÚD}´¯Mò 6ùvᝍV‹”~õ-ËQvL6–'Ê?³ìX-V¾¯¿:¢åÕlÑ‘þ<:ÚÌül¯ÑÒrvD›:Š?ÏŽV{w³Ú×NV;ºX_j»ým*©íY×éÿªJjõúÕ…ÔöBõWRýúZHíOò¦V[›Í£®ÕÝÊ|«lž²Jšú:ˤ©¯£ûzµR_Q'-ú: ¥E_ÙJ}­ô^E¥4õu–J‹—1[±¯W+õµÒ¢¯£XZô•­Ô×_QRÍês®û¿¹’j¿fýù=)~›2þñ|N£âé}÷ò—T³r¥÷þ^ÿ ¬šû—ø×?ý¨ÚÙ·²jïÂg»²jó}þñÿ÷eÕö/h¡îîK}ÏHÜÉw[Æ¥ìy÷èlË%ç+¿¾“™ÙÌyß–»ãƒÄíjŸÊ^¯°³Ïq1Mà.vۢХ¾-×ÅÝÛ2™þ`íîÒ„Ü–Õ>•$Î^4îu¸¿[·X0Ë#ËÂQÝ aÐÇŒsw£[fnÃÐ#-{ð Û €Mر†0u»:†@ßþûfbta«}21š?B")»£Q¸"!òš…¸5¤¡¦·Åpžkôù©Œj¶±’êlƒak|2=™ÏѰh˜ M‹„Ý•³ÿ^íýߟúIG;Çt™C–N ӲݻËöi;š·E#xÀlÛ¢•äŒë¹fÿ”WŸÛ÷Ýf1õ—b‘\Ë´Šuîöï-Ï'kÇa”ÓÜ«4àŽÏÆ€ŒªóLÛ–¿Áļ û¹†,‹§šcb¬Ü¶Ü퓹È7Û,†d0šr[¦õ^8æÖèF7Ë£ðŸ ç¾Í¹ Wñ·9~`Y´||¸žÁ§æ×çõn£10èj[4† XªB&þöL1„UX:ˆ“¬Í?ÊòÅCkoø'³7 »™]¼‰öŒjPxüìødâ(>˜v‹?4سÍ´à‚«†À Þm©lCjäN¢Sû.+ywÁ¾Ë yÁë5>Kuñ,º~Æ!m‹®Ÿ®Q;m•¯ê^±h±×u@\^+LÇ^º{­"ÈV8ÛÒx ïBë ÈÁäSí»Ìh+^¯}—9$<µÍ. ®ìu€câÕ5àѯÔ4‚¼:›ÙÙ–îY¨'³-¾êŒ:†ÛbnX0ÑÕÞÄ¿9†ÊJÛr…4É{ÞgÿTÄFÞ}»õŒÚ–Å\lÖ 2èÃ÷r<õÀriU|i•+›zµ)ËÀÙm—¯3Èžý¡oõs±"&ÇjßfÀZ4za·Ec¨z½¯™Ú8o\.ê#V 3Ë p%Ó Ã¥„¼-yýìuæõßl3Æ'Ã|&®ßöøâˆxϧ‚¤x7íËÌqZ±/³j>Ò’×?x}Ï#ÂÕÜe}ªÐ!îÌ]ïO…3ÁЦ…ÅDµ}¾4qy÷·!ÜB×åØF_ªÄÈ6ЉÒ1«FŒ7yÊ'ÉÛh]ðÒºÞæ§Iy›· "ŲoK¿å=1NÛç‹ñмɆŒZÐ¯Š‹ýÊ7ôÃãŸè×>iü5SÀŸžÀ„?jÓü5®“ƒýb‘ìÇh˜ƒýZcÂëbǧ 9yjŽ:Øø(ðëb™–ðZ¿€_n€_רüºÆà׃óD~£ðãÎtøuÄ+øÅ´+ŠËê¿XØøqwÃü:? ~ä7]ýÐÔ7Ä:A}C«ì ¾!êúíƒú†p‡Ô7‚AÈÅ>¨opêIêtPß~õ = WŽ€Â•# aõñO Ÿ{xÏ ÌáVù¼ KŽ\ÿ¥ë¿ÄÝD¾Ã•@äóà4˜Ï-¤·v˹Àû@æ‹tÁ|nÁ} ó¹K‚ô^Š2uÁ|Kø¼þðQͺðy xý±Ž'ï¹…Vr?Ç‹÷ÜB–—Ü%$[×?Eï·®?Û€•¼°{,EEüà½(uGÞó7ÿ~4(¾Kc¸õ毟!òžûYØxïìçò¡Ü/òžûbhÑÂó²4…€Oåøƒ÷'óžWÃ{ñž[ðó“÷<¢‘X¦!° ^_D=ðy¢€/êì𹫈Ÿ»pņ°ä |4†¥ï=o=Á¥ò˜F ð¥{IÀçî%4„’’CÀ”&ßiðyQ?^ €o=KëeŸ—Þ{_lq@àó^â;ÎCâsï׋ø¼x ò¹…m4‚Gä[5‚Gh ^r‡Ø‹ø¼Y¸ÅÏ£;Lâs NEâs7‰®ñ,•[g§ó|~%5Ÿ[x €/}s>·s\pµÀÍ~|ÜÈá¾"ô%ðùÃ|Þ3QMcàrPÀWŠVî¾£_Ò’ö™8€¯8 øŠ˜FÀWs ã |ªQ˜ÀWïÈ{áO à+U˜Cà+r%Œ_ai…¾’xGX*ܺ3ï8/o—€/œ|ònï•*wƒxÏš°ò^a‰ñž*&&ï©4cò^J¼WY”¸g'"|’÷ìDÄ.ò^©œYD|…/’øŽƒ46 +•ªõ¿p¯TApÏj%²q¯ ÷J ÷Ta1q¯4=žÂ½Òô  ÷J“‡B¼ga ¹R¸^ßÀ½Òô›÷J“o¸WZ q¯4̓Â=kC>Í!ðí^9R­pO÷ìÜlCÜS!ÉĽ£âÞÑOŽÎš¥1pLÀ½ã<Ä=•šLܳ6ní…;hÏB7Ï1€7í±îå_P/-xÏÓëä½G(7.yU…rÊI¥f7‡<Å\®‘õÜ}Kb\MŽa‰ƒO•¥“ÛJ‘«ø­ô–ÊYâÒº…´çÉ­/¥/ªFíùQTí®!‹ŽRZ-×1¤½Ã•Mà;{É1°M?Æ@¯<²Hû«+FõRúŽûEà;-ãÒ¨¸ðï9†Á³kwy_”š âóìõ¡cè–ߟÄçåè^ÄçÜOBßq&B_dšôEš@@ßÙóEÏÐýEêó£©ÏÏD"Eè7‰"Y åÄ÷²DÉ-r"‰/Ê}ñy(鋸< ö¥óEÙ°ÔùÚtI¯³(ê|í –ät$ôåõIèú¾‡Ð7ª\RúFÕR\Jߨ\óKè£WA*ßЧ%T>®¯%ñª·$¾ì’ ßЧ† ß`eáTøFÕµßyíjCu¬q _»t³%ðµKr™¾†Ý˜Rß³f6áX9/å½Ô#y¯]º‘’÷ÚätuOeSÝk¡†KÝk¬›êÞцÚX÷‘Ô=ÃIu¯‡IêžÅ×R¨ÓV°‡ÐÃQ%yO±Æ)ï™…xçòžÊĤ¼Ç€åT÷zˆ£’÷z̾’÷zÈ¥’÷zDHHÞ³ÜíYœò^¿¾Ðž‡´¾å½þ^É{ýâ’ê^¿µR–ºg;º³Õ=Ûž›h—„É{]‰÷liö¢=¦%RÞëÜò'å½.[È{ªt“òž"„%ïY´/é¯)ú—ÜF}¯ËKú^žY_¿Órå-ðõ©¬¾>î Y¬9ÏE¯3ï'>=7¡ïõ*Xj*;;%UHßë]+Xé{=äé{½……ú^/½ô½ÞµDl9ÞNá^ïbá^CßëkZÉ{ñSÞSᣤ½.¯gÐÞq Q©-¹E{v +ìùX öúMP#úá{}Èe Øë=,¤½*Œh¯Ç’´g¿Â›ö:=ô{1‹ìõ&¹T°§º[ {=48ÁžÕÔ"Niñ¤ ö¬¸Ý›öz•ÂFT²6!ìõ*ìu±&ì©>_žªú%ì©äWÒ^>#¢½}7¢½|®…{y‡g($ÜCÿ¿Ä×–¦_—È6•ør±[ŸRVøz𿀯º øìÔ¤0Ò’Òwøz‘3GÀ§¤š$¾r³ˆ¯‹–|=ÔfŸý¼l£r¥<3yO‰9É{vf¶ÉˆŸ4‚‚_£‹,G\Šïnð^¯zŠÅ{½HÆï©Æ[ò^þ˜KõúèPY¬Ö§éH¼×Ã"ÞSêSŸ]ïø”B•À×Ã'$àk7¦‰?Sí ¼ŠúhåU-”ôBI#è…F¤'(OÒëZ éõÐEI]KÕ ½XŽé¥E¤bZ^HgAzR€“ôÒ"Jê\èô2ÀT '1:A„ä¼.qªçMœ×%WçÅb.8O,Ÿœ×©æ¥b˜8t=oÀCîþî“”W4³å™å¥ë¿ÉÈëC^v,ÈËŸDwtCÈË;A^¡WbÝ;4.yù0ˆóò<â¼Òƒ´ÈyE „༢p€à¼ã¨coÎË«‹xN-i2ž³ €#ž3{Ö$c ¾VÂDÞR0düNÐƒŠ€ÎxÂ# 3ºÉ¨IÆBŠXH*‹ŠçŒ_.â9ãwaû@¿ :)M¥ S&[ :;XtâÚ»HÑ9ô.ÆÕp>é™$éÜ$I:7RtÞòr m$ù]Ü&ýøÑNô+¢Å-)ÂåÄ~ —ûU Å~üî$ûQ:ýb?´$ûݯp>ßâ‚9ÉAú@ƒÁ4¢¿¡ë%ýMºD“óýMîÇ„ê ÿ ‘ìÄ`•¤¿l!ý¡Ú×Aû—ü)TðGÑTÂßMTü-þJ‚¿[@FøÛ”Õþ˜Y5áyi“ýŠ|dd?Û€Á~LkžìW`©úI/ô+åÓÅW _²_¡!HìW*»ˆ~Lù™èg ëKשœ¤É~Exl².oô+¯ ѹ1‰~–”î~ €ùéqI~Z"E~¥óg"ùž‘üо+$¿2Ô‡S Gägù'ß®>; ã€üÊx);• 3ɯˆ’H~ú¨‹üX.ѯ¬ÏH>[Xz@¿t~ýÊTKÎÜÉ9ÈANö+[ Q€SI1å…¤y”z‚ýÒÉOö+û#”Ͼ¼/e§¯B@Hp“=–ïP¾r+(è÷áè+„ßq¯_rA‚_‘þ.Àùû’ûž†õæ¾r:úª ×ä¾ÂÐ]qßÓv~rßq¸Ï2ú½d~98¸¯*Ú‹ÜWÜWe–î+bYr_•Û„ÜW ÷“¿Z˜3 ?rr¶üªÂ¤~•5‘Ÿ¥p{GòU… ‘üjåŽ'ȯŠ‚üª¤`$¿JµÁï8 À¯á"À¯J†Fð«r¬ü*mJ¿*µÁ¯Vú;~•69_­/]ç]ßQ|U^‚_mŠ5UÅüjƒü˜,1Á¯6>?kšªâ›~µñ)"øÕ&õ%À¯2àWét$÷!arŸõÀ ¦§¥¿Ý|•™Ä}vÔ;ˆOg"ö1bb_U ¹¯vb Á¯6ÅüjÄ œz¼cøjç¯?r àWŸ+‚Ÿµ¼Ý|•aÑ¿JášÀ¯vêþ~•R6ßÓ‚WEn¾ìjªãÇWãï~ǹ~–ÞñÇWl?fLð3½ ð àg}à øUZ~uÈ;˜søä«“ÎT’_å ô«ÒRý꤄äÇ*VI~uHJÉ) ‰)ÁMU”Dò«SrP_dJ’“K&ù=K t°$¿:ù½ ò³§°Ó¾øäW“9éè[Rm‚üêâ:rç °Ý9X åè›±Ù<3 Õq#KÔCvÝ2Òf"žßÔ'3 }tɃ˜íóˆ?­FQ¾cl¶œ©ÂÐÆlBúóÈ7Ö,Ý^?bË9Ú8þ<Z»½S©±å5P´i þy Ô+c~tÛ*½9Ú8þü§gB«Ëk§üGË„öý‰®£6†š2ÕáëL½YŒuä8ÃX¯gëè…±^½8Væ8ãXgŽ3Ž•½8ÖÙ‹ïWæ8ÃX¯g|)³ÆzõâX™ãŒc™Ð8VöâXÿ@&´gçkã´Lh?ñ1ýõýqüöéüõÇðù9ý§÷=Ê΄V, ëswþ˜ mÿ(Ú_ÿ7ÈVGQ<øÅOâÁ¹P6«OüÝ+cÞïh §Þ¨c*œ: êiQ<øBËR<øwFTÏh¹ X祈êØÑÕY:ccó|Ñ(øbäpüÙë~\çP@òÆób°nØÐž–[Áºqqsm†µ´pö¥:9Øëºb·YWéŒsÅ0«6FµnÕ*£'1ÇÕ²Šc8XëšbSý´ÜŒmvm†„Þ賃 +.–Œ>›S¸9…Í) IJîÚk×·[Uf°hè…V뎃bðêž—2ƒa©<`˜Á^›-¸Þ½Stë½ç;5X"r‡­»F™›™‰Àê]•lâ¨V)©èÓ å1a˨÷¸¤-C˼âožiÞ’’DÃÊ<`ñÛÞ[yÀØrOÊcâi×5(éh)Ê¡O}»j£)~¢¥I7>ßg”n¤GÃP­`‰§å¦mžÃLü=ð÷‚è¢ã¹o׆肯i»n¥ §I+—t#˜B)™DkEKmT’Äå•V©Ž‰+]9´6úp ¨Ah-™,¦Rhq˜…Câ÷o Ñ¿pcæVK½”C+, ­ÉFØR[ÂJÞj«/ÿB«½0/X¶WÎaŒ߆¦{¡¥VŠcb‰êV˜ ^Èx¡ºUæ‚ÏñBŸqÅß=8.˜ÝÖe´àþ™ òüxÏN–³ŠïÑCïƒò˜ !ÚzRÓ[Îa¡çÅöO§?Kìs§Ö û.XT‰},–ØG:#÷iû+îƒ#,±¾²Ä>~®û˜r ±‰}ôå'öQØ—-œB,Sä>fGKîËr´‰} IìË–œÀÆÅå6xФ>â>Jg’ûˆ¾ìÂ|bÝÉ}„؇Jäö© ©ñ„I} ëMêSŸÀ¹}Þ#ûΣ:ri×Fyÿo^>5[„¾³ÏÚ´7\ÀÀ½4#Àä=iog¡ï8 Ðç-@¼c1 Ïû€Åz‘ª ㌋ª2ЮCßÙcÞšÆý6‡›sÈQî©`Õ54+`UéšU,ª ¾<©/G&õy¿h—&õ¢¾£Ë¼ßÖÖœp-{iN¸–œA RŽ ¼˜ïèRÛÇŒÀ|Ç™À|ù«ùÎ>9žjnM)æàÐwži/Î ÃÊ2:˜/Ó!’ùŽæ;û´ªIÅåúÎ>ãú˜ Ïûs ‡S(ô×rOM)n¨/' è;.¥å0LË p˜^>¦è;ûŒ›S©æÖŒÐe­5Îû=g¾ãÿƒùŽ9ƒùò4@¾³K«ïǬçåãaèÇ忈ï¸ZßÙg­øÎ>œf4޼ïÈwöiª"Á>Á|9) Ÿ7Üh¹?&5Ž) ÏZ“ó}îññî8ó“šÇ@ÇЧÕIùÎ>C¹DÙg¨¦ê`ðbŽ)ÄùÎ>·r‰‚îþ1''¾cßq-ë˜A\ï:f@¾»>~(ßÙgÊú ÐñW“SÀA9ÒÜÕ?~(ßÙ§¶sßÙ¡Ë~ÏAŽ Ï1ô™[-è³ÖÇÓä;ûÜCsàSˆ>wN¡ÍjÕ¤â}¾[}Ò‹fß0 _NÄwrL|·ÖǤ@|çÅÜãýå&ñe_ŽCâ˳òå#ÈwŽ:®_>[î÷Eæ;û3Zæ ØçÖV}}G@ßq½€¾³¥Í ×˻Ƿ9úΖ¹ß¯¡ïì³µÃ.Ç€P9‡x(}ÇõÕZß¡ïìÓµcŸq½Ï”sÀÕúŽ+ô}vn†€·vCõ}ÇÕ´œ®¦søúcYЈ}(á!ìsõ;ø¬Á¢=^Þ>oéìá‚öeø$¹ÏûĶÜ—qä¾ ¨$÷y¨&œ{—„öØÆƒûÜzþâ¾³OÃÕ”ƒûŽó€ûüZÐcJi_€póæœè\›Ñ“=÷ò÷éD9ºàÔ·"”á ¿oÊÅFßÕÑßÇšXéï›4°^9Ž<e Š~ÙgâïûÅ~~ δeÍ>9‡FË9Ð¥–î2ÌJ?Æ!¤ÇoÂE!‡cØÒáGEd:üøœ§Ç=~¶”ôøájoUÌøp÷-ÀU^ÿþæîÃÅ¥»/þLg~9ûr:û8åšÿöõé7ƒ¯Ow_Î>ýBröi 9û4JË«gŸ–¢ž²)ŸáP½Â"}}90}}4­¦¯)ÀéëÓ}¯^R¹ú’®>æOW—‚tõiF='€õœ†¡§O¯=}úÚÊÓwÍOOŸVAxúòDtõ]KGYCWŸÖ ùú´ZÉ×§ÕA¾¾‹Ñ•òõ¥;xäxeš8}}ùSÒ×—'__žhæpkæ·)Ð×w´ÀO–}}ùu ¯/o1}}Ç8ÇàÙƒŸ,ç _-òòõåÛ¾>-òõiI–¯/ª•s€Ÿ–¾¾|ðéëË«¡¯/úú´âÊ×Ç9¸Ò®þÑP´"zÕ׎L~>Õé’Ÿ'¡—/ïäþvíôòåÓ@7_þútóY\Ê›8 T^?|Þtóåg…n>e×€›/¿qtó=Fnãл¸ó?5½|GËž“¢—O?‘¼|úÔÈËw´äH —×À€½œ¿šü|z¤äçÓÍ“ŸO³ü|š¥ü|ÚùÉѧß_޾<ŠŽ>ÝP9ú˜ÐD~¾¼…Sh8$§ÐÐ>2=òóéËÏ—'‚›O£Ü|yoj΀dYΉn>½ÈróåïD7Ÿ^I¸ùô‘“›O¯‚Ü|â¹ùôI“›O+€Ü|9Ý|zðåæÓ68‰ïçßKƒ–˜çEºÌ«Òc6(Ì&až¼>¼&´ªÊ¦uA¶ÙÚ»Ggþ¥øs(µúýAy_‚¼ö òò y¬”™GMBžúò˜-!Ÿ„¼&`ã Ðad*­Æk¢ÉÔDîÆËSïÌ¥¿á­\Z¸˜SÀQ;§À>UÉ´pÁ‚<ÚFN]ç~a£ûN]'}‹ó#XbÞ‡¨3;ÜYõåß;[Jfœåð{ òtCQ'œ¬‡¨nM@Í6 yÙ¢ à#”§ç÷Pu’àHHLâ“”'§Ð¡ê„AòÊ9Ð7×UÝõúuò “òªŽš÷{\R^ŽKÊã½IÊ“e[”Ç»ž”WÅt¤¼ôÍ‘òdœæÉ8+Ìû`¼*á'1IÆy0^^ O.UažŽæé(až.W˜GGqb^¶ôh€èéWè¥û.§€ƒÖ~Ý:€Þ%%èégèQj Ç,à z훪SwF¤'÷¨HO—+Òût扈yz†€yyš€$‰ÂÄy²ä‹ót!â¼*ò#çe^~ŽÌ˯ß$òs ôtÃzÙ‡ §›×9‡OГcޤgJœ§‹çiXqDŸ„<Íq×ÿòîwF‡Aˆxé컕u¿ò$<Ý™‡]„—î6Ò‘®D„Gq§r¡rXâó®&ÞéÍÞeË­T¢Yx§&ðN?ªðNç^9ëåØ;& ¼Ó´…wºá]öYÙPïòz8µñà7#ñGßiÎâ;=â; gñ>ÝzÇÕ ñô ñpùN®øŽO»ðNW'¼ÓýÞézwºÂ;&ËL¼Óo$¾ÓG|÷wúwzgwLž–pÇ[—pÇS'ܽȎïÉŽ÷5É.¹ëù ;^l’]Ž£Ë? E¼m‰uü}ë²±NÊë²Oçå¾õ›Ç1ã~ï’ëò¨¥X– ŒÛÊ ¥cù6‡šs`KiofH°Ë>»ªÃŸã:7 ‰tºýB:]½.ÏA¤ã—HÇu&‘.[xõ”ÊI¹y…ðþd:;Cöê‡vs‚ÂÚ[I&ífûåCºÙå{£t“ÞÔn2eQj7·ÏÒnšÒGÓLíædü•´›ô‰HºIÝ/¥›ÔæRº¹ÁGÝã’B”ÊÍÝæþR¶É:‹)ÛÜø¾¤lsÓ{#ÙæËuç…?bõ'Ñ&+øQ´Éz)Ú¼v—Hô麻D”ĺKã똎'±Žåæë.†æ‘êŠÄ“éV>‚õ2†ŽTÇ„a¤:F›$Õ1ç­‡ççˆÖ£ü3CÝp1·¾$©K_¶}Ú×I0|ëo\·¾qÝ"Ç]çWÿ Öƒj÷à:RÜÁu`ʃë^ºÍc ppíÀ: UbÝøÖkˆ¼<±n|8ïX-$±náL‰uˆHÖ5¹ór ë#ZO}„u]’Kb]§Aü×´‘ê:-¿¢:uÉxÃ`=…aë:lމuþÝÄ:&vK¬cœÄºÎÈaC7ëx1¢º®@Òž&æ1ÕSbÞ”—Ž˜ÇÜúIzSÞ>’Þä÷ñ>ælË9ÐFRÒÙåÉ랼ɯµP©”õ4Ï;ç€g@´—g".åÈ·ÔLõƒö(‚KÚ›Œf»róoú1 ±Ní`nHÍ4?\yŠJðåyr ãä xæ;ÕL ¬Kj¦õŽÙ“â)™oâ{—ÌGÿ:™oŠÌrŒó’3­æ£.#™o*öoK‘µq¦œ#ôr8{MGØýÍ™W^òÍÃÅz:óÀuræØgFIg9œyä7Å‚‡3ï³'õO’Ÿœ‚-ç€$×™ê¬GLÖ̤9ÓÒÍf¦ßÔ'S}tɃ˜êìóˆ?êl<Ëä/¯|`l9ó¡é‚ôç‘Xl쫼3”±å5P´i þy 4v=r`ý%[ÎÐÆôç?=CÙ¨]øÊPö7r‚Y¾Üú-cÓ·#qÙG*±ïOL·róÌæôƒdÞg»HØ#)Âl¤W‚0ŒtôÁHïdcéHæ#éÁ8RöáH¯Tcxrô`6Ò+9ö샑މÆ0Ò‘ÌG:ˆq¤ìÑþ‘b}ETÕ¬üa?ñ…úõýÅùö=úõ‡Oíëõã‡öc”?ž?¬//Oó¿yþ°¿þ`Ì¿þÃùÃJü–?ÌÚþ]ÿú×´1X›'X·•"~¤É·Š ,ážv:Zn¶(¤QwSH24/wWLòFËPK,„÷Ì+ý½:M8ÓFËæfï¾ëÛ`7®KŠ…8÷¸ÊK 3®z%âzŸ©²ÆÕ6ó1Ä&r\]© îhÈ\°±ç×L{§q-T{¾±¯WLÁÊ ŒsÇây‹cÞ£\± z¶k±£¥Ä.èy›cŸ6J½âï€ïçïØ-ÚÃFÁº²ëwã7 Û­KF¡Q¦í€ž–‰)–å‰ ¯Â’£Øði©Lí>Š_þº£úå/Oe—_=!ͺìMEƒ…Ö5Sž…×þÞÜQ>Øm{¸eÉZº]ù2;Uà¨1›:ûÄ l£Û«QWæÈuÛ·l²ìc¦ö§e3ßûhf÷|–AûDÅÈ-¦`ÞÓâs¨uÿ‚.^Á{ÕU€SÏ»g‡ŒÅ?vR«.ä y¾f×ZuÓ23ȶ95%K-fÐ:µ'ãÁFoYÌG>š½iO˾Ãêö|<|õí…I³F·Œ?O‹2_?-¾f÷¡›Þc}6cèsênCLî‡ûLÈj]›Ž>Í®µúff +çÓ‡…GëïöôÆcÕãú-_wXÃÆ0[ôײš8÷ðKO SÐ<-f×Zã™5žˆaeÕŸ–Åâ)cØke}.ìüǰ9ÌÎ}ÿÃF$ ç_fzÆ ‡Ž±Ì°µÌ;ä2†çÚ]3yÞâI2žíSÉŒ3˜é¤ÆŒÌvƒýž–;æ¤eV³ ­çAãó:Ûò­•™ªãÞøÅ?}žÏÕÄÈ6‡¥ŠÇcÆÖÅÂc®î-*…1l/óÌÊü&Ö2<c[½ÁæôœïײÔHÏ(“×§Åg°ž9U…LfàÏ“ê-öÙÆQ}úït3ÿ÷x~ŸÓÝÕç¹Gk_LN=VÌ`«€ÁX1K‘Ž÷`™Í~M*!ÁËþúlKZõŒSõy²!í\ƒyØÇö—z™w%8ôùÁ}»²€ÜØ}zËÒ7xÏ·ëé˜0ò4»Ö³;¹b‘{!;õb>ƱwóIáË¿ãú÷bÂúqÇõï~ó iÖâXh¹}F7s] «Ë<ìJ˜arØòb3²ý`œúÆõo{~ ¿~»h¼+÷ì>£¡OÚ½<ƒ°×=Š9>‹òÓ£³ݰ%¹Ø¹¾Ó–ägVž#~E æÐ¸.>-13“öh©;f…ä-ój+&ÅìäóêÓ_ŸN·Ú¼ÆðOB¡a{^˜‚Ú¼!f`e²Ãê;¯í€ãuEpîÛ¯—å×§­È6§Nký´Ùú„àùÓ¾¼Ëýp1D‰Ë÷ŠqJ[ÑBwÞ,}úŒô¸>›ºá?ÓÍjOÓJX-»8>xÓJXÙŒæ…%b– ®Ò}(>³.Æí}Öäø‘0FõâA˵ÇC4}e³Q'l6'«e穘ÁEñ¬˜ÁdâJ°ù²B,7Žš¶ ZV¬e¢ØÓ²h„VÁÊæ´4o«`e?Š-rÑÒ|ƒÊÓù,Éö7ŠkM[K\J|]§-È5]hi˧TY)çù^OŸRçÎj¶0.X9—°0͆ ,¦ýœFÖ2ù~M+`…)ñì¶g~ÆQª³Ù]©¼¯øÀÍ×P¬ÙóúñÔÙrl-f¸G¨7ßY9šØ7ÍÞ}dÃT´Œ3ºa]–‹ÈÁmµZ0Ž_ÿs%Ì}7;®0ÊrÚ¢î3êøNÎánç}u®!Ó XÙŒ×Áù¬Év fÎÁ9Ü¿ ƒOaÛ~±c>½¥³òÔ|ÖdŸÔ¦ãkÚÔãiˆåu>«ŠOª0áð|¾Ú1)ÊâçÀ]êÓ*XY˦caNØ*÷¯Ó*XÙ¤Ad>g|¬Âa9mI¶¯öóÞ´øü§ ƒñ³Çn¤Ð›söø¥h•œsù>ÈLáxט®6l(ö¥Æ7dáú+wä´¼Ø#á×òÓIÃÖŸ¬#îÁzÙˆõXºëd=dÖC‰X¯bIHØã—/aO‚$ÑžâéE{BО'™`…½ŒyiI{®i”q|­H{Ç¢ÚsíÆîÙ;Œ>Sy‡ ÈrI¢Že—¸wåÙoñ¢…¸gÙUbÀ=åúî™õÇ÷ ݵ½r«ÄW¹*ù¢X °q†ÑÛö @ÍFïgræsdm'óMûé±É¯˜Ãó_@±B€®ß* Ï±› ƒ¾i»‚X Ãýèjéa¸ŸÌ—è{ZŒò€¾}ú¦}†p¢R†Íò¾`¾yÛûB˰YðÌ÷ô¡ÈˆÌwY:Zb “}t°Ûuè»*½u„¾ËêŒFC@ߥ’9„¾« R}öɾA—Mö`ò‚š®ÁÊ·¤¾kÚ1@}׳JÂê»&ÖMBŸ?»õ¹èƒú®E}©Ï]Yh 껬>&F ê+f´€ÆlÜX{I}¥èrA}ÅÖ¥xh@}E¥gI}¦Ní€úJE]8B_iÌÐgf¼ñ}¥kë è+¶)âô=·Y¸Ðg£ úž5Ü{„>« Ší: ¯èkHè³2cx{}UnWB_m,×Hè«r†ôUÕó!ô™XÈd/î Ï*šáA}öÁ^ì«f­!ä9öÕ¥y.Ρ ï#±Ïê—à™êbÕpb_ÝÏûìýÄ+æØ×ì›…QbíB™JR_Sí-R_ËgÔg}`zõ™\f³Å©¯Üô5ºc¶ÿƒqÐgåÓ®ôuS0€ñúÚVxˆúÚf!+RŸX»^àgãâùø™ ðëÉ}½éæûz—% Ü×Í ÷Ü×kûºî°¯O}½ò«áÔ×'Ë\“úL̓5¨Ï6ŸØï€ú¬[?PŸé{°ÁõõEµ±¯ë¡öy‘³ßNêÛÜèƒú¼3f0.V %ö™½cƒo7]ñæûFc=bŸU{»Ð'ÈϾJ Ÿ‹«ùÙwêFŸà¦áåuKð³Ú®× üž×š°ð›€ßÓ‡êð¿çƒ×;Ào¬óü¬80àg¢büN?ßaØ0Á- ÁotZH ~n%ùƒ›ž‡‡sø™}O Àïy±È8?ûJ’­lS•BüfcñH’Ÿ}EÛ‹ü†UxÂ1A~“õ ~Óè-1§+àg5ï Züž‹ä”~¶»/ÀE?óÚð¦ø-“9Wà–Oá  ø›Ú|þ¬vÞ~Áßôj”¿%û=À" ö³bzϨå´Y3ì·Lº…Iýž#¹ìgåõÐ'ØïùÓbös‹"ÇÙÏŽw‚ý¬nÆÅžUKÇ8Ù SqT€Óê2xþž·…†ˆ€¿çr³ ø[.æÂȘC£¼–ðg¢0þÖ²Ç}þÜz‰gßáïiàCø[‹Š@Ÿݛõ‚¿ÕY´™ô·ìÍÜýYyBtqø{nEá÷ügFQ¼ à?»`¡¦à[Ò?’@ŒØí*_¸„wé,ƒÇ¾2nI€·–_ ×å†Då,)A´á‘iè…c10àÉêß’ÿ¼HðÛÛ×¶̽}MÆgzûºVczûkÕÈÛ÷ü:åÈN? ø¯òó–î¾›{ ò_£À\ü§j³â¿*ÿ$ùÏv±owŸVÛÀ¿&k.ñ¯kBük,ã#ü³ç X t2lƒƒèÔ™¹Aø÷ŒŒ ñ¯38Cø÷|Î`&þ –Œþ=+ûÿ„¹ÏÚ…M9ño23Yâ¿^‰,²)ü3 DàßÔV”ü7õÃÿž"øo²høo^I„šœÉÁÞ‚‡ÀøÏï.*¬Æ”[p„šÝ–|ÀÝ 5û`1 ƒÇ$Ð[@T€Ó6t8W sxþ2€q…à0Îá|N€¯ÝÇ€%è€íf¨Ù‡L!à¿Ë Ì/þ»Ú¢süÚ3Hü»ºÞoàŸ÷"þ™“@øwuíÛÁfQ„£ÍùÏN‹qþ3³%œ¬à?÷kƒƒÿ\) F þ»Ìæ‚>Á}w¸ü‡ô/¢^\¾ P`N׳íÀ½ü™½y¾<~—j?þ,ð„>Ÿ€Â: —×·ÿMì7oÕþûM‹gó.Øoší§ö›·êÅýÜP‚.%”ì{ÿr’_( Ày-Dà[Läç-°<ùÍøÆÿFð« #øYè¾z ¿jïã‹üjK´ lª7q$?Û*öA~&uí/ô³]yAú™‰ÐÏ­ /ô+f ÂÈ~¦Z¤;ú™]_ ŸUco/ô»¶<Ç@¿k³x;ÑÏf½|~¦ €úYqx:øý Žððý®¢3$?{uð2ýì…ƒq èg/~^g?[3ñÚ‚ý®&¦ûÙ 9ØÏÖ^l“Á~f»^ìç¯ø0ØïÒ.ìw=4#?àÏÈžãÄž1 ð×1öà@ p*káÏ>†tóüÙ>”>»â˯ø+…rÂ_¹ä•üÙ&süÙ;MÌ ø³  ðgægðgÞLÀŸ­X*Èé’0‰ðw-z`Á~×¢ñ6ØÏöùtìç{ÐaLÁBÉ mûÙ©‚ô‚ýìá"wûY` €¿6™ÃPRì[T øó––pox(þ^*1Ÿë2_À7¾ßõáó;‚;D|—Pć„I|ƒ1$¾²…>£Ä7ð=—p¿<~w:H|òׂø,r>7Ì 2”MÄg&cp‰O‹˜ˆ ”’øä©#ñ5z˜“ø´÷”À“ﮈ¯SPp <çÛãgUôqä{`[{ <~bö›xoÙv‡§ ‡ŸEªÑà›Ú øµ">&añ™Ù”Eâ£Â@Ä×¹WKâÛÄyßHÿ]‡ß“ã:0 ÖñMmùI|“j ßœÄgÞÓ7ô=¯L1„¾Å] oKð è³µ°½ ¯\WüÄW”{ÄgI#_Oû ð4ÀÝgôA/Ü}¥ õ wŸ91ÛËÝgÎQ¼Np÷=ûI¾Np÷y,?È SŽ;“œp÷yJ€—Êóù®Ó™gÐW¶la„>+5ý‚>Ë¡O¨+æCÎD>˜VI|µèjA|æ,/â«M–/ŸõÁRâ{>uñgà^M»‚ã^íZC€{æëåipõ³H@‰Ë¯Ø‡öÌqZ^ž>[çÉi{uëÞ÷lëÙ^ž>û¦âïÙ6›Vºôîƒ÷š+x¯nf÷%ïÙFxAš¼gé àïµÊL²ä½¦sò^k4»’÷LëþöõÙwÛSð^ñ|$¿%îÕ‹Ñ&ĽZû‡ÄÓìOƒ÷jÝ÷ ݉{×pÞàž/t@°€¥jŽ= °T —âž=io‘§µ€s€{†Ÿ< S¨È´g‡PÓi¨TeÃ&í¬Q¿´g1µëåê«£bPÀž û–xÚA nÐ^ÕG›´w´WÍCÚ3éÁxÑ^5µþáé3ÇSä´Wµƒ€½º™V°çýËÑg¯ [öª%:%žÏ£H‰?iÏúÜ/‰gSŠMÒžm$î—§¯5æ® í™éá€=ëä!ì™\î¥òŒðãßÖÛ,¶JÖk‹“õê-:뙹Œ„È Jsà8°ž<(é¼øA Š2X¯)—l°ž»½XÏÎ7¬×Dd½¦²Òd=ÿÐÀõ¬g1ÕõÅz­]’œëµ®»Ö³ÏH£¦3b] ³ïõzM( س•„X½³aöZ™r Æ\“ `½"wX¯›MÖëyj°ÞBþ.¢^ïúDõLëÛ PÏvŽÒyþlޱľ^?±¯ò„}dV%|B¬»¤ž`³®ÚTHM'çGDŸrHäy3VŸÈgk Z€|Ê”!} kŽ|VˆUUX²O õÓÉ÷ÒxÍaõ&ñun| |ƒ™¼|Cû'ßó£Ë1i‰RLÐÒFÞ.ð^˜ëÓÅç&ÆëÕ0l=D “oðž«ç©ð|öÁ ’bPßl´¼3¨oQ†£¨¾»Ê釨>Kj†sETŸ&…¨> :Õ‚–\šÇ8¿° Í$³z‡¥{c†õmºûÖg†ÿñU+ 1_¼Ñ´ä&³hÞ«£èÌÁ{–w¼×®*–CPߢñPA}Ò~“÷,«¶ˆê»å­ðµç«ÀQøš=ƒ@7„õu¬³Šê³h ˨>ªn2ª¯sÞ³ôMãÅ{½0U%y¯­ñöï…¸ æq}C<q}]O0ãúCÁÖ·¤PeXßsï(çDXßlÂÓ˜€é²ö+¬Ïƒ~´dù›}~Ö÷ì±ádXß%xÏMp‚óÞ0o×Á{¶ ð†õ•…ç³ÿ¦]Fa}¢Zð^ÛLL¤°¾‘~ë{|Ö·˜¼gëÞ9ðž-Û°.ùLÌÅð@ë»ôžù,9by)<ç¦ôÄ· 3äø|…ñõÞ>ˆoÉGâsú` ib\_Ê×—_$œúÄ·VH"0±QæFâëŸ0yÂ¥ïyzDòÝ ¡%¡&cúdñy\"ŽÂõk­˜>ºó—– ÀwA|«0!"ú µ^Šè«Ò½3¨¯]K"¨¯2–IA}ëpù9.Yæ©·¸ÓC䀅|KQõD¾µ¥ŸePßb‰"ß.òù,7Ö8ä{+ªÈ·mÉõíˆÏîogŸbúÖ;¦Ïì BÄô5éÊ@|ëy ?ÔÏ‚0_òNOlöòðYú¬û…|[¹¬ˆ|Ë„yGTŸ?N¨@>KÎy½\|+ÁÌ7$Mæ3Õ™v•gq}‡_0ϳg¾ÏÂ8‰Žˆë+·ŽŠ)l3 â\6…}Áõΰ¾FÏb:çËÁ·MFdXß’;a}vÑ'&`)ÃîwX_£¢šÌ··D·`>{ÎæÛ—G`>Såá~†ºs³è Ô‹æ|Åõ™©h†¸>cìôÙ†þÆõIÌMè³]#ñ q}öÌ`ÄõµIâDXœgkü-‘ÏUKp»òYÈf#ã]vhöTdߦϟÌg_“òrðÙoÀ¨=DöæTdŸ-§gdŸÏ§f`bQ_ÌÀ"¶<~ÁKövãÉóy>KÊ=}dI_ïCܹUëL}¶* GLÁ\˜oON2²ÏCÂSqçͰn2ßZ6ù¶’ùvg, ‘Ï^ â[“=Ÿ°RPÛyë]mç¼âà=ó÷@• ÞÛB2ßÎX ;o=z> ç‰ø¶Rk“øö`j1ßnÜõø6}Gj1P?[鯾|ßû—ÿôüáIÔÐð›zL‹ð÷óÿþì”Ge§öó Æ¾]–lÉöGë×o§øËÑÂ"IÏTv®ãZÕp Ŷ*[Ž¡,íó:®J çPh;†RKUí÷¼FyÙp Ŷ*[r¨NÆ2“ìù ¶éY}˜˜ªz„蟒Aí­ÌcñÏz-ó±*KÕ·ç?ŸGðù|«ïº5îóÏë㟖oj(ÍÐ÷'ÂìrÏÎNê¯?z,-¿î:ûpœañX^똱å){q¨³—ÆzØÓé -¯±ÔKc½4"N±ƒzŒ¥^ëè¥×Àywc±å+{q¬³×Ï>?î©ösøŽý×lžy͘_LOÌüèyÈÆ;«Ùïôú–Õì÷ú}f5ûÖïYÍþþÇñG¡ïßÂ_ÿ{vvú‰¯êßü=lM~û5þ³ý,¶Ï±Ÿd>Ž]}õq*¶ìê¯-ÎÑËs¾nì Nƒ4{О–;ìÂkìhqSÜ2Kn·ažÝ¹£¶Uk°5öi]ÛCrJ_"–[¹ü¨êß‹®üçïË·]DõÛi58üòL^ѽLNÛ"û(ØäÙv”y¶Ø.?wxõv³ñv4ø¼wwp· ²£ã†r¾å¸ÂcÅní²lÞfGxöÖRƒd-çPyn­·Ä8f3º}C…LHÛ÷—µ¬Ø!;;Z| ïi}ºŸ¶"WUU;Êáùi°9;y }¨ÙÓçm£6°@gƒ- dñ|7¬‘V†nw÷£À†&6z>Ö²ƒ0M„^ªS¡^¸m—¼VÀÌaÕÝnvx\:d窤ЫºZçi¡ÌÀ”Øckf£0À\6 ¹1Û™…Þ¯-a™¸¦'÷é[žpÄØºéÚdŠ·«1§¶ C.›W£ÏÝÔ:~ MÃìèQ"‹xߌ+6 û›i Ku“¤÷ðA,š½Û4;Qß4þètŠŠL÷9mšƒ!™eº·[:¬0¸™«Ý¬Á ›²ü²ú– ¹„‘§ïIiYôíe)§PpÅ’ˆÛ¹Œ£¥xŽ? …Qª«|º‘'j“Ø,¬ñ=&¯°7m›N3j<“+ZÂtg1sÄ0(e3Ý.õô¡©ÎôöñÚK5&]©ÖÍ|‚ê›·kL»½OHJ‰í½åÿž–ªŠ¢ÓÃø›×m°éõ­ðst›¦lc‡î'§Ë¯MnwCwe³±S¡dòrÓK7Ó*oÏ`Ù-o Óµ»?¸›c/,¾pêf7‹C÷ü÷~_¬›MY?íƒ?£Euo×Äv3Œ5ãÙƒØï ªåûºJ'’Y•Ç ŸŒÇðvS…¦ùLÁû~A?iÞ#›&5¸?¤[0!¥]·Yœ­]^výÑ…‰Ü(õ´H¹iÊ%›¢¡3Êô[¡ŸVªGDéVw×uËâ÷tóX÷º2Ú×Óu‹Ë’‘Ƭ]ݳí"öÍë·"õ­”’}¿=º ¦‡mÛ wΨa“°sM&°ZJ6‡ÉlKDhO®å·Â·÷¡vÓj6Ü#†ñ«±Úu;wÈl¶µ7óf-¯eå~á‰X5¥êw”_ 3ØÚçÛT­qŒUƒ²Yn†kÚ¶Á¾Þ·Ô“¶æÚ×Û³iùQ¶îÙ×ûV*[¯¦d§º™nÆWˆ}ü×ô»êfºy[ íãmqUák²úy¹Üoß0[¡Ÿ æïEi{E+sdÃhly›{SCcßû|Û3Eó¤?Ÿïaå†ÂØä‰…ºµT¬IfA\~*¦Ýpit±>3ÖO½£ÁÏmi{ž·ØÇ5ÊhÿNŒ>[ ‹©Ò=å¶U›C£‹ÂÊ)5;ÓsÆpÞ^Ôʽñq·ì.u;U|ÕbÚž'|xôP÷ËQ9âÑò_³Úxöí6}»êªUSÚ5úøS\]0úå^þ Œè–hÇ©¦« »Õ•p‡UuµêŒ)”ØÒlÚw|~ª•Sj6Íé1ªËt›eñ”T¯¦ä'Ç­ºSܦ9㹩&®þÜøƳì—-¶ãµDf’aiÇüÚL6yÛ¹“R rÇÕ!?ª%üÃÜ,5NbŠA»—újËr1*®ìvÏà0)¬;ªéÙºŸè”k¸ô½c•”Iùþ×qHÃD;VÖùÛ†…O8T+¥´{Ì ~÷ÆÛ$7ÔûÕ–åËNµ¡mª.{´ïØÑU[•‹ÍsckQmY®~*l’«Gvøùý]®– ¦·¸Ã¾£«VNiT<"ÑÇëYù³sh‘¾d¸Ä:Z†oö™û²P-hcϸœ˜§Û_lž;êU[˜/;Ó†¯T k!{íϦi{Ã_ý„?_^ðçç;௅ "ù[Þÿ¹2äÅþšü×ã~€ÿÀåà¿(¨uà~òÿ`è:ðP™ø‡øÖÿF,£‰¡³?èÕ~úh&ýíB°¤¿-I;´$ BfÑßF’¤¿uÒßFz®¤?>JI¬'øÛø:&ýmÄ$ˆþ6ôF¢?kñýšèÏZ|%ú3êõ)ˆþ¬Åß*ÑŸ{^¿ø3 v‡©àÏZüö þ Œý™üY‹/R¢?÷JÛ¬„‹ËªðÏÚÏEü3|öÅDøç-~ñÏ|-î6þYKœø·TÃ’øg€pUÿ–4åÄ¿u³¬ ñÏ8<6Ä¿¥,Ä?ë]@Æêá×#ýYËõ¦?IÜE¶9ø:áïbø¬àO §It‚¿ Ú5ÁßÕ°kü©8ºàÏŠ¸CþLjGø»è¨ü™L&°’ðwáNø»˜ã@ð§f‚¿káÞþ,‰Ø×Á~×™Ä~–Þç)ö»¶ª‚ý.fÁû]Ü ŠýÊÅâ `¿ÂšØ¯0§¡Ø¯0þKìWXþVìWP×@ì§&±_a@±_QA²Ÿå@ Ø/"þúÁ…….X⟵„„À—3 ÄFøg-ÈÞüÛA¤?8‘þŽÐß10èo»í€?Wæ¼àφA¬!àÏZê þ¬jÐ`?³ï0JÀŸíÕ/Š AC¡fÏ?á»R5Lúóð×Ö€€›À?KΜÀ?7}%ýÙßLøôg-“¹Ôü¾ë¢7ôçz$F„;þYrñÎkÇ¿­ŒÄ¿ ·9ØÏ,Op)ƒýìûÅ~Ö‚ì``?; ù„ýlá)/ô³–hòó¥)¨ŽÎÓÖ‰l ?“<Ä"ù¹Ñ+ŽúYKÀÑÏF¥ÐϺ` ŸYÊâ³GôséVôûYŸx È~Ö×ôÛá>ÐÏZâúˆ~Ö$OôÛš,²ŸÕè‹ß‰ìçu£O°_·ÿàöó–ýâï C ß–‡è·ôó‰ÇQ@¿0~ú¹½/tï@¿nº¶XûÀ~Þ Á~~PLœìg-7HïŠo7¡ˆìçfÃv²Ÿ›ãÜŽ~Ý’$ÇwèçÇ쀭`¿n7mÅý|›ób?¿±m`?7YØ9ûy—Ø‘“ý6ÓðˆýL°vÅ©‚ý¢O ìç}b÷öó–û„?·…ÆÉ>N‹–€?ïÓº@ÖT tëè8°«  °›JdDËC€Ý¨+¸3Ð[æI€ÝD‚#(1Ð[‚§@€~TÐÐ ³5 ,Ð ³¾$v‰yˆ€1ŽOØMÔ7ØMéä–C"`´|%zCüVA€Þà |Z𓟖›ô£bæ ÀØÏ ì›™_@€>p.A€ÞeDK`\pð^ […G_`©H½Ï:0ŒÔvò?©í Àeó=)ðÆû•xƒm’ïŸ0Qà}‡Ù$)ðFáQ oPm`Q d|NöWŒA ô ¬Ÿ˜h-w´­Å9Z¸iZ‹ïË…>Žc1$â@û€õ‘­ÅO%ô>// /ÿNä@[–}_!ÜL°B´uÎজQ h‹˜¯AwZ¹ã h-~9"AÛ%øs(´„O‹$èHœàä¬pǦð鬰,§°!³Qú+,KélXÖÒØ žM? ÃgÒØr‘ŽÀŒ™ŽÀU:k0Tú;rD¦°#gVú{–Ó h¼à§–°ÑÕn@FëÉ PqpàVª¹;ƒªåìÌ 7àÓg¾@Ðw†A˜r2+lº¹KM7 ·p"AåU 6F:ÈH%¶PPeÄ‚Ú5‰óZŠp;Y°1›X°31°XP[± êU‰;3"ˆ;óv‰;ã…Å‚¦  vf& 6z*ƒºˆ„ÁNו`°3 ¨`ÐtÐÑ|žíëí| ƒ“úƒ–<ü~„Af½ipÒß%´{|Hœ¬Ó+œYg48™šV4h!kч48ºª9ƒ,  ÁÁ  f¼ öëØwK8¸*4ÆÂÁÕY:—8¸‹“==âAÓ‘Çõ×T "xp1Ñ«€ðù* R‚@8•@¨L´B«dõuòàTØ;pf¾<áPJá¤Ç˜H˜ÉE‰„·ðèLU<‘ðfå@!ááÜ@›)£I„w–~Z°ÔÕp^Uig… ãî*-2¨FÒ¤Â-Ù>°ð¹]õåô™h!NÆ µòÂÂ[ž;zÍCý•Thw ŽF:/z¢ä¼L%àÅ×^Á‹ ›Waá`­kaáͬÂB/Ž".*1„…´¶&Z²©ÀKbá¦0Ÿ\¸HÚ⛹"ä¬L[J.¼eq š8^{q¡P‰ 7KLŠ U C9 -r ^|R†V93rÍÞ #n´îN~#òŠ —Ü„t ×§S°ÂXN0¼jä¬ÜíË#XK|Ä“ 7JYˆ oVNš– …¦˜o$¡Ð"’ëéô'0G—`A„Âl …¤ø‚B/; ¼â¾Ìp- ½|hœPhn÷'Ú†,@ˆPhy’¼ …wÇ[Phé;À PèŦâ(@á-¤'ÚS8€…7“ƒ =XÀ%¨Ð”Ƌ ÷7 ½X|ô ZhV Ð³™ùÕ íÜ`7@¡ÉK‚è…7íÇ‚B«ÝtŸnAÿšÐ oäçÞL¿"&´L`ñÓ‘ í‰?‘ÀíàÀiߥ^þ ˆ7ùÀ@TôH ìña90ß°tÞØO¤3о—l´˜(gà=ã[™Þ@{¸ÞÞ@û©ÞÞÀK|zoÄò¥7ðÆÛ”ˆÔÇéäÀé¼lxˆA'<{)eŸƒBjpˆA±YM5hÈ'1(²èbPDxbPÝ&VØ^ DQ…ƒw,ª¢@¦}9(0ìn - ,É€ µ4„&°Íx ’;Rï%v:&v”ÙH´¯·ˆiMìõø©¨8(››ƒw| „=11p@¡™Ø™ØEØqK d>`aà äH8*ŒöÂÀÁúÂÀÁêÂÀÁâ:Â@•¸Ò0™he'ÞÁA×£0p°„"1Ðʺ„SNµKbà`îaàBTzP&¸NÖ"J=(óÁ g|„9(C E“ÅÑRÊüš)e4è)…j¸˜+7å ,[šrP¹Ik|º¾‡”É%-ø=E»Õ$e¥Ý”ƒRK•rPìÜSºa`ÞLirÊAcK›rPÖÚL9(üá‡"”e³SJŒÒk-A(2€Jʼ„ ŸSÊ3§ ”%}%½èFHAèÏ"õ n©EfÉA­‚ÓÊÄî¡©€ä jJª¬q„6†MA(}¥)¥S‚Ъ:ÀÒ„2“4¡}ür Ee³ %¡‹ Þ¨•׊Pù'SªLÒ’„®Ìu»K ör šyŒI€–ÿuàÕ^¨5³f€$¡™˜ŠÐδT„v~K¤í|ë¤xðSŠã„NæAþ Ö5“ tàK"þ3oE¨HÉi0„Ö5‘ø÷|Zb! t1P[‚PKªþ„.¦j“ tá– t‰)]LÜAú»•å€ôgºRh;ƒþüjÂãGA¨©ç¢ éo_ ;ÑŸRÅ‹þT‡ôwßÔ(“þ¬OØH÷Më‡èï¦èZô·iÌý-–"þÝÊ£Mü{¦þ%ö×Q€ä L+ô³4±å­eœD¿%ýv(GD~7ì’ 7r„$üÝPʦ”%Rz!ãxÊAí›NBêA â©-Î=êA¯I²“ µRj¯·&´ÀÔœ¢Pê}! ¥$E¡—.†¢PVMQh MEjB/ð@jB-[B 5¡6ª…–( ‘šÐ ÅPRZ`ÊLMèµãÁOMhAQãÔ„^ô¸QzA’—šÐµRzÝoöóÛy¿Ùo¢TJBËúå@¿a…5—+Eh¡wWŠP®†©-p…$û=# d¿{ÿòF¿Ž]ÞHèöÂÀºß¢P„e¢P¼6gD`lGSŠUñ…"ä…N¦(›FˆBáÞ:D¡ØHÛÃ+«‰ ˆ7ñÅ€Þçtº *]Ꙥ+ðÂR‘®À«ÇÓx!ËOº¯ýè²³3"Є_Žr$NLW`Á®@VW £ûñm; I¨ÒÆë7¾=ÔˆÇá Àعˆ|B/ ÀKG ¦èÄ•ˆ­×A€X’Dç$ÀícàÀ:8‘!- pDN¿À‰¤) €Vm#Œ¨3àdÚYàdŠSàdX…p±Ž«ÐÞ~À‚ÀÅDÿÀ- %n¦J²Œºøos¯JþS63ñß¾éâ#ÿÉà-þ»7œÉ,Ó%þ3+t0"øÏSC¾%¡7‹ o¤é%ÿV„Ÿ’üw+W&ù›˜ƒÿ<÷ãé4ÏügTûòß­J(ä¿›!0Ä¿Œ;#þyµ¹8SàŸ§Û ®”RÄ?OôrÊð+ü³]Wø‚ÉNO¯p@·ë¿$¡f§\¯p@–xnÉž»óèïÜË hÛýõâ?Or4w½x@Øi&4oñKjÌÞF9o–ÚÅ€÷€•P+l,ª"ì``§ã& p¶Íüi$Àª¬|$À­4$@•¹%U> v%ê$vUf;¢‘wH  ðÚ*º ´ïå;*°°D鈔[ ÀJ§›°Våø…I€Fc̆XXPðDÀùFÀƼœB@K±ô’†n"¿°b„€•È"Tñ ùŸICm£°ŒÃM'à 9R:¾A¢@Û¾€¿ƒ(°S! l|EF@Áf¤Àíqbà@L¢(Ð$ÑB üº‰'óC“;]ÿòZ YDmèbµ Q`cÊ@ ]½?|€ÿ'Ú]ÿ:8Ðå/m¨]y¸¨ ÝÈÚÐ{0¼P^@nåôìfo/`džêðîW\ ¯ ˆµ£p Ã\z=WÚ‰ð ÒH?Œ<€fÀ 7§<€öÞ²ÐûƒÝ£s–°SD+`EäÌá$פEÓSzî’@Å·Њ<ÄQô^¨f–À±rH`¯ û£°NŽ@[©âÞÈØøkÓhwë £.t!´'u¡›~×t^±›’ Ðän!/¥ ðÂÞ8]€e’&é,3¸ZØ€) Ýãè?–oöŽ4oÕîO;Òõ1ÚÊdÄg¾¶NyTvúÑa?ŸæíÛe©áÌ‚öqŠ¿-™­ê€§¡Ôp Ŷ*[r¨n ­÷}L› ÇPlË¡²åÊVHFKz'6œC¡íJ-ÿì4o–5sÙ þQš·ký~>¶ÈóVÏÜmŸ ÛžÞëGyÞîÎZ®¥ÄE?x$"ÿô‘sëÏåðZág.8ŒsdpÃ@g7Ž”½8Ô+ÇÊ nëÈ঱ÔKcÙà8VfpãXG7¥^ëÌÇ÷ 3¸a¬3ƒ›^ZõâXÿHž·êéJ,æñyÞÆßÊóö-¯ßó¼ýN¯oyÞ~¯ßgž·g|çyûû_Ç}…¾ ýýÚÙé'>«¿þñtiu‡Qî‡éÒ–Ò¥-¥K{¥1;þù/?ÈhÆ„i­ü¿N˜ö× ¿ã_sÿ aÚÓø/úW$L[WÝœÚÓø-aÚÓöïú׿þ M ÓêßN˜V_jòŒ÷Í„¹(ïßž‰?Ãá›Ùü#ö…Çš™|÷øÊiÍ OÜg‚´få.IJ£íÜJXP·š%—(7lªÃ[†Ã†ÛT{´ÀOŸ†– x½ONlƒ~qPrщ•äAƒç ¿ÅÀk(ÎɃñgt@àÕÕ\ù¤A+ä ºÆ¿ÈÄA?¢œ8èò£x(€ƒn¢Z1È€è¢b)"ÆÅEŸ…°ëŠ`xâ`gtiØdA" šÅ‚vH B´õ8! Z¡Ø +²`#Ê™ù7a°!#Ñ ÃñuÂ`Z ]0x*ƒü@0Xã( ¶0Xè« ¾<‚^Y @`ºåD‚Ã’,©I‚ ì“¿°"ÁVbÕ$ØèÝ ²ÐW’`+ø ‹¬I‚.&=A0˜¹×ÈÆÖ1 9°UºûÀM¾=r`‹lð‰ša`¹í&âÀVðÅ6d÷Od5žä@F%6$EH´q¢…ØP#9I'Å­BÉ ™¿’·&â@$°N ¤–71°…¾EÈg")ÏDR >s í¢ûÈ]¯І.dÀ†±dÀŠÈÂdÀJW™°""!° €Ö%¼\D@k‰çšh…Šh}Ö‹ýÜÑ (S3ÐO`´–p—’7óø ½ÒÅ×Á€Ö%¦@ô"/´ø÷À€›±ßb@k“ h-ñ;]zvz£O Pô¿Ãoô–8¨šñB@[gBÚ@ôÿñˆ€’Æ YD˜ @/£€U‹!«!õ1n=©_›¤¾ ÕxE}æ– Z#õ]ÈÿŸÔ—}H}Ü¢¾«C_)êc|¯¨ïB€YRßEK½¨ï¢ÈPÔw!ËÍ! E­ÑCŠÒJ‡$TÞBIB!|õqéHê³Ð¥8)BQßñ¥mž°ïŠl>¢>;Q#A(q<¡ ®Ë„†šäЃÂn•àgÅ\Þzвé*$øþx?fR<È<&ò³-uŒLòƒì'Á¯"ed‚„ü3ÁåQîƒD/± ìÛpá ûèêLîƒ"ÑÏèý*ÇD?îš“ýP$í`?ºgÅ~æëz«AYÛä`¿E‘¦ØòE±ŸÙ­ä䤺Rì7ßìW!d:ü€7ž£d¿†›“ì‡Õð`¿ø¢è×âgIò£s;É>ß$¿I§ŸÈo’E~›R‘ßf’,í/7`¿È¯‡íýðöOöëMúP°Ÿy Èè¤_)½€ðÀ^@þÞ§0øKìgé¿~{;ã¥K' ‰7€°ÇN@$w?œ€ƒH&' ²'ü Ò¾àÏŠ‹¼€HŒ’ð7pÅ‚¿Ay…àÏò—FÂßb²ß„½;ÙÏ¢cà Gö›«‰Øo6j?É~5“ý&'%ö›“œIö›Hœ>À#ŒØoÞt.’ý,1ÈÛhýô ž’# ŒðÇ⢿Åýè•7“þ’º%þ­‰=’ðùº’ÿ·ªâ¿µ?ùo›U+áoá·Kø[nÁ N'ü-*ý‹x@ø[¨ˆœð·&’ô÷ \¹GúÛ=”¤?fJüÛ“0ü“ÀVøÇ¨×Ä¿"X‰7ª|&þIË+ü³¬^áZ$þÝ0Ã$ÿÝå©ä¿ËEòßBÉw§˜“üwciMþ»IÁ7J]&ÿY-• =º¯øö¦ðº8=€ãô^¨ÇšÀ«²…@Û‘…ßÀ †™Ä¿›0/àÕˆ`ôZ.ú·ðЬ@ò^X ÒxÑ!. ¡{ô¡ÉSÒx!ciºK£Ï2]€ëëUº êÕ¤ÐBÃâ(ú™¤ }€,žwø‘ùûð"—FúÍ-ô¾¿é¤VW>@VµK`……L>ÀÚ)Õ¤¼tXÌ ÷¦ °ðŠå¬tËØ(— °u:é¤è[.@‹ô Ü£ °!wºÒФ °! ²\€­sº¿Bò¢DÌáÄ,€ƒ?§œ€/ wÚƒóˆä5ÃèRŠÂ¯àÀ€8©BÜ)© ¥Ÿ)U¡ Ë\ªB7‘ªPV HUè]躣*ônðkHzÏOU轨I¥*ô¦$a°À§% »ÄÁ‚ÈRx° Ò}% Š…Ä‚Ïc³ $—H ÃúÒÈ=üé/U¨í™cšbÁÆX± lõbÁ† oÉ‚V-€A$J„”“ hI\¿NÈ”—h˜ãR‚,w‘ 8ë'NX7m¡¿Ip£‚†ŸATN¼aŒNÜ »7qàM9Ð#³â¨Å\‘=´º†åí¼cþH‚7Ÿ|¢ +‰^.@OüŠ ¼Cô tmÊ×Áž 8Úw8 ô Ñg3û–BÁw“"蟻-pàšÂ@;¨½0ÐÒœÄA ´>ñ®ï*³Â@k‰}Œ Ÿ2! rÅ€–Ù62 ±RmË|½𖤎x+N™h}æ‹=Ä)Hh;m÷-]Op+(0"‘N ô$šqg‚½K¸÷@LßP GÓÔ=\)H,(ÐcNŒð  7‡@vŸèá6A|Á€O¯`@“ „z¼Ð<• ãtèQFó„ÀqMJ^ÞP ôjòå8)çzÔ8• žq´@ŸU|4qß`Pà¸èûúÝB„b@à°4JP^zT=c=¸‹€N>pØ?@Þ'N |îPà¸*6ý.‡w/ ÐãŠâY–{g ô ±z AŸ;Z°OzhÏuzÇeѺ'>Gmj:#ö(º>Ýl Œ–Sú´à!È À :!Ð[b£ þ߸ä€@sŠ‘¸¹›WTà®ï¨@¿ý‚zìâȆ–‹»S…Þ7¥¡ ´ˆ¤€f†Z4T;½€£@T¯°@ 1ÂK…%Ra…EX(³QX`±bo ´ÉõS: ëð*.ÐòYÆÀIc:QV2Ðû…€‘ºß17r0fLàBŒ \TFLà–3A7€ ¼ÕÈ Àr‘èxc-É @~¦X¢p­ĘÀR8iÅndóÌ ÀÞ[Æ–‹Ï9ƒ-Çh\‚KAܲ‚ ³ ((ÐνN|~I‰KhQbãTz FŽ @;\wˆ ´-䈌 ,òÕ2*°p9¢é,cT`yñŸÏ X!åB …z ¶¸F>ßoœšQö£†N”QVÌ$pŠQe¬è‰^Êh‘™Aɰ@{—Ç+,ð'ý²P!4c¤eLà„šD1W¶ (ÐZ®ÿüÍݯ @‹Ô[¯ @OŒ~⟯òûðÿù*ÕOü…µ«xÝõ1æ©qh/ÇýÆ?Kööõʘ6Zg$Y$éYezêbåb3õÙG§<*;ý谟Ϙöí²Ôp$û<Å_Ž–L(6\º{\«ΡÐv ¥–j>‡ä8ñ×1ˆ7äø3_¶ ã®±á„m9N¶ü³³¤ SãÙMý;YÒ¾e3‹,iíÌ|ö™î쟒%íÁ¬‘Ä\«~ð,ö†8Qöá8™ÿŒùÏ8RöâPg/¥ügëȦ±ÔKc½4–òŸi¬#ÿ™ÆR/uôÒ³¯ügë̦U½8Ö?’%ÍÖ‘î5Ã~%mý­,iß~ïfIû^ß²¤ý^¿Ï,i?~ÊÞYÒþþñG_žïÀ_ÿ#vvú‰Oé?%møºsÿ0KÚÜÌ’öüëßô¯¿™%íùÿÿ]ÿb–´ÒŽÿý³YÒÞgúë†ÿ벤5^ÿßçK{®œÁÖ;ÈxÕ&~E§úñðx[o¸Àž ‚­Y¶óiA°õÆk<b‹`ë4Í£_¶Þ(Å5ºˆ`ë ÙÜèÁÖ– ÍÇé-‚­ÍpÃD!¢°ÙÞÞ2l•yFŸŒµ.±;ö|ŒµFå¹Ñ7c­Qáéia¬5ŒÖ£ßa\óJˆ~Åãb¬56}cD˜pȇ¢O ãšÙ_Ý35Fc¬5TÙctÆZ—Ðö1k Ož=)C­QôkŒÅPë?ÆÎPëGí µŽ™;C­Ý'7æ¥PkwFZ—à·çÔjÝ¢OËPë+Z:C­¡zöÌŒ¶†²jÌ™áÖWôY ·†œqÌ}„[GŸ ™EA¾1o†[G@ÅX£­‘Uè¹7TY #þXÒ—øÿ" Ty6ôY ÓXƒÁÖaûk2Öº…yp¬Å`kxÀÆÚ ¶î¼” •EE¯aÑûnoðŸöm¿ã.õéÑàׂH—ÇøÍ4Ê…¨nç¬á2‰hˆÂ/`ŽÈ¿ f€®Ðñ—8õ‚Æ" áÖ²}}4¤¼Þ¡txu‡hˆ'ÄC6³lêëñµ~Z °Gµw)°G‰Y/ ìa’›µPaÇ—dÖJ…=òEÎÚ ±°£¼¡Saj¾³(,²eBdÑá`ŸuAdÑZ?-anÁ©vµ!²è˜™õ†È¢_,–t…ÈÂ|V­@dÑ |¶AYt„¤ÌÖ ²°";ÞБÖ!™Ïg ¼f›!±èˆO˜mAbÑá}š¶<_8‘Œ¦-Ïþù¶Òq17$Q³_XôH‡8{¢7Ն¢C¾<{ƒÂÂ^d¿5½CaÁ ³(,:^ÎÙ'eg_PXt$“öN‹i‹³¿;T°Óç‚rCQIÊçõˆ0È(PØwDêMKÞ‘‚2~¹Ñ °ï7‹Zu(ì;ÔsŒÈloj1w½ÌgÕŒ/¸´–…ýˆ|Z­.ÿ„È¢§­Îþ ,Ìq‡ÂÞn‘2/(ìÒ²L[ž+Ê!ùÇ÷YU¡°/Ÿ³AaOò™³CaÿM<s„Â~µ0öN+×åßðïò´r]þ ‹}ö+Ü¡ÓÊuù7œÙ.缡°ÎäÆi«sA‰øRØêìßp–k˜«BaoÙ ¢OƒÂ~a}›«Ca¿P-u®…ýŠusZÅ.ÿ„o¤f™V±‹J¦8Ó‚Â~Ã97‘}(ܪqî ûTÓVè R«ø Øý*M2m®¨úo•- Ù6ãyëâþYßN> wŠÛîI<×G-hìo„ÖNSoùWü†GyÚ96ºDà ý Uáô<›P;•h)Ùß(M>m™ö83ñN[¦+ÔNèãvæ ùݱä’5üäVÄó&^ˆê™V'Óó&>[Üì;j“p;-_¢çM¤zÞqa.:²—íò´‰ävëŠt»‘fÂê@)ä%\WÈY£¼lõ–Þ¿]p5ëŠ×Ò54þÞ/÷$Ax Ï¢ÀT‹?oT—ê늚{™a]á ÷ÿå–Ó£¼Á ‰]‚àF$B‚ ò½‚¬íœ h{ÑètDø:8ÐÐužhè JôÌfq@Ð`¶`Í7}E€ µ``€ ámð@Ð@p A/xÿ"Ak‰Ë! :û©H‚Ö7G$x!)‚HИ8ž’ g÷gG$xaÛ’$x!*:Ið*@4’ #¾’cŒÀ@Æ¢%^@$ä&9ð‚ò?Aðº“äÀkr`rà…j˜É’/b«@ФK_'–B<# 5“ ²S‰éþK,õ“ òC% TUL,±L,|£H‚Û“$Á‚JGI‚Š´DÁ¯W¢`ANöDÁ‚ì^‰‚–(=Zˆ‚aµ‰‚õ .¬Ð' 2½z¢`½ÈZDÁŠ$&BÁŠÅ Q°ró&„½ I°Â ’$hE I°âU V” N¬Èÿ•(˜}ˆ‚¹Z+Rž' V(/’aˆH¬¨P(X‘£;QÐ .ëÉ+*% R 4'sD¬o¤É#9°†<31©™³!9°BÌtp gÉŒò>8D'd²äÀÏqr å‚Ú©>8°€uĈSO l¨Z™h1LÁkÁ†¥V Ø’ ذ>'¶ˆ5Klg"R•È¢† ‚-â½’Yí/9QCÉf½„#¶Å>äÀ¹Ur`[ÄRçÀ†äVÉ ¹ “™ðàÀ‚[“x-’¡?88Y¬¿Ä0ÄÀ;ϤÀŽà¤ÀkUb`GÍÏÄÀŽlÂ@ñ°0°³³0°#G[b`‡r)1ÐD¬>Ma`‚Á¢@=L d‚ă ÐLh}ãjˆ,œ›8QE%1p’8…yª'Ÿa ‹9&Nž„Eú’ÂUÄ Ù]’çÍS‘©éI´£Þ¸Pä09Ðd9o´ °¯]øàn|(„vo¿N |bXBà†× !psQ" &: 2#nDa%2EqB`T+=!pÓÞ´ƒâù#ZKÁ(•z¸?ApWý&VÔáI¬›H¬7$È”jI‚¥±%‘‘ ƒe|:më‡ Æ/¯`<&éDÐÃ+¨‘å\äCy ž§[0è*ý‚3 ćcpüò¦ÁŠÝDúa=ü‚Q(a°¢lÌá,ñ<ŠmØ83aP]À‚ÉÑ’ëõé´Ç1úÈ-Øcx¸Û' 2¡Öá,¿¼Q°EöŸÃ)X¾9!x>Hð&½Š‘Pâ A„„$ rC’$8±MŒ¤± b1:H0þ<0£Ò#ˆ8»Ã#ˆœû‡GêƒÃ#H“jzQÞéðvìÃÒ%X‰Šr :îäDŠýÃ%Xèî“Kð¨&B²yp TÆ/ŒÅ¨8þFÁ -¢`ÇáDf’Ã#¸èG”KY p¸$ Â<{  woé$~' "2ñ@Á_ÃDA˜W„ˆâ@ÁB O² ¼ybA=Ò)ˆ%ñåÄÕü §à…§)að¦ÇO0¡8‡Sð¢N0HZÂà¦÷N0Yσˆù{Á HT0ˆÌ„AÚaž:`pëN§à׋'~ÌdÁI¿¡X)v„±4a°£ÖÆ‹Áu¢ÁŠy' ’èAƒñš‹±l4XñP$ Ò@4x“ýDƒž¤Ah?„ƒQ¹‰ƒ…é'ýr‰ƒ”!$N¼¯ÂÁõǃ߼‚¶Û…ŒÂÁJŽ"ôæÀAúØ„ƒ#4N¢Á±ÃårÐ`äI”.¤S0-‡OÎøô "$òð nXŸ7yQ08ðiM,Ÿ0È×L4¸.ºIƒ“¿8iprÁ N>Ç¢Á‰ˆ­¤Á ‘SÒàDtyÒà á¨`ðá¨0 Ih .º#ƒO›`pc¡O\”‡ˆtvãCÒà‚ !ipAý•48w-“Ÿ»sµ‘'$ NÄ û x;ò²$v¤}K·às“ppÿ/îÞggsÉúÛû*rY½øÒ"Å¿7`o Ø@]€1‹7i»ñsÿVDœs‚zÞœª¬v÷._&E‰’Š?žAîãrà ´:â Eë〃¾™c´G?ƒö.yM‡¼tDø¢ÿ0kÚ¡ú~³/„!ã@@„tØ |€€%‰€5€0<8¨’­šb@ìz0à"’Ë„“L Xä.%–X…I´ùÿK ô*/W(‚"=·Ú˪m¤=°©²Ÿ©6$=ËÛ‡;Wê…JhêØõÔC½’h>»à3é*¡hºX”HläEꊟ“ X;¥= ‚ƒt(ApÀå—‚ –ºAžC\ß?b7¬Š¡rk—Ô¹iLꦋÖQ¼‘46õÀ›aƒ”)¯$ ÞÈm‘,xßô¡îLÅüVol¶›(xc 5QðÆF‰‚w§Ç(HkV¢àð#L¢Wê7ö2=Âá9â%W2Npáþeœ ¼îGœàb¨žAMŠàDˆo*‚˜ÁŠà¢óS’ ¤„Á†ï÷¡ b>‘]çä*y «£8ÁMÒ# 6ÚDƒSvÑ`“ë”4(•F4ظ LlôŠÍXÂÁvq„ƒ G6zŃ«æâÁÆyŸ€°!WcaÃÏ>°ÑÐ# lå3RÐTà€°áÇ' lØ0°aká†äC/Y0Ž*bNLh—üíDB;(H“HØ°Ãø)HœÐbè¢a"aÃ'üˆ„#8j¤@A¢'Ú—üÛ „LáãTœ —è3P°1–P‘‚´"J¼¡X¥(H‡pŠ‚‘ÝôÐ)ae  ]^(ˆœÓ¯HÁú6l="û§(Øb•¢ 9-EAäW?"éôC¤ ’G¢ a #Ë'Þ´NžÑû#R©¢ßª``›TÁŽ™ý© ö¤ *âPª ’²ª`,v¢àÆbDA.¥(¸(*R?S µçxXDãTòˆnÐizDž¦€°5À‰€PÝLQp‚ÕÓ#:âç!""œÑù¡ ò¥vÞ‹Œ¼©$*R£RZDiY•E”kRbÂIÞK‹hg8¡,¢xXD!»‘ •ê”18dAÚáSDÚ´C\ø]¥.¨0@Bá€Cèå}aá$v§IôþÄBËÖáW“&Qä`™D#ô3M¢›òM¢RïdEjèÄBE2 7íiE2¸Ã$ÚéP%nf—(’k.ÑMï¦\¢‹@§XAEÆ ^jÎXÁ«3±‚Ðf¬àw† r­÷,lXá‚H‰p„ "ùB† Ž˜á‚=€8£;ÈŒœ T¹D¹¾•.ÑÒbÚpdS›ó†ª„d>»Û0säb3-ÚG¥<*+ýì°_Ϧ¶,›ô½ó*8±,seI&[–¿/B Ñ ΦPv4¥’lêys6¸ÝfÁÑ˲©,9š²Ï$(½ ΦPv4¥’vfµé¹A÷;³Úg¶ªŸýÓ èž÷oãWë¶þÛþ…ºÍv’¸_YØ>“lýJB¶//øœö¹;scýäm¶¨žWÊ6´r$Z‹fÎV”ÜÑNƒ_cab:mýyb£Œfñ®‘ö>Mñ)$€‹ØšµÆx?mxEà½ýis4wk,¬mOß ‹È‘0Âv_¹agòõÍi{¢4lǹv‹:[—+(ÙHÐ {Ýsób…ÎJâÚ,}¿»5‚ç:ˆ%:+‰*+Vè|µÜ v,Ðy¶:»âu]¾@çÛ J,ÐY‰£Êº*½ˆ[–úFŽ;П' t¸Ó£dc¯KdéZW_±×%¤ïuX óìQeÆ­§_q9+è<ß@ó’ tÊ@°Ê t^â-—rcƒ“ëZ–T<ö7Á*Æ*±…¶—Ä—F³‚¬Ÿ’ýMnî–¶v"¾mÅòœ•¬¨ã;h„—)νb}N¹ýVÙ±>ç"Ô+–ç<‚ßPûù^-Jü-y~±i‚ƒ»dckúeßæÊsû½ò/pÇûÃuo&NWìn¾Š¿âpB¹s-FÏ4±£$F ³,W)pT<ßâÒ»Ùq»ìÓ̽Šã®»¹¿ å(™Ü&»Å2Ír#7´ÎçÚtk`ʱl…¤õó\¶Öv»Ž_o?†pҸ˱)XÄßÜ&;ò'>çá.ÙX~æÜ%οe_ç ÝŒa¾Îa¶C ÚµwÉî±~¼öæ6Ù˜íìëâ>Ùy÷U¸Oöð?+7Ɇ¤º}ïôÑijÛ~_–Âu6ÉߣÑÎ=²‘„qÛn_ÊñŽ’ÉM²³íã\`^ÄÕì¦}Š}€ÚåŠU9ýï‚E¹ VÚméý¼‹q½åƢ܅,¬Ûvûð.úX½m·¯‰3ù ºm¡e! NÜ*Ûîká\ÑÛî+r쯸íë ùŒ¯è¶¯3r³v½`ÖxJâškYãB¨Å3Ï ³Óëìzì‘Un˜5.¬PnÛñ+’èb£çm[~M´3âTf sÁm[~!·ÏŒfÌæSò^Õ ³Æ…Ú}_0kè(û>W¸4ãéÝf+>&û¶>”óÜ÷½1|Ç·cßO:ü‹ñæØ–_þÅxÛl˯I\”ÌŽ|Çka;~môrFÉnÇÿ·Ø‡=Î%±;£L‡Û¾ÌÖEWüw»/8íà}J6œvØùn·¶à´Ãbýn}ÂiwÅ€¹m˯àgŸ”lÛò‹¹“®(YMÉ“®hyßHž„4Û¾ÍW9¯Ç¾ÍålØ>ÍLž? û8ûøÍìqOɆÓ›tˆ»uÉ¿š|í€óÍØþèà?Lq“ÿn¦œüþ¦ä?Æ$ÿÁsðÃY’ÿ+pð>2ÿ!¥çÁ +íÉ\Oþkˆ·Iþë¼ñb„ÈøÂüG„Mäêw" Óò%FŠŽƒ;nh ’Ÿ8U”8p½I€ƒÜ(ð_%b»¦dÀ»§pÁ’‘ ¸'øœ ¸ô’ ¸ æ%2Ǻ„ ¸&‰” ¸&9‘ ¸`¸I|JbJ+|Jv@ÐJ|n$\Ø>!pagÕ„Àµk„@l{˜¸Ù›˜׊«„ÀÛUB`Ü=!àÂÖP‰€¡‹ŸH‰K¸0°&†à…€Øm<ëI€aª9 0¬B'.äN´’o/$z$^1}ND$áA€\’H¼H’D@lhx R_Å€Ê?#é€ð¡»ÒˆôÜÐ$@ä};«I€ˆi?PuH€ 81X"õ @$æúzÈ·Âò›ˆ­è=+ŽZIüÄH€þõ"@„‰ç®èá_/ô:s@@_‹ñ $úBK ÐOò½e¿B‡@ûs¿ ЛC~H  Ðp¢ Ð))˜è Cq(P[:ˆ}Ù'èkAb @_° .ú*¸00ÐW‚¢e` ×‰v熚* ôKŽ*À@;(^bàÜ ôÕ"?Šè§ Ê ôfüî}m(` èKLQh%±„H ôE§oúúQ”€µ Eô@½oú S4 ô˜;?ˆ ˜ Jd@/ âz¼_€X0 B¾tX ô’z3Ax @?U((0—ÀH[øí€@_—úv0 –ÀÄ€jWè©Q}ÞH Ôõ ½N”zHâ‹}GŸf“}å*¨¨@Fq ×‰ úŠ\p_p äB@ЪÄÕ}i- 87>µAŒ£‚“Û =B2J‚~®€<€ o” ô³Ç³„ è-G @Ðÿ¾%N[‹µf'ôu½hèWŒ´’öâ@_é V ô‹‰*à@_BŒS‰¯³6'3ŠH¸!zîoúbÔƶ'â@¿à(ÂÑ|p æb³íAo$@K$ˆØÖ$ÁKPG´’¨C¼ŠJ¶¢fãé Õo¡ ž% ê† ¯H”$ˆõÌÁ+ò%^±q¨0ð‚Ñ61k«‰¾á‰ ÎMùuÃAùr¯‰—GZˆmµª_çn>X;!úQ€}Á%úz†Ó9Ð"‚úÀvT}逞Þ+¨h%÷‹’vi)ÀÖ¶–"@}i)bƹÆÔRÄŽ’É,Î ùóÖB#û¥*S¨˜Mq ‡º½8ÐS¼@ÐwŠ:AÏY’@ÐK^ h%# o0“3¸@ ¨ˆB çY{ ·s‚ ÇȽÄ@?è‚ LGµKq1Q$.&™'r$q çf{iF%‹©œ)ôôÊþU&Zø*“= ä%*ÄDè—êƒY¿ ÐO¨]ž‚^çÛÁyà@ßùéÛ^Ín¦ïB¦0‘ M¬âV=ÇC`^e /Œ$A+ˆy,IГ>°5frŽ˜k`^ IЫ„¦8™ÈE‘ ×‰£639#öX(¨LØBA¿â(©Ìä\b  2$S(èsÌ•åZ(è×p8˜À«'s9S." f¯ˆ‚ža.¨îb2çB¥¯Te߸& z0ePXÐJ® zI´ôäÝ/ôsÅQÁ‚V%Äh² Rë‰}lüv  ¼ÕÀ§d¼XPýZ‚Ø€‚~ê·X+¨]j`E5°">-Õ@&L5°Vü¥f ÕÀ*D£X:žz ’Ÿ§X±ŸFêµJ¼puqõÀþ)r+ñ”™˜=å@Ý`é–/=¦ȽÝRÔ““Xéžz`E”sêÑú)êìkä X íÒÕéÌçžz`•:I=¡Æ©Ö›”=°"ˆ,õ@½²Ò¹‡]êzó¥V„Фh-ÕQ¬÷›ýŠ)>UfÔ¡X‘ÿ,å@f©O9°ÞÐú¨VdB•Xc¢T™Ò4å@U¡XiøȬú©"t;Å@}$Vl'”b TŠö#~ëÛm¥X±º’z`AXƒôÀF—Ô+ÂSTʹR¬•""åÀ‚`5ɶ§È_wêjXz`E(XêRÔÉ¥r·ƒÔùcM=Ð>ê/ ô:ÑõÀ ÿ[ê©òç!=° sgê NR¬X{J=À”ùcM9°Þ oÊõþÀ@¿à871ð) qJXƽOQB ¬XUJ9ÐbD3”9ê'ÖÆêô 'V¸3’+$œäÀÚˆ¥›£a`9°J”#V¸“™k69¹Rd àÄ@Ή¨b@N’+B)¹9HR`mT툙 Äá)É)ý“í¥ùöRáQ¸bÌÿ“œk)º‰èLðW}KöCÝÁ~7°$ÙïÆ1B¿Fƒ¥Ð‰ý°Çå~ ûQ%úÅBàA~Ȥžà‡¥ÖüÚðÃî©øUž‰æ•ýýÄà‡¸¼?šWü.Øòü̘òíä>¦²Jî»*ÌœÄ>Cê»—Ôw5r ©ïÂ+–Ô'O ©ïB\R¯7©“ÐG¡/suÅ,HÄg§yŸ]É·“ø.„·%ñÉÀ#⓯FÄw!'gŸŽññ)%ñ©ßÕb$>YƒD|Ù‰ïB€D¾ !ùB>>•d¾‹d!滨ü¤ôÆQ§4f"imà@¡¨P ©þ5ÀÐi{q@¯·ü·Fq8@;æ4§´›Iÿë:éª\Z@¿ý8Õ¿Nz“ú‡}¥Sý˜D¦ú‡ °õ«ó©þasCýÈÇ4‡ø‡EôCýC¦çCý›$5©p"êv:<Ô?8šõù RýC’Cý[_üŸ°&êß"@Iý[ø…¤ü·(ÁQþCb«—4¤ñÔÿ¸ô“úŸJ¤ÿÁôtè¤SÿS‰ô¿Í³Kÿƒ ò&¨‡ü·©ÓɊ̇!´ô€^xÒJ!9= ª#h,çЂ3= °ñP|í(rãPll~x@‘‡àð€r M È¸p˜@im• ‰¼è›øž ñæ§”ØÐ=NPlâšЊ)  $Ý4€rñ#  $Ò4€’bÓJ8O(á4€Òe›ÐöÝ4€"7Üa½áHH蘃4€ê(@?‘O^Øt€Š$åmøf¦ûÿPìù}8@–ÉÒŠ«9 ñá<  75:y@ÑÌáEV¤ÃŠ=tÒ Cïam4ŽÊŠ(„ÃÚ)ÊÊYlš@;dE™@‘»õp" áp"³ÃáíßQ@hÄPÖߤÃ:hø”t‡Ó:¨;ÊŠˆÃ:(­ÉJ}UP|r hW - Ð§ (6Ê;, H1pX@éΕte…ùêþhàMéoP³“t~3ß5!âÉŠýw(¢åÚ´€¤¤?ì³pHÈûsH“ ¸Ï‹KåºÌ¡üA@9”?dÐ=”?(‰|òÊòCÊßþþö€^ø¬Â…çTþ6‘TÒt˜CûƒÏ+Å?ä‡?Ä¿…ç”âߢqTâÍ»§´G¨å/gZ;l ž-ëå…óãðÂWž>ÐH¶ôN¤Hh$Â:l ›Ä'èf°m ‚nÚ@ÍÌ’m +_i5ûT´CèóÊKþ›û¦–G¨ýä£Ú@·Œ¡ô®D*Ù@Íñò¶nÆ$ÊÊùgÚ@’”>P†-¥t#Tú@7lÛÂew€ ”ž™0A8R&†*}p`¸œ‡ˆ‘ÿ@ÁûSü3 þö&Á0G& 6s àx™@ýu„‚ýú"Å ô¬DA¼¢ €“$ˆÍ\\lX$È™x’ tí$ÁÊKdìX’à&åQýƒó=Å¿kŠL)+ñVøÔþ®-5i›±9NŠÛî¤øW8•øg[ÇåQü£©=Å¿‚Äu)þΆ%þ1íqŠØY-µ?¦+NñûKü‹ÉÃA‚« hŠ…’ƒÄ¿B-Câ_@‚”¿‚ýtRù+ØìPþM0•¿Â%)¥*…Ñ—Rþ²*…z•?;è­ü¾úRþ¸AJ…Aœ’þ¸9rJ…Þ=j…¿2i%ƒRú+±…M*–3J¨ü•Fž£òW&‚ФüäÂOå¯Ðø-å¯`ژʷQHå¯ üÈ„[k$–)­ïŠ?ã–I÷&1P, äú}r`Ùø9‹Íâ—G,È›h&‹€3r`Yd¤?m)ýüB‡þ‡4û‡þ·¾è4IKÿÖ"‡þøtÈo¾H°2ìU$X±n|$W+W1ñö›Rô”²m;üP3KÚG¥<*+ýì°_O®V.Ë9}ž€Gî1–e¦¢,ÉÜc岜~÷Ù ^MEÙÙKަžqf|¯g·Qp6…²£)•œM­újhÕÏfV}7²>R½ýs’ª=#°çìü‡’ª•þË9ÕžYë/çTkwÿ›Síë{ýÐëø¾ò½þý§oq Í%ë L˜Æ†ÎŒil騅¦^µØ–R¦©­#gšÚÊZlë¬Å¶”4MmYÓÔVÖb[g-þT•6myÓôÏZhëÉ®¶·mbð¯•]íÏÇÒß¿ ‹?:ÿéÛû1šþüõýÒÒ_ή¶=ä¤ü,¿šeû?ô¯ÿYÚ³/ùÕÞÐþyùÕÆOZÿûùüjÏc|¾Ó„fû–\½yJZg:µ %k±¾þøü=¡ ÓS2ïï”Q`ÛXFO0Ÿ‹4ý–ïåª_ ¸¥¡dG°z¯x-ˆÐƶ¶O‰Ïܼd „]Àôì)a°ËÚSÒK ê D¦ûÂÇó÷¼vÞâŠëªÑ),Ö=%ìÃàͺه£dG,x4|;GÇ"tØD- ޹Ÿ‰ÖSÒzô k~O {0ƒNŸ’LníN†ãÿ=ëqdvCñÙˆh+W»09Áj¿•àú{ÔØµÓl:ŠEó8w»Çw,£ßhÇ’…GIÁQ½EŸ°ÑS2îïÙžq³ÚD˜7Þ‘¶°ðާÖlÅKñ^Ðm• % ÏÆ£í¬%3nMG6öyJÐìù6—ë,ÙÑÞÛw;_ÑþtÑ GÙ^£(Á.ä»qnv¡ðj†Ç¨…vÀ’ýGíx‡-’„š€˨óµ!æSb»XDü|û€MeŸÛ”(JxvÛa8Jð:û*¢$ú0–´Gô|ì3Šº\“}@¢'+A²¤,–àYMÛZ>Jðóž¶§Jâjf‹Ï̾ùRLö!ñ§€]È*–2J<˜¹Ê÷õ.±'%x×uÅßÿÞ dÆol± ð/=%ìBã­ð·£d¡Ä’â»fö€ îú”< ¨ƒ±?ŸÅt¾×¶a.KP°¿Ÿ¨‡".&àÃß¡ÙØ"î)©“iûJxýÈõ”´ÎÖéí;ÜKøHlßÙKz\ÍžˆÍ†Sê)Yå;}QQÀ@–²t›ô”r™BU<ûºÄßñK°±›ŠwÚÆÆï´R­(a²]vaê¨q³ÄEëb/èwæíùVùNwÕŽ’àìlÇ3Ù…»*®¸d&J ¬T%Z)m¸¶ðüm{Ô Jl“‰(‰_F)Oh¬EöŸö˜o'.,á¹mü–6.+‰ Ð{ñzê…ØìXÎ} ʤi+Z©GÄ;]ê}f!|þný;àãÚ죌×JËFİݖÊ4„¬ÃëGhÞSÂëÊ vHz—ÿy_1›Ý±ÿçSPb´±ŸÜSbû)ùñÕ.77JEoî¸zE?%½±ïå=nnWŸàrÏúñÄ(Ypeð;óÐùõq³utùø¥Ûl¼êØv`Œ¤Ž³Ûv`t“űíÀ˜Û% gB¯ûPx¿û€¼QOɬ*ÁQ«°Wq¿›'T‰á ÷n7 ?ï*»¿ÙSÂ.<Û ømÙf`ðªÆ¬tߟ¥)ú)é8õˆ{eßdèÆ1i(={ÀcØlò”l,ÊTö»ûë"qùùm]ë;\jxF™ò EŸ»PyË»Py'l/0”  ßßa\Ã/{ \KL¸Š}‘Ñ'œgag\~€ËÈÄ$â) }’µg,¸»„i–É>áG9ë`ŸâܶÌeA&;€l(O {€¸§dTòÑð¬ïcVa²HŒ­ž†ç[ª÷V¢.Œ(Yìg eŢɠ˶!çGmÇü=^ßÁ'Jp1¶=u(aˆ=eÍ3àù{ÑÀ]¶Ï1J0 Ø÷Šïæ3Ò®ïp§á<[—zõS’=À™AÚº ¿šOí|£~ßø¾o(ïŽ7 yï&Œˆ÷4á:€³½ø@Xd%ļǾ'ï!$ãà½Æ©‘x¯ÅúûÁ{“Fñ^ã¼×8ï52—x¯aZYdõ‚;{°Y²É°˜3 ÷zÒïi&ÞC*·ƒ÷:1A¼×ÙKðžHø¦!ŠIÞë€pá^ǃíuÌ¿Z^>f¢-/ŸøGØÃ.zì ¦{nÁž&š‚½A‚ì >ü€½5ÈR„½5¸Î@Ú[U’ö Òß´gùãâ̤½£NöŸ´·ßhÒÞœê“öÖàTŸ´·&vÐžàŸ°·&oao!»Dž­É{ ©-öèdKØ[Ï’¬·&0Èz‹³N±ÞšìYÏÐ0XoMö;X/ÿžÙàYÏ#Àq% ½µø° zV‚FzÈl—œgK@6^–€“’â$è-¤,MÐ[‹” ·ë:AÝYºø°å%å1^RÞZ„vRsÝ%èåê AÛD%è­Í7„ ·6¹‰ ·6G’^®·é!µ~‚Þâl[ Çýcô˜C/A/vwýq€ÞÚ¼½µù ôö⽋[¤Ç™p’ÞEVé]ü¤^ÌýO#é!‘ÎAzÞˆ$=dv8Hï"‹ˆô4WéaÇ€ƒô.~ªEz–Ï’ô¸F”¤§£@zEDV±†tÞÅI‚H¯pâ&Ò+¼3"½B"(ÙT!(¢“@¯pÞ#Ѓëò=.F%éâ{€Y:H¯ð®ˆô4kéŒÛIzˆç8H¯p‚U³˜¥‹ô*ï&PÏ×Åâ(Ñ^å Q¸§‰;pé…{UàÆ. gºpï85p/Έ{¾Ü†’U¸œu½pÏS-³ x€{Jm(Üsë0+pÏBÉ\·°QÛEÙ]McnÎY{¾Ô X:ϼ§­)Ä{Vƒ.yÏtesu°¤°” yä½ó ÎõA¼ç]xñž/äáv“HòžŸ ¬¼§l>_þCIŸR8 øÎ:ìƒÎàó³£$x‰;nø')àS,¥ˆÏë vA¼âó€¬ Kß?Ÿ¯`ç*–¾9«%òùâc\ßd:]fv£~-6ñù©ÑÈ*ì ħô">_|Œ£»Ðù£ñ è³:äÄ»kE%­±Sí} Š:ÙÂãÄõ•úŽëôGì­>Å1€¾\Ý•ÐO¿ ï,¼Êwö/dOKî‹rrŸ“¾¹o#1¹Ï2?¢ÀÏ;Qð³…̘ üö¤ AðÛãSécÇ$?;* ~YîÛ“š=€—½ûöä„+°oO À>9$ö17dr_žšà—Güvÿùò>û˜÷ ¹OKÙâ¾ìÂ]€zp‡;ü"HÝ“±í É…¬íÁ àç±ã€¯ ¿£ÐÏ3á¡NôÀê´ú)–]èguÀlA~žÁ,äG÷¿Àï(˜ +.úy!&4)OɇÄ}ÊÜ#î;Âå#!š°Ïóë $ ÉK€t}ò û”ôDØçGØçÆR\ »Ào/¹oÝRÄÁ}¾©ý‹ûl슗 Ø·n)ŽÀ>;t îó†qTp“5\÷Y À}^%Á}Þ´Â]¢ÆKâ[w%6Mö@«À>úó~+6dþ‘àçø—Âg%¥A~^‚:èAY:U€“ùóñÞ€üÜîþ"?Ïã~ž¼àçFvhuÙ¬ñ€ý”ÕOìç~äû¹7; ý¬Êý”©IèçFbÔAj™7¹çG7¹Û œüj/ìS:ÉTùôKî;že>‹A+=³‚à ‘1€"e¾*ÁŽ2Ÿ=··Ì§ß©d¾*(¦ÌW%2Ræ«—ê@æc²´”ùìŠfÅt“2Ÿ• •ìY‘òJ•i¥RæcXMÊ|e/(ó•-®Ê.àF/»@ÏJ ÇAçcÂ*ê|̹–:ŸÅÇ ]ô!o_Ï>TÔLfv|’àæÐ }‹B_MBŸ~bÔùìٽЦM¯ Wt }L¥J¡¯Šüúô\(ôåÝ£ÐWv–lö×K¡/úrØ Ðgw|¥Ï^6ðºPµâE¥¯`ÀTúªV¼Bé³a g‚ÒWKRÞ¥^¡ÎV&Õòâ¾ã¹PécnÕûê…±ƒZ_•|M­¹tSë+\ä”Ögc5´<&ïÃX²˜zW©1^)õYüŸPéË`çåãì¼|Œ Tú òCüI®´ôªMN_ ws/ÐkœÀôdkèa="9¯Q“ç5Æel­©Hj¤¤݈yô… óT@ÌËcxýMϼþ·º§5 b^ª†Ä¼/ê^:·jvÀ–×?Þfέ9±0¯Eèõys a^£J!Ìk\W¿³ h˜=€‡5Ô½-éqiAˆ-l-w(ïe§[^ÿý6sæ­£¾wuQßË;C}/o'õ½ÝÞfÎ-à™³‰·ÖƒpwåæÔµÈͩ땛3ë=€RwôÈF'dž‹nN½4rsfËtsª}àÕ}ð™9õXdæT³2sfª%­ûzG§ÆÑð"Ù2zP2sêéåL^Üåõ÷Ì.¬²ãÃÊ©óÌôAŽ·Â§µå?²r6.¬ÌìÁõÅË ªK+'äQY9%ºÃÊù–÷¸ñáãì\’³ã³•>ND¾Ÿ>N.éääjåéäÄ#9œœ´Œòú‡Œ¦éƒ¤µS6HÒØÅs€±tr²œðVòò²qNÞlÙ8'ÇðÃÆÉv¨îM™H©îÍ$ºKKsh™˜"¸ô@BN£s}ˆ{²t‚¦ä½&¡ð”WCþ+tëÿÊÍ—œøW$FßÙú()aMWôgíÜ(îqPøWä@ ü+\›þ®6 ÿJWÜÕ½,=YÉÿ,û"ÎMuo(’Ž]èœÿÌßñ2uz7ßøÇ¼ŽI€ÏQÔ;dù(>;LÈ>ÐI",®hàq5 ÀÒ?¢ø²SÀ2¤Ó± ƒ†h»ÚDÅ=ƦËÀã þ3%çÄWø5ÿYjH\]v ¼ù¯ŒOþ³T•/O§·À¿2>,VBý=˜\n“¶— SüAÛ¤+âŸÝ”ÿ˜ï2ñ¯L…Ò]sžì!¼ùŽ:à?&ÁLþ³–QBq2)îiY1øÏæÅ ÈÈ®Êñ_¡ÿOü'«ñ¯ Eö±“Ë=ä¿¢ÕK©{³s&B«ýê™ê¡»f9i•ƒç‡j¼¡½+åQG"´Ÿö¡UË =ްà̆²#©JŽ”c·åÞkGS,8›BÙÑ”JΦ¬3§ ^MEÙÙKަZeèï`åÄ1›BÙÑ”Jþé Ñêôµøµ„h_ÞïÚëͰSd”úÉÛ|iøâ]‹vŽTghè•ê -µÐÔ«ÛÊTglëLuƶ²Û:k±­LuƶÎTgl+k±­³²™ê m½¢ñ§žµÐÖ?’í™íõÈìþ/”íOÇÔß¿ ?BÿéÛû1ªþüõýÒÒ_NˆöL»=-ÿÿ¢­Ÿ%Dûû4hµ—Æ¡gUü¾×³®Úo~7üݪ¢Åg”tW_(Š®¾ñé ¯Ž5Úçb(ò…–—‚“ ÚÙ NŽ*ãRtuÔ¥1h7&ïup0eœñCbXÂéT ‹¼+þì…ÉÁ.”Œ‹A¯±OÉæªïÄiæâ²/®„WÏ×:¶2Å”¬Î«³$æ×u–Æuà˜Ü?”x3Â5ؽλ2Â5 ëlLô…cºr ÔKb‘ò)Ù E¿çóºJÙp5K‰´*νc­¦.ôacW£X%‹Õ®{`úšó…£n%ÒÂsz>é <ÄsZ‰´Pƒ}À:ÁS -óE8—ê.Ê£…[¼«Ìx…÷-óȨën‰´êîJ¤Õq®DZgJ¤…ǰ§ xA÷’d¡Ý-F<ªûºº¼?%JбÊ|_5¨Ã>p‰ñùN*—ÖFË=3QU”(™ÖÆQŒXö»¯) Ͻ&óNéÞ×– ç.ìÃÄëv—"Æ…:õ~çºË-Fwiraà vaáÁ<%›†…@ŸûAN•àä“Ç •%F¼\wAÖa‹ó‚zÉGoÒ]‹Lh¶V™0âfÕ[ ÜNû²Au†ºŸ¯*} !_=%2aLœŠ=à¸p×É\NÑëºàÀÕîAÛ*ÜW§ê€«½K£Â’ê}Çõg£ûŽ¸Ý Z¾[‘æ’~Ž.Õ7~Œ¥4M8ùœR&NÎàöÞ{¼:ЮNDÁsm¥½SÝ­ÞìRüäîg:¢,MqžÆÐp·ì@ütŸ’Í’Ž’±Ø%ž}NŠá¸¡m ¦4Š¥â»mÊ1þgg8XÞöQ&w¡¤ÊÆ€_S¿+Åp¼ ½Šáx*½_L–Öم›Ýìì%š2'Kâþõ5Ø' }weŠË³òDÁ.ÜXJ¸»ÀHîû™ Rš¨ÓddÀ³ýz'9zJ¶2EÁЮEáu¸Ç”££dÉÇ€±gìÃ=¯ÆNáÍŸÂT¬ºÜ³ÞRÃãÜ3»€—d² wö‹±œü”lªC‹Ñ…%VŒ/É=Ù.wÞ“] ǾËMûâÚòìMÅ+œî»åA»íà m´B?>—÷baøU»×Xì¾kfÀdt`­Á.\Üî¼bóÞì“î]dÄÀ¹l¿.t)&Ž÷¾¡Ðᥱïry·Ò/ªx±^ö”@]íª“}À¯nÏÉüZö’4‰ÈvëB¯bVЮ«±Wwˆ«3¦v± Øtç)¹ëyÁíjèÀÀßýâcj,‘0¹pž±øœpš¼þP.ÚÅëøÈµkK˜Œ•ÎV®ÆÅ}h¶YdÈæšmÖ…çŸÆf›u¡KèdQp »0uLÇúóÓ4û(ר²n+sJ†Œ>”5®‹vئåm•}  ÙŒ‡P‚^Õ a’ùršíÖ2ôƒfûuQ‡Œ‚~ÅŸ° ® f_e”àFØ:V£âËÝê’0³nI«U\ïqÅ3N}gb¸$ek£Ð_N†vbßsì£>DìÓœùÀ¾´û˜Ý!±¯!´:±ºNbÎ%öÁcÔÇ7±ÂNr_–û˜Ø‚Ü—7\.°ÜÇ4vÉ}š½‹û²„ÜÇ4 ~Y’àÇØÕ¿öü²„àG#Àïø;û0u€&+Ôš£H~‹I6~ Ž-q_´² ñ‹ût±O.,a_Võ-† €úŽV³¸ì›2%@¦ã(`ßÂ.¿‰}ynbßQçèÂûÂSD}¹BêSŠwPßQÔ—dPX¸8ð«ù±PÈ·‚#ä;J>®_ħ3‰øŽ†KG±ß5@|G ˆï(9zð&¾l—Ä·'Š$¾£ˆo5~áI|ÇQGPçèÀtÔ™ë]Èw\17šQ2_Ö©GÞÌwÔô%€>æTóåå‘ù–¦õèŽRð÷úhз4Yô—è;Z¹ $;@x f:ë3uúÎ:A}g9Ù§úŽ?÷xµæ;Zó%õVÂJ”ó%yýñ5'óu˜Î:c}ôÌçu^Ì—]hìAÿÒ0ßq"0ßyÔ­Ì¢, æËù¼€˜=ÀAÙ–Leåå,jy9[™EQÇ™ïèõÈ.àÎŒ£ ¨s×NùÎ’~½;ä;›ë㱌£ àÂ5>º æ;ê€ùŽ:Î|Ç™À|g£ @¼£ 8ªk&Ä:]3¡ý‚>/ÎùÑ«yôW|ô@wi*°ôG9ôßõãmö­|éÃ:ú€vÆúè¸ï¬³ÆG¯À}ǹöѰ×ÑÔ©š á.;÷g÷5ºft¬Ó÷G¯öÑœij6Ä:k|ô Ü—='÷åó$øe;¿³ÎýúøåµüòÌ¿³¡ùÜ~‘ßYrôײ5¹@~GßÑÈï¸bßÙN+ïGÀ˜}ô äw¶2çG¯@~g;GÀpG€_åþ,©šmð×]>zò;ÎåèwÜ›Ê>p‡èwžijNÄ3­ñÑ+°ßq&iýº7ûÐáK…uþJN4á_$TKüÛSpw3<ÖäÁÇL™ø·™«Wø·iJþiy\øgí€ö€O\¼þ)‚Rø·™«Wøg%oüS^2àŸÒ‰ÿ6MIâ?[©§Êw½ƒ,ÅG💛‰ÿŽ3o”7ÿ%͘Mü'‰Bü·kBÝO–î§[%݆­Ôýô ¤ûM2Žt¿)µºß$X®ìÂ9Ž]Ð-•î§§+ÝOAºc7¨û1…rê~Yƒ}D+áO÷BŸƒ„?nP’ŸÎ%áOçÚÙ<` º;þÔO º +º)üMIŒG>„¿<7E3¾&)üñަð'åJÂþdxkRõ›ÒëzÆ-㨮¸eª‡c¿OLÕº›D?F§èÇ|E§èGÄJÑ:D¿%¢þ¤â·°®”’Ÿ”¸’×=$?¬ðCòË”üøHRòS—¤ùéâÍ”æÇëý@r©ùá¡HóËfRó㩎. »@-q½†•ýt)ä? jâ?; J\Š–GÝÚh¾ù/o'ù/uWòß^ðtˆÿŽsMíŸCr½_W¨~ÒnI€ùPH€Štê†ó4íè¤Â£ Oyà €vª(ÿUÀù‹lì…¸ìjóÞ:·2ŒâgKÌg@<Ú9ºðýÎë>©SÀì0\ nð8z€ G€`w¦ܵL1=S¤¢`«Ghø§›„y¯ˆÇÕò]$þåQù¦ÿ²â_þâˆycˆù ˆöä .E#âÿô æÑ…7ýå’þòVþrl úË‹!ýYèéïhåè8Ž]€ó[ð§€ì—K¡úF¿<õ>:€’ìKjý,¹_ó¡_>[¢_Þ*¢ŸîïÎà‡AòS~ù‹#øéZ~ºŸÞÏ îãy€}µ…}z Â>ýr„}z…}ºß¾ŽB>ýn„|ygˆ|Ø…|›ñB>Íü„|y}|z=„|Ö  ph Ôq5sj¾£€|šßù²"Ÿf‡B>ÍÀ…|æÅ;ï?͈–˜çÁàæ1…1‘d‰y_T>¦JÊãNEIy²Ê‰ò¸-nRó±'æÑ½˜—%Ä<¦‹OÌSËÀ¼ü»Õwd$¦ÂHÌ“Æ#ÌkŸöδàìæü#{hº2-ÕÛޙ͈òRû•Y‹j»@3gWf-Ö™Z‹à§ÄTëÃÞÙ~Ä<Gå"1OG­ì]—éŸÝʬÅ*é Ê;T=m“Zé÷Ì.D©A¡OÈËBžJyº7‚<ÝÑÃÝ #îáîÄ=>ܬs¸;OO©Ow'~a;ûpã˜ìÃx+}J¤pº;á4äq«¯„<þ8’ó¨'çe 9‰×œœÇ+$çÉG&Σž Ç>$è1¿^‚^–“Ô+£<ôt/Äz:W9ú`Ì>¼¥>=N¢ÇŸD½¼<¢žŽê©ã5»€›%ÔÓ êåQd=uJ¬Ç˜Ød==ªzôl÷Ѱš$詞.M GÛD‚Þ-ËËï Ç»+ΫÒÉyzÅyîYqG r,ä<æ.IÎã79†Œä¼¬CÐÓ}kÙœI §«èÉM'ÐÓû ÒËs‘ôô>€ôÔnÏ>´ÒÓ™DzíÃÞy³½öaìôŸ ZšÉµÐãËš Ç‰p’Ÿu’I’žŽée[YRÙŽúðzGI΃ÞúÞÑÊœï甬—çÎ>ÐÇyôá­ïeË‚=µ#ØË’–s9¨wýz·’}`¡yëÌùÑ+Á^ži÷÷Û—°§»~gÚì!ßÒ_I–öNÏ%ûŠêëPænÄç] ¶¦S1M=¢ú>O{çu“öÎÁÀü êÛîÎI!DöNæVH{çüŒê[_ÜK$x# úÜ«gX@Ú;™ü'í[­ÐÞ gnbß’ù.EȘ.™= LÜ… ¡Û¡'ô1%&¡¯H $ô1F%¡)pú2‚/cúÓ‡°µ?ŒéÃcôUžëˆéCŽ˜>°÷A}óE}Óû3¦Ø…Êè·#¦·ïˆéÃsÄôÁi|ÄôµêcÖˆ=`èÝ?²e¯~Qöª‚ú8’ÐwS$ÞÙ¶Ë.p#ó„¾›<‚¾zeBlú¶ren€!ûÀ`Æ„¾[{¦[ð80–èS ‘7Wva~0W”’ùî/â^Sà™{ žÌG1O= )4‘ï3¢/¼Ä%ó! ã`>¬Ġ ”“ùP'™ÓŸ“ù>bú¸oáÉ|l'™“ƒùÚ'óájÈLÊgI}x!îìŽè:*¡éÃÞ™SäûÖìãQÄ>Eû:Å'`_ÿ öíWPŸ§-õy€×}¨ÃdËìAÿNÇçf&2éòD}]Ú"©9ÓI}L¦•Ô׿è{ȘþGÐ׉xÉ|âÈ«ïÀÇ$Y |:/y 8“÷º"è.Ü·we^<™‹WÏY |ܸý>p#¯3”TÀ§G$àãm |œ›$ðéeðu!O-ø:¾ƒI| kžÙ…ù¶væOç`¾W8Ÿß ”ù: #É|Œ²›Ùƒõ|Cžˆ¹Â’øÅ}÷ñLâëòc’ø‡<wMâcºÊ$¾ÎßµˆáfI|Š7òé¨}èâ^—G³j§Q´ æÓýó1ZB_¶Ûµ[*/ûÀÈARÓ Ê)ìŠ%$ö±$±¯+8¯h·Tdhãdö ûø´ûx«ûØÄ>ægKìËv|| ‡Lìøy'öéz…}]fKbŸ®°´×«•Ø×)Íum.Á˜?Rß’HêÔ }ꥠ)¡O=ô1 kB_Ö¹µ¹Û!ô 2ú˜q$¡Œ“Зu¦R\Ð×?MzEÄ|z¯Ä|ÈÇ÷B¾çˤh–=+sD=D7,1­òðüPWR´w¥<êHŠö“ÃþBR´þ|_9ÃXpæ CÙ‘XH%Gú±‰ަPðj*ÊΦXr45xýÞÏn£àl eGS*ù§g2ëödË;“Ùä³<»õK‚§/þ ÁÙGʱ/oOÛ¥ä»óûÏÞ”±tw‘Õ)Z9S‰Y3¯Dbh稃†ÞIÉÐÒ‘HÌ[:Óˆ±¥¬Ã–^)ÉÐÒ‘FÌ[:“ˆ±¥¬Ã–^ ÉðC8’ˆYK¯Dcüùd´ô%k3¦åÿByÆþt˜úýˈó³Qé÷Ÿ½²ŸÕOßÚ¯-ýõñ˜ ZúnÄwh׋%1-}JèÂÅ„¶oºTÕèÂv:]:D{t&ÃêôžˆÔ‘…h¯›i¸ðÙߢ‚iI¿.Lˆ fõý*ôÊÌø»Ê¸S§“:&è×­ .ýjØúÒQûBsÃÄ~ ¤K…tÖ¯‰m¡é®êWtÁ·$ÆA;ÒÜt¾ôrE‚ƒ›ÀÐK‰– ºEIµ üïé :-ô½àúsJ<\×?¸sÖ3ÔGzƒÉt½ŒÈo°¨ó÷2#¿ÁÆY—O†¶¶¹é%®~[‚÷¸˜W¿-U2JН í›+*O‰¯ íÆ ÑžO¯ÿ ªz Û§s† %ͧs–ä½á¸þ=™Ó£×¸~Ã…ðÉô:mQÈ^Ú¡§äâ³®¶Ú÷”ÜØÂ´ß¶ ÑSй%t¿½^‚ë½½þ„ìÐﺼdÑÛøüöì˜Æäø˜NuKé¸g€°ûóC³öÀž*¶~F¢ö@yêu{I*±eY«Ãùû3zÄ×|!Voö–>sc%û)‰)ÀdʮޢöC@ìÍzPkç+Óš·A¿^·©ÒÓ£ú|zУ6ìÝ}â:þý|.ea.Û[tÀžqüŒ{‹XÎt<Ünau¸RлeÛJ÷B~JlYë¹ñÜæê™sزVm»…§ÎÍmØŸ’è‚BÙûŒ>´ÆÝú¼§—Ü›?–Ùluëyã¸ÃnŸÖkgc‘¬ÏagZ”6úD§3ºÐ ɱ»}ÐNݰžîxNÄÈî{?<%ñPÝ7<~J´}U[Ýz^fîÁû<ðïš>+« ïÔâ.f}uϨk‹•~Ö°Õ­§ÎäíZó9÷ó]à°–­nÅgB†zµÑ‡E½¦ïryɼ³d{¯¹úy!myëù‘p¿‰¾ïé½z&‡ uÐË=߆±¸Ù÷h^P¸›Mß3R®›õç»üü}3{L·¯r‰Ç€a_eëT/ø1Œ+º`êÄ×ç)‰.Ü_±qU[꾡Î%÷ŒNÝx÷ÇÕ†wª6Õé=Þ¿‰Ïç¸Ð0F” ¶òŒ’Öa ³ñ|˜í «Ã>Ë%nVG‰}Dìjh•xJ¶÷ ,èÀͤ|£ÜÓKÚ×z”6¼K¦CÖ(éÝêfÂ¥a›`YFçAéeØ&XÖ%[tmQ‚èx»¸ÁH ñ ìv¾!þˎsHõ7ì³\ãrqqµ.ï-Úã tà¦ótTtÀ,ãR‚ÐmdÅâü^Í»ôŒ$Ú±ë´Ë«¼¿¶ÖŠvBø¶–ui0 ÷~»àÁ ÇóaŽÛÒðçŽñ8ì«\ãAÇ€:î{z— ´Íq·áïÝ„`6n\~ãÚܸqùæwË¿½vlÿ+F4A ÛÿjljfZ\?»G‹ Ûã%uy—Ž:÷ô.ÙT4›õ¡ FëÝÒbÔïóÍð¬Ýö=ˆ[ý}J˜Lj4ô`sgÄa`YÉ¢v<ü÷ç Äèž«ßÚË ŠýÙ¹ +cLŸ »°±jŒ“ï+A†¶Ë3z0.nu£Ef#þåcñ}>0W_Þ%ðÉ{LÔ{òb=Ä{L:–ÀG*HàcB¦>Ôø,Ë?ø À·¸ðà³k »0ñ ør®à›l¢aý›# iÏÍñ©í¹'u¦\O¨²´‚ßÁ;£”ãc ÚËnE{–4ô¤½‹ê·€Ï2Æ™|JD'à+üÄ øL%ÄQ¾‚e~ñ^ÙbÂ@>ó•l0!€µr¯="ߺ g­@>CØ‚:|«UÒ²#ßrýýG"Ÿí2€s|¾}šE:TtŸíg¶ÑêŒm¶ÆÒyVì6˜ÎÄ÷Ìʸ‹-ï)Ù*AlŸ$ Uù |FǼ†|O‹@¬³Û äs<Æ5˜ÏëàÑó5“Üð’ó5Û¥„%ŽLÕqî`¾f{¶`-$ ïùí1É. ï)á’€¾§dBZwèk&Ë. úü·‰;Ð÷ü6…f}O 퀾çתu™†,†`úL¸ÃDÐg¿è넾f›´ßú.{Ñp}6}ÄÛè3Þb‡>Û¶gÄdz`Ìä}6R¼˜ïš„ Ÿ©}Ž äs¸ ׿™ÿ—Èg“Ôë…|—¶ %ó]»©`¾¢/™¯TlHÈgÓK\ ïRd‘Ïüp|V‚ßÏvvÃøä3Ѱ¿¯˜‰Ü]0¢GùJ¾$@¾ò|›±bä+æýCI Ÿ­I´ùÌìCLDrÐóUm Gæ3³Ö¤À|Õ’¥ÆÕ€ùjEŽm"_…ò™²ˆwÈW;Í~D>tæ ùLk$òÙÃv ùêÔº!¯vN¡ˆ|¾Ñˆ ]°$8,xÉT/œÈg>@¾ªÜíD¾»ñÓLä»}÷§I|÷Í„ºD¾ûÖzÏë ù|üÈgÞ£x ä³É4fœ@>1oòÝmQ‰|¶P±ÑN ß½¹Fä»ë¼òÙQ çB:Wˆ|Í\¼ ¦;7ƒ÷n3ߨÀ{6@Þ‚÷l¥%¦,ä=k— äk7÷ òµÊý$‰|¶U^EË|6„/”òµgÄǤÈך¦ç@>›ÿµ}ù£`¦íÄ×&S9“ølÓÝþB>ÃçcùšœUD>ëR}!Ÿá<¦¿D>€sÁL¶†‚û ä3ëÀœÈgƒJùlo?´ãÈgëŒgÈdé¿ßÌg„Ìg»’Á|ÊaNè³ï h™Ô§­ÙD}¶?gÜ-RŸoêkë;Nè3_6°*¡ 7R«þŽ. =GR_ç¾¾¢¾Ê÷ľlØ·¹ÿ*±¯Ûâ+®]°é,Î]…€°Ïž!/°Ï ‰%À>æj÷%N’ûìNÆH®\øøi?V_ãGà7ÜJø#¹ÏÜn7÷5-ûlKb0&¸oHø=8Þàgv7 ›ŸiŒÇø=åÕ~†yxC ~U3ßà ~ܹžä眇: ¿››¡‹ü· ùR®Û=ÁáÏ·ÿyÑßÑŸöþ ý-ß‹üGÒ_niOúˈIž0<8}3|ôgŸjø€@OIüè·|bþ#Éoù öÁÏHåzŸIk˜Pül×d|Ó©ô-þJéã¶¼©ô%tBéÓ:¤¾Êµ@I}¶¥î þ|—àüÙtGþ ‘ðW%þª‡ðW»JЇ›[ þî‹w‡ðwk½Ÿôw/  ¿Æï’è¯Ñ4/úk̈-úkšž’þºd— ¿Î=•…½‹!‰z2¿1Fü×é0ÿ™Š£À]úù¯w |à?û ÜÐ^ä¿õŒL˜P“ÿº´Dç¿õ\8ž8}V6}GIðŸO%q¦à¿åU$þ™Ú ñøg%Tÿ¬øg ãÿìÁ¼4¿W ºÐ¤u¶è7)ü[Zç$þÙ+] øguÐmâ_•ÆBü«‚çF€½(Zþ9À‚aˆ7·þµÝ„F^ç:5¿fa#Tða«”8Ã?Çë~j~mkUü×v¹)jþãzÛÖ€4ÐÛ% pýÏ`Ù „›%ÐGÿÚJÄ ükKNjàßS¢§büç ¹è€o‹Fflí²¤ þ5ÓA#;v§YÌÏ ük†(x;ÿžݬÀ?_+Ù'þ5 Â[à_3;2V'ÿÜm€–À¿§„Y-€SkFÄ¿%øç.5€f°“±ò~I~6»ïø® õûW¯˜Lÿ®‡yðÿlÑàzáßU¸úú³ˆ ¬ý=Ÿª¥†§¯zl ‰NO ·^ý¹6‹ ¿fKÀÞ ¿§äâý úó/+^› ¿§D+lAþ=ÆÙƒþž’Ê{ø÷üX6Ÿ]à_ü !::ùOu%þùTpø÷”0àø?²Sñ‹u.úPèùþùÏŽØæøçS“ú€ÏOˆþâ_=ÎøWon@ü«ú)ÿŠ dÀH£§rÐT`©\’$^ZÄ šŸSO Ù<æ‹}í:aÔõ|Ûú‹-NŒlh¾̹A€—v~&^ FA€ö7QÍðéÒÖW@Àçýã+@ÀX½&:>%åÆ@@GYÇ{à³6„y×1[ l{4ê‹€þƒX›½„ó@_³$†]v½{Ä8>Kæ ô7äØìõÇÝ Œ´¾ñÉu2•üW;¿,ä¿Z¤¡‚ÿlweÒg`Ñ J|úF9ÉÐfmÔëKR8°\\Ž"C€—îç0ÐÞuBbàõÀ&‘0úp=$¬¹¯gPÀÃ^7c% €¾„ =.ð*º_€—6l'^sl/m¢F¼´—ðBoÑ݈åðÅAè¯,è)°Yì^ë @—ò÷Ô¹DsaLµ:Ý @7žµ$À§wŠ#º£"^ô¡Õ!10ð^ÌÌL¼ŸÉ6–|@€æg"%º‡-Ô½U¬ÚiMVî·?K7FèóÕ’ôÑIÐW™;’߯*GB[B_—œ×µ‹MŸ }äK@ŸíÜô’ü,ˆŠB!¹¯Ò4Cð+’¿‚ü o®ÈÏœ#(ð+SfM‚í& ~ŒÿIð[xü4I!øÝòÙünƯ ü,°`Ehª\u%øu®cü:÷ëø ¹u›'„à7 :.—§æryÎOî{^Åõ2zÚÌðzsDBŸ–@1“}ö è˜ÿ€>‹¦‡(è³à´›§v›”ͳ4YAaó,\P#ôÙœˆžÓ€>'(æ3 Sq0Ÿ7Àf0ª6iaÔüz—©z™ýzÓæù¼Ú7goÔü&¥ùÍ[¼ Í/¶Ôüž™„šŸíÖzj~ÏëÏÕfú<]銂ðyZìÛ¦ósÇÈM£}ž×ó~–”üž×ÿÅ|ÏßM’`ø<í› )|ž ‡ø<í·‰n“ù:ŒB>‹Hf˜žùü¤¾ÈÔû'ò& È7ÄøD¾Ù¥ :òY”*”DG>mé,ä{~ !"_šõˆ|KØMÍÏÞþ“ùÜOŒçOͯ^ßOæ{ ¤GQò{Jp÷ ùÙAxØü®Š èü®Úäé„äwkPägSf¬SAò»Òh ÉÏ>öx ù]]j8$?Y]˜\N¥äw Z—¡ø™bz¿? ë‰|ýÊ¡'/ýäD¾‹_d"ß•ìKä³ ÈKñ+EŽy _©C Ìg&éþryZ ݘP-o©Ÿ`¾Òô"úÊÝU’ŸÕA¯\ò³ ¼æüŠÕ^’ŸÁ.x’Ÿ•€ú!ù•õÒûŠÒ°Rï+©²Cï+o¨÷™JÓ'4ËK–S~Õ '/g}æÔ Mð³ü ¼¸üŒ°d¹üêMô¾Z&æÿû*- JÞ(ð/´¾zÓþN­¯jƒRÂ^Iñ °W ØÉzbô–‚õê%tÖ»¹|&Ö{¾, Ö³Wˆl¬ç:J¢ 6q§J¬W´:KÖ+7í;d½gjC§+XÏþƒú_°^iIèC¯èf \eæÙ@½r T¨}eÀÝC±ÏVOÞbŸ¯§œ¤ç–:5qýËùû,Þ·¼ü6-åÅ„ØWvReˆ}fA쳟Å<üö8Å> 8À4bŸMO JBì+‹pÔúlNC"ê]E§a:/¬g?%–€õžÈzvÏÀŒÁzöÊß/±Ï:ybŸµ‚ Ö³gñûlùš'Yo½@¯š­5 ‚ój,äY°° g«xB Ê¨Bžå¥ò™MȳÛÉÞ!¯Xb¥äÙ8Ð^gçÆ»È³Û´^öN;ÓõRù< °/d¾jK„Êg<΋‰.Ô[ E>{e+Kv„„ð H‘Ï#€Yu…×b¾ÏâÅñ2ñîBS!Ï$¨Â+Ìé$Â{þË> <«C­0ï¾™ã_„gË%Ñ…ßÞ_I2–¸Wæ÷üîÕɾ*£Å³Ë¬I‹'WÓâÉñRÏ]¤'Ò"ÉMÉ3¦Ö_ñž Ñ()°?‚¯ˆ{E|É{øXž¼‡FÀJÏ-¼w/Ézྲྀ>…¾g. ï=ã,>¨ä=› ÝÀKb1´.xÏHGa|Æ{{*¶.xϲsð˜èÃ~®ópðžk0l‚—†¦…aqío¾m?ãSèó;}ŸÀçë9ŒÑó><%•“슸8moæ{nýÎ|¾Ð‰¥â`>¯Àk±(d¶¯3²Ï?èP`ù|•¿ŸÈçw„ŠbDö•OÏ¿˜dªí³ž\'ó=w¤¨NtÁ¾¼XM@h_µX84 ˜Ì¨F /Bû|ªVëó¸ÍØ>Ë/…[Ø>ÐNä{z¢·ÈçË”§ÍÓ/†äÌg–.baшÑN›§”ý`>»¦Ãæé1n°¥‚ùî Øj0ßÝ>lžÏ]•ѱ}®†ßlž¥ˆbd&2 íó»Wh_ëÌ.G—çÆo¸<}¶€ï­€Kwy¶©û —§•à½bhßÓiø<›%íãÃçióŠNW§÷ M„Òù<äíeó|þ‡k`¾æ™ž~$ò™S Ú uÀâ^q}Ñ |}®ï/Þ³Ïàzñ^ŸZžï5nÞ@ܳp‡·ÃÓî}—¸ú[6ðžä^¼gßí7ïÙüÑyoÜ´5)¨Ïàí¢ 6*¼ž ±^ßÂ%xÏR]JôsÞ[£'xï™ë‘PÁ{E \²ÔUÝÕ7y»€{]¿À=»g 'àžåÈBpo(qo¦ë¸7æf7A|eHw âJÎKâw“‡.]@Œ.ÌÉU"Ÿ½-xâ ê›ÌXÀ7‡4}Ÿu¡žŸ¿ä·èÂì$ ߨŠSõÙQX…õy¾à‚úŠ‚žÔ·/ÂetaÚgä¥ðY2X¾@}£@&è³tœ× úfí²fôÍç]c4^@Ÿû› ºEædÎOBŸÝ›·À7'£:}³7]@Ÿë }sñ¢vGú†ЙÏ3@î æólg,qèó Ö+¨Ïïî€>ÏyÊ{ÏëÀE!BŸ­j/™fc>22߬i/ æË@2ß´õ§ƒùì¡YÓ€É$¼˜Ï¼V I0Ÿg^¬ôYÞ&ˆZ€>ë$a-:0–„É|6†¶æ³7„¤säæú™o=´F´ æ³.]GXßèMš[ta®ëƒù+åaªô“£~=ÙØ×ËÊ&ÈýýóYéù¥¬ø=]µÉýu^j–dS,SS*8›²üÏó¼ª,9šBY6Å‚£©j£Üóî7P%ÙËÔ” ަþ9yËž9òå÷ׂŒž‚9ªªMÊo™¡ÖRþ±øgµ¥ú}+aÕ— ç?=QOQݹÕîóÏëãŸfïîÊ5ô“7bÙ Î>^Ôßú^Z Ú|Õb[÷Õ\éɶXr¶•µØÖYKmšÔW[(yµ¥Zj먥¶?#ò™ í™T!A›ýëßõ/æMkÇ¿þwý/“²ÕŠ\jÏÝÕÏ_ÍÏfUülC…Ùæßõ¯/ùÙÞ§D~¶}7ul~ÍÏö”ý‡þõo?)S~¶òÇùÙlJ÷<¼`C{ˆÃK\°Äö£òŸ„Ï“‰wׇôñƒl–fØÿ»ÿÓAÃ󇕣ÄWz<É^iQâkœÏìÏþjù¤k¡$ZµU—ám`åϸ¶ö%®å Öî%nŒ¾M½·³ƒ­¦]ýÕ¢ÄÕU›oúHµ 4OwÍ(ñe¨yÛlØNn•v¹ŽÍšYÈ\d7؇ÖK\FžÖ‰b'g®›^Û‚Âx®xÃðæÛÚvõ›i+~¥nh^«xF?íöf?Ä,FÏìÛJZÉãF.;ùFüË2uù“H·ï!waðpŠ˜xÚ¾ ;¦ZÈynKÐÏìà›o‰áìaN rÙ ô µKƒ°}Vµ¢¾§‚ab[0­Ýv[=r?Ò¶«u+©ÁÓæþíÏ•>%wL„·õá9kµÇèŒeÎã§Ñ(±Ç¹=†°XÁ 5{è3r<%ßEÃf„n;J|mÏlÏàh%0PmÏÞdí,.mëÄe'/LŽ|]® U¼CVRüA>%3À ök˜Ê*f.H{og¥ÏÒÌÃ6H£ºËÆO ´îk¸3® \šSÂç¬ð¤Yàø¶3Ý\ž¶ÜqWGI\ðÓ¿7B Šõ ZqÉL^cƒMŒ¶wÀ’¢£Êíë­æg¯°¾· ¶“¾}y­ú†8Q§y aµ˜;l0Ò}›˜§eÞ [·Ñ̳R#µ¾Ç‹ÕuŸ ¤ÝïjiD˜~Ú \}…yÔ]6ª¾ƒ‡ø§ãÜ+>hTB«®zIE>ìÛ®*ö¢ ½®yšoy:»çT[ ‹¬÷b%p-²qD/˜S[Weä¯eM³a}Uº…ÚvA¶šÎ4“³o«9Ì£æªÉ~Þ¬O¹usÑ%…jÙU˜ˆÂ£;« Á‹‚„-åV ƒPðt Ùyó‹ûJ³uò¦1ÝVá­™[aFËóqV Œ‚OmûrO5§êÅ…M[ó}{h±Ï‘ŸLõm~«iŠgö‰¦=:È«=ä¨Ãåû²øý\\!±u™š!v¶±’à¶¢U”é ~‡±¨g°sM¦Aðõ;ˆ¿’ôš4¸Û‚ϲ:;êÚ.»Ç%㨧öa_áö¶Ïï²_¯ßãé›[U3ÛF§lo%¿íbbáß–êlü¶¸¢ lo%ÀÍšŠ:ËS\Vhæa¿$ÀmY>n…½Ï6€ûB½·ã{+Ù¹ž_T<={F6‚/íšb‘¥6„[”KÜÀÑùO }Dö‘¶!Üö5Š_•}¥m 7wF-1Wÿ~ƹÃñR}q?J,yÑ´¦8°Í•l·8°ÁÙæJ6„[ÝX0„i¶šë5¤i» ÃM¾O׎ÐájÉXcˆ´à:Ãwƒ0eßh*LGˆŸ•}£mm—¼`ûîÛMøÝ²Ý•l·ƒb\ؾÇUÝ 7k«àSç¦Z(•àf§õÙJµh+ÁÍ5ì/A5³«àæ7ðA©ZÐ̪qÓýúêå[\ÕMI5£êv–ºxÐÓÁí®ÏhØvˆñø¸_ím#øHLVͺxãYµ(ÙžR­nÚ<ªo¯ägY®º3mÅïQ¥ºQªšÓÂLµÝ•l÷^EIÝV3(ûÒcµ¬,6€[\õànµ ‡;* 7@W3U ‘é+‡þ,G\ÌòXn'Z\ÌvA,î–?s µïV‰’â›(ùÎV>©¨–pÅéôÆæhÕŒ|ÃÖXüŪfå±ñÛr÷8¤»ÁÜo•ËWÕÒ­ØømN„èB uÆ^$ÿӥͺ¸Vµo³ßÏ´ÝÇ£jg¿Í²½•îŽûݼ¤¸yØ;äŸëj{+Ùø½™$µÞ¾¿UµymôǶV¶²tc=¥Zz“i=¼Kh}Õ¶Vz®ô)«0-Æ„8Óô™†oøåÃc.OU†ìÿJ²¶7þÍ/øgg៫â/ü ˜þEŽÏñ‘<Ù/ÄX 1C?2ÿ€ø™ˆx¿GÜš•~ L/@æˆIœHSÈŸFàŒÙlòßÄì,ùÏv’òƒÄÌñ$þƒâžø7± bâß WGÒß„ã/éo~¡¿‰i`ÒßÄçGô7cƔ𷰃aÒß‚9éo‘*E Þ¤¤¿u}Òß‚©]ôg@ílEø³Ÿù þ¬$"üaûAd?‡p»>ÁŸC¸S%áϵi'FŸA¸Ÿ‰ìg¢d?;ÈŸ¥ØÏêÄä‘ì7”·ŒìguBN#üy 6ÀŸá}Àá/v·:Ø/ À~¾$Ç€ýl2u¿àÏJ½Bø³Eˆò„?ÿ™|;ào(v¦˜Ùþ옘‹þ¬$¦„?[|‰ðguBÀ&üùÕ´oýÙEÈi¤?²â\ ?[@П•€ì@&–`óKП]OLÒIv.ì7ôgƇðŸþ†ì«¤?»î>ôg3Và`ÀŸ 38ðçU¢$àolš? vîx•® û™¾‚øó:q„?™r v9Ø ð74é$ü¥ŠIø³:ج‘ðwÁŒ*ö»8Õû]Ü`Ô?¶ýZI¾Qjào^̈Døóµ›0†þ.’áÏÇíhðçu¢eÀŸ·-ƒþ´ä#ú³e!l ú›™=ô7©ß’ÿ¦E‹Ãèügí"aøÏªÀ®þ³x]À“9‚‰3sÂÿf¡ üs­›¡ÿŽÞ ‚&ÿ¦.´øg%÷‹ÿìTŒ£þ³:ˆdÿMKZÕ?øÏ¼$pÕ€ÿl‹tðŸÕ¡üg%¥Á¶Žÿy8*øÏˆ.VGÈöŽ1’ügž¨8ˆügubYü7IAä?[g ï øoV ^ÀŸ]I1áÏŽTþ¦{þì^…§ƒðç¾?Šð7•ü›ðç]úv°Ÿ›ÚÀ~Vxô›œu ýŽƒ€~é8ûÙAá8 ûMeü!ûYI¼ d¿y_¨Cöó™_1ÙÏÖÝ‚¶€~S ‰‰~3ìä>söÕøYIÜ`‚Ÿ´ò›Zb!ùÙQ÷I~óæèMò³’ëE~vPÌëI~Þ(ùYÉý"?»œ˜~ƒü&ýp"?+‰3ül}´¢$ÀÏJz”üðNàguF0&Ào6ìb$𳣜: ~æ ì øÙAQÜgk³þë÷Y•ûf[lƸÏf_Üg%-š÷Ùoð.¹Ïx¯÷ÙÕZ“ûfƒ—‘ÜWÍzã³:qŸ: ìó“ïà<Ÿ-çÅ“ü¬¤Eà ¿€Fìóถ ?»”õ"?ý¾D~“A‘"?ë6 äg—;ƒA~æAòo ÉÏlQ%ÈÏWŸQ%ÈÏ—–KÐaŸï÷w†ägëÚÑm Ÿ×i'úYo)[ÛAf„>á;/%ü-ävHø[È•)øÛð&ým;Isû¤¿4A¶¤¿]?å¿Yûþ6̬ ;Ò÷'ûmXŠ“ý¸Ù¶ØÏ ^âŸÏ.É~6Oð3‰ý|æð‚?û*ø%øsç§—þìœׄ?{}¶-ú3yÆ=D“‰®„vòþÿ&£å„Ò¥„ö%õ™*ñoúÛ'øó#\Ä#üù·×Å@Ÿ}Ì},üÙT¢½àÏU3?áÏꄈ'éÏLùoé¯`J—ÒŸíPê°'éï)©/ü³Ï¬¿ž©ý1ßxjZGj sJ5Ù©üULZRùãŠÖ¡ümX¥üÝ4 Jú»Ÿ.éïn˜žIú»™;NÒŸbc¥ý&GHí;¢¤ø§sQü«4áJü«¬“ê³nJýc ­Ô¿nO‰ÚIâ_aj+‰• U$þi¾&õ¯pÃ(©•±úRÿ* &àŸ}µ7ü3g%BuÀ™g’ü×wþË*ò_gFWñßP òßÜ݃ü'[ü§ÄĩۑÿfUÊ^ðŸR6ˆÿÆøä?®¥'ÿMQ#ùorjò_'΋ÿÆõÉ}}èS>jñßdÒàÓ‰ñ@‹ìh$®ëÛ € 2”øo1©‹øoñ‹ÿ©Qüga‘Ái俸C'.îÁ(T”§p•OœüqŠ':"ÀNe”hê~¬½‰¹œ-\Êì&4kR”gûPÿ,*"NN´Ô¼±H! ÜL{& Ô ¢(Ð^—7.¦án.‘µ+ D3BàÄ¢^B eéó =!ÐîNÌÄ ‹y –hjGÄÀ…¢@K=u(’¹#bRàó‹ ½J8KLHEž°*ØŒh“å-bà¾ÈxÄÀGœhoe´ô‡|IÜØýØ'Ah/ëˆÓXŠ-ìÍ’uyä@Ï|ê~T\9Ð÷Š ! 艟Ù‚6å/4ûÅ| y6‚¾Ä‚†TÀ ãz²àB*àdÁéo²à†G,¸8µ z ``X{ˆŠí‚áÈ‚OÃÁ‚–à YÙLÅ‚6Ù\ .f˜ø“ÔmD€õDØñA€=ÆP ÂN-ñ‘ƒ˜›µ$®ž þ[Hï›ü·Ò0ù–Ç@+y« ÁõI€ ¢l 4t†‹î0ò4"ÍüaþD#éý\1C:¼Ÿ¸ºÃû¹ *Êû¹âë}x?á&?¼Ÿ=Öï'¤ÔÄ¿‚¡òÀ?XüÃ`~à_ŒqbÒt ÆÊƒG,¡ˆŒãI€øúãO´Ò7ÚBë·käÜ9øªÎÁ=Îtð6…Iþ«èÃÁøHü7¡+&býE€þ)>©D€FoTèY`!ËÉüÉ8¸$@f(Md0àMG”ð¾¾ ãˆÓþÙñMû'çÿI€´€L>•8ñÝÞÌ›.¼¹‹RÚ?¹OMÚ?¹¤°qÿ:`cÆ`ƒ«& °á=Hl”‘D€ ¿¾ÃÿYÞ  {;£€èÑÍ'vÚâD€]ê ð±a%¹=€ƒæ0!ààVoBÀ‰§p0[”pLÊ}DÀÁ î„€÷%Ú&)/p*ÄS ¨Ð{1 ]‡û“VI1àº(Ã]°«Î—ýóHéBä0™ ¨™ÒþÉ|#b@[Æ - ¸éiÒ§ž ¸•b† ¸™ŸM ¸É‰ò^´íÉzi¸p€^Šd—´i38@¯¡Ôp€^ÚµšÐK9íé-Ù`-Ú²˜Тô†2€þ?ܽK’¤;•lV+ ïÇ84€kÕ(«Ž§Só/ÂÝü3¥³¶®®UÝ£ŽVbƒ AòñÁ=E›Óš§’Á*! YG^PFùš‡6W4k·:@µ•  Eº2€2·¢  E’  &9cÑjDô6€V&L’´1ß  •Y¸ämÃèmë5r€6z¡åíÜgCÐÎÝòäí”xåm³å®ËÚ¶-hgºgB íÞ1hûVøƒh» ŸC •ø 4'n}É€g³ ¯<6Ö—ô4ó¶€v‰q€À¥L‚ÀÁÝlç¦b@»*ÿ>× ­“í…ƒ~HèdR2à)ñvœO$¯\Ìb-\LŽÐÕ4 py>ˆ`@›ÄÞB ™9¡àÍKØ_P3ôºCQP㊯ í Ð&Ð’Ö:l’mäz@³À‰í‰ç=à9·‹x @;U})6#ÎÑʃŸ»Q?h¡N "$é¢A<Š‹1{{Ñàa=ɰTšù’ÈnPQð àBLØ,äÀTY90a¾r …² –˜á^90+/]<¸O7 LKÂA{\þ„ƒYg)1ÖJ(qÐ|§D8XñA Ķ‚Aƒ×r¨M8ذ\<ØÝ@8Ø‘×?p°cÓÝÀÁgNàà@.ÀÁ}'£ÂÁ9>CÏ{÷uãàbn}áàâÎÂÁ5 ]óë7S„ w„þµ#!qpñÝ*©!ið*½ô@­”‰m ç8¸´OqÐJö+жÆ­Ä?åÄA›¿AWÚ¬/Wˆ‘ÀA+Œ-[N}áàYËsŽÚ½pö .IF¤A oòhp) iÐò2®®AuŠ8hóq pЂ™ÞÑ€'¿Ï­®Ét‰ƒ65óâ T^ú‰â¹‚0`E(àäb ÔF Šƒ„Áþ)žmæ?‚†LNF ;>‰W0 g7îM£žb7ì Ȭ„Á…d·W, žSÄ6jPAÛûÁ1E$¸^JàfêôàÀ޶+9ƒaB‘€;“ñ ˜6ÍœŒ<©_k¢9h˜ýmËýìPy‚;¶q \ã3°ÿðÖE2¤h±;ð\ïzÇ@ ˆÝmƒ'µ8r íÕÞဠžä@{±úK´_ay…ÚÈrÈc8à@6´¬™w8 ½ÕN®öþ¹û‚›Æ¥œ¹‚»"t@ xJŠŒiÞΫwº±6}CHbÄ:W¶ÏJq˜*ýrÔŸ§yûyYQreA{Ÿ"*ÝYÐj/ÇbMEI4Å25¥‚«©f‰·×¾{­’hŠejJwSöd˜¤7¥’«)”ES,ø·§y;ùéíþþ–æ-ÍœÍó¼•;wÛg¶çŸ{þ–çmG»¨pÿÓ>²S9‹~{%¦€Wº­ß^LsY¯W-¶uepC[w7¶µØÖ+ÛŠ nlëÊশTKmÝÙàØVdpc[W7µ¥ZjëΧ߂2¸¡­;ƒ›~¶ªÅ¶þ•ó¼ýžRðçíO†È_Æ¢âßþɨvUúƒ¡õo=]šm6aks¿¦K›J—6•.í•Æìúgdc´šÿ Óþã—„iËÿ5Ö/ ÓžÂÿGÿò„i3•Å®=…?¦=eÿKÿúï¿”)aZùç ÓÎ$Õ¾ó'>ž?°ŽGçùl 6ŒònúÚkà±ïV¥Úöy¬-5å3±ñi^RŽŽä ©ã”Ô£'{zõ’ü€XZ{F©“!Ü£ÇË)é'ö*‚Å«m”P,>½ÄF ~¦®iÌ!žï,ŸO÷|V\­WÛdkzÁ™·Õœ³'@]H²_m{¤…Øë3™ª¶ÅF¨õð£êÙúÖý,§ -ÿV/H}õŒK¾Hëc;yèõ>ó×z6¹š^°ýD ‘×ySjÞˆ¼Þž§ÚöT'ðz#MJµí©Nä5UäjÊLDïzÃgÓœåѲgvZmŠøÙ³>WKƒñ‚*r-Æ‹SµôÿÇx‘0G«eºó"aˆZ|;RôðËÙp^$¤³«5Ñ{ŸpCφ1Íí@gÁé™xÂy‘ÝmóÐz¬ôõlrÀ?¨ÁxÁ Z;ŒÅñ©ÖßEÁºm­“Îûñí+Œ÷g£Öí¶‹ê;Ô–h¼‡àù<†ñþô±úîáº~JຨHôW[…ë‚›ÎÖÖÜuÑðR[‡ë‚áiµ ïÁO§i¼Ç¦Rµ-Ø.:²q×¶«{6m)úô¡'Ø.:ÌAµç°ÞŸ†{¡ó~ã%ÕvB8–‹ËEí –‹ Tí–‹±ü·Òݺ\Ï‚ãb «Tí Ž‹æA¥OÀp1±?wµäßG@XØ»Ž ÃW\ê(0\,$â{J`¸0Ô8'5 N«m¹à† ÞÞÑi¸(lgÀt¿±2Wmœ4Ú3>ŒÆýâêL¹åëÍÕ¾ÞG«£[«Z_¸ÈæOÿ¤ÆÏX0=÷ÆÖå=å"êëÙ~hy¯Îc8×uÖºñüWÁ›ÿ¶NóÕ¯ßÇ[[c½ ;ÛYC8½±l@Çi1)ªÔ§Å€•´îŠÕµ•”j+(gu­rpµ¥ƒáXþ°Y,DšTÛj¹LëƒÛ^XYk—²a²à²h;;Hw_8«/Í>Égam#}F³OòYXKXÏl¶)Tõgx¾ÑÍö„:y¶,/ÔgËü/§ ca­ÀÜlK¨³²Všÿ(šm uÒl,26Ûê¤Ùâ^qâP[ : ÂÍ6Ÿ8kk6’ÔS’±¶V¡a4û"Ÿ<[þ– ÖÖ²§j–íü,­l5Ñró¥5nVÖlK¨“gËFI?ÓÀÒãd›m uÖÖzõIN³-¡&r|7N;ûP_C:ƒQ+Éólu,6Û⬭  µ³ÇÛôš#5û$Ÿµµ›@+5òl³F+ ËkÈ×JGš­…Èþvö„Ú¾N:ýä“y¶’ÿZší 5°Œ‡£6V׬›í õÜ•zv®=ulO¨ã²°‘çŸO²Òý²2âùš}³e†ÊHAÖìƒ\Œ`)65Ûê)ªI8Ñ8ËkÕ6ÙB;“y¶\hÕçbO‚¹šm 5ìä…¯qó O35ÛjÙ©òÄóµ-(öé%D«f峺fû–žËiÕ]Üfß䳺6°¤Ùš§'«G,õf’muxf›í åò¶²h¶+ÔY]ãο­­¹Î <|³M¡ŽÍbaºf»BM,Êž¡Ù®Pgu­!iN³=(ÎêÚóÖúïþËgum!³I³ïröÅüó§g=IȼO¶Ÿ’Ûg=Ø™Çzte«åéˆNþ½æGí"qä\í 5°Æ½älÌu’›ùOÞv…šxoüâlW¨5]{ð_¯mAqïÍŸ¯}—Óyo°~Ù컜Ï{³1Ùw¹`Àñ—Âö§(Û¹ìÛzràëzö™} rç»Ð¦ë}ç†úÀufªöâØâ{ñ’íêHA‚‚6Ïæ\õ,š{`ÕXï„™}·=q{ÁÏ%Ÿe û äóh'K«jCЉžl -2’,í…~'Wö›ýκëÍ~_èçߦ@?lÀs¡¼h/ôK_B¿á”y¡ßðÍ…~ƒX'ôC. ý&aè7ñ»ôC^³ ¿ Ó˜ÈiÍ‚ü&¼"A~&‚üLEv€$ùÍÙ–Ðo"Ca öλÐ/±a±ŸcÁ¶ä¿…}‘‚ü–hŒä·À6¿…èé?›Ë9@ülzä(ؘs ï¶ÀÏh6yÉ`Ò­á³pßI²àí‚ûŽOÉK6snÁt!î3âååȹ5y̹EÒ'ø™¿Ég\?ãd?ÁïdØòsõȹ•^ä§ä "¿³=Ú×E~Vàwäg(¶Snak6¡ßI%~®†ìgNªdÎ-DTûY"¬¯ ýŒ~ ²@?¦í ôK°Kú=%NB?1ºÐ/!Ì.Ð/!}d°_Ú9²_‚$ø—°×Uà_BžÅÀ¿ÅüÇÌNÁfæðCÈz[ …ðœ‹æML#roÓ@l%üW2~‡â?&ˆ þ+¶Ä¹ÙƒÿlVç''ÿ=-£Žóß9•7C,˜O OR/!2¹¸ –‚ÿ*Ÿ/øÏÂXügFþ³ïùo6.„‘ÿ¬Î™Q -ÔÅïpr#aà‰‡wîÚŠ…ÿ €æTð>Oºˆõu! u´ ´ ÿ‘“OØú'zÚéh >l­™å ´ œxÂV^¨~à 9ç" ZÉñ»ŠOà®× ZËþ*“ívûí! šQω™0¨( ÍøÏŠ0hÍøÛD´U`hð82ô@ƒæ$t  Ú²Ió£œ'ÅnÑ U™v A+)Þ pÐÂfŠˆƒöÊ8B‚­À§œ¤ÁI3hЖD^0xb¬ÏåO±C`Ð,‹íƒvÔ1:Š™ã0x‚ˆ½`Ð\/q„A;Æçô„AóÁ¼ap%"8að¬9~9 ßã í—âkÂàÙÀ%ˆºÞäNÂàdT¥`ð8_4h1<>)% Z?0x³_0x"üT€ÁãÊý Œ¸±àJ¾ùº£à —Ï_‚ÇÎæ·(xânò‚Ǹ½GÁsµM@ÁbãÃô:!×5ó\ N æt' žõ.ŸCƒOIqøÊpÜ[öµ›½G6°à‰Kr‚t´“§ ZÉY¾" ž†qªÁë…K& .n-<>¸/¡àY5sÔ .º”E‚öÖ°„×ÄP’àò˼HЖ{‚fjõ•² ½²ÎQdA‹/òC´~ Ú¢œßP²àªØPU0h¿;¿7€ÁI9ˆ0xJ|µ‚0hýô!ÂàµnôÀ>G?‡AOÆpžaÐ~þðƒçGï×ç,xîºÿìÈ‚g:%dÁUè%΂Çwæ ]dA»d ÛaÁã‚Z7 z`ÕÍ‚¾bé ; ƒ¯¿ý`Áã¿ñ»CÙÕ„!ú/dO ´ù¢ÁÅo¤A‹êã 8,¸aà Ü>ô nßq6H¹cƒw'å‘w§xG´I‚‰²ƒ7µ’ )T¾ O<ÓßmFêëÀDA«âßd¢ “ªŠí ’ •ê@‚“ã&IÐ |²K´wÈ'>$Á“ôÕñ0h%ů0xŽrf ž£¼0hSÈѸ2=ÐàÌX ž´¯o0s#Ðê8ÙQ̈þ– ˜95 ÐwÊ 0g’žT@„_* ä— È†CDúìKT;’ ¸Ž*`RÌÈÅ2`.%©2JE: CPCÌ0A‡˜ ‰‘J é)±_[þµ¹¤ÀM¯*Ù¯c¿Ä`¿î3—@¿ŽPàK äêœÐϲ]8ý,þòå=ê%R÷÷ ý,ç+ƒãJ¾ì%D¿ôW/!p|ÈŽèg¿¬—#Ôêø¯.„@*ž!.¼É!nÚ9É~“ m!búð71Ãü1wMÀßáý!1Í¥r‚!ú›HØõÒ}a^:`þ~™B­ܦ’)Å… çî%Rã °³ŽtÀAŸ¨tÀ ÏØ-ú \ô·Ö‡+tÒÎq “îR H¢+ü[‹ Gü[pø^J`£žHüÛ…TâßFÄÌ¥ò¥bí @¦Uº”@ .%K"@Ó1ö‡X11%pð\R9镸¼o_¨µìÓ̧›è/-ÐSm^R >Ôi ”˜F~iroR LH›Z ÝNsÔs¡u”Z q™«ŒÔóâÙ¥f¼ëÒ3²Õ„X†=´ÀLï^h¤K-0û\4¤ÀŒ´¤!ÊsL<öý¯‹Ï6Û/4Y4]®ÐSå-Ê4-)ÐòÃzJ¥PŸ£H»IHæH}àÉgíè< n¼j¶SŇH[­´Àº(MJ DzµÐ+áx¶ ÷*@Àc›ÿºðèÎ{ô…r7q ©Ž~GI€&‹B@¤X‘ÂHhîú7*;¢Ðä8¿;D@ëç¸}¡'ÿÊD ´@P/_¨Ë…/\tì„X‘c=´Àžü-)k-’GfõgN»hpÙˆý¢AWŠÃ:ûÎÐÙo8C‘½ûr†ÒCÎÐMÕŽ0¸ à ®òé ]X- \H¬4ˆ|ÜWL ¹.`ðGLàÆ¢[À çë!&„o„X˜'=°ÑOúõ@IiÔM°ùÐ¥EJwJD*ŒÐ ]NÒ™ì&`°æï7 r—¸`Á:¼G¬X` 9°Š$2MÐ`§»Œ8Ø'‰ƒƒR†pptæ‘'R” N|‚'6š\ØÞ&hpqÑ_4¸èîÂ:ÄAÅC—Æëwì$®  .><Ñ LAƒÌß+4û€ÏU‰ƒvnOààâÂ’pÐ>†(Úç 9™‹ïqPylŃ6^ù¤“@¸¸—“€ð| þ!WõXï@Â…4XBBû¸¸jט€Ë÷Z>&¿[ÝIíÃj9KÐ(€ð|…ýÄBåZ ¿~á‰ór½@h^ 9¡%ò€@¸¸åŒ€Ð®P"´ïœ7‰ðì‚à-ƒí{·¨¡Ådù$žDxB°\~Z–7L"´@†”¸(Œ’×L_ƒ®‘_R ÅV!¤‘©Ý…ƒ»lzPƒžáÄÈÈÀ…$²ÈÀ#2p!W™pÐrÒÌ.î3±›q”ÄAC³õ ´ÌMþ|ÁƒçŠ_ÆPË%“^Ràæ¶kW| Wȃ›)Ø"@p`Sˆ܉’]a.zÆÉƒ›ÉÞŃ3ÖZ4š5yÐÒmåw”à¬t}:Z°—¿ÇäAû>ô’-šåŃ'åê×…ƒö}¯ï Aúò‰ƒVÒƒS <èa<®)2JÐöYwfÚg2JÐ&/^‡Q‚¹¿#JpRàP”àÜ´b2JpÈô©(A¬F”`A¬F„ Vj Ô%ÈA‚ûPF`E’°´wÂå?‡Á¡øON3g?§ÁÇåòš‚Ód<¢Ó ÕùºXТÕüQ„`åÏ,x ¬!X+±Ž‚ž§õ‚Áó– >=â³ žwdß‚ÏÅñç£ÁîáDÁL‡XD†rÛˆlŒç žõ"A r¬Wˆ`MZ·QˆàT‰£à™¬û²QPy#Dp0–“(hÏÉíº@Á§"œB'aZ!‚{#¨‘‚ 1?$Áš*UmEZHäÁC‚'üÏ_ FvÆ1+B "Bp5jŠŒ|Æ€üŽ™‘†ŒìÍ¥NëÏÔѵ$&ê™yœ€ÎÈ Ä:W´ÏJq˜*ýrÔŸ§NûyYQ™Å>N•îÌbÝ¢ÀË}©Qr5…²hŠWS£­tµƒ?£‘S ü¯ëð™<#èuÓT°Lí¨àßž.­ÛÖèvOÿ“ti?Òšyº´z§@ûÌ{öoI—öÛk0Ч3¬U¿½Œ­"rTµØV$Bc[w"4¶µØÖ]Km)šÚº¡©-ÕR[W-µ¥DhjëJ„¦¶TKm]µâýg"4¶u'BÓOUµØÖ¿’.­MÏV^~K—6ÿYº´ý×tiÿ Ötiÿ¨Þgº´ß_µwº´?~ ‚û'#ÙUé†Ó!]Z/¶PµM—6Ó¥=ÿúú×?M—öüw¦KË•©Í^¹Ëþ4]ÚûL‘-ÚüßÒ¥e¦ÿó‰Óž+‡çbž½Ïñ[xŠgß,÷쉽fž™‚°'¨û)A67¦êu#{"CWo ž Lý{Ëð\LpH¦ñȸ¯S&ÊßtôœÍ.žièÉsVVë)é ÂÎlf0Ûk=?Æ`W,†`#Ë×S‚ìÕY²‚Ít ½'„`/¸¡zÏÁf`^ï!Ø ¦¥Þ+C°¡‚öÞƒ Ïxï1Øð>SÆ`#ª½÷Él,Öõ¾ƒ ‰é)a 6ä™Þ·/³8íS2ÒYf;†žsª‘„ˆÉçÜ ÂÎ>í£2;ûêuAØÍ—cŸ©3ƒ°‘Ÿ¨Á l¬eö1„< ÝžcG` K„=}U¾ÛŻ듇nÿ̓°±Õ]?qÓ0ÿ„í³ÀeèÀ³·ýŒ~H£ëb[?›ÎÑ{ M÷0ÿvS·Ý¶‰¹t?Ú0,4¸ºE×=rÏtSHâ½Üõ•h»‡®ÐÏ>` %ç‘Ûbžû6ùvÙ"œû67¹¥zBÁéÂY;C~8¿çk`ãëÂ_Œå‚÷Þ-ivƒ[ÇßZÛ;ç8/ Ò½t˸„4sËúNp^äè–ŠÈ·+ÈÑO¤sTeI…ó¢À?ÖmYé8/ ,ÁÝVŽó¢ év?y†¶×9‹xý,+ ‚E»-ÊëEÁfìÝV{|ûJ„_ö½a½(Ô¯Çz4aÃxú™ÎÀ5ž‹%Q²ãð÷ÄõSÒ`½(È÷>R‡õ‚ûbŽ4`½(ø9 /™pÞ›#À›™pÞì«5l²sFpý7œ÷ܬiœ\(ÙK¼gÛ+˜ÊÎBÚ˜Öû4_ãì‘ S™ï vîe÷KM‚í0•éè˜Öû ³á°lØ@†ùÂ<Œ£_ž:ž½rÀ²t|g>ŠÚ'ÚC°R4ì!ÎaØ'ºÀÐ6½¤ÂyošØiÙœgŸX%&ž1|NÜ÷5ƒÔ}Ãvñ°´ù‹a/¸yɇåRˆÛ"§ 8ç @Ï“¡Ìk$¯2rh`ò”låÐ8oè´ý»\ìÆ¨9mÿ®‰\¾a\ö(Ϫq޲ý»öW¤Ù˜Ù§‘¢`Ú94Ο­ºÒùjÚç¹ WÇ91 ÜN|^™?Í¢öâÀ“EíÅõúâ¨0SáÀÀp „¿óÂ@dÙ¾8á"rpàp?`p s¦Nì8áF œÈš$ÈügA‚N Â@ûõ9Ð “IfÛ. „Ù/0Ð2Ê8<¹[¢0pÁ@ÈLÝ«‘/‰ _‡ÀÀy'0pá#- \“ˆ 9šϦ“§ß¤Àó sèžžS š—³#10Áʘž¸00%'10!œ=00! =00!^<0Ö¬ÀÀ„Oa å™ys 3o&ßG=00!H``‚%40ÐðÜ›úàÆ@£s:b S@Ò«˜‘%00a Ä 3F¸À@fXÇ3ÄìÀÀŒ„×4‰šÈ(ÔàÀ ŸFp`+’3>UÁ Ç"˜900ó- ÌœŠmŽ~æSâ@æ= ¤]780C'Ìx Ÿ:oÌËA?80#FòâÀÄ:ä@؉…\»¸00á)ÂZXTãBAÎt…‚Lz(X<”öBAxu Œ‚>œ Õ0Q° ù{ `ñ,ÖBAë Úˆ— '¨BAý dOÔÊ„P°óˆ‚©Ý‹o$$XøÞˆ‹˜Ž$Xðý ´íEOD‚O‰c²H°@¤m)HЖ ¼„$hîÔ)$Ùƒ3qR$˜ðÊ "wÇ…‚…› +ðV(X«/ ÖF€$ ¢r } ½9°’Ä&ÊàÀŠ›ÁéeÅV¼àÀŠ÷Á;4 +›+òUŠe‰+ ÂÀΡNرO}``ƒw+0°c-70°#¼50ûÔöÁb`'7û¢& mÂÀî›A¶œWŽLà$¤ï \¥dá Xx Øo40pp5MøÀ­8ÂÀ±ð3 Ìø1Âla k"¼_8IPÂÀ§Ä_IaàÄRm`àä›. œs'Öæ…“£”0p•H '0pba;0prUFHc]` çË«|{)p!£{PàB~» @n8 Hç_àÂâ­Hp ¢¡‚mƒË7 ’¾E‚6ÌNq ÁöuÀ$xR;:÷‘” ‘ •œ7G0hG5/ ZXò£@ƒŠ'û yÔÍt>^@¸(Ë- šÓ‰pÿAÝ„««„›[näRšþä( œ)¡•€4;ñ±ú& ´™Í|)ƒg>tú@ TV áùö½˜Ð>@Ž{@B 'í/$4?r})ƒç’倄Vâ K$<‰ü(GBëƒC‘p2¤MHxržyù¸¼ÊŠhìò§[–ƒO~ë( Z»Îˆ­sŽr 9’Â`öEÙKÄåÒ±‡G肹|á™6ûQÔKöÐ ò|….X°OÀ¥ "ƺ`ÂTöÒ+Hä˺ ,‰—08€8·0ˆ£.aŒHa&ß BNfƒ ×naЩû]›“.ÈÕ邼šø@˜ŒDÈLVA„; æÊ–A„–Ñç- 2ÏÎE„JfƒzmƒÝ×÷/aë! vÜŠ[t:„A ×0X|Œ½„A¾9! "à% r¡YDˆìBL¿ˆpaîD8Ɉ"BŒ9"Ú ”A$K¸”Aäþ¾”AøÐ+°b–H !ÑñbÀ™à„æ8FÄñ'c“ƒi œ¬"\pVŠ™Þ/0!¨&PfB1`ZöГЩ‹hgwÀ#šfëb ð- n¬H]ÞPö[ÞPäs½¼¡‹J¢¼¡‹Ø(oè”LHo()V(’PlxC9ýo(VßÞPo†¢àÆæ€—(H«eˆ‚؃ëRù|CĮė*8 —*¸_ÞPeлTA¤¾ U(Uðm M3âÿVê.I߀—$èÎé[tÎ I0C½ I0ýó'Zä«×‘$H­L’`#JLtt•qOxÖbÞÈÄÿ—$˜¡#R¤8A¨8â?kwxðß1&{ðß©óu㟖GˆVÿ¬¤ºØü;ÍxàßÉí÷ObAoøwŽràþaË%BàŸ]Îÿ(ùþ¥Dn#þÙÝzãŸy?¼aâ_‚µVøÇ2ð/a¯ÅÀ¿¯­ðïÜ‹—3ôôÊK€ç¿¡‰Sñ_âHüÇïVð_â¾оhn(%&ÀðÏ"ÎIÈHüKB;âŸÏvÅ~‰*­Ø/!Ór°_jtt’ýl~;CS!בýí|b¿D!Oì—Q?ØÏ¤y×"É~ºB²_ŸÖÐËI°_BV—`?~]‚ýžËIoö{:Ú_ì—*=§d¿Û¯Ð/Ñ`,öKT–Å~ [)û1q°_F*¼`?nrì—×'ûe¸N‚ýhqöË»ö˾{Ð/‚Ñ/cCÅ@?$ÒòcBö€?¦âøSyæþ,ó¥ëŒ„¿<‰q„¿¼deFæ½H𗱿PÀ_¦Ið—±_rÀ_Á‡6௠gaÐ_ñ,wÅ7ŠöÓ* Ù/ÓŠ+öãþCÁ~•¿±_…nìWuE²_õD Á~0HöóíÍ~ ÙþƒýÚ M”ì×ô%د!R:د!»ŸØ¯bFìWi$üU,Šü|"þ´À"ø«¾ÉW°_m´€’ý¸\°_£¿Yì×?د­O5ÐRR¾Ù¯s"ûùèp³ßs@Šì×ù8Å~®£`¿þ¿N71Á¯sAMàבì6À¯c¡IÜ×=+°¯W^ ±¯c‰7°¯#ÿY`_‡8Ü×!ÉøuD´ø=G}xBû üzÿ¿Ž9}€_¬Bðë×G%°!¥f(™‹B ìÈ™#%°mjz$¿†= ‚ü†º ¿†I Ÿ%‘y£_ÃÛ_H£vYCÏÊÛ  ¡OÖÐÐý"DpÁ-Jo(ƒç CHËLJPIïa }ˆß5=8C—8Q‚؃÷Š\¸¼ˆÜ$P:C7¶" g覊!gènÔ%i݃òÍ¡{1OH±ðaØ”ˆ÷%¶·7ô|¸ß$"­g†¶_¿u@Ä:„˜Ó'fNðIY4/!°á‚Cl`,Q YÖ¾þ~ë€\˜çžùÀËz2(ýýÖé 0±a逨,÷Ò=uoÈ€¥ ~Ìe@S+^ÆÐ£¹4G ,— ,ò)°à£(…Jx•p“Vv.pо™bV8< ÄÞ=A ]Z‚ÀBÊ$²¼â7GÅz>“+<ºe„n±Â¡O]áË R«g|¼D@øÃB¬‰’)°æïž´+~Ôk¢–H °fR¤ `e®4ÀšIoÔ¹[­ °„㑟Ÿ2ˆ«ˆ X3íœdÀÊɼ°r™ X35A2 áÞ X‘>$ÀаÍy+B¬Èä X3ýÈ€•‘AbÀŠÆÁ€vÉN…dÀZY‡ XݳX± ˜(PÚ“(°ÂúX9ù¸E@; °Ò«)SÉiV.Zl„6¢!APsÉl<»BÛÛªë‹A$ؼBåðTˆ`ºFˆ J"ÓHh€º¸4@†ä…8xD@X½/¡!"Dæ"èŒ' .äˆDòðW„`þ!訂ŒŸ _è‹ „vÇúlù®PNðCôÜR—ˆ¿®øÀòCœtJÄDàŠäâPh€ØÐøŠä¯^ñø`_ñ…`¨øÀ„fŠd…—H7¤@P?3‚`´J¬x%">PÑ€2†<ÝA9^ èoz T/–ŒK¤»þFAHÃJAT(8£‰‚ƒ×#g(2ï^ÎPLÏ/g(i6œ¡ó‡3´QÑ“3´ú+ÆP°Áe ¥¸ñTÖC¬ŒE”1‰É^2`ûˆäè&g(å»p†"Üär†"ßÇå à\‚ /e&¨¯’±î* ,C¬?T@ÞœP±WÂ¥.žI* VJ®ø@dé¿âpñH2pÅb½ç ÄçëŠD;Æbâ{Ånr&x0"õB DšßK ¬>ɾ”@ˆÊ¡bãrñàI‘ûõ œŽ:%˜ñ.]Q‚ž„'¢3vY¾R©Í3Û¸Ó{í‡zF9ƒXçJŠöY)S¥_ŽúóTjËr:Õ}µ%‘uŒeJe¤‚+ëØ²ô}[ȦTr5…²hŠWS;ÙFcýîµJ¢)–©)ÜM5Ÿ\M©äj eÑ þíiÕæÑö;­Úg–ªßþy¼ì³þ·ñ§u[ÿoûê¶gŒxfLwÞ­ÏäZ’íç >çÉÚxçÄúíu>ÈòÊØ†–®,kÞÒd-E%´ôÊׯ–"ÇZºR¬©%UbKw¶6¶ÖÐÒ•`M-©[ºsµñçùÕ¼¥;½š~䪄–þ•l'ØãäÞÿ/”ƒíOÆÓ¿}Ž¿ŒžûõÅýQq´ô—s°™S«ÿš­¥ÿlÿúà lVõG6+Œ6—þõ#›¦_NîØž©pE'­ð3›•ý/ýë¿ÿRÆ leÿó lóèø† ýÌðÝjtlpˆ†wÒqqyÁ™rÏ9¼=¡0Mû-Ÿàí »Ï´<'x{â·9mWœãÓ`ðÎ3Y;¡§Äs/XbýãÓ˜›i›«ŸÆÄjê<‰à——Ùö)OcbcËgŠŸÆ„iå¹@ø4æf;>‰ŒáÏoøŸgÞþÌ áÓ`:¸gƇèmÆâ?3>Do/lº6wAôöB˜é´œÐÛsœ[±›/ÒÙBóYì›–¶ü$é\Ëñ»û*•Logø*ÝI=çGM_¥³·oíå«tgÓ/Ù¾JwÖÏ­åe ÆïD+e_¥³’Óõgæ¯ÆÂºÉ3s„WcÁ3õª+ϳLw4¿¼åëtVRýLÛ×éNɹÇ%ù:ÝàFY«ø~ñôôü|S•zÖéN&…soJóu:+9Œð”ø:Ý1ÎN•¯ÆBêìõ¼Ô°Ûy¸ô*s„Ûîô¡,_¦³*ÞÍâùO¼ä\qM¾Lg%~òš}™ÎJü¨ž°í¨‡,V­:Ëöå´‡Rt–í¿û§d£ î¾N‡y+¾Ng¹λ¾ªgð8%8juäbDìߪ»AhIÎBÏxR!´à7¼Z.Z`Í_­d-°R=íët'ó„·ã "GÔ9@÷”lî°†ºZ_LÆxþó›Gœ[Óæ€Û[—¬æ/ë)™^âf½#ùÓì©Âm‡¢ÕsA&FxzV?§à ]Ë&O%×ó-ñQÜšY^â«t†þf÷¾ä¶^gL¸í '­>ÜvØTꎻrp/ÙMn;ûGªÊÁáoÎÈn;ß¹k’a¶ã匚`¶køÉŒ†ÓþPFÛ0ÛaÏ5úB $î[cL¤à@’Àu¾uH‘é½<ãNäáèrÐçüE:asÛKü1œŒL£yº€Ì×õ ®üÔñ;q¬‘iÄ«4_§;UÎÃ;óWÔ8Wlé3†o¬¹.ûJ—‰+ö’Õá·C ÏuráL>ÚÙÁÃ7ÂÈ–mˆ3^%ccHžkÕÃ7–mŵpÔÑ–íúÅ=ŒýdißÃñ}Ë>ÒÜÃø¬e¬å¯Ÿë¬Ã2.ÛÚ¤Â`é'ß©Âp‡yŲÔävÔ#ý<„ša¸CÐíÚ5qÛ*ÿ\Xºÿ‰SùàkIøêø«nldoñßüö;/9½²¯tF?—_ÎòuºÓ‰óêØn¾‰1¦9Û6¨01žQi§\ฃ¼¶SÉrÜ%?ª&9î²lx¦·+¹Ûvƒð€Ü¶Àd™î§d „ÍÂồÏ½ŽŸ{u…Í6?jÇÚç…Û9ù2wcÜ9¬£`ýûy0X§K0=3*¬Ó%¬ömÛ lÀýê·Âv›Hˆ“¼¤O â¡¿m'°¯&N5;Æp83·}¦)–g/ÙX¦Kˆ ßö™.èç™>o–éÀŸ)_þÆc8/û.ËtôÇ>%°mXɹœÒ`Û ÃsÛN`R½Ÿ{Àµ‘<²vÛ>`ðe&ovÁ´‘ü¿ï¦\ºþPjªòKŸ“غÀV8½Jaà ¿§?Õ.¶B¿áµn¤ÒÅÇb×¶J)u¶m6`´ï^ò\ÿDÏC±=ÀŒÃ›Y ³È¥ñüê|†¨m_ç„óœÅòm_g7LŸ“ا™ni?m« niìžý”l¹¥Ïwa·¶à–FÞ·Ýú„[¦¤Ý< —øQ³Ã- o¶ À˜@ɉm¶ëݲ}žÎå?0û<£À/ǾΧ:}°¯sq+ª OÉF%Ĭˆ¿ÏÞVŒ¹ÿ“ l/lýª;bY‚ÐÈ.ìÈF ƒü‚ǹ@é+.„w >Uºwq Ü0ò¤8AbU;0p¸ƒˆLâ" m`à¤MKÈ}'¢c'>Vâuˆ“n*aàœD—œØ)7 pB×Îåë½sçVâÈGœÈ×h ýu3 %ä8;2 m5å4Gœˆl|JŠŸ‰ H8œÄGœ0—Nè­Á€–`@×ànœûº1,0š&Ì]Ä€‰Ü(ħäbÀä‚âÅ€Øíb@µ^ ˆ]/ƒùN ˆE"uÙÅ€þ-¹Q˜²Š0“-…€°Õ_ˆ /ôQÿ"@,\\ˆ„ˆ”JÂçÈí±ƒí(¯#D²ä ÀE„ZË^B\…tG\•,G\ØA6P×#\ÈéèŒC\ Ý.èªA€ Y9‚×ÿ–›?‚þ,éÌ× q” ›ìüé²ß‚¯8ØOUˆ~ »‘úY‰~ Ö÷@¿?K ßB{ Ÿ–sÄ~L¤ì·áì·`g öã^éÁ~ ^•`¿åy ý(ú­±Rè·y4ÐA§~ ‰•ý\Ã~ ÙIýxGè·`Bú-O±ägkD§—"¿…äA~ roßBþÒ ¿5Á”$¿…<ËA~ÌBägëQåë&?­5‰ü>ŽA~ ûŸù-ÄùiéKèÇœ¡~–KØyŒè·wèg>'4¢ßrãªÈo!‡TßB–Î ¿…0‹ ?»Ž$?-b‰ü–ïïà·ð¹÷™YØiŒÜ·<ÛJ`ß‚õ"°oa›À¾…lp½ ä¾³æUÄ} ¬Hì[`¨ >|z‚úléίWÔG&õ3;Š‘úìÆ8fú¬að¨ÏJ΂•¨ïôÉÔ§d¯õ‰…}ÉË ûð)öi1OØw®ç´Ø—€ÖÄ>+ñ».ìÃ&³Â¾¸_ľ³V÷¾³ÚøÂ>­ù‰ûÎ.Û~”ƒßà6•?«r¦Lb¿õê´öÓšŸàïÔqþüY;·`¿s»ò×Å~'9®—€ý¬@Øï¬Ì9U‚ýÎb˜ŸðwzåøÓzžÃŸ-g«§+ÀßYµ<§&ÿY üwÚn¬ÞÁè&þS ³øï8ð½eðŸÖ1ŧãNà?eÿi3ñßiç+ðï,ûz àß ÑGüwvíqfÿ§é%Ô_ÝKù—r®®ãæ¹pyHlàF(PF' ½†.ü‘7ö.Ü…Ò[ºB¶÷H€ A€ÆÃ À ;Y ££" ·&äë Èõs0ঈ&´‹ùºpcž)§¹ÂmlLN<§ð1d›.P¹„€VÒ^ ¨¨c1à¹d¿œÅmlª$<—ãØ•²Ma†xÎîuJQÖâ X²]?t@-Œ‘­ÀeR •ì—8én^Í,n×ð”¼(ð´ãj\fà6ü¾¢À™¨h“î- ñà‰#sÕÐŒ>P„^>P,‡_>ÐŒ^ø@aj¿| åS Ü\ÿ#hWÔ} ÈÊ~ù@¹®>ÐJª| *Yø@˧¸‘'öòb#§ËÊ%ðz™ËJí8l Ø¦î²6º>åå"| Õ_ê°’ío¨ß¼°’ÒÃJ•:l d.º@¬ßá%Ò„ ´}ú5~û=(ÒP_&PÌn/(6ˆºL ýû­Êþ&P~*Š™Êeí¸çaÅFvaš@)õ† {^&PLK.è \((¿¾a¥6L 8ê2"®æ2Âu™@aš½L BK¸@Ç÷m=†Ý¯—8é$•ƒõ¥.JŠò€Âht©“RÔ@fè}y@iR§¯]^jà’>5Ðf·ŽrR×(uÑÀ,Ô@Kj ®Gj b!.5›á^jàH \dD© ¢S¨ ÷4Ô@dú½Ô@„.]j <½ù·´ÀM•ˆoÒ¥bêK Ä.2—¨‰Ø‘à÷üK€ìiüKP+ÿ >‡ˆ?¤?šlƒþ \ô‡PŽ‹þü“yIHtÁ_¢8(øK Ñ€¿ô!žäºÎƒ¢?¤¸¸è/OEP,.ú£f,úK®¿ü±•€?$7¸àÏN]NPÈp!çÚeµtÞ//(ó„”‘zò‚.l^Ðí?¾Ë ºÁTâÀ•PN¸ðù\Ô²ÄtU.¬8.¬Úõucà<mzüŽ ¤¡¸& ”ȹçˆßô¸‰ŠŠ Ü0•FL ¼" &rŸH¶]$(¹P$ ðE‚¼[A‚X"¼P)Iiä ä?P°…‚«®7 z‘àð3Hp@Õb÷Ç â 8É¥A|y.¤£5HlA‚œà n|ÌC „ä"Á õ!´@XA.Tù›_~ÐSâ—,1¹Å.1c!Ò)b G „ˆ—âÒ3nzh™±|—èœZ v'¼´@˜ñ/-Pu¤RL -°ü¢B »µ@/¹´@÷î†Èiê¥æWLàY:ûÐýŸÒ}»ÛK ¤‘0¤@ìÚuI')°SÔ“Ø î†ØY")p|ýýÖ;]¥Òñƒ‘ ˆ=t/p8:„ ˆ,— H„Yv/ÓŠPé PÍHDJâKœß/<{-{313ºDÀIz”¸pCœ$-©€ts‡ ˆ)Â%Ò–: ÃD¡¼CĮ◸1—ÈíêB̉°H0óç: ]ìÒ3f¡fìÔ: sd†ø”8öQÌ™q{”s&sBdîÍ­ÄÏM0'À"UÀœiH¥ ˜3£ë¨æB«&TÀ\èÔ¤ ˜=#qè€6ÃD tÀŒt[¡fŽÒ3àÒsPR Ì\þ“˜ c)æL7'¥@ËÏíâ¥@ûQ8æQ äÎs’¹ývHû÷†˜%*)™JC ÌØŒ+´ÀÜ?HÐŽJ/Ôvà¡òC ÌRþ¨æöýA«¹R`n,È~†˜1)0w&¥ÀÜ?ÂÏQ/cè9•´@U‘˜;•?jÙ—sC ÌT¿$æÁ¨BJYÅB Ìý xÚõ†©Z"ò¯[Ì !0c™!„ÀŒ%„óDˆtÀ<>uÀ<>u@n—:`FDQ耖Ô¦˜'D[ê€Y˜J0cß²Ðó¤êG0û÷$d@Ëüò„jö3¶ÂP×'´Øý(Ê€™«â@l%˜±”*`Frp`^ŒÓ#æÅX>r`FþàÀŒ=XBÌXF̈‰ Ì‹Ú!A0#¶8@0sEA ˜=+8Ð’û%“-‰°90JÀySó#–ôh›~ÝXh7Ú;â¨lk9eëûW¤ëÉyŸä•‘ˆu®¼iŸ•â0Uúå¨?϶–“eŸ~µ¯’HFÆ2%-RÁ•Œ,'ËñW_M±änÊË®¦Pp7õŒ2㻼zÍ’«)”ES,x5µÊ»¡U>›YåÕÈúÈýöïɲö ¿Öÿ¥,k¹ÿq’µgÊúÇIÖZíÿo“¬ýò^?ð:¾×õ^ÿí÷×8»ârÕB[‘AmÝ)ÔØÖU m½j±-åPS[W5µµØÖ]‹m)‹šÚºÒ¨©­¨Å¶îZüµ*Ûº©éGµÐÖ¿’nmÛúõü/–níOÔ¿}Ž¿ Ÿûý~©ÿà þlé/§[Û¶üL²I¸f™Åþ§þõ?~Kƒö#ášýw&\ëÿÆ|kã—|kÿñ}¾µç)–ÉèÇÈt&íOI댪?àû”t®ÆVÿ{ V›1<%³~#f½¡Ž-—zÉY˜yJlÙÐK΢KNÅ–¼}7w”ìo„­7ÔɈ֞l¹Ø·XúEöaz\àSÂ>,^s±mOPâý,1ê5fU:Ú}ú€Ðñ3{Jؘ'žOû°…­d³w§Ú&F^rŽžÛ´%~ku£ÆÄf¨OIëßÌöæW\ÑËöæ×\B³ Îíñ2ØpÏ>°Øc%hc+V{{IK>#Y‰Ï¥¡ Ë€O z° -<%¶´—tÔ±\ê¾*žüi6ûøx¼I­·oÄf£KBƒPe"È:y—Úââ»ßºf&/éÞÉ~¶ñ:%°hÀÒù”ØÚëLo§³…/Mg`¹²)]gIŹlÏ/~½ý风š…ÁÍÙoM_ÌBç7¦³:Ó8²Ó9fe”ìo„L7PÃ@u¼ (V¿„a5£ŠŸj° Ý×€ž’ÞX‚_Ôõ‘Á 'ºÀ@e´¼±Ýù¼-eØù{ø1“]讥X ºÐqÁŽ$^Åû}6kwÅ'½}QÜòSÒü+ÃØÜ§„=àt²ƒ<)¾ý ‚˳·Ðë,––0–¡æ%+%ÿ{Wü½½KÞèâåkäY¼|T°¬ÿן­ÃÉ„¾¬ÞØžbÔo¤§CA\ùÄIxåüX($ªd”ìo8’we'ü‘`gDikü{pýÆ&ôfóò±ßSÒ:Cg+êôöM×’?Ô}²½{”žwaOÄioÝò*|¹ í°›cëF6V sNi}Ãì´½ Ã~äc…Ùßð,9.Úˆø wQÁ1èÂÆ²c¶Ÿ5ÃdqžQYàã³½—ßÌÛ‡:'µû)ñ'g·˜}ª¨c)™Ðð¹ÇvûäÈó?Ô˜ÞJfP%þ´=!¼ÂBÏõ#æÑGÀœ{û†¯i „Ⱦö”°™—m¤öÿy>³µô ©.áìÛ“A[¿Ü’àËÈx%Oþâ)•ÂèJo¶T†*úC²o1ìHG<€5 ÷©ŒÊ.u´b{‰{ܹ oèSÂ@2²’Í.ÕÄç~&ŸÈ^%Ù§@»ðöUÛTuPÂ>øP‘+ûÕSÒKª_q•½òÁ-×YÈúèC]ðdT¼õŸ'õ u؇ê£f¶}ÁP€ ¶ÁàÞÂkdƒ!2ØïM«ðdèÜ­a w¯uI¬þ©Í=¨¼–6}´µô”,ŸÁ‡õìÄ š+K|·±¼ý¼°ìd±§„=€û))ƒ%þ²yö7_ÕÍÞ -÷öþ{TZˆÑ©]بÃ.t¾å}'–´†ŸE;#ùhwüTGž²ûÛ7ŠÌ¶¸ƒ]€‘ö)i%þÑɶ1Øí!Jh–Â/ʾÆôã˜å³8Z“Ÿ’ènñ 2ÁÕø õÑ\÷vÎfd¸>oçl¹…:(©>‹Ûƒa²Ø[ð)a¯Ðö»Uô§dBw÷;lßc8ÀÐí¹}·‡/‰[ɦW 'ZÑ<Í…E“=ñæ¯âs fz|JjgŸJZcnE }¶3Øz×a¦OMòb0H¬…”‰oŸ1}¤•øÈ|[§`§Åù7Wk>›Ä“7¯ºÖœÍ†ÿ4­Ú ÷êÞå\¼‡‰&xiÖ.Þëœ)ˆ÷:g â=Ä4\¼×9ïõ @ðÞàD]¼78Ûï N§Å{ƒ“;ñÞøþÀ=Í…{CpGܜР÷†0µÓØ…ÁŽ ÷øêî ü÷„¾Â½É ‘pïÍz&J²Ó—“õ,Žë͉Y1QÏÐùô¬`Š?ùìIz{ªé1M\Þœœ»‘ô&ü0AzLœ¨7'gŽ= wÒÒ¶&êÍ%êÍE\$êY”õ˜Ž=Po†¨Çlsz±@Ô³’7êÍEš&êÍÍy·£Þ\‚ÊèÃ&Ø%•€ÈÀIÖÊõææëAÖ‹3‘õ®öa“ÀÉz¶á %[xðÞD^ë ½¹dzss8 èÅÂÄŒŒ7é]u€Jf¾óS õ’ÿ λ!ç%‘A/JˆKœ…è%×ë.ÐK\mè%޽Ä_“Xéó.ÖK¢?òRâ"âKE|‰ï•ˆ/q\\Ѭ“¬èÞ#1_"¾Šù’H,}üMæË\ó%þÆÄ|™«Ub¾Ì‘FÌ—ñÒù2ÉYÈ—¹RBä³ÿû@¾Ì‘’È·ÄB>$¾ ó-±Ž˜/û$È·æÈg7u؃hÈ´D%d>æ æ³OZóiKÌ· çT9º@`ÓfþgA T2ßBLG0ßùh9 æ³-”D| ó- ™oκÈ|º<"Ÿ¿x¾UIÝ|«bì¼·*§hä½U¿ýÚ‰{« {« {«’Ò‰{Ñ /×A{«r6EÚ[/aoU¬ öVÅ´®òúqk\?˜‡¬·`~ Ö[•Œ¬·;@Ö³:oÖ[•‘¬§¥BÁÞjœVöVã ì-Ôí­Æ9£ÓžVE{ÜÕ"ho5’ioý =-B ÷ìL(Ø\r$;EpP. ”•Vãs!í-l3´w•tœÔKÚ[?tÒ7íÁv°w5 ØsËÐß/Ø[|@Ú[OŠ´·:Ç‚]`; %æ\ Ú[?I§½„Ú33H´g%¨}((Ø,@ž] ø °·`å Ø[‚FÂÞB*䀽…ö®£€J«ã7å¬Çt{«‹!{fu/(Q|^$Ø[ƒÃao .t‘öÒæí­NŒ$íYÇQÚ[ƒÐÈ ..vË'N{Zaí1Ü5ho ¡po ~ vt`¾qo ¸‰{ìä_ȢķŽuø&¾¥=‰Ù$I|kq>Dâ‹•`ß’Fâ[‹‹ù$¾X&ñ!Æ5€oÁ+À·4Õ%ðažCÚ[]°ÔŶ(’‰óö®“ö6°çû·þý‚½h—°-öp±$=]Aom®»ô˜óÒõtwØ—¬'¾PïÄè Æ¦çþü ÒSb7‘Þi%~å§„朤H‘Þ‰ëA‰“žNä˜'g¿0ñC ¼Óæ%èÓ*ZtB:†T¿§ <+ÁûÊ“±U”g%õ%èYIzQÞi›Ò9 uœòd¢å:^à7sbª 8$º€Nòfáª#!ÏJPàŒgûü¢`<+y3ž4_Œg%/ijè`%¢ßæ{6 ¶9%W%NI×kÐS¬@ïü.л~íê .º€I3@ï *^àt=:pÞi9èYL‰;»Pðkêì(œgÍàÇÎ;}B‰sžÕ6uFà]ç)HDœw¢D^ªž•@|èN½@ïÜ À—ƒÞihå w¢aP'úÀöAK½3i:%)2 w¦0¨1 g þôÎÀ:ìCÁ•¤wΩ-i*ÔWYS!*iES!ô¤wŽBöAK“}àZ @ï4ƒ*\_¤wænú6fsÈ+Ò;ßSp]ta·”έp9( pUÍæ0¾ƒôb.IÒ;/ÀŽ}ÐdM¼JÐÅRRv_R^ã­”×$Â¥;È%åµï%¯‰èØ…&€£%ÔÁä–”×p”òš°R^ ¯¦º€ÐŽ.|Jy>Hy\ˆ—’§™–¤<-²KÊÓAì&³Rò4¡”’·Ä}Tò¸¶J^Ô¡’‡U¸ò¸DH!V*y×CÈÛ y›1 yH„t y›ó y[´H1lójeÞ¤‰U:ÞæLVÞÍÄ)‰Ì›rǼ™8Yƒy3Qۣxx7¯_ÞÍ$_&½›r¹Ê»™¨ •¸~Ö¡ï1‰´èÝLRÙèÝÌœÍÉ»™¤²U$ëüQÞÍü©ç1yàåÝÌ´•É»™‰¥òn–€:y7Ë[Ï‹™7 AUæÍ"•æÍB¬—{³Hwk8Õ;ö¡ÃÚ?Ü›…¿I¹7%˾Y‚ü6ƒ]iÄ *K€ŠZ«¨ŽÖGñ…Ü›•¿¸75Y—{S\%÷¦¼¯roŠ£äÞ¬œw:îGɽ)™ZöÍúÁyá¡Ñ…òáÞÔœ^îÍÊñîÍÊ…¹7 Q2oF•èJ6K(˜ÑùÈoV˜7+ÎdÞ¬¤E™7i&žÑŒÊ3z¸–wSŠ3¼›z2oR–w³Id8± ï&'ÙáÝl4‰Ê¼ÙØ™7¥˼‰Ï/óf“73º°_îÍÆ7îÍ^Í$ç0 ”îM®×†}Së²oê¨ý£²oâ;÷r¡½œ»¼œ2.ÊÁ , œ“‹Ü2p.º!eà\œªÊÀ¹eé$8ñëЗøÙôÉ,$è+?ô<x~E˜Gðãøà§¹ÀO“±]Á~Ńýý$öëäÖäT°™-Ø”Fö›œÇ‹ýí#ö[ŠòSÆßÛÃÉLÂûm b?)Žb¿­È»P%aÇûm¹/NúN þv(‚€?î‡ð·¥±þ˜—ð· Õ‡?nZð§/•àOßDÁß®ôßþ˜É:àoWÒ6áokšLøÛ\GümNœÉ~›F±ßVtÁOC‰ÈowúII~H3à·úFîÛŠ™%÷1‹z€ß–cšàÇd¥~›¦^rŸìââ¾=eÝð¥cAÜ·e£%÷mä>;¤n•_’ïŒ_âx$/iÒDÏv·qLÏ\àK2uQàKŒúÀgǼ>KTˆó@àKêõ½«v`Èë u,I¤¾—4÷¢¾—†ŒšÐ÷€!ïÙŸ 6ö`P¡¾—9"}/ >ê{‰qÌø¬åùY‰¼êž%¾¤# |‰³¾4©{PàKƒ/£ |‰Ë¯øÒçE`N£À—8TKáKº©ð%F”HáKø¶HàKS<] ê˜ÕyÅíìŠ/ò;'G;ý}j*|iÑ)G…/-Ù4£ 0SáKKÊ!>Ã=¾ÄÀg)|‰AØRøÒú~99pqÌšAˆcW3ƒçBÏFÔ€À—6±ƒ_Ú„` |iq=…_Úâ/|I«Hø>Ô½´ù ¨î=%oð;uÞò^\°Ë{iˤ y/:@yO–É{is[Ñô"?+Y¯°=+{’ò^Ú’!ï¥Í1€òÞu.öaKJœ0)±Ý…Ä”øÁKÞKj•ò^çQÞK\$ï%þ6$ï%jÀÔ÷h~º³Ÿ•žú•ê!»fYh#éÎßUçÎ~öQ)‹ìg?ú ÙÏŠe‚wû*¹„¡,r±àÎ3V-ß^»›RÉÕÊ¢)¼šš«¾©©änÊË®¦Pp7Õ ‚¸,¹šBY4Å‚´â!~ÿÕ² ý|¿K/•‘¦LFõÛëœîô{þºy[W~3´õÊo†¶®ZhëU‹mE~3¶uç7c[Q‹mݵØVä7c[w~3¶µØÖ]‹¿ÚÈo†¶^YÐøcZhë_É‚öLùºgtÿ¯”íÖ¿}’¿ £ûý~­ÿà þlé/gA{&ß'ÿÿ³ ­ß² ýÇÿ¹ÏJÏÃOçŸ'_$+½"ÚÛ§Èïƈûܶôžß1⥤´f,QPuE;3‚ªQ²TÍso…$»öYFê @võ»ŒÜ€Œv‡TÆSM-c$ÆêNœglÅê/™‹+¿çAüZz°( :ôy‰s¾ß%¥2*Ô×<ʬ…Q¡% ž<}0.CÉHŒ¡Ä³›c3†Ò—.Ÿïìb ¥¯È”¹&c(ÚÙƒ“¾UVR0¿˜•• ͬRߢYµPoh¦e-gûM^‹×΋e ¥ÃƒYC)ÀŽ™J åSâ²ÖÔ ·?ðµ•AË'¼owF³á%ÙY9À&JŠr€9w>3ºÂ¼»)…ξ»Rh9O—=B«£ÆØ´˜øZÉ3ˆ‡¡uV8J¼{ùÍN»5%åÒò;ZSnïUúšJå*½¯ž×T•LËŸeæ*½Ë 5õÄôZ GueÓj8jàïîN%ÓòQ ¦¥dZ ‡l%Óòµ½šÙþkÎM%~1Ï'™ ÷,©J¦å‹;5·L¥£®dZ8{@p«zR'O¨3×ûï5©õã>ä­dZx %)™–£R-YÉ´|añùø)›–+¢µTù¼Oöuƒô€‡ð|X)=–ÈŽ±p*v!Cr©eBœH8fÑ.àO¥ìA¡ßY¯ÖÔÙ%o´æFEïU-J¦…*¸|KÑäz&,Áõ×®\ZÍô-™ß¯¦Ž%™GM%ÓòQµÖ…c6ZÙhÕÙº¶‰¨¼ 7ŠÉþÙ¨­á ZH]%ì@åï¢E|ôyJ¶„WïvK)šÐΜS®g ¯Gmh¾\;»€tþOIV&*¼16óE¯ð:ôZ('ûP]{ËñzO”^}!ü)Q|d©}èøH=´9YÒÐòÌÑÄ£¶²iù纎tKºÏßÑT`h ¯£‰DÞñÑ”‰ªâ¨ž¨'/lŠÇxƈdZþì{@%©ºÅ³hsà§dwæ7òq¸žegoÏaf(T®ìUû4#E“_Ìd4ÀÎèƽÙáe “ò)Ù”¾ð»œcQúÂo{ÎÉM%Ñ a3ºà¤ºRc‰Ï\êÊJDå+7uhV3ìÓ 5 íÚ§ùôŠ3¯ºØß¹Ú ¶’Lù±ÆÒƒÂÅÌÉ,MøÝ­¥\Z —·;…._…¯›] \7»°ø ²íºP‚NíŠ Æ‹d_fJ|~nû2ãQáó³ûæƒñ Û3¶,Êwø=ï9YRÑò‚J¹°HX÷îô|Äo¶YÄ/¿¥ÍvëZ^â/JKìC”T¤Óòëk‰ûùB^³ïr¾ïy³ï2ú‚•ÛK<%Ñœ%®5¶JÍvêB‡ÜçÐl§.<& ›íÔ…Çä»ÙN]èÐD ;ÐЮwàˆ­%XhâBn³Ïrfé·.O©¬ç^ƒ‚$[Ž>œ÷³•Ô¨GúBx+Y ¥×Z)!Q¢¤f>%á›íÔµ_Oáù0{·}ll¥KdÝ8ÓX씫B­ÌÉN±Ý5(»úÈü°¼TV·ìpÝçå¯ìCÆû)Ö¶1ÊÑú3¡Ýð×Êþ€?èVÁ~Œ] ö ^ÚÞa£Ù±`Á~‚ý(9ûqöcÒí`¿(!ûq¬#û16Œìÿì%d?f1ö‹°ßU= UF H Üt•œ˜¤Mè ¿ÉøRŸ‹ü&ƒ]E~×1À¦«ÈOÙàD~“2›È/ê¬èA}£ßUlŠ¢ŸÕ¢ý®’ž_ç^WÐnôí›”ÁNèwµ ô›ŒáúMDûˆü”©]ä§"ùM†[Šü®: ?+³ò»Úù]­üèÂŽ.´7ù©ŽÈo2ôTä§s‰üÔq‘Ÿ®Xä§s‰ü®£ÀMºfßÕ ÐﺠßÕÊÕ?S¾úàuˆ~q&¢ßUèç"ú]u®>¯>àì§«¹^÷ìwÕàv3:Ù/ÎT®> ØiBŠú]ý®°ßÕ Øïªsu-«  Ã5ßÿì§K!úÅ!d¿8MëG35:Ðh`§«Øi2P^ðO—ðw ðw]»À3íñjƒð5HÑé/ÎCú‹ëmÑ\o‹´7ý]u@NW; ?ÝbÂßuÉûÝH.àD„¿«N©"ü]uWÀßU'ºÀ:Ñ…ø»ê¬{­àOÝtö‹?£èõˆàA‘ý¢ßd¿h¦§.‘ýârÉ~WèOpІÁMÑ#¢_4ãèýâzgô3£l¥k-œíôýÑ)²ßu5SÙQyÔÕ…7û©SD¿h†è—ìèý®MËùý~Wè:Nö»Zžó£Sd¿¸àÝ?ú´¯.xAô £¤”>9ùÅyH~Wž>úDò‹ì«oò»ÚYãcä#ùñ‚~ª"ð‹*Ѱ@ª¯¸OW+îÓÕŠû®ÓŒõúñˆû®f®ËG3»¿’ÈOÍüt_~Q¥æåö¾Ü|uçéûõ-"öÝUæ|÷Ôwu:_׈º®¸–ë»G¤¾h†ÔO€ÔwÕééÕÈuý8ÏXï׎Ðw7²Æ»K`¾«Š´~5S¯8ÛÖü•thÂ>“YÖ…}‹&A`Ÿ¶Å}kŠÎÀ}k’0È}‹K=â¾…}ƒûÖ¤œCî»J¨˜1+ˆ¸Oaâ>+ÕûÖÄZ3¸oM’ªsŸv÷-z§Å}kJ7÷I)Òühp ÍOªåˆà(i~\¿ÍOGIóãrUh~Q‡}xƒßB*õPü°?ó¥ø©ORü&VmBñ‹*~Kâ]ô€\=Àó–ä7±f’ߤ¬%Éo’^!ù1‘vH~“:æŠ>àä7?¹oM*’Tü¦´»¤=s¨±Qñ›"¸èµºPˈ¡–ár¤øé’¡øq/šPü&\·¡øé¥ÞŸ]à‡Ç{ë}Œ—µwª„ÜG.:@I0:Ð>ä¾I!Ar_´3öýk ½o~BŸºzÝ¡÷éLÒûx;Cïão7ô>¦› ½OçÊчI Üïß oÑ© è»þôÅÝ"ôéA úô›ô-®“ùâ‚¥÷ñG&è‹§Iè»êPð‹v¢ P(Šºp ~}‹éÈD}Ñ©/nyýу=¾™âr }zÉ|W»`>+A»`>ňù®3ïñ: ™/™O'&òÅÛ@ä Ù»ÅõÏ·àÇVħ1CÄŸÄw] /îoS Eðs"òÙ™PÀO’Èw“È÷ŠÈ§;Ñ£ PˆúÕÐÜœ*A3Kihxò R!º¥÷ÓÑ…ýÖûâž“ùìb¾¸¡„¾è&¡ïjÐwëêÃú®:;ÂÁPI©tвS_´Bê‹·„Ô×Gê[oäÓkDâ‹g@â‹;Nâ‹«qýhwDSŠø4Õñ)-ˆ/ÞEŸ&"¾¸-$>thÅõc!î©‹¤½è"iO“á^\˾®ÿ­ôE;ä½èµó^\-yïªÑc*GÜ´žàÅÛWPgÎÏS¼ää=•øx+Ä{ê‚€Oo €OöŸnƒ€OIÀwÕšÉAKWÞÄÇC¶æ@ Bpi1¯¤xOý!îé•ïÅMpÞ»¹®ÿÍ{zH>\iOv!á^ÜHâžž¢pOážÆcñž¦â=ý¨Å{œ}÷ C¼w• Í€pÎ÷LU¼wÕÙ1zßâäPÀ·¸Á«€oaë·ÿ,+Z@Þ±É\Ç|„<æ<Ècp@žäAž AžÜm‚¼0ˆ.¥¨°zn¥¨ÂQ‚<Æ¥ä ™)‹’lÑêIPm·¸wÑ•   ÈãRE@ž®N%Ñ^/{Ð~;‡P++ÉKyM2\U’­7ä5Ù8£ðle¨ouoq¦ ¼(Y‘d '"å1¿iPžÜ¾+ºðiìd²® <.åцHÊcVt±³«„#2²OËb<ÙŒÅxŒA Æ?\<·o€«/O'I1<‹Nx:Ž O'nïåéüiéDIX:1â /ÃÒé?Œ`¼0yFpPô`è’R¡QéÛò©¢dàïñaéä£Äãï Oíæè¬B<]O- ñ†P‘ˆÇݲñ¢Nôa¼u½ëzæëYâñÙâ銅xz0%úp㌧s‰ñt}b¼¨CÆÓ½(Ñžë£`¼¸^2ÞŠ‘ñBm#ãÉr&ÆcÊî`<­ òÔA^—!“”Çq.(OW,Ê‹ëY¯W§‡-ÈÓå òÆ'äu!!OoZ»®ÿòB³#"…ÒGD ÑŽ”§(/”GvçîW¼€„D'£/„µZÞ_£`<™ÅxWÉgzô€WC@Ò{&Èã‡$ KÁ„<]͈.Œ·°§9A@?>yò® òÔA^œk(W*Š>°„¤ßŠ Ogä©W€<½l‚<{FX'úÀVzúè•@OW#Ћvzz#çÕ´ü£"=¤œ Ð y­ÔW#= t½(¹ºð–öâEëéæöâòÖøøQ öôºíÏ.ìèî„XOw ¬§S‹õÔHׄŽû=G Ò‹V¦&Ct‹®ñ1Ήô¤ºˆô¤„ õBÉ‹ð(ö€Ç´×C ÔãÕêECÓ9–\=@;WD{¼›A{œLíé(á^”TMçX¢>|àÞ‰³ï^ ÷x‡ƒøø¤‚øâLWNA‰.|Ÿ.GÀ§Ëðér|ÑNO÷ÄÇŒõY25!b++ÂtP²5!/[g|:‚ø¤&ŠøšÿÿJ†´ÛÙ9o‰oÊœ¨°>82›6J…¢"g'Õ&;£–dì\Ÿìg[i~;7Õ;Äì—Ä[d¿ôƒý˜(ˆì—e·d@%6jXB?æ\ ô+J¢_•£”èW¥Gý*ÑDèÇÌû~Ü6îF?p“Я©¢´0¡_ =/ñó‹*§N¿(ÉÓ³ ?ùooòƒ\v‘߇¾Çp/òÃQA~ Ø }¯ß¾N-ùÝúž¿ýýZ ø[Ò ÉN[×Gø[Œ(üéuü-’»Àýkþ6âl‚þúIúSôèo3%•èO¹\ETõöuZê4”€”¹5ðo ›ŸÂ?; òú°™2Kü·¹‰¨øÏ®í€vQ;ƒCòÿYüÚÿYðZaøKÿÙÝzû:7S‡ˆÿ,l ”þ³3þ³,zàHö¡|C›‹.Ðèñpû¶uZTšþY 4?†ô)L!}UhÇ.p?ŽécæVáŸRÂFL_å\J1}Uèü³<§^À.0—CúâïÅì}h”!}Ø„*"úìÒÇØékÂA^?óFL_ãõ+¦!Ó×eâdL_ 2¦1Œéëo[çîRâÇ@ÛêShÖÔñ@A}Šº‚ú¼£ ¾Ê;¡ ¾ÊWø ê+(‰ >b$ð/ž-‚ú¸ÃgõARc4\çê…"úœ}AdŒèSð–"ú¸|DôÑž} SDŸVn®ˆ>Œ>ŠèSÀ"úÔŠ"úB-Çÿæî]vnG’d½¹ž"‡U€:E27šJPpÐz¤B«! ß_anfÁ½³²²ú´ áŒrÿ‘\\‹·`|næîûú}v팾üyGFßûUøf·AÓ}~µìŒ>¿8vF_WÆÎès(}gôyÇJèKÿA&ôu‡<2£ïõ’}yŽŒ>ëw;®~5>·FœÑ—yv™Ñ—"Y߇P¿"ßLé*3ú¼ZsFßp²hfôÜÂ}™üvdô=_OSgæó=y63ÏÉP;/ó3/úHç«?¥ó‰w:Ÿì™o–Õóv¤óéòg:_ºV2oìl8÷Èt8é¹™Îçó»ÓùF*kNçË4°kƒ·)ª´yè—Õ9w:ßЛg§ó9¯hçó¥täó‰9÷Ô¯Î7ÝuôLè›â±;KŽm³ú.I;¡ï¿}D¿sdú˜ìýlY5Õú¡óùö ü¦}7;ŸoUM~Óµ’üfJ†gBv>ßóC>_w¢ ÓùŠ\›GF¢>²ÓùL˜â¾éŠ!É}s¦×S܇/’®'îó!ô8¨´Óù¦+cïúh(¤uT‹Z\×¢Z\Žü5·9ë£ý°ÑþØ®öó§þúhu½¿åÃrä(¦±]]Èg%²:®û[Ô,GÎ]qìØ•Î]µ…°¿ÖÏQ{䨕Æö®<ðŸ_Ô¬âÊÞߢf¿SF %wŸŸÊ<ý´ÁïÔ:û¡úØÏwÏ;ïû¸wþò›·J”µþn¥=UۧOM1íéØF{úÖ'ÓžŽšb±§³¢˜÷´·ñž>ÕÉ´§£¢Xìé¬'æ=ím¼§Om2= G=1ìéSsÌÐÞF{úÕ{;Wçÿ-•ûsÕ_~œw~cfúËoÞ·?ÌV¿}ãþ´§¼äØ;"yüÿç%Çþí7JŽýÛ¸äØbÅŸJŽaìßó_ÿüc.9VÚß)9öâ­ÁËÔülùåÁ@Óº//¼™N3Wug»ðÏ7s]´6˜5s]duš­ºš˜jÌ®\Þ9ŠC‘rù̩ףl½®ÛÖšÉ[!¹K<ââ­‘éhPá@É5y²^o®‰´×š%¸b«WSéTWݯWg”W½92Ô%Úí8ê5ÙbùQW¤z_¬Âþ¸£T½o6‰.îBRïM¢_W-[³ÄZRp·7 W Z|Ë:òëWÒáUïÊ8ÍÚ¦±ÄA·‹ªÞ%†kDÔ{°ÄA²U½y#ÛOׇÇ0‡àêsGph”K+ç5Ñ!ÈÕ&þ¬yUž˺Ñ£«Ï˺Fiü1a¢<ðÃC˜A1Ð#64KÉoÞšÅ,ê3#¼5 7µ\ÛBØðP ~T—÷Hüü™kjyF¼u/•][^°èÓÌï傪\eŠ@Öì€ØV¹ªI¦.Ô^T®~‹wk‰ß¿~€|¦µàð1àþ=µ ¸Fnßœï¯Í ž¨¥‚×Èën¯k$^¶w—¥®¾üýëUé#zKl `v}ßµ‡çÉSðVÄ ®=Çõmˆl­7¨|w®‘7?ÅŸÿD›€à¯Ö ‹ úºÙyÝ\®VôÅ6y¢Ö]‡z¢ü| <ˆk•'¯u:®~_Å”÷É¿c–Roßÿµ!&å|‡F:âZç¼é3Q ·”iÃ~­pbÄujã 2ºöÜxxÝ™1‚.<¤ö ,TÞöz.k¥ÇÒj]5M2íE\«<íR„dýdì¥;$U›Žáv «¶Ž°PyQMû†¥^ª¾V#Œ»ôjô|X#·‹Ö¨$½Fšý†k$K]baí<„uÚD­µ—×i«×Ed«,(P(®öŠÈVAmtƺꚥÖ!·/®‡°ÅSL×!D!"î¼vb׫¨£D§n3Púz¸X-oøHÀ ä RáRô¨ñ^tÝÁÄ|k›bH!ó=#½+b¾mŒ^Á|ôI­@ }ò`, /p_s ï‰tÅ Ô¯îý,è{be­‘€¾µ96Ä|ðù #ó­Ýø½%æ{ iòý"æ{¦³ÂÌ|4Ð@ðÒEóþ ôKÝD¾°#Mù®çMp$ò]÷È-ÈKA—Ö©•¡™ï:è̇ᆘ ]'1‚B5"ßµ:áB>®U#D¾ûúðÞ}%»÷®™1áÞ}9uȸ‡•¶n<ñÞÕòu Þ»o‡*Í{˜2ïňм‡x¹È?J[¼w?†óÚáu톼}Uç7xï®.¦mà‹9õ|˜wu¾{Ø®càƒ/ªƒ—nØ_4Bà{Ö¤¬W‚€N)]1_—<†çu¼Jȇy—6!/=˜·@¾gÝz:{B¾çiIfD>‚ÖÕB¾ˆô7Ä!<ãJ$0=ÑÉî¯ùð{µòÅŽxD>(Â]8§CÀÓ®/×!LQ"éYëM­Í‚÷žxYÿuãÞƒ5ŽFÈ{`­bÅ{òEfúùÈÕበ:fñ^)I£B>ôî}…sD¾õ"ñ‚^ÈX1(òÊÓü‹qåv¯Z_¹íc4ñ=–U“øÖí«yßÈoØýA>p“ÖûB>|±˜@ÈŽ2}iß܆ÈWªÂ}&¾² @<'â+iB&ñ´€ÒßÀ%ü’ˆ¶9oAâ+ëfˆøJ*&¾Rýj0ñÁ$÷ˆ5uÃ¥ÞM|xS›‰Keª«§‰­û‡øÞÛEÆI|áwû^¨U[–ЖQà+â{ÑóC|h–xé›H|ïë·¤‰ÁG èà?ú_Áœ­/'.EÿIŽøpnš¨‹À‡ÎÒzø`’Ðåð­_£éËÀ‡müònX]_½üÊ3ña`´$ña• _,â«A ÝÄ÷¢ÿùÖRRB‰‘o­?äé3ò­•„9ñ‰ 6ñÕו”L|øuz¶E|o-É€$¾÷µ•ÙÈ÷^{"_ÑÄ)ÞÑx`ÞC V;ïE”zø¯,f䋪Î'ò ûNÞ.Kœ¼7½òLÞ›ÎKOÞC)r}J¼7Ý!4y/}J½-ž÷¢¸¶ ‘¸}„%§÷Ðæ¹ÒÄ4q†pbšØŽGÐ×ê‡öNMnK{ZƒÚÞЧ¶¶÷|xow–MmïJ¹!o¦ä&X‚WJ@%q "0Ľ[’ä½[‘ĽÛù‰{0£K’*Ýf÷{J£>iO cÓÞ“Ëý¤=ušÞ°ç6Í {X{H·*=#•¼€½'c÷†½âxSÂ^É%£a¯Øïž°.⿬ýövOØ{2šoÚ9|Ä=Œ”/íÅÝó×öŠ[c öö1 öðï„°‡m´íÅŠYûÕ!<îzkÚ‹³¥²[gK´ÝÍÍvì‘SÞ‹EýE{9ô=n¡½¼Ú‡8ÑF¤Ýˆöâ{Ä™¤=äµèŽí<ë›uÃo-Ó¾:nѲaLr¤½žiŒ¦=ŒH“íaÏzRƒöðÝæÊÚ>‚¶h¯»j¾a¯c^Ô×ö!Úa=ß*ìaIJ›~›>"Á|ƺn¢½Þ¼îíň6!ìõæ1{¾¨¢J@{ûësæ`{å–ao­jíàìň°·FòÖë:„ê,¢½§›„´# ö4ëí'ðň@‡ÄW­Þ˜ø®f [Àw½ù„ø®fP£õ–áï•?§¾·Vÿîh!Þ{Ð W·aí9`)R–ú |øÐãDà[#éÊð=#sô||Ú iøžÑ”M"Þ ×ƒØ˜¼·Ð¢'b,­ [â½5’z)yï‰Ø;xá·8qibü3Hiýyûäöœ±kÃ^Ħ4QöÖˆc‚½q]F;þþ˳½`ïO^qlÂÞ×綠't*qÛËîÐÓï4ÓÞÕJî™´w­gn|h/,+ÿÂù0£%*‰/Â4à[÷Õ•R\_Äê |‘¦Å‰9l§Â·FÞ ƒøÖ}eEZÄ·F,¢Šø"4ÖOâ[wZ5ÔùÖß©RùâÎ+¹X=¬û¬ëò­‘ê‹@ä‹[O4Dä{ ×ôùÖˆûØ£‹›ñÖ§‚˜âfÔ %ò=x¬<Ì ‰‚j2_ÜŸZÏ—8†Ç7_0ßú;ŠÌ·Fžä°`¾¸aß“ùÂw$’ó]Žîù.ôüˆ|Wwç)#ßµ©iǦëÙŸ"ó]·SkÄ|ëÎzµ| æ[÷Õµ0±Gó\ÓIq“Ì·Fü\Šù¾;U_Ì÷`xõÝÁ|kÄQnA_Lj턾5¢?'MN—3HE|‘º)ý“Ä÷ D4ˆ/îÄë$¾H •ØIâ‹ ò‡ø8¢½T†½›}-"¾­ÐýMA|ëþL¥•Äìq"ßÑì2à)ìíEƒïÂ(X»õÖ³ Þ[¸6šy¯dWwóFæ‡÷žÅÏþ^òÞó$F÷ðì6mBÜÃb]÷‡ˆ³Ëø(|W¶éKŸvSªòß+-¶)ï_aϲA¯&²ôn§¨$è¹1ݽ™!A u‹èõ«¤ÔgÒ³)r“ž—¼›ôœ´IÏ©­&½GPdлýNIÒ[÷»JIz¹tJÒ» ½X )%ìM7QJeoÇß-í!Ró‘öpà—äµMzϤçGŤ—ÒzZ''ëÙY’¬·ÞÛzK›õÖkæÖ{ÒHdØ+N¼Ý°÷&EöÒl–´÷š`RÚ»|T)í¥4"i/ãÞI{VF {o^]ÃÞ«–gÉz°æi‘R½½‰Xóƒö+Ök·¾È¨‡ þ+ìĺFøûq‚4"N‚Y#ÁIÃG²²úÅqb½é !Yo:𕬘8œ!êî³²wÙ1‘ÊH^Ô&eïIeRöîÔ¬ì=)=RÙCœöÊÞ“’§•½u_I)·²w¥#׬×R1ëÕ Ò˜õjšÍz5}¥f½5‹þÀzkú×ï5ëaÑ÷e½–±²^s‘V±^S-’õ¾Â^`›¾Ø¬÷øCb=¸>ÂRA±^h´ÖCæ§Å?‚Vä§°o`±\,úLmTl­âñ°üRõbÑ&‚$ê h·D=¸yôìõà$‘ôF¿Ó¦©è=™MÐ]Ϥ7ªu“^”ÐW‘ôFÖR Ò{vªI¥ëæüÞZ—4Ïh]˜”å9õ®í¸êݶ¤%êÕ4Ýõjº?õÌI&½M¢"½ÙJŽô ìÊ­¤7{b¼Hi²æNêmýRö€Gºº"½ÙŸÔèHJ@³²·Ö9ÉIÙÎljzåÚo){^±ú.‘®»ÈS¤„3¡OBÝÙ6RJ{×ãürK{±PÙ»p¤¯QÙƒ­Œ”=ÏF{3ûPZÚÞ'ì­ •*ÂÞƒåŒVš„=šÿ9@Pš·\:B½ÇSQ¢ÞsmëæÅµ©“ ÌzQöDü%\m5•;‘R?¥½ðQ zX ·zØæ9Ýœñ€ùçôœ$!Ðën—gÐ _½Œ¬%èmG¨AoÔÜF?ÕxN;gìGÀ —…’ô¦õ½ù¦²HÐÃ%±úHЋ,óô…X× ÐÃÓoáN”ôÜi±$èÁ¡s'Л[‚ Î #E;ÝœkäâŸüõ3“{EyÁkº1MyWÏSÞ•žK*{xnÌpPöÀó¤<ú3¤õQ»žtòJÙó¥+)e/ÒE8@aïü…=¬tm¨®e!T‡PnØUT•źޅR]Ñ8qtèzW{’étu3`­„ÚÇÉÛp€tÁiǪz°QèÖ”ªw¿1YÕ»áSÓ7ñâ±”Pv)—åñc!Yµmì’õî’7t=ä¿èBŠó¶þ~œœ÷“Îcq^ØVÎëuÅ’½Û¦CgHÎêúÇ+Šm7ç|¾Ð—éù }¯î¸„¾áÖ‘µçÔútsöÌì³›s¸›®Õ½¬–nÎáHÝNÜ«‰NÜ›™—'7çL³ Ýœ3×:¦>P–@QÔwÙ²½©/ר—‰ÉOlê{%W’Ö÷Þ;ô½êTÔ÷°þ”*(bêN54ô­Sa÷¦ õ!$ôe¡˜ÑÑúIÝÃJÜÉ|<¤ÊÉZ(æ‹¥˜FHLX«ØªIæë ×ó!Ø(²óa)¢Õ£˜…·RÏcîTôOêÞÌǂ̇[ôFæ›Ýµs }˜±E섾X<<§sMpwæ÷1ù ‘¸û”ø Ö »û"~gäÅ)ãr±¯Üåö•;_TNß»ßÌtdþÞ_ro2ï¾{¢"ó÷îÃÊß‹¹‰Jß«Uwþ^O Íù{]Vçï=¸­Oè+Ï}H~1çáZèÎR_\A[ ?W*Ìà[·QýfðÁzBýP§3¢_Æ@eðͼJáƒËCh«¾òÍß[[³˜¾[Ðéä,¥µ$@¦ï­U\ søù/’ÖŽô=÷®øÊ=f&ô1}/’ìNà+ï툫Ó÷`rÓlàô½Ö2¡O¿ÿ¾ýfïmÊì½ë+' v6j2{ ë20{o‡ då|Ÿú&eïÍ7¹‘ÒNzù¤ïųq"ߺ²¯²r¢x–0Üé{õÍO)}>Wi‚4C®cñ!/g9@¥ï¥@uoMI¾PNßÃ<öCúÞLó©ò÷FŠÍòsÖ™9«òs"ÇO æô½LØtúÞ“Fmù9‘oh TþÛùoÎßÛïù9kwýuåï­)Ä’ ø`ŽÐ5¶œE§¾»¦¥’È„³n‡'óßö'Å~ε&LS_µ½-søjªËÎá+ozG•×[þ%ÀeÚœrøî‘\¨¾â¸ © p¶xê.»Ö3‡ïí‰tÊ€Û`å$¾±½™Jâ»Òå$>d}{I|Ç~”Ä÷fT˜:Ãé Ì£«)²äêD4vx$\HR09‹ïNƒæÎâ*Ž7íF‰|%}Nä[ÛÜ?$ò]N•r"_ߌ‡p¥Œ‰|Ãi5™Èw¹¾^&òN¯ «Â&NÀZÄ8ýÏ™|-sòœÉg†«³¯Wã8ɯ ø:>¶NX$d:‘oä+H‹Cx2?L‰|).:‘9½§ÄWb…õMä~eYâƒR¬»È‰|ÍRk|ˆé꾒ƇO½úëQ¼Ã™|—3Sȇ”LÉuqÝÆûLä»]¤Ïð‡3®µ¿à'F·§àiœ6’þpÊE•ÊãKó[æñ­wª°Íy|°gè‘Ê˰wù˜ XÊヸ"D¼ãºå ì<¾'Æy|—#k™Èw_‰•Jƒ{’ôÈ÷ø5`Dy‰ëcëÄï“á¹îc0rž°ˆ~?ËjA"°gÉ2`ÏŒ“LåK=ƈG×VOî’òú ¶`H„ó§è›€ˆëÛ‰ê:FÓO‡°£’Ë­Ã+˜?J‹­×ùZ­Œ_Öb`áÝúWèú5fÿ¿é«ƒ[ìí÷¿õ™?^Qìûkò¯èSÁrO?îoµ–´’Ã×áÅzÜ¿2ÿ:öã±½Ÿ9÷f÷ïÉ¿ÎýhìØGŽýkþëØÇö~räØÏNA²õ ¼pÆ JÅà©îTÈþ÷Ÿªª=‘…ÅøÏçZ§z–,BõÓç?ñ>yîܶÏÜïúçõÃ?QPªfý î侯‰‰÷ä_~ºáëêùýÙ‘çø¼GÎ}ì­¼Ÿs+ï ‘Ì{_9÷µ·ò¾Î­r_8ç¾4òÙWn•û:¶ÚwüÿoïË#ç¾öVÞ×¹Õ½g¢²ÉšÞ¢8ü·PY; •¹´XÞ#í‡ ]‚¬}K•ýÍí~(Uö·¶û±TÙOÛýF©²ß›û~k¦ùy¶ûËߘ±Î-þÞŒù»×¯ê³.Jõ¬ý ”›O. ‚ÁvÐþôËŸ!j¬…÷Ÿþ§?ÿŒJ#£m=Ãx)Ô÷Oÿcîÿý¯ÆÊòžGÿçúʵ~X ÆKpÿòOø‰ÏàM.Z´û_Ö¶¿>kîøÓÿüçk—÷ýÓÿºÈÿ–ÿûGM±µ®¨úKþëȯü?ÖvÈÒ¿êŸþ¯üÿ÷ŸQ«q¡òŸþåÏÿe¼¯=üÃUßpD¨+ö„s±œUßÖAUßð¯É¹Û{üë¿äÿuÍ·çóOÿÿþG«¾aÓ£ê[ËÁÍý[þ맪oÜûQÕ·YÞ<²þsÕ·5öïù¯þ±¬úvÿ~շв5kqŠ´’ukhªz¯Æ‘P'ÁÜxÎ1ò„½Ðl-㡊m×t@~¨EÔ<Ý_ŽŒX¶®õûâA|î ,ÕÖùW<%©tk½ù W,°LVƒ#oP ˜òn#Ff¨Õ07=k‡'û E›µXÖ7wÜ·±M” ~b„M-Wõ§֒3UE“0pE”2ì1½ÅȈå{àáZÚcåZ‚éácYË/k ,ˆR*O‹‘7V’=œbør8Šc?ýŠ3‹ÃˆUbTNÁŽÑÄ=>dÔb¤Ç²«Ùòb›çì¯ÿJ“¼»A”?N‘º~|Ä;b! X<¾FàíÀžª¿ ¬‘J|Ãy#‰¢Br Þ€¥#–?¯N ŠvÌXèÅðûŸò â5%.-¤Í{­nqïÔ¸g"M| ;Õ¸˜Õ ñ=(‹RyøqΑ¶ÈIg #3.T„ž| âNÒ»ŒÿR]]zÂÞ7g ÔðuÃAÙ¾Š+ ö]ÌËï•8å¨ð6þ­³ók‹y~®ƒÀ#ÐP€ö~/œŠ6(j™øÒu¡Û…ª: 0¥¯;¨ÁÍ ÂÚëÀÈ$ºB\ÏB4Oa(ã*QÓ>RýõFBAÄ‹6¹hjÐ3ˆÉW‹Ä ±º‰ya€¿yã¯è ±^Þ ~Uú5¢hHC¦ ׌Êtˆ5"æë¢,NˆÅX÷ÃÎÇÖ=!.þä{Ä¢°;z!ö½ÎJÓ=†‘¦"ÄÎn}Ózñì¿ÄŸǰŽ­1~‡uœˆºk?#‚@(èt3Ìt³juƒ…F\®TdH†×Ÿ;|ŽQk—'h®EÝ—ørÄ~ñèËgÈ^gsg24í£>Ÿ¼;R©×q6GÁžÆéw¿û‡Ff,6Q”hÛ‹JbœÜЛ‹OlñЊS®¨ ¥¸Ô##<ÛXZê‘^»&£ÀLõÄ`†6j˜èÊ¡ÊÝúYÑaVMFÖà^¶­”Ú›_q7-Rp#Ðï#Þ ~U;ƒå~¢JVqGp†EÑ)-â’ þ¹tŸ›‰Ä87ç}¡ç€Á•GyÆú ì’·J•CBycDùÖ(çµÏ8@?~,‘“µEÅïPÿT¢¦G—Œ^ƒwDinÕþ×h$‰„RW®èc—e·T!\ÄÌïfIë×5€¤_çnLà‘-÷ºÂb[‘ë®aèÞ"—KF°#cº2”,TG± 1m 7#r+#ÏMö¢0‡#šp]¥"°‰øý­|Ó;:~Àd©Ë p74NÝå"HG g%CÖFˆ¿997Œ= uºD)Dev‰WulRdúèa`Â~»Tò’2”}áÄU^ê"t×tL°ûlãÈTxU×õ¼âÄ®ƒŒ"wóF\ bh¨A£}ùCÌrMÞ±ÆÒ#–ƒ/Zw=oòN%=bvÚïs¼ÇõóØDMjèÛÔq:×øOômšqP•' }›ÖôÃ!߈7Ò$Öä#| ¢²^Ö—b}Òøt@@^³÷¸, "UfÍ;ø*MxC¯™WA¼¡×WDªÏ ÞÐë!… • »­›ÖìuÛ¨»Ìè …kg€&Ÿõ¥Q;-îô›Ö-MýÒȦà°Ç{þAç¦õFFTÐåÓÌš¾Áä¼ð\Ñ@ Y+½sœñU3Þ‡^Ͼjh&{.VðB›¯—çb‘ã(×3øsF¨ÁØs¹ùU3:tãþzBP|¢u¾Åb´nZ3BX‹¿Ÿ¨ö3ê!1¶þµk^Üo×õ-Q† ~-:D¬ÉÛpöyÀÞ=·“FáNxôSñ^^“7$3]¼—×¥€‘•·çƒ¦MëÖE:Ç7ãƒR$/oOš6­­ æêAÓ¦ÓëUŒ ïÔú.ü~×Ãð(Ü­¯¶©‘3/D‹7þƒ‚ ëY„“ÎmZ  {«¾=ºg¡$—‚^Í7Ïå]ù¡y¦È.áL÷ sfïè`ç%(^|Õú 1Õ=èÜ´>u¿¯Dï¬áŠÚ6­ÉË妕m›Öí¿nr'5RBྛ•#-ú–Dz!o4¼š×7`IM^pÔ"’+ã#¬ÜŸò#F˜ù࿸AOü‹×èA%ù“þâŒnø[ñÄoøëZ„þzÕ kÝÔ¿ð‡R%øCå¥xÅ'üá-‹æ„¿P¿ƒì 8¯1Ëþ’<þš "á/¸÷X9År'á«Áx]oø#2ðwiJHøCM‰ØMÂß%8Øðw ¦7üɬžì‡ÅcÜÉ~ýÖŠ(Ù3ŸÙµwú‡ýÂ'Üfö[ÏËEØþuω]þ­¤?èTñ`&ýÁ¯‰¤?°svA!)á˜&Â#BÍÕJNˆ±!›û=!;Öb]xnC ¬QI‰„G Ä6þrR ¾J D,è–mˆ‘î™A™å À¸O DiÊ/I ÄH³ -(°Å'#XP ¨íqᇀ;lÓŠ‹àýÚb ºÂy``»ºË âoÅDÇ/çŽb¤º$tP`‹ÌY*‚»¶ #¾5N l7ž—[bäÉWp Š«+¾%¤ЬHħô”[<µñ! v#$âXLl$AŒ˜ûH‚±¢!A»Qpƒ$ˆÐ^“ >Ã5 I#|¯˜ñ)ÎnA ˆ}‚p¥ÍÂ58»"f7DgÁ†¦8‚ >e4$Âs6è bä*'">È_LÄ|½›±…b"âÀaüHˆ’\ ›[ Žˆˆ%a`tƒæ½/ lWÌæ@„&o&9ÛÅÌ1Â7¬8&K…³ÄØæáq’ϬåäÀpf’BĈpR}0âS\n˜ô¼ï“;}çÁøP!5‰ñU\å ±mŒøn­é…؆qc`‹ Ï_L ÄWÕÆ@<¤|¦ #ñ]µãƒØæª=Â`‹"¼A*‚Á؆‹c¯…ßL„q¦jdADvyï›æãk 7,¹Š(ˆ*ü iQ…Ÿ“‰QÛðcÄW‰´„‚s1bŒž ýDÁØÏ øãÛyЉ‚p[¶ÆÝ21_~ˆ(ˆiP‘¡ ¢Ó|Çñ)Q§P#|ªÄ‚èQ@)Ë0ˆ"½X0x½Å‚áâÒ,ˆýí—,±ò—#dÁp•ªQÞ.—8©=°[˜HDjH|e!„'òžˆ0ºæà<&baK¦DB´}9.‘ŽHÊŠ@B,SãÖH$rr%™wܲ±‰Ù/ÜÆ@ˆ‘X|$Ž¢x™õ{)Èsi”@6› óWŒq~xç! ñýe Ä6 à ñV‰ËgÄ ƒÓ’y0œnñ€&Nk´ „³ê„C‹¥·0G±ga,Obk ŒåI?Å@|hF¼ÖDˆÕÑ&ÂãSBB,—â1Æ’%ÞÁ&½Œ0ÆJ(Ga¸òã!1bYSȈ"BœcNx&B,b¸€JAyEã#"=!¦Òì/~A$•pÄ‚à·3)M‚ Žæ=‰ߥ8¿ÁÇÊg ‚ïÖñJz?z ãHi”'³ÔHëÎ#µɾü&ÉøhTrà•xËðØ($>~zS|,ù¦ˆe1× ÖqšÒo{·¹… mË8LžQ˺7âç𠬮U±ŸÔÀðŽȤB}>r æ&.&%¢;W1–óH902¾¹ÉÏeÈz ²y Ö‘ìªýP¼í@HAðu”õÀè d ‚¯•ù×d_$JD–ϱAdlªC·AL¸nôMEÔó\Š Þ–\#[ÄAx¶$ˆ HíG’ 2xx­BÄ2Š«VÁ`hÄê1,Ä'ÝQ¬ž’ Ô^:Dƒr¥#Š«ƒä¦Al£¥£i0²ç˜Ö(l©ƒ˜‘Ó6\,&–µ)Š—4ˆRÆÂ8Ò õ´‰h^>'e‘ñ!×­ ®+üf1y/%ªqDƒë÷SŒ•¬r‰Dƒx“ºXy0«!±tv¹1â`ÔÐsѯXJ Ú6]V+–ÑòƒƒÑ9ОñÀÁ6…ƒÍ ÎÄAäÈ_-„|O† B•QÚi0vÊ‚qþxà¦ÁwS›håð(èšû£)Ç4ˆÒVŒ„ˆ‘&_¤’q{s‚1 ft0i¹@óÔ[$(|pM©yW‰¤Á8Ø_ùŒÑà®|p°:ÑÑ4ˆfÌGHÌ ži?E(õ ‹’ã­ûAÁî—‡I0*"ÅÉ4 b&à}/DÖ-;‰‚Õö DÁH‹&Ÿ c©ôAAD•ûÇ´wÄ(ˆ‰œå‚¨› (ˆÄNFAôi4¡`:/_Ghq‘…‹DÁ¸ É%DÁ(‚EK(Øc¹w² þ\¥$ˆ YÁ,X=Í›£r9%ÁȦHhª1›(¥S>(¸îÇIx5 ÏR‰‚hí×)à »j„qO\Ü+Q0R%Ú‰‚Qæ‰ò©P°GÚ!”(«æ¯,xu‰fÁè0ss² ª‘n…‚=:`œª ÛÛœ(Ø3ZfD”ô2£ ø×¡ Æ/ P(˜1úDA´<"»Ò³“›C&A´l•T ˆ–®Œ5£¢UL‘ NŸ)“`Ô#`ã¹NŒóYNQ·ßŧ‚Ü xðg‘fÃ_Ó´œð×M †?ü ˜+þºê¡&ûuåF'úuÏí~ø+¦·D¿ýÿÍ~Ñx1¾%­ ªß² Vž·T;ÛêoJ#è”®° ~×o#è”IdA‡B Ûê5ÌÖÇOFÐ="-phí¶µÀÁù–‘ÿ _o?ø@;dÞD?¬ zF¿[eŸL~H…¤Ähòƒ×›nR“ßãÙ6Ée×GD~x‘M~Ï¥»9Ñõ§?VPÜ(’þŒ~¹~OôCbàsZAŒã—è÷øÅè‡B)ü”ÑÙsaPè‡øÜûñ‚¢jEE£_˜µbÏF?¬·¹r4úaÏŒÚý  ýÏ×®ÑvŠØ³LB¿½h6úa¹ƒD?Ô<’)öÃâá:µÀ Þ+hqÌb[A«—Ѷ‚V¯5Ò Zâ±>ض¾áÓ êxæö‚V¿á 8ÏþÖaÙvj/è%@Âß{å~D€ŽûCh÷ù~¼ Xƒ“Lk©Í¡éÁµþ1ƒ¾vô$ý!Ü6O-#å:µÀÓš*úü.Ù‘ô‡üyÉŽ¢¿¨MÜþ!¹›‹xã¼5óƒ(|øÅ?Í6þ¡Ç#ñÆ¿–7ñ¯:‹ÒôÕÇ9"úCn0—즿žËô‡È؆ÐîœsÃ"‡_%p8n›ðC+®áodÓ@±–IjO!ö›×~P,ê%-˜ýÚËÀŒÙ/Cx齺ûA¯êŸ“~PÔI9Øï’éj“ôƒb5 :D?”vÄÉú¤[ÙvШhó±ƒBEsíöðƒÞ›2åݾ9B£÷µrâiEIÈú1„^©MÛŠ…€L†Ðk8¹Z†PÄn>èÕFŒ2„"Ìñu„FK%ÀÒŠm®#ôø-¡Oš l -‡±%¥|žS ÄëY0`O(&!)Šò„¢Lø}À_¯yà6…¶t¦ÐúžR ¼’SVR™B1œql %œì‡u²l÷ö„â¬Qj³'´æÝoO(œ~2jÊŠX çu{B«ã’é fVü=¡5¯ƒÅ‚Ä{@¸w%ÐÙ"ò•<¡ÛênÄyäûÁžP˜½Ú)Âs)…]««vL„q<§'4ºðÅ(ŒשFùPº5€X8ÉH#Œ‹8Nìa #ƒÉŠ”^2ƒgdžO`— Îü7T?6ñ/ª±ðs¦¾Hø‹"ê‡Ä?4n²£ ÿ¢˜ÍÇŠŽ¢…„EüâRBøŸz™‹ü×ÑŽQNò_tªl§/ß.§£ø/º[>Ü3|¡ð¨4ñ ¶(!¡p&‹Šÿà†¡jþCUiò–ð.yKô7,$ý!¿Ö¦PøF$Ï ÿp‚ÈòÆ?$o°ŒxÇÜ'þá™}ßÿP[»!þḹÆ7þá („mShIä"ÿKÿ¡šâ©â«fûàpl)p*Á$ùfH}HØìJ܈¨¼ °Üö…ÎX*ž,è—ûi ¥x;C‡d²´†Ú¿¾­¡êøYðÒeÞ0xI× Þš¡7 –4‚UÒo³ ÚoìÊ Ú,è÷ÖÓ­¹a7 ÜtñD' fþ\ÂàpRQ ÖÏ© ÆUc l]í„AT `º¡a÷Ò׊'¯}Œ¡Q¡< œ¦Á貟¡sê¾ÝB f)7ÞÚøÊY›8ˆà¿*…À¡‹›8x+Ñäùû¶8•°…@c6 ¾š.vbàmjÓ ’¶hëȦÁK“mÒ š˜Æ-»iðÕ»3iÐX7 N/èS|Ì ƒÕÑÔoŦ͂o”.M Ðǘ ˆÎ$C§6¯íÌX/\DdH#âÀ×'xsà“Ô'„äBØØ¨e‡9ðµawk€ÃÞ°äÀžü&O(Ú.]§'4f‚'4HZû–;]¢âÀÒ2gqsà}ZBßÓº 3‰(ìD9ÀèúUIÕX¼hL t¶pR r0¸öL ¼mCÏIÛzÛ¿h „'i|²‹³¢“‹£Ì[ôœ™Xz’¢EÀaƒVŠ€ xÆ@T"i¥èøSb ZqÐk D͹1n‰wâÀZ܇Bˆ'L]'„eHââ5¤PŠ1pŸacà›b„1­cY®Ïˆª”÷G,3÷, ‹‹ûÄÀH[•“ӆЙnOI€EQ·-ö$:q`õ’&%ÀZœ:f •ÞU9]`¾R’kúÓúšè,¢°©«¥Qܸ5ÀͰóÌGD' UK’ˆ4 Ua’ø&¨ZD7PĨ¢’5À–{¶8My÷=j?þã‹õZ‹€iô2FÊ}û¨€ï°£ÜžÐ;óü¤FƒU~ÈžÐ<«€HA’æ'·ë8A÷ y$Xw¦¬U@TmzI,Í!«€è•Á‰Ó2 |@DÐV³¶e@tÜáä ) wÊÇ }„ÓdºBs”Z LÏ™>3Á˜\¡ïLƒ§m¡?iÑõc ­©±MçùhèF.%RZà;äQL-p⤢BçkHs¯$+ipT ¬–fíJ(‰_Wè£W¬]¡˜Sd7•+—ã• T¶Ð+UGÙB_5PM%ðuêAºB!¤I˜”x “€•À×9Ì) )ÿ¦¤ÀêB)"e™¹h–£dàG ÄÄ}ØBa¾ÏA‚¿Z¶ÐºŒl¡ïkñͶP¼Bê©F6 }ò…¢¯®d=Ò ¦5¥#ÚŠ"BõÃþôÈJ_hÆSÒz|Jb –€4®ÚÚH_hM±Rb Jý¼1w‹²ûHƒ`.¼¶/ô–Š¾Ð®,Ó R@d¬Mcè­Ç3¡ÈĦ·ÕÆP ÷ÇÚŠ‚¤i á,m”uæ¢Yq´aHš‹‹¡ÿwÖŒ;·ØÛï-~ë3¼ÎÜ÷×ä_g=¶ö¿·:ë±­G@ûÉ¿Žýxlï'GŽý¼jË¥£õ_Ç~<¶÷“#ç~ðZd¦$¶ð_ç~4vìÇ#ÿéuæP¦³—úÛuæ®þ· ±ÐÜsû±bÜúçì¿UhnîýjƒóŸpÅö,YôãmÐc¢s°oÁ•.³ >{”ÓçÏrÞÇÞÊûù”£Ó¾ŽrÚ×YBÎûÚ[y_ŸrtÞ×.!ç}%är_¹Uîë,G—·|–Ó¾ÎrùpæVÞפÐ܃æ¾Hûû¹Ð\ý½Bs?•ü…æþæv?šû[ÛýXhî·K~ ÍýÞä÷[SÍÏÓÝ_þÆ”unñ÷¦Ì¤Ð*ß‚V?…æþx}¸ñû…æþxźo¡¹ÿXY·g°,Éo–uëYÖ­gY·OµµãŸ»8𫹕ûüçma·ûÂnƒÿjã7 »­Áÿ’ÿba·~=ÃǶ*ì¶Æþ=ÿõÏ¿1–…Ýžß/ì¶–'-Öö*M J±—ô0¹cÚ>õ ôhh“9ùñB*×Å ñæÒ1ѸdÔ# ?:ìNæÓ3Z®}N<Ž‘É"‹S‹üèï|ÏòÒÞ·ÖOÑ#t0” ¶4•r‹uΚH‘@# וkDwб¾ø ‘ÀÓPWnÅ‘|^îHgŒð0#zå~¢c6‘ÄSПcVŽ~jÄ%¿΃ Ÿˆ™]åÆAD™Q²À72ÄGÃÝ™!Žm&ß`†8²¿_~Õd†ø¸/Ï¥ qÅLÊs+A¼j![žG âUšÅQ‚¸kôç˜ Eó>¯ć"å©J7‡”§1A|Úâ^ž âÓYžýÄ®¦`VžÉñhäÇP.&ˆOGߢ¯‚sÈ)¿ÖÃLG;Vìh%‰H*`) ^^8tè˜Ì½¥ŽUJe0¯^mÓ D‘·#49FìïåïŠÞ¾è%:ME‚Ï ZJ"ø Y+v†oë@å}Dô}D"Fpy‹RòÚ¼o„a‹âÍ„& È»ËPÄÎÌ> @¬g8ðQïæu1ˆÆýÂ6Zˆ½!é-¢`40ú{ÆnêÍh`y3Yë`Fa âýUFq ó”ʦaç¥A§‡Á@"¥VFßWöˆR›\ðúê®h «”ÈÍRØgò#“áÀæj+%ôŒ7øF&.ÚÃÀž³ È¦ˆIô?¨óH—‹¾ È6rϯRòÎÁ@‘Íé%ÿEKT¶PPdwvD‰ŽK±ã‹— öYJÉ•lKÐi"`CASذ”VI½%|…ÎèŠUÿ‚!†1°(&ÞÂþÂàxé/ãYÎ'Êü+%€Æ ‚^¨á!íÜq—/Äu ¢0=(çø„D_Ó›Þ–8*Tq _ˆ ÚÄž¼'ÑŽáÀ9%†ôûF8pZB ÚcÂrÙ¾EÚBì@)(ôÓ£ÊÕ¥‚Æ|6r†§×+™ÁÀ9åÿ/(ÇWÈe¹º Á:\!wοób0š7pwÏ'šhÁb»dA-xB²*\™…žèá?=´à AÈ“7ɬô„ÀÙ«ý4šBngÍôÐá‚f¼® …/ZhÁ‚Z‘#ÄcHÚtw¼÷EKšMÄMòâ5 Oâjá¡yñš†'ä±qûÅkžu¾ÑË,Ž!ž©÷¹é ™.(ùâ5}©à]\á¯i¸BªC—/^Órå~_šBðj~¸ãª2aE®©7ºhÍ(Æ@Ñ‹.Z•ÇéOñ×óæÑE«³”³\ô„`z‰ƒ&Z°„„Îû]/éø®÷^¼¡a ‰ŽÌ)´„4~yñ†~T±/&…=´à A€:ÞÙ/zhÁâþ/zh…)ÄÖ·0ùâ8§ý=´Úˆšt´›¿h¢…JaˆšÆëãE-T ‹Øà+…Eþ:?õ°RXuÒ÷^fÔq|ß—•Š# /ÞЭ/|6_ôÑZ8døçtV {Q~ÑG •°n(üªISˆ¯Ae—Ž(dA-T Ãâ?"¸oeóxôÿÕ„n¨vÙ_¼ŸQ) /·_¼ŸQ)¬9ëúÅûùF½>¿_tÓZówÔ^ã&è†z}Uf“7²²kü>7–‚kþƇÞ0á¾L+ŽŸ££Œ¾K¬ÆÓٶ뛦+ï½XJ¬_1ì⑇t\ã÷qýâ½&p|ŠSRa8Ÿ]Ñâ7’{î_`% tþ¦ºÎ>n ¦Ð¼x÷þ¾”^tÓzQ|­ÓÈôâÝXßønpy#q§Äïc¢õ‹W@¿Y—ŽSo"E3ø Ëß`…9Nch¥µž¾ãGH¦þ‚­€o<´ø&ç8d ”ÿ¡*o,õG¤ÇhÓ üW ²PΦÁþ« Î0ØumÌÅSÂàÐdà]+ ƒÍ•n[®5 ƒÍY ƒÑ°—p* Á”Û÷ˆ`°Ù©±aðÚè't–ù†ÁÍl†ÁÛKü„Á[sža°?LêNDS#.iÌ‚ÝÊi²`táˆX°;‡;Y°[ŽHÄìÊ%Œa}¥ú‘ºÃ•·a°Ûx›0ˆš©¼4†Aˆ‚JÁ`÷âH,Ø-& fâM²`·+%Y5#¸Æ7 ¢×nfA”‘˜ä³GÅœo2ðlŒ"¼)łʃ#MÅš—¨bÁpmõ“C÷#Ö‘1@qË,RÖJ\,‡©bA°³îv±`“ñsÄ‚ Å‚QÀ‹˜Wå išÛ‚ÓD^¡`TBç • syI£`Ôâ"^1BÒ^®®8ßC¹.9/‚9ðR~Zbàõú®1f+b Þ!'â‹yão—ÃM ¼íÐK „Ch& ¼]V71Æ™ñÁÀÛ)¿‰¶ì'Þ®àœˆŽ‚@.|žünB  ÜB 혜0ºFÃÄ€kê&>ÎÄM,€‚´8K˜Q'‰'Ë ø¸˜œpg™á†aZS2`q!X3`ˆï7YØ‚HY·01·#Œ{ï3b„> N·8’Ø¢Š&áNX\EÓ²Ê`ôZåÃ#Ä)'‹ˆÿ®W€0R½ÉØÐí’¿FØ篙#ÒND³‚"’$âu¡ #Ä6\³˜ñ’a€Ýˆ` Ë;º‰…€qkM²pW;âá0Ì‘¨çGˆ¥J`ìQðD@ôõ0ˆ»@ ˆ“¡9@ þ@–É\m›©¢*fŒ¤ÀBž#ö4ñ?m#ôÄë‚ÀèÔÀ{G9c ›ˆcÞ¢À8˼qEýrÑ ¾[‚`çâèÁî›A)´^¥æÀ %S>$mj¹H0bÄ¢›«Z“ lnׇGOZ f¥ß$Á´' W”OœÎZNœÝë,‘ ÊŠàD‚Ófu“`óÔ ˆå2ÃèAĶùÝÁ(fÛU0«Û£ûÅO F´²ÆPÁ¨¡Æï†4FtrY|ª‚xÅÁc¥-ÄúO·A0ÊÛr1$ĈuB‚à¹M v#YI$xnB<¾J$ˆ-D‚±"“HðÜÆª`ñm‘ª`IuѪ`±¢–ªàk\HUÐaÔT¯\ïZÄÛ™Gª B[ÜMª‚ξJU0Ú4K¤*˜¯ÞT÷—[Ä—SÒ*x•” ¥ âe¡KÜÇiU0›Y¥,‡øÍ(YûáWY¼2®4h÷fÊ‚ûì$¾^é'^V)“‹î›U;E8è*HóŒƒP}%- /ÕªI¼Rk4 ¢36Ó vópÑ ÖHƒû b?_¼j²žpÞÕñ1ÂÛße¦Á½gÓ Üße<>%Ĺàìf¼ÜŸ qðjž%Ń؄ypŸ ó`þääÁ¬…”•@Iò)¾¿~ý ·;¡&úa„ëu£ *ò-Þ¾cS ,Ž¥øØU˜Z {Dm-°Øhö{\$µÀæG9µÀîpXjN3Oö{R6ü=®¿µÀ¼÷ (Õ@”ûea®„?ˆ8(ú+ N¦¿âÚ¹[ |}§›þ°Ÿyj¥¦ÑTôWšïGÓ_Ù)úÃþEˆ¢¿â*%I0W1aúË#IÈË3ŠþPÀæ¯û5'ü½ö¦%ü½n4”ð™5܆ð—ÎÈ„¿úø dø«eÃ_}•ɶÅ@’þ²’€éõЈ<¦¿šê€é¯ZŸNúCšE<Ó_dÛrÑ_ó[)ñ¯ºOâ_“\žô×lKOükéE3þeïÈÄ¿æZ:‰Y¶Ìø‡!ÛÆ?ø¸*¿\ø×ÓKüsçˤ¿ìb™ø‡äîN¼"ÿµ-¡12?ü×\–.ù%uÊ)B‚Õ5ÿ¥å<ù¯;¤—ü—Ÿä¿îBÖÉ=í›æ¿‘.<ó_x÷Xâ¿èKJiü‡#oóßxô¸&ÿ'INü‡ŠÔ2xŠÿàÕá96ÿÔqÌ)$ÿeS¼ä¿áW^òßL¹Ôü—Í«òß°ë#ùol‡'ù/{ômUpïXü7_•ÍNþƒðÅM„óUø0ùoºvƒùoæSeþ›*›¿EAw½NQ« ^p‹‚X¯Ì“ÿz–„JQðr©¡ä?,ƒDâ?@ÎW¬ÖXÜñ¦Ô§}ÕÖ//€áÐÿh‚=2ÕÉ{$@èË’Y­ "@"?§4Á㫤 fuÌÔ±º”D)MðRë+ ¤E.#R¼†c1–Ñü™VK‚Xañ”Z¼ìú°$x»ñ@J‚¨ÿÔOch:PDK`‹î‰'â­oÙP’ úÉÄDðTzÛÞÐ' Ú¦xxCÕK+½¡#ÍÞPÏ{Iƒýr¼Þ4˜}l“»£ Iƒ½(ô´3_»&3SÐ=Nv¦à°/3‡½oÆAä²H´·1fçÑÄALï'SpºÙÕÆA?ÿ[ܰ'gô3S±®!St·È- ÇðS¬?¸C±€­ÊÄ“(Mhï÷ Œf=ÏG|jJ€¡–Kð“(˜ÍåR,Õ+D‹‚åµMI¢`É|9‹‚o¨EA\ûvÚC£pR‹‚`1¢DÁš‡eQ°¹yŠ‚­eÒŸDÁv[X²(ð£JcQ5.iV´(8\D7±p>¦cq!.åYs!º†Ü§=yY) WÇJ.Dä€"–¹0=PæÂ©"zÆÂ¨è«¤?baÏp±±°ozF¢ona!æG}“¸³™Œ†â˜UeÝ$öì2e.ìnEi,ì—+º 1éÂz!=²Ñ#K¡¨Uwâ ¹‚4†íH±i&’'……˜áÇÇ ÚÒ, ,D¹\}¹°7EÃÂBœO-ÜÅ…Q"ö# â í"%†—…kyr!êFI\öȶ=%Á(ù{s„\ˆ T`Ì…#«R Y?Et„Á…È3ó‘ û~„Ä…(uå‘ GzmÌ…kA©Š9æB9M…™'ˆ¶D!¸î–•S‰‚õu†¹p¼#eÂÀÂÅ8Ž‘9OpÚžb,ÄÎú¡ â×qUg*ì[ò¢ÈÖ7O0òC˜ éI&ÂUÉ)öǰê)œÀûv¦NxˆyØâÁ‰Ü.žPñàl®ÚfDªcEæA|£oæAäÉ€'D­VÝâAäAi¡*A8Ƀcºœy`«¼œäA|Q;“çÝþˆƒ(-§€p¥å¤q ÏOç]D[¢AlBeÂ48Q @ipFcÓ#:õpzDQlV’qR4 NT¿$‰Qãω„¤ÁYÒ§é$ÁMÂÁ(DÄ«IDù^‹,ÁfK(ÓGû!M°Gv·Ùi‚º)œ&x_>r§ ¢¦Î'KðéŠLf–àΗtš`T7ãyóW•ÐHœÅ¿2M«MÆ]”&ˆWg?Á‰Î§Eµ •0ë,AÄeq– ^d";â .§žDá ŽAA § ÖaåÛi‚ëzÊwë4A”/%Ý‹ç“Ï¢y0³s2Oðqñ n ãÁÇ^<8#¶õËÆAœQ–‹Ï<Áž®[µêžìŽBoµ¼””¢ ÑbÑ;òâíÿwm;·ØÛï-~ë3¼ÐÛ÷×ä_GA´÷¿·: ¢Õ‰aþ•ù×¹ûñȱŸE,—vÂ{ˆýqþy|¶ã-ÈìHœ)ÿuìÁc{'9òŸ^Ü­¬éÛß-îöS6w+gÁ¶«´ý§wûñÒ·ÈtvÑ­o;ÕÝÿןÝeÛüù³l›÷±·ò~έ¼¯]¶Íû:˶y_{+ïëÜ*÷•eÛr_GÙ¶ÜWn•û:¶Ú·¹Ë¶y_gÙ¶| s+ïë?RÜ ïŠ¹~?wë¿WÜí§+ü7Š»ýÍí~(îö·¶û±¸ÛoßYßân¿7áýÖôòó÷—¿1M[ü½iò)XD>ÅÝPim]œõ¦ý»EÙî]Ýíúc…ÞÞ÷ïîô_ÿüO Ô«þÇ+½UÄ'Qó7*½µáJoë_ÿ’ÿúÝJoëÿ»¼Û]ÎîÿÿG+½}¿jpû×ü׿ýV¥·;¯ÿïk¾­_No²üsÂhLûuq-ΤôÇc­üè i÷5BgB»OµL:C2;¿¾!ŠcäVš¸ ÐÔ÷Qš¸Ë¹Õ·0Oü–B¹î»h Àùø9oUžxQ¼¤¾ÖnúZšª€¢úÚCº½œk„öt»ù]“ö>Düµ^´‡ Õ#«ÞÊwÖ`­òÄoBa]'™K‹"Œ­õUšxÑʽÖÊ4qg ®µ³ÒÄ›²ãj” èÛ6S#žUØq¬‘TÎ*lŒvÕ°—± s‡k¸5"ðL#ZEg‹9[O… ÒÄåÚ«ˆÕF–x‘‡§Fõë—Éæ<&äÀFš¸ã×y²/³g¸æ­è‡r¬H–ávÓJŸa‡èh¨p Àãn3SHo’IØC\,¨FÚ'Œ1ô1¯D6ÃÁ Šì!EÁ¯uwÈR䶨ˆz)7€fFRr–Fä ¢1“œ¥$uw(9À]¨*ÂUVvÞ}*9 KX×NÉCk½ŠàÓ áF'¥p–:ËvÝ0Jp"n/“˜Yá+ ûT„eÚmÈ–uÁ}¥S”X=yùEAk€öÛù²ë– {H¶r© àF ¤ RŽ~ —ïóù(5`r‰²n ºCn÷©ó¥;ävOìuKÑr»ÃyEtâæWU}y§=ä¶OaÝ紇ܮ·Fh¹ÝkfÝR´‡ÜVŽ× D{Þ§#wØCXüû¡;Á„8Yë:Ór7=dë^ ;äîšoÖÕ¢;!6¸½Ý!¨Ë7b ³w€áx]2zCî¡™m¨wÀ`¾Ë:ô† ¼§okzC2u]!zCnW¥\'›Þ´­ÉÖw6ÂÅ 0z»ºí:%4‡ ˆÏKwSë·ÀZÿRë×q[ÿ¢9äV¸s „7!ÂÁIoÈíŠ4ëÿÑr»vúš†è ÁwÇÅlÏCoÈín>í)ô†<.`מ—Þ¬?^ŽTzCn\3Í!XNt6—ê4‡ ª½>5hÄÚΡ9ßÅ/Ÿô†äVôüc—­Ü´†ÜªÆÕÊCgÈãÐV !`k›—-ÄáÜâTªú”_ùw cHÄ8Ði É m!ø%¼‹ðrŽj²4¼›£Úc>丹ò¬{–¦({ì¦ü>4…àÕºT{ M!xÆùcß—¦§J-Z¯~µ hn÷õ6šB×Elo§)Wxp›qÅGh£jx1_ô¼1JØðbÆÔýØÐÓðb~xÇ0}¬Õ›¦Ç±ª´¿ô¼Q|Y¯,šB°Ÿ¸Öz#fn¤GóÁ¨•wˆ\s =!H¯}¸ãNOÚ ó„FuWöFÒ³Vev ÐÅ«™&8z\[$˰/ó9›NE© í?µ°G.ÃÔ ªéKÏ£³ mM*åTÚ2^ž·P5(™˜¼KU«Á5„É….~UgV}l©CË”çûL @šÓg¤§ßa‚£<Ø"7žÝxyPѬíX¸4l‘8ÍV\4TÇ{)åênë•YÕõ¢Eçë< EàXæÃ›tfà½Î+ކhQæã•TÕ ‡M5ãRë“7¶áÀͬĕ G¢á<íl¼sF‰ `´ÃåW·¸Ê} mD$žý´çv³Ì‡š‚µUJ Pšo,}Š•CC0œZ´æ+„Øë~„Òf´•¾[±iBã;µáÕŒ©?^L¼›£È‡C± ÁÓÕHÙo¶AJˆ"—ž( /µi}õú_˜¹»“BZ¡aæî¯'´Bëlù;õópw¨éœ&:Z¡aæîÖû;Z¡aæîN¬êx5Kƒçº°ãÕ|Ó¼Ðñj~èA«Ü‡pÇÀä^p¬%RùEQÔ+üejÞ~ñÓð©1}±£šL}¼#:º¡ÁÕ‡úUá…èè†6ØrXûA7´F1Þ{ÝÐ0yÃek³Ž73¦o(+!ë06Ói¿ãÍŒù{d‹AÅâ(«Ó9þH•·ÿ½? #Þ' 7ò±Úèú”»”› €]bs`~Klί7¢dh% €¨O؈r@å Ê ›«æn´;qàºa¹~M¼dÚx+Uj ÍG €Ý1úÀ®ÊV €=W´ÀîÒ2ÀîT¸@<â= •0bìΫMD'—›_%„/…—Oˆr˜“€%ÌÚkI€ÃbI" Jò–‰‹,u›]:m³  ÷% ‰“_aK‚à«@ÕÁ×·u’`5'Ú1²A°+Yxƒ`Kì¢æü€à‚EZÍ ‚P]ˆ-j7AxUùû/#°A™D ñŠàW _ªßWSæAÛMßš;B‰&‘›³Ñä&Á|<’3>cD}›p(Ì6ÃÏ‘‰‚·oõDÁK™`FÁp ¾¿œ(øêõ¿QPõR“³cä&Áª°í‰‚Œ`' ¾îù²QPµ°7 NEm7 ºçË&ÁÇ¿/QÐ…šN䋟–‘êW¹ å@¤ßK3 ¾Â$ 'Ì‚w†"RtiŠ­V)g[Ü:ÞÖ¨I=°$›Zôš~ë·o¶Ô‡àSô]œz =˧_i ƒÃÁà„ÁñëW¼œŒ±YÐÞÍ‚Û' b­ûhD‚àL:´"8%çoEÐ ¾·"Ø•”µÁ­ZÌUL*‚¯•< ‚n½A‡/7 >ž„ÁÇ ’©ä% ºÆÁKÆ¡Œ]„W¿4è¾CIƒ[s3 >nܼÁT(S¼4Enœ>;‰ƒãW ”¦Á®|¦¤Á& ÂIƒ:Iƒ.L|Ò V»Iƒ¶o|,5ˆ1KóFIUðõÂ:uAgïm]0×È) :=m ƒ%¹ÎÊàcQ iÐ}·2x«²ÖVݧá¤A‰TIƒ—’O6 æBŸ4x%¬Šq]¸7 î'$ip&šÇÊ`¹?1‚®¸…qPÅ6º&ÑGä8èÂ6ý¢ß8Ø~ýÀ`òbÂ`ó³0è6X ƒPtÕ2 b·œ· ƒ›)¥*èìÛ ƒ—%Ã`ujOÂ à‹±0à Lýý# ¾®á¾apšV ƒø"ap²ÂfÁáxYðµ»%YÉo "í”»•(صâODºïr“`&—& šÁFÁfZ4 6×JDÁ~F Ø^Ç7L‚PEp[¤9ÿ$Af4% ÖŒÛ$ ^žÒ·*¨¹%IÐŽþ$Áš!“`tæˆHR''“`uÉ1“`ÖhHî¿I0§â$Áf³Ã! Ú“›üù?…Á!åÍ$XR 6×MJD§)2“I°¹ [’`kšL‚­)7I°¹C’`s{Œ$Áé¶I‚ðÁê~"Áù¦Hœ.âs’ 3ÿ7 º\ö&AÏÅ›US´|øw*½mü#ÿ~ñÁ§ßÿn1þM÷6þE6þ½ÉeÆ¿ÊÄÌMÝv@ÓŸk¢oúÖ’gB¤ÁcDˆ]4Bš¯[7vàu%IJ\GeµOŠàtnx*‚èçCð9P²æé %m¦'ôõ’z{B™ž´=¡Ý:Ýá -·Ù¦PÑFšB»â0…Ê,iÌãL,6¤¦)ôÕÄ¿!ð6Zt¸vK‚E÷ã–s}Ÿ’`st!%A—Û’ [-¦$¸¾\Qk‚°º¶/^vô¯„5i‚ÈÇÿJ‚E‚–Ÿ4ŸZtƒ- úe»%Áú“$øZý>$AeJ‚{Äš «ÍlMð5;Z¬©ÓItå- ÚT²%A½Í¶"øªž)0ö{iDŠ |1)1 5ç5C ¶±á“¬dï$†™!A`tdÂ!1b!!·×ņ@\_¾´ Ç.Œ{à=M¡iv6ÆÀ8Áš•yÌ€qœ´‰cn“´G̳eŒÝpí'Ä­õb@ ”Æ¥»N=0¢['âî»NŒ›ožr`tcä]¸ÝÚ&@L´ZUŠ#Ä´0tc}ЏÝFÀh F¹H¸Ë–wS# ¦gYT…€Ñ"î)!à>N`Èã\ÀŠÃqÎå 0B?"7`èãr’’ãaxNŒ³SOOhlS¹g`œSÊkBÀ:Ghœ*Æó… ÿŽ£þíڲƿ8H®ôŒxqÞ‰øm,°gü –h2^œ½Sdþa„áãßVüÿ¢¹ó)âr!eü‹ƒ £‰þ\û2áoÑú¿ëJqPð‡¤Øñ‘¯”þxÄ?T'øÊ€é*0øm÷D‚ßuý ^j›Üw¹'‹Á/îÕy’_\G’«È/Ú„Tù?/ÎÛÝvj‘_”m!瘺‡Ø/S’ý:¬ö˸`²b‡„³ß•:›ÙÊ4g'±ß–¡Í~˜)¤Šý²>e²ßí…l²ßæI³_Ô„ 'öCæ2' ³ßí2.É~ä ·k¨%ü!ä"3§àñ R†é¯3¸ð¯<ªKøWŽOúCc{‚±é7Ù2Eˆ§0Ìfüÿó`ü+9››ÿPD”&þÛÖkóÂX¼“ÍÙ0ù¯<Žšÿpœ¼1ÄX ð=aþÃýËAÅU’þÞ;ý¢¿÷ÊmDø‰Œðuƒ÷Ÿá{‘‘Tð÷^Ž|þÞÛ:¥áeexH†¿×Ù# ÅÝËþpØt>þžd+Ãj¾H<ü¡œ¶ü—}Kø+~ (Ò¸ÁjwêËE•<’ýnu+Hô{o«‹F¿×9FF¿W}/’ü^·|Iò{]#;Éï}s¿"¿×õÍ’ü^~ÿ ¼m[茻ò„Àℯ´…UyÚ¾PßÛ:Eë ˜Ý%ª a©lßÄÀW냨#™Ø3ŸÏyC9kfÀ±s Å€h$ÈL(»B!À–ì ÝÞC»B]”;p¸AöFÀË U‰€™–XÓjЭ7¶ ¨f¬©Ž$7«€3aÓ* ëòoP…L¶˜—N툖ÀÝÙÂo'‘›EÀ‘)EE£gºD¥âeÄk)lÙp«€.î–2 ¼_\¸[„H ã¨eÀ¢—ÚÖ‹…«CT€Ái÷++ndnmÉ: ¬V¼I¬Þîè˜:àÝÓ&*ïÊç$À”:`¾­RD2eÕÔ»íÅïÌ8µx»¥w ObŽ•@Tó"ÞQDbok ÷°ÙT: Ò„æé èºU?U¾m´ˆÌ¨zxB#·h|ÒןŸ´Àçþ1-0ê^}tÀ'$ÖaëªÞ0é‰ÒÓ-–:`&ý¤ˆý\ü”t@Ôñð)ë€øT9u@¤}d@|“ØM2àãÒ)beñœ R\MZ<ö#Ðø¾uÀú«ÐR2ೡP2 V_Kèγ² ø8–2àSÓ¨)ðqyÖ”Ñ;óúè€Ø3å1ë€i°³ …ÑøU’w’—›-«RŸš:œT@|曘UË· èê›;/°9[,UÀ–ú¢UÀú“ ¨äê-v«™XsÏ´Àî ©Ì t¬-«ÂVŸt_ef`O#©3›\%;30U Ì l© J´B‘"`µK/EÀflJ0S…RlN‰ýÐ E¶X 3)¾>ªŸœSä•IÐ1¥-óÓªõò‘hµÑ–Ðᓞ"`73" ôÚt…ºþÜG”UÓ2à+a?eÀ×Kó”› 9eÀBh0ÅOÃàN! îXà Àƒ¨µM¡:ðÃ*¦O0ݦ™˜IhÖ‹´ÎL¼-m¦'´yýžÉ]“èNtë¦è[‰‚ÑÏ”B›=¡¯ŸD£`qNffV§§%4eó´„^áY;Hp}J¨-¡Í—÷°„j²KK¨OqZBm5ۖд/¤%´13;Ð}Îì@ÊJ`mR tt+UW&-¡íWIŽÖ]£.u@gv$vWÜŽP—HìN®ø¤¾Dz`?ÓQDŒöOB›cL)Ö_­ùItõ„­ºŸûVÓ+“*àP›¿A¼UnŽa·¼8"U7z‚àh’›GË<>àèz»¥t&aÚêìùÁé@ÄV-· ˜Úaª€~¡¤ ˜¿Æ,˜ádAÔXg‚ І3¼jŒ °TMÅ‚=(*`–w[¸H)êÍúÖö.Öÿ;Kµ[ìí÷¿õ™?^Þm Æu™Ú{þu”DóØ®¿”#GI´Í)R c?þëÜÆŽýxäØÏ¼üR}´þëØÇö~räÜÞ‡L‘ÄþëÜÆŽýxä?½Ô[G€y±O©·KiýÖ?:¥—?µ?ºí[ÿ4ÿÀ¶/ôÀò) ÷c°?R!î{/÷JîúñÆ]oÉ]ÕËŸ<*¿ñÓgá7ïao¤½|jÈiOGÝ7îé,ûæ=í´§O9ïiW}ÓžŽ¢o¹§ÜÈ{:ëÇù™Ü5߸§³ä[>ʹ‘öô© בö-𿡺p¿7Sþå§yï·æÆ¿üt‡þ8Wþ|›þ¼?^n¬—ã§&ÜQ¾MÕÝZ–l[ÿú×?£½Ò=Ï1w[Ë“~ŒŽ]&î¿ÿý\{îoîé[{bDÇÿw«Åù¯åý-‡M*‡ÁÍü×OÅâ0xå¿öY,n-‹ƒ?‹ÃØ¿ç¿þù7Æ\,_,®£|c?ή'fðÓgÚñ܇Yþha-iVÂ:Ê»OF‰µ êƒÖ’6”5ÜQ÷fù8ªy}\ô–´!KÀ‘(:iÿL{A\ˆ“Í…­:kª³=]㥷$Û&­zKºSŸ;*ùvv!a¤®£Pø`©:eúèô–€N_þžÁh‰:&½%Ý­úú¼h.éêQÚUk:¬V\$·ޒ5¢QZšÝNøãæKkI®ç×­%kD>µYi-é΋í¨ÜY¥€‘»E6´– ­¯Ô´–#“ÞXëmÆu…·kþ –qÝô–ôW‘ãq=ô–`$T€qšKP/â‘ëbÒ\ÒÝC`Ð\‚ï•ÛÔp—t~M£³ý(n~ ÓY‚‘àÆ5è,ÁÈä§&%°â€Æ}ÑX’EÖIcI7¶Žû¡±díŸ.«u£Ýî·Ì¸_úJ°IÑ}%Ý ^%•‹i,hQ8ÒÃXÒ]"}¬¹1Œ%Ø„gáž4–tG–ÇsÑXÒ]ä{àé…³%‚Öƒ@g Ê@Ч„³òHÜÀãyé,éV‰×%}(º¶8–ÖŒtnÓè-éÎ.OovRÉÏ ·¤Û™3žIoIwCQ.zKº³(Ö“JoIw {”‡Þ|{<0£zK·â»ÊKoIv[#á-évRé-A4;˜QZ·4ÄØü(Þ’a[Ð(ƒæ’áú(“æ’¬‰±¦šK†-Žã½i.YÛP=ïCs jÇD¬v?Í%ÃíÆûÒ\‚Oñ÷¼/Í%Ã.ëñVšK†ƒñãma0ÁnbÒo§Ád8Sv¼,˜%:*w!7ýB[ÝX“Ë7?èý|8~ ­‹šA3 :ðr¾XèEsItñ¸ãSÌ #ªºÆËcŒÊnÐŽj1#¬Ÿ qfÌ+Š»!ó@¹÷JëìÐÈs³ý—Ò ÆÄAÐ\¯ðŽæUM%ó¨bt[æE™5Šۤ;f`¢ÊÌ‹‹÷óͦ×z¿ÍÁVäØ3¯ÊœlEž¶Øy]lEŽðSè!óºÙŠ|¸Wš·o÷ƒæZ`¢¥šúAS›h©Ö¥zÇ-:Á€,ŸÃ§a¢£Úàƒ÷Õ&í–”&^Òí–œnæ5Ø‹|LÝ×/é˜Â'ŸÞyãø÷ß'pg_­ËrsŸ2;¬•ÔEsà%¹k¢ŸZ¸íýœè§ÖeŽ h"n4ØõZg ÕмK'ªIÜçrâ%¸{Ì; ¯± ãã/é‡iÌô¬çáž§ ”±ë|ÊEuß~å52é”Åz¢Zãqr™4ÑN­¿ŸEòÿ/»ùøD;5šÖùbŸO¸Ìùóîx¾4ºnäÄ+ZönÝ\xE?,†ÄÕþ,K˜O뿳”‹Aû²×ȤAГfA•Ú®ùÏ}aÙ%”&Ú©uú®é²›h§6ø] ™M´S ·ë!¬g>bƾ'^Ð×éÍŸxAß,mÌ鉴 ÞU#zÈàë½52iðV3‘ùâènÜ¢vÚÝ¡r¢™ZãAÒ±<ßhŸ{¡Æ3ÑL-l‚Üé,´æoûùºÏOàÝLo7߆¯æðv»•GÄlY‘ù0W´ªúùñãbÀEëÿG Æ ˆ7Ì—m>‰[*ý&!u‹7n4v96v:÷6vËKT…Ê €Vœ6áI €t~°Ù ›¸ÕØìŸ%6''f ô@”®„9 ¨VÛˆÛLlb„¾3# ÚÔ°8¢°9Ç<,Üù]B@xº…BÀ潉€Íýé›Ý:‰€—¬/e.o¼¤'mTÊû&@—¨ØèbI€{Sà¥,žM®Ù·)ÐÎÂM¹ŸÄ@Ûò6^^1$Þ^8%ºDÕæÀ[ í›oi`›où7>>ƒæÀ[6´ÍŽl|dØxSÜx{ ‘èʉîâ»1ð‘kucà£J=¾ÝEjc Àn ,>]‰LÞé¶‹|ó‹n¤@K}IØäþP`‘1)ug™O˜}’ûËi>!p‡; ½xénìnd™û"Wº†ÀîÔù„@„;ˆT†@„D/0bd~ 1`¯IŸ@¨«<›@}@ð·?aøC»Õ÷ ^5Á_wŒ„?˜1yž Ù^!ᯇ#b?¤Br¦Ø/½<É~ˆ.ê÷ˆý†Wd¿0pâÄ~ØÉ—ýp]«f?ëb©“ì— ËÉ~èÕÃëkøîà›ô7ìcLúËž?Iø”¨Rô‡BãÛˆ12‰w"Àa»™ p8ƒ( W˜·¿ 0z¦k„ˆ/Ä#|ýƒ%âÃ{Ÿ8î…@|å)âzh 1 [Ç8ì¶Kîê’8¼ŽK ÄIEQ F(dóT'{³3œ8\ó51í·Y5ˆs­ß3Úq3Dœ¸·1Î'e?a FæGÄHý(h_Nã—1U¦'ÅšIæ¯öÓ2É\+ŒYx:1²·10à ÆÀüPb FžâC\ò3¿>9ÛP0f¼9/ì‡-óÌáJÌ"É™\ˆ‡¬8ŸâÊÁ“úGœê0Ÿ8ßÄIaàþÆÀé ³‰S%ô’MºÓÌ%Ñ™MDóM‰îÊ4sÓÚyæZU§«Añƒ îÍ^iÔe§k…´"ÝVšկ̀º62êË (½eäì•f@]?™y%dìX¾¦0OE+`ã&‚¬€Vç°v¢«¬€ÓRZ¹N+ cWÒ ÈsidÀvš1§niìXX¥°Ñ’.3`×ph Ô£.S`§©š¦@¦’LS`G<Øi \À>š±Á;ÖZ¿‘.Ù/Šyœì׌#öëXW þ:sô þ^ž¤?¦ßOúc™¤?†{&ý ÚÔDt]Hú£+EÒß mNô71#%ýe?]U‡" ƒà¯1aÀßÄIÂßÀ}Lø›H,ö£G‰Ðo2VLèg½ ¸|úÙA+ è›!°ÏΤöMæ\ö™äŠ>€}v½ïöÉ1„Øg— HìK¯bßd¬¯°NÔggB¿ >›Ô7Q0UÐ'×2ßd>1Ÿn¢˜o²‚ƒ˜O·DÌg^lµ“ùŽ6€¾9Òã3 OTЗ><„>•©õMFF“úô”‰úl8±H!õ)Ë_ÚþN2þÑ?'‹Æ+ÿX[CÔ§]Qß”å–Ôçù ^> *y-îS® qßd@¦¸Ïæ™·¨IúËø§MnrŸŠ1ˆûl/ž¹€ç¾YäÌIPšJåZÈkò-Äy€r3%=@ ÿò-4È”9(Ò”{oéÊ ÄôeæÄôÅöY:€Ê5’ ÜPKPùbË”9éZ„ ÜÁJÐJv¢håª] ‹Y9€Ê©Q ŽÊrm|–äÊ0ÝtÕ"PNúéÚŠ']@™5}@5 É”õóÒ´Á7> ;;òeÐpú€vÀµ\@»Ì„to `:(Ê”Õ2Ò”Ù¶ÒTSŽ<@0X üŒ¥èàö…@ÇÇ8í“yþÒÿ““ôÿ"MúNbˆü?õiÿ'SžÈtÒ›] “re½©tøO'ÐIÇRú€.båª&tenº€ÎŒ— ô+<=@#‹rz€.:ËtÑ¡›ìwqGFìwñ=û]Üû]r6%ûÑ0Ùïâ#,ö»`TKö»°‚ú¡Fk’+E%ù]\]ŠünâŽÈOŒ$¿_þD¿[~¤D¿UpýXT6ѯ|€I~{ü"?õ"òãtäwÛäWàœäWÁ"¿"ÏM’Ÿœ E~ÏV’_!‹ü b¹“ü˜Û"ɯ`ÎLòã¾ÐE!ýš2…~Ìh—èÇD¼‰~Ì`—èÇ­îý°îú1=Ù¯"´<Ù»áÉ~Ž?É~“[²³:'û1õi²_Eþˆ„?l&'û5ù–’ý4d±_Åë ö«|"Å~ÒIì§ñŠý¸Éz²l×b?nð$ûIËô|ñ ¯Á„¿7“„¿‚=Æ—è'ø+x§É~_Îà Fûƒýà·|¸Æn\º>˜–~ GÜé jY/OOÐÉrÆò],”4'¿0²Í«.Bý‚VQ7° ˜ÑkA‹L Ò•R&šSRø2’mNŠêZä@[ü…o¥¢ùŒdZÎŒ\²/2p‰Tg¬™+‚ ‚70$Þ4@ŠiEN¤5?Q°`Å’(ø(ú((£©p°ÂÏ"q«¬ÄAV'IlŸ­€“ „ƒCÑÄAæ(Oü® §\HɃ [Hdõ0ñà„³wáÂRLF@ºá§ß¾4^rФ5ÈÒÈPù¹I+`4Ò X`ÖM+àÍE©¬€Ìa–f@Îø2>üÄË (ƒèa¤ý.Í€ ø;Ì€¯˜@Õhd™´46$-9€ëh›§p2¥P›á26‘'Í€²½È È)6Í€Úû–™vÓÈÍÜ´vZ”eÌ£`ò¥Pì.Cà @†À!:¥!øidòë´Ò:í€ Ì3EôÚc€?¾ŽÄAKL ¼—!p!§· ¬·–†ÀÅç<è×0šàA?w<àAOŠŒØ¾[§×ƒžkyœñ€Ö V³ÀAï÷>qÐU¨'zmèvâ …§8hð4p0늭 †ÀAë8xœ 8èi1Êdœ~¸?b4è}ܧG¨«xРŸg´£p€ƒªzGôr×p#]H;]êB´&ãEƒ^qí„Aoô‹4cW%\½’u̳€A/~[äœf"YÒ _^Ø rNW²>hꉕ5iЋqU‚í(ܸ A_¼© A︜¡Ö1lâ AOU:O´\¥2pÐ+áµÓ%ÔkoÏÓè•ú®Ó%ÔÚÀ»@xŒ@èÕüÂË@˜µÀ „^Žû ôš‹óäÁ,ØMô”n/§P?*z ô’q׉ƒžªµžž’µž¦@U'zÍqòZø‚½ÝsZ³¾9yÐs½Žƒ½R9Áƒ™ –<è™ÈÏx@ÄæqÐÎ s xл¶9š‹|ð ×à ¥Àƒ~µ@dÁƒ^•žšÁƒÞÏsZ½N¸2xÐû2x0Ë7’] 8©Z›W@ ×V¿‚ì}80 zܰZ\8èz¶3 ð1pл‰øNàà) ô~¢c§A/¬‡Aƒ&u4èIy’4hUùbR% š$"xIƒg› Ao£ fÅxÒ`V$ zÝŸÆÀAÕ% z}ølÐàyª£ƒc)hÐË;†Å4èç‰g 4èc‰ÀCРÅH¾ A•¦' ž Z z hÀ K€‡ƒö±ÂŽ`0‹›=7rpàH < ôìÉí„A¯}ÖÃ`Á,†y¤ˆ»¯Ûòð#%Ñ}/KòˆÄGüÛ™îíl‘í³Å÷Žùý)âîËe«wþ:R©Q–©˜$9R©í«5˜ìŸó׫Ÿý@rö³'–þQ¤-~ý@vôCÉ«ŸY²—Y>÷1Ë»‡ù)UÝ“nO¶–6õÏK w·ßn¯Nwf¸ú´if¸OðÆÔþ1•»ëË{ûRšű™öÇŸyߨÇÑ ý¼Z¡¯LüƾÎÌoìëh…¾^­Ø—R¿©¯#÷›úÊVìëlÅWRÉߨיýM¯r¶B_Nޏµ"ç_Sޏ_›*ú2ñ}orüéë³úi²üÎóú¥ßŸ#î¶­–ñ)O\&‚û^š¸#‹Üoewë©yâîË«}/Wœ%Eû'ýë¿—ÁíK®8û{&ˆûãRÅõ金ûå/>UÜ~fˈùÕÓú¾f\ì‰nImÈ Žê[Ò°¡Ì¥E÷íE‹ÞoX8XŒï‘"Ø;v^·dëñà*[byè#ô¼Ä}FšÇ~Å–l"Ò<0}K C·Ô–ôˆõ§šý{D¤wP²­Ü¡øð-YŒ3ç­­×õqÖ1IhðèæVh€Hï-°:È¢]c(u+ááa?Ù’­@„qXmÉV`†O@íÏ‚¿ŽYÆöý{†ñ ¢ 3s†à‰ûÖ¬šK:Ú´+bÌ«®\³jÍ6P ÁfK @Ãf¤­L$•Gm"œzÄuhVø[&©Û ™àäœHlWãV7¨Ð¹æöŠlaýX¬„z¯8Æ „9¤Åy¼xõ7½%öeˆ@i¼N 0’zK¶àå± ¹:½pA-ÛxDÇvՖ̈4g9”-Yº^÷5 ÂŒüì&  <ѰïEt‹+>¬°Â7½%[…ˆ)~(©þ9ÜHÙ¨0¶[&|·Ä RB¼ÉMð\ 3=Dø2îܼ®o™QÏ~/è4!€L–·%Ð`éÍž[DíÆPfmáþÅW}¶À"fÆÛ«Rü-3ìm Xp_ÚhÀ¼|[bn‡G˜IÖ¼ÆðÀ® ¿{ô²îð1¹°½%VH#<Ä ‘×pKjƒ$ P[²UG³ØÝ+®nemFø˜\pðÛóû–Á¿[îð›1Ahps^Ù«II|Wìö8þ¶âáf·ßæÅ°ÅEÒ¶Û¦„/ãîÚÛ,}˜yì‚$Œ·=¡p=ó­òÛž¿Å ·Kükaý2É‚R± Ûaõ8êF`(¦£û.ãpMÛ¿·á¾6â-ÙDÔf&o‰•Yø–‘µ[ ­¸%Ѐ.nvâ|ö"õú§·Â³/OÏm‘µ¸ åŠHsVÙ’{Àó,@xKJ–ýûA¼%®‚}”#ø3²@mÉÖîlÇô3g¦]˜ò±¸ñˆÜ T~öÇ0 ŸœI$?—/Ü'=¶äö…mìL´±’-‡1vK ¾ö÷#x훌,~qíöŒˆMžyì^P0o”æÝ~,«Ù·Ìxh’… }±³¿oÿ5!‰²†[rûBÈ-xqO¬[xßEÍ–<dÞàg¾%5|â"nÞ+*ÀûV¡AGÚÝ-:ņè–L_Mz´oÉò…51¾å‹9óêÃ%oСs¥y7èÐ9 ßVm¼ÎeõØÂÕ’í…Ï:®Mkðê‹Ùþ¶¯2ò.H Ý· =F þwñ¾½šªÅ9Â÷¨ã¨øÆÞ^Z,<òðHôBÇá°òÛk 8ÌlI­à©¶J&áe80Õôþ¼òqz–oÉôµœ·D*ð¹·z!©˜ÔÆåk¡£çqûZˆþÛ6itºbf±zl¡Sm 4˜ðYÙ¨ÀÔ¶[Ò $ák¼%#‘`û÷¼¡T8¶d]PŠÏÈ€ ;×{ ƒ SOߌ}¡‰„ ¶ס_ +ÆïELaVm¼»ir)^8(5`“þX$Þs†Ï!ß'û*à O´}•㘎^×5‘HKîkYÑ'ÌÊ ,.˹³0'üŒoj¸“ù ÞÌšOæ+ø¤“ù¸&ó±g2ßù|0ú˜?.©opqFêp"Jê£Ý+©ý¤>Ý’ú¦Ö ¾ž+L§¾RA}&ÁúÔ×iDõuüD}J1'êKØôìbUèë¬v*è3ÜŲÐwJ Â‚ÐgÌ º‘.bEÄ|ÊS'æë4*‰ù^’?³Ò‰ù:K ú”Å]Ðw7 ¯/­ò}Êô.è빸­Ð´^á›Æõ&¨¯Óp–ÔwqÒõPß%v õ]Èa–Ôwqy)ê»ø!õåj—Øwñ&õ]ð¾$õ]¢ RßÅÅ…°ïâd-îc}Þä¾K|LîCTXbß­gšØw ¢‰}Zg“ú˜1/©ïÖÍ%õÝp¤"õÑ™#©ï†4±ïF®´Ä¾[7›Øw#ö&±/·:ˆ}7\ÓûîJé°Úûn¸e'÷â±ï†ÕØW`ïOìc®œä¾¢!r_ábŒÜgËmÂÀ¯Dœˆ¸o>4ľŠÄ¾C"æ'`ŸÍ[7% ›(ÜËrìt—öY¿ÐØg½P x‰ûNI@“ü‰ûL‚ùÜwJ‚ûL‚íÃ%øÖ-éÀµ6Ào<\å9÷åþ¹/÷ŽÈ}ÖÉxqŸµÁ’þ’ ¸Ðd[Nõ…}–&K`ŸI°®ö ºçû¬ŸõÂ>“`¹s£"Cåï}Ôõ™ žhRŸmnµõåv©ï”HŽ$˜‰ùÅ|&`¿Á|ÇàÀ|¶ý…•8˜Ï6Ö&(°ÄvVÁ|ª!æ³ó\/æSbC1ßhØ\$òÙiЋ†éŸÈg½,BàâfF äcijŸ5!¬ñ)‰!ˆÏö÷°ñÙö]ü\Êí<Ÿõv à³í<øAðžùŸ=À{&‚÷lÇxϾâ*€÷ä6-Þ;%¨~§¸çKh€ñw¸^÷”ˆP¸gÝ€€{ÖOjî º ÷LR^¸7º àž;D–,¿"Þ>ðžr0ørË’À7¢Ñ|&Á€Oe?|EáÅ{¶ÏI– Þ³MKÜ]ðÞÙ¦°XßÑ.*žWðžerÄCà;ûAµŽ‹-ø,W"NŸ²' ø”DRÀ—{µ¾Á2Ù¾ÁbÖ"¾ãì ¾1ôÎø¬. Hjâ³~ÀCN|ã ¹ ¾C+ßÙ¯tàˆo0MÄg=cÈgZáêù´ Lâ˽cŸmt–¶&T€ñ+ïÊâæ·z ä;ä;ŽZRoóÒøç ø½ñ œ˜ûÛ󩔊˜ÏkºÇšêF¾Fìe’ùlë÷Í|ʼ(æSI1Ÿ—–~1ŸÝ{×úì(b`@Ÿ½¦X\úLò¼ Ï$õeêcd²˜oÞ²!Ö‹Áš Ì—[ʲô±˜ÏzÁÂû‘ <5-}tôÙç ýúL› OaÛ‚>LFOêðЧÐPŸ…\àr‚úT$곈N’XPŸBD}«¤¹-4PþyQßyT0“¹RbóÔ§x QŸIxTçö[ƒúL'ÿ `jR' æsª«”ØTÑo†â’ùìÿ4;óõ›9© }~Ô6¡Â­=;@ŸIh.ê3Él'õ¹ï\PŸIhD6ê³r×å:m}Väš3À2í92¹Ç>è'¨Ïo/tN}éOêsÇ~*˜³7ÞŒ€>÷L‡‘3 ïÕÆ™)}ÿI}’úÜÿþ>}~¿qï&Th☠Zš™ìò ês|XwûÒÇœÜç®ÌعšÐ¹”‰}îÛÜOìs¯n(ØçžÁ#­}éMìóc(qì3ÇVYSìBö¥;,±Ï Ø×=¦ì4÷¹ç-ûqìÛGůÿyæÿÍüûD¾ôç æóßX²ó™/,íÁ|6’ˆä$óYYärü<Ê™Éq)qfò«É£úÒK™Ðgãá.m@ŸµáJ* Ïoe|çoÚ¨ÜÛræsOhÀM@Ÿß6¢˜CŸu³= /® }é0MèsÉ:6½ŽrlrwórbŸ_ÚáS8æÔç^ë¸V*p‡Û¨Ïó‡¦ô>'õ¥g9©Ï‡ »žSŸ†®À>“„Ï5±ï<ȹÉ=óV}ö¶qÔçq @Å >“DVР¾×ïPÀÎŒ5`pŸ!hùsnò÷šìèàçñ¸×A~~-ë‰~Þ3m “íPA~Þ¤BâØämÀc~Þ/QðQàöOj}_» ˜häçÇ”ÓÐç@A‡&Ié'ø¹çqîócpPƒ“ÐÙrüXdöeıÏo°‹Øw|”ûü÷ û2&„ØçaALi@ S`Ÿß¸E\Љ3Fpß1iƒû|.m'÷ùM€­ºK‡Žýà>_<'÷gïè!n÷¹ž°ê9ö½:‘ Ñpq!D®ì;ŸØÀ>?õË_‰…£¨ˆ}Þ3¬dC*]‡TàŽY`Ÿ·ÁŽÓ1âyÚù<8ë>©Ï?¯°¤ ¨Àê¤>“ÌuÚùüD8uPŸD¡ÉÓ͆¡ôy¿x-ú^½@&’9Êù©wè³ßKˆwA#^¨€>“àžóùð±ù¸0üƠϰxƒú,fò†;ù¯æ}KÒ‹ºé =«$=ÛÆ5lk`ÁÐC^t=Û²€E 7Ò*г£bàgèŽ~z§$@Ï$²à¼Ü} ç™^sà<Ápºtæú6\:Yl5]:ƒ @ÎŽté”ÕZ.y¦=µCdéÒ)ó¼\:‡ÖÖté̳?ÒA=÷ún1ž×u K§<íèÑ™JÒ£s~ñèDª¡tèÌÑÒ£“Nrè̡ѡóEx¹Õ#gÎìâÓØÃ—sˆÃèÌ ƒIO»>2ée4é ¤OI“^>^4é ®WdÒ;Ž‚I/ŸšôŽ~`Ó;úÁøõ{q/‹XƒXvB“Þ‰vǦšÌyÚB“=ïhS¹Å+M{^^*ôrp鯩6rãT›u¿^»¡ñsa¼ÆOcÞq}8ã yÚ.•!o%‹aì‹ßò–¸™†¼%à…!ojJKÞ±å–<ÛWÁ# Kž ‰È’§ŠÃ²äÍK3Xzpη%ONN^[Øòr ¦¼c“ ¦<£ŠÝÈý‘¾ÂSþ”„ç-Ï{zpæ– =8‹Ð•.œhÒ…óÑn]8Y#]8å(Î'?áÂùh;‹.œ> ôá¬4?ʇ3½ú‡³jÉHN–ôM·*ÎG±—t ¹†>œUFC8@Ö4Â…3}øèÂYš.œÙæ– ´OÞ(Í‹uüÂt&¤gKs <8›h–œíãmÊSÚÒtàdÁßtàìZ(Ó3üèÀÉ”1éÀ™®wtàìiÞ+áŠGŠC^<1òß”Ý7»Ì­tßìÚ‚§ûf—»nÑø¹´¢ÿf×­¦ÿæÐj–þ›CtKÿÍ¡Íúo$l¢ÿfzºÑshËþ›CV+:pGÁƒsŠ‘éÂÉÜ éÂyœ[:ÐeŽ.œƒö&zpNÝJzpf8p¦¥"ù–œ“{¯ràœÚÜ gºÙÑsjAKΉÂpéÀ9e¢ç”ŠœéGÎã(¸?2)`zp.š:ƒsÉI‘œéEGÎ%›)=8ãKäÁ¹ä@ÎEZô,:o!,z&¡Ód¨°®t¬” Ü’EÏ£|ÑOXÃŒkNNkA_ѰèY Ž.œ¬=,‹žÝ %ô÷¥§<¹Ï¦Éç»gŸZègßpâ!TÐwžèg^î÷ ýæçн³› ¿ü°‚ü ŠülM†Gšä·4ÅMi@ó^P“Ýd¢`€Ÿá3ÀÏÞÅuóNÓ7Èoå{ ò³ïÏõ"?“¼|8•Çàg–ùò?¥ÚøYj[¼.?ks¿ÀÏ¢òq­~–þ†X€_~¤~–Øð³D§xï~ö‰$@BfÄøYEЋƒŸRï üÌo €Ÿå-—üVÆnü¬¢}6ƒœÒÿä§:d"?Nù©¦˜È¥Ô~*ð;:¹Q‰> ?sl  0ÈO•´D~ªa"ôSµ*¡Ÿ «E ßê %ùYöÆë審’m"?KÞÈOE›@~*¬ô³á2/¸É Ö`± ö[]´ö³|¯È=Uóú©HžÐOu„~¦ãýB?ËI‚µÐo ÚÃ@~& Wæù)éÕòÛ0 ägÉ'ÁD ?;ª½ÈÏNM_ߤd€ßŠÓø™d=¿XŒ± l²•¸M ?+GÓO“žgµ¤y®âLã»·tBòÛZŠ@~v"ÜßÊÀ-ßRèÉoMÙ?A~kÊ ò3 ÞAßî‡sŸ©€Gäg#¤§f‹ÔŸ|9 °wÑR‡~õ^£6-ÅrѨwéÝ&ú-ÍFD¿ ÑOß ¢ßZ|éH~ŠÑù-QSÓ-'ù-‘zZ…‹ü–H†ä·tAI~K›'$¿!#z·\E~‹&1‚ßBšê´é] Î¥MOÙ/`Ó»øÒѦwqq,›Þ¥'Ÿ6½[”L›Þ¥ 9Úô˜Ö4mzyëhÔ»eΦUïb¤™¬z·¢_É}‹ $pß’_nXõRZõ.Y”iÕ» K³^^šõŠlºKàÓ,îcPәŭ´«!éÕ†ºjÉt³¸áo¯,nG‹ldqûÎ1?Å­X.ëÎÞùëÌxÙ‘,‰’3kÚc¹+û᯳ÈŽ~(yõ3æ“ÙàøëÕOÈÎ~ 9û©%V…¸jøuöÙÑ%|6·bþØý¯.›ÛûQ.{&‹¨R\àOîÅtñXűGž6ÿÊÓ†>ŽVèçÕ }yÚÐ×+Oú:Z¡¯W+ö•yÚØ×™§}e+öu¶â«™yÚÐ×+›_él…¾þœln{5ç. UÙÜ~eÊüéËø½Iò§¯Ïê§Ió;Ïë—>~ ›[ñ"âïlnG–µÝtn™6î·:šD ·M¦ëÿ‡)Üæ÷R¸ýò¸­´»"@ßÖÅ1q Œ>–‚¥=¥~ág-m‡•µ´v#´èûŽ_m‡ù«xxw„}´ Çf@q3W„c?!XŒ¢Æ¨¸+Õ·,'²%wEÌôÄpz|ìƒKÁbÔâ¹ÔnôR#tÞª¥·Çnï‹cí¸ ¸°Ÿ~c£úÂA“ÙËà½\:P˜mWÃÖ5ÜÊ˸+ÂXî±÷Akì­ìÕjA€$LñeÔòjИ¾ ¶’2úEIØ8¶d1æsâ¨1! _³2f¸4ZËX Íàh\æÅôe°—oü®Œ ¼Ð¦0ûVŽûÞÀu ;¥eÖ!…¼“³!Ö®áwgþ2>V* ±öLÎì_ Å2çxmÈ—¹˜ü {e] €ÂJ»ìÛK0ùCì¥(GYVeö/ø–Õ˜ý‹÷{õËÁ–Çþaà,ä¸%ƒé¿à¦RÖ¤óHðd±Ä©!ˆã¹.fÿŠNžë¦çèû¹ÊƒO—ßH˜=ŸgÐo@ü<¨Êûö¬ðæÀ+úÔKŽ#±¿´‡BÏSŸZXIøÈìÕ=Gb’~j¥çÈ`Ïž#=Ü’ ^õ§vzŽÀèðÔ1`%Á>Ð~ñè9ÂÛRl-a$³õüDð’Úç815=¶Œ ¶xžöè„¡´J·ĦíG‰n#°SnÉ‚™q2Oƒ“ÒǧÑ0Çĵr}ã øˆ<¾µüíHôô ¾xm;`Æ-‹;¢û™¤Ó^ýšÁÃ~ZOoÍ>'j vl/?½ÓmOgôÁZ`?f’ø°?}Ñã»Bϸ*Ì>ˆÐÙÃzú<ö=•xóG(°.|dž Ø6¦ÉÑ®·k–,:"ðDN#ðÒÜ/Á #®çH HB; ç²êh!Á'ä±òhëtVx&ÊÒ«ÅC§øÓ<öEFõI<"3uxÐ tÈñÍN‡ ìî×vÀîsã1g8’E§ìÆ> :M :nô?V-$pŸxÖSN[ÑcŸäû4‰=öI‹†ß ¶,,Òö´2a¹‚âYc@RÙï¤Ã‡«:Å­«V-LYøtV«³T¬êÆàÔ뉲˜ÇëUïÓÔUíƒäϨöAŽcðRîõþ„J¸¹õ’ˆq©xø5­×jP Ö£j•Ñ€®Õ*£Em²¸·Õ £¡ŒcÜj…ÑPêñÆAPOy½¥ܪ}“!‰g¯Ú7uœi Xáõ±¸[tº¡A%Ô’`xFAar„Km-ÁÞiy«V-”‚Y§Ze´Pª³Ÿv§.Рr‹·Ú'9$0ØUÛŠ óR&Ô2;,Ž0TÕ²ÂÌ¢’Ú¼J;e} ‚ ^Ü>X ÓåïNÙvÐÞÝ_°‡e `oðeí)óšhOF0ÑÞÐzš´§p9ÑÞàGV´7h‡$îYz6¬Ô{&@¹À½.»q϶ ¡Ã ÷ºÌ<ĽLúFÜ3 É-xÏ$XɃ÷ „±þïh0iò&ïuïe:9òÞyTßÙ¦–w è ` Ÿµ!G.eš:ßÙ&ˆïlÄ×Hàë¬Ï$à3 ù.pÉ$õE|§$ˆï”´ûÝ‹T€ñŠÄgrcàÒÙ&pé”òÙœr½ïèÈw¶I@fLg“¦£IŸ ˆ€|¯ß‹™oÀ¦4P·Ò¹ÖH|نȗmÈ|Ù3™¯Ó`Cä;›HX‰|穙ΣúzŸ:˜ï8Q0ßÙmjMîTM€|]‘Žd¾ãL`¾ôD$ómR¬ïÔ'`ê²óóÙ§«*0ßÑÌw ¦¤ 85˜ï8 /æ;ôóÝóu†ÌùÎsSžg~ê"ïÐÌw´ómrüãÅ|Ö+z0ß¡˜ïì'˜ïì'˜ïlÌw¶j±úKG0ß10ß10_^: ßÙP7R@Ý1å>'‘ï.ïlÈwöРI6òMŠj^`¼@¾c¼`¾ãRùޱ´Ô€m¤ú d:ÛLúþrGÐw´qè;zé©[Höè;ÛT&@åˆA}ÇÅõýõý¤ÏdTv¼Ú'¥€}G7Ž}Ç`€}g‹T'©!ïút§€}G“>?Ý(Pßy¦T€ãM ÞÔ×§vï@}g›ò¼zõ-êýéFÍT¡@   ïìfŒO÷ ÐwtÌw4Y©0+€J@¾£ÉƒÑb£Äw Äw¶ æ;:Éñóiæ;Ï”:ÔôçômJù¤ /ŸFBßÙ¦]ï©ÏÔ¹R›Á•ÚL®„Ôfq)Ä6tYÈ6OêÀ6©C 3ñïÏÛFð³¼k&ùe0wßPò ’_¦Ÿ#ù™Ý¤¾È/ëŸü2!ÉÏl"´NÆ„/žk1( dèË£hè›Éy…áb4è€à3úÒbCCó¹ËÎwtÑ.„¡/Âø—˜Žv¾<í|‹ùWdç[ôY“OÓÎwDxˆ€}C†>ƉÈΗ½ÂÌwô 3ß!™/ÏD3ßdöt™ù¦@zÊH6høƒo ¾iç›Âü°ó¥ÑŒv¾)ȧï8Ó`„¸ŒŽ“U~ø€¤¡[iè“9N†>ކ†¾¼™4ôMnÛÉЗ×ë0ôÑ<دO†¿w™ÙùŽC¤‚ì‡M9YúfÓûòâûò}"÷åpÈ}ùöûì\õÅ}§¤¯óa#÷ eÆ!øéi#÷ƒ¹e¬d·¿¼w¿|~‡â¿SfÚSÚƒ›ŽËåäwŽ/È/Ÿ’ß1>ßqTIÊËÚwJ‚œŽÛôËgèwèwJ¾èP¨Ç7ß·ìwHÀ~C¹§È~G¯Oj@«4Èë ö3I§uïâTW_ö¾ãn‚ýΣ‚ýl<ÏÁ~9ïû½‚ýŽ» öó‡/Fö;ôüÔ/Ti +a ÓÙO S΄?ͼd¿³›Õ_*µ/*þŽKú;Þ:ÐßÙOÐ_NH¤¿C)ÐßÙOªÀ6ANC9ÁHÇ%ý™6§¿¡¬V¤¿Áäc„¿œÀ~Ç•ûzƒý¬ Œ¥`¿ã‘û¦øá´ô; rÊPFö;ßù»0ó3ýå«Mú˱‘þòù ýåàHù4þÎÑ­ö^8þìÕ¾a«»¹âø@G? ¿œÄ‚þŽñÝ_týãýiö$üðwfµ÷,GøËEá/OÂ_~à I „¿ãâ8üå£HøË‹ðw¶ øË¥#á/yˆðg£¹^&?[ÆR›ð—‹oŸ՗(áüëéÛà3ÀKàS"DŸ2D ø…|J­%àrÑì nG¶XñžÂÝ޻رxÎÉ{ñK¬K´X¯¥Í¬C4XoÊ—‘¬§üïìÁE°7>@ƒC%jì•ÖC¤<„J7Œj"%:‚õToT¬—V«ÊT¬×ÒyT¤$‡M‘26ŠöòÂöRmÒ^¶IÚƒÿ =ID{4’ö”ïï =xq‰ö.¶ÜxHÚƒ—ÉáÕ‰§L°¿Ò£É=ùx ôxšôèÄÈÈyƒ¾Kâ<%t;8 â<ÞÙä?./‡Ÿ€Ç •€Ç^ð$ù2|^öœ€WÞ|—W3ùx‡ëÀ;öº»ød¤¡‰î0Wˆît–„;ž%áŽÓ£Ñó Qž‰l§O“ØNo´ØNÃ'ÚÛŸá¼Ivˆ%Ùåy“ìØ É.oGÕøËÛ“s(!åAvp­ÙqúØÝ€ìò–ìèxÖ¾¨@²Ë‘ìò‰J²£R$; †`—´Cƒ|V€Xת+¬;N´˜ºþJÀº—ç1ø®Áó¦êrd„:}úuùrêòÒêò©KªÓÙADzÆu@1~Ýõ5åætÁ†FND²\ŽŠ,—7‹,—Yî8jŒOº \m–Òµ¢ Y.õ"!^퀹¼„9ÝtÂ\ÞŽ)øM©ÀÁ$ÌáÂ’åô)Ëi!%–ӹס@4~Þ’\^O¢_)¢\^¢\^)²ÜLP)@µÉr9˜Éå>âb96Ë)«©XN—J,§{–;Z€å莘,‡XN:Šå‰Æ¯~Sö,–ƒ÷õi½#”;$¥|R)Q7(w´hŸ–kB¹0QîŒñ~Är©Â*T8UJIÄAP3QާJ”c‘9q(qœÎ+ŽÃÃ)ŽÓÇ&9Ήáâ×},ÔÄnŒú‘Ül‡Ç¦9`ž.›4r1>€’z ¾kªÔ:Ѧ³R«‚ï ‡LAG€ƒÊ2@%“å²¹´†Î½ëÌ]˜bÄrW²ô*m}5òÆ1‹,wÉE–SMS±Ü•„8bj¸é]-šSÞÑ3Ò ænùë‘ænºˆænq‘æTÄ4§#¢¹›^梹›_iÑÜ!ùñ§U4w3ƒ—hN9ôDs7SŠæ2‘4w3ÌH4w3hD4wó¡ÍÑi®ˆlHs,*˜KÁd•Ók¾ü5-™É€i @W˜úD@W˜—Y@WAE@WXóH@Wf  ;$= µòY$Ð!õ’¨ ) +Š“$ÐFèX¨UÇæåAtÙ KƒBŠ’‚@ QQ¸!¡®00[PW@K¨;ŽÔg— ’ŠbIuÙÉN Ð]CºKFêÀ6©CïÀF…Ûá»ԓxw´Þ•dKé ñ¥åå¨i’ûå¨yôx—½ïŽcÀw©ÃL$¡bÀÎ,jÀ;ÚLf) ð²Í’á’’Ž£žóË/ÂË‘ðŠ¸–„wH¤‚H„tœ„tÄ+L(Æ+Éo`¼£Mª@ UxÀ…õ~ÿn×['1žVMbœ‰Ù,­òWm ë–7òý¬¿½³-²ý‘˜í;Çü@b¶¶?™ÀŒ¿Îfy(9¡µyÝ™P¿^ý„ìì’³Ÿ¾yù»þ9ý@vôCÉŸP­Ù}¼ß Õ~%…™¥ö-_rN}ið+yÖ>e>{?+uÝ÷7å£úô\ôÅ{‘e*Ž<3šÙѯ|fèáhƒ^޹Ѣ§3Ÿ™õôÊf†žŽ6èé =Ù̼§3—{Ê6ìé• Ïü‘ËÌzzå;ã›’mÐÓŸ•ï¬_ÿ5¥;û•‰è§/ÓÊ÷¦žŸ¾< Ÿ§¢¯é×>~ ÝY«æTòNwöùÌ~Â2Ë¡V­*Èý/HXV=OÎ_z²_¾“°ì—?4aÙ¦W$'³ý×ïȘ°ìé¿‘°¬Úg˶?mKo=¢¹¹pZå‚ßôU»ÁÎu=áÝÈQWeü ÜåêjŒŸAÚýÎ6îv¢›Ám5ú#­É6"öw6d•¹xÚuÝHç3Y»îHt…$èí*têG8È–,$UBù v=‰a`jn[¤L¨ì§½S&´«7¤õ²¶kT¤ÀEʉvͨ…­è™v-¯#½_Æ`Øv_^GúVñvß^ »T¦^Ùê_û7s³ìŸ^ {ûŸív\‰u7a{%ìʺæín^EºMîà¶»{!ìÞI‘í^Û®olm¶{z!l+\u£ŸP`©,C+®MEØtj{B2É-öÜÛ˜Oe°ßæ#ç.-(‡¥HŒ£Vª-(Ç3XÈ£×a4•5mÅu° aädß3mM¥ ЭX-´oÃÒ¾„â–ç±³å<]ÛsÙÖÚ´bèñœ·ÇU˜Ê{l‰©0÷mÁ“öØÙM={ϳñKgŽ•Ý¬*¤·§Û\›MõRÛþ­ÓìJÕ×`Ú]˜8Êj}³ÌÇØöje(ùf™‘2iϾÖðœÇqE7ãXVÚØèØ’X¡4¦òoÕu°ØÅof7p¸ìø½g‚eɨcM½]¶ÁfÓ¬ÚmÍ€xÝâ뾞EëîþҘ˒=ã1ª®À²²'áúÕö›kKÄÖ˜Ö¬°÷–¨pÝ–Ø›OáxÑöݵÎuÙfvHÛ`³Â;7z6zaÒéÖZ·¿[nŒøÝmê6¨Å¥³ eëT2Ò´æÉŠmƒ™¢yvšoVµ&V?ûýr¬DÊži¯LþÍ Œ|àÔý^.1JŒ7ÌÞëý±»**ç´þ ×ÈŒE!¨Ý²Û~MÛ êâ(`%9btöï»´Ÿ3Dœí¹×ö§¬DÊæÎ¾l‡Íʪ|Äu×í*ÙÆlœhXÉp;Õ~a$®Àþï£B XÌŒöÊšJ¶ ÃÙ¶ét—›jÖ\)3Ê M·‹7ïãp¬†R[µA,ûiH,åNœ)¼ AV/áø´"çß¼lž‡y/×Êf HÊt­žEfè`LËöb›Ä¶ŠÑ¦yÒá{4Þ˜Ùm‹Í ÇÖ¶_ckQùHL+ÇóÍÒÏ󑘡ƒíîãU^ÐÁ@)nÕ²òõvî…Ÿ¶7e?±?¹Æé*u¦ïkF¦’½à1”¬FS\¾ö ¿p¢^]â59B2<òmÞ¯h3m(Ä¿-”I.Ü–n_eS©|²ö« X©Iè`[æ3$6÷³¼ñ G=¶¿¶¿~#î—Í®q:$­Åã÷à÷ :Xù¬è G`‘Ê~Œ'Îe™íÃ7·ÛwÙòä– ·²ÛwÙ´š,æ°%˵²EAœé†ža($F!yÐsí®•Í8ªÙbÈë€ð콺V¶ŠsÙ4hm*B¦û:4´qö£&徿̖[úÁßM=—ì¿Cbk¡Ûr¨Çýî¥ØrίD|z ü3£+ÐÀ?0?kËà¶–’^]%³bÅ%·`§ Á,®QåäÒ­˜iÔ ^ºþ¸Õ>±ñÛr0YeÜû(£žû*ûUÖÏ3ü.iÛŸÚ?ðZâî?T`b‚ê°ÉcKjŽnz>ñX„¸ÀªYæøÅÛo%ÀL%³Å««`ŸÂ‰ß¡Â¼âg™ñÓ¾@.°‹j}V¾:µv¿Eö¡›è#5†_»'6/– +.nÅð-'Úpø{Ö‹ñ[°£‹uz· `¦Ñ~qñ¬˜o`˜Q.$÷ŠsÇro¡‚›Ùb|-txÊýë¾— .¹.¬Êúþ,»V{[qû+WC«}n´±Ô¾ÐSç›Ñ0{ö:<^8ÄVãÁ3È[µ:HbŦ ¸¤VÌ”z,Ç`HŠ©í»ã÷3ü¾4æ1î*ÔÊ硇 ÏÝ©ÔnäS£±|Åv¦‡oi·*n¦ÔÀòC»=fRŠ£u¨ølpg§ ¬ðwâ2Rßgâæw½‹ù˜–.‘è#äô3ò %h#ò)W™/3Eù "æë+_60Ÿ­À-Á|—–’d>9•ùÒFæ³»ÑAŽÁ|Æ@Ï‹ù¬Œáó‚>ã˘»}æà3€¤¡ÂTùR0Ÿg³Ï]‘,øÑR7˜Ï½^ ¯r‰>}G]M@Ÿg߃Þ7¨µÓõŽÔglÀ~ƒúì3‚µ-¨ï4sú¬Xä` [))àVÅÄúö'…¹ ¾ýu`•k§¾=©3¨Ï ø '¨ÏÊíñò«²zƒúºµl`3Óòì}cÏ/ððöVtËû†=Þ3±ÏŒ´ÈNìØç‡ðhö ÷•‚Ĺϋ¼¸o el÷ÙJžmpßð(¾¸-Á}æ‹…Sö™+<)}féEín`ŸU*"°öÍ»1¹«cß´÷k[Ã>+)Hì3~/<³cß<è7¸o¶¡‹ÜgKÌà¾Y/ø½û¬nSöÒ£û¦mwÅWÜg¾YØ|øMÏìÓÀfÝvrŸÕ6âÜ7ÝǬèÐdIÁ}f.†[!ÀÏæytÜgÓ|,c€}k/²ùöíÇCHØgE±yÔ·l²Ùõ­¦ðA§¾5 ,ê³Õ7N ØN&KRßÍÏ#©Ï˜5©¯¼ï*•ÝùìSçÈwÙ§Ý1P4H‚˜.缟“ø ¢^N|f‚æH‚ø.eu'ñ]Õ*?»ÄwÙ¢Ø`ºàbEæ³n€Ðd¾=•c2óîà Fæ³­ "˜Ï`&.9™ï¾â'`é.XøjùÀOðž劕y¯.1†ÅaÏ©€m¥:ð´ön²IïæRš¤çðñóz^Róçƒóì“ I0’qq2 :pžÕ E›à<#?,ÊÉyûËÐÑ38ÏÀG™æ§G´ºîà,ÚÁyv?pqÁy÷°šï! γk…e<8ïî¢vpžm”ij"л¸MCлý^üœœgëŒÝèYmL,®z·;a¹ä ñÃiÀ®ø¢¼çMyv.t”gGá΂òÊœ¼þ ¼Çˆmbô¶®Žù’”÷ìya€“l ç˜÷¸uÐ%À<«FçÌ1ÏŽ3ó̯ð´“̈ԫÜcê­ÅKGÔs#~H€z³~¼HÏ a’9¡‚M¥(iˆÏAzV¡"IÏòcƒìŒôž<5H¯>7ûé™n”&Õ‹›©$=«sS/I¯î•âÂh‚ô[‡ @¯¶AèÙ¥ÇÛÒ«¶³Ò qJªž%^í̘¤gå>±?Ò«­ð~wª°>‘ž• %SéÕ»qAzu/0ØsžÅþ H¯–Ê÷iP‡Ž÷‰Î^DøÛå*“…Ϫš¼g.965°Ò W%yO%Rˆ{6" ¸§Z ¤=óåFÂ7ОÑü€Y0h/Sô“ö2M>i/+3ƒöÌ„ÆÏ¿ÑÞžûY@´×Ím \^TA°w”¢$ìe „ÃÀGã-|UÖÀ^V±%íY%š$ƒö²>qÏJèÆEÜ3ó"ö›ÝÄg[*XÃÆg.›4¼A‡‡åhã3çr°'qo$¸÷”õïÀ=¢0pÏЧ¼q/ ­Ä½Êè âÞ=h°%îÙ·¾¸Wî4à2 ÜÛÏ?׈À½¢,øÄ=Û×ä¹÷J.j{EÅtˆ{%Y ¸·Ÿ‹FsœQÔä=kƒ+Þ3¬ÅÓä¼w+ÏxϲïYܘÀ=Tœ(T¸•š ¸g—¡”À=k#Cšãž…·!pÏŽ¢‰9pÏ$4î™y<÷ü7èÉpÏoqÐqÏ{¥ÝÏqÏ%¸ {æŒÒÀ½nû’àÌPÀ6bhHsX2Lé”8-õM 4AÆ6Ç=s{~ãžM± šýnxÇ ÷l(Xtíõ®šÀ =³Ó"´g39¢0@{ûÁØ(Оí"tšô|üMæù€½î*sV²½¢³^oªŠÖ3 g(ƒ½ýñ”E/ÆoZý•l_„¯W°Þ¾°zQ‚õÌËb ž àýÖÛK™›öL‚(UÀžm¸À°çþ – ½=8ú€öL‚„ ½šnA{«+ºš´÷ä&RО¡'gá =ƒ\¢}ÐÞ¬ã¶|óIâà›Ú›ïÍkhº Þkj¢Þ3/NŸo`Ô4ñ®Ò>óGºQŸmÀ4Zç\…a“ß}ߨò™ñÙF ¢ƒøÆ£Òd >«'ͽ’ ¾a ‹§"ˆÏ¶‘Oâ¶Ÿ‚‹Ðwn>ô ÿHœÔg1ØÊõÙ5±Ú êëV^¼Ã¦ç:XdຠðëK%Ã~Ý>Å0û™×I%@:ûÙ.fBÀŸ=:Ø¿ý™ïö1Aveññsú›f&Çø‚þlõ6@æýÙôg„è:LÛ†£%ÐÙɪb#ô7oZ¯Ó–wÀ«€¿‘”öà‘üœþ†E€ö4òÙã7‰h£):ð7öÔQNö³ã¼Á~&AM°ŸE{ 1ØÏ|v&í€NOæÕƒM,ÀŸoPBí€?›@²¨Ãß(7S.:ü"ì4üóQ˜:ÿìá¬òÀ¿q+Š øçsÙIË}OŸo$ñ¼>~w ¡­ÐÑÉÞ!ÄHþ–}qq‚þö;ÉÅèoîg™©œþ¦ÛHƒ¦ÂlënП?U¡eÀŸÍacžðçF´Ø9üY¼)ffÀŸÍv­ƒ®‚Å­^¸c nËþÆÒwðgŸú€¿1 æðg"œùÃNRø³md¤/ü Û~89ÙÖ3&xÀŸm6c®üY\Ñ ¹ÐéÏ>1ê9t°ùö¸+6¾;¶ ?{>±îýÙÓ¸h×+ötÊJv¾ýxâJ€þÊ=§ ?ÛqÁ‰þî½OÂßeE9_ðgsÛþlÓSÀŸaâ†éTÞ/lñþV²2Ÿ­*ßÄÇŠV$¾þA£€¯¨t‰¯)ˆo]tû#òÙîô‚é0o5•Á"òµÄBðÒ¤IHÈ—V"÷Í@|iÃñÙ’€ÐÈg|ر&ò5nïÒ¼7e•ñmÐE¸‰Ï\CiÍ â³Qc-Dû^ýäÓ™…eßS•;_á—'ì{+ý!ißk‰°ï-Î*¾[‹7ß#«/}$ |KvMÚ÷ªVî> ô½_Àw¥mÀw¥-„ÀwËÚàÀgÁÁë|6™ÃÖà»õÑð¦ ð5-æ |ªpEà3ÿ¬P|O“qÀg~êXáøªâ¬ |{‘J”ðUUš àk _%ïÙ÷¾aབ¦_K5|{ ƒcŸ”ðÙÜŀϞQZÙøLBk^Ÿ™k¡ÂLã¬_Ö à›J¥Hà[iPðÙYNûž»ƒ|æŠ>ˆï0Í‚øìrBKŸ¯Ó‹3ˆÏH¡¾ˆÏ, _ËÇĉ¯=D›`"¦ƒøšÊ“ŠøÒÍ7‰O'ñ¥/ˆÏŠ'·ÓÀ×=áNL¹CFäË,d¾›q?'óYmTJL…ÉBd>+îIÿÑ`>¯ƒ‚@¾½ÀF® Ÿ}I/–Ìç»V$ËØÁ]´`¾Qvtæ3ÉELg>[½?Œù¬/î6ó²ôu2ßxšœíƒùÆ“Vâ`¾>+œùºWË=|vý®ùúÒ’Ì×½Ô$Ú8/u‹.)'óÙQ7%Î|=+>:ó¹›uI—¡‚}¾IfÁ|öúb®ó™WfT0Ÿ%ªy3Ÿ{^„Èwé #òíŽ “@¾Üwòm,ä— È·§Tbª#Ÿ9gÐÀÈWôí#òù„z:vÀÈg(( ߨÊäfŸ":òÙQFò™ÏžuÝuèKUj|öô?I|cÚéœøì•èô¬tâ³6D¨ ¾ý =;‚L´g¯O!Ê-Ùý‡+]àÞ¸T Œ¸w©qo«($ŒáÛŠügÿ›°N{="N§½-éëE{ ô½[)˜ˆ{wç´g›¹°y€ö¬cœÉaÉf´IwR‡={uðùìÙ[Šy°ç3ã{=Sž;íYæ¨dï5Ÿº =K8Ä›´gROàžM•lâã·w–Ü´gŸ¸F ¡£ÒÈmwО?Îx ƒöŒ!$öì%àó`´ç-D¬•ï,`Ï6w¸ ´gï1(hÏfTìŽöŒÛ1Y‰ö¦´g§â½îU…*÷ªÛˆ{»g¸±÷ª–{à îµ<pÏ’p€ä‚öl›–'%ã^î¸íy‚$šö¦ÇVÀéÔioÙðhŠt ' ½&J•_wÚú.»Ê'íÝW/ôv[Ÿ8ÀË´çNý8&hϲúÀ Ú³™åmë³Ù—B¸Wè¯MÜó¬!î ÆqÐÖwÕE·ÝAzØ4$¿™Ð¯­—oç:,{Ò WÚäà)oçá“ ßN¥<#ú‹;ÏD¿QÒÛñ|•ÛŠçyö@?[Ê–—o§,ÌáÚiF`ÆØ… N°‚ü.ÖŠùåÖônZÚ£ ôsÃÖ}~{öIïÏç;âÏÎ×Jšƒ›º¢Îç>°¥E8_V[ßdnšú¦ø"ÀÏüùømÉÄËÜç ¤ûŒæ³Dhôn î³£GÜ—å£Á}¶)IïZDó­©¥¢ùÌ{£ž†¾Ù´Ð2ì³+’¢Sß<,CA}æÊ†Õ[@ŸoÍâ¿eKá’/˜Ï¢Õè<Ìgžk(jæ³·çÅ|Ëë‚“ð.wC+ „ äY È·_»ÊØC¾µLå9ó­µÔI‹yB@¾û² Gtë„£ÚéÒéÁ]îŠi¢ïçþ4ñÝ×~~éãéÄw[”7ùîŽi¢sêe ßRê'>¯¡¹®z<§BŸÿ<'ñݶr©ñÙm#€T(`{ó„æøÄx»„³'’®— „«p˜ñY®DLÅŒä»;âCȧ0¾Û3|%ñY†CxS1ïv=~ðm~¹‰|w<[?‹÷ËtE'àžÃ§ÏgàÒ´ExUFÜSuÁÈWÌ2û\DòÙøZztZ2šÓÈg霢ÀçÐvQpÜ @_±ý³ÓÄçñEt²Œ0¾êѬxŸö¤½Û“Àí²V8¢0ˆ¯xÅŸÅzËâ¬ÈvÃWs&ƒ7gugäÄè愈8xsVGe—À›Ó\rêiß³¤xô-…Cgµ4„Cçcû¿ð³ ÌÙ†¸p‡´¤fÂp‡¬–†æ„=“¹>[ µölüxÁže:£d¨°çvøvѡӮ^'ý¹Säc›ã€´ðè´·åeß»«9¿¿¢ølÆ‚–íÅgkÌzÂÞ¾½õ〽Û+"+ë³¹¡Æ×"ðê|ìSðŠâk±Iðëlƒ é×iד¡vá×¹ç#.„‚õ¦àÂé)YÔ4›KÑ$4°4ô ¿È§*JÆ};Û3¾í’“|;«› qßNÛ m„ Í^°\xFÖ=XoàÛi ÌúŠá«¶(%†og-½ùàÛÙxêP yäEHܱӲžÌ+Òâ%dÉsÇNÛ|fˆ_8vÚi) ÇNsŽ©'홪\ä±Ӝéèü®‘¶S»^Ž6:\xv>r„s…g§Ç]¼Bø,߈]˜ëÞí»©/çNÓr¼œ;÷—4;m;•6ÁpÑP ì=eP_h`Ž ”„g¤_ ž‘uNQ¹ÓÖtxŒàÜiëG™ó®ðƒÄõ„s§±}?‰ïvŸ´ ÏH{¬à çNó%!»…s§íaäçNËu„ñÁ»ÓVq”@»w/ïNKÓ9_q|¶þ¼âøìZôû³fl£zÈáÝiöz„.Efô.u¹iùӼæ°EçN{/á ïÎî¹ðùk9^Ζ;’ÁuHn´—Ö ]ßþîÓ‡5€ïnŸœ;›û„L†íø|ýØ àëÂï|m¤$€ÏîÔ+ŠÏ@ä~Eñ5» ¯(>‹|‚÷~o%3ðÎÚÜú²¯R$Äùw2¿Zþöï3uÑøÓßíÏà~ÂëßþÄ?KÙÿúßÙô—W–#Ûu²ðŸøû¿ù‡ógõýßþçŸlfXsýíÿȃþå§Ù3éôü4ö…<ÎòïÙÍÿ{ù§<ôßýåP-66;ùÏ9„_þŸ‡ð{Zý[Ê~úÓß·ÌÞu=öb'ùO[hö_}|Ε˜îÚ½2´2›˜Õ&õißÌY$ùý±œêË’Y\ëì ’rfwûûdôttGÉoÚŸÕ…™ÔïsD”üО†º³÷µ¼F‰u÷_þæÿw&endstream endobj 6 0 obj 164230 endobj 4 0 obj <> /Contents 5 0 R >> endobj 3 0 obj << /Type /Pages /Kids [ 4 0 R ] /Count 1 >> endobj 1 0 obj <> endobj 8 0 obj <> endobj 7 0 obj <> endobj 9 0 obj <>stream 2020-10-09T14:32:44-05:00 2020-10-09T14:32:44-05:00 GL2PS 1.3.9, (C) 1999-2015 C. Geuzaine gl2ps_renderer figureOctave endstream endobj 2 0 obj <>endobj xref 0 10 0000000000 65535 f 0000164780 00000 n 0000166293 00000 n 0000164721 00000 n 0000164588 00000 n 0000000266 00000 n 0000164566 00000 n 0000164873 00000 n 0000164844 00000 n 0000164937 00000 n trailer << /Size 10 /Root 1 0 R /Info 2 0 R /ID [<65044504397A694DA276CC650DBDFBF6><65044504397A694DA276CC650DBDFBF6>] >> startxref 166513 %%EOF blis-0.9.0/docs/graphs/sup/dgemm_ccc_zen2_nt32.png000066400000000000000000006377301422157504600217350ustar00rootroot00000000000000‰PNG  IHDR¬táÂgAMA± üa cHRMz&€„ú€èu0ê`:˜pœºQ<bKGDÿÿÿ ½§“ pHYsNNÆÊ/¥tIMEä !0Ÿœy>zTXtRaw profile type xmpH‰ÍVI’Û0 ¼óy €€ôY$o©Ê1ÏO”mylÏdªrˆTÚHÝX©ôûç¯ôG¡%'ÞyØbY‹²^´šPVÒª¦«vnd}\.—A†ñUÅGªq•ÆYšeaÈ.º&Yl3,¬l›ô*Š'2cîys0‰‡ f‹ËÔT¡z7<%c K‘p%ÙE‰®*lá ­Íùj¡ìߺk7ö9ç¨%]qx›7ñ0æ®c—0k‘V3ù÷À¹ƒýêîHLÔyÅU¨qa¦ Æ–Pi:ð~¡ŒùÎ c'Oå üü˜N$ç¤]LpfÞÀkXÔ BÔC±Ñèê'Þ2È 0£M%x²!Vnš-p&0m^ѵ.Ïp)„û)&i0´ÑðŽ “²{ìÑ(‘"|¯îÁ„íÀ< ’@÷(âxŒQ~m¾öôŽÏ\r0â#†ùp±Ã«F¹â„¯,ˆ”L('ˆ–G´ÂîàOŒKpì÷Œ‹¬ú–³Bxp·gz(Ú¤¹q ¡¶‚[qFäÙqOJ¿Ã¤*xÞ.Â]Xb5€{æ= nJÓYëT:+ìqÔ9s—x›¾ûRé6}AÔ£¹Ã—;SÍZ>ÒÀë1¦E˜V= ¥¥ YÐ=Т¨GTDÌc‡bækN€.“Þ¥üLŠÏËâœ8é¯2i ÍõEi\“'}•=PØ®Mî¦Ð¹ 0«Þ³¼[zv´s°©ÑÚ7´ÜŒK¼,Ö‚wâÅ› |Y`F\㌷â 1Á1¸ÑËÁ㋚zWRég Ä/ºe†<é~ï”.‡{MXx³Ž›¾9Z(Û@Ô5ûÜ1ÌÊf© Ó­óDIÎ¥>‰kr¸›X|;¸²«)> RÏÂéÞ©á°(p?:v]d8xp‘’]cSôË÷p²6Ïü=áÌl}æ2}ò‘³9£‡Ä?S¯ÞHËGcPƒžC^¶z§^s¸«¸rx†;1†¡é]}”Ænz}úðlÙh ÿäüGŠòö¿1‚¢ù?öôóI)jó¿-ýFeX`õgRecaNvPÏR¹7€IDATxÚìÝ{|õy/þWÛdF@Œ1*f„1 ;Lˆ¸$³Á&-¡¤#¥IšØ'h6I5ô(잤¸§¤=ÙIõkâÞ’“š$$4‰[ÚÄÑ„Æi¢$DCX\šØŽm[60 ßßýÎήVÒj/Z]>ï×K/[{™Ûî>úî<ó<ßFGGGADDDDDDDDDDDDDT†k½DDDDDDDDDDDDD4û1ñHDDDDDDDDDDDDDec⑈ˆˆˆˆˆˆˆˆˆˆˆˆÊÆÄ#•‰G"""""""""""""*DDDDDDDDDDDDDT6&‰ˆˆˆˆˆˆˆˆˆˆˆˆ¨lL<QÙ˜x$""""""""""""¢²1ñHDDDDDDDDDDDDDe›S‰Ç àºn­7ƒ*(xžWÑåUó=âº.‚ ¨ÉºË5Ó·o¾î •Ïó<ø¾Ÿs[5ß#Åj¯»\3yÛæÃöSõMå=2Ñã Å•b–Ç1·•¦_þçuªï‘ñ[é8PʶM§™¼msa{irµ<7À1ÁìÙ¾¹ºíTX¹q¡Ü1ÂTñ³?3Ì¥}¡êà9à mÛèÒÛÛ;:ÇviÞ5 cÀ(€QMÓFûûûË^nµß#F{{{k²îrÍô훯ûB¥ëïïUU5Œ#º®ŽŽV÷=2Q¨öºË5“·m>l?U_±ï‘ÁÁÁ‚Õ4-Œ+†a½nޏ­4½ÆLå=R(T+ŒŽÎì÷ïLÞ¶¹°½4¾ZŸà˜`vmß\ÝvÊUn\¨Ä¡üìÏ si_¨:xΰ2Û6§*iîH&“ð}ÃÃÃ…ªª°,«Ö›ED³Hkk+ ÃÀèè(†‡‡ˆØBD4ß÷á8Z[[ ÞÇ¡ªjW<Ïc\!š¡ÊL ˆ¦W­Î pL@4s•x®€ˆ¨úN®õ”˶mø¾EQ iÚ¸÷«ª ]×áº.LÓ J[ey¨a9ÏO&“H$°mA@Ó4†‘³¾D"Qòã'’L&‘J¥r¶]ns1÷{ÌÀ4M¨ªZôý“=w¢}*öøAÛ¶ÑßßEQ ÜßbŽïûp]†a„]סëú˜í ‚–e…¯ÿTž;•c]èý)÷3(ŠÓ4Ãý-æý!¹® ß÷Ãý¾FùÛ>Ùs£Ç¤Ü}Ÿnë‰â€<•ˆ•ŒÑ׫± œ81Ù>{ŒŠùz\€ÙùÙ¯Ô;p]Žã|¬\v?„ŸYÛ¶s>OS}8F(¿̽ïåŽä2ŠäÇù¾( *¢Ç“c„òÍ„ï¥<¾˜×s¾~(çÜǥǂÙ<&˜Ê±ÞÏ1ÂØcÌÌ1B¹ç ÒÇûS9Ö#L|Ì€™9F(çûB9cž3,>ÌêŠÇæææðŠ×uÇ\‰–L&à ¯T“G˲ÂÇA€æææœ?Ròþ Z[[‹ÅÂ?D–eå\ 3ÕÇOIJ,ÄãñðÅO&“cÖ5Ñý‰Çãá1ñ}ÍÍÍ9ýÌ'º²çN¶OÅy›üÃïº.EÉyÃOt |߇mÛhll ׋ů#y» dSyn1&zA€ÆÆÆð—ã8ˆÅbE˨è¢X,–skkë˜÷õxÏ•*±ïÓm¢c=QǤR± ’q@>¾± œ8QÌ>{ŒŠùFà9ÃÙñÙÏÇ1ÂÜ#”ó}¡œ1ÏN!Ôº7l©Òéô¨¢(£ƒƒƒám²¿÷èh¶ô~UUGu]ï‹öÿ–Ë“Œ¦ÓéðwMÓFMÓ O$£º®—üø‰M$9Û–¿®‰îOÿ˜c¢ëz¸¬‰îŸì¹ÅìS±Ç§»»;ì±®ªê¨ªª£Š¢ä¼^Ùo8•JåÜ`ô_ÿõ_GŒنɞ+熛l?{{{'}æ÷DߛŬ#*zìò—‘H$r暘è¹í{1ÛU+ë‰âÀèèhÅcA%ã€\ÞtÇ‚râD±ûTì1*æó8Y,P%Œ!ªªŽ™ã±P,¨TÏïýY­8 _“RbÁlŠÕüì×r —7ÞûºÔÏýèèÜùì—:ˆÎÛ2Þ8@*4w\N¡ÇqŒPü>0w¿”;Ë(4(6D·# =†c„Ú™IßJyüDæû÷rÎ pLPz,˜c‚|#ÌÝ1B¹ç GGK#ðœáÌÿìçãaîŽÊù¾PÎç ‹³¶âQ–ÅG¯H‰–‹:Ž3æ~Ã0ˆ,­ªª‚ ,—–¿G¯x‰>WQ”IKY§úø‰DKT UèLv!…ŽIô ¾‰îŸì¹Å(öøD¯^Äàà LÓ“ÕŸìDKÓå{ãW¿ú„WKÈ÷D1ϯEc!“½?åíñx<¼:«···è×r…ŽAH&“ÐuététŠ¢Œ¹ g¢XPn&~V+ÈפœX0â@µ?ûµ¶KùÜw\fëg¿”1@ôó;Ù8 ‰>CSù|qŒP9ü>0w¿H¥Œ€âƵŒÇ•4Ó¾”òø‰Ìçï•87À1Aas1DqŒ0wÇ寅JŒxÎ0w›gÒg?ÇswŒ •ú}¡˜çòœañǼP˜µs<Ž×2Ošè`ù¾ŸÓ‹Vš-}©ç:]×aYVNPJ$°, ®ë–ü:E•¦iÐuñxƒƒƒSzn1&{ªªŠÞÞÞ°Œ?˜¦‰t:]Ö±“-dÐ*÷Äw)û>Ý&:Ö“MƂ٩˜÷¤ìÞÝÝÞ¦ª*š››sþ@N%”òY˜èýY­8T>ÌÄ8ÀÏþüSÎû0ÿ¹SÈçŒg*ƒŽ*‡ßæŸbßsÞùÎw¨m8F¨$Ž æ®jœà˜@˜‹± Šc„¹«Ü¸P1ÏÎ\#Ì?µ:oÀs†cÍÚÄ£ªªc²ÈÑ€¡(ʸDÓ´0K}®çy ç‚üc’?¹èx÷óÜJ™èÍ>•‚œxUþ?ºýétAÀqœ1¦NöÜbLöþ”ÆÊ««<ÏC,ƒ¦i%OÇq`Û6à•L&§|µE¹û>Ý&:ÖÅ€± j*ŸõéŠÑmê{2úI~.¢WáL *ñY˜èýY8T&̆8ÀÏ~iæúg¿ØçN6($C ý¿X#T¿”f6|ˆnk)﹉Æû÷ïPÛ8 —Å1BepLPšÙ0&¨Ä¹Ž Æš«± Šc„Ò̆1B¹q¡cž3œ¹Ÿý|#”f6Œ¢ÛZ‹ó“>ûS9Ö#6[ÆR­ÎðœaöÿãÅY[ñ¨i‰Z[[¡iZ˜9ÎÍ”N§‹Å ëzØ3WÜT*…d2ß÷s®`˜‹ EQrzw¿Ì°÷ÜJëîîF, _Ÿ ¦üúø¾ÆÆÆðù…J‘ ÀaˆÇã9Ë/æ¹™ìýiš&ÇAcc#4M ¯–)拊išárƒ ÿP†Û¶ÑØØUUÃ÷¼¼’Á4ÍqŸÝnÏórö}¦.&:ÖÅŒ%|Ö'‹#ÕPÊçQÓ´p;åû}¢÷s4ÈV¬åƹã½?«ä¾” fKàgêæÃgªÏo0žT*…X,Π(JNûæbpŒP9ü>0u³éûPz˜hâ£q@n#Ç•Á1ÁÔͦ1A¹ç8&(-̶1ÁT-Çcͦ1B9q¡cž3œ¹Ÿý©kŽ ›Mc`úÏðœañqà„ÑÑÑÑÊ¿äÓÇ÷ýðM½²E–>˨ª*lÛ†ïûaoùyÐfz_êJ3 p_ê‰îŸì¹•}}¦².×u‹Å0::fç‹}}ËyîDÇ:ÿý]€qïçy‚ªªŽiç’¿Ýròcù¸‰ž;Þ2fƒBǺ˜8}ÜlÛçJ3`êŸõ鈕øëÕˆÑå– fKàg¿ôc̽Ï~5>¿ùJŸŒw,9F(¿”~Ì€™ù} RŸåRÆŨTˆn#Çå㘠ôcÌÌ1TÊgŽc‚òbÁl{l9F˜ü˜3sŒ •ûù› ç ø}`úpŒPú1fæ¡Vç xΰðó ™õ‰ÇñȬs˜1ŽÅbH$UͲO&¬ÆS꛵šËž‰ëO4Tê¹Ó±3í8ÎŒ•]öt¯·œÏr9&Z/cÁìÀÏ~e—=Ýë­Æßñjb\˜¹ *»ìé\o­Æ3éÔjs ã@e—=×;Ž &ÂØPÙeÏÄõVÏÎ-Œ•]öt¯·Vç xΰx³¶Õêd¢¥½²U‚,­¥ñúæF•z%@5—=×;¦cçÃqœnŒ•]öL\ïtc,˜øÙ¯ì²gâzgÆ…™‹± ²Ëž‰ëI f&ÆÊ.{&®w&a˜=*»ì™¸ÞéÄÏþìÄ8PÙeÏÄõN7Æ‚\s¶â‘ˆˆˆˆˆˆˆˆˆˆˆˆˆ¦Ï‰µÞ"""""""""""""šý˜x$""""""""""""¢²1ñHDDDDDDDDDDDDDec⑈ˆˆˆˆˆˆˆˆˆˆˆˆÊÆÄ#•‰G"""""""""""""*DDDDDDDDDDDDDT¶“k½Ó¡½½û÷ïÇ9çœSëM™V{÷îÅ\Pë͘VÄâÅ‹qúé§×zS¦ÕT_ë—^z ÝÝݵÞìiwÍ5×ࢋ.ªõfL+~&橾ÖGEKK n¿ýöZoú´â˜`þ8zô(^zé%,]º´Ö›2­¦úZ5+ÿNÌÖXÀížÙÛ=_¿|á _@__߬‹õóéoÔL0[·à9Ãbµ¶¶bñâŵތ²ÌÖ¿WQ³5¶EÍæx݇rÇó"ñxøðaÜtÓM¸å–[j½)ÓjóæÍرcG­7cZuvv¢¥¥---µÞ”i5Õ×zóæÍµÞäšxõÕWù™˜'ÿ&××ׇ¾¾¾Zoö´ã˜`þïñŽŽŽZoÊ´šêkÝÙىÇ×z³§Ýo¼1+?³õ³<[Ç#³u»K‰óñûÁáÇñ®w½kVþ˜­±€Û=³·{¾~?xã7pûí·ÏºX?ŸþFͳu»ž3,ÖâÅ‹ge¬š­¯¢fkl‹šÍñ"Ê1#[­ŽŒŒ`ݺuw®³³ë֭êU«°eË Mº¼åË—Ï»ÊذaC­7aÚµ´´ ¡¡¡Ö›1íæâk]é8gŸ}v­wkÚñ31ÌÕךc‚ʘŸ‰†††Yýe¥Tsõµ/”:&˜­fëë;[ÿFÍÖíž«ñ¯ßf«Ù ¸ÝÜîJ`,ø7ŠÛ]¬¹  › ¯õlmQ³9^TÒŒLräÇAWWW­w“¨¦úúúÐÙÙ‰ƒÖzS ªf€ƒ¢³³³ìÉq‰f»ÎÎN8Žƒ#GŽÔzS šŽ1Aggg­w“¨¦†††ÐÙÙ‰‡~¸Ö›2®‰bA¹c‚C‡…­˜ˆæ³®®.tvvâСCµÞ”‚ªýýàá‡Fgg缚ÿ‰¨~?à÷"ž3ä9C"@|?¨Ä˜`Æ$mÛÆ’%KÐÞÞ^ñe/X°MMMX½zu­w“¨¦déÅ‹×zS ªf€Å‹ω^áDåjiiASS,XPëM)h:Æì·OóÝ’%KÐÒÒ‚åË—×zSÆUÍX°páB´´´ðûÍ{«W¯FKK .\XëM)¨Úß–/_Ž––,Y²¤Ö»JTSü~ÀïDŽ ˆ`, "Æš?,Ë7AhY,ËMÆãñ0Q‹Å\×-øüh’²JÎÿX‘9ëêêPWW‡w¿ûÝØ¸qcÁ«ã>``عs'šššˆù!×­[‡¾¾>lذÐÓÓÎ% Û¶mƒ®ëèéé CD³ãŒD$ ˆæ6Ž ˆ`, "Æšy|߇ªªe/Ƕm˜¦™³\˲&\¶eY0M¾ïCQÙJÆ  ëz˜”ô<ñxýýýð}ŠFß÷'­ˆœŠŠT< aÉ’%X½z5†††Â`ý™H]]ÚÛÛÃÀQÈÀÀ†††ÐÒÒÞÖÐЀ¦¦&ìÞ½»b„ˆjƒq€ˆÆ"&‹ŒDsÇD0ãÍ,AT¬20?Ù—_͘ÿXPžçÁ÷}hšMÓày<σ®ëP¾ï#Äb1xžVAjšîÃx˯”ŠT<ÊjÆ¡¡!ôôôàðáÀ–––œûxÂe àðáÃèêêBSSSøüè2£–,Y2ibóÈ‘#pCCCáDóQ__úúúpðàÁZoÊÕŽpðàAtvv›ˆæªÎÎNìÛ·¯`‡‚Z›®1A__߄݈溡¡!tuuáᇞ‘'‹òäA©c‚C‡¡³³ ü~@óZWW†††pèСZoÊÓñýàá‡Fgg'ÚÚÚÐÐÐPë]&ª~?à÷"ž3ä9C*ŽLäUjYŠ¢„ AÛ¶¡ëú¸‰AEQ ªj¸ òw9/¤\N~B3š˜Œþ?Êu]¸®‹®®.üô§?-{LP‘Ä#lݺ]]]9·mß¾ ضmÛ„W$Duvv¢¯¯€HhVbг`Á455aõêÕ•Ú]¢Y©¡¡---øÙÏ~VëM™P5â,^¼---<©@ó^KK žxâ <ÿüóµÞ” UsLpÙe—Õz÷ˆjjÉ’%hiiÁ¾}ûj½)“ªF,X¸p!ZZZ°dÉ’ZïQM­^½ m«T Õú~°|ùrÆ"ðû¿ñœ!ÏR±\×­Xu`4A(ÿÕu=gŽFÏóÂ䢬p”‰FUU¡( \×EH$á6º®&1eÅc*•ÊY¿çy°, ÝÝÝa²ów~çwpäÈ‘²ÇI¾ïcÓ¦p†a„Õ4-¬b”•2Ù˜H$ÂßUU +5MƒëºPU5üDâ1Z1)“™Aàé§ŸÆ‹/¾XÖ1¬Hâ1âÖ(y5òD½”{zz°iÓ¦ ×!—Ÿ?l__K ‰æÆ" ˆH˜,0Í}ÀX@DŒ4uå$Ç3 ã8rçw|øágàûâ>y›mÛáºÇmÛhll ™®ë¢¹¹ög?Á‡?ü\tÑv˜¦‰X,ÏóP_ߌÓNÓ~ó›§ãškn ¾ïc×®8p`y¸2q¨ëzØfÒé4‘¨T¾ï™Ó@ø\ÙªUÎù›ßüguVY¯AE ãV4Ê„ãDWlذ###9¥ÜrBÛhB³­­ ]]] ÚÁÔÕÕaãÆ•Ø "ª!Æ" ˆH(&0ÍmÀX@DŒ4u²Ui)¢Õrªe¡ªª8rä<cªãñxøØîîn ¶mÄãqÄb1Àø(ŠóÎÛt:ÞÞ^ âàÁÅUUqüøñ°ÂQÎùÓŸ®Çÿñ¥t˜¦V/öööæ´†ÕuÝÝÝa»Uy[¡}’­]åcƒ À‘#Gpþùç—õTdŽÇ 6„ü7¢©©)l¯ÚÙÙ‰¦¦¦ {$744à®»îÂÖ­[aÛ6–,Y‚¡¡!´··çôhîèèÀ¦M›póÍ7£®®CCCD–ˆj‡q€ˆÆ"ЉŒDsÇD0ãMœ·Ð¶íœJÀbž'“–ržGÇqÂùå<‰ðƒÁ[ßš[])Ú°ªøÀîMö™¦ ß÷Ñßß¡¡£øƒ?P±té}øïÿþ#€¢èP„í[u]ÇÙgàºë.…¢ˆçÛ¶‡•+GpÁuxüñKHÜž³íŽFöw#ó‹LHæ'%Y-)++=ÏÃÏþs\qÅe½I^Îu¨iAX!é8š››¡( EmÛXºôØ»÷l躎ÎÎOâ쳯G:Æ…¶Ã²D¶ppðLœvÚ5a"4ÊqÄϹç¾ÿûÍÍ"ÉhÙÄ£hµ ôöæV0ú> s†ã%eÂ2owä«ç‰$è¡CõøÎw.*¸ŒD"K.¹¤ì׬b‰Ç®®.lÞ¼ámëÖ­ÃÖ­[à ]‰ˆˆˆˆˆˆˆˆˆˆˆˆŠáºnÎ\ŠQ²-ª¼ÿÇ?~"¼Oέd[°:Ž&'‘ˆK$Ð4 ½½½PªªÂu](Š‚­[¿€·¾u=ÇÁÅ¿®+*wî\ × Á7ß|?\7…åË¿V:ª,4 LSÌÁ¨ë@2)‚٤뱘¸¯±8á„èóƶT•‰HMÏO&³Õ“Q²¥ë¡CõxöÙ[ n£®ë¸îºëÊ~Í*’xܾ};¶nÝ 9}“ÛÚÚðÀ`Ó¦M•X Íù‰Åhu#Û }ôÊpÎBÃ0Âdb°¬ìã%Ù^´··7|žlšN§qÚiÅOú ø¾ Z¹I=ßÞö¶ßA]Ý·ðÛßþ.‚@$ %þ|_$eU¥|œ®gÿíïd^T&6ûû³ÕŽŠ’M º®x¬||<ž­z,´~™ ’É$žzê}PUº®Ãó²Ù»¾¾Wñè£'l/šOUUÜxãmSK®_ÿ±wê§â‰GBOO>ŒŽŽ¸®‹¦¦¦j¬Šˆˆˆˆˆˆˆˆˆˆˆˆf8™tô}ñxJ$Ëöå/? U5pß}§â”S>˜I<ŠÄ ’kÑä™ïg«U5ÛrTU³·+Jnå ªŠ"²t ÃYg›Ÿ$”s-æ3 ‘üœL:]÷T²±…ª"åqp]ñ¯ó™N¬];Œîîny;¨ª*LÓÄu×]Wö6\Ê“úúúuuucnooo/ø&‰ˆˆˆˆˆˆˆˆˆˆˆæß÷áy‚ À‚[ñüó?B]ðÌ3uðý58ýôž<òÈ#X¹r¾_Us.Êyãq1gaooî²£Õ~²€R×Eq¢yŸzêµ°òÒ4EòNQÄzä‹S™g±U?¾ŸS±ThnŽÃÈôQ‰\íí:b1š¦A×u†Çñ‘LÖÃqœ0ìû>Òé4|߇axõÕWÃ`©Jªx”­UGFFÂÛzzz«W¯Îy¬L8655Uç¨Ñ´r]7§r.(P&¢Í'¼úêòðyGŽœŒ… I9k×CU ' µZ¯êDI¾+º°{÷n8p \®L<ªj¶Ei¹‰G@Ta¹•˜•A8wf4ˆêG9—¦¦ip]±X ªª"‘Сi@"‘€ž9ÈA ™L†Ï¯„’2¹hÛvx›œßQ¶VÍ¿=?!IDDDDDDDDDDDD³“¬fD,š3Êgî¼ó‡xË[vo{Ûo1<¼6|̲e")rGM+œ,'9xìØ²È¶e×çybÎÇJäá’IÀ¶ÅO^7Ô²xž‡d2 ×u¡( t]‡eY°m¾ïCQضVšöFJE C´Uu]Žã »»f&ƒ«V(;ZR«Õºº:´··cûöíaÉåÀÀ@N›Õtuu¡«« ííícÚ²Ñìäû>|߇®ëp'¬x”íEebÐ0 ¬Yó>Üz뵨¯?À—på•#øñ›pöÙk!Š÷T|ä#çaÅ ñ¼ÑQñ\Ï«LP^‹C‡ŽàøñÓɹOV<Êÿ—KÓÄüŽ•¨ž”dÂ1‘H„ÉCÃ0`FäøûÐ4 †a µµݲôÙ$k*•‚išP±X A •JUdKJ<@GG«íííèèèïïìì ç|ŒÞNDDDDDDDDDDDD³Ÿïû‚ L<º®‹{îYŠ5kÖ ‘•…ùHË–]󼎎:¤RÃÎÞvÅKÆ,_&ï*5Gb}ý#X¸ð–.ý!.¸àtëÃû ±®ÆÆÊ$MS,¯RÕŽrþF]בH$`Û6º»»¡ª*¡iZ˜<´, º®ç$Üý’ŽÝÝÝmµZrâÚÚÚÐÖÖV𾎎ÎëHDDDDDDDDDDD4Gɪ;EQÂê¹¥KÃùç‹ûßï}o9¾ô% ­mºº†¨hmÚÚF°k×+™%y㮣Rs.ÀEý ÖãØ± °páó9÷ɤc¥ÐÜ,š•šã1N‡ó3Ú¶ ]ס( Òé4<σ¢(aj±ŒAÀ¶í°åj¹Jšã1ª¯¯}}}ȹIG"""""""""""¢¹K&­ À®ëPU®AW×›ð<àÀX¶ìèêZ‘yV6 wàÀ¹¤q×Q©¤<ûì-øå/ߎ‘‘•P”ÜËõT¨ãhX¥©i"ùX*9¦ã8°D_Z@oo/´ÌJ Ã@*•‚ªª0M®ëÂuÝ¢–/“—•Rrâq``º®cóæÍؼy3n¾ùflݺµbFDDDDDDDDDDDD3›çy8pà6üÇ|=X¾ü}8ë¬=™£y¤¾,_þ*€‡ÑQà½ïÝÀ†e=2áò5­r­V¥ººgpñÅ猹=‘’ÉÊ­G×Åòl»øçA&ƒ @ss3b± Ã@:§Ž“‘•mSµ"š¢(ae%”œxìììÄáÇÑÞÞŽ;v`Æ èêêBgggÅ6Žˆˆˆˆˆˆˆˆˆˆˆˆ¦_Œ­Bô tDU œ‹ýûaçΕhhø3œrÊPxÿ+¯,´´,€¨vÔ‹ßûÞr&‰µnG%[­žyfvRÉÓO?^`Ÿ+{ 5 ˜Êô‰žç!™L¢µµ5<¶½½½€X,»ˆ ¦®ëaÛÕb%Ê)ÉÌSRâqhh}}}èèè@GGZZZ°mÛ6455i¹Z¬‘‘lݺë֭êU« ë:zzzÆ<®³³3|Ì–-[044TÂÚˆh&b "€±€ˆ„bbãÑÜÆ1ŒDÄ8PK…’\AÈž2¹e|_T÷¹.°jÕc8pà@˜Ä«««CȤ^\p`ÅŠD¥ÝDI² M=X¸ð`Ïž6ìß¿hÌýŠ"ö£R ñSì2å|™étŽã ™LÂq¤Óé°êLWrârnoii)yC¶lÙ‚xŸýìgà Ê-[¶äÎÎNtuu¡££;vìÀÐжlÙRëcHDÂ8@Dc “ÅÆ¢¹c" ˆˆq –üqJõ¢Sjš¶éô}Qxî¹û°hÑþœ*EM“É7'œÐ û»e=Rt[Ðr½ím?ÃÛÞö³i;†Š"æŒ,”x”¥Éd¶m#™LBÓ4¤R)ø¾Û¶¡i Àªªð}Ü×$ŸZɉ1§¨äV«•422‚¾¾>|ö³ŸÅ† ÐÒÒ‚ŽŽ455á×ÓÓƒ¶¶6´µµ…U–¯n ¢Ù…q€ˆÆ"ЉŒDsÇD0ã@-¹®[0ÉåyÙÖ¡ÃÃkQW×Ã0`"¹f"¹hÑ~ÔÕ½Àçg‰HñdU•Ë1&mµZI¿üåÛñoÿv`Ù²ccîÛ?=Û"«Çïûpn&«kš&EeYab7•J=£aÓ³̈ÄãÐÐZZZÐÔÔ”sûêÕ«122'544 ©© »wï®õ.Q™ˆ`, "a²XÀ8@4÷qL@Dc1ÌDû÷¿‚8Ïó0<¼{ö¬ ’ˆš&wŠ¢`dd%¾óˆÖ Ž# Ô×?’yLS–/âøñÓN¼òÊ+µÞ”1¦ãûÁ¾}ûÐ×מ´$š¯øý€ßˆxÎç q]7¬¾“<ÏÃ=÷´àèÑS°e˶œû,KT1Ê|×ßËÜ£ÁuÅí²ûçððZø>0Á´ŽUsÁÏ`éÒhžþ•#Û^Õ¶m$ Äãñ‚si@"‘˜pîˉ”Rñ800P‘1AY‰ÇÍ›7cÕªUáÏöíÛÑ××—s›ü™ŠžžÜ|óÍhhh¨ÈD™¯¾ú*xuÍ{rñÒK/ÕzS&Ué8/½ôD@x²ýÕW_­õ¦LªZcžX ùîðáÃ3:ñ˜¯Ò±@&ùý€æ»Ý»wÏØÄc¾j|?‰Gy²’h¾â÷~? â9Cž3,–ã8X¶ì/°lÙ1?~:Ž=+WŠ‹¸t=›X€£Gwá–[žÅ¹çþ;R©TUE<‡eY0M³¦ó0ÒÖÖ††††²Ç%'+ýAÀ¦M›ÐÒÒ×usJ§ó—ßÏ9ÿw"šˆ`, "¡˜XÀ8@4·qL@Dc1ÔŠl *»v ahèOðwwî¾û0|ßàã{ßÓày"±8:*ž+•¿úÕ8zt-âñìrׯÿ¼úêmPÑjõ¢‹Â믟>§ÚÖ®]‹;âøñ¿ Wu]Š¢À0 èºÏóÐÚÚŠT*Û¶áGK>瘊ÍñØ×ׇíÛ·‡íV§jË–-ظq#¶mÛV0pÈ+òÛ!õõõhˆhva "€±€ˆ„‰bãÑüÀ1ŒDÄ80<Ï çô<§v[xßç>÷sÔÕ]€çŸ?gŸ} €‡«¯>†LŽrŒ£GOÉù]U]»þ?ýézàyÀã߉ƒ¯-y.ÃR?~:§*ë´m–eÁ÷}(Š]×3û®BÓ4Äãq¤Ó銵 ž‰Jªx”FFF`Û6ºººÆLÆ^WW‡¶¶¶¢Jžeÿä–––1IË%K–„W%´µµ¡«« 7nD]]¶oߎºº:lܸ±ÖÇ‘ˆÊÄ8@Dc ÅÄÆ¢¹c" ˆˆq`ºA€»îú^&Y¦âå—¿€ï~÷/áy*|ð¬]{!\PÕsĤñÎwŠçjÚäË5jàºâÿ¯¿þú´îg}ý#ö¡³ÑѶ³ã¿d2‰D"Ïóàº.‰Qý¨( ‰Ä´&Yk¡äÄãÈÈ6mÚ„´µµ¡¥¥%L0ŽŒŒ„}}}¸çž{&L>Ê€±eË–1÷µ´´`ÇŽDÏùM›6áæ›oF]]†††ÐÑÑQ±^ÎDT;ŒD0‘PL,` šÛ8& "€±€ˆ¦[Ø·¯–eáôÓpô(°gÏEøû¿?+V,A}}}¤ºQà²tèºh›µdÉ‹P”.;v\Îï˜JÉdf :põÕÁüªÝöTZ»v]´?<µç%“IX–…QÙO6Ãó<(ŠUUá8R©âñ8‰º»»s+« 纒ÂŽ; NÀ¼aÃlذ[¶lAgg'îºë®q—ÕÑÑQÔœ‘uuuعsglV¯^ÍÀA4G0ÀX@DB1±€q€hn㘀ˆÆ"b˜nßÿþ¯¨°í$Ö¯ÿ víî»ï9,_>€Ïþ½hmÉBÁƒLjšH(F­[wyd%Ö­{\°&œÒ÷s+üã¯p3?Ó£®î™)?ÇqtwwÃ÷}X–MÓ`š&ÇAH§Ó°m©T*ü¿¬v”4M [¯Îe%%‡††ÐÕÕ…ööö‚IG©¥¥mmmؾ}{E¯.˜hD4?0ÀX@DŒD$0ÀX@DŒå:t¨Š¢Á4H¥®Â† ;ñàƒî¹Ç‡¦½½€e‰Ç.[öìß/’ñ8«¥ááµxðÁµ9mX}l’rºyž7¥Ç»®‹îîn8ŽÇqñx†a@Ó4xž‡d2 Ó4ÃÄb¡9MÓœ'–ò¤¡¡!¢oòdäcò'v%"""""""""""¢™á¿ÿû–,y©T É$àû:þt]‡ç±˜H&@SÓþðyA0Þ"Áçy@4gÛ¹Z´hÑ´îgí[Û¶Ãùe ÕÞÞÞ°úQ¶Y•IÉñ̇¤#PbâQ–+744LúXù˜ü‰_‰ˆˆˆˆˆˆˆˆˆˆˆhfØ¿ÿ<ìÙs|_ü~ƯãÏÿüƒ²‰ÅdR$`ÅŠ.ŒŽŠ¤bá¢.zhdÌ}ùIÊ·½íõš¶ uÝñÛ¼ú¾]בH$ ( ´ÌÆ»®V=š¦‰ÁÁAôæ—|ÎS%%e¹²¬|œˆ| Kœ‰ˆˆˆˆˆˆˆˆˆˆˆf™h|ã/áôÓ‡¿ÇbõaËPE•ŽQ]tb1Ñ~5¿ˆP$èxÿûë iÙuhZî‰pÓMǧm_Õèʰj1¸® Kö’…hÉêyìüMˆ¶©étzÌ<Ž3^ù©¢’«W¯tuuMúXùù""""""""""""ª½ ÈÎÛ84ôç8zôŒWèy¢Õª¦!¬ü“·×ETÓ²’€x~´íªx®>&!X-ªªæTWú¾×uá8’É$,ËB}}=,ËBss3<ÏCwwwÁåh…ûËÎl«ì¥L¨¤Äc]]ÚÚÚ°}ûvôôôŒû¸žžlß¾mmm¨«««îžQÑ<pœlÅ¢ªŠÿëúØö©® 47M$ŽgÙ²c“®?D5ät%àÜsÏ ÿï8Òé44MC:Æðð0Òé4LÓÄèè(R©Ô´nÛ´°øÕ[üÉ¥>±££»wïÆ–-[°aô´´„ó9 ¡¯¯===hjjBGGÇt6""""""""""""Gð<AüéŸþ†!’~‘‰)Çÿ*þkjZ4éóu½ðs«é¬³Î Z©€eYð}?L@†1½4:Dâ±JùÔ’uuu¸çž{`Û6ºººÆT>ÖÕÕ¡½½¦i²Ú‘ˆˆˆˆˆˆˆˆˆˆˆhpº®#‹!•ꇦù¸÷Þ> hÂV«ãµOćA ™,üØT*ßËrœñ“‹ª:ñz*-‹Á0 ¬Y³Žã@UUtwwÃ󼜬s– À0ZU”œxDr±££èëë˹¯¥¥ezMÊu]´¶¶BÓ4xžoûž{î X¿þ\u•HÚ6Hˆ¤`”iŠûT5ÛUÓÆ>NŠÇÅ}U4ʤätåü4Mƒ®ëxíµ×ð…/|!“ õaYÌèä“s•ÀÎüß…¨~¬°²QL4Í\Žã@QxžŠOü>þå_ŽãÍ7ŸÃŠï‚ã†!’€"¹˜û\Ó‰ÉüÛ'jËêûbyÓYÕ8žÆÆÆpÎÆw¼ãxî¹ç`|ߟ{ó8NF‡HBV!ñxbµ·½³³«V­ªöjˆˆˆˆˆˆˆˆˆˆˆˆ¨ß÷ñ§úUtw÷â’KÃâÅ÷â”SNÁÈÈIø½ß» [·.«5MT"Ê–«R2 Añë”ó7&"iYHo/JUn?弒뺂¾ï#‘H„íT5MC*³bUUçö¼Ž…h¦ðZNEÕDDDDDDDDDDDDTÉdøÊW®ÄÕWÿ)n¿ý|ìÚu*>úÑ>qttÜ UÍ&-Kü[¨жsO¥€tºðzƒ`ü6¬ÕØG×u‹ÅÂD£çyhmm…mÛhnn†¦iPÆ)½œmV£täV;ÁԲʨX«U""""""""""""š9<σeYø§ú>ùÉ•øÞ÷.Å5׈–ª‰„ Ïó¡e&aÌŸ‹1?i˜N‹yó—\ ‚‰Û°VjÿÄ|•¢ÒÑ4MX–˲ ë:z{{Ä£6Ñd“óEc¤2É×$²ÉGÏ%®7ÞXö*XñHDDDDDDDDDDD49ŽÃ0°råÊ0A˜é6 UUÃv£ù % ãñ©U0jZu+mÛF,Ccc#LÓ ÷Åó<¤Óiø¾ SÅ7ï*dzÙ G@´•n–……¿ùMÙ«`⑈ˆˆˆˆˆˆˆˆˆˆhr]š¦…mO‡‡s+圇ùLsl¤¦mµ:ÓnÇr%“I@oo/t]÷Ã4Mø¾¨âwÿæùÂÌd” 2Áœ©]~ï½e¯Š‰G"""""""""""¢9ÆóÔéš\r6pQ®êyÀS`dnWÈi5 H$°÷Ÿ({u%ÍñØ×ׇ͛7×úPQž ‹Å`š&4M›R¥b29þÜŒÓ=M¢eYH$9·566¢»»{ÜjÆD"&"ç=ßÏNÌé8™Û ’_°€_˜À·t‘•6 ¼Þ×Wö*KJ<.Y²---µ>\DDDDDDDDDDDD”Çq,\ø{°í4 Àu‹ŸoQQD‹ÔüÇ«já*ÈjëÐ"ÏT*•ó{¾ñæ­œ—‚@d‹ C$/7€©ˆŠÇûZ Wt•%%¥ŽŽ455Õî€QÇqpñņýûEÛTU->ñhâ9A{{þïÓ!¿ªÑu]8޳Z“GNÀtu‚Õ4Ñ;‰Ç¥ðÄ›a} xª±â«,iŽÇÇ£¯¯‡ι}ÕªUèì윦£EDDDDDDDDDDDDQ¿øÅ¸n‹_ @tÛTU`œÎ¤cø¾¨l¬uâQÎQÙÚÚŠx<'Ó*Ô0Œ2—\cq1Sh[½½¢âQ‹¾;“ýtQ à‚/} ×ÞY«)«â‘ˆˆˆˆˆˆˆˆˆˆˆˆ¦ŸãˆêÄ|wÜñÿ˜¸ÿ~ ­S[[EÞ©˜ªGÙN5?Q9ÝLƒ €¦iÐ4 Š¢ xžµØÒ͙ʀ¨zL$Ê[Ü”=j‹¤§iwö¯ˆÅ€ÑÑŠ,ž‰G"""""""""""¢YÆóÆ&ÿèF຾öµýX]IG@tÝœ êF]×Ãv«¶mò,tww×zËãC$‘x¬&ÏÙfE¿J?µEå#ܯ§[ÀÒl–yésÏ•µÊ’Z­QíÈÊÄèïßúV.½t7þø—!•9'Yõ(sO“Ñ´â烬4×u‘J¥ ë:|ßϹÏ4Mô÷÷ÏþV«²•ŽÕÞ•x<÷ò³8d_`À.‰Ç}þ0~xà e­’‰G"""""""""""¢YÆussJ¶ ,]úC|ô£«s§i"ùX¬©ÌYiÉdžçA×utww‡ÕŽÙ}™%e›Ñ( ÈÖ*®ÇqÆf§f²Ï2ñø_lÈ1‘}ýŒ3pðüóËZ-DDDDDDDDDDDD³¬bô}‘x´··chh===hjj*ª-kWW¶nÝ:áczzzÐÖÖ†¶¶6À¶mÛ ë:zzz°aƲÕãQõù¾øY½ºÖ[2>Æ"&ŒDsÇD0ã@”ëf Þº»EòQL[(ª »+4G ¦U¾âÑu]X–ÎáxÍi× îá:œœÜTÂe;U › s]`xXü?ž¸ué° @ILO»UY‰yÔ¶Fæ^Tàc `H!›´,À4Å~ôöŠ%™/º¤iâÍ`”¹*€pt÷Ѳ%W<Þyç¶mÛÆ$;::°mÛ6ìܹCCC™ty---رcvìØQðþ ¡¥¥%¼­¡¡MMMؽ{wy”ˆfÆ¢òÈ‹¦€‰«ó»1Ì4ŒDL ˆæŽ ˆ`, "Æ(ß—‰F1•áW¿úE‹Å ªjE[­Vn›}8ŽƒD"þþ~twwcxx—~øR 1Çb)³'À4MœD"›Œ”å ã¹%ó¯ìLš¬ÂÎËD£¤i"ˆ´HôE),ˆDh*%~sŸ‹Ì}Ѭ°¢L-éè`Âc¾÷{ñØU•µÛ%U<ÊjÆŽŽŽ ¯ÕŽwÞyç¤W444 ¡¡aÜû> 9Á–,Y2ny5Í.ŒD“sݱ­.dÂ1‘È^àeÛÀèháexpc&Š®Æ"&ŽŒDóÇD0ã@¾TJœ÷±,xÍÍÍð}ƒÑ$Õ çtL&“ð3WÁFOVÉ9-ˆ¹‹­°”²×, *=/“Ô+Âúð øDÂ/ QmXI­­"1­DU”l²3Jƒ¨º 2ÛT-r=UTRÅ£œ”U–-OdãÆwÂ×éð / ³³5Û¢ZkmmÅ?ÿó?cóæÍØ»wo­7§&öî݋͛7£«««Ö›B4©üŠÅd檫ÖV‘|Læ]…%ÛÖ§Ó…[aø¾Ÿè¿øÅtvvâ…^¨õnN;9&˜ÊüÓDsÑÀÀ6oÞŒûï¿¿Ö›RÄæÍ›ùý€æ=ù7ñàÁƒµÞ”š¸ÿþû±yóæ9yB’h*äßD~? š¿ºººxÎpœ3ôÈ÷E÷Ík¯=Àƒçy0M3la:8Žƒx<Žx<UUÑÛÛ‹þþþ¼AÌih ø9}_d\m;·ª®O­Å×U `Qôùs–Ò%Ì÷ʼn¹|¶-^´tzì}ãu*KA$b«ÉÀØjË ™G+wLPRÅ£L"ÖÕÕåÜÞÖÖ6æªù˜1÷M—³Ï>7ÞxcÍÖO48Žß÷áû>Ö­[WëÍ©‰ .¸`Ü– Dù|â6ðÕÖÚ*.†’IDËc(U­4l[\áˆ1ŒªŠ1Žãˆ‹»¢sL€mÛ°, ë×ß„_¼ çžû^œp³µÛÁᘀHhjjÂŽ;æmâméÒ¥á´)óõ„û 7Ü0fê¢ùhÇŽèëë«iÑ@­ðû‘ çFœ¯c‚ÙpÎ0€XLúÉNX7ÜpN=U¦%JUºT¯<žçAÓ4¤Ói(Š‚ÆÆFhšVxÊ4Šk·*[~ÉêÆè•÷šä'6§JÉl‡9…ç8‰Œ]¿ëŠ q¡„ðxû«@$a3ó-VE2³ì]y;::*2&(©âQþ1–•RCCØ?Ôò1MMM9&…®D¬Ô²‰f#o¢‰Ü Ð4 ?øÁj½Ùea jð}‘ÌknN8A´‰wнÚ*#&ŒmOþ8yõZˆm±m1¨”-Ûå…Ròbª¯|åQÁØíõ}qÑAss3lÛ†¦iصkàžÇ¾}ûj}ØËÂX@DŒD0‘ÀX@Ds9$“ÙNW’ïûÐ4­fIÇd2‰xÞ•ïA ¾¾†a ‘H„U˜ÝÝÝc·3z~¬c«=/÷$šœ_¨·W\‹HQ&žÏ±B…Î8 '¯ø’'ú U=F[ÁFMTU)Û¾Z(­úr†()ñ¸zõj(ªôX>f¢ÌÅ ÍüÉ`ûúúÊ^6Q-™ )« ñ‹(O&“¨¯¯‡ëN~YH?z{{gí•|ŒT)ÑyG\1&{ã뺿ôöŠ –ŠíÒ`Y@}½HÊ1W2™]Ok«ø=[(ÉuYÖØÛ娯qDüX¾üî¾ûn477ãÁDˆý’Uš†!.þ‰{{{Çaš¢ýr}}¬Ö/EI ˆˆq€ˆÆ" ˆh>ÄEÉM:Êù5­Ø‰+Ï0 ض ày¢å«ã8H¥Rc¶KÓ4¨ù­Åd¢QÁØv«®+ªêë³ ÇTJœ°SUqÏœJibž&xgæ|ºL&Ž7ï¡ëŠ“‡­­â§±1›5M±M†‘M<Êêy{¾ÉÎ5ÈÎ}9K•”x¬««C{{;¶oß>aò±«« Û·oG[[[E>àmmmèêêÂÈÈ`ûöí¨««ÃÆktøˆJX·±±ÉüÉÚ2,ËBsssÁªÆhâRQ” ù÷­X±¢Ö‡ dŒTÏãƒXLŒ]š›EP×ÅØep0{Á”lk:QN_vxã‰tZtUcQq(~\WüžHˆß[[xÜÅ¿ør¸<9Žjk»¤ÜUyŒ*YØšBá6³Trâ±®®;vì«ûúú°}ûöðþ††´··—”t|úé§Ç]çÎ;É-W¯^=ëÍ}A@Qض Û¶ÑÛÛ&å$»ã‘{¼ŠGy{"‘@ss3„%öòjÇq ªjMËîKÁ8@•‹‰¿õÑš¢ŒŸt”š›E%d~«x™´ìï1W$“Ixž‡¥Kÿþp=þþï—ãÅŸÅÇ?~±X+t]‡ëº‚ªªâå—¿Š­[ûqÿýÿ€ Çç?ÿkÀ¾}ÿŽE‹attž|òšp½õдzضs¥RÙèâůaÿ~‘xÆâÅçãÚk¯ ·WÒ4àšk¢Ìy¢§c…cãÑüÂ1ŒD4¿â€e‰b»T*{NÊu]8ŽƒÁÁÁš&ea,€ñ\×E:†mÛáム·Q&u]/˜˜ô<ªª†AÝ0Œp®È蜎r>I¢ÙÈÍëv ù¾¨D”É8Ç'ÉÊCÇÏÓ´lrPÎ==Uét¶¥»ªŠeÐ×w/êêÎA\‰Î΋¡( š›Åœ«ét®ë"‹á´ÓNƒï®[MÓàû~ÎÅW]õA¼ýío‡¦-¬Ys;þþﺺ?ð÷8ñÄ=Ä6A¶ÊÑ0²ûÓÝ-ŽÕk¯ãÇŸìÚõ\pÁº0aªë"A) ÍL–%ÎgE§K ‚ ì¨WKÑ.|RI‰Ç»-qrËÈLî¸Ã-àåi¨ä2€õ§Kà?Ë 5!Z£NÕDÇCÐ]ärˆªG+ó£ÈçM$ª·Z=±º‹'šýÆ+—Œ­™‰b=ÏC<¯ô°m¾ïÃó¼pŽFÙ6U&"eò°Ðz|߇ªªç€ ‚ lµ*Ÿ¯ëzغ5Z )ÿ?ÛZ­¢}ôâ  mEm;Ûb4DbMUÅÏ££âÿɤx¾e‰Ç—úóCIx^étMKb÷î?ÅÞ½„úz‘Pìï(02ƒ%]סª*n½uE\ ªê˜ äõë×c``aXÍ(“œ×\³€hâyçr”E$å|ÕŠ,]ú^|ñç€={ö`ÅŠÄ2c11Xõ¼‰ç­$"""""""¢Ú q.'z Û¶ ž[šÞm ¦>—ãxžµsOR]¨­&°\ ¿j:E®JŒu¾Àh‰ZŠñæ‚D"q*ËMA$ “¨Ìqñ*´œ 0ñH4Çq‘L&‹ÅŠBÏóL&á8\× ‰º®#‘HÀ4ÍœJÇ  ëz˜ü‹¶N•‰Ãüvª2©(ŸãG²/…Z¯†&=t]GkkkXéèOTÖMT%ž—›(›*9‡¡ç‰$b2)lVæb(ÓIÆtZü¿ÐÎr9¥\tMÞ777ömX–…ÆÆÆ°‚ypp½½½èî(H¥R9ƒ?Ã0`š÷dc×?ò¶Õ«OÔ××g–%~äâ‚@<¾¹9{ÜÞ½gc×®ÇÐØØØ·ï\¨jöØdBj8£µUœ¿1ŒÜó[²Úq²óLÕæyÞÔ»ë¹nöJ{É÷øÙjGé[)ÀÖ–BvŽÅ©’­Ø*¹- €x–傉G¢Z±m;LðÉJB˲ˆ„„ïûH&“P–e!‚0‰m½ ˆ$¦¼MUÕœ Æh»Ô¨üåå'erC&&£IÇîÌ„¸²í+Ñt‘­@ƒ@ ”š›³É®ÉXVîENÉd¶Êϲ²jæ¶™(Ä0ÄUarì2Ù…`òóÜÜÜŒÆÆF466"g¶# MÓ088ˆt: Ó4Ñßß&ûu]?ߦi†J¥&m5¡(büåy…‚rŒ"üWÓDÒuxX´‘•IÞÞÞ4Òé4=<®¦™­ .“ˆˆˆˆˆˆˆˆf×Ížó‘<ÏCkk+E™ÖÄccÎ/û¾ž{.ŠlÕ•9¯J;´Â'ÃÕ†Õ6Ùù1@æÿ¥$+}å¿lµZ‰¤,[­M™(”•Š®ëBÓ4ôöö†åãžçÁó<(ŠV8ÉêH%L4M ŒÑV§2 m}šŸŒÄ<ÑÇÊV®¶m‡IÉü„†išÐ4 Š¢@Ó´œ«Oj9á0Ͷ 46бD,&nëïÉ¿‰Z{¶¶ŠçÙ¶\Åã"é˜N‹çpuw‹Z±oeÓôÃ¥˜ßÐ “‰®ë†UÁ¶m£¹¹žçÁ0 $ èºß÷à R©T8¸«H+‰]‰C¹ŸÂ*E]Ï& ekÕ豌VzÊÇËvÏÉd=R)‘ö}ñ\£}à‰ˆˆˆˆˆˆˆ¨*¢Ò"ùËœhK§Ó9矫Ͳ¬0ñ˜L&ÑÚÚŠx<>îÔdc8Ñ'+ ¢ÀŠq* ˆ ?k²”!ÑNu2òV9UpruO4ó%“I˜¦ EQL&aFXé(Û§J2Aèû~øÃ0ÇáºnÎ'Ñ Gß÷s*e’R&GFVâ;ß9 Ã@غÕ󼜫Gä¶%“IA€D"1&ù˜ŸÌô}†aÀq&©*äƒ~¦3B*%’a²½©¦‰Ä¢œ'QV-ªjn+ÕtZ<6 ´DB& ÅãÇO8ÊŠd)X–Û¶ñýïÿš¶$L4ÊÏŽ¼J,‹AÓ´1 ÅhÒQ~Ö«)ËÎ¥­ibߣûÍuŽW­¨i"™Ý‡lXU³se2ùHDDDDDDD4óÈi‹¢§¡d'½ÞèIŸià8Nxa~}}}XìÒÛÛ›snB²½j¡‹ø·¦ÆOÀÉý· Z‚V¶@HBTV“|”§üãÈ&ÿÊ¡£ôÄŸ  7sldåcm»ïÄÄ#ÍkÑ…œ—ñ®»ú°`A¶Åj~âÑ÷ý°âP&W¬¸¾¸A þ8ÈŠC™ø‹’IGQ= \xáZ¼òÊ¢°l^Î )“…ï{ßíH¥RÐ4-\¿¦iH&“ã&ÅM燕gŸ]ëCMsLˆ¤c2™+9šÐŠv}Ð4ñXÛÎ>¾¹YÜ—J‰JF9^éîÎM¸å·Íçû>š››Ãχ뺰, ªªBQtu}ÍÍâŠ,Ó4aYVø¹éïïÇxäçÊ¶í©µ(‘¢dÛÃÖ×ç&£û>:Zü2eÕ¤¬¤”?öLè‘ODDDDDDDD9\wì90˲r¦õ©ÈJÄÉë1wù¾žÿŽÇãá”CJkñjš¹íºrV‘Èo±:DkÑXæÿÅ$«É„H‚Æ —¹¬Ìô–%Ó2ÇÆ†8†²s@crØL<Ò¼&[¦†˲ ( zz^Çùç{c*ì\‹®ë"‘H„É—úúöìI¢¯ï$xžˆÛ££BUÕ0Á(E—7<¼® ,ýÕëxü~ôà-¸çœ·ãÈÛb8Õ¼8|Ü=ý6lýí0ÏH#qfêÇÛMË&3åRÉÞsýÓP?מY‡Uoy¿?2‚7>ó@Óàù Ž9§Ö‡žf¡ ÈÎmšâ½oš…/ZŠ’íQãñlec*•M„EÊ£›fîã¢-„Ǧi°m;ü¼öööB×uضd2 ]­ŽS©<σã8EµKÕu=l·\m½½ÙDaô”s1›¢ˆã-“rÙ5žƒœˆˆˆˆˆˆˆˆ ðýÜs`ÉdH$*³×ç‘M3wId§%’糇‡³Ùµ’畜¬ƒØd‰2"ág¡ò‰Ç¦^u(+$eµd© Ò|ˆda¹ÌÌ>$!¢½EnS ÀŠJÁÄ#Íjò*Œd2‰nÃÖ­çÂóD""¿Ðó¼°­b:FaRaÑ¢mP‘ŒøŸÿóL<õ”‹T*5¦¢PUÕLQΡ&ZG^uÕ ñ³Ÿ £õ¦×à~ÿœ½ì ªß†ªªøÒ³Ï†=¯ÁÁeËðÒ 7 ¡a1‚XTw9.\ôÞyÎyÖ}¯ž×ÃxQ!,\†TË7áþ¶Þ†ó¡k È$¦ ÿÖsÑÚ ø£¨{Pü1 ,ZôNo:?ñ ëºÆÕŠØþ¯áü†ß­õKG³„çeç4M‘<4MQ‘WìÅVŠ’­t”㔩ŒWdŽPλjåMFÝÝÝ]ðÊ/Ó4á8Ç ÛQȪÈèã‘ÆÓѦ8:¨TUq|+!ºÛ.œì%"""""""¢Úñ}qŽÙ¶E70@$-ËBwwwå¦r|oùr¼7/é(.Ü×Ãóg% “åšrî¤ÉNniú‹Xn¢%k "YX©óZ͉º©žƒS3Ûã@Tª˜z²’§õÌ~´B$4gÈy?&iÖ’ëA€ pê©ïÀ+¯¼ >˜Àš5ßÃe—}wÜñ‡‚­­­á¼ŒÿñÇýýë¡ë:,k!î»ïqÜxãrÄãÀG?úwH&o;7âË/_ Ql• ÿè:𓟼,Y´¶"qæ5PŽ.€ýŒ‰w½K$:½÷¼Gd_uŠ‚w|UÅÁƒ§àÔSõª«°ç”« õ~–%b´ñGG$xN„¦}&€ÖÖ5ð< pÅÇ c5ôÛD¢9þO0 ¡'žx€7¡j>²íj`áB‡NÀëo¬«õËG³€e‰9W£¢Ã%¶0ŒÒ*ídûa™ôWýýýá\©¶mOØn¢»»–e…‰FÙ‚µ˜*FEQŠJPVZµòœœæ•ˆˆˆˆˆˆˆhf‰ÇÅEÿýýââ{EÅ6–e…]½JfÛÙù}¼ñ­oá«##xoæîÖÖÖpùÅž/+Èó¢›°åVÿ$YE¢’q²n_*DeŸL>¢ôJÃJP2Ûìe~bÒ'ó‹¥¢²ÉG¹Mr[&[6[­Ò| [æs‘tS„meûSUUáº.TUÍG'¡«ëvïÐß k׺aÒ!‘HÀóÄó}ô$:dÃób0 QNµiÓò°­á¥—Þ hkû8|_lck+àû\yå£p¾µý­ÿÔ/ß/}i/vî¼ð}hžƒtw7àG®hyW‘ÀN‚ûÂ6ˆ…æsK&ÅíÑ®ª*cYb>8ÏÿʤŽëŠM^zi).» pœeâï‹Ú3þå_DR“‰²ó5ú¾‡Äãâ=eÛâ½W‰ÖœEt6 yž^0A˜XÌŸ¼ZQ”I[M(Š’ÓVUÓ´¢lÓÑbµð6Wg¹ü¼Í®+ÎÉÉ)x$Û¶¡ëzéIGy‚ØqÄI¾Œã›7¿ù ,Ë‚¦ixÿ’%xëi§ÁœÊ‰»BE”jªª8Y]y~䜆D¢­‚Ó^N}‘­””sUÊ$j1çõä,RÕ¨w° ’€hÁšÿÒÊd)[­Ò\$çŠËEâ¾tZÜ.«²¿øÅ—qÚinXÝxãÅw¾óy|îsÃx÷»×¢µøØÇ€¯|eW_}÷Ýw€áÏþìv¼ô’‰TÊ„¢(ˆÅ€•+Gð³Ÿ]‡eËÞ‰ ®À{Þs4M$[äÔqª*~Þò–hlñÙ0€¦¦ã#ù?èé醋5ýàÌa|"‘ÀÎnY€aÀTÏ{ߘývyåJÞúÖñ䓹ÉFÏËMBæ'!äßÙm2š´DŒO&ÅíW_} ޳–%.2Õ‘Àk¯ÝUÝQë·Ͷ-~‚@$m[¼Gt¬þúÇA<GP¦i†­TMÓ„a­:œjâq:Ú¬æ«TÛþ|œÛ‘ˆˆˆˆˆˆˆhfð}q®6¿»˜ìð•*5ÇQUsæJzç~]×錆 ؽ»ôõÈslòd:PÝ9~ä|qˆ¤]%[¯–*Ñ6–Ù.¹‰Éé$ÛÒÙŠRd¶ÅÞmbâ‘j²² GßÏ^€qàÀ«¸à‚‡aÛ«¡( ±=Õª¦¢Ù#²ÉF@¼mS)ñޓݪÁó¾úïÿ޾'Ÿ„ã8Æ£ÿùŸXöþê}ßÝ¿Ï}éK¨omÅ5÷Þ+…“õÙ'"""""""¢ªÝêò‹ƒ €eYÅW;Úv¶B%ÓîJ.OQX–…ÁÁÁðœ›"«cäIëÉÎÅÉJJ@Tõö–Wᢡô¹Uˆ„£l»Ú ‘ä›Ê¹ÍrÖ?Ñv¥ ’Ž~f»4ˆÄht}AÖåf¶EC6Ñ(ó4É’–8eL<Ò¸,KÄ™Œ­››ELζ‹–ŒŠ’m‹e/®øÅ/öàÍ7W@ÓÄc.½ô¿ðÓŸ®Gcã7àû‚iŠç´¶ÞŠTªý×gà‘G¶ãAkëû‘Hô†qìk_[ˆ•+÷ââ‹„mJó&ÿëƒWá¦Oœ‚ Oø5þìÿZËYð®¸%“4YÓsÎ:~ý» >úÔËUW¡ªb;’ŸzÚòPÎoÖž)‚EF˜`”Ù×q¬ªŠø­.ëïêë³Uî2Y+!ŠrJÈ Ô‘-…¶í‹â¾þ~ñZ`ÏØuËåi'Þ€²X,C»Ðž~üâŠZ¿½¨ÊäEK²ºVÓ²]‰©Í¹8ùºD餸¸® Û¶á8TU…ªªH$9WjÉdc~UcÉm$f 9m±<ÏsCÎmž+$N{òIÜúÕ¯â¿.½k1rÎ90iâå/~#©~çÕWqåCᲡ!œ¾m^9ë,<»b.Ê$x¿ô¥/áâ‹/®õa""""""""š7ä¹âtzìiåx<MÓŠ«vô<‘tL§Å À¼sP¾ïÃÏT¸hš–“t ɩޓMZ ½—mà£Fv#Ç©¤,™Ÿù)‡‘Ù^"É7q½˜bQ Õ«þS‘MB:•†DrTÍü[î¾OtLš!*0 ¥-RÈ­„¬&ç¹B3Èd¢m‹˜# c’I‘¬èí ÑÊSÄ$Y)˜Ž”[pï½Oâ/þâ÷ðÆÃÈȧ1<,.¢8å”!\zéã»ßý_ø§Ëùð‡÷!|à+ñÉO*X³¦?Ü‚Ë/¯°6l‡À7.Àò心ï}O¬+Ö<ºÀøÜÇÄ)ëþÁSMðýìö©ºŽ+ŒE»Óó×@ÓIJm;3·ä£'A]¹vº¼ùÖâñìÅ&ºžmcéû¹¿G«#eB±÷–̾µC @P,Àjͼ†']¯¦ÚÙ€þ ^tÿ-€ç}P6Æyµœ}—ªÍqÄ{OU³­y5M¼Ó,ñ—˜d2 /S«( ‚ €išèïï“H“j1wât‘Ç%‹¡»»F¦—¾¬ò4MžçÁqhš†T*ÏóÐÜÜŒüë¿âª}ß»æ|«®A`õòåøÃîn\}ì.ùЇðÚûÞ‡•ÿùŸ8xíµxÛyçáàG?Š[3*‹á>Š›_x!,—>=ó,\¸ž®ãnV}=V­Z…N8¡Ö‡‹ˆˆˆˆˆˆˆh^I$r¦^ ’Ž®ë¢···ø™æ˜*Gɶmxž7ùòz{@s®po»ÀK° ^ÖOW©4ÏGéíV£ˆdšLB&!’}zæ¶Zž‚Ô‘­4”íO“ÉѪ“øÔ2û,«@ ½=Šìâ[&ç!ÏËV Ê‹"¢dÅ´¬–nm±ílE£¼"DlkmÿZ–…D"Çq (¾ýíG{÷®m1zÒI}‚ÄoÔ…-A/¿ü¿ iEªCCoÁ¡C>lÛÆ¹ç~ž·<œ“®¥åR\¹RÁ?þ)¼g—ɯæ”p©_¾H¿8ëãh3ÅìÌ~‰‹@tèºØž ^n›ŒÕš–©»"¸Á :Aëx½ > .ÜïÎd¦~´Ä Y˜ïœ€r©HܦÓâØË¤{7 œ™YšY¦)¶Asõl@{PŸ)°~ €è7ñ¯ö§S™m>çgçÔúmH$çM$DE- >2ižHˆû+QLœLßb9€Ñ4 ýýýa壬rœËÇçy0M3ÜoÇq`š&188ˆÞÞ^Äb1¤ÓiضD"Ïóðݯk~ò|À/®º ±X º®ãð>€×¾þu Žâü÷½êÞ½0MC=†«,ï³,`Ó& §'Ü–ºÈvuww#cÙùçãÑ^×™«+NÔ4¨A€T*…k®¹}}}µ>”DDDDDDDDó‚ç‰ó¿ùçèâñ8ÇAñçÔ4­à¼I¾ï£¹¹½½½“wó$Uq¾ûfpZe:°ÉV™ÀÿR€NˆV¥ëX*}êPŠAˆsãD’oÙóøÑêò»!“}zf{‚*®+QeYÃÓ³L<Îa²j1 4ßIµhbQV,FÛ©ö÷çþ.Û4*ŠX†¦‰D˜“ñ¶nÝ×^ûÁ=°, 𦡵µ@7~ùË“ÑÖfÀ²TÜr˳κu‡ÑÕõ-\ye /¼¬Xñ,N<ñ"üç~%¬ŽRU@»äe\x`-~õ«_aÑ{Ä\š&’(›¿ùMœ²knYð8´K ²²¢û¯ló(+5aRÓÈT›_±I¹ÀQ¹P­È~h“ U˜gJ¨µ…€wàï4€ ø«í ‚W7ÈT<>¿è¿}€2 ˜o°J<qˆ l ×”Ÿ¹=üìv)kõ“¾ ¨ÿÀõ€’)ç¾ãw`vÔú-Je’­z››¶ Î~N%™„,µíºïû‚¶möípjUU1<<<7çc”W%¨jØ26™L"‘H„XA€ ÐÜÜŒîînø¾S††ð‹‡‚jÛP|ùŽ;`EÁÆSNaYbù™~ËëׯÇÓÏ?Ã0PgY"hÿû¿c™®ãJȇªÀM7‰_d/ëqÈ95»‡‡sïÐ4À÷aDœL:Í]Ñ–:ªªÂu]xžÆóì<ÓN02»cÊû ñÿ“NÔÝ@pÀ§öy6uÀUïaˆ ,'œÍÿ# “‰ÌìaÝ™¤²Ú(_¬ñ›”¦LN4-É š›Å@Å0Æ&Kåû~Ø>5‚°2FQ˜¦‰t: MÓàû~ÎÕR3)é(*xÄ6˶¦ñx©T Éd†a ‡mOMÓ„ïûX~àž:t_xî9¤Ói(Š‚×þìÏ z\EAmc8S=¨e^€eW^)Ì?FnÌ^é‘|eÂjÅJPéByVy½DT2¡­XíÅÚáµxhÏCpà`%>€g­Àš+‚gŸ½GŽœƒsÎùg ~ ?EKËeX¸p!nºéø§zïôÖàá5=¸âì½Ø´ø üò±_¢ã÷?†Ý_ÜóÎ:Á³V×z׉ˆˆˆˆˆæ,×ÍNU–J‰ï|Éd®ë¢¿¿üslž'ª‹ C$#çåä99Ÿ¢œgq&ÎÀ$]fÛ2–E“bâqJf®,mB£ç“››Åï¶m5*'ªÕ´ìÜŽª*ŽrC@İw¿{ ~®ÛV3ýð‡Ï8 v㥗¶àOÿô}øð‡oE<ÞŒtúK0 Ü–-[(æ³,Üü h}d;6žø|ïë¯àÓŸîÁ¿x_ü¾Ôü üè<èN‡»ÿw ½s=·©Ô á~è·¬@ðý˜3Á,uèNdnƒ¸MÕõï¼€ì|‹™À&[¨"ÓâT=73b+²ÐÍÜo±ÛB s&ùu!‹²ôÌã=dK·e0“d ÿdŠšf?į: ºÖB$C‡Åã ð\×cò«2Žá:,±Zæyæ4LK•åûb0âJ(9W# þ­@žÚrs žçÁ¶í°•¨¢(Ð4-lÉ ç%«¦{ÞFY¡˜ÿ»ã80 Žã@Ó´°D<Ï™0[×u¬¦iÐu=L š2ð)Š–ªŠõ÷gW|É%À‡>Ý0pè׿ÎݨèãÆSãù-‹j¥ADÓ.za‡ly*«°}߇¢(ECÃf¼þú8å”ãxé¥wàŠ“Wà]'®À3g½kμ?¼ú1 ù«C¸kÿ«¸ø÷NÆEß½¯<‚yæoñ±uá¢B¡€IDATÃÂß,ÄñÇŸ_õ*ÜôŸPKçBQ\æ/Ã¥ú¥¸ô â°‡ö<„ÕL<UE2)ÎÃ'ÙFW±X ªªNÞ^UÓŨq®ë†SŠ•|Þn*§‘täV(Ê–žrNEÙiÊú!ΧWznÈJPv+¤ê`âq“ó·É¹=OÄÛÉ$ÙZÆßÃiÉÆTBF6ɨëÙ†dY>¾ð…!45݇¿üËÛÈŠ&‘Õz×»žÅý÷--ç²Z¡dÚÊ –H$àyR–|æ38cóm…ö]Àò pÉ%Kñ{¿we;{0¢A}P5 È+oV@y²åÛ^&Ÿø5ˆ`¥h”ûýŸ3³3÷eÚ‘&‘ÛM@ 5‘ð3!‚ª ”Í\@¿Ù$bþ1TV)†dâ1YŽœv¢ Mžª€‹ˆÓêþ~õä ¸¢ùYüú׃X¼`-~=¤`ûµŸÃIø8ì;–õà»xû†Oâ ¿ò±¶}-^ùË-X¸p!þÀì_òdÇ3 ä\mšÿetÑ¢Eµ>ŒDDDDDDs’ìhÖÛ›-JfªŠº»»ÇV:ÊJ¡h1@ä;œ<'ÖÜÜŒîîîœ ðK"«Ë¡"·PgÙ©ÁâßQq.> ‘ŒÔ2ÿ²AלÅÄã ã8Ùó᎓­t²m‘pд1UÕ!Ù¥Ô0²IÊ|²-T#wËû 4S<^‹Î™»e²°Àv„b¿0Y{S¹l¹<%{›|½ä¤Àæz¥AÇsàZ"Á#+0¢ f˲ðàƒ½Lª<ÛÎέ*çnÎ&§ÚWÎo(çjt]7¼¤Óièº~Ƨƒ¬J&“á\‹‰DÉd©T*ljF¸A ˜¦ MÓÄí™×K—Ï<üßÿ \wX‰ãˆûS©Ü^´Rt_Ùo˜ªWæÍi®ë†±ëgÞÀ-ÏÞëY 'žq"þ}ý¿ã?ÎüÔ?’DbXqâøÑðBÔ9 O|ÿ$¼~ÂËØºú ^{s6zgþ¯“pÃõžhk\(Æ:öI¸~ð¿°U×Ô#.»! ø8ÄxÆCî¸ÅóÄQÓœúÕ)A½Ú…ó¾Uãˆ"]Ïž×ÿaK ¾þßÿK- ·ßž}p"‘[-Zq”™Öë™gžïúøÜÏ?‡ü÷`ÌôH%“S‡UKô¼¹<õC¸Ïqð'§œ‚ýŸú¬³ÏÎ&¸%[>ùœŠ7¿z~øßg‰ä!\`oÊ/5àƒW(Ä3Ç@¶05 &ÄUr~Äü¤ŸŒ‘ѼÀ`f™¥T{Éå4bòä_¾$D0ÌTHæ¯ßó<œ÷‘ó° ËäVo)ŠÛ¶¡ªªHæºJØÊLÞ–H$ÐÚÚŠt:{o¿·¾÷V¸–H,Ú– ]×Ãû=σ뺰, š¦!#•JÁ÷ý‚‰ÈX,MÓ`Û6Òé4EišaRG>G& {ì±rÞfT‚èù^Y€—H”VÕèy^˜ltž'z«ª Ã0H$àû~Nb¯šlÛÆ{֭×»º ª*’É$º»»qþSO¡þóŸGJUqÞþýèO§Ì|‹ÄÉsÇE–iG[¾æ_qDFBš–=ˆDÓÍGv¾àÉ*Ü©æ|ß+l ]ôÊ"[x,¼íرe^‹E‹öã·¿ýš›mìÚu1^yâ<\sê+xôÔŸâõ£ÿˆýîyøÆƒ+Ÿ}§v/þèã—㦿YƒÏÿé‰PöDëç—"½ú›0ZÀs>ð¾nàÓÎÆÙâÊÇÉôÅÏĽÁÁèÆŠEtmlr;™ÌVrG'²ýù inÎÆÙ¼/¨×Þ?^oi©õËDDDDDD4'ÈâEÙ^Õó<ìýÌgpÝSOá„x'üáæ~wSÑþ çψó Í⦕X õr×ÿëõ@=²çÞ£Ýóä¹ì©žÌïîGT!L<–ËHºõ¢¨‰XãqqÎ Ç0Æ­ž.Lžò}¼tê©xð?ŸÁÃËÞO¢}úñà“¯¿†ßÔÃ?Þz+†‡‡qf{;ž>~±X ¦ù2ຸä¥S±ëÌ3Ñðû­zôUÜúúå¸Ñ¸Q$]ÐRa‹Ó¿|æ+ŸÁ_ÿË_gæ>Ìœäò3ûœi Ùµ5óÙ²ùÏNDAù'r µSÍ9Œ¢2Ì0Œðß¡«†ðÎ'Þ‰Øÿᡇ 'œÎ'gšf8/žóÂ$_ww7lÛ†¦ia•V*rÐó¼°m¤¦ièî®Šã•¡ª*‰DX d†©T*¬ “INÓ4a‚ @"‘ÌÑç<¼Š‚SO=µÌLňE|öEäʆ‡§¾,×uÃö¹²E©®ë0 ÝÝÝ…'v]ñ¯çM9Açy<Ï ?#º®#™L"N‡•‹v}=®¿þz,øÁpÞÉ'ã–sÎÁ‰ßÿ~ø>×- „æyÙ~ÑÑ€''¯uq2\–{7vtP¦ªÅ—‚Ušü;'¿ ̲â1×µÌ5 9sEGEý¿}ž¢d/¦Š>Î4³¡H=ø§þàСC8tè–-;†µk‡ñýï7âñÇO…e=‚;ï<ðæ›Kp≇±dÉ‹xï¹ûpáÀZ<¾ô9ÀÈgã‘“~‘Ñ“pÁ‰o`éiÏáàËçãPý÷ñÄo~Œ¡¡£—mjÐFZf`ðì’gñä+Å{_=Ï/}Ϋ®9þ'øö+õ€kÁÿ[ðs¼ôÄ»qú‚ã¸þ²%ÐÞ \ôñ{°k×)Xá>ƒS>µŸø ‘ø(øø1À¼ €ÿ?Üs½/ÆRù1M׳¿+ÊØÞùò‚ YÕÙ¸){ñ÷ÓKµ¾^,;ÎM.Ú¶x^´´>â‡7ܦ‰ˆˆˆˆˆÊ红ÒÑ4Åi+×uÑÚÚŠß»ì2¹õV|ôïþ.û`9µXÀ‚8¿öœµÏ_ð<6`ÒÝ¢“YXXЋl²ÐÍüø™çëç*d7~ˆóòwy~^¶î‘§ ™x¤*`â±òC®Cœ„ìGÎUòD\|3à?è7ˆóKÝÝ™óP—{ÂI6~–'–ñ`EÃÈàØÂcxmøC8ã‰×qèÍCX†c¸—b¸­ 7¿ K®Y‚eoÿ NýÅÃXñ¤ |ÃÃò5~ú<4ªªbÓâM€ý >²ì}dÔý™õ{™ýÐ!b*D°Ò©‰ž+ô3ó|Ù²´ KV.hš˲`š&âñ8z{{ÃÊÀúX=z{{aÛ6 Ã+¢sÉù¾×uÃuú_!ý‹4>í‚°Wöp^–ÈÍœA• ƉJÛekK™’&£ÿ&ÆIÉçõgN6Ê$§mÛá¾¥Óéi¯ÆçºÙöìš&rÞÆ Éöpÿ7îÇ®»?öçxô¤Gñ¡w|ï9ã=øË¯ÿ%.½ú\àÿÚÀ³+ ‚L"NËÆ¦X X¦û}±!Šž3â¡{þá!<ùÐ÷ð»¿û»èü-Vþá•øÌ'?ƒnü šw~§|îoaîy`54ãñ/<Ž×¾†W¾û Z?dá¼Söãò\PqÑUà+P5s1B¦wBÙ˜beöQ ™€jf¯È |z–%rhžzÙÖÚ•hId–ù»+;!Èì2q'%¢‚:Ä—Ù‘åøñãøÕ¯^Dzeǰr庺VàôÓãÎ;G"±6gÑü#üeÿ;qÞ‚Wðî5ýèºO\ŽúúGPWW‡ƒcÍšÏâÙgolhù~ñPö;gž$Š>—}o9öìzõ-xËñ!\³ä¬,Â"Àeý/)¬À üo\6t˜8„CØ…]ø®„šC/Ÿ…s¾‚ïÞö]¼°÷œqÊxùÍ=xáøhQ~‰éý~òæb\½øGXvÚ2|û·¸ø´#xíøAœpâ2|êÕňp 6^öoÂMø““¢qý¯ñÔÎÇ¥§á='}4]ާŸŽ7ß\‚;ö=‹7ÞPqî‚—q¹|¤ù78iä$Ôÿºÿ'~-–t&–™ym°W,ñÛ/^Õ‘Ò4 æ©R©LÐRU¤~¢X_øµ–%Æcšâ'zQ†$ûðgtT¼b1± yŬìé= ðDDTCò¤¥$¿—G¿›»‘ÇÊŽE<ÙHDD45Aä'ñ÷4ØŽ(Ü}诰ñèFœ}öÙpÕ+ÐveÖ?½^|Aèn‘-ßVHÿÿìÝ{|Õ7þs$rƤ$!˜„1$P‡K3æRÓB)£Åi÷%»²»ÝvIvkéÙ>Oq»õ®´²-lw¥§n»Ùþ¶]ËÝu»í¶Øê†Þ·šÞ‹JÁ(Ä@DHBƒ'Vr~ŒÏh$˶lÉÖÅŸ÷ëå—miftæöÕ™ùÎ9çjw¤ßÿyÀ¿~ü_ñÎ/¼Óîþtqx±hœý*'G~ ‚@öÖTcÉ1áhŽt›h·$ù-º0µZhzÓº4u& ż€•˜¯™¦‰ÁÁA» øÿ%¦­ëX Å‚õ¡=¢lÁ`@Àná8Ýi–’"!(#•©`˜\40½ý€ï.À³ˆÞHó‘ºà÷Á:§œOø†¬`ÐŒfüãÜËð¾s7|ø3À|×|Ñš¯ÀÀWœOH@—duU¬aäÉ¥¤5ý¢’›‚xýÊ«ñÌÏ þõXpô¸äнX `õ¼ZÌÿÙç±aé—°z£ŒOoø4®ß{=ðî9ÀR¨‘y.w)¸ü×À­½·ŽÄ•¿¶âWÀ~ø:ì Z=™#;[K‰m`Œ”U‚wœ¢Huñìü[];‹Á©½°*mjÆçÌ®ÓcV™±X Á:ΰ*åâ{;ë˜ËÖM<ÌÓ ès³0Ÿ$ }Ð×Á¿´òDÚ ©Ùü×úàÄâ¸ôÒCHÄ‹¿¾óÏÎDZ Žáæ<ýo'ðë9'±¬*‰9áKàG5à~_à(vB= ;–›žÁ=‡Þƒ£]Gñ÷Wü-{[ð½»þõÏ×ãÜEçð?wîÀµ»¯EÍËoG2™ÄE¾tÛøèÃÅ[ ßÂ?.[†¯.^ŒWª^AÍo!Ï™þÓvÜ<ÿfüàñàÚÚkQýT5~ýœù<®yÛõøÙ¥ÆW_ÁÅñ‹ñ?7ü®ÝÆÆ!+éùà5â½÷<~µÝ®–.l‰uãŸ7·àWÿµ>Ï2¼þý×qÑÝŸÀ=?Ù‹+†¯À© N!>?Ž÷µbÿê·ðú—L<ú«Àëõ­‰‹öBQ.‚a¼ˆ!eäÁ éÙD~¾»O^é.àê pyèð±}häA+F¶zuúo]Þ4Åi}¨¦ÆŠ•e«ÅáHËsx½ã'§JQF·†ÌE0˜½yj?˜TôkƒBs^cˆ8Äœ­’%Çë:¬ï¾Œ‡ìz‹H0HËRߣâoQÇÉüç4â! ©ïqçƒÈR– R7VÄ Î²d&E¼HëÀ˜Iã /Ì“îµâ­¼ÌZ†þ€éÌׯ”Ûý¡‘Õñº£N¦<Ÿ0 ߤÛùf Ü (oXè§O5þ>€5€º0~2²:ˤÛÏÕ@øKÖ~øVÙ% 0NêbÀ¶¾#”s€ºÿvd=.pˆÞ¸£€´^ ~>òþk¹Ê9«Ü¡'u-¼ pÿ€Ó€| ¢"ðC€íÈô{Ó7mô~@×'zB®´U\,RÇ;~® ™çx©sr"¢~¬!u}¤êíã]ÓÓŠº¶ˆCb|bñP¡ˆ!#_›"u?EÌ'Rt®§6ò¾óg1M/¬ë±bŸçŒ'¢¬~X×cÎr8)c”Õ)èx_ul/'gYÇŠe@êÁLç4¢ì¢5ŠX†ØbÅöÕ2¦ûDÄcg¼ÎÜ&Ù&b>°èõE(w ˆhRf$ˆ‡êG†3{ã-À÷E Ó«£õk*Ž|ã"|ãø î¾{ ‚jÐúîr6Öñ'Àk+^Ãìø¨~ß}Áæ Ç{àt,J–ÿX÷ 3¿Óåqæ#*²J<ŠÀ!FGGÚÚÚ°cÇŽéÿpqÃQT¨U!ÀüO "  7ú$B;¯Dȇ ÈŸùsÈø€5ÀÞœÚ|AÁ‰o/ÂâÇãÄžx>ò•+àé»Öâ½huýôâÉ/ËV¿î|7.zã³8xÝu¸õÎ;!C Àün;³Ë-ü õàgý  þ‹u¢­ ü pX³DÎXM>呇‚®Àb\¡i¸Âa+¼D"PG‚v‹ÿfkƒ{LÑÍôÈ÷eg§5/ "¥†™ß§ #iˆqg38šjRp¦x<94±¯ E½6p !UWßÕâa™$€ªŒéýHÝXÏìIp>pãœ^-¯ŸãÉ,¤@¿ú/Gfi4QÎ%VÒ'ý‹€ñ ~À/s? /™n%àý ü9ë_ï@û@OæY@^ È»üˆ< ~t¥¯ŽGŒ¶æSä“ÖôÆ ë?Ôl‡èÀ±MÔïJµ•d¬„šû_Ò§é|;ù íüGìB?´Þ“—Y?þU@àG€T wõ¾´PVÒ„Èy@9x¾h= ¢¹|ÀÕ€Zè/éFzwz9$Œwø u޼¶À@^Èg­ùq# ? `ÏH€´¸ôåCŠÎÇU§âØœc8üô\xæÏÅé•§ñÜиð$î|õBÌ­K`•+~¶K÷$Ñ{ìmxkõ[xE}íóV`Ý÷âí7ýßû=×H§ñê±y¸fí|¼ué[˜ûÖ\Ìn>?dbuÝ#Þ—÷éP % IÔiÃH=ì,Î ‘„ "UÿõZã?t7jì`Xõc?¬:²/ãýlŠÄ˜ä˜Gv,Û™×C^+)²õYÚN@MšÖ–#Ÿ!ß˜Ó HKé` 8 ಠ#W+ë¬sQ3ù@zÑŠaò@û!€E€÷: ü,€pÌšÏ{ ÐæZÉuÍÈf}À^gsðÏÂbúáGó‹€ñó‘ÏÞ Èóȯ¬ÿƒ·>¿‚UwlÂß³âœgýÈÃâºhÀ.kš@€@°¼àšÔ2$PçZ1SšxWÍÏÊåF®I£kß'­Ïé¼Úúþ`¾5²Û¯üw¦bft#àÞ‰´ï 8ÿ­ë±ôôPžI ˆhR¦-ˆ.QÑ×M`»\®wÉÐÔNøþð~\Ö‰Úîv¼p~3Þ~òkxßýÏÁÿè5Ö÷ÜÈu‚išÐu²$£îÓuVCÅjl"Å{6 ")«Äc__ZZZÐÒÒؾ};TUE__ššš¦¾`ñDŸó6:1Ö߯ŸÚJ@¿Ð€aC·YOÃzÛyïcZÙ”œ tXY¿Ò€G`££Ÿô?‡Gc­°ÀkQhZjÈ­†¶À¹sð®~ÁËÀ»è ð¨u<›¦‰/u¡fïN|â :„ ‚ÛqŽ(Š‚¿ÂÒ+¯ÄŠ÷½Ïê/ÑãÁ'œ7·½ÞÔƒ¯’cdà4MÓ¬Ö>n7úûûÓÆ}çŠavK_g¥åýÅÞySá|Úz¬P Žñ7JZúG~w"Õ‚Õ@êIcgë̱n¸dÞàÄ ÞÇô™OG×Õ•à|ÚÙ9½s[¨HµFϳuKõ@5ÊYAbÁÿ6€G€ùpogj¿}ÀoÄPÈ€œ·ýžn9ÿ"è#1dÇ•GñÄÁE¨¾âe,zæ3ðzA˜¸qœ9uu§$|ðÍ(^»íá…/¯} ‹O>Œ» xV^Eþï9‡xwÚ75ì{ÿã‚W%LJѲ¸|È…aë¬T)˜ûÔOñ;ppõj$ ,|ì3xbãF\yv„wÀ»Á‹«¯¾®'wÂ?ú\.ì{úé´‡x¼‘@}áàßþ ?ÛñŸ€r%þ‹‡­ ÂO‘]¸.¾X»vTWá7~ô£€¢àš‘ïúe7¦{2 AB‘ôíŸÙ½¸è[VŒ‹˜müCÿ…aæ23§c,fö_ë”L‚ÊCÞq@ð Ø+Ù}ÖþÕ›z¹@]F@oQj5‹/Ò€ïjÀÝDC‘‹¼@TNÕ×;Ã0Ÿ?ýàjëÿS« ô¾ß]A]GøçŽ`½p!Ôc`t.A$2ò7<·ö~H‹N@^qº¶Q¿#7tuäÐ>b­› ë”po·N§~?©Ï¨7[óyæÆ]€¾ÀB@ö¥ôŠSÒ|'€–‘aæßðq@2—#2på• Ü=pW]µÇæÇqÑ ÕoéÒ³¸òÊŽÖüõYìýùÅ8µêo‚û½‹ádlB(Tƒàñ'Œû6/ÇÅpàØ1,<}óo:Š#Gj⦋À ¦Ž®–“Z¶ CË–YË0åC©*ÃËöâSm+ñ«Àª'Š.†42Áö?ßb½.Dž¬®·þÖÏ ,@ –bÏ{GçÍC.èI8,¹øZ¬šÿ:\{öØžÙ{%4\È­ù:Vá½ ÏãÐÞCVbŽŽFZ½§õxùð rlŸ_ õL—@~ø—Õ«±ë……0±ŽŸ_pþÏâ‹qèÐ!\Úemß?߸xcdÆ7Ðθž’É$^®®Æ÷jšñ'Ͻsò'a‰˜¶û…ÔŒTK9AÔ1½°ê’î,ïÓÿݱ ’ÈþTCwU²Îañ¿NØ0Ò¿Bu=563n‚€À¿üý¥‘n܇ü#€€â ä© ëY,·0CÖW«®4D©GûGʤ9[’ôÞeÍX_·îŒ3ìù4k¹ª þ%õ a-@ ×Z^ð ôo#ë4² å*Ë}¹õ¿Ù èM¿4Ì>¼8ùŸoà†»šq€Ë†pòäbüKßo€¥#+<¼þìI´´XçÃVîÇçN¼‰k_xW¯Ü…ƒWCúš‰olÄЊ+Q®!”E, IÓuݾ¿˜1lS6ãõl¦wÝ0I¦iŽ*ƒ,ËöP™DïpSYOqOHÜÇÌ2×­[W°užiaX•Ê‘çRÑ àÁðš \(Á¸Õ ãÜ„BÀ•Ê3Hè¹fÞsÅØuß|Èòj˜&à{Ó€yÚ„^Scaˆ@¯( Öl^ƒ‹”‹ð÷ø{{Œ¾¬$@WuȲl=aÈvk?çˆH@ˆd¡Ûí†ßï·}õW…|àvÒÐ96¢3ÑØÙÙi·DÓˆä (»àL(Š/FÃ0à÷ûíòˆñ ‹¡§§6l@}}}ÑÊP hoo/v1¦]>qöíÛ|Ç>Ndx~Þ $Çì·dè_¾ fýuÐ^º ú‚º50´¢XúÿòñG %‡0çÔ 8òÊ+ëǹ‚Ö4 ^·»\¨ª©Á’%K0ÿæ›ñÝÿý¿±zõj{lÎ9?þ1¾Ûc”% îš;©/IE±Ï7Ã0àõzaš&TUÅàà dY¶Çý ÆÌDý¬?'d¤ß°-Ö3yÇø[ù[‘ØÝˉל]AeÒÓ‹®§œï ήšœÓ#c1xøHË{áСC8·ù.9yIêÉwgwQbþ 5ßú߬ÇþßÛ?{£ð R'ì~.‘M+9mç¬d‚0 ëÆ—y¨úGpäÈ^ôô¬ÅÚµ/ãÎ;×âµÄ¬8Ãνwã¯a`óë<»hú–áw®uØÿÖ[ø‹;Ûñï==èÿÏÿ„ÏçƒÇãAÿqÿ×~ý+WâÐéÓp¹\ðþÏÿà³?ù ‘¢—GñõWàâ¿ù"þëõ×áñxpæñÇáÿýß·ë¢q…cýÄ!a·Šyh!22æñ\dé>]ÄÞÞìI=1îàx&JÖ‰»‡ãñûÇ?—–þŽÏÀ®§žB‹sÄ‹|aÇ:AnuÀßù€ßFY±4šküá(RO5o'üÔ*«7Bz€Õ@dÖž ‹Þ· ú5ÀâÅÀ‰~p!|X§Ÿßè=ï…¶7u¦ÊˆÐù~kü—U«N ö_Áîý ±r‰•Ztð ^ýúÓ8rÓMذa1Ö¬9Š¥ÏÅð÷<ƒçŸ×=‹Ó+æã?¸~¿•0«9r1w/¶Ü½—:øMÝu‡‡ ªV]â_Þ¾9qY àeàÀâňDVÛåÒuàÝßx¡‘$ÜÑ£GñÍ3gìFÀ E¬üˆ3RˆNa„(€/#½'GqÉuË-·à‘G~‹£ÇŽ¥íŠoÖÖÂÿ¶·aéÒ¥8qâî{ýuüÉk¯¥MóÉ¡kñÔ¼yXºt)Ž=нò Ö;†%gÎ^X½^¹Ë—/DzeËpö7¿ApïÞ´eüðúëñ©sçpÝu×aïÞ½ø£¡!Üõ iÓl»ÿ~üüç?ÇG>òüó?ÿ3þ8‘€káa4½u9:„#uuèºè"Ü{ï½8pàdÓÄ–S§`.]ŠÕ«Wcÿþý8ù¿nÀ_¾ø"¾ô‘/á+_ù þdíZ\òøã¸à‚ËqòäIÌ™3ç>úQ<þøãxà°íê«ñí®.´´´àk_û>þñÃÜ¿ªª"‰àª pç¹sؽ{7V®\‰'žxÿpß}Pü~D£Q¸Ýn|øþÿã÷ãÚk¯ÅîPWW—6¤E(B!ôúýh…ðûñ™Ï|_ùèÜvécÓ–¸‚Ä‚8n*°\>¤X_ª€¿1ÍŽJW t(0z$OòæÀ“0Ÿ~Ìó‹¡Ÿ¾ÞïÞ†pÀAÀûÞõsèC«9æÍƒç±*À»‘ïÊ)ÀóÀ~4ÿ¿Å0ŽÕXŸã¢ÿuî?]`$žD‡ í¬ÁUK_‹G×Ásë!ø?¿¡õo(´ív-j/xܪjMk„–ö°]ÈŠ9 V•8­}ˆfÅÍ1M—MÝG’H=»¡ŸY#\@OOFç3#;¬²¬^½}}Çð7ÃøiÞ<,Y²çÏŸÇÜWçbÏåcéÒ¥èé9Š¥K—"ôÜN .[†sɳxëÄ\|ã§KðŠË…×^›3gΠnn.zë5¼Y]µxª`çî7‘XþNœ8ùóçÜs.éæÎ‹… âì鳨³çËx÷»ß—_~Ë—/GüêýØ»w/.½ôR,[¶ ¯-X€E‹~…E‹áÈ‘“Xrýi|ûñÒUïÄàà .»ìíØs4Ž«—g·¤ùÆ‚·õ>–‘`êP€9"<v„ÝŽ¤Ñ øœ?ýÔËÀ< p)Àü ,TS×g§4à:àR`~ú©ÕP¾õ‘žþ0ýÌßáü™aœLÖàü‚×°ôÿ\‰D§ÕGÑâ¿|çÿöMœ>}sæÎÁœE—àÂ[/ÆÜ—ãÇÏÔ ¡þNˆà—ƒïÌ=w°ìý‡pàÇÿ °êÊ,~y7öŸºsÎÅùóçqxÁ…˜s…† ÷~§OÆê?!ùÃ?DN#‰˜›<†E¿…çÖbÿðÕ˜akª~ŠƒGê‘L&qîœõÐÑ3Kz°æØgÇð\7'‰¡óuöf;‡aüßF=¶ÞÄå¸ßµßÆ…~ƒSP0ëq‡±?ļÏár$1IÌÅ<ˆ ªþóæÍCÍÂcå‰Óx9iÝ÷¨Nà Oà|݈¿ôpöìYÜxÅG10øûsÎW-ÄeË_±“k ­ÀR¼„uó~“ïÃÙsU˜ƒS¨š{V^µ û_þÎ;‡K~·Í]—Ë‘L&Q•<‰+–Gbå±ÿåáüùóøÀïý1vô}ɪE˜ «Ùñu—¿ÃÇeì5/ÂZéMÈø~ù†5ÅîŸɪE¸éÎ'ñøÈþi¸êœŒ'ðÄÏ–¸sçÌÅÛWžÅ Lâ?ÿmΟ??ýý{ñïmGòÜiT?†ªª*ÜqÃy\±p5^Xz®^øä×~‰ÇömÄms‡1wî\œŸÿ6lu¿Žÿ|Ɋ÷ßxGžy¿=v0w pþ$®]ø~µÔùèSù(Ht@ï×€£_ƒòçwÉÔuªééE$22"G'pýõObî܆Ûý~Üê½ט·Â4MDŒÂá0ü~?ÜuVãq¿=9M»Vµ`%ÜÇÀ®]»ìølU6‰ÇááaH P]]‘'XÇ’H$püþ3pþ t(Ë1ß5OhaìÙ|;Ž;†+~^x+ö·n¬-™›Ào=Šç_ÿ(.^ùþûË<æk€ Ý|ÀK—]†ß¾ím¸âŠ+H$p÷ÝwãôéÓhmmÅ×¾ö5tvvÚ7C¡OÌèº'ÕÍ™ÛíÆàà FGºOL_(º/Í6V¡¢(öHI’pøða{:Y–íîH놤išvKDñdEoo¯ý¾ów¶V‡â51O)´LŒÇã³²ÿþ‰ÎJ‘O€cÇŽÁ·ù§xjÎ}¸ãöÛqúš ±øàb¼ÙÚƒßþö&;ö,.»ì,~øÃaiôw8{ö%ÔÔ|ï~w'N¼MKõÀ·lÙ2¬[·/¿ü2<^þáñÁ~O>ù$”Ï~ÿ1ÒQ$ç=â‘G±‹N~¿ßn8ÑX¤â<ÎuÜUž’™£Èî‚cüë2ì]ÒŽ7ãï¯w|¸¤ñ’ôé³å‹TàÉØ“x6ö,~¿WØm5ò­œý¿CÃ3·`ÑòÇqõ¦gqêÈ\ùàã[ߺ GŽÔ`íÚ§ð pâÄ*TU½‚“'‡Èønذ¿ûÝïpòd–-{믽é_†¥Koƒÿæ›íÞš››Ñßß@ €Ä7bþ¾}¬xdY†òùÏÃ9ßÅmÿŸŒü|ì«_ʇŠó~Òß·Š‚GOŸ†g¬d[…vÝ=<<Œx<^ìbÌ8Ö r«ÀŽþ>»öqðàj;v 555¸ôSÿ…ï}¯ÃÃsðž¾><¼3h]ñÃßбxñW±gÏõ <\÷m¼ôÒ{P]]ãÇ—k 6ì›xë­•¨­=€PèÙQŸkIµø1 à}g+°èÑE¸üòËñ_ÿuW\q^~ùe,Z´'ÏžÄk®ÀË_ +V¬ÀÂ… Ñ4o.åœ={óæÍÃ[o½…·–/ÇS#¼===¸rÉ,;tûW®D"‘€kÅ Ì;‰D—]vzzzðïy¢?ûZZZíéÁ{?ò„¿òø|> ¢®®‰½{qèÅ1ÿæ›ÑÓÓƒÏ=ü0ÞsÏ=Ö ¸ª*¸¾ô%4ô£hiiÁž={pé5×àöW_űcÇð®w½ Ï?ÿ<žüÒ—pÓG?jÏýÏÿÄŸî‘ s\–r<ý¯ë:‚Á ž ì±Îãž‘ÿ#‘dY†ê¼fZ»ºÇƒ@ `_“ƒAÜ6ò¦¦i¸@–θÎÚ¢ª8}ú4n¹å¬\¹æW¾‚¯}ï{ðz½ˆŒ\›½×q=fš&^•$hš¿ßŸÜ` ŒS¿|ùr,—eœp¡$áäÈ:}@’pã7Ú×i( êïº ʇ>„•Нn=Œ*>3MWŒs V,8ŽßÄã÷àÙóWãHÒìZïû ¾ùâ_áøÙ¸c¸oKÀ¡kÀ¾™øë?ûK,{³§OŸÆß…z1wO VÍÙ‰Kª^Áܹs1ü_1„—-C•«ÏG_ÃkúøŽ-l„†=PøS1Ö‹ŽPÈ„#Õ¿£#…ÿÒp»GÞwäöµCÀ³W_Å‹ã[ßÚ;—/‡ïÕ—¬$þÁ£X±`þ1¾oÔôâĉxãÅh>r+ßz óæÍÃÛ‡$Iø×È)\}õÕØ¿?n»í6Ì?ýZ·köÿ .į,Bü­j$ üèG?ÂûÞùNüæÄ ÜpÛô<µ×]×€O<÷¬^ÇË—/ÇW¯ÆeW]…•+Wâ¹çžÃ¦M›0‰àãÿ¸u…Bpk>ô¡áž~lØ€={ö`#€+¯¼{ö컥U#ÓŠy4¿ÝÝÝøâ¿ˆ+¯¼ÿxð >uö,Þõ®wAÓ4ë>‡Ûm߃‰F£¨r»ÑÙÙi÷$£ëºÕ¶¢àë_ÿ:‚_ûš=­ø­ü…BVïOºnà02¿ßïÇÎŒynv»ݱÞçE]ÇÇ5 ªªvÜjnnFoo/Nøœ#ÖeÞú Çƒg|øÃF ÀÇ>ö1,¾æ\ôö·c•,c®a`¥cž{Fâã½÷wx8À?õ)ü÷_üÖ¼õV±Oë)É7xå)ì~ÑÀÙêÅ8|j1Î_ƒËÃýøÙ››a1qÉCÏ£êé ±ïø]©™^jþê¼4ðg8vì.V>{ƒzªø½ÿø*^_øv~?Výzï9þïø¾m¿KÞ{ŽÁêidíÎ\ŒxïÜŽã ¬B¼½óиáŸ{þ„ýZu¼ K~ù$s_Æë÷`ÇÎ=øƒ:N\ƒóUspºêÌ©šƒ‹ÌßॅÇqîÜ9\Yõ&6œyOŸDÓX×oá§ñ»{qòäIÜRUsî ¨š3HžÇù9s0ïŠ3H\À‰#'°pÙ¼û­8"O_„ùsç¢êÜ9Ì›;¿wïïaPŸ‡“'Nↆ°äÛ?ÁÑ3ob8wþj×WãõEk0/iMóÝ}ÿÀ0ŽÍ‘°G°¤ê(®ù£[ðÊéuøÝKñ¶‹âÆ× DŸÆ-ówáÌ™³˜û¶ÕØø—ÿOýèB?vï¹óþÜB:usªªp>™„üŽKPóG·ã©-„9ô:îþ(þþóçÏÃÙsç0§ª ×Üs)^9½ µo,ÀÛ.^ƒ–a ?úåÃØ5©ÏùØíxêGó±ÿµ7P}ñ[¸õ·ßÅ;æ»°ïìjœO&¡¼ó"¸ZÞWbó0ïÌ«¸·^Å«±'1þ<ܺð7øÙ‰pÍ—â‚KÎâüñ“˜sáYløí+xÛ/ã¸jÉ›8yê$^»øVH¿¿ïn¨ÂÐЮ¸¹É¿ÿ†»0gîœ?w5ï¾oÖ×ⓟ<‹×^{ ¬¿ÿê±há"œ9c%¡ß~/\ŒÛŸÃœ ‡±á·Ï`ýÑâh"¥.\^³õ×à“Ÿ<;ò9süû‡ ^àøœ[oÆ;v~¬Ø§ô”¢N^AäÕË %ïp/¶ž{¯Üþœ9s§N½ÃPpäH ΟïÁÂ…_ƒËõ6TU-A{{; Ã@ss³Ý`oo/TU…ªªvÝ`ºïWµ`%ÜÇœ­÷"2U%§+Å^`±X [·nÅîÝéhlݺÐÝÝ=æ¼ù—‰_õœ6ïÀN¼€‰ªª#H&=X° çÎíÁâÅ_ǹskPUu <‡ùó磺ºDmm-Þxã »bÛØØˆ½{÷béÒ¥ög,Y²ÇŽêU«ðÒK/aݺuöï`íÚµ8zô(,X€Ó§O€ý÷‚ my…pèÐ!¬X±¢Ø»nF9r‹-¢Eå?(úd亯:„ÇcéÒ¥øñ\ìbOZ>qn¾ùf$žz'^8¿"s´`Ás8þGX°à}8}úE\|ñwH$°råJŸ§ŠçÄì1™}=00€óçÏãÿøñÉO~²ØEŸ´|ëßúVÎ|7 P4þ|TUý æÎ݇ŋÇâÅXOHâÖ[oõýþæ›o⢋.²¿×/ºè¢boš1ÍÆsâäÉ“8yò$–tÁ8[亯;†}ûöáìÙ³øîw¿[vwùÖ š››ñ½ï­Ä©Swaîܹ#×'qâħ°lY+ŽÕÕ/#‘˜‹·½íhZ]ü=<<Œ•+Wâ7ÞÀÍ#ˆë…+V¤ÕNœ8K/½GŽI«?èºnÿ¿jÕ*;v K–,±÷QfãÒK/Åk¯½–6ÏÂ… G•íèÑ£v½ä’K.UOɶ>¹Î3•:N¹ÖGʵܓ‰ûöíñcǰvíZûÒr’O,ˆÇã¸ûî»ñôÓß` ªª sæÌÁÜ¹Ï ™Œ¢ªÊÓ§OcùòÿÀððp¹\H$X¶¬‰DË—/76tè?DlpƸôÒKX±áìÙ³8qâD^ñd²óìÝkýÒK/aíÚµxî¹ç°víZµ NŸ>¥K—ŽŠ'/¿ü2jkk³n·ÌyŽ=Š… ŽŠA™÷SDýëôéÓ8|øpZs~N>ʵ5™rÏæëƒÏ}îsûqøðg0oÞ«8{ö,æÏŸ3g>‰E‹îÃùóobÁ‚_àÌ™Z2,X€sçÎaáÂ…8}úATW¿¦ibÕª×qàÀ%$ §OŸÆ…^ˆóç_Æœ9øðÂÓ8qâV¬X={öØç÷•W^‰ÁÁAÜ|óÍö}Æ£G­' Äßk×®µ[®;¯[·‡‚$I9Ï£(ʤ?§Ðó¬Zµ O?ý´]w*¥²7ÏË/¿Œ… Ú-;K©lͳvíZìÝ»wÂy<ˆE‹áøñãØ›ÑkD9È÷úàŽ;îÀÊŸlÁ1Ç/ð·8 îÇ©S÷â‚ Náܹ=ذ!†½{÷âºë®Ã‹/¾ˆ 6Øß—¢Ž\Ìûåú}åT®õo§r¿±oß>$‰¼ëeÓâ1ŸÿüçÏg{Ç9–`y7C&¢‰=ñÄY^U|Âñÿ¿»˜D4>ÿùÏ[õ‚QbÅ.Í Ñ –ÛG~ßWì¢Ñ ©­­ÅÎ;Gþsö&r;Ò¯ü¹/”ˆÊÎ'?ùI¤î«:cA¿ãïOŒ1wñ†"¢ÂJo ñ¿‹]¢²7§Ø˜¬lM†Ë¹Ï_"š<Æ" ˆˆq€ˆ,ŒD0ãQ©(›Ä£èŸy×®]i¯Çb±²ëŠˆ¦†q€ˆÆ"b " cŒDÄ8@TjÊ&ñ---èééA"‘tuuÁåraÓ¦MÅ.ÍÆ" ˆˆq€ˆ,ŒD0ãQ)©J&“Éb"W‰D[¶lA"‘€ËåB<G{{;ZZZŠ]4"š!ŒD0ãY ˆ`, "Æ¢RRV‰G!‹6lØ—ËUìâQ0ÀX@DŒDda, "€±€ˆˆJAY&‰ˆˆˆˆˆˆˆˆˆˆˆˆ¨´”ÕDDDDDDDDDDDDDTš˜x$""""""""""""¢¼1ñHDDDDDDDDDDDDDyc⑈ˆˆˆˆˆˆˆˆˆˆˆˆòÆÄ#å­¢¸á†°~ýz´µµ!»HyéëëÃÖ­[Gý Lz½ËaÛlÞ¼±X,ë{…XÇRÝc­w.û¿Rö}¡UÚ:*”ËvÉ'”ó9‘m½gÛ÷@¡UÒ:ÏÆca¬XP¨u,ÅíÀ:AåI$hkkÃúõë±~ýzlÞ¼yÔy ”n]·¯¯ªªbýúõPU}}}%_îD"mÛ¶¥-sºbe!Ê>ÖyŸ¹Ù¶¡¶/cÃô+T,(Æþœ(”b¹s‰…*W¡ÊO,(¥˜FãË%”êþœ‰:A¡Ë]nu {,(T —iŠo&ãþL­Ï 7Ü0ê¸.‡u˜©:PÅHV¨Ï~ö³É†††äC=”|üñÇ“÷ÜsOòž{î)v±ò^§;î¸#ùÙÏ~6íçÕW_Ôz—ö ‡ÃÉuëÖ%üñ¬Û!ßu,Õm0Ñz·ÿ+eßZ%®s!bA¹l—|bA9Ÿc­÷lú(´J[çÙv,ŒwNbKq;°NP™Äv~üñÇ“?þxò¾ûîK644$‡‡‡íiJµ®ûØc%×­[— ‡ÃÉÇ™Çu9¬ÃLÕ*IÅ&ÅÍáÕW_„ËÍý÷ߟ¼ÿþûó^ïRÞ6=ôPrݺuöO¶Šv!Ö±Ô¶A.ë=Ñþ/÷}?]*q  J}»"”ã91ÑzφïéRië<[Ž…‰Î‰B­c)mÖ *×®]»’ëÖ­KîÚµË~mxxxZŽÙéØ¿÷ÜsOÚ2“Édò¾ûîK>ôÐC%[îÇ|Ô ááaû‚¿Påηì÷ÙŽ±Oî»ï¾‚n_ƆéW¨XPŒý9Q(Årç U®|Ë]ˆXP 1r“K,(Õý9u‚B—»\êÉäø± Pu‚\¦a(¾™Œû3!'ï¹çžQÇu9¬ÃLÕ*IEvµ:00€x<ŽÆÆFûµÚÚZÔ××c×®]Å.Þ”Åãq¸\®¼Ö»Ô·Mcc#º»»ÑÝÝ=mëXŠÛ`¢õÆßÿ•°ï§C¥®s¾± ¶K¾± \ω‰Ö{6|L‡J\çÙr,ŒwNjKm;°NP¹\.Z[[Q__?æ4¥Z×ÇãH[&lß¾---%[nÑ…SmmmÚ~ذaƒ½N¥Grùþolluìlذ‰D¢`Û—±af"cNJµÜÅ\?s&bX¾± Tbåf¢XPªûs&êÓQîr©ãÇ‚BÔ r™†q 4ÌTÜŸ ‡ÃxðÁG½^êë0Su J3¯Ø˜ÃÃÃ0ê`¨®®Îڹصk†‡‡±~ýzÖd{{»}€ç²Þ¥¾mjkkÓ*™ ±ŽâõRÚ­70þþ¯„}?*uó¥xdÊ7䲎¥x|L´Þ³á{`:Tâ:Ï–ca¼s¢PëXjÛu‚ÊU[[‹öövÖ…éðð0zzzP__oï‹R­ëŠ›óµµµØ¶mâñ8jkkÑÒÒ‚úúú’-÷† ìò;Ï+±>…ª/ä{NMtÞ××׺ù˜H$ðØc´þÇØ03  б?'Š¥Zî‰â@®Ÿ91,ßXP©u£J5Q,7¢KmÎD`:Ê].u±mÇŠ…¨ä2M9Ü7š f*îO·D"ûï¿^¯wTµÖa¦ê@•¦"[r‰åÓ(÷XPªûs&ê….7ë¥Óhb3÷§C,Cuu5¶mÛ†­[·bëÖ­R-½Ëa„™ªUŠŠL<Š'ý3æŒÅb%ÿÄÐXúúúÒNF!ÛÁ&—õ.÷mSˆu,Çm0ÑþŸ û~**q  *a»bËm;ð{`ê*my,  ëXnÛu‚òÕ×ׇ-[¶Œ;M©ÖuŸH™ËÌ©ÔÊH$ÐÑÑ‘vC ‘H ‹aÆ eGÚÚÚ°iÓ&lß¾=ë2gcݨ\"cNJµÜÅ\?³T®±Æ‹åÓhâXPªûs&êÓQnÖ J3¦ÑÄf"îO§––<ðÀhmmµ`Ó¦Mhmm-‹u˜©:P¥©ÈÄ#`Ô===ö“ß]]]p¹\Ø´iS±‹6%õõõˆÅbèèè°_‹Åbvÿï“Yïrß6…XÇrÛ¹ìÿÙ°ï§¢ÒÖ¹P± ¶K!Ö±œ¶¿òSIëÌc!¥PëXNÛu‚òÕÔÔ„D"®®.ûµX,†X,–ÖEr)ÖuER»££Ã^¦8îD—j¥Zî¾¾¾´mÞÑÑ—ËUÐrOGÙb±âñ¸Ý Æùã|jz¶ÕÊU¡bÁLïÏ\â@©–{¢8P¨rM÷ù“K,(‡˜F–\bA)îÏ™ªLG¹Y'(­˜F›É¸?]DÒÍùX×µ…ŽuÓe&ë@•¤*™L&‹]ˆéH$°eË$ ¸\.Äãq´··—üx ãééé±o2UWW#£µµííí“ZïrÙ6ëׯGww÷¨±ª ±Ž¥¼ ÆZï‰ö%íûBªÄu.D,(§í2ÕXPîçD¶õžmß…Tië<…lçD¡Ö±T·ë•§§§Û¶mƒËåšÖsw:öo<G[[P__‚wÓQîX,†¶¶6TWWcxxÕÕÕØ¾}»Ý¥Q©Å‘lç}GGGÚR§ÆÆF{l°J¯U’BÄ‚bìωâ@©–{¢8P¨r²ÜS¥Óh|Å‚RÝŸ3Q'˜Žr—[ U'ÈeÆâ›É¸?“2ërX‡™ªU’ŠM< ¢_ô 6”Í «ãI$v“ÜÚÚÚ1›âæ²Þå¾m ±Žå¶ rÙÿ³aßOE¥­s¡bA%l—B¬c9m~ä§’Ö™ÇBá×±œ¶ëå+ÛÝòL÷¹;ûW,s:»B—Ûy¾d&ò Yîé(ûT̶ºQ¹*T,(Æþœ(”b¹s‰…*W)œ?•Ó*].± T÷çLÔ ]nÖ &?M)¬M¬\ŽÉr_‡™ªU‚ŠO<Ñô«Ø1‰ˆˆˆˆˆˆˆˆˆˆˆˆhæ0ñHDDDDDDDDDDDDDyc⑈ˆˆˆˆˆˆˆˆˆˆˆˆòÆÄ#å‰G"""""""""""""ÊDDDDDDDDDDDDD”7&‰ˆˆˆˆˆˆˆˆˆˆˆˆ(oL<QÞ˜x$""""""""""""¢¼1ñHDDDDDDDDDDDDDyc⑈ˆˆˆˆˆˆˆˆˆˆˆˆòÆÄ#å‰G"""""""""""""Ê[E&MÓ„¦iÅ.åÉ4Mèº^°eMç1¡iLÓ,Êgç«ÔËÇõ¢|èºÃ0ìÿ ²+å²Íæu¡Â™Ìq1Þt™1%×å•c\(‡òUjÙ©0²¯Œ“WÊe«ä²SJ!ï ˆåMæ¸kÚBÇ©”m&•rÙfóºÌfùĆ|ë“U®u€r(׋ ‰÷ Ç6¥ò%+P4MV誥éììL»744”ôxŒ£UH& ¦¢”ËVÉeŸŒJÓq_ ™œÜq‘-LW˜lÙfZ)—m6¯ËxF+Da*ʵPåãz¯RãÀtá=ñM¥|Ùâq¶ˆD"“~®†¡¡!$“IȲŒP(Tìb•¤Jùjnn†ÇãA2™ÄÐÐ+¶U žû…e"‘š››³¾ïóù ˲St]gL¡’ÀX0Z>uÆ*G•Šy_`¼XÀ8@傱a4Þ' Ù¦R㕇yÅ.@¡„Ãa†I’ (JÖ÷dY†ªªÐ4 ^¯×~_Ó4»©¨ÇãI›?Àï÷#Ã4M(ŠÇ“öy~¿ÊÓ'  ¦•_”[¼‰DªªNj;€×ë…,Ë9½—Ëûã­G®ÛÄ4M„Ãaô÷÷C’$°·ÁDÛÄ0 hšÇcW:TUͺmLÓD(²÷÷dæÌvÎv<Šu4M’$ÁëõÚëšËñ hšÃ0ÒŽeç>r–?—yÅ6ÉwÝ‹i¼íî|²± ˜q@,/Ûq?q`¢÷g"är>Ž Ä2ÄôâxÈÖ K%Æ‚±âÀxóŠýX®q ŸsŸu€ÜÞ/õs²çn湯iš½=3‰e÷÷÷€}¾†Ãá´ó)W¬#L^TÆõÀDçs¡êÀ싳¡ŽÀëʨLt_`¼mäwo@ÙbA¡ã€s{f³Å¨Œ7¹Å‚\·³ó=ÖJ¿ŽÏ=C`êuI’Êþ>Aæ>ªÔë©nwçû¬#”v!ß{†³=0•:ÀTcAE´xlhh°ŸPÑ4-í©´@ `o ñÄš³ …ìéMÓDCCCZeV¼oš&LÓDss3Ün·ýÅ …ÒžŽ™ìôã …Bðù|öÁòzÇçóÙÛÂ0 444ØËï½\ÞŸh=rÝ&â5ñå¯i$I²úñ¶‰a‡Ã¨««³?ËívÚfâuÈ&3o.Æ;MÓD]]ýE‰Dàv»sÞŽN™Cn·;mšææfûXžh^Y÷bo»ùÅ‚bÆ1}¡bA>çúLÅ\Îlj¶‰$Ii΋e¡cÁxq`¢yòŒùœû¬Tι?™s7Û¹ïõzF³Þ4Ÿå¼“Å:Âôáõ@nÊáz`¢ó¹u±¯gS,˜ u^ä¦êݘh›äso;2c³Åªä29Ä‚\·3À:‚S9Ôò¹gL½ŽPî÷ €Ùq=0ÖrSu„|ïÎæüA¾u`’± ØýÃæ«³³3)IRZÅ¢¯oÑ¿ó=Y–“ªª&“ÉTýξÀÅòÉÎÎNûEQ’^¯×þßï÷ÛË›ÊôãôûýiesΫªê¸ã8õ÷÷Úªª&ý~ÿ¸ïM4o®ë‘ë6éííµûY—e9)ËrR’${·MD_ÃÁ`0í}ɇ~8 9444êó'šWô÷>Ñ:F£ÑqGççCCCIUUsêo;ótÍ<–2—ã÷ûíñ&Æ›w¼u/—~À'ÚîùÆ‚bƱ¼±ŽûBʼnޟÉ8Ëù8Q|ŒF£II’ì"ËrÚ• Æ‹ãÍ[®q ŸsŸu€Ê:÷'šw¢s_È6nXN¶éÊ!.ˆ}VÉu^TÖõÀDçóTëÎeÏÆXPéu^TV`¢ûm“|î 8ež…ŠbYc³ÅªŒ7¹Ä‚L¬#TV!Ÿ{†ÉäÔëå~Ÿ@ì“J¾ë•UGÈ÷žálÎLµ0ѺU®²oñ(šÉ;ŸPÍ?#‘Ȩ÷<ý·¦ie¦iÚÍ¥ÅÿÎ'`œóK’4a³ÖÉN?gsÕ\›'g“m[ˆ'øÆ{o¢ys•ë6q>½488ˆÁÁAx½Þ´¬þDÛÄÙ] /½ôØOK8ƒ‰æ«Û…lÆ;åõù|ö“YÑh4¯}+ˆåˆ§4Mƒiš9ÏŸmÝË¥ð‰¶{!bA1ãP˜XϹ>“q@˜è|k›˜¦‰@ UUÑÙÙ‰ÎÎNH’”öN¥Æ‚Ùò9÷Y¨¼s?—y':÷³ïšÌùÅ:Âôáõ@nÊåz@ï|ΧÌÎX0›ãÀëñ¶C)Ö r¹/Ë6ÉçÞ@6…ŠÀøÇ,ë…Ã:BnÊ¥ŽÏ=ÃBÔÊõ>Ø'³éÜwb!7åRGò¹o0Öü•ž?È7ŒµîcÅ‚²ãq¬fñÀÄ?Ã0Òú¥ʱŸêJ¡ª*B¡PZ`òûý…BvóâÉr*EQ ª*|>'5o.Æ;+pD£Q»Ù¾išðz½èììÌ{Û‰nDàÊ÷K+ßùgÒDÛ± 2äzLŠ>Ð{{{í×dYFCCÞõ®w¨ÜX0Ûâ@>ç>Ïûò‘Ïq˜9ïdÏ}1ÏX&Sñgaúðz`vÈ帯à¼Hž±`6Ç€± ÜLt_`ªû%Ÿ{bž±LöfàxÇ,ë…Ã:BeÉçžátÔÊå>0ûÎ}'Öf‡BÓ¼g8µí–©ì²,Ê(‹€!IÒ¸ÁCQ;cìœW×õq+”å*s[ˆBÇ{Od®'z¿PÆ;Xs=Ä «âogÙ;;;aš&"‘ȨS'š7ãìcÅÓUº®ÃívCQ”¼¶e$A8Æàà ¸À¤ž¶ÈwÝ‹i¢íÎX}»¹Ÿë¹Ì;eÊ1éœOçÅTf,˜q Ÿs6÷™Û¨Ìs?—y':÷³ç“óâ`¢ …±–Ã:Âôàõ@îÊázÀYÖÉwãÕœOâζX0ÛãÀX0ÖvJ³NPˆû¢¼S½7M¡â€XÖXÇ,ë…Ã:BîÊ¡ŽOl(D¡ï³óÜwb!wåPGp–5Ÿcr¶å &»îeßÕªÇãIèÒù‚Çã±ï9ÌTUuÔkbðÑr‘ëíõzGm ŸÏggÌÇzo¢y MQȲœöI €,Ë9óÌÁd%IÂÆí×ÄÀÓ¡PhTSàlóNæ –ñŽGiO*˜ôÓÎ}àÜUœô"pˆæÿ¹Ì›mÝÅ6/—§w&Úî• &z&ã€0Õó1s;ç¯äXKkÞlë]q Ÿs¿ÜÏ{±>¹˜-ç~®óŽwîg#Î籉D&Õ5À:Âtâõ@e]S‰ãÕfs,˜ u^TV ÷Ä<Âd¯²)TÆ?f‹Y'oþÌmZб`2Û¹Òã‚X§\”K!ŸØPˆ:B9Þ'ÿWúõÀxXG¨¬:‚ïù8Ûò…¨d®ûD± ì[<*Š¿ßææf(ŠbgÒu]‡,Ëèìì„Û톪ªvÿ¹Î§›‚Á €< ÃH{‚¡”‰¾ÈÅ >žlÛB’$x½^;ƒží½‰æ½½½p»Ýö>1MsRûÄ0 ÔÕÕÙófk†ìñxàñxàóùҖ˼ãïx¬ ‰DPWWEQì§cr¹Pñz½örMÓ´¿Åú„ÃaÔÕÕA–eûXO3Œ7¯(·®ëië^.çA.Û½’cA¡âÀDïO'¦ÃTÏGEQ첊c^Ó™•žJйÄñbA9Æ|Îýr>ïžûùÎ;Ö¹?–`0·Ûm IRZ—L¹`aúðz ò®€©Å‚ñêÙÌ–X0꼨¼:A¾÷€üî Œ¥qÿ˜-f ÜcÁd¶s%ÇQþJ¬#L56äSGçx9Þ'ëRé×ùl÷JŽ•ZGò?g[þ ß:€(÷dbAU2™Ln—aöA-žrÍžÅÆ”eáp†a¤õé-¦°\ú©v®_®]{ˆíŒî‹z¼÷ry:Öm2Ÿ¥iÜn7’ɤÏuæ3ïxÛÙyO¥«r޳¡ŽÀëʨd®Ûd?kºë…ŠÀø± u‚©Ì_XG¨Œ:BæºMå³fë}çr+ùz`<¬#TF!ßó±”î;”ãõ@¶eŒ¥bÙˆìs¿=v»ÝðûýÓšqŸˆ3Pe2m¡—W¬õÈ—óä/ä¼3±ž¥¶-+ cÁÔ–W¬õÈç\Î×XŸÍ8Pžfù_Ì㦔ÎýbŠƆÒ7âÀt,¯Xë·P*Û ŸQé ¦¶¼b­G¾ŠG ÊãÂÔ–W¬õ(&Þ3¬lŒS[^±Ö#ßïøé¸ïÀ8]Ùwµ:g`цh6ZLcõ¡ë4™§ ½¼RÿÜ™6ë9[¶e±0Lmy¥þ¹3‰q <͆s¿˜Ç YƆr0âÀt,¯Ô?·”0”Æ‚©-¯Ô?·”0”Æ…©-¯Ô?w¦ñÜ/ŒS[^©îLbÈ®¢[<Ñ̘SìQùc⑈ˆˆˆˆˆˆˆˆˆˆˆˆòÆÄ#å‰G"""""""""""""ÊDDDDDDDDDDDDD”7&‰ˆˆˆˆˆˆˆˆˆˆˆˆ(oL<QÞæ»3á?øúûû±dÉ’beF>|Ë—//v1fÔÑ£G±páB,X° ØE™Q“Ý×sçÎÅ'>ñ‰b{Æýíßþ-jjjŠ]ŒÅsbö˜ì¾>uêÜn7n¼ñÆb}F±N0{œ>}§NÂÒ¥K‹]”5Ù}}ôèQ|ò“Ÿ„Ëå*vÑgÔ7¿ùM¼þúëÅ.Ƥ•ë¹\®õ‘r-÷Tâß%—\‚~ðƒÅ.úŒJ$øÜç>W–ßå XîÒ.÷l½>xòÉ'F±páÂbeRfÓwT)(×r¼g˜«/|á 8wî\±‹‘—rý¾r*רæTÎñB(D`V$»»»ñö·¿Å.ÊŒêèèÀ]wÝUìb̨H$‚úúz¼ýío/vQfÔd÷õ¾ð…YY‰øáˆ/~ñ‹Å.ÆŒâ91{Lv_?ÿüóÐ4mÖÝX``öxþùç100€;ï¼³ØE™Q“ÝבH»víšuçÄ÷¿ÿ}|ìc+v1&­\Ïår­”k¹§ÿ¾øÅ/κÄã®]»H$Êò{¢\cË]Ú垭ך¦aÅŠeëgÓwT)(×r¼g˜«X,Vöë]®ßWNåÛœÊ9^8×!ß:AI&‰î¸ãlß¾}ÔMŽŽôôô ‘H ©© ííí¨­­wysçÎÅš5kfÝ •êêêY·Î±XlVÞPžì¾îêê*v‘'Tè8X±`¶<'f©ìë#GŽ»Øb 0fã9XÇøl[ïÉîëX,Vì"çd¬X0Õ:Á¢E‹ÊòØ(×s¹\ë#åZn`òño¶^¬^½º,÷o¹Æ–»ôË=¯,XP–±~6}G•Šr-7ïæV'X²dIYî_§rý¾r*çØæT®ñ"sòQ’c<¶µµ!‘HŒz]Žöövtww#£­­mÂåÝxãe%ŸªîîîbaƵ··—ýI=•¸¯  ¾¾¾Ø«5ãxNÌ•º¯Y'(ŒÙxN466¢½½½ØÅ˜q•º¯³Å‚|êåª\÷o¹~G•k¹+5þMÇõA¹*×XÀr³Ü…ÀX`áwË«JŒŒÙU¾.רæTÎñ¢J.ñØÕÕ…ááá¬ïõõõ¡¥¥---hllÄöíÛ100€¾¾¾b›ˆ ˆq€ˆÆ"²Œ ˆfÖ ˆ`, "Æ¢rQR‰Ç„Ãa<øàƒYß‹ÇãiïÚÚZÔ××c×®]Å.:ãŒDd+0ͬÀX@DŒDå¤d‰D÷ß?¼^oÖîÅ“ ™Mm«««1000î²OŸ>mêI4›ÅãqÄb1;v¬ØEÉj:ã;v ±X ñx¼Ø«JTT±X Ï?ÿ]ì¢d5u‚r׎hº$ Äb1ìß¿¿ØE·ŒcÅ‚|ë'OžD,ãõÍzˆÅb8yòd±‹’Õt_ìß¿±X,kwmD³ ¯x}@Ä{†¼gHX×…¨”Lâ1£ºº­­­_ö©S§000À§hÖ•ˆãÇ»(YMg€ãdzAØ7ÛO:Uì¢d5uÞX Ùnxx¸äÓ Dâ‘×4ÛíÚµ«¤Ó}} cuÙF4[ðú€×D¼gÈ{†D€u}Pˆ:Á¼b¯`Upzzz°cÇŽiYþÒ¥Kqçw–ýÀ¤DùjllDcccI>Ý?ÝqV¬XÁÁ}‰` Ö‹ÅJòâšu¢™Q[[‹öövttt»(YMw,X¶lëDZZZ`Ö^ÜxãŒDàõ¯ˆxÏ÷ ‰,---¨­­Í»NP2‰ÇêêjlÛ¶-íõŽŽTWW£»»Û~m```TsêlÍ«‰¨¼0ÀX@D–‰bxÒ™q€¨r±N@Dc1•£’H<¶´´Œz²(‹aÓ¦Mv`ïïÚµ+-XÄb1455{ˆ(OŒD0‘e¢XÀ8@TùX' "€±€ˆˆÊQI$kkkQ[[;êuçMÀ 2===Ø´i\.ºººàr¹°iÓ¦b¯å‰q€ˆÆ"²ä &Ï4Mèºe²,»HDcb€ˆÆ"b *G%‘xÌU{{;¶lÙ‚Í›7Ãår!£½½.—«ØE#¢Â8@DcU^p»ÝÐ4mÔ몪¢··’$ÙÓ@4ͺœ@ €P(„d2i¿fš&Âáð¸Ë&*G• ˆhj ˆˆq€¨t”lâq÷îÝ£^s¹\رc‡=°å† 8ˆ*ãŒDdÉŒ•EA0´ÿ7M>Ÿ>Ÿ½½½S^n(B$A4…ªªMÓ ²l¢™Ä:ŒDÄ8@TêJ6ñ8žÌ>‰höa "€±€ˆ*+H’d']× …òZn8†×ëM[¶ªªðûýðù|ίiZ^]³Š.^EaëJš6• ˆhê ˆˆq€¨øæ»DDDDDD4¶|Çb”$ †aŒzÝãñŒÙe+`µ”¬ªª‚ÛíF]]`š& ªªjT×°Î×4MCUUÂá0êêêàv»QSSƒ@ PìÍIDDDDDDÓˆ‰G"""""¢`š&4M³ĸŒ~¿?¯åz<D"ÔÕÕ!ØÉÁl-,Ã0ÐÙÙ‰d2‰ÁÁA˜¦9éÖ—¡PÑhÉdÁ`¡PhÔX“DDDDDDT9ʲ«U"""""¢J£ë:ÜnwÚk²,çÝ=i0„ªªˆD"ˆD"vòÐãñÀï÷CQ”Qóˆ’â=Y–§4¤sù~¿†a ‰ÀëõÎü&"""""¢iÇDDDDDD㨪ª*øO6ªª"™L¦ýx<477gí*u2TUEgg'Ñßß`0MÓàv»íîS3§W hnnF(‚$IY“”}®“,Ë£ºh%"""""¢ÊÁÄ#Ñ82“…øÉU0€)wO*ºLuR~¿ýýý0MsÌe÷÷÷£··²,§uÕ:™­5óm½IDDDDDD¥‰G"""""¢%Z#N5a'ÆeŒD"£Þo™š¦! Áãñ  ¢¿¿~¿Ì1³µšËq2 cÒ­&‰ˆˆˆˆˆ¨|pŒG"""""¢`šæ¨DèâÔ9&b¶é€ÑÝšVëFUUíåˆiLÓD µlA´”]® ²,Ûkšf/o¬–¡PªªB’$躎p8Ìñ‰ˆˆˆˆˆ*DDDDDD%@×u¸Ýî´×EA4Mk˜m:cváÚÛÛ‹æææQóȲŒÞÞÞ¬-½^/"‘ (Š=Ædgg'Ø­5MƒišPUuÌÄgMM E®ëðz½v÷±DDDDDDTy˜x$"""""*²h4Zé‚Áà¨Äž$IˆF£0 ÃN Ù[Hf~–®ëv7ªŠ¢ØIÊ`0ÇÓ4!IҘݧvvvÂëõN8U&‰ˆˆˆˆˆfY–ÓºJÍÅx‰Â\“ˆL6ÍsŠ]"""""""""""""*L<QA‰±)‰ˆˆˆˆˆhva⑈ˆˆˆˆˆ J’¤ Ç$"""""¢ÊÃÄ#åm^± @DDDDDDÓÏ4Mèºe²,»HDDDDDDTaØâ‘ˆˆˆˆˆ¨ÈÜn7ªªªFý¸Ýn˜¦™6Ûís9@UUUi¯™¦ ŸÏ‡šš{þºººQË&""""""ÊDDDDDD%@QD£Qû§··º®ÃçóåµÜP(„H$‚h4Šd2‰d2‰h4 Ã0ò^6‘»Z%"""""*’$AUÕ´×t]G(Êk¹áp^¯7mÙªªÂï÷ç”xݳ*Š’õ=Ó4G•;sI’ص+Ñ,PÐ}}}èèè@GG ‹!‘H{‰ˆˆˆˆˆ¦LÓ4{|DÃ0 ëzÚߦiÚÓdþkžÉÈ7a'I ÃõºÇãA4s>]×QWW‡††444 ®®Î.»®ëöën·555‡Ãö¼UUU…Böü¢kW¡¹¹ÍÍÍ£>¯ªªjÒÛ‡ˆˆˆˆˆˆJGA‰D[·nE[[ºººÐÕÕèêêÂwÜb¯'Ñ”„B!†H$MÓ‰DÒþ6 Þ&ó÷Xód#–â' Ãï÷çU~ǃH$‚ºº:hš { K§ææf¨ªŠ¡¡! AUU;Y(~ !™LÚ­' Îp8ŒÞÞ^$“Iô÷÷CÓ4;9)Êäc2‰@Q”¬-+‰ˆˆˆˆˆ¨<¤«Õp8Œ]»v¡»»X¿~=à@GG¶lÙ‚ÿøÇp¹\Å^_"""""¢I­ÇKˆ‰i2O&‰¦ëzZ«@Àjí(IR^åƒPUÕN~Š®[=ü~Ö2Š„j0´?ßï÷Ã0 |ýë_‡aL{/‰ # ÚËËVªªÚ‰IÇI’‰DàõzíÏQy*H‹Çžžx½^466¦½^[[‹|‰D»ví*öº•,UU‘L&Ó~<š››³v•:ÙewvvbppýýýƒÐ4 n·;­Õ¡ ë:EIKzʲŒh4j÷h“Ù¬ªªiݤŽ×š°’¢õ¥è†–‰G"""""¢òV°®Vëëë³¾'Z9²»U"""""¢É­ã'N†ai¯)Š¿ßþþ~˜¦9æ²ómi9Ñ S”A´‚$"""""¢òUÄc}}=úúú²¾‹Å`TkH""""""Ÿh8Õ„œiš…BYÇ•o™²,Û­Ër»ÝX³fMZÙMÓFµ‚³»ÕH$Ç33•ˆˆˆˆˆˆ¦MAÆxôz½hkk455°Žñxhll³E$Y‰¼Ìd_(‚$Ii]f›ÈÞµ©[Q,GLcš&À¨e @>ŸvYt]G4ÅßýÝß!Øï…Ãaèºn·ÐÌ•×ëµËÁÄ#Qù+HⱩ© <ð:::ÐÓÓغu+ ¥¥íííÅ^O"""""¢’¦ë:ÜnwÚkŠ¢ ¦µNÌ6$“ɬËíííEssó¨ydYFoooÖ–’$! "ØINÓ4íÄb4…ÛíF$$I0 Á`pÂq3y<„B!ŽíHDDDDDT! ’xŒÅbhllÄSO=ew­ 6l°Çx$"""""¢ì¢ÑhA¦ ƒ£ZJ’„h4 Ã0`†ýúDIB¯× Ç]×XIP‘¤Tƒƒƒö{²,§u³š- š­ìŠ¢Œ™0%"""""¢òS1ÛÚÚì–ŽöÏd’މDmmmX¿~=Ö¯_Í›7c```Ôt¸á†°~ýz´µµ!{Q0ÀX@D–\bãÀäȲ UUíŸ\ˆîYUUÕ2ÒùÞdÆv$ÊëD0ãQ¹)HâÑëõ¢¯¯‰DbÊËØ²e âñ8º»»ÑÝÝÚÚZlÙ²%m™¢+×öövtww#ÛcKQùc "€±€ˆ,ÅÆ¢ÊÇ:ŒDÄ8@Tn ÒÕªËå‚ËåÂwÜM›6emé8Þ8ÀŽ;P__Àê¦õ†n@,CSS ¯¯---hiilß¾ªª¢¯¯Ïž†ˆÊãŒDdÉ%TZp»ÝöXŠÙˆîH«ªªF'=–"Q¹a€ˆÆ"b *GI<ÆãqTWW£ººzJÍ—].Z[[íÀ‘ÍÀÀâñ8í×jkkQ__]»v1x•9Æ" ˆÈ2Q,¨Ä8 IE5>c&¿ßÏnMiV`€ˆÆ"b *GI<Ž×š1µµµö20<<ŒžžÔ××ÛÁbxxÒ‚TWWgíÏ™ˆÊ ãŒDd™(ìÚµ @eÅÓ4í1Ç“-1©ë:$I7!i Ãsù¹,ƒh&±N@Dc1•£‚$…x<޾¾¾´=ódŸHGGb±+¡™­ÛÖÉ:|ø0:::ÐØØ˜w’”¨œõôô ¯¯ûöí+vQÆ5qöíÛ‡­[·¢©©Éîvh6Úºu+†‡‡±nݺbe\ÓY'¨®®Fwww±W‘¨hÐÑÑ}ûöMº¾>Ó¦#:t[·nE}}}Ù]8»ZÕuÍÍÍ0 €ÕR×uøý~;Áhš&š››ín\%IB0„×ëEUU‚Á Âá°½ UUF‹½š4C:::000€C‡»(–s:®}ôQ  ½½}ÜVD•Ž×¼> â=CÞ3$RçX¾u‚‚%·mÛ†žžž´×ºººP[[‹íÛ·ç\‰_ò±X [·n…ËåÊûd_¾|9îºë®’¿©B4ÝD?ç[·n-vQÆ5qÖ¬Yà "XçX,³+륊u¢éS__îînttt»(Ê jkkóZæŠ+J®N I ÃÈ:Σè†5“Ï烪ªv+H·Ûm'…ææf˜¦‰ÁÁAȲŒP(ŸÏg·l ‡Ãèíí…¢(Ðu ‡Ãðz½ÅÞ$4Dâ}¶^¼ï}ï+»‡ˆ¦¯x}@Ä{†¼gHX×…¨Ì)Da:::ÐÓÓƒööv<õÔSؽ{7vïÞîîn¸\.´µµ;<ÕäY´–Ì\ÁlM£ùd"Qùc "€±€ˆ,¹Æ‚‹ðÈ@€že=cú@ÆûLÓ„®ëp»Ý£~À¨éu]·[7J’I’ÐÙÙ Ó4Ó¦Ñ4 ½½½v¢Ñï÷Ããñ <ÔTªªŽJ^ëD0ãQ9*HⱯ¯­­­hmmMkÞÜØØˆíÛ·#›!íëëÖ-[Æý ñä‘ÏEˆÅby?ñLDÅÇ8@DcY&Š3ü?êÈ€€œe9czOÆûY¨ªŠd29ê'[×§‘HdÔ˜Œ™­"E1#Ø?¦iÚ Ê‰Æ”$*Ö ˆ`, "Æ¢rTÄc<³Kqb7ˆkSS‰ºººì×DsNçr[ZZÐÓÓƒD"ÀêÊÕåraÓ¦MÅÞŽD”'Æ" ˆÈ’K,˜Ñ8 füÈ#?*€”e)cz%ãý$iÜ÷­EÇã)üv"* Ö ˆ`, "Æ¢rT1kkkGè‚H8Ž×¤¹¶¶<ð¶mÛ†p8ŒêêjÄãq´¶¶¦õÑÜÞÞŽ-[¶`óæÍp¹\ˆÇãD–ˆŠ‡q€ˆÆ"²ä f{P¡P¦iÚ ÈÌ.RÝ«:“”ápx¤%Q±±N@Dc1•£‚$›ššì'6mÚ„úúz»{ÕŽŽÔ××O8HsKK ÇX%³´ËåÂŽ;ìn[7lØÀÀATAˆ`, "ËD± Òâ€$I0 š¦e}_Q”´d¡ªª$ @0j,HUU!ËrÚ4º®ÃçóÙÿ•2Ö ˆ`, "Æ*âYPY¶þvŒŒ1«$ñØÞÞÀj¾ìlò ¤ÆyÌE¶€‘ÍDIL"*_ŒD0‘%—XP)qÀ4M躷Ûõýh4š6£$IˆF£p»ÝÐ4 ¦ifí>µ··ÍÍͨ©©,ËÐu~¿^¯>Ÿ¯Ø«M4!Ö ˆ`, "ÆšY¦ Œ×IL è:¦¿[ ÇÞ^ë·aâ2.<žñ—[) ’x¬ä£×ëÅ®]»000`‚ñºX%""""""+±˜‹d2iÿ­( ¡ë:$I‚,ˇÃiÓ‹iDKJY–í.XËšl9ˆˆˆˆˆˆ*‘ašx½O—I×S­5 PëïHðù¬äc4š=ùèv[‰É‰>·Ì)Ô‚zzzÐÖÖ†êêj´¶¶¢©© [¶lÁ¶mÛì]‰ˆˆˆˆˆ(¦i¢ªª º®CUU(ŠbÝèl)¨ªjw½JDDDDDDÙ‰ÄãTd^néºõ;‚ÁT"2ÓÌžÌ,GIŸ555ö2Ŷký‰ˆˆˆˆˆ&"Z!†•ìˤë©nN ÃJF"£§—%²lM¤’‰â=¯×Z†®b çåL0h½®ëVËJQžh؈Äd¹*Hâ±¶¶±X,ë{ñx@*IDDDDDDéDÒÑ4MD£Q$“I$“IôööBÓ´¢%ßEA4µz{{¡ë:|>ߤ—‰D`š&dYF$ËU|(B$I[ÿh4 Ã0¦ôyDDDDD4ûd»lÏ=†ÕÅi6¢µ¡hµ¨ªÖß55©"‰¤>GU­D¤aXÉÃPÈú[´h¬V" )þ÷û­éTÕšÇí¶º`¬î[³%>§ºþ™ï;Ÿêx–ã)HⱩ© ]]]èêêB"‘°_ïëëC[[jkkÙÍ*Ñ$IB4…ê¸"õx<èïï‡ady4×4Mhš6nRÒ0Œ¬- ]×íîZ3I’d·¨TU^¯7kâp"š¦ÁãñÀãñd?ÛÝÇ ªªÂï÷Oé󈈈ˆˆhv©ªJ%—OârÈyÙdéÉ=1Ÿ¢X?¡Pªåa$býíì2UQÇJ:ªªÕÒÑí¶þw^~‰y3‰i#kzg6é‰Êɘè™M]·›™Û¦ ’xlooGkk+:::pà 7`ýúõX¿~=ÚÚÚÛ·o/|ɉˆˆˆˆˆ*€H úýþ¬Ý¥J’¯×‹ðÈ㵚¦¡ªª ápØîŠ´¦¦fTbÒ4Í´îJkjjìeTUU! ¡®® ö4¹šì¸‹¦i"‰ØÉKñæzfK€z<D£Ñâì"""""* c<+is&ÐL3Õ²QÌ'Z-ŠKÃHOÀÉrz+FMKµHT”ôä¡×k½æ¼, …Ò»V­E—ª™dÙJ\*Š5½¢X-&+))ZWŽ'óÙT‘Lo[)ŠU~ =™ZHI<VòQÓ4<ðÀhmmEkk+º»»±cÇv³JDDDDD4}äJÏãñŒ9hèl¹ …ìnIƒÁ B¡X€ææf˜¦‰ÁÁA$“Iøý~ø|>{áp½½½H&“èïiió©•â' Ãï÷Oj#‘$I‚Çã¢(eyT+LѲ®®@À~_´º$""""¢Ùk¢Dœh©¨iV"/³å¡H°ev#ƒ¢+ÕP(}ÜFEI%(EëEñ̦¢¤¾ø­ëÖ2$ÉJf»Ôëíµ’“"‰)–/žÏœ(щXeÍL¸ŠÏÒ4«h¶õuv;#zÌ›ÊLxì±Ç°iÓ¦´¤bmm-ZZZ _J"""""¢bÉ|%â #½u£ËÐÙÂÑëMãQ´Z?âÒO$1#+9‰X—w¢%$êbÕ¹,]·¦—ˆ^ïØå—7"áé÷[‹ÄãD AŸÏZ¾óRÑ0¬ÿ­/u={·­†1ú266lÈ_M)ñX[[‹ÚÚZ„Ãa  ©© 6l@SSSþ%""""""*%Î+SÀz„TôMXWl™Óƒé¿fìá¸ò 5Ó4ÇLèeë‚4³ ,ËvRQLŸ­ãXóg£ªê¨nNš››Ó’šã1 º®C–e»;XQ‘(u~ž(—Hž†B!;‰:Ù„'•]O¿”L3•XË6½'QUÓ[ò‰K)Ã=þ¡hí(ËVâH%EÒQU­Ÿpغ —uÎKBÁùü©,[‡Ã©”ãQÕT+D±¾ãqNg©V˜Oê3ë/8ÿ R± "‘Â$§ÔÕªËåBKK ¶oߎ;v ¶¶±X ªªbÛ¶mèëëË¿dDDDDDD¥ Mÿɼbƒq82¯”ƒÁô÷Óf·¦ÍóÐI´Št& 3“pÎÿÍ1®RE·K×\ƒA£“šcݬš¦ ]סë: À$Ivwª†aŒ£RQøý~ô÷÷Ã4Íœ?ˆˆˆˆˆÊ×X—EÎÍÍé B ½•£ ëV".µ.Éœ¯‹V"ñ&’~ârI’Rc(Šä£1ç%`0˜Jø nºé&ÄãqlÞ¼…þ("""""¢Š aÜnwZ·ªš¦ÁívÃ4M»¥¡ ’vì±E‹HUUÓº6Óø|¾1[Cfcš&4MKûinn†$Ii‰ÐlÓišf·nÌÖ­«˜?‰ØcLŠnUË £>ˆˆˆˆˆ*W¶–w†‘wÑÙ’PÓ¬„™HDJRªÛUç˜"a)Z:— ŽÝu*`-+´~û|£»lR-"³½>ñù¢ü¢æXÉGM³~D·²¢ŒýýéŸ)Š¢E#JnŠe ÃjAêóYŸ·{÷’¼÷_^-;::Ð×ׇ¦¦&´··zzz°mÛ6{šúúzlß¾õõõy–ˆˆˆˆˆ¨)Š‚h4Š@ €ººº´÷TUEÿ¨–Š¢ ¦¦Š¢@×ux½Þ´ädoo/š››QSSY–¡ë:ü~?¼^/|Ù®”³Ðun1XHFYåÉ6jq™­{WY–¡(ŠÝšS”7s9²,£··—-‰ˆˆˆˆf gKDÑý(`%ÌD‚Ð9RƒHЩjjÇj hšV EY¶’k¢E¡HÎÉrª5¤3!™ñܧm¼îHsI2fã_RÓÆþlAŒe)ºY GÁã±ÖÕ뵌"9+º¢ë ¥ZCŠò?õTuÖÖ¦“1åÄcGGºººÐÔÔ„ÆÆF@<ǶmÛP__ööv$ Üÿýèèè@www~%%"""""ª`"¡§ëºÝ*Q–e»ÛÔLðz½0M’$Ùݬ:—788h· t.+™LŽZ^4cìÉÌÿÇ2ÑtÁq®šûWÈ’$!Â0Œ´VŸêT¯Þ‰ˆˆˆˆ¨ìˆ`%ã†ÃV2­³ÓjÁ'Z4ªª•dôx¬d`%×ü~kÙº.uŽo¤’›-s•ÙìxÄ¥Ÿ¢XŸ1Vg5’”j]‰XÓe»,-"E7°Îmj{‡úím¹Þ#4N-ñ˜H$ÐÕÕ…ööv´¶¶Ú¯÷ôô¶oߎÚÚZûõ¶¶6 °Õ#Ñ”\ÉqÚrKÜ—l%""""¢ò%’€ã¢Ùªß?zG Õ¨X®ó=瘒”ÞÂQ<ƒ¤º L"Ñ™ÍÅ$.ï ËÖô¢…¢adoEiÖ::Ç‘Ì܆bœË`ÐêJUl¯ø¿ÿ÷ç0ÍÛ°sç0þú¯5øý~¨ª•´ýÉO–àºër/s6Sãq×®]€–––´×ErÑ™tljj`µ†$"""""""""""¢ÙG$ÓÆ#’ÎÿeÙjѧ(V°†¢KVѺQQ¬i=žTRΙœ-#Eë>‘œL"Ƚ#JNfÙ¢{Ù‰>'[Â422˜£ØN‰ÄÀÇ?þzè½xàƒö_úÒïìÞv«œK—žÜÆÈbJ‰ÇX,p¹\£^Ý®fb⑈ˆˆˆˆ(¢KV"""""¢R'’|@ª¥ÞXDL ûîlÁèv§Ã¨(©–^¯õ¾HÚ©q :;G¿æ÷[¯çÚ2Q´Jœ.VP$TÇc•CÇk¯=g¿æóùXÛdÛ¶m8wîI¬Xñ Äb§`AìÜY…«®º ðÑÎKë!GQ€õëå½SJ<Šäb"‘°_ëëëlذ!mZ‘pd7«DDDDDDù“$©ìºO%""""¢ÙIÓÆO6©®RÔX…¡•ˆ-U5½‹VÑÂÑ4Ÿ/Õzq¼$b¶B!+I™kw«^¯Õ}étñºRj€IDATzM C–ÇN<Šdî~ð8>ºš¦Á0 (ŠÃ0`š&¢Ñ(Âá0b±[ñ™ÏlFuõ;ðÜsÏá7ÞÀÚµOák_ûèº}d|ùËk°gÏš¼ÖaJ‰G‘\ ;RÆb|Gѵjæë™ I""""""""""""ªl"¦ª©¤`8l%Ð #Õ:Q×­$b¿•$4Më=Ñ}ª“®[ï)Jª«UÀJ$:[YŽEtÇ*ZN–Ã0 I&úû­íáL@𦠝ðû5œ81`¿vÑEAÓ4ȲŒH$‚P(„'žxCCCek~îsó±víZ45½ ªj`ûöí#Ÿ%Á0 hš†U« iÆKn™RâÑår¡µµ]]]ؼy36oÞŒX,†ÖÖV{šlÛ¶ ]]]hmmÕ-+YÜn7ªªªìñ82TUU!àxØív§ý/„ÃaTUUÙŠºÝn¸E_EDDDDDD3L$öTwª‘ˆ• 4MëG\ ɲ•<é1Ôž?³õŸh¡(ˆ¢5¤x}¬Nb<žÑݱfk 9Ì1—t¶B|è¡Ãp^&†B!„ÃÀwÎÁÎ;qýõïÀ‚¯áK_úàÅ_„¦iiMÓD(äßüÉÏñío_mÛVâߨ‚… Â0 <þøã…BèììÄ?ýÓ›hn®Ék½æMuÆöövÔÖÖÚ]¬¶¶¶¢½½Ý~¿££ÃNF:_'"""""¢ì4Mƒ'óQ^`Ì„d¦p8 ŸÏ‡ÎÎNxýÍ Ó´’€™­ Ãa«;T1Þ¢hõ¨ë©¤¡hí(ºOÍÖ]«h9©ëéc7ŠË©±ºN5ŒT‹HÑ0—’™t]‡’ç`áp^¯RFau]‡aðzsç>‚'6£¦æãeº®cóæ?ÇùóOáë_ÿ:®½öZ\rÉ%صkvïÞ_þò—øÙÏ~†÷¼ç=ö²t]‡¦i8s¦¡Õ:´¾¾çÎÃÁƒñï|§NBGGæÍëÀ³Ï®À?ÿóÔ×kJ-…––tww£»»{Tr±½½»wïfÒ‘ˆˆˆˆˆ('k‚Q×u˜¦9ḎL:Q)‡Ó[0FªÅ¢s\FÑâÐ㱌¢ ÈçIÒøIAIÊÞZÑ0ÆN<ŠÖ“ÑhêsûûÇþŒl½Ì†‘óáã1MÓnÙè|Í4M†p8ŒãÇOúOqþüZ,Y²7ß|3^yåo„ñÖ[oÁívãÎ;ïÄË/¿Œ_þò—$ O<ñn¾ùf{yÎ\#k;¿øâ‹8~ü8î¾ûn|ÿûßÇï~÷;<ôÐC0Œ0®¼r_^ë•Wâb±b±Ò^¯¯¯Ï{£Í²,C’¤Q°‘H$k+H'&‰ˆˆˆˆ¨TˆnT+¹×Ù™j± Z¿Ý¯Šd ÇcµÆÉDçø‹Ù*ÊèÄ£è¶Õc˜B1Û=ñØŽš¦eí5‰À0òÑÚú¨Ä£ø_´RL:.¼p n½õV<ñÄxþùwaÆcáÂ…¸çž{pÇwàðáÃPU~¿‘HK–,±—“º¦4ðþ÷ïÇüùq?~^x!n¹å,^¼{öìA4ÅsÏ}\ð¼ÖkÊ]­  ­­ ñxÜ~­¥¥<ð@Þ›ˆˆˆˆˆ¨Td>à*jZªëñ¤®àõ¦^SÕô'|ÔÅv&ÑêÑ™hŒD"ƒö˜™DÒÑëõ2éHDDDDDEa©Öš–êòÔç³^ëíµ®ƒDWŸ"Ÿ'~‹k&Y¶®§DkGÑj6Séét¼åe]žfÒ¦Ò7ëËÏì®U$ ÀaøÉO~‚÷¾7‚¡¡ßÇÝw/Æ·¿ým¼ðÂjÔÔ\ŠOúÓxÇ;Þêêj€ßï‡,Ëv÷­š¦A’$(Š‚eË:ü>^}õUȲŒ;ï¼þð‡ñáØ.Ë_üÅ_`pp0¯õšr‹ÇŽŽ £µµÝÝÝhjjBOO::: ²Á‰ˆˆˆˆˆf‘xOÕŠnVÇjñ(’ŽápxÔÓ²DDDDDD3!¶Ú ‡­‡/%5~#`ý-’Œ™—-"(Z>ÖüÎË l#Od»LIűFªÐõôrGtS ¡Pn·ápš¦å}í%ºTËñù|0 þþ3 «V­ÂG>ò¨*pòä»ðGô2jk·bþü‹qõÕWÃï÷¬³ EQ ª*dY†ßï‡išðz½Ð4ÍNn®Zu<²;w,Ë:žˆÓÜ}÷Ýv7­S5¥ñx±X <ðZZZؼyó¨.Ws•H$ÐÑÑÇ{ ‰DµµµhooGSSSÚtèééA"‘@SSÚÛÛQ[[›×F ¢ÒÀ8@DcYr‰3Æjè¼Í6ÍXóGQȲŒH$¯×‹p8ŸÍÍÍhnn†ÛíFCC"‘Ȩe+ŠÓ4pýõ×#cß¾}8yò$®¾új9r¡P’$aïÞ娏±¿ûÝR¼ë]‹GµèÌL$F£QûZQYÑË.û`Ù²!ûµé0å®V )‘H ‹áÁDSSÑÞÞŽúúz<öØcöt}}}hiiAKK ±}ûv ¤"*OŒD0‘%—XPÉq@t·*žx¨Å£ ºÊ …Bs„¨XX' "€±€ˆJ]8láX‰DEIµ6t^ƈ—¢X­!ÅX€ÕJ°ZA†Ã©×EÍí¶–9ÙeŒ š4êzªë×ÌùB¡TTUº®Û×eŠ¢ÀëõB–e{ˆ v²Qt£*Ë2 G%MÓ„ªª$ ‘HË–-Ã~ð|ãßÀ+¯¼‚•+WÂëõ:Ê‚ªšiÛt,’$jñxÓM¿ F1J"ñÇÑØØˆúúú´×7lØ€D"°§jkkQ__]»v{ˆ(OŒD0‘e¢XPéq@t· …rN: ^¯ǾØÄØ$™?D¥Šu" ˆˆq ŒuY¡ëV+G Õ’Q×S-Uuô΄O*ùŒý9cñ‰Œh¯×jí¨i@<þs°[©nUEת²,C’¤Q×fÎîVE²2"¢³³½½½èìì„,Ëö˜Îd¨ae×^{-àÎ;ï„iš¸ýöÛ!I^ýu˜¦™6ÇãÁž=k åÖU¬hÕ(¿ýíMp¹ö¤½6J"ñX__îîî´®[‰{ì1;  Ýkuuõ”Ç•$¢ÒÁ8@DcY&г!ˆ ÓñºYKgg'€ô m]×áv»Gý•*Ö ˆ`, "ÆR—™8tæ²Ä¥LæoEI%" Ãêj5[ë=Ñ]k4š[’ €<ïAËpØJˆnÜ8„?û³{줣èqF×u˜¦‰H$¿ßUUáñxFue*IÂá0PWWÇUUíEQÒº:U%­Õ£®ëeµµµiÝ¢ bÜGçë~¿“ÉʲœvM)I@"qeÚøÓa^>3oݺ5ëëëׯõÚîÝ»s^n__:::P[[›ÖŒtª>ŒŽŽ»6ÑlÕÓÓƒ¾¾>ìÛ·¯ØE™P¡ãìÛ·[·nESSZZZнŠDE³uëV cݺuÅ.Ê„¦«NP]]îîîb¯QÑ  ££ûöíËkœö™’ ò}jùСCغu+êëëKæú Mïê& "˜Ñ—Pæ4™ÿ ’$ahhhÂéˆ:::000€C‡»(šŽëƒG}vwmD³¯x}@Ä{†¼g8U#y>hZúøNÎ1uÝšFU­äŸ,[¿‡†¬÷Ò“—’”êŠuþü8€ÚQË…Bðûýöx÷Ο¦iPUápáp'O¶a``®¼2;M444Ø­ u]G$Aoo¯ý ¨aY{¢‘e‘Hÿðÿ€Ï}îs¸í¶ÛÆÝV^¯>Ÿ’$ÁëõÚ]±>òÈ#¸÷Þ{³l7Éd2í5I’Ò¸¹p&.ßóž¥=gã±££±X,ï:Á”µµµhmmÍ냳‰ÇãØ¶mb±Z[[áõzár¹ò^îòåËq×]w•ÅM¢é$ú9ë¡R0]qÖ¬Yà "ÝÝ݈ÅbˆÅbÅ.ʘX' š^â©áŽŽŽbe\Ó V¬XÁ:`'ÞgëõÁûÞ÷¾’yø€¨˜x}Àë"Þ3ä=Ã|ˆ1щGUM£¨ª©®SE—ª¢%£è–up05M¦o~óqæŒgT¯0áp^¯×N6677”%UÃ0 ë:–,y?ü0ÜîµPÅnÑèóùì®QY–³&é$I²»R}ã7¤Z\³ H)å>ŸÏ>ÞÐÛÛ;©žnDQ×S­HÇß?™ z1Fäèujoo/H`ʉÇBWΰeË466BÓ´´¦Ó™Óe>‰È'‰*ãŒDdÉ%0U6Ö ˆ`, "ÆR&Z:jš•8TÕôdXfëEñžs,GÁ4º: £‘ ­í$¶ojy¨išTÔuÝnùè÷ûáóùì–Œb¼FEQ ëÛ-5E±“„Š¢ Ãï÷ç´îbºH$]×áñx ëºÝÂP$1½^¯ý7Ü{ï½x衇°jÕ*|êSŸšR—§ªš½ui6ΣÛ]‡‡~»wO_7«@ÇxŒÅbèêêBWW×”²¡mmmØ´i¶oßž5pˆ'2»UŠÅbc"*/ŒD0‘e¼XÀ8@4;°N@Dc1”:ÓLµ\Ì5–IŒçX ;‘0­Ÿyæ§`¿.8»TÕ4 Š¢Ø­Åôb¬ÇÔ¸†²øt&ýÄ<“íÂWŒ )æ‹®XE™eY†®ëX¸p!N:…úúzx½ÞQc;æb¬nm'òŽwTã׿¾-mhŽé׉Dáp===H$iï¹\.´´´äÔä9‹!£±±qTÒ²ººÚ~*¡¥¥===Ø´i\.ºººàr¹°iÓ¦iÝHD4ýˆ`, "K.±€q€¨²±N@Dc1C$dÒºný8órªjMkš@4š{2L’€`КO×S¿£QÀç‹@’$øý~„ÃaÔÖþ~ûÛW!I’Ä ðx<ˆD"PÅnùèì²T$ôô‘,£h¸sg††€ùó¥%E—«ò$3zªªÚÉÆææfûÿP(„h4І†øý~¨ªj¿‡'ý9NÙöO)™râ1‘H`Ë–-@KK íc"‘°[@Æb1|õ«_7ù(F[[Û¨÷íþnÛÛÛ±eËlÞ¼.— ñxíííëË™ˆŠ‡q€ˆÆ"²ä ˆ*ëD0ã@1èz*±%‚’dµjŒDR‰GðZÞ©*n÷ènRU5{·ªŠb-KÓ€ÎÎÔç|êS'ì®S­Ï7qá…"ï‚ßo}°¦i…Bv÷©b|FUUGu[êìúTü½ví›X¶ÌÄÂ…÷AQîu”Iɹ›Ug+ÆH$‚H$ǃÁÁAhšfw½*Ë2úûûÓÊ%IdYžR«ÎíWʦœxìèè@<GwwwÖ˜›ššÐÔÔ„¶¶6tttàsYííí9ér¹°cÇ;Ølذƒ¨B0ÀX@D–\bãQec€ˆÆ"b˜iÎnS+èv[ Dg²KÓ€æfkzUµÆwÌF’²'É$Éj©iV2µ^?tè$IB$iš# È?°ÇvÔu‘H~¿†a ³³ÓNRfvY*º6Õu’$Á4MȲŒyóžÁÐPGŽÜ5ª\¹v{ I:;;!I‚Á 4MƒÏçƒ,Ë0 ÃNbfkÙ¨ªj^-KÝ”ñx===hmmÍštÑÒÒ‚®®®‚>]0ÞgÑìÀ8@Dc1‘…±€ˆÆ"bÈ—èöTqÌé%•XÌÖ€OQ²·xôû­é%)ý3†††ì.VuÇŒ¢5£èRÕëõÚ‰;ѽª'£ÿQ‘]°jšY–ñÎwÀo áÈŠ2¹ñSë¥ Ûÿtvv¢··Š¢  *Oæü•œxœ3•™âñ8«ß䉈i2v%"""""""""""¢ÒáLúýÀÐ5#JŠä¤Ç“J8ŽÕX0ÛëŠbµx ¬e¬^} CCCvk@‘xôûýðx<$Én½˜™´S%kkEÑ%ªw¤XI’pðàjìÝ;€6éîN#‘€hã5ƒAD"»Ìã-»Ò[Ÿ555eôËX ½£GÆÂ…ûí¢9R`0I’ìD^¶£H,:‰ä^¿äS«V­ áÆ¯5HŠ„¢S8¶ËÔßß·Û MÓFaEÉZŽldYfâ1“h®,Z>ŽGLÃ&ÎDDDDDDDDDDDD¥EäEÒÑÙ²q¬ü˜¢¤Z;ŽÓ«¨M$çB¡À€D"Ã0H|7Þ8wdÙŠÝZ1õyJÚo§±~ýýývkH‘¸|ÿûÐØøþ´i5M³“¢º®#Àçó!@Ó4¨ªŠ`0EQ044dO”Q2ÑÊwAc›RâqÆ €žžž §Óˆyˆˆˆˆˆˆˆˆˆˆˆˆ¨ø #Õ½ª3™^¯Õݪߟž€ŒDÒ[9:—1MÓì.H­ ßxã {<Ä .H呜ÉI'e¢¦•ÎîNÅgìÜYøÂÞ?jzÃ0ÒºOÕ4 ‘Hº®cpp0-±ØÜÜ Ã0F¡ªjέ‹NÐŒÒK<º\.´´´ «« }}}cN××ׇ®®.´´´ÀårMóÖ""""""""""""¢\Fz Gg^/J%C!+)æ¬Ä$`Ó:—id|†õ¿HÐi#¨ªÀðð^¨ªŠ––½¸êª«ìy4MËy,Ç\ˆ$äýÑFÜ|óÏGÖׄ¦i0M¡P^¯áp†aÀëõbppп1sü~?4Mƒaå7f£ ÀÈwAÙM)ñííí¨¯¯G[[ÚÚÚÐÓÓƒX,†X,†žžûõúúz´··gãQV"§iVKFEIu¹êìzÕ0¬ä£i¦ÎÖ‘áp@ÀNæ9†a'æTUµ“}«WŸ‚i† ª*Þ|s-n¹eQÚ|™É¼|º3õdMexôÑkí2»Ýn»…£$IˆD"èïï·çÓu~¿TÂSUÕ´ñ#ËŠ«Åc8ße7oª3º\.|õ«_E8FOOϨ–.— ­­­ðz½líHDDDDDDDDDDDTbÄøŽºžê.U×­qݧƒ@ Þ-«“aÐuº®jèl½¨( dY†¦iøå/UÔÔ¸í÷Ä窪j·è¤ªê”×S’$躎††$“I{y½½½0Mn·ƒƒƒ£># Ž¹Ì²M:vÂJ:êy.k SN<Vr±½½íííˆÅbiï566ÎÌF""""""""""""¢IÓu« $Y­=žT‹FÑâQU­¤c0h%£ÑôÖŽÖ´&LÓ„že°GÓ4ÓZ z<ø|>½X³æ:Ör'êE5ßq}>_Ú2€Ýý«¢($iÊ]¹– VkÇ^”^W«™Ó~ˆˆˆˆˆˆˆˆˆˆˆˆ¨4£_óx€ÎÎT’Ñjqhý½zõ iÉÀ@øã?~n7‰DPWW·Û ÕâÑ rpvµ X­;;;qå• Üxãò‘׬ϞN¢»U]× …à÷ûáõzgGÂ1“ Ó’|,Xâq,X¿~ýt eaš@8œJ0 ‘ˆõ;ü~«¤Ûm%çæÏº®áÆw°ZFcþücvËFMÓÒºVÝ­jšfõèìjUðxŠüàK/½Àê&uÁ‚㨩٠xðä“›íå*Š’µ‹U1æcf7«NÎn] M×u†UU …ìñÅ8”Š¢ä=fdYÒˆ]¥8þ. &‰ˆˆˆˆˆˆˆˆˆˆˆ*P(”ú[Q¬îTûû­Öšfµbݦ* ìâ³ÏvÃX¿þY %¡(À—0íyDKFñæßÙºY¼Þü¦iÂçó!‰ÀçóA×u477Û]«úý~øý~»u£ªªi]ÃÎ:ÎD£:òS`L<U ‘Ô]jʲH8Z¿##}¬š¦‰P(„Ph'ŽiD(Â…Þ @Ëu‹@æÀ€"Ñ(Œ¢¥£a0MsJ]§Ê²ƒAx<˜¦‰††ƒA¨ªŠ††» ¹šÌ´AÓ¬ÞÑÙkºÜìž3µMÎ&“yÜ”ÆxÀÖ­[100PìÍEDDDDDDDDDDDD#tÝjÌfV#7'•htr6ü‹D"0MÁ`ÕÕïE(9Rc¿¯( <hh¨»…¡,ËPUÕ?QtÁ*|¹¶DÌÆ0 x½^;y©ë:ü~?<$IBoooy&ðZÎðv~$‹~¤Z5^«ûGúâ qèî»óþ¸)%‡‡‡‹Å0<<œöúúõëÑÑÑ1C[Šˆˆˆˆˆˆˆˆˆˆˆˆ„pØJ2†ÃV.I’¬’4ºMUMu…ªiE$I¸êª« ëÀ¢Eo·»8•e‹-‚3[–Ù’Q´x˲œWRP×uÔÕÕA’$ÔÕÕ!‰ÀívÃãñŒY†²à›ÁÏ3ŒTŸ»ç+é ZÍbÿ· œ2€ù…KÞN)ñHDDDDDDDDDDDD¥E$ #5¬Ÿa@j\ÇL’$Ù‰G˜?>T¸üòôn7/¿<‰•+÷š¼äßT‘HÄîúµ¿¿^¯½½½$ ƒƒƒyµ , anFžËÊ…®[™gMVŒì+Y¶~ªM`¥xƒ‰G"""""""""""¢YËíN»Ñ0Ó¼^`pÐJ@*ŠÕ° °rO™œ ÇÌâí·ŸK{í®»bÆoŒZ†èZU]®:[@æ¾Nn„B!477#ÛËUUÍÍÍv ͲÐ @Õúq:ˆÌ³ ËÖkk3úÛ•eàù`A?zÞ4­MM³†íSëoŸÏJ8 ÖoÑÒ1³a¢iš#¯+i ÈÎN«{Ö .Ø6½¢(ÐuÝž^ðz½iÓƒÁ‘òM~CI’ÐÙÙ9ª¥¤ÏQͨ²`³¨(D5°ºN5ÍTv9± ¯×Ê<›¦u,Ê’Ö4HNæCÇÆDDDDDDDDDDDDeÆ™ƒóù¬nU³ñz­|T$’Þ¼N´É<‘x ‡S-)-UUµ‚¹Œ­¨ªê¤…‘H$í3²-oR4ÍJÊ ¦ ÔÕYÏD§Q`%ýLsì~pE¹Ò›·:…BÖ4n·õ°¦uî#I²/¬n^3ËQ@L<•‘§Òu+Qhš€ß?öô÷Ýw>Ÿ/í5]סª*$I3©çw,T’$;á8ã,š¦i·Â,˜pØJÚiš•|3 à;šÕ¯ÅM@ª\> ¦&=AêXï뺵Î×T22±þIHMKÏLVâ1ŒÑ­,%ƒ ´éóêjuëÖ­£^ëêêBWWר×wïÞ]˜Íb†aå–<+×ä÷gÃQ¸ä’¯Ã4M躎H$Y–aš¦=£³£×k-3[£FǃP(T°õ‡Ã0 ÃN8ŠnZ BU­.H}¾ÔÆñx€‡4@W­–~¬V€Å x& |¨øº×J67§å´6ˆµš–Ê6›¦µƒ<žTËFðÆk …¬hš£ÀØ]»ú`µ„Ü€¼M)ñX[[‹ÖÖÖéÜÜDDDDDDDDDDDD”…È+y½VÎÉ;Aò,Û¿#‘LÓ„,ËöøŒÎá°•ËÊ–È”$ ^¯·`-‘dšhí8¥–”¦iµ ‡­ ¬3 ëõ¦´VørˆÂJ:bŒÅÔÊX¿Çè*Öðÿ³wïñqÕuâÿ_½Ñ mÚ“K)¡å„¶`Ë­'Ü ‚à¹t½€ßIUPé õ·kuí:³úwÝí®¢»ºÜoq—dV] 8£\¡æ„†RJ-¡´šÓ¦…Ж’ßŸùœ™É=™I&“¼Ÿ}ä‘t.g>çöžÏù¼Ïçó1QÉÄiÜ‚†“éÁ«åéÄcv1‘ÈôÞt]µn¦©ÖÛ4ÕOO Ü *áÙ™‰êýYÌÄãÚµkóÿt!„B!„B!„BÑ/zÄPŸ zÎ1i®ëâ8–eÇ …B¸®K*•ò{:vjÕé%!gö•Xë‡ì^“y÷rŒÅTÃáLÖ4{ÂËì„–{=ˆ¡z:Öµy¯N¦†Ñ÷¹¢ þ½VZðXVÙ†GÍZ5›N°f÷xìœyîmÜ]£‡Ç°`×6/Þœ×f‘s<^wÝu444tûܺuë8ï¼óX²d kÖ¬¡¥¥¥ØÅB ‰BX „PzŠ„;¤N „‰B‰z$ÎtçE CýôÔÛ±ªª ÏóˆÇãƒA?¹hYÁtb®»¹ Wì•ëºÄb1\×-Ì\‘¡ÔÖª„_kknÒ±3Ë‚»šÕßzÕ 5Ï£Nö¾òÐæ@GzçY–JúUÿÕ©g¦ãôœÖëöÝÝ5[ÕÓ³3ð`öfsþÃççµòN<ÖÕÕ±aÃÿïÕ«WwûÓ_wÞy'MMMÝ>·nÝ:êêêX»v-ëׯ§¥¥…5kÖä» BˆF–HdFrM$! çX q@ˆ±CêBX „8*åyêw(¤rNµµÝ‰ê8ŽãPUUE<Ƕí.‰Çžz.šfßù³þò<@ @ee%±XŒªª**++¹ûö»©Ö†¶@ÇQ= µ1ò)°4RØÄcö6uÕh—='f"'ZpqÖëLÔ|“Ç[™¦™Nµ³úúÂg‡M ;?¿“·§¾×¢xlkkãºë®ãÖ[oeË–-´´´ÐÐÐÀÒ¥K)++£¡¡ôk>Ⱥº:–,Yºuëz|͆ Xµj«V­bÅŠÜqÇ455ù‰O!Di“8 D÷zUA?W] ••½QJ$! ïX q@ˆÑOêBX „8-•‰³¶jjTÏÇž:÷¹®‹eY„B!lÛ& aY†aø¿{âÔ4Ö‰®7ÙsIš¦I0¤¶¶– ×_•@d s¨ªRó9ƒÝg\*vuà+–Û§ðtÔóTY«ª2½xàhjjbíÚµ,]º´Ø«+DÑÈõ\!m†#¿ÍPwž³,•ËÒSÿ…»¥Ôu]jjjº$µpx€C›RMM ©Tª×!] ¢n=‰ÅT‚Q÷l¬¯/̰ˆÀK.P¯zÿ5¢~Ýåa]W%MS}~v/ÃP`Àí\¶P(÷1ÓTÝUã=”«ÕóPŠ}íôYÖ­[GCCCÞu‚AõxÔ“²öç$¼úê«ikkëqÂ×á0gÎÖ®]+ bÌ[µjëׯgÁ‚Å.JQ,X°€õëר „YGÕ!âñ½§s-F²†˜ð<•pŒÅ`Ü8õãeÝg^ôüùžçK'ÿ¯ÿú¯\vÙeüñüU‹O× ¤QAŒuK—.eýúõ\sÍ5Å.JQÌ;—õë×Ëõóôwâܹs‹]”¢¸æškX¿~½$ا¿çÌ™Sì¢ ;¹>B‘6Ñßf¨§¬¯W7žƒª ({¤Ïxº+’n(ò<ÏŸÓ1›QˆáIûJ¥°m›ÚÚÚ‡sU…Aõ6¬éæ9×U^5YOjâÉý&¼œÕÀæôPPŸo*a˜]ŽdRõdìi¬[P;k ÛÛ@ ?Ûß ƒI¯o7t-ß:Á :‰XVV–ó¸PÙôkúsgBQ ñ¸ªÀ9ŽªÏ”—gx‰Dÿ—ÓßÄc  ê,‘H÷¯Çs—¥GhlTu•ìJ¥NBºé?ûì!ž~z‡?܆ëºD"‘H×u‰Åb|ç;ßáÕW_-ö¦B!„B!„}èœ÷2Í®£n% <Ï#‘HL&Ó¯‚a:{áº.ŽãÇýäc‚¨žwÝ u꺪Ͳ —lÌ6Ë„ƒY lF”ÃUëtƒamm&¨wÆP$p­ô6Ìœ“#È ºË²îù¨UTTtéά_S¨;»K`Ê݉BŒ-D¾t2Ñu¡²RÕ!âqUŸÑc僽߰Ô×í=Yé8™1ø‰ÌkÙ,K=—Hè¤ë?ÞÜ o½µÏóˆD"ttÔrÝu›Ò½«X½ú,–/¿™@@%6‰ñxÜŸ¼»ººšX,ÆW¿úU-ZTì]‘‰B‰BX „P$!FkÐÓvÎáééµT*E,Ã4MlÛÆ¶íaI<ê›ÞõOMMßÛ±_ôze' C­\4:4Ã~Û†Ü9ŽÛðH"3ŒªV[[ع•< ÙËóõ¨¤lFUëV•àBƒJ<.[¶ Pc?÷E¿¦·1˜ûC'4;OÛÐÐ÷²…¥Aâ€(×U½ ++U0R= Õpµµj¤è_"{ØSÝK1•"«Ç¡úJ©zK*¥>«¶63Cee¦ž£“––¥^»téÛTUU‘J¥¨©©áŸx†|ä~*++I$Ô×ÏâïþîÄãqÎ<ó~Î>ûßé9ÃI$þ$âÑhÛ¶ …BœwÞyÅÞƒ&±@!q@ „ŠÄ!ÄhŽ55ª}¨»Žƒ¶i»J¥¢b±Vº‡`½nb®ëâº.¡PÛ¶‰F£ûs7ŒLrí"nÉš{È0T]o=&ó–G3ËO&áþz8œn ÔÂáÁõLèzyÞBÍ7Y=4«ÞÛP«…2¨ÄcYY7ß|3wÞyg¯ÉǺº:î¼óNV­ZU|ÕªUÔÕÕÑÖÖÀwÞIYYW_}õÐn%!J˜ç å€ÐÃOâ€È‡ã¨‰¸Ãa•ø³,õ·a¨ŸÎuÛÎ$!{:•jjr‡š×‰ÌÄßãÆ©Ä¢žoZ3 U†PHõ|Ôcó›¦ú*ãÆýÏóÄãqzè!.ü¡Pˆù—?sÚi«øÌg>C4åôÓçrá…WQî½·çž{Çqƒ¸.xžI0Å4k9xpb±wG^$!$!@bB‘X „q •RíI=åß²s²æåѽ‡c.GPsKF£QLÓ$S]]Ý¿Ï6Qsº.<€#NÏ pCáô¬.£¦©ÊÓl€1ÄÝû#ŒJÊÖä» n¤ò_D_Ýê …hjjâÖ[oeÆ ,]ºÔ¿³ ¡¡††šššXºt)k×®-Ha×®]Ë7ÞÈu×]GYY---¬]»¶Ë\“BˆŒH$Òÿní%@â€(ÏËôBŒDT²¯¿#4è^Š*hÛ™J]$¢’„–¥*¶­þvÒu$ÇÉ$C¡Ü»Ð²éòضÃ×¾6›ºº…œqÆ÷ùùÏ߇ëZÄb·N8 ñƒüœO}ê4,+JU•zÿòå³…ÂDüÃL::Zyà…ƒALÓ$‘PCsD£ª¼³g/¡ºú±bïžA“X „8 „‰BEbb4ÆDBµ)õ6Åa$!âyÁ`D"Ñû¼Š/£šWR';C¡Pÿ‡w mé^óMØŸT‰ÈbŠ¡ÊB%"‡‚EïC­’.CÕ3ÒJ—§„ :ñXVVÆúõëý^ ÜyçþóÜ|ó̓J:nÛ¶­Çϼ÷Þ{ihhÔ¯¥8„ÈW*•Â4Í^ƒ¹ã88Žãßqâº.,vÑû$q@ôFßüÔùæ)×U BÏS3ÓTU§‡&¨­U÷Wö©e*ÙØØ¨wñ¸Jâ餢þl|¬­U¿£QõÞx<ŽeYX–…ã8X–…çyTUUa®ërâ‰+oÒÖö0ÕÕ?L÷Tts*m·Ývååj®GøÌ.§ã@yy%û÷oòÉOþ?@½.UÛ¦¶>ó™ÉÅÞý"±@ÝljBŒ-R'B€Ä!ÄØ‰zNǾrˆ‰D‚`0èxå8Î'#‘¶m“J¥H¥R466úÏ…Òð’–ÊÔ¶Uï>‡!Ÿ°W*ùjQs-šjµ£e©eȇE y³vóÍ7sóÍ7ÓÒÒBKK  ’ŽC9v²îY)Ähàyžßõ<•JùI†¾Äb1"éîM¡PÈÇ»¾¾ÞÇTâ1“H$üÄž}ûнÚy“806E"™d¢žѲÔO,–ù(”™:Î$ݬV\L33Ô*¨¤^,¦~ÂáLÓuá‡?< LFl‘}{žG$!cY@À?÷MÓ$ ú=Ÿ~zçž{555Äb1jkksn.ÐÉV½þž—yL÷ªL¥–óì³ßgÒ¤2}útÿõ¦©ÊJÁk¯M)öî,‰B‰BX „P$!FKÐ#w57÷üÇqp]ÇqH¥RD£Q¢Ñè—Íqb±ÍÍÍþ(]ýZ!=çP<žîUV½ õœŠz¾G¡ïùìá3lT™R¨D¨=Deéon8ˆJ<Ö ’…úì!Þ¾›ài¨“B”ªìÄbg®ëúc`ƒJ&†Ñ%ñXSSã?®“ˆžçù ‰@ €eY†A"‘𮫢u<Ç4Mq]—|àÅÞ,b”s]õcšÝ/:±X&ñª×žif†3íÜ›1Ê ƒ/G,¦“yjYž—™R3MزerÎÿõüª†a‹Åð<ÇqH$477“H$…B91âÜs¦×¯–h4ÚmüÐ=,;¯›.çé§ßÇ /ü/ Þ œ¨í” ¼á†]…Ù1B!„B!„¢ "ÕP·CõFwDÑmÊz¤­¡àº.®ëRSSCcc#±XŒ@ @mmmÿzX¦R¹C…éiv{]¨N?6ÔùÓDús:÷ÿ1Ó?6™äcý—¥/ATI£@ÛÅ¢tBˆîÅãñïüˆÇã~rBwM×I†H$â'S©žç‹Å°,‹p8œ“œÔ>‘HøË±m×u1MÏóü2˜¦Éûßÿþbo1Jé!P««ñ{þ…ÙºD—‘H¨J–îYhêïÚZõ£Ç¸‡Þ+a® ••ª×â`©”Zd†Uí<ϵ^¶a¸ƒ&†¡n°m›`0H<' ùIGÝ»±¯»ÂzºiÁ²2Û@Ï[©×7ƒO¬<.»ìALóoµ?:ܾ}3·Q„B!„B!DÁ9Žº‘>™ì:ÅPæ5ŽßEy Ř ñxÇq‡Ã~{U0ì¢3ͽ£ß4!ÒÍëlÔãCxìÏ𥵨„ßHþ5‰ê Z.W>‰Ã™žCdüðm!ÆÇqüÄ¢þ¿N•T‹v»v¤ïáN- Õ;Òës‰ýg0ðD¦•þq ´m†8‘*‰G!ò¤‰ZvC­¨ÿ®©©¡ººšqãÆQ^^îÁíº.ápØï¹¨“ŽÉd’d2‰eYƒÁ>¿@²Ÿ×C;ö§W•ƒ¥{zžJƒêïhT7ª^£E"]ë6ž55ꧺZ%››Õãõõêý©”Zö@é9{K<Æb1b±®ßØú¦ãß˧?ýi¶l™Ìý÷ßO<÷_ï8@€@ À‚ßfÞ¼'¸ï¾Wik;ŸúúzR©‘HÄ¿ë̶í.s6†®§ƒ]ç­4 X±B ûzæ™GÒåÌl í†v1uêÛy•C!„B!„BŽm«ÞŽ=u$ÔÉ¾ŽŽš››ýQµú•xŒÇaÜ8Õˆ7Àäc ðGçü¶ìn¹®ê™0nÝ¿ÆCõ&ìN•\x~t`úÛ<—Hÿã³³é¡Vc¨a`+‰ µ*ÄH‰DˆÅb$“I<Ïó{Né;?²{<êD`2™ôƒ´ëºÄb1\×õÁ`êêj€AÉmÛ6ápØO¦HÒQšÎ3Uõ•D"37´m«¡P³‡þ̾±)‘Èô¼ÓÉDÓÌôàËž;±¾^=¨å æPÖeꎾ1@yœ=Dq*•Âqjkk9zôIV­ZŹ禈Dþ Ã0ü„~MM ¦ibš&/½TÍâÅopþù³¸þúÓÓIA5¶¾žÇ5™L ô½Óónw·]tbóÖ[Oô÷CçÄíWìãÅ%ñ(„B!„B1¸nfj¡ž$‰.êêÑðzå8ê®ÿh4Ó˜w½S=‹çy¸®‹eYÔÖÖæ´U†Ñý𮎣ól;Ó3¡ÛòôRÖ *1—†ªi[ÏñØŸ`•ÓuNÈÁ~¶3ÈeÙ¨¡V«Q ÄÁô\ X^HâQˆAÒIC˲ôpçFvG Û^‹ÙC¢ê×èÉ€{äy=ò}çw¾ÃÂ… !&•J Ù„ÂblJ$TŲ2ó/Ú¶:u]#»Îѹþfæ’…Ô²‚ÁL­»¹kkÕë2bDçÏÌ]‡DÎy«+IñxܯÔ9 …xãMœtÒ_‰\D8Æu]‰„ÿÚd2‰aD"§™Ó³s¥l(ôÔÔ4MâqUß3Í®!ãî»çÓÑqö–M!„B!„BôO*¥ÚÞzjëÑ7ËwîiدŽ'ñ¸jÈË~m"¡²Ï<Ï#‹ ©ªª"’H$hll̼H'2G5Þ錩e©åõ•A5é=©h¢}C?ßc_¢¨DaUº\ƒl£,=­ƒÚFa†t¾ÆÁÄ£Ý~/Æêêj,ËJ'ÔŒ·¶m …°,‹d2Éo~ö3Þwø0ñtPv]Ó4sŽã¨¤£çeÆ›L÷†rG%'ÒÝÁB¡—=ùdn‚Qg,K½?ÊýRˆÇÁ0XXSµµØÁ ½ì2.ý·Ët9 …zsRˆ^èQÂauèUVª Qv£3}øê0 …T]$Íí%ÙùõÙB!õºÁäï<ÏËk>‰DZmÓ4ýˆŽãPSS“.ƒá‘‰Dxã ›6à÷\ ÔÔÔ …r–Ÿ=G6 ®×r!X–•¶{wwÌtÒÛìÚU”â !„B!„Bˆ´@@µÝô6]P<÷{;ö{ =a¤a¨¹Î,«Ë«zT?=Š_sssÎÿL¯Æ`P Û¹A¯¯¤#¨„bo½  ¨Ê-?*Á—OOCûÿœ‘AÔöÓî6{å’Ä£ižç‘H$üùSé‰éR©TºçPÜŸ›­:ÀI'# Ãà3{ö@,F´±‘x<î'µ–gŸeú“Ob…Ù@lÛ‹7Ž›.Ô…€šn¹æ&56æ&-KõH$3¹[6=פa¨×ƒ|ï{ßcn]úÑíE‹}‹ˆ(%z~EP½³óhý¹™ÊóTïÆÎIF}X÷wÞÆ¾òwžçù7 †A<÷‰­­­~ÂQ-Ë"‘Hä {jY–×–î©lš&•••Ìšõ¸ä’©|ãÙë& å )¡×M÷-&ÝkÚ437®u·­_}unq *„B!„B1†é¾&¡ú»»ü çyÔÔÔøaúÅu¡ºº÷Þ‡–å7üeO=téU™ss½î–ÙÓýÑWâTr¯(G%ý 9ìê`ÑôûªÒe 1¸ž†ñôºç;#“E&áXŽJFÚéßE&‰G1úé^‚è$#àÏñ¦çj³,ËO8Ú¶Mmm­ ¶©Ü6e ?ÈO;‘PY˜¬Œv:p'Ë®½– Èܲ¢ƒr(Ä;W\Á‚™3ýÿãºïyð裹·¸X–z_O]'Qt’qÜ8vtÀ¹çfÊ8ÀIƒÅؤ‡uH$ToF}Øt>úSÏÑïñ<•¸,DB.{UÏóˆD"~²0‰à8Ž??cMM ‘H„T*E}}=¦iúïéiÒmÃ0üçÔЪ¿jˆÅ²“‹v7ïËüŒzþÌî†é8餷™=ûÍbQ!„B!„bLrÕŽ”Lª64ÏËL™“-‘HäŒÜÕ§TJ%m»÷¼tG—@ àFsF÷Âóü‘û|…êØÒß^ƒµ¨žnúïBˆàó;—¥–ÌЫ .ùXèAÒ’¨Þ5¨9$£½”+ß„g?HâQŒz/ýŸÿÃÑo}‹ï?þ¸ßJ¿¨ïÔˆF£~’‘êj?ñD¾œJaÛv&ÐÆbê¶“Pˆÿu]ÜTJ=¨œ¸:±Ñ~Ç$‡Î9‡OÄ»r|7…‹Åüž‹ÕÔÔðôŽOÿ„Ãa’É$ÍÍÍ$ƒA’¡¡X,ÓƒÉ4¹ø·¿%ä8Dc±LÀÕc†Ã~ÂÒ²,õíМDÙ0 Çaã%—P <|å•üïóÏ÷Ø»*'¹Y(zPpPw8än0‚N_ýØÅX«zHöïx\Õ#jk —HÓÓ—ö¤»ó×q*++‰ÇãTWW“J¥p]×O0& à  ÑÚÚJss3áp˜ÆÆFÿFõÙj%:Ÿý{Ñ0 ¾öµ ¬žŒB!„B!„¢t¹®jVîœÌnr‡šš¿ ¬[‘Hn¶Ò¶Õf½$]×Å0 Âá0¿úóŸsÚÒºˆÇU¡ª«»fE‡“…J¨ÄY"¿ÅD=*±*Éô6,&3].‹L¯ÌìÝæ¡æ„b’x%KÉX,F  ‰P^^Nee%ßøØßsÿWÿ™x<ÎÝó¿É)O=E=КL‡±M£²jj2ÝÎÓ"Dÿ¹Ï1gΪ tƒA•‘1M?Q8iÒõxÖ7‚eYþ˜Øó.þVzøÕÎ_ž—‰ÕýM‚è÷eÿî–î§]‰ç±pß¾bï>QD®«ê$55™ütc#´¶ªß…îkš½'1«««ýùAUª¡PˆÚÚZR©¡Pˆúúz’és¸µµ•ÚÚZÂé‰&;'5Ø·ó¼#+îyrïR {ˆ !„B!„BˆâŠÇUÇÄÞ¾s]—@@uñ«¯¯ï¾ãŠëªÞˆÕÕ¹÷Òü)Š€Þ;Äx^&‘ÙØXØ»ò-TÒn°ï©&¿$_’ wj¢z`Ö£’¢5éŸÞÚîC韡d¢† ££ãÒå2(ì\™=Ä£(9žç‘H$¨ªª¢ªªÊ¿ãÃqB¡¿¨¨àí{çÐúÝ?`Û6ÏNú$/9ž sæd‚®iªLBk+´¶·j‰D2=¾âf”MŸý,äÞí â8ðŸÿùyÀäýï¯ É-_0Ä0 b±sæ|`0H2™ÌæT°X ,ËfË–]WÔMÿt¢¿˜jjü¹» 3ãw;ä&m›,önÃ(;I¨¤c"‘éÙ e’jC‘\ëik×uqÇÞ!‰ƒA¢Ñ¨?ÌCçÄ}{ Û¶ÝåÜ 2Jçy¤R)¿R™Hû¶+!„B!„Bˆ±-‘è;‡W]]mÛþtBÝŠDú݃@÷ž¬¯¯÷oäï"•‚ªªÌÐe†‘™?©Ð†1Ô ƒ&7Ñ7˜ÁývhT•mD Hÿt×~Ÿ`Xz*Á饷—î9 +dŽG1¬Üt"­§8åyà=Û‚ytîìó0ω—Κè!UõœnÙÉF?)‰À³Ïò7g<À½ïìäGáëøÂÞÃJ,.¹Üà:2“ôv˜@¥ÊEÚ¶zÌqT‚D [$‹1aÂù8ŽŠ»¦©âìöíeÌŸÿ%V®T¯FÕºéyv?ûÙqüñ1wîé=n ýyjõ¦uÚP¯„à9`üŒÒñÞÝ¥ÊສLÝväÊNÒ8d‚h xÙ”Äã¡Ï·@@‰¨c¦¹yx{ïéÏÒI°X,†eY~, bYžç U¯ä¬»× V?D 4áõHj5‘HH$°m»Ï±ý=Ïó+©$ "‘ˆJÄÊpËB!„B!„EÑ[oG×u‰Ç㸮K2™ìy!®«Úw’É^ú\×¥ªªŠúúz ›‘÷G%A5~Ùvñærˆ ™N;UéÿG–¤Z¯L2ÃÆÉíFµÓ§(LoËþÒsbÓŸ= »W¢ ²{Þ™f¦‡•Žy†¡zèéÑÃa•  Z®z±eñío¿Á׿>‡Ÿþ2Û_0X~ܯøØ_ý–O<ü0žæøã÷òú±'ØvÖYœ³`î¿'ñ»™8ŽZ^MÂ&¶q"ÓøÕ¯¾ƒmOgûvÓ4q]¨¬T±S'íjks{3yžJ&†…aüýß—ù‰ÉTJõ³Îgëßf%T2óì†Ã‹O}ýùdéK$Ô(ú½ñx&–ûS3¦À½boC4•_ƒàû z5¤¾ ÆúÌhª‘ˆúL½ƒÁÌòâ߆º«ÁƒÄ}Ük²{æ%ÌËžRŒ*: ^]­rОååêïÆÆ¡ÛíŽãø=u/FP½†S©žçaÁ`Ð>5•J {í•8¡ˆ»Sð9TA¯{UUU‘L&1 Ïóð<Ó4szˆ& Âá0†aຮ?Ìóy³góýŸýŒÓï»Ðw¾ã'qƒ¦I `õG?ÊO~˜¹ŸûœpB±7B!„B!Ę‘J©vÜîš»ôôC¦iR[[Û{[’iªÞ½ÐS•E£QlÛî~*"ËRËyÖ…¿Ø*™—B%Ìt¢l(èžxùÐ܆Q=+ætù‡z(Óþ”M'—ã¨Añt¹L†%ù×­aú\I<ŠAqÝLrQß¡޵µ*€&êÎHD%< C%=ô͆g/—9ð?NobêÔ£l:rox+/ï¹”¯ýê+üþìsøà„ÏÓÞ>…ç¿q=–—Îr&j¿ŠQ™ ÔŽasÔçNŸ>PŸ}×]cÛKI¥ÔkëëURF'³F¦Gáç?ÿ¾ýmH^F24À¹UÅ^ÿsLï2Ý‘Èù}:!› Hy™á¶uOGÝÛÒ²2Ã_ƒuÀÙ ©ç áBðfp[Á Aðiˆ«T^‘uê³uxÓÛBû˜“ÀŽ7jžó‹pÊïS£†7‘ÈÌÕ¨ÏÚšÜ!U )‰øC {Y㺃AlÛö+8ÝõÐhBn¤Ò“rëuI¥R†á'Mkjjü^Š555X–åËœ-ûóR¦R)LÓ$‹ùÉÅP(D4õ{>îÚ²…3b1ªöìQËòÅÔg†*ŸNàú{ܸjL³Ý*Õ0T/ôž$“`–]ÇCsÀ¸øb¦7bè0ÿ)3·®iªm¥{E†Ãàý'„Î/ âw5¾ ¬G¡:Ö9PRåŒÅT9uOLÇ€tOùÐWU¢2‘€X*ch2„Ö{©z­Þ7Ædàv•°tßw8[!‘£̵zè‚^pèîX•J©s0íz®é›ÒsMû½-K{ú\ð¼Â'õœ±XÌŸKQ÷\´û9$C©$]×Í¦×u©¯¯Çó<¿w§ã8ƒA¿¢eY~OP×uI¥RX–Åû¶nåÚ³ÏæÂO~’h4J*•bÙÝwãüìgŒ?í4Â?þ1555ƒAê æ3oó÷ìá‘d’„ëòþSNáû¯½†1y2µÀ½û÷ãyÍz¸ Ûfr,Æe—]Fzaê—ë²jÇö×ÔÐ:uª?^ÿ?··³9îþ€0 … ,à¹çž+öæBäIÏ}­‡Ðq²æpݶí(--¢®¶‚Œÿ9Þ}÷bÎ9g3gîãÏþn-öj!„B!ĨæyªÝ·»¤c"‘ ‰ …roÒ×®«‰“Én“ŽŽãø7ÃëiŽúÕV§Gë멽ÜB eC%ðlTrRÏc8Rd’¨:ª“éõÎ9Ç I<Žb:™¨{ê¤X$¢b–ê3ÍôšŠFsç:tõúŽõX8œYŽîå‡ë²é¡‡ðâq®|æ–ESÓÞ~û2>rÚA®›“–,h”eG×…t'œ¬v2@õÚò'^MOºjŸ¯Ê£Ÿ×CƒêqÓT ÇQIï,ƒø$H,N÷újCu¢‚L7 Ë‚Ð*à«dÆaަ»øw{˜áÌ—õõªn#ØóÀ™¦ž‹ÅTL£°!d x1°ÞL0Sø{U4Èä ô&ÓÉÕšÀ½¬hz9é®ïîi; Æ^hœ åªå™Ÿ#Ý#óä“‹}tоÄãêXJ&Õ±®çyÖæF£™^¡!¸[F'S©”_yÑèڶMsssNÀR “¥ú·ž3QgªƒA,Ëòç¦Ô“yëm0ûé§Ù³gûÓŸæVââq¬¬nã—Þx#Ï~zfHÕª*ÜýûÕé»Ó‚–…çyœþüóL¾í6H¥8–.ƒ¯§I½- B!fýÇ0 §“¤±Ù³{ž¡<ËŒ3нK„½Ð±JÇÇq°,‹'ŸÜÆ£>‹ªŒ¨ ÂÂ… ™8ñ ¼ûn×^»3ÞaõêI¥ªYtbß»ö›ürÿ.ýàDöîùsÂzžÇ’%¿fÆŒÏ{u…B!„bTJ¥2C¬&“];ñD"b±Ñh”pw=l[µótJ8zžG,ó§1ª¯¯Ç4Í~B¨v徨6ñ0ª]<…j‹Ö=Ýôß#5‘§“¤ATU_Jë¶~1$$ñXâtrQß1™!««ÓC~z™aRMS%ét ËNhufÛ* úÏy¦ëðÆ=›xxÑ"ÿŽú‹î»¼ðowüò—Yú¡ÑxùåÄb.Ñh+«¶?Ôó ¤#­eu3¡®‡º A3ÀJ‚=¼v°RøͶ3C•fÏÑèŒk:„,H³Œí¨¤a#j¼gP3‚llŒCÍ1°N'>}ºdìÂ×dz§@lk& jšéõ«:È$;=µûc`SË3VAãßwÝ‘HzhÛ‹Àº8ëɘZŽq¿Š‰#*÷n„P¢{Õ¶²P˸ñÆa:@Å€éù:#u”>/ôy®ÏëP¨p GÝ mÛ¶_ÙÑt.cYÖˆ5•JåT¦ô0¦úw$Á²,‰„ÿ:}×W¶P(D(Âu]Nî9>ò':¤‡3Õ¬êêLwSσ+rw‚¾ƒ£¾\—‹,‹‹²[c#þD³YÛ1gîË`õͺMNQ___ì]#„è¾ ÔCUw¦“:éxñÅŸ¢|_·±?e¿Ù9™æ–S™:uüà/¹ï¾ëøèGïçÿý¿¸öÚù<÷Ü7¸ì²òïüÉd9ü»?rù#_á⎣öìˉã†aÐÞÞ^ìÍ"„B!„£V$’î{cví¬XSSC"‘ ±±Ëê&sgÝw‘D%,u/ÇD"‘Û¾Ô_!Tûtè$¨¶ñª!Zwбү±²–Û[2²Xsš¨dF‡=“Äc Ó=­Ãa•Xô<‹LS%©‚A•ô 3CvĽ÷>Âçð™²o³kÞ™¿gm&ðŸÇŽ7M¿GÐ/Î<““ï¾˲¸(ëýÁ é'C»Ð÷ÖaJO^«ƒŸ­þ6—€9•(ôPs.ÖCüŒLÀ² ± â ÁN÷Ò¬©ë2wb$ÈŒï¬'œÕeÚª’wî›YÛ-¢> 'ýž°Z†ÑÞQˆ>îât߃ €ûÔöÅT—®<ýe:Õ«2Á{¡¦ÜwÓïÓÅ23Iàœ/*K½ ú³ù4¨ùjzˆMýÝ”Rë÷;Né‹9ZE"¹ó§êä¢fÐÛ<Ð¥ç …BTWW“J¥0 Ã0H&“»;j˜Äãq¿\®ëhll¤ººšúúzÉd’p(ĺ/|p8Œaþ\‹†¾#T0ò+u†ã`¥Çq>^ß ¡ƒª¦+z¶M·Á­½ û3x¾J­'ª£Nê´<ÏcÛƒÛ8å”S8øçƒœóÙsøÆw`ÛGŽáÜsÏå¹ç^娱Ïò曕=úQæÍû +WNæ'?9 kÑóüóóï% +ÛÎ'¾~úÖç¸è¢/¿¼™[o½™+RXÖ‰rB¡Óù×UÃ5ÛÇÙ°¦yӧªc¢ê1´µµ{“ !„B!Ĩ¤;©t7-£N:&“I•ŸÓs.%}ΦçqŒF£þô>ƒAµ¹´·bçŽaTû³‹ºÞL¡’‘&jÀìvxý>ýÚb‘æ³!%‰ÇNw®Ñ½tG$=§¡iªE0ØÝ\‹ªm½ººï„E*•¢|ófæß}7_VÆî©SI¥làš'NfÚòSxé#¡ãÔS ƒ„ûѰm<€ `¹I·t=éù$àMê3Àú|ºí¾•¬‹ªß‡É \vÕÓQ÷ÜÔsB™»2’éß±ôc&*(.‚Ä쬡eu] ëoPIÌïCè0 ÞC`¼ö&0¢¹CÁúõv'œYf`+¸¶‹eeæë벿³”Jõ;çfˆ¶þp/¿øÅkú܇bèÅã™^ŽzÎÒîÎç|è!S;Ûg†?a2™ÄuÝÁÝ•'Ýs1 I¥RƒAâñ¸Ÿ}â®»xâ®»0M“oìc|äË_¦#=tmm-Kþs:ÒÝ‚ÝýûaÓ&ø§Ò‰8ÙÕ ÃÎ2ËÊ¿¹;ÙICIî 1f¤R)vüd/-|‰P(D"‘ð{VëŠj.ÅGQ•—3Îæ¤“&±hÑv6Üι‡frùŒMœÖ~ß¼ã$à6Ê7ïç[¿ÉéSnå˜û ¯€#GŽðÉOâÅÇʕ˹á†É\úÑ“¹Ûò¸ë–|ê½Cb,‡åÕËU$jƒ‘¢¹Ë§Cæ®S]I êP!`N±·°B!„BŒ>z„Â.Ó2:Ýt‰;3IǪªÌ0~½´Íyž‡ëºÄb1ÿ†ûü Y •5 Ë^!rÛÃãd†vM¢ÚþC¯ç£R’xaGýè9=O%ÌÂáL›¹ad†KÕ±¥»6pÃP½üüQ‡=?ü!³fÍâÀÓOóò¸q\ôè£é÷›T=ÊÿmiáæÏçî÷½•ß;‘[Ã/òÉsC\7ã+*IX‹ "•¨¬(*HÔâ÷ÞóÅÁþpEú9}‡}0ý¾êôOu„ž¯0H¦Gd7ǽQ2]¸=2Á+ÝÀf–É!è‘ ýíä’éáM¿?»«ø§À½_틜ϳÉ$MÓ¬e§ª¤¨õØo©ž–ž—•«°èººc§§¾M{¸Ýƒçy˜¦ƒaØ~’FO8¬{¥R)LÓäúë/¢¼|3±X^zηD"iš¸®‹eY´¶þ øVa^Ño®«~âqu~77çv–Ë'§åº.ñôƒI:Ú¶í÷ú ‡Ã˜¦é÷Êé2qõ¬³ëçªçUÔÇn(ä7?û«fÏæºæf.zî9Nù‡À±,lÛæ¹ûîcÙG>ÂÅ55ØmmpÉ%þ²ýÞ™S¦¨ßõõ]7¢ž U÷dìœ`4Œw c[€Ì÷µjjjHÖ'ÙÒ¾…ÛçßÎã?{œ—½ýüéèC<»q ö…g¿ò©–¯sÞ `KÛ ÊŽ{ƒ£“þÂÞ½ 9th5×?­m[˜YÄå=Ž ÷¼è –¿'Äÿ™ó="q0ù$‡êã`òt8óËð$ªÞ±>õßYã«ëc®•@ÔCÓ§Põ,›ôÍT.ü4]ù2õPdêa?wá1—e;æÃŠboi!„B!„=b1u¼mgu^t]žüë¿æÂGeÏäÉ4ïÞi«­Í4úw»<5—#¨¶¾ÆÆÆÂt¨{êë×ì6þìÑ¥MeÔ’Äã‘H¨Ø¢§Ó77D£éaT›[I†7ã=Ñ„qÒTõ&3”»l8 <ë`Ô׳pá;–¤¦æ^>{Ï=þpZͳf±áw¨­­Ít6•‚@€ºürë3<§Åæ”z2ã9ë;Tƒ—›~]}ÖãAÒ]øèz×C-PEæŽ{PI==&tï=Ê»ô„ô_Se±/ËÕ–••‹°;ýŽæ.Ëþ_0Ê»¹ÁÄ!3a.¨Àœ£?™R¶øΕ;±°0 üyœt’0‹Åüñ·ubPÑL}{*g¾p&?®þ1–eÇI&“TWWçüv; õhšfzˆÅ?ªÇƒîÕæº.Ñh×u1M“½{÷ਕH¨c°ª*“ ¯¯ï:ÔÂ@¥R)^F}êãɲ,ÿ<ïŽUÀd›ã8œ6~<[¶láµ)Sü‹^,†eYlè!λðBœº:¿Öeš&n,ùËLöí£ü#sÏ%zî¹þ0tt¨àwß%Ô¶{Æt+J˜Kf©$—<Ý <ûÿ»w¿ÍŽ;xì±ûxú O3ížiÜ:ùVÜžâg|eÉ;¼¼ý Ö?|ªØÍ7+ó¯{ßÏk«Û˜U{2p²ZØþûÒ7mUáŸÿü.6nü'êwüϳ£ªú娠¿ÞõÅXöõd*•þ"Ý‹d’¶:&=àÖüÎ)˜k‰Aü5ɼ`®Éå6â|±§±ñ…B!„B D,¦š®,+«9Êqxëâ‹9üî»Üwýõ¼ïöÛs;d7Bë˳x1Ã5øì‚Ïr¬ìs=Wµ¥g·§ç£—‚ºEæXÕ$ñX$ñ¸JBD£*ÙèºPÿ‘_ÿ&ÁÓ·ÂÖ`|k!î µòsð.F»œcåÛfÏý÷Óòô!Îza5Î\‡¿¹ùfvìøŽû/>ùÉ yõoÖsÑéqä…#ØÇP£ƒºí+Xé^A¡V:i;ݬ€¾cT¢1† *qh§—WOÏ  ¹ÓczNG=Œj-ý§ƒV¨‚ð'sŸÖCÓúŸÝy,jTÏB=$éßüÍ«XÖ™€ê­USSC²6 Õ(‰Døì埥bj¿üÖ@$¢þŽÅb466úó<9Žƒëº¸®ëϧjx4Ó4ýyö®ûþu\Çuéý¯²¢­éñrõïúôÑ~Ì+§_#s¿ ¿ô®ÇuÕ¹ÞØ¨z8æ³+âñ8©TÊ?^=Ïó‡Ö ‡ÃC:?ãÆŸÿœ;~û[¢Ñ¨ÌžüwÇ{ZZ°öïàž¹s¹}ëVÿ?4içþîwXsæÀÌ™„ëëÁ¶3å …zFÂg]‡H¢â¨ï9=dÈðP\R\·ï˜§{‚Ûv&Ÿ¦™ff=ôüÃ魯¹ƒ3ÞaÑ¢6/>ȃNgܸß3kV×ñåOûåil.ßÌ;ÍMǾf6²›ÉœÁ!–ÐÊ8Þ¥™SfÏ`×;g0©}%Ì}„ûZnÃnú6üiÊ»Ü>îijOjçÕCI.ŠNà–¿†CgBí¯çaðVfEgÁ Ž ‡œ›¤ à›ßœFuuyNÙrnjíëX2M/³ã¡¾D–„[ ¸ ;}D£]æ£í˜ö6Ó·M—^B!„B‘§x\%³ïw‡X,Æü ¸aãF.ë®@ uјž¬ýâv¼ìAØ ¨o¬'l‡™S>'3liÕ®]•þ¿i¯»‘õ²5=ªžsQîÕC@ùÐÃ{ꓵ‡“ÔóÀùüO0¦´O™Äw­ \£zÊÕþ ˜¯>€yßc0Ý€ÍÃî-°:©@5ð‘z¸ x÷?Þå©”ŸtH¥RxŽG3Í<6÷1.m¹•ŸÝr-[̧ÚM·bîJJyI¯Cz¹JR}¦ öiýع Æ*ùfàË Ó{Ñéß[ôüJºgŸiš¼ú7¯r©}©?S,K÷8LùÉ’«']ͶÄ6Êšš’É$@€d2É¿ý[5'Ÿ%FURÑ„G/|” £Â®²Œ2¦\9¥Û ~,™îÝ¥ë¤açy˜Š1¿ž‰„ªh8Nf®ÐÚÚæ©Õ:i­Ž¡PÈ:UÿîæÍ™I$õ Ù«'Oañ‰góÆ®7¸ræLÎl;‰7.ç¬7ÿBâ#paÝ{°[–ñ¯ü5gž{)õ6óíërÁ¦pïW®bÍ''`¸ ê³Âj´Óè ÝÅ*Ã0üº@¿TW«¬¤ÎLêÛ˂Ֆªß-$wT‡nüÛíÿÆŠ%’uBˆ’—ýÕ©¯«]2S“èÞõš¾‰*8€ÏB!D®ê;ÕP׿55jPËp!å’ðÙÒBÐ òâ‹/rÙe—ñè¿>ÊëÝį>ôg.œ±„/ÜÊõ'¿Æ›/ÇŒ3Xôé6‚Xˆi‚a¨„¤ª;¤3‡‘‚¶Ô4ù–ùQªÃãÔÕc4Å#žVcÿî$q5¾vc¯O¥ÔgëI¼£Q•dL—‡TªKÅ~É™B¡xdæ×§£®Ÿi¸~Iý8Ö_©Ó×ï­½ìOezrCÖ #»Ó?óÀ¼8Ó›[_Vø—+›å™÷¥þB5¯ö¨—g€Uætp¦¤—s R¦—q"0BWCüÁôêÙúIÖóoƒy ؇×^{o±÷ÈW„Üù~õ Rvú1‡LbR'$õhE™ú!;™©ÿÖË·zY–¾‰2#e'K-Ôõ€‡º>Ú)è…BˆÁK‘Iô%€ZpOS—qµÿôö7>SÜ;g5ÇŽ …ˆšÑÌwaõÝ™þÙ}×n¦üÕ¿Íû;ÿólÛ&ìÇEÕé·þ;g¤ÄnÞ׌CªäëÖ­£®®Ž¶¶6®ºê*Ö®]KEEÅð@÷ ãê8‚ýÕ¯žÓÂ*{ ët° îã+åà^­Lö‰­+Ú.¸žêͤ{8½4ó%þaã?àáûO5' îe7á?'`.0!„’3œJ¦a]Ç¥¾.ž³Û²²”±SOŽì¡HõïX,†mÛ~oCýÓ3I$þœ†ÑhÔ¿S£ººšÚÚZbé¹ßtâ1 ú½»²“‘®ëúëžL&ýÏîç¨Ó½ ô°¤ê]Å0Œ.½%yQ|êQ èJ'\ 6¬/@ü7`Œó,ˆ¾ æ!T/ã&à½d¶Ò•Š=ó÷°ÿ~^Þÿ2¶?ï¿þkÊ6]Îkó^ãàŒƒ|ü´Eœuì1¦ïÞÆ¸Cûa/o„is3Ã!|ÔTWËÓÇèÿ±ÙÚ°•YKgñô§iinaÖMc\Ó~>´c#o¸‡û?¶ÀœÕshìx•™±ßÿþ÷ùÑ~Äý÷ßÏU_¸Šó#ãàÔ˜5™ͦç`Õ úôÒ ú5Ùñ¥£›íÚ¹’ÓÝÐʽ,C'~uc‰¾ÉB7*’þ]™þ»‘LãŠn| e­Ÿ®ô‰’1d±@÷v]øƒ ÷7§'hÐ7òÄãð_ x°¢~RÉy¼ÿóRpþœqàtGUã®õ~¨ù>œz\ÿ³èNÓ,:fµRf¼ÁÔÙïðËà €U‹àà3¯@ê!Ið‹‹¸ûöû1 “Ý»wÓ:«•‹gŸÆì?¼†yÒx~}oœŸ®¼­÷oå£Ë—óòæwËqüÝ·þ ëRõ}ôSO¢êÛ,‹gÿëYvßµ›û￟5+øïÿMMu oÿúm–œº„¶?·qô›G1 Ûµ0Í À~&ÇÜc,¶sÐ96NæÌÊ39ôçCLŸ>©æTî2ï겫.åRp}ì%ˆG¸öCêñ{ÂáN½¼OPWŽãO°›SЭÿz߃™! õãéa¢ý1_5ÇQËŽFIg63Ï¥‡¯§*=þM0¨–£é ³iªåèžâ®«ºÎ×Öæ76÷PôkPß5ú†"Ýà¯o¦Ñ#ŒèÝè’þ(»§Qç’²o¸‰¦ŸÏ ÄŸkÜM¤Ó2²?'ûÎg#ëw+0ŽÌ÷¶nô×χÀ{œ;€é`ýÜksï¹0~¤n¤tv«ÀœñÚÌý.¼ ¼O§WáKÀ÷;U/ÎЫæ@ø_!öéLÞÁìôûÀ¸ì#Ûœ»ÊÑAä éM´ ¨ËÝlÆéª„Àýêÿõ0®:ëy ´ Ü_AâˆýÅzb;r?§# t}0ƒÈ­àÎóçÆŸoä·‘ßúÿ× 6D³mÃ00M“Ðÿ„ü^v¡ÎW Š½Í¥ØIvò03iœP(D*•Šðÿ…Býß±XŒp8Œçy]æ-4M3g],˲,?yX[[ë'{¢ïêèßõUÕ˜¿ê£«ºßVݵyÛ=ü=À¡dóÒ]¹t¨Ôª‘B?®“£ÙÃKg7ìê»Öt«ŸnT‰£3²öc¬U‰D‚¯.ø*wr'?úÑøç/|•ÿºù+<ŸøçÔ”Ñôr©TŠÉ+&3oU•Óxõ¢0¡­7O…+?õ)½F Ã`¾{œßsøí·™7oÉÖúܤšëª„["AhðÞ׸éSj¨ÕsœsÀq0Sÿõ—ÄÒsHgßµ™Ja¦Çеb1l]785ýš@VwgÏSɹì^€®›{2Aê²zžJüy^ÏóÉÖö2©´iª±r²—ßùyÓTâê ³oZÒÉC=7c¶ú*pµµj=eö^$¤:ýÝ@Ý]#·¾yErfú5ºGQgç·ºy]úûÆÙ£’|¦ T‚»ŒM`”AüPÖ{^H÷d›.V ¸Ë ñÓÁ;Ü•Nn%‡!úõôß­éÕö ÷Rõ>ûÁZ±ìFù$ïJU‚ð#à,W#;˜¦J2ZÛÀþ®{$ïçiHS§§eÑNHª¡3€Zp:%[½›Á˜•þÏÅ`„s7‘ióÒ„OUÓ™Zqµ|ÏK?~%„Ó§«i‚÷÷`§“)‡¢¢bº:¥õܦK,¶€“NšÊk¯µ3o^;gÎÍÊóÎůsð'ð›7'2wÁ›”o.g×Ê]¤¦%™þN˜ñÒ;ü·ý2[Ê·pÜìã8ôÒ!vΟ@k`z^uæ_5MS6qð ÊRüeãgø¿§NãÃW= À¹sžå¼ãúë?“ãžþþîÌWyôÂG9ôÈÖ•Õ³eñdÚ§L¡b÷Qž¹jÞL¸äí©Ìœ7“'Zþ‡+Úvq¨D‰ð•ç0ï=óH–Ïà‚×ÅÌ é è˜tÊþôÐjôkàï)EEk'}‚®‡Q 7Ý#Q'ù4Ýs½–Ì .™ÆJ€Œ’ÉÐ÷ÑA^UFVïÚo‡ÀªK'Ðy¼àm¦ƒ{?ð˜ Õ¬‚è=éÎùú O€]îÃà6ƒ9 Ìç!q¹J¼ñ¶ZõdGæk=U÷Ø8¤·Iµ:ŸÍË!ñ/@DwAä¥tù?Þ_ Î6Hí»‚×@¬ ÜÝøIÅŽ ŒKÿ¼jjU<ÕwØ U0ö¤Ú¦ÉA@lL¿/±ºôH6sÀ˜ ±MÀ¦Ì6mü¾ –=ÕÛÀ:ÜsB:Fhc„? ±ÇÁy¬CÀrˆÞ‰ûÁA˜N98Bݬ0Ü…Ú ìo†z€'Ô/³ Ü7 ÑÖQðþJ¤A;ðPÞiàîólµ_¹Ø îÛà•ƒµì?<çÃ)‰X J’nó4M33úYÖã†aày¦iæü_Ó5²GbÓ,Ëò§Ê‡nëì{³]¯½öÚpoâ‚)xȹÌþ¶^P_0ÞÅÅ[vÕ·Ù\ºìg>×?´ wB¿ž¸_¼§’?\ùø_ü©8ÓÁ ZÂn˜ššÂá0ÍÍÍ9Ç–£AI%7lØÀªU«XµJ5ŽßqÇض͆ ¸êª«z|ßÁƒyë­·Ôôð"ú.AáÂ= (OÁ± Xé†]hˆÃæ^åå8ÓÏÃ=: i¨‹õÚZ°Ž>Iè`“g1S.^Ä&•þ×ó<Ú~˜ ^y…={öà¯Í›ÇÓä¸tE4 qá¡CPQé!‚õù©ùšN0Äb1êëëI$ضM"‘ðc‰î™Û]ÝîΉ±P™ñÏ ƒLƒtß “Ý“R7(kFÖäÞ­ÓgßqÞihLÉLø]KfÈîìϵÉ4pw7´löâ?Ç‚·§¾Í‘ûPö±²Ìºv×CÆPŸ³ü¤å4|¹a˜÷Láä]'x؃«#p8å6„ƒ™ä@™•I4ÒáÒ“Ä·¶vðÿÐJmí©T–aÙ› x§<ÉWvüëÈ!~Øî‘¡Á©¦IÇ„ ¬8c;oßIhCÈ?·OÜ2™¶gžarº÷ÿ×½Áõ¯\ÃWn|??¼ýv¾wÅ t„ëp÷ï'‘îñ0÷±ÇøÒž=Ì|â ¦nT-dnm-¡PÓ4©©®‚ª*~ðGÕiðW–?Ç0 nˆD˜«u¶ ŸúTæ¢Óó gžþÛu¡¹9“<3ŒÜñ5¤¨~̲rp:ÑYvLê®~¾ù°ók²ç@ÌÒÖÖÆÔÝ­ºC‘ÈÓC¤ê1q»ûŒÎ£'ôg™ƒ,«Ô úW'à‚<‚‰.´§¿{C™^0—ûža¸"ê' ¼ ßÄñžð»]Lì»>Mœ‹°Sª«ÃÙ1;³Œ;Ë ×-'X ÛL ¶<çcÂo¿€yÍé$`í„ Á}ÒÂÃÀÀØüüëgT¯5PÈg€59³ ËRɺënçàÁƒ”ŸiX¥Ö3° &¶·s‚ L¢jåDæÍkgéîT§åÍ›73ý¬³H5µù‡pùþý¬Z´ŸU‹ÔÿçïÙÃsoŸNêÉYþkî½êþïø0öÌÜÃî]SùùÏg3qâD c"‰ÜôÒKèaµµñØÜ¹D"óý²ÿçÏð¡7ßdÒ¤ILœ8‘P¬5w øHæ~=êceÖ÷¯Iz‹¬·ÄÈÍ%GÉ­&”“[H’{Õ÷Lçï/¦½½©S§rÎo🯼¢¬×Ô-\Èùóç³k×.Ê'Là=ÜÃ5‡3ãwh™4‰.ÚÍ›Gßdîësq]—Øþý˜ííLŸ>C‡±sÎ>=cKN\ÂÎGwÒz4Éß¶îâ½O¼ÃĉikkãØxô™×¸ì²Ëذo3ë8Ì“&MâØ±cL›6_¨ŠÉó&³s÷N>>çTÇᢋ.âOú ®9‰ÆÆ×ù·mÿÖ÷93Bå ²‡…ÜÊÙÈfËžv¡óMh^7ï3 õ`ð_ÀV0ÛÁ©?€Ùv%Ä_¦÷][I× ƒÁô½65ðæ›oò ÇãyªÊdî“©¬Ì-j8œ²7¥¾Bm;3¢7¨XQ[ հʳ>ç0pا^c‡Á€·/½Ù²æ›fÿ~ØÝ æÁ1x£ì Žs?Æ$Õäämõ8ù#üüO1{ö‡xþù]ÌÜ÷&¹ílÝu"矶ƒZvÑ~Õª»aË»ùÄòç™ÜÚÊ Õç•sÆå&³ŸÞÁe—…ûøoøÿfµ1wÉ\Z[[™ÒÑÊwÊ'SSc²9©'_â¶å/±à­]¼øæé|g󦼯Ÿ/;ðej™©ðÈ…2Ï»<û‡%˜U Vz;¾Œù#SþÛœmû“Ÿž†m«ºwìßáÇ'¼Ä¢¶¶Ì Ú ]»RÿÌNwˆ98þ2\\&³‚ùì¡yLe7Í´R•j)ûsæÍ›ÇÁƒ©9TƒAÅô Þù.[vmÁĤy´“d/2þœœ7þ¼œõßýün:ÄäãOd/ÇóÒ›¿ãâã/fvÅy¼vòoY޺ܿ¡iÆŒ잺›w-d6ã™\qãg`GãxÆGGGóçϧììM´ýù|ÊnçÍ7æ²tÒ¦8ÌNo³'íàücßçË•wоïÁ1ø\\+Ó£ÿÒ nåâG–oœÅE3ß$މDØ¿â2Z^Á‰+m Ö‚ÿw#óBóˆD"„Ãaªªªhllô{567v¼ÓÑp-8ÚösÚ"ư’I<655ÑÒÒŠ+üÇ***Xºt)[¶lé5xlݺ•s^;•Ô ?ÁÚ{?Æägá° ¡ÜýêÎ7ëÄþôسÙÂÁâœM/±âšWxþØ{x÷ø—øà³ß£•_aìö =<Ï]Ÿ˜Çßz‹0þ|Æ740yòdæÎ˱cǸì²Ëxæ™g¸þúë™?>7ÜpCNRAßñ‡Ã:::7nœŸ …B~âPß=cšf—;YtÐÒ½ ŸþyÞB=O¡Nv‚t°C‘Ž4uuu¬X±"ç8 Ö­[Çúõë‹]Œ!—Oعs'Μâî{œà.|؆ÛjÔôP¨æ­Q‚Ï}ÕŸÍ4=¾üCæÌ™OMÍK8N3Mï4ñŸóþÂöí®ÊS¥R8©—]v‡fÉgðLºŒœ4eŠß{8 H&“ªªH&“þPÄ@Î]nºwpö¹«{ësÖêcŽ19'¨§Í™}UÞS¸¬íáõZöÕwù= ¸¾°ìü9Ý]Lf]7ý6ñ[æo™ÏŠðŠÌ냹¯ñ—mÁÎ'w泉‹*ß:ÁŠ­ó‰'îÇœ; ûþÌÜ{)~ó›]œüû½lÞ\Îo;·ÞR ¶óçßÏþýwòæ›ÇÿüÏTTTptÆxZfÏæ3¸ô¬³xgòSüìÕyìÙ³‡åéÑ6ÇbXá0Éd’›ÜÄw¿0¿}å&ßsöÎì:ã ¶Þp nÌYòž÷°üßÿõ]ÍÍÔTUÁòå$¿úUÿ5¤RêçÄáßP»<;gYБ9èV¯^ÍúÎs†Bªu1ËôÈËfY¹=ýb±Üž„:ᦥR]‡íëF#ÝÚ›ÁÌqlÙ²…††Ö®];ô=;o‹"’:Aÿêü¥†ö»ÄÂÝ=w÷T,⦚òý(‹«†Ÿ-ú-Ï>;dzcÇvÞ>{*‡NœÄܹ¯2eJ;S¼§ùÑþU«.¢¥å×üã‡X¾ü S§NåèÑ£,;|÷Õ‰<üŸ˜4iÉd;OΘÁÁåIöìÙƒåy¤ÚÛ‰WÞ诊ëš@ ÔÔÈì_Íúÿã“'ó¥¥KýZkk+/ïØá?pÒ$žzŠ: ¼¼œÖÖVV=ÊÒýûy÷Ýw?~­--\0q"ÓÞy‡½ÇÏîÝ»?~<¦i²mÛ6Õ ØÒBUU|ê)*R?ø7Ýt/¾ø"Ó–-cgs3GŽ¡¼¼œ––Bá05±?úÑøÂ¾À¼/~‘Ø~À 7ÜÀSO=EeUÁwÞaçÎ\~ùå¤R)^®®¦:ößó»îÂüÆ7¨¯¯'‰0®²’omÝÊ)gŸÍÖiÓð\¹èv­\Éï_ÎñÇ¿@ËËáÊüùóyêõ×immeÑ¢Elß¾™û_øÆ7¸é¦›øÉO~ÂM7݄󓟋Ũ««cöìÙüxÁ~qì˜sÃ\wßíJ‹ÅsÅW0~üx,Ëâ‰'žàü£G¹üòËUûR8̸@€_ýêW\{íµ$“IRk¦f1[:ò•ßÙ ÷ÝãèH_“ÿ( ÷Ú¤ZÁüxÿþ¼×¶ç¼oܺÏþ` ;OÀú®CÓ§ŸÈyþôÛÙ2í“Üw3f¿Î²·þ‹_ì¹Ä¾cÜN]ô[v„éèè`ÁœM¼çõ<lã;ÓÁD¦M8±Sž`ÏË_`*ç1µÓ<%å¼À^ª8Èbfð"g“ây5{¹o?c?qæÑλü‰9LÀÅÄS·4qéø'™¹øÏüö…/ðÕåßÙœÝîx)×>ø;^:z6ϵÏåÌ©KXÎÃü¬=7Qýÿ}ð×|ãwàÚS_äà˯ʺ(½è¸&f/LñÕ˜Áw.ú87×Ý”³ŒëO|‚MíKqX3=.>zßyëÆ.ŸóGÕçÜTµOg>ç¼ÿøX÷·ÓølôþƸü_ÌYÆçç>˳S‘Ú;•KçÁ>ò+bûrG‚j¾*?¢þ޾Ï!õ¸—³>öÌ—ˆ|ú4"?TÿOÆ6§o(Û­~­=·™g¼J~½ì9œ]×ås:~ãÒw$¿±ï§2Ÿó¦úœšÏü±Ÿ/@rõ%™ÏI WíÀ9°_ìûXë¨ËþœíбîjÆÝ¡?çjb?MñÝN ÙðU‡)E©¸?ÿq­ïbL¶©yHÔáÀ[om῜GÝý ™3g'ee?â¾ÎË/ŸAuu5Ë—«ýáy@€P(Dõ§«ýÞŒÙzújˬÑp-8Ú1sÚ"ưqù/fè544°zõj¶mÛ–óøêÕ«z=©®¹æN~4@ý[Ÿå踎v¼ËQ Ž;î ŽÙš~Uª%X·êên‘®_™Ó¿Ï9çš››9餓üTgžy&‡fÑ¢E<üðÃ\sÍ5<ðÀ9¿·oßÎÉ'ŸÌ¾}êÁÙ³ÕÏ'Ÿ|2¯¾ú*'Ÿ|2S TÑÓŸ;–lÚ´‰ùóç3þüüVBú»¯wíÚÅ®]»xíµ×xâ‰'ú±ä‘%Ÿ8ê<Út'[ÇÍãл ˜8ñW¼ó΋d&BªAÅÕUÌ0 >ÌäÉ“™:u*ííí”——ÓÜÜÌÊ•+ihhàk_ûñxÜ?ßÏ:ë, sŽïÛ·/ç|‡Âç}‘sbìȾ޴I õöÞ÷¾—ù—)vÑ,ß:·e2;Z~ÈNÎz&€·\MÖ6eÊ::š™7ï5vìxšsÎ9‡gžy†•+Wrÿý÷ …ؾ}»ß?uêTN>ùdÞÞ½›K?žƒ2gÎÞxã ŽžuãÊ3wÏ}õU¦´·3sß>v.ZÄÙ³jcñœÐßyçŸ~±‹2¬ú»¯<ÈÖ­[Ù½{7±X¬ä.ìò­|ðƒä©§®¥­íóž©"ÓÜ!wìnÝBw‰ÌôhÓ ÆúÿÙõ€Ã‡3gÎ^yå?ž\~ùå<üðÃþÿO9å<ÈŒ3üzÂ{Þó\×å‚ .à©§žâ„Nàõ×_÷ÿoš&dɤI,ž8‘öövæÌ™ÃS/¾È)×^Ë<@(âç?ÿ9×\s ¿üå/¹üòËsê&úïíÛ·ûËÕuýÿE‹ è=­­­”——ûIÍgŸ}–Y³fqÊ)§ÐÚÚšsý“ý;û=ííí~Ý©½=“lÑïêúT©Ö£ÿ^xáÚÚÚØ¿?¿ûÝïŠ]ôË'444‡Ù¼ñ.Þê8Õ¼|ÜÿÐÚÑLfX‹:.ÌÇe;ˆ“¹“Luy^žîi“™z4Åìٳٷo_Nl8éí·9î¸ãØvô(“'OÆó<Þ;o'íÞÍüùóÙ²kï7ÿݽ›Y±Tü>óÈŽ{óM5'Tss—x²òÄ™tèÓ¦Mã/Ó§³õða ÃàÅ_ä¯þê¯h»÷^>øÁ²yófŽ»è"™}Úiþç,9tˆ mm++ãÁ¿üÅ?Ï¿ô¥/u¹îÑ绾¹¹¼¼ÜO†=ðÀ|êSŸòcÐ]wÝÅW\àotÛ·o‹-â©§žò×§»”Ýž’ýýÚìßÛ·oïõ=—_~9O>ù$gu–ÿ½úóÊËËI¥R|øÃî6né6}­øÏž={HÞ3;«î¸oß>¦M›Æ«¯¾Ê¢EÙ}¯VÿÛ´i{÷ªjÌ]|å+_á¹ÿy-ß̉Ó pÈOŸÇ˜ŠE;6SI1 P}[#Lžü=Ž9Âܹߣuï—)Ÿ4‰}L˜0‰áرcŒ`„\pÒóì|9ÀY³ÿ—¿pâ¬Y¼¼ÿ;L~ÏÿåСg)/™ÓZ[™þîBÚfœÂ´q/SvÒI<¾÷*+«yá…°«Æ±÷G˜={6m²ÿ„˜€ËÑió?~6{öleåÅóxê¿_ļòJÚ‡%K–ðÃ?àÚkÿ‘—_~™O|‹i¯d÷„9œüÖ[ü¹½ûô¹ü¿†»¹úêÿ˦M›øô‡¦âüÏ~–,Y–;WVÆëo>ÇÁñã™5k9­­Í\qŹlüŸÍØK—òë§žâêK.á¿kùÀ¾Ê3Ïû,—_~9n<ÎÊ•+Ù´i ?ö1þç÷¿÷cÑÉ'ŸÌ)/¾È 'œÀŒ38xð Ç~:߾礸øÜçØ\÷—ž7››žà„Nà‘ƒ90~¼žÝxæ™4Ü?¶msÿý÷³råJþñÉ'ùØÇ>Ɔ ˜6m¤{ê:XçÏùÒg>ÖŸýŒ•+WòÌ3Ïp´¢‚ÝéúŠŽ•¶aðð½÷ú×–+W®äËék̇~˜E‹ñÞôp§z}ÊÎ9‡[úÓœÏñR)Î?ÿ|^~ùeþRQÁþýû98q¢ÿ9+O<‘ç{Œ—ËË9î¹çXºf ¿üå/¹æškxøá‡9ùä“÷òËT=Ê{–,aÃë¯cãŸÏÃmû´Ö8pÉ%—0yã:6sçNúOp6&<ÃÛo/EÝNã„þÌ믿È9çã™gžá /ä­·Þòão{{»ÿÝØ9&‡ÑpÝ_ªõïl¥Þñ /°k×®¼Û ÇDâñÕW_åî»ïæÙgŸ¥¼<@KË!æÌ™Ã”)Oø•·iÓ¦qꩪ‚¡ƒúI'Ä /¼ÀyçWìÕ¢ ^ýu^ýuÞóž÷ðá¸ØÅ°|+¿ùÍoøÍo~ÃqÇÍåàÁżýöÛœzj+o¾©.äÆÇ¥—^ÊŸþô'N?ýt9ÿŨõüóÏpÕUWù º¥¤uÇqX¸ð ^|ñ/žHGG3§žzªªˆL]`É’%Å^]!†Ä[o½ÅŽtï¶›nº)¿…A¾u‚M›6ñ“Ÿü––Iœyæ¿.ðꫯ²xñb^}õUlÛæ…^`þüù]ýg̘Á®]»¤¾ JÞÎ;yóÍ79묳J²q$ßXð“Ÿü„Ÿÿ|7óæÍcÒ¤CœzªJ:½õÖ[L›6}ûöù±áúë¯Ï¹Nè-6œwÞyþÿ³ßsúé§û¯b$ë×wÞù?<òÈAN;í4Þxã Î>ûöí{‰óÏ?Ÿwß}׿6€®m†Ùç·þýÚk¯É{ä=%÷žW^y…‰'rìØ1¾üå/û´°B´>ø¯2å\uÎg×Î8ã Ž;Æyçç¯Ë÷¹­ôõA¾u‚1‘xBŒ„ ±@!q@¡H,B€Ä!„Ä!FšñÅ.À@555uy¬Ô'MB ŒÄ!H,BHB( „ ±@!q@ˆ‘¢dzÞ™-[¶ä<ÞÐÐ@EEE±‹'„„ ±@!q@¡H,B€Ä!„Ä!Fš’I<¬ZµŠºº:ÚÚÔÎwÞy'eee\}õÕÅ.šb˜HB€Ä!„Ä!„"±@ „„IJfŽG€¶¶6n¼ñFÚÚÚ(++£¥¥…µkײjÕªbM1L$!@bBâ€B‘X „‰B‰BŒ$%•xÔX¶leeeÅ.Ž¢$!@bBâ€B‘X „‰B‰BŒ%™xB!„B!„B!„BŒ,%5Ç£B!„B!„B!„bd’Ä£B!„B!„B!„"o’xB!„B!„B!„BäMB!„B!„B!„Bˆ¼êÄãºuë8ï¼óX²d kÖ¬¡¥¥¥ØEʈ X½zu—Ÿ¦¦¦¯w)l›ë®»Ž†††nŸ+Ä:ŽÔmÐÓz÷gÿ–}_h£m  Je»ä Jùœèn½ÇÚ÷@¡¦u‹ÇBO± Pë8·ƒÔ FŸ¶¶6Ö¬YÃ’%KX²d ×]w]—óFn]wÆ ض͒%K°m› 6Œør·µµqë­·æ,s¨be!ÊÞÓyßy=ºÛþ…Ú¾†^¡bA1ög_q`$–»?q På*T¹ó‰#)¦‰Þõ'ŒÔý9u‚B—»ÔêÐ},(T ?¯‘8P|Ã÷‡k}Î;ï¼.Çu)¬ÃpÕFŽQê»ßýnGUUUÇ=÷ÜÓ±qãÆŽk¯½¶ãÚk¯-v±ò^§|àßýîws~^yå•­w)l›x<Þ±xñâŽ7v»ò]Ç‘º úZïÞöÿhÙ÷…6×¹± T¶K>± ”ωžÖ{,}Úh[ç±v,ôvNbGâv:Á褷óÆ;6nÜØñÅ/~±£ªªªãÀþkFj]÷ÁìX¼xqG<ïØ¸qcÇ-·ÜÒ±xñâ‚wCQn½Œ|ÐßæøÀ º½ UöÞÎûo¼±£ªªÊ_ï~÷»‹/îxðÁ º}%6 BÄ‚bìϾâÀH-w_q På*T¹ó‰#)¦‰¾õ FêþŽ:ÁP”»”ê=Ç‚BÔ úó‰#ÃpÅýá\ŸÎÇu)¬ÃpÕF“Q›xÔ1Ú+¯¼Ò%—š[n¹¥ã–[nÉ{½Gò¶¹çž{:/^ìÿtWÑ.Ä:Ž´mПõîkÿ—ú¾*£q  Fúv)D,(Ås¢¯õ ßCe´­óX9ú:' µŽ#i;H`ôÚ²eKÇâÅ‹;¶lÙâ?vàÀ!9f‡bÿ^{íµ9Ëìèèèøâ¿ØqÏ=÷ŒØroܸ±KƒÀü þB•;ß²÷uÞwwœè}òÅ/~± ÛWbÃÐ+T,(Æþì+ŒÄr÷'ª\ù–»±`$Ä4Ñ?ý‰#uG Ðå.•:AGGï± Pu‚þ¼Fâ@ñ gÜñx¼ãÚk¯ír\—Â: Wh4•C­655ÑÒÒŠ+üÇ***Xºt)[¶l)vñ­¥¥…²²²¼Ö{¤o›+V°~ýzÖ¯_?dë8·A_ë ½ïÿѰï‡Âh]ç|cA)l—|cA©ž}­÷Xø £qÇʱÐÛ9Q¨uiÛAê£WYY7ß|3K—.íñ5#µ®ÛÒÒBSSSÎ2î¸ãV­Z5bË­‡pª¨¨ÈÙË–-ó×i$Ä‘þ|ÿ¯X±¢Ë±³lÙ2ÚÚÚ ¶}%6 BÄ‚bìϾâÀH-w_q ¿Ÿ91,ßX0RbšèŸ¾bÁHÝŸÃQ'Šr—Jz…¨ôç5F†áŠûá©©‰x<η¾õ­.ôu®:Ðh3±Ø èr0Ìœ9³ÛqüKÅ–-[8pàK–,ÔäÚµký¼?ë=Ò·MEEEN% ³B¬£~|$mƒ¾Özßÿ£aß…ѺÎùÆ‚‘xt–o,èÏ:ŽÄ㣯õ ßCa4®óX9z;' µŽ#m;H`ôª¨¨`íÚµ€º0=pàuuu,]ºÔß#µ®«ç+**¸õÖ[iii¡¢¢‚U«V±téÒ[îeË–ùåÏ>¯ôúª¾ï9Õ×y¿téÒ.mmm<øàƒ­ÿIl…ˆÅØŸ}Å‘Zî¾â@?s8bX¾±`´ÖF«¾bnˆiûs8êCQîR©èmÛS,(D ?¯)…v£±`¸âþPkkkã–[n! uI¢–Â: Wh´•=G«¶¶6***H¥R¤R)V­ZÅ­·ÞÚí„ãbô‘ý/49Æ.Ù÷B“cal“ý_úÖ­[ÇêÕ«Ù°aW_}u¯=˜G’ë®»Ž²²2–.]JKK 7Þx㈾P^±beee~AKK‹ÿw)Û°a×]w„B¡bGä¡cÄ‘CbÁè!±`èÖX q`l)ÕýÇ™9s&7ß|s±‹’—R‹{Å6*{<ŽVÛ¶mËùÿÚµkihh ®®®K¶\Œ>½í}W“$Œ]²ï…&ÇÂØ&u‚Ò§ï\nhh`õêÕ”•••ľ …B9 ¶mSWWÇUW]Uì¢u«¬¬ŒŸþô§¬Y³Û¶¸êª«zâr$Ó¤ Ü|óÍ„B¡’hœ=+ÅXÐS¸ýöÛ‹]´n¶8 F£îbA_#`›Ô ŠKâÀØRÊû[_§Þ{ï½Å.JÞJ­Tl£ºÇcwçRýBéÉŠ+ü1¼²Þ¥¾m ±Ž¥¾  ëþ û~0ÆÂ:&Œ†íRˆu,õí0V¿c´¯óX= µŽ¥¾¤N0òé¹A²­X±‚+Vté­:Rëº"W]uUNO‘Xî¥K—’J¥Ø¶mÛ¶mãŽ;î`æÌ™CR_Êsª©©É¿Ë:•J±víÚnœ¤n4ò2cöFb¹û U®¡>ú J!¦‰þÇ‚‘º?‡£NPèrK`äÅ4Ñ·áŒûC¡¡¡™3grë­·²zõjV¯^ dzz—Â:hÃU-FeâQßéßybΆ††ÇPO6lØs2j---~°éÏz—ú¶)Ä:–â6èkÿ…}?£q  FÃv)Ä:–ÚvïÁmë,Ç]ÇRÛR'(]6làÆoìõ5#µ®«çEê¼ÌÎó"´r·µµ±nݺœ¶¶6X¶lYIÅ‘5kÖpõÕWsÇwt»Ì±X7*U…ˆÅØŸ}Å‘Zî¾â@?s¤\cõ J)¦‰¾cÁHÝŸÃQ'ŠrK`dÆ4Ñ·áˆûCiÕªUÜ~ûíÜ|óÍþÀÕW_ÍÍ7ß\ë0\u ÑfT&AÔuuuþßwÞy'eee\}õÕÅ.Ú ,]º”††Ö­[ç?ÖÐÐàÿ>õ.õmSˆu,µmПý?öý`Œ¶u.T, Û¥ëXJÛA¾ò3šÖYŽ…ŒB­c)m©”®«®ºŠ¶¶6î¼óNÿ±††r†H‰u]Ô^·n¿L}Üé!ÕFj¹7lسÍ×­[GYYYAË=eÏÖÐÐ@KK‹ß &û'û®é±V7*U…Šý?ûFj¹ûŠ…*×PŸ?ý‰¥Ó„ÒŸX0÷çpÕ †¢ÜR'Y1Môm8ãþPÑI·ìP×µ…ŽuCe8ë@£É¸ŽŽŽŽbb(´µµqã7ÒÖÖFYY---¬]»vÄϗЛºº:¿‘iæÌ™´´´póÍ7³víÚ­w©l›%K–°~ýú.sUbGò6èi½ûÚÿ£ißÒh\çBÄ‚RÚ.ƒ¥~Nt·Þcí{ FÛ:Åc¡»s¢Pë8R·ƒÔ FŸºº:n½õVÊÊʆôÜŠýÛÒÒš5khjjbéÒ¥455ü¸Šr744°fÍfΜɘ9s&wÜq‡?¤ÑH‹#Ý÷ëÖ­Ëi(ͶbÅ n°Ñ^7M  б?ûŠ#µÜ}ÅB•«ål,i1Mô®¯X0R÷çpÔ †¢Ü¥V'€®± Pu‚þ¼Fâ@ñ gÜNëRX‡áª&£6ñ¨éqÑ—-[V2“®ö¦­­Íï’[QQÑcWÜþ¬w©o›B¬c©mƒþìÿ±°ïc´­s¡bÁhØ.…XÇRÚò=ŸÑ´Îr,~Ki;H tµ´´øÃò õ¹;ûW/s(»B—;û|éœÈ/d¹‡¢ìƒ1ÖêF¥ªP± û³¯80ËÝŸ8P¨r„óg4Å´Ñ®?±`¤îÏᨺÜR'økFÂzˆ¾•Ê1Yêë0\u Ñ`Ô'…B!„B!„B!„CoÔÎñ(„B!„B!„B!„>’xB!„B!„B!„BäMB!„B!„B!„Bˆ¼IâQ!„B!„B!„B‘7I< !„B!„B!„B!ò&‰G!„B!„B!„B!DÞ$ñ(„B!„B!„B!„È›$…B!„B!„B!„y“Ä£B!„B!„B!„"o’xB!„B!„B!„BäMB!„B!„B!„Bˆ¼IâQ!„B!„B!„B‘7I< !„B!„B!„B!ò&‰G!„B!„B!„B!DÞFeâÑó;LÓôãˆmÛ­­­ z0’Ë6V×EÎûÂêïqÑÜÜÜíëš››;,ËòcJ0ì÷g—j\(…òÖ²g“X0p=Õ::$ ÆH.Ûh.{gc1 E»@GÇÀŽ‹îbÁPÅ–m¸ä²Õu‹q¡£#¿ØPˆ:Â`”j Ê'ë5vcÁP6Þ ¦|£²Çãh‘H$|Ýh‰Dp]—ÖÖV:::0M“X,Vìb Q4c5䣺ºš`0HGG­­­€Š-B” 9ëº$ ª««»}¾¦¦Ó4ý˜â8ŽÄ1,$ \>u‰b¤‹± ˜í½Å‰b¤‹qò‹ ÒN F£± ÄÈ7±Ø(”x<Žëº†eYÝ>gš&¶m“J¥…Bþó©TÊï* sÞ‰D‡ÃÄãq<Ïò,‚Á`Îç…ÃáA¿¾¯õI$ضM$!æ¬Oöz d;„B!LÓì×sýy¾'Ù&žçÇillÄ0 õ²zÚ®ë’J¥ƒ~¥Ã¶mlÛîR&ÏóˆÅbþþÈ{²»;õ:zž‡a„B!]ûÚŽÑhÔÿ*•ÂuÝœc {e—¿?ïÕÛ$ßu/¦Þ¶{öóÅŠÙe.d,Èç\Ž8Пó±¯mຮÿz}m†0ø:B©·ÀظèÔFO!ß6ñœ?È·ŒÅ6_µµµ†aäŒe¬ÇúÖãñg?gšf‡mÛ™ñú³Ç×ËÓ€ŽÚÚZÿÿ–eu„B!ÿÿápØ_Þ`^ßÛ¶sÆý:ÂápNYû»¬ÆÆÆ.Û¶íŽp8Üës}½·?²MêëëýqÖMÓì0M³Ã0 õ¶ ôXÃÑh4çy ãW¿úUÐÑÚÚÚåóûz¯ッuL&“½ÙŸ£µ¶¶vضݯ±¸;Ÿ®¥ÎË ‡Ãþ|½½··u/•1ÂûÚîùÆ‚bÆŽŽÂÅ‚|ÎõáŒý9ûÚÉd²Ã0 ?†˜¦™3Çãh½ÅÞÞ[ªq Ÿs¿Ôêzùrîw¿ úzo_ç¾Öݼz9ݽ®â‚Þg£¹Ž ×£ëz ¯óy°u€ìeÅX0Úër=0ºê}µ ôµ òiÈÖù|,TÐËêé˜-V ·÷—J,èL꣫ŽO›aGÇàë¥ÞN ÷Éh¾èÔFW!ß6ñœ?l ¯uï©\%ßãQw“ϾCEwÿL$]ž ƒþß©T Ó4ñ<Ïï.­ÿŸ}Löû Ãè³[ë@_?ÙÝWûÛ]¹§m¡ïàëí¹¾ÞÛ_ýÝ&Ùw/577ÓÜÜL(ÊÉê÷µ ²»£ëcáÅ_ðï–È>úzoOÃ.t§·ã1»¼555þYÉdr@û²'z9ún„T*…çyý~wë^*c„÷µÝ  FR€ÁÅ‚|ÎõáŒZ_çcOÛÀó<"‘¶mS[[Kmm-†aäÜ…3ZcÁX‹ùœû¥X9÷ûÚ}½·¯s¿;½C9¿¤Ž0täz Jåz@ëí|Χc3Œå8r=ÐÛv‰u‚þ´ ôgäÓ6ÐBÅèý˜•:AáH¡J¥ŽO›a!ê¥ÚN ÷ÉX:÷³IatÕ´|Ú zzÿhÏäzZ÷žbAÉÏñØS·xè»âçºnθ´Z)ŽS=ZضM,Ë Láp˜X,æw/¨ì@eY¶mSSSCssó€ÞÛ½ G2™ô»í{žG(¢¶¶6ïm§‡Ð+ß/­Bé ¥¾¶»Ä‚Ñ¡¿Ç¤½¾¾ÞÌ4Mªªª¸ä’K€Ñ ÆZÈçÜ—ó¾täsv~ï@Ï}ýžž ¤â/u„¡#×cCŽ»ÞêÙÉc1Œå8 JM_íƒÝ/ù´ è÷ôd ½³R'(©#Œ.ù´E¡TÚ `ìûÙ¤Ž06ò˜–6ÃÁm·ÎJ>ñhšf—Œ²†aô<,Ëò3ÆÙïu§× e©ê¼-ô¡½=§3×}=_(½¬ý=ô¤«úïì²×ÖÖây‰D¢Ë„©}½·?z;ÂX}w•ã8,ËÊk[& âñ8ÍÍÍ~àŠD"ºÛ"ßu/¦¾¶»Ä‚î· ôÿ\ïÏ{‡¢¬ƒ9&³ß§éób÷îÝÀèŒc1äsî¥ó¾óvÑyî÷ç½}ûÝÑçSöÅA_ =-GêCC®ú¯®²Ë:Ðã®·:@ö¸c-Œõ8 zÚ.02ë…hÐålÛ@w ô²z:f¥NP8RGè¿R¨#ä QG(Åv›ç~6©#ô_)Բ˚Ï19Öò…ˆ]÷’j5 æLt™}B0ô'ÖÏeO˜iÛv—Çôä£#E¡y(ê²-jjjüŒyOÏõõÞB³, Ó4sî"‰D"˜¦Ùï`Þy2YÃ0X¾|¹ÿ˜žx:‹ué ÜÝ{rKoÇ#s§0à» ²÷Aöä®ú¤×CwÿïÏ{»[w½ÍKåî¾¶»Ä%Ÿs}8ã€6Øó±óþÎ~ÿhŽý‰=½·»õ.…8Ϲ?VÎ{;ç~ßÛÛ¹ß}d+‰Db@C³Ô†’\ôO©\hƒ‰½ÕÆr, u¹èŸR©¢]@¿Gèõ@w  ÷c¶˜u‚ÞÞßy›ŽÄX0í,q!£TêùĆBÔJ±@ÿ´_ôFêýS*u-ßóq¬å Qè¼î}Å‚’ïñhYáp˜êêj,Ëò3éŽã`š&µµµlÛöÇÏ;»)‰DüàáºnÎ ŤÇ×'p>ºÛ†a …ü zwÏõõÞ¡P__O ð÷‰çyÚ'®ëRYYé¿·»nÈÁ``0HMMMβûóÞÞôv<‚ Ò‰D‚ÊÊJ,ËòïŽéÏ…J(ò—ëyžÿŨ×'SYY‰išþ±®ïfèí½ºÜŽãä¬ûH9 ±Ý%Ðãvèï¹ÞWœ ƒ=-Ëò˪y}Lw®ôŒ¦XП8Ð[,(Å8Ϲ?VÎûž¶Ãh<÷òÞžÎýžD£Q€?‚a9C2õ‡Ô†Ž\ôO)]ÀàbAou€îŒ•X0êr=Ð?¥T'È·]òkèI!âô~̳NPê±` ÛYâBF)Õò©#ès¼Û ôºŒöë|¶»ÄzÜ#µŽùŸc-o@—{ ±`\GGGGávyñ¸®ëÔú.ÝíYoLÓ4‰Ç㸮›3¦·~Þ€#eœêìòb"áìí]Ç¢îí¹þÏJ¥R:::üì|÷g>ïím;g?èñùž8Žƒçy=Ë®'<Ö]¸{{owï/5=mw‰Ýo'ø¹>q PçcvYÇR,è-ôõÞîÞ_ ò9÷ÇÊyŸ½`ôû…>w»3˜ºIw¤Ž0täz``Û Fæõ@!ÎçÁÔú«”cÁX¨#ÈõÀÀ¶ŒÌ:Açõèg u½ PqzŨ æý¥@êÛN02ë×}0Ÿ5VÛ ²—;š¯z#u„m'™u„|ÏÇ‘ÔîPŠ×Ý-£'£&ñØ}nllô³Ç@€p8<¤÷¾dªž ä -ôòеùÊ>ù ùÞáXÏ‘¶-G‰ƒ[^±Ö#Ÿs9_=}¶ÄÒ4Îýb7#éÜ/VÜØ0ò…80Ë+Öz@që#eã3F;‰ƒ[^±Ö#_ň# JÄ…Á-¯XëQLÒf8ºI,Üòеù~ÇE»ƒÄî•üP«½ÉÀÐÝF‹©§1t³ 䮀B/o¤îpŽõ+Û²X$ ny#ýs‡“ÄÒ4Îýb7rÌJl(c! ÅòFúçŽ$JƒÄ‚Á-o¤îH"± ôH\ÜòFúç79÷KŸÄ‚Á-o¤îp’8нQÝãQ!„B!„B!„B1<Æ»B!„B!„B!„BˆÒ'‰G!„B!„B!„B!DÞ$ñ(„B!„B!„B!„È›$…B!„B!„B!„y“Ä£B!„B!„B!„"o’xB!„B!„B!„Bämb± 0ÚÚÚØ²eK±‹!Ĉ1sæL–.]Zìb »¦¦&8Pìb1b,[¶Œ²²²bcXI@ˆ®V¬XQì" »––ZZZŠ] !FŒŠŠ ***Š]Œa×ÐÐPì"1¢ÈõBÚ …`\GGGG±Wb¨}ô£eÆŒœ}öÙÅ.ʰzà¸æškŠ]ŒaµiÓ&æÏŸÏüùó‹]”a5Ð}ý‡?üx ØÅvçœs7ÜpC±‹1¬äœ;º¯wíÚEYYßüæ7‹]ôa%u‚±c×®]ìÚµ‹óÏ?¿ØEVÝ×›6mâK_úÒ˜K>^{íµ\|ñÅÅ.Æ€•ê¹\ªõ‘R-÷`â߯ùÕ¯~U좫††¾ÿýï—ä÷D©Æ)÷È.÷X½>¸í¶Ûhkk+¹X?–¾£F‚R-7H›a]sÍ5\qÅÅ.F^Jõû*[©Æ¶l¥/²×!ß:Á˜èñxÜqÇqÙe—qÓM7»(ê©©‰µk×»Ãjݺu¬X±bÌ5ž t_755»ÈEqÜqÇÉ91FHüë[CCؼË_êc‡>ÆÇÚzt_¯[·®ØE.ŠY³f•ä±Qªçr©ÖGJµÜƒ‰cõúàüóÏ/ÉsªTc”{d—{¬^̘1ƒ+¯¼²äbýXúŽ JµÜ m†ý5wîÜ’Ü¿ÙJõû*[©Æ¶l¥/:¯C>FämmmœwÞyݮܺuë8ï¼óX²d kÖ¬é×Igœq .,öj »R>¸kÕªU,[¶¬ØÅv£q_:,X° Ø«5ìäœ;Fë¾–:AaŒÅsbÙ²e¬ZµªØÅv£u_÷ ['(U¥ºKõ;ªTË=ZãßP\”ªRRn)w!H,Pä;JÊÝ_£1HèÞhØ×¥Û²•r¼(¤™x\³f mmm]_·nuuu¬]»–õë×ÓÒÒš5kú\ÞŒ3˜6mZ±WkØÅñ¸+**ÆÜ|0:÷u¡ãÀôéÓ‹½ZÃNΉ±c´îk©ÆX<'ÊÊÊÆä|e£u_w ò©”ªRÝ¿¥úUªå­ño(®JU©Æ)·”»$(ò%åî¯Ñ $to4ìëRmÙJ9^ÒˆK<Þyç=NäºaÃV­ZŪU«X±bwÜqMMMlذ¡ØÅBÄ!H,B(=ʼnBŒR'B€Ä!„Ä!JňJ<655ÇùÖ·¾Õís---9ãûVTT°téR¶lÙRì¢ ! Dâ€$!”žbÄ!Æ©!@bB‥dÄ$ÛÚÚ¸å–[…BÝv Öw2tžXtæÌ™}NzûÆo°nÝ:Ö­[WìÕ¢¨êêêX½z5;wî,vQº5”q`çά^½šºººb¯ªEµzõjÖ­[Ço¼Qì¢tk8ê«W¯.öj QTMMM¬^½šx ØEéQo± ß:ÁÞ½{ýX(ÄX¦¿÷îÝ[ì¢tk¨¯xàV¯^Ý¯× 1šÉõ\!m†Òf(àçÑò­L,öŠhñxœ™3gróÍ7|ÙsæÌáÃþp—À#ÄX£‡©ꡌ ,`ýúõÅ^M!Šnýúõ444t;ûH u!†ÞÒ¥KY¿~ýˆN¼ e,˜;w®Ô „Ö®] 0f¯®¹æ1–Éõ\!m†Òf(¨ëƒBÔ FDⱡ¡ºº:î½÷ÞbEQ$„ ±@¡H,BHB€Ä!„Ä!JшI<Μ9“[o½5çñuëÖ1sæÌœ» šššºt§î®{µ¢´HB€Ä!„ÒW,Ðw:Kbô’:$!$QŠFDâqÕªU]†4hhhàꫯöƒ~~Ë–-9Á¢¡¡«®ºªØ« „È“Ä!H,B(}ʼnBŒ~R'B€Ä!„Ä!JшHò.¼ð¼>¯ ‰Ç¶¶¶‡RÕó;655l# !„B!„B!„B1Ú8ŽÓkâÑqœ^ߟý^ÏóüDc$¡¦¦¦Ç÷÷–”ˆ‚$—.]ʆ º}NÏûع7¤B!„B!„B!„"#•Jõ˜xt‡@ @*•êöyÏóxž‡ëºÄãq\×%‰‹ÅH&“þgdK$\qÅy—b!6B(bÍš5\uÕU€J8¶´´°nÝ:V¬XÑcH!„B!„B!„B!Æ:ì)ñ5k*•"PUUEcc£?Lkuu5©T Ã00M“X,F8Ʋ,lÛî²üx^.Å0G?ëÀ£çy†ëº¸®K†ÄãqÇÀ0löí‡ç©LÅ+¯œÃ~PGyy9±X ÇÓôY¼8 ¨ c¨ c<ž„64@&£~W·Qǫ㋙Œº<¶©©ùÁ Žãð÷ÿ S¦ÜÄÝwWãû>žç‘Lª€ çy„aH†8ŽC,Ãu-n¸áóüò—ß"ãû1¦Ný#7Þx€yóîbäÈ·˜6mW_­ƒ%%5˜¦É7¾±’%Kn$×E½Tà1 Up± …#±X¾Üj6«²++óÁIËRÁÈU«®ä3ŸQ×»®Úç@À£ÖÚÚÊš5kؽ{7Eoöž”––FÁËææfvïÞM}}=eeeÑí ÷YhâĉÝÖs.´gÏ\×¥µµ5Zñ Ä騱±‘ÆÆFvîÜ9Ô‡ÒÅ`;w¶¶×c“ÃUmm-Û¶m£¤¤d¨¥‹uNÐØØØï…SBœÊZ[[©¯¯gݺu'åßÄc7nú~N°k×.jkk)--•Ïâ´V__Okk+»víêCéâD|>X·nµµµTWWSZZ:ÔYˆ!#Ÿäó2g(s†¢w|ß'‘H°`Á^~y$4‚*« ª÷bee%AÍfùå/wòË_†$“I2™HrÍ5*@p÷Ý¿äsŸû AÏR€ï}ïF6oVAÃl6‹e©Ë H§‹¶­·WûJ&Õ—ëªË3™|ðQ…!\zéNÞÿ~·ßçx¼ýöÛ©¯¯/ºlÅŠ”––²|ùò£®H(T[[Kcc# 2)â¤g̘1”••1þüz¸Bœ’JKK©¨¨àÉ'ŸêC9ªÁÎ>ûl***dRAœö***xî¹çxõÕW‡úPŽj0Ï .¾øâ¡~xB ©‰'RQQÁ¶mÛ†úPŽi0Æ‚±cÇRQQÁĉ‡úá 1¤æÏŸOiii—ž3'›Áú|0cÆ  „@>Èç!dÎPæ Eoø¾Ï5×<À‚OrÑEç±aËÑå:ð¸jÕ®½¶†+¯Iüû¿ß,`üøg™4éf®»n™Ì™5«×­&T°®îƒ€ 64¨  a¨ äÑNÕu°1—Y¤®®8 *Ћ©@£HêÌHÛ†Lf*_øBY¿Ï $ðXظµºº:zÃ766R[[˲eË¢Z¶Ç²råÊè¶·Ür %%%ý^…Èç!dÎPæ űýý߿ʛoÞÅ”)ð‘@}ýa‚ Èe<ªÌÅýè,\XJ2©²ËËU@oçÎKxßû`Á‚rÝuWbÕø¾ÊV,‹©ï³gçž§‚„™f×2«šî騆•)©–¶­Ž#“7Þx£G?دçêŒxÂ׬YÃÒ¥KYºtiÑ*ƒŠŠ –/_NkkëQ'5Z[[»¤<ë´æÎ·ë.5ZŠBœúdB€ŒB¥·cŒB _rN „ „2ˆ¾Ë%!˜Í›ßÆÜ¹Ï†*8bÄdÇÉ]£¬¬ƒ·Þz'A`’J©LB]òT°¯¥nºé:lÛ&™T—FÏ÷«ÌEèy»£{â8ê1X45僟¶ ¯¼2¶ßÏÕ€;7n-¤W#­–òš5kX²dÉQïCï_÷sÑ%Zˆa@Æ!ÈX „PŽ5È8 Äð'çB±@!ã€è»L¦ï·í´ ˜1ãî¸c3ɤ ÚÍžýÔ×ÿŠK.ù;Fúÿ8㌯ðü†x\öl[}鲦±˜þÃê®6j' ùÞét>²³î2!{òºfJªÞ’ý7 ÇÒÒÒ3uÀñh+ -ZD{{{Q*·nh[Ь®®¦¾¾žööv@•ƒ)))áú믘gC1ddB€ŒB¥7cŒB orN „ „2ˆ¾Û¼ys¯· CpÝüÏ:hé8*s±ª Ö¯¯Ä0 ªªT€îÅ?ÅÖ­ç°wïßRZúÉd Ê|´,‹;nføüò÷ãyÙl–D"Ad2N烆¡ú6† Æ¥R)^|ñy.»ìÛ˜f×>¡:iÛùŸ¦7Û 7’ñX__Ouu5+W®,ª³\SSÃý÷ßOsssÔÔU!„B!„B!„Bˆžø¾¨@ išxž]çºnpŒÅb$“IÂ0$•J1wîm€ ,^}õ?“É€a4440iÒÒ¢ûˆÇ¡¼ªªà™göâyŽãðµ¯ý%÷ÜSÒíqé ÆÞ”Y=] Hà±µµ•E‹u{]YY@Q V!„B!„B!„B!º“H$¢,Æt:]xLŒÇãX–…ad³YÆÿK¾÷½1M•‘øè£c Cµ½ëÂo|Œ Öɨ>–¥‚”O=õ+*++±,‹[o½ù¨åQ{Sbõt6 ÇÒÒÒ3[[[|R!„B!„B!„BˆîA€ïû¤R)b±±XŒ0 £,H-NG?WVZ|ä#?TPѶU Õx\]ÊÊžcêÔ?ê² /Üm«ÌÅ×^{ˆd2I6›ê‡ÊÀã¢E‹X±b+V¬ ½½=º|Íš5,[¶ŒÒÒR***†ú± !„B!„B!„Bˆ“˜ëºQ&£mÛ\}õwI¥RÑ6³g—S^nPY ••*sñÛߨ bB"¡¶õ}x¼úêM<õÔ,þå_2nÜvÞÿþ 9òeÂ0ß7Rôß™±“ššjkk©­­-º®¬¬ŒåË—õãB!„B!„B!„'9×u£,ÇX®®iÆØ¸ñÛÜ~û³Äã“0 `¬«SÁFÏS?ë€cª€£.©ú¡Í`ÅŠGX»ör £™X,Æw¾É“]‚ ˆ‚œ¢úxlnnæÁäúë¯J¨ÖÔÔP]]McccT^µ¢¢B2…B!„B!„B!ÄQA€ïû444`š&Ž£Ê¦N›6†?üáîºk`bÛªŒªa¨ÛZ45å÷•Lª’«ñ¸Êxlhð˜4i;vx44€m׋y|ñ‹gñå/§1ôÎD¿ô)ðXZZJii)ŽãÐÜÜÌ¢E‹˜?>‹-¢ººz¨“B!„B!„B!„8E„aHee%»v%5j¦9PÁC]:µ½}—_ÞÆúõY #tÔt¥T}m«ïž§2“Iƒd2ÆßýÝYÑmlÛfåJ°¬¹Cý }êñXRRBuu5Ë—/gÕªU”––ÒØØˆmÛÜ~ûí¬Y³f¨—B!„B!„B!„8d2žH[Û—9ÿü}$J©À¡ï«Àã¼ywóùÏ?˜fÏûÒS“É|0RÿЇÎ*ú½óÏ¢ÿúÝãQ!µ5kÖÐØØÈm·Ý•Z½þúë)))êÇ*„B!„B!„B!N"ŽãÉd¸ùæíŒ÷&ñøY<ð€ 8f³*cѲÀ÷W³y³| ÛÎö¸¿dR}×ȶ¶âìHÓìš-)NŸ2fÑ¢EÜqÇ<õÔSÄãqZ[[Y¼x1ÍÍÍCýX…B!„B!„B!Är‡T*ýþ/ÿò}>ÿùûùö·§ñÏÿ|úÐYQV£ë惈ª¤wÔýwÎ`ìt” ÇÁÕïŒÇî´¶¶ÒÜÜLII 555ÔÔÔ õãB!„B!„B!„CÈq‰É\Z¢ïû´¶þ/¦9#GòÛ…!Äb*H*ëQ]öû$ð8¸ú•ñX[[‹mÛÔÖÖF—Õ××cÛ6Ë–-ã–[n‘lG!„B!„B!„BˆÓP&“Ée)*®ë]ç¯1nÜ8n½õ¬¢Ë Ce9Fþç¢K±ŠÁÑçÀcmm-+V¬ ¬¬ŒŠŠ @e:Þ~û픕•±råJ–/_NkkkQ`R!„B!„B!„B aâ8arûí³mÛ Ñu•••¬Zõ|þó?ër;ËÊ-«¸\ª%)‹ƒæùçŸç‰'žè×>úTjµ½½+VPSSÃÒ¥K£ËëëëX¾|9¥¥¥ÑåË–-£¹¹™²²²¡~΄B!„B!„B!Ä àû>?þ6¾ñQ”•¥£cztÝÎ×0nÜ—ÈdÆv¹]:ÿÙ²ô—…ïû…QHÑ+¾ïcšæ1Ÿ»Í›7³eË–~ÝWŸ27nÜ@uuuÑå:¸Xt\´h ²!…B!„B!„B!ÄéÁ÷}Þxãc<ø_ŒÛ€Ke|õÕ…¼ï}¯sñøP?ŠS[TVV’Édp§¨ômg&Làƒü`¿î¯OÇÆÆFJJJº\®Ë®v&G!„B!„B!„BˆÓC†„aȼyó˜7o ög¿ã }¿ým;;w^Ã5×ì<æ~Ls¨É©I=Ï#›ÍbÛ6™L†Ù³g÷|üÙÏ~ƶmÛúu¿} <êàb{{{tÙš5k˜?~Ѷ:à(eV…B!„B!„B!†?ÇqH¥R†ÁŽ3¸ôÒñ<ùä{yöÙÛxñÅO±nÝ=Œµ—Ë/oêC–\×eöìÙxže9Ú¶MKK Ùl¶Ç’«ûØÇ¸ôÒKûuß} <êà¢ã8Ñeº¿£.­ÚùòÎI!„B!„B!„B1¼„aH*•Âq,Ë"‡I“ÚØµk޶;xð_Ž{ßžç õÃ;%†A2™ ™L‹Å¢ë<Ï#•Ju¹ïûÜzë­ý¾ï3ûr£’’–.]ÊŠ+¢²«ÍÍÍ,]º4Ú¦¹¹™úúzêëëYºti—²¬B!„B!„B!„bxÉd2†eY”•½ßËjcß¾}´µµ1cÆ ÆÛNGG8Ô‡:츮K*•ŠúhVVVÇ‹±XŒ0ìúÜ[–ÅÿþïÿòúëÇî»y4}Êx¨©©áŽ;î`âĉLœ8‘¥K—RSS]_[[ /B!„B!„B!„ÃGaËq’É$étš7Þ˜‹NRœ0áÞxc*³fÕîPö°cYét:*­ªÿ:o“H$ºÜ6“Épï½÷öûú”ñ¨UWWS]]Ýíu555Ò×Q!„B!„B!„b˜ËdTðqÓ¦M9òo„aË‚OÚâœsÔ6%%[€?rÝu[Ù±c-›6…Qfžè?ß÷)//çÈ‘#Äb1‚  ªª**¹ZH_ošfÑeçwÞÐe©B!„B!„B!„bè9è$¼ûîÛÊwìàÎ;ÓÚú o¼q?³f½H,–¿ŽoyæÀ£ºzëP?ŒS†a„… 4Â4Mêêêº\Ö˲¢À±æy¯¼òJ¿¹OÇÖÖV©©©¡¦¦†ŠŠ –/_NYYY—’«½ÕÞÞÎí·ßÎW\ÁE]„mÛ¬Y³¦ËvµµµÑ63.…§6„ cBéÍX ã€Ûœ!@Æ!„Œ'› ßWÁÇúúOñÈ#Óxúé­L˜ð›7_' «y¾ùæ6À?¾;<Í„aH*•" ècUUU¯‚ú6Ç£pûž‚”Ç«ÏG€ÒÒÒ¢Ë+**ú| Ë–-ãÁäk_ûZ”A¹lÙ²¢¤¶¶–úúzjjjX¹r%­­­,[¶l@ž!ÄГq@2!”c21üÉ9d,BÈ8p2êèè`óæÍLž¼ž³ÎZM]] <ĨQ{¸æš³»½ÝÆ?’Ô×Ïê‡pÒò}Çqp]— p]—t:Ý«À£a½Ú¶M,£¼¼¼èò¹sçöû1ô¹Çã@joo§±±‘åË—³hÑ"@1yðÁ£ËÖ¬YCuu5ÕÕÕ,_¾Ú>›Uß;Uõ.Ãn8q]—x<¨ç'›{gÏžMKKËQŸ3¯»'ù(LÓ,ê]tQ¿CŸ{<¤ÖÖV***(+++º|þüù´··ÐÜÜm§•––RVVÆÆ‡ú!!úIÆ!ÈX „PŽ5È8 Äð'çB±@!ãÀÉÆq`ß¾ç¸ðÂûزåmmGèèøs::¦sðàx|ßJwê ž••]ƒŽ–¥¾Kà1Ï÷}|ß' Ã(ðè8Žã`YMMM½ÚÏñ”Z5 ƒT*…뺀úÿ˜0aB¿ËIx,++cåÊ•E¥[ÛÛÛyðÁ£e÷îÝ@×r®'N”.{عs'µµµ466õÃbHÕÖÖâº.{öìêCéâDÔÖÖõCbHµ¶¶R[[˺uë†úPºu¬± ¿ç»víŠJ1 q:«¯¯§¶¶–]»v õ¡tq">¬[·ŽÚÚZéÿ$N{òù@>!s†2gØ®«¾‚ÀãÅ?ŨQÿ0ù³?S…5u™Õ xÇ;öPWW|{KGÃêGsò)//'‘HÇ Ã×u‰ÅbÔåžH×uI鯙=0MÛ¶ë~ãñxN$üà?è÷9A¿·Ür ]tQôµbÅ ‹.Ó_ÇcÍš5,^¼˜ÒÒÒ(²ÛcÆŒ¡¬¬Œùóç÷{_BœÊJKK©¨¨àì³ÏîÿÎÙ@gŸ}6]úÓ qºÑ+ÇŒ3Ô‡rLƒuNП¾ÔB 'N¤¢¢‚3f õ¡ôÊ@cÇŽ¥¢¢B>ˆÓÞüù󩨨`ìØ±C}(Ç4Ÿf̘AEE'Nê‡'Ä’Ïòù@™3”9ÃîÊpCH$ÔÏ[¶\ ÀìÙ»˜1c—_ÞÖå¶/¼0ÊJõs:­2(Ú˜ ™ìÛ1/‡“ hjj², ÃÀ²,b±UUU8¹ÿ„x'±@œîJJJ¢¾('³Á tàQˆÓþŒ|º~>ÐG!Nwòù@>!s†2gØ PŽñ¸úyÊ”vÖ¯‘Q£ÎãàA¸øâ±lÙ²‹dòrÆŽ}„ .8Ýö¯þêò(¸XU ùòª£Fý™LߎI/‡[‰VÇqÃ0ÊnH¥R$“Ib±Xô˜GŒqÔ>zÛãQÌ]ºt)=öX¿ç úx¬©©éÿ³Y ¹¹™%K–PQQçy=®.hnnî@”€¢ÃŒB±@¡ôf,q@ˆáMÎ „ cBÆ¡äûêûgìæÍ7?Élcþü›ùö·²jÕu\u•ªœ±oßwyå•ÃÑíL“(ð*cR›0áàò~×p <¦R)âñ8±X¬ #Tihhˆ2 µººº.ÛJ$X–E:îõ1X–…ã8ø¾Ï‘#Gdò€õxllldÅŠQ¹ÕãµlÙ2®¿þz–/_ÞíÀ¡WtnÛØØ()ÐB 2!@Æ!„r´±@Æ!NrN „ „2 ßÏ ÿîï6±mÛOñý&¶mû<ºÊmeåˆÜÖivïþ@—Ûk…±²©S&™>ÁCÏóð lT*E&“!“ÉDý Ë¡º®K&“¡¼¼¼ËóaÛv·AÆ£õyL§ÓÇtÔ ÃÀó¶flk»ÏSÇáгÑ÷}Â0ìñ±8ŽC,‹‹UUUX–…eY444àº.Ùl¶W÷Uxav L¦R)lÛ>f/ÈÎâñ8©Tª×Çq,}<¶··³dÉš››©®®¦¢¢" 0¶··GÜÿýG >êcÙ²e]®«¨¨`åÊ•ÔÔÔ°dÉ/^LII ­­­ÔÔÔ X-g!ÄБq@2!”ÞŒ21¼É9d,BÈ80ªªÔwã ‚€;–ÐÒÒB@&£“ Jªf³PYY™»EѾÂl»xÿŽê‡8àÂ\$6•Jaš&ñxœ Èd2´µµáû>A†!¦i‹ÅH$Ñm{›ýiYV\L$444ÓétŸ2IMÓ$ C‰ßýîwûý|ô9ðX[[Kkk++W®ì¶ñê¢E‹X´hË–-£¶¶–;Ç}ÕÔÔôªgdII «V­Š›ùóçËÀ!Ä0!ã€d,B(½ dbx“s!ÈX „qàD (L¥TàqÆŒý”——3wîOpßWÛXV> ¨bŽG€J £sV^q¶£aLú0¶}9=T'=©AÐ%°g†aDWß÷q]ÇqŠz2êòª±XŒL&C<Ƕm|ßÇî= ˲p]7*Ù‹ÅH¥R¤ÓiR©Édò¸ö§ÕÕÕEÇØ_} <¶¶¶R__ÏÒ¥K» :jTWW³bÅŠ]]p´ûBœdB€ŒB„ŠŒB±@!ã@UU©,F€]»vñê«¿ç‹_Œ†7ª|j2©z6¦Rp´v‚–¥J­f2ùíTPr5¶}+™Lߎ1›Ížð­aây™L†¦¦¦¢ë2™ ADÇdš&‰D"Ê"¢@ îYWW‡iš†qÜŠétšÉ“'Ç£ûÔÌx<ÞçÞ™:S³sIã¾8£/7jmmTÝäcÑÛtnì*„B!„B!„B!†žîÉ‹élF‡ƒ’N§)¨žm§+|æÛ ÷¬«+Îv(¶mwém8Ø2™ ®ëAe@¦ÓiÚÚÚðuº²Î|<½¤8 !„B!„B!„Bœ\WõatHÔŠ™Œºü¦›Ú1Í|d2©¾LS]*9cÆêhŸ…/ÇÉ OE:“Ðó<,ËŠ²-]×% à©© Ã0Èf³Äb1€nKÁº®[”Ù_º¯¤çy¤ÓiÂ0ì¶e±ÇfŸóçÏ ¾¾þ˜Ûêmôm„B!„B!„B!ÄÐñÊôéŸdìØŠ~÷}•áèº*PiÛÅÊöö9]J|¦RjÛS™iš†Ñ%¨ƒ«ñx<ÊrÔlÛî6ãQ_7Ð ï+›ÍöîFI D!Á™}½aMM 7ndÙ²e,Z´ˆŠŠŠ¨Ÿckk+¬Y³†²²2jjjçè…B!„B!„B!ÄqÑCHÔÇaûöïmkš*ã±'ãÆmïr™e©¬ÊÂ$¿ÁÈúëݱ°×d†E={:^]ê´·=Oš~–à&ªÜê üwô9ðXRRÂý÷ßã8Ô××wÉ|,))aéÒ¥ÄãqÉvB!„B!„B!„8 ¸®*³ÚÖ¹ä½H&“aÒ¤¿b×®ÉÑe†¡¾âqL,”NÃ?þãã:Ôõ~,«¸ÜêPßÂ0Ä÷ý¢¬C]2Õ4M|ßDz,‚ ‚¨ŸcO’É$¾?ˆ‹~H6*ëqô9ð*¸XSSCMM E×UTTœ€gH!„B!„B!„BK¨ DÏ+A€išd2Â0äïœÀÚµ*¨hYPY©²"»‹³¹.<ÿü¥\xañ屘ʦìMÛÁàº.±X ÇqˆwjXéyUUU´µµc Ã0ÃÃ0p]—ºº: ÃèU&cO%UOj&F ½~î«}êñØŠŠŠ¢/­¶¶–‹.ºhpŸ(!„B!„B!„BÑ­ €Ù³U ÐóòåUƒ ‘H†!™L†t:ͨQ£ˆÇU ÑuÕv:ÆÖ¹dO,KÝlj ‰D‚ (n^hYÙl–¦¦&R©aî ‰‰D" Vf³Ù¨¯ã°å©Ü÷AêÁÙ¯ŒG!„B!„B!„BqrÓÙŠ©” BêÀ£çyxžGyy9–eÇ1 µ}aF‹ë.ëñ /$›Ív¹üD&&“É¢ŒÅB™ŒŠ°¥Ói|ßgöìÙ˜¦I]] ‚–ቊž,lT¿Ç€ïó8`B!„B!„B!„âäãû*ØXW·Ýö,¾¯êlê2«aF8ßWeRm; ì‰iö`ŽmmmX–…ïûX–U˜‹ÅÔ¨ÌÇòrõ³mç/ï­Þö„ì«T*E"‘T@QgoVVVÇI§ÓAÐ¥üªaQ¶çi•íh:ùŸ½¿ < !„B!„B!„B 3©Ìž Ž£2,X¨¨¾ˆ†at ¼™¦ 8žìÂ0ì’­©W]]±X Ó4£c¡Â`kr°££'X›Ëð´•9€úTjµ±±‘[n¹eHŸ!„B!„B!„BÑ•îӘͪŸ«ª ‘x²(ÈhÛv·A7¯ βŽÝçq¨drÑQÇqº<T´,«ÇŒF½MçlÈam‡;sõoMT©U„ } ËÊÊX¹rå>3B!„B!„B!„¢;:à†é´‰ãÄŽ#Ѝãr¾?ÔFI¥RQ ´¼¼œd2I,;fFûdMÙ ë|˜Yð|y¹¯ìÀÝEŸz<677sË-·ÐÜÜ<´OB!„B!„B!„ ¡²R•V5M•X^^Žeùø¾Ì fYª7d&“`5Çq¨ªª"‘HÐÐÐe,-ÛQt²QˆµP¥VPŸ2wïÞMcc#»wï.ºü¢‹.béÒ¥ÔÔÔœàgJ!„B!„B!„âôá8ù¬D- Á0 ®N]×+>Z½ ÒÙ¶*±ª[ž ƒžç‘ÍæÓòz@,ìTvÖ¸âlŸ2…B!„B!„B!ÄÐqÝâßÃR)H§óÁBß÷‰ÅbÄãñ¢ÀÝцêë‹åûDžh©TŠ ¨ªª¢¼¼œT*…ëºX–%AÇÁà Ü®ú”ñ(„B!„B!„B!N<×UAÁ Pýu.“Q¿&5º®K2™ŒÊ’ö†eå÷ÙËXå€ ÃÉ“'cY†a†aÔ×ñxúSŠ£Øê¨P,†.–ù(B!„B!„B!„§` ‚üe¾¯J¯ÖÕå/ ‚€ N¹€]:&›Í†!±X,ú½†Å?ëß3¨a’§¢×¾¯¾_‚„}º·.$ð(„B …'›B!„B!„bx Cð&“`­&¶U ²¡A½p’@ΜÙÿ|Å>í¡´´”¥K—õÓ'„Bœ¶Â°¸n¿^ÌÔAð›ßü†±cÇõÃB!„B!„ÇÁuUÅ+ÇQq¤LFÅ™LSõªªªÕ'1õáváû>UUUd³Y|ß' à •J2Ù™'5x4MPÌfó Ac1¨,3½¶¬|½^ÏàœIçÀ¹ý;„>kjj†úéB!N)º4jª¿ûýáöPs=•ÊWSè‰çyÜ{ï½|úÓŸê§D!„B!„Bô’®v«Àc,¦ºõŽçy˜¦I<'™Lõáöð<²Ù,‰DÛ¶©««Ãu]âñ8–e õá8ª¯â@³,5ñhÐÔ”¿,+ž,|}TU©mâiÎ|ùÌ~Ïìç®//^Lccc·×ÕÖÖrÅWpÑE±lÙ2Z[[‡úp…ƒ@Æ1é`¡çå}›T*r©/³,uÒ™Ét-¹êy®ëðÛß¶óÿx¯¼ò ¿ýío‡ú)9& „ÐóX 〧9'B€ŒB‚@UÇõݲTlI_æû>¶mŸ´AGõ Ÿ‘†!©Tj¨ëÄK™AØo,–AÒeÓ´Â ¤ø&áÌ=g2¶£UÒúx¬¯¯gÍš5ÑÏ·ÜrK·_½µbÅ š››»½®¶¶–úúzjjjX¹r%­­­,[¶¬¿Aq’‘q@ W: èû½/‹ZH3u{×Íï§°Çcwçžçñ…/l㓟læµ×fòÁÞÆœ9s†ú)9* „ÐóX 〧9'B€ŒB@-@×ñ#[,Lô<ï¤Ï4M˲°m;úyÈ¥^ÿwÑ'!ª×b pû¹¯Þ:VùµÜ$ã9¿9‡wüþýº«>ÛÛÛY¼x1·ß~;7n µµ•ÆÆFÊÊÊ())¡±±‘Ý»w÷ªd}}=]tµµµ=n³fͪ««©®®¦¢¢‚åË—ÓÜÜ>…§6ÄéÀóTðXzÚÆ0Ô e6«~•éyêw½Ú­óí=Ïã׿žÌÿxáê«?tÒe,BÀ±Ç„þäœ@2!dÐ\W-F×:Ç‘\×2O6aAé/_¯¢QA·@]fšƒQwô(\T¿Ã¡à¢²“œøà§Mׯ}_ßëÌÜ2³_wÑçÀãm·ÝFkk+Ë—/ïÒﱦ¦†åË—³jÕ*Z[[ioo?æþ***X¹r%+W®ìöúææfZ[[©¨¨ˆ.+--¥¬¬, | 1œyÞP-¿8qd§ºÞ”O ‚£oçûêúÙ³»–LÍdTȺ:`ÌfÕï™L¾odCüð‡¯·oGÔqàÀN,+À²\¾ùÍù<óÌECý”uKÆ!},q@ˆÓƒœ!@Æ!„Œšï«6;Ý%®ér¥ÉdòÄðŽ!•Já8™L&êå@"÷U®² Oèqûä3 OTÆa!ˆý<¦RH¨Ÿ«ªŽñ`Ð}à1÷ÿ²íãÛxøƒ÷ëÎìËZ[[Y³f 555,Z´¨ÇíÊÊʨ©©á¶Ûn;êv ‚ÒÒү߽{7@Ñà0qâÄÓ«µðÜsÏ1qâDÊÊÊúõ„ 1TÂ0Äó¼~­Ximmå+_ù ûöíê‡Ó­ÁöîÝKccã1ïGˆ¾J$Ôß鞪C„¡úÛêd±»·³ëv¹¦Ë¬f³ê¼"S÷§ƒ™†{öü0œ’»Ïýh+0—ÇßO]]>ú(øÃo1âäìup"Î º»½§“ööv6nÜȶmÛ†úPzt´± ¿çûöí£±±Q>ˆÓ^ss3»wï>m?lÛ¶ÆÆFæÏŸOIIÉP?\!†Lcc#Ï=÷êCé–|>bðµ¶¶ÒÚÚÊÞ½{‡úPº%s†jqºe©y îdr©étz¨µà˜=‚ ˆÊ¿:Ž€mÛÄb1•ñ\¸îåëNl‰Ø|Ì¢q'Zäî;ÖÏ}ÅbPY Ž£&URÕEeZ2MˆÇinnæ™ÖgøÓ„?õëú”ñ¨›²VWWsÛ믿žööö¾žû÷ï§¹¹yX­n§‚îgc¸ªª*\×Åqž|òIxà6oÞ<ÔgH¼ñÆ466ËÆÒbè¹®ú Ã|éÓªªâ…F¾7n#ŠëïwÞç©¿÷Ý-ôòýâË3™|™XLÔµµµáûê~¿ð…¼üò Ã±,‹ƒrøð¯8ûìCý´púœ`(ÏK„8ìÞ½›ÆÆÆ“:ð8˜tàQ>ˆÓÝÆillgè8jž¨§¸¢ã8†‘/a:D|ßÇ0 R©TT6U“É$†aPYYI<WsÛ)TàÑ„±ÎØ¡9èªÜ«ƒÊ¾ Vîb䃂º“.‹j’±°/S6›¿Þ0ò“ˆÇ§Çàcuu5¥¥¥ý>'èSÆ£þcÜy@iii—?Ôz›*aÔÝà'å‘ÄéÀ÷}‚ À÷ý¢f¼½QWW‡mÛÑíþâ/þb¨N¿È8 N©”:ñÓ‡;wîä‰'dݺ÷áº#¨¬A*UÅÍ7oÂqòç»vMf×®QÀ°§÷³e©ÛäªPDAÎÂ&â…AÈŸÿ|,ž§³¢3ìØ±ƒgŸ}ƒ… ?ÌUW­=)N@šŒB„ cB‘±@1ÇßWsP=õv•x‹õ·^ç@«ÏìÙ³1M“0 £d€xGÓÛÛ¶:ÙÌd2˜fþ¤óðáY€*µ qêëg1aŸð}?*ÑÜŸ±' „2!@Æ!„"cb¸ñxÏÙŽ®ëâûþ.6w]— p]—††Òé4At µ,+ʆŒ˜¨R£^¯î®gaAÐnòdÕ÷PO¨é@de¥úÙD•zôôé97:?Ö4ðù˜“UB]*¥¦F~ÒPOÃ`âSOõ{7} <–””°téRV¬XqÔàc}}=+V¬ˆÒ3û«ººšúúzÚÛÕ¤íŠ+())áúë¯ï÷¾…H*ëèøo—Jå{Ãél(Mg;\×ͺWØR—h5Í£q>È8 :K¥º¾_‚>Oq V<¥R©\ÏT˜2åešš¸÷ÞYÌ›÷sçÎåöÛ?išX–…mÛ444`Y×\ó-b1µ éС‰\uÕÚhŸ¾ïG‹tV£.¡jsQOœÅbª×aKK>+0W¿ƒ >þg¨2ÿ@õYl:AO–îÝ”+1[dI Jš ©¥÷eSZ,ÆøçŸgâë¯÷k7}êñê…ÓÜÜÌí·ßΚ5k(++‹VèºðÍÍÍ”•• X}äšš–,YÂâÅ‹)))¡µµ•ššš.½&…8^A56ß}÷›üÝßE2™/ƒ†a4Ðþ¬ï[÷ˆÓqBËRYN…+Y‚ ˆÒÔ5ÙÔ]ß7}_šišüèGbšÇÎT>™É8pêÈ÷U!‹©ûÈdò‹~‚ã¨ãÎdÔßx×U߃ Àqf̸šÝ»òÚkŸâÉ'¸‘ ºßŸeY<ôÐ;ij‚7ß|€Ñ£æž'µ",ê1Íœùñø|^|ñ0ý×ÿÅ_üÅW±,UNõî»ïà‡?|úúY@`òÄ÷aYóçïÇ÷aüøçsÏY8l²5 „2!@Æ!„"cb8Žzþ«;aRUUE,#9P“bÇ)“ÉJ¥8rä®ëª¾9±XìØ‹áëPý A•ííÚùTJM†w7ו«@Ö£lV•\íLu.RÈAJ&Šû4>`Â]éürÒR%_¾ôl¡£=ϦÉî+®àO>Ù¯»ès౤¤„•+WFY¬X±"º¾´´”¥K—ö)èøüóÏ÷xŸ«V­Š[Ο?ÿ”8ÄÉ£s¯?yäÒéëp]ÀˆÅBÇÁ²’¬^½‰ŠŠEi掣ŽÙ¬cF~ƒå˛ٷoÉä%E¥¨ƒ ‚hw]—‰¿ÔcàŠK+¾øâ,fÌ?ÔOw¯È8pêÓô >ê@f"¡Þ³©44¨ë ÏcôvG;9ë, Õñº®újj‚ûïßHSSžw ©TŠL&ƒeYøþ4æÌYF¶^PP8^Mž¬‚š6êŸu&cqß7õÇà‡?ÜBؼüòvíú?‚¾ó^{m&žëÖ•téÓ˜HÀìÙ*hùøãocäÈ+¹ì²Ëغµº(ÛqÁ‚k£ûkoŸC"aqÖ®½¾èø‚@íSõ‡ËJJÔíèÏ!DÏtÆ`¡cŽ ßkš~Í'jŸUUù¾É¾Ÿ¿iæß»:0™Lª…C–¥Î7&O>úñ¦Rê½ü¯ÿºŽ†—xÜ¡ªªœL&CCCɤ:Ëhi¹ ª•öÙgsÓMWF¿ëEÝUiP׫¥Z™ ìܹ3×ì;¿ˆÀ4MlÛÆ÷}\~üã=˜¦ÁêÕßTÙÕŽŽw³wï¨Ücö£FÜÏ>;šgŸËÎ×pð`>›ùŸx7“&µÁ±W— !„B!„Bˆ“B"¡æ«Â°û6a’Éd¨««;a}uÉT “J¥ˆÇãý :B×>‡1TàQÝY¾DYáD<¨IBÃÈ÷H²¬ÞÝ_¡ç]ØÜi"SO¡%PÁÇÁt´CöªA¾ÿÞ–µí£ < ÑW¾Ÿ/kÜ×Ûë@…>øþÑ:+Jo£Ç°0T_©Tþ˜ô¸¦¯³,¸úêM$ðÝï>Æ’%;pµýúõ/1jÔZzõë×ãû°oß> aß¾qQÐÑëô Uv•Guõnî¹§„‘#7pß}[X°`‡åëÖÍd÷îs˜5ë2@=ŽTJ0õsR•œtYÖñã2ø#¦8¹nñûîXïCèZM Ô븪*TL&UÆq,VœAÙР~¶¬|2Ôv:ø¨ð…÷òÀ›øèGÛ¹í¶µüÏÿ¼L&ãðÿ¸ˆD"A"‘ ‹ÑÔÔD,ömÆÿ0ëׯˆÊª~þóÛø×ý›¢ãŽÅzÎì4 ƒ’’CÌ›÷³Ü{2 “Yïû†mÛxžÇóÏdóæÍ$“I’É“'ïâë_¿±c;;öQöî]‹çyضeY¬_¿€ùó÷3iRD'×]7È—[n=…B!„B!†]A4ÏW+äº.¦iv[Út0A›·Î÷•t;gôGçÀ£|$—©ãºÅ“„™ŒºL<ëêÔÄa_ž‹±ìï&úf£J­¦¼à\ˆ*3Ûý˾ðn>ùɯ²fÍÔ2ظqÄó<¶lù!7ß¼Ÿ 0€9sڹ暯†I¾ûÝOk×¶FÑqÆ{ŒmÛ¦‘JÁÅ7žÛ·ãùç¿È¬Y—å‚ ‡ÿ7…K#\7Ÿ¦„ìÚ•O÷Z¿~2áĪ8yéàüñ(ìè8ê½jšêä*/^ºn¾Ü*ä3ãñ|IÖέ ;—Pö<¥Kż‡çŸÿkfÎüÙ¬I[[Ùl–ºº:’ÉdA6£ÅÞ½ Ä9çœ+pxüñKŽ{EÙ•WŽÌs& h&“—³nÝ!lÛŽÊ­666rǶmÒé4mm“°,øÒ—^dëÖj>üáÇ£À#øL›öm&Mjcÿþ³( <Þyçû¢ÌH!„B!„BqrÓ•ìššºÏvx±Ç+ê¸à‚/Ç)/‡1c>Ï“Oþ)Thbß¾í@&*£úË_¾ ð©®>ƒsÎù gœ±PŒw¼ã£üâÏ1iR–åð‰O¼›©SßTðäsŸ›Ëäɕ̙óY~ö³báÂWéè˜ÎŽ3˜?S®|j±˜ÊÞxàMlÝúî½w mm—GýÝTÜÃ¥ºz+œ=Ô/q Ó'B:ÃXÿÍ4Œâ÷w&S¼ É÷Õû;•R¯WýžÖ·ÉfU…„Âs ÃÈWKH§óÙ ~¶,˜;÷ FŽüG|‚gŸ}˜ÊÊJªªªH&“¬[W¿x€·¿ý ?ùÉmlØp.ÄqªzÝûð ŸfÞ¼G¨«ƒ––®Y”úXãK§ÓŽ=Θ1yë­†júÒ—ÐÔT¼ýØMÓIJ¼.µóuqáÂK¹üò¶¢ËôýJðQ!„B!„âä¦ç¼»›wR×'¢ÞŠ'¢ºUee%¾ïS^^Žã8TUUaÛv¯çÓúũɿÂy-ÝWéxK®uçš8Üš_Üëæ'ØA•;õP¥N2èw¼ý(mTTÑÅ*»:ÐAÕN$ð(.QZXâ´0è§uV˜fqÏG˜ÐÙˆ…·×cLáø£³°Òé|¿7(î÷¦ßß–•¿ïoû¾ùÍMŒ5ŠÉ“_â‹_ü"ùȧ()y#Gš˜5kãÆ‹¦ gŸ} »víÂìyk5€IDAT0 fÌØ¤™4éË€ ,<ø S¦Œ¤¼|66ü‡¿ÀèÑïbîÜw1vìŸ3eÊu¼ç=ŸdÆ)\rIq@ððáËØ²å,Ëâ]ïšË¨Qñž÷œÏ‚ïcòärêëgq|_=k×®eÛ¶yœ}öüñ³sçf,Ë*è•gs燙5ë©¡~yˆS㨠LFýlšù2ê¦YÜçP¿‡ ÿ^WU©×i2©Þ‹®›ÿ{^>“±^ؤï_/4‚€ €7ß|“åËÿ‚5kÞÎÚµWñµ¯}˲ˆÅb¤ÓiÞÿþ#¼ñÆhÆŽý*|H°páA>ñ‰é½~Ü••#˜?¿1z|ÝÛé”GSWW\&ãŸËÿ8ËÊ—í|îVx.’í\š|&åœ9íxÞˆnO<-Ë¢©©iÀ^B!„B!„bàè*€ ÝÏ/鞊---]¥†ªª*²Ù,Éd’t:M6›Å²¬ :zG¹.žû2âjBM3 õ5Y¿5¡97†jÒ³s6§ :DàÑóò •ÃÔ{ITéW¨€c!·¿A$G1à‚ ¸§bá8 ƒ|:€¡K¨êmt £pî¼ðzj®ŽÇ˜x¼8øQ˜=¤/×¥VA]7yò.ƌنmÇH$\qÅ…¬XQÍÛÞv6¶ W^¹ŠÍ›¿Èu׽ݿöÖ[o,Ë¢¤¤ Æãq~úÓ ^{m17ÜPÕÂxíµ™´´Lbÿþ¼øâ,ÆŽjãqõ¼ìÚ5€û?ÿyâØŠ=5þÎa×οcÞ¼1Ñãô}0Î>ÀÆwð®wæ›ß¼„믅aQùÖt:-ýÞÄqÓ¥TS©ü{._24ÿ>ÖˆA Þkú<( Õ6uuùŒF½ÎxVå…‹ïW¿_õ[G_¿oß>ÊsÍM›Î¢¤äZîºëã|ç;_%NGåHãq›I“ê8tè^°í€ßýnÔq=þÁꓸbÅ…ÑXdj¼ê|7…'›ÝÜ^fF·ÇiF B!„B!„'ÇÉÏkwÇóqê Ã| Ï÷U†“îŸØ]ÏF¸Ð=õ>@½Ç 1ø~>Ш³úг© çÓõvÝ¥¤ö|T%YC2™ »w…÷¼§•drF´­ªxìÝ{=àóðÃcÆ Š2_|qíí†g„ ̘±šË/oá‘GT°B/¸`š??ü&÷ë**?<ÛVûß¼ŸØuû ·oÿ&þ#ï 0oWöÖÕ̸ñFB î£ k䦕¾Éûß“&Á3.#1™ñ°Ç™{×Fýñ\÷ƒ´?s1Vø"Npô2âôæyů0,.“ªßÃ--ù…uuê\ ™Ìg7×Õ©÷µ.k¬Ëû¾Êv,¬Ž`šùÛé€~ç×h,Vœálš0~üA~ùË/†!¿øÅ?ÿÄÚµ·EÇøîwg2~èCó Ãù¨¿Æô)gš&á@”púñö©B!„B!„§]í«§«åååø¾ßm%¬?ŸÊÊJZZZŠ.×=ö΀J’n>cÈqòÑW•X‰êq¨c‚xŒ¡‚y¾¯&BV-,Ž €V¡z.+[PgRè>R ¾÷·?¦‘{|ÔTg%*y¼Ù‹ƒÿR’ŒGѳ — Fõ‚È0²Yu¹ç ³—b1õ³nè~Ž_Ü K0êàC*•/¥ jŒéœm]¸ŸB†¡Ž%‡º:“É“'³cÇ&*¡ºúœèx;?3gÎ`Ó¦E×Çbðê«¥€‰eYÔÔ”°mÛ Œ>pIÑê“ø•`Ä~ºq#}m·Ä4ó}*­Oc½o"ußum îÁ¿Œn›NCfã päF‹üüC xçu/cš&™ ¼cÚ<ÞEй»ÄO&΢²R=†Á‹‡ Ö½5&¢;úu­ËŸvîs\¸@@÷fŒ^¿ýU¡¸¤qª÷ne¥z¿.²mý^Ì¿Ç;'ôélç'žx0 Ù»w/{÷Žâ’KÞ†eYtt¼‚e•GÇÇ>ïèKI˲NÚ>‰±cÕ{B!„B!„'…TJÍ›%“]çÅÇ!ÚÚÚtn* CR©žçQUU…ïûŒ1‚ H&“]æÏ,Ë"ÙSd´/‚îK•ùàA"Ñ53AÚ2¨¬Cu0s ºw£î¤÷«'6 ™¨ hÌ.8–îè̬ÊÊâÀIçýõg ¯0[ôx3'A,™E*òÔïÔ ÇÝ»­0€¡ƒ¦™ÏŠ*/W Ó$ÊÖÓïóÂÛëËb±üx¤K@j…ý×R©âw],0kV=ùÈk¼õÖ;Éf³<ûìO¹ùæýÜtÓlúØÞ|s Ó§OWr×]|úÞ/ñîéÓóÏÁ¸28r„-÷ÜCËäÙ„ ÿ2Z¸‹?ê*8rD¥“¥Ó—ÍŠþÐõÃ4Í(clÒ¤¶\0¶ŒÎüÃá_1fAIt¿†&þùA,1ÃëQ§-ý¾ÑeRAe%VU—7õ>( .¦ÓùêP¼Ð¨¡¨´¯ö'“Å @]§K.»n÷Ç Poßwð}Ÿ­[Àg>ó ÃÀqœèDH¿æËÉZ¢¸»A!„B!„Bqòs]5¿ÖÝœ–®ÖǬ·bUUa†!¾ïGU¾<Ï£©©‰X,Öc€±ßÇ  A ‚ŒÏ{pkZMêžLÝ-¨·Q=TÍ„E÷…ÁÎL¦Ó¤|މÊμÒËÀBè4ÏžJ©`G,¦æû{êÇéqôàeo¨ìKpsÏÍIT°M¢[:3±»÷˜ïç³ {´;¢¡Ùüâ}½îѪ3ò4ÏSìÌf‹3¨Òiµ¯–uyK‹Ú×Odß¾}¤R)2™ •••¼ñƹ}z8¹H$˜=;Á}÷UóòËSøó?¿8Z%rÿýc0 ÑSÏSûCxÏ{Ƌ٪_$¹Á1•‚×^ v^+¤RøG.àŒõÿÇùïy kú?T?¹9Ÿù çÜ0ëªQÑsTdÕOHCƒúõX;鱘ꩾãŽkhhh ]WǨÿøhV¨"ÂÞãg« O¨'¹¼œ‹_ye¨_bb鞊Pü^÷ýü{M¿!×C´ £0“Qß;/:(dYêõßÐÐóßX}>aš0fÌF2™DtR‰D‚ë®ÛÀ;ß9ÏóØ´©‘«®Z‹iæl…¶“4)qÐ èŠ3!„B!„B1è|_ÅÜzª¾™Éeþ Ô¼OQ1•JQWW‡iš¤ÓiR©Ô€7»p]5—>{¶ d2jÂ🲰±àÁÛvÏM.Ó¨@›ÇÀeëõ”›cù,‰Îåe3Ø’-tÖçÑt.Y­ƒ9:û*‡O|bzîç8–e©Ò—ûWC*…]²®àÆqµÒ"£lûö÷â'α˜z-ÖÕ©÷sCC¾Ü1¨çúu¬‚~ůíÎ?×Õ©/8Ïd2Q@Q׃·,˜4éHÔsuÿþÕ¸®ËäÉ“£…†a°fÍÞóžó ‚Ïóøâ_ÍíWg:æOŠNÒ¤ÄA×—lÌ0 yø®»ÛÑ1Ô‡/„B!„BqZé<ß™çyd2, è8N4lšf4ŸdYétz`«}…aqï¦0TŽMMùº²ã;=.]±'º¼h•ÝçÒ?=eê‰ÒL&ÑššT`ñwYØß¦U¯ÅrT0±°ã± ä¨û¬ê2‹a˜Ï<Ö¥WuÔwä×¶ÂzÕº«Þ®°×ªm«ýÇbù€ÆüùûiooÇq¦LigêÔgyùåd×®õA@SSétšW_}•qãT`MÒjŸê >pÍÄl;¿Â"'Øy6™­Õø¼ ®¹ÿå)„¡:¾×^«x[›`šš°?3'7V&£cÖ‹2zZ‰RlÔãÐÑÆ"Û.Nö¦ÿl6 vÅ›êɼòÊü킊Ӓ穗}ç>¨™ŒŠ§ë÷º~ë UUùmuâÂ÷ë±z:ë aáb€T*Å®]¿æ‰'¤­­’’‡hkkãÈ‘#$“Ilj޳–eáº.a]Vø]ÛpäºG?“Š÷æ‡!Žãà8?½ÿ~žÿð‡ù̪U\úÄCýð„B!„B!N+ºê_wUÂÂ0$‘HL&¼¥Ž8¦;Ýñ€VÓ CõuÉÄx\e(ÄbÅÁƒ¾0P½ T`-Ó÷]‘Eìº>Iêx{“¹h¡²1MTðÑ¥÷åN:ÁT?7iT VrÏQl<ÁeX%ðxK$T@Aýâñâò‹±˜t¹UÓT17…¨³ {µ–ÕYɉ„ºN;:oó¶·íÄ4ußVŸÊÊJfÏÞEÂÝwo‹²¡¶lù!lÆó<ØÌž=ÿK<Ê©š¦I,cäÈ <ÛPÇÂÒRöŽÍÜÛo‚¦ _ûó(k1ª+ ØIuPæ_]7Ü@xp|ñª=8 ø*àbFûÖå){Z‰¢³ÅÒé|¿È£Å :{-÷dN˜¾}ûŠÇq¥ÜiÇóÔß|]RU {þÝ××ëm5Uê·ø­Pøžs®T*E{où¾çyQðTä¬Y³X»ött4så•#£ûÈ¿_ó+¯€¢šöúºá˜ñ8{öìhÁ¨úûÇäûj‰nV›³á·¿¥|ÄÈdx×]waš&Ï?ñ{[[y쓟dݵ×õÃB!„B!„8m誃Ùl÷½‰†at öGyy9¶mx ³‹LFÍOA¾ŒaOúK ¨ÌÇÙô­li%Çî³Ø›lS#w,qòY†©c“ÉÀfÓùÈ‘üml[ÝβÔܵ&èm«ªÔï…åU}_ý¬A¿No«÷çº*0Læƒiû÷¯æÈ‘ø8ãÆý3;vìÂ0BLӚضí–5ƒ/ù6&Mº›­[ŸfóÏ~o¾y?ñxSQfÀe\À×q+ÛæÍã{›6Eƒªmƒ•þ T®Ê7®Í)Ì@ÔÇy̱¸¼¼Ë~Ž¥OÙñÇ7 åžä{wCjb¾Ñlpû§,Á¬û064¨ïzq.‰¬³›c±ü{_Ó ²Ù®/ï råNÕ‹)•JE+¦%Â0¤®®ß÷£€£ëºÄr©ÁøÀ…lÛv«Wßȇ>”ÀÛ¶aEHÃ0Š2û:%O¾ïcFÔœ;“ɋŰ,+jÜm÷°š C&OžÌï~ücJŸžË/¸€øú×1M“»ÿüϹuõjÏšÅW\¡Ô¸ºqne¥º,÷ÿô§?¥ èX¾œß_q·íèþ¯¼òJÞ¾gÏP?eB!„B!„§ ÓTI)ÝÍ»®‹ëº´´´ È}UUUaÛv475 ‚ ¸´!ä{9õª:Ýgö– ¬él¾rT¶ßñ$ñ äS’Î}T厧5otº/‹Ïx쎑ûªË=/',ø(ÇaDg1ë@¡~Ÿë²¥:à WS45u½½ï!tà"•RßuPÑ4UPB_¦Ç’ÂE †eeû˜9³• ˜C<»v}òò†\0~ö³/àºcX¾ü«455aYwA®ïl%®ãœsvSYy)uu¿Ä0 Âð~îš7Ëu‰Q<ž˜—_ÀˆMð£ë®ã}÷Þ‹kšÔôDìöÁ玿Ç\T¢SÇ£ñ®‡*¢V(¸¨ÉD­žÐòHggY˜¿XùÅRpîžsþ˜ÅÓÊa˜/ý«{5ê’ÆA bVza‚^Œ†Å/e½ð »sÏóÃx“ÉÉd¨œ=›/ÿÛ¿‘É-œÈd2|ñÕWyúºëXð× aÈÿ^y%ëÂt:M&“¡åƒdzs3Ÿ9’’††âÿœ††ü€]ð¼|â _à¾Õ«ùø¶mL»ýö¢ã¾öÚk9ã )| „B!„Bq"èéäî*xú¾•Xío¿ÅÊÊJLÓ$õsŒæ²¢lXavƒ.‘ÖÓdbw"9FÏ•ë f‚|™ÑcM`uÙ.ÈgtV¢²MÔ<•©Ë´ž(±‚çåX™ž@f‡ ÝÑ0T`±­M}×=c1 ÔYN™L׿µº´¢m«ÛÛ¶º,“É2ô|¶Î¨ê\ 4|R©™LË‚ÖÖgøò—¿Ì;Éd&“ͪw~yy9ååå¹Û]êV›@ÒôIš`f2<'謰giþTàLØR¹ZíMMMÔÕÕÑÐЕ°m;*»jYVTÎ!ãû~®‘5E'A…:—“ˆu>N\¶£~ÜUVVâ8UUUl|䜪*â†Á·_y…ŸnÜÈ‚™3iiiÁu]*++™qãd ƒàËuu¼vï½d2ÊËË ‚€ßlÝÊøçŸWƒõ‘#üþ£%“ÉàyMMM,¹ãVM™Â3gvýÏÑÏ_nÓ}!‰õ³fñÑ‘#»”€~ßûÞǶmÛNÈs(„8ùèêB!„B!N Çé>‡% CªªªˆÅbý*±©TŠt:M:ƶmÌLFe+Íž­ª÷éIÂþÒe;-‚ï5îçµûBgõµ æÂ«€¹ï^·éKyÖã=&UÔÚPÎÂyú¡t*"JÆã)L—R •ÕÔÒrôÅ *»HM³ë¼µžÃï¼î2»uOȲ²Ç€wùÆ·¦iâyApèÐŽIÓÔ”Ê AÀÛœ?>û, MM¬_¿¾¨Œ¢^þQsè‡.¹„©Ÿû– O?}9ï{ßašÓi,Ëâ¾›nbÎM71£àø ƒÇ“J~Ì,p¸k ß°±'™ÜözÜus·5àyô¼ªAucZP«!,òêÜvzU‡þ£ì;¥ÿósÇ‘QûøÓ„?õêùCK/°,u~Íÿõõ®«ÞÛºÇh¡lV½ç»ëǨÃðè/å ¢ ¢~ÿAÕ›ï\TïÅX,†ëº$“ɨtªeY?«m»[Éeô"“¸»`äñÐAßW†êgßß'°í(púòªU¬ûá9oï^:::xë­·xÏM7‹ÅˆÇã¤fÏ& *ªÃw¾ÃÄÜcÊf³„aÈ®ÿû?hkcÌäɼ÷¥—øÛ9sÈf³xž—Ë-çʺ:.Ìý'Ϙ?ŸX,5ø¶,‹l6•­Õ+³sp½Bζí(ûÔ ‚.Ïñ„ ¸ôÒKûõ !NnAÁÿëÁ¼3ÿùÒ¶Õß•3öÓÖö9~üãg†úP…B!„bXÓ ?Én2í*++1 ƒºîR!{µï€ÊÊJr“ƒºmÏ<ÐeϪzŸîÇ}Ï Œr£ñÜ—Jî©DÿR¨ùv=èõiï}œú¸`p³-Ox<ÅèÌ¥ P_ ê÷d²wïïX,ŸíÔÝö:ËñØB<¯’LÆç«_5iii¡ªª P%ƒ  ª¼XÏ=Œºê*f]v  V"AÀTÓä‚ à‘¹s‹'Ås+;¦Ü£À§>5«8=8ü¾÷qéÂ…‡mÓ§àDˆ|¬Üw<,G mª:@ b…AD5ÄPƒZçd©LÁþõá¥r÷[—»Ì&_Z?\‹|ðRgAV嶵ȗcM“Èb¹ûÓyøÞñ?%âÄò}µ  Uð?Ë—LM¥òÁFÛî¹.<äK¯êóËêºÉ0ò—…aeË…a}¹®KØ)5& ã–;mhhˆÊžðt”õµ|Äñf<ú¾OUU?ºï>žÿþ÷¹oëÖèØæ½ù&—|ï{Ø¿Ÿ©£Gã^.³3‹û›¿!p]vMÊÛßùN:::ø§»ïÎï<ÃÉeov7¿üe&W¥RÑ 4ý|t~~mÛ¦²²» /c†TVVÒÒÒB†¤R)âñ8†aàû~ôÿ¤OTu¹Û¢N!Ä)O/Ñ}´™¦¦#<ÿüxÊÊÆ1kÖ‹<þø¬[·€’‡ø`ýíÌä_ÙÇ>¶g|þ•VþcÛø3™0¡t¨’B!„B K®›oYÖÒÒu/•JAŸû:†aÍ_Y–¥Z ÞÉÑ2('OV™ } êÀc_ô¢ d¿X¨yö:ò¥XsI9$ù¾…O:»1•Rƒt:¿@¡‡v…ÝÒ¥X{š¯Oöm‚Çqð}_s™‹mmmÌž=›ªª*|ß§¥¥# ± Z€cÆ0糟UwZ¨®.:ˆ—|Ÿ³{QëK•eìäèv¢?ÞSêbùÚÏzùƲ™ÜíTv¤~YòåZ esûšMq&¤N-7Èg<:¹Ë|NìjqÜt³ç©ÅHúÜ ¡A]>{¶ B65õ®dº.—œLRaØu;ÛVå9uùTÈ(SQOt[–e Í`õaÔÁÐÂ÷úÆŸýŒi7ÒþÛß2rÃî\¼8¯6|ö³|aút²†Á”D‚3ÿð¶oNÎÎß·ËgÌ`×K/ñØw¾ƒcY¤ KÀZæQR¢“Éã[ª¤K^ê.;[—©Íÿš455EÙ™uuuxže—êÿ“ (//zezž¼ñ…8•èÊaò·ý-‡ÿí0OŽzÞó ~ÿÌïÙËU€Á¸qett¼›qãÊøÐ‡Vóê«É+¯¼Åe—½ÆsÏ=|„;Î^ÂßõGž?ø<ÉÚ€“p˜týõLÿÅêãSY;r¨®B!„B Ka¨æób±î«& \×%›Í÷‚qÏó¢êƒ¦iRgš*†päHïv¢{4Åãù*zj^ÚCÍmë°ú´Ô_ODŸC#w?iÔ<û êsx:“ÀãIÊ÷ÕjËÊg8&“ÇdìÉÑ‚z~Ûqb±†aD .“èºn¾|b’¶,®•\ŒÊ64°#˜ß]à¡à Ž™µä|×A¼Âž‡:ï»Û…¶‹¡µ ù¥:`çæöcänkä®O¢Ú ù€^6÷û½–ÚV_®yäÙêÌGÝ_Qg86å¶+Ïý¬÷Qð„|`²³Â FÝ ÒB š…’vÁW"·íÎ^¼PÄ åyjaÎb¬«ëúwÛ4{p,¼ ßFŸÇè>¦ibYV”=WK¥Rø¾OCCADÁ-Õ£qp ‚…åAuÍxàÀæÍÜ;r$FŽŒ¡‹zˆ+7l 4MþøÆL¿ã¬‘#ñ}ß÷¹2g¹ç2uÇCæçÒDuÆ£6 øù¤IÅAÇ^ˆlB¹X¨»€¦ïûd2Â0$‹e•êÿ;0özð^ý"oŸù$«w¬f´=#4XpíJ—ðžä{ÈŒË`[6ÿµð¿ø"_ê§H!„B!†ÝÓ±sUÝÒH·ª—çy„aH<çãóæ1cÉuE2ÙsfQwæXpoû€‰š¿6ÉÏ™'È'Ô$QWÿ/M^¾ Û©¦0)O2º¼¢ï«ØmwM ŽãÇ ‚€L&ƒã8QðÑu]¢‰ë«÷ïçÍ»ï&–É@&CÌ4Iöx3Íh€³û˜ðQ™…z†-Ž "êLÁ8jÔH=ˆ‡ä}¯ß¬³CT¦ äk>[¨§UÎ4›ûYB#È õ¥ƒ•fî8 ç ¯FÁ6ùÒ­úûlTó[£à˜z«°¤*7‡ÕÁÈÎe[ïß‹A ²ãq¨ªRßm»ç²©Ç™T¨ý-\x×ý ¦iâæ 8ŽSԻѲ¬.AGP™y:‹NŸyž7°¬ P: ÕŠ‹0„tšòòrhÿíoY|çl))!6uï¼é&¾r×]Ñ„½• ÓäšÜnçôñpúÓÄ»?º;Éì®Tt,‹Æf=nw.»¨{l:¹†nÇ›‘)„褰—2eö¶Hlk»œ ^`óæ·±gç™ü€¿áL²dyut)/¼õ^žæCl;<€ &ÖñÒnUë%“YÏW“Ó™7yç˜óiþîÕ*2w•͛ϗ’Ïqó#ìûÅvFM˜ÀÕ—^ÍÕº|¸üÚËÕvÓbœuëYÑñê1Nß°aÃP?»B!„B1ì¤RÝÏíû¾õtL§ÓÇtÔ‹Ï«ªª¨««Só=¹y4â}¨]:Í‚;ðï¨ùãÂé£òÕó<`µŸ( X‡‡ ¶µÕÅE_â´&Ç“€ç©¹vÛVAËRÒ`¶ãÒ™M:Ðèyžçáº.ÿ:s&¼á¶=òSR)®ºê*n¸áÖýîwð£AhbXvœãÏøqQƒ—vÖ…ä3ôtyR­…|-憂mõ!è:˜×ùÐŒÜuºÌj5°êF¯U¨ÀcC§û켟Âãµrû‹wº\³sûÓ%W ÷Ñ9Kq þï“*k̈$ªÜ7ç>îôîdÏž=t¢/|ßÇ4MªªªxÛÛ¾õ`Õ½õõ:°åû~ ¬ 3ÿt¦ãq½ßsË»¶=ò“.¿œ³/¹„Ð4£Îÿ°{7³êëØRRÂ+_Ìß——G“â_úá™ÙÔ„ã8ضÍj×Åž7/:žÓ~îõb]R£s0Ø4ͨ©¸¢otÕ‡†°oÏû6·^}+ÿòýáú½×3qÖDÞ¶óm¸.ÿUú_ÄÎO²oÄù<µé#ìÞ}S§¾Á{Güøês¹ñw“0&ƹæí¿dL8†šé¯QzÖA&•Mâ‚·WòÖߢỗ¨œÍ§ê1yýxàKp>¼ëéÜÝØý~¢ð—ŒüB„³$ãY!„B!N¨TJM‡ÅbÝ—WÅb=ÎÃu¿¿TÔJèÓ§ÓVØKÍ0útè°aŠŸOŽ 5qé8jÒÒ¶!i«yóÐTA‹Q&”šù²¬>ùŠ…º˜M>iÔ¼·Iñ¼wá|¸v$ð8D|?߯±pˆRª…tŒ.£èyÉd'“!Èd°k/&ÞÐ@UUÉd’¯än;¦¢‚Wþi,W-hÍg†€gsåWžVƒKÈB܌牅ý!¹Î¸Ó©ÚIÔSžÛN_W˜Â’/Jn{ ìœ ê’O È÷Wì‰î…Å©ÕIT9ÖÎÀc „qò†=é) YðÿuÆ…g0mß4:ÂŽ(Ààû~ôDå1u¶W,‹‚šîÉYدäÚ’^½nÄà‚âÚî™XW؇Ugâè2œ–u ñxœx<Žçyd2™(©Orô8ÑEAÇÂ,E`ßöí¸ñFJ®½6zƃ€ý<‡©ÚK–*¸Ï¥AÀœ9sø‡+˜ré¥üÖuiÈM”———ÓÔÔ¤jÕ玵»,@ѽÓ10{Âè^¾Ó¶tÙ›Ÿ/û9ïþê»ÙñòÌM&SfMáÈ™G˜6mÏ~oGœßñAöþú ¶ú>>ºçbžô —ïœ\Âîoìæ³  ,ëcê|¿ ö$uþ‘ø[Æ}9€É€æ›sçJ@öÆîÜ»cv®¤ƒÎ$ÇÕØ†ù%·zä’ÙB!„Bqº õQ«¡¡¸õQ†¤R)Â0ìuµ­D"eY,~è!æ®ZEìÐ!øà.céˆ /€:ŽúÒA‹Â…¬†Qü{O±Nd¤çú ƒ“ ¨ ƒúö}Œ—Š“ŸO0ÇÉg8Æbj.h ‚A¸.[Ÿ~š-[¶0mÌ6?þ8Deùîºáâ‰q`߸q*@ð¯ÿ ¹IýxÁêˆ)œ3þ#PÁA™§W0$s_:P¨ƒu*(èTt_ÆÕÏÐÏ]ßD>ÛQÏ}é}¥QƒOoƒ…H},}a’n¯îÓ󼨛.wYøÿ‹ÅRªŸÝ³¿{–¸gáì…êò ˆ²Sõ'ufÛ6aF$˜©¬¬Œ²ÒŠê„‡6ÒÜrË-}|rÄñ Ã|°ÑóT¹Ô––þíÓ÷ý¨ß¢þÀ¶mlÛ&Nãº.™L& P'“I,˲¬( ©WK†QT¦³H¨/ßWÄ4‹VQm{äÎüÖ·5jäÙ7Þà;MMŒ++‹öÄãÌÎdhiiasFå ô}«ç)ì’Ém#ÄI#@ýí3Ég²‹!§?Üò<íÛÇqpëx à'O?øó¶Óì¿›‘g·³gÏïhoŸÃ¨Q{Ùµk=Û·—&“H²‹Ù,-y‘ÿq&žéñû?}”ÿï̀ݭÿ¿ÿÖ«ü±}÷üçEpq ç\ÂìÙ­¾{Ö‹°õk\þí$, ˜ÈD àCg&£‚€Ùlñ7ÓTæ,K}ï<þÙ¶úôª¯ënì. D(5}2ZP_!„B!Dÿù>TVªm…õ<Ï#‘PåûŽ9×¥ç{mÛÆ0 ®¼î:uE,VÍì¯Îsïétÿƒ…‡×]RçTl@·Ã’ûKgØÎ:I¥Ô ççy:Ï3éÔG|ÐîM^ KBv»yzôØrÖk´MjÃËxürÔAìƒÏ°{Â9¼R2–ëo¼‘Øç>Gee%ñxœÅÿï³Ü¸zÿ|Ý/X°xcÍÜþcwãù>ŠàˆĈâúÎ:sQA]¯Ó§ ò=TyRºynêÈ—í\ Õ,Øw_Ÿþ®–H«àŽeYQ4à±, ×uI&“xžG<§²²’l6K"‘ ¡¡òòr²Ù,™L†xx_ÿ:_ïÁ®C׳ƒ¼£dÞ÷ÿH¿½óU“ªÃO°tÔD~Cî ~õZ~ôõ‘\›ÍòìÿÀýŸ1ÈPM|ÆjÒ¿¹ÃP‹JL÷uðs‹5~Uð@sµúÌ÷»~…cM³8ºz¬ŒÅ±Õ0Tæcgµµƒó‚B!„Bˆá.$š[÷<¨ªRŸ¥ ?ê% Ç!™L’L&t\wï½lXµŠù—]Í…?¾X<¦æØu¹%°ƒ|\Â$Ÿ(¤õ¶:S9*1èD“ÜÞû"@ (&*58‰*Ú¢.ó¼|V£îïj•íÃ|íì ð\ÿÂ: nŠçà§)Øœ)¾¯ì¨‚7§½Éö#ßåüàVþôÖÛ™zø]¼Î“|˜Ð1ö£¬[°Ž›o½™óÆÌË­¬‡‰¹ ǹ¸kÞ]üõ†¿¦Ä)á/ª¿ÊÜis‹K š¨ŒÆÂÚÌ*@X8§¥.œ·Ò™ôÒäK¢«Ôi©ò‘*hÛvQFaáåïOör?{žG,#•JQWWÇìÙ³£àa:ŽV•è}è,,˲H§ÓA@†Ø¶MKKK”qX˜e¨Bm½hàW82!fv-'ÙS‰IÓ4™={vЉ÷µ®·èßWóºUUù‰ý£.2èF†Q¹Ô0 £ìXýZJ悈†a¨;Ôؾ¯& s“ʆað›ÿwH¥Ôùƒãe*†A:çà{ßË[/¼À¹cÆÐ6y2óæqÇêÕ$“I‚ À¬«ÃÉõpM¥R4ÔÔH$¨««‹2,;ÓoPÙ‹¶m½¾{[NBˆ“Na‰:ò%¾ûQnUíXÞÁ>‚'¿}@]*sñ©lV­¦,tùåmÌ™ÓÎêÕ3˜2åe.|µk¯gÚŸ¦qäÀÂÑ!—Üû&¼6âgÞ¿‘g<Èy/ý?ÂÑ!m£Û88ò >ºšM›n¥¤d òŸâ\¿–ßñ>À…\ˆ•×&laëžQ<Á÷™™±y‚üÌËla»ØÅ£™Õ¼Ê ìc/>ŸŽ±gó*/síþk™¶ožÕΥό禳_fý‘õ|ìþñÊûyë¢'¹fË5À(¦>6›sÞœÆÿwöXûL®½°„_ÿÆÿ\ù?„„œ1ãBÎß6ŸÝ—­ekó9Ü|àV֞ߊñöµ”>±€1üßœ¿†‰¿ÿüÏoñwÿWxWœs-ÙÞñŽw°}ûëüì]Ó™øíŸÂö€?NÆBæÈ—±*'«±üÊ?ヵ‹0I›7DÏ»iÒ5ÈØ90hš*lÛ**+„ÝЋHzCŸöf{]ö¿0Ú0Ôí8{¨¶è/µ8J³PŸÇu±t§ë¡x‘±B!z',ø^XêÏmU•š–ÓÓoºzçy455å+Ò¹nþ³!€a¬œ·þð'®<ôÞ~î|¦yÓ¨0?Õõ¾õßõ\Ò6jN?Ñi» ×…ƒTüÁ+¸^·9 ŠAqÊkkk©¯¯§½½E‹QSSCiié‰;‡|yµÜIz˜_ÚFå/'îGlœO²Ü"ö&ÄÀ{F-‚Œ6Yð ¦Md>ü^øÂÛxþ²ñ¼¼vç5ÇÞÏÜÇùÎç†M7`Û6ÖËT©D?Æ…¹ùªq,tÂò™‚>*(š;Îø qÎÚtü>ÕÝ ¥é¸„M÷©Ð½U˜µX ‚¢@ Îö Ã0 £``&“!N“H$¢¾t±X,Ê,Ìd2Q`Äó<\ײuéR˲ŠzÙÊs' |è išQ°°®®Ó4i:FÃMÒ?]‚'2ÀÒÐЕWî†|ÈÑý–mÊ/ƒ°’7CÝí`U°¡‡ú#^ØhÙP¿¿øß/òÚ–×xhÁCìüåNfn™‰‡ÇßÌ¿–w·µò3çröÁꎾ“UMŸuùâg`_Ó,˜ƒÃ¡£tsfÓ» f:*sñ‡Ý?ÿ5Ûÿy;ûöí£nWši›ÃÆígñÎÄ÷É>ô—þv“š&Ñú±Vü'|¦ýt—Õ_ÆÂ… Õë݇üúL|jbñj*}ò¢ï;¤À´L̸Y<É¡³ºí‚ÛÅÉ/ÂÐÁÝ„Ú'ßÕ¥XáŠþÙÌÝžÜ}®üÒ“/FÁï…÷mçn[X½P÷N7÷I7·Ó‹9ôý¼Ä ökå~.Ì–ÓÙßz¹×r؃2„¨ÿûüI}a¹äD7·ñÕ¶þv? ØüÌ%¸[mÖôS¨¼QýlNóLx|íµ×ÈfÏ õ‘7(Û»=;ßÄÞk2ãŒý¬¿–³n7w9ÌÌý3±*ÇÓ€‹‡GŒoŒ~ƒ‡Î|ˆ…O.äÃSrdzö<.¹Š/¿ñe¾úç_åÑoðÊÞóøØžs™;z.c_™DÅ_.¤ô¿Î`Ê”‹øæŒorç¯î„­Õêöm—óÂáËØ<ïgì¾ôûLŸ>ÖgZ;ÿfž}ðA>\½_ÝWËU¸ž)¿z‘9Ÿ¹ˆ'ð$ïŸô~ÚÛç0ëð,¾žø:¦É6×åöº?#•ªŠúÄãq¯xÉ£'óÅþÄîOÏæÍ»·0oÚ<&MšIÛ;¹?öñ¨òÀ÷ü³°í‹sÕ ¦SU‰‰§Õ®¿¼8 >²0÷$Ì M*+¹Ûó`ùWU¼Ø¶¹<—Y=‡9êàÏ2êCàëê–ÉôK`MV¿ä>öª Cw‹€lûøV£ˆc:YÎ Dÿf^[V>H¦é8¾^˜¡3¸ o«·±¦n£÷«ÛÕ€ª"•Jå÷¡o§ïG'ëu…ë¼ô¢t:¿¬ð~LS]jMBee¾Š²^ ¦[/4ÉtZƒÚÔ”_ÐÖÝB½Ö!“QûÐ÷S¨ðvÉdþüU?·†¡CSÓ_ õK _†åX?ÿ,<_Õ Ï9!Ž­Ï]ue&«àòÎAÆuÞRx®éì«óg¿à+¤¸Kç@§>¶ŠÏ×Ë Ž òçÑnîr›®Ôº‚ÛÅsÛvž<-|Žº;_×ǪÏÑmº~¶HængtÚ‡~¼zr÷hÁÜ4ùªUú±é±,È=Ý¢T˘ÊNÿùÏDÿŸ îÇ_Ö4òU«:†)¼]È€¿ŒË ÜáÅÀöÜ×;`ò¥cÛ1–SÙ° „Ç儌ÿ@½×Ù`ؤž{ª*j‹åˤ:ŽƒeYjιøHs =„I¶Zç0böfÞ9“qSßSàÀûª™ö_ïêTþ´›cˆãwÈ—4µÈÏ«u&¹bœRG=p裶¶–eË–±jÕªÁ½c}Ò="÷{xf>àP9Ì)аÚ#Í Ä‚±&Üc©¿ý@Ò¿ Ó!Ϭ}†íÏmç·~Bõ@Ë}ñB¾§™uÃXlûJÚ¬¶â€Rá`aÑõ„…:ÍM^ŸÅY ]Þ³0x¨ƒ†©Tªè».÷ªK˜ê ¤Ú¶ïûQ Ð0Œ(kP—™Ô«Ct€Oï)ÃO÷<,ÌÔÁB}Yç ¡}ŠNZYßû$6$ã€Côá2ü[È|8Ÿl,†¦KÀ| Ø4÷úpa~¶lÓߟ҉+xyÊËü`¸õ¹L84Éd¹`Ä‹Lzº„±ç=ÂÔwO%ùÉ$4ú°¶F— YpqAÏÞÖ@[[ãFŽ£ãO윷“Ýß‚)/OaïE{ ¸ôùK9Òv-s8Âö7~ÁÚäü'ÎçŠ ¯à–›¿È9/_ÉB˜ÕÕÕ`Bæ† x°páB˜ó«ç='Nìù¹Ò³ñG –«†»¾mávú»Õö¶ nülÒ÷ ž.a¡÷§' ÷çwú¹ðw“|ª0¨ª·åö¯ƒ\z¢Pá*5=îwš¤Œn§KêE(zò#×ä{öã³Yo­ïã“1ôu,ð}ˆçÞlës³57'!žÎÿýÍÕSöÞ~~ÕÇŸG|!Týü-¾‚s÷<Õ o‰uæ.Æ_u>•?ͪñ#™°wÖàO^ÏúÉë¹ç­{ð¶> ÛlêV×ñL`/¿çâ+~Ϙc{ÁÅ\zí<~¿÷wŒÎ>ã ~ý˧™ýn“ÃfÁ•‡¸×{†}êc<úÉG¹ùæ›i\õMþìšÏòý ßç›7“çÞ|Ó4y1|‘××9`Àu]ê>VGêYõ÷ú°s˜àÞÇq¨š\Å›¿„©gfäøøÓ™>}:G>þqLÓdÜ_ŒÃ¶,>ü§k=ú߸Ìa ,p“`_˜N‡tqËÏ£¡¡Èÿ­¶Â¼o2ã5>ì«òôõLb¤R˜¹™}ÛT'bVáŸx\}õÔ³ŠKŸv.[ êS¢d"ž2†ì³Aw '„»›¨/T¸(¥pÑ =ìÃ$ß=Çßæ»Á¿ØæÞáÛs¼ÁtˆÍ„ÌOÀºH½´Ýo¿3¿; ÁC°Ì«rsÔOäö? Œ©ÿH,QÛÇ¿þ7Ôõá>õ=Y ì‚ÌC`Í„º$T}E-¼Ð²ßÌíàm…dت¶/ÔtT~6¿}å'Õ1˜“r·«s¤þ¬ ¹2÷ï#Œ÷ßêçØRÿù‚çígêv~½š¬ÖBøc Ö$M†àYàEÔyÝ.0[V°Æ»!|¬½j{c/˜[ýû0¶]ÆÙ`\vÙj`­`\öà©Û_ç’·Þbÿ¼kã9\òÞQwˆŠoòäYoñÖÿœÁoŸÈ˜«ÞdòúŸ}`Gæíãß`[Ù6ÎùÑ9,^ÐξwícÜmçåÏåðè‰ìÚµ‹€€ßêàÉsèÛÁïöýŽÔæóùÿ¦íi0¥m ›Íìÿþ|ÊJ ¼wPÞƒí¤ zÒya/\ë4ôpßv?ƒúlQE>ë!CþÍ ÏGõÂë´ÚÖ ö'Á Œk.„oÞá6+Á< xLUq •èœÖ6ÁË@ð$Ø×‚ó(Øç«©’ð`^ æùàåÖ>Åog5ð]@_vxWBpØ—çž®6à×À9¾I2c ØéOAê>à;ÀAàˆZ$j¾nã!ySn›ÞvCº2 Ü ±›Õý¸|Œq`L‚ô6H½¨®KRÿ ,^o'$ÏPã–û¨ËbAeç"WTzêÿ$w;Ô¸jO…øUPÕyeP™ v&Ïÿ%ð¾]¼Í_=‹³_îÅ úätJŒBœ$ôœ¬®º5\ ú8ð‘üÊ…½!\hÃ,(Ñ&lø&8ç·»Yõ¿æçËÎU£®âÇ+ÌÂñ ÕüÏݳ9rƸèCÜ[>“%o[—ëâÜp× Ìúñ,.]øOƒ“LrzL‹“Ј#GŽêƒè-Û¶£• ­­­Ø¶ÍòåËY´hQ·«­­¥¢¢‚ŠŠŠ®WêI‚£L „­NjÃ?ƒÌÔ„¢:µÚ5 sóVW™6<“Ä÷ý((Aô{á`®Ëê[a?¿ÁP˜aèû~x ‚ Záº. TVV’N§q'Ê4L&“]‚†PÜ ±©© ×u‰ÇãQbám,ËÂ÷} ÃèÒ“Nœ8·Ür +W®êÃ蓾Ž]÷Óü؇9†Ê"ÔÜ79ð¶ægƒï!óp<µòðêG×'rNp»?w!ðáGMù@o/ˆ"Te`FY2æÈ—IÜ9S ë¸øü |ìmçòËÛÙZö4 ÖÝ˧^|‘­gœÁ›ûÇð[Úq0ùõ¿fù'–³hÓJvmáÌàÌw¼ƒ𳊠–þÕR~µôW\}ëÕÌûÄÅìŸ1ƒmÛ¶awϛǎ}(ú[~Ó† œûûß3eäHÆlÛ@*™$GsÉ“‹Ÿ€XL-ÃÔ<¯ûô˜ÂE8UU]ëòî# UÊ>‡1 u?…çuÃkÓÌŸ8u*+ÕmuV`çóÇ隺$AÂ~;êyòI®ßç·Ý¦^—ù° Ü•.~¦S*ËB[­lÖ/ÅÔº°­`þNÿs&á…`þ„·®ÂÛ5Žð­3àŒ±0u ±w]…óm`Ä?¶Ô×;ÔmsËBcKÏ'øÁYdv=’S×Sù»Ë‹%[¨K&Á_‘›|ŒQ» â&¤~”@ÝRHüGñÉü\ Î|˜Á{2wå$`b.À÷Ïê÷ø?ƒ—{J^?ûu»4äƒgð⦉쟼óÒm¿›Æ™{^⌷ÞPboýh{÷îeÄÅë™ûôÎ:rgž©xû¹ãh>Š9/Ïà÷sÇ{Ÿœçø7žç©Kf1íõ fì˜AˤÎ;øÆïx•±cÆòÖ[o1îÀ8>Q¾O½¨ª»¬ž±š/l~…³ßÊ—Ý4qON™Àåmê¹|êœzþæÅCL>ðm£/`ò—¨Ÿy‡G\ƈ—FðܾçXÌ:®à :è`ãÃ4.e3ñܲr‡FÎf£h§G™Î·ƒû÷0ŸçföG×ÜÆ(®æVBB~ÍÌâÅèX?ò\n}K'-%$äÑéâ¬_Qôÿ÷Óis $=z4Ž}”%¯oæÊ¶ßmó­Ò1ލ±òWÅnÞÄÄCOåïçmÆè¶•¼0ánÜqcßÞŒC¬¯cAcc#ÑíUŠž‹å~+;MIdÀZšÏ¦Í­¹)úS¨ÿäêó“ÂþÌA¿^wf蜫¥ÓP^®~N&Õ¶ž—ÿÓ®ÿlëS†#G`Ĉâ}è63Ž£þŒëìb½>Öó ­MVèûìîO{áñÕÕ—œ/|Œ»víâ¼óZ¹æšKxàìÛ·/Úæ†¶±zõŒ.?kÓ§w0}zë׫ó¤›nz™^˜À™´=³—mm“xß_¿ÅÓOŸÁøñ9ï¼½ì{ê)öï=ɹs«}ûöñò9[ÙºõBÆŽí`Ú´mŒü}ñÚþQÓ;ØUR®]ê6óÆ=GûÖs}àç†!Û¦NeÔÜ7تsžiÓ¶1ºå‡öŽâµ›¸úoÑ1v,Û¦Mò‚Ëêë‹îgýäɬ/8综­Ë;µ{Y=cÛÇË?GÛ¶1½£#ú}û¸q|üx***¸ûî»ûô2jƒ2gxŠÓ嵃@½¿ôÏú”\Ÿ–fûw×'^+‡ôéº~¿üæ7[¹÷Þ‰d2jð¸þúVî½÷PÑ>:¿ÿº{žþvŽiË=†€;f°{÷9EÛ\qÅV|p!o½õVÔZB›4©‹.z†—_žÃŽ3˜6m'¾ÎóÏ_ʤImÑ{òª«Vò«_}€©S¦£c:íís()Ù¸qçÓÑñ ãÆmgçÎk¸ðÂûxñÅâ*r“'¯ç­·&D·;óÌ=´µ]Ξ=ïàÌ3OGGÓ§‡íÛ¿\~y[s•eôíÔˆ|¬±c›Ù·ogµ‰7ß܆ZR‡úŸ!Ÿ"®åV0è•Æ¤P+R ?Sé?Dº×VH~E³žTH1zômìßz@7s¥ßráÝ|ÙTOM ø™›L‚wO#S6?z_mßþÏüã·þÀ¹‡Îeç™`¦ÇÔ7¿e6Û?¹Ã_>̘Š1œ»ê\²Ù,®ë’N§O‹ªuâÔ4çɧLÆcss3­­­E'¥¥¥”••±qãÆ£ëÖ­cÒ¤ITü~ üÍ*O˜­+:Ñgi ¿­àðtü·Þyþ(‚9‹É¬…Ø!yþ&îüŸò, 'a<šS9x<ú3èÛó€Oø…Á#-øhf}ÊÆ”ážqÁìû öŽÃß=û'ncÛÈdv†mÄ“>[ŸÞJëËûÙµbÞŠ$sì Ã`ᥗâ,^̹çžË;ßùNþcút^}õUlÛ&‘H`7— Sß“¹Š:óTV®ÎÖÁzýþÒ¥Õ?´ð=q:‡Ý{âXæ µ«rÿ×FEñçÖx4Ïhæ™Ægø§^àq Î ¦}îQŒ§Ó bP•VÏYÁR,'aêÃöº=Ăկ1eÊC¬_?›iÓ¶ñĘ»Y¸žYûUÝêø›Éó9묳¸lìe<:v,#®»ŽÇÏ>››nº ï¿þ‹†tš÷—¿ŸØ´­ý‚Òñã;yã^}•‰3gRRRÂቇ ì€Ø 1ÖÝssnº‰À÷1m›[{ñÜèwyô7;·¾ì–[naåÇ>Öµ ˜mGÛô¨¡áè×FÔ_¶çëÅø“+yÚ£ãì_|B'”O"ÃnüëAÏ ø˜Oyp¨ eþã}>ð~§2w½}* f¶œ‡ñ8?Uë8’©«Iýé}xä3|³l'1‚õlÞaò膑0.™ü‡Gæ¹÷?Æî}j’-8ïi.œ7’‰£örÉä—ýúëüqË쪞Mõ®ÉŒÛÁÖ}ñ»«^¦¥¥…kÎ>›Ž±cùÞË7æJg¼òè+|ªdŸ*É?¼Õ‡gÚ6rñÊŸ=° *ݱ££ƒŽŽ* ãª[ÕG¢ù5,0ym~ÿFµM¡Êß'|fWÁÇ:msþ«Ó3f “'O¦íÉ6^Úº€WÆŽå¥#h?ŸÿøýÎ9çÚÚÚøËWJyã1êÿgïÞãã¨î»ñ ¶±Á^1æbÀ(À#)@™$J)ì›\HÜg¥´O[¬<ÕnIÛ(ýUÍn/øI¡iwµ“6<;j£Ü^-Ò¶¤¤)ˆî$i.lÐØ€Ìb.Áh¬µÁwôûãèÌήvW+íJ{Ñçýzé%i/3gfw¾{v¾ó=gÅ ,_¾'ObüŒñE|Wß|5|ðAüíÊ•¸øä«X³j ;Œ£«WãðáKñÅ ¾ˆ¦¦&LNNâ…u¯ãÀذa^~ùe¬ÿèÿ†ñë~w¾öµ¯aû¦kðÄÄϰjÕ*Ï`bbé÷œŽoÿâ›ø¿ýܾ½ñF<0:Šk®¹ßúîwqóÍ7ã\û\üü²ŸcÕªUÐÞÔ𧆧žz øÀð¥/} wßßà·n½±q1üO¾ñ üŸO~üàñÌ3Ï`Ó¦M¸ü‚ jÚa¿üÜçÐóÉObàÑGÑsíµü3þÃçÃÛ?õvçBÎ/¿ã6ì¿àç{ªªÐõ¿G,Ã`x›~öoh÷ùð{¿÷{øÄ'>H$Û¶±R}–eáB\ˆ¡O½¦ùNgT™@ Ÿïíè¹¥·¢þN2V$¼3 týÿ« ù3C¶™@_æ‘sa[ œhwþ:Ì¿¹Æàý8`Ýÿ ¬'/V…yb#"_ºá^'¦‡õ½ôY˜/_û˜(ô­W€Ðb¨Ü(Š> _(sÁ ù3t­]†Ï|æ¸âŠCxÿû_ÅÉû9~~üH§Ó8û¬³ðÖé§ã¢‹Òxþù 8zô(¾ñÇÿû{qôŒ3p€Uǎᇓ‡pò²)œsÎ:¼òʼý‘¢ó­Yã¬ë›ß<]]â89xð \uô%œ³é¸“d{åäÓˆFíé„¢†}à§øÌµ‡²vãÞŸ®Åá+œk—Ò?H£ç²“øåÿìÅ5§NÁ‹£p_ÕÞ.ú-adçg;7ŠÇ¸GfõEsb€¯¹þ·ltå円²ºx€nnÆßœwÖ®]‹C‡á—tŸÉ1á^ÙŒ‡=¬X±O?ý48yRŒÎ0íéµkñ¿.½Tĵ‰ ¼ø¢ûÄÎý§NÂ/¸÷­Xn¸¿øÅ/ðá•+qÅ/~5kÖàèÑ£X>±ú1=âì³ÏÆž=ñ‡¯¾ŠuÏ=‡5kÖàðÈaL\vþyï^\}õÕH§ÓxþùçÑuHìûU«VáèÑ£8ù¶·áG‡ãÃþ0þë¿þ [¯¸kxo½õV®\‰åË—ã'o½…© .Àe—]†‡~W_}5lÓDKK ÆÇÇñîw¿÷>û,N;í´²Ëj(7œ7rø’!†µmà ì _ž~‡úÜ«{]ï“Õ*ðÍì?ÌC€Ö˜¿þYËUo¹Ɖ÷Âú  ¶jË£xð«vV÷û½¡sñÃh\õÞ_â‰îÁ/ÒoÃ[SS8mÙ24Ÿ±k;žÀw¾ÿA4¯8Û>z'þ9~&O-ÇcS¢òñ ?ÓG/Ã㯟w®}לö= NvfµåÛ¿„ÿØó)ÀMçŒbyú^>µOO‹ðÎeÏ<‡Ÿ¿,¾^^žþÔ,xð<øÞDá ü4ú4ÖcûñkÎ:Þ†_â½C_ÃjìÂ&¤ñÿ¢Ø„58€Vœ~úéHã,`Õ¾qüG¸úÔ~4ö-œ·çÃXñÖëx}Ù°q6N_¿ÚÛpæÉ3q•g=”cûqäÍó€eÀ9Ë^ÇÂÄ‘q¼ïÅ­X¾b9®|²«9†3NMü2pÙþU8zÁ‹xûkoÇÅ«±êúÃÖWßľ—u¯N´A]ö VIüåË—ãüsš±çW.ÇÚ{V¼µü%ÞþÃ70µòGø Þ•§±þÆnìÙÿ*~i­Ç—üî?ô(Þþò>¬X±PxÛêóðÌï^|ó.ZûL^}).ýþàÙô•xîÔ¹xî¬sxgÿuíÅØðÀ!\²2ˆ§nú”o~Ë–-Ê+à]ý,¬_û=˜Ï6cù“‡ðööû‘úå#Àîïc2F“Çuí%x±ïÃxýoÞÂEk?w—ƒaX/®ƒubÌãðG͉ëÏü.°Tûì~ñÀ¿Ã~c¡ß´H@ähU@W0 ‘pGúULNþyä¯aÛ6º¯Îûï¯bõe›`©*öÝú ÞõIF#£·…‘ø·FÍì‘ü*­¾ 6¹ý¥z."WÝ$'''`Æ›®©©I$Š8~ü8žûÿÞºC*®:í$Þ¶|9Ž5-Ãh°‡Îû3?~-6ˆ‡Ÿÿ àœ•Oà¬ÓžÇúÃcìÇÿÀˆßo¸_txàžuë°bÅ ¼NcâÅqî¹çbùòåøÄý‰>ýéOãŸøþüÏÿŸøÄ'ðÅ/~Ÿþô§qã7âOÿôOqÑEaíڵػw/ÚÛÛq÷Ýwã«_ý*î¾ûn‚W^y·ÝvŽ;†3Ï<¯¼òJÖ~mkkC2™¬ö[#Ëþýûñä“OV»‹nrr²¤×âµ×^s~êQ9qNœ8öß:&¾-ëïÅþÓßÀ9¿x/ü&'»°"ù8Î?ÿGxùå÷Áãy¶màäÉ×pë­â«íþ'°nÝ:x<LLLà}ï{ŒÃ‡ñÙÏ~øÓ?Å_ÿõ_ãOþäO°¦¹{÷îÅ™gž‰'žx‡ÂE]„ÑÑQ¬[·\p8€M›6áÀøÐ‡>„ƒâK_úà#ùˆÓæ¶¶6ç˜|ê©§pæ™gfýž ‰¥c.¯õ“O>‰}ûöÕ퉅rû¯Ýõ46¾ðyœyúïcÝoc¹ñÎi÷áÉ'¿#G.Ä9çü)ŽkÃáÇ!'.zòÉ}8~üU´´´àé§ÇñÎw¾©T ×Þt¾Õ+×´´à¥—^»Þõ.Üýè£ØpÛmXqß}8yò¤s¼ÿùWÿk×®ÅE®ãü$€ ×YÇ;®¾Ú9ÞË}?ONN"yæ™À±cÀ96ž|òIìß¿ÉÅ‚Rãß›o¾‰çŸ?þx]~©+·O099‰oÜ„_¬ý¼´rÞxc%Î<óLœÕÓƒç!ªÊÔ`Ï¿öy¬Z5†©©),[¶ gí»§¥>‡ënÀáÃ)Ä#ì«Clø~;S;gßCÓÜþS÷é¸öÚk±wï^<ñÄÅxqÿ‹X·n¾ñÚ1œqÆÀ!àØ˜øûرcxíïÄý?ý)®¸â üŸ§ŸÆM7Ý„ïE£hmmÅÄÄ®Z³‡ÆÑ£G±jÕ*8pS]Ã0p×]wáŽ;îÀÇo¾‰§žÂ%—\‚C^¹ürÜtþùH¥RhnnÆ÷¾÷=ø?ÿÑú'|ñ‹_DøÓŸÆÿ¾ãà®»ð™Ï|£££xo[¾ôÜsxóÍ7ak~ðƒàöÛoÇäÝw;ßwR·ßŽëò+¿‚—^z ]t6&“X³f ®ºê*¼ôÒKܹwß}·Ó¶Ï|æ3h¿ï>ÜxãØ³gÖ_t¾wýõY}¨[o½—ßw>ö±á7ÞÀ©[oÅ—î»íííÎzÞÿÒK€‹.º/½ôÞÚ²¿Ü³ë6oÆï»¿yË-ð®Z…k®¹¿û»¿‹ 6àЯþ*N[+ª+§ÂæµkñÛW_ UUáõzñÌ 7`êÀ‹›7c•׋g7lÀï:„µÓÏ94ýwÛ¡CXyÑE^=öŸq¾øÅ/â•W^ÁC=øãÅØ²§ïÝ‹µk×âí]ä丿ûÝïâ$€¿xè!¼täþbú9ò¹î¾¡|·µµ‰¡ð¿ô¥/áØ±cø‹¿ø <õÔSøÒ—¾„'Ÿ|Ÿþô§qýõ×;Ï“wÿÝÖÖ†}ûöa``÷ßUŽår• üqüÞãïÇ‘¼yÚ›xöT+6Å޽ü?<õÒm8ý‡ilkýüë«Ùá¼ë/?ŠÔÑ¿Â[o½…ï|ËÀožƒ•'Waý²§pìø2¬Zy];?‰õ«nÁÑ/ãá!ÜŠM¸À&Ïøç¯[H,Ó…*Y—é>9]Õüè£â'`óš58~ê8–Z†ƒëÖá÷ÿ ´´´`ïÞ½8rþùØv4…UX…S§NáôÓOÇ¿<¹Ï'ž:týùÏ‘<óL,{iÞxã <±y3þ?s:;;Fqûu×Á÷è£8ï¼ópèÐ!¬Zµ ñÅxâÈ\z饸ŸÿùüqK NûùÏqÙe—á¹çžÃÅ_Œð‹/âÃþ0öîÝ‹ææfÜ8:Š'N`ÕªU8|ø0Ú?úQÃÃøêW¿ŠO|âøý;î@ô®»ÐÕÕ…Ç{ _|1ÖŸq¶¼öš³Í¯½ÿýðýÍßà“Ÿü$¾ò•¯à“Ÿü$ð•¯à‹_ü"FGG±víZ\7:šuæöÛoÇéwßÛn» wß}7VüùŸãº»ïÆí·ßŽïÿû¸è¢‹pð¥—pD\qÅxê©§ðú­·â«Ë—ã—¿ü%®¹æ\tÑE8ó¥—p&€sÎ9W_}5^ß²÷-_Ž[o½÷ÝwÞ¾iNíÝ‹“'OVû°ž—rbÁ¡C‡0òoßÁWžjÁ©åkðÖ©)ÿ6>øo8Œ?Á98†³ñ,Nâ$¾~ןbËŠœ:u {~ü=´¥Oá’·¢iÙaœþÖqlþ÷úç‘~,—ß×íÞ8”Éÿ©µ—àø‰ãHµ´à¹Ïã|ûñÈ#àò®6\ñÙA(Š‚ÃoÆÊ+qß{Ö£eê$®|óJ¼züU¼cùÿàäèW±fãìß¿ÍÜ€¿½ð üïwïGú±4lm 7ù,?µ«W­Æ‘£GðÖ{oÄSéqüÆG›‘L&ÑqíÙ8ûçÿŒs7œ‹ƒbùšåøÁÛ6aù凱vM3R‡SØöúNK?ŠßV~„§?sÚ¶ào–¿+âÚþÓ÷aëþg²×óŽ‘´Ào|ü7¾7÷^{6Vîþ66lØ€Ëì±zÕjüàÔ>{Û¸ôíÍøáá>Üþ,'džéÑmÎhÛ‚w?ŒßøøoàÙÇS8sõ™8´v6œù,.Ÿ^Ï›oÄîW¾‡«>þø¯dMob¥çGذa&ì <½j5~°ÿïq¬iš}Íxðp 7žÿ,NÇ>\¼rVœZ³Ö\…ûFv"ÐÀØ‘1|ûËÐúêÓXõÖ*´­Z‰8‚G×^7Ò?ªö!½èqçLÃ+ÿ ú‰íhZæÇK§7áz^¾ápúéçbjjSSgOŸ'ˆãé§wã´Ó6ãÔ©Sðù|ø¿ÇŽáÐ7¢½½]|Ö¨*¾úÕ¯:ý4ùm!¿Ÿ6¹°F8Yïç"öíÛ‡'Ÿ|²ìs†u3Ôj2™Dww7öîÝ›u{ww7Íæýë_Ç7ÿê~¼6~>¬ÕïÁ‘#⬳öàĉ@SÓãäÉŸáì³Gqü¸8°nÝ:œ…3ÎØ©©)œvÚi8óÌW°råpúé›`Û66o~ããã¸æškðØc͈ çŸ><OÑØ ÿß¼y3^{í5lܸœ8ñÌ3Ïdņûï¿ßù?_<9÷Üs1555ãûÈ\âIîïBÏ)vž#÷9gžy¦ów>õÚY í^Êß¾ûÝï"Æž=;°fÍ^;v Š¢àÈ‘]X»ö8~ü°fÍ/ñæ›gà­·špÆgàì³Ç±iÓ¹xì±ÇœØàî ¼öÚkذaNœ83Žó|¿sÏ3Ê¿sûòw[[R©Î?ÿü’Ÿ3ŸõTú9—^z)~úÓŸâú믯¹¶{Ξ={°fͧ(¤–Ú6Ûs®¸â <ýôÓ³>g||gœqÒé4~üãWû°^Ô8===xmЋS§ïÃÃgÿ ŽÛ€•+ß@:};.¾øU:ôßøèG¯Âã?Ž|àÎgôêÕ«õ|1õúyåV¯ýo·z?±gÏQÅ[fŸ n*ËqÛm·á¶Ûn˹õWÜ.Qí&Ñ"ø—ù—<·öV»YD´ˆò÷ öˆ––?û³?CþË?T»iD´H<þýßÿ}ú¿«Ýœ,K}h.¢Åô¡}ÈubÕ ä÷ƒß¯v‰h NÆgªÝ¢ºWwc¬å+nmm­v³ˆh1ÀX@DŒD$0ÀX@DŒDµ¢nr|æÝ»wgÝžL&ÑÜÜ\íæÑ"` "€±€ˆˆH`, "€±€ˆˆjMÝ$ «« CCCH§ÓD ´ÇãÁ¶mÛªÝ4"Z$ŒD0ã ŒD0ãQ-Y6555UíF”*NcÇŽΤí©T }}}èêêªvÓˆh‘0ÀX@DŒD$0ÀX@DŒDµ¤®R2™´µµÁãñT»9DTŒD0ã ŒD0ãQ-¨ËÄ#Õ–ºšã‘ˆˆˆˆˆˆˆˆˆˆˆˆˆjDDDDDDDDDDDDDT6&‰ˆˆˆˆˆˆˆˆˆˆˆˆ¨lL<QÙ:ñØßß-[¶ ¥¥½½½H¥RÕnRYFFFÐÝÝ=ãglllÎÛ]ûfûöíH&“yï«Ä6Öê>(´Ý¥¼þòÚWZ£ms¥bA½ì—rbA=ù¶{©}TZ#móR|/Š•ÚÆZÜì4žt:ÞÞ^´´´ ¥¥Û·oŸqܵÛ××ëEKK ¼^/FFFj¾Ýét;wîÌZæBÅÊJ´½ÐqŸ»ùö¥ö/cëT,¨Æë9[¨Åv—*Õ®Jµ»œXPK1Š+%Ôêë¹}‚J·»Þú@þXP©>A)a¨¾ÅŒû‹µ=[¶l™ñ¾®‡mX¬>PØjP_øÂ¦ÚÛÛ§î¹çž©‡zhêcûØÔÇ>ö±j7«ìmºé¦›¦¾ð…/dý¼ð sÚîzØ7º®O]qÅS=ôPÞýPî6Öê>˜m»‹½þòÚWZ#ns%bA½ì—rbA=…¶{)}TZ£móR{/;&*±µ¸Ø'hLr??ôÐCS=ôÐÔ§>õ©©ööö©ÉÉIç1µÚ×}ম¸âŠ)]×§zè¡©;î¸cêŠ+®¨èûn!Ú-—ñÀ8ûü¦›nªèþ®TÛ‹÷;vì˜joow¶ã _øÂÔW\1õÀTtÿ26,ŽJÄ‚j¼ž³ÅZm÷lq RíªT»Ë‰µÓhv³Å‚Z}=£O°í®§>ÁÔTáXP‰>A)a¨ ‹÷s{rß×õ° ‹Õj$ ›x”'c¤^xaF®7wÜqÇÔwÜQöv×ò¾¹çž{¦®¸â ç'_G»ÛXkû ”ížíõ¯÷×~¡4â6W"Ôú~©D,¨Çcb¶í^ Ÿ ¥Ñ¶y©¼f;&*µµ´Ø'h\»wâŠ+¦vïÞíÜ699¹ ïÙ…x}?ö±e-sjjjêSŸúÔÔ=÷ÜS³í~衇fœ˜œœt¾ðWªÝå¶}¶ã>ßûD¾&ŸúÔ§*º^¥bA5^ÏÙâ@-¶»”8P©v•ÛîJÄ‚ZˆiTšRbA­¾ž‹Ñ'¨t»ë¥O05U<TªOPÊcªo1ãþbÐu}êcûØŒ÷u=lÃbõICµ:66†T*…ŽŽç¶ææf´¶¶b÷îÝÕnÞ¼¥R)x<ž²¶»Ö÷MGG188¸`ÛX‹û`¶íŠ¿þðÚ/„FÝærcA=ì—rcA½³m÷RøX¸ÍKå½P온Ô6ÖÚ~`Ÿ qy<ôôô µµµàcjµ¯›J¥066–µLصkºººj¶Ýr§æææ¬×¡­­ÍÙ¦Zˆ#¥|þwttÌxï´µµ!NWlÿ26,ŽJÄ‚j¼ž³ÅZm÷lq Ôu.F +7ÔJL£ÒÌ jõõ\Œ>ÁB´»^ú@ñXP‰>A)a¨ ‹÷ÃØØt]Ç]wÝ5ãöZ߆Åê5šåÕnÀB˜œœ€o†¦¦¦¼ãø×‹Ý»wcrr---Äd__Ÿó/e»k}ß477gurUbåíµ´fÛn øë߯ýBhÔm.7Ôâ1«ÜXPÊ6Öâûc¶í^ Ÿ ¡·y©¼Š•ÚÆZÛì4®ææfôõõ_L'''144„ÖÖV絨վ®<9ßÜÜŒ;w"•J¡¹¹]]]hmm­Ùv·µµ9íwWr{*Õ_(÷˜ší¸ommqò1Nã¨hÿ±aqT"Tãõœ-Ôj»g‹¥®s1bX¹± QûFj¶X OD×Úë¹}‚…hw½ô ä¾- *Ñ'(å1õpÞh)X¬¸¿ÐÒé4î¸ãIÔz؆Åê5š†¬xlTétÍÍÍ0 †a «« ;wîÌ;á85¾þ$ñ½°tñµ'‰ï…¥¯ýëïïGww7FFF°mÛ¶¢̵dûöíðx–Â6Ï'4Â~©Ä6Öû~XªŸóÑèÛ¼Tß •ÚÆzßìÔ>97ˆ[GG:::fT«Öj_77!²uëÖ¬JZlwkk+ ÃÀÞ½{±wï^ìÚµ MMM Ò_XÈcjll̹ÊÚ0 ôõõå=áľQí«d,¨Æë9[¨Åv—*Õ®…>~J‰õÓ¨ôXP«¯çbô *Ýnö j/¦Ñì3î/„d2‰¦¦&ìܹÝÝÝèîî©ô®‡m«Ô(2ñ(¯ôϘ3™LÖüC…ŒŒŒdŒR*•r‚M)Û]ïû¦ÛXû`¶×)¼öóшÛ\‰XÐû¥ÛXoûŸó×hÛÌ÷*ºõ¶Ø'¨_###رcGÑÇÔj_W΋”»ÌÜy‘j­ÝétýýýY'Òé4’É$ÚÚÚê*ŽôööbÛ¶mصkWÞe.žQ½ªD,¨Æë9[¨ÕvÏJ]g­|Ç* ê)¦Ñì± V_ÏÅè,D»Ù'¨Í˜F³[Œ¸¿ºººpçw¢§§Çù€mÛ¶¡§§§.¶a±ú@¦!€xS 9W~ Àãñ`Û¶mÕnÚ¼´¶¶"™L¢¿¿ß¹-™L:ã¿Ïe»ë}ßTbëm”òú/…×~>m›+ a¿Tbëi?ðs <´Í|/dTjëi?°OP¿¶nÝŠt:ç¶d2‰d2™5Dr-öueR»¿¿ßY¦|ßÉ!ÕjµÝ###Yû¼¿¿§¢í^ˆ¶»%“I¤R)§ Æýã¾jz©õêU¥bÁb¿ž¥ÄZm÷lq RíZèã§”XP1„RbA-¾ž‹Õ'Xˆv³OP[1f·˜q¡È¤›ûßk+ëÊböɲ©©©©j7b!¤ÓiìØ±ét©T }}}5?_B1CCCÎI¦¦¦&¤R)ôôô ¯¯oNÛ]/û¦¥¥ƒƒƒ3檪Ä6Öò>(´Ý³½þôÚWR#ns%bA=í—ùÆ‚z?&òm÷Rû¨¤FÛæ¥ø^ÈwLTjku?°OÐx†††°sçNx<ž=vâõM¥RèííÅØØZ[[166Vñ÷ÝB´;™L¢··MMM˜œœDSSvíÚå iTkq$ßqßßߟu¢Ô­££Ã™¬ÑûF¤± ¯çlq VÛ=[¨T»*ÙîùÆ‚Z‹iTÜl± V_ÏÅè,D»ë­OÌŒ•ê”òÆê[̸¿˜rß×õ° ‹Õj$ ›x”ä¸èmmmu3éj1étÚ)Émnn.XŠ[Êv×û¾©Ä6ÖÛ>(åõ_ ¯ý|4Ú6W*4Â~©Ä6ÖÓ~àç@yi›ù^¨ü6ÖÓ~`Ÿ ~¥R)gXž…>vâõ•Ë\È÷]¥Ûí>^rù•l÷B´}>–Zߨ^U*Tãõœ-Ôb»K‰•jW-?Ó])± V_ÏÅèTºÝìÌý1µ°4»zyOÖû6,V¨4|⑈ˆˆˆˆˆˆˆˆˆˆˆˆ^ÃÎñHDDDDDDDDDDDDD‹‡‰G"""""""""""""*DDDDDDDDDDDDDT6&‰ˆˆˆˆˆˆˆˆˆˆˆˆ¨lL<QÙ˜x$""""""""""""¢²1ñHDDDDDDDDDDDDDec⑈ˆˆˆˆˆˆˆˆˆˆˆˆÊÆÄ#•‰G"""""""""""""*DDDDDDDDDDDDDT6&‰ˆˆˆˆˆˆˆˆˆˆˆˆ¨lL<QÙ˜x$""""""""""""¢²5lâѶm†QífÐ<ض Ó4+º¼…|/†Û¶«²îZÞ/µb©l'e3M–e9ÿ3VëíãvQ9æú>(ôØÜ˜2—åÕcl¨å¶-åm¡Òä;^çò>(ö¸ùÄ‚zõо¥¶KQ%Ï TªO,­XPËmãv-MåÄ…rûóÁc¿¶-•í¤â +«}S *‘HL5ÊæÅb±©ñññ‚ÿ7Љ‰‰)¿ß?` À”¦iS£££e/w¡ß ¦‰DUÖ]Ëû¥V4Êvæ;î5”ctttJUU'Žx½Þ©‰‰ Æ"j½}K}»–J`¡Ìå}0>>>ã±ãããSš¦91Åï÷Ïiýõj¹mKu[ fW¨05Uúû _·Ï7Ôk¨‡ö-µíXJßâÜ@¹}yûR‹µÜ6n—°TúåÄ…Jôæ‹Ç~mk”í\J}„…À8PX9íkØŠÇFdz®ÈÉý¿Q„ÃaX–…‰‰ LMMAUUD£Ñj7‹¨&ä;î5”£³³~¿SSS˜˜˜ b Q½Z*}€j², ñx3î ƒPUÕ‰)¦i2¦PU0Ì®œ>@±80PmXJߪun€±€êÑRé#”xž€ÝRê#PýX^íT’®ë°, Š¢@Ó´‚÷«ª ¯× Ã0œû ÃpJGý~¿³Œp8ŒP(]×aÛ64MƒßïÏZ_(r–3×Ç—²Mñx€è»ÿ÷z½sZ¨ªZÒ}¥Ü_È\öƒmÛÐu£££P‰D ëzÖòämòu °, †aÀï÷;¯×[pߨ¶h4 ¿ßEQæôܹìëÜ÷¡ÜFÛ¶¡( €³­¥ìËH$âüo,ËrÞ¿î×(·ý…ž+_G¹?*±íµ¢œXP(È}YX¼^oÞÛJ]0¿c}1bÁlÇs¡8 Y–åÂâXˆXÀïÕïÈå‹¥ô€™± Pp·«R±€}„ÅÁï³/ ¨ÍX0Û¹jô ÜË®çX°û¥îs÷ýì#Ô_\Ë«tç ãØÏÅ>ÂìËj3Të¼ÏÎ/4LÅc{{»sµŠa3®P ‡ÃÎΑW°¹;”ÑhÔyŽmÛhoow>Àä}¶mömtvvÂçó9RÑh4ëJ™¹>~¡ƒAgÛ-ËB{{»ó&+v_)÷3—ý o“þ†a@Q”¬7}4E0tÖ‡+žt]ÇÆuù|¾¼ûXÞ'Ù\ž[ŠBïCÛ¶±qãFçÃ)Ãçó•¼ÜÜ«¸Ü_ˆ|>_ÖýY¯bÏP±m¯åÄ‚bqÀ}=Æ‚rõÅŠ³“…․(JÖw‡YÊ¥¬w.нˉ³ËÅbÁlÏê?ÛïåôÜ÷/µc¿œã~®û¡œc¿Ôã7ß±ˆ/E‰DbÆIC¹.÷ceßa>ØGX  ê9õñ} ”c¹X,(¥ _ÛÜXP(È啉ì#,~(¬bÁlçªÑ'Ë–í’ê),Å>ÏÖqA>¾Ò}ž3¬ÿc?û…ÕC,¨Öyž3œg,¨ö8±•‹Å¦EÉ·XŽû=5•Ÿß}¿ªªS^¯7ë~÷Øàr™SSbÞX,æÜ§iÚT pþ…BβæóøÙx½Þ¬q€sÿ/ftttƶ{½Þ©P(Tô¾Ùž[йì‡ááagœuUU§TUR%ë5µîX,æì S‘H$ë>Ys»MLLÌhÃlÏ-u;‰DÑ÷aîxÈS^¯·ä±¶sU÷¾Ë]N(Êšk¢Ðs‹m{½Ž^N,˜-È}Y­Xï¸/5”{¬/f,˜í˜,¤D"1¥(ŠCTU5”²ÞR¶q¶8à^4—XP,ÈפP,(öÜFˆÅö{¹}¹ÿj娝T`¶ûË=îçºÊ9ö‹=÷ÛßþvÑcß-÷ø”ËÈ÷öjÓBÆ~¨~@.¯X,È×p/{¶Xo“rcû‹‹ß «—X0Û¹jô ÜËÉ÷¸zˆK­OàÆs†…5J\Ë«tç ëûØÏÅ>Baõ ªuÞ€ç ç ¢âQ–Ì»¯Vq—‚Æãñ÷ûý~çoÃ0 ª*lÛvJ¦åÿ2»î~®¢(³–¸Îõñ %ß¶Ë+øŠÝ7ÛsKUê~p_½4>>ŽññqY}woîÕIîòsùú»¯h’WK¸_ûRŸ[ŠbïCy[0t®ÌJ$s²®¹y5‚a°m»äççÛöz¼œXPJê3”{¬/f,Š“…â€mÛ‡Ãðz½ˆÅbˆÅbP%ë*œbq`¶õ–b¶÷ cÁÂ(¶ß+Ñ–Þ±_‰ã~>ûa>Ç~±ç>ýôÓf?öó)vüÌ娨GX,  ê1ÚöZü> ÍöYœ/”Òª ØGXü>PX½Ä‚RÎ ,vŸ¨ÿX°”â@.ž3,¬‘â°p}ž3Ìno½û¹ØG(¬^bT­ós‹¥®×m¶÷ cÁÂ(¶ßÙ¨oå¼ÝÏë±/ŸSÈ\;þì#,Æ‚ÆTnÀý%¹š±€}„ÅÁïõo¶sóQnŸ@>¯zˆK)äâ9ÃúWÎ9Ã…è#ðœa}b¡qUë¼ÏתªÎÈ.»ƒ…¢(Eƒ‡¦iNYþ # í\Ö‹Üm7 Ã÷Ø}¥Ü_)ÅÞ¬¥î¶Ê1‡Ýb±˜Ó©È7~s±ç–¢ØûPN‹Å011ÑÑQÄãñ²÷¥\Æøø8‰b±Øœß³•ØöZQN,XÊq ÷/d{K}_ʉ—ÝäúË/¿  x˜ïzs×Wì=ÈX°0Šíwöæl/öqŸ»Î¹¾‹=w¶c??ÜWñÍöE¡Ø²ØGXxŒ…ÕÃ÷|ë«DÀ} W3°°8ø} ¸zˆ }n`>q¨ïX°Ôâ@.ž3,®ÑãB%úç¡Ùö cA~õò}@ªt Ôï…T*°°8ø} °z‰ un œ>Pß±`)ö Üxΰ°¥*ÑGà9Ãì}^/Ç~.ö «—X Uë¼Ïfþ.%4ÄP«š¦! ¡³³š¦Á²,çMˆ)‹ÁçóÁëõ:ã麯€ŽD"‡ÃN±, ‰D¢Ú›æ´/;{îÿÅäÛvEQœåºo¶ç.„ááaø|¾¬«)æòX–…7:Ï-T†ì÷ûá÷û «J}n1ÅÞ‡@ñx7n„¦i0Mš¦•ü%%8˵mÛù0ôûýÐu7n„ªªÎ{[^É >W¶Ù4ͬm¯•÷ý|” ê-º-ŸÙŽårï_ó9&5MsÚ)ßïò=ÛáqÇ÷k\n,˜í=XN,(v,— =W¶»žcA±ýÎ>ÀüŽíÙú ¥œc°”ç:ö ‰D"ðù|ÎüŠ¢d ÉT*öcA~õô}@î÷Jöò©F,`aqðû@aõ ãÜÀ\ãP¿±`)ö æ²ÏÙGhì¸PNç ëûØŸËk°P/±@îûjœ7à9ùłeSSSSx½k‚eYΛÛ}Å‹mÛÎ 9†®ë°,+kŒoù8¹CkeÜjwûÝ×Êÿç²o€™ãO»¯”ûb[ç².Ã0àóù055ådçK}ýÊyîlû:÷}(× ï}³1M¶mç}ÝsÛ.'9–+öÜ|ϯwåÄ‚z‰…n+e¿ó;Ö#Tâ˜t·³Z± Xëæ æz,»cÁlÏÍ÷üz“o¿³PÞ±½X}€Zû,w›OߤöcAñýÔæ÷jõJU©XÀ>Ââà÷Ù÷ P›± w{ç²®…îÌ·]ùT#,Å>Ïξo€Æ‹ ùÚÉs†KëØÏÅ>Âìû¨ÍXP­óB¡Ð‚_¹_Œ;XRì…,÷ùÕl{%¹þJ>w1¶±–öãRÀXPÙ÷ÑB¬·œã¹Œ«QûJ-£ZmϵPŸå …q¡þ4j,h¤ïÕêÔÒ>¨Ö:–Æ‚Ú}Æù`\¨ý>Bµð<ÁÒÂXPû}„j7`,˜Ÿ†ju6î’_Y-ËÉ«©ÐØÚnÅ®(÷ùÕl{=XŒm\ û±–0ÔV»ëcA}kÔã¾R˨VÛëãBýiÔXÀïÕÅXP j«Ý€q þ1.Ô^ÛëýÆÃXP[í®Œ…-‰ŠG"""""""""""""ZX§U»DDDDDDDDDDDDDTÿ˜x$""""""""""""¢²1ñHDDDDDDDDDDDDDec⑈ˆˆˆˆˆˆˆˆˆˆˆˆÊÆÄ#•‰G"""""""""""""*DDDDDDDDDDDDDT¶åÕnÀbøË¿üK<úè£hjjªvSÕ«¯¾Šõë×W»‹êàÁƒXµjV­ZUí¦,ª¹¾Ö§Ÿ~:þñÿ±ÚÍ^túЇpÞyçU»‹ŠÇÄÒ1××úèÑ£øÈG>‚_ÿõ_¯vÓûKÇÑ£GqôèQœ}öÙÕnÊ¢šëk=99‰]»v¡¹¹¹ÚM_TüÇŒT»sV¯Çr½öGêµÝó‰çž{.¾ð…/T»é‹*•J¡···.ûõ ØîÚn÷Rý~ð/ÿò/øÎw¾Sw±~)}FÕ‚zm7Às†¥úßùœ:uªÚÍ(K½~^¹Õkls«çxáÞ†rûK"ñøøãã–[nÁïüÎïT»)‹ª»»ƒƒƒÕnÆ¢êïïGGG:::ªÝ”E5×׺»»»ÚM®Š_þò—øîw¿[íf,*KÇ\_ëd2‰d2Yíf/:ö –ùïëë«vSÕ\_ëþþ~¤R©%—x_]]] dçª_ëJÇK2ð˜X:õµfŸ 2–â1ÑÚÚŠ®®®j7cÑ5êk/”Ó'¨WõúúÖëgT½¶»QãßB|?¨Wõ Øn¶» ~F±Ý¥jÄXÀ8_#¼ÖõÛÜê9^TRÍ%099™÷¾‘‘tuu¡«« صkÆÆÆ022RífQ1ÀX@DB¡XÀ8@´t°O@Dc1Õ‹šJ<ŽA×uÜu×]yï“s0HÍÍÍhmmÅîÝ»«Ýt"ªÆ" ˆH( ˆ–ö ˆ`, "Æ¢zR3‰Çt:;î¸@ o9­¼’!wbѦ¦&Œ]öñãÇñä“OÎú8¢F—J¥L&qøðáj7%¯…Œpøða$“É%5¾;Q>ÉdO>ù$Ž?^í¦äµ}‚r'É&ªwétÉdû÷ï¯vSж±P,(·OpôèQ$“I~? %oll ÉdG­vSòZèïû÷ïG2™Ì;\ÑRÂïü~@Äs†vìÆÆÆxu-y²ñÆoT»)y-d€7Þxƒ"À9Ù~ìØ±j7%¯ÅèðÄ-u“““5Ÿx\ÈX ü~@KÝîÝ»k:ñ¸Ðßdâ±ÐmDK¿ðûÏòœ! ¾T¢O°¼ÚˆÎÐÐî½÷ÞYþÚµkqóÍ7ϸâh©éèè@GGGM^Ý¿ÐqÖ¯_ß-•«¯¯Éd²&¿\³O@´8š››Ñ×ׇþþþj7%¯…ŽgŸ}6ûDººº`É~?¸îºë ˆÀïü~@Äs†AÍ$›šš°sçάÛûûûÑÔÔ„ÁÁAç¶±±±åÔùÊ«‰¨¾0ÀX@DÂl±@^éÌ8@Ô¸Ø' "€±€ˆˆêQM$»ººf\Y”L&±mÛ6'0ÈûwïÞ,’É$¶nÝZíM ¢21ÀX@DÂl±€q€¨ñ±O@Dc1Õ£šH<677£¹¹yÆíî“ €2CCCضm<àñx°mÛ¶jo•‰q€ˆÆ"J‰ŒD}" ˆˆq€¨ÕDâ±T}}}رc¶oßǃT*…¾¾>x<žj7ˆ ãŒDÄ8@DcŒDÄ8@TKj6ñ¸wïÞ·y<Ü{ï½ÎÄ–mmm D Œq€ˆÆ"rcãÑÒÃ>ŒDÄ8@Tëj6ñXLî˜ÎD´ô0ÀX@DŒD$0ÀX@DŒDµà´j7€ˆˆˆˆˆˆˆˆˆˆˆˆˆêDDDDDDDDDDDDDT6&‰ˆˆˆˆˆˆˆˆˆˆˆˆ¨lL<QÙ˜x$""""""""""""¢²1ñHDDDDDDDDDDDDDec⑈ˆˆˆˆˆˆˆˆˆˆˆˆÊÆÄ#•‰G"""""""""""""*DDDDDDDDDDDDDT6&‰ˆˆˆˆˆˆˆˆˆˆˆˆ¨lL<QÙ˜x$""""""""""""¢²1ñHDDDDDDDDDDDDDec⑈ˆˆˆˆˆˆˆˆˆˆˆˆÊÆÄ#•‰G"""""""""""""*ÛòJ.ldd»wïôõõ!™L¢­­ §ÚÛIDDDDDDDDDDDDD ¨"‰Çt:ÞÞ^$“Iç¶¾¾> `÷îÝøÚ×¾†ÖÖÖjo+-Š µªë:vïÞÁÁAìÝ»×¹ýÎ;ïDGG#¾>]€IDATvìØt:]ím%""""""""""""¢R‘ÄãÐÐ:::²nonnÆ]wÝ…t:í ÁJDDDDDDDDDDDDD§"‰Çt:]p(U9¿ãØØXµ·•ˆˆˆˆˆˆˆˆˆˆˆˆˆHE­­­É{Ÿœ÷1·’ˆˆˆˆˆˆˆˆˆˆˆˆˆÇòJ,$ ··°uëV"á˜J¥ÐßßŽŽŽ‚‘DDDDDDDDDDDDDTÿ*’xܺu+î¼óNô÷÷chhÐÝÝ èêêB___µ·“ˆˆˆˆˆˆˆˆˆˆˆˆˆPE€H0vuu9C«@[[›3Ç#5®Š$“É$š››ÑÜÜ̹‰ˆˆˆˆˆˆˆˆˆˆˆˆ– Ó*±ÞÞ^gˆÕùJ§ÓèííEKK ZZZ°}ûvŒÍx\?¶lÙ‚––ôöö"•JUgÏQÅ1ÀX@DB)±€q€¨±±O@Dc1Õ›Š$FFFN§ç½Œ;v •JappƒƒƒhnnÆŽ;²–)çìëëÃàà R©z{{«½‰¨Bˆ`, "a¶XÀ8@ÔøØ' "€±€ˆhé1MÀ¶«ÝŠù«ÈP«7Ýt¶mÛ–w^Ǿ¾¾‚ÏÃØØî½÷^´¶¶óCnÙ²Éd[·nŒŒŒ8sIÀ®]»àõz122â<†ˆêãŒD$” ˆûD0ã-¶ (Šø;B!Àë­v«æ§"©T MMMhkkC*•r‚û§ǃžž'pä366†T*•5‡dss3Z[[±{÷îjïG"*ãŒD$Ì ˆûD0ã-ºžùÛ¶EÕc®p°¬¹/Û¶ÃX¼m©HÅ£¬fL¥RÁää$ ££#ë`/¤¹¹ÙYÆØØ&''144„ÖÖVçùîeº555ÍšØ<~ü8ž|òI455 PD.•J!•JáðáÃÕnÊ àðáÃH&“hnnFsssµ7™¨j’É$ž|òI?~¼ÚM™a±úùžO´”¤ÓiìÞ½û÷ï¯vSòš-È“óí=zÉd’ßhÉ“Ç×Ñ£G«Ý”ãûÁþýû‘L&ÑÖÖ–wä&¢¥‚ßøý€ˆç yΪÏ0D•# *åP«îJÈhTTAªêÜ–mÛ€ÏLMÜØØXEúI<ÀÎ;144”uÛÀÀš››±k×®’¿Ð÷÷÷#™L ÍJtþ;†±±1¬]»–'hIK¥RH&“xã7ªÝ”¢"Ào¼d2‰ŽŽv"hIK&“ؿ͟`[È>ÁÁƒyb–´ÉÉI'Ôº…ˆ2ñ(¯‚&ZªvïÞT*U“‰G·…ú~ ÍÍÍ5ß/"ZHü~ÀïD$“I§³^«Ø' Z8òªáþþþj7eVùbA¹'Î>ûlö ˆçsu©~?¸îºë ˆÀïü~@Äs†Ÿ˜«Q.Ç]³—o^GËâq‘"™(“Š´·‹d§l_$2s;+5ĪT±Ä# ®*èèèàÁMDDDDDDDDDDDDU1ßdšaˆ¤ßø¸HØÉyÝdBѶ³‡5Õ´Ì}r^GÛ˱,±\ “t¥ª(™ÊIÓÿ+J¦b2•C®.[&~Ë*ÆhT<^®WÓÄs;;3‰SÙ6·@@´/Íÿ|œV™ÅCCCèîîÆØØ˜sÛ–-[°sçNgBW""""""""""""¢…äžÛp6†¬['þ–ÕŒòö|T5“ð“U‰¹ët£êóeWF"âv™ ´¬LbQÞ®ªâ¶pX$óUoÊùeÂѶÅïX,S­ ‰eèz¦Mò·¬¢ ‡ÅsåP±åªHâq``;wq“»ººðÀ`ÇŽ•i-QsI<ªj&Ù(« erN&÷Âa‘@”7Mq›ªŠ!SeRÑ„ŒÅ2ÿËŸ\–»2R±ZˆœkR¶ ±^™øŒÅÄíŠ"Úi™¹MS¬CêìC°ZVf[dÂóСòJ­Hâqhh]]]Ìg¹¯¯_ûÚ×066æLêJDDDDDDDDDDDD´PÜs0ÎÆ=W£üß²D•¡U&LRàêºFUÓ2•‹ª*Œr¨VwâO’êêz&A d*#‘LBÑ]¥hbÙâù‘HfhVMËüøýây^¯Ø¿_<^&實™Yÿž=g•½ï+’xL¥RغukÞûZ[[ kV""""""""""""¢…"«e¥a±Ç¹«ñ·L:ZVö<‹€Hâ%ÙCªºŸ/î„!¢UQDBPV$"ÉèVU×Ūfé*×§iâ~¹}òy‰„x¼¬¢4M±žx<3”ìèhf;€Ìm[¶L–½ß+’xlnn.XјJ¥dDDDDDDDDDDDDD A&òdÂÍ=¿a>~¿HÚ¹…–•™#Q&ðd%¤\ö²eâMɾx<3äj4*žˆû€L…# Ú%“‰š&žgÙՇLPÊ J7ùx¹î`Pü¸ç”C©JÑhfý²²3¾õ­ eïÿŠ$·nÝŠ N;·ŒŒ ··ÍÍÍèèè¨Äªˆˆˆˆˆˆˆˆˆˆˆˆˆ rÏ]hÛ™yÝÉ7É0Dâ-IHY‰ˆ\IºçdÔ´Ìüápfñ¸HÊûE´Ëë‘ID9_¤LÊ¡Wåãå:òÍ)‡¹Û.ï“d…¥û1²^ofù53Çc__zzzÐßß-[¶ ¥¥---èííìÚµ««!""""""""""""šÁç C™dÓ4‘` …D’Ï43I@7ËÊ Ajš"‘'‡DÍeÛ¢²pxXü/‡5•ÜÉ=MËNt&™¤£¼_&eBÒ½,wâ1‘C±Êùå¼²¢3EÉl‡ßŸYŸ¦e¯+7ÉY®y¥.ÇÆÆðÀ`Û¶mΪ}}}èêêB2™t†Wíèè`¥#-(9T) ’q¡P¦rQwê~¬ÏLLˆÿ‘œ“ó%F£"9'çnôû3 JŸ/SMèóSSÙË–m‰O9" |†!’ˆ@&á ‰å+Jæ¾ááìd iŠvÅbb™2Yê®l”ËÌm‹¢ˆç3“œrºìÝ»W_]Þë0¯Äcss3š››¡ë:ÆÆÆ°uëV´µµaëÖ­èêê*¯EDDDDDDDDDDDDÔ° #»:p6ržF™8Ë'·ZPÎc(vrD7w¢RÎר(âv¯7{ÞÇHDÜ/‡H•s#JržFÛÆÇ3‰J7MIÃ`03·£®g†Q•C»&3Š’e‰6ȹs‡`•ÕîêJ÷<•ñ¸¸ß½|U·MM(ûµ×P«]]]صkî½÷^477#™LÂëõbçÎ)»aDDDDDDDDDDDDÔxò͵XL8,’r–,[–y¾¼M&ÝØªj&™˜oŠ"w¹U‰^¯¨”U2§ë"a‰dæU”¿eµ¤ß/–·qcføR™Ü”ë,”8-”h,¤ÐãÝïz½3+2%÷6Ëç½ôÒª¹5"²çx”IÈ;&a ££Éd[¶lAoo/†††N§Ën(Õ?9„i©d%bîТápfY¹ËÎ$ #‘™ ?w¥ »2RQ2U²âQQ2ÇE"Ò½>UͬË=Ôj¾ä`4*~ËŠOù;·r±Ð~“•’r®ÇÜí’óZæ#÷…lŸ›mßúÖ†¹¿˜9ÊN<æÚºu+î¼óN<òÈ#H¥Rؾ};ÆÆÆ*½*""""""""""""ªCsM<ʤž|žÆT&úäp¡^¯ª4Î ¡*çC”I:™(ÔõL’Q.OUEbQ&èd²/Ë•m•ò1²2R• dÅê–[}™;Ll¡}0<,–/ç¢L$ò'Tó +›HˆöÈçæR`˖ɲ_׊' •Jadd“““èëëƒahmm]ˆUQ‘É7]Ÿ}èÕh4“<” DÛÉ>w"2ËòùÄm2)iš™yåc-+{ÔX,ó·×+–¥ª™ù"ÌrÝ’if’£Á`ñíqÏU™Hdæ\ …2÷沬L;J¡çd=eÛ Ñ4 ¥åð^ÁüÊJ<ö÷÷Ãëõ¢¿¿ß¹mhh^¯½½½èîîfµ#ågª }¾ÂɵD"3‡¢if’‡îÄ£ü‘Ü™§mg–‰ˆ„_¾ Ì|C™™ L9\©üí÷‹åÉõ&ù«e’2÷69ge>¶-ÚïÞ¦bŒÙÜ'N|NU‡ZíïïÇÀÀZ[[ÑÑÑ@T:îܹ­­­Ä®]»J¥²“DDDDDDDDDDDD´´É¼˜ªf†;•â¢jÐ]´çU& E ?ªªâ·ßŸ™Ñ=‡¡VUR”Ì<ˆržH 3ߢL ZÖÌ¡Iå|“@vRQQ2àÊu‡Ã3©r¸ÔB %½^ÑæbÏÍÞ¿™Ä£®ëXµjŽ=Š={öTø•̶|>OJ§Ó@__zzzœÛ‡††»víBss³s{oo/ÆÆÆ8Ü*9 4EÉ$ÛÜI7]ŸY‰(+þäP«ŠlÜ(ŽržE¹9ߣ×+–åN6*ŠXF"‘I z½Ù Èx\$s+ åð«nrxÔܤ¡\›®çNUµš¯ÂÒMV}cY윆ŸsίâÀgpèÐWü]Áç>óÌ%e¼ªó¬xܽ{7 ««+ëv™\t'·nÝ @TCQc)¥ ¯³3S=˜Hd’Ц™©~ÌMÈɹå<ˆ@&™ç^§Ì±ézf™º.†n5ŒLR®ß²DbQÞdWHšf¦²QUEe£ªŠ¤_<>3Á¨ªâG&>ÝËÊ'7q)o‹F‹'£QѶBU‘™ýa# Á¶mض Ã0°ÿ•xæ™S¸þúÛÊÁ‹˜Wâ1™L<ÏŒÛå°«¹˜x$"""""""""""j<îyÝÜs0º“m>_&á螣Q׳“vr.FŸOÜ‹ÇF&A'çQÎ^·{}†‘I0â®NÔ´L;T5Si)‡z{9¹‰Ä|U”n³µS&VÝÌéäðª¦iB×u躞UùøÄoàûߟD|zC Ã@0tîïë{_üjiYÀ¼2¹˜N§ÛFFFmmmY• G³JDDDDDDDDDDDÔ˜ò%Ìt=3·bn•žL:Z–Hƹ’UQ2Õ„’× Äbb9ápö<‘š&ªå\rhÖ\±Xöð¦2Ù(Ÿ+ÿ–í2Œ™óGæ 2m‰DfVqZVþŠÇ¹ë7Míííðù|Ðu>ŸÏI>†B!(Š‚ÎÎN Oge×­;8½?Ôé×À€eYX¶lÂá0¾üå3ñâ‹ëËjÛ¼2¹¨»fâ”ó;Ê¡UsoÏMHQcÈ7ܪifß.ÿÎMÞiZ&Y''â·¢d’€š–Iäɤ¦{¨Vùx™hŒFE¢/7i)ÉêA™”Ì7÷¢LÊäg8\|hÙÙ†•ò–Cn¢(ðûýH$PUÃÃÃÐuápº®#0½Q×^;‰‰Qø|ËÇF¡( ‰ÆÇÇfŒt:Ëçó$ǃžž 8Ã®Ž¡§§ÇyÌØØ†††044„žžžŠ4–ˆˆˆˆˆˆˆˆˆˆˆˆjO¾yC¡LÕ¢œŸÉEùw"‘y IHú|â1r˜S9¯£iŠ*DÛž9”éèh¦¢Ð¶3‘‰ÉD"s[$"’ˆ†Q¼Q¶GQÄß®š¼¼%S%™L¢zn±¤äè(ðÍoEÿ`š&E¢(hooÇøø8‰LÓ„¦ihoo‡6½Ñè:üÁ\ƒ^¸\p?lÛvî“oû?òʛ:q^‰GèëëCss³3ÄjOOúúúœûûûû‘L&gÜNDDDDDDDDDDDDEV †ÃâïXL$eÒ/•z^ovU Ï'n“ÕŒî$ œQ&EÛó몪BÓ4§ê1³~Å©rŒÅbÎíã㙊ÐB.ºè(öïŸûà´ù>qll ^¯ÝÝÝèîîÆöíÛ±sçÎòZCDDDDDDDDDDDDu%‰-MÉÇ@@ÜnšÙ‰GùÛë :ËÊ$U5óIBYÕYˆl_¥uvvâòËÿÿøíø—¹Š¢d%óQ\(÷óB´ÍmÞ‰Çþþ~LNN¢§§ƒƒƒØºu+†††Ðßß¿°-&"""""""""""¢šáó7f*ê:;Åï@@$ Cüí65Õƒ’mg†‘™Ï1Ë$$å\‹ñøüÚ)”–%ˆù†„-&‘˜9\ëb°m‰D+V¬À=÷xί¬2¯‘^ 3{ÑEGËn뼩T Éd}}}èëëCGGvíÚ…ÖÖVŒÍ«!ét;wîÄ–-[ÐÒү׋‘‘‘ëïïwÓÛÛ‹T*UöN ¢ÚÀ8@Dc ¥ÄÆ¢ÆÆ>ŒDÄ8PËdòN’#~º“‰rèÕÜy£ÑL È<Æ4ErOÓÄ®gW0º“rŽHMËŒDÄ8P‹ÜÉ>UÍ®bTÕìjÀx\ü¯i"Q&+eòN&åsB!Q)‡î¤¥›êÔÝù·aˆõJ<†ÃbýºžÌ,Õl•†¥²mÑhÑhñxÜI𦠝×ëÜ.éºÓ4aÙIGÛ¶áóù`FV•¤eY0MP€æìMÓ`Û6B¡4MsŸ÷Ýw_ÙÛVVâ±»»---ÎÏÀÀ’ÉdÖmòg.FFF°}ûv477#PÊ@µ³8pàúûûÑßß_ö²ˆêÙÐк»»±oß¾j7eV•ްoß>twwchh¨Ú›GTUÝÝÝèïïǪݔY-TŸ »»»Ú›FTUcccèîîÆý÷ß_í¦”¤Ò±àÕW_ub!ÑR&?_}µ¼¡”ÃB|?¸ÿþûÑÝÝÍ’´äñû¿ñœ!ÏÎ…®g^o&©(Z¦)†EuÃ*šQ•dÏÑ(çxtWEJÑhá$ |ÎlkžF;gG¸“Ž˜˜˜€×ëÅðð0TUE$וYUUªkLÙÍ›ß@ggçôð«*b±XVâÑ4Mhš†P(Ã0‹Å˜X³æ<¯×‹ññqg=–e᪫®‚®ëe÷ –ÏçIÍÍÍèé驸ÎO¥Rعs'’É$zzzàñxÊ^î¹çž‹|ä#3®x Zjä8çµÜ¡^¨8—\r «½‰DU788ˆd2‰d2Yí¦Ä>ÑÂ’W ×zâm¡bÁúõëÙ' Ð××KöûÁ-·Üâ좥Œßøý€ˆç yΰØ9W¢;‡¦ë"(‡=•C Z–ø-« å†!~Ëü™¬‚¹n]ëË—HÌw[(Tø> ³þÙæ€,&‘˜Ûã£Ñ("®I*u]G<ÇÄÄDÁçÄãqض ˲pÖYgág?ûvî܉PÈ Óz{?ŒsÏÝ˲‹Åà÷ûFáóù`Y,Ë‚¦iÐ4 ªªBÓ4\rɃ8çœC8rä¹é HA>æÛßþ66n܈eË–Íç ŒÄc¥;çcccرc:::`FVétîãrÇsÎýŸˆêãŒD$” ˆûD0ã@µ†˜‡q|<“(tß—KV3jšH8™Ä£¢ˆD¢ªŠáM5M$e%c8œ?™'×[l¸Õ\¦™I†æ¶ë …2ÛàÊ–$ûejjnÏ‹Çãðûý0Mªªb4'Ûj4Mƒ¢(0 »wïÆ?øA8p÷Þ{/6oÞŒp8Œ /ü-ŒŽeËb||Á`~¿Š¢`xxðûý°mÚôòOOfyèÐVœyæœ<ù44m»³n¯× ¿ßUUÑÒÒ‚Ç|îo—ŠÍñ˜L&100à ·:W½½½Ø¶mvíÚ•7pÈ+r'ƒM&“ ÕÆ" ˆH( ˆ–ö ˆ`, "Æj‘ó0Êmgns“ãÊye²Ñ¶3Ž€¨ZŒÅ²—/‡SÍ•›Pœ˜˜y›Lh.¶ùŒð+çnûÓ€aY‡¶m;æʿ{ì1ôööâñLJ×ëÅSO=…ë®»÷w‡—_^«¯þ ‹9ËÒ4Í>5æÞÙ.O=µÏ<“=”ª¢(NEæ7ÞX´³óªx”Òé4t]ÇÐÐÒétÖ}]]]%•<'“I¤R)tttÌHZ6559W%tuuahhÛ¶mƒÇãÁÀÀ<¶mÛVÖN ¢êc "€±€ˆ„RbãQccŸ€ˆÆ"b¨&ÛÉ>9$i4*’…~v²Ð=ç#ù[QD²QV3z½@0˜¹ß0ÄòÂá™Ãžz½³'ø†‡«³_Âá¹WIÊ!O7n܈H$‚ÖY¦˜§1;•±X ¿ök¿†={öàî»ï ’ŒW_ýG€+®¸bÎm÷x<9ÅL5d®ßüÍßÌšKr>æxL§ÓرcÆÆÆÐÕÕ…ŽŽ'Á˜N§ Èd2‰¯}íkE“2`ôööθ¯££Ã_¹¯¯;vìÀöíÛáñxJ¥Ð××W±±œ‰¨zˆ`, "¡”XÀ8@ÔØØ' "€±€ˆ›m‹d¡ÌI™&ÐÙ™™ƒÑ]ˆù9Tª×›IZâ> S)sZr^È|LS$4ÇÇ«½Gò‹Ç3sI#«¿þõ¯##‹ÁëÚh]סit]G"‘€ªªƒ…BPU›6m¾ðç9ªªâóŸÿ<>ùIà“Ÿ|×¼Ú¾aÃbÿ~3«â²ÒæxìïïG*•Âàà`Þ ˜·nÝŠ­[·¢··ýýý¸óÎ; .«¯¯¯¤9#=î½÷^'Ø´µµ1p5Æ" ˆH(%056ö ˆ`, "ÆÅfš¢*QÎëè÷‹$›$‡O•‚AñÛ›šÊ®TŒÇ3ÿ[V¦RÒÜfVÊœ˜®Ï§º0SaYè~E)|ÿlB!1ÇãìûÒ„oú¶mcÅŠ¸ï¾û˜Þ!¶m#O·Is’‹ ×d—–eÁ’™Ûiÿø&üéŸNáõ×/sÛo¸á|ýëX³æ†ùm|‰æ•xL¥RBOOOÞ¤£ÔÑÑ®®. Tôê‚bë$¢¥q€ˆÆ"b "±€ˆÆ"b¨$UI6wâQUÅ;ù¨iÙÿ»É$ŸdY"ágYbèV™TŒÇ³‘š6sNÇR)ŠH NMÞ.EÉ?_e.Û¶ašfV•bf.KsÆp¥º®Ã²,„B!D£Qx½^(Š]×±yóf,[¶Ìyl8†¦i°mÛIFæ•¥¦9Ûwðà2ÌÇÑ£p)>øÁÎoç–hÞ‰G@Œ›<™xܽ{7z"""""""""""¢bÛ™dœe‰ßîd¢eeW2Fv£×+æ>Ì%‡WD"Q&-ÝI¿@ Ð4gŸç±WÑà ñ¸hGN!áôvZYó†]×Ä£a8qâ+ÐÞޯכU¡(¶mÃ0 ÃëõÂï÷CQ´··;ë0M¡P(+©¹X:ñxÚ|ž$Ë•›››g}¬|LîįDDDDDDDDDDDDT]º.~+J¦BQ& å\†Á ¨ö‹FEbOQ2É;™ÌË‹eª#‘L"ÑÔÔõÂÕù–YŠÙry–•©Þ”¢Ñ(:;;ÿeòÐ0 üüç?ŸÞAŒŽŽbÅŠFGGa†3ªeY0M‘Hº®Ã¶mx½^gÈUMÓœùQ1©(Šó³n¸á<+àÂO^„Ë_^!óJ<ÊÊEYùXŒ| «‰ˆˆˆˆˆˆˆˆˆˆˆj‡eeˆrxUEIB™4”IH)ÍTFÊß²úq6îåJùŒóju6×]w/¼^÷°±4MÃwÜÓ4aYâñ8‚Á ÃÀÊ•+ñáðù|xã7ð¾÷uæeôù|‡ÃÐuš¦!@UUø§wˆªªˆÅb¯× Û¶då|«‡‡ç—”=ýôM¸êÒPXÀ\缆Zmkk Í:±ëÐÐPÖsˆˆˆˆˆˆˆˆˆˆˆˆ¨ú,+Sh"©hÛ"™¨iâ·¢ˆda0˜†ÕŒ f&' Ñu± 9£œó1Wžé K‡ÉÍl:Ûjá¯þʃS§ÄÿGÅ7¾Ñ‰›o¾O=õZZZ`lÛÆK/½˲ð‡ø‡ø»¿û;<òÈ#˜œœÄ¯ýZ^ye  9ñÀç>÷9D£Ñ¬9-Ërªª"ò¬²ªKMòÎÜ~à¥Ã¾€À `¼óªxôx<ÎÜ###722‚tuuÁãñT¾õDDDDDDDDDDDD4oîªG7UÉGEs8Ú¶¸-É®¸s»Z Ã6n̬»xÛJ_°mÛˆF£ŸF³þß³gEÁ%—\‚O}êSX³f >ûÙÏⳟý,zè!lÚ´ û·‹P(„ÓN; ‰D©Ôa<ñÄDÅb$A"‘@"‘À~ðX–…@ àT<*ŠâÌ©ª* ÀišÐª¤sÖË€}Õô?fY‹*h^Ð×ׇݻw£··[·nEGG‡3Ÿc*•B2™ÄÈÈZ[[g­Š$"""""""""""¢ÅeÛ"qhÛ¢’NV;3çAÌ7ôª¦‰*ÆR ød¾M.w¶!CÃá0†‡‡aÛvÑ*Á`0è$ûÂá0€3”©mÛø“?ù“éÊD?žþy¼þú¥xñÅ}ðûýN0‘H`jj ï|ç;‘L&]ÛA(‚¢(xÏ{Žâ²Ë^q†LUÅy¾œÓs8š¦™whU˲œdäbS›ål Ô„y'=¾öµ¯A×u ͨ|ôx<èééA `µ#QE£bG7M·™&‹ DwNÌ02뺹+M³ô¡VE¬³Àh¨3X–Ã0  …²†1àTÊáNEA<G<G @$Áûßÿ~ìÞ½7Üp~þs‘¯:qâöìÙƒh´_þò—‰Dœ¤aþv‹¤ç…®Âàà/ÿlÛ†®ëH$P†a8C«F£Qøý~†‘5—£ªªÐu¡Üb¨* ž(ÿ`€8Äp«6ïÄ# ’‹}}}èëëËÊþ@GGÇâí-""""""""""""*(Ÿ™x”s.Ê„£ß/~L3Sñ(óq~¿H†Ãâÿp8³¼RGDÕ41'd<ž©~,6ê¨išÎ¼ˆÁ`ªªf%ò‚Á b±Øôöų†9õù|°m»wï|ô£Å‘#_Ã%—\nx'~ø›¸õÖ1x½Þ’‡>UàòË/‡ª¦aš&FGGÑÞÞ¿ßÛ¶‰D‡‹Åœ¡_eû‘xT¥*‰G¯WÌÓi] ¨6@‰ à¹(+ñèÆD#Qí±¬L‚Ѳ€ÎN`b"û~YéØÞ.’Tš&n³,ñ¿×›yŒ»8°ÔêE¹žh4»ªÒ4ER‰ÄH$âT€®ëÐ4 š¦!g Yjš¦3w£mÛÎã Ã@ @4ÅæÍ›±wï^ü÷ÿ7žþVüâMø×=gžùi|êSÏÎ) hYÀºuëàóù¡P‘é ‡O•òjš† ÷N†¶U&ÛtQ(ðiÄp«*>äêi ½!ýýýhiiYèÕQ²"Q§*‡FUUQµ˜Hˆÿe1¡adæ´¬LR²m‘p,±P0ëyŪ# Ã@ggçt›-'Açõzáõzdz+¶)î Á*+Ãá0‚Á 6lØ€[o½ò'‚÷¼ç=˜˜¸ /¼°/¾ø" Ì+ ˜H$œ¤¢ßï‡iš°,Ëig¡95M«JÒ1Ë( Ç+UçbÁDDDDDDDDDDDD´ørç^ÔõìÛ,K$}¾ÌPª¡H@ÊùÇÇE•¢‰ˆáRÃáìÊÇR¨*pÛmÇf,+ÓQŸlÙ2gžDY=(‡Pmoo‡iš0 ÃIðiš†@ UUaÛ6LÓÄðð0> ]×ñ¹Ï}¡Pï~w G~gu?–/ÿïy%E$BÝÏD"NûjÕŒÊT €1Ÿ%ÇÄ#Q’ÃkÊÊFÛÎNô™f¦²Q×3C±jZ¦š±½={™á°kØÎ9ºçž{ðÜs³æwTUQ¡¨O/tbb±XÌ©x”U„0>>UUÑÞÞŽx<î “ªªª3äi<G$¦iøÞ÷¾‡ÑÑQgýË—¿€çž{+WnÆ­·þá¼¹É\©Ôy"«%¼—ÞuÓ7D,@®”‰G"""""""""""¢$G&µm‘àIF9­¡¬XÔ´LÒ¶³+e¤ûÿ¹°]™º|?úÑzäŽDǡ뺓`”Õ‹^¯×™3EÁðð0FGG‘H$ iZV¢eYÐu>ŸñxŸ'%“ItwwWq÷Q!Š"’ƒ–%„²ÚÈüHˆß¦)’‰±˜«2®D2é§( ¢Ñ¨3ï" †= ðûýN"0þàö#ÂëõÂ0Œ¬¡UgcY Ã@{{;,Ë‚mÛðûýð»J5M+8㥗^Šw¿{ßœ‡Œ­wª Xo(ÀQU¼àšD!‘Ê­g^‰Ç¦¦&tttT{Q–%*ÝE‘铦‰ûƒA`j*{ØÔ@ »Â1ÊžãQ.[ÝF!MMÓÌzœaÎÃÃÀú§{ÑÛ{žÞ€¢(0M^¯ªªæ­PDe£¬hŒF£ˆD"ˆÇãÎÿù’Œ<¥‰ò&¿ÿXUòmÀ>u&pŸO¼1Þ—¬9fšg1¯Äckk+«½ˆˆˆˆˆˆˆˆˆˆˆˆÈ%‰BÃÉ&YÜæfÙs:ºï—ÕÅæ2´mñügžy¶m; @Û5i¤5ÍÌ­büC„BÀƒÞ ¿ßEQ Mg/ Ãpæo,”L¼á†œ H-Ϙ§ápðù|0M‰D^¯×I@Jªªb||¼Ú»¼öY”Oý–øû§Šx$À7bÀÔ0`W®üs^“““H&“˜œœÌº½¥¥===èëë«ÞÎ#"""""""""""Z‚d‚ѶÅp¨ºªÝr«ë"ÿ¤i™ùeR2˲ðÕ¯þÒéMðùnð"FG#ÓÏS`Û6 Ã@4€¬$¡вªªBÓ´¼‰G]׋Šª*:;;¡( Eqª(çKµºÔ†Y…®CY· ÊS–‰ÛEd™c¦G[]~èPÙ«šW⑈ˆˆˆˆˆˆˆˆˆˆˆªÇ0D‚PNohÛâ6@T2†Ã"Á6:*nË1· ²Ñh×\ó+xíµOà©§€ /¼0+qhš&EA(wRH]b1ñw¾Ä£mÛH$Îí‰D©œ”sFÎ×’jÕ¶]‡õûÿelÙÌû5A  åŽ;pô¼ó€2 ç5Ô*UOggvò°½]T9jš¨rDb-ÎÜ'E"s¯ú³, º®ãƒü 6lØøÆ7~Û¹_qe6UUE$É;Ï"©Àt'åüº®#g-KŠÇãeW=.9òMòþ÷Ã:˜ç~€ÀƾøE<þîw—µ:&‰ˆˆˆˆˆˆˆˆˆˆˆêŒœ¿¿§ Û ("©h"Ù˜[éˆd¤|l!–eÁte6ãñ84MCOϵÎ^WÉ ;¨ÉjjZ&ñœÇnܸÑh^¯×™ÿqæsóÍ:ó©ô¬{rŒYäܧp‘]½º¬U1ñHDDDDDDDDDDDTgdáŸm‹êG¯73mŸ;7ˆaEss^ov>J²máp–e! fÝ®iL3sBæ2gÉì)JvÂÓ0 ƒA$ ø|>2£š£P%áõîý¦çyŒVàöyàDDDDDDDDDDDDuÀ²²ˆŠ"†UUU1¯c.¯WT>ææýþì¡WÝ:;;ä¡iš‡ÃˆD"°,Ë©N4MÀ禦ò/£XÅ£L<š¦ UUaÛ6Eq*ÇÇÇ >Wëø°3žŸù]æ¢êަ‰k‹<@ð‘ò×SVâ±»»{Æm˜qûÞ½{+½ˆˆˆˆˆˆˆˆˆˆˆˆ–ŒhˆÅÄßÃÃ"¨ëÙm@vÅ# ’¹‰¶x\üv–Š`0Ó4aÛ¶“h”Õ‡³ ¡ ˆÄ ;A™Ý^¯Š<ùäQèz^¯†a`ttÔyœRlü×2ÉfYVf¸×¥BQ¯ ßvûs¾°ª¼õÌ+ñØÜÜŒžžžjï#"""""""""""¢%#IE¿_ ¯ ˆdZ¾!SeòQU³“‹@¦ÚÑÔuñx‰D>Ÿñx¡PÑh€¨P …2“ºþtÈÄcþ¶Ça,+M[¿ß˲²æ‰\hîêÏE\íL:D²oár¬Ù-761§c>~`ÍÞ5ÀÕå­n^s<677£¯¯oN?s±}ûv$“ɼ÷õ÷÷cË–-hiiAoo/R©Ty{€ˆjãQ¶p8ûÿBCa4Æ" ÇÆ¢¥ƒ}" ˆˆqÉDMË$Ï ± drMªš>F¯X½ú!,[¶ ˆF£Ð4ÍöT&e¤ªªbÈÎÄÌá[3mÔòÞî÷ûáõzqäÈìÚµ š¦Á0Œ‚_èý¸€…•³‹ˆ.ÂzÂáL†L…Î+V(;¯ÄãBÀØØXÞûúûû144„¾¾> "•J¡···ÚM&¢ c šI}!éó˜ìÙ²Äóf™ß»f0P80-ìÀX@DŒ€8·ˆ¹åùññ™ÃªJùª ÝtøÂ¾¿ß@ ¥*+݉GMÓŸ>9¥ªª3¯äô¬3?~vÎ8¦¶mÃçóÁ0 <û쳸á†àõz …Êž·q.éaiÊþE[íLDòqA×aˆ*_Ö9?príI\òÌ%e­¶¬9`hhMMMغu+†††022’÷qƒƒƒ³.gçÎE322‚®®.tuuvíگ׋‘‘lݺµÜM!¢*c Z ëÙI¾R?—še‰e9€™¦¸ÈIÓ€k¯]Gy?æ8(Á¢`, "`öXÀ8@ÔøØ' "€±€ˆ$Û燂Aqn§”ù ‹åóTðxNá‰'~„ÿ÷˜3Dªœ_QUU'!¨ª*LÓÌJJ:jš†¡¡!D£QDr&žŒD"°¬ XVøÂC.]ÌÆÃ€w N-Þº&Ä6kÕ‡ µýѨȴÎá„⪗Váªç®*kµó®xL§Óؾ};vî܉ݻwR©’É$Z[[áñxL&199YÒ|,˜ C*•BGG‡s[ss3Z[[õQ}c Z s•áAv Ms~“VË縢цbpWEŠñóÅäㆼôÒ*9RæLÑ „±€ˆ€â±€q€hi`Ÿ€ˆÆ"b‚AqNGž³’ÃÎ—× ¬\ù"Þÿþ÷g%¥ÜÄcª)UUÅ%—\Ó4*IˆF£°mŠ¢@Q|ü±‹¡F;±øVOÿþ ;º, Aó8_X²Ü‰85Rußíûø_åUbÌ»âñŽ;î@*•®]»f\1 çtÃŽ;N§g]^ss3š›› Þ?99 YÁššš –WQ}a j±,‘ÈóûŘø^oöDÓóeÛb¬øx\\E&×1Û0ù–SÊs,ËÊê ºÛÿ¯ÿú(b1¯Ó!=th9V¯>ºH{xn ˆ( ˆ–ö ˆ`, "Æ@œ§ŠÇÅy&™û“ç}¼%Ì˧ë:Âá04MƒišG<®àÀKpà 7ä}Ž×ë…1]Ö(ç|ŒÅb³®+0}˲,§JRÎ )Ï[…B!¬ûü: ‘|´,Ò|‹ŠàÐô?ø'£‹³n‡‘Œ@$!uˆ}Qiù2Ó*ŠVXž\{GËAwwwµ›BTUcccèîîÆý÷ß_í¦TÅ«¯¾Šîîn~? %O~&¾úê«ÕnJUÜÿýèîîn˜’Dó%?8Pí¦,:~? xΰöφÃ"afÛpÎï¥W², Á`@š¦AUU„Ãa<ûìÎ8c7þðß_ð¹rîG¯×‹D"á à ˆó[9#©:âñ8¼^/EA8F<G<Ϫ <ûÚ³Eå 1ßá"ÉåìýÞ.dÅa!ò\_‹–t æ•,pÎSæÑÊíÌ«â1•J€3^r1Û¶mÃÎ;‘L&g\q°XÎ=÷\|ä#©Úú‰j…ç|©v¨/¹ä’Y盥ú3ßyåxøápf9Š’Ið¹ÿ.E8,ï®LŒÇEò/B™ ‡EÇL×3úÛÛÎ$0½^ñ8EËSUÑ´,º®;B÷°®–eaõê—±k—øÿ‘GþçŸW]õ@•^µêaŸ€HhmmÅààà’M¼­_¿ž}"dF+Zªßn¹åg-eƒƒƒH&“H&“ÕnÊ¢ã÷"ç kÿœ¡ß/Î ÅãâÜ“a”~îJ×ux½^g¾EÓ4áóù`Û:€)gÄ®|äЪJ„Ã3GòDE£¦iN²QÓ4g˜UG¢ÊÏ ‘xô/ξÔ4 ò;€ý€ö!ˆ`ÀG(+‹»ÑÀ‡L¶Šúúú*Ò'˜WÅ£\©Çãɺ½««kÆ*S©+ó-§µµµ"Ë&¢úÀ8@nîy gcšÀ²eÀÆ™¤œ®‹Î›¼_vØæ2Ïcg§XN0(þŽÇEÇ+ÈtårU5{žGy…š{þÆ\–%Ú"—!‡Ö}5]×g<ß¶3W½™¦‰‡jE8 ض .ØÍ›ßÀºuíuZŒDÄ8@Dc ŒDÔˆq@ަ%ÏYE£â<‘¹k6¶mg]¨ˆdb"‘À¦M·˜Û…÷ùX®!¹ ÀeYðù|€H$‚X,–U9C‹šô³, þCÀ÷èô¹3?µâ€H4º×iC ·Zé Í7œ[b˜×4¯Ä£¼ HV>JÍÍÍ3®’)÷—ËÍ 6™Lß™ˆãåShH‰ÜDœiŠŽÚè(‹ãã¢êpx8“d”ÃUHÑhñu[àóe&ó5U?9Dj<žY7 ’rÞÆR:‰ª*ž3<,+Åí2ù“Ÿ¼4=L¬‘Õ6@ÜfO?PÓÄDÞO=u'î»o=ŽYUí—o^ ˆˆq€ˆÆ" ˆ¨Qã€m‹sSâ÷üŽò¦xWW†††N§ðx<ضmÛÂî%¢ÒÞÞŽ×_½Ú͘7ÆÊ•/ñ˜¯ãeY"ùç_Q2‹Äaî…Wò*²pXüÈ«ÌÑñS1¤„¬HŒD2‰È@ {(ŒööÌüŽrèT÷vØv¾m±ÇþÑ€®‹õœ8qÂy~¦c¹DíÉ'Å$ÐñxÜ™ûqÏž=ÐuW^y%àÈ‘ŸTûå›7Æ"b "€±€ˆÆ"jÄ8 ÏmÉ ÒÌ<^oæ¶|t]DzeËF1<<¼ í …äˆ_†á éjY6nܘõØX,æ õš—nu¨*à?ºyºÚSHÆUºâ°˜Üó™D4ˆÊ%@K™tÌkŽGǃžž  ¹¹¹à\CCC@WWWE}}}رc¶oßǃT*…¾¾¾C¾‘ZÑ0 øý~(Š‚`0è\YòÄOT»yóÆ8@n™¡D3ó5ÊùåüŠr¸ˆÜjÆ\º.–“p±žHˆ„Ÿ{NFY);xùƱ2ë …ÄsdgQ¶YN.GºC£ævu]‡m‡ (À±cI7àÇ?þ1R©§*ðûULNþêô£U'É88x Àu¸çžg°iS€†}ûöAUU¼ï}¿‹ ,lÚ´©Ú/á¼1ãŒD$0Q#ÆhTœr+úýâœR4*ÎSåK>Z–…`0ˆX,6£ÒÑMU Ÿ×*E<.ÖßÞÞŽááa(ŠŸÏ¿ßŸ5´kAd®¡_Ìùà)À|ÄUà‡H<–±?Ê&‡@5!±•o]kî‹™«y%‘ÅÃÎ;122‚ÖÖV§¤YN>966†ÖÖÖ9OÖ¾wïÞ¼·{<Ü{ï½Î“mmmu8ˆÊeÛ6Âá04MËú1MíííÐ4 ápªªÂ¶mضP(4c˜äZÄ8@…ä&åmrø EÕ‹€èÉ”ªOâ~9¼j©s2ºÉD¤·Œ1ÕÃá0z蛸暇ñê«¢ÊP^ôuêÔ3ðz3 Ô‡z¦iNwÒøò—Aöx^xálœ8±[·~ð›¿ùcˆË°L.¿üñk¿ö,ÞûÞß ¢©é8yr-¶l9gÁ^s""""""""*<6ÛHb¦)~.¾ø~ø|>¨ªŠÑÑÑK:ÊsÎÃÃÃÐuÑhO<ñöï?ÃyŒ¢(¥U::›ó¿Q¹ÀUš„Þ%~fP NÅ-ä©u rf¤Â†§÷E'æ>ìªû„hÞûxûÀÄ#Ñ‚’ó/Z–…p8 ]×ÑÞÞîL° ˆ`=<<ì$-Ë‚išðNg:4MsÞ"ÙP(¿ß˲XÑDU'ç-Ôu‘d+ÖçÐuÀçWsÉ r,+“¬4ŒÌœ¹ LYõ¨(™ÏS9„©juxXü‰Ì^ñ˜o;ÊÉáG£QD£Qx½^ìÝÛŒ}ûÃÙgOà•W^`âÕW_…¦‰677ŸÀÏ@×u(Š‚ññÿ…7ßÜ U5ðæ›?†cáì³Ïv­%~íמ`ãÿð8Þ÷¾‹ˆJH¯×ÿüÏ Œ DDDDDDDD5ltTœËš-÷ÿø0Màÿø„B!Äb±^Õ¶mÄãqX–åºŒŽŽ" áWõœ²Î›åDysÎÂ4ßøÉKγ؉ùwZŒ ”ÑáBbÓû£Ôv¨ª8‰®ÑÀÄ#Q=1M°, Á`>ŸÑhÔ™ÔW~È`í¾Äëõ:‰CÛ¶D‚¢(N2r¶UU³>ˆªÅ²DÂN& ;]ÃضH®['’Šá°HF"@"!>åU]¶-þ×´Ì\Ž2w&ˤ£\§\¿{2îx\$7çʶç_íèóù ë:b±B¡ŽY…#G^š5{áñ<@óÏþ?Äã¢}^8@T@Ÿ~úího?¸òÊÝPU1¿«HÆñö·_8½´¬ßî ¤C‡Îsö§·œÒM""""""""Z0¦ ´·žšO², CC @ w*G«´p8Œh4Šp8ŒH$⌾ˆóÐïyÏf,@®S$Üʘ¶©"TˆáHÛ«ÜŽ€qˆDl¸Äçx½âÄi¡AÙCÜ.&‰Ê$“ŒëÖ­ƒÏçƒaÎx×±X ^¯†aÀ0 gEÓ4ó&ÝIFI&f«xà$&YÕD‹-ΞsÑøózÅÿѨ˜ïQV&¢5<,.ÄQñ“HˆV(”ùŒ”÷Ë!Vår5-3ôª¼OêNPÊvÍ5'/‡s+Y¥,+™Å±kbÕª·ãÕWã©§ŽáÊ+ŒÃ‡Søà÷ãòËŸÇîÝ_ÇêÕŸìÞÝk¯=@;>ò‘ N Ë ;ǺŒ!îdn2rÏž³ ÊýÃÄ#Q-’àÏ&ãÊ+;°fM3n¾ù抷Ã4Mç'`||¼ÈcËXQ¡ÓTˆJ¿ªzÔ4 q-0*ò @búg!’ sIü©UŠúÚ’H,@£KÇÄ#Qá°¸ŒÀ0 D£Q†á ™‡ÑÞÞŽ7²,D"„B!ض Û¶á÷ûá÷û …šÎ„È*GÛ¶ó‰êþßëšO&fK0©@‹!ßüÄrìùéC‘H&Á(ßÖÑèÌD^4*ætt'Ãaq[<.þîìË—s<ÊÇÊŠJ¹™|ÌM2ªªXV¨Xg¢÷DÝs¡ëº3«tå•_G0x'N|¦Æ—¾t šœyæ—ñì³—áÃnÅ‘#¢’qýú•×ÈTF{½Þé+Ë,g¹îÉ»UU…¢(YIÉ5k~ ËÛ>—!ö‰ˆˆˆˆˆˆˆhqiš¸@¿9…×m·µáðáó©«ÎÎNtvv" "‘H¯ÐHž%± Œ…¨~ÁÊn Îú–•’ÄS ’}•N‚εâÐkß¶D²ÈôÐõÙ']L<åˆÇãØ¸q#:;;d£2ÑçóÁ4ͬ¡RÇÇÇEUà$£ÑLÔòz½ˆD"Î0¨mÇŽAHBª2¹ØÙ)êèƒA|võjñD×Äw?;u ÷\z©»‘âþ'^Èxr•kæ^X ã®~”ÿ¯^ý2&&*Û %"""""""¢ÊqôUˆÏçsæZ”E.@åÎù†7:绕Z8™¤A$u¯ò[hé*“|40÷dª>MÓ°÷þ!»Ê(Ù7¹l×¼×Ü}·H NW.¾¯µUMdVÄ¹é&± E·'xâ–[àéëˬoú±ˆÇ³'½pÙÙgcS:IF2ñH³ÈW×=ÛЪ¹Ù‡†-H0Qâ㕇AÔ»nŽOˆAT)ÚIÃrŠ ç“¼´,ñæ°,17¦Ü'6€Zb8Øç\Ãó¬üý7&©®˜¦9c˜C]×ÑÙÙ UU …àõzaÛ6|>,ËÂèè("–…ýú–-[†eË–9 J¿ß‰‰ x½^†ªbÅáÀeAFñ·/¾ˆo>ŒëÏ)1çc¢Úp¾¼æZ+`Yâ—™fbHEÍ~êþÁvÆ êÜO¦.€åÕnQ©lÛFg§ˆFòD»mÛÐu±XÌ©öquêõz¡D£€mC{òIܦªNS p–£i¢Ñ(v^y¥È‚h (xÇž=ˆP?øAÙ‘eq'LSDX×ÉUU³‹A3 'iªiþµ³'˜çK4ä^ÉRÌ5}}"Aš[ý4<,*5k ðPíäâím"Ñ(‡I•oyYÁhYâ­‰ˆ·½|¼ÕýöÊ×ùÐ4‘—*ËBÁI°åcJéóÈX`öïÿŽó? :VÑhúty§aPUÕyŒeY0M>Ÿêt¬wž#“‰Š¢À¶mƒA†X,æ$3c±Øœ‡¢p' ÙŸ{B±9]ó%#ùe‰ˆˆˆˆˆˆˆ¨*t=3]4êԴ̇ašfÞ¤ <Wª`0Ó4¡( €3c ”RÕ€H>êI»9&]s)ã™yÝ9Ïb¢ú°Tæž@•¯¿{$F]'oÏ0®Vø–W´Ë‘àÌg§ï˜x¤:¡ë:¢Ñ¨så…LàÉÉnó^¿ß/2&ѨÈtLGnÍ4¡É’ª`ˆÅ ª*®ê)à›ß …0‘H ü裕Q?‘ËsŸè÷zEåá´|‹€HÈá^UU…uå•y?M´¹^ª’K~bEb¹;$ûR"d'u=3Ä©ü-‡QÕ4'ïEB²ÐÕXîy%9Œª¢ˆÃɶó_%+&åïÂí7‡¡( âñ¸S™¨ª*Âá0,Ër* Ã@"‘€¦ihoow’Á`л> 9󻨪:£z1wNEMÓœu–;þ}%GF•W«I–e!#ct®=S""""""""ª9Ò—û¼\>òBz ¼étLÓDgg'‰„SáX—ÓóÄ ví Àæ˜ð³Ä‰IÛ†^:ÿ¶hÉÐðt{bÓ·•ÒžR’ކ!Þ$òĨL»O¶Æãâq²hI…H@F!*2ˆ$£û¼­ qÿ’ÆÄ#Õ9¢L2ÊÿC¡B¡ÐÜNìÇ㙲݂A‘ípUIF<âZ×rË X·.“ ÌT.™„È%“ò1…dmŸíú]jUU‘Ñi‡¸²!q%H™KhÞñŽÊ¼XT—âñLán Þ†!>·dŸÃ0Ä©Nõ¾’xôû3Ï‹Åò¯Ç=Ôªû6ÓÌ’ÅgÓŒÃëõOÿm:â†B!gXSkz^UÃ00::êÌï:<<ì ¥*+ý~¿“4F<w”±é(tüæã~\Ù ” 7‘8¹]òJ6¹ÏþâúëFqýõ×/x›‰ˆˆˆˆˆˆˆ([4š97—{ѾL6躯×;¯¶r…B¡‚3uE0 ‘<Û‘ð+µ`SQ2sŸ¯äJEÃ0`†sE›ÜÞ]«WcY<ÀGúSà½ï]´í&"""""""ZêÜôƒââ|÷)"ŸOLljDb^ÉBÛ¶QÂt]Ǹkľš Pãâüõ\«/erMƒHªÉ9 ýÓ˵,qBѲÄùÿˆ £xúóÞOT›l;3Ÿ°Hä‰Û£Qñ4*:5òs0‰F9Ïb<ž}{^G·Rú(Á`º®Ããùx½_€|£F£QÄãqœuÖ—¡i"Ywðà÷`š7! :É59œD(ô¯N’Q&óUUÅððpÑ ÜÈÄ^%Æ­—qÌ0 èºîÌàóùðÿ·wæñQ•çâÿ&BH2a"0lbÀ…kƒ[ëDA[z'i­ ´2i½­\åvrío±zgjºÐÅšÁµjMÒjÕ"hæº3n\ "ÛŒì! ùýqæ% Ù&ÉÌäùòá“YΜó¾ï9ïsžó>[EEyyy”••”BÕ%ÿT4¦Íf DÍf3sæÌ ´±"ÄSIÕ˜(Ãd‰ÉN'3Þ~›á))xõzÊÊÊ0 \\ZŠîë_'99÷É“X­VŠòóÙa4jÖdôøÃÕÕì¾ðBæ÷ê•)‚ ‚ ‚ ‚ €¶þæõ3cZ,Û Ky`ýG¯×w+°E9¨{<ŒFc`)jŒŽŒjxÍ­ÁÁðzÏ^ð2‡CÛV-€šLP[¡ó¬ÐCŠ VÍ(ih§ ¢}ª¶vÞ¹ þU6‹Ð &§3P;Ú)l£íhkúN‚[î¿P]¢ŒŽ †G!‚¨hœÐ©N§“ÉDEEEPÀÍ™55Aïü!äˆE«&OÖ&rIIТ&tèÄnnŽHû[ `•êÔƒ6! éšáQ õk4ªFg7B–ž›Z½7ùþc”´Ó.£ÿØÊóÃãÿ&š‘1¢ƒÂBí>«¦‰Á M!»]s’q8‚u†Ž ‘143±2>*o«ÎÞçv»=¶´¼¼œ²²2œNg =¨ÃáÔjµÛçË/ÏcΜ›0 TT”øÿjÊPyy9&“ ½ß˜ÖÒhØ#bGFÇÐB‘­þ«ô­Êàh4q:TTT`6›ñz½˜L&ŒF#Í~9¤d]hDghf^^z½‹ÅBee%÷,ZÄŸz(0^ze5Vá©&&³™|·‹ÅBaa!/8AãÓO3ä»ßå`z:Ö«®"SÉS§“‚êjžÕéøö¹çò­àÀhQç-R/Ì6 —ËÕGW© ý†M÷y¸Pµ~½^ضí rsOõw+AAAAÇ~³Y[×›<ù………~GüÎZÃÂÉÏÏÇ`0J‡µÊî×øÓÅb2…×y²Ù´HÇP› Ñ¨-Vv'˜f4ÔXg7­FmÝ<д:ŒÂŒ}&«ß¬ Ò²†>ËÊ£/òò‚Ç UUX,A{…Û¾°jðÿWË“*XɉÍÞ£-ÛÈÐˈáQè'Õn·c00”••<3áàn·&Ijkƒ;1´Iåõ=”àP_ÝhôÒµb®Jè9мl † ­£ ÛÂàÿÎëÿë愼.ò¿nÙ.'­ ¼Zeþ}xÛèŸ3ä½­õß'ö?ÁU\Õ½±ú‡#h“W÷Qí[1y2k\®@zÕPfÜz+–M›Â>ëNrA¢å\äöÿ ™ÎNgÐ)Ôá€n8I}ý<÷ÜTôzæ¹zþpéLq%åË~üÄ}ÌJø„ƒon¥œr>N_G}}y÷RAA!.Qëz*P®åÍúõ7 Óy))©èÒ~óý·ÛMeeeûë?ååÁ€ £QkÔŽ«©t6Ê˵Ω”j •OölÆ4x£Ö½Õ¤ÛtÆw:ƒµ¥jk»×^•=Petnx VŒ4Ö~9ºæ§Ö[FmÆ bx:D”Ñ 4%¢^¯T¾GÐ&QK‹ÈÙ £¶¢ì@ª¶b9Ú‚[­S‘¶…Ý¿]Ú"]>š1¡Õ;T]=þý‡Ê-•Õƒfp,ò¿Wy˜Õ  ÍÀh@32*Ê ¦E Emcðï#4ºQ >'g5Š:-d¡Í è&£ym(¯Ž6Ï'B ŸŒTTeùTöa½^‹Vì ¡÷å¶tƒ!|› òò q:Z†Ê‹Êáp"óóóÉÏÏÇjµb0Z«6 X­Ö°šŒ-£UäcWÈËËÃb±àp8Ç 5BªZª&£jŸjc(F£1<2Ûã w„•cn·–^A¯j‹ÊÑB tIIk…ËÅb [bµZ;sÇŽƒj[t§€ ýòiP¢åÈ‘ \¾n>‚ƒ‡OñDãP¾9lµMÃÙ×4 €[R>åDÂ^’†=ÎO|xIN>η¿ýmŽ¿xœ’WËÈó7fÏžÍÜïÏå‘£0¢nW×^ÍE\ÄùïžßßÝAAAˆK”oºÕªùŸ·\*,,  »R‡QeùR¿s:­ÖÛÂPéM[Ø<þô~ƒ¶^­¢Í_¡õZ³Ã¡ýW)OU='Ew3o…ÚÔþòò´vG¢N¥Š²4n|ì ¼^­äœÂno²¬¬—шáQ4aàp8 ø*LÛëõj)•§ÊÝÕRZª|-CŸ[Ò^ÚÓ–ÂCÕAT…z‚ƹ"‚цªöaKœà¶€Ñ^=è+µŸh@/¸“ÀXD0…ª*“v˜,S£ª:ÿ¶þ6ئL-ô·E}Þ–“J‘Ö.Ttv¨ÐÎóïß ÃmaÃâ zÉxýi\õ*’SEc¡hÍá¿3´ßNŸž¡+Gˆ$*¥·šb6[¸±¢B»§G2k¦ÓéÄãñœ|=^ï8ìv;EEE †@ ÝŸ_}ÇŽãÙlÆd2"ðZþ ¥##X¨ÑÑëõ”%¯×Kaaa /½ª!k4ÆLeÐT5!éW€ KÀQ·£ÛôÆr»[[p‹Š‚žUmEšLA%ál O;ßÍÀÚUãkEE×<áAè'¼hÎOJg0‚;Vüì$—ýgl9‘Æø´ý¸·9Óœ¸IH˜Ìÿ5'²™5|ÎX<¾‘ãGïb¦>‘«N¿Nžn½´¦Ø&®`êsSƒédìÐtA/W¾Ì¸qãxê©§Z=ÈŽd$iÅi¤§§÷÷( ‚ ‚ ‚ Äj JÙüZRXXHyy9]Zr8x<jCŒXa™ÄT}¦Pc]{é?ïu@©( fî3\k÷øÿç¡­3+ƒäyf0y´cõ¶ñ¬7Ö¿ô´_>-bÇÐÛ>3‘‰á1ŽèL Re4MM¨<$Ýx#³Þ}—Y™MM¼i6£pŠŠ4˼ ²Û!ÙN'è æ@*fhBÉAÐ æE3ºyÐ" •w•NÙbÑ¢½l©`VsÒ^¿üt8Àðk0ïÊ¡h¥¶ûŠë@ÿ°?g¶ß Wä€ «Öô’(œVnÂ9Pñkð.֚㞎÷Áñìx JYÔxt»JVþb4¡ìA3¨¸Ým§CTa¨R(kµ Ë7îwx&“)PWÑápÞFÊËË©¬¬ÄívSXXÈìÚZþ}ÈþþÖ[Ü5m3,–ðAÊË ¦?5™Z j›–m¥UíŒ2 +Ab7A*cð37šc„Ï÷mtºClÛ6?N⪫¶’öBS›.á¯ß½ƒÌ/ŠXç¼€Yì$-q,+Fpòô0þœ|€OÌeÍx >^ÃMŒûòϬ=—‹/n)ŸÌí·ÏïÅ9˜Áä,Í¡daI—¼gAAA„îãñhËTVkÛv¹P££±“µ‹ŠŠðz½ÆÖkm^¯¶˜¬ê"ÁÚˆg#˃óa¿¿¦ahSÌÞ`ºS‹f™@oö¯mëÁ`Óƒ&4TÚÐ2Bpº=›[{ÁIñDoÖÑŒrÄðŨ¨'ehPõ”¼p»ƒ©¸T€ÇÓÚ0¡¢åååèõz¼^o í`NÎeLž\Îìuèÿ\LùQ æ3¸àVlÖ;5P¸mPióôSÁS»£GÇ_×ëÕ [v»Dd(ç¡|˜÷€³˜ªmã9†BðžûWÀ¼òÀ|%è‚épTjD£?$½¨H3̲¹Vj†AG:XCÑ£à|,׃m è«´í”aO8iã¦ÊJÚ?ÇP¨,Ïfp?†Tð ½òó49 `´h7 ¯W“E³ƒAQ%¿ö/Ì D-ªcVV‚ýcpÓ‚!U}]Áè4=Ä¢äº'ÄPZc7´Ô\a!ÔÕUóÃ&ñÇ?þ³ÙLòñT.ofüøw9~<™¤¤›ùñ“€TÞ{/­¿/ïü÷¨9íõF6š±%N§“òòò°­˜L&^ýc,ø€aü­R~*ƒcg)**Âl6ãt:õ+**5!óó󩬬 D2*…©¤¤£×«M§“¿ç–Çã¡iËìçœii\™š 3f´>°2¶.l0ôî  U;xà9­ 8”s–×ëå¦?ÞÄà7³}âvvÙÍ•ï]‰Ðcäù„i|ÑüN°”o$îáø™ R÷éIiÈÁÖ¼ƒ}Ǭ̙cgjíp®¼ò~ðƒ¹çi[n0™¾8¦ÁcÀà1€RM©\|ñÅklè3ßGd‚ÿ_@Q uµõz¹à½÷ 7·¿‡YAA!n°ÛÛ÷y/**ê´ÑÑãñP^^ŽÝn§¬¬ ·Ûݪ„Cm!Ùlºéˆddø£[B£ ¼^ÈÌ Ö]4a4áÙû”Ó+K‰©òd¬¥¨ÊŠCþ«4®ñWÚPð#†Ç(D•+/¾7ý¡ÙÃk¡¶ç†Lœ2±X‚rÅbòà(7ðý¯meï.?½ÃÅã;wòÄ¿àÃôs1Ô[0è¡ðHÆ}ë±U\0\회sÿï±Üq÷˜ë(vd; ÿqpŸÏÐc8›f`›ÎK VåG6kÆ¿ü|0 Ã<(,@¹Ö»V÷–æZ°_ÎÁò¨}Ícâ*0O…Âm{ù§ÒPÛlÚþM–z‚õw`¼lI`x&¯„’Áù‚&äõzmŒ**´}Í™4ö8`¼ ô¯w˜ÒÁ='Üðg4jÇ„`dºÛ­µÇdòo›ªÝTÜn°^éÏrf33ÁZÎýÚ>½^øÉOš8眣xƃæÕç$¼¾¯7x<^yå6lØ@}}=·¿¾”±µ9œ—´š=CW’ÑðŸdlÞÎ>Æâc$ç?Å×/:Öç–jP¯ïåýìÑ|¥z>Mï5¡_ð¢?züüã‡?äÎU?,ôaKyI)/U³¬!7‰PYi0ø¿·†Gt+Åí~—ŸïW[< z½\øþûœ¥ · ‚ ‚ ‚ÐÔšuKÛ_QQQ YYYY‡FG‡Ã(Id³Ù0˜ †à‚s¨S©Ñؽ”¤f ·ž²‡®×kQ4gkcè³l¨±¢Åþ!h˜ E¥qâ1<ö5*ôÎbÁ«7R‹zf݈cS.Nÿ,õ žŽ>; ½^T…·7àÙ›‚‘x0àõÇ!¿ôR{÷¦’²—Éïý‚o’KÊu¬å'¼ùó)L»ð}®»î\qE*s‹ÀpÎI*¿ñ(¶v`ßx=…yà9 •RüL4æœ öB°­Ñä™2àY­0y28šÀüUà|齬@áHðœÛó`<4Ö©H>ƒ2µÏ,V0ÜÜæ?¼ ¿OIÐðײö­ÉŒ|Tö‰@¤çE`\­5§¤$¸n§¢BËÊ´mË˃u (üLÇÁºìCƒê6›Öί};ï½—ÍŒÏräȬY“ÂÍ7oE¯ßÁàáϾ·û"î½wëÖ=‚ÅSˆÃa ¢^ý9tº±—ŽâÖ¯½Å÷¾w'Oþßÿþœ8‘“OÞÆéÓ Œÿw&N\È;ïœÏ¾}ãxíµ'ÐéÖð·¿•àpxyôÑálØ ˜¸í6ø¯ÿšÃõ׃ÅR€Ý>¨ Ñ#Z»¿žC‡à‘G.bòdÈÈÉ™3Çû{& T4²Á46ªë¯¢"èTÐ]¼^/EEEØl6Ünw #(,m6›ÞQeeea9ßM-£|p™vŽššY)>ãÖ¬¡þ/aÑ„ ,©©!sÎ0›Ǫûè#>v¹øó¬Yd~ð&HTè®Âfk;á½ D#4=3šòÃzª¼J󬲩«Ï•“„r¸Q(ñ¡J?+{¿§ÅCƒÊÌ ‚™•Sø³¸øe Ót¢t:ÃE„Êv`2ñ(¸·Â‡õ‡9pôI'“¨kJdöl-B:)écöìi`ذË9uj+cǦðî»ãùÞ¡syâód܇àÁ:žæ£~æóLÞ’Gí Lª¯¤¹¹™gšžáš×ð‡óÙÆµ¤%~/¦$àÁSéŒ}9W_´‰ªªËغ·e½Ä?9ˆmÝ÷øuþzÔx¨¯ø;9xǬzÍÍU_TÄ¥¥°}»&óZ¦©(/×ÌlÖ¾oéH¡d¥Rœ-žÞ”ŒÏÏרjÕ³¼¼í‡Fƒ¿.]ŠÄ; ‚ ‚ ‚ ôœÂBíñ+ôqÏãñ`·Û)//ײ}µ•*5•±Ðfµñâ/rëŒ[—}Rs4U)ÔŒÆö3~u…< ÌØvTD$Ó„š:x/Äbxì)ut‚¡ÅÎÖ I™™U4çìŸâ>|w]Ð0aßôfý~¬swQþiæ2dÞaðîЉZrÆ`ªÒóå /ycôóìÝýMRSSøÆ7ÖpéÑÜóæhOLÚiðìŽaµØ_€“¡b6˜6$É¥XnïÃPäö§[N@óF(B[4+ÊKÀ™ŒøS¨×eeZÚQã<ÂÊ ™J`G¡64E \B¯ÁžJ6€ K ä¸‡DC1›ƒrõøñMx½ãðx<èõz 3o9Ié˃©~!€©S}lÛ¦£  ¯7ƒ¶àóOR’“é’’.ÁñÖBÖ 9IáÊoðÈ#r×]¯3|øO),LÄ`¨à±Çò°Ùlx½^¶n½ãÇ/âÔ©÷ñxÎàv»ùÁ¦“šú Ë–]ÂCÙyå•mÜqÇï1®çž{illä²ËÊ8~\Ï=÷<Ç/¿|%z=47k}yôÑŸâphF_«l¶;€;´q5éibM¦àâî­·&ÂöUJZ56þŒ•X­ÁÀ³Žóû{æÄ=NgpÝ·¬Lÿ²²ð9Ðz'ÊTE*o)«Õ¨‘š²Áëõb·Ûà M·Àëõþ †@ZÔã/¾Èï¾ËìÚÚ€#Ó»W\ÁþùÏ@ÚÔõwÜAÃùç3ú´µ˜°_̧ŸæˆÑH¦D# ±ŒªãkG«UìA«]a…Yéj*•—‡Ûëm6MÖƒ&ÓÕkÆàý ¤Ä¿ž žÝà=vÈóß;¬VxçÖ¯O k‡Ý¾«u6Ç×rÇMO±òñ»ÉM9Îǧ“8Þ˜ÌÝÓö°¯qŸ×72"ë5öÕÍädÂ0<_9rgÎfÊ”ÇØ¾ýNt:Ëç±Ú)Ô®'aX©GS©t˜ê“‰l:“LÃÈw¸¼iÎz='†àôCÔ×Ân¿‡Y¬á…_5ñÔ©ñ8Uìb8³MyÎjÎ4–ù§Gñóædð?Ž“, ‰wYÏýHúˆýgV°åƒ;87é ‡›¿Âï2'Pqr8ãÇ^ÇΓ)lIÊæï‹qnS=˜ìƒùž †à˜ 3 ¦¦¸ªŒ«r µAWi)Be¢Õªýw8‚…šC.:›ZÝ@ZF0ªP%ïõú §Õ®-!‚0 ð =„ƒ¶6¡R©µŠP_/Ú3¼°vá‚ ‚ „cG»—hÏàååZ°Ñ¨­µ•——STT„ÑhÞÚfì7mÀ4c8dù7ËÚŒþ²,_ÛMþÿÌÀ¸œ>í;O˜ À—Pf ÖÑ\paÛïÙŽ~èÜÕzŒüNÜPå¡yš‰¥ºÛ±œ¹Š¿î?—ĤDJ&Þ© ”;3ؼ`ŸöiÇ0þœVÅZÍ&ðú#0¡  š°ôBùàÐå‡mƒJ!ÚÊxbŒàø¸Ë[¯‰)¬Ö`„ƒ¶¿ áC¯×óZS"Æ6L& yy…Øl6ŠŠŠ°X,ÜqÇe$''“—·‚§žÒÒ5ª¿}´È-7©©³Ø½û~ÒÒ~ɶmÂãÉgâÄÙºõB&LÐa00'°{÷>ª«Gpÿý²²fñÎ;  šU°YYÑÚ=a””ÜÖ§›nÒþ P\<³y*Ü{¯’ðÚ`ÝsvRk‘*òR½.,lmlU÷%›-¼>`èz¥Å¢µM¯Ö±„à¾JJ´×C†ÃëMí°¾°ÐyÔú³É¤ù€v>Ôrg×’½þ A¥SP5ZN§“ÉD~~>f³™²²2ìv;?=šYãǃɄÉdÂf³i ÞEEè[‹‰èp80TšL\;r$Gvîä¢Ó§ù\7žÂk¿ÊÎûSS¦ÂwsÈ2¼ã{©ÍÜw¾v=[ nùË-¤Ý”ÆŒ– ~9¢ E›æÖ)TNwД µ½Bïÿ\mª4ÑÆïôþÿž³ì#ô˜¡Û„þ®­mŒ!}2´±½ß„MÀ´k œÖŠ{ T½få,bHç`¢ßhøp¾ÜÞ:Ü—ƒÞ”“µ`È‚ÄQuüã*/ŸVŽDŸáeë«{¸ð ÔeWóåŽó˜8¸‘±©ïâýd(³gk 4Íær¦Œ¾–ÿÙùœCìç]LÖ ÜÕì0‡Ë©¥ìØ1``¸ÍÀÓÙŸsêÔ)޽>˜§Æ?Íö‰Û¹(ûºw¾Ïxïç\z"©ISÙ\ÛÄØ±û¹ºòjö ÛÇïšKx¨ö!|n[Ò¶0nß0l“~ÇÂáغu+É_OfóšÍ\× ÞúÍ[üøª«¸ô…¼tîîl:Ì3ãžá{¿ÇE'/*©K¬ã÷w¯â®w^bÑ¢EÌxúižúýS<ñÄÜn´0bÍþçúÔ7Œbòé/X6nã.G­­–Æý|ñ•/xxj&ÓÝ-ÎÐ(ÿßsy¿&$œÁtäï<2f7ú¡ ˜FÈ‘p›Pœ-íèÍT¯‡;‚ÊMKg õÞfÓnÒž^Ê+ú0«¼Ž!ÌîhF\+”óžšz¡ÑÜJ^+}:t{·; ®ìû*ûJh úÐã@ðY'4[‹ÂlÖœ •s`Ëhoµ•Т¢Bs"i¹Õ>£QÛWy‹ûRèï”ãJh°´É¤ígëÖ«úõÜ íà¤}ýUé¸J—U Ž&ÿwè(èÑÍt®fµ¿&1NeVP W,þãy®;˜B¶W·¥òǪ@[Kqú_çÔ»Õ1ÔïŒþ}ÚCöçF{ìWNX%þïCëKµµÁçƒNÂ3Yø3:­·‚F^B>󴨇“p'uµ{gÈwjœTÿ[>Ç(ºú e$ø|F¿ yzdh'.A!ÌÙÇÞ_ƒçuMoSFG§ÓI~~>ƒ‹Å¢­Ó)¼hrß ¾k}|þÿ>ç’Gr'œõ6LûgúŸ-Õ1`( ÖK4tRÆC=á÷Aùo õú•Ú‡¬ ½@Ì‹‹‹)--Åçó1þ|–-[FvvvïX)Ùj‘ÑŒ¦(šÁk÷Û༿ wýßðžw Þ'ÁpFs<0 ï™Ñ?÷K:L³À:^yû4ïO8È›ïœÃÏÇmᙜµä¹×âÌtbÄÈù§Îç£VP7d?yÕÒ:»žÎC“¿m*퀌ƒ7Ï¿öÔ†Quèý}Rßß úgÛ7‚“o¼g#z½>`4-*‹q&Øg`ïÞõäç¯ÄjµÒBª¿O¹¿‘ƒÁ€^¯Çívc6›yÿý fϾšÚZ-’Q…¡[­V   榛NrÛm­CÁ-Íx×Ðp>cÇÁfû EEPRbG¯‡Ç72y2˜Í¦ÀÂÀã«__„Ç{÷¶~øW˜LgV³Zµ‡úö‚ l¶¶S֩󢌲- ‡¦ªmkß%%ÚM®¼\‹®ózƒÑ“\¤¹å–¡×¯&Vés9j03 )' üsðÔùv°¯o˜/æ‚ÞêAºíØïE‹…£í·³þÄzîØ§E¸<ç}ŠL#¨a¸ùç5—òKþΩÓƒ'æÀäÉ”¶1óÖ—oqÅW°|ârVTÜ`Ÿ À›Å8nÀRma÷ŒÝüÛ¨c͹ãœç3Qf iŸ5 6σßCªj¬‰€ÃEiв½zˆUrC)Df‚‹ê³ ´…/áçJž™_Ð0…¼V¨T—JÉ2´8hž_EÔ>”\WÎEþ}ØZŸ*кÇßw/­*B~úZ-XüýVÆ++áãæ Õ7­BWTB=Ô”#‰'äuËE¤mI#Öé5Y VŸN¨J»IóرGÿk§ØÆùþZ¿ÿóx(ßÎÝ ×ñ0ŽÓDà8™p£=™EúFnŸz˜/§½Euu5_:Æû“w$™ÙöÙ0à Ÿâ3Ò:#IDAT_ñß ¢ž'y‡-&pǨÉþ¶BÞðálÜRÊ/¯ «!‹G&È]Ï[B'Ûyå¢W¨ö"ŸOû Çç·—þ–}ûö¡×ë)**¢¢¢‚ü¼|ž|òIœ·;YÿëyõÑW¹á†ØóÒê'Ôó‹´_`4¹Ðp!žs˸ÔlÆáp0Í2M–ßré÷îä±É«¸þúëÉý8™mS¶pΗ级‘_2ƒ´´4öî=ÍìÙ³á¯?½ž¯þú«4»+Á«Õs½Ô3ø,2¼ü7·ðß—N·›^v”>Êý÷k5 ï¼Íï¤jü2FxÜÆÆhŸ©âÑFcðæë÷*)¼Í`ß¼ZZ- ã´ÐìÍ5+t›~{6ˆT©EËì¼CЙPeQ†9°«"« † QNîTv§Pƒ—2n…Fj«@_¯WÛŸÛœŠjšUVjÙ^*_ƒ9_o«Õ { ˜.Ó(úyø6ÏCÞÍÁvx>ÇsÁïF0Cûqª_wn¡o{sÁ³ÜŸ·7•‚:L—¯ OŸï~LÀ;Ò?NGÀ2Êx©×ƒa,P ÞÐûÀ{î?7:›ÇiŸ…e¡ÙœÐœYHF„dÔ˜Æ@½¿?;ÁšÌö?ÿ-ÔžHý%Z[^}µª¯ÌÈw²ÀøçC˜~¨PF=¥ï)=¯„pÃ_Ëß´DéÒ…!ûTº|{z«2d…÷BõM7ˆ*]éÜ¡Ñ^ÿ¾­þíÊüß[[ì/ÔÐzëTû¶€{ÿ+å hN ñ< žþ[¯ÿØžñàyô¯ƒÁ n% r€5`Üîz GÀ{¼ïGýÛTƒa88>ÑÖd,fp>l÷60ŒÃÇà­g­6_÷‚û·ài@›Ço‚e8vûOÑI𼨵‹1Àt0|àw\óÃÁ²KýmÔù ¸=à9¦4ðÜ åÃ9ÀåZÿmhŽåz˜ Àù¾Ö&‚;Œ›ÁÄlíŠìµÜÇÄ,¡Ëôªp»5¥·¨uÃb#å+lþl—hvBððóÿø+O®|‹Õ‚Íê~,ì^VαÉ/0ô‹y¼s|\ M¾&¼×üýv'IjÑ×Rî¬ÓÒúugªµ¥ HÕ#¡—ˆ)ãJ`³téRž{ïül(4xw€³HSúÊó4ãNy &ï»pj6ž(ùèÿs´HèûîÛȸ“.Nîo„ãoS¸ÉƒÛãVgínÀx¾³ÁH—NzëvÙÀ`÷?€¶!8Ôâ@K`U§M¥d4ØívL&ƒÁ€Óéäøñxû®Ù×ÑèG-“¯»áE7Üj tì³CÚ^ª×²vúÓWãýÏî¢ðó{pû¦‚ØKïBøæ¹'8/ñ n³™¿x÷íóÑx4•'9Ã{wâ&&nϪâú!3Øœ²†)¾D꾑˅[ÏeÑË‹8vÞ18™ÇPýPžt˜)Õ7óÊE1ÁlÆçóñqå{ï±àM-\òZþ“<Àö³Jòêó())áÈܹ̮­åÚ¡völ¦1ŠmßúV ó”ÄD >úˆ1ÿúWܘÊ'o§¶²Œ3˜ñ›Œ)ú-Øí\ ÁÕw€8·ñȸë.¦ðä“|ÃlËÔà8——“‘Y*\©¤$ü¥Œ†ê3õW-\–»ÃC†”U#ô&ÚòÆÞ2Ò/´† #RÅœÕ>¥ÞlÌQ@,m©`µe© ½Î<ø½Þ m˜ò_—6`Ž/Gq“Žqr=îÉc1.˜Šû¯ÀT0~ãŽÛá <š ÅdƒÇêйÌ »)úD¥CNÁà J샃)“ À]ž@?Ên„¼Rí}å#wW¸#´íNð>æ¿}\ †:(ßìÿ½;“ Ê©'<…Ácõ`¨£˜úÏü¯ Þ ·ƒ¹Ü¿¿É`ªòßšCœk 5ÚmQÖŽ¬Çã¯Ao¤ý‰ `¸+~›Âh7V¼8ÉÄ@ ͸WT͘õ¿¥„yòMº lÈÏÄÊlØU¯¼Dņõa§øKÇuü í\&¾9‘ÚúZŽNü5ç)uÂ==<—ÒÊ…dÉ乤çxaý¯æØÇMW²yê唽w%ÿÜy%¯¾À™Ä3œ~ã4Ûv!¶çVðqë‹«Öà kKéÄg±UðÀG`{kyØ÷›×Ý@fÒýXjgóÖo1ìÔSX‡ëv=VÀÛž <*Z„Ï}L𙓎tjªD#ý¶NÐæ ) *ΆÝçF3¶©(½Pc ^ÛÙ¿­òŸR½í9¨ß¸Ý`yìÏ×€éJÍ í,o!0 0íÞ†­V¿³•:vQ¸ú\¿wYäûo¿V8íÁÌO03¸#_ko…©u¤¯Í¦í×íö;$؃·tžðWH¤oÅ%÷3ÿ÷~yhù¶=:ì¥Ú1­n(ª×RRy­ƒ1d5`»¿üEã0f‚y6”?Ó„wož½)è­§0Nõa-LÁ½C§ùÁ¾ÓœÒ zÕ`¾b?žä¸ÝP=¢šÍî69Ãé3gÈxíç¦à‹¼j*^¼•¬¬&LÛÍúí©T7œ±û£7Òpõ$ª«§pôè`>=³Ã#O1èØ1Ðüµø|ôF6ߺ½{SX“Õ@VVS¦|©}ù 䌮åÔÂmÔÕ.aב#TSIc‚ŽQµà…sëqñÄu¸Îý&'²ôãDé1! „vq»ÝaÙžT:J·ÛÝ­ý©}©ÌhÝÝO{¨õÓ–ŸyÛ‹`ˆð±ÕqÚ;žÁ`¬Óv•±cÇözz‹^‘¡ë:wB“ªõ¸o¿¯nåoÁw¾Qå§p]êbÆÁ\g%²9u3C¢Ýûó¤9€›“úqüaãn¾zŸ‘¦+š´uî›@Š ñFBshþÈ(Çd2<jjj0™L¬\¹’ùóç·û»{«®ºŠo¼1Xé#'ü§)f Œ?žŸÕ×£Û¶±cÇòQ]Ùÿïÿ±ô¥—jÎ;N¬V+‡ƒ’’G`ÎZ­Ö@MÆö‰–sb ÐÕs½áïpmvñ£û~ÔßMï=Ö ÆÃw á¸RÍðiY0ŠÕŸ*˹܇Ás$(s}ô “'á7YÿÃÓÏã–¦Wùê~'¿˜p%ì|9pœÇÇŒaá¡CTeeqrÜ8ª§L!ñšk(·—sé-—2綾¸ò=mz›NGBf&ù^/¿üûßÉËËcÇŽ<}ÓM|û‡?äÍ7ßä‚+¯ä㤤0½aDb"Gkj˜9n\0'kË„ߘòÆopÕ¹çúûg ÿÞáÏýÝ–a%ô¡µ;jûššjjjÈÍÍíï¦ô)]•ÅÅÅäææÆä8õD'X¼x1«FCi‹0¢Êæðçƒkò´çŸÏðÛà‚ëàÚoSîW£Ì×<‹ã‘¼º4<ÍZÛÃ)äÿ|ž½`] î'7âôÎ ?Ì þh½A`Ëÿ€"k†ä½èëàèŒwÑŸo¹ €iK ŽW†“qø3æžÒŒSFO%µ ™9„¦pÑæ- Û½™A õ|ùë8qÎXRö¦ÐÕ@ÊÞõdnØhàcƒøCÎø°vÝYZJJJ MMMœ:uŠÝcưöÊ+ßÛ·/àðÐÐÐ@SSòòxõÌ™À—ÕãÁÔb¡ë’¹sINNfèP-_E ƒî³:wùeœÛíÆèõ¶²³¨$ ­³Eµ•° ”r६,’““ijjbÌîÝü`Ät§O3jÐ jæï™™láü¬,2¶ogذa\¶û2RN¥ðûó]ì>~œéÓ§óæ›orÇÌ™lÿðC.»ð2Þù䲿Íã_Ÿ}Æ„ ¨««###ƒi_hV†±cÇòÏšŒF#ïmÙB~~>/ÿáen¸áþµþ_äåçñÚk¯qÕ¹ç²éøq²²²Ø»w/×Í{kײ`ÁÖ®]KámEìøÝp&5OââC÷`FöÝ•.— —ËŲ Ë´EÅ^Øç†ë eFܩԜÕþ+pŒQ+qòª>è$ö|œ¾£°y+d‚ñ¶Ù”?ªeH±|¿¬†4´ˆ¹l0MhÂ3z*åq"˜uPô\x`$0¬÷ !ïf-K…Õ î×}8?Ðú Ok¢ìùÁ#[hä°ÂZx†KÉûÄo4£Ô°Ñ£©­¯ç·|Ê£Ï\ÀWì§ö³ìø$è§>+s'£þm6drêÔA.ü€÷lÃI4ˆAƒ´íFLÜN噉ÔÕ`úôO™Xÿ{ÿo2ó†¾Àú—qjú››t5»vMå ßÇèÚLò¦ÀqtI>Ö}ó2ŽÉdïÞ½ òN' ü)hJ'Nä—™ù¤§oeðà£Ì®­¥hÃNôþUaJfgƒªØ7l`vmmà½=“õá ö¡ c*¹IHí€-8”"““tW.…&R1·&'371‘m:³É÷z xæÍ›Çõ»w3ª¾ž””NŸ>Í AƒøÕ¨Q9•žžÎ¢Ï?çôéÓ <˜¤¤$ÞKKã£#hjjbrB×TW3dÈ2d«fÊ5×ð§?ý©£i•tWt¡ä\øÌ{ý£m6Â¿Ž¬œBÕ÷³M°Í ß6/‚É^ÍQ.”¯ ÛLŸ›ÙÆ6KLáés]nؼ6<Í——&õóTêëëi»‡sÞ¬áÀ¤¦¦’ššŠï¼‘{þÆ/7²¯i3|œ[‡ôØ3z#¼S¨^Ë´_ܘØfKj6uSê·o;70©R›7Ç“’iHJuZÇ !«!‹·È´ƒ˜´­™ÚùµŠý3Áƒ‡kI"=$˜¢žA<˶À6;¨ÄÜ"ßsµÔ‘ˆ^¼¤é°0ý¢Àq(îÅl0³uëVv%íâë“/æ¼úc’À±AÇØ8üÓê§°5ý}®ß3&ì8îLHhÎ$ýT:ãg§9a™î#ŒðÏ€.Ô1nß8Ž?·>àßÒ‡‡›/-‰Ï'§Æm÷˜M̯ECC þ5¡mu$4g’r"…†¡ $7î&{os¿Nã¦w7nŸÍË O‘••ECV#*?"éx’6þãg0èÄúÊ޾y”ôôtšg×2vÍÞ°þÔ'‘МɠúAœJ?EÒñ] ::Š}o­ÁðoÚ3àž¬=¤oÕÎGCV?o˜æ0ºwï^¦M›Æ_øñ€\3 [+ý¥JüõÉ<–`+“ÝîØ®Må;îØÇŒO`·ÛÙxz éér:GÇк*Ž»Žª=óHûC…s )ýõOùËÏóý<ë:^Oˆ‡µ°xXÇŒ‡µˆ€žìŸKÝ!f"«ªªZ°ììlrrrØ´iÓY…ÇîÝ»9S²ç·@⌸qbÂøÃ9¼›>Œ·vcÚË_ðѾýTÅëÇç0w››‘ž²ÈÔտƉÿù#i;Ð>ŠwÖhÏ"G1ð›ß$1hÐ FEcc#ßüæ7ùôÓOyüñç·¿ý-ùK%………·Û^¯Çn·c0AµØ¨¢ óóóý)I=aAõzæÌa¨EXQQÁ`à³Ï>cÏž)\pÁp®½öbŒFc jp‡ûM…ßòVÑŽNKé4–v…Žê¯tDw¢ô\.¹¹¹dggªÚ£eÓ¶Úß“¶÷d]Vy‹¶µ_å¥ʺuëÂn,••áå¥zé~ÖçôD:tG†Ï‹åü©xæüÃ.dWª’µ ¶ñã¿ÊÃoÞÆ‰)è›= Óä¥ßÎØ±™ŒõùùïšSòÌ™39:q"7Þx#/”–rÎ9ç°{÷næÌ™ÃÿŽEZZC‡e÷îÝFÑh³q§?åðsååXæÍÃaå æ°ú«ï`’…ΉDË91èê¹>1ö'ªOôw³»EOu‚áú”¢Wª!ý>Ì/~šÓ‰ðé›<[=mÛtÌøòmÞxc»wÏ`Ô¨OHLüˆ3g>äàÁu€‡ àÞyó¨Mu²Û``ìÞ霞ÌWßIuu5V«•¼¼<Æùïë•Ï?ÏSEEØÎ?Ÿy·ÍÃh4²X×]dÍ›‡ÏëÅh4¢ÌÊ'ì¾O?`êµbË—´Õ¡‹C‰ÛºñøåÈO?ÍU¿øEÛßwT„6Fo$555y1(ò¯§:Y&œWåÃE³ñ¦Ã»UÌ­|Ÿ¿×Ofwm2ßcËÖákÐ}8í>ĔР>=2Ó§O³ëÈ—|4i.Œ†ºº/ÉÌLàÁWþÉE_Ì”£ƒ©Úñ%“óOâûè#LCCéééX~^Off&û÷ïç'/e²+{µ™™444°yóæ@ÔˆÐQJµŸµ\OLLäiïG¼VWÇ”)Sذa·œs3vïfÈ!œ:uŠAƒñâŽshhh %%…ÚÚZÎOLÄ»oÍ“&qüÀÆfeQZZÊôéÓ©««cܰaì9’cÇŽ‘:r$555$76RþüóX­Vìv;s¯¹»ÇCnn.;vì`òäÉ9xÆÆF.½ôRÖ¬YÃ/ív¬V+O>ù$·ß~;öŸý ¯ÕÊÌ™3©­­eÄ5×`ܦ¥kž:u*ï¼ówß}7N«•Gy„»îº‹éÏ?OÞÍ7œ*Íf3æç$·?J=WQVV†§P«¯ê]o÷heŽø<ï6™p8X­V¾óï0ïñǹÿþûÜ5¯òxbÂwø‡ñ&n·›¹&v»’’>+*bÉ’%}9ΰèƒþ+ð\7fÌn·Xp8\c±Píp`2™˜êÿ>ôùÏë¿gÌñ¦ö¯×ë1™L¤_˜Î„ 8pà·Ü}7N§3àðªÛ>KIá2«•õ))¤÷*jN¿Ä–··p1±gxŒˆ,ÈOÀe`pgñöuÿKåóÃ1$ÀùÊ). 5Ò»±9HþßàÎÿ;ÌæO±¾4Ëâl~öùóTÔ\ÍÉ3'©{õ¶×LÀˆj`ýg•<;f G^ÊÖÕæÂ¸[+™`ú _Àß–!'g§OŸÆéÜÙíÁèñâÁ€þ¨—9yA#Æœ9­wØK‚4§S³“â|ý)…ó6ÐCöîÍâ¡3gøÁÑ£œ:uЦ¦&t'u˜ÿ:œ)S¦°}ûvž|r÷ø˜C: 4g-lII!%%§ÓÇ%#GråÉ?Ð8jÎÕí 9Îæ%ý7\ÒÃ’®>Oå·ÈšZÅÊxÈætÒ(’N¤iÐHÒ“3ùÐߟÙ|ɶíÓhNH&ñŒ<ûâ)$›Ë§ëÏ!oÚ1¾6äùgí(€æ¤ ΜàÏ?ÿoþq: ‰ |ç«û9õ܃xB ‹iÉçò³ï åàZnô’ï­Ç±ü2÷ðà7¯¢6m"½=‚1ÙÇùÆÈßñøKƒûHœOXq,…ÉÃOñïÿ6Ïo Ùz:ËñæcÓ9‘q‚_=ìÆqû;açýë_›Cóà‹ùà3'·çÆÆ?òçYáÛ|ó[8Ÿ3pâÄ ¦N4ràÕ'ñ|ænÖMàÒKfðîs³hlläΟ¿ÍS+7 e®Ó |ƯÍ!uøå¼öa"c²smÂø‹+ ÞØä߯Ç×gäáü‡¦SM˜n‚ª?=2nïkÇ6œwÿq9|ï׳êÉã$&&r¦¹™„æ“ÌÙ1˜æÁSøà3c²sC‚“¿¸<ÀH^M‹øûÊŠù¬Y5‹¦SM\¶àOÿå§a燡[Q¸cZ¬ Àû«±ÿ|?öúk1¥ŽÃvžŽÝ×ïæ™gšÛ¸—µ?Ncûö‰ŒõÆÝËOlbÆŒ|ë[ßâÓmÛ¸`ËÔ~1œ×ª«¹úÞŸòÌšg°lØ*lL6™x0P¹wˆ‡gÁxXǨk-‰™ˆG—ËÅâŋٲeKØç‹/8«'Æw¾óþ9‡-'¾ÉçL ù&`N»rILLdðàΜùî4dÒ¤Iìܹ“I“&Q[[ËŒ3Ø¿?YYYÔ×kÅ3”gÙĉ©®®fÚ´ilݺ5ìïÞ½{IKK#ٯȅz–Õ××G<”}×®]lÙòfÎ\ÃØ±ŸõËyÛ¸ñ:fÍz¹ç;ê$û÷ï'55•´´4^}õ?ûµïõõ£HO?Ø'ûܵk&Lèð7û÷ïçСC$''óöÛo÷˸ô„žÈ€‹/¾˜ÌWð!©GE8Ð\—´'cƼȾ}ã1â#>̨Q£Ðét$''ÓÐÐ@VVÕÕÕ|õ«_eëÖ­¾iÓ¦Q]]Íĉs 999𺯠‰³Í‰x¥+纪ªŠÓ§Osíµ×òÐCõwÓ»LOu‚ÊÿÛIÆÁ_àä¿õ¢t‚ÄÄj ú C†h‘£FâàÁƒÌœ9“mÛ¶‘››H×søðaÒÒÒ8zô( E“466’žžÞos¾=âœ8zô(ÇŽcôèÑýÝ”>¥³çúèÑ£ìÚµ‹ÆÆFž~úirrrú»é]¢§:Áõ×_Ói¢±ñ‹9ÌmhŒ¤¤¤pæÌ« ¬-x5551xð`Ž=ʈ#8|øp@çWÏ JP²@éuuuy¢ô‡©S§²mÛ6F0×û÷ïçüóÏgÛ¶m̘1ƒC‡Ž—••ÅÑ£G²_½Vë-õ”Ž~3kÖ,6n܈ÑhdÏž=Œ9’C‡‘žž¦Û„>èmÆŽö›‘#GR__Ï!C8tèƒ bøðá­ž{êëëûUW:±ªGuEþíÚµ‹£G2jÔ(Ö¬YÓßMï2=‘UUU|÷»ßå“O>ùT÷ =¸Ñž,¤¤¤ÐÐð:ŸïuRR.ãÔ©S$'kÏUmÉ5§BeCccc«ùWWWǘ1cØ·o“&MbÏž=g• §NâøñãmBå‰ÇãaÊ”)È7 𺺺£ÑøûꫯžiBeCccc Ý‘'‡fâĉ­~óá‡rÞyç¶S:TËãÌš5+ GZÊ ÆÆF ¸ž’žž¶m[2û}g~£¶;yò$µµµL˜0¡UNž<&¿BÇ<èŠþ7Ÿî½÷^ž)ÙÁ®Úž>çƒDþ'§NKsólHknæxRMM?!%e% Œû;öì¹›””IJJ"!áï$$$Ï™3b0¸Ù¼ùrÿ5·Í?ïW0fÌrêêê9òcêëGqêÔ¹~™ÓÀ¨Q£Ø¹ó¿˜4éÙ¹s'—_¾™·ßžAVVuuu¤¦¦ræÌ«$&^CSÓfÍÚÏÛoÏ[ÏTû8xð £F}‚׫ïÔq&MšÄÁƒúPO£×ë©©¹¯×éþìß¿ŸŒŒihÈê—qëÉqÎ9ç8ÐáqŽ=JJJ çžz„ê>êïiݧràòË/gð;v¶3‘tà3&(Œ(güøÏùòË·¸ð ùòË/™>}:õõõŒ1" ÿC#fûšxxîUý;”X_‹Øµkuuu=Ö b&â±'üíocçÎlܸ‘n5<†FùÅFÚ°®RT6ÛùýÜ sÏw³}¢‰>úˆ7ß|“+¯ MwšÏV\!^ùÛßþ†×ëm‘¦X„æÆþÏþn¦ ½L¸E9!@xA_kçw(BÌ‘““ÃÇÜâSák&ÂeÁÝýÝlA"ÌC=DÛ몡k†_oçסÏm­+^òz^;û¸£­ì(Jê{ØG_ç–8ëO¼gI'¶‰?Þ~ûmžzê)tºCÜpC[)§ãÓv ½Å€0<Lš4‰I“&õw3úœ)ÃÔ+ô$Í«¿\R§H„‰^¯ï0M± ‚ ‚ ‚ ‡[o½µ¿› qCb7 «TUUµú,ÖRCõ%ÙðØQ G!v9 ˆ,Aä€ " A‘‚ ˆ„h!f ªç¦M›Â>w¹\1]lT„Î#r@Y ‚ÈA4D‚" A9 ÑFÌ (--Åçó°jÕ*t: ,èï¦ ‚ÐGˆD‚ r@ ‘‚ €ÈADB4‘ÐÜÜÜÜßè,>ŸE‹áóùÐétÔÔÔ°lÙ2 ú»i‚ ô"A‘‚ ˆACd  ²@‘‚MÄ”áQár¹˜9s&:®¿›#B? r@Y ‚ÈA4D‚" A9 Ñ@LAAAAAAAˆ.bªÆ£ ‚ ‚ ‚ ‚ ‚ ‚ щAAAAAAAè1bxAAAAAA¡ÇˆáQAAAAAA„׆ÇââbæÎËôéÓYºt)555ýݤ±nÝ:/^ÜêUUU—û c³páB\.W›ßE¢Ñ:íõ»3ç?^Î}¤‰·>GJÄʸôDÄòœh«ßí>iâ©ÏñZhODªÑ8¢Ä>Ÿ¥K—2}út¦OŸÎÂ… [Í[ˆ^]wݺu˜L&¦OŸŽÉdbݺuQßnŸÏÇòåËÃöÙ[²2mooÞ·ìG[ã©ñÙÐûDJôÇùìHDc»;#"Õ®Hµ»'² šdšpv:# ¢õ|ö…NévÇšNmË‚HéÙFä@ÿÓ—r¿¯ú3wîÜV×u,ô¡¯t ¸¡9Nyøá‡›çÌ™Óüì³Ï6¯_¿¾ùæ›on¾ùæ›û»Y=îÓÕW_ÝüðÇýÿâ‹/ºÔïX‡ÃÑÛù—siâ±Ï‘±2.=‘±<'Úë÷@ºDšxëó@»Î6'"ÑÇhÑ â5Îëׯo^¿~}óÝwßÝÖ®]󫯾:¢ã©¶ŸmÞ/Z´¨yΜ9~<üðÃÍÓ¦Mk^»vmDÇWdCß YÐç³#9­íîHDª]‘jwOdA4É4¡c:’Ñz>ûB'èvÇ’NÐÜܾ,ˆ„NЙmDD}%÷û²?-¯ëXèC_é@ñDÜÕbŒâ‹/¾h%„cûù¾ûîëq¿£ylž}öÙæiÓ¦þ·¥hG¢Ñ6éwGç?ÖÏ}o}Ž„,ˆöq‰„,ˆÅ9ÑQ¿Â} ·ˆ·>”k¡£9©>FÓ8ˆN¿lÚ´©yÚ´iÍ›6m |VWW×+×loœß›o¾9lŸÍÍÍÍwß}wó³Ï>µí^¿~}«ºººÀ¤ÚÝÓ¶w4ïÛºNÔ9¹ûî»#:¾"zŸHÉ‚þ8ŸÉhlwgä@¤ÚÕÓvGBDƒL:GgdA´žÏ¾Ð "ÝîXÑ š›Ï. "¥tf‘ýO_Êý¾Àáp4ß|óÍ­®ëXèC_é@ñD\¦Z­ªª¢¦¦†ÜÜÜÀgÙÙÙäää°iÓ¦þn^·©©©A§Óõ¨ßÑ>6¹¹¹¬^½šÕ«W÷Z£q :ê7œýüÇùï âµÏ=•±0.=•±:':ê÷@¸ôñØçr-œmNDªÑ6¢Ä/:Ž%K–““Óî6ѪëÖÔÔPUU¶O€•+WRPPµíV)œ²³³ÃÎÃÌ™3}Š9Ò™ûnnn«kgæÌ™ø|¾ˆ¯È†¾!² ?ÎgGr ZÛÝ‘èì1ûB†õTD‹L:GG² ZÏg_è½ÑîXÑ àì² :Ag¶9ô•Üï ªªªp8<ðÀ­>ö>ô•o êïôuuu­.†ŒŒŒ6óøÇ ›6m¢®®ŽéÓ§Ú rÙ²e ¼3ýŽö±ÉÎÎSZ‰>ªÏ£i :ê7œýüÇùï âµÏ=•Ñ8ZÒSYЙ>FãõÑQ¿Â} 7ˆÇ>”káls"R}Œ¶q ~ÉÎÎfÙ²e€ö`ZWWGii)999s­º®ZœÏÎÎfùòåÔÔÔMAA999QÛî™3gÚ:¯T"¥/ôtNu4ïsrrZ->ú|>Ö®]QýOdCß YÐç³#9­íîHtö˜}!Ãz* âU7ŠW:’j!:ÚÎg_è½ÑîXÑ ÔØ¶' "¡tf›XX7ô•Üïm|>÷Ýw‹¥•5úÐW:P¼—ñŠÏç#;;§Ó‰Ó餠 €åË—·Yp\ˆ?äü ¹.rî…\ 9ÿ±Oqq1‹/fݺu,X°à¬ÌÑÄÂ… ÑétäääPSSâE‹¢úA977NX ¨©© ¼ŽeÖ­[ÇÂ… ÉÎÎÆb±ôws„‹²@ä@ô ² ~YÐûÄ«,90°ˆÕóíp8ÈÈÈ`É’%ýÝ”kr¯¿‰ËˆÇxeË–-aï—-[†Ë墴´´•µ\ˆ?Îvþ•W“00Y0p‘s/(äZ؈Nû(Ïe—ËÅâÅ‹Ñét1qî,KØ‚Éd¢´´”ùóç÷wÓÚD§Óñøã³téRL&óçÏ?kŠËhF-’º\.–,Y‚Åb‰‰Åi¡}bQ´'V¬XÑßMk“x“ ² iKt”£¿ 90°ˆåó­žSŸ{î¹þnJ‰5¨¿‰ëˆÇ¶,αzCiÜÜÜ@ï®ô;ÖÇ&}Œõ1€Öç œûî0úÜYã‰>Æú8 Ôû@wˆ÷>Ôk!R}Œõq úQµABÉÍÍ%77·U´j´êº- "óçÏ‹ˆÆvçääàt:Ù²e [¶laåÊ•dddôŠ¾Ð›sªªª*àeít:Y¶lY› N¢E?‘”ýq>;’ÑØîÎÈHµ«·çOgdA,È4¡ó² ZÏg_è‘n·èÑ'Ó„ŽéK¹ß¸\.222X¾|9‹/fñâÅ@0Ò;ú è+(^ˆKãòôoY˜ÓårE½ÇP{¬[·.l2*jjj¦3ýŽõ±‰Dcq ::ÿáÜw‡xìs$dA<ŒK$úkã ÷îo}–kˆö1ÖÆAt‚Øeݺu,Z´è¬ÛD«®«ê"µÜg˺HÑÖnŸÏGqqqØ‚€ÏçÃår1sæÌ˜’#K—.eÁ‚¬\¹²Í}DÝ(V‰„,èóÙ‘ˆÖvw$:{ÌhyÆ:›,ˆ%™&t, ¢õ|ö…NÐí :ešÐ1}!÷{“‚‚V¬XÁ’%Kÿ,XÀ’%Kb¢}¥Åqixí¢.-- x~¯Zµ NÇ‚ ú»iÝ"''—ËEqqqà3—ËÈÿÞ•~ÇúØD¢±69ÿáÜw‡xës¤dA<ŒK$úKã ÷žO}–k!H¤úKã :Aì2þ||>«V­ |ær¹p¹\a)’£Q×UFíâââÀ>Õu§RªEk»×­[6æÅÅÅètºˆ¶»7ÚŠË墦¦&ú?Ôkz éF±J¤dA_ŸÏÎÈhmwGr RíêíùÓY 2MÐèŒ,ˆÆóÙW:Ao´[t‚è’iBÇô¥Üï-”Ñ-ô?hϵ‘–u½E_ê@ñDBssss7¢7ðù|,Z´ŸÏ‡N§£¦¦†eË–E}½„³QZZXdÊÈÈ ¦¦†%K–°lÙ².õ;VÆfúôé¬^½ºU­ªHô1šÇ ½~wtþãéÜG’xìs$dA,KweA¬Ï‰¶ú=Ðî‘$Þú<¯…¶æD¤ú­ã :AüQZZÊòåËÑét½:w{ãüÖÔÔ°téRªªªÈÉÉ¡ªª*â×]o´Ûår±téR222¨««###ƒ•+WRE›ikÞ‡-”†’››¨ ïºQ< YÐç³#9­íîHDª]‘lwweA´É4áìt$ ¢õ|ö…NÐíŽ5ZË‚HéÙFä@ÿÓ—r¿/iy]ÇBúJŠ'âÖð¨PyÑgΜ3EWφÏç „äfgg·ŠÛ™~ÇúØD¢±69ÿáÜw‡xës¤dA<ŒK$úKã ÷žO}–k!ò}Œ¥q v©©© ¤åéí¹ÛçWí³7¯»H·;t¾´4äG²Ý½Ñöî0Ðt£X%R² ?ÎgGr ÛÝ9©vEÃü‰'™ïtFDëùì Òí ëÛDC?„މ•k2ÖûÐW:P<÷†GAAAAAAAzŸ¸­ñ(‚ ‚ ‚ ‚ ‚ ‚ Bß!†GAAAAAAAzŒAAAAAAAè1bxAAAAAA¡ÇˆáQи\.|>_7C„~Dä€ËÈõ+Â@Cäž "!ˆÌA„î!ò³wã1ªªªX¼x1Ó§Ogúôé,^¼8ê'ïâŋٴiS7Cb–ââbæÎ˜÷Ë—/úyß‘B,Ó_×oii)‹/>ë÷&“‰éÓ§3wî\Š‹‹ûs˜Aˆ"¥3ˆÜ„Ø&ëý©¿ŸMˆúƒxyžÅ5Eˆ5A¨Ä‹üŒVÄð(D„šš-Z„N§cõêÕ¬\¹’M›6±téÒþnš ½Dqq1«V­¢  €Õ«W³bÅ Ö®]+ó^âŸÏGiii»ß»\.–/_Nnn.«W¯¦  €U«VÉâ› `b]g¹'‘!Ö× Î& DB÷‰UÙëú Bo2¨¿ Ä«V­"##ƒxNø|éÒ¥TUU‘““ÓßM!”––RPPÀ²eËŸù|>Š‹‹ñù|a²@„اªªŠââb\.¹¹¹mnWZZJNN+V¬l§êBå… ‡XÕDî Bd‰ÕuƒÎÈ‘‚Ð}bU6Ī~#‚ÐHÄcœP\\LiiiXˆÿÒ¥K7<õYo¥*(--eþüùa7Õùóç³eË–0A¥N8›Ç°ê˪U«iJ.\HUUU¯cgÚ'ÑJ_϶iõ¾®®èÚœï/ùÕ‘B,ӛׯN§#''‡%K–ÝîvëÖ­kµ 7þ||>_`Á®3mÙП:‰ (º;:;ÇúâúîŒÎÐ]bIî BwéÌ|½»³ë]¥·õ÷ÎÈ‘B´Ðr> 4Ù/ú ôý-Ä.?ˆá1NPx555¬\¹’eË–±nÝ:®¾úê°Ï\.WÄS}¨‰Ÿ››KMM «V­bÕªUÔÔÔ´Ú¶®®—ËÕæw¡û+--Åår±bÅ V®\ À¢E‹z} -ZDvv6½z,Aè úzî,Y²$p<ÐÒ£(O_õ@ÞÙ9ß_ò«­¶ˆb•Þ¾~³³³Y¶lË–-kwÑ­½Hµ}¨,èH>Dƒlè/DBéî\èÌë«ë»3:CwÇ&–äž t—ÎÌ×h×»»²nÐÕýö¶þÞ‘,9 D m͇&âA¿„þ¤¿ŸÃÅ.?HªÕ8";;;0sssY»v->Ÿ/쳎”î ¼xÖ­[Gii)ÙÙÙÔÕÕQ\\ÌŠ+Â&knn.[¶lépŸ>ŸÇ¼UŠ—ËÕnŠ£ž „Ë‚ ©Q!é˹³lÙ²€7";;›çž{.ð¾³s¾¿äW("„X&گ߶Þ:#¢A6ôµN"mѹЙ9ÖW×wgt†®‹rOzBGó5Úõt‘‚¤½ù0eC,ë7‚ ô÷s¸Øâ1<Æ-'^FFþ½Ëå »Y¶ÅÙ”•µk×òÜsÏÒ ,_¾¹¹¹aÂålyÑ{Ú*>ŸOj/1O_ÎUçdÉ’%äæææ’z@èj»Cékù%r@ˆeºrýöt®ô5=• ‘èsWäª ô‘˜ íí·/ô†Hê ßrOÚ#R÷£þÖ»#µn r@‚Dây6^dƒêK,ê7‚-ô·<»@| †G!ÀÌ™3Y½zu·o±XÂr¯/[¶ŒÒÒÒnSïÊCTOÛ]\\Ì’%KXµj‡C„ŒÓôÕÜ©ªªbÕªU,[¶Œ%K–šb““ÃâÅ‹ÉÉÉéÓÔ"„LW®ßžÎ•ž CIWéiŸÅÐ(Ä3}¡7ô†Î rOˆDËý(ZÖ DBhxžÙ±«ßB¼Ð—ÏಽˆáQ Ó麮¬”è–ŸûêÁ¨»íV„* «V­ ¤©„x§'sG¥Ci9ïÕþú:Èa Ó•ë·§s¥#fΜ ´–ªîIK™ÑôvŸa ÐݹÔ:ƒÈ=Aè?¢eÝ@ä€ ‰†çÙh‘ }Õîh[„h¢/ŸÁe=0zã »¡É999ètºVy–ÕM¶·½ûzR­”‹Åºuë(..–|ì€ )‡|>ßYßÇJ_D±LW®ßÞN5¦ÓéÈÎΦªª*ìsõ^-Ìõ%’^M"COçR$u‘{‚ÐD˺ÈA ϳÑ"úªÝŠhY„h¢/ŸÁe=0zã '¡É”––¼|>K—.E§Ó…¥¨ªª¢¸¸˜ùóçG,å@¤Ò¦èt:V¬XÁâÅ‹)..–Ðj!îéÉÜQu999dggãóù¸ï¾ûÂæ}oÌùH÷%‘B,Ó™ë·/RP\\LAA999ÔÔÔàp8(((ó\Ž5ù ±F¤çXwçRgu€ÒÒRÖ­[DzeË:!krOz“X¸¯vvÝ +²@ä€ ik> TÙÐÛíîŠ~#¾|—õÀèE B€ž„&/[¶Œššš0NÇã?¦d×ÕÕár¹"šj$’áÛ¹¹¹ÌŸ?ŸÒÒR º\ÀZb‰žÎ•+W²téRL&SØ>xàÀÜé9ß} Eä€ËttýöEÊ“%K–PSSÃÂ… ÉÉÉ¡ªªŠœœœVŠ{,ÊAˆ%"=Çz2—:£3€Ýàr¹éË:C,É=AèMbá¾ÚÙuƒ®Ê‘‚¤å|Ȳ¡·ÛÝYýF±”j5YŒ, ÍÍÍÍýÝ!~¨ªª (43gÎlÓ³Ïårár¹D„8Áår¬Ûš÷2ça`ª´÷ òAz—h›cé ÅÅÅ1[[¥3rOz“h›óíÑ™uƒX•"„hDdCïÒýFa !BDÉÉÉ9«•ÏçÃår‰Ç€ ÄgSúeÎ ÂÀEtAè_¢qŽu´PXSSCUUUÔ/Œ¶GGrOz“hœóíÑÑ\‰eY r@ˆ6D6ô>ÑfAˆû»ÂÀ¢®®ŽììlÉu.™ó‚ ´‡ÈAè]bqŽÕÔÔ°bÅŠþn† Ä$±8çÛCd D‘ ‚ B ©VAAAAAAAè1ñ(‚ ‚ ‚ ‚ ‚ ‚ Bã ‚ ‚ ‚ ‚ ‚ ‚ =F ‚ ‚ ‚ ‚ ‚ ‚ ‚ ô1< ‚ ‚ ‚ ‚ ‚ ‚ ‚ÐcÄð(‚ ‚ ‚ ‚ ‚ ‚ Bã ‚ ‚ ‚ ‚ ‚ ‚ =F ‚ ‚ ‚ ‚ ‚ ‚ ‚ ô1< ‚ ‚ ‚ ‚ ‚ ‚ ‚Ðcþ?+o¡ÿ½ÿqX%tEXtdate:create2020-10-09T19:33:36+00:001W/%tEXtdate:modify2020-10-09T19:33:36+00:00@Íï“!tEXtpdf:HiResBoundingBox1728x900+0+0×ì&ŒtEXtpdf:VersionPDF-1.7½8;í(tEXtxmp:CreateDate2020-10-09T14:32:44-05:00,š%6tEXtxmp:CreatorToolGL2PS 1.3.9, (C) 1999-2015 C. GeuzaineÛ©AJ(tEXtxmp:ModifyDate2020-10-09T14:32:44-05:00˜d¡IEND®B`‚blis-0.9.0/docs/graphs/sup/dgemm_ccc_zen_nt1.pdf000066400000000000000000006060371422157504600215500ustar00rootroot00000000000000%PDF-1.7 %Çì¢ 5 0 obj <> stream xœÜ½I.9²ž¹Ï_ˬE…|$Ý· ´ tKY;AèEÝÛH*áJZèï7öÆ8'G´îç³àät’ÆÇÍŒüoÛçþ±Åÿà¿ýûÿêß÷¿ýöøŸÿþ·þ¼ŸûöñçãÝ>öçêÛÇ{œÛÇÿçþ¿_úÓ¾½Ççù~´gÛ>Ÿöñ÷Žû9>ß[’ÿ"ɳoÛøùK™„ ”ãþøŸ?Œ¶_ï»ßþãßÿ›ö«ÝŸÛYÊ´d¿?{4ä'ÉfÁNòlÏ=zf¦xÎþÙz-G’Rd,‡?]ÎqìÛç¹×g”ÄåP†rôÓåÄ3>ïÑ>¾ýÇxiÿmtÕ|¡øÏ_ÿþñüe¼Úçc?>þ2z:ÿø±Ÿís‹¾hûçèÛ¿üý‡ÿðãñ§?ýó<Ïöã¶üs?ÇÛhýÇë—\?¶ŸKpôø÷õÿòoø?ÿòÿûÎß÷m$)£ä§oFN ‹ö|n×’ŠEõ­ïŸ÷î¢(¨E9‹ª©TÔyŸ{/EA°¥D*ª¤RQm?>Ÿ£ÁR”©¨’JE=Ïùy=¥(–¢”HE•T¿ux¼íó8ûš}L‡ÑÏsx¬¯qû¯wk÷È÷Oã÷òÇ?÷ükË?î?7PÈhÝ×t÷÷Ò¡¸¯ãtZÿácoñÿqüß?ýp|üÛß´&ý´®1߬@?}oÈ®«Ò÷ì—R~á œŸóDÿÿ9^Äxmó%ôýù¼¯3_¿ùÓ±}^ÇÑü׺>ßó9ü¿þtÜŸííýÇÿ[üÆœ¼>Ÿýi?þô§?¿ÛçÝÛ¡.ʪÏr±½cºÆc¼Ÿïá³)ÿä×ð7ÿóŸÿt·ÿþ§?oóçý.ÿþî¿FºùÿŠð¯ýkùUs¶/9ÿÅ¿ÿó¿|oäëßâõü'÷,¦_Ÿg’s¼Ï>%ÏKC¿ûöÙRð~ÏŒsg¦1ûX î÷ù÷'Ö•7ü~ìûg‹õècì·‚.?žÑªiÚ畿çgiú6–Ý)9·¡Î"Í‹%oHÆä9B2ºx6ïÚvü«÷¡Z3É1ŸQÌûÙç{9Ïñ§g•<ñžG¦ùÆBr ¥iöã)$÷˜°WHîÐý!¯¾½!i1 ¦ä‰¦Éþyf®±Ä¶cæNÁ3G]-&æoÖ”oá|û\ë#É>;çÚîÏ+ºâ€Ú¯P Qð³÷¬é:æ^bHF'=)é±ñ’3º?$çfJú¬ëºBõg®–uÝcÇq„äF“¯{¼ê'%ïìì£j9ýˆW2$=´Ò”ŒW2ÓŒšiž>]?.̪뽢w‡ä‰:‡ä/ûx³œûIÉ;§«k¿£§jU÷(°Ý‹dLÿ}És¾sºFM-%cDoû"¹¯9_K1cÿô®iÚ;çk‘ô6çkõeöò=†ùÑs<ù ï>'¬å=Æëþ¤à˜Å´±$´™äÌýÊÞÆ:µ½‹d¼¤ûZ%Ïœ°*1»¯»Ž¸v1a=ÚÛ½Ï[’Œ`¶æÂŠØÆBuÜu ·~΃=ל±±3¶´æyrƺà±Rm­–Ü·sÎØ"}3öÀË •xµ®x‘sʪ®ëÚY'_¿6LYKž/S¶ß7¦,'ÛX1e9Ñû\xgs¹íc±Ú–þêc¿¾Ìáþ_¦lìæ”U>c€§¬ZóŒÅjNYµðQë‹Õ~,%]t/}ñ¤žªåŒüZÓô+§¬kroZ%oNYKÞžSV’wK ë’ß}jØ*H ¯úœSâ=¦†-IÎÔ°‘äÝþ^©a«$Ul)æN[Ò´T±EÒSÅ–\c±Ê)Kð>©c½0¾oêX-°Ç¶¥Ž­’7þå…úØöT²Er¤’-’3•lHúž’©dµ< ýÞ0gs9¶{*YÍêck»¦ì“IÚƒ)Ë<½aƪØ:–£ôØÞ3Ö’3ósP+u,ÆÛØlœ˜±˜"Gl¦žº¦ •¬$'•¬$WìŠÉM%«Úo*YI”,‡c¬˜±ì‹1û>ï¥}•ìœÃc{%ËUç¯ 3–iì5Í%kÉ%Ë‘|'”¬Ó\P²N3ÔÑÝÉ %ëÚ”,ç𼚱ô® É%ëÚßc±C%Ë9rœ[*Y v(Y|©dUÊy¼š±s^ý$”¬3]P²œiÇySÉnùó]§ëq6hX$èP¯ÜúçÐD½$x \à…r•äKÔ¶¤¹v(WMæk¾LÔë€rå¢p\g*W .(Ws¥rµà†rÕt¿”«[Ó©\ÙMW‡ruU”«K~¡\•æÞ \‹ÊUOuï_”ëqç—©zŸT®œQ÷X¢rªJrQ¹ré¸o(W­RwÛ–ýp~ÆX¦êÝoNÕ·~OÔ:öS|Ø~é“ ƒc½kyÁÎ!1 4Ù ’[(Ìkÿ0 ŽÝM‹É&lïØwS€Û;J¹SW 7“ÄÁàNppp³#õqp‹íjJ€ƒÛØ[¥v%ÆÚÛòà>^vêNò`¬ž¹)%ƧA€x0ZšPA J 4E ŒV$”‡æE_€ÇLøÜ“í„Q>ø/0ŠOÆ%ƒrsD ŒÒ² „c0~>ùÂ#6 F9Ï„Q¸ @xÆÇ…£¼+¹ Dx¼³ÎB„çÉM)‰ðܨ$ÂX*³Í$ÂøR8g¶ˆðŒ0q/‰0šÕ²á9Þp*«3¨è£¡äÁ¨ï^xð¯·'£ãIr`“g›<Çî"ÀA @ƒÑêübA<-µ,4'h0æ}¡ÁsìRr˜ý…4xŽ¡¾ƒýRQcµý£Ðà9ê|g{@ƒç˯9¤Á36 •Iƒg¶ªÐ`è…Y5a03×Â`)0èL`Á’ ,xާÍA¼ÆHÍIFŒ×~æ3ã+{~ ! †–ÊÑG†,xý& zW@¼ÆBœB¼Æ±¯±ï8 ‚9¿ ^ñâ³*`É”$ˆ•C€$¨I0Š=ݲ ‹! º&²`¤I°' ªÁDÁ+æiŒb ÔU‘$ º°à5f8,Xê Fš# ,½•œBôk úÉÉ‚ÑÐüB¼nøüˆýÀ‚®‰,X$€Á’ 0«õ»À iPc‹0Iëƒn0`ЙÀ‚ébA&! º\¢ “] H°H’#O>¤HÐI’‹$8KÂ"IP³W$¨yHŒ]~~9 jöŠ•F$(6 ZBT E‚±³ZQ°H€‚׆uU(h QPLÔ  ²× ƒúMTÍbA ± ÓU‘XP",À –Á`l¶ ƒã/éÝ!t9„A—Ct›Iƒ.™8è\ÄAãqp”“ß=ˆƒêbá :ƒ8xÁeE4¨E@4¨ªEƒ–K4Øa : iP‹¯i«` Ža˨aРsùà-IÕÊ)cäà ²C ƒ| †A¾Ó s‘-!  t«Ê *h#Ç4¨öˆ-! :iP8-tí¤AÁ3iÐÒ ‡­hÐIHƒc†Ü‰¤A Ó Òˆ†4è4¤A§! bl9& ƒÎDtÁ„A=•`ÐiHƒœø¦A§! :Íû®V4ÈUÒ4¨wEtâ ^°xPE<¨ç Ô+»K<è$äA=‚x°H _9©Íƒêvñ J*—xÍbm rÛcÔB@ävÊ4h iPk…h°H _-! ª‹Eƒ’ˆ5pDƒšgÂA½Ná Ó]qPóJ8èrˆƒ9ÄACÔÈ!jü YpPÿküâ:‡ãYp Œ’Š€@ø‡Êk“˜û!# ­0`¬1gµn*"k A3 >¤`À‰Z‹ApÌO:ž‚_æÄ€c@‘©À€aMKíK½ H DËæÈ xˉ xÜd BàqSMÒ"؈²69‘Â"Øi”EÐuÓ"èL´Žq¯Á±7¬É"xc7o‹à‹½;)0Ê´œÈ"({¤,‚Ù®‚ÑæÕ"ËkˆQ×¹p`i!8ðo6!X –‡H&ºG EÔP"úÅ‹ XŠz>“=,È€ªŠè7t" kº `)èÞ#ºkˆ€îO" Ÿ’èg"–ÖK9`Àx/Ûbd“…€ªJ¨‡:PÏ@ mšÛR`PAîâA€¡ŸÅx4|º¢ÞÖ¹*ÔC ÕÅ@ç"ú) €Et9ÀRP $ÿYü+åÿœ$éOÛ Ñ_©9é¯ú+П޿èÏ/Žôç\¤¿"ý 诔|Q­b±þi< ÿ´ ÿJ{Ú»ÎUá_©ý¡begÿÜaÄ?®7¤?ÿÞ©VY௠Þu® þJš‹z•ƒðç¶þü¤?½pŸ`¿’ç¡ZåP#û¹n²_‘ìT¬xn¢ŸìW$'ô*ó\T«*ö‚ZEs‰~~h¢_ÉÓ©U•¦?_f*ѯ¤y©U™†è§æ‘üÜ3$?'øyi!øyi!øy)$øÉM*I‚ŸLð+ Nð;—àu¿’ë˜Àý«½o›f8ÃÞØg$\ôÏÁ†¤7æÐµÞ‘qk?8^Ä7O|¤7ƒãõ-”˜wMѹpÞ½Ñ-Pq€£Nx0lA€]ÉyÑ©Ïâø©xBbÞ>iüæÝ¯ÌÀ¼û•9€=S¸Ó²Ç@@Ç "ðÀqÅŽ‘³B^ žÍeà%z䵋ÆÅÞÄGÅÌ&®òZŒÎÅÖû×4hòZ†RÈkc¤Ï!¯f9€¼za©Zçë$ä•4 y¥É€¼6”|EòŽIÈk·x ×Ò©‰ˆ7÷èÉP@¼Öhz&âµ\N ãEG¼‹Û§;‚ýf.P^„u‹­o†‘/”@žµ¤¼¼K ÃC‰yŽ %æ¹bžÛÌ‹ÊÓÑŽ˜×:݃y-8á ˜Iòc1¯ÔÎk£åK ß.9/(' Ôä¼Èô.A€m¬T;Ü<“óBÒ`ýK…Ô2m½6G~j"é9v–¤WrôÚ@ÌÐ lp zAa«µ¯J¦Fš öQ8¯e'b伈ÚÍ…ŒœW%©‘ZPO²*8¯çÏOOä¼–ö…óÚ{åNVœ×^xLó¢˜\^ˆy®Š˜çL ¼öÒýš”ç$€¼h&°/!/+äE”ñUý>K@^T”¯‰”×^ê Ž5:! çèeÅÿÅ —Æ6Æÿâò+Žâÿ­ø?çbüßèi°!ãÿŠñCèdüŸËaüßv}ÿ³„ñ['Ä1þOiÿç$ŒÿSÔ,ãÿÆJ¾-žŸ}cÄ‚âÿœ‰ñ nuüã.ÿç4Šÿcô­ãÿ «ð?Å|*üÏq ÿS¤ŠÂÿÆ¿„ÿ)ÑÜcôŸ£òý§šJôßQAÏq4ÿc”—ÃÿQæø?Fc9þO¹ÿ§\Šÿc.Çÿõ/¤ç\ŽÿS.Åÿ)âÿêåø?•¬ø?Æ”9þOiÿ§$ŠÿSÁŒÿc8•ãÿ”„ñ Ârüs9þU)þ/cÏüǘ{ÿ¹Xÿ)nKÁ–0øOQZ þCEŒüsFþ)ÔK‘N£È?=#ÿ,‡È?µE‘– òOå*òÏFþ©#ùÇðGþ•X@†×«*ÿñ©ÿ§ºÿ§4 dˆCه⠃¨À<…*0O!€8úÀ!€ŠT %T¹ Ôès ÂûȹéÀ9ÿ§zÿ§á©ø?ÜmÏ—©êø?…à)þOŠÿãtvüÃSÿLJRüŸ^§âÿ8wÿÇ1ð ñðÒüiBÞ‹Þ˜àï³@^ضkŒßh×Ç!pž€RœQb×râ‹„z—#úàÕ©€*¹uŽšR×È­³ã("»uÆž1+§[§ÂtäÖ9²ÜõÎñÒSb·Næ"êÅ|_õb>,½óüõ³DÔsdPÏQCd½sôúVYϱ[„½’ °ç8'ÂÞ9¶S°ñö¢}8аç4ž+WŒßPgI½„=w2a¯äbŒ;G!~ê?…ø© ñS&Fø=àkø¹øé¹à7·ºu:“Bü”I!~ÅcˆŸ^Bü\¦¿ÐkŒŸºFA~ÎÅ ?…¶)ÈÏ-Tß½¿‚üô1°ÇW­G¾ `o‘LT%öª a¯J&ì-‚7cr-IØ«’„½*IÚ[$S'UIÒ^•$‹UIÒÞ"™:©H@{U’´W%I{‹dê¤*IÜ«’‰{U¸·HB'UAò^•$ïUIòÞ"™:©J’÷мW%É{‹dª¥*Ià«’¾*Ià[$“øª$‰¯Jùªd"ß"˜j©J&òUA"_‘ùÉD¾*Iæ«’d¾*Iæ’†8<“²H’ùª$™¯J’ùjÉÉ|U’ÌWs%ó-|Hµä…׌$`¾*™Ì·^ÌYIŽŒ£·àD½%âè‹äÅœ•$™¯J’ùª$™o‘¼˜³’$ôUIBŸ%„¾E2¡¯Júª$©¯J’úÉó¹&Iê«’I}UÔ·HÌYI’úª$©¯J’úɃ9K ¨Ïc‡ÔWÓ$õ-’sV’¤¾*Iê«’¤¾Eò`ÎJ2©¯ ’úªdRß"蘳’$õ•§õ•4<ɵJ:æ¬$ ~µœ¿š&Áo‘Lð«’¿*Ið[$ï:gÉ~µö狞%û-’/zìWû= ö[_ô,Ù¯J®/z–ì·H¾èY²_•ô/z–ì·H¾èY²_‘€ýªdÿ¢gÉ~Ur|ѳ`¿*¸¾èY°_Ü_ô,Ù¯Jú=Kö«’狞%þ ðo‘|ѳĿ*9¾èYâ_qÀ¿šæú¢g‰5WÛÖ9 ü«™ú½ÎYžº’#ñï×bþ¶obþB].6ÀöŽ— °Û©ºNœ¥<Ü.†±·[‡ÂÀás,«Ãg,œ+Ff0%ðp• Žá`Ù0²¦e‹l86Åð\Òù/£3¯å| ǾçÇö‘ǽ€íÑK:{Ã/–Àýá©!ÄÃ=vY{òáØ÷ñSðaÓª»g)|èRȇc#ÈUÀ‡1b2î…|i“užñpì zÀÃxÌü`A<ŒæÜ$ ð0,0xX<œJøÃtXž“¦@%¡%pì\«´:I] %OÝ4ú±i,ÅÀèŠ`,I`ŒK9HhŒ‚Òi,­!°¤!PUÑèL´úí€% ì€% ‘¶Â4ú=ÑXŠIC`¬3kØ_IKàØöÓzK †ÀR î-††@·†@?-6´–r` ,uÁMNó!,% LN’–À’–ÀÒ˜´,îZ†–À€ ¦@WES Ãh ,i` ôsÓXÒÀXÊ)°ä‚)°´¦ÀRL% L¥˜]MNS ‹¡)°$IS ^-î@Z†@·—†ÀR ¥"KKXË3Á¨æÈ¨w.K Ê‘%pÆÐÁȇ%°$IK SÀ¨ÓXj†!0 YcþJK]ì€zlÙ•„f@—B3 3Ñ ¸¿'#õ`t1°F’5à¯+`© V@÷¬€% ¬€¥˜´ºi,¥À èÖÐ è4´ú¡h,i`,åÀèÚi,åÀXÒÀXÒÀè¥-°¤-ÐN[`il¥Í°Æá~p×L[ “Ðèª` ,I` ,¥Àè§¢-°¤-°¤-ÐÏI[ ŸŠ¶@?m%l% l~Ú†¶À’¶@·™¶@·¶À’¶@7¶@ ([ [L[`)¶ÀÒØ‹æÀÒ˜]ÍÎEs`Is Ë¡9°¤9°¤9ÐOAs`‘ÜÔ¯’¤9Pk­~°ºÿh ÔÊú“/5ûm½¡ã Óã½—«@(ÑeC?Ÿ I˜@9ìjúŸ~嚢ÁÓ8ç²-ñµ@”ánýôµ@ç„ßzÝ‘%¥ÈXºœëŒÑW¯;²ÄåP†rôó}MÑa®ÑÿÈkŠº.Ùo%à?ãß¾(åÛ7ΈɶÜóuÅøˆíù’ˆEù"Uo bQN…¢j"¥ˆTT¹HE)‹*‰T”n RQå"¥T,ª$RQºHE•ˆT”R±¨?pMÑ9Ôìß9ÿ·¸¦è·¬M?­kÍ7+ÑOß²Ëêôýñú¥”ß}CP|1ÙûÿÊ ‚ÆŒ­9ÿÅâÈô9vÜÏ…¾%èøõ[‚ÆÓ ¥÷Ø…p(Ç'Àï s†<ÇLƒŒ®)ºj†õì8/ôŒPÖóà“ß‘µmÃv¦›òy„'oÕ÷#¿kíÑ<´·ßñ­)sÅ'Ãyå¼FÎ3¾î<Å|<äGꖉƓnñ%¯÷±—‚ §5oï}wÃ5Ž˜ç<™ø*ïœóØá‘äÆç¨!èéî5¨«e1ížî^á]‘IÆÃÜ‘$Ž Î?[$À¡­g¸ŽL_¯7ŽóŒýN, Α;㨱3Ò¼8,òœçªFšgœœW›ÜƒÕ÷”Wúz½{~\<㘰=Ò„Æ‘’Ó9ëÊ'ˆÃ¦¯×‹S1Ï8|ê>—ºâóNtVœï›åÄ7Äk)§ÏÔ=”å“’8Š-–ÅAZC©EœgÄÕÁ;7xOœ1%qÿS´øÅÑjcó;ÛÕúÏ”„Øì‹#?r É<©i¤É&Îûl¹Ö8ÓἯB>ƒà‰óÛêØÞ=GžS1S—Æ hý¼Û¼äj$9sG:À9wwñ1az+rœµîg~«I´>vëmnîžGÍrÓã»Å•’±©žwÖ8õaHžÏ¥÷Z\Ù3%ˆ9ã«+““¬]3¶e6fzÞ1âc²>Î?#d¢/=ñÇžÞ³à>"ižüLÖ'6ª™+>ïDwa7€Î¸|*&«›®ÙÓ3óÁÏg8(Oç̇*Ÿá%“5+»4¼öžù\×<³øìç âI2$lúœ«1nZ–2úàÈçYÛîúP½Å¥Ÿ5I›ÎÒåeö~×AÓŸù™~vÕô ’7窆pŒÔ³•¶=Û•SUýõèùÎL³Oçò*£À˜ªÏ‰ ë3òÏ©ªöFþí©ôŒm✪b¬Ïçž¶›ñž¶ŒÚ8ŸvåT=6V =§ªÞÓÓ_LU¾ƒ8ÑÿYš<Ö‡coD]ÞҮݳ'®vÆq’m|q/Àœ©*÷=±-º¨3$Ïœª=ŽQŸƒï¯y:fÆóÞø¶Ó—ºÆuuÚ½íɹªÄ®¿L˜÷™ùk{’Ö{tmê©7¾î¼%×µå’=> NÍuÍ› Ê›+8ö„7¢†äÉɪ$ç“ÕI®“uËér…UmNVÑ!y0Y•¦¥fÕd¸¶žšUËêµ=©Y£Å ’Ԭꯡb¦'ßH³ç¤¿Â„÷žeE蟚5–ž‚¯­T¾©Yä<0YYÓ~MŪ.‚ŽÉŠr…Íl_’´“•Ͻ÷­vL¨ftÒ âÖˆw/Á)Wàõœ¬Âì®8ªtÎV.ñ×±uÌV¾¨cOÅêŽ9Ò¯XcÿŠ#gÚ¹d:S¯jBõ ½ê4ñeçɱ?]‡¯ˆ!“•ËìÂs²ªƒãÔ’9Y5úŽ'õª^Óñ@¯êuÇý U·]罪>wèUõp¸ün­Žüó€b½¬w'«K¾ X5ú@É¥ÅçÝ0[•¦A³ª“Ïͪ‡ïÉ9[ǘü\áó»ÌÖ >¿%W˜¿urűöwæ™öÞ+R§õç»Ôðξa0¼â@æç®‡Ë˳´úÒ]q Õœ¬zð«A³r¹jÖ;— ±#ƒfÕ@¹hVuÎ5ô眬®ë혬,9"fϧ¦¹ƒZÏúè÷Õê4t«:ð>ç³ÌÎû¢råÀ½ïT®jà}C¹ju»gމò×Ý¡Y¹HÜŠUóù~ X]ä ͪv´š•ÏÜ6hVM—ˆÂÝ×4ǼŸ£¦9¡Y5íÚ ÍJ=zÍ Û'hnʯv§f•çÿŸkž·xõ_.{^µ§S–q>£—ÎŒ@¾eºÄ ¶/}Ñ7¨VµxÆTÕê/œd¿õz QàÖê·‘`ëŸÂH- Ÿ~ ¤Àö<ÔÉ ÀAT7Ó$¶÷F)pð%bMDÛ~±PàvpI Ü:75¤À­a;OÜÇ"P†»’ AòÐîNŸ&òC¬ pïð^#G Ô·Ú„Àã$,aå‚ÀiÔH6†q$‹%ê`A N3În] P§™ ÃÌñ.¨Ó(ç† ]A NÚƽ?ÓÚ'4öuË!0Þrv!P&„ÀÔY…à’#‚ #ãIÈމG †¦ËÎ!†&»‚¾1m¡Àó¼Hx À0ð€7Aa½É¤Àso@•¶0vÉ'ð7Þ D|Ï9·Ì€}»pO‘,ò ·%ð…ó¿, ™¶%°_´(Êø¤?»-Bñm OþD&0à}qKBŒ¡”æB`l¶‘f>@`  Ä3šy^!PÇ€‰ÛË]Ií¤é…Ø\Ü‘ØNœu& Œ¡–†6R`;ZúøŠ£ØD,@`»q ³ 0Hà\,í‚M‚ Øn T1`/–˜C ¯ç¬ så^—ó6G  ŠØNá&Pg›yú™Ð¥€‹t“ÀOTÏÝ$@×L,`U* °¸ÿEè7Il®žVI`É ¬;t.B`H„Àvàê9A › ô{!ε/Q Øv~„ –ÖK.@`äÊ­7!°´Øv\^) ?ü´œ“Ûv S]µ$j`<}~  °m´ Ý:@ ¼smÇío„ÀR. ÐíŸÕ¼ –ÀÀR10Ð5“CBêKeårÈÂC„8Ðu‘ýäÀR8°ä–Ú‚!É… Øö›h˜ X è‡ èaDtk‚ErÒÕÊ’$Áxw-Ë úm’ýä$ÁÒ@`)$èÇ" –6ƒËsÕƒ"AÕEÔœ –$I‚j±HPïS$¨#%E‚¥n`ÉÔS‰K. `I,u‹(X$@A—Ct{ˆ‚%×IÅŠ9A,I€‚QL–›$XŠ j‚& j”ïœ/œqJ j1 ¶ N7BA6¡`‘«šU=CÔ#‘Ýd’ Ÿ’$X$@ÁR0PнÔ˜ –$É‚~dA'! ja j ‰]YÐí# –’Á‚¥v° Ÿ“,XÒ€KÉ`Á’ë¡nU]`A—Ct9`AON² ß'X0¦Çò£neïÛ†Û8Å‚¥°`į= ™`Á*n…– jk*ŒL°é¥jå@& ¦²ºTb`àÔ½X™x%0M’„ÀЃ¹1!°$Þ£AÙ wæÈ«ÈÅ€±-‚í ’\‹È€Úy #V0ÍÔ„ÀøK¥ 3ž0Q 8ËKÆÞû“f7@ ŽöÞáQ¿@`ÉŒ-a~O Þ ‚@ !ðÎ×:{˜xGPm¢$ Pî‘‚Àˆ­ÌE I¶˜!GºÿâM@2þ½ÓÄ_Á/?¬ŠúNÚ D}'U®ü?_€+êó×aQ߆iÎ"õ¿\ õér&Q_Ćä.ŸÔ7zÆRßõ°vRßõ>°âú"È#I‹Ðwï ˆ`¾c§o'˜/&Cš*Á|1ÞÅòùñz2_@FÃOê¦;2ßÝÎ/–¿$úîÖÉ…€¾ˆ³½Ë_̪¾XþJ9 ¾’ Ôg`o‹ûgIìÓ˜öEʵ`_Ì‚4yûxº6©ïî‡ö…0–ØìsEÄ>ó;¹OûâSXØçÖûJÝÀ¾R0°O3[ØWìsßûJíÀ>?9±ÏµûJšÄ>¿b_ɔأb¡¾hxúà’ú´ñõyPúJPŸ6P¢¾û¦[3©/yð$¨ÏR_Ä‹Ã4US(º´Wü"Èv<€ŸgÁï¾i…÷Ý×CLî+pŸ'"¸/*z` „z²¤ßu2“ûªú颡ŒÜw_; Ü’üFî‹Ðzøm‚ûŠÜÁb°‚ût‚½¸/$°öûJpŸ[Hî+í÷•ÚÁ}å)’ûâÛZ®Öä>îs)ä>·†ÜoaÁ>7Øœk>±/ N6õ¹oH}¥nPŸß7©¯T껯öÅþçOˆ¤¾*Iê“DÔw_²å%õÅð{÷OUNêÓ8õŶ)7–¤>bQŸ^ƒ¨OcRÔ§§õ±×}E€©~0_Ì1˜ÆÀ|n™ÏÏ@æs‹É|œòB>N^ŸT¢ˆ¯TÈwß°> ù¢T`bß²i´B­n8m]È7vØùî ‡¢ ùîö,"Ÿ¶B¾H³-ÈW%P«=òÝm8d¾(ù¯g2_ìÎã_œã‘[@"_)ÈWšœÈWP«–$òY@ä»7™Û€|Uµª® ò©Á$>]Í!â+UøŠÄç¾!ñ•4 ¾{£Í†Äç^'ñù}’øÜ]$>×â+I@|.ÄçrI|zp_)Àç® ð•4>÷1¯4ÄWrøJŸ»‹Èç‘Cä+P_HÞÅ÷Óm&õéAÅ}ûÔbŸ#ìÛÛŸŸZܧ© îS—‹û\,¹o£±\ܧ*îSÕâ>=£¸ÏrŸzFÜçºÈ}z/ä>™±Ä}º WÜûe“û"Ü/þ¬Ü;ê\SÉ}(—ˆÜwõ¯ÞŸ% ¸Oi¾sŒ|aÛ]Po¬•`2Ð^a2ÐÞ˜Ú°6öbo~.Ñ~º¡@´§;D{ޝ#íÉ¿[´÷„ËæG=GþöÞŽ_„½çÛöâ„•}ñó|oîí{ïyÓZÜ‹ãR¶jâ{Æ.÷Þ[ÇÀ½·çÒÞ³mì*Ò^œêÖÀv©–Þ—vÐÞÈÕéW Ú{_$A{Ï‚, ‡HyA×åç,¤¼·ã{¢(/H$ý£Iy% (﯇Y2(Ïk)ožÉ´¸yjé!äE’gñò|Ø`Áxþ Ä *‚g"žRðâJðô—%á½>} ñŠˆ÷>´¨ñÞþßÀxEÆ{_YÿÀx^)Éxï+ï}iæ&ã ï¯4ß&/þ›nPd<¥!ã©1^I2ï‰3¯roÆ„*“ñ†d“GçT§5 ¯´Œ’^Cüj®„¼E2ÕéÔ> V ¼'ž.w^ ¼’”7$ä&åY‘ò†äO0ϺœW“$çyíçUAržUÀ会œ&îKŸ|‡Èy5× …ºã+29oHnMγ#ç-(TKÎ/ •œgeIÎ{☳­FùMµ'6(Ô½ÑÇ´S¡v¢ß#… ¿OèÓý%«¾P©,œW%û•JΫ’*Õ’*5¼µô†Ì> ç€GAo–sÕ ¿Zr‚^-9AoJ2:  7÷(•ó,æ ÁÅ載yS~½À¼9=MóÊ|æ•bóŠ )¯ò† 1–0!o‘<9U-IÈ«’„¼)IPä•®ä•ä cLyÏv2†WÓ$äMIŽGP^é>`ž4)ï‰søzõ𬒙áTŒ`RÞ0T”7Óœ•òj!Iyå@y% (¯J’òJÉ ¼Yû[]CB^éò„¼Ø ÓO4!oHzn(y% ¯ŒjB^h¥-O6Ò@‚»}ÞYè.Vâî‚J²‡/Žíþ wcf&²ÝÅ ±]ÜÈ»âͺ6Ší†âƒÃ$ÙîÅý}‚»wÃ5I†;m„w·3îâcpb™àŽçÈî:,ц»‹V7“î´5 ¸+„C[^œŽýÔ£\&•U¸óÚo¸;yä‰áŽÖSÁ]øŸ&î80 wzÜqûQà®óDÂÝÉw>7î¸%0Üqr î.Ü“j¸»qŨùN\F¾S‹Åwª[|wÃ9Ú|§'ß]Qí†2ÒSðJxåõðÂŽMÓ]Þ~"ÒC€·_ü²AÀ‹ÑdRÞ¦‡Å‡S燓ð"I[ù4x:„\€·_Œy#áÅééˆìá o¿y\ /$ˆ3á9ê•„·ß'É€ðæa¢itáÅQåÇÈž'…ðöF# O'ž‹ðâ8ó¶˜óâ˜RØê’ðö†síEx:ßœ„§cÒEx:ÞXOG­ ötjº`/ÎZïËy.:]°W% {:^°Ç³ÖÅz:ù]¬§“¬ÅzEÖ+°žN_ëé€s±ž$b=âMÖÓèb½’$íy:[ö¼"=¯d‚=¯¤ëñpp¡žŽk–9è2ç9Ìy:vYæ½öìÜFlÏNZµ‹gçõåL—È>¤ Ï:‘c§HÇÎǔг3^Øþà‚Bÿ"yvî<Dž;½ˆåÙIoA9vÛz¬ç½Óª,ÇNùðɱS-ÇÎßäØyò@9v: ;ÇÐþdòëÔ›’_ç®S^è×yú”—t@Ùi—_']5äש±'ÇN=”;Õ`9vžóyu: ½:ù²åÔézèÔ©7)§ÎÝÇ·À©SÍ•W'= Ä1’7äÕÉw)§N4yuj˜Ó«óà 4ÄÀ(·U ”_·œ:Âx:uÒÄNEç“ãør¦‹ÓÈ©“£A>j!PM‘K§žP.¡¦t¹@@÷œ<:‰ô`±G§¼Ùåѹó zt“Ǭšþœ|Cr礫Ý9écÎ'*ÉŸS“Bþœ.‡ôî²C§CN àΩæÑ›sç¡PòæT:sÊ/EΜOž3§ÜèÌÉ7kgNyÑ™SîJræÜy䆜9é9%_N®Ðöåt&úrÊM¾œ–Й“oÖÞœò§’7§Z,oαú´Õ›S¹ä͹ñ0ys"&ÂÞœr¹¢;§üÌäÎéšàΩ—;'^¼9V¾c£(­|`Š7ç.IªÒ¸)-ƒ œ’væÄ¸ørÂZ'_NIèËI}W|9ùþíË)ŸP:sî7±NΜò •3§Î3ç®ãhäÌI'ÑD?­€öåÜq’yñ夜}9å¨I_Nç’3§]7©JéT+gNu…9å„)gN¹wÒ™s×!1ræ¤'©|9åïI_Î]Ç´È—S.–ôå”@¾œ’$ú] ý\“œ9¹gN9jÊ™Óç¶P›òUÙ™Sç¿È™Sž¤tæt]ræäŒ²3'] åÌ©dgN¹G_ô©99ØíÌ)ßMysÚy3½9õªìÍ©SdRcJÙ™“cØÎœ:SàO†#dÞUŸ üb¾W+_™ÎÕ—3A ܧ½¸ïz}² ]9ùÐä> ¹r^Ç—¾¸àñZBø®çË9.׫bèÊ9*¯çxÆöxƒk'<9œ¼hON¥±''LöädÔL¹×çŽÃÌ–+-ڼĮ—»3(Ñ-=?Ÿ I˜àÜës÷¸d¥^Ãa‰ïÑ¡ —yè§ïÑióîÙz?%.‡2”£Ÿ¥œ€¯«ÞdI)2–ßÿè{}îyÕýý{}¾¹•'¯í¹t¯ÏÏ$ø÷ú|ûæͨÙzÕÊ×!ã#ãjj*–å+{XV½³‡e9˪©T–îìQYåÒ•¥T*«¤RYº´Ge•[{T–R©¬’JeéÖ•U®íQYJ¥²þÀå>±ñ|5ÿrŸã—.÷9~árŸoÄÏ\î3ÒÝßK÷årŸï¯o/÷ù- ÔOë‚óÍrôÓwÇí²D}Ð~)åw_îŸr¶1ÿ{»Ïè¿ùŸÿ¬»w~튟å¢ÿ«üùw^öS„ÿùú—ýŒ§k±åkqãÅ<ã+wts¸»ô© âÛNÜ“~áÞí!yç–/ü¦àŠJÌðgº{@@~ìoˆ=¿öwœáyÇV~Sˆœ9p_ñy'Ok8@ú¾"îíšÇ©ÍŸñmgž®Ö?³žå)›0 Þ,ù΃KñQî¾Ó Ö5jžÛ÷àkö}ç1±=ÞÎôB¸#Nx~äÜpÓw&ÅvOñõ÷ýÌmñt÷A9±Ý ¬ÂŠwÇ™óà>UÕæ¹xO~ ¿ã¸¸Øñ:pÀÍAM4ÛqÄÚ‡kÍíÞŽó%î8 l¢™sŧ١G~Õ¸ã@³¸Ú1®ïž}ÕÚtŸšÅäËmc8Íýž’ôà?8âc9¿Ÿ8dHÞ<¶/¶ÕÙ¾w*÷’kÞ]µãÃ÷Ý÷#·{܆ä¿Í\óûïØùöÜïS︪/™r_Sºbìô>[öø‘¥„ÏÅì-\Àt÷12ç~O¯r^Õ2'[›ìk¦Á™ãmÏcDjåaQŒîÚq!Ôýló<µ3v~¢’7HnÖ5ý®ï¸ö)fªŸ*nøÙÏ%M|äyê«™×Â\Yòô ¹#BçZú+Ϊg¸¤ßOÛ'8³ež9[ÝO·³ùfrä„Fíw}ÃϘÇ8ËgHžœ®*æ (ÛËõcwÄuÜË(}ãΣ>Õßyæ„/ûï±”zž:þß<¹¼ãU8žúFgdúâÈ’û™ÓUÏqF1]KíÏ3§ëžÎˆ÷ô{¿KMcúÎΉ2-| çte×´ðÇzkG´éãÙ–BÂÏ :¤…ÏÖQàôœ®s¬µ-¾ñôÒ/-´Áœ¬;ΕjqXÿœ­œeCÒs¶bBµæJ6ÛzÚ‰ZD¢]K’÷͹ÊÑØö‘xÎÕš„PÓGÎÕ"y?—Æ„Ø2WÛ/‹ ndhe4¶ð†ºÝ áŸ4'*_t ïž«¼³N/9Oñ@a[œÓ”·…e}™¦íØ.LS…´cO…ªÉÔâþ9MÕ ÇÑršrR¶8¡e»j7WêT¿¸#¢Ø¯úØÇ=•ªæE Ó”íèS©–Öd GmÍÓ0MÙyqRiNS,P-ŽàÓTuÇi«9MqàQ‹3e§Våµ-Î×½z9O¸… 1§)&å<óÎd?Dœá>§©%iNó»ŠÃ¦{]ùÚ<îü­/øì©Týè¡î··vûù¦V-¹æ(×üŠÁp-Ã3ú-Õ*û&ä³­¨UÍ–ëLµ{´;˹¨V¡ìZ|Ó˜çáæ¶)¡^…µ]Ї,µ,½¥äNÅŠ¨+Ró<ëu~~kó˓ۉ¹¥kñÅ'&këÜa¶øtÜß²'jñA|`Ýá:0öS±ž==žÚ4Yݹ/™¶ûGA´%Ë•z5 ¹Ü©Wu²|›GžÔC‰Zœzs틤§^=x´ûI½ª[Ú$yâIká3É• õ¸pün‹{0cª†ÇÂüb×zK…zœe½§Bu1áDþ–ƒ«ZR£'Îl=¾ÅÆú;·Ã“.c¦ê¶—!IzŒ¿Ì/¸óÃÒ¼º%Tàü\81â6¾˜¨Ç†ã¾†$ª\MòBôÃO††;™ª_B’ŸÛ?f¿mrGe¿´Bö{rdökq5Unµ£!GGÂߨwãú*Â_‹Ü’©«Ú{âóá¯Eph à¯E dn¬Àí}àC+ ƒ\n¬€¿í · ìÀ-L™¸õ‹™@€º_H¨ë„D€Û{Š SWEš–LŒÍÆÔU"@y‹#Í•œ”¯°0v$w– ”´0|—·,^FÇB€ò&û‹—÷ƒ(ïD ¼éD€an{,¹@€1sàÈJ ðء΄€Gúý<ĨŠcC´g.0`LówaÀ°ÿ½ù”`À0÷% ‘ãÒh_ª*ÝÀ$ŒÉŸC<.ÄᓃÀB ,J¦®â2$Ôj&ÔÚ% »â Iªªã$ÒókÚ­„€ÇűNŒ]Þ\f„€nP˶0Òô„9 `”ü~ÔSÝ5ÀãÂÙÑ@.”â¿°°îYlò_Ü^•ŸŸÈGmRþ;BÉ-ü§{±ÄºáJüçŽ ÿ… yþsíä¿£áÛµø/LÀùÉŒüwÄ„B]©Íä?ë"ÿ ø¯´9ù¯ Kò4·å®/`”‘û`8òm ƽb¹ý#Æ`{€{ÐW‹ºPR XJêÆ21`ôÍ*LT ½³ J¡Ž`>A`€È,— '#-ƒ‰€®‡¨'–B€€Qs’°¤º#HáÙS t§“ƒœ²yÀÀèó¤b .œº?‰Çƒ#f„Â@¿Mb *'ê‚RàÑáÿ( Ômo¤@¿R »˜(OPQ ö•D@w0ЛW"àq>  fÐ@dEà?·–üm|{ €ñn·ýDÀR0öÎ ÀRNŽðü-þóßɺIDü}ú@¥ªá@þó3‘ÿ<Èš)Ä?½{ÒŸ‡é]GôóX ú¶xB¿Hs&ýüHD?¢ŸèçŒìçþûy•!ûyÄ“ýL"d?/d?¯hd¿’ìç‘Göód'ûIñ‰ý¤kÄ~&²Ÿû‹ìwœyn¸ÐO[£·1B?ñ•Ð{(¢ß±Ç•üv|K6üü|"øã>ÑüÇý›øO!'æ?Љð/B¢ŽLüS˜€ðOñbÆ¿ŸÌˆÚê ÿŠø§XDáŸÂÄûÅ{îEÉ{œV˜˜FþSw’ÿt²øOážÀE@…e÷þÅÀ=Üí> ÿ…Bl<åë7^ñc|çúQðmh°‡ûbnÜiÿÛO|ÚP‘ 2jŽÊ¨¯v2ê6*‹%Àp¾'ÂÈOA¶òs–l€ÏÅöÑȯEDÀpKB ÆC˜ _~®¤5@FÀ sK(·D! K&^q­öb¼âòúã˜ëÜCÊxã\.!`¸¢åþ¨£°mt¨ƒ1elؼ6É€WR®L€Ïö¹ðŸü¿m,|ª|6Úåhl"²¢Úÿœ…ö¿vãhdP† €±¿‚I0•U(­¶À_œ“Æ*éÝe Ô³PuÉHç-yÞŸ €ífU0>øXg 3ÑÈØég ÂlÔ[“ðÅ…Ç6vìLlÌN—õOÍ“õÏYhý+Xÿ„íÛúwDlýÓ˜ õïåŠ ë]ßdýSGÈú72]«õÏåÒú§\²þÑ«ÞÖ? Yÿ:œ òÞ´ñG>Úøg tеñOÓöçL`?z6Úô×qs¶L*ä'÷m˜þØu6ý±‘Ÿ\Dmús.šþ0¹~òOµå/6 ‰p4þ=¸õMàWZGã]müÃ#‰ûä2mãò·õï¹±3!øÉ9ÖÖ¿áÙúÇEèGßXÿ8îeüSÕ$?9?Ûø÷àâ>ÛÿÜ<Ÿü˜mt.ZÜî'ôsWÈÈ)f bÉD~ ‘°ýþ±¶ÿÑiUà§pÛÿµ&û߃˶E~ŠI‘ý®¯6ÿIî“ç³­j¬z D?yY ýÜWD?õÉÏGòS´”àOq ‚?Æ:ˆýž!öSx”ØOñ/b¿’ ìWrÍQÎ{%.„ðç,„?KøóSþJ9€?¿'Â_)ô§Há_Éü+¹@€~$ÀRІ¨iG,I€ò½'ʧ_è'Êk]èEXŠj}jí–r€^ €ò€r9ÿÑÝ]ø§Ð ៓€þÜ`⟂—„^Ñ.ô'ÍGú+…ÿä¯/ü+­þ•Š€NCüsUÄ?—Lþcø€ð¯$þÉï_øç‰üW$à¿ØÀ¥øçõ’øçµ™ø§Ó˜…Vˆÿ¬7ˆV Ä?KüÓÆUø§Ý†ð/v-É™Ä?mè„:ÚPø§­¢øO»è_¹ÝÇÌwÍ‘]™ïj²òù¶ç«ÏgÇG3HÔ>Ÿ´_ÚçóˆÑç“_ìó¹ÓoL>Ÿ2ÈíS_êÉ|úþDæó§r2ߌE¯Ì§Olb¾ø®˜›,2ŸŒÞb>ÙßÅ|ºf׎ŸNæ;^Bˆ?Ì'àùÂø¿Ÿ‘YnŸ¼>ZħK‰E|º¤ÛnŸ›Ì’I|ºsÚnŸ¸j^Ÿ;Ö81ŸÿæÓÕÛb>][-æÓeÜb>Ýf.擟„°O—] ût¶°¯H€}ç¹ÑŸ”~Ÿ®ØÎÁ9ˆ‰}ºþ]Øç\ľ’Øžiqö¹rb_I’ØgÇdbŸüA„}ºh^Øž&{B°¯ ì‹kî¥À>—Cì‹4'$ôOa_üÎóÀ%ùñ@Ÿ«"ø¹»~Eðãöä>9ˈû"1jà>?7¹¯$÷•bÀ}j/±OŽ:¾ȴòRG•4ྒÜwž8ÏMÜçÊÉ}s«¹8}žg§‹'À/$ùQ‡àçCòsƒüJ~QUj‰~ªYèw^ÛGá>5_ÜW²€ûÔXŸç~çùÒ.ð+-ø•4¿RÀOÝ ò;¯ »[’_ÔË!ÈO‘>"?<&±ÏYˆ}.Øw^8OÜW2%÷E’¾XüJ’ÛÁJ°æûJMà¾R¸ÏJî+å€û\¹Ïµ“ûJ€Ÿ‹äçÎ"ù¹.’ŸÛCò+¹’üJ’Æp >ȯ” ô+IÀ~% ØÏ-&ûÅ =öós’ýö¶b¿ýàwŸ–ÁŸÝõž„?dÒ_•@±æp#úyý<Ò‰~¥ê÷©Yˆ~n ÑÏ…ýJ _‘ÐïSýŠ„~ŸrR$ú•4@?÷žü>†~ŸXfíö©W'·OIäöiIº}Rߨí“KŸÜ>‰~ŸÐ%rû¤r¶Û'·vû<Ętûiu¶×§$0ýµ‹V<ÚþèY!Óilú“S‰L÷C+ž\?%¡éï|iÅ£ë牳Šíúi ]?yr”mNCßOºeÙ÷s§³|?-¡ïçŽp;îôz–óçFg8v™ú6ø¾mpì¤íOÖKÙþ,¡í'˜ÙögWO9ÒZ¶?žDjÛO+ü)Ìî;WüøÚ´6Uàëðqðñ¹lã£-Ò¼×pù m|/> øŽ˜¶I‰¾“ÁD²ñ]/½C |)Ýläk8UF¾¦ Ÿ¸Œ~<>Ì‘~œ¯Žô£3µ¯Ñ–©H¿ã`ÔÏÆH?ç"ði®H?ˆ¯o4ù´ñò‰-„|í&€ù´cò¹v Ÿ ©B>mF“ù¸yòµƒæ·ã‹j2ó‰Ä| '“™ùœ‹Ìg ™¯1:TÌGåoæS׈ùd.ó]¸¡ÇÌÇí“™OÏ%æãöÄÌç\d>µÌÇŒ™OJæk8(ÝÌ7·>î1 |÷#¿ÏwÝGø.ßlàkôüð)€O #àS]>=“ˆO¯AÄç4$>uŸ‰hKä»:£…|"R Ÿ¡•È7ÊÏŠD|ŠÄ§Š„|F>Ž#Ëò9—ïüâçY°ÈÇšøÄ‰">e"ñ]¸DºŸX’ÄÇ)/âÓÄÇ핈dè»èÚbèãNÎÐÇý•¡O¹}‚GAŸÊ!ô±û ô©…‚>n÷ }ÊEès.BŸZhèc Å}ìcs_‘€ûÄŽä>mtÉ}êÁ_à>g"÷9—¸ïøâéi$÷Y"îÉ„æ>¥÷‰Ì}9}ê@aŸ%¾›NšÄ>§öé9}¢P`ßi ”«†…±OôHìÓ‹öi+.ìÓ@‘·§'éíiQb—cß!+ ±ß¼ ö …}€QŸÔà§L?Lð+êcÏïŽÀïøjó+À&ð“eNà‡uÊà§W%ðSä™À_ ø}µù­~.ççÉO½.ò;dœùµ/F¿m ?~E4ù ýö5âï[ô3Ä ýø Aè§çú9 Ñ›¹ñG ­Øo§)Sì§6+âOªˆ?~GwÄ?Ç‹ý´%ûÉ—NìÇ/ö øsÕ@¿Ò`°_ŒÚsa¿Æö‹£x“]È~î ²_LÜüNCö IOûù1É~^ È~2eˆýÜ¥d?¿b²_˜ZPö•ýJå@?ñÐÖ#û}ÊÙìç¡DösÍd?÷ÙïÜúös(ÙÏÍ#û90TG!mðä(7ÿ,Ì·÷Å=Fçbäã $b>•(æóÁ d¾ðxC´˜/Ž"™ùtb°˜¯m<ˆ‚Ì7ÖdX È|í`´™/¶ù{í‹{-‡»€ Ì|qíÛׂ.æ X€C&˜¯½â90_{èfFækïÆX:0_{a#òõí¦¯%¯oí‰@>]Œ+äëö&B¾ Œm9Ü¥ï€3_™ºDö9I_̳k9Ú%.ä<Ù7€nœ¾8n.KàëCÁ{=&2!x/JIœ'ïõ£ÌÉ{ý|)ïõã¡K&x/Šw±ñEš}±ñ•‚÷м×/ò'y¯-x‚îR#õ“G÷÷ú™w´ ÷âLâ§â^ÉÜ‹<8·%qÏ…€ö,ï•Æ÷ª$ÕQ´£à=w1y¯Ÿ<öˆ¼7¦*æ y¯Ïcß îѤ¥˜¸ç' î•4À½~6÷4nH{º„ˆ´§;ˆD{rv'íÅѰ9:I{º”H¸§K‰„{–÷⚢Õ§K‰„{þrEÜ‹ý|_,| î…ÇÃ÷övÒ­¼§ËÄ{{ŽFÂ^Üu´-1}ºýˆ°—-Ö= õtñ‘POý„zEÔÓíHB½üÅA0@½*ÁGH}`$êIãGȇ£@=G^õte’PÏ3‰zUòâ#|—ê PO$ õJšD=†/‹ô,HÐóopžîaçéÖ%q^Hò«.9O1â¼’ œ§K–Äy:Mœç4ä¼*Iª8nžnkèéF ^IÐ+iôŠ W$ zUU7UôxŸ“8Ob^ Tž—KÙ¸ÇÛœlÜS§“òJ.P^ÉÊ+i@y% (¯J*Ï[<„yºKJ˜W$À¼’ks^ü!ÌÓm!Â<Ý-%Ì«’‹£¤ˆy% 0¯¤æÙ†@Ì+`^‘óª$•ª.©æ 0ϹˆyU’JÕ¹ˆy¼¸Š”Wò€òœ"!Ï¿ÁxñÜÃD<÷¯ÔÄs1 :‹å“MŒ?¬§»èú„@#ˆãøõ<Eá}åêNQ`;x€ )0ÿX(Pw‰K.P`|:hK€/Æ5:ǽ¼ z mÒGÏÈu,F?¥ êêcQ`\¿sÕø>Ý $ ŒCï“ßÇf¿qçгœí2OÅ_(02Á§ëÃéèWI ô7RàÝoI‰€Ë›EqPþ³ýîŽ#ÚDQÕ±P`¼gô@ñÜÇr¸Ëýœrëœ+”ü>SaEŠ­†÷ŵIÛr¸K\ot/F¿û9äø‰X„—çã’CiâèP`ôñ»î2Aúª]Ç7ϸœà]Ü<ãDpžä™ú*ª‚5ÍIü%¶ 90k[üüèàÀyÉÁá7ö@0ÔLŒë¬ö%Â/Þ\~ï& ¶›'†Ç,'ÁÛŽ˜e‘`»y IP‹€H°¸2M$³xõôlûù%įítÞ! –º@‚‘ë\w‰‹±ŽÅÓ3Ö‡%Ä/–޶Øü¢ù ØO ! úÉ‚š bA}- Æ*˜›~²`;yÌY°u…‚ÛÁÈ‚ZKÄ‚qľøz¶s'ç6À¼CÔ'O±`Üv.,‹0sÁÇÕ8c ò‹½WlÑ FûZuõŒŠ^œ÷‚«÷F‡Q `Ü-8 rE „¡÷%`°uFDÝÇ„Áhß¶xzÆÅg÷æç1@ÔÂ%ÔP" j ÆÕ!¹c' ¶Æ@!²`è¶øzú9ç8o4 õw’`ôŒg AO)’`ŒÐ´ ="H‚q§NŠ FãvHR±zô‘Õðì §IÐo$Xê z&’µ°ŠƒXÒc$8á*Q0ø.¿XËò° ß.aP]Jô’Iôœ' –bƒ±CÁI5 AwiУ„4èºHƒ®‹4èºHƒ^ÿHƒ±ñÊI¤ÁèœÍ l²dœßóWIƒ~ AuaPjI0X ,Ue» R“Š­È‚C©A‘­QÈ‚dÁûåq¶dÁ¶ñpb²àX+×8¿û‘Ïf·j]ãü¬˜ˆ‚Úâ$ Æ¥×ççšÉ‚Úˆˆï—¤dÁØeŸË1/Úì‹ckw,q~±YsßÝøÍ€0°å9/ºhÆ¢.7_<ô è>ŸŸÍ‚üû¸¨Çfç©E[â w(Ã…úé wžy¥éÒDI\e(G?K9ï)¥”±üúG_þÓŸØMößxùO½æ'6ô­ë »)Á7ÿœi_ÝôKI󢦋B¾y'æ³\ÕòelEwŦ}IÃ’|éKª—þ $'BI5JÒ•?*©\ùÃ’”ˆ%•4*Iþ¨¤ráKR"–TÒ¨$]÷£’Êu?,I‰XÒ¸hš!‡.ýßãJ ß°^ý´®@_—§Ÿ¾;V—%ë»u-ãw_, ]ý¿ò: 1UËu@ã×÷®â‘3¾|öþãc¡¯j¿~Ðü€Àí˜ëʰÞOx+Äí°ÛBçu×óœ¿wô;°£J7”ö‘çüñô½¡Ù¶øã³ö¦®ëåİùcžó÷⤩z[‰“IÍ{Û±gnîâ\3õ÷ÛŠ ÑœÈéï•aÖÜýØGgndÎýÃç§Ïm_ïÅ{jînÓ?sINÕgmn]3€NÎ ÒÝ >WƒyæY¸5WÓÝ‹.}Ó åE¨Ù‘-̃•í>86=;>„ÂYpHÞ Ìƒ£lïá|u—Òé>r”/£Ó£ µ²nN§½ú³öÞ¦Õ…®÷8,_ªjs·Xsµ'ý½\W|ü‰þºa—ï¡ Ÿ™{÷ô÷¢ð<éïEWòþÄןéÇÛ}̧¿½i{Üp5¾Šä ‚™åä;~¦ëÖ ã~[‰ôÐäMcÏ8ØdL‡¼ZóØæ=Õ;®?cc“Õé.1–ÿ þ™ðk’'ï°»ñ­´?ïî^*øïD½¶ïÝ·ôϼá 0$=Øi6pn|ûÎ?ç’æ<Ò?“w ô÷Úæe躶jHzúgÞðùèï=³öeWý¯?H3‘}ìà¶tÐtš°ÎdUù ϳUó¾Çgý2?ïÿ0ïŽ PѳÅ3«˜OÜDvî®iÞœ®|UÏSçX$ñí§/‡Ëì øQ É›ÓUGøÇYºæ‰3ãçlU’´vù- É›“Õ KÚSûjè¤+½3áûøìªædå‹zâÈ£TQ°s®êöóÂdì½=¾̾ÂWî!ys®òu?aÈ™sU].s®Žæ]YNß1WÕšøÀs,%ǧŸÚYqÎæœªŒyⶃý©•Û“Sµá‹ÿ3O©Óì‰SHçTå¢ùù¶ÙÁq*yNU¸©e\)Õ—ÞºN¨V§9_ÍUH®yYR-ù†juíªNøOœ’sÕ!:Ïù¹–‚hV?V˜I¯¥ojVuμªù®™â¬ãÃQŽOXØÚ2¸îšU ¾OhV=Ô}A³ºàšÕiîG³5“°5UY–¹Îih®ãê6×=p`kKÖ:5PÖ:Yë^\Z-kÝ 8›ë4öi®ãEí6×ñEÙ\Çbl®ãÀ±¹ŽoÏö: Ûëøà¶×ñ©l¯+Øë8$m°c'Û`çºh±ã´ÅŽ/Â;å¢ÅŽÎÛbç$°ØY@“%4Ù½pä´ÉŽïÊ&;µF&;õ»Lv¼ m²s.šì\2Mv.‡6;µP6;å’ÍŽ“Ä6;ç¢Í®#Æ6;u±lv–Àf§Q!›'‘mvœŒ¶ÙqôÛfg mvë¶Ùé¹e³SoÉf§ºd³ÓSÊf§Ñ%›Æ¤lv–ÐfGUd›žT6;×N£ú‡F; hµÓ«¢ÕÎZí4¯dµÓ‹ÕNuËj§rdµÓ“ËjçrhµÓÌ—ÕÎihµsZí¨„mµë8.Õf;õ—Ìv–Ðlç’a¶S“e¶Sšíô†e¶S¹2Û9Ív–Ðlçªh¶Ó“Ël§^–ÙN/Tf;Íj™í:÷½2Û¹Í4Û©™í4e¶Ó–ÝîÉ3`m¶£ÎµÙNM¦ÙNO.³FŠÌv.†f;=•ÌvzÃ2Û©¿d¶s.˜íôà4Ûa_«ÚF«ZO«Þ-­vÜÈjç°ÚY«ZE«]¤bu–~/‡ÕNc%­vzy´Ú©Q´Ú©khµSGÐj×WÌ+m ÕN}A«ß>vÎ1vnŒvn¬vEf;\Ô)««„ÕN=A«Š ÕNYhµ³V;õ­vÚ¤ÕŽ'ìÊj'µM³”f;EšíÜN˜íôÆh¶“:¡ÙÎY`·c;åšûbæ&¬’ÝM¿±Ÿ÷ÅŒÐ2XÞ@vûËÝ¡|1y“¯}1w„YËs{‰ŒôÅ´¾˜°]I¸‹8¼Õ3Òt˜çî" <pÏðV_LÞq,¶‹½:Áv¥°n\Ûùw~pÂ])pWpç×@¸;ŽÞ£€;—L¸Ó½Ñ‚;…ù ît²àîÈa3ÉÎí'Ù¹^])d§sÇEvû‚ÕXWÛ°soìüÌ;ç"ØùÕìÐzR[Gª‹NÉÏ"¤:?©ÎãŒXW*Ö °Î@¬+%'Öù™ˆuº·›XW’ëÔa]>¤˜No^L§‡Ó©qb:;1ªÓéÄtE¦SGˆéJƒÁt¥v0@‡Ÿ 9-“¢9šÓ‹͹õ¤9÷ i®¤Í•‚AsºM4çç!Í•\ ¹RhNsG4çrHsniNs_4ç'ÍÅtJj˜4ç@š+’¤¹"Íù HsU’4çž Í•'Í•’As%hÎ#4ç§$Í hÎí!͹vÒœû†4·¿â;МG i®Ôšó»Í•$ ¹RÌ…Ê7Nšós’æ\ iνCš+’ãú2WIsÒï¢9×Nšó3æÜdÒœGi®ÔÞ©RõUªêÍIç“æüjHsΚ£J̹"œ0WÒ\_Tª`Î@˜+iÚ•*˜+íÌyèæÊSæÜœË!Ì•4€¹"Í•\ 9?hΕ“æŠ4§>%Ì•r;«êÌ•šsE’0瘋¾I@4§zsîpÀœÛ˜óÌùas¥Œ„9W’,ç'Ë9A_:(WÒÊiG”óßrnP® &Êq#C’óc‚äJ™IrnPÎ͘(§gÉ•“äÜ- ¹Rb¢\$ʹ¯r.(§ yˆr.(W²$ÊyHL”³ŠÊùÉrz2\©"IÎ äJ• r¥È9çHŽS‘ß¹qÇF¹<”´°Ûqã±/²ºÅµPÇb”+Ö3åd,“QŽW©È(Ç ;l•£ç¾¬r¼ÁÃV9… É*Çèž_°ÊÑeÛf9zÛ,Çóþm—“P†9™îh—S„—ìr ‡’]N%»œ ¦]NV6ÌÑKR†9å’aŽžû2ÌñFæéDÜ‚ªd˜kr¤¤aÎih˜s¬ sì æõ%Ü’Ð.§ž]®Ée“v9§¡]NÙåôܲËiTÈ.'Û§ìr K»œ ³²Ëµ<¿ËAtŒ6“YNÍ•YÎ!~4Ëñ©e•sÛh•Ók’UN‘UŽ—øØ*§'r}kD§Ð;Zå\Ž‚è2§ :N™åxG”Ír4R;†®Ó­V9=•¬r5´Ê¹y%ˆîZðí7Ññ=”(:z´;ŠŽñ²Ê)~KV96¹DÑ1¸CV9§¡UÎåÐ*çö(ŽNî—´Ê1t€F9ŽœFGŸ{åÈ$£œª–QNÍs]ã_ £s&…ѵÕÛ²ôß/„ѹ´É1@&¹X“œÞh’s`MrŒ¥eã0F§h7˜äøÔ²ÈiÔÈ"Ç d‹œÓ(ŠN1sŠ¢Û¾0œ«R»ÊAtxٲǩÇCç¨:ÆÐ©Úã8 mãeYK ]fRceŽsHÌqz“2Çq™9Î} ¢cƒeŽSˆÌqlS[#sœºBæ8ö–cèÆFkœ†‘cèø ²ÆñŸCÇUÁAt tq‹Ö8— kÛ'cGmqj¯Cè°è/!tù¡S0mqªÙ!t Å£-Ρx´Å©y4ÅI@Kƒ—K×9бgd‰S‹e‰s-qÜ<”:±)‚NÁp—¢ÓT¬*FtÖ S¹´ÄiÙp VrÁ×pÔ®,qóž;FÏq¼(zŽ*zNñuŒžã ¢ÎÀçp:FÏ© FÏq‰¡N+¢ç8˜=§½ŒžS8£ç–Æà96ògƒç´à–๠žS4ƒç¢Ç;9±<§¿Ã§ÎTô{Fás8]Àás*ƒásŠ:cøŸDásŠ\cø«UøÕ=§¼<¯¢“å=‡-½Ãçø>>Ç=Çß°Âi&Ñ §I¬à9GÓ=5̹\™#hÃbÚâ4= ÚæR\ª"+j ¦‚1 ÔÖÆ^†;P[âV¡Í¿Álºl†Ì¦&Ål:0ÌÖÆv0ÝÉÈlóP·‚l13ˆÍ)l}î£ ¯õÅÖÖÞ‡.‘¶~( l1Ó÷ç»ql1רâȹ¾[@øÀÖOòx-ˆ ¡fÉkºÃD¼w˜$Í‚×tŠxM·åˆ×t3‹x-Všô%¯•‚lqrð Iª–X°®D8[¿H$¶H“¹$¶Hƒ‡±éö[›w×à¸Ñ.:•’Ø"M/‰ÍO1‰­Ÿü¤@bë7¼CAl8y¯[uœMbë7¼½Dl¼%FÄæABb‹Û…@“ 6·ŸÄ¦{xDlý>¿øQ–\ ¶PÛâG‘¾¾$6] $bë±1LG[¼Õ¶8RÆ›ÏL ¶8Ôù¬§žD xl‚Øb$=õØ“’ĦA"bÓk±õ†#¡Elz(›JÄÆ Øb\öÅä˱'=”iÂ!€-$p¬°E/¼‡d=‹Å-º/]+ÈkqD#¼Øz‡ç¬€Ã¼6ÚÎ൨(ÝùÈkîòZorl°iY°éí ØæN!+°éõ Øæj°8QÆI”Ùé6?›ÛLbs›IlqZåjv›‡gÑöò. lšˆ6?‰­T bó!±yô‘ØJ9 6× `‹y·P››ûŠÈVÒÙBò,Èæž!²õÞi ²ù½ÙJÉ`6b2›‡(˜ÍÚÌ'î0Ãõœ¬ì.2›»”ÌæšÈlÎEfós’ÙÔ¥D6Ïy2›»‚Ì6Œ_˜ÍšÌæIfãj,dÓº*dó+'²yúÙbÜ“›;ÐÏý,67?7¡Më¬ Í ¡­Th“´õ~}±¹u^h&jÓ½hÂ6w ±MW» Û´‘Úú-ÿDP›G©MšTÔæéIj“ò"µ¹wHm±Dž µùÍÛÜͶm±¹¹—‰m¥.\È{‰m~ã=oä×4›ç3ÈM·Ã‘ܺùmÝ<¶€n¼ ‘äæ6Ü<†An3“ÜÜ ·è ³’›§?È­¤HrsßÜÔ*€›¶·"Hpó`¸yí¹yMrÓ\¸¹÷n~p€›•à¦}ÉM[€›¶Ú7יܦ7ú;nÂÑÁ'q¦Årêk\Ep/Æ8]¿ä¹ WU”C-é×%GJÍÑ‘2Nô¯Ž”qä}n¿eÛu6 ¬q:GÒ1r¸[Ö8lÛ¿8Rc­qŠ‘r­ ?%çªhk (”5ŽŸámSL—¬qpþ-Ar ¶£1NQJ2ÆÁ¹É=d'Øâ"êsµÅ}$§È5°]héÖ9ºð³jÙâH¶+¹hŒ‹øÑÕçæ€í®­óZã^ºÛ’íâV£­|2s­Ž”®]Ö8Ř‘í®>ƒ²ÆÅ6ÛÖ¸k£Ÿ,ÙîÂÁ“Ivn,ÉÎM#ÙņØ©9¸ã’ìtK“ÈîÚå² ²‹çéK„œ+'ÙÅSûBv×F'c’Ý5Ò®Z–\ »¹K;È..³J*'Ù]c’l‹-νI´+¹íÐ{äºÒ–äº(¢#`.¹.6ëq–jœ¸®HÀuqÑ™×EUùµŒ\§÷"°+uìôv¥d€]\=»À®” ²«’$»k?yÆ%Èîóñ¬ñqQðÃ[’´+y€vñ2ëÁ'£\#²Ó›Ù]¨X×’ÕCO|‹µ¨NoNTMygJ?"©.îíÈÙ¤ºhËcP’꜋Tç’Iu%W¾my[ëJ!‰uîKb:ŠTypj&¨ÎIuh„º"Õy€êÜW¤:÷©ÎÏHªó€%Õ•r@u~/¤:ÍeQ]Iª+P]É•TW’€êJ“ê0fˆt~l"F‰ÎL¢ó3’èÜ"G+‘Nëž®äÒ NwÏ éüHdºÒB0]ɦ+íI¦Ó²'¦óèÓ¹\2]•¤FÕ`#Ò]ûCëÎE¤s¯éJ ‘.–å­ž|R“HW¤óZC¦ó4$Ó9™®HÀt×ÁÄt~ 0‚LçUŒLçN&ÓùEé¼4“é<°Étî0ûLçO¦skÁtî0]$ÓyÌ€é¬Àt%E2]©%™Î-ÓiÀôuÌéJ‰t^#t®Hç €tî ]É’H§)¤s@:¿} ;w"G®T‘Hç…Hçw ¤+E&Ò©c€tžH@º"H¤s­@:@ ]ÌV]´‹%Ó¹óÀtn˜Î#PçgÔù‚ê¬îAu%KbFZ¹Óæm£Iõò†±{8çQ5º#‚ÝQó³yÿwÚìÛ>9)EKâ[d(Õúé{dö-.í<–r(©å¤Låàg)gl®–Öàw)cJXBþøGßgó¾órÒï^gó«WÔ´ë·_gÓž?tŸÍ7ãá×–-׌|VsÐóÔ¤’ %ù¦”ToªaINÄ’j*–¤›jXR¹©F%)‘J*©X’nªaI妕¤D*©¤bIº©†%•›jT’©¤?pŸÍ›÷»~ÿ:›öK×Ù´_¸Îæ›Qð3×ÙŒt÷÷Ò}¹ÎæûƒêÛël~ÃRõÓ²ö|³0ýô½¡ZתŸ§k¿û:›8Êöhß¿Íf<üßüÏÖå2¿v›Írÿõ›n³iß+ã_þàm6o»óø¯<Ž·LÙ¡£çp‚'Øpçä÷\FŒÛ…󆇆›Jp¿áð¶wÞÉûÃßpxÊèï(<£û¹R¿ý@<6¯C€€|úyû¼.×!§o|0‡w¨¾=®8¬?Ÿåpbñ†ÑóMÁÜc¼a]0‡ —R¿=® üðMÛCðÌf]¸®ôíñ¹*RàNÑ÷Ù2>‡ ïAÜ!xÒÞ6³H\]úF;qóæØDâÞÃùXO\E9 þ+CÐg³]à}ÏfÇ ™¥ÙlÜô޽ìl¶ í¸ÞpÍåûL7 }²Ùo†Ù5\s:TüV[ùncwç¥ÅcÏ’: ׎¾ïq|ââ¢çÿçî r~I‘í>÷*zØ=ðUf lÀžX²¥ÚƒGïI=ðþe‚8'âU·ºªÝ¶¬×=¸õ$$~œ€€až¥š¶^o—tמ笾EçEPãigZ?GÍ·è¤áí^îÈ´W/7›kî½d!+§‡ÙÃê„S ë3a뀖â®.Ë}ï¢w„°4‹ïª“4Ï{~YŠo«ëˆ»º,Õwêt„6ËÜåg³-KóÝ:l•ey±Vþâw÷í:†|¸ÆNq8-ÃwìôæëòËbQ|Öÿ½ýÖ Ã«€gn3³wW!+uÛ–õ£À÷š4[lpÀ2¼owaY–½ Ëýë·=šæ~}O]GS³Œzß²¬äãÌw}Rž³Rôê,Í^¾¸ÊŽ^xÆyö^j[Üò.`êE;Ô³w gË<¥}jðÔçx–¥ùκ,‹½?g ¬õŸ£kYO<ŸÂ3|{”wøþºuÕôî÷Ìv¤(×Ãg0`˜^¼èWåîŸ*ì GL\)ÇìHÂ~ØvŸ‚Å›~Î4 Æ-lsõûè/N€éòÝ›]ó1½8ÿ%/éØîšÝ±ßßU¼àÝ—i¤0æpV¡cÏkÔÒ|ž£¼›^3IëŸÏ¹IñïY¾þ ÷ùy}¼ŸÏyŸ•o*®FÕ¨ÓÀñ/Yïݯ9² œÿ’UØÿªUÅ‚=°Y«±÷}çÃØ›Ïe¼>ªJù°V®åÇ90 ì„UË8ŸÂ¼^ö#fÞåÓËçssÔB’ƒj|‰g9±Y1¨Æ0;qŒ\ÓÆg^0ßö™Û œ —qÖ`ŒÏç|NŒ©|t6ÿ‘KlvqL¼Ì‚wOÉÆÇsfcCÒù&ØþÇ™qíç‹`(Î ¼!ì“ÀYÓtŒ©™'ÀÈ­öÁ'R<#)æ<ز9¿–ëŸA• 9»X–ÉöŽÅe„Èù°!Ï Ó{u-§‘ƒ çÞawCãÜkÙéÁq.£ÛçÖWë 8Ͻ֫ðÜ2T_Ͻ¶ ´zü4g[lv{ü4ç»ûb,xîµ~ß<Åæ¹×8y´ý÷æ+«à¹×°b»W€ç^[Õ}ß6ÏeÄðÜ; ¶ €çÔ°yîµ…`o繌ÑžÛ†<§lž{MoŸÎZ;jA^¿ynE<· ÝYlóÜkxÛ<·ÃÖ6Ïeœ ðœfºynpzƒ¸ÄxN²tžSÃ퇤od žÛ¿/æY*ç9½Eõ3Ò+âX‚ç4æg¤×€í<§†Ísjاù›”sçæ9Író\^@ž{íóxðܶ<Ês‡åñsÒåªâa ÄRoî;nžËò‘玫v¸IÑý´tÆx"Ïí4ô6ü “4›ç¶eßü=Í«è˺òNsv ;rÞ@÷šüv¸ëçš t‡åõÐjŸ:8ÐwÚ@wÜiÝi^¾°8н濂áè¹Ï;9Ðéžgœ)Jc ˜¢zt¹OóðrŸæñ Äòz€ɧ?Ÿ8ЖΧÀ«æÙâtšÂ‰NïíD·-˜©9ÑW•çS'ºã^µž‚ÝqÕëñä^/^æ¼j‡6‘{y ×Ì›½„iædp''ºeñ#@HtšÝiñ¸bÙD§Ås¢;nµ‰î¸ªÍó÷&ºãšîѲxãþoø€)·žï'Ýa¹}̬ÃWít‡åñQ3nî<§†zŸWT6³,ŽszÉëãfúÅ'À\\ÓÒŽö-?â‹äUsšæ½Î·ÇaîH#Q‡¹ÃМÉaN“4A5,§I{/ ½Mû2ô^Þgɼ†Ž@#ÙÎqšGG¨‘¼èégá;BH.õù´~G°‘¬ sÜqÕ[Ù{ˆmÏÑøŽqÇ%ãýV`ÖOãôÖa÷Ä‚ #bAܽÌy ìˆZæ§ ¡G¢ £]a ðˆÜçÅPš„ip$&Äiæ÷ÕsˆÓ4NqšÆ)îHó`( †ÒIHŸåsM-¬S Ꞥiƒ-Ì4ocºbÜa×§#9Ç9Ïv>…ÍqÇïûb n¢]?Ë;,åaX½~|r®ý| ¹Ãò>çsÉù òžÜk´ó7ï©e~êà$wXîz¶1%ðìK ¹#Méú¥ùakÀrÝ&§×!§‡_JsÃýBBš{8%§4Wüޡ̭ר;ýAšk7dJs­(· 8ïˆÒÜýb#1¥9Óÿ¦“™Ks)Bš“&ÍÙ q8u¹4w7ì¦4')\šƒKsR —æ,Åãwiî~}4•¹ûÅV|*s™àz=„¹ûEÄQæìò˙˅9ù» s÷+'¹»(gÉå,Áíäè¢\^áš\Vš\qkrödg!×äòQA”3Ï^×H!ÊÝ«,U N .ÊÙM‹Šr¨¹lD(rbpEN ®Èe;mEŽù¹—­ 9.Šr\\r\\r\Ü4ä¸hîã4—ãâ „§W¹§÷zëyËqšÂå8ÍÅå8½·ËqbwX;î=î¦<çb\<½ãË`Ð4[Œ‹^b\dêJ\ô€PâÔâJ\¼Ž¡ÄE&.Ãé]\†“’A†“4[†“L!ÃIgØ2œ45d¸x%B†Ó\]†“âC†Ó4.Ãi—áÔâ2\¼^!ée¶#_Èp‡ezù¢ Ã±é Âiá"+prW(pÒrPàâÛ œ^å Ž_Ü–þÉ×8ÍŸ8\?8É œZ\‚“« Áɽ ÁéU.ÁéU.Ái—à4Ÿv–œ^ÓᯂÑ&$8i?HpÒ¯ ÁIHp’3$8é¯à¤A‚“Ç Žwëoúg×ß4‹Ö>o(ô7µôÃ2¾…!³J®¿IsB“Ýú›¦¸1NF.ÐßäÞàä5€§i*̨98i`(pš+pZžÃ&svNºñ–àØàÐߤÐß$ èoR8èo’)ô7ùÒBÓ45ÆÏ‹’Üü|¡À©å­ß4]>¶ßôÏ.¿IËA~“C~“–ƒüÆl¡½I+@{“V€ö& Ú›f[_ù´³CC{Ó|ßñùŠC{“7Ú›¦qíMÚÚ›\ñM®‚ø¦–çþt!¨oj)çÈ õMê õMúÔ7-ÍÛ>u€ú¦9ë[‡ñK!¿e>.¿å½©¿iŠ»Ÿ#õ7tŠoš ^ç;JõM³uõ-‚ꛦqõ-«DõM <še>ç;JéMnéMné-Ÿ¥7¹1¤7½ªô£‡üƒ4Aikpªí 4è{Ä´ŠY81íÆnçÀ´õ@ÚáAùP—"§=”™ÈiE"rÚCõ…œ&‹ µrÚz̯§§h>Žik³iâA`ZæL+XVL+ŽÀ´Ì˜)ÈidVbZÁ‚%8-þ L+Àt`Zü”–¥•A_H€Z¦©¥¤VAùAjiª•I'N Z¤pT‹¿ÕâDµLTÃd±`ª¥¨V/_ ¬UĦ X‹`µ,%Xm]AwÉGÓƒÖâ7` ¿“ÕÒT£³p¢ZÅ®ýD53QM,@5¹ ¨Æ¢&ªÉUÕ$PM->ÎH¾@5±Õ¢R$51 ÖùÔ²,d5IV“4`5±Ô÷ü V“\€kjŸâÖÒX“kÀkjŸö%¯ÕX8u^‹l‰krÉÆ5ù \+±ÞH\“Lkrp- q]?q- Z“ŒAkrÑlGaHk™‚´–…!­‰À&WØ$g0›¤³‰ÌVby–Ì&iÞùyÎlù~‘Ùä0›ä fË~EfË“ÙÄfËœÉlÙd¶,™M,`¶xTŽl’-M.²IlrM dËâÙò*"[^Ed˻٢À$¶4ÔóU!³e [@lr›äb“4 ¶ÌÀòZæâ¼&¿ÁkÙ–äµ`ïÉkrxM,à5±€×$ç÷úÔ€¼&–Þ>œ¼–•Ú¸&—€Ø"-ó °eél’À–Ù”ú)yM.¯e%Ékbyë7M?›È–·±å‹Lb‹$61ÌO"²e[Êw %°e’ú~>ãÎkrðšZÆç%¯e¶À5ɸ&e™ß”¸ÙÖÒðÜŸŠ°&–r¾Ñ„µ,.a-?’„µ¼XM²«e šÜ ¨–Iæg©1A€Z¼jr @-ʬ… V“«Àjy+ š\T PMnTËlF;~‚ÕäÆ`µHBTË$DµLRÃg PcÑ~#ÈLlo{'¥À™}'Îlâ:UC[ó@ÌÌg×…x:„3{NC÷·e À™åÑu[^8SÃul¾u³éUïõ©˜M-½}ëçÈŽ¸"€6M1û§ 6µÜÏç9€ÚÔòtÖ%¶išú|êlÓ«ZÿÔئ–þÉ¥ÏoÆË:0ßY?u¸–ùy 7µ<õS°›Ü 즖úÓ-À›æòÞßò½ãSÀ›ZFùÖaÞÇ\1èMÒ€Þ$ ðM-Ïý©øM-åsM-Ÿ¾~Ó{·ñicœ^Õ˧ApšfŒO?ÂeG¸LA†;,ýlc2œ¦)Ï7M½Îç@†SKkgqjé×ÙÆ„8M3Ú™Â1î°ÌOùÀq’ 8NÓ<ϧ 9µ”s|•ˆ3”×ì°¦gg0мñˆHpq( ®V‚« û Ipµò€ \]ßËæHçWß~ºAf¦ ¸º&~·ËeNpuv–WGñ¨Fpu\?œßlðìŽkÎoÕNEòB9¿Õõ`nˆi{ªëä.„à7Iáüf)Ô ²]çv¶e Ò¸ñ­Ù±ŽIzk÷£ô&—;½5›iCoÛý܆îªôÖVOyÔ2oáðfçOOìnÛÃõ*®µ5wwV»å›Ýì@Æn‘ýp›ä nËÇl³—å 6é| 6)/¨MZÔ&åµi>Nm͆p¤1j“Öµi.NmmªÓ²©ÍŽÌ‡c¨ÍŽ€…Ó¨­=¡»€ÚZiÜŒj³œïÃ-²•;Î!qjkÏ>v[œÚ …îl›g.NmÍüGŽ“I¤ŸƒÚ,KãÔfw*à8§6©¨M®µIë€Ú,|@;¨Mjj[-è?ë}TÈf7Æi@¶fÞ(DZ$ò€l;¶e·áß‘øÎÙäñÙäÑÙäªlöP®Ùä1Ù¤4@6yL@6y”@6½“#›¦qd“‡ dS‹#›Ô2›–ÐMïäÈ&  xMÞvðš4xÍŠ÷5ðšfë¼&Í^S‹óšT ¼&}oóš4 xMïí¼&½¼&w¯–ùyà5élà5¹;xÍ®â"e~ê^“®µyMºxÍ,t¨t^SKÇ - ^Ó:8¯É{ ^“.^“ç ^“6¯± ÖäÖÖ¤krcÀZL•Öä# X“ŽXÓ;‹)¶¸O/¬¥Åa-a-«HXËGXË:Örp!¬ÅEVÓ[·vV¬¦7wVÓ4ý3¦:«e!«É­çgH%ªIa€j9ôÕbJ¨fßâÉ‚Aµð Ý?c&Ä8? !'±¾£iNKº<œÄBH82áp›*û±!<œdzœ8›d}±= žM2P%Î&™ g“Xh'1œM2;Ñg“LÒG“¬{ÁµrM2'O…„w!®]Hqi€*$¥81øRâu¤¸0PŠ»î'†q\).ÿ¾¥¸ü )΂©8‰AŠK¤¸(%¥¸ÌR\¦€—y@г'„âÂàG“DëSŠË¿CŠK¤81øªa ÅE9)Å¥R\^). â®BF„—yŒGkJ).s€GCJq¼&¥8I)Ž÷M)N®‚'Hqj™GùSŠ“{m)NR@Š“\ ÅIHq’R\¦¡§–ñ©¥8I)NÒ@ŠËSŠË–â$HqbgñrŽÃ&ãQ¦'÷†'Hq’3¤¸, ¥¸¼—KqòR\ÞÛ¥¸Ì•RœäгIøÉI)ŽŸ˜”âÄ)N,âøH)Nî)N,³×PŠËÒðl±àl~3ól’‰¨U)ÅIÎâ²Ä”â$M;_ÔâÔâç#HyúYoJqüpåÙ$r Î&I ¥¸¼Š‡“HHqy/JqY+JqÙ·(Åe(Å©ežùBŠ“Ò@Š ¤8µŒOO§—ix:I>=JqywžN"ip:I¶¥8ÉyKqúû;SŠËòQŠË– 'WAŠ“œqBIö7žP’žP’up).sá %r ¤¸¼7(ÉzSŠËÖ¢'WAŠ )‘| ÅI>âÄ20žf™÷9%’ *I ¥¸¼7¥¸Ì—'•dÛPŠ“4åV󬹤8¹¤8±¼ñN3ç~>MV’ÏRœ\ƒÃJòÞ<¬D-~X §)Åei(ÅeΔâ$ ¤8I)N,íKy\‰”Rœä ).[”Rœä;¿ï"+ÉgE).s¦—mJ).GJqrU9Ÿ +Éç@)N®'w‚'HqbÁq%Ù:<®D,ââ^âä÷}O!¤¸¸SHqrŽ+‰ö‹ãJâÞ!ÅÉUââYÅq%’¤8¹ Rœ”g´ó7Ž+‘\ ÅeJqyoJqy'W’ù𸒬+¡E‚ÍÜwû<– ®P?Â-£ÍÀÑc~~’0Á?oæy ¼2gü–ø.ÛÂpþCâÃ<ý~¥øÿ.ÍÃm‘ ~J>åv÷©#-’l̇?ÿÕñfîçÞ§ýsñfÆÿõx3¿Ñ#nûÏûŒ8óéZ»ß¼×ÑÙ~‰¼4šŒçuÄœA^’ y‘i—Ä“A^u†ye*æuĦA^QyiÜæ•©˜×yIL䥑g˜W¦b^ÿDä™Û±pÀÿ!BÏü‘×/ç‡èWŸ©_~³ßŸ®ŸtÚ3—?~f=ìfg/üÿfHü™¿ÿ‰ø3« ±ü㻥¥sïϘ/^(ú‹Ñp>òØÑ¡KlJÏ^µ —> Y–=D2þî2…Çp|ËR÷!⬩=žÍ€ ,›@#¸Ý²¼ˆ‡W¸c|øBP]-p£xÃCâÙ-Q_ ªë1fÇmTrßÓׂ¤4óö°x \2^CY;—‚×à°ëÐïàž¾d,pÛá¸ûV<Àý¶ãÉ,Í'Y϶´Z4TÜüõèx‹œ]ë»-’UáeÀˆe™çïá®7/ãqܶ;=_߸ÿ\¾T;›Žoèù²,¾TÃ5¤yÜÿfÍúý’çò¥ p1‹{àXXS¤Ùq3mù6wÁéìGÏåKAæ…Ó‘Ë ?œ]½,Ýql…uî‰CWže™îŠ#÷žî‹“å[óÃOÖlë‡ø-ó—p ÒÑ\÷Ž®;pnöú]š{5Þèvy_-m/äZ.Ï€ÅCQÚ·ùìÇ|-È*µÃ.Ë.ב³¯©e6¯Âð`ék’刵,÷u4ŸEqjGó=‡¥Ì{?åñ®4!§-‹¦82|Yj÷: L>×ÏcSÚ79ï˜íGi\à×|z÷:ÀjY|5HsÞW¥|.ð×ÞøÊõz|žâú¾Üº<·W¡ùaìf™Ÿ&.ÅÃTæƒ)µ~Þ†ÒÞÂZ‡?Imx £õ-^,J‡8†?¾`VÛý"ø#ª³xÓâäúû1O¸þ± ÿÐÅD¿÷øD´§…Ý"¿¥¸ ë>ÍW€ä#תG”Í7§ù Þû½>Ëæ+@šO÷¨²ùéi¾$Ÿž6¯óc¾,xÙ2ïŽüܾÇf íøZ½÷ô*Ä×ó}|Hͽ¥² LS}HÍJ½Õ‡Ôü½Í‡T¹—/I£¿ýác@Å_W÷5çq6ÍëÚ¾ôÄ~ùšÕ]Û·1ËIÀwzïþTvÔªS%Ÿâor|zÅÊ(k&èCªd㾬R…þžMÜáÍ*¸³f5;üYóév8´Z¬k¿j\R£Rƒ.­¾ü#Ù ø´fñFyóíðh•»øÚtˆñqk]–·}šwÀ±UnÏVµ –ŸùÀ·5ÓLWD¥­¦K¢rÕ¼Ç1%˜.Šj Wö­Ó\^‡é¨^UûO>.ji\Ú×|\=,ýÓÀÓåQyæ|ÎIK¹Ìß5ï½~÷o —H5k¤šÆEÒ,M¹\%Õ«\&Í'\.×Isê¸,ó|U×HØÏçP®^ÙS˜óN3”õÛÇS~Êåb©ÏNP*ú*·‹¥ùy\¼…QàÛÅR)Ì2;~¹]+Íïù²øxšå½]+ÍÏD¹ßª±r»VšŸ„eññ4^¨r»Všär»V*^³_/ÃÃ,‹¨yo ŒyÇ‹XJ¥0kò!ߢõÓ‡Ó˜Þ—§Â»<óqT-ïÅYcX|‹FŒŸ.9ògõÐ’¾yl„Îó'Á{y „)hïߢ#,I6¿ÁÞQPÿ™Âiï°@øÏ«œöN‹¿€Y§½(®£Þ‘ yX&h!+ì wXz=ûÇ×2¾¥G@’,«ƒÞaA@µ¸Ì˜Å­üQ\ç¼üYõou| ^‰„ Þò)wE µx$± „ÐyÒ) OÓ8ä—³nyZ7ƒ¼ãw¹>/eC(±T„ Ä"A%ðägÿ–¬7íÐmËÉv§oZ4ÁÝñû~>mïpwXžþ)ºÃÝa©–ÞÉ.¶®E€„?ûó)÷ M_,ãlŒŠ~ZèN‹•Y[hzjAø±-Õ2?ÝÆ‰Nëß#zºÿ¤?+~JwV±ÀŸU,phUËø”~ ôˆXàÔšW „‘4pkKùü†_kç Æà¹Óâ#¥XzDîÀ{bßw ôžX{/-Á÷²„Ñ÷Ôr¶ÍDü=±@Ë bð©¥Úx" _ÖsBË âðuО;òA$>©Õü¼{›çÎߟ÷µLÖwGd>Ióž%¾™OR 2Ÿ¤Ad>± 2_Zœè¤Ÿ€èŽ4÷ûiãç)ç—~CÝ‘qùÄRÛ§Ÿ<ˆÌ'–÷úô“‘ù¤4ýDÿDÔšPôpR—*zëɻܣ E/¢$SÐ[_ÌÈ)è=“kðTôÖ[‡•|*zë+•ú[\Z¦¢·Þp,ÂSÑ[ï*Vb©è­÷‡ËPÑ[oëò¡è­þè‘>¡è•;¸Š^1çI ’+z’ ½õ¾°4PôVÿüÑÏ×+Öë\*z«ã»°Šž\䂞ÍJÒ=)/=¹¨ïÂM„Τž§™¸ž—•¤žg–N…ox¸½‡zÞzY°•zÞêä@rêy–¦õ†W!ïUß3×óô×óÌÛøé° ¯CZ\ÏS‹ëyjq=Okåzž¥À+×ó¤<Ðó¤Äô . ؃¶™æ\Гւ 'µ‚ §W¹ §W¹ 'u€ §%vA¯<ˆÈ‚ž•\ézžTzžgëyÇïî)ò×ó¤i çÉ­¡çå­!çI[AÎÓl\ÎÓ4.çIO‚œ'õ†œ'ÏeËyÒzó²0ó¤Nó¤0óä±@Γ‡9O-¯s^årž´ ô<©&ô<½ª×3…ëyZ>×ó¤šÐó$èyjq=O®‚ §i\г/Ç ìrEOÚkKzÒäôôšÖ>僤§wêxãaBÓÓœ]ÔS‹ëzù᢮'i ëi×õäYm]O¯q]Oj ]Ïr¹ ¾¹®—ßYêzk.¿Zêzù§®§×õ´|®ëI B×Ó»O¼‹,\Ø“{Cسç¥Å]eâÃOaOJa¯Ü~lGèzRMèzz+×õôV/Ö¼•ëzZàŽ5o>úQIèzb®Ce=+ äbÈzr#ÈzR`ÈzzUÁÕ„®'·jX£¼õô¢}FM¶d=k‡ûõ¬xðqÞ¬‹7Çù êI¨zjy0°F ëåœÃe½ru~ ìIñ ìÉ­ÆÕhN{Rk{j_Æ…=-Œ {b°'½ž䳅=Mñ`\†€°'%†°§¹¸°'MaOKó>Ÿ&†°—]OÚºž^4¶±Ùu=xªrà¶Lå@éHÔõ4×õÔ⺞^庞Z\×ËjR×Óò¸®·þò£@és]Oó;—úÑõ²[SØ „=)1„½ÃâïaÌœ)ì壢°—­NeOóqeO-®ì©å­g.ýf7)P]Ù“zBÙÓÒ¸²'ù@Ù“Ö‚²'meOò¸§ù<Hy.îÉ£ƒ¸'âžÉ¥7ú­9®ÿpð‹¤~þœþ-¹/ã<‘ûòønrŸÄ÷Ù̸/ƒ›‘û26¹O"OÌJpCMÆ@á©æ„>ÉÐQú4 ‚ ˆ¥FÐ-CŸ¤ôÝ•Gú$g@_¶ÖíqPXk _DÝ äÓ\ùìŸFÄñí…‰|š HyB0Dkù,Ÿçðá”4`>I³™ÏÊw̧)œù¤€ù¤`>MS„!-­²7丌ЧwïˆÂÀƒ4}Ò:ú´–Œ]¹¿) /<ˆÀÀ3‡È{öh¤µò²‹ÓR+Ÿ³uÞ“vïIYÁ{jéõhð^†.!ïÉK Þc{R8Àž\Ø‹Kü$zH/»s­Ÿñò. ’i^D`ˆÇUÿ$š  §W9èEÙfù´>(/ƒò¤§€ò$ÛMywåI3¤¼¬acô“¼¤"C$að“¼Ï‹ QÅÆà'ÑÀxzo?É[MD`ˆoCcüÞ|#žÜˆ'7â1.ZžÜ„'ï8/Gj"ž¦iÏ@U>­6OËÇð'yóÑÏkfŒ¢xåAx9®ñ¤a€x’Og”¸7OÚˆ—“"žÞ§fÅÁxz÷÷ü„ƒñôÞô'Fdgóñ¤xƒ!P¢â`<)Þ`”(OŠ3ÊùÅãi AÉæ ùïÓ`”xt€¼ˆÔAÆÓ$ˆú'•BØ¿,OÒ€ñË8º#Oª0%î ÆÓ4ŒƒÕãiBÉ|0 /ÂäeøB^–Ù!ïø—™“—õ&äeùyY>BžæÌx€,1!OÓ0$`æÌ €™³CžZ<,`^3æù¶òâ{CÆ“$7cFaÀxš†±£ 7c²§“ñ¤¹nƌތ ˜9¿ÇðCÆÓ;16`TûflÀ´06`”ŒwX"¨ê Ƴ­Ö i¾Ññ¤¼Où5"äé/!OZâatÀ¨ÃÃð€h‹ß£`‡%j»ð¢%×µš\d\gÃ×{hzv`ä$ Ýk=g»·Å¦2°Ý» ÞÔW³Û(rHzv:X?Ðî-€ÐÑ®_éêhׯ7w´ë׈"ÚÙYD#§;hXNwý¦£]ÒÇÒÑ®?<÷‘hןp Úõ'‰ËÑ®Ûú`;;bã=Ø®—9;ÛõÒ~@)4´³óË:ÒÑN3q´ë•q4Èv}õ¸IÚÛƒ’¥iÐÇœíì$´çØ¡'‹Ó¡è¥HE/–÷]Ñ Õ%½LA/u zÖÂÛ™ôâ*z™1ô¼”XBÏKõŽz^ªlÔó2Mêy`°çÌVä2Ôò²Í)æå3ļÌb^´ ļÈ%ļ(_ˆy‘Kˆy¡$‡˜'ù@Ì“;AÌ Gó¢Ä!æEÍCÌ“4½~ë0>¹PÌË:PÌ Å¼x2!æ©ež£~ˆyü̆–&´<¹´¼l@jy’æ­g jyq#Hyr#HyÙ”ò2JyYƒò¢…)åe>”ò$M9ÅHjyr§Ú>壖—•¤–—OŠZž¤–wÇiS ±“›.²¨Çæ…¥)ÛeüU÷ؼó¨¸lÚ9´¸Ë¦ýÌ—Íõµæn8¸l®QjR¨s—ÍõÒ?ß©ÿ(\6× (Ô9ß=ûĺK¼³l($"ÂÊö_ŸáÝcøÉñÎ,tÏÜc‘öP$y€ïlFÌ£S¼ïÊEŽwköÈ#c€wf)ÈÆñNÓ8ÞiÇ;ɸïÂÕ`DÇ;³ÀGx—â*ËãLïòÖĻ̙x·&®tƒÞéUŽwšs}ÏkœïÌGð]V’|§iœïÔâ|§9;à–áuˆÒð$ž¦qÀËNì„'µáÉ@xv/56'<½Ê ï±É·îÅ“~CÂÓœðòU á=§t'·Þ-ž ëÉÆ;û –sº“:ƒîì*nŽwÒRÀ;ÍÖñNJ ¼Ó|癩À;{•qøðN꼓>±ñ.?ä»|ýÉwö…ÅÎ ð]~jÈwû+ Èr¾“Òð4^~GxRbžæã€'m±OêÀÓ|ðòsI‹O Îwù="ßIÛ€ï¤%Àwš¦Þ^:œg¾SKÃ[˜wr¾3Ë}ðÏñ.¾X¤;»3–›@w’/èî° O™ àNn½áNšp'Í ¸ËÂí4‡»wÒ€;Mãp'½t'=t'-º“»oº“;î4Å5ª ºÓ« Ôè‹ ;½ªNörîlo€q¼Ë6ÝiÆ}ã‘ÖÅá.›l§O³Ïí¤5Ávrc°dSð"‡ÁÉNžÈN-ˆ$˜}q“¼' ;i ZíËø< ´ ÐNº'Ðî° ÖA_‘ç¶ÓÎvRÀÔp§‡;µŒ‹Ó2–ØáNkåp'÷ÜIy(â¥O͆;ù¾î4—‚ñ4J¸Ó|îäYî¤Oîô^ýúôrÀ¦ß!p·FN8I8Üå½ wÙ‹ wYb¦q¸Ëzîò î²îô*ìØ« -;öÄ‚{bÙ;öô·ïØ‹31bÇ^Z¸c/¯âŽ=Iƒ{bÁŽ=±`Çžäƒ{’;öÄ‚{byÏsÇžZÆ·ر'ìØËÒpÇ^¦áŽ=±`ÇžX°cO,{Ç^eôÃØ±')°cOÒ`Çž¤ÁŽ=µøŽ=¹ ;öhùqyÒmÓ¢¾Ç!º³<ÿž‡¢Û}(ª¿ã¸)¾“ðÜ\“#ä ÏÍ5-<Ïà´É08Ž›ZS8n®w—[øà¸¹¾ZÜÂÇÍ5D=ÜÂç^'ë ~!ÍvÜí³aO-ðÝ\}fPïs¯“ÁÏÃwsıÚôÝ”4ðÝ\÷æN:ønš<êønNž¾›ó‰ðÝÌ‹¶ëæäíáº9^$\7ד,fšðÝ\ßózè{÷˜¡—Áws}.ž¼âN'jq§Õ»-ÛysÍt¨ Âysöÿ©Á]N¤,pÝ”\áº)iàº)w‚ëæäñçặ¢çf^DÏÍL²=7³íèº9zì̓ëæðàPé¹Ý,<7Gãò*=7£;„ç¦\ÏÍÕûé¹Ý*<7£ë…çfÇ7óÖtÜŒ7%7×—ò=6ëI-鸹º%A8nÆ›Ž›‹ÞÎÃ75 7³štÜ”«à¸¹^àJGÍËÝôÛÌK躹’`£ ]7Çç]Â{SÒÀ{3^÷ðÞÌ[Ó{3 LïMIïMÉÞ›ùìÜ{3>Xá½¹¾[<‚Þ›ë1€°é½iýJ8ùm ÿMë=ôètw“̆.œ’.œ’ñöá\_ØqÈ{ùÍ ÎõéÅô>œë›tskž¿…’|8ÅÎ7M g áÆG¸qŠnœïq>‹øË‡§¤€ç =Nœ’)¼8×”9|6Ý‹3}ËéÅ)xq¾õsçýÆ;ôâ”J‹óUÎ7Ο¡'ÿ μ=8óôàŒ=áÁÉLà¾ùÆÙGtß̧JÿM^çÍ%á»™†íº)å‚ëf>`ºnfºnfAèº)WÁuS®‚ëfì¼×MI×Í(=7cKDxnf’í¸™Ý„Ž›ï眖ãÎpÜ|ÃI†ž›ë “Å๙KÏÍÌ™ž›YoznFñÜqseRNÇMÉŽ›6tÖน CÇM¹ Ž›RôÜÌŠú²³»çf¾hôÜ|âËY`¸mæëL·ÍhzmÊ]൹>C¼^›yœ6³½é´™G§Íhr8mFŠpÚ|dðØä]ÂaS ólýð׌V Íèˆá¯õ Í7U¿f¼Já¯]þš1Ô„¿f|ÿÃ_3-tØŒ/w8lrð Í$Â_S²ÁT8/‚»f–†îš1Ž„»f| ᮹Rð€N¸kfëÑ]3l¸kæc¤»f<zkæ­é­/ExkæEpÖÌöugM¹ΚÑÃY3»5%8kæÓ¦³¦Xà¬É–Ðð›c3øDC4º ÏK†çùéE σÿLxž_ç ‹#7È$^§®Û8ó ‹äóáOÍg‡—•\ü·æa–ÈaÿëÛåGjJ[Ñ"yÀÆ\øSó9‹>(ÍGžƒ<–y¸ ›wŽqÆ ²?vÆæ;~»%c;xýùyl¡•ÀŽþkùýÚïEú„ú­U†<“Ÿµ/B7†ª¿þ†ŸÐ_~çK˜I~úQø?dyÿBýý·òøû?:huå½Jk°[?>¶éì-šÚ™Òëeõ5´2›¯Ò¶Ø1_[ê4©ø=¸·Õ]zË„B¨¹ewÂé\;XoŒŸ–ñ{ŠÚ³Ó²#I½| ªUNêu—s£B½| *÷D,ˆ_l1¨—¯Aõ†õzU{y¯â+>õò(cßp²,›{Gãíõz7ú}øbc½úFß±èm ÛqùW>DÕ‚4ío½žê5šŒMõ¾6úZóº|Rï{£ï¼°AlöìÙ–/8ÕEÃö»a«Þ¾e§Y3Û²ù×ÖQ}¥úž¹n?£À¶{X>\e©·/@Ù¿#çw#°lç±zû”³‡g²–Ìra’]m ÖBÞìE˲1ØîîHSŸËò5Ì÷|Ÿ{s°uG§j’Í(V ùZR5YÇê`ˬž¯¹SØìgÚâñ(ͧùŒb5ãMËÜå[MŒÖyìˆùÓb+Pçm¾`tÕ`XçjH±W Žk0‡27·m(—OÎ ð`±S1,Æ›ªÛ)ÎÒ¬šÖ5‘]UFEîZ×a?†ÕŠ>1­¥ÞÞÄ/6®÷‘…¨ÖyùC@¤°eèÞE&VÈk»š?ƒŠuõÚö*Ô0Àu€U¾ëxÚm/C­/ÖŠk3_3ïæ ùîe(-p«sWÁ\p§½uÜé­^…nýaÁcj²ÁŠÃ(jµþymÖOÞë9ºÕ{M à]ßûÝUÈÖ{Ÿ}_ŒèV_‹>gi«ùîÕ(}š¯ !Gƒ¾{9JŸ¯M¼_}Ç;²w¾ýÝÈnóîå¨ýè¨Ò¼ýEÍM Ñóº=½K¿¿or·Áàø¬ôgìâ[(¿m%»ý™¸vTm Ø{”®·ûó{ø;Uîoû”¿÷âåw©ïµ¨Ý¼®²HIVš'Òìµ(-±‚ÏqÕØkQZžqÑÂc¯Fí»£RÎÕ_Âü‚ÚýKsÁ  Žæcêo˜:Þ=¤Zj&£ûˆš)úPWg„º_‡Çú4£ÑpqÖÆ0×ûëtqvúf,‹¨ùiœ÷:SXsQM˜°øˆºÊ„qeú’Ô´þ‹«³RšÙ0¢F‰§Ë³Z>_’’±fº<;žxàÓåY-˳2O“gm•Ï»t».Œ¨Ó˜v¹öM+l½ÛåÙ1éäÝn×g­Í‘­ë³zk_“Ú=¹>›Mc*l×±,{aÙ:¡Ï–׸Ò~`x÷)i{\Ÿ;›9åX×êúì2 O0pIi^ºhñÇõÙ9éÝŸ›Å?åíqVïy}@ad sws¾ íqVž÷ãmÌtÛãúl¾­¸>+h¥0æ³_õ kåÁ€zóù—²uÑI˲˜çú¶ùé…·´cÄ;¹@»PÊU+¯¿…“¾ÀË29éòEÓV|~<&w«·20¢r€oe>g‰}ùÀ¶ãéVWh¥Û`Ñ!ZâGJî³1ïXª\Æ%ö­ïvVûìSO¨{-E §.Ǿwì¡èß‚úÞa#),¾9<*Ô÷Úû¥jPŸ ¬å >su¸aqêK}˜Ôw?#®rêKÉàg„Ü‘¦âxEÜÎ'cG’üÊ ɯt¶É/Cm’ü¶ÀK‹‡¬1B‚üL˜…ä÷–{A~ëcÊ»ýZ£WŽ£ß[cnô3å²ýÚŒ¡è÷ö¨'ÐÏ ùÁýÍà¾wbß±oM¶8·ö™‰æuìëã¾ö½ƒG :ö­&ç5À¾õÞØ§<ìËöÀ¾¾Ý®€Ž}Ý"’ 7öuóª};öÉ|©o]ÄNîÔ7;õu‹±Evt¿ƒnë.°lêë¶ínÀ¾>,{€Öƾ>BŒúŽ‹6õ­‹N”Ô7 `ÙÔ×ÍYkÒ²)›La°©o¬Bñœúº¹|ñNÝ©Âó @}몤R÷;Ð*L¥ÖÜ ½È©¯Û ÿÒ2¼JÅTØ·ÊB Ü×MÈÅÍûd0÷iqŒûº}VÑæÎ}ëšÊÅç¾ÝžXqî[Ï…!¸O§}Î}ë*ž±îëæV‡£ƒ_·èg¤ÅîÃÔê,X rð[WÑà·®ºI8~¥Â]>L­O"°ÙÁ/'à>mç¾nãIA÷BY²s_·I÷ÄUî†`ƒ]û´) üºEgb8ø­ÇÇÒÁoÜÁoO¾Èœî‡sY°Ÿô$g¿ý41´8ûm`(Ê~{ʆAËÙoáì·2¦Ýf?äÁ~2ûéSqöÛKrèÎ~»)08ûéBž³ßJ¨Ûà×͉²ÐÜ Á&Ö>Û ð‹yÀO cà×m&€•¿œÊ‚ûºñ ¾jà¾l^p_NK ~ÂZ ?ÉàgÃ,¿\à ð#P:÷éâ ¸/ÖMƒû:æ…Á}1Ïî˵KrŸÐ¸/ÊØÏÚ±O—}òÔûâ¡ûÌíif÷U)¨à@äˉ¤#߯r‘KâI|ƒ¬à›ÜàÀ—Su>Y]ð外ÄgÓ%€$ˆ/iÉOVf’øø­ñ%8òɃ äK<"ò%ýù²V|È@¾¨Ojȵ"óMnÈóåÚ\ _<Ø`¾$qg¾ UÀDæ Úæ 'óåÍúòA9ô)úÌùúV¥&îMè èã‚h@_>*BŸä 苵— ¾ÉbA}Y+P_¦ õÅÚ†SŸ>pP_²8¡/º5™/ô0Ÿ‚,™/ëDæË|ûgÈw`ê|Î ù‚ùƒø8Nâmþ™¨B}kúu(Ù¯-V8·úlèßP_¿»ľúÒ bßscµ%´>[âtÃϤ¾8@ƒÌgs"L}À|‚7„¾Vipâk=Ñ̉Ï\.'ÐÌ‰Ïæ)XmÛÄ·ø‰@ä³if#@¾nÝÜèÈgî“ó@¾5ëâd È×KL)öådÈ' 䳄(G>s}| ùlÜÄ$k#_B ˆO&à ¾QbµÄ's_Ÿ…¦çÄ'z% o¬¤˜½Sì{® G§¾1 údÒ è³Ž†é§k}7} }cµ'0Ð'qj}9¥ôÉìƒZ_Nª}9!óY6XwôMóTV©o=î÷€>™6úLNU¥OçO`>kÿ>’ùdVè³i8 Ð'ÓJ}ë!ÌúdbC©/'¤.õ™“ ›ÛNæ‹ÉOTd"_®‚;ó¥> æËµ¶`¾l+2_ÎÍ}ö ‚Mè‹ñ0 /çxÔúbe—Ð'šÅ>QÊîX›ÄU}©*ú²ÍCìKЗõ¤Ø'i}±àb_–˜Ð—³Rª}©ÂúbÂj_ @}:ç§Ú— ;¡/&m¡ö‰ÀµoMœ:X j_ŠFTûD#„Ú—R8Õ>)ÏOä¾l-Ê}æwJqr_´å¾õB>€((~1Û É/ÅÛü „’ŸäCÉïÂaV)ù…Øè’_Ö‰’_j®Ä¾|R!ù¥ÜÉ/Û’_ö b_öÉü¢Cò‹Ö Éïå'%¿$'H~¡$SòËö£ä—NŽ~;,É9ûäf¿ãN›ý´EþŽ4þ´w9ü‰NøË4øSmÖáOs‡¿¤+°Ÿö?g?mOg?Õµþ´–„¿pþT`vøÛ"jSÍOÅY‡¿¸èO* ÜOªæ€Œ;ÑH6¥%Â-7 ”—>0TßM€Ò4 @i> 4M`8g€åႵ|A€KN€ÒEA€G>Žhò^N€GšM€×SA€âìÔZ9åÒx\4áDÃÅý$@~{A€â{ÔÇà(Î"›¥}šØ P¾c ÀãN ~4ì}A€Q)À#ãq^À#›éCkáÔ¨ml(Ÿb |¢BöË'ç¨wrÜŸ¤ùÖÎ^‚׃(¥yáHÓBÀ{áHoŒ3 6 e¿ì9Æ€ÇædÂ!P»!k{ÿ(¦Pª}›Óü*§l!÷M„ î[]†l¸¹ÏÆ%¤€“gl–#øÅ>Ó¿Ê8~•±^ÂÇ3¼>ƒünžó@ô[c å°_mñÕûµ‡ÑIÈ~"žmök6HÒ­sÏÛ³o°ß{— =g?›:a<ûåyÚd¿·Ò3 è'*Ðï]íGnrôëw÷KG¿w&Ç9úÙœ‚xøìóµÁÍD?Û‘‡‘è' ô[XÌA è×+•íûÒè×{ðÐÏÒ€Ú(øõXþ§à÷Ä öÛÓ0ÚµE¸˜û„à=ìgýó>ü<%_ ~5Á~æ’ÛOÁ/%+ ~5Üæ6íÀwÅoµÍs*~‰Î€?sF&üÖŒŒ~”ü@³Tû’o)÷­^DçLÈ}£‡,¹ïeÄæ ¿Õw ,SîW8unòK­,ä¾ñƒ˜w}¤2ª}“ýŠÜw»ø ê“¢‘úžX!õ¥Eê[ßߤƒÒî1}ÉÚŽ}æw€À¾'´Þú¼pd¾Â ÛÁ|{{Ý6ù6kmˆïŽ‹2_êK$>‘Ñ ó嚉ï©ÁO›øRM"ñY %¾Cz£Ìò+e>Û#}Ê|)QæËÕ_áQô*óÍ“øDª„Ì—Þä.ó­Oì£Ä§÷&ñeû…Ή:ßÅ€D¡ó‰ªo=nè:Ôù$ t¾›çÿCç[Ÿ>¼lÔùâySæË¥Ìî=!óeµ)ó=ب2ßú–’¹ óåúe¾ì}”ùìuVÞ[iÞ ¹vJ­”ùDïI.ùR~¥Ì—/!e¾Ü @ÞËö¤Ò·Ú$N¥/_Tç=½©ô­5ý*·Ò—o•¾ì”ú²OPê ªÐúBê§Ô'Ù@êËnM­ï}~(í¾˜úr=Ž>ž¹+Áµ¾•‚ ­/dj}ù®RëKÉ›Z_‹1˜Z_ʺû* Ïó Š}é"@±/·‚PìË/|<©¥‡ÚWyÞF~•GÑ„gìóÁ/êŠ_ô¶ü¢!ùñ³.ž¶=G¿x9Bñ«<¸%¿X.Ïtפâ]6¿x{ÃÉ3"©ø­~‰Æ¡âŸŽPü$(~Ñi7ïΣPüÒ1Š_|(Bñc·'Ïls*~r#(~ÑžáäÉ—,¿¼¿¸õ¾ÈÅå>É>žYgÊ}ñ½ ¹/‹K¹/ïóbPåW-Ô¾øj„Úkà¡öÅw-Ô¾¬Õ¾¸•‹}1„†Ø—™PìË:QìËL öe'¢Ú'ÙÀÃ3ËKµïi¡+BíËÆ¢Ü'i ÷I‘çáDr_|ÔBïË\ˆz|+²Pêz—5Ÿâ]§»dèzy@ùξ›ä¹}^5½åÈwõ%±ïÊ*òÙÎo},BÄ&¾õ¦>è€÷ÚãR9à½7ÕðÝ(±vÈ=|6µ;÷ðõø6scõ`ß«y±/y€ws}›öO¸/çòÜÇ'9CÚ³iÿÁw‚±ï JH{vþ͹‘/§.íMFwˆ|µ‡—(´=¹6ò¥ÐDmoU/'ZÔödç!ºqN¬¸‘ïúztŠ'™ˆ{˜Ó»¸—NWÜÈ—ÓŠ{9½¥¸—“Š{¹!Ľ˜QÜË–ê^ns¤º—¢›«{ù\¨îPª{!SÞK?,Ê{áµDu/<BÝKÙê^®â‡ºó2žèrP÷ræ‚|ܱJq/,îãK¹%ĽpÍ"ä¥çÕ½Ø0ûø®‹ž˜À¼p¡â.¾”*BÜ %RžHwåÜÃ|)òR3Ä>¾TMBÛ‹ç>¾¬6I/*{©Ç„²ÇßTöRf¤²—ꕽLe/ Êžh}ãã;Ia/u2 {Ñ!ì…`Â{…½”)ì…ÌÂ^ȇäIY/6^‡¬jœNÅ;i|!•ðæxk,ÁæD¼Gñ"46ÏzÞqLK«q‚ouš8þÅ ¯×çã»iC1w:áéy) ¼lĶâÙŽ-îâˆ'»€xcM †Hx9ùâÙ@R£Zd­•GµXRܨûH”ãOVRñbû?øN_ïÆµZ†D…sZr±|'ǧìƒZò6Îw+—yPKzØùv˜!¯ÂA-räÊëÃÐJ †ßÙWRøîÙ“Ÿmp¼Ó$Žw–„¢¤ã}—ÕwÓÚ£x§Ç»kÎ~gmFt¼»¯Ð¶€wöug>Žwû{OEÏ:\Ï{q¼»×Wü•{6$ÔC¿;,~Ôázû0áÞÝvÄ1à'? G¾»:ºïö™`,Ç»ûa´>âZïìÁóÇ»»0T¤ã•M‡Oç»»ð{jx›|gWñÔœ,W9ßETqÊxµ›|—Q±)ãe|pžZpTpDÅvÀ‹˜öTñ¬sc |·GaËâG–féœï¤’òÔâ|'•„’'ÍÀ³¦*çJž®‰Ù/ƒÑ;àɃàÙcÌh¡ä©ç?3µ=?¸TòÁ‘Áå:jé6EAñphpVBžZœï²µ ãYÛˆç¦^OSÜg˜yÊxòT@w·Ž2^E'Ý©§GÐvÒ].äÝ&¹‚ÛNñðã!o]ã?íì{]ÏNÈæ‘0848NꥊgÙÂE½óÐ`LÏOzÝŠIÝÌE<µàÔà&ã"žf‹cƒãœ]Šxy¤7E<Í÷űß<#š*Þaéß* û{ ã‰2^žJKOÓì@qÂ2e¼<ý–2^žúKOê9H£ŽjÑœI#NÍ¥Œ§9#’†¤A$8g™2^žfë2^Þ›2^¦ ŒwXpx(^ñòL\Êxy@/e<½*Ï~•îäÜ\×ñì÷¥tw¤ÀùÁ’ biˆeÆñû]éNN3¦Ž§ÄÒè!EBÇ˳•©ãåQÊÔñ4ŸŠßÇÆ=1 ”†|H•óøà´ ”FœØLï°ø˜jß7À“ËxjA, ±¸ŽwXÆùÛ…¼ U@!OÓ š†¤A4ž"¢iD¨*yÒ‚Jž¦A48ƒƒJžX äÉUÅÃi\¡ƒ¹”§× œFDž ”wXN#-®åiÎ §qSt)O“0šÕJyjùFÓp)OS0œF¤¨ §‘†Ó¨yXË /”ø·åˆãœÎÁˆF??§s}âàÝvá´º­{6wæ±/€¶pÆ«'NîD¨˜š8¤00€+…{è[ai€¥Ä  \ÿòÓ ,½>œ6Sħç[ñ–bžßÓ{:qÞ1[òS[j@68%Nm©áŠÄS[žÜyÏö¤"œÚÒ ØGìo8Ùű-“3µ ½†ã5>ÑqlˈÃÚâØ–úñâ´­ ÜŒGÎ+”P ­~”ƒE³¥#çÏœç¶Øü÷ã¼CÀ±-±‚M?ÎÜJGNÝÓ玜O¬óØ–Ü=JgÎ;v ñØ–Ü.Êc[ò¼9:sʦ>8sð]îfú²eï(m±sÑq3 Å0£ç¦»ˆ‰C[Rîšp–;€I5¾ã|Ú²ÊÐÎC[rq (¾´›åH_0àX½‰Üè h3WH]`@;[ŒûîàÍ;åÉ€zD¾;¾€À1“ZáÍ)G½8Êñ?ôæ‰l‹|æÚòÄW (ÞÉÀ@qp®§^˜ðæÌdáÍéð®œ1w§Â'.¡/ÜHé•é h‡¥Q¡ð¥ä¾œ-\MéË«‹TøÒßΜYm0 ¸`SáõŽÎœéð gÎt u…ïfؾpæ”k ð¥ +¾ØGF/œÊ—3èË)~šôå GW` ±Uh~ƒâ ˜®œé$ꮜá ®œé´LWN[Ð9\9Åqž_*›áËßwúræ™QôåÌŠÓ™3ËGgN[—>÷î‰XwÉùÖ½{‡Ë%œ9s —Μé-BgÎt|¥À—B&9ÓY7œ9+/œ9Óç…Μù6Й3_ÍŸœÜ= |9Åß¾œâ, _Nñ÷¤/gºXBâ ®œr|9÷¾œâþ _Îv±¼?qå¿Ýµ~#°Ïø`ýò«OÏo}ž~ù­Žû«OÖo÷Ü_çõ;OæÊëyسøÏöPÖ ½ˆEBíkôÚä¿þm€Oÿëù›Í FùëûÛš³½jç¿ÇÿÇz?íøÔñþõ—¿ýg§þ>Ñ\>ÒÐú&E‚¯ w9# •Œ4Tv¤¡÷*;@Ðû×ÿõ·g¨QB •3—÷såßówFª ª©þ‹–7šä뾚·¥"Üøj»5¥¨æ¤éàgaÑŸõ$ÖŒ× ÉÓÅ{-ƒ›l¹–E7F|ôºµù5€‡‹-R.jl¶ÂáópÓŸÖ0ßêš+øšƒ©0‹WšÖõY7‚Ö.êø¶¶»@½µŠŸÓæ³Í–?,”v·ÏŽ­œîÂ=æä»Ò´ÂÅ­çÞ+‰Ë2°ŒöÜÛ·§5#'¿jM*›}˜ì8OS¶?D³­û §¶éÂbÓìfŸ!øuÛ~„Íbä2ì¬Í²×o2IßîT+“ÊòÙ=oKÃs¶;Óø5 £?=«!_KcsW_ë]“õÕ´+Ÿ'qn[i&Où60_ úŠúF‘5Y¯Ö“g•=ç]ÙÄùe»}4‹Ê‹Ð—u/Ìl‹7WYS½5_–‰ŽTV£¼«-ÞťΊe} oKc¾Š^œnÓì¶—d=›±÷´½ &›e7[õ oÔö_–'Žk6çm¶³ÐûèlKlm·™Åaé¶xÓl­$]6},ˈ½Ô6К×5]_߇•¦‡çø‡Wš—ùøìJÚÂÆ•ji,v]‚kÔbÉ­½¬›‘xí±í¬GûLÍyA›5]³=<ƒNŽ?vkž¹_W+2wWÙD{߉2É~[³)šoGZ7jäÅ5]·×5«Ù\Ämûü/Ì;ýuµÍ>÷^/‚½®ïÃÃ)l ¬Ií(uŸ{›ÿ9J<·+ÊNãk'¯­¬íL¯Í=¦6Žõ{c³žv×¹Ó¬åYsצµ°¿M}ÂïÙ‚uxÙ'Ch×y].^nãz{Ùo¬”x}¨îWùc¿°YÍ×¼ò_íoݽ=Z…~_þÂf;ŽÃÒ˜wÛ®B7¯Î¡%î¥ø½¢×Ëߨ(`¯Ãߨ´´æolZÞâolt ;tâõnëw²ouÓ÷¡¶_ؼdúLÍ,¾LcŽ…ß7Zú~aóûf‡a–[_;aÂ_XÏVàÏ0" h«ÊþÂÆÝ×P´_X;˜÷Àñ^þÂF“ÚF°ýÂF³#Ù÷ k±ëüÝò`~[÷ö6,³û kN„»§Ø’R?ÞF;ìáÑJØ"âùÂÚš×­mjËûòÙ*Ó~c£¯Ow Ù_™1&žgš×Ø}>Šß¼ûk ƾX3ýýÖ4ÃÇX©Õô16Zð1Ncq¯g»¨Éç±¥“ýÆ.Ëþ^<æ»ëol¤)>ƾµûk³,>Æì‡|ìÄÓ=ÆÚA‚ÛÐöê¹^ ±™íëClT󹺱Hþõb£Ÿkbˆ‹±™ó}aˆJ­éÞØHó`Œ] xÁ‚16ªiÎaýLSmVì%tCÃÛ ¹>Ûñ§Ù¼>ÄF­îŽ!6ZÇT÷Cl4Îê:>Ä.Ë^Ž{Ö£ò!6ª x—{›Æ¼ßXö“çy0Äfš‚!6 øT ±«V¾¸ò¬ÔíLÓ0Ä®wy¿Õkº†!6s~1Äf™;†XŽFÍX÷›–‰!¶W–Cl´r¹|ˆâï76-±bÀ›¹Œ±i©c£V¥ÝxcÙ J›xcÙ¦åÅËnañOž®†õªôç¸ÓÀ»òßû‹§ú-q½*Þ×°Üa£mìl¨y´V}0ÂFjñÖNÞÅ©#lTªVaÓÐ0Âæ½_Œ°ié÷ç…5pØ/lsévÍÆ1ÂFÅëÄ«]a£À÷e¿¯ÌÆ(t ÿälyâ17üRKÁËF7¸8ÞÖVÛçmm Ãkæ½Î·u/j4-K÷á5rÅ:H\ò‡c ‘-:J›Jƒvv2 48lŒüÙhU‡­N¿$ ÖáÄ ÁjꨫÀ Ájâ¢/+«é>ÏV;×WvƒÕÜ\\"šøâsâ -º˜C"ÜÎ'Ž• Âëå…DxÛc_E"Ü~ñn·€· Ÿ“ˆÐœW}¬$¦s%ˆðÙÎ'„ÛÝÈ™Ñp ûV¡¹`¸BJ ´bú6ð±!Ôo ´ì°û@hù`Ç?€ð±ÉS€ð±¿ @ø”€2áv"rhÚ§Ñ™Dhe÷Y ‰ð±qÕÉ DA„¦]ÀWÊðq: ´Ú1–Õ­ž·ÇÁ>ZY“@{î0g|´2ÏøQmx¸;aVö1g¨­lccúhõìr šòÒ`O/å"ð 9±ÜÓ!( ïÁÊ*z쬞‹¹ñp¿à©lÄ*<ŒeT$ ’à=SºúHUÖ+Àc4öHõL.ï­k °hpw(O´04ÕÉ/ f Z[y×' Úióؽ”[³… ƒÖ' Z­W ƒr`Ð:…¿„A{+œ¦ƒb ZvXöPUÖûìD M üCA4g#`°Øú‹À d,¶ò»‡0Xn~# ƒñ‘mrá_c²`& šÁ{Q°<ØY@,ë[† Zp ’$¸¿ ¿=T™>èMN‹£ •4;)%tô>¢`>'¢`v?¢`v}¢ 9x9ÓÍ› L4µÒ×"H‚ù,I‚&`úHEÜáœ(A‚b ʽ@‚ù𑳳‘Ëú¦€½@‚Y`^D´V%Áü²‘å"`)Õ¿QÁl ‚`yÚƒ­t`Ep`&JqR%``Ü)0Ð, /` ‹(£NAñ¤HͲü"PàS0!²“ÚK×Þ@|[ãIÆ«¯K@ Û*Ð’ìž =?Ð^ø½ ßµ`@±€ã= Œ./"!0ËÌf½É€ÙâdÀ|NdÀ¼Š ïF0 \Ì.AÌ{‘% 0>ªÁ€Ô³E‰€bÆ×:°\pA”[KÁ$"`|xÅâýœhOa:‚ãã@`¶ 0ž&°”Ûå‚ À|¾D@{ŠhÃur\Å€Bo `|³gc"EÌ.J”$ãjÜ (ùÍÑw¯jn×_OÓ9°²žd@޽€a faH€ù¥ Úô}J€Öë|É‹h³ºêiÀ€y«Ê•&ÊE΀æàÜaÀÀz ´9 ð™Ø}hSL×öÿxø¡Pû®šp ¹ U›¹Ú¹èUÐÄ`ç†Pí™ìa‘ªàj¨ëP£CÌ+eÁœƒQŒ—/80Çmr ¹0ÁÅâ yp`Y#:° h/hÎÚ>µ$n÷í=È‘3ð,9Ð^©êÃxen¡N˜ÎöŽùL¬ë9»¿@Ð\¾!ëExÚ{é'Ö›j9°^±Qh„3æÀu½é8cho³C0°®!lÂ`µ“žý"` 9 {P Á•÷R eã>ø¤Àj.¾^` \åhIN]Ðîý¨.(…æEÄÀjŽûØâ–y{qŸƒX’˜mC Ìö#šÙÅs©ö€e÷„£68ОïàÎÛ=`Ù& ñK->bå&šdH´º`™•N˜@ÁÔÛ‚™ Q0+”|‰‚“B4QÐv!Àó(˜ý˜(hc¶¨ËêÐõdÁõ>ÀE,h;ya°¬ç! f=ƒmæé EÌ4dÁ푯(hÎh®ßó" `¼¯‚ÓU† Á(o`–…$˜Ù’'¥¯@ÁA5P0Ò ÎŽ…¦@Á¸W°`|r‚£„ƒi! Ƨ+h­0• dÓ f €‚QÉ@Áy}TÁ첂qU `t‰@Áè¢Á‚yY0ïEŒ: fÎdÁõ€‹ƒÓBÌ{‘ó^dA6h àJê¸(o Q0“GâQ0:q `4` `T*X03& ÚNç:Â`^EäŒn08¸60ÈWº¤Á°F#ŸÀA¶_â`'p0Š88^B$q0s&òYæEäÁÌ<(ð ­ÆûEäÁH<˜ò`Ü*x0-äÁ´ÓBÄ;”8˜IˆƒÑÈÁƒÑ€Áƒi!®ú^ŽžäÁx|ÁƒY-ò`4yж9î›Fqȃñ€£cæEB|j“ùáOäkŸ@˜D†B~§3aT<€Å ä·"y0^òàÁ(y0š8x˜ÀÁÌ–8È4Ï2h0š&h0ËBŒlHƒü¦'Féyi0Âç Ú`?ެì#AƒÑã«8=€8È©Sâ …8˜/\¶ñ˜þQ ¢@@#¶z `m”Ú/‚ÙOC/1 ÜÇç¸ÜGßøE@À}j,>FٙΠDÀ{r¬#Ú†è~  ¥ñ[m‡ôsàsq‚K´ý>>!"а|öv.@I´­Öà2àóBd.à¿çqÿl+¶+¡>D°Ð×Ôý>øO®¢h¾™Pý¨:K…XèàIðaü /¨±)¦,0¯¢hZ®ðQÄ­Á~’ %ÀÌ ùÖ`–`V€`\Dö³V8ÙÏZ“±d!ƽÉ~ñLB,…›©æE@?{Ôûƒ]ä³0žÉO.¢ø¦C´ñ‘gœî¡)WTB´ªœ`d ð{ìhÊüì€ØÓå+5쬿}JŽÉð¡I,ÔóÞÔ/ž}" ù;üä^?)ÀÏrÆF5€_Þ‹à—i~Ö:ïáš÷"ùÉU ?{VþùùÉE ?¹¹£Ÿ$úI.@¿è$¿l@’Ÿ\ò³gåK]$¿¼7É/2&øe6?û@9Ùü$ ÀO2øeï"ùå“!ù‰ÅÑO2ûeûe›“ý2 Ù/‡ì—ŸT²ŸíÄ,‡ h–qè€ûÌ WâÀ~–ó}x„JÎ`?¹ ì'÷ûɽÀ~bûåÀ@ö“{þÒBøË|’ð'Iþ$ àO’þ"Ú;Ù/ @?Éè—-Aô˾Dö“;ý,c_Æ"û…%Ø/rö‹|‚ývÀz'Æ'V\ö“4`¿1•d¿´8üÉQ󀿨gÀŸÜ ô'ù€þ$Ð_ZHÑ+‚þ²V¤?¹ ô=0èO®ý‰ô—µ ýe™ArèO’8ýeÍI’ô—iHYÒŸZ0À¦ô—­CúË’þ²VÄ?¹ ø'i€RBàŸ\üË~Jü ð/ëNüË4À¿ðÏ üËÇüãËô—Ù’þäÐ_^ú“;·y¾±A’ èOÒ€þ2cÀŸ\øË:þò椿Þƒþì*x\>`#§?Iú“lÿäNläò–Ó'.øo½ƒX ÿ™Ž¥à¿}Œ®K‘@ƒ‚r Z0ÄrbxÏ`9 YÐõ¡ƒ,KÜ¡|œÜ€f)ð¹Há@Ëþ©@±@Ì;Q´½`¾ßó×ñ‰RøÛ*”ú&×éƒú&ÝäH}*©oãŠ8€¦¤™Ûcý?÷âÉä~@ ?êWq?àޤ ¾ÚádFè«3ÔBPŸÍƒ]¯ËtCŠ™~oG åÌØh‡=9|qG`×Mî8È™GgläxC*÷µÊ ¸oÇeòƒûlÒ‹ ‹à¾÷ßNn´ ±ûNýd—7ÆÞ!¢_±'vÆæ«Ø›MbGà} _Æïí€Y€Ü HwøÜ ¸,åðþÌ|~‘Ì…Cp_íŒ;Wÿ¿Ï€Ü;³áFÀ6À½ïmÌW©/b#àÛ°’_žÎ€/b#à‹ób# Jâ×p#àK¯ÝؘnÌ«¸°Óé!vFšØ ˜î´ ù~báNÀ¼Š;;w€ˆm€kv± p]^ã6À•悯§ïSö)¤û}-Ô—R_”HêËûOˆŒ}€gÏÇ>ÀLÃ}€ƒnı°Óe=öÚùƒ‡â÷ŽpFå>@;à/}fðŒm€‘„»‘c`Xb /â&ÀÁ ± 0ÊËM€QÉØ¸.òOjl 6¦…›ý•c`Z¸ pÐ?=6ø å&@›9Ðir Óä&À>˜Ühþò‡à'Wqà€½?ÞÞôþxÃc`\Â=€óëýiQÝçáþ)îœô9‹=€“>£ÜÅÀIGºØ8+õ4nœt:‹-€“ž¦±pÒÓ4¶¦…{gûè}Vd—[¸%Ž-€3ÜS±0³åÀLÂ-€‘Æs टilÌ4ܘi¸0î[ã^±0Óp `æÌ-€î½±0oÅ€ywòHÕÜÈ÷,wFÆÜÙpà¤[.q¯_ˆ@ÜSƒ¬ýº)¯q Ñë¢7Îpå@±``^à“œ|rwnÌ"ƒøìªs`ôÑØý˜Àׯ‡€Ï,Ðò|6„uuÿ4ƒ¿á>µì¡UrðEñÈ{iîIY€{™´'I@{y#ÒžZ|\ËÍquÀ¿€´'à^Þ‹¸—O¸'àžX÷$nŒ.À=€¹c‘›ù ÕEyï>¬#1¯Ù‰h>—$æÙ9ÅU1ÏÞ»yøwæîbž¾ºÏ/‘óÚÅs`àbßÞ¿ä@ø„)¼;[¥ß(½;¼táÝycæÞ<ö>¼; „wgÍ“`àÝùr×axw¾q ½;Û&¼;í¤>¿¼;ó"`^V˜'`žä̳4ï±ÍÏjuÊ{e Úó8÷ÅŽ)¦Ã'ÍÅO,>?ÊW]<묱uÎO¯ràS‹ŸÜœgUŠÅO¯rà“Zø4ŸæãħiœøËŒwWÍï¬[€|r•3Ÿ̧–Í|zM©ŸwÌwXæçó©Å™O-Î|‡eâ ‹3ŸZœùÒBæ;,›ùÔâ̧g¾¬:™OÓlè«"¾;^:ôU;à[·üi.N}‡eœï,©O-N}jqê;,ï,sö©Å±O®ö–w6,Ž}jñ·C-Ž}‡eà-|ûÔàܧmî; ïlÔÁ¹O,à>¹Š§»ª¥Ÿï,¹O-Î}jqî;,›ûÔâܧ¿Ã2Ïw–àWí¬èéT70Φerœýìû“|œüÔpÆYßaøŒ³$?¹È/ýíH~zU›ç;KòSK¯ç;Kò;,Ÿq–èWíÜôª‡¿lËTô“«€~jy>ã,ÐO õ3ÎýÔÐ8β-À~Û¢g¿H‚ýÔ28̆e–Ï+ ø;,fÃrc˜Ýç}'ûUû\OÝù§9û©¥r” KûŒ²`¿ÃÀQ–Máì·_ê®[ÿê,¾\ñgÂî1Çy ø8´`ÙŒ'ÀÌ02´¸Ú8$ÆÉpe€’u‚^¦nŸ×»Á†×àbœ3x¨D¸}^Å)0¾&”3Jr¤Àk}+¯C ŒùhH’¤@ÉR X Jq JHÙ€Ôã\ÅÐÅ-0ËC-0s¦(i\ Ì[Q Œg)P.i\1é-ðqÈ(ÄÀÌZ d3Þóm¥˜I¨fߢ˜U p€LL ´À|œÔóqR Ì:P ´«ÔóÓ><{ÞVž¥ )ðz¯ÇA0×z'†+ȨØö¨#JÇŽ³×n‰ B‹$úùu™Šiþ¹@FÅ©62’– D[F,IK *-êÑ Hi‘¼`“¼Â’yíПCƒ"¥%ó¢-óJË¿:‘‰_ÃÚå_ȨGˆ‘»Eþ§ýw†Oùu_(ý±e¾ýÊzŒÍ×DÌ*c1+QĬ2²ÒD‘UÄ(Ь$FQd©˜•$Ь"FQd%1Š"«HŬ$Qd1Š"+‰QYE*fõO2²«.[ùüÈè|°~ùÕ§ç·>O¿üfÇý~²~»ãþ:¯?CÈ4a‹‘öÿ.„Ðz{õÊ¿§Ù®ü±æãã¯#GèùÇq„Šº¸W ÷~~vk›s?ð )‡þkÞ¯»Å†(㋼>Ý2|ëO‡ÙÇêbÿ~‰Êöð3ÿ ßóòìˆNÈOö(v ÚeQnlõa[ÊÕÜŒ§’—}úi'áUѽï±õÛEÿbGîùQðð/v®¥»mŸ±lÇ‘í, ,æØb®Bb°óæØž`w÷I…=€í flµë]úÞö¸’T_¨(e\ë纲xÙÖØbs¿^±÷ XƒØÜ/Âh;2ªXšÇ,Ë>ߣõ‰íâŵÚn`¶~·+i›+lîgº·”]òfa½·OÙ™ÌmiðÑÕº'6Í"ãîVsÙ.~«âÙXã›gS+þ%]–­%¬[!€R©}Çim+÷ñJ¬¥Íý,nó4æg¹ ެ^†¹'ïz»L” Ê ƒVƒÇã¾;"þ)G.ÖŸ,¾Ã|Û ²½ÀâÑabÓìàuoÏ××)W>XT_«¯4žuÝ=ÞÜØúP<úL³°Â{9¿¼%¸ÙúÊ^A,vè¾½©ãA0›Õ_Û~SåÞk¾ýÜúÞ¾HµŠ^ÌÛÞÔñ t$ó9¶7ÕjîÝÏ íUµ/Ç^â/æ÷f¯j¯ÕóeÙ[eÚŽ¿ËÜmågw ìu)öºÙ»jÏÁ_ëâö®æî=åLS-œñníéYz{ö»:n,;•þÚI{ÒúÛ÷»jI./Ÿñ_v|ëcõõõ¿ÙìVг|²l5·–v°ßµOØû£µÞ­¿ÓT<…ag‹}àÃÖ}†?Í×ÓÔ}*È~š{E½Œ¶×·›­Ÿ¡<ëÛT«öÑa£Ýîĵ,ÓßÕh›aaž, bD‹ÆþýoZgÕ¾5¯½r½r¾^Lη—5Þ©œûUCÁéÁ¥²µ.{ã œÎÊ–ÌíG|v¿«ÑÓ-Æny4ãwø»= ï”Ex‡vYÛw×£8¾âœ]­îs2k~ªÅ>ÖnT¯sÃÇ·-ÃðW®^¥ù«ú@«{Æ{ËC©å`¿ªyUóAÕÊ»»_½Þ†Wuª¦zÝÏQÞáƒêx°µ©^®êU¶êÓåcR÷ʱµÖsûhRMzÚ¯*?ÕÔQ´„÷ãÃjÔü.ÞTÞê®{Tº o*>7õn{TµÞó‚j®«­¹ôËKÛ<Þá\ Oùj1çêjÇɪ³_U~ «m ݯjÜÚöÕîWõAÀ¦úø|`¿ªÝÓ<>ªF°h ^Ÿ=ßXc³ªÑ±êÓöFÑÃâ£jvŠçõQ5ÂÓ1ªfq†ªq*Rìƒc¥Åí(ýý¢ÆìÌZ¾¨ÞkìÜâý¦Æ­íÈäýªò3VÍ›t«QóèÜÃjôв<+ó&õW•ïKy9®²‡ÚfÒý®Šeø»Z°×®_nÉšÛSûU}¦»(×za\å7ªÚÙ–úfÚñ¦öªö7ÓZwvÍ´Ž½¦¶f§V3Û‚aµ X­Ãj”®6«lãúbX–°-uV‡§cXgU†ÕxœÕWû¤«ê)÷j†UŽ~Õbfí£¶AöÑ‘bY0ªr”_uhöªK'hÃ*°5U£RB³¡¹öÚWm~¿,­cTÍÃjÔÈöÔ–£­ÚݽÆba>]{ŸŸìGï3*Ûï*‹k[Iß縨pTe­mƒ§¿«,ò3…η¡£ÚÆÆZeCOµ‰C¶–TÛ¨Wª6žíŽG¾ƒƒ*¿k¶±§ËS²Ï—¿ª0ìõ®UCK§k¹êÀýѸA¤¿î/›ÐŸÍs.§6§¿je¾Áz{ ª£aцô·wŸû,ô·(òHuË[~•Ó_îïÄ¿e™î}øwUøwœ’øëºÁ&üL'Bðßýt!øÏ|¼„à¿8¼,øï®ØAþ»Gàø/6[8ÿÙ‘>Ÿ ÿÝ;̓ÿì©íûü{þƒÿ"¸Oð_œwügh—ø'gþ=/¶þIÆà?#÷zðßS1·"þÙªÂã$ü‹Ó¿ÿ"rñÏF9Ïôg–ô÷¬«,éÏzF?ð/BÿE›à¿ÇöÅúUà?ëO'ÿeÈæXãÏŸh#ìÖf#ÂN`„ ŒC΃³¢$@Ʀ´³Ò,{ ŠÐ€Ï„‹0ŽÃ|&‰# A`V“(#pK`œòGÙÆ&‰À|4À8#?°\p{ Œ €A€Ö `< Î$>0`UDŒ4y¡È€Ç ¬ýaƒ$ÆÓì6 ¼·§ÌIܶùJÔѽÏØz²ˆ€×Ñt%âKO‰€ßG¥,‡ÞÎ[’00|™Oˆ~¹\Åt{20ð­ 0K ¼ xÀÀé§œ`˜Gƒ%Ëu†1°½­z0’¤è310æ'ؘ'h‰£„cÑ۾ᜠØJ7d@KÔáW‚@~%Œr’@ qòVÊ„@% oíE¬>Û.ƒå—@ N V&P N ¶çˆƒ‰Ž…kpHRÙqR Y@5ì¤@Æ& ¬‹K l½Æ lN…Þcñ@ñÿ¶è€U0Ð2#Ó–Œ—h`à=ò&0°ZL ´š€:¼Nxޱ jãáœÜB ¬L¤@ž›' ÿ6 0Zœ_uu-D÷€ ¼#Äu¦ÆÕÈ00îîdb`õ`b \}„:æOxwœo( Œsþ€fÀÀè4 è–\­ªGÄÀj1°j'VíÄ@³-0ðî'QhmÖ£hÅ«*``91°2‘«\r`³r •¬ñ"šhÍZ9à@³cÞ€‚– è–AõK ¨Ú ‚ê–@Ð2%jF Õ+ NZ1AÍ Y‚fòVZåàÀê9PC!Ô£B XÝ"š h–A7`e­ÊÍÔ´M¬±"Æ6§g‘ï ®2Á¸Ëwˆƒ÷+î`UD¬º‚n¸_9 A=Q‚– Xí!êJ‘­9@A«*Q°f QÐjJ,Q°& iÐÒ€- h°ê& Z.Рº@¬ëM´b@ƒuÁIƒV9hÐ, Áê9i°ê" V] ÁªŠ4X—4ëûXÄ@uŠ0ÎÙw–´Rƒuíƒ5݃V`ÐÒk*#M& VådÁêYðk+/YP«}DÁ€·îZ`5˜(x?ƒŠbæhTõ€‚nÁâúàðe¡àýLê³LI}f õUM >³€úÂr.â_ìaJòõ½“åC}'µaßIÕFØ'‹°ï|î›Ó0¹‰ÜÇGSqßa¢¸¯ÒûÊðÓ]%ð«Ê~;a¿ZT‚ß·ˆÀ¯J%ø•…àw@¹(ð‹ù©äüvŠU¿ý" üv©t¿²üÔŸº ð«öüv¨r⾪œÜ§®“ûv€WܧLä>=ÚÄ}•„ܧ¡÷•…ÜW¹È};Ÿïâ¾JCîÓàˆû48â>õJÜWåûÊBî«’É},¹¸%‹û* ¹#(î«$ä¾²ûxñŠûöS$îc‹‹û* ¹¯,ä>öªÀ¯j'øÉ"ðS'~*Yà‡éUÜ'±×\ا.û4 Ä¾½ÿX©¯÷lK ¾Ø+ Põ]ÇøÈW§lGê‹ëk¡¾«ãÜuQŸY@}± u[@cLU„Ô¹Rç"õE.(w ¾8¤seµ4À¾«ãŒwaŸ•œØç†\Z££Ðûªľª‰ØW­!öEÝÐØ€}ÕbŸ¥öY9ྰ¤Jî«’ûêJû¬pŸÕî³rÀ}U¹Ï-su½R3"ôÕÕôÅÅ„Pè«Á"õÕ€’újhH}Õ8R_u‰ÔgPßÕq䌨ÏJõÕD&öÕ öÕ`ûj ˆ}U±Ï,ྺxä>³$÷¹!×V+f樚Á}Õ'rßµêŒ#æ«Ñ$óU%d¾ê3™ÏÒ€ùªf2Ÿ[r]5 ˜Ïjó½CÿcA¾˜=¡‰|‘$ªÁ|Wœ•0ŸYú®Ü/nÐIf 2_å!ó½—Þd>¥ùIŒ q^›"Š«|}ãÆ¾›>)RðÀyq{æ>r^iqä¼xqÌ—}r^m‹#ç='ßqÉy=^Ô«­4D½ÚÃAÔëgj õú WQ/N>uõÆqkoß\”Æ.bëƒ ì8y#“€öFœÎ¾Ûâ'7à÷Æ#¥¸7ÄÒÞ¸ñåB´7:â0ŠöÆC‚´7 &¤½xyàþ™‹R8ÏB íÅkO~Ô&îtÏÒ÷âP¸dDÐÞhÔ-ˆ{Ñ«|ω{£QnîE’¶x{V&âÞxæM¸§Ù¤>CÜ _³„{q¾ÍßNlKhOR»ýº8j»ß[W:îi»ßÚ×v¿·àTNµÝï-&Ý |½ÓÃQÛý:ö¦Ôv¿Î¸Ý¯#JBm÷Ó´æv¿Ánm÷y"~íö|»Ön¿*¼76²y/^è;öÿå¢46:’÷‚rÀ{ñÖe ¼§@(â=…_ï,›ýÊÚ{ç;Ð^œ”t¸³ç8Nz•‚öÆ}}s9ÇóÙè7~˜¨ì±/¨ç–\ŽÂ;{zãÄ'=¡^¥!êß„z#Þ3 P/8gñô´$ ½°´EâqÍÒ‹Ã"±õ¤g êEUû‚zãB|q¢Þ¸w&êÅ™yõ"O~£#êŃ.=+ˆzfêÕè7nʾD½8ÎéZ¶úE¯RÆ'êY. ^=‡‰zã~VWÏ0äRBÒ‹L¸.IoÜø|-Ò‹ ®Eá3K’Þhø,NÐ Ãæžžz ôô¸èéY(Ð㲠΋LcqôMj#8/,éÁEÎÓ3Uœ§HœWrÞxRGæE8qób`ïe§_¬@ùÒGЋU Þ• z–  7žNKÐÓ:&Ò³$AzñóYIO/;"½‹îP$=ËÒ‹Ζ~£Ã%B 7úA_P€ÞÀ¾ƒ ê™o¢¼(ä\´=fâÅ––}A¼°¤ß/oô›>Ÿ@¼8|íôM~–ˆIòñj$‰x5’D¼*—ˆWÅñâ­a[vùé=BˆÇ7ÞØ-‹», ¼2€ï,øÎ,à»1Nò&ø.,ù–M¾û›Éw•‰ˆW·O·1 /·K‡„gÞxo ÔtHxcÀwI„gi@x‘f[ÏrðÆÀvf^Ô~Áí3Ó²ðâ±u$4ðÌÂ Ë“Ž  <½ñ‰ðbØ[ÒÏ,“ðÚ¶aó7 ¯Åá—vùµ8&8wÒ‚ðË\R=KBÞ,6õ,R^µŽ”ç,©º2¤¼Ržf!¯¦5!¯††W†/ççByq¾"$CPžåJÊ«+NÊÓýÈ«ûWR^=Hy±Úå‡4Rž^-4è.§;ž¡Zt§M1¤;EX-º£BûGt§3MHwÜw)¸‹7­Ôw ]p×q’®ànìØPpׄÜÅÎBìöû]¸‹çÖ/ÎvzË$Ûq¡/¶Ã¢´ã+´S™$»!ïG¢2íÞ ÏS„vz/Úñ)H´›·ÒíǸÌr{D;1ÐÎëJ´kq„/:çenqg[|8c¥YÎqñº&ÛÕ}L¶kqÊgÙN=ÛY)`»ÙšœX`»×2¸ol‡Ív;>ßvVÑÍ¥O`V\ŽÙéPX‘ÎïÙ•…d§ÓEv<¦›`§£©v:k™`·ï)°Ó¡Î";·-²ÓYÚ"»x1ÃŽAÊØÍ3H!/,É~àºýܨ¿ëâõn‡²—KÑ~B×™`·-:^w:–S\âDùÛOq1Èn?‡ü5'ܹ!án¾l–güÄÎ?ÀÝ~Q#Ü™pgÙ¯ûøÌ¸‹ªóV%Üí±˜p–¶8pšt/Ãör% 9ÀÝ×==CwfÜí œpgiîâôX8†îʸ ýœâbÀÝ~ó)L¸3 àn¿µÿpÁàõ ¸3 àÎrî‚ òûáÎÒ€îö›ßêHwaá¶½¤;+t§\¢;¥!ÝYàÝ~7x=ï,ðn¿á1!¼ KºGï, øn㛤¾‹P ÇÂw‘¦-:ž¥ß…%w³ïbÛzÂð® À;mlÞUÐvwˆî,ÓµnÝ™%é.JIÆ"Ýi{|ÒÝÞð)Gt··‹Î¦ ;³€îö¶œâ ÚÂvU,Ù®ê%ÛYà•¼«ª‰w–„gå€ðâ<æ•ð,ÏÒ$áYž%IÂ+ ooÛâ@x–„gžY@xV/,ÏrŽ‹Y€xfãíí!MòÂâäY@ž•È«4„¼*··N‘g™ò" 6ÊòÜ‚…µŠåYPžY@y– ”··<¸PgIy•ŒgIÀxJBÄ+O>u"<·`Y- /,Ið$<³¤†ç¬«ea” Ï-XWp€d<+„W^å"áYž¥á™ˆç,¬š5D¼š$D¼ºˆxu7ñôxáÕÓ‘„Wj ^=—‰xµ*ñ̲s]åDÄ‹5sÏ£gÿr !à1Qîȹó@†ß?Ë3,;6öåZµ=7ÞOäÈùH(î±_'1‘Žœï;ü¶lãS$U1 vñ–/§Ža Æ)¡‹¾÷¾¢CV(WNøß ã¾äÙ-éÊ9¨YÉ—sÃ^&ùröÏY.qÐùV abò•VÞœ;Â)ÖŠå…RΜq ¾ÓŠ0 üIgN8TBÞ»ö抯ç\ÐÜà(ïɹAò•öræ”»å=éê”÷âôö±zsx€W—äyÏ,ôæ<Ïõ,ψŽs,xEà¨Ä0:sž|…%ʃC(wˆræÜ) å” ŒèáóINù¢å ¬räϹIÍK ¬A'F·yOŽÃ„@y†åƒPîœ;aXcL¬i"wÎý{–‹¼$„Q΢îUåòæäwxQ`Ýt¤ÀkdI×sá “«rPà ˆ”ßô8AR໠Ƚ'‹’cN ʇGSwQø* !ðjyj¿°ÚF dz{ñå¬ÛP¾œžž›ð9y°A_Xx $D´\€ÀšY„Àkðs °ž%„À˜ç`£„Àª‰gðU!0j8º^'@Bà ’µlâ« @´\€@=’È€1ì©-“­0`LôüH oýg9ÌE^ED@Í" j–°\ ‰€×ÀW!`ù­ `<ìže Ÿµ¨»WÈ-"@M `UE¬’ËñŒ ¨»W¹ò…Šh¹Ë3Žxuº’Xí#j½K¼:Ï!F¤’suæÜwr#95Vræä´.gβșSî”ræÜD†tædƒË™S§²È™ó”®gNN¿ræì*9ßI»*}æJJgN†œ9«9pæÔœ3g>X™äÌÉÆœ9q X9sòÉeΜ9sÊ?QΜ•‹Îœ|z”3gç9;ræäs³œ95‚åÌÉ\ræÔ¸Ó™Sý}ζó”Mús¶¾nâ3WMºsj¸äΩn–;§ÜBåÎÉGƒÜ9ùü#wN]P¹sjåΩ^É“¯åΉժ¼9u»Ê›Sw„¼9C‘7'Ý_åÍ©>¤7gÃËysj^Ë›S·¸:«¹ôèÔµ”GgÓq)ôèT]òè|xÞŒ<:ïþÙÅ–œ[òèTíòè¬\ôèÜè¿ —Î8ñvûäŒ)Nž»"N –<:7nô£G§üBË¥s¤¿»<:/òIÎ"ÿy_’ÇÙ¢Í(wÅҠŃøü~¾JÅ4ÿ,øÏýd춪¡,d‡¶ŠòQ– ²Óf¸Z$T–*‹¶*«,VV<*/$T+ 6+K–uðŸ{†½ºüç7¡{2¶Ï¥à?¿“àoÿùí\¸ßwÒ.Ùâ±|çU̘?Öè?,«âú°,ìò*ËòT*K}T–EöQYJ¥²,•ÊRd•e¡}T–R©,K¥²ÚGeYl•¥T*ëDºç©äãw"èøƒ@¿™¿èMwÿ,Ý'ÐÏç×o#ý•§Ö¯¿yþüìõëOgï÷¹õóÙûÛ²þv Ø;y¿wûOC½£ñõÏW€ž?‹´Dóùï›GõåÏ3"ÿ÷õ7"Ýg¾¼/óœ=Žw¾áêð¾©ÏÈÐWxØÒ2ýu®@®‰þïºÚB~onx9½ëê•êÅÜ÷edOu€Šêüp¶Gš÷íðÈ4g˃þNœã?Ï›ý]8½~~”¸F6LKÏ#9|«›ï—ý8_D摜;üOæ÷£yb(>ÐÎwùyJ,O=Ÿ6æg¶¢½¯OgžÈù¾3Ïï„óóѾ{ݱ±-¢DšåhùqôÆvƒùU,Oä„h8÷v#Åœn­sGóÜèþÀ xžA0伡*̳"fº>»¾ïs[nt똆y–wmê˜'A´¹®¹ó$¦èÃ{¥çkÌá¾Ü¤á=oR z¸Ï›T3?< w¯:¼ îìÒìÀ{Óž–¡mçÎBOXž¼MGúƾPvçmÊ;¿Å©óŒë§µÇñ>a[<åó>ÅI*-–æ}ŠsSÚÖܧÙÅwÆ[/íkyò>}pJ‹ø¨ó>íðÀlyÞ§¼J-b„ç}Š] mßܧpc$ÔŒhûû€:|bµ8ÌäÉžLò> ö5IœÑà#ºç–;ÑÐóVe‹CZ>¯ÞW‡+ïUN£¶÷=ïÕJÓîÕ¼ºm ·*ÆïØ.Ý©™çØsA­{.¨š{ïs¹áNE¹ÇyáF¥áÊåTSïµtܧœqôÿåÃy4,§½ãÉåT×àx°œòlq®ì±/­XNUwœ}¼/Ó/ÎÚŸ÷)çlȇó̘Ž/-Î?Ïcse9±šª9qPùùø…Š£®çªá;o¬¦º¼g|›8í*œ «© ÓÊ“»ël´âoóNåƒïµtŸW׆U ® ª ¹®¨™ëxp«âÙÓ®“K*Vöv]XR¹*´øV1oÕ†M¯K*_"ÚüÀ1Ó 6G ,¹gšÜÙÔâ»ÓÀ›ÇȪ:—T¼h´©¤Ì4Àî‡éÌ[õ-x¾†µðFÎ%õÎù-N ˜·ª:ÂãlÍÁ$'ÖTµ/N4iÞ…8ŒfÞª ~í¾±ªÞðøi3òd¤áQB¯Ëê•{ÖZ¸FÏ;•‚t Nœw*ÔoóìÃHÃSÐ[œ¡9ïÕˆ?-mêÊÈ­í¹ªæÑG­XR7h;mžózÙ)ãí}ùæËC¥[Ëðšutk÷žg\ãÃÛkÈ%Ug"·67"Õ©Îï+U.©:O¸µ¾#Ä'V·L3ÜZ~km䊆¼›Ÿ-WTfÜž=WÔãFŒ¦×’Kª…jÏ‘KjDŒÏ~Îù…à…€Ì’§ÝÇ]«¯%ÔxN¶x_ïyŸ;¼åÛÓrEU€”ö<¹¢^Z„‰;5ô†#Óô\S=_RÛ3}vÂ?~66‚ƪ/-ÂÔÍã­Õ– –^ðÀšQ˜Üu¦E¬¡¸O÷§H?sEÝc³ÑlIÏ£“&åâØï^1O9~€#Ê_TÜ÷LWGã¾é+#î‹>ç{?¹OáÈ}W•?-É}Wo8ЗÜ7å«*¸ïñÊýKaß^ý#Ñ+±ïŠŠóqMì»b7#ªöÅ“|÷Jì»Âc|žpDÏ—<`ßvBlöé»”°o»°ëHØQ‡æ§`a_Èz€3`ß6 ûäŠ.ìÛ·A€öÅ[Íž%ûö §$ ûä3.ìÛÏNXöå+‹aŸ¼…}‘iOKbßþ‰}ûÿ•$?9.Šüö«‰ütýäY)ô‹˜GyéÈ~t~úí]0ô‹7#P(Ð/î0%Ð/npØO¡“Ä~!3!Á~ûÀJ*öSP&±ß±‰É~zXþŽ÷Êçhþx[‹ýŽ gWþŽ §È þâ‰s¤ôÍÓð/^æNa®S|ƈþâ 0+ü;öp þ"IOüüUóljЯ‚¿Hs&þªÛ„¿êáOÍ!û…H;’ã’ýt^ Ø/.]~‘ûbýŠýŽˆõü‹¡_èº÷‚~ª™ä¾jm!¿šÄN’Ÿ ¡ŸY€~lj8¾b?-Lb¿Ÿ;°ŸZLôËÅMà¯åù<"ø…ƒ_~©ø¶·‰üŽ÷á˜o;“ü”@ä‡w{#?³ýŽpWYÐO=úEEù’Gô;N<-…~V2ÐÏ,`?·$û©ßb?†8úÉÉPèÛ¬ò;òUÞÈÏ, ¿úw'?wùÕ+ȯúMò³rA~uH~Š·&ò;î›tò³ª@~A]w– ô;.œ¥'ö G„|m&ûE9Ù ²_Žoý4\d¿z#üUå„¿H“lø‹ž ü1ÚÙ¯êúEsóõœèg¥ýªKD?ÝM+RŸ è‹'å±@Ÿ•è³¶ú,  /žã D¤¾X$:PßqàHQ_=žH}zñ'ôÅí›_Î}ªŠÜ§uPܧW!qß>ø½MÜ·où(î«‚Á}zU#÷í @@_!¡/ž?,û– ’ˆúä _ÔÇ0˜E};üÎE}ñ^™µ“úb?ÛHôõÞäCCàÇ·2ß~îdN€ß~"¢œÀO;Ñ~ÚPàopiøí;B‚ü¸¬ÈðD~ûv‘A~zá/ôÛà|$ôÛFº) ý‚î´ýD…~{Ãz$}=¼ˆRMÿË!€DÓ/µ;ýƒˆú3PýÕ)ÐRý´›BªŸžüRý´@ªŸâIõÓç©~úV#Õ¯ä ©~úBÕO߉Jõ{òØmÒ_8–0à+¥ÔÒßµñÅ™ôÇãàÑÛdeÂßuñlî‹æ[ þæó»ÿbð§}‚¿°ôEó“‹‘à/¶$å’þ± $èO.ݤ?¹Î‰þÂá)_õÛâi%ú“—èO>\¢¿pß>Wá.p¢?ùg ÿÂIª-ø'W5áŸåþYƒrˆþY t¥ýÉkOô'×/Ñ_øBoýÉôW#LüÓÄýÉñPôw]¬ú£šàO'0 þjþ¬àŸ\0…:IGø§ƒ…ò¸þ]WÃG⟕ü« Lü‹P`É0俚¢à?yЊÿâM%ïpðŸåÿi³Š°¦P§,Šå÷-ŒW k!ÀëFôd`ÕE¤'ŸÐªÊÅW¨ëIŒ^åw2 6vˆëÞZM`@ù-'ªýb@=Ä€jœP7‡Ð,`ÀØ´-òŸÜ Å€r=ZóÀ€– ¨ù'”Û² P#!¼?M“é6/´$€Àª¨­‚@Ë”¨]‚Àª ¨Z (wY1 ·¢u»é³,Ôö `\ßÞÛµ'"‹!Þ¼âD€r¤V‹‰€Œs ”×0 Ðò€ïm§ò˜(od1 bÀª(t!`Í>" î]! \‹Å€5æÄ@íÖ,&êºkøHj1!P›}– huƒ¯ÁwËI‘À ŒbY @5ŽXõkdˆÚ‘% ó}ÁÀê1°æ9°z@Œ'¤=p`'9°š Ôa ¶ªµG¨=&Ä@+X=VÇ ‚Õ<©t˜Ö#Š hUuÇ“­ àÀ¨ê^8°º@Ô&`(A°žÎÁj AP‹¦@P; ‚Úî ÌÓ—I–áá¢Ê‡.AP'` µB ¨÷3`=‚zuÖ£„ X·3AP»‚õ¨#Öóœ X‚ ¥y¸¬nBÃA³õ&š XÏ]‚ ¶ù^ ä{Ÿ0°  ÀxÜ bQÕrM ¬–«"P Þcþ$üO‘ß1õ0'¿½K僿'åE~Ó1>‰þž1SVOsù{Þ'T>º{éu¿Òfäî)@îž;δøéË‹Ü=õ‰Ÿàw\gÞ¦$?}ùéÛ¬ÈOߊD~Gã[!ÑïhÂ( ßÑø.Iô‹U2_Öˆ~+8‡èih@?Gú)\°Ðïè[ž $ô‹]û@ñ¡’ò¾ÐO‰~ -ô š¼ž-œß„8 Ÿ"\ ý¬ ŸœJø‹ }‹Ó§b„ ýäÔ ôSv¡Ÿ¥úY*Œ.ô;lB?Å#/åo`Ë[)Œî-ö;àJŸÏ k ÁOâK÷S[¨ûU¡Ôýï;’ã©—×çFn‘ìWí§×'cÆ—ð§‚åõ©4þ* ½>U—¼>7,†åõYi(ü±ÉÒýª` úÚC§Ï +h9}n¹ÈÊçs£7€|>7¬V>ŸÕú|²¹|îxÕ)—Ï ŸÑÊå“n9åóI?œòù¬\túܰS¼œ>«.:}nx‰*§Ïmóèõ©!–×§:J¯ÏªœnŸ¬ nŸ^»äõY§×'›RnŸo·Sa’ÛgYèö¹ãåW^ŸûNOz}–…^Ÿe¡Ûg¼ÑÂnŸj1½>+ ½>ͯOyTÉë“ýåõÉËéS­¡Ó'Å,§Oåϧ~Óå³*¾kÓR¾IÊås'Éå³ÒÐå“[–Êå³,ôùT·åô©4rúdåóÉSUÊçS½”Óg¥¡×gUE¯Ou”^Ÿ=y}ªWôú¬RèõY ¦×g•K¯OµO^Ÿòޓק®.¹/>¥™ Üs#_8åö¹}¹Ï,tûäÓ¥Ü>5÷åö¹‰Øè÷ÉI+¿ÏÊD¿ÏÊD¿Ï\’~ŸJ ¿Oõ[~Ÿe¡ß§ ‘ß'å÷©>Éï³Ê¡ßg¥¡ßg•L¿ÏíK~–‹ŽŸe¡ã§\åøÉd9~*—?+ ?7±?ÕQI€\G¥ò”¡ÒËB ï¥B’4@¾O”È·¯ÒùU Y°²ò}¬D@ %>8á¤DÀ_YËùSªªœ?©~J”L Ð p©‘¢KßO¹]È÷³,ôý”ˆ|?éeSΟ²H, e@ú:•óç†cîËù“ÞEåü¹a«‹É€8¹ü?·ó+vzK, eÀžbP©€ËRË’þŸ7¬T@žV* ÏA,'Š•˜4+çOzm–÷'~,ïÏ ÑK¼èd,ïOž†ú“8@&õ!àk¾Jê“öYÀ×q\CI};7JêÓ»½€opŸ‹¤>^Ì’ú΃˜øûüè”RRß½³.ý“‹øÊ‚ ~'Û"¾'?³ðšÜß§ªr‹Ÿ^VµÅïÂ$­-~q–Ì"õieïÅA"-7çq“_¥á&?¾,Õ&?mÅÔ&?¾¯Ô&¿Š}íò£ó~íòÛ)Pk—Ÿj×.¿žµËO%k—ßO ùÎÞ•Øå·w*pÜå·#¶ùqS@mó«$ÜçÇ7¬B¾“οÚèw<ô%ò1Hrmô;oî£#òíyäXíóã{YßÉí¸">ŸˆOýÔ>¿cPýã>¿âDîó3ÂKäÛ•=!ß8ù:7 ùŽ“â‘o¾F|¼Ë„|Ž?3ät ùfD¾Ê%äCóŠøT ‰ïÀùlE|šl">¶XÀÇËR¼'þ$ï©Oä=VÞkø Ý|Ýd|Åe>¾ øª"Ÿ0̈µ‹ø²K||sð‰$ |¼¶|z5ðéU´€5ïÞøÔ)Ž|ÂFŸ B>Ò’OC,䫿 ùp¯òé\ÈGš/ä;½ÕO¼DäÓûõ0ù¤Ý*ä£Ó“O@äS? ùðÔò©S…|ªIȧæù ð¸®6ÊxD>|À)gÏ÷Iº-J_ùåñ ±èðÉodåðɯqF|¤9I£€OÂ#‰O¦ˆ—³ˆ Òïñ¡Û|ÒþÈ{_¥Ïȼ§ÆïQ—*ÞcMÄ=}**ÜcÑžÚ+Úã)Ú¦‰ö$¿‰ö”†þž…rð÷Ô…Ó6¿BDÒžÄAѯmÑÝòŠöŠÿH{ùݲ`¯g{šŸ‚=~É,Ø“E°ÇÏɶÍOêšvúñâ öÆâîY#CÔÓe!éi¨DzeiXQ™åá7TÒ5Aï ¨É<+*¯›@oùz_‚^•,Ðë?uˆ”§Ö òªTB^—ÀÈM~º$ÚäרÎi“_ƒDFȳ‚¹Ç¯ÃG,!OÞìd¼£ÁA§öø=ƒÔÇ=~<áyU9¯öf’ójç%9/D”má¼ØÀ¹îU¹,Ð zû{ÿ€ï –6n7ç9 ä»rö#ß½C…×LòÝ}añ.ŽÒMQˆx×visÀ»˜æY7è®5zÒîÚ¹ó°ÐÝ<Ù-“tç†\†âÀÛuß;ÿHXÀ»Öán ¼kÏïâ~aïZßx^ ø®u~•'ßµ÷òopîL¾{6¼„‰ïží .¾‹{ŠŽ›ÉwqŽÜµœßbð]œÒ›H¾{Ž‹rø®ƒ[å6Ôs,|÷ä!|ÆwqÒoƒz— QÕC¾‹û{Õó, øîÙÁJÄ»gßèh ¼SÄ`á] W ›Ä»ç8©Hï¢à¾à]4g,ùªâ]Wü,‡¸X“°ÀwÕ@òåß=ÁD‹/g¤Ù`É¥(žé¹C|-ÌÁ ßí±|¯ß<Ø›áfžb ðÓH€Ç˜F¼0<Ëf>Æ4ß•xW^êÄ;…=ÞiøÎ,à»8·as7Ⱦ‹ÐH«+§B#‰ðÂÒ]Ñ3¯ö0LÂS0%^° ŽEᙄ§Ý½"<³€ð´mX„gi@x:·K„§ LB¼ú:IÄSü$1ž¥ã)2“/,ðÊã™g@ž6HòÎI§£ÆyÜ-ÆSè&1žö>‹ñÌÆ«},d<|â•„'¯ ;FãÖò]íŽ!ß™€§Q<·$ài8Ï <³$à)þ“/,mÙÎgix•†€ç–\YÍBM¯, ¼ºr$¼ÚÏC³\ '1OÁi„yU²¶õ•…Ûúô4Ѷ>=”ˆz¶õÛúô”žÇ°y¥ç•…zŸ£Òó´HÏ+K7ÄËjéyZÿ¤çiµ“žWZÜQ+k[X¯VMizZ¡¥éi]—¦W¹¨é1Íß d‡yÎg€æÙ°Ç9Ì3ýÝt˜§Ž÷ä¡.OÛñèÜÉà’bÁY°në«×#i}r”# êP›ÒúŽo©ÒúpÒ”¤>2~íê“ï·õiC”¶õ:}”gyJ£ã®¾¾€`F©s5Ž(¨2H‚m_\;gD•”ñ€5EˆqËC’ã¦>.ÈÂ@«ƒð,ZßKìâÚY‹8#³dÉÀ@}Ö…#Öe"Æ-ŸI}aÅ‘+ ÀoP`=%HÕMR`Ý-¤Àz"õ! Ô’# Ôã[um‹ØWÏ(b Þ2„ñì= ¬ïµìê‹çMR 1ðnt^Ƙ¤‡ Ap¾: F;sÏH0^.ïåTÏ÷݇çÈ€ëN êµC$x7žÇJ¬«G´4 A-w"Áê&IÐÒ€ïÀÙ,$Xm& ê¥B$XË"Q0rí‹kç}Ñss¢à}áH~¡`¼š,ç»Ü'é–$A!öEõ»ožgK¼Ïë£ú)æ¦HPoN"A½]U ’ób(Åzît£¨X=B1x <²ÏïæªDLòÏ=ñÎÓ½‚²TàÚ*èGY*ðNŸ!P—ÆÊReÑVe•ÅÊAgK¿a°’ÒdÑð¯ôÄé1&)‡ý‰WÒö(.ÐÝ”à7ÿœi‡"ýQÒ Ò,ä·Óä™(Ó—Ð-Ÿ ã/òK–TA€X’BI•%y•¤@*ÉB±$%bI–F%)J²@,I‰X’¥QI ÿ£’,üKR"–ôBE4Õ¾ÝÿCBý…‡Ø¯¿y ýä™õëOgì÷9öÓû›’þvx '>V½«ùÿËð@ïmkáÞ_? ôšß2â{Ãóü¯^Æ Ôþ<<Ð_fî ôcS|ßð}è‰ï'©`¡zâÃÂT p îs_wn©åpÏüÌ1=Å{åï‡ïá~b!~l_ÀÏ´¹ù§á¨'^][zḛ̂g¾•Þ¿ÔaçÏ=ÏY«]ÕO|™Þ` ðØOo0îây‚:{3¡§ÅÎ}ߨåý¾…\p›}lqXôa;_Ë\‰ädö´ûÁŽZ%‰/C¾£ö _•í4W©×2à_ »gz¸ÿ^'§{×=áuÒm_ãóÌPèåû<ñ/ßù<“Ê?ýyâÍÇ7ê½–z雸±Nöüџ'> õÕÒÓm“>·OC½œ„ŸþÂãôÚ¤/ôÓÓ‘¡\n_K˜-Ïç·îöK9Ø?=âÓÏÏÉ8óÿ}›|ItÉñ> Î{±Äkß9ò¾nœð°VÁñù|7Oè×Ò3´ÑŸžžƒÖíò,–üBiµø04‹ïœq¶úôÛT·G|êK¦kži Œóןá×e¼O•ãòŽ6¿øW˜¬÷…nKÇÍ*'xÌ.ËèwÞ¨ôÉ|Æ ¸·Ïµ‘.5ß7ô.Ö˜6}‹/ñ>Z}{ÿuú6•×2´bN’¾OÞ«l^ߞź×Y-~ {!0èïT{~lK’ø,4–öÅF²ë—Ú1Ûç–ª±ô*ƒ:Õîˆ'Jž66}Ï–Ö…ðå3¯û.2y«²uá_²ïKž}–Àd=D¹¼WUu|òM}oçz¯öˆcp>K9/nõ¥9ÑÍ“Ä ?§Ý‡=ŽV÷[µÇ¿¼U1Cû<dxûâ|ÓÛOgèÇé>z{ÝK=±ÑÍfg”y«²qbzXWš÷ •û–8b“سVϼfO…»Gç­Z=xqU®ðâ¿—4s{nÕ¹˜ô}Þ«ó±ÐcûOïK9ç{Uå\XT±àôкŽk)&¾ ïzDLÙoïzÄ]™½‚pÙg|™»%=Nܼ—bG®©JAÞ®e@¯màNåu‰È»¼vٖ븴" Žˆ¸y§²Ûà;»SgÝ5Íeµjo\VñÚÒã,¡kÐ)(]K®ŽeµZòé2E¯‘몚soXW˲纪RB„jö4| XV5Ïï³á^eEñ¥b󥢇\s-÷s¨…cy°Ý ë*¯Ì”Ÿ´w|rß÷~w,«UðÀ²* ¾”ZCUÙ†—Üv®«ÐÉ{;¦æ¹ÎS÷k6y~Hö±h—VøÇ½+ëû•“©5.­¼‡ÚÃ¥µÿÈrŸÏÊÚ[ÇÊZ-ÆFIM'T›gî“äh†³ìrƒ…׿ø¥vë½Kþ–óC%ÆÛ±·â ñô—’ªû/Ç~>mû±û =-WÓªöYžgOϵTÍ›M8\^AwboS¹Ô[Ýãø—zuí=ÄÒ%¶Dê"Å–ã}©;"Õê~?¾Òôx^J™ÔÞã]اFïí‡_>.¶;/èØölUráT™#ÞS­ˆòè’#Þ‚½Ùã¶áä­²ýpWƒ÷}íü±Ìñí«ºèR$¶?r®êÃ;:â]À¯¿uptÿjè1]Ã˧”÷iwáLwõU‘Lwõ§¾ê®xa½3MBÝrm¾%ê®ø–6œP÷>F÷t‰&Ô½–›Ü7¡îšòm&I¨»âÊä»bB]9±ê^ ¸LwÅÅë°Ìè É7ñL÷ZÒߘH÷ˆ º×2Rº'Õ]ãâ«-°î å8_¬us‹}òYRF3bx#BÝ´äpê^K'%Ô]¡H [“êfL¤3“$ÕU”$PÝk€;©îµÀ)ŠTwÅÄMÖ¹%±Îs%Ö]-!.±îµ4Œ°ÎÓ$ÖÍ4I<À:Ï•X÷Zð5œX7-‰l‰ufHª³R@uW¨õg²àÙ–ŸIuÓ22ˤºÅ0—ž×ï5R[’ꮑæ’0“êátþ´o9†p ®,„Óžt!œ¥ÂÅž¾| &ÂEí)á*(®*'È)A®zEÓ±å9È)²³@ÎZ³’rÕ‚\ AÎú³4¹êA®ZH’«ºHr–$Wƒ1I®*"Éíã ¢—(o¨9‰rÕK¢ÜÞ¾(ÅÐÅ2Ë”³ª€rÕ¢\ô~@¹êQÎ,@¹j3Q®ÚC”«Ú‰rVPÎjÊ™(gmN–³$`¹@ƒü”œ«± Îé.ΩÅÂ9µO8§>çt}ÅsjŸxÎÒ€ç, xÎjÐYí:+@g½ÐY]¥ÐíË®š ³<:³è4ì:+Dg¹@tÕ+]µ˜Dg%ƒètÇŠè¬.žp"ºªDWu‘è43„tûS·t“TW— TW³‚Tg¥‚êÜ’TW= ÕY{Au–TWãGª«\Ä:=d„uÕob]•L¬«Žë¬ä‹+ì‘øÂ:ˬ³º€uV΃5–ƒA¬«1ÖY’Á5–b]õXWuë,×QklÎ%bÖaåÖY]÷gÖí /h¤:Kò|–XQ]],R]MdP]µ†TWI@uU©®j"ÕUM¤:Kª«©Lª³47—XÕ¬«a'ÖÕ´ ÖÅmµ¹DgÓ‚XW-$ÖU9Ä:½:ˆëjxÈuV¸®Ú °³$»jÁŽ¡Tvuó‘ìêBíjÉvÖ¾d»êØNëU²]µ lWã ¸«‹¸«QÝU¥ »šäÀ;K‘xg)ï¬NºÃd:ogàÿœxW5ïÌxWÞéÝU™ »º »j$讆bÒ]õ xW— xg­J¼3Câ•‘|WÍßUð’ïª ð¥H¾sÃð€g•&àÕèðÜÐ, ^M=žš€gYðÔ¬Ÿà)Y.Ï#5¨;ÎJ¡N§ã—.7– t:½D¹‹Îb$ºÚ ¢“«k©rüR"UŽڥʙ%¿"’¦M•Ã9ž¥Ê©1Rå.(™¥ÊqP‰rT'K”“tFQî¤#D¹3ò,MnNE’£Ì%Iî¢#›$9ÆŽ)I^J‘S$ÊáûJérêr¥°I—£ª(]®ÒP—Óu*]Žê¤t9†ã)]î‚l^ºN83YŽÂ£d9%¡*§š¤Êq<¥Ê©ÁRåJ.£*§±IUNóLªœÚOYîÂ%ËI¤•,w~\-çE¸ñû¡Ú/UNÊU9ÍN©rjT9)ªRåÔ@©r‰rºþ媊rUE¹§Ê–(§Ù(QNcNUNý”*Ç@<æ4a%ÌqDK˜ãVÂs•0§ïˆæôUÊ\å¢2Ç{¬”9}†“2§ïג檅”æx±JšÃ5/e®šCeNÅP™Ó¦)s¼œRæÔ<)s¸9J˜ã•*aŽ7])sU •9”¹ GŠ–2Çë[Êœ*§0§Á’0G¿†æ”Fœ.ž„9Pe9N(sj¾”¹*Êœ¾ÇJ™«LTæ* •9>{J™ÃíSœJÂ\LaN)s,FÂ]BJ˜»èˆ&aŽ·O s¥–Q˜£ËJ s¼wK˜S¯$Ì•œaŽ^,&ÌáÒR—«æQ—»äzH]޾ÒåtƒI—ã!YN*YŽ1¾J–£KMÉr7NÂ)YN³\²œvÍH–«ºžÏšZ²;.Uî‘ôRåT“T9%¡*§›PªœRåt;I•Sc¤Êiü¤ÊUU”åt‡I–ÓÄ‘,§‰d9mt’,w}\,í YNbÉrê…t9•#]NÏ>éršMæt…%ÌéZI˜ã»W)s¼­¤Ìá…¨”9  ¤¹ªÒœzIiÎöÓu/‚ÒœÜᆵ Jsôî’6WU@›ã]@mN³ƒÚœ.3µ9åxncJsUÀ”æÔIJsºÁ)Íi0)Í©”æj#¤9]jJszÔPšÓ£Òœîƒ”æ8P”æ®ÅÍÒšMe/Îæx}%Ìáf¥.§yN]Ž‘;¥Ë©Ôå4ÒÔåt{§0W[ë ÌÕß!ÌU‘æ4ß)ÌéiOaŽ!]Žý€,Ç~R•ãõ¶h:‚5Äü5X‹C÷ÎÖâ0àÇ÷ÆÕ™sâ5ž8(\ RêÛrqÑé‹Ä5ä)\‹c݇Rg:ŠÖZãé& µ‹s.´!op¶I.-m§ßri‰[>_u kíáé ¤5E¡­µSwEkmtìF#­µþP7®YðZÔ?ðZ;ì#$¯)„ŒxM‘slO„Õ²ÍqôFÀ¦¸36°)€M‘rlе"`‹ òžÀf­°Å#oO̰Yí 6ұ)B‹­j'²U.2[ôfÀo2—è0Ü ÁlÏAЛ±~:²Ùâ œsÈInraQŒ!›ÓÙ¬`0Û¼Ø/—KKTÕù-Î ¼—3OâùŸ‚5™í9H™d¶hOBm.™ÌöœdW2[XVf³4`¶O2[ÌŽE|{®·/í9é\Kd«Á²Y±@6M !›.ƒ- >–3OÔM!›å²©.!ÛœÎÚÙ¢éXAd‹\ùþCdÓµ²Y ›PÌ‹uú‡‘Ùâ H¸+&³=÷ŽE’Ìöfãõ²Y!`¶j™-Žî^M\ȦÙ&d‹Lù©”Èfi€lU0-Z“ß%‰lš¢B¶ç¤ÄHd«Á"²=—¼+Am56“Út߉ڪO ¶º”¤¶+RÛsÑuÔ¦@b¢¶hïµ(oV°­‹Ø¦›UØV×’ÜVcCnÓå%¶Õ¼&¶ÕU ¶é¾¶YÁÀ6= …mVNbÛs.Δu™m5„6Å×´Õõ'´é‘)h«ùIj‹³æÁ_ ¶ºyImV2¨­n^R[Hÿ$Ú⦻Ù-†&ß·ImŠ &j{N2.±­À¶2Ûêl« Il«!%¶ÕE ¶Õ£Ø†ëBf‹iô,ÌfÙ´Ô‰Ù,˜­žGd¶zò’Ùâqo§d64†ÀWnƒg%×TိFœÀV7/€­n [M[õ€À¦×›Uþp]•fçº*÷P„Ô¼²=ýñ&²Õ¥²Uklu]ÁlÏÆS_Àl5N`¶šb€¶š €¶z(Úâ ð(‡J+!©­FuR_nmõ`´E7á-™ÐVch«) hS¨>B›Þúm5cmu!'´U#Amj&¨­®¨MïJĶšÜà¶êÀ­Ú p«‡À­à Áð3OjtF®Þ|ÀÜÚu¡ç7 $¸ÕD¸Õ$¸áf¶EœŽË¹MCnÓØþÈ8uŽe^±D{ðLzV–×$=+»ª<+¡{×9–M‡ poÜpuŽåN'Ižc©3yŽ¥N Ô9–Œ,\›ã´Í2œŽ” '°d8mO£ '±I:ÜɃ=¤ÃÙv9~5¤ê&rYm.ÃI𣠧ýR’áJRÓÎ8JVḅ¥d¸Ú¡ÆíqDÉp®›T8©DRá´OL*œ2Q„Ó&,‰pÜ<% î‘Û%E8íÁ’÷Ð%V*\DZñ¶7޹$Ã=ÎG” W¹(Ã=tÅæ8•d¸wz%}S†{¶KeµN2\GT¡’áúö=ÇÒ,ø\øV•;@¥Ãu¹9R‡{žëæ¸Î/)’áù4R†ëò¤×åcIN!N ”§nI‡«’©ÃuùjB‡̤§«@®j¢÷^øt_×G¥úP:\Gx˜Òáºü©ÃU.êp}´øOÓáº<3©ÃEd–õ$ËÊE®ÒP‡cGKˆ8»„8¥¡×¾KˆÓ`Pˆ«$âÊB%n D)q•†J&S q#ø”ÇÙ_:œú-®ÒPˆÓu§º%ı*épýëNY—JRCnCŠÓu’Ç*)NÕP‰«TâªmTâ4àRâx—•WM¡÷溦«\’âT—´¸qëÜJhqê¶´8°´8]iq|0©ÅifI‹ëˆëQZœFƒZ\¨Åq©ÅišK‹Siqã¡dF-NC*-N]÷–Gé Ë*Ÿ%ÆiØ%Æé–’Ççh‰qº4ãª.Šq•†b\ÕN5n 6’Ô8U%5N׊jœnD©qkJÓ #5Ž£.1NsIbÜ@p㔉Z\•K-Nã'-Nã'-® ¦§‘§ñ“g¬­j²´8•,-NS’Zœ&Š´8±´8uBZ\UE1NÝ’§{Ojœ®Õ8µjœ&iªqj Õ8ݽTãT$å8M+ÊqšC”ãtûP«Z Çév¢W…® ¹ªc rº4䔟‚œ.09] rO rá~$ÈUäªrjG rê89 ?%¹*’Ü;!S£&Ç)OMN (Ê159µš\å€&§J©Ééz¤&§ššœšMMNuB’«!ÉU# ÉiþR“«2!ÊiÎS•cíf„˜åÞWˆsžR£@´xÜšßÍV‰äŸE»Ù·}ž­oÈRqeh«e©È2ûaœŽ¥,Z¼¬´yY´XYï+×Ò*ü¶r¦ÅJÁïu¤›8{ý<ÐÍŸ¯i×_tÓú?Štó›2¦Žº ùε9Žyˆ’¥BIÃ%y –T‰X’§bIŠaÃ’,†JR"•d©X’bذ$‹a£’”H%Y*–¤6,Ébب$%RIÿ ÒMœ^§¨ý4ÐMû£@7íÝüfüN ›7Ýý³tŸ@7?ŸT¿ tóž_¿~E?{Zýú³ ûy€ý΄ýMI;Ð͈ÒÚÏãܼñõÏWØ™?‹s³Ä¨ùï‹Ã|_ÄýkqnÚÏÊø¯çf´ǃͷ>»}ïôßxˆuÝç'¨Ñž83æ÷üD2¹"¶œpªm앟âGø;ÌÝøž=Â1à´ýb#˜¹S$2â[êaÛeÆü°ÿ˰yeŠ÷½zî–Á ñˆïµñÕpëÕx":â± þ=>‘ED«~ê ”Ç[÷|xGñœ¡'ö "8žØì¿{ÖÙcÁ™ñº·,"Þ-€÷èÛ|í<Ä"=â,†áž²Þû{î~Ø04/ÅÎF¿Ôfú€Áã@¼âñâÖlô‰ˆ£¯á™®â c¡ƒFÄ;÷£‡kKf™_4Ç<Ç: øü;Þ··Ùê2Œü&«jǶÅÏ+¿™¿?3°P¼ïÎn}¾uš!æÇj˜oŠh4Æü|:O_›_!Ǹ®%æÑ3h¸§¸ç['Opïdœí~Çdj|ïpe‚'•­÷Íj€HµJ*Û­ £e»‘bß¶íʆg¯!ŽëÎ$ó’†edËñQûµ-›÷¥×r^?Ž5×µgÛî”Â2²ùy£½†»eó¦ôµ´ù9!}ßßÏž­«Šâk« Òk™qFë#ük‰ Øa×û¶íÙ DXzv¡çW‡xUkÙ…²„{–7xß§÷,¸7XzvAÍÙm£1;*z_©×.¼‹'F&6!ŸÙñ#bî¼ š}:u½i®<1ÿµ„7ÖZòèaä:¶{v¡†ôØÏ¥DZ}.Âqôe8㶘=ù}ëµ\“½ÔùÉ~)÷~~|Êiwö ,Ï‘=ÐH}Ë>3JhXž¼Uû¸—‹{n“mô"dÕÚ¾8ÐðZFoú©.ýoÇÓŒlŸê±bíÃô¥¶Ûøµ´#¯‚YƧç 'f}èïTÖ=öœ%šŽ¬³7oÞkk9Æêçµg8!ÝÎ×1)ò˜³0 #§¹ZwÓ#q]×§×½ç#0uXÖ¾Zû±Þ¼×sæUP/¯¾Z×{^uû ™îíÌ‹ æÝûž]ÐÝ|ï¹\Öm.›»W!Yï¼óSýk¹Ö>ÞWçËŸ‹iUÕ.vÅ<Ç’åìÆåéí3Ažqñ Mß° *Mß° ²à¾7>14ý¸x—æøös_ÛßÏÏjگƥˆõÌèY5r½a5Õ}Ó[ÿ´¿ç÷¹Þs5­«ÔÇþݲ>ÈdžÕTµýüc2XÝózÉÓ2Â[ú§ r‹e‚ÜRò¹ÕÒ³}²$Ƚ8‰%Èy{äVK_z ·”zìóÜæàMƒ59An±´›#ü8È-%÷íÛƒžÁÌ2î¥G r>V rKš=£˜e‚œ—› ç-Nó'È-–ûbû˜«Ÿ>$È-µ?k¿ä–rGA°rÇøô!AÎÓ$ÈÍ4vìc¦9g-åË•Ÿ;­®‰rטÓ% ë'Éy§’ä–ÆôýÛ¼Þ¿]iPr¢œ—œ(ç¹å¼äD¹%×d¹%Í R£.%Ê-YîûÓ…D¹ÅòlŸ™aÎÓô\:«*D©^&É­–¾’(·XmÄ,g.¡ª(IÎ W.¡ žG’[,mût !*_óÜß0*Ÿ’ÌÈ#Vcò1ÁƒØ#eØNqäy~¤’Ïgz<ˆ?b™®\J«CÏ5>Ó#AnIÓ.F¼AšÏ:Ir‹¥·Ï“&IΜ ·rE-B‘T±ùªØŽh$•éŸñïHRIîu,;â‘T‚–«iAG@³ôóÓ|D$±rG_çFRœ—’çc›癎\J-Ó¹ô8n)Áø*ÉÝסM„[ò<ç§ù‰p«¥sn0׸—áŸç?÷mm<Γ÷2úÀ7«øæI®gm>èm±´\DÍòlËÐÞ–$ýÓZÄà³cpnÀ’ðfÅ&»-IR÷¶‚ÞËù,sûoD°‘ 7æñc¦Â…IêlóøÄ/ÄÒáTºß•á°yV2=ú%Ã1DŽd¸†ý.’á¸-€2ÜÞR ƒ×6f)ÁÅof7Ž£ÝAróƒ"s§þf²`êoV[ p:’”œR€ÓyàtL'¸H‘X;¸AU©ÀY ópË›?¨ÀÅéÑgþ=83¤g5¤ÇÓ¤)Àéj pVI pÕ/pe˜œ}£WuB€«n@€Ó9Éàªçà,K pÕ3p¥ÓB€³,©ÀY–TàªkSóŸ#.C*pøÂNeJ‚[,cQ%Áyš”à4’à¤g݆gCÎj‡ç–ý\ò@³‘˜ ò›U ùÍ ùÍÓ¤üæÕ¦üæiR~órR~³NC~órÆÚXÈoV.ä7+ò›§Iùm’<ä7vÚ›5Ú›5Ú›[R{³+ íÍËyü*íÍ®´7ϓڛ• íÍrA{sKŠož+Õ7O“ê›[R}³ù õÍÓÜcé7Ô7O‘ê›×Ý÷oûR~sËhŸ ä7Kùm±ä2Yò›]pèožëZïèo6êÐßõ7ÿ½¯K§8« œõœµ œ[n¬ »Ä³¶q)bííùÜÐà¼Dm°γhý÷óéD8« "œÕÎj‚çåàHÚ ˆpž ‡ÒZ]÷óy^B…óÚŸuU€ gs 2œ×=®Ïý n±ŒO ÃY9Ðá< ΧuËøÜ¯âôþ)ÎëÆµ–§õÏ3RœÞí$ÅÙ<ç­XWU7¤8«Rœ•)ÎÚ)Î-çzí ŹåÞ>s RœõZœ§y°®Vš¾ñ¹É4½Û7îõ¹™Z\µ8O±îEjqn9¾YBÙ‚·X^Öußk¨Åy®g[û@-Î-ý^#dƒ•;Æòæ+-ÎrA‹³º!Æ-–±®MãTןİÃÝï«hx|¸#´¸;ön&À1àMÜûà€Ò‚‹·Ë ŠÜ\ž¶Øà”•Ûä¡$¸xý„ö•÷Þ“ž@pïÍ”Jq–%)NŸâæ~ÇüsBÜ{ÏPMK޳Éq–"9.®Ý–ä™YБä¸JŽ‹çdGp\¤H|œ÷Þsè98Î2œçR`r\ü’]rœeHŽ3CrœÕ‘ ÷ÞÄTä¬Ð¹È’ô™§ßãª@`\Œ3Cb\ºûQZŠÄ8K‘Wu&ÅYޤ8Ë‘g)’â,E?ÖŸ#ÛÍ*âT€ Î- q‹e,-ÄÅVÚ r[BœçJˆó\ qnIˆórÚµ¦Hˆó qnIˆsKrœYÀq‹¥g|©ÆY€qš6Â8k 0Î ¾ZþÆ·<`œ§HŒ[,ýÛ¼Ä8/'1ÎÓ$Æ-–žíS.`œ¥™g=ÆyŠc<œ[’ä¼”$9O“$çi’äÜ’$ç¹’äÅ&ɹ%IÎ*J+8N)qœµgå‚ãlÀÁqž&9Î-ÉqVù½>F€q– )ÎÛÒqV{“â<ÍhŸ4 8« g— W•â3Z6ŸÅÒÓÜǧÀ7­­Â7«ê¹¹â3S?>ÉIoÞÞñ¬óðfm¼-–ÁÖ¡-€7Os^Ÿñ¼y®k|šxó\íú¦y–ûìf†Þ¾=×òæ"t³¶Ý,Э ¹y’sÿÜ¡ 7Osµåµ äæiûg¥¹yž§} 7·Œý۾ї·+‘›• r³\ 7½(ŠÜ¬…“Ü<Ïu~†ä¶XúgˆAnöœ¹yûúöíCï?–GÀ­ Npóßû¶Lr[•JnóLç±N$rÛbyÖg=¹ÍKnÇz+Ûj<ÉmÖÀ¾¶wëc’ÔVIm–Ðæl­LÇX&¹¶™òü$*¤¶{ž×Q®’qàM*gá)9ž{õ”µxJ¾²zJ†Áw¼™ž’£S‚§dR8§¤¥HOÉ8c'ùž’fHOÉѱ¿mþŸ¡é&i†t“4CúIš~’fHoŽoÒò“Ìé$©?ÓKÒ =¶ÅK² ÓK²~ÂKÒ )5—^’U¼$û¢µÍß;˜-Ý;*œ$«L8I*K:IÚÏtî(œ$U$Í0تÝ6»U3é#Y9à#i†ñi|$ËÉ2ôcý9>í†$ å&i¸IºexÓËK² p’´Ÿ>Ð1²F‚Ž‘V#-W{>מ‘fg¤å𮑖®‘e¡od—bNçÈ*…Αfw¤•s^ŸöÑ;Ò-ãÓ>zGZxGšåYG‚Þ‘fw¤YàYºGV?éiià i8Hš’nÁbZ%ÃC²ú.’–.’néŸ>ÐGÒ,ð‘4ËøÞ‹t’Ä>gºHVãè"Y…ÐEÒÒÀGÒÒœŸ"IfP=s¡¦Y/¡¦y®TÓj8¡¦]ïSèZ$±›wªi6a¡¦Ù´‚œfrš5rš-Ó삜æ¹RN³¥rš§I9ÍršÝ.SN³›zš—›‚Z]èiö$žf™ §ÙŒ€žfÏ(j5æÐÓÏBÈi±~¾™Í//ä´xyÄ 9-x@œÚ±¤jÚ@N³; rZ<-à:å4kä4ëä4k1ä4¯)å4Èi6µ §Ù‡œæu¥žVW3õ´z· žV·µxÆ®ŽW¿ÅG)¨Õ£‚Z1µšÔ7õ2Ks}ï-êe–z+z>E@,«¥XÆ ãòyB™L?ÇgfS#«Ç52f@Vm @ÆPÇøó^Ÿ\”Æøçö]©‹YÐÅÌ]ÌrA« 4Vi(U9”Æ,Íñ]S«ñ 4fyîïHi ¤.f…>ߺ˜[¾ u1•]Ì~ï› ¾D1KpÜ6üÅ,ÁµYÓ¥ˆY‚û³J3 15]Š˜¥é÷úŠ+†VEPÓ%–†,ÔÂt­¤…U-ÔÂX¬…Ù÷gFÛ´€瑯.ÿäòûù*ÓüÃ0ÇTåã·EZ™ ê€ß­åˆð•})…/'m^-VÖ¹çCÕzL‹•›•%Ë¿:Ì~ìóNþg`úÿõ0?™#{ßæMâ1`>ómΤ¶-3ðW•åñ]²¬% ʲT(kƒ², Êò80,«R±¬%Z ʲ/(Ë#Á°¬JŲ–x1(Ë¢¼ ,ò*Ëú±`ö8'‚÷þóWžf¿þæ¹ô³gׯ?½ßçÙïÌÞß”õ·Âìó}¤üÿ¦[D˜ÿúaÞÄéCÛüÒi]Ço¿„dFÈê×2ÃO2†Üûû@ä:„² K~ |_Ëó#õËÜùòâï{PPé%ñZîüFy_˜/,ù²á„à¸ùRŸ¶÷žÚ»}ˆí=…?:S„ZÁÉÕ»gù€:R~/‘g£r‡‹zûHù½ô¯}Sø»ßEêÊö”ßïcãV†qMá/BJž;,)üÅ J¾3ˆÕ;Ë2ÆÀ_:ãÙuìy|Cœñˆ¸Žiëï>…¿¨»£¦‘Êß;ÅæËýØR~¯¿–TþÔâcKùý~ßÖòÝc;Rù;ò{íkHý=¢‰ç$x-)üø„ûZ¦þ~ž*öžºß}âîkþ~"xvXRù;kþµxËrÞÙƒ{c=øûâká§°]k.(ðñE5µ©üy®Tà=MŸÊßýÞ0©½¼–T N|ò~-cJ÷Å7ÌãH þ½óxÁßžG|ßOöA5E ¢Ùİ-ç”þ"<†oTŸå¦~t„ÖÚ‡ˆ0ò¬u·#ûpAQz-SúsËódªhðVΘ¥ ÎyüÙ¾†‡ÀqnéOSåž©À[¹ç±g4Z'øêÕûØäuHþ8¯ëÓ‡óÞ³jO„ƒß—ku¶–}¸9³ÏçZÆ8Â[_kkzÏ™®+s¦oWïÚN^ŒÍ•¼µïÚ{^‡lÜ•ú»U}gv@Ãw]ûÒØëêÙ|‘ê»~¶óÓô+¥w›0ñð=sH:rõ|ó²Z§ž:›žÂÛ1Ý–¡ OŒ})çÞoN!æ:Î¥ñTš­ï8Vô¸S|· M½–a»S|÷rZ:ÓT‹ïß½œçþ ÿê»]´{ä{hïú»`Ûî¥OmǬéÛöñ¹MÛñdÔšv^ÙV»2Îa]™v¥3Õu?|Ô0Wªï6¡ÛsàQƒŸƒó›ÅöõùÕR{·™úlûç"<©½['÷|8hïûÅÁ{ÎýóœyNÜÇšQ!­®ô5õ’ÓÙôÚµ§åš<émj#õ¤»©›þ¦ž&=N­S=ÅwÍžN§Ö…žâ»Í‘žn§Ö©~¶¥}=ÝNí"ôßy•zúêgÈŸésêUöÓ‡ M¯Sµžn§6#ýNmúŒt<õ4ûºzŒãæ*„çì8ÏÐŽtAµA©¹ÛŒûæc-©¹»åù®¤š{]´‘ž¨Þžq¬·è¹…/jõòý›˜åž[º£V)ç–þ¨õ0x-cãs;±’²Ÿç–.©žë>¸R1Í=Ö1~—@¬¤•æÉ•ÔÊéÇÚ‡Ž•´,ðLÕ|`Ú3;ïëcæ îcÍÏÔjÍŽWc½_½KôþéÃ~}VÒs¿Ûú6pîmŽ(ß‚Î==S½î+)ßÏ==S½&x¦ê]“ëèé™j×óØoÓ¼åÎã8ù¨d®síÁ‘ž©Öš3Ö<ðM­+ÅÏÕ«#S­çü˜ÁyüWcÈû3Æ>õ»Ñs?Áï ¾B@Ÿ¿ èBð«ˆ-¿.e°ùá”áO~уàgÑ~~®t‚ßþçÓ¡Ù‡‰’{ʇ‡üm:tûx–&Xø]〛¸Ï {ê‡UÏ€h Q–šØwÅCìtìóšûfÍÏľYÕŽ’ò–"âIïIPßáÌ;90šOK°cOñ¤ƒ/¨ïŠ6mÀ5hö']A}¯åÈ@/hö¯¥åz“Ô·¤fÒKØgí›Ø7Û‡w¯Ä>k1°ÏZ ì[ZüÜß>ô”­5cûöaôO’ûËžúâ™Çi“ûCÏŸé¢ì»Âñ$¿û˽±áú}µ.±o±@¿7Kß¾=€„o–q³cßb —-k_bßb9®Oû¦¥òÎTÍr¥Øh–;ÅÆ“.ÓÀ¾Õ2Ö!NêóNPòÍ2ŽÏïÔñUHBŸ â×0$ó­–¼ «ÛÉ|Kšëú¦¹Sx¬n'ó-––Úcu;˜oùÝS~tKÿtj¾ I|Þº z¾[R¬ö^ôÍržì-×'ÅÕ9EУ ¾YÚùéÁyß-©?š¥ßŸi”èç–D¿™ ¬µõÏ,Oò[,Çz¹“üVËó™åI~‹2¿5¦mœåL¥ßÒ<÷· ûÍ2RЬ¡¸!÷—%Èoù½ß{.ªf9žO’ü¼çI~Kšk|¦I’Ÿ·¸Aò7Ës|&zƒîo–¾>„ÿ²$ü­–ñ™&PÝùß,çþyÚ$üÙÄIöóæ=ðO5 TݲÎô.ªf“ªU /U·ôO:<ÌOU³ÀÀ-XVÙ©~®?á©j9àPIà­Z†ö½ ;ÜUÍU·ôoûá±Zi\V+̀Ϫ¥Ù×qð]Uó¼ÊïUË€JÖ2À  pb5óŽì€«5u|îÀ‰~–è·¤€#«YàÉê–±N _5ä·$¹¥?7À™µ ϵ í¤¾åçXf˜Ï ‰|ÞŒ¾¬nëÄò-–óú¦/«[Æ:y€|‹¥-íÝŸýÇÇÐ?£¿Ã“µ’À‘U†Ä½ÅЗ¹ØsœX«š`½õwÿ4=Yo±ÜŸ5”2ûbù¬¡”7Ù˜¿qF*_¼oN{w¸ÂBî‚ÌgN§Ì^¨;Xê@°qƧ¦Ì~©}‘ùÞG9å/È|ïâS¢^FGmÅ‘)óE§!Aæ‹r eAæ‹ÇiRæ{ “)ó¥̯– !óŽ@–ÌÃë¸ç…@å;º *_¼ª|^Uª|‘ ç«Aå{—<­*Ÿ§I•ïè<]3U>¯)U>O‘*_øú°RäsCïÜbGïÜÚC¯j¢ÈwtìR—ÈW½L‘ϧÈgU§ÆWͥƨhÐøj¨ñÕSãóæ¥È÷®PÒÃRä{—>WG‘¯š‘/F"?G¤Èg#‘Ï‘Ϫ†Èç¥ÈçI‘Ï-)òYcRã󯤯WS„ŸÏÆoj|Ëï¼—«\h|nIo± vº*4>h|ž&5>»¾Ðø¼Å©ñy9©ñyíãXú /&h•¥ÆgåBã³ ÏÓã3ÆÐø<Íuq&¡WÐø¬ÅÐø¬…Ðø¬çSã³IÏËMÏ®4¾šø,$>k0$>Ë”"Ÿ• ‘Ï‹¹>)Räóbïûs¯Bê‹>A³‡ÔçiRê³Æ¤Òg÷Kâž?' ôY(}vßAéó\ǹ¦H¥o±dÌñ¾Ñ¿J_<ÏᘥÏ.Pú¼5©ôyšTú¼®TúÜ’JßbyÖ%)•>›²PúÂW (}Öb(}V.”>/'•>O“JŸõJŸçJ¥ÏÛ—JŸ×þŒŸ6÷gM‘bŸ:Ä>«bŸ•±ï…¦Œ ±ÏËI±ÏÓœƒ}ÀxAìsË}±Ú^®«VN›Ë~çãjŸ§èXW«Å©öyšÑyP7Ô¾HCm/Õ>·¤Úgå@í³öLµÏS\XY56Pû@ì³’!öYÉû¬ˆ}žæÜ×RRìó)öyšûì:@ìó4)öy‹Ÿ{Ió'1jŠúbGàX¨/Ø…úö›ºcR_…P"õYÐPŸ…Ïõ½5r;¨ooÚ ê«@i¤>·4„áÑyb ¾xQÆVPŸ×…@“ï#’ؤ¾ðö¿êSŒMQŸõa|ãLû*ر¯"û,аÏzìcPQŸ 2¨ÏyRŸ7¦¢Ü‘ú4ÌWõúªý„>·qÇàH„¾ªšÐWA–úª)„¾ àEê«àf¤>o߃wMR_ ©Ïëq§öú¬vPŸ[„¸3Ëâ’Øg½Ú/…Ã"Þq§ÖìŒ5y||;Ýò5Iî³ÑÙ¿±&É}–ëØ>wbrŸÕî³öû¬Wà>« Üç5]q§yîó4M!îXWû„¸#÷y‹+àd7î[~NtXÀ}n©p“´qÇ`aä>k ¸Ï-îçÊuBÜ‘ûÜÒÚg”'÷y)!îÌ‚w¼åÉ}vçüܲBÜü¬ä‹á&+×y~®Ãu-’Ÿ—Âp“eIòÛÛ Õ1Úd%Ið«Ç*ÉÏ“äWÅü,ÀOÁ ~‘æ2OO‘àgÅ2Ö¤: î³$ 5©û¼\„š´šû¬˜~|7¶õyNê³NNê³<ÿ‡»wÙÕW²õú~ŠÝ¬jœ„DJ”ôÇ6°ŸÁvÃU@5üþ0ƒ1.Á™¹rï, ã´ÖúcRÔ•—#‚êsµ€¾bHæ+†Ž1U† CªÎ â+·â+!ɤ É{õZ‘e²\íûäc‚W.x¯Þ+Ç€÷|"à^=)&]$i¯²û öꉰ‹h)“°WÏ4~\rª—cUݧFVõRiÕ‡üÁzåɼL¬®£Àzqý8™ZÝõ¬ü’å¦W× €õj¦X÷¹‘_²Ôû(Ïzßh¯ÖÃLë¶ Õºí•2À½òHîÕcnÝ÷ Ü«er½”A~Ér&$]/ä—,ä]¯–‡Ï˜53óºË äî!™Ï%È|Õ‚ìëå¤_/e]÷Iè«e½”A v½=R_-ƒ$ìåìI}µÌÛ~üþ~^±» ¨¯œÔ·Y¾ý['õÕ2˜  ±ë=úª‰ØËQãÚK {µä€:è¼Lê«äb÷Q ¾r&P_9 Ô–ÝųÕÏýdb/%’úª¹Øýü@}õú‹½œû¹·2æF¤7›\¬½Ò«sðVvÐÙ"½{ˆ’@zwô훾7fONLÒ[cjIÒ ÙNEzc¶m†&éÛª`’ÞöMÒÄ1ÞxNûw®)vÃAzãUä@/vÝÀžf½ñrË:‚Þx톙 –MÞ‹­9H—œ7>:ê‘óFLWqÉyÕ’ ÷âm€^Œ–N »™1€0Aï9@˜ ã)Õ±d½ç¸8%ê=óÉ%ê=óö{õæ¼[\%Á.W!%ñJß[‘ìiYúÞ|} â‹O÷™ ð•2øf-/  _±@à+GAà+ç†Àç£(ðÍ+~6Ô+÷@…oÞ'}*—ÂWJ@áó™¨ð ¾r>_1¾bÂW®_µ<|Æ´@âó]Qâ‹k•ø|5”ø|Å”ø|5”ø|&J|å(H|~Ÿ”øJ=øªåûñPâ+e ñ•³¨·…Ϩð¹Z*|¾<*|ÕòýxÄTøJ(|¾<*|å((|óþ/P¾rÔó㊡ðé¦(ð•C ðÙB…¯X ðż•è÷ò-@½ƒÂW‚Âç§• Ÿ¯Ž Ÿ?,*|Å…¯Ô…o½·`¾z$¾r.H|þD)ñé¨ðù¨ðÍSôj%Pø|"*|¥(|rL‘ÂWŽ‚ÂçO‚ _© Ÿ?*|kè^|¥âïgCLÏ·@Ï™Ÿ»( |å(|î®)ðù‚)ðùj(ðùMQà+e ðùQPàÓ›J}¯œúž+¡¾çË£¾çSSßó‰¨ïùÓ¢¾Wj†¾ç³SßÓåQÞóó£¼ç"co¨î•Z¡î•;€ºWîꞪ¥¸çŠ)îù Š{¾mŠ{ƒ3"ˆ{¾Š{þŠ(î•c îùb í•AÜógDuÏAܳÚžOMmÏO†âžo2Å=Ÿ‡â^±@ÜsÛ¦¸ç†@q¯œéÖ˜ºÅóEDøÕ½r1÷ü=Pß+—}MúžîZúž^Šô=U+Ï•@ß+E ïé ‘¾§!ÏÕ@ßÓåJß+è{j;Ð÷ô4¥ï•‹¾g õ=×K}ÏõPß+e ïé‘Kß›£èƒ°<è{¥è{z»Ò÷øv!ï•÷Ô•KÞóÓ£¼W.òž/òž/†òžë¡¼ç³SÞ+–%ï•Zú»æ’÷Ê1÷Šò^ðÏ FT_ ä=¾ª’'Ç€w¬=Wê6-sðÖøýò]ÿÒsÎj>8íx ίîߊÿflªFšƒÿ¦ŠÀ}Sš§Ý7½· Ý7‹³&Ü7éxIïMûf¦÷fñÕ¤÷&½ì½I¯¹oÒ1AÞ›ò¤÷f9èúáebïÍC`ïÍrÔ— v‰“÷&½Aè½I{oÚ»”Þ›ò¦‘û¦é¿)úo–2ôß´…þ›v«¤ÿ¦-¿òßt-tàt:pÚóלÅ]óøáu%N9—ÉSeäÀi =8íŸÙÞíúäÁiMzpÍã‡G•<8]=8}}ôàtºpËóÃkM.œ:»\8mIN#N—  §®F.œ.CN[èÂi ]8}.ºpºŒ]8éæINŸR^s$à·? ^qˆ¤ §-tá´….œªG.œ¶Ð…ÓG]×Ï2tát^)CN}]páÔ—#NCN×KN•‘§- <;)ɇS_ Ï~WD<»)Á‰S×KÄ+õÞj‹,Ä“¯–|8Õðʩߎcòá´%}8UÍŸøpÚò×>œ,AN[ìÃÉ3чӖ_úpÚ%„ççùkN» ñ\O"ž=æäÃiOK žk!âé’ðüÌIxvú+.œtê¤ §OÂsÅ¿ôàô}Ãӕ|?†V{pÚ‡’œª—„W,ôà´„Wê¡§- <Åòà´ï%¯Ô<ª÷¯¸œñŠ“'¯8˜~ï[ ã¹9pÊgÒþ›òè|9; ¿fÿáÏ Äó–ÿ¦kâù®å¿i_Ì_:pòAñÊ Ø“.’ößÄõ‘ñìÉ N— §¼(x~šòßTºoúÌôß´‹'8urà”w)8]Äœ¬˜œvoLN¾’ê¹^ñ™¤ '¥ »pºZºpÚ©Ó.œ´Ð‡³X2novؤ3î "÷®G¨¸B÷fó¸ Ý!v¯”@ðž-ŒÞ+DïUKFï¹fFï•2ˆÞ+Dï•£½W,ˆÞ+–±_1Ã÷J Äï â÷Š|®‡|Õòþ¸Æð ‚øŠ¥£Ä½ñùÜ â+eÄçwÇ ¾RA|Å‚ >žû/$Ù±?çìžöÍrc›lHY€ÀøŽmÛ[ž‡òÑŸóPÖ$úsžÈw%wNª€ðå\û}ÿ[qå<½'\9O¦o’+ç©mTèÊyzs¸ržÚ4%]9[ÿéÊÙ¼ \9wÞ+gã$rålöû„RÝŠ —¾' Ñžòä,EàÉé"ðä,EàÉÙ,.ONÍ’åÉÙ-“SW'gÎØ¿rwæŒw ƒ3çœ">ºf9sÆk#ÀjYΜóqpG8s–pæì’áËÙ™sP¾œ.WÎR®œÉ|íÊ9ïr€”àÊÙÙòäÊYÊÀ•Óõ¤+§ÏDWÎR \9ý<éÊYÊÀ•³ÔWÎΞB®œr –+g)WÎR\9}.ºrúÝ¥+g)WN¿ºr–2pålCº!\9ý´èÊÉOVžœ~ôälÚœŽœþèÈé"€¿RËòãÔg/?Nß"ý8ý`èÇYÊÀ³”g§ß‚ü8ý™Ó³XàÇYê'û4¹qªÏ‚§ú'¹qžô&çÉÍ¡äÆ©ÎSnœ¾)ºqúòèÆé÷D7N?sºqú§gû±aK}ètãT$7ÎöcÖÕ_üÕzàÇ©~W~œ‘<Â9Û»w¦#çÁ½äÈy4í—¹9¦þ”#g©žœÇ«=@áÉ©|q\9‹®œåLpå,5Õ³\|9˹àËyÜÚϾœ>Wúrº}9K 8sújèÍé3ѳÔN_1ý9ýÔéÏy\Ú9¥xtÒ)îœåò–;çñh#Q¸s üE}Ó²ÕÈŒ_dÀvXøs–zþj™„¿¨çÜàïø? ö;>­°€ýêÉÇ·—Hø+•$ûŸ–À~õÌÉ~¥:tjvDö+GÑ¡óP$0:&ëÛýâbzG^JÀ›³T‘äWŠ$øÅÕÊuóøyý‰~‘µíÙB÷ÊÕý\1}9}Ó‹üÊ-ƒüª%ѯ<^úr ئ/§¿L°_y`¿r1‰~A5t,Mö+÷ö«—“ìóÜAÖ;j ²ß¢¥ þtj²Ÿ'ÙÏ×KöóMö+Õ$úÕs§¼çÖDyÏwIyOŸHª{1iº¨ö­5²Û|›§¸ç/„âž_Žxšp1„¸W-99.wq¯Ü6ĽZ&Žò„—ºW§ºWÏ”êžĽò"!î•SCÜ+7q¯<-ˆ{¥ˆ{>ÕÒöüð íÕZSÚ+G¤²WîˆIM\K {åЃ“­«&ýé_[Pë¤72Ñ9é,[ÒŸ_W’þ Ì2éÏïÏ KM²³Ÿãß‹¥$ì¹Ú·öÒr]²”º`+uÉRëZ™dKMù»Ö–ZKþ.uÜGîÍYž-¥ØJM²Ôºö÷Uß`­k;õ}ý—'#Š9êüô¶lD‘@(ò€÷w™aœa¨GöíöëÌE³Àl·ã_úŸ×pÿY>£‰‰þè+ëoy7¿zÆÈ鸥/ʺjÊ¡¬kK9„ºJ)Ôµ§/B]%åêª)‡X—K±®-}ê*)‡PWM9ĺ\Šumé‹PWI9„ºjb"ÖåR¬ë?“˜¨Çòôó?Jb¢¢ÇýÃ~íwýëßÿ¤ÜJý²‡ø—˜¨ÏQi~ÿ¿ILôTÇügõØPxå|ZiTjÇ€‘7Vgc¿êŽÝûûwcs6î<Ñ<ÖuçsÊÈ©À×¢½äû¿…ƒ¹Œú÷®!¾ÏyÉ…2¹nuÍÉ!6ôþ¾Lhÿs®ƒÙe˜Úæ:Ö:ÉÍs?ÎëÈu«xa¹X;-‹—0p¹rõ4n8~Í^iþ~’q¹nõÄ´ùeñr¬â¾¸š±x9èæNóp9z_(òì!xÁïÂåw ]Þ—IБõ :™·k§;|ÅpD8Ì9Ú@™\¸ŠËÉÀƒk"ôü=ßS>ôëÌe«X3¨¥/\žÐ„tõ³¬iö;ßO.[\³Õ¬{¸¨]g®[½Z®Þ‹{˜# Ï W±gyC™wáòJ]žøü.LJsà¾EÌïìùryæjǬ7À)Ý™®v.bþvP¢-bþNæý™–EÌßÁ4JW님c5úÁQ¹r«Ú7,÷"æ ©Žzråêk ºÂƒ+ÞCc˜ÐÕbéêkøó»h9V«Sw¸Z®[½‘ ¬©ÕtˆGÞsÝêý˜Oêêç™7ÀìQÓ²€ù;œrõµ$Xo»÷Ì‘/¼_gÞÀñ5Ó°xù;¹ëÄ5{ˆøÍò¯>0GzøŽJžEÌ‘õÆ1ÏBæHÙš±HWÏe«zSßbæw¥óÕ«V+?kƒe!óJ<Ÿ÷tåªUùÌç›[wà ¼rݪ¼¦yö8›<\W.Z•¯êº2GÏvâ±s¤p=pêñäèá]Ï/áÚ\×Ûò^èš×õy Ì‘0-O>afãºîãΗ‡Ü¹fõÌ5¯îˆ‹k¹<:®«¯1Á½Û·½µ;¬Ê£»¯Ì¡¥äâüuç‚Uh2¹¸pÝcs쌟òÌu?j¹;-‹˜Ëãï™­àÅÙ¿ëÇ+GËÖ•ëZW®Å=\O.~_ãù {åÑÖT)ö¢QI_È;)ß–…Ìßl™'*¾2ÇWŸÃÑ5rͪ¼‚1Îl¤'ÆŸ"µGÛ½—ÈE«z}ß™¯ X¦%Û`¤ãÈ«‰è±^ßÝœdÚ"æò€Ÿöf7£õô‘w Ç÷\=ÛAÇŠóüÏl¸Þç^#jìŒ;`wÞžçóô| 4œdtðòp—Ï»FÔ/r¨£ž\¶*5¿GÏ{x؇½¹nµYÖˆZÞÔ›+WñùaD}ûþɾ¹nUžð»¾—;Ò2àŠcœ\CW®wä:Õû`HeÖÁiÁÊÕîëͼ¢õŠ? ©7t½ëKQ7,èÖ¾\º ­ó„ï¼·Z¾\¹*ÏøKQ7ºKt?_®\ÕZRÕ-]ê—KWn0_ »ñ™à˜\¸Š'Œ¡ñK]·|I_êºå ”uëå…¬ë~ï>RÖõk¹”uý9NKާj@÷‘²®{ÔûÈ•+Œ`öUf æëÛ?ôûH]×/á>ƵŸ)e]$Óòæõ1‡Ð}¤°ë·ºÞ:KX«£˜¤#Vj!aAjÅûL]×£î’ažÚO,)i¿…³cHe7{Ÿ×¨ßð}¦®[náL]7˜%µ„ ,× ±¶Çyk·±6 Þæ4÷ùå€:_×ÀQ)ëÆÐ’¢ÅYr@=‘jñn©êzP»[ËñTóˆiy÷Jú½Hk¯â5 !íãÝrr\JQ×õÚ¬¸o7ÝRÔ-wÐRÔõp·ã)sïÜ-EÝR¦s–œSß=DÝòJú™cª¯¦§¨7•1Î+ÏjLùCW¤e©ÏÇ hs ^cêÓTœ)UÝ×G¶@M+§%TM&âdKÖáî)êúyöo=…?¾¥ òAz«qáAÓ¶:!‘yo%‡Ú‚nú]ùBÙAJ.0_<,Z‚ùÞøÈ€Ë—'¬'ó]:õ¾éË£ôC`¾+<@P’Ì7;»W$–ÌwÌN"ÀÉ|É.ËÈçõn"ß‚pœÕCE^›(‘Ï¡JD¾¹1ÙòõØ/„—Ì7gÖ¼Á|KWá%óÅ|EùæƒùÆÁL¾D¾9É3ùî&ˆYÈ7æç›òÅ|ì¦%³O@¾A ùF ó°$òØjG%ò… ¤òŤ hä‹ÉÈ1‰/æ!c#¾qÓÉ/‰ï9(Ç“ø¼‰YI|ÏmRKâs>‰ï™Wù‚“øžKS1ß;‡ÌA|OÌ(`Iâ{.M ñ•…@_äï’ePÏE$óEòl`,™o~$–d¾H 6UÉ|k9à•ÌWpÌÝ:(0™/tN̳}octmBß;?°ìú}ïÅ8"AßÁŒÆ„¾'VuP/ oRêô͉ÉKÆ;r&F=žÔWîÔWpÔWI@}ïG¾¤¾2Ãö½—Z°/´Z|8Ä>£ ±oL¾Lì‹{@ó%öi˜"ö­)$ŽJì+sP`ßûÑ÷„äWjNò3`ýÂïC‰D¿P AcI~±XðÐòý¶0À¯,üâZp)à¾Âྂ¥/Vpèä$î+ðµ¸ïàVâ>ãÁoÎ²Þ üÊÃ#øq–bî;È à¾òdÈ}~+ä¾HÜGüþVÈ}‘kg"÷¹ ¸Ïì+Àìó*¹Ï#ð3jüæU¢¹ü4'ø•šøÍWŒÞPà§›$øy½àOÁÕ€ûf·û‚9É}¢or¡Ï`Cè›m[Ч•Š„¾R) oÞÆCKBŸ_6 ¯<@ßÙ† }Ö}ßü.ðž}å(BŸ ™Ðwkt!ô=êáú¼j"è»ØUúbj“0_Ä€¦Èç÷Fäó“ óùIúbë¢úæ‹ÃÀñKè›c=1¡/¶AúôZ}z ‚¾Øãhè‹™€Ð'ŽôÍ÷•# /Ò[×}'€¾ù¬rðôÍëÛ¡o\Ä7BßlÀÄ@@ßÅ-k}ñ=íÐçs“ú\3©ÏwEêý7T èóãJèóÃ"ôͯ±Ãè›=Y~{‚>õ⾇C¾¸OK¢â>.ûf5˜ØçŠÉ}~6ä>5pŸ/ܧOܧS“û´(îó«#÷ J=â>ß¹/f¢¸bqŸÚ‹¸Om ÜçgNîs½ä¾pA™ä>÷ä>µ(bŸ»ab_4øw'?­Ù‰üÔMˆüüÌI~¾ÍD?­¾‰þü©‘þ\/é½ù_ÉQ$\½Fá¿÷Ñ࿘7ÝUó›I—Ó˧žpªØ4¿pŒî•ÿÊÒÒüæçC±Ê½z©ùÝ'ŠÉsÊÂù,5¿9` [Þ·”j~wú!Þ1JÀ²4¿&é8nÍ€ÏP÷KÍo~‹›€µL ·“è7-T@€ÏŧCŒù5æ<ýb*N0E¿9à’Ë‚{(»Qô£oD¿ù€eýæÓ"kBô+b"D¿!í•¢_Œù Dˆ~Ÿà¢_9;D¿ðÐÅBôô¬M|_xΓ_zìÍO* °*‡Ôü¸ÂC,—GÍ/WZˆƒ ¡Þ÷êÌϵÍx)ùy ú+*ð¯,tKò³TɯëõSò+J$¿HL ìX ÔÜ’ŸçÒü°¸ÉOý¼$?O·HêHIå6Ae’ úóŸ4?«ÔüKú»µ6BúÓdJªŸgž¤?—IúÓTJô7¯Ò éïVwDÙ¯Ôú‹­«mÀ¿R²_ì;¾ãßìYñ6‰Ccâß§nŽø§Ù•ðo2ßÙ¯”ÿ½\ÿ­~~€‘Ó-  ¿ùX_ò`Òß«¥9Òß¼(,þÊQ‹þ4«ýùêH¾kÒ_©ôWÊÿ4'þ–þ½Z€$ºf ß PÏ&ПЯ’èWIô'A,§ºý@ €±þ®úù…ýH €ŸV?Ÿpþó»$ÿùÔÀR 02?RãK|µ8K$œÿ^ú‘þ ›‚þÊy€CËÂ?~œ¢¿WBé¯Z’þæGO9ô§''úÓ{ý  èoö&xôÇ{ü•þb C¨/7Ãû¹ÐOý ÐO­_è§ïYèQ ÷€~ór?Ê{9žF Î.ø©?ûùá‘ýŒ¦É~㘓žeÀ~¾o²ßœ,;û•šÁ~¥ àχð÷ÑÝMðçz_-øûš$>ÀŸ¾MÁ_ÌewÕovXF ýù“þôº ¥௜ ð§^Cðç &üùëKøóMþŠð§‹!û±i ýüðÈ~ïOɯZÀ~¾'²ŸÏô+— ôûšÈ…~êU„~ª„äç–äÇ…Ü”›Èrß›@TÜ‹)õ†{oܰ .žãÃÖÀ½Ùý_Uî+±n½N·6âž3!÷V€ê†{sŽJY ¸W-‰{×}É3qoÎÎÛh/¦oßF{óÎé›°wßrÿìÝMž…€½ûÑB`ï¾Ä€½Ñ¹Ùa/Ä3Ì;{#†÷Mî­I„ƒÜ§í² {1­Ùå>ï… ¹oð–ÀzO£XNÖ+rXï¡gi‚ÞsHXè=ƒK—༧K5çÅÜÎ qíØ8/fîžk`z†hSê{5Á•Ô'îè…¾…¥VJ}ó#Â=ô KSê³ÞF©Ï,MÖ;. { {…gìÅ<k”ú.‹•ð÷ÿÎë”§&`ïÔêµ>-`ïíú¤©õÝ’°©õué´Ôú¬‚Që».)Kë‹íè7Ïr ½â£JOKšÔú¬ìQë›×÷lž!¹ õAßLH}Ñ@\ƒÔç ”Ô×%Û-©¯Èƒú$gQé ®Áµö¬_Ré³û1•¾âò™´÷¾ åíU—ÏTú¬¥ö¬pQèÓF²ž}X©óÉ9VžôŸ±ÎÇí ÄzE³ëÙÏ™¬g…¬÷~Œâ·Ò§N‚JßìW¾]é³2µX¯xs“õŠ®—¬ç»–ÐÇ»éÅ Ý9“ôÊ»–Ð'Ѥ3wÜ%H¯¬õ$éùeƒôêõ‚ôì@ Ò+Ÿ+IÏn× ½r}D½¢Ù%ë=“¬WêIÖ+O˜¬æy=‹õj-`½RK²^¼K,,’õìÖ+k\d½9ÀPwLÖ 1X¯¸ ƒõÊÓë•/ ¬Í~ öÊÓì•öØ«eàâù2|D.ž¥ \<ç(ƒÖ@Ïùìâ)íYjŸ\Y {òì]îÄbØîáé5žENžýu {v¾&ìÙ÷€°ç>òž— |n¬>¯²ø,Ý'ð—IŸJˆøä+â“6.ⳋ‰Ï¾l$>{’øìGâ‹ïeòÙÏ’Èg>2_©Ì'¹?ññ´g2Ÿ¿;yÊ’̧žA̧¶IæSW䳑OLrŸâˆ|îÒ…|Å)õÝÃ&D|~ ¾rO$>y²ø\ yÏ/wñžã5Ä{~và=÷ â=û ‚÷êµ€÷ü |nÍ>?qŸe|Å‘2¯\sŸÖâ |åL¾RKÿ1® ù|5@>÷³B¾Rf´ß¶þšÈg%2_¹+2_¹æ¯•É„ÂE] ˜/†²wc>=ô?ÊLdUïDf"q^ç¤X²ÞIWzÉzý–CæX^“ŸJ$ç]CivÁyñ`±•8oͯöP¾‡;IóF³†P¾Ï!wÉye΋¼>Ïzöµc$ßÁùÙâ<øç:ŠO Â(>‡®òÞy®sãÜOCa|Wº¤èyÍ0>Ï´Æ÷ü€<¿]B^™-fßÓä‹™”WF…ñ½BŤ¼ÞFEÏ„AEï1rBÑ܇¤W¦y ãÓP¬0>i: ãSÍÆ'Ÿ**zžÝRÑó0«(>¹ÇQÑ»‚©(>ÍÆ¨èÙ/ˆQ|gç̪ž=™þ8ŠOØOIÏ£9%½"ÅýÑ€’ž¾(éy²AIÏKü”ôJ=ôäKDE¯Dä-IÏk÷”ôì7FIO‹ØRôØp(èYˆ£ § êy– ¨çéÚ(çy¡žržßõ‘ä<62ËyRo-ç•2Ôópb°JŠyV:“íê“‘˜§»¶ÛJPÌßvµ©äù,’òt%’òºïÀuþ:%åñçG¨ãýñô< âùF âéõQÄ“æH =LM@dŽ;b¾qÜ¡ÍTÀq³âÖ)à8ï{·8® NþÍq÷ÙU&9.v¾¤ê—7bÿSì­ñ'vŽ„@Ž‹À0øã 9ä¸G p\ ÇȽkÖe¸úÖ{ƒåÞëeÔ_¢\Yý&ÊŽñ{~:’å¼òš(Wú¢\Ù¼"QnÄæ†XCÊ•€wêuMõ$Ê•]RÊãdþ,¢\AD¹›&Rl»¯=š#Ini\ÉÅþ‡GÕì®`X wE—@°\ ·,t M 7_FÚÈÕßIr1 QÔK’ÃnéiÉL9È%ÉÕ3%É]Ñ£‚i’ä®õÉÑ’[ÞǾËfy®ý÷‚¹­–7·¼/–ÜÏ&Yn ¾˜²&ËÕŠ“åj5ÉrWôá“å6Ëb¹Ýòæ-œp9Y0·ý^0wÅÐGOËsõa%ÍÕš8w}ëË]†EsWôu l[8wE¦²¶pnY¨Æ%Ï•wž‹ÖA¯Éä¹ðniôØ|ó÷³ñ\ÎU–!q®|6À¹òÙçÂro8 p.6i¶Ø¼ã0&γ}öM² æ¶À¹5u*±yÑ¢îm[–èËvÍh˜ÄÄä¹° Ïó)>[t^l"¶  ‹N`º°PK¢³Ã‰.æv˜ƒèÂr—ð¼èkÁT tGüèª%®ZèbÖÍ=óˆxÒM´‹mðw «eè6Ë:µ4z]ÌM÷è¼jI¢ ™[ “€’èJ|8ˆîhC0]-’L·öݶe©_X=¤ÈÝ?J$ÕÅîÿ¤±¤º8æÛ¶e9BÆß4»Z&©îèòÕÅQ P]”áÖ(Iuå(P]LîI‡ …‹¥÷ºâK¬«%ë¢ÌFuÅPwDP/1¼¡¨.öñÅò¨.Ž¢+(2m¸ ¨n³ä~Â]N‘çþ› ×—¯Èe0ÝÑ2]XŽéŽù4Î-<¯Z°™ð´P L¦ vj[xÞfÉAõRØùb:ÿ&Ó—`Ljq uÕ’P§í4uÕ’PùlævÂÅ’PÛ+_êêƒ»­`/aþLœ;ö½XŽÙGpû“d¹Íòþ,“,òT²\-“:]-“,W-×ú-w>°\µ$Ëm–7oà‘‡g uÕ’,wÌћޤÉr›%÷m*[²\µ$ÌÅ[Øan³¼ùû?%ÌUKÂ\µääxÍ‘·Yª%a®ZæÂòmΙ›%‡ÓbI­®XÀsÇ-Ê^ZÝö;‡ÓÙʰ&¤«–dº°ÐÑ2™®Z’é"wʹ…æUK2ÝfÉá´X’ëÂ26­®–ùÖ™®ß6²+‡íª›ÞÞ¿’wȾšKü¯ìw ªƒ¯æÅG¾š7ÏÎÝ8oJ$D¿ãAYn̲ú®MÁóÎï$¿c00À/¶ ç6'È!sÉ àé):wÞD>kæÊ%øõ‹®¥Ú˜å£×Ø¿ëàüÜçs¿²; À/ö%æ%øÞ¶ üÂT–5D­Ô@WîËòSÃ{>M~ó]Û’àWv] 𻯢حAê~?ª}Yš‚•gàwœÇp[–û•!we95¶pW–¡Ô¸+Ë©UF(xŻ۲Øùtßøä–ð¾"rßøä1à]¹¯Š‡PðŠO+¼˜láò à•-]¹+K“¿ÜRðÆãB¸jzŸ îÊbçXnËâÝ^ âE™»‚ßý ÉÜ–¥ý..ÏN:ñž[ð•^d»·°¼(rY"^Ý#&E¼xܧ"ž÷Çã®,Þæ2ž·±¢Œ‘¥O¿;ösêŒÔ{ÓéW·©½8}T‚_ÔücW–¦å‹~åèªyÐ1à÷Œ²ó&bÈ1.WM;ÌÒUÓNµtÕtÅØ“Å;ê€ûÊfC”ñŠ&WMÇÏ.î‹Zè. _Íàµû—{o¶ße¼aXĦ,+gÚ”ÅN¶ôÕl·êIì‹ 8:újÚá˜BžBÑá«éÍsÀ}1çÆšðÕœ}/=&á¬é' î+îÙTò¬°Ð[ÓôÖ|™NÞšÞg_q ·f97•<ÅSÑ[sž '¿Ò—Ð[óV§ð+›EÒ[ÓßÕDŠÊK'òšx(ò"ÍxNW¯xðÿþ?­Tx³3¥åßd îÉGøüÉq.Å2õ¸¿xè ïÆ^Î`Ëìý®T&iã9þ½Xb2ѲTä±O­K–Rl¥.Y\W$èŒ~¡Ü¹,®‹6×e‹ëú¯Jô3g%ñ\b0œ½äÊÂ|(Ý©wºsóŒG¹y~Qàú—ñ«™¼ãròžß} ç¹\¿ý ýýwŸU|0c ;µ«ê!P´îªh¨U¹«ª¥TU ùJU0lU©ª*¥TÕ}¯íe] [U*¤ªJ)UŒÒJMù{«ˆETËü³ŸFhk}öÔ‘ÈuNÕäì¹þ Ýνýñ9{~÷ü"gO?êûãœ=üYýAΞ¢³úûïº?êšþþGíﺫ?þj_ן¼˜,Î÷ïâ¿ÅK‰gã…ô9Ætq½ÿù_Ãë¼]ã_þû¿ ίø_þ—õˆÔ9ÿ«þú¿ÍÆ9Ãóÿò÷ýo1{FÓóú뙃BnœÃfŒstÜ3ugê+sÐø‡Iƒf¹HYF5–TA}¯¥t1ë ÿðog ºþ‰,A‘|ð®d¶”O tNZø—'ÆG>ß9¨¶X³D&òÈäFÃ(‰oGt,±­çšOD:çù¶VÊÀ4ć0¦åâ2ìy/ᬯõ¿,ãÀ,ãð‘ϱ¶!›†SÊóYõȸ›“Ã3‚<çÕÄ¢\NhÏys^Ð#Ç-2´kÝïð(['os~~Î2#Ö(×ü åžŸÓr@?h!ÉÎ.gÄUd™¶:¤kc¹‚ÕúŠwí¾È +¸w”qÂà˜_÷àS$ÛœýÚ„–iáܹ˜^÷gþ!—ˆÚœ¥·(òP(náw†…òwÄßÏ+íAŸëá´H"4‹Ä²2³m®•ð‰œŒs.>Á,C‰¡Ÿkð¾ÖAr!9²GßÚ¹ÇZŸeN&{°%öóù°_w¬0Õzæ4½Eÿ{+«äœ¦èŇö…ëí÷÷fÈ'¦×«BWߢ[.„ÇúbtnQ,Œ0$–zMmÔ"¸G°)¼EÖ´¢±Â°gzAÊS£H|bXŠ9@”y¤ú¯íúšàBÑ¢Ëë+Ë+kfÕ#@‡ -^k_Æ}[ƒ‘úšì“À׈·â©nFk틹›K´ÖuÔC—Ëøè»ó¨Ü±+{Ñ&ÿËÅ«œéŽ Ù»a¹ô²[ÿl]ÑX#%'Ë÷Rûš,ç„z¬ì ý;¹ßü=Vâ»jyÖþ[=r’7çé-¾¾›ÙIïp“Æ—…}D3t­¯•‡u±3z4V%#®/ëÆ:M¸kÝW­y´åÓ>­¯oôŒÞ½¯]lîðå©RF÷úüùÅ"ý»z¬$=¶ÔKŸƒñ¬`ú¾V¹²–ù ëóãZvˆ¨eÂÃq•Ѐ">j5Vž;v\m5VSδ¬ýôûZ®HK»³­æ‡ÿÌj5Ô€ÀuæØÜa5Ô— Ì#êj5Ôª_×ËÙ«¡¾ìÅbÄÕPsKì– Þl©/²Ü¯äh '¼×bÝ|µÔÓŽóM×ÐRm,¯–ƒÉzK±È—M•õ¼!ŒÚÆÂ²¡9Ÿ°,)}@ìmµÔ“d_Á‘y®±vÆëk£¥eíOYË„;s´Uás\ýj«lqñÑT=¯g««©j1$ ¯¦šo9,çX½@»Úªú›Z´Ã\‘ŽÝWW[Õ `IJ¬¶ªî&⇲±²»ùrƒÏÒ|Ã!3+Û|8Ï¿è9rðoËö”¾äËÕ©ËyO_Ž«êKZø—žÀrjáÒu¼åÜ-œ¨¢©–£ZŽ«êŒÛòÅ©O«…gH|¢ >ká.Ðïò^Z(¸o¶±å2ÒŽq¢­^¹ö=-9®ªÕµãÉqu-k~Ëòb`Øö´d,¨?þ¶|t[ù´[¤í^•­jN1:ë“(ÛΆ•ílZ0°¾˜nµ9Žf{qo=ÁóZâg-sc`åô´``½òzFެl!mö Ù^?ìÉÚfãË{åÆÓ€¡Õ–ÏCëBÆÖ ­IIì}-é¾iyÐ^Ñ[k[ÙªæT‘cë‘­]Ú+ßp›ÃÐý”fÕÞרÊñwÎÑÚ«Ž[ÙhÚš![=ï…ËmÆV}‚íÃØªsõc­ê†Zä­ÍËSÍ9p6X´éiÀહw®OJ?­_]Ù¨[¤*ùÎúmÏÙl6X[FŽ®ÅòäèZ,ïr\ÝЦåC“=s¼mýËÑU½Î|W6Ù¥_×s9ºú ¯óE“å]\-GWשS¾Ú\WŽ®êc¦e ¯šÑ´ëÎá•N ÿ9«áÉÁU]W»rÙ·ZÞ\5i×—ƒ«/æ>rtU7ÙÂãájµžûÌѵ”i9ÀÆ]®‡uwŒ¯jh÷ì©V{U ¾/Œ¯fæwŒñUŸí=r|U+Zëwýjï'Xž^ágüO' ^«O)(oÛPpí:¶ÆšDÁ™R°á±ÚÚ†,m¡`{#¦.Il1Œ¦ü lÑŽRû ¶Ø<6׬Á‚-ôåòÁ‚míf–5ƒc<ÉÈ‚Zà Ú“,xÄ òË1+Ɔ¼s²`Œ9Í' †x,xÆ'–” <&D@Áèxs¦H E#Ýœ‚sB (ºCæ·›SG¢àœwÀœ,8{$}€ÛÁ‡C ý"§dÁùÅb6I œÛZÙ/(ØÁ!Pp¶]¦ü Fÿ& `t¼@S `ˆI×`ÁvçúP0n—{¬+üH>„Ìä€ÕÂ9 ~H9`µïU6¥°Úª¾°`<ØN?”5`EOG°Ö®w †˜ro0ØO¼o²`¼ nf›ãÕüްà(6ì¦ýDÁx…T)s¸ê±.H·Ñ5\õy»ÜŽ%‡+ßP04™ocÁðŽ¡L²†«å.ÃÝ ×påÌXdÁë 9gc€r ­À‚ý䬞,ØÛA±,Ø/Ñ,X0¾B¤ ÚBì§²dÁ+.i ÆØ›sx²`¿BXpV„©5X°À‚ñ5ßc7 K~J„Á~sŠ0÷™ÀMŒôó«% F3ÉvGŒ¹AªÆ¤Á°tðaŽW¡™åÒi0d¶ä8ð y°¼+<è‡C\ÓdFð`Ÿx”~¼àÁï’ÀɃýæz€0¼\þ!ú aŸg<ˆ „á5•ß$Д@X,˜¥¾G Œ‰SÞ9°X„Ñó$`Ë+OŒgŒ"àÁþЇ’<½ ÄB¿ah—¹®J ìy½ Á.0$ ö9KO~ Æ;ȧGŒ©`¶yÒ`¨S –¤A¿Ò`XrMƒ4¸¦‹+0ØŽ9„Á°¤?>i0\×r`'ö§ý–”Œw¹:Ñ`¶Él€A´(ØÃ‡*2QÐ%@‚ºZ’ ž”H0ö#MäƇ—3O‚`9 ŸÙ›GûýòLA=L`”I % @P/E ¨S X,Aß'APß™@P= APO‹Øç#90“ã;/XNô‰Èúè‚jƒÁ8ÕØ@°Ô,GÙÅÑe}ÉxàÀ8èõa\eS 8P-W¨nM¨îQè£À®˜èjÀѱäm’³µ Ë€Àr ЗBT'!ôƒ òD @?p`ŸßA.]ý|I€> ÐG‘ýrI€Å’èöOôÇôõ‘Ý¢ˆ€þÔÈ€ndÀ5­Ì+–2`@·C2 "º1cÐ:ÒÔð#T÷B,EÀ€¾ 2`”4 tŸDôã®\¦y1/ÇTŒÞ%10|¯¾)‚Ïû¿l…ÿfE0E.ó[®¨«êQ5'#êT‚ÀpÍf ׫tnAàÇiAà¼KlËAŒ‡ŸÕõ‰cÜÝÁ>ïJ LJªàBŒX*# Ô* ä—$|/´…èj6uW„À‡™ P­Nèƒ.CôÕ.ëõ(Å‚ËB nB¨F$ ôQ¤@=dQ -¤À—{]1)ðeŽ9R ‹U¯(P‰m!ª ¾Üj@è2¤@[H¶m!ª çç á’h 1Pˆ0ÐWH Ô¹„ì.‚ºsƒ Ÿ:AÐE‚ê— ‚¢3‚ OMt »I‘ nJ$ÈîL øqà‡EL“`ì[’šIÐeˆ‚¼`Ì‚ü’ ÚDRh K4ÈïÍ4ˆÎÂ4ÈGlägkÔA„A0´ê± ê òݙߞ fAB²PßšQPEH‚.B´$È×mt  ‹¼?W£ ,BAºPÐeΣ«Q£—QÐeˆ‚Í‚>Š,è£È‚üÒÍ‚lˆfAݺXÐ5“}dAEÔë êädA½_± _žhPŸ‰h Ú4¨Ë ê¦Dƒ>Š4¨‡# ôõõ„²U€Pgº S!» ¡:!'B[„®†@È Š3!Ç<¡ž»€P}…€­\<è"äAuJâA½s¡-B÷B[„Zzjµ„@Èåñ Kü£äBbÀcMM FÈEbX"`_M‰a@À!RFw%p(†/ò0¢¨ŸÍ)4:/$0z¦\&F@O*DÀóá:(аˆf@ÀóãÐFŒ¿ŒÛ!ÏL*ßûÃ+tE˜o‘£c¼«'87l1ÚWœ=.$`9H0Ž:6l'œ  ‚¾‚ ï“$èË! º€ ï èË#–ZË©‚å €`© èSƒýøÈ¶}nr OEô©ÈÅ,õ€K=à@??r ? r`9*9°Œ/2¡X à@÷ä@Æä@äÀpH"ÚÕXŽú™’‹XŽVKr`±€ýi“ýaýÜÉ®‡èëºÿ êÛúÔäÀbN Á: 9°XÀÅ,õ€ËÕ€ýyãEÀ ¨W#TÍAݸ@P5 yçâÀRMr`;’J…í81™ʳF¨OIèóõh„ÅòÑÕF×ÔÛªbr "V †WWT),en¯|ž$ÁRs’ ï$X*NôKµGW¾&‚`±œ]Q 9ÐÕËAà@}kâ@u8âÀb¹9ºê¨ÁÑU5Ž®^§GW]ÏËÑ•— ô³!ú³º1Ðïè—@ ô©É:51Ð/ŠXêú Á¡Uõ‚‹X-ûÐ*ô‹è«!ª2  ‰€~TDÀjÉ‘Õç °œXÊ‹X,‡V\ ÐEH€þŒˆ€~zDÀxQ›"è7G, ïX,I€åj@€~Z Àb`¸.-”kHØ×ëü)öž:50vq8 û>,»3p2ðäd(àÇ …ÊiŠÔg?RŸÅžœ•“ú®Æà6R_ì_©Ôw úú‘úSHê»^n‰Aê»:Ê‘úâÍoÐwŸ ù ôÝíÅ( è»;œ±È|÷%™ÌwßÁ|÷-•ÌwìJEä‹a÷þŒ!×q‰|÷# È߈ Èw¿J ä[Éœ òå˜tˆÑ$ñÝŸ¨ÄW, ¾#ï³õ ˜CR±$ñ­]ÒA|¥š$¾qtíx—cÒ8ðH⇶ ñ­mÝ ôå˜Û­íÄ7ή\<9(“~Ì$¾qr‡G"ß8¹w$‘oÇß ñƽI|±sÓ³ùŽy÷ÞYcÒhò‰o¥Æ>.9(9€•Ä;@=50ŠpÃÉÕXK‰¾0h#üÕZ‹ÀçZÀ{c /Rð^9¼WÊ€÷FçŠy/Ø+—_È{‘–yýØÂªoÂ_””¼§ƒˆ{ö%îŽm‰{£c“ â^9poÌ™ä¹Ä½R¸7.†À÷ЏÕ\[$`)Þ ô:ðÞ˜m«oº_X «÷b3¯ìnÈ{ãzРÉ{ÅÞ+G÷ʹÀ{‘/àØx¯X’÷ÆìÉ(æ°T*NÞ+Ç€÷|5ä½8( ¸OèÜ[;&:÷V:ƒ ÷ÆM—tâ^©¸e×Ü+e€{#üáóz€{k3Ä ÷Êõ÷¢žw“ýÆÞ‹ÖŽˆFðÞÊàž”Þã¥Ó%xO» ø¢ ¼,|å(_±øÆìPÏ-Ðg'ð•2¾r®¾r€¯”ÀWŽñ•ƒ@|¶ø|Å$>WLäsÍD¾RÈ–±…VK"ßx0“ò•2@¾(Ó bxµÈ7žó·-°ò¹ˆOŸƒ÷lHÜsĽ(ñn¸çc€{¾Câ^©¸W,à½ñ4ú‰‚÷Â’ä½ñl°ÇŸ@=ü$çùprÞx îˆóŠ W,IzÅÒ«–T¹¡†H—Ì+€y1ÖÂ5˜ÇCÀxåêÁx¶òüÈy~ô„¼µ=íûWêåù’òJPž/˜”WjNÊ+—Ê+%å•ëå lQíôC îû:ÒÉ«ó¤½:K ^÷½wÕó<  #ûƲk1ØrKDöÍQèëedß›\c²k±ß'x‘}1 Ãs >ËðV9o]-"ìÊõì¦åCPÀ®Å¸ŽÈ¹»eùªKgµ$ÙUK’]­y‘]­8Ñ®ZÚ­c^ˆwëÔzíª%ٮņGe»e¹+Ûm–5üTK²Ýz{g•óª%Ù®¼aÀ]-“pWkN¸«–„»Í²†Ÿr w-ǫ̈^ŰЮ<  ]±íª%Ñ®ÏØ`&Ù®Z’í6˛Ֆd»bÛUK²ÝfYƒQµ$ÛUK²]µ$Û-K./íª%Ù®Z’íªe±Ýfx³µÚ²Ø®’íŠl·Y4WYîª%á®Zî6˃æ*KÂ]Œ]ÐçwÕ’p·Y4WYîª%án³`ÝÔ–ƒ«,€»j99¸Ê€ñÕ–†Èy:ÆW[.Œ¯Å‚ñÕ–›ã«,ƒã«,X[>´YY^°ùóãèZ#ûüsA~žTïÒ§ŸÃ)~æXz×X>ý¼1Šæ¯!tÛÌE? žøùbäÄÏÃ&b̼+¯égš~6 •ü‰qò®Œ¦Ÿ húycxäOŒwqÉÔ¯Ãâ]œ1ý #â]Ý0[l¥–[r€Åª[®V ‡CY‡CY:‡CY.‡¶,«–›Ã¡,ƒÃ¡-ey8Êòr@”åãˆh ‡DZǪáä˜(KØhÇDY:ÇDY.މ׾5Ëfá˜(Ëà˜(ËÃ1Q–$²ÍÂ1Q–cbÏU¢Yµœmá˜(Kã˜(Kǘ(ÃÅ1ÑŒ‰2Üeey8&ÚÂ1Q–—c¢,ÇDZh›…c¢,'ÇDYÇDY:ÇD[^4OY.މ²Üemà˜(˃1Q†—c",%.Ò¾ì Çê™w¼ØA3.6í¾`@`ÞI‡FèsÞÙ„úÜñqO^™¡J%³É+“(0ï`Ø“¼2C<Úô¹•,–Ô纰{'ô¹ØÆ<1ÈsŽ”Sf…›&œ2.rRžk6l¡Sæà2»œ2¿¦ [ÒeäÅj¥óbÊÁ)Sûw(0¯q«9eÆ4`ÛªÓ;o(0ï<¸&ó´û…óZg¤#ónì·¦À¼@·m«Nž:.ovÙGe¸²áƒó®›:#ó´%€"ó´Có´W‚Bó´ ƒBó7ÈÐ<6*4OÑqŒÌÓΊÌSX›Bó´Có”ú“¡yº>‡æñãWhžb®›G×'ç1¸†ÝuÈ‘SÁy „@ý30< È;çéì Îcð¶ƒó,Åà<Å„Q¡‹çvïÁyºbJt¥ ƒóÈà¼/=›§"Åæ}ö¿<êƒàAHtñpàáÈØ<Å)*6Oõ(8OõP£»Ž.™ö€Fç× Ø<Å^26á܎ͳE±yŒ¬ulÞ©ý;_ÅѶM£óQŠÍSŒŸbók[có ì16Oq€ŠÍsÔcó6éØóØSH¡‹D‚é±§È<ß#ó>y™24ﳓ&F×ï§K¦ºlÇæ}ÈÅ,‰.ö(?¶ ;ÕßI¢»,ƒ;8Ïõ@¢+e ѱ¿£B›Ÿ¿§>ÕTèÊC¡ãêèb”ÍÝ&)ÐEª8ˆfèJtq&øRB +GA +e Ð]'B=$Ð ºHK—[\P ÓÐ$.ʤw%ô¹ëìpÀ„>w˜6JŸ‹MùSë¥@w:¡DE¾‚„«È¹íÖYŠ@£ÓÅP£+õB£ómS£Ó-Q¢óÛ¥Dç{¢DÕ|[`^¹uºJu~À”ê|S”êüh(ÕùTêüV(ÕÉÝŽR])©.ÎxmN™qycÛ¨E{úK­‹YÞYy°ž ‚ë¡`ç³S°óÙ)ØùÍP°+GA°+5C°óÙ)Øù™R°Óc‡^/ïÝô:¿NèuåDÐëôJ‚¡9±?ö +åÝ}–œ´ÔDA¿>Î¥Xæ?—`hyÛÝ5ˆ-NäC›³‰ØâD>=2¶š¬È–Rl¥.Y\×ÊÄùÖdE¶¸.Ú\—-ÿÕ †"îÏå¿2ÁУìç­üoüß™M~ÿ-¬9cE°ä}ùù]ųFZˆU9w«ª¹ƒX•K¡ªZHU5æRU͹ƒT•J±ªRHU)wª*¹ƒT•J±ªRHU1{jrö UÄ2¬ç¯' ì?báóˆCÿLgõ÷ßu;Ô5ýý?ÚŸÝÕ´¿¯ë/§ö‰üu‘·ìÿ»Ì>³åÖ#ÿÃæ8è·9ÿåµÑé}Ú?Nï3\$AlÏ»VløM/ Ûð®Uµ¾¶U¾s‘®·ÌÍÑ#õözsk/ݶöîÊ%¥Ü87šâÕXäíØù6#–sÿ]Ãæ×þ»GKWüµÍÀÚªvÍüü-ûJïÎäsò±<'×î°}9Ä#{òÚò6æ~XyK¿áùŒ]‹s í*¾§kŬƵFµÜ³^쎻¶¶›wùÌk¸Òð¬IBRt\Gl‚¾˜3f~ωbÉÄÌï™3À¼”À”eúÈ…´œòE™ýÖ ¦~ÏÀ&óú׌¥?2¿ö«¯,ýÉIá²|™åÀ¼i>Úµb6û#>ˆHŠ~¯4ipÄ^{%AarŸiY9œ¸§_±ðe.ìÇ=‡È+³ \ðcÛ¹R+0ÿÏ4|™ZùVæ#¬Âó˜žÓ›9-¾2³³«ô»È‚‚H‹iùåÄ·u÷‘½î€çS¿cÝgd2Ÿü¸"^"3+ gÊ—xŸ’÷¤ßcdf¦;˜Ÿ@ÇNíHKÐïùts§vl¼‚!r§öŒóX‘™X='6kwü5È­@‚ãr>po%&OÅp£}äóë-[õ/ñ÷öÆòË¿98M›å/ßà•³ˆ¹R—¯k´UíÝ¿üÃÆ(ûÜOË›9‹Nd¤š`yƯ<ož<¼e¡|UO¬û¼µÌ!+ûGωòlkóéŠÄB©Ýß’ßi¶ƒ•atò&ž¾öû^ùsÖÕ<±mxɧ3[S[mUÉ}zìI–4Ó𬶪ÌRýyÖϬ ²ãÄsÃùvZ¾ÕPK•ß³ª-oìx–ì@³3k™­H—þsϺXhk2p>%ËP\jÌV”×îp«¡2éÈ´|ÙPg×úe=÷ȆÊAënWCeê¡ÕHVC}Zzl­&‘éŠkeãyëç¹VCUë‰óö¬¤™­ˆ}cäjÉ (È&Ò#›ì6¸Îùyï³$7é+cܨõ^­QTý‹ný)™&ÏžuPÏ >oi˜ü;íF_9‘ß<Ó“ef#Ït 7F€ï[ÎÆNpÇÈüH\rkôêJä;ûnL ™qaABiØ×‘æcÍ?V+=0Ž\Ç} ³Zÿ´¼h¥È rÅh›­ô๟ŽÌbØ[ü:ÞSÕELKŽ©Ê–1Ç–;à×í}Cf1ôW$0ŒVºRiybt-õœíFf1ôW$:x®z…çudº"¤™†ÙOd¹ïÌ~"ÃÈ1U)+æØw”/bþÌ1U©æ®óÍ1uå•Ï2_Ž©ï‰©iÉ152š¯ÆrEPåjªq6WËU€¾ò«¯ÛŽÝ;VS½ÌqEšƒÕT¯ ¸ZÇÊîê ñrµTö W»×š§Û÷´|{K½"CÁj©ºÑö`He®+dÇ·4 iÀÊt)ž%ËÏš®–жqÅÆýÙP‘èŠ÷3U‘, *3l]½c@e£›PÌ ŽˆÉnªWHŒ«©rø¼b+ÛL-¦ |0 Ë«¶ºî2ö‹:¯’ åŠåßlªH‰pÅâj6UŒËW,DÞ%;Ê‹3_}XW[j©¤ç€Z-/2¡—¸bvºe›ލÈKt]#GTå.º"˜4Û*rúÌ™FTõbDu™Øë=|9¢êuÞT]àêèV$Sv—3Ý-T÷@÷ì¥Î¯öR÷Õ~4Õû>~;Kr£iÈ!ÕÝͽå"»î§!K¦¿Óò!­ûˆûÍQU9€®ˆ%}ÏÚ׌\É/GEhæS’^ˆº,†Lf®ÉÑ…™UL†QÝ.xKî£+¢¸®«öø„´Ú©ÞI„’ô« —W„¼etœo#*‡Ÿ9¥ÆˆÊ67> ©œ|æÚÁY¾WPÄœ@ üÑë <èŸÍæ#ò ÷Œ«’ß3°&ò{>ì$Mòkqo2[’_‹ÙIÎé~-kâЯ­IÃiÁ~³³‚ÇÙoZ:Iì'?±ßq¦¤$ô;†€è*Ñ™@ô‹An¹2ýbhLvúã¾ÐïL²÷ÅÈt¥ÜwvBÀâ¾[Þû´'™¸O{€‰ûή7â>ín#îc¬¼°¯5¬ û´™°¯uø” ûJÅÀ¾–¯šÌ·Dœ,æS®1ßr“I.óÉa†Ìûsç ™Ì׿Ì4¹Ì®5É€@¾ø’Ž ùÚ…Xf!]~D|-â?ò _¬}àD ¾ðÐÉoÄ'ï_|Ø_Ö âSÖ!_ˆ£ñµW äSR!!_ŒÐ 5 _¸åÒ˜¯}d2_´¡|O`>¥óÉ‘IÐ×>DH ú´º /Ž’HÁ|ñ(pÁ`¾Pž´€ùü(È|Ú7]Ìk®I©d¾>À“0Ÿ™/Ú8ØÐWÊúú‘8–ÈçgEä ¨‘u$òÉñJÈk©Iø ùbŽt‚ñÒ!™‘¨OŠÐ·:ŸD*@ŸÒE ú”ïHЧ|L‚¾pÐʯ‘Ðç‡Iè‹ìPÙæ}1‹*úúù}~˜„¾˜Ø]ÀÀ^jÂÉ„¾RЇç âSî%!_8ºåÓ#òɯMÈ'g81_)æ+e}Êo%èó{!ôE™<9˜O‰©}±D›}¡OkŽd>ùˉùôzÅ|³ßÈ%2BŸÞœ O¹µ}ý|ò5‰ú”aJÔ§'êS>QÓƒ úJ‘‡ë¨O.w úâjîL@_¹@ŸËúârú}qÉ9±%ôù\„>_¡Oß,¡ÏÏÐWN•ÐWjô•"}~À„>½nAŸ¾GAŸ:BAŸ²:úä*èSZ4Aû1ŸZ O}€ ¯Tè‹2ÄÀ-õãÉ}Ñé‚J}êÖ}åT€¾(r¤%©OLè˶,äS×.äSæ7!Ÿ¯–ÈÇJÀ{¾Tòž:ñ^©¼çÇBÞóý÷J=¾R€CÚóö|C¤=_/pÏ—BÜóiˆ{¾âžž-iO]»h/ž;‰px,½6Ú“'±hÏö4~ ö˜æO°çZ{þæI{®†´'ocÑ^©´ç{íÅ'o“´§!8iOj«h¯íiv ÚÓ8/ÚÓLD´§´‰¢½R¸§Dâ½RÀ§ù‹ˆ¯=Ø¢BÄ×^ä’ñ…_x²1‰Ù |6$ïÅœ,ëÈ{œ°÷|h/äÝs£=Íý„{áPž«’¼ìHò÷øbÝ¢Ÿ•ø¾Æˆo6"l+#­OÛ-K닼¡-‚ا,ƒû˜ÑjT­öÁ›MÀ'—<ßìÇ1‹"ñ…7ÒØˆOþ:"¾Ù?å¢2o~|˜ëøÂaéI:ðͯ Æ`¾€žoc¾k€AòÅߓÈ|×+-Èw½ØvAÈe¾ ù®«úD¾pÏ)™ïúøžÈ|±ÙX漕 ä»ÎI‰|áSžS>R_)ê O©žꋾ(WúI}ÑåLÔwŸœU‘ú®ïø­ }Áz@(P_“¯€Ô·ú¯”Ú@}÷)9ØGïØWêöÅÓ:`ÉqªX€}÷ÉÙ-±/œÆ ûÂ)ÿÚ„¾¸»œû´é›°/ŽJ\ öù }~Ä>ß°¯ì+û&±Ï/Øç{ ÷ùÎÉ}þÈ}å(pŸÏEî‹°¨ià¾ëåB ¹Ï-‚ÜÎz`Cp_X²ûVxDUûŠèWJôs+"ú…W³\=?òÑ/^8nèç—Iöó·OösÃ#ûùa‘ýü)‘ý|.²_<ôcc¿RìçCö+Gýü¹‘ýÊõ€ýÊQÉ~ê+ˆ~>7èÏ·@úsµ¤¿bý¹c ýéL„¿r௜ðWÊþ|¤¿8ÕH…ôç7Cú‹¾'¯ôW®ô§ŠEª˜ô§F%ú+E’þ¢m~ýÝÕÒŸÎ-ú+ƒþŠøõ¤àCüSûþ•2À¿rvàŸËÿÔŸÿâìɧĿRøç+$þKâ_5äØêÇü+gþé•'þ©»þ]W§(ü»®‹e€êæ…jõÂ?µá_±4®¶|h­¼òŸ?òŸ¾cñŸÚ¯øÏ_ù¯Ôüptå£ÿÅø˜”üûˆ¦ºþ[¡`+üçcˆ€. ç›H€÷|É9Ý$–2€À(“ )!ðn”® >°T 2Iå… Xª†Ú!Ðeˆ¾` "–ƒ}›ÄÀØ…5Ubàݨ[uSÄÀRX-Z¹á«00&9ï†Å,G55ú(‚ &'AÇÁbª£Fœá]e¿ûäJAPÃb‚ ;yq {r`¸ÛC¤j†#ÔQè2äÀû”öt'j. Ô\E¨™¥8PS q {Qr ûC‚`±$ º¯# –›H¼BcNuóãØÊþ,è^ž,èK>Ë|uÿ iø/·Þªü÷Ütû'ÿÅT´þûèŠ(þ“ô"gO­Í›ÿТ ÿ5ºb’)$íì‰È¤‚K1þuˆG¢¿‹#ú»©ÖÿF§Û&ðïÇ™èïù¨Öþ^úl‰þøÖ€šÿGŸN$øsŸ-„?µ:Â_©‡ô§w+úÓ‹þ0Ñ2üéËüùT„?[ú@Eú¬Eš…ŠþXFôgéÏþl ýñܦ?6;Ó_—7'é÷`úsͤ?EúC/`øsŸ,‚?QþºÜ; >Šð§›üu,ü þº|B ®ðgáÏ–å'WV;}D¹;»Ù «…ý ý<ï"ú ÐO+VB?WLôsÅ ?~å€_©àWÊüb0=R.Lð+—÷rYU–?ÏZI~Z=ùéòH~QËH°ù¹^’_©øâ²ªŽº¸¬ªSü´¼'ôÓ2œÐO«yB¿búy Oô»¾MþÓÏ5 òˆÏ$âóEøL $>3 ‰Ï—Eäó ùJÍ@¾RÈW,@>?\"_9;OkþB>_³‘‰Èç%"_©ÈWÊ\\NU=÷¾œZO'ÿq˜ï€Àç‡Gà+Ðàs_0ŸžÜÀ' "ð¹ €¯@a¾üV |¡%èøæ'J¸ðK¤,€¯|¡e§Hࣶ$à“ %à‹øøg|â_|†kÌýƒ=rë ÿ6È›o.å¤?ùæìNœ¿„<û& ò¸¿ Oqúù½òHy…“ÒÇYªBúÅB…ô1ñŒCúÂ¥qóëTJ‡ôA-uH7'èWXǾ+Ëé;SåvH_ë¿mžO|c+˜÷\ØžÊ}÷ÕÅ}ØXÇ}vù“€¾ç ²æ=1—Ùú¹i2 ïDFô¯} d@_ï„Cô1:Â}qYIQ èkxZ ècè¼ú:#/ÐÇ€ô]t•T@ßE—FôÝØ„Î}ŠÆR@ß}ÃUO}{¢; O[ èt¨TDŸb¸ÈyK$ç9 œ“òcsït08ï}(d‘ó"6,Å.r^)ÐsA/BSD!è9Ü‘ ñù©ôHEÐ ¯ô\X è9f‹ .çpÍdLÃ3Óg ƒú¢¥˜>…_ó¥ Ð ɯ  WŠ F øPè)®A §¸žâzòúè)&A Ç&󹂞£/ zŠdè•2 ½@ª{‹ëûr/¿BzŽâ$é…åØ\Ôw=?¾ï˜Œ÷Í>üDŒ_Žªå0^9÷ÝØÀN–±õ}7v£å (/ÎÎ0¿Wã“Ì3RÞúH·¨¾oޝßÕ¯Aç•2à¼Rœ–XÀyÕãêwc¯HrÞwßXQ ç}76£çUKŽ«®˜ ÷ÝcözÅЋØh‡½¨ùÙ$>ßAï»?,)ôª%Aï: @/Ε— ÎóAD=ßh¯ðK_t(ü:) ¶ð•z|¾<öÙà‹0¥Mâ D?ÆõùäŒësð^lÐݼ÷Å÷²ùz x/,}ã½jAdßìSÇÇȾ vÙ7èŒì{ÒÏ}ãc”Þ:àÁDÔ}O£"ÉÀ>—a`ŸË0°O—¢À>]®ûtqŠìØС}ºmÅö¹÷éܧJâ‹2¹¢Eâ+e@|q=pMâ+Ÿß&ˆ¯\ ˆÏwEâóõ‘ø|‰OM±d쑜w„ VwniÈL­ø½w`“ï1ƒ÷dFtðÞËI?ƒ÷bÖßëÆ--fý ! Þ‹égFQòœT…”×”„”çl¤¼¦d(¤¼jIÊs¢PÞfx‡H–EyN7CÊ«E&åm?ŸÜÄÝ7˜ç\2ä¼Í²z R8ÏùqÈyÕ’œç¬:ä¼ó¾V9¯Z’óª%9o³¬ñhYÒßœWË$çÕ³/ÎÛ Òñ’“óÊçUKr^yà¼jIÎSNb^1$åUCîØæ‡È+¯ WË$äÕ2 yÕ’W,ܵN)}y›åý­æy"äUË‚¼jHÈÛ,/².È’W- yI}ÈxÕð"ç IxÅ€gø®4Kð]µ$ßUKò]µ$ßm–'*Óõðª!¯Zàm†'ª-Ïþ3o³|ȶð0Ì/¯XxÕ’€·Y>d[%¯Zðª%o³|ÙPmIÀ+=¯Zð6ˇt ²,À«†¼bIÀÛ ßžˆ€W- xMÙrx›åÍ–jK^µ$áUK"Þfy÷ DÚß±Xñª%o³¼h«°ñªe!^SÂ2ÞfÉQÕ†ŽaÕ– ê-7FÖbÁÈjËÀÈjËÓ÷ Dä¼Í‚‘Õ–ä¼bçUËɑՖÅyÕÒ8²ÊÒ1²Úr["‚^µÜ÷–ˆ¤W-ϱ~þ͘§ŸïÅÄC3àù'FÓ» xúyb½«×¦~%ÙqN?/Œwìü£&~ ™øù\%ÛàÍ¿¾’mØÆ_`6ý<Ï’lˆ´¦Ÿ Cã]9M?¯³$Ò6¦ü™x¦Ÿ£—dC3ÿ|Ѹòç‹QeÈdÅ&Û,e89 ÊÒ0 ÊÐ9 ÚÂQP–ëÞs‘ɪep´…ã ,Ͻç"”UKBÙfáPH  ¬Zʪ¥q(´…C¡, eÕrq,”å>¶äC¤²jùqÄñÐŽ…²¼ eù8Ò*Û, e99Ê’TÖ”l†T¶Y8v*sIeÕrs,”ep,DrORYµ< ex9Êòa,Ìœ¡„²RPæ"`²bhýöôXœ[~Tfû¨Pi·ÍhtÛú1ï·í¶ÃŽ¢æ‰mÞ%ÎE·xÒrÑÛaȳÓkF!xЧ8ØõÃóÐîšçæxÏm/!Îi—~;aÆpšGÁ ³‰ìè…ÙɧŠÁk¿íN˜ò1K'Ì놫¤cð¨å(ïá~ƒŠÁÜ@£Æàe¬bð^ª;ŠÁs,Ÿbð^â<…é]té;´-?Í|0ŽÁS4bð(æÈÓG)1ôÁT |0OnK Lú3ÛS1erÁtœžbð)GL]°cðà•m̃b±\0u}ŽÁSäžbð¨>9!YrÁ” ­\0õpƒ§ˆ6ú`ÊW1x’¾èƒéÀ=ÆàqW Çàñ¡;OõÒ SޏŽÁÓ©è„ézè„飃§{P Ÿ»œ0EmÎAPŽÁãf%ŽÁK6*x É£ËUJz`:TNxtVžâëè‚郞ê”#eîÚ·Ûô ;úŽí‰²œÏâè;mcr~ –Mi›²œÃÝ|Ççæà;…Ú)øN~ ¾Óæ, ¾ÓQ ¾£êêà;~!ô¿t5оSX0ÏŸ{¯øûpôà耩ïU˜úò~§8¡Êù‘ÊóÔN+Œ¾CLƒ0ð+L5B9`úr~§zè€É£ì€É£ä€yz«8`*–„˜èèŠÿ%ƒcäécèY,𿤱ý/ºáè;oµrüè‘¦ë¡æùsóÇ ÉSõÈSa@rÀ„ë®ý/FÿK ÉÿÒµÀÿÒCÿK[–ÿ¥àÞ+¯I{¯œ éƒ6çgEmίÒÁwÚ¾’Áw|uнÓkQìc£{§ ÅÞÜ“¡wŠ%RèÞŠBïtÛ ½Ó=0ôNŸCïtS½S¤ŽbïtÁнÓM)øÎß)ÊJÁw|6н³cªîI¡wºÅÞ±©:öÎG1öÎÆÞùú{§G¡Ø;^Cïtn…Þ)ÊŠ¡wŠŽRè–Bït1 ½ÓûVìNÍÐ;Q讆¡wzu ½óå(ôîç~›%r¡w<9e9߃"ïÜÆÈ;}мӋqä?%EÞ9ïQSÍ·p{«õq\C>=‡Þé< ½CkqäîÈw cà¢z©Ê•2PåÆFUNcï0U®„ÙÑSŽÐòÃü¸åŽï¸”ïH«À;ùö öx‡AÞwŠÐ•¦Üeå‡ùb«œ’”çŽl˜[Ö‰±ÒÏ=%Ï-5¹Î¯s)–ùÏ%幟k}÷>ƒ-N~C›3pØâä7ce‘­ ~lq]´¹.[J]•yÕ?¶”º`+uÉò_”ç^©î?NÊó»”:™sçRRž_ø Iy~ÿ-Ü+»aÛr¥üü®â‹‰\ˆ{VÖå|;¬«&Üa].źj)ÕÕ˜pGu5gÜQ]*¥ºJ)Õ¥Œ;ª«¤ÜQ]*¥ºJ)ÕŤ;ªÊYwT˨¢¿ž™'b•¾ÙÇüqfžög™yÚŸdæùÝÇð‹Ì<³ÜýGå~dæùãoë÷™yþ™ëï¿ë{þ¨úû~¹?û¬?þr_×_ÎÌIÙîÙÒÿ05Ï|ÿ§ÿû¿+qÎ?ÊÏ3 ÿßÿ:ÿ7Iå+ùvÊŸÿb¦žbü¿®¿©çî±U4î1jCŽ¥È9¯±ê޼™©\Ⱥ#äR¾3;ÉûJGØ.Ÿ‹îïx`¡„àš­Ì‰È¹$p™[.Lw¬ÒQf ¿÷}Å2ÐÁã#ß;vâUà{àˆy_± e^4Ö;"¾ïÂ;–áâ Aw¬Ô1`a­Þ±šÛ>È~ÇbF,&ÜþîÀ×µ$zÀcÀXØ™3;f*ç*“{)ß1IZiÌž3„;b –;L¯iÎ!r1#Œ§ùç ¿úZq¬½iYóÈû¾×*gµÄ*P”™“£¬æ9rêyW§ey¢Õƒbkýk³|}¥b?3ó=bgÀ»Ö2Ž·ôÚ÷ˆ9Ý*ðåò6»êÀ6kóÒÖÝ®Z¿¬v"Ö»çZûB{3î9ïl+ocœ*¿šK@Ïvª±ZשÖÌø±¹Ý³Õ3GÇ»oGÅJÐ[Oþ­‘¾Üäs¬¼Ó‚p;r2õ«^Îs®˜zT[¹Ê©ž~ýöÔëÃdg³|™žNÇÜÏš–"‘cæÌ2GZ2$¦¢¶§þÄ:ÐSßÕ“Þòå¨7>Õ§õË»»œý=צƒåí½s"~öí¨¾R%­Ç¾Øçç­ãª/â• õ¼Zâǽd›í™†ÎUÞLD?¼Ûã W²¾ÞžmU'ú¢V?®•IaC8믖ª×îò÷¨·i‡²©ò Xzꉾ~£¥òÉD×·gžÃoߎŠu w;U8ämÏê‹u o+i¶¯zã_¤‰ÞNõÝh«yųíöòpGt:ÙTmyÐTqqÌn4U<™qLÆZM5b®Îe‰5 ±[´U\Ë8îm•×[¸·­ÈÃ9!‹D6ƒÚRgWseKgZ£ÂÄƦªjbè+Ÿù8M•õ Ê]³“jwyÀÓò­¦z û˜lë õí˜H=¶=­óÆt˜]þˆ”u_ùø&×^h©|ègfd©ç~?´T|#öGyêÓŠíø·†:Úyª¡f‘óC;…J6»ævÊ[hýB;•å:³È›7-/Ú©Nußjñ…è»=ÏØ…~ ªE ªº¼wlítÄ&ôµŽØ—#j^JlI<Û鼿ñGÄ ®Ä4Gˆ‹¡³_n3zLjêã—–w%CŽ×´À|ô‹#*o ßQu5c…µXU¾²âõÀ iDºù­™ŽÈlÔabDÆòÕN}TÔQí„GdÁ¾¶‡›ncêˆÈÕPd¼ŸŒ©º§ÐB[IFlc³ ªsÜÅ z ñß´`PÅ4f\ƒcªNþ,õZ̓1Õ—óbPU5± Tç#¤°^û½Ë6«¡êMÅJÔj¨jP±qÃSÏü{C½{Ž©¢Æ}­1u>cDŒû昪sŽ©æe©-:Ö–G=kL­õ¼×–º²B>[=ßSW=K›3™‘àÁ4cœS1:ŽÑ8¦òÃíË °ê#'ÀúøÇÅ1•gwŽ©œÝNË 0brƈù|L£{ªÚs^ÅA5ã&Æx9¦êbÞ5¨ÎƒZ:*Œñ­QµÅàµÖ­ÆspTea®9ªÚòfk-g èãikXmá¹þd™ð ß:ÈçZÃê<û•A¨Ó²†Õ&ù•>!•ö’òeD0l¶×œ$çÁ¨³ž<ù쥎x¢7”“ñ¼kXø‚•óñ¬$1¬#’_®Öª:Þc}åRÞs «Ë²Àßùav ø;?Ì^çÇ…ÒŸï“øz1Ð øw¾˜Ú ÿâ)·DDðŸl‰ÿÚÁÕò_¤Ó:Óþk‘6.ÙüŠvËzÀíàŠù¯XÀ1í?aYü·ž«Vä¿8UOZ:zy6À¸ïd'ðŸ„ø¯?ùOBü×fg’#?ù¯”ÿµCd lgÆŠÿÚÙ2ªR¨O@$“ã&°œEå›(tÍ@½ ë†‡@Î^€~:ÀÈr¶ñ_œúÛøO‰ÐÄ~¢À–.ý´€-Ö^ó( Ÿ: ЇÏxlà×Ól'¢&…€Qó³!`µ$F}+n‘è'Jl ;…Ë™€€¥^0 ï“ØpÖ@~ ÀrW Àò±ƒÝ`„>;10Îõmè6D ,çJ,·N,õ€‹ØfDzü™Å¥žo;9П9Їè€è‘Û¯ïÃùåõåë—è[ –³ýY}SAî$A$AÜ$Áø¤Ÿd8 ? ŠãkZ®·$A7>`i"$A?e’`©f`„eßO\M6‘„$ý:0$¨½mI‚sœz% zÄ j  F_•5ƒ×ä"ßHpZÞ . žƒ8TšI’àœ2B’=Í žÙbÈÑc}°`xÍ 0z’%ÔÔQxv¤m#zÒJD’LA f›„À5e]2!°öì!öð‘ËïQ>HIx¤ÀEIsjŽ-µH=F›|2‹}GÄÀóꤵ««7v÷"N ¶E"N h‰õ¨ŽÕÕ\tΟoήóA!í—õöðT Ë_Èã#Œ‰ÝùmJ c®Ä±gÇ m09PDNœT¢äÀùÔà2Cì1øæDX-Éš¶×üvsÀB&®¥oÁ@÷Ä@wÃs/ç…ÄÀp|òb€á˜s[ràäÝüæ„‚1"nB`døÌÅ{Ò ÒK‰#-TÞq0FÍwÃK0)ˆ8¨ô\ÂÁ°ä$ž8¨daÂA¥ç*mq°p’*™Yâ Rß •BO8¨ŒhâAe¨*Ížx0S± #¾¤%Å™ÅP,è§IŒÔ\yb° ]ŠË‚•ôM,¨ŸbAå1 *ã˜XÐ,¨”ibA&g# *çPÐo„(¨ÄvBÁÈ™ =QÐõ‚;³É‰• Q$Us•$è““å‘+ôó# *á¨H0žßN‚þ¨I‚ÊçJŒeÁyôøMƒu›A ËåÝ‚J)ô×HTâ? Ro ãÆÀ ‚J¡(TöK`© XŽ*¯¦@Ð- XÆ„7çW uuA=r‘à|S\I‚ÊI),`¤aƒ!‡ªR ¨.@ X®$¨[ *I¥H0bÉÞM Ô·%ôQ$A] APMS h¹>ô™‚Úš’ ¨¤®"Á °"H°T –£@‚å( ;;`¸kM TÒ: ‚ß‚JR ¼2–®€`Džåì” ÈœtâÀð«Îù80 9ï$^ƒ³)p`98°XÀÚÔTè‹!à<jWSq`Üx¾_r`©€“³^r`@PJpäÀ˜F$‘“#ž ,õ€Kp`©¨}WÅaf¸6Žå6±âÀ¨6[ 9Ð7Nô©ÉÌxlèS“µu¬8Ð7Eôå‘ËQàÀRXμî\îúrˆá¿ ‚®˜S¾œgK5À@ XJ€cïìîHR™ç*øSÈMÁÅ€ –‹ÆsÍvGôÇFŒsg£'FÉ–ìT:*1`9 o5?~2`±$FDêçdÀköåÀÍdÀ+Yª0`¹``„¤&Èãq%ë]11°X€J”) ôµI²HÐ×C,e@‚WÇ–B"ÁÀ‰¾Éî†H‚îÞH‚îßH‚‘þ3ÏE‚ÑÇF‚ŒòA"ÌÑõjà'‘àzêºM’`9 $ýH¬ *a`P;" ƒ¬’Ù ƒ×yÑùõOùXü–ÞQqä@æö!ÎYVl €w§3&°ÿpc"öF5J‘!jáÂøB‡žo:}±X+þÃú³ñ¯áÿ¸>hü‹Dór‰ oÀø'DþÍO¸Áþ»ðé™ÿ\†üñ*I`ä¿þ5É7™ùï>YùïF&;óßfgþsò_„-þÍø×bc¯M Œñ>Ycá_èé„íF$ük£ÑyøWÊÿbÏ(rÀ¿8uÛäÀÀgx”‚Ëå™ËØè+šïÉ€¥2à€(KôMu9BÀÁN¨DÊBÀy©] ìJMô©‰€z6B@Ÿèe!àC…˜ X,`@[È€L(mÔÉ%2´0êpûÄR¥ªúŠE€³`¹h¦&@Ÿh°TÚl# ž–´Àç…jLŒ£N_ŽR®‡X,Ô'¹<ú ¥>Øc\Gå·.-Ð×C-PYZàƒ¹Ù¿-rM* PiÉ-ºµ@—¡è2 @ݤµ@¦@–z¨ÚB-©Ô-¾í·£È±`ì<’:‚´@ŸœZà‹Ý8¬2ÿºµ@Õ#-'§ø"7·¥@‰R Ö—,ºVJ*B%ÐE¨rÝÊJ C™¬º •@Õ#%pz¢¨ –¨›’裨ò’%úTU: ž¸t@]0u@WBÐWGP¯I: ÊHÔw$P ùïx8'ÿ)…u@61ë€\”²è2Ô}vê€úŠ¥ê.¤ª It=Ô}®üÎñ5JÔy$ê¾%ªÉ€:d@Ý¥d@×L]”e@µyÉ€.C°X0°ú(Ê€¾BÊ€*#Pe$²ƒ´ è£ ²¿¶ ÈS2 ~Ë€Ž-‘&eÀbÁÐÊqÞ2 çVBÀb6(à¿v‘UÈšŠÿJj€ý¤»%øÏz;ù/TÝ;ü×"ĬòŸf´â?MƒÉv{ ÿYJ'ÿYz• H¯$ñ_xÇ$\QT©€˜´[|>’E@é£Òé9d~T¢?)D¢¿P6ó+!ýYë$ý72%ˆþÎûü¡ËÒ¥ JlX(ý­Ý4þVàÏâ'áïìrõüU œlúwP{%K½„¿Øÿ#cÉ—Óǂ߱|Ã6Þã,¼g¡²ðÞ‹¹‹y«â=)׿½B€à½ÙF“ $ø]ª‡¼÷) O¼G6Ÿf‘"¾AÿQ"Ÿ˜ħ ™ˆ¯ç~løè¨j½©Ïš €/w6ïIï™åÈ{wc¸ y2‡qï#$ ÷^ƹïÛqOsp㞎¢Ü—Ÿ‰qO’%p„#Ü“&cÜÃZ§q¯ F¥ï„×&iO ô'´§‡'ÚÓ Ø´g¶íù(ÒžA´§9ºpÏRqÏ„%ÜãJñ“ØDÜ3r÷ sÀ=> áÙÉ´'f$íY}í}t3íñ.E{òšö8Q1î™§ˆ{zÆ=6—_ãžj ~Ä\áž>bá‰K¸'š'îÙ Ü#: ÷ÈÏ¢=ô'´§w)Ú+–÷‡4/Úsͤ=žÜ°§S ö„m‚=>Ãžà“°§€°§F%Ú#’öP«iO³ÓçU¢=Þ¶i·dØÓô̰GeB°ÇÏܰǧgØSÅ„=8L˜õ4¡ëù¦Èzƒ:‰XOSC±ž®F¬ÇÁžž„`OO‚°§é£h&Úc¯eÜã:–qÏG÷|*âžÏ%܈ö@û†=Ý¥`OOB°§É¬`ÏG‘öT1aOß iO÷$Úc¿!ÚãËìñ{5ìé{lO†=%Øãº‘`ÏÞ‡rú”g¡a, ØãŠõôêÌz”Ìzºd±ž/‡¬ÇÇ'ÔÓÛê ái~æD±žž¸XOWgÖcsë©)˜õØèþŒõ$’õøh„zº¡›ªHOOƤ'ö#ééSé©b“ÞÿÃÝ»îþ’cKBßyŠþØtJy±Ó¶@bbÐ 5O„èŽÄE<>^^k…]{WW54µÔµñ÷=錌uáF ¦—µÀôxp$ÓËfÞíª=.M½ q$z•ÚZ½ ~$z±C“èUÈùAô*5DR½¸vAõê)õeçAõâ& ª÷…dHªgÙ6©OjêÕÐñHõøÖT3˜^ìÏ`zQ¤óPåÒÑ‹9‘éåÒéIP½ÈT/™3©žÍ›ž8U³eP½xªˆƒê™1 ›Cê=/,@ç…Œ4ex¦;]û˜0#]û˜ø$]û˜©%\û")L¸öEn™pí³¼™pÓs×¾ŒGC×>C ºk_ÿð%…Y‹HðøìÎ~Â( ìnCÜ Ý]êÜ—©Hïqz·!݃½· ÆfàwŠ8¿[ˆNïèê='w,n÷XðØGÉ݆ôí§“;EœÜ)âänCšzoäÁ`wŠ8»SÄÙ݆4ôžˆ³;EœÝmÈð@ï‰8»ìð¯sv§eœÝ)âìNk-v§BÝ)b‘Nïq~§ˆó» qtAœß)âüNð» qtAœß-Ä?7€ßiçwZÆ ž–q‚§eœà)²Þ¸º ‹à)àO'xâN艀á)â OgxâNè‚8ÃSÄž"Nñ6¤ãn Ä)ž"NñqŠ·!ý—}NñYO:ÅÛ†;6§xŠ8ÅSÄ9Þ†4ܱ8ÇSÄ9ž"Îñ6¤áŽ ÄYž"Îò6dÄ ƒMgyŠ 6¤¹ŽÓ„óÁûnF 8ËSd±<œåmÈÀȇo§‰4œ¬‰tœ¬‚àdMdàd 4O‘'« é4Äyž"/NÖD NVA:îØ@ªŸ¬ |8Yi~² €“5‘ŽÃ5‘ó50½ Áùš‚¼‚ /‚¼8_YLO‘Âó5Êó5„yQ„'l Gl ÎõÊ~åcÜÊ~ÏG±²_$ú¹ì'Z¡ë~@þÙ-=鲺Ixè~aœºßû =Bê~¡Pø³èðÿŸùo¬ñR÷Kw1ê~‘È „?K7ôm~~¯%`øSÃLÖºŸ] Mö{Ë€+d? ïìº_yºPÃ׎@øëA÷³Øñ×fæfðéå×–ƒºŸ%î¹7á/<#Bø3 èw‹ø9/é/›•gØÎ‡îg¾/׿éW?^mê~v,¾›îW.Få îWÛENè~¥‡7 t¿R>8~Q÷˾ ûÙÉ黚º_d¢îW?†5¡ðùzBù£7Bµ!zÍ?„?;Ç}¼ÐýjC@ZÊ~ŒÌª_d¯ ÕÏ@ U¿ðªŸå@ð[޲Ÿ¥h›ì™BBö“¾\ö³\7??;ùÕÈ3âò‡êWûÁ¢_d ÕÏ’Z å„2:ª~–} @¡úÙÕ.›êg9¢Ê量ŒúCÕÏR݈îé(mýªrÂמ»g\ª~–9alªŸíüGÃ½Èø ú­×WÄ®Wò„ê ªßlŒ‘[ úÙÝì&CTý"õRÈ~Òd¿]È~‘p&d?{æ@a„ì'µ ûEþ²þjg¬A –šÂ]M(üY΋wþ,1—;ÀQø³÷Aÿ†Já/ן½´½J _{e*üÙ#Ûå$ V©oÂ_­›êWŸpéƒê'ý@õ‹'@¨~ö>ëNTý>{¿p] ²_ìâÐý²/ê~¶JWWk’²Ÿ©¡úÙ«*|!ûÕÆ`*ýrx”ý¾›^/ý,Hߌ<#’~è~ß½yøÅ­¢Ÿõãû“¢ßw#…bˆ~öp×-Š~ÕK¹¨ÑÏR·]›èg—Ö Â¨úYXwWѨúå…¢êW?ŸQõ³Ú/ U?ëkSýìLÊg¥JÇŵÇQõ3â² U¿jg¢ÛjBõ³U úÙèúæàW ÂPõ³Zïæà—›ª_µ·-¯ÙÏFõ²_î#ê~¶~îyDݯНÔýª?ð’ ®”~—2ÁuÇ¿ÊeÕ¡ûÙ ßaÏé‡j<›©ûUŸK2AyPø³ã–™þl•e‚òl¡ð—7…¿ÜKþì`€ÉçÀ½1\ üåÃÂ_$× á/Þ&Bø³åB k¶ˆŸù‚ðyrBø“®\ø³£÷Úl<íetþò‰Nå/Ï *ya¨üñh á/72…?KPäÛŸÂ_ä! á/»¢ð'vzøá϶ÿØ„?K©ÁÈ.8X™o)´¿|¸Qûc48ø1ƒ]Hù˜¢ôïH!ýEj¢þê[pSúËË~–Z!ýÅX¨üEÉôï㋪ä j¶ ¶\Ýâ kšõç§µ²‹ücÉ‚š½ñtí ‘LÊC,“‚$’Iyúz³ÞH¶E,ÛJDÚóI\·y–’†üK' jÝÞ.ÛïL¤)ªJ-rÕ/ ü꟫ìˆìA¿UÔ“‰|‘Lä×Û¤ÕgEÕÔ.dž³õ²—ø­ [z#A[z%AZÊBhIËDK‘(Z’ô@l) ±%)-Er hI’±¥(Ä–¤L´Ää@ÑP&b;,Âfþxú K¯Úç[Ïéƒ~Ç쯿zýàyõ×îÖóöÃÝú«–þpê fߨæ9ûÿgê yËJê ùëG©ƒ&Í/#z"í—ê!Ð×X>‹‡ÿIj¡öy€˜…xÏŸÙîeüµQûÔ6¤< ¾#:îDü¸qwÛ|ëôtHYæ[û1c¿·ÏÚö2öIhlH_Fy+ûÑújÐ>û&4´fù ëŽ †í^9­Y0š½Ä|!$‚|kæÊòy‘ÅE&2< }[­É¸Æ³!mÙWÉø,ný£€}ê[»¸ñÕwû(Ô%rzë‹!›éöMhl•že¤•Þo+0Ÿ¥êhÍTjh£óYðV¾ê‘೑¹·W$x†#o}’Ý ~€~M¤¯\|‘S Y˜t†‚÷2Ããèfþ‚¹.׺S³åq/Ï0-óT¿S±OB}CÊÚ ÒüNMd>WÖ:ó¹ÙþíeÌÎIÓu5»·iy"_ÛŠúÊé<ÝÓ%Ûí–Z£ÜÒn¿ü[‘ùŒZ÷*Ç7‘á÷j"óõèšö˾íeêã÷j¶lŸ„úVëk~¯0»I 27D;R³l³è÷*®V¿ì_U–§[üöWV§[´ö¶™©gž7+Û½çSêÞÖ¢lÖ½Œycíeꇛ•ó´X£ãÙÊØg¡¦«c^z}[Ó|[¯Û’Åëþê ÛoWNÔÂ6~º¿úR|†öeN~¿F-^rŸ”ÅÖ(º™ºÙOîmÔ7l±.Ûî2ûãg[ 3cÞîØ¾<¤uk÷ǽٴÌè¸c9@‹›V·2+èXÛgkŒÇÂÅõ¾!“m¿ïV«àlµ™œwlÔ²Ï)ÛjÌ×ܱ¼2oóÃ5‹ôk¿c'â‡k§k “=wl¹pºÆz•§kÌ¡<8]³Öûì¹V‚ òÛMT¹÷"•‡k çÃáš ‹æcº/¡lÃé<\£ÓO÷2‡+×o}!ØVǾèéÚüÛÛgítíõåée O×(Sï¸aQ¦òtåZÔ§k °ñxv<ù„–éy¾¢ÌøŽ_çe^ß,ÊÜ=nX”±C{™÷{Ögñœ±||…‡l4SS¶OY싯‡ìDŽC¶‡lŒÆks0m¹PnÀ¶mÚÊ‚--4{YÞ“Ou‹ÒmMšxºU±å 0étkãÃÁÊ5jû¦kýÙïÑùú°Õ7ÉTKï²=º ¦[ {?–v.«5ÜŒVKu½»[ÑæF›»QiÆáÛb›Õî>*{)Þ“–6`”_¶[}¬”U0ö¯4`"©ŽsØ ±Žt¼cû»½ o7ytkÒmfè¿l§äp“Y)áVrùìxÛ'`·ÑÆïM¯Y† ý@ó˜b\Uã…Ap¼ðŽgÚïz¿#Å ³ø x&þú (^ï00Š×;ܤHñ–¼Q¼°S!Å Ÿöäx—{Ö%Å»Š{D%Å»Ì$)žEmõ2¤x7'Å»oÿ.žï.$¤x7"7'Å»?ÿ´Ÿïvÿïdx÷ Ÿ#ó¸¼kâÁð˜)Þ=Þƒ@½IñhÃïAˆØ¤x>'Å{Û5)^–!ÅóoüJñü:¿{ 7'¿{:V&^–!ÃË2dxÌ• /2<ûð¾Sfº@èØ#ù\Œ™„ÎNÐuš‘ÐE'$tÑø\¨Û$Éç²Eð¹¬>-‚Îeйh“t.Ú$cdsñd.š$™‹ï¶/Éå²Gp¹X(r¹,.—¸\àrÙ¸œ}{ú9~HçV°æ{Sɯžõ¤s+4ó2•!{o³|rNåtneáì^Æù\†à ŸKó{ð¹•MËŸÓ9xãƒËeº2r¹ÆÎY˜s¹¦Ë»—‹À]äriÀO.—aÅÈåÒ÷ž\.ï‘ËmÈ:t2â¹\Æp —ËËärB “¹ôØ'™Ë˜$s‚€Ìe¹ @2—Á!@æ2"É\†Ò ™Ëà$s2+¹ŒPF2—Q¡Éç´çsÚ—ó¹ŒgA>§Cv>—a:Èç¤ø\†« ŸË0äs2÷îaŽ¢çsÒµó9™øœVr>§=;ŸÓfœÏeô ò¹ >D>—ÑSÈç2lùœ¬øœŒ„N'tÒ;]„'!Ÿ“ÅŸ“EŸÓá8Ÿ“åq>§=9Ÿ“ž˨¤sÙé\î$Ò¹\QÒ¹œ%é\ôD6—‹E6—€l.gI6·nWç+`sZËÙœÙÙœtîdN+9™Ë{dNz™ËÇ È\®É\^’9­ädNú™Ó®œÌåS‰d.ïh’¹œ¸œǹœ"NæòD2—Í€ËÉÕ—“+2'ã{ÞmK€ÌÉ”œÍÉÊ€ÍÉàÀæd(ÎærÃ’Íɵ›“JNædïÌÉŠƒÌÉ2€Ìe+’9Y¹ì \N.8TcR sZÆÉœ¬Èœ"ÍOÖè©ã`ÍÝÖXOp9¹&àrÙ ¸œ7ÎÕXp9™5¸\>AIædJ s²æ s² syB’Ìɽ6'Ó›Ó2Nç´ÌˆsÕµ²‹Ç*gåtNv øœ4>'“¡“'–©·!=îSofàLÁ€Ï)rãLyƒÏÉ4ÁçyóXE;Ç*—|N®5nÕ¦*]ŽtNöèœVê8Ucq>¤³ˆç†ó¹ ø´]öâ„N®¬:éà ÔX„NÀ ÖXŒNÅè6ÀÒ¸IZ«º-œÒÉÍi”N‹/J'ÓvJ§À¢tÒ¤s:-±8ôÑÉ4«,N·s-¦n¤N®³“:™§“:íc‘:ÅbuZeàØäqV—ëï¤NÃYÖX´N†é´NzïÐ=â¼Nÿ¾xŒ{ pivºxˆ[ç? ³Åë´Ø&ø;éz’˽ËK¹“Þ&—cæÕärˆJTî- ¤röjá­É½’˜\©Ù@å" 6Ùœù¼°¹»Àdžl.ëÍ™ã÷³Ñ¹p:i†ƒÎå Hç"»PÐ9säkëüØIšK:'}ÎI_ s2fйœéœô:—é\¶:w›7›³%Ð9©ätÎbƒ»ù±c“rålNZ›³ë};S›ËI‘Íeà sí<ÈœŒdNÊ€Ì)Ò}ýrgï s9)’¹¬E2'µ@æ¤Ö»m’9AœÌåÕ%™Ë@2wÛ‹ØFæìZvØ[ú±#c™³%ö$s¹ $s‚€Ìåí@2—}‘Ìå,IærG’ÌI;`sRlÎòc§]`s¹Øœ”p:'}8“*Nçbä`s97°¹,ÐtuÀ夸q9iÞ¹\Ž\.•ËCT."P¹¼¯Aår%Aåâá&—}ÔíI"—v'í9ËY€ÇÉ,œÇE q¹ÎàqYÀi\ö— 'M¬A<>@ãr qÙ…³¸5Xœtá,.k8‰Ë•‰S ëJþ íN˜TÂPÝæÂX.ÜæÂ–+ÜæÂt+ÜæÂž*ÜæÂ+Üæ a†×\ü¦ÓEÏpš£lšNs/_“é4E¢2Š„I¥ ´üäI˶{ÍyØŽämBÛ@hRùâm#M*³ M*³ m*¡Me"´© $l*õG´©|Í÷OÁÛ´m*ßA!Œ6•Y†6•±ÊaS™ Ó¦RZ€B³ÊDhV™Í*¡ ‘0«Œ1§Ye” ³Ê(C³ÊDÞmÀiVÍ*£F˜UŽ]†“µI³Êh&Ì*£V˜UrÓ¬’µÒ¬²‡èF³Ê(f•Q&ì*£LØUF™°«L„v•„]e aWHØU&‹hW7VØUFÚUI»JÞ3iW™ehW)ÈØïX±«ì»—«#v•Q&ì*¡]e"aWHØUFËaWe®’HØUòµ!í*£í*ÙnÚUv•„]e"´«Œ†Ã®2Ê„]e aWµÂ®2Ê„]e aXœ+ +éû+†•„e%—çÙ/yZVFšVF‘0­Œ"aZ™HßïX±­ $l+ ÛÊDh[I$m+ ÛÊ@¶2°„me a[ɵIãJÎ=+ñÜãÊ(CãÊh8Œ+Á@W²•4®LdwlZWæ•l9Í+£Ì›g,°¯ ¤–ãŽMûJši†yetÕŽ#Vì+ ˨5ö#V,,Y$,,£Ès7lšXF™°±Œ2aceêqÄŠ‘e ßqÄŠ‘e ad¹s8í*Œ,‰¤‘%›I#Ë(F–„‘eÔ #Ë(C#ËxÈF–ÑÌw²bdµÂÈ2Ê„•e”¡•%‹„•¥9ý;í, e´³L†–ì4 -£--£--£M-Ø7]˜Zà¦–Ñ M-ù÷0µ €¦–¬¶–aI[Ë(A[Ëhƒ¶–Q‚Æ–Q¢îhl-€±e4IkËhmI ¬-8ŽÐ0· €ö–Q…ö– lÛ0¸Œhphp™@ß—Ðà2¥Áe” Á%JH†ŒâmÔ?ޱ™Ó?®Ñ–*üã:ͶÂ?®Ó+äúûË¥[fl§jô£YYúÇUjyðK€þq¹©Â?®{ê¬ s €Ë àÇLï´^#•TNP9Eü˜TNP9A@åÒ TNP9A@å!•Sd3€Ê âTNP9EüœTNP9A@åñsFP9#2nJ*'¨œ"~Ð$B*'¨œ  rŠøA#È» ˜TN 8•“" rRTNP9©*§ˆŸ2‚€Ê%B*'¨œ"Nå²wR9)*'e@å¤ ¨œ  r‚€Ê *§Hûe›©\nP9)*HP9A@å•‹†ƒÊIP9A@å•SdàŽ TNP9éTNÊ€Ê *—¨\\š rRÄ©œ r‚€ÊåhHåûTNP9A@åé¸c•T.R9E:îØ@@å•ä½÷Ÿwl NårAIå•S¤ãŽ TNP9A@åéûT.ËÊ *§×hTNʯTž¯‰4ܱ|<`i8`è<`ÁÀà K„TNž±Üp9ŽCdN's8™Ëtì‡9ÈœNæ@ö@ú>p9éÃÉœ”p2'%œÌE‰?9'•»ke¹W‹K÷§K²÷Þ7cVÐâòÈÇð[&—é7Òæ²j‚?óž›[¦ªÉås¿tӣݑYà@—>lá@×<’t¥îÒ]æ¼N:ÍŠ]øÔуnΠn&—?ð  ªð ëŒ8tÕóš¦]8F…Rp§ÿý/Ò.œžè?×yYÂ.¼ è?×M;ý磷„ÿ\{~Q²§•è>S ÷9&½N÷¹†ñé>×p&Üçæ1ë Ó{®3JMxÏßWÙ.#§÷Ü|¼Vˆt°ôŒdÞsYfyÏåOzÏíRƒË. .ßu$Õ{-ÝÃñRGç¹ÉrÆfoiµªR=)Îsƒavho™µÂyn0†N8ÏÍv<Ž í-ß 1ßÓyÎŽsX`º½eL‹æ–ïá9—ýÐs.Ö ¶–Ò =çâ Ðu.6m-ß«0*$]çØnºÎ Ä‘cË÷B<Ÿt›kU7cKë¼mÖ–öBŽè$ô󺿉ïœe,Ù}ç¸Vé;—µ`m{ ¬-e„tž›ÏªÇãBÂy.†Îs1u:Ïq½Òy.[µeöÎs±^á<«Îs?Ê© çÆýËfl)|ç¸Òw.ŠÐu.–†¦–ÆyÆî;à ߹˜føÎÅ¢»ïï„0µä~ ×¹˜O¸ÎÅœÃu.–7|çâj‡ï\…¾sÜÄé<7¢ çxÏ¥ó\´LSKÛéþ<œç²çbÌá=}…÷\Œ'¼çbuÂ{.–/¼çx¥è<ó ﹬ﹸNá=ÇGTzÏÅ–÷9>TÓ.¦þs1àðŸ‹i†ÿ\l-ýç² ýçb¹ÂnÖºÝ$“þs1‹ðŸËÞé?ŠðŸ‹{“þs±±Ã.8Ðņ]¬W8ÐÅhÂ.6n8Ðe;t 9-èbxáA“ ºxR„ 8XãÒ„ ],i¸ÐÅÃ…N¬Y‹.tq±Â….Ö‹.tq;† ]6Lº`¸ÐeX]æÃ7|è²súÐÅšÒ‡ŽKJºX?w¡‹Û—>t±vô¡‹)Ó‡.6,è² 8Ñ%'ºìNtÙ œè²—¶!t¢‹™º],èbaxoáD[‰Nt±iéDÂò2ž½ô¡ãZÒ….›\.t9·¼Ì ¦—Ù <èbÖô Ë&Fœ>&zÐÅE:Št±t0½ÌmCº¨ñn EºìtQþs±Çè?à>—ƒ†û\<=é>5à=ÇyK2œñ•oËí0ßÞEÄ#—MkóÓjYEþ±d8÷uÓÒÉ´3Ä2ÇE"™xæ¾,éç³µEDÛrLÛ""mÍ·­mTø-í,DZÁïéD86ݾÈþ(ÎßÍmó•ߟçëÿP"œ_íñ­ð¦š£äÜkk=ëC‘”BK™â-iж”…Ø’–bK‘â†-IŠ›h) EKRŠ-Eж$)n¢¥(-I)¶Ä$7l(“ÜD;,ÍüñD8£ú×âæÁù~+Î÷yp~µ~’g–«?*wäÁùñ†úuœßñìúëùúÑ“ê¯?Ú¬ÇÃë'›õW-ýá<8–Æe¾-þ0 Î\ˆÿ9ÿù?FVš¿—gþ?þbqC'Ÿ•d6¿+ Î÷£48ÿü¦Á_õ/ŸnÝ‘Y:3R©î0¾ö-•þ£óìs+–ùbZýTYÔã±d°Õ« ·ba"›Ñ.·bAÚšÑî—©—óÃ\q7b±'^ã‰ÐË{´ù:½BW#]åhæ(±õÞ*ÌW阺»Ì<£ë~}®â»žF2•Ž6g`_>¯â_ ‡…‘~¼Ä2aÍbVPýsìœózÛ´o+_М󵞌Ñh¿W“Ȱ8&}]ÊË?‹Î%YCx=Bê˜4Ë^5¬=_™Éjì]äºð¥uLŽà£f“­†[ëŒù‚ëƒFÀë 4twäaÆ4÷ÖÉxüqîéŠç‘i‹+ˆôÜÅ…1X<æâ:€õª™ ZÚsý]ŠgDãoKm©Ë8êðeäç>ô1G­%ú£“´ôBukr^xô$9ˈé¾Ö…Þ …ã2`èjOàù|11މ¼…c_™H¹}9ÿJlÈàè× N¤~~`¾þñv"_Ù·Û5ºž·ì1þqtkÒ±¼«[Góû n+ís|}¼÷ýùAÈóú ¢«û½× ¤ÌÛ}1Ë»uìsûŽ|—O!fy[vîm ·å ÷ZëÆÈ|n<{-#ô{Ë£ûøb4ÏU}ƒÄ•zîw«ó<÷5K<ÛÕÞêÈFËã;?Ö×¾ó¯f‹¨7¤ù5ˆ)=_õ-’µÇ'ðúÿ‰ôkÛà†´ã"̧òV⽞_NdøÇezïö˾±^ {¾ï}ý½,gõ¾ƒ Œ‹ð–Æ9°L;ðö9¼ßÃM2 >X8œÖö®{ñ]”%ÆÍ‡ ËŒÁ;H¹>Þ§¨e§õ>…òÜ¿ì}•g—¡¼þ7G)å¸ ¥Þà°®|~ì¹½Ç&)ýæèØlï¼îåxŒÔëå£ÍÔû>5õîÜä,ó|ÛÃ}"+¬tU˽]ZK½Ï ÖÊ`¼–ƒw¿Ok»ŽG“³­L¯Ç³¦˜Ìw]Çmú]ÛÂ|w=vÈ÷à&Œ)~ïÅ' æô½7‚_¶¯Ôã|5NN"ßulïkÇ5øZ=Ö÷sS¦ýk›«˜2ƒvmèîç¸Í¿ÖÈXÚÓŽ-Þü{"å9.A+ã]«í8ŒÚWŽ]ÔÚ¾­í`"ýÛ¸rL¡_÷¾Ç»k˜²ýþŽô§Ï™þÞÇC¤¿ƒ›sêþ GkÕ¢£ëþ Gùúq—öv§fͼ_„>îc-SGÓ®, Ç>ƒq¿Ç ,ÉÅ>Ë*°o’ñî×d”÷Øä£^ÇÓ~Ô~ìòñÕãQiI)ŸmÀý:.Âzß+ã4µ€½XlJ;É÷‡ˆÛ{âm‡Ñ>{¶ï{Äž§û ìùä3àÉhÏ„} víOrÛÄçzݧ0ŽóÔæ½okæ˜Ã}—}“äw.ÅýŒcxü8ÂÎoŠò·ÖVâxùˆ3NÓù[¿ùÞ ×ç¹ð:_s×ߺ¸n/åÜrÅÔEçNNàq~æ ®[À06·\©ŸËNdp–ö{8Çsg߈›7ê néìN ëú;â“Áõ† ŸdpýCŒc0¸Ç¾2?ÞäbpéÌ·Œb1¸ Tò©Ë ÂZ#;Z nºW¨Î¯ƒÓ¿¿ê- ·g*Nážðž…S`q¸ À¬î¡3(ܪádÖ)œÖ0섽ÈâpOøg€Ãe‹NážpƇ{ÂõNj,§5J¡?‡³cgqOøj€Å)°Xœ‹Å=ôÕX$nYÒ9uu§å‰K€$.Z ‡Û€ÝO‚$n"ƒo®Nâ²g’¸­Ö"qiœE—–Nâ¶ßíþåD:­ÙS‡YXŽf±¸§O–sƒÞ\÷1§qÚ²Ó8mÇiÜVfѸ­Ì¢q[_ËèT~/§#v·Zù@ÑÛÚ]4nCÛEãv¤ãs§ãyîwëÛiÜŽì=;ÛJ”‡3`™êVœ6$p½ÚŽ«à'rÚŽ9mljÜVëÇœÈmí”Â9°Ìbr;²¯±S¹­§ö×Á©ÜV¦wÎeÆÇ9`4Îå´Œs¹éLGÒõø‘)Èëg¦ Ëßdt¬Ò}âdnC¾—s`+ÍΜô8-Óý蔾`LeœÍi_ßÕ÷wå ÐÓƒj)ó^¼´³L©ÇœÏmÈwqì >ˆ‚4?IÇC¢˜9úØÌ2­Ößí¸ ÆÕ‚¸4*5˜Wçò9¡ÛXçò9¡ÛÊÀÄZÚ~Ù7ºm<í9~ã28¡ÛÊ ?Z³]gt;2Ž9tØZg;^ˆRÖÖRæÇVê°¸–Zõ ,®ñÃ5.f‡Éuý=6I‡ÍuýØçÎè6ä~‹àŒnGú1ñuÊË €‰ÁQŠÔ¾OÀùÜV¤½çèúÅáõ}“;K`±9ýy_ûØÁæ´ÈS÷Õ™Ó"åÚ7¸œ©u<¨œ\!P¹­ ³™~Œn‡ŠŒ}iÁä¤'r <Ï1~'rò6Ý> ½ ©œíœ«¨7Ûljا)wAåRwq&÷^ëÕ ˆÜ|›(n• "÷šíë|èòOóJ].“Ýþ‘Ñ£2‘[@wöø'Æùõ‘[mT!r¯½C7ho÷Ödõï‹ |þy1û€gï¢àmþqñ  )nî(hŠâæs£nRÜKÒJ)n¾Èûjº—?!ÅE“®Ååß¡Ådï -.+@‹Ëã€7Wè…:瀗BŒ‹q¸7ÿ¾’ †—Ô¸¬9N€Áay Èq³@sZ=.r1* r±Üä²¹èdéq9èqñgÈqì2å8”H5Žm¤'• Çq=Sã5H=NjAË® Ç%°Ô8ijœ´ 9n–¨9NjAŽK„r\tD9.¦Ç œr?å8ir\NÒå¸\<Êq¼b)Çå` ÆI#PãdxPã' Cãí›j\tåb\vD1.Çëb\V€'U Æ 1N‘öËÞ ´¸,µ¸œµ8iZœ c_mjqÙ.µ8)-Nhqy©Å)2¶›3µ8)S˾¼”âr9©Å ÒŽf¡ÅI hq2)hq‰P‹Ëv¨Å -N‘qì"jqÒ2ĸ˜µ8©T·ýK-Nú'´¸œ%µ8A Æå-H1.GG1.kQŒË¾(Æå€)Æ Rö™j\LŠbœT'ĸ¬-NF-NF-.ËPŒ‹f\‹“ã—c¡—‹G1NjAjœ PãrÉ©ÆIËm?=S“2K“vG;îTÊq‚@SdÛœzœ”'HyŽ9PËñPˤ'eÚsüÇÓžz\\:êqY„zœ"c?¨ÇeOÔãyÏã”z\69.§ír\^êqÒ,ô¸lrœ'Í@Ž“Ž Çåè¨ÇeêqÙ2õ8Eú±Ó]“v¡Ç =Nzªý˜õ¸¼ÚÔã¤rŠôãD¢ Çå‚BS¤íÏÂäbx!ÈIr1©ä¤ 9i‚œÔ‚ §Èq¨B“V ÈI‰1öGIrÙ.¹¬EANÊ<Ç¡ŠËü„6ÁÞìµw³¦sõbo9Ò`o|a ú6ß=Ý„‘ü lä­"g·ÚÉ[ oø‘ô!ÓO·Faˆä­QZrò–yKä­ÁW9È[+‡¥~5ŠS$oºÉ[ oôí'È[‹¼åO·a‰Ü­A¼ î–5ÀÝZ£m'¸›~ü4ÊSänÑ ¨[Ôpê}’ºE¤n €ºe  n Np·,î–%ÀÝÚ8Œ)³p·¬î–UúÞÈ[V{k©Y½ úÖRé}k©†¾µC‰Ûj¾IÐ7)þÖBkp'u@àéç@सDHàéÛ¶H'œ `píPâ¶2å¨×%.wCR¸\cR8© ×BÉ$…kMÉàZ­dpYÉ)œ”…‹FœÁIP8A@á¤P8Eü¸iP¦“à ÇGNr8E)¬5êö›.ëÃåhÈᇓvÀá|à‡“¾ÀᤠHœô'eÚvÝÈᤠ8œT‡Ë®Éá² 9\¶C]‘ÂIP8iNÊ€Ã)2ö: q‚€Ä §Hç¡ó`| q´·ÒðÆK?¸‚ [áW‘4(üà*r…\ôƒ«È¿Žpµ\ÁÎ^œ\Á.KÀ®Vr)8ÂUdX‚#œütG¸àW‘âf”<ÎÝŒrTäz¤¥ÐÝŒ2KÀŒ2KÀŒR¾ýt3Jia%/ÈŸnF©@óaàf”¸¥ôáf”RÂí(p;ʱÖ(\þ^V”ò˳Äo7¢´ß xnD©€HOÀ­(p+JÜŠRÁ1p+ʆQæ]V”úsø°p+ÊX¨°¢Œ"aF¹!ƒÛ„ˆÛQj;nG©eÜŽR˸¥"nG©ÈwŒÆí(µ„ÛQj™þãs;JA`G¹!ÝçˆÛQ*âv”ƒ1ÂŽ2®IØQj™òí%ÜŽRK¸å†ôm{„¥"nG©ˆÛQrC„¥4 3J©´Ì(õ·›QnÈÞ1Ì(q3JíÇÍ(µŒ›Q*âf”9\XQj·¢ÜvN`ìÃ…册íþ +ÊìF”ZÄ(7dìË J-RË1:ØPnÈ8Ë´½Y7¡À-(µ†[PfPJP*â”2Ž À€RvûIÜ|RëÔ}p0Ÿ”*íåøôû[￲6`:)À}oOõ°œ”"Ï·v“Òñ²›”¥oÇM˜MJ‘ïÝΛ°š”"­ï;6“Œ8'É™®8(Ù…Ť@>‘,ò^ûÊÃ^R€R÷e…µ¤ßµ¶’´z޽?ûÂ/SIýÙŽ¡ÃR2‹ÀPR± f’¼eŒ$û¸`")ÀWŽmo¡ý^„y¤£ì‡q¤LÆ‘Räþ¶÷°Tä½ýÛHi™E¨ûH¾8-ÙÄ×÷ÑÃ0R‹ô÷>R‹d¥Ñ÷…‡a¤÷»/+Ì"èûØ—Q¤ô £H)€ {R¤öcð°Š”Jí=FÖ36‘ÚȨÛàÝ(R~Þ×¾›i)Ežº ž6‘Z§\¿ìÍ–¶/<"¥È÷lƒ§I¤ÖAZ=Aú1Øñl+O“H)“È,“H-ò<ûða)ÀÛ¶-- h"úH;íê³ps ly¯ÍŠ.&âFFï5Ï`“´«[¤ÜÍ{m[øà½6ŸX–Û ïµ~ê½@Ýÿïµè½¼×ìmȉ¼×püཽ׀÷š[“ô^KàÝÆ@ï5Üî7x¯%ïµà½&@;† ÷µà¾€»¯É϶›þk ÀM€ÁauQ΀[p``pXàÀ–Øè{ ð`KlÒƒM¸°)2¶±§› ða>lŠŒmüéÃ&ÈwŒ>lŠôsða>l‰Ð‡M‘~Ì>l‚À‡Mø°)Ò9¸›ü†› ðaS¤Ÿãƒ› ða>lŠôc|ôaäÞ{¢›"{Ïôa>l‚À‡M‘vÌ€>l‚À‡Mø°)ÒÎŒ}¼ôaSd㣛 ða>lŠŒc|ôa¤–c|ôaSdœeÚÑ.|Ø›"ã˜}Ø› ðaSds › ða>lŠì㣛 ða¤Ÿw"}ØçM6AàæH?æ@6AÞ÷˜ƒû°éï~Ì>l‚|ï9¾vs › ½žsï1>ú°)²·K6Ažg;ŽÒ‡Mʼí˜}Ø©ûYš>lRækÇèÃ&HÎ9ŒëøÝŽ9ЉMû9æ@'6AžvÌNl‚”ç˜Ø©í˜ØiG+mœsèçéJ'¶DèĦÈyºÒ‰Mç<]éĦÈyºÒ‰MzŒæ;OW:± ÒÎ{‘nl‚Œó^¤["ôcä>OWú±)rž®îÇ&¿ËyºÒ‘M‘ót¥'› í<]éɦÈyºÒ—-8³Éïû8]ÛMç8_ÃMrœ¯áÏ&H=Î×ph¤çk8´ ÒçœÃ8Î×ðhä>Î×ðiSä8_çÈÈ: ¯Z7Bð¾0r\o¾S6/™9HðÚ‡À~$x­ý²ñ»ˆ¸A~7ÈïZX=‚ß €¼:aõ~—ø]W»H‰ÙA~—ÿ‹Ž!9Èï"ù]–¿Ë6Àï22ø]Æù¿ käwùwO$?Áïhû°#:I4Éè$1(F'‰ OB“ÐOÓ° „'ÉŸmvÄ' €ñI¢ ã“°P1O $Ú`€’¨Â%Q…J¢”àJ¢IF(‰¡ä‰@ŽŒPòÐP B”Ü ’1JaŒ’l‡1JaŒAÇO„1J²å¯ì¿£$ÇÇ%#MEŒ’¬~Çë!1J¢ïˆQµ"FI–aŒ’D£D~ÌÁù”`Œ’,Á%‚ FIŽ˜1J² c”<{¨É­ c”Ü{¨É ¹÷ÕŠ%‚ì=GŒ’{5©c!¿S¤3ˆ%‰€ßI-Æ(‰• ¿dìã%¿ËVÈï¤ ø]¶1J¿Sdl½äwÒ2ø”¿“2àwR¦íWŽüNÆ(dðn¸ö%Y†üNð;EÆ1ò»ù”¿“2uì¿Áïd|àwÒ ø"ý¸äwy“ße-ò;Eú±ÓɦÜ{OàwRü.ÇG~'H»Žë@~'ø]®ù]¶C~—eœße+äw‚0éc"ïuÌüNR9ßI™ï:ž8äwR üN&JÏZžÿ1Ûežô(A~—­ßI怌vÈïy˱OÈïÇ>!¿üNv´~'ø £s ¿ËóŒü.k‘ßI-¦JÏ2L )Èyº’ßI™zŒ†i!cÕÉï¤N;OWò;igœ÷"ù]"äwY‹üNÊ<÷ö†“üNj½ûsŠüNJ0Uz–¿“2ßyº’ß ÒÏÓ•üNð»1ø]”~§Èq/¿‹¿‹¿“2å8_ƒßI­ï8_ƒßI­vœ¯àwò{çkð»l…ü.ËßIð;)~'ø‘ߟ­b-lûÓ»òK½žá?ÿK¤*ø×™•࿊tÍ¿ÿ)ÀÿýÿÜSDú‚¹a{yËŸþ»ýýwÿñ?Øøÿð¿Eã™1áÿúË?Í‚Vxu3OÈò²—ÿ"[ù_f/h懙þÝ>ZËy5Úù71„þq]þëÇÓúÏýë_þé¶Ô_íZ”ß^“­rüó_ýå±@ÅãÕ9þ›¿ü“‘¼÷*«ñG—âo9YŠÿ>ûù¿ÿ÷Ÿ$»°¶¬…ÿFþü_CýY– :U}}ÿôÙ{_Ïäæ½@þ@ T4e9F‡¶äÀ‹Ôƒ¶ì.Mò÷½EÑ‚eνª¶äÇVʨUìkÅ£µ€ìâ:J[ŠÂ{›2?ö!­Ý}yÈJk@¶¤U÷Ýúz.f*–•.¶kÖ* šêçõ²Ëüƒy«žÇ>Üdûø-ù¡"éhð[rL=–l·o­ÑvÓ–ˆH[sýÖ»›Ì˜ˆ´LÚ ä_:oÕýÜë•àË[Õÿ?Ï[õƒ=r÷k°š¹êØok'}×¶ÿmiV*okË]…¶¤ÚÚ3\¡-ÉK…¶4{ÛÊRlkËq…¶$3ÚÒüUl+K±­-ËÚÊìThJ2X±¥(Æþx«ûþ<Ñø)¬~ϓ쯿z&ýè¹õ×îÜóYö“û«¶þp«Û’øÎ3âßïÞʸ—ϯ´2Üõþ³ìW<Ëå·Yúf_Šáž÷í1ê¹€²<~-Ýé‹"e¹ü.¾žêrù5vÿb4ßrùm¥{Ê«‰´åòÛÞêÙ½ ö»xòËù{ë^í6÷ó² ‡C[y.w¼·LªNc‹ƒhSø˜€æ¹ÜñÞ”Tz–Ço.Þs¹ß}³Ô»¨ôvŸBE€ç2¿{í¨.ßfÊQÂýî­#–ù–Ëok8&Ò–Ëo[[°òŸÍ"ÜYÏdì>æ˜Èòøm²wÍÃùZ.¿Öpr/—_û:²‚8NäY.¿­¯ÔØŽX»öU×Û½ßåòÛæ²®øüq×{Ë{£N½| %‘å¨}þVm_f|Aow½o½XÒë…ôåókßjPÄ=i:0–ǯÉ]yÜõÞŠxXœgN|[«Ù‘_„Xàç)¾ÀŸ¿AOä]¿–<×ï‰,ßìú)ÍibOÚÛ^q^€ð”ù–Ão»;ÜJŸÇýÖ| Âÿ=»Þ›¨×0)ËåÜæMè–çqÇ{éi>¾l öäòÀ4ÏëŽ÷ÆRªOá}–ï}èò÷á‰øm8–y?¿Ñ÷[ünÎ}ërøÕvêð9äx¾åðkŸÐ´ÜÖˆyðyûrømö9åÒyе;ÞK×åz} çCžˆ;ÞÛ~ôgÀDº_†Á%.îxo¨ÇF{Êûúââ•ro»º”îû<½T܆9šïõË}»ç½¶Ûº_9H÷&ËG d,ßuìx;õZþ¾öl~ˆ,ßÜõ®>…h¸>¯ß Þs}/ŸA,yuÇûni”åíÛ-½Ï©ºç½Œ®~—Ï Ö³ºç½tÕª_„‚óSÝñ^öHþê(»ë½]–áe¾«n—黟_Ndªv¶à†ÿžæƒùÞâ× ®å·b[½–êz RYgªÌò«žˆ5Wâs¿{0®÷ןª¸Û½èÛ²|îsŸ@»îã.mîr/‹ëLo–ù<}ÉDÜåþ{>O{o~–yýN~ñw"ž|V.[zÒæÆkjJG㱦ä)Ò<Ø”ÖñhSÝ¢ £–Gœ’ZÝ]îe‡t9%·Jw—{¹LÝ£N­å>«þ~Û ºG’kÐÝå^.m÷ÈS&@`%–AÊ>>=¥}{ð)™g÷èSrõº‡Ÿdxü)é}x*nšqïàñà<އûÛËÃtx *yÎ ÷·—åµr#a’Ãýíei†¢’=>ÜßÞvXG-E¥Srû¼ïeѨr“¬fuG<U>þßËRå¬V0é¾×zÛ~3¼WÁ‘ÊÕy/J•Ûf"cß$ó,l<ŽX¦ù‘ü½ú³¯ò½—‡¦jó•ÈÏš÷¾p¤rÕßû>ŽÔ‰Œc|·‡¦’YÝxAŽ·µyVû‘:÷»o¶‰¬#u>Qp­ÞÛCS™诠ïm¡©¾›ìÞÛCSÕÎWYGj'6ÛõÐT¦¶6ÌÁCSÕ¹OüEö}®u¦šúë;g"ëL-£üÏw‰u¦– ÉŸ&â¡©Êóœï ö›±{çïu¦–ç‰vË:S퀾ðiÏCS™êÝQË¿' 5ŽZšÊé­ó½à÷~Ü%û[Y¯e}¿¡é0*šOÔÞv/_£‚ãäS$ËøŒ¤í=5'Oæù“| )Xf¿‰|†äï1¯;éqò7F7^ìAþ&2g‹¾†9[™TêÏ}An·i4cÀºhDàgÚ÷€çþ\Å¢ôotÕéŸ?,Q¦ºÛðÄ£ôo"Tôo!¸ Fÿ+‹Ò¿… ´2ÜsxîßKéßB¸çð<‰o28îÏ'7S§« xÐÇý èŸ gÑ? èß³lÔÀäฯˆûçðš»ËðºûË`ÆÅ)|Jÿt Nÿ‚7{§]f°©Ç=ˆèþ³ƒÆ½îA,÷³J½öñßpÛÏñ;õÓÑÞðÛ—Ñöë?üöeü£îãฟ€‰2Z§~y‚=îF,Èë~ÄŠ¸#ñDðžêÜoCª» ò¹/±"ã˜s?0<÷¥Èx¶ðÛÀ‰ŸNò…ß¾ ÏÍ `J/üöy?N€H)Çœømeª{K™Ï]ŠçÞo2â÷˜&›¿­Dïç༟ˆ3¿ û¾"îV,ü÷sÄÎü6¤ì3pæ·!ðàä{¹IˆÀ…?gåÌoCóÛáÞʼn8óÛ‘~ÌÁ©ß†<ïþû½Ž^áÈ/H©ÇF¯påÏY9÷ÛFgþ9°+' ÁÛi…7¿Ôîf¬H;ö‰‘?Ý'NþvÄýŒ¥ÎÓŽ98ûÓ98ûÛ‘qܬÎþ6~ý‚´ç˜Ãß~Aú~í>øöçœîÈ8Ö’ –wÿD@öneÞÁ2DŠªye¢Uå¬ÂUIïß¾Æ «¤"VI„¬R¤{½ÃÇ_D­Êwxù+⧪ ïñq«rm:ýéÇup ¨kÓ½JƇðU9óŽøU‚ €UÖˆ`%BX)²_ß V‚Àß?ç0ÈJ‘vì“PVRÿ‚ ˜•"íXãpV2b8ý²X Ô ÜJ ¬• ˆk¥ÈØç¸!m%b[)28‡ þ†èV‚´²ï”Å÷ßc_c°@íÉY ÎáFˆ+)s÷"Xà†¼å,ƒWŠŒý~ ܯì¿âJ‘~Î!®rž7B\%â,pGú¾—À7!®ìàfï­çXà†œ¯‰ Ä• îÅl!®¤o„¸"ò,sRô¨ë"Þ7)8eÀ»ð³¬Ë€÷ÂdÀõB .æ2 »e‚Ѯˀڎˀw{A•)Ú‹1=—Íœ]¹ hoÊcSµ+Wír³S'•‚öEжTJ¨€·)ÎÔ×gKóiø6ÐÞÉ jùWŽIöLWý[ꀓÚA“¢xN5ÑeÀÉÛ˜´ 2  2 6l2 NÁe@íÈeÀèˆ*`vDpþ÷:«P¸Z¡Âç* ´ë" u}% \ýP™sP{vÐn87l§¨e\Ô®]ÌIRÜîëÛ [SÌÅ¢ (-CÌ•X"  oà·‹€VàE³.j#.Ê j-eq j-e0.ÊjA”ΡJÃKÌF ÊX J×¥h€28ˆ€ÚŒ‹€¹! j%×µ’k€:\×uJãhÅ5@A f×¥H€28ƒD\ýÓ–]ýSÄÕ?¹¸e€}_€ÒÀ û( Pî%€²{!*R¾c‡CÔ–¿û¸KÔ:í;îR€ŠŒûxŒC”v!J€Zæ¹Ç @™ùõwyç À Áišˆ €ÚS{ù¬$ÕÃaG'ô?9:¡ÿI3Ðÿ²È ì`€ÚÆ{ž¥7¤£ƒ(£ƒ¨e\”Á¸þ§•z=&0p”²—ÿòEò_¾òPþÓ:.ÿå« å¿ìšò_tMõO€úì¯3ÿre(þi»-ÎR4ÓŸý'NÒ¬1¾_¶7JJY ÊŸ¹Ç¾=¨ü)âïÄùˆ ò' »ð's„ð§È·í Ò}±Þþ´Œ ‚@ø“ž üɵ…ð§e\ø‹'˜ë~ZÅu?Yè~ZÆu?0t?íÈu?EZÝ®ÂßñžH–·žjJò敲¶³ö@œä…•a¼ Jg<¡k yó:Ü*÷Ív3…ýœä­‡Ñß„ãÍ-üBYÉk_R:'yó^¦ú’'\q€;öÍÔóžÏÿ¡jßÚJHmF’ƒ!ÇËñ’ã Žgþ,*öéðHòrmHòŒö€öäå;É“áäµÓÖ3G,/–,/ÇGšgeÆNóbq‚æ5Ú«Ï‹ñ€çI ð<.i^8hž 4OšgΞ0hžtš—ƒ!Í4/†–'/š§¿æI°¼ïƒAIžtã$ϘÍäI¼œHÞ†4Žn3õ”•!É›t âé"y²¾`y2°<é4oCƾÍIó´ hžôž7׆¦¨Îódâäy2ð¼¹Ía¶ãE@ø¤–>¹«@ø´/'|:'|Š8ãÓ¾Æy7.Æ'uÀø¤'P>YP>1(ŸŒ”Ož™ |ÚrmÇ@ùiçÀ¾œòi˽íuœóIOà|RœOV‚¤O>i¤O¿§ó¾"链@ú¤Öw­ }ò¤OZé¤OF җפ/k‘ôI>EühÍ5vÒ7·!-EAúâ{y>Eül·-E@>i¤/Î3’>üd•¾Áùò9OΗ}“ô圜õI °>AÞãl%é íƒ#åËÁ‘òe0>-(ß÷„´Ê'c狆Áù¢•à|RœOÊ€óq0Aù¤(_ÜÞÁù¤¾^¾lœ/P¾ú³ÿÇÐÀøæ­á†Áør°¤|94R¾h†Œ/¼ '¾'ÀØÇNº75èžüÝË!Ý“¡îIнDH÷²é^^Ò=#c¨åtOÆù^Ž|OZß“:à{1mÒ= èžTÝc™¸ºÅÃãls¦á­¾RÔ¢ó}çs¯oïoðBçxfÏ sCp¼òÐÏlUé9è¯Ì'5”2p¼bD eœäòlJž½—<¤të(*eü‚;Ç+5",Ž·?©E§–Ç+5,NÁñÊ<$žä•ùø„í(H^ÿ’ä'EDêO¤!› cÿížzЏ§^"ôÔÛ>,â€×ˆW=E\‘Î9)ÇowÕSqÀéœ÷ÕSÄ}õq_½ éÇà«§ˆûê)âÎz²· o=E \w×ÛvŒþzŠ ¸ !íŸûë ‡=EÌ@{ûÝÎî±§ˆ{ìÙH½Î=ö´Œ{ì)â{ZË=ö6Ä£ â{Š ¸ ãh‘ÀÓž"ˆ.ˆ;ímÈ8Ƨ=EJ9˸ÓÞ†ŒcpÚS¤#v§½ éç <8í)‚HàŠôcpÚSÄö)G wÚS‘Àq§=E \‘~ÎÁöq§=Aà´·!ý˜œöyöžà´·!혜öA$pAÜioCÚ9>wÚS‘À×9ÄOd9íéïû9KÜ㘜öyË18ímÈ8æ§=E \ös€Óž"ýh‘ÀÓÞ†Œc|pÚSä9ïE8ímÈyOÃiO‘Ì„C„ÉN9Ƈl8‚ Ž È‡£H?æ§=EGDW¤sXN{úYqA$pEú18í)‚Ü8‚ôóž†Óž"H“œöA‚Eövá´§" ‚49Š´c|pÚS‘ÀAªEÚ9>$Ëdw£;ím¿ÛY syŽó•N{Š gŽ å8_é´·!ÇùJ§=EZ9GØVú8Ç7Žó•N{ŠÜÇùJ§=Ežã|¥Óž"å8_é´§H=ÎWwÚÓßí8_Áô6¤çÆq¾ÒioCŽó•N{Š<ÇùêN{Ûïã|¥Óž"õ8_é´·!ÇùJ§½@þ@hé4ç,‹©=§Xkú§ŒçîawiZß<è©F­Ï”û=j}ùEŸZßkÑ'¨þM²4ªWúÞ—¡)õ½¥†ˆèRß[ß N„º'µ¾—±GMè{çŽÉ\è[oqÅúÞÙÆ¡ïíéŸçBß;`¶Kï%⽸Î÷Žž±\\ç»nF¨¡ÎgIAP:Ÿ…RÚ<öÊ—Àu¾ûæ ÏÒL` ÐùîíHïf85Ê|w„ñ¢Ì÷Dô*È|åŽ0cùLµÝèàDJØ„–Ï£Á7:Ÿ–p¯Ìw™{ ÜiÕdȆèF‰¸Î§È@t£‹!Πó26Ÿ½Œ€D¯¼øœA™o½(ÃÈòéþû†`ç2_JÓ”ù,Ôì> ói—ùÊ˵”ù Á—WÈ|ÅîŠz—O!"ÖAæÓZ.óI-È|2‡%óY+ƒöÍKt0ƒÌ§­¸ÌgÈÐø-K‚¿” Š(O™O˸̧½»Ì§e\æSÄe>í}­¸Ì'd>YÈ|å-acé2߆ø˜›2Ÿ\=È|²• óåÆÊ'€‹|Z§m¹(òiÏ.ò)â"ŸŒ"Ÿ".òÉõ†È—ƒÈ'Û"ŸtµD>mÖE¾²žf p‘O×ød1¡ñÉ6‡Æ'•\ãÀ%>iŸ´O×øy¶~ ñɽ‰Oö$>E Üj¹Æ·!Ãc-×ød/BãSÄ5>¹Ã ñÉÄ—Æ'=Aã“IB㓾¡ñi­·pc³ã”¾¡òiWùq•OWù´/Wùéû3 *Ÿ´™OîmÈ|R 2Ÿ"îÁ¬å:Ÿô O×ùd[CèÓ–]è“U^BŸ¬1„>­ãBŸÖq¡Oûv¡OÊ@è“2ú¤/}ZË…¾¼›—Η;2ŸÌ2Ÿ<{ óÉ3:ŸÖrOG×ãPhžç¡ ¡/GOtÐùä´^:Ÿý~6O×ù¤Y—ù´HÁ™E*ŽÔt>y+€Î'•\çÓv;NÔlfĉª:_Þ¹Ôùò:R狎(óIüEÈ|öîÓ6×½|¢Î—kGOã:_¾€Pç“èÐùòr»Î§%úàa».ôåÒPè“Ñ@è“v!ô¥5…>é BŸ¶\p rÑ)ôɬ ôYÜKiKèÓ.ôéø\èÓ2.ôå[)…>YuFî”虈ܙ-3rg¶ÃÈ9Ü)%¹“3¢FäNcAØÎœt„ídðnÊ|2T½cådé23-ÐOëI" ”ùýº‡@4ñÎÞÇ¿D’øÌ+µ>Ôe[H[À¤­@´­•[ZòßÚŽ!ÚŠÿ–6êå ¬i˜´ˆ¶µ_/½‚ÚÖ~uôzý‹'(²÷ÔÉ· E–TÈ2 ~ýWc2ëé÷ùy6£Y`>}¾?¿¿ÝBý­GG²¢í²·ËµùÙ#ñì–ÒÈÛÒ4DÞÖ–†mI)´µ§4B[O¦!B[¤!b[YŠmi)¶%iˆÐ–¦!b[YŠmm)ÐV&"BS’¬ˆ-E6ô$+z=ü ÉŠ~ÇÓö‡Ï´_=[ÿúÏÇ­ÔOŸÿï’½c¥*ù÷&YÑ?ÿ(YÑ?ÿ£ÉŠæž^ßw[Y69úP˜¤A£¬ï»ö׳Qýû®¥E™Ï¾ïFTéù{ð–>þâ¯,šÅ{Gw— Æ›÷Ž»lX†#"î¦Ñ̾\þíjò^¼1•ëvÓX‹þ9õùÙQæqÞ\^„ø*>_ãBËÅž 7 @Ë…WsiÜ|j"‹8WsÃzùœ8»c¹ÚbÍF•;¾Xs}é¤?‘Åš¿B‰9ͰfÈ}-ÖüY´ooç¾=çš½¤W ëMû«ôR˜ïAöûáKW¹‘tÆŒûÐî»Xó÷à]|îj¿rÇ. "Ô‹hàåFΙŸ~‹¹¡Ù >™.7rÎØ§gÔêž@jþ¡'a* b!JV)ZË•ç²Àö5–÷¹=á…™òùœžgqæ ¼?Ïxa6w(ózÆ {¹ô¾äœ)ô»,¶ìY~Çj=È9S™’k¾®.Îl´Ófæ‹qÑ|Ló%Øó]îû‰xÎû˜Ž:ëÅj–¡·Ë|-ö¤3–\Ùç°l­Lã.1Cº®É‹Š [ŠF‹eEnež+`ëWdù˜i¡Ôoñf‹Ÿî&n¥"ëÌÜÝ ãm‹7[,LÜTµ7/·o‹7[”Rïü»žm}×z󱛨±ßí9¤lU}Öß³^—L;ÂŽýÞE›-¯Á‰,Úlep/|eÑfK=ŽûùóoW6˜e¾E›åÒ™{òÂG†bÓµ*/Üçß®ì]ûÜòÒÙUè4‡žÈºÇ3°?ÛµX³ì£¶–ä5µ ·B{nß#ñ`³Dvæ‰äAi¯çš›çRk¶¬ç¸U[]%¤±ù{ªë„öáµoª²-ó[ÙËøÇ+ÙHöİË0ÀÄ?^™ðçRc±IvÞ8”º½²ÏZ¸ú½NUËÂŽEîþýÊrxB‡Òß×Gs£]ÿ|%{Öžzv Ï » ÊÞÈ·ÎUûô…sÕk'ÝÐ÷ŠÝý6…y«ÞhÙFóÕ]Þµ ^d ÿ¨9'V Ol¤q¯[wÀ-½ ÿ~Õç-‚ca¸ºÛ?æ9,ÿ_Éid‘ŠÇìðïW}\7Ï"UèŠX†¿Òv\ÞÍ{¸º«vu×äc7.cà¬óU/xí1ñ:àúnŸ·‚«Ñõº‘Hйiêåú®iÇþ€¯—½²KÚÐŽ ¼ÝžTÈ:Vóh›G?Vç |¡¯oKåV/—wû¼?”ð¯W6%¿Üõêq¬v”ñ¯Wy¹ëí¯=0ý11‘u;g¦z»Â›÷ê|V¿Nóxì×ÛÞ<¶&Ò9tÌ÷FÝXõFfÆxO©· ¼v«ÞDüTåó¼ÞL};ðºSo×w—Ê~†ª y¶ Á¡Šïàóhñ35õ¹q¨FÃÏã‡êk«è®mÁïgê‹O»õ)8Séì[ŸŠ3•&i¼ƒqy7O¤yÒù™OÐútœ©•ƒqu×$笫»–oÆß«êëê®åÈÁ®~MÝ•ŽÌþ¿èñ¾ÎÔ‹›æ}ýL5Eíºº›OŸjÏÞ²«»öPøPæ{¶#Ã_lž(â/ÉrÞŽ3•Gݤ ÖQe†—øœ`G¶O²¸¸+ oqzÿî\EIþ–WÄöE(<'Hþ*íTHþÚGZáäÏ^U?þvãž;b¯ ²Ï'Â!8ù[©‰H‘tÆÜ•ˆxDîz»E Éßu1v3Éß}Ó›†äϨ^ý@þîù¼‡€ü=sáIü=&z¢„om£x†‚ü½ó¢ƒ ~pŒ¼ø’þ—_¤ÉÿÊÍlœäa&CúgÜ´€N9ý«ÑìHÿŠ] ”qúW/z99ý«ñHÿ ùPÇé_}™ŒüÏôU¼/‚f–aÀï‹×xÀ·s)@-wX¹œ·&NyIM¹eXð#»û{ã…ˆì/²’ýÙ«Ž^°?{›ê`‘`sÅð‚ö—)[ƒý•xÝû³w9¼a8û³ÕØÙ_’ ²?f*&ù“J ¦w~¤zHwH£ óƒ7’¿¤«?'IWAþò´sò‰ÉýúM»•à~v¿¢Œs?e¢à~ÉâÈý*SU÷3ÙTŠÜ²Zp¿xò÷Æ×’¿xŒ‚ü !ù3ñ}ƒüÕø>ò'¯®$ñÂä/ßšHþò5žäÏÞO0+’?>Æ‚üÅÁ™ì/Vg±¿|‘ ög‚J8ûËž`“«aSýKÚú—ß@ÿdÄ v€´ìôÏή#&ýKŠèô/ŽhÐ?;¸ù{ð½“ô/§ úgЏ5IÿÌd§o|ª!ý›ì}п|?$ýSb¹èŸ ­þñÕŸìo^œŒì/ÉT°¿Â=úgo;ýK²ö—L™äoÞŸøøHò—‚äOÚ5ògËpó·“¿Ù:i¦“¿|› ò'ãùËYùcÜà 7ó™ù³­¼“¿l9È_|­ùÂêäo¶ rEò—ä”ä/y:Ù_n$²¿÷Šñý=×/èšäŸ’ÉýÌž‚=9÷³d/©Þ:TÍ‚´ÍÉß0Fîº};÷³eøˆŒ½‚úÙðFê—£ó“eó“eó…ßÂÉüÆ|8â± ê'0@ý†}nê7_Ðø^ê7æÕó3¹_¶Kîgï]ç~1KR¿ñЦ˜ÔÏÞ"Ã×—FHýb}ùÙhÁnÀüòR“ùi³ÎüÆ÷þBéÄ/—ÄϾ¼ uNü²gð>™#xŸ­CG%ç}£^Áµœ÷å‡ç}ãÃËy_lDҾܤ}fµC–ç¼Ï.ù‹fœ÷Ù· 2Îû¤a§}f.}F9ï“)÷ô­í'¬/Ûé³Ý~Ò—œ/w9Ÿ¬8ŸÑ*p>Y[p>Y>í¤Ïžé“ »HŸ-BcrÒgû=‘ô}wPG'}Ö÷ ô£4>‘ôå†ç3ÓóÍ8çãê‚ñ呌Oî>2¾Ú‚’ŽÇ¿ Õñù´y'ãËÑ’ñÍ•Z_®ÿH^¢ }ß·K÷Ë|ŽÎIßXçõß’óÙ:7üÖ# %>Äh㎥àwÏ·<¿ý)ø=ãf³.ø=µÁ—z_Æ2#å›,€/0 |*²ÁX½ÅW

“ËÀ—@ùì]ìÊ'ò(_uÁבu8}ƒ!Hù¾r‡è”ÏÊà-”Ï,KÙ·S¾VsÎùìýblœÏNpò7ç|™fœœÏ¤Y¼H,Î×îxËç.ÎgŒ¯øà|™Ç›œ¯µ“ó™&Î9p>-ƒïñŽœ/ÓÈ“óÉ÷Up>Ñwç¢Úg_ÀAûä%´¯›Á=ÈD¿Îðk¤}ù.D¿$ }òúNÑ/_úí‹O¥Áúâ£Y_jX”üòõެ/>‘õ %ë)¬OÞ?Àúò-–¤o®*&@Ò‡Oç‹ñÉë)ß`ÀR¾|#¹/µ P>ûÜVÆ—Í€ñÙ[¶Ÿ².g|î)´'|6Ãw#|"ÿ,—߻Høìµ  „oÜŒ¾„/_rAøò% |O^¹À÷òÅt/OÒ={Õ¸6­/ß<ÁöìÍóV­/Ű=!+ÔúJhÏ`{òþO¶7ŸRXq°=ž(öÅql/ô+j}–Á}#{ò6J­Ï‚€,]û:íÅ™D¶—'|ˆ}ñ2 ²'‘ìÍ-KŠèdO„2j}¹6${ùÞîd/^@Hö´'°½x• ÛVF¶¯šÁöò]žb_¶Cº€t/ÞIH÷¬>m‘îåî¥ÀEºïGA÷DÙÝ‹w… {)‚‘î%M#Ý‹·î {9bÒ½¹öƒÐé^î j}ɹÛËýI¶¯bÁöâõ'Ø^îX²=élOÚÝ‹7Ýà{¹KÈ÷âu2ø^.)ù^¼‚ðå$Iøj¼Há‹%ã# ÂWÃd†Œï»¢k0¾¤š |yHøòî áËžÀ÷dÀ?á{1–à{|{¾÷RÇ!ßû˜ª0_r¾äaà{Òø^L„/f„/ùžŒ%ùÞµ¾d $|óNháãs._ΉŒ/.n0¾¯D-0¾\-0¾ )Ÿ´Î'eÀùr!~Îù¤ 8ŸÅ4>H¯w>³IéËvÈû,¢rÒ·9‘øå¼Iü’©ùYZÔó‹‹Gâ7oØoû„|‘øå%ñÄo.ΕñË ìÄO؈Ÿ-?Z¥ñKrEâ7Ûi;ñ“vÀüd4`~RäOÚùËE&ù›Wš°“?iä/×ä/·@È}°³ù{)Š‚ðÕÙNU¾Áô$|f ô«ñ™œ¨|ÃØf‚ñ]‘·˜Œon78mñ5r„ |-MEó¥Ãzp¾ÊÐÝä|écœÏ^¬Á»`ã¹ÞxO{•‚b·L<8Øã»’»ÑÂ3Ž0>{CÃgC2¾;Ç#ÏÁËFž‹ƒñ]wp5y~ñ‰Œï›¯ èFžz:Œs›„З&‡úrúR£Ð'e(ôQjƒÐŸ ¨óuÆè /§ æ'_¨óãSä›èñaã™@ä“2?ùÒÚÌU>£" gìQÂÜ‚*Ÿ…å=£ÊÇ9RäK-¼O6 E¾T_)òIØxæv\¼OmP!òÉ`œ÷ÉBPåKƒ>ð>™<Ãì*T¾6v•O‹8ï“ý@™ïë4êïKë-Øx~5;ç}ò‹6ži‹ Þ'× ¼OÛqÞ§=9ï“2à}ò= ¼O¼Ov e¾°ªsâ§%œøÉ=â—{¼O4zð>¹Rà}bÌ Þ'2y_·†Îv4ò ¼/PÝÈ3?x‘÷å·+y¦èLÞ—*)ˆŸ™¶áÖ¤‘gj¢4òóQ0¿9<0Áüäf¥•ç`Ôð°òL³x·òL³:ZyΪaÔéRþ™Ô/÷~˜yŠñ%Ì<ÓäfžñÔ 3Oð Úx¦Uå"~yo„g˜c‡g|ÿ ϘbØx†IyØxfË´ñœ\›Ö—Oó°ñ”v`ã÷]ØxÆã…6ž-ìBù¥±Lyæ’ÓÈ3íiåÙï'aå)=ÁÊSf+Ïøfž9+šyÆífžý µnÙyfO´ó”V`ç™×vž¹6´óŒs6ì„SÞÁú^~„§¾‚õ½øŒú>ÒSÜK½‚ê^.¹«{©PÝKÇ)ª{©h„ºfZT÷bB"î‘KBÜ‹/ã!î¥ÿÕ½Ô¨î‰$u/¾ƒSÝ»ùi€ê^JT÷RÁ¢º¦º'’ Ô½øvê^ÊST÷R¢º'šà·}Å u/%Lª{ñ;Õ½0Ô½¼ØT÷RW¢ºîSݧ+_jF!ïÅÌCÞ ÕÈå½OBÞË‹@y/gEyï +õ÷â‚SÞ“ž ï‰Py/>î§¼'‚ŸË{y­BÞ‹ëàú^^ê{Ò ô½5BßK½”úžô}/gN}/·1yž´ž—}QßËGè{a´ò3}/5È{yˇ¼îÚ¡ïeê{Y†ú^ ˜4//9>)ðÅ%§Â—t/LëBàãÓ%¾sBà õ$¾Ÿ(ð¥G}/»¢ÀJW|¡,¹À—š ô½T4(ð‰´H/$¬øDλ÷‹_ª;øR¢Àá¾govTüú!QBßK]ú^Αú^ƒEÊ{)BÞkôšyODKÈ{Ù Ô½{¨î¥¬ê^,Õ½ÆÖP÷b…º'²Ô½”žBÝû~Ù\ù´#ª{¡_…º—†ºs q/mA!î™w¸Ä=Â\Ükø°’â^ †â^c8‰÷òÊ…¸×ÿâ^®Ž~E-Š{ÙŽî îå> qDâžôDq/JPܹâÛÕÎï¶:È9c”ß)ò"çŒ=‚A nÏsÑ"‘ó» y<ÏE»°ÄÎï$døÝŽxš‹/Ýñêñûó4_èÊÎï ÁOÏqÁŸH6cÏ2Uð‚ËVlFOp!’Íòx‚‹l¹ ÝŒ"«o†³ÛJTOp!e>¿“ñ_ižàâ+aÚ=Á… Ã\(â .¾7¨Ûå .f0ØŠt3R湎ߞlF꼞àBÊ ÙÌ®ŽNï¶2H6#Èç .A²i§y‚ {yOì~/ 2<ÁE"Æïößžàb"øàü.? ‚ÞmE^Ïo¡ˆç·¤x~ Ak&þ<½…{ÇÍS[$€<3 Omñ…/ì‡43‰8µÛû=Ë<žÚBÿVú…¹€S» )~ž RÕÏSA>÷~¤!µÅeif¤L™IÄ©¶Ó™fF¤ŽJ„‰fyßý7ÓÌ0Z,¨Ý†Ôz–ù:*‘†ÔQ‚ uT"½rD1‘Á„Œ‚4ÎÈ Ê‚,3 ŒcƒIfa>ƨÄ3 mTÌ0Ã4 uZ„¹@Ψ¬3šþ«Ë* u€ŒQ0!c6Âä2‰0!£ c>8݆|eÿÍtŒŒ× R·•aBÆD˜\¦g4$ŒŠvn&dL„ aBÆD˜1[fBÆ,SŽßLȘ2 ‚„Q‰0¹L"LȘȸ8>Dι™1Ê8¯Û&dŒZÎëv¤ï¿ßzŒïaBÆD˜1k1!c"LȘ2&„Œ‚4Î2ò2!c"žQ~·c|/2&òFNÔü ³LiÇø^&dd0»­&dL„ aBÆly=1!cÔ)LȘ2ù#i‰2PËÒí•ú™p ãKP¿y¶Wl‚úYÂP´ïÞ¬ JgáE”΋Ÿx"J§Y…‘èy˜Î‹ñ#LçMÂNaïþâÃ?M8¿Â0_ø¸Ð„³U°÷~']Ø+fä?¥ó¢Urxí}aŸ6œL¤”6œã Ô9d.íÕyqûfÃ9÷yX_Âkﻯ=Ó)ÜÁkï¦Ù©›p¦x eïkaçBÎ;â-Ò„s¤ù(œö®°j¡ gïÐa™*L8熢A)#u†‘öRÉ£ çlŽZÞ2áÌÑЄó '2šp¦ã!M8¯±J§½4¼£ ç!7l8ãEž6œm”±ZÄfsÙpÚù¾ÇjI“)j{OòßFêœ'×¥ÜO#¬¥Åg]Úp¦ !m8ßA÷9˜pJøLšp†±²›pŠ!(uæ` í¥KÎ4™¢ §xÒ†3lˆ#XKHˬº1µ½tŽƒ §ÄBa Î0w„ gF…¡ gÊ‹@ñÒ^Fn  §Äa¶—S4áL#¹ˆÕ’AA«%ž@Ô÷R¤ g$q}/iÁ†#iÂÙCs£ gL“ò^*˜Ô÷Òó‘úÞÑ™hÅ)bª%B”Њ3Mâ¨ï¥¬åúÞöÔ÷ž¸=¨ï¥õ½”ÔiÆ)a8!ð¥¬E//>ñ „À—3w/½7iÆ!UÂ{/”ê{á×Hy/%UÊ{©sSÞKUÊ{óxh×Ù)=¡¨{ôƒ´'¾|KÚ“°, ÔB'׈ÓKÊt‰ödô?õÛËØ#£3ЈÑV"ì½›ý¦ºÊýÄqO®0LK¸šF˜–¸j!ì¥@HÇ= Û Ç½ì ž‰¡gìW {b É@-©À-a/w…½¼ã¨ìI´({Ô†ÊÞÕRÇ{ˆÕþ“«å=]÷Ò 8bµ|ÜìT]Ù =‹Ê^‡ ²—¡ ¨ìIð({ñL e/ÌFRÚ˾ íI˜ÆjÉ 0¬eöÂ>!„½¸~CØËá¹ò%…½Œ0Ba/¢È†°Ï™TöBK Ͻð•seOüô¬….À¡ì…ÀÒ^DåMi/”öÂg‘Ò^zÏQÛ‹».´=A®…Æ%ªíAå‚ç^DD ϽôöûYÈ µm/wMh{ô‹ mOâˤç^øòµÝV#ĽD(îeˆ{©í‰S^:îÝ»¶—S ¶—Qg¨í±ãµÄŒ(ìIGöÄC°a—2dKv4´ªzÑ U½ÜgTõø Ñ´D×XšyYYâÁû­”ys;ù[ ¥MYïZÿÓoÔËR,£õþ@Z"ãXóÊgÌýùb€ØÅ¿ä‚/á,eïšsGKSD¤)@ÒT Ù”¥ð´G³Ì›H6E(›J$›ú—Ê4ï9_sn©ž„ÉRÞÌÉófÒž¯EÒžŸ(þ~VÀ3{”Ìêó«m0ù§j¹{þú«e{e>ÕæNK±©1ïékdKø­ E¶#eØŒ%ƒ4ÂíІ²[ÒRÑTµ‡¯´ä¿·†X$ÚÉ2ÑŒE˜¾tD¶†¢P´$¥~ï¦æ29&£¥¶¾{2Ÿò[É|Êo$óùÕøI2Ÿ÷;Úûq2Ÿo©$óùϨ¿þêió£'Ò_´aõ”úñŽýu[¿q5ì½XoÒjöæ7)rê<ãþÓ_ìïOûþüŸÎõxæJ]UÀï/ó5ã›/yþOË¿þ»øë¯›¹‹€ÿëÍÝ©!¿Òý§²ñYäZÛ+ëÃÑ…½ò_þå1§|þW™‹Y-ÿù_GGÿ&þúßÎgÆ|c½û÷ç¿þ埌 ·ï‰Kùdz™5Ç]þô˜Cj/{¶£7³½+ÛÑ÷w½žèÈÿO@Ioôî­È“ïßYÿœ¿3³Qù™.ÿl·>™>oúù¶c~©iÙý›’â~þß–]p®Ò|9ù¸{“\]vd;s*·)™^ÈaÄ5$<¨‘óGºq¶¸o7BB­s~Û¬œN:ùÑÌhØ®4|C¦"Ãcß¾îµA¨P˜\ï׺Šöªu`!Á¬çðH.†æne­øt_šsÕ!ê Múz~{*lå‡/Å]“ïâ¾r-Ç“¯5W}ˆPÎ3àÖ³Œ†àûÒÜß—ìÚ:Ü÷QÖokÑ:ƒŒaTš/ ¦î½þ>×Qð¶ kåõ^u»õöí ßJóÊ¡g+áúBÖJ®Î-ÁÁçü¾™µO]ë®6çª ÿ0†(l$Öº{g¼Ü©ÆÿpOOµ}Üðmô×bmTýŽ;¬×{?p ³Ô°TŠ ƒ@ÉSço)@®ÛtdÙ†»ñ:Îêp^·yWû^ß}·;x×ûkúf?FK×§p gíp¯Y‹¿éþò½ü¯OÖ>MÜ¿¾]«G¿Í0§wí÷¿Ê_n¨+Æß2ºâ ×Ô¥àc ZûJ¬JuÊC3¦qûZ=ôÊߊ:z™ªÃÙzÑ_iFdÕ«$§ýF7­#ú/ðj_+%¿/×÷}XÃi¼¾_š#cì±Û%Ó!âëÜct©pïqà–%?ÃFo}´+ò®éº7wlM×è产ᛮë¸BšôX[þu\8'çµ1]ë±n Ö|íãã ÅUóµ_ÕY÷¬9ÎsÄ%íN>‹y*‰OÀ+Ø>F×%¼üþWÓuÄZB®2»³sÎwD?ESÇò?yòÁ/œ-Çë»Öq@>"x몉÷ÍZ†1_Ÿ‡çNÕëÅ›Õâu®˜¯u‡ÂIÁ÷W÷Ê£àëº0_ß‹z•OZŽÀë÷”L°l¼¾*¯5_Ì·n Ûoó†ÓÏ÷4ì¨oÏ; ÀŠ\vlè í{;Ì×{ß1_=üïºÌoz†Z0_uj__‰1_;MÙÌiê(¯_ú÷KŽƒ.¾Ÿ:J‹iUùžñP5Â1pnÚðTî1_}ÿE]¤¾¯èb|ùklÞœÓϾ`¾zÆŽâÄq/§å°u>ùPu&½ìù ud~Œ(;˜:Kóµ%vÐÕRœ¯Õ™ôsä¬#ó1_kq-¬hB÷:U#e-ºå—´–Þ1_=PêPz<§l2ê„霾]åÀ³0 TVuž„ùª)SÇïšÏP_¶/)«êgËgxïÖÏù>X`ÇÅhà‹Ö=ø1%X×õIFôS|ÛÖ‹Öi6,°nó¶ìX`Ÿ&Ÿ€ë놋­µc¾jÅÝ–ëë÷‚6乸¾ÖÐÜ Áúú¬Hpcqõ¥ÿÛ‚ýZ¶å]9[9?ÉÃÙÊÎÔX^ëžÎqøí3vNWöçV7=O|}·„#?nÛ·šbº*œÀö-Ne¹Þoa«ýû˜®+í? –Wî¶u¨„׊ú‡šî³UOõý÷×™õôi¶~û".®+­û¶mÁêêϳNâ)Kí=VWtð¶ii¥ é¶í\ZÝyÛÁ¥Õ·…1}¶Š*¼äÐû6iXZ=ð·íâÒª/ä6vÈo샶íÁÒêÀ[9ònïÔžWK«Ú³/XZÝûÊ¥Õãfß°´j­ýZZi»UÎeÅv+wà1U7^r´íçʩʷ°Ÿ/gªFÍ~aiíù´ßZZ-y†DóheÕ‹ª¡˜¨z„£ž=Ù¾cÕʪÁw¬\Y;׆•µXÁâG’ZÖ­n0ÞshÖ.öÄÂ…\»&*Gùqseu)7V¿–ãáÂêés¼\XýÎeù1UÏE+«žé\¹²ê’âíܸ²–o4ùܹ²zÜT(LUK®¬ž0çÉ•Õ^W7_hÎŽª.®¬ÝÀ+kçáùŒŸêo‡9 –^¢¶¾¾ª­Ã3]’`=êƒ$X[ó‡Ý$ÁZ’l怂cÆY7Q°VÝ Qp¨½È†c¥*í–q‚`-{ç™ XGÐ+H† XV6ÇEÉØ‡¾ cà —2®ø-8p9´…–ªJqàÐÁ€ñÈùȵ$Áe£òL¸nºÅØ1˜Ä+6Á¥•Á[øm­E†Áñp@&’àZîD –© ­šH‚߇˜ê‘àzoÜ<‰ãJ’`}«±a –± Þ¸H0$$ÁP,¬Þ)·:ÊšHpÛ´×$ n‹a‘$XohŸHp«-û„‚•Fv0X¬êÉ× #€2QðûäËz‹(Xú¨}BÁz÷ç„‚!‹(X«Ý£+‘ÆzUF=÷„‚ñDÁ­Î+¨*Åz5Ö?ú b½*"éÇrÕM& n§|OD‚Ýb’à¶‹é‚#꘎ ¸í²©%~+‡ôoÁm1 ·:·AÕÁÈE¬æ½Fó‚-v.à°’‚„ XJ?â#Ap×BXsv0¤À D!`í-®DÀo!3k‹"!`Íj%°G•°Š™°Œµp¸&¬7Ï„°Þ NÄ€[-û½‰‡©Ø¨K ¹È€õi1‹¿EŒˆ ¬]>¢dÀÈD °Ô¥xIbÀíZÙã‚À~‚@¾$ ûSØoE¸•Þ”H,Õ-ž0r+΀ª™ô·•Õþêö‰þªu+% ¿ÈEúÛîBÑ_7†ô×ý"úÛÊK Ð_$!ýU)¤JÒ_ÕtA[P¡nÒ_I`™$ú‹\¤¿ÈEú‹ºH‘‹ôç¾0ý¹.ÓŸ‡„éÏu™þü¤¦¿ÈüûF˜@“øç5SøWK6Â?ODã_HH€Q7 ÐSÁX’”HÔ5ÖTX'ü6ä)ò_My¨²ÅÝbñ_HÈž¼æ? ZÃ_7Žðç7gúS _?±Ð¯ßˆØ¯ß¬Ø¯s‰ýÆæFöó(7þu[„æÆ¿3Â?OfãßömHˆ[ÍY!—S÷”ðÏ+„ñO‹šé/2‘þ*3šCúë$¢¿n鯇«èÏßwÓŸ?–¦¿(†ô7 PPñ/Ê!þu· ÿúõ ÿ¼0ÿE _-¨·è‰ü×cXüçÏŸùÏ_øçuYø×Ã\ø×­!ÿy³fþëÑ%þë™ þëy)ì‘#Œ4o/«ce캀ýàÀm¡FÊX›mÒWÕHaüûš.n;´¨êðCøi€)ТªG þysÙÚý+1D€oiè’‡wèD€ecöâ[ºÀoXƒj¤ \C)Û7BÊÀ¦)·êp¤¡2°,·’TöNDÊÀÞúIØ+¹”ÅMà A`aát\¸Õò ‚"~(Ì`Qà¾ÈD\¸›K,„¢À2v'¿‘÷Ò&†€¸×þ·†ÀþMÜ¿%ýžp?Ú<Š˺ [1à^^'màþ-¼Â€ ¸Ÿ åÄ€{‚M Xß-^qNÜ¿M5†dÀ"?ˆ«.hSÅ€ÕÂ…º?,WãÛz#F{À€û7Gq³‡°2éF…±hí§”žDÀ¼kÖ^WÔMØ¥÷ºÉ]Ÿ5«…6­DÀJ³éæ®±fíßÐÖíÆX³ªKtÙÔØ[–/ƒâebÉê$À2ßãzÀáA{d¬Xõ:u!*V¬À*G#°dõh#îÁ—vX²ú1I€nž°RØïIØ]#¬5’ñ…€ï!CW"`•ÌXD@~`÷°›#ìçV1Ø‹‹kƒß€Ý5bÀn 0ÄÀúÄÀh 10ª&öËFƒÉ{™çÉõf¬Ê1ƒÄî-a`W. ì ;)Ð]#¬‰Ž±&ìžÖæß}B`÷„ °_!°ü|p¢#ìŽvGû$ôˆ»nq`?¶8°»FiÈQ9°šóN(ØO%ì÷"Œrˆ‚‘‹(Ø%ìn' F¢`ùN©ìr…‚ýª„‚ýäBÁ(˜(¸—Ü„‚ýÝ öˆ vïû… ½]²QйŒ‚~.£ Q0Ò˰ 4&¬åü·&A7Ø$U“£X’`TMt—šSÂÅõ›Ø  ýöŒ‚ÉFÁnŽP°›,Œ4DÁn P0%\[»Ð`Cô@¦€‹kK„žEÂ.X@i„ëÂnŸ€°ŸA@ص ûe Ç.¹®Ë«0Ê!Ön‡ZDa¿>aä"v]$Â2Í'¸‘k“8é»\¡g£‰0Š!zµ2–…?“ˆÐ3ßDؽ,"¬ÚÁ`"ÂÚK.h ‰0$¯ØUœF"ì6‹ýu0zp‹»»H„! zS#"ìÇúãj"ìá%"¬bV2¢Xìj „ñL¯ÖW¡VFó`7Ø6$ØÍ#VoI‚Q0I°ŸR$Ø},ì¹'ì’…‚U9„„‚QP0ª" ®å®ö[“ Ÿ@ X à³) A°ŸI ­#v «º-âÀÇ.…«XœÐˆ»yÁî`wŒ@0$Á(† ØíFr`W$ì‹×SâÀºãc2]Onˆ+Ó;„öˆFUäÀ£dr`[]ˆCBì>FÉäÀÎ%ì6“»ÉâÀÈìrÅÝbq`w 8Ð( ŒLÄÀ¨‰U#Í£ÕÕU½Z]Q•)ÐU™]Œ)ÐU™CB ¬\פÜy,ÛXß³ÄÀ¨‰¥\²³±ä–ë&ú1Q21°Ëúu# 9°ËzT˜# 90$äÀ¨‹iÀý"Ä!ö“‹£r`×$짦„‹kKȵ}Ú&»ÐHCŒ4ä@oºÌ‘†-$F.r ‡©0°¤À~¢ÀJ])0¤ÀÎD ì‘# Œ$û=ÏWS # VV ˆ€^|€Þù½×ÃpI\oK2Ù„~;&ò“°6ëû„€EPºC@L VÖ&¬ @E" pÝ…ï"ÀHCŒr‰€õ]€i®°Ê™B»d1`—,Œ\dÀµî!ñqqÝ^Ú¾Š¿m<õ˜bÀµ<AodÀhýJŒ$dÀ’Ðþ X—?œé¿ŽÊo‰Ø7 ­éX×&í“#à÷Ù‚ûzÙ÷}’Û-r_©Ä`<Ùž€b{–qîÄ}µ³E)r¬M$ľsÓ9§këð[PßµÈ ÍŽ€+­ÛìxP'Ý~€»¬­Ú!sÿÜ ð^u k7À…‡êò< xò´û1„¿‡?g'@ûÉØ Ð.Wölg=¹~ˆôRB7@{4‰øÚUÊn€uQÒÈ ðZeVJâ+3õu2þ,o8(iíH—ƒöü2Ÿ“àˆ© (ð=»lŒìø½S*åxùúuú)ì}Q9ŽU÷høÊ5TÑ•°&¥kÒy«“|冺On€g½^1…5©îžrxѱ‹,”áMX’ê2ªIñw>ò½îßXV<¬H•Iq±$Ïë€X“J¢;p°&…¼w¾›\óÈ{ç»ÿÒ…"5S#q¯RðâÞùÊÑR¸wÖú@¸ÃšTÿs²ý%资 w >bÐ @¯òP)GЋRz•i‡Â ’ÞuÈ‚V¨åõ¼™5ë]‡laÅz•æCBÖë.ë…„°w²}ì…„°W’øØëæöºÉ„½ÈCÚëö‰öBBÚ»ê~¾‰ö¢Ò^¤!íµD´—®«~*Ñ^-óÏD{Zø {ýT‚½öz¤öú¥ö®ƒZÃ^¿Â^ÝfJõ#aÏߤ Ž$å^}ÞÉijÝßšñênË÷¿Z÷…Ð7Ö£áM¿p裋_ÉÔí{øiÎ ÆÃuôÈÈ{³#ït$ãÕE›Ç‘>~µ¢?l ¯.°]®¤¼§zmÉÛ^¼–†¼*† €¼ÊsiÝY0q¤‹_ô ¯.0†©)/ƒñâ7/Ú wI^±ÑäÝ×ò] Æ*ôÔ ,ïR¼+ÂÚh ¼+|Z饼«4OÒ]ÝCü¦Ug xH@º›$cJÉ »€îjëFgNÐÝSßJàëP´ŽtW’›×­‚3Ò]æÝEU¤»ªkáu¦ »¢Zú¹’îžÚ·¥c_4t—Åï&ÉXˆžºuM1DÆJ”à]UõyÇKWNº‹öî¢Ò]JÞE! »,tIwÙÀ] , ¸K à.sîRº«ÊwÞ º«kwï'•y‘‹t—Ð]”CºK è® pN¸ËºÜe!€»(p°]æÛU±(Ù.ª&Û¥låíR¶ëʉvY Ð.*'Ú¥h—¹€v)l]C¶ËÖ ¶Ë<€»îÊ‘~ãå-€»”î2à.ª"ÜEsw)Üe.À]JwÑ„»”î2øn’àØ4jâ…„ˆ—’xQ ¯ŽÈh¡9/~ð² Þ$Á‚ÚO@ÀK /sð&É‹ÙÚ¹xÕœk²êì\¼Î%ÀK /sðRÀ›$µ¨ÖÅ¥ γ x)€—5ð& Öð²&^¦áM¬­î !ž_–/2‘ñ& –Ö€ñ¢9d¼LÆ›$X\ë c ³Îò2ÓƒÅ5X\CÈ !/%€¼I‚ŵ;‡—’}Ó„U®ƒ‹kHä¥ä<ç +Ê›$\][Ϋ‹Aî5ýüJ²ÞðD|7MXåz_MXJÀy)X¹¼¶dÃò‚WSV’ë«û‚œ×C‡˜—I€y‘äâòÚIn.¯-åM.¯-y¹¼Ö-€1PÞ³¥‹_ ¤äJÂKÉÆ¥9v¬«øqpM•ŸÀ®.&9h¤yrI­CõTãEp]-ˆ\—™®©-×E.rÝ$ášê\亊K€¡¸.%»^´vY2À.Óì2Í»ºÁFZ=¬©‘gp]Ý”sa˜’ëJ‚Æü+¡‘|Íçñkòì+‘¨Žàçá`ðk>#øPœ ð«Nìð«¨d/‚_ÅëÃér—¾Ë…·»”EïšFu;û±%ùÕÕûÜÐêv—rUKí^­z7†àWÁc%÷ÕRI øÕíû$0€ß;¨%Á¯./_i ò«kôI¼ ¿ŠÅL&&úÕî[¸õ½µK$,‚ý*{ðW±¤øV™ ô÷~ß±ýM¿¾J# ϱDùºiÑ_æ!ýÝÒÉ‘ýÊ‹zOöë»sÈ~ãðWIx1,á/ÓþÞš’Á~™ì÷–ãÄFE^-O}ùÑï­«2é ô«R^´ô«} &ŒÐ¯Âp)ºÑXœj3³Lz½Š5­Ð;X›F4\Zmbmª« dÙ9ȯB œ©Ö« ówØküÞ±ÉLð‹¡Ið‹bÀ}QŒ¸o¶M+Î’ð&ÏÁ}]±¯âDà(Ôõûê¢~r?±/ öeK„}eR•:½û\ô¹ öE1 ¾šŸÏ™ÔW±/–é:—ú^\4´õu1„¾jÍèë~ô…ÐÅ èËR}#DmB_{;úú Cè«îÑ‘újMý©/$ ¾ÈEê‹×"êëÖˆúBêË\À¾”û*dÝI °¯–^×ìË\À¾”û¢rb_Höe`_HŒ}—>+ƾKç&ľÌìK ±¯_°¯›Cì‹^&ö¥„Ø×}!ì °ï=OÁ±¯&ÕµPì‹ö¼?]å‰}½ö€úzj úz9%õ…ØWÑuŽ#±¯]/D}Q1©/$WÓUÓƒÔWáFãIÐ×ý è  ïU 1_Å—áE+D¾º¥bI^7ÆÈ÷V R§7âªCâÛtḉ/$ ¾(–ÄWÁ¢&à‹¶ø"oDbFßwŒš|5P® øBBâ«‹~òJÏ3—&”¾nŽ€/$>’øF¤Ò´ßÌÊ|! ðE&_ÅZ™x/ª&ïµD¼×¥ˆ÷\Œp¯«î…„¸Å÷ºÒ^¿Ñ^HH{Q i¯‹ìéþІ½”ö¼©5ìuÁ„½®[°ço`/òöܱ^»'Ö a/Š!ìu1„½Û|‚=Å)7ëÕ%“_Å;ωõ:X¯îœ¡â¼×¹Ä{õ2xí y¯»Ì×#VÜÅüƦ‚_ÔMð ÉÏ:%“_HH~Q2ɯ[,ò«ðVojôRBò;„&¿ü"Éï¤qŠÁ¯›#ðë$à¾~_H~u UÞèùÔ>T1Di¯›ý¦ #Tß¹FÈI2¼ÑŸçëTJóï…Eú@`lø»K:‘D ¥%€hÄÀÚ2Â’%QEQ”%]Ôúd„%Kº(‰º¨–üg‡Eªë2joüŸévpõtý·þßO~? ö ÚèŒXósHÕ`©=ú”HE9æ‘JŠ˜G*ÈiXN$Q1ñHådÄ#Ô©XR&rQŠyä’:æ‘ R•ÓI\Œ#¹œˆx䂜J%ýa‘öo™]¾ïÅÿa‘þÎ7ê¿ûÚüÑé8`~¥þxÀþ¾¬¿i/ëöïKa‘Íèþ§ÑŒ'ü£ H]é|þ  O8‡Eú÷âÕ½ëý¿3lÑ÷ÝÉœÿ«Å¶è×ÇÏ×Evì¢íŸÇ.Ú·áÊŸo~)°©L³×Eaãè¿®®Fwz…äÁ„ºxo¯[¯òM(¾Û‡¤ dû­âN¾·5Ž*r&,º>ÉSVÌßÎü„%Ö¾/'-Eyw÷÷xLоñXè¿g\êoëõÒÿc¯ËW† šl÷º:aØ ÕU‘£=ãb„Jóðtl¯+¶¶pFØw„Óü’QïG\øú8ŒÅúmN+ºSE â½Zûþ,pNxùs¨Žð|ì7B»<°¡ä÷+"}’·Ü˜û“·ëpäGÃõký1ÌÏ|[ú~ÔÕц>ɸR·þ|;çs­K n¤A‡tøœý¸VŠàýIF„íô±÷°øî{á¿…ýàôzQGqiø/|‚7Ðïg…(FW쬜0èc¾•N MòI^‹ ½ø~~”sê¯ó•öuýû‰QF㓌½ˆ/»ßÏŠ=b<|ï§íz÷r'Ðû©Îç¡=,ö²à_3Ÿ6cíb±—-ùrdsÊüŒX û…‹&žcö½áX²—-çsæS–q‚EÐ\ü°'ƒEЬû¡ñ"V”ZçSW¾Êë~‡‰V¾ûUTõ¢^”í×;<ŽÛïe¿ë„jø´ìÌuÏV3õþ>ûcuÚï:¡z²*ÖȈë¢Eû]'To<ö ³á~O÷ˆ4Ûwõï7v}ñŒ÷µ ƒ[ìåçSóÔ×ùï÷}F”¡½"šŒyªð;{9ÈŒ8 ³×ßö+B|ìõ?ÌTÍžŠC0fª±qg˜œ½¬MÖL‚Á‰ög?ƒIo²ÂÆ-öeÄ‘?÷IRçSoôLõq„Ò>Oßðaú$/c0¹ÉÏ…LšïÏ÷šƒ‰^#öðÖuŽWÄvúXîú1QGœëÑ]ôÚ‘†Ï5|Üyå8z©mª¼N¨î,5"Ûî[>U)™î'G(©%^Diƒ®9Í»r¦Ò¥e¯˜˜©¬ýX–‹3•Ÿ›cYwÌT©~ßï…•OõIž_Gôè±ì'g*ßݱ;‚0=t÷9–ËjJ°¬Öƒo¨ê²êî:–˪_ù±<‹'ëŠÚŸ‡“•]ñ-0ã:’H³.XV=#Ž 9MÖO2|{è+AúSw Ð#âuUÌŸô£â6ŒeÕM.ÇÜ5^ðQ7eŒeµ%÷ꎺ=eL×Rv᮫ŒÙw¬¯ÖÕƒö“h]¥ßÓ±-\W]pEVëªöQWï¯w/ØÇ 0BöÑTøØv-«zƺy,«Š\wÔ}Øï~wG]¶:f«².ô³µsÝXV#Í3–Õê<Ôý¼œ¬Û‹UÕ‚}9æÉzì+WÕo¬Œ«•> VÕl\U«cGïpòèÊQ7Ïɪ\„PׇŽÉÚ¹.,«QòeµßÕ^‡TÏ$y¸¬º“÷W˪ÞÞ±`Y­ýÍ8ü$cYí–oìÀPùyÇ6ÖÕZ".$Ù±®:ÊÕ'y8[5ªãäl¥IïQÛmÍaq\XZ»ÅÇ…¥µ{縹´º/އKk§©w=vv¼Ó÷“pi½é•xœ —V·ù,Eî>I6,­Ýçvÿ˜­ç>îeÉ’¬®Þ3ç¹üšÆyÞœ®útÈ¡ž8o®®þ’•w瘮7\8rËÓUñ*2ÅÓUÛ×£Çt½áz”ᘭµE’õæl]àxp\¥Éݲ÷.lÕ¢ªòÒÓµÓ”KÄ“ýPè0¦k)ÆàâÚú ðÅ\cù!@dºÇÚðpmí$ïX[ï{…«Î'àÚzÓIG +Ò ;FðÒJ#Ÿâ>8Q®¿°HøW»½w þ+ (΢€÷Å»ÂÄ€µpâœY hS! õH"ÀÚ€àÊk`iëpÊ,|ëÆÃ1’D€oâtlSà²kß#\*˜$$Àyá_…+äÿj!ÜQñïC|1#ðÏWÿ|Ñð¯”M'bª» °YÿùÖ) î0ÿ­0èþóæ¿2Õ.hæ?ßíeþsTó_•ŒMšø¯4P .ñ_­Ÿ7Òÿ¶U0ñŸ/o7ÿ•¯à†ºÀU vÜ⿲B“ÿÖ—l,üó=ìÆ¿Z–€ñ¯”_ب ÿ¶ K¢éÏA LC«6ÑÂÒ˜ýòÇè·†A¢ß¶k÷/ôÓýô&¿šQØ[‹ü|ǾɯÎÛ0/H~à`òs¡Ÿ/l7ú±ùâ>_¯oîsXs_MT N¡Ÿ#Ûý*tŠ!ùùn“ŸÂüjÀàç ?„Ç0õÕÕMÈ[$B ìóuóâ>‡"0÷mß`Ÿã"ûjÓ„g¾#†>hƾñm‘ûJ+:¶ƾJnö9†±oûúk¢>‡r1õUœvˆúj“‡Œ¨o{ëÌÔ7¾¦ã™D}µñ÷@Ø×Ý)ì«,f¬°Ï}Eê+=.&£¨¯Rà#Jêë$¢¾êNôŸ¨¯Œé0)D}uk'ÀÐç(†>_ìiè󿆾 ¶O}Õ7HBæ‹bÈ|Ý5b¾ît1ߨ%ƒ/É|Ûsÿ`¾ c‚òE 2_­W;° ̧Öùº Ÿß‰‰oØž¿ñEßþͲTHâÛêûŠ\$¾}ÙÄ›$¾zu/È‘Ä×iD|îsß¾ðÚg_¥Y@U$¾HCâ‹r@|•ä¦+i ”à+0­ïEÅ{Õ1'Г¼çÛaÍ{!!ðyÊø<1 |žr> |žr&>L|Q‰/Òø¢Ÿµ‰/Ê!ñyT‹ø¶›w¯ù¢* Ÿc÷ùüá3ò9<‘ÏÞÈiˆ|žñF¾nŽÏ¡BŒ|ý&„|Q‘ϼŒ|úD™øÍÄ×/TÄç?">¯&¾.†Ä×.âóÚbâó2`âs Ÿ—Ÿߘø¢rŸ—:_<‰Ïñ|L|^ÛL|Þ˜øÉÈÄgu®‰Ïa§L|Þ¢˜øú)H|Q‰¯8ˆÏ ßF$î9Ny/ª%ïyËbÞsÀ>_¤!ðuÛ|‘†ÀçŽO[7ó^í÷np#yÏ»HŸø¶ƒgò>‡!4ðyO(àóÖÀWzðõðuß¶ñÚœÖÝ+Í¿¢ˆÌ'ßf¾÷«ÖFb¾&Œ‚Vüé ·Vü)§½ÚKñ·¯VRñ÷mty0,Å_™°cÇ(Åßþ‹­ø‹4ľ¢# €°¯j›ep¤ù§¶š$¿ï#%#Éï8`Õ/ð;N^1`ð+“,ê ü¾1Ìý·À︵±ø•‰žHàW&Z8üùßÒ"¿"®z5’_öJ"¿ãëshE~ÇÃí‰É¯ÒP?Gò;¾¾!ˆüŠÜΉüÊ€ú$‘_ÁÜ=‘_•ƒ&ùÅ>¿øuÝ¿ú‡€Fò;WÞógòK Ö«ÈEòÅMŠ?×-ò+ó5TMðëD¿ýÊçB¿~D¡_wƒØ¯~Öúß¾„ª7²ß¹¬RØýúˆýÎ…¡ŒÅ~‘‡ìG?‡À¿nð¯ô-üëgþÕÒ²Lš¿ª‹@Hþ«¾ÀTÿuÉÀ¢Àü÷€•/,‡¨qÅ€%¹&<ncÅ€5æ¨.$H‡ØÓC’{þI<lOÍ€5}¨§$–¥$¨A ØSL Ø#@XËù x#†„X£„ê7B`}ÞIõ×#IØSU%ýXbÀz( GÅ(@B`?9!°¼lp¤!ì®VE$…0âyÈ6åÔK›òZ"ÊóQŠA¯áÊ wò˜ß¤gn2é9ÉŸ£O¦õ´Kê¥D¨çrˆzQŽQO;+¡^ï‘õ §ŽzÞ 6굄¨çšöÜÓ^óŸhO»nÓáN¨çjL{¦AÐ^ÿÔªj=ÞŸÓÞ—à,Ú—ˆ—H{^ |µC‡nHÌW¹f]_å¢-'™/Ê!óE.2_Ô.滬Ù#ó…„Ì0ß·­¤œ˜/$`¾~1_%¹']_¤!óE2ßXþ äkˆï^pO«‰/$$>a›øBBâ+ Ô">Ž›øŽ[šQ_± ’E|ÞJ‰ø:“ˆ¯2Áf™ÄBŸO" }!!ô…„Ð×5â¾ò¦Æ™„¸/$ä>oÈÌ}>õ4úEÒŸ4MÞ šþêäî™T}>Ë3ý…„ô×µ‹þ¢.Ð_?„èÏDz ?o;Mïü·€¿¨†ð×IÈ~>!6ûõÛûõ»ûE²_¿)±_ä"ûE²_?ƒáï°†Pð·Â"¬Ùï°†ì×yÈ~‘„ì×IÄ~;ƒ!4ûµDì·KÏhö«‡ƒìï"‰÷x©\ðÞÅÐb¡ÒÛ„r½û–ºîÏ}ù6ž 5îÓ„{5»Ž´äLq¯Ïa…{gÝùEW¥º;ª7âÞùÊøÐ¾|«\¥ìË·Ý€{uÑ>ùò]‡…p¯Þ`N®|Ë*½àpåûZ Ë!»òm‡$òåÛسù*H;oræûú»;óÙ/ÊÎ|²g>›nÊ™O&ÔíÌg–væ“B´ùäƒcg¾UÆ…íÌw åÌgo);óÉ ÐÎ|›ºœÀW{Ým¾Î$à«-3F€ùì6(àëÖØ™¯`‚Æ›ræk÷>9óÉ9ÎÞ|à»ò­Ô‰våÓCÚ•¯Œ†Á¤½ÚÑ•{ýØöä³ÿŸ<ùvHÚ‘o×¹<ù¾v£ý&=ù_©=ùÙÚ“ïäâÛž|§ôÇvæ ùN©âD{‘†´WnàŒB´W÷Ð?Ž´Wi`'Ú+L™Uzu‰ ¸M¾|- /ßÅeËÎ|—(ìÌ×IèÌW›-Âù¾O>ƒõêB Y¯.€:'^ñÒ9iôꊺkræ a¯n²:É—¯&pK¾|·‘L¾|4¼”#ß#F·#_­¹F9òµ„¤÷ÜÂm‘^¤!éÕ¿t¤'ß#Lê=ˆž|ìÑ…z•—ú2¢^ÝÍ…¯‘=ù:<ùBÖ‹ªÈzÏ7­0WÄzQ;Y¯$Û¤Î{ÞI§Ÿ¤¼§ŒÓ È{ÞŸAž›ß.|jˆ]øXJ»ð½:á– ß+¬± _'!ãÕeËÄxÏûÉxÏ‹èuF¼zpÅ#á•N9"¼·˜ iHxoq~$¼ *xM„W’urà{¿©‹ýŸ/ÒðBB«qqèÆZúÖ²=9ðÕ=lؾòÞ¯[±/äE’‚¼ü‰Å4$„¼’`K(È{×óä•ä òÊpé™ ¯n…Û&È{ëØß‚ñê.ÕuòàëªÄx‰ˆWåÞâ½Û"—>"^Hˆxu ç‘|Q ¯2=©Öëæ ñêÂGØó ñº&!^#Ä‹\d¼šÐÈDÆëæ‰ñÞÚG" /šCÆ«4'Ýõ°˜VÁí;ÁxåܳO朑‹Œ÷nT ˜ñºv2ž[,Ä«»òî´æ ¯óðºf^µî™Œ9CBÂ{7îNMxõõɯ*_'cÎ(‡„×=!Âë’ExÝ"¼ð*×A–Ó.Y„×!‹r@xïÎ-ª ¯¼®0cNäp=$¼~n!^d!â…„Œ×=!Æ{÷…ïb¼î 1^¿+1^ ã}ràëŠñ" ¯§ƒ¯gž/ZHÈëù@È«ÁMò¢Å„¼žœ‚¼Z[Aœ‚¼òܾ8$'½{\®w´8ƃà®oMÜõU„vÒóU”í¥§kí¦çÀ9‚»¾¶OpÂÝsÈkŸlçûׄvµ}å}+ »Ú]“"/ Øõm» [ô¦ÏᆈuÅH\×ñ‡×U¬¡E€ëŽHX×ሄu‘‰XWˆb°.%À:Ç$Õuð Q]í_leIuƒèZÒE/% :Ç)Ô…LWåGši:â‘.¿ˆ ä, º€è:Þˆ®K!Ðu4$]GÐ9’x.3çRžK .%@ºR$¤K .šC¦‹4dºIR«P u)P×áu“äA%…UÔ¥P—¹u™P—iuEIPBÝ$¹ç¡%€º”êRª›$cêøLĺëR2°nŒe(%÷üX7I^DyP#a]‡kÖ¥Xåë2 ¸.%ດí¢v¢]J€v)Ú¥h7I^Ä|hÉ@;Ç)Ùµ`—¿_eq五€ë"°.“ë" ¨.€º€éRð ‹€ºëB¬‹åXç$¢º ¨‹ß€ºà€Ô¿÷k¨.%@ºIòÌ‘“Ät)Ôu`"A]–¨Ë4€ºêR¨›$ê¢dB]Ju™k@Ý$ÀB’u)ԥ䃺é'VÒêR¨›$XJ»ûu‘†P—@Ý$ÁZP]J@uY°n’`1\Àº”ëR2°n`= ÉÀº¨‰X—`]d"Ö¥X—`]JÀu“+jÔ®K ¸.së2 ¸.Ó€ëR®‹\äºIòü:'À.%ìR°›$"'I²K È.% »Iò(r’$÷©ÈI’<\Q[²›$·"'QB²K È.%Û2‡:Ù¥d—’cSè$IÎå×: ¸¤*tÒ »üyoŠ›„;È.Ó<\R;ÍË%Õ’Ý$yçÈI"»”€ìR²sI —Ô–€ìRrrIõ-+WÔ ® Áõôǽ,!x±žv%/T¥ Óu€01]J6.¨’ü Á†|/'BôÕgcKÎ÷PÐHA_ÇXôUì2†4zãË;ÝÎY Å|;çòêxßœrý¶F¯ï²Fo}gÀùÕyO=û‡[£WßbÞ«)ÎïQ±½¦F¯>l+I§õɤPœºC*½ºê}¥Åf¹•—ºÕÈ€ó¤O¯Uz*gb?„äù­Ñ¯m)Ú€s…J£÷maí’GK{@Ù€sÓƒÒèU#xa§ 8åðdN©‹Û€sOÙI¯ Jå¤wüÐèugbò_T%Nû8Ú„sÕ­6á´Yª4zmFkÎ7:¶§LÔlÁyêæ[pZ¡ÜœRáØ‚Ó^—¶à´™o[pʬΜöôçî»RlÁ©ºä¨'{#kõj½áÍ(Ðê…e¨õd†ÓŽz‡¯Ö¤VÏÖyöÓ+åÖdÁY5“ g›çÙOïÒ$Rê ³ §ß•M8/©mÂyHÚ&œv—“ §ë² ç¡ûiì§'Ç2›pÊÔÉ&œ‡ì Ú„Óš¿{êr›pzhµ §eÃé·k΃®êaÃi?8ÙpÊè«m8;—Œ8ÛTFœþ؈Óßq¶u¨Œ8eÕFœçË‹LÚSOæ«2âìL²âô[°§^»îÑÖÄn˜¶âtMöÔÓø³£žìgÚŠó”#¸­8ý-³£^Kä¨'‹8köz*J¹gc#ë÷zôKÁ×fãRðµA’|mïFŸ e­ákc(jød©o_ä¡‚ÏÖóá¯'ã6)ø<Û_Ï&URñUU×tcK{€HÅuQÅ×¹¤â³]¹U|rñ´†¯­æ¤á³…°5|á) _›LIÃ×n-Ôðµ;Š4|mÃ74|ýD}eË+¥¯lq™qʼÍ8mÖfœ6¶”§L¹ÛŒÓr6ã´©˜Í8Ý6ã´éÍ8Ýíº§÷k3N}ÛŒ³sÑŒ““ª­8m®g+N[ʈÓ/ÅFœ®ÇFœ6d³§{ÝVœËfœê ›qªy¶âôµçõó¾–ðÿ“§>¾aÅ©Ñg+NÍù¶âô@·§LmÅIûù6âÔ„o#Î6ë” ¼® ²§g|qÎ7tº'léMPÛpvódémØprÚ„Óæ¢m©1û&œK&œÚ)µ §hN[ÁÊ„S‹G›pºÏi©G² §ç¡m8ÛxÔ6œÎ%#N?SqêMµ§æ¼8µúþ¥§ mÄ©.nNu–m8O]cNÍ2Ûpúû-NÛmÛ†³Ë¥ § ‘ ç¥[’lÂé<6á´Í¸M8µ›ŽðCßùm\#ÀÞ¡=$É0Bž¯S)Í¿~輿ѵf K:ÐDs¤%èçq3’‘%]”D]TK¢¨ú2ÉÈ’(Š¢(Ê’ÿìðCç»uþQø¡ßBt¡Ãá‡þ$Á¿~è÷ÃàÜëêÝmŠ ósHÕ`9FHÅL¥²[HEEp!•ä4*(Ò¨œ-¤‚2¶JêT**S¹,ErQ^È%) ê4.ÇÁ…\PDrINå¢þD­T)ƒhû«DÛ_Ä úÝ@ø“D_ºóÒýˆAôÇãê÷1ˆþ·ê¿ûäüÑgé8j~ªþxÔþ¾¬¿ƒè¬ž¿ÏIÄ úÿõÿþ¶û²ÿ³ÐAÇÏDŸ¬ÿú/Ä úOXWÞ翃èüöìË÷•úà DßûüïýßÿæAÿ,Ñ—øÿý¯¥ü{Ÿ7þþc…ðÿBL¢s¯¥ôû4í#"ªfêú[ÅTø³n+…F]R7N>É[ÛØ2l¢ä¨¬ŠœüRg{æd/w†ü¶O#Ü÷W¼bø“¼µÛZ—‡ÄqÖyRmc+’û’áf¸:=(§Î°^¡ÞÈU1’ϸIù¬í@e:iâx¸¬y]\*~ŽýVœŸžµËwÖ. ës–ëvmc}³òY—Ð ‡ü¡Îò±X+ÍèãŸä) è3ßó,ÇÝú¯¼òÿ<÷×®¼<ý¬QöŽk¦y9þY¾;Ï|‡5àyž'®Ô5Óg-‡[¥Yy…ý·]píàÆÐ gMÄqíà¶«.¸î~¹N>éùÑø]îNœWÝ‚Z¡ë ?ɨ‡6çU†¡ã¶=z ž×¶:w^ð5nÁ̓~‚«¢÷æÍƒçuŒãNéiÎñZ? “ÎëZpó`HnÜ<È[¤Ï r~ºhœn ÒQᓼ¸yPwSŸ‘Œ[õF¦{9pñ Ÿáþfý¸xp×0¾ëkô'}?¾=ý›uáY±1ª5ºÁZÛ´/ÉŠ}ÿY¡­®¸Tðê‡YRGx+n4DcêZúë·¾+û,;µcê¬ ðÌuskéÓt'ÞŒˆYVÛ÷ žå(2. ÕÝçPÈŒÞZ¯gåœO‚2Ê·„ºsžc\H3$I#¸è1åú>-G\÷x‡ƒit=ßgjÏZ±—Çtõû­øÌáJ·yŸ4ïûÏ2ì^×¾Žò,KêsN²­˜­®jX?Þàãöîã"Ó;g+ï\?+^ý˜­ÈÏ å>f«;çýhhÌVwé |‹±ô–ïב/ëý¾TëÔä÷ÄlU¦oúî1Ø®¥ÂTeg}’›³•=üåÉÙzãäéZj0Äø»–:¾ÊûH>ÉɪéqÕ=ÿc²êÎk¹6^Ê÷r-77£z¤Orc¶jn^ ‚^ôˆüwãlu“ëûÆ‹¹*>Àž%ªé‡¨¥e›ú¢Â ÜxQ/òì7f«æÐ·«8ÆlÕ}ùW­,˜­œTŸ„ûp÷úz]˜®%‘˜®W­˜®üâ|’Óµs½¦«^øµ}ß)LW5p[±¸ú1·k«FúUkÖ4Y¯ÊòÕ}Õö1Yøú$&«_^ù+SÕ×Î+òõàueñ_²«îÆdUoÕmÒ˜¬Nórmõ««Knr²~,­V_^u×iMÖêÆ¡¹Êy²&kÇCÕÍ8ï4þö}8ùGsöƒK«_Ã~rií\¥Øs‚ì—ÖnòÍ¥Õ¥nQ]ÞìöýåÚªWµqîáx,ZZù÷º€çÍyxl\XÝþºç™ß±saåÚv•*ìÎõù[z¹®º±uϘªž¼<¯‰‡®còs˪C¨wYäÿø Ãþ'¾tWÝ1¡•u|1¯º™àÎÕ÷ª»Ëp§¯%WV†±»Î+«§Ë¹¿ó\=®¬~ªóäʺQ¿z—V€Î‹K«Ÿê¼µ´ºœ‡K«?RçË¥µŸêÕÒªr®…K«§Ðµriå~æº6­¬*øÚ¸²v1;WVO¡ëÐʪ }XYÝ娋•UìëâÊÊÁuÝ\XµJ]×Ã…U»ÞOÒ +^Ãõrau¹÷¢•Uo¼<|±²êmÞ«VV§Ù´²ªÿîúßHÃ]äu\Yµé¹*\çÆÑµ¡öR÷f‘«â%bÌÀkWEð¹Ž)×ýp²Zòpimɸ|e¦«8iÌÖr’¾ áÒª—Yµ§a×ð°z´LŒ·iü•_À=§9´´ª'* û˜¯Ú—÷9ÏúBC÷w£Ëeø]ƒïÇÛ"Á ºº`K¬xE;Y $Xá¦Æ9¯@°b'®7H XˆU/¬½âó&ÖFðDUÁò6„-¶@ðyOU¬½ì²Èµ[ðø~ß9øßZ±^€+8ðý(Õ ,•)BÞ›—ol’èÈKÙÑ€»Èµ‹Z‹XÛ¨1Ì¥î$=’—C;Bq`C²8°T¢ $äÀRwÞ`EràòPÑn\^F*0F.pà׿Ü芻òÁkÝ’P$®5ÆG‡Šו޲æÀu¹L†X®ÖÞšÆÀµ¶1¿®oß1:(”)°„ñÄÀËy``íñ¦„n0p=VØ$×ohÚ˸ši \w^Oj tØ*Qàúý3ÌÀMëÉ»LÕÌ a`E¶Â[®8? t +c ›' ,ÁK –ªõ¤ª)p½OÒ¤(0Ò×ëøA¥Ë&ó‘K™=ôL¦Àz1XêlLVQ`?)p­ãKä!vWˆ×Vd†Àõ¢™!Ða¿LîA`?· p½WN^Aàz_°C2®×.2#:˜!ÐaÉ kùœ!!З…×›q©ëEÏA`ï§Žvf \Ë`¬F ,¼™)p­ã@PR {Âí!º×MëË+àX1 ?ßf@Îh ?±ÀþÎ ×ë„Õ…0*"ÖúV"ÿÕ™ÄëÁ{' €ýÔÀÚ¥ÜÖÇ ƒBX¶høkDZ÷€õELþóvÍØ)ÈÃz õÿ¼£3ÿÕ§D-þ[Þ[”FþóÎËü·< 3eþ[ÿj#{‰ëÎû£ŒËÍ+‘ŒµµEݤ¿å¢¶ÛôWËÇJ èo9u(úsðRÐßRæ.¿ü-/Íg ËNÇiÓ_íèÉh¤¿a ˆ$ýyonú+ãIæ"ý-wDÆ¿îSá_÷ ð¯ Qø×*üë·%ü«/î™ø×SDøçª€• ¿ðÏí5þ›UlÄ¿c¡]‚ñÏ>OÆ¿újï“0rÿʹëEâŸCÿ" ñÏoÏøçž0þÕ™Iüë ÿê¹Àn¤¿2‰F òŸÃ× ËE Ú"@;Ɖïë?©í9eŒæ ùÂÍÈ÷Íü™øöçI|Ö›øÖú*NÄg­}ûþ-2™òÕ®€Fä«;_?¥ˆ¯ìÈh:Jâk«;Ÿ ‰¯­ÏD|Ý7"¾¦j™|Ê~ÆÄWVw+õ€´íTóÉäÓl6ù´¡žM>w)MmòÙ¹dóiÃ<}ú5ØèÓfn6ú¼xå{}ÚCÔFŸ¶´Ñg×%£ÏƒwÔµÕ§ë²Õ§­mõy0dHX}:Í>m*«O~lôéž°Ñg×c£O ­4úd.}v.}jhµÍ§Í#mô©¡e£ÏoaÜ!‘ѧ«²Ñg›ŠÊèSUÙæÓ©m>ep*“O}ªmòY7ý€ådòÙͣɧMfÿÂäÓß6Ÿž.¶ùl³KÛ|î?<ÿl—ÓFŸ®ËFŸKFŸKFŸm›i£O)ömôióW}v]2ú¤ám>=mó©<´ù”¥‘M>udÖ&Ÿê‡6ùÔµÉ'?mñÙ™dñéšdð)“ß6øìL2øt&Ù{º"™{öóÈÜÓV6÷ÝBÛ}º.Û}v.Ù}êƒÙvŸ~²ûìL¤½~,Ù}j:·Ý§V¿¶ûìöÉîó:¹4íµ£hÏ~“¶û´¢í>Û¦Ó¸ç\½vóîÙ‰ªqG<{]Žÿ¬¾3î …{‡Õ€Â½v;|ó\­qÏ1îÙ!³}ÿ¤Õmß?§îV'÷„ÝéüG§=áž9ȸw̬׮Šöü“g¢ÿÔUzRõÜ1‰zÔ±­?\êÛñ϶ÿp©oÖs³žzƬ×Řõ¨OkÔ“NP¤g¯g“^Wm·¿û‡Õg×Ýnöàé¹£ž\áÃïOþí÷ç\òûs¯ÛïOÖí÷çbè÷çÑgÇ?O;þµ‡¡ÿ:ÿTp;þIgiÇ?÷E;þ‰°íøçÑgÇ??•ÿ:ÿämÇ?·°ÿDávü³Û\;þéÝü™ãßB¡vü[.~oþÜñO—vüsß´ãŸÓØñÏæ¡vüÓSÚñ¯Ë‘㟮ùˆ Fæ¼ú OÖßwõ¸èɇ[^*JÔW½?"Ы­vŠòí;Ê$•ž|ðíSÜ »ö9²]ûê4ˆ^ytí«;¶ßɵÏ1–Äy(s!¢ ÎK8¯$g:÷=§”8伺+ö:Ò·¯“óBÊKÁXŒJ@-(!/%€¼”€ò&Ƀ8MßÌ\Ò±¯$X‹”—i@y™”—i@yO.ÓaqP^$!åM’'sòRÊK (o’Œµ(% ¼”€òJBgOR^¦å¥”—¹@y™”—i@y!!奔åò2 (/Ó ÊË$À¼IRßš˜C`^¦æEP^&奔™@y- äEB^$ãe0^$âÅ!ãE ^–Æ‹$ñ2/R ‹߼€ï² ð]'!Þ…tÀ] Æ ]@v!Ø¥`,?!Ö…T@] êâ7˜Î‚tñ H×oEHI@t!Ðuì9]$Ð…@×#^@IÀs)<ð\€sÙà\Hˆs‰4—I@s‘dÀ\üË…` \”›$¯&£$@¹($—IžU“Ñ’W³ñH®‹!È…—‚W“‘…ã" (.“€â&É£Ù(É ¸€âR2(n<š’€âRŠ )n’<š“’€âú¡q!Ã¥` \@pY*.’àRðL³Rø–…ßR|›$Oþ$¾¥ø–àÛ$¹LNâ[J€o)¾M’[ÓSà[?%.ï¯Ï€K .$¸Iòþ˜¡¸” €Kn’¼ó$%À¥ä<~LRÜ$yÌR"\JžãÇ,%ÂuçàZ@€‹<¸”à&ÉûcžàRrì?æ)nÌË&ù-~ßó²)zË2žyÙ¼µ€ìyÈn‘dõº©$›NI€n‘ ä« É-3ÜRryñ”ä^~ÌS’[JžóÇ<-rë¶ÜRðc%·E ä¶H²ÿX@Im!´…àü±~Öÿ–ìÉ!f‘‘î¨õ'í5ï:Ž›î”!žˆî°ÊM@'¯%Ûj^4½Ð} T]E¬É[Ï÷rPƒQuW!í€Qr׫MÇd¨yžº›Cš»s‘‰–ÝõN]ú Í]ökÒÜ<Ú]ïûv¨š»s⾯óv:òØWOß)¨íjœÓ§j»jÛ|]‹?RVÛ}ë¶nÖ¤Ú®ÂÓÀ¥È¾zßwçœ|õ*® l ¥¶;×‹í·¯ž‚óYmwÖyúoÍ}k…|&Å]?“4wõÍä/ÔÜË¡[UäªW»šIsWXöNFšµïÊÛZ'Ί;/¾RÜ€*¹¯c®YqW!wP³<õ^Ý[bO½ÎDÍÝy¬ºŒSžzKžzu™^rߨñ oì©§(]í©§øsÖÜ}Ûð_øÅ‡Ì®zŠÍgÍݹȌP®zГӮzn 5wU>ØvÕSð§vÕ;¹[µæîÜeKiW=ÆdjO=?”wÚǵ£ž‚Sµ£žk’ÞîA~kúë˜Qí©çO¦ôvýÑ’ÞÎÁ²¬·ó®Üz»ÚÁ_“§žC0AoW³ížôvõÕ¿&;M@´â®ýq¥¸ëÉ ÅC'YqçØŸVÜõ #Å ZqçmZÄ+ºë“2åx*(_F’¡ £ýi®N¤$ÿ^°¢»v=OV`I‡’¨ƒ“´¤Ã=#èÔVIº(‰º¨–DQo9¨OO AI”#Áv ¢û©íåý·eH¢³V£Û1‹ÎË ~÷ß‘öuô¢¿JŠp —Ãü~„ܵD~ƒ?ÃËükÕ[µ‰ŸÒ¨$‡(RA¢ˆå8 ‹‰*¥Ã©˜ OÄr: Ê4.Iá‰\P‡'R9J¢b:…Kqh"¡‰TŽ© #|QEv}¾<ÿg„/úß­üîôŸ©üáHýùéúÑú»’þ~è¢ZB¾™“¡‹2æÐÅ$úG,ú«ˆDïù_$<þËÿõýõ[â·g¿þ.BÒ'ûÃb6zÿýÀFøøÖ²ÿ¾ÏQ6ú~ýQ`£OüÿõÛ¼ÕŸO ;°ÑõÏÝu2ömzß:ÇùVþ˜ÂËA#Ÿ»6CǸ&ޏòInÜQXŠ}HÊ•ˆ&ócwÈÓc|Ÿ_WnéšþIî_i¼y×ÇzM¿óû¬ès¿õ=h÷ùÆ2üqxÜõIî_y¥ë÷Ê—ê&ÆûcaÞ)Êëƒ>ɸ‰|˜*-ÈU=˜ÒßÖꀽÚþ»?¹Ú·ã›çO2VØvD¿¯2nçÒÔË;ÕuŽûºÓß:ñš“Ô­g>Ö[—1·è÷âNÌVä«~Åë˜ ŸàeP jžº'cŠ×ô,ÅäL3 知nvY£1Ÿä¥¡Ó|Ÿ©-{ô)¿×ëžê:7Ækbÿ}’ӵ˹nLWY9>u‡æñNµ?+¦+{ë©»9Çlµà#É';ë)ïµq§ƒ°<¥Z¹Óœò© G·lÝú徦žXëªË0¨|êôsêк9}™:´üŽ~O}ö0W]ð½r®ºœ$1WýuÜõô VÜ_UÕ¼ætþ$ç*­9ŸñI{§4uZvüÖ×à>Ûžè)«Ý#?lO™¿SÍu´sæ#ÕU™)ᚯg)ñl¥8›Ó<;檾φK’{>¥»’e)Òì¸ ¬gݳ×Wzº>û¶p®¶äæ\U{¾UsÕ’ƒK«Î~.œ«êžý¼1Y;×ur²ª7ö{¬­ÑäkkdzÆÚêó³ã‚権THÇšÏy,\[]L]´Ïi6®­òñ}êà³Uïø-®càuê÷:†9§þªÓ:ÜéÎcÑgÄJ~¦\7×–<\\=ØëæÉ]ÇaÓ»âávôNNó£Žo1]5JÏíµbuî—ç+%‡ÖVuW)AŽkªêÔÚÊæ×¥õ©Cügê­:•ÞònæO¢¥Õ•¿Z[UÎUÚáiN_«ÖVõúµjmÕ·öª3¯9Í®åUq\^äÐòªÉw'§¬Ó\?–×纵¼ê!®›ËkçzÎSöâ5>Ît—rø·vÚþOtð]ªálÚ][åì–»¸$_ÛÖü¬Ý¥ÎFܵMž ½–_Ӈ¤v÷ÔA÷ƒÕOúí¦ü¥ ÎF=µ=Î O)ƒ³QOmŽs”<¥ ÎÉñðÊ?úS1•Á{ÜŽçœÖ’§vÅÓßK <µs¨¯Sð\¿¦iüŒCÙhÅ»¬¿òºOðÎ ×rM‚ê×,ô­íp¼öwsL¼µÎv¿¥ùJäõ<. ô¾9Î^^ÎÓEð„¦µžžƒ‡:š]7`‘¯FÕöäÑÓ·K¥¡°¯Nxqm±¯¶Ðð|à=»¨†|÷Úþïê½/'Jx×î »6p"ÞÕXØV$Þ=¥cÜdàÝ3¦8X xW»ì÷"Ìm¸„­L+Þßï¾É1»ñ® &Þ=Õ„ å€ï¾±‹£iáÝSgÄ2àÝ3è ïjC¿ìï*ÓÝ}£ñ›³IwC»<éî_߀Â@wß—Í™îjÔŸ;P tçàN„»oÈðT w%Y‰i€»o~{LHw™ pW¦dD°] ¶l÷ÔîHM¶K Ø.%`»š§ lÂ]Jwï·ÓXA„»wáUðb»Lò±]þÛSÁ ‡l—IÀvQ(Ð.[´ËL@»,hÅ€ì*Ó…w@²K È.Š!Ù•äKìê0ž#„`÷.4½×E`]¤Õ•à!ë²X`Ý$©5(3ëb<€ëÞ…za{AT@]÷® .’€éB¤ ˆ®_ˆˆ®ûVD—]æÑuÿ‹è2.Ó€éܽDº(—Hç7B¢‹ßº€ç¢Lð\ Î…4À\¿0ÁÜ$0—À\J@s=Ds‘†4—Ð\J@sÝÀm¼æ.0—’s)Ì•äyˆ€¹L˜+{(êýs™0—åæ& Ô5‹0—À\ä"ÌM’óÓí!Ì¥0—%æ²À\JsUƒå²\°Ü$¹MY€r- ÉE’Ü»ÜB2€\ÀqQ0./f¨€¸¬¥‚áz¼á¢ˆp)ÂE&\t-.D¸Î‚Ë ¸¨‡—i@pñD$¸Ì‚Ë\ ¸L„Ë4@¸”á&É£Iªr^® –ᢅD¸IÂ%´%@¸”ì\Eõ2Apù›khg9¹ˆ¶äÚ5M™éæÚIn®¡Nòp í$ß:è-½åÏo‘~Ð[üðö–Þì x˼õ(»Åïnù«¦ßÙsඬïã¶H<°­þ|á|Ø–‚mÔíµu€¶¨Ð% f‹ßç=U8-ód›ïFd‹߃Ì ¶(Ä–‚Al)ÄÖeØ*v¸ƒØb~€Ø"ý¶è'Û$x¦VØâ7Tó‘aðZ÷4uùúý/„°É ?5r;Ò9ßFÔ¹q{[«ãx›Rkã¾QuÍÚ8ÝCbmœâ)Z·- ¨amœk­s¹ÐÆm+®·2®µVRƵVÈÊ8k ¤Œóå­ŒÓak㬠±6ÎJkãß­Ó¥­Ó‘Jkã¬^²6Ϊ#kã¬T±6Ϊkã¬ì’6N78[gEŒµq~kã¥ÙÚ¸n_kã\Ž´q]Ž´qV½X§Kž[×iãBÂ#C]xÑê8·Ðê8÷²Õq¼1¤µqî.hãt}Ck㜃Ê8¹]´2ÎÝ)e\÷ƒ•qÒ©´2NJªÖÅñ>ìÖŵVí/tqÖ¡….Ži¤‹k‰tqÖIçöµ*N½iU\§±.NÅHç®°*N%]\4˜º8]µ.NêœVÅY&Uœ“„&Ž´ÐĽ‰mqÂõš¸ÖúI×z7iâ¬T“"®Õn¦‡³¦ËЏÖ}-Á\wû€¹ú;4©‚¹îÒ\7W4W[ë™dZÉ{ß sÑ6Â\d"Í•j]Ñ\×-šë1!šK h®I4×O%š‹\Ĺ~w¹I¹(™8%“çÜÃĹx™VªsHskíØ)͹·ŒsNcœs{Ís~Ûæ¹HCž‹’És~Jó\”Cž‹4ä9÷„Φå&:÷±‘.réZ"ÛÊeXéú!ˆtž fºê<; u)Õ­u#ÃèSQ¿¬¦ºJ›4Q]ÔEªSDyC]w— Î—àêº*A]7PP¹uå{NƒÆ}zA]Hu_÷qUÔE=¤ºz€‡æ– º(†TWíÝS×-¨ë ¨ë‡ÔuÁ‚:#¨‹L›¼ôuÝ3‚ºe¬ôÿ³™®JL™®K«˜®ŸRL ÓU‡ÎL× ÓõÓuÁ‚:/¿†ºn± .rêBB¨‹\„ºh¡®:‡pH¨‹Ú uQ¡®ûKPiuÝA]WN¨‹$„ºîRAÇ€˜®š7l~Ìt]µ˜.%\Z] ‘®$º~á"ºå•Ž@D×™t]‘€®{FD×-¢ëçÑ…„D%ƒèúµˆè" ‰.Òè¢r]4HiˆtQ2ƒe¸}Dº6éºb"]€tQ®ë ÒuÈt=ˆtî~]” ¢ë/Ú§¡B¤ëŠè¢ ºî]@¢ëÏ ‰®î÷¸€g º(ƒQ1Z¢ë'ÑEŠ3Ÿ’@×E KÁûëÈà¹~0òœÀA<×5’çºMä¹~ä¹Hž‹ûacÄsÝJò\Ïmò\ ž_Ó׉<×ÝMž‹BÁs‘<çýG '»¼ðÝm«02\[Y‘ᬵâS g¥¢.“ „kŦ®$4ÔÃ¥ WÛÙP«§ Âu \ `õ±.Ò¢m´úpÓÈo‘ü–˜}´ôÀ[Àn)èÛûMÜŠ-rë$·HpKÀ-%ÜRp+És&¸ešƒV~?·Lp›$°ú À-ë¸eÚMFÚMvÙM†„v“!¡Ýd—#ÃÉìSƒe8 `8™}D&YNzØÉr2ÒÐr2%°ú M'["ÓÉ®]¦“‘†¦“!¡ídHh;O¦Ö“!¡ùdHh>šO¦d‚xŒÝÚ¦AÖ“‘…æ“ÊcóÉÐ|²´ž ¬']ªÍ'; Í'# Í'SóÉÐ|²‹¡õd$¡õd'¡ñd h;ÙydÚOº"ÙOFP†„”‰”- eä¡eHh@P¶D”)yæYjÊÈ€Ò}3,(#-(C ÊЂ2$´ LÉ3ÏR[Pº#d@Ih@™P:“ì';‰ì'CBûÉÎDóÉHBóÉÈ|ÒÖ?2ŸŒ44Ÿ Í'»*˜OF šO¦äþ5 Þcž¢²Ÿ Á¼Ú|² ‘ýd'¡ýd$Ùç•Ô”‘䜗Ò6 ´Õ”,(; ([ðÌK©í'C€•T¿e=ÙXOöoO†àÇ*jÛÉNBÓÉÐr2Ï<7e7¥Òn²“ÈlÒ"³ÉNòþX?m5é$2š WOå¡Íd'¡Éd `2¿¹zZ@‹ÉÐ`²÷¥Ó“äù±rÊ`²²˜l Ä% &û7 &#?,&; &û7ì%# &; &ã÷´NÂ`2²Ãb²ÿ\“ñëžšK{Éþ sÉø sÉ6^„¹d×G{ÉÎsÉøýNÍæ’ý Ö’ýÆ’ñ{ØJFu°•ì°•ì´•tšJöoXJöoJöoJÆïÉž”v’ýgØIöo˜IÆïgj/­$û7¬$£ý°’ì°’ÔïˆÅcêÚj³÷u=e½B÷2º­•9Ø‘÷’8ô޽ÖjgGûS·5™Òkíû}²z­U\¦Ôœ¥€^k)^kìÈKI: ½ÖR¯µÐk-$ôZ ½Ö›/Òk­tZk}ÖZ@—µã‡ dè±Ö:¬Y µ wµþMoµÃV‹ðVëßtV |ÕZ@Wµã‡ácè©8ªµ€~j- ›Z @[)kE ÈZ!j…¤•‚±T„`Ïf³B0(+e"`¬±BÂJÁX%B¾jñªrõ^M’W‘ t•I@W)]M’S±% «”€®Rºš$÷¯kÐ9-$¯&Á‹Ù(‰ø*%¬”€°&É‹ÙØ VJÀX)cM’²%`¬”²RÈš$/&eK€Y!f¥˜5IÞ_Ó3³RÌJ 8k’¼šœ’€³RÐJ Hk’<𠳫ZJ@Z!!iM’G“tvUK H+%ó+'i¥dV @Z)iM’G“UVJ€Z)jM’gž°b­”€µRÖš$÷+þ>ˆ+þ>ˆË¿ÿ…P:&2ä 5Ø÷Õ»gKFéymʸlòý²)#öÏ d}™UÛ2Ú N¶Œç+¥–<Ó|ñ¡Œ÷Ç~hòLCè ;¦ÙûɶŒŠ©Ýžiá«F#z’nÏ´¾8RžinŒ=Ó”·=Ó–÷ð‡gšœÃì™V¡ˆÆ.µï‰ô­öL£k{¦UäŠ{"u+¤<Óä[%Ï4Ý živ2£gš(·gšP‡gÚùãžH1nÏ´ A ƒGy¦ÙÌžicW´gÚ÷Êß¼K$]çä™Ö%Ë3 ±9šÓâMØ3íÜ8Þì™ví¿’Ô¢9ðLëòLsz¦)z{¦¼„½=Ó.ÆThÏ4…ânÏ´ ½›ÀöåZ9þ욦Ààíšv-Юi×|G¤;Á~iî(û¥Ý;ÜŽi~(;¦ù¡ì˜vëjX;¦Õ€Ÿ=ÓNF˲gš{žií«FÏ4ŠoÏ4 óvMSG´kšÚ×¾iÃ_´oZ}ˆ†@®iI®i-‘kšF~»¦´ãn×4…¾jß4…)oç´Ú;B@ç4 ávNÓ °sÚ1{¦éeÛ3­ö@ó‘zí›v1òPû¦)°y;§éK×Îišƒíœ¦™ÐÎiú´sÚÅøíœv2XR;§¹=vNS «vNÓ\hç´ŠõÃ@9§¹.8§¹1vNSÐ-;§ù-Ù9í‚¢\Óô“~i«í—æWf¿4½U»¥yÙ-MIì•vòêíöJóÓÙ-M“ ÝÒ\·ÝÒ<ì–ÖåÈ-­ë’[š¾*í–ÖuÑ-Ÿ¸öJkÖSw¶Ò4ÑÛ)íbžvJë4òJóØ+M§öJó¸³W^“]Ò<|ì’æ®²KšßŠ]Ò<Àí’ÖÉ%­sÉ%­›G—´Ú¼Á—L.i»rIówÈ.i~vIó`¶KZç’Kš[l—´k¾’?åŒæWog4¿6;£yˆÛÍßZ;£¹^;£y"ÙÍÏÞh2vF³@¾hþŒÊíšÑÜ6;¢yFÛ­®Œƒ?›ÑjÉM>‹AfO4÷Œ<Ñ.†²'šŸžhòDóà–'š‹”'Z§ 'Ú÷‰Ä@’Z è†ÖРͽ7´þ;ýÐ.†Á¡Z·™~huòCsWÉÍY䇿a)?´.ƒ~h…~hcòCó@†šß†üÐ4.ä†Ö­¢š¶ÆvCóÛ’ÚÅOöCsWÉÍ‹ŽüÐ\‹üÐüÆå‡¦v½ó§@nhž'rCó ”š_ÜÐüèrCë:醿W(742冦gX8ïU×öGŒ‡2ì¬×Õ1%$ɨ6š­1É¿ çC¹B«¬@’Ž;#Q‡ºhIGžY— ü¹MEQ’EA”EIE}[«©MøÅ AÂßÿÙqpÞº‹ñø£08ÿ4´Íuüý08×óoÅÁùÝàx¯šúS˜’ŸÃlŒ Ú|O©X’cܰ ˆq£rœDÅD–ÒnXLF¸Q9He*•¤7*¨cܸ%q1F¥8Љ7.lj\пç=ÇæáÃà\çú‹08¿{ûçKwþQºapþx0ý> Îßødýãç×ç>Pÿø£úã›õ'õw%ýý08Å¥ë›QpþCÁkþ¢é4"çŸD¯¹þÿç­Ø®×ÇÀù^óïÿþ7‡¤ùg1p¾ÄÿïýæÐòyüïoÅÀ¹þ(Îÿú7cà¼×‰ûÄ`Îß_¥ï£Œ›‚?Ay+ì<5}¯{ uøìoMËþòòòÓ÷z×É_åÐ[^ï½ÀYa¯-Iý^á«p0Fè{oðUPØìO_…s…ü{c®œ,N†Rü^ÒŽëË¿¾÷¹âtsÅßÏg¸P\ Ýûí<àÓ÷}Gð`wE}ý­c.¼wÊ–`Ù|‚g4«âžCðž£á_Šóö}xÿŒhý®¨7q¼û F‰Œû~>Eïù¶?Õ„:½ÅÏªÕ ÷ó îÑêwƒ«ìûTÀÖ0díûqÆhõ{c+øÖåÑÛ”åÆò˲oÝð¼Ne¼¼éLe¼K¹ÿ¼Ï/þ‚÷^…êéßûèÂ"¤(·×)ņ}ôÂh·ïû}vj=úÞØ ¾ï}t§øvÊûËO€}tgùx`RÜR0„ø·WÜæŸïX*»„¯FÃoÐS]VpŒ=ëÂP¹Ÿ¤Œí‘iÄ´- W‘Ö?ɆÍt ì ’Ì«º?ɱN+É;vÜˉ8²ŸäÄžZùIÓçßï{êÈómíÞ¹î»ê(å{µÏT÷¸`aJ³.Ïôjÿyýx†r¾¦ö¬ß†qú¢´çœëø‘§ÎYæÀ—±¦JðülÞ·‡{æbžÍëªëŽñx¿%yЬûÄ r÷ùyíh^KîåÇ[}Nižó×=õçɨî®kY~|0¯å™Zs­ç'¸¶íG_ûòãƒyí÷ü±¹†:d¬8$X®sûñ×µàBrÿx ×}jœsä_P̦dIõ ¾¨˜íºoJõCÝã ?7¥"ÍvÿI7¦ºûîcÓ@gí7¦¢öóÖ@ççð¾¥áyß[vß}¿?­û¹~Œ’ûå²ê±õ,+ö)öB%y|1Ÿõç²úP/Ûðð”*JÞßù‹ùð¤*Š9çUõáIUg¹~.ªÏíE•àyv >÷Ãê0’r‹Ò»zQå}7.ª/NÁJÂEÕM~÷y.ª‹ë¾¡E‰ƒï=ŸiÓõI.¯ª*çÞ¶ïYô ìó÷ù¹ª¾ï9¤Úe{k1o jIGûTw-‘ó\­Uiþê×G~^”껊gàE½u) ×U})Æ•Sw>UÍ3¢Òͬ·YâãLÇeX€Ü÷Bü$ÈýŽt׎£ÈÙ9@rVHÎJ€ä¬HÎJ€ä¬H.JÌäì׃FÆqõWõãâ$‚ãB ×ã¬0®êÅYPœíguÆùÏùÀ1—U&ǹŽË’ã԰ĸ µøŒËÙçuÈ‘›ß0ηºÏ¾ 0ÎŒó2À8W€qÕ`Rœíšg‘â\Åå”çe€qÖ…‰q¾'`œ—ÆYó@q^ç (.O~Rœ7Wâl£ qV-)ÎNå¤8ÿ гJqyÅ&Ä5åiWdBœ—ÄycqÖ#B\Þ]qV !.oY q^ç Îê%Äy@œ—Äy@œµ˜çeq®<ý¼â|O ¸¦ ô!Rœ+ 8W@qvtHq¶wRœµgŸç[]ý*$Åùž@q^/(ÎëÅùVã^Ê⬠).uIq^f¿õ\:ÅY›'ÅÙÑ"Åù¾¯k¹Ûâò+oRœõ“çÊ{éZ•2ús31ÎÊLŒóÛµŒubœ—9~Ëy Æy½çµŒbœouÿ–cLŒó­žk9Æä8;‚“ã¼–Á'i– ÇÙ½‚g{"ÇùVà8/ŽsåÜ—±N³ä\¹Oõa×Äɽ—ÈùžrÞ>€œ)9«‡ ç @Îj&Èy™c[î‰9ë'AÎË\}T䬗9ßæ¹—cL³±DË7Ä9ë9AÎöNseßtÏa{r^æX¶9e¬äš²>[ r^æá³µZüþ–ó@ó­ÆÕÇ:@®J䪜o³_ý_uoË¥ò™nÈooÜgvƒÛä¾=èžÜÄ·]X@šøïçÛaâ[Œ¶{·I“c4Ïø‹»ÂEÜý‹‰—À·¨ô!'M|óM&¾…0n›79¾Û5&6M|ó¿O|ß± —ß|§ß¼ÄÄ·&ăÈ+ø%.£7û=ámÄ“’Ai[«ð6¾“¸í9sÒÿ>áÍê›ìf¿'ºùݼ‰nM˜ù…L˜èÂýº™ìVû»ùŸ'¼Y 7Ûb›˜ðæULx³-&»y oß ëo;¾ ޼Πo.¼{ÿ9ú¡¼Õ>oM™ðÖ•Á¦£Ñ[+3é­•™ôÖ•1Û¯‰ÞZ™{iͤ·¶Í¤·Væ½×öMzó­€o¾ð­)ßÚVß¼fà[Ûjâ[Ûê\¶™øÖJL|ëÊ»¶oò[S&¿µ­&¿uå]Ú€kÊÖ.G"ø­˜üÖ” p¾Éä·¶—ÉoM™üÖ”ÉoÞ~ð[+3ù­)£oð›7üæÛ€ßš2ù­m5ù­+c#à·¦\çÒ>ð[«çk™g©wò[S&¿µZ&¿yÏÁo^üÖ”Éo]˵ ~³Ó |óæßÚFW ·¶É¤·¶É»­­›ôÖ¶÷2’@o¾è­+ïr„Ao­ÌqôqðÖ œ¯ßÄÅn­È},=»uå][÷^k£Ä°[Wú‘»5™J|›ã·œ°[SÎk9Â`·VÏgèYS+Ÿ¥ @·¦¼ûÚ…È\Ò~?K€n^èÖ•±4èÖê9ÚãTäÖ6:׫äÖÊÜçÒ… ·þ{¬]xïµ ã\ºrëÊúT¹5e_Ÿª ·®Œ¥ ·¦\Kká¤)ïÒ[Sރ0m½ n®ÜüpÜš²¯U€[SŽÞm€[S­¯)ïÒ€[Sž£tp[Ûõû.GÜVMl³Ä6«„Øæ›ìW»ÙÚZ-çïoK½çÓÛOhkʽ÷ÚZ$곿W/0öµc,ͳ5e[ž©ZÔÈê³µ2X I±ô8Bµx<ùBJ¬fH`5‹8b€[Fþ(À-ƒbà¦hÅ·ÕoÄ·ÕoÄ·eà…âÛªÂÛjŒo³-"¾­Ê#¾­~#¼Í¶G|[@x›ý~=rIÁmù›Ámõ±möÛIÛfÂq´Ÿˆmsáa<·•Àè6…àdx› s¦¾ o+ñmY)âÛìçÓ›­ø¶¬AnU‚n%0­†¸•À7P´Ƹ•À·Úäm]WŒ[ Œq³x0ƸU”‹bܬ cÜLaŒ[…)ÆÍÊ0ÈÍ•±Äˆ)ÈÍ”{i £ÜlOŒr³mÞ»ÛŠr³ 1†¹¹ò¶qQqnlÆ87jûó8·TÎe›çVÊ»¶nV†nV†n®¼KûèfÊŸºÕžèö¶Ù’èf Ýl+ºY™? t³2èVʳö`ôö*ÐÍ•±´n^æOÝl+º¹ÂH7Ûêê—¡@­mu¥ˆu³ßŒu3…±n®Œå<0ÖÍ»Ykìæeífeíf £Ýl+D»y™«Ek2ÚÍ7a¸›)ïz!2ÜÍ•±†­2ÞÍ•m[ºÀ€7/ƒ€7/À7+snËïw&Œxså>–C̈·¦¼ËŪ7SƱ´!oV1oö{»–“  7Sôæ[zòT1æÍ7BÌ›+zkʳÜ÷õæÊ»/#iF½ycƳtQoVFQo®Œe˜(êÍ”ã\Ú§¨·ì8ƒÞ¼£ÞL¹× aoþ{,ãˆao^ao¦(ìÍ•±œ†½¹²¯V†½y†½™‚°7W®¥5÷æo‡õæEžõÉʰ7WÆÖ°¢Þª£Þ\ÙÖ+ãÞ¼ âÞ\9z¯øæµ ò­)냕¡o®<냕¡o¾¯w}°2ö­Ê0ø-K(øÍKlý…6ƒß\9–G«‚ß¼ ‚ß\¹®Þ¿¹ò,VE¿ÕÑo^/Âß|›±éšò®}ëM¦sL×”wé™Î0+çRLç ˜Î0+`º¦¼kûÀt®Œci™®)½^2+û¾´L×”g-s^Ku®Ü¿¥„:Wžkíû¯}¿å÷³ôPçʶ/} Ô¹²?Ku®œûÒR+׳ôTçʳÔòŒµïút%Õ™BªkÊút%Õ¹²¯OWR]SÖ§+©Î•kiͽ>]‰u®<ëµH¬se¬×"¹Îr+Û±ô\×”õé:¹ÎŸÇÒr]SÞ¥ä:Wžcmß»>]Éu®Œåé ®óßÛòt×¹²/ÏWq+çïoKÍçÓû ®såÞ{ÄuMyÖ>¼K‹Ç¾öa,ÏWq+Ûò|×5ey¾ŠëR±t;Ûö¼ÑAË&qìó5ÉòíPñÌ9¾]•R™3ãξäeõã·å¶™‚%ÔàoK³Çæo«„ŠWÉ+’bUÛ¼{©XU”¬ªTþ»3îlƒîßʸóþ/ϸóÃc{q•´œ;ËP›ƒ(Ò.™yP—eÔAUžu‡5UVÔ2ó ϨƒŠZÞÖd¥XUÏÎú*««²Ì;ª)˨"ÏÎÃz,«+òÜ;ª©J©ª#÷ÎL¨qíÿ‡$ßùWn`ÿñ·¢?º]ýÇŽÚõö'£öêú×ð|WòÌEbx*7ÎÿÒ<™è翨åýoÈÀóë7Aþß;Ïk)xþó/¤àùÆ W{ÂÊXvûo> ãñ{ýÏ-}>Ôx#_éµ=\ü{RÌpŠHg‰•½?e†SD¨Aå˜á÷«8øX¹8îÛ…»"1ÍŒ¦ˆ´Ú ÿឯLäáåV7ry}£ìåVˆžùñÖqqú^Oÿ"fx~eÍ‘ðu¦ºÆ—èáX˜š­ÛŒVŒï¢¿‡ÊŒlz£×#«Í{Y Û2oö\"`œ3X1> f¬b$ÃÞ¨\3VÑ•{Æ*ÆŠÕ\n<3V1p`HñûQÆ;cã\p1ðÿ®|ó«Y¶1ÓéSf¬â{0)b, >ãšbík›ý·ÏXÅX«‘Xû!ÃïÁ|Ž¡ÌXÅXûâ¾"d8¼>nü¾f¤âû—õ"d8>ì",÷Sf¬b,Rýr«gÆ*ÆZÊ;ë}g¬âüúËùD Ĺ٫™,hÖÃ>l¿«øâµc*ÛŒUŒz0n¾ |Æ*úV6†bø¾ûÝŒU|?ä?Ñš qÃñéëHìÛ5c­}↣ˆÚãAv fVŒ°áï ß#kSt!¨›AØpd3¿¹«1Cß›aBß‹$‡ƒÜæ«Ý§ÄòìQ ¾ø~?(Á•ñ>e?Ñ…¬w?f¨¢×{ÌPÅyõ±žó™]¸£oS¸f¤b\Ž¬åžŠoœÁÊ@r›çAª¹ˆåe™1+áZtñ{Æ ¿ÏΫe?~7:ÀU÷>1Ñ˳ ¿Í8Å™ø}£‚ë02£yß sö ö}œ¸œm_׌Sôš¯§è5ß3NÑ·zf‹µDÎ~¼ú cu¼/ºâ@ÈpT‹ ûù;Ðmt"b8ðñRyq,Îø)ˆŽ^*Çdkâ]`‹4¯X îûýâä‘91ì¹õ@õ"b8êå0:Ÿ]`µï…éÄ"Kú Q|ߓܵ_¿¢øÆwÁƒÊ‹è¡ð±Ò…d'¯=v w?œ€ÜÓ…paëäu^è@Õ‚pa¯çž!ŠÞ„ «K{ob…í(\ã÷·~|/D [óîßÕJÜ.ã7n™æóÔÚvïóyjm»s9¾÷¹/í¿Ïã[õ\ÎAî ‘Â^ä™ÏÓ¨†×ÅXáxÐr„ÜïÓŽÃHakÌóÛp ò€?ˆŽ=÷‰¯~$D Ûž[ šë9†Ê ìýAZPëÃs: j2…z=w"ɱ~?X%§ÖƒUr"%ò#å]΋@akÌ‹…r\A °]”/–ʱCú}`½X*ÇkA °]O/–˱CóÞ—.Sí æXÇ_¬˜c±dŽªkæØV‹æØ¾VͱC<¶~… ¬›c­vkçÔAˆöj°xŽ+ˆ¶Ã5°|Ž—Aœ°= ÐÑå=&\•¿X@§Îí÷;/e…ã‡Etj7ÇËèøVXGÇË`!Wγwàø]|žÖ¾°˜N]ßß“ðé—êñ{ε…ïÞ[óâšcøøaEºTXóöèʶõqtÄr¢{k͆%u¬5Û±\Îß“šÔl߆%u|«‹ÔÚû}öߨ¬ëéX'·÷Ö —‚õtì*¶»ù±cAÀßkŸ§zæ;ÔñzŽ¥–Ó© ãø¨h_íé:4Hxø¤.¹c¿ß¥üvô ŒóÄ·¢-M¨ï‰„¥GûÊßê9«àˆ¡H‰¿@»‹i‚~v7S ü*ÏÀ/ÓÊü, ÁÏ'ü|l€_d«ßÕ<Ìxø^¶ô¹à/QY3f=Ägnuá{EŒ··”‡9_g#ÂMîóûæÓ±/ökÛd¾hóÅ|Ù6_kÛ$>oÛ¾Ö¶ |­%øºò.íðÍ ?Î{.L܋؞øöß÷By„˜êàe&îY@{ÞÐ^S0ÓÁ:ÜkÀLW&îY@{.|W¸7°çì5eÂ^W¦·úÝfxaöš2i/^ĽVó¬ས`¦ƒuaôÃܳ =ï%h¯)“ö¼O ½¦LÚkʤ=ïh¯+ÓYõ­&íù‘Úk¿'íuå]û€Y¦÷š‚YMyÙ‡T0ËÁÚÞkʹ”˜¼×Ìr°~ƒ÷š‚YMy9JÔO _S&ò¹äëÊË>¨W@¾¦ìýhù¼@>o¯)˜åàÊD¾®F~Ö‚_S0¸)£÷à×”ùÖÕ”w©e‚_S0'ø%!ýÎ~úº2úø ô5åX®eB_WÆÒ~@_SîÞZ@_WÞ>†È}MÁ|`SÀ}]™ÏU0_þÂ<`ë_ð^ÿý.-ï5å:–±Þke0ØÌNå/$úI£/Fîý¸Ñ‡qð÷²úbbó]Ä·Å;.“ÛÒêÛ¾Û‹\;X}1iy° ¬¾PÎæõÅ«ñ-ÀÃ*ØÁyÜ ^_¼, ðàõm“‰þ^VßÔJVßßÄI—Ìòò„‡Õ³Yœøæ&\ù›N_L²>›Óg•Ðé åqä‹#¤^Òê‹©Ù?î ^ß×ÿÅë åfÍðú|+x}[L•2P‚LM¯Ïx}U¯¼¾¸º×`A¿€^Ÿ+ðúb«W”‡Åè­ ¼>ß×¹ü†×çµ0ËËëØ'ƒMFŸW£Ïw £/ ­}¦Ð諃'£oë.ßwŽõvº|Öº|±ãáØçM¡Ëg=¤Ëç \¾¨™.)m¾-Æ(ËÀæ‹Öð3*m>ß 6Ÿu‰6ŸµgÚ|¶oÚ|V m>W`óYÏióYkhó¹ŸÏ÷£/æIðS5>;‚túthóycƾüF‚—Ú1m>; ´ùlˆÓæó2LðR‡œ6Ÿ5Ž6ŸGÏ7ÇçÇç»~úx ÇçÛÀäÛòùá§Ãg;¦Å×d”¨jiñYShñY§ÅçµÀâs…©]LÅçícjWQ¶‚ËgW$]>u›ŸUB‹ok°ç‡rú{[#½ög¦tÉ»¬Ì=»>hîÙA¢¹g‰æž+ð÷¼æt±½Ãßóš™Õ¥áô÷¬ý=«—Ÿ+0ø¬54ø¼|:4t÷¼Ü=W˜ÑÅØ{vÆhï¹ò.õ2£K)´÷lÚ{vhïÙ=žöž×s,QÙ{^æäC´j¾øÍ!@{Ï·ºG¯÷áC´¶yׇ(ý½¦¼Ëø¦¿Wcù{V3ý=/³ó!Ê÷Ø{^àä3Tï²÷¼ ³V§hïù®™×ð«G ÚVÌlhûbjÃÚŠö^<°h ÒÞó23½av‰îž5˜îžíšîžmÄ|.V„IMa>«˜i«ßt÷¬bæ9¬sI¯ª¿W‡Aþ^uQþž+Ìv¨ÉÞ3Ù­^¦;¬"Lw˜í—¹ç;bÂC«æž+3çaU o¯¼=SèíÙ®éíy™× *¦µgÂú:,gÏŠ0åaŽ {ÖÇiìùŽ™ò°*aÆCÛ3šÂŒ‡µ#Z{My{èìÕð³g­™Î^ûýjI9ùÍj™ð°ZGcÏŠ0ß¡a¾C5÷¿ÈÿSlwÌ…¨Û]š¾(¸S>Óp—9 îöMö“àîûO' w»Üâ„;%÷Üî¾[ÜÇ'Ó÷LÛ;Ü}Ê˽“î¬ éÎp”t÷½àÈó›tOFâñnÿ¥ÅG¼ûnF‚0â]õAxge8ž«»j±ð.ÞHh×ïl+âÝþÜ·¤»]“4Hw1£™] ÝYcHw¹MÒ]v!én¿ŽHwy@“îò'ÝYͤ»='m€î²5IwÙâ¤;Û7ÏÚGÀ³­x{Îíàí‡fû ðª5¼ªG€g Ï•·×BÆ«c#ÆÛsúНŽÏê!ãÙVd¼:^b<ÛŠŒWÇKŒWÇKŒWGŒW{ã™BÆ«‹ñ\KÄxÕb1ž)dÀží‰°WíìYÂ^?Áží‰°gí#ìÙ¾ {UF¼W5‹÷ªf!_µÈWíõ¹ò,ÇXÔW­õYkH}ÖRŸí›Ôgû"õY=¤>+Cê«2 >Ýøújׂ¾­&~úöš|Iè³2„¾ª˜Ø÷yÜÝóû¼°ÏvNì³2JåY»z—z•È3a_6FÔW¡Ï¶QÏR}®d^Þ‹¸Fè³2„¾|IèseôZ}V‚ÐW‡\ÐW] óm5gRY<³b1Ÿ•QÏuN§uз­s:}eñ¬2„¾Ì1™Ðg­y2-¯BŸ+LË[û"ôUÍ‚¾Ú» ¯  ÏJ(©})Êâ™ûõY-ç’!;±ÏÊ(gÍ Uvûj±ÒxVå·¯š•ÈSí!÷å6É}¦(É}ÍÇT–û*£4÷¥(Ï}íI‰îKQ¦{SFïC¢Ÿ)D?SÞ}ù=úPOö«2b?S*ãý†Ù¶\Š ¦(ã}Õ³f¼Oü³2Êx_ezÆûÄ?k2Þ—¢Œ÷Uïšñ>ù¯¶Ú+ã=·ÚVÊx_[-/o •8—ÙI€uD€›Mö|ûXOÔ¾þ mPb߯ ÍÒ;w…›‘ú®ïdB¢I}÷÷vù#Súî#\*ˆÞû†˜æc2zoèq÷çá{O¬_@zdøÞ7¶¾w¥!¦ð½K_3|ï;$Š7døÞóȧœÑ{ßËå A1zï»q§ƒ‡è=+£è½‘>ÛŸFïY¢÷^ÑÛŸGïÝ òE£÷"™®”™÷Ï¢÷®…ùþ¥è=Û Ì·ÇåÜ Ì‹4ñÆJæ‹2¼ENæó`¾ïMMOI2_”yó<4ä‹ €/ID>WCÔMyì~èU…ÈW“øöqd,Ÿ à³ø|_(o3õöóNãÀu7õ|+ß>×Йx/°Š~yϛ޳³BÞ«LܳãBÜ‹S  –À=;MÄ=Û5qÏëîYcˆ{^3pÏŽqÏ ܳ!AÜó2cïõ÷¬qÏÊ÷¾—÷÷¬ŸÄ=W€{^pÏ÷ܳž÷|_À=Ö÷lÜ÷¼pÏË÷êd’öLìÙ('ìÙ™"ì¹ØsåÜZµ`=¯öº–aNÖ‹N'Ùñ"¬2`=«¨g#‹¨gǨgÕõ¼ PÏÎÁD=ED½oü99Ï7çÙá&çÙÉ'çÙÉ'çypÞ‡Œ γaEÎó½ƒó¾ÓÕ8ÏöDÐSHyu äÙA!äå ¼ïl û‰x¾ ž5ŒˆgG’ˆ×”±ÜC&âÙ! âÙy&âYsÉxÖBžÕKȳ;'!/î)´8 yv( y^ Ï@žõjBž4Bž·§L³DijMˆx{ÜEˆY@<;D<;|Di»EtÞw¾Îu±8àÖƒó¾M¶Ý¹®U‹è¼Xèéu7ïýZãd=ˆÎ‹Ç7Bp^ðÔãS5›‚༦Ìh‚ï^òhå–γߌÎsÑyM™Ñ® <ÏÌ@þ”ýÇÍh‚¦Œµ Âó\Axž+ˆÏkÊ迟ç "ôJQ„^S^öaos5›‚=W¢×”·÷1zþ1z® J¯)oïƒÂô\A˜Þ÷Øg,¨Âôš2£ La˜ž+ˆÓszMéõ2PÏ깂@½¦0VÏÄ깂X½¦Œ¥ŒÕs±z®Œ¥ë™Âh=W­ç ¢õš2–ö1ZÏD빂h½¦Œ¥ŒÖsåYZŒh½¦¼k­g £õ\A´^SÞ¥ŒÖsÑz®œK D빂h=W­çʳ^‹ŒÖsÑz® ZÏFë5å]úÀh=Wö¾'Fë5åYúÀh=W­ç ¢õšò¬íC´ž+ˆÖsÑz?›Ô¹^Œ3XÏoëÍ`½OÙ¸ bõ¼bõ\A¬^SÆÒÆêYÅÕ3‘z¾ "õ\yŸ¶ õ¬õš2–Æ1P¯ªaœž Ósa½–¥gE¤çE¤×”vl£gBôL@„ž oo;ãóL@xž ˆÎsáíMŸ±yÖLÆæY„æ¹ðö–30Ï„g}’2.ÏŠ¼ïÒôqõ¦3(Ï„í×›>Còìç~õ–3 Ï„s}‚2ÏŠ\W?èŒÆ3áùõ–3Ï„÷ZZ>öÖ2ãùÏgùûv¶–+Ï…Ñ®8<γ5\Qx.ŒÖpÅà™ðœKÃÞ^Ã;–f»7œ!x&l[o8ðLØïÞp†ß™pn½á ¾3±wG»ÅÞùïgëMgè ˆ¼ómÆÑÛÎÀ;ð„¬m{çÊ~ôÖÏð;/p¼ý¨3ú΋\Go=ƒï¼Èýö#ÏØ»,ò’ %ÐÅÒèm~f¤‚Ñ•sïÆç<+‘çJ*èÆ÷~¢y–“çr¥`áÜøî;¼Iscœµ„ˤ¹1^’梖»áÜøŠš:inDŠ›{š4ŠBü&Ìù6ËÅêëß-sþ&Ë}o&· 9d)¼s¿D¹ÌŒ›(ç ó…ÚV@¹¦ŒµÌ¥,…[#9å(ÜŒãì'0ÎP\ ‚¸JK%ˆse[š â\9–„f‚8WÎå÷Õóù&Ä5 3ý– Î@œ+€¸¦, q®â\Ù—…€8ÿ ˆseÍ*ˆkŠr…r Aœ+k®PA\S–„f‚8Sq®l¿å÷³–Ø•¡0•C KKq®â\Ä5e,} Ĺ’ÙBSK-™+T !Îæ 5eß–>â\Ĺržk™k[ú@ˆså¾—>Lˆó߀¸¦¼k2Y¨Bœ+LêÊ»ôçÊq,}8Ï¥Äù.= ĹrKqMy×>¼×Zf,I qMY’ â\Ùû×”g¹^ q®\ûr?!Ä5eÉ*ˆseÍ*ˆkÊ’/W·lBœ £ßÔÉp&JP(Wœ+ 8W˜)Ô0\S+Ô”w©—™BK!ÄÕSçʶ>ÓK€êLÕEö2Õ ¬ûÎëfÜ|Œ6e>F]Ù¹´såE-[›~i+!ŠîL!Þš‹'¼sa^u&ï¾wÞÓ—ÔôÀ;æÔà ÷Ù~îl€;+¸³`»3–Æ×ËùèlÊ|tººstçJà]¼ ]nÉ5|9‘Í5ð×À‹9ŽZnåí= ße-žkè{tÏg\H­g¹†¨´\Cºåb™3×Ð?îAŠg÷黸M±DAçwaGͪ’bUQ²ªRñª"g®W4{5!x%ømU\¿‰u~è¨X5”¬¢T¼ª~®ììyUýÄø©úoÏ€ï¢ïë)"kQ¤!»ßHKSiŽï•çØÿ<]ÒWà»ýÜÿ×ñÏk¸þY¥%Ò ¯ãµóògÙ){Î$Ôe™ŽP•g:bMU†µŒI¨g³žž?Lo×'„9±öÞ^&d9˜à~Çd5ç̦¤œçÓÛ‘¤œZfp“{N­}>ÚØ¹£gN­}ž˜MåSk#>c§0gÖ>¾•Ÿ¿ÜpÏÃLIg¤—šùóïœÛ6gÖF‚XLr=7Lp¾¾â5óüîÕžëéÜ0½=’¶îRºp0Üæ»„4ïæ Ö¹]U‰÷btsÃôv&Dª¼Ÿ;7Ìn¾ÎªÁ/"U"'5Žß6c׸Oa¤Ê¥ã·ÿæCàáwòsߪ"X:÷‰12¤äSã'J>÷‰1vÍ¿;w¦¦ù]ŒÑ9ç$µÿi)˜>+éï9²öÁ*»¦&žûLMóAÅÍz_„ªdÒ£O™3òž `ûñï;/¹ø<~|ü}lƒ­>rA” ëSæÛçã"Ì5;Á*ßH`¯ŽãÀCS¤q'2cd¢«OAf Åäœß=ëàï‰1êÐcJGö)HŒa[1=Ív§2c\~â»Ã#=M¾oð£ U†éiŽCWÃwöpòäLP“Ù±>eÆñœ6'ÓÓd†­O@bŒoSž†óf¦©Mýœ™•ü4œ2c(ýØy¾HŒQ?clšèü)HŒ‘qPçõCbŒ*s1EÍo×Åy…÷ŸXvýF†šïx \é¼䯨4/ò¼˜¡¦Æþu"7F¦;/Ìt¿÷<Ä×Ü»fežSÔì W8ãÞy{dÔy½ÎÂÉ. ¤ÆøŽ1+¾{;O÷©1ê®uoH‘™ÙÎ{GjŒÜõ} 3†UË5ß%{¡—‘ïiGøf‚š:Â÷Ì®Œv„ïy1âTà8ÜLPSw¤{ 3F<ì¹3ÔÔ ~~HŽQ[=’cÔ°~ömèÏŽä5ПÉ1¾3ŽRÎÈÁw{XÛ7ÛyŠ”|W»=7rc욦{F ¾qoª– j¬Ú¹1ê z˜ ¦¶Š1¿{üÜù2A+H7UgüeŠš:U_qÓÂ4çóe‚šmc§æw®v+‰O¢g¯äF¶©ÚèA²©ß¥'Ù\ô¾]@/r®ÚÍðE¨) 6l“ÔÔ‘Û…|3LQS'w Ô¦¨©ëg Ô†Í`Šš<½ v¢3ÔÔm ÔNøx—«y Ô®º1¿I\?D€Ö¾~ˆ [}“ÂǪޙ®"@ëösýʇ ¿'´"ÌO“O­ïæÈPnrŸ~Q^?ån¬*˜Ÿ&#D¯ßÿyý˜Ÿ&Ïãµ1þ3oŸ×ÆøÏ<'צøOÌkcöFS˜½1oŸ‚GjƧ^Ûyûˆ¹6foŒõr 0ycÞƒ¯É­1˜ã^¬kcòÆ:)±äÓ»Éäá[ yûÔ¼¯\;“7ÖAÞwûx‘Ø—”"ìûnUܱ/úð£BìËG¨°¯œHì;òûŒ¼€}ÏG&[Ǿzƒöe Ú¾¿‰úT™/'óÅ|AÖ!æK.óÅg3²™¯úæû.1îIÌgôö§ÌwjeÊd¾L'æ3jóÅ —,CæËt½ }™Ò9¡Ï0З™– }gÞ|}ʳ›Ì—¹£“ùê{‚ /Ó5'ôü”&蛣} d¾Ļ\—D¾Ì-œÈ ;òenÞD>k ‘/«ñ)sß•_æ1ðÅDN*_æëNàËDѾ: "¾:Ù"¾[ËÍ$ñ½Z1‰/su&ñ ¥¡OâËŒ‰I|™È:‰¯j&ñÅt ÞÍE|™"›Ä—©8E|ñ|ç÷!ßÐR¥‰|™•:‘/n¬Ü7™/sG&ó}7 ÞæÄ|ï“KæËì‘É|ß8óX˜ˆe¶–“:™ïÕ ˜b¾ñÓGf!ßüÒ+âËqDà³!â‹·òˆ/ªåÇ`ß×Ü!ÀcŠá|ùÆœÏ4… ¾±ë[p_»$¾¡ò"¾ƒ¯ü$¾ñÓ²EI|yV„|ã§§n"_Žb!ßønP)oRßw¡m$RR_La- >¯Ô7OE§¾LšÔsÙˆL ¾ï„êÝœÔ7b‰ŽÔ7ô¾!êqw{©€úr¬úbÌ€k}:ÿ }ß('oúâêQë}ã»åâÖÐl‡¾ªÌ7¾'áKóÙóå óÅXÇíÌWÃNÌóy½`¾˜Ou‰ðð<­aCæózÁ|á"^¤@2_uŠÌç{óxÓcÍÀ>;\¾:Qûì4ûbØ΀}1Fþ¸5ÿ:öÅK[þ˜vÃGê³N‘ú⃗!Q_ÝóE}ugöÙU6±¯îÌÂ>ë±/ñáÓgrôý•ÔF¿x°~w_#¿x†_îùÅ ³ã¢97Ñ/t†ºÃó‹A%û¦_å?JÓï§'Jš~1¤Y†KZýôr(Óï 73z~1ý™FËïÈû5áï{EÔs’ðsj:o€¿˜¬­¦ç·çká/Þžxß'üÝß]™ïþ„¿˜ ÛØ/Ö£@ö»÷üN/Óo¯þîHgK°üÅ8Éišä¾-çyMîûnš¼¶Å}C:dÎGÔµÿrR)¸ï»c§¡ð»"Ëm3ý®+Žàw}!Õð‹w4ͯøÝGNéøý²¿ûȹ7¿M‘•¿š¯Jî‹©Ñ&{ÞO¾Ó“ûî‹øî(îÛò½Z¶ß›Šf{þô¥S®ß›~­\¿# [aß/_e1ÙóЕ\®_‚¹ïù¡&`‚ûâÝJlH×/n¾Ä1p_Xoœp)ׯ¦åÊõ»rÜûâ#Apš~L‘¬eú½CÄ®¹ž12–¹ž‰®rý¾¡u4×/æz>šý ×/‹[ÑõKŸ?]¿ï…öXæz&ºÊõ{ßô1Ùs$ÃÉõË>ˆüj>‘\¿râr²g":ɯæ*$ùÕ<>‘_í=]¿GŸëE~_ºR9ÙsÓò«Ù‹9Ù³Ü8’_Më’ëWV‹Ð/ÞÛH´ýêc€ÐÏÚGç¯<2±_í]Î_™Ab¿oh?rú~ø¤põÙžµo9å´¥ó—צœ¿¸a·ÙžõÉ@Æßwó½Yèwþx±Ê÷+ÃF¾_}^Ißï§Ë¾_M§•ï—{–ïW~m¿ù1º~5•R®_Y¼rýlÆ(m¿:à²ýjn|?3%éûÙ¤Rú~gÞáåû•Ù)߯ ZÕ¾tþòÀÈù+wSS=óФñ§S ßï»ûü û¼ú~evÊ÷û*y÷¹ŸH߯ eù~õ1H¾_}Ï’ïÏ~"}¿:Ý6Ó“GB¾_æN ïgõr¦gÍV•ïgµÐ÷«1!߯Œtù~51_¾_qù~O>äû•s*߯.Íõ|sb }¿|ãï'TäDϺ’åú=ùV¶Ÿ^Ìj¢çw%òN-߯®vÍô¬È÷»ó ±|¿2I5Õ3¢œ¸÷9ÕSŸ&Ó÷ûÞHFŸéù '’fzj¼æDÏ´¥Óö«"œè™ŸÓõË‘–=ceî{º~ùñ2]¿ëý›0_ReØçTÏ*Bϯö#Ï/¯•œé™ã#gzÖqç—WOÎô´zèùY=s¦g¼ÞåíÕ»ez{izÉÛË@š{㇟rö’"ÄwwÛ=óíþÌÙÓ#·œ½œ"•Ξ^’ïÊm“³—³ú„w9¹)}½|_!Ý…1Áј¾ÞS.ޯ͑!ÜÕ;ZÚz97m½3£ïÕPÜÕH_/­¡ôõ4Ã(½šj%¸{·œ$Ic/ ±Í¾„¯—“ŽÓ×{–H>kŒØ®c¾žŒlgeäë=ë¬ÎœS¾^ºY¢»œ3“¾ž¹v“ôõÒlÞ噓­Wˆl½œ„–®ž>Å&ÞÕhLW¯ª‘«·'kNW¯ì¹zæ1ÊÕ“&SÏŠ”©Ç+P¦ž9iÛâ'¤­—3oÊÖË[·l½:½²õÊA‚­WÆ©|½òiëÕO[OVFùzé›Ê×+ë¶ž¹d²õÒ†L[O3âÜÖ# ¤­—ö^~w/[¯j¡­W –­g~}=³åë¥5)_/­Œôõò[|úzi›¤¯Weäë9}¾žÍò”¯WÎ}½²òõlOòõd\¤¯—.Dùzå!Ê׫}Ñ×3ïO¾žœ4öj´ÑØK_JÆ^:Jòõd¦­gî›l½‹¯(eë¥5$[ï9c´l=a!}½Cß»éëÕlFùzç/MFùzÕùzoÆÊ×+‡Ž¾žùqôõÊ‘¯Wû’¯W6”|½sS8búzåN_/bœh¶Ñ׳ZèëYúz‡‚nÒØ;Œ¤±W¾Œ½òydìU¯dìU‹eìÕ¾dìÕ¾`ìY-4öMðJc¯Æ€Œ½sËÀ<{u~eìÙžhì™ÕGcÏöEc¯ú)cïTÀT:{‡>¸ÓÙ;όߣ³g^½:ãröjœÈÙ‹…ä ÐØ«æÉØ‹—gÒ½j°Œ½ª†¾^ùz§œúzÖ#úz±æçqÒ׫öjf'w䙎ÌÂûOÆvñŽÿ´½oG¡‡ÅZ*•Є;[•‘t_5´œ £öîâ¢ö¾“}ÐåÃRÇñR‘Éwï£8dÐ]DÞ¼B£‰wñæyHÁBÇñbs»WKÍ‘îj wÖ4ÂÝ\I’¦àd;[ž†lg}&ÛÕb•D»ZÎ’d7W—M8°®jع°aUUž¶&椺ZГPgËn꼩€:›‹K¨³õ uµb™Î–ª$Ó5e2]­3I¤³u&‰tqðß_ÅêÙ‘Dº¦L¤«õItÞ\ÁÒÆuÖtM}\çlÙ‰s¶°!qÎ?$ε2ç\ÎùVÀ¹ø"­\&Í…%Áܤ¹Pø…@çMžkMžk]ËïÉsM™<×j™<f“Nx®¾ïç,ûyÎ’›èâkÓÍ3   EÓ''ÏùžÀs¡ŒôïÞþk»2®Õ2®+sYUW&еz&е2èZ™ t1ùøiqz–çDç'ˆ®ÿžË×ñй€e]ý€æ\˜0ç–4Ž÷Ì×çh6e²\ëÏd9ïO°\ÿ=—VµS –³u„¹ÊQG–k2gd¦;²\|P½Èû`¹¶§Ér]ý÷ƒäV sÓd–=Â\+Ãì4¥æš²k™}[ú˜kÊù´$ÌùÑ ˜ë¿‘CÔûZúšk ÓÔ¸ò²©0QMžМïêe¦Wcª6b²šêeÀ\Û„ÉjjÏ€¹¶Í„¹è«Ü¼Ér.L”{ÂŒâ˜Ê…òSpà{-ç(çÊ`úFWžåÊùYLZã 2Lݱª ¦­±2Ìßhõ2q+Êߘ SטÂŽyÈÇš¿‘$×”™¿1“ä¬Z¢\WF»P‰r.0Mv›$וÑ[G’kÊ}¶j™ºÑ„—m“ÀÔ%0ƒMf=$ÅyK¶5s#)®•aæÆ¬xcâÆjìÆÄ¦œËo&n4…‰]y9†r×Lcc 7VcÆoiÓ6¦‚óíÌÚXÕ‚àºÒw ‚k ³6šÂ¬¶'fm4…YMaÖF«‡Y]y؇T˜µ±”ƒY«æcfmôßÏÒ>\S&ÁÅ\>"HpG/çn\+¤UäÞ×Ö1g£í‰9MaÎFS²ˆ27* Ε“9kO's6Jù+¹ñ¦Ádˆwn ^ ¼« ð2øÎ²3iŠæ^†ßä»`̧x‘`‡–ü»XÏYë€Â¿‹¥æµf&Ve©dH2ð"c‡¬7x{<ÿdé!Íý“›´,ËW‘œÁ¹,˯–ýÄ·‰ Åá12¯VÑ ÍSiƒeàGN Ó²,gÆ hY–#¿ÓÀ‹‹@tÅмCŸYéß]Ѻsðï®ø0bþúwçž¾ý»ã®•Z´ç¡oõš¡¹ÝúðJÿ.¦:êÅuœðÇuY~Oû.Þ½Îz>=ö]$ÒМH¬ËRË_¾‹Œ#Z©ö]DYòû$í»xóVüœ–ã¬e39CsË/æôïl’)ý»{+þ]¼ñž¶§Eʿ˩9EóÔ÷•œ¢¹¥‰BÿÎ&ÊÒ¿»ûª,6ÑWæ]Í¡ÓüL[Ë…«²ù›þÍ¿þÝ}å.úw÷/×;•W>›ægV<'ý»šúKûîzóú¡ÃSk]ÂÀ³p5=³–Èé™O.Óïy÷6=3s¶µ8mž/¼ûkžùM9;3Wk¤g+¿ÒÀ‹ÕhúZœ¾sx:qéÞeS.Ä™_`¦}¡°ô÷àÞE&–”g‹àм{~¿Z¤…æÂÃäÝÙÜM­Â¹—S‡)ÒOž$zw3/ ËÀ»{¶œ†žÞ]ú„ðîj*¡ffÖt9zwV¢.˜w÷Y“*aÞ]o®Ñ#÷Î\Bºw5AR“3k±Dºw<Ý;›[@÷Îú”î]ù„œœYóÚ49³æ о³¹Ö´ïlÕ#Úw6<í»¼*5;ÓVæ„}gë MûîÙ–¨<›ïNû..ö£Gå•§–«²äÚ3:;Ó&_Ó¿{¾·kÍu„gBúwW®tÉÙ™¶ Ëœ©itµ gN¡ }g½¦}7ïͤ7…å•5ûî¾s¹Úwבã&â¬>99³f»Ð¾³…¨3,/KNÎÌG„&gÖêËšŸ™«Ó½{Æñ·6;ÓÆcšwiIjvf-4£Ù™9E“3k2½;›VCïÎÖߦw—¡^¹*‹æ6ÔìL­˜³3µ¼g-ùI€wî·xwåËqv¦¢škræHÃoNÎÌ•Fk!Î\t‘Ö]Üü9Ï.­»2 9=3§ÐæôÌšëFë®æ ɺ‹áoû_·îÊ·É%Yré LÏÌõšžù[⹺ÊÍp‡_Î'•sW>"ggÚú0œ™Ó~kvfM½äìÌ:¤tîÂÀy´ìf:w—¼¼×-ý œž©·QŸžÉó­é™š{/ãÎ։̈¼4£4=ÓVráôÌŽšžY³5=óZÄ[MÏÌk¹BònÇù™C_Šr~fΑÉù™¹ ¯Œ;Ötîên^Î]š£¹(K­äÂù™cçÁÑôL›@ªé™ZúŽÓ33,¥œ»tû4=³Æ„¦gjš÷üÿûünÝÜendstream endobj 6 0 obj 197029 endobj 4 0 obj <> /Contents 5 0 R >> endobj 3 0 obj << /Type /Pages /Kids [ 4 0 R ] /Count 1 >> endobj 1 0 obj <> endobj 7 0 obj <>endobj 9 0 obj <> endobj 10 0 obj <> endobj 8 0 obj <> endobj 11 0 obj <>stream 2020-03-03T12:20:20-06:00 2020-03-03T12:20:20-06:00 GL2PS 1.4.0, (C) 1999-2017 C. Geuzaine gl2ps_renderer figureOctave endstream endobj 2 0 obj <>endobj xref 0 12 0000000000 65535 f 0000197346 00000 n 0000199096 00000 n 0000197287 00000 n 0000197136 00000 n 0000000015 00000 n 0000197114 00000 n 0000197411 00000 n 0000197511 00000 n 0000197452 00000 n 0000197481 00000 n 0000197575 00000 n trailer << /Size 12 /Root 1 0 R /Info 2 0 R /ID [<7A0790A4A6BB811A1D5E00AAFF03A3A6><7A0790A4A6BB811A1D5E00AAFF03A3A6>] >> startxref 199316 %%EOF blis-0.9.0/docs/graphs/sup/dgemm_ccc_zen_nt1.png000066400000000000000000007267601422157504600215710ustar00rootroot00000000000000‰PNG  IHDRTjûF¦Â &iCCPiccH‰••gP“YÇïó<é…@B‡PC‘*%€”Z(Ò«¨@èPElˆ¸+Šˆ4EE\•"kE ‹‚tƒ,ʺqQAYpß÷?¼ÿ™{ÏoþsæÞsÏùp ˆƒeÁË{bRºÀÛÉŽÌß(ŒŸ–ÂñôtßÕ»­Ä{ºßÏù®‘iü常¼rù)‚t ìeÖÌJOYá£ËLÿÂgWX°\à2ßXáèyìKο,ú’ãëÍ]~ )úÿ†ÿsïŠT8‚ôبÈl¦OrTzV˜ ’™¶Ò —Ëô$GÅ&D~Sðÿ•ü¥Gf§¯DnrÊ&AltL:ó5204_gñÆëK!FÿÏgE_½äzØs û¾zá•tî@úÑWOm¹¯”|:îð3™ÿz¨• €è@(U  t0–À8à|AØø $ȹ`(E`8ª@-hM œà<¸®ƒÛà.L‚—@Þ‚°¢A2¤é@F²† 7È ‚B¡h( Ê€r¡PT UAuPô tºÝ„¡‡Ð84ý }„˜ÓaXÖ‡Ù0v…}áõp4œ çÀùð^¸®‡OÂðø6< á—ð"Â@”]„p$‰BÈV¤)Gê‘V¤éCî!Bdù€Â h(&Je‰rFù¡ø¨TÔVT1ª uÕêEÝC£D¨Ïh2Z­ƒ¶@óÐèhtº]ŽnD·£¯¡‡Ñ“èw †aaÌ0Θ Lf3¦sÓ†¹ŒÄL`æ°X¬ Vk…õÀ†aÓ±ØJìIì%ìvûGÄ)áŒpޏ`\.WŽkÆ]Ä á¦p xq¼:ÞïÀo—àðÝø;øIüA‚À"X| q„„ B+áaŒð†H$ª͉^ÄXâvbññqœøD%i“¸¤Ri/é8é2é!é ™LÖ Û’ƒÉéä½ä&òUòSò{1š˜žO,Bl›XµX‡ØØ+ ž¢NáP6Pr(å”3”;”Yq¼¸†8WJ)Hq¤"¥öHµJ IÍKËIÛJGJJ·IK”aÊ8ÈÄËì—é”y"‹’Õ–õ’Í’="{MvVŽ.g)Ç—+”;-÷H–×–÷–ß,L¾_~NAQÁI!E¡RáªÂ¬"CÑV1N±Lñ¢âŒMÉZ)V©Lé’Ò ¦$“ÃL`V0{™"eyegå å:åå–ŠŸJžJ›ÊU‚*[5JµLµGU¤¦¤æ®–«Ö¢öH¯ÎVQ?¤Þ§>¯ÁÒÐØ­Ñ©1Í’fñX9¬Ö˜&YÓF3U³^ó¾F‹­¯uXë®6¬m¢£]­}GÖ1Õ‰Õ9¬3¸ ½Ê|UÒªúU£º$]Žn¦n‹î¸CÏM/O¯Sš~°þ~ý>ýÏ&   ©†.†y†Ý†iñªî¯&¯v\½mu×êׯ:Æ‘ÆGŒ˜ÐLÜMv›ô˜|253˜¶šÎ˜©™…šÕ˜²élOv1û†9ÚÜÎ|›ùyó¦é§-þ²ÔµŒ·l¶œ^ÃZ¹¦aÍ„•ŠU˜U•Кij}ÔZh£lfSoóÌVÕ6¶ÑvУʼnãœä¼²3°صÛÍs-¸[¸—í{'ûBûªƒŸC•ÃSGÇhÇG‘“‰Óf§ËÎhgWçýΣ<Ÿ×Ĺ˜¹lqéu%¹ú¸V¹>sÓv¸u»Ãî.îÜÇÖª¯MZÛé—ˆÿ2Â6¢,b&Ò*²4r*Ê*ª4j:Ú*ú@ôLŒMLyÌl,7¶*öuœs\mÜ|¼Güñø¥„€„¶D\bhâ¹$jR|Ro²brvò`ŠNJAŠ0Õ"õ`ªHà*hLƒÒÖ§u¥Ó—?Åþ ÍŒ]ã™Ö™Õ™ï³ü³ÎdKd'e÷oÒÞ´gÓTŽcÎO›Q›ù›{r•swäŽoál©Û m ßÚ³Mu[þ¶ÉíNÛOì ìˆßñ[žA^iÞÛ;»óò·çOìrÚÕR V (Ým¹»öÔ±? ìY½§rÏçˆÂ[EEåE‹Åüâ[?þXñãÒÞ¨½%¦%Göaö%íÙo³ÿD©DiNéÄ÷e̲²·7¼Yn\^{ˆp(ã°Â­¢«R­r_åbULÕpµ]u[|ÍžšùÇ‡ŽØi­U¨-ªýx4öèƒ:§ºŽzúòc˜c™Çž7ø7ôýÄþ©©Q¶±¨ñÓñ¤ãÂÞ'z›Ìšššå›KZà–Œ–™“!'ïþlÿsW«nk]£­è8•qêÅ/¡¿Œœv=Ýs†}¦õ¬úÙšvZ{aÔ±©CÔÓ)ì ê<çr®§Û²»ýW½_ŸW>_}AòBÉEÂÅü‹K—r.Í]N¹<{%úÊDÏÆžÇW¯Þïõê¸æzíÆuÇëWû8}—nXÝ8Óâæ¹[ì[·Mowô›ô·ÿfò[û€é@dz;]wÍïv®¼8d3tåžý½ë÷y÷o¯ñy02*|ñ`úaÂÃ×2-<Þ>†+|"þ¤ü©üÓúßµ~oš /ŒÛ÷?óyöx‚?ñò´?'󟓟—O)M5MMŸŸqœ¹ûb݋ɗ)/f þ”ø³æ•櫳ÙþÕ/ M¾¼^ú»øÌ›ãoßöÌyÎ=}—øna¾ð½ÌûØú>|œZÈZÄ.V|ÒúÔýÙõóØRâÒÒ?B,¾“sMT cHRMz&€„ú€èu0ê`:˜pœºQ<bKGDÿÿÿ ½§“ oFFsF×j`` pHYsNNÆÊ/¥tIMEä&>(Ê vpAg´¨“ÁQè€IDATxÚì½{œU™ÿÿË2I `qH¬ rIp‘‡›h ¢¸¸ÕÁõÙ…juq•µ{w¿¨‹®¿îuv‘Åu· wïéRvQApjP‹Sˆ’nS›8Ä$¦’!Hæ÷Gõ©®žû­gz&Ï{^óê:U]OŸSçsžç™ÕÛÛÛ‹ ‚ ‚ ‚ ‚ ‚ ‚0(‡LuAAAAAAjTAAAAAA†AAAAAAA„aAEAAAAAaDPAAAAAATAAAAAA†AAAAAAA„a˜‘‚Šã8xž7ÕÕF@†xž‡ïûã.+Ç™êS†AìsæA?»ûœˆ}œŒÔ>}ß' é®®0b»3›ÚUµ\l·¶Ûœ>LÕs©ØçÔ!ö9=«mŽ·í&±Éƒ“éj“3RPq]WŒpàû>MMMäóyR©étz\åA€ëºS}ZÂ0ˆ}Îl²Ù,ÍÍÍýìZìsz öyp2û ‚€ÖÖÖ h&±Ý™Ë`í*ˆíNÄ6§Sõ\*ö9µˆ}Ö>cµÍñ¶ÂÔ 6yp2]mò°©®€pð’J¥Èd2d2Â0¤¹¹×u±,kª«&‚€|>Ogg'º®†! ض=ÕUaœŒwpI„Ñ3T»jƈÊÛ„ᙪçR±OA𱨿D´‚ Ã1#©TŠY³fÅ?Э­­8ŽCCC 8ŽC6›¥¡¡¦¦¦ åt4Û…*'Yß‘¬ ß÷innfÖ¬Y¤R©øÜ[>ܺ‘Ô¸ëàya’ÉdÐ4ÎÎθaì\}ß¿CUæ`®aj»Ñî'L,ã±ÏÁlÄ>«iŸÃÙË`窾[MÓâWÕ‰í‹Øgm0”}N§¶3YVßûr¢ms¨uSm›ƒïhm,iŸê³aòZCÌÛÌvu¨uµj»£iWAl·~ïÐÔb¿w²ŸK“ËÄ>'—j´0ò{Mú½£»^ÃÙæ`ç;Ö¶SžI'éÏN-Úäd?‹Ö¼MöNs:;;{Þ\.×ÛÛÛÛ›ÉdzÞL&ÓÛÛÛÛÛÝÝÝ«iZo±Xìíîîîµm»èmoo¯X¯öoooïÕ4-.W•“ËåúÇ4͸£Ùv(€^Û¶{»»»{;::z5M‹ë:Ôº¡®:U]×]>Ô>#­ÿH®C¡Pè5M3~µ,«â\;×öööŠuêûRëTù¶m÷†ÑÛÝݯƒí'TñØçP¶ÙÛ;:›ûÝuÎ^†:WÛ¶{-Ëê- ½–eU”)öY[ eŸÓ­íTe t_N¤mµ®ls°ëÏç‡Üo(ûìèèèÕu½·»»»×4M±Ë`&Ùîdµ«C­«eÛmoo´]UåŠíÖÒïžýÞÉ~.ííûœ ªÕvööŽü^“~o¹îa›C]‡±´òL:¹HvèkS‹69ÙÏ¢µn“Ó^PÉd2½¶mW,Óu½âfHAwww…! …^Ã0*ö·m;6f…ú"“ŸûâH·  ¢³•ì` µn0r¹\¯eYý®Ù`ˇÚg¤õÉuP×W5Šês²S2й*ê[7Û¶ãòmÛîÕ4­bÿ¡öªÇxìs(Ûìí͉}Žî: g/C«j¸Õ«ÚGì³öÊ>§[Û©Ê辜HÛj]-Øæ`×!ŸÏ¹ß`öÙÝÝÝ«ëzoGGLj¯P}f’íNV»:ÔºZ¶]ÕG¨]MCl·6~ïôì÷Nös©ØçÔP­¶³·wä÷šô{ËuÉuÎ6‡ºci;å™tr‘þìàÔªMNö³h­Ûä´ùåû~ìʧÐu=~†a…mßmƒ À÷}fÍšÿOµ Qß:ŽtÝ@„aXq=r¹Ü Ë‡Úg¢Ñub±ˆišär9lÛ®¸öƒk_·hMÓ‚ Â%¯¯{ÛPû Õa<öY‹¶Ù·Ž£Y7µlŸÃÙË@çê8®ëÒÑÑA.—£³³ß÷Éçó€Øg­1”}NǶs z·|0Æbƒµb›ƒïpû dŸù|Ã0Ã0»àû¾$ÏbfšíNF»:ÔºZ¶Ý»îºkÈvÄvk é÷M-÷{'ó¹Tìsj˜imç@õnù`ÔrÛ9œmt¾cm;AžI'“™f“ÒŸú|Çò,:ÒãMÓ^PIÌÑ¡.¶¦i˜¦Ioä­ÿWãÆ«<ÏcïÞ½.,®äPëÆ‚išýŒl¤?2}¿Ïd½ àP(ÉdúÅ`j?¡:ŒÇ>FÛ„Ú°O›½A€®ë¶lšf¼¯Øgm1œ}JÛYÉp68Z»+cµ•áöÌ>Ã0$ŸÏ“Ïç ‚×u+↠“Øîè˜Î¶»uëÖ!ÛUÛ­%¤ß;zj¡ß;Ï¥bŸ“´££ÚÎ±ÚæxÚNy&<Ä&GG-Ø$Lþ³h-Ûä´Tt]Çqœø¢ú¾_¡lY–UqõM*dYVÅŒ0 ijjš1Ó4+®çy¤R).¹ä’—«¦ÁÖM†aĪ2D×ÝuÝ~Šê@Aj?Ó4r›ÉdÐu½bÂPû Õa<ö9Ómj×>alö¢ì:9˜ãºnEB@û¬†²Oi;ÍQÛàPv;‘ŒÕV†Ûo ûÌår´··Çÿ†aËåfôÃÊt@lwpfší¾ùÍo²]±ÝZBú½CS«ýÞÉ~.ûœ¤íœZm;Çj›cm;AžI'±ÉÁ©U›„É}Ïñ&ƒÃ¦ºãŶm|ß§©©)þÁµ,+^o–eÑÜÜŒ®ëýÔ,]×Éd2´¶¶Æû›¦YQÆtF‹º>¾ï“Ëå]>Ô>‰¦iär9š››1M3¾î¶m»¯®ë¤Óit]gÄg2™~?²ª|õ]¶ŸP=ÆcŸ3Ý6¡víÆf/ªã“ü¾ Ãû¬Q†²Oi;Goƒµl›£Ý/iŸ#™q-L.b»ƒ3Ól÷ÜsÏeûöí¶«!¶;µH¿whjµß;ÙÏ¥b›Sƒ´ƒS«mçXms¬mç²eËä™t›œZµI˜ÜgÑZ·ÉY¥¤1Óß÷ã8{I. ÃØE( CLÓdÖ¬Ytww÷‹[š¦ÍÈNŽº>º®W(úƒ-nÝD1Úëîyù|žööv<Ï«ú~ÂÄ0ûœé¶™¼>µbŸãµ—ɲkabÈ>¥í¬¼6£±ÁZ´M±±™‰Øîð×fºÛ®b¦_3 é÷ŽìúÔJ¿W!ý׃i;‡¿6µÒv*ÆzÝŦ§b“Ã_›Z±ÉÉ~­u›œö*ŠÁ.j†´¶¶R,1 ƒl6;`,Æj6Š †L”dšæ¨\—FSÞ`×g¨›1¹n¢ë®Ïu«›W­¸‡LŒÇ>§£m޶ÌZµOµïh™ »ÆÎ@÷ÙLn;GSæHmp¨åÕ²Oi…ƒÍv'¢]j]-Ûîd|_ÂÄQëý^¨Mûœê~¯ô_¶¶s4eÖjÛ9Öë.6==8Ølò`îÏNÅ~ÕdÆ*ƒ¡ë:…B!Ž¿¦ë:ÅbqJê¢âÝ Uש,¯VŽ5\=Æ¢HÖš’)DÔŠ}VãþžÎö9Ùö"öY{ÔŠm‚Øgß²¤ †b&Ûîd÷EkÁv…™…ØgmÖ}<õ»žÌdÛ¬V™µp¬‰Flºv˜É6y0öggê3ìŒ ù%‚ ‚ ‚ ‚ ‚ ‚P-™ê ‚ ‚ ‚ ‚ ‚ ‚ Ô:"¨‚ ‚ ‚ ‚ ‚ ‚ ƒ*‚ ‚ ‚ ‚ ‚ ‚ à ‚Š ‚ ‚ ‚ ‚ ‚ Â0ˆ "‚ ‚ ‚ ‚ ‚ ‚0 "¨‚ ‚ ‚ ‚ ‚ ‚ ÃaS]ñrÆg°råÊ©®Æ l߾ŋOu5eïÞ½ìÝ»—E‹MuU¥Ö¯áæÍ›¹úê«ùà?8ÕU©)¾üå/ãyË–-›êª J­ß[;wîdÞ¼yÌ›7oª«2 Óá÷cÆ <úè£S]šãï|gMÛæt¸·ä÷c|ìÚµ‹††¾ñoLuUjŽZïÛŽ”Z¿GC­ÛûHéw"}ÛùÞ÷¾Ç-·ÜRÓíçH9ØîééÀH¿éÛL­÷mGÊtè”™ò;3ÒïDú¶ƒsê©§òÖ·¾uª«1(µÞ–L‡ß…Z·÷§Ÿ~š?ýÓ?å/þâ/&¬Ìi/¨¬\¹’[o½uª«1(kÖ¬©éú­[·ŽuëÖqÝu×MuU¥Ö¯a[[ÛŒè¼M4ïxÇ;˜3gŽÜ[ã ­­––ZZZ¦º*2]~?„þ,[¶¬¦ïýéroÕò5œ.¿Bj½o;Rjý µnï#e¤ß‰ômfÙ²e\|ñÅ5Ý6”ƒížžŒô;‘¾íÀÔzßv¤L‡>ðH™)¿3#ýN¤o;8sæÌ©é{¡ÖÛ’éð»PëöžJ¥˜;wî„–9í•Z§–ox€U«VÑØØ8ÕÕ’Z¿†Âô¥Öï­Õ«W³pᩮƠL‡ßaz2î-ùý„¡™I÷`­ÛûH™I߉0>äž®=fÊw"ŒéÐ)3åžžIßÉTQë“4j½-™÷`­ÛûI'ÄòåË'´LTªL­‡l¨¯¯§¾¾~ª«1$µ~ …éK­ß[µÞhN‡ßaz2î-ùý„¡™I÷`­ÛûH™I߉0>äž®=fÊw"ŒéÐ)3åžžIßÉTqÄGLu†¤ÖÛ’épÖº½/X°€Ã?|BË”¤ô‚ ÌBB‚©®† ‚ ‚ ‚ ‚ 3TA˜1¤HáàààÐLs¼.$œêê ‚ ‚ ‚ ‚ ãDM¨Í’ɵ¤"‚Š ÓŽ<ùø}3͸¸88hhøø8¥?€l鯆©®¶ ‚ ‚ ‚ ‚0\ÜX8É“ÇÁÁÃÃÁ!MzJë–ÏçÇ_ˆ0mAE„š' ˆ½M²dññãÓÇ'Ož9òäi§ +n` <¼©>¡!à•þýÒ2Èi µô>ùŸJ,Wû‰r‚ÒrñIAAA„™ƒÓÏÅdzwJ ¿_:Æu]Â0pŸ Èf³Ã–7Øþc¥©©‰0ì?òáû>ž7ðø×CßzhÂŽ_ú æøÉÕAø8$å+w;x»!½/Ú5$ZïAiªõÄ#IéA¨y\ܸ‘üy®%ÃWpù!E ¼—g`Gg:ïAÇGÃÆÆÄÄÀˆ…sªOgÚá&Q»¦Ú6Õ i€^úÜ·Ýk'GT”¶Uï­DÙP)‚äúÔÁ/í«%Žé‰+”SJ‘åÌùó§úò ‚ ‚ ‚ ‚0F¼Òß`ŒEPq]×u)‹± ’Éd0 #ÞÎ÷}4MÃ÷}‚ @Ó4lÛ •JaYžç¡ë:ŽS¾7MÓ4ãe¶mãº.ŽãÐÑÑ—­ŽÕÜÜL.—Ã4M²Ù,º®£iûŸÙϲËxû‰o硺‡xïµïå×ÿ5=›{‚×u±m;®g†äóy|ß§³³“u?ÝÈÿ}¿ÝKþ›Gžz„ë>ð½à/¢bt, <ÞBá =L´‘ ø>Ú¹¥!ÄÉŸ ™#¢÷¾ ú&¾ Æåêà?a=øƒýà"Èžú Ím'„Ç€[¼Æ\Ð~ á!à/g_…Õ[!8‚ã l€yßç,—‚þø‹á´ƒ¦5À06@öз¶¿¸†;žøÍ„Þ“"¨‚P“¥? ƒâE2<ŠÆÃ¤8‰) ¶ð3l.öa± VÀDÃÇ ˜˜ql̓‘d×ÃL,KŠ!åvÑ#jHU7B FâU‰~鳕XŸ%S\"qÄ ’H) °n ’Á2¥zªz·÷YŸ~qúéSpµAAAA˜(üÒÔÉäDÙä2ƒJ$)Š(òù|,ˆ(/ŽÖÖV|ßG×uš››c±$—ËUìgF,¬¸®‹¦ihš†çyd2¾sÊ)äO: ]×9ôÝïæ‘ýW<Ï‹½[lÛÆqö-]J6›Åu]–íXÆ_ÿøûر0 ¹ý“·³`Ñqò gqïž{¹¸áíP§1?<…s–>Ä'þé0î;þ>^ú§—øñ’³®e?ù»¿ç«_ý*ß>üÛ4ÑÈü|›}÷aYg|÷×Ô¿ZOǿ͓+/åí'|ˆws9¡ Â×Á< ô9àm„p?è @Âà¶€¾¬[!ìàUðÿ‚9ùu´½¿*B|€õàn…p!ì¿Ân`tGï÷‹ÎklúÜ2ÞôAÐ7€5 ~þoc h¯@f/ÜþWðó¿‚xŒïGÇI¿g×þ¸´»@û"xë@;ô^ðoìï õÏ~É‚åuz?Š "BMâáñ¸Ô£ñW丟äù<?,IwaÑ ¤1ø&ïÁR°—Â#_ƒ,€7Ù o£u }·òu{õ0ŠõðÎw~Ÿì/çÒù¯rÜïwaêGóT3<Ñõ2,ÝDGÝJþß÷îå–/œŒÞÕHæ'°àÅ8ì]Góч³vøË/¦ñ¼F.üܬš{ÿý±“®ñÑ;tø­Føk°í]bœ¤ó¹úÁ^¬|3œ}ÇÞ,ø‹ßî&|ËóèŸ× Ø™ã[Äß{wÀ7¾°‚-·m™ÐûRAj’€€ßà3 "oAã÷ø|/ ‘'Ç›ÐxP¤ˆ^ &• Êy5¦‘ð1P t~ZésŠH01K¯EÊ"†6HÙ ƒ‰5 ìµRM”H¤°Î^\¾¼Ê5AAA¡¤HÅ)}C{…„˜˜áÀTî ˆäS©TÅçL&'Ïd2hš +ž¦qÊ 7ð¡9sø×ï~—/æ¥O|‚‹/» ½¡!ÊËaš<|~ýzœº:œ× ˜‰î;M\@Û ÿwA+ \”ã¸×_çïÞuÚî£à8áÃ6îqà í\Àk¯?Ïï}[ÍÅ6ÔÁW¬CiЀ}`Í…µ2ó°Îù¼Ä|æ_µ›¿Í¬À<´à ‹ç ù°4çÁ;7=Í7= hýÎ?p[æ|ãøëUå °G|õkÌû‰´gLÒéyÇá#î"RÇîå[—¼‰Ç÷;á ]gr}±“ý;@ww7v6Ë÷—Õ3ûCÉïÏA3 ló^{þÝäž hýëV8ÀÛþÏ<ýƒ‡ïû¯~ò“ÜxÞìÝ{,Ý[Òöç9õÏOÅ¿Ê稣~ˆ¦Á>ðÞö¶·ñÜsφÿBW×âºÿ‡ïû¬^ý7sÌË‹_ç[ßÚÈøC|ðNŽ>úEÎ>û~V­:œ|“Nº £å x|âïKTA¨I|| ñ:ЉI6Ï$¤}ÀáôÚD%Ç2ˆÄ õ"ñA'JÆn‰Ã…ÃÊ °l(/“ɼRÕk’D¡ÃnÞû÷·Þ:‰g-‚ ‚ ‚ ÂXéÖ+)š8¥L­zé`ûöí°¸œh>ŸÏãº.¦i†!–e¶mG!¿ˆ&ߪq ‡hrê‰ú:ð§–E–h gÉ!siô}Àë`=ߺ°^óaÐ^㾊Ÿí%hýœñÏà| ô§#÷(<ºž{¼ hû c/8_ƒM¼¿ÎA¸Ìcà=×?ÃòãŽã7ÎŘKé:Àg—ê†!‹ýÙ|6€¼ÔCÀ»€_ÙÍ[Þþ<º®ó©Oý==Ï} Èf³twwp €|*Åœ9sxãßÈÇ2¿³Ï Ñub¡@Ç/–Ðñ‹E‹zã<3[¶ü˜ÿ¼éÿcóæ6n½õ^xáÞð†“ùþ÷¿Ä~ô#¶mÛÆ¼y§ð_ÿõ4…BŸüä'|ãùå?FÓ²víZ6nÜÈüù_áÉ'_å©§þ›Ã?œ;#Žx„Ù³g£i=ìß¿ŸsÏ=—»îÒù¯ÿ:š§žÊ‘J¥8ÿü?çå—¯ç?h ®ÎÃó<‚@£·wøÃOéìŒÂ{^š¹s¯áƒ¯ýšÏ¿tɄޣ"¨‚P3xxhh\Š,- “«nº 'e/ŸrΑ åÄé¥å!Ð\zí`r…éŒò²©¶'Œ ‚ ‚ ‚ Õ%$$O>T œ+E +>~,¦h¥ØO<ñîƒ.¾ïÇùJ2™ –eatuñÚSOÅeªh&Ñd×4 ï‰þ†hc¿ü¥`n^‚œ×4\ 瀾+Ú6­C{§!tÏ…³ïƒÂ߀µ0Àóáï<(dÀœ ”Ä’…ai2í1Ñç?ËöïÇàĸ¾¹44ìÄ÷;1 ß÷yí5“UmÅõYÊåR nî+<öñ¥»?MGGõõçsÒI¿Î! C6nÜÈ}÷mâW¿z[n±I§Óœ~úé´´ü ÷ßÿ¾/---üéŸþ)ÍÍßcß¾7²cGétš·¾õ­45íåÛß>šøÃär9V®ü(sçnaÆ?ðÃþ€ýè$n¾y)Ùì?ðÈ#_âÎ;路÷-,Zô§œ|ò%œ}ö±üÇüû÷¿JOÏ2Î>»…%K–ÐØØÈQGmföìøó?φ!‹-âÔS÷³~ýñÜs‹ ÃåËßÉG¼™Ã;™çž{ß÷yôÑã™5ë­tw_Í;ßy>÷ßÿÿÐõ/¼°€÷½r lŸÐûTAj†,YVa²—%XX˜¼óÇQ¦1ªò6È+Ä¡¢+ j˜Ò:%¢ ŠK#W„Ñ¡yó‚ ‚ ‚ ‚0½ñÁQ“o54ÂÄŸAè…\¶ÿ2þ÷¸ÿÅ÷||ß'“Éày^œXÞ¾ÔØH{c# €¾Âž Á0~Ú¡,c;„½Ðþ&ß^äþŒõ@œuÐ~è JXà4A¡½²ÞyðKˆÃˆ¼òÊz6?Ñ‹©”0ú„&Y¹r/Û ‚9¤R):::H¥à”S¶ñàƒ­´··£i眳‘Ý»_bÏžÛ¶¹÷ÞGÙ²þó?ÿ‰,â8÷ß8›7[|ùËß'“ÉðÔSO1wîíœpÂ)øþ3hAÀ_¿¸ædyä7ÜvÛm  ™ Ÿh»˜3Î8”E‹VÉdH¥R„á-,\x…B”÷/ÿòClܰjÕL3:Qσ³ÎÚüyïÇu]V¬XA]Ýùœ{î7Ø»÷töîíæÔSO塇ö2gÎsœxâÅ8NÛ¶ùá_¢«ëØöªøz<þø;سg+?>—7¾ñm|êSu¤R°dÉ2™OaYð±Ý† ó¸çž?¦®îLzzNã¶Û ødÀÂ_-„–‰»O™${A óvòœŠÉ>r܈Éùýšñí]‰PR¥ÿæÄ:‡h`¿H”ô½“(W±´\£2÷‰ ‚ ‚ ‚ ‚ÑJkEú$&fEÔ’úõô<Þƒ“wèiëañâÅär9:::-+ðw‰&¼ªÈ!À~ðý‰h]8 ŠßƒÌß‚ñ<Ø7BÇ' ÜCà+×€ñ"× Üõ -!ôÉDËçÍÛSQß0„ö>˳¿ÞÅœ×"QG…&ð}hnn&‚ à§?mäˆ#ΠP(ÏçQ›çr9Â0$•J±téRN>ù' ÖÖvgœq>x'a’ÍfùÜç–pÎ9¹í¶Ñ4Ù³góóŸϲe—‘Édøq]†®sóßïåø¿|ï{ Òi>tçœqÆ¡ðÚk\õì³xžÇG?z-àóկ׽§çröí;ßÏà%ô£u\ýÅäóy Ã`ûösY»v!wÝu?¼úúóI¥~À²e;øÕ¯®" lÚô1¶l9‰E‹ºÉç!•‚lL3º–o{Ûò ÿËã…®Cg'twŸF€ã@CÃ,n¿ýV¬øõõÏ ëѾÚ9>û–î›Ð{UAj‚4yÇæ4®À¨o Ÿr"÷¦Òk†H$é j?•p¢ ×%‚ ‚ ‚ ‚0:ÂRì0Ž…€/lÚÄq/Ÿˆ…ÅË/àÑîbá‹ ñ< ÄÛ¦!ö–ÈSŽ,’²€ý5°ïãU0=è¾ òX1Bø›£dî¸@‚ãaÿß %’0¬¬÷‘GîÂOè@¾­­ö».ÿõ“½tu/‚l–/œ}6Ùl–0ôùÁvbù|TÓSN9…-[¾J6›-•å³zõ&ÂÐŶm\×åßø!ßÿ~=—_~ííí†AKË{سç à»»Ï3Y´hgœñq‚@+m×BIƒaíòåP,¢5Ìâø$+V¯†|ÿ+÷»êYvýá,>ÓMœuß. CãÓŸz/ÎG~ó{ |Ó¯½—ô•ûÈfÁuAÓà3Ÿidþü»øùÏ/çÀåìÜù7Ür˯ ûîû÷Üó%V¯ÞÄõ×?8Ì›7úúý\yåÝd2`ÛÏG/¥¯“Y³þ‡œ‹®GÇØ¾ýn\7ºÞ»wïàå—ocÅŠoPÒÔØ|üfö»wBïSTA¨ :ðø6ÇbrÆ„zr£ØÖ!N€V¢†¸ÔΠSN/Þ&‚ ‚ ‚ ‚ OH'¢Wì­«ãì_ŒžÇ{ØyÄœøãc| €Ù³gåï*é¼_ú·ÜH#Ñ·u'.ã·`=LœL%"¬ ˆ~JƒñaØ_< ÃÊ0]¾ï³e˺ºv—Ö‡ðØc|ýû÷òê§? Ù,Ë–,áCÇݾÏgÿýß±\—WŸ~ÃöïÀ0 l;Êi²gÏÎ8ãrlÛŽ…’Í›7óö·_ž‡eYlÙ2ã¤W8ôУâz\ñ·òÑÖáyTx‹¼óËyøáSÈfaÛ¶¥œvZ7ºÇ]K—‚¦Q(F#\³ZM²Wl%ûåz ²·ŸÄ ¯â[ïü¸øbLSÇzÿk„?œü]«÷×cYÐyÞŸQ$…öí›Ñ±,èh9ãM|áMí¬Zñk ä¼óÞÂŽ_æä7ü–SNœÃ¾p-ç÷Àã¤úýœzj=–eÉ5ÍÊë¬ë:¾ï£ëå/â³§µcYÑùîÛw†a†a”·«’CE„)%K“#0HÅ Ó5*Œ—G$hDž'J,Q‰Ê@AAAA„‰ÄÇÃÀ+%Ož3Ηr`çStm:’§ÿ÷q~y9—^z)ᥗRÐu\\ÊjóDŠý(xÇ€ñzО,Nƃ¬ë‰fκ‰üR²Ö'ŸÜÎÙg ÎOä áû%¯‰ àéŽ^fßq_ówäz{¹q÷ø×c/å÷]ûøic#—Þ|3ÿó‘ö¾üvn<ù,^ݸ‘÷½ï}<÷Õ—8aá!œqüñìpÞ·t)?¢žï~÷–,ñ0M“#¼€% õø?ÚBðÝ/aþþ~‚º˜»ñJœúëÐJ.!Þ'_; —\C:}™ãï€åï‘ÉDuþÅïൗæaœø2¾?ŸgŸ½Š††è¼s¹ÈëCÓ–ÐÜLì%ò®wmçk]'ðñKêÑ;7ü2áFZó&aúõ‰¡iA€÷¥#¢ †Ü·åó0Wçm_æt]Gºïm¾ƒß?ÿøÍh†Ø?~/fÝJ çp”{‰ùÆ'±þíàÊŸïØ§T’ÖV®â Ž ࢋºxþùÍó¸ñ¤“°n¿t=:*0%‚JWW]]]´´´ ¸®±±‘ÆR² A&‡¡l3¹~¢ì3$$_r¾ÜN®JçÕW”ˆÜ<•ˆb‰(‚PËL¶} ‚0r¤o+µ‰´‚P»ˆ} Bí2Ù}Û¿ô§Â|©Dô>>©Ù¿zñÇ,ý‹ÿÇÞOĹQlÛÆÅÅí¯ôMà/Æ{Œÿ€‚þW@ÛF4 d@ A fÏ&By}Bœüá{xòÉYýêìyN7Ñ©ëxý´¾ñyÞó­+M“ üØÿðéûNçãó¶ðÆo7xÛÛ>ÈCíåµ¥ïþúMüöÀÛGËYdzãÉ0Ší¼‹_´Â™gvQüúg°{ ìYøN˜ÝE~ã‰4q?‚ûöÃ¥7üü(²ÁX‹žÀ>ï±µ‘íþ,î“gáÝ»ˆŽúwblú!ØoÿÎn~w×,Þ=ë„ÖU¼á ð±­îçu£Âeé:üѽÎO~r-ßÿþ®¿¾´AiãvSíaÄ;ÄËt=J~¢ëüç¡;hÍÀ—nz/¿ÿi#'FÇë舾¯ ˆ¾„ ]'÷¡'àú¯€ëòÓ½{Ñ7lˆÊÎåÀqøÄž=|àÁyä‘OG.7®ËiÝÝüöÄYjToºö¤ *mmm¬]»–U«VÑÕÕE}}=·Ývõõõ¬]»–¶¶6V­ZÅúõë¹îºëX½zõdWQJ†²M *ö©füùXU=¿x–(ŒWHäÁY¬úU„‰a*ìS„‘!}[A¨M¤í„ÚEìSj—©ìÛ*1ÅÄÄÃã4¢‘ù"Å(Œ–®³÷Øcé<Ñ¢‘€h|'¶/ˆÊ±€ürèü(h/EËœ{K"Á@Ä–dΈ4‚¾ËŽííäé_iÀ²HEÑuÚoã»ÅwpÍÉ'Á¾}ÞÑAûî¿#{þ=Ú`z™_õrÈœÅ<óÌý„á\R©¹\; ÌåÆþäONã¼÷¿Ÿ§žt‡lv™ó¾ˆuñ˘;v<¸wï^²_]‚7ÿ(lû(2;3ÏÄó —cÐùßQâöl¼'O¡¸ñr8Îb`;ÆõÏç?|;?úï¿ w×Ù\òùtwŸF&Óÿ»0ÍòûO|‚;ï¼ÎΟô 6,%QCÓÊ1_BMãè¦YäþûÄÄfFÅö1¥ð_Ç8(AÅ0 P`kk+Ÿþâ)‹xž¹_lmÅ4M.š)‚JWW·Ür wÜq+W®¢$Ak×®åꫯ¦­­›nº‰––6lØÀe—]FKK‹ÌF„*3œmU±O—äØH–ÕUóO‰hꨘxpPã¿a’˜*ûax¤o+µ‰´‚P»ˆ} Bí2U}[¿ßò äN¢¡áùQfòCN?À èqx/híY¿ë`ý?‚a‚þ- Â#!øliã’xFÚH±˜âºñ@þŠmY¡Í% ßÄ+Ÿü$G|ç;´>óu2äÑ.Ñ)ÔÕqØ™‹ùÛ›¹ï¾y|Ú²0M“ûîÛŶmGqÎ9ŸÂ4¡³³“tZ§µõ1î¹ç ÃrÂuÈBmù'~Ë·lû(쯃wónüEÕÊÝ&a¨¼cÊÚC.W®¶B×#QÄu—E à¿~óAÙ~ pÄ›x×»ºGü-}øÃsÑÆ _Ó4Ì’JcFY@º®£÷ùÒ ÃÀó¢Ðhª|]×ÇTþh˜Ô¤ô]]]´´´ÄF pá…²k×.Ö­[ÇÂ… cW²•+W²råJÖ­[7™U„ƒ’¡l¨Š}øø¼\r <­Šç×tKǸ¿?Æýa"˜ ûadHßVji;¡vû„Ú¥Vú¶‹ÐÙIÀ<ÀÏ{zÈë:K¶láÀòå(ç‰8õ ¯úëÛwýìõ€mä¿ØÿÞ³LcAÅó"µ# ¹ã•óû£æ™«®bÁÓOó¯?}йs·°÷ˆG8çSŸ¢¡¹™›î|™'ŸœOCÃÐuMÓ¸÷Þ{9óÌÙx^$t„a$twŸÆùçדJ•“Ýçr‘÷Œã”ëeY¥ 7žD±HìE¢iѺ¾!ºÔ>It½3€E‹"媫žß„\®Òse4†A¦t–eUx¬Œ¦ ˲\Þ÷óXÊ “*¨´´´pë­·ÆŸ{zz¸çž{hlldÆ ýÍ… Æ1ûcûöí´µµMæiBL[[>úèTWcÜ e›À˜íóÑGeíÚµ® °°XYj ?Ë•«ŒúYÆUŠ0ÙtuuÑÖÖÆÎ;§º*ã¦ö¹sçNÚÚÚäÁT˜Ö­[‡ëº¼ôÒKS]•q#}[a¦!}Û±÷m¡š¨¾íöíÛ§º*ãFú¶ÂLCú¶#ëÛ·D¡¾ )eÃ]ÿÕõ¼÷Úkñt·•®± vñZº+–†`ö%–_ö»‰¼QJƒ:}CU™f±ÁZò ün"ˆbpñØ-·0gÖNØt:K¯¸‚9ù—~ø>Þóžõ ! ~ò;xþy²¾Ï¶+®àMW_Íño_ À•7ßÌ>ùIÇ㨣Žâ™gN%›ïÏ:k—]VϦM«ùæ7ç‘ÍFˆmCw7‹‘ŠçEË #ª“eQ‘¿D )ÙìðßeõÏ÷2í}âÞqÄlÛ6³úz}•$«V­ªJßvÒ“Ò÷ôôpíµ×ÒÕÕÅ 7Ü?0dX]]]nfqÄGÈC§0e´´´Ì˜Y0ƒÙ&ŒÝ>—.]:ä6Gb`ítNÊ9úã ÞUÝŒÂDR__OKK ·ÜrËTWeB˜hûT‚0466ròÉ'Ï2¾­0³¾íøú¶‚P-¤o+}[¡v‘¾íÄôm}|,¢pNõ¼|à<[Ê­¤&„š”Æft0:ÁüwpN…Ù{‰fÄêýCa…!%ñ#±0óµG l†T LÑè|q!ÍÀ+Ÿû_Íçéîîn¾õ­º®óîw_ÎÖ­GÆÅèºïÃÉ'G"I& êxʳd § MëïA2šÔc‰juÌ1{€úQícš&ŽãŒþ`“À@!À’¬\¹²*‚ʤ{¨\yå•466–\¢ÊµråÊ~î_»ví’‚0I f›0ñö»§ú¤‡«g8z–jãû>aCûÌA@žC5¼m|ß'N»ª×pxžG†øƒL¹Pç5Øú‘c:1™ö)Âè¾­ Ô&Òv Bí"ö)µËTömutll ÞðÚ^ýu^¯«Ã!ŠÞ•ù{hWúdþÌÝÐþ—DIs[/9 ”•Ï£§«‹Ï¿|}÷ËóÈzÛ,àù0 ƒt:mÛ<ôÐá¼á o [ryÏ{ÞÃòåËãü$ *G ttD‰Oú #‰t¥0€K.7:ñEqÌ1{X½úÀàã)Qí$ïce¬ îÇˤz¨¬]»–žž.¼ðŠ™O´´´ÄIŽZZZذa]]]\tÑE“~Qá`c(Û¬†}úÀïð9‹‰œG¤„†~Lóù˜‹a¸®K†˜¦Yï1yÌl6‹eYñgu.aâ8Nü^ º®S(Ð4 ×uã:A€®ëø¾®ëq½T¹Û>õ)ö.Z‡Âr‡l6‹mÛqò4×uñh‹Â{WoJ"‡ïG‡¦®‹¦[hG¼©ù<‡¼©^ ƒçÞþvtËbó_ÊqÇýºþ>2™ ïxÇŸq ÷ÓÝ})—_þ½è° "—‹Bo©¹¥j˜i œ'#e2µ5Æ"ŒžITºººèêêbÍš5˯¾új®»î:®»î:®½öZV­ZÅúõë¹îºë¨¯’ £g8Û&Ü>{€¹–=%›Í†!š¦U*jP>›ÍBZ[[( ˜¦‰çyø¾‹ žçÄÂL>Ÿ§ûê«¡¡Gyçâ‹Ñ4->V>ŸÇ4MŠÅ"‰,JÜPÇV„"” –eÅ"®ë†A6›ÅMÓ°,+>/MÓb‘&•JÅÂD¦xS Jp]MÓÊǽývV¯^ÍòåËHhêèèÀqœØ…3—ËQ(*Ä'ß÷ñ<ÖÖV ÃÀ4͸¾š¦U4Âù|>.ËuÝøûèîîŽëĉºVííí8ŽC{{{\žïûA DjûL&ƒ®ëÌš5+Þ®X,VˆHétšM›6MÐ6uL…} ‚02¤o+µ‰´‚P»ˆ} BíRK}ÛEÝÝl[z/Gõô°£PyEB •(î— Ù× ]  …‘(áû¥pZŽCØÚ„¶ïhÐ#IJXÿÀnæÍÛƒïÿÿÊ+ ‚€ýûëŽs8¦éÐÒòa.„süÝßÅÇ?^΢òèz$ÞôB::ÆvÞ†1¹¢Š*ccRe|ƒ±zõjZZZèêêŠg'‚P}†³M˜Xûü*‘|ïAiîÁøð}?ÀOÐ;Ž &†aà‡Ñ ¼$\×ê3™ ù|ž\.‹*ŒÕ¢RÌÎßüæ7¸Åb¬â†ïû¤R)šššâã«c†A&“‰ëÔÔÔ‹1í¥Ì`JÐPõ„H”éèèГFÃ0 rªMÓb¡Å.ù–^xÇñúgžy&®ï@e%…)å]3Ü1!;”`¤ÊIzæ¨{ ²Ì>DÕ¹Smïû>–eUt …B¿Žàtd²íS„‘#}[A¨M¤í„ÚEìSj—©êÛþ¼O¾[xuûvXº”·½ôÛæ×G } MÇÜ(ýÿ¼²,ß=ðºOC[¸™öÖ4 ¹hŒæ„nfÛ¶¥rÈ‘ñÄÌoÛbéÒ; ¸à‚qƳX¶ ~¸÷¼'Іe1E1P(¯ZÖ)j1¼ýtcÒ“Ò‡4–‚P»L”}Þ…C”flä¨PV-s]—L&ƒiš¤R©Ø[Åó¼X,±,‹s·K¡I8MMMýD‚dÈ-ˆ Û¶qغu+‹-pÀ_ ö÷ éÕ—ÎÎÎ~ËT}”pây^,rTƒE¥f;wîä›_ü"7 “Àk¬†1éyLj5¦çd!í§ Ô&b›‚P»ˆ} Bí"ö)µI5lóu`y)í|¨ì¬ =Æ d~ൂ‘Í"WÚ‰¼Uâ®»ÀûE¬l˜FÈÜÃæÆ«}ô2¾øÅxà!Î9g³gÿ¦ ž§¶0N2ýõ‹pœÊDóÓ•ÑŽÕ†OÒ"jNPafã…ÔZŒ9Â}”§HGÂgÒu]òù<…B×uc%°A@ggg…0q'¡—‚ŒÙ¶M.—«ðé; ¯ò”|{ãF–,Y2`ýFâµ1Ô,mZç;wrî¹çêù1Qø¾/ ¯ ‚ ‚ ‚ ò°ƒ€H+©Û³‡³Î:‹Ö¿ypƒ}.˜vô"ñÃó 9ÀT_ÿ(ú¶upªÅý Áß*›½…gKcK{öìáúëKOÏ¥ÜtÓVZZærØa‡†‘hbY‘§K”=Rª<|2)˜¦å*½PFA&•€€å˜,F2ÌžJ¥â< :+R©TœœÊ?ôÉÊ3d$öÒK<²g .¬ÚuQùZ&ëcçÎ,Z´¨êÇQT;&§¸« ‚ ‚ ‚ Âôä%àP¢8&»wï†#Ž açN€ŠÈ&ahTúÐwêž=PlÝÊ’Y³±¾wg´.[Þ̶m‚ à–[6ñƒ¼›ÛoŸË–-'ÑÚ ÅbäТæ¸*Ae¦¡òíú¾?d”apDPaR xNƒ%¤W9NTbu•(=‚8qz²P Ü'’Ã;Œ;wòÇ Tíº$×W³A[°`›wíb×®],«ÚQˆ¿¯j£rÝø¾?þÂAAAA˜tæcc qãÿý¼ñÌÞ½Ð6–60€W!|‘7Ji@ɶÇÃ?ã¨}ýà¥ã /|oO6›Ê•ÇC.—›ôØoxÃx÷»ß]õã„a{äÌDèAFJHHž<>#ã³¥¿Ñ0Ú}BÂQÕ) ÀÅr¿°ô7žëåáÅ×MAaºáàÄï]`×®]üõ[ßÊ'ys”¡^< þÜ8Ç|Œ®'–yÿ¾3Å‹û¶1{önÇÁ¶m^xaGý/¿¼˜›n:†/}i š‹upÊ)Û)"OIÿ*ŒTA¨)T‘¾â‰ û•Éd&]p¨¯¯4!ýD¢Îk¦*“‘FA¨\\²d ú ð'E‰* !š¡èáÅËCB²dãeM4áààãÇB‚‹K@¹½I ‰jwD"IHH+­¤IÓJk¼ÌÃ#M:.#O‡©ø=@+­ƒ'Uúððb‘'y>êš$¼äÉ“%K+­Û¨ë6Øù$ËAA˜jv–ú&ðTc#GqóæÍ‹V†DYê5`v)=@BbÎýáæžh™¦ñæú fuÿýß»Éd2„aÈöí_ã½ïÝËe—í áÏÿ¼]ò©$'ìΡa_‚ LƒeÖP†aàû>íííqn]×§ÔÛa²ÒžO–±sçN¨bNÓ4I¥R“òMF®A„™„òŒÐÉf ¡ÅôzéÏ$Êóå㣡áã“&‹‹…E3Íñþ::..2„„dÈàãÓD::>>669r4ÑDHH3͘˜¸¸xx´Ó‹>>2‰‹‹‰I† Í4cc£¡abÆbL† F,f„„ØØXX±0¡ÎS½Ï‘‹Å¿ô§Ê°°ððJý € 0ÔùçÈaaÅ‚“_¯€“):éDC#O“`štf ìßÿ<óæ½t:MGGwܱ™ÓN[Á«¯Áå—<¡½„ê!‚Š “† I¦Œw]7ž B}©YÉäò¦iN©çÆd´·¹\®êç¸`Á¶=ó PÝ* dv•}f Èsíµ‰š•®'ZŸ&ŽÞo°Ê3̇(ÂhPÂ@'88±`b¢¡ÑJk?AA ÖwÐA–,Fé¯v<<,¬X0Pô.n<¸ßI'Y²hhdÈ Z?%ʨòhÀÄDGÇÂ"$¤@9ö³òÔÐÑãú5Óÿ¦hh¤HacS¤ï×AGÜ+i¥—"E||tt‚¸=¾J”QbG;í„„±€‘¼Fyòèè´ÓNš4yòdJNé¯H‘©Ø‹F¡D¦ Zi=L44 Šñðbq§ƒÒ¤cÑËÀ C/‡||tôXpÑÑi¢‰.8–Ý-S}› ‚ Ô>HoT&¤÷òrL|â´(èÿQz% / …!hÉ%ß'|}ú½ÿ÷]wíZÍüù¿á¹ç^æºëîáöÛçâypÏ=Gðþ÷—Š žê+ LgDPaÒX†Y!¨¨ÁpÃ0â¤ì¦i˜t~ªÍ úMŒ¨Îq&Á›ãøã‡Ç£çøã«~¬ÞÞÞªC‰nZE¯J˜ Ô€]_Ô`­‰I@@–, ñ ¦4T³¤‚x¶7‡õé¤?èU3¯=¼xPR„þ¸¸± Í•'„òV(Pˆó~(!9h¯…fšãíll|üx]ÒþÕû"ÅXdPË’BÈ`¨2•袄‹ä²$ÊûB‰% ØØuR‚L’äïF;íýêß#öþPÛ(A#Yžòøpp(P EŠ…x%:)ìÒ_²®J QËMÌØã&C&D’û(¯õYy®ØØñ= ê‘&M‘"VBMýöþí²¿å¨Ö-)‚P³}þXÞ" 2EH„Ñ’ ÛCdcÛö탹s£œ):‘ÁYÄ2Ay©àûø×܆ÎÆlnÂ-Yío~ó/^ÌóÏ÷ÒÖÖÏþý§V[ס½A3"¨T²Ç÷ý8‘¶ìSÆŠ0 ‚ qÔ7~Ÿ0v”ºÝwˆM…_T¿Á27¹¼DåÌž b»‚€b±ˆa57@"÷Š F@@+­)Æ–*´Œ_‘ˆgk«5*ôš ¯€ÕŒêt {Þ::­´VxÐ$/Õv}s¡ôµ’á»ú^ŸvÚãï]yA$îôÜÒñ-ÇŽûz ‚ L'òDc¶j4Æ$Óí zÌŽ±\A'99DÙº•O<økèøãh¡Vú/)™¾–8´·zÑ2Çü,”&Ç,[¶Œ_ü7þ ¼…ÿú/ñF&TFˆã8±ð`Y¾ïDZûóù|<{^Ó4‚ À²,Â0ì7ó^刂MÓâ÷–e‘ÏçTÔ> •kÂ4Ëó#ÔÀ´:–ÚF×ulÛÆó¼8±·ëºýŽ?Pî]ׇÌéàû~ÅùèºN†èºN±XŒÅ %.C4ÓcïÞ½åS} {ö°gÏŽïé᱆vÏžÍ1{ö°µ®Ž°oß>;ì0ŽxþyöÖÕ0¯´ïöùó™½{7{Ž9†º­[£í_z‰úgžaKKÊà°ßÿžÙ³g³ç˜c8d×.ŽÚ¼™ç8‚ý§žÊ¢BW~˜/¾ÿý¬ºâŠx¦JR¬9jÊîÊéG@À&àÉe‰ûKÙA­2“\¼_z饩®Â„Ñ÷·P˜|TŒÿ4éxæ¶òXQ!!9rñ,k P«Ì*fnC4˜ª&Éb*§‚ 쨜#*o‡‰YáA¡JecÉ{ Ÿ-öEå?ék£ÕÆf>° 16tÓ=¢í’×q p†C D‚Gòœ,¬~×a¸sÊso¸k*‚0Óq 1?>¯UâIr™ ÕC…†~ŒhŒí‰—^âS/¯‚f"ìãE†`Ö=M—” ÓŒrÄ>ûì³°6oÞÌûßo³~ýN?ý¾S˜ŽW˜¡ˆ 2 ©T*ö2) xžGd³ÙŠ$Ù#žQ?ÐÀŸc‚  µµ5~Ÿ q¤U˲Èf³ÇMŠ:…ò<æææø=D‚w\×ËUûìž=›§,à¾Çc¡i²ù¨£8ãÐCÙZWÇc ññêêêÐêê*bjÀÿ<öG>ö{Ž9†Å>Èa/½Äë °wï^߸‘ýõõ¼¾`uuuÔ—ò9(ž~úi,XÀûV­`gCoÙ‹$ uí• 3Ðõ7 ÃÌã‡dˆ£dîˆÆF rÂÆFÜU«°Jç‘ýìgÙþê«d^{ùžÇÜ-[ІÇã»/½Äa^È˧ŸÎýU½ g dF|¯$=S`êBz ‡T7Èä²wï^êêêfÄ‚a‹ET¦/ñ×A 4`cƃ è©Ð:# Ó• $BTž Îñ¡Bâõµ¤gIßù¹!íRCQÈ®Éf&þ>ô='%@ ‚ ãÃÒ”Çjkó Tf>*BÁc%O•×^{ã?€ü&0}*Ä£þœïÌ'§ëày¦…eA,¢®®σeËžá„`Õª/ñ•¯Ðu™-L<£TÖ­[GWW«W¯`Æ ´µµ°råJ®»îº©>Ÿ Áó<<Ï‹=-T>õ¾š 4Mp`YyŸŒdÐYy†è€fYè¥÷Ñ, ¿ôiÆÛ'_Õ¶N; ­ô9V“Ø6ù¨ç <€Y,|ßÇ(Ý/Õb8†‘~gÊ“0À¢0gNôŸ('é1ÔÖÖ-’¸s$lö¢QyyPù¾OSSSÍ *Ã5™^ìܹ“Ûzº¦i"¦LY²XXqN”^F–7GaâððÈ“' ˆsq¨_*‡ÇH™,/AA˜l|"!EC„A¨%’φ~õ+h= lÂy%óðuõWÄ P|\žxâe^øïïðÉC^aãÆ«¸üòÝ@íNÚ¦?#QûÜç>ÇÚµk¹úê«èêêâÊ+¯dÕªU¬\¹’{®®.nºé¦©>§1†!ŽãÄ^º®“ËÜE"*)u¨išFqäø€’g…Ú†²ø‘|Õ!ŽLØžØGcâ©r’?W“‘d{*˜©ç5ä¨t£VaåTx<¡ú{öÙÌ_ºtª«!LCTN•‹¡oHAª‹ƒ &*1|ž|ìY¢’¡«m’ÉÜAá`%RDIåå‰Sj ƒcv¶òìŽgY´hQ4੾˜~¡ºü]+h/B<òXJRÔQû)þTçðÛP# C¥/„ñ2"AeÆ üô§?åŽ;î`åÊ•ÜsÏ=,\¸›nº‰úúzV¯^ištuuÑX ¡4ÝH¥R†aC )É„æã% 2u¯ô^ $Ab}@9vgR´P9<’ÿ‚PËìéóÙ÷}4MÃ÷}lÛÆ¶gR`­ÚEáJ!Y²äÈÅy||,,‚~¹„á C‚ʃRäC4-Z'“¨„¡È–Râª^yòƒŠ&"¤‚ B4ž’"Š: OA‚P[¨|›‡ì[ þýÑÂÒ h°·ôìäûQ"úÅMkkì ‚aDÏOMMõ,¾ö6´ ¯rî¹—ò–·4’ÉÌ´X#B-1"Aå§?ý)---±˜Qø¯ /¼úúzillœ–‚Šïû8Ž3¤GЏ¥%d‡(Ó¡œ¼\aPK’:i@”ŸAOüˆ@"ÌžGÜÙ÷¼²Š*Ï0ÊKDåAÙcE;•ŠÞ«ã¨²û.SåŠgûÌEyˆ…„"¦‚ Â0d‰ÆWä‰Sj“Ñ8ìÞº:>üã%•3ÓÒéè!)—«S zö¹óÎ;ÐN)‹"¤“ˆ•… ²nݺøó=÷Ü@K"wOO6l`áÂ…S}N#"N“Ífq'5¤ieÃ%F"¥H$x¨-,"‘¥¡´[Z®Ä’QíõÒ>2 )¼Ô%r-„aX‘L|ĉÅó¥—ÈL"Ö #Åǯé•aæºL;¥ß’|>+°,†¤Óƒ ù|´¯ÚG ,a-Óõh»\®üY×£ý”€’ËE³¨‚ ¥ÜáÙly½[ê`47Ge¨ãAäÑ¢¶wœè¸jY:í«ÄUF_ÁE•¯ÊLž»P;„„±gŠ ¿'‚ ÂàDŒ3·+3‡ÆMÏs®÷*+:‰sÄC´*3}bÌH=Ÿìܹ“Ï~úæó¦'# ùuá…â8ŸûÜçhiiÁqZZZb”žžÚÚÚhll¬ 6===ìÚµ«Â󥫫‹®®®ŠíV­ZUÏÏóÐuß÷)¨ Êa½"Ï’ÁeˆÆrÛD˜Y d›P]ûVLñ€4‘ —J8T šr4Ð䕜Hf“iŸ!á´™ïáU|N¥ XŒúÞºžèŒu¾M3zõý(ÔV:…æR9Nt=r¹h™aD‚…ëFáºl;ö:¢ím»ì‰¢š\®¼]*÷óH°("aE9é©:*±ÊuÉç£×dÝ“aÄTùê¸A½Wu ‚èz¨kÑÚ“mGçnYQy¦½Wç.ŒŽjömóD±áLÌ8Ù¼ #c*ú¶‚ ŒŒjÚgšh«L(„±QíqÛä¡Ã^?ŒO<ûfÎzá¸0 tKù%5 l;öä7 õ¼ç±sg3kÖ¼…‡úÜT_.á cD‚Jcc#·Ýv×^{-k×®¥¥¥…ë®»ˆB­Y³†ÆÆFnºi䊠SzêWå´µµÅÞ/Š[o½µÂf¼„aH>ŸÇ4Í !¢qÚ<åð\C¡!3„™É@¶ oŸa"®M»Ê(¦PBIŠÈU ½<‘˘_Z®—ÞçKÛ”ãïAÔƒÿna1YöéââáMIˆ/%†x^ÔYVB',«ì ¢ë‘ @¡2䕚±”ÏG¢¦EË”x¢ÊWÛ*MW‰*“òå¡"ÂÈ™¬¶S„ÑS-û ˆB³Ë£  ŒÉ· €Ù¯Ïæô§3gÓœh¨·”›²·;ÞN=§¨g´/}é5ÞøÆ.Ö¯ÿ7¾ùÍiÒS}É„ƒˆ *+W®Äó¼~ËW­Z5*ãY»v-ëÖ­ãž{îáꫯ®X×ÓÓSõNl>Ÿ' Ã~ùRÒDã²#Sa&2”mÂøí3 `Oòs`X›KÔûm”™ê” 锽O”€¢^C"C.R[²¥2sÀ[‰*F§œIÂl 5Lµí³/!!ú¸z©TJ °¬rçYy](±B…Ò"ÔbCש˜½¤º.®‰¹\´eE"„ï—Å({w$Ãu)Ïöö²ø ¼LTx/%dtt”Å%HF$’(oµ¼PˆÞ'»$IšŽŽJñȲ¢m“7I/UˆÎµ¹9ªs6‹iFë‹År˜0ËŠD–îîHÌR^3jòÎQõPuQ⋆2ñ,“ÉèÛ±WŠŽ~Pæ3„Ñ2Ùm§ #§Úöé"bŠ Œ•É·U}Û&à”Wz9ªç¨höz"§¤çA¦µÔÖaË–¯ÒÕõ\vÙ.î¸ã"/~Çù,º.!J„ÉeÄ‚Ê`Ô××ÊV­ZEccc?1ˆ¼]n¸á†ªž°ëºtttÄùR|"1Å šø.+CÙ&Œß>ö÷q¸Næ-ŠcíyDÊæ@3¡ûöŠ3¥}ŒA¶1)g!ÔW—¶O /ÙÒ:§tlÕ€«öXyÇ$ •xc•^UƒŸì¹«°cA©L²¤•–û¥íU.•d),-ÓKŸÝÒ{U¿L¢ Uß TO•AO¼/Å 5~âüUYAéßNœ·FYœJ†õ7ûl#Œ™jÛg_BB:éœÐshm- *¤T6½ª|!ÉŸ5xŸô QásUâwõ¼yn ¢m‚ *?“©d'ú¬<6”·ˆÊW¢Ž«¼D::ÊùRT“ÎÒ¥1Ͳ·HÉ( 'P¬žêŠv¨ž::ÊåªóÈCD•¯^•‹¦õ_åº+å1£ê¯kÖ¬áî»ïžêjLƒÙ&ŒÝ>ï¾ûnÚÚÚâÏÇöIJ_5T(¯‘ 12—2£´íb¢ÄG9 ³´¼èÀ.ý[D‚…b”(àMh&êI«Ðby •H QâŠg”h’§,6¨7q&e‘§‰²x¡„( J@i*7 ú!Ë—–¥K˲¥÷NéX­‰}z€×õwëJ稼{’‚:'½Ï¹9¥mS¥mÜÒ:§TV6±M>±¯z­6l`Íš5lß¾½:˜d&Ú>·oßΚ5kÜn¢ó3$œ+Ï’¤Àåeº^ö*QbƒFÔO† “¥Ä€yá1qùPTî ˆ<5”G”=YòùrbxU‡B¡2ä•eEËL3Z”¨ ¼P”W‰]NIÏUŸ¤(£Ðõ²Ð¢D!Ë*ŸW{{tm\·jMm£¾SåÍ£D+åµ’ÍVnÓ—µk×ÒÖÖÆŽ;¦úrMÕîÛúøSâ-&œHßvhúöma²P}ÛÍ›7OuU&„j÷m“óã¡ÚHßvhTßv°qdXñĮ胚h 8_ÜŽ¾åñvaO=õmm‡qüñ=\sÍ\–.ÝÈŸþéES}É„¦­­­*}Û{¨¨» /¼uëÖqå•WrÇwôK6VºººhiiáꫯæÖ[oeݺu\{íµ466é³lÙ2n½õÖÃó<2‰išjìVB| cåÖ[o=(ªÆjŸ_|q¿x¸ŠXPI yÊUÄÃ<þü@‹U8±<‘GË@õS?+ZbŸ¡Ê„þž4}—ƒ¼W$ÚXß÷¸6QÇD 9¯=i(/ž‚“å– z¸dµ>)(µR«Tˆ7“èGYyÓè¥ëê3rá,ÁÊ•+¹õÖ[G,¸OgÆbŸ‹/´íœHA%)ž@YIFûSñj0^‰*ì”=Nr¹è5•Š–‡ai0ßzœ-Oz›d2eÏlj„šŽŽh;U– i¥r(Á¢÷PM”£ëåp^¶]ö`QžE*˜¦EáÅÔµUe(ÁJ‰ca•±zõjY·nÝTŸjU™¨¾­ƒƒ%K„IBú¶cïÛ B5‘¾íÈû¶>ÕS’!‰ômÇ7n«WýC'ljŽÆÔXG]nû¢xHAÓ ±ñ5}ôßÐ4 MÓhiɳtiX:Õ—G¨QªÕo‘ ²nÝ:ºººøÕ¯~E}}=¦i²víÚ «˜ê (ZZZ¸è¢‹X·nÝ„Äæ ‚€0 㜠¥\¯â™"# ö©ëz¥§‚ÊR‹(Ña0¦K8+HÈx½ôŸaò®¹òÄé>-y]mÊaÍ”¢¼tlÊ3‘S(­ÏqPSûç¡ÙUH(ˆÄ’L&1°üšüW!½\7zUIâM3˜×´Ê[}þvúSdå^΢Du\ÚJyŸ¨²Ô±“å eq*ÂKÓÊaÃ,«,¾tt”=‚2™rx5åÅ¢®¹mCC|ï{ãŽ:[óL”mzx¤Ç*JµŸ=A;ãµO•bs¢AE8Ø©FÛ©æÞýv÷oY­­®Ÿ¨¯‡’W DÏÏ>û3,ë xž‡aض]J^&‰‡üjii‰Åˆþ˜=TT/* ÊB… ½¥’À«êU…†RyS”§Šê{^4ï8åÜ%©T)9¡ó #Ú79Èošå¼#º^ö”èì¬N’Iâ…2*üÚ`Ï(ê;RÛBt u½œ¬Þ4£ï­X,{"Ù6üêW GV‰iÌDØæxìQ„Á©ö³§ cg¼ö"QH¡LdÛ”äÉ {U¹o¡?¸®€ëºtttLõ%bF,¨¬_¿¾"ZWW@?w¯‘&ˆh»n¸ 6°k×.'l†ïûض''“´ž‚08ƒÙðxì3$äx –—>ŸÖ}Z¢i¤cDÅbœGÁÅÂÐ@×ʃ­® –eƶºi#í*©zÉtÐb5í=—+'qH’Í–“d³å6“«SÕ-™Ù;Y•¬ Û(éþª„©/} ˜=¹uŸ lpv¹˜‹§º&F5ì3I3Í£T\7²;ukª|$…Bt;*O•%"J *º23õ:Yt½0aⱬòwûñofݺ]S]¥ ¥}[›*ð Â$Qí¶S„±3Ñö"“ga¢¨æ¸m0TF¢ÒøŒŸ‡æfâÐÎAgž¹ØD±XœêË#äŒHPY¸p!«V­ªXV­çÊ•+'¼Ì Ðu4#¿¡?aŸžçñ¦Þ7U†mêK6‰ R©(|Œã”%+ÍÀuËɫð¬‹$õ…¤ÃI2áu?‹Tr; WïË'Vö’QBGßéîù|9)D•JVÂ÷˱|?ZŸÌíyÑ…€òEHž˜:Y5Ý_ÅDR‹ÑòC_¤aÜߥP[Œ×>U¨¯ £S1Tç6)¦¨[0rKåÔÈåÊ·­ç••Oeª1E¨ã±Í€@B~ B©Æ³§ ÃXìSÂ} BõoÛéá‘&M† >°mÛ6fÏî?áÓ¶Ëù7}V¯ÞÄk¯=„ëÞA$¦0…ŒHPY¹råˆ=Oj ß÷1 #ÎO,æ&SÏïßöûÁ1›Å[¿“òà¬?ÔÀ­iFÚãDlr»l¶ü^…—Qyno¾³ccìÙ2Xî²0,çq0 Êñ‰T2k?7å¢âA¥ ¢b y^yŠE_Tå-Ó·‚*qÄ`¢OnÙ¡4 öì©ò7,LGBB ŒQÞªH|IŠÅÈÕ«J$?P>Ž (çU¡LH(bŠ 3 —RaL\\||,, ÂÒ__OY‡,YLÌx[³ô§ ñ‰úàF¿|p!!Á€ž¸Aé¯oˆE=~(£ªwò÷:$s>º¡ppxuþLŠÝ+ÂÁN÷ üð¬_óªJÅP‡z>TC$ÿöo ÃËÉç7šCÅÇuÄA £Î¡ÒÕÕźuëâ_\tÑEÔ××Oõ¹ ˆçyœ|ÖY¤`”snA¨ºóC¯(M=HùítS9Hëûe"Ž^u½RHåjP9”âyåe;ƒ¶uäó‘6ÑòŽŽÈñ#“)‡/Êd¢ò ÐÔÔuÛŽÅE9„ŽêƒEfQSð„a'AfXAÙÇ0Œñ=ž™&ÞÒ¥â­'ôC BŒ%Xª×0,;cµ¶–©ÒM³2 ØŒ%dâ‚y‡H<‹ƒy a<äÉcc8°¯B­$E€ÁD…$}—òä±°ú•£>»¸qy.n,„dÉ!ÏTVõQå«m:éÄÃÃÇ'M:.C•íà ¡a•‚{§ˆ<ºµÒŸ<||2dâk£„UOU y‚øjh×N-÷ñÉMlÊ’EC£@!ˆ\\ôÒ_@@žÀŒ¼p 5„Ñ3*A¥­­[n¹…úúú8Ø-·ÜB[[¶msõÕWOõùôÃ÷}öýëØHîA˜*v–ÞoY¿…å‹–ÓÐ7䔊T,R,µ~b|W%ªnoiUD-õJ‰Ê3¥P(‡ ò¼hÐv¹ù,w9KÑõr^]ëûÑ6n4qM‹Ö§R`›:–®ãûÑg%ÀØvÙ+Æ0¢øžííeǶ‰ÅKmßÞm_(”Ã%Àª:[V9ÜY:}6Íh½*7—+;·(Û.T+‡À¬kFO<‹©ñ<T2qÛ.‡]SË•x¥®+Tž«Nê½!Ï5‰z°)éttÿºnÙ>s¹rD;¨¼/ûÞ]wdÎUSŽruíÛ™PbIß!à…7L—^!zÒÏM@;å§~­´}²|7ñšÔ»r¥2)•ë”êg”Ê/PÎȪ¾RÈ#Éä¦* Ÿ 3“¾âD@€ƒC† N,T¤IÇž&f,dÉR¤Hžh’‰‰‡ $9rñ€¾†{¦ªí•P¡öQ"€ƒ‹êwI N…øÄ¹Ÿòäã:«ºêè±ø H~VçÒMw\¶K,¬xÛ0*2d*¼Orä*?ÂN¡¦)ÿî½`¼Ì퟇–ò36›EÓ´(jÇŒq Ô:#T6lØÀ-·ÜÂwÜÑ/ùP}}},¢8ŽSS‚Šã8ù7ÃåS]AXBªêÐ Ì[4oÀmTŽõ>3¢6Õ¶#AA5¦êU ØjÚà9 £$J°…«rÏb§(í({†¨¶;9H¯òºû?Ü„ûàb:ÿP .MMeOÇ)×E×Ëž.ííÑ:u ]¯ôîP^m§ÜZUºåm¢Â™)‘H•aYQ9ê¸ •Ò%ÙÏP8ÇÝ4¥u é5ýzÃNì 6áןÿÜâ¨Þ¹×É,sp?g} íÞ^Â…Ëé°ËBQáòŸãÞw$ÅÆkÈvýlööS‚¨Îᯗ‘¹r;úyoÁœ]Gñ¬vœí—Æ×5'¾ßÞFç áüÇ\L=$ØvxôÝ·¼Bó_u`}´¿½êêßXº6l"÷ýå@9„[Fâ;މ‘ Þú~Yæ%ŒÈÁDA¦yòøøèè±Øô”Hâ7Т¥?«‹a2'‰‰Y!FýD"Åøøj}ßm’¹I2¥¿$}ë+Ôçd™  :úˆ„¤áòe©ïàÈMGNõiÕ4>ê]¦ ÑcÆI‡oáÕpi4¤ëýB¡«gMÛ¶Ñ4 ß[¨jA˜HF$¨¬[·Ž–––~bJ’«¯¾š¶¶¶xÛZÀu]^¼ûny„`wéõÙåÏrä…G²œåë=/ú7Írˆ Û.ÐÈeèšs­íhœ2ª} ´zè«ÏNŠ™e”(¢„d½«{ß´*¶].§ï¾É>E_Á@y w]”ͯ}Ø£¨ÓNÃüìiñ6Éh@™|æT™’›I˜éTsÞú@½å0 ñ}ÀD^)tZAœÿ! Ct]gÛA€ã8xž‡išèºN††mÛ¸®K†aq9ª,ÓŒÂ!iš†ëº†ëºX–…çyø¾eYñ1“ø¾aø¾OX£}È„qpÅ–âœÖŸ½ ­ïÕ‹åü¹étš\.7h¸/iß„ÉdD‚Ê®]»FTX­)Š_½ø"§Ïž-ѧ¡Ø ;¡Á59dõ!ÑB•¤DÅ÷*¡ëåV*?ÊT¢ëþßwûl÷ø ›b, Ú7üî_-ĶçO ÑA Ì'ûýJx²ßñt4‚¯›t£vÎ]K“Èçá„æOuõ§ #ÍÕ &¹nô å°sÝÝQÇ·BàóéþÊ'¤o¦ìÝ ¼>Ôø±Ê÷¡’ …‰m”°¡¼=¾Øçs޲¡DUåY¢&6é”E“d½3Dâ†NY,È%Öy¥z)Lâ˜A⽓8>”Cîi‰sUª¥ò ™Nϰ‘'Nòzªë¬¾²ÇO.ºÖ‡:ª4~‚ Ó†&š00âœ%9rUHG:Bª5o= CÖþìg¬{Ë[—,!Â0ÄqœXŒp‡B¡@:&(=À*á"›ÍT„+2MÏób¡D×ulÛ¦X,âya)n®ëºäóyt]÷I—F™-ËÂ4Íøø­­­èºN6›%“ÉJ¥âm\×Å÷}r¹º®£iù|×uÉårq]”0£PõÈd2hš'ÃL& ;¾ï“IÌT¢’l’áš\×Aì} Ì•'‚¦i±¥D%6©cêº Nɺ{ž‹HJˆRß›Z®®«eYñµ¶,+./ Ãø½ªwض×ñðßÔ{}& æÓ=Sÿ ÁžãñoÞ‡Õµ• Ù¶ÝO „©bDO³ .‘¨²nݺš ùÕÔÚ*ú¤ ÔZ~Vÿ «Ï/åaÊçãQòdh •;Dy{è50A×ÀG;¹¶Dã±rá¯wqÁ–æ-fÛTWeܘZLðý—É»`ö+Q*ç¨ó½?œ<ÕUœ6 %¨¨=¦ul!µT¾Šöª|¸•7‡A4¨ž£œ7Ä —A-׈<TN‘ TF+åœ& η–ÊØ Á»ôУœ ʉàÛ)çÉ—ÊU‚Œò&Q,•ÞVâU $FŸu$ÎA­K†ßêëÝ1”n¥1=ãT¨0iŠÑ÷oõ¹NÑu÷aþ¼ù,|qáT×¼fQ‰ŒA˜>¨„å..66::)Rqò±–92W*¯E„aH>Ÿ…0 ñ<Ïó8çSŸ¢®®Ž¦¦& È5øŸN§ijj"—Ëa÷ ; ’¾žjßl6{$—±‡IrY.—‹E˜ä2I †aTˆyÉ477cšf,JtttÐÔÔ„mÛX–Esss,Phš†®ë±ÓÜÜ]ë’@†a,ä(!#•JÅ‚E2DS²¾ª~ÙlÛ¶q'sR©T…0¢Ä%U†ªwR¬Quu]7ÞFm¯DUGÓ4iooÇ÷}Ç!ŸÏWœ·ïûñ} þ=Ï‹E'%åóylÛ&^}õUN:é¤jßâ3‚Ÿà± xx‡÷4w-½Îøí4y„ ài€|Üù8«Y'ɾwv (¾¯Â:E¯µ” #÷?§ƒÞ8ÕÕ7aû÷×îùcrÁôOêîm8í‘FôÓè[Í^³fª«8-ðð†¼U9’ é £üjš ÏVSöêh/½W¶¬<:T>›Êœ .‘≠j•×Cy8(ÔÀý¦’ ‚^Î=2P’¾ƒþP~ò.Äû4·•IEgàëi{'½|ïËìëÙ7Õ5­YFÆG„©ÅÅ%Mš:È““¾OD¤¡Úg^abÃ0öQbˆ¬·,‹B)þr+ðL÷ÀQ …B¼]_ÌaÂ(d0Ú_`ÖarÙ`3ùu]§{€sèííß'!%T(q#3‚‡tÇqÈd2qÔ¹%ë§!å-ÒÑÑQÕDãÊË&—xf4 £ßw–ôøQž7JLq'Â0Œ½f>ñ‰OT­î3mÀ4–oxl7 s[¸cï&¬£‹·ñýòã½ Y7œ Âd2"A¥±±‘«¯¾šk¯½Û¶Y½z5õõõôôôà8·Ür 7ÝtÓTŸOL,Y²dâEUB[5 “ M¢f¾:¥m­Ò¶”–éDD*~ºN4s¶oØdHZG…%Q‰i“3w«)«xócE…žQƒs*¦¾ú>ª0]¾'$äС5ѱËçKSÚçU„ôò¼R²ó˜U=jÁMf¢NcÑ"8é¤i/¦¨óqOºfFœËT3\(õ|£„O5k(ó1ЕsªÊ•a3ð€zò{(G«ZÖ÷9m¨¤çð;଩¾‚ˆ(ݯ/x½u{§º65‹„ñ„Ú'  ™fLL44ttZiÅšÐð^"® ÂÈG±­Ê1¢iZ좼ô)zãV£^}=t†ún[-r¹áfOUn£„#å‰Ów}Rdøð‡?̺uë&å\fõ¥¶­»·›ÙófÃæÍø»Ž†°ðý( B.§&ñ±' Ô #`}ÝuבҬ¼QvíÚEOOÜtÓM\xá…S}>l[ºtüÝO§ôŸ£2™ ¢Ú… å¸é*ô…O4»Ê1ÛU y5à”<Ž …¢âŒ«DµvâØI'9ØôÙÆ¡“rÜzU†ò W=B©~!åxò¥cX{€C~pû.ÝÇÜ%sÙò¹-ýŸG3çÄ9ø¡Q4€cÿåXöß¶Ÿù7Ïê“<†Ee\yu~É@§E¢iªÙ>ç¡ös('ÕÍ–ÊUç˜!¯ÜÊPƒr~⻲KÛ%ëáPN6$Ö…‰ãªÄÁGùî:¨¨#š £—bbbš`ø©ÈEé+*½PT5=Ý0ÕU™l§ñü#¼ °[À»9ú¬ÕAþ&°A$hLhLjú-Ì,‚1‡arpqɉηӎ/¶+S„š;9Ùl6ö>p˲èèè˜êê ÂAÉC[â„÷ž€}÷ݤæÞ Æ¡èa$¦¨Ho*çO2ô› L5£ÊzÝu×aÛ6ëÖ­cýúõ@”ˆ¾¥¥…®®.ÚÚÚbáeªùÉC±ûŒ3†oP=Ê!@šK¯6Ñ`¼P/ ä'ûÆ*l’¤z£÷Ù~°}’ë”H¢’݉eJ˜PBM>q<%2¨ñ0%î$OÞ ÃÒuB ,ä@êݽÝq²œ‘õÝ(¶§f‘ëÈ‘ÏçùÎ×¾ÃîÔnÒFš“çžL±PŒ’p͉«x¾‡íÚ¸®ËÙ+Ϧó׬×z>ïaæ¾gn¹ê\Ô«ž2°iÓ&–/_-KöeÚ˱5•«)€fkÛÄߥ>>†i€ Hèį́à9'4.›f¹¼XÐRÅ(QE%á}|¸›Lè&Jk0ÿÉùh­¥ï®ä®éy‘˜Q£©i}Z ŽJ&>SçŸñ3\x¡àqðëÀßù«Á,õ ŒoMuíkwFŸ ‚0sññÉ©h?'ZLÉ„q¡Ìp=Âl6K†‹ER©–eÈsA„ê°tÛRÎÜv&ÿÞ¹Û¡±‡J&f³YÚÛÛ«NF˨€úúz.¼ðÂ~Þ(]]]ÜrË-5#¨lZ±‚wuwC)4Ù€x”ÚZ”Cè0ánG™xíÛ'ÎõÙn°•a¢iNè`[6ùÒHµmØdý,…BϤ>%Ó*ºø¾O&“!²Ùlì¶è8)'EÖÍbþ¥ÉËÁË477ÓÙÙ'á*‹d³Y:::ðÐ/6¶eYñìDÇq*’\ …~ ?A˜X‚ ²ýWÑt=j¯4møþAV†%O†åüP‰šT©iQÞ8ÛŽ&8èzt¬d½óùhýhÇ ‚ <1E]×Á®a–¯›ÚO×£e{ơ̈ؓŸ¡LF®£p„AŒ$,˜ O:Æ÷ýx`V‚0ù¨l)çnÝ Ç{Ë¡€UÔÃ8Ï Ô£T¦ OqW80ø.‘ R$ š&}Ф‹›$²Ù,¶mÇÊmgg'žça¦iÆ"€ad³Y,Ë"›Íbš&¦iâº.Åb‘|>'ÝRÛ«+Ó4ã¨ä`˜àJvDÔÀ“:¾jLÓ¤¹¹9ähmmÅ0Œx†ˆ:†*/ C:::Èf³†A.—‹ë¤âœ†aš´··ã8š¦U¨Øét:NfšfÅuPIÆTY*>£eYhš†aÿ˜§R) Ãàî»ïæ]ïz×Tß5M‘‰ÝqÂoûÍ*PûŽƒä÷&˜\Nª •øøXC$Àò{ÀÜô§‚y>˜ï¼<Çqâ¶¢ßKÕY–{¶¶¶ÒÑÑïûñosss3íííqâȤ®Äl6 ê_ýêW©{¨ˆÚ¦¦& j“”8oY®yb*!>NW´J˜WõöKÉbTLmÕNX–…çyA 0ªÝTÉ,¡œäÔ²¬¸}U 8mÛŽE}]× ‚€\.— ‘ÀŸÉdâßNuÂÌ¡–r¨$…€ëDÿžµ-©Tä„Í*ŒöK¥"oBljʳ,hm-‡úT“*‚ ¼Vr¹h[%6hZ´^×£÷n)oa&íëûQ¹–m“˜‹ƒë–i•²©TTÏ##é8Ñ1”à¡ÎGí«Ž¡®‘ëB±ͪ4Œh½:†ïG×EÓÊùâòùhß\.ZŸN—C\47—¯‰mGe¶·G¯ê¼l;*S]3ÛŽÊT"‰ª_>]Ÿ ({©Ay_]Þ»n´ï¦Má]ïÚ0Õ·^MT=!¼_“xp$9½ L2? PÚ+“ÉH?J¦ؽ{7Ë—/ÇöÓ„¥>“ê+šf4.ùì#µÂŒTžol$Ów*V–ÈE…Ìê ¦“Ž'˜ÔŒZ5{6“ÉÄa°‚ •JŃý©T Ó4ñ}¿b G Ò¨Á%¨ “2PÒ­ñv0t]Dz¬x–q÷#æÅbqÐuýxªºiš×]1Pb3UþP‚¦iñ²äµiooïw=Ty‡z踮ÑÁ@7øpèæCYño”[H*6„ÉAÄa šÝªf/›§AÎ…Ö4\tQŸùL#êgWy‹hšFss3Åb1öüð}Û¶ãßét:{9jš JTPñ¬Óét,^«ÉÍÍÍhšF±ÈŸÏçI§ÓøòÎ=÷\¾ü…/TÄØUífGGG,N(e°Ž¹ß]×¥P(ày­­­ëÓét[žY©EA¨-RBû÷ÀÚ‰)ÝÝÝ|úÓ_#•ÊÇÛ8Ž·A¦iVˆúj™j{ÔL@fQ×uZ[[ÉårCòW JœO¢¼Vn8ü>¼äÃí¶jã“‚»Ú_‰äC¡iZ…gfRx ÕÖ*á#šl$®êÊÆ÷}r¹ÜˆÚOÇqp]·ÂÓ% C‰3<˜ÈçaX"š›£Ay%„¨Áõ|>Ze¯ %0(ïÏ+ ÿŒ£Àþ‡Ê0SIL“rÞ¹>¨[[uKÓReªí£Ð—• T¹IqFc¨®pr~N²¼¾¹ºÔO‘¦ y7þOœ Py@ªðT±gˆ —•4’ÞƒêáVµcÉe}QB×u–°¤ê×h4᪪ÞÃ1Òɶmǡà È=}TˆÍdø±hmm‘À$Ô.}s$—©ðP*T•ÿd®¶Gío±æJ0Ï‚P-ŠvGxh*”uF*z°ÕA;ægˆò : DàiÊŠF”ÿ/ty‰ç)‡Úu‰:ìQ^@·ô>¤†×'ʘ.•OiY*‹RÒTæ4¢:“/½Ï—ö×)‹;Ni_‹(pòxj{£T¯¤ùôý‰Jîk'Þ«z¨2Ä«FÙc>,•a—ê”þ­Òº°ÏñÕõUÛ©óIž›Ú&,CÝAâÚ¨r“?OjÜÞ…eÁ2qPõÌWm†T <¼–&3Ÿdsèº."¤Bñ¿¥Òž={ø“Wß›ŸÊ!I•—t2± Ô#TºººØ°aø8º--#ïy÷ôô°k×.û«««‹ÆÆÆ~ëFÊ›7S×ÛKÃÛçA3èóuÚiÇÅ¥všiÆ.=ýtÒI–l,Â4Ñ &ZÜi.P E~#9¥£ÇÂÊŽý;xñÀ‹Ìž=›Ïìàûc–xÑ€šµëy^œ»$™D%Áõ}¿_¬ä TƒÁlÆiŸ!F÷—bºHð­ÈKÄ(ýtÐÑoÿ\é OuÉëý€IDAT“¡À’¨ä½>~,¤NÀñ—Ï“O>Éoîÿ üàùéü”G¾ø¯¯ÄÉx‹ÅbO]½W3w•+ Ò„©` Û„ °OŽÞ~|ÆŽãvëúÁ“Ï#–/(™°ˆ? à _й¢ª}ßÇu]ŠÅbœT; Ã8L’ ¤¶S9ŒT>ÏóâœÒ)™žTË>û…¸t!øc8o WÃÿ{[W^¹”ý³ŸAÏdp‡¯¿ëodéWÀ{Þƒí†Eiì.—c (>jÒô`-œW<Q“-ü Pœ5M«ø­P}Šl6K>Ÿ'“ÉÄbŠú ÆÇDömGvÖóÊÞž–îbÈþ3´çÀ¿Œ×@σe‰"ŠÃA»’h€ß:¡RtÀ*öI8I$ŒÚ¼Bd¯Ñø¿r61ÌRY9"£/NXªC<¼¥‰Dz€rôз£¯¦WÎ:®øQ¢KIñÍ.k$¡¡ zŸ2ùJ´)Õ[/Õ=.¿2E_TÉ"^#^Ÿêô¢ò”/’Z•?tfùÕô5 µ—¯›%G²€h]Å¡òt1){ó$é`™ú±.ɇ9øYÛÏh™A.*Õh;}|2ýnAFKµú¶®ëJßFÆIµÆmšÑ_íÕÞòV¬£"ÏM+‡2U99ÅCE¨EF$¨ôôôÐÕÕÅÊ•+Ç}ÀµkײnÝ:î¹ç®¾úêŠummmÜtÓM´´´°aÃ.»ì2ZZZF¥xúøÜô_0Î!Ø|—̹(0j—ìäöCíkÍútòQ"YWsY¶c÷Þq/§é§ñÓý)º®óÏëþ™‡3ǃ©P™M¢ SÍP¶ cŸOìx,‹À-'aµ¬‘Åûž*’âTæ=RÿÊ£L5ø*ßC*•ŠgF©™*,ÚO‰%ŽãÄá‘Òé(Ä`.—Ã÷}<Ï‹·+‹q¹* mÛ‰½¡œ#Âqœ¸<@\f§)“aŸ1y@0Ÿ|2²Õ~v#Û»rôŸ´sèUŸÁ¹ürvÜsúQGEƒªDãŽ)¢q9É&(-ëZKÛ¨Éã”'H;¥íUÔ “r¤uÇ&ûKFÕ±˜Y(ÛœHÁSå±Qd2š››1 ƒ b!V;ÕèÛ&g¾+Ç e9 ÷iØÕK6Šã!ýa¸ë\x‡ ÿdu(4BþÒ²#ƒKÙA"gƒuË£²U­¤ƒrPu€²³ˆr²0?zí5þtölnÞ·ïÿæ7ì[µŠ³f¡»?„µ¹|è'N<‘ã,à‚Cá[{£˜bË`k]Ë_|‘Ð÷Ùxá…4ïÜÉ­³g³éC˜ýÛß²û„xyñb®Ý»—{Ÿy†—;ŒO?ÍóôvwóÑ³ÏæÏ>Kv}ÈÖÒóÊ!‡ÂÒmÛxí©§ØtÁÌÚ¹“Ù³g£W­â=G¿Â¿ð÷<ñ:÷}4u{÷²eî\NøíoÙ¿c‡<®3gÎŽ~é%zzzø³Å¯s髯ò?ÍâÖÙ³ùÃ1ǰàõ×Yqä‘ìºï>ö{,õû÷óü[ÞBOOŸùó×éÉ·ñÀEñ»º:ö®\ÉÉ6pé)§PèîfÉ–-ÌÛ³‡M+Vð¶ûïçÎ}ˆ›sÛyîÆÙòž÷ðZc#?>æ{Œ•[·òð¹çrìCqò† ¼øÖ·²d˶­ZÅÏD.|üq8á–lÙ ÿð\rÖYìlnfÞ† Ì;ë,v>öGz(GœwÿÞ¾ß÷éé9ž¯=ü0W­âÜùóéêé™rJ5ÛN•@„±Q ûLÈS“È&šá³ Âô§Úã¶ŠžÜͼmó¢OÊãBjx4›ÍR(ÄÓL¨IF$¨8ŽÃ† ¸õÖ[ãemmm¬^½zÔF³jÕ*éêêªX¾nÝ:.\‡ [¹r%+W®dݺu£R;=<^?´‡–}g£Z4ëªJ±Õ„@U³ÂÕŒO•Ö¶m\ÜX˜©FÃ.ãe0Û„ñÙg<Ï:€7¿ùÍ@z"wÎZ15‹IÍW"¶m†aœ"•JaYV<[C%HÓul6‹¦i†A:¦½½ß÷ãÙáª%Ž(QEy®A4 ª„('¹N’Ì9¡L”Íd2ß÷Éçó"âN3ªeŸÐ?>»7´e°[ƒí>üò—{ßüfÞ\wõM­l8î8V›&ù’˜¢É“§œÂ®#ä£?ý)a¢iß~ó›).ZÄG¿ñ R½½X–ÅCÏ>Ë÷¿ô%þû˜cxÇ‚œZ_φ³ÎâøžžÛ²…Û_y…×4þ¤·—+{ ˆÚ»GO=•‡L“ë3Ë/¿œÀóXûâ‹\ðë_óÍK.áà-ÝÝüÉwpò1ǰ¤¥…Û5§žÊ¬Ção{zKýúWN:‰[L“Ü4íÜÉG6làŒíÛq]—o~8Z&CÓ¬Y,,Ùßÿ=/8ÀÍ_ÿ:á5×ðþ×^ãsç² £¸ýG?âø×^ã„3Ïà-Û¶±yåJN½÷^þaÕ*v]{-'tu±Ûó¸zËf¥Rܵr%§îÙÃÖóÏg«a0ç¹çئi<ùꫜ±i›=c×.¾ù“ŸðÃ]»àóŸç—óæñú /P÷¶·qäÏ~ÆQgœÁs{÷òè† lš?ŸûçÎeþ³Ïòæyó8÷;ßáÞeËxå]ïšj³šªÙvJ"xAÕ°ÏdÚ)5qm¢AE8¨vßV1§{æ}ޝÃÍ—òõ%Î …‚Lj– *qË-·ŒI…T^. .¬X¾aÆ~e-\¸pÀ6ÉæÍ›Y³fM,ö„„Ìzý3|fÁÙp3%ßý‰½hÙl–\.G:Žgª«p<¶m÷KÂ+Ì\Ö¬YÃæÍ›G•?¨VÌ6aìöy÷ÝwãŸ<.Bx¬!dÐõÈ3Åq¢Fs²Ø»w/[ípLôY ÊÓDÙ±išhšV!l455‘Ëåp'N¾ å¥iZ,˜ªå*äÖ`¨™è}; 5C½ïlŽƒÅCeÆ ´µµ±}ûö©®Ê„0Ñö¹}ûvÖ¬YÃ…^È‘«¬ðÄôÞœ »î½÷Qæ¾å-,~ë᜙¹ŒG+—#OY1(§Lðˆš^%´¨¨2ÊÓÊÞ&™ÄöZiY1±½Zr¥}ÛKëTX ÖÒñ+_–Ž×J”;™ºÀ9p€âÖ­´uöÖ­°d Þ¼y´yÑän¾™|k+Zo/æ–-¤Ï?ŸÂ¡‡’-•©=ú(Nc#Å/~‘Ö¯|…â÷¾GpÕU¥óÈîØAæÓŸÆ9ë,£Æ?åÂåË fÏŽS.ð‹_à­XA{&CöòË)´·“¿ñÆØ+à”'ŸÄW6†•OŽCx uu?ý€†r*ªôØ ‚èß4û GÉ<*žçMz•µkײvíÚXdŸîLtßöÉWŸä÷¿û=œ}V¹Û[\¼«àªïÀ³çÀŠÿ…† !»"ºç•x§Ò{l~üqN]¶Œ¿¹åÜB[+«iþ©O±éì³yñ´Óâ0“©T*õçÌ!\¸«L³$À÷ŽwðöK/åÊùó1Î=ã¯þª²â—^½žqF¼èÈüGöœs·y$æ9çÀ9çð©Nú¼óâ·?úÈG §‡¿óÎx™®ë|䬳¼^á›ÞÄ÷ÚÚXº?ßÎåà”S€Ê¼B\~yTŽe£ÃÛ?÷9ZæÏ§=—«8þûÔ›‹.¢Tµë7oÛÆ97òà‡?\qœL /YR¹ßEáyÖO~Â対Êm×\-?æÞ?Ä÷ïº.©¥K¹jíZnY½ºâzÞP_}¨¯‡7¾€¯Þ~;Ùÿû?þvçN¾píµ@ŸßU·+âEïÿÎw¸óCâúä†sϿշåK_bºS­¾-€~]õûR#° 9VTßvóæÍS]• ¡}Ûßýîwüì‰'X±b…„7&éÛŽlÜöºë®«ˆ|ôí7Ôm½( %MWMR„ñÐÖÖÆÝwß=áã¶cT&š]»võ[6±fÙ²ež3s~õQÎ?ë¬rœã @ ¸&?'Ãh$b%VçÁí·ÞJ[[ÛTW£êŒÕ>/¾øb\|"p'á=gmÊIÆ&sBtss3³ÿi6]{»øñµ?®ðQbˆëºqX®¤0êº.¾ïS,ã0[…æI¾¯UÑBåh.O“º>jv×t{(Y¹r%·Þz+kÖ¬™êªT±ØçâÅ‹ã¶Ó£Ï`z©¸g~»ÌüŸícö_-âÌT´\ #J Q‚Bž8·uœK:M4È›¢$J”¡D‹Š” Q*…|ýðà /¼íøãã<Õ™t4b]î™gbŸq¦¡oýuëéfã΀`Ǭ͛i}ÿûÑgÏ&¼Þ^l×¥yõj ßþ6þ›ßLxôј@s©üô?ˆ¶{7úæÍ8Ë—Sرwñâø<½·¾•ÌóÏ“ýú×É<û,ù+®ˆsX7™£Ž¢õ¶ÛÐ÷ï'7{vöúr#ÉÒ)yYª¶L…­,‹±÷tss3oýѰ‹Å÷[/:Ἧ} {/ÉÁxWG~¡€9Š}߸‘U£hC5MãÔGU;¥io|øaÌQtDt]GkhàÃxxÖæ›¦ÉÎÖVÞSù‰aÐÜÌêQx’ž³jûš›ùè(®ó‡æÌáÎl–¿ê3 Lú¶CsñÅsêu§ò ÏT½ŽRLH"}Ûáû¶'Ÿ|2«O>™|>_µgéBú¶CÓwÜ¢ç¤íáÅ,-šK–| ‘‰êÂDÐ7G×DQ3‚Ê@3Æ’·eýëOSWW~¨‘Žq µf³ÙŠÐù|¾"L$yf2ãµÏ%¼öG¯±zǦx™iN¼wJ2¯‰¦i¤ÓéX,1M“MË6ñÀpçÄ6«Ä…d>$¦iþÿìÝ{œ\u}øÿWî !—HkâY. ·œ%â*Pä¬"(ZÚÙXo 3ÚÖ¢ý¥ÎT Zlu¦¤ Õ¯:ƒµ*d§¥¢¢{¬Š²BÌA.Y‚„KHdOvsOHö÷Ǚϙ3³³;³—Ù9»y?óÈcwgæœùœ3ç=çœÏûsñc]ÅøhÃ3ûC‘e2¿²M}ß©ž7j_¨!ÂÔ0h‘H„l6K4õ÷¯JÀ¨çÕÐgj~•°ŠÇãþç#ß™Ãc¸ÎŸ¸ðb+ì; /¾8~K_DOý8ø>5¿‰šcÙ ?¯µWqï>þ8fOæ™g¢Ïšå͇œHxÝÒ"Ò†Q8æ_Cƒ×£"ÅÐuèî”Ëõ¾4M׉þò—°r¥Š˱cüÕóÏó¶•ÍXºNtåJ¿U¿0n¬Zå%o>üá‚MŽäÊÍܹÞÿÅ‹ ž#·­Lš zSŸyfÁTĪÚ39~<Œ_°~µ…F‰ÇTo¨¸ñFÌuë¸ïcãëïxúÌ™l$Ÿ´J\z)¹Þ7—_N«÷‘ùC£eçÏǹñF²«WÓrð ‰Ë/÷篢ŽCÓ‚[·bnÞ gœAâòˉ·¶rçÁƒlÞ¼™™0™xíQTÏ¡;à?&LàÀ”)þ\7Fn;\¼„P/IœÏûD7ØØœ»m.Q¢$ð>}/è[AÜ¿s1ÿš½D,‹D®I}ŸkšÆÆK¾‡iš¤R)¿§R%“\WC\Ä`&©á4ú>}¯h4:àe ÃÐ2º®c p?¨ùÔ²LÓDO$ÐNÐ!@‡zî”d‡Õ3ÔøTõ6ÃJŸy™wlOö³Áž¿æ4pupŸw;pè==Ø Ú80§€µ´)àNc¸ãAŒ'À½œyàtáõÜ#`]‘v`>0ì×ÁØúnp§v18/ƒ~ ¬³Á|œE¹òí€÷>Lõþ;x×lªÑŒº&UÃ…*ª×+ä‡ ΗhF7ø·¢~™f¿VC›ª×j÷Vëíë›W½Ÿ: ZEëŒäž+¸? ߣ>øžn‰õï“`Ùu†\í8j ç}§œúíûám&h:‰wFI¥RÒ`]„Vh*Ë–-cݺuuuu hH1—i‡NgñÞ½ùÚž!J$´¶¶úÃ!¸®ëÏ=P­‰Î„›áˆÏC“w°gÎàMr‰ôÍf(êëëýy,Ë"ÇqÇŸ %ý³4ïz×»øæµßô+x‚'è¾*"ÆÚ0Yê»,›Í‰Düd’ú>s]· ÒLMb­æc±m]×ijj"$¥TòIÍCc†ÿ]ljÅb~bZ•C½ŸšÇA%gÔúT+ë`Ùe¾‡¼¡Æ§¼=ÈÀc¯ééáä3Žp`â<Î4¼|ÏU¡îlß ú £¹Ù rMCD@µ,J&½ÿŽãuS+>öQñ x_ÁϼèóŸ:e r –R ŒþÔ2­§Þ[ÇKD}æ7¿áõcǘ¼`7lð‡Rß>Áªï–ëò·eÂ8ùd/¹Eàæóì³IÖŠÄ–-ƒÃ‡ÙÚÕEfÖ,~;mwé:ÿû‘pêßýM—_îßT™83ãǹ–eY¼c )÷3‚×KGõ¤Ñr?U5­š]]šYÀ”E‹¸`Œ·âllNÞ?=Ÿ¬zoç¹Ðü,$ïöB"‘HøÉqõ[éwc¹^Š¥¨9ÅB%Ñú>#‘„Ì\bƒYfcßmøL:7¤[¥4M+9'Û‰b(çN +4 ½ð<.Ä0ØøTu± Á^wQÇ»PQ“”©®¿ª¦\_›;•ƒ½ ô?sA â'Ó Î}>ph9ìÞ¢é“Aÿg°'@æsùh°2K!2 ¬ ÀZ úïqóà¼ß¹âÀÙœ+ÿåý?p.k^‚e&D7‚µÌ—À:‘Ü“Á~/˜ghóÀ8ì u»2§¸»!~Ø ú×À~3èÓA?î{Á~ôçAèsÀîvö»\‚â&Ðúx¯ÜöÀvpfxåÔÀØîfÈš`lƒÔBpg@|¢×ŽÊ= ΫàÞÆ1°_¶}& ÁÝ,Mý>œÙÀ40NƒÔQïã3@vb®Ò”\Rç`n?ã0?—$:Ú!Ђsª÷þÚDÐ&yÉ+g8€™… žŽóÏgåîÝ5Šš‘1õB;±Ñ€Ó^ú"ü_ßwcrÏ/¬â„JGGG¯îßëׯïÕ¥m°]iéêꢭ­ÆÆFÚÛÛéèèàÝjâ ØØL=v!§½ür~¼‘!PCÝØ¶ã8þߪÒQZW‹ÅpÄçök~ÂÞ‡çùWød³Y¾“X,F2™ô{•©XUjѰÜ×RqËÜrßg¥*w¢Ñ(Žã‰Dz%œ\×%‹…•<Áõ'‹ ÎGì L¦¨eÔ6ŽãàºnÁúU¯Ó4ÇT¬?CO×§]ÝLþ™÷øiïy…ÅîT~ÿóXE~²x ¯ò€Dò ¥Å› ¼D‰ëö=¦Ÿ®÷N¦ `±ëòÆWðäòåðì³Ã²ÞRßv&œ2}Êtò‰£¥…î;ùüÝwsþ~D$ñ¾Oo½•ìÃûËG(šŸ! žüq¢oõ¹¿£ä'LÿòÔ©<ÿüïõêzlzû-ò:…̽ ÿ ¸®E}}ŒH$B2™$•Jùs{UJÍ6ªGbµ—9Q¾»Em 5>+ßd¨Ê½~´‹'’¡Æ§mÛ¥Ï=.Þ8¨êb¶|÷“|×kÕEAµ „a`1 ¦ÞºÎûaÆ-ë£y? ÒýiïuéÀóÁ×Df§å¸±¨üK@[ÑßÅïqcþï¨*Xpý®²×õœ ¼\ æBoƒ#äö“ <í ÍÄ|`:кX™‘{½š q˜íø÷XÀÎܾÕ!²˜ñ͹ÇTR˶y¯á·ÞçQ]AÊmÜÀZ¼¤ØÏMußV¤j‡¤Èw«1É·XR“?fÈOD§v`†|+!uKêx ŸÌ×!~CþÀèúÄ1~Ò¸Þ˘5õB‡rõ2õÝõ~ÅPpJG˲hnn–ì"Ô*J¨ÔÕÕQWWG{{»ÿXcccÙ‰‡jÍš5Ü|óÍ,_¾œM›6±fÍfª‰+àâòÊñã|èåñð]òMȶm8]×ýnfC¿¯×õBŒ2CŠÏÃpÊÆñìš:ð©…JpªáªÔPUj~Ã0ظq£TÊŒ€¾ö±Jrõ÷Ÿ ¦.œ2¹á¡T/š ×uý„‹ëºd2¿‡‹z­mÛc~[e¨çO ú:Øšk¥÷š¯ýøt.™?›‰¹]ߨ6xÃbé:45yÍä£Ñ|2ü^#Íe`­àÃhÞÊ•\uíµÞpUn´Q2!2Óqøò¡Cüômo#‘Hø½ÆT²³¸‚Bõ6SZñîC-¼ûÖÞ}nœÂäα­[ÙðÜsðÎwŽø~IC‰Mox7¾ ´BöQ˜{øs$?#NûIqÓ4ýž‚•k=/…ŒÁƧƒ3bs¤8Q åüé_—Äð*Á[r?ÕxOjÜZuÑRLýt"NßL@õU¯môó¸z.¸¾H?Ë™%ÖÑ×sªLýuM/¾Ø-w‹RêóN’oyXŸxêÛïhgWÛ.ƺ¡ÞwÌÁDŽ?^òy5”©4baVQBeÕªU¬ZµjX߸xB"õ>*Q£’8acóƤK¸nç…CêœOa ã 1Ú•ŠMb|‚ý“ÞʺêùœåM¥0ˆÑ,ü MMM$“IÇñ{'èºîÏÒ§×È­¢Z†úÝiš¦ß먘šG×u?™R*ó»ßý®Ö»aXU%>sœI@ö%`Â7ÞàÀÌIÄ.™Äíí5Ä#óz£¨àF½äIHæ²±‰Pûná*ùPîøonnöY5$Ò‘^ ;¾7Ætîû.›Íú1`åšnUR®*Ø‹‡ð++gjs3‘övÌÖVšššüaö2™Œ?”ŸJ¬477ÓÚÚê—G•ÊÄK¨¤ðî5‹’o¼Á´C‡jûa ³á¾¶õ?áÜ(yíÏdÙ¤ ~Ï!Å4MiÁ'D?†ûÜé÷ìB ÙpǧeY,_¸ÜëYÅë]Ð@aŸ"Õ2†Æ´ ?ø ŽàwŠeY8ŽãWdg³Y€‚¿“ɤßcJõèP=êLÓ,HúªIÁu]'›Íz=ëfÏfÏ[ßÊ¥;w’J¥ü׫9ŒT4MóñxœD"á'=‚½HÔðxétÚ†oãÆÛ•Éd +ã5 'FÏ­gãÆ=²Ù,±XŒ­[·úÛ§æU*–¤pâÏÕà å8`Íö"¼õ­_埈÷š/D×õAÍí!„žsg-=þøãt.îÄç}†A6›%“Éø½vÕù)•JaÛ6étºà<Ífýó‹šPýžH$ü‘Tc5ïà÷Vç%u>³,«dc%8ÔkCª†Á¹KUÏȾ–QëµmÛ?÷f2ÿ|«FPÛ¥~×uÝ¿îTçL57`4õ{ƫשaiUÌàü€ê¹à9Yõ¦W¯ n—jŒ¡Ê¡®K4Mó?W˲Ð4W^y¥Ö‡Ýˆl|¾ÿï÷†¤RÃuw“B Ép;·Ìø+r¿'¥ÊðÝ66fÙîHB Ý€*k×®¥»»›Ûn»µk×r×]w<_WWç_ôÔ£Øßó^Îûâ9p>•4]R)ÈfùÏéÓùÐìUئÓà8Lon†;½¡7Ô_ºžŠ#ñ*˜Šƒ]×!óÖh-Âd2ÍzµÊ¦é­#xslYÞ„¾®ë½Æu ’3€—°Qep]ï÷`…H"AA͵axcÜ·Û¶ *,¶%“ñžWë/÷>›õþG"ù²–º¡·mïu¦Ù{(˜D¢ðoÃ(¬¤S˪2«÷^œg2…É.µ-J0^ £°UµeyÿUù4­ÿáVÇ{MHZf‡Ù¾À0<®«áº0ÀyShhh Nû¡½Z銱§\%¡T$]ñEgýg»y!ÞÃ[þx}é¯@7ó‰”ç•’ª˜šwIURþœKº®û•JÁ!äT…‘ã8~eŒJº¤R) Ãð‡ &]T‚CM®*qÔ#À¯¨Q±¡†2M§Ó$ ¿ÒFU©ÊU©“J¥ ’”šëb:f<šFss³?¿œªX+•ü žE+ùlDž ; ´óàÃàk_ûLó³µ.š'¼jL>QõƾùΛÙuæ._MÇ æ¦Sßãë6®ãøŸ§á/ü‰ê¼‹Åüïéàï þw²êñ¨Î'ÍÍÍ~EVss3‘HÄ?w8ŽCss³¿ŒJ.¨ß0M“l6ë7P ÷`ïMuîUçõ·Ú~õ·Z·z]}}½¾Åbþû«ó®J8+áR©”¿.ÕAmƒÚ/ê½-Ë"‘HøëŒD"Äb1¢Ñ(õõõD"?i¤Gš¦ùë öæt]×O²¨ŸÁÄÍœ9sˆÇãþ1 †/V×@AC}ûöÕìØ ,ËâýSÞ_8|“\~JŸö0+ü”Jž3ظŒa ÅèPqBåÖ[o塇*hÅØØØÈm·ÝƺuëX¿~=wÞygM7æ\&¿°‡9{æTÖ2“ñ’)Ñ(lÜÈi¹‹#?xu½ïq‰ÊµÌM&½ z?ùÒ”Î0òú*YPÌuóC©”ªØoiÉ';t½w¢¢\£ëæË§.:‹+:tÝK"麗Ø(~>Éoƒ¦õ.C6ë%•LÓ[G0aTœÜ*^o_•çÁÄPñg\‡êQ¤ë…ï©$j=Á¤™z¾¾¾ðýãñšÍ0š<‡ oÀºþÀ¡aÛ½óýQ‡étšææfÒé´3å{¥!ÊS Øö™ýRÇÜ]°,p>¬5_R0qLl€× ô+¿þ Ú£š?ã8~Ué2Ë0 ¿²DU$©ºP‰ÕÂ5XQ£’&¥z³©½Áäo_Ã3Ý9m?Þ°ìÙS°|ñºKÍ?l\Ü"Ø0 xDµ-ªÒFUz©Ê`eWàM¼ó`Cè:_ݾ3üÖÌà%¦Ô~-þ c±­­ƒœÜîDõkÀ†ßÎoçÓŸ¾–x|ìô b4ÊÈ–eùÿª'Hð;W=‰DøÂG¿ÀŽïïÀqêëëýó`}}½nXûkùÙÌŸi‰ø‰ u¾Ù˜»U‰}UÁß_Ï‘¾zWÒx¥ÒùFU¢ TT¦Ô95XuNV,ËêÕó¦/"Q½gpðâÆ\C™gU­{ Cs®^½zHï7ÖÍÙ3‡ÉWO–$Š!¥F ùõ]ðxðô#C}‰Ñ ¢„J{{;ëÖ­ã¾ûîcÙ²eÏÕÕÕ±fÍfÍšÅ-·ÜÂ}÷ÝWÓ š´o_ßÉÕãBµºŒFýž jœò¡t-+ i}']‚L¥.ÀJõäÈú+¡ëå“.•$2ú+«iÂÖ­ý·h.W†`§/å.ŠK%{º]‡žÄÀíN;npû9v^û)ì6êSÃÞ¨›ËJ†€B Œ KxãØ1¾ú™øÇDßUJ¥ *'TåšSD%XT¢Äu]M;ÄYg…û‹iš~ õ}¡zƒ¨u+.6–h8¡žW?û« Τî±-[Ø·s'þ¢ µOÕ~Õ4ͯäS×B€ßZ9N£'“Þ9Û¶9I×Ùª¥¡¡ÁO`Åãñ’ •¡´4;Y€¾ÈÂíãSŸúw’Ékj],!Ä ¨'*q¯zö©ù‚=S‚‰Û¶éžÐÍ-W¬¯8!pWø]KõÜV‰}¥Ö“üª†¥TZ6uîí+É1ܪY¹WëÏc¬¹à± ˜6mZ­‹!„胃Ã4tf<7ƒ÷|OþqGý”{1:T”Py衇hllì•L ºé¦›Èd2´··÷ûºjšÆÞW&•N¨d2Þÿ¢Ö‘¶m“H$hii!™LÊÍp’ž8 LÝ¡1çµ=~G¥Ü“¨ÊOÖIˆêqc6Ø:LüàSüÏ—Ž¡Ÿwèsªú¾ÁñÓÕßjNX,æá¡'ÑhÔ¯l aræÇÏdÛ’m\c\ƒ¦iD£Ñ’-PÃÞÚiúyçq£iÂÏ>bïî%“É`Y–?OU°7 Ï0ÐT¹.ÿ~íµÜxÑE$“I²Ù,MMM~ èâaKDåôÀVxêÌI|壵¹¶BÚ²h ZMßÕЋ†aÐÜÜL4%‰”MÐ÷×ÛPQÞ´Ó8çÜO·Nûçà ¡ùà Òsÿ,¬‚¡uml¿—›M–,&&2hhDˆTô=#Äh5 7f¼ÁñqŸî#“É·'S÷}B„Ý '¥_µjÝÝÝÕÕÕÑÕÕU“ ±±‡ÆäS'ÃyEO&^-nkk¯J~ÕJH "®B ¿¥Ï¿À!ít²Y¯3P%ÈlÛö[¡[–5äîôBˆþéû! póÛp?O$VÝdŠëºÔ××ÓÒÒâ®z¢©qÎÕu2™ì5.ºëºþ¯Vî_„1Òƒ­F×"Å-¥ÕØñjxš’=]—k¦Láš•+ÁuÉä’àjšt:íW,ª¡YD…ž˶ؿ>]´¸Ö¥BäèeÆ–¶m»`^ ]×4Ì”bð–t/)˜ÄÍÎýSÉàãŠJˆ¸¸~|«DЉé'R\\ Œ^I‘RÃfÉ¢£û˨ëÔ,Y"DH’$A“T‹……‹K”()R~r&N ïºW•¼¤Ž*‡ƒão³ŽŽƒƒŽ^P¦àvƒ7”¡Z§Ú_j›#D ÓÑ11±±‰!C7÷Oí?µ¿ƒ«¤Q†÷§Úê³PŸ‡‹ëo»Ú7ê5Áïç`òK%«¢D%Y‡€ƒ rÚ‘M€7C~&mÐõ²&fAœ QM%TfÍšÕ+QRWWWðwww7ííí5Û—Iè4<6 ®/z2÷jqK´J¥Rþâ2¹µÕ1eîA^<Ùû©ä~2›Íú“8'“Ié"Dù7$pÙ®]¼¨ï'?sØGûJ$þyVMzžN§ýž'àMºÚÒÒâ÷Ž€¾‡ñ“ó'©ù½jøW|£ëº?±p6›-˜¬Þ/s2éÍÍÖÔDKK‹¿ŽúúzR©;wîô“,’P©Œ D¾ÍëOW¸Ÿï¦8n ﳊF½FFš–Ÿ#òÝGƒ'éæfïu®ë­3÷~·íü\Á×§RÞãAɤ×CÜqð'Q3ÍÂak‰ÂmPsïÙ¶·œ:f‚qáºÞ\}j›Õü„™Lþ5†Ñ{x\õ^ªü‘Hþ.^­+)ìJ«¶Y•Í0¼r¹n~{KÍy˜ÍzÏ«9ƒë *žKPÍï|L-§iùϤx>@µÿ‚åPË©ã¡øùàq#±9,²Ù,©TŠd2‰išò½'ÄspXÀ$üÞ::6¶_ïâÒBKU+ÖU" …ê©ÇÄ$K–­l¥‰&h@C#Nœ$HãÍw×L³ŸÄˆõËß@:ºŸ$öš10È’ÅÅ%I’,¬‚DKštA’ÁÀðÏ’õ_'N–,qâ~‚%Jǯ°V•ÖÍ4cbúëReQÉ"Àßvõy¨äQ_TB)E   y#VðY“0¥’E:º¿?R¤H"u µ¶˜}‚™ûf…— –eá8ŽÔϊЫ(¡rÕUW±víZÖ¯_ÏUW]Uò5™L†™3gÒØØX“ qp8tø0¼ü¦ü_Ù¬wÓPê†#'‰L2'„~Ç7Láh]•v2Q“MO®)„~::îYÀQ¸:ý]¾=~UE‰ÏJ©^&®ë’J¥ˆF£¤Óiš››I&“þc€7W‡®Ÿ¸=ÒBÖ‚Y}÷ªÄW6›%‘H”Lrg²Y¯‡Kàzëüº:R‰.^ï—`÷ýW^y¥Ö›zÆçaÁ‚·ñýж½¤€iæ+óUÒB%"‘Þ Óôžojò®‹U"Áuó•éÅËÄã…•í† Þãêïâ÷PI(üéºùõ'9"‘|BGžãä®Ûû½T’')L·!x,£z}6›/‹J48Na¼ý¤Þ3“tÚû=•Ê'8l»×°Â~BHm»Z‡eåWû¶8y’Jye ­‡e&câñüö:ŽW6×õÊ\W6ë­OíÓt:¿ÞL&ŸP*.¿(éåÓ^î³¶¡¡]×ýd „¨I!ÆÒ+Òü–ßâⲑ5ë$é÷ØØÊÖ‚¡ÁZiíUáßB¾ÁJðwÅÄ$ÎÀ®K%-Jõ°S=7‚Ôß*Q\–r6²qÀË”“ á÷Qɧb*aÔ×çìí"jÃÆfö1xû–Ñyæ›qœÂ[ 5ÁP©¤£ÕRQB¥®®Ž›nº‰›o¾™›nº‰U«Vù=TÔ„õëÖ­ãÎ;ï¬Ù†88œÔ½N?f (1Ù,xYO]×Éf³Òú]ˆ*;>y›¹£ïô©9èéé©uÑEÁñƒûë^«Z-‰ðÑа7‚6ƽð3gÎò:3™Œ?†eY$ âñ¸ß…[×uZZZÐ4­ Çƒ »^jnšD"A6›Åq8¶T*åÍ‘’.¼¹ýø)§pù”)|úðaLÓ$“É i±XŒSN9¥fpF…N/ùlûç¡« ˜å=®z]XVa/Ç––¾ç¯+N6@éÊü Õë#(ééïõÅï]ªD©åÊ}¨žQÁr¯¿Ô{©Ç"‘|r¢\7ø>ªŒaxû»ÜrŽã%±ÔgU\îR¢Q¨¯/Ü/å–³m/1R|‘¥ë½âÒç8ù{%©ô¯ØÁ©KV ª^˜r_)D Ù0õ²©þ0UUíè XòyGC×½'U#X¹/853™Ì GRÃß5Ñ„M'µÞ\1†U<‡Êš5k˜5k™L†»îº«à¹ºº:î¾ûîšßïw»î–x7Á.öEÔpBa2D5&sœü=U°Ç¿jø…÷BêõÅ£ GwP þTC=Õ€Pý´íüÈÁuF~ƒhÔ»· ®'ØøO}ZEõ¬Ñh¾a_$â­/(ñÖ«FPPü ¿íºžA"õÖl(˜LæÝE£ÊØÕà/XæàvF"Þ¡¤F` Ž$¡öçSO…Ô U¦\¸'.N÷U zQ‰ ÕòIM~hc— Xý¸/jµžàúŠiÅT×ìþnŠË¡º´›˜þ¤ÅåUë‹);¦¹èÍÔlhÆo`Ù÷¿Ï+Ñ;†¼^Çqp‡X,F<'Nã8NAESØÏ¿¢´d2I&“ÁÍÍ•^o_ËêP}×·¿±x1S?ò§LÁ6 šššˆÇã\{íµ´µµÕzsBËž ÿµø–ÿª}÷ ¬ÀF{÷fL%î`˜c©÷Ø`¶ ½ÈT¯›|ß©äIdsBE"^Ù²Mê}$™2 K¶-A_Y¸ÏT¾åZ !ªjÝóëØðÞ ,e逖 Žd½RÕ—8N¾Î@š©¨Žªî"8’¤ãôýu®ê¤-ÑÀH¯ƒ±aÒÉɳ³D¯é}]5”„ ZñzÜ6ÑTëÍcÜ€&¥¿é¦›¸é¦› n€g͚ŲeËj½ØØ>ÖÈ¿:–ïÆßÏE­šw ­aU…~&“A%ÔsÑh~$Óô¥iìàû4ÞcÅË«Q TÅ¿ªÀoi)VZ5>T'y•0&Ô \ ?­Ê§NúÁ‡™A%h‚£4W£(êâòª%¸;ƒ‰ üSù$Q$’ÿ½8ù¬ö…Jð¨åƒ-AÔºÔP×*¤>u«FTPõóÁïæ`Ò'˜PR‰*ÃðF@PNÁrªý}ï½§o ãÑ<¶ìÄfÚv“ƒãÊ¿6›ÍbYétú„¨lup &ëü$ˆ¢ÆßU  ­Wâ@=¦º@þzÕ$ˆÐ»—ˆZFMpXMI’e'ˆSc+Y²~¢F‘«’G66M4ù˪q|%ÁRž ¼ °øê·1O¹˜›Ï:äõ꺎ã8´´´Èp'ä“Áq«×*εÎôÇ÷`›ZÁk‚¯ >®& íoxƒRå ~gw¨$&ôÑÒ/ê}ï<úè£|å×_a÷ºÝ,]º”=ïá-óÞŸ¼éOèìôZ„­;—[^y…é?øÉÜü*¦i²yóæZ,¡fìƒÉ?Ì?½åq0¿_ë∡ÌP~ƒI\ ¦!JȆ –l[Òë{Q58®]…³-çnáÉ·>É<æõ9Ä”ey÷úªž$8²¢)R%QT…¢$¥¨¯ÓLÆ«† ŽZY_Ÿ¯›Põ&Á©Ë‚Ór©F¢ª%öÖiÛ^]P&ã-«Ê­êLN„ÄŒšK¦x21 í…?ûýŸa¶˜½WÇb1h!uÝ_c`Èß7÷Fûõ;Mã¾ám ? „ŠRëž(}™üÊ%ÀæòÃ൰t‡H­¿‚‰Õ"A×ó½ûƒs:ç›T½Ôë·nõÿ÷¯ø°ûE®Õ—Ü»”º >Vj8ãà¥F.ß×½U¹FoÁÄA©‹†àc•Üóõ5„R껲’‹‚âž3ý­£ÔáP¼ŒzMqyJT¡~¿úê‡pÆDX>û¦=y¨ìë²¹³éh7EUn“"ÁŠ%Xy©& *¾꘳ý-?’I‡nG%¯WÔjLa•€±°È’ezdúˆmßh´Ç롲 öÍ;¹úŠ‚z%Ôü(º®ãº. ~üÚ¶=&.†ƒ1­ÁçJ)•P ¾âÎxz2ÖKß!{Î’”N(,ÃçYXp‰·?šò#Î8û Þÿ0ÿ9÷?™ÿò|Þ;õ½¼}ÚÛÑãq>6þÿ¸ñÆ1¡Ïë.QäUø¶ó6þîÃój]!D?‰„?$¢¢¶¶ïÙNHù)ÆT5ÝÔ@/Q+y}ð«@5ݺ5_¤FÅhmÍ']T’§¥%_Ï¢ê¢Ô:TCQð^lhšÉ@s³÷šl6_Îl6Ÿ„QÉUÏœ¦k´Þ?Æ>w‡˜Z~J:È'­‚û48õY°qopä˜ Ë‚ööY<8ô†icÝÎÜÏC‡¼ú!Õ˜[pL&ÇÄý㉤¯†³ÁûfÕ0Vý^ŽøŒùR‰K)®KrÿèÂÂáÝîA%TÂêõSg2ãOg@äò’Ï77{'ÑHÄ%‘HÐÚÚêi¿PÕTª÷¼:)ÁdB_•øÅOÒöq’¶X^ëÝ$Ĉ;ïþ?ðäâÉeyÉd2´s('KÔI ø‹\Uvš˜~fÜÄìÕûBT‡Žî'W’$Y] W׺Tᵇiè¸;àåW_æøÛ¶ l™ÜXˆ®ëbÛ¶ß+%L-uUO&ÇïÑŒáà·ê¡TÜ3,ø|0™7Ø<ß.‹È¿ó."’áN*÷Aô’(¶m“Íf¹T»ÔO°ý䚟ðƒKÀÛ§½,YR¤ü}5kÖ+¼sêJ`M­7%tv/^ û2þØ>þô–Õº8Bˆ~ õ¥ríÁË=¯;¨dÁ¯s0sÿS¹¿£€™À"¹ŸVnùhnýVnÖ\g6P€dà±xÑ{¨ÿª^CË•ÝÉý×gsG¯WÛ\F=fåÊ£Á Ú¸¹ÿÁ÷VëÕåvr¯‰–³ï«ö•Ø&õ¼ÚwNîuj¨ýiÞ[­Ã¼>¸ïµÀëÔózàýTÙ´¢ÇÔ1`Ö£ö—]´ŽÜö,Þ½x;ôÄðÒ©/1ïÕypª÷·VKÎaäF !“Œ3ð!‡@ÝâOE¦†/¦†>‡Â¬¥³&“ù$‹’=¸^Õ3FÕ}†W7¦¦S=^Tr'8r¾eåGëÕnšùQKR©|ÂG=¦Fÿ0Œ|Â(ÎÆùçÕòP8Œ*wpÄ’IÙ_ñpt‰T~wµ.ÕZMrÅ`mæ"ör& rɤd2¿Ýºžj^Ó¼÷M$òI*õjÇbùÆÔ‰„÷û³9ãŒ)#râäÊlà%|ŒÜëUòG­/Na²G•à ìO•DQI— ùäŒ*G0” ì»`Â%¸ïŠ“*ªŒj_8rDs?ƒ )µ?Õv$eWï¡þVÇM°K¹ý% •¾í9¶‡³ž>‹©WN%ó‘ßúŸ¥´ÌŽ’~ù~W9dš^ n6›s=8ºÊ4(©T~Ø`××Í׬«î&ªR ò™œjËe´\¹Š;ÌüªÞ2Ù¬·é´W/Ö˜z"™Ì}¼—O$¼uD£ù¼”* ò»RÕ¯©Ý¡-*Á¥Ö­’+‘Háü¾jN_µþÿ0ÖñRæ«Äãù¡ÒÔ¨,j9•° ÎG ðø6^5ÂÍ|Æoð~ª}ühãñüôdÅm>ƒõýªú¢­mmm]Õÿ¼Ç€Å.çƒGö^ÐkøÁ0 \×âÚ='Ò½Ypè ™‚Æ„ÅsêFˆÐDSAÏÕxPÕo©çÔh j]CMNµÆc&¡²—c¼N÷’nÿ1×…††üܺo}ëý\zé%˜æt&Oö¾|G¢AüX;p„¨ÔQàØ¸.öîíûëÆ¶mšššFt¸+÷ ç) ŽÉ%*-Ę·pÞw^K&S8ïU%b±˜_^+êP]è W’D œú×4L&ƒa~·}˲ü®ü¢oºö¼Î¡CµŸ£PÑ·D"Á^úŸÐ„WQ¯’*É zš(Á‘ƒ——ÁÞ êñh‰eJ]&{FØ6~†%x7Éaíä*’så –-RôúbÁ×ä'¥åJ}Í·öñÚ x¯/µÞþN%j|¥t™u´ôó¼e•î-ÚZâµÁ±™Š•úÜÊmG?½úµúW\ÏõˆÞþ>õ÷<ð•xÅ™Jê—±ñ§/¡}sJþxP]9Š•ë©¢i0gN~ÂÚ`²EM^«jóƒq‘HN]%qTfÃu ׫Æ)SÝ#Tæ"¸|p|/]ϯ?“ñÊ©‡Â±ä]½¡ÞÏ`¤ õ7ÇñÖ`k˜® º·Ôóq#wÝŸµÑUw]÷ßÎt2¹õ€®2%A™ d¼ ‹®\…óÖÚ6Ø`ºX6IÖÿ‚–ž˜pÆ”—m1‚Y×E·²à8¹ºïÞ‡urgþÈ5Õkò^Mƒ¨nAÆÁÐõ@OÀ¢ïõi§uv2küøá?°Ç #¯î¥sòl‰|¾2“ÉJ¥HfN¸¤’ª.ÉÌýnÅsëfsÿTòC=¯FFQCÉ´Ðâ?¯ê·‚CÒ'ø½˜Ôi÷6f*/âpӃϲlþNÿ1•ÉVx9ŽÃƒ®æÆoæóŸÿüHõîâ„vð80n/ döìÒ¯Ñ4x<>"cë«ù5ŒÜ¿àDæBœ¨ôðcâ^,ëäŠÒ©ÖCñx¼æsé胺0 5cé(œCª÷¦è~â$“É`Y–?$œèßk3^ã¾·ÞÇûç×Õº8Bˆ,Ëâ]KÞÅ9眷’ïéLЍæßj (l½ùJUõz5 uj.®’j\j%“ÉW¬º®W;UÜã[M *YUå²ÿZ)~Ÿ`®ª.–¥©É{\Ýh—*«*‹ªÈìkª•²j&^¼½AE•ŤRùåûÚÕ#AIÔÙYX©¬”.µŽl6_鬨1„”X,?Óy©ýžJåg)/µ-ÁÏ?÷9EÎ8QšöšÆŠÎlüƒdfÚs`fÔ«R-tK-§/uí¦†,ÕSE‘¥Žâû`'—-þÎPúJ—×¶ cA•»³3KÅë vIQßKÁ¸Nü¢Ê^\Fõœ¦yǹJº(ªWpÂâ`ìã<ÐEÄ!"8¡‰Z‡š&ø¼¿Ë¶á×á, 4³moì3È_ƒ—ÚŽ`£±àçhÛù!o\—©¯¼Âá¥Kýë¦wîC›£têŠF£Ã>ü{ñ|J]ÖÂê5ì•FLÕ#eÉ#æÿìé¡FC諱_ŠT¯QÔû©d‰zÎÄ$MÚ•¡5—ÝÎMTjk1¼ÆLB¥ƒqìbÁ{Þx×H*ɯ¾5M£µµ5´s41&ƒ©û/£‹¾[½Û¶M$©úäc&&­´Jv]ˆœC¸Ì~Þtð5¬ƒ ü†Z•hjjòϧµN¨ŒÅ-Lj––²Ù,¦iÒÜÜ]×%>LǾ††]0Illœ‚$Šá~ ý ýB>ø»…Õk5:Jqâ£ÜÜ»š?‡§*£¨1“P94þ2 ÿaÀ»v-N0g³Y4M“„Š#¬§ó,vì˜F{{ïkÇqÈd2#ÖµS’)BäíÂfvœþ¿b‘f07ÐU¿/v®%m:–󩨈®ëþÍ‘®ëÄb1®»Nz^ôç]?ü­§~¦ÖÅBôaÞ¯æ±÷²_1»ùG^¢$í]q^\¡'„¨ª]Ï>Ë#ÇÿŒƒã%ÜDo&&)RC_‘’Øì{s’'w¾ºóu¶ñxMÓ†­‘­áËUJpè®,Y?q!BšÁÕM©ùv•J“9bt UB¥££ƒŽŽŽ‚Ç–/_ÎÌ™3Ë.{˜ôÆ wÏE×õª·€b¬l|vN²Ø³çFvリqãz?ŸÉdp]WbSˆ!Êùóý¿6yߺﰭ~‡ÞÜ:ŽCss³ßãSˆRI¸öööZeD 66§¼z”Wusj½ BŒYC9wž³éê¾5vŸ,5·BTÁ`âóÔŽî:€ñwµ.½c×PÎ“ÑØ¼c:ïæ-ïÊ?žJ¥ª>4°šGWõF‰AGg#eH,1`¡J¨¬]»–õë×é0+VôÔºøBŒiƒ>w:°wâ^¸è9ø„¨ŠÁÄçŠÎNÆ¿óhّ؄ƒ7”ûN€‰èœÒ:…#“§Œ‚Y­!¤Õœ#2Dˆ”VKˆJ„*¡ÒÝÝ= @T¦Óùݼóè²ósõ¼Æq¤òGˆ!l|N›°˜Ççü+/8«z íº®?i±bðŸ;¾×IçäÉ,ZtŒ{îéÿõš¦áº.¶m˼)bH¾øÅ/ÒvŒ3=˜Øœ·w//[ĶmKj]|!Æ´Áž;ýÔ¯ùùÕ?g%+k½ BŒYƒ‰Ï}°aû92ÈŽU4ØsgЙ»phþé¤Rù邲Ù,Ñrsl €ŽN†Œ?i»ôBÃm|­ ÔÖÖF]]Ý –}}’Žã%S‚ú۶MSSiª Ä  :>÷¿Á»·O"ï=÷œmÛd³ÙZoš£ÞPΟ öãÉsÎaöìÙ”kwÉdˆÇãÃ6Y cÝ`có{'][6…C3Øø\ö©G˜?e~­‹/Ę6˜øœ§hgžRë¢ 1¦ å¾SÙ1ùë<þøœ‚ú¡áž›SG§“NZi%IR’)bØ…&¡ÒÝÝ À­·ÞÊYgÅÅ_̺uëÊ.·k×.²Ù,sö¦ë”."‘Þ½SÔP_2y®nk×®eÆ µ.FÕ 6>7lØ@Ïñ£tN™Mssïçƒ 1œ:::X»v-{öì©uQªn0ñ¹gÏÖ®]K÷Ñ?²àØ<¶ŸvZÙ÷I$Ò+E ‹¶¶6²Ù,{÷î­uQªj°çÎMðÌÈe«¨¹¶í߆ ˜ùò79çÃçÔzÄ F]ÛîÚµ«ÖE©ºÁ^Ûþ°çJz¦l¯uñÅ H®mû·k×.Ö®]˦í›xxþåó€ÂidN]Q-ëÖ­«Êµmh*466rÓM7ñÇ?þ‘;3µk×–búôé¼ù¼óô N=å)‰Þ¯‰D"’LUÑØØxBŒ?Øø\¸p!{OžÊ¾ôÅçG˲H$8ŽSëÍcЬY³hlldêÔ©µ.JÕ &>§NJcc#=t£ïÐÙ»÷IV¬èìóõ¶mc†$Tݨ««cÙ²eL™2¥ÖE©ª¡\ÛöôÈü)¢6äÚ¶ÿø¼dÒ$œ©šTüˆ§®m§OŸ^ë¢TÝ`¯m__x)—_~r­‹/N@rm[þÚ¶±±Gsè&¾ñ:@Aý­Ô ‰jY¾|yU®mC“PY¶lYÁ8|¼ûÝï.˜'Ÿ|2»ÎžÌœW]ævvcÛ½_ÓÜÜŠùS\Ü¡¯D„ʉrÓ9Øø\¸p!“Žç‚ó/ xªÇqˆÇã’ìU1sæÌ&¡2˜øT •qÇ£T§½}W^¹¢Ï×[– Wlqbª««ãÜsÏeòäɵ.JU åÚö’K~Œä/E-ȵmÿñ¹dÂz&¾Y*bÄ©kÛ“Oû ƒÁ^Û^|ñ)\}uù^×âÄU­:9¹¶-mÛØØÈI'Äâã1Ž*qGY¶lÙØN¨tttÐÞÞ^ðØÌ™3+Zvs_ÃÃGßFkkïçÓét­7{è+¢†ŸÓŽNâ{ÝŸÄ-qí"•³B ÝPâ“cÀ÷2>¼°dŒ‚—L1 Cæ!b€†›?žªuñ…ÓŸKžîæÕC;^Ñ¿ÁÆgq>!ŠIÜÐ é¾SÙs”ß?ÇÉϱë8Žß€OˆÑ"4 •¶¶6n¾ùfL¾îînÖ¯__ÑdG{€Ifòÿ¶5÷oÚ²,l[¾4…ŠÁÆç–E[ :;Wôji+“Ñ 1<†rþä(»ÿK,\x¸Ï °Ç E/O!F›ÁÆæîÝ»k]t!ƼÁÆçÓ+?ÄÎ…—ÖºøBŒiCº¶¢:Ò»p(†%6OáPÃ× †„—¹uÅh4±ÖPV­ZE{{;×]wuuulÚ´‰U«V±jÕª²Ëvïùí3¸ó—|> ]Ç É†‹Qk(ñ9õàbÆÍx£×ãIiB$İÒùsªËî¹³8óÌñ%*ÍÍÍèºN4­õf 1ê 66>Ì{ßû°¢²7B Ø`ãsÑ–E<5ñ©Z_ˆ1m(×¶BôG*C3ÔØÜð<ýô‡¸çžüã©TŠH$Šº[!*š„ Àm·ÝF{{;]]]ÔÕÕ (Ëùú¸k9vÒ¸‚ÇlÛ&“ÉÐÒÒRëMCCZ÷ŠÑm°ñÙób=“'M*x,›Í’ÍfC›BŒƒÏãã™Ë–-×á8´r]]×e‚@!†`0±yúé§3yò'k]t!ƼÁÄçö)Ûy|Îãe_çZîç`Gì·s˹u#÷˜¨AR*©† .¯çÊWLÏý/ÇÊ•ÁÌ•#¸îáâ¶}¨´Üvö&Ž»/®uFÄPꆄÕ3”Ø|›©óàøñÅ÷ÉdRFD£N¨*àM3¯9KX°à`ÁcŽãH«Z!†Ñ@ã³{útÆÙÉ[Þò+àLÿq×u%™"Ä0ÌùSë>ŸW¦÷ô–Oc+±*ÄÐ &6%)ÄÈh|®Óz´ 42x ¯¢^%OÔïAª"04z'Ôú]òI õ{%Œ\YÀ²&°Å†¹†÷~ê+hOî—Ù%6@-Û l2Eå ›,ÍíÏÑÜFýDI¨Àà놄Õ5ØØÜ‹Ë¢M:oÔ=Üè?ÞÐÐÀÖ­[k½YB Hè*ƒñ6/\Ém_|[Áã™L†ÖR³Ô !FÄÞ“OfâkG™4é,ÿ1Çqd^#!ÂbÜ$¾9ï Ûg÷zÊ0 Œâ‰É„BŒj¶mËwû­»ñFÞ Äñ’¶ ® Á9u#H$¼¤C$éý®’¥® ªÝŸmƒ¦y R)¯·¨ëz“õêX¹i“IˆÅð‡èTëpo†á-[oàèp_Ö[>íýµœëz¿[dsÛÚ ¼Ç€M¬´@ÓóÛnYÞú5­ð½#‘|¹Ý\·–àk\ZZòå–#›õþG"Þ2¶í•ÛqòåSïÓÚ MMÞïû/û ¼rG×C&“/§ÚgÅŸÚßµ\°Áã£ø³K$(˜68nZZ¼ß÷îš×Wÿ8Bˆj8©ýe&N,¼‘|b4 •£À¯[4–Ÿ™¿0™£AˆZÓ^×8rS§.È?¦i2á˜!²cÚ4ÎI&“477“N§innæ=ïyµ ‚{iâDM›F¯=•KB¨ }MËWˆ†W‘®TÒÎ/x/kY^E}ð±¶ŽRïÝW9‚Ë•zMð±`¯ÖTîçN ª—ÞöìƒàkÒioŸªaIÕþ Þæ«¤Œ¦å_Sj{¹²~•ÂeûÊ/¶´ä“,Áϵ/*)RÉd²Ïï,uÍ¡^Û™ûÒS÷÷]W¼=ªŒ•ô‚/^6¸Ž¾¨²©¡/*)£Z__ïWÉ>Qï×ÙÙÉÚµk+;ÈN@/Ô×síÎdÛú½!ô*5Zææ5€Þ°aÃ]f= éóý+¼T1é=,ZË#•¼G©×T²?Š“5ñ­BF{&BçÖÔ¾_#‘ˆÍ)Äh26*ÇŽ±bÂ&tý2ÿ¡° U¢££¡IBe z꬧`_­KNAÏñIœ{n¾‡Šœ0… ‹I'k,|óM$…­=c±‘á¨ÑB Ø)§¼È@Û¸®‹ã88ŽSЃ"Nû ŒLÓôÅTåºzNýTI‹þÎÛêz»\2£¿ÇTB@ýìï^•¥8)1R×ý2iê‰my[‡Ÿú öüÂóæ‰ÌÒ„^L „êEhÛ6¦iú=ƒ='ƒ½ÿ¿G`°7e:ö{|÷ÀTçîâÞÁeb±Ø€zS–뽩–Ïf³~OÈr˨Æ–e‘N§Ë.l´‘Édüe‚½6c±ñxÜß'j–ëéYɾöJ .³ý“ÛI|-ÑkÕ;´ø}2™ †aôzÕC7¸Ì§>õ)éÝYF×Ô7˜ðê1þä3üÇÔ±$Äh3&*§Lâ‘©gð«¸T*ª¡Jtt’r 7&­ýùZ¤ƒJi¯ÏvèüE„ó×Ôù577³±’ñ „UõøA˜½} .(xÜu]âñx¨%!zs]˲ †éŠÇã~24ØsÆ B ƒK.¹„o~s>2wn¡QÒ™fÔ”STO6›õ{o‚wŽTçSE%CT" ¸WeSS‘H¤ ‰ùŒÁÞ”­­­~OOõ¸êñ©þ.¦–QëS=Aûë=®–QçüJz*öõÚRË7„JHõSÕ ô׈«¯÷©¤g©Zp3ib}÷ U?ÓétÅÛuÇwÐÖÖ†èÛÎ 6óÜw±té^ÿ1iÄ'F«1‘P9<á 6ìKÁcº®Ë£57…qoLõ»Ì;ŽCKK‹´î" ^†Ù]»¹ð²#Ûd³YÇ‘„Š!eÛ¶_F †ÉBT×Ë/Ÿ6j†â+Ô¼?ª•xpøAUQlI_¬Ô0àÅ­õÕúTOõXpýÁ¹ ‚sJ©k¦â9¨T﵎âòª×¨a+]fïÞ½ˆK$ò½t]÷+Ê››› †aøåê¼ZÜ0¡’ÖôÁã18‡¨YáH0ÙR®'hp¹~ÔCÔÔÁ‰œ6m.ïÿE€7,¬Ô ‰ÑjL$T&ÿq93¦t§ø= !jk·6‰ÃÛgû«nÒBˆ8l9ûïÿßúVþaÕN>ªB()c Q[¶,â}ï«ÎºU¥ºª¸Wöª’]=®ZÓG"R©Ñh”l6ë‰Düu©ûâ`Ò!›Í 4gÎZ[[ý!{²Ù¬¾H =ÔÒÒBss³?”ŽzU‘ë8ŽŸ”¿£–Åbþ²¥†"Rï²'“Éø‡*5 Oñö©‘+ú{¿l6ë¿®ë~ÕOõ”ž)8÷TpŽ(õw_Û7Øež{î¹Z‡Á¨¢Î›Á¡º‚ZZZj]D1‚LLR¹Cáâbcû +vÙ*÷Pýšë=ÇÿS‹Ñl\OOOO­ 1«W¯æ¿Þ?åÉkøÝï.ò É΋‘°víZe¼Ì"mmm|ta†o¿…ýõ­­„ «W¯æî»ï®u1BgõêÕ¸=žßÿ2Î{îÖ¯¿ðnÚ‰„Ü\Šªkkk£­­5kÖÔº(¡Sê{˲,b±˜?$…Õ$×¶¥ å{Ëq¿wƒJ¨ùš››ýñýUÒB5@êkŽ€`/ˆâÅ=äžxl‘kÛÒŠ÷‹ëº~N*lÅHkÛ¾©øœu¼cs¿Í¾Î üùg„¨¶j\ÛŽú*G¦Oçø‹ ˜5k7à]¬Z–%A)DL:²—ËÞÿoÀ7hhhÊ !Bb—v3_|ïxÇqÿ15N³"…iÓv°té<,Ë’Ø"d.¾g6+V¬Àqâñ¸$=…5ѵ"|²Ù¬$S„!©"¼¶aÁI/óæ7Ï&‘HÈt bÔõ •ñã_dáÂÈf³B„Ìé§ÿ/K–tKËw!Bhû„¹¬XÑéOª+„‡½{÷J…!µ{÷nâñ¸œ7…¡H$Rë"!ú°mßn.˜ø$à%?¥1Ÿí&ÖºÅ:::èèè ®®Žººº²¯?~üyšš.B×u9 QeÏ«¯¾Úoý.„¨®Æç‹hÆ4M“ Z!ªh ±9cÆ ™ÓHˆ2Ðø|ê©§xó›ß,çM!FÀ@ãS12›][¦³èÅz2™ ¶mË„ôbÔ U•uëÖqÝu×q×]wqÝu×±nݺ²Ëœ~úéD£Q²Ùl­‹/Ę6˜ø¤ç˜#`0ñ¹dÉ_J¥°,«ÖÅbÌì¹SQ}ƒ‰Ï+®¸BžBŒ9 NƒÍÿYʬ3OÂ0 ’Éd­7Cˆ! UBeíÚµÜyçÜ}÷Ý|÷»ßåÖ[o¥£££ìr–eÑÒÒRëâ—öGGmmmµ.F¿Â¾Oƒ‰Ï—_~Ã0B;tIØ­¶¶¶Š¾ke4|œ(Ÿ·ß~;‘H$”C£áØ’ïQ‰Á^ÛŽcé {¼Wj,}&ÃáDŽO9¦Ãg¬|&ÃåDÏÑp \©±rL¥Ïd8 &6ï[ ­W ë6™L&tÃf†ý\2ŽÁ°ÇûöíÛyíµ×†u¡ò«­­Y³fÑØØÀ²eËX¶lmmm¬ZµªÏåÇá±ÇcùòåµÞ„’Ö­[êî©Ï<ó íííµ.F¿Â¼Ÿyæžzê).¼ðÂZ¥ªŸ¯½ö=ö .¬õ&”æc ¼IO—-[ƹçž[뢔æïðâ‹/ûI3ŒŸ|æ3ŸáŠ+®àýï­7¡—0[Š| Þk¯½ÆÆyã7j]”ªìµíÎ;ùö·¿ÊÏn Â| TØã½R•|&rmÛw|8p€§žzŠ{E‹Õz†äD:¦G‹rŸ‰º¶Ý¹sg­‹Zuƒ½¶ýö·¿Í¼yó˜7o^­7aÐFÃ5p¥ÆÊ÷L%Ÿ‰\ÛömûìVf¾’óÎ;]¿,tɰŸKFÃ÷B˜ã}Û¶müá ¾¾~Xך„J{{{¯?kÖ¬²Y‰'²|ùòФ²téÒЖ àÈ‘#Ìœ93Ôe ó>ܰa»wïfܸqµ.JU &>÷ïßÏI'ľ}ûBûù…ùؘ9s&¯¾ú*{öì©uQJ ó÷ÇÞ½{Ù¼y3ǯuQªn0ñ9qâDN=õTŽ=ÊÏ/ÌÇ–"߃·}ûvžþyÎ;ï¼Z¥ª{m{äÈ~þóŸ‡ò³ˆ0ƒöx¯T%Ÿ‰\ÛöŸãÆcûöíüâ¿àì³Ï®õ& ɉtLå>um{äÈ‘Zµê{mûóŸÿœ… †¶1_%FÃ5p¥ÆÊ÷L%Ÿ‰\Ûöm;eïxæûK6o¾Šýû÷×z3z û¹d4|/„9ÞŸ}öY/^<¬ë MB¥«««×c•d·~ñ‹_ÔºèBŒyƒ‰Ï~ðƒ|ðƒ¬uÑ…óŸÿýßÿ]ëb 1æÉµ­á5˜ø¼òÊ+¹òÊ+k]t!Æ<¹¶"œ{mûðÃ׺èB »ÐÌ¡2kÖ¬^…y ;!N$ŸB„—ħá$±)DxI| ^ŸB„“Ħy¡I¨,[¶¬W vuu…v 6!N$ŸB„—ħá$±)DxI| ^ŸB„“Ħy¡I¨466ÒÕÕå¹ÖÞÞNGGï~÷»k]4!NxŸB„—ħá$±)DxI| ^ŸB„“Ħy¡™C`Íš5Ü|óÍ,_¾œM›6±fÍfΜYëb !ø"Ì$>…'‰M!ÂKâSˆð’ø"œ$6…ðŒëééé©u!‚:::èèè ®®Nº 2ŸB„—ħá$±)DxI| ^ŸB„“Ħ!L¨!„B!„B!„B„MhæPB!„B!„B!„+I¨!„B!„B!„B”! !„B!„B!„Bˆ2&|á _øB­ 1ZuttÐÞÞîOÆÔ×ó³fÍðóé½½©S§2eÊ”P•¯»»Û¶éîîæÔSOPFrÿ‰Ñg(ñYëØ¬¤ µŽÏ0”OŒ^ýÅg˜Ž­ÁÄg­c3lûPŒÕŠÛZÕˆï‘Þ–j§å;bt©æ=i˜âs¨ñ7’ÛRÍ{\‰ÏÑ¥š÷¤µ8ªqï¦sçPË*ñÙ[öIww7¯¾újhÏa¿7nooçùçŸ}½íˆ×­õˆA¹ýöÛ{zn¸á†ž+¯¼²çOÿôO{ºººüçï½÷^ÿù†††ž{ï½·`ùrϧ—^z©§¡¡¡ç‘G Uù6mÚT°o¹å–ŠË0’ûOŒ>C‰ÏZÇf%e¨u|†¡|bôê/>Ãtl &>k›aÛ‡bì¨VÜÖêx¬F|ô¶Të<-ߣK5ïIßC¿‘Ü–jÞãJ|Ž.Õ¼'­Å±P{×0;GãgvaÙ'·ß~{Ïí·ß>àòDùÃ~o|Ë-·ô\yå•¡¯·­EÝš$Tᥗ^êYºtiϦM›üÇ®¼òÊžL&ãÿü 7mÚÔ³téÒž—^z©â燓:0‚VÊÜg]]]=W^yeÏC=TQFrÿ‰Ñe¨ñYëØ¬¤ µŽÏ0”OŒNåâ3LÇÖ`â³Ö±¶}(ƆjÆm­ŽÇjÄ÷HoKµÎÓò1zTûž4Lñ9ÔøÉm©æ=®ÄçèQí{ÒZ Õ¸w Ó¹s4~&aWë}rï½÷öüíßþmÏÒ¥KK&Tjý™†ýÞX% U‚§TyÃßµ¨[“9T¡££ƒÆÆF–-[æ?vÕUWÑÕÕ@[[³fÍ¢±±€eË–±lÙ2ÚÚÚ*z~8­]»–eË–±|ùrÿ±0”¯­­®®.nºé&fΜ‰eY\uÕUeË0’ûOŒ>C‰ÏZÇf¹òUòüpè/>ÃP>1zõŸa:¶ŸµŽÍJö‘ħŒjÅm­ŽÇjÄ÷HoKµÎÓò1ºTóž4Lñ9ÔøÉm©æ=®ÄçèRÍ{ÒZ Õ¸w Ó¹s4~&a†}²|ùrV­ZU‡•–o$Êö{㎎V­ZÅÌ™3üáȤnÍ# •Ahlläî»ïöÿîîîfýúõþÁÕÞÞÞkÜ»Y³fÑÑÑQÑóÃ¥½½õë×F{=^ëòutt°|ùrÖ­[ÇêÕ«¹ùæ› ÚþÊ0RûOŒNC‰ÏZÇf¹òUòüpè/>ÃP>1zõŸa9¶ŸµŽÍJö‘ħŒjÅm-ŽÇjÅ÷HoKµÎÓò1ºTóž4Lñ9ÔøÉm©æ=®ÄçèRÍ{Ò‘>ªuï¦sçPË*ñÙ[öɲeËhll,9/F>Ó°ß_uÕU¬Y³†îînÚÚÚüÄ…J@„!¾kY·& •!Z¿~=×]w¬Zµ Ègë‚‚R¹ç‡Cww77ß|3wÞy§ŸM¬ôýG¢|~Öò¦›n¢®®ŽÕ«Wûne‰ò‰±a ñYëØ¬¤ µŽÏ0”OŒ Åñ†ck(ñYëØ¬¤ Ÿb¨†3nGúx¬f|ô¶Të<-ߣ×pß“†)>‡#¹-ռǕø½†ûžt$…jÞ»†éÜ9Ô²J|öö}¶Ï4Œ÷ÆJGGwÝuëׯ÷“)åÊö{÷á(£$T©»»›Õ«W³víZn»í6n»í6ÿ¹RÙÏ`†«ÜóÃ!“ɰlÙ2¿«XWWííí´··‡¢|à¨wÞy'¬Y³†U«V±nݺ²e©ò‰Ñk°ñYëØ¬¤ µŽÏ°”OŒ^}ÅgŽ­¡Äg­c3,ûPŒMÕˆÛ‘>«ßµˆ­jœ§å;bô©Ö=i˜âs¨ñ7ÒÛR­{\‰ÏѧZ÷¤#y,TóÞ5LçΡ–Uâ³·°ï“°|¦a¾7V–-[ÆÝwßÍ}÷ÝÇúõëCSo[ëº5I¨ Ò 7Ü@]]–edèÀ;ØŠ?„®®.?ÓUîùáÒÝÝÍ]wÝÅ]wÝEGG=ô=ôP(Ê×ØØØ+ƒü»¿2ŒÔþ£×`ã³Ö±Y®|•µÎ°×ÛŽtÝš$TáöÛoïYºti¯ÿÁ½÷Þ{{zn¸á†ž†††‚®’ç‡[ñ†òÝ{ï½=K—.í¹á†z®¼òÊž[n¹¥â2Œôþ£ÇPã³Ö±YIjŸa(ŸÊÅgØŽ­Æg­c3ŒûPŒ~ÕŒÛZÃß#½-Õ:OËwÄèQí{Ò0ÅçPão$·¥š÷¸Ÿ£GµïIku, ÷½k˜Î£õ3 ³°ì“¾*µþLGý±Šõa®·麵q====ÃÚßFø:::èèè ®®®d—¡rÏŸåSï1kÖ,–-[6 2Ôzÿ‰Ñ-ìÇVØã3 åcÓh8¶jýý1”sgXö¡[†rÌ…íxJYGz[ªužÛg"†f¬ C¿‘Ü–jÞã†é3C7VŽ…Ñô=#ñ9²Â¾OÂþ™†¡|íííþPXaï‘܇’PB!„B!„B!„(C&¥B!„B!„B!„(C*B!„B!„B!„eHBE!„B!„B!„¢ I¨!„B!„B!„B”! !„B!„B!„Bˆ2$¡"„B!„B!„BQ†$T„B!„B!„B!Ê„ŠB!„B!„B!D’PB!„B!„B!„(C*B!„B!„B!„eHBE!„B!„B!„¢ I¨!„B!„B!„B”! !„B!„B!„Bˆ2$¡"„B!„B!„BQ†$T„B!„B!„B!Ê„ŠB!„B!„B!D’PB!„B!„B!„(C*B!„B!„B!„eHBE!„B!„B!„¢ I¨!„B!„B!„B”! !„B!„B!„Bˆ2$¡"„B!„B!„BQ†$T„B!„B!„B!Ê„ŠB!„B!„B!D’PB!„B!„B!„(C*B!„B!„B!„eHBE!„B!„B!„¢ I¨!„B!„B!„B”! !„B!„B!„Bˆ2$¡"„B!„B!„BQ†$T„B!„B!„B!Ê„ŠB!„B!„B!D’PB!„B!„B!„(C*B!„B!„B!„eHBE!„B!„B!„¢Œ1PÉd2X–Uëbˆ\×Ų,lÛ–õ9ŽC&“©õf‰ø{Ç)ן£‹Äæ‰c ±iÛ6®ëֺȢ»cÏPÏ«·á!ñ^µº/•ø ‰Ïðl|–:Ê=éè ñxâí19¦*ÙlvÌbSSÓ°]ìÕŠmÛÔ×דJ¥hnn&‹ yŽãÍfk½ib$>Ç–D"ACCCɸ–ø]Æbl‰Ÿ}©46Ç‘ý7 HìŽ-C=¯J܆ËXŒÏ±p|Õê¾Tâ3\$>Ãi°ñÙ×ùSîIG‡±06br¸ö˜œX눱,kÔ·dinn&Çq]—††²Ù,‘H¤ÖEbHÆB|†ã8¤R)¶nÝŠ®ë¸®Ëœ9sˆF£†Qëâ œ¸ñ9†£‚IˆÁ:cw8Ϋ·¢ÚÆBlÖê¾TâSTÛ‰Ÿý?…¨¥±“¢Ð˜ê¡’Íf©¯¯gܸqÄb±^«ÊpÏ™3‡D"A"‘ð3„¶mÓÜÜ̸qãü/j¥©©‰L&Ü9s˜3g™L†D"Áœ9s¨¯¯/ÈžäµýQë)./PPîþضMCCãÆ£¹¹¹`™¾žëo™JÊ[n»Õ—H<@Ó4¶nÝZpR,µí¶mûû@­³¿®aÁÏw ˉêé/>û‹Mõ|©ø¬El×UøLÜVZÞrÛ^.^Jm7à–š¦ù?Õl)Ÿá2”s§z>,ñÙ×1z"Çç@â,ø]|Ì0 IކÐX¿î…Ån¯{+‰¿RÛ>Øójðo‰ÛÚ’ëÞBaŒÏ‘¾/ þ-ñY[c%>Çòuo¹øŽûÒ`lÊ}iíÈõl¡0ž/{=;æëq{ƈ­[·ö=Éd²§§§§'÷=ñx¼§§§§§³³³GÓ´ž–––žÎÎΞh4Úô´¶¶úÏ©e[[[{4MëÙºukOOOOÁz’Éd¯÷1MÓ/Ç@^Û 'ötvvölܸ±GÓ´žÖÖV¿Ì•ìµ½ê½u]ï÷¹þ–©¤¼•lw:î1MÓÿ‰DzmO©mO¥R«ÏH-ÛÚÚê¿G4í1 Ã]ˉ‘Ñ_|ö›===ýÆg-bS­«ñ9˜¸­´¼•l{¹xék»{z¼¸‹D"=étº'‰ìO‰Ïðʹ3ø|X⳿côDÏþ–ë+6•7öèºÞÓÙÙÙcš¦Äfˆœ(×½ê¹rÇ^X¯{+9Ïõµíƒ9¯öôH܆\÷öÞaŒÏ‘¾/í鑸 ƒ±Ÿcùº·\|æ¾´¿Ø”ûÒÚëÙÞû#ŒçËÁ^ÏŽõzÜ1“P‰Çã=Ñh´à1]× Ž`tvvút:î1 £`Ùh4ê/Ì;©6øwq VúÚþ•ê‚«Òc2™ì‰D"½öQÏõ·L%å­d»Õ¤:!ª¿Õ—^_ÛžJ¥z4Mëó3WïF{4M+81ö·œýÅg±ÙÓÓÓo|Ö"6ÕºªŸƒ‰ÛJË[ɶ—‹—¾¶[½N}¦º®|ÞŸá5”sgOOøâ³¿côDÏþ–ë+6Õg­ëzÏÆ{íKQ{'Êu¯z®Ü±ÖëÞJÎs}mû`Ϋ·á ×½…Ÿ#}_*ñc)>Çòuo¹øÌ}i×½r_Zr=[(¬çËÁ^ÏŽõzÜ13ä—mÛ~·>E×uÿw×u ºÕ_ë8¶m3nÜ8ÿºoÏ@¸®[°ýÉd²ßçú[f8éºNKK ¦i’L&‰F£½öw©m/î­iŽãø»á»¸•[NT_ñÙ_l‰Ÿƒ‰ÛáV.^Jmw&“!›Í²qãF’É$[·nŶmR©”ÿ‰ÏpʹŸC‰MµÍc)>Ë-×Wl¦R) ÃÀu]ØÛ¶e2ÅëÞBa¾î­äÇòuo¹øÌ}i_×½ ÷¥µ ׳…Â|¾Ìõl%Ëæz¢1“P©d Ò¾v¾¦i˜¦I×cÇÿ_ƒ°–ú›ɲ,:4 eÃ4Í^AVéNñçW\.Ã0H§ÓÄãñ‚±Ë-'ª¯\|ö÷Åx"Åç@c°› &^ÇA×õ‚X6M³`Y‰Ïpʹ$>GC|–[®¯ØT¯K¥R¤R)Ç!›ÍŒM,jG®{Ë Ãu/ .nwìØ1èóªÄmíÉuoyaˆÏZÜ—J|ÖžÄgya¸îl|–»/íïºWîKGž\Ï–†ó%Tç>Fw=јI¨èºN&“ñw²mÛ™®H$RpP?lâº.õõõ£úâÆ4Í‚ýaYÍÍÍþ—N©çÞóž÷ô¹Ìp1 ÃÏ$ƒ·¯³Ùl¯Œj)ŽãøŸ›ZÎ4MÿyUÎx<Ž®ë~+„rˉêë/>û‹Mõü‰ŸýÅ`1=œ/*®ƒ7‹Ùl¶ lŸá4”s§z^â3ÜñYn¹¾b3™LÒÚÚêÿ7 ƒd29ænRF+¹î-Öë^\Ü.]ºtPçU‰ÛpëÞBaÏ‘¾/•ø ‰ÏBa½îl|–»/íëºä¾´äz¶PXÏ—PûPÝõDk]€áF±m›úúzÿK4‰øÏ†A$¡¡¡]× ²[º®Çijjò—5M³`ù°ÐuD"A:î7›«Ê¯ö‡mÛþÅZ_Ïõ·ÌpÑ4d2ICC¦iúû:V´í±X ]×ý–ñx¼äkÕ{,Z´h@ˉêè/>û‹M8±âs0q[mh¼¨ àçk†Äç(0”s'H|ކøìo¹âŠ›‘H¤¢c¢vN”ë^UÞr±Öë^UþÆíe—]Æ®]»|^•Ø ¹î-ÖøéûR‰Ïpø,ÖëÞÁÆg÷¥ý]÷ª}&÷¥#K®g …õ|©Ê?œ÷¡¥Œ¶z¢q¹ÉcÆ Û¶ýqö‚9×uý.C®ëbš&ãÆ£³³Óã88Žƒ¦i¡½ØQe,Þ¾rûC×õ^Ùü¾žëo™áÞŽJ÷µeY¤R)Z[[±,«êˉê(Ÿ•Ä&œXñ9˜¸C—‘Šk1ü†rî‰ÏJž*9ŠRÆúuo°œ•ÄnØ®{Gú¼*ÂE®{Kï°ÄgñvÈyõÄ"ñYz„康x;ä¾tl“ëÙÒû#,çË‘¾-ñ8æ*}q‡††ZZZ0 ƒT*…mÛ´¶¶Žx9ú›(É4ÍŠ»M ÇzF²ÌC ¨‘XNŒœ°Ä¦*ËPõÑ›#/Ÿá'ñYÛòÉyP DXb÷D¿î•øÅ›ª,£é¼Z‹÷+Eâzì’ø¬mykIâ:œÂ“r=;²÷¡£%ÇÌ_åèºN:öÇcÓu–––/‡û®¿rŽäzÂö^ý•a0ɰf2E^Xb†çXͱ9Òñ"ñ~Ÿµ-oñúä<(*–Ø=ѯ{%þD±°Ä&Œ¾ój-Þ¯¯2H\MŸµ-o-I\‡SXbR®gGö>t´Äã ÓCE!„B!„B!„b°Æ×ºB!„B!„B!„a' !„B!„B!„Bˆ2$¡"„B!„B!„BQ†$T„B!„B!„B!Ê„ŠB!„B!„B!D’PB!„B!„B!„(cb­ 0T?úÑX¼xq­‹!N`¯½ö†apÆgÔº(¡òÌ3ϰeËæÍ›W뢈Ø‹/¾È?øÁZ#t~ò“Ÿ0wîÜZCœÀöïßϬY³X¹re­‹:rm+jM®mK{ùå—±m[®mEMɵmirm+jM®mû&×¶¢Öªqm;ê*ßþö·¹úê«k]Œ>=øàƒ¡.ßöíÛÙ¾}{¨¿ôþ7lØ 7EÚÚÚøùÏ.ÇÖlذ… ²páÂZ¥¤Ñòý!7½}ë[ßâïxG­‹Ñ§ÑrlÉ÷Çàmß¾ ÔŸq­„ýÚ¶Ra?"ìñ^©J?¹¶-Ͷm~øÃމï­í˜ *ýLäÚ¶´°_ÛVj4\Wj¬|ÏTú™Èµmß’É$ýèGk]Œ>…ý\2¾Âï÷ß?ï{ßûX³fͰ­sÔ'T-Z4¬;d¸µ··‡º|mmm´µµ…ºŒa߇k×®•–j%œ{î¹ìÙ³'ÔŸÝh8¶ill¬uQJ-ߢ·ÓN;-ÔŸÛh9¶Â\¾Ñòý!z ûµm¥Â~ DØã½R•~&rm[Ú¼yóX¹rå˜8N´cz4¨ô3‘kÛÒÂ~m[©Ñp \©±ò=Ség"×¶}›:uj¨…°ŸKFÃ÷BØã}Æ Ìž={X×9ê*aw÷Ýw׺ý ó—†ö}(F¯°[a>!Áèøþ£Óh8¶äûCˆþ¥c0ìñ^©±ô™ˆ¡‘c:|ÆÊg"†f4\Wj¬Ócé3©•eË–Õºý û¹d4ƒa÷•+Wrî¹çë:eRz!„B!„B!„Bˆ2$¡"„B!„B!„BQ†$T„£Z XX¸¸8888dÈÔºxB!„B!„bë„i’PBŒZ ~B%EŠ llšh"EªÖEB!„B!„CL ¨úŸfšqpüú!!F‚$T„¡çâú'Ç ê©çÇXü‹4illê©ÇÊýK M·Ö› úàVà?¹Ÿ‰¢ÿ™ÀóŠ[^!„B!„c“ƒã×õXE5ê9»ÖÅu‚‹Öeå^Ÿ ¬‡ÜãË­G'2Þš{\-­õB!„B!İppÈ’-ÙXÖÆÛC¹¹ÿÁª,•…0z¿ˆ 7û&H< ƹZ&€Ö‰7Àè„i`œt@BU"ÚЦCæÐŽAä÷`_Æ.°N…W_†.…ìaÐ÷ƒ;lÍ«sb?dv€±2&´N†æCÙÖD¸ýi‡÷c‘„Š"”²d±±qqÑÑqÛHI^ÇÅ&ÅeDDˆGGÇÈýÐÿÀëÝÒâ}å ¼Eq‹|’$˜8iÁ; «“¯ž{N#ŸLÑr¯s€ùDJ’’çù^ÜÜriò'vEýÌ­3›{/Õ©×6æþNá],HbE!„B!„½‚óä~¯”jöNQõ…e¢WSÝÏýžÅ«ÃÐJ¬ÌùèW粯÷50/óž·~ö¹ O‡ˆª´É€³ô@ì,°š3°qhâÏ ëq€Ø60_„ôAûª÷|S®œÎ~`:°šMˆ< Úfo=ú Ȭ÷ Dî‡ìU`v‚= œ/€s5X€>œóÁý:4}Üã Ö˜óÇiþÎxÜs@;þzî€æ/‚³´•pü%8ö*Lz8³!þ<úMHE@öl07ÂοÔW ²ܹàž¾šï}è!s9œ}4è‚È/ sÌ¿nøú¥|gËSÃz\HBEJ ÌEg;÷³•·“à{¤ø qb@=ðcLl E :Þ #Jï$’ ÂY˜œŽ4ÑTëͪÕ»C%@œÜß*ñ¡^§RJêDkàèU×Ê8… Õ3DÃKZ” ünäþVÃx¥+Ü /aRŽ(ŸN¾÷ŠžÛ6ï&¸W_]Á…B!„B6Í4cæšX'¢ïncû k‡BÕ§! ¼äH°Î£ ¯ž#X“!ß0U5,åuˆÎõžOý+°¬·@kÜÓA{Ü™ý hK shÝ`ìX¤Ú?ÀMOÂm“àÜŸy½?œÏ€ó¤~ ö¼\}ŽL‡¦CÀ°=&ýĺÁíñ’2©©°ð·`7€{h“!ûàqMÇÔ5ãp§€yžý ÈüèãÁžÆÉðJë‹dÍÅDfÁIScL™Âýpã°æõ×Y9w.?øåüø‰Ó¸˜ÔïÙßϞͧυCûÀ\Z'Äç@ô®WxjÜþùŽ©^½Ô…Ð`¶ ·÷0¯ë+0Á€+r•[.ÐôÜïÀµ¹Ö½öbøÿþZ?Úƒ ­€·ÛðõM°Ôú§Ÿ6aXKI¨!B'A‚¾N–ã褀«ÑyT.5ÐB Þ‰-…—`Q"x'À86I O~£32Øs$øœJ–˜ä{r{‹[N4í§J:Ð:À2Gð>—j°¦á%OŒ¢Ç¢¹ýôÜk¯U¹B!„B!„.2DscNØØ˜˜¸¸þï€ÿ·†6,óæ:ä{y¨‘1RäGã0ðê²x=1bãsõ-GÁè%@Rè½™ƒ`/Íû H}f¿o< ‰NpÎëR8ö(LÞ3?âõÒˆì‚÷ÀÏ®„•Ó!ö^BãÅ&¸7 ê¹÷œZs)kÚQˆ<öá\Bg ˜Cr1üæqxd×a´)S0÷BdÜñß°µ Î{0ÝÛÞK–9×ÌçÖ)s°m›D}=éšÍéüŦïqíû¯GŸgì:ÈrÍEO¤Ð4x<ν¯ãßh¡û¥'1“Iþe7¶žIë4¨_nð™ÖV¾øÔ©üÎQH¤ˆD£0Gç§-­ôô¬À¼ã<ÿs°mo_§²Í´´xÍ?÷¹'X³æB¿bOÜnXþcð‡ ¯c0ríj§þfN„Ž¿‰íßÝ>¬Ç¨$T„¡óu²ÜÍVŽcónt²Àý, ¤E"ßUeqk‚ ù!¬ÂšPQi©ñ+ur=+«ZîyÕ´xÍRô2WS+ÕŸ4Þ$ßÓ¦XXýûßà !„B!„b°\\²dý„ xI5¬WpÈ/ ÍŸW·U·¢üdûv¾·};ÿ½r%Ð@¾Þ%–{MoNû8ÔOòêS4 úŸº’ÛÁqÀØæW u3Äﺡþq˜õ $Îóz $‚'Áï€ìÏÀ=­{áþýкVÏ2z —“-øº‘/ÏNtÀÔAË•%õ‹qœlÁF84ÎÓáÃ@t…·ìóëÖ±ç™Uħ@ö#͘--0 pÆS¿ã–³ÏàÃgvñ“Ìv´9{°S)Z£QŽí;‹#÷âdzîæÒåˉe2ìÞ}‹2‰F°,‹nø4ãÇßB×Ãû1ÿÌ ‘HÐÚÚÃÑ£—‘ÍfÙ¸q#‰D‚§žú {ö<†ã8455ÑÚÚÊ»Þõ.–.ˆeYd2*Õž={°, Ã0øýïóÿþߣ˜æYÄb1 Ã`ÿþ¿á³Ÿ½‡Å‹Ÿ'™LòË_>ÁI'ÍÃqÀ¶³Ø¶×OèàÁƒÌ|}&Û‘„Šb {—ãèd€wb°o˜)ƒkËtá,Ÿ2J~Ø©Z Nü <WSM¸nOš d{ÃF2x‰“¡wîB!„B!D-•šE%QTv÷¨â€IDATOÅÀ@« ÖÁƺ«Õ_|¥£ƒg§O÷ç~uç0pœiÞëÒ?ƒ£Oåo>3 ó(¸»aã@ôÃUÍšð±¾Álþ+øGï â?ƒÿ^ Ç[ac´·€ñ:|N‡+ÆCò¤\Ù¸p ¢Ñ( ³nÝ:Þô¦7¡Çß xu[Ç€Ÿ¹ù!Õ]Û&£iØõshÍ´à8¦™dßîãýÿîås¯ü”{ãÇŸgÖ¬ŸáغNSSo{ÛOèÙz³Ÿ~šÌãi?øÁR¦M[ÄOüŠÆÆF2™ [¶ü S§¾ÂOüš¯}íkÌœ9“C‡¦ñ›ß²$“IÞÿþ¯³gÏn¼ñF ÃÅq,+Οþé£47ÇØºu#Ñh”Ë.û“&ý--ãhhh`ùòG¸õÖÃ<ö˜×ÓŲ,xàüïÿfùîw?‰eYضMOOœÅ‹ÓÐÐÀÆ¹ë®Ø»w";w.çï8N6›åsŸû%;w~ƒï~÷a.»LC×u¾üåu¼øâ*ÖO|ŠEÃ|œŽ¯ÆÁ/„ƒ#Ƈˆq­À‡ ¦˜¿,ÞIÚÊýlÊý¬üÊkkî¯{¥–̪LTJ ûöä’B!„B!ú–% ôNª88èèt™ÎÁÀc@É£LÑßjŽÙ¿ýÞ÷øø¿þ+õÀS§žJç›ßLoh¯ä}`> zg®Ž¦¢$yësûIŸ ?â­,}V'ÍïáÓ|šç?Ï}sïã;{þ 'êxQH¾ ;^ýŽóæ¹ÿþûyá~å )fÛÔ××s÷Ý¿æ?ØL*•"‘HÉdx饽¼ðÂ/p‡X,† l³áÝ?{¿xË[Ð\—}ûöáº:_úÒÏ8vì;wîäÎ;狼k<ßúÖ:Ö¯_ÏÇ?þqî¹g=û÷¿Ì§>õO˜¦I4åÑGbϞDZm›IO=©ûöMbûöí|ç;ßᤓNbÙé§sèÐÛ7®––üq,Ëk®¼wï^’É$š¦qã7ðË_nò¬\böì©çñÇ_@×u Ãàž{ÖðÎwŽ'· 6nÜÈüùS˜7o/™LÃ00M“ñãÏäœsîÇ4M"‘®ë¢ëð?ÿó­­­hšÆÃ?ÌÙgïçÔS/Á4M\×åßø_üâ™0a.¦iò®wm#ÛÃÑS꘸wxû”H!D(ü›‡°èÀáC¹™="Ã4P—3ôUô¹Þ ^"EüÏâUð§s¯‰’í*E)B!„B!„8eÈ``”œÅÄäûî^šûK˜N¼„JœxA&þ€aMä`þð¼óØoœ±ã/ë:—<ØÁÉM'}âè½.|øKÞ=4pÚLþéÚèF=hÐñÁ>m¾ÄK¾ÅÍóvî²îâ¿îý/à:ÇA×½Û†S5¯çIÌuI§Ó<ûì×Ù½ûH$d³YLÓäûßM³¹þúë9pàŽãpùåcӦߠisçÎ%‹aÛiÚÛȱcàòË/§££ƒ… Àþç#ÜsÏw¸é¦›¸÷Þ$õõË9ÿüwqË-_àÆoäÒK¿ÍÏ~O>ù/ƾÿýïS_ßÄ_ýÕ‡¸ôÒ$]sç2nÎVΘ3e>?¸á&.;rÚÛyå²é$?»ãÞ¯yê)n¸a'ë×בJ¥Èf³ÌžýçLšt5™ÌÏ9v웸®ËÝwŸÅ3Ïè<ÿü<.ºÈÛ÷ÿú¯s¸öÚljDsÍ5¿á¶ÛÎã‰'ž`æÌ>ðÛq]0 ƒI“¼aÔÀûÛ0¼„Ù£Çu½}ûïÿþ)šš@×u’É(™ ˜&lÜø-¶ldž °uëgÐux|á+,—„Šb¬qqi¦™I¤™B‚?Æ>)jÒúá zsºä“(Q¼DH_=$‚É“ÑÒÓF!„B!„¢VœÜ?ÅÚk3œGvLAgr®–%I’&šøew7Ìœé/©†€¿ð¾-ú/Ýì<­‹çº^ÂÜTG¼ˆÃù8ÿI<øÜ7øÀÖðÓ÷ü”ÿÛ4ƒ¶Óô¥zÈÂ?ÿèŸ9팿góæ4ýozJ'EŠ ^ä·¿mÇ4Mb±]]cÛ7âºY4M£©©‰Í›2iÒ©l~à¾óoÿÆÑ“Oæ½ï=/|á£|ï{sH&“˜¦I6û¸îU,X°€eË–±gÏÆ‘Y³~ÏÎGÈd28ŽC*u çœsŒGù'4Í¿ãŽ;®ä3Ÿ¹’‹.‚¦¦&à"ž~º_ýêWÌ›§á8&¼“nXHg'|דּøÔÿþ/ûš4¾“Ö¸ŒË ¹âqøéAš¯ŸFòŒ³‰Ì™ƒsî{hüè÷¹ç‡Óùñ]uüþÆVÿì .þË hX8™÷j øªã°hÑxvîÜÉ/~ñ."‘Ù8ŽÃ† ¼üò#ìßÿ·´·Oå/þb-Û·’cÇ~ÉßÿýõìÞ}œ3Ï좾~N¡±ñ[|ík—ñÌ3‡øÚ×þ‹¥Kÿ‚¿ù›_3kÖn^ýB¦Oÿ!×_?›ÿøëI&gâ8^BÅqÆá8É€ëÂg?»ï¿z og;+†ñø”„Š¢¦$ÐÑ9“—c²ŒÞ?¢S§÷Í&?÷‰ 4ã%OLúO¢!„B!„BˆQI” \\ttÿ±#GްwÒ$bÀIÀå$1ËÚÀ/·mƒóÎ#æºÂûÆ¿ç?Ïé½›}ûþ:8«Éââ‹Ó|â)¿7Šëº€Fkk'Ï>û¶lÙÂsϽ ÜÈÅ_Ì'>ð.úÌg¸bâu,žÝÃ_~™Û?ö1:oº‰¶¶ëyá…q´¶¶âº.š¦¡ëIÞxã9b±[ùìg?‹mÛ¼ãu\rÉ?B6‹ã8œqÆet¾ò ûžz íòË™?ÿÌÀI&“$ð…/,ãõ×ïá˜K,ÖÄâÅ‹ùÙϼaÇX¸Oé:f, ̤ 7b9:š Ú!ˆmþë2œû÷ã8ð¾?Aô·ͪ¯Åˆ|é"ŒKO¢©ñ|¾üÆ̆=,Z´ƒtz6ú±uÌùÕ?2er;øÃå8Ot“Xs1ö³&L˜€®]€—Ÿí¿»€ööo2eÊ5ÌŸ¿‚÷½o'S¦Lá½ï½™Ÿüä{¼ûÝ—ðÈ#ïb×®éÜrËåìÚõC¦Lù ‰„·Ý†Ó§?È×#G¦3~üç¹÷Þ+9x°‹3~8¬Ç©$T„5•!C„;ÑrIŠáO¦¸x­ƒ×£EuÕðz–˜T>Y¼B!„B!„•<É’EGÇÀ@G'B„Ô¬nLüð&iwð†ôR“ͧ€ÿ]²„Ó_8ÄïN:Âþñãù«§Wðáø.f;ƒU¿Šé¸?ƒ/Ÿò{Þ±­Yãÿ^ØÀ4MG“$É5×ìgÇŽâ8ÍÍÍ$“I2X±"ßßÁ¶mN:é|žiû+Þz6SÏ;ë#WÐôi›O|à4|üãLŸ>oï_ÿ'¾éz>þàƒl?|˜ß·í$vúã8§²¹­oÞx#GÎÛÉøñã™0a8n&Ãg?ÁúáyÐÜLrëVœŽI¼LŠEã]ê킺:Œ?üƶÇq'ßN*5x\•2™¹twC}}{ö졵u6®ëbŽºÙ¬×9%ѱmH&½^©Ô8l ´÷ž{<»÷…Ä>}­­üÚtœÇb=<ûHW¿«›Ãö´}ïŸ8eâ­üõÊÇÑ´K0½NzëŸãΨ`Ëu×Ñ=w.-QøŸ?Éñ7þ„Ûßû¸É4™ 莅ýð“øÞ¹8[\²+§ãî8ÄûÚ‹±DcËÞò¹g_£93™Dâq6ýäKÜú™ÏТ·ñé]ÓøêÝ[Y»v-3fÌÖã´& •ŽŽ:::hll,ù\]]uuuµ(ž'¬þb3øüpŧÍA¼¤ÊZ«ÖãÃ-ó\ o.õþ°1÷»E¾‹¨µ4Òñ)„¨œ\Û Nrî"¼$>…¯‘¾¶usÿ¬\틉‰…E:::66š£ã2þǹp¼Åãh¸xa°y3ön`î—ƒšÆM÷äß?uwýîEÞñÕÅèÎ ˆÂ¹¹èÁŽÀ±[®àönþèÍ<~Çã|üã{ˆDzü²Ù¶COÏi444N§‰D"$P_¿‡úzƒ­É$Ëâ7ÞFfùµ¼kóý<~Ûm<ò¹_²eâu¬ÿ»4[þäO˜wÕU|ñëG84ùln>xO®]ËK/½ÄŽqã8¾wÑH7›eú±cìÿé4Î8£Žë7o†T M`Y&ÆÑû½l†¦án›×_Ï„m¿çy W3I}|Æ¥×2Dû[Ü»Ðâ÷£ëðéOþ5ÌßNÓ:H§ž}ö¼Ü\$Þ(_–•ñ+“ñÞÎ0ðç(Q=`¢iƒ(P_Ÿû; 0ÛŸÛä†.ã¶Ûž$qÕ˜: ó#^ït}Ïã$>¾ûáý´~v¡¿¯c÷Ÿ…Û±~ó.ñ¸Fýü·Òzý ñ¯èñ8ñ(à„T7d2|ûÌ3‰þÍd²÷ÃŒoðå­[Yxà `|5ú0 ÓÜÌÅF<¡²víZÖ­[ÇòåËéèè`æÌ™|÷»ßeæÌ™¬[·Žµkײ|ùr6mÚÄš5kXµjÕHQˆR± T%>-,farˆ,««8€V©>/ òI”(Þdf.2Œ—§Zħ¢2rm+D8ɹSˆð’ø"¼jqmkcûÉ” í¹Ÿ­´òŸ;aæÌ™LzýuVœ ¹šxîµ×˜|Ú,&ñ´Ëy/çÍO䯇{•<HLƒd”ü¸î‰Ï?Çç¸òÊÙØ6hŠ¡3æíeËK§óÙÏÆ‰ä&HwøÔ ›½ Ó èYÁ¡CA›¹ˆ= Ì]»–ï5~’£Ot1qÉ\fýYG€·¿ýØö8^ÎÂK/e¹¦ñÕûÁ>øЦ¡E£ ë4ž·“‡žÏGþüiíZ‰LcÀËpã$5póg’úÍuñŽÅ0 uÊvš?}ÎÅ«ˆÝv)ñúÿ"©gˆÙQ&ôôðo»VsëißâØÇ«G¿ˆ¦y •`Â$¸LÓK¨$‰xI¥¥ÅK¸(®‹ßã ¹þÂ’Ÿ¹qålì­³ Ó/Ï%è>œÎ?vÞt2ãb$·Æò/Ô4¯É$75‘Ê•yÉ’n¾výõ$ãñ ¨‚M¨tttp×]wqß}÷±lÙ2ÀëFµnÝ:nºé&Ö®]ËwÞIcc#ííí\wÝu466Jk!ª¬\lU‰Ï,Y&Ódù—*OÙ6ä~ªÄÉÖÜï*ár"%S¤×ÍèQ«øB”'×¶B„“œ;…/‰O!Â+L×¶SÑx‹;b͇O\|1'?ú(Óº»Yr*ü–üPí?:wÉ®øítZÞ?tXsä x¯ƒBì&¼ÊŸÜø`š §œr&ÿôOù쀟p]¿B~þæ6šÎ}…w¾ó#tîsÌüØÇ“3ÛÛ9ÿ‚ù<øéO³ðŸ¡nn7÷.™‹ÆB>ÿùÏs쫳ò­/óÚ›g‰Dhhh ¡¡ ]?È¡CÓr“È{yDbsæÀÆtÃÀÎÌ'‘ýgÛþ4®å½®)û>´•9©”WvËò’†¹óhúóY¸faþøoÀuIGáÙg÷Óøð#Äo€ûŸx/ùÀ+L˜pFÁú‚ ð&é´×E×{?Wüw%¹Œà\/å^gôS]hÛÞQÐÚ –eyûµÊÉ€ñU‡€ŽŽý ¸êª«èêꢭ­Y³fù]É–-[ƲeËhkkÉ" qBê/6ªÄ§†ÆYè¤Iz=•ÐðΛ+ñÎ¥Q x¼§ª¥¢µˆO!DeäÚVˆp’s§á%ñ)DxÕêÚÖÎý šŸktûƒ×_gí}÷±òdÞÜã ÅÕ‰Å%‡sþÑ£`Û<µô,&õŒÃx0à{6üUÛD¯ÂÇð ¥>¼Ðëe’ãºÞ|#44x `ÿø‹™2e ÿç8¾nÇaâøy÷îu,¼öZöŸvß«ßÿ|e?š¦sëW¿Êì7¿™¯}­SN9“?ÿóϰqãFfÏžÍÇ>vŒ«®šç¿g"á% L3—ÐuÿwMçðB²Y¯‡H<î%;œ@%ÕÖ­ù„ƒmz†$½Þ$Ñ(ø]P€ ðâ‹/ò«_-Åuu¢Q5dWÿL³wB¥”ÎÎò¯Ñ4¯|åÄãý'_Ôç§^cÕm¬­ŒhB¥±±‘»ï¾Ûÿ»»»›õë×SWWG{{{¯Œæ¬Y³ü1ûú²mÛ6V¯^=’›!„oõêÕ<øàƒµ.Æõ›À ãóÁdíÚµ%Ÿ³±1r'È(|sA ùÉäÍÜÿJóÕ›Ô^„C{{;«W¯f×®]µ.ÊU#>wíÚÅêÕ«Y·n]­7Oœ€ÔP¯¿þz­‹2drm+ƹ¶üµ­Õ¤®m·mÛVë¢ ™\ÛŠ±F®m+»¶mooïó5n®ÖEÕʼns4×üõØòOñëÜ{,Z´ˆ£G°û­¼l¿Ì¤}û8>{ç:㈷xëÓëð&Æ5é³í×¾¶×-l>kÿ²ç‰n~ä#Éðëÿ˜WÑ8tå—9õÔSñÅèºÎÿÏ$¾÷á[1M˲XúÎàë_ŸÎ·¾õ<®ëmK<ž¦»{nÁúužxb.?üáûÈu¬ð“#šæõ4QZZ¼d‚®{½C 7¬—±˜÷_Q9„H$ŸðP ‹L¦p»gÏž dxæ™ÿD×5>ñ‰Â2ö§ÒÞ'a²víÚª\ÛŽhB%hýúõ~×°U«Vù­‚*é2¶hÑ¢‚`b$Ý}÷Ý\}õÕµ.ư*ŽM`ÐñyõÕW³fÍš’Ï98Lƨ¨‡Èpq‘Q¹m{ÀK†ßÈäíkcÙ²eÜ}÷ÝœvÚiµ.ʰ®ø<í´Ó¸ûî»e,jQ«V­bÍš5Ì[ùÅûh ×¶b,kÛþõwm+D5©kÛE‹Õº(ÃJ®mÅX ×¶ýS×¶Á^/¥88h¹¦¯35Ën¾/0é©Iyéãöã~u13ºñZĶ‚£rþÐ$¥†¯*®kûë_â‡ÝŽÃ®ää“OfÅ¡Cœ4å8‡N?®ÇçËëÖ±bÅ"&N<“x<Ž®ë4>>‡½{`Û'‰Dp]˜0,ër2™|ö½ÿɤ÷3›õ’†áõ01Í|¹ÔcºÞ»¬Áž'ºî­oÜ8o;û«fÑ´Þë²mxýõ™Ãs°„„ã8躎ëº#6ä׈'Tn¸á–/_Þ«åݲeËzuÏìêê’IÇ„!}Å& |~™/â°8e·Á¶mÇ!ÒÏ@Œê‹¶X6›õ—Ëd2èºN&“¡%âJoÇqÐ4ÍŸxl0Ë«rªE4p• žW“pÙ¶®ë†á¿¯ëº<ÑÝÍü¥Kᤓü}–J¥HæfÓuÛ¶ý$ˆã8¸®‹®ëhšF<×Âqœ‚ç²Ù,™L†H$â¿_<'•JaÛ6®ë’Éõ5ÕuÇq0M×u‰D"ضí/ï8Ž¿¶m“L&ýíp]˲üíu‡ÖÖVýÁå#‘»wᆲ†F2>…#×¶B„“œ;…/‰O!«–×¶Z Ùçæ;aÆAê;žeëÙ¹TK3œvõi<ùä“ü¥ñ—üÛ‚­[ 1°8-E׋zŠd2<×ýž9z>ا}ò“dL“Î+þŽoýß)|⪗¸éË_&ÒØxÕ«wÑÔaëÖ­Üzë5|ò“^ï’DÂKnd³ù^'ÁyL ÃÆKÍÍ¢iùˆey«²ªª"5§JP©¤I%s™@~¸°Á,;†QPÏ7Ø:·фʺuëèîîæª«®*˜´¨®®ŽÆÆF’£ÆÆFÚÛÛéèèàÝï~÷HQˆR±Yøü6 ÀäEL†«Sv,Ãu]4M+™PI¥R÷^‰D0MÓO¨¤B<÷“2j]–eqðmoƒiÓ8tè™ïßÿ¢N¥R~¯ •h/©ø‰L&ƒëºÄãq¢Ñ¨ŸŒP õšt:íÿí8NA"B½§aþóêq×uýƒÊÆ«dD"‘ðš¦ñÊßþ-³gÏfñâÅìÛ·Xs3‘H„¦¦&ÿ5*cÛ6¦iúÛaY–ŸQ¯S‰"Ó4immõ_gYñxÜOü˜¦‰»R°, Ã0ü¤Ú‘H˲ˆF£ûɲ,R©”ÿžº®ûåjnnö? ÇqH$~Ë‘ææfÎ8ãŒa—‘6Òñ)„¨œ\Û Nrî"¼$>…¯0\Ûne+»gÍâp÷>N9rŽs×›3iá• ™´uØ{Ò+£ ¦ç-H¨8®«ç‡¶J$À²xtÏßã’Ÿ}åg?Ë?üù,Ž9‡ht®_ã8i>þñǸ:lÛK’d³ùIâ #ŸL‰Ç½‰J¤¨×«ªZZ¼¤JpÞ”­[½^*•äJ çUJqo0Ù5Tjþš‘0¢ •ŽŽ:::zM´yÓM7±fÍÖ¬YÃÍ7ßÌòåËÙ´ikÖ¬aæÌ±Õ Iˆ0*›@âÓÆaxæñö¨ö>Q•û~÷‹ÅˆF£þ2†aL&ýÊxÓ4ýÞÍÍÍÌÚ°Î<“Ç{Œïçà•©*úÕc–eù‰µn¯ ¨K*•"‹ù UéŸL&‰F£Ø¶M$¡¹¹ÙOhšÆÖ­ÞEpÛT"(˜d(Õµ1]Ôá­¿þ5;wîä3·Ýæ'y‚‰¨R=xÔ6¨”ÞG“Ã0ˆF£455ùI!Õ“F•Oý &¡”`¯õÑRýu‹^£7ÁEñx|LLì\›øBTB®m…'9w ^ŸB„W®mutlà¤Í›9”|šOÞ¼”ïró¢Le*óöÏÃxëWpöåœä†Ë*¨®ˆÅp›RË—S¼,H4ÊY›/çѽº„÷ßÏßéK,\øº»÷^‹j¸ú½ïÃÌ™?Á0 \×{tÚË͇ìÚºÕ{,•ò’%ÐÚê½&“ñž Vƒ¨ùP‚¢Q/ùRNkëàö¯¦Ý¤Ê˜M¨¨àë˪U«hll¤££Ão „¨¾r± ß^ï©@šÊçñ°,«`Õ+CõtPÃB577û½(‚É‹ÖÖVÞqì~å¼ê©¢ëº?Ü•išI‰H$B6›eÛ$oÒ³gŸ}+7¼”*K:ößÓqâñxAb"¸>Ué|L½·êÕ¡†êj-svT=:jÖîݰh‡bÅŠDo¼(Ü(6!ËT·K5$Xµ¨ò¨ca,ÉøB Œ\Û Nrî"¼$>…¯Z]Û¾øÝb¹ßM×dþÁ©´´ÿ0áÝãßÍÓGŸF;GƒðýÂu9N¾gˆa¶¶ð²?8“/?ÝÈÔO~’“®¿žŸû®»î²Ù'p‡t:ÍUWýK–|]Ÿë×YÄbç‰L)xŸ¦&/9ÒÔä½§ª®ŠÇ½÷VCzAÿClW±d³¹m¯â´¹j¨1Cj2˜:²Áñ9TÊ‘“¥á5\ñ9ƒÓѨôüà8±XÌï©^kl6Kkk+Ùl–7ú½5‰à%;ÔÐ^+YéŸÕ°QAÅòº®³qãFÆûöícöìÙ%+íU2¢\…~ºÔà•Eª=‰ÖìÎN:xI­±d¤ÆÊ +9 N›B„—ħá%ñ)D8U#6·`35×ÜÖÎýŸ´w/étÚ«ÏÉ.d²pàÊù0óiX¤€l®—H iáºà>³ÜvˆFqç¼ mÆl?p€¯oÞLZÓxÏ{¦òÃÖñßÿ½ÒŸ«µ£ãßxî9o~”–ËòÖÝÒ‰„îÓ^5GŠaä“&jž”âjxÜë¥RN©IéEß"‘™L†h4zb'T„cßltN®ðµjh+'pF‰Åbþ°Zjò)U™®†¿RsqôÅ@ºÿ¤Í›yîàAfÏž]òùáH€¨9OªÙ›`ÆŒlÛµ €å3fTõ½ÔdÕ6’Ý:…B!„B1|ºùD11Ù±c,XÀœqãòõ# Aöq8eÒ8;¿¬aöò0 ¸ð ðÀSpüçÐÒ‚•€ô¿ï`꾿Ř0×uÙ´i>“&JCC---˜¦É¹ç¤©i¶í%JÔ]™Œ—HQÉÓôþ«¡¿‚ó (ÅÕóºô#©lÈ/á1 £¢ÆËÃm|­7\qb±°˜‰Á-´TôúL&ãM(þ–eù½Q2™LAr$‰Ç z³ UOg'OMšÄÔ©ÕëÓ¡.ÇP²g –,YRò÷jlš|¾š4Më•pB!„B!ÄèðFà÷;v0-÷Óç‚ù'0õšƒØÓlT+]ÛÎõè8xÐûûwðÄ+áᇠÆÚŠ}a*×|õiÇÁqººÎä‚ îáÔSÿ MóéΙ3ð4‰Da/ÓôËdò«Õõüœ'ÅU7þm•Í]¢iý&ÂA*Bˆ÷F¿“Ñ777û¿;ŽC$!ú“ºG"Z[[1 £×8‰Á!¾†Ë´iÓØÚÙI}îäZ-jΑ±@%TªÝã¦ÚëB!„B!DuI“ÇÞxƒé>È;v/ ÈQ@k3Ú? w’ ×xËYVnx¯Í›½¶laîøÑÞy1YÃÀÎu Ù±ãn¹å ÃÀ²,.»l:W]u=6Û††oqÃð’'ÁÉÛ“IoØ/ðz¬WÛD£½çB)õ÷ŽH%ªL*Bˆšèo ¨l6K&“¡¡¡]×iiiAÓ4²Ù,®ëú MÓˆF£U¯TŸ4iÏ>û,ç=ZÝ}¢i#6¹ºšG¥ÚF*á!‰!„,,l*!'C‡êöT´±«þB!„'šf¼µ6ÞÈ^¯<È­óçóßâ%Tx³ÔëÀAXÁ oÁÜ],ð{¨Ì}þç\rƃh·~Òoèùâ‹/2gÎî¸ãLÓ$›ÍrÊ)]üô§ítv®ð’2®—ðÐ4/A’Lz¿«Äв+ïÝÓ$™¬¬÷I?£Ò‹QF*Bˆec3¾+¿Uël6[\PÉÕ3¼Éà“ÉdÕË‘¢0³Ä2vnx­9s@×Ù|Á"Ü­§ó_ÿµ‡d2‰ã8|éKûX´h‹/&“t:MSÌž=›dÒ›E×{σìQ"Cv‰ I¨!FT;}ƒÇÁ²,¾”`rA×õª'ú3ƒ|´¨A9Ljt:]õ÷0 ƒL&#C~…Œ…åW,öÅÅ%C†(Q44,¼ÄX°¢Q-¯*Uëó(Ñ‚™˜JUø !*çäþ™˜~Å~0¦TE¾J”dÉ’&…E D‰’Äë1š!C„ˆŸ$i¢É_×F6úCzʼn!â'2ZiõãúÿgïÝãä&ï{ÿ7ƒ¯2ã8-æf“ ZHºI m4 &ôÐhœ4WŸMÛ“’ÖíÌé9¡-ée&q›ÒsÚfEZ·iz¯R~M{HVmJ.[JV„4d;Æ`s±ì5`þýñè+ifgwg/³;»~ÞûÚ×Îj¤G4óH¾Ÿï%$¤H1clìT$ˆ‰11)R¬ÛFéG7Ý”)§A… ÝtÓO*ø(àâ2À@Ýââ¦#¢´M—z¨PI÷)}‚ä'&ÆÇ§J5“Dˆ)QJ…"éw@À0ÃIRÔ LLBBÊ”Ó6‚ô\ØØT©R ö¡B%u€Tœ‘ÿûèÃÂJ—ùø©(óÎ_л·w®¿–F£Ñh827Ù—>ï6`~% ˜d*(Aô`}ù1ØïaœöŒÛ?KøÙÇÀuyxøoûý¼÷½gS«Õ¨V«ŒŒÄ,Yò >ÿùÅ£DÀáa•òKûjjZE *fV9“|¨J¥B¹\Æ0 <ÏÃ÷}úúúFE£ÌfÄC#L"YÇü`ß¾}mßÇl¤û’¥ÙˆTÒ´N‰RjØâˆ,!!6vêݽšÕXÉ‘Š,%Ji{N"Ãæ ¾â­-ÆÔ¼AS£ÑŒFD ‰dðð¨RM ê665j˜˜ 3œŠ' „9 (SN#-œ:ñ%áЗü)R¦Œ“üéØo¤š%µs3y-‚C?õN}ôÕ­?À@]¿ªÉ3²N@öÇÅM#YÆB":òâGãû.n*¶ˆ`,"ŽƒCL\'N)ÒG_]{"â¬f5.nÚÇ5\Ü4RE~HE•a†ë¢T"¢t›<VzÍ•¾U¨àÞëºYþ‚j4F£9éAåe”vræóÏóÐYgaþ*2%@ +Iý’0„­\U0þýEDO»x}'ˆ?«æ^ßøÆ÷ùÑV³}û¢Ô&12r\ð{€eV¯VÊ@Ã#ä,”³Õ,´ ¢9iiž ¨{¤ÉŒèòø3~1uÍø„„€º•0 ÃÛ¶ á¡¡9Oša’Þ¿䬷¼e®»¡Y@ˆ±UŒƒ"œäkH 1XöÓ‰9Êpy §`bÖyš7"mˆP3ÙÖÍÉ‚ù””["BÔ¨1Ä ØØ 34¦Ó©‘ )bK°€ádyÞ¾ ÑhÚC¸åK_âç6lólµÐB ÀÄÏβ`£»— ŠžT« ,zó5%jü"~Š<ÆÒ¥WàûðÒK¯#ŽÕ&a¶­ Ñk3‚fªhAESG^è×fò+ùÈŽ¼Op~’á.PLÖiœ|äMåv²//ùë0þdÅHÞ÷Q+iÃ¥µè™, µ°.I¿ä˜«ÔGW€µ_ÌúÅ‹§{êO î&âü&Ëã8¦R©t|Ú¦Îî]ëÜpà ì:ûì¹îÆŒ`YÕj×ÕEtÛM>M¨¨©0ÔäŠ*^×ÚX«Ñ´‰Ô’bì..>>Ѹx]{èäÆÂ¢F­¥(#F£YhD(‡IqÌt€>FÛ"$“…?©Ö5M+ˆcÇ}€ǼðƒðÏž !„Wá*D°â€Áÿ»þ—ú?4 =P.“Š.G~ÞÞÅ|ãÏñôÓñ}U¥¿_ÕK‰"%Ì„:ÉfhAe"Þ­!ˆ8RjXÞèqaÕÉDŒü/Ô‹ò7 ^|9ÐbŸ×\2±c˜ÖÝ“õë³’}ÄÉ>óDÀî×¼†÷íß?ÉVONî!â9¯Î 0MÏó‚Ç™ì·`v°þÎwÎ?ÿ|ö²0ÂÕ ÃÐbÊ,Q¤ˆADD}Ô¨áàŒi¬+]—F£™¤h¹ˆ'’Š+"ÂÀHǬF3ú{¢ÑhN&BH+õ•™¼B£ÑÌ,ÿqüjµQ”Y*ý'ÁŽê•¢g³ù]w©‚€8±jìÛ·¥û—¸ûî»ùÙŸ} »vàë_¿,-4oJH±¬,RE£™*“TÙ³g›7o`çÎlÛ¦BÂ7nÜÈÖ­[çúx,"xĨ ¹žødâGÔ°®"y#°äý Qâm» ªí6@Ñþº&ù´_Þ*&ðÝU«X¾wo›tá°¶áIñå8NÇ *pb®;¡ÑÌ!R\YjžˆüX9ÿ§K>F£iN˜üuukC¹fBôwD£Ñœ,„([JˆŠDÑ3M¦s8qâQ©¬%!ÊwáyfÕ¦\†ƒsîás‰Ïˆ)R(\ÊààýD‘A_ŸJû%T¿¿8F£™2- *·Ür ;vìছn`Ïž=|øÃfÓ¦Mlܸ‘»îº‹={öpÛm·Íõ1Íkd~KãQœ×L„¡¿'fÁ#v™¡¹îˆF£…‹›ÌEŽÇ1^úáÌ ü’ÜŠa¾O__•8¦.=ôC=Ä|)‡NíæšM÷ðÕ¯^ʲe‹R§]Ó]vU3Ó´œò«Q$Lk©"®,"Tê-PµGlà×»K¥:AE òW¯æËkÖðü¥—rü‰'Xñ裸†Áç>ýiN=tˆ3x€Ø0ˆ, /RÂu]¢$‰ßý##D¿ÿûTÀuÝTñ<8ŽÓ¨ß÷ë„ |ß' ÃT<0 #" ÃÇq¨T*A ò×qœô¢#Ç%‚„eY”ËåQ†oé“ìïS÷ÝÇß=õK–,a`` -Ÿã8ôôô`š&Õjµi„C+Q†aP­Ž]<Ù÷ýT°Ê ÂîÝ»Ûr| ‘#dÆâ8®ÁZŠP‰QƒÒÎý¯“B;fhZ%$¤L™ †:ü4HÝfßÏDŽF$Ow7 gÿ‡!”JjY¥Ž£ÚŠ"èï‡ZMMìk5µ~µš­¯ÑŒ‡‰‰Ó‚­6–k&¢¾¹î†F£Ñ´U€^»i4GH˜¦”>ï^voøÞà ê ÝÝêaÊó¨™U ©…pÖYÇØ½ûxá¬_ÿ2†q* #S4í£%AeåÊ•ÜyçéÿwÝu½½½é²‘‘vîÜÉÊ•+[ÚñÈȇªjöìÙÞ={êÖÛ´iÓ¬ 5RøÝGE¤˜ÀÑßùþå¾ûˆ«Uìr™÷ìÚÅ+žx‚/?÷û_xïy±iR>ýt®yòIv$µd~EüS¹œ‹=ÏÃ0 úúÔÃKÇôôô°çý/X¶ŒÝ»ws«iâÕ¯Â0¤R©`Y¶m†!CCCMÅ0 ÇLÕÕÓÓ(‘`x«ÍDBC~½|?®¸â þ|ÇÂ0dÑg´ís2 ƒr¹LEmM•O6Q ´…@³± 33>‘Z"94!2+–"CvÞ• ×AÝ„mf§ÐÎúÒqÙ*etbhfïÞ©Ñh&O;Çgô 2€èéF3yfÃnkag;“ß<ç79ýôÓS[mgÏQòÀe<°Œuéö†?þñ¿±~ý2Ž\ù8—ÆWëgͬВ ríµ×ây·Ür ½½½xžGooo:`FFFضm]]]uiÁÆÃóTìÇÖ­[ÓeÛ¶mKÅaûöíuÂM»ñ Ê;DI¨Ê?ý_îï§`šÜW©pá¿þ+_}ê)~¥·—µ‹sÚ† ™@º~=¯CˆhLfÃÃÜõíoÛÞÄ‘#Gš¦³,«.Òc,þaãý%ºeRì)pðàAâ8fÉúõmÝ; q{ùZ*'ÍÆ&ÌÔøÌŒ¤ùó9¦¸WAÍ~#Tœv “ª$Ë*IÓF²~ò·P¢J­&hæ=íŸ>>..Fò3›HÝ&ò·«bQErLö&…Eè¡êÅH'‹I²o¦ÂDCOzOJjÅqR©¨ù¾¤öò<õ^+a¤RÉDÏS}±Æ4Õ²0ÌÚK¥DÀT*j™m«×ÙbYj{‰†ñ¼Lè©ÕÔúµšêCc²6O NÚ1·•ô11>þ¤N]C£QÌÖ½S£ÑLžvŽO%¦èL?ÍÔ˜-»m7pÁ³GyÛ…ocý=ëa=`A­¤ê’‡Âjç ¬·@œ8™&¼úÕÃÜu×é¼jó8fóôÍLÓ’ ÒÕÕÅ_ýÕ_qóÍ7³cÇz{{Ó588È–-[èêêâ¶$*cØ«QqQƒr¢TòC(±eÒ¾M}$’6ŠÉ>Td IûVÒ‰˜±rïI¿'Ng_œùC˜Y'Lú¥³½,Ú=>óøø-Õg˜*¥ÚDÌÈëØ¶Õ!‘(R Ì>3õDѲh ûŽc•²K"9,Kµ%¢‚% D|ú¬RIí/Ž•".õÒ߯ÖéëSI__&nHdŠD€Ú·<¸®z-‚†ëª>ÉkßWí‹#ý‘ã-—3Á&ßoÏSmT«êu¹¬Ö)Ô2‰ŠÁÉ4ÕvþùÔc:„~4íœÛ˜˜ØØÉF£iÙ¼wj4šÉÑîñYC=žéXMfòÌ–Ý6¦ÁÆ¡l5ɳFúÌ‘ËôÕ¯>ÍêÕ/³qãaòä“[€£ê9%YgûAk:ˆS[]qÏž=ÜrË-lÙ²…›o¾™;wJ˜Œ2¹qãFz{{GÕZQ¾ë·Ür _|1W^y%;v옰½ýû÷³mÛ¶)Ÿ€à8ÀÖ_äü÷¿ŸÃù—Ôj5úûûéïï§Z­R.—[ª%2–,Y‚çy[·núƒ®o§ bæŽg¡0VʯmÛ¶qï½÷Îu÷f„±Æ&L}|Þ{ï½uëåk¨ŒŠÈòP‚E %^´2ä Z2d·k’víÜ>ú’_%¼Èëáäÿ*YÊ1#égêâQK–WPÂL!y]J^ûɺ…d½J´éN–ûÀêdý0Y&ïrç¤;÷ZÚ+å¶+$¿Q²n%×^þý0yïxò+}Šrý–×ò+ý¾{¹¾Ún|]Ë­O²P^òZþ’íf(PoÏž=lÛ¶ƒÎLƒsÌLσ²mÛ6G½ÍhtŠ¥’z-Æù±ø‹ÒUXXiº«0Tq¬Œþ’vKÚ_i;/ÖHtJ>â¤RQíäk@&tHt‡DÇHÍÛ®Vñ¼ÑëˆH"âˆm«÷@E|HôŠôO¦Ž£ÚE–Éßþ~Õ¦¬'Ç^­f}uœL Cµ_Ùd©Çzz²è˜|Œ¤ó}ÕÏËΉçeBVOÚ®V# š,ƒƒƒø¾ÏáÇgì{6—´sn×E¦„„:REÓVôÜv|ç¶Íl!sÛýû÷ÏuWf„vÏmÛå[¶°],5SEÏmÇGæ¶M”<üÛ@×_þ©Z“)#Ôi)i¢Èà±ÇÖðÎwª,Iø‡‹h³ÉV3Ù±cG[æ¶-G¨lÙ²PõTùð‡?ÌwÜ1ªxØTÙ³g½½½ÜtÓMlß¾ÁÁAn¾ùfºººÆl–.]:¥P³Z­Æ¾w½‹ýÝݬ¾òJ¾tß}¬_¹’ÒsÏaÛvàP.·ßÍ{ùòåœyÁD«W·u?Rо©«L`õêÕ¼ûæ›ÙÙæã™-lÛnš&­··—½{÷Îu÷ÚÎTÇçºuëØ´iSÓ÷FOƒL´hLÝ5Wäk²t£Ä•féë¥>‹Mvó—´a"øÈÄÀNÚò‚P²^ã±7›ȹ²’>…Éþš•£É÷Ù£I­&}—'„üù—¤ÃÒ/ù|¢ä¯™Û&¿Ÿ~2±ÆÌ­/)Õ$‰†~øÔGëÈ×D"ƒ¤+w®›|WV®\Ioo/a²Ð™Êø\¼x1½½½Mïá!á´‹YçëŸHT…aÔ×!¬ˆÇðEo'úªtÇY!uÙN¼”òËâWP°²ÿ¥‰ RgÄ÷³6$’Ã0²¢ïiÆDhu ¦™¥ÑêëSb„ˆ'ÒPˆ mM6ª£ÙCA^lÁåĉúõ%udbŽiªmMS ;¦Y_w¥XTç@"$ºEΜ§ ÈD*‰ Šã,ÅZ«ÙD¥æÞ“O>9­ïY§3sÛ¼ÀiaêÚ(š¶¢ç¶SŸÛj4íDæ¶ÿñÿ1×]i;35·mÇÝ2dr‰ 4'znÛÚܶQ Qs[Å»îX§B-R›FªÈz‰ÐåÔ¿k×)|ûÛKX²ä î¾û:>ûÙÜ~{'4ȦM›¸çž{f¼Ý–•ÁÁAöìÙÃw¾ó4…“mÛìØ±cTñ°©²qãF¶oßžþßÛÛËu×]Çààà¸sÙ²eST>»c~áxïÿ1—8¯Ovÿ §òj•+VPþ×eŠÎž-cÛö¬ÔY³f ?ó[¿Åζïivè«T½½½M=¼SŸëÖ­cãÆ€J[rznZ› *Ô¬4@ m¶‡„XSQk¤Ð}3ŒÜ_{œu&²QOÆé¸q?­’ Œ/¢Ä§I{­ØÒ'ê«Áh!¨<Æë<ùª‘½")Ò¢Ü2+y¢"‰$ÚÅQë­pUôäí·ß>‰“:?™Êø”‡ÎfÌ„Á6/¨ÈPAD¢,@E8H:*I•OÍ%Q%Aÿ%¸Mê…Ä1¼š¬MÙ¤½2Œ,õW©¤™˜KÛ"܈P"ˆ24”‡üq#ð9Q³Ù@Î{I%–ïoµš-ÎÎiµZŸNÍq²T_E¼HtD ù~ýgEêµDÆäÅ–®®..»ì²A631·ra{ZHÑÌznÛúÜV£™M$3ˆžÛN<· è ß<ÍɃžÛNÝn+öGÍBËäYæÈ8pâ³À00 ¡rÍ5Ç9tèT‚@­xõÕWÏõ©Ñt07nd]²Aµœò«···®Ƶ×^;£Ù³gOšFLhWý0 9ò×ÍŸù }}³2ú†¯édfb|îV$ßô ” "wÏõ…æÛH<Õ@í…2H-”˜3[·¥Ø(ÄM^Kª¶¾dYò~Ì]L"W$õÙIÀLß?§$8&H¦Ç8΄1ÄKD‰çeEÖ-«>åV>Â÷3#}¾.ˆiÖGoˆ"Åâ%Â$_¤]„‰(‘ßj5+^/"AžFe!Ñì˜ä¼Jº²þþìó_ I&Q2a˜E ÉçU©¨Ô`PŸ¦M>ëh†Rûu:316uz/¦=Ìæ³§F£™ÓŸíTôYs²ÓÎ{çã—=ž:G¦œ~:<ôPú@bšðk¿ö»wïfdäë,[v|®O‰æ$¦eA¥ÝH¨˜ääᮻ”byþçîݼréRîºñFš¦rÒÌ Å}²3ãó "6$¯K¥’2¥Ž‚If<ŸŒ ’·ÎJ†<Å¢²æy^fÉ;Ù±€Ó!^Å âÁ"µq ”à2 øpîás纇mg&ïŸR{2HAsÈ ¥‹Á{j4šÉ1ÝñÓñ£wä šÖl•÷‚&ϲQ¥¿ÍÞãxÌmÃ0$‚4=rÔ’ ½¼'ý‰ã¸îu4IϘV¶‘¾6žƒ“!}ó|b&ïQCñÔ+\‘Ù…¬7.‚\0„OúëÖ­ã=ïÙÀûo‹X»ví\ŸÍIHÇ<ÍnÞ¼™;wrã7ÒÕÕÅ<ÀæÍ›Ù¼yó´Ûö}Ÿ(Š(—ËüèàAþí¢‹xÐÔ¨M«ÌÄø|–˜õÉÝÑ4M,ËR‘eš× iD*R‹‹¹, ìZtã$TŠÈz—ïW…é©tEÊb(.ë xÂsæº#3x<îÍuÛÏLÞ?‚IG¨Hñx¨Pdø‰HQ*©á%µ<¤ÖI>"EŠ»‹ ÒÓ“¥Ñc~¹¬Þ ‚Lœ9­M ³K/ù´WÈðՎB¢RZ©ÿ’Ï&Çêó¬TÔ9-³Ú.µš:ß?¾x®¯íLwlFD£Ò|M9ÊR£ÑÔÑÎgOF3=¦ÿl{ÒƒÑûLÓ4SÂ4MÂ0¤R©¤µle(ŠÃÇqˆ¢(¤–¯´a¦ibš&¥R)mWö#ûµm›R©”¶'ûr’‰´lkYVÓýHZøSN9Çq0M“bR.}%pÈÿ²o˲Òåygå ¦P(¤çèĉ¬^½ºn=i˶íTÔ‘¶ ÃHûhå&¤çÐ0ŒT‘ãÉ×EŽ¢Ã0FõYÚ!GÖ‘s/ïA€mÛ©xeƨTúßùÎw¼³öLÞ;#¢:Ç¡ #F¥ ·ïøeÌ_»ì+Òe¯}íkY¼øaî½÷×ùÑY4šÙ eAåH Óƒ õF…{åóéG³õn½õVvîÜÉ¡C‡èêêš1¡0 Ó äOýÙŸñ“×_ß‘bŠ~DÖtcáéŽÏ'<Ò"í*¢`<'ù¬$RÅu•¸Ò×ðëX·îâ¹>¼e¦ç¶Ñ(3$L‹Ôk4šÖh÷½S£ÑLvŒÏ™Î,š7¼ïÛ·Êÿ1a¦Æy×uñ’¼·yƒºˆŽãÕj5A à¿¿?i¥Îm5™¨ÆqL†©_„ Yž·ˆ|íØjµZ'Õãœ(–e¥¢†¼. ©Ñ××G¡P R©`YÙó†¬3Ñù—}JTŽl#ö>×uÓs.¢H#r΢(Âqœºs ¤â—mÛu‚•ëºA€ã8”Ëåô=Ù_ÇŒŒŒŒ:OóvÛm Ô¸ª# X¤vJ€5¢:"¿ÏfQÓe¬cÊ/Ïï3ÿZ„ ™ä¸Åž‰ú,ëË>%B§ÙùoY¾_cõhhhÌíœo­Æ}¬[·ŽÁÁÁéžòyÁLß;/{üñúZ,a¨ΞY‘¦„Ž"eRyöÙww¦«º®~†ÓÌ - *7nl9ò¤S¹gÙ2Â5k¨Æ1f * ¡¤FÓHL̉Ä(†!ï>ðnøÆœíæ=Ý£a•¨;ù?ʲ|ù~fÄ•ô?P"âJÞ1eWp!$ۉѶqŸ¢‰˜&x¾ëÚYåeQfòx^æVߨ(¨»¾ì°RQómT*ªm)"ÇYéX&]—³H&~RZNŽ>ù Þ)§Ô¯¿köIRxõ¯{ÿšŸä'çºó‚ÉÖk¨T²¯r~üÈ×0¿\¾Þò—1ê8Y4dé¿d{×m­/‹Œg§}ü}EÊi¦L³‡œ÷¿/'É3ç”i¡¢Ñh4³MüXX8-yC)Eበ‰‰µh¬™S±©T*¢(JÓMY–…mÛiä„ã8ø¾Ï'~ï÷ؽaCÝ(°,‹þ‰²œ¤,ôôWšé‘Oc;òo#œ~úêÌ”Ø]úÎ>oGV¯3àoT¯E[H‰D4ó‹I×PÙ³gƒƒƒiʯ®®.®»îºz5±ƒ‚€Moy þÆopÙ'?É/ýÙŸÍu—šb¡#T4 —Ó1ÒÉíásë:ÔÓ£<šk5u/¯GDLEJ¤˜f¦MˆaV<¾\|9ðmÉFduzz”Žáy™nR*%_©¸ÜŒ\^›¼$DNs¼Â yq%oI CåÜ ËR—“Ó¬Ÿ'NÔí#^ºt’1š“…I>ÂzÁR —ƒŠ-Q´=Ñ¥H¼ã¨1èyjÌŠŽhY­ )3ÉLDbYþÎü©¬ jý¨›½ d ¾#š_#T­)3i×IþúÉk3i3yÈ œÛoÜÐͼd²cæä¡B… —€€ˆ·I¹˜8M(†,ƒ <¼´ i”°[¢D•*5j˜˜øÉ…E?Í É5jøøÄÄôÓ…E&&}I®ß8ù‘ë\‘"Nò“?/´T¨àà`aQ¢@™2%JØØ88øø”{þݘ»¿!aSQ{¬å3‰»®ú:yBZŸþT*LÓÄ÷}†††ÆÇ!vÏõj4 ¹–†€õM‹;r»kõæ‘î+VR.«gÈáaõwåÊ•sÝu˜¤ ²mÛ6n¿ývV¬X‘¦»ýöÛÙ¶m®ërÓM7ÍõñŒ"¿÷½\µ{7ÿëÆçº;c¢—5 U˜À¢gñØšÇ¸Š«š¯X«?óëÀ©©0"Q#âÑ.5„þþ̰+¯Ecðå¨(ù£43ÂD‚Ф×1²Âð’ŽOˆ¢¬`½ŒçF$ XY ýÓ¹Qç£4ò„¢Ü2—L¤0”¸Q! ÀJ„è?yÏO¶óÉŠR²L‚d_2®=2#JÚô“õH–‰ÈBÒ†ìW††´•w<–Ha ÙW™Ø’ 4EµÄ¹sQKúb%ÇSH^K;äú m³‚N÷¥Ñ,L ¨T®1qj !EŒöà §ïKdI@ðåž-‘%B… «Y¦èÊåJ”ˆ‰)S¦H‘!†RÁ"ŸnKDiÛÆN£U¤=a†S£˜ˆ:Vúw˜á´M(úèK…‹5ªTÓtbUªT¨¥ý®P¡›î4:¥‡úéO×Ò>úè¡'~LÌÔx7À@ú¿¤V”¾ôГŠB ¤Â’ˆQ91q*Iÿ}|LLÊ”ÓÿEp R‘I>C~D$‹‰)PÀÆN£ˆ@EÖ|çCß™ë¯pGc:A@¡P ¿¿¿¥¨Íô ‚€ròkš&µZmT-Íɉˆð5à¢3Ì«º^•½™„©ˆf"6“u뎱råùéŸvf¼^F3YZTvîÜÉí·ßÎwÜ1ªøÐŠ+RÅó¼ŽTv®]Ë›µ˜2ëhAE3‡漋Ïóýøø²ºÿ+•Ìè*Þ R'¥ZU5ëÅÈ/åG$LTÊ‹¤uúÈVˆŸwT;®›¥ )AR(¨u¢(ûí; ÛVïIè©ØúK%ÕF©”õ]!ÈÒ‘I*#ñ°cêëSú†D¼ eµîMV¯ÎÄ•žµ9¥R–BIR˜I? C‰.’n©VƒepdõAüOþçúçðþñRŒ»waýÜúô˜œ£C­¶{ùàý¿+°¯ØKw¥%_JÿÖ‹_Ãß5Õ·-%zd'µÕoI qŒûÐDZÎßKÏ£‡û» ý,Zá¿,£|î.ÌK÷_‡ûý/Qøð[úþ™ê{ƒñü™xÿpåg?A¸oæÖáCJkÜEê@‡‡ÑLŸpÂÜèòý”ñ#¦œ±Ò¶3²1œìH÷«@âgÀÐî>2a%/xT’õ%•ˆùy´¬¢’¹ÿTäÆ0Jøå1Ôe1P"B-y?$ h$íVëÓP²üµrÇá‰1"È8d"É2’~ŠÑ œü¶bQhüXE,±“í›eE9@–‹TDØ 9·ýÉg'ÇO_¦Ñh4š4—DÈ2‰tȧ£’èŒf"j££ƒËÄ91Ë”ÓÔ]͈gÌÔ‚FÝþÌäGD‰^™Lÿ¤ éçxÛI¤Ž ¢‰E"|4Û¿‰É0DóÔ¹"”äûÒxLÕs10Re5«qpf+ùÉ#)Í€4šˆTùvûèKÏWB*œ-úëEpå„_ƒ“–ñŠÒ×j5Êå2µZMG¥Ì¶m§ui ¾¨¼F£œ Ô#ÝýçWQ»fìu¥gOÏ^õª×áy-¨h朖•ÁÁAz{{G‰)ynºé&¶mÛ–®Û „aÈË¿þë-L;ç±í̇¾j4Sá`òwÃî yã‘QïK½U"ï2Ï•¨ ‰âåbK·íÑåG§¾Ž|¸Â>€ã¬I ½†‘ÕuÈ×”H×M"L~ýiì÷œƒm«>äëµ”ËYª1)²-©ÊG 0–¥ö!L±¨úœ¯#5[ÈΉԖuDdi¬1Çõ.2éÈÏ3$%Ó«œ#ϯ¢øýOàþïJÄŸÄèêyPýJävµÚš´h·:gë‰ãõô»àûï£üGê<:ŽÎMüðË”° Üêj5Õžïƒû‹§„¡ï Vó†k°–fBSA_߇ð¿>ן }› ¨e߇Zhã^~5†(KÔD×LžV<âE‰¢,ˆ(_Œ^¥¯Sß“rÀ±Q‚ˆ!¹áÁ°›{/ºQÆüJDñr¯ d©±Äˆ/b‹¤´2ÉŒ(iS¢1$²DÄ’(Y×É­#Q"|ˆ€‘¥Ý²’ý»Ô‹ "PÔríÆ¹×å"Ñ"¹óQ#”fÃqÏaâÔ^ò¾Œ);9×$}QÊ'ªÅ /Y¦ƒ-&E@ÐÔÈÙÌ€¨Ñh: /(¨"òµK„™ŽF“´RcQ¥J”¸¿M¶N“DwÌ$UªM—7;ŽüºÍú1Ýs9^Ý•VÎM£@3ý%æœñÜÓ:Æ“8Ž rù¢«Õê4ZÓh43ÅZLàG‹q^D= iuqµ,eËX´è{ìÚµ’¡ñjÌj4³DK‚Ê¡C‡Zj¬S„á›<À)öD~%‰ÍÂ`>œsÍìrõ=ÿOàÈÚÑ‚Š¤ô²¾{(rV÷SAî›ÍæÁ’ ,/4H*¬<ï)ïÆ`Mú¿a¨ûu£ƒR__}Û…Â92Á꘼ðÓˆÔUieY^ pœ,ý˜,¯óôÏg#Ͳ`ÉzŸýæ™\ð?Ž14t¾Ÿ¿÷™o«¿¡æhþ8e_ëÈrYWö/BYãytœ¬^L¨É“¤]³¬,…”iªÈ$Ó„ð±_¥?üwbÓ¢VKŒù7>J°{ƒÎ6IZ­× i½äsÈÄ´øAð×ù48’òJ¾ÓR_¤š¼.¡¢ò‚ˆ$­‘OK哹J„Šìãã¹¶%£B&TPI€>J(£¬ß˜,̽Ÿ¯S"Q(’LêŽH:1A®R %?Þ%JE—™¯õ2QrN¦ÙŽs™@e’ D"0“s'Þ#XöóË&½»“±Œ–ZPÑh:!†ÒÚy&+`´‹©^GôõgltšÆÎ q„ù¾O¥RÁ0 ¦;ñÑh43Á§xØt?ø w¿ñ0w°Tÿx’ÏbÛð¡Ǻuëæºû Т ²råÊ–D•ÁÁÁŽJùuÏñã\süø\wã¤E—RÕR\Ñ~wÙïÒ÷îѹl$"%þû…šz-‘Õ1Í"T`´P²Áõ¸ÓJDCyýÜÞÀ¦¶§Ù, ?ò2»ÿð âÿÒ\š)$}Z³åcý/¢K^ØÉ§ñ%:úð¹êïµ÷c<ò”͈Òo–1{Ôv/¼°´ý'u0ž! Ž“qx6„ߪ¯•²z5To¢ CÛÁYÖn”¸!…àäþŠX! |@&ŠTPøB²N?* ÄEE°¸d‹ì…`s€ÚÍ ÙO-×§ˆúš$"ä=äu•ú-ù¿0vô…Ck³[—¤ûÊG¡X¨s*‹Ô©‘Z6Uxöس08‹Ç¬Ñh4m¤H1-H.©š4Íì7YÕj˲tª©9B§fÒ4cðæï$ζ×…»ŸMÙƒŠd1±måÄW(üwúúú€sÝ}¦5AåÚk¯0×¶mÛèêêê¨(•ÿX¾œ›Ï;oú i¦D<ý&4 ˆåXÃç¿ýyÖškÓå…‚ŠÉ—·,à8êæY,6Âh¤säê…ŸƒM­5è\, þù‰G(}f Æ]>×Ý™>çŸOì¸Ø·ü Nt+FZú´Vƒïÿú¹îá¼ žàŠ]*%‘C_w±k}¿ ÑK`þo¹â×@°hE¨³›ü_%KÔ¥=Ïk—¨%Ä,Þ䃌&û’ëH>šJ–×g£Åcj¶]g8#×ãR_h¾]È5Y>Ó(·L‹)ã2Vʯi‡i4š™DꢄÉx×hfš‰æjš,ØXˆã˜0 éo £Ÿæ>4­a5x а¢Mžc_ˆ5kÞŒðÀêŒ:–¥•+%ŽÏ¡Z­jaTÓ1œÚÊJ]]]ÜtÓMÜ|óÍÜ~û파Œ¤ïŒŒ°mÛ6n¿ýv¶nÝ:×ÇSÇã‹ó–³ÎšënœÔèÇ °|è?Q?¡•º ‚Ô‘ú cEžÌ:ù¸æ)a•/¾ŽêÙŸ[0)±‚Âkÿç¨p$W¥j™pÂvApÂ/Bpp·ZlýØRC¤ñsLZ©ÒX×Þ¤^LÑLL4ý&&Íü¿„Î*:}ŒFÓùøø(P¦Ì0ÃZLÑ´hNnÜóüT#g6 Óišaúz¨™˜#‹pâÕ'ˆ®†ÓO¯KÛašê÷¾ûîKÓ÷M„dGÑhÚMK‚ ÀÖ­[Ù¼y3žçqå•WbÛ6W^y%W^y%wÝu·Ýv×^{í\OJÇœvÕUÓõQ©G*¨t5”[B•ŠD~}²üášm ÐO‡®<Ä¿½áßê–DZºgº®2öA}¡vh^oD35lâ–RŒFAFIÇùçzOE;ù“oT3 ñ²Ÿ‚x1ðI0ß æ+€KÕ:ù:<³Š æFm©Ÿ>*JE£Ñh4Ó"$¤J§%fjˆ˜¢…öÉÁ¨(‰é åfæØ•üýοC×5]D‡ÎÆz󒺇I?y”?ï¼EÄq¬£›4EË‚ (Qå_þå_RñdóæÍlß¾ :JLøâ£rÁÓOO~äX*>*O»äx—\ìâ¥[EUK +>+BËdÓhè¸QÍIÂKy‰Ÿ^ÿÓuËÂP¥û*•À\ºŸà¯÷õÑÚ¹ef阨Ÿ:)Ž®™:!á¸^µá· ~¢sÕ¼ xø#Yj¾¹œßçè‹Ä¤°Ñy95fˆˆ(SÖ‘)š¶"‚ŠþžMŽ™ŽPÑ“ÇÕ)4ãD°ìžepð ñ³‹Ò÷$CB_¼ôÒ½8Ž££ž4EK5Tò¬X±‚k¯½v”€²gÏvìØÑ1i¿þéÈ^}äHk+{(áÄJ¨|ê6¤‰ø“æéH¤à*dŸEÔÕÁ$seâ´1Y¡ÝdÿQòZ£Y ¬Ž9ÂÞó÷Ö-ãìfY~ÏnJ·®ÓÆñ6ãûsküžI代£ù§GLŒ=^õô‡À< þ `^ á^°/Ubg«ÏI•J×uuÞÛNÀAÍw4Í‚!ŽUĦžCÍ.ºø¼f6Б)“#Š"¢(ÒÞì€* >öÿš““G¯ò ^z‰µk“úº_LôܺtRò¬Ç1¦ibš¦è4Ť•±Ø³gOGÕQyhÝ:nÝ¿ü•$—…B,TÑÛ™=¥LD„P,”pÒƒlP"N*ÂE¢TBTZ±˜Ñ\kI»’6ÐIÚ ’÷Œ¤-Ihç^“ì·–{&ûñÉ¢p¤&õƒã¤-³aŸù>ÚL??zæS¦Æ±ZÏ4Õ{a¨Ú²ízÁE>Ï0yqõÿßÿýÛèí}v®¿zO¨Ó hf ™Ò2"=Ï£V«iã}¢ â€Ã‰!îÔC‡Ø°aƒZxÉ%˜‰ÙHæe¶­ž·ÂPßo5ÇŒ *Æþ¥Ky“(͈PwÜ™PÆ"oçp©ÏY."N^0ñP‘1Y4‹x‘J_óÆCW†sÇa‘‰2"è8É_;9îLl‘>Źe²­ü†d‚Œ‘´W&‹®éGEÝHÎzàBàÀWrýò“ã•TjÕd;3*d"ÉûRŸF<ÐkÉú"T¹óe$ë[I¿Œäu!yßJÎg”ë¿›¼öÕ¹s%ëÙd"L)é[9ëãÕ_¹š{_lÏ÷gq:KŽ.õÞÐ22D8/ü-ü„~`h7Õ…Q>E3ƒ„„”iPÙ<2!¨m¢Ì@gš£=¡K¥}}}”J%lÛN†b±ˆëºø¾OEø¾ëºDQ”Š"ÂA@OO–eáû>A`š&aq§-ËÂ4Mî¾înž¹ûþõ«ÿŠaضMOO®ëR«Õ¨T*X–E©TJ…B¢(¢\.ãû~*z„a˜Š;"ˆPcYžçaš&qœåÍ’ö…(ŠÒÐôüqZ–•_±XL! C<Ï£Z­R«ÕR ¨Û—ü•v«ÕêÔNõ¥¶ã™ dßÏÆµï+Q¡TRµç%µ”ìL@¨%Ž:–¥Ö•à(R¿"fȶ "|Ôj™ÐÝ­ö!BEµ Å¢ZÇ4ÕßZ-ëK±˜½yøVÛ‡a¶ˆ1"Òˆ@#‚†¬E0<œ –•ÌQrb2¨þš¦êËÐP&¼ˆÐbê=y].«õK¥La¦\ÎΉãÔŸÈ¢rY½/B‹'†¡þ7Œ,rSÄšfœrnDß–ÏJö±aÃnàìYÿþÍ7BB9 ÑtbFˆP‘Úx¯Ñt2&###lÚ· ÖgÎ"Í+ÕÊjÙLß“5³É‚T|`é¿ÿ;æ7Ž~S DÊX?×X¹¿E2Ñ@¼æ ²h—f4;#·¼ñ!*yÒ̳0¿,$O¬\{!™‘_ˆÑõ`>|žLøqÉió@Cåv7íE+}3×n”»l/ýË·ÛÐV”ìÃj8ŸI;5ê#²~ÍÃtÓflŽ+°øüÚ?æ-Æ[Òåâš>ðÖÂ)î¡ÑÌ3Fy?ÖP×NÜשñ ðÄOkÓ¡*iâ8Æ÷ý4ªB„×u1 ƒjµJ©TÂ4M†††¨T*ôõõ¥Â.ÕjÏóê¼ kµ…B×u±mÇqêösæ™gò©O}ŠŸý³ŸM·‘HjLÓÄ÷}LÓL£Dò“óüC·´Ÿs¤oA044”F±ä£Q¢ä$IôŒôϲ¬ºÈ’ꪦˆ.QÑßß?j»Fâ8¦P(P«Õp§®Ý¼@år9+Ìj¡ë·ÍÚå‘,Ñ%",˜¦%”P.«¿†¡Ö1 %„a& dª|Ek5õ;0E>ˆH‘Š Ã,ê2ƒ¿ˆ²-(aC¶É×jêï϶q§q¨4‹ É/“‡öF{›¬Ó̱¹Y›rlÍìvý¹9¼ ¿ü2ÇÉŽ¢ÈÑüeCÎs~[Y6žó„|6}“ã{ÍkzÑŒMDDýã>¨i4šÙÆü0¬‹ˆÖh4ÅÁäï‹/¾È³ÿëY°Á«¨ydµªæªâ´cÛÊ©®ª½B5Æ‚TB`Ž÷Ò}ã¯3À^R%¾Z¬‚ qS[UÃIÔ†€ Î3×G¹˜9ÌbRþÆÈ“N@D†Æ~Ž•âAÞ˧“ ¡É^ûŒ Þk& Œrl¬>›ŒŸ¦L0׎œ—(Ãþmûµ 2G€7…µGÖ¦½ZM=ÀË}®.„¡ÑÌ9™8Å÷CÖ‡ ïcð©OÝÇç?_f —gÍó¼T¨èëë# CRñ$oÈÏ‹$ý‰U1ŽãTtQ£Ñ£ÐuÝQHž˜˜e,kúž• £‘¤V E è[_ú”ß¶±?ÿ·²ŸÆ}i𝉠/†ÁÀÀ@$‘5qcF*æ8ŽC±XLÿ¿ýS·³Þ^?©¾iæ'•Jf°/}úþH‰'éP©@ü$ !Š¡z3Õ Áþ}ˆ¾ æZ¨}+‰ª\ ¢¯æüSáW ï60>ñ~0~Ìý³/†ÚÓàÞœ et C¡Ã{ <¸àT ¼‚×'¢ ¨›1ù­BÐ ö ÔQæU],‘ÄAòë«v ‹Ö–èä2Á!„ð|0Þæ!ü?fñEà>OV+0—·òJ0ï7„à`žf…,¬!}j_þœBÒN®¿"tˆ°TI¶³ L"FJu׃)iwÅiGDÈÄ?i¿’g‘-©xŹGDp'·½¤À-%Ûˆx%Ë¥–¢ˆMrÙH„$ÎvbBB]×B£éPò)Y5Mg²X5< \ Ÿ,âœaX¯”­H…*•ŠU4IK‚Êž={عsç„ëõö¶>22¡C‡èê굯={öÐÕÕ5ê½VùÎË/sJϨR¥D‰¾°¾ ÖG-*K*DD 1„……‰IHˆ‹KD„M‰ ˜˜øø˜˜T©ÒM7eÊÔ’Jïà `aÜlX•eÝš÷H›ªVÍg¬± SŸ#€u üãŠG¬`kAøû_e¨ƒNõ•£±àv†©‘4ÿZð}?­Ã )Š$Õ’faÑŽñ Ô;„@DW¤ÈóÞ½{9‡Ekžã_ù>ôŠWpñÏýýÄOðÆßû=ªÀ)À ”]qãm·ñ—Ë—SDÙ+dNÒbÏglBRtMÅ0Qnay‘kE±XL¯S.n¯©c&ç¶ñ³¨Y°DŒ²•=† Øô'ð¦ð¾à¼×Aõ¿Á†^øÈ÷`ärˆ÷0TVAßóý ôls¢—Á|X‘{@ÏUIªYI¹ÔFß$‡ãõgT+dAá—¡oJf}p…Û¯ÚK²9¤åëìý&„+²2}^.EUl¤+Ô¬DøK0ÎJÄÀ¿\µßØV¦1Hɼˆ~jç‚sj˜ò¦¬¤Ÿ‘¬Y?ý÷µâwBíRÕ7×N—«ª>`;ê8K&øôÿ2°JW«þWÏÍüt7+íàç ¼üLû`˜Æà–Bùw ò.uû’å–“ÛždÿâõàÿÜ·÷5_öàPbÚ‡÷ßË\Ѧ‘2û´ãÞcë;˜f êÒ@,Ú1>õœF£™Úi·] 8xÓ~é4ø­˜ UÂP9Û†r¾½ÿþûù…_°&õ¯ÑÌ- *×]w›6mbãÆ3¶c/I\¼uëÖtÙŽ;ضm›6mâ`ëÖ­lÞ¼yÒm˜çþë[Xÿh©'‹ÐGn®˜†LˆÅ¨Ô‡r———0Í‘kaá⦹s=<ŠSo¥¡´HgÓ,V +AŒ©‡aˆišuÛæÛ2B¼øÈÌ÷QŠû6‹¥¿ãõ{ÊH‡“€fc¦7>æ1øÂC_àc|,-šïy–è_wqÕ\öŒÑ(xHIT©T¨V«DQ”¾–Ú†aP.—Ó÷ä{,mJ[R8[þ·,+]_ ²¶mÓÝÝÖœu¥·ž”ÌOÚ1>¡¾VC¼ pá”8C-xþßâ©?x=«®òX±¢ˆïû¼xÝu¼ó·›'”á4Ù^2óX—_Î3dÎ×ùL:"¨ɲ]Æd†ËƘq`§mY¡=.‹@j±´ ‰h‘ÔbZ€frnåâ|CÔ¸¨’e™ ÷C¸þ÷c°ó(þ78ï.øf ¹ðú=¸Ì…ÝfV:Ð[¥Æ\iEX¤Æ—}*°BíO‚D³µVPbJ?Ê0Ÿ-è&—õ,(ÚiÀjÿ•Ü1I[&j½Âjµ¿ád½b²\Έ¬ô$Û—î$ýWãì[®GàRHú1t¯Q}”@ ö($åZ#¥ôú€Òod⇊ÔÈCœäX¤¯}@íÏ2aH2™9ÉqA–Lc5Ä_Î>ƒ"™oO…LH‘k®˜« ø™ìÜúŸÏÖ³>¹_aÒQª«U»¿ñë!¸ï¾ ¿§ó…vÜ;ÅO£™-ªÃæLŽÏX}ß}']T³FÓ.Úe·ÝGÈ«°9ïÐ%týÃÙ&Œ¨Z}’Þ¶!Šž¦Tª¤µ%5šN¢%AÅónþÁ‡áG(1%—ÉÂÄœÔäׯÆÃ««±"XX©È"‘+5j¬fu*ÚØØmɯ+FSI»"BC¹\¦V«¥MÓĶmJ¥R]ê•(Š( ô÷÷§î"”¸®‹çy†A†©È†ajœ•\íR<¸T*Ñ××ÇÞöb,~Ñ/p7°¡yÿ=ÏKsćaˆã8©á¸V«ÇqÚï´Ø±œ*• ®ëbš&µZ ß÷)—Ëxž‡iš˜¦™îCRšH‘àI{­80›%uæ‚ñÆ&Lo|!~ñÂ_TdJCðÇ`¼öU£+Évùza¨L†aày®ë¦cOŠnKQí8Ž©V«é÷SRóH­y/Š¢t\Iù.K•J˲èïïO W›¦‰ã8X–EEéø‘F®yÁFÆŒf~ÑÎñÙHí'•ñmE’F& aïÎ7ñŠîÅüø¼óફð·mã¸ã°ôê«é"ñö&3¬6–0ðÉŒe´‘÷âÜö”!PÊ(ƒb9Y&ÆOe<Clñ°Ÿ¯ÌƃÜ'ôšÔ§s/N‰vÌmóóFÉ€eåPs`Å_šûÀx<Ý;ž‚/÷Á¾gÀgLREDIÈÄJgFóRr6õ‘c27«&MÊû,Ñ“Ob%‘a2öä~EA²nE ½úÕüÖ‘#˜ƒƒ¸‰ÓCL–=‹äü¦ÉîÙÃñ‡&´mªÒ×0Äôð™$sD;ïÑôÓ=k4“`¡Õëi×ø¼èðaègfZ´Ûn ðSXúÞCð°¿jÂçUm?ËßW‚ФÖbЦ™rQúÛo¿}JƒfÓ¦Mtuu±gÏžºåƒƒƒ¬\¹2M¶qãF6nÜÈààà¤ÔNŸå€÷?ÿ®,Ÿð400˜ Z|†©¨Ç1U£Š‹‹‘F®”)cf* ˆøÐŒJ¥B¹\N¦ù¨ ñ0w‡J¥ÂÐÐQ¥Þ¬"zDQ” "bLï<¸yžÇðð0žçaÛ6µZ--(œZ¢(J³–eáû~êaïy^š‡}``€Z­†eYœuÁY„Àóß{8+H€:Q P(`Û6aAzÅ#xx8McE®ëÖ¶EØR~‰rnäØmÛf`` =f˜ä}ùkšfº~cOÆ›0ýñ¹"yx4Iù•|t„ß=•ò_¿e® "<˜¦YõQ.—ë"Bdlôôô`Y* UÆM¡PH×!S„ ‰:éëëK¿{r-hŒüÊGZåk4ó$ÏGAƒò¹FåoÔj5ªÕ*šùC;Çg]ý€ÍÊ@xJRoà[ßÝÅ™g.å½ß=‡ûï_~pùå¬;vŒøÌ3ëÓøyªçSÔHÔ‰ú•ÉR€I‹‘¬'%òõ™%}M™,E…ò获ß 3QÆVñÏn`ÄS2Oñ>”H#žõ•Ü2)3ࣼækI’”ÉÌõÕî9Ì—^"^±‚b²¾ô+_ê vàåÕ«ëjNÃìçý¶,«NÀÕ^“§ÝsÛèXÏ+dà‹PÝÅßSuC¼?‚Ú|x—EÓz|&¤s9Pß±²m³ñ‰'ð¿õ­ô=¹éHç_i)iéd]ùÞä#«,Ëâ×þëÅu]ÊŽCEø¾ŸFlú¾Ÿ¶ŠÉÙæOÃ×u ÃR©”‹aø¾OX©ðöOšàÏÿ×u |ŸÕÉ\ä+[¶ðR2Xº^yžÇÛ?÷9†ð‡‡Óϲ{õj.¾øâ!¨´óÞ¹P£4‰‰Y¹¸h×ø<þä“s}hͼ§Ýs[€7cpìË1ì5`mvOM¦l©Ï­S4Ê”•©"iÃV®\Y·|çΣę•+W6½ÁæÙ½{7[¶lI£g¾NÈ©ÿ»tbÝ™aÅñ“÷òétÊ”qq)RÄôÍÔ›=,ËJRå¡1ÿ èû~!^‚"º”J¥TŒˆ’‡=%d (º»»èïïO Ë:bp¯÷ü{yäØÄ>úúú‚€Ï>~7ð6¾™[{þ0='á’O4<<<æ>„Æ^b,îîî¦Z­Ž*jÜÌXìH±ää¡^¢päÁ^•R©T'®T*•4ºEÈmÛÆ4Mnºé&80©úAÊXc¦>>¿ò•¯púÖú‡Î8†ré ñ¡K0º–Íú±Š@'Æ#1ìˆè!ùŽŠ¨Œ;1¸T«Õ:DÚ“ï d·óßÑü¸Ê¿ž-¯ô“¡ ÛÎ;Ù¶mû÷ïŸë®Ì3=>÷ïßÏ–-[¸öÚk9{óÙ™×cŒŠ,Ü ÇNÝñzúÿõϽv=¯{Ýëx°?ñ ‹FqÈRù”È<µE€45qn}IAcæ–Iê4­J¼è#»ËòrnÿÛQ‚Ê+ž÷¬³(&û“Úϼô…C‡0~ô#*+W/[矯ê$=ÇŽÁáÃÇŽá½ø"æý÷Ó}à i´ŒXßøE Z½oåJŒ%KˆÏ9'­wm}ÿû„«VÁé§cìßûàƒn¸!«†qì8@ðµ¯Ø6Á}÷mÜgžÉ¤×£å†A|÷ÝħŸŽÿ¦7á¢Ò(¹€sÇDGŽ`ÿð‡Ô6oƾä’4ªÇüƒ)ï{«Wc®^õÐCÊÅk ò‚q±X¤¿¿ŸÈ0Úê»cÇvìØÁE]ÔÆ½Ìí˜Û>üà×e©¤ÞªÒ@{€E`^Õ>•_Ú²àÝMÚ ‚ @®Õjé½Ê4MÌD0‘y¥mÛ©ã ÐÔé§»»Ã0SxË‹²ÜE¼“Ô“2g•íd.öä¯ýçœ Äa@DŸ|‰ˆ+Å¢J uàÀ´/ÍÒÓæûÙÓÓƒmÛuÑÛãEQšJ³ÙùiVã,J¥®ë¶ìÈàû>¥÷½r¹È¾ðÞÿþ÷ÏõáiN2ôܶ5»íÖ­[ëJI¬=²V½0A¦8’ÍÄ0t=$Ḭ́mÛ6¾ò•¯Ì¸ÝvÖ•±8tèШe­D¿\pÁu©ÈvÁ·‡%d.¤3ˆDQä=Ðĸ*ø¼—žD¯ùÇ#¸®K©TÂqúûû©T*©È’¯[R©TRã?(Ñ!ÿ@(mò€ÚŒfnMøfÛ¶¹æóÇø.ð;ï}¯|Ç{Ó÷ä‚8Öád‘óØŠXΟDäÏQþ|ˆ[>1ˆ`å8NšKr×®]¼ùÍonÛ¹ì¦:>¯¿þz¶nÝÊðUö>°·î½øÄ*Ì×)CP;‘Ï `ß±}|òöO²æûkÒtrâ-*©= ÃPF†$bK <™%ë63ÐäÅÆNÅ4ÍT4lì§\oòF*9~ÇqêþQ²¨3Ù^®séM²qãF¶oßΖÄ3w!3•ñ¹fÍšôÞYWä4„ÝgÀHÇv.†ºï%V¾å%BN”7_T^2 IÊ©a µR @Ìzù+¿iÚ+Ž¡RÁ5 0 lÇ¡œV¢Ž¡Và Cœ$=ê#…¼dY«W>I;888©ïú|c:sÛÓ.;Iúºƒ`œ Æ€ þ+ÁxN­+—YÒy¥8ˆXæûþ¨t ===i”±0ÞýËq‚ 7Š©q{q^È‹ùušÍßä>3–3Mžü1÷^³~Ž7‡o›±æœÍÚ’h™É82È6“™+Ktöd·‘Èò<Û·ogÛ¶m-·3_™ÎÜöu[_ǽÜ;ׇ 9ÉXºt©žÛŽÃš5k¸ì²Ë¸ôÒKÛmN¿ ÍDÏmǧÑn+¸\†Ü¡ô!"ŠÀ4Õ_@×yÔÌ5ºfŠŽTšy&ìÙ³§N½œˆ/½ŽÅO>©žîË-o:!’ C¢IÄ“.É!¡ÿyƒ£<Àþù÷ÿÿ?Hk˜¦I±XLÛϲñ‡ŸÉ,›QÛÁÈÈp.ßþèÿcó;&ú7Dðhòð+â‰Å@곺ãŽ;Úv|ÂLŒÏ½ïØËYŸ(Ú0ÌRÍ]"¤ÔehZÿÅõ¬ºjtý¥uu€TD‘Z>E”HÁæÆÜêó™jµš¦<‘Ú,rÞÇIŠ´Œl+⊜kÈê:IÛ"Xzž—¿–ÏE s’fMO”¦ÎLŒOH ›pÏŸÿ/=þ2§ýàÎþ™µô¼ç4^HÖ“TW!ù:sa©”ÆûMªä¸†‘͘ó†ÆZM-³,µn¨ ˆ›’T(„Ä@k7ö9ç`Þw_jÔ%Þ¬_ý±Õu'Ÿ!ÉX¹®¿]ßA¨šÆmå½ü>å¨ïæùúu%¼W¿xø’KpŽǺàͰÕ%K`ÉõÏ5פËÓý¬_¯úé¥é{Rd|ˆ}”à¾ûè.0ŽÁ>ûlâÅ‹±|ðƒ¾ç.ù«¿âçz{¹î?ÿã#à@òYû¨h;9æ€úÛnr^JÉþäjé£D˜!NcÄTÇæ3ëŸI_›@¹õ¥¬@ð¨ý4䯳ý!×Úf×W;W¿£U\×t„£ˆ“Ýf²HÄèdÈG”Of?“í___ߤ¶‘( ÉauÑ9­ µ'+Ó½wêú)Mû˜êø”ZZÓB õ•sÿ‹Š ±Ù°®”ÛI˜[&ž7Ž_.“i3yçÚ‹ ÚŒ°¿i«¾”rm…ÙzDÉò|?'Zf®í|_æ÷#­f˜©çNá‹K~L•Ú÷Õ£ž™‹ViŒÔÕh:‰–•={öŒòVºë®»F)°SU~6nÜÈŽ;ê–:7€IDATthR5ZbbFŽwñÓgž©r´aìIt‡¤P#»<ôH )*-^Ú÷,»‡êUÊD#FƼhÒ××GEiZ€ùÎâÅ‹YÿÜ˼ýíoŸë®L×uÓ×tr$ÂL2ñ)ÆÖ ?w!G Ge3u˜É2â™+"@­VKkI1³ß_ñû¬Y³†à«ASÇXŸçBK‘%$ß÷ÓZ.’‚e¬s¿¦åÉOr'<½—¿¦IzBß÷ÓkeE‹ÅQùøåz+‚—¤ ”×"`Ë~Û}שL÷þ)*5 ê‘Î ^zé%.ú™#ìúÚZ.7³Z'*¢C°ÂPEÈ8 HrücJøï•e)K°\O¿où‹B³q·îcQ¾¶w/GÖ®å±înÊÎXÛuEÆ7lÀ>çÜÄŒ#GÒóîœq\}5ñå—áˆßÓ£"3 CÕàùôªÑFYš¬¨úêäïW\Ó$åçBbªcóØYÇ01 P)óø&p)Pï¯ÔdžÅb-“Šp’¿_w=”¨ÌÉ0§œ©Ìi§òð<•ûôT¢¥gk›ÙšwœŒ÷La:÷Θ٭u¥ÑœlLu|VBâ\0.PƒðÓ!ñå1ñ“cŒ‰îŠT±©>à|ߪÿ×çÀ¢¡ðŸ­‰0ŽD+"̳LŒ{ ¸‹CÌ'LŒ×DoˆWÆpÌ—L8 Œõ†jk pX,V¢îõË“}€±Â ¼.$<#$þß1ìÎ^ŸÇzˆß«¹û^ˆ¯ˆ1›DWD8ßwˆVGT¿XÅ»ÐƒÓ z,ÂÜc°~Õ¿Þ'îŽU?.~¬Öõ¨…qØ ^c/³‰ÌˆàÅ÷?\¸‚' !æs&æÃ&ÆÏÃæã&áO„XZDK#â%1Ö^ ƒøâãYƒèx„¹È$:¿"Æ\¢¥æÅ&ü3„Vˆñ s¯ ‡!¸,Àù‘ƒoøXç[÷Ä‹bœËºz11!!6 뾘 »-ÀÁÄJ´üÄ#`½È¢®-+TÄ]£éDZTºººèêêbçÎé²ÞÞÞ óäM†ÞÞ^:Äàà ½½½ìܹ“={öpÝu×µÜF@ÀK§¬f•xhÍ€â~Ê)§¤_"žäÃ÷W¯^M__ߨz"AÔý¿ˆEéëf7x)„¹PØ?½i9÷¸ï}ï0×pÍôœC$¯|¾ðýÉÆtÆgÞ\³oß:â¯ßOôÏgb–/pÛñˆ P©ª$TÒW†ÁÐÐPjÔ·,‹·›Jà+¿naŒ³éO}'ÿÇd£r$×½¤ ›h?’n-jxFþŠÇu±X¬»ÆŠ(ãº.¾ïŸTcu&îŸ6¶Já”ä³:bÁ‰½È²å/ò‚‘E_Ô™_ã8NòFÓ(‚rylñã$¢§Â•?ŽýùÏSX½º};2 Ì7½ .»,‹©<ÃuÓhÙ0 ñ}?€°m»©±×I~»Qß—~ @’¦,Y–—Oï»ÁRãh,¦:6—?µ'3Ä%{a¢ÈÃ÷}¨Õjéu¯ÕZ ÐZ4ôL0•ˆÎùª™LçÞfµÇ4ÍŒ3ݹ­ÜG¢C‘H6Cp4 |&„#½#Âü€‰q¿ÙeÂMÀùɶ¥$Mx2ÆmlŒ5Fú8„ÆÇÚ ÿ¯L~.£Ókr¯W¨?Aò3°t ~FrûŒ—Ä”®)abRº¼„…ED„MœüÛu|b8[…š¸­Ä™ÚµôzÀ>°c¿èŸcžfÒ¿¯‰ç@pV€}ºMÜS^QVÐ20›xoôˆ+1%<b¿`Ÿãuà.6ð,D/FpÿižâŸåÃ)`þ‹Imu ë°EÄ'”æxJ%Ô¬ˆÌûÛ6¥W•pv;„ëBj}œï8¸ƒ®òª$'l ù`M2¢M$ÿרOwQâ\TaãÇ6²ó­;YÈÌÄs'Às‰cž¥{Ò¯µã€ï«$¦©J'´ZN£™ ZT6oÞÌæÍíKÛ$lݺ•›o¾™M›6ñÀ°uëVV¬X1©6Î:|«þxì|“DŠgŠ@"žÒâq7444Ê@Øh¨l•…t±øÜæÏqWpÁÌuW¦išiÁÞ“™©ŽÏûX|ÿŒï³kו„}C8?uñ´lªRD^ÒìY–EµZ¥T*¥EX%Šl¢¢¬šö`Ƥνx=u=ßrÅS%í2œx»—Ëe*• Q±wïÞV»0¯™‰û'@ð+pt, aßYgñ³žÍG.£™\ð>šdŽ¢Hæ›'ZE£½ýÏ?Ÿ€YÌÀ`£ Y…!x^ú9ækLù¾ïû©cI~^$X¨çQ“,õW?Ì£Off™ÊØ\þÔòÄÀ¡vB¥CCpìØ T*ßLkëI„³!4šÉ3{§¡såh4meªã3Š"bb 06°Î·à~0ÿͤl”1>”»?‘ü=’³êmíYtîX¸’9Ìc5W’ʆð,°ØMLD–,Øýëß3°éÇ$Ë6^Ÿ¤F^lª_ulàP­—ŽÏ¯?W!Àzpq P¹4›ó›³þÙI[!YÚXÖuµêqzߨ¶‘ôº!`\Ș2vxÅè÷â«a1Ϭqq11©P!zSK¾*ŽŠHÊû™®K&´1£C´Íä`’“üØûãØÈ1:3ñܹ 8wäÙtY¥¢KdJ+N]'s4­¦³™³*Í mÞ¼9|‘¨˜ÉðuB^~îíüäS¦ºMqÜÕjµÔÛ= ClÛ3ÎLî…ô0|Ý^Çß®ú[®ÿùëçº+3‚x€ž 4›0½ñ¹*™Æ½þõ+‰ÿî{DþÈ”ûÇ1¥R ˲ÒÏ$LÓ¬+º»ÐÒtišcƘE’]×åOþäO溋3J;ÆgWá2}ùeNûÐÓüÒ;פ“Z*%¢¸®šíš¦JçÕ!bs»S°äë ‡DÅI=!I_'u‰d.Q(Ò: ò~fß>v¡¦/A¤’NT®u’‚¯R©àºnºžai$©‘/¢íyÞ¨¨±Q”ËP(dõk’m%¢!ŸV±§§‡r¹\]›‘È×Û9˜É¹m*¬EÀ' üeøïÿ}/Ë—ÿW{ìËuë6FIk4šzfúÞ1¹tys‰¤Vµ,‹0 Ã°î™Æó¼Q©Yºzw²DËó±Ô •û‚Üï\×Å4MÂ0LëOJ”±eY”J¥tû8ŽÓhHÏóRÁ^îe ®qM¨wNè´Ô¯cõYSÏLÏÓÞ~=#=¸Ÿu)(g޶¯›¹>w“9ŽÄ¨À…Fä*‘ÿ˜ÔÛìש‘ID¨ÈÞÀãD”¨/"¥TJ¹6¿ý£Ë©4îÓlhCÞw¨/#ï‰À‘””©;6éw%9/&*ðCJÅ“×1£Å(9¶8·Ÿü9‰sý1rû—ùR^P’c‹1°±S‘êRl¾M ÒÐ`ZÙ9² 1ÉFí€qir’Ú¹¾€o«eð¯~%½ÿ8ºÆÈ|¦v[Áˆcž?íR–çì6¶­1ƒ LS“k4ʤ•mÛ¶122­·ÞʶmÛ¸ýöÛëÞïêêJSðL•é ÈWî:•uÇÖMëé]&r’§_ŒÓÉÝw²åÚ=~ü8Wÿàj^±òð®¹îÍôÑySŸ‹1X·oß\Äù网©^&<ÏKüòo­¦9Qªé]£4ÅXé‡Ä¸ø·û·sÝÅYcZBŠp¼i¾yÕa^Þ~1¼3Y.â¥`|žy6Ñm4‹ÅT´°m›(ЍT*ô÷÷§Æ%PâºGjµZj<á"o8’:uúÂÔ˜åºnšXö+s'ÿk_cÓ»ÞÅ¡Ûo'Z¼˜(ЍV«ôôô044„ai„žDŠA@©É0 ŠÅbZóHÖ—}T*•T܃V¦ ÃÃê3ÏÑLHϱ±Ò•ž,BÊDLulš?Þæ/¨º)ÿçÿü˜ŸüÉ6¦‚ÓhNB¦2>câY‰ˆŒ¢ÏóÒ{M^¸4Œ‚¤¸ñBœN$UµÜãV¯^¶õ÷…¼ðáû~* ôôô¤íK»"€äïA ¤?Òi¿V«¥ÛH'‰4.—Ëé=·»»»®yFú—¯%ëÊþò÷¬ü}\ú9‘ƒ·üÍ Sùvóç»qÐè„‘oSæÒ·F¡ 21̶mî~ãÝ=z”¶ûxºÌÂ9?Î¥—^šÝÚ¤.Ê,Ô\˜ ?:ø#ÂázïT1öäE¹Žxž—BLÓLk„Hj+˲¨T*uJ__¥R‰¡¡!ªÕjz“çy©Äq,ËJ *ù~‰¥¯¯¯.M¨mÛ>ÈYŸú—>öXºþÀÀ†aŒ™R´ñ#_CHœD€TÔ1 #õ4#•Ü` /ßĨ'©ÀDÌ Ã°.Ý¢ffˆŽ}ðÅ{ŸæËwÜÂyç-çw~§6Í–5M'!"JÈ5[Är¹¸®›F)‚ºÈüز¬ôÞ#z˲0M3,ñ;Ñ–ûå¾ÿ?/Ø4‹¶kÞxÏ›9ö¼¸!mç™Æmò÷·üûr/¢ˆ8ŽëÒÄÊ9,—Ëø¾Ÿ§{£h’GÎÿLdÿùÈé¡¡!J¥Rp“wÜ0 #‘$}cþ€´Ÿ+W®ä‚ .à׫¿Îÿù?ÿgV¾›ó‘8ŽyÊz ç;3–¾L¤÷Ú‘fÚ­©±OyñÄ ³œeò}±ZX¾UÖEŽÓl²Mã“NcŽl“?JØÁwÜ1gs>Ïì}†Kþʆ_šÄ†žžÇK>Ê®ë®ãªînnt]e CÞtÛmœõÿo|c}R?PbJOòèŒ"õÛߟâXI­N²‰ak™´M7|YUvRý™…‹ÓYûÎbÙ¯.›rÚ5Íã(<ºâQ–{ÁÏô×9 Ã:oqÉݯÑhf†8¹XGÀ‰'pxÿOí…蘺gt˜"»"$XX|÷àwSãH¥RI#4Äà$Æ Û¶ÓÈPž±RÔ[–I„jÞ»TÄ 1Ì4K³ÔÌ“j¼ôƒF›uûöá}á |æÒúê¦Ó}¨ãiìO¥RICy£™DÐ4tVUŠL<1 èï§¿¿Ÿb±˜Fþtww§©Ì4S'¬>_ûÝÒÛû>ó™wÌu·4 SÏ< 'ùèD©T*©R­Vë®Ù÷1È·B³û“܃šÕ¯ƒú{Ïd®é“M»5Þ}r¬ýÊ6Í"Lòé5—çÏÃT¼Ÿû:Ñ}¿1Š¾Ù±Ê²±Žµ\.§EÁ­õúázüÌo¥øžU ÿu8+"|žÆ”\AP,NSYI‰xy>±ñ ¾÷½ï±žõxžWçy*‘%"šˆ°.ÄØ‘7rˆˆ’OÕ‘O©Õ..ýæ7ù·¾>øÁY9×yàR©ÄÀÀ…B!='}244¤æcɪÕ*…B!õò/ ˜¦u uÛäá‡æWUÏ]4šN¡Õ*!é­$Ò°Z­¦ÑŽãèºÍ qßêû¸ðß/„ŸŸëžh4š±ˆˆXrÜäôçóàÅÃå| P¦OÛF;Ïjæ S.J¿yófFFFê–uuuqèС99U˜¬{n\0ÆJ"\ä&­QáNñWßøåÏ|†ó§R`w,ƒ“m'û •¹ÑÀ`JÜ1 éâºÙ:‰÷ç¸4^hûnYJð™¨ïyq£1Š&в÷EÀhœøû~½ô¢?ˆáóEø Ó\Äh,¤Ñ슘ÓÌ€%‚“¤\«Õ”Ø”Ë|?ƒ¤½Æ¾ôô¨åb(²¬úó:•È"M=§ÃŸ<ñ'T>ö±´¦õDHê×u)‹ è”2M»X œ¦^î[Å?>ú4æšçÚ™ÒÝÝM*VHíÛ¶Ó4Q¥Ø«Õj]”Z¥Rà’^ÂÞðÜËÝ45ˆ´éºn*LTP~Î1 Ö®];k÷›üùèïïOS£ä#|$}I£ÁO —ËeÌ àï7là¶ü ݲ¢ÆÏYÓ"O¨1qæ™{y×»&ŸÊV£Ñ´‡V¼Æ+• ¾ïã8NúÛˆR4š™å‰%OðG·ÿ\ÇÌçš#‚Y©Ù¤ÑÌ&‹N,yb o{ò_G½—Oƒ©Ñt2- *+W®%”4 açÎs|8GŸ>Ú<ijRQ†wÛ®5$‡x¹\N½…f·ËFæõéºÓ7¢LÅsv"ëv* C£¡;ðàjg´è#L¤:O´ßV§V,÷¹\ócR©¨ÏÈóFE}à¶Ûîí¸“”¯“à˜Ñ÷cY¯3 (x9‡aH¿~èÔhÚÉ#`,ÿr8í¡ugF˜›¯jÛîâ8Nó•ÇqL©TJk˜5¦ß* ¤kÉq.i¬ à H~Ì&Ù¨ÛQÒ6&r„hõÓ××—z…‹Eúûû›æ®C!Àž‹/æÐ¡Cl¿à‚Ô9¡V«ÕåâO#]4-ÎZ±uÖY¿2×ÝÑh4-OéeÃsp-×,L,¬¦sM=Ÿøþ'Xyhe[ŠÑÏ%:õ—f!²èÙEœ~vf’¿É& Ñt:- *×^{-Û¶mã®»îâÚk¯mºŽçy¬X±‚Þ92,ÇÄNþ{`þ—Ñ+8NÓTâßÓÓC__ßÜæü^H&p †¬F\7‹”iLËüÍÍ7£å”±9FŒqÈüûRì×µVHRÇØ¶Ýù^åÍ<&  |˜›`ݱc¼¸üÌÛÓ.ÝÕHwww-"…sÇÁó¼4åIÇ8ŽƒïûéýX Rù4`º>ÇÌ“÷ –è)’A$ņe¹mÛ<¹l÷üìÏrçAQ$FÅ p]Ïó(•J†¡¯é-bý»}øƒÖ6ˆ¢ÌD¢wgtšWÃPÇy§”ä³Kß³íz§I+Î0¾¯¶,:º¿ô¾`´M¡¥…Ñ‘ÁÒ¾m×Ϲòõ{$Z:ÿÀ]©¨íØÅ¢ê£e©}ºn¶]©”·ãÔGåÉ9ÉS­fÑÑr –5z»0ÌÎeµªÖ)•ê'ïH†õûëëSïÕjj›|êÝüçEj;I­+í˼U~ÇÚ®ñ¼‡!ø>Wß{//jg¡I†!Åb1·êëœf&1’ÍøDQį˜ënh4š 8zŠú{Ê õ"_e@žCtÚ/M§Ó’ ÒÕÕÅM7ÝÄÍ7ßÌM7ÝÄæÍ›Ó)X¿cÇn»í¶9;%˜¼íÑu™G‚< IH¢(JÓ\htqØ„®i·Ôè‹ù´¸hÉZ cù‡[:•¥R  .mF£i66ñà|øÌ?þ#¿±äõXÖÌ•›Šc«LŠe‚\«ÕÒ±bx’º'mýI/)’MÓ$Š"ÇIÅÓ4S!%Jž|jµšŠö­V!)´lÛ6Åb‘Z­ÆÐÐPšÎÍ4M|ß§··—×¾öµs}¨Ëà¡«ë5˜æ)£ßqAjì gFó È ëZ¶­Þãú4¸R‡/šGL÷÷Cww6¡f¼{´m+¡Ñ˜ßߟշk6GïîV…‘u¬qœ B5S@E¦[V–j6/bı/D€Ê“?'yqGúÍÇ«|²/YÏq2¡Å4ë÷'ËÊeuò9Èçeš™(”Ç0Ô:¾__#RêÊû)E¤)Õg*Ç‘¬¿;ŽÑIæšóؚǚ.—ÚQÓ*¢ëíKU¡ž“ã)ì#J¶k»|›A²Ÿ¹¿iN2¢(âÈÚ¬Èõ¨ú¹"x«•Õr?åš)5X;DÕÑ)š…Ⱦ3áË—|™·Å*çtww~Jjif^Ðr •­[·²råJ<ÏãöÛo¯{¯««‹íÛ·ÏYtŠðÔñ..:|a¶ VS7É&ƒQÒ…hƒm›Hœõý_`üó*ÖmØ@÷¹—N¸¾ŒO]3¥³‰ˆ00 [Þ&$$f uªš`&?:¯ðô _©þžöAφߟö3¤Þ%µW±XÄu]‚ HÓ>‰h¢rtȹù¨h žžªÕ*CCCxž‡a˜¦Y·Ž›óú¢Ó4¹ùïägœQ'œIzÕuëÖqÑEÍõ¡v,ÑøÆóqäÈxã±»!\V?ŸÈ^û~öz¢t©ò~ØpÝ–¶'Ú¶VËRçN4¶íLDÈ#Fþ±°¬±SØŽ%8V*c§yëØ$âf¬6ÇÚNþŸè\5[6Ö6"¦@}½EI <r.MS‰Wr&2êK ÇB¡>m¯i‚i²ûþûµ 2Geà ÃP¥© ÂL´¨[%8„(Ñ!F‰V²®—,3ɶ—õü†¶€Rò~?P$Jb”c[D&‚Ø m¬#ÏkÕ\²'Ù—ôÙIÚÉžïú’~HIPZÚŽ•lë'Ël Öp~òm¸Éºùib¾ 9Þ™¸cåä|†I?£äØòS¾ò:ÿYå·³“å>õ}•íŒäu)ÙÆÉý r¯óŸ´ã6釧l'çÝÊ3Y'„sWž‹flöþÊ^ÖeâtþšÇù¼Bõ†¡ºŽJ”'ŒŽ>”ÈL¹GåïÅPïì ×çüþ=OÝGE$‡ÑéÇ …,²0þüÈ™¸Ã,Ô²ê#!óûñý,23a Y”¢´!Î ù{oÖ‡ È}#ôCÞoŒŠM¢ëœ'ïƒâÜ ŽÐÎ"påiÖWiCÎkã~‚VßG¸~î³Óû]Ý9‘s5žsS~?ó1­p°øExäÔÿàO9å×}=lÛÖ 4ϤŠÒßtÓMÜtÓM ¦ËV®\ÉÆçú8ˆ‰9óøq¾ÿßg2ïƒ1B‚ Žc‚ Ð!Ùí@&ò púÈ"6ìÞÍïzã=â‡aXW€Z36Q2À¢Ü@‹‰Ç7"¢:1C^K iKþÏ¿?^š¼a!&žTJ kÊ) BBjÔˆ‰±±Óö´È2I.{˜÷ÞKøKgO»9?1ðJ $‰PÐ÷Û)F?¤O““›yòµOÂ0$Žc\×Mk]Ù¶M­VKűB¡Àðð0oúÀà¶Û RÁŠ«W³*y8ºá†¸çž{æöS¶ù7í›Úñ˜-¬7ѹ0^[ ÿ7½Æÿ'º<5k£Ù¶ú2×:}}Ó»_'¸O58“°¨þÙ.¿›(Âr,&ŠÂ€‰…¨?ÇcEfND¾žÛX}hÔJ_«ÕDã.4o¯Å6ÆãÙ‹/fÿ3ÏLÜŽ†E+ öž¹Pš™”-å˜§í´šùÀ”•NdxᩳٴoS}ÈàH^pîK£é,Ä£}> bGLL€òœ Sc¤¼Ÿ7rZX£ŒÆ( ·eÃèL0Å”F¬äÇi°@¼ûßÞ ×Ïuï:—Ž«àY ¶é-ôLò«'i½â8&Š"*•Jšâ)Žg&½Û\Ñ(zÈ8òb‡Œy`Ôøm>óËëÖ}â ¼ŸèƒOSM¬+‰¤³Eš®o1üŒù3üóÎæèeGÙ½a7ƒ ò¹—?Ç‘[ŽÐ¿¤ŸOîÿ$K-åømÇù…¿û6lØ€˜ÉõoÅî[Wž62ßúñ+øºwh®{¢Ñhr<³ò™ôz¾ë»»Ø»w/KþiI½‘]Éj4sÂO<ÁÓïx‰WuH Õ™b!<«i4u<ëÎRζ’åÍ4#|?œ¶ÞL¥×h&bÁ*/—<ô矾R&H•ÇñÉ[ôV£™E޳ï¼ý¬||âukµZÇÕM‘¨1ªÊÿb¯mùqq 00F÷5³Ïò§–Ïu:š˜ë˜o€_þgøçÏý+WN®Z­FdžmÛ u\˜¶D‚A}Ÿ¼X"‚HcŠ»¼˜1JaziëF±3À®½¬ ÚYÆ€f¢ŽýެÁހ⛊ôõõ¥Î*¿¼ò—yö›Ïòð)³›Ýi$Àâó–`î…¢NäñË.ÃØ ß>ýE–~øÃsÝF“ãÀªé}`÷/ïæý—¾_׌Ôh:„åO-çÂ+/œ~C9$ûWcv,y-¾CRV#вLW–¥2IIy‘Z-kËuÕrßWë:N}[’‘ë®â –PñêûT­ª>4 6ñ<"mç3€i4sÍQàØácØû"C¢Ø"ŠÀqbj5Ú‚JH¨í0šYaÁ*KŽ-áðE'\OòO AkLÍèûY-°ñÒ5ù›¥F³9øBĉg,LÓwŒT*úûûçiSDkæ' FPÙEÄ%Çœ³áÜ ×ãxL£Üt䦆êæhYªFlÞ› TÊnŠa˜Ý\AÕ;óñIã”'?­Ëû 6&K±¬Ñˆ‡ÎW¿M¦RÕª:.©§.Q-r\Ò×|Ÿ¥""ÍÓ)§fóï]ɪ‘a°,ŒH"ªÂ¦NXM§²`•— ¾ÿ׬ž…4OÇ1ÝÝݘ¦™m£( ×¥ÞËMÔqÔëZMÝ”F;ÊMÈ02O€(R¯}_ÕCó}x<øïl®î§¿²>½ÉÉÍO¶Ë÷ADœ‰È¯+á£ùTiC&㆙g†F3cœ]»†9ÀøßÁr¹Œ; 3º˜8õb÷ñ±°01±±g½v‰FÓ ìZgžþkÖ|›0¼ºå{@†iáù¹6˜›˜TÑ“ïNB¾¦iR©Tê¾#¾ïó ¿ð ÜrË-sÝÍŽd×Ù»ØqÉ>pÞùÀ‡æº;&džÝ019ó7Îä ¿ò†¹îŽF£Éa¼À9?(»H¡P!Ò߯l¦­&5ßçK&‘(Rö&ÃPÇ044öúr|å2‹Y$ïg6#±i‰Ùy”6$GpÝÌÁ¸¯oj篛Už8Vû{œfþ`{%Ï+1ÈNÇqˆ¢ˆ(ÿÅÓh:˜#¨¬Âä-O>°uÔ{ž'ÂÅ)¸®‹išø¾™æ·”ÐÎjUÝ|/Æc9Ìç=,+[/ Õo^€ùj¼—+ì†LÕ—r9‹réïϹé YZ1¹Ùå#cd_¦™ 2µšZ60 Ö·mu3ëéQÇÙ×W/Üä#h¢(“l»>,T<:LSÝh}?;öBA­S­fa³"H õcYúFwRr*œóôwxE÷J~b ½d¼¨±™ÄÀP5#E`5';ÿIȾUðÞù7âÕÏñHÜz„ŠŸ\ôu "7á†eY„aH±Xd``˲xÿûß?×Ýêh~eóêpú i4š™'†'°áí¦ßV£Õ²™Ëx¥’½–|@yïi#ß–<Ä ùT B£p~?0úž$ÖÚ<ûÉ¿ŸïKzî’Ã|AŠfûÉ¢€Ñ²É£ÝX$¢ñ¼Ê:ù‡Qé‡ÏéïkžÆ‚mÈñ4öUrDIn›‰úÚØFn?ëŸyMs–]¸ L3S\7‹D‘¯ÐB›fMuêhšÊ>$¶«j•4R]e¸4ž»Æá–wæ±ElSbêëS—¡0T¶¤ü°ð}eß’tk}}Êž•‚,%šˆ;Q”Õ©çbÛVûðýl8;Nvy©n âgß ¹Ô€ú+Â’³8Cƒê¿\6¥ßrÉCøìg/Æ0žë¯Ä¼àè‹ûØ{þùä+Õjµ´&§F3X0‚Ê`ćF…u”JÙø–[¾Ï[ÞbE.A .’"RÌdT†eÕwÃq tîì:qƶ3§RÉæšå²ú•‹»ˆ5"dضI$jF.æCCYdÌÀ€j«»;;Î0T7&éƒlS©¨›xôôdsãBA­kšjß•ŠÚFÒŸI[Ò‰Ô)—Õ~ƒ@mcYY4¬#…Ô2E:»ÙÉß|x®C>ÂG¢sÄ»"ÿˆ§…Ì[Eð‘pÞR)[_¡jUõMæèî+ç&¿¼qέƒãpþÓgòŸ¼†ç‚ÑψQÎ,„FYXô3»)Å4šNf˜˜eÇl."~ó¡›Zº¦…aˆçy¸®;ç54óƒrâ…144DET*®¸â {ì±¹îZÇrj ¬žë^h4š¦„0xl’•{˜ËUº»[ý5 õðR­ÖO†%WÏx^g*¹|ÖF3nyH‘ ´R•ºY®¢Æÿ×iìw£8ÐØ†~m%ßRc›Ò†XjÇTòÛ4ŠyÑ¥Ùƒ›X’å¯ñ!^ú*ÛË9j´$ç7Ž› *ù~4¶‘ïkþ¼±ŸËMs–žÿ0?žÚd¨é² ÍiüÊËW7Ÿ.,Oþ<æ¿æùíš½™>šwØ•,+1$bŽadö,É(#ö%Ù‡\åÒ iûeýjU½/—LÙGÉ|;ÎRðGQf{“>ɺҦh«¶­lHqœ¥[»PÁOýÔÓ,^üŸÀÛæú£íh§¼‡·láa/«'äºî´£Sll‚iµ¡Ñ´JG *{öìaÏž=uË6mÚÄŠ­;ûáëþϧ°²møÜçº8ÿ|3úè„h‰Æ>äç×ùRþfgšpà@öž0úƧònfÛ‰2ßݽ×òšß¦qî-ïåÃHå&(ý«Õ²Ú3Ò¾eÕ{.È\ßq2…J%»é‰X”wú‘¾È¥R‰jµªÅͤ1 ˲ \.säÈ‘¹îRÛ™êØÜÆ®¾z?ZUÑhÚÇTÇçÁ/äÈÚäú%‘R•º‘üƒU3ZIw;Ñ:cY?ó´rÏžÈ+¸ÑÈßξNÔ߉ÚhÅm&úÚÊç7Ã}ýÊ–-œ º§4>ƒeéÚ †d?Æú|S®åuÜñ›üe£Ù¥8ow“!×ÝiœÍhÖf¾ßùíÊe|†ÁÁ¹=ϳÁtí¶Ýõß9÷§9õÔÌîV©T%M£™t” ²mÛ6îºë®ºeÛ·o§··wÜíB”Uû¥S~/]&sÛþþÌéäŸØÍG?ÚË<×G:š¾¾Ì±©ŽúŽ“…]¶B+Þ?v YJ1YÞ¬]‰Q#?çlìg£…8uÁè¹j³›´D¶4:XÆèí¥"B‰·B¾ï==pà ‹§÷¡Ì¦:>_<-ækk¯`õ+ÞÙ´Ä»R4šé3Õñ À°æ©Gøèïîæ£_P1 ƒr¹¬sÛj¦Í 7ÜÀàIðÔ9•±yîáÃDÇÎâÜsÏëîk4 š©Þ;7 rhñ¡ú¼ÆÍòFk4š)3¥ñY­ây̓´4Èl‡¥„ÓLŽi=w»øÆy?ä¥Ç×sìX–…Ç0´]H3¿è(AedddRQˆ‰9þâëxþôKÓeµZ}ĵaÀÑ£KøË¿\4ׇÙ‰¦h7Rk¥ŽÅSÍã9U/’ÉL˜DìñýÑ‘9í£VSߣ|íÛ†Ç[33'®Ã™êø93ÞÚ4>Š"jµšöDÐh¦ÉTÇ'§àöäGߺŒ~tüUƒ À4M¢Ñ´ÈTÇæÀÙrþÈ9sÝ}fA3ÕñyÑ^ÄsŸzN=LæB£Ñ´ÌTÇg>S†FÓHLf<ÊÛu4­3­çN`=6o}ü2þþð œqFæØ\,ž(ªS£é :JPäÖ[oÒ¶g{™_õ"E ÈRòuúÓîI¯@KØb;'a¨¢:²è”v ‘"­D…çiL±;"ô4‹ì©VaÛ¶ÝÀºöh‡0Õñ¹›G–?ÂÅŒvÜÓ©¾4š™aªãs!kÙå¾oŒ´¼«s(h4-3•±ùÔòå|ß08®;¯Ñ,p¦zï\º©.š«Ñ´™©ŽOI/®Ñ4ÃB;…M—éØmŽ/üOírX—ùÄÓ§NÆ«s%?!âèD똘ºéÿ¸ógô8:FPQÆœ[n¹…ÁÁAV¬XÁÖ­[Ù¼yó¸ÛíÞ½›OúÓœYÚÈ‘ÅGÒÈë¼`ày¶mw¼Gm0 µ“#,ڜ漰Ò$¯D÷´*’LÖ(ukLlÙ²…Ý»wOYŸ/Lu|~å+_adëi¼ãñ3y¹IÍIÏó´·»¦-ìܹ“mÛ¶±ÿþ¹îJÛ™ÊøÜ¿?[¶láÙÛŽ±ö/M}´+¯|÷¸û©HþCfšìرƒ;vpÑEÍuWÚÊtæ¶ßûÞF …¹>ÍɈžÛN<·í:ã6_šëCМdÈÜv÷îÝsÝ•¶3Õ¹í»ßý?¾×½´Õ]iN2 Ú“šQÏm'žÛnÙ²…­[·rüb8úýã<4r>ïz¶N3â¬BÒLŽfBÇXG>}^ãú&ch Œqß711’Ÿ‰°™ø;³mÛ6¾ò•¯ÀïÎìùêAeÏž=ôöörÓM7±}ûv¹ùæ›éêêwBÁpï¿ø{N{ñ/ðýkˆ¢úzåDA0:8¯­e©4T Å›¢ZUi²Úm'¯T$ßbû©RgsûöílÛ¶­ý;Ÿc¦:>¯¿þzÂ翊=ìóÖÚëÄ,ÏóˆãX‹)š¶°qãF¶oßΖ-[æº+mg*ãsÍš5lß¾³0Nƒ(2)V¹Ïóp]·£ï£šùÃæÍ›éêêZð5T¦3·}å+_Ð)K4s‚žÛŽ?>ßû†÷ò³ÿö±¹î¾æ$DÏm'žÛ^ý§ÃIîL£™ôÜvâ¹íöíÛ•Øqžx~PïmN&ÌXXÔ¨Íõij;!a*6äÅŽFñ#&õ¿AD„‰9JüKè°°F‰vò3غuk[ÚíAE&Boo/×]wƒƒƒzH}‘€E‡óòÙ*š Q”èéééø\|³% ̳%9ŽúÌÛm“"šÖ9Y˜Îø<ý ^úÊQD†aà8ÎŒÜ85š“™éŒOëïklܸ“r¹4æ:Qa†T4šI0±yöÙ‡&•žT£ÑLŽ©ŽÏu»Žqpq7'GEfn˜êøl–¢[£ÑÌÓ}î YtÂàÌ—âÔ©Üu! C¢hâ4OÑ®¤v§¡¹"‚Hþ8%šCŽ_ÄMLLbbî® tŒ ²gÏFFFظqcºlÅŠ-où÷/am×Ù8ÎèÔO’‹/$SÁ‹ã,Úb!ígSP)Û»ÛVéOf¦5>_8Áÿ<úyîiHý¦£S4š™a:ãóði!/†ðÌ+ÿ„0l~Ýö}Çq´˜¢ÑL’éŒÍ½{ß1æ˜Ôh4ÓgªãsÙá'9pÆ«µ ¢Ñ´‘©ŽÏ(Òé5šv2]»-À±&¬X‹ãPQ6S޶­Ôߘ-$…V^(‘TY"x"„ˆÍXD-„t.§Îu “œ|###Üu×]tuuµ´ý‰S^楳^¢X¬ôÃZ‡XÃÇËågšªÖÈB©ÏÇê˜ÚmóÖn,KMÐNV¦:>,>/¼È±SG_jfÂA£ÑLïþ¹ü%‹ƒëV³jÕª1× uîfJLul>þøã?¾L‹)M™êø¼ |”gÎ\9×Ý×h4SŸ¦©#T4šv2]»-Àâçá¾C;ê² Åq<#õS K_SI~ ðñgô\DDÉO~? tÓî3 &NSdU©2Àà 3û©R¥L9]ÏJ~4KÇD¨lÞ¼™;wrã7ÒÕÕÅ<ÀæÍ›',n°8sÑ |þéËG=|š¦™ÖP™K Œ ‹#-$ç_ËR…ÜÛÍl¦Ã˜l1û…ÄTÇçckãÅï]Êþ%KF½§S}i43Ãtø"B¡pJÓëiww7årYG“i4S`ªcsùòåüÚ¯=\1ׇ Ñ,X¦:>¿Ûu%O^xœ7Ïõh4 ˜©ŽÏ…✪Ñt*ÓzîLX Œ¬þ- ‹P‘ôÒ3E… !!V*PȲ‰jäëŒH´‹¤ãRÄÄLI­U¦ŸqÏ-YÃ#¼jÔ{QQ.—u„ŠF3 ¦26—/_ζmïá7s®{¯Ñ,l¦2>ï|ýãŒ>1à%Ç#Œäï|&NŽ!ïjóÉUÊ`âÏK0©ÿÌÆÚÖLÞ sëÈ9ŠÆØÆJ–ÇÉöan›±f_ñõ×Ïõ雦:·Õh4íe:c3&N­ÐŽ“9a†1c|1qí! 0€‡‡?ªp}cqö|[‚Ô'qq›nל|t” Ôåâk•}„œûÂ[xþù3ë—Ç[3*B%¢(ê˜:dÍ|e*s[¦ÑÌ“ŸÏ<ó †aP|2A†l+¾d‹"È›Ÿ¢N3àu¦òÖ}X&íZ™¯iª´Êqƒe>¿ŽmÎ ÷÷(RÏf¦YŸ·¾•ý†ú•Œ½²yÖ“tϲ]ãúB¾‷'ÎŽ7¿iª×q ÄpV¬¶1ŒLœŠ#Ø“ü]–ÛO·ß á5&œbÀprlOk'LX ¼AWrNþ_¨Þ{µi*Qã_øÅdý¯F°Î¬ßN>3,x$„BÒ‡µ¨/ȳ1¬Žá­ çäYààÉvLÖ?ÃI²Ÿ»C8 ø>8©ïì|f*÷OFÓ~¦:6ÿ…Óž9…Ÿíùa˜EbW*œò`®ÒYß0ŒTP‘ÏQ¶5M³î¯mÛxž7ê³ð}Ÿ·¿ýís< :—SzzX²d U”±Ý÷•Q]Ä„r¹Þ¡,o#jÅ^Ô¬D+u!òë´²~³©x+Ûå¯gb?–Õ¼Ne~»fç­•©I>Àv¬õóÑÍŽ'¿ï±_&:÷Û5kg2ÁÀ[¶´¾®F£ÍDµ5mä9Xòüažaij'¬ÕÔÜGgÒÌ7„ Âñ8å?ÿ‚(úÃtQ†A@µƒ*“ÅÄcÖQ‘||ùÂGy"¢¦yú¤`’¼–¶òï5.·±Ó~DDÉO~?ÛL–Ÿ/_LXìbŸñ{[ÚÆÄÄÀH‹=µ‚……1©ú4â0™ýØØu…¨]pjb¯{ŒŸ¸|UúÚë]£é^€U«Þ=Êx†!®ëj1E£™–/Š™(1&ÆsÏóp]—R©„뺩a^Œý"‡a˜¦‰eY©Ðâ8–e›ŽA¼ óʼnÂ0 lÛÆ4ÍÔè/û2 ƒjµŠišé¶ÿw-Nò²JTzc?š!5Üׇfû“c—me¿²m+Qñ²nã¶²¿fçWö'ë´r|‚8—ÉóPãßf.®ë²mÛ¶ Û>Y¹ðÊ+¹î¥T*ÊŸÔÔNdFÓÙXXøøuv´©"6³ƒãgçÄâs}ˆÏ¢ÔÝ/ÇѳšyÉÂT^|‰µ§^ÈÆÜ3<´u "Œeø÷ñ`€š?¬F3PÂ0&¦B%"Ú±Ÿ˜˜ûý·†]ü–õ3cO#"V´~)•……‡×òvT¼½Ý$Ëq³kHHœüøøuû‰ˆ¸ß¹ŸÞ½½Ó:g •Ã+³¨ë‹—¾¾n¹6Òj4sϳÀ žbùò£<*Å[\£ÑÌ>Ë—?Åd9£(J$RÃ÷}úúúRAC ðã‰"b`#¾ü?ÕÈRR&ÛF'Íá5š<vïæÎ$ ”žÎj4š±È;/ˆ£Bž(Šˆ¢¨iZFß÷Ó{¦l†!†aÔmcÛvºŸ|ŠJqZ×ÛHû2oÈG7¦ŽÌï§•m$êu¢mòN òW>òÇ%ç"‚t]‰ÜÇÛ¶ëŽ_Ú9xßA.ÿÐåüÑþˆk®¹†»ï¾›×¾öµóÔʇ9ôÕ÷ÁÙ8 ‚`Æ Ži4š©ó°b׳;ö1|_¥)õ€×I÷OF3š(Šˆã˜ Ò1+‘$ríKrÈè4›ÍÌ m?Íü%ÁY.—SÃ~£Q_R,zžWÙ9V II)©óë7¦tA£1c> cãÿÛ4û_ŽA„„féó‚‡ã8£ÒyæÓH6ë£ëº“Ú¨[žßFúAšjXœ1d‰¤•m$§AŽ" ä£o¥nØ»y7Ö—¿Den9`°¨}¶–Fæ6žsÿ÷5.áñpÔ6Ò·Ÿ2Š;w2rtd®¿ÞÍGb^õòy|üãKÓeº~Šf¾rʉ'æuLÚ–-[ø›¿ø¯^ñ9îÝsEš¶Dnó ‰¶Xi¤ 01±°p™¼càáµ]„êN“aF?=mÛ¶ÞÞ^z{u”JžÁÁA~ûØv¾ûñóÈ×U>x™DiC­f¶Ø²e Û·oŸënt[¶láÈö5<ø•§YúÉð·{M.m Ã0Ru¦ 288ÈÖ­[çº+Çx×­8ŽS#iš©¢ÑÌ$znÛœÁÁA>ûÙgX²ä“ªyÑ鈇»\KD°#s>EßD^ñy«ç·/ù¼y¾yïÔwªÕjuèbdÍ÷QÚkôt—6šuó†gi_jCIbx–ý6nÓ¸?ù›ßŸl›m›÷°o¬9%õœLÓä÷~ï÷øú׿>×_›Žc¢9éwORÃû¾OÇxž—FvækVuÍê5AÏmÇFÆç«Ÿ)pÎÏý;þòÍIÝe(Š:ªTƒfaÒŽ¹í‚ˆPYñìY8íUubŠŒœO4KA5_qp(Qbˆ‰óIO‡vŠ5yú韑”k'Ϭ^Ä‘S—¦cSG§h4Ä®g9qç[ùéŸþÿÙ{÷8IÊêþÿ½,÷ËÎÖ²ÀÂ2‚5rÑY¨qTP©–[â…X½~£6ˆ&»ã/FÃ7ÆnYcPcÒ½Æõš°S ÑD`qJE #â ìÀr™‚e\`¦v‡ËîrëßÕOuuOÏLÏ¥§«gÎ{_ýÚéº>U]§žËç9ç<]ÇVÄAˆ'žçaÛv˜sD„Ö0×MY5°ïº}tvt­(aÛv8Ð_(H&“ ²Ùl8 ¯Dƒèlm5“>“ÉL&éïï÷±m]×ÉçóUâBôï|>O¡P¨š=®Bð(¢ežhF}í,òÚèÊ ¯vº¦è¾Ñ{§¼öÔ wµ{¢×‘®ëzÕ=ªfÁG…Ÿè>ªocFxŒè¬yu å¡ÖG·Që'Ë9·„Æq‡|>O.——LµwU˜[5!w*ÏNSa†w=´ž„ÎTïùɳ€`A šB3‘Y|Sï½eÛ6ù|¾¡Äç‚0[¤m[ŸÙ¼·”w™iša!%h(¯‹hH j@]‰jañ"mÛúÔÞß÷CÛŠ S‚Ð,¤m;1Ê>;žéâÄ¿òÄmo‚ü)òK˜ÄC¥/v¯<|(«Ví^ƒçy$“Iép B ØwÈ>^}ÅÿþB ‰ "ñ`ßÑG°kh%Gœ?.ó}_f¾ BÌ(‹hš&m[AhT¾å=’N§éëë CZ©Á#õmT…z^¢Ñ<‚ LM­W“ 1`¿#8ã±!àm26$´5m/¨üÖ8”¥;xãoÎCÓ´¶ õ% •Ãö½ž¿y>üÁ@­Ø¦ ĈQx©ôþðÙá"BDfñ B¼é‚¢a°R©ÃåÌõꉞ óC6›IB‚'\Ø¿ë0=+\¤„OAhGökufËAKöã€ZËqÇý>Ì€£„xpÂö“8úÙ— .t±Xlu‘A(³Ÿýz>ü®¼Sd&Ÿ ćžžI<ûò2yåD  1ãåGVqäÑ#@0CÈuÝVI„…BAAˆ)Ùl–L&#Þׂ#ÇÁ¶m¤„òø£ ñ© ‚ŠŒß íLÛ'¥x®T÷N1HAˆ[^~;‡.{™|>H2NAˆGóo0; $_&“iu‘A(“ÍfÑu]êMAˆ1"x B¼ðï‚cöÀè×/àñW"ù„AÛ{¨Ü{Üqì:ì…ð»T ‚~åNyÓX–%3ø!f¼øu“gŸ=€d2‰ïû­.’ eTNAâG>Ÿû„’L&[]A&à'¦Çž;W“H¬À÷}Úž¶T{ìurÈ^ÇAÓ4qï„qÈ!sòÉG‘H$Ä6!fœøÐñœ~z'®ëÒ××'!&¼ð d³Y©7!¦ø¾/Þc‚Cr¹œ´g!¦ì~ä>{Ý÷9ó̱m»ÕÅ„Y;Aedd„FFFÚþå—dõêð}_*OAh2ÓµÏ5k8ûì¥är¹V]<ÓµÏGï_é§H>ŸïAh"ÓµM@fí Â<1]û|ðÁ¥Ï)óÄtíS„NA˜fÒ¶}è…ݽõ|ßÇ4M©K…¶'V‚ÊæÍ›¹ôÒKÙ¸q#—^z)›7ožrŸC}‚tº ×u%Š 4‘™Øç9çœ#‰a˜‰}¾øâ‹¬Ys(¹\N: ‚Ð$fb›x „„y`&ö¹gÏ„y`&ö)Bó™©m>wïjŽ|öplÛ–*‚ VIé7lØÀµ×^Koo/CCC\zé¥ôööÒÙÙ9á>Gy$¦iR,[]|AXÐÌÄ>Iª+óÀLìsõêû(ïA×u™ /Mb¦u§ Íg&öyúé§Ë$>A˜¤þ„x2Û<ꙣxáç§rüš}ÁDXÄÆCe``€ŽŽz{{èî»›)÷Íçó±5È 6´º“244ûÙq¿‡‹™ÚçÝwßïû±õP‰û³µyóf†††Z]Œ i‡÷Çb`¦ö¹iÓ©X–K1¥ž-yS1›¶íB`!=ƒq·÷FYH¿ÉlYìö)ÏtüX(¿É\°˜í³ÚÀ²Pžé…ô›Ì–™ÚæÇüðÃ$“IÎ9çÎ<óÌV_Â8âül)äý1svìØÁ¶mÛxÕ«^Õê¢4•™¶mï½÷^’É$gŸ}v«/aVÄùœ.q·÷Fiä7‘¶íÄöùä“Oòƒü€mÛ¶qê©§¶úfÅbz¦Û…©~Õ¶ë¡82›¶íêÕ«Ûúyh‡6p£,”÷L#¿‰´m'^wþïƒsà¿ó³ŸýŠ7¾ñ±Š{]Òï…8Ûû¶mÛp]wÎÛn±TvïÞ=nY#îœúЇèèèàu¯{]«/¡.J¹fNœïáòåËÙµkׂi5ûìííe×®]¬^½šN8¡Õ—0aãLÜËgžþy:;;Ù·o_«‹ÒtfbŸ—]v/¿ü2GuGuT«/¡-‰»}ƹ|O>ù$]]]¬Y³¦ÕEi*3mÛ&“ÉX·m%ÎÏàb½–F®CÚ¶cï~÷»cݶm”ÅôL· S]‹jÛÖ{vÒ¶],$ûœ iÛNÎeô!^xáÞð†4‡zh«/c‹éYmq¾‡«W¯æÔSOåýïÿœ76‚JGGǸe###twwOºß_üÅ_´ºèÂ"&Î/¹d&öùº×½®íƒ¡˜‰}®[·®ÕÅ„´m…vDÚ¶ÛçñÇÏúõë[]tAXðHÛV≴m…v¤YmÛØäPéîîç¾´{÷nI:&1@ìSâ‹Ø§ ıMAˆ/bŸ‚_Ä>!žˆm B…Ø*½½½ìÞ½;Lf444ÄÈÈ]tQ«‹&‹±OAˆ/bŸ‚OÄ6!¾ˆ} B|û„x"¶)bò `ýúõ\uÕU¬Y³†­[·²~ýz–-[Öêb ‚€Ø§ ıOAˆ'b›‚_Ä>!¾ˆ} B<Û„€%¥R©ÔêBDadd„ÎÎNq„˜!ö)ñEìSâ‰Ø¦ ıOAˆ/bŸ‚OÄ6!†‚Š ‚ ‚ ‚ ‚ ‚ B܈MAAAAAA„¸"‚Š ‚ ‚ ‚ ‚ ‚ ˆ "‚ ‚ ‚ ‚ ‚ ‚0"¨‚ ‚ ‚ ‚ ‚ ‚ LÁÒÏ~ö³Ÿmu!Ú•‘‘†††¡³³sÂõÓ^?— qðÁsÐAŪ|ccc¸®ËØØG}ô´Ê0Ÿ÷Oh?fcŸ­¶ÍFÊÐjûŒCù„öe2ûŒÓ³5ûlµmÆí ‡fÙm«žÇfØ÷|_K³êiyG´Íì“ÆÉ>gkóy-ÍìãŠ}¶Íì“¶âYhFß5NuçlË*ö9ž8Ü“±±1~÷»ßŶîˆ{ßxhhˆ‡z(öã¶ó>¶VfÄ5×\Sêéé)]~ùå¥óÏ?¿ôÞ÷¾·´{÷îpýu×]®ïéé)]wÝuUûOµ~.yôÑGK===¥[o½5VåÛºukÕ=üô§?Ýpæóþ íÇlì³Õ¶ÙHZmŸq(ŸÐ¾LfŸqz¶fbŸ­¶Í¸ÝCaáÐ,»mÕóØ ûžïkiV=-ïˆö¢™}Ò8Ùçlío>¯¥™}\±Ïö¢™}ÒV< Íè»Æ©îlÇß$îÄåž\sÍ5¥k®¹fÚå›òǽoüéOºtþùçÇ~ܶck"¨Ì€G}´tòÉ'—¶nÝ.;ÿüóKÅb1üý!·nÝZ:ùä“K>úhÃëçõ`D¬8”/zÏvïÞ]:ÿüóK7ÝtSCe˜Ïû'´³µÏVÛf#ehµ}Æ¡|B{2•}ÆéÙš‰}¶Ú6ãv……A3í¶UÏc3ì{¾¯¥Yõ´¼#Ú‡f÷IãdŸ³µ¿ù¼–föqÅ>Û‡f÷I[ñ,4£ï§º³“¸Óê{rÝuו>ö±•N>ù亂J«Ó¸÷•©žzå‹}·blMr¨Ì€‘‘z{{éîî—]xá…ìÞ½€:::èíí »»›îînZ?—lذîînÖ¬Y.‹Cùؽ{7W^y%Ë–-Ãq.¼ðÂ)Ë0Ÿ÷Oh?fcŸ­¶Í©Ê×Èú¹`2ûŒCù„öe2ûŒÓ³5ûlµm6rÄ>…™Ð,»mÕóØ ûžïkiV=-ïˆö¢™}Ò8Ùçlío>¯¥™}\±Ïö¢™}ÒV< Íè»Æ©îlÇß$îÄឬY³†µk×VÙa£å›òǽo<22ÂÚµkY¶l@ŽLÆÖDP™½½½lÚ´)ü>66Æ–-[‡khhh\Ü»ŽŽFFFZ?W ±eËR©Ô¸å­.ßÈÈkÖ¬aóæÍ¬[·Ž«®ºªê¡¬ óuÿ„öd6öÙjÛœª|¬Ÿ &³Ï8”Oh_&³Ï¸<[3µÏVÛf#÷HìS˜ ͲÛV<Ͳïù¾–fÕÓòŽh/šÙ'“}ÎÖþæóZšÙÇûl/šÙ'ïg¡Y}×8Õ³-«ØçxâpOº»»éíí­›#¿iÜûÆ^x!ëׯgllŒP¸PD컕ck"¨Ì’-[¶p饗ÒÛÛËÚµkŠZ%ú#Mµ~.㪫®âÚk¯ ÕÄFÏ?å UË+¯¼’ÎÎNÖ­[>¸“•a>Ê', ¦kŸ­¶ÍFÊÐjûŒCù„…A­}ÆáÙš}¶Ú6)ƒØ§0[æÒnçûyl¦}Ï÷µ4«ž–wDû2×}Ò8Ùçlío>¯¥™}\±Ïöe®û¤óù,4³ï§ºs¶eûOÜïIÜ~Ó8ö###lܸ‘-[¶„bÊTeˆ{ß}.Ê(‚Ê cݺulذ«¯¾š«¯¾:\WOýŒ*\S­Ÿ ŠÅ"ÝÝÝ¡«ØîÝ»bhh(åƒàA½öÚkéííeýúõ¬]»–Í›7OY†ù*ŸÐ¾ÌÔ>[m›”¡Õö—ò íËDö‡gk6öÙjÛŒË=&ͰÛù~›iß­°­fÔÓòŽh?šÕ'“}ÎÖþæûZšÕÇûl?šÕ'Ïg¡™}×8Õ³-«Øçxâ~Oâò›Æ¹o¬èîîfÓ¦M\ýõlÙ²%6ã¶­[Ae†\~ùåtvvâ8N•BÁÃVû#ìÞ½;Tº¦Z?WŒ±qãF6nÜÈÈÈ7Ýt7ÝtS,Ê×ÛÛ;NAŒ~Ÿ¬ óuÿ„öe¦öÙjÛœª|¬Ÿ &³Ï8”Oho&²Ï¸<[3µÏVÛfœî¡°ðh†Ý¶âyl–}Ï÷µ4«ž–wDûѬ>iœìs¶ö7Ÿ×ÒÌ>®ØgûѬ>é|? Íê»Æ©îœmYÅ>Ç÷{—ß4Î}ãÍ›7³qãÆðû²e˪ÎûnéØZC©ë…*®»îºÒùçŸ_ºõÖ[«>>úh¸MOOOéÖ[o-•J¥ÒÖ­[K===¥Ý»w7¼~®¹üòËÃóÅ¡|»wï.õôô”¶nÝ~?ÿüóK×]w]Ce˜ïû'´³µÏVÛf#ehµ}¶º|Bû2•}ÆíÙš®}¶Ú6ãx…ö§™vÛÊçq®í{>¯¥™õ´¼#Ú‡f÷IãdŸ³µ¿ùº–f÷qÅ>Û‡f÷I[õ,Ìuß5Nug»þ&q&.÷äòË//]sÍ5Ó._³Ë÷¾±*Ÿ:fÜÇmç{lM•pÍ5×”N>ùäqŸ¨^wÝu¥žžžÒå—_^êéé©zàY?×Ô>Xq(ßu×]W:ùä“K—_~yéüóÏ/}úÓŸn¸ ó}ÿ„öa¶öÙjÛl¤ ­¶Ï8”OhO¦²Ï¸=[ÓµÏVÛfï¡Ðþ4Ón[ù<ε}Ï÷µ4«ž–wDûÐì>iœìs¶ö7Ÿ×ÒÌ>®ØgûÐì>i«ž…¹î»Æ©îl×ß$ÎÄåžL$¨´ú7m‡¾±²uŽ8ÛÎ÷ØÚ’R©TšS!ddd„‘‘:;;ëº Mµ~1”O£££ƒîîîi•¡Õ÷OhoâþlÅÝ>ãP>aaÒÏV«ß³©;ãr……Ålž¹¸=³)ë|_K³êé¸ý&ÂìX(ÏÂlío>¯¥™}Ü8ý&ÂìY(ÏB;½gÄ>痸ߓ¸ÿ¦q(ßÐÐP +îö=Ÿ÷PAAAAAA„)¤ô‚ ‚ ‚ ‚ ‚ ‚ S ‚Š ‚ ‚ ‚ ‚ ‚ ˆ "‚ ‚ ‚ ‚ ‚ ‚0"¨‚ ‚ ‚ ‚ ‚ ‚ L*‚ ‚ ‚ ‚ ‚ ‚ S ‚Š ‚ ‚ ‚ ‚ ‚ ˆ "‚ ‚ ‚ ‚ ‚ ‚0"¨‚ ‚ ‚ ‚ ‚ ‚ L*‚ ‚ ‚ ‚ ‚ ‚ S ‚Š ‚ ‚ ‚ ‚ ‚ ˆ "‚ ‚ ‚ ‚ ‚ ‚0"¨‚ ‚ ‚ ‚ ‚ ‚ L*‚ ‚ ‚ ‚ ‚ ‚ S ‚Š ‚ ‚ ‚ ‚ ‚ ˆ "‚ ‚ ‚ ‚ ‚ ‚0"¨‚ ‚ ‚ ‚ ‚ ‚ L*‚ ‚ ‚ ‚ ‚ ‚ S ‚Š ‚ ‚ ‚ ‚ ‚ ˆ "‚ ‚ ‚ ‚ ‚ ‚0"¨‚ ‚ ‚ ‚ ‚ ‚ L*‚ ‚ ‚ ‚ ‚ ‚ S ‚Š ‚ ‚ ‚ ‚ ‚ ˆ "‚ ‚ ‚ ‚ ‚ ‚0"¨‚ ‚ ‚ ‚ ‚ ‚ L*‚ ‚ ‚ ‚ ‚ ‚ S ‚Š ‚ ‚ ‚ ‚ ‚ ˆ "‚ ‚ ‚ ‚ ‚ ‚0"¨‚ ‚ ‚ ‚ ‚ ‚ L*‚ ‚ ‚ ‚ ‚ ‚ S ‚Š ‚ ‚ ‚ ‚ ‚ ˆ "‚ ‚ ‚ ‚ ‚ ‚0"¨‚ ‚ ‚ ‚ ‚ ‚ L*‚ ‚ ‚ ‚ ‚ ‚ S ‚Š ‚ ‚ ‚ ‚ ‚ ˆ "‚ ‚ ‚ ‚ ‚ ‚0 ZP)‹8ŽÓêbuð}Çqp]wNŽçyÅb±Õ—%L±Ï…‡çyuíZì³½Û\i{ ö¸xhw›\ЂŠmÛmkˆ‰DbÎuqÃu]ºººÈçó$“IÒéô¬éy¶m·úÒ„i ö¹°Èf³ôôôÔµk±ÏöBlsñШmzž'÷¶ Û]X̶^»bŸñ¤UýR±ÏxÑ®ö¹ÐŸ¡™ÚçDõ§ôIÛƒvµGXø69×´»MîßêõqgÁÎXI&“d22™ ¾ïÓÓÓƒmÛX–Õê¢ BC,dûœ žç‘ÏçF×u|ßgÅŠ¤R) Ãhuñ„E„Øfs˜‹&A˜ ±Ýjæ¢^»抅lŸ­ê—Š} sÁB¶M˜™}NV B³Yè6)T³ §cgj»Úe†aˆ8C¤Ý[MÛ½Ø_½ëi½ý.vÛZ¤Ý[Mís¾û¥ÑïbŸ­e!ØçBo÷NeŸsÑ/Ú¦ôK[‡´g«‰c}9Óöì‚Ç--†‡‡K@)—Ë•J¥R)“É”€R&“)•J¥ÒèèhIÓ´R___itt´”J¥J@©¿¿?\§öíïï/išV.•J¥ªãär¹qç1M3,Çt¶ U6õw*•*ŽŽ–Kš¦…ë&»êzÕ¹u]ŸtÝdû4RÞF®»P(”LÓ ÿ·,kܵԻÞ|>_µ\ýFjßþþþð©TªdF¸Ýdû óÃdö9™m–J¥Ií³¶©ŽÕ ûœ‰Ý6ZÞF®}*{™ìZS©Tɲ¬R¡P(Y–Uu?Å>ãËlêÎèú¸Øg´lêûb·ÏÉö›È6ƒƒƒ%]×K£££%Ó4Å6c„´{Çß8¶{©ç&ºÞ™Ô«¥’ØmvïøûGûœï~i©$ö’}.ävïTö9“~éd¶)ýÒÖ íÙñ÷#ŽõåLÛ³ }wÁ*™L¦”J¥ª–éº^õpD`tt4|Ø …BÉ0Œª}S©T¸oTwR?lô{­!6ºídÔbt€£‘ÆW.—+Y–5îM¶n²})o#×­^ªBTßÕKo¢ëÍçó%MÓ&üÍÕ9R©TIÓ´ªŠq²ý„ùa2ûœÌ6K¥Ò¤öÙ ÛTÇj†}ÎÄn-o#×>•½Lv­ªâVÿGo±Ïø2›º³TŠŸ}ÖëX.vûœl¿‰lSýÖº®—¾wÂü!íÞjâÚîm¤ž›èzgR¯ŠÝÆi÷VWûœï~©ØgLÓ$—Ë‘J¥ÆÝïz×[ë­ižç…ߣnxQ·©öšÏdö9™mÂâ²Ï™Øí\3•½Ô»Öb±ˆmÛ ’ËåÆu]òù|¸Øg<™MÝ bŸí`ŸSí7‘mæóy ÃÀ÷ý0ì‚뺒h1&H»·š8·{©çj¯÷†n˜Q½*v¤Ý[Mœís>û¥bŸñ@쳚8·{§²Ï™ôK'j÷‚ôK[´g«‰s}9“öl#ûµó8Ñ‚T‰A:ÑÍ×4 Ó4);á§a+™,A’ã8ìÝ»wZûÌÓ4ÇY£/™Ú߯¶\†aP(Èd2U±§ÚOh>SÙçd/ÆÅdŸÓµÁf$=›‰½xž‡®ëU¶lšfÕ¾bŸñd6u'ˆ}¶ƒ}NµßD¶©¶Ëçóäóy<ÏÃ¶íªØÄBëvïÔÄ¡Ý 3³ÛÇ|ÆõªØmë‘vïÔÄÁ>[Ñ/ûl=bŸS‡vïLísª~édí^é—Î?Òžš8ԗМ~(´÷8Ñ‚Tt]§X,†7ÙuÝ*¥Ë²¬ª‡ªv]tvˆïûtuuµuãÆ4ͪûá8Éd2|éÔ[÷{¿÷{î3W†*ÉÜkÛ¶Ç)ªõð“Ùçd¶©Ö/ûœÌ'³é¹d&ö¢ì:ÚY´m»ªlbŸñd6u§Z/öoûœj¿‰l3—ËÑßß~ à —Ë-¸NJ»"íÞjâÚî…™ÙíÉ'Ÿ<£zUì6H»·š¸Úç|÷KÅ>ãØg5qm÷ÎÔ>§ê—NÔîé—¶iÏV×úšÓ…ö'Ú¿Õ˜+R©®ëÒÕÕ¾D-Ë ×†eYôôô ëz•º¥ë:™L†D"îkšfÕþó®ëd³Y …ÂŒöWåW÷Ãuݰ±6ѺÉö™+4M#—ËÑÓÓƒišá½N¥R Ý“t:®ëá̃L&Sw[uŽN8aZû Ía2ûœÌ6aqÙçLì¶×6]{Q èïk†Øg0›ºâgŸQÛldÆS=š}N¶_í@²M˲f|ÿ„ùAÚ½Õĵݫ®mºv{î¹ç²sçÎi׫b»ñ@Ú½ÕÄÕ>ç»_*ö’}.ävïLís²~édí^u?¥_:¿H{¶š¸Ö—êÚæ²Zv'ZRN³`p]7Œ³Uä|ß]†|ßÇ4M–,YÂèèh¸çyxž‡¦i-o쨲Ô^ÇLëãÔü‰ÖM¶Ï\__£÷Úqòù<ýýý8ŽÓôý„æPÏ>±MX\ö9» fk/óe×ÂÜ3›ºâcŸse›Ñ{Òîö)v¶°‘voýû—vï|׫B¼voýûû¬½>©W Á>r»·ö¥_º°‘ölýû—úr¾û¡íb NP™Ïóèé顯¯Ã0Èçó¸®Kÿ¼—c²DI¦i6ì65Ç™Ï2φ¨AÍÇ~ÂüÛTe™í³Þζ9ßö"öÄ>[[Þ(R Ó!.¶»ØÛ½bB-q±MU–vªW[q¾zˆ]/\Ä>[[ÞV"vOâb“Òžß~h»Øã‚ ù5º®S(Âxlº®Ó××7ïåP±ï&+ç|'n皬 3Q$ãªd âb›07Ïz;Ûæ|Û‹Øgüûlmyk'õ Ð(q±ÝÅÞîûj‰‹mBûÕ«­8ßDe»^˜ˆ}¶¶¼­Dì:žÄÅ&¥=;¿ýÐv±ÇEã¡"‚ ‚ ‚ ‚ ‚ ‚0SökuAAAAAAâŽ*‚ ‚ ‚ ‚ ‚ ‚ S ‚Š ‚ ‚ ‚ ‚ ‚ ˆ "‚ ‚ ‚ ‚ ‚ ‚0"¨‚ ‚ ‚ ‚ ‚ ‚ L*‚ ‚ ‚ ‚ ‚ ‚ S°« 0[®¸â N=õÔVcBžzê)V®\ÙêbLÈ /¼À¾}û8âˆ#Z]” ‰û=ܱcÿçÿüÎ>ûìV%Vüà?à–[naõêÕ­.Ê„ÄýÙzæ™g8è ƒ8ðÀ[]”º´ÃûcÛ¶m|ýë_ou1bÇ_þå_rÌ1Ç´ºÒÏ–¼?f_¾ÎÎN®¸âŠV%vĽmÛ(q§CÜí½QýM¤m[ŸÛo¿ÿ÷uÛ¶QÛ3Ý4ú›HÛ¶>qoÛ6J;´e¡¼gýM¤m;1ïÿûéééiu1&$îuI;¼ânï=ôïÿûyÛÛÞ6gÇl{Aåé§Ÿ¦···ÕŘ 6ð®w½«ÕŘ{ï½—¡¡!.¸à‚VeBâ~mÛfll¬Õň-bŸ3Ƕmº»»yÝë^×ê¢Ô¥Þ·Þzk«‹KyäÞûÞ÷¶ºÒÏ–¼?fǽ÷ÞËÈÈH«‹KâÞ¶m”¸?ƒÓ!îöÞ(þ&Ò¶­º' Á>Û3Ý4ú›HÛ¶>qoÛ6J;´e¡¼gýM¤m;1<ðûØÇZ]Œ ‰{]Òï…¸ÛûO~ò¶nÝ*‚J”å˗ǺQÛÛÛëòuttpÄGĺŒq¿‡zè¡­.Fì8ꨣX½zu¬»¸?[###¬Y³†îîîV¥.íðþX¾|y«‹K?üðXÿníðlÉûcöìÚµ«ÕEˆ%qoÛ6J;<ƒw{o”FiÛÖçÐC}Û¶QÛ3Ý4ú›HÛ¶>qoÛ6J;´e¡¼g¦ó›HÛ¶>qoÛÆ½.i‡÷BÜíý¸ãŽãÈ#œÓc¶½ wÖ¯_ßê"LJwwwl_ЏßC¡}‰û³µvíÚVaRÚáý!´'íðlÉûC&g!=ƒq·÷FYH¿‰0;䙎 å7fG;´e¡<Ó é7i'œpB«‹0)q¯KÚጻ½Ÿzê©sþJRzAAAAAA„)AEAAAAAa DPAAAAAA˜TAAAAAAˆ>àM°î§~åop<Õ˼òòf IéA„–á—?zä»MPñyåï"¨ òòbùï(j9¦ ‚ ‚0=²ÙlÕw]×±, MÓÂõ©T ]¯ßâ*‹èºŽiš¸®‹mÛhšF*• %‚ BhV é1~¬D‰ZçUc2j?­¼Ì,/Ë—ÿþW›ÁµäU>ÜâÀ?X•1›û\¸ß†u9Оgì¾ö÷áx ÜÁ?îy¼÷ƒpâ{ÀÙ,ózàý7À˧Ûé{৯û7ûá.s'Œý¼ÿíï,zwì˜Óû(‚Š ‚ÐJ¤Ð*N‡ ¢ô#ßu*©[^gˆJÑ"ûÔë‚å}4*Iš@h‰ 0Fy™:žVÞN­+/XV«o› ‚ BÛ‘Ïç1 #=Ç!›Í288ˆ®ëäóyLÓœPP±mÃ00M“|>O>Ÿ'•J…ÇÊçóá±A¡ˆŠ Š"Á$PÆ) Æ JH°"ûc#• ¦.Á¸†Uþ[y[¤¨G¹®_OçÈ——_q%ìÞ¬O–·ûq®ÌTŽõfvÚð÷™àxù—A߯ ëàíç%XúcxÇ« tFpçEðþÞÿÑ@Èðžï0;Þò}øÙ«!#û€ï= æãðÕŸÁÞÀí‰=œüäþœòÀÜrßËì¸n?^üà ôŸÀ÷ ûpÎ#` ìï'%üÃJŒ ìÇŸñ‡=ww ×}^³¯Dá]KÐ?ï>úž>§ƒÍ–¸ä¼çùÞˇñù;`ÙÈ3ð÷sû ˆ "‚°HP•§ªø}ªÝ•¢\â?Ü1þà…î?øw\ôÚ¯¢¿ëjÞó‹ùƒ?|cë*¾ýj=û¾ºú$Ö|ä^ÿµ§ÙsØŸy «o½UŸ½Gï\Ë[—=óx×EÏröº¥|‘§xáŽCxé Wñ•ÒÕ\zìŸÐwû=œÞ1ÀOþ+îíz‘ k¶qÌOrÚ²SøÒcwðoO=ÇÎýNãôWÀò;_ÍãÿnNŸ TAJQÿGãM*¯ ÂWb†š5¡yn¥QŒÙ¢aŽxòÉy<› ‚ ÂÂe.½I2™ ¾ï×]—Íf±mÏó°,‹B¡€çy¡0ÝÎ*{#«pbÅbMÓÈd2¡GŒ ‚ 4‚ÊÁ‘©Y¦¦DC”g©LõÆ9”Gˆ¾Š'Êûù{À?:o…âàï©oÁzaõƒ  ^7ô}þé¸ÿȽ´=`þþø6Øþ Xÿc;Œ‡á†nøÍçáOFàGÀu{áo÷Â]ï‡M+àòüÑž!Ž>ädžyßœzsð8{à÷xò%xú‚—øâQûqÑ_À›žâW?ÞÇÍw.åà›fïÕ{ñOÓøÊWöñÚ·_‡µÇâ†wÝÀÉ#ÿÆÏÎú/¾pì>ûÙïâë)N;m'o>r€?ÞóVÞñˆÏç?ñ §þî|Þóø»ßøŒò-4Ž?á—|òÿ‚³Þ÷4æ!¿æQÿ4û6nü_,ýï½KãÈc¡ëâorثٺ¢‡O|à$>õ©×yÇáCV?é4|üã/ógv&_ýêƒüË–W±sç™üã?îáu¯{Œ›oþ}n¼ñ0îráóŸïãmŸ;”ç=xNŸTAÚ?òQx•JQÿ« ßœö™AA!È{¢pÇqªFI¥R$“I,ËÂ0 ,ËšPœQ¹VúûûÑ4-ôd1MÇqÆm«¼^TH±ááa\×%™LVåpA„(.8’#gIP q®"{¨jâªsQaÍS‘}Œ¯@òÏ Ð.‚ž‡7|~ý7çI毠_‡ëÿ Þñ-H}Œ·Âÿ]w> ßþVn‹A8zd„O$W£=²©Ûa÷wóQ­ƒôµð¯ûÃð‹Kvðí/ 'œÁ—^Ü—ŽùGv÷¼“]wüšßûÀ©|ã§'ðÌ>›XÊè‹—òÑþ!ßÚü ùGEÕiœvöÿcË–#ø«Ž‹9Å<™Û?ÿ þ¨Ïÿù?Ïñè£_dͽûù(Ã÷ðçý>O|rš¦aÛ_#™„Ï~”ÛnÓùÔ§Vò©OAW×ʰN6 pÝ×âû`š©°-róÍ'ây'†¿™®ë|ÿû i„-úûÇ·] æ ÞþöÊÄr‚]+v±ÿ3s+ˆ Òd|ß§X,ây^Øhö©TJ’&.P”FŸß÷ÃåA¥Øh#b¨ª„U·O 'P˜]…à2Ëûx@!²ší0ÑÒxž–Uý­ëz¬m²<Ï«ê\±~O ‚ ‚ L…ëºãÚ7óÍdIåa|•b±H"‘`tttÚç²,+l“zžG:&™L2<<¦i\sMï}ïkx÷»·ÇJÁÞp0ï~÷e¼ãà8^èER,žˆ®Š–ˆïyÏy¼ç=ç…¿AMuaŸh\]/{éDPß5mz㱉D‚¾¾>4MãŽý^÷ìëæô™A¥ xžG>Ÿ'“ÉH$B—æB¡€mÛ¡â8š¦‘L&Éd2hš†ã8-(T‚‰išäóy ÃÀ÷ýªåT*E&“¡X,bF(¦d2²Ù,¾ï‡3š·ÖuÝÐX•׺÷jöRí¸Kj÷Éd2U™T*5Î¥Üó<‰Ä¸¿ÐÞd³Y sYÓ4R©Tøl×þÞÍÈSÉÄŠT'[×#ßMªó•LÅD–£DZ…TçSÙŸiš¡(T,ÃåÓM":×([ó}\ÇWÍZTÞ@žç…"´iš¡ AXåíW(Â÷ ‚ B;ÐŽù=Ô¤£éà8Ùl–ÁÁÁªã¨¾r=r¹¹\Çq(‹¤Ó麢J´W+NµÚûGAh*Tß´V1<<Êöíc|÷»OðÈ#{Ù¼9Ïy罇7½éfŠE‡ú§¯ñøãñÊ+ŸäÉ'Ÿä»ß=žU«þ†¸ HP(x¬\¹’]»Öò ÷òªWý‚Gý+W®äíoÛöxÇ;:¸ûýíoà®»nãÁ=Þÿþ÷sçwrÎ9ç`š&ùÈGøô§?‡ëº¬~â;üà{—sök¿Ç¯þ(¿;ýttÍç£çïD?÷´ðžžyf_üb ‚¤R}áòHõÒÀ<ˆ£ê÷èk¯$¢Æ>;ôY¾wø÷æ´"¨Ìª×ÓÓC*• à-˪ÀT³r¢ BKÖu]òùüôNc"¨ÌÅb‘|>Šù|žÁÁÁ†ó¤¨í”7È\àºn8[Ý0Œp ¶P(T ʪÁeÕð üh ¹UOt-}}}¡!DBEQ†P#W Ϊ{¢ÔDMÓƒê>E=gr¹\Ýêõ~ƒèñ§ƒeY¤ÓéÐKG%Iܽ{7¯}íkçäwš‡ã8¤ÓéPÔL§Óôõõ…ßÇ 3<‚ºÔÉdXöàƒDPgö3u8®‰PÏo­÷—z¾U˜@•ÀS…TvPFži%"5ºN PQQí«þz}EE]×I§ÓáºB¡0ã„BPT°^ËTö\.‡mÛa²Òl6z n¹å–þJ‚ ‚ ‹›Z’Zoçzëk“Ö«v`6›¥X,†}> î¤™T*EOO===¡p¢Âe†AOOOÝ6£j{FÛ»3íÓ ‚ í‹ùß§ŠÝ¢’lÞÊBN{'hç;ŠßÞ ©Ë;eÀ¿è¥™Ê„l˜C°ví#œyæ‰8<ÿü/‹nx‚+nÄ÷-çZ®:®Ÿü¿}Ÿ]/>ωÄ7_âG`É’/°œÏ°ëŸßüæ7¬\¹’§žú=ô;xà,_¾œÓN;;vpðÁß§TeåJÏ}îs|å+_aëÖÿ$•ÊqÓMGòÝï~7(n¹Þ‹Ž3+¢c+ш?®ërÑGÏaíUo©LHÐõ ‰ï‡bÊ+ï{¥åËYzÒIar’».¼U«V±ª··¬8A6‘àýŸúg¼ýíáù¢â‰Ê/žÏçÇ *J,Éf³a4$Û¶éëë#™L¢ë:oéîæ‘GÁqœªèCjl)ŸÏ‡mÇqð<“N:iΟ3Tf‰šE®‰¾¾>‰ÄŒ“ÎÏ$ÎkôaT³P1µ¬P(„ù!šºJåmPá{‰D8ã\© Ê3GrtöúD¨kRÇ€ùs—7MsÜ}ËårlÞ¼™ãŽ;n^Ê L5Øîºn•ЩžÁ(.Á$„,bR©3/ºûnn»é&rgŸ=­ó+¯ %2ø¾O2™ ½§T(.ß÷Ãpc©T*tW4MsÆï“ZR©TGrªcF(%´ÖÞWÏóB›Pi´’žÊ6ç*g”eYaLo]פX,â8/¼ðœÜ;AA„ÅD©TšÕú¨°’J¥B¯k˜|‚›®ëŒŽŽ†ÛFû‡ƒƒƒáòÚI{º®Óß߆՞«ö³ ‚o²”=L"‰ø‘å*¬—×—B@üÏ€VóåL`x«€õ@È€—K×£|"߇|¾üåƒøÅ/\~x àðæ7qÇïâÌ{»9üÙÿ˜«åý/þßÇdÿýÈ‹/zܰó0^»çÛôuï~êk\r䑼ñ¨£øë§žâµgÜΡ‡®aéÒ7râ‰'òÁ~0¬ uýËÏó¥/})(H2ɯ?ùI°í y @±ŠS¡•÷þñ‡ã7ù|½\‡›åcÚžÇañøŽÃÔdÏcéöítüìg°jU¸ìª[oå°d^~9ˆ¦ëìûÊWÛ¾e/¿ÌC¿þ5Þ¾À—_ΪU«Øvãò—ˆ#Å"¯ýÖ·Ðóyž:ã ܱ1\×ÅÒuÞôóŸ£ßs/?õ7¿éM†ÁªüGÎûÝïxæž{8dófœGÁó<ú€n¾™§|—/½tΟ;Tf€ M£ÂZår¹ªÙÚY9Ó!ÚðS”º®ÓÓÓÃððpèQ’J¥Â|%j`Vy‡Ô'Ê|†ÄQaÌT8žFWÛ Ë²Ø¾}{«‹!Ô <+”Â]+ø€žÉ„‰Kµ·IŠ`öB¯³“ª<•êºn¨ž¡WX2™ …å¦Â¨™µájíd.;ƒ*„V4I=”U(&´ËZ1*¾« …*AGyú‚ ‚ ñ`:ý½‰¶êíØ§AfŽM0†£DärÊ«ÑãgPØøK0F‡ÜApNó=åsðüÖç¹íû€y÷}ç>>“ü =ô÷¼÷½'pôÑ„‰Õ_yå!V®<šÑÑûøþ§Þ¹+x†#¿~ëv߯_ÞÂÛv8yÉn¾üøùñþÍ貇éý¾wîOؽ{7Ç<ñ?=òdþþÉ>V'“¾Ïé‡ÚÃòÙËÈfm²é4'žyfpR¥âäóñ8æÏþ,ÈL‚ã‹›ö¼Š§‰ÂuƒO9»¦iaî]]×I&“†išxžG6›Å²,œßþ–¨ãè:ÿï´Ó8éŒ3øœ:¿®óGo~3—vø‡3ÊëùçùèᇳìÈ#ÙöòÇuÑ—x€m»vñÍ{îaß*–Åêl–?:öXÞsÌ1xwÝ…mÛûæ7óä#°÷¥—ø™að`9¤×WV®äÇ]]¼á‘G¸ãõ¯'³v-Ùl–‡N<‘˶mcåI'ÑùôÓsþܵDPadd€ÞÞÞºë:;;éììlEñ&E ’*âB¡0§Ç×ul6‹aá«’Ã+ÏMÓèêê ;£ÞqC%”øµíÁd¶]WûT®~ét:  ëzh6A=é&Fäÿ©ˆŠÙl¶*Ô†ÅR'*ö³úžJ¥°m{œ¸3ß¾hΡz(¯;˲ڪCZOÐq‡ã?¾ÕE›3ÚÝ>a!ÓÎm[AXÈHݹ8”öDìSâK;µmÕ$Y¿ü7ãéºh†ÁWÏ=7Qü;‚ý=|yìûŠH”þþ~²·ÞxŸ|ík$‰ íÆªU<|kÕ*ü{î¡ð§D[Y»–çóôÿÃ?pû]w1¾–™ó.¨lذ͛7³fÍFFFX¶lßüæ7Y¶l›7ofÆ ¬Y³†­[·²~ýzÖ®];ßE¬‹Š÷jÛv8³¼"zPÒé4ýýý¡€¢„%àÌ4±ô|cYÖ¸™ìB<™Ì6XÛ§òºÈçó¡XÆg$põ´ êÍ3Ï}âºn(lV­‹†þsgÜú¸ÄqV.õH§ÓaœêvSê¡~‹…"¨´³} ÂB§]Û¶‚°Ð‘ºsñ &R íƒØ§ Ä—8·m=‚0í*o¼ ïå(zyÝ ïãºr÷rÜÄO _¹²XàéàdËè Æ{öî=„SN¹›»Æ8ôÐ}ø¾Ï™¥aÎ9î+ôÿä¬?÷+œþÆ£øÃæ€[o厗ðÄËà¾øŽ;î¿H<ÞªƒH¼å8 CŸ°‚òï~÷»ùŸÿù.¿üFÞô¦ ª&ž/¿úê  º‘pšÿöoAè.5~cY˜R[ßE¿G…•è1m»rM Ö—ÏßaÔ#5!Yåó…êÔº®ã8NUòx%¶¨*I¼Ê«­r…{žW¡Eå?q]7ŒæbFø?årår¹ð\êØ†a0::GåWëT™ÔØÖ]wÝ5÷ciyôÑGK'Ÿ|riëÖ­á²óÏ?¿T,K¥R©ÔÓÓSºõÖ[K¥R©´uëÖÒÉ'Ÿ\zôÑG'=æå—_Þôr—t]/†Q2 c>o™Ð\sÍ5ásÛ®Le›¥ÒôíóÖ[o-]sÍ5M/ûèèhÉ0ŒR&“)Ýò裥×þüç¥ÿð‡¥áR©”)•Jz©Tê+•J£-º·qD×õR¡P¿–t]/e2™VmNJï|ç;[]ŒYÓ ûœºS&c¾êˆfÓ®m[A˜ iÛÖg¡¼·„öf!ÔÒ¶" ¥Žˆ{ÛÖ,•Jýå¿3åïF©TÒÊŸÔoK¥R_©¤S*õ_WÙhRÉ0JÁÀPù —]öxiõêÇKŸøÄ@Éóü’a¥Ë.ûriõê{K¯Zâ•.XóPúû%éÒYgUú8fIc´Ôyø¥s1KýP:묳Jºn”–.½³ô×ýÅÒI'Túä'?Y* ¥7½éOKwÜqGixx¸Õ?ëŒÐu=üß4ÍR&“)Y–U²,«”úûûKš¦•LÓ,†Q2M³dYVÉ4ÍR.—+išVêïï/™¦î¯>@)“É„Çîïï/á1r¹\©¿¿Ü|&“)™¦9nYíX–®ë¥\.~oFÛv¿¹—h&fdd„ÞÞ^º»»Ãe^x!»wïf``€ŽŽŽÐ•¬»»›îîn泈ãÈçó$“ÉP “ÐUÂBd2ÛbkŸ*GÏ[~ÿ÷ñr9þ¸³“ËÞúVþû’KHL<è'p÷ŒgP¼ÖÐ×׿cR÷°P(´ç[£´»—¢]íSíØ¶„Å€Ô³'›ÍV}Tlõèz5´Åb±*̬ëºá±òù|Õ±„Ņا Ä—vkÛ:T¼UL@¿ðÀ?Ì÷¸­à¼ì ¡9ð ŸÓNû%ø%¾úÕÓøû¿¿×u¹åú³1üJv?¼‚CIñŸXlÛ¶8|ƒ.Fž½ˆ]iuáèè0ø/½ô*vîÜæ‘ø gžyfKsÍÎåA s¯"ž(OÃ0Èår úûû±Ë¡Æ2™ ýýýhšæðU‘eT#Ó4±,«êþ˜¦‰mÛ˜¦æp‰R/ÝE=/Õùð\WA¥··—M›6…ßÇÆÆØ²e ‹½×ÑÑÆì›ˆíÛ·³nݺ¦”×ó… „¿Ì}T“ Õ¨ŠI儚,ù|»244ÄC=Ä+¯¼Òê¢ÌšfØçÎ;Y·n›7onõå ‹*à©§žjuQfM»µma*¤mÛº¶mÜÈçó8Ž€‹EºººB%ŸÏO*¨Ø¶ *ù|žD"®s§êXÂÔ ±nÝ:¶oßÞê¢ÌiÛ iÛ6Ö¶š“2º‘N%'nÈx ¯ÿ<Ê1¿€K‚ÿõ©Oµ­€RÚ^‰+¹\Ïó°,+¬Ã£âE4§™Z ù¥Br)TšµL½«ôµ“~ë %õRM¤R©ðwذaCSÚ¶ó*¨DÙ²e —^z)½½½¬]»6œ¥‘äF'œpB•±Ï%¶mWý° É(„¹aÓ¦M\|ñÅ­.ÆœRk›ÀŒíóâ‹/fýúõs^F×uñ“ÉÔõ$1MMÓÂ{9YnÃ0rtP"Àúõë›Ò¶÷¤ôccc\uÕUŒŒŒpõÕW‡®bã¶™ƒ› ¾ïS,éïïoÉùa¾™È6!~öiÛ6g\z)EÓ¤Of‚eYø¾/Bq›ÐNö)‹viÛ ÂbCêιg.Û™Lf°_*$­ ¢a¢Ë à “É„/‰D"i|ß\t]ÿö}Ÿd2I___ݰ!Âü!ö9}|߯ûÜzžFFQ“ë Nª=Ñ}Ti¨žÝ]µ' L:­Î¯“=Ï#›Í’ËåÂäÕŽã„Ͼï“H$ªl½ÚÔvѲ©„Ö™L¦n¹ÕDÁh¹ëÝu/Õ{DÞã‰sÛÖ§"ª@Ž@Hþ)ØÆ[l-ïP~\ý…W¸ãŽ+Xøîƒ¿ÍvÝÇo€—^Èð?‡U/üœƒ—/§§§ÇqøÕ¯ÞÆêÕoâàÝÈ~ô#Î<óLX¤ôI©µEêo%XÔ®«×NPËR©Tøþ¨7±wpppÊòLdÓ­`Þ•Ë/¿œ5kÖŒ›y×ÝÝ=Î=s÷îÝ ©sM±X cÞÉ`£°X˜È6!>öéº.7ß~;»þþïÙˆˆ)³AB¶í`Ÿ‚°Xi‡¶­ ,Fâ^wf³Ùª?]×±m›\.G6›¥¿¿ŸD"~Wá5ær×u'mª¶7ŽãÌhÂa*•"™L†Ñjc¦GñŸíMå9P¡£Ç!‘H„ï%è¨üIžçáû~(¤*ûv'\W+òض]1FÓ4zzzÐu=\®fЫЄQ±H‰*µ ÕwuuÏR©Ô‚ò0˜)qnÛjyS @óAwÁÿ!èÇx§àôd3Å4!™LòòËëYŠË‡wrÓ=£±‘ï>ñ·ì<ôÝuòÉx—ÏãÏþ!ÝÝ—ñøãc¬ZµŠeË–qøá¿££ãU|èC •Å‚¦iuÙ¨(R;1¢žPõ‰nW[·Ûøû¼ *›7ofllŒ /¼°*iQgg'½½½a’£ÞÞ^†††ᢋ.š÷›¢!¨@÷ìØÁoÆ·¿}0¿üå/ƒó{®[Ä0Xôé ê½sâ~«Ì« ¢Œo"Ö®]Koo/###áì„ùÂ÷}lÛ¨r¯„ÅÀT¶ ­µOf«=qÙez×]|¨·—Ä’%hˆ˜"õh•} ‚09b›‚_Ä>GM@œî@£Ê¥ D ÅDƒ–JQ°ŽãL&ùЇ>æZ˜NyT"ÕßÚ‡VØgt¢­B……Rb… çe}}}a’ôþþ~2™ …B!)4M Ÿõ‰<4ê‰ 3ÔWùBÅ0ŒÐk¦QTè¼f “õò0LÅLÂÖz¤¨ë&g¾lSý:ªöÐÛ®äfЕ•¯zå%Ç£·÷K¸®ËÞäùáÙá~/8ÎÞ½{ùÕÊ•<~È!¬\¹’Õ«÷qÀ#lÚ´‰ÑÑQz{{Éf“|ç;omõíÚ„Ø *­"êæ'B|Èf³|dûvÞñÐC|ÿÔS[]AAAX$ –,YÂ’%KX±bžçUÍÖ®_²dI]]×) d³YzzzH$tuu…3ökQùSºººH$$“É0×J*•ª:†eYSöáUR]ß÷¥¿/L‰Êñ£D%žôõõ… Þ{zzÂäðQê…¯Rž#Ó:¦zJ…ïšÉäàéì3Ý?Jä˜ϰz9)_tŸzI¶…Öá—?iÀÞÖÏ`ôWð¾ÏPI¤¢Á6'wÞ¹÷ßßùÇç9‘OnÙÂKŒðy4@ç…#dÛñÇsÊ)§pÉ%ÏsüñÛB[W!­d‚}}t]—I 5Ìkȯ8㺮ÄS„rݲel?þx¾Ûê‚‚ ‚ Â"¡T*Íj}4Þ¼Êá f~O5hU(Âd·*_¹TR©T˜Ë"Þ§¶<ÑóKHo¡ÇÁ¶múûûI§ÓhšF:s¡†A>ŸÇ4Íi…ª´Ÿ %>Lge ó!\L§\Êkfºåš¯AíÚó¨0`B|PÒ¢wäþüSÜU {·ìeÏã¿ctôMhÏ@ïÙÃãcoਣî‚'_ÏK/ý;vìÀ0 vモãŽKa»fbn±¡ëú´C .tDPyqYaúøÀ—]Ægþã?0®ºªÕÅAAa†LÇCd¢ÕZ!Eæå‰ÒßßÎÄÎçó …ªçvº^ ³:š-B¨|!Ó=ÇtŸ=Ï›·ÜE†aÌÉ}–Äôñ¢ê×0Àÿf9!½ECÅ€]Ïì⿈)[·~sÆ^aŒ±ÿþxòÉ×yV¯>”/ù‡èºN2™ä ox§üÞÂŒYô‚ŠŠÉ*J› Ä?ò¯½ÿ~>+bŠ ‚ ‚ ÌÅb±î@“®ëažIÖ+,òù<©T*@2™ ™L¦jÓ4g,¨LgÓ4§- L”£e*¦{žé„DÒ4 Ïó0MsÚ"èLîÁLB~ÕÛG‰Fú©õ¸“lS€·pÀœOAêÒ /Ê¿¼ƒKÉrý9^Àfì°Ã¸ã98ëôûyì±ÏðÄ‹ëvQ,) ø¾Ï—¾ôZŠÅ_H8HaFˆ â8¡ë° ñ ŸÏsÜ[ÞÂæcå3Û¶Á´ºH‚ ‚ ‚°h°mß÷ëjzžG>ŸAEh[‰™LÓ4ÃDôÃÃà í;]q`&U3±­éî3b:Â:öLòRÌd€{&czQ-z_fšF˜[tAEú¾¸ ŸÞ˵ƒ?Ë®¿ZÁk0Ø­¹Œùg,»™ŸŽi©ù,?`9££ý|á ßåþˆ*³ÁÁA`fÏ €*¸®+$1Âó<²Ù,¯ýùÏùàŽâ"‚ ‚ - —ËM8°9UAˆ+ÊûÊqœ0gF£É– Øö@{£BM”ù£Òu}Ñ‹¢õ~Kå¡2ÝÜÏ<óL«/gAá) ?ÚÀm4 òyøÞé·qßïNg€WóüØR\Î>õì¹}=§³ß~/óÉO~’W^y’×¼æëèú;Z}YÂb¿V Ud³YlÛÚ ‚Ç]çþÎN>~è¡­.Ž ‚ ‚ \×%‘HT}ïêêbÅŠd³Y²ÙlUž×uI&“,Y²„žžlÛ×% ŠÅbÕþ‚Ð,|ß§X,†á¼òù<ŽãŒ ï5jV»°p™nžÅý÷ßßê¢/< °ýJw ÜÀóÀ÷áÐ}û8â‰'xÿ~ù†Á²e:Ï>{¿ÿû¿ÏW¾òÎ;ï<ÞñŽ_KîlaNY´*ŽãP,Å;Eb†ã8œýŸÿÉíŸÿ—Ë…y$oÐLT²qMÓð}ŸL&#ƒ¬M¦mZ ÇÓ}6N:é¤V½mñËŸhü cäþ¸¼AÅƒŽŽWxçvãzß䛼yÍ=·B¦\7­^ý|Ðöíð7lÔ MeQ *jVB½TẨ ^Íÿ w‚ý•þ‘c¨å3­ŠÈÿ~ùXõ”øâD¾5eW"‹*sÁÆÿ˜ýÿø§ý‚ ‚ B[1ÑL±É•zèSc"æ°Á=YxMÓ0M“þþþ¹;¡ Ìß÷«rè.ö„ìͦ=S*D”*­ÁR7ÁÃYpëÂ:óo÷ûËÌKùÒý!=z!p«VÁ#ÀöíÛ) ‹E|ß'›ÍÒ×××êË(ÓTaíÚµ ±aú»»Y¿~}«¯§!¢³ Ï ETÔðk¶Uë]*‚ˆòWû(±$êäm3÷QÄULZ‡çylîè ¿re«‹"‚ ‚ BX–E"‘ÃãÔ –ÏçÃI¾ïÓÓÓC.—“ü’N§%ìІa`Ûv«‹±¨P`ØÆÿÿ»`•u-Ïóø×gþ?¾<øqv>}/p‡t2'œpÛ¶-·q‡¾¾>LÓlkO)!Þ4,¨üÍßü ›7oæÊ+¯`dd„Ë/¿œ5kÖÐÝÝÍ–-[áÚk¯mõ5MŠçyU³â†òüP/%lØT #µapÕ'êM¢ÂZ¹‘õÐ^"Ââ#NsÐ÷¿t«AA¡õ$‰ºË£Þ&*JOOO˜w ŠÊŸ’H$0 ÏóÂ<*‚ÐlÇÁq2™ žç-¸‰µBs0M“l6;û ÓÂ#jÿYðŸzÓÁ):øò;ùÿV®ÄÁåØåƒ<õÜ©œwÞé<ñÄëÃúÇ4MÇ‘DôBSiHP⦛nâú믧»»€-[¶ÐÑÑÁµ×^˲eËX»v-¦i222Bggg«¯kBºººæÝmÏ#D,‚Üõòˆ¨¤ç:•pºÊƒÄÔ<ŠhH­F™èjELâ‚çyx†Á»;lZ϶ ‚ ‚ sÏT!ºJ¥„QJ¥R¤R)|ßÇ4M–,YRî'“É`Yžç…ÉçkÓèya:äóAâÛ¶%|S Álaºdg9X¿–ƒö&@‡î~–R?¿xÅ/qútžü úÝy<óÌI|ãß‚‰ºº®cY–<BSiHP¹é¦›èíí ÅÂ]xá…,[¶ €ÎÎN:;;c-¨8ŽC*•¢P(4õ<6Չ͕H’,ÿ?&¢ÌÛžçñÊW Ø‚ ‚ ‚Ð>ø¾O"‘ ¯¯Ã0Èf³uìèºÛ(ÂÂÄ÷ýð㺮xEµ€f½5Ã0pG„¸aüôMàŸ Å"œpów¸â¡‡øI<ÏÁ4 týe~ô#£X,†¿U&“AÓ4ÉŸ"4•ýݰV$`Íš5UË”¸W\×mJ#Î'Q²@Õ"Ê0€’ö­N¡y|÷¾û8äCÄkJ„Å$9z)ƒÿóùà ‘A„vC×u …ù|žd2‰ïû2ˆ%Ä•T\×uoí,b)AE˜_¢Ý§ì_C: Ù=ÏÈðÔÞãÐŽx[¾/—Ëñ…/¼¦,°¶®BK B³iÈC¥££ƒ›nº)ü¾eËz{{Ãeccc ÑÑÑÑêkšå‚<£}ËŸ,•Äí•„ífù“azá¸A€;V¬@š·‚ ´ö}*ïðlr¹êe¶ –ˆ(š+™„ÁÁ`ûT*XgÛP(Ë,+ØNµùóyÈdªÏﺉŒ"‚ óŠmÛ¸n´ZåK©Å²¬98­Í[P/tK6›%•JM:YRåΘh;×uäӚ¦‘J¥$<ÌÃqœºy}¡DP™‚‰éÖ6@ï•`¹±ßì8ä8¾û‰vð’ ß´¦¡iZ¹?µÛ¶) äj;i‚Ð$òP¹ð áoþæoزe Åb‘ÞÞÞÐ#ellŒ 6ÐÙÙYl2ÆÆÆ©Z622ÂÀÀ@ÕglllÎ.Öuݪx­àx$4h2ôx¡ô—¿çÊë¤ &´;õlškŸ¿=æ>¾zu«/]bO+ìs1õQO†mB‡ãT¼J’ÉʱŠÅ@©Ft=Ø!¥X –+±Å4+ÇtÝ`›èñÝš$lj]T”I§ƒÿgraîiEÛV„©‘ºsfø¾OOOO•À‘Ífééé –fÏçÃd®ëR,éêꪚqœÏç§œœÏçÉçó¡hR».‘H„ßÇwa~h¦}zž‡aãòöB#†ÑÔw];0Ÿm[õöÕ€¾o)`u0‰Í}éõüôá?Ãäðã·¯mÛ"~ óNC*|ó›ß䪫®bóæÍôöö²~ýz ýµnÝ::;;¹öÚk>q±O6›%›Í²bÅ ºººÂÁ·èq’É$K–,¡§§'ôQIWW+V¬æ«–éˆÛ¶iš¤R)\×mÈó$“ÉR³&„¦3ö©žH¦ËtÂ~=óÌ3­.îœÑª¶­h¿ò€ô›´ŽWx晓9âˆ#سçH$xž‡çyø¾®ë"œ óNÂÊD,[¶lZƳfÍÖ®][W| ³³³)ªÜ='Ã'íeS ã%Õ®°X˜Ì6¡yöùã%KxëO´úò!Ö´Ê>ç‹hböÚUQOûtºÚc#º½1¢Â@±XÔOTLˆ†ßRû«¦‚ò4Qá¸Ô~ù| L(A£6„—çUÃ÷a#Ÿ¾g2•}L3ØV 4J01ŒŠw‰ò@QÞ2êo%âø~°½êCôõUušV¹ŸÑkP÷H NêÕFGQ÷G¨O«Ú¶‚ LÎB¯;›‰$ê B«ðIwÞy'ù|ß÷¦P(ÍfÃÁGß÷I$†A©T ½[”÷ˆëº ÒßßO±X¬´T‚Žã8á1§#vضeYa‚âÚ°_©TŠd2I:¦X,†rjþh¶}ªü)‚0LÓœVد+V´ºÈsB+Û¶ú£„ñ¿þëÿ›Ó_=Ìég¼ ÀK/ÁÐЛyßûÞ åê.óMŠʡ²nÝ:®ºê*†††ftÂîînz{{Ç%¯W1÷þæoþ†SN9…7¼á lÞ¼yÊãmß¾uëÖM¹ÝTª$ò ô#BŠÐëÖ­ãÆolu1愉lfnŸ7Þx#6l˜t›í+Wò.ÉŸ"Ì1CCC¬[·Ž;w¶º(sÂ\ÛçÎ;Y·n]CvÜLTøòhõõÓ >Éd°m6[}¯R©`?5eš/æÌó*^3ê8 ×­WЍ05]6oÞ̆ xê©§ZúüÍ­jÛ B3¶íä4Ò¶må©>õí¢ëë%ÇRÊ~ôS;°ÔÈy¦‰Z4M£P( iZè¢Ä Û¶Ñu= ·¥B²(/–\.Š3µB†mÛa5˜Ù耙ʽ¢Â¿DÏ©( ah¯|>ÏŠ+H$±Î— Ú¶Û·oouQæ„f·m§î]êÑh•Í›7³}ûvJ¥R«‹<'4«m;é8òh°Š``Ö€ß>uŒŽ²mÛŸ³té¿òÆ7Þ¡‡ Ö/â"Lņ šÒ¶mXPY·ntww322Âå—_^7yØL¡··—+¯¼’û￟k¯½– 60000é~'œp›6mštÇqÂY6õPbJªü„FÙ´i_|q«‹ÑtfjŸ_|ñ¸x¸Q<àÅûïŸÐ6a¦tww³iÓ&Ž9æ˜V¥éÌÄ>9æ6mÚÄÚµk›^>®+™¬Œ)á#ꅢƈԘÊDã&jåѢƉ¢9P¢ÇScGÊ›C%žW"Gt_5.¥µ*‹$2™ '‰eUŽašÁr%<¨(QáD <*WŠPT®ß¾+¯˜|>ØO•5•Ú=šs%ŸÖ)/uÓ¬/¶]u¢yaúúªWë½½‡žÄ1Vú ¦ˆÔ2޵kײ~ýzV®\Ùô篕4³m+ÍBÚ¶³kÛN‹ *š¦M*`¨uµBˆ¦iá¬aÏóp]—%K–„Ÿ¨°1Ù`w.—£¿¿?üd2™ª$ò“aÛ6š¦‘L&I$ض–%ŠeY †‡‡‚¼1qEµmO8á„V¥éÌEÛÖó<éc sB#¢ÊÚµk9ᄤm;ªm;išˆ—@¸‹ °ü„§8õÅûÙ¹sK–$Y¶ìRŽ=ö1 ƒb±ˆëºø¾/*¤¬_¿¾)mÛ†’Ò 022¯ýk–-[3L6oÞ ’Œ½X¬l—ÉTsÛ®ä2Q!±ÒéÊ6J QÇUbŽU¢ž/–xÐôõÂA&¬ëêªö2)*^"Édµ¨Ázå%¢ŽË7GþK¡Ì«kTD˧¶SùZúú‚ÿs¹àÚL38¿:—ãëÔýH&+"Šº'ÅbEdQB‘eU~˨8“LV„%f)‘(Î­Ä›Åøú‰£m ‚ ûl$„ÕTIØ•‹âlÏSƒeYd³ÙºÉ˜UÈ®¯}íkã¼u¢ƒZÊk¥_UâòJ‘o]×0³m›T*U5˜žÍf±m;̇Íf¬:þtD¡¹Ì…}F½”a6˜¦¾?;ͬ;ÝÃÀØæ-³Þ5xú¹{8to'oZ¹’=Çß®ËÈÈZòù<©T ]×%¼ŸÐ2öPéíí Å€ /¼pN 2222Îý+z¾ÙRoŒ¤"¦Âd4Ë>ù ¼}¶ÇÉçƒQÏl6å«7+/› ¶QŸÚÙ}ét°<™ FKkÏ©,ÑsIt¶`my'(s´Üµ¨åétð‰Ìøs‚}»º‚ÿÕtòÙà¼4òÇ#H8U$P¦‹@¶üÉ—ÿ÷Ëç#ûÎ0DÐŒX$Uš]Î%šÔ›([»c=ʃ$*x(‘$Ÿ¯ˆétå˜ÊÓ%**x^å{:] ŸA&¦YöùðŠ|¤‡sJÔHšê­fE§¹«)è¹~¼   ¼gF;õMhjŠ´¢¦_GGV£¨ìÔ†Œ"ªŽ¥õÎtœêéó¾LÓŽÆ1J$*1y`üèªÊ2­iÁµFÊ«tWëJ|}õ>ò7¬Á´+ë}?ä(d*9 RNe&~ôtJ+R¡Ô`ªç׃y.èwwxGó\pîR÷‚}KÁ} ´m`] øàïâíÀ(¤öÛfÙÓ×¹ø:p˜+å±ó`¼Ü}à Aê ðž½;hhÑH{ɺàÄ·œ8«g´hfý9]”W‚z–TRv…`>º^ñr­xL(¯enÑÄìÊûD=»j ^…ßR!¶”sV:쫾GML 0j{õ±¬jÏ•Ã$— ö‹^C­xeªÉÅóE&3þÕõ”QaÅÔÿêµÕ|•—Žò$R÷,“©è¾ƒƒAX0åí¢òÏD=ÒiX¿>6MЦ'Û¡±Ï©Éård³Yººº0 MÓp‡L&C&“Áu]t]'N£ë:žçUåL‰z}††`jÄk ÖSÄ4Mr5j½mt]Dz¬q“)•ÇM …Ùl–b±X¦¬O¹h -e.ìSB s…¦iá{b±{B4³îÔw€þC‚AÚŽ Îð‹/Žr#§|0 úfÅbq\ óMlz³k×®ehhˆK/½”ÎÎN¶nÝÊÚµkç,¾{í‹O…ù'PA˜šfÙçØÊ•|è´Ó¦ÞP%=('-ðWtá²×@áuÒ·@ßÅé­Ú‹à_Î# ŸÖX'Å}ä¾ɳ ÷…Ê»ÀØ Î×Á<Ñ$(Xš‰³ôÁ¼²¿…¿ƒwàÅ÷þ * µž+ºŽ÷Á¿AךpµÒM‚¾š†Ö?Úú~ ˜T’M'³¼,…Ì_•Ãcßæ›A?ü[Àz;8À2N"=˜Ïe€~ä¢*±fÜ¿ „žxï+.Þ%—„á~TÞ5°­i¹ü_BþÁ²n•ª$ÎötðÆ€ÕtËú–ž h .‡¡Vƒ´¾öH;Ám´mÐÞ þ÷ ÿHðó&ßڡиËÍ,/Bnÿ¼nÈü58 Ƨ‚ë¦H ”;@?x¿=o¸ñ Mµ8Ðìús*TrrÞŸ¨‰D“Áëze€^…æRû*3Šº+á¥v?Õv® !•ýL3àÏå*‚@4g T’Ó«¿•ÇŠúD'©ªÐWê: âñÒ.Ô U_Û'Ô´j¯Ë ^¿j|IEÈ©ß[åQ:p*+VT~Ö+˜üà˜¬Õ¶)ÂĈ}6F.— ҨX¡ë:ýýý8Ž&˜’Éd°,+L®Ö×&nކk$©ót?ëº^µO*•"•J…³Îë•]hbŸBÜPa¿2ÑÙV‹¦Û¦z \có·:8mï­óf³êýlÛ6}}}ôôô0Úˆ;¿ 4‰†•­[·²nݺð»JH_ëîÕhÍzÛ]}õÕ ±{÷n:;;éì윓‹¬M U$°SSa<Ùð\Û§öË_Â¥—N½±Š_ãj8÷Bö“:(”ëÊBêmý ¸cëÿZ(Xå» u%xY>ŸýõÓ ûKÐÿü Á¸Š_k)˜Añi°ö€÷zÈŸ¼ÿ±.ú>VDÌf˃ƒ®»tì wŠNú¿A_œÛ;üG ó°îÂJ°s%oç€oƒw"$ ;ÌSA»ðÁÛ¹UÀYåûñZÀë àR(üIðŒ÷„àŠ¢ña‚0\‡Þñ±Kü/ðÿôà Ä"Lµ¯9ø U!ÑAæzQ¶Žã0h¹øg_€öòSá¨xt°Ý¤<Ò}µßÔ k0|0ô@n•¿üß`äÛ×t¬óAKÙóáqÈ^ÆçÀÙÙ›Á8rï€äa ÿñØëfõœÆù²Ïé D%D@å»òbP(où¨ˆ¢– ËTöÁÁ@QNZJhQQìúú*ž$*—iV<²”—‹ 'ÕI胃Áþ*OŠò¨ˆ¢r¦DŸßh~˜…LÔÁNQOQ÷¾P¨ÜoõÛ©q2•·Å²à;ß9†O|¢ÕW7·ÌgÛV„ƉcÝÙN¨\(“1Ùz]×c;«[B|µžfÙg½ï‚0S,Ë"™L.:Ae¾Ú¶]@´–pÞâò©ïìÇÈK/q Õö¬< µ]ažiHPéèè`Íš5UËšÕàìîîžócFÕLÒ¿ÆG„ÅË\Ú§ÁèZ=AÅóÊn”’tuBß› }dÞÎŽ`@µJúïT¼"ÑÀ€ÀÛÃ20èÖÖQ§~“êð>QRó-»°ßz=§Kî¨ýÈ?æÑàåÁ» ¬À9 p¿ ¹¯;Ëeˆ3Ãõ¡àVNl|.(Ÿ ø»A;³úv4ÔnT¯ohoZO?‹ûígqŠ.¹3þ ú#w"Gu¢ƒ¼W‚Ql•¯F¹àD{?pyÆßßÿåxרÄmÒ4ø_Î4à_ŒJŽ•AàyX­C>µÖLóºTð;÷€uJß]Eâ‹'÷ýRyß4 —“a¿ëÆ{¹›¹ƒmO3êÏFˆ¦Šþ­<@Tª Û…¨—‚òŒŠFôSž.êïl¶Ú#B…œÒ´`»h2wj ‚ó(Ï”d²~¨.ޝB_©äòµ?j=VÔ¹C®ÓéLحݶ¶Ÿ£Öë:¼ãOóÛßÓêË›Ze›‚ LØç̯¡ÙÌÔ>]×AE˜S”(,a¿æºî ‡hÂÉœžçqöÙ›I¥Ra]ãy®ëbš&®ë6BRšEC‚JwwwÞ'qëIöœ%k•W  ´8¥ìéVE±|q.ÿ1ÐÞÖŸB¢<=õ¥ˆ8•/)ê'"Ö³31þ«t¬?sáŒÇúáHEÚ窩ÆZ·7p<ñ¢‡^YÕLôã@»wþûíW×™e9ŽæzQ¨x>“1ULÓ‰ÖGŸ_M }§Ê7ÊÈ‘J'Ð?zÆy‡WÖ—q3¸ñÆ&ßP¡ %Ž@EP‰ !PIT¯9ögT–5k¶30°³ÕÅAfˆa"¨±Ä÷}ôæ˲$ìW“ÐsÁäÎHµòÐCW`YgUmkš&ŽãŒË“-óÍ´s¨ŒŒŒ000†üêìì䢋.bÙ²e­¾–ºxž6ôlåS¼S¡õÜ·o½{÷V/ÌfÁuqŸù † Îa`/ë5ã$ê¢ÑEÂ\K×›¯x4ý m[ƒ¾ÏAÿÀûêO?o‡ðjðÖ00¿ ´ñe´ ¸¸Õ¥]¨ôJðPùRÔ„@Û.çÿ)‡ØÊåB§P¨$WL*¬VT‰z4x^Å¥X –GE–¨€¢öQL6Þ£ÖµÃc¿PïñV—DA„…È\'¤÷ &JSqq“J¥èééA¥ è@êRðþ6ȃ»ï7 »j¶‹ÚvíäyA˜o¦%¨lذ7²lÙ²0ØÆÙ°a©TŠ+¯¼²Õ×3)Y‚(2‚ ´èÚµ«zæŠ ”$ñGÐ8KaðžJž–³f:9÷‚Ññ9Ü{†±â5íï­g•d*q‡r_šŠçUD Û®Uúû+‘ã,«"ž •p^J|Qá¾”‰eûZVð‰Š&Ê+Ey‹D“Ö׊&Óõoê;¦H¥î•ÿÎR‰- E8‡rèÃÈ1œòöjÕ·hsÁWAˆÙhX‚7–e…¡”²Ù,©TjJOÇqÂÙĵۺ®‹mÛ@B,•JU…j*‹uÍLÓÄ4Í ×ëº^5{Ù¶í0¯ªa&fãºî´=Tœò'‡¹‘ƒŽþ9•D²•\*®ëа%´œ†• 6°yóf®¾újÖ®].cóæÍlذ v¢Šã8躎KP ÊXƒ ´»ë®ê†îóXœ«@; òcÁbM›:zÔ¼ ²e·;«Ê„“ÏC;k¶‹ê7é驸=(— aÎñý@·ŠšB*x«(/2ß’ÉçrPbš•P`ét°¯ò6±¬`[߯2PWÔ9¡:Ç‘k©·,–ÕÅôÊM‚„n&˜âˆ+I‚äNE·ZµÞ/”ã@ذQûC9^ù»jô¸‘r¨õzd;›Šk}T¤A5ù|Ã0Â,ÇqÈf³ ¢ë:ù|Ó4§¸Îçó8Žƒ¦iU`ù|ž|> ŽãÏçÃãC „ø¾?.ÆTë¾ï“H$ð}?Q²Ù,ù|žB¡ !Ë0“=—J8ñšc4¹t‚¦’OÕDy¦äÊ˳‹Ã0pGÞsH(d^¼Ù7ýŒs^8Ç^y§tŒ¯ëº„õbAC‚ÊÐÐ7näú믗|hÙ²e¡ˆR,c'¨@`pj\B„Öóý{ùíÏNêsŸ«,ü®8'@æÃÁ€k&Nú…J´Ðæd2࿊K¶º4sˆeO„!Ì9žx˜XV tx^ šd2ТBq¹nàe¢~µ\×Q¥¿?p*RãJ@Q^(Åb%ÇÊGm˜Tù•ˆ¢Ž AÂ&è¥+‘D (&•|Aµ˜‘cÛÔ$•¢Ò3Qâ‰ÚÖ*¯KSÝ(ŠŽ,¤½¼½*[‘ŠØ£’Ñùåÿ•¸#‚ ,(r¹fÄ…3‘HP,É58ÛÉó<Ç!“ÉŒË=Íféïï¯:~:ÅŽ‰Ê0U£$“I Ãw¼t:M:fpPâW,\*Í“JóJÍá©74[/í¥°¸Q‚J=N9å”V¯m1v€û4rß>^zî<ü—tžzj¿ªíÔ½Šý‚Ð*Tèíí'¦D¹òÊ+Ù°aC¸m\ð<¥+Wb#á¾!.<ôôÓ¼ñ¨£ª–y÷sY9ôCƒ2Pïºà¼£Õ¥hâò;/DÅ ¶ /“þþŠ™ôõ‚‰Š¶‘N?‘e‹iË p,R"‹V¢BÊðp«¯z–¨ Û ‚8)ª§8*aB…ýRëú8¶Æx1ª{ÿfu“5ˆŠåcšå¿•¸’¢"eË×’¤ŽL•Å¥’ãH C‚ ‚`º3‚mÛÆ4MR©ù|Ïó&=F&“™³ü®ëâ8£££ãÖår9ººº°m[Â-@\× =Ÿ|‚&˜r¤¹QK|?h#kZÅC[׃ö¯çU<»!h‹•¨ÅžW™¤äy•‰Fµ¹3™Êq5­2AImW›ÛPå)ŒšV*U“På=Ty UHÝrD> …`²”Zïûoôh µ½BåP4Œà<µåÈdª×»nå:Õvj"T®u¢ïê>¨ß@ªó>ªû§îWô¼“¡iZ>0Šçy±Í+ÝÀùh¯GŸ?ˆ‘—^àÌ3O¬ÚL×u ÄôB,hHPÙ½{wC‹“¢ð}ŸÛÏ8#œd)BëyüCH<ñDðåƒ6|¾ü%Ð÷ƒŠ) U•0L‚0[êô)Â]>t‚R©Š¸í¼@¥S%9“æ`:dŽJø.åÑQ(ÿ­¶Éˆ(Yï•V‘ªù»¶¿ílF…—ÊôÎ<•f9*ž/>RL¡L–ꨌ­À¢¾.¯ˆª\(ýѸœS`Ûv˜;Å0Œ*/•T*E2™Ä²¬0¯I=±¥vðRå1˜h=”#T”Åœz³˜£¹DPY˜¨g)MðœÏUÓʧ"<(1A 櫜~ê‘T∬Wý¯B!ØÇ0‚Aÿ¾šI4µcÅ™LE€J^×­P”@¢Î«Ì*Ú¾VžàªÜJR¨c¨²ø~u¹¢9'+;¦ŠÅàø–U-‚èze^œ§"™&$“ÁwÓ¬ˆCžWÙÞ²*BŠ­~‡|9¦[>ì“ËU<á!ئ¿?8‡ ]¬D!Ó >JH ÎcpÇyV¬€w½k«WßÀ÷¾·^ØÆñÇÏÑC¶9R/Cñàǰ_<ø;L33n¼¢X,’Éd$äš T:::UbòËó<ŠˆwÊBB5&T%ªf¨˜üªTy©ÕúhduU1*TNÃtº:ÂStÖˆšíáºAåÿÓŸžM µÄXãQnäþ¹ ·8ð= ãk _ ƒü󅤦ƒšÅ}fR©JÇ.:£L%•7ŒJx05».•ª¼s …Êr·Õ#JM»q‘¿'òQÞªÚø8U¼Pý‹Š‡JŠ@,Ò€žò²†³öžÅ°ÕîîG‚ 3')§Â¶íqámõ q]·J°°,+ ( ˜¦æNI§Ó˜¦I.—«,«-ƒa“®Wçš ³pQÏh’  21EµS=¶ð3:ËBƒ¦ã“íÖ‹ŽmO7:.@jÛˆÆYo²ÒT˜¢å¬=ÿt©X5Q9êÝÚóÖm¢ËÔ1¢¯è1ê½+y"s¹rT‡òw˪ô…R)xÕ«þœsÎ9šýè`Î=÷\R©Å"<òÈ/¸ûî†ÓT QvAñw»°¼¢¼ ?ú¢ˆ˜"ĉ†¬ý /œ2œ×† èì쌕—J±<’‘ÙJjÝ¡¢„§Ó ¬É4îCÔUÅß÷¼`NU`Q‘$ê.kÛ•{¨f%(aEÍhPî¤j/Ÿ¯„›Q®­j5ãA%J.ƒ}Ԍۮ̉ÆüWâÍ!‡ìoõmm|`ùè(݇›²àôAœí“þyöÇ ÂD¨äòÊu*J.¼•H­fɩަ®ëÕ~µªèL¾‡ÏâÎ-ÁPyWl ¸ûö>°·Õ%A&¡6?I±X$‘HÔ £U‹mÛhšF2™‚AnÏóp]7³,+?<Ï#N“L&ŽtŒgšC%ŸÏO*þÌUh1!~ø¾G0‰oºkUŽ@ÀžžÊ8€e&|×…o.æ¶Ý%üËÔ¦æŒþ}Ê) ë:}}UëÆÏ~ö7¬\¹²Õ—Òv¸»€Žßàýî¼p¹3„ÀC2›Íâû~Uý ­¤!A¥³³“+¯¼’«®ºŠT*ÅÚµkÃø€ccc‹E6nÜȵ×^Ûêë©"ŸÏsêÝwÓ*'^助˜ÔàQ$'ŽÚÒࣧ”‹¡T‚^{¾Á€ó†w'°ô×1nàH%&öýÀ•U%-Îd*‚EÔƒD©ÿjpM‰j³:ÎdÔ¬£éjï__U uk×Gg;Ô;÷9çÜ ÄGHŒ;.€ëò†Ì×áôɼ<÷Åø=Û ]¯ÌÐY0a•„yÃóqDÙª¹S©Š'ŸªÃ”@ÉŒ#eA‡ŸS»…Jû \§>»ïYv?ÝXHYA!èºÞ°¡Â}EÅŽl6‹mÛø¾O6›­J ¯ë:™L†D"1'eµ,‹l6[%à(<ÏÃqrÒùX躎ÃôÒ¸)!¥X¬Lê¬Qc`•ˆ)‹žÚ÷}µkßÉÀÀ@«‹×vø€á¯|…õï¹ïoÝÊC]Š™étšL&#!…XѰ?Úúõë`VŠòFÙ½{7ccctvvríµ×rá…¶úzªè<ýt¶vØìó¡ªd±Zùo5ãÔ'˜iY^æ®íiHÌ7ƒûSpžƒÔqÀÀpïп Þm`,ÿ§  Ù¿÷îêÐ)Ѥ¾ÑJ~Ö9˜<°¿ ÆIàÜþ³ ½!8¾÷KÐÏo¼r{Ù¬ €½àÞÖ…ào‡|_9mXÝàï„_ö§ô<Ë«_½<€<¯2Ó£¯o|¨­h¹,Jœy§ìoÄfש ÎØå߯¢:>»Wó1Êÿ[Áñ®DÍ>*DIk.°fÇj<ýMð9“‚^ɳ ÌÊ}YÅu+u“Â0*a”0nš••P £8™`õzYp¨Þ¼Ô%‚ B›ãû~˜—d*ÇÁó<2™LUh-ö+•Jáºnøwt¿FŽßJ I§Óôõõ…95<Ï#™L’J¥$tÌD ~6‡ÕËf+„¢“_¡2¨?Ç<šüîq6|ÿ9昀JØh€¾¾>|ß'ŸÏ‹.Ćiø[¿~=©TжnÝ ‰èãæKáy£g5{ï”bù£ì]*‚JŠ«A{äo³œà\¹ó@{ü£ ÿ?ƒ}@¾Fo9Om¦<ƒw98¿ÂAû[ÐÔà‹úßö×O‚ü U#8Ýàÿ'x»Àú[ðþœ²'¶~dóD`,¼£Àý_Èï}yùóNHý/Ð ¼ôƒÁû_ЇWx…ý^½?úß§I½áHîþ©+Žæ„×]ÇO·ÿ”B¡@OO[>´…‘=Ë–ßþŠÌòµA´lYûÈA‡êøò•p zyµÞ§"hiååZùj}2r õ›©d¸zd­rßHõ<u‚ v©ò±ˆœ§9¦´Á§¼Û9¾–zºO¸»8õ›FNQA´©TE(JrI•×*› –E=O¢ 1.“gûA„Së-¢rœL¶¾¿¿Û¶±,k\žå5ây…Bl6K±XDÓ4¼rã¢oªpS”QQ*•Èård³Yººº0 MÓp‡L&ær®ërÐ%—°©»ê¾„õ²¬ÀEÒêB X\'þâ1ÀGÓ|>ñ‰ê¾c6›¥¿¿ÎwA˜ ¦1iÙ²e\xá…ã¼QFFFؼysèÉÒj<ÏcéLo¼»H0PõõÐ# “•ótèσ÷˜g›÷÷ƒG*GHX1`Á¡UîÃ(Ï‚ð!•:€?-o¯Õüï¡» œ äGÏ’Ô¹`ßZ ôcÁþ)W€y,hÁ9Rårüö·ÏñËïÀU_ÛËúõŸ£ÏÍ“L&1°àÛF0‹çô>zþ"Ìê)ñ<Ë·°ïµ±º-œA‡Ogƒ¤PúRD"A__É~„·žøV^ßÓÅÿ³ÿŸÞôéꙹýTÜ®Í`‰ïûhšÆØ-ôð}×uÑ-=lô& rfÝÒ—?-CÑ/bY®ëâ>¦iâyzN'›Í’ñ2X9‹d2I&“Áó< ßÀ·|ŠÅ"=˜‚¢Êáû~P¶rŒTÏ÷Ðú44_«iÁ ™ dàÊÜ• ý÷P«ù¶ÁÞ¹Ð+9„ùeA笚‚òFQ!¾l;°_•oʲ*1¦•¸•¸·‹z"—¼ãA„6¤T*Íx}a‚iþº®Wí—J¥Â„òš¦óéŸböÏTë!ȱ’ÉdpËß¾¾>IH¿ÀyúÌ3ùó)¶Q9ÿr¹éµS¥ %s‡ðDð÷cgvÀm6'œ°Ç© Û/^)Bü˜¶ 2###lܸ1V‚Ê#ï{_c*.ç„òŠ˜ÀV³Ù`À(®ˆ$}}Á÷ÁÁ` I‰(0ù ‡qo”7L<øR^ž» 2å0+žçÐWn|ªÆ¡ã8躎çyd³–e‘N'éëëÃql<Ðãæ›u’É‹Åp‘²Ùl¸Ì0 r¹¾ï“J¥ªÜ¥•bYV91WåÂŽyÓ1äí<†aâFÙå[¹vÛ¶]u MÓ0M3Œ««\¾ƒkÊc—ãÈX–…ïû¡Ûx&“Á0 ‰DØ0ïëë£X,R,Éårxž‡mÛØ¶M&“Á4Í0®®¦i躎aá9t=s,ËÂ4M4=¸·¶kãë>†eàyÛ³Ûé•* ó»]/²ÿÎGÉ›Ò ”—Š 4Š 9©¼S¢ è]·:´cT$]ôa¼ÙBA2ó1ãXõ3…ÅÁ«WOö]M40 ùHp A˜[ŠQÌgàÇœ ¼ÈòåÐÑQÙÆqœº¹°¡ÕÌ™ 7îØµkòI¡>A.ŸÀŠû™0k™ç•®ú_)¥*Én4\Q³'»>¾ét‚ááa’É,}}}äóylÛ&—Ë‘ÏçC"*:(WêB¡@>Ÿ'“ÉP,1 #Dt]¯Š 9QãSŒšéuÜ Ô Oy˜(O%t¨x¹j;õ’T³‡¢nØ“½@£åS³”Tù£J¶aU×¥®9ô\)ß÷O%ʸ®KOO}}}d³Ù°ü*†ð?ÿó?Ç2ì]\ye÷.–¯Î íJêÆùŶEP¦‡çÎb±’ãK¡þV"K ô˵g m AAa^p]—½¯}-õ†eTˆ¯\nf“úįIæÿÐ_«¾Ù¬Zuÿø•õº„4bÊ‚Tî=î8Nƒ+êo¦â‘’bÜt5ؘÍVfæöõßS©æ 'ÑD}¶m“J¥H&“ô÷÷“L&Ã6JDéëë Cn)Ͼ¾> èò(QÔŠ ÑD€sý²2 £®=gtÛèÿõÖÍ5õΩÊ|†Ëª™l¢bÏ¿üË¿4¥l o7h;ÇoNý §SIf-Ì?Ó O-UBI=Tâ@Óœ|»EEUA„¶Ãó¼*/ÿèߎãÔíË B¸óÈ#Y³o_Õ2Û®äùËdd ąrthô»]N9ånžxâ×¼ùÍUµëºø*Ž´ ĈýZ]€fái—tÐø>AŽ”Aˆ­:‰Å'˜…›LƒB® >jÚÜ%+Sž"Ê}M…µÈçóax*]×C%›Í†‰UH/Åðð0†a`š&–e…¨¹ÍçœsÎiuÚï¡÷§[)œ$™ lM¼ïçÇ|¾Õ¥Út:øßó‚Ψê„êúøäôj¦ŸUÚJË^¡¾»@2ò·Ú^y»ªùùòÇFò§‚ m‰çyäËÅÚ¿UxdAˆ#»V¬àÈý*Ã\®)ÙlÐ>-P⃠þÛ|!Ë–-o£»ûêŽaʸ¦GòP````ÒmÆÆÆ¦uâ±±1vïÞMgggÕò‘‘FFFèìì·n:ì9öX>tì±Õ ‹ƒVù3jÉ4ƒïÏnpH…«*‹¡8ÒÓÓÃèèh\½œ$Ïu]Ç¡P(Íf«µ÷÷÷ÉÖË/•«$ê)!sÁD¶ ³·OïAxá€ßñÄŠ“píJx ÅN4¤ëºèºŽïû¡½Gge¨wy$ï…OÄó‚öj_ßÜ…˜ŽÎ©qÊÿ»T‡ó#ÛXML›êÔz.•f¢K}^£Ò¬Œ6;ò¾ZyS^^ˆ”Á‰lGy[#ò·:Ot9T¢Þ«ýµò1ÔuYÝǯ9žš“äÔ_;E¥©ì–ïK½yLª[áGöU×›ŠÜ/R†èiu¿¢û8‘c«2DË7Õ£á±xçHÍGÛÖøïÛáhz‘ï|ç²pì‚è=žç‰W¤KTFFFšr»éä‘(‹UIì7oÞ̆ X³f [·neýúõ¬]»vF¶§VLQ9S™0øe"T´š|R©` h&)žçáºn9|šÁÁA  U¹K”x¢òw ‰…B!L²•]¢Ê óA=Û„¹±Oï轜ô?eõåo'—[˜¹S¢âˆ²ueÃÊCMÓ4|ßó©¼G*ZäN2Ð4 ÏóðE>ˆ)†Q™ñ×øA z•ÎðËÛ§Bh©˜KГ UÞÄ$† ]«& f2™p°Ë¶í°«¾»®K.—#›ÍbÛ6žçaY…B!l·& ,Ë #6DCišF¡PÀ4͆·Ú‡¹¶Ïßx LŠM&ƒ#s‰FÐÄSâFí\ݨ 4W4Q-*€ú‚f¥RTš¾‘E¡š¬f¤fy?Õ\V¨ýTSV§"z¨å*¾V^§„ŠØâEþŽî¯„”hù2TÄ"/r¼žÈ2“ŠÓ·:Ž"*v¨{©ÖwEÊjDöuË×®®!*P­ˆÜGÕô·"ÇW×\OlñËËÝÈz-²N•Wÿ'ÝÝœ¹c ‰ykÛ¾Zƒ‡¨S 2~jIœ>!†4$¨\tÑE¬Y³†îîîYŸpóæÍ °eË®¼òʪu6làÚk¯¥··—¡¡!.½ôRz{{§­xúÀž¡!P¢Šz«æ¨+¦ØvG}úû+ÂÊtÉf³av *ñ{±XÄ4MLÓ¬V¢BI´¡*óÉd¶ scŸÞñÓÒI¤ŸXÓ–Þ)¾ï‡¡ø Ù§ò¥Ói …étMÓÐu]×I$ᬠÞO .ê=Ñ××v83™ ¦i†ÇVN„幦PÇšhÖFmã#•Já8Ž“Åó*_åáâû>š¦á8Nø´ Qo˜Ú²(”¤Ö)áHDá™3öY‹çU•¨˜bYA©¹IÛ·i‚Þ‹AEpP‚…êqéåå”·é!È;íáe©î Õ†á&è ©í(Sõ‚T³«|5åoXBeê òdñ#ÛY=E·¼šîV¤Ò‹V=GU^ê©|‚f>Ú¶qÇ÷+^kÅbð~ðýJ[:š3Í÷ë×ÿ*<ötÚßJÜm”Åjt±]o-­¨;§C‘"^‹+ ³üo2Ô„… ==<<Œëº$“It]COçóyòù<©TŠt:M˜´¿¿MÓH§Óäóù0§§š 4::J>Ÿ'N“Ëå%›Í’ÏçÃöq#Û ñ§YöùüAqå«_m7'WJ†Šós£ÛG«©èÓiL°ªE³æxŠÔ$ûÔ;f#¨&ödUñT·µÞyU³6Ö™k°ô:S"„a†Š'Æn9µ‚ˆê F·Ÿ«†„ê¦Óé°l*D˜Œ¢áÔ£–Ù¶¦i¡H¬i¶m“J¥ð}?ô¨Qžz¦ibÛvx?Ô½‰îj.¯u¡0öY‹¦Uוýý''õäÍ|Ø3¶– ]ƒá/CþtÐö”Ýìó~*‚C¼?-kÛÁÈ‚šVÉåy•wœãçWçrÝàS(Û‹•2˜f¥,ù|åút=Ø_?¶3ŒJl;8n&ì«ÎeÁ:Ï«.›˜R©`½ï‹•þŒº—ÉdpwìØÁÐÐPxl¯;6 D% ¨eÊ›Ì0Œªä›š¦…bC*• Cvår¹ªa=WÔ8\o=Tg´–‰ò2Õ›í=†êXOv>%°@Å;G‰SJxò<ÇqBAÚ¶í0|™*G#Þ.ccclݺ•½ ¤Q;×ö¹wï^&{«Ü Szzàƒ©@ãp]è7à xøËÁ;¼%àž úaà^h£FðæSà^Å`0 ‰k¡ÿÒ²ÓÉX——÷ÏÀ^ ú³  ÉÃaøÏ‚ô')€ÿ ö쇤…Ð ‚º^ùç×öx'›N¨Q¿'Uû˜©b5JJ¯\zÔGÅn™á6Fa'add„{ï½—^x¡ÕE™æ£m;Wø~0hžJ»©í•¡<Ôcv4¨3jn¾šššJeX åµm_¨Ÿe¹‡{S“{Ý«ë…^ *‰áO„Ã…ÞPè)Q®žS5>2Œòçqõµ®*ýU Eý^:­?g¯iî¶ýëWÏ—ëE®¶©NÑþrwwÚîiÈÂrÛPåîiNÔrûPnj»Ý]©÷­;þõø_Wº¯ª<þí”–É÷ãyúé‡7î1FCB¥'Cum{4R ‹uí^5ZòÏ'˜L&I&“˜¦I&“ñ†}ÓÞÞNss3ûöí«tQFd_KõåÚö7O<Áž|lÊ` b$ɵmÏÔµmmmmÑ{dN2ð«cÅÌ™]–S£h16lÝ •r-Z[[{½X3gN— ÌžÞ·úÝ»Ýß b$âÞH$“…kª5\oü>;¾»Nÿ|j"iqôX½z5kÖ¬©t1†Ý@ãsÙ²e^×Oж5ç+¾‡·Å^JMPiY©T MÓ¼ŠwÿüFápØk-§~Dåù“/åzÀ¨yi‰étÚ2,‹y=Y^{íµJïÆ°H|Θ1£Ë¹³”aÀ»ò•‡Û߆¿ÿ_¸ãKðì÷À¾2!°ûR`œ{ÊR˜ØQuõæqß¶ ó¸ãàí·INžLâ3n§“üˆ\»w“©©!ùÓŸ’øä' ?ÿ<ö»ÞEwŠ”Ôºu„|}ýz²Ÿþ4á~Øòå4©Ä›˜xç”S?û,±P§­ …)M¬/~‘ä½÷’¹è"RS¦À1î%P4_>#—óºž;wbÍ™ãMøîw1ócó¦fSY†ŒaÐd$(Œ±ÇMú8ù÷ÁÎ'`â¸SĤ)  Ù7ßtËsø0ÎÇ?Ž>}:Vþ¹ >öX¸í6²³g»#>Œ6na mrㄞ~šØYg¡ïß~äˆ7&´8»váìÞM|Ö,ì| cC÷Ö®ÄéÃkz£ÍÍ̓\S° åµmO ÷ÚV AeÛnòÜ^ápqb¥©Éíµ zwd³Å=$zâ»m Cã‰QE®mû~m{´R½‰Õµ–jˆ¤Äb1¢Ñ(áp˜úúzïšÜ²,r¹œ·\Â?A›èUmm-«W¯fãÆ•.ʰèµí{¾øE´{î!“)ô˜b$ȵíÀ®m-GÀÇß¹‚8»èyIº‹¡°bÅŠ^{Q D`*K–,aݺuEµ··hb£W'Ov[ɘÝèéº{³™LÆî+5ù²¦iD£Q‰DÑÄÓÒ#EŒfCŸÖ«¯òN{30´ãÙª!¹Ô¤”*ybY™LÆ›×£¥¥¥hŽÕËÁßâA†¨>†axZªQK~¼Û¶ùüç?_é"»¡<ú=hÁ“°tàM¸ëûའÒuù¹Ø—’&ÜJûþÃ0ÚÚH}ìc´©ÇŽ!úõ¯cÏKôÇ?F»ì2B_ûš72W8—#üƒ`\t¡ûîƒ÷¾ÂT(É+`Å p¢ù»dÕøÐšv,楗ºÓ®,^LHÍœI4_6°¦L!ó™Ï¦pi æ´WëQ‰sΚòÏ«d†›ØQ—ÙücÉüïMù×…ò?jûp~)Üäú½)¿\*¿màÊ+Ýyg.Ä8æì ¼òo'bNœH.¿lËøñ^¶“ß¾3y2©eËÜιùçUbGB{÷â´µ{þyÌ3΀ã'9q¢WŽ(îÔs*I£>êsP¯Q=‡üû}›:æhá~¸bÓÏqܤˆšË ÃEE"…ù9rwCæ+š †F>ÓhhU~ŒB&0A!î£0/‘w@Q˜áUeõ Š?ä0x]Á, óiù¿ÓùçÔ²þ,ŸMa.£¢§kVÓ)YV•G=¦‚9I!d—YÎð­×ÌÿÍ¿F÷mßñ-¯^“É¿F} ¨÷O}9d}û¨~WÛU¥ËúʣʯùÖ…ïýTQ6[}* ª²Þ¦o;êsQïÿhŸÀg$âs´ÒuH$â ÕjFQb( !«&¦O§ÓÔ××S___Ô;\ˆrŸSƶû?/®¢wCyîtÍy ^Ù‚ƒÃ e^“H$$©"«Ï •ÖÖÖ.­•Ö¯_ß%ÛŸu~ ^7Ö††6nÜHkk+—\rI¿Öc ;:Ü?²@~áÒÉè5­0Æpë³,oX/5ÄW<÷&jâh0$ñù/rxÿ,NÐ4‰¾Å_olÛöæ°ù›ßÄÙ¼}É’S¦@(äVîÏŸï¶jøò—»ÖÛ…Ãù“´¿R¾K'o5–OœB}§RzÊ¿ÎÏÀMTPæµêy(ž^Å_¿LÉëBe^§—Y‡Jà”î[ã‹/â,[“'“ÕtwBˆ¡5”çN :ÌÎ÷턟Á¦MW=ŸÉd$™"­O 5i­¿{iCCÃw™Y½z5×]wK—.eÆ ¬^½ºßc:À˜—^bñ›‹Ý“ü„“Ù¬ÛJ¡¿ aêëëijjÂqššš¼‹ôHG›ÁƧ©u2ñõ‰ŒÓ8$ݯMÓÄ4M Ãð’*€7¤W<'˘›â¨0çOå«)˜¤Áb€(ÌÃÒ?Âþ:xùø9îäð¡Ûo'¹j•{ÇÚÒRhþ¥/¡9ΈÞÉöe¨ªj`¼ôÖ²eXóæ ùºK?$ÀâŰx1þaÆÃý(¤Ó^½Ò$FqrHÕ ƒ{ VO¡NÙÉ¿¶ŽBݹZ~Ã[oñÔi§ô[<â†26¡09ºÖËy ZÞ†Ô™½’ª Õ{ œ&Q˜KÐ:LRüAB×,dééS+ów´›×ûõšP7Ï—[¾Üõzg7¯-WþruªÉn~è:Êñ_ߤË<ïßïîÖßÛ6B%¯ïéùî®·z¹ËnÍÒ@ÿæð©FCŸGMÓ”¼„‡è«Ä§Ê[VÏs^ !nHÏö³é’·‰Ÿ'•šê=¬†õVe…¢>%TV¬X1äcÅ®]»¶ìvT¢F%qúË6=þ8/ŠÀgÜÇ,ËýH655aÛ¶7Ѽ$RÄhW.6aâsÎ|Núß8åÃ{øÔ§WF•è4MÓëF½!¾€¢VoBŒÃŸ>÷çÙÀ†OÁ”ùpð:˜ñÚtç-rš†¶olÞ\˜áZÑ´â¿Eß]tQQ£÷ЇÝI9¢Ñ²½Jù«ÆTýz·?BaØ0Õ¹!“ͳ[·Òüüóð‘Tro‡Ôp]Ûú¥¾Ɖ`ýrçås9Hjn’ÅËœ€LÈ+02çN!ÄÀ e|þ|Ë&¿úª7¦bpFâÚvÿܹ°qcÑ0}–e‘N§¥þUZ`æPQ»wïfζmÌyb|Ñ}Ì0Ü!K|sÉ÷(“Éð‡ï|‡¿9þxÞ<ã ´¥K»Î­`ç§®µ,wÅþ&™Œû¿4‹£Ì â³soØÂ}ßiàÿûÿ¶ Ó4½9‹êêêH§Ó„B!/>¥õ‚8š UeÐt^æŸF^²³è˜×‰å2ŸÿÛ©'?,ŠišÞüP¶m£ë:Žã …¼^zÙlÖkü…žzê÷~‰FÝëšl¶O •Rqºõ¥:ô6,Ùh5T±é8 íq0fƒöaàF¼ž#2¼‰ý'‰!‚k ñYûÆÞ–v=B «Áž;Õh¦L˜ƒõHùa½d¤týJ¨¬Y³†ŽŽnºé&Ö¬YÃm·ÝVô|mm­WP)¿ý6ï<é$¸»ð˜iB:ÝÃBÙüÈÞù€þøã\ßÙÉ1gÅç~øCÆD"ÅF‰Dñ2¥]— b±B'-Üå:Na yÇq_ë_·ZF×Ým¨þªþ»äLÆMèF¡%°¿ÂöÝ×ø×Uºÿkm»ë@£ªY‡ÊB•ˆTµJVÛVë)å/Gwl»ð~”n£”ÿýîn9?•ôR2¨jwû&ú̪…=ÏtðÖØñò+“Éxs¦Äãqr¹œ  Ä0p 8Æšá¬ãà™Évýìg‰.]Zéâ Z&“!%Fü½ÛÀŸ©±±‘Í›7c«@cc#ÉdÒKb8Žã%5Ôä¼àö3M“T*E8ƶm²Ù,‰D‚t:M$!N‹Å‡Ãd24M#cšLñEþßÿH6›õʋżÄH$ñ’*¦iâ8Ùl–P(ä%Q2ù†jŒût:í%v’É$¶m{C˜–½Y¢ù¦Ô4r;4Hù Ø­Á8¿—¿t”S b% ¯x©T*…¦iD£Q‰Ñh´¨¢ã8Þ9Ð0Œ²¯b8zs"çH£v!O´ óp‡;1_ü¢ð\é½™AÔç„Ê׿þuxࢃº¡¡›nº‰uëÖ±~ýzn½õÖJï§lnóÆ‹V“v–¥žÌ'=lÛFÓ4N½æþôîw»ãõ•ëÖ’Lö<~˜a@.ç&Nt½ëÐ'ªض݄A8\x㸠•€…Êb…²FqBAÓ ÛÐ4÷5¥ëˆDÜåu½˜ñW ¨ÄZ¯e¹ûägš…„Œã¸Ëû¿ôÔä5j;ápמ<*1¥ÊÚÔÔuþò—ÖÄ«ä‘úuÝýlü¯óoC­ËÿùY–ûž—~Æ¥ëH$ ït}?DÏ&ÖgÚøñ/û¿¨eY^%¨ªÌ”îŸB ­îpü¯ývn€qSàÓŸi ÑèY‡ª˜Jô–TU=?ü8¦izc¿«­eY8ŽC$! aétÚûî1 Ó4ijj"‹‘ËåÐ4 Û¶‰Çã„B!7!’OdX–E8&—Ëaš&ñx¼è;«¥¥ÅK–¨ž+–e‘L&ùÉúõÌ¿á>’?¯9Žƒã8Þ>ø¿ÿT2¤4)¢zÁ¨2^G%S¢Ñ(Ùl–T*E4õÊã_¶ˆ:Ÿ«ë’>|KŸÁ!’Ÿ]¯ä§ zE¿; !D¿ù“&~¶m{=/£Ñ(©Tª¨Ç¸ã8466¯J_#ÄpÙûú4ôó†aÅjXM‡¾MÜ—o F×khU?eä׫åÿ‡¾_oû—3Ê<n7á(…Ée4ß¶ý—ÐVþ5Fɾپu©‰ð4Üñ[Ám1£Æªõï“ã+×hí-äfU ˆè³Üß§N=L"1Ù«bK÷Ø"^ˆ`èSBeãÆ¬[·Ž{%K–=W[[ËêÕ«™>}:7Üp÷ÜsOEwhûĉÌÛ12àÄÝœ@Ùžbª^×½DB"_‘’H$hkk\AJ+íýû+€J³®ºÞ5©PJ-Ó]¸Òm”ÓÛ6B¡Þ×ÑÛðJ–å–±»mE£½ÓÛ6†¢œ*Ö“x|ÈZì•l{Òf{v¿M$^å§išä$‘%İH‘¯ß“÷ÃÁóvóîv›Ü;ÏÆxèPÑkýɾ$“ý¯W•WªÜþ^)*Y“J¥¼ÇS©¦iz¯÷mØý_õ€-×B ;™oƒs>„WAH’)Bˆ¢ë:Ùl¶(qŸÍf»=ù“)R!&FÚ‹55œ8q;½Ždã^ø†q/p³¸ n #'ÿœ;Vi·ò<Ä|ëÑq/ž¾×ÚÆ3R—yV~ä_Ÿ°ÄKt$ó˨2˜¾ç”8ÐHabºXÉóª¼*Á¡å×É?oà&W²#þ6¥:…ŠZ‡zLí¸ —-ßú³ùýQÉ•h0óÇ}û«$}Ûö—[1ò«÷µ¨§8™Ï/£Þ3Ý÷û÷7V²M‹BrÈ(Y.™½ãÛ÷t¾ü6îÜtYßç£&Ì—þ ói>³ÑR4€’H$¤ÞG^Ÿ*<ð ]’)~«V­"“ɰqãÆ_7Ü&¿ú*§? È7¤<ÿ ÉèvHdŠ{YtS‘¯išW¡"I泊m3cÎŽYøŸÆ÷ûµ¨J¤„B!™#EˆafcSð‘o>ÁŸ;›wm[Ô1o¨©a§üêëë‹*óu]G×ulÛÆ4MïûÀß{Ä0 ¢Ñ(‘H„x<î%Òé´×»C½F%ü=CJ{½©ä¿i$zÅ-˜>Owï¸cØ·…y§Ç!‘HxI•²-ˆÕp™ê=éëÄtbÐì­™ÚÓ¾¢Ò¥BMTã‚Ò„ŠzÜO’)"6˜Fa€ ·ÝßF¤·2\U¶Çq+É“¸ì-*꣸ëþê!õ»¿‡B_ê}ýÕOåÚ£ݼ֯Ó÷û@ëšÓC¼ŽîB=ÔÍïýÙ¶ÿ5}©¢Sï›ê¤—¬#×ËrP|¬”+¿J¬©Þ>¾ÏmkóV|J¿¼½û yä5Z[køüçÝÇÇ‘sˆ¨ ž”~ÅŠttt=V[[K{{{ÅvÆf´µqæ£gÂz°Mжü?ãVt“áTÑd2éU(ô6鬢¦¼ÕNëkÛçŠYUYª†â‘dŠÃÏv}þ÷÷uÄý Ö¿/ÖܸšSDÍ â8Ž7•¦iÄbn³2]×½$†axs¨^(jù\.ç%ºûÎÐ4­è9•( Ä0‚šÆÜ¹sG|<'MÓ¼¹]Ôð_¥É.5‡•JD}™[–Ûs%—ùƆó hs ú7•.‰b(%ÅCS†›³V#çrÐØX¼L8ìŽxlYîëÕ´›~Édaþ×—ÛNéˆÌ¥¢Ñ(uuu^å–mÛ8Žã …©¨dŠT„‰JÚ¿?Lv/E,às&tš`&á+6ÔY`XùëšZò½L·>“Ί‡ª¡Î¡0\»×##¿L‡Cí‘eå×Ý͵”*ƒ\kõLcøºÖûë2pëPÍ4 ãíǹ袿淿uÃ,wëLÓ”úx}J¨LŸ>½K¢¤¶¶¶è6nÜXéýaöëãxkÚ[Þ .ôç‚ÑÒcKÊÆÆFÒé´7>ºbhY55LØ=¡Ëä‡ä‘›2!F޳Î>mÖñˇô^DMN«¶m{¿g2ož$5Ù{.—#—Ëyó‘¨ïÿ°[ñÑ:cKËà×1ê(“ÉxI-õ©'e{¯¨¹Üb1™_lè¦Ë¤þDˆÑ¦»º"ÿ×h_¾RË%Dú²\_^£†ÝU½RJ‡ÿRb±ñxœT*%“ ‹Š™¾i¡ðøÑùð½ÔW¤Ý–·!&æ3‘ÑhñI5›-4 …º&FTòP%OüÁ›Ÿ?Ï›û5îú¼.UÍ_ë>›-¬CÍëŸÏÕ4ÝqìÛv‡\õ—1‘p×£ënR&.^=¯”66N$ û¨Þ‡tºø=ª¯w· ¹ÿ§ÓÅeˆÅ ™ÛrsΖΟ«öÓ?4®šKXÓ *ÿóê½ðo·ô³L¥ŠëþÂá®sãú3Ì¥CÈ›fá½Pó—nCÍ7¬ë…Ï\.Òúg7„~ K~ü(ì‹´·>¶nï7„˜>%T.¾øbÖ¬YÃúõë¹øâ‹Ë¾&“ÉPSSCCCCÅvÆ&ï{•g¿|€÷ò^ ÿÝ©¾Ë-“ïÂlÛ¶d@…&ÎSOqÆÞEsÚ.àÔ^_ŸH$¼çÙlVbSˆb¼ÔNzŸ¢ª_ëöõxP“ÙjšF}}=étš––êêêÈårEÉÿd죞®ßøjýF‰Åb8ŽÃÌ™3Éår^Ï•l6[>‘º7©‰„ ù9”,HÝÑ÷âÐB…Ôð»*¡¢†Óô‹ÇãÞ›±XL& ±ü0ú*üøøë(ÜìOì…è¶ÛBo øÔu㸉ƒrÏuGUÆwwQÓã¤/}36w¯ÃÊeJ“ÉžËÙ—ë6ÕØÇ²Ü„Jéuyoïa_æÏu»'¸¿û{)ºî–Õÿýã¿8r÷'ê¾Auéµv6[üþªÏÊq s.—~—56ºÿõP×(ºg‡Ð¯rf˳Ø×ì/ÊY¥ò D©A×§„Jmm-«V­âºë®cÕªU¬X±Âë¡¢&¬_·n·Þzk¥÷‡úõ3™3îxR¯¸Iã¾4ŽÑ4­ìDHBˆ!ò¡ñæ½cØ¿ÿ´>½<›ÍÊœ)BŒ 5h‡µs'3èz3Xªû¶aÄãq/ÎUëWp{H¨9SŽJjÑ«z¶µµy‰.MÓÐ4D"Qþû9úçhfpf—Ô¥8N¡5«®»•ª"#soìÕx@¥1±˜ûzM+®Iøf¦Õõ®Ã·Åbîg믨il,´¶µí®­@{ºÄqÜåT ÏÒשР©¨¢¢Âá0‰D‚x<^v¸/(4zPI—X,& ‹·cÇ<÷— q¸¹·™é@ÓÜÞ!ý5”-”z*ÛH\Gª^Éõê½*÷žõv i½'‡JË^º¥»DW…z’&ÎжµÒ6~Ó¦ ÞvÕˆKˆ Û×®^½šÕ«W³nÝ:B¡§v§v—]vÍÍͬ]»¶ÛÞ+#ÅÆïÚË©sÿLôOÐÖdöºŒjm#·B {ü\:ÇLdïÞñ½¿Ö¶‰ÇãØ¶íUÞ !†_hˬi5¼û ÷~l0£í™¦é5TÈd2$ r¹œ7Œ”a„B!/¹¢âü¨è…R…ÔÜ4jn•R‘HÄý¥L Ì;¾ô¥J¿ºm†dèžâá>üTÒAQ•)ÝÍgÃæÍn…‚zC ?’˹Ej|x¿h´ÐòSÉå É”r±›ÍºI—ÆÆâá5ÀMàD"îÿõõ…á5üÏÇb][˜&PWWøñ'‚Ôsj›¥KD"îóõõ0sfaYU†ÆF÷ñÒÖÇ–UXV%²ÀÝï™3ÝeÕò¥û©Êá_Ü¿U9Ýõû÷ÕqÜÇëë»~öþeÕvUy ïMér‰„[^ÿvýï‹zÌÿž AaØ/5YoÒé4¶m{­Œ…)LfÉœ·àÙaH¦!†Î[`XËxPû,<2µèÈ)DõkRúU«V±jÕ*š››½Ç¦OŸÎ’%K*½žÝÛ'Ž¡qÓh1&vû:U©½-a…!öT8|äàœ_—J¥°, ]×¥U›#ÌXÿkœ]Í”v·N|æLèìغÔ9VM2oš&™L†Í›7{¯ Dk½j¤ÆePCÿu’×XõR±m›P(Dccc—ïmÛ¶12:}”šùó C5ˆ¾IZ„įW“ÛòþÂãšæ&FÊé­åh¡ù_q¾ZÆß:´t½¡[™ïßvO­aÕg].áÒÓq ÆY÷}_-×ݲšV~Åߪؿïþrv7GP<^êEí³®C[[a}Ýígcc×÷)ußO]/žÐXI$Êó¯–F»&ÓLÓ}¼» oÿ{gš…ÏY½/ªWÀš5á§*}i„¨æ@lllôO€;oié:åz_ µ©›§º-må2Sˆà:ˆÂÜ73K:)K£ZQ-ú•PQ*9OJO,àê¶³aóípÜq ëöµŽãxÜ !†ÙЃɓ'÷ø²p8Œ¦i}jý&„b'ÑòÓqŒi‚Ÿ¯ë¾¾¶/ ÃðæA1 Ûì\ôÂqºN–0ÑhÇq°m›úúzÂá0¡P¨lK2Ó4™ýÕ¯2ýƒ¤æðáJ½úlH`.ÿ úåË`¨/WÒ,íÿnI ÙöÀ†-éÏ—V¹ëÿžX©÷«»ë5yn¹åÂáòeSÛ+7>»JšõtŸRº½þ¼gÝ%Í„ðéôµªˆF£E͇B!¯aDg™Ö¡P¨èñζТfÌhãRg‚$S„ºüÀ%SßšZ4ꫪ§•ú Q ”P *8ãµ3pÎ< q=¾6“É] !†Ñã²sÿXÎ;¯ç„J$! á8Ž$;…AÀôIpDóõ¥ý©U“Ó666‡1M]×åÛ_–å&T^±©išW±¦g@—ïîl6K8æ‘×^£Öwcä8?¿åÞ5~¥w%Ð2˰&}(8Sˆ”«øAîÅ4² düÄ ¿BPÏýúKø’Q"àÚ ¦xƒlVµ 1»ÌÏ%Dª„ ÀÔÃS±¾¸=Ûóë’ɤTô1B¬EÓ˜tÈä¦èEݾ&“ÉH\ Q!ÀÜ@ÿëòÕP}étÚ›ÿ(Ý“Ë%ü­• Ã(J¨Ø¶M2™ôz³øY–ÅÎ;9púé•Þ…@ËNº óŽâyà…BQÞ‰¯ŸÄâVºBˆÞtì‡çsÿ‘+0Œ‹…À¶ué"ªÊ¨I¨¨[õ×§½Ž®×ÒS ªIò¤âVˆ²o¿¿o™ÓË7º´mÛ›sAâRˆ 8¡ßák%Ô7*nëëë‹æH¤i#Ó `È‹íNXï8†a`š&Žã”½)2 ƒ;êêhŸ5«ÒŶS!ú®ÀwXB!aú„ЮøH¥‹!„è…3ñ0œâØÜù´´¸©dBzQ-ÆVºCÅŒM»ylÒf»¿ùTó¦¤Òý^10㦱èìEÝ>mÛ6†aµvBŒ ÀÜ/nšfŸ&ª} ë›?¢âÅÖq‡H$â Çq§K÷ýL&Ãã?^é"› ÎËîhQòK!FƒD‹J©Çg΄º:ÈdŠŸÏd ¯©«sJç?+ÝN"Qü¼iB}}aõõ½¯£\Y…ç܃/¡=;ˆ Z!Ĉ°ôš.©{ é¡"ªÅ¨é¡ðæ†?aMhÉOl]þ5±X @&ÈbYg.æŒi/ô8$¸Ìi$De5~Ú®ìß2¶mcš&ÑhT†÷ º^~²è* ëº7i±iš^ë2Ã0º´4 ‡Ã>|˜7Þx£ÒÅ®‡²8ä†Rˆªå8…ÊqËrÿ‡‹[ý™¦[1ŸOB]Çø««sÿWçXÃ(îîɸ•î†QØ^.W¼D¢¸¢^Ó ô^¸¾¾ð»m»Ûð'÷3· «¿eé…}&ã.«”6°íâÄ„m»ç<ÿkLÓýQåtœ®Û)MLEÃSø×¡ø×÷ž©îm¬Åh´÷ƽ54 …ðšf«÷£´\åÖ±r%¢¼Û~‰yo×"W¤B›ÑÑ'@[ÛÙE«†X†tÏU`Ô$T`¶6ÞsòYœÓ͵ê"?BŒ¬³6MÄÞz9¦Ùµ®0›ÍbÛ¶´D¢’6>,ïÒ0²'ª'‚a’ *#5é÷0+Mg2™¢ïøT*ŦM›xç;ßYé¢×o3„/’ó¢U#•r+êýü‰Ã(Nœ@!á ¹ rH½ ¥9ûP\±ßÓvTr¨Ã(>‡•&4­ë@é9Ïß°À²ÊŸûºÛ.¿|P»ý‚ó¥m;V#ô­J—BÑmë[pbˆ9s. #HÈ8 €IDAT2ET‹Q“P±€ºžæÎ×?Í¢n®ñt]'KÅ#ÈŽ9¤Iï({ÿbYÙl–xéM¨bØ9ùëäy„ÎkòföXïbÛ6™L†h4J("Ê8·¢Wáp˜X,–ïAì6lyê©§xá…*]´àzÞF_^éB!zdYn‹rÉMë=‘áO¢WKROåìmÊ%TzzOº{mÖ!Ž*µ³kÝ [!D°MžÉÌdþüÛQ ]×%™"ªJ *­­­´¶¶=¶téRjjjú´ü”¶mtžÜÙm£™l6+*Ä 4>-@›æ°õÀä²÷YÙl––ÞZÅ !z4˜øÌöô)hۦͺ O»;Uª‰Ç#‘¹üpÒãSôFõXq‡l6‹iš\xá…GÅ<*Móà§0Ÿ„ê›MGˆê1Ø{Ob1·×F5ÌÍ©Ú>È)[T‰Äç¤C“$¡"Ä0ì¹Ó¦¼ h›Èk¯ý­÷x6›•9uEU TBeÍš5¬_¿¾è±µk×ÒÐÐЧåÇ¿õ×¼þúÉÝV麎Ô.¾BÜ€ãóɽ̲†ßï.ÿuÓÔÔ$q)Ä æüi¡'þŒ=þRzël’J¥ÐuÝëi D_ø“n†a`Y»víbìØ±•.Ú°Hl.xã ´·æ`\PéÒ 1º öÞ“\®0|”ƒ{BÕ€n‹7‘aa@Mý‘ôý®Î»j„? 0pYß¶l`3P—. Dò«jÛÙüïqßv(Ù¶ÞÊ¿Þð•SRùÇB¾u¾uDòÛHæ÷[•U/Sþ¨o›ª¬ñür–o½jØQõž4å—sòÛI•ìK˜BËp~Ý ê:Ô<îÉ|™Ôvœü>„óÛ@ÚWVÿþ¦JÊoùÊ©å—kÌoS­ÃÊ?§Þ-¿Ïê}UëTåÍåßW=_&õ¾ê¾õ„àÊæ~NxW¥Ÿ¹Å>7!İô¹˜ôKHÝ©3qâvï±d_†§"@•Péèèèw *ð‘— àÍn‡EÍd22½4Ðø´¶=ÃÛvqÎ9€ËŠž3M“l6KºZö `O÷>þ”mSpæÃæGéq•h4ŠeY2Ì—Ã0øõ¯]ébŒˆÄæëÓ¦¡Ÿq 2µ˜Ãk0÷ž@~ÒtÜQ5ºŽ[©oRè bäšp+ÐUEoÊ5ÔÝÜÍïÝ-Wn;¥¥»Y‡*koåá&z*G¹ï³¾ŒÂëÃëýåö²Žî*ÛýË•ë8ß—*„¶n¶éçá¸Üþøß×njßñ§;xïëCªÛ€ãSÚû1¬}îN˜ü7ܰ…¿üå÷Àõ466ÒÖÖ6àu 1Ò•Pinn榛nðò“Ÿ†Úó—vyÜq,˒ᾄ„Ƨ3y?ØÆüù]ãOµtB Î`ΟIà´[—óÒY½o‹ÅúÔ«ÌŸpÉd2ÞÜeªw‚eY„Ãa²Ù,º®£ë:¶m …H¥R„B!,ËBÓ4lÛFÓ4oYoSµ,¸ ZÅ4MB¡¶m£ëºw …¼çÔ6]×1M³è1Ã0Ð4Í[ÞqÂá0V>ë¤zê¨çB¡7»z\­ÛÉGªëº÷¸Ú'ÿ¶üüÏ©}Qï¯z¿ÔëÔ5Žiše×4Ó¦McÖ¬Y•.ưHl·g™I p2}›KZ10ƒ½÷ÄÁ핦kB¡\e¸Fuµž—áÁD (>«)¾„¨Rƒ=wšÀÞG,¾pç%œ{î~ïñÍ›7xBTB`*|ýë_§¹¹™ššV¯^ÍŠ+z\nëÖ­¬\¹Ö®¥£s—^:¡ËkT+xé"†ÚÊ•+Ùºuë ²óÕ` ñyÿý÷S7K§uÃràí.ϧR)'S ‹7²fÍvîÜYé¢ »ÄçÎ;Y¹r%m×_ϵ‹£Íì}Ž×D"Á”)SÈd2ÄãqR©”—h€âä€ã88Žƒ®ë^ܘ×4 ]׉Åb†iš^’#‹F1MÓK¦¨$B&“)JF^"C%3üIµM• Ñ4Í[o6›Å¶í¢†*Y£&Dôï›Ú?94M£±±±(Ù£†DËf³^òE-£’D*9â8NÑöu]/êênš&‰DÇqhjj"‰N§Éd2ضM4Ŷmoޏh4J,CÓ4r¹õõõär9"‘ŽãÇq‡T*E:FÓ4"‘Ñh”d2I$AÓ4Òé4‘H„P(ä}&©TÊ+c"‘ wùW 3U6•<ó[·nëÖ­cÑ¢E#)#o çÎ÷>È®¶ûù×Ð¥•Þq’kÛÞ¯m?øóŸsÆŸþä&S¢ôk²#•\Wç$ÿ9ÁÎSç0"]Qçu.2MÓû[¿TcÕ8¡ôG%æÕ<þ¿ÕùW5>‡ÃEË«óYi#FÿµÚoc u.ô7@PåQso©÷Mm[QÇñÖ¥Ö¯öÛÏßA½Þߨ¡týª¼þÏM=ÖÓßþÇT™úÊ ”®w×®]<öØcŒ7®ï\•ðµ-+¹xÝŽƱCM®mûVo»zõjX²„9ϼÀòåË½×øçèb(­Y³†ûï¿ȯm“Pimm¥¡¡U«V±víZš››¹îºë¨­­íq§çÏŸÏÚµk™ùæ~Ö¼ù$Kí3˾NÆãÃaíÚµ¬Y³¦ÒÅvÏK/½”_ןAí~‡E‹:‹žK$†!=ÇİX²d k×®uî£Ü@âsΜ9¬]»Öý Ðç‚ÖMBÅq"‘[·neÚ´iìÛ·Ï«À‡Ã„Ãat]'“ÉN§5I}OÃÿU"ùZ®ÿ1U™£‰D‚¦¦&/Ù ¾ßüIˆl6ËæÍ›1M“H$âµÆjll$“ÉFillÄ4Mr¹Ùl–úúzZZÜ1HTbE%Lt]§¥¥…H$B,#N“Ífill$ …¼ßãñ¸—dijjò@étšD"QTÙäÿ …Bd³Ù¢¤”zÀÌ™3½.ú‰DÂKöd2o¹/c·bÅ jkkinnñÏt$ æÚvÙ2I¦ˆÊkÛÞ¯mÏøõ¯Ýa½ Ê&STBB%²Ù¬×(zN%üÉU¹¯ªÑ€Z·ªôWßÁ* îNõTŒÇãÞPª‚ß¿>ÿkÇñM”kX ’(Ñh”l6ë%èýÂá°wžP‰ ÿ¾¨}ð7¶ð¿FýtIn”&J“0êܤ<þë˲¼õ•ö~U (ÿúÕzýÛðoW½gêsUEJ-¥×DþäT¹çK_£žWÿ/[¶Œ;î¸cx‚"@sm+D%ȵmßêm•ÍmS9÷Ü … ©³ÃeõêÕòÞÀ$TTå—ÒÐÐÀ%—\BsssŸ²HúËÛ3½®ì„ôª2@10ƒ‹Ï™Lhogá®7\A’Fˆj0Øó'=„5éÌ’á…,ËòzH{ì±\}õÕ\ýõE½OüâñxïÛeüÉ•P(ä%=º»!ˆÇã^b( œN§I¥Rd24M£³ÓMB«d„JÎ455yï.—óÏår^%Œjí«®}ü]蛚š¼çT/#5ŒY$!™LzI´h4êõ&²m»( ÇI$˜¦‰ã8d³Y¯²Í?Ìšª¬*õƒü€3Ï,ßf´tlö“¿ÂÖÿ˜¿¥´ªøSŸSio)+ùÒVë€÷y« Qõõ}àoñ­¶«ŽÿvË gçïÁ¥*cK÷Å_µUyZZõšr•’½ñÏ©åË}ï•VÀ–n·§á÷ü­ðÕ{Û—2–}Xn½¥=àúJí÷¸qãF}•Æçü_]/L,žWÚKÑL†Qôí†r(©^¡¥úº•€ñÿ]º¬:®z:¾üÏõ4´o¹rõg(àþ¼v ïuoeÊõöõ5úÓŸ´Íj2ÒçO!Dß ElZÀ oOfþü½„б@ÛŠj˜„Jkk+,Y²Ä{¬¦¦¦ÏËÏxm' ǼYvÏžn:„½T|Nž‰ùf;×ëÅ1˜Íf¥‚C`0ñiïÛÏý >tlô=nÛ^åúxÇ;Þá]à–«è}ÓÓ{g†—ìðW¨–öäëîw(nAÛ]EŒ}þnõÉd²h^+MÓ¼äjm¬5¶m{•njx/uäOè^²Æ_eY¿ýíoG}Be0±»u¶~ªõ¸ªŒU-ªU¥½n!ÅßÛ=¬Žõxéðv¥Ç¡ªüÇãGeüû‡1*—DéË\ê=T‰ÿüLе‡^çTC'…£¥‡Ê@âsúoÀÔS!4áõ@Éf³e“Ø~}ùŽB ¾nH1<†*6Ïßòš—oòþ–DЍFI¨477sÛm·qÏ=÷PSSCGGëׯgÕªU½.ëo›È·^?‡¿/ó|6›•y„„ÁÄ'3áÍcÞD×—=|4VÈ1uþy f³¯è1ÿd—BˆÁL|rø0úÓm$2î¤ô†á¶€oiiñ&]Wópx‰6õ»š{Å0 R©”7§Žê±¢†7¡âOÔ¼ñÆ•Þa5¨ØÌËf³ÞûšËåŽúĆCe ñùØûßÏï ³»n7ÑHÃ0ŽÊ!/…NCqþB ½¡ˆMû0|gò›|£¶¶èqip+ªM`*7Ýt7n¤½½ÚÚZjK¬'ÎÖ³™ÄØ.ûoî…7Ðøœ¶{S¼VôØ@ÇöB”7àóçž=pa!c±Ñh´h˜ éå)Jù‡SVB¡™LÆ›G%“ÉMr_WWG4õ†7:í´ÓŠæ­›á°Ûø ‘HÐÔÔ$çL!†Á€Ï H†Üa“É$6`f™—Ú¸£)ô‡ èe~÷³p§qŒîÖ­žÓò?Ý=O™å­ücNþG•Qý­– •,CþµVÉ6ý¿;¾Çœn^×]¹Ô¾Ú¾×÷¥êÎö½Nýïÿ<ßzõ’ÇýÏ«òÚ¾¿K÷ÉÿwéçoûÖ=¥sÇT³ÁÔ !†Ï`cSk…½‡Ç3wî~ï15„°Õ$P  h,¾þØ¿c"ÆÂÃE© ”›P!†Æ@âsÑ”g?åÀ‡B‘ì~!Äà èü9}ÔÏ‚pûí·MHë8¡PH.nEŸD£QïX1 ƒp8ìµ4ó'Nêêê0 ƒššöïß? mU›Ä¦mC"‘ Ëu¬è¿ñ9iÿ$^›{˜ï]p§_z)ùÇ ÜŠïÒŠ|Uq/MûÄPY™ÍÂ¥—Vº#b uCBˆá5˜ØÔ^ÞÄÒ>,®ôn1(K¨ „œ0>xù`Ž÷¸kZQ9¯ýi.û'Àû[Ó4™Œ^ˆ€°§N†“9pà=ô¯¼r§÷œã8rÖÝp«jÞ•U«VñøãWº˜õóŸoáÐE£˜¸×ºþVѪ·¿5³ÝÇu÷Ö²ÝßÂÜ¿nU1¬–?|ø0ãǧ££ƒÉ“'³gϦM›æý¿ÿ~Æω“'÷«…¾¿º³ÿ~>LMM mmmÔÍœÉ+û÷sÌ1ÇxÛUåÃWÖýû÷{e¬:•^½Çϸ­[™?>û÷ïç­·ÞâðáüõÖ[Lž<™ýû÷3sæL¶oßΙ'ŸLë޽̜9“¶¶6o]“'Oîv{µS§vY¦­­Í[·*k¹íÍ›7íÛ·3þ|¶nÝʼyóعs'sæÌ)Zàý>mÚ4^{í5oÙSO=•M›6yÏœ9“ýû÷3yòd¦>Ìëùí¶µµ1oÞ<:::8Ó°}û0ÙÕoζ9|ô¦œ÷ÒÖWº0B!D5±€qüÏÿ\̵×v`š¦ÜsŠª4**ЖÏóŸ9£èq]×¥UŸöæ–‰ÔL{Áû;“É•xYár4³ã7|ô£K‹žËd2Ò:^ ¹d2I}}=§Ÿ~:¯¾új¥‹Xüâ;ßÁÆM^h‘òý¯’-}éȲ,ÆÎšEǸq<ÿÀÞœ7Ñh”X,Ææ¦&"‘éü9j·/æ¹;1ÚÚÐuÛ¶ ‡Ã¤R)’É$™L†h4êýoš&‡N:‰ýò—¬~ÿû±,«h8AU–d2I$¡©©‰D"Ágÿíßøö·¿Í­×]G&“Á0 lÛM©íª¹yÔ<>÷Ý\{íµü×]çÍÕcÛ¶7ä¯ú]íg&“᢯}u?ù ×êSdþsÂá0¦i¢ëº7Ï›a8Žƒvð ö–-¼ØÙÉó?ý)ß¹ñF"×\C<'›Í …ºÝÞ’ë®ÃÊdøÎ7’øö·½í‡Ãa,ËòöI×uoÛ½ù&³Ÿ|’ЬYX[¶:õTÌ-[0fÍ"³n7œž¦i^YŸ9ñDÞ±c‡WV£Ì²Ö–-ècÇâ8cgÍâ^~™“ž{ÎÛO}ìX2™ ³gφ††J‡A ížTǸyþüÁ¯L!„8ŠØ-ÀÂ=ìß¿ÃXè>æ»~¢šŒéììì¬t!cåʕ̹ê*Ö_×Éš5ïCÍ›kY©TЦ¦¦JQŒrkÖ¬¡¡¡¹ñ,ÒÜÜLss3ÿ3÷ÞýøÝ|ç;7x•rÒ#aåÊ•¬]»¶ÒÅõ¾4n‚Ü8eÕ:~ó›w{q™Íf¤µ6ê±zõêJ%p.YñmÌm_䑇Ð ê<›J¥ˆÇãÄb1’É$©TÊ«ˆW±®æ4³m»P©>ÄçgÇqd¢Ñ*#×¶å577sÿŸ¦ðÛ–ŸÓü³›*]q”’kÛòä}z¶m{†j}}½ÆP¯ínÕ˜@5,P 6ú{ 3kÕ0IJ,B¡¦ib=öO?ý´\Û–¡âÓ|~üûÿã_œÍoœ ¸ó^q=ÿOˆá0×¶£¢‡ À„ÿ»S†¢òfo_Hë†S©=0Ï{Ì4MoŽ!D…í|gïÙlßÞ€®&T-Ï…#ïÐÉLjÿ-F~8ŽãUxd2’É$Ùl–d2I8F×uoβž© ˆáH|H2EŒ&3:sLÙõ§JC1ÌÇÁ², Ãðz>f2ounS=(ý==›ò==“¾žž€×sQý®®·ÉårE½5ý !T¾¦i˜¦éõÒL§ÓnÏÒÍ›ill,ÚžJ.¨ëÃ0¼ëƒD"Q¶Œþí¨DŠišhšæ•Iý‹ÅH§Ód³Yo_J÷Ë¿L</êYê/£zu]/*£Ú?ÿvûº½¡XÆß ´t™t:í}ª!Ë 7Ü zó8 @Mͳ8œ‚‰É7?÷M®à ,,B„H"õ¸¢:ŒŠ„Š5m&¶¼]”PÉd2„B!i/Dí=æ4v??–ãß=¾èq©\" ÆÃÆnଳ^Ü„ŠeYrþ¢B¦tæ8wî~è!¡bY–WÉá8Ñh”P(„¦iÞü5CÕ¢TQ°mÛ6¹Ž¢J©j¨F5¢‰J:¨† *á *ÊÕð·ápØKjø¡PÈ;'“I4Mó3¨ÿÕ°—Ñh´Ë5v[[›7o.Z¦\Cˆh4Zôé2êÿrÔ2¥¯íiu-QúÚ–– ça¼K—)]×@ÊØŸí ÷2ª·úÿ;ßùÍÍ͈žÍˆœÁ–ä'häêw×s×ÛwñQ> @„2D‰’"…ƒC”¨ô\4**tæm'=‡eÜw!*ìù3ŸgÜoOà£u{¨ø[è!*ËØÿùŸopÉ%­…Çe[!*jÖ¬YÜpà eŸ³,Ë«2 Ãm¹ŠFq¯……Ó¯©àƒKGÇv¿±Äyqþ‹4 ­lËÙ¿`Αª½?yªZ¿«VæêuþáiT«ûÒÖ÷ÙlÖky¯’µjžÿüCªÂ¹»ù€ Ðš[µŠ÷ϯäÿ¿§ù‡ÔkâñxQKz5G’jE¯¶n%h¹çétšD"ámÏ_ÆÒ9™r¹\·­ýýeì©%½™îZÅ—.ǽŠúžZÒ«†/¢ïÔ¹Ü {•ôPsg©÷X%EJ+ÌKc^UúûùÁr¤nJpá·w„“þé$B¼’°CßùŠ'E ƒ)Ò¤»¬K=/D¥ŒŽ„ʱs˜>¦ð§mÛÄb1/k.„¨ŒCÑ9¦0MÓ“—?ÉEúE88˜˜„‘䊕b¿ø"u¿y•;6ßû^a¸/5I´¢rtÝM"dÈ`cãàðð‡yçÂwòÖõoaÍt+ÔR¤Ê.¯¡¦5ŸƒS”ð)ýÀÆî¶¼:z—eÄà”{ÏÕcOöì­t ƒéÅ_äòË//z,ŸÃÀ0 ›Û—ÿÓu÷G½fÅŠvR)‡ °cÇf̘Á¾}÷qÊ)’ÍZ,[6Ž7ßœÈë¯O£½½€éÓ§säÈ]ìÚu[¶ü™ï~÷®»n?ï|ç;9xp‹-[®áî»g°j•Æm·ÕpàÀRžxbº>“ÿýßزå²YÏ}îN²Ù¹FË‚;vðõ¯¿É·¿=“3fp ÛùÝï:xæ™S˜7ïGd³'çp˜5ë6þýßO ™l"“)|6O<±›U«fðë_.‹ãÌ Ï‘H¸ËüèG' i9B!ÈdÜÏ5-ünQ²Y‡sù¿sd³Lºë0ŒÂ± –p…rd2…e #—m#Ôe;àWñ¸»?Ó¦}µÒaPUR©Žãt{m+½9…9ÖxxsÛ>Ž\öqîÅÛEÉFûþM’ÄÀ Ž:$¼ëáž®¡p-££c` åÿ„xCgT$Tž{s.ãÆoŽÇÁ¡u|+MMMdÉJ…­¤½þ:Çìfüiã‰ãsÿÈûkÞÏŽ#&ñ)D…½2f1'þ/º ÝD|óoIa£¥Ý±1:.ï`ëÖ­ÌŸ?Ÿíó¶swM ,þèbfßâ &¼îá!&ü5ÜÉC<ÁÝð~ÈÝ^‚úo'Õ)¶ôµz7¯ïé±n^“êëëõî×1œÛ鲜чåÊmÇèáõå–뮬CøÞ÷ôú×ìnìÃÊŽ^÷î½—‡v>ÄÝ¿¹»ÒEB(°çAOx•O.ø$€7ïŸ_8ÿO‰í늄òÿzR®`¹z©žêˆýÏuwÿ«†¯Hrÿ}u¹^ÞCMÕ«YXGÅ=ý`T}BeÊ¡)hc;ÙšúêÙŵo^Ë¿6þ+öx·›W† Y²Þá?€Ë}©$QM}¡2¡CÅÉÿ;*|«!x»à1Þ’f|ÝyaÃ>Lˆ°æÄÅ'r'w¢£“$‰‰I‚!BE]2 Ë;ÉùŸ+˜¬»Dh¤~Y¦/묆ãy°Fbûz!¡£óÆ‚7*ý––½Ntö³äý“±°H‘"·8ÇŠ±+–„2íõi^2EÍ# C’ ¿ùK»Bw16þ;l4¯²æÕW_åç_û9éÒØ;mBï AM~¡y•.µMVfWÂ¥•.E0YXDˆPóL ÓfLãéOwiî¤á1EõÛ>;'mNlÅE|ÅíãnDZÝÞ€rA+Dp¤R)I¦`–eÉp|Bˆã8hš&q)De`êǘ9n&¡PHó‰ªVõ •ó~ÿ{ZþþræîŸ ”ŸÔHQÛÞ‚)oáXŽ›ÒsLˆ`h;ògNHÄ00pG†("@LÓ¤©©©ÒÅBt£¾¾Ã0¤!‚bÛ6Žü!Ã…8Y5pè´g8÷œq‡T*%÷Ÿ¢ªU}B`ï¡i\»øZR©¶]“æq4Ø»{/Ǹ‡l6‹e ýDïBˆ{ñ™ üÉ×·EŸ´æ"8²Ù¬\Ó PŽã6’dŠÁbÛ¶´x" œ•°÷‡g0gÇ¥8Ž#±*ª^Õ'T^˜_Ñ“_rGî×u©"HÚrÊë'‡å„)DÀ,lz™SµvÀm /„Žh4*×´BT,«t„ed³Y*Sˆ€ú£é0¶¥žå˧’Íf¥wЍzUŸPy¾ýLÚ}Û¶1MS‚RˆYüÊùê{æ‰D*]!D‰—'Mã½'¾ƒl6K(’ó§±gωD¥‹!„èF<—Þ)BPSS“$T„¨'gþŒãVügœQ‹¦irï)ª^à*­­­477ÓÚÚÚ§×kN;öAé2&Äèo|Λw±cÛex!F@ãóÀ‹§óÁ†±X–%´B £þÆæ´iÓÈår•.¶G…þÆç#…#c ±ùøØÝøî§wx>I~Šj¨„ʺuë¸ì²Ë¸í¶Û¸ì²ËX·n]¯Ë8ð õõ»I$24‚Ãh ñyî¹çò«_ýªÒEbÔH|žp`†aHBEˆa2ØBŒŒÄçÂ… ‰Çã•.º£žœ?…¦Äæ”CSxÝžÀq;°m[zyŠQá˜JÀoÍš5Üzë­444°qãF.»ì2¨­­ív™Ù³gsÍ5×ðøãWºøBŒj‰Ïýû÷Få„)Ä0H|~ò“›°¬7$>…F‰M!ÄÈH|Κ5KZÕ 1äü)D0 $6=x,G~w:çœacš&™LVz7„´ÀôPinnfúôé444°dÉ–,YBsss¯Ë®ZµŠh4Zé](kåÊ••.Bš››Y³fM¥‹Ñ£ ¿‡GƒÆç#<èÉ®ƒ~l­Y³¦Oß•R ßGƒÆ§®ëèºÈÞÕplÉ÷‡èÍ`®mGƒÑt =Þûj4}&ƒu´Ç§ÓÁ3Z>“¡p4Çg5\÷Õh9¦GÓg2XÍ?ÙĘÇÏâÝïÈ{Ï ŸKªá z¼?öØc<óÌ3CºÎÀôPÙ¸qc—ŒæôéÓ{“ïÉ'ŸäàÁƒýð¶nÝزìÝ»—}ûö±qãÆJ¥[A~7nÜȘ7ožwRŸ¿ÿýïÙ²e {öìá¹çž«ô.”äc `çÎ<úè£ÜvÛm•.JYAþþØ»w/[·nåСC•.ʰH|>óÌ3üþ÷¿çÔSOåþûï¯ô.täcK‘ïÁ•mÇŽ,Z´¨ÒEV½¶µ,‹eË–±dÉ’Jï ù쯠Ç{_õå3‘kÛîãsëÖ­ÜyçÜÿýÌŸ?¿Ò»0(GÓ1]-zûLÔµí*]Ôa7ÐkÛeË–1{ölæÌ™Sé]°j¸î«Ñò=Ó—ÏD®m{¾¶}å©—óÊÕüä'»9ýôÓùÉO~Ré])ôsI5|/9Þ·nÝÊÎ;9çœs†t½I¨´··wy¬/Ý9ƒ|@ 1Z $>¿öµ¯ñµ¯}­ÒEbÔH|>ú裕.¶£Þ@¯mŸzê©J]ˆQo ñùéOšOúÓ•.º£ž\Û L½¶Ý¼¹¥ÒEbÈfȯéÓ§wy¬·,§bdH| \ŸB“ĦÁ%ñ)DpI| L›B&¡²dÉ’.ØÞÞ.“Ž ŸB—ħÁ$±)DpI| \ŸB“ĦI¨444ÐÞÞîM´qãFZ[[¹ä’K*]4!ŽzŸB—ħÁ$±)DpI| \ŸB“Ħ™C`õêÕ\wÝu,]º” 6°zõjjjj*],!ŸB™Ä§Á$±)DpI| \ŸB“Ħ®1•.„_kk+­­­ÔÖÖJ·1!FâSˆà’ø"˜$6….‰O!‚KâSˆ`’Ø"€ !„B!„B!„Bˆ  Ì*B!„B!„B!„A% !„B!„B!„Bˆ^HBE!„B!„B!„¢ã¾ño|£Ò…¨V­­­lܸћŒ©»ç¦OŸÞïç‡ÒÆ™4i'N Tù:::°,‹ŽŽŽ?þø~•a$ß?Q}Ÿ•ŽÍ¾”¡Òñ„ò‰êÕS|éØH|V:6ƒöŠÑc¸â¶RÇãpÄ÷HïËp§å;¢º ç=iâs°ñ7’û2œ÷¸ŸÕe8ïI+q, ǽk΃-«ÄgWAxO:::xíµ×{îú½ñÆÙ´iSàëmG¼n­S È-·ÜÒY__ßyÕUWu^xá…ŸøÄ':ÛÛÛ½çïºë.ïùúúúλhùÞžJ/¿ürg}}}çÃ?¨òmذ¡è=¼á†ú\†‘|ÿDõL|V:6ûR†JÇgÊ'ªWOñ¤ck ñYéØ Ú{(FáŠÛJÃß#½/Ãuž–ïˆê2œ÷¤AŠÏÁÆßHîËpÞãJ|V—á¼'­Ä±0÷®A:wVãgtAyOn¹å–Î[n¹¥ßå‰òýÞø†nè¼ð _o[‰º5I¨ ÀË/¿Ü¹hѢΠ6x]xá…™LÆûÛÿAnذ¡sÑ¢E/¿ürŸŸJêÀðXA(Ÿÿ=kooï¼ð ;xà>•a$ß?Q]Ÿ•ŽÍ¾”¡Òñ„ò‰êÔ[|éØH|V:6ƒöŠÑa8ã¶RÇãpÄ÷HïËp§å;¢z ÷=iâs°ñ7’û2œ÷¸ŸÕc¸ïI+q, ǽkÎÕø™]¥ß“»îº«óK_úRç¢E‹Ê&T*ý™ýÞX% U‚§\yƒß•¨[“9T µµ•††–,Yâ=vñÅÓÞÞ@ss3Ó§O§¡¡€%K–°dÉš››ûôüPZ³f K–,aéÒ¥ÞcA(_ss3ííí¬Zµ €ššLÓäâ‹/îµ #ùþ‰ê3˜ø¬tlöV¾¾«ËpÞ“VâXŽ{× ;«ñ3 º ¼'K—.eÅŠEqØ×òDùƒ~oÜÚÚÊŠ+¨©©ð†#“º5—$T ¡¡µk×zwtt°~ýzïàÚ¸qc—qï¦OŸNkkkŸž*7ndýúõD£Ñ.Wº|­­­,]º”uëÖ±råJ®»îº¢ƒ¶§2ŒÔû'ªÓ`â³Ò±Ù[ùúòüPè)>ƒP>Q½zŠÏ [ÏJÇf_Þ#‰O1÷•8‡+¾Gz_†ë<-ßÕe8ïIƒŸƒ¿‘Ü—á¼Ç•ø¬.ÃyO:ÒÇÂpÝ»éÜ9زJ|v„÷dÉ’%444”#ŸiÐï/¾øbV¯^MGGÍÍÍ^âB% ‚ß•¬[“„Ê ­_¿žË.»Œ††V¬X²u~þ©·ç‡BGG×]w·Þz«—MìëöG¢|­­­^ÖrÕªUÔÖÖ²råJïÀí© #Q>1:ô7>+›})C¥ã3å£Ci|áØL|V:6ûR‰O1XC·#}<g|ô¾ ×yZ¾#ª×Pß“)>#¹/Ãy+ñY½†úžt$…á¼w Ò¹s°e•øì*èïIÐ>Ó Þ+­­­ÜvÛm¬_¿ÞK¦ôV† ß»E%¡2@¬\¹’5kÖpÓM7qÓM7yÏ•Ë~ú3\½=?2™ K–,ñºŠµ··³qãF6n܈ò{ Þzë­444°zõjV¬XÁºuëz-ÃH•OT¯Æg¥c³/e¨t|¥|¢zuŸA8¶Ÿ•ŽÍ ¼‡btޏéãq8ã»±5çiùލ>ÃuO¤ølüô¾ ×=®Ägõ®{Ò‘<†óÞ5HçÎÁ–UⳫ ¿'AùLƒ|o¬,Y²„µk×rÏ=÷°~ýúÀÔÛVºnM*tÕUWQ[[‹išE:p¶Ò¡½½ÝËtõöüPéèèà¶Ûnã¶Ûn£µµ•x€x åkhhè’AôÿÝSFêýÕk ñYéØì­|}y~(ôŸA(Ÿ¨nÝÅgPŽ­Æg¥c3Hï¡}†#n+q<W|ô¾ ×yZ¾#ªÏpÝ“)>#¹/Ãy+ñY}†ëžt¤…áºw Ò¹s°e•øì*èïIP>Ó ß¯[·ŽÛn»Íû»¦¦¦h»AˆïŠÖ­õiêzQä®»îê¼ð ;~øá¢Ÿ—_~Ù{M}}}çÃ?ÜÙÙÙÙ¹aÆÎúúúÎööö>??Ô®ºê*o{A(_{{{g}}}ç† ¼¿/¼ðÂλOeé÷OTÁÆg¥c³/e¨t|Vº|¢zõŸA;¶úŸ•ŽÍ ¾‡¢ú gÜVòxêøÉ}Îó´|GTá¾' R|6þFj_†ûWâ³z ÷=i¥Ž…¡¾w Ò¹³Z?“ Ê{rÕUWuÞrË-ý.ßp—?è÷ƪ|jA¯·éº5I¨ À-·ÜÒ¹hÑ¢.?þ½ë®»:ëëë;¯ºêªÎúúú¢®/ϵÒ+å»ë®»:-ZÔyÕUWu^xá…7ÜpCŸË0ÒƒÏJÇf_ÊPéø BùDuê->ƒvlõ7>+›A|Eõθ­äñ8Ôñ=Òû2\çiùލÃ}O¤ølüä¾ ç=®Ägõî{ÒJ C}ï¤sgµ~&A”÷¤»„J¥?Ój¸7V±¢¶äzÛ‘®[ÓÙÙÙ9¤ým„§µµ•ÖÖVjkkËvêíù£¡|jÓ§OgÉ’%ý*C¥ß?QÝ‚~l=>ƒP>1:UñUéïÁœ;ƒòŠÑe0Ç\ÐŽÇÁ”u¤÷e¸ÎÓAûLÄàŒ–ca°ñ7’û2œ÷¸AúLÄà–c¡š¾g$>GVÐß“ ¦A(߯½¡°‚ß#ùJBE!„B!„B!„¢2)½B!„B!„B!D/$¡"„B!„B!„BÑ I¨!„B!„B!„BôB*B!„B!„B!„½„ŠB!„B!„B!D/$¡"„B!„B!„BÑ I¨!„B!„B!„BôB*B!„B!„B!„½„ŠB!„B!„B!D/$¡"„B!„B!„BÑ I¨!„B!„B!„BôB*B!„B!„B!„½„ŠB!„B!„B!D/$¡"„B!„B!„BÑ I¨!„B!„B!„BôB*B!„B!„B!„½„ŠB!„B!„B!D/$¡"„B!„B!„BÑ I¨!„B!„B!„BôB*B!„B!„B!„½„ŠB!„B!„B!D/$¡"„B!„B!„BÑ I¨!„B!„B!„BôB*B!„B!„B!„½„ŠB!„B!„B!D/$¡"„B!„B!„BÑ I¨!„B!„B!„BôB*B!„B!„B!„½„ŠB!„B!„B!D/$¡"„B!„B!„BÑ I¨!„B!„B!„BôB*B!„B!„B!„½„ŠB!„B!„B!D/$¡"„B!„B!„BÑ I¨!„B!„B!„Bôâ¨H¨d2LÓ¬t1Džã8˜¦‰eYƒ^—mÛd2™Jï’ ‰ÍÑÁ¶í²1-ñYÝ$>G·¾Æ§eY8ŽSéâŠ~ØÊ[ûs^•Ø ‰Í`Ê{Rø¬vŸÁ2Ðø”ûÒÑCbrô-ñxT$T²ÙlÕbcc£w2ðÿ^­,Ë¢®®ŽT*E$!‹ j}¶m“Íf+½[b€FKl–ûûh‘H$¨¯¯/ÓŸÕm´ÄçÑ›½éK|Ú¶-ï_’Ø­~Ý[ûz^•Ø ¦Ñ›åþ®6C}O ŸÕn´Äçh8¶Ÿr_:ºHLŽ^£%©tDÏLÓôZ¯ø¯V‘H„xå¾´úÉõì躞=*êq;G™Í›7wÉd²³³³³3wñx¼³­­­SӴΦ¦¦Î¶¶¶Îh4Ú tær¹ÎÎÎNïyµl.—ëÔ4Í[g<ïììììL&“]¶ …¼2ôçµ½ñ—Ïÿ{oïÚOµM]×»}¼§eúZƾìo:î …BÞÿáp¸h€Îh4ÚÙÖÖÖÙÒÒÒ©iZg.—ëÌårEÏ©ÏE=§ÖF; Ãèlkkó>¿î–#¯§Øìì쬺ø,ǾÄç@bp$b³/±Ò]|F£ÑÎp8Ü™N§;ÃápÑû×]|JlÏ`â³§Øììì_Ì G|öÜÙÓsAŽÏT*Õãr=?[ZZ:u]ïlkkë …B›&×½Á½îí-v»;¯vvvv{ní)n;;%vƒD®{Gþ¼Ú×ýíížT­g(Ï«ŸA"×½Á½îh|Ê}iu“ëÙÑw={4Ô㎺„J<ïŒF£EéºÞÇ;“ÉdQ´µµÜétºÓ0Œ¢e£Ñ¨ÌŠú€ý—b__Û›b2™ì ‡Ã]Þ—îïi™¾–±/û«ÞGuRTû/>üêBSP¹ÏY­?vjšV´|Oˉ‘×SlvvvV]|äÆr 18±Ù—Xé.>ÕI[ýï_¦»ø”Ø žÁÄgO±ÙÙÙ¿˜Žøì¹³§ç‚Ÿ©TªÇ庋϶¶¶N]×;[ZZ¼uñV¸äº7¸×½½ÅnwçUõºrçÖž®{%vƒE®{Gþ¼Ú×ýíížT­g¨Î«êó•ø ¹î îuï@ãSîK«›\ÏŽ¾ëÙ£¡wÔ ùeY–×ÍOÑup»Ðû»×–¾Î¶m,Ëb̘1ÞO`»õÀqoŸ•d2Ùíã=-3Ôt]§©©‰P(D2™$½Ç¥Ÿ‰RÚ-ZÓ4lÛ(êzWÚ½­§åÄÈê)6áèˆÏÄàHÅf_b¥ô3ùÕ¯~E6›¥¥¥…d2ÉæÍ›±,‹T*彦»ø”Ø –ÁÄçhˆMµ£)>û²\¹øL¥R†ã8Þ° –eÉdŠ%×½Á¾îí-ËÅm&“éñÜÚÝyUb7Xäº7ØçÕÞîIaèΫ ñ4rÝ;úâSîK«›\ÏŽ¾ëÙÞ– õ¸£.¡ÒÛx¤=}𦠅èt{îx?Ãq@Ž4Ó49pà@ÙÇ»Wr¨'O …B]­»À+Uú¹ùËeétšx<Þe¬Åž–#«/cñÙ[ ö7nj ±òꫯ¢ëzQ‡B¡>ŧÄf° &>GklBuÇg_–ë.>Ç!•J‘J¥°m›l6[4>¸¹î-/×½0°Øµm»ÇskO×½»Á!×½åá¼:\÷¤ ñY-亷¼jŽO¹/­nr=[^5_Ïö¶Üh¨Çu ]×Éd2ÞnY–—ù ‡ÃEWé¤Báp¸¨¥ˆã8ÔÕÕUÝ…N(*zLÓ$‰ðá¸ìãê ¨»ç†Ša^öX½¿Ùl¶KFµÛ¶½ÏK- …€Â 6£ëzQ+„ž–#«§Ø„£#>{гÄíPH¬,Z´Û¶‹*a³ÙlQÙº‹O‰Í`L|Ž†Ø„ÑŸ}Y®\|&“Ir¹œ÷cÉdrTÜ”ŒFrÝÜë^XìªëåîέÝW%vƒE®{ƒ{^®{Rø¬rÝ;úâSîK«›\ÏŽ¾ëÙÞ– õ¸ÇTºC-bYuuuÞ—q8Ü/çp8L}}=º®wÉréºN<§±±Ñ[6 yËW‚®ë$ ÒétÑï=epU™Õ{`YÉd²ÛÇ{Zf(išF2™¤¾¾žP(使Ñh´OïC,C×u¯å^<ïòeªÖ¯>³î–#¯§Ø„ê‹ÏÒxìK|$G"6Õþô7V.¸àvîÜYô™†Ñír*>çÏŸ/±0ƒ‰Ï Å¦*ÓP;{z.ÈñÙßåüçϾ´ÜÁ ×½Á½îUûÓߨUåέ=]÷JÜ‹\÷÷¼:÷¤åH|—\÷޾ø”ûÒê&׳£ïz¶§åFK=î˜ü$2£ŽeYÞX{*óå8Ž×uÈqB¡cÆŒ¡­­­Ë¸˜¶m£iZÅ/~TYÔ˜«ê÷¾dÕ{ ëzQF¿»Ç{{n¨÷©¯ï¯iš¤R)r¹¦iûrbx•‹M¨¾øôǦÓ±¯ñ9ÎØl¬ŒTL‹á7˜ø JlúË2”çΞž b|Jœ]äº7x×½#}nÁ$×½Á;¯ô½•óêè#×½£'>ºœÄu°Èõì蹞=îaGmB¥Û¶©¯¯§©© Ã0H¥RX–E.—«HYzš() •íÒ4ÐåF²ŒCÍP#±œ¨ ‰Ï‘)c9#+›Õ'(ñY ±9ÔÛ“s ¨ Ä­*KÐcw¨·%1(z"ñ92eJÓG Äç`Žû£->Jâ:ø‚ª,GÛùr¤ïE«)&GÝ_=Ñut:íͦë:MMM)‹ï®§²år#YÆ¡6ÐŒd3™¢+‰Ï‘)cwëÉX‘ج>A‰ÏjˆÍ¡ÞžœÅ@%n¡:bw¨·%1(z"ñ92eê÷Ibúè”øÌq´Åç`Ê.qlA‰G8:Ï—#}/ZM1yTõPB!„B!„B!„ˆ±•.€B!„B!„B!DÐIBE!„B!„B!„¢’PB!„B!„B!„è…$T„B!„B!„B!z! !„B!„B!„Bˆ^HBE!„B!„B!„¢’PB!„B!„B!„èÅ1•.À`}à`þüù•.F·vîÜÉœ9s*]Œn8p€0cÆŒJ¥[AwîÜÉ5×\ÃG?úÑJ%Pþíßþ\.øÏ.ÈåÛ½{7“&MbÒ¤I•.JYÕðý±uëV~ûÛßVº‰D˜2eJ¥‹Ñ­j8¶äûcpöîÝË‚ ¸å–[*]”À úµm_ýì Ç{_õõ3‘kÛòþ÷ÿ—ÿüÏÿÇÂÑvLWƒ¾~&rm[^Яmûª®ûj´|Ïôõ3‘kÛîsÎ9¼ãï¨t1ºôsI5|/=Þ_zé%®¼òJV®\9dë¬ú„ÊüùóY»vm¥‹Ñ­•+Wº|ÍÍÍ477³zõêJ¥[A׬YÃìÙ³+]ŒÀ9çœs8räˆ[ƒ°fÍhhh¨tQʪ–ïÑÕ”)S}ìW˱ä÷°Z¾?DWA¿¶í« ƒýôx﫾~&rm[ÞìÙ³ùÀ>èsS_mÇt5èëg"×¶åýÚ¶¯ªá¸¯FË÷L_?¹¶í^ggg … ŸKªá{!èñ‰D8räÈ®S†üf_|q¥‹Ð£ÚÚÚÀ~i(AEõ ú±ÕÐÐ@mmm¥‹Ñ­jøþÕ©Ž-ùþ¢g£é z¼÷ÕhúLÄàÈ1<£å3ƒS ×À}5ZŽéÑô™TJÐiý\R Ç`Ðã}Þ¼ywÜqCºÎªï¡t+V¬¨tzT[[è/þ{(ªWЭ Ÿ4«áûCT§j8¶äûCˆž¦c0èñÞW£é3ƒ#ÇtðŒ–ÏD N5\÷Õh9¦GÓgR)A ‚.©†c0èñ> é¡"„B!„B!„BÑ I¨!„B!„B!„BôB*B!„B!„B!„½„ŠB!„B!„B!ËÉÿ”c`9dRz!„B!„B!„BtËŒ’ǾeÃ×t°¿þo¸è¯ÜäG8Ý{ïƒ÷\å.o÷g•î¾.¼–‚3Bp¬îãe!‚š»œ´9ÓÜíÛùŸ øHÒ}ÞæÙ°yœù¡²à­·†ô}„ŠBˆ!QîÄêÎÁ=ù€N¡UAÈ÷|ˆåÿážßzu š\£p‚uòÏ !„B!„BŒv–FI%ÌÅ XŸ,üýç­‰À‹?4Èü BŸ…‡mxo¾%ÐÚÛžá>–̃=ú± ™`އoü>w38ÁÞÎ4°ëàžv°§æ7ºöþj¯pÿ µÃµÂ¤_Á¶«Üí…·ƒõ3ؼ rI·n'´Z·@î.ø˜ÖN= ?ÿgøæùn]QзÃu°ã¡áT0LЖÀªBèJ¿Ú#ð£cá{·À;½Â‰sk†ô½—„ŠBåÌüÿ:îI,‹›°ðÓ}9¾ßüïV~Y›B²D-£*‘’¥8’¢ Iä_—ÃmÍÿÉ¿ÞÌÿîäÿQh¡§Ð2A-·ç¸ã*ýö !„B!„B³ÁyØÚu¸+YÈ~´-ç>pž‡Ïüþþc0ï¯Á¹Xýüá_Á^–¯39¿NAêZpæAv̵aÓ.ˆígd? ÿ^f®qëOŒ'á¥&˜ü6d¯çXÐ÷›·@¬ôSÁ9B¿“~ ¿8 ¾ÑÚ[ ÀÂû é¿@û |ì[|û‘q$£cßÿ\ÛßýÐï4ø›çöÐ9é̦Éh1÷ýÈ> ÖKì _8X÷òÛüÝÆrù™¼²ÿNßv:ϼ·¾ŒÅx]RvOì$œƒ¶ß}ì<æ@ø¥ 0·aH?:I¨!Ä(–?wéÅaQèý¦øP½A òÿ‡|ë QèºiMý(S´¯‹—ùÝß;E%OŒ|y2ùý çOλß]‰·]!„B!„G‰Îÿn·‚~œvcáÖç!{<$¸eþ 6œO>Ÿý èo@â_`×`áLˆƒÐ1`þØ9¸f*¼ è] ã'Â'C+zÌSA[ ©é µAèÿàÉI€ Ö<ÐÿñGàÎ7áôç`ùný‰>>ò› ¼²äxšvq#‡Æ‡aÙø§ñ­Ô>^KÇìæoû7Üý–}i5ókÐuøŸaÅÒ-ðG0'±à¶@Ã!ý¼%¡"„UL%Lðý¯#ªH˜Bï5ÌV˜î‡çê+¾'G†’J ©ÄâOÀ¨ ™•÷ßápJ)„B!„Bˆj¦FáPÜäI·ND _žô6pÆ‚9Â?‚d˜÷5 ÃÌ'áŽçÁþ0²7ÃÔ_Á1S!v hA “_‡?€%:dO„Ð$¨Ñá…}Üï³Ù¼‹Iûg³ùapöOÀ§öÁÀU»@› ¿ìx•¿™>¦y³pvXÔͬ#ô˜'Aò£ù>úü!~øÃÃhmbZЏg?s9°e'Ÿøê§hiiáˆs„)S. uA+ßúÁ·p‡h4Šã„ùç~ž… G<çÐmïäÍ7OÆr@Ó4R©Ï>{>ŽóYöí;ùWÌ'›Í2gÎ;¹ï¾ålÙ²…w]ö.yâ‰3f´qdž¡Pˆp8ÌÉg•×_‡û&|›ÐÒ±XŒeËþš|_üâ&,Çâ=_¼îÑùû¿’ùó³$“I~÷»ûi01aÓ@*B1ê©%*I¥x(.5L—(­2ˆB!„B!D©¨šï±îˆ…:™, €ì$жƒ3Žý¤®g†›É\ {.ƒÈõÀdp&»ëŸù3°nÈ[¾îøœ0.Ç—$|yâNŽß_ýLÆžän;¥Cøƒ OίÏq¸mÏ1¼˲`!ƒS ú¶}XSî'ü±0÷~r-u§„ÀžE$¡©© ®6À„T&@(â?ØÄäÉá8ç£i‘H„öö»9|øÛ$“I"‘¶m³wïcìÚõ0ñxMÓÈd2d2aÎ=w B$áС èè¸[n¹¿û;·ë?üÃ8tÝaÏžsH¥®Çqêê²Ìž½•O}ê?Ù¼ÙøÅ¶ÛøÿXN.—ò,‰O<‘cÊ”œþdB¡–eñ“Ÿ¼—“OžF2y)‰D‚ .¥¦æùËqÜ|sÀú§¢ñ×ðҘ͟‡ôX‘„ŠB 354•šdÜÖ YßktßkUïÂÐZ ÃY›`‘ä‰B!„Bˆþ°m›L&C4E×»ÞUš¦I(ê²L6›Å0 t]ǶmÇÁqojÛ¶Ñ4l6‹mÛ†A("•J‡±,ËÛF4í²mÓ4 ‡Ã躎eYÞöLÓôÊœÍfÑ4­K9{bYŽã`©T MÓˆÇãÞvo[åÖ›ÍfÑuÃ0pÇÛ7˲*ý‘Š!’8ÑI@+˜[ÀʇHdèoƒóœp ¤þÛí‘¢mqç+é¼´(¤ïçÄ.ƒíÀ<Ð7At,üx|$gÆ z+0Řý¹M0¦ Z{2p-Ô·ÃÝÛá¬áuuù·¡SÝ¿<ü*¾±0§•å¾,˜Ù¬w>úèë,Y2Ó4I$$“I #Äÿ¸Ÿúúóijj" qî¹ò§?ÍÁq,4Mã–[ngÞ¼K˜3çR¾÷½‰D‚ Nà˜c>ÎÚµ÷2{öÛ¤Óiî¼ó,[ör¹­>È'"Ò_þ¸ÿÏ|îwOB>ñxù…oam:„ý­{ˆ~ÍM~& „BníÕ7Þˆã@&3?ŸÔÓÔ8öØó¹ùæó‹öSÓÜ$ˆãhè:D"ÐÔ4…ï}oŠ·,€aPô7ÀSO}†HB!7±¤FvÏdÜߚ¿øL³°œ®Ãé§lòãG*B1êûYuùT“£ë¾çuº&Mz"É!„B!„Tå¼aîôTïÕ BUì;ŽƒeYÞkëëë½eü õÚp8ì=ÇÉf³$ ¯‡J”¤Óib±º®ç+e eQ‰–¡’N§Ë>îfN˦¦¦n×UÚs¥·Çýɠᤒ)þÏ `Ù²eú]1Ä,°æƒ¹ô =‘¿†ùÏ–‰0æMÈè`< Gþsk ÝÚOAûwø«·amhŸÃ»«}Cµ®Õ ì@†m»µý†Áæ`Ë–¿Â¶!“IpÍŠÀYn‘|‰Ã3Ï<“ÖÖ‡7~lÛæÅ¿ÅóÏïãóŸw{OÕ××sì±Ïð™Ïü†mÛÜØøÀ>É•W. “ ¡iîwJ]]–©Sw3}ú¢Ñ¶mÓÒÒɹçŽÇ¡ö«_¥¥¥…ÆFøÇü„wÌh€l=%{Û‹Dµ5d¶$¿–ë~ü,¹ûÞ$›ÕÐã:–åöžÑu7¹‘L‚e¹ ‘lÖM€D£nB%“)îi£i…ß½Çr_£Â]=ï8…(N¸8¾„NaY€Ï/}‘©ÏŸ CwIBE!º¡’"&…ÉÆ, Ãw9&wWÀ !„B!„8:8Žƒiš^E¨eYضí kîPX*aâ8ñxœP(D&“ñ†·Ò4­Û„„_wIž†¾ê)q1Z w"EQ=SüÉ|6ë€\ûwö‡ðlãAýÀ8œÁщðò0ãeXñW`O€ø>¸e,DgB(¼ ,…ñ“ó•úù°s‡šš]ÆBlÛfÎCaÍø0çß„¶ÿH§©ßþÂLÃ~ø<.9÷\æ]p'üýKÌž=-[NŲ,,ËbëÖ0cÆ»Éf¿@:&‘Hpß}_#²I&ÝÉÛ“É$W_} kÖ<ÉoEsnüêOydà ù¹\ŽDN>ù-Ö¯Ÿ‡iB(¤óå/™LòxïSøÞÏP_ÿZ~èþmu,$ºðê^û;’ä_¿&Ôדš½…pxâ X÷"áåyö›@ ìØAüÐmÄ~u=ØÛA×ÉdÜM¾ìÞK€y^/M+N‚„ÃJ¹;Ž›˜1 òC’'Pø_Ó •pQÿ?uîSL=mêS’PBˆ<wX.5é˜bøþ#‰!„B!„8š©¡¶2™ ápØÊJ ©ÐÒÒ‚ã8ÞS¥ “þÌÿ!„8ûE°æ¸sÙjû ò]˜ó§1þùœå`Ï€ø“`N†S'ATý@ œeÁ2U äëõàÏEضÍq{¾ÍWÿæN¯ù6‘Ý»ÑÞxcúÕüßÖ>úè/˜ qóSçòaÖÝÁɯŸýû÷³ó®o±wï|¾ð§¹í©çøò~ĬY³øË_¶sÚiîÌš¦1eÊæÏÙ,ü`ÁŽùùÏ·÷ƒžø!7ÑWWÇÔÅ×ÂÒ/z×.Ì{ã+‡ƒeËf3{öì¢2;nW’ä ¦zz´´F -ùÄ¡œ ¤7Cd¾ûØOÀ Ñþð¿Øü[aEÓ¦¡ïù öû®Gù÷X„w|cÓh;~Ö×±mwÛÚׯ%ûÌuD˯~Øõ›Ýdë’hã:°Çý5$ßI8 ö×n‡½{á³À®EÓt°m´±³ÐwoÎÆ0Ü]‹~h;ú¸×yrŽ©±#} Ãý€;䌔(DõJu€êTÝ ä|?ÉüOI¦!„B!ÄÑÆ4MÆŒC*•¢®®ŽH$‚ã8är9’É$¹\Žh4J.—£¥¥…––À­M&“ÝU%„è»T*åMŽÞ­•ûipjàΧ÷sýî·عo5?ÜIxÄ×Ar>ÔwÀ'C ×âŽßÜ~ûî¼ó•.ÛØ±c3gΤãw¿ã¡þÍë˜ñàƒDË}ÍÌrdútÌÙˈ[N=•3W¬à¢‹¶òÜI£ææ›ÙþÃòògñ‹L„Gv×ñýš~øõ¯3e÷5|hÑÿǹ{ÇFYvøB;‚ù«ƒœúío³éW1N~wœyf!1ò °{7Æ{& ýú.¨¯'üÖ÷ùå/¿‰>ùUœÝIP”’*P˜¿ /D ÃxÍ›·t]wãê«aùrؼÙMxØúì èÿþeŒ¿^†ùÉ€ãL‚ñõA:MLkÂÖ ·—  _uz[ $“د¹=IræÌyW¢`Ñ‹_ÜdO,÷)Ì7ÜaÒÈdhj±Ïþæ^Û&™„TÂ!ò‰ÃhW’UÉ$ÇìÙ3¤ÇbEz¨´¶¶ÒÚÚ @CCCÙçjkk©­­­DñÊrò? ­Ø-ÜÖê ó&ˆàP“†T×ÏÑ §Øô?´øTÞ÷À<ú¾÷ñ¹É“鮳´ã8Äb1Þr /ΟEù â…šjO!F³j¼¶âh çN!‚+¨ñ©z˜¨¡R¶ÍÛ·ãlßN:&•JÑÔÔÔeÈ'5o‰£AP¯mMÓÄ0Œ^c-‹[wk‰Ë€c`éŸaã)“Ø=c —ýa¾þ6ã;ÿBø„1N4˜Aa’sÿþ67Nô{õ‘ÿà±±§rò[i¿è"f|—Ž×ó_ÿš»ó~ÛKü.y5 Þâ†_ü‚ÿ\·Ž-[:Ø´i6LæÒK?Ï?þÏÿðëöÕl»ývþ¸÷o8ûõ{x[×yqǵ<ðn~æŸÝñ®æœEø¡š÷)Ð4ŽOÇy*z3d@×ÙðÙÏòÜçðÈÝÏáܵ–çŽÀ”}ŒùáÚ&læ;“n%õÓK`jæXèΟ¯3mkkò^BÓŒ¢<‹eYlÚ´‰ÖÖÑÚjqï½_Á²nC× ,Ë}ÊG£nBŶ s£8ÎbÐÜäL.§“Íf9ýÌmüíß^BMM™Ì=D£QâÄRîî&¿úYÓ‰þÛt2ÙÅ^Y4 âÿ2ƒXl¹›H /'vNÉó¿ÌÏó—¿ü…dþØÐ ¬©A.GÓm·±dÚ´!=G<¡²fÍÖ­[ÇÒ¥Kimm¥¦¦†þð‡ÔÔÔ°nÝ:Ö¬YÃÒ¥KÙ°a«W¯fÅŠ#]IJR¸½R¦>Ì»¾õ-â7ÞH7©bઢºzÚ¶M</»>5ž¦eYÄãñÇ_T]I»[×pÉd2½¶¢P“©õ4™™ê⇋ºÀú¿³Ù,–e‘J¥Ø¼ysÑsŽãH$Ð4p8ìMÂæï.«Ö©Ö£Æ' ‡Ã]ºÕ& ,Ë" ¡ë:š¦y]mÕØ§º®“Éd¼I¡¢ÑhQbF­àþûï/{XmzŠM Ðñi_Ú¾ííí\ô…/ÀÚµDp{cfqc´q÷n¾ò«_ñ»qãàæ›ynÿ~ÖR~"x5îm6›íq¼Yul«cDˆáRÍñ)ÄhW­×¶BŒvrî"¸‚Ÿ_ùñùÕŽÌýÒ—ØôöÛLyòI®˜;—‡®¼Ø,÷}b” òµíŽcíùØcé8ìsLóm¼o?ú·wsáÞ¹ŒËý7Ë_Î/ÿtÈ­*©²,Ë«§ýð[ßçÈžwsï½{øÝ¾À–±cùà›×ñ‹‰Sùæçsü 'pÞöí¼gßµ<øÊ—¸ëî»±m›¼ãN&O~Ï<3™¦¦&þû¿ÿ›©S¿Ç”)8xðƒ\sÍ]|îs éè¸ÃÇ™Ì-¹œ#o½È¢úzþëµ…X3¿Ä]/þOvt°ø#o’šÇJÜA,faÛ“g/dß¾_PWÿw†Á¬eùò娶ÍKSïgÎdé¤Syñű£QÒ5±å’ß`?¾MG×±òs=½üòïˆÅ~MCõ<ûìAêêR¼úêD"Ÿã¢‹b¬\ygœ±’SNùLÓ$w*jnMsذa;_ùÊRfÏîà'?¹•åË—ó¯ÿº—ÓOÿ:/¾ø}êê>íÕÁÞrË™Ì˜ÑæÕ=ëîÈ]ùySܺ¶X,A*5ƒûî»ï~w º®säÈ.–/?‹Ph<–e±­cѧ·ñÊ+¿¦³³ÇY–߆Û]§}Ö¬!?G4¡ÒÚÚÊm·ÝÆ=÷ÜÃ’%KwÌÈuëÖ±jÕ*Ö¬Yí·ÞJCC7nä²Ë.£¡¡¡¢­…"€ªNMÖ¿þ+‰o|ƒïÜx£×KEÏÿoÛ6™L†T*åí›J‚ø'$S•µº®{˜•&TTrAÓ4LÓÄqœ.•úŠ:ÐÀíNZ.ñbÛ¶÷S®âW•ò,/a¡i†a`™L]×½$‚J^¨I×üT¢B%ETÒ%‘H …¼õÛ¶M8ö’êýÊäû|e³Y4Móöݲ,‰ápÓ4‰D"Äãqt]§¾¾Þ›.z ’ºº:fΜéí³z¯ãñ8ÙlÖ{O"‘ˆ·¼úœ ÃðÊkš¦‘H$¼ñPGÓ$d½Å&Èøøò¬}ê)ÎûÑxø¦›ˆüבÆíMf³·nåë³gó¥}û8·®Ž›O9…÷lÛF&“ÁH§½ãS0Õ1¡Ž=«ŠŠs/Éd²Û䣊;ápxÈZ-©£_5ǧ£]5^Û q4s§ÁÔøüΛoòµövÞ~ÿûYtÜq|à?ÿ“{¯¸ý²ËˆUúbýÚvÃg?Ë3gÍy›Á7µI ž;ù7«l f¿ÚÁ®¹5ŒÛ² žüw7â×c:ðû©O­Ë–-´µÕðÇóÎãÇ+VðÙk¯¥õÈç9ïÅ[¸yõf~öæ›ùþ÷ùø•'rï‘«yø²¯p£mócÓáïXɳí[°¬—øîw¿ËŒïgïÞ—Ù³g»wïæ‚ .à·¿ÝÍ¡Cð+Vü=ÉäbÝžÑ(hÚÍhš›¤H¥²ëéû84î&X<ýôg8th9ßÿþ£Lº„ººÉÔÕélÛöCþ韞ଳ¦“ɸCvÆ—il,ÌÓt÷ݳÈd2üä'£#õUÞñŽÙµk>õõrüñÿÍi§ÝËÔ©C(tx–¥K¯$“‰°rå~ÿûÍXœrÊõüøÇ;°¬ÿ²L®ºj'¾I.×ÄîÝwðöÛßâé§O"}›çžûK–ÜΣ¶ÐØMM…¡Ý^, °,˜9s&†aðàƒÿÈöí·“Éü*_'k0qâ}̘1ƒX쯼dLsó\–,ùø%·Þú >üá©lÙrØ«cv“TÃw,ŽxB¥¡¡Á J€‹/¾˜öövš››™>}º×ÒÉ’%,Y²„æææ³{÷¹yXzXº‰YÀîo›¦|ktÇq°5 8ïÕWY·o]„®ë´´´x ‘ÆÆF4Mó*UÂá0š¦‘N§½Ê|MÓ¼¤Acc#€—,H§Ó$ LÓ${‰Õ‚Þq/‰’Éd¼ˆišÞWŽãx½C¢Ñ¨WÑ«*ýI 73èöЈDÜ‘K *ù¡>ª'!ª×Šê…“H$°m›\.çU§R)Òé´÷w(¢¾¾žp8LKKK·Æê}Èf³^¹K{¢Þ¸¥*é£Ê¬¶¥ø+§ËU «ŠuÃ0Šzã477“UÝïªXO±©ös ñ¹}ûv6nÜX´Þò·PVmÚÄÏÇŽå¯ï¹‡äw¿ à§©e³hùäÇÅ_þ2ž}6W¼÷½î‚sæ`š&±XÌ‹d2é%=ÔvÔ1æ¯T*E</:ŽMÓôžÓ4¦¦&2™ Ùl–p8ìC™LÆÛŽJ²ª¸÷o»4颒°¦izë‚ÂñÝ£yØ»ŽŽ6lØÀ*]”AŽøû,©X>urãE¯;úî¨D_µ¶¶²wï^¹¶í†º¶]ºt©× m ÇMcïÞ½dp‡ó¼aÜ5 s´Ž;‘ XpöŸ;™úÈFºè=Ì{*_>öQ¯ÕüÞ{÷ÒÖv¶·îL&Þ=ÛøË“ÿÌégœNí³Ï …xç„û¸âUüĸ—¹>È?=õ§}èlÎ[ob‡ç‘ɤø—ùO2‡iÓ~Æ?ÿ³Æ%—4pÇ6‹ïf„G½úJwØ+›w¾ó Î>»¸ÞGõô…Üž†apèлøÌg.'†ÆFÈåÚH$ ZÈ;Þ3fÀ)§|™ÿû?8ë¬ÂdòàŽæå8n/÷¾÷½Üyç7øÔ§®Äq~ÊcÝŦMËI§ã$Ë9ãŒåœz*^}g]|èCðÿþŸ».•äiiPèêêÜÆøúP”?üán¼ñ æÍ‹ä)»¯M&Ýú7Õß4)ª›J&Ýò†Ã…:VÛ^μyËùÑ õ‰„»O†QjñÅwqÅßçã¿3Ÿ|rחɼM6›õÊŸþ<¦OÿGÎ?ÿü!¿·Ñ„JCCCÑttt°~ýzV­ZÅÆ»œø¦OŸîÙ×}ûö ùM§;Ä—Ûûä—¯¾Ê¦}û°ÓiÚÚÚˆÅbn!➎œë®ãð7¿É¿%“„óí©žªrwóæÍ]*JUr&‘HF½ñ8C]&2ˆÅbÞÐW*£’ŠZW<'Nõ€1 ƒºº:½D„ê‰RJ%^zjL­GQIEU„çr¹.Ë–®[Ó4ï½ê‰Jê¨Þ;ÝU—Kžôôºî>#•)}ŸFËMgO± 8>·oßΆ }Ó©’êØ°€ìßÏá§žâ_Çã*_’K%3™ ¡Pˆ¤/.ýT"Ã?¤Wéç …ˆD"^o¥T*U6ѧzM555yIÑp8ÜåX®««ó†¤s3æ©TÊKdÆb1¯™¿W™êÙ¢bͶmïµêýQ±…ãYmGõÈR=ÊToµœÚLí¿Z:öU™UB´µŒίÒ=¸ÔßhH¨ G|ª›Ni‰+*¡µµ•7ê†*(ªåÚVˆ¾’kÛ‘¹¶¢¿Ôµí¾}û*]”A ʵm xõÀÒLص‹Ÿ:D(&ýPDÿµ¶¶²oß>æÌ©›Ü‡¶å–þv3—LZÈÕ6ÜzÒ”¢‘E¸g+°„l6K*•Âqn¿–ó'ý‚<Èž|’“¾ÿ}VüãT¨y7¦ö Çž{.š¦1nÜ=ľü5LÓ­Ù±ã ãByäU>úÑo“NÏÎÏyÛT=&ž}ö Ï>ûN®¸¢»}…\®‰lÖý=.Ìë¢ënr"-$OT;o]÷¦DÁ4 É'“ïåŠ+rÞºçËÄbäë¡Ü×úG»O&ÝÇÔúuÝÝ~,æþ®êºÇMfÌ›7U¤SÕt©”»îÒ6ð¶í>—ËêkýÉ$ÿcºº^xì–[f{e3 ·¬‰,Yò§0 ”m›üÕ_ý?ûÙÏ|Üu§"“Ò¬_¿ž5kÖÐÐÐÀŠ+X³fM—×ôåD8gÎV¯^=¤eËàf6ã¸ù“?ý‰íü ßËWþ«Ÿ{õUž½æ˜8‘Å‹^¼¸h=ª'Jo•ù›7o&‹yó”{½ªUëì.P:—‰J¼(þä@Oóž(™·Å¿ 5ŸÌpè)Ñ1ÔÛQ½Jß÷Õ«W—=v«Yil^k!¿¾Äç²eË=žf"‘(êdáÅWûÕ¯róe—•M>& ZZZz^«/Ƕa¤ó©Äc¹ØSÉMµLwó©455¡iZQ¹üåhjjB×u/±Ú]œ«aëbù ~•p)×K«¾¾žH$â% ý=}TrÅ0 ¯7š¸>Õ+Kí·Jl©$ PÔNý®zÛ¨Þ8ªçŽÈ@5÷’?ŽÕrjèAµ>ÿgéï-¦–)ÿµµµ¬^½š7øØ ¢¡ŠÏ3f ù¹Sˆ¾R7iÍÍÍ•.Ê òµ­}%×¶=Šk[!B®m‡öÚöªƒùé#0öÝïæš[náÆ/}é¨ìÕ/†FCCŽã0mˆ'½®´ ^ÛN›655l¡Ðà¥Ý»ùy{;Ó8fŽáÍ-Sóøý|{¢Áœsgç§i(^×y‡Ê‹“Î%‰‹FYrÞyÜrÍnþrd>^=mÏ>ËÂË/gÞO&ÑÖÖÆ§®¿]×¹¶±‘íÛÈí·»Éƒp8‰iº•úÉd˜×_Ÿ ¸‰ Ót+ü-Ëý_Óà˜cöPSó"ŽÓ{r)v“ *1n"E­ÛM–’(þ„J4êö4)•H¸eQÕVjRy·÷La»jýJ(TH¨(šæ&EüÕr¥Õ3šæ&|JßÃ($]ü•¾®\•º¿ êýÕu˜;wnQ£iU77oÞ¼AwåŒxB¥££ƒë®»ŽÖÖVnºé&ï¦zúôé]^ÛÚÚ:¢­T/‘¬®Ó‚›TY·n9p€†‰‹*LÕ0]ñxœxUï‰Í›7‰Døñ³Ïrý‚,ùæ71jjÊÇ*&‡ê˜…BÄb±²sõWoË«çû’ì ‡Ã}úŽ)?5ôžJJ¨÷°ÜPc¥Ôð…jž¢î’ª‹e"‘ð†üƒÂ0†à~¶jÈ5U†p8ì ã§’CÙlÖ룒›jøBp“>›7oÆ4M¯—ŒŸF‹ ƧÂäk[!Žfrî"¸*Ÿ1à±ÇcåOJæ}ïãK›7K2E Úž={*]„!´kÛX,æî1ᡇ`ÿ~ÌC`8ÀHϘ3f°èá7yiþ±;ýmNO}9ùúÝ)®„'‘ ù/ Ì>p€¯,»œP&ïwíbÊ)ËiÙ¤ÓrÝüéò…h©ï~÷•Ü{ïx/bóæÍÄãqþùŸGÓ q“šæ®?ý+òÓB£îQ=U@%G^ ù«J“ àn£´íl,VHÐäw‡\ÎݦêÑnb$?åv‰¨jf•ð3ÍÂóPXoé×¥{аÃÀ›ÛÅOÓº>6ÐtÝ-ÇHVxB媫®béÒ¥¬]»¶èñ%K–°nݺ¢ÇÚÛÛGt(’”¦qçܹ|7™bÛ6O<ñãnº‰ñãÇ{¯S-ÕUkr(ŒÝ7PápÇqúT‘:þÖïÃÉ?±÷po†·â´ÐUlø÷§’º‹M¨\|f2¯2~f}=×/XÀØË/'úÙÏö˜|j*9Üq3TOµ_JoÉõzÿ2ÝÅ]8ö†Kë®—žšk¦Ü6J×埇¦ôùH$‚eYÄb1o^*5`*•bÓ¦M•~ˇDãSá òµ­G39w \•ŠÏ°óÐ!ŽýÊWH·´tB]œk[·nVÝß755ñ¾ãgÇøñh€3¬¸C …@·aÞÜc ú5c‰F K-Ë­ÀwвYö>ƒ?w_»ê]ðØ]Lºâ Ì”Æ{?°‰|$ɲeãøÑNaÅŠo»õîpð…õB!¡nR -ô¬Ðu·§HK‹ûœišùáÜÝ¿37âèÄ_í¡z`ø©D‰ªRQ‰˜Ò„Œ;TVÏﳪ†.Mfø6J¹$H2Ùuþ¿C¡âäMoúÑ7Áºïc<>rI•M¨¬[·ŽŽŽ.¾øâ¢ajkkihhðÆmhh`ãÆ´¶¶rÉ%—ŒHÙR©„ÃÜúË_zó!¤R)bá0©‰ñà …º´úlBE×õaO¦@ñÐDÃIÓ´¢ay†‹j±>‰›ÑœLé)6+Ÿjn€‡>óf¯YÃ{N8¡_½¿†B2™‘ãy¤¨a³†ó»@Ó´nç[ˆîntTâ¦t.'p‡;[´hѰíãH j| !‚}m+ÄÑLÎBW¥â3dóþå_8}öhb(éÚ6ƒ;¤—®ë^½Ð¢¶6ž˜9“àlóT¨ùÛýt<5™<~€Ió'‘ÔaLÊ×sÂv³íüü±D£ûÒ6ö®{€¹s?Ãöûî㟿û]vìøãÆÝÜ@&³&?Üy 3f\¦Ý–-£PFõbÛ…Þ!šV¢K=»þnâÅ­ÛˆF)Z—ã¸Id²x˜«dÒ]Ÿ?©bÅ˪ꧤ'N8Ü5)RJõn)ý:TCù«ßüÛ,}ºãöÜ)?tW)5œY†»#Ym;¢ •ÖÖVZ[[Y¹reÑã«V­bõêÕ¬^½šë®»Ž¥K—²aÃV¯^="–~åW¿"{ì±¼k×.w²ùü¤ÖápØM@ôar.¦*Ã-NH¢Ã?TÑhÔ[l#Ÿ^‚Q×uÀ²qãøÃH´½DüóŠT;·5EÊ›<¾Ú…B!Ç)›jiiérLW£ Å§¢ ¨×¶BíäÜ)DpU">MÜdJv÷nBwÞ9lÃ’ Qí‚vmÛ¼c‡§NŦ¸!»<0æ5tûxÚ¾Àw¶LÂy8·d%±¼çlûœ|®sgxßò…>ô¡­lÛölk&rýõpçw‹A:ÏÏCëöñ×9¨öðj‚x?]w¶]HnD£ÐØè®'‘Ðó£o¸I•°ð'+¡³³ð¸;|áy5¼•?IáVLQÃ’©uAaî’ÞåÚü«„QõµÿÀ@’)jßýï÷HÑ„Š ¾î¬X±‚††Z[[½Ö ÃÍ~vòɼ÷œsÙ6÷ä'PîibérFoß…SL§‘ª‰^=•Ô[lÂÈŧšð¼¾¾ž¦¦&LÜ8m9á„âÅ€D²s¤èº>$óKYâSQ,ˆ×¶B9w d•ˆÏpÝ«¯þÈG†t¾M!”O<±ÒEAº¶}òÉ'iooç¹ÿú/lÜ+“É ¶ÿ›yÌ=öu~ö•ÉìŸ0³~ö(ÄÏñêf ŒºÝ`·¹Y+€ 88s&v8Œ®ëlÝzíí38æ˜sùú×ODz,öïß®«Êyh4ŠeA4:ÓK$ø'›W“ÆC!áanOÿ׌z+Q=?,o]jy5ˆZ¾}Q½<ü £Ð+F%,JçZ)÷˜®»‰µÝþ –4U/ùz.7<Ùpñ9Tz3Ò³ÿpÏ=Þ´‰Ÿ_=θq|Á4‰F£#>¤ÐhcÙlVÞÇQf$âÓ4Mâñ8¡PÝ0¨†nà(ŒúÄÑJ*ƒ„&‰M!‚KâSˆàªøTÇoÍ'S¤ŽB ‡yóæUº#f¤ÎííílÙ²…ÝË—c€ì$Xз1Å:ÄgŒåç5˜qìX¾}Ü9EËZ˜7#Ý>p •‘ä8'MâºSO “YG£QKst]Ç0Œ²“Q Ñ“L&C.—C×u$2¤ÞPí=®„B!„¾rð ×·µq+H2Eˆ*ò´i´{,Ö›À$˜Ñ güù-vÚÉi{Ocñ)ci™R² mó‘o`=|€ð©6„BX&XG`ñŠã¸òÊ3°,‹çŸßÆqÇ`Þ¼ƒèz]‡¿û;w†Q<„”J>¨Þ"þªN• ð “ͺ ¯ âEQÓ+jÈ«ÆÆâ$G¹Áyü£áÛv×ùSz¢æ* Úà%ƒéi2Ó’9j*WüáÜ]_ï?7Ožì=.É”¡F¥ÒVô[*•"œï~©Î)r !„B!„评eñÖ¶mìß¹S{ Q…ÆŸ{.‡gŒû÷îX¸g!Oœ~µ'Õ MOæ_œÏxؿʭÏÁÂÙ^VbïÞ½ìÚõ0wÜ‘bÇŽÙ„Ãab±ñúëëÙ¿ÿØö ¯7J.çVΗN>¯þVóu@a(¯rJ“,¥‰µ.ÿó݉F{Þ¶û6ñ{2Y²,ˆ •j©’[éTJ®³“çŸÏß>ð@ÑãérÎ !†å›uʲ,¢Ñ($…B!„B ÄC&ðÊ­·ÊpäBT¡={öp¸¶–š#G°40l˜4ö²—½§íÃÍ$Î'&"ì_=Ë_ÆDàc#•J‘H$xßûÞâÿgïÜãã¨Îûýà»ðEc°QìŒm.1W A$8—Q¹%!¥Y™6âVIÛ”´u³Û¦”6ínê&дMµš4Wk!M(¢I$($ñ8PÀM¬aŒÇ–mä+þýqö™]­¤Õeµ’|}ôÙÝ™3gÎÌî™9ó~Ïû¾ÕÕ“J¥p‡={ÚY´hW]ÕÑˈï8N‡Ÿ #L>T ôöˆ"Gt¹m‡ èË*-Ü–m÷/¨˜¦joa˜±b$“aû ct¹O$NZAeï¼y˜¾Ï K–Tº)ÍIMccc$!—‹i𤠝ëF£Ñh4F£,>ðÛyó¸jþ||ßבH4šqÆìÙ³¸tòdì8çð÷¿‡óêÎS%"Äb(u"“áõƒ/rNÕ¿å¼:Lb±ßþö¯¸óÎïqðàÓ†ëº<öعüú×û9ãŒ7âITÜï‘TªAÃ÷{‡ÛrÝ|AFˆÇ)Ûµh0!¿¤Ð[äÑ”ÆIòkÒi§yF b¨7æ¤Ä÷}\×Å÷}Ç Ü°³ÀæáU­Ñh4F£Ñh4š“” `8ŽöLÑhƾïÓÐÐÀÔÏ>o’­õ[xð8vü=˜1NHyåu‘ÊŰºð¬I,Zu:É$ø~˲xá…køÄ'ÞÇ>40ˆÇãd³SùèG×âû¡÷É)§À‰J@1 åÉ!aÀ ½PI¤ ßeH”‚+ŠäÊe+?á²&' âû>s÷ÝÌ{÷»1Ï;oDëv•S£)'w×QŲ,²¨~¤ÅIF£Ñh4F£Ñ …/wwó¶çŸ'öÙÏVº)f¸®‹çyTUUa±¯ÃÌXyýG™ûÆÉJÅñü$üg ƒï|k7¯>ù^>Êßý]˲xôѧ8ûì³ùÁ–Hă|ž QA"™T%B&£>‹ø"˜fè¥%î;Qz_“û“I•l~(¹M‰ÒËŠ$ÿ:ÅÔà9)B~Ec湮˶o§ö”SFt:4‘F3x\×%‘H*«ï÷‚p_F£Ñh4F£Ñ …×^{‹çÌÑ:ÇXþffBâº.±XŒ}5Ë¡ÌoCb*Éîx×»f¨‚¹Ä&Ù/í&þð(•À0˜5k;wîdáÂ.Òé4®ëòä“O2kÖ¬¼äò931¦zŸ‘™½–¥–‹¨"ÛÅã½Å ñhŒf}°,%Øôå 3¤RÁ©Ò9T†ÁI!¨ø™ÐqÌxœkÏ=wD÷¡gÓk4ƒGr¦x9ùý¿–.%†öôÒh4F£Ñh4ÍÐp€9Û¶x®-¨h4åÁE…éeõmã ð2°ì?D^§F6ŠÅÀóðöÎ#[õ¡`ñ–-[¸è¢‹X¸p!÷wÿmÛ\|ñÅ,Z´(WïýKæ‹)¯)ßܬ^3™Þ‚GKK¾w‹e ,ª#WâL9Cwe³J´±¬pšÁsR„üò|<Ï#ÓØØÈ­Ÿù ÷í•n”F£Ñh4F£ÑhÆ-€ëbâ•nŠF£)±çšxÇ1»¡éf0Ÿ"0ÆbJ DË‚m'p–”¨ÓÈÖ­[Ùµk;wncÍš›YºôXÖ x²xÃPÂI4w‰x³Hø- ÇU*CTjk¾k°DÅ †uœ}…&ÓôÍI!¨Hâkxþ¢‹¸xÎíQ2L$d I¾@á¢D Y»‘r^äÕ ?üܶ} F®Œ«3û죋|ñDö‘ˆìGÚÞTâ±& E;W—S¨­®fÿ”“¢+(¾ïçÅœùák¡S£Ñh4F£Ñh4úücAAE&xj4šò‘AM¼Mš&tyHÌnÎþOL™ ïWêFS–° ¨cÉ’Ýüíß.ç¹çÎâÕW/Ê-û,®«„˜b ßm[ynæ.‰ ,/M,JÉmâ8ùù[F’X,ÌûRÎÐb“ ìº.–eñµgŸ¥æ©§h^»¶ÒMª8"x‘ÿbƒéÿâÁa ½=? ”Ø` ®yµ(á")Û—7™´©T¡Ã–¡’Bf oµÁz³Ù¹còsÇJ¼‰åŽïÛ¿÷{X¯¾:èïàdGú%@SSÙ%KJþî5F£Ñh4F£)† œ÷Úk#Z§LþÔh4#›ûp×.æüçªIÙ»’ë…`öl8à)$òà‰'Ž’Íþ/±XŒ'ž8Ê¡C§ñÝïÞÌÚµwsóö%BGÔ+#/Ê+Šˆ(™Œ` •ëcưmÛAØûb˜fyóšø~x :ÊД ÒÚÚJgg'ks‚D[[6l`åÊ•¬_¿¾ÒÇS1Úf=O­Z5aÂ4EÃaAx1B#ÂJ<92„‰¿ T謑 ›ç4¬\Ý”PÿPB6玩œß©ÃѦ=sçrfWW[01q'ðP±ãq2èjF£Ñh4F£:>0¿»»Ï¤Ïfì!¼_~ùeÞvÎ9l^ÿ"8€m0có~Hv^#|(*¦ ‡'“É‹ÅX´h'N,峟ý?~:ïU"¢I6æ*Œˆáº}‹%Qú f Ä”[äðýðØËé 3Ñ)YP¹ýöÛÙ´i·Ür |øÃæüóÏgåÊ•<ôÐCtvvr×]wUú˜òÕos{;Ý+Wò±¥K+ݤÒÛžûqBĹÐHø«(>¡Ç†ÕG”QÆGåÂŒÆ1È~Š‹ tïÝ;J­˜XDC~eA‡ûÒh4F£Ñh4Ͱp7îÙÃR=õZ£wô̘ÁÒKÕ‡#à\žï âí¨"õÕ*°ÂlêÙ,˜f†aà8Ž“áOþäl¾üå 45Ýä{•Hn”Bo”œ>“‡i†BLÔ££œIãm[µ¯Ü†úׂÊÐ(IPikkãûßÿ>÷Ýw+W®ࡇ¢ººš»îº‹9sæ°víZlÛ¦³³“šššJW€ã8Ìüð‡9üŽw°òž{à¶Ûʶ¯¡üÞ}”À!yA’(AD¼.¢ùHâ ¿‰ Å¥}…¢2Ý»vUºyã×uijRg6l®tƒ4F£Ñh4F3®q€£[·Vºft¯XsX½Ÿ{¤÷zwî;q“ÐÒBž+Ç‹/žË²e×á8ø‡_Æ÷!S_{öäO•%î²Ë²”¨¢ï CytŒ£¡KN˜è¹Ñ”ΤR }ÿûß§®®.S@…ÿºúê«™3g555ÔÔÔÐÙÙYécÊÃqæ¾ó,¿ç®=x°¬û*jOÄ%–$FTîZ >·>+ï£v”—IŠ0—ž_1ö°€³´ 2,$$vÈÖh4';:) F£Ñh4Íð™ÚÙ9`XF36q§ƒõ$,¹"ºÐ…d–/Ï{fò}• åøñmÌžý6 ÃàþûÛ˜ñx¼¨'‰a(á¤Ð d K†ï«ü+åôN01}9‰Çuþ”áR’ ôò:immåüóÏÏ[&âÊXÂu].\ÈÔʺù:„ÂImîs-*§‰x¡ÄP‚ÉæÜŠÐ»ÅC–Ç1àB=ûeи®Ä´Í2rù{4¦ÒDæý $õõê5›Uÿ •n½F£Ñh4ÍøÆ޾ür¥›¡ÑhÁÞ½{‰:ØîçÂm9NðÐä8ù¹I\n¼q;W_ýk.»l ®ërÎ9ç¢GS$ÜLT1ÍâÞ&ý‰%’g¥Üé™l»¼a¸¤nÓT!δ°24JTª««imm >?ôÐCÔÕÕ˺»»ikk£ºººÒÇ 9\à‚³Î*ë “PLᤙÐÛ¤e|·)n<ŽÚ\F+/ˆFS)|ßÇÊÝ©tþF3Þ¡${7“Q¯é´œ{žšDá«ã„¢‰ç©q³.uŸF£Ñh4šþéþñƒçMF3öÙ[›Ørá¢îœxÑЗU>Îß¶££ƒÿ÷ÿ~È¿¸˜ææf.\¬ËdÔ3X,–/„XVoaIJú2Äs¤Üa¿ £¼"G&>»šæèäk™ˆ””Cåꫯ&“Épûí·SWWG&“¡®®.ðHéîîfÆ ÔÔÔä…ëîînöíÛ—çùÒÙÙÙ+dØùçŸ?dÏ×u1MøÂ>̈/J<é+yù@èúš±B±¾ #Û?ýÜ[®ÛZ×hJc4úçDÅóò¦"hDçZ¤ÓáLdR¹;Ž\{žx65©uMM¡pbYj[€;ŽªWD× Þ2`ºr‹û¸¼J;}?Ü—´GêO$Âvû~ï‚ÂãÕ”ŸÑÛj4šÁ£ïÍØ¥ýÓLß/«ýG£9ͱíÎ;aéRæìÞM÷üù˜oUÏPž‡zØ2MhnfsG7é/ÍÁuCo’ººé8ðvìè]¯a¨zJ¹H’öþp݉ñŒ%çNçO:% *555Ü{ï½Üzë­lÚ´‰ºº:Ö¯_¨Ð_ëÖ­£¦¦†»îº«ägrr˜Ô°aÆÀûEظqcž'Ì`1 C…Ñ*óÍÔ@‹"QÊîOSFŠõMÙþéº.–eép_Í þ9VˆŠC---ÁsXôPž¥ / Cõ4‰>ëW2™ð™QO°:% *}1gΜAužóÏ?Ÿµk×_Z[[{¹z˲ƕ 2„ˆñt¾5!ýõMÙþ)Ié]tÎ ¦F³–‹¨ÐQ"*Dë/Žhy ¤œ¼Êúè:ñXQAÆè–¥ÊEÉÙl§7:0/|/bKTØ‘vÉ ^ßW³¢Ä«E²¶Ýû˜Åk&êŠvd½x܈‹å{ÏȱD½k–- ë”eõõ½¿;®tŒÝÞŒöØV£Ñ”ÆD¸wj4•rõOXØÕ…©­„Í©ÄØöĤ¹Ì=<s{îË8fž«ýWÜÏ¢E=¬^½t:ÍM7ý=+U¬X×O$zçFj˜«D"?ôòx§ÜùZ&2% *Ü~ûí¬[·Ž[o½•¶¶¶!ípåÊ•ÔÕÕõJ^ßÝÝ Àí·ßÎ9çœÃêÕ«Ù´iÓ€õutt°nݺ¢ë<ÏcÛ’%ãÆÀœ~¼r2È×­[ǃ>XéfŒ}õMzÿ|ðÁÙ°aCÑu–e©p|•>pÍ„¤­­uëÖ±k×®J7eDéþ¹k×.Ö­[WR?)DT(–ÈODÈŸ=Ô_ÂvYî8¡ÈR¸NBh£^"Åê‚ü'òYB†ù¾ª;=Z¢á¹$Ìo"ÑÛƶóE›TJÕ ñ‹…Œ¼Jn—TJåT‘Ü-"èDÛ*â’œ×hþÏSíŽ QržE`ò âvFÏECCîá&Ó[h*•M›6±aÃvïÞ=¼Õa4ǶM¹ÑcÛþéol«Ñ”ÛvttTº)#B¹Æ¶<òPþïM”M›6ÑÑѡǶ} cÛþìÈÇŽã]_ocÊiSh·ZVÌ£þñÇßišôô,"•JñÇüWttLÂIsòŒ¥Xx¯¦¦¡Ÿ‰tyéK„šHlذ¡,cÛ’•uëÖÑÚÚÊÊ•+éììäÃþp¯DDá³³“ºº:n¹å¶nÝÊ]wÝņ hmmíw»%K–°qãÆ¢ë|ßçÉ+ÆMH!—‰þh"ˆC±qãF®½öÚJ7£ì µ^{íµ½âá‚;µwJ‰ w6¸ÄhZ¹‡ê´>ν:@È*¾òYB$e€ÆÜg)ŸÌÕáä¶(©RÈæÊIÙl\¹’7²`Á‚ažÀ±ÏPúç‚ ظq#k×®-K›¢ÞBÔ€/ƒcq5ÎfC’¾êƒP¼(ü9z„Èúh2 )ê)#ÛI7‘$õ"TH]"J46æ‹¡çF<®þePšÉ„ÛBXŸl/J2©þ’ÅuC1BQFö__ &²½ˆ2âù"!À¢ÂOÔ­]B…E=yäøå5úýEïE¿Ù>*²DsÄôÅÚµkY¿~=óçÏ/Ëïo¬Pޱ­FSnôØvhc[¦ÜÈØvÉ’%•nJÙÎØö¢·½ŽŽí¡¢UÖ®]Ë’%KôضdlÛ_šˆÃ‡cš&ïn©‚fÀëÀ£°}{^¹)S¦àû>?¼×uùå/7ñþ÷«g~™¸}&0B€æädýúõeÛ–$¨´¶¶ÒÙÙÉ}÷ÝÇúõë¹ï¾û¨®®Ñ™­2@ðauuu\sÍ5vÌþxáÕWq€øk=&¢aY_¯&#Ý?MÓÄFd˜[øCË ŒòË ýbØëKåû•_uŠO³ŽÆM¾êÁ¬tàƒø°Šià£¹Ä 7&áÃʪš%4V¤á´zX\ ÎÂ_¤¡ Œ>P‹ZÞ˜;?Y”ÒÛ•;"°˜@,·,‰r1Š©Ü:;÷ïçêòsõ×çÚ.ï—å^]B1Gê\–+ëä^ksÿrìÉH{4e¹—b‚ŠÐF !ú¾pf‘ˆ!’7BC¼:$á`¡X"m’ÏÅö'-"˜†ohÈ/Ù¯ëªnX[^2L31D$‘$ôîCÇGó·47‡³«§÷¹0ŒPDI&C‘ʶ•ð"ûÍdò½hdŸÑó=ÆÂ0aQä|D=作9¿’ '› E0o qu‚1û¦F£Qèþ©ÑŒ]†Ó?] úÕWµ ¢Ñ”rÞ;£oqª0~²±¿Y{öä•;vì®ërýõgaYW\q;vìPuÅÃqEóXjÔùho¯t+Æ?%{¨ÔÕÕ1gΜàóÕW_=¢ éìììåþÝßH$ˆh+5ƒEc&#Ù?½œEmØ é³À÷\xS¦-ƒSëá¬ZøGOùÛ·xð½z¸²êà­õðç®2Ì‹—Åô¸©‘ôŸ…¤ñWÿ=þ%@=dN¾g@2Ý[l)5!Dñ“ ¦|××C2‰ÿ™»ð~E(\™O4Â\>äÀbÞéãÍÿ7(1á qXÜLöï‡Äð¦p? ÄrzÃ/ðƒtmƺ‰äÂXàÜi¶(Î-¹ÿ8ø1õÞ] 4ƒgŸ@uæD®¼¡¾<¿ ¼å€$ÄŽ *) )·¬=¬ßkʽ—eV®l*·]sd]Sn›sÿñ\}¡à#ßc=¡˜$ïO79Êtÿ"ý%:~áó­ï‡Þ²¾¯P_’K$• E qÀÊfCAÂAs4^® êinîíÝ"â@"¡Ê´´¨¶ÛvØ6ÛÃo‰hÒÔ¤Ú!åL3OR)UG<žŸä^ÎETH‰žË††üã0ŒÐ‹FÚK{ £wžKÄ+(+8Ï™ Ml꿽]µ©¡!ÜßæÍa½–îÔ¹’°dâ™#Šˆ."8[öïŸ2ú?ÐQf,õMF“îŸÍØe¸ý³gˆáé5šáòâ‹/Vº e¥Ü÷ÎØc`E„䓪úû¼Ùp===˜¦ÉO~òižzêõõìÙ³*¯žÂðÒZ_ÍÇ4{çÌÔ ža'¥)Z[[¹õÖ[ƒ˜|ÝÝÝ<ôÐCCNvä8G/¼Ô¶ÖŒZžŒdÿô<˲òËGÐõà²4œâÞgÀ;-8Ò¯µÀ6Á#&äfaóA“ôM-8ŸZ‰8µ ¿ ‹-7—àñ›á©2§]n&ýÎO“¹H(§ ¸¯Ü„÷ð6Õþ¯>®¬lT¯7&•0áåÚøQoö‡p§þ \VOrJT»ø?ïð´;áÞ•Ÿí6™ÿ{ÉOäŽÓn“¹­ç})üDŠeÙÞ&?†ô ðâ°ìË&þw ã2Ÿ´Io‡†àäf‡§ÓàbQß`¹2&4>|?ý8î÷ ùy ®Œ°ž§ŒÒ(ÙN.µ]ÓiU®¶Ò/AæPÿ>õ-[&®–ð?’_¡¾>L.7îd2 ó”Lªòóæ©}I{=/¬+™ÌµÃ×F‰>)Bï˜Â÷¦ú>f™YéîSvFúþ9Ä`½ÃB‰WI¡û5„á³ =[Ä»"ê+“ …Ùl'Æü¨›w2 ŸsDÊÈL¦h¸ªè¾d.³›‰ð·+ítÝ0_¢a„aµä·‡‚“|Žz°"øHø/ÃPm—s!‡!¦Š5±È,Ë ½^Ä‹&šs%SçMò¶44(ñHΧ\ äs4&q6ær‰†‹zª$¡7’ìC„$×…çžÓ}S£ÑTÝ?5š±Ëpûç°‡šqZ£===•nBY)ç½óõ㯫 ‘1rÏò*éIö-wå¹ê_tÑó8ŽÃüGöÞo4’@”Í›+}öÆýE“ДΘ™¸víZÚÚڸᆨ©©á™gžaíÚµCŽïîû>¯^qE¥kpm®t4š>ÉþõP)Ypû‰ NîóàÆüÜ̉5´´ÔÐÐKÒ¼ØÂs!f*c`xÙ\¬À¬à×+¯ σlR9BxÛ!™ë„Îã¿57 Ü‚¬qÆ7_ vö›I¾±ºááïùkhú6,{ Zþþ4²=ÿŒwÊ|š>ð²6ñeT5,°~ Îþ5°b µŸ‡ÄuàMû÷Á¿)¼±e¾¦^Å*¢ƒ¼Å ¶ ¬à´æ ¤ÎÒÏdB£­ã¨DCø¯MÂÿþý°ä ²ÏI.ÆW1@KØ ™eîûJL‰Å ûêÕšæpCªmCòOºaÿ~²÷ÀžÅdîªÂ~w--¡Hâ|i.ƼSHßµ“øš546^x8Í{0^ë¢þì9ØWôþéÌ•Ud³Êð›¾ý æñm¤º8PçGíß3À˜§þß©•î>eg¤ïŸƒEŒí‰D¾ÇETÐdîé´ú~DH‘ßhñ’€ð÷Wì™8*^ˆá^úH4gˆˆt"NˆÐ#¿wù\ØöX,ô‚‘W2¢ÉÛ[¤¡À"íŽ &ržÄËD„ñ~‰ÅÂu"Èúd2¼ÈqK~Y/ýT„ Û'ÂP\r~¢å£Þ%é´:¦¨èqäœÕ׫ëJc£ªCĬ¨@”N«sÍÝ"ï7ožËEÊO´bTºoj4š¾ÑýS£» §ú„ÿ)'‰¼FS”rÞ;;æ_õQ==¸¯.Í3ýîw¿ãÞ{ã\qÅÃ|à7­«Ø¤5í¥bšÅC£iGÉ‚Ê3Ï<úuë‚Ï’¾ÐÝ«Ô$šÅÊÝqÇ´µµ±oß>jjj†¥rº®Ëëê`ñâòžÁDßœ5c¾úðHõOÏó0l»4ï¸3887Þ„ý‘ëȸ`{á¬kP7 ù#†P™ÝmYáÌîl64 ¦Ó*ÜO6«Þ‹UBäD“6{ gã?¿« ÌsT»²ËÀRg>Iƒßˆ2ÍÍ3I¯y ×½88nIè-çû‚ ^©t—QÊÝ?‡Š„‚ŠæFékÐ*^Q$Läç-aD„˜Í›U9é+–¥ê’me`(õËzy/¯"–Hè,É™¡Š$5”ßU&£„ «=ž¨0$¡Â¤Ï65…Ká5˶ógÉuJÊg2ùÇ$õʹŽ&§/é_rˆ^Säz Mt¿ÑïLè÷)çC®±Ñ6ÈqFë^{]W­ZZàŸÿyÆ„TÊ=¶Õh4Cc¬Þ;5ÍÈ÷OX0ÁÃ.i4£ÅhŽm÷ÏÙ¯"Mø¨pß î}Øä•›:õH&?É%—üi0™2Š|ÖJ߈ýH3éªëQ.žP{ûа.¿ã}«ˆÿ³Æ'PùÌåí+ö¿ïW¯E¾ÚbmŒ½ƒ:þl°€” ð·êØså%‰ZjÍ÷©}ÇU4{r`@±,†çŸ_="¿ÙñÀHõÏÁR˜ƒBoñn¤f2ªßHé—ò»÷}µ¾¡A•‘±ôÅH/×Ç ó§Dˈ衸"ž$’3¤p°-DÚП<=*ÂFO2E¤TúqÔˬð˜D|ˆ G"FH¹ˆg‡ˆQAGÒhÿ—¶Š×i†‚ª¼F]Ú¥ŽèC…¼ «ò¾0lš¬—}Êñæ‰Ö'Âs±poÑã/:¤¾ò•LšT]¾¨F£Ñh4š“Žýû÷S[¦©é6 'ukúâÌ3ϬtÆ5_Ÿ†wEî™"gHI¦møEôyÆâî»-–-[Æ?øç|èCáD¸¨ £P`Ñä3â6¦“”AçPéì줵µ5ùUSSÃ5×\Ü9s*},½X¸pa¥› Ñh ð}Ÿ—fÌèí¡’š|˜Û@ý¾DK<4´Š("ZFd¶µä ÙÔ á2™}ÝРD ™/¡³ œÙ.ÆBÑ $ù´ïƒùÕÇixâÓ¤rñ&ÅÀ)7ð––p{1DF žB7¯Q¹ñ/®» û›ŸÂøì¥£°ÃòbÖ/Ãtpf†1–| ,Ëä‚ DMuÑŒ4":H?$ì„} BÑÃóBARBFIߎŠâeõ>±S–EEŒBo”úú0ä•a¨þ%^©T~Ž ÓTå!ÌA"?%¹zHbz9ލ§„âFT$Í7rn©ý=óˬ¡¼ë†ŸûÏm'r¯r„ÇZHaȵh…å£ë¢³˜¢ÂeôÂkŸÎQQ+z¼]]zœ¦Ñh4fäx~ölê :Í(0{öìJ7aÜâ8KŸ_Eæüy¤bä)—â ŸHÀ—¾ô >÷¹y|ô£qÎ<³–ÆÆüÏB±çMˆ¾DŽ “SxÆ ض͆ hkk£­­Ûo¿w¾óÜ}÷Ý•>–<ºW¬¨tNj´‡¦?<Š„·s€…ð–þéË!:£¡€Ó¹ú’¹:Ü¿›[6.²QO™¨°$yhäûO¼ÚÚ½¼öÚôáïX£Ñh4&ÇÙû÷Wº f|èŠ+˜zbÌEE-É=¨É3„<‡-Zô&/^L2™dÑ¢ž`²­öH<:ÇÌð)ÙCeÆ lÚ´‰;µk×Ë»»»Ù´i6là–[n©ô1ðâÁƒŒ‘€4'%:|™¦¾ïcFoÁÍ^l€›ŠcÔKùÐè)‰¬[Z”qÔ÷Ãç¶ÆíOIÐ,Q1æÅbý·±OQÄó0oªô)6Žž ,­tKF= ¥"DÅèí­C%‰„ë*Œm+¢¤ïç{’ˆh!ÛDÃéI}ÒY.©xÅH¿–I²¿ÂcÙÓ¸Ê[åDN8õ¾æÊ°|<æs`þ˜;š›PBF AyØ(Ñc3J´ð#Ë}T|`%vX¹ÿZàDn;+W¶uõ€±9÷‹lŸÊ••eªÖò}ø¹2äÚ‘Í­³rí‹åÚÏ-ËæÊ›¹ý{¹uƒÀ*â#ŸW¯ÞÇÑ£O¿7´ŸF£Ñh4MÝÝÝ•n‚F£$;ªª¸àøÑpAî!Bž%åùmË–-tu‰išØ¶<+F'µi&ŠZ3tJTÚÚÚ¸ûï¾ûz%š3gN ¢d2™1#¨Œ·p_boСì4×u™óö·“§Yä¼Mø‹fe`DA%Iµ„Jä hÌ…øú°.…úë åz0ª€4ÄÛQ¢Ã» é`Ä6£ ±\«Ô•`ü9ø10ëPžâª%v4 %ÁÉȽJ^yoå¶·rŸ‹…ä*6øïƒÚJ`ŠGΉ)"H5¢D–|i Õ¯VWºÕF£Ñh&sÛÛ‡_‰F£ÄÁÝðañ­à¶ìÉs;‘h¶­l>;vì`îܹ½êÑö ÁÍYª:% *W_}5mmmý &6l ¦¦fLx©f¬Ë!Ó î%ÀL çee^þãû=Àgã“ÀõÞʉö·À\$ þ/¹iRÛÙïsU'ÀʕӔ†ù†4:ó‡O=\é–j4F£™@ìÝ»S?4j4ã5ïêüï´²æo€®®4ù¸®ËŽª*Œ/å<%sðú }ÔÈïºaNÉÕJéÄY#穇v‘Õ”J6›S€µ,\îy`ïsð`ÌöæúéÀ­¿ŒO¨p}ɯ(´X ˜¯úý²e¹ü+©ÖÙïUÂFöµL.dVìÔç jðìO¶Cv+JÉý®cá{ŒÄ镴̶Ãz5e"Eàñ³ëú]ª:Téi4F£™`hAE£?ül×.ê^©ãøsÛ¡ª*÷ ¨hhP¯wÞy'ûöíãâ‹ßÞ+ʆaèÈCÁÒ‰¯‡MI‚ ÀúõëY»v-™L†Õ«WcÛ6«W¯fõêÕ<ôÐCÜu×]\}õÕ•>~µoK¶m~E>j&e_ë¼È¿v—ÒhJbeU•òët’µ3:æO7—´Ú0ôŒƒ‘Ä4µ¢<Á,–-àþz›Î=àîT^$¬c5˜õ Êˆ{v&õõjY2™ß¯m;§ÓJd ¼_"d³áoW% * D•þð‡x²víZ6n܈ã8¬\¹’ 6Túxè˜?Ÿ5^8´}”±7 Ô&TõQ±¿“À2Âdµ ¨^®|.”EIÈ… ¾ÒgL£z-‚£¨äÌñxàné8êÆiÛáòÍ›+Ýò‰ƒ 6²ÙJ·D3ž\σÓd ý°)§>Æ;C!Dɳø:N︭Å\·ãñü^±Y4–Æ›À¼-¬C5F£ÑhNNÒÞ¯ÍxbWÕ¼öì$õñ®¼u±äïx0¸ùæ›{moÛZP úœ ŸA *sæÌáꫯfýúõ¬_¿>È™ÒÙÙÉÝwß]éã`ߤI¬ˆ„%+ %Ž8„^)’Ï,[g¢Ä“Í„Éj7ç–5¡’Öz¹ÏJ€qsïky¹ºdõ(ÆÌÕ¡Ç ‘WÁ‰,s …›¾âßùÛÍïlç÷Q^–'sÿ>¡Èä ú«*?ÙÜ¿àDŽ#9Ölî³qÔGe¡gÑ"¬.Ô¹6M0 b±P8±¬0ìWnµ¦ h1E3XܯÛTB÷Ä›Q×}Pᛦ*ÁDÄÇQÛX,ÊËRƒáT*|_(ŽXVÖϲTÙl¸»¹ãòÈwŒ\äx›sûörß—kCC® ’ä6–«\ý±È:–‘ó/í•ý9nñ8’óYX¯|7:tÒ Ø~ÚiÐAø›BÍRO$B1%V†Ñb!4#ƒœk¦dªÀ½øpð3H¥ÃAm<®~SQ±NB÷9ŽŠ›J)1¤±Q•$ÞÏu{ÇÀ•ωD8ð‹ t?Öh4F£ÑœTxÀÂ… +Ý F3H.øí,Ù±·÷:Ã0H¥Ryî4ÃCž¿5Ãc *ÐóÒK°bEÿÈe`/†ˆƒé´"¬' ÖÇ ñR¯ì}z‹:"d4E–µD¸˜ÑYÄ©?jøw =k ÛE¤¼t0'w<ñÈç&z‹ V®]°%¨<|"r<.J(i*²ÿBdrNDÜ1c3Jï Ó'ôœIDÖ‰X$çN„ž¢ßƒ´U eËÞcQè"ævð–Wº#Hš0ʧXß„á÷OÇq˜·àrØíåÍHÚg¼çôQ#›Í¢ˆˆ$²^×u‰iK÷˜ \ý³(.xÓQ×¾*%„d2*ב¸\GC~ù¾G g»XV(À¸n(¼ÈO.z-Ð1q5ã™rŽm5ÍÐÕ{§F£#Ý?-ZTéCÒh& åÛºÀ›¶CÍ‘¹X[¶‘=«w^ßýîtvïV¶Û¶ƒ<›Ú411Ã0 êëëinn¦±±ß÷ijj"›ÍÒØØˆaÄãqœ\ $ù,ž&---˜¦I2™¤©©)è{©T*4,Ë"^ÄÂýGgkÒ×ﻵõž|òI’É$–e‘Ífƒ>%ýKêÍf³g‹eYA9y5 Çq‚~%ýR„ @‹1#@¹ûgQbàe¬÷„³† ÅOñ.O•XL•I$Ô¿a„"‹m‡ý>*¬ØåæÒhÆ0åÛŽ\WÏÔŒ-*rïÔh4%QŽþ¹£ªŠE³f•µÝú6§9±­tOéæîz. {VÔ.T]ýëÖÅÛ„gŽ ZPJT2™ mmmlܸ1X¶aÃÖ®];èNsþùçSSSCgggÞòÖÖVª««ƒ°a+W®dåÊ•´¶¶JíÜzô(o™=»àPÉç'è&*ˆ¨‘Éd#¦ã8X–Ecc#‰D"˜ /"D,Ãu]Ç £±XŒl6‹iš¸®ˆ,®ë’ÍYÓdV½ïûÄb±@”q‡ýË?…sólEÚ/¹¶ËÌýD"‘WÆË]IÇÉå}p‚cCt*• B&Ù¶²AšMÓ¤±±1xŸN§inn Èbàòš^ô—¼~‚ÐWß„‘éŸÏÏžÍÙÛ¦@C œp¦z,¦f¯c(Ü]2™$‹ÑÐÐ@{{;@ðÛ—ß¿a477ÓÐÐ@"‘À²,Òé4MMMy‚ˆü£Q¡˜h•y¤`pñÅKضÍIJ¬ G1FÚ'Þ5rlr°m;ð¦u¿p‡¦¦¦`»ÚÚZâñxž·œŸh?4ÆÒ`ŒQîþÙ‹dä} |'Ìy½PÇ ó¦8‘àÒét~^¤èOÛ¶ÕoÑ4•ð¢ÑŒWÊ=¶­"ÈkaN¤(¾ ÐÞµµêZ ÞiÑþ]˜/I–Féã©Ã÷•x›J©6ÊõÄuÃOƒ©7ºˆÂrÌ"÷5oÇ÷Õ±zž×D/zþ¤¬\ 3UVÆA‰„Ú·L:ñ¼ÐûO¼{m[mçyÊcPŽ3›UûÛ0Â8䆡®ÇÒ®¨-·Ù—ãÀ¡C Ê÷ÃEFýÞ©ÑhJ¦ýóÀÔ©Ìèé)k»õÓŠæd`´Æ¶ÓLãò]Uð&ìTã tZƒ, .¼ðhÞS=OsäÐçrø”$¨ãî»ï’ )^.ÕÕÕyËÛÚÚzÕU]]]ô¥££ƒuëÖbÏ¡ª*ÖžvZXÀCM#(£1Üó<2™Ì€ÞQ2™LÑ™ç@ |Dg€‹!RŒ¹"š$ ’Éd`ˆC¦´)“Éä 2Ó\ÊIëD"ACCÍÍÍxžGcc#MMMy†„!c³ˆ'"´´´´åOÏ…ûúæ©ßÄò¯ÂI¸¢D"§S©–eÇ!ÆZ™%‹Å‚ó/û—¼öHö!ßISS†aÐØØHss3Éd2¨·¡¡T*x¸®›‚IŒÈbŽâû>·Ür {öìTþ ±J_}†Þ?|ðA t·ç”`ç…a€*Eô7'ýW<—\×¥¹¹™ÚÚÚ æ©jdòƒ,­ô©˜°d³'O¸í 6ðàƒޏÝvÈ‚ÊH³oß¾^ËJk–,YÒ÷g™ò¦ÔÖÖ²yóæà³„Èòf` b M&“˜¦¼·m›t:R—ÓétPZ¼D\× Œ½QÃ"‘¼/2™Là‘!"ˆ dÄà ¡1Ø4MZrÙ ·‡üõ².jlmnnæOïÙÀïo¿(h»ÐÜÜxDëo9wQcm_aiiiéeìM1PÉñEóMÈ÷­_„Ä3F<\Ä(‹±}ûvn¼ñÆ‘ýA†Ú?¯½öÚàóGÝ“¸pßë@hC”Ù–‰Dù/æÒG³ÙlÐÇÄ@/‚žhâ±aÛ6©TªèïO–•6î$¢ðœD?Ëy+°d¹ˆ­^_$Œš„"L¥R$“Iâñx^~×uƒ<3+W®dãÆ¬[·®Ò§£ì ¥.X° cmˆx¤ˆáO’ÒÇãês,ê$œWt,FDÇG}”¯½†Tªÿ>Óõ½ï±ø=ï >‹wXJ.žÇÁ_äèO0÷¿þ+(÷ôí·³äᇙsüx`ô¢ù…ÒiÈf9øâ‹Ìܵ  ¼œïy¦ë†¢ŠïóìM7q^´a2M<‚„ije x,Ƴ;w2½®N‰‘™Tý<ñË–©úD„£|ÔS- óÿbØO&C$WåD<‡>ÇQÇ%íÅTyñàµAƒX,ôÉfÕö--¡8"âŒtËX,£ ô‚‰ÇCÁH„ ÈÃÈÐVê,6„•ËxòD…éæfuÌííù¢Wô’!åe¸Õv-+_¼N§U9ÓìíamwXÿ›ø‡8Ù³•üŒÄØV£MôØvà±í’%K8ï¼ó(7õ¹W1üÉØIˆ‘/ˆ¸¹21BÇp?²m,²½ˆfA+÷ÙÏ­h.±©£1·Ì(RŸˆ;áQÚ,ÛK³õš‘6¹¨ñ¤™+'û1"ûÑ)z®ÌHYi£YŒdŸF¤¼Ô‘Žl'çÇ/¨ß _l±rç¦ðz‘:¢ßCpÌkײý]ïâ _ÿ:™‘Û¾~üõà}Ô+Wæ¾UUUUú',cxî݈S®qÛ˜TŠÍLJÞ–½óæÁöíêC†|+Á0£‰iš½fe»®üGó Hh+ ³¯ET< b؃}&“¡½½=»•H$œ‘-"BtÖy¡as0^4ÃáØ1õvð‘§yׯµ½ ÒÅ Ô‰!Ä|ioogÙ²e×@) d—ó'¯2ÛBJ~ÍÍͼÿýïŸ*ý1ýó”îS¸lÛÿ¯Ç3óð%ÁõH"^Z^*ê…Mê.a«lÛŒñQ´`R^DøR(âF¯¹r ‹†“<5"2‹Ð a¨²‰ÌHÝ?2@S8ãZ£#„!¾Äð)³ßÅxèºNΠª&<ùäU<ñÄÐÒôFëëÁ5Àó¸ëCâÝmmA(¹·oÛÆ©Ÿú»fÎäÈ‘#üñš5Áº[W®¤óÏþŒîÉ“™6mO=Ê;o¹%øý|üÞ{éž<™Ó–/çøîݰ{7OÖÖžž¾ïS_[KÊuI‰'gmmRÈó”òþüÏItuÉ7oÞÜç¥M2ÁABÚEïNO®9ò^ÆÑߦa¼í6vü×ñ9àï'MâG÷ÝUU°nîûßÏ{ž}–'ßúV²õõ¼¶p!³ßò^ß´‰§Æç¿û]þjÍÌ×_çÜŽ¾üÙÏâ{«÷í㢋.bë÷¿Oí›ßÌîãÇY´k=sæðåÿwî~ç;Ù¼t)¯/_ÎÑ£GYpð {çÍã܃ù§ž¦üîwÜqæ™›=› ví"išøÀõGŽpðàAž˜5‹3¦N ”ŨG=ÀŽÓå!Ô¶–9ÆùX`Äûf‰D"¸/È=]®-"ÜDóƒÁ Éû%cƒ¨XX ¬Î¹m?ýt¾ý›ßÐ3s&Þv›w¼öç=üpð{÷¶mÃþä'Éd2<è8¼õÀlÃ`ÁÁƒ<þ…/ð¶·½¿úã?fsî×ú œ}úét?ù$ßxâ þöî»™÷À|û¶Ûø³sΡººß49õ‘Gxî™g¸ëóŸçú+¯äÓßûí›7³ëg?#nÛd³Y~sÕU¼ºt)ç47+a37}þ7;vð—ý(w~ó›¼póÍØ®ËƒkÖpÙ}÷±{Î^~9×?÷÷ÍŸÏÔ+¸éç?¯t÷)+#Ý7£ˆð`¡hâ|b5`ÿÞeмÒŸë8ÄÏïIˆ{Þ ¶¡þñàé3ž&õ/ððÃó†Þ@Õ™U,8{?ÿðà¹<û/°øÉÅTÝTÅ޼˜®é]ûqÚ^jãæ/ÝL&›ápëaVo_Mõ%Õô,êá…ì ~²P9û§F£CíŸÝÝÝ•nzQ B/»Ÿ2QCÿ="÷‰Uâ2iS± /ÍÔa}iúVäµÔ‰òÍ1h}bÍp'ë›À´ƒ™~âÄ0kÛŒô½³êøV˜ñ xìÊD=Ó„åË—Wú5š>)YPéììdÆ yËzè¡^á†êJSWWǾ}ûhmm¥®®Ž¶¶6:;;¹æškUÏ”ýû•ÂEMæHÂ{†ä CŠtd¦tT(I§Ó´´´äÍ’–¼ …Éž!ô†ˆ&ÁÏ\Uÿc>þå³ÙÙº›+¯àPîÜ2#¹˜—eY\xá…eÝÿX`$úg‡9ŸšÝ¿Â:d8êx4Yzax=ñ<‘v‚ö:™Øˆ‘:•JaFêþ)¸¯ïæ'-–?Û·ïÆu–.½9(ÿð¼ÌŽ~ïµW_ý'œöÊEœ}âIàÜٟ僟þ4é\¯yóæ1/'$Hø½#¹0‹Qñ#ŠÙÑÂrt kò9ê)÷]™ô`Fžw¤/B4]2™Ì Ñ)å YñN±,+¯MÑrÅ<2}à;vð¥mÛxÁ4¹jÑ¢^ç!Šœ‹x<Þ« ²×÷FÆA‰o$溤?õ)‰/^ÌO#íì\µŠš5k‚ÏÿvÓMpÓM×_4oŸü¤úÍäB{Úñ8o{â ~õñÓÜÓÃûÏ8ƒ?üÔ§ðâq.›2…=Æcg…ÉðÌôé<7Á’FºoB~r/Ø—‚û)0Ú€÷BýC»êÿ6¥[xy÷ÛH½ÿQþãWÿÁY—žÅ߯˜Ï¼½óp3u|íÔ¯ñ=¾‡ù333ëÏW“ ü]>Þ9Öt ÷Ÿ\f™³xÇÒwðÌ9ϋŸœËéø±Šå¿ðâ…¤¦‚|}¾ï³ÍÝÆ‡¾ÊÙûÏæœ?Zì§gqÿÚûYüìb¬]ç™ç±ç{øõñ_“¾1Íã?Î=m÷ðö‡ßÎôW¦ó¾¯¿çÛ‹ß³˜9Ìaëg·²ó¿vòÔѧX˜XÈ|>·¾x+—ýùeìº~ó~8Ç>Æ•W^ÉØÒ´…YGÕ¬Çm[¶aš&g6œIõ Õ<¿åy®Ø{¿yü7\:ÿRöŸ¾Ÿö>ÀŽC;¨[XÇE]Ä#'áίßÉu×]Çžž=,¸cçÞ~.ýƒÌ\=“3ß&¯ýušbM?éóÜtþMð"L¾p2Ou>ÅwÞùþdÊŸÐ5£‹Çßó8‹[3Å™‚™6Ùzd+?yóO¸ðè…Üûñ{Yóò|ÃçŒg°iö&NüøSΞÂñÇŽsÊOá¢õ±rÞJŽœu„g÷=˼êyÜ?÷~^h{k:®agíN~~ôç˜†Éæ×7³ðá…<ï ¯Í{«®ºŠßíÿ‡Ÿ8LÕ¡*.™41bÀ÷G9ú§F£†Ú?;6æòVj4‰‘ºwŠSõ«Ó=Xc‚f$2¡C‡øÚ×þ†©S_þ§Ò‡­Ñ¥$A¥¦¦†ššÚÚÚ‚euuu&,ëׯçÖ[oåüóÏç™gžaýúõÌ™3§äí`êᇈ 'F ™ÁZ__OKKK0 ^’°Û¶—£#)™3sˆñ¤/C®eY444L˜™ò×¹ž'vPutü»<Šq ¾¾~Bˆ]Ce¸ýsÞ¾)œ•KJï8jö$ ¾ï“L&ó g³Y|ßgóæÍAx=/³H£™  ·øÀŒÐh›Éy“I~…M›ŽÑݽ‡w¼žqþ¥=Á¿üSþôü³áI¸í¶ÛøéOÛèè˜ÏÅïàüH>ñâ€P¬hŠ$<°úæäA)ÂPî›ö ]㢹ÇÊ… Lv:/¿ ‚ÊH"!+sòÖÕ|ã°uk¯XF¦iö64ú½=òæ7«¼,³f±xñbüXŒÏ.Y¢Å9—ý . ‘H0ë$¸§ŽXßÌѰZž÷{`ùàžMŸƒômÐý–ûHüýÛ˜;·…ç㬳L>×ü7Ì5ÿÇxšÿþÎãyÙl–;r']±. i¹½¥¤‰Ë–-ãÀÔ¤R©ð;Ï Á•/jڶͲÌ2:NÒ¦’™Xý ί0¯à ® Þ­Çëöh_ÓÎMknÊ+cÝ]°}\ÅH?€ûºKûK¥ý¦ÇQáû.öølËg‹–¹€ àÎÈ6ïsxü'C†ï<òµðÏ` kh¤±hiÒ¼Çy†apCó Áò빞۸­è6Éd’ù?âãâ)ÕßÌ›óÊ\Îå½¶ÉìÌе°‹T*ÅÖÐ×qÉIÖyë°,‹óçq^$kÔc+é<ŽwFºVŠèXød@<ÌK!:™1º¬Øù’|gžçõ9éo?R§LöŠæ=-¥]Ѽlbkvœ,ßm”¡ôϵ÷܃5Rá4š!ðâ‹/Vº eg¤î&pÖÁÓà•*ˆä§3 ؼù«WÛ,_~%úÐŒ;JTÖ®]ËÚµkGtÇÅ­]»6jDÄ,§üö·på•JP¢íC‹X–$BADfºËÌ÷¾J®’x<>èÁÛXeÓÒMœùƒ3Y1cb„Ãjhhµü3•¦¯D¸Ã퟿[TÅ“§¾‹ý0'³m-–„ò}ŸT*ˆ‘Æ+“›ñÚE3±(Wÿ ðëÃDÐQ›úsÏ}c/¿‘Óçþ”™3ßÊ‘)ÿÍŸÏþ+ºù5_¾çÞñŽã,Z´ˆx|Ž‰ÄŽª? IJ9þ¼\?¨0]ÝÝüjÞ<æýîwyÛFÇr‹^ÛFÔ˜–H¨¤r¡Š`•{½aβ_\ÔYøú믟pIéË5¶‚4ÎÓàý;x/@ì3pÕåÝüõ¿ý;?+W^ù-®ºjûXGnbÛùaQÅ{J¼oó<Ž`(†FÙfP‡ZÄÐØr<ƒÙƶmêëë%ȆAýSƒÛF¼ñsΤmƒq ÃàÓ™OZø•É'²ß;Ë€„›ÎfU*çèõ=^òsY–•úVÖËý!*D˜¦”•uò^ú¹¼÷Xx)¼îæ@•s*Ç%û•hR¿œ«è¹‰Þƒ£÷Þœ›ÑsšÉd‘%‹9R£m”å¶mÓÐÐ@,Ã0 ƒý‰X3I×G“ñØ?5š¾èéé©tF”rŽmSÀÅ™o§ÿ1o¹e©Ü)ÓJ¨ìh{-ËÊ{æ.ü½Ëd‚ ¤¤mD}£Ø¤ƒhû夞èòhXÏh;$¢L¸ì«Ÿ‰°UlßQA¤ðxåû—åÑïEÂFŸ~ðƒÃúÝ'Æ…â¢lO…©oÜŒ0rŠŸ+^~†fî½{ïf«÷’¸ÛJöz y/·*» ~reÝÈ6™È6ƒ½¸CØF3!‰¾ißžq”ä{_ÓçÏïàС·ðÿ0¹Ò‡ªÑôÉ • 6ÐÝÝÍwÜÁ† ¸ûî»óÖ×ÔÔä J*Áy¯½¦Þ 1Œ„³\$ƒã8½r0húçè7޲oá>¼A¥›2"h1eø˜Ô9t#‚J,¦lw¥’L&q]7¿×ÞÞžg@“u¼F3,r%ý³”0²cÇ`[¶láGModÁÜjŽŸr §_ò:üæÎ ÀÒ¥sƒ*Æš]Nf†óæ€ðZ‘Éd‚2b‰Î*ÎèÇãw‰~ãP4Ô‡„ûؼysàé9Ä8ÖU[Ëô§žâ÷.äßßô&>õÚkxßúV-Úîl6ËæÍ›–뺴´´3`Åèä8étšX,?2 8•J‘Éd€âù\\ÏS!3&ÐDqÞÀËELûbÏ,_~Fç¼õ­oaÉ’xߦä*‡ @3–c?C1ð÷gäì ɵVÎm¢ÞƒÙÇ`σl3”¶é1Sù‘TQÄKA¢Äb±à^Sn‘«Ѳ°L±ßVáï®/o~Û¶‹ÞkúkGôþ[¸¿þèË[³¯¾1PŸ‰æV+¥ì@û(VG1ªXRæì³ÏðÈ_ΜIÃÞ½¼øÞ÷ò¥_ü‚[ßÿ~²W^Éœú'º¾û]ê¦Oçܪ*œ9“[wìàËóçsÍÔ©jâ¡m“ʵ[&Ýñ86aT„ZrF¯œ"“ìâ„Ñä<Ø„ó<¬Üûá¤F™ø×Ä^y…É‹qZ[Ûˆ|¥ÅføÚ¶„0M&“ø”H$¡*VL(±,ؼY'|?Œ§)?]@7|rÇ«ô\ñAêëÕC§eÉkОå,ÆPBqņðŠAy(as‡²¤ƒa(^îCÉÛ·gÏžQÙf`D¸–P]’Q£Ñ”—¼°ŒPŸ{/ñ¤h¦x¾Ýè-Î(²L32»ýZ¬/,S¬l_ïÍÈg»Hý…e¡·Ð-S¬ü亟°ã—;Ê{î&Û¶mã²ÈgßJØFÛÎn¢ÑŒ5JT¾ÿýïSWW×KL‰rË-·Édhkkë·\9ùõ”)ü©<„»È‰@=$V¸iòOé4¶eÑROÖ0 Œ5kŠïÔ0z‹Qd]_ Éd(z¤RѧcEÔò\(Ïú~þ2ÇQÛTLS•/|xL&Ãs"DüDp’6Y–2 DËg³jßyíËÕñ öÕ6Ñ 9îè±æ¨Y¶,œ ëyjûèLºLFí;Ú–Âï"™ Ï£|Ú_æœòMàcø¾úÚJµ±d³YÒét0s\‹)M™ÈÝ: ص‹÷uÜÁãµÿDç‹`ÿÔ©|:ÉÆÐ;?îÃÍ9·ýÔ³ª<§º„¹<Ô6²L&ƒ5Ó_{ô©§^ø¿ô(ö3®¼Ó÷y_u5ǾùMìXŒÓ§L¡{ÿ~î›<™•¤möîåÑ9sxýò˹´£ƒ¤mó—Ó¦ñ?¹¤—ϘÁ¿_|±Š ð·<ý%J¹uÑ"â(AG"ˆ¨# Âcl |ÆrrËjQw=‰LМ;æ&”p’P§‰4jžAcn„Ä>!ßeñ ÛVO£@Ô˜*ž€ÍÍÍA~—¢g¹çêp`£Föè8µ›¦þœµç¯å ‡Ÿ¶ۤь|ß§±±‘–––!…¼Óh4C'ðˆ”ðTM¨Áç2Ô,™8¥O¼ÕhÉ™gžYé&Œ+z^îaùѾ™·\¢ÄãÚt§Û 9)ýÚµkéîîÎ[VSSþ}û*v0gï߯ވõ#Šç)a ÐƒÄ0H挵ÍÍÍd³Ù‘}(è Oî«<]$t œÙw 1öFI¥ú¯Ã²@¼uLwá4”€Cy[@’8E~hç$J„¨ªï¿Ÿ«®ºŠ–¹s¹çÉ'yÇÅsÁ£2yÆ ¦M›Æül–ÝŸý,.äsmm|â­ożà>|ø0ÿ²u+‰åËIÏ›x¸4-ZDJÀ°«ª°/¾˜4a(k #'ô‘»—)c‘E@rŠ»3ɼðè3ºÜù¢w¸æ‚×>©@˲hii¡¾¾žæææàz›L&žÅî8Ê}©©I -#kåóûöñ×ýfÖ¯W§»p褶Meñ}Ÿl6K&“!ÉJ£Ñ Û¶Ã ÔàLG7ÔhÆ;áÌïŸÉ¡i¿aNn‘ð35—ÖqÛv$1€íqX3Æ(©TªÌ4{‡U“Á–ë†ÂÊX¾Æ ‡žÜΩû¦‘Lª Ì ½#¼E‘¸þžçé©F3˜à}FÝ>÷LšÄÿûc.¹îº Ȧ•Æê¸Ù\þ Þ,\3Ì•b£æ4x„¹$M” ñÎk¯%»v-–ë’4M¦çö~üÏÿœ––îhn&™LK$òîÇÿõÉOVú쌶]q/J1¶··“L&ó¾‹t:ïû½Y®ù¶ µµ*t¨6P ^ÿåëübçâ×Y8¹˜r}Þ?³YuÞó<†Ý0|ªï÷þ}¹no·Qq%-Ú¦\þßœð'aiµ¡Y3q]Ó4õ˜U£ ø(7aßWÞ³¶N®ÌdÂPå¶­ÊÈ„Ût:ÌgY½ïqŽ£þc±0ÿm± —r³†Þ‚äÝ•rN]ÛC±m£eä^*÷øb÷Öþê’ãŒÞÿõ¸M3šÌ€¯ŸàÔC§‹¤k %ÏŸFS JTjjj¸å–[¸õÖ[¹å–[X»vmà¡" ë7mÚÄ]wÝU±ñ…]]\¶ÿ2X[˜N«T?oñxœX,†ã8z6ÑHbY.¬tC ðá¾ð7`Û½ |ð®»h¯8^èž:‰®EËà·j;Pr1‰Ý?”D®fxPšÌw`ÿ~Žl™ÇE7ÐÆÂŸÜDléth°‘û¤ã¨å…žæ“5)D @ROSS¾!¥¡!|/#é›Éd(Ðî§±1ßÐ#¹òóæê“ö‰á§½]Õ%†"ioôú͆ah%Ï^4o çõ~ÁI Zœ;ZW4ç^ôØŠ¥¢†1)W89+“).”ÊvѺŠ抅ÆíϘ5ä°¢ë ã«L #£¦d|ß'“ÉŒŒñ'‹š%§ïDØ’ LNf¡f2عua|KIÖa‰Ã'ôPugBÈ23²}t™™+oçÞK;¤¼Äÿ”x™~¤)#m–vg(žÛ"—«-8®(‰H»¬Ü{ŸÞm•xžFAüÜ>HéÈz#Ò&/÷Ù$Ï«7Ø.K˜$®p½Y.ûÌD¶5"uÈ@*›[©’;gK_]Zʯéä% øYp’á½A¨Å®·’'Ö¶Õ=¨0¬‚\kT™Âzä>½&NXèr-v/•ët:­^ Ÿ‡óÛT˜hBòÌÊñF_Y/ç¦P@ŠÞ›¹§ Ñœ¸®z+«CŽUB¶Gëq*ºŸèùÈdòÛQhŸqœðþ^¬ÙOÓÌ¿_ÛO±óZ8ù¶`?WÜ?ÏJM¿¸ÕpÙÔCLŸ5=X&§7™LjQE3.(9‡Êúõë©®®&“Ép÷Ýwç­«©©aãÆóNé…I˜€~¯“††ššš´wÊH4O$Š ¾¾zë­Œ‘_þ˜å7‹1{éTbµO~q]WçJÑhF< œ`úŸÖpF×,~àMå<öz°<oò_=Ï/V‘oûˆšÒ?ôîwãû¾ò8‰Å‚üd®ëâç‡÷Üê žz‡d³Ê8ÓܬÞ'½Ïs,¦þåû‘û«ç©mš›{Ýûrñ}e¸(æõmšÊè#ÂIô>n}{÷Z–t ¹>ô•¿Ï¶Cã†a(c‰Ì6ÎfCQ%zlÑuò>‘È?'õõê|t'<~Y'Ÿ£ö]ßWm+ )+žÏr¾ ûˆë†¹£çN„«è¹11¢E hÑã/4(‰€$Æ?1Œ%“pÕUhJ#™L⺮š FúÂçŸ ¡‘ÞEÐB¡C’w‰@!åÓ‘õ ’’%sõ¤…€,¡Ñ>jt#ûzDäý;‘u¹û|°ÌŽ”±@ê°rËE”‘í¥vdÿ^¤nA½Dêv'»`;3²o¹H[Eüˆ #"Ú)#ûˆÖiçγ$UaÆ(Ø¿NÅ„9ö$Jä)\/B—ˆ_rþ ÅŸ¨p%ÏÒQa*×v-¨ €ìsÕ½¬ðÞÑßX$*B£Š€Ò—ݨÐÐ_Œ& ŽDñxiytûòJÛO’£uD= Û½~_щr¿,ܧäó•2Åì…ç´Ø~ '!ûíD½yŠÌ}¹¦†ý¢)˜}`6±{8/·H†ªñx\Ûƒ4ã‚A%¥¿å–[¸å–[hmm –UWW³råÊJ.pèÐ!º®ëb©½–å0ûèˆÉÜCE"‘О)å œ¨t#4c…)ÝS¸à©#¼°´´\ËMMM}ç4ÍÈ#“ÛÚØ½‚·¾s*?>fÁ÷“p0gÛP•{ùv*´ïÄŠTW__x/X–„ˆÒ÷Û‚1ä¡õò)¹æú£Ø¸{ ñ´¿6ôÕÆ¨P*}™¢¬bF&Yïû*¤”‰~ýísÞ¼ÞÆœþ ^²Ÿ––ÞÛ‰pU ÃP纯óÙW[ gêlØ0¸s{ã8í"26¢ŒÞM¨‡S1Þǽl”1½”Ÿo±ŸHôë/fw-ÅÑÓŽlk•PG±vˆ7K_ûŒî£¿vô·Rˆî»¯[Kty±6EÏiô¸újë@罯vD·‹ PG?<²înâ¦!ž°‰eYªßm>É=žGƒÁŒú÷õ' †1í«µe :Ä{f cˆG‘:·]|1;::J?/';žCOý¼à£œÒÆÆFR©Tðœ¡ÑŒU%¨cÆ%‚LúÑxóþ Þä–”DÜ÷}²Ù¬v%ÓhÊÌ䃓é™ÑC&£žçûz¦oll$“ÉÐÜÜL,ÜN4ÍÐÉÙ@w/_ÎäÉ“Ùï¡Ü-tM ûPcÀ¹â}=¶8¹YfÍÍÍ8Žôc-¤”ˆ„ó²âñ8žçáº.Éd2xà‘<*–eå祋\ð³Ùl0X30ÿø»§©y=© ‚($}2XOkñ\ ¦9xc"ÑŸ§MÛ45 îû‘mû|¢ÇM£N6›å#D%sQq3eÒ² ¢—ó“¸ûh4£A*•‚ÚJ·B£Ñ”«¯¿ŠýÉp¬sÝu¯áy;ó&mi4c™! *c™É“'«7<𙦩 ¶Í(ѱ¨‡×—¾|î«{J>}ÕhF™4X‹žåGo{U/§*7[s6ðh®ÏEšSdS×uq‡D"*š!âyc&ÜWˆ÷‘¸ã»®K<Ç÷}ÇÁ0 <ÏÃ4Mjkkijj²¬@ˆÑ×øÒ0ºvÒvíMìË–ð“СkG‡¡üv‡òÝèïs\à8wl»n#Œ{©/oMeÑe5š±OwïE™ŒOk«òj×)4ã #¨Áš(éa'oö¤F£)+“¿Fí²evÍd2©Ñk4À[FÍb¶¼þ:‡_šA€ 7ZpŸ çæÊëÃ’t~Ù²e´··ãû>¾ïk¯”“ñð•Ü*ŽãÍfqEÖ "¼iJÀ…ÉS–ñâþ³9«ÒmÑh4½ð}Ÿžû{Xð–ÅÃ7i4šÑçk.üă&Ý)5š1Íصó/!³/˜D2oÞ¼À^£LªtF 8íÁ}*6í@e}?/¸F£)/ wxô,ZÔgxS×uY¶l™žµ¬ÑTèúë9ÌÙ½›iONÆ²à‚Œr–ˆÅÂÉÒÅn⥠Iæ ÃÐbÊp0ÍÁ‡úÄãqš››inn&•Jáû>™LÓ4q%“N§‡¹§“¾:ù5þõ_§jgf âº.«oµž ¯ÑŒ%\žr‡_F£)/]ð“^Ï Wº|ù=$“Éà¹A£ëLAàÝþJx­ÿh2™$›Í’Í– ¼h4šaÆaН/£„à3ÆpÞfB³žÍ@ÕŽé˜L<—纣몴Åð}?í¤ûïQJÎ1L,Ã÷}Òét ®I(¸t:ošþÙö­m\sêÔÖªHpflñìמåºg®ËÏ‘¢Ñh*K¿?~ÇPÍIÃÑ^›<=/oä /ÜŒmÛú™R3n˜P‚JÞ»áåþ…×u1 C‡œÐhF àÄQ’ÉâeÒé4¶më~©ÑT¸Y½=¸m7‡·O"“QŽ–Õ~ôÚZ•ùSç>!l»¸Ð8Ã4MZZZˆÅbÁ?(/¦úúúJ7o\°eËÞ½äP¥›¡Ñhúà ?“¯š<º;H]õ<ð}­ÂjN^Z]8Wc5š±Îk¼Êö3NË[ÖÕÕ Ÿ)5ㆠ“C`þ¡ø§¾ žçåÅõÖh4£Ãñí¯bä½ôéŶm"H£©.ðØTõNvõqÎý>†¡Pq”î)) „ÐöööJ·^3hhh ‘HàyÍÍÍïð$ îÁïqã)ïPÔÔh4•á ¿À#븠çA:­^-K¹}¦RùIÉ’Iå jYª\,–/®»nïYIÑxœ ¶— ¾¯þ ïѹIñx~Éd~†‘_‡ï«: CµÓ0z·5Ú¡0?b2©ŽI°¬¾×0Ô $'/vp2 HÕašª\"Ñû¼÷׎èw7Ðy7MÕV×í}¼õõªiße…m-v¼¦ÉÛžMìNÕÆXfÌs¢ŠƒË.Ï[TUU…eYÚCE3nS‚Jgg'yËÎ?ÿ|æÌ™SÒö»g,aA?6Y ó¥gÁk4ƒgÈýsT#Ðûù ¾¾˲t^#f ÷þé.:̤ªC\0õ›€÷Xà8ê¹>› í Bg¦R)}/Õ”L{{{0™¥±±ß÷Y³f 3f̨tÓÊÎPúæÌ#3Y´ëW>ÿ0†q*z¢žFS†zïÜûÛ½|þàçÃp_b¼÷}uã, mhÛ¡X’HôVIS©þ½-«ø :J¡8RŒÍ›û_?P; –¡¶c 1¿e©óT¸ï(‰„:ï}…ÈŒž3ÇQâDáä­D"ºú:ÞX¬w]9^×U߬H2ô–µÎu‹ïKÏ Å›ÂýÅbÁ`lûo~ÃÉÀúçò†O£)3Ã}îØ?c6ÏN}+æ´yÀžžžÀ«]£Œ)AeÆ <ôÐCyË6nÜH]]Ý€Û:À3sÏcA?etŽfè µú‡`ÚëÓðö1Z[[+Ý”²3´¾éóóSNgöìÙÚþªÑ”‘¡Þ;÷g?“–çR‘ê1¬FS†5¶Õh4ec$úæÌƒ'XrÆq\WMâ‹ÅàС3+}hÍ SIé[[[©©©Ò¶³£ªªªÏõ¾ï“H$Ê’§A<|ujÍDfÈýÓßÉ[€Þ“·´gŠF32 µº@ý§¯ãGW^,kiQ³„ŠÍ=p‡T*¥EP¦D†Ò7Oß¿ŸWæç_ÿuj¥›¯ÑLh†zïœöâ4æ_5¿ÒÍ×h&4CêŸ}DÆËdBÏkF3<†c·VN÷xj×Áœ„Lž{nf¥M£cFPéîîàöÛoçœsÎaõêÕlÚ´iÀí8@kk+§?…û®º¯h™d2Immí ·QÄóTùúz•‹oÞ<ÕéA-khPÿÚ>|rÑÚÚJWWW¥›Qv†Ú?»ºº8è¿Ä”)¯]ïû¾žé®) ÝÝÝ´¶¶rèСJ7eTŽ×?:Dkk+Ï¿ò ÆÑÅüfñi\ø¿Ô= z *®ëâû~Y&&hN.:;;ùÍo~Ñ#G*Ý”²2Ô{ç3ӧ󹪷ôÊë¬ÑŒzlÛ?]]]œrào8ïç XV£Idl{àÀJ7eTކ6¶ævpe³‘|€ jœ[_¾ÇjF”ÎÎN~÷»ßqüøñJ7¥¬ ×nÛÝÝyf?/½<ƒÆF•Þ+•‚7¿YO$Ò”‡¶¶¶²ŒmÇŒ ÒÙÙI]]·Ür [·nå®»îbÆ †ƒ8xð ­­­Lß}5¿(®’Æb1ZZZˆIçûêF›Lªÿ†H§aÙ2õ>™Tå2U¶¹YåloW3x%÷`K‹úÏdTžÍÉÁÉòÐ9ÔþÙÕÕÅo9ÊogÂ4óC{žGVd5ebß¾}' 2”þ)Ovwc> ³¾³Ÿ½íoì7rI&“ѨfDèì줭­Ã‡Wº)e?ΡŽm·oß^éækNRôØvà±íÅû¶Uºùš“Û?…x<´¹®‹ã8úyS3®3*­­­Üzë­AL¾îînzè¡’“½¡ãeŒK{gÐõ}ß÷I§U¬ÌeË”ûg*Uš˜bšJÔhlìí*"I!2#B¼_d»l6ô^ilTyXjk•ñJ¶‘už§„Ixï8ª¼”[¶,Ü·äo50˜7/sjkÕ2PË¥\4œY2©ÖÚN¶uÎÄG^5'ÃéŸkæòƒ…ïÀó ri4šá3¬ûç^àïäùçŸgáÂ…$½EüL&£=S4š!0Ô¾¹ÿ~zz¡çh4åc¨ýsî+'x¶zq¥›¯ÑLh†3¶M§‹Ûh éË–£Ñhúf¸v[æÍãê×߉ç…!ámÛ.š¢A£ËŒ•µk×ÒÖÖÆ 7Ü@MM Ï<ó k×®eíÚµ¥UpÊöÔÎíµøë_?BSÓ'ÉdÂ^ƒ¹qZV8[·Øƒ­¸âyê?/MMáúÍ›CË Eù,mt]%ÂîÇ4•ÒÒ’Ÿ—Bfd‰D~ûe?"ÒGÔ÷Ãm\W•1 uɤ:¦TJ­3 ôÃþIÂpúç¶9sèxìjš¾–ïåÕÔÔÔË{L£Ñ žaÝ?gÀ±9§sƯð®wÍÈ»/€>MÓÔ}U£Cí›û÷ïgáÂ…•n¾F3¡jÿt'[¼ñÔ7VºùÍ„f8c[Ç #†ôG*•ÿlªÑ —Õ«WsôèÑJ7£¬ Ûn ¸¯Á‡Ìɳƒ&“IlÛÖL4ãŠ1#¨ÜqÇ´µµ±oß>jjj§ržx;ÇN}¹×â/¹ƒýè.¹D}ŽÆÎ,ÛîÿF›Éä %²Q[ó“p«¼m‡Â‰¬Ïf•háºj™?±XXW,–ŸŸEDGl;ƒP-“ú|_…ocY¡hãûá¶Ñd--¡že©å’'&“={FøG ³ µ.ýÝë™Ùa„±ò}ß§±±‘–RF»f@†|ÿ<åÝ“º¹âŠ+ú,âyžÜj4Cd(}óÌ3Ïä’KÖTºéÍ„g¨÷ÎbùÙÒ€ø¨pÔVîµ?ÜÈ6:Êßɇ˜“}×Iâ5<ÔþYªP’É(û‡ž¯Ñ ŽaÙmÓ‡§O,ȳ‡êpðšñȘT€¼X|ƒáøäùô,ê>û¾ WµbÅ.¹¤yHuBx£õ‹Œrl[¹”öuÃ.ûÚïc´$â†e…"Šˆ,¾¯ÞË~¤¬älÊdÂm@•‹ 'âáy,uy^(0ù~¾÷Žä¼ˆ‡ 8,+SGy¯45éo¡ôÏYþQºªzò–yžG"‘¨ôáh4Š¡ôO÷å×XíŸÂiç­îåâ8ŽS4š`H}SçÐÓhF…ÁöÏóºÎãµê×H£7÷”a\Ĺ{„†ó(1ò éVA9/W‡<Š™„"ÌhâçÚ Ç5Òû—:½~Ε´CþÍ~Ê2P½Ñó;JÝ>* Eϧ؃¨ó=¿ü%\{í[;¾lÿ”\¹¶=pYòK£:CµÛ/À¬/cšgvɆ†ÚÛÛ+}XÍ s‚ÊPpö)íy!I £ãSlÞû«ó´íÛ‡Ù≋„%/îK£© 'Ž?Ω ašgËRQéF3N˜‚Š˜X7[ø¾Jê®Ü7/vݱ˜úï+!{±Ùƒn«Ð}´˜WH!â•"ûljRâE¡‰ã„‰ëñ$ñCÄPÛ›¦:7‚\³Ãp^’#¥¡!q¤NÛ—Gs±x^(Èh4…Ÿ<•}¬8 PᾚšÊùø©ÑhJfÒT:M¥ñÃ×v¹W9ޣŦB$“o,ùည£³KÁˆlc,3P¡‹ÈÕ÷Ü‘#T:Äî9s8zô(===TUUÑÓÓâ3H8@UU{öìáŒ3Π««‹ ÐÕÕÅáÅ‹©ªª*jìééáèÑ£TUU±ÿ~fÏžÍþýûÙ3w.‡æì)SØ¿?UUU=z”©S§ÒÓÓìÏž=,^¼˜®®.&-_Îk]],›7®®.æÍ›”“}nƒi‚ç±xñb^xá/^Ìž={‚c¨ªª¢»»›¥K—ò /0íÜs9úò˜٦««‹3Î8#hktÛžž^Z´ˆª;‚¶E·yùå—™7o^°_i£ošTíØÁfÏæ…^`ùòåÁëË/¿\t?¯¼á Læ™ ìªU«Ø²eKðyñâÅyç³§§ß49£³“yóæ±}ûv–/_NGGsb1꺺*Ý Æ$ÿù†ÿdë;DŸfìáû¥y§DËk4šÑÃ8e مǸ07A[ò§h4ã !¨°s'k~ýP‹ç©ç£XÌÅu‡‡·Q×-=¾¦Ìð-&0Hh®Är ýõ6É=bYù¡¸|_=ˆËìÆ†%®ˆ‡‹L†1( #LR/‰ç³Ùüc2ÍÐ{Ç÷COí¡¢‰òâ‚Ø:—6OçƒTË29P‡üÒhÆÝðRÏK'b4—a:Ü—FS!žE‰)q†ïâçxžçáû>žçaFðÞ4M²Ù,©TŠd2I"‘ NË}ŽÇ㸮ËÛM/7{Ç̽Çãd2™à5‘Hþ¯ÿ"‘Hànߎ9i Ä \× ¶“:|ßǶí`Ûh]òjÛvÐNÙÆ0 ¼íÛ±N; wûvìåËÉ<ð±X,د”“sPlG>ïÚ…9s&Lš„¹xq°?ß÷1/VçêÈŒÎN\×Ų,²ßþ6ñxœô=÷ǃ}Èù–÷æ©§â>û,–eáFöovÞ¾}“&áïÛûö©möíÃÜ·÷Ùg±mÿoĘ3V­R_èœ9E¿gÏó`î\ÌhÙÂ× zo3iìÝ sçb?Ž»kO>ü0ÔÕUºŒI\~9U¯t34M\7?ZGX–öRÑhFwÌÝûí;ü+–eaiC¢f21•m{9þºš'äy".Œœ!HBZ•Š”o“(žW<.vnâbYá¿„3Me“„÷®«ɃLZZÔ¿$³ÏfÃY"ˆ¤Rªžt:lGCC(ÀHè/ƒÂp0êU„ÇQe$˜ hzfÌ`ù /Ë‚eqùO£3øç‚ê³,.XžL&1M3/”¦F£ŽÌœ‰‚{¹òÓé4±XŒÆÆFR©étšT*–e}[ÆÊro–pœ2SP>ÇúIè"a _¥ŽÍ›7X‡x®öUW1¤í²9†þf9nSøZXNΓaÁþ¬“‰!¥„©èký¤L©×á¡<÷ÛÆ¶mž|òÉA×u²ptÍ.˜9³ÒÍÐh4EˆÅò+›ÕB5šQå”,èjgÞ¼‹‚¾çºn¿cDf¬2!oêQÍœ(‘¡¹2™ìˆ¸Iƒ‰P$aSŠÝœ£É磈øQ,1Z<¶Cñ‘0]…‡êy¡Ç‰x¢DÛ×Ô¶3Vç,ÚŽ¨÷‹x±ÄbjÐáyáù0MU^êÊdÔ1ˆP£ÑÌ|ÓQn×ëÁçúúzš››µ¡V£xGb鋱XLÏÒh*Ä´ƒy1 ”jÌu]\×Å÷}Ç¡©©)MDÈ(Åx¯ÑhJã´}ûÐSƒ4š±É`çíe³¥Ù,Üœ‘F<;EÀ÷}?ðZ”×t:M<Çqœ<¯LÛ¶ƒ‰Ùl6ß³3·„>Šn#“ŽãÛˆGi, &QȤ Á4ÍÀP-Þž2Á"™L’J¥Èf³yÛ†l#e _ ·‘¶õ·M&“Á²¬<Îb²…¯±X,( jÃ0úÜOss3 ƒÚ¦¥¥…úúú¢mó}ß÷9q⇮t7Ûtìàè”Ó€Pü4MsØ­4šÑeB*¯LžŠùô Såûþˆy¨ˆ¸Pju’ ½˜È*!¹Šõ.‰âûP_{ö¨›~&†ù’0[¦™ûÞ0òÑÁ‚x²ˆ8#Ç%‚Iô½Ô'û”噌ªÏqÔgiwÔ“¥’&šà>züÅâžÊ6Ñðd!¹]´í ²ÌìžÉ÷z6 _2±RYæwÏ'•Jé0BÍaÕ–çz‰›™LÏó´ñU£Ãd³ÙÀ cñx<ð˜Ðž MùXÑÑ¡M>Í8Æó¼ ¬ä¤I?Âu/Á÷ý@ ÏX,Ö˦$ÆóL&ƒã8$‰@8‘WñðoPg{ž‡çyض”‰z-†A"‘Æßb¤—:¤LtÓ4‰Ç㘦Ìðñ'êaiÛvPÞ4ÍÀûTöÝÆ²,LÓ &hHÙþ¶‘‰X2i²pñB•m¢ÇXè![ø*å¢Ï+¥lSÈhlÓÚÚJkkëÿb'‡V°‹c|úÓ=xxÄöÄ8zýQ²(CdM°â òXXèɸš±Ç„TŽÎœÌëwÜ™ywµÜç½›W/y•Œ‘!Áðó4ˆ÷F©Fqaúž!a·zo+Iê!Ì]"¢C´mQ‘¢©)ÿ}&£ÖK~)õ¤‰ÇÃ÷’¥°Íž—Ê,E &bÀ²eaÂút.Ë©¸âº®Z&u‰hã8j{ ß&íuunÔ>Ä“FÖò°ÑJr¿ÈyÉdÔ¹ïÛsÃÄãa›t<Õ‘cÖþYLßWÍ‹ÖwñÈrÿÔûù Ÿ¡‘FÚi¯t5š“×åÄ乇±ðºWÌ»S´Åðr «HŠo?(㺗Ê: èúˆî7ÚŽRë°°‚v «Ï}DÛ 9ÑïÜÄÄÀèµ½‰‰‡—wlÏ-{Ž¥íKýݜ숒J¥ãŠF£© >þ ®ïåÄÁÁÀ`Î6•cgÅŠü´ç§tuuqÝÂëxþùç9ûì³yþùçyéM/ñú«¯³zÒj¶lÙ¢E‹X´hÛ¶mcÖ¬YlÙ²…ë®»Ž¯ÿìëœ{í¹ô´õPµ²Šç|Ž¥ïXÊöíÛ™;w.‹Ú°hÑ"vìØÁÙgŸÍ–-[¸òÊ+yà¸îºëz½Êþ¢û•m}ôQ®»î:î¼óNn¾ùf¾õ­oqã7ò­o}‹U«V±cÇŽ ¼ìwÛ¶mAýk×® ö­#º-ÀŽ;Xµj=ö×]w]°_Ùöž{îáÆoäÑGeÕªUlÙ²…Ù³gç{Ö¬Y<öØcÜ|óÍÜsÏ=|âŸ`Ó¦M¬]»6o[iëìÙ³Y±bEpÌ;vì`Íš5ÜsÏ=AÑ×{Ÿ¾—³O?›£[ö:ÞŸöü´Ò?·q‡xr666ÒÒÒˆëÖ½—¯|å0GŽü°™7¯yóLR)åá)!Ò£ÄbjœlšÊˆ[¹ˆ!©Ü$\ñ^±›„Lõ}e0Í8¾Žcã8Û9[‰Lp5MÓ4;GŸûâRv¼ç|êÚê¸éðMØ l²di 8q 2d01É’¥‰A„ ÒhF‰ !¨tÏX¤×W“Lû¼5þ<¹ëÇ<~Íã\ÌÅ¢)ócQÝŒæ6)$:™?ïÛ•5*|DïU¦®‹–‘p]Q¢‚J1!©p›h›£0â…“Hä‹/Q\6oV7` ;&ÂG"÷ÒiõYÂmÞæŒ±¤±Q‰%›7‡Âl#"‰m+1FŽC6ÒfZÃzEd‘i®«DÏSç!†Ý»¯¤®îXy ã”­Kk8qâu~d|›6šXñò ¾õöoaçRì& Gtbt‹ÓîžÍhàûìß³„G½P×Ègêîä³O~–%7,ÁÇú¢ÌûBÖ‰È0ﳃÁî' x1á!F,Xîãccç MRŸ™ûë Ù¾X;dýQlŸ¥ û-¶ê41ƒõ yß}Bܢ݋èÞ×=ø/ç$ॗÞÔkb‡çy466ÒÜܬãLk4&K–4êc(÷¼íÛ·³téRöîÝËÞ½{èèè`úôé>|˜êêj:::¸ì²ËxôÑGY³f >ú(W]u?üpðù¢‹.bïo÷2cÑ öíÛGuu5< »víâ²Ë.ã™®g˜<2¿Þÿk.›r?ßÿs®|íJ{á1^^ò23¬ì8´ÃÞ9{UÛæk¸Ì]5—C‡ñÔ§8g@³©á"IDATï9Ì]5—3f°páBL[À.k=3z8tæ!~=ã×<³ðf3ÁVu¾îµöÒ3£‡gÎÀǶÝ:wkPfÅÇVб´ƒE\ÄÖ…[¹ü¶Ë˜»w.ÓçNg)KÙ»w/=ô0ßšÏÖ¹[™õÞYyû©O×ÓAç}ü¥«Ô¶‡bïÞ½L_8úëêÙzh++>¶‚¶EmÁþeÛ¥+–rèÐ!²½{÷âÍð˜kÎåÄŒ°:–vm,|½äôK˜;w.¼Uµwᡅ̘1€3vŸQé.0®Èf³d2ZZZhoW“ùÄëäcSÏóÏ>ûÉÜDÌUœ8NÖ Å…±H¤Ûî]&º2¡S¢…ØvX—aô¶ÉdØÊÈ2Ó ÃÂ÷U&ú^l!=DŽGÞt<ш$…ÛÙ¶Š°¥0o4:ŠJ…d%'o4º‹œ“bBO´-"òè cÿ xõ—?àE¦p)üg}ì¸úQŠ(Mƒ8qbĨ¥–$ɢį'Þëù ÷<¤Ñ –SNœ8q¢ÒëÖ­ã;w~™UÍ v´|ˆg›/ÀØcP?¯ž)h¹&f0»ÒÁ!F,Op‚Ï£M2©n2«œû‘ðeåÊq"bG<®öW®ýD½KŠå‘)ÄsFÍ"éí±“Ng¹é¦ÅÔÕÕ•§ã”ÖÖVîiŸÏ£ÿýVj7ß²oÆ0 öz{i¦ '0Æyx88A1z4 þ4šRX·n7n¬t3ÆëÖ­ãÏ>ö1>ôàbŽ~c6ÇçgrêS\û–iÌùÅî¸òŽJ7Q3Á‘°ëׯ¯tSÆï{ß'ùèG?‡eû88<°ó:Ķ9Û˜7o^ŸÛõåY%èøÔ'QO: Ïà/†EqY6¹c2÷vݫǶ´¶¶rÛý4ßÒL -ö'É[ ùH$A¸!Y¹$~¿,$?ƒF£Ç¶Å)v^jkkijjÒ}g!bˆ8…ÂMT܉Ǖ­&Šm+Q44¾”‘É*"ÜÈûè„àÁìÂý|å+]œuÖƒüó?ßRéÓ8æþ™|x/O»)vÍ7ÙÓØØ„„–± ƒÍ(O1™øµ‰7¾Ø”2dzM‹z‘FmÂ}M‚[°Lô•Ir²?=†ßlذºººÛN•…/v±åÈ)|Ø\ëº\÷âu\ýõ˜˜A'\\šiÆÅÅÃËS:£ï£¨X( ;o¦tr»×LÓè@ É…Rr›”“h˜¯r 9gäxÊ…Ü gH”ãx¢¡Ò ×­XÑ,._Æ1Óí`ÎÛÀ[ÌwN¦ñð‚>/’ÖSÂôEgÈÍÐà úpTléë7qTú£ôÙèìüÁÔQ,ô‘ž¡‹øÆ¥Lzâ «ß·™Ç—>Îÿ³>ÉÝúÏ|0þÁJ7M£9©™=û<;C#ibÄðw½é]üõÒ¿®È¤ÍÉdžìÐZJQöÌÝ“ã½ÏóH&“$‰@‘DÌw?š¡År jƒ°FS_Ûù5vîÜI¬9†oúN8ÐŒ¢ysûŠÌR,JJáúD$ò±z #µó„éÏ;Hñ„ñ}¨­ÝKw·NJß/í?§kÕ#Lùï8Ä)êu]8a¡Xß®·sbÛÑ»N¹zÏ 3bkÑE¼Q¥¬…E†PaëÏKUœ¾ìDÅÊÛØy“Ž¢Ð) ˜}Bû¶L¦) 3-“qôµ²t&„ 2÷@{·½‰w½k¾ïsÇwô9ȕΪcZXE;\ùAƉçý³daDBŠI'7µhùÂxãÑÏ/p36kÙ侀ø°sЍ#?òè,³(…³Ïä"Ña¯`‰¿ž[ÏÐÈÿåÍN‹*±…m¬a¹Ë½—˜»˜§yšzþ²äíJ½Ðô˜‹èvÿ…½L§Õú"Y+y…çÕÂêÓ€~³œ?°–âypØ|‡®!““‘×f½DûïV²ÒK„.Ei.K…‚ã@ý´ÁÄµŽ 6Q›"š_® ÑñH½áö7 O$çA®=Ñþ ×¹ÉÊþ¢YÍ+Qi,,^zÓK•nƘÅÿì?e?ϽãAî±ë¹„¥X–¥6M…92óiÒlf3™t†{c÷5°j4šÑgEÇŠ^edŒ+3m%±´ÌºÕ÷UftppH’dɯ—pé™—â›~` ¢g›{LåŒqú¸D›fÄ6eG‹çÂÿæ„1_ï[½ºïéÙý±ùMóñÞØÎ*¿ÏóH§Ó½& µoöÉDìýMt-e¬ˆ. %Ù§œÀN\JˆP'È7mw_ˆí¶XnK(žƒS"6Eó7Ð@ŒØˆ÷ñB{Z¹®»>~g'›û+ÌûyäƒG¨kÙþ9î•W—.e÷i_äò7Ÿ‹mC2éŒxléb«¯ÙõCåLûCøþZºéf -e‹?Ÿ6RÎ\¾ÿ>Àÿ”e·Y/àû‹©²~C -%m'šRgó{¦‡eý/²«U|ÛJn_”èà ˜ý)ópß À6ó^^cožÇRG¬ƒº.}ã,Ƈ>ÿy¾Q•æbs¾?º9 ŒAy† V°ÑŒmD,zá•*Ý”1‹;öýþ_ò6k66™L&3¢Ñh*Ç´ƒÓ‚‡Ï󴘢ьaÄ ”H$hnnÖýU£© Y²\ù³+9·ã\âWœ­ædÆÇ§–Z€<ìD'’\RXXÁdå±^á5;;:yqß‹•nú˜¦gúKœ²éÜcNÅ0Œ^á¾Æ:Ñ ú¥–lý£A=ùIŽ Œ’'>E’$I“&÷»VmøêÈ{_{Aåð©§2gûnÚ6|nÃ0Æå, E,Âuaªq ¬É|–M¢`Þp«ê—CÂ0 ÊÜQò6ƒÍabÒ`Öòƒl5ˆ-/y»b©þŒéÛÍ{Àƒ%ñ‡YhœÊÞ:,Bßt.|ê3~ƒa¼ƒd2=în˜šñ‹Ìæøú+_¯tSÆ,{¯òè~[œ/Ä/Ôý3õ×h4EÂi4š±…ï«\ŽßøÆ>|˜ÿ÷æ¼xüò^¹~*éµ ESX&º]aòæbeÚe©ÏýíDzÂÐÉ’4Û0T(œÚZâ&•Rï! ·‡y L3Ì› ÇÜÔ¤’}K»$‚ç…¡§:IJÍæï§ç-‘Gòž–ûûéëxÎ: MXXð´ö Id’âÉæÑSh›ŠF¹é‹Ö­¼zèÕJ7}LóäÅS?Þ@¢Òé4¦ikñs´‘ÜÅò».§ z4¨”4î•kéá?ÏäZ{¾ïã8θ|øìvWàz>ûíïWVº9â-3•îÄ“Ì3¶”u_^ÖbµQÞœ0‹XÄtðëdëâGÑé0Jçþ+Ï¢jËl@k5ÍØá‰ßþ™þJåqçºd³Ù÷ðÔh4CÇ÷}=Û]£c¼øâjk¡¾~/W^9“U«ÎDzòãñ·ô᜵+ÓR‚SÿhíçĉâïûÚÏæÍ½×G£¸ôe/OçÍ.áp4ŽgݺÛq²b{6/£ ´#Œ„ÒÑh†…sNÝBÕÔ+0M•?Es+CT,”4šÁ3©Ò .§îoãÀû¿Â§*Jsss¥›4$®°{8ÍÜǹæ´J7eØ̶žçÇÎdŽg>RÖ}YV~±r°ÆšÅEñŸãû°ÊÞSÞM0¶/ÙÍÁ­ç“ÍfûL¼©Ñh*Ãþ)¿æ¬·þ@ÏÒhÆZàÔhÆ&UU‡hn†Í›m®¿þï}ï¬J7I£ÑDÐZflâì…ž—Žðú鸮K:Ö“n+H4_Êx÷P©ã^PÙvÆqöÝÒŒç©Ðã5þû\sGÍ­ìqVUº)#B=<ïÎfºñZY÷“J•×; Æ˜E¶Ñf^쇣Óp¢ðÊ.bqõa|ß×7KfŒ1éØ+Ð~.€Ðj4c ÏótŸÔhÆ §¶ßwhiiÑa…4š1†žÄ§ÑŒaΆ×ZßÀóÏÏÆ²,R©ñ›³c¼cc¹F:ýÉĸT~}Ù~޾¸ ÓôI$ãv`;Ç};dOg! +Ý”a*SyGê¼9ñh¥›2l$Nf—;1¾›ÑdÎO—°rÁ™€Že«ÑŒ5æmý §ìPÑMÓÔ}T£CŒ×œ€ÍÉ@:Æ÷ýJ7C£Ñ Cej4c—ÿ׿1­s1ðKill·“á'>¾ž8>Dƽ 2éW“˜¾{:™L†l6[éæ ™YÌâuë—\ÿy¥›2"\Úò)6&Ïašsm¥›2"Š}•£ÎšJ7cÜqìØE\rÉëãºoj4•ã?ºŽ Î=B2™ÔŸÍbÿþýú!S££ôôôÐÔÔ¤ï›ÍDÏx×hÆ./}„ê;ˆÅ ko² ba‘%K’¤öPc.)}gg'ÔÔÔPSS3`ùƒ/.`þìÉØ¶=®¶«åË\@µ±Êœd4xºá6ªü3™ewWº)#Bs;ÝæäJ7£â ¶¾ÿý/rÎ9¶­·M¹lÿÜù÷rë?OgÆ KÏ„×hÊÈ`ûæìÙ³µQH£%Û?Ÿxâ ¦M›F¢ÜI5Í û§F£†Ò7ŸªÞB÷7?†ó{™LfÜæ¿ž4Ѩõ•G38Æ”‡Ê¦M›¸á†¸ûá†Ø´iÓ€ÛœqÆÜqÇLÇu¬é·[sØ¿g*éļJ7eDXdöÐéžQéfŒ1Ûà#±9•nFEJÿ¬ª:Ä÷¿ÿJ7]£™ð ¥ôôܯsi4ed¨}S£Ñ”Ÿ¡ôÏ·¿ýíZLÑhF}ÿÔhÆ&Cí›/?rKÏÝŽaú>:°sqâ:)ýS‚ʆ ¸ë®»Ø¸q#÷Þ{/·ß~;ýn3{ö+¼éM/ÑÒÒR鿥­­­ÒMè—îîîÏñP¸,þkŽsœzkøÑX8‡ñ¸ú?™Jÿ|õÕW‰ÅbcvöûXømõGgg'ÝÝc×Ë«\×ÍàJÿüøÇŸÁ0 b±X¥›ß‹ñðÛÒ×M) ¥oN&Òop¬÷÷R™HßÉHp2÷Oý›{L”ïd¤8Yûçx—ÊDùMO¤ïd$JßœrðtŽ=²„7/í$N9ûÐX¿—Œ‡ßàXïïÿ¿½ûqãîó8þ5÷pI%q$$•ðñ<Ç6£æ‚p1­\ìr`ˆ9¢V*Öe„A\'¶zŽU³íªpŠHW¸Œ¶X—ž?n I äìR8MBð.s…Ñd׫•F3ó›ßw¤÷ ÏîøÑ~gôýÌo~óÓŸ_~ùE~ûí·\SÍ‚ŠçyR­VÅu]qGÇÏóV”÷Þ{Oí«kƒí–šN§F^íñýwùÏÿþù×úçÌ¥ýnƒ´ùüòË/U¼öÞÇ2Nm—q%Sç¬'m>úé'ùþûïUŽŸeè-ÎX%m67Å&õ ö¼'µIÏIVÛžOzZŸMyNò°Íù,Ã5pR›ÒÓ›ôœd•6›ÿïLþqú7iµþEåÇÚjKÊЃÚóþõ×_Ë“'Or}L5ß¡âûþ¥ÏÞ«V«+WážùÄö.,¤¹·DD~þùgyüø± ‡CÛ¥,dúü‘ů¿þ*OŸ>•k×®Ù.Ÿ4ù<;;“Ï>ûL®_¿.ß|óí]¸DsoÍqþHïÙ³gòìÙ3yçwl—bTÚkÛ¯¾úJnܸ!ŽãØÞ…L4÷ິç=©$Ï ×¶WçóùóçòÑGÉÇ,ׯ_·½ ™lSO—Ūçd~mûÇØ.Õ¸´×¶7nÜ7ß|SÞ~ûmÛ»Z®“Ú”óL’ç„kÛå×¶ÿûÍWòÚÿ&ÿû_U~’ö±¤ çÍyúô©<þ\ööör}\5 *³ÙìÒï’í‹/¾°]:°ñÒäóîÝ»r÷î]Û¥/M>>|h»l`ãqm è•&Ÿ·nÝ’[·nÙ.Øx\Û:¥½¶Õ¼¤¥æ#¿ªÕê¥ßiÿŒ8`[O@/ò èD6½È' ùt"›ÀŸÔ,¨8Žs)ˆ³ÙLåÛÁ€mC>½È' Ùô"Ÿ€^äЉlR³ âº®Ìf³øËŒ|ß— rÿŒ3ë#Ÿ€^äЉlz‘O@/ò èD6?©ù‘^¯'ÝnWêõºL§SéõzR©Tl—@È' ùt"›€^äЋ|:‘Mà¥kQE¶‹8/ ‚@jµo”!Ÿ€^äЉlz‘O@/ò èD6… *Ú¨ù­XPX€þáƒ>øÀveø¾ÓUÛEDªÕêÚÛóäû¾¼þúëòÚk¯©ª/ Cyüø±„a(o½õÖZ5yüP>Yòi;›Ij°O õ¡¼–åSSo¥É§ílj;†Ø¦rk«Mä»è}15NsŽ(“sRMùÌš¿"÷Åä—|–‹É9©^01wÕ4vf­•|^¦á˜„a(?þø£Ú±CûÜØ÷}ùî»ïÔß·-üÞZ„T£F£µÛí¨ÙlFï¾ûn4›Íâí£Ñ(ÞÞh4¢Ñhtáÿ¿j{žÎÎ΢F£=zôHU}ÓéôÂ1ì÷û‰k(òø¡|²äÓv6“Ô`;ŸêCy-˧¦ÞJ“OÛÙÔv ±9LåÖV?šÈwÑûbjœæQ.&礚ò™5Eî‹É9.ù,“sR½`bîªiì,ãs¢–crxx®]_õkŸ÷ûý¨Ùlª¿okãÞ *)œE;;;Ñt:×l6£ãããøçóOät:vvv¢³³³ÄÛó4oŒó¥¡¾óÇl6›EÍf3šL&‰j(òø¡\²æÓv6“Ô`;ŸêC9­Ê§¦ÞJ“OÛÙÔv ±LæÖV?šÈwÑûbjœæQ¦ç¤šò™5Eî‹É9.ù,ÓsR½`bîªiì,ãs¢íc2¢÷ß?ÚÙÙY¸ bû9Õ>7ž/@ÎxÕ«%ß6î­ñ*)A ®ëŠã8ñïvwwe6›‰ˆˆçyR­VÅu]qGÇÏómÏÓ`0Çq¤^¯Ç¿ÓPŸçy2›Íd_DD*•ŠœžžÊîîîÊŠ<~(Ÿ,ù´ÍUõ%Ùž‡eùÔPÊkY>5õVš|ÚÎf’cD>‘†©ÜÚêGù.z_LÓœ#ÊÅäœTS>³æ¯È}19Ç%ŸåbrNj£LÌ]5e|N´ÓpLêõº´Z­ 9LZ_õkŸA ­VK*•ŠˆHüqdÜ[{‰•\וû÷ïÇ?‡a('''qsù¾ésïªÕªAh{^|ß—““¹sçÎ¥ßÛ®/©×ë2¥ÓéH·Û½Ð´Ëj(êø¡œ²äÓv6WÕ—d{–åSC}(¯eùÔÒ[iói;›IŽùD¦rk£Må»è}15NsŽ(“sRMùÌš¿"÷Åä—|–‹É9iѽ`jîªiìÌZ+ù¼LÃ1qG\×]ø½žSísãÝÝ]éõz†¡xž/\Ì 4äÛæ½5T2:99‘Û·o‹ëºÒjµDäÏÕºóÎ?I«¶ç! Cév»rtt¯&&ýûEÔA¼j¹¿¿/µZM:NܸËj(¢>l†uói;›Ij°O õa3¼šO ½•%Ÿ¶³™¤ò‰¬òÌmÑýh2ßEï‹©qšsDyå='ՔϬù+r_LÎqÉgyå='-²LÎ]5Yk%Ÿ—i?&ÚžSsã¹ d8ÊÉÉI¼˜²ªís÷¦æ¤E÷‚©¹«¦±3k­äó2íÇDËsªyn<e8Æ?W*• WC¾­Þ[KôÕõ¸`4EÍf3zôèÑ…ÿÎÎÎâÓh4¢GEQEÓé4j4Ñl6K¼=oív;þ{ê›ÍfQ£Ñˆ¦Óiüs³ÙŒF£Q¢Š>~(¬ù´Í$5ØÎ§íúP^«ò©­·Öͧílj<†(?“¹µÙyç»È}19NsŽ(ÓsRMùÌš¿¢öÅô—|–‡é9©­^È{îªiì,ës¢™–cÒn·£ÃÃõë3]¿ö¹ñ¼¾ùcj¿o[ô½5TR8<<Œvvv.ýw> £Ñ(j4Q»ÝŽÆ…†K²=o¯6–†úF£Q´³³µÛí¨ÙlFý~?q E?”GÖ|ÚÎf’lçSC}(§UùÔÖ[ëæÓv65C”ŸÉÜÚìǼó]ô¾˜§9G”‡é9©¦|fÍ_‘ûbrŽK>ËÃôœÔV/ä=wÕ4v–õ9ÑLË1¹jAÅösZ†¹ñ<+ó¿¡ù¾mÑ÷Ö®EQåú~Ä‚ ¤V«-|ËЪíÛPßüoT«Uqg­l?”›öÞÒžO õa3•¡·lŸ?²ŒZŽ!6K–žÓÖYj-z_LÓÚžd³)½5Eî‹É9®¦çÙmJ/”é‹¥ý˜hN5Ôçû~üQXÚó]ä1dA`¾”`TV`A`TV`Ae‹ø¾/žçI†Vë‚@ƒíÃX†¡xž'žçÙ.åò ÍŠêÏyF”Sšq¶Èñs ¶ÝºóRò‰²*ÛÜJË=£ó4Ï2+ÛùIT¶@†Òét¤Ýn˽{÷¤ÙlŠïûÖê ‚@†Ã¡íÃX1¥Ùlʽ{÷¤ÛíÊÍ›7­æñUäšÕŸÇÇÇÒétlï.€Ò޳EŽœc°­ÒÎKÉ'ʪ,s+m÷Œæ´Ï2+ËùI+T¶À|ÅñáÇrzz*{{{Òívm—l¥Á` wîÜ‘ÓÓSùüóÏÅq^(ây–@‰ig9Ç`›iŸ—’Ol+­ÙÔ>¦Ø^,¨X2 $ C Òétd<‹ˆÈp8”N§oÏ* CÇÒëõ¤R©ˆˆÈþþ¾ìîîÆÿÆó¼…ƒÒ¼†¼kZTã`0à•PÃdï‡a(ŽãÄ?ïííÅo_¾*‹çk2}ÎXT/ù„Vy÷g†Òív¥×ë]Ú¦%ŸEÍÀ"ëöºkÌeã캓÷ø·ìd±*Sư$óÒu‹|¢ŒõR{6Ë0¦y+úþLs@îý¬‡K†Ã¡t»]©V«â8ŽÜ»wOnß¾-Aˆã82¥ßïgþ;ÓéTDDǹð¹“ç/¯z%Îp8”~¿/³ÙL\×Ïór•B†Òn·/ ”€M&{¿V«Å9 ÃP&“I|±ºìUqE3Î#ŸÐÌDöû}iµZ OK>‹›«¬Ûë6®1—³I™ÿ–c€,VeJÖd^šùDY]Õ»ËÆÊ2dSû˜˜PôýÓs@îý¬ï/¶ Øf»»»ÒjµDDâÀƒƒy9pœœœdþóËÛ·oÇ¿ó}_â¿Ýëõ®,kµZ¼­V« l½^÷ÐÂTïI»ÝŽ/škµš¡Y’þ\§÷mÝ,I›O`[Øgó>¿ÌlóRò‰²*rn¥ñžQšºlÌ"˜šrï§X|)ý†sGjµšÇ¿;>>–J¥‡Éó< Öj<88ápæ °©öööÄ÷ý Ÿ¥9¥R©H½^·žÅEÈ'4Ë«?]×?¿º×ëÅ+ÐëõÔŒ•@›U㬈Èx<¾r²y^žã_’s `’†1lÕ¼4i6EÈ'ÊkQïÚÎg’{Fëä3/IÆtùáÞÏzx‡JÉœÿ¢¤æ_ä5ˆf³™|øá‡ñvÏód8¦^…LSÓy®ëJ«Õ’~¿ÏŒ¡TÖí}Çqäàà@ºÝ®8Ž#aÊl6“^¯'•J%só¨ñUäš-ëϬ½ÿ*ù´+úsÕ8+"ñõðª/Ú-òü˜¦e [6/MšMò‰òZÔ»yçÓÄ=£uò™W]IÆt ŒLSÜû)Öµ(Š"ÛEÀ¼0 ã/«×ë— Á`À…'Pey$‹€^äXŸÜ¬ºîít:|¡-¶Ž–1lY>É&¶•†|j;WÕ6ð•-qþ횯ò<ÏÈgdXìª<’E@/ò ¬ÏVn–]÷‡ÃL¯°ÊHÓvU>É&¶•–|j;—Õ¶ð€øRz€XPX€XPX€þÓÀgºœ}‡%tEXtdate:create2020-03-05T16:38:18-06:00n;×+%tEXtdate:modify2020-03-05T16:38:18-06:00fo—-tEXticc:copyrightCopyright Artifex Software 2011ºÅ´1tEXticc:descriptionArtifex Software sRGB ICC Profile †2tEXticc:manufacturerArtifex Software sRGB ICC Profile\~=Ÿ+tEXticc:modelArtifex Software sRGB ICC Profile1(‚¡!tEXtpdf:HiResBoundingBox1584x864+0+0û8²ùtEXtpdf:VersionPDF-1.7 7ji»IEND®B`‚blis-0.9.0/docs/graphs/sup/dgemm_ccc_zen_nt32.pdf000066400000000000000000005101021422157504600216170ustar00rootroot00000000000000%PDF-1.7 %Çì¢ 5 0 obj <> stream xœÜ½M¯.;’7¯_ñ«µ•L&¿¦l‚Ûªž ‚­v’ÚnÉÿ}3b­ÁÜçÜ[÷–]]uÞØLæ™ä+ü¯Ÿë«|.û?þïßÿÓþÕ¿ŸüþP>öÿíÿðçRËõùó½®O™Ï¸>ë®×ç¿ýÃþÏ_ûS¹ÖýU×§ÏëúšýóO¸Û¼¿V Ë Ë,×µþÚA,¢qDûü¿Ø×þ¬uÝŸÿñoÿõOêLKi_Ã.ä/ȼfÛOÆK´6¿Ê«ž°õЦzô3빯»~­×=†%ë‘õÄÏ£žg®¯ñª',G=´©ýÌzìYÍu÷ÏÿØ/ÿ¿îGá ƒÿó÷ÿôùŸþn7‘ù)÷çïöÃ÷Ÿ÷)í™öòµŸÝçïþéÿîןþ|g?ÈçÍþùUkí°Æ?ËìûGùcù¥gÙ6ÚWgÙ_¬÷öïçßÿÝ¿ùÃÿüwø?~Ö Êµ‹Íñ/?4Qk}~]Ï«”ª¥¬¯{fU2œUe!Uu–Šªž:¾ÆQ~¿*R‘¨'ËD5£õ¯RŽzhxU…¢¦£T¶üñ|µšUÉpV•…TÕYê·¶Õ¿î:ʧï·{ígœm'^áõ©åk>÷>î?î?¶×ÿ<ðׂ?~oIß+)ó‡rí×Nvÿj»úwŸÒí6þýþÿÿø‡ûóo~Ó—ï‡ηïÜ_~å³E~ÖZ¿Õò+¯ ~ùK°ðg{³â-ŒëÙ/²â-üë?Ý××~ãÿËŸž¯Ugýãÿú§{wÂ5Æÿ·øãÿ¾ûæó5w_þã_òŸÿj?­ýFk™üû?ý¹^_õªü¿ãðÿö§{}­q•?þÃ.x•¯Ý»ã±ârÏhßе›ÀÜk•Ëÿùêþ1ÿùjýÿô§?_þ³­×¿ÿC–û¿¬œÿ×aüû¿ÿûã×ydÿvä?çïÿüÏ?k8h2—5™ÏâcÀZ»ùáµîO){àíma]­ý”²òh°Ün¸ïýÿý Ä~º%vmfÙß‹ênxv_ífÙ «¸¥Ý_We L[Vá¶ìöÑÜÒû~°L”Ù}¾³x}f™û¤÷Ûâ½mi¼àÝíG…¡{‘{.^¤ï¯¼[Jùê^fß?-k/f™VÖ,wÿjþ´ŸÍ]5Àîçˆ2Ï~*ö,ÊõÕ,óËGÊÝìüÎ÷ì«z‘ûËŸÖÝ÷íÙïºÛ¸F±'°-»}ãbÆü²ïÖ,ûVpÐÜR{Ze|=8õª_ÝËL>ÑŠ—Ø­¥ÖËüjö´vê~®ºGðeOt¿ÕŽ£öà±Ga¿Íº{Ô´+Ü EêÜ- ÔòìAÙK Þvmû-ÚÃÚc¢–¾ÏiO¢î7«Ù_òbeê~°Ø° n|¾.{»E=~ãuí' ƒmÛ0ðmÚ¾y‘g¿èǞģ{zö³žVñSÙþžýª—Ùõ Ì¾öáe&¯ï©ûö¬Lã›z¬B{Xûæ ,mÏaìî—ú š¶=ŠÖöÇÉ-ݾM(ƒÛ|Æm/­ÏýH-˺ʶ<|Ïø*oË…š×ƒÞºç1—×ÜvçñÞÚ[vÛ-Ñ{ë¸ØŽÛn vû”èœí~Ð]íYû»jûØmîk@Ãiu¡»n˃Zžî:¾àÖt×=¿ë~ÅmÏȼ»ÎÉgÑúBwÝï ]ºŽîºûäÂQ»ÆÛËŒ/ÜÂ*è®ûãtã6÷¿¬»îyö×åí­[Ç­°àä}÷ë®Ëþ‚2··‡¾ÊÅ~ÕïéÝuí‡ä§êµ{oµ"Õìb%¢/öV¼·®]ÿ*°L뮫,~ÜúþLYw]¸Å>ª÷Õ=¯eËßÐûª[,Óûêº9A+}?ë««v¶Ç±¿zÖW×n…h$c_¦õÕµ[úz`™vÛRù!»KZ_]»7Ô³?RÖY—Ý ,Ïå½ÕÊÌ–é½u¡Ö¼«®}«7f{(æWÌë©Ë¾â–á=uÍý?“1†õÔeÑŸ°}«¬§®1q1s n/²?:–á=uíi îiîO”õÔesTÖ­­§.Ü¢uFë¦k56qëh»3ŽËÞʌǻéÚ-M|Ṅ¯0çôAuO74@ZÓ¾­Ìþ 5¿àuù º-þy3K±Qu\·>ðÖ¾º™ü ¯ÛFÕ]dòòªy~zÁz|TÝ–ÆÏåz|TÝé±›5KóQuϾôE°—¸ɶì®fø¨º-¿…öôo/3ùøÖôau\ûCÀK^>¬î2¯á¶§Ò+ÎÕXöàievCòOËžù°ºË,ô\!è.Ó¾pPõQu\¯f[ìÕoù÷ˆî£ê0*ð®|_͆Õqí†äᾺ«»H·O…[¼­º¥Ã2|XÝGu<œûš>¬î2û[†Ë[þª‡ýïM‹«nñF{¥.{\ø‹YðIÙ–ŽW~ïiˆ5úmh^Ûâãêîç…·µÇQëªÛ2­ ™å±é³±]Átï¾]ý¶\¼žÒ|`Ý–ÝbüÞ÷Wkw×mhøNÜû³`—1|zç{Nö›]~°r·%G¶=#òquØeú—ùÞ¯Êz«UüÔwñquéÛâãê¶Üø`Þ÷í㪗ñ9Û}WXÝâ-ù¾X‡ÝîðÏàØCƺ]‹«»Hã]ÞÝÇU/s¡L÷¯ô¶4{¯fH½¿h<Õôquø7±|\Ýen¾«{ù¸º-„λÚLqö¸Šû¬ÅÇÕmQË®·«Û°øpêíãêþj?æ1Kõquì~jPk–ÇÇÕmÙ–æãê>÷²náWwNŒïÚ}\öŠxÔðqu[n]ñþÈ/31£ØX½Ì…+\>°z<¯Ç(mâzð²žâë°Yô°øÀêôÏçö‘u5¬[šÅæÊf(|}Ïã#«¹PG¸¼‡§ùÈêçF£|º®ûL_ÅÝ,|p»ó°<Ã×aszÞÃôÁÕ-hÏòÁuìf…iùÝ.\w5Êvùàº-ü˜Þ­øàº-Ÿö»Ý>¸úÙñF[õÁuì‰å¶Lï±ûáò›Ò_½f8 J¯¦ârl¶l×wóY¸Û£á˜Šs;zXß)§“Ók™p²ü;£Ù_ùÈð ‚oä“q É0A€t‚`E‘A > ‚E¸ XàJ<@°pŽ˜ Èw|€ ¿/¼ñ-?@ã ÁŠà ÁÊa-I°’+¯'Ið%rôIܰ"9p ÄIq a)¸ ¸ ˜nšÏósrànþ©ƒ¯ÎÉ{p u¿ÉàÀ€Ûà@›m¡Œ8ðÒ¼18Ð, -qàÃopŸ@0-"Ár[‚mö 6 îG™a`P²Hp* ZO#øc®$¸›ª÷ˆ$Á" Ü÷ëj’ uóö9IÐ,@/‘`] îÑ 9P° q¨Pp7 <Ó@Á ò@Á"ø ¼]‡Ü8ÃS‹wÿT xîωöyò»ÚKÅAÂ@Þ†Ä@û ÄÀ›Í/(Ð@h& Ül’ùH6[ÅQ¢@<ï@À›““DÀ=¯à™Å€6!z1 YІŀfy!àܳE€£Ð\À !àÔG3Ѐ30à´?øÀ€s÷r|¢È€v º˜p/‹0ЪÁôXhlp$:¬€6IÓúÕç€Àùxcš¯Gˆw¢p¢…hGHE€Væ¡8¹fAßšoŽhN”7š_aR yU0&ˆçžï£k‹­ ž¯(pî'f% œÖËP†heœÂ@»›`8Âas/‰s7\4a 9lÀÇ"A;jA‚^·%œMþ7’ \A' nËÒQ‹ÃªYü\$Á>m:zà6¢D‚Û¢q $èxH‚n÷qXÝ_¢!GUk©(Ò8ªn ªíTûâÓ"z-x{äÀ>mh:9ÐÂÈFt'Ôz]Tw§xq [€1ä@÷T“݈"vúnu% [nœ¼aX¬ÅnxpLç°ŠOSrà¶Œ/Ðää¨j>pë⨺‹Ðî⨺QÊ' ÂÀm XÃhuZnŽªæª rTü„îlÃôž¸-•lb rŸ¤@÷Ùñ:ÆÔ}áë„@xì Lž(°[[Æi‡ÔmÀ<”è `aáºGhrXáºö¯¬ p[n23!p[*NEܽ(B WÓ|#êâ·YèER!Ôýz Øtd@·€³É€ni'ºÓÑvd@]`@·T –3 »%Ë'Ð . —Ÿ@÷R¢Õ·eÚ$nË /a$ý(ðÐËtÔ3éY•Tè8%€îE¿$z=ã@÷)ß°Ür­>ðya8Ð+">ð¬ÞA{MžU:¦Än!4:W‹è˜ü·ËÈ‹Bþó£º?.òß¶Àµ/üsÃ<ño[¸Û…ÛRéÿ þ™ë—^'âß¾}'ˆn!Ê=t¯ÞîÕ[=ü‡"@ÄNÿê~°'ÿù7œ‰*­? ;Èøïqλý¿Ï“ü\Ò|kÍÈúd@sR¾µÀÝ›¯—Xî$ðp$Úy‹×NÜ8}ƒ·JP0 M×qn1à¶.Å€Û2PF h܃Ð$å·¸_4°Kh§z‹˜,žh>èzbÀ˜/‰‚À}¿N÷x5„@{ÿo4W;-®ö—®ãÜ¢À]Ýx«ûû]"(Ðæ2´p¼Úõ¬7Ú8 ¦îË‚ï:(pwƒ•öE: ܃¦ÃAC#(Ðf/=Ч™'Ú,tIšv:š;?{ cr.hCîçdÀ©yk0`î73ß hCΛ÷¨ŒŠ{X2 y–ßR`’ %–I2)°PMH)ðV°DH·:sH·ºnH“ã­(¤@s<~\\“©^ô¦&îëD%¤Àuó¸[+@hï 7 Üø­ÚWdB“h®Ô·h2“xs¶”bà¾ÙB.¤¸-$3‰·05ÄÀ*/Uè7§{A«p›z`Q3×á5ˆ}f¾$ZÿÁ úô,F 4UüÔ;«K 4Áu¾(píÆå‚CPà²Î©ºp =[¸,`õ— ¹Tÿ0°®ýêÑ/Ŧ*£±‹íœðd‰W¥Ë.8Ðß7r 5R9ÐnsIq «ý/´F¹(úÈê­EÈ.Ã\†v”ÿ0²®ýy}Áe؇z ‚&-?/4]2ŠHpÙ§÷@\N° A{þlH4íþ9AWü׋­U– Z{‡"´'H±$蟂SDË=Xp\…@!^'=R¯kbh]KOG0hp©A{Ó˜K¼lx¢F8B¿‡ì$\ûà) -²«hÐÛ+- ÁÕB¦# .›s¾hЦ̈́?â uRàà-•Z’àeÑUŸ¤Á}h/Eðºæ!EÐT~²A+=\4¸:¡=ppɾ(#þÛý|ü·-TüÄUaÄÁû‘PoÿíOãó}.Y€»ÁàÆ ç€Û2Þþ†Àˆ ´O5Ê÷AÖ€O’÷1‹HH|Ñ'„À]ÐheP±Ð&bo4gÇçÀgð;hŸXć ·¥R$¶BGFà~üÄ7`#×6ùgI‰€¦(¡ )p·^ÔXØ*SÁÇASΣ ÀÉx±¤À)/¤ÀÝÀ©BJ ¤-p—³-äÀIx5p*Ê ÔÀ}Ð;ÔµF^¡.€çC œ“ñ‰¡N¢x)b•8›sp`¡£J¸™o\¨)œK´&5pIú5pêh¡.©ž¡nË$R \ K5p=Rú¤.>Ò÷ûx^hlƒ´À%Å8´@›£i»ñâ‰&^ü.…¸éJ <Šˆ7`¬S ´"ŒÂ”¸BcF0Oˆ6‰á‰/EâÚš2)0ˈ#Ä&(pßË[ ”K'ÅÀÉdŠ» ±PxiÊ–Ø!N¨¹j@`Èx‚ÀK— p0k,š4Zx –"AShs\ °(1 ÐIç679£Bv!qÞ\h>lXÜY©6‹C œ 9ð¢’G9p2ëoÆè…X6r CsSlTÛB ì„áP§¦²€{`Á8Ð>'ÿ=ÒÖ‚ÿì›üRmö OAðßÓY*þ{é”ü÷pLòß~f÷ÉîÝ ¤)9PãGÊ­ Ô(î®Å0äÀÆYb`CäzòßþÊŒ7ÿu†f$ÿmK} ‚?oAPñøÿ! ñO‰½QÏ ü닉þ‚4CÜ“¼†‡ä,ÉF¬÷êŽ82$š§Éó ôÀ‰OIÒßnާý™^ KÐßPÑß’*ôgS \°èo‰þ, öM&#ƒE‹ŽçÔ·…)=ÐúÉ+Ô-5ƒþlIÐNôw]:Šôgj4D©Z\:q0Òæax{¬Ú¬3ãA]¼~¢>ÇB_Ä„©kª Áˆ e\þ*¤ˆ˜Ð‡ÓÂŒ mÄ¢Œ mRö"&TÁ5JÇÎJ‡Õʈç#&TÓ˜Œ ZÃ1¡Sñž!v-âÞ±^PDh«N!Ó‰-ÆøM„wk’oÎ6ó¡ù¦{B{ÔÀJa¸þ·åzë{<ßQ¡Ût T@oòàõ]¼n<8åN9PÈsÊÏ[´Ù.G<ØÆ×;&´1(pðÑÛ |‚N‰ƒ{Œhßxpñ¾“Qƒì0˜ÁàÚ0(ñ2a°|ƒAžÆkm /C=„A›çà9 .®Hœ•€ÁÐõí;ý9Yоoì"H±`“%XІ4! ¶ÂË;Y°ýÈ‚àÅ`Á'ÈO,ª"Yоܼš¡Kkâƒ6`¸)apxµ0°pF’ ÍÍßQ¡¶žúZˆ·0ïÎð•õVm8yE…v­  ^,ؾ¯ Ì',h«XpX0¡,è~ÐWXè°y2u;)‚tøŠÅ@/Éõ–d(90â“C¼´Ä,Hи…!Ipé' öï$8µœõ Áûºÿü î^¬슡ŒÀG’ฆÄ}’à~7‰<A«‹µ<ð–Ö(E°…Ž(E°j¹w(‚6e#øQ´•Û¯¸P#ª†Á‚$“õ&‚gÿ]*l—$E± Í-I‡Z«@*XðæZý„ÁÂñ#ap7D®  îæ†Õ±Aƒ×M™6Vîï c6¥ÚØüZxÙÐ ¥OZà£qieõƒ‹^ß„Á*€ î§…Æ4ØècK|¤À ʳž4+ƒCåŽ , K,Z’4xi³´@œúZX,0N4h=î­6µ‚ Á[®¥ A… .NFB Üÿ3ÞÑ¡jÅ_2óÚžÖ_ï?{ê™IH–Ȉö˱ˆ Ä™‰æ?ý•\j?Ö–Ì9ö:A9rŽU›:W=a9ê¡MõègÖóØRàöº×°d=²±žøyÔcSÍúª',G=´©ýü—Î¥V-tØžéß–KíùY.µÒ¾ýó{.µmm¿T©‹îH]ô³fÉéÌpõ½­ZCôhú³ªÊ4iªêL“¦ª²«: EUJ”5e¢´¨HeTO‰j"MZÔs¤I‹Š¢”j: eËWš4Uu¦I‹î¥XÕß’K­š¿Ü†ÎÿäRû-_À>8ß¾wù•ÏVùYcýVËïNIV=±Ìø™’l÷×óÈN³ôµçõó3™—ìþëyÉö3³y}¦%CcÖâóLJ–V᤹8IÜÏà‚“FS¹m™pÒ\ôyÕ{x 0,onÁ|‹Ä«[Ö…5F}HÛâqjp…úQÕ|H;Ù7yƒû.¸Û÷zN!÷O:¼nË G•Ëfö³kô¨Ò¥¼Û¨#ª;P,6ÓƒáÆ™Ú`p CÞí ¸¦à{°gšWë¼>¾£àâLhã gÜc]Ck(sÖçr×Bk`Xv'e‚Gõ”Á…»™öå{€/~ýOuÇÇ”89lË¢7•þÞ=©`¾›j_}š<Ðã‚Å\H –³›7‘«{Ý¡QŸá –ÜOçzK}öܽr].ÞÂcôO—cy¦Ügxa–¶Ÿøþ?j¦Õ° <ZµÝîTP‡[Ü©óÄÔV;:º¿A3<žQ-Ó‡ÕÖ ôúmq«–Æu¸ŒüZïð¦jÉè~ÿ•ÞT5âf‘¾HCm­Í êë N =WøQýò¸p3ø=ôR‚Ô& –ùÅÅ”îWªýnŒÛ^:È¢ª?ˆJ@½Ï…Î*™f[f(€¨¥µPëñÌ{¯¡ÖãIôq¡¯.z@¶eR­Ÿ_8õl`>ûP b[1qßà†a>$J¥>Oß–‘ÈçgÅWo ½âqßÐÿ$øÖQ/è7ƒmñÈu÷§ùëOsù例ŽvCþ»™¦Ž~9ò)|iøi¿¥…5É.¢Îv–A3QÒÝÕ®¬-Äj{+Ìu=ˆu |._Céüì}e¼1·¼„üöc¨+¨î2L·ø\p ;ÃC‹ªEŒŠ¡óÜy›xÊåcªin@ž¾ÆÔžËp5+Ò’áú,]ÕÍäa7Žª>¦ºoæFÅ–,Á ¤¾ ¾™vñL–/ê`p¡œ[| Ýcße?;ïÙÓ>uœ¥ãJæÃDkl#åYª^¦ª’åc*,~m7’´¸·ÄǰÇ2YÞ&{Î^±%*¹Îð¶ï{!ÏÚ`ás× íÑTŸOˆæ=þ¹›'Øñ{Z0øˆêùÐXº¨û 8?÷x¥-Wës›Ê Å=ü¨¦9ºÁxÚ~3Ðô©—¨£\\SüÔR"Íš»ƒS=l(ÃQ_·…™!ŸZ}DÝ–ÂfUás7Þ\}|DWà=µuôÔÝ›Qo¯è¨‹ÙÑ6£xe“lËDG]\+òÔÙ‘dM‰‚ö¼¦¢£î‚ÏŸóUX,Ó;jWÏ}#íþ2Üæc+Õ¬ñ¯ûL” ·e"ËÚE—Úó< YÖ £y¶¡"ËÚ5UO÷Õs¾¡M<}"ËšÖï™XCšµ›ËÞŸgúŠÌp~çÏò¨Ï&‡{XYÖpíòñuøólÅg×£T.W{Ú}!ÅZå$p[|<Ýj;û|•¿t÷öÜȱVq"ëŒö‹©É¶Á‡SÏPÇ3{·^œÜ?mÜÈ®V©qoËBv5åY|ÚôñtWRtÔòñÔSá¡L¿ndW«TÆ·e!»Zå®=aõuEõï馯²LÃQõ†ÿ´25˶ø€ê4àþx®Ôa¡>=yzóÕ-èræÁñ~Ú ±-î9u¯5> ÝfÇf Ws¿üéÕ*#^ÄǧmXè¨h8 ˜ÜQôÓ¡Þ#…õSpóoKCöâ¾°ÏÇæöÁr`ß4<°¯ûì•$öÝ?`3ŠاIJb_åd'¹«.‚&÷1iÅÁ}Œ'LîÃG*±Ï¾°ïÒt'°ïjªÖ±ïê‚¥Kì»ú›Ü—qßµDyâ¾ÂüÉ}†© 3q_áâ¿ä¾´ˆûÊ­zÄ}…ñpÉ}¥ˆCÅ}qÚ‰}¦ªáäľ”>‰}åù†}¥É ì+Ct&ì³µ$oì+”+û´~1¹o ‚öÝÌ͘ØwkbÜg(‚jÄ}7sÕ%÷iñdrß­yipßÍÔ1É}öÁ%å‘û$G÷Ý‹Ž‰à¾Ê5ßÁ}öžQ‹¸¯έƒû6HÀãàW4™àg°2¿ºÈ·~õ…}Fìý…}褼+ÖTL€¹ÏbƒÐåÅ}‘ó*¸Ï°ŽqŸ¯@=ä>Ãú~‚ŸüɈû,P þrßT¸ApŸ¥C@vî3ȯİ8ú¹ƒåéý@àè‡ÐŒO’Ÿgf¿`Ùä ®ä‡EÇŸ?Ï7p£ÀÏWvÓ€1ÕjÁœŽÜçÂ4æ}ä>«÷“ÔçnP©Ï™'õ¹³jRŸÅ5}ùàöA0ŸÈcúFæÛ–ÆY*™Ž O Ÿ×Ò—@>·øHDæó„ñ˜ü’ù|õ¬¿."ŸÇµOZCg†,@>wJ»€|~ÔEÀÃhjaìhrD>Äp˜Ï“%}D<Œ¦+ØŒÐ玫yB_&]ôy\!¡ÏC‚žú¼° ÌçW ç ˜‘ŸD>Oƒ_i™LƒÏ0„|q¡ ’ç€|‰‘Ïk"ùܵ†–Gäƒå“ć°'Yô¢Nf/õy¸~­úhuÓ‹:˜ŠMÔçG]°€ú܇‡Nêó54Q€Ÿ/_"¡5úQáŽèú9èGµ/2QŽÔÕÄŠ“ŽÔm¹pO‹ŽÔÅôá?¿' ¹ïÂÕú¿8^}ïÐw)=¡q4/è³S‘}—„w+è»UÐg'ôùcðéIÈš±úåw$Kðsž8ÉOiÔ’ü”ž6ÉO›Î$ùÝ"• ¿ÊýP’ü*ã“üböäW‹”:‘ŸMÞäW‹èJäóß ¿:œÈïázš$¿'’ä÷0»g¢ßsëäD¿‡£ý,YÁ'ÈïaRÑ$¿‡{$ù=ü%ù='¶A~v¨Iä÷H ò³a õˆüžNi!Èï¡9Éïáøžä÷‰ŠüæOò{°î-Á/d¸ ¿g ;I~6¾Q”àG)ô>®9ô>fe;ô>Fzß”Â&ð{4kðSˆ$?åÇMòö);nbßÃM~ûòÔÂ>e—Iì‹2}ýx‰}=î}æBI}vÛŸú‰%}Z°Ð‡ â{–ÀQÄ—‡ˆøâ ñ5é¿ }qꀾE_PBßúúø? Oš{@Ÿ\û }Ó¸%ôqòr2U8A_“ÚÐÇ…¥ôE‘Á忀–„¾‹­# ¯!ª Ïî$&è{¸è*¡Ï®–BŸ5 ¯1O{B_ãfH }MâT@_c6„>«õúâÕô= ûNê³Fs‘úžE.ô5}¸}QI@_»¾CßÃÅ }ñú&9NèÓ–I }Ú , Ï¿N@NAߨ(è‹OO@_|{}ùÁô5úÌB>"ôÍDâóï+ùŽQG'˜>ÿ¶û.àóñE|6F`¢"àó„(Càs—É©õe ð>o,8ŠÀçÉÅ!=’øÌƒ‰ ˆÏÊÌH|žÈüE|fÁ5‹øÌîò™U §§ã$>¯÷ûÎZ€|‚[ˆØÎJ™ÌgËFÆ‹ù¬À8Õ>$ A%„>ócñD}f$#êóùÌJÔç CP†àg–ÅàçA,Ü~¾-Þ üŽ2d?+Uì7•Û)ØÏ-Ðî†"hÆBÁŸÝ(õ?ާñtÈ~ž)ˆFöËjž;|Hø³2<ŠðçYWd„?¿…üÅÕˆýÜ€S‘ý<ï>(Žìge` úyþÔKôs ®èçwõ9ÈÏ3ü¿ÈÏo ˜òó"0ùQuyD¿<‘Ø/ŸØÏ,”ŸéiÐJÄ~f©/ö›ÚR.Øo*=Z°Ÿ·Z”!ûù%£ áÏÏE GÕhm‚¿¼sÁŸ×ó9ØÏúó9Ø/ŸºØ/"úý¢Ýýà÷ùƒúØçï§ öùS^û"ùO`ŸŸðEì˧BîÃQ(Côó§rê}Çë'úá-zßñäˆ~xÿ¨‡è看èçkTO½o e€~ÙDˆ~¸uÊ{E~¢ßq}d¿L„ì—ÕDH«®ï¯äKÞs®xñ©4yOy¯ÞCŽˆ÷èƒHÜ»9Ì%îÝLÜ—¸§E؉{ʘ¸g ¬ÞñÚ$qO ¬÷nͰ÷l<†E¸wk+܃\¬1cb=3|NÔ»WDs^øy¿ƒ;³€XïæŠ¯d=_¯¢^"¶S2c;‡tÀˆí?Äv¾>æø{Åu.Fq*®Sq‰g\'‰2â:oñcÄurµRÆuÒ×”˜W=œ§ä\Éy6¿‚ó˜;þà¼Ê9\r^å”79Q‡‰yM˜§V—¤7t}"½&94HÏ>´ô—~'éÙþ%ïÀÎÆx‘$½ÆõKAzI(õÚRH&Y¯_ŠÈëõ;B=90õGÑ Â=N°^ïÒÅz¶ð÷Ízû/,#ÖÓ.¶ëMRäÉz•ô7"i©-XI¡ïþ.ð=̼•¬'ÏpÀžRm'ì)ÕvÀ^Dàìuq/`ïY ýì@;ÁÞ`b³„½Q%† öö´ ˆ°7øñMØÛCüEA{ûQÓ"ÚKü'ÚK$ßúN{ƒ“Á¤½=égܦhOñ`‡ÆñŸ¤=eì>4>&Üã¾#I{»Ÿ“ÒD{KªjО‰u °ø8ãNÚ“S:£;µñxÒžÖ0íy¢+Z$ñÉÑ—Üt§ÄWË™Úè)ñDF†Ä79þ‡Ä§éHH|Üã<>Åz¥ÂW¤†ÂÇä©ð)ûä¡ðiʘ ?‘‡Â÷0„êTøæÜé«#Ÿ3ºó(_a$yJ|7eRâS*„¾! ">[úø9€o1¥R_xÎCãSøá)òáRä›ß€o=døL+Æy|‹»D%ð-1MŸrÐ%ð-æILà[š`ð-À·ªÐMÀzFߢÓ7o15KßbÒŠû.& µ‘¥’úl;DA©ïâ`—RŸ­+IëSþžÔú,uàNZߥÕÐú´ibj}—(;´¾m©°Hë»ÎèN\Þ‹ö<åÛ‹öŽ‹‘ÐWIˆú°ŽûÀ=kÓ•8µ% š^(}·Ô)}Ó2§ÔWÕ"©iÜóí`P¤>m ˜Rß¶Ügt'>?°÷´íAâž%$î¡£„{J5•¸7¥3îMîÈž¼§}­’÷&#p’÷¦DؾÙuo*6 €o2;™Oéåú&Ss'ôMä]KæÛìR_eÆ—”úJSD'™Ï>íŒñ„> ™Ïò …ŠùVÄŠ‹ù,ëU92ŸIyøð†Üw—oÌgMœ*æ[ > ¹O«T‚ù7‹òÅÆBòMrb ßÃìQòqƒõù˜ÿwä;ñïþ¶¾Ëýük’ò„…àžüWí{ð÷½<ø¯PãHþÓ„/ù¯ôT*¬ƒÿ´j(ùñßÿ1WÎÁ7¾·ÿi½Œø¯P6?øqµT¬ïSb®ïÃY°¸Çâ¾)œÅ}Sü‹ûT&W÷­ïZ_a›<¢<¥Êf”'ýö €—BCƒå‚¼è{ž&Ú¾_ÐìD€LV–¨×€÷%jÞÈÕüws'“ä¿ÌþÝÜŒ8ñïVÀñßÙÞø§lkÉöMçJ?xYŽOLM3ÀS+X3À3p”ügŸŽçÅJø·j€ñÏŠHúã@%9[øgcWúÿ¬^dà—uËú¸áͱ®ï"ÁN…LŽàäv|F(©°kYTààv† €=àN؈ðìLӗدïbŸöíLTÀiª}3Ä=ª}%Õ¾.1jÓùj_•6jŸ"Î3ÄóL C Ü|c-j`(Z€&C>ZŸhéT_‹ûRÑ |˜<úû'‡Ú§%¢¡öáÁŸIQˆÌ”Ö÷|[Ûçá¼°ˆþêýêÐ!B¿,ô«Ü=Tèçë|®saŸ¯‰º)ëqa_eU.ìS:,¡ŸÅÐ|Nî[•±Á}‹ÚZrß®ìy‡v6nƒÜ×¹ÁCrßÃÕ¬~U“þ¿:¿^Bߺ‰÷]/¡oi¼;¸ïúœÐ§LŸ }W\­ O{ð¤Ê·˜e(U>[Ò‹T¾Åµ©ò-izó‘ÆÄ|“®È€>fHIæ›Z²#‘o–÷’¾toP䛡JäÓ¯É|;7%ó!éÉ|Ú1/™/Ž æ³ÐGJzH;—&ó5¦2LæëŠî æ“_/™¯q_­d¾6*æ³"/æó¯×±¨Ï ã\Ô‡/NN•O‰ sU߸$´qU_yDýZÕgkÃÆkU_© 2ÊU}¶E=­ê«/•oÔjbU_åªø\ÖwÕˆçä²¾"ý+Ào šüvÓç²¾ÜPæˆðäÀ—žôA¼"íe‘Ô‹Õ"À³ÐCœžÚí4#<-+ñ¹¨Ï}Ï[ä[òCõÙRJjzMµ+@R_ôÞ¤¾%€ ê›â@QßCRß}PßxØ7ƒúF¨‰¢¾q‰R…}ý;öEjÚ”ú£^Rê³%¹¯(ÏØL;¥¾Î]®RêSš†”úú·¥}júÔmceŸå"+jeŸR»ÇʾÎÜ ¹²ÏÈXÊ•}—F›ò\úÜE”çnï÷{i_»µØOKû*=¬G±=1^ïÌ6úRe Y"%Ø/Ä"*ð7$û±î´d²­× ²È‘l«™„T_õ„娇6Õ£ŸYO·”Ëåu¯aÉzdc=ñó¨gDîkÕ–£ÚT~þK'kÆ öLšD¬ür²¯ïIÄ~’ ì_$‰ØÏšízíò/?´Ukˆ"ô›úü«=¾ÆÈW]óT£2²æÖå}à›š0LfĬð€´guzV™,fOÇ*¼6…áe­ ]œnËäž~T»Z»;=«—,µ gÒÚãNd›°L:V©·Ö¦™77Ul­Wîë¾tãb0WŽoËd0YÅ„°µéNŸÌìßÚžëÀ‰À"ýºMFéw[¸Œ7ÐMÒd$­{"Z¿ïØèÌçVûâ.Æh#w6Œ›nÝœ#g`òžÍÞL _0ýjÝ\JNX\>½-³LËÁî7àÍKeÞdÂÁ¶Õ‘aØ-xwÝæôL*æ¶ŸÞ&ìÜê§r# Lùí·Å¶—ñ¹ýžr؛ާ«mØRïOÆA4›†J Ñ¡÷÷„¡ îLÏÕæmìúgî®Æ¼|Œ–87¶—@´„?öa^%Ÿ¹«©õ ¿Æ5ëËÞ_ÇÃâ™õXÆ}*ÍïÜÿÀr?诃ñ`Í—ýxõEk1Þ_¹Ê¯±=ÀKó8÷vl(@OcÅÕôÉ.ÐlvtjâZh-¹¢qgöã½XP‚‚lÐLÙ,|¢h]ÐA#¸'óþÀÇ:UY>Ü[Š÷ë{3ÆÙ­Y"2øX©Ú7[êÝu·VÅš¹´núa…½ Þž-Zô-QôîjçÂõ˜ÖŽS¹ï³ù⽆KvhÞý·í¦[Ò,läÀõ Ýà_Q6îwï–#KQ6Þ?º9eƒ‡Þ-Sµw×Álݲ: VsãT­1ȆMö«ß讃©ÿû58d–Á F»uK¤äÝup»ònùkmï…ëY‹A6LÜÓ-wW5Ú^ðñö£ ÊÜwìMxÓ²eSápî¾;bÕxP[жÝw瑼:aá\E‹Û»ïÎÃ2>tvÛGÛú]°L¯sÀÚmwﮓ+zºïÎÃPÝ»íÎss±½7Àî»óp±½‚ý.^µ´ûî<4ƒ»>Œ²áöÝwçq×Åã€Ô}sž§Â‹°íyh8¦ct] Í2|t]š!tßÇe\Ûäк¸ÃO÷­y6‚GT×ï{󰌶z-ZíKëwä{óH4ñ°½yCKp¾7Ï8ŸžíÍ3éæñËñ­yØü:,ýâž~”«»ïͳ‚nç{ó0 ¦¢ÁxK*¸Àűu0Ðz[pæŽÒî[ó°ñ¹_­Ûî<è¬ ãI÷ÝyØZ8¸Î ìÛ}wžŽ–û¶Ýyëyp®†ÁÕÃ\P¦qpU"£î»ó° > z²Ÿ½ÑÂÁuÌMºíÎó0bà ×Ã=’¨¥uÛž½õÆ$¬ûö<ì­>Üvßž‡/wöuÛŸg S¡DåØ:¸u·íy¨­Ý(òplµ¥Ü°4Ž­“s²î»óx™‡oÓvçyè,÷¡«ûî<e.frljú¾;Ïà¹,['£ ºoÐ3y^mÐS˜H~sl¢¶…cë` C÷ zÊà\¾AÏóÉ S»íÐÃ}.I»oÐã]‘ úíÐSñÁÁïÁÁÕ6ñ@µ“ƒëbÄr÷ýy‰ˆ/m_\'c=»ïÏÓñMB+…ƒ+ÓÐõQ8¶N.í¶CϺ«ñ zé§¶ýyÐY¹ ¸ûþ<Ü~«¢ \öþAoõýyè“ÅÓóýy”ÁWÊ7èYŸfºoÐC¹ïwH¹AûôíyV‡n¨²øÝ°­‹qÚÈgÄïß KåØº˜l+‰6‡j­‹ó/H¤÷«Ñð⒬ߚvì‚÷w¼~`A`J²`ù¹Ìí`Á"> d„ÁÁ‚Œ8XP3¼dA2,X1‹9XºS°àõ)Å‚uÕ`Á U-nI ¨S¯Nt¼è«O¼¸2AP™®Á¶Ø æÄÀR8« ,ÜN81І‰ÏI¥nƒ‹&üA¶a®ŽXð]MÔ>ó„À29Ÿ ”‚šx_â0AàÍ!)ð¢Þ—x?¤ê @%ðJ ¼9éM ¼;[LPà-Ï@P ­`ùœhî.à’ 0: °2ÇHB`Å,)°r•`À:dVÌ1~„–¨õ‹‰€ÒR$>—UøPWM|Ô\ƒŽ[I€ö-}` } ÖÓ'Úzi2!G)í{ ?ˆ"µJ #¥“M B`ã^ƒ‰€yΤï*°“„ëLÿ.4Jük pMükÜ 9ñOA-‰û¨ùÆ¿¦nøwø×P˜ø×:”ø×Ô°„íÍ~ö @E×Ê€…~veoôkAD‰~ *l’_ãi‰~Ms@?“$?'ùµ¥+ùu‘V_gä$¿þèjD~ÿ°ˆü:5ì$¿ÎЇ$¿Þ8õòëüÂ%ùuÎ$~’Fü:}l~vá¨Dà7’à7øÁHð©üH‚ßà׿ÁÖüc×übzà§Tq ~ÖcÞà7ø‚Å}ÉÁ}ƒ+ü”#)ÀopùQ€ŸwEð;êøÉ)j°·àNô›Ìõ’èט`*ÑoêúÅ<;Я3—\¢_Þúa<9Ño2u\²ŸœuÁ~³327ØÏ¯5û >õ`¿^u.±ß‚S°r·èW_B¿Î…±úºAý˜*á@?X‰~K®¡ŸuöF? ÿäaI~“Y6^ä‡>ä7†HTä7rv÷’=ÈëÈòcb· ?‹~üœä7/Á—ÈOÏ&Èo4± Èo0h1Éo0b’Ÿ¶îNòÂÙ ¿>9òCÙ“ü†7A~c Ç‚üäžòÜ—$ÉoꓘäÇõ)/òƒS#ÈO—ä7éÌNò+x¢A~“ê$¿ÉÍ’ü¶ï.ÈÏü@+‘Ÿ…·~#?]^¢Sœè׿¡ß`ðu²_òb°ŸRèpè7¹µE¢ßdì~â¯@?ëиl@̹O¢ßÄ¢ä$?îÕžà7¹<ó?.àKð3àúœà7©‹ä'ò% ü"uåïÈ<–ìW|áÉ~…Ðd¿›YÜ“ýlPœØï^â:±Ÿ-ZL‰ýêÍyf°_ed`²÷ûHô«\šèwO‚E _½„D¿GÌè÷tNÊ„~»¡ZÁŸÅq Á_gôyÂßl,ð§~žð§4X J•“ðטâ ù¯qeZòßnÔ à&þÓ—(ù¯sÙhàþ÷7vù'ÿÅVü×é¬N§ËT¹~>P sq‘'6.O9d@z_û#HjR“¨b Æ™CdÐÚ!†2 Wx2 06e@=Š @;;8L8‚…€{ðëAhƒXM8„Ôb@{‚op× „ì LìDõ`@3 1  á°ˆ;Û’;Q20ø(°Ë!ˆýU_¨'š(A9P»É$N¦x œ ªOœUDJœBÝ`@[Òý9p0Î7ãÄÀŽxä@û ¾EÀAè!r48DÀ‹Ý.EÀêBd†ýC¬ªY8‘7!!pr¹dB ò8*3jr ÍÇ Í]œˆÏo _Ó¡rõ{‚àä rh€MP" |¤)lP´sŠ€ä¾Cå Šé‚—3$ †ÿ5Hp1ßv’ ‚o“—ÄÎ ÁusŽ ;Y¢àâ®*©2ÝÁ¡>’ …‚óáL#5À[ú^h€\h€×à¥Ë ¼O¡  R)¢à"À‘c[çCT«\mà%‚òB,¢P‚ ¢Ã‡Þ”@PëQ'—Ñ ؾ‹€“©ü“íÑ€˜D‚ #c®)ô¥ÍÀ5‚ åÀ„^ hâ]} Ò ÆïäÀA—|J€p½ÆflIÚl+)pqM)p‰Ž#މZdv` cÃûdO œÜ³"1p~cÀA1- PÙà_H±/ P"]ÊLñh/èH¨Là 1;\l¸‹Ô·þ½P¸¯2wR`'9†üǤI JVŸ¨ Jª¸¸#!p)"Bè©òA]‚Àżç ÛLê7[<PÞd@Ä2Èm´O„×$°êb„€”Sovn! Ý@{# Š$.î(¸.Áy àj¢9" ¯·8 ×ø†€¦ÞƒÂBþx.E¤üÇ솇üÇ<) ¼’™.äÅ€ÏÉ€ÕŠ#%J@àÒ^ªA ! ´ÔðJˆ—öÑ ´¯7°蟖oò!ãÿ8ýù+9ÈÕÏÝù)Þ.ȯp_Žƒün|jòc&Ž$¿ýFj|$¿Ðy‚üÌòŽÝ½‘Ÿ˜äW9óò»¢*ò»/á¢ÈÏb0ïÉP ¥Gèd”c€2QÄÊàWèõCèõ-@ýŠ7¥?n-sHtKÒß-]/¤?îèóÒþÖ;ô'Ú_”‘ö×¼â_“–vñ<óÍ~…+p“ý ½éÉ~Eóõ`?“3ß! ¥ˆÇÄ~¥ˆÙÄ~Ú!)Ù¯…Šý²ŒØ¯0³p²ŸÍ“PFìWÿ”ìW8$ûe±ß~`+¡_eŒIù/ÞmÈ…Ù&Rþ+ŠÄ ù¯pïÙ”ÿÌò9©OM/Ä¿r+8TâŸcPŸµy*}QÕ›ª8øHÐÍ, ÏNªô¹-úÊ[øS[à+õ»îWXÌWù̧‘(™¯Ôï!ŸúÒ'óÅ£ æÓåòE{ä+ä8!_y„oD¾òD€§Ó‡d.ä+B‹@¾Òt˜ÏV‡’ð4˜6ñœ˜+×Oæ+LŽ‘Ì§È©d¾Ò‚5š6rC0Ÿ¥r‚EÌg_)"žFSÝy@_aúŽ„¾´ˆú ÝôA}¥}§>{à5RŸR&özîSù³;” û ňľÒùÊCù+LWžØWú׋úŽƒD}iö…#öÙCœ ûª>ø}•¾Ê¯Z@_}$ ú”%¡¯6ÅŽ"Ï·!ü)B,•?û¾|æ³"ßB>«´ýPþ*ë©üUîG‘ÊßMÍ;˜Ï:>ªóÙ$‹Ns²ƒÿ<Ü+ê“.õÄ?-· ü³– OøW ô¢¿·ì—Hð§ø·€¿Â¨€¤¿Ò´°PôWºÂKƒþŠþ:]ìI’PDUs³ ¿*%&è¯Òãšô÷0YUÒŸr'Â_ך¼Cøc¤¥èû|$ü=Ztê~í½üñVÉ~J‚œì×é¨yË~8·Ø¯W “©ûaÆì×cÅR8PÄ>t¿GÁ˜b?¥”Höëž)öt„&û)PéÐýèí9t?- ö³ïÎ%öSH²ŸögOöZ+ì§à¥d¿9Wb?ó©R äx¥ÅB òæüÍ©5y‚¿ÙU áo2 (áOrCŸ"ìåM cùßP=‚?æ'{­þ«oøÛSF»r…ÑIðg²Å{õßdú´×ê?Ö,ú›Ìô§Iƒ[½§ðÇqæ%ü]¯àÏÙÄ¿9è$üÛ]1ð‘!I{*†¦ô7µ:1èÏ‚© óݧòÿœZðgK>'û-îdì‡ÏX€Ÿd«$¿%A9Èoq^ä·ôþƒübÈoõà¼\žÐ_ä—²Qß’‡_äçÈÞä·4=òSêç ¿ã(’Ÿëù™¤'ô[K´Jö3±æzÃßRè/Ï%ü‹-`ÿ"qnàŸù]Û‰f¯¥¾– ü³ÆÓ_²Ÿ§ß}-ýó¤×€QòŸ_ÍKö³Ta‹"_aÒÞ)Ò$Æn³€¾î+t]Š!LÙ¯K|;–þ5HƒD@·Pæ\ú¾#zþl$p)#©Ð ïPK«ÔN\Ý‚@“ã¸`0–ÿiÑ› ÐwÕAÍBFVËyG¾#®ÂÝ·å¯sJÊŸM†ßÊ_Ñ‚ÆPþ‚ÄCúSÖÏ\þgP†£BûSó ñ¯0áP` «ú0¸æ ­hëK|F´jÁtÄ@KT×_«ÿ–\‡K>ç ÁH5(h_80ÿE ‹-ç2O¥Å7ù ZÅÏ‹-ß.â\E‚fÁC .% ´ì[-Zí\à3’`l\,´×2)õad]·båH‚ž6úE‚v1ã¥þùm¾HpI¬´£Ú‹—Ò záÏ‚KzFŠ7ÛZÅxZ5ëµöϲNêY2A³à»$\Êœ*´]á÷z5 <€  M =ƒ6±úßÍ=—ýÝ!ú” èð‚~*®õ+Ì·&í1ô¿û‘(G´zæK<ê! ®»ê(’àa! Z=xBÁ¥Ü³Á‚Þ ^ …jˆ‚~‰‚~‚õ¿¸§ÐÿnE>„þw7¾†Ðÿtžÿî'ÂBGôÖW ¨ƒ$ôxS*«ó‘˜l´k¾åL˾ÙÃð_dˆ$c¿xKèïCV²aÓyV–ÌÞ%óÅÏÌÞ5=ÕòëÃ’õÈÆzâçQ}nÛëNi8jI•ð׿t&±akXí9œ™Äžß‘lÒÚzøáŸå60ʬcÛzÿ†ÃX¨Gb¡ÈhÖMçѨþò½Ù£³Ùû«LÔd9(W9k¢å¬) ©¦£ŒjÚß–9T“,GMYˆ5e¢¦:ÜŸ}ÔDËYSRMG™¨©uß«ø¨‰–³¦(¤šŽ2QS$0‹šŽfª) ©¦£LÔdÙ8Ëëšh9kŠBªé(ó›[¶9®ök)ÎþlK’÷ÜõjÌcv4ñ¯?Ù>dk®o™Ê¾R~½ÆòÛkÜCI&?ûåïßõ·äPû _쿼¿Áß?Ðùi}}´Ú=ßuüîüicϯêQÿGæOÛ¨#Úþõ³üiÛ¼4çõx}'ÿsùÕÏÜ/æO­4È"Ø5éõýãþ-£Õ ðz1Gɰür.‹Àíb,QpíÊ¿{þrGŒë±U”ôó³K-DWètÃîY…!,ÎÒ£ÙRx]+δ|‹*Ÿ‚8zmËø¢ûÔ磣_3ù7^^/7ÜL¶Žš–e¥Çvñ£ßƒÛs2ÀaO¸ø™ö n¢ÌsÃÏTg²-¬+c!G· Íîšå’çÑ‘e [ÕºaxŒò £bd4ñäé'Ÿn¦‡t£#„{fÝñ±ç%¶í0,¬1æØc”þ¥Ý©Šx`’/ÙuÖ£­1þ¢aqñ"×׎ñtx™÷ÜÖC®O­ƒþ½ qoç¾ Û2_ΔRcÀOŠ…8jú£Í¥c¬‹Z&/r‹Æa-±`Ý¡ÿ,~¦A·ö°@*d­:|{G®×óÀ·}â3ýÌðmˆï—f‘¹™ðìîë#<üª ZFåZ¨†géÙl¸úÌçÅÃÃPYäF½«ÑLÞð„<Ìâõš¡±È eØ õ"xpN.Þ6Ÿðí™þ͈Uf[Ü÷ÊBÏðTÖ DÃ[­¡›j—ªáù°ŒfµÆÅØò´Œ/Kv¦ź3æF5–Ù Žƒ‰ë³Ýª:WöÞö|ÐÇÄMæU¼4¼EÃ-÷ ÛWG Ê¶,P«Jö×l€Z 3ˆÍëq¹†Ç-íµ* i[¨Uá-»¹Ïwuò ŒgFuj5AG!S{!5ÝÕô.n±\ÛÄV÷î±é¶2òq8 ±•h6=É,~¦rwRkXLÙºÁ2Õp›åñ¨rgho(:6A3Àù{´V2 ˆUùÉ·ez7µÝ¼%ít±ÖªY»³[ª\—º¿ÙžeÅ·cséc[&ˆµRݵƒX+ƒß÷w½zW]ÚœbÞþº+›Ú¼‘]bàriY?FÓ÷ò"\™6mß!'V¥€œ¾ï=†‡²Û´}‡YmãyXfÅh Ëë¦m;äȪ]Û§o;d«!ªdÚ®Cî_zÔ†}×!/ÂüÓvrÿ’mR`Áº³wNÛu¨²Œ»t¦ï:ä›M ¸}¦ï:ÄÍ&ʘl½,cªmJµp®ácªm‰Q±í£_ nÜv2CgžÁé›ùA\¡5mó!ï«ZS>}ó!VŒ;·Í‡üå)áô͇,xê¶ù÷ÕÁPçà5d9m÷!φߗjnS×¸á·Ø£"Õ5õ>}"–Y¸f,:ïbbPµ½?Ð}"+£$cÓ¶ ²Š¤àÙ4ÇÁ™l "¿F—Nß‚ÈAãÍ´-ˆ¼«*Áô-ˆ:,î¾™íÁ¨š§ö-ˆ¼ w©¶‘÷U-œž¾‘=®©fk[ywMË,ØmQç¶‘w×Åvë;ÙÓšôïÏŽXîmáâÃÙÜm‚íCÕô-ˆ¸% º§ïAäe´¸é{5ÔŒµMˆ–íéÀµ§oBÔÀÁøôÚ&DÞa—²oBdyì/}Vm¢Q°7Ä…zF×㧮Æ– èzñ60ŽiÚDÍö“˜a87œ˜¶ÿÐcnÖ:mû¡ƒmÓvªç9aÀkÃÞC~ Û{ȶ¾PTéÄÖCÆ7|•më!¿]nî5mç¡q)\iÚÎCíUúì'÷§›¶ë]vá8>-aÔB h¥ˆöÚg`z„‰ À† ¨¦<&çÀoW†‡í`ƒ;÷P+ððMN†w 5ÏÝqž¯-Ämâãí¹¬µyÏîg%˜‡bbŸ¡q)uÒô¤hf ®8±ÓÐ6t¾A“#¸ÛF­D½ M2} .Ù6¶Ù…Wö‡="aÏܨ%Ø2OÛ¿ÔØ©dá.»a¢_Ÿé‡`¬X®{ 4`ú"ìy£ƒù&Vbê2Ᾰœ~k.´ë|¾ñÂ:MDë8á8°îá¤>°ÎôFŸ³Ö]œáÕ]ôÌÕ]]€&ªSoªSÃKª;, º‹)#“êÊ…Æ™TW4¿ ªS}R]᎖IuÖøßTWÄDAuªAuÀ‰šEu…Y‰ë–XW˜ü(±Î\ =a]áFÁ‰u…k‘‚ë ’ënæ@ ®³æ›ë0Ѫ»¹­ZR‰ à¡'Œýí,+algWÓq&²'û„‘í|ÓC¿>±]d# ¼³5ýä?âù\Ú ï|k3XˆwžØF¼³³©ˆwY³ðî°ïaÝáá ¬»´Ä:÷Õ¡{ëÉüäX‡ãܹ—0©îpÿêÜ…yRBºð{|ÍóqCY«ž@_8¾£ÜOÖ¼…ó€º ¢s¨sZ Î£´P~3»ñ ÀtîYäéÜùH s¦;ü“`º¼ â2@l•1Iú˜‚é_†ßˆH*ú6M߇Pé©…‹r¤CtoaS.¾!Òù}``Ò¹#“ÀvÅçx”@:lnê¿èüÑᣢ;¨ :ùÙÜÓS¹-/‘î<À‘βtÆÅ9|øððüéNý{°]é·¨äʵ$¯ÿæDgvöðûK¯³ ';1NÎE6»pØÙü3tö¾õ:³@õ!Ù-íjd·”THdg†Au޾ÅÎìö"»,"² ï^]øƒì|zŠ2·|‹X+`wô¤kqà ‚ ô®sì¯8\7®ÔøÀuîM ‹‚ëœÓëÉué¤× ‹<§\·ZÂ+ç:7àQë†ÍrË¡×íZ4'×½,>m ŸÉÎý ù@v~1õ‚ìÆÓz’ݶpf-²ó2TAvgݶ4 dw”!ÙùC†XE²×£F@²Û–"ž@^O€ŸçÂßvçyÜŠZ#Áî¬`çN™“ëvyÈunÎJ°óŠÑvnyNÍηœHìüÜhø;¯ø>5;Ý× vÇÉ vîŠ^ì|]ÆÆù†ÀίÁÎË<§f—×'°ó2„6€ŸßI‚]^ŽÀΛØ\—7%®Û¹âÉunŽ\ç'‡’\w–×m ·&×¹…ºÙ¯ãÈLqÊ®;j!×+y \ççÆÐG®¶}7Æ)rݸº¼¦ä:¯ç1‚ë²y‰ëüì¤7Ñ[ó\à:¯*¹ÎÏîÕë¼È¢e¢³ÆAÄ:·ÌSµ;.çÆ _pëö!Œ Ö Û£ü>±Î‹PDýÛÂX^‘ݰ•˜“ìN Ð畆,@´³2ø‰È±‹= ëü<=p_]¢쎫#Øy5ðeìÎ2»£åìv®áع®d‚×C¥ÏÁÎ 1îB_UœÁî¼b€[1îF_}$ì†wXv~Ô)Ù—G®;×¹¥œ\ç´|r[&:¬m©€Ý°e6äÃÁµci’ÀΫ9»ój†Õ>%µ]Vo’ë¼VÐ!¹îhÒä:¯†–Êq5«y8®QÁ./\çÕ ?‘ë¼´ r_Îu vG‹$×í£¤“뼸΋,ÊsU£Há :¤AëŽ[ ×ùAh×ÒëÂÏD°ójʩחz’§^—G ެö–ÁÒë†déu} ª¨×õìü¸¥× Òë§¡×ÅC^/½.|Ò놸Jz]犋Ðë²49í¡× .ä¡^7aCzÒÁ†^7‘“!äº,@¹®÷¯—ZgN¤—\GN£Vgéïi€VW­n,¾/iuyBju#h“Z]ç&!¡Õ[€J­nŠô¤Õ .» ­nH²•VgÓ0µºxÒêâN–¾ h‰uÚD*ĺ¡‰u–s5P¬œã‡X7¤?K¬Ë;¡X—wB±®ÓƒðW’—%ÍÁ£pÒ\QŒYÐÜÍÌ!Is7ýæIsUp4W •“ ¹Ê`ˆ ¹›Ùi“æ÷4W0g³çS¦3C{Ã\UøXÀœökM˜K‹`ŽL sõQ|¦`®rž™0W¿«tf¹OšsË©Q¥;NN•î¸dªt>?ÿ"= „yJ¤Ë ¤H—ç–Hn‰tùø$ÒåMI§;ÊP§³gƒHPétù¢¤Ó§¢Nw”¡Nw”¡NïW2@ ’éò®$ÓÅ«’J¡`¡Òe[“Jw”©ý¼8©tyfªt§Îĸ~©ty)éŽS¤³ƒ¨ÉQ¥;,Rén…®†J—ÉtwOI¦{¡Ü¡¦†FŠkht»V¦Fw+j64º»J”F¬4º›;ø¦Fw·¯3ú2öŸJ‰Žk¸R¡»‹› Ý­9f(t·<œ¡ÐÝŽ)….8B¡»™o7:)»©Ðqc«ènîÖ’ÝÍýpS ³©€Pdåèä n-#-)ÐUMx$ÐU&JM.-è"‚$ºª ¦誼Ô!ÐU&[H®Êÿ]¥8ô¹*e*ô9kÄ`Fésa }®*€0ô¹*=+ô9éÜ©ÏUîH}îøI}®jÖ }. Òç*˜§>W›‚:%ÑUiW!Ñ¥E]¥¸]‘DG==º0H¡«šÅ„DwXFÈé¤4ItØS¢“PŸ]冾)ÑUÉd!Ñm DItSƦD'U>$:®H…î¡ã5º‡Þð螢hL tÜh-õ¹';ésÚh-õ¹ç¦·:ô¹GŽøÐ瞔㴞¡JY“@÷(ˆ.º§ò ÝSŃRèîÇ A¤B÷p«…Pè‘ ¼ª©ÐuîK—¨2º®¯D(tÚ…::ˆÌ!ÏÙÔ8乤AÉsÚ!6幡€ä¹™œ$}.Ž’>7aBŸ \]ì8¶I—@7ƒb¤Ð¥8 ÝP…Nûz…Bçù¨_—žè*t¾“Žb¢žÁžI.õb莟PèfÌò©Ð% ÐùfD@*Ht)šS¢›1i§D7ƒ(Ñy6bb,å¢(tžµÚA Ëß&Ðy®iþJX“]ÊÛèçÙïA†Ðç|ò¢‚>çû !—H!^‚@g%¸:Ýa€@wRµË$?t¦šS:ƒ@g%úqH1Ä LèL¯§ÈÇÌ;y×îjª$Î ç*rÏfÿw¤#ËÀËîéÎÀK‰øItJ`˜DWøMH¢Ó¢’$:›‹Q#ÑI<ŽÈKeäe,Rä¥\Oy©oDD^ÎXЦÈËEwy"ÝÅDºK2d voH¦Ó:dº›ÃD2]Àm0Ý-ñ%™®¿×Ó­:$¾Ò1–+‘îÑò£`º~k¥™˜®‡ÞE¦ëäÀ@º¦§%¤ëŒÒN¤³=¿ ûÕo¡ÿ‰t#–å é,ÐäziQóPé¬q…tShH§­-’é´á@2Ýbtt2ö6H¨›t²¥@w…&îª ‰t…îº)­I ³Ðƒƒé<Òþ:™n[““]áÂŽTè6 …¤Bg«œN¨ó2Xâ ]-Òì$Ñ)<%:F§Bw/Æk†@wIÖ“@êftš`¦@Wé¤Lîaú“—@G1Pñ<ô9©]¡Ï=±t0ô9Åׄ>×™Ô'õ¹Ž„–)Ï…6ò\×’çB^y®£ºa †ƒ$Ïu¾–”çsè§<—ÉsóD:w¼1TÚÜÔZÚ\¤ÍjÜŒ“)ŽS›Û@‹´¹…”M)ÍM¦AMinjESHs‹þ¤”æ–GIsåRð¤¤9»ðë ¹Üén’æÊÅ<ء͕Â<1¡ÍY͘2K›+JcÚœÕs3ÆÒïRʦ´¹ré5Q›+—isåb›‘4gúa &¤¹R¦ÖåQš+EžxIs–Ú ÕP™+·VšIœ³\gŒX¤:Wn¦u®ÜLÚê\‰@©s¥*TWê\©U*Õ¹bZ¤:W*3 …:g5CÙ”:WªÖŒQ+±ÆRê\© ê—:Wbá Ô¹òp‹¤PçìܘgK³vAê\Ö#y®´bä9; ­Vò\iÜ—(ä9«çŒº–î>Ã.‡%~£GuÎÊ`6-u®t½ÉsEK&%ÏY?á}Bž³n‚V!y®Ä¢EÊsÖK®—1*tvÈuÝ.¡K…®,É®ÐYBÂv°Ý6 Ž Ý}i¡º )ЕÅ`-)tv6(twQ„%ºÛr£$:;ì‘ξë'ÚÏÒE:+®B‘Î ¯u÷ÅÜ„éìœíéìÑsA‚ˤHw_L¸/‘Ά´/Št·-&hA¤»5ß’Hwl î.S‹á ÑÙ£Á´„]Þ95:KYOî¾õŤFg§ tÎÎrJt÷Íé’èâY ÆV÷@³Ì#³‡¶ WºY"aØ/Ãüûß`lÖžYÿ¨:,™ÒK6fωŸ™Ô«\–Cù~Õ#ËYlQõì™Êëjøû¨Ã-ª?þ¥“‹­ÝÕŒy–[ìWó…yn±ç·ç»Êon±𯲫nŸ3ùÑ÷æíç†(K©¦È¦šŽ¬aQSŠšŽR¬)³†±¦3k˜jÊBªé,¥š"k˜j:²†EMQ(j:J©¦È¦šŽ¬aQSŠšŽRª)²†©¦#kXÔ…¢¦£”jЬaªéÈ5E¡¨éoÈ-¶¼?M-Ö5µØn~_²µ—Ú2mWÿÕÔb?¯±üöH-öóïßõgù«¾§û ß꿼>¾?|™ÿò³z~¬¡w¾ëøÝ©Å¶²üif±ýþ1ÿù‘èë¯e{eËý¦Ìbýguüóf±Õœ½{.å òëGGø6ëÈWØóÀR( 7Løz¹Ãê‹{ó\@¡m€«·põÖ÷¡ø¿F©ÚÄÌ'³kÜ%>ÂÕ[üwí_Ü0o N=öuÖÓ{Fûë›ö¯‰¨çïù¤PIõûiÖ¯sÁ5l#ØO.Þ ÆRË×°ìèW¹ý”¶@Ÿ¹Ë|¤]¾i×'äáýÛ¥KÊTËÎE}Ö}ª{NäB&=ÉËTDW-!Ã,[ëš%UÌåKb¡Ÿù¸±|è'5Ìeîc×¹†pùæl,‹ö?õ¿åùguUbÏsL8yˆXË–vqM±ÃɲEO¾Ò–é-–¯ãùäÞå)>™Ûl¹ÿ÷“Ëj—9{Ý!N$[Ëè%&~C7i _Z¶*¥À…~áˆÍ³Ä€=¼ñ熻˜Ë/»sMØ2§*7¬ðSî/…åüøxгƒmðtcÈœHÜ`¹!žt&Ú– Ê‚[È'›n˜eAac¶4H(1·©Ò¢°H(ÚÇÚ,2s×lËDÏ\$³-ù¸¦µãLæ]ªPÚÆCË”ÔVp}Å–©}ríé¶Xîbˆ Ϣؖ&)¿™a~qëd5®Ëj†ýÛ¤)˜mKgò6¶6³Ì/f>c‘}éó޶ÅöiÿäþØÛb‹G¡Xu^ïâôW—ëÞ_0®åÓº §…3¯4È'W¥…û%7œù®P:SIlË©s1ß¶4¬FÔ.¼fázDâжt,H¼î¨ypEbZæ¥u’“GM®IäÊÉmY¾p·\/æm‹?WßøyÿQE-X—¨LnÛâ1YØ{—[+¦£ÚÀ,ؼ Dã¬&±¼íÛаyAaDó¶t®NÄ×Ï \žH7î¶Œqˆiû÷äÅ¡Z(ú›Ì‚Š5Ø~@ãVÔ)žÂŠô0oËŠ Õ4 –(„nKíJæ~á)ØŽ@²F·ÿ¶4Læo¦2 ó¢7<]îd‹ yG¶!WXN^6:š±V±ñÜ«¿YîI×…ÕŠ5:ít³ gñ½Ø!mC ’QƒÛP+‚@£±¶§Á~ö{~1ï?;¶CoVÛ+â'¹"Ú ÔÇÊX:äAÛ⻚xî7ÕÃ…ÀŠï,—mÔQ¦Ê2ñ›ß Ûˆ)åPmçbà‡€ÛR}Ø<ŠÔ"xÕ¶]þù6ø ãUÜx*¶Ð ’ï±3W¢ä¶ 8m¶¡Î \åÃÛ_,'¬ýFnãöAå\Ü¢Û øŒ3®A ·KŸ;Û ˆçØê¹Ðiy|UF<3 ûiµé¶´[xôÚl+ ¦ÑÓ©†WBqÆ~¯/êªì¶«³Ñm' ¿…®×h;M(¸<Ó”`›®nŒjßI¶¦…Û•Â]~žË7ÄB=< +sܶ4.Žå-p È™g–‰[xÔ6¹Õrã½øFæÏQ÷ gL.îL&f–ù5¹\¶ÂüÆQìÉö…¤¢Ì +¥sU­Y|$å°ÛâQ¸׃변žOfÌÛ†á2ù&²á]Žíø-D7µDx7$p~öLûöµ¹1æq/ Ó8uy«}Q8ǧ§øf@öÛý­Å¦~Ê}gt‡_±QÑï`r©J)ž¡Ë,¿ìóî·0™Ò,J'åb(¿ÛÔ ®?[æå)ô.üG'—h™ãèä6ÅÚ*ÅGÚÞ®ŸéÌ‚¡t©Z5¸.Ú–‚¡t’ÏÙfY¼¸¯ÓQé×ï¯é·æKp³Ñíä¶NnqÇ™7q n܃%Èí–èn×C¦"·] € nÛ† $"·]Œ} n»Ÿàv ÁͰ%Ú±)`ÛÅ™]Û…ùa€›’¸ ÜÊ%’#¸ŠÜ´ûu›RÝ”›,ÐM9þˆn…[ݺ)-Y°›²’»áŠÝJûÆnJ[ìf;¦á¢ÈneˆîÈnÖ×9Înñw±[azè`·Â¡<Øí0€Ýl7:TIv3dEvS~°Ûa¼)cbÀ›BðÞ”½Œô¦Ðú 7Åѽ逤7|â›…¡ˆo oO|»͈oÇQÄ·{è#)|³ÆM#¾)mšðÍb¡x5Ä7z ’Þê¥éºè­ÆÐ/z«%ÈìŠý$9i½)KZÒ[eTjÒ[‘^ôVë7z«·à§(þ]HEz;JÞP“ôÆUûIoµkh½1V<áM™ÙÞ–“ðÝêЬOì&ׇØM±ÚÉn ÖNtS"¶@7+0‡8Õ‡[‡ºEàu [^ºeæx“Ý"[ÐÛ˲¾v]^ôÞ‚ÞÌ[ÃgGz3  ð6Ÿ˜Þ¦²$½™…-ôæ³)^ðͺ9¯ˆRi ñ-|EÁoá, ~³£è¡ ÂE.¹@8ó Æ€p‘Í-ΜL|ÄD¸H˜wÖ„‹pD¸ÈHgµØ€pvîJXäž®­ªõᬠ§cD¸IWù;úlžä·Øw5ø-²ÏÀE¢» 8;Š¯Î n¶˜œ‘àÌSF× n*ƒCÜY/ÎüeüêI{dº8ËOÇY½6tUkœe…„]/¹€pSI‚à"\\ä´ „‹ÜxAqçQÀ¸³f`œ ïü„ãbïƒÀ8+ÃŽIŒ‹ˆq‘.0Ψ¡¿0nr)~P\$ê Š³ƒøøHqlj´Ÿk_úî‘âÌu(hcùaÆ™…˜ ˆq‡s‘7G2%0k&‚á|òb¸HÕ 7¹f=n*Š0î¸k"œ9$Ù)‰p±¬"ηý…¡Ñó9_‹!áϧ¶r1æábÁD ÜÔÂê@8[ºÀ¶G„;ÎE„‹€pÚÆ"nŽÁö± nŽ@k\ìlçq!¼ œ•a#'™;—HL„3Ç,…¶s—Fn"\¤ $Âùn·D¢ÂE\E—Žc1œy|ob.VQÃ¥WX k1‚áÒ¹,†‹¤…q±ÍG`\ìµAŒ›Œ!Ãi‹@¸ãÚˆp±X"N) Så×Ò† 8;íCÊ£ú('öïH‡¼…GÈÀuQsŒó]<¡¦.î®Æ™¡ÛàaÔÆ²â8kÈPhr±{‡@.Rð äÌt È­+ä0€ÜaÈ-ž‚ã"Þ@ÜQ$w@rÇ! ¹<@.¯’ ·®.y GÌ2ÏÛ$ÇåŸëëÁã|/[ÔŒ³è–ë”à,Z $CŒ3>™¤6øüp¢8«‚èŠ[Š ÅY‰ Ø1г€ñ~*pf­’â"—¾(ÎJPìÅÙz  >(ÎSôÏCà ärŠó |à'(.b® qûw:Äeª0‡8y O‡¸L™Fˆón…j•Cœ§Lã”ç~ûq™!MçgâGÉÃÄpÅ=DuËc!«,†ó h1¥Gl—€æ 7쳡q» „ nqQ—Ä c¿%¸/S–¦”€8· 9ÄYt8~:Á ã<ç—7N„óðñBôÚ«I­¹åÔß<Ä|ú[F¥ áÎ焈Ôwƒ#œ×ËQçaè”j€pæMùÄÎÊ…D7¢QËÔ©ï{Qéb¸QzÑü—¿‚8tž'Äyx/ݲ€8Âå‰bR-Oå —‘»b¸ma¾V0œGém7‚´øÁÃyÄ-/ 综0ܰ¼©qUDq)ž[ ç÷tó ±_Yì„pÕ,„ÛÝz@¸óaÕÁØh¦#ܶÄKÂù1ì'@8r¦ÀæçEØGApþÄ9áÁ탆ZÎÃáù8Apþ 8Á Û}ç/jɲÐ"8iÁ½,Npþ ˆc ¸óA€àöÕ ÎëaïÄùÃy„loU¦nà:%¸³€àü¶u”¯%hÑÈAp~)ÒÎVy´õ&8¿¸uœ7éG–©&ÂÖ„óšùµjŒï—” ÜÙ&ºÇ„÷ç­ÁõvF…[6f¢—#ܸwe!Ë ”™Ò¾€pÖ=O„óz^Jܶ})pâXO„¾ ‡õL,ó0™žõX„xYÒÂ@pÃ6½_D&„ˆ[ õ:Î_‡ŒÁ ñ+Ú'Îã±Ù9†ÂÄãÅá¼ ¿YC‘â] „óšÙp€p¡„Û¿‡Σ®y1NpÏkq†ó°wò9.£õÅpþ¢ØÃqÇN_ Î+¦ˆÛ/aÉ-ˆó{è!nÜ^ ¡súr‰Ã)(Î_·ô½>ÕHørAq¯£œâ¼ÙðÔˆ·"ìð€8¿`¶P@ܾà¹q¾8â³õÕvRÜù­6ŠóZ(Ý=Oóƒˆ{[0 Jù"Ãù¢ ºÀp~P?ÎÇ 6,0\®ÍÃùÕ]¤&,ZAHêAH½0¾ïd8?JTWï÷-áüsÊWy(È… w|éÈpLjD†ËA‹—Kh€pÞ¹ O…“vyUÚ†ÔÁŪÂ8ý_0¤¶G· ÈèÆluâ¸Xÿ”áÔS÷¿’,Ð K´npD£'WB(pó©Q›”ÎCSV‚àDÏ¡Á)Å~hp“)=Bƒʇ—jp“ù)oO„cJy{èxKé-ËHz‹xÑCz£öBíIfí­kÆí­*ŒOÒ[(½¥Ê[šlKy«”*å­Æ,XÊ›²8Ê[ˆ|)¼ ìS6qjÂ[Ä/…ð– o!†ðƒ!¼¥€'å-å:)oØÊÛC á­FÈ£„·Pôõên—ÞênE;/ênÏ·GQw+Mìé­Ì\*oU2 •·”—Cy3˜åͦÿ pOË"·Py+ €¢òÖôãQyK*oé@å-¯Ê[SÔO(om*~ Ê[Ó‡„Ê[mŠ9 åͲ Ý'­ÂBRÞLŠÇ7˜Ê›í§€“PÞÚ–†å­WÎ**o,ŠÊ›™‚ófÊÛó1¼Î8Ïí¾ôfßÑ~bœ_ ýCz+£€!½yž?@[HovîÆÙãÏÐݘ2Nº[é"?t7;Ѥ«¤±øCw+GŒ\o¥K¬¡ò6¤/Ryëî¾PÞìqRë‚òfEð¢!„7Ókëw^…·t‰ ð–*ooC“ŽÂÛÐúOá­U]0„·¼Mo¶v­3îu¦PÞL©noåmJȤò–‘“TÞX3•·¡/x(oCŠ.¥·¡ÕÒw{)½É̓Ò[—€åm(&™ÊÛL_I(oGT”·†bqRÞG2•7¦yKåMn)RÞt&)o ÏH*onRÞä"åMñƒRÞ¿lRÞ:ò¶¥ô6ß émÐÉVÒ›Â/%½É[@ÒÛBr°”ÞR}I‰kãÞªÆö¶£à”î«”uwv—VaÛV¾/´(×/„.ìðg2~Õ!j¶¼…ùlâ#CWµìÄ÷k¶œcD›FÁŸÇ8­Àb–÷È–c´qþùÏÎøU,K]ù³¿îÿ’¿~ðrûßòuf%ú|Ëüš×ë½û9Ç:òya¬3ëÇÊ^ë•,Æ:3zÅX¯¼_ëè…±ÞÙÁ0Ö‘Ó c™¿8VöâX¯ü`ëÈê…±ÎÜ_+{q¬W†0ŒuäõÂXgö/Ž•½8Ö+GÆ:2{a¬3ÿÇÊ^ëOäÿ*%Éÿÿ`¿/Øïùzÿüþ÷­þù‡3öõýþ…éúå'+%,,ÿug;¾œÿá õ×óá­p¹@ùú Râ.7<®›8·W*`xõów ƒo©ÜmX ¬3ÚùiiaðeìòÓÒÃàËXd{ÖaðEÒ.k{oUB€{.çò䌖³’›¦¿<Ð6صÜp^hti.wB´NÙp]x^¬ôÊ-uô÷B£i¿X…(ÔØ­mx/ ’ÏÓСŸ*/éîÐO©K“×kÖH×OiF+{*¼° ïõŠ«,fN„~:Ѳ¡ŸÒ¬V¯ë#n±š¥a}à¿ Sµ¤ûë+uÅzÁ…‘Õª«¿„»z¹ƒRkU¯eš[lë†ÙužySøºp¢5U[ÒzÝa©>úì‹auOK¨§¬lùlL.D.Ò4XÍp®[ÞR/†¥±O}ÅŠUÏöý•…sžx1°HÏÓ2.*KµÀAñdÕö•%yž–¥R7 GÝ•%üvåþÐ]ª§7~U/E<á¹?·þ•žCö÷¢ÏÎ]+üUk«¬1sᨶé s£O‡ *ÄØ74Ô}ñúê„Ò= › ¸.´ÖÛ¦V¸2(ÙW­^ÉiStþG†MkFmפž¼Á‘!j54ÔMóêÓqC¯­…„º8[[ïì‚÷¯P7ÃdŸ–È?séÝo3Ð\Ì}RŸ­TƒÛnw$ ¹(l?-7c¸ ÆE ¨ìÓ¯ÆD]ø½;R@]”oŸ–H@£¨‹Ú«Â´ØÒ",‚µG‰ÍŽÞ#ýÌ¥9Õ‘ŠEcž–ÙÎ…ƒ–4#œgEþ™‹Á¬µß±Ž–Úw$Ÿ)”ë¸"ùŒŒŠOK$ŸQ4JµÊ=®+1¶µŽêEzèÂT­ngƒj\@¢m=’Ï~Þë@¨£ÏŒä3…¾Ò•…X•㬎{ÿ¢¯+±ÊzY­p”1ü’¬ÅZ¨ ?ÛQüËe¥²Îmu{üPPïi©‘¦ÐAªZÝhlxÉ­n'£è[­n—í¡ktµº=^Ú‡Ru" TeXgµÂ=%ú`ŠMäR³ú|‰Þã" TåJW­lÏŽ|/Y¶G)ÕÂǸ,ÜS™f©Zåžõ•uV­%ºU}×R1W®˜u $t£ ¶.„Z*éÛÓâ×ÇUµ.[VúHÕ…hK¥]« á–ºX]·ÌÝÈ•·p#à2¾‘Ê>K-r©ÌkµXuê!—ÊWUŒ•{±z#îÒ’Š`\¤R V½y)Ës½¡} ³€ðÓ ¸1ÁTݳ]Õ 8Úå>TßçoêÀºâ¾‚–Ø&[ËÂ8áçk6ݘ­„Ÿ¯²øµn¾öÃ_8h"Í_üº­„›¯éé-±¬-áæ›™ýZ 7_Wáãg°Ø¿<.­†›¯]~r+Þóº¼n¾Ö°1ŒUëtõj5ü|m0ê±Ú©ZÂÓ÷< V¢¼íž¾æö€_ж¥Ž½ôïM!v é_HA)!ñÁ!‚ÿ.Á ùï¢Û¨øï HðßÅ´/â¿‹©a€¥u`á6SÈì^ €Lï•Èâe@¦÷Jd†¯$ÀR¿±!0À…_ñó€%ž-±ï,](LZ&2}XàqÔÚï@ûò¼°ÐÕTXî€LC–x´àÙrËîŒG@›&@B `¡S«P6!àÓo‰ðè´}Æf³f"`ŽCDFñ$À£áŽ?±u"ùÏ| pðßqø¯0©øï8 üÇ´mÉEÌ@þË“o%Ã0Ä¿<(ðO‡þdrý‡€þŽ> ¿£èÉדþ MÂ_abIÑ_Þ$éï9›pÒ_^ý:‹þòÔ¤¿ìCú+\¸DGÐß1ð¯ÈBüË{ þGþ#þã¬3£žðïÕr3 ¯nìynàŸµTÂ^ù¸>àßÙnì…®ÙÄ?%ôþ½þÚ㸱çõÿŽ'þ;î x¶ž#g¾Zn>cœ èE›Yõ}&0 µÀ<ûO x¶žWOö£% ÐÄ™*Üþ€ÀóàËž¿žCàqn@àñnÏ>u}Ü ðl <ž: ðì3ï}àÍ~œ}U¾Kx‚€Àó¨{½ï Þìù;cÇÕH Õ™Ç<¾€Àü‡<[àô{¶¼?'`À³ü~ó‹¸XóB“~±è….xŒs³ì/ x s³î…ž¨3à9,Üpf?úÀ8Ÿ'ðlp~{o&RÍ«a&Uýv7S©ê÷ÝÌ¥*~b.Uýt»¼‡Ý̦ª žÇ0£ªÖ% àqÁ›9Uõ"Ïq˜UU xüš›yUõpÀ€9N0`Þ60ÏMÌ7‰ ˜ç&ž}Ü©Oðì3>W2àyvx-ëcq <ǽ7¯çÞ‹+ðx`ÀW‹&"B g^Miýý*‘-±l%î÷l%æ§6 ðøÇ]Ï3ÝóýQ'æ/N<Ž×´– }ªWÕÊëÙ€sƒg <~úgšZ\ç‹­CÍÈB– x»ät:1ÈÜL4ë,2v; šá˜œUQ‚i’ ÁÔz)Võa¿H0¾K´.   ¨ÔÑ‚»PÃZC} 療ÓȸKê~ÁÖB­”·ñ˜ xö <[`â8Fî¨B”TÁó A³S‚çÉÏ£¼Ú¼ŠjÏQ­Ïx)yA0Ç%–l€àajq€ Ù©;Žòâèúå‚gK€ i½´@kÁ è¿t¾A;w#ö]Ÿ÷ xØç‚zoÈÇå­…¢×eW’à¡AÏ>‚ùæÏ>‚ÖöH  Š¦û ÚŒ—h}:Ð ¥`J¥™ÕQð¸%°àqj°àÙ,xÜX0g&Y0_t²àqÅ€Áœš„AÈ%R³Õ@Í^©:9Ô@=©z÷¤êLRõKJ ÔS Ì«¡x´@ ÌŸ—j`>RªÇÙ—Vpß½^žbàÓkÅ@B-0ï›Z`C-0‚˜“…R`^¥Àœð”>sà¹ßg†x´@ ÌדJ`ÎnJyÛ”óÔ”ó(JšTƒ–À„@n.¤æg™:`ét x´@Ìa æ=RÌN0w”ó(Ê€¹ 0õwÊ€Ç1ó‹F0ßMÊ€y›”ó¦(æ>†2`î~(æ—›2`î¨êz ª‡tÀ£tÀ£t@=-逺+é€ÚÁI<ú@è€Ú‹IÔÓ’˜ãPÔ3–xŒÃMr¶@Ì{ x´@<ÎîB ‰à;úÅ%£@<®B`E!0¢˜÷I!0Ÿ1•ÀÂLxPPóפ˜WC%0ïŠJàÓ20”À㊡ò¨ßHa–Ü·¼ÊÇ)Þß €÷”fùø àÍ„/RwêtPâ(ð¦÷‚ÀÍ”/R£ -P])PNdwÑMm »á©ÉìU’)} nº7HÜ ¤“¸%>RÜÌ?# ðàNA`>@J€ÇQ.W ðh¨‡% P}$êú$êL’ùˆ¥Ã@<êóÝ àq1Pcæý¾)€G(€ú©¤} æ8T·¼i¨æS<Žª÷ûoh€G €òÑPÌÛ¤xœàÑ Po¨4Àch€ÇQ³…" .'4À„"àÑ0ŸEÀ¼Š€G D@½èéš¾›POú€r†K<ÆIÐy€ßÙƒ> ºù€RáOÐl x3N.}@5²œ@urÕË ôhÙ¼ž *àѲúûLPïý~ç1P³…*àÑp—O0ÏEðèðhq0¯†*`Þ%UÀc\¨€GËÒLäQPó‰R<Î 0[¨æoE0ïœ*àqT}­RPQ ny±Q<Ž‚ ÈšÄóÆ)A<."àqò­ÉHIíz_0EÀ¼<Š€Zl%æ™(æ™(g‚xŒ<´´ò(ˆ€Çõ¬úqó§ ðè0G¡˜}(} }jÿxÆ>sq  xôaÍg–é*àÑ*àÑãnŸ÷0ª€y5Tó(ª€yeÀ£O½?Þ¥óפ x3´¸R¬c׼𩩸!ãÜ×gÈ€ùt(æ¹(æSÌqBÌOuÀ£tÀ¼ê€gËúøäP<ú@Ìw:àq3[i^Q<ÆÙ³: F‘x´”þþlJ<úÔý~ץ귒xôxŒ3öû]—¨ßJ:àÑçÆ" •:àq ³½rŽKÌsSÌgCðèSçû]—x´@<Æéûý.I̧:`ÞuÀã˜õ±¼JÌû¤˜}¨æ8Ô>Ðé"0òAÚÇê*0/†2à1ʼÞ+“dÀãb ò5þ)ÑŸOLJ?¨ò «T•oO8AŠ,hë:€™û`AFÎ3óQ03ϳhQI¢“UЉ(x©˜Ž‚7Ë#& Eú•¢W(x£n¢`–…ÚÊe,ŸM  Rû l%¼uW¢àÓÒßÞ Œ)t¼ålK¼89PCˆÏ¬UGx¯OWÐŒ #G£ú|Ÿ xŒÔM ed-Á ¨;ÞKú@0ÏNÌ£‚9r€`ÞAð^àq$Á£Hð$xœ $˜Ñv$ÁcFê©“õúe4 ž¢‘â-ƒ³ƒu1G0 E7fæ©A‚ÇÈ ä  jvœÑ€×;ðWtdI7 g·8ÐJ{£ˆ,ï*zˆ¨¯†0Éä*'' ¼ßD ÇQ€Àã\w}÷ç&ê¾ z6‚À‡x´°êöúbÀ£ ë~ðUê‡IÌ“Ïþ¾<ÖýÈqY÷#aÝ=2 3g ³ ðh!î±î¿ `À<5ð xôaéÝ0o“ ˜¿·ßÈ?ÞÈ6jãË>bÏJ oþ»Ÿ”æ_2ÕÌÿ¤,A?ç¿©ñÿú¿•Ÿæ“ÆëûùÿÛùWÿö¿ù“ƒÿ»ÿôƒ:ÿÏOmV¥5?òåiþûæÿxNƒq~˜¿ç?¾/·½.÷ßèþñãcù?¾¯­?ÿôWˉÈË}?•ÿåÈùó?ŒôKÙ}¨é>ûhÏPjŸÄç'ü»ïKÙ–:-ˆ˜Ìšß½(õÓb‹NØûñpýw¸˜a¯[]/«A¦[_«)ð\N$þéõ²ª).z-Qô£3Åûó òªV±!àâi‰ªσûy¯ UnþHµGšrEÆõ:¢ê@§ ÏÓiÊsùõ:Qíû†q±×å%£윽Þ^sÀ+'³ÅÓ”×Â`ØÊxýb¼ŠíŠúÀ•é z+^u *?ûÓâUì¢Â›»·êiÊë¦*Ð &ž{hŠSí­{šòÖ˜åiñªÍì.ñ;<ŸˆçïIa«·éEËñ<-^ýv=ßÞC[^vÀJ>à>ÛYyof•ëÞ=FÆoÕÝ<ú´húôˢM9*{wóè³—-°u÷çç³{x&#ß‚îÒÕíæ*Zl`E·0®›G—YhñKõá‰ÊÇÅ"`½O/;0l·±Ñâ‰Ê;wöOËò²}2u_ï·'*寮àj¶—0»nǹ¶'*,ËTú¸¼ìÀ0•2Fn ]C%Òž ¼ž¿ïãoOT>6³‚öѼìÀ¼ô 7®©´0O‹—˜eêLn}Z:ä>¦—°‘'ZÜ<ú´°¾ÇÓ╦%áÂ8·W˜•u­ûØ^dZž©xó²3™œ¶ð·ïž¦å÷glf÷°>0³Æ–ëÒ7ÈÎi·°™léiñ Vd¡ ¥{á+ùÐÑâÖÑe…""À¨ÛfÚnA¥õœÖÌO…ÕDzx^“ çvëès5K}¶WX•Ùc{ÔÈZϬâ«E²Ö²¤RÑǪdyŸ‹8Êd=}˜2¯[¡,߀.pXJYËþƒ¼•ÊšvöÊÉhµ²ž'Áä—ÝŠe ëÁ˜ÖÕ²žq¯÷ûò‡½Ü~Œƒnd¦¾ø°zYv •Ñê= f­µX¡­ÛBm·°õ-‹’YËÖëÉ/=àIsâÆ£lÖZS·`u³žkÒmGá¬ç½^¼í¨œµìÝ(8føŒ^óÖ™¼vÖrÃOÜ•p³ïËæW=ªgy ¾‘7syÐzÔÏZ ײ#÷\¨·Ð£~Ös^ª‡}?—´|Ó§Zç/»Ý`Mùƒö(¡õ¼{ÌÕ·û,+.‚VTÑò·üÂQî@°–›ó¼ÁÍ¢þó㞣ŽÖ3sk˜&ûv÷¼¸˜(¥eσgƒhß«ßîRZKy/ÇåîË4’xéjiÙÜŽµy\î>°LïˆË(¦e- G9.?/äÄä(¦ek¢»,×2îh±bZ¦ˆÜèáÎÏ1ü6ÓZ¦páÜîA°F… t ––½ô1KjiYM•È~5Š;<±rí@9­eñpŠ;,›TaϨ§eŸ—††;î€2äðzZ6¥ð„‹û,ÿŽÅõ¢ž–í'†uÿe…X .Ùéë­ËsÿeªÎÀÈQOËžžgqÿÿÌÅ6v ž–}0ruÿoÁZ^릣ÅßóÚÇn ¢–')‹{@E­eN-8Æ7ÈËHaaܨ¨ewÕÐÇýž È´_Eµld<¿êþ>·ÎEµ†ä¹QÝ`9ÄÈ(«u«zÓhË=÷tñÍBQ-û‚Åç}4w ˆéÏEµlmˆÉ;š;,W³pTÕ²ªIøš;¬n-QTËîªàú¢¨–}QεbM5_¸+ÔÕZ7ê¹iíòn>t$â»8º»xü’°axõkFÔü.ÓéoŸ ~€_ü™Ô‡B_%ú˜Z8¡ ÐW˜2RÐÇâÕ }é)E}¶&¡Ô§”Ä¢¾‹Þ¢¾ç`€ ©Ïž#ÆéÀK iy‡ÐWXKЧˆHq_I0÷•[·î«ârŸ¹£Er_B4p_eQ\¡_ÝX³œü¼hz¬# ?ÏûNTÁðù"?KÐŽ=ÐÏÙòB¿LÇNôóbÅèŸs²8ÑÏ#¶ ~î€ÇÛÜû­,9ú…Jœ)ÐozÀQ4Ôǵ |V#÷âsðóà2¼•Añ•ˆàçYX±Å¯Šïz#üf,âÞà1ñ£á ì›¶€·û¼*'¶Æ0r›È‹-6°Ïj\’ñ"×ÖrPU‰hÜûƒú¦ÕÃÄÔgå)±3õYiÌëE}æúÆ>Ãÿf¤5©ÏZð³ú¬âã~QŸ©µ-A}—U療ú.–#õÙ"S¨ÏÝÀbA}VèóÔgUö`ÔõÙë=«S_–´"õY©Q‚ú¬ˆG ê+ʬOê³e˜… >“kÁo ¾bw }õâ6ÌWžÿHÀ|ÕòæÄ³óÙ"uæ3¯62V0ŸYÈsÁ|u°²™ÏZ8n0ŸyµáÀ|uqDæ«ÏaŸ`¾§þôÅ©ªRÏÖtÌR_½|ÀgÅ+ñZølBÜh à«›æ:Ÿ¹°|öú“÷ìÍD€÷ê ƒ÷ší[HwÎ{­1?kðžyÏáŽÀ{íyÊøÀ{¶žß8&xÏÞ~DÀ{-Ísà½Ö5—Á{m1/yÏ ÷¼×¶¾qà½66OÜkiIsܳWopÏ&ìÀ=«~„õ ¼÷ÌqÒ`½n¹£H¡‚&rƒõº­c¸¼€½¾ i)pÏ*lqÞ{~-2—á^·‰‰¿÷ºÙ „{ÏÜîuã·îYÉQ|Û{ÏÄãë Üëæ,O¼×Eä=³Qa"øÌ²…_Ä7lgŒs9ñi‹Câóψ*ˆïywpW$>ûn-‰|£Ð¢Gä3?LœÈg> ëÅ|ÃvMhé~O´R’ùìŠÑ!oØž8È7|›ò·ƒø $>s 'ñÙÕu Ä7žIB2 â³/8~;Ÿ¹ tòÝHf|â3Â%ˆÏ¬‹7¸1ˆÏ|Doô â3«àÀ(A|ö™g ˆÏœ›pTŸµ”ñÍ´Aø6k1“øÌ“4–ß”µ Äg–~0WßT¹YŸÙ$xLßHöñ=û7µñ™©èÀg ì>»`6€oZ]pœ Àg–Âðù8ñ™s,^tŸý x}æ K ÏJé ú~¯Kr_µô‹û«ü,ËZ†2"Ø'à¯öo =°Ÿ=ï·àWL ö³ iìg{‚7û™®û54Ä~£&éû Æ+‰ý†ÌŒd¿©]E°ß”PDøëãSñè þžÀZJø˜×b?wÒ†@¿4•ýlO’úõ%"ú±Ž•ÈϾ:‡ègþ±Øùýæý‰~K[4¢Ÿ-yè÷,²Øéýî‹ÜAô»µÔ— ‡@ŸLž¢ß´:GdÊ­`\Êl‚]ðdH~‰B«òÃÆ¾èg¾‹Øý<† ‚"ž«¬`²`?Uë‹ý,* ŠØÏ6\^¬ çú»sÇú;Þ#º8MVŒýy ~]àŸ• £0ø—åĈF×íý¼…(× œãt”;£—¦ãŸ—?{‰~ÎñàíÀ¿è´[(wÆOÀ¿iqnÀŒÀ¿h!ì]‡ñšþM+RÜNÑÏåbüOKÊ!+Ú½$³5Cã%1¶#'Úbîàß47êûý¦…¬AÂü{h—»"S—)Ø/ªŠàr7в4)’EY.)sWdc²O\Ì@N´Ê;ÁßôÒG'üyf¸qÂ_¤gB&DÓä ø‹¢UÑ€|hÏ·wìçõ³öÉ~î€ÙøçÖàJàŸ× £&¸‡»hì1ü›îEOD.s<ÿÜl³OÁÏ@ñBÿyü,~Jà­{r0Ðô)´Ú÷`iüWžÙÍË þ³²ç¼¼à¿RPÀœøWòÉÿ,to¿ðïš,ú@ü³Õâ"ì9þ]Ú·ÿ®ÔO^g}‚ÿ.Ysƒÿ®K¶Çà?·Á˜ü÷\eçKü÷L}ú²¢-ÊÀgjlŠ„HŠ6™à 8J`°¼‘mèùN+dŽUëFZ´®Ùmèb –ÞHŠÖe4 < ½ÔV@ÀÓN蓎À´T®Ñl,cEt¼u¡Æ°Ñˆ*°>¿¸3`­Ô¾È€ec¯C4ÿýõBÀ‡JâÏà¿ReMÿYül=à¿k£ ñïz~Z|É×bÙ!âß5+ ú»†>NÏÎÏ€ôg¶¾Ž ú»ªöÚ ¿Ë²RGCÀŸ•‰Ç~ðwYá€2?7ð’ûüuåÀHl’@Γ¡çœðç¯o;å¾é7q‘2xɈH†6 øsl(€¿§åú€?3,0YÀ_·}#Ž ø3×–ù‚?C€‘Ã_µI ­1à¯:I‘þj“×5èÏlˆlA™ìMA€øWÖ%á0ð/+ÑÿŠ}M\VÆÄü3sêEØsü»ž9ž»ãŸy6×þ]kJ$ ü»&#ωf‰ÿÌlŒ_øwu‰µÀ¿«Ña‡øg/ a4ð϶ñ€yàŸ}.)±þ]V}‘¸wÙßÜáÿ"vüo¢?·ŸãaýÅ+zê}¾Aöôç/)ûÿn¬æ¢¿è ú{æÖõ¢?3Gà÷ý™YˆB¢Ñ_¯LŠJú3©PsHñ;NÿýçsÉo…$$ñ³4½ˆoÈó’Äwaz'ñ-‰yÙäïäã—È7™6BÈw‡|×·â«Xœ|•–1_“-’À÷´©| ®˜ ½v½i¯Ñ,‘R±?¥¾-PОÇd{`¯v±]ÀžUJü =9µ‘öžðA{M®¤½Î‡Â=™÷ž·“:pož…{CB$qïù •7îyàÜTú:ŒôúÖÛÇÓà)þ¤Ê·…•©òáÁz¿³D¾2ª|´T¦Ê×dù¬Ö+†íJfk+e>Ûn³%–¦gª•êYqJzoºÎ×túú”, ¡ïi!xRèÓ¶¨gË;ö‹Tú¦~8*}iŠ Ò7—ô·@=ÛéõêíÍ<ÛD=[^9ò˜q üzöu£¨··<²€z¶•ÀÏÔ³´DÆ@½\ìõäGÔ«´# õl.‚¸€zÏäx)}GQ ^“âMÔëE¾¥@½g¿A¨§?QïÛöÆEY¬÷üšDH°žE%“þ‚õ !O¥ïiÑ´$ëM)¹{æ“ÿölÊÛ{“¤‚=™{ÈzƒÅD{&É``Àž-ºOÀÞjßÞ¬gfSês˜Æ1z{ ¥®¿,~#žƒHÏ¢a^éí-[(}=)ó wðÂæùkFÄ Ì³5ž}f¡µwèœgtŸœ‹üÉyO w7=Sßé Ð+‹ z¶ú¼A¯Hv"èÙÇ$Ðó­‡7ó¤Ù“ó´AçU-Ðù|G Ï58¼@ç³Hmrh}¶86’ßûx$ȦÎg§&k…Ðg»1¼¾ú®ƒµBèó`nèx¡ô]i¯t¥Ïrélêz±7lú,Cé»Ì”‚>¡ô&Ã<©Ï‚Ä;©Î¥>à  ``žýtå优Ù'çùüÂ÷~£<Œ‘ä·8K¦ÛËà ›çy ¾ƒåalöÉûzÈãz£<Œ¹À r_O¦ºëÅ×}ûzÊw£@Ì’Qs£@Ìóˆ¢Ø(s˽½@Ì]äˉ16'èËkªòþ€ö|î^PäP æißÞ…Ü×wQ pï9w¡¿g¬©Fg`Mâ§po³<ºpÏR\ pÏ\cOÜó_êqoï7î¹ÌEõz ÷ìÀC¸gGÑDzÁ{æÖQ{—g¨ùiϦ(´gƒÔíWª±¤Ú‡õM{×VŸ =; B-hïR#ÒÞu8Kíõ€5A{öÂC&í•–òß=` íUš¹D{¯Ÿh¯²>«hÏ>Jhí)˜%i.ׂ½V¤Nö,’àåÝizOìÙ¶“ÒYqï¡;`Ï6ˆZŸA÷ {ËRBMº{†óÌ\Òñ:œg$5ö,mA%Û…óŒ½/Ú3g^^Ð^ÙE4´gGUzs¹?ëÔ|i}ö“öí­e œµ¥7ÂdôøI~³’>ž›…¿~…ü¬ð”=‚Cr~æÒõÜ·åÊ:¸5ÃýP$, ìR½>lÀ„~7½B?‰SB?™¦IŽòƒSDð7)ª þ–üµÏ÷¶5ÒŸhÞø'¨!ý­òÞg®à­ ?Û£•ýÙÎÛAП­%ô£ô¿5RÚ‹åªË5L~2C3ÂÏ‚$¢~­*2ÏáÏ'ìE Ëd—ô·lqÁj¥¿‹œ~·VeFøuÂsøUúÚ0¾oÈëñ}v‘ŒŒø>ËÉB¹ ñ}f–>ùo];ÝG#¾ÏâAeˆï³…„dñ}vߨ=y|ߥדñ}mõ@|ßXbFÄ÷™‚ßgßüwš‹ßWZS¤^Ä÷™|ý <=}¡CKxzÖgCOYñ}VÚüˆï3/D’\xzú¸ DÄ÷5yÂÓÓþýòô,û„¿ç;*×E÷=Sƒ¸…à¾çq2L/Ü<Û¢ƒ.¼<ŸÇ¬¼ðò4[;e½†¸ÇòŠí+Vøïd?÷àüˆí³Íi0bû†\ààåÙTÁ@±}σÇÖnžæB8Oú Hèdáçi?à;¶Ï¼8ñ[ºŸ§yqþí+•y¦­WlŸý|Œ ?Oû%¯ÿÜ¿ ó~ž¶öÀ†?Ï–þjðól©åÃÕÓÌÃÕÓ<»°†«§{•²®PäðGX%»DQøyÚ¢‡GGÏjÖlÆñ•pT­Ù‘}WÆú…Ð7lAGfà³¥ÁBŸXâ(#Àn«=ާçJ¹0”¾^JOO³Óá·œÃ(Ñz° €*ðy»£OO9 ‘Çm ÐÕK´Ú`ËÀ/@ t´LFŽžb฻ÎhÞ‹§Î·læA ¦£gU¬Ð&*¹ÀöÌàAéÏÐríAÚëÕ´îåéi!®!Áæ@úÂ?[Ú)ó=︾܌ê“ÙŸü7äEÏ< á¦COOÛQSÕ W쨯 †öYÐTñw¾$í…¯§ÉLo_Ïçû‡Í„>Ó=ùïùYë­Ï&ÕuòŸ{/â E_Ï¡5V¾žƒ÷ ±Ïâ®9N¨}¿}¨}J?ÎPû, v¾Ô¾©u.£ûˆá”ûìCEnƒ¯ç↎¾žîáˆ>ðõ|þ¡Üàë©/qøzz1Ž _ÏÑå‡_ÏnL =9_®žæ@xѱӗÔn~æ )¸zš? `/ðoöWhŸ… cÏо%O@úy®*Ðý<Íqú%õ™?&#ðþ|­AŸúlqÃüYÔ#Xðç_®—§§%}éïØ>Û7¿àoZ.p žžÏ‹ V–§g“oeõ„$yzî©oq1àoLE,þFºš€?‹Æû™F‡Ñ€¿±¸*þl⥡£ç3Z}Áßé´¡}œ˜„¿aù/pLÀß0kè Žž2²“þºÕÉx…öõIáðg1—×+²o]ÜØHê»…ø³ÜŸøí–Muðç™\q¦€¿aò*„½€?ËQÿj:zøŒœ¹¾®íñGϲPÍñïÿÊ“¹>k[þ¦–éá8v’ÿíWŽË^ìs÷’~}w†l¹A&?wŽ¿-ñ–Òg¸- Ø¿Ñ?þ¯ÏTµ0¨{zOüïû<¹ñl%Ëý—÷Ó_mwrµ¿ü'þþd»Ýu•¿üû§ãsÖg²ëÿñÄi^Kµ|Íg¥~(ê8­eâ´æ‰ÓæoæLkžïlþå?ÿTï³ñÈ”ÖÞ£Ì#ÿ‘g’´þ;’¤]Û=Žâ—½9+Þß%ØÝ.ÿñéwWÜÌå ^¥ºï¯·D ³vÇß¡d–îjÁÓB}×ü¾®-1îÚ½“EY–Ö]¢eF,\lYËÄ«D¢boA=Ûí²ÞG³9/ÿ#î¹^ž›âi€»¬¹f‹†›el›ô´¨¸Vu.v4ígm\c‹’ÿÛ.éiPÚm‹Ø†yóÝcûi鬵`Ò¹5¨øÂò½ôÓ2³âñ7ÿ€ÝŒÊ­DàXŒÚÛ}ºž¥Zà 7tfš¶-y·t7R.{iÔ§%|šª»wËr,uæægW÷<¸: KmÞgÁË©»$Ö-Ùz¸B4 (ž”¥[ÀAÓ»™ëcÜé‰ÙÃFe!§Ó:°nOêÑ-£Á[¼íÿ»EóLzeù‡ÉLñLƒà‚ƒƒ?u¼ts7ãˆy¸ö×-Ë3[yì]w*ÊþF¸Ýœ¨è ]íçð^<³§'™eå²Ï²¹U¡ý©ts c裿bÝ ú0ÝŒ"{&U1pû™ÊUønâÅC€nÑ:•›wŸ©æ›Å(­å3Õ"…ÀŸÃOc ¦¶÷&L§ò>ù™6SÝV}n/mÔ-ʸ‰Rz¦ۣкypÊÎç}˜Þg i)Ál®ºá·5-VÚž×dŽÀYÝây²7Œ$–îË&«YaÐb)kØ0LÍáúj·pœ ¤9ŒÅ}”0oÎéry·8Ÿ¸bK f“Õ[b˜Û#Mº×ŠjÑâ^Ý+·xÃvOnÁÑërµ¦{m+¿ÍU<®À @!úYþ¤^­…~«º£Û3ÎÆK°<3·õ¡r½Â¯+ÔÂ’Ù|5dz LK+eóÕs,ú[R ›°Ã›ëy4L485vKSï±}Ó¬ÁBEbÜ;‰]`bß›°–ð4Üïð#îæâï‰'±>r­²)gÖÂR‚¬]3³>ñ63lÂîF¬··Ü&ìî¬Eq‡‘Ê­añž˜7¡MX‹^‰(8{«lº¾W¸ºOXs S™yÚ„Ý 2÷8°G…ÛÂMª÷á9-»ÅøA–Îï¯b–#ªÆ[‚ëíœv›ƒ™­Ö•MXK1¶´fé§]¿ÍŸ¤{jMæå±½#žÝ§Ë× Ncþ6aÝ-F^îðôa¤‡yHØ„5Ã`|ñvä}êæíå}¼à•MØíÕi¼aÛV¢[êMßAx½+›¯ØQ¼üj§ôßÜë]Ù|5k¢¯ô^ïÊ»Àɸ:XóÒˆ‡/®foŒk ;U7_'š±¶šgá£ÄVÂG‰3‡»´_K‹;ر¶º»J‹–X[í 7#{µ+Ÿ®¬àÕ®|ºnäjõjWÏt“ÉZµ«˜®¬+çõ®|ºÞ0º×gu²¤»ÈãŒX_=åJŒ3bõ¿u«w5mÏ ?ÇZ"k–_N<¿â•†ý`8wD7x ®xûëÖXÿf{µ«Ûæ™j‰v£Î„×»ZÖGT_\‡yŸ¹O¼»zæª?‡+Æè±¸n~ȼØÕ°>Ltù ã‹ë0‘-Ó×q1«»ÚÖÇ6í1òZAØLWâÅ®nƒg ]VìÊÎáGÍgûê:L´÷5¯6Û)û=Å:îõ®¦wAiºç®lu£ÁWW¿s2­ùâêÖ¶ûâ:,ëz½ÜÕ¶>¡‘^îªÙ£hØ÷x¹«»ÆÃiqÔòÅu˜Žº=ÃP˜»ã\±¶øãŠ·/®ÏQ­–¯ô²>ÏUø‡ÌK^ {\î3^ójÛã¢êç5¯º=‹ ßk^Y&â¬n\qPü½âgÂw¢‡+Ú°ˆ 3}mæ¹³Ì$bkÂUËK^ÍÔèsûâê6üãl_\‡GùmZÉ«½¢Ó½äU·>+2zÅ+Ÿ¬Ïw,ž–%Ü‹ÉêçñD þ8oŽa^ðö8'ä/x5í9L¾–G¡ô8ÊW@/xe—»àÆ—/±Y«Æù4eºmt¿3]Ú‹ç'ÆêŸȸô/4$FCB`¨* tÞJd*‰„@L³;í„À®º—„@Šö ô;Md•¤Àu21p°x–0p°B!1pQÐ.&c.lïˆÂ0I \ (R ý=HÊt! \t‚*(0úžhh 0š|Ž:@ÀÀE‡l‘àÍ09‘ )³h ÞôW >-(èDœ´$Å ZE¯ØN­!0(hÐŒà'Aû›©ö‚“¢I‚ÖÂÔâA‚Þ‚÷X¨Ö^/A‚Ö‚\Ø A#mÆ z ¼ b±Z›é0H‚ßp´.ys}_¹2¹8@ÐÓ:ÒE8ìs›ÁÖAk`FÓÁµ›|^­…©>ëË h:Å Aë"¾˜­ä|r Zx!‚­޳àÀ%çyr õ?!8ÐZÖ‹Í¦Í èV† /ràÅÀSr +ÀhÖbÄÀ‹±^Â@ëp TGaàź…ÄÀ‹Ø, ”–& ¼¢/ ¼è ¼è/*¼˜„C¨WäÀ[ü ´€1°ÐY†è}¾ ô¼ž/ ô–:€ù³!ZK<-` Sâ ` —Ÿ‰=‡d ¼åØK 4ëJœ›˜… ˆîŠùÂ@k逾ÀÀ,~@ ô–¯ƒ­!~a‘z `scU]‚»@?W;°[î ¸- Û[ã]úË4ã¨&ëjX^€nLw Ðϯ°GÔÀ0ÚÆ1 «ªIB_ÉýŽ]Eò_÷úÊqêMãj…ü–Ý@¬ «ªOœä¿®ÚÔâ?{¯kZêÊâ“D@?y‰£:VUž‰€þlJàÜŒUÕ6¸_I€]*A€çõB¥µß`þ¾xŠÌ–¸;Mhv±7Þ4éw•4ÜLüI T ¤(ÐsƒçH›‰žEf q¸o+ ܤ.Qধ±(p³ø¹(pSén²!P~°„À[…¶qƒ ôMN´mŸ:¸A\B tMéÄÀŒ°'zʵ—h[ÖÿÅŠU˜M ôØýúº° ´Ãza -Žý%Úõ„´ ´Ë™/=ÐÇðÃ'Úª[Þ‚ Çuh!ÁÎTI-ÝF4PìTD(*ûœA¾ÂjÕ”é‰jà`øšÔ@Ûë2Z«•â ©öÌÙŒÕÊJ_~h;B!Ä@Ûk}xg±jóÊj%X¬š<–¹XÕôË…ؾ½зº/Ì _‡9NZàɾƒxñŸ]þ‡8™XBà`@Õ¯ |?N!™5YòÛ¥8HÀAO^ ƒÉŸD€ƒž¦"@¥ƒ*e< °3†PØ™ŸH[j $ `#Áˆq¹Ä¿ÍÇ—2 #–Sdðo“ Ä›±Æâ?/ª}âßMÄÿ)E øÏò›Æ0ä¿I¡Wü§Léä¿y©K•{ñß lˆÿ:bõ„±•/äÒ–hÞïzÔY.65À Kmj€s„ˆþìK€HúÛ,ä!ú³‡ãoæÚæåëä?“§¾Nü3£dŒBTÂ5àdu"  Ÿ÷~œh²ÜõB@ÓPA‰”+K¹Hl ¹–¨€9I€%ý$&£‘x1I´PV I€ HHäb xCÅO¼á? H;tB …  goyk€•j 5@£®8†"`GJÀRò¦Øî9U@NðT ùƒ©„Õ§ X–™"à%zÚ˲ p#OPRàÆ÷9)ðF*ƒ¤ÀELx#õ)вjÔ·8'/'(p‹ÞHÊA ´& ¸Yj 5@f©úÛð´Ÿê äÚ+~½ ÐÞÀûÔÝ¡ázC w f« ¸ ·¢À‘D– $Þ@bà^ü!ˆž…$*0Ðdé (P §DêWC³‡½XÈÊ‚@zˆíaů@´éB ¹WÝ'#@hïVˆÇ„@{|ãT»2m&n+§ xáC* -P§ Ø=¡IÐ дõ˜€@ÓÍ©ùIöq£€@—Í¿´lwhoÛóÍÖ˜¤@›­2A»*… @ÏTh ÜökQà.H‰) ´Ü¥a’ Øo¶M}ïh¹¡Ù|–ˆRÉIö´‚Aö†ž ´.;F ôt—1 0ÐÞ­žà¿žD-ÑÏ3¼Ð‹P¢_ÿ@?i)B¿›NXD¿›‘”B¿›©„~7RRˆün&[ùݬ ò»÷·7ø©¼ŒÀϺÄA?p üî aGäw³‹ä?‹mú’(¬Ò ”a¨éÊ’)rÕÉåªaèÊŒéºåJ7PæI7PµPTêZ €›i’Ò”êJú2iKº‚ÒÿUè'½Eè'éDèw1ù~ú‚r/¾ =Ò”¯r½ «r¥ "gPˆ §/(t:ù‚f¹ôêÑT ­ä ªlrÊáLWЕÁÓ±«”!ú+ÊÒMü³qæ«TŽCü+Ê;Mü+·’¸ÿê¥,¢à¿š‰PÁò¼#ÿÙ‘‘q±¯¬C™I-wå×I€UuI€U‰3I€•YÄD€JŽ/´Õ ÎD|ú ìXoñ°² ŽPn€"@Ú€1'Ol,þ lØ $6–¾%6jÇÀÆ\À6?%ÀF›P «@¤B6æê6 ¦B@³„|¨:h"ÀŽª7ÀN«°W< E£Ø™¥PØë§ر£vš,D€¬A4×Çh2)«ÐÊ(*€rq–¨æRûõ©6úiKìœ0‚À~á¥ö‚i&Ô³v&ÂöJwVR ž²0P¿„0P/Š0P1ÝÄÀN1QØ™1ŸJ`ç—¨BJ ýt”;ÓØK ìBPJ9ý$ö0…§˜‘;soJ ìÜü‰-1Oð)Á£‡ˆŸ/)°CZO dÀsJ´Ì§xQç£X>(Ð5Ç8ˆR`CtnjÌ¿“Z`C ¯Ô­®GŒC-°ÞߨVˆR’+oAR`¥A_øü ZH…(’!!'V: ë&ÐA ¤bœR ‹•H l•àH)Љ—R`ƒ‘>¥ÀVHo”’W¦ظ–Øàè”R`Cºº”÷Ó’mºØn!–×V©L™[7!e†S ÔK lp²J)Ð|»C²ƒØ…5JÏk¼ üÅêj3hƒX^R¤hIX¿ ´Q,$v„Ö¤Øf<¥@{ q*JyÁ” ˜Ê×A>]£)°_”ð(Zªˆp­¤Ø˜R`¿ØB)fzI¬Ú™R =I™…R ¤ph’©ÞüTœbà‡¸éAJ-pS'•xÓb$-pcyH1Мè‚Ä(6¸æ§hŽXo1Ðä°h¡hŽW12Å@ÛÛ‡6 1p#à.1PËÄÀŠ-ÕÀ‚/×É®–HhŸ«—G(ïI„—@A„ÌB’¡ è£K(=ÈÒ%”êVº„Ò2]B–Ôt em†t å.9]B·œD麿} áE^Ò$2ÞBH¸Y½+Å@æ‚Ê NHhiêã\@ÂÍ„BÂÍt&D WûD ~n†_ˆ-•r¸°Šé2˜DÈt5gd œ2E„ñ}=€ŒÂN_¤Ô'ûµ!O-ðba,¡r© ³\Ÿ· K d Á „„H"äSD(/=¡R ¯ª ÛX².!^Ròèú,ýȰC$Ü7³ MXþ:‰pQÿJ;*j(ƒo†8î\³ H"\Œ*¡*ˆP™ÄE„…ÉH„Ee‰„EΦDÂr±:‘Ð2G"áÅ H!áÂò($Üu0! ‘p³vŠp}z…ÒÙçÐEnDÂN[‚°êrBBA¢°@Ç$V‰„Dš*a¬Y•…¥„„Ò÷…„ ,¹S-œ+ü) „–º;Ü#„öµ¸I\Œ×#ªxNj‚…|íp_ˆkP³J$¤7l"!ß$!!w2BBƯŠ+íh$ÂJÏkaE¾I!…œ 'UY % 6:((ïSñàf!ñàMUS<¸˜U<8©Y Y©%qp…ƒLŽóÂÁ8¹pŸHá`cÂNâ EâëmFUP2!UA f€U°q’*h±'чªàEC‘ppr o¡'yЪ˽Ó@<8a?TÁõíhVÈ€HŠ‚W:‚ׄƒ7üa×P MâÁØãäÁȉÃ5tÑóð ]oßЇBZp D9>©‚Š‘K‚øLUðbd¥TAδT/ø¾¡H @x#çy¡e h"™U!k¤% |N‰;}-“'•DhéC‚E„a†”Ç¢×)eAƒ€‡²`[Œ­ƒ,Øz4‘5¤…„Aý‰„¶¹µô¹)o&ÒøÈ„z·Å„Ù3“ Ÿ7Þ«dBæ*8˜ð&’ Yj&™Ð?€ L¸5AÉ„)ýŠ -/eè‰Téè&&|¾qr1á&1‹ ‘¡ôå gU2a¿¿ñþ¸ÂAXHh‡7TG2¡¬bBº’%–E–#V>Šd‚ŸXÊ`£l/e° ¦Õá ZIsbBñ'^ÄOzˆÊÍ™¢Ït_gŒ`úIךå%ùñ| £¨åoj9“§ýòqÙ‹}þ\ÒµïÏ-™ìó?Z2!Y³ÍÔz¥–c,´c©%ÇòôÒãuçjɱؖceË1ÖŒÑc,µc¡íK-ÿì¤kͶ¬öŒÿ\Òµþ£¤ke|üïgÒµ§uüRßHjT•ÔèG¯Eà—y°>_b{= ^8TæSãPg>5•½0ÔÙIC)Ÿš†:ò©i(õâPG' ¥|jêȧ¦¡Ô‹Cr*0Ÿ‡:ó©åÄe/ õg’®5ãAfüÿBÒµßóuüÑ7èûoáÏ¿ò=;{ýèÅý~¬?œ»¬Ù÷ «ü—Ë]öLßóÈd³ùí€û/w6f³úÛ Ìž'gë|æ/‹÷××Îö,°äk5 ¼a^ãËÈôæ1ÐÅ÷Ñ­Ú‡ Ë|Çù<¸1¾ Þ9Í‚æÌ}¶WV §}Z»Fù.ä±î±FïÂFâ¹Q·6†9sEË‚ýuÇž¸YNëpÉA<öó¾ºÉ/b­£e\a€½Â ô4,¸ä >Ã~pÉi<ÓâŠ`[»¯ø+Vîv/øã­ZÛþ8ˆbmýòpÀp¿¹£eÛ>Ï͉¾¥i½,„øÖ€«fIÎWÈßë¶nÖ¦Ž*ñÓõ¶a}Eõ”góë®ng[qvóäoa‹[ÑgÄøâO·ô{f1·b5K|#žcEËÝá ThÝr¤}¹ïˆ›åŸ† [œ±žÇmÙÝ&éöŸgÞaͧH‘pß%¼Š–{ÍPhÃê_ÂÎá»Ïæ™Ñg´8Ë·É7"ì3ú W-Ã…".Ç¼Š¹5÷×q¬ö6¾6Kåx8¿ÅÉï;¶š ÁRÍ„bÆ£˜ááü~£^ ´£%ú˜ ÝWd ósÖ^Qm6Kòî;óx8³;£:¥ø–ÿi¹‹±ÙòlÛ#ôú€L :d^›Ëuý {ZnD"Oy›÷:\ƒ÷°=s…o²¬Úº® Ã?õ§e!c…9¢-38Á±>fȪ5 :72©·å[¼OÜé2*„¤W¸ÜÑ=¼QýoËÒâ°þmYHHS‰3GA`÷ÉtÖiËó‚›Mó„ 3\=Ýâ×<ù@ _íxk ?D¦/¿iÏ·Wà-¥†Ë¨›(›— …KsÌõSÇ;ãz*b¹a¶yÏæÜøÊù‹ÐÂ^/£ÆìP±œ½Üà»—ËŽ>¶ÖmpuôY;F{¸)5{¨w¸ÎÆÅìþ¢ƒßA3ÎxÖª‚oØŽjÝ*¦Å™qw}³>K3§n7»N¤gð’C~¼nÙñ’CîÔñð¼¢f«sª×²‰jΡñ-Üaë{ÂÓÅ«9.¾å^ÓОÖDZ9¯:4ï0çí'¶î);â."c·Šh~Íݲ]ÞʯWrÒíÕØ‹lz‘{Å!P¢¡ÅŠêÅк·ôXQí0èˆ%ÕËjFŸqGާ i½æÐt{$ÒŽt¯þJ#Žº¯Èñt¡8ÛÓâKªçxòe׋õWè /:9ž¢2¤×jæ­\JL¯9t{ª¨ÿ¬äPdxªðÒö¢C«Ç(qîbÁR‘¾©Ä(a”÷ÔQ~^ª'Ìdèl7¬Ð'ZW$ÝŠÖBv§«•—òìN’Ä{¹¡6#—“/Û^nè.q±þõ²zC‘Ý©A“ò’CžÝÉB´T_O‡Õsƒ«—òìNtµè5*Ê{v';½äа>=R¦yÅ¡}Gú©]¢¼ŠgnŠwÄJÝÃÄÀ«Gv§†¸%¯9äg‚íôiØ‘Þi Ü³—² žp°êíê‘Ý©ããê‡<»SÇW®©zv§Ž¬K^qÈAmt.¬âÐö>Ñ¡—Hí4à æå†ndËò%×Ê ÙSólYñKZÁ!Oï4QG©·U"½ÓÀÖ Í;ÆqÙ½·ñ=AUüRVshì8Ê¿½_%²wO$hðšC#|u÷’Cލ±M^s¨ãéù™zØ|ÇÅrVrÈ&ê°â^+ê#2±MxS? -&êBRX/:4­Yd£O˜þŸH>^tÈ'ê‚È×­B‰OÔJÖ^t¨[Ÿ%ô¼èOÔ…u‹ùLÝQ ÕkùDݿ慨œŽr¡ÈWò™j_oh.¢ó[Ø1L¯1Sïs˜ãÆ‹n5‡|ªnxö÷áGŒGîaï‘ŒÔ ù\e~A/8äsu#Âß ù\ÝHùe‡b®n˜×½êÏÕZW7ó©º!‡yÑ¡Yãê\"è³ù’:ìkçž^tȦª• ‰K¶¢CûŽ–'¾¤ŽÂr’^tÈçjÕ8ÓÄa"DœÊ6Èq¦;.8Ê.?-pô¢C+NObn_SýgŠo¡еÀ•£¯ÒcªnìÕÓ¦b¥»þHÚ²ùÍOò‹}þ¯’_ ËäA~±MMòƒWÑA~‹ü±u<òë`Ê$?ä;ÈN ùÁa.ÉÏ®+ Žä·Õ.òcJ²$¿…89‘ߊŠ& ~k‘ü2{&ù-¸´'ù-,¼I~+.%ø-L¢?fÍNð»Ë'øÝ°’'øÝ•˜GðË€ŸÁ*(à·î85ÀÏ; ü’o ~–k;à à·2'ð³–\àç%©|‚Ÿ¢9~‹Ne?Ï-?£äØ—üÜU'Z~ÎÍAl?eTø™ŸP{Ÿ‘ôŒ>?Ïr× òSÒ-‘Ÿ·|àgŽ/_÷¹7Tp¸ò§¸9¸„},F•ØwA´Lì»Pë;±!‰}"akÊ&ö]á?™ÔW:øMÔWhcõìá’úXb-©¯ b=©¯À ,©¯`§ÔgáÁ >VæNì«Øñˆû‘ÜW°¶÷Á­áà>OEÜÁà3'÷ÙQAcÀ>&ˆ Ø—&’Ÿû jüÜ“3XäçnÕÑäçBZ‚ü<{B &Èïw“ƒüÜÍ)ú€ü^~²ßÍ*Ûb?³g„ñ‰ìwψúyݹ °@?;¦FПçÎ_Ižˆ&º€þî…Ÿ\ôwßH¿)ú3à ÎôçF‘Øx’þLøEý…¦ù•ðçn·±íü…Ê}f'‰7àÏM)±»ýyŸ¸П+í'À?¿‰Øƒÿܾ2ÿ"683ðÏ J ìü攓ÿü  ⻾<ÕúøJþ‹Ðø“ÿ|Œ8m\¶{àijþyœj & üó8UÐUàŸ»$ø§Žøçqª±;þ¹ŸG<àŸG·ÿÜ·¬ÇÈÁ~TÆÂjqÛñÚ€ÿ<ÊýÄ¿ÈÚóuUY݉=?ãLŽnŠŠc€Þeöb]Ý [UПw‰—ôç]wAyNô>ZbY•CÐ[â‰ÝÕ¡ÅQ€žI è}€žuÄ.~Í@7sÝhñ…Õܺ€Þ%~˜@?w€njª@ÂXYÍÏ àèª+È20ÈÇ8€çQ€Ý>_1{€qq9€~v\O`'ÇõºQ-@è#µ @w‰© ô£bÒƒ=Èù>0úÄQ€>NXÝ2Œ @@·ßÍ&"÷÷7ðLª“¯ Ð[0Æ “ªù¢œèÖ< דê,¸`XüNôD A’@@O5_ à«VÕµy®@@·.bœ«êBT"`¼¤_I€i€* ŸèæÇ'ÚaU¥%œè¶Ä8ðy6ð“"†Íò+п@¾ý¬eb@ÛÜÖºI/YÃ’7"j’÷þÐþ|Ë}@€¹‰%zKÿ:ÐcÇOTÚXàMçJà‘*`Zxî+H€ î ÞÌ’!´–Øo¯/y o…Sû³1c‡Cô ¬Ñè~ùAT @t·¨hzéÝ@*  õ1ÐúÔ—öçÞè1ÐŽRû3 •ŽÚ_¡J"ù/œ³ <úPþÓn^ò7w)ÿQ¾ ü—Òžä¿MAðÿ@]”ÿ*ÕÊ”ÿ¢$À¡þácq¨ÈX{¨Ü@KýË£¨þU|³Sý«KÉOKñMÿ1½D “I ÌT €%’¼‹ÿô7ñ¯ rAâ_AE„Ä?a…ð¯ utâß3dEâ_wò_iŸügÉ8^⟽ª±ÍÿYHhkji݈€ŸøW° ýY›¯þ˜;Dðg-ëÿÜp7 ø“ȸ®8 öº„?û÷ U°Ÿ²šþì äzŠ ’àO5îÖ «\O¹Ñ&ü¹ë¨õu°Ÿ__`ØÏ£»b˜Ao¨Ä~>L ¼èM³%õÅrÊ:}‚¿;æbŸûb?Ïçòu Ÿ¤ö³cÀc`¿¼²ß}¡—Øï¾öûݱƒ&øå-ü|Sùó–À‚ŸµÜ/ðS½BŸ`ðós}%÷yªÙÀ*pŸû•Øç*P±Ñ Êk!öYKܱÏÏüuPŸŸ(†™´§ê I{*í¤>â§ì¿Ê)û…¥ö”ýâƒÄ@}ºBŸž™Oï‘ÏOýB¾<‘/_"ßEšÈw³ð} _¾d¾›ö"_þhD>o‰Q|ùNù4 ‰//…Ä—s€Äw3¾HÄw³Ÿˆïfþ@ßÑâÓÓ$ðy„TðˆÏU dßÍbUB>oá•×%ñù/à-$>?æë¾|9I|zV¿‘ ,•>O£ú¢¼NÑŽ Ç\èa¡8@o`« ©oO¸ïHêÛTÅ$õíÈØ“Jßq§ÒÇTY©ôÑtxpÞÿÇ伋þ›ä<Ê-¼ @„y7Ò¼+¤‹òX#21ï"*æéRÞ…M« ï‚%ååàY>žÇ8”úö$˜BêÛôÃ’Ô·4+©ÏŒ!­ò.lÅx|,’ñ®È™ˆg¨qïâ^WŒgÚÕÛÃó¢ã˜3'Oâ•ïY-ãi‰ñJ£(Æ£AAŒWú§‹§„2rí¼ÂÇGÌ+›üÄ<¸X˜G 81p(Ìk`ó(õ&æ!nïà<¥ô5úoó˜_'1¯¡®Tb^£íG˜—Š¡”¾H_-ÊküžŠò’6 óz$ŒNÊëº)¯GÖÚ„<+‹ ‡N¬ML~È|ÅAb­ã‰yÏ· R 1¯ck’˜ÇÔ‰yµ óœ˜7† ÌcáÖļaÞñˆyÙëÄy KÐc¤z‚^ì#OÃôÖw ·PÉ'AÏ2e¿AÏú„ÿ(A/}C zæòúž£C/èÝbI9G¡.[B=[ëƒÛÀz³Óg“¬·)ëõ,cʇÐ×è¶é°gÛ¯“õv'–öæøöf½Ë"-#C'‚Ä|–ãÚC'Ú‘Ì76¥H2Ÿå¯ .$óY–¸B2ßv!Ÿ½AáÆIæ›…ìEè{6ü8I}ÎõuB]*úX÷&u¾‹~›„>«<*WÏøó}¦ì¿u>Ù™¤ó]tƒ—ÎwaÇ‘Ð'õ_: M’ùJ‡ë'™o#ü;U¾JŸ}©|•Þ¬Rù.ÄN$ó­J%ôÝ›\x@_Ø(}¨ó‚¾ ÇNAßýA}È´tP\9D}…“Ô·âSòò‘ØÞ¾ž7Üß\ÖD€7Ò"H§§$@…ð‰ñ]?0ÿˆ€XœáGq ùSΞ,j”Ξ©TÓÙs#q:{n¤¬È0?”µ?ÂüM7Ãüè@”a~@yÆùÝ𥳧x.Ãü¨‰åÀx†ùÅné¤Àûƒ/Šv'Âÿ“Èк¤@[ ¤#dR`ýŽÅ—¢@x'"ckB rgˆcÄ€ð†NwÏÍoº{6:SÊÝÕßwO”ú>Ü=\{Óݳ}(}GËáî×'oÏö!ô-–‘nI2„@ ßH@àN‡J@àfHŒ »²¤@s|Ž. À›’¢(p23ãüæ·7ÎÁY0!p|æ7°+KìpHìNA`‡›BB`Ã/.d!ÉdÀ† “dÀV?°ñ% ’ d@Æ×&â[O¤?rb à’‘ƒû @úœb„ªä¿J¿YñŸ'pø:ø¯bß•üW# ¯ðÚ¿âü m!Šó³$²ñŠ(ÎoSÅeœ_¹øb)ÎϦë©öù¼¤þ‡P¿6(ËÑÓ“{¬ôôŒŸNnž7 ÷¦›§Hnž¬›”nž¬Ü•nž‰åæ 1M>žt¶¦§Yß>ž‹\< 2Ǥ‹'¿Uéây êèâi)ßb³/$øÑ¤Ÿà·7)ð[ P‚©#ÉOªœÈ¯‰ó®÷4ø¡"ï~ÏWà7°¬üÇ%ø Zšü:ŠŽ¥Ú×9rKS¦Ü÷œ/[%÷uFŠüzTO¹ŽÊRûÚ G‘üv`©öÑÆšj_C±¡Tû*2€'ùU~jâ·»ª¿Î_—1~ Œ1~O—qÈ}òÆ:Ã? K7–1~W1~(­¿ /õ‘uìÙïw–› ;RæÕaË™=ì—Ë^ìó粎}†lÉŒ\ŸçøûÑ’¹†ýæí5–ZޱÐvŒ¥–kZòæòºsµäXl˱²åk)‘6ÇRË1ÚŽ±ÔòÏÎ:6Œìÿ0ëXùåì`ŸYÇ~>쟒uìG¯…¥Î©Ç ûów/±½ž}3f/Ž• Å8Ö™QŒce/ŽuöÒXÊ(¦±Ž”bK½4ÖÑKc)¥˜Æ:rŠi,õÒXG¯œÌ)ƱΤb9yÙ‹cý™Ôc–tqw£þ¥«¿–z¬þJê±ï^ˆ_H=Æ×é»~ïÔc?~¿¾O=ö{>‘?ú}ÿAüùW>jg¯½½ßõ‡SYžËõ¬e?L=ö<ÿ=ÿ÷ß+1Øoå{eûÏ?Ù‹÷lÒÎþƒ™ÈŽÆÿð‹¿ü¯'%Ç]ÇÖ|åeîköh¶2¯hiÑàõZ"ÈÜ»ôˆòá-¥‡Yg¡úß³òæGU͸no0³Ó†ûLõ–Þ#ŠwÁ¹}t3;¡¼ƒûûG†MXqF·¸”/¿nqÐjòÂ)qUnýòš€¾C{näÖ„è9z¡sË£ž-[ ,KõQ°žÑdø´Ü¨_¼6†™C`(sãÀð¥fZß*Ñ=\( ®h¹a‚E˜1Æ€ß<ôǘžÚ<Üüì!/¸á ¦ÓÓrÃó F¯1nÿ2¥Øn>LG¾1¯KÞ¡¾M{Za,®wZ†r„l ÃHo1ã-™íR¸…oÀž–÷ЛÈ1»?þÌBûly+*ÆWü¼3 Ž;‘•8j®ØŒV$sy~\ÇAgý1ï b„÷´llFáM7æ^¨áåZW‡¼‚”c•2DCûÓâ;vß»yÍ× üþЗeÌ.¾¶'(#ð9zôÍŠñqãëÙþ³–š³þX³Cà‡Ú6Ö*aÙaòa³ cw¿¢Å O0+Ö¸<{ËO9޽/k}eE³án´ìããÜa}qÉ0¦+~€pðGj;ý¨DÖ^æ­GKÎ5æ7(·Ýÿž 1÷-¬ãÓ ÿ´èqÅ©×ÂñðHŸVø§–×GfÍèã—GR¼ƒß¼%VV¿)¿˜V&Ä}©Ó+ÿàqhi±²šÇ‹é•V´ÄÙ­òOØxbØe•Ù¦•ý‰j.¨é3½ì'úçq¶…e5/ïnQÎeÁ=ÛÆººPeóië†áEF¼WþažVôgÃk)æ®ýq›5êgM+úsŸ&ßéEå ¦FïXWí3#¬«N½ÓŠþøL53vŒ3±®U3bäè³°®ÄxM«úÓá®ã’Äôª?(ášó´ª?>UW”Ÿ^ôgÇ rNŸ^ô‹@\Ψ±¬>×SÕ‹þŒXnvti±®|d§ýA~Œ¸+úCWœ8fbY¨¥<­æO,«|E¼æ–ÌßXV߀±±¬„M«ùSá­·àEà¸ä{…iE|®Xç¬XVBWŸ,«3ʪN¯ù³c˜ø,xÍhñ[Ñxï¸V0½æ,ŒñKYÑœ:>Ö^ó‡R~ãVö'VUì‚ç¼±ªÎ‚‹ÙXU'3N¯ú©ÿY°¦ÎŽeÂKþ¬ø:Æ¥XÉŸ GøyÉô‰éc%bž¢Lçô’?ðÔÁ©Çˆ©:W8'O/ù³ñMˆ–…EÜé5vœ<¯ù3¾Òh.fWï“ïÂÑÁ—üéÛç}â5ò’?”ŠýžHdØzB ã(k¬NÉ€µ‡þ%¬Hq™ G `E"âD@3=+ Ç&²Úe"`ƒ-0°"ì6©‡7{BÀ6°˜ T™D@rw"`ƒ·i2`ãFM Ø[ž ØðÛ%vÄÝ'†*{@`¯†ÈÊm‚@s³z#ö…ý‰(°#ÑyR`‡'nR ¡Uð&)°#211Ð\Xbdbà¸HUÄ@fpK ‘Z:)p ÃjR k&&2±qR ‘Y8À€,S•h>r`¾€Àé“ç‘ Ø:a“ h>ýTdÀïD2 ¹¼p Üo2`kD32`C%·d@›³1°ÁöœH]b`ƒ?Nb`ƒhŸØ‘51©¸ûæ¹IŽâ@Ë—”Eì…´Fœ|­ÅzEŦL‰‘;2™%ö­O ¤½01P;haà@>÷ÄÀŽ4®‰t‚<0Î?‰ÙÏ“ß q ŒCâÀ)žØâÓ+ìðþHì7ÏD4È ¤6’!9°'ÉŒ’88°’É©º’u Éð•=8^Oòƒ,Œýÿ iID9ÁF‚L䔎AN½Ó¼ X$ÍNì\D‚ŒøJ´íN°apÀ;ap`Ç—0H—¥„Áq“Ùƒæ ÌF Ö Á`^aP¤Aó’¹Ì€/\žhþSIƒ¦ F&³+»1“48!è4X¾£A#ŒÄø QYòàí_œ“éž<¸¹Ñ"zèv xP‰È„¶qÓ:ÐZ:Z°f]ý­ Z°q²zXx d\¸p0wúÀAÏÇ}÷xJ‚žj+Žz­êÀÕÍE«QÜ»¸hm n…‹·ñäA¦ùZCˆÄAå¯zÑœ8˜Ò˜Ávs*‚ YºS¤×X*‚ ~p©ÖÉ‘¡6¸«¥"Èj·T#ur ‚*A°Žodm¯õ¢AeöMA°Ã×/A=N ‚¶z¾pÐ?;‚ &ÉK Þ6l}ëÄm§ HýY<Ø•;ò`„Hœ<Ø©ï’õôă%êSœ¸sñ e’CD™éäÁ¶y&ò ¹•¾A«ÀûæÁGèäAFC'>/Ì;ñ`»HWäÁv‘ãȃù=¼qëâAš “g¥ŽHEà‡"HÁYŠàøND¤äA.GɃÜk'ÚbpEìÈs˜<ØJ<ØQSà7žWŠ‚0ö¢ ØS<¸9ypác!ìˆAJ„nòà¸Ø@d()€p4ˆ ÂqÅ‹sh‚n¡EtG‹4Aäû=4A®=© "PàЩ4¤&ˆ ù"êë„o”eW<è÷eVjm΋"!q)OSDxâà„'kj‚ã;M‰ƒvÿ1 qp §Þ! ®DƒÙ°^4ØâܤAø& ®(––0¸"-AÂàB"šC¤¬™’ DëCDn…C¤¨EœHן8h¯rœ 88byh‚°ƒš`2 °8q° ±²˜DŒ\âàB¨xâࢉ@8x7‚&qðFyÄC”š'U°qd©‚ÈMr¨‚XôÍR# ïbÃó"è) –à/âàäå -Ú=>É‚XÄl”ꈃfmqˆƒpfOœØ@8Hköƒ·Z°¸.ÁŸTAlV¥d '¾ûRNì+/Cœ ?§pPzqeÕYô œH9Ÿi)Þ´wá$¡ÄH ¼‘ #µÀ›;fi7>¸©2²2ÅÀÛ£o„ߥxÃvŸbàMʼnô§L¢?—Rá  ”uE èÏZ‚¦IÞ<úóG}@^•8xôgO+ -àÏ{„:ø³QZ|}ò›ŠþT1Jð·nÚÖ²ƒ“ÅC®Ç©ùöþlœûyS„¿uÓRCøK™ðçg¹ƒê}$ûùï'ûYK9µ@ox±Ÿ¿:1n°_¾]d?/ÔgûYË uðÆdÅ.Tì—ìçGýü]Š>`?k Î$ûyKðØ/ßI²Ÿõ y²ßbJ(±ŸÏ¬8;àÏlj>€¿ü±ùÚþT:;àOŸ ÁŸÿP[€?)âÀŸ'®|9„ú‰^¡Ö=ðç¯äË!Ôï2ŽüyŸÀJÀ_±ŸŠŸ þ4‰~Z¶J¦…õ™ôç·bèïhýɃ‚ôç§ =ô§ÉHú‹êmB?}š…~_ðuŸD~þÍ þ!ŽëúñÃ+ò³†Ø*ü¬%öôD¿…bEB?oBúù™‚Ѐ~yn¢Ÿ}€~~ªS TE:¡Ÿµ€-&/xe Å|¡ŸµÀ[us]eŸ ¤,Ùϳè„ôV¸®Ò@@öó4Z×UdûùMu®«Hc öÓ#%úåÏIôÓ;Lòóïã×~þ¢½ÀÏçØ¹O#û|„VW¸¬F1NQŸ7¼œAu©„¾üõ }Úúü©DŸÁE•RŸ=§ú¢>™‰ËY\TÉ5¤>o ,õù+É‹*=ÄI}Ö²_Ôç¿mô©XU©¾“ú|£uRߺ¹['õiw&êóôBÑgrUEÒjQŸµ¼D@o »¹¨ÞΠÖ‡ÑÍE™ñ}ÿ/{³«=Îdíó>ŠgX5ø²EŠ”È°'ÜÀ{ Û¿† FŸ?š±ÖŠÐÎ̪Ìr¡Û2w<Eé–D^\ñc#އ‘Ðg–¡Ï,`³ÎI9ô}î½G Ϊð*óùBõ£zâ¥hò`R…Lä3CˆÐD>%Zò™åƒ|Ên,ä3K(Îd¾Ò¦qJ¥3 ¡Ï‡÷«2ß…/ª˜ïšàD"ßõP¤#ò]¨W—ÈwA IäcÊìd¾Ö:ƒ2å,° ø“ú.$Nì³ ü__ÐY“úZ‡Hè³Ûó…>¦´OècŽí„>›Lè»ð¢þôeý¿oP›Käw6о(Á`À…ìë_aŸ—ï$@~c’ ’Å\I€Œšbƒ õ?EÓQÿK-’úßõþ ´d~P™Rÿ“/›ô¿Æ;˜ J •_‰~(¶w0ÀõÛ•)õ¿žjô¿›+ãÔÿfl¹¤þw¼©ÿ±bZêwÆ.ì$…IŒ½øÔÿèv•àÞݹa)*J ³Ó¤8[Ìü)Îx¹RÿËŽ©ÿÙ7áC€¾«DJý.ý©ÿ™XïOz¬LèÆÒÿl£úëú| 0Eâ”ÿ6Yò5ˆ”ÿž›'¢ü÷ lÊÏ@X¡â±–ê߃ɵÄÞ?ã¤$/ñ€ñùMño^¿ ü)Y*ôäIåoÒW5c'YO±€ð%Kå¾=Eù£'·”¿²_:}ÒSE |Ê~Sa~”ýž•²ßÜ?Ðχ¯ìw,ë 8‘/,e?[Yü*ä—ò¦T¿G~¡”ýôóKöc‚d¿IORö{½²_*f”ýz§Iö{¡ì‡lV©úÉ@ÑïE²ýlöëÊŸ)ú½/FŠ~/æDi~vPtLÑï]SŠ~ï# T¿wRã£ê÷RU£è÷2DJ¢£$ú½¨¢KÎJôÓ¶¬D?mÂJô{‘²·ˆ~“Sô{Qc&U¿:~ª~/² ¥êÇ2èEõ£Ê›²ß&JI÷㪨ê~èGºÊ©ûuá t¿…”ð È!K÷[< Èp7é~‹nŒÒýVT HÝeSö³Ç/¼%)û-<ø)û±ôoÊ~kÐW“²ßÂWî#û½?d?†ÊJöK¤ì'0–ìÇ=¢”ýÖó3p¡ˆIÊ~Üg…ì·Qô(e¿õ0²³˜–h@@IöcUø ˆT¿)û±|qÊ~‹âÒý69¥ûmnîH÷Û“¼GÝoÓ“Zºßóõ!@áý!@?êC€ö徿n ñ;Òý6ƒ%¥ûí‡t¿=¨×Q÷Û\ÊK÷ãZ1u¿M§^é~q7©ûíAü¤î·#‹VÊ~L‡š²ß¦ë# p_|e$ûmzÖJöcÊ·”ý6Ýz%ûÙº-Ž¢ì·±*Ùoó+)ÙoÓœ²ßæ7[²ßæF²ß~~ºnÔDHÝo3HTº%™þ(í¤ð·¹½$åϘI;"ú“7÷„EßíÉùU)É"“7¿¢@ýÀ¢À<‹yÇ% 7ò‚&nz€õü‰™G9Ap3[ ¸a)´_3,Á=~‚ c«J6³wF©–Lœ³,Wç#Ã?i¨9Éþô¨lÄ&ÿ¹Tf¯-{V=AZ2Ím™A(-™æky®æÏ`eɾh˾ÒRú²lëósÝ0”žÂT:¢á¿:õ˜oìÛ=©©ÇÆßH'¶`üî[÷mtåŠ:Öþ‹ÔCRýþ‘y§‘á*OÚ?~>|vïlNþ´QOVÐú}kO°ÔžÔˆ=•6ìi¶é²höDKé)¡§ÚF=ùÂ¡Ž‰–Ú“±§ÒF=Yîíý,µ'5bO¥zR¶3õT²±'5bO¥z²„×gL°ÔžÔˆ=•6ùɶ ËÞ«?͇öß,zù¬i¯‰,eåÿMYµ¾iÍ~ÒþýÛßï±ÿqg>û™Ií¯öxÿ•Œká3þß}’ÿà«ý?|O~Éÿð=ý]O;ÛšÍÏ–zãÿÙÖΧ벭óéÃ`ÞÏ7ómÿî'ïO³­½³ÍPL^˜ù| cAóÎHzìÛ­¾ª=–‚ bOߥ^Bo~Ý2;äø}g”[òâ8–÷·*Z¼64Æx7·˜þ+=Þyþé‚+ ¦w+7ø+êÚç}®Ê+ ê=$«å »$ÇâY <÷yÞ'2.ûn«/OÏšl ^äa?£ÇrùBë±Äüí?|8Ï|c¹Ü° {Ÿg $/ÀûD*š£Ž³¿!É(ñû>ëAH2æó÷‰õ˜ˆørï¬BF.ãXöoˆ‡öëû¶'ÖË¿Ìk[¼¿< Â!à}m#Öà ¢2å1ìX-wdØxßHkë^áþQ?Ï˰µ&É>ÏK‹lÀ7R2Ë‚úäðÞ'VË7’ð½î5€ÔUñØæ;£ß8û^±\üi\QA$nKè‹À8¿ ¯$½Ã=# ²Œ…%TÍöÚä€ßëŠn-Eù§É\‘±Û·nx&vŒ±øzøûømûáÅÖ^<³ÆÜ ‘¥qlÙüÀaÕwE_Ë7}a6îž%—w¸E¼Ö1øÌþ‚þDì>á€ß®óžtø´bSùµÚ^ ñA2åcyá>ƒëßm»ð{›·m³l,ï…Ý(þ¼Û}»Ý ÒwˆÎçù0ô}{àÝF‘¿2[Ï1ì`[ûfù*ÿ2už…¾I¸®6âm]Èêu^Ûoë‹ê DzáÓŠüë2?ýß»;¯öˆ·uá!93{·ÕýÌoëBìëyÖÞx[íÃ5Ü[i‰²çõo€[T¸?–okä©7Ë~@·pJ\g:ºÅvîj­n‘rãXöoH,î_®óy·Hâ çвS .Ëë=QÜáŠñ¾–4ìíŠn–ïaœ¡ ÎȲ²Fö¶Z“ƒÛ@¬eeìmÝL¹¼¬‘·ybÛkYY#{]­çmzÌ­v”wlUî;ÊSÜÑqĨŒm[¢~ ^ÕhÄAñØxY£§ŠgÖËÍ8U<×V×È®êF(êºWÌ­û†ßú²ÒFn€ËÚòÊFOÔÆˆ·Õ*ÙÛj_•¸L¯läm°µ½¬²‘ÿx7”Öå•ìV |¹–U6²·µô6¶£V5\Ð:mƶ¼²Ñ ˈ£ž˜[÷ÃçÆ+­8×ã‰ÍñaÊH£VÌ­V˜dÅumw¸Û¼Ôc„ÛçÖÍ(¿5caàMbÈVÜÈÆ7ùzm#À_ƒ%&×=À·¼¶‘µ™ÐHÖ1¹n&[^Ûè‰ qß­¶‘¿®)‡–×6WÆ lÅü}eL÷òâFÞ{–ËŠùûú ¨ÓòâFΰo„7²Š›‘ÍË‹ÙýzøTzq#”Z‰ÛãÕv”c‰ßϫ٠{¿¬¼ÑŽá¬8hÄüº8Q­'šÆF§åÕž0ÄËgÕü}7žS¯näm°Ç»¬º‘¿²/2ë¬'$åX­õzéèó+óóñz!¹±äË Ù¾ol?/«kdƒ¡ê-+kd·É­Ñ¥=ºf@ŧ…¢F6/ÆkEÞ膨iäunV|R5i-~ /id]Æ„åþ›qí#þ}_v´â;yŠïäk$¾s‡¸ BðÕÄwJÝ-¾SE@ñ*ù‰ï ¯Êwî ü¾cA;⇚=ï¼H_øÎ‹ÂÇAà»—úˆøÎúíÑ|çß“hC¾»" ¤ð΀-Kxwšï¼Lüï.ÌØ‰wŠ˜'Þ]È<—xwafM¼»à‘ ¼Ð ï®vÝå߀» ùj’î.à'Ý1gDâö „wV[éW¥» ‹¯¤;ÖMºk˜²ïÌÛ.Ž"Þ1sYâ]CÈgâ]CEÃÄ»´ï¡UxÇZo‰w >!»†!Ñ3´‰î졌Áî2¤&Ý5$ MºC鼄»Î¥ àŽcI¸ë71p—Gî: Gl×ïxÃ’íú #’í²c²]G-àd»Î9YlgKûÛݨÿ”l×á)¶ëk:±ÉÆÁWd»i¶’í² ØÎú‰‰Rp—mw*I/¸Ó–ŽèÎŽG‚î<åB´Ý)½èÎ,ñ “îÜ/p t·nè¢;ÉwÃìñ»î<ú>ޏóT¸SÆ6Áݺ#7¦ØÎ½Ý´Sæ+±ªQ‰í´“$¶óæÁm`;³ìÛÙ7f‚ä.ä0B;å&Ûy¹¬èl§Ðz±g^a ¶S¶±ÏâäÁvk†ƒ”ÐNÕµ‰vÊy/´Ó^—ÐNqÌB;OÎæ&ÚɵMh牤ܲ³ƒây Ùy,¬Ÿœdg!Àwœ dçî‘qÈÎsÌ‘ìVTuýg’Çb»`—p]9wp¶ÌÄužé»r½…u6¸ ±Ne½…už}7Úë´ñ&¬Séoa]9 XçÎc4À:'Ö¹W¬³~€‡À:ù— ë”ûWX§ì Â:ú´Ö-æºÖ¹W´ ¬Ó.Ÿ°NNŸÂ:w's°n±@‹°Îæ¢`;ž?b{W¬3ª¸à:óðb¹£ðÂö2¹Înà:ë!.\—»ràºÅ2rã­\—w€µj|C¬3¦‰½ ¨TKo'bâ7v¬+g ¬[Œù#Öå¾%°Î#ëÊŽ$°Î6-~p ¦;±.·Pu¹_º&:âßë“ðëŒÕbó%°®¬»øB‚ëÜ·ÉÇÉ´∸îjlÑz^ÅÜ\çîŸñõ®s¿¦ÜvÛk®óšð÷‡ë.¾dŽÀ;ªnëüˆ˜òëF8Yü3uþ+êé‚êÂW.Ð2´KûÍ ÿW²¢ í¬÷Õ>¾Ü1ÚÙ"ñù Ý ÐÎü†ÇGº³Bšãƒv¶P´³Ž¯èh·olÁíŠhg ÔKl/²Ñζ6¯Ú™åÛ‹?¾ÐÎ6%Çí´½(´Ó& Ð®ôhç\>*Ú9ˆ£M Ý4¿å»¢—h H#Úy­á*Ý•£€vn‰›hç{±ØÚ uÃ`;mí¼Å®ÒÝ´5õ–@;¿¨À  wCóièX¨>íŽe4ƒíü(H€ÁvÞ&ž°Ý±¬ß`ðYÈ £¢]Tv .ÐÎO>+ÚùQwUî¦Ub¾ÃnŒ÷®Ê]ž9ÐÎ÷\^|ª]Ûù7ƒíN›è۹嘷¢~`öpWŽÜË p7 m ÂÜùQñîΘñí$Üy?!sî|'(v wÞó æ ¸ó£v€dÀݱÀ[pçmV;o·tW“ ;?75èîX¸tÝ ?Š ;ï„x÷±ø¯äýÌŠwnéïü7ï¦ã~‚‚ïÜ. ¾«# ¾«# ¾«ç ¾ó~€’ÁwóºQØ |çéx7íZB• ¼óNbÃx—7xçƒ $ÞyÉå˜/wÞq,rwu0wåæï¼Í¬âݼ~â[b^Þ•[ ¼ó67,+Þ×»²ŸâX°]¾w§1àÎû„–çpw hL¶óc{Áv^xz²âeÍ^‚î¼›¸› ;YŸJwÞO,P@wÇò@Ý•~@w~®QéÎ-!sï¼ç€nà]mxç>,wyé »:œ ;¯ËÊAw~¦X ï¼I¬¡ïæÅ¢\Ä;·ôŠwþðÅ’xççÞïÜ7xWzßù%¬Êw>(nÁwn Üß¹ àÓõ®NhyÎw§ ÂRÈwóÀð¦…@ƒðÜòKî˜ZJ ‘ð¼ã‚ðÊø€xùÍ$ây¿ñºñ¼ãxLxÇ‚loDlAw§EÃ÷(è®öῸ·¸ŠhwZ è§ÓÝù÷ JÐ÷ïDÐ÷@Ü ÑNolÐ]¹ô ;ïtºó>V¡;?K|$©ÚÍF‰ ªe¶Ì…j7 •¡ÚéÍ j7±`Ýùí‹ïU»lÕN»lTítÇ©ÚÍUùÎŸÜøêQ¶ãsò$;ÓÁó©0Ç`ý*H§ˆ¢D: ö8#Ò]\´ é..H…tå0 Ö|¼1­ \8tÜ$ºë–C¢#E'ÑÑA(‰îÂîZ¹UAÑ“¡AIt<·€. ๋ËSJuf U‹R˜]R]1¤:€uá9EIª³žè-¤:³ì€³êHÿRêòLêÌ0>ž˜y?)Õ•6tÅÔ`(ÕéNP©34@(uÙJ] Ô•ñC¨+סN—$Nc¡Ngõ¦ÎD™.'—éÊéJƒÐéJu¥ …º „º<1tº|ä©Ó•Ž!Ô™XÚ‚¦ Ô¥|J¡NE¤$Ô™å£Ó¥—2u:é´”éÌŠ&e:³ÄƒG™N™%Ó¥tK™NÕ©(Ót:s‘~n>Ó1:Ètf€c$d:›ˆî rnÇeÈtR{%Ó™%>ö”éTK2—‘Ú‚LgŠp«ç–˜q©Ó™%¦"étôéNŽõµR§Ë6Ôé˜_2ÝÅ•—dº šUº‹^LRéŽeUº‹‘Tº‹Û³Ré¨i§JwqOW*ÝE•F*X]6 Dw ² %º ~Ï)ÑÉ“FÝÅÝgItb‘S¢£¬ îBˆsjtÔÆ¥Ñ]ò“¤FG‡ùÔèŠ"Ýŵ˜Tº ™ŠR¥ƒ ž"Ý1Ä.¾D:[<´Q¤£Äž"«ˆ§HwI]£JGÑ=Uº&·HªtM UºbJרzI¥kØ4•Jw ¡K¦+–éZ‡;(U:n ¦J׸].•Ž>©ÒÙç9,Téò(Êt žA)Ó¥…2Ý…@ª”éøËH¥K¤Jw TI•N0/™.¢Nw#±œt:!‡tº›®»ÔénúlJ¨­J¨›J¨ô¥J7ø1 •ŽÕ¿¥Ò Ô;•J7¤˜A¥x)Ò T~HǪVé‚w$ÒI}§Jg¥¨ÄqCåå¥Ò17>TºyA†¥J'až* NI¥ÛP¥›©Òe &ïá'€*Ë-K¥›(¨•.ÿ*ë(H¥›?U:©ïPéTZI*ÝLQ.TºÉP¨tªŽ,•.JÇjHTéÒ› T:¦J§Hªt^ 8D·,ÔÑ‹÷e†ÑP¦3À.t:Ïb}@¨{@Tê,ƒÎ¯¿•¿,™î~¿Q´rIH¦[ƒj˜NYIÄt&ï~e:OH$¦“p*¦ãWULg_›·FØy1 ]E°¢ Ô)ìˆLgq>_•ÎÓz˜N™V’éèv/£¸`gKà AØ%{1Ànoº[ŠêÂ=£@Ý€¤”P·â­J‘®_lC¨ëÄF¦ëtì#ÓÙÆRÕ芞J¨cÕ¾„:†($ÔEêufA7„º‰mõ¤::ü'Õ T+J¬Ë~Èu,ï\÷4 ±Ž~úâ:‹$íV\÷È™’\·¸¥ °{y/ì^†Á‘ë’ŠëÞÁx•¹vßâ ͵1¿1uõ¨æÚÃ×—Ò\Ò\ô¹£4×&ê Hškƒò0¥¹Æ¢J’æì;8ª4§Œ4”æÚƒ,œ!͵yS iÎrö*͵gÈÙÒ¥9ËcØKTR¸î4xeú\›‘í”ò\›¨\IyÎnÑ­˜:¿®è0Ô¹öðÙvu®=/\7CœËBœk¶²ù8×l®â¾óÿ”8×^Tá¢8×^Xˆs6ˆ^\/gc-’笇Y Î{ˆ9â\iâ\c-Šsveð q®)Æâ\[¨ºKqÎ ñ]‚8×¼ú(Î5‚Bœk,~âœåŠ| ÔͦEˆsms‘qÎRPƇâ\³P©àÀçìæñ25FÒ\‹¥Â?3•Ò¢¼d";kÜç“R欼ä_¦°¡¥æûÓòšüç2‘YÈ(«ž@–ÌùE[¦ÖIKfý:ß~Kœðé‹–ÚWØj_´”¾Îjë3*ü]úqKéÿWg!³@Pãß?JBöï&ó$dã¯'!»ÚÿÙ$d¿{Xöã8V³$ý|ìü‰ê¾[TZ±'¥cO%½˜zR#õTZ¡§L/†žjz1ö”ØSmÅž”^Œ=•ôbêIÔSiÅž”^Œ=•ôbêIÔSiÅž”^Œ=•ôbêIÔSiÅž”^Œ=•ôbêIÔÓ" ™mxçå {þÝdçñûí_Íò0\æ÷zþÝdÜcûû=ö?îñg²¿ÑãýGÉ­~æ û ðüüÿÑçúôšþø‚ÿÉkú»žþv²m5 ï?NAvnØÿ’ÿû?)#Ø”‚ì“>ìÿ£[^þùÏS=ÔÇ¿ýŸOA¶Ÿé{À>ÛçK8c§æhî¯Í~Þ¨œðbSø¬|Ø¢Ê]ð>·®±×ƒï+=Ù~/”A"›ý¶Èî¸àP°_õiÌ—ÕǰX»ÅÈû½8Ó#ï×bÿ"8;þz!—Ý"Šþü¹¢äÿ³fq½Ô 3†e+Èá}‡l{|Ô·WT)e#¶4ü¥ìíñп\œv„Ù.[þÊ0èc€ìºþ^žT åâ³pBßCÞq™ßö¢°¿2ãÙö ¸"Ån‹gY©YnÛî¿2#Ú¶\OÐãçX^>È ¾¨ÜÈã &B Î"Èt•ÃC.³lsBl²¯è·%ôAn´¸•¶‹ëA»ˆ÷9†ÐU˜m{4K®h1BW1xÿÛ$˜_ž)ÍDz T·e)©Ñ¹Û¶2K*µ³Êì¿2âw{ú‹_…»·§ öZ¾ßÑ.>ù•A¸ÇÒÚoO}7Ë,PB‘/ýXz(+ç‘¼Ñæ†þ&Ç0BZ¡¦i–£ÇÓv,3ä•¢cy *òÔoÈ+1öfY¡Ãøs…º2à&p,æSÔÁ³ ½Ûøm0Ë %nÿÃ¡ŠžbÞ1ô;t lË=¤µù²Òú —ñ5îümÕÇeØæ±<…¯ç†e…<éXÞùŠ#Ä@…>úö•÷ÁËÙ(ޤ÷íê^ÈC½VŒ¶·»([çï~U•Å (¿û¢Á (#1e„úà£u,34Pªš!DЂÀ±<¡‚¾Mݼ!ƒ2 ôXÖÅ:¸}…ú>üÝûžÑK‹áÝ2»¡ä¦YvDB?–rè‹4×Çr^6TÝwè¡Lþf–(ƒ°ù},#QF%ËD8 ˚苽 ³ tÒö±„ú„­åó÷ Y”;£Ç²C]ø8š%„Ñ…uóYÎ\¡Œ¢$Þ1´PF­¤düúVXÈ/ÕÃ̲ xޱÂBî××ù6Za!¾Ä‡õXfû ùÑñ´Žé äçów”²~ñäY]¡ý=u…Öæc3Vh¤¥ŸÄë—i……˜k?޲ÂBH˜Ž'É !7]‹'É U·¼c¹ïpíü@ÌÈd¿u¦±â òËŒÌn¶)†ç¦s%^++„(R¼„Zù¼‹— ËôuÇ‚P òl—Õz¢üT^Wˆ>çÏ6éâŠS?ÈÕ.^µ2%Œ©éÌòÆl<$VWÈÓäéu±ºB+,x†­®g™Óú Ðб¼>unlÞœt¨ÅB5¤æ·¿ÃI·!mY»^¤„Ê6oì,0žvŒnóNÝ1:ÜqT2Iõ{ge…zHªxPVÈN…‚Õ²+èX±Ë3¢Íæ½9këhq¡—×'ÒÝõze¾8¦_gýòÄy#Žr¾ÐsñMXtûâ—d…‚mbá_Ptûæ$¸KLÑ×,>•Zæ¼÷k!žøžü@®Hg¸ùP£°ÒۙŧÒ}Ã-ãXR|ßøuí»³~e¨ë±„³‚b|Ͳ"8wp®qg³<¼–$ñ)Òñ±tŸO-@O±Ý¿„Å[ºoƒ‰Üèh§ÞPt¹¯l–W ‰Î2Ä­L<$‘ÙÍûÅÓçjotó XGÞ¿UU½5¯,d¨ÏŒ-*"ºsaóÊB!ŽwXz¤tH¶ÐšÇj…ßöª.jþ±&jòË®0ÌÈê6à¤Ýì›QµÙ;ö[Még–Hì6Í‘_žM0&ûü f×`öæ%ÄçݺñK˜HÍv,ͧT³¼1îõL¤_1‹Ï©v·â[£¢‰˜·¿šc,ùí6]¥òÛÀ¢ü†ÌÉo\ý‹ß°*¿½ÈN$~³#ƒÎÀoL›'~3²®¿½ñh ßÞEø¾1™ð•Š€oëŠ%µðmáñ¾­X±‰Þ’/‹ÞX+\ô–ôæõ|.”:G!dâ[’ªã›h Zë(û@pu|S¥Xâ›ÊÔ’ß”†›üæ¶1†à7lô÷]ƒÞT>žôæµ2£ÅFV7dÊ z3PÞk×KPnsAof•Þ”çŒôV AoÊ Nz3—û¸À7zܓ޿AoÙ àM)Ï‚Þ^&ö#½Çz“×¼èÍÖ½Ñk^ðf¬£of™_xcÖ4Ñ›ù¿cJ$½]ÉjAoÖ ž ·ëâú‘ôfK"ò\Ð}Ùà蕞G_ö¸ëià˜- ®´Âq'"%Tá¸;A„cÕD¸ëý‰pöIá臞Gód¸–pŒ»Ä  ¸KëoRܵ¹T ŠÓ!„8:}“âšÖ¤¸ÖIê¤8l—$ĵÎ%)®X@qM«qR\ÓjœW-ÈকAP\\‹“☯-)®i™BŠkØ‘KŠkŸEb\ž›WÚã˜31®½¸Ÿ¤¸&8 Åu­Ïof†ÃÃIŠëÏ)®káBŠëÏ)®7.¬ˆqMOŒë¤kR·’âl1 ¶Åõñ“☟×—ǼIq…Í“âú#ÊÅõÉߎ×ñ”×Eö¤¸ì‡×ñýOŠëÚ!ÅÙNÖ"µ!Ý´Å•^‚âlk wW Œ³6®W¶È€qÚEÆ•£€qeÓ,Êò\8Î6Èú‡ãl|¢¶Øû¼µëŽ«ýÈ1éœ8®ìÅãÊ~ÝCÇÜ'vÅq<€' ·åSX€@Na¹²É+[x 9kƒ'$§P‘œ¼‚Eråì,;:%œrà‰äÖ­}'9&äÈ)'ž@® WºÈYtž€\µÀÙ|$ì¡òEnDä쨛–˜UÇË9 §t€9"äF «gzµ-Š÷$ç˱ÉY?„Ñ ¹²Ç ’ËR€œ²ö äÖ¯ä,#nÎŽÂ7/ §À‘ÜǂћÏHnMM@9Û‚m”S„„P΢ð~€å®–Ë~ÉrÊ;(˜³Hò_ÀœµÐ&`®ZæjÏsk"Ñ‘hÎÚlPWМbDsJ"(š³ñ¼°°H0ÿFrÔùŠƒæ½GEsªÂ,šËíhÒœãc¡Xm7“æ¼tp‰<ÿ+™ÅtðåO ³mÑ;·µE¯ t¬°Cn  Ó)NÛ¨:#‡» …è¬E0€Î èèA~  +}Ðqc6x®üóK¶çò2Ás*ÏJž«†Å1aPãd ·ÂWMjœFj\þ 5Ž[ÐPãòß¡Æé"s–s~Wœ3ÿ§€sJOœÛ,ÍD¢ÛÉAtö6vÝ^¨=Dgl^l).ø ’èN×àX/6g8 èìëp‡aDºŠ†ú¾:ÏtÕã¬3ÒUø,- óÄC¢At™óƉn^ X;C s¢ó M«]fV"Ñe. "]&"Òyæ‡ºØ fú”e„[\»8AÒËöÍp³U`Ñý»ù<éÜSD {ï~αÙH7Í Ëó@:÷Õ¥ìåHçm°F ¤«=Ò¹/1®*ÎÏ#˜n¶{rJmîv;w‰ƒéܲÑâ Vºæ’éÜ}w=˜Î}Ù3Ýlà!Ò¹ã+VÖÁtÇró¢‚é|xÀ¯v‡G+ÚÁtî„;Hy+¼ñ+ÓM"ÆL÷±Ìðb]ºê€:÷aäPžpd¥S"¡îXtuç¨ñ•æ¼MKinÚ•òêÜ3´W¨;m^ÎÊuÓb ÈUu§ßE\¨;ý\¸¿ÁtEk0;Çœé¦ýZÍŽ­SJB0;ˆb™}»û£ç,˜®ÞÏ`:˪Lç^¸ Ÿ+¼[ßp'ѹ«*%¶Þè)ŒMŠ@:÷&VÝp‹Û™@:·ŒŠtîÖŒå!ÝoD ‘覅‡`;ˆÎ;y©ÂÅ+8bB]:e“輟4t…£ëÀ§™DçƒÁ¯Dç—¹ Ô9ѹõ[‰®Þô9à •0ˆîÜO} ƒèüG˜•èüžã ¢ó‡è@çÞ§:Dp+&ÜÈõ¤Ïù Åjùq?òÕøšÏùÏÿá9w4n•禅ÒthaÎsæ:ÌCt[‚æü-À·3hÎ}¹{UåÎQ7 hÎßd(ÉAsî<`q§r‹ÕÄpæN/4w,oxМ¿ý«êrÇ2yî 9“±ÿ4ç7‚š›ÓœyG㥠˜ó“c¹0çÄS0—nÙs~ ÙÍiî3§9?5>äAs~‹ÙÍ'ÔÞø„̹C8•;:™/¾>sþEÀ^p3/GÝ1ŸžQÌàj~Ì–Ë,J¿p5·Èè÷‰ùtߤãgs|Š‚äνü/¸›/9fÉ¡tî™ÉùO@5­Ådúö¯&ç‘ánýø”Êù[K­oÄdZ,‘ ÕçK¨3&SKV î‰Ét5aÚ“éûò{(W?ÓrÓCܰc2=Ý j7dK0O‹ÙtpE’sË)õ˜O’;°Xéäü*N4b:eA®|ÜrÞÍCîâ§|=#ʲgÍzÕ¹s B r>š§Êr¾HhU–óØ¢É ŽÓ³'@Îìâ-”»µ¥ñ4ËBLðÁÛÞ¸xCr~±Û„L-v#W‹ÝfȵB·‰Â?B7ò²ÐQýB7Fí‹Ý&Å9 !Wè–†‰‡xx£û”à¸-x›ô$¼±ä¦àmJ¼©S›ú ½e‹¶>‚Þ˜¾ô6Q9Wô–À™2 p¦ÌS™2[À›²ÞÆ7å¤Ç,½)5Žð¦Ô 7eþ;¼)Õ%½)óxS¦Þ”i€7%·;äN™-àN™§…;ežî”S^ëó‹ÑŸ2»„?% éOɬéOÉÓ¦?%ozúS–6äÒa•å(HrŇÊrÔóc4äÊ™ É•^ É $¹ì—’Ü”³%9¾4)É•6äøÀ·JKn•y®ñ|{¡[ež‰šœ´4Jr[èI®p”ä1š’\»øsR“K± ’ó!Q’+S“ô‚&''5irr‘“&—BE9M¢åà…4¹G°FMNjš4¹W.›Ô䤯A“S irúI¤Éé¡¡&ÇâG©Éõ‹Û¬Ôäú%gFhrÌAžš\±@“K©Œ¢\µ@”»å~é¢\—[D¹!õ¢œT/‰r©ƒQ”ÓQåè“]D¹‡wGªÜçFªÜÃGVªÜK"’*W,¨ñDÈ£*·DcTå¶Ô>ªr›÷OªÜ¦RKUŽ¥¡R•+¨rwûé[ÉšN©ÊùÏêŠr˱Ðäî[~”ÐäRó’&7äH M.e'irò(”&'l–&—„IMNÞåÒ侚Ð䤜Q’“Šœ„))r[J¹´P‘Ût $—~í”äªå¥äÕ+Ĺkö'“å¼”à\’ë¢PHrLœ’\Å(ÉÉ3‚’sl¥$‡[E‘“À%EnòÁ’"'¿z)rЊ‚œ…1Ñ•²P“ï¹±øàIK銂œü+$ÈÑ__z§ÉqéI9N[”ãÒ…ŸrÜÔ$rÜì‚/f€*̨+ÊqSÎÖ”ãR£W-‹ŽþÔ» Ç¥ë¿ô8ù}RcÖ«¢Ç=ÜA„'g éqTœRË6Ôã¨0¥'Ç éqšL¤Ç¬[œñ±ã%=Nzô¸-ÇIèqÏõ¥8_x*Åy¢ô8†8HŽ+AŽcEû”ãR‡Mrœ­¿>Î•Öæ+ÇaCIj3»5ŽJ¥Ô8>²)ƱjqR_S‹£d«ðÀ׿‘=L8ÑXç˜8wáÂÅsÌy)ž;†Ò[ÌPtIе+~½œt\ª è8 èèó ¢Tëtü|èˆ(:ìkèì» èžH["žcÙ.ñÜ‹)(Å8 •ä¹w1Ì <·IªPãx7És¬žÛŒJ#Ï1MµÔ8fÞ–×àw"5î¢o$Õ¸6¾<ç’×o:\Bëðƒw#îIjÓ˜Hˆ¹ǺóRãnì P›ðÕ!Ω”8qn)Ëðìç qÎì œ“‡sà\ù÷À9û°=ŒsÖ%ÃËç,A¼Ýs;¥àœÔKá\|Ý4gU´Ù$hnk›0g½ÐO3`n/9·;ÌíÜÌí•B`ÀœªZ æLJUŒóÂã ˆqv±Ñævî(æv:ŸæÌrW˜óôe˜b!ÆU‹§«ºäÄ1î*^šj)i2‚g¹ÃàŸ1îJ?ˆq–œŒ=‡wiŸbœý^Xö@ŒS"¨qª›%5îJ;WãTŽIjœM?½zXf-©q*Ö#5Ne:¤ÆY ÈPãj›…ÂÜP¤gµ3ÒÃÒ¹«‡¥jyK‹»´ƒ§º’⬠¨RÜ•ZÐ⬛VYn^9ÕC‹Sº2‰q–x¬×09¯­@±Ðs¿aÇPZÜÅ]iq–™ìƒrÞÉúˆqvãæB³w€ 5ÎNET 5Îæw jœå"#†wùÔ; ÆYê|sG¾µç#Ç]‘ÑÈ-!ÇY¹«†ÉM[I|Ô8[~<5îzõÆAóåG%¹sÔþúWúQã£ÆÙÉŸŠrž+ ßWã,K(jÜ•á‹Pã®% jÜ•ÁŠPã¬ßVYÎo˜rœåJ»+ËùøT!ÇY¶»ÈqvjþrܵS%CÍ+ä 9΃ߒrçO)råF@‘³D€›Þ”®È][Â$¹ø²º!9k‚÷‚œYfºWº+¾Œä˜3Nz\9zܵõ²P³·TzœuL! …X¶< ÇYÏxB!ÈYþ7 ‡‚Ü¥‰‚ܵ(» gÙW¥9÷Æ ü‚\=&9ËÏrfÁh¨ÈµÆÏ¹ÖùkR‘»ä ENõR‘kƒ’!¹³d¡FçŠ\›ØÔ  ×ÈKAÎ’TïJÌ]qÎO´*ι+ &jrMÂ>5¹¦O5¹ŒŒ¤&×_M®wªà¡É1k[jr631,.4¹.ù’šóÞ¥&×57S“ë©ÛA“Kçjr÷àý¢(wß’Ó.œiÕP9 ‰Š¢\ yå˜0E¹;]'¡Ê ”[KUîæD Uî O£*'÷©r% ªÜ¥à8Wåt•Rå§©r7±_ª\ôQ•»%PR•£âVT9®9¥Ê 8]•ìa­½î¡XÒÁÜ=¶º3},5ØŸ—­Øæ?™@¬whSÿø»$êrKI‰ƒ¿K²¯n×§Zj?a«=ÑRúº[l§•+¦¥ô[éK–ÿêb­7ߪùÏ%[ÿ¿L öKóÂ'ßb?=¨žëó0þ#û*éÁÐWM"ƾ²ûú¤‹¾j‚°èë“F }•Vèë›l }•aè«&c_ÙŠ}}Ò¡¯’$ }ÕTbì+[±¯OÂ1ôUÒ„¡¯šLŒ}e+öõI9†¾J¢0ôUÓ‰±¯lžþéÄšù}x£ÿ;ŸØ_É'öW>éÿøÝÇù>àÿøÃ÷öçGýOÞÛßõõ·sŠ5ó=ëôÿk'+_ÑÿõßþF&±s#wäŸO"ÂÂ걂 y¡ŽÅËg1FûüÝ£8ÖbÞ—îJõ±ÜoU/u2F„ùrŸ§y|KIÿe–q¾LmÓ,-Oÿ¥:\öû y1>Åv/拥ЂӃ¹ÝŲfm„Þb·~ÃçÕŽ¥5&íºhÙÜä ­ YZ ‘¥ªÓ6|«Ú¬Xúû+K™%ÄÖÆ”JͶ÷» ËB¯ð«„~6«à’¶â\¶×²¤Üöz(hóÜbë e¥_—B cIÚ­–÷úU„Þ~ÁçAòp÷ªÜ¿\è}Ñ>¶ÎC›ûÙ(¶z,ãNØm“b†åÁ¹áóP-‹áƒG½[)®vcs„â }1|0 ®;CW²»¿ý¯¬d ÔÓ¡žÙÍ/þ M—ÙÜíAÚe·…û,coðzø÷yQæ»q¸<°‚α<ó#óõ—%áêæn ÇË ØˆËÓõ~IŸÁïíŠcø'œ–WâXú D¶ÐÉÝ¿Î?Dz¿Ù9襌†ƒæ ßÌ Ë#Ï¥C­=)º}¥Z(Y!Ïö‡çÖh¼^ÔÃäCçïðwxPF¡õû ©õa"‘~Ãßá¡gʤZÆë êìèºï;´Vh%Ç0âM~¸¹ÑïZëCw‡c ­µXžÐZ:RôûõÓÝ¡ß+´VKR CH­¥ ¼$Ák}\!µ¾z¹¼^z!KH­/Ò×õg¥ëã¥õ¥8ÐGÔ AiDû;tV¥ëîÚFëã ¥õen”ó<@X¢#鱄ҺûÚÇšŸðŒJkZæuQ~za¡õeàC·â@ †}µ>ûúTHÝJÍh€ÇuÂÝuuŽeLf$Ã7eÂÝ¡Xž‹)É0x;,æñëÆ0=­ai Kã£v謋q­µ”Ùì,KsxÝj¡E(ºÝjí_Šä;†þ~‚ÚŽå¡Uy׺•B$\ÌiÝJù%ècd¥ü8ËõîJ¡Ö­6P o‡Òf½Ñã…»Cvk•<§ÓÝ òð¦aGm Ú $âM‡¾àï°éÝÐDâ2ÈÄ¥gèÄ›ªS_yá¨)õ ¥xkØ yá²MC¾¹úîH ×øÝØH&ÅÚ ÇBÁ˜ëž¾‘Lªôɸ…lR—&— ÑXQvU_­ŸP4ú†l̤yU_ýÚü ûrݸþý27_¼Í÷åX»¦÷é˜õMÌÚ±|_P/Îl÷ù˜%‰úqi™Õx 2+PË;b„yT”-æÚü6]`D‹½@EÎ6¨úZ®¡AE¾0‘Ý(ûjÃâ t7ˆÈ“…Ý *²­ªÑ1TdV²6KÈÈpÞ 2²å¢‰6—‘z7ÈÈ¥_ÈÈ'Ñ»AFÎCE¾"õìÆ+Ã]tE¼;D䯷•jÅáX "7&׸½ì«¼ìïH Wúº¯¨Ÿå–ð®l•~Â%8Ójƒ©Á ò¯æ +äç>½ò—ü˜DŒä÷BÞø½ô³ù½r|ù KH~L6ä·¸:ù-zÕŠüŠè'}©a02P1]ÐEÞþ™è§ü`B?³€Æ€j)¡ÈÏ,p–ù%ül«;ç?%øÉÑIàçšNàg¸G9øÕ¿ü̼øe/¿W~¿j ðSš2Ÿ üÌB»™å;þÏ·‹ >ÿö¡>³`!ê3Ëý¡>³`Ùê³ iêSºqQŸ:»+N††\qüD‘ù¬[2\_õ4@>¥jóÕC&2ÆËûÛúZžÉñO &¸O9ßÄ}fÙîSÆtq_iî³6Xç9÷Y °9ÀÏ,˜‰~vÌõ¿Úo€_í'À¯\ÈÏúy>äg–ùA¿:¾iä.h ŸY°äuô«£ ô+ýýʽú•Ñý>–ÍñáL@¿j öË­)²_í'ØO)úÄ~ÕòŽ’¢Oìçõ$ÑKÀ_=wÀ_97௴ü) à¯ô ú+gýUËøÑ"è¯ö;'LJkýÕ6/2î繃þjÏAÕô§Ôÿ¢¿rÀ¿rvà_9—ó_í%ø¯<[à¿rGÁµ—à¿òû‚ÿ”>QXÞ`y&€õhy¼¯€e4Àeóp&`¹*`¹[ Àz¦±ùœà×Ö~žñ㛬mÞÍ⪜ë¹÷àø`–^€€e4TFËQ]ï"~O `¹@Àòµ–ß XûAÖÕ¼;΀åÖ^x5ï °^R¯æøÀ€åÉ–Ñ€KÏ`ÀÚÏý|îÍbù  XÛ°„FöòLŽgb ݉Å*ºªÅ2z&Á€å~K0`éÙ°Œ X[–sƒËs¬m“µô X® Xz5¿Ò‚Ô¬åvÿ>ëy !ÐZÀÐÆ÷È€y³È€9`2`þxdÀzj¦hm"P&iå€É€µçw|?(Á€ykÈ€ù&–cÀ€ÕÂT­ °œ»õÓ+!0?Ú„ÀÚÏø1½«åßѼíûÉ!Ö~×óóöÍkÀh€‹¦×¸9 ÀœHå§r ,'–[ LÁ‹X-p>جnB 4Ëõ´ýÔeâÀÕn Únî êC´³êIÚ¶ìü(€Jh&ÌÚÁÜ%.¹Vm_“77óƒ}AÐ+1â\z^“PdÞ±ÔK›ýÖMVi€Ú•XÚ@\Œõ’XŽ‚XÚ@4ÔÔA,GA\to“˜×@ í©®Ô(¡–^ æž/5ÀjAn9m×R\/÷G©êÜÒµëK 0 ®–ó@\tš“Èø‘T—T,*€¥ @Ô3NpQS£¨òWjjó)æ¾v€ê–úŸn¯Àb¸¶TCh€yIÔË`  D@›1Ð3DÀÜ1§¸è'PUR nÿIÌ=uª€y³¨VK¨€›y‹¤nFšKÌñQÌ+§¸™îR:`1tÀr®^ž –sSÌ;A0û¥˜BuÀÒtÀ|(æï@!0ÇG!Цƒ¯XÆóþ1„ÀÒ/”ÀÒJ Þ( ¶w¥%eôSQÌn¨Êÿ[J`ž<”À¼ÅT󇢘o/•À¼TË™ –Ñ@ ̇‚J`ކJ`^¥ÀÒ†R oNHåHÕòò)ÁeJ ä+N%0b*¥Júq%êÑ’¨ÑA ,ÝP T7PES* H%PR•Àì„J î¯”@]¶”@μ©¦Ê—J >mR5H Ìs­ï‘ø’£)æ3L)p1°¤ÀŤ’s4”óvQ ÔÌ+)°ô -°ôÌd­zåC Ôl--0?ÎÔK&lMÉ“[5jÙ†Z`ŠÁÔ—\H¨æ{Z`9†i[5ÓR Ì»N-°œZ`ÞQjåÜÌßšý0«ÄéÅ Qõ¼3…+v…wÓÌz¬÷ŸS+8°ÌÏÔ«ååøHkH”Ï(80W~äÀ%¦ÖÒR±F10›f'ÄÀüaÈÕ‚´@å(ä’þOÌ%/9PImÅöoZöwL´~,ïø.‚ƒë™Öæøx&$Êñ™¡WX.˜kWb î')0R`97(°ŒXGóŒÏX¨œÙ² ’å}æà€€Õ°¾/*0_"`žÈ °œ˜$@³\̯ °Ü 1 ÕÏô,±/|Û*öYæL`“\)Ùv`_ùا4F¾(ô(æËŒd>z† ù2U‘﹊@¾GQ2D>…T ù&„|OªŠûýôBäË´ D¾<7‘¯X€|™ÊÈ÷ÈE–ÈWŽòåhˆ|Ç‚Xúu¶ý½Çâ½b¹ÇÏ6£ý¸_ÞS_^C_ù;óÁÒƒô]?¯a=?¯aßß輦¯ZÖßÐWÚôûÇ5õÕ¿×+ õ•6óÇü*êË{Lê+G½z§½?ÿbž´$@Kô@UaÚÏTu¿ÑÖTbF Ò˜%ªª˜P Å€ª!&Üܪf˜PObÀLQGTÊD0 &&^òžfZ;2 ²Ø3g°t,m€€™ûŽ8)RsÀDÀÁ=u `9P•Ç„€²§öω€°´ê\BÀr°XÆó=†( €¨ªgBÀÒ P÷FX, ÀjYŒ[/Ð2R`±0ôoÊó2Bÿ¸û§È¿lÀÐ?Æä(øO¡> þã&]ÿ)@ˆ$8·£è¿û' –£Àƒy”¢ÿÔ&x0{!–àA…3‹aó `ʲ ¤& –n¥Yed`0oa0oaP÷3Xpp÷L,¨DAÕ" f“®²‡4Ä+ÙþÝÌñs´Á-A°´yXõ0þ|? kEySH<˜ç  Ñ{à¿:ùoÜ?ùoÜâ´Ñ>##ÿ•cÀߘ?ÿUKÌOå(ð߸ò_ކü—mÈ9ò_iÓï:‰ÿTYSü72¢üWŽb’ã.Mü—w”ü—ïù¯ŒIŽu/ÈJ<3Í1ÎüWþnšKq ù/¯üW,à¿ R&ÿåøÈÅþSÒeñŸ%¼¤¶‡ÉTWõdéQŽÙù¯ô’…GÉEà¿jÙßõ üË'‡ü—=“ÿÆWêËG‚ðWae=ê„¿¼¤€¿¼1„¿2\À_iø+½þò’y«9Â_>~„¿ÒÏý|{aVX]%á¯ôøËk ü•~y „¿|yå„?eïüåÙ ÊÞ øË~ ÅøË«"üåˆ ¥ à/Â_>„¿2bæ9Ξ¥ç­WQ°÷ÉZ.øÓ½üé·ü©_ÁŸ>S‚?]ƒàOãü &µü à¯ô øÓ/øÓS!øÓ§Cð—WEøËk üå™ú=Ù3á/ï áOO à/¯œð—×ðWŽüå ü)ϧà¯ô øËÑþòL„?^ûå…“ýÄG`¿ü1É~嘡¹•°_žèùñ& ýNÄ‚ýX¶ºæS»=ïñ¯’ g¢DæSƒå“OíO+ùÔÐæ?™Omôõ:ƒ,%l%-,%Úð<Þ¥§ø»öc–ÚKü]úˆr£Ÿ+¦¥ô[éI–ÿò|j£¹—ã'¡ÚŸf;k·åàéžqí48oûS³ýIÒ~ÿ Üû^åÅù>OvGPŠä“J-úš—ùÒ-µ¯Òj2niž†ÅÐÎÚ,Ÿ¾²ûª­ØWI3†¾jš1ö•­Ø×'e߇³ú¸wé‹–ÚWi…¾j«¿üŒÜVžÓ~‘?MFvýº-¡éùÀxήoF¯ÿöÆ¿þ>«Øvr&ïŸíæ¶û]J±?x¾þ UØ_øZýãwß?ú6ýãŸÞß«?~zß×ßOvGÒÖÿˤ û·?êãßþ³©ÂnK–ßÿôóÒó)"|Á²ß{˜9Ó@Ìmñ7¼f, ½Ç®›6‚_–’º­·\XçÞˆþ}éw,‹1ä±?8.†ÿvø«Œ«EÐáâúf\Œÿ¥‡Ñ±,ÆoXl)až¬ã𯅭fžA< lò bó4ë úTÙªa‰ž‘ëÅ€WЧ%dmaÙAŸ7sK쫹œ‡Èna‰Ü`Ç"­"byÇ!Ò_žb(€j4lý¼L5¬#×Ðï@’ .¿†çžŒ´úÍŸ³æGªÜaõp-‡Â¹‹‘¦w´Øü±íPt¼Pæ`#@nXMR¯%ðà©VöÓ’(œ'9R<Œ~Y·/·ÃG”C× .ª÷H³n‰¤a@Ýq.LG¿‘e½ÃïpôuÇ­TŽš‘eýeúäcÙ‘ÞûQ?OdY·*¨ÎësØäé ™¨æXVdgάs{Næa²OœiÞžfÝrôãݘ¾ 4‡½?h3<ͺ?ÃôM 3÷½ðióñ4ë¶g®Kcú&ÐK²ùzšõao>ŽZžf}XÚqŒp{Áƒy7Î-µ3-RäùÛ—RÓ*Ã…¡y–õ©ÔyãqeÊÓȲ“Û³¬Û}ÅÓöø6_úždÝö+ãæE= z¢ÇS¬Oû=°Ø‰o–¢VÈG.}h·þêà Ùà¢N›Í/c”šs1ŸË°š@Öæ<üøGQ céüÈYU 3üç¼”ø GY ?†k…ì&‹Ë « äãc/ÓÓ«Û½ QÈ-Žy=Áúc÷ý®HÛ{žu¼qžã´9?cˆp# Çäæ×Ò’hvë‡ûÚ#J6/|»½ãáÜw#ªM+¿€‰ÎÊM[:Å™£Lß<¬Q'húÆjŒÅüPG„Óx¡ õÜðzrõ!9pD¥ xq’«Þ׈ZAÓžóð®õ¤Q6þ¦opÔ òk OÞ3áùgE€õ‚¦×œè°xruoœ:*ù2ÔØ®ŒžS7$_Q3È|··+£çÁìÆ·~¢ ÎäÂèŒwÌ ®‹ž&7¿Q8hú… ØþÃ^˜TfÔ òÑÅ~Ѽ\=£ãü:£nÿŽñÈÌË…Q¿yñpÎ(t,L]xžVXcÒâÓ©•ÑØèÙ…Q?êA?Fóà—EÏE¬ÜfTŠm\¶G>`ÙñÞÜš¨d@üP^éÁÚÌç74q]ÔßÁ×EýT‘€¢pèˆIÃ3ä?q»޲ÂAÏ9ôÂ1®‹úÛK˜‰ÂAϡ٫µt Käµ~Nƒ³¹,Ᶎ+Ø>žÁj6—EýዃP7èQYÐ3eûlúØÒ–¨d/TLiÓ+Y9‘Èe7Q9Ⱦ©xlP9èºWÝÇþ®ÄöÛDå ûV_ë¢çÆéj¢rÐ㿎\õáÅ®ØDá ^ÇÉ]6+ÄRx¢v=x&îÃqçwÃü0Q:ÈÆSû¼]õ±à·Eé Çò7 ë¢~Ý–(dåXðrÜ.Œžž™ùo¢tË:è9J™Ô‚ê~_~+±S‡êA²îœ5†i½ºÈØ—°ñ-ìî¹4:M°‰O‹v3˜¨î/g ûÀP—à·~‚_üIêkøgR+Ž%õݘl’ú8a&õ n°’úŽå úNw˜~H}/=PD}¯–菉—5ëE}Vú¬8üLü²‘ú,#ÏØçùÇp}ž( g ìó Fô³.¥®@?ëe¾ýl¤ša!MbŸÍȘ¸€}¯’FûÌBôr컘÷VØw1\JØg”ñÁ>/ÛüÁ>K,Í6Ðü;ãcˆ}fÁ¤ ì[ª@Bî³jµãÃ}îgsm86Úåî7Ð&°Ï³ð {hŽ/3-€ûŽ¥“™‚ûœw±†ëCI¸ÌྈŹ ûLÃÃÜç žë‘1ð®ÜçDŒS‡ð¿»ð›àVK¸Òÿ~˜Ô7Ì©è®9õù ‹õ >¯ÑGÒrìsŒÊöyY<¬ûû†)eØqì3= ‡ö™n0°Ï0šöYY·ýÁ>óÚ8*°ï28‹KöYѳFKÔÖZL•Cì3 Ï,°Ï_$XûšªÿöÙÔ„öÙÔŽçÜ×”“ÜgsðŽû¬zÐ>÷µÜ÷y]" gpŸ \_î3  ÌÜg>C¸*¸¯Ù;6Æ}íeNrŸÕrÁˆÁ}ö2À}V–å¥Å§*óõÁ²Ü×mŽ ÷™ ì³Í6 ì³EÂûìÕÂçØ×§6mûüåÛøÛg*S¸®÷ÙtÇÜç‹Ü×-Ñ2-¸Ï^¾˜o~fÁò³›}@?{ÿðà8úÙpè×_†’þn+^‚þle‡ôwÛ“ N ú³ ²TÐßm¥ŸÀƒA÷¸Òâôwç=ýÝ&x‚Û‚þ쨇´‡«\¤A§?[lt´ú3ÝwôwÛ”ƒ3-€é¼[ ?[¢LX‚þî‡ôHÃîx0èï¶â§?Óª0ÿÌc @Ç?;/=øï¬"xÁwnz€ÿÌo Ó ð¶“ä½+®A“м¾xJæL¤~'KI'ú6H-ÐöðepEì€Ãê·ÇÍn …5Ð\¿ð3€í¿Šº$ÚøˆŸ€£‹ÏäÉp^jb8¤ý“‡ëÞÿLôo)‘Ðп¥ÀÆ@s*ÃAÁ6’ lüw>)p²"ÿyDZ\ÿ î=þÔ¯Ãò EàŸ}a ü³²”„ÑÀ?Û:k ®À?ûö÷þ™%žàä?~×Ä6§øo²®´øÏ¾ý ç?so!€ÿ†±P.øoÚSŽ6€îà†£àÒ{ý@Û¤=Í¹Ž†eÌ›N´M¬Xo§Õ-%î]±OÃ"•€æ[÷m“ ô6à´À(¿ùÏä¿ù FÿÌûîýàŸM^Ëà¿i•9I„ol„i¯üw=²࿩u}ðßeþýÆ0ä€8W7@ßb6-5,@+<Žž€­«gàÂáÀ¹Y^h‡x_€æwÈ£¶ß –³!NÖÿ]üÊ‘ÿ¬[ ûëIÂçW|÷Y骉€‹%:…€›ÓkPàòJ¨ÿL´I„b Ð2͇!p©D&Ðz>ÊŸ[@jpùVt2 Å+ìògì€-‚áù0 ‹m…WÖ‡½tχ0™QúëÚ,¤ô×YGSÒß%!…Ò_ãçLÒ_{Esþòì”þº¤5(·4¦@Àózb-E-µ@Åp`ß”8Ä=DÀÁ 2BÀÁÚ¥B@#”00Xª PŸ_àÃÚ›"À³HE› ÀGÛïDÀ3#bBœš‰€“Ú´pŠˆ€ƒù¡…€C ðÜœY¥?¿Øüï/ýþ>hž‰Îßå0 [>hOŵ€@þˆ…‹~`¸7€@£ì·j^f‰º^@ UÂZêƒåœÀBA.EtƒCœ€¾(ߤ¥ç 𛡠@ï<x–>=‚‡}@°æ ôB÷xHƒÏÒ§a“; pXHÍM,4>¬S<«®-ÑnF½‰3`â¦Cà0U,þEh@ ­øx+êM4mغ2Ž—> ÐkR@é»ÂïÔìUû+e>œ½, U<¦{Òë è CÈ–L÷t§ˆ3í·*ýÅîGŒ7Зdz2 ×¶T0à0ßal9ú2"|0`”3rƒ! oΠ“@@/‘D,k¨á¤'6Ð×ó„Â5œ¨E‹; hÅáçGûë^à”6Øäã´°2ëBóM± èº=-QèÜt ¬ @ ŽêýÏBª¨íZ-a<ÔA€¶—jxG½‰%Œ«L 0ÊŸàÜN€NpTA€çþ»A€öâQ€Fë÷û’û Ð\|ii¾Cù‰hÓ ¶†€€mh_ØzH¶ô²^^ˆ< N€ö>´Å™0ÐÜÉǯü‚í‘ämë ߟš5 pX‰l&ÞÙ‹£"<Ò6"A ¿XÙqÀY8ÚÚcËs¡ðËÃå (Ð/—Ú¡~™CgŠàÈ=Yî è1Ïá‘[>ìÀÀa‹XpB` 9)áÏØ[½™˜ h³Îüh€63]$>g@KÞ·.Ò°¿—ÄÆ`@‹¼Ã€Ïnª‚΀MõÕÈ€¶ä"m6"a q|Ð zã ÝŒr^ÃÎê–Tx½þô¯ÜƒÇŽøwÙÄŠ.ÿ,®aÜÿì™ÀAmÚ` þó! þ³ç®a$iŸFª}i@9-øÏ7·IwiEß;ØÉ`ǃ@*ÿ 0Àç9ä¤þó*ŽŒ´'“"œóŸ?›ýËó‘”þ{8W‹ÿ׊â¿&Æÿdlç?[ZááÿåV'ð>?1®è[¦ÿ4EXBßmË“îÇ›—Ð×±¢ôÙ|U>·â(ýÙÞz!õ‘Iû˜¹)±¯±TÁ>x ûç4bßEÇaßéþiľKïľcÁ !‡OJYñ'‚òW;([ûîTþì2Pß QŸ=÷_êË…¤¨¯q2'õ5† ûÚ"z9õÙ„ðõuíG“úl?Pß¹dù‹ùÎÔB×M0_úó1÷ŸoËùÈç d7€øÎ󭆲_úèQö³dtÿŒ©InDTý¬¬9š@õ³?Ú@õ³­g"`¨~VŸ7 ó 'Ýöá={ñGÞÛ ¶'ï•‘>ƒ÷컈— ¼gR&¶òÉ{·| Á{ö`9Þ³ßw¼ç…H©ñEÐï{IO¼W´ ó'B~SÕðøÐ‰ôARÑþõöt~"¡¾“ ©S®L*J¼»˜Üu_&=ÅV‹ˆïæýñ=Rç‚øÌ‚ølýIJñïñmy£’ø¶œ®‰|[.àD¾sî^½=½ =9_T”®ä³…9ýHùvKÍÏWòôŸ àsËølyŒõ6€ÏŸXò]”4Ù€*`Ô´59,#ê öG˜!¿öTÏêîéýp|ÏŽ•µ ¾ÓBÛjA|¾XïTø¢¾àMÄç» ` >¬[%>ñ¨ŸNT`TŸmtÃÄ7Ó+Äg¿`%¾‡Þ6I|Ú”"ñ=‹ßeßùŽÄ÷H~"ñ=©@‚øÌµlâ³í8PˆÏÜAf ¾WNÂ$>+úNtâ#‚÷^MÄ=[‹Â¿¸·ô&÷ ŒÐ¸—ñ{çkw8p/R’ã"Φ,‡L8[ƒÙ,ó©ÝÎí™p6½½Àz~(vB62áì?ŠX_›ÐaA&œ½Õ-b}7“^õ|Û›.›5>õ} Öóá±ç…7ùDF&/š Ëö~7&X/‹I&ë5~¯ÄzÚèë5>œb½ó–Ãñ¬gûÔUñ;îùˆõ¥d°ÞY¯ý`½Æˆ±žíµ£_°^ç½ëudxOÔ£7AÒžN´çó%–ÏA{nÁeíù^È5Þ˜SYJÒiÏ¿è6á8wVØóÁµzëùwˆ¸wž§©ÑEÛTÅUî•MUàž¿Éb÷Že ÄúŠ¿[%>âØ"áØÛð.¶¡™pò ä¶ôÇÈç öVÉ/Úùô]òÙnÎùŽ¿K ßÒ5ù,rõù›²áöi¡%‘Ð7(Í-‹Ê!Âý&‹OÓíÓstÁnŸæMˆ½¸}ÚãuUÉoÚ¯þÃís‰XÜíó~o)j÷ë‚nŸ%î‘nŸæ³ô ÷³Ø'<¯pû¼mp·Om$Òïó6å=#ÜouÉ‹÷ëœÑè÷9–ßý>-Ró#úùcCïÌðû´)#–ß§¾-ôû¼ô}„ê÷¼¢¨~æ‰õ|T?s/£ÄMϵ‹~÷’lÑï¶ ·Ï]Bü\ô3'Tºœ†è7rwAMý@ô3ï=†ïÁíÓ²¾ Wø:]¼p¸}ÚüýV<Å”œ8[Èëôwãõ†×§¥\Ãö¼>Gú³ÃëÓB]o2ax}¾r¿€×§¥–럘¿ûæj‰^ŸÝVT´DÌßùvá»  ¿Ä?wk{¿!æÃƒ{|Úy±‹EOí6ÓãÓBXý;¯xŠ.ît1æ¯'Z"æïæž´\>' !÷ÙšŠÞ›!÷Ms©Ÿé KO{Ž …áñyÜpÅü5ñbþÒçrŸÅ¾É4<>åòG½o˜÷ÒGïÊÆ@½Ï¢Mè}wO?VúSy$ê}VÐì½@}F}”ÁH>Ÿ[nmrú|x§Ï%m NŸ÷ÎCýMn³!èïÅV'>§<½äô9èu¦˜¿¾¥+2æ¯Ë©NŸJm ˜¿ỗà÷\¼Ãrú\—Âô÷háΠ?½Ë!ø å¿ àwFŽO?{ )-†à7.FgRð{Cüügø8}>M‘–ŒúSh‡¼>§„Ch~çIP0¼>×!û™'3¢3éõù =ª¢þšÂìèôÙ¹"¡ìç) Ñ ¢þ:ÜÉíó}“øÂíÓ|v0¸}ÚS~àöÙÓea]"u„ýInŸçs ~¢Û§M‚±àö™1`@Ÿ[Ð&Ðò ±ç`À÷|¬ÀÌ”ý&sk(îolqzöéöé©[²…J9nŸ““Ðfâ˜nÈ€úË\:Jvmwr9ËÖaOÞÿöÿðL–gˆ´üSc èàþwŽËVlSû‰Â~w†´LÈ?ÿøÝ9þ·bé‹*g›ÓKŠ•¾d)}ÁVú’%ûò|Èûså²d_´e_i)}™ëúûéK–Òl¥/Y²¯ÿ¢äcÆÏvmš=ÞL,e«ËiŸ<»²ˆÅÿznî»)EÔïÔ¶æÆü¼µíŸöÙ‰Ff'ûýcaî wy^ÿñ»gØžÎÇ£çk+vuèË~ü¯Ú þ™=èßu¸§õm¥>¨‘ú)­ÔÕcNÏu00|ºR#uUZåãoq 3»¢¡v•ØUmõWŸ׎ΧÚ2<2ø‘ŒlüA±ùùÇ?IFö»ßÿGF³ŸOÏïNöMFöÇÓ$#û _Ä?úîüþû÷çV[ýÑÓúû¾þ_ÃVâç÷°ßâ¿Ùb©­ü±5ç™üùïÿµ›gÍxþå¿û×3ÉzþËÿð¯ÝR½ï¿üú×ÿ×y?Ïjô¼Ïÿòüßÿç¹uó,Vþåÿý¯ÿÍÖGçÿþwüü«­qß«ýËÿtšÙ†Ä;u‡ÿ~5‹d´üÔvîóÁü$Q»3‰ÚíIÔžÿ0ÚigYÓ,ÚS%kÚýíåI³ôoùw&L!aÚµ=†ÇØðŸ±w±ãˆ%z ÀsK,­Z·µÿ1Ð3»u/á–XÚÆU C´á)0<2ê€O× ÜKË5¼Š.<®šº5È_׎…nm¹Œ[bÒ–çurK¬ÙÚù¼þ æòµ›JfmT@ÁÂQŸ;,¬µíËÍcÁnY7÷0»]gè( {sf½™ßÝBì^œKÛò¿ÛZ )€§; |%»I™ø©£›}äºñ2ÓB/[mú´Ë «^k±¿ê'l÷Ø<–®òŸÍÃ-÷å(x,ÌÊo¡ÛîèC7¬;|2Ž…+Qó \6ÂáQw„jœ'4¶óZ“—Þø¶{Ðín®½/ÚÐ-Fµ=ßó”Öqý“ýÍʲƒ^3,ØÐ·••§éÞo|–„ù³Hv#CkkÙ¶}ú›èç{r{ú¾Öfg ¹?áÝt€IÃúî ¸]fRuw©0¼Ö¸{|£| £ºoI`¿Â}œÜB_g_›»….Àþe¶ô|Ë·ÿdÇÂTAóòmݾšd·Ë·Ò<‘7>míß-1ô ²¶&ù[,‰œýÍìrÆ1ö®z 2sxÞ‚nCH¢3=¤›Øéñ úî¾Y±®<h7O,äüxݱ¯›·¼\ynO,Ô—¾7Ó„f»[ƒ‚¹ÅŒ=wXâ+eTg徭ÎÄízzó—Õ+…ô°ø>³å÷?ïÇßÔeÌÝhÃi´=¶%kMÖ]~L;†—™Ø †ìU5KÜ`ÏÛb7BÙ„žå9Ù<¡ylèún†·¡_ÕÛ­Çò@(x/ßík!3àÛ|ÑsžÇwím®ÓtÆðnÞî‹ÝjÊĆß{{ o¯Ç;Üϼ›g@À³MϽ²ý£øÅíke¯ª øay<1ŠçN_Á^þ' µ<$ö®î†›§¬´¿™íÃ\,í]ÝŠqs÷É–ØŸ°ø2{W·ëfˆ–î©'üÌödÚ«ê¾.~oü9la™axýMM¡Û{SM” p÷‡e…%¦‹×²WÕ<1bĆ öªšÌ‰6¯ înAÏ+VQæü—(·›õPZ³›mïªK‹~”yBØ»šN*æW`|)šÁãM¸û`@v™/¢(ýòìN¼tò²‹¹|mEg1óÛhÛ9c±½ 7… ¯{žù8ÑÓªI˜ñ„š—‹½ª&£ÅŽn¯ªY⎚8}^ÕÛ¼¤ýnyMŸÇ¨…n)Çâ!þ·åÀÜai>¯Þ&|úç,ê ëƒñ-GÇ0Øi ½¦7‰¬yÝÓ[‹Q^ÓÇNdÝ Ï«·— jañyõöî£Û×çUÏqÿD7Ë¿znñÉ®[ÖçËÚØy\æöyõ´Á¿—ô9o«gÆ÷o—ôÖÆB"¼g×m„6.X|b5ˆ‹IÓ«ú¼ÞæŠýœn‘ÝÛÌP{½¬Ïc÷bÁ³çX|bu‹ë¿^Ödž¼óÜMC»ìfÐÝÉ«ú˜aC ò¢>N˜ïÍ3mŸZoÛ¯ KÕÒ|ju‹ïyYŸó¾Þ¶ºôÁôî3ëíUŽüæXpÁc ÕàKÓM<ïë± Ä ûÌGE?Ó§ÖÛ¶=0½°Ïy_=™\„aß¶6 ZŠö1šµ­QÿõL;¯ëízk4Ù>µ ÒLziŸsÿo“ }›´›Rdã3—­´ÏcM,…¡lNµ¿Q0ÞKûL»¡[géSëm¬oX"FóX é¥}¶µ±ÿF›éS«·Á`Âg> D›×§ÖÛ´îxl=¨µy¤Ñ-ï§½¯V`„eûÔz7&>=?Ãð÷ÕÒ»Æoe%~ì}µ¼/.zy•{_M!Ÿaé>»Þ¦«Ã♃n/ Ÿ]ïóµÄ¥[F;Ó†:ÑÇôÙÕÚqÐã¯î}žp\ùx}v½{‹$^äçñ&HöÙmÝÞWÛ5ŽÏ’íðÚûê fÜ2CÁ;Gõøúz‘{_­_+{‘{_íTN1VäÇßWò›‘·Ï®^ŠaE?æD|ÛÙ‘.ÕËüØûjïNü¶?jï«cˆsÙbÙ Xíu$ϼí-ÀAæglýÂQ\;0½E‚ð¿˜>íƒý'>¿Ã@€!1)¢*†ÐQ05Ç…tK dÀRa  Mô6ÄÀÁ˜q Ê‹³[ ÓH…¤‚@s|ò›E ÌÎ! T´º(Ћ%U´ÕI`!!p^*  T ¹ p2° p2o“ ÐËV4ÔýUP‰UÄ€“«'1 EÅhÈ€“1'bÀÉlx„ÀÉÌ:‚Àù(ñ^Pà¤_ˆ(p*R™˜R ÉÐpÆNeŸ#N%d%Î É>rÐ&*ɤ0ði Û 4¿¨³ûÚÒ–Ö»}±Í±±C÷P3ÁS< 4‚§ëj` ü 8ç/ëC~b !=㼜_s,’øfÒNp Y »Í‚p6p ÑR€Í‚@9p ·‰smû ¼mÈfã,8з¬À™ºŸè›az²Å4p YB/& zúŰ ZYàHÐ'àKá— h†øÁ ‚æzø|@ÐS’Äè‚f‰/AÐãÕ‚û‚¯r‘­Mì_Ô“Í1´k’`&z$ Ú¶($èm‚A‚ïBn@‚ b h[)7 ‚^…,F$è ¢[ 5´‰Ç$ø*5QÐÚ•ßM—!¢à»Xðð’Í‚6`Áwûm'àŒ h‡ÄçŽ h©+”AkÓ? ¸·Mô€º <€ Y€}>³Z€]ð.9УÆ‚ÍG4@ ‚æ$ûoA³ÄlGtGÒ 8€ í)ÅÝ#zþÍ HÐ E,‚Í[4$Áe¼ç ìæuãß’`·˜ÀXY‚ûj“– A·Ì@-h—f ü º%Ö£A‚~òXq»ùÇÆj*PзÁ.€_L®vЈƒ½ F(è–è%HÐûQ ºX$èûkO\ ·qÿ’ ·‰U#H°[©ãì$è{n±Ö vsRº¢Ÿ Ao3ƒ1ƒ½ÍSI°/æL væß!ƹ‰½Ò_Ü`p`·ô@ÁGà@ï$® Ø-iJœèmFåÀn‰_‚w‚Ýâ.ý$Ö~­Î –üÁnÇq'‚±³ú`õF‰‚ բ͋MÖE=H‚ÞϬ$ØÍ÷kýJô-K0Ü{¬,çFô&¡A‚¾aÙ€†ØdŸ0I°›óu<£ Aoàô6Q A·àä6YéªOì–Eè­$蛣=®aa“•«D’`iì EQ‚]%° ‚¾w§vK†ôxÇ.ëDnJr`·”Kñ z“ø1Á¾W ¤{°Ë:u껬ñDA·€evY'&i‚ ÷Óƒ³.l³Ú =PìÂ6+Ì‚]…Î ‚ݲ¿Ä]F©Ë8*@0Ž 4 Œ«¨ è#¼ zÇÁݲOÅ/è†Y9ÐOtG°¿žI-iпΕ'ƒEƒ» ¢Á‡‘¢Á‡¹dHƒ’žDƒ‰%F‰&t ÚÃB|ï)|¸e,|è+´8ë 0Ò ²x‰ŸÁ’ȤÁ—Ά¢Á—å„„6+BÄœu]±Z$šWrh€äÁMgTð EôGdyЦÝX´M5š_Up#…Bá&·=[Ä¿€myñ|DAŸ«ƒÛÀƒ¶v@½Q¡iMQp)`Ž@hË €&€ÐòìzÕ©fj<áºèÇJ \ô!zy«Ú€YZ sVkJŽ9‹Áœ°”Š¡sÂR®gРuOmÐàºX¾0h7†.ë¾¶´ –É9]½ò§Æte¯ aºš?XÐ&B¦ó¡&¨‚Ô/æ¢NMþ²”•ó‘’`k™_ò7ÜÄáQ¼/èÏÒíW:¤&Ø•ÚRš ˆäA_µ|„Á¥­-ò`f vˆCÆÅƒ7법2@@xsOÂ`c*-)ƒÊ4# ÜL$eðâ&¤”Á‹Õç¤ ¦…@¸év |™XB@¸î- |ñO |$Ø.­„Z Ç—ïMí48B  Zôw`]°àv7ó‚‚BKÌ«v_‚™ˆ‚v[œ,¸Y/Ypã‰H\H™š,H ?YpuÒYð‰Ì=‰‚¶]ÈF|¨·ŠBAñ& N$Ç& Ú“"YPáß„Á-N! Z`m¬¡ ƒVø¡ÄÍ@ šªäB´g9n2aÐ< €~€Á¬ÿÉ‚û¥(¨[,|áN•(è.À¿* Ú mˆ‚¶eÚ"PpOäƒ ZÀzìi=M»Å–•t‹,hwtUUÐ}âg ÚÝZUt÷ ð"XÐ\4âþ‘íÉ^Uô—÷ YpE¡³DAF¾& .lf' ¾È³/ܬZ(´ÔPóÀ‚C& š¥Š‚áà4Ë„Lè“«çˆ3-CIh³„Ae1 z¶–8`pk_†0¸é…•0¸‘V?að¼ÛñC·´;Âà‚<%´ñp ƒ[_? å€ ´(©*èî8{À põ@ƒ–2%¨4¸'´v ݮ«ÀàŸfUKôí½ÞôÕ>˜! €“!è@Ò®p2Þ3¹’xQgâsS±¯ €¬~•ÈÝø@&QOdq»@F mmûu }ºVü—Q|8eóÜ@ FâŠÁ<ˆ‚àƒÇ³¸…ªàËÍx)‚/É¥¾JxGEðåž¹A¥x”$¸øÓH\Le*MPõ¦¤ ®FTj‚‹®ÀÒ+©Q\Œ•&¸¶ v…&h¡t’Ô-è ‰¦4¦€&(ÕAšàV¦:y†úŠÊ3TIpåªr/ò U ^¹†.EìNÉ J¸ ×PˆÕ3ôf!¸†rg 1¹Çoˆ9^S‰?ôÂ@a61ðÚ™Õ*ƒ• …Ëü«R`c!Q`cV…> Í$>ýˆ¹lO¤;˜PÜ#|Œ@bàK¬ø6ú’B|±•r %ØúÊöT·P§°^ÝBÝËmÉ/=%rw=å@ÏeR p¡TA@äM\¨øœHO‡DÀׯDÀŒV©îÎ6T-ÃÍì5p£ oªæ à‹yu#Iqª{ýBÝÍŽx‘ð¥nlJÄB½àÍ~@€ö•Yô‘èh$Nô"’¡ã/¸?$6$¿Hl¨‘È<{BÀ9g“¹õ'l‹;–hI€i©&$ š$@C•_7s~ÝÄô4{¿ ÿ9}†¬Gþc¥Ýä¿›~Ýâ¿{Ðß”üw?ôç$ÿ58lˆÿ$ ä?»Ó1bðŸ¶U¾Éµóßɱ–0è%>0È$W ƒ ò ²Faú†2ׂ|CY5<}C¹Ú Z¢”ð% Z^胄A¦E N£ NÖi Zž/ ªxwFN¬QÅ‚/óৈ Å©>TÉ‚±“-dt,ør¯T,ø²”.Yð…»r²àËLbÁci_ïP;ê+¾Ð‚* ö(HYO$ÈÆÿ/{o²k9²¬g¾ÊV  é¤7Ï‘Ï h +àôþ(šýùÚ™'2u  5‹mát6‹ö[S$¨Ê÷Ö6Qb`ÓIY lâ*‹—Z~”¨;Ébà©ÜšM Ñ¡±<ì,èG1PÝÇŠUA¤Hpˆ M‚ 2-|~ʼÝOH$xýø:IgÁx *i ¸.UŠ· ¸”Œfœ®Î'´¨m|\YJ$xêvˆ/VSæ¨Q°)WN(xI®$ÁábŽT׈ä'ëT×—BAµÇ.” f<Á,Œt%6$ †“Lˆ‚˼„‚ëbCL‘`ºG¿vœÒò ‚Q6‹ØGbWƒ õ¶=KðúÈÌÒ@;ÞŠR6õP76. › M‚jøAlQÏïÜI0-ÏGl蚪«(ŒÚ¢çG–`ô”"‘ã»߉H0># ˜žwêƒ$Á¹È}ÁÉð¤"Á¡²ÿ"Á®´o“`w!IðQȇIP!ME‚·!Ûyª¾%Q°ÅB"P°E¡'êz@Áv"i§ Nµkwšà£j›Nljìå4ÁK±ÒNTöH¥ Ú'c\ò¸§:s'¹Ó,èPi±`×Ãjì&½„Ávâv$ fÒÑÚ•À3÷Ad´Ú€‚-*–b ~±9G°«¤šsŸKÒ¥rcU\$ º·¸ip¬oÌ„TXDƒ*g]4ȃqh„Á!w¾r_ù2 ¾×‰Õ²œ LÖv)°Eoof+n ‚pÊ;AP=M‚q®÷ f!Y0I0Šìû‚)/}€`–^þÁ¸xT ‚QîúS t6oàšŠ..¦-+?ðz¤J)?0–=Pì˜{ü–wí‚™ÑøìR`‹n;»Ø¢jJJàbE‰RÕÍ¢”@Eãra-ŒݳçæêGCŒtã“|U³YÀ‡Uf?Ò߯ÖW1`‹B®©¹]ªrOæw;7ðPa%FA9¨XJ<äsr`ÜX¸£ ‹AÝ%%ŠûÐAàÓ~|¨€‹¥B@3ŒðÂw®¯ÒßËô--ðНãC+-pî `‹r­s ͼÏû#-0’N™¬‡´À¸R€c¥Æ[Hi‡Z>ÿ©cOñß”Tfþ‹µŽFØO¥Ý Ùk¼™>µ 5!ç6»;/ðá7·ò½Z”O'\åF‚+ÃS‘÷ѱǃ¾›Ù)/0š¨=Ÿàd°ìVaíý¹ŽÏê>Yþó9mù[öJi¾]Ò˜Vaíç=”¥ª}ßÇÿØ,U}¬ÅÒi|ÌeË6mÛ\¶Ô\YOúù8s[j.Ùj®²lsÅŠ³}ÌeË6mÛ\¶ü»+¬µh]×øŸUX»Uaí|¾ýó{…µ×úüÙX”3º\ÎèW·ÅýݪÖ÷›8nÏ|Ÿïƒ4K¨i—PÓ$üÎàÿöæ.žæ¶âižÄ£4Ï6ÈS¹xš§ÚЧy*ÒTÛ ºýUú‘nZ†ð¼–ùƒa ¸ÆY‹›– –îcdbÞ;û]¤Ç+}/¯eR¼ïüaúóP¼Ÿš¸7‹÷ ûy3¦þ<0ϘTïé9k=\JLŠ{`Y©»dZ‚}èÛ™!ñéez-ƒñÛþý6‚»˜Â•Ðþ>D<6»B· hé}Iwåkù¼NßÜùîùÊhSÜ¥ñä¦Ë†ÂA‹GŒºgÇ´==¯iY˜$Ý@“^ï¹ßé[L)l¡ï¤o5Baq´Hx†~™ÇwǤdˆ3Ê4”ößâ—‡H.iÌÍH"ÆÃ9Ño%U;Oæ:Np46º37.u¼žJyªá]ÆF(bpEB¼Ú2t?ÇPUlT‡‹ê[Œž€W< ¡µ^ ÃÅïÑê_c‹b‰ƒÏÍË¢Zâ ¢¡[6òëpýá3Í•ODW&Æeƒ¡•ÈÈ„ýl0”88‹ †æ@ kþº e!2²“LJŠr—{ßµ¨Î•^›(&ŽC·Ò$ÙÃò¾¦R\Œ%ÎCñ´®øÍã²ßQVëÈ1T ²ÃP\œÅ\l0”«^öfIˆ¸Q‘kb“–Ö¬ã•Ö\‡¤×¦Æ<ܫߑ¯e½z1""; u޹°ï‘ÖDwðÌk‹=äCÿZòÚŽÛ‘†•?QI3 EQ§Cß·l0ÔÂKpSçÈC³ÁucÌ•ßÖDå¼ ²ÅЈS(t‡câ‚»/߇Ù`(7ƒÊå}†?Žæ;×U±­÷xÄŸnˆl.”ÞÕňÕl.”ÞUU¥ÈæB­onl.4s̉7]4Ê’N1s~ø³½P”t²;à]ç§µÅJ/]¶Êlò;ßá¡É’N½ÞÙ^è‰:F‡Ž9Ú ­#§l¶ºoÒ”šÃ_qÚjܨét1Æ,; Å4[¦¼†k£·/ Åçr5 íȇ´÷…·uöêYJKGœztÛÊ1 =Y&ëÀ ' -–Òê˜çÎok–Ûz°¯;¿­-„ä\ÒD‡¡¸Ë²¼ÕľXúZ°>¸ÛÈOkÉO}öêY»Šõòî†N¬-ägœgôzX ÷ItOˆÙÑ!?BÙc( ^1²/[ ¡¦Óà] UÂÍ¥±MËOë»Ñ‰¥Htʧ5«oåñE“¡,Á¶èZz 5ØÂG,óZô_Àµ‰Æ!ç ~Íh2ô TÀº±ÕÌ/k».¼÷³ÇÐ=P¡ Þ£è1k”Ö­=†âaÒUx|£ÇÐÌ"Y?ùsp³6v÷Í.Cñ°†^ž ‘÷žð[ôvÈ÷svÊÇ5a°„üú•¬€»+š Åã\ô§g]-¶œÉCñ¸†è~ãXF~.[¸q#E‡¡x\£ÄÄ9!:¸E¯*ܢї#×xðpF¡x\Ã…Ì1g~Z_ ¥þì1Ô¯ô6cÉs÷vÑÕúðÞŠCñ¸æVy Ñc(צFDÙcè†×šoÚŽ(ñ¼fîY²5ÅÒ÷<. ~…>óÓšç‰MBzÅ9ØÏZ¨¿6YbŽ„px'÷8o<¬Æödœ“-â~·ZÙ^ß)0?Š '- [¡)o ÈR(2¨mc@ªŽ2ù{ã@æ¡ÞŒë)T|Lq ÊŽÞ¨Äc ¼™@Zè•°0P{ ïÅ%17ÿ†W&Æ@• + Œ€Éõµc`|5YÂÀ‡¹e…ªšYø4Èd…!Ü`faàÃzœ…z~ ŸA~>Œh+ |´„5>ºä¢À‡½( Õ*ÜËu€˜00V>10VíkÇÀÎHáÂ@æ. 쌅) ìLÂ6Y÷ Œ­&öE Êl3&Yúˆ®ýe ¹>—#ÆÀØ YèšßÂÀˆ‡j˜A¹sb`nlC L>Çb`öìÄ4ÄÀÈ"ÁÁƒylD Ì$)Ðm=Ma9Á ¤À,B"¶ô2Fæ 8 ½úD/B`To˜`*!0|àsAàÐÂ\ØÖ‰…¤À〦d±X‡Ç8Ô2½(ð`RNQ —û‡FèÊP†Àr03Ì cY¨c‘Æ—‡(0«PÁB Œ1py™ÕÃÙ >)00 0“-> 0Â>0/!0³:Ö×®lnŒ1 92 sÌ€S½¹Ì€.,`ÌòCùŠã5" 0BN>!0cäp€„ÀL‡…˜a)D¾Ó÷æ!N(6Æ<¤,@`z;€f€@¾%Vè¼(ed0/(5v`".ž|YÃ2°oP`&4cO€À,5ð®r#Ì8!lÌà2 Rž¿ ~D(LLÏ á ˜qó7P ˆ€wŒIÌÃsȹ1àk`-+€™?üEÌXw¬K‰€i9€w@Àœë<" o¿Š3ˆ KÌ ð ‘ .`F ã„H€éfÁe ¦?‰„‡)™øÎØe`F0‘?A€¹¯[s+,VA€é`"$‚3’ p`zœN0ÃÏò>«9ïW`9A\@DÈç¼ÀŒQç4À ËÂÊ™ó|ý¥¯ FúË(ìgÇ¿<^,þ‰¹ë Óÿ2Òd# þ]ñ^Âõþe$‡ÿ2œ·ðóæ/GüK_ܤŸÔ ¨ÂFÀ¿Ê~þåÄxLÉÖ'⛚ó;ÿå<fÿ!±33jéÜ0¢ ¿ŠþÄ”Lú»Üº^ô—N¾tC‹þ2<¾c+Ð_ú o0èo»è ¿¼Âð‘þr#‚fnÑX¬\ô‡úØèïZ*Í+úË øáHytxÁ’þ2LÌCúƒW¬wÒ±ªt¢¿Ü;Ήô—û¹“þ23é/ã¿ƒÛ„ô—g+Jú«JÄ¿wÃÝ”g%߈9wñï}‚™Ÿ*üËÀ6x²ˆ]ŠgJ‚gÖ+þýf…2`åóA€ïŒ„°sþBÀÎÂH…€]*ÐË`3à ™cú©†,õµ#`t*c Çià#ªj!à@"QàÔjÅ8…BÀ)µp>„DàdÞNऋ“¨Ì¨"Àø`/"À‡¯'ãó ãÝ”N6„)Ìã;ÿ©[Iñß:¾vø›Ìp*ø{jw‚¿EïkÑ#C þ¼`7ü)þÑð·K¿™ào!Õ¤Øo]?¾)€—Í ß…›È Å›¨[¡ÀÆëbô[M'ôS)ÜB?u/-ô[(â]ä·.²ŒÉo!¿®ÀÒ©Oç(è[—ÀKÐçÝ ú‹Môi%Qзo\ÐÑß°ˆú“ÙŠúVÓQŸVE}Kj¹©o11²¨o!Ç¥¨oÂ(Q—ô1}ƒ¾›ÂOAóÚ úX6hƒ>Ö +軵kB_&™”ôY(<|CSÇ }y(Cè E0õåcR_Ì|}ha~.ê˳ø ¾<ìÔ7lêËy03°/pAB$ö…~~ìØ—Ûа\n a_Í+îË1_ö9ùÇØ\da_^.à±/-؊ط±oCìËëCû«K*ìë–>Hìs¡ c_Œ¡$ìÛ†ûòñ eêi…G_Ø—Ïï×F}x%ùôJ0ñå; ‰Ïo #_ì~y!_ŽÁ~È|~Yú²:ÇôÕáŠúâ=ÝÉ ¾a$õ¹·›©/,‹‡Oéb¸‰©/^ Ô~K£RqŸS øÄ>7•3öeî%6™ú–°o˜éÄ}1 ”¸/>XµŠû2þuékÊï¶¹oà7ôÅja}@Ÿ>ìf¾Øs)>ú˜v©d>g1óÉ1_zÑ>˜Ï5QÅ|aÀr^ÌK\1_ŽÙU¿´P›#ôe4>B_îüú²!àôŸ6Ä}÷¢ /“úÒ‚1„¾í€ }š„Ä—ë5Ê{üœÎ›Ò‰/ TI|ZÁ ø²?@À·MBàK Ðí–µñ™ðض ~Ø7Æt9Q…ó>70ðm{'ð……ûZò¢6Â¥˜/÷þµ!_îjür#êrD¾°ànòÕi ù¶]ùÂ@º$ò9š È—³‰|¹ !Ôš„È—0 ‘o¨Óš‘/Wì #"Ÿ»9ùÂ2wÁ/-Ï.øíóùÒß $òeWˆ]ðƒ¿ûù\ ÉÈ·mäÊ¿4òå*ƒˆ‡ªúX˜ùì7óå˜ü]Ä|ƒ™lã:%!üe²ú2½mǼhmÿõAy¼*åÉ]Z”7Û)Êë‚S^ªì”-h§<| óN:Ä ó.Un˜‡6ʃ>cÌ?|~OyC«ecÞP<›8o|F{­¦yƒ®‚¼Áu[´'êoÁžó{°ç8¥à ò ¶†¼(.å ŠýEy£+°ÔÁžRðë)é­b=—&6ç±bÞd]œ=µA©XOØ‚='~#sž"â*Ö“ 6Ò é!_r=æ0n Çº½PbVêPO¦$m¡ž§ ò/B=% 9Ô33+Îó`¡œ-Îó`´ ã~|À^ˆDŒØ”Äw_ý$ñÝ7iÚßÃÙ’øVË-‰ï}dñö±ÄÇ|ÃRøžÎKn…/J?Ró£ÂÉÕ°Pâëºñ-ñuVþ´Ä×Ù6¥$¾® K|ãT|¦4¾Á¥ñYʶÆïŸOo(tÖ_WÀ­5¾ ë”Æ×YP·4¾!_ƒ5¾¡°gk|³é˜¥ñMV‰*ÏÁ€Òø¼Ž°Æ7aoò•^ßœ"5i|‹õwJã[ ¤´Æ·X‰­ˆ¯/ x£<§X/øÆÁ8D_T7 ø:k l*Ÿ\ú–ùÂ5Î2Jòl*Ÿ ùz6Jäƒð__Hã늡³Æ7.ÁD¾¦9-ò1‚¼D¾ëœJäS äRù.ŒU¾²HåS©”Rù.ö7(•OýJå‹­>U>Åå—Êw17¼T¾Kš‰U¾ÆÔ¥òµCú!ˆ/^P2D|a¡ â˺æPÍH|ñ²ƒø&‘¯u…pø\:ÃÀï:¨¾lã”$ðeÓÌCàSA?ó^¼Ïú‡Î…<>‘/+æ}mÄ—Õ¿6à‹z+dóÅiƒPÅ|q mWùÂYWÌgÐw•/÷؃<>ðµ1_î§JbÏD¾©â F¾©ÂÜF¾¸T„À¡ì ±†/íAžøR|mÄç¶í&¾°€ÔH|ÎÜ0ñÍKN_ÖóÃF>׿3ðeà,¾©¶-¾|C€ÞðhÓQkà›Š¤2ðMa‚o*¶ÊÀc>/BðÀ øâs •5¾K.k|ëò•ÆwM‘Æ×äS³Æ×ø7ðEL‡¼7±RÚx/ƒ v‰/¶y>x/6𻯆ñÁ{ÙEáký,žÛ÷‚ßI¼ÓäBáo”ÛÙ¯}y>Mòàïaý‡ þâIÁ~oðG—ÒTA þ:Û·üu†˜šýúóýºã>Å~‘ô Ý‘ ‚¿w óÿQp„QÌöSˆáÏ1‡‚¿Î§ºø¯#”„ø×OA§ð¯+¼«ðïRä¥ùOëÃJö“"YÉ~üšmÉ~í§d¿öãSäSßÓ¿®å¿ù¯óÃYü§¾WÅ]Étæ¿~ YÅ5ù//ÙŽŠ©c<5GÅx>’ìãÉ8é-Æ“Um¶Ïç»Ð×…“n1ž×·OåÖUŒ'#!¶ÏG‰†ŽñdT“ù/ "b‰€.Qd\êY¸XÑ8X³P×OØh|Oʉ з&ÀÛäæL¿AÍÓØè!,l ,lÊ4^Ê‚^ì9Ux0À´ð¡&n<­¨ Oå£6A4L)T±M`°cË}Ch¹OÚYÉ}]!–ûtiJîc=ïMîs§å>[,÷)D¶ä>¶<Ûä¾ó3Õ/Oø›Üw8³ÞIª'%÷Möã.¹/t —侨þŠi¤÷Éû\zß`…;!`f‹ír_æ‚uò^`ÒZ{”g;.fol©~,â´¥ú=•ê×™9W©~I„•êgPª_ÔðøûÖAð6FÀ0 L¸åŠ'ÃiŠý½7eqU”'‹«U˜§*oažFTÅyªCxz>| o¶.¼åÂ7Þ C2FüÕ×΀­+‹ ¨‚KÞBC`;$ /‚.ðâ׺ðR€¡¿¥UY1 ‹¬ú^ ¨ÂúÅ€P €§¢] €ƒµÌ‡UCñß!)Äüw eõ‰ÿŽGÇ"þ;(ÞÿÞ_fö€Ç± ÿ©Â?g9Ío,±Òüº’8+Ío °”æçD¥ù-ÇæõÞSª4¿È)e* ÓüŽCwž=×¥ä@z†pøµ`>–‰Åø-çy³VÅy6±¦âv |¿~Jtv%]À­ôØ»B^Ÿeo:‹àW¡Yöb¾]Ò˜Vzìç=”¥Êr}ßÇÿØ,U–ëaÓ‹m.[¶¹hÛæ²¥æê‘Ry~œ¹-5—l5WY¶¹†Jg{.[¶¹hÛæ²åß]zì ’ˆküËÒc矗û^zì5Äþ-¥Ç~u[ 5c¯ õý&ŽÛy§û(ÍÅÚbšÈÅÅ4 ÿ_Søÿ½½ËŠyŠ­®˜gñ(O´ò\®+æ¹¶ÂbžË£<×6ªÓ\{e±z`5Jsý“úcQmq½kÎ_×»þªþØõõÇ~º þ¤þ˜n¡ŸvöYì×÷ÔÏõÇ~çµø«—ÏÏ/Á?þâE¶úÕûó\»þX¸ï÷ë—õÇÞ«ñßêŸÿÕÕÁþU²wðÿü¿cµ½æÚŠŠmÿý7Ë‘mÆÿþ§¿ü_W&{êò#)½ûžW:>Hˆ#¯ôײrvÓÛòÜÈ’ÌÄðä¬'®ÝÅäñ\w½ ŸQg7ó0_Kv?‚·4g¾Ã÷´ì? Ë}#ðìaçç~²S¦Qä:úµLV×d¹ªçÎl¶ÊÏ~îéà†½±ÚxîLV«Þð¯a²®&E°ç^^؇mºÞµZƒöáªþyN~Æ¢ÍßËts@|ÒŸ«Ó Ër²O~1è«Ã?1ÊöZ&ݰ xž(ÖàßÅÞØ¹oïÚñ`‘âµLDž Ö$y¨ª•ó<¸úU]ôž9oÌv¾iÉ(—‰5ßÓÏ‡Í (f=ýºyÆ<Ç÷àFž1®ëµ Fž±!ðÓÃñÄè4Îü\h1»¶ Ïk˜å*ðµ Dž-úxð"PNòÓçEß²[^ÃBàYüªØùè±èû¯ÞM`ä2õç!â ò¾–LYN¨Ìµâ»DFvËzFVÊ!y)b!pææ»<VÅÏ·]Ï.ì¨ß"Ž%Ë8!¾l}Ò²Øoš1?OF˜’¿ñpfT5{ÔáfËœ nþŒ¯ùsvH†'#¹Ÿð œÙ£ŽÁXOƦL^® Ëb,jP?é(erÜûíLª™ùŒþæÑD(óÅóÇÌÞKðDà.™¸_à%Lò_ò·<0dMðâé'«€ÜqÜBļ ¹£èlq°†Ý€a2’›N'JM瓺&/LäÅ5ÞYØ(*ùðxÌûL<©‹e Ÿ…òyÀ‰%Ï ·ÓÂV ¸OÔÔÊ'ué•é’¹1qõóÞËþ}tY_/·èQ ëæ­—OêkôÂ2ª¸‡‹™öŒ>êQƒ9iñ<5OøœòÞcÚêkèq =ºgÇ[fàXúX '‘ŽÈ~¡nÞ''öþôÜ¿o¶÷y°«ŽF~Vc\ó ߌª]ÐYp§<=Ûûè’æ4¢CÇÌõÎ*Ï¡Š kkõ†®ÉÝÑ£ÁϺàŽÞÐNѹ÷hð3Û~ggƒŸIÏÆôÍ/–¡êÙàga+<3ÙàçÆS„߸!æºÚŽöìðó`+Σ[=ߎ=ûû<ØQªå=úû,¾âÓóݳ¿Oçã0`|\Yµ¡gŸŽ'/ý =ü¨u .r6ø<… >¬SýÓz6øQõ ì=$Ú H®{6ø¡7e4ø¹Ùò§™ ~x¦øÑ£ÁOc&Î"ü°„'nžlðóð,ò£ÃÏÀĸ<ÙàçÁ]_þ~xæ¶¹ùiEK^åhð“OìÉwxÏ?|Îq•£Ã>­ŒxîÙágàV>±ÕÔ§•®¸ž~Æ~SF‹ŸK³´d {xj¢ÇÏÉÇ/¯ìñÃGva«‹ŸÖ Îìž-~Ÿá<älñÃ!øA£ÉË™rßÏäËF=šüðm‘>Þž=~ n‚ŽRpáÏßü²^—Žu?®8”lðÓ÷iÇyòqerPÏ?AqÍ£ÁÏb¸Xº{6øákƒèð“ë5´¯×p7€ˆË»$Ëü2 6µÈžyÐ7‡»O«âÇzææðaÄÅãpsQÈÿ_0ðÓŠÜ€'?­øõÂrñÓz±¶GÏׯU®]z¸vÇ,luóÛ2Æ<ü¶¶ƒ¯-Ñp:báÕø½ÚdŸxçÀ|½mqÃ@†NmHM}Ã@ lÈŽ>\"j¹l ,Àª@a`TV„…x³rMa JÉU¨î­ò£²Q `Ãþc¢(ða‚AQàû»JM“ŠŸ&æšSMªÿZÌ# |† Oøhk ì‡,ÄÀÎ¢Ž…·_¦ÀNy£(°³ƒiQ ›‹;#7‹;uº¢Àβ”E]‡k ìS[‰; ìŽK + ” cE†c¾[çsm  63Fž†ÃÐÁx¤À!õYò10¨-?ÂÀ€æöN/4fÚº6‚10B†ÄÀL¼üÚ(0#U¤@:0f²sþV¢ÀLÄV‘Ý Þ4ŽßA˜4ŽyˆÁ?„>b`Dú€“‹¥ÂÀ¹ÄŽâÀE®2NÝAå}.nÌœYI0æÁ#dœè#´‘ ÃG64Ô‰U÷aCA–ŒÚPL´¡ ƒN6|t€FA½$‚ŒŠ1 fž7ÐêhDdИQð¤H%ôÝP±ˆ…‚›>n(ÈX‘ ™šR,x|‚à!P0— ¦)o$xdŠ›(Ô$˜«ƒÂÀ‹Dg 䛤(°H‘x²ñÔ†ºvÂÀK—¥0“š™Áµ1à… H²ÙLÎÜ ð"ò2T{ƒÀŽñ‚@ ™°³Aà$ sÒ µÒ )š›XÜØðn4¶›ë(3`cíbÀ?Q!àÍbý…€7_Ÿ…€Y¾…€çIŒ5Þº~FÀkøD@µ (DÍŽ€'³à Û!ܾ¿±Ux1ÿ¥ð’CÆxÑ?L|.!—ðäá/¶·/¼Ð­ðÂê¬ðb0pàÅ÷}`cU¤@6ž+þ»Øÿ­øï‘Ômþk'ïPó_cââ¿‹¯åâ¿pÉò_»°T(þkLÓ3ÿ)n©ø¯±Ó˜ù¯±ìYñŸ]æ?©ûÅ×âå2ÿ5VZ(þ;Y2¬ø¯éudþ;ù±Ùøï ²ÿ™öÌÌÀû࿇D(þ£c|@VnÞ° €zU6:´þå¬ÚPç K*Ï¥žZôOäÁÈTöÌ€R%Ì€e±Ȫ}ª79Ъ¢)PK S`{¾ëcŒ‹Û!QN hÉ$ØØ9«HPýoM‚íŠ/&v›ÛA7v‘ ±Î0(uÁ`çÜÁñMd1Ô ‡†Aq¨aðfFHÁà-Z0 ÞlvW0x3 ¿`ðÖ*«`ÕO Û)ÔŠ½`ð‘°(d™˜MR”"Ⱥě"(j7z…T8xH#´"øüÀÓ ‹" >§(N4x³öÁFƒË¢Á[ªœiðž:Ó ‹Ìl4xŠWEƒï¥}(ÿñÛê 4x#ÿ±`°±•[ÁàÍ|¸‚Á6yùLƒ7; ¶S˜)Œ>Dá Z-Þ\Ê6ú³6¤~_8ÈBL…ƒ›wzunôêÜ8xKÍ-<‘ÄÁX>Cm3>bHá Ûtm8Èš …ƒª­\8èËn|øö‰ƒÍZ¤pÐ?¯qðD~]ÆÆÁv õ„ƒùm…ƒeG6\ßåÀÎßÊ4èßÊ485‹iÕvß`m‘ ïÓx8í¼9>Á»ñ13 Þü" Þ·èK4X[‰of· FAšhð.> ŠÉŠõZ2 ÞŠ¶Øip|£AS¥iðÐ< AùŒƒ·.—qðæ%6 ÞÙƒêÚZ<øZàØ4b·ƒ“·‘aðñ­þ—•Ë6Ì/;>”Å7ld¥@¦õö¡Q Ú¤ªA`gZU`ŠÚFà<ö%ìâ2`WÀª°³£4À~*šU`?~|J€Ýl% °sýV _uÖ{S`§4@¿I¬ªDi€ýa$ªàϺ¹%ÀÎft%:DÜ`>à/F€¯­j*€]XÁ_ÖdJIìŒå7üY°7ýeÆ?C? öã›èWµé/ïOì‹ôcˆvÄ?E´›þò†Å!“þ€%ü¥2!á/=çu|‚¿Ã8NŸKM þÒ'ùµ±ßªûE¤@û`¿ ÿƒ¹f¿Œ/øÀQ²_„|ƒ†¡}耱(Á2Qè–þ~a‘2(·*ߺF¿´|ƒ:,Áèçr«F¿fh;úÅjz]nUG™ºU «D¿Ò>‚A3âC Ì$ЗR§âÄ„~±;ÀQD¿,Y Ù/›£ÃBöË"¼PùÈ~ÙX |HöËvlà1²ß¶w²_ÇexètyßãC t)\³_ž;,d¿¬ñ‰yK ÈaA¢àÏUƒ qâ !½”eÁw‰á/ýÛ ²»²,pk þ²S<æ!üe‡ Œ!ü¹ú„á/ã&>‚AsžúËbÝôcÏ¢¿Ú—èo¨¯“é¯öEú Gtÿ‡‡‹þ"ÒƒÒéÏÔMîcaúË€ ò ?­jaú CÒŸº3þ2Òãkc?w}0ûe‡ Ú©øn$ôSG“_îùk#¿ü¸C‹»\3ø|üÂ@Š{”cq‹1;ƒkäú…TÑa™Ê²`Ä‹Ñ/¶: ²!L~—"òs+“_v^ ®¹Iò‹×qcà'?¬Cb«È/,xq‰üREÂ<$¿|µb_$¿z ‰ü\×ä—E{Á‚ªNéä—u~Ad$¿, Ñ/? J`ðüˆuÙa£_&l}mð7ÔaÛð³{Ï?ÏL°i©¿]Æl‹Íòÿ ÈxòÁXc¯öµÚ@õ66œõ ‚LiØ@Ðø(|¦² ‚(…´q \áŃkTq  yŽ“Ú%1pPÕ. |Uïª/,Æ@÷/tÌ^ JÔ*!ÐcÄˉy¼GÌò$°HÎñ“øhùd%0㟙sŽK |G–ñjßh0*sag)°À$ªXeI}‰®6)šS‡ÔBIª‹i)p°;OI·3%v¹«-ÞâKèGða¼ÒŸ‹é„’‡Ô,ö%sL¨RÖ,vøÀJTØRZ¥ÞìÔ\*àÔãü-"´+d•"à輘UO©DÀ¨M‡1ñƒ;‰€Ñ|…Q¢çž'0(íS”—¡BBùz,Pn»»rE-N6/°Kùµ8NFÇZÔ‹·DÀ15D@y)~"K¼™jkP}4Jœ:‹€,T`”8û ¤úÚ(0Ênávµ¨Üÿ’×’$i pRµ$F…¯û3#p ±º@‰0 #â–°¸äà°¸[LŒâb¸VbÀh"{ï `vÆ…H(p]b72`tú¤Ü‡oj4Œñ Ùãcˆ€ëdÁP#`”iÌþÃ75¾íCŒr”ÏK_kCàjÇ·xÐè÷Š7–@5Õ,°[¼“HÂ`¼-ÁB°‹ñ­F™9L+P%bKÒάªèt)€ýf€¨À®¸{ €}|ÏìCA¤;ƒKôy[ÄÀêŸ]†VÿXh¿Ä¿.'…Å¿ÚHâ_gë2б‡%þõ¥ÈO‰]‰VÿºbC¬þõ)(”ú×Çwõ¯+–Ö`gdR €¾Tcïˆu³ñ¼oÎÚ93*uö¯*ÖCÃ^ŠìO·ªAòÏ*˜XëÌ}e©ê^²U¡²Tu¯™›?Ö–šK¶š«,Û\+#÷ó¦a› ¦m"þÝDz#X\“½âØý7ªˆMZŸî?ýó¼ÒérQ¯õúÍP}¨»úÐÏ·Ìx® >Â* õíæ‹kkù1ž)ÚY]Ì3ѲÏäAši£™Úyå«·f’e›©q¦}ŒgjHÚfjJ'ª™¨‘Þ™oŸ÷¼à~bw½×°à~Š*ÛØ¨çNÓã×±«qƒiÉõÞ§'˜öaIê×’É é~È_ü½¹;¨¶3#ižYM‘rȉT†b£×²ÐYåÂf.óˆa8š³Ý„Z¾¬ç‰Pß}š{áAíô™¾Ä×Ý^íÂÑô†5ÊR¤aœxPÑ"%-ª"Kæ9;žÔšf5<©ƒ•óÞ'åÄ“:ùúZ&žÔÁ¯Àû vûŸòFyŸ¦†'u²-Ìû¤œpta‹6ñ¤âÒ]Éúþu‚{g¶4ÊÿgŶ-&§È÷×¼;˜Î§Ž} ÞFtOî}ŸÆ†ué.Š–Fù .ÆFÏli”Þ'f´Î†ŠÙ"3{ øwÒo4£§Q>©K·Hö4JÕ/ÝŒžFù¨†Œ™g‘=ñ\&ácy.+L ÁsYä#ÿ&ÏÅ\sñœ½RFºšEH—…-òœ„tY`;*!#—Œt`4ÒÕ)鲿!Ó؉yÈtÛÌdºù töšè²-KÅàðÎÐet0€.;v~»}è²ò@þÜ:Ä5ÐÍ&й!›.²¥<—ý×°sò\LC $ÏmÓçâpp 蔸ožËœhy.¦Á _<ç£ÎeJtþÞ¹˜k|â\øçˆjĹ,r$ÎMÕÏ5Îm[çb )áܼYtØ8r1C‚oZÎ… ¨”ÁêÍ"œ ß!7ÎE0 7Εw‘8—a"€1v§}X×H<—rù7{Ó>¯qnÛkÞqO牑çb|€’çÂÇHÄÏÍ.ßy.cRAZà9‡/Šçb/y.£Cò(Ésq^˜8sÎçÂCËQæ$ˆæbô–8×…{ÎÅ.qŸ’ç2® #–Ý Ažs$€.â)óR’ç"¤ÿœ+,qn*Í8çîŠÂ9Ÿ6in½C–›ÌiÊeèöÇßÁF°B¹XÂ}K” ñ…­äMxÿ^æƒk ™æbã¾všË¨É\–‰æìR5ÍÙÝiš ')­¢¹©d.Ýœ—D<]Æð}tä €nª¼­‰ÎnT!]„Db¡.¦‹!PÚˆt1„‘.,XÔ éjObº3IpüöLâ¿™®ŽFL·”ïn¦[Ê×6ÓÅ"¹}0ÝR¾»™n)ßÄL·”o¦[*Q-¦ Ÿ#1]tByéV§›ÒH–IˆtK )Fº°ú\ì lF¢[*y`¢³WÈDw}ƒðG¢³“ÇD·ÍC¢³ßÇDHë'¢KÈ"‘è–UZ]Œ›D· “":ûn„tÛž‰tr™èb*ƒ$ºe$Ñ­ÁÎ&ºˆâÂŽtá%úà¹Ø¿“xn ©’â¹s~(ta™÷$œË2jvÀ¹Ø÷ÂÄĹmWÄ9{”ŒsËê5qnBžËwÚ.ÑÅÈœóÁç–xØ8;jÔã€såØÎ……Òq.öý`+â\yÉ„s‹ošÛ¦!Ím‡Cš ÷Þø¢9;ìskXÖ#Ì­ÉaÁ\ i4·”Ë,œ‹!X\çj^áÜš É7Î……ØHœÛ,ĹH«€8 ž‹™¯…n)GÐ@8ÄtK^3]|´Hgdº%‚™.,ëƒéâ꣈t1„Ø—¿÷d§‘.¶ yéêP„tK9ÓFºò´ éÂBà$Ò-SéêàˆtÛé–ü!Fº#¤‹]ݰéÖdºiits~ÓèbÌ1Òè|ZBº%Nit“•SÍtaK£SˆHitu{,ѱ§vIt³ÿø º¥4ëé&K˜–H7µ³H7WŸéä*‘nNiiéâË‹­$ÒMéÎVéjïRé& q—J7¥·X¥«ã‘J7±kJt ‹)‰n±kž%º)™ÜÝB]éRèËë”B·‰^ ÝbÉ­RèâÙK [¦@ tá€Â4èÖ)Ä“@g™:æT—@·Ø¼°:‚õ¹%̶>çŸÉúÜbWÄÒç|4Òç6¿©>ës‘ÆŽ‰¥Ï©ç{és žü’ç|‰-Ï-)Ä’çÖ…x{ËsKj0ä9ßS’ç|h’çtá¤Îé’8§,W‹s«‹÷¨Î­KtFu.¾ØÕ¹ð;‚ïp»±–—å¹Å^5”çÞ?/Òä9û%Ï-{µ<·ä¹EÑQòÜ{íû‡)úA}nÉå!}Î'"n±ª:·ºÚ„šOP SpšºX†âÿ)Щ‹„º%Y_ NUÿ¦>·ä’>gg¯õ9¾°ÿE-³¹;¿Ò Ç/xœ‚w ä]^rï[äÈ ÞÒrãþr¢à¹¡ ?\¬Ç°oœêäÁº6Erc0R 7èš*“'¢@.êh‚ÜP˜šA®Æäb ô1Üf!È9jÉ ¨91¿9nª¬Ž9..(bøÈqŽt2Ç…åpäêgÈÅOG²£±fQœeWh ã,‡Bøg9¤Â8ÎrðµY–ƒïÅ ´Ty¡Š´—d@EZÚâHK•œªHËÁ7rEZnúß µüZT¨e `¬åP¼£ƒ-kV[ÒT±–5¯b-‡ôfÇZúòYšcÚW)sVU­Ìyˆ„9«µ欳Z˜cðBér5Dº\—3ºœÊ¨•.Wérp¥Ë•Aœ] s–f-̽ aæºÔ sà°0'Ø/aN2p s}iK˜r»Z˜¬[Â\‘0W sÑžæ}i%ÌÕ s¶å"Ö{0´òd&0¢4§üÕ’æ†âEÅr!8_ÒÜnË9ˆÜ,ç r³œti£Üp4ˆPn yˆ…rƒdn’³šm’ Ëø ¹Lí‘ä¬oåâ<FWž›_êœ:ú–:×\çÕ]âÜÁ¸„ç…úZœ;~ ·,ePê\ Rç,8ZS£êRç…vZ;$%XcÜy‰sêV°‰sRKœ“‡»Ô9ŃZ;YÏÉêœåO«s›Ö³I<”>Ô#Ž:õN£@ga\º­Y ³˜.îb $ tÝ7ÒçÔ!Âú\(Ð]4>5ê`\ºK.#)tõÿTè®þM¡»ä!’BW*t—¼/Rè6ºKŠºK!´’èÔBÚÝ¥!Htíøº,¤ÿ¡ÑÕuå`ê‹uº&‡„t: ÿÒéÚõr™½öK¯ÿF…²Â;¤$íx×à‰(º»%V˜î$Ý=|x‹î:=ÓEw¡&¦»Ã)q¢;¾! w|ÊŠíN%²‰ít´F»6•Ç&´kK:žØNÍŠín®2‹íž®ðH±r_6¶wÛÑ—UlÇ$B»ð…v¥ í–óþ¤ÑJƳFwèrJ£;NåÙI£Sz„EºCk‘îbÓÑé®CZšDº‹§`ît.žD:õ/‘®ÆH¤kR«,Ò)z¿DºkŠ%Ò©Ya‰tÊñ‘Eps}Št”ŤÐÝ”*¨Ð=òEX¡»EKR¡»åä°B×øº.‰NE–K¢ë'U<)t…–J¡S8ú&ÑéÇ.n(CÎ3q6Žk¦Ò褕Fg™Ñ"üþ%ÒIé)‘NäéäëÛµCá~é–ÿÀvïVýµHWóJ¥³+l—ó;Ûµãä]#¶{ÇhÙN¶{-,˜(¶Ë­H¶k‡¿¥d»×rjï`»íÀvíhtÃíZ–QD»rÐ’h—ÓÀÛK´{G™"@»wˆt¢]Nƒ‰v-*…µ=îÝè[Ý;FcD»×¢œ ¢Ýk‘?•h׎›QB»In*d»w+Gx‚íÞ­% ¶{Ç é·Øî¢ßl÷ZŠd»wWM$¶{->Év¹c$ó¿‡â,Áv»%Ù.gÅnÀv¯A¹ d»×2¸"Ûµ£K^#Û½–›±{d»v 9°Év9·Û½[Y^Û½[I Û¥:ÙîµÈýN¶k‡ü”‚»×ÂÚô‚»×–M‚»ÜêÜeºvÌ[q•€»÷*Îp÷nÄf`‚»²Ét9mÛC/[”Š£x¶{·aô†Øîµ°õØîÝŠeÚÄv¯…%¡Äv-“µ u¯eJ`Ûí[îr«kêÚyJl"ܵóP^áîµ43à.-cO§{-“ïÀÝk8ø îÒ2¶èË×ÀÒl¢»í¬Hw9/~ÒÝ{Äâw›l—ç„×Ùî…M-Ävïú˜Åv¹eA°];ÕÁLpײˆß|™;ÇÍE¸Ë™ç}Ù¢ÐßžL÷PWYh÷nêKB»¬÷Âyí^{÷ í^ &írÜJD»œ¦äòóúZt»í^ B»v6ý @»×ðX› ´Ë¸ÄvïŸMè—l—dž_l×¢’!l×Î{8¹.Ø®Å똱–Évï&S¹nÉv¯rÉví|Åk&Ûå&ØkÞp·bÀvïø›ªt°];;û©‘íÞ t‡‚í¶Àv-¾L•K¶kQ~Ïà.G02áî5(,p÷XÙ”p÷Ρ{(à.’@™p—§¹¶ðË×€ª‚d»Ï-›.jmÙtï>YÎŽl—;'l÷^ Ý_€»v:§p—#n†[ž:nd.lÝ,Ùîý{HÝK¶{ Ê}Û½ &ýíò¨ðw¢Ý¾K–AêzOíZ|ŽÊw¨œô°ÃêVxlõèrôUdÞDKwÅYöbºY âVxì<ÎÌQØv`K•ø’­*锥Š|½oíð÷~Ì%Ë>lû\²ls½+®£âßÛÐ!AåïR =Á‘?žkí÷º¡CÂÃx¢×žàÈÏõÇúˆ<¬ÏºÆ‰J޹4Xã:õ!L~ t3Ÿ{ÖÑ×êÄÚ}(§ Gqºm×@+4&!­l8 ÿÄ=Ól„†cÊžN•]½"-xBÇ™Gr,3©;FDG¨Ú‚°BÝåè•¶!ݦð5LhȹÏÔ '½«¦öU­™VTn¢XܱAԼشâ•^é-õx…Sz"_'þÚ IÅévZ¨¯\ùË+sI¶´ã•Eq`Àq¬ã@–oòýû' àÒGɦꌾ°&Zlq¿¢0 ÛÓ¤Or¡È š»ä=´n´éQÚðZ‘ë…\cü€Yiã«êŸ­È«8·<Ý•Õ"¾2›öÆ^K ÏnÔøûAÍwYD³Q3O'ÅË»áÏÛ¤Ð׉«_Nâ ¥Pj¬¯å‚¶r0¤äµ4j¡”5_Ë uEeXÖ]è|-O—àÌ:eÅ“Ç2 °0 5 óÇÚÄæ×2¡°Hü{-«A<º4Íy Îº˜‡eB¢?8Ö«=Ï@Šßk‰æÖ›òõZÚ)é‹ûͮ͡Äys›ÉñJ€%…î×ÒÉ_ƒÛD¢Ë&ˆ½–ˆƒ¢=E‡M8z-á;~¥sXlwÀ(£ó¸òWÜç¹NÖ]»p%® Bhø¹ÍÅ=üJWƒÚ¦®çuC U­¶×ò@ UjjX ‡F yî¹C•Çñµ ¢7½¯eBUµ¶°° |ð¯a±zÛÄmÕf-2É',ëÓE;v‹»ûcG-~¡¯Ê}-¹‹ÌÛ z(cîµÜPG è¯åÁøÜz8Z‡>ºÍӗƯeA#U©¶°@$}Xáë]ŸPI¥i½–“‰Œô¿– :©’<ÃÂTFŠ'¯¥uä*ÝúÑGˆ1n çpg©”Ê™ V'Ž˜m„Â!ÐpµîÁœF:d_  Åžxm¢“ÐÄN»XhÝE#¡-×2–r§B/YÛ¨ ã¯åʯeH8|!E¡ç«"_ËÍ|4¢‹kÂñ–.BŒi8§è"Ä‚ý“³ŒãÇíi¨yxOD¡Tùu- HPm¹óˆ6BÊâ³hI¥ÑT4z>·aTÂô#„˜<É—l4ZŸóÜùu ãkyò ªLÈ×Ðó †uÒÂ$Lfབ‘ßÐ(B×9²0Ytáµd€Â6 õÝÚf0Da1îµÀ¿ÒÚI ‚äª~-W~M­¨¾Æ),?BÑG( à ]õZÄÏ×ò œƒ¡ ®üªRv¯eä,Ôzâo|U×à) ©ÔâÏ•ŸÔðbñgŠZìûÀÀ”¸K'õka¼B¨¸Sêî©[m2ý`JTXò›3óA C?üu™©•~pÙBhÉ-–‰èú°‡P¬zø †Àç°ô;M£ÝG¼ò«Eóx}S«Æ¾œW~ìSZ¾hɦIûñ„^çpúá])ðž~t£[žƒ¿c‹ ïyè¡[Ùwã i•G)¦óâRDBá…ƒ9ð3d²ÛWÕý K~TC.¿8Ízp šø<îoæX_à¸r ËÀáQ\>ã ‰S`¾À%Œ©yo¤Äý?hAâHtGàÌ2G.–B8ãµçp±îäO™Î0îâ<‡‹a gÜ'Øæà¼Ôw·}¯ü®.9õϘ&ÏáÒêñ ùM;Zèóy?;x OöŠ­x-ì)b>êï–+ŽËÙÎq)‰§u¾PîfÔ‡Qîf§£ÜÍŠÇF9U 3ÊÝ|Œr7½EsÌÆ7Í=ËMs*×gš{øìæ…hNÅ®Ms³–Ls€B4÷vJš{náiîá÷Í4§f¦9c+hŽÍLsÊb'ͱ` aNåÎ sªmf˜SÒ»aîaE_Ã[šåT®Û,×ÙÏ,§˜ ²œÁY,ç „sêoœë¬[dœc(¾i®ƒËˆrýJe”ë 36Ê)äÞ(× UB9ÇÎå²¹ôW¡œ£ä…r˜ƒw"QÎaóF9‡Ä›åLüf¹@þñÁrf~³\Xø5 Ë9Þ,7ƒÈsû6€9·›æb.æIsŽ‘7͹¾ši.<»ùƒë|Cæín˜S´»YÎ~³œCÙÉröD˜å¶=åâAãIå²1& ¹ìö @Î]U rÙVš§S9ws\tÎ$ý]*ï¾>8n›äRf®ÅÈq1×:ä¸ìØLþÇ fó㢗?ĸ˜f}`Ü@,TZ€qCíÇŒqaYÄÁŠ®9nL/9Èq1/¯.9n·€ãbÒ 9ÎEÜÌqQŽë]rÜ`Òª1n¨õ•1n¬C$JŒ —דM}ŒIÊĸ\rGÀ¸±¼r!ƹ¾1.Ɖ@q1„‹[R\¸†x…IqûPœëç›âìr2Åm˜·oÃf°Š 3Åŧ‚KvQÜ!$'ÄíÓ’â^¦áõ$ÅÅħ)Œ‹ÑÄ-bÜ{'ìˆqÇiH#ÆÉå%Œ;ìÆZÚ㎦բ0n³ãªVw\zþ…qL9)Š;ìiÅÕÄ 8UÀ+Š+œ(î(®#ÅN¤¸Ck&S\yîDq‡? ¸chA.ŒÛæ!ÆST§h;aÜ»¸ô73EürÆ•Pwü„qg!1î¼užÂ8å¶Æ„-2Üù N¢îôË^ wúK†S¾B1œêíâœbŽs‚9.||ã6¯¡8îìºóÉqNa0Ç9Á—=ƒIˆŒ>/¿æDÎÅØ«l9n;÷‚=ô€“㜦`Ž‹1tŽ‘ãæe79n;r\ŒáÞÉqÛÞÉqáå\­Î{Ó;j:%ÇÅÂ’î r\\F:–Èqû€Üæ«%ÈŘŽÛœ·ä8çWã” aŒ›ŠÐ4ÆÕ 㲟('Æ9éÂçdc\luqnŠkŒ‹›åä¾€q®k¸m0Îy¸xEÌ’äÖÍÔ%a\MIŒ‹ €ÐĸÄ3rêWœ— [ž; œëAåÚÁf6$¹÷ïçÇrkî‚\äs>ÕBšüs¡Z‹x㢜—<ĸˆû'â¼(®EX¼( ï¸Nk,6sÈg Šk‡nQÜkéò¼âÚE%‹âÚñØc ŠËðnî(!®¥'â^‹ƒ€¸ ©æR—a×<P\‹8~Â*(îÝŠw•(®*I)ŒËu~\qˆÍOé™áñ¡eì’\Æ£_»$—órÕŽË`ò]‘kqøÈeÐõ¶?þr.’kǰƒñÊ´…Á°]‘\‹—ý]Š\îgîŠ\;íÇÈe 1йŒM~v’kÌLHKGk9^ArÌ+’Ë8hɃq¬g·@¸ì› \FÜ’;@ríl÷ä2˜ô——ñ̼ÑÀqï¼×Ýʃ;ºV~À¸¼ß’ãÒÒ$¾!¢µNW!ãภ3Çe ô³Ëqï˜ÇRàB\«B©ÅqïV‡nE€\n%îBhë5´o€Ü{†ÔU€\‹ï´€ëFt«ºÞärŒô¹…¸xn‘÷þ¿×®À¸ü±û.Æåu Lƒã2 ž??8n¿6฼Â\KƒãòØÕ¸ü¡>0îÝhê–ÆU”>0.½—þž¸ÀS°•WŒç›—‘èM\7qLÞz€¸œ†wôÃò«™›’â*æ·O ŠËiy9;£ÈãQ¤ˆ–—çÄ0 P\‹¥lP\†u‹µ’â2ž}‡¸†7 ±æÃt˜ —>`¸ŒG§*Ù3žü>­ &ÃåzÍÆ·ˆr1\îš³ Æ”G³d¸Œç¦n9UÎvb¸ ¨'æ)¬ÜO%(.§á=ŠËXt.؃ârí:).#Çyñ@qá.ŠËKcf;Èýð`qùÌâ2…@Èv!¤Y}ŸŒ0¿,vâ2—‚/¨É0óÀ›ãòzö]ŒÛ¯ .Çe&#ÍëÒâÞ­š±Ž±æ±øæi&Ľ–C .ßÂ}ãr«!éíÄ9Üz»âÞ1—¾$qùÐ}@\^¿k‡¸œå–<7¯Ë]'Ãå´\±€áö —ct0 qyÑyNÉp•»†Ës${ȱ–H†ÛÞ`d8géáòëyJw;ô*¿ c7¿§Ï2.Ç4ÒW÷÷´ï—3Î<ø=]FÁù`›‹ó.|OO<Ãå*|`¸|çªlÉp™suJwãõ¤‡ —Ÿ‘µ+qùÕ½£ ˜Á-#´6nSAr‘ÚÜv}“ß̕涋ÅÍmbZsÛõM~s ”¹MÐkn»bnSæ¾¹­Á#LlkÖïÈme ·©¦Á­ 7U 0¸5k€7ne ¹©eÉÍSŠÜÊÐ>ŽAä¶ÆG ‘Ûf¹m›€ÜêÔInÛ& ·í°AnuØInõÿ$·ÚÉmrÛF€ÜüûÜTîAÜVGI n›\6Ém30š²Žb^ÿÏpÊ20œ²Y#P8¥+§ÜÆ0ž²I|P8esè‚Â)·iN¹MÃpÊË1O §ÔeW<¥nòЧÜöÄ€JsT^K_:TÚ5å€ÊšG•>)ÅSn)žÒ¬xÊm ã)ëpOYÓ2œ² ”àºù$ÁuÇ«Jƒëx’·Y(Âu»Ó%•E*\fµTáº]ÜRáºéPá¤ê– Wº­T8•/®›Ô%Ãu»×%à ;å%à Ç×J†S¹³’áJí… 7­—$éPyÉp*T^2\)Ä’á†#´$Õ,®Ô^Épñ_ÒáÔ»t¸m u¸HŠ%õ¡œ—fÒáFeR‡[€%t8\(N‘ì%Ä©Îw q*¬VBܨK qV‰¥Ã•2\)Ëá†}û’áÆ´tGnXi  7†Òá6Ëê#-Œ:Ü´"@Î-Á¬Ãíc Ã z](Â…Ø|m±”›¦MnLËáv D¸Ì|%óA„Ûi%Îë[,eXøèR…ÛÄpªpîEF.þfØU8'X… ]»}ÄRn‚9U¸Mû¦ ‚yßù--'·êLGØ,ÎGÐVƒ #9Ù£p:6U8÷f· 眫pc:’—*\ŒQ $T8÷W³ ·é÷TáÜõÝ*ܦßSˆS[6ëp›8O.ÄyÞ&©Ã¹+›u8÷`³çÌ ëp%ÖS†Ëß¹©†óþP†Û-ê8/ñD2Ü)@nn¨Ä4e¸± ®”ᆠU[† AŸHn‹.  7XÚ"ÜP j‹pÎ ±WQƒÛ"¨ÁmJ<5¸- 5¸¡2ÆÖඈjp|S—ý_Ôà‚\𦡷·[ ÂÅVd&´ÅSjD87¸³W¡áÂ29 D¸Šcç¶wáÂrSƒ7TpÙ"ÜX¥ .ÆX–ÃGuÛ -ù–EBªp‡° ç0«pLÞ)îPà©qUcÞ"ÜPžÊ Ôwâo”s4%^Š[4åH!šRƒ£)µ{GSNf²8šò}c^‰qz©:š² Œ¦ÔËÑ8§€Æ9…]çNDw™æ˜7DšSRŽi®R4§(DÓcJ†SŸhNMÀþB†“)šë—Àédo,DžŠæºÐ47ÌY¤¹ÉØZÓœRLs¬úb˜SŸ$ÃÜäšÖ0·XîÑ0·C8ÉrrP…S™2³Übô…U¸ã"©å5£œÊ—Ǽ ‹p甲˜‹wÙµÃܶ e8Å[‰kÍÒÛç TâHm%NõÌJ‰+¤¤¸Ûü„¹¨»Åű¤¸æÀBIq÷вŒ4)ÖçÍ­['Ñ\Të’2˜UÑÔ‡×4×B¹{ ¹ÃåiÎM»MsQó‹ó’æÜJÉ4•ß4âܪ>qέTŒsÖNs1†’8j'=¤ä¹P;×йń.¾&ó#¨RíÌsËŸFâ\|o¤碻׀ĹU‘m‰sî aœsIqªLf)î8Áµ¸£b®¨ÅÅV Í„5Ï$ B‹‹1¼vÔâŽÓKwjqGÅeQ‹‹šggEU¾³¬ÞÒue×Djâ⫪t9hqÇa9”bÜqÈYK-n;ŠqGûPŒ‹2i\ÓRŒ;Ú&½¥ï=Šqa‘¨—Õ¤“#1.x>Oã$É[‹;*ë’Z\”‰ãíJ-.ª¤ )o©ÅÅÓ٤αFÛé¤6jqMꥸØHH)®r S‹Ûdv‰qÏám ÆÅÁ¬1.J¶YžK1.2œb\A£ƒœbÜÁ5•¸(›¦48Hq[iZ‰ •¿•¸ØÈìvB ×´PâBò;˵£[:¤ ¨±³\Îó¡Ä[J¤¸(ËÇ—'¥¸|÷) î€^~)n4¥¸  A)îP§CKq/ 鎦oLjBŠÛ·‚Êá”⎮0lJq‡ú8X‹;*óZÜ¡âÿÖââÄÏ"¹”ü›þŠY“A‹;*;‘Z\ìI‰fÐâ¶ÀjqQ A-եç xÖâb¥+´ƒ§À×?µ¸mšââãò(À2¥¸¨wï ü .B@nA[êpÇÔ[†:\ÔŸ#‡R‡{¹ÌZt¸c=•‡°–ÙßA.?†´@‡‹O¿CÐáŽS×’:Ü1ç7.*Ô}$ŽcŽï:ÜaU•:\ëû¦Ì#þá¢?p”áJª‘ ¼öœ¸íj¥ JË£ wX” WRá¤î” WÁ”ᎨÊõ!Õ´)®¢B¤Ã½‰j©Ã9dÁBœ·±w°`Y qÇíhE*qï›íÜ9.Ïa)KJܱ½¥Ä)„FJœ&,Ä’­Kˆ{ö”¸ P'…¸mGâ×è’7 vâ⟒ÝX¼èÀRˆÛ-â$8nµÂÎ3Øè£øK»èâv±0Zö²_¾]Ò˜X.ìº2kÍóóï­,WZ¶8ü{+íuE¡ãù1‹,û<°í3ɲÍÕNzÑêŒeÙæ¢m›Ë–w¹°ó:s‘üÏÊ…ÍÿåÂ~q»œáŒ8¿> †}»õò¦êÇÇÍøG͵ã\{É0ÍU£4×Ga1̵—Ã\EÃ8×6Šs}–ã\[A0ε— Ó\5Js}ã\[I0εÓ\5Js}”ã\[Q0ε—Ó\5Js}ã\[Y0εÓ\5Jsýƒâa/.¢ýÿ_=ì·ª‡ýÎ+ýŸ^οzÿñËçöûKýOžÛŸæúÛÄÞ[kÄ‚úÿìbÛ[ô¿ÿçߨö^Hæß©¹|¼s1™_œ`˜†lœõÈKÎëRÖ4ðéLµý+Ӡ銞 k—;8KÞ„Á™ÿQ@&ebå–áKL[åsÎ(µÂ&ÕßêµLJ¬]ð“ÉÆÖFϹ˜`Ëò‹¹Æj’üZÎSeºxx‹¹ÆÎH=×ÕåûåÚh1×x2]ÿµÜPX#‚¾Ñ…uN²ÛMÓû.ʜѕüÜÕ¯e0Õ‘ùòaY»2rFþýµ%6žhº‰×Á\㥲 WxhæîÊ¿F:8kñ:.$Ù¹Œt8伻¥@öà˜ŒtP÷Œ÷Žtæ\ G©¿PX˜êˆL×0àÈV?Ÿ×2›RìNŽYpeŸZò]Y—û+þp?^±ŽÏ,6Ö8¹2ÌíkK}»b­Ú¿Y2NëÄíùÌ_»NV:'Ù+ªó2û«Ë¼(y®³Ã¥­¤¬ëdÑ(çq]ç„SÛå³®“E£ùr½÷Œ¢epµ/–º”¢|]g)I£{ÿf”ÒãÔt]Wcœ’‚‰_ •”Rûn„P¥›Oò»âe¬’|²×Õ¬DìºX2êf‰‚×2­T±hÔ­*lוM¢nßcKF1kê¼ÚÑ•%Uôj¬¥Þ)¯åBÀÒÍr aAŨ[áðWk]…»8ñ}K `_í9•tÔ8ñ³TKÓô®d)pYáŠ9úW›§²¼x§¶‰p%{¸ÞËp%ÓºîáJ.”uÝÌ4~T[çµ \éa'±×ÂLc»½®»!^©+.âº3ÓøQ|Èû7¢•¶m˜iü( òº;–ºœ×ïí€çÏEº^ 2»Â®{"ñû&¿2»®ç8TžŒ×3liŠ+±´—Æ\ísDCŽã6‚©Æ]WôÊsP’ýõ0Õ/Î+š}Ô»Ô Hs^Ë@‚ã7ør¯Wù¸®htbGüéÔÈ®¼wMšU¼n4z°'|:¯hĺcüqûmuø1í âªkt]Ѩaf¾Â¢!Ðøª¬¯åAŠãðCØ™j¾&n5PÿmH3¸:“íj¼úd50ÞH©ÆSîê+ú­yÝëÕ[‘ŠCíãKÂÍ^kLCý·Éö?aÁÓl7l.f²lÄYæÄÄ8ËÁ¨Þ©¬öˆDËûa`¯ÚVœ¶ùÊ2^gahïìºÍc{‡ê$å÷ïžxóMF÷NÖ£Ìôá&Üž,Ü?-™g¼”MŸ’ã.µ¾*Ä«yf¦//EâåÛUŸkI&VÛÅ~@Q ÷Uˆb_[±µ”ÄxøýS—ÊsPžE ?Y®L¯ËvH.f3›3óù+ nÅèߥTø8Xü ï–"º«´¥èÀX<˜Æã‡Þ÷íHÉØÎÒ­€nX:ŽÀK_¹Æ.¯U-}—¬þ†›¼±Ík,¢±ë“šq4­äFÔŒë:œÔŒ‰\™årîÅÕÚÉà% ;º ŒÛÍ]S3>UÖNF;ݬŒöïßNFûñiÑ è£@`»<ÙAᵜ]osþ*C€Õ_ùµ46J†7¿] öǧ©Ïk4´‹1ÀþÚÈITøv±¤êÃʱ¢]××ûÝcò%£| ŸïŒ|‘† ?0˜ïvU3Ÿ–¤Å|NÄó=NÄô© XAߣuª¡ï1éúI‡†¾x±“è}¯…É ¢¾Ç„êS 뢾p^~RߣO¤©o³úÅ|™úTT¬¨ïѪÙÔ÷è3jêÃwßÈ÷8RLȧÉ{‹é‰÷ž!Pï= $3ï½–E ;XÈ{jÉLÞ«cïí[±ºÔ3 ä½}LV—ÚF<¬ç!ÏÕÒ |å'ñ§u²œÔD|±Õ²œÏŠÄ·mEä ?D¾°pMŸÈ·oÓXnQ9õíÛ<, Wó2º}³ôGçÀï5±o·ûÂyKØ·[€}aÁ‹UܧrrľmZbß6 ±/,ëûö1â¬'ìÛvôÜ…ëŒ}aiÜ·mìÛ÷Íàömßëúœ–¡í*oîÛÆûvËuê ´CÛ·1à¾} Ào·ü>,ˆªÝ,¿°LÎ<òˆU£Vè·oôÛ·ap{WUK¡ßnap{mEôÛÇ0¸]®6‘ß¾Ñ}~üN$¿}ÃÛ»ã$¿}G o߯Œùýæ£SàÁ¬öí&!ø……î%‚ß>æ|t üíüömÚ¡S°eè Ër?ß~‚ßné‡NÁ–ñíF'ûÕIýö€~ÛF·×$¿íI%ùÕ&¿í~ÛãCðÛ.Áos¯o·9Áoߊ±íõf!øm§MðÛÕ¿ýoƶ×6¿m ÁoSr(˜à·øÕ›„Ü·Øf¤Î‰Ü· aüï6¤¯ß€Ü·`pýä¾ýà\rß6¹¯†Ü·ùÖ#ƒÜ·ÿ­‡)ïÐÑiµÉðî''0Õ'ÃCXYu3Ìo¯ABßvŠ„¾ÝÂâªõÚKìÛŽØ·ÍKìÛǰÈênzÏh^–YÝæa`{½‹VZåyûê4—J­úµGê«@}5BÔ·P¹UíZÔW‡'êl½kè«7¥ ÏG'æÛgyÖÇ ˆú¶i}Û”]õÿOKu>«~‡„|»åô·Ô>}>g2ßvBd>×­5óÕÑù6Ë®ú§ñmXuµ«D¼€o»L¾}Ç«};߇eê"ðø¶S"ðm3'ðm‡KàÛŽÀ·[XwuÛªûKª}+ëÓXú¦öý7ê‘ú¢(Þ‡d~£}ê|á)ô…‹^² /÷;-ìM!_º ¯Üö‚¾}  ¯úWúÊo/è ß>)éÌÛ0߇®É{|(}ñ7SWÈ|%ˆùjGD¾0,òÅ4¬NäÛÇù¶]ùÂòp Ï)¦¾°\¼S§ ­²Sýíšä¿ýh«ÅiŒÀ¯f±ÐHO™ŒB_47¥ôG¡O‹KèÛ¶¢Ð·Í|÷ý¼-ôÝýøí{ê.G÷¿¤¾ÛÞTI}*ÜVRßv4ËÕã(•Qé«K!©Ï÷€¥>€“ÔwÛ1*µo›…jŸŠÊ•Úw+ÏÙj_ ž:o©}Û®©öÝrÜJì»-‹JìS!¿Rû¼ľºšûê”$öÕ&ÔúêòJë«=[ë«1ûê”$öÝÊå.µÏ×JjŸoüRûê×õq5­öyË}Öפöù,­öé'°ØçýX쫨öÕ¾¥öí–õí7ØÔ>Í<>oié}Ê©*½o³\µñú¶1Öû†÷–Þ§²²Öû|â’û¶i ÷)þ×rß¶kÉ}µ#Ê}Û,ãøv“HîÛ¶¢Üç{Mj_íÜjŸ2õ­öÕ4RûêîƒÚW,µo›—j_ýrRû¶Y¨ömóPð«_J‚_Ý%ü¶ã£àçk.½o›fù9¤&½¯®žô¾ú)¥÷Õ,Òû¼#É}Û4”ûvËÒ¦¸#¹¯~LÉ}~¢¤ömÓPí{Nëˆs|lB±Ïé ûê ±¯~'‰}u’ûÜžÊbß¶žGÁ>ûꀥömc(÷mó¤Ü÷XÀ’ÜW?‚ä¾:mÉ}zôXî{Hn¹¯îjÉ}n±e½¯f–ÞWǽïQ™2ë}nÂe½ïQ›¿m ¿m^ ~um$øÕï ÁoCÁïùIð«½KñÛÆ ”AXVü¶TüjGRüêâW—BŠ_… Hñ«—âW—XŠ_¿úí$øyWüü{[ðó)Xðó¯+ô«y-øù`,ø=ŸjŸo«}Û¡°ÚÏ6†‚ŸÏZìW?%ào?ܹtpŽ‚Ÿ¯¦è/–ñÆ’?þUDÛ<¤¿í$Iû̬ùSÇCüÛ·¢â÷(t ü·ï‰5ê¼¥øÕ%—âçE¾?¯Z­øÝ…rTüØdÁ¯v.ÁÏ…¤)øÕ¥‘àç'Â_¤¿:` ~>) ~¾¤ø=…ÿE)³b>”eß™ïúÛ9•{(äS‘#_s¡8!_s!_“däk·E"_³þ%äk.{ äsE3_¤-*–ó¶j+•±ª­’ùšcOÅ|5‹˜¯ŽXзmEèÛ,*cUŠ¡¯ö-èÛ,„¾&ÕËÐW×BÐ×\ÌзÍBèknÁ%èk¬9kæóFf¾VœÊX•…Ìçƒ1óµåÈ|ÛVwÿAæk%’ù¶mÈ|n¼iæÛ,Ó… FJæÛöEæ«óômB_ ¯öèÛþ&ôÕž}MºÞñíÎê ªMˆ|Û¡ù¶C!òmó(À³,d¾šYÌ×’ÄOoãOÝEáY³(ÂÓGãϲúêâY– ñäm#êÛŽG1že!õmdzøDMQàúvE}›…ØWG#ìã%è« !èÛ&!ôÕ¡úêBú¶­}ÛÌãþœ…ÐWw° o›…ÐW{ôÕ) úêÒú¶­}u4¢¾Ú¨Ï¯>Sß¶Íóý)õmGCêÛöMêÛæ!õmb_Í,ì«ãömcˆ}µ/`_°¯ö$ìÛ,·ÛüÊBìÛöDì«ßJØ·!ömbßfYÇ··¸¯öîÛþ&÷ÕY‰ûê‘÷m[ü6 Á¯ŽFà·yÆ·çAàWG,ò«;YäWWä·í‰èW¡_•Яö-ôÛ,—?¬ëý¶yˆ~uçý¶½«íFYúùí*ý¶=þí ý6Ë:¿Ÿѯ®Ð¯Æýj_B¿:>¡ß6¦õÏYîï_V¡ß6Få\}çý¶­T¨ö=oσÐoÛj=ßž¡_í]èW×èWG#öÛ¶!ûm–ûøö;ˆýê (ö«ãûm–q|ûÄ~ÛñÌçû9,?'Éè8ö†?áÏû6üm[©ÎkYMÉRæ¿mf{Õ"×ü·íKå^k ùo›g~›…ü·YTò•™;þqˆðo·|û¼ÿ¶1µV–åöçÕ–¥Sà ÿêpúçñŠþ¶MTñÕWFô§…±áϱŸÆìW{üùPÌ~5¤ßþžŸªÙo£‚¯µë~|;:¢_£ÐO÷Ìß(‚ö!ý÷n‚œ<sOñ«c 8ŒÎS0:ßè^âÆ@×ø0*Zß8K$*OèX]# u§œÀFÀ9>GtÔµÐqíFÀ%7.Õ,2:>Þ¸”´f\®J \òsyOt„¼БãFÀu›È€3/t”ºp=VùÈ€Žm7ºá†ÐÄÉ€Û,dÀmßdÀÝ2?ÏÁ ¸p›™ ¸!ÖÌbÀÊn2`Í ¬sV®€pC ¬«% Ü,ÄÀ×Âa`]Qaàn:>ÍC t}c Ë­·ÄÀ¥Ö>ÆÀm 1p·,ƒ,ÄÀmb`·”ÔǼ„C ÜÆ 7¥§òH tš)p©.±)°.(°OXB¸[–#¬} ëh‚Û¾‚Û‚à6O‚à¶o‚à¶ A°.–@°,Á(Ñö ‚õÈ}AÅuÀâÀmâûü¸³Äu‡Š—š6škGÄÀmGÄÀíx‰Ûb`ÖÕÖc& ¬ë ¬SÖÃ* ¬ûF¸í‰¸Yˆõ2Ö‹UXPXPX¿”0°ŽXÛë%% Œ ·Ä,b`%K ëE& ¬} ë¥) ¬snû"î–¥×ú³cà6/156‹ëðDþškZQ ¿›¦À:Q`] Q`]bQ`]RQද¤ÀÊVÞ›(Ð9X¦À:qQàk‰‘kO¢@éM[Ž)p•à×ú缤@Õ5- ÜÆý3ëb9áÏ—ø/þNj˜JøóÓ \ªbo¬™[žRþj„RþJETÊßeTSÊßù‹”?Í£”¿Òò”òWi„@§’UÊŸ/©SþJRCÊŸÅ(§ü•Ħ”¿«üøiýI\%çýyÊ_Í£”?-5 Ûñ)ëOºµ!pÛWBà*ɸíIY%Ì‘½¨5ÖY‰×O" LMµ/Qಪ* ôý¶§ý}ˆ€uµ„Ê/­¬¿š„8—E‰uAÅ˪ª8pC4Kë§Úf·y ‚JÏ5Ö5:× ¸J9$Îé:®¢Ö¢XðGœG \E–*jºÝVEcþaµûZˆª÷lÙª–Ѷ²e«€v£dwÍÔÁïy²ς¿·9žƒéyuƲlóжÍdË¿½ŠÚ%–îÏ2jZãìl3zþyµwÀû^î{­ Qíç{ ­6·k„+òy?ÅQÛ‘½€æŠjªÛDùç>‹þÿQµ[Mãö¹~>÷)hù˜¥Fi¢}”æÚ Šq®½ ˜æªQšë£8™žh½ølsɲϵâ\û¨ß¾/ÚÈ&¹Qv,š ¾ ”÷}›Õ¹>kwý—Áÿý©~Ø/'¹®ŸÆ=¿ÜÙOÅÃ~qOý¢(Øo¼¡þøé]ó«÷Ñ¿¾c¿½£~}Çþ<×ß/ ¿èûQù?¦(Øþª(ØÿÃÝ»íüŽck_·R‡Ý«ÈÆIl!Ná ¤¾¬þŸ÷/òŒgcgÎêêªÖHœt×ë™8ù'ŽíßxÆæ¿þ«IÁÞa½ÿ»m™ Ÿ0Úí̉\ØÇu:¬|ךqïü[aãfh–B.gCÁ¾ÍµwÏÑÑœëöͲ8FOÈx]©mömÊÞð~lŒ2¼\بmöuqÍšÆ|ÒØ¢pß—Š.ÕªÜÐ)”m›‚}»ËÎ6”|V¢0fÚm(²¬:;¾öÃ(CðáÍ–®ê·BÏÒW’­#¿a9Q‘wŒ$±åÑs*ô¼!%¬kA¨A2ÅОº½úKñƒ~ö.Ód«“S f±wÛeúyÔéÕœ9„f”¶ÓîSuÔÉ]¸9\˜¶í4û`“ï^;k ãíÉ–Q´9ngx[XÇàq±vlþf¿ÇÎ2ÃÑ‚ï¼Åꨟq©…©—w¹rµãdõ8O´£1ó2^ßÀq1:Œ–êøRæeÛ¯ÛqßÌ |ÈÞÞ±Êj—·Îé•?»ZýÈ£³*ž©®Tûš*ôÊTWíܘyù}XÄ¥ööYIu»k*¼-•A›Ö®–£R/#ñ?¿Ÿvž,g|Þii•zùhZÑRIÔ»ýª‹_øóQñvÞ•Aýp½Ÿv>•xÉ÷‡y*…úYF›jèL(º©Ç*\p¾ûv]¢•Áç½;'K{[:•º¸xkeðy'¬SxÓÚQéÓ‘x_㽕Éç<Á‰]-¸.B©x³­ >'î@o¤]•s»éMçÜ•>½¡X«*å2æu¦lí©ìéïç-ÂÖz¥\n§KÛ¶V%œÞ–]SÜÛR9—‘UŸ4Ý®­Ò§·Û`Ò®²øœ­à²åØð·âÞ?+å2’êë\geOGï v•¹ç¼ð€ÜRÙÓ¯Ã9ŒÚU枆>Z0ÚuWöô/H]ºÌ=u-ŸõTúôksí³wãñð—Xjר×;Ê4 î ‰bwU„{ÿ¬íÓudj½÷JŸ~5QŸHmº`jë:ë¬ êÈ´OSÎÛR FŸëλ;®êx"ôÂo¬òs^—Kж»Ü¿-Ão p"Ë¿Þ ýà4Wîj¬ôó^;sJý` ¸¹ [c­Ÿw¬9 ±ØÏ{Ì.sOCµó®$z1,÷s"A¿¦JÔûÁôÜÓOü©~t-”üÁoò~Pôç=BUž[åÕÀ͸È^cÕŸ·¥ù§R¨ÃÈǷĪ?ï–áÊezeP¿‘ eë9Q*@¯Iqÿ0>ð$þ9Q@ S%Aäv™¶ÚÆâ?ïµ»×!Tÿ9ñj˜7£±üωקi‘õÞçrȚќÇ4ÛïKÕÏ>t7O%P¿R|¦±Pµ4µ(û0 Lóa±Ð{?§ê.´¡|Ä}iyø\?¾c‚âŸeêy_Òía4J}/Ôei¬ôvâ…6jÏôþ„ ÖªKë‹¥Šž°óê²"ÐÛr¦Ÿ’EOÔÄÐw9J=a«Ö aY ó†QטRuïbU ÷ƒ:l#ØJ­Ÿ™–ÁÙÆé€®*p‚kŸü³ì<'>r>q¡ò‰yŠOübI Õ7¸ º¶’Eë}µÜ¸•U^U²‹Ä©/÷bI ÷qÞÚ^[É¢5r‘¸Xè½ÝK;œ‹%Þ+u-ä×^²(~€ò‹%Þùèâ²wí¥ŠÖë?tH©¢'¦Qâk/UôÄ„x«ãvóÙ þY¢è;o½¶‹ê[ç÷ÚK}_ÿОçÚ•Só§Î*Qô}‘§>÷‹%Þ³\ õÚK}¯åÉübI R…žßQ¢hE·Ü‹EjæãJwUQ et‹Ý©–w©(Š™h@¿flî›ZjM}\¢êm)QôDÍ–KWbQ Ìï›ú)Q´f’¦³XˆkW5”&ÊyŽKe”üQË‹põ…i«(Tîí®³4Ñ÷œS*Á¥ª@8k×Y¥‰r¨…UŒn]©4Ñ÷öòòT¯j¸¥ÖÔç}\›®^›ã7®Îº@Pôp^ }ÏÙ½ñMbs½«•(Z³—P[2ÀX·ƒþPZ°}"º }Â5C_³«Š ÏEWè;Õ‰¡ïrš·@ße/C_K"=C_‚Š})CèkÙÒúˆækÎxæÃò¡nŠù.¿á0ßå"¾a¾$ ó%=W˜ïš\(æs2#ßs»’†‘+yÿ _ÕWzíª‚ìüÌf¾ª2,ö:êïÇ^1_UÀÕ9d¾J¤®%xÙ} û©÷ûuzÿ`\Št)©ý»_±¯o·4öõ*øÃjŒGöÍE}ØDðúàP¤í8¡¯b|6c`âöõ&I}K §¨¯ÆjCAê+øýP³«²á¾.’*FA5 áeߣ¹…¥ë¶n¥É{ìÎb'è;àwÔWè;°CÐO ôUi=s°t¶F:¦ ï€ß‘†,¡ïÀǧ¡¯¤2™ @}UÊNb_Ig‚]r_•˜ó1Å}oË.AVàw ç! ûÁƒÈ,EøÛ0› õU¶K,EøÛZ>Á_U½ÈþP0LÛׂ?l n]‰ð‡_›ð‡JOFHÂ$._éVÁËûqÑß6œÁô‡Z9î‡ôŸ"½Ñ_ù åH;¨‡ „¿Ov¿Áaþ›wA¢6ÒßÞ\EÈô·O»„èo*íeøƒ.&0üí¨¤ú¿°¶«¥ªwKÀ?I~ø:Í‚$?¸éÁùácìþ»V)|V"t¡ß`ù ß‘ŠaF?¸Ýn)ôƒéÛgý`—¸?èw€sÔBô;«uD¿ã ¢ ýŽËÙÕ~Ø"¸_¢ß1Z€‘è‡ïSÃ\è÷>=?¡·'Õ@ò;Q^Ó-2°ÃæËù½OÐó„Èï½gá"¿÷$›œ„~°®èõ ýÎúdªèwb`Òc—Ëé_Í~ÐK„ä‚?x;}á6= ÁZÆþÎǬ ðµ’å¡àÖãáó”~‚àЇ¦>Áß ÷]‰ð‡kkLþp%¸àóæ£~˜sôËïnÀæ Á,#"=²ܼdU(ö+“¿þ&üaß&ú"ûµÍ’®Ùï„v¬“È~ï²îÕFìÉN,öÃ1_ö;‡+nšýð ´û#ïWì¯3÷\ì7¡Bì‡í©‹ì‡’”íÃ~˜ç…Nb?Ô›Ô^Zø×6—3þÁóëÔ1Ä¿¦šÆ¡¿–½#é¯í6i™þj\º¥è¯!Ô@ÝŠþn¯H¦?¼)ݞ试7Ñß'üÁê%üµËõÕM­Û“'ô7ñEô×P]˜úk™&þÙ•Áøwa T¿Ä¿ë<}{®¨d×ÓÜï¾ô×PìÝ-µ¦¶ ¤Ðßicµé¯.®Ñò¹ÜjÁ£AÕséŽ~—ˆŒôw^[LpÈ;Eˆ¤?¬]·Žý%ñqèïpò#Ó¯ëK)Ìjü»Þ‡¬7.ü»0ÞÕü»`æ:ÿ®w°P1þÁaнÿ`q3’ÿ`|tñï‚û‰Îþaá¶ÿ.x¯|ðïJ‰šà_\å(*º©e”åsËýÿlu3þ]Ièoü»†BqþLްI€7þJ€3£€ 0…&‚€3½ð8IcÄFî‹€Î:Fø&KàÓ~$ÀÇ^h!@XÒ…j"@¬c:F8Z¤7" Êujï¹¹¶Kvr…€ŠÐÙïùU &„÷ÝWõ{÷€ãÕo˜PL€ÃŒ€ïä­}…°« FÀîzµQý¶MKU¿÷޵TRõÛz;©~»'¸¨~{v½Výö@¬…¿Ý‰ÜM€ˆ‘Üx¨ hð}ÎÚ°˜ß{°¢(<³œß•Ü*Y!à9‘J xn“øÈ€ïŒ~ˆØú ¿Òê:æbüFöE‚À*HdMðaüÆ·Càeü0/}!ðܬ4‡…k¤À‚gÂýøüH€ïºí* DôYÿH€(·ü|0¶-MvÂÀm¢­0V3}šÂ@T•6Ðá„îb ¶Fòî!ˆ¼¦øÈè=ÄÀ»²kÅÀÕ´ËS§‰ÖYû?én*ò’L›v«S.ÙTäõäÄk ŽÄîS"ÆVE^@õ¨umº{ÃÙHT@¢G•ü…)õ‚¨Á}èö†ª™;¤È ¸õ‰}AlQ Á-¥Y ‚|c7nçTøÈUå\Ý’+ÂT´Fܶp*9ðÀv^Ï“XãÏ7ÃÐÈñØÑMXSdtÁ‡öëf´&¨o™¡‘°Œ[ÒíŒf³“8°ìë]‚C#ÇéJ›âÀ¡måÀÚˆÈRA”ü‡€t9t–ü·;þyÍtô"4±Ö!qØÿ§nÅ~w7ñ˜ýbû=“!Å~ÏcJ£ß"“ú/à տþÄ«²Ô?Äå|<>±®kÏdõï}ªò1ûm“ëÄ~[6ªf¿­ùöˆ~èÆ·'öKq°©þ=~6Qÿbw6û½oðZå¿wÍÙ¾ú]ÅRb¿ÓŽ a?,$ò¼ûaû¬cœê7»m³ŒE:Æ©~#§™ýRÊHì‡ðe¿;6fÃßm÷‡ÐƹðJô×ÖSMÁÇ$bú›°á˜!†òÆ”þ·ÅGÖúßþƒÓg…éM§ÏZ.ŸÕë³Ùa±OyfŒ¯VÿûçDýÆ«…ðWs…0Éð—)ø«ýšT:Åú—E-‡J ñ¿T´ï þ ÊjT7Çú:ìÊðWÏJÇÜ ÞÜò8JrÿŸ;ùñuüÄS äòôŽr‰•"¿w¿l"ùaï­1Rä7ŽlE~h1±‘üÆ1‰’ä7àZ»jÕ¯üÉD~8KpHðÃ{ú8~Öº§¹Qà7š+Ïšüà¯ícH~£~4ø¶JõîÏÕë³0æK}ØG^öñd=Á3v(R_]×b`cAÁéHê«_t¯^Ÿ5ÎÆ”þÞ#ÎH…}õèL“ òÅ:¡ϸƒûÞß`ÙDØWw¬³Œ}g\/E}§=æB}­ýH}â‘ ŸwáB¾{› D¾Ôò¡¼  PÈwÝ_áïm±s®‰ïÊ«7ñ]q¿0ñÝG<"_mÉYD>­!òš'ªÄH‘¹Sćú*û•§Â¶Ê~õ›ôáˆøFh&âÃÎÁ²d_=Þm%¾2ؘ%• §w?­¡L8cÊqŽðµkøØÉiº;=«ur(Îp¢[ñ^µì+ï­Óúptïöuù¬žÍ–Žî šeÂÁJ®ž• ž «ìW¥6åLÞÛöpšxoÛâwéd8#~–N†ãÙ6¼_çð*Å«gñÞ5ɼ·]Å{[TòÞöƒ×g1Ä‘æ½ø †÷nyMÞ»}%óÞážá½x܈÷*8]N佚GD›ä=+WÞCÏü³Ýúb;f婂 ’c&,Èð˜ gØ*Ø«û+ìÕ4.\±£úöG÷LoQm“õÙ1nßn—í¨˜N'ìÕ„¦‡IØ«ùË‚óàÔ‚!lãÎ6)»’ öšÖk~;Þµ8Žšß~äÑHóÛoö¬ù!T|_YïD.%¿z¬‚+H~únö¥Í9T’ß«ßGò;Þ…Y4-ÉïØ¶ø‰RòÛ‹ºþ>I™yôžDzù‘*ÒÛ¯T’Þœ2éíïl.ÿØ"½ý²™Ò¤‡^ôôDzøÙòÄéíòIÿ3™ÁVè;Ûúl”˜Ðw:ù¡ïýŒ·Uð»¼õ™ÐwåCŸŒÊa>èÕ§8¿;1ç#Åe$3óÝñ= ôµ¡¯oñßôu_+Ð×§£(¿n¨õõx›ú:¶hÅ‹ž}•iM¨Hè«„Ûna˜¶Ùºa…ùí õaN:Õ·ñÞ# ‘új9Z|>ñIÛíòTéé„@Zñ«çZ „¾±çéú |#ýƪöÛ6AÅùÝ‘ç§!ß¹½Ë· h9§`á 1Îï=U»ÉÄùõâüöÓ Žóô>>~ûûß«ÜwbÙ9 x ô;"G:Я£H|d¸ߘ.µŠó;·È8?L‹ö?Uœ2ˆæçwlíÇ8¿+,©8¿ ×V ãü°V‰?çW+¥<çw%"3q~ݯ¡ýdL£\‘~˜hE- õ;ºÓ09ÔïØ¯à&cý*K‡Ž¡ËçÞÇWñ;q²(ï—@…ûÎÈbϣٻǟ;\À„^gçÜ«á)ÏY€VÁ¯<5…YòøDü×½ ~g»2ðåñ‰ßooSz|ž‹HÏs ±òø„¡×^–ôøDp¥ö‡rùÏç¶à¶É"¹y@Èåþˆzvù¼ãuk—Ïwhw+µïFm¥¢ýŒ”ú`.ÕK’Ö‡÷Ð&ôÈæ0>j}ð{ÔÙþžwfi}‚dÖ׿ä#­™Ëì?IÏ6W;|Þ-z>á3æp@:|¶xÐÄá³;ß'>ñÁ<+ø7”zA>[–X{|Âýëì‡Ê~£tølÅvÕ O¤B"ÉßóLpªü=±KÛÜÒ»r¯R߉q ™¦ü=¯¹€ÉßÙØ>îž ¶‚O¬fG ÊÝsÄåÂîžG¦F)}ˆþÒ•(ô]GÜœííÙîDÅQè;§gŽ„>|–ñÊÝS8,•Åá:{Πnú†äCJ•ïÝ£M×΃1fÝÎÑvöD”޹õúó²¯ç™]O|=·Ù2-›tùzÞCavõ¼±›•/%]=áÝÖWæ;¯>éÍa~ʳOÏæO4žž·ævô„~÷ñôDš= Råéy¿Ïüþxz"ÀpøÊQZtG?Ï{·sm¢üfp–ý̆@¹yÂwáƒ|WB·å7ärg仯OË ò»/?,{y¾ƒéøzy&®(^ž§¿7#ÞÝùàe,Êó‹.Eæ«ð<· F7b>¬7_æÃbhý±¼<Ï'¡Œd¾ TX vòÜ÷>ÙŠʳ&ƒÁ;Ÿ"¹b«´H•¦ò$Üò÷´›·tÿûïœ7ò1ëy" ØOWHË©éño?]â¿,-›ŒÁÈêsU–ö¥+·,]©ié*-³«Ê|<>¿Û-³+7Í®fËÒUëµ{XºrËÒ•š–®Ò2»úOJ*X~ÝU–Ê™: ;ÉÆÄN•?(¹ÁøŸ•ûÜ“ê§Öcáz|?ë±ÿ°_æj3çØÏf¢s©ûiôb\ÞÛµå®v¬Nýž]¹aíjä®Ö£Ò\‡Þ™rv¥†OW9(]-G¥«û©œ‰³+5|ºÊAéj9*]Ê0;{âߟŽ|Hú™ÇüÑ‘Sw_*ãÓŽµßK;Ö~'íØOãà¤;ïúûí´c¿=¬~#íØ˜kêùyüÛïÌbëQ¿5jîëwÞöàë— ééÆš/YÙ¿`ÉþË/Å¿Ïý—ÿþ}Nj۵4Þ}·á÷»«üË—¶ù¯ÿ‘ý¹›½-ÿþ6",ãQ&¸ý—Ãý½k[äÞ0Œpwÿã_aŒøFß{9–k]5(,ì©OZ®œn¯ ƒ'—Þ€ã}b)Ò䀌&ï'Š`&àz*/5ýôºh¹r‘y=WÙ¤ÝÊ]J þF^™G@Y¬D.ï­$èdïW‰´'^ úþS¯HFžt–ý´ä¾88Zâ;JÞW¥Î‚;˜æ ã{'ïãÙ(„*‹P%ð]ßO9Ø#úAó†'à]-4ñÞ½´ŠËrÔÝTKŒ¡/YeÞ×k|×Ó|örJª€ þ‚š1ßcoˆ¯ÓÏû!öëñƒÀ,ð~¢ÑÃÂ÷û~¢p+»øYàÃ{¿Q˜ÆvÎfõYjᨠ#8ÄnÝï ÷̾ð‘|¿P¸âëG!3ðùð:£¶0•þž¿ ƒå}H•š÷‚¡Ñïjá…õöÊIÏsŽòò„µsV‡ß±W¿zzU éù^Ù¯¥3«(ÄrÎU ¸ÿw6ws—>L{z»™†cn϶2!Œ}3^ù—_JìçkA’Ë÷34ׯâÀ¿¿S_@yÙ]¿@3ÓºŠÐ‰÷Þ 265Ô2 7®“kY¹üRB>-å‰u×!UƒI ÉòÃG6÷…²†/|zQ‘&øB¿h98ñ€§–Ðr:â7<Þ7þ~Ÿä¹R †Ðûf*«>ß3²{¼ßçxŸpõR%„ÞÎ@ÿ.Kjù|Õ—V„ÞÏsT¶‡á™Äµ ½ß'záX®B8¶#^ˆY88íj)û½Š¦üc»kæª~v›Î|qlO-‚¥ûÃsz- xü¨mÔ G¥]÷2j…Ç9GX•z¿Ïú#[˜lTìQý¦JõñÞì£Zj Elų󬳖ÐQ®¢<IçÎ:k°áª%¯¯oj©%¤Vöº*ôÞððFçxg|Ÿ8bÜ<¼Þýí¦€‘*4pÈÐÂPŃÞï ªîŃÞïs‡Ë~Ùƒ¡ûfë\•zê%?9Ž£ÖÐð¢³ÎZD÷„™G«E´Îºx­V›Æ}Ûeâ?:æï`áXƒžõ~3uõ‹W¿k!ÝËòÌcž‡pȵ¾êõâv)&¨„Ïôm9}Ö¨•ôm‘—öqbÙB7Ò«€Ð}餻Zà)„C4}Uý  Ï¢ñϳÒ:ñÃ3Z-¤{•oà1ÌN³#Nâàu®ZHwxp !«DǽœtQ<Gïø&t»HËcšTêãd]…·EŽžU>è>ëöhÍ<sìÛ­Š U>èj¼Ãòã®òAcðÑpèÀVßð$Å*Tý TjÚCù ¼û:„øô@4 B…½ÌËÏþ9é©™¨^ÝÉû{j9­K5öÓk9­caìR]«|Ú«€ÐxøË9/ÃÖä@†±»ã/ùê¡€P}®%–àï³Óå=\5w²—2ŒW¡¢)xæ@~½OôRªë* Tƒ@É.i{Á£¸…VU?èâýrâŠ9êP—?œªm!½ÖD=‚Ò$=óVH/è'ÔÃxcKPo/NÖÓ6¬÷x;ÖCÂcÖCôà‡õÀŒ\ÎÍz»sÌzhàÎÒ¬!÷Ëz+Íz(ž°}Xo¦6¡Þ>RHLß¡‰t’Þ&è1éÁï–½šô6?N£ÞîgeÔ;¼Ä„õ€¯íÃzGªüõŽÃ[y³ÞáF½‰³f= eÞžY€Ë»1ë\ÂCzIûaÐC̾ÐO¤w8šAïHnvqÞÛ ¶çŽì0æaQÔ­óôã„xÍxpr²2Þ¹yëgÈ;' ò€Õš'äaU’ç•(jÏe‡ü¢<cø½3iýÄyhøe¡<¸yÊ/8.1dKÉļÓ¦¼¥wZ:ãùbÌxÐld<]²CÖÇyæk0åáøXDy… ÜËòÐ"ˇ(ª€¸(Ç(0‘;BÐy8G¢¯ì|–¢¼rmà…Dy0%p+*È«‚ý— yU1@½òª>@_ ȳéR^ <åÁú°•òªE HÊ«>_Q^e}ÜÕRëÒSÁz+æ•+$¿ha^#H"æ¡>iaÎF óªZïG˜ßG÷LÌC‹¸D˜Wn—|½Â¼Ê0Iç¡¥qÝV¦˜nèÁ©Ò´X ÷èÞyeRáT!È«?š y0©h"åÁ½S³Ÿ07Ôu1ïI&Q^us¬”÷$ç–(¯b˜¤<ÄBIyø¡ZDyh![ òz'èäá}¶=˜tøQŠó•8̃HoV˜‡˜D·æ¡MùÂ<)jÊçá$BÎ{Ê¿få<¼)3I-¢s¡ìM·á¯Ö<.jžë!´Ñ`JÖƒ Š[S±^¥Ÿá®]´‡nÌS¤½²[‘h,‘ö¦Ý„iÇîŠöÊ´Å#{¸§zÁ~·ˆF°·BÚ{ºÍƽºw”Â=ŒbAŽpïq}`ÓŒhõn {0³}XþPäL¡Þ3ÄÖ&=DU6IùRoõBÒƒáía/$=tËaÒC‹!­P9Võ„z8D Ez8‚Ï@ ‡†rs0çÁ¾ÇÏÞœW9ŽÈãâ<´ð36çá,îÌy‚R1ÎÐHãUùhõJÆ«ü0º2¯ÎR ¶F²# ¯Ü\+áa^áGmÂC¿"mZ8e›ðÞï×4¢Dxˆ+¥ÝE„‡t;œPLx½¼Ey!Ù ØBÈ+O8ÞŸ vÏ[ 4–bÿùa¼¾ûÓ7ãáâ4t™ñ0}’c…x0–ê-ñpˆ¬/B¼2± Ööi.Õ1D<¤"ÒâU2*B 'ÉL"Ä+÷õ.è+ƒi¥R䕈x½vÏ<‰ˆW?Sýñpǯù–¶ð°Fø~ xø•º’·wí+àU7| ¼î»ù®2ñE‰ð˜äŠÝðÊÍ^¥z"ñ‘7S|ÇdPj ¹ô8’Ewu#ÛêcS®’ÛŸÍÄfÀƒ7é>VÂÃÎ÷üˆy¨=B#áÍ+½ ¯Ĭ„ynžLxçãm¥ ï\ô=®OØb×¶Ø€kÆø&DÝon”Mxçmõć}ñøîØ<Çõ ÙBN1 ¯ã«„x—\úLxpé—&(»cÄâá—´âÁyZpIÄ«‘¼Ž¯ÛA΄÷„1Lx‰ñ7áeGcÀ{²×7áUò™þ»ÔDxó ðžî¢X"<ø—)¥žïˆîWˆ7Sê ñ‰C'‰ñúÜ$ã=ÙòF6S‚Ìy#Qkâ<uûRó² G̓³)NrÞ¶[ˆ1èÍ_`ÒŽÍ5é0‘I5UÕBÒÑDzyR½îˆ's^áÆœ‡µ8ûfë{ZF¤EÉy眄ÑÄd9ÚË¥.OÓZ`9ï´€9ïpõ*«y»iÀb^2ZËÛ3ÉXÌÛ\‹ObÞæ•ÀZÞö#âÇgˆò*¥Ñ‡òzÜ,åµÍ µ<äH÷IÌkΊm-¯Ù¦"ÈC/zÞ‚¼>*QÄ]Ù Dy•A²­Z¶_--"8R–Ü/åaû'ä$äAÒ–±@”‡$'bqb†¼°_˜WÊ81‘ãƒyÌéÇ^ˆy¸íKú^-£ý™ýó:‚t88…yå€)˜×/ÝŠòå¯}(\Š»(^¨"ÌÃÛ‘jFÊC²MmqDy—¸BÞ²…äaNÔœ‡}1ADW?I`X×”"€#äAWæ®Ä×cb¼þãA¯Ö¶]Œ‡£} -Æ1R^ŸÒ 0ù»ØŠœ×§¸)ÐÈ%\ó0^Ûªçu;Ê›ò›FðHÈCƒå;êyÙ[ÎÛg+ÆCl½Þ‡Õ<•úš·å±˜ò°fÞÊë‘Eyxt¼}CÞ³ z·w½ë  ôðS%Ý ôZDUƒÞ¹ ybÜV›ò…û£ã!T}³jW+h=—g¥<ý¼.!™tYAR~’Èx•= }oøñúïâñ¼{¼»•i8t‡Ñ&$Ý!;Öõ¡»ëøî°kádºƒ6÷¬t7.oiLw˜c„¢»_4Ó"†E±¤»rAØVºÃ¤q‚p‡Ç¤f¸Ã¶Fjàn„X wNÙ¸{¶°œè÷Û‡î ÈÁaºƒ¹•r§éîò¶2tË.¹Lt‡Úìf¹Z>+yÛµÒ–æ>árè¡‹ï*uÌ\·Õç3“øn,¬IÂ{¼Þ‡ð†ÿ,ÇZ¨®üüW¨CäêªÎÚªÛ½XkO¨ÎY uá¡@SJ‡é¯¦aºÃû¯@],Ù:{—„éŽð¤™îôÞ/LçÚ²AºÓ»ˆ m2Aº3»A#:&Œ‰éfƒn^ˆDwžIZŽU´«S>¢Ý¼ÿ8hfëÍ3RŸ˜5 EpdºwŠt‘¹TâJHwyé Ò]‡Ý<…tq€4Òáí=÷ÌËÑB&º+´n¤»î‘® ’‰tÓ4o¤»ÛôÆ,¤«€v‡¸¹{æý“twgðÆ?³™ìŸÙýš u˜?¾þ™#tÿÌ }4“5Ý.šgÂaã¡9îv÷¤V®¤»XâÃs7dÿèàIç,ºøy†è¶°‘®O‰MH×Ïô+ñ‹fU‘þB]o?A÷hº~ÿuHz"OO©w=Õ¤Þè©Vï@cí£ÞÙ>™î0N¦“N¦;×l¤s¨¾‰nÜþAB:XDpb:´pÒ1Óá»™nØLí¦mùuŠé6‹üF:€ìø ¾æþñÐÄ6ëY¥;´¨c#Ýf?q#’$ž‚<2Ýf㇙î=‡3H¿ 3Ýc.PçÌ,òÏÄò=Vénš¿ãŸ ×.!œ ù2~‚º ùOÙ"¨Û%ƒ›éªêíêŸY ÀW`¨Û½žêöH†ºÝCÈL‡„|RfºÝ>¼aº[÷b¢»d>1ÑÁš{}ˆn·º. ÛÇî™e«§iO@_" ƒ›«îˆ!ÌDs¹.-¢Ã§q~ˆn6#™è¶Û›‘ÕÇ®Òm×Nšx5\ ‚tHܰºi–IšÚÞ$:z¯™èâË¢Ûz7†Éµ:iâS‹l‡ñòX¤#Ñí›/, ƒ€òQí0<´×4ÑÁ¬±I¤#Ñ¡ÂÇI³l!r¥Ñm=ž“": EyWŠèMt­ÒúùQºk"ÝE'°v÷dÓíîN?ÒîrËÑîìÜñÎ+´Á®f¢±ºi–d¶}廼îÈwñ5Ømam‘~ƒÐ:ž]ÌMv•øµIÔ+²CK?W²K݃]ÍÓòíÜa®á•wžÏ^wS¶´‚·Ï%;BA¼Ý)SÁ›Ò¼ÍN"¡;â?*xòÀáAäûêw—Y:^¤8ëw%>Þ&çÁˆw°šê]÷°2ßMa(êÝn ³x·û=Z¼;b“ÞÕ·Q($íÊÃóÑî°!Ï$µ»JéøÁ»crä`‡M0Gº»”?t‡šÍ4ˆî°k"´„î,zî#É„»áÑk¸Cn/9H’îjJ»;32­Ý=Jµh¸ƒ#LïGY¼»äí®öN+ÛÝ·{ÚÝçôÌü£IÕâœYÉ[VÊÛ"…™ò4y¶ùÆ73ûfFÒŠo¦ÅïPK7šðPëA&<Ä ßƒ·ç2ŽÁKDX‚ðbµáiKÞ”×ÌxñC2㵩¯™ñâãÈËÏ^(¯ ûHy®ÉÈ»â%*Èk­xf:»Î„§G³ái‡“ ¼8Æ3Ó:ütÍLhV\3ÃDqÍvÄTÞñƒn÷dÿbȃùäúèvøVtŒƒð²ï7å]»wÅ¢¼)äšòÚDCRÞéòY†¼ÊÿÑíÎ#'ÊkqWŠƒæžð8;hvo°LyØN¯%Í{B]¤»nð{¸‡Ü¼ ç¹l9/>Cá¼+²·AïΖˤ‡,6Î9JÒ{¯øC(Ò%è’ Å… â¦éºnz-‘šñÒ¼h½éL)Î;m"çÕ3ù‘óŽÇ²v÷85‹1ÏîIÁ¼'ÛvsÞí*Ƽ÷Q‰ŒyW‚èì¤ùŽõ.ð“—f7TÄKóΛŠDœ4½ç1è5gj1çaosÞÛ¹oNœ—ÙÀ˜÷8ú0”WÙ;sX°·sæãzÖöÍ|lV²k&ÌÉÞâ.{f6Ýz3÷œ#ÇLX.?€WµÊùóä˜Ù‚lÇLØÓÛªÚA€HJ¶ÃÑiRíN{ªÄ7z†"ÜxØi5oɳk&rrê$ùf¦²^\3c¸‰oæù£ofí¤VÕÏjÿ¨v5OU¶Ã®©ÖΙ…Q?rÎl§û±wfó*ï̶‡åÙ¶xHÒ;/çøÈvƒxgŽ3ÒžÝ3»Ý@åÙ3Û;óì鸌"Ží#Ûáaùfäœ9Žíœ‰‰K‚›¼3ñhg'ï̺©U·+ãã'-û¶ wåíO¤s¦?Ø@Þa9J—U?¾™Í!®ñÍ~·Ó7³E”ofüV㛉pW —ÑÌÎñÎlÍîšòÎÄ^¶­²]9LSƒ;b,5­‰ñPÑUž–b¼s$èïJ0»"Íx‰ÿ5ãÅ–kÆÃ>zÕîpw×¹jwµ•¥ (MF™‰îj~¯Ü•±’]öÍÌF×lwª´’Ñ®æ¥w&žÉ±ÐîŒ$e´Ã^ñü°ÝXÛá1i,¸Ã|¦Qg¸9¬pWë„äÙühíaKl7}¹ÅvU‹EÞd; ù‹íæ²l¸›¶uÓ]9Æ[ÐãzÙäc¼KiSã]ebÐÝð–OK€Wo' …9JÅwxÂT­ÄwX™¿òÝÓ~ä;|Kâ®â;Ü®4Zñ|·¬Ößa‡ªOK|‡åýËwØØÅ“€—u×€Wûeþj^Û=ŒxøöET¼ŠÂX]3+4¨­±wsF1Þ·è»Ú¡¼d¤»TÑ ÝůÐt‡yôè‹t‡ ‹¥Eâ]QD_ð 8ÝéyN}]Kµwþ}S÷TRÏk_’¹eM„öÏ›Gù˜-ÚÏWHËÌ/öã%þËÒ2ó‹Ø'=Ÿ®Ü²t¥¦¥«´Ì®*=ôõùÝn™]¹iv5[–®îŠ[»rËÒ•š–®ÒòŸ@íÜáusýk ÔÚo%PÛ¯þóÇjoëõŽe* #©€~k@ XåýÉkõãðÅÀĶÿs»š¹ÑÜÕšÍ]Í£ÔÕzPºJn´tµäFKW9Ê]-¥«äFKWKn´t•£ÜÕrPºrv´ô4³£¥#ã~þ|5dBÞÞ5ôÿ ÔþÈœø[SÏÏ3àß~g[ú­Aûs_Î5šòž=ÿ4ïYÏ¿•>í7ò°]ý7:z¿ Ôþµ|eØ¡,Õÿ‹ùÊÞÉg=ó¿Îfä+ûõe”þ>£4ΤeÇ?OZö¾{$ÅuÎ2~”ÊPV{ó@îÎã®Ü 3GY%¸?qÞy¹µ"Îo¶ R#ÎÕÍ(¹ê‰XÅ;·ƒ¡âìædÑšç +àûû*àC‘F¢÷GV _˜>ÉZoËC/lW.í27%¿z¿¶IcÁcn¹¶_¹:tiä¢ÕòâÈôÍdcõç£Ev«¿ú¶Øß*“¸Ü{¸o:Ïwg9è×BûÛÙP›–)Ó¶ª¢­ úiLañ¸ó{ßUan†cœí¬²êØmé´—>¶ßÊ‘-ñ9ˆ›•vÿâ®YϾÝ;·Ä§L¿oK¥ïG wÖLñMÄ % ~ŒýÕPhˆJ(X#.¼ ƒ±¿r y42Ê——Mý¹7Æý:,å¥q¿Ê¾ÎLâ÷bÖx—¨ª?^!±EH•yܵ÷&¹œ®“žê|¶&/ÈæéÞ *›œ©Î*y?àQ+sÄ çY(’c÷!ý.Wð;GŒFWð!0;áÿü”ƒçÐߣ’;mr-8ᢉÜN›ãÊÎÊ ßMë2UÕèýµ• ‹Wà*g^o% FÇNŸÌU?‡¦}”4‚c!B×½°”kÕÕâ܇ìQP#»Â}«¨ÑK p åX¨×˜ŒŸ/r1½«ŠM&QIçý4+‰Z ¹ªitý2*™Ž®¦ª2RZù}sš«‚Fýª qþl•‡^Ð䫤ÑsW5ÎoK-œ(ePZU4ºéK›nÛžZ7˘ªKõz¸TýÈ·¡ÖÍá"UШ=•3Oª !ïÚiõ¯ ðܵ0^úYùθü  Q9ƒ»|BU4zZuÃ)ª¡ì:/=Ôo«uÙÌê;i;’ôTŽ´G÷BòDqI¦ÞUnCv3þçäk¶tU-#$];ä§Y¥ŒÞoWèºóQ 'ê é.Ö¶«²—jÙkå¬Òey'©Z9Çe¥Š!ñÚ-i¨g-œ°/sÅ«ZF×YÒøRºDCë~•2z?Ía‡ÿ*eÔ‘n¬ËŠRFå ‡÷*fÔëN&oC­›S½NüWJ2§s«¥†lθUÊ_ç-£OAãã|§D®2UÉç°¤W•Œðyv9çW!#ä]‹©« õÊ6¦Bƒ(d„Pu0êîPɨ29Ñ¶Š–gg&'X÷/¶t|žcØë²ýf&§Š®ª–QKgešâïFYžJ¾©eU2+ï*:U•ŒŠž7Õ®JFy¯.rÖÒY9·8jP] ¯aQ­©•nÈLS¯}L¼Ö”Š­JÝ8æR²·¥3ñÚ¥24Uʨ¯Ý,ÉÑPf«CÓ„U%£ö(Å–Zæ];U.³*•>K©S«’Q?™’¬îæ:6¥]Ó:PµŒüò.¯Ú†";ŽäóÚÁ¼kðڨ׉Êø™Ø½ñ¤«ÑÊŸµñž¡²#UÈyתòoîÌ»ÖO–ʨJFçÍ{yø“F-£û^¶Þ†*Ö‚ç€d 7[Ó®¹@ð;Ô*Z^<¤ò£¥*n÷Y‹èÛ¢8­*eô~¨u%Î;(e4ê¹æV5£÷Ke?Õp×"ºCHáìsßÔ²We9¶T¡›·Õ¤Þ·_‹èŽ¢h/„¿úÖ¹Ç`ε®ÔG4là9@Ĭ'ƒ:•s­o¬^3=.äñGó“-P×úT§äBuÚ.‡êþ»Bv* Ô:ÆP÷H:šT§4¼ê¬@êölfŒuq· Öíò€ ÕÅ'T‡7^‹¿¡n· c¨Û¥O¦S(S˜n“I¨.yÅHvpÙánÔdw8»FÈ‹mÿÝ$P“²d ÒDv‡’1…ì,jìûÙìùÞ†ëŽl° v‡×´€]Õ¸ù€ÝÑûcbœÀîS‚w*áºc˜‹Èuɬ²;ê#dw:š)h7±Øhgm.dwª~mÀÙ»®ØŽ* ØNg°;í…²kÞíÚ–ûÚ5Gªíâ[´kªþc²k~“»6yŠ`×ì°k» Ø5:.ëð7?,cr¯X7Åjc|jÜ+Ñ®rzóÞHvÑB"ØUPŽ]eËâ›Ø¶ù{ÄuORËìJJ ì*'’]ùY©dW‘'üúÈvåª!<$ÜA†u=Ê%Ý=#'LwÉ`¸ƒËÏÜUîðc…»Êt@FÜ•Ÿß»àŽuNyán&7Üûõ… îpŒ&Á"FÜB¸æ+Ü!¤TC³]‰íàëË×h´Û¼IÚÍP³ÝL?d¸ëÎ)k¶ƒ»·¬b;d—åA;ÌâA²]E¤‹Åv»ãØÃvðÛºØRlƒWµ°ÝqNÚ+¸Û‡alW5öed;˜ D\Ü öýF»ÊX ²ZD b»~öœE¶ë.}f¶C·€b;4ÁÈvÝ®F;4h›-´ëµ"Dí0>Eb;$àN’hW:Äzµ|"œ›Ë„Ø âC¢Ƹ^Єð®ÇÚg¼Côüþá»ê¤­|W-|iâ;ô#zßá^Câ;Ô09‹ïàVÌÛßÁì Ûß!»;_¾ø®©„w°àÔ¼k¼Ã´fïðÕŠ¶‰wuöJº+g¬¾ÐÌc¢»þØ>lº‹Ÿ·é®»îœáF ² w=>¦;´p’5Ýõ®å†;$P¿„;˜HÄÁ‚;XZøîzrÒîzžŸ¬á®âÀk‰2ÜÁ²ÂO¶+ ¯$¶C ·‹b»Š‰ÞErµzâB\Ìvh‘MGlדhÏl‡~ô°Äv°vqí0Ûu'®3ÚÁª£¯Bl‡âóÑÓkW¿D;Í46…vð™ã–ÀhãÎÛ¡b½èh‡Ø|Ž"‘Log"; ¹È®'¥§Énì6¾ÙẜÊvUS]ì†sH›ëà\±®l€„$bÝH/c~±¢°®œù}Šëª²±Ư¦†Z=Ño)†:,Kš½u³×ÈÕÁʦá!ª•4™gÕá^dÖá^80IuxŒ…0Õ!D]³’¨®lj|‡¢: ·êÁâOä%3Ø¡b湂cÑÃu•_=LÝÇL׬ é°MáŽÅH—…!H×”˜$HWQ+„$!]³Q5H‡Òß»ŽH—L aº–Í‘™îr…@ÝåÂ:†:¤2Ø?JÝûçJupÌ´‰ê.çU"Õ]öi ÕÝ N ÔÝ2„énÒÝÎO¤»‹fºä4 ÔÑÁ|aºÛós nj[†º,dºÛ‹f îv²ë@ÝíX‚@–¿bºûð^ÚP7÷ñ¢ºÛ)OBuwö¯¦ºICu·ËêLÁÎ9¦`w™B#Ø"Ø]‘ùÄuù®×á˜ñá:ôÜ?\w;'E¸÷ÌÇe®»/“‘°îVÊncÝ-UÃTw_ðHu·ãŽCuw‹è'ª›2¥¹›C]X`w+xÀE»÷K…»Û¥VBv÷Tß„v÷m¥Ldw{%d—·´»à5Ñî6O™ìîHt";{O²»s%’Ý­ª»d< Ø%7qÀ.)v÷m5Q`w?‘ÛDv÷=9Žd7Éî¾#ä‰ìò v·+ìn»Èìnï vËÅv·j@ìnLJ얓ˆv·×*³]éØÏÊvåQ»êvåÙ+#Û!~@ÃApW-×în¹•šíêJê˜lW¿€Kl‡a°ø®ZĈä»ú <„|Wâ< Þ­ýï–A$¼›Çï0\µÖï2ÄMw3U¶è®Ê‘ñoÒ]¾sÃ]5<’鸎æË6ÝÕwr¯t‡ƒ%én~¶¦»ÊÒ½‰÷¸”â,ÝùnÎLæ»9‹ð¦åÄ€W=«v‡o›{)ñÝôÜàÍEÄ€7‹· ðªþ-×ÒûH'/àeU4ßáßµËßa±­ÝxWK ÷óÂ;.¥¤0âÝt¿6ÞÕ‚|I¬ÓRj ãÎ’€)¾«…_"ZÓZÙS€÷DÇ7á=ImfÄ›#^œTDxÏåTF¼:Bw3èùâSDxµ·!fíñ|ávW€W½r‹,Â[!àÍ 4¼ji«|›ÞøÈwUÉ?ZˆWgÍ„xËOâ•=±vß"<4è=‰ðj{ÆC„÷$÷”¯"ýøº…x©+(Â+£ä±^ý‚{Uïæ>Є‡cú‡ð* C—¾e#UÞÒðÈB^€WaKüx³X€¯ZxüåÞL dÀ«± —’qGˆ‡–SðEÄ«h—KZݦ°ª0×ÒdB+Ä«^ɬb<´ú¸”âñ(o½ !oéU”W‘xÔy8D_Ž ‡HnäUµòêR솔7ë3óª…÷'Ì[»!æÍzƼŠ~ÓY…ye3ßWÌ{RPœWÕ"¤æq)E´] Ê+6)u¤¼§j9Åuö2éþ“¼d¡º½Þß‚uS¡ ×9òd;Wç ÜÁï«lèΩ‘&ÝÅIk¡;mm‚wÁàÝt©4Þ9áùÄ»ó'¼k?â]mý?x×¼Éݵì˜Mw­åâ]*¢ïp’d<à] #ïšânƒw³Óxczð¬Þ˜B5;c:9öê©Ý|¼1ío1½1­dšïš“ÃNoÌ=2ž½1÷tloL)ÞÓs³^(º;­vÚÓ Bw‰.7Ý5ç4 Ý…õ wЮžÜዼ?’]JîZ÷Ó4ÜÁÅî+Ú]›Ý<Åvמ»Û]G¸MlwÙz¶»¦ö'¶»¢v›í²zîœwcÒÝþDwûTèDwÞ-Mº›Ž•¢;TKgŠî’¾#x—ŒäÁ»'£Èx·#¼{¢ïy{|”»§Erß= ßÁóîùðÝ}Õ€÷ôœEÀ{ÈÀë›%Aò]?~à»~|øÎ…P‚w=Vã3©ïzÁx7\z&x‡¤¢0á,Êí#Üa=;?Âݸ"î‰ïF †‰ïF\ãÍwÃEÞÂw#"³Ý27Û앹e¾•[æ¦\'Sºs’R{eV¡Iñ^­Iðà=?x7˜E»Û¾ÝxW9ƒÚW»;4gXºsа(w{LXQïì8Õ»#ß)ñjÔ»=£ÞêÝžo2ê]·5ÛêÝî¯Vïöìç£Þ9žÖêݱÅÉÒòœŽ£ÞÎîùî°&ò]ò~NùÎ9J¦|·E\´|'wÙ)ßEΰ~·g—jý.O"Þn×*ëwÇ—GéwI/ýN1,ßa'Í3¤ÞÊZnñ.5r£Þ¹œÅ»ä5xwNøÜa‡ÌgbºÃ¶ª¯â]¥Ä;ˆâzþ¦;|Ù¤)Á|á…S‚»|ü;„«cÁ]ïÑwÃ)¯w˜ žÜÃâœØnx‘1Ü¥fPàÎÉÍvCåhÂv#.©†»ÌC¡»á­¦ánd'oºV! w㶇§Ønä«1Ûõ'´'¶ëNù.{™ÈwÎìõî´ó¡Å»Ó…u#Þ5O¿V>â]›ZÅ»æ"^ïÚ>aâ]‹=Àâ];s–Ä»ÿN’„®¶’4o+uD;äÒ’Ú+´ƒæ-¤Ûõd0ÛÕô¿jwh°RG´Cª/ýJ¡]/zZÑÙ©5 „vHÊÌW)²ƒ\nB¤xw¹†ÉçèÝ^u†+˜ì*ÈJvx¯j ØUv豂]Ÿ†*]¿hÏd‡œ]ôHv•MN˜$;´Èþ"²Cü¿k‘A z;4ìý®d{~Ö»Îq=¹¹Ð5žÉuxܾ2¹®_Sn,®C'þI»îb²›v5“Ýé,tç~þDn²8fŽZÈWÒ‹RÒ‹—I/òå$=ûÔ‡ôNG)ôüÚÃy§3鮜§eÛœwöP9ÏÕ#VÎÓÖÜw: _8ï´å(œwNWÌâ¼S ƒy§³óNoMpçñ¦ ;o1sw† gÌÔÄPÞ™¶IyÚ–ó"póšvh¡<e&åyZ›1wrÃåUØÑ/ äqƒ2äQÀLy§ÍHóÒ/1/…ž‚yÉI×L_9ž™·äÎ8f>~Rq̼ƒ^v̼-TÅ3óÉ1vÍÌPˆkæqЮ™¹Ïž™ö<6ä.{lÈësç/ÈÃD(ÕA‡IÄ!Æë5Ÿ¢ òàûeˆ"åÕNPr\Q6prª$äÍZt†¼YÁ.w»¿µDÜ=!P1ž3zΈ;ï[ƒx3ˈ¯?Þp£©à í× xݹÅxÝrbøÎá(+ß­1w/Ìý² ÝÓŒjrÊtý˜é”iÇdúd:Ìôɦp§xªèvñ!°nwuG´I¶»T¨;ªÝå™Þ¢­§í®xY‹ê*ŠEÇëócª#z¦¨nGV>QÜ~ìBJ¬CÕ Ií¸;&X×¥ôÎx»[8kª“¦'¢›jˆîv†ÁÝÔÈŒt-ZF:˜ WÉ®"8å~)¢;²‘[ˆîl×S!Hç ‚Ý$NÝaôžD·ýè’‰Œ²Å®v ò„t[‹'$¡ÎººÍµ5¬Ø%ÿq$»±8an¬Mµ}4»>r€°›={`ráL>ú‰uæËP\[&ÔíñLu›ù˜ê’pjRÝúDu|uÝy¿u×@ÝsEu3ªMT÷<~¦º'€+¬{";ˆë*ìEN"×íæSµŒ„òpÌìÞ–çWyÝŽ sâ-’Ý@—¨»fSÔ]‹bH²WÌ"»qµ*ên·&.²+ç¼¶ªvð³“g·LO’‹_¦*í—é›Ù!cÚµŠvåê¦sDvê%n ì.—[ ؽ_«õ7‘]r¯hwÿ€vÙÝín3‚Ñî¸â*´CŽ,N f»ÃëPØn·~m´Û£íðô„B»ÝöİÝâUI¶Û\ +l—ºd»MëvÐŽ„æºÍN»æºÍÁLáº->Þìx®Ûœl,\·Ù­Ø9Ø ‚]^½»1dì†7_ì`2i«`WÙ–‰ÄŽ¶Û‘ÎþŒ¶C¶eÆ&Ü®ÓÙn:ëýùö_Ö1CKó»O?*Ïo¼ô®6²gq=|[ú½)Òúº X”Чë®nú ß›€ïºG‰³e‚ÃÊú>ºFC”³¬_r©,¶ª«ê1Z„á…¬vÝ)5„0ž_f͆ ïkç!ŧWåt›3WÅÓñô戌دͫ‚°¸m°eÔ÷y˯ {–3%Ðh_×Ô pòðAÑ_ãªDdÇb8» žßŒš!¸]¶wZõh^¿ e_ ['!]•ŒÎàüÎ BÌ…€ÒAo"Ž©2L-±$W…†ÒÅ\1›ŠàkD%åg¹*àQ ú£Ó h3^ˆÃ7z»ØÓÛE3)‹A\U •ehú ßh©plá_ÇÔ«D¢¤òRêí öƒÎªüF+)R§­•¿rÜmÄÎïp ËÆbç½¾èæ1>ë™h*öo—ã÷)ƒ¾-/|ó/¸«ðIÕ|Ú¢º°ñå—mÅ—Ž9ÆïÛ«éFNŸƒYÒò°½”ô{ƒ¡ìáSÙØ1$G£ð½=Ülऋ O|—´eæ»}„Íw›÷kæ;éïG„‡ïR&0€‡‚A_Â;œŒ(„w8¯lÏ>¡¼Ã%šBx‡%õ Þáo7ˆ‡,«ìFˆwÈÍ+„w¸ Sïtu ìºj!á¡òûù!<'à-¸$Â{×Á›ï´Óvï´'}q3Dn^ü x-ÀaÀâuþ²ð]SN ð]sÚñð]s´gø®yoÀkÚðR")€wé/.L›8¾tçy=t×Ò…é®ypïþ7ù.`6ùŽ••ïÌžæ;Å8N¼Ë'a¾KØDøîÞÂe“ïH,Á» æàâõ'Ý=?ѪNº³»gèŽ+´{82Ñ®þHvg²Ýã¦Iv]cÔ`7ñK\÷8?S¸ÎUƒuØ÷¶Ö¥¾ìŠu2A™ë’?m‚Ý-{’×IvŠ Ù%"þCvû!ÙaÐsH™ìn{Î’ìn;Ðí;@‡í»z†ír/“í.=‰ÉvšÏ'ÚÝ9Il÷Ü¿ŠÒ„vØ/p´ >™íº¦ÂvÝC5t—(–àƹÀLx×ü‹S|ð®ÛD¼sÿð]›ï°ëãNÆ|7Œ×á»aÉ=|7䜾Î×ÀNÀÙÒ›ð†ë‡†ð†¿ìÞpªj#>pmT…xØšpC)Â+Õ{_ ¯êjói ñ°í0âUÅvuCÄ«Lu:©¯Âjôwg­ë‰’„^ó'Èk^»yÍÄyÍEXBy=aŠòš÷¢‚¼[¾Ya¼ÛcÄŒw›ÌxÉŽÆ»e-Œ×]4;ŒçÙ Þ³ý²àÝýÅwå½,š‹ùQv}óÝcG­ð]wu¤€æúhx] ¢x >àÝÏ3àu-á»á"ê¼ù xNÀ»‡æø¼·àÕý£àa^9 ðàã&œÓªäN¼áÔÃ!¼»‡.Ex±…†ð°ð?Â{š°Ä„×›·í&¼dÁ åu»ä†ò"iÊs‘’@Þp C¾'Á£ ~,ÔpLyÝÅ¡¼~ZOäu'奸L(/fØPÞcßÃPÞsEéæIŒâ=.=ƳˆÄ{"º‹ñ°ÌÈÈx™Ž…ye ë+æ•O´Àïñr¤S„yóQóæ+2çõ©™ ôúÖè 9ÃOгÎ3õ»ÕO ÷Œà˜<'XA¯}%<è uI °C`ÑPlçd"A;W 0Ù¡CÊ`‡¬%dÛ Ýð7bùnß}’ÑÎI'ÚÅ­!h÷øs Û9ŸËðnk~f»ÝKEØÎANb»bY³Ý®p‹ Ý.)Ú`·;(8Ú]Ò«íÐ OÙa‚ljìvmr&ØelE¹s(á?Ie6iî¨UfŹM.V¦9çÕ Ì9 8,wŽhof¹]¾sa¹Í{­°Üæ §Y¾‰ìW(w:?dP.¥RƒrI«f–;00w:ÙŸaÁß××!óŒVhLÏÑÓ%3~ZñÉ<¼ÇOæb²bw¼,Ù)iëTì¢Æ èâºèuí듉CÎÏ%ΪØõ»Ðƒ»=ž‘Vì”Ä^ŠmkºÃ©kCtG0ÝD·#¢;ƒ£€îP™ðÜaÿ£ÝᔸºÃs€î°«E€îP¢ÚðÜÑã *žK…¥ÝaÙÈõ9Ò܆ƹ£›»¤Ø®‰ÅîpZ«vhh’ñ¸ Î lœ;.Ëx¹Cõ BsI š;bl1Ía`ršæŽ{ÂÛîÏó‘GšÃg»h.¥¦CsÇ­»1Ì¡ß[xG˜Cu#š›ƒ×ª^ÓõQí›Às©¸š;¢ ÍvfËá;É.ã%0wت˜CˇåK³¹|h¹Ã[³œ§±°Üá:­a¹£Gø“b—!ÅÇœÅ.<ŠÝá¬:Qì$¼I­ók±néAb>KuG×FÎwô\AJÝ¡º2¸åA\¿â[q‡ê‘†áÐ0V†C‹¥; uk‹Åóp:¿xbö[‰'ærŒ<1íäOÌ#j<13§Å³*d,2´ï´/æÛ¢nqçî䋉“ÎU¦«µIž—¢¸SŸ¡¸Ó%Vã‹yá­Ò¥ì]|1—QÜa¨·+æ|qVé<ÿÇ3kDºÃúyD:´l«HW-ûF_G©1îPaÔP\•;^5ºªÛJq™cCqGìöÄ”b'}.SyÜ0K1Üaç^»a·b7Ì9šp8éY-æ¹af|áŽÈ|öÃÌNÅ~˜‡ræ”æ©Ü0F8§ ÁaŒõUœCK¼.¹xÎQg?Lg‹‰ær’Ü0Ï©&J›;·é˜ÉÕ3y£Í¶OG›Ëêmµ¹#^äÖæð¶ÔͨËå±˜ßæOÀåಠŒ&jÐô•અF;a&—`œ0ϸJ[žCmé±ÊsÕr¬·¶H ;]I9N˜g4|a\É<Œƒ6äû‘fË—c.™àâ‡ye’±#&*ëá¸rÅz¤Êqm6HŠåàxÅÙÍŽ˜—KE¦ƒ·–œ, s•‚ú—Érpð’ùF,‡+ÛSn˜×ÇLENVY8\éOd.›ž˜´C-`‡š¦¹=£Ÿ;1£Ýá:%“íü–'ÛÅÝQl——¶;#$ØÎƒÂÝöC°ÝéÔ“íìøk¶K¢Á°]òZ›íâŽg´kÃNŸ"»Ëc;dw™N v&Çv—êüM©ît”œ°îÞÀº[í«N'7?sÝ3)N\çœIÁºÄßL.×X÷ÄÐ:/mª{žs•³¥ÉÃÍT׳³7Õõ3ô%ªë‰Æ2Õ+qÂ:‹S¦ó[ŽLGÆE¦3Éêâת=Š °n&JQ]œ™LuåêüuÄŒLdª±ëJb×I'í‹–B»éG.¶+g’í äëíêùo í`ƒ”£¥Ðn´øköØåCh´Kâã Ÿ·À.†Ãp]r£šë–Çb®–OÂu#^Ú;û´‡ëFœ²Åus4˜ëÆý£LóMtº.72]& ƒ]|‰ v}SêPs]ìÄIâ:¨^c•é¦ã»ÁnºìÐ1žKÆ%Äu3 œ¹® ÒêÅ*ë¦R\WçÔ8ÖÕ)g°†ðcå:Lv'ãUï‘ñðÆQXW –ä¶&#ã“€¹&+c‹²wÉÊØ¬ã‘ëÐ mÂâºE ×- ’5:T€W¿ÖènÇÝQ¡ÛŸ¨bŠ ØVèvÇZX sµrƒÝÈ>ÝÝñRÝaSºÐ®c„ôíЫÜZÅv=^ÿf;|<î—lWØ'ÌÎN¢„»êùøtðéï…î8ÌOèŽDcY¡;’îˆ;‘º#Ž®èR3Ñ Ý±[±“@‡‘³ÆÙõBBW¦¤U¢Ã[bpo$º#qUvÂ<'ÌÃÅw˃ˆH“¿Eº“¾”èŽD íf:È(t§SÚF¢ X¡;¢“X¡K¦ð(t)|…Î6*tÇOEù_ž.ÝÿKì®ÆG¡K±÷(t§³.Å3õ1#ÑeO‰ù[-ÔèNWŒ1àÕ/е$Ò1êX¤;=IÆsîé­Òqb¶JwÚleÄâá8:©t犢JszTº$ µæãƒ=0“¶5˜ç°¬o™î|ü]Z¦kq·Lwª@td:ÐVûÈtíGÈC7z\–é Gœ$Ó-~’ÒéÎ8¾Z¨;]©'B]R9òpuÁQ¨kG\= z¸Åõç­÷BÐëIŒ©?[w'©î´w€¥º3󧵺3jµÅº³ÿ Öé-ÖÁ_‹u§ó²E­;Ç?®¥-Äcµ.µ²£Ö {³Z×âDb¹®©hÔºå¡Ö%ím»Ó1ßVìÚ–ì`Òìæ“±fw:q{4»3ö3‹vóæ,Úå‘[´ƒÅYÌ¢]³£ö’ÉìÅÁþMŸÓ‘ŸsÍû¤†5Ù?Ü#PÓƒwPmýÞ†‡zˤ<×»¿9Û"}¿{¸CR¬˜÷¹Þ ÎѽämyªÀÁÁ5÷Á¢·3|ã…°É0ð“G œ\ž?ÜÞ¾-½±­Ô­Ü[c;Eí<÷^¼\ô‡‡¼ßog-ú²®3¸™<ÿàé\Œ×­Ûª sæ‹Ùt™ÊãUîæ§Ró°º,N?׃§’µ0 íQO……ôòíÖK•!p°=0™î½|V)C>ek¬ŽTÝÊ3hñ±¯VMbÃ{Ñ{‰²}P‡¨1>€»ðu(hß,+̃„Ö'—¨·ÓišäûCZlåÛàîHÓDoZ=©Þ;ËJ©\í{7}ö´%}oúd0–Èî½çδ]`ü ñ÷ )éþAÿŠ”tÐÇ 8½i‡û3šìmxhLËXÈê&7T™öx»ã9eNsõ³·åù•~Šú»#G«¡ñ¤/³iëm…è‡k¡¾øõИ¦"{ï¯Ä³KòbàýUyΫ"ÜÎÀûG™R†Ž™ÙÂé ÿþòƒv4' {[éÜtÞÁËYª8’_l¤sG‹½/b/:ôù¶À _˜W¿ù}êwáùÌ‘á^µ–žêWç°òÂpV„^µ–ž*ôPÓzG©¥·;hbœÖ{•ZêÕB¿ŽRK7ޱ#D¯ZK£›÷R¥–Úç$̤¨1á@â^µ–®ú‘©¨¶4ª_Ù¢ªØÒ{H»°›«VÍ‘TM½ª-ÝÕ¢·jKÏ^géT¹%c¦~W€ã/ö8#Ý¥qÃÑPÕ–®j ®ÿ6ôúS3;J-µj •¡c_;ªÎw½ÜÜ~Rxéìwëšš¿Xhi$ލWÕžºO¤;‹-ÝRd¯”+¿  žŠ-¡ïÚv•äá"ü>Úíýw—ÊèPXqÛÃË$ÌQGpoÜKóû;ýèVïmŸNÌ×±¾uU‘ÞKÔÆ]ðõ×rQ}rÛÕ{IÚ£Y-}¿Mÿä&jZd¡¢ú™¨#‚»º´¤TÉÀÏ=Tu¥ålnäÊÑÅÚJ(D¤Á…ÚJGÝSÍxOï¿Û±£ã‰îu‡Ô2;~ oY‹ãx/<\²ã^¯º¯’Jï¿_JÿÔGÉ×%óAA¥^èŒR¯q ²[ÁOI¿Ú:B³²L]Í’þͤ6ñ¬‚,V“œuæÐ”¸C¼F[Ø^€VNvÛÐ.gZ4¡¡E@CB[¢á¡óƒ¡=—óԘЖ^h•{I„†}­B´ò-$W Ñf†q#–5ÄhkÏÅhUr®­¶^ª(-•í iÈg¡•M† ñg›ÒàËÄ}›(-½Ô*í›pŠ V¥É¶ÔhÂ0¤Í,p†´™›Ø¶CH£È[!¤MK‡! IѸ* Òž'ë$!­rQ| ½§ŠÒfŠicÚ¬|hL›i{Íi3¯¶9-fc &_L›†cZ2Ó`SÑ^Aœ6SàÔàû§µ^¤Vå׸tŠÔ`SÑ:%R«œ»"’ÚÌÔ[¨† ‰~k•ž¶/°öô‰P„5؉´G­Uf5>=ÑZRîÖpaîpÅj¸ÛAô$«UªÜ±²Ú4$™Ö–cDkqE4­M[“q­òm’ˆk°5iÌת,Ö!8ã çIãÚzqòZùí ×ÊŽ/[¼†è~™l3¡‰‰­²~"4®¢É§kfK>]#[9á²mÙ‹Ùjn瘱;œíÙÐVY¿D[¤¶µEÔ¶Ñ fÛ®¤˜->wa¶ÍÛ0[Ì]f¶-HifKê3Û¶¥mïT½ÈÈl¸‘· mƛڜÈ,̶«¤k˜Íö/#[œ?l¹Ü>Ì6!³U¾ N“b6xpw*d«ªuœB6ÚNÑ™mf,0³á,½Z1.e*fC7Vb¶òèè‘Ùæ²Áwè$"Û O6²M/:#¶D~…l¸ìD¶žB.…l8~[ˆ­œÆhElÝÑz¶òÃ8ù7x fDY~Èk½¢'Äjþ£8­'ÿ®8 Jäú<ô÷àÓp35@ip* ´=u«™Hià,Íï¤4X5·ÒÊGªz$¤õ„M Ò»#)­7'¥•Ë¥õÄzˆÒ¦O(­øçø•¾Iú i¸Ž^) –Â}Å4œÂ/„”“ªî‰œ ŸfL‚aô¬jåÓ³ÔÊ1ˆ¨á Ã$µi‹$©õ’©õ3æ’Ú´­ÔXmR\¶ÿJŸ¦ká´ù ü‰ŒhF5Œ:Ø™'«ÅÖkTîV»|¡ZU·}V%­;ÿ™Q-¿Û¨†I!DµÞ" Õ`ƒÕ’¬VU¶Es„5´ˆæ Öp !@°†Ä‚5ÂWbX[[kË…kKÇd54è)ˆÕÖK‘Õ`¥ÑIDµ¥¤¶6©a˜Ñ¾mR“iEj#„*RÃ!]è6Êöã4I&µ1 •¨ó·@Fµi02ªęկñDõ"«á]š¨6NçS6ªRÀÙBT‡W³ÚÚBXÃç%µ°†n8¬ k#±:†µ‘P/ÃÚ˜ä+X›ö£¢µªÍû® Ìv‡ð¬,ƒ§ªš×Ї°\À6’.ÜÀ¶C`›æ2Ûz)Û¨tÄÛ´%™ØpŒTN!Z ID¶! "¯M3›ymœSÙ"¯­-ä5X¹Ìbä5ùæBb^ç¦+^gVñÚ˜VòÚz%Û°[¦y çhÞ¯ÍKØÐE2Ûz‰m=†Ä†~d˵xXšÚæ›Ú† †6t³¯Ì†+™ Élh±øFh[~¡m¹aAZ´›"´Õû:VhÃ!ÚM ÚÖcmh8 Ú–_)jC‹6 ¢¶Ñ&’‘ÚÖž‰mëÕ‰m8KÆNaۈײ± -ZÜ…mÓ„)j-º¨¨ -ü:ŠÚ𧨎І«vmè“VCÛz¡m4û€Úp– ŒÔ¶öClƒíó¡ºGlCÃö‘Ø`/Õ¶ Û}LmÓ‚jl[®$l[~´°mÄ&el[/ElÃYÚÓ Ûó­° ;š+ˆm8B{\aÛzNan˜veQÛrލ ž§_jÃ|Ò?؆ ja ÚÚQ ÛæÝ‰Ú«¼¨­&ª2‚6T$×(´Õ®‹#XØVUËÙ@jC/&FR¤ôðDmËÛ%µ-¿IÔ6ªÞßBmøIúxDm£9ér¤¶v›ã$µµn RÔ† ýÂ6tl9ŽÜ6ZTVkmK‹Ä¶+n‘z¾­¿qI!2rÛìÇrÛ<ÆrÛÚÂ%u9KzÛåÈzÛõXzÛüYÖÛæ#µÞvmúä-·-'In›‡Hmk±rXm»bÁÜ(Ëm—àRn›¿PrÛ‘ÜvÅÀ!¹mEÉm‘d¤¶]¹¥¶]‘$¥¶¡rߘԶ9.Km›ŽÔ¶åg@m»â"µm©m¶ãZl›W”Ø6ŸƒÄ¶Ø‚-¶-GPm»T±ÍbÛÒçÅã-ðQl›ÇSkSx¹¥¶9p$µ-¤Ö6µ.jmñŠ:Û|ÊRÚ.'5·Ô6Ÿ’¥¶ Þ’Úæ/–ÖvÅP5Å6jyÔÚ®ÓÖim‰¿°Öv¹ž›µ¶X÷­µÍß$©ÍúÝ?I}lÛ¹mX±ÍO"ÜvÆ´n³{Íä6‹]á¶éip»­^Üî·æ*š·æœ5·6+InD“Ûl¸5;DÜZÅàv>ëÄmí™îŽ·æä'7{™ÛР̸áGkƒ-r[N"¹Më‚Ém’³À ½ðƒ6¹¡E Vä¶Ar[[ŠÜÐ ¥Täöi¡ypi!¹áÁƒnk¿$·O íƒHZ®³HnËp¹-ÃAä¶ü&’Ûl¸õä¹3¸aÜ™Òh Äxs‘Û#¸ííô—ÉløG9¨’ÙüÏä5ü³%;òÚ(öœw ÿGhòÜhœ‡H]Ëf=òZrúE^K$`ôµf #úÚrŒ¶å lÓEØÛ”@-°eß ~xÒò$°­-%°5k#Øà‡w,nOvÑQز{·ÀÖ" X`‹Ãr¶òÃX -Z,±Í­­%¶ÚrJT£ÌÖ\<"2ÛrŒd¶xXXek6·Zd[¨±5%‹Æ6wŠÒذ—|V\‹Ök‰-)ü#±Ím¡%¶èǑؖ³$±EÛÆv•Á×úÚÜ¡X_»¶ôµk·_¤äµk·¦ÔµhÁQ×®Øu­®Ù9<â¶-|­×°¢è…—ìÕÑÊZêU[Y›ë¥•µËE¢¬-'IY«5t…4ü`ÙA­­-w/qírRˈkó‹kó‹k×TŤ®Í'eumn4¬®]1[]˃±¸v9[nĵyˆ´5ÌÎÜÓI\[$®ÍG!q EÂ¥ÐI\‹öq-µƒ#®a‹]ÃÝâÚ•`LQÚrˆ´µË~¿–Ö®)ÈIZ»bÆ·´viª5¤AÒâ Òf|)­JÂ}(mm!¥M×QZ• ÿhkðàG@HÃßÚy Ò*³Í!±*qA0¥U¸sÕÖí`FÓÒT!F«ôÔìäV Ad]!ÚÔ‚EhL¿Šk³D« ­ ²n+¡-’­­ +ØE’*Ë1$´E0¡UåTrÚ™h Œ¿롆 /Dg8A˜$:«Ì6"ÃGAù¸„g‹O<«Ê»’Ê Ïª\šÄ´íã@<[ ÏfaáÙ§xVÕË8ÈgSÔ&ž-Í ÑYÕêÑØföÑþÝ™ïs[diÒYå_U¶*Ð<›]…g3-ð #Hs)ñ¬’!YU;~Ý—ˆñÙ,§R|V7VgÈ ;™­êw­:ÛŸ|él)$BƒoM‹:Û´%´mñô—Ð6;•жÅùFBÛØÚ6—>´Ò¶ü;•¶­ii–Ò¶œA¥-q'VÚ¦/¤¶Íû_KmSvW€âé¡ú'ÒšÅ-ò)W¸Å-r´Ä…‰ÙÛqÃl{ÿ‘Ù–A[2_Úð\‹ÚVeà¹#¶c¤',;FÚ—%Ž‘*F¶8„Ù’)?С?ÐvÜ‘Ém‘ÆCmΨ¼B›ØÊb[Tœ@›}“m‰”´ñ›Ø`»ãhb{¶&6LNR³ˆlOÜÑŒl=N§B¶¾%¶MÈ6âl)bK^ÿÛˆ¢d­m[…6øä·Î¶e—n-ŽüÑÙâ QRÇŠk#• #´í3|LBÛÖðŠ»£)"´M²„¶øÑZg;„he <¼ÄFcÛ{´1klyFÖØš'«©±]}³ÄF‹Ä¦ø ©°E…³Âv)‹~¶˜‘"°-Όٲ­‰È6»‘ÆvmŽ´ÆvÇTbíV¡ƒHl÷ΣĆÜ?m%¶o@žC…íVæÌlñC³ÀÖã]bmúÚY`{He}í‰[‰õµÛiO¢¯ugÀ‹¾6lu´¼ÖcL·¼6Ýì¯Í͈¶kº¶D5šØöm«´X7±½ ×ü=Äö¶Üxð7²Õ9T„lÕ"Ì#²½-[­¿ÙömO”‘í]eù'yí=à½ßj ²í”ñÕ%rGB´¾2ÛÛÇÆ¤†¶·¥f·¿‡ÚÞ³êzµ½Ç´_EK¤¶÷˜[÷+l«–kU×Þ³n]ÜöÞrûü?í½Ë²î8²¤7裡©ÚF‚ ˜žBVÏ ëA§µÞßwWfVeUÉÎ@£Ì/? àƒÇ…¹- –%¿ÜÖßéÂ@p;‘œM§!¸Hà&à¶~‡&ÍCàv"›Ž"¸-˃<5¿%¸-‹¸À-®æ¬à¶,Ø+ Ám…-°Ü¢Ÿ£F±?ÅßÜÎ#F ß’Û–aÈ@n;ñn›ä‚ÛV“Çý܃×ð›ÁmbNü-Áí<"ÝÑoæ¶ß-qÛ‰¼uo•×Ö1—nRÜy*ÜÎãõÏ p[m¢,,$·r.¡[´á!t[ýDî²ßÝ–åþ%eŒìv"'ÞS¶hÃGì×#($»í'*t[Mž_/'Ðmõë—BèM:!+Øm5êVì¶,íë¹n å ÃBv[mü½‹ÝeØémj¸ émµ94ßÊ ßN U7"¿HøT~ ïSü¶,~-ÄoËâ]üWø0>ŒüwÁ/Dü¶,¯¾FñÛyb Cà[ô+Ù‹üv"]!!Â-ë_\'êáNd4”c&nY"cÝo‰pÑæ)Mø%á¢? ÜúÓn_< nÖׯ*°-CÓëJ‚;‘F‘£4 nu1íQ· Ö~Ép«ÃÕ«Â+wFÄ_ü · *  ytÊ`¸r<n]Ô­_Ž · :Èp뾚 Áp«ELó¿™áNÌK–ÔÚ/ýŽp›qÙÈRO ·º<ô"’áNL[ܸ!Ãų*mÑ'i2\œ³2\9îŒ$•…áâ$ ) †‹Ë 7e \œ”ßn.Íe@¸õ°ýýáΘ[IWpñ¬øøÉpË0™êG Wu­müY(;ÐÙU¶Q wžéË¡„BçÅÁ©d,›ÜJþ¼AÜ™ïÆ–š{ìOÛÔäßËX¶fq`U=-;;˜M; ϶ìü`ëÅ ÷éJ–ÚMµ+[JW˜?7—nÂP:ÑßÿÙÙÊ&r-÷?JVöE²²þד•çÿj²²ß½'óyÎ’ôíûÆÅËŸqm¥žv2õTÓ¹§ÝÈ=ÕVêi§!SO5 ™{ÚÜSmåž2 ™{*iȲ§l”=•Vî)Ó¹§’†,{ÊFÙSiåž2 ™{*iȲ§l”=•Vî)Ó¹§’†,{ÊFÙÓ¿‘¬,|"ž?ÉUöüÃ\eëõûõ¿ÁÕwÜÎöüÃ\eÏ?ÌUö/ôØþqí¯÷ø»\eÏ?ÈUöÆî¿ÿ†ÿh¤þû}¦?ï?ùL×Ó_ÏU†$ÚëM+©Êþ§Sƒý™-lç «yÌþIбç¿`¦2ì(¬Éù•­÷â¿ïÿý¿2oØ?KT¶ÿßù>íÿ+ÿüç‰Êž?JTV²—ý»‰Ê惺å~EÁùð½y¸ 3â×cΜÏËFÞ'_ˬˆ°ŸHz>óTu1Ê8Ë€QÔóŠ}¸ù¬?ÆêPëQG¦ËŒŸ8§{nÍÈvÕoþô®‘ÏŒ;]3ªÏ³a§áf.ÅXÐÎÐßÂâåßO¾]ù&Pu ² ݆1×îÄ$ýfÔð 1ŸÛ|3âévÀõŒ°·-ݯ¿Gˆò[·Èœš~rs\×çO¸jEzÆ>sQXçÂ[41~-„ÎÈfóù;¶×3Þx" EEêÎ{¿US\‹»£T›Ÿ˜”oÖä4œ!=öˆ™ÈÜÑÃ;##â}ùPàyÎŒjzŒá¾\g8œE@p¬„'v3™Ojû’,^OÇ„õ!Dm±÷ömÌÁ"êúé°aÇÚ”~fìÎ…ð;ù ø!õ¢Ä- ÂÔXâý”!dÜaÿìÄ=¿Þ+¼,W¹å x´°.ü%ÃüÅè\nMbðùÅ —ûÈáWž}ëï—eƒÃJE[€,ûpæy s… IùûyñM¦¶ËøU#P±Bn´ ³, ‹ž’ø {‹ç¯³DÞÂ2~1®–^ËÒYNâõ™ð! ;~á •Â,#t.G- ~зŠmË+”.{Éa¿ñPmb °¸ò_rì[Þ!Ò9¥Å²DynEŠcs4‚$'Ú_±óÈ·+â$¤Š]͈“<]³›‹)y>ùÄÛ±’ç™÷Øž–DÑ…S–7"&O KË0"j<Þe`Ô¤cß—eÞ‘\Ÿ_ön™N›h0̸8‰0ØŒ|U—@?ëYKÉßÖ_WN69€ÃUÙSûÂg„N6ûMaK–Uìb¿,OOº  <™1œËšõþõ÷`øä™7‡’IU%„…!”Vô±GÚnFD.ËÉdp-bÔLzK":XGùHJX¬d"ˆ‘C,Ð/ÞkøSCÍ$æ1õ6õ›¹ë†þŒ‚I‘ _/?*&Mfï×£bŤé–Py»…dì; ’:&v~RéœXX†Ð›ƒ°DT¥#—?âöO]̘%h[¿g‰“ÄßãWñrÄ>/SÂå÷šI×·äo(¢Fï‰mÕû×[’Õa›7¢“ïË/ª&!Æq»¨šíS¿+Ê&áê÷Ëÿ0@ùž9h¡lR‹ïe“æ×9:rÚùBݤ–ìóbè¬>9]ˆŸüjP6é ƒ¯ŸÄÏcÖƒ åG‘)ø3ÄèÒàeÔòsçïüÆþÇÐ/ú2fù=øtÃF™¯RÅ’^z²aŸ·ÅUÏ|ÛT+é½òà /§È¢ççF¢Í­÷xͯ¡ûkÁ\HEùRèÐað烹¤ïÄtØ&?ãÚoDC*ôÈùdÐ¥Â{ãØ%ºt;èSñŽœr¢\A\ïyЫâ½óÍpÂ}§§]JÂYº†¸ÈUùïüé°RRÎùEŠôsƒ6ûè3ô¬˜G^-6Y£?m¨ÖÌ´§^P*鉜yºDÀžqŒGÁg]–=îLx CBài"-úð :é9\NsÇt9œøaYž˜.Ç“£ DÒb½§ ©o$ëó¤BI3?¹€¼p ×*¶Ã¯Pô¹>;C¼ãÔü Ψ•YöèÎs†ÔÖKj¾3ä8¶áÀJÛ'¾Ü¤Ç|9šx†äÔ"ŒË=žräÄ„ê—ÝðWL–Ó•Û°ÍÎ|zzJ!zÜÑ¥ž}L±ÇG[Ú=N¢÷àD™¤‘'ñþ”§Kn?G AŸ•”½ïÿ¯f%KcBÈÂbvÈ"‹eŽ2ÃX¦(3Œaµª„±3ù†±Cì%³ˆa¬ùõ4Œ9’Û,–9ú cØBoÆš‹gÆ6 ŠÆŠ8f? ãX³”yÌÕ¾cÍþƱ¦ÐÓXD…Wk#éç%­™ÌõÇÉcYÜ×mX¾63ÇÆpT"\À¶œüÝÆbVÒÏFCïÆÐƃi쵯ši ùæ¼ íŒt¦1X4f‘ÆÐÇ£; ŽaK›=¤±¨`Û+í1ÓÚø7P ÛÌgÃÊ_{QÃöõ’M4¶=ÞMcuߌ4†ƒü0Ich#* Œeí\³Xm(†5¯ÖÉb8æª,ö9³\ƒ7®Áµ}äàOÛÅÌb;%ŸYl—T0á( d²Òñ›îí eu—û›{A„²r¹d²í%O&{Ó!ÑL3Ø“UC YºÅÉ>á©”LVv‰d;ÂL†^ülÉdu“’L‹~DBvõ¶Œˆí˜¸oc&×=ÞÇ4@ªzm¹”Á}Ì=;‘ÉÐÆ_4¡ g6RÊvq SÙð0–}-ãA,ƒç±·YÉeñuˆjZ\›ä‚Ë¢úò]¹l‡d˜ËbÁÊŸ€X–¥MeQ¹W,‹bÀ‚.D+MAÊÊYLeǹAŽT–¦²,¸‘Tv¨‚©¡ìÓo@¶\5ð‰ÊvXSÙ.Ó‘d¦Ä…ä²Ìh,ï.$¨¬l Ëð8Ñ‹ÊÐ¥¾;‘ÙŽ•0šƒÏLX–ÁÿB2‘öž×£J0î+—ûನœJƒ\6²¼¸,7Y…e𳺪F¶Kº Ì@¯r¶OÅä²ahÃUÊÁ,·dÅeΌìógì6µâ2܆T°à24à).‹ª¬­èdµE€Y1Ì2§ ÀŒYÊÊ Ê2aa@Ù¾2Ù®Q"(›Q5–†€²¹1‘T†O}l¶7u·€2€’u·€²(_P¶Ó‚•Íä>RÙN¨%,Ûùå…e;™° Ÿ¡°,£De@‚_„QbY¸I‡c‹°, |½ˆeá¢}±Ïà2 FÚH˜tê~¹ @,›^TˆÊÖK™»ˆ¤²ùìý%RF3ñ¤2œÊêV@b<@Ê2*ÀPÜf° ²pÌíê7¨,ü˜‡»p%ÇÌ«–a……BÙ´Œð4µOµ¹ «£d·³ím0 omm̰¸äŸeóøg0Y8Ðë߃É>”ar¦·4©,¼žu3¤2Ìd–Heq;¯ú * wï*…C³v› eXOýòÅ”amDO_SY Çw¥²x*÷–ÇêÅ˰úei+ÜÿíÈm,Ã|BGcYx/O^ ¹ 3 ½ÓÍeáè;%v=ô–ÅW¯6fáQlµnÐ_ö@š&YÒaV*À,ÎdU)À,îé¶h6ËÓÄ3Ìf ¹0™…?ð¨dW<¬MÖÃ|è(k6‹ž¯Êf˜‘ïa6ÛŽåf³èGOp¾ÊgÕÊÂíW¿%éìk¡ í¾bâY}Zijø­¬OŸÅ¹u5ä³ðj·å¢Þȯ‰€¶]á hqÔ½ kE,ù,^Y½8ä³p–ç->‹¯eV>‹O¯ ù,NdÒ:.¿&U+‹ƒôüˆgX "T!,gÛ§Ù|ƒºœ;ì_o>‹g¥{$ E¿ZtÐâ ëƒ'¡…ç¾a1-½Þ há‚oÍîêùQÐâõÓM=tXþ ˆhñ[‘’ÏzËAD çW`ˆÞÞú]Èhñht „´XbY;â=?s &¤…[¹Þ>RZ¸c_U2 ïi_2¼×Ï«{œ §G­‰ÉýÊ'LN‹^4½ò`GàoŠœ¶Ú<¿¬´É‡ýò3'§…¶‘KNìQ±–à´ðÝÖDP‹£¬„½â‡ú PKçmƒÚç µðK×hCT ?ÍEDµÕæþUÕ³Ð1AjËñCa‘;ûyûé‘ÔâÇÕ- ¹´Ÿ9€ÕV‹3™P.í0«m×{ÃÚçÜkñªéCrkoŠs1¬Å-ÈBXÛø†5"ÏNX ‹^YÂZܧÆoÀZDbh°ã° ·BO&c‚ k1Qø €µúýÖâQè…%­EÈ´ex Ñ– q->Ž[€v\¼\ñÏÉ9náB àµ2“ˆ×bP;DZgÕýhéšUÏmá¬:ĉk1®ÈðpFu¤‘i-†S_ÐZ °ïæµ8F`E`‹‘²‹ ƒØâ?M¸Ć×Vo½-V· N.Ú¯¢[ŒlöTl‹™&¾ö’xÌ"ƒÄ·†–®OÔÐ2BÓZÒ¶54ó¸Y-“ ˜Õ{}XD›©º Ö’¾ kéeXsmK³Zº;Ö|Ô¥š‘Íj™®À¬vl!°–é k‡;›Õ²€YmŸR¬¶[ÖªaÔSØÊIl¥9‘­^¾d³ ¶r[$¶zŠ@¶!5vAl¸†êÕXÎ `+g ±•IlûQØjƒ¶ÚE[5²•ç@d+–ÈVNĆ¿¥ª’ØÊ 1G+ï ‰­vÈVýåˆl¸ˆô6 dËNLlÕ5ȶ·€DlŸ~ûù¹2#ÛÇr?º¼[ÐdõØ/ÈV¯%ˆíÓÉxtui bû¸§Úx—ÄVî€Ìö9H~¹ò#¶}œ ÛÊåÚ> Ò«Ñ‹´´ëÉ{”–v=?µ´ÌzZZ¦ëH-íÚ›èÓ®$Wii×›RGhi–aSK»öö~hi×ÈßCZZ¦…K--Ó¤˜–Ù RLKý6Å´k»,RL«M(¦õܾ—––‰ã¤¥õÔ$¥ÅWRZOï+)i½xBRJË4r)¥™XbÚ…¥¥õôû’”Ö·§¯¤´- KIë[K) ¶¯–ZZµPKëé,)m«Ñ’Òz7.QHëý‡WãÛ»ÅC i™™.…´, –JZæ¡K%Íyè$¤!°Õ8 iNC—:Z1 Ø–´%£©\2Zß:‚d4 ù©,¶ó?–!•Ûþ’Ñ2ynêh[ç­oGSÉhE<—޶µrÉhÅ@­oÉB2Z*OíÞÒ’ÑŠE2ÚÇ2>𻄴{K!Òîíö*!-sΦV-TÒœ/•´"ÝKJsB*iå[J+N–”ÒTŸ\JÚ»Ç'IiùïÒ¿–ÒÑʶŸt´ªµQG« iïl$¤ÅQBÚ»Ç i[µ´–c u´{,£í¡Å:Z‘ý$¤í±ÅJÚv/‘’_F{RJ+b¡¥´b‘”–_½•´¤¤íPB)íÉqZRÚØ¿¡¤´‘ß§¤´ÌÚ–RZ ,”6ög#)­È…’ÒŠò')­({’Ò>Ji©ìQIKÍÑBÚ6HHÛNÞÒöa!-÷;­£ÙÖ2ÚD°ŽVÔ8éhÙFBšÓ‚m%-%Df»*˜É u©¤¥«ŠÈ¬Jt’Ò”¼Íhqض•4{û™ÍªîÇ̨óÝ.ƒÂßekŸ\i&3XäF))-² feâxÞ%fÎ+Ç ‡6û[ü ‰Æ iª2±)-g|RZ:™Ò‡ÏE¸(-çv{:º¶¦s9`JË{²«ãîB®ŽLìê˜Õ íê8¶æFWǬôGWÇÍ’ruLM;1M…r’Ò¶'#)­9q 1mM†KIjoJRÄ´Ó FcZ?ª³#0uÓ.{fÓz)­oÙŒ”ælɦ´5Ñô^)­§÷ä+oú¿m@»ÓçO„–eèhó¯ÑÞ¶ãÐèHoG=#šÏh·åXÚ ~F:KïoÓÙ;Ó1’t–nè¦3—(7 YOË4f¤³ù|ä´#ß ÁÙ¼sòœÍ«ø4œÍ^¶ÐÓÎ#ýµ%¨{Á'Amoæ‘Îð€é‚ζ„i:Û ÖHgèöþjèÅ XâÙ.×d<Ãðï—xñÓÓ3ñl†“jų,¢d—l6ÇúÍætš@³tkËß„³Y|Šˆg8µý?‰g³,±,¤‡åA iÇcœ|6ËúŽ|†¥ŠŸ…´5bØóQJÚ‘*3 mb›÷+¤­i›š„6÷Ê:Ú™ò·u4çÛBڑŠ…4¤}QHC¶>$ ɱtûÁ÷Ë”' Óž@J:Úìz%4ü,¦<ÉhR) e´³YµŽÖμ:êhÇ‘²„u´3eÜÐÑáÎáaÔÑЋ$[éhèåQGCBI«ÒÑpSÒ²(£!EŸF%Éh¥ e´z&Êhë{È륌†U§NDíhÞ±§Š†È¿™Æ­)ùUªh8FJ*Z¦ñKmAR¬¢e^¼Tѓ﨔G}bÐÂYA¢‰d4¬aFm;4„ІÄyÓvÁTÑp-ކ£Š†}z9¥¢eö¿TÑ0MZi£Œ†yò®Qh;‹`êhhc-‹:Ú5:héòJIOÜÐѬªt&êh˜ÝË#¯””c¥£ÁÅasÔÑŽ~II±Ž–™SG;úí×F:Z京Nx™­ÐYG»Ÿ¼¨£AmQŒ[èhÇZ«t4¸«¤lv8碣àn9§<¾s ip`ÑP(! i5­êQHCŽÃ[=SHËÄ‚)¤ígL! -^+Ï/•´tÁI%ÍZœd4¬Äk4Z<ªÓž”Ñ;ˆ¤’öXO)­t´ã9ô…¥Žv[啎–:©£åo”:ÖÂ_ Ó ’Ñnƒ[FS¹"£åƒ²Œöȧä;Ϙš)æjܨÞIÅd©éÁþü¸ÝÊmþÍ´b­§vÿü»$ð CI–£¿K°†ÃǧYj74ÕŽl)]]'·ÆÊýÊRº’©t•–ÿì´b ðEÿ[iÅÆÿ—iÅþàM9C˜ú&ûñÖÅûôŸ÷ðïÙWMƾ>©ÅÔWi¥¾¾ ÈØWMƾ>ÉÅÔWi¥¾¾)ÈÔWI¦¾jz1÷µ[¹¯O2õUR‡©¯š`Ì}íVî듆L}•äaꫦs_»•ûú$"S_%}˜úªIÆÜ×nå¾þ$c‹ƒŽþÿ,c-ËØ_Íÿþ»qùÆî¿ÿáwûs<ÿ“ïöw}ýõLckX»àLURí$`ÿ¯æËŒfÿ¤—ñŸal}9Ïæ¿vб2IüÿøòŠ­÷„ÑËŠM/#þÞ0:c˜3R|YPð¤Ã5VÄ?Dضâ}NøÿψÄÖ¦þ‰d+½DV/Kç~v&:8±Wy•ÀeX¦djoë#E•l­$ƒ™·Î{FꊢÀ.C¨I=éý“úš„—s*œÙBã9ÏP‚³¸,¬”bljm¶Q²}- £™³šÏ²ôPƒ³ª,!ß[À>Ó1N߀="Æ…*Ô‰îîòôÓ›¨µÃ5OìMô×Ô|N‡UJ¢Z+›Sy½¶%vß3Mײ0¢y‡2¶@ÆÙ†4ï8ÅœzjtcÃz»È‘-œþ‹Â×úal!±aÌb<·zC.ˆ¹,ã’ž—'š±ôpõ†Ô0=ªíZ@ ²KÞgii‡¢ç|ª®Y £]ÂSUЖžYØgYîЃ·pµ,ßjAËòÜ >ËS¿.$¡ªãøUJ Á@AÉÑh«ûЃӗm­¨éŒ‘%~–åî_°Ø“Ê·AêŒ"0T¼Zc¢©â«5‘<œreýY¦N§zi×öQ'¾˜dªZÚ© _¾”‹I¦ŽŒZn×îT;™X»zW0ŠŸíºÃ*’-Ôœ£Ë¿žp¦JhYÞ^‰µk„3U9d„3UV½Y¦˜ÊM¯Öð¥:3KKëÌ0Õ2ðvY—êÌÛÖ™b*«ÿ,Ë)oZú©4¼ç£eþ†õwøR¥¤µ,L2ÕRìoâí?²Äµ—¡ }7/ƒA¯L±,3Zø]~Ú3?C{Zû¥›qíw:OœÌ7e¥vèhì* ËÀ|S;o\ô4î9¡7V©Í„ˆmÐÕ8Ë/‹JÕŽœeÇí–¼&O›ä»–™ëÄwÍâ»ñ®à'ñ.È…wÎC–t×ÞnÄ»Lvx‡XëKâ]Ë8Æ»ÌW–x— ËïZŽ;Æ»–C¹ñ¢¤ž¯øN¹¶Ew-vÓ]íƒx·û0Þe:´Ä»j!ÞáÇã(ºÛ nºkNŽh¸‹ØxYwõÂ]µÈË>CLwáü¡6¤»k¯ºEwõ(ÒR¼¼»ö _xW-Ä;çKºËDp¢»ú7é®ZähŸ©w×F á]=šîêAr´ßMw‘{@†W÷5Iw»‰à+!M­w»SÂݧAëº|÷q¹ÐK6¹¦²ßiÀÛ½W&^Û},Oû¤È3Û}Ú¼¯n -ôµ¯çš?z¡«}±ï>zÛ_Í»¤;¼t!ÝÕS“î>ÝÝÕn‚î>†©,ÙoàÝNH¼ûôxW; ¼«:Û—^‰w°+IwÃÐÕç1tµßÝ’íꥡé÷ï¡‹÷Å’í>ÝÛÁâu!ÙîÓæº_Ý`¤L®Q„võTd»r½D»úíêÛ´û´¸Ý;¡§}1ôûûø vÕðß·GµlË'A°ûœ8¥Ã´Ø}-þú¼úØ•ìê'N°«wL²û´¹ºF—´ô¦ï3OÔ§nÁãáîÓ3íË D¼«7N¾ûô<Þï¹én_n›„W†^=õÖpÝ ¯žš€W_3Þç(VR©mä›\ú¡sr=êù>b^½I^ýTxå·#ßÕS“ïꉆjcäA¼zî¡âûL¼ò) Ç(ç¡Ã}ù"‡*dì߀|W»aVÖzžqüæ‰wõ &fÝÒ]¹!Â]ý¬w; ªá®^áîsŒ´î‹#Ü}Ú(Gë¾kÂ]½˜ÌÒš†÷ÇÃãþñ‘îJ¿wåÌ‚»Ý­Ø®<9±Æ;á´Ø®¤|­ù; íöÓÙ}š(eën¢”­Ûðöïë\WÏ;æwüÖ•ÁYXWž“°mD'ĺúXÈuå§×}ºéç÷Ø},÷4Àîsy¯gPß#ÉîsÌx¾¯‡Ð®<*¢]mB´+wI²«¿#É®ž dWïšdW¯—h÷é…¹[ˉèQ›(Ü´X^O¢ÿrʳÄ;¾l¾ÃþöcÈâ®Å™§ ¾Ãž¸aÈwQsÒÀÇúEœ ¾+Å3ÄwØñVf:â æ,âÝç à;XoŒ >3W|·+¿ð°+ž<:ßøÛYÈIx{ß\€‡N,»1ˆºïpˆñnGhï>mï`q~>â]=uÐÝç ÷Ôõçõ¾óÛIð]í$ð®h¤»rŒè®ô*ºû´ ¼ûXD]„ò¶ð³Mjñ]Ýä'ߡͬx÷éäuZ:ï·ïFKï}á,Þ2$ÞaSßèvÜR|½¤»rnÒŽÙjÞø¤;œGOŠp·ƒm wŸNXfk„»Ú +Ã9„p÷é—µaŠT@º+UY„wõ(à]yÒîÊI»kwªg”îùÑ>Ò]ËÐ^Kwûޤܵ'Á]Ê]=“*Äìƒ(ÜíÇ á.kÓP·k™7ÛÂ]¹?)wû wå¡H¸+WÂ]{¶¸Gá®Ü´„»Ú•»r’îÊ=J»+RRhwõojwåaJ¼+/ŒÄ»rn©wûQY¼Û· ñn? kwEc“vWúíççqZ»ÛÏÁÚÝî6¥;?Kwå IwÅ"énwCå®4±t—/«•»ýQ[¹Ûã•»|,î2´)…»=žX¹Û£‡•»ü,ÜeD°•»òè,Ý ¥»Ú1¥»åÕúrBº«S»+w-ín?;iw»d“Å»ò`¤ÞÕn¨Þ•g#ùnß·ä»rOÒïö–~WÞªÐïêµPÀ+g–‚Wƒ¼}f x­o¹Ž^S‚Ëweü–|·[P¼«'¦x×®-R¼«çùärMñ®Z”͵X”Ï5Ϭt®»WIwÕ¢Œ®yËÒîŠr.ínOH!Ý•óJºËóJ¸+3¬„;çPMÝ®6QZ×ÝD1¨åZ•×µœyzö´Eº]ù=¤Û9¬d»ò§ò»¦ƒ•U»òòHµ+—+Õ®¶¡j·o@¢]1P³«g¢fW¯Ÿ¢]>KivÙ %»æj~Vìö2ÄŠ]Þ ;'ñM½n»0X¯Ûo¤õºr"Êu¾0‹uûf,Öµ”†¤Õ•>Fû\•ºb P·‡…ºr©êÊy¥ÔÕ6”ꪅkßzµºý`%յ̹b©nY ”êj'ÔêꉨÕU źr"ju²WèE±n?9iu¥iuûYIªÛ7”ºr­RêäJÝa¥ÉJ];¿4W”ºòz‘æÐ†Âø?É„–7~:Ê×ü"¸]y‘W’w‹àJÊo!ÜvÔ2Â)dEø¶| ßêÄ·LÆøv¤‡n—w4À÷¾|åÁr±Yܑθr&\þ&8]½ðí(ʵ ½•k½é×`z«WB|+ÝÞj7 7_É­^Ñ-;0ºUSÓmƒ’_m¿ [ñ²¸•ƒÈmûÌä6^—™­4W9Ï|Âf6ðúívÈ$¯Õ#Èkõ:Ékå"lÕB`+G‰ØJÏAlõ›®M¸V{ ®},/_þEV+w#X«ç$¬Õ>kõ(ÂZi#X+mÖJ¿ö´,-äiYz‘§eñ¢”§¥…ïâhiƒü,³J]úYVËÔø ¹Y–ÉÏr»ÑÏrB\Û_´q­"^«òÚÇ2\x­\ŒxmŸ\¸V»!®ÕnˆkÕòöïßĵÒ-i­Þim7¬•^Dk ÓÖõÀHkµ i­œ)h­œ§{Þ™_X+Mkµ÷øyq„µj!¬U i­ô#Z+W¸VÛ×ö孕뮕 ×jâZmC\«mÈkµ y­^ y­\ q­Þq­vC\+§ \+Ç×j‹s~áZmB\«Ýôöã„kµÍýþx‹Äkµ y­žëõ”éËŸO¸Vz®},óÇÕ‰×Êó¯íóØj“kþhBb+W+b+w$b+=Ÿ§+^«}ŒëÇ #^«mæø’¶rµ¶Ò„À¶x­<–¶úw¿~ ‘B¶zåvÝç!²•«²ÕŽÇÏÏXÌVO¥¯ûTb¶}*![mr~_LA[mqµïû-f+×+f+W'f«mžö}¼‚¶z¦÷ýŽb¶Úd¶ïBlûüý~ÞcÛîÄÜVš(åkir½ß_ÀÜV-Êúš÷ht«mž÷;ĘÝê¹Fû\Ìð,joþ˜D o¥WÁÛÇ2¿×ðVûÑÊ·´é?fQÓ[ms?ß—œôVžƒèmß“à­6ßYÔðVî@ð¶›ÞÊ¥ÞöºÀôVÎøV.vã[¶H~ËSß×÷7ÁÕ~žó¨ οܿ1-aî 7øÂrÏöõ“·å®AGoËÛÑÞ–oßènYÛÐÝAâçoÓ™êäm¹³}ÚÛrgµ»eµ(žÎûýN— FÆÓ‹âéü·ãéÞGËe~SÚã²ZT4µ{\~,ógz\V =.«…—ËüþMŸËj¡Ï厴ÏåÇâ«V?äsYÛ4§XM‹ª„VËÐ=¤¥ÿø›^—ÕB¯Ëznz]î'j¯ËÚ†^—ÕB¯Ëe|Ÿ±½.KÏòº¬º]Ö£Ú·_¹]V Ý.«…n—ËûãúäwYÏM¿ËÚf8Íj¶Q†ãb¡çe±Èõ²Zàz¹ßuû^V }/«…ΗËÔ=¤…Ηý‡:W¾Mû^fÕZ»^=/ûÞç—çeµÌöãï©L©Ñóã©Âß”æ8ÓÛórŸYŽ—¥_9^ÖƒèxYÛÐó²¥®—ÕB×Ë^”¶·ÿ¦ëe=†¾—åò¦ þº‰|/K7r¾,—'ïËý ä|¹5Ûû²o¯ŸŸ#è{Yþ]YŽSQçåNmÏË%¼Fvi»^f”³=/w*j{^:Yµ/ûϘºßš~—™ÿÚn—Õn—åº]Ý.Ë!t»,-”Þx· ×e¿Tl-½.«…^—=7…íu¹ÓwÓër‚Ûí²ïPD¹]ö?,·Ëj¡ÛeµÐírg·Ûe&$·×å28¶M^—ÕB¯Ë…iË ªðº¬-èu¹O$§Ëj˜º8÷!§ËÒ‹œ.k:]~,óg:]fvû\ö*ŸËÒä™ß™Öqƒo¦„uÐë›9a³Mf…µE>—Λ.—;¼}.?Ρû ëù6 ÏeµÐç23ئÏeµÐç²Zèt¹ÓÜÛéòcºƒ´Ðër×P·ÛeµÐïòca¿f+º]½.‹N—ÕðþúTj·ÏeµÐç²Zètù±¸@@Â!½.«…^—ÛB¯ËÏßïÏt»\–/é}-œ>¨·ËØí²èvY S7ðõºÜ%ìvY-£ýø{êÚÒB¿Ëb‘ße?¶c#ý.?–©«K /«EËáb¡ãeVm°ße1Ðí²žþù“N—Õ0tùéJŸËj¡Ïe±Èéòcºü´Ðë²ZèuY-×ôº¬z]ö T·×eµÐíòcº‡´Ðí2{®¹Ö®Ù®o®œ[•v®5Y>¹Öþô¸’kMmþÍ\k½ÍQ÷l)ÙÍd*iƒÒR¥õÈÞ]:Š¿k70ÔNøwéâ>ˆcå~e)ÝÈT:JËz®µ~F Ä’líO3¡×€»ëŸgc[ àÇ[Sîü“j¿ÿù¯yò€ø<¾¯ž‡êŒ|Ò¬±¯HŠ9žÒ—-µ¯ÒJ}}Z¹¯ ©ßÚ—,Ÿ¾v+÷U[¹¯’‚L}Õdîk·r_ŸtfêkÆâ®tEç§lãŽv›¿üv\‘næ%);þ†èµìg.¯o¦¯ÿýÕ¿þ.ÛØv²¦³Ÿíî?<ÙïRýÁ»õ)Äþ õ÷ß 74$ýýßÜÃÔ¿¹¿ïë_H!ÖciR2ˆý 9Âþj°ÿbk‰ñ>ÿ YÀ:ëÂþ—Éö”ì?þÝ,`WTÆþ“aK¾0ȨÎDÜo¼æ})˦œ/DÚ¼ÛÕ|ýS÷™õ¯®ÉͧsØÓjŽ˜¹Q÷Òî=µ¬¶,ã4Þî=a·ð%^­ˆç¾hàÖÓZ%rUÓ‘SYñ(—ŽQÈïí3õ£kƒ´ØÛõ}änÕQ™ŠÞ#Ol Ì_–7øÉš÷5„¯’›«G‰Þ¿½oó³ëÇ ~§%úy0°ãðNC?Ï@à]/¦ŸÜzšY¨¬/,þ[Ô«»ù'Ý Ö7*쨬 ÿ«aJ^ph$¨CáN!~V' P¿,¡sÂî‹¡§Á›/ÄECçœÿš‘›ü·ŽˆÊº(¯ ÆÞŽÕçtBœÞÎ93 üRC㜙iYX~ah3¡·+’À÷&·¦ÞbÓ /´Ü1z»#|¦W[†©ûtÕí S“Øë™,Ž4çSÖQ>œ»{Y¢ô™ë5å’ "DÇýŠ-§õ±zG¾_'3Àc§BmNf€?ìuۯƬѨÇJÃu99¶Þ«+i´S9/ 3À¯;sÇ÷Ã\ÃzO¯‡ à×1zå®—I£×½ˆ–…)àoÓA¿†’Fwåeîk¬ø¥tÏ,¼Fu&~β,Ì¿.Š››kœaÒèÅW‡Žj—K3¿sïÓFgUée‰Ê¯ëa阮¢æk\Ñ™nÖR†÷Ú<¬¥|ºhë²DÞèøžÔæeø×†½5wb¥Þ'‹)Nª¾,L=s”¹SÆ`Î£îØƒŠª²CHG±5~ëo5ÇŽ k)¯¯MÓP'¾K Dwg-åy¦åfMs”£—åQ-å®A¼ß±§ê:ùËbÊØj‘e°˜òítýýž¬j¾îŸ;–ƒ”¢ýw¬ÈÚúúsFxìžëjžÆšæ3_“çb5剠!*1´,8Пià[V6è¬I´¾GÙ¹:Šá§:LY¿LÅÝŸ—µ”±šW'±õË/êá"#ˆ,QÒ{ùú¡XšèŒœ¢¼`Ô&BLz|%Xœ: Ç…HÚ£\Àº³>ѺÀGDØc[ÏÜ•’;*±…þd)e€®ºEëD] è;ÅÎÛÔ×Ë*EÐÃ~u"<–1SÇTüNú-£F+³»jPf¡"ˆ,*žÝ‘`³Ag±"ÈKþQ­›/˜õŠâL,mÑY°(Þý”HAÔùŽœ:*jžeyþ MÙØ;KÅû¨Ž•â›÷º˜e!uüâžîú˜™ôùu]öÎúEØrõ5Ïø»û&YÀˆ?·z ]úˆJÖ1Š×F“Ø a6έW‚•Œ°Áêym†0‹­E†,f„=L¿¢¬f„ À_:U³ØEöoÇ’FØEÎKžÑí¥QâfE#ìXªêÇ•Ep1ðŒ–%ª1@~:*„YlÔëaݬh–[GÒÇããÐw³¤QœK….‹mNÕç¸QÑ{¹*%pGÕi´xõܬhw}è‚C—Åf£’›N” âÌq³¢ö²Thá>~Îxµ-¡Ëb«Ó·p†.‹ý.•H¸YÒh ×/bZ½n»7j!7ñòÎe±`öM±®V¿ î3dÙu”K>Þ¬ltÆ ¬Ë YS°Æ„›¥NÔàñm†,›Ü;½YÛ«N&w U6ºáûx³¸VnT7Â<®¯åfy#,W4Ü,otÆ4©^bmŒ—E¥?n–7Â'ëo¡Êž˜àª,Újr·Pe±XòëÇòFXÙåÙC•ÅšÓŽð]ÿê<×…¬W8“(ëЫª,ú÷kÍúFõú®Peq¿š2o8Âx›G…,÷©·˜ŽÖìüú‡a£út®XÇs¡z³ÄÖ ~×r£…GotÜx‹yW=„Yì]ê“Òæº,ñó‚ýCæSpÉf>odoèsb5BŸ§çÂ|Þ®5óe0ƒ¡Cú% ¡ïtÆM3ß9¬º›ùb{O2ß²vÌ|‡ECC_;}-çÑ`>|÷êƒÈ‡ñî5òíäaF>$ëÒÚFȇT>j8׌ñḢ¹_s¼˜ÛíÃ|˜)ŸóAÊx^r7°ÀÈ™«ù= vAx4-ô4Xom2`ÖrbñEUE“cßû&ÍøPÖèKà‹²®ÆÄ€¾(z:*ô!¸Ekæ`¾ã²ìhè;fb®¨Kú&üjS‘žÊX'싨c½M¡Àmu;•¨|B~p’‹…È/d@á#\ËŸ|A~0Hüø{})Á}c8ƒš°\;ÍxáØŠuµ~R,Ãõ¡¸Ÿbô½´öáK–Þ*ì›;Z4°¯Ô¶öáCÖ÷(ìCíº[cvü&ôMTAÒûMèíêi“ùðißÂ¥@¾92d)‘ÓŠ`MÈ-W víJA†@U»Ò(äCU%-¹„|GT…¦…Èw|êẎ5õcæS‘¡Í|W"²™@Ì;'óÁ×N°F惼(°óá×ן̇q…1ßërv }X†òÜú„ç‚>ŒZT úFñ% kQ«¨D"õaâ3™ú^ïë˜ú®Ãhê»r ÄÔ×ói‰ú°JÒoeêƒg‹,¤¾†”¾â@RŽÒ÷Ô×@ç¯þìÃcÈ#öµ' ^Ø×zn(ûp”ž…¹o8mtrß} &„}W®Xû^GPû°$:‹Â>\ŽŽºt"ÍÆ>¬ßu&a*»Ò@êÀ§)ÀÔw»x|R_|Ø4¼|ÀÃËÔ7“èD}ðÓõšú¦–dž>,ðu5ÌùÛôÁ™M È|×yÚ@äâLï½U75¾ ù®óÎóù.¬Ü„…D>Ì×ù.ÌææÃQúµÅ|p¤…ù@(ZÞ‹ù®Ë» f¾+ÇÌ|×ÓÍjD¾ ¹¤¹‚òú¨"_GâEäÃ|á£È|½©î$‘ÏW’ø®¬3nâ‹*Ž¢Bæ¥Sç!ñu|‰b7ßšî´çhâ‹YG¨Fâëpäâ¹D|¨[ Fâ/Öˆ|( ÚÕsbuA!‘?µ’òS©_"_¿]ÔÈ×1b«#ŸwŒ|kü‰|øðDoB>lÉ"æ‹Ùá·|wsJr!V9B5!JéÉbä;²["_Üæù°Zÿ|M{EF>L·ÃŒ|¨ZڿȇZä»›ÜùnüäùPõ. ùVCÝU"_ó‹cäëGB–‘oI…|wOòaJÖcäÃò\G ùà´óA>LÛÚ¨òÝÇ>eUõüù’ñ…|7^l¾Æb>ÜÃMÿ¯ç Kìá~W°‘ñÊm î»\åר‡õ'ãïƒú²2ybßv¤3öa_ùø`_Ï€QßÜŒ}}¯Vt3¾RÆJ[È}Ï–Ä}k çæ¾5z&Püð&š%ömNä÷<[ $ù…ÃGì&õù¡<°û!ù¡.òû!?¼CÆ-’ßs¦rGð{·®(ð…ã@~#Ÿ°Ù/™Eb¿‘Á-f¿1¶¶GöC1f= ±ßt68£ßœùÌÅ~X-i>“؇OO˜ì‡.›Ô8òw!ü¥CrÂßåMb²_Ô±Ñ0Ù/R )²jê|$?Ü€™2ÈަþáH~¸ëTƒü ¯¯€~øÛ¿ÙOs~D?<ñdU:c­wý=+ýÁÒ+ýᇓƒ±èˤ?°µ0ˆðWê% þ^ü:¦³ Ó`Á~øÛGö ŸÜ§²_ýRHèöq/ô4¯m‚þ¢Þ“ЉaŨa¤—žø‹·Dˆ¥SuÛÄ¿¹Ãâ…hãÍàßÀ†±ŒqÅ#3_ÿÆëê³¢?Tñõ‡AúêÒ?-é¾½Ùñ` ‰,*!ú`Sé/"­îJ¨â±çV—,Àô7®ýônÕp¹òHc§Bý!ì«%N§ëÒÒúV¨ËðBøÃ®ˆ7”(´ãÁˆðyá„¿ÈÚh¹1à/Љ¿ŽÆJÒ׎©3D?|Øþ%‰~pÛöÆÑ/RmèHôKÚè÷¸4M¢ß•¹ÑñƒBHê}‡IÀ‚j ¿ãò”nôCp–~\¢4~•úÍQ±E“åÀ-ì‹¥½9Siøàú0çzŠÐ¨°› oAGö̇âð‰ƒùæÑò "óáãò»@æC`žz2ß™’IÌ7Þ¬€#苈?+pŒ,ÆZFàÌ.ïb3F¯_H >ÎñEÕŒ |#\d*ñ¡‹ý H|(¬âm5œPü•ù®+ÙLÈwåš"…¾7D#_Ë}1âÁt×Á|gWév#|´_[Xðy=_ÍK‚>¬Œ]„>¸ËAЇÕÈЩ }ðp×@Oè›3÷UÈ|¨²í'AæÃî›§2ߌÅúf>TøÖv¨˜o"TTȇµž÷ ùæµµÁ@>af/|ÔÔï$äîäeÀ äÃ3ÆÂ@>¼¯ÏF>øìœ:êÌîE‰/Þ^*ÓꌌÜòE0ê´¤»¨ïp9!¦‚[MH|àKM¤ñÝ›I|mšP|Øø0ÎõØkºË|ð”—¼‡Å•É’¼w6—3ïaCïùð0…Xâ=ÿàÞ‘•){QÁžÒ^ÄH|p+å´ŒxÇ^´‡wì¤ìa³V¿Y1ixcôëɇAzØY~MƒAzÇÕ¦A»’<zx 5Æ ôð} cS€Þ„”§6½¹3w ôf&çÍ3W÷â¼¹Wšâ£n’X·º1@ ë`¹?\wÜ,öù¯¤+ˆwþpÚL¿Èd¼B^d¼fb"âá÷û8m^»¢®ïjï3R¯ïp?Eêí:¶"¼]“Í„þI_ÂÛ+¬#³Dy_xž×¬B¼Çû$¼wÏÓB¼½dÈ›Íë1Þxsbã­±ø‡Ûæ¼÷µñFVŠÍP½,….Èr5#à!Hå1!ðSœ8¶xón¦÷?„;T+×Â^Qzc/g¥‡\qEFé½÷–é‚ð0áZz$áa ‘¢œ¢ôr|âEp›5Â@¼¹ *âa&µ²@¼ù¶\­ñ"¦ÊÁ{ác‚n[¥¼Ó­`½ùä+XïÞļp‘[Âõîs;‘"\Y7|&Æë5¼2óÂÍä\ÏFžhŽ×öBëÅ>Ÿüo¯7vè]°^ Vǯ—Q°ß-- ØCn3ÅË(`¯m/¨ØÃÔfQìe “öZ··€öÎ벟£ö°èªê]øòÝ ˆsÀÞ“áy ØCžÓ½7á:õ(Þ›§.F®›ëLÚuT´ÞÞ!·ë&÷Õ…\7¯Œ„‘ë&@ìýDë]ëÎ {gÛÑPrݼ0ô™íÂÉéCÜ3]71›h9*×M<òQiïŒÕƒéî€?ÛñÃu“ƒe8ºnb*mU¼£À wJºn"D¯¬\7!TŒÊ{á,© ¹nbvõõÑu~Ez!åºyµTŠåºÙ[†ëæu©—)\ïL'Q‡ëÍÔ.äºÙï!Ûu9rôQI¿{Ú‘atÔïði -ý®cú¨ßÁïÉü ý.ÂZô·\7áN" ¥~‡ïè«ßµ˜hˆïð¹¹#ÏM¼?&µ3Ó`Œ¯çæš¿ñzÝÐ^”<7±B09Ês¯ wd—ÈEŽ›èD¿œ7ÑÉU‰/<ãîJ|‘—$e=:n>9pÈqOBÖöæiÀ ÏÍs;cËsó~ZªvôÜD^¹¢ãȵç˜9znâÓ²8HÏÍëM}S®›‘>H×Í Ÿ(Ÿ\7ìÉÌ̺*óñb*óůy:n£ŠÖ;¯®›÷ñdºn>`+™£õòÝ öCZEù §ë¦?(³_?7Êuó°k¾Ù÷à˜:±ß¹ÏMö{à~jÒ£¤—%½v´Þkß\±_\¡HO®›g·VËh½Ó‘xé¹ùh×è×sšMÏÍCÅòþþßþÏÿöÿÞ‚> /Contents 5 0 R >> endobj 3 0 obj << /Type /Pages /Kids [ 4 0 R ] /Count 1 >> endobj 1 0 obj <> endobj 7 0 obj <>endobj 9 0 obj <> endobj 10 0 obj <> endobj 8 0 obj <> endobj 11 0 obj <>stream 2020-03-05T16:36:38-06:00 2020-03-05T16:36:38-06:00 GL2PS 1.4.0, (C) 1999-2017 C. Geuzaine gl2ps_renderer figureOctave endstream endobj 2 0 obj <>endobj xref 0 12 0000000000 65535 f 0000165637 00000 n 0000167387 00000 n 0000165578 00000 n 0000165427 00000 n 0000000015 00000 n 0000165405 00000 n 0000165702 00000 n 0000165802 00000 n 0000165743 00000 n 0000165772 00000 n 0000165866 00000 n trailer << /Size 12 /Root 1 0 R /Info 2 0 R /ID [<7A35A1FFF093A2D78938623B570DB003><7A35A1FFF093A2D78938623B570DB003>] >> startxref 167607 %%EOF blis-0.9.0/docs/graphs/sup/dgemm_ccc_zen_nt32.png000066400000000000000000005507611422157504600216510ustar00rootroot00000000000000‰PNG  IHDRTjûF¦Â &iCCPiccH‰••gP“YÇïó<é…@B‡PC‘*%€”Z(Ò«¨@èPElˆ¸+Šˆ4EE\•"kE ‹‚tƒ,ʺqQAYpß÷?¼ÿ™{ÏoþsæÞsÏùp ˆƒeÁË{bRºÀÛÉŽÌß(ŒŸ–ÂñôtßÕ»­Ä{ºßÏù®‘iü常¼rù)‚t ìeÖÌJOYá£ËLÿÂgWX°\à2ßXáèyìKο,ú’ãëÍ]~ )úÿ†ÿsïŠT8‚ôبÈl¦OrTzV˜ ’™¶Ò —Ëô$GÅ&D~Sðÿ•ü¥Gf§¯DnrÊ&AltL:ó5204_gñÆëK!FÿÏgE_½äzØs û¾zá•tî@úÑWOm¹¯”|:îð3™ÿz¨• €è@(U  t0–À8à|AØø $ȹ`(E`8ª@-hM œà<¸®ƒÛà.L‚—@Þ‚°¢A2¤é@F²† 7È ‚B¡h( Ê€r¡PT UAuPô tºÝ„¡‡Ð84ý }„˜ÓaXÖ‡Ù0v…}áõp4œ çÀùð^¸®‡OÂðø6< á—ð"Â@”]„p$‰BÈV¤)Gê‘V¤éCî!Bdù€Â h(&Je‰rFù¡ø¨TÔVT1ª uÕêEÝC£D¨Ïh2Z­ƒ¶@óÐèhtº]ŽnD·£¯¡‡Ñ“èw †aaÌ0Θ Lf3¦sÓ†¹ŒÄL`æ°X¬ Vk…õÀ†aÓ±ØJìIì%ìvûGÄ)áŒpޏ`\.WŽkÆ]Ä á¦p xq¼:ÞïÀo—àðÝø;øIüA‚À"X| q„„ B+áaŒð†H$ª͉^ÄXâvbññqœøD%i“¸¤Ri/é8é2é!é ™LÖ Û’ƒÉéä½ä&òUòSò{1š˜žO,Bl›XµX‡ØØ+ ž¢NáP6Pr(å”3”;”Yq¼¸†8WJ)Hq¤"¥öHµJ IÍKËIÛJGJJ·IK”aÊ8ÈÄËì—é”y"‹’Õ–õ’Í’="{MvVŽ.g)Ç—+”;-÷H–×–÷–ß,L¾_~NAQÁI!E¡RáªÂ¬"CÑV1N±Lñ¢âŒMÉZ)V©Lé’Ò ¦$“ÃL`V0{™"eyegå å:åå–ŠŸJžJ›ÊU‚*[5JµLµGU¤¦¤æ®–«Ö¢öH¯ÎVQ?¤Þ§>¯ÁÒÐØ­Ñ©1Í’fñX9¬Ö˜&YÓF3U³^ó¾F‹­¯uXë®6¬m¢£]­}GÖ1Õ‰Õ9¬3¸ ½Ê|UÒªúU£º$]Žn¦n‹î¸CÏM/O¯Sš~°þ~ý>ýÏ&   ©†.†y†Ý†iñªî¯&¯v\½mu×êׯ:Æ‘ÆGŒ˜ÐLÜMv›ô˜|253˜¶šÎ˜©™…šÕ˜²élOv1û†9ÚÜÎ|›ùyó¦é§-þ²ÔµŒ·l¶œ^ÃZ¹¦aÍ„•ŠU˜U•Кij}ÔZh£lfSoóÌVÕ6¶ÑvУʼnãœä¼²3°صÛÍs-¸[¸—í{'ûBûªƒŸC•ÃSGÇhÇG‘“‰Óf§ËÎhgWçýΣ<Ÿ×Ĺ˜¹lqéu%¹ú¸V¹>sÓv¸u»Ãî.îÜÇÖª¯MZÛé—ˆÿ2Â6¢,b&Ò*²4r*Ê*ª4j:Ú*ú@ôLŒMLyÌl,7¶*öuœs\mÜ|¼Güñø¥„€„¶D\bhâ¹$jR|Ro²brvò`ŠNJAŠ0Õ"õ`ªHà*hLƒÒÖ§u¥Ó—?Åþ ÍŒ]ã™Ö™Õ™ï³ü³ÎdKd'e÷oÒÞ´gÓTŽcÎO›Q›ù›{r•swäŽoál©Û m ßÚ³Mu[þ¶ÉíNÛOì ìˆßñ[žA^iÞÛ;»óò·çOìrÚÕR V (Ým¹»öÔ±? ìY½§rÏçˆÂ[EEåE‹Åüâ[?þXñãÒÞ¨½%¦%Göaö%íÙo³ÿD©DiNéÄ÷e̲²·7¼Yn\^{ˆp(ã°Â­¢«R­r_åbULÕpµ]u[|ÍžšùÇ‡ŽØi­U¨-ªýx4öèƒ:§ºŽzúòc˜c™Çž7ø7ôýÄþ©©Q¶±¨ñÓñ¤ãÂÞ'z›Ìšššå›KZà–Œ–™“!'ïþlÿsW«nk]£­è8•qêÅ/¡¿Œœv=Ýs†}¦õ¬úÙšvZ{aÔ±©CÔÓ)ì ê<çr®§Û²»ýW½_ŸW>_}AòBÉEÂÅü‹K—r.Í]N¹<{%úÊDÏÆžÇW¯Þïõê¸æzíÆuÇëWû8}—nXÝ8Óâæ¹[ì[·Mowô›ô·ÿfò[û€é@dz;]wÍïv®¼8d3tåžý½ë÷y÷o¯ñy02*|ñ`úaÂÃ×2-<Þ>†+|"þ¤ü©üÓúßµ~oš /ŒÛ÷?óyöx‚?ñò´?'󟓟—O)M5MMŸŸqœ¹ûb݋ɗ)/f þ”ø³æ•櫳ÙþÕ/ M¾¼^ú»øÌ›ãoßöÌyÎ=}—øna¾ð½ÌûØú>|œZÈZÄ.V|ÒúÔýÙõóØRâÒÒ?B,¾“sMT cHRMz&€„ú€èu0ê`:˜pœºQ<bKGDÿÿÿ ½§“ oFFsF×j`` pHYsNNÆÊ/¥tIMEä&>(Ê vpAg´¨“ÁQè€IDATxÚìÝ{|g}/þ IìØ‘³³«ÝÕ®´«]IŸ÷ëå—¥ÝËŽöÙ™y¾Ïóý®š™™™Uõ²vïQ§c@…ˆˆˆˆˆˆˆˆˆˆˆh ¨Í"""""""""""¢90 BDDDDDDDDDDD4TˆˆˆˆˆˆˆˆˆˆˆˆæÀ€ ÑVD@Ų,8ŽÓîÝ :ø¾ÇqàºnSÖçy,Ëj÷Û¢Ø>—?Ïófµk¶ÍÎÄö¸2ÕÛ}߇çy—w§âsÔl«ËßBÎl«íÅö¹4´ã¾³ZÛ˳}..¶Õ¥c¾í•÷¡KÛæÊ´ÔÚæŠ¨Ø¶ÍƸ¸®‹¾¾>˜¦‰D"d2¹àuzžÛ¶ÛýÖ¨¶ÏåÍ0 Îj×l›‰íqeª·=š¦9ë"ײ¬°.©‹à¥Œmuy[蹓mµ½Ø>;_»î;+µM€í³]ØV—†ù¶WÞ‡.]l›+ÓRk›+" BKC"‘@*•B6›Åøø8ÇYR‰ˆJyžÓ41>>¶k˲š6ˆ‡eYH$0MsÖs†a`ll ÙlÙlÉd’£k‰`!çN¶U¢ú,ö}g­¶ °}Õ2ŸöÊûP"jµeP±m}}}Xµj’É$|ß/y^D¸{zz` Ã(ùbu]‰D«V­Âàà`øeÇaYzzzÐÓÓ˲`zzzÐ××WAmäµµˆõD÷·žçjq]ƒƒƒXµj‰DøÞ«=>×sõìÿ\ÇÁqø¾T*$ “““Ð4­æ{u]7üŠuÖÑý{7²5ÏBÚgµ¶ °}¶²}ÎÕ^ª½Wñ·•$)ü_–åYs Ø6ëÙ5ÏJhóm‹â=vR{¬§m4ã|m ( t]‡¢(%¯s’$AUÕðuŠ¢pDY ¬„¶:×sµtZ[ë_Ìs'À¶Ú.µÚç|ï;ú?kÍj›Ñu5ë\:Ÿ6ØîûÎjïw¾÷@õ¶)ö‡ísq°Ÿ¨¶N<—ηŸˆ÷¡KK+Σ˽]Öz®Ý׸ÕÞï²ë¿Yf&''g̤Óé™™™™™T*5`&•JÍÌÌÌÌ>|xF’¤™±±±™Ã‡Ïèº>`&›Í–|xf|||F’¤p_k=Wëøˆ÷/öE–åª×Z¦Þý¯ç8d2™UUÃÿ5M+y/ÕÞk6›-yNü½Ä²Ùl6܆®ë3Š¢„¯«µµÆBÚg­¶93ÓX›cûlì8ÌÕ^j½W]×g4M›Éd23𦕬³RÛ¬g{Ô+¥=Χ-ŠãÓií±ž¶1Ÿóe­ö¥ªj¸b?Ëÿ>寡…[)mu®çjŸNk«âX/æ¹3ŠmuñÔjŸ ¹ïœ™©ÿ³Ö¬¶)ÖÕ¬sé|Ú`'ÜwV;¦iÎë¾3ªR»cû\ì'ZšçÒùöÍÌð>t©hÕyt9·ËZÏuÂ5nµ÷;ßóh§¶ËePI¥R3º®—<&Ërɇ"Ú>\Ò 3™ÌŒ¢(%Ëëº6jAüA£¿—7Èz_[ €’ 1Ñ¡2×sÕ¤ÓéMÓf³j×Z¦Þý¯ç8ˆã+Nâ÷è E¥÷*Rù¾‰Ï€Ø†®ë3’$•œ(k-G­±öY«mÎÌ4ÖæØ>;sµ—ZïUœÀÅÿsµÍz¶GͱRÚã|Ú¢xÿÖëió9_ÖjQå<•n0¢ŸjŽ•ÒVçz®šNl«âçÅÚqßY Ûçâ`?Qã:á\:ßöÊûÐ¥ƒçÑÆtÂy˜;YNý·Ë. "Ë2,Ë ®ëº%.MÓJ>LåÅ…4Mƒëºa$Ì÷}ôõõ•\ÊTU-9>Žã ‘Hà·û·+>.¾ ª=×,âB2zÜmÛ®ëBÒó¼ðï(–Eý€â 7•JA–åpTÂ\ËQó-¤}.÷¶ tnûæ×^D»û&–‹f·ÍùnÃöX[§¶Ç…´ZËÖjµŽ‘ïû% =Ï+)ìK ǶZ[§¶U`ñϵŽÛjkÔjŸ¼ïTnƒµÚm³´ã¾s®ãÄöÙzì'ª­SÏ¥óm¯¼]:x­®SÏ£ÀüÛÉrê¿}y[·Þº®Ãu]ôõõ…_¢Ñ‹EQ i!Ëò¬¨–,ËH¥RˆÇãáòªª.› ñ^Äñq]étºêãµ–i&I’N§188UUÃã®ëúœËʲŒd2 Y–Ñ©TªâkÅ66nÜØÐrÔ iŸË½mÛ>ÆÚ™ .€¢oEQJ¥f] ‰¶)þžlŸ­ÇöX[§¶Ç…´jËÖjsK§ÓH$%ï·Ùì+ÛjmÚVÅ=w²­¶G­öÉûÎÆÛàr¼ïdûì ì'ª­SÏ¥óm¯¼]:x­®SÏ£ÀüÛÉrê¿]U(³ì¸®æÛ‹^Œø¾Nò}ªªbÕªU8|øð¬œÓžçA’¤º¦‡.5âøÈ²\ݯöø\Ï5K£ÇÝq˜¦‰l6 ÇqZ¾5ÇBÚçro›ÑãÓ)ís¡íe±Ú5ÍÛc}ǧÚãBÚF+Û•ø´òú€ØVë=>ÐVÅ?w6²N¶Õæ«Ô>yßYzliƒËé¾³Ñýaûl-öÕw|:å\*Ì÷¸wZ;§êxûØtÊyt±ûa;µ].Û€J5žçappcccP¦iÂu]d³Ù¶ìK­‚Iªª64…©Ùëë”mÕmX‹±µV§´ÏV|¾—rû\ìöÂöÙØ;¯=.¤m°]-_ÒVžðÚ6À6G˹m¶j°­jئ—·åÜ^WZ[]¶óÎÂvÙ¼¶Ò ÷¤Ë­ÿvÙ¥üš‹,ËÈd2a6Y–166Ö–}yïjík;××)Ûšk?æ™ì”ˆ&•ê”öÙŠÏ÷RnŸ‹Ý^Ø>;ÛcçíÿBÚÛÕòÕ)màµmùúØæV¶åÜ6[µÎNØV­}`›^¾–s{]imu¡ûÏvÞ9Ø.;sÿ»¶SÛ力¡BDDDDDDDDDDDÔ¨—µ{ˆˆˆˆˆˆˆˆˆˆˆˆ:*DDDDDDDDDDDDs`@…ˆˆˆˆ¨Å&&&0==ÝîÝ ¢ Ø>‰:Û'uTˆˆˆˆˆZ(ŸÏã†nÀ¾}ûÚ½+DT†í“¨s±}Q'b@…ˆˆˆˆ¨…vîÜÙî] ¢*Ø>‰:Û'u¢—·{ˆˆˆˆˆ–«‘‘ô÷÷·{7ˆ¨¶O¢ÎÅöIDDjÉT.»ì2¼öµ¯m÷n,Ø‘#G°zõj¬^½ºÝ»²`‡™gžÙîÝX´÷±ÿ~lÛ¶ ïxÇ;Ú½ËåCúî¾ûn\pÁíÞ•[.Ÿé•ø=311ûݻÛq®ºê*\rÉ%íÞ;~ü8Ž?Žõë×·{Wl¹|ÏÔû7™ššBOO>ó™Ï´{—[jbb{÷îÅ­·ÞŠí۷׵̫_ýj¬^½zÉw"­ÄsN§«ço211ãÇãÏÿüÏ—ýµm£íó_ÿõ_ñ‰O|§Ÿ~:6nÜØîÝ_•ô™^*æú›<ýôÓØ¿?Ž?Žþð‡íÞÝ–k´}^uÕU˜™™Áé§Ÿ¾¤?Û¼¶í<õüM:„ƒâ‚ .À-·ÜÒî]î8W^yeG_×vú¹d)|/tz{oE¿í’¨œtÒIسgO»wcÁFFF‹Å‹ÅÚ½+ 6<<¼,þ&õ¾‘‘‘%SÕ ²,ãÑG]QŸ…N·¿g†‡‡Û½«ifffY|¦s¹r¹vìØÑî]Y°åò=SïßD¼n9›žžÆöíÛqÓM7¡«««îåEYŸ…•xÎétõþMVµí|ÚçÆqýõ×óœÓAVâ÷ÌJ¸¶Oû¼ä’K–Ågš×¶‡×¶ ×ßßßÑŸ…N?—,…ï…Noï­¸¶]ò•år±?44„îîîvïFStr#_‰ï£]6mÚ„‹/¾¸Ý»ÑËå³Àï–˹s``½½½íÞ¦X.Ÿéåô7Y(˲Ðßß©©)är9LMMabbÝÝÝ=J¯YxÎé<Ëéo²P+½}ò3Ýy–ËߤVrû\N×QËå3½œþ&TY§ŸK–Âgp¹´÷F,ù€ÊºuëÚ½ MÑé£Ëå"g¹¼v9å”Spê©§¶{7šb¹|ø=CÂr9wvuu54ò¿“-—Ïôrú›4Ãôô4vïÞ Èçó¸óÎ;155µlþÞµðœÓy–ÓߤVrû\.ïq9}¦—ËߤYVjû\N×QËåoµœþ&TY§ŸK–Âgp¹´÷F,ù€ Q§)©5<<ŒmÛ¶ul:¢•„퓨s±}Q§{Y»w€ˆˆˆˆˆˆˆˆˆˆˆ¨Óq† Q‹ur¡F¢•Ží“¨s±}Q§á """""""""""¢90 BDDDDDDDDDDD4TˆˆˆˆˆˆˆˆˆˆˆˆæÀ€ ÑX”žˆˆˆˆˆˆˆˆˆêbFÉï²,CÓ4H’>¯ë:dY®¸¼eYeªª\×…mÛI’ ëz¸."¢NÃ*DDDDDDDDDTÓ4á8\ׅ뺰, }}}ð\.‡\.Wõ¹|>ßîcC´âÔj›ÑçÙ>‰Û'u"ß÷ç•BK–e¸®;«H¼ã8×eFhQUš¦…ÁI’Â}‚ú)Ñ€Š˜ñ3ß}]IØoKTÛ¢ÏPÁèè(ÏçÑÕÕ…›o¾]]]ÅÈȰoß>ìØ±CCCí>FD+B­¶ €í“¨Ø>‰ˆˆˆˆ¨“”Ï uOj=_>“D–ed2†˲ IR©TE×u bpp0LÛ%¶©( EÁàà`˜L¤ú’eÉd²,Ãó¼p ÍÆ~[¢¹-j@%ŸÏc÷îݸõÖ[Ñßß øBŶmÛ022‚›nº ±X غu+b±z{{Û}œˆ–µ¹Ú&¶O¢6aû$""""¢N233³ ç£]סëz8ƒD’¤ªµ[dYÆáÇÃ×*ŠÎL€ñññð91ÅqȲŒl6 Çqj®¥c¿-Q}5åW>ŸG, %lÞ¼SSSÈårèîîF,ô÷÷£¿¿¿jj"jžZmÛ'Q±}Ñr'êÆÔì¯SÊŸ«¶ƒ)ձߖ¨>‹P‰ÅbسgOøûôô4öîÝ‹ÞÞ^LLLÌŠhvwwÏ™“ïСCYÌ·AÁ}÷Ý×îÝX°ZmÀ¼Ûç}÷݇ÑÑÑv¿=ZòùE@…¨z{{qÉ%—,‹dDDDDDË ûmi9éïïoI@eÞ3T¦§§‘Ëå011ÑÐr7Üpz{{á8NIƒêïïŸ5ýkjjŠ£g‰Iµ¶ °}µÛ'µûm‰æ6¯*###á¨ßX,†mÛ¶açθ馛jF&GGG1==Í›7—ŒêïííE, ‹Åb1LLL ŸÏcË–-í>FDË^­¶ÉöIÔ^lŸDDDDDÔI Ã(ù]–ehš‰7 º®C–åŠË[–Y–Ãâñ®ë¶mAÍ]×+œ§Öb¿-Q}¨ìÝ»£££a‘¢Ý»w‡ùôn¸á|ík_CWWWÅeóù<òù<†‡‡Kß¶mvìØ;v`ûöíÀ¾}û°cÇŽªë"¢æ™«m`û$j¶O"""""ê$¦iBQ”0èá8 ÃÀøø8dY†išPUµj@Ŷm(ŠUUaš&LÓ„®ëáºLÓ ×E‹‡ý¶Dõi8 ’Ëå0444«vĶmÛpçwbß¾}Usã‰ÆWXo>ŸGÞQëÍÕ6¶O¢vaû$""""¢N“N§Ã&ÇaYVÃà Ã@6›-YW2™„išÈd2í~›+ ûm‰ê3ï*­"¦‘±Qu¶O¢ÎÅöIDDDDDíÒÌÙ$©T*œ±RÎu] bÕªUH$p]·âsƒƒƒa1ìéëëCOOO˜²Ì0 X–.ïû>âñ8|ßo÷áìX¼ï$šÇ •X,†øÃ³r䎎"ŸÏc`` Ýˆˆˆ¨#LLL`jj ÝÝÝ5k Ñâcû$ê\+½}:ŽÏó ª*,Ë‚®ë³þw²,Ãó<nÖ2ŽãT j( d8ŽÇqÍf~¯º®#‘H@Ó4(ŠMÓªg<ÏC<G&“¦i0 ‰D“““a0$•Ja||¦i"™LBQ”ð}‡ëPU’$…ïR‘ù¾Ïú-DTSÕ͛7cß¾}غu+z{{155UU155ÅÜyDDDDD;wîD.—Coo/òù•Jf¹D‹Ý§Óéð}‰õêºÃ0àydYž3ˆDDÌ# 2::¡ÏårᬔX,Æ` ‚‘µwÞy'¾öµ¯¡«« ù|ªªbhhhEŽ´%ê$lŸD‹í3¡!j‹”ÿ_+àÑŒeæ ¨”×P±, ñx‡nøýjšI<ÏC2™ gžDù¾?köŠªø¾_²?â8Š O¥Y'’$AÓ4ضÎÊaÝ"šKÕ|>ÑÑQÜzë­j÷þuœ|>¡¡¡pÀ‘È3=55Õî]#ZñØ>‰:ÛçÒ ^ÔËq†ñññ’õ¤R)Äãñº×!‚?"•™POú.‘î ;L÷EDsi¸(½®ëÀÈÈr¹Ü¬DDDDD+ÝæÍ›±cÇLOO#—ËaddýýýˆÅb5—Û¿?†‡‡Û½û´B ãŽ;îh÷n´Ü|ÛçwÜ‘‘‘vï>­@ÆþýûÛ½+-7ŸöyèÐ! ctt´Ý»¿bù¾¦ãj„,Ëp]·¤0<I*­K?DàÆq$‰p¦‰¨=ÓÈ>iš¦³d1::Š‘‘<õÔS‹z̉¨}ž¡bYVx’Ú½{÷¬çzè¡v¿'""""¢ŽÏç±{÷näóylÞ¼yÎ×oܸ{öìi÷nÓ µgÏž0h´}^wÝuرcG»w›V þþ~ìÙ³gEÜiŸgžy&ÏmP>ƒDÔ=©õ|yÑzY–‘Éd`,Ë‚$Ia@dlllÖ6Eý”¾¾>(Š×uÃm*Š]×188>§iÚœŒq]·á€ ¡··—ƒÌ‰V†*;vìàE$QD'Øôô4¶nÝŠÞÞ^¦Í%êlŸD‹í³³ÍÌÌ,èùh`E×õ°~ €°p|5™Lº®‡õT¢5UÒé4t]‹Ì‹çÊ÷§<°S)xCDTMÕ¨‰‰ LMM¡»»{E#""""ªettÓÓÓØ¶m «« ýýýÈçóíÞ5¢퓨s±}®\Ì©p)²5[Ã5T€àwÅW`ëÖ­ÆÖ­[¡ª*&&&Úý~ˆˆˆˆˆ:‚è€ééiLLL„Åu‰¨½Ø>‰:Û'u²†g¨ˆ¢`;vìÀ–-[ÐÕÕæ¶¼á†pÿý÷·û=µÕÐÐöîݦ)Ù·o¶lÙÂt%D€í“¨s±}Q§k8 ²wï^ •œÌz{{±k×.är9är9Äb±v¿/""""¢¶Ú³gO˜"···—£k‰:Û'Qçbûì|–e…Åã£dY†ªª°,«¤@=ÑrÒp@ejj ]]]Ÿ«ö8ÑJÄ:ƒD‹í“¨s±}v6Û¶áû>$Išõœçy0M“"Z¶¨Äb1ìÞ½[¶l)9ÁŽŽ"ŸÏc`` ÝˆˆˆˆˆˆˆˆZ$NW-$?33ÓîÝ#"j™†‹Ò !‹aëÖ­aQzUUú*œ¥BDDDDDDDD´ò¸®‹x<>ë±¾¾>ôôôÀ0 †×uÃç‰V­Z…ÁÁAض.ÇaYVɲDDíÖð صk†††Ëå055…Í›7‡ꉈˆˆˆˆˆˆˆhù‘(Y–áû>Ç ó}ñx™LªªÂ0 X–UUÃçR©ÆÆÆà8‰E,Ëp²,c||žç!CUÕª3cˆˆÊýò—¿ÄÑ£G›ºÎyT€ Ÿ%sZ5‘À.{, @LüHžÆ4rd¹4€ò ¯°\ùëË·£ÖQ…mÛ%Ð4 ²,—¾Ë‚¢(Ð4-Ø­t–e…ëe©T  ª*4M+)jŸN§!IE¢(mþÃQ§ß1Õ¾¾ò•¯4ý»c^•\.‡½{÷b×®]ŠõSt]ç,""""""""¢ùÒ ÿÊe#?+5–­ôzÔñú–«VC¥<Èâû~Igf´½çyp]«V­*YFXÊ_ODñ<Žã@×õ…¯l‘÷;œu]7ü1M³$x+f²UZÎ÷};v çœsNS÷¯á*.y¬··¹\7ÜpÃâU"""""""""êxžçU|\’$¨ªŠ™™™’bv -L"‘g„ÍÅqø¾¿(ûU)e àû>úúúàû~øÝ‘L&áyLÓ„išðŸGooï¬Ç»ººJ÷%ÞðŽ;ÂÇFFF°wïÞ’×íÙ³±X¬éoœˆ*«Ô6¶O¢NÀöIDDDDD W|<›-Í&ê§ †EëQ?%CQxžÖQ¡öb¿íÒ&foŒ#‘HÌJ™iû|߇išá¬0Çq*aš%‘H@×uH’T5xã8NXKIUÕ0ˆây^ø|߇$I³fÔø¾×uÃúLpî¹ç6ý}4PÀèè(†††J+{÷îÅÄÄDÅ`KÔèèhXƒeÛ¶m%ÏMOO³!µI­¶ °}µÛ'uŠò I¹™™™ðgß÷¡ë:t]‡ïûPU«V­ ;FS©4MƒçyañùJë©g»´pì·]lÛ#²,—#lÛƒ–¶m—ÌkeÊ/ß÷aÛ6t]÷Å0Œ° |2™ k½hšEÇ)©¥$ËrÉ,6Q‹il,ø¼Š@¢(p]·¤¦J³4œòkÛ¶mˆÅbPUÃÃÃÆÖ­[±}ûvìÚµk΀ÊÀÀ†††Ðßß?ë¹\.7çòDÔµÚ&ÀöIÔNlŸDDDDD´ù¾x<Ž2iˆÊ;HUU- ¦P{°ßv騕žKÌòŠ!šî+šrÏó¼ªõŽ€Ú)ÁĬñºr‰D"|^pŽ;=v\× ·-öGQ¤R©’ïì3SÄs¢žÊ㯪ªázD0¦3T¨À®]»pë­·¢¿¿ýýýزe ÇÁÐÐМËö÷÷#‹¡»»»äq‘soçθð qÅW`tttÎõíß¿ÃÃÃM?0DõÆwÜÑîÝhŠjm˜û¼ãŽ;022Òî·F+ÐÄƇ‡qèСvïJS4»}:tÃÃÃuµc¢fÅÈÈžzê©vï µ˜,ËÈd20M‰D¾ïcll¬Ý»EU´ªßvbb¢ÝomY±, ƒƒƒ%³K Ã@__ Ã(Iñ¥ªê¬`† Ò쨙†Kl³Ú –D"Ã0`šf¸ý¾¾>xžÇqà8N¸-±o‡_ŽýûÏ·}N’$¤R©’À«ëº³¶Ýßuë^€’` |ãßhúñ¯+å×èè(FGG±eËlÞ¼½½½a0¥Yòù‰ˆˆˆˆ¨Dç.P,>ßJ†a”ü.Ë24M+éü5 º®×¬› FÌW{]4}‘$IagïJÆûÎös¦i†Ÿ{]×ÃY*âó  b;uTÄçX8Dj0ñyòÂô¢ßqÇZ”׬3BR©€`¶ŠXPL1V,Ù¿ÿ혞>ªúH*Ÿ]RI*• k¯DgÜ<ýô‰8r¤®ëA×µ0•`+Ôò««« ›7oÆ®]»°gÏž°8ýðð0FFF>Žl60¢é®±œëº%Aè ŽhÊ/ˆÇã%S1óeçÎ÷f¨Ù¶ Ó4gÍà*¯Õ¢iZ¸^œ9x𠦧ÏûP¾®ýûß„uë®uœÄûT«Wõ×Þ øÕ¯~#|Ïå¥f©+å×\šQOehhغu+z{{±oß> ÕU螈Z‹í“¨s±}Ñbq]ŽãàðáóžK§Óèëëƒišaç©eYaéhç¦ëºá,‘.HtØÆãñ0ˆáû>t]Gä—«•Ú«‘ZH×õp6Ë\ëH¥RU‹q¯¼ïl=×uÇáû)?þBø¸Hé5>>^q¹FÒÑù¾.ï8E g«”×>Ö¯?Œ;îx>œ%¦( <Ï›è³R”ñÙüþ÷ß„ï~÷¡’Ç£ŸÑùªTlfr†UUÃZ+¶m#NCQ”’xgžùsr8EÓ´°fJt}å3a̪grÎ9?Æ+^ñ1<þøoÚ[¥8@Î:ëzüò—Åöðà=ák8€£GÏÅU_ƒ½âeØ~úO°~ýú–þ­êNùµsçN #ŸÏrçÝpà ‚`ÊÞ½{±}ûöïP?b±%Qbû$ê\lŸDDDDDÔnÑ´C™L’$…3BDŠ-Û¶!ËrØI¬ª*4M+IÝ•N§ÃM´“U¤2M3ì\­wöˆU/f”o2™ 2™ € ÍROOâñxKkÃ,%¼ïl‘Šî²Ë.Ñ#GJ¯Th¾"PR‰hg¢=jš6kÖ‰r>ôЫ±~ýz8ŽSRä¾<"jžˆ`7nÅc•Îf:vìl<ùä+±sç¯ÈÔØû ¾ûÝ7FÒ–ýýkÂ}ß°aN?}o|îE¼æ”ñïÿ~ÞùγZú·ªk†ÊÄÄî¼óNÜzë­aj¯½{÷¢»»7Ýtººº044UU‘ÏçÙ¨ˆˆˆˆˆˆˆˆˆæÃ²€òúå³0 ˆvò+ M‹åºÁk¢4 ˆÖ¨g;e$IªÀð}§vÚ¬Öh±kÏóàº.V­ZUòšè(üjiŒÒétÉHw˲Ç+¦ +gÛ6$I GÔû¾îKt5M ;°=ÏC2™D"‘ÀäääÜ;¢yñ¹?ýôàû>LÓœ5³c>¢é·Ê)ŠR’NL×õ’ö'Ër˜Lì›Ø_±oåíõG?ú0¶lɆßG¾G^UòšcÇÎÆÁƒŸÁÌÌ»qÒI?„ï_‹ÊÍ^/ìK †HRð—J¥ ª*Þýî¿À3/{þA'øW¢Jì¨iêš¡rçw"‹•ÔIÉårؼy3ººº œê%f°Qƒt=lDÿ•K§KŸ/¯1¢(³×Q^ ¹ží”Ñ4-œéQN|¿öÚkguÜFƒ0bÖÊÌÌLÉ¿juRj©Tç¡‘R)•J!•J…)ÄÌÇq0888ký©Tªêè~¢fµ„@–¾¾žð³8ŸvÍÈåûþ¬`g¹èì1 4XrÚioÇO\‹‹.º.|¬Òì™cÇη3=}>~üã~lذÂYgkÖ<Ž‹/f’ _[öý Þ0°qã#€_ýêµPÕàÝwß#a°óä“/Æw_8ç}æ¼Âñ,®ëÞ{_‡Z×Ô¿WÝ)¿Êgär9 ”<&‚+DDDDDDDDD´¼ˆÎÖd2Ydð<‰Dº®ãüóσ+@Љ+j¯³ƒ2¾ï£¯¯/ lÔ«|½µˆEbD»ø§iZ¸ÝhAîòe›1K€¨Û¶aYV˜ð}àøñ·„m­‘¢óå\7X_ðsÐÞ¶¾q¼öµâðáßCÿccc%¯9~| Ö®ýNøûá×ãä“OƪU=áöÅ>ôô¬*­YêJùÕÝÝ;ï¼3ü}ïÞ½€X,>6==‰‰ tww7}'‰ˆˆˆˆˆˆˆˆ¨ýÒé4 Ã@__E$Iaý‡T*×u!Ë2’ÉdX»!:ê]üÇ¡( <Ï ƒs‰È‚ú+å#ø+½F–ehš6«3YÓ4†M2™ ÀeY$) •w-”að}¾ïcll,L©åûÀ‰'žˆl3Æ!Ö?bVàࢋ~„{îÙŽgžÙPñµnÀSO½ FnÚôÈd¦á߇]ƒSO}@0Y.Ú4=/ª|߇ëºPUžç…³«Êƒu®”;jI fs?KóJ]'Rt ëׯ7¿y2<ï¼’×™fìh8á„i±@2dŒÎöêê Ry‰ŠˆÊr°Ãøk*N<ñ Àã¿–eáŒ3þ'®¸âÏqùåAP÷moËaÀ?““÷ãóŸÿ< @–ض¾>çŸÿxSÿ–uTz{{qóÍ7cûöíE,ÃŽ;©¿†‡‡ÑÛÛ‹›nº©©;GDDDD´”åóù°Æ`tv7µÛ'Qçbû\Š£Ö««õ¼,Ë 5ßJLñEÍdlÛ†,Ëa½QϧËš]òh>—>Îê *©½&''ƒƒƒa=ŸJ$©˜«^ž,W­<Šç³ÊD»ôEa•Q¾Hӂ׺nVköúl*ÅA-+°Üu׉nƒ¢AÉõë(Î>©DQŠï9˜µÌÌÆš5Û±zõgðªW½ž§âرoR ñx1¨;:úZüÅêÿÄÿù“?<‘,Øþu×}@_Sÿ¦u‡hòù^)ÕžxÈ+ÌðH¥‚Y*²,G¤J¸lOÏìå]8zôå,ø~P#墋~®7P¹ûî-%Až‡~%|ßÇOº 7nD2iÂq€žžŽ½6lÀ?øªðõÑÒ36ÜŽ‹_þ,.ÿàå€<'&áœ{î¡yþU««+ ’ËåÏçqë­·bÇŽ¸õÖ[ÑÝÝÍDDDDDÄb1ìÙ³'ü}zz{÷îEoooÍå:„‘‘‘vï>­P###¸ï¾ûÚ½-7ßöyß}÷ñ˜Ú"ŸÏcdd‡5¿S¨Ó̧}9r###ÈåríÞ}Zr¹lÛÆÑ£GÛ½+ÔFe´ ,1Ÿôwõ¥/O –LV^NUƒ$ñxåý ö±”±íàwIªÜqK– uKÿ‚ 8ðf¬Z5 ¸ÜsÏñŠÛÇãxÍkNÅæÍÿøÛ¿=’¬ïÙgŸÅ©§>Œ³Ï>»dVeïÙ¶ƒí<øâ)ás¶‘,«áC_—ºg¨Äb±’|•›7onÍ-#{÷îÅÖ­[‹Å044Tóµk×®e:]j›X,† 6´{7U#ísÆ h÷.Ó ÔÝÝX,†µk×.|eKH½ísõêÕˆÅbsE‰Z¡··ýýý8ùä“Û½+ÔF•2Ü™¦Ys&J5bBKyú. ¢ˆç’Tü9‚%•êÌK0>^œARº­"@£(Õê§_\ùs~Î9÷àÈ‘¿ƒ,k×þ® LOŸk¯]8㌧‘Édà8<ÏC_ß8rä€ u×…žˆ®®ÂÏ~l[ÔArغõ×Q6Ñ’ì·xOÇŽ ~ˆ¤k{@…ˆˆˆˆˆê7==ááaŒŒŒ`×®]صkלˬ[·Žj›•P™OûܰaCI"¢Å"j×®[·®Ý»²(mŸ ¨,>Ã0`Ué©4M³ä9Ã0à• ¥÷}†aÀuÝŠÏ/%½½½¸ä’KpÒI'µ{W¨’ÉÒ`†ae¹j”¹Ö%'åÛ. ¢iÆ,+ªÔ*hŸÉ áé§OÄñãkÁ ÅíÐõâë=8tèšð÷h@ç+_9 ¯yÍïBQ€k¯}ƒƒG iÀÅëÖ½¸öÚu¸öÚka‰î¹g {ì±ðûBÌ’ñûÀÀ?T<Ž"è£ëÀYg…¯¿øõÂŽËŠ ×u×}³éoTˆˆˆˆˆZà†n@oo/Ça„¨Ã°}u.¶ÏÎgš&Œ …<σa°#=½¦i–L|ßG<‡ïûPeÖóDKïû°m{Ví”rµ>öšÌÐ(¯}¢ª•ÓvÙvPó¤|BŒ,ƒ"†Q„yøáS±iÓ£ð¼âö€`›¾_,N_mu½¸‡Âg>ó¨*pë­§ãèÑ àyÀ~ôa€ëº0Më×¯ÇÆ[¡ë:Ž ¦¦¦`Û6TU :bfJp,Ë/__ñ)J$J&uO¯ÃÙ8»°N°ª <òÈÆ¦ÿ_^ï ÷íÛ‡áááðwQ~bb¢äuÑ\—DDDDD+Ñèè(¦§§±yóæ’œî½½½AKÔflŸD‹ísée¶mC‹m°m»f½LQeÎÎf¢¥$ö (AD¢¼]T““•Ÿ«L‚ H´‰‰ ‡˜Qž¦Ëq‚Çd¹˜òKìÚÅñãÂbñ®[ ¾ˆm”ÏY³æq¨ê›Ãmû~°Ÿÿø9X·î­p]Àq$\tÑ|õ«03s·ß~;8€t:ÿïÿÛ€þðCøÌg€O}ê9|ìcƒ,Ëežlß¶‹û¡i¥ï7J’‚€‰a¯xé帅‚õ‘c (À}÷­ðbSÿÞuTº»»gåŠå‰Œˆˆˆˆ¨²|>|>_2 ¶mÛ†;v´{÷ˆV4¶O¢ÎÅö¹thšÇqfTÄãåL¡åʲ,†¦Ÿr§îÚ)¾&ʃ¢>H­¦"˳—s õCÄlÏ+ÎöдÒÙ-·Ü²gµŽs^x)Ÿý"Ö<ò^ùÊSKž³í ˜ó‰O<€óÎû R©,®¾úA\}õF¸î“xõ«ÏÄÅ_Œ7¿ùÍH$åñ°ØüYg\’ÊK–‹!±Ñ”cÕh𓻞Åôƒßp%PX^U{îy@_SÿæuTúûû9󄈈ˆˆ¨N;vì`ÇQ‡bû$ê\lŸË*MÍÙl0¢:£Å˜b'ªX.FnGiZq$zùëË·­AP‰®ëèëë ƒ#žç…i¼Ê*Ñ4_ ¦Ðrây^¡ˆŽ¯ý1hZ7\×­9S«¸lÐFE½AÄ(¥t¶†xβ‚eŌюE ®è,U- ®ˆ<òH®¾ú¿¡ëײ‚e¢5L¢ûéyzèüöo_>.ËA'(2„?ÿó)ø¾G‰áï܈»îº—]¦C×u†Q¦ï9Z³¥œi–Öz™‹ïûž¸?ÇN¤\€BM™sÏ=„¶T¢òù0>±i¢0 ³±u4ª¡¢ô###PU###˜˜˜ÀÄÄvî܉ßüÍßÄîÝ»Úðôôt”‰*ØÑâªÖ6¶O¢vcû$""""¢N¡ªj8¥V@%•J!•J!“ÉÀ0 ¡_Øo;7ß÷áºn Ö«µÏ³9‚ ÁáÃA£|FHù¬11áKÔ:I§E£\)¯]¶<ãºÀoÆSO=…“Núž¢Ñí?ðÀ_#Ÿ—^ú6œ}öٸ袋J‚#÷ÝwÎ<ó€¢(H&“x©T ÿò/,Ù/1kG‡òt‚ÒÔKQ€­W=U|@®ùù¨; 222‚ÑÑQìÚµ ÷ß?öìÙƒ={öàþûëi(¨bYFGGKÅÖ­[±{÷nlݺuÖóDÔz•Ú&ÀöIÔ Ø>‰ˆˆˆˆ¨Sˆ™)Ñt_•ˆÇ5MƒªªH&“íÞušûmçfÛvX$•{챚é¾DÊ- j$ÁìŠò€Jt†F¥UYVqVJyàAU‹é¾àÈ‘#³öÁ²€cÇÎÆO:ˆK.¹Ï=÷„ë:aaxÇq`Y¾úÕ}ضíWH§_Y)Ää°Ýÿã?¾€sÏýV¯>MÓ066†ýèäYû,Ërh*Ÿ)S.›­>¯]¾>qÎ:ë¬âƒFýËÏG]•‰‰ ìÞ½7ß|3†††Jžëêê ‹ƒ‰èT-£££Ø¾}{ÅàËÈÈnºé&ìÙ³7ß|3vîÜɈ'Ñ"©Õ6¶O¢vbû$""""¢N#Ò~%“ɺÒ@&“çy0Íçä¡ya¿mý\×-ùÜÿán®X#ÈóŠEÖ£Jé¾€Bý€ *¬3J,+PˆÔZ ╞çá?þã?f­Ûq€^x5^|ñTÜ~ûíPU ;v¼ÏóÉø°,¾ïÃó<$}xöÙ“qÞyçÁ÷Ŭ Ùl¦iâÛßþ<~þóÿÀ¶m‡ 럻ø‰,û^OjÁzy_X…Õ«WG‚Z*-RW@%—Ë!‹¡¿¿¿êk¶mÛ†ééiär¹šëÀÐÐЬuår9tww#‹úûûÑßß?çúˆ¨9ªµM€í“¨ÝØ>‰ˆˆˆˆ¨‰´_õT$I S¹…aêñx«V­ ÿÅ£…#hQ±ß¶~Žã@Q”p–É]wm¬P0ŒÒš)@I§±±Ù³5A0À ~)¿Ê_#æ5D×_nÓ¦Mxà3j2àÃ~Ï?ÿ<ž}ö,\{íµxñÅïB’‚Yf"…Ÿ¦iH§Óx×»~'Ÿ|6~øÅ0 "d2d2LMMáÁ7T?P€²9ŽSZf¡¤ß¾7ô½â2ÚP™ššªke¢QÕÒßßX,†îîî’Ç'&&ÐÛÛ[òXww÷œ‘Îýû÷cxx¸uGˆ¨†ááaÜqÇíÞ¦¨Ö6ù·Ï;î¸###í~k´MLL`xx‡j÷®4E³Ûç¡C‡0<<¼â§hS{ŒŽŽbddO=õÔÂWFDDDD‹nff&üY×uÌÌÌ„iŽTUE62ô|fffV'³ªªá2333³þe›9tÒª~Û‰‰‰v¿µ¦Š¦öò¼ê)ª¢³S\·1Íb ¤â¤ŽHÝ,3;d9X$ËÚvé:Ä$™D"ë¯_ƒ .8 9ŽƒµkïÀÔÔN>yT[ÅÇ?¾o{Ûw`Û6\×E*2ÝEQ¤R)ÜvÛšªÇâúë߀šS\Ì*ßháù99@:Z8E ŽáÈÈHKúm_^Ï‹º»»ë ªär9lÛ¶m^;Riýå µ’7bÏž=M?0DõسgÏŠÌ·}^wÝuرcG»wŸV þþ~ìÙ³gEÜçÓ>Ï<óLž;©m†††ÐÛÛ»¢G³-%ì·-%f§A`C–ƒ@†HÁ% ¶D'†D ¾‹ B4]W( @¿8«EQ4-ø§(A°fhè1¸î/¡( zzzpýõ¿€m¯Æöí7áóŸ¿Ï?ÿ1\{í«á8R©Taß¿‰³öŸ…+¦þ‡^v(œ9V‰çy0ŒêÅâuQ;š Á¦:'´ÍŸÀEËú$ëš¡²yófLLLÔ¼ñAooo]³T*©4êv%çá#ê$lŸD‹í“ˆˆˆˆˆˆZ‰÷¥\× g^y^±à¼ž¾_:«Äu‹3VÃ({ì0‚4Yf°œHïåûA%ZÔ]Ó€îîO ™LÂu]躎M›~ÓFGï¼á ýð}š¦…õÏò“±ÿÉ÷6ýrR©E ƒDQ™L&œ3¯™%‚\‘ãR^÷eÁѸŽÀŸçºêPW@¥··Û¶m ‹MOO‡ÏMOOcdd»wï^PÔ§¿¿VCœššª+ÚID­ÅöIÔ¹Ø>‰ˆˆˆˆˆ¨•xßY$RcU >¸n@t=ø'f¬Dƒ!Bùcé?@€·¤³R€â¬ ¨w266¿•ùâ¯,8ÿü7!>þñ­H$$ š¦Á4M;v6Nĉ8|ùáºâ}Ìkf‰ ÀÑJJ6‚÷åÌc]u¨+ Sd†††`Y®¸â ¨ªŠ+®¸W\qöîÝ‹›nº ›7ož÷ŽÄb1LMM…³`&&&Ïç±eË–Ö¼s"ªÛ'Qçbû$"""""¢VZ‰÷¾ï#™L"™L†Á ß÷ašfÅ:?ªÌT±"Ø-+ˆ$“Áó™L‘¤bú,ñ˜`Ü ` aPE–ƒ¦Y ¼ë Rt†Û¶a$IB*•B6›Æ›ß|1 #x½¦iP‰DÙlCCŸÁû×À£ðhÅ”\åœ ª›Žº¶3ÿ?º3!-›¥RW aÇŽÐu¹\ûöí4¨ù¦ùª´þíÛ·c``ûöíÃŽ;ÐÕÕÕšwND aû$ê\lŸDDDDDDÔJ+í¾Ó4MH’I’Â@„iš8÷Ü!WÈ}¥ª@6‹0ˆ!(Jpœ à¢ëA0EQÌBÁvM+Ì:yA!w¯ty×-¦ÉÒ4–õ<ÏÃØØ$I‚ªªá¬Ç)­×" ÍC’$Ü}÷Ü¿ú ¾ðð©À½@´ž{%ÊB‚! Š3HÒ XO£T´l†JCèêêÂæÍ›gÍFÉçó­;íW¥‚DCCCˆÅbÈçóèíí]‘ÓÆˆÚ­Z±0¶O¢öcû$"""""¢Vc¿mÚK ÇÁG?zn¿ýA¼üå/yªSz•Dm”lˆÇ‹5Q¢©ÁT5Â03hŠ-’,óôÓOÃ4?]XNE__ÆÆÆÂú(bÖŠª5QR¤ªü¥Oœ‹£ì>=÷±µ[Äûlˆ„ ¨’ÄâTd€·7Õu§üšK>ŸÇîÝ»¼QØ~¹7J¢¥ˆí“¨s±}Q+-—ûÎòÔ\³Ÿ÷ (J€H¥Røë¿>‚SNù¾ÿýJR_9N鬔hyÏ ‚!==(¬§˜LP” X26VXfªð„\|¾«ëÀ7^MÓ ë:TUE6›…V(l"‚)BºFðbÆ 8ë̳píï\;;UVª¼×†¥UZL…ïIÓ*DDDDDDDDDDDÌój×1M3 TÁl?ù“à¾û‚g~ÚÑYét3Wd9HÅU^‚EQ‚ëîÁÙë|ûÛOÇùçOãË_Þd2¦"SkLI$ª§êêï_ƒÕ›Wvª¾c–ÉÌs†Š6I‘Ÿ›­Z@E6>²±é›c@…ˆˆˆˆˆˆˆˆˆˆVI*%eš&<σ¦ipÝÒà‰¢SpE黀B”1 F¤ì‚Yå³cDazß^ê~ S§Máxÿq†ß÷Çñž÷tA–å°Ê\D1ûJTï+ü¢×µºÎ&j´Ì:À™??³é›c@…ˆˆˆˆˆˆˆˆˆˆV„jÏó`YÆ ù·l»t&K:ü+OëM…eÛÅçEÐF–Kk¦”Ï‘eàÈ‘#ù>žØÿ~1ñ Ü×uzŽôÀu]¤R)X朕R¾Îd²òs’Èk ¿øÜºV9?b¢ÒÂíTKE¦½ú¡¦o®®¢ô¹\¹\®æk¦§§[tDˆˆˆˆˆˆˆˆˆˆˆÎu+§ü2M©T*¬âûÅ ˆ(Ì.("®}xç‘5L׃¢ô" á"ÌÌLâûß¿yÊið\§}ï4üîÐïâ³Îg‘N§N·¥ªÕëĸnßÞ‘šL u×kiXµY6ØÀÄ[&šº¹º*ù|so8‹µè¨-\yß÷á82™ |¿˜L?\7x^i¥<0“JÛ.]¢é·Êƒ)†a@–eœ~úéH$®Âëó¿€ç{X÷Ü:œþùH¿/]q¹¹h0>^ù¹T ÅY*‚ J«D6ïµÔ&G ßÜpëZ41lQW@eË–-@‹Þ5Qk9Niݰ, š¦Áq‚Ù$33A$P‚ ‰i—+Ìx^± |4Xy!zA¤ñºþú¢¿+¾wlzÎü‚g(µ–¦â2VZMA0KE^èŠ*¨²Îo^÷M¼æœ×4uSuÕP±, ###%ŒŒ ŸÏ·àݵ†e•Î.ñ<ªªÂ¶‹ézq–Iµà„,—>§(AFU«×j‰nÓó<$“IÜvÛMAŠ®‡€_ÞÿKœyó™Õkƒ4C4dÍ{-qѺ÷TåXO6…O}±©›šwQúÝ»w3 BDDDDDDDDDDK†®i¯¢³KǪªP” âyAQwؽ|:’Zª< ³Q¼õBÜB$Çu]¤Ói¤ÓiH’YÒç¦câ¢_»¨µÅâ£ï«•ã£ÇFEëê¨,¢yTˆˆˆˆˆˆˆˆˆˆˆ–Q¬]–¾¾`¦ˆ\˜NâûÅÂòÕj¥FñyÇ™<ì£|߇a0 ‰DžçÁ*ìˆRˆÈ¤Ó€ñ(‚î­*/DS|)hÍÌ¥uST4?Ý—ã´f½50 BDDDDDDDDDD+Šãé¹víú4-èù7Œbº.E2™ÙË)Jð:kŽTY…U"‘H Ãó<ø¾l6 ˲ ª*¤Hµy·•3RÊE ¸+hMaz¥3a€ pÓ¬Y*¾L#òìoŨ¬®¢ôD°, Š¢„‘c"""""""""Z:DJ/QGezú9Ü|sP¥^Q‚~zQP~p8|¸ty] ÏkZ±fJ9YlÐ4²,#“É”OÒѼaЏŠÐÚBñ€¬8 fÅ,€ Õ„uYVðGðd€•®^즉ê¨äóùY…é÷îÝ‹\.WòØŽ;Z¾ÓD‹%:åϲ,X–Y–1660Mßüæ7‹ÅÚ½«DDDÔ¡¦§§155…ÞÞÞvï •aû$ê\lŸDÔ*žW^f„¼ýíoŸ“¤àŸëRpAp%šÂË÷ƒ¦gÄ¿(1ÃŲ,èº^L©FÓMÌzñÌæheP%ÊAsSg©ö_0ˆ…T’Éà”ÍšK•Ò¢8-TW@¥··½½½˜˜˜‹Åb,JOËša°m™L®ë¶mŒ!ò,†I’055Õî]%""¢&r#sൊa”GD>oYðYV0¢R–ƒŽÑ‘àºÅ\áùüoáÒK·û--¶OšÅ cQs±SelŸDÔ*ž\]vÙK8th7Þøù’çEì#Z>z­¥(A?~<^yý¾ïã´Ó¦ ª›à8~]Á”YÌN—ÕJ¢ŽŠÞÄu:…ÑëTQÆÅÂêÄèzq6Š `²S[ª+ 244„¡¡¡–ï Ñbñ}®ëB–åp ض Ã0 Ë2$IB:†S˜ã§ª*dYF:†eYH§Ó$ £££8zôh»ßu˜ÑÑQär9ìݻ۶mk÷îÐåyAª ]nîEŠ ŘL‹â¨ây‘ŠB’€T*A)Ö½×tÝ 7¸eÿð?À©§öµûm·Ûç2ç#HÿQ©£Ftà$t™…ÿ£fíÂóÑ€Š‡Ê¿ðÁ—¦bû$¢V»ûî»ñéOëÖý^óšßi&é´˜Y]d9¸ÞÊdJûêe9ª”×Q±m®ë²,¤R)hšÖX@%ZÄ}1+¤œ#ÃX¶Míå8M;ÅÇ|¿xÑÜd¬¡BË’˜¨ª Çq ¤ñ\×…¦iðý Ÿ¡eY/ù¢E©¢¿GÛ¿?N=õÔv¿e"""ê0èííå¬nª›ïQüÔu‹©¡%)˜UbÛÁͼ¸¼•¤àÆß÷‹¯¹¼Çǃ×x^TÑ+Œ8¢áÜsXþ¶ÏeÊG ± ¿g¤‰vv‰@ P ”Ät$)& ¯D±@¯‚ 5‰Èùî¶#ž— ëÔ@MÀöID­äº.<ˆ/|á ¸÷Þ¿ÄÆïÁþýâ¹àZ,›-¦ü’åbj¯r¦YÐ"ø…´Sº®Ã÷ýÆë0Gc2‚sM+ê›T˜ÝŒ‚óàbH ¨áÒ¬A gËÀz¹8 $ ¾þõ@“K54PÁôô4víÚ…‘‘ìÞ½»äùÞÞÞ’Žk¢vð<‰D’$Áqض =r÷¨( \×ÅØØ|߇išPU®ëÖÓˆˆˆh.ýýý€îîyúé§‘ËåXŸmðýb°DAl»8 Ò÷‹)¹²ÙâL‘¢Bäîã|Äì•J7û²\9˜R.—ËáÀí>4‹b>íóÀ˜˜˜—¥ABFlhçíTÁ¨W1ÊVW¼ÂcRáyA°EAÑP: XÇì”'‰ÂküºS…ŸµÂú“(Îp± Ï©…eìÂsNá8E:•Ò«”užýìgGñóŸÿO?ýtîâi´}?~¹\.LWO´˜òù<~üããùçŸo÷®PÇÁË_>„uëÖ!NÃóŠÄõP¼SU PJyI ^­¯bš&&''áy^˜º°!Ñ™â<ÑŠ€}´(½ Ò~-FÝ–‚ë‡tƒË‰‹árgË€ªD1ªH’ðÐg?‹fßYÕPÙ¹s'î¼óÎ’ŽéX,†]»vatt{÷îÅM7ÝÔäÝ#ªŸëº0 ¾ï#•JAUUôõõA×u¤R•+‰´^Àì™(DTªÚ9«FýEDDì™gža@¥CEgŠžŒL3J€bv1šQ’‚Ÿm»8‚Q’Š3Mĸ¸a×õàgß~/¿ŒçbQ0µ™VR@e>8€}ûö1 ":\’( `H:ID*-A‡VøYFÐ"^W‹ ¡þÏTy_XŸ¸íBA<ñË— û  Ô3x8Ú™V¾ß2‚N©da¿3…íÉ…ÇD`E¼@ú ]QØg°¿ H_ÔëQL#¦ÞK@òÀý÷¯Å 7Lâg?» 5Ë%NTb±*´èòù<&&&ÐÕÕÕî]¡:¹®‹|ä­á QkNUKƒ#Ñþje9%èˆv)f³A”B’$¨ ­ç!j,V—¥Ь€Š\c]"Ýf£3pL38àÕŽm+.’ËÔP™˜˜Àèè(n½õÖY½½½Ø±cº»»ñá·Þzë¼w&ŸÏÏšÒ900À/%ªÊ4MȲÏd2%_V"W!-Û'ÅãÀäbMýlë©OVj@…í“hù8óÌ3Y|·‰T\bc&D'ø],•åàgE ^#nÄUµ˜ƒ[YÆÆŠÏkZéx£™!šeÇŽißîpW^yåÊ­-ê"˜¡á£˜ò :IÄõ¡è„ƒq}Ùã¢é²<ñÈÏ>‚NA°c¼°=Åѹ"=—Ù†H…"R|U ÐTêSoüˆ`iyût ÇÂ0‚víñmÀ•€ta&šH# έ€ÔF Îô€"žȧæ;í2 õå—!‘xÖ¬ùqKÿÌKÕúõëyƒ`r¹\»w¥å–Ã}§çyp]¾1ÞùÎâãvá<âºÁ÷|:={PK%ÅÚu)¸® ˲ày^XwyÁÁy±´*h^š1QÓ¬šJEëçRédÜè,—ª+ rçw"‹Õ‰³mÛ6X–µ )Ð###Ø»woÉc{öìá= ù¾·m²,‡õOÊkŸ¨:3…Çö¹²‰é¯ââ¢ÓˆÙ)ñxe¥aû$"j.ßÒn¥RÁ ¶H§åûÅ ˆÁ˜NçŸñq ¯/èP÷ÎÑ@¿8¦ù†¨)DŠ,Ñ/ä¡rG‹HŸ%¨¨>2U+¬Ã@10"fz8˜Ã=YŸ‚ Ø":}æ1èǶKG"»nqv˜ïÓl6¸ŽÇƒöìyÁkĵ§xPün¿§ÓÅ`«¦Ë‰D0HÉÓ …Œß ŒÝ,¯÷o¾”] Þ§ü,°ëÜÇ\²(r"¢rKñ¾Ó0Šß׊$“I¤ÓéY…äÅlb ±>Ïsqúéûñú×_‚d2‰T*µðRÑí‹Uµ¢ŽJµ@ÇXCk©m®€J AͲFS†–c1kv1R•aE釆†0==]òXoo/¦¦¦æ½3ÓÓÓß©}|ßG<‡¢(°mÙl’$Í«ƒ×0¿™M&KÓ9¬4lŸ+[4EI+ù¾I±qãSðýïC’T|õ«ðÖ·nhãÑZ|lŸDDøpÝbýI ®S©à‘þA×gŸŬQã$›íÌD Vž²£ÞKµZi-ƒ˜)_®RM±Žl;hߢ­Êr1(âû¥YCÄì1QÏHUƒ€‡¬DÛ¶aïE^ýB bhZñµ¢¨±ë¯5ÍÒT2å÷¤ããÁzf]s§±—û×áºùÿ‰ˆ`)ÞwŠ"ó® ¤R$I‚¦i³Ò™+Jðýëºõ¯[ÔpþøÇSÐu޳¡á¾ŒŠÊÏY´& Rí½J¨|nž‘þ²Öó…ô—‹=Ëd!ê ¨twwÏ ””祜žžÆÄÄÄ‚v&—Ëa×®]í>&ÔFÑ‹G×u!I’É$|߇ëºH¥RaÍap˜™il;¦Ùx@¥‘/Õåˆí“$©8j.›m^=Ã0`YTU…ªª0 ©T ©T ¦i"•JÁ÷}˜¦ I’ T7õ10ðn|á /âÖ[ <ôP/î½×G.÷º5C퓈hn¾_yè8ÅŠèH+Ö9 n¬Å¿¹ˆs"ƒ)´¬(ŽmU= u؈Î.1’8• K$‚ÇÓéâ¬M+fI$‚¶.‚$²\,çûÁcÑ‚ÃÑÙe•.)Åv¢©úÄ}lô{@¤ú‹®w®ï‰Š˜”Öý ˆˆêµï;E]»à»ÞÂXáËÞ0J³[ˆïóFmK’„l6QœÞKˆˆösŠt˜Íœ9R‹DÑŒâôõ\C¤ ï¹^•J;èh~À©†º*›7o§umÞ¼¹âk,ËBWW×¼£”b¶ËÎ;‘ËåÐÕÕ…;vÌ™£öСCa¾ÌeÀó'¦Š¢À4Md w§"·©¢(UGz¨ªŠÛn»6ÜI‚ï>x †††`Û6^|ñÅv²–›Oû\½z5b±X[.h‰z{{Ñßß'žx¢Ý»BK˜ç¨š\kjZiaxq}¯GËï½æsýH´dø"2‚âî;t^(‚%~ä9 A§Ž 3EEÐÒ„ €õë8Å€I4è‘HmUd5HR©b—H¯]6š­`Ž[G""š§…öÛvww·e¿U587d26þê¯nœóõs Øý˜¶m#“É4'ÅW¹Ã›D4X¬óœ¸~ÐѺº$b$…èï3qæs}î`V0pï½÷6}×뮡²cÇtwwò,ìÞ½»ä¹ÞÞÞçÐëïï/}‹Å°eËär¹šë]·n*JŒ œý¸ »0´Èqhš†L&I’`YdùÒ°-ÍLŠí¯ŠÒø2º^%Äb1är¹Å:¤m3ßö¹aÃô÷÷·{÷—”N-ú¾oßçpûí·"þ0÷4€0HѦS©T˜ºËó¼0mW­)°"ˆ*IRø:UU¡Ìq@&&^çž;Xx}pãýÞ÷¾~ çž{n»]Ëͧ}Š€ Q;ôööâ’K.Á‘#GÚ½+´„ˆëJQð9•*Œiº€bà¤ÒÀ5¢ÃDÐᢠèœÈ¢4݆Hqâ!H±¡¡Øi"ÚŠŽ x™'qmëûAêX‘vE´UQX–ƒú!‚hÓÍL3KDDó·ûm]78ÏH’ƒÍ›†·¿ýüº–ókÌÌp’$alllξŠy‹£x®Ž2œ“›q^T ¶¨% YØ—ùf)©5F\ˆ~¢ ‚k˜&êïïdž ͯ±ÛPQúmÛ‚*Ñäîîî¦t˜æóyLOO—¬k%¥‚ètñxpÁÛȈ1R0“AØIšH$ Ë24M s J‘¨‹çÍÎE;Um¬¾‰ëÛ™Ïè%qÐêÂ܆ísñ”çñl'1«Ä0 œ{î xúéÿ Ã0ðíoÿ×^û1xÞK SqɲŒl6 Ó4aTU Ÿ«‡ªªa$1‹¥ž ”õë×£§§!M¥€ßû½Mxá…ðì³·û0¶Û'-bÄzôKÌ©~t}vŠŽF§ÅDСa èܨv™ä XÀ½R§‹hg Š£`õ²×Îc4ªÈS/þwœ p»Hs%R5‹'@õ6Ì QgYJ÷ÉdpÍèûbf¤Y¾2,NŸNW?ÿÌ•‰C m‹‚™¤Í(Þî"¸^¨µ.‘:´Uã%©4z%!¸Dõ ŽÈçÛæÑS T„VDs¹vïÞ[o½]]]˜žžÆÞ½{±mÛ¶¶ *rÝÆnZ?ùÉxôÑ_A’> Û¶áû>ÒétÍVPi”hƒõ:Ĉ(Ïk|6€¦­Ì€ ÛçâqœàßbçVvœ`Ø€aH§Ó0 Š¢„#/|_Á?þãOà8ƒt:ÿñ?¾ƒ—^ú>t]ƒ ‚®ë Sw5":+­Þåׯ__¶Ž ]¿éMïÄÑ£ÿ°¸² Ø>‰h)…¥%)š¸nð˜¸L4Œà†V佞O­‚Žâ¡4­ ¿»nT­ÂïâþÜ),#þ(Î8°*¬_/,/F.ºnBÇ ?‹YÖÑAHjáõ*‚›äB+/ºà$ÆÎd!øh¨=RÔGã#IdëyAÛÞàúK¤ÛÓ´àç±±àù•vÿDD´Ü,¥ûNË ®#E]”DÂE&£#/ö;6šµFp§}@‚ëÅÅ:¯¦̘×¥óÙçjT5è‹’\›&Qœ5%:sË)XÐŒÚFÍ+ Ò CCC˜˜˜ÀÖ­[ÑÛÛ‹}ûöahhˆÅ¬[À0‚/”FGôÕ; Äu]$ LOW^y^÷º-Ðu½®¼‚"¸ÑH CQë|V”bníhþÞZDÎ^U –[iù¶Ù>—ë.^@Å0Œ0e—Hµeš&dY. hø>ðwwd9ÈÅpÎ9?‚iŽ`rröNQ”p&ÚbX½z56n,º+I@OO—\rÏâÈ6bû$¢NçûAª. ¸Òõ`ä ¨M§iÁM¯èp¯ƒ`êÛ‚ ŒàSt(Ë(7 náqÅ ‡xLœÅLÑ Ï‹›;¥…:ÕÂúÄH>£°¼Zøßü.Šs¢ìy±¯I)^aŸõÂúÝÈs(lÏAps=ŽbE/,köe¬ðZÅ@Ž @ÔžðÞ´^øê 1‰ÉEü„P]DÍEйac~9ÆÙdai'b€™e““AÛSŠR ~ŠvÌ™&DDËÃRºïÔ´ _Åq€¾ß÷ Y0гV’ɹg£D‰ìÙv§Ñ\,t‚F#©Ã²(ÜÓ Áõn¥m‰ˆW¹4‚ëá$*§%«4JCÜ,’Ž ¨À®]»011©©)ôöö²Xn ÍgH¥/×uáy4MC2™ ‹Japp#Þó`ݺkë¾–åbŽÝz߇賭§Hv°ÏÅÙa‰D}ÁP‘åàæa¥T¶ÏÅ¢ëź@ó½uMD½"ÏóÉd ( ,Ë Û¨ëºpét:¬Yâû>zzz06V(a¢ÝpÃZ˜fÕÎÀ““‹×sÍ5? k¨’lÜØ™Ó[퓈蘞l„Áï§€u»ó6@ÿ5@~©op€ìÿä;Üœ¥ÔoõàqI@D`@C1X ^[hÐP lˆ€ŠùYœÂkÄu£R((RĘ€hýˆhaïè½´Wx]ô:TÌ…5Ëoðlƒ%@éÍb´x¸ ¢z & ÅÀ"¯“#Ï Â@“+»PĆ"û÷ƒ«~€Óqúü>Ô:âþHEðùH¢z@¥Á9b´®¨©iAG“¨;iYA}Ña𥳯$iv)DDËÏR¸ïtœâ œ#GŽàk_Û‰‰àÂ-• ž7Íú3Fù¾ÁÁAd³Ùš5a›ªÖØT1¨b¾3F„zR~•ïSÁžÅ\dΞ®ë}6#ÈÔ€Ž ¨`ëEàºÅ<ÔõR”à '$AÇqÂ4A"°âû~X˜IUeoÛÅ|»õ,+‚#étpÑ_·ƒ€9׿ãÞv@ý6 ½¥s ‡·Ûgë‰Ób´Ä\Ÿ3ß÷!I\×…eY$©TëyžÃ0uJÆÇÇ‘H$ iZh)n_B&“©8»$º/©T0<Ö0‚TíÔ×—¬xœtø›¿¹¤½;·ˆØ>‰¨"ÅÀ‡à¦ÄCpÃa!¸‘’ ¿‹‘gFaYñÝ*F‰eÜH¹‘çug_HLÀ8P'ï«@6ÈPìvùÓ:}E°!SØx°ŽY£Ñ´Âãc( xˆ÷¨¢x%:™ýÂ{,ïtN£4È]—ÈM]é:´Úù®Úudy¥üýT³טŽã crrrÖ,ò¾î‡ˆÃœ_G´7h3šÄL&ÑÎÔPq]`p°t@›¸ÿ’¤à¾O\–ß7®ÄÁeDDèÔûÎh /I ÊÜ|³[nyOIíf1ó²ÞÙ)žç!NC–åº2ï4çÍÌñ¼HóZo_Œë®âMÛ6 5˜QDAp]+õUªÍNûU«Ó+àúßCñÞ`¾¹Úš¬ã*´8ýüuu=E9ŸûÜÜ~{Ы( 2™L8 ~ll¬äKJÌÜ2ÍÆSr5:õh°Ñ]ýí€÷e@þàÇëÇ®`©G+(ŸÁ¢N'£•AœOÄhÀZ9ã“É$lÛF&“ kŸØ¶]2ãRp•OK­5ƒ¤Z£òY•btG»ë U ŠÊ2°oߛ۷cDDí`"èPE(æŽÖÖˆ£X;C¤½Ê œŒ£ØI+%*àßHÙà\Ö£ûàýà ¸^p>Öé¢8£ü;ºÒu¡xMµ, ªß4V»f”P}µó–ŒÖÝl1Ïóæ¼É·, Žã@UUX–]×Ãæbyß÷qÇw´¤f&-~ c‚ ÓÉÉ‘×Uhg–Ü›‰Ù÷33Õ7Ç&DD´”XV1‹¦ïzðÊW¾¿ó;³^«(A9„ZÙ»LÓ S¢-ö(Ò¹J.ˆÔ®õÖLEÎâñàw‘óQb€“‹úƒ9â~¢’D"¡[)¨" .¦Ô x$fµWëü]äëwT–8Ë*ý«W6[=˲`Y¾÷½¯¡¯ïñ³Ÿ]…{î+Ñ®(JÉï‚(>X^_¨ñ:1e¼žY Ñú)¥³hjxÀj@7䃀šj¥ŠÖ•Bûÿdð¿õ*@¿þ¼þãNT/q08X|,™LÂuÝ0h)r€¦Ói$“I¤R)hš¶huK‘¿Ñh3É2pâ‰yøþº’ ®,¿õ[`OûvŽˆh±É(%ÜìD;V5G–i5–¿ i >(ÉbZ ‘‡ZzI?—Ô=a‡ì¼ˆÙ§åÄÌðòtžç¡¯¯ãããáëüBþ\ñ³–èº^’ Ô‰\¨‹ÙæÛ·oo÷! J Ò :f§·ˆünÛÅû>ÛjžèzЉĀ -b° øÙ·ïsxÝëÎÀÿüŸ[*¾^–k÷‹zž6I·£³£V_¨è,3ÈEÊ[ èDJ§ƒŽÒò‘§åï£Î¾ÚYR‚â>c®ë‰<à PªDUDړ赯ïÁI FÜkJÛ¬tíƒÂ>-byT–81ÓDUë!¯wœêÁ1‚Íu]¤R)ìÚµ?üOèë«?Õ•mìªZŠ,ÑÖEñ÷¹–q]ÀùK ýùÛ€õé¹*R7 ~Å\ÔIÀVMD;+ÛKSWkC€yH»ÎQSTš9æû~Øu]‡ªª%LQMohŠVãD€´œªç?Q˜´]3U¾ô¥¿Ä /h‹—Ó”ˆ¨yF¬‹×ñ*¯‹5¯B\»F1C€,×vét±uT;g+.®ë–äéŽÞÐ' ùmE S|ŠÀ‹ªª„,Ë%× bÀEµ,•Λ###í> T‰Ú©âÜß)Jé œt:hÏÑÉÉíCDDÔl¾_ìOÙ¿wßý5LLÜTõÚTLب¼.?ì •$©â —–—låõD !.ŽbJjA`CA˜ˆÇƒÇ}?(€Vk·é¯©FÔq‰cîš*?°€¯;À— ÓÛÇÆŠ¿¢XµHm}¯"0%fç¢rÍÁEĀʧªAG¦ë6–VKä Œ², ¶mCQ”ðËCÜd‰æùäËÕõú‚#ª ¨6€@—WüoÒ]¨=uëL@Rµ °ß h»Pµ£Àý* ?à}ÁïšVˆLû(²ÙlÅŽI’pøðá–ïcµ€Š$iÉL³DmÓ4áû><ÏC*•‚aÈd2øÒ—zñ·«Ã0 H’„D"±±1¸õNÅ#"Z.<4íÆÂ0ŠAq/À³kÉ͇mÛPU’$Îí€,Ë0 ®ëB×õ°¡ø§ë:‰|߃'¾ï#“É„3ODÍ3aú.×u+ÎÛ¤%ꉔ|@1u—l“B±Q„eíTô·Øvpo#zŠ?û"O`&""ZTŽœ÷|¸å–.ìÙó?jB¥4Ý—H¡îyâñx¡.t¡“Õ9m1°b 8’É;Z$)8É[V!m—fnÈ¥#(ærªT_aéJÄÌÁõJµ~ÛkÓÀF8½pQS¾-1](ú¸(.\N¤æµ¤5Ûp™Ë€J}Ü :NcEÜb¡k½5 # ¤¤Óiø¾Fb‘[°Þ´Z¾_ù$ËA[ŸkÇœ1 ]˜vfÿ1€ïé_!¸¹¨’RëNëJéÁ÷Gа*tîz?äÕÅßÅL8§P½È¶\7xãŠÜ{"pà{€;( $ Hëܯ®ÅUG¯ÂÓoyºÑ?7QØb4MÃÎoƺu½ð¼‹¡ª*ü$I…ã| í# ÅwL¥ó¬x<‘¨þšjÄ UUÑ¸Š¢À²,ø¾UUËaªY–166Ïóð“Ÿ<QdYëÃX–…£G¶÷À-¦âÈ"Ó“i÷h®[ cYÁuûàë#%Eë•yžÛ¶aY@Ó4ض Y–K+–e…×Ýâ¼ –ÔCÌRUåZš,””‚ Åüè&ànd¿x{"îEôTª8{Œmwiß žçÁqœ’ï³0 Ò÷}ø¾'Ÿ|²Ý»KDÔ‘‚Y'Ilݺ7Ü𡆖õ<‰DP/:ÌêºÁIÕ0‚‰@……àšÛB0K¢™ƒJ ÒFÒéà±hGKùL èÅÛë½ðœ¤,ìÂAB±®Êo;À  /ÙÀ2ŠE¶£DÇñ|®_E TA-¹6$*a@¥ƒØv±~H½\·8dî׺p]þçƒø½ßËॗރk®y_ì×,PUopÄuËÆtJp‘oýo@ÿøX0p’º#è …Žª÷×–î_*xWò¿TyÇ©Åá\žå‹"ytãSçSÖ4…SÄñÝ~÷Ú’}Ð$†!¼W¾€«qJý4ZñLÓ„eYá¨Ó±±±Âˆ4§Œ*‰DýióÚE–ƒžtÎEûDÀ(¦0µ_Òé4$I‚išáÈ\QWL¯T¢£(:ÊVQlÜ8½{Çg@ÑuúPcRDDKš9o(Dg¬,£ëÁµèØ![Ê÷} †)´LÓ„,Ëe¶m‡Ï‹T\²,CÓ´°®‰˜"j™ˆó\2bÔeT!¨bü&àœŒŠíŠ.•jä²ív†èLiÏóÂdâqQQSD­#EQH$šFÑŽŠ¢`ÇŽí~kDD!eà‹_üN>øÊW¦D¿kÃþÇ :bÊO¶.‚>Ã4‚Î| õ†¯ÆqŠÛò}@ ;„‚š6÷É]*ìO¼ðs sÏZ—œ×À}Q@×uƒ} gÍðÀ ¸S^TG6®V9>v€W¢"¨‡íaþ5a払"‚ªÚØgJÓŠÓJÄxqÑöÊW¾š¦aýúïáÞ{Ÿ¨oÜ ]¼ä‹Pó¦]þ%Â)ìzÿK@»¾WùõJ ßTü=œÉfºUÖÕséÈìã‘H¦º¿Á®ð€7#hüšy= ]„0˜E’JA5%Π8]®@ï¤ fÿÁÔ_Ýáûþ—Ý?¯¿9­ "§Hí%IÆÇÇëÎÅ)Šþ¶Sù9Áu–Håc#¸v©p )n8 £˜nY|¯‹Ÿ£æ“âu©³Eʃ"½¤˜I":?E*.˲`š&t]‡ïûp'œå Eà£3U„è¹N’$S¨TäËóŠéö,«ð< ÿÓàu²ÜXªgj.×uÃt|®ë²¬0@*¾W„×É"M_*• ¯™Åu®X®‘üü›6mj÷! "j›D¢ØoYAZZÓ®¼r¦ùɰ¡ŽãàñÿY½ºt&H¥ â¿*ôÜ«…¾Š,‚þCA£(Q”ÊiÃD>•*¼.{¾‘‘Y—7ÜT;ÅH48XÇzm»Xçdllö¨þhÐÉCp¿ò¿y\”¥nÍ)TT:ˆªm¬žz#寯fÏÒ2MŽãÀ÷}躎±Â<(J¯RéÌ=òÝóìG!‡ҀĵÀØE¾0ªåä=‚p”• @?p@M/ûNpmÀû: ¿µø˜$R^¨ƒ(Në*ì¯÷#@9%o^’ A•ó@öÒ°Wn°'h½Î@}ßWÚÚÒé .Š­š„àK¨Ðà­©kK÷ª µÇÄÿ¸ú¿pê©}Mý,Pkù~±C©ÕÇišaljHKU‰HßPNUd2¸xH§[[§¤ô8ùaàä÷~ï—¸êªÿƦMBUU$“ÉðFR™ˆ"¸ÿ÷ÐÛ{6>ö±KqûíÏ㵯í.¼¹Ï â&S䃯©Ð3hY;100ûê…UD´¤‰ÜÀ×$6‚ë§èW©ø9‰ HcÙ “ïj¾ERz‰IÉ+á+Réu]‡$Iag§H£ œˆô:Z!ºäº.4M›•W×u8޾®\=ç:¢‘ËÏ ®÷¢í3›dm-¼ºÜˆÀ†øÙ¶mH’Y–Ãfb6¹ˆˆk^UU!Ër˜F\ÿŠ:Gµ”o°¶QcD¼Ã4‹…èm0Œ.d2©†ÔbÐÌ-ÿüÏA·¿}îN¢i£˜ Ò®Åot€‚&"øLG3EÏåµëHÏyÄvo³iÊY…¥•âˆ8ÈJòÎkZé¬Z}52‚û1øËÆÂfðt(TZD4ìFnV-«˜‚¡Þz Ñõ¿ãÓ¸ì²?ƒã8ᔵt: Y–«~©ˆš(•¦‹ ’¤× hàò;ƒ€cÚ@õ€ÊÛJM¥‚÷&( ‘ÓÈn9˜š½šL&h×ã #˜R÷ ø† ï¿rï/€ä%¥tP”Ëa¹Ù ›¾àw /8¿ò.g³…L`ƒ€j!x“2àNW¯?u0 ²”ˆQ µ>÷óáºnÄ´ 'M1ú5]G£v]”¤üŠÊd‚6·& "n%I GÛiš˲Édðò—¿oxÃ9¸îºß@"‘G~ˆÎ¨¨w¾3h,ý(°mÛšà;¤Ô˜®ëÖ7s®ýÔCg ûß'V|É\0÷zˆˆ:¦Œ¡wµo¬ª|eú~pÎH¥‚ë›vÏvl•hú-1+T’¤pVèàà € Ð.‚íétº$ø!–™«ƒS’¤ªÁ¢yqdqâ<¢ƒkÃè ˜5Ö "M–ø'f€8ŽSrmý^]×E6›-©kT®žk{"Z:ÄõCôçhÚjq ¨Ñ4~¾ïãÑGÅ¥—^Úî·±"ˆr¢6û)§<àâº3\ˆA£¶mã¼ÇÃO>‰çvìÀ)øÀÜ Ëyåk¼8ðŒ ôØÀù ðpäd.Îõ:s ¦Zè@Š4‚ëA—¥rDOk¢ŸS’ŠAžfÝ0H…÷Ðä~·NÁ€J‹8N<¨³4 €b:E©?…ª7‘®ëbÿþ#{+&'kwD*ܨfbø±ÚÛð<À}2Ò–e õ‰`Ä£6(F°®h^<å4@~töºD:®ñ÷Ò ‚ñ>i¿fí/\¤Î߸¶Ùl!¨òŸ*Õ!o¤·x_…å S“ÉÂ÷‚ ¸_Ô*©gEÐÄ : ô¾iÕrñŸýlýdê¾'¥þf%âÊqœpĪªªa*fÎ’iY £´ÆW=û¨È2¾ÿŽwàâðâÃãЃ†7–b¿£ùS©T˜ÿ6mþø7@É4ÚZ#@‚Àf±OäퟫJ¢/I™RíÂCUá˜'‚ˆhY11kà €âTf/r#-LéypwÝó»o„| äË×#ó•Ó¾B0œâtÞð‰§ðœ¸‘£è‘‹Hlw‰\¢#CœÃD`_ÌA1Z\ü,^W}Ñòþ­IV阖?nÛ6î½÷^Äb±z7Aó$®ç¤¯Þ†b¦*ŠÖ׳ÊÄgÖ²,¨ªvrFùDÓn‰™i¤ÛåL3¢Öªtn*O§'Dƒ£"¶H!-–ëŒÎ<õ<¯dÖ©x^lW,Ýèµ€˜±&ˆ×ˆÇÄöŀމ‰ 1+¦D2ÖA*¯šœú €?(æ&¯#Z!\7ø>°íà£/IÁcªü/ú¿m»øá8ÅÑ]¶]ú»$v„µÕâvÄ2@± ¹PøUÕbEY.¶ûO\‡_þ²»Ý‡®#­}~ma4™Ø6Ü«?û¬÷ßÿb t´³/r0þáØÿõÈ|àA¨¯úIp¢ÃxékU5ø£‰)ÊåEƒƒÅ+å'™D"x̶5T'‘&(íÔ°m;œ}-:2D/ñÚZ3rn^Š<σmÛP†a N‡TÑëÇqÂk[]×aR©N;í´v¿…eOÜÓxò@æïVN1yñù‹¦yé´D'ª¨GÁ Ó4ÃT[Áñó099®§Ùƒ˜ˆ¨¶èlŽ(ÈÄ`=ÌP%œ=*ÎÍ’$•ÔЦËö3rÅ/d‘öx||5ÒŸ€Ëƒåß…â¥(•‹‰©jpqWí„(f(VèD©—%*ˆë[1âT×õ°ƒT(¯c²\‰Ž' ˜Š(v6‰ã$iš†d2‰ñññp°•H×):•ÆÇÇÃÎ+ÑÑ%:£D}EÑa%f þå_þ%Þýîw·ûp,;¦\‰ïîñq@R J[fâ³=.~)sDpTŒ4—e9 š8Žƒ±±±9Óðq& Õ$Fc‹bÅFÙó¢ýy(¦¦ƒDd éÈrZáµ~áŸYYGtœÈäaE~ÛŒî‡Ø¶_Ø×è~Dÿw ?Ë…Ÿ}û|Är6‚Ñçe5£¡|ð ~qÉ/°æñ5Xóøtßß ¾wÅ÷°æøœ{è\üûÿ=ƒ=¸àgàøñã8~ü8Ö¯_~éŸñŽ£ïÀúõë±ÿMûqÞcçáÜCç‡իWãôîÓ1øƒèy Ä;ÿôX÷¥uX}Êj¬îYƒ?9ˆôx:ØwÅNãòc&Þ‹\v< ÇMS´b}ŽÀT±Ò4 šjq9¯ð7Šþ}£? Zá‹ôKÑÏHÙ:ú§ú1kþ`*½ºzR}Ù¶s¿ó¼òŸþ ¾ð ¾YÌ:¤ê…âóc!0%>÷µÎûÑÏvKbáÿ:²¬Su ¨´Htè\EßaHï}ßǯýÚ7qãWãSŸÆÅŸ^HjšV2/{‚/õB{N#ès4>]¨oM©U ü`ö.¤ÓÁ~ü‹@v u»ÀÕ>ðg20 Px¡çoªÐƒ#pä4ô‡Ÿv°8 P×¼xß()V"¦ÈrFÏ öUUƒç² H+Ï ;Dç“çï}ïÜuWzz¾EyLÓ„®ëH&“á º˜îl^Æ>°ßÿþ›06\à‹¼˜Š¢„7•"ÍèÌõ<щQùKúºë®--ÑL)btµm–Ñû2‘ÆKŒ~ÁÌzss6ºSª*ã´Ó¦à8÷C-䬻÷Î;qÞÇa€€IDATcá™gžÁWßüfàâ‹áû>î½÷N¼ïCøèMŸƶGßß^¤Å“ o¬oµ}l;ìµÿë7  }¯´#ÏuÃÂðAΊB¯¬¸ñ•åbîÃÈ•O&ìžèT(ï#‹v(…Ê‹ U"Šâ‚^DÙŒÄiGD$ú³˜e%>梶`"Q b@& 8ÿô_}»þí º»7aõêcøÕ¯þ_þò H&?Y.Ö¹Àgõq³= ¼ûmÏá¦|«_z=R7¬FOOÐÌDJ=ÑTlÛ;PÓéÚm¥ZßT´ÙE›z8)Lt8¸€.^[¨Ñ!:ÅwhÉ6,@f‰r'Ÿü!ôÓvÿÉ;ÒÚçŸl L"û7A§k4'ø~± §ëÖŸ@ñ;»’zFy×1ZHÌ䌎N3:eY눟—Sqfðˆ¦³›E0CŒÀEî£E°]×…¦i0M3LË)hšMÓ‘¾“““a'u&“ïû¥)3Qù6:;µüœ{î¹ç¶ûv6»ðOÄüÊ;ä(v¸ð>ØßÜ€ÃÛé](¦ñtØ-‘¸€• ”„‡¥0ð¬Òˆq øìÖ;‹¤%×Ú´üùâ(í,”Q ‚”·3¹ðZñ¿„0ãFøzÅFJd]â5Ñ€‡ø§žsQÌm.Rd]@1¨*¶)¡4Ø#¶í¢XWÍŽ9¯ÏÓß}¯¸ê¸ínCß}øÙe?×ïËxngŸ}6üqœ}öÙ¸ÿ®û1ôØžxõ8yõÉXs| zŽ÷àØÇpÁàâó/FÏ=X³z >–ú~øa\xÆ…ÁÌÙÂ{R‡Ššh )úÞ$—›°)Ø×SŠO¯ÇúâûÇK¬ eëQ+ü\¾q|ÄÈ{ñ÷ëMŽ«8Þ• f«ü%‚^@q¦øËÁr¹ ʵN´Dz,˜¦Yßì#ÓÄ•##d‡¿ó…S%¡¸Ÿ™$Šß …,:%ŸñVT¨)Pi¶Â—·ãú•ûÿò Ïå×&xöäg1xã)å¾°ˆõÇ>v" ×]wfÕÎø×€lYŸt:èO4.y 郿J°Ý“-(=yÝÀ8Œ°G,§¹°ï¸îѧá÷Ÿí净) Þ;g# ¾ Å`Џ—eèjÐñä§¿ˆä{¡½ãJàq@N”í쬀Áýxaâ , Ø´iï}ïyák$IÂóÏ?oº.¼Bþ[ñ¥yÿýã¸ä’øÅ/nƒï¿+Ý”­q“ÌøEC__$I*©Q‰,×oX½vmë?WÔTÑ>$E)-ø®ª.ž{.‡o}ë“a°M×uxž‡t:Ýܲ…€Ås®‹{íŸáâ+OÇ3Ïü¾úU\|àÖ^s žþû¿Ç¦×¾ï,*nHo¾¹x1 F—‹‘ëÚeïôŽÿ yÇÖÙd®ôüFe2¥%‘ç€ë©€^6…L4âj4mvÄÄuÓ„26,V=èïßU]=ÿãÊÙ)K–(!¾«m»X/ȲŠˆf©PËKˆ¦ÞçÔ´`;b°}t;ñx±®™iÊÚ½ØC€öšÂìJÛÔÇÇspÛmøÛ¿½ ëÖ½×u1qÓîIâ«GÿƸoå3üQ~Ú÷Sœòµp]'œð‡8|øT$“»ƒâéqܸúF|Ëþ|ßÇý‡ïÇå}“ØøÒ‹xÓEo±íDZÚYÜŠtøôÿú4&^3{þóĽ8Ö¯_\¬‹‘P@ñ&.âãn %GÞYÀÔSè~mŽKÌŒ€mémøÌÐgpÍO®ÁYΦM›pèùC¸ç ÷à7þå7ðƒ ~€ÿÚô_xñá±~r=èy7=~ÞÛó^œ»ö\~ë“¿…×­ýüÛÕ÷ଳΠÖcöZ ¾û{@™FÐÀì`8¢w¤è}?J /%“ã² ÷¤_‡ñÅë _è>€/*p/:§wÒêS³G&* ´*ðý`æˆåcWÎ[ˆ¾Í*£…$ Ì$´xpÃïºÀØ› - 7žbj·È›).Ô/ýÉO Ù?‚üâÿÂïŸü¼Jÿk|9™ Ó=¸¿ökÐ 3NDç6½ ÿÔ}á.þ†bù‚xÎ\)(–3QPÞ²,;v6î»ï÷ñŽw¼ë×oÃÙg¯?ò ßFÒÃ…)¨ ¹Ë-ËÂ[7lÀSõWØðîw㣟ÿ<®ÿüç1ñ—ëß:€ßùëÂΘKÈ-®7³ÙÂhú¡?‚ùá§áý¯3àå‹ñ YdE™;ÿ}¤½kï­«4ZQ™-iE$““Rx îl…÷䩸è{.Eê¼ÏAëÁ:òUßoj2ÁˆÚJŲÅóU>&¢@úqá~Ì܉b–¶tº˜ÒÑú$àdõmÅ ˆ(÷ ‚ð‡Æ5תŸõá?î< éßܯö]N¤W©€}3à?_œq¢ë€ô,àÿ Ýh£8ÓÓ n„‘BÉ6U`‡Î=„oúœùÔV|ó$?ûïŸá©}OáüïŸË_Ž®|ùÿ|Ò‰â²ã—áÏNþ3Ü5rÞzñøÕ¯úàyÖzkñŽ;Þ'v>Á?Ä®ïlÀºë°6câw?ý»xìíá«Ý_Åää$6oÞŒ/ßõe¼{àÝXûŵxÇçÞƒbè´!lU·bÿ•ûÑóµüðŒâãG>Žcÿy gv‰ÍWmƽOÞ‹[ßt+.Ùå8ñ]'âÅ_Äš5kà)^xâÜ»î^ä^¾œzê©8Òs?ý9^÷¦×áÙ7<‹?}áO±jÕ*<=ó4®ùõȼ*ƒ‡zÂÁS⣫?ŠõÊzü÷ÿ76n܈5÷¬ÁMnÂk{ N}í©xý±×ã‚7^íö¿o?~ñÍ_à#™à‹_ü"®è»'œtÎ8=¹žv¢;–H‹í5ÀÄ×c+û.ÅlM1¨%ZüYœÅÀƒh!øN-j+~DDÑët:D"±±±’:$"-¬®ë°m™L&ÌÔ €ˆkUñ¿zˆ}gD9R#¢pð!‰isÁ‚¥ƒÄLÑÂkÌNÙfYÅqN.¨ˆß žCç°ÿüý€áYp ›±ÒÑmî Ÿ‚¹÷5€±K?†”¢Z…¾QšVzìÅôé¨è –òÙ¸å\ £45_¡¥H··áàA¼þ¶Û°fÍ;v ðÉ“OÆš·¼’$…)‘EЯV¢rØþƒøž³ÇÄïžçáùŸü3…ëî³Ï>ßzöY¼á-oëºÁ¿t7^z)î¾ûn\{íµØ÷Õ¯BG"‘@:.ùî9~üx»ßjç’\ÀJ® ·ë×!ýÎX–8Oɾþcpœåüiè—~¾YZGÎÊ~xáàÅ5k¾îŒd°zM¼á>R4<(çOCÛß¾FUÄ¿þn°|6óSärñ£„W¼âg8»û—øîÝoıéi¼ôÒKxqÕ*¼ö¢›q¯ùÖ¬9¿ÄªŸ]„‰_lE~ê<ôž> _ù"RÉžðka|H¼åäçƒö‹—^€öìÃðÜ«ÃÁBòYgÁÎ~˜žN<X³ÙÔªðë#ì¯ÿÜGŠ]ÌÊùÓ#_?é4`d?X<ÆÇŽA{nÞÉÅL,ávN=8ñÄšÛQΟ†|Â*Hvq;©T•íD2¾È]—ÁÎ^l§§Òº0”nç±÷Â}¤ òÙÇà=¾Ê¥ÏCFäý|èôÒíLOC;x ÞÉÅÙçÊ9ý°]Þc/º‚}Kgë:`ÿípŸ,æÅW޼ 3Ý¿ÄsÏÙîV°,¹…ì6©ð•¯<†Gµfׯõ% ió¹ì<ð‰ðÖ oÅ›žy€‚´["uÛ|53«[t&UøfQ:û:*µø€ÿë€â‰·Ùä'4DM ^AÀÑ<](ÌnÊûgð6õ;ø£É3ðð“ã„óOÀo»ÿ÷ƒÿ²$ãô]ÀYï\WÒ¸5©°’€Ô¿e ¿èçéðNìüÄËJ÷9r±«¼B¾^ ÐÒ üÏx%jŽ çÅý›5VzS/.üÄ©ø_\0ªª„ééý8áñøŸ!“É„#E@EäÇÕu²$–U¹À€üè‘ q1ú©Ù…É·X•H(OKÆÝwçñüó'!‘x˜NUÕ’ ÿ߇µ÷Y«KŠ5Wü¨ˆŒòÎ ßÇÁBQºüàxæûßÇKïyOøô³_ŒƒñPU|¾ÐÁây@ooðüBnFE!h ™ÿ컎öâFÒN7õcžÉ§*`‹c›þéP¸½DâÕ V\@‰>¡èáa ÒEd#8˜(½ð3QÌS= À¼1Àšì´÷Ò`þ# íÒ2€ ƒþ%ßRTJpX^øÒ øÞÐ÷ðöû.Â?~Þ¯}÷üýqœ{âË ª'býúõ8㌻qÁx`5v= þøÿ\ ÿM€¦iðïþë™GqÑÎcø×_\‚©ó¦ðÜšçpvúl8Žƒ3º/ÄÉ™ÂÀ[¸ý‹·câÏ'pÕ®Â#O=‚o~û›Øõ]8ù䓯y¯y>ñÃzïŒG ¼âg¯À+ßøJüô§?ÅééÓqýç®G:Æ¿¼í_ð–O¼£ŸÅEÿó"üûÝÿí -,þìI¤¿“pÉm—àPü¾ùªoÂ÷}œò©SðýîxþhšÛ¶ñï|¯¸ø8ôÓCÈf³øÐ‡>„ãÇã³Oçq¾ôÈ—ð® Þ…—~ùþôÒ?ÅóÏ?'Ÿ|¯yÍkðïÛþ©?KáÑËÅûcïÇßøF|ô¶âÜÏÅ—Þˆ›|3þøÃŒÏ>ýY躎/}éKØù—;ñÞ÷¾µë¯ðµÇ¾†7þoÄe¸ ݯíÆõÞõegzg–¤n’$©rš¾‚ópÆ EÑ£¯aÑÎêŽ}EÕò&ÑþÕú7ë"F£‹t>âï,F¤{ž×’Úa#æ£ûáy^xSíy^£êMÓD6› [‹€ˆHY$Ö—J¥ (Jx“.‚%“…ŽÐhê¢èïÑ‘ú’$GÀF;´ëé0/?1‹kŒhÑ¢(E .Úk î©gP‚Ø.O¨sÚøÈ#€:X¥RÆ4{ßû¡Ý(¾W˜Š2× _ 0â½Æ=Jùç)¶mø²NNt 3ý}Ë ï¿ Ë˜yÿûq Ðù/I>ßÄ÷Zô~6zß}â;oË…â®þg¼ùÍoÆí·ßŽ7žz*Þ÷ØcH§ÓH&“Èd28~õÕ¸ôÒKqùÃãä“OÆÏ˜7ÞnsúßÀ÷îÅË®¸"¨Eñøã8óÕ¯·­i4E<C…z‡G¯ºª¤®‘ZøNÑüñg´û0v.ׄ­gaXr0ƒó·õìà)I²ß^ƒâ`Ô.oP:IEÓföȾ5úÛú²g{ ³ƒsI"aCùu9,Œ¶œâñâyë/~¯|¦×Õ‘u^\¶bÀ#Úì'}?PÞ™ ôœ ô=E¿~”[6Íz?åÛɺåǤ|&FýÛ ²I÷„ãîÄéK–”ÙS2ÉE–7„ ‚מùÊ` M@p gŸÿÙ&¨~ño.þc$© »8³7º/"½¯$ íìYƒ’´¶êŽËJºÔ$ xî¹#Ç”_ÍQ¨wã)ÁXQãÑ4=LNfá8™ }¹(öÍêÖ{xzËñÌï¼ÏÜvÎûòyX£ÚˆH£å <'Æ5ˆKQïD¤¬F .l^Š-«ffffÚ½ 1<<Œ={ö,|E‚¡1„³CÄÙ”÷é>Ü÷þ‡}+‚F&îƒ$s)Àÿúò Øú‘ûð‹Õ¿§No}n¾v(Žþö'8ö_¯‡~5 Ñ–ÂbFí{Ë”ܧ`>™„ºú$àAÀëÒß©ï-šf1ÿvùÌVqs½ 4 º®Ã0ŒpdŒªª%7ŸbDÞ\—-ÀíûØðîw³0}™\.‡\.‡;v´{WÂQ¨žçá¿þë~\7p5^ó–~(Štð‰iYÑœ…ˆƒ,&##“TµÐ@{éüࣈ]~ï?ó̰¬¨ã#F÷‰MÓª¶•h6½VrœâQÇ]–5eTµ8™DQ€ž g QëÛö‹étð|µ>‡¦#–™yÁ9oÀ ‚À‰ø?ÜU€| 0~x‡€ô €9 (S@ê*À^ ¨×ò4€p÷ÝwcÍãkpì¶cøî+¿‹ßý×ßÅ?½øOøÜÉŸ Û¥$IxÃ9AeöËn¹ '=sNÌŸœ{ÓÏ¿Ÿüê'ñü5ÏãðúÃa€ßó<<ûì³Øvù6|î[ŸÃ×܈7ÜóÜÕu’G’xá…pýë¯ÇC=„£G"‘H@Ó4<ðÀÐ4 “““$ wÝu®¼òJÜþÅÛ±~ýz[Œt]/éØ]Ȭǿ~ï_ãO¿ô§ø£Í„‡žx[¶l o²Å96‡)DÊ!UQƒz+¢¶YÕï/<_×óx«uÒ9¢Ó ãïþnϬsmßÙ™ÌÂú½ÅÌL8)dÄ`Ñk^׉tÎ ¬²?Ñ ]°z§d Žøß4M¤R©pƈø?‘H„ÿGg‰ˆóqtÝ‹"zò* XJFFF‹Åxm[&—Ëá¯} üÇ\õojÁõU+ÿä"—æDRÓˆ‚ïÑÿ£³É–"ÑþÅùÊ÷}œö²—ágÿöo8zô(N=õT<þøã8ëÍoÆ_~úÓH§Ó0 Ÿ¹òJÜû¥/á7/¿Ýy'Nû­ßÂûŸy&LçÉ2ÎûÌgðŠ£Gq¤§kÖ¬Á¡k®Á³ï|g¸ óy7òšhaPù-yx†‡#GŽàïŸù{|è¥7A{ùc8÷øóøæs¯ƒ3±úök‹EEu 8%U˜K\X· œsÎqô>ò¿1ùû¯ÃÁŸ]Óî= {3ã÷®<?þòqß*œÏÂ?>|¼ïž‡ñÛVÁ½JCâÏå @>Ø?•W§ài€tj°ŸîQ@uŽî7O´@ÝTö~£Åõ”È{Ql€ª³}‰@„˜0":§0£À)Ün‡âl›@!cE¸¢ÎFI@Åq‚y³p¢­9΋…cï]X›ïÀ{ P_¤þÐEÊ,·ðwë¸î\“;Î7¾ 6üxa$¸›ÂÿÏÞ½‡·Qžyãÿrʃ i$jÒ !€ ¥[A¡-ãÅ¡ºÙʦÛS¼­¥¥»mÊ®©}—l›n[iÑn7Ûîòz®éö„­_ó.-MB=ÝÒT<”¥ 2±$ýûcôŒF²,ɶdìïçº|ÙÖqº53Ïý<Ͻ°i!æ_2 ~¼ß¼ò›ø&¾Y|9>aÿÒ4 |ñã—¿ü%.X|xàÌ;wþw¯½öÞýîwC’$gJÇD"Ï^ñY|/ñ=¼[7žÔžÄ¾à>´··c(:„ÎÎN$ g£‘‘Œ9E ¯¾újH’„oÞöÍr[jÚnü¿7ÿèÃÄÃÄñØI»”k,›èþFnd›ÍŠ5ÆŠNí“i¨ Q,Zœû‰ÏÐLƒw'GD2R,‹aN籜¢±Ó=5—h£IE¯mâÿ‘‚©,+*T:vWÛì/¹©Ÿ ^4k[¸¤¼œ™ªæÎ—Ê”f¬X"‘p ¿»gqáž6n2ÓqÕšˆW]×Ѷjþ¿/~«¯»{ž{ÎyÌ»y£¿û^yå477cxdoþíß:פØ}æ™xä‘GpöÙgcíþ€—?ñ ­­ÎwÉû÷ïGëÃãÕ .À‚£Gñ¶#G°ò áË~G eç¿]‘­´äG?ks¦ŽÎ6¸‰Š˜ãÆ&( Nýð‡ÕsÊQj†•/¼PÏ%ñ4M³;Lç°æîtÀIXŠÄ¤8Ž–:~6b}0¢ºKÀNV¨€¾°Vƒ€0ÿ~üZú5îùþ¡ùgÍvˆë”/Ó!…Ã0MÓn­ôdY´µˆU‘«oäjQŠP·xçKu湄J:F:†ÏçƒOÌ}Sm&r ©ƒÈÚäOc8ÅÃ@ù8}¿…;ï|ÿñ' ¿ÿ<öØÏpê©âÏ¥ûñÑ•oâ Ü…OìlBÔ²ÆÏlj@VôµhÌ'?#å˽‡,Û]à‹4Šƒ¹=48×£O×å¼9Ÿ‡‹Ì·*z(q£IÄ”Wâ¢T\|²‘¥Á ÄãXUïå˜!5‹OöÐÉ‚žç1>¡¢ÂŽa3÷÷c=†§öß< ãÕW_Åÿ$Fñîý+|gúpwÏÝÀVx`X«ÚOz8ûÚ¢­CðqÏ<ó Î<óL<°ø,>~1~ròOб¦Ûô‡ð¹Ç÷àÕ§ÿ/®< ülè B7ŽAU—à:ëÙ×9Þ™ó²ïtÀ|ÁNÆ"H`XVgëðýøÿ€Èû€èGãÀDý?gÙàZg±MÄUd·Y¹¡®î„\‰eŸÎþížZ;”ÉNÇ”-NÛ\,ƒ¨átý-ˆ½Äc‚ÙûÅþ+¶¬Á2ï#jê€þ üXv}DRíA¸+\„ÿ´3¦ø¡l‹Ï]Q¯@üN‡€qÓøˆûkÞ;—ˆ©ÜÅIç˜jÅf©Íçn£´€\oõh4:¥ž²î×½ÃMÓDË3Ï }×]8Á§¡PápØâNŠpÎEEÏïbS®Ž¯“7ÑÀ][Ä}ñœHäO·UXü_ƒ¢p ¥HÄäNŒD£ùçç¢T={дL6>÷î]U«ìÝ-> ¢J%aÝ “&ò¦Ús×è©…ÂéwÿøÇXù書ýöÛqÝu×áöÛoÇû¾þuhÙ©ÂLÓĺ_þ ÃâDZpáB$œü…/8Éÿøìg°ò¹ç0Ù2¬;tû¯¼8ág¦ƒ·<ˆEŸþ4Î<ÓžSç"PU'þűymÁòŠè,¶=eçEálìXcû£b®4×O6>'ÓÿSœwŠßbŠ¡)ŽYápxÆGñy]MÚ…n0€-b#—{"p³Žo}ïüXú1Rß•¿ ü¹,ˆÏ&u1MsÚ7ËŽ®ž*÷KJ`±xrx*¡200€x<ŽÖÖVìÞ½½½½èêêªÞdîÌ“í¿Éo·™âz«È5™aøýïÏÅ?þÅßà=¿ý-`š8ñÄñ¾yó0ïÀé]]Xµêo1<¼VòBüáù? ÷Þ?‚réÑâsÐ åõ2’¤£žŽ!µ/HÍ@¡lr$ÒÞî\˜ŠG1ç+ç$[–e§7®8É‘¡róóUhZñð+Vs¸ä"èQÀ< j€qmöês }²q9ÐçŠ9Ûš®(@"'n}?{ßû`Xô=7íwŸ}g,^Œ%Ÿ¿KV¯Æ+J~ÃÆ* #;5LȺÝÌõ–Õ"š=uHÌnJJ ðfç}ü<¬VW#|½Go+X-ç‚Î}’-.®‘;öN4Uð öoÓŒ ž¨7lÞ\šÅÚzË…z¶8›ó·(Âmº^Û(XðÂëU ùI¨b÷{Œ¨7U¸>b´‘4Áû˜¼kùTñžbh®@ ·€îÎßæ‚)ǧà[4`}p ¤“.‚õ( ý€µ }o>Œœ =;}B 0¾¦V"‘@$b8ÓAŠZQ‹@#8ÝÓøˆ¤,Ë!)Žo}}}yÇ6ò°HÄnQ,œ÷_Ë~‡‡Bö—] P•i¢E­ÎmE¡x1ÊC4º*ŠRÑ4#"9âžæ5# 9SVºG“ˆB˪ªÚ=ÏC!œý/ÿ‚Å®‘Ì·Þ|3.zã ²­ÊÁ`p|¢CÓrIM³Gwž«¶µ¹'2·[©ÝŸ)]·@n¾ÊÂú"¢M© ëh´x]÷ýå>«³ñ³lhž#=à§ŸË—ÀÐÐøV±‚h¨IN÷´”œXlÒD<_Œr5.‰„sý(¦Ç ƒèììÄàà s¯!–/à©p˯¼m‡ãÄ»ï†  ÙõÝ"IR®®O6¶¿]&‘ Q~û[¹Š˲?—¸W`6&:¨êª}ü4 #¯V˜øÜö5'D•©Jlþ·\(Ù#RLƒ€vÒ#}ò㜲ññ‹“^Äü¯|a9 U–P;ÞÀAyÇ¥Øréq4[’À9>Í0O%Tâñ8¶lÙ¿ßT*…õë×Ãï÷—Ìx8pÀÀ¿5€»uàM øº |6{RÚ`›Üowy¼òHóŽ@üŒs>xë­O@zè!ü~ß,;îqÜ÷Æ.Ü?ÿ< ½zV¬8ˆŽŽ$Ž.X€cü Ö®]‹ç.¼¯8;Ûx46v–5õs*4í7ˆÞ°‘HrIÑkO\À*Šâô€€½{÷bÆ N’3T¨Y¯¤Z¨n"Œëá “Ï矖iÁzûˆ=ó,̓σ 1ø7€ñ¬ýã ñјSNרüÛ{^Ñ#GpÙe?ÁOïx¤gŸÅodp䤠Åw^:¸Ï>ûe´·ÇpùåÏàú[ÏÆ‘#G°pûBìß¿ÿùŸKð‘‹ÀÒ¥ç²X¶ìÝy;|¾×pÒI'¡³SΛ֮p”VaCT­? ²<ù^“&É““¹^$¢!À½ª…×·ÅÚ¡Ô þžèyÅS¢Æj¥ï3nŸŒÛ~pw·vwã²ênIOšl|8pø ÆßÝ‚N‡ñ–« ì?曀ñ{`H"»^Nü=>þÛnÎÜŽC×-Bò²ËHÌw„6,_Žw¯]‹ÏüéŸ"“É`U{;¾10€@ €X,ÿyçá¿ý-ÞX±Âé1$æŸv¦ï±,¢QÀ4UUÀ² OT˜YÈ6”ŠÞQ“ž u¢iáÜs¸ãƒÅænå–µð} ß#;DuàþûsŸi1ÐdÞ§°ñØý>âõ G‰¸·…ÂVÁH$ÿUÍ_1%‘†‡‘~ñE¤“ÉÜ>™ Γ0•sÛBöhä\òDÔç’$ _üâñ /8s¶‹i^ n8ÉLw ÷4¯îéò {®»9·Œð¸¨©)W˜ ÀþýûqüÂ…8ó²ËÜO.?’£ÜœI…ŸÁb‚h&Ѩ;[Î “ÉdùÞ¤†Î­[12½§Ÿ ÷±æîí.’"^Ü×s…ñ*êý¹8uÒ,üí®Õçõ%ª"AcY–SCHtLËSì3­<ò€ÜÔV+³¿ó®E=v]ZÑgºAÌ–ï™j™îñS$PÄÔ—Š¢8¯îvw}Xq›¦iƒã~N])þVUÕyŒ{Ôf4—ÄOã7Üp~øÃâÝï~wÅÏß ¢ÖPá²¹ëŽ>GtØu×Ó Nm²öövŒŒŒ8ë‰Dò:^¹‘ub¤Z[[ÆÆÆpá…¢¿¿¿¢çD" ¡½½½èûˆ¤´øÞtOY/F²‹²aäO Ë24M+º “Íâû[Ôo‹F£øÂ¾€|ä#¸óÎ;Çí[qÎ$Ë2^~ùeœ~úéõš›VlÞfÁüËMÐÞh…¼éOa¶,A j_¦Ü²è£èï¿Û·ëÍf íržö•¯|\r v½ñEÁßWyZ=¯K¦|Í;ƒæâ1Ì3Eé“É$6mÚ”WToýúõèêê*¹S®¸à ¬I}»N¼æØY¸rÍ/q^kÿ{h-~¸’¤cÁ‚0M/¾¸o¼qçžûqìÛ÷ dYF&“Á¢E‹0þ|,X°K—.tttà–[nÁõ×_¿û»¿Ã7Þˆïÿû¸þúëñ?ÿó?8묳œe8묳ðôÓOã}ï{ŸS¬N;í´Š×?‘H ¥¥çŸ~½wÅ´ÅãñYQˆ«’õxøá‡ñ«_ý Ÿüä'.ñ5S‰Ïx<ާ¾ü¿Ñ.¬½ü÷8iéïñÎw¾‰§žz Ä‹/¾ˆyóæáÁ;!²°ÍÍoâàÁƒX±b=žzê|ô£Â¾ð'öž~úi@[[ž~úi\|ñŸãŽ;píµ×âÑGÅÅ_œ{öœŠ³Î:†ÓN{}Jë?[>Ósé{æå—_ÆO<ÿþïÿÆwÞYïÅ­©©ÄçÚµkqñÞñã×®Àeø5.|‹?ŽT*Ë’qøðã8vì,;v'Î8ã œvÚi8õÔSñꫯbÞ¼yP{öìAìðaüöÀ¥—^н{÷¢iýzüîôÓqî¹çâÈ‘#8oÿ~,ÿþ÷óÞ{ßõ×ãÅ5kœÿWÜrKÞýÇÎ: ®½ÖùÿÔ={°â–[òžs¸­ £_Œ‡~©T 5o–üây¯“*(»â–[pêž=Îÿ/®Yƒ}×_?î}Žu^?í4œºgϸem¾ÿ~,Ê6öžºgŽuFn¼qÜû”ZŸO?¥wÜ‘÷˜×^‹øÁœÏôéÿó?yË*¶[©÷Ûd¢÷9vÖYxá}ïÃë®ïÆS÷ìÁ ™LÞë¸_C¬³Û+Ë–á˜ëèÄ#GpÊ£:·‹}RjʦçŸÃÃÃxýõ×ño|³ÕTÏm×­[‡^x'žx"yä,]º'Ÿ|2/^Œ––ìÞ½ÿøÇóÔï}ï{¸þúëã (Ò|äÈœuÖY“:­¦¹tÌi•ìžÛNŸº®ãßÿýßñÌ3Ï`éÒ¥øßÿý_¼ôÒK8ñÄqþùçãСCX½z5`Þ¼y8묳ð½ï}ÿðÿ€[n¹7Þx£·"^ï¿ÿ~\|ñÅ8rä8±»Æuì©…¹ô™n•žÛþèG?ÂŽ;꽸55•ø¼öÚkñúë¯cÏž=8|ø0N8á\qÅƦM›œØ¿ï¿ÿ~¬Y³Æ¹®<묳0<<ŒüãN›Náï§Ÿ~Ú‰QyÇÚÂÇŠc±89rÄyl)•œG5ŠÙò=ÃsÛœéœÛ¾ã—ŸÀàÑ˱h‘…ÅÊsðûüàB¼øâIxýõOcÙ²exã7°~ýzìܹӉ×}ìchjjªé9­×%ð½àåxß·ovìØQõs[Ï$T¶nÝŠd2‰þþ~ç¶îîn´´´”Ü)W\qöÿöu,¾ð5>|^yåC˜?ÿÇxí5æÏŸÅ‹ÇÊ•+ÛþýûqÙe—áСCX¾|9^xá,\¸G,\¸°.Yå#GŽ`þüù˜7oÞÌoü*;xð –,YRïŘ‘õصk^xá|éK_ÂUW]UïE®™©Äçþç"íà /<†sÎ9O?ý´“ ñù|8þøãÑÔÔ„7Þx§œr V¯^£GâôÓOÇSO=åü¿páÂz¯þ¬ùLÏ¥ï™#GŽà‘GÁ‹/¾ˆíÛ·×{qkj*ñùþ÷¿ÿû¿GpÜqcÉ’%8tèÎ:ë,9rmmm0M—]vzè!\xá…N,ž|òÉžˆIáÕW_Å+¯¼R·ãjš-ß3•ì“ýû÷ã±ÇÃ\€¯ýëõ^äš™ê¹íUW]…‡~ïz׻𶷽͉¹£Gbùòåõ^­ŠÍ¥cN£¨dŸðÜvâøüùÏŽ¿ýÛ¿ÅóÏ?k®¹{÷îuŽ‘‹/vÎc½tœœÈ\úL7ŠJÏm_xáüüç?¯÷âÖÔTâóOÿôOñÄOàä“OÆå—_ÞpÇLç¶ÞÃsÛœéœÛ.¿»¿}ëO€æœãäñÇ+VàðáÃxï{ß[·v ¯Ká{ÁËñþè£âñǯú¹­g¦üw[%í~õ«_¹õïê½:D³ÊTâóÏÿüÏñçþçõ^t¢Yo*ñùÓŸþ´Þ‹M4ëMõÜv¶7”yÁTâ󪫮‰¼‰±I”㙄JKK˸@õlQ ¢¹„ñIä]ŒO"oblyã“È»ŸDÞÄØ$ÊñLBÅï÷cttÉdJ¥N§±nݺz/ÑœÇø$ò.Æ'‘716‰¼‹ñIä]ŒO"oblåx¦† ôööbãÆhmmÅîÝ»ÑÛÛ‹¦¦¦z/ñIäeŒO"oblyã“È»ŸDÞÄØ$²7666Vï…pK§ÓH§Óðù|6Fä1ŒO"ïb|yc“È»ŸDÞÅø$ò&Æ&‘*DDDDDDDDDDDD^ã™*DDDDDDDDDDDD^Å„ QL¨•q—¿üå/×{!¦*N#•Jš››ë½8%—QmJ§ÓhnnÆüùó+^z¯g&“ÁsÏ=7éeóâz[—éî£zï/j”m2öýDñ9Ýø›éu+·í#¯­G#h”mÒèû~ªÇÎr÷Ï–cg½Ö…¦/•JaÁ‚UÛ×3ý9ï—ÉdðÖ·¾µªË:ëRÉñ²XØFÚG45Åbh¬}_*>½~n[Éq*ñYïõ¢ê˜J|zißOçØ9Ýõ¬†©Æ§×׋ʫåùQµUû»Z2™ èɹsCkP·ß~ûX[[ÛØ† ÆÚÚÚÆn¿ýöz/RQŸÿüçÇÎ9眼Ÿ{ï½·âõðÂzÞ|óÍc7ß|ó¸ÛK-›W׫غLgyaÿxM#m“Ù°ï‹}¦§õX·‰¾gJí#/®‡×5Ò6iô}?•cg¹ûg˱³žëBÓóä“O޵µµUm_Ïôçàæ›ovÞ磌®»é¦›ª¶¬3µ.Åâ±p½þäOþdltt´!÷MM±Øk¬}_*>áÜv¢ãþtâÓ ëEÓ7•øôÒ¾ŸÎ±sºëYÍu˜l|6ÂzQiµ½|n[êX9Ýø¬÷÷UÇTâÓ+û~ºÇÎé®çtM'>½¼^T^­Ïª­ÚçØÕâÞf£££cW]uÕØŽ;*Z†Ù YC%™L¢¹¹~¿ÐÒÒ‚––$“Éz/ZÑe-6¬¬’õ¨÷z¶¶¶¢«« ---“Zv/®W¹u™Ê>ª÷þñ¢FÛ&¼ï'úLO7þfzÝJÅf©}äµõh¶MußOõØYîþÙrìôÂ>¢©‰ÇãhiiAkk«s[#}¦3™ €ÜtMMMðù|ö²ÎĺLét~¿?ïöŽŽŽŠÖËkûˆ¦¦XlµïKŧ×ÏmK+§Ÿõ^/ªŽ©Ä§—öýtŽÓ]Ïj˜j|z}½¨¼ZžU[µÏ±«%™Lbtt===ìø×ue—a.ÄÁ‰õ^€©H¥Rã.â›››‘N§ë½hyÄÁgÓ¦MH&“hjjBoo/ººº*Zz¯§øâ)6Ï]©eËd2ž[¯‰Öe:û¨ÜzÎEõþÌNF£ïû‰>ÓÓý^™é}Xê{¦Ô>òÚz4‚FÚ&¼ï§zì,w=¾wjqì¬ä~òžT*…;wbÛ¶mظqcÞíò™niiAWWnºé&øý~')(.ô¼~n;Q<úý~g;>wîÜé\ü6Ò>¢É›(6Å}²ïKÅçÖ­[=}n[ê¸?øôÂ÷MÏTãÓKû~:ÇÎé®gµ–_¼n¡Rñéõõ¢òjy~TMµ8Ç®–t:ÖÖV `çÎhjjBWWWUÎgƒ†¡"2Šnõ’¬'‘íééÁž={°eËÄãq'#Wn=¼¼ž¥–­‘Ök:ûÈKëá´Mf뾟nüyiÝJí£FZ¯h¤m2[÷ýt–ÝKë5›Ïoh¼L&ƒ7bË–-hjjÊ»¯Ñ>ÓMMMNaÒ‹ÀÙpn»sçN¬_¿~¿ßIp6Ú>¢Ê•ŠM ñöýDñ9[Îm'Ÿ²^TÜtâÓkû~ªÇÎé®çL*ŒÏÙ²^d«öùQµÔê»ZÒé´3Ú¤§§>ŸÝÝÝNRd®ÇAC&TŠe—½˜åjiiA¿“½óûýX·nÓàPn=¼¼ž¥–­‘Ök:ûÈKëá´Mf뾟nüyiÝJí£FZ¯h¤m2[÷ýt–ÝKë5›ÏohòÒzxE#m“Ùºï§^Z·Rû¨‘ÖÃ+i›ÌÖ}?e÷ÒzÍæó*.“É`ë֭غu+Òé4vìØ;v4Ôg:NÃçóå}Vý~¿Óƒ®‘Ïm7lØŸÏ]×ó¦·¨dÙ¼´hò&ŠM ±ö}©ølôs۩Ƨ×׋ʛj|zißOçØ9Ýõœ Åg£¯Ùju~TMµ8Ç®¿ß?näÌlh3«š(|_mmmc÷Þ{ïØØØØØîÝ»ÇÚÚÚÆFGGë½Xyn¿ýö±«®ºÊY®ÑÑѱ«®ºjìöÛo¯x=¼°ž6l»ùæ›ÇÝ^jÙ¼º^…ë2Ý}ä…ýã5²Mf˾/ŸÓ¿z¬[±õ(·¼¸^×(Ûd6ìû©;ËÝ?[Žõ\š¾ 68ûnl¬q>Ó;vì(ú¹Õ4­*Ë:Së2Q<Þ{ï½y?O>ùdÃí#šžÂØkœ}_.>áܶԹìTãÓ ëEÕ1ÙøôʾŸî±sºëYÍí?Ùøl„õ¢‰Õúü¨ªyŽ] £££cmmmc»wïvþoÄ6³ZiÈ¢ôÐÛÛ‹7¢µµ»wïFoooѹ)ëIÏ]¿~=|>vïÞ®®.gξJÖÃËëYjÙe½¦»¼²^Ò(Ûd6ïûéÆŸWÖ­Ü>j”õð’FÙ&³yßOgÙ½²^³ýü†&§Q>ÓH&“¸êª«ÐÚÚŠt:––§8ét—µ^Ÿét:t:îîî¼Û{zzÐÛÛÛPûˆª¯Qö}¹ølÔsÛ鯧W׋ª£öýtÓ]ÏZ*Ÿº^d«õùÑL¨÷ò555¡··×©?#êhΆ6³j8nlll¬Þ 1U"@|>Ÿ§‡ ¥R)ghS±å,·^^ÏRËÖHë5}ä¥õðŠFÚ&³ußO7þ¼´n¥öQ#­‡W4Ò6™­û~:Ëî¥õšÍç749ô™ï×ÜÜŒ–––ª.«—?Ó´¨ºiß—ŠÏÙtn;™ekäõ¢òeßOçØ9Ýõ¬§Ùº^”ã¥8óêòÕòܹ‘5tB…ˆˆˆˆˆˆˆˆˆˆˆh&4dQz"""""""""""¢™Ä„ QL¨•Á„ QL¨•Á„ QL¨•Á„ QL¨•Á„ QL¨•Á„ QL¨•Á„ QL¨•Á„ QL¨•Á„ QL¨•Á„ QL¨•Á„ QL¨•Á„ QL¨•Á„ QL¨•Á„ QL¨•Á„ QL¨•Á„ QL¨•Á„ QL¨•1§*š¦A×õz/aYt]‡aUy=Ó4¡iZ½W‹&ñ9û˜¦Y4®ŸÞÇxœ*E˲`𿄝¡ëú„÷Sm1VgŸé;«ÞÂøô®j^{N÷XÊØ¬?ƪwM5VyÚø—sG£ÆåœJ¨$‰YíííUKBÔ‹aXµjb±:;; …¦ýš¦i"‘HÔ{ÕhŸ³K$A[[[Ѹf|zãqn¨4c±XÑ“\MÓœ8okkkÈáFÇX]¦{ìd¬z ãÓ›ª}í9c)cÓ«Þ4ÕXåuèì0㘱Ym—s*¡2éº˲ê½ÓÒÙÙ‰p8Œ¡¡! C×õ† &¢B³!>§Â4MÄb1 ;q­iO¨®æjë›îךmñYI¼[w±/%Ir~˲<á‰ã³þù¦sõŽÇbë]ÉóÜÜÛ EA0„¢(ã«ë:$I‚ªªÎcE™•=ɼ¤± Tþ9l”X-u_½cu¢uŸê±`¬zÅl9–Nt<™ ÇÒrמ3y,elÖÛ‰òyñX:Õv"^‡6®Ù—À䎣^ŒË©žãÎÚöÛ±Yjddd ÀX4 ‡ÃcÆÂáðØØØØØ¡C‡Æ$I;tèÐX00644äÜ'ž;444&IÒØÈÈÈØØØXÞëD£Ñqª³“yl)Æ‚ÁàØ¡C‡Æ†‡‡Ç$Ir–¹’í!ÖW¼·,Ë%ï+õœJ–·’õîëëSUÕùÆ­O±uÅby·‹}$ž;44ä¼G0SÅy\©çÑÌ(Ÿ¥bsll¬d|Ö#6ÅkÍÆø¬$^&Z÷`08ÆúúúÆ@Þöd|z ãqüö˜lÌy!'ZïRÏ›( ©ªê,£FÇí—b£ê©U¬ŽUþ9l„X-uŸbµÔºOåØéÆX­ŸÙt,èó)îkäci¹kÏ™<–26ëƒíDã·‡¥Sm'âuhcš+q)î+÷¹òj\Nõw¶¶ßÎÚ„J8 ƒy·É²œ÷!qáC‡œv__ߘ¢(yÏ ƒÎsÝy(±ƒÝÿd¥-@Þ‰™ªª“:PF£Ñ±@ 0n•º¯Ôs*YÞJÖ[|QФø_|ùM´î±XlL’¤ ÷¹x`08&I’ó|€=fF©ø,›ccc%ã³±)^k6Æg%ñ2Ѻ‹¸øí~ãÓ[ù¦s^ˆÇ‰Ö»Ôó&ŠÅBÅxŠ]T¸Ï•¨új«cc•!VKÝç…X-µîS9vº1Vëg6K'ú|ŠûùXZîÚs&¥ŒÍú`;Q>¯K§ÚNÄëÐÆ4WâRÜW.6½—S=Ç­í·³vÊ/Ã0œa~‚,ËÎß–eå »u?Ö4M†ãŽ;Îùñ°¢Âõ™ ˲òÖ¢ÑhÉûJ=§šdYÆàà TUE4E0·½‹­{á°iI’òæœuÇsu+÷<ª½RñY*6Ƨ¸o¦â³’x)\÷Ÿþô§H$F4ÅÈÈ ÃÈ›;šñéŒÇ|S‰9¯ÄãDë]êyÅb9ÅÞ‹±Z[ŒÕ|/ÇåTÎq+y^#Æå¬M¨›C¸ÐD;AÌe:fàq~jña¬§RÅt]DZcÇ&õœ©PUu\°UúÅS¸ÿ —KQôõõ!çÍÁXîyT{åâ³Ô$ãsæâ˜Z¼<óÌ3e9/–UUÍ{.ãÓ;åM%æ¼åž7Q,–£(JÑ×-<‘§êa¬–7W¥0Vgã³\…÷†ádÅ,˪U«ò 5UU󶇮ëèììt¾|ŠÝ÷|`ÂçT‹8‘toëD"Qщ¤išÎ~ÏEý€Ü7C–e§WB¹çQ핊ÏR±)îg|ÎL|S‹—sÎ9¦i:Ë&žç^6Ƨw0óM%æJÅp5M5>J=o¢X¬d;Y–•W¤Ð4ͼb¡T]ŒÕ|56§ƒq=wx%^çú±t¦1ƽqYÿefþzÔëq9k§ü*G–eôõõ9ó²É²ŒÁÁÁ_1^©åœÉ×ñÚ{•Z†©d&½–Ѥñ¼›@u>ë3/Õ|¿™ŽƧ÷0뻼…¯ÇãMd¶Åj5_g¦ß‹1G…f[|6jlNw9×sƒWâu®KgcÜÛ—õ_fñZ3y=êõ¸œ³#Tˆˆˆˆˆˆˆˆˆˆˆˆ*u|½€ˆˆˆˆˆˆˆˆˆˆˆÈë˜P!"""""""""""*ƒ """""""""""¢2˜P!""""ª±T*…L&SïÅ ¢"ŸDÞÅø$""¯aB…ˆˆˆˆ¨†Òé46l؀ݻw×{Qˆ¨ã“È»ŸDDäEL¨ÕЦM›ê½D4Æ'‘w1>‰ˆÈ‹N¬÷L×~ð¬\¹²Þ‹AsØóÏ?EQ°|ùòz/Ч<üðÃØ»w/Þò–·Ô{Qh{â‰'ðgögõ^ ÏùñŒ%K–Ô{1h{饗ÐÜÜŒK.¹¤Þ‹Rsñx---?þŸþéŸÐÜÜŒóÏ?¿Þ‹NsÐÃ?ŒÃ‡ãºë®›ç¶“‰Ï§žz ·ß~;–-[†+VÔ{ÑiŽyùå—ñÄO`ttó7SïÅ™“‰Ïþþ~¼ñÆxË[ÞÂëOšqÏ?ÿ<Òé4Z[[ñž÷¼§Þ‹ã9l·¥z«E»mÃ'T¢Ñ(>ùÉOÖ{1¦m×®]X¶l–-[VïE™¶íÛ·ãšk®©÷bÌØzìÚµ æÄEçdüð‡?ÄÝwßk¯½¶Þ‹2m³å3=¿g¶oß΄J›6mÂÇ?þñz/Æ´íß¿û÷ïŸò³å{¦Ò}²ÿ~˜û®”T*…;wbÛ¶mظqcEÏÄŠ+pøðáz/þ´ÌÅcŽ×U²OvíÚ…gžy«W¯žõç¶“OÃ0pÇw`Íš58÷Üsë½øÓ2—>Ó¢Ü>9räyäìÛ·oN$T&ŸßùÎwðÖ·¾µá?<·õžJöÉþýûñè£â÷¿ÿ=*EÜzë­žþ,xýXÒß ^÷Z´Û6|BeÁ‚èíí­÷bL[<‡ßï‡ßï¯÷¢L[*•šû¤ÒõˆÇãìSÄŠ+pæ™gΩς×ÍÅï™T*UïEõ¤yóæÍŠÏt2™D2™œë2[¾g*Ý'âq³Y&“ÁƱeË455Uü¼óÏ?ýýýõ^üi›‹Ç¯«tŸÌ…sÛ©Äç[Þò\{íµ³â³0×>Ó Ò}ÒÝÝ]ïE­¹©ÄçÛßþöYqìä¹­÷ðÜvúV¬XáéÏ‚×%ð½àõx¯Å¹mÃ'T&3…‚—yùƒ7Y³áDf6­G½œþù ß»V˜-Ÿ~Ï0[Ž^>ñ¬Ùò™žMûdº4MCKK FGG‘L&1::ŠT*…æææYƒ¥ð˜ã=³iŸL×\O~¦½g¶ì“j˜Ëñ9›Î£fËgz6í*ÎëÇ’Fø ΖxŸŒ†O¨yQ&“ÁÖ­[ét;vìÀèèè¬o"jŒO"ïb|‘—1¡BDDDDTe…½Ýº»»ÑÓÓãùfDsã“È»ŸDDäuÇ×{ˆˆˆˆˆˆˆˆˆˆˆˆ¼Ž#Tˆˆˆˆˆjl.Î-LÔ(ŸDÞÅø$""¯á"""""""""""¢2˜P!"""""""""""*ƒ """""""""""¢2˜P!"""""""""""*ƒ """""""""""¢2˜P!"""""""""""*ƒ """""""""""¢2˜P!"""""""""""*ƒ """""""""""¢2˜P!"""""""""""*ƒ """""""""""¢2˜P!"""""""""""*ãÄz¼i:F:øýþ¢÷ù|>ø|¾zo¢9¥Tlºïg|Í<Æ'ÕÛm‰J›ñ„J<ÇÀÀZ[[‘N§ÑÔÔ„Ûn» MMM@<Gkk+vïÞÞÞ^tuuÕ{Í ¥b㓨ŽŸDDDDDDTkl·%*oF*ét[·nŶmÛÐÒÒPUèééA<Ç–-[à÷û‘J¥°~ýzøý~f<‰j¬\l`|Õ ã“ˆˆˆˆˆˆjí¶D•™Ñ*ét~¿ß JèèèÀèè(’É$š››¡d---hiiA2™¬÷6"šõJÅ&Æ'Q1>‰ˆˆˆˆˆ¨ÖØnKT™M¨øý~ô÷÷;ÿg2ìܹ>Ÿ©Tj\F³¹¹Ù™³o"ûöíCww÷L®‘£»»Û·o¯÷bL[©Ø0åøÜ¾};âñx½Wæ T*…îîn8p Þ‹2mµˆÏ »»õ^=šƒÄT¬÷¢QV-ÛmS©T½Wæ x<^“vÛM¨¸íܹÓÖÕÕåô´u«dÈØŠ+ò‚h&õ÷÷ãšk®©÷bTUal˜r|^sÍ5èíí­÷*ÑÔÒÒ‚þþ~,]º´Þ‹RUÕŠÏ¥K—¢¿¿ŸóÝR]tuu¡··K–,©÷¢QÕn·uz!š)½½½5i·ñ¢ô™L7nD:ÆæÍ›¡bÍÍÍã›N§pD3d¢ØŸDõÆø$"""""¢Zc»-QyS¡’ÉdL&'=dkÆ ðù|Ðu=¯A¨¥¥eÜ0±ÑÑQ6"š!Å&Àø$ª7Æ'ÕÛm‰Ê›Ò•x<Ž­[·°ç×ëééÁ¦M›°eË–’™Éd2tttä-òù|ðûýN‘#¿ßT*…t:uëÖÕ{Íz¥b“ñIT_ŒO""""""ª5¶ÛUfÒ •;wb``À©[²uëVg>½ 6àç?ÿ9šššŠ>7N#N+"ßÓÓƒÞÞ^ôööbãÆhmmÅîÝ»ÑÛÛ;ákQõ”‹MŒO¢:a|Q­±Ý–¨2“N¨$“ItuuÁï÷çe+{zz°cÇìÞ½{Üt$‚¾‰ˆ×M§ÓNÏ["ª½r± 0>‰ê…ñIDDDDDDµÆv[¢ÊÌxQúrDÞÅø$ò.Æ'Õ¯;‰¦Pñûý¸é¦›ÆÍ‘700€t:ÖÖÖz¯‘'¤R)ŒŽŽ¢¹¹¹d­A"šyŒO"ïb|‘WM:¡ÒÑÑÝ»wcýúõðù|…ªªåÜyDDDDDY›6mB2™„ÏçC:†ßïÇæÍ›ë½XDÆ'‘—1>‰ˆÈË&PpŠÐ'“IgTŠßïg2…ˆˆˆˆvÏÚ;vàç?ÿ9šššN§¡ª*ºººØÓ–¨ÎŸDÞÅø$""¯›tB%Nc``Û¶mCWWW½—ŸˆˆˆˆÈsÒé4ºººœGb®éÑÑÑz/ÑœÇø$ò.Æ'yݤ*Á`™Lñx~¿ÜýÅn#""""šK:::ÐÑÑL&ƒÝ»w#™L¢¥¥¥ì¹ò¾}ûÐÝÝþþþz¯ÍAÝÝÝØ·o߬¿¦›j|nß¾ÐÛÛ[ïU 9&•J!cß¾}õ^”š›J|8pÝÝÝèèè`Ç_šqÀ9çœSïE!¢2鄊¦ilݺuÜý{öì©÷:yB:ÆÖ­[‘N§ÑÑÑQöñ+V¬`2…ꦿ¿ñx¼Þ‹1c&Ÿ×\s “)T---èïïGwww½eÆL&>—.]Êc'ÕMWW|>’Éd½…ˆfȤ*½½½<‰$""""ª€hËd2X¿~=|>{Ïyã“È»ŸDDäUÇOçÉ©T Éd©TªÞëADDDDäy£¹›ššÐÒÒ‚t:]ïE#šóŸDÞÅø$""¯›RBe``_|1Ö¯_îîn¬_¿ªª2±BDDDD”500€L&Èd2H¥RNq]"ª/Æ'‘w1>‰ˆÈË&=åW2™D<Goo/Ö­[‡¦¦&gnË 6àþûï¯÷:ÕUWWvîÜéLS²{÷n¬[·ŽÓ•yã“È»ŸDDäu“N¨ìܹ]]]y3ŸÏ‡Í›7#™L"™LÂï÷×{½ˆˆˆˆˆêª¿¿©T £££ðù|ì]Kä!ŒO"ïb|‘—M:¡2::Ц¦¦¢÷Mt;Ñ\ÔÒÒRïE ¢ 0>‰¼‹ñIDD^5é*~¿;wîW/e``ét­­­õ^'"""""""""""¢ªšô•®®.¤R)¬_¿---hnnF:Æèè(z{{9J…ˆˆˆˆˆˆˆˆˆˆˆfI'T`óæÍèêêB2™Äèè(:::œõDDDDDDDDDDDD³Í¤§ü€d2‰ôôô ·· i2™L½×‡ˆˆˆˆˆˆˆˆˆˆˆ¨ê&PI¥RèîîλÍçó!™LbÆ õ^"""""""""""¢ª›ô”_;vì@WW6oÞìÜæ÷ûqÛm·aýúõH&“ðûýe_'“É`tt>ŸÏ¹-N#Nç=®µµ•S‰Í b± 0>‰¼€ñIDDDDDDµÆv[¢‰M:¡’N§Ç5ä@SSÓ¤HÓ4p¦ €x<Ž;wæ=®¿¿¿¢ UG±ØŸD^Àø$"""""¢Zc»-ÑÄ&PimmÅÀÀºººò+;wîD*•*šlq@2™ÄÎ;ÑÓÓ“w_&“a ÕI©ØŸDõÄø$"""""¢Zc»-5ªPèë›™÷štB¥§§étªª:4::ŠT*…Í›7—M¨´¶¶Âçó"ØÅîÝS‰ÑÌ)›ã“¨žŸDDDDDDTkl·¥™b€i@u^OÓf.¡2é¢ô°yóflÛ¶ ---hiiÁºuë ë:ºººÊ>·¥¥~¿ÍÍÍy·g2À¦M›°fÍ\|ñÅ(ûz@<Ÿ™­ET c×®]õ^Œª˜(6©Çç®]»*zQµ¥ÓiÄãq>|¸Þ‹RÕŽÏÇ##™LÖ{ÕhJ&“H$8räH½…ˆˆˆˆˆ\jÕn;Qç@š» Ãþ©IÛÀÀ@MÚm'=BEÉ”jI§ÓðûýèééA?’É$6nÜŸÏWr(Ù)§œÂ¡fT7~¿û÷ï¯÷bÔÜTãsÙ²ehmm­÷âÓÔÜÜ ¿ß£šGgšJ|.X°~¿¿ì¨R¢Zðù|hiiÁsÏ=WïE!""""¢ L·Ý¶Xç@šÛL³º¯'I€eå'VZ[[qß}÷U}Ù+¡200€õë×cëÖ­5Ë(¶´´äÍÃç÷û±nݺ²½gO=õT&T¨nü~?–-[VïŨ¹©Æç²e˪šx%ªTSSü~?,XPïE©¹©Ä'*TO>ŸçŸ>æÍ›WïE!""""¢ L·Ý¶©©©Þ«@TÍ>°¦9þõZZZjÒn[QB¥«« ·Ýv|>¶nÝŠîînÄãq¤R©ª-H:÷z 6"o`|y㓈ˆˆˆˆˆj‰×TmÁà̼Ï~ô#ìÙ³§ª¯Yq •¦¦&ttt`óæÍèïïGkk+ª–\CÅÄœ|™L;wîdïY"`|y㓈ˆˆˆˆˆj‰×TwD‰¦UV^Ó4X–5îvÓ4ÑÖÖ†X,‡sÓˆ…B!´µµ¡­­ {÷îÅš5kªº¦\C¥££€T*…;vছnÂW¿úÕ)MñÓÕÕ…T*…õë×Ãçóa÷îÝèêꪨÐ=Õã“È»ŸDDDDDDTK¼î$ˆD€hP”ê¼^(T~¤Š¦ieªª:·éºÓ4¡( ‰%ŒX ظñ4í¿`Y†‡‡¡iî¸ãŽªo‡I%T’É$Òé´,©T ñx€='Ù¶mÛ*~­þþþq·mÞ¼©T £££ðù|ÌrÕA±ØŸD^Àø$"""""¢Zc»mýhš°¨FÒÂ0 Äb1 VmùLsòËfš€®ç'OÖ­KãÇ?>ÀÉX¼8t(¹EeY0Œ0žyfaÞëµ·›P Ñh†aàÅ_D¸ëT,;¼±Ø~ôöö‚Á 3ªªš*N¨lÚ´ èéé`Ï·aô¶¶¢¥¥;wîD:Æ–-[¦µ@,`Mä]ŒO"ïb|Q-ñº³öL°¬ê$T&š.kª‚A{Ú¯J¦ê*\§D"?¡‰˜xä‰üdžB!hš†ÁÁAH’„“Nz+î½÷^|â—°“-'œp #UU¡ª*žxâGPõ)|ê`θàe¬^½¸jë\LE 1¥×¶mÛœÀÙ¹s'š››±eË455¡«« ªª"N3CIDDDDDDDDDD4 ’d'T¦#‘H@’$EŠžˆé²‚®ìF®I¸äëÆã\tQÓ¤“>îÇÅb1„Ãa<ñÄX¹r ãlçþH$F$išhiù!ž}vt]G"‘ÀèèÅX½úR\{­½¬Á`W\qþôÄ6lœ2†¿†¸f«ºŠŠÒïØ±~¿?/ ™L&ÑÑѦ¦&p†z¥ÓéÚ--Ñ,$IS®iš0 ‘HPUuÜ•D"SToÏÒu½ìHMÓ°k×.¤RG¡ë7²ÄmÆoåýÿ,ÓO¦i"‰ ‘HàØ±c H’=‚åñÇ#‘H ¯¯Š¢`hh###hjZ}û– ‹A’$Üu×hjZ@ e]ô^è/™è:z<Âáé'¤Ê©(¡`ܨ“d2‰ÖÖÖ¼ÛDr…ˆˆˆˆˆˆˆˆˆˆˆ*Wë˜P±Ñ'mmmH$‡Ãƒe–e9 “Âä‰eYÐuÝõþ¦óÛ®ab¿O,âEkñ±ý¾ìrýä'—åÝvß}Ïá„¦iP%ûZWañâ`ÀË/ïÇe—}>oÔŒÉ,ÁO<¢X¼8„+šò’&_øÂpÙë—á©yOÍÈ>ª(¡ÒÜÜŒd2éü¿sçN€ßïw­\©T ÍÍÍ3²àDDDDDDDDDDD³‰,—L{{{Þÿ,Ëèëëƒ,Ë8zôLÄb1hšæ$GÜ#Tt]‡¢(Îmâu#‘b±ÚÚÚÐÖÖ†@ €Ã‡ãÖ[φiNœøI§_Ä¡CoÏ»íðápèÐÛaÂá0 ÃÀ¥—žˆųÏ>‚·½ík¸÷Þu¦3M ³Ó~€Ã‡C @"D£ùÛÇ4M<ðÀ€g.Àê“2(3sÙ´U”Péèè@:ƦM›°sçNhš¿ßïŒHÉd2ˆÇãðù|,NDDDDDDDDDDD4EŸäI$y£GìçäF’ÈÙŒƒa?üe'¡"F¯ä¿—ä#UDbÅ0 çñ}}}ˆF£¸úêñòËû¡iÅ Ówvvâ¶Ûnsn …€cÇâµ×~Ó4 IÞ÷¾•8ãŒýØ¿ÿx×»þ##‹œç¸ëȨ*°lÙOÐÒr/öïÿ@ ª …B}­‹OÆðG†a½i:ɘD"[o=÷ß_Ý %T|>n»í6$“IlܸÍÍÍèíí`OýuñÅ#™LbË–-U]8""""""""""¢¹¢Ô´_…BÖ= Ë,Ëþû’K®C,C  ¢ë:Ô‚ î¦iB–e˜¦ UU¡d«Æ/Z´W^¹ i¹Ç‹dŽaøùÏ:ËfÀ/¹\ðª³\ÃÃÃH$I’ Ë2,X׬cˆÅò ÙŸwÞ$ ¡ŒgŸ}@n”J4ŧ?½ç/^€Ðq!¤¶¤œçE"ìßFÕ÷ω•>°¥¥%o>5¡µµýýýyÓN§‘N§€çËDÃø$ò.Æ'ÍUÅF~š¦Á²,:t‘H$/¡¢ë:À¸‚ó]´ 'œ ààÁ¯axøkyEïÅó%I‚aÐu’$AÓ4,Yr úúyÉ–½{›ðÚkËpê©Oáùç_G$òå‚eYxñÅÈØºõÜx£Ë$IÇ‘#ÅùçŸ —ð UE^BÅ4íÿ£QàK_Ê`ýúÓðùÏÿ.»ìC$ /¾˜ÆÂ…'bժˡ( dy¸P`É]K _¢£³SÃÈÈ>ò‘Ÿáâ‹ß¬ê>ª8¡2‘¦¦&܈ˆˆˆˆ Äãq  µµétMMM¸í¶Ûœis‰¨~ŸDÞÅø$¢¹,ÉaßA @,Ãðð0;)a$IÊ«R8jåÁ/ÁÚµWeG«ä¿®¦iNÂDŒBQU‰D¯¼r/>ýéüÑí틋݆“NZŽ·¾õŸœÃ0088ˆË.ÛK.ùW<ôÐ?ãíoß…ÓN³“"Š˜fmm:.»ìýÎk©ªŽ;ž7b°*ŠüéŸ~wßÝÏ~ö |ýë7à’K~ Iº?| wÜñ‚Á =Zæ—n®\ÿ÷‡Ñ×g¯Ï¡C‹¼^Õ}TqB%NcëÖ­ÎÁ, ²^ QâÜyÛ¶mÎ9³ªª@OOO½hNc|y㓈‘®Ûµ>ªEÓìÑB"‘pF HÙ!&bJ®P(ÀNˆƒAƒÁ¼×:õÔ×0oÞ5¸ï>÷òêÎï¾¾>çvÃ0ð³Ÿ=†ÑÑñSeÙKLœ}öñxòI ÑèÒìó€7ß|Ç¿·Ýö+|å+C×u |ùH‹-™g.´µµalìgH$þ3»ÀÕWg ë»²‰ ŠÜqG Ö®};FFcåʃø?ÿça´¶žŒ{ï}{ö,Å×¾€,Ëé>€N`‹ Iör=õÔRû«º¿+ª¡ÝÝÝH&“hiiA:Ɔ œá—DDDDD”“N§á÷ûó: utt`tt´Þ‹F4ç1>‰¼‹ñID(›þk„B!X–…@ „Š»H|a­MÓ qÑEŸÆÐÐ0TUu¦Óì×ùÖ·^Å#¼;ïyb4Šae‰pàÀ0M_Ü…PHG__®N‰H}}aÜ{o+.º(7jP’€nx‹­Å}÷Чž:Û¶€ÑÑ¿ÀßÿýnçýìQ2‚Á {ì1D"öûôõ­·>'ž8}}Àƒ>ˆ@@Æ?þãñØ»÷<ñÄñøÐ‡Zaš&R©ŸàÊ+w8¯«i€ñN€ìè–ÎN{´P©®Š*ÉdétÛ¶mCoo/¶mÛ†ææf T}ˆˆˆˆˆßïG¿ó&“ÁÎ;áóùJ>oß¾}èîî®÷âÓÕÝÝíÛ·×{1jnªñ¹}ûvÄãñz/>ÍA©T ÝÝÝØ·o_½¥æ¦Ÿ@ww7Û¨¨.ÇqðàÁz/ ÕQ‘²ã±, †a@Ó4†P(ä¤7 N!ùp8œ—PÑu5›€ `õê/AÓÆW²7 àÑGOÁÙg¡¡\‚DŒryûÛ{œÇþ'044„Ÿý¬‹/†,çž‚Á $IÂÂ… ÛLÓž쥗殺êÎ8ã \zé¥8th(;zÆNtˆõ=í´ÓœõÑu;vœŠ•+?ƒ¿üËÿÄ 7<‚7ÞØ…'Ÿ<Í0ŒÂaû½TU…¢(øÿiÌžðLvad{´eÙ£|–/?Põý]ñ”_~¿?o¾ÊŽŽŽª/ Ñl³sçNÄãqøý~tuu•|ìŠ+ò’ˆfRÿœKL&>¯¹æôööÖ{‘ijiiAÿœK¸WŸK—.屓ꦫ« >ŸÉd²Þ‹B H™uHÚÛÛ:'ˆF£$ Š¢8I»È» ‡ÃΈظ }4šKú¸§{ä‘/8¯\¹ÒI¸Öp™ˆX]·‹‚÷çž»Ï<Ó‘‘E¸úêÕδ^ºƒ2ñáŸ]× ¡( Âá7°m ª7À0€¾¾óò:îåŽD"¸úê‘ÜÈ cöæîW% !Û#TêšP!""""¢Êe2lܸét›7o†ßï¯÷"Qã“È»ŸDÔhTujuTD2Å4MȲ Y–ñÚk¯áŸþé$D"2L3àŒÌì)· #— ‰f³ –gd‹›¢Ø£RD¢Ä=’F×uü°,Ø5H¤Üº(J.Y2‘@ ÿ1Š" Ðвßý®ÁrÚÛïÂþçÝ0 4MƒªªøçVavæ& áŠ+¾˲—UUí×Å·þÂȈLI$Šló0 èëÚÛ /Ü`UU÷wÅ5Tˆˆˆˆˆ¨r6l€Ï烮ël "òÆ'‘w1>‰¨Ñ˜æøz#…Ä^ùÏ3:&€]Ûäw¿ûþê¯~‰§žú+Fákäþ–å\2Ã4óGp‰DnÚ.E±'‚eYx饥0 ²k޹ߒdðp/«û=Š­o,f?O–¡!;©144„ááaìÙ³'œ° ï„¢(Ð4{ê±X,UUñÒKKeï¯('u;™ êZ@>C,(#·Î¿ýí;ª¾¿+¡²{÷î¼á¥¢ }*•Ê{‡YÑ\700€L&ƒŽŽŽ¼) |>_Ù: DT[ŒO"ïb|Ñl•H$`eçó2 Š¢À²,(ŠâW—e¯¾ú<óÌK8óÌËÆ%-‚A;ùØI‘ÈÉEÉO¬¸G­†Õb'2 ÃÀÊ•ï„eíÜo/Cî9bú1èîþ>ž~úØ»w%€Üˆ÷ãO9åQtvž‹¡!ûþ'žxÍÍ1ôõõA’$,Z´O<±†!FÕ˜0MƒƒƒÎè”ÎN{=TÕ^Ö‰U²lßßÞZé-â:€ìôg «ú¾¬(¡ÒÜÜŒÖÖÖ¼Ûx #""""*.N#N›ï¾§§‡5ˆêŒñIä]ŒO"jD²\~”Šîšo+ ¡µõNÜÿ øÀþŠò* à䓟Å'>ñœ|ò§‹å'HÚÛs¹„‰©áQ"¸ë¡ˆ‰,˸瞧qùåÏ@QÎvÞÃ0òG„¸*ïÿûñÀùëlYv‚'´ÿÿØÇ~‘‘·C×ÿªÅ ',ÆŠagÝ4-— €`0·râ6ñÚb½Ê1MÀlä«Ä ÁNª@§ß`YU÷wE QˆˆˆˆˆÊëííeÑG1>‰¼‹ñIDH\/Lˆ)‰D’$ÁÌf@ ÃÀèè1¼ím‚å˯u ’$á;ß‘ ËÀáËÇMw%˹‘$’”K¨$¹:(…µOÜ5Nœ"îŽ=?ÜM³_SL¯åN ‰÷Ó4 ™ü ZZ>à3ìä‡aØË‰--_ASÓ{á÷χeYPU ù:TUu¦4ÛǨ)¦Üôiãû, ýÀ'(p¦üRUàÁ«ŸP™t •t:ÄãqÄãqg8&Ñ\R¬ <Äb1,^¼‰DƒƒƒeÙ™îëñÇã©§>Vôy@Ï<³0ot‰ (v"CÔq¿·eå×YÅÝñµHŽ9‚Õ«30 àþûßÄáÇ!IùuVÅ~I>ô¡OáðáÅyëÜÞn'’, øÀ.à 7\MÂá0ÚÛÛ!I’“LìóŠb?G,¡bEèK‘$Àz¹nLLî5&kR •x<UUÇ‘J¥J¥°iÓ&\uÕUغuë¤Þ8“É8uXÜÒé4’ÉdÑûˆ¨ö&ŠM€ñIToŒO""""""ª5¶ÛNŸa°, CCC !“Y Ã0ÐÚú)œvÚÛ`Yò¸ÂóCC@4ÅȈxû·˜1¬¯ÏþÛÉÓÌŸÖ«0¹ãN¤¸7þ~|㋲#ZLŒŒ "Êþý×'qÏ=GaÀÈÈ!ˆ¹´"‘4-ä<î„¶Á0 H’”å"£¯¯áp8/¡"”¡"FËT*ô }Þý"µÙ§BÅ 1eóæÍ¸ÿþûÑßßþþ~ÜÿýƒˆÇã“Jªhš†¼Û°~ýzlݺëׯw?Õ^±ØŸD^Àø$"""""¢Zc»íä(JþÈÓ4ÑÞÞÓ4‚ó†<÷Ü_g§ÿ’±xñb¨êøäÁâì Y¶“+â~Y¶Gœ„Bp ¸ÖLq×Uì$Œû‘ÛˆF£xÿûïÀÈÈ"À²eËð¹Ïù¸ ¥¬]»÷Þ»ÃÃc8óÌ31::ŠD"UU 1þ~tu=={>ŒpvhÉ¡C⽊ÏÛ¥(èƤ)G’ë Íý&UݽãT”PI¥Rغu+n»í6tuuåÝ×ÔÔäÓ4­ìk `ãÆE“/ñx[¶lA?n»í6lÚ´‰O¢R*6Æ'Q=1>‰ˆˆˆˆˆ¨ÖØn;5†‘ŸÜ£SLÓ„¦Iy£Pt]ÇÚµkâì…y÷èH$72°“bÊ,Ó´ëN戺*â~ñî×+|Uöïÿ1n¸áZ\qŬ]{ÈYö%KöaÅŠƒøÖ·¼ãi°, Š¢`Ù²gq啯at´DŠ¡`´ˆ»öK1ƒƒ“Kªˆ)¿òoDMG©T”PI&“ðûýhii™ð1===Èd2H&“%_«µµ]]]ã^+™L¢¹¹~¿ kiiAKKKÙ×#¢ê˜(6Æ'Q½1>‰ˆˆˆˆˆ¨ÖØn;yváù¶¼Dˆ¨“"˲ScD’€… "ãÌ3Ï„¢Ñh~¡x`âd‚H”ƒ¹Q+€ý|‘tÉ]·“<ªšŸ°#XDÂEQìÛ>øÁËpÍ5·Á0 hš]×ñòËûqÝuqÜtÓI8ãŒù8÷Üye@02¢`õêÕN±ù¢"Ù{Z³êlY¤S n„T©‘+yÐèèhE/&‚ªÍÍÍy·§R)ø|¾¼Ûš››Ëf:÷íÛ‡îînô÷÷×n+M »»ûöí«è³ïuÅ&0õøÜ¾}; ···Þ«GsL*•B<Çê½(UQíøŸ½ÙˆˆˆˆˆÛm'öÀ㤓ÎÀ_üÅb|ä#ûñÐCi¼ø¢…`0ËÚÚì„F"‘K|¹Éà`þ빓#–•KŠH’`1 {TŠm"IùI1¥Ö=÷|û÷o‚ªž èìì„¢D‹É€è—€£—ÅêË3X½úw¤\gKY–¡ª*dY†išPÕ&$ökŽ,)¬Û2N@Aú@ x2iÊdjÁÿÐ;T›6ÉŠ¦üêèè@*•*yáÇáóù¦œñ)Öë–óðyã“È»ŸDDDDDDTK¼îO×uÄb1¼öÚ}xç;°dIßùίñÊ+¯ ¯ÏÅ!F’btˆeŒ/,ïNNX–ý(dÿ$v"BLíåNJÄb1tvv"^xáM<óÌ'±xñbìÚu; Ã@8Æy罌3ÎØ÷¾w"Aà„O@ÓÞ¦që&I’“PQ³Ã[J%MÜ#iÆiƒ=bÄp¿>JO6]2òFÄT[E ŸÏ‡žž§(Q&“qîËd2ˆÇãØºuë´z¢·´´Œ ÄÑÑÑŠ²DT[ŒO"ïb|Q-ñºs¼D"MÓ𳟽€ãï‘#w#“¹W^y%”lÅ]D^°¬ñ¯å.Zïþ[QìÿÅmâõÄmbä g4ÉÞ½qÞy¿†Ïw%/^Œ_üâ?ÐÙ٠˲pà ×â–[Ã?þãbOÏ¿çyt¸ÑM¢Ñ(d‡§Y÷ÄšÆsË1‘?å`×m©Ñ{V4å« iš3ett™L>Ÿ[¶lAGGÇ”Äï÷cttÉd~¿©T étëÖ­«ÍšQÅŸDÞÅø$"""""¢Zâuçxº®CQüVà¾ûv`éÒ@UOq#¦ÉI”`Ðþ;Ì%B%?ÉR8}—aØwÓ‚‰K$,Ë„i>ˆLFÇ}÷ùŠ’+T¢ª*®¼òB,[¶š÷4zñ!¬{ºü>TU{„Œø{RªT'¥$ ö¨7y£bª©â„ `'U‚Á ’É$vïÞ À¨jvéííÅÆÑÚÚŠÝ»w£··MMMÓa"š6Æ'‘w1>‰ˆˆˆˆˆ¨–xÝi»ðÂïã¯þê%¨ªŠp8Œ‡z+n¿ý €n¾y#tý'é`švBQìäH"a'O"‘ü‚ì–ebQÕñµEûuÜI—Âé¾EA"‘@gg':„U«N÷>b*2à(ŽXˆ=«÷`UYRL×íQ*“л0}­¦ù’a'U oÓ,©þÛM*¡MMMèèè7%Nc`` âi¿Š$êêê‚ßïG:†Ïç›ÓÃÆˆêe¢baŒO¢úc|Q­±Ývb##kñÿñ-¬_/g§Ù,x€‰O|âL´·N$’©âäF›´µccvÒ%´k¢„ÃaȲ=JEÔNÓÔ I b1¦iB–e(ŠUU122I’044¾>‹pï½ 1¶p ÷· ì)¿Î²<Í"ò2ì„JãÕ`ÀNž¸§$Sà„ÊDÒéô´ë¨˜ÓIäuŒO"ïb|Q-ñºxùå—±k×íøÚ×؉†ü ÌŸoWf/L˜¹âô"9âž¾K’€ÎÎñSiÅb1ƒAƒtÝ~L0$v–Ä4MH’äub“—²s‰%Å—oÿù‰8õÂST¶Þ"ñ3e* ÀTF¹L…‚ñÓ€UIEE鉈ˆˆˆˆˆˆˆˆˆ®çj‚TÊ4/ù(ì–zÅ)ý§–#Gò68j—T f ©À‚£ ªþvÕPI&“H&“%“Édj´Eˆˆˆˆˆˆˆˆˆˆˆª£’*¿ýío±fÍåÎÿïyÏñÎw®tF›¹Dˆ›¦åZÑu;¡"Þ·ØÔYŠ|÷»ÇpÏÝG1lJxå‘W '! A’$œ~z“5QÒH’m¿«†»;±R ¢=`×P Nãµ&¢en¢éLQVBE •t:T*Uöq~¿¿6KIDDDDDDDDDD4M¢nÉDì‘% w\zèE˜¦‰DÂÂÑ£¿Âu×]‡ûîË=V$KÄàEÉMï%Jœ¸§ËrÕÏó½ïý¿ùÍ»aYžù¯chù¬¬pê©§ˆ)~»e¸Rl T\GeJÜI €‰ÚŒT™ y²ô©¥xáéªúV%TÖ­[‡ÖÖV´´´Ô`m‰ˆˆˆˆˆˆˆˆˆˆjÏ4'®" Ö«jË–ý#ÞñŽAhÚŽìt]—Ãç;ÿöo¹Ç&f‚A{„J,f¿Öð°P)•1MÏ<ó öïÿ5þþìËðí¿¾_^øeH¦„p8\“m <ýC†ä¨•€ëï¾)¿Ji*&LÒ<ôGa–Uõí*J¨hš†T*…þþ~ç¶x<Ž®®.ø|¾m """"""""""¢êÑõ‰§üÒu{‡aøô§OÅÖ­+püñ}ðùE0xRÙ×–$û5T57í—¨RÈ0 $ ˜¦‰ht­­Ç0¶`¾öï٣9jÈzÝõHªÔbäHÀXáìÏäg/+ÍÄ„ÛkÏ…{púY§Wõí¦\”~ëÖ­H§ÓU^{""""""""""¢ÚuOÜuN„@hjÚ…¾¾>lÛ¶û÷ŸEQð⋹dJa ÕUD’r µL]]×!Ë2TU…,G.€9*Þv2¢ pÔuà jžÀ±7ìz-Õf°f`ù³¦œP!""""""""""j$ª Ù‰‘Å‹óïëî>€%KN Â4… ¿EQòF˜H’=­W$bOåU˜`*]£E0 ¦iBÊÎ?6n‹Œš$ žpÝ«Á†.$’63˜ü¨&TˆˆˆˆˆˆˆˆˆˆhNÉð§÷²\ üO=õÞýn»æ†¢ ~ªª"æJ8èºý#ËökKž˜f~¢EÓ4hšæü‹ÅF ¡f‡²€ÈM½@m¦áwiµ)L_lZ5v§UTC…ˆˆˆˆˆˆˆÈÓ,ؽ_-Ø Ce¦Zqæ\/6ÍIgöu†@DD³,çj†ýÛ²,ŒŽžŽM›š¢õÇŽ]EÉ“ (vÑy1½×DD¢¦³³²,Ã0 X–Ó4aYÖ¸‚ó² à ÷ 4T¿æˆxm÷ßµx¥Èë†Ñð#T*N¨¤ÓiÄãñ¼Ûvî܉d2™w[ooo½×‰ˆˆˆˆÈ32™ FGGáóùê½(D쓚fÏŸ-zNš¦ÝSS’VÀï¯÷ÎÆç4°J4Ø 1°ç`/—Ĩ¥PvYdØóÎÀî+!WlWË.£{z3û3˜]'vcš}l±"½¦ëýDcQµiŒšÃŸDTKªj'CÙÑ‘Hº®ãmo»‰D3,Ë>O²¬ãÑ(B4* ×ÛËrñ×£ZdYF4u) ÎûÜ ßBîØ#Ã>ŽÕâø’tý˾O5GĈãª{U%m°ÑÕÄÌԀɪ(¡âóùàóùJ¥œÛü~?‹Ò•!†ö³ãÍÓÌ]Ô›f®×d,fß Ú½1M…ì†Y¶Tصk€×ë½3†ñ9IìF솹Qƒ° Õl ™,v"$»qEG.iÌ.ï ìD }b ×$¦W#W: Xåz®h´‘³Ï F"ÉDUÁø$¢Z’$ ³ÓþmY@"‘@ @këk8ãŒÜ”^’d'N “&}}vg÷ù–Û 'dÉèдƒìÄJ)Šà ä'däF`V“Räÿò§«q¨Òë‰Î3Ô©£¢„JWWºººff‰ˆˆˆˆˆf$“Iìܹ===õ^š… ÃN”˜¦Ý08h7 d¯Ù‘HØæÁ Ý`öcMÓ¾-;]·3E8 Äã¿0û‡¨0>§ ;a Fr Ãn܉dïW³÷‰FŸÂé´,Ø ¦Þ6–}1¢$»H$NÂÙ× dÿ!×0äî…[ØX¤d_¯P {_(ûwã§/Ñ‘K2‰uFö·–½½@rS‘IËCyŸDTkÁ QûçñÇ€ªªˆF£ˆD€÷¿ß>_Òõlwi|áyÀ>¿rwfqÛ»÷v\t‘Ó”œ))¬›"’÷ÕNŠüï>nVƒ<Ár7ø15Tˆˆˆˆˆj µµ>Ÿ£ºiR,+7%W4j÷| sñ†´µÙÉ“XÌ~Œªæ%ѨP·µå(€ýz‰„}Ÿ Iv2e.a|N’;9лqÄݨäN.ˆ&ì‘`ϱ²¯Ñ†\BÈM¡%OðÞ ä¦ ±²ïB.9q-›„\cP_Ö]4d N°|jv‚ÙmÉ.C_öyföoQ“¥ã§Y)sm³Z#ö0Æ'Õš¦ÙçO}ÙãDw÷OqÓM˜f®À|(”;¯ŠÅrçRnº>ñ{H’„p8\vTÊ8â˜&Ž‘âØWmä× £N«9Ft‚($¦ ¢:‰"/Nù%Äãqd2lÞ¼ñx[·nÍ»ßçóA/õI"""""š#ZZZÍÍÍ?çÀˆÇãœÞd–³k•ØI ÑûQ×sÓEèº}/¦ÓQˆ’ÃÃößWÏBYÎï)þÎïp8?™âDZk×.øç@•©Äç®]»00007goH ²âìröq¢1FÔ잯×ßmÙǨ°“%ìDˆ;ä¦ïêCnÊ.A$KDáøZNµ5\æ~÷(˜@v}ÈJ‘³¯af—Óp=·-û|-{Ÿ”}® »±iHŸ”ÆÀÀ8PÕôŽÉÆçáÇÇá÷ûçÄ÷yK2™D"‘@SSS½…&áž{ŽbñâG ªkñÿøFFÖBUU˜¦}~%λÄß5w‹À… À®ëÎT_“æ>Þ‰ 3!Š™I¨ö1Sï¦k¢)¿, kzÕ.x|¥Ü´iòŠùý~躎žžø|>lÙ²¥ª GDDÞ Õ{ &‹ÙˉLÿµˆˆêé”SNacPƒ#JŠik³M«VÙ[VnĈ,Û·kš}!®ªö…{_02’+ÚÿÛ÷E£Å§œ¨”TâÙï÷cÙ²eõÞ¤žµlÙ2´¶¶Ö{1ªKлAÃ-;)Оý=Ù†ñ9‰Â^½QصV†³gÿWaÎ²ï ØÉÔàº%b4N0»^âÿÂå”c섉 ˜Š½­Œ—Ðws5²ãßí‡777cåÊ÷á¾û¾]ï5ô¤ Àï÷³x=Õ…ÏçCKK æÏŸ_ïE¡Ihiy¿üe?`ûö¯BUÄböy™è”¢ªöÿ’dŸ‹#꫸išMÓŠŸ¹cb­‰ãðL½—èPQ+†+¶o¯úËV4B%•Ja``Û¶msz >Ÿ½½½hnnÆM7Ý„mÛ¶MyaÒéô¸!­­­ÌòyãsnÓuûD"ÈÍ·î%’dŸôXµ<{ã“hö8õÔS™Pñ(ð3¢Ç¢Y¢iù5HD=‘d r#BÚÚìé"Ä”bT‰4ƒS”â÷û‘L&뽞µlÙ²q×à OLAe!W¶ v2 ; êÌ1’˜™¢¸5bv2UUíWU{¤`è#@ìG€â*k·ï”V - ¨í€¹]¨íM°­Åµ‹ƒ99X"¡BT>ŸçŸ>>\ïE©¹F½î´,û;xÈ5Òò¡‡^Ä©§> Ó4ñâ‹i¼ÿýg8£…uÝþÞ®dp‰ªÚÿö·»|  ( ¤jà)˜¹$‡%jbf7ìºE§ûB°,üö=ïÁ©U~ÙŠ*;vì€ßï/yòØÓÓMÓJ¥¦|’DZsçμÛúûûy`$òÆçÜ&zÈ&ÞL¨Äbv‘öö‰ ÂÍfŒO"¢êK$r X,wq Øÿ˲}¡Ý×—KêK’ý „OŒgÿYx€wÕ{õ‰hŽjÔëNQgÎíñÇcùr ‰D@±XnDŠø®ä‰ˆ¦NŒ.Ú‘H®Gy(”K¢ å¦u(,ê䎑â"|ªSfM[ö”]ƒ°“"ä œ°{ƒŠiR]SPav’eŽuLì˜S¶ˆ9óÛ³£F‚Áܨ4ÑÐ&¦ê‹Fók æ7(Jî;Æ}jçî/EQrQ|»ûázo*"šÃñºÓý]îöÚk¯Á²,†p8 Ë‚ó3–eáÔS÷áúë¯Æ•W~¦: ]X,°§à‚W^y¡P ÅüÇsX±â.¨^JS#ŒO"¢òDïDQTÔ0r…áÝEß;¡¢(¹Þäîcž»“È“tØ=>c°(C°FD]ÀnD‰a|ãLƒ>™¦»’”›nO–íÄh__î1î„i4šû.£ËÜñ Ù· åžÛÞže؉A$VTµxç£9ÔLJˆf¹F¼î´¬\Ñ`PtŽ1pôè1¬]k·1(ŠÓ´“ë@e3^X–=ºEÓ4¨ª Ÿ/XþIÓ1Óçžbš±éŽŒ1`Ÿ—”z ìéF:¬çU”Péèèp†uutt}Œ¦ihjjšr–RŒvÙ´i’É$šššÐÛÛ‹®®®’ÏÛ·oº»»Ñßß_ÏíHsTww7öíÛ×PÙù©˜j|nÏ~êíí­÷*Ð4‰‹LÑo:µJ,ËB[[›“81 ƒƒƒˆÅbH$H$0Mƒƒƒ…B°, Š¢À²,H’Ó4!Ë2†² *Jo¾ùÆÆÆœÞ…ŸøÄŸá]ïzÖ®][ïMWsS‰Ï »»e㘨Ú000€sÎ9§Þ‹2cxžZ☠ªöß–e'O܉Ñ:2b7šF"ù=™8™ý:>c° …ŸSv/ÏìDJvRÅÝ@…Ý€Ñàý‰D.©¢(ö¹ª;æƒÁÜ}á°ý£ëösÄ÷¨X8Ê ÈMû7Ÿ¯äJ¯X±‚Yª)MÓ ( ”‚³çD"k®¹ÿðÿ€={öÌê¤ÊTãóšk®a2e–0 ûâ3Í/Ò6±X ±X ’$!8=:FFF ITUE,ƒ®ëˆD"Έ•@‰3š‘‘!ø|èrz·´´ ãÛßþv½7]ÍM%>—.]Êc'Õ8dákš ˲{»{…‹šY¢7¡¦Ù¢ö kè rÇ­‰’$²œÿúDžfÂn<(v>&й»ç\/ÖÛÖS{‰ˆèA,v"$È%GƒÁÜôZ¢~‰;™âž²khÈ~žøÛYey|CY% ñDDsU#·ÛF£v§Ã0¡i1 Ã4%$vÇM7UÍuÈ)FÓ4§M£fÓŒ›En Àž«ZÇ"Qx~"ìÅtG©”›òKaŸ×S|?E?=ccXtÞyUÙdn×PéííEss34MÃÖ­[óîóù|ÓžC¯¥¥%/Àü~?Ö­[‡d29«ªÉ{‰TU…$I°, ±X 022âüïnì=tèÖ¬YSïÅ®)Æ'¹)JnºΈÓ4aFÞÈèìì`Oá%’'€=R% æ„„ÃaƒA˜¦‰X,†¡¡¡²SwIRÏ?ó¿hp s"¡Âø$¢¹@…?¢'º˜ëzp0ô À&4ËɰGÄ0~Îñ€Ø uŽw >‘ 1,jE²õ\$É  Ù·…ù©ºsÏSyiš}ÿD &@ˆˆª§¯; #—l—e ¿?h4 I’‰ˆ™8&×»@´vvvÖft `O‘U(€êo·P:¡Ø }šïËþ®$I…=*&ÉŸ¿PȲŒ}ûöÕ{5kŽñ9sÄÔZõ¨§ …œ&b>PÀéqå•Wâ®»îB{»=âãÞ{-\~¹ŠP(UU¡ª*,ËB_6$’—†aL¹8|¥½=®¾z}ô®åµ/®C¡™ß†õÀø$¢F§iöT>¢§ºeå¦ùSõ åz¯»ÕòZ¶(‘ta_ÔºqföGÍþÖa÷–I +{Ÿ‘ý goWaOq`!7Ou(û|1´¸x!~iÑ[Qv½‡0˜}|ì‹L+û#zðufÿI•ìEóÒ§–ÎðF¥)Ÿ5‘ s'Îf°sŽ5"F/‹D§¦Ù„dÙNŒŠ‘d¢£¨éê[xª(ê”Sƒ§DD4Fºî,LÀ†Ï|¦‡݈G=Ë—‹‘Í•·ØÇb1§ÓuÝ„¬BÑZ!5£À>߈!7¥èT^£RbºRq¾;™¤Êïsláªo–)%Tj¡«« ©T ëׯ‡ÏçÃîÝ»ÑÕÕÅb¹4-‘HÄiÐ N!ìh4 Ó4¡išs›,ËhkkC0D´ %-†ôp¦3R¦iâ7Þ¨÷jÖãsæ¸ bÎÓ4!I’“h ‡Ã0MÃÃÃNR%ã¶Û^ÂO~r¾ô¥(EÁòå¯@UçCQ'9Y¨Xí¡Zøßÿ½+V,λMUí„ÊWÌܶ¬Æ'5Qï@$QÚÛíïìH0ŸÔOØ ‡‘KHÙ¿ äzˉÞ{"!!hƒÙÿ;a zòK®ûÈÕ 0]ï1”½MÄÉÙu›HH$`_\šÙÛÜ ”HöñmÈ]"ûX‘ØÄbD²¦=ûw=¹9¬‹ o‡=ÅP<á2Tð+û˜"mK?„JC =ñ9‰;ÑàQ£B鱘ý#’ îÄÈð°Ý+8°“'…µŒ€\Oá97’Œˆ¨Á5Êu§iÚI~ñ[’ì©ý`ñâUNM³G±TÂ0 (Š2nÊòš)Õ'uùhfB¹sâ©¿'»ÉD½˜öìúNg“G£À/~QõM♄ lÞ¼©T £££ðù|Ná{"7˲òj0tvvbpp°è—šišˆF£…B8tèLÓtê£(Š‚¾¾>Äb1çK1‘H L’$hšæô´ƒNCqa«ÙŠñ93 ûÀ>2R×Jä%; ÀeYÎçXÓ4D"'ñQ˜Ht]¾ü\ýÕÎÅïwÌÏxvŽzYŽyK½cF0>‰¨êÜIÑpkºþ7]ÿK`ˆäF6aþ1Ðy1\˜ï·Ö«€º° 6?;ñåìÿîdˆ¸°’åaº–U$IÄEžœ½=»aYBnj$öèŒAä’rI’ìDƒh¬v';‚®÷ɈHöõÝ£gDC,o±c¥{ûôsã/VUL|q-#—LAÁs'êIè.V^à{'zúC ²`7.¸?â³C~nšL3W”WLÕ% Á Ù wbÅ0ìû*mœ""¢ÆãåëN]πɔ@À¾­½]G__žyf!Î<Ó>¦M&±¯iZm‹Ð*Õ)BLÁÄôê¤UZ,°Ï%äΟ'“T£i'Kt Ò0õ‘1€½£g{B@Uê±PãZµj†††œ¤F,szÌ>Æ0 'É!F™¹!{"y" \K’äLéåæn4.v?`÷´D"ÎÐ>1­‘¢(X½zu½7ÛŒa|Öž$Ù|ØzϽP(Y–&¢Þˆ«D"I’œ‘(mmmÎgz"…Ó)Šý³jUé9FgÂ¥—^Š5kÎw{ üÓ?]Sß…›AŒO"rˆQ rs-‹©žÈM”p=GB®¦†‚ÜÈ q;`''†²¯'å^ßúW òK úÏ@(HÇÒù@ø‡@@¬Ã@ø›€õk@þ€‹LÙ#NùÄéYÀu»û"®ðZ6;9á>n›Ál)¼¯(¸OuÝ?Ñq¹Ôqp*€S8þ‹Z“y|{{;†‡‡aYÚÚÚœsâíÛ·ãcûØœj.„Ü4îÄž†Üè¥)ž?F"¹óÏÂQd¢Já,'â2JUë3]-Í<¯^wŠY˃Á\®DøË¿ü%$IÊ›Š<«ì5E嚟ŸHãG»õ!×Ábª9žÉÖcQ`Ÿ‡O%©2UQØ×ä¦Å-õØ乄 Í –e9ÉY–aY–“4‰D"yõ8 ò,##‰°k,ˆé¸bÙoDqAé.x]Øó°/D&pS­A4€}€¬ —a,s~¦i"81 êišæLQ7<<ìÔ‚$I84®„Š2½äO5<ýô|àã›Á ðÃ> à=õ[8"¢™A.ÁAn*Ñ;LŒ4rÉ QDô~`üEœû¼Éuþdš€%Û°ÒÕ€~–Û «¦ „oÉ>7{ñ#:õI0ш‰2&.†éÑ‘’3Å4M¬Zµ #Ùá­’$9ŒÄHTq¾mLÓ„išPíííìÑ×±X @—^z)N;í´z¯rÇ`¡ §s#Múúìš&‰DnšTYÎÕ,rÉIªC­"""¢I#%Ý¿wïÞ?ù“÷Œë<Ú JÑuš¦Õ·fÊDdØÇþf´nZ^Re•<£½§ZóELÛÛ†‰9šü— Ü3sÅÕ˜P¡šŠDŠ÷^ïìì„,ËNOz]×!I¢Ñ(>ó™÷âÖ[á4 ‹ðªª"‘H85NÜS‰çVLÌÁ@E᪪âC­‚Ô&Ù¯s|šÝ{DH"aÿ-@€\=QHŒ¾ N ÁÁAgÄ`¨r¿Æ¤b%+,^ÛEQræõ"¦Ÿ(fåÊûë·`DDõà>O1`_x¸¯-Šõ ÷N[å¦! 0² ÿD"W%Í}{uÈF"Î} §•'úúú`š&‰E®ëPU¡PÈ©¨(ŠÓ9IŒLÓÞŠsUU‹Å`Y¢Ñ¨s~Çë½ HpÏUä‹ÐZV®ÎI tvÚ±*F£ˆÚ}ÑèÄc¼ØŽDDDäfYv§€PÈ>®õõÙE1666îñbz°R ÃpÚ"g\%M6aØ#W-Lm”Êd¦ü*|ÞìöTQ°¾‘™Žpö}:³‘»‰Åìš'¸‰Å€N˜æŒÇ„ U•®ë0 Á`mmmØ¿ÿWÐõkûEq.þúúúœÇf»âÉä ¿‹‘&b®B÷ô\ÎEæTŠ")°ƒPñ4`7 ”ø2¹ãŽ;rsq'²Ï×\Rï­N³…eåF¥ôõÙßûßýî½øò—?éÄ„aΔ"nV­Z…p8 I’Æ%S„Â!®“¥iŧs‡í‹òÎNû"z‹È2 ËL37ÒMÔ‹!"šS ä×Q˜â|æi·ÚÇ"ñÝ æ P‹bŸÕ¨ù5׉äH8†aÐu±X ªªBÓ4§S„$IƒÎ¨I’œdÊàà sŽ ’$ö1RvF£›÷Û}nMub!WL^Œ&uy€\ç/Q˨ ]Ï%KܵMb±Ü¹še/ODDÔˆ Ã>þ‰4Ö¬I#}±Ø¢ì„K¡D"áÌ€Fë7KM¹)¿„>Øm” JVM$ì ã>ø"¼(wOá\PŒzï„ü)Õ¡j:Ó’ –(’Ýn+®wv™À’ìň$åê9Òuàê«§¹ã1¡2G‰9q'cñâÜç´P,ƒiš0 Š¢`ÕªUÙ©–¡¯¯Ïé%gYV^­UUó¾ ¬‡]/j’\ÁtDíÈeEM”î&æ sa‹ù†#(ÝëK; íösl_PÕ}Cs×w>ƒÿú¯3Ñ×gf{¡ªØ¿>î¼sЙ¾®1õ€¢É”Z‹Fíï”D¢zäbŽè-‰Dœžµbº@Ó´·ÓÀÀg`Y?r’)Á`–e!‘Hàï|çŒo"¢º…Õ§)³¿ÏEoöPÈNž çF  Ú×eTšHrH’„D"W´& !"‹A’$ȲŒ¶¶6v’C×upF Š©º€sî\xn n/¬‹6™Ú*Tä_cˆkq­f 7ßD/ÉN³¶ãULãÕ×ÇQcDD4û‰sÒ`xÏ{^ƒ¦ý9‚Ay„Há4—‚8'µfëѾ2iQØç "É!˜¦½a"ûľ°Íà‡‰Êß§;ÁaÁNê„Qü:DË.×dsSùªjŸØˆö\3lÿ#tLØ S¢ào1¡2YVn\¥ß ÿò/ߢ|†!AQ,'q"j›$ D£QH’”bÈNJ’ýAV*ø@Ëÿ¨Æù€² ö…„‰’=,µ3€ ø" ÁÎT–J°š€u' [Ùõ‹%!7ÿ`±ìia±¦ì·~÷ƒØÕþší/š½LÓD(rŽº\{í· i·AQüÙŸ­Áÿ÷!›_²žJ%±Uk¢d$Rº0i"‘p„ÚÛÛFïÎT%b½4MC"‘pjÁ(Šâ40™¦‰_üb‰3½‰û}dYÆ‘#Gê½iˆˆfŽ(_!Ó´/(ň1údhhâ©Iš{E¨C¡Âá°3ê°åbĵ˜ŠK$?,Ër¦µTU…®ëèëësFi»_±X Á`pÜÈEQœÇyá¸OU$:{ …Ó|ˆ)9²»]L +IÙ›ŠÇ"£Q&Qfñ#¢â»äÕW_­÷¢yŽeÙÇAYÆÆ†¡ªv›@_…s“‹6 ]×N#îaر˜Ýà18h7àÇ`wx¢þµü,BÀ÷@抷›¦`,ž`X«ߌLöÝòIÙ¹ÎåŠÇWªd#réÛaï @в×9¨ù… * Î4íäH©yo ‰º å:«éº˲ Ë2þÏÿyo¼¡à±Ç~†ÓO¿ÙÉÚêºEQœâÖnbˆ¹¸X¯„ö _ Hëa+uG-ö&yÌ5²MTì Nì·€‘*¸ØÃN¨LTÔ©Øö ûnÛ‡G8J…*#¦íÐ4 †aäMg÷—ynº)Œßÿ~·sðþð‡s‰y/·ŸH°jÕa<úè+ˆD–"ˆ9AíííNo[UU†¨¡¡!Ȳì4 ‰“Ñ%NdJ“eMMD"F^¡9‘pùÆ7¾QïMCD4³Ê+tÝþõDÝ®`µ&"F=Š&ªª"‰À²,g*-I’ÐÞÞî×DøÁÁA¨ª ˲œój¡X¯GNÁEE mm€³ãTUík,UµÏÁÜçˆ^>_$8#¬\²DÔ •$ÉIÒŠkkññrÊ)§Ô{ˆˆêN×s¹·H$‚k®±æ .Ų,§Ý8¢×¨,çFxt"7ÛMyf”è-/¦ò ìöÌ6ؤauæz?‰)KcÙ÷M3•’N$ìŸh´òdaÙÑ)°O‚"‘ñ£qj€ •Y@–ssV*þú¯ॗÞÓ4 ³StÅœ) ÄÅ ¦iðûûpÉ%'@×ס/ºKŸZŠ–O¶ o°oâ!p{³¿? XçÒC°çô.Ï‹é ñ =›½°ÂŒbE™$@>;·þNNgv"ŸTQeøj‘׋Â~ö¢x=°ÖÙ‰ßÂØÞõÞ]ðŸæ¯Áž¥Ù"‹9' ¨ªŠ`08nø©®>ðÕ¯žšw»Ý»¢¾Èî¢ô")$–_Œ"‰F£¸ãŽæÍëÇí·_„ßü¦×\ó.D£Q(ŠâÌá.æ%ÏŠ¢)‰Lrz’è¸áº¢Hïþð‡úm4"¢é0‘›Â«öùL û·ŽÜùTv9v‡"_ŸbÚdÀ>Öˆ: ##ö}ê ^oyE{{;‚Á s\ N‡Ñq€sßÐÐb±t]7²¤‘t!Çœø.Q<>´GŽYÖäÛ¨ºÄ4Öº®C–eçœUŒNßœ‰ªªyu ¯ŸE'ÅÂ:‰â>÷5Cwww½7Q݈i-ݹqœÜ·ïA躎ááa¥;fºY–…ááá¼)ÇÙi¦²ßÃ:rÒ{Ê«Dö§’Bò•šhÔ‹»§­®ÛËåÎ*E‘+VBù’›*ÁS)ûþQäêU_bGL`ž˜VþZÀùØ;´¯oê'9rö}-ÅÞî×âñê­g*£ëÈX®ìñb$S%×g¢§Ë#œŒoüFGÿ±˜†|d:;;aš&LÓ„$IùCÛ퀼X¿ØuûEZÀ÷¯ü>ÖÖMü†¿‚ïÌ „ý%3Ñ»˜ ɲcÊùî W8^B~CHGöv{;8Óʰ“*bžû‹M´!û±âË8ïœvvV×=Å—¯¡¿±ççõpc›Ì¨©é …BÎ…•,ËNM¡‰\xá•ã'€ý=‰gzÃ0ð­o-òeIÜu××Fï“H$‚h4Ꜭ Á²M[Ž_ýêrÈò)ÎúˆÇ”;±Ÿe9=Ф¢(¸à‚ fvcUƒ¡+þ(ŠÂ>‡Ò1¾@¥H¼Lp=¤ëö×¥8vd¯1³yj Qì]Lá ÎuûX‹Å`†3•­èP$F”ˆئimè$ªŠ‚N”†a_ãɲ@åÅT&T}"iaY$Ir¾/Ĩq›¨‡Àqí>g E§—1 Ùáa²êV™ˆÈƒÅ>&Z–Ýþnv[‰$²ü·ã"èììÄàà`ñç6º;5 jöö¦ŸT1 àa+÷&bŠ»±Xœ‹Nt/Ánµ²Ëddÿ/Öl²ºF½veصáVuí*AvŠÓ"Ç4˪l¾áJL¦¶Å41¡â1âd¹ÒÑIâü­³³xC"‘Èë)#Ë2~õ«›°uëñÊ+­8ãŒó²ñ8ˆP(Ttê.ˆ< ©ö N ëÌu¹â?EoŒÇ-dÿo)€TØËÒM¬& Ìõ–·£ö—€»!!ûžÆãYû;%ÌÏRCý¥a"ï‹ÍÜgÿŽFsÅVÇÅ[¹ †ýÛ\oß%¦É Æ åO©XÍ‹ÓH$MÓòæ:SQMµwª$ÙñmYöt²\Ñ*±XlÜHÃ0œú#’$Á²,Àï#ÞóžðéOB’$ç9CE*¹I’èý|Š3%!Py܈÷,JÓòƒVÓ ëÅ¿0%IÂÝwß=ý ED4ÓBÈÕwÝ6Ñ÷¾Œ¢µã,+W\Þݱn¶=ºÝSm‰&bD¤h5¸Ü “¢– €²ók³¨;Õ”i_ÓYVnºä˜ú{Ö#©MÓœs\wý#1…`Çxgg§sþ+ÎáEãšeYNý¤©`Ý#¢ÙÁýÝ¢ëº3Ú,‘H`÷îÝX¾|y½qÖK$²eL,ûG$SD§ÙÉ$¡E{ˆÑ‚ìtŒp'V Ûodß‹ªû1°Û,Eqv “«#bš¹-’œ®ÇÉ@0{Ì K×™ˆ1¢Áîl.³ë¡£ò)¹& å6¾h§qóF†K?¿§ºeBÅc*é”í& /ƒÀç>÷{\qÅoœŠè#¦ó'€íí@@½ÐÈ?Êé€üN¹hè³\ á\¬«&`˜€b"7„¬päu€ÏÙß ÃîDDv@ËÙñ%“’ƒÁ (hŸ½˜PkHpÕ8±–ÁOáoä¾DÇ‘a±µÁþ2Ùÿ%7ºÇ5*;G‚¸±›þkIA¬G"@0ˆæ^¨á'‚jAQò¾ÃÃÓ{½H$âœ\Y–…‘‘˜¦‰ööv W­!F’ìãh"a~+¬¯æô®Ó4ÍIê$ „ÃaƒA§x®¸ÀŒîi½dذáÚI-¯ªÚÓɈDHx–;S«lä\kƒ,ÛÁ 剭­­UÙöDsÁLŽÞ£‰òjv~ü0rVbÇhZAïäÒ‹D A?´ú¡µ¨ÑKrmÏ·šË|çîsD«ªý·8ÁL3¿ö ŽÔSìÄb1'Qâî  +¢—¹ªª0M³l¢d®ôü#p išæl˲‰DJ^P èv¸u¶ÛáÈZFSj)ŠâLÍWø¹ç´@À¹_|¾Ýõ‰ÜI"ò>qÜÓí¹;*ŠiõÄßîQcî¦"*F¢¹“«â·;É*¸¯‰Ýç²,#²{«ªŠ³Î: G­÷¦šõ #ÿzÅ®­ã«_}µâôâœÇI”‹Æ¡Jz·ËnÑ‹ß'¢Žˆ(a !¿Nè@*>O"Ú‹©|Å}Ó=_uŸWhÈ‚—`wt·²…ÜUu|Ï]˲—Ý0ì¿Ãáü ¦üÑõ\–kŽ`B¥FtÝŽÇÁÁÉfrŸÁrÙ Ã@&³Û:t¼ñâ«øéðcùrû€Q8e—[x>ìi#L¯±õ@ôtØ£9&hH‘ŽäþŽF³ópBf!¿¼ M¹$¥¢ä:–«*ì„HvB& {4›˜‹ìçD£¹mÞwG¹¹øàt rÛÊ4íi0Xð=…ý…¤Ö‡ëUûu-Ë~\{;ÆÕ`pæ#Ì&že^ÞHðÒß{Šjâ¿ý-^ÿà§ÿ¡¡#¦m ‡³>+ˆ·B±XÌ)Fó¦P‡šÔkVÒ˜©(¹éê²çoÎqW46E£QD"gº‚¯½÷½ø«sÏÅ7ÜwQémR¨Z M"ie¹âq¢nZ±í.IRÞ‰+{g…Bö—ªx’˜~åÖ €¦¢ï}ÖYgUeˆ¼B\#ŠÜb®¶Q.¶úúrçı˜wƒƒ¹)jÃa»Ý\Åy€8Š×ˆÝµ‹D'‹rÄyBµÎ’É$’ÉdU^‹&Vx¬ ‡M´·‡ðÐCCíKwr^–eû‚¦³³ò 1¯—¸_$UÂÙÇê~jf˜Ë5øæV¦0iâîx^m"É#â\Жm`M$ò§Þ=yE#T±ú¢Á{ŽtRrcB¥Ft=7U¥ Ó´?ƒb´—{”™išÎðeÑhªª*Ô#×áè™GñÁ}bdmäG<9û¤ «¡ÿFîÌ>$Ûs<° P Ø/j -Ì 1w0H"ÝSk™€Ù ¨Rþ´J¢aFQ`'_¤ì{jöÿ®”‡íÿÇmC1µ…àƒ>”»KŒ<(l#€g BÃoocñ]iÀµ×€e-ů½úé·pàûßÇ¡µk±;;’eYH$d4Ÿð[<|ìJ¼ãC'à…“þÚ£·ã¼'ŸÄ33ñ¡¢ªÑ´ÜþIÌqÉ»"t]wæT–$iÂy’§ªÒúI†aàÌ3ïÁÈÈZ<öØ›øÂuMØ÷à6üYg;®Ûû Ž~ùËPUÕ99 MÃêleù©\h&Óë1)ÎÄ6ŽDÆÏ –eÙ'ÏbDÑ“£Xoè@‰7¡¼·j»hB•$=ÍìÔ-âc+®#Eç'÷ý¦™k—³u½.‚ ú[ûÐe à$û~Ãî¹ç(6n\ˆ{ï=†Ÿüä(Él`Y@ð\ûõDc¨Shšv¢Et$INëaÿ(”Mª(vlŠc¥iæBЄ)¶-ÜßbHRîuE{þ]wx–ÐÙ ã’ëa¬XM²]Ñèø.Ú#{æ:ˆ4ïœà$4.ÞO’€‰:¸¿°+¼h½=Ec©˜‚Ë>¯J8É÷4;Á`Ði4™-I‘bÛÅÝP$ˆ)‰b±‚Á t]wÎÿÅÔCíííèëëC(B__"‘úúúœíeYÚÛÛ ÞùbÄŽ{TªªªNM³a×I³h°¦tä7BІSÑø˜@®RLû¡FH¼Ðu%0ò!@ú{`øw¨]ÃI¸RÅgX4œº{ƒ‹ø÷‹¤ŠH¢ˆïwt¢’ ØmìØ1£°Û*DbCÌ‚!ÃŽY÷cÜ ¢†™èPê~Ëõ<ñ¢}à í¢ž¬˜ÃÍ}›êZNAFî»Fü_,"¾ŸÜm4‚ Œ~qÖ­-Z„a 㤛NÂüùó±hÑ";v ûÏÛWy§žŽßþÏ,|k­ÅáÇqîKçâÁė߉Ï<öœöüi0dïßÿ~,[¸ ‡;Œ7ð~?ø{¬9i Þ÷ìû°æŒ58þìãÑòp àÄOÄë‡^Ç`åÿ]‰£CGñ¹o~˾µ pôèQ,\¸0·­Ùõ ºö ö—Ø7&r3¡ˆïTQœ[†Ý©· ¹ïgÑ&¥g_WÌŠA~rj({K|‰÷ï-þ˜ûƒû§ý¦Ê†áœUšL5`ÇËòä§,9Ca(z’‰݇åê©H è³?W• àÈ–¨j‘ûB✰¯ Š5\×£€oaB¥F²í–˜Ìõˆ(>èîÁ)z—‰ž8"臆† ( Úš¯Ý @â`Æã hȈ >ÿòÒÜߢ¤³Ó¾—ň1ú$;·^àóùÏr8ÑëBôfèàjDm ªjÑ4{ ûÆìO0ŒÏ6‹Qw±˜ÝäôÆIš{wÛ‚ˆõ»î:ˆï~÷5=ú“¼Þ㗿\‡ /| ‘ˆžíÙÂ}÷}ßÿþÉöeð¶ ÷¡é¡‡pž,ã;‘‰‰V®Ü‹o~ótœ¾b»v½ˆóç-‡¦KøÚË/×õ³F“çîÌ&>ˆ^×â3‹Åò¦Ér÷œ“eyJÅÎÊ1ew”0ÑÃÈõTýä'N¯½¨,#’Qû^+?Ä¿î:á/_i?GdƒÁ\€ˆV]±²îá§3$ÎVÉëlmYøðž=X#NFÊeqÂa—fì/‰ž“f˜û­`6#1¢Y$;Üê ›bh¹ý±óÜ‹Ñbij®Ò^ ñSàÍ“ÞÄï^<ןÁãÍã¾±û Ë&|¾ ñ®w½ ™Ì øàߊÏ|æ1÷«U˜ÿ˜…Ïo8Œg‡OÆÂWïÅü{ÎÃ)O¾ óßıc&ahÚaY®¿þV÷óUXïÀ¹ó~ ¾z¾õä·°ùÿ á忌°Ðgǘ¸xÌRä†}ÿ €+ó;A¸¯3ì§W£Ì>W4ª€#o¤žeXòVãÐ^GÛÅÇã‰[cåÀJ<õ®§°P=†/.¨÷'Á“NyõUX-—£óöõÊ%µ Ï)Åm¢ÏD£þf‚{êql §îäb”€Š/~½L4‹õp¦ÈâÜ!‘H8=êŹ…H‰b¨b”©x=‘H‘$ ‘ìÅ….~‹dˆØþ}}}ySœâEQœÆ„bEÁ}÷݇O}êSõÞ¼ž´æ¡5ÀíÈuîß©†ë6×éˆõ ÀZhŠÝ΢¬¢C€*¾¿‰†L¦hšæ$DB¡‚Á ó"Äô­î¤j0t:«K* …S¿6úwÍQZE®ƒ¨{Љf4 –yL%£ÇÜ}ì&šÓý±.–¬äòÒµ,f°`Hög]ÅX |XˆlÏÝl'Yç¡Ü¾)¼­Ø6tOÞR¬ÏHá%d±ËO÷ûŠ¿OòCIìKîÕ–8}±, ¡Páp¸dÂ]œ“Åb1\½d E‘ÁétŒí,‚˜&@LUØT´{¹:Í1ärâ>Qa¦1i2%L¨T“ûÄ8ìj$4È»€è•˜øÙ ›,8çÌ#øõ'Ä󿹋ÿý£ø“Õ?Ä[ÚOÄððpÑ^åÒkpN’¬·“#ƒ·fJBÈ ! ¢Ç¨aRÀ5â$ óéœüçˆi·ÅH•€èu!ŠÇ[€õx~‚D´×Š‘'â6Nµ`8éÉ'¿‚k®y_üâa|õ«oÁððî¸ã çÄý›ß\ŠŽŽ1þ¯ùtÞò–øë®5¸ûîáûß Á`®° è±+.NíDÕ:è:ðܼƒ¸èß[œÖ£h4 ]×ñ¯'ŸŒOÿô¯på•?ć?lgL0Œáéß|§Ôû³G“RxM&Ž¥þð£Ø³ç5<¸]dDÌ ÅÕº s÷Ö±ýè£bñâ—¡iQçbSUUôõõ9IÙ~2íÑ'.8£A h’´VÌž±E–yÙɈ>÷L9- j’¹Œ†{î 1?—H¾ý1Px‚[J$’m9PÆCéì„dP}"¶ï:´oúpÊ)°,`èú_à—ˆâ!¿Á¡e5®}Õ^V&TjOôž«â9—õ,’îQîc…ÑÞ^Ð^$òÅÇ,› ¹÷ÞgÐÜü&Z[—9 ÑⵃeC fŸïŠN ¢T…YÎ| ´Ê~ØÇùìq5èU94dá‚ žÅÞ½Oâ’K¶!‘Ðqsæf4Íÿ6N¸äDU¡Î¼w-éÿv*;„î{{N݃;ß²¿ùM«®Ææ5o@‚´ï:÷]¸öw}æ.Ü4ï&üÝ+gw˜ >zâGñë-?ÁgÞü Žþ×Ql¿w;>»ð³øîw¿‹®“»Ð1ÐÿQ?îÚuZ¿Òг>uûúcXY—¾ù~ú VH+ «öô*?ÝüS´ÜÙ‚ç.|ÛVoÃ[>ˆó?p>4MÃé¿;àÛãÿ?ÿïX°u:NìÀ/Ý÷5¿+ÿ~%¾×ú=üÍþó_žgnD÷kÝ8xô ¾tö—pôWGÑÜ܌櫛±{÷n¬¼y%.¼òÂz¢=é¥yó8ÿïXŸÔr_·Fnv÷Èü™ ’¢ÃŠEÀé€ :ˆ)z‘{ª-ñw(r–Äí9Ón†Ãá¼$ŠH&uvv:õÕÄ4]"9"Î9ÄÈ÷(ØÉtä(z®"²ÄÙó ç1bš17¶ªbõêÕ8räHÅï7—ì[½Ø‚ìB×g÷îÉnSco"·ž œx"ú~Ø”×yÄ>GÓóGã ¢§+;06‰ì½xnáPg±ÏÅAv¢×zvSn1P%¯£ˆqY–‘H$ò>·•ž'Ïú&ÅæûÃÝc£0®ÛÛqï'?‰ÔÑ£Î5‚¸f(œ:‰ŠHÀn³'•zÁ4:"fÜ ÷8)DW¡X‡`0?ö¦ð>›šðà%¹):îÚ…3ò<û쳀Ç㇧†ôI'9 ‘,Z„kæÍóÏ>‹3Î8°ãÊ+!˲3½óq_ü"-Z4¹õq}—(Šâéíæ¥÷YÐÖª-÷aOŒÆ-zž)F.ØupÞÒö¿ˆpÝu—½¯§3âQ0TÐî0™©<ÜÉ÷kŠ‘R*ìd ez*Ó]ä‰á‡¢‡‘ö—mG ¼ ¨A öQ@ÿ#@m F’öó_»ï5|çìïàºw]‡ãqß|ëFüµï¯ñOêßáÒÓAû¶‚ÁW³—ÄPG—ÀÊüÿÅô×¢ TBnHê*@¿Št•å\R5ήg6©jý#`<ß~øÿÙ»÷ø8Êû^ü®¶Œ-ydƒ¯‹aŒ …F²I )#° „ÆÉJðkR¬¯Ú4‰ÚݦÅIÜ&ÝMtÒã&=­ÖiEÓ´AÚÄ=äb‹hr!  ÂE 8à³6¶{¬5ø6úý1ûÌήö®]í®ôy¿^zIÚËì33ûËó}.º¯WA8 ¿p žŽ3àÝÔ)Qù¤ù'~Îà ðôÓoâ†ÎÁùçŸk¯}_ùÊ;‰–z^Üÿóøþ÷W¡½½@+W>‡ë¯ÿüÑ=ÿ÷[pß}·@’€¾¾»±5wê(<Oò`jšýói\ýBìÜ™Lä¤n+žIcÏ~!šÛbp0yŒUã°=÷_kÓ&!K ϶à¯ð¥jAiR‚Á t]Ç›oÊP”?ÀÁƒë¡(ëík/k˜ºÉßô†P(ŸÏgWB‰–©ÃÃÃè|ùo°òíÙè¼jVˆ1²^ÑuMד“$X™A{ùâ:1H~ßÃáY07ÿ7üÝÉ¡:C! \“Îêzr¬LѿÑL“‹£ª¦^„vt$']È4)Yâ #É2HÏ5¯‡©9Zø2ÛÂ…åü:P.&¬ < sRECòâÏÌ3ãp2çÏY@ðÀ\žZŸ ýÀ,À÷Àx ÀÀ7˜ìí)r€/áŸ8Šhô8-Ú‹·w]‰×ÎÃëï‹N-Âñ3gcñ² É|/ŽŽ?‰uŸ=²¼ÞvRQù o ¯°>XŒ-¦nB7¬+p1ìˆišx×ýïÂÓWÆß*‹Ù¯ÌÆÚ~„{–߃–†œùõ31÷í¹¸½ý(–þö¸åÍEøÈG>‚}÷Cø‹…ÁÀ ÚÚÚ (Š]™zçÏï´ç1¸ï]÷á3¯ÁÝwã×Ë÷=ú¾ ›võ·VC KøâÐñÚ¯aÍåk0¾j7j7¢¡¡ »×Üp ޾x_‰ã7ŒãžŸÜƒû6݇ÈÖvÄÜ·çâòÏ]ŽHÁ‹G_ıûá­·ÞÂÂâÌ3ÏDss3Þjx ŸÞóiDÅ]gÞóM¬o\WŽ¿‚_Üù üÍþ¿Á=÷ÜÃ00W‹§ýO£¤Á`_íü*ûqãÆñOûþ K^Š—×¼Œð k g«û“'OrœéÂáÌC" ¡Pò4P)¢‡¤¨DIY–ÑÖÜŒý³gC¾â f­D­å S1¬VGG‡ômúúúìÇ»»»áñx I’Ý{D ]&Ö[ô8º‹ß™ZL:çWË™$ G¢#e‡‹1‚•¬b<^!Jï&Q¡.§W, ‰Jùë®»óæÍ«ö.ªQ&ô'»-fIR¹Æà]±žuo&ºõ‰E˜©Û]ÓR¶ˆ×ŽdXúçH~GÄ5›ó}¢qŒ$á@$‚Q¤ǵúç?ÇÛ¯¾ŠñÇqFs3~vÓM)óˆkVŸÏWÓñ<~äæº\8½gÝ£«áÄ \úÑâÒ%Ký幸é–Åè¾áJ ‘Ü´ˉÉêljÒÏ+ÿ¸#‰›!†ÅÍV¶ç16=zÞq>Ÿ¾ÜLŸ#ŽgéÇ< y<Ià\Ÿ#–“©E‰s¹>'{œú<ëãpêôiPù‰!’Å¥Ðà÷ÿŸäÐ¥bø=ÑÀ=1tÛC×=„íýW|ûO¿ 4¬~l­’Õ›«Ôv²EŽVô$ “)uáŒññññjb2ºººÐßß_ž…éHŽ·(ŽÝ!Àp¡M€~60üϰZÂ'~‹á§Äø‹&€6 ´ ð.0˜lôèGN¡íºÇÑxºa#ŒW_}{/ß‹ëÖ^UUñ¹]‰ïyǰðóÉÊÁpðü+@yVBåN ˜mœõ B¯¬†ïßÏI=˜ûý0‚a´ŸùS( ÏÀ{ÙCPõ  æçóC1È'þ)9¡IâÜôx Z¿÷:¼Á»ï ÐÞ ýôUðŽ8ntñO} 8~ü8¾tè/ðdóJ<ùâJÜxãa¼½ÿa,=<ÞS=8ÿÚkñ—/¼€?üâÑÑѯ½>øþò/7â®»ÆýÑGñ‹_¼Œ‹.ºÏãž{–[‰ q‚Ôu„» F|!d9QÑú£þñ[†¾ é}—CúýR÷¥˜i\Q`.mAûOýþå,±8(aêÅ‡× MòØËó¶ˆk1É4Ðöî“yó]¾6.×A ìæäiĤl===Õ.J MÓðÆçà‘GvÚ“`:ÇÄ=¨³–¸®+´#„®ëö°÷¹Ïá›W^‰ØSOaÏž=xÏ{ÞƒËûûS.Îüw¼õÒ—¡¾µÃz ½ò$¹`ØÁZDmš¸7ïîN¶ø/ôíb82{Aé7ýÎÿS^\:QW$ê‚Dg1„8LtwÃÆJÇX‚Ie=GL#%o1$d©ÃˆV5AÀøú`<€t P>(Ëü PV%Þ'¾&:€à¥k^ÂÑK­VÑ?Œþsžƒ›÷ÜŒíg?ß<…/X‰+Öý GŽ4>ö±&\óýkÐð,ú´c´µµÁçó!ØÃ©(Šb'_Ãá0þqÙ?âç{~Ž'/}>Ÿ?úá× øÙØÏpýõ×Ûs%8'õcO<ñüʃðöy!Izè!Üwß}øô§? M³†ÁtÝ`ÂÿåR«çˆZðñÿ%^z髆s _4-ãá®d"i¨iB¡=\,ËöyQUÕÔïߟ¹µÊÃ8ˆr°çZIÑA$3Eå¦øÎ‹×‰‹èšUúx€ÖJýßÙ²U×'&:üþd«!H­¼ “çWñ:oZ¥¼¸–-ópH½½½p»Ý¼¶M‰D°ïßÿñÝÏP‘'z)Š•ôœêaøD<‹„‰–¨Äuž£Äu¯ IïÛ‡eÏ>[õ˜.a…“¸".s®Àÿú¯XûÐCxûí·qÎ9çàøñãxçcÃÏW­²ÏïúŸÿÁøð0.üЇðÀ ³³ŸÜ·@ÀnôÔ{ç¸gÃÜÿý¸å–[02¾\unKqüÇKçÐf™†âËHÔÜ-ÝÝøÚK/á/|°Ú[¾ætuu¡ÿÍ7áŸóÐF­Þ}}ÉûÑ-½­—¢¤öˆvÎé $w…¨š t„7Þx¢)üK/½„áá¼þúi†„S§.ÌŸ?—]vvᄌûî00ð^=z hhh€ÇƒÄÉ^ÙÎ|8`õHíÚÔŽl¢üÎ÷ÉÓ‘Xo1Œ¨˜S’’Ëë62bÝ_‰öqÖ{ÅéH|N0hýöù¬¿EòJ´µmd›@±~â0ÚÞný=û,øþ`Ý"|aö’£'|ÆÑ©0U;ººpù½÷NœOGrnœ0R+ƒ°îqe$çäÉt ÔŽìÃRͪĵ-*B7’ØH°2›‰ §ü¿䛬D¦çç>cUHöþHC·ûÀûÉa|ð1¼ýâ7qÞ;Ëñ÷üww¿ƒw-^œÒ½»¹8%oÔ4 ðx {ûìð<ó%H'ŽC;gÂ/®Dß?žÌz#%škšuò‡;o«£Uhbh!çð —/~þæîÓxGVðÄè1ü×½†o|ã»5­Çã±[ò‰‹Fqùàƒ+ðÈCo௞ø.Ûðn4‹±‡Ò[Õ%.Ã÷½‰àÑOÁ<6+ÙÚ²½=Y{¨Í6ëý@`Ù7Ðýßk`ž¹»Û:“¬8WÜqµãÿÑúölû"ép d-W¼.­û‘ߟœ Øž×æSq ?Ú8aó¦3³Z©,-¢²hñâO`ß¾wáOÿt=¤F!Dc'ñµ €ÞÞ8-:·Þ:?üç¯àòæ•xåÿ†ÏÝx1zè!œ÷oØ'ñ3_z MÉ–9ZŠ‹ÅJϹ)’"a(.<Å=´smñxs3Pí³…(—8¦Y½m¬0Vü›s3¡’YIÛ¥É Wz lôwæ /Bà½ðj€þ§€â$Ñ»21¹§é±Î7«ï\øƒ@Ç÷:0÷Õ¹øû÷þ=N_uÚNˆÊEQ éRòØ «AƒŒäD“#$¤ ;$twwÛÿ_òÒ%Xµgö.Ú S51::Š /¼­­­˜3gNʰ>ƒƒƒvìÏ>ÿ3Üý±»¡IZʤ¹å *„EÂÄëõ¢­­Ín¹.*À¦Ûd¼µrލE]]]øú×û3Ž#æK)U8N©p}"ÞD+é¼I4Ѱ 󉉡„DùDbÑ{dppÐî5")ttt ¯¯š¦ÙåwƽX^EZÔû3tÁNßÎÖî&#ª}¼¶Í,ßqKL['†F®-­•;†OUU{˜:À:3 WEe+²/îŽ9‚×Þó,¼ã;ñp`Ë\òÛßb쥗°`l £³fáŒP߉DìãÄgfÍÂ;/¼€¦¦&¯&çô2“óF$ êêüê÷ãßÿçp×ÃW»$5§«« ‹õÛëåLf¦o)†`sÎM%8"ÐÌò½ï=ŽgŸàÞ{?]í¢Ôœ‚ï=s:›kö;€¾A@9œŒœÄgg}Ñèqüð‡[!uKVý«ü°ZbÄyç‡g—-ÃUCC…D¢UÌoâ±Ê3ñ¿ŠdzÙçI¢šU‰kÛšò+‹!‹ÁårÁårUöð‚PT‰Ö~"€מf7 {o¢´£PGC1:.–¹y3bO=…¹»vaûïvbÝ'>lØ`wE“MÚmŸF·Dì¯^BßÇ~} ÔOZïW$ÓýŽÙÜÅÊ’è¹ÅìúX©9[¿š¦ŸOÆŠáG?r¡¿ÿ-Ú ÌyÓn­äooÇÈȈ=Îs8†ÇãÁgþIƒ¢¼f_€¶¶ö¥´VÌ&¢/,ÄûîÈþ"ÑÄ#„ÇçƒÇs amVòæ#ÃpDRÊSŸï–Ľ©’!=,”(«W”÷;çZò¦<ŸNÜ[•ÍÀà`#fºŠÆ§«²T…•Ьݔ6jÊd^@²µ|â$Çñ•Û:püøqüà]?À'Ž}ï~îÝ8}Õiüüñ³ }^Ì΀õÅú²|Êœ“h¢0ÀŸ€Ó Nþø$^¾ðIÜéÄÛ'gÍZ…³¼Œãw|¯ÄÿkÏèÁ;÷ÃÂóša¼º¿}û›ðü×¼»á4.ÿ÷óáÿ 6ÞI¿ý^HÉUñþ0þÿÄÕÚáHâfb(ŽíÓçØ&Jâ1¬ãVbÈ"»Ëk–P•åÔKV_İà¢qmµ9‡4’ ãáaÊä+õê]EâÓ€_€A@7€°U Ô ˜ox²¾n^L¨2ðÎ?¿ƒûÿx§}œûô°9l%Iιä¬o\Óÿ÷4\Ë\ø¿ÊÿÍXÓ4¡A³'ÙD}Vå©i˜0drX¶orC¡];<< I’àñxà÷ûáíóZCJþy{õ½øøÇ?MÓpàÀ»"JQ{øH14|¿õåSQþ›dg…HòޤuM¨‰Ê°ÉÊ7”Ä4VJlfºÿK¾;›ô„‰sxÑ2]’¤¬ßãR“"¹!’"bq])z‚ˆгQŽ˜kEôIƒ"&ÄPZbΑŠUX¥÷BIo¦š+ÒêF9Ï~ÿÄyh‹áŒUÃ0R*pÓç.ñù|ös}“™X·š†ßùàĉX¼x1þß`õw  ÁëõâoIJeËð /à‚ .ÀÐk¯áä—¾dt]ÇŸÅbØ»hZNœÀ¾w½ Ñ'ŸÄü³Î²áY³àý·³{™½%z×Ì™c#Š=^¥3êîüª(8ÇŽÉ/§NŸ¢÷}©ÉÓ4‡íó”¦iö÷Q|WìºzûîPÅ-]z/½t¢ÚŘ¹ïôÃnän¸ß§åàÄm'ð«ü ë?¼}›n¶îM×… É (I–!ƒP¥økYqÌð 9¬5{¡P5•P@oo/Z[[1::ŠžžtvvVæÃD°#™HÒbÏ0eÁK€ödÓÄ÷Þýkü×.ÄšïÜŒWŽ4ã⋽8p Ÿk:„ß»l.nØ€«q{è;¸=-ÕW¾ø¸%д÷!º¿h]|K2V6ˆ hÓÔáõJ‰Vö³ðÖ[—âÀèºÛn±×ÞÞžÒ’OtC^¸0Ž%KŽã?ÿS`ðÄFLX&.ÆE«ØôÉ ½hÉŸœD3|G·òb+l‹yýdFCÃ=Íte‹OÑÅÒ„k‰ù„Dëu ñ¸„äzNâ5*0zl£ŽÂ8m`»¹ÝzZ–¡Ê*.~áb† LôAþsœ@9ròÍwÞ¿LÎIdÊxâòÏãþ„×ëµâé%´·¯Äàà B¡…ÿÏ¿†—ýo¸öÒq<µt)®Þ¸I_·‹u.™°ª¦ xÿÃ1L¬žìž¬'&µÖB€ÞR, H¤ƒD}ŽØ¦ã·H¢H°']ƒŠä„fAÇr°ZõÖqO$’ÄO"e=‘(–ž\®½ÚË ;>Wì79ñ¸xMzC^Ñ}VÏðza¸°ÏQÂÀa±­ÚÏ?Þ\-¿Òð¥9׸Ŭo“ŽOÉá.ÃHŽãÚmý¿PÌä$ØÞ@¢Ó‰cxbÑÓQ´ž5MX¨qê§Uø¤Ì㯛¦‰P8¯âE(‚ªªèîî¶ç.I‘è-LŜހ5|•¨Ìç4ç²,£¯¯’$Ù±âÇ„e †&&Öúwt¤Žqíh02Lŵ­ˆ;@²‡W©-eE+nQaë¶&ãW¬Àï¾ó,öxìkO1Œ¦hñíõzíòbþ {#‹.¡â#8b¨ŸôÉfÅ#‚/Ò¹Œ¶¶Ô‹Õô!¹Ä¸$Î÷uÕË„ò+%>jBGGê(S}}Éáa ¡i´D/&["Öœ±**m‰÷R‰s¤è‰™Ûbø*ǃ¥ü æ_}5ž}öY\rÉ%V|ùËöëŽ<þ8šOœÀÕW_ýû÷cÖÕWãàîÝv¢V–eÿäOàõzqP×±\QpWZÃtW¸%í1qÍ Žâ±¦õœ.Ù( ¢K–`]µË1J‰ÏBïÙÓ¯Yä¹É™¬›òd%Q(ëµ­¨ÓPl "t› MW ¿x7ý=ÚåÇaüÐÀæOlÆ] þ6¼Ö¨Àõ ‚‰¹þœ ∦JM%Tz{{±uëV¸ÝnD£Q¬_¿n·»ðŒ§h±.#Ù‚[E²Â€±0~t¼`Ýõ©ãóK …¹ïƒ„††g02òAÜ÷gÿ–îß#GŽàU— K®¼_þØ²Ä ëMà,/ÐÑ È+(ÍÉ¢%Zå‰yÉaI2ßW_ýtýoR†3D0´»$‹dqamšn(ŠbW¥·ä«Æ…¦Ï—yjªo%ǧ àSð á‹AþýÛÞè'€Áí@ðãÀ™šå¹ßÁ#/J­ÔЬ;Ôï,ûïûþ{ë+xÒ4a@KËR|`ù[¸äðüÍø˜{ô(ð«7 üéjèº5ßüÇÃX|øbüøüOáÀ;ïÅ‘³Ž/øpb"zǃP(„¾¾>kh!I‚Ïçƒ$IÖdŽ‹é‹ñqÀÕn3qï+ê_Òën€Ô:žŒÉH9í·3Éä¼fp6˜ÍVo¶;ËßÙdºçu¶ÔP x_!-;&û9&¬ž;²ãͺÈ}øê§?oP„zWr|ú܆9똷^ãÜ; Í Ðo~ þ'WÀˆ6B}ß›P®_hÏÛ ZÍ:ΛPC@jŬ˜ç@´` ƒèëë³+“DE8§¥÷ÔDƒç…s¶JQñ2ÙÊ(ÊBŒ»'¶z…ó Jžd2ékÛ4é•@"É!â!Så3Ñ"†rÆ èÁRæÉ ™ ¬ø[¥ª˜³l–)Šuí©iP% …¬ÓQ(”5Ña?’žè’ƒÃ é‰1)²xO¶ä‡,މá3bkš¡”øœ3çdÆ!½ÒOWÎó$:D8_Šùz²%<Å9QÌe%~;“—Î×ʲl8 zi¶··Û#ˆe9ß+z¬‰ø–eØ· ’d_ï~¹€m¹)ñ[¬‹hÜÀF e&ËxféÒj—bJ”óüélx êeÄ5ëtém"ÖË9Ÿ˜³îI$TÅÜ|ÎcŠ8Ö8ë«Òçr.˹½Ä㢠©s’8oP2-+ÛòÇ9Qæ<žªªj¯»(³X–8f;·Kú18}»‰õ+¯¼‚ãÇWû«Pq“ŽÍ €Þð5ðŸÉ¡»º—y`þ ï|–EþC^ˆÁÿ89¿rGž¾òrÄoþ"~ÂL\³¦ûJ4Uj&¡‰DÐÔÔdgÖÒÒ‚––D"‘œÙÎ={öß4`nþ!ôÙq¨³~ lôª¸±ðó0†~l‚ï€wé1ü³ŽÄ¸åÀ¡C‡°ü¡§0ôÍ%xçôi¬‚†ž¿/¾u=\®¹øÄ'þßø—˜;w.nJ@ä ªuAªÃãQá÷øÐÝÝ Ã¶[Ù¦¨EЋƒö«¯îÂ?ýÓß¡¥¥eÂpƒuVÑÛÛ;-ÆDŸ.ëQ¥Äçž={püWÇ¡}é[ž|Œó>õâãðý1 \ïÉ_í„igœñ8¾ùãáÅ#ûð…†ã8q¢×_ÿ·xöi–Åã˜}Ök8ã 7Þwå.\rÅ­X¾ü–,9Ž7O>‹_ž{1~³ÿi\yÓMxðÁqÿ™ °ñpà 7àĉg±dÉûñÜᓘ?¸è¢‹pç pà ëí²ŠJÙôqpÅï©ú.T:ÿ900€ÖÖV´´´T|]*-eŸˆ^:N‰ùæ¹çV»¨Wj|bƒŽÐÀv„|ÆÉuð-;#h}ë#€óOFpÞ3qäšWq{C޽ë]$ sæÌÁ§÷îÅYg…‹ÛÛñä“O¢¥±w&†û ƒXÕUhxæ8ÿ|,Y²mš,@ H¶ž°Á ý{B%kúœ‰^ŽÑh£££è¼æš‰“D;æ(œóAL¦•Þ“Â4­ÏÎð9–á”^V1&¼s†Sçkt}âúx<èÇ“ßéP(ÙÚÃ9£f¦mRÌç¤Oz %"b=Ó‡ÜlkKÝŽéŸ#Ê–8~F£QŒ T®‡q)õÚÖÉ™<+W®Äå—_Ž?û³?ÕW^i¡#æ …Bv%³âÖY‰*x½^(Šb'/ ©üçÆeùHêÎa±ü÷/~KOžs *k8O¾‰Æ*p2.ׄÓé:`²Jφ†)_1›¢±œˆSI’ÐÜÜŒ‹/¾—]v®»î:;^½^oÊxΡ¾Ò“"â>Rô qûåœ+E´Ð Äý¤ø-’­¹®më1ù1¾ÓÓå8S“=Š^`º®#bõêÕ8ÿüóqË-·ØÃJ:ã @J¼ˆ½ôßéÉL¯>ŸÏ!Ä9÷W¶÷ˆaÄ2}Ž×ëÅ׿þutuuMxN3SÒTôòv&DQMÓ I’ý± çñÇùQG%ÞÓ××g×kùý~{¾µô÷8?§¯¯kÖ¬Áw¿û]{½Òºù¶E)Û/ý=ο=‚Á ]FÑDÌcèüq\÷x<ؼy3n»í6Œ¥‹Å§"¡òꫯbïÞ½ÕŸŠšTlš€qõÃÐ_»ÁÙ=ð™…iµ•ž:/†Öí„_û)ÔO|ÂÞ—Š¢ ££Ã>¿©ï?ŸüdY׫ÖÏ%ö=o ß_ÍÄsXÍLJ¿mÛ6D"‘”‰ŠºººÐÒÒ’s§Ü¼êf<ÿB³gÀ!¼7Î\€ùóûpâD ŽéÀœ9ßÀ¬YÇß 8}úy,_þ·xýõ×qÅWàÕW_Ecc#Î>ûlœ}öÙ˜7oàÊ+¯ÄŽ;°nÝ:ìØ±ûØÇðè£âÚk¯ÅóÏ?åË—ÛehhhÀñãÇS+Öc=†eË–aÙ²eÕÞ“&¶[½+d={ì1ìß¿===¸ýöÛ«]äŠ)%>ï½÷^¼´õž|óV å[û–.]Š—_~gŸ}6Ž;†ãÇãÜD…·$I8uê.¸à¼ôÒK¸öÚkñ›ßüwÞy§½/öîÝ‹ àСC€U«VáøñãX°`Ž;† Tdý§Ëwz&gŽ=ŠgŸ}ûöíÃÃÓ|âÎRâóÊ+¯Ä’]§ÏœIáøñW0>~ccc0MóæÍƒ$I8zô(.ºè"ŒcñâÅ8yò$ ¹¹‡Æú+°ç‰'ðž÷¼¯¿þ:æº\8²r¥ý9M‡á=>šòÙO^{-Ʊzå#¤ü{V­JùÅóϧü¤¹c `ß¾}Ø·o<’4á5™>g~¢Uú‰†ìYµ ÓÎÛÙ>ǹ>óÓZ¶§—uÑÞ½˜íhv¢¡!åsf?ŽYÇŽMXgçwºÏI/kúçT‹Ø'«W¯Îùšçž{^xá´N£ÔkÛk¯½ÑhgufÍš…E‹áäÉ“X¾|9š››ñüóÏcݺuxôÑGñá{÷îÅòåËqèÐ!,X° Õ^u3ëœS/ Ù'¼¶ÍŸ<ð>ÿùÏãå—_ƬY³püøq,[¶ ¯¿þ:Z[[qàÀ\yå•öˆâ\yíµ×ÚñúüóÏcÕªUØ»w/š››1gΜªÄìLúN׋B¯m÷ìÙƒGÓ®­¦›RâóCúvíÚÓ4±hÑ"œ8qëÖ­Ãã?nŸ3E,^yå•’õ8οÅýdµÎ¥…\GÕ‹érœáµmÒd®m—?ÀïÎ8o4=Œ³üóæ=Š_lÃÉ“sÐØx?.¼ðBìÛ·wÜq~ô£aݺuxê©§på•WNª®µµ~.©‡ãB-ÇûsÏ=‡]»v•ýÚ¶fz¨ŒMx¬.c7ýÉMh|¤W_}5:„9sæàر³ìÂôáüó—aéÒ¥xî¹'pùå—ãèÑùXºô»•©££#å÷m·ÝV±õÞé`º¬K!ë1þ|9rdÚá[J|ÞyçøÎéïàôKÿ„w¿ûÝØ»w–/_޽{÷âŠ+®Àœ9s0oÞ<,- ÛºˆÁj™Ißéz‘o]Ž;—Ëe'¦³Râóž{îÁ3ÏŒàâ£GqÁïÅ¡Cbùòå˜3g®¹æüæ7¿Áå—_n72ÈE ’­Cÿ©´sç„v?n7æ¦=´,Ãkr>àTÚÿ™>G¼æl+?Å~NºB^³²€×äûNçÛ&…~N-xíµ×°råJ´¶¶V»(UêµmGG^yå¼ï}ïËyެäui9̤sN½àµmR)ñ©( n¿ývŒáþàð›ßü×\sMAŸ'âõÆo¬öª˜YßézQèµm¦ïîtSJ|Þu×]8pà.¼ðB\|ñÅž1XëçÎéd:Åg>¼¶Í­££O6ün¹îœ:u sæ\à6\pÁX¼x1öí“SΧÿøÇí÷M…™ô]­”Zކ˖-Ãå—_^ökÛšI¨455Mx,‹åírõ¹Ï}® åß|óÍÕ^Eš†jù QN¥ÄçW\¯|å+Õ.:Ñ´WJ|vuuå\æL9¶UR¥¯m‰*a¦ÿK‰ÏåË—§\ÛΔmE4Õ*qmKD“7©k[^ÞR•TêzíÌj¯˜ÐÒÒ‚X,–òØØØXÉ“vQù0>‰j㓨616‰j㓨v1>‰jc“(©f*n·cccˆD"¬Iwb±Ö®][í¢ÍxŒO¢ÚÅø$ªMŒM¢ÚÅø$ª]ŒO¢ÚÄØ$Jª™!¿ §§›6mBkk+FGGÑÓÓƒÆÆÆj‹ˆÀø$ªeŒO¢ÚÄØ$ª]ŒO¢ÚÅø$ªMŒM"ËããããÕ.„S,C,ƒËåb·1¢Ãø$ª]ŒO¢ÚÄØ$ª]ŒO¢ÚÅø$ªMŒM¢L¨Õšš™C…ˆˆˆˆˆˆˆˆˆˆˆ¨V1¡BDDDDDDDDDDD”*DDDDDDDDDDDDy0¡BDDDDDDDDDDD”ÇY_üâ¿XíB”*‹!šššª]œœeŒÅböOSSfÍšUðzT{=ãñ8^}õÕ¢ËV‹ë•i]&»ª½jQ½l“é°ï³Åçdãoª×-ßzdÛGµ¶õ ^¶I½ïûRÏùžŸ.çÎj­ M^4Åìٳ˶¯§ú{ >/ã‚ .(kY§b] 9_º\®¢ËVKûˆJ“)6úÚ÷¹â³Ö¯m 9ï—ŸÕ^/*Râ³–öýdΓ]Ïr(5>k}½(¿J^•[¹¯±Ë%C×õŠ\;×µñ:uÿý÷·µµoذa¼­­müþûï¯v‘2úìg?;~饗¦ü<üðïG-¬ç×¾öµñ¯}íkÏU¶Z]¯Lë2™}T û§ÖÔÓ6™û>Ówz²ñWuËvœÉµjq=j]=m“zß÷¥œ;ó=?]ÎÕ\šœ—_~y¼­­­lûzª¿_ûÚ×ìÏ»ñÆÇï½÷Þ²•uªÖ%S<¦¯×G?úÑñ±±±ºÜGTšL±9>^_û>W|Öõm¶óþdâ³Ö‹&¯”ø¬¥}?™sçd׳œëPl|ÖÃzQn•¼>*·r_c—ËèèhÅ®ë]Ý&Tœ_´ÑÑÑñK/½tüå—_®v±&ذaÄg1ëQÍõ¼ÿþûí “L'Ÿ\e«µõʵ.“ÙGõò=œJõ´MêyßçúNO6þ¦rÝògrí£ZZzQOÛ¤^÷ýdÎùžŸ.çÎj¬ •‡¸!rîûzùN¿üòË)Ë¿ôÒKÇGGGËRÖJ¯K¶xëå\o¼q< ÕÝ>¢ÒeŠÍññúÙ÷ùâ³–¯ms+'ŸÕ>îPy”Ÿµ²ï'{îœìzNÖdⳖ׋ò«ôõQ¹•û»\œÛllllüÆoß¹sgAe˜îqP—s¨D"455ÁívZZZÐÒÒ‚H$Rí¢e,k¦ne…¬Gµ×³µµhii)ªìµ¸^ùÖ¥”}TíýS‹êm›Ôó¾ÏöžlüMõºåŠÍ\û¨ÖÖ£ÔÛ6©×}_ê¹3ßóÓåÜY ûˆJÓÛÛ‹––´¶¶ÚÕÓw:H7ÐØØ—Ë…±±±I—u*Ö%[<Æb1¸Ýî”Ç׬YSÐzÕÚ>¢ÒdŠM ¾ö}®ø¬õkÛ\çÊÉÄgµ×‹Ê£”ø¬¥}?™sçd׳JÏZ_/ʯ’×GåVîkìr‰D"ÃÆXñ¯iÖ¬Y“· 3!ήvJF'ÜÄ755!‹U»h)ÄÉgóæÍˆD"hllDOO:;; Zj¯§8ðdç.WÙâñxÍ­W¶u™Ì>Ê·ž3Qµ¿³Å¨÷}Ÿí;=ÙãÊTïÃ\Ç™\û¨ÖÖ£ÔÓ6©ç}_ê¹3ßóÕ8îTâÜYÈóT{¢Ñ(†††°}ûvlÚ´)åñzùN·´´ ³³÷Þ{/Ün·7zµ~m›-Ýn·½€ŸCCCöÍo=í#*^¶ØÏÕ˾ÏŸÛ¶m«ékÛ\çýÉÄg-whrJÏZÚ÷“9wNv=ËU~±Üt¹â³Ö׋ò«äõQ9Uâ»\b±Z[[100€¡¡!466¢³³³,×ÎÓA]öPE§l­$«IdD7n܈]»vaëÖ­èííµ3rùÖ£–×3WÙêi½&³ji=jE=m“éºï'µ´n¹öQ=­G­¨§m2]÷ýdÊ^Kë5¯oh¢x<ŽM›6aëÖ­hllLy®Þ¾ÓöĤé7ÓáÚvhhëׯ‡Ûí¶œõ¶¨p¹b¨¿}Ÿ->§Ëµm±ñY/ëE™M&>kmß—zîœìzN¥ôøœ.ëE–r_•K¥®±Ë%‹Ù½M6nÜ—Ë…®®.;)2Óã .*™²Ëµ˜åjiiA¿½s»ÝX»v­]áo=jy=s•­žÖk2û¨–Ö£VÔÓ6™®û~²ñWKë–kÕÓzÔŠzÚ&ÓußO¦ìµ´^Óùú†& …Bhii±‡ÀC4E4­«ï´h]·}ûvôôô@Ó4ŒŽŽbÛ¶m“.kµ¿Óñx]]]èííÅ–-[°eË–‚ËVKûˆŠ“+6úÚ÷¹â³Þ¯mKÏZ_/Êm2ñYKû~2çÎÉ®çTÈŸõ¾^d©ÔõQ¹T껜\.¶nÝ ·ÛmH000· 3!ê2¡ÒÒÒ2aGŒÕ\¶KdðœYÇ|ëQË뙫lõ´^“ÙGµ´µ¢ž¶ÉtÝ÷“¿ZZ·\û¨žÖ£VÔÓ6™®û~2e¯¥õšÎ×7”Y<ǶmÛ°mÛ6Äb1ìܹ;wït,ƒËåJù®ºÝn»]=_Ûnذ.— 𦥠oQHÙjiQñ²Å&P_û>W|Öûµm©ñYëëEù•Ÿµ´ï'sîœìzN…lñYïëE–J]•S%®±ËÅívOè93êÌÊf &¾¯ˆ¶¶¶ñ‡~x|||||ttt¼­­m|ll¬ÚÅJqÿý÷ßxãv¹ÆÆÆÆo¼ñÆñûï¿¿àõ¨…õܰaÃø×¾öµ ç*[­®WúºLvÕÂþ©5õ²M¦Ë¾ÏŸ“¿j¬[¦õÈ·jq=j]½l“é°ïK9wæ{~ºœ;«¹.4y6l°÷Ýøxý|§wîÜ™ñ{ …ÊRÖ©Z—lñøðçü¼üòËu·hrÒcs|¼~ö}¾ø¬‡kÛ\ײ¥Æg-¬•G±ñY+û~²çÎÉ®g9·±ñYëEÙUúú¨Êy]cccãmmm㣣£öÿõXgV)u9)=ôôô`Ó¦MhmmÅèè(zzz2ŽMYMbòÜõë×Ãårattö˜}…¬G-¯g®²ÕËzMvÕÊzÔ’zÙ&ÓyßO6þjeÝòí£zYZR/Ûd:ïûÉ”½VÖkº_ßPqêå;½fÍD"ÜxãhmmE,CKK‹=9édËZ­ït,C,CWWWÊã7nDOOO]í#*¿zÙ÷ùâ³^¯m'Ÿµº^Tõ°ï'{îœìzVR¾ø¬×õ"K¥¯¦BµË×ØØˆžž{þ1æt¨3+‡3ÆÇÇÇ«]ˆR‰q¹\5Ým(Ú]›2•3ßzÔòzæ*[=­×döQ-­G­¨§m2]÷ýd㯖Ö-×>ª§õ¨õ´M¦ë¾ŸLÙki½¦óõ §ž¾ÓâóšššÐÒÒRÖ²Öòwºžö•W=íû\ñ9®m‹)[=¯åW/û~2çÎÉ®g5M×õ¢¤ZгZ-_%¯ëY]'Tˆˆˆˆˆˆˆˆˆˆˆˆ¦B]NJODDDDDDDDDDD4•˜P!"""""""""""ʃ """""""""""¢<˜P!"""""""""""ʃ """""""""""¢<˜P!"""""""""""ʃ """""""""""¢<˜P!"""""""""""ʃ """""""""""¢<˜P!"""""""""""ʃ """""""""""¢<˜P!"""""""""""ʃ """""""""""¢<˜P!"""""""""""ʃ """""""""""¢<˜P!"""""""""""ʃ """""""""""¢<˜P!"""""""""""ʃ """""""""""¢<˜P!"""""""""""ʃ """""""""""¢<˜P!"""""""""""ʃ """""""""""¢<˜P!"""""""""""ʃ """""""""""¢<˜P!"""""""""""ʃ """""""""""¢<˜P!"""""""""""ʃ """""""""""¢<˜P!"""""""""""ʃ """""""""""¢<˜P!"""""""""""ʃ """""""""""¢<˜P!"""""""""""ʃ """""""""""¢Æjí*5VyZÿ—3G½ÆåŒJ¨„ÃẠÈööö²%j®ëX¹r%‚Á :::ÐÝÝ=ée†p8\íU£"0>§¿ß¶¶¶ŒqÍø¬}ŒÇ™¡ÐX ƒ/rC¡çmmmuy!\ï«ÓËdÏŒÕÚR¯ñ9Ýc³Ü÷ž“9—26kC½Æ*0½ãµÔXå}èôÀ¸œ9ê5.gTB¥žišÓ4«]ŒŠèèè€ÏçÃðð0FFF iZ]Í\Ó9>Ka‚Á FFF츅B¼¨ )Áx,ŸP(„ŽŽƒÁŒÏûý~ bxxÃÃÃèîîf [*c5ÕdÎŒU*§é›S}ï™+>›4YÓ9^K‰UÞ‡R-˜ÎqIIÓ:¡‡±råJœqÆèîîžð…ïææføý~øý~û@«ë::::pÆg ­­-åÀÝÞÞŽP(„ææf477# Áï÷£¹¹+W®LÉ¢óÚlü~¿ý[×u{™Î²B×u´µµáŒ3Î@GGGÊI%Ûs¹Þ“K¡ë-4>Ÿ IvïÞ Ç3aYÎõÕuÝÞgb™¹Zô8÷o1ï£ÊÉŸ¹bS<Ÿ)>§:6韅ÄK¦õûR’$û·,ËY/*ŸÕÇxLUJÌU;³­k1q%^'(Š¯× EQ&¼VÓ4H’UUí×*ŠR·-ÉêE%b(ü{X/±šë¹jǪsYå8wŒÕZ1Î¥é±é\ît8—æ»÷œÊs)c³zXO”ªÏ¥¥Öñ>´~1.SÕb\–z;mëoǧ©Ý»wããããã>ŸoÀ¸Ïç?|øð¸$Iッƒã‡÷z½ãƇ‡‡íçÄ{‡‡‡Ç%Iß½{÷øøøxÊrÀ„ÏQUÕ.G1¯ÍE”MüíõzÇ><>222.I’ý\®í!ÖW|¶,Ë9ŸËõžBÊ[Èz÷õõ«ªjÿöx<Ö%ÓúƒÁ”ÇÅ>ï¶?ÃëõŽ+Šb¿.×ûhjäŠÏ\±9>>ž3>«›bYÓ1> ‰—lëëõzÇ=Ïx__߸ÇãIÙžŒÏÚÂxœ¸=йZˆÇlëšë}Ùb1ªªv…@ 0a¿dz•O¥bu|¼ðïa=Äj®çj!Vs­o)çN'ÆjõL§s©³lâÿér.Íwï9•çRÆfu°žhâö¨Åsi©õD¼­OŒË‰Û£ã²ÔkÜéZ;m*>ŸoÜëõ¦<&ËrÊ—Ä ‡¶¿ô}}}㊢¤¼×ëõÚïuæ¡ÄvþŸ…¾6—ô€t^¤©ªš÷ Æ=Ï„m”ë¹\ï)¤¼…¬·8PФø_ü²­o0—$)ë>ŸáõzÇ%I²ß/0ÛûhjäŠÏ\±9>>ž3>«›bYÓ1> ‰—lë+Nàâ·ó=ŒÏÚÂxLUJÌÕB ‰—ôõýñŒp8Œ‘‘ìÞ½º®§ŒÍø¬ŒÇT¥Ä\­Äc¶uÍõ¾l±XÊve¬Vc5Ï…Å+cuj0>SÕò¹4ß½çTK›ÕÁz¢Tµ|.-¥žˆ÷¡õ‰q™ª–ã²”kÜBÞWq9m*™ÆN—m'ˆ±LÇ­<öO%¾ŒÕ”k¢$MÓpâĉ¢ÞS UU'[¡›ôý—^.EQÐ×ןϗ2c¾÷Qåå‹Ï\HÆçÔÅ'PZ¼ìß¿²,§Ä²ªª)ïe|ÖÆc~¥Ä\­Äc¾÷e‹Å|EɸÜô y*Æj~3õÜ™ cuj0>ó«…si¥î=›õƒõDùÕ¹´ÔXå}h}b\æW q Tæ~¨Ï¸œ¶ Y– …ì­ëzJÆËãñ¤|¹ÒŸÓuÝΊ™¦‰•+W¦LlToTUMÙ𦡣£Ã>ødzîÖ[oÍúžr’Îm‡ º4 ÃÞoâ}bR? yÂõù|eÙn•ï}Ty¹â3WlŠçŸSŸ@iñr饗Â0 »lâ}β1>kã1U)1—+†Ë©ÔøÈõ¾l±XÈv2M3e’BÃ0R& ¥òb¬¦â¹³°xe¬N ÆgªZ=—VêÞ“±Y?XO”ªVÏ¥¥Æ*ïCëã2U­Æ%P™ûQ >ãòìj R¼^/t]ÇÊ•+탱óâDQx<´µµA–å”,—,Ëðù|hoo·ß«ªjU/ndY†ßïG___IïåÛC×u;c›í¹\ï)I’ÐÖÖUUímíõz Ú&ÝÝÝe†aØû-ñ+V¬(ê}T¹â3WlŒÏ©ŒO±nÅÆËõ×_ƒ¦ì_EQŸ5Šñ˜ª”˜«åxÌõ¾ôJ=‹§ –b@)ë\î‹vJb¬¦â¹³ðxe¬VÞtŠOglr.ȤVÏ¥•¸÷œÌ¹”±9õXO”ªVÏ¥¥Æ*ïCëã2U­Æ¥X·rÞfR/qyFbÒ˜iK×u{¼=çʼnišv×!Ó4¡ª*Î8ã >|Ø~a0 ’$•|1Y.¢,éëQêöeyBv?Ûs¹ÞSîõ+t[kš†`0ˆááahšVñ÷QedŠÏBb`|òžÉšl¼LU\Sy03obb®ã±Òq%¶w%¯(c5óö˜©çÎb—ËX­¬éŸåŠMçö¨•siú:Ö¹”±Y¬'ʼ=jå\š¾~¼—™·G­ÄåTßÖz\Nû„J6†a ­­ ƒƒƒPÁ`º®cxxxÊË‘kÂ$UU î>UŽåLe™'ÃXSñ>š:µ›¢,“ý®Ou¼”óó¦:^Ÿµ‡ñXÝò:ñ¼G¹L·X-çr¦²ÌcŽ&šnñY¯±9Œë™£Vâu¦ŸK§c¼¶1.«_f`êïGk=.§í_ùȲŒ¾¾>{\6Y–1888ååcàå*çT.§Ö>+WJÉLÖZF“&ª•ØÊó]Ÿêx)ççMu¼0>k㱺åM_Ï{”Ít‹Õr.gª?‹1Gé¦[|ÖklN¶Œë™¡Vâu¦ŸK§c¼¶1.«_f±¬©¼­õ¸œ±=Tˆˆˆˆˆˆˆˆˆˆˆˆ ufµ @DDDDDDDDDDDTë˜P!"""""""""""ʃ """"¢ ‹F£ˆÇãÕ.eÀø$ª]ŒO""ª5L¨UP,Æ 0::Zí¢QÆ'Qíb|Q-bB…ˆˆˆˆ¨‚6oÞ\í"QŒO¢ÚÅø$"¢Ztvµ @DDDD4]õöö¢¥¥¥ÚÅ ¢ ŸDµ‹ñIDDµªî*wÜqÚÚÚª]ŒI;zô(fÍš…sÏ=·ÚE™´×_ .¬v1¦l=öíÛ‡;KW¯®v‘kÊý÷ß_üâ¸ä’Kª]”I›.ßé™xœyî¹çð­o}«ÚÅ­97nÄe—]VíbLÚ[o½…“'ObÞ¼yÕ.ʤM—ãL¡ûäèÑ£p¹\¸û]䊊F£ÂöíÛ±iÓ¦‚Þsë­·bΜ9u]1Ï9µ®}òØcáèÑ£øÒ—¾T÷ßÁ|ŠÏÇ{ _øÂ°lÙ2\~ùåÕ.þ¤Ì¤ït½È·OŽ=ŠgŸ}ÇŽÃ~ô£j·âŠÏ 6àØ±cX¶l–-[Ví◌׶µ§}²oß>¼øâ‹øÀ>€žžžj¹æÜ}÷Ý5}Þ¬õsI=j=Þ+Qo[÷ •ßýîwøìg?[íbLZ8FKK ®¸âŠjeÒz{{ñ‘|¤ÚŘ²õ‡Ãœ$/ƒ½{÷âå—_ÆþáV»(“6]¾Ó3ñ8óðÃW»¨5éñÇGWWWµ‹1iÏ<ó ¢Ñ(n¾ùæjeÒ¦Ëq¦Ð}òÌ3Ï ‹U»¸DZiÓ&lݺ¿ïôéӸ馛êþX=Ï9µ®}2þ|üò—¿œö×¶¥Äg<ÇùçŸo¼+V¬¨ö*LÊLúN׋|û䨱cp¹\øþ÷¿_í¢V\)ñiš&n»í6œþù8ÿüó«½ %ãµmí)dŸ¼öÚk˜;w.:TíâÖ¤C‡ÁívW»YÕú¹¤Ž µ·­û„Êüùók:0 ‹ÅÐÚÚ:-º´ºÝîi±O ]H$‚9sæT»¸5gÙ²eXºtéŒú.Ôº™xœ™?~µ‹Z“ššš¦Åwº©© óæÍ›ë2]Ž3Åì“#GŽT»¸ …ÐÒÒ‚±±1D"Œ!¢©©)çqxñâÅÓ¢çÎL<çÔºBö‰ÛíÆ‘#G¦ýµm)ñ9gÎ\y啸óÎ;«]üI›IßézQè>™ …J‰Ïæææiqîäµmí)tŸœþùˆD"Õ.nMªõzÛZ?—ÔÃq¡Öã½õ¶uŸP©÷ÖABgggµ‹P6Ó¥‹ãtYjY±bEMwë,Ætù.ð8CÂt9w¶´´Ôì…o±¦Ëwz:í“rˆÇãØ¶mëfmçΛۈçœÚ3öI9ÌäøäwºöL—}R.35>§ÓuÔtùNO§}B™Õú¹¤¾ƒÓ%Þ‹Q÷ """"¢Z“~cÑÕÕ…7Ötë-¢™‚ñIT»ŸDDTëάvˆˆˆˆˆˆˆˆˆˆˆˆj{¨UXµ‹@DY0>‰j㓈ˆj {¨åÁ„ QL¨åÁ„ QL¨åÁ„ QL¨åÁ„ QL¨åÁ„ QL¨åÁ„ QL¨åqv5>4‹!‹ÜnwÆç\.\.Wµ·ÑŒ’+6Ï3>‰¦㓈ˆˆˆˆˆ*õ¶D¹MyB¥··hmmE,Ccc#î»ï>466b``½½½hmmÅèè(zzzÐÙÙYímD4#äŠMŒO¢*b|Q¥±Þ–(¿)M¨Äb1lÛ¶ Û·oGKK @UU `ãÆèííÅÖ­[áv»F±~ýz¸Ýnf<‰*,_l`|U 㓈ˆˆˆˆˆ*õ¶D…™Ò9Tb±Ün·”°fÍŒ!‰ ©©ÉîJÖÒÒ‚––D"‘jo#¢i/Wl`|U㓈ˆˆˆˆˆ*õ¶D…™Ò„ŠÛíF¿ý<ÇÐÐ\.¢Ñ脌fSS“=f_6{öìAWW×T®‘­«« ;vì¨v1&-Wl(9>wìØÞÞÞj¯Í@Ñh]]]8xð`µ‹2i•ˆÏƒ¢«« Õ^=šÄP¯¿þzµ‹BDDDDD •¬·F£Õ^=šz{{+Ro;¥ §¡¡!»kXgg§ÝÒÖ©.c+V¬H v¢©ÔßßuëÖU»e•›JŽÏuëÖ¡§§§Ú«D3PKK úûû±hÑ¢j¥¬ÊŸ‹-B?Ç»¥ªèììDOO.\Xí¢Qå®·uöz!š*===©·-y•x<ŽÑÑQ455ñx›6mB,Ö-[ì®bMMM^‹ÅpDS$[lŒO¢jc|Q¥±Þ–(¿’z¨ôööâšk®AWWz{{‰D ªjAÝ·6lØ—ËMÓR*„ZZZ&tãÄFDS$[lŒO¢jc|Q¥±Þ–(¿¢{¨ a``ÀfkÛ¶mv÷¯ 6à§?ý)3¾w``ñxkÖ¬I™´ÈårÁívÛ“¹ÝnD£QÄb1¬]»¶ÚÛˆhÚË›ŒO¢êb|Q¥±Þ–¨0E'T"‘:;;áv»S‚kãÆØ¹s'FGG'´žb±b±Ø„Iä7n܈žžôôô`Ó¦MhmmÅèè(zzz²&gˆ¨|òÅ&Æ'Q•0>‰ˆˆˆˆˆ¨ÒXoKT˜’çP)…¾lD¢&‹Ù-o‰¨òòÅ&Àø$ªÆ'Uëm‰ StBÅívãÞ{ïÐ¥k``±X ­­­“*’¨v1>‰j㓈ˆˆˆˆˆ*‰÷D%$TÖ¬YƒÑÑQ¬_¿.— cccPUcccìêEDDDDäF166†¦¦&´´´T»8DäÀø$ª]ŒO""ªU% ùÕÓÓƒÎÎND"»WŠÛíf2…ˆˆˆˆ(aóæÍˆD"p¹\ˆÅbp»ÝزeKµ‹ED`|Õ2Æ'Õ²¢*p¹\p»Ýèìì¬vù‰ˆˆˆˆjN4ÅÎ;ñÓŸþˆÅbPUliKTeŒO¢ÚÅø$"¢Zwf±oˆÅbèíí­v¹‰ˆˆˆˆjV,Cgg§Ýƒ[Œ5=66–ó}o¼ñ"‘Hµ‹O3T$Á¾}ûª]ŒŠ+5>÷íÛ‡h4ZíâÓ Ç‰DðÆoT»(WJ|ž8qÂA…hªÅb1<óÌ3xë­·ª]"š"E÷Pñz½ˆÇãèíí…Ûížð|¦Çˆˆˆˆˆf’5kÖ`Íš5ˆÇãE$AKKKÞkå7ß|‘H„×ÔT3%¡Rj|îÛ·£££l%OSnll ‘Ho¾ùfµ‹Rq¥Ä§H¨¸ÝnN–MS.‹!r¢¤è„J(ÂÀÀ`Û¶mžßµkWµ×‰ˆˆˆˆ¨&Äb1lÛ¶ ±X kÖ¬ÉûúE‹¡§§§ÚŦª§§gFFPl|®^½šÃ^SU¸\.ôôǫ̂RÅÄçüùóyÉ>ö0&š9ŠN¨ôôôØ'ªh4б±1455±•Qš––ô÷÷#cýúõp¹\¬%ªŒO¢ÚÅø$"¢ZUtB°&¦ïííE<·s¹\غu++DDDD4ã cãÆ€ÆÆF´´´p|w¢Àø$ª]ŒO""ªuEOJ‰DÐÛÛ‹žžüæ7¿Á®]» iÜn76lØPíõ!""""ª ¢R°&ŽF£Û¨F0>‰j㓈ˆjYÑ=T†††ÐÙÙ™ÒÕÒåraË–-ˆD"œD“ˆˆˆˆf¼ÎÎN ÙÔŒŽŽbíÚµ®„¨0>‰j㓈ˆj]Ñ •±±1466f|.ÛãDDDDD3M¿=ç ËåbëZ¢Âø$ª]ŒO""ªeE'TÜn7¶mÛ†µkצ̗200€X,†ÖÖÖj¯QMàü‚Dµ‹ñIT»ŸDDT«ŠN¨tvv"býúõhiiASSb±ÆÆÆÐÓÓÃ^*DDDDDDDDDDD4íP€-[¶ ³³‘HcccX³f Ö®]Ëd MK%%T«û%»`ÑLpf)oŠD"ؼy³ýÿÀÀz{{Ç«½>DDDDDDDDDDDDeWtB%¢««+å1—Ë…H$‚ 6T{}ˆˆˆˆˆˆˆˆˆˆˆh†0Í©û¬¢‡üÚ¹s':;;±eËû1·Ûûî»ëׯG$Ûíλœx<ޱ±1¸\.û±X,†X,–òºÖÖVÎÍB4…2Å&Àø$ªŒO""""""ª4ÖÛR= …B‡½žøÜ#<‚ ”¯(TÑ •X,6¡"‹  P(èéé±ëííÅÐÐPÊëúûû˺ÂD”[¦ØŸDµ€ñIDDDDDD•Æz[ª4Ó´~d9ûk À$I$)粂Á à ]%õ¹Ã‡—}š’¢*­­­@gggJbehhÑh4c²Åi``‘HCCCظqcÊsñxœHT%¹b`|U㓈ˆˆˆˆˆ*õ¶4U4ÍúéëËþšP(UU¡ªjÎe†ÇZ^zBeïÞ½X¶lYYË^tBeãÆˆÅbPUÕ ±±1D£QlÙ²%oB¥µµ.—kB1ÀšìÞ9”M\± 0>‰ª‰ñIDDDDDD•Æz[š*Š’»w ˜¦ MÓR*†a@ÎðÆÝ»h¶ÿonnÆáÇK—.-kÙ‹ž”¶lÙ‚íÛ·£¥¥---X»v-4MCgggÞ÷¶´´Àív£©©)åqÑõfóæÍ¸ì²ËpÍ5×``` ïòöìÙƒ®®®²n¢BuuuaÇŽÕ.FYd‹M ôøÜ±cz{{«½j4E£QtuuáàÁƒÕ.JY”;><ˆ®®®‚☨ÜÐÛÛ‹×_½ÚE!"""""‡JÕÛF£Ñj¯ÚŒd†=|[­Ñ4Àï·~g*·ó7` ë¥ëÀwöBÓ4躎îînhŽ<ñDáp€•Œ©Ô}gA •¬_¿Û¶m³3”---èééAOO6nܘ·gJ>±X n·7nÄ®]»°uëVôöö"‰ä|ߊ+Ðßß_ö CTˆþþ~¬[·®ÚŨ¸Rãsݺuæz š ---èïïÇ¢E‹ª]”Š+%>-Z„þþþ‚B•[gg'zzz°páÂj…ˆˆˆˆˆ 0ÙzÛ–––j¯ÂŒ á÷ûó¾Î™¸Èõ˜ßoÍ{2Y†a ¿ÿ!Èræ„ÊÊ•+XIñ[Ó4„ÃÀ«¯ÞÐuÝQF«ÇÊ‚¿ÅÃ?ƒŸÿü Ö@'Nœ(ûv-(¡ÒÙÙ‰ûî».— Û¶mCWWz{{Ëš]•_b1·7Dq€IDATÛµk׿ L"ª<Æ'Qíb|Q%ñ¾³þˆ$„Çã®ëY_ …ÐÝÝ=áñ`0˜Òût½| •@’€x ±lÁ`0íót9Òœ’<9óÌߦüo­›•PY±ây<ôÐZüæ7ïØŸ³|ùò²oÛ‚‡üjllÄš5k°eËô÷÷Û“Ó—+¹‹Å&,£±±±ì+LDÅc|Õ.Æ'Uï;ëƒsx¯P(¯× EQ íÞé‚Á ð𦡻»†aLH¨XÏ^ÈÐÑÅ.‹¢»wχ®ë‡Ã0MÓNþˆò<øàz<þx³c°öï?Ã0 ë:LÓÄÕW_ —ëU<úè<ìÚåÂã7§,£ÜJšC@Jreíڵعs'Ö¯__rb%‰`Ó¦Mö˜|ñxCCC“JŒˆ&ñIT»ŸDDDDDDTI¼ï¬}¦i¢»»~¿º®# ÁãñÀëõB–e´··OHª„Ãa¨ªŠ@ €ŽŽ˜¦‰p8l'+2%$4 ö<%™¤'Tº»öööÄ{5;iÒа² ¼ýö#¸í¶+ÀNˆ²I’„ùóãÀ“¯ÂxðÁõ0MŠ¢À4MÌ›÷;,^ü¬Xq?–-û1víz’$A×uŒub×®¹eÝÖg—c!brúÉèììD4Åúõëár¹0::ŠÎÎNŽïNTŸDµ‹ñIDDDDDD•ÄûΩã÷’ø|ŽO×uø|¾Ä\#a B–­¡°ü~¿=¤V `%-|>E®ëÐuÝî•¢(Ê„„Êð0pë­ûìdM¶r8ÝrË1ÜsõX0„/±b ûñÌ3ð¿þ׳8|Øz½sÞEQðôÓ'ðë_º»M(J/¾ÂÑ£sð®wKô¨ cø?Æqñ‹ÏblÕáÈ‘Ùɖٳ߃xü¬²î£¢*‘H±XÌ–h4ŠÞÞ^ÉIê •i"ù-[¶ bll .—‹YN¢*ț㓨0>‰ˆˆˆˆˆ¨ÒXo[]¹æ) ‡Ãðûýðxïy†Göí;†|DE08Œ[nù0Z[ØŸ×ò| .’߃_ƉË.{ +VÈÐ4 眳§Ëº òkóæÍèêêB,`·aëÀ--¦M›&] ––¸Ýn%Q b|Õ.Æ'Uï;+O’r?/zŸˆ%@2Q¡(Šý“N–eŒŒŒÀëõÚCv9_'Ë2 À,ËP²,cppÐîÕ ñÈ#oã—¿\„]»ÞNY¶³g œ»Ä4Mìßß@ÁûÞ÷¦=Œ˜išX¼x1öïßǃsÏ}Ç/±×gïÞ~˜¦Š¢àœsÞÀƒ®‡¢(¸ðÂG³gÏÆÕW_m¯Ã¥—ÅÍóöàâñ‹!Ë2vízÛîusþùgã²ËÞ(ë>*¨‡J4ÅÎ;±}ûv{h¯¡¡!455aëÖ­hllDgg'TUE,cPA’2Oü.æ7ÑuŠ¢Àãñ C–e´µµÁ4Í”+™ˆÞ'b.“ôçDRFÉÀJšÜ{ïÓøÙÏÎÄãŸèèè@ €®ëxä‘]vÏšo|ã$fͲþnh8ãÇM|õ«³RÖå ÅâÅ‹0{¶ŒX 8rä »|óçÆ‘#^(Š‚ææÿƒ—^Z…›nR𓟼õëe|øÃ—á­·®‡¢üîwó=Úˆyã&|sù7qðàrœ>}1$I¡C¿`_Y÷QA=TvîÜ ·Û2OJ$Áš5kÐØØvW/у…ˆˆˆˆˆˆˆˆˆˆˆ c@†&èèè@8¶ªª"# bÕª¯axø0¤ Ý[üþÔs¾1Ç û½\p Ã3aŽ]×ñßÿ}ccc¬×Šž1°gÏsÕÿøÇË ë:NœhÀ¢E{ÑØØˆýû ªªÝCå…îÆÈÈnȲŒ¦¦C8|øbûs6nœY³¼]4I’° dYÆþç ðzÇ*ç¼yóðÔɧ°çæ=‰Ó‹X¶l:::ðÎ;ï”}<äWz¯“H$‚ÖÖÖ”ÇDr…ˆˆˆˆˆˆˆˆˆˆˆ ÷ÐC!Ní="’ÃÃÃ)sžˆ^*W]µ>ë¼+¡õ#ˆ¹QÄßN@o¿íšÐCF×u˜¦‰–¡©éÅ.—ø9räÄöÏ?oå~ýëƒX¼xV¯þÞy稪š’ÈihØY–!I:dÙ°?/_ˆ÷¼gàøñãØ¿¿GŽ4ãäÉ0M=ôB!kø³p8Œƒ—£ M8±ôEÁ7^ŒO}êSÁîÝã•W^)ë>*(¡ÒÔÔ„H$bÿ?44p»ÝŽ#¢©©©¬$""""""""""šîü #5чS&|vïÞ ]Ï<‘½a@¶çŒ ù|>È2à|JQ””ž1—_þ4Ÿýì>;™bš&Î<óšÄ;¬²>|5ö㬳þŠ¢ ãºëþ¿”aÅ4Mƒ¢(xä‘8vÌ EQÐÚztX±¢ºœ:u ³gÏÆ\‡†††£GŸÄÀÀ $ †aàÀ“XŒÅxî?ŸÃm ·áôéF|à[0wî#XºtiY÷QA •5kÖ ‹aóæÍB(‚Ûí¶{¤ÄãqôööÂår¥ FDDDDDDDDDDDÙ™¦‰ŽŽœuÖB,\¸'å¹p8û ¼»ñ×Xsçüò—¿ÄþýÏࢋ.‚,˸馟•}_”Pq¹\¸ï¾û‰D°iÓ&455¡§§€5ô×5×\ƒH$‚­[·–½€DDDDDDDDDDDµ(Ó$òÅ ‡Ã$ ÿó?ïÇ’%߯-·|%ÆërÎw’NQ¯wâã†a•-}j1}¶u1  »;SBEGCÃ~x½!:ôŽ=KCC ÞûÞpÿý¯бtéØ?ÿï±ÿ~9r²,ãÏþì:H’õÙŠ¢à²ËžJrlÑ¢Eðx‰j㓈êM¶á¶ò¿O·‡Þ2MÓNpÌŸ? ¾ªº###}~bZ’Œ‚A+¡"I€ª^¯ÞL]ZL¦ˆyWœÉ—ƒ¯Çɓ߀ªª8óÌ—pâD¼^/^|±O>ù$®¼r'öïNœØÀ…C‡þ žÀZ¦®áðƒ8}ú4öìù$þð­B{½^ttsæœÄ]wÄŠÀŸÿy.¾øðÔSoá©§¾ŽÓ§ÿk×> à ãý¯8ï<Ÿ]fél*¬¤ €¾>+Éôá?`YY÷wÁ •X,†mÛ¶Ù'3¯×Ë)DDDDDˆkçíÛ·Û×̪ªb``7n¬vñˆf4Æ'Qíb|Q½Ò4+Y‘M0„¢(ö¼%á0 ëa„Ãa†a'8<àô髱k—+ç烀ÏÊ'äMèH’•tH×ÖŒŒ$ß/z¥¨ªõ#&»wε"æ@9çœ~ í^5+V<§žzsçÎÅœ9¼óŽÀóp¹ÞN¼O‡ª*<‰!»®µ—iž~úi¬\y~¿÷¾÷"\~ù"üó?»ñÁ⪫>‹S§~€#G’sËÜzëltt¬À‡?l•Uú¯Ä݆­!Ð xì±N•u_<äWWW"‘ZZZ‹Å°aÃÄb±²†ˆˆˆˆh:ˆÅbp»Ý) Ö¬Yƒ±±±jhÆc|Õ.Æ'Õ£Ó›°z¢„ÃaƒAû±înñ^†aØÃz°jÕ*Ìž=;ç2Å\'0<œù5bnŸÏJ:ˆ^'éåN€>ù¼ßŸL ˜&pø°×N >ÝˆÆÆÛ¯½ôÒKqüø,^| öí;†k¯ýfÏžU«V!£££ýèÛÐ4 ÃÃÃ8vì˜}¬×4 óçÏÇòåðÞ÷þÆÇ­^9«WŸ…Ûoÿ¾üå/£££-eˆ2Uµ&®‡Ð?úQ3uýN”}”P‰D"ˆÅbؾ};zzz°}ûv455a`` ì"""""ªwn·ýýýöÿñxCCCp¹r·4Û³gºººª]|š¡ººº°cÇŽj£âJÏ;v ···Úŧ(¢«« {öì™üÂj\)ñyðàAtuu±ŽŠªb``½½½xýõ׫]ª"'÷[ápxÂ[’dB×u bppО ] ß•iD.ÑcDü-øý™?_×­a¯¬ÉàS*†a%ÄrD‚Ç4“˲ʢ @׿æ]Î{î¹ñøj{ysçΜ:5.‡Ëu%,¸ W_}5 @–­ùR`ïÞ?À­·Þ ÀúŒ¯|å½™ïÿkðùdø|>(J2é£( |¢KN‚è…¸[<˜ú¼5äWyÜCÅív§ŒW¹fÍš²†ˆˆˆˆhºÂúõëáv»ÑÙÙ™óµ+V¬H©H"šJýýýX·n]µ‹1¥Š‰ÏuëÖ¡§§§ÚE¦¨¥¥ýýýX±bEµ‹2¥ ÏE‹¡¿¿?o UBgg'zzz°páÂj…ª(´~²Ñ4 F¢öß0 †„]»Þ¶N’d%8ÚÛSïèHMŠ8“*“B ã•,“Uf±}Kcãóöð_wܱ·Þ:ÝÝÝðx€K/= ÀšÿÎ;o9ZZs§XsżðÂOðùÏÿ ðþ÷‡ßïG8Fww7®ºê4àõ׿ §†aÀç˨¬^*úÿøVâ)½T*aÒ“ÒÑDñx›6mB,Ö-[àv»«]$"J`|Õ.Æ'M'ápŠ¢@’${Ȫp8ŒsÎùÿpþù×f}Ÿ®OL’Ȳ•h¶!ºnõެž(†aMÆî|½èé¢ëVÂ$°þ7Œä<)ºn½N–“ÏVÏgRcñâÅP”+íekš5$˜õ:k®”'–böìçpų!IÖ:˜¦‰@ €sÏÝ‹ƒo444@Q”DâÄI’ ªÀ²e'1wî\(ù2)Ž2šGÓ¶•k‚ú )¸‡ nÆ p¹\Ð4•AD5†ñIT»ŸDToœI! båÊ•ðûýöü(’$AÓ4|ç;¬_íígLxŸÈ#ŒŒ¤ÎÍ"z£8ç81Óæ …R— YsŒˆå:{´èzr^•@Àú[Ó’C‰e:?ï†nHéQÿüÏWáøñã€eË~Œùóãþ ^/ ë~„B!x<H’„ƒ¿‰~ðY»Ü†a@’${ûÀ»Þ5Ë&¬Šx> (ÎNÄFÁo/IÁ=TFGGSÆsÒG£Ñ”×qˆ""""šéDZfÍD"ûq—Ë•wž"ª,Æ'Qíb|Q= …R“¦i" add$%!& ?yr~ó›‹pÑE31"· –gšÉÞªšüÛç³’"†a½Ç뵆s£"A#IÀà`êg)Š•Dñû­¤Šs¢{QÑ F–S‡ ¬çÎ<ó&\rÉ }?.¿øò—WØÛA wXó§øýÀâÅ¢—Mêœ(¢LÀ-o{ÑkÇ'z樴Êîï‚*MMMhmmMyŒ'2""""¢Ìb±b±Ø„ æ7nÜÈ9ˆªŒñIT»ŸDTd9™¿ßocå$I‚Á n¹e3ž}ÖJ^hZj¢Âï·’ €µL‘PŸ %ß§öRq–!“¶6`÷nëoñgÇ·¿}¥Áî­â\/Ñ«Å4S“-pñŇÑÜü=œ‰ªñIDDDDDD•ÆzÛâ<üðÃ0 «gJ0̘LÑ4à_þ¥ ªªb÷îù0 +!â÷§¾îðáäߺ>q^ Ù+Åï·þ ÑãEåÔ$Šè"Ê û!ºu &'±<kH-ÑKÆéÜs@gç477# P°téRÄã?G(‚7}a‰2ttß%_gÚÁò-;“¢*½½½PU½½½ˆF£ˆF£Ø¼y3n¼ñFlÛ¶­¨…BHyl``ëׯǶmÛ°~ýú ÏQåeŠM€ñIT ŸDDDDDDTi¬·-Îñã›pÞyÏAÓ4ŒŒŒ@MŸl$Á9<0qNX¹2õy‘ÄPÕääñ’d%>%5¡¢(ç@q&TÄëkÒ{xÿûˆ§Ÿ>×~>˜˜^’€¾>ÌÄ‚Á LÓĪUq\pÁ×íäÉO¬†¢x¡ëú„!ÏI²†++ €3Ù#£¢Ó<)½è²eËtv&Ó>ñxÜî±XãZæ200€H$‚¡¡¡ ¯íííÅÖ­[áv»F±~ýz¸ÝnÎ×B4rÅ&Àø$ª&Æ'Uëm‹gõøð ëÇå—¯Ky.¶ž½1DÁÙ‹$=©’>¡¼HøýV"BU“ï÷z­,¦™L´ˆÉêÅ„óéI!¼^G^‹«¯¾~¿ªªBUUøý~Ȳl'D†‡=…€óÏ¿Ó~¿˜fddCC À˜ ~É’%›vXCq%xHiZ[[ÑÙÙ‰–––”Ç#‘šššàv»Xó¶´´´ ‰Tní‰È–-6Æ'Qµ1>‰ˆˆˆˆˆ¨ÒXo[MÓðÌ3ûÑØøa;æÆ­·~6åy‘ ôd 0±×J:gu»¢X?²œ\v0˜:½RKÏ0ÈYgÅñ½ï`½·££«WDZoß¿C’$„B!øc…B!ƒA躎÷¿ÿßÑ×w>ú¨Ý3Å0 C’$H’%S÷!-yâõFE+À™–§ý_f%T"‘ÜnwÆŠaãÆˆÇãy©¥¥n·MMM)G£Ñ ͦ¦¦¼cò½ñÆ3>x©z"‘öíÛWíb”E¶ØJÏ}ûö!V{Õhç£'NT»(eQîøÀJĈץ21wîÛée4á­å¤XŸF+Ro[Ð_ccc-Ld)K‘é3 é2öæ›oÚ ¢©6*¹”ŸûöíÃèèhÎd,Q%ŒM«„J¾uM—/>EB…ݳ©b±¢Ñ(«]"""""*Àdëm].WÝ_ÿkšõãœL]Ó4¼ùæ"44̪ííVÅùÑ“$J&VœÉŽôÄ‚³· 9ñ ’$¢ÇŠ“axñÅX¼ø^øýVO1•É­·¾ÑèÇ iøë®¸êŸ¯¼HL( f\÷›o¶EË—Ÿ‡o~S³{¦¤“eóç…¢4'ÔxQYjâÇ.ˆõ¹£ï­H½mA=Tššš JªL¦§H¦V·…´œ]´hzzzʾaˆ ÑÓÓƒÕ«WW»Wj|®^½zÂ0DSÁår¡§§óçϯvQ*®”øœ?>zzzتÂívÃãñ`Þ¼yÕ. `²õ¶Ó¡!Ÿ®§öÑcj80çž»ŠbõqRU+A’˜¯¦™ŠK õ%I©=TÒ{¤È2pÆÉ¿+I’m„­îînlÙ²ÀK/½„öö•vyC¡úúúÐÔôZOÎÁê'VàõzáK/|ZdÙZŸ¾¾¾¬“Í˲Œýûò´Ö\y†6› €ßYÐÙÙY‘zÛ‚*kÖ¬A4Í™0éíí…Ëå*¹r¦¥¥eB ŽM‹€#ªwŒO¢ÚÅø$"""""¢Jâ}§•1MÀï÷£¹¹Á`GwI²'Î%"Qâ÷'“+byçDñÎ÷¤Ï}âõZ=^ÄçÖë3å4 ÀÏçÃÛoï³ÏFpêÔ);Q"Iúúú ë:æÎÝ…‹çŒãàõ)Ðg£ªÖúäœ+Àþý T`õT™Jƒ“_D6%T\.6n܈M›6aÛ¶m)ãÞÅãqôööbÛ¶m“ê)âv»í!ZkŒ³X,†µk×Vn퉨 ŒO¢ÚÅø$"""""¢Jâ}§5tö'‡ ë:<~÷»ßÙ¯‘åô^,Öoð’!’4qΔôüD¦ÿUÕ2L$^‚Á Œ´®,†a ½½ªªâôéõ¸ä’KXs½twwÃ0 x<\{íùüÕa˜’ d˜£%“<ùÛÕWN}@$R üœ² Ãê¹RÍ¡ÀN–„B!»7ÊØØâñ8\.¶nÝŠ5kÖLª0===Ø´iZ[[1::Šžžžº_hº`|Õ.Æ'UÒL¿ï|üñïáõ×Oã²Ë®„×ë…ªªeo¼Ly]8‰j㓈ˆˆˆˆˆ*õ¶©LÓÄ /üGÞ'ŸüW˜&ìä ã=ïyÀ 2O"/†ëRU ¹ÙJ²8“¦i=~ø°•ñ¦õ毇ÃÐu¦i" Â4MìÞ½¡Pííí) •¾> <ÙQVËw¿{Œ« 0°D]RÐ6(´‡Êóϧ%ÙdXI•ß_©“Ò€V¯˜'ÊÿqE%T ±±kÖ¬™Ð%‹MzØ/3. ©~tw[£™ŒñIT»ŸDDDDDDTIÓå¾Ó4­¡·òLÃ0 …`V¬ø3HðöÛg@×­äˆEÁ‘#ö{Ä$óÙæFQ”ä\(Âà ÐÑ‘ö¸»‡ŠßïDZcŸ$Iö\'ƒƒƒöÿ>Ÿo¤òšfõ|ÉT—)I€r© |R¶&sWQŠ¢`áÂ8GR% À  Ö¼&rI‹ÎÍÄÄ!ÅdA«ÊÿqÍ¡BD'…"¢©§ë: Ã@8†ßïÇÊ•+3¾®½½š6ÕýI‰ˆˆˆˆˆˆ¨ÖéºÕ{#Ó4ÑÞÞI’ Ë2æÎ½þç7Àç“R%K–¤öðp>'†ñrs¢¤?æñ$ʇջÂQ>Ó4±lÙí0 ¦iB–e(Š2¡çIz9äB’áòm×@ €ï~7Ë0pžò~VŠL  9K™ÝC…h:hk½à ¢ëVöº ƒ•](B(‚™h²áõz¡( B¡¼Ž«”`0MÓ&´Î """""""òa ñ{¿÷xáq""""""""!Êý|8ÆyçÝn×!úýÖoÃH­«RCù‘^¬’Ó(dj4/Gš`.æ–õ£ J¨tvv¢³³³‚kLd ‡“žb;¯I0h8 M¨F2à XC‰¹V¯^]íÍFT÷t]G[[|>ŸH ‡ÃÉÛ•UQtwwÃçó¥ô^!"""""""J Y?bDš´g1þ_Úÿ%듯ðûSëÓë1C!k¹Îa¾rÕuʲ ÇI2pñÏÜV‚C¼}eN¤a${¦Tj²øt¬u+²Þ· Y–¹xßbœõ›³Ê:JAs¨Äãñ‚z¨M–˜ä©â Xìç:Ü`½Vt¬Öó²,Ã0 :t¨º¨Î™¦‰ŽŽŒŒŒ@×u˜¦ ŸÏ‡ÁÁA(dW}>vïÞ]þÖDDDDDDD4íÈröFÖ=öÇX¹²bq1™¼sÔ-g¡>Ìix¸°y˜u]·‡:—$ †!ãÅ“ÍÉTrnQÿª8þ®çvV‘¹'Iýäc?ÁØ5ce]fA •P(„ÞÞÞ”Çz{{‹Å¦v ÐŒPloŸ¯ø$Ìà`ò€˜‰iš9²4’dMõúëá–[>EQàóùàñxð‹_ü¢Ú›Œ¨&éYS$PÂá0ü~?ÚÛÛáóù&$O«\Óߊ9‚’µ¦hø’*Dùˆñ‹©×TUk|Áb敇S'yÊG,E ȲŒp8 MÓì™®ëÐu^¯7à[ßz<ð 9Ò U]a/ïÃþ0æÍ›WÝMTB¡TU…išðûýðù|öP^¡Pš¦Á0 x½ÞœÃs™¦YtB$Lö<+!CDDDDDDD3ŒªZÉYÖÐÑÑ‘¨«è€ÏgÕ/XÏYõ‡Îj Ñ»%×è7™†Ĥ÷é#kÈ2 ÉÉÛÅœ#•H8—Yé‰é<°z­”c‚úŽ«2hŠÇcB…*FŠ©ÍÖÝ.1a|¡Ÿ¥(ÀsÏý'x`.ì‚$IP}}}Ž×(v¥î-·Ü‚ÑQË–-Ccãú¢Ö‰h&…Bèî(ö(^¯~¿ßîùåñx08˜»¿ªèÍRl/Ñ:H×”ˆˆˆˆˆˆˆ(¿p»Gáõz¡i.¸à}Ðõ«¡iÉ:Êôn$ÉjØ©(V]f!U¦iBÓ4Ȳ I’ ª*ÔLCôhH&6<¨ÌP\bÙ‚ŠÊ ™•ž8ñÂJÞL6¡"z§È²µÌ)TÐ*D~a“)¥+¶¥¸ÈüûY…¾Çï÷c``'NœÀÈÈ <^¯ÃÃÃÌ| 0wî\Üpà P”âçx!š.º»'>‡ … …Ð××UUS&ˆ÷ù|Ð4 >ŸbºžAœC½^«·Zòq‘H¤Ú›ˆˆˆˆˆˆˆjHˆ<úèkðz½Ðu+Vœ†¢Xõ Šb¾£ëë­:ÂP¨°Æámmmöèr®ÊEÉ&¬!²*Á¹\ @{>CÂÄD X†e‡BÉ9 4w¶—Vy]‚‚{¨Äb± Ó M¨¬êéé™’‚ÓÔÒuë§Ød‚YBÕ0&f~s½HßåœKE×uȲ Ã0`š&‚A+Zãñ8$é|âïÂu×]‡nPò¶†w&R˜P¡™H´Ì±)†ï …Be'ã0^’$axx8÷ÅB£È aX1š)Œßxãjo:""ÄãqŒqîAªºPbP'9§` ìí]JOñzÇø$ª]ŒO"ªÑ«D’€_|Ë—_Ÿ¨·P±kו$ëzIU“£á¤·Á–¤Üõ÷¢>2Ãçóapp°°áÍ${o(üS´QTX‰‰r/&câh\âÿR‡ýÒ4د‘‘ä².V ¯Pž¤‚z¨¸\.¸\.D£QûÇív#‹¥<F+^`ªqV(‘ä(5©RI²n%y`3MÝÝÝèîîF[[ÚÚÚìù†‡‡qûí×ãÁÿªªâïþnnAC ézrýu=9´ÑL¡(@_ÐÞÜwßö0^ƒƒƒ„/Ç8[Å$SJ™^´(±>+Y$Ë2,XPíMGD„P(„jƒêœ¸5Mk¸h‘1Íäã€u­iÖó+WZ¯ï5 ëïîîä mmÖýhw·µŒ§žº¬Ú«:¥Ÿ3˜ «HNšk¢¸¡Uf`r*1>‰¨Rœ½JNúŽY X²d V¬xÝ~¨ÿÓõ‰ ñx¶zÏ`0ˆ¶¶6„Ãa´··C+´2qªr§""*å¤ÈTŸìAé=o‚Ak£Œ¤¶¬]"[Àb‡„ÃÀÊ•øäÖ­˜ýÊ+e]­‚z¨tvv¢³³³¬LÓŸÇc}‡³t²QÕºnÅG_ð±=†… ÿ†aÀãñ`ddáÄø?ápØÎëŠ+nÅìÙ¡ªjƉ¥2q–G¼§˜u"ªw=ôþÏÿŹçÄ¿ÅÏ~V\¯“Bɲ ³È,¬æËëµæOq‹ "ª¦D" aãÆÕ.Õ¡ŽëšÓëµþ’ç:E±’ šf½FÜЇÃVƒ#ŸÏú Y÷–âÀzªZ÷ ¢M„èéÝÛ» €»Ú«^qŒÏiJ\FJYž‰/¬Š?¬ %V%’x¿/ñ¿`‡+ËéЇÌc·›˜ê9r§ Æ'U𮸧úÎ9ç!(Š‚ßÿý÷.½ô(þøOOxýáÙ—£(Öµ˜'m2wÓ4áõz Iü~ÆQ=2 #õ¼R©ä½À°ã劫ßóF\èŠVAé.U€cŽáKTÁO¾ô%¬\º´¬Åç¤ôT@ÀúÎ3ñ{[›uƒVÌè=€ùêSu]‡axúéE|º¾ {÷~¿ýípÊë<‰#šÇqd›;w.îºë.ûó iïLž¨ª• %š)ü~?FGclì]øë¿¾?øÁí55ôò °ŽÁ`²ÂhÞ¼yÕ.Í`­­­p¹\ˆÅbÕ. Õ`0ÙˆGô¾–åäØÜârVôÌÃñ:çéºuýí¼¾õz“=9…ô›þ™ˆñYF¬Ö§TnBÛBå‘`UH ÂJz˜Få”tÀª8JŒ2¡5°H°ô%Þ¯ÀJ²È‰eËt¬¿–x^lƒn»‘ìù¢9Þ@êdÀ”‚ñID•vòdÿ÷±nÝÿÆÊ•+ÑÒr1`ñâ[ðÓŸ®Ä'?YØõ’¢¤ÖI~¿Š¢ØC|MjNÙ©šp]ªÀg©È<„˜ 뼪£ðkÑ3%Ó)2¬ð§}Žõ±.ˆ._Ž•e^­¢*½½½ˆÇãØ²e z{{±mÛ¶”ç].WáÝ—¨jÄÎÅŒ¬ãlÅV(I*®· `µžÎý]×Ñ‘h¢÷Î;MøÿïÌÛ†pxEA k>”ù¬8ôû­‰¤òm3±\1”Ñtf4M³“—³fÝ‚n¸ŸøÄl|á Õ.]*Qá$ˆ„l__þöoÿ¶ÚÅ#¢¬¥¥ÐÔÔTð{öìÙƒ®®.ô÷÷W»øTÎkSð®©Å]Šbýˆae‡‡­ûCq}ªiÉ™ˆ÷§?6]]]سgÜîéßC¥”øÜ±cÎ:H.¤·tu ÕñZ VeJ¡Â°*^DŒ‘XžHæhHŽÇn8œøíìa2èX–sŒút²ãµ#‰e·ÃJ„„ë©#™ ª„’Là ÂJÜVbÆ@²ÇK®F‡bØ1GÙ|ðy|ýëÿÇÆLPl|ŸoÂØžÎ!*Ãa«’¨Ã…(%4­ñ+Ê'IÖ…P¡Ã“NŒO"¢Ê½’ÅM¶H¨ƒÉs£$%çד$Ñ:ù¿iZ‹Sç᣺%ÁJ¦ˆ^&bH-qù@²'ÇH⹬¤Ë0R[§z`%CB‰åˆ¤ˆHœˆ!±t¤&LŽå¨iˬtl%¨ápr#1w‘hÔãL´¶·[÷‹Á`ò~º»;™LõÞ˜Q@Û Hÿh!Àÿ Чj ßR@ïä%Öª*ó^«ü~&"Ê¢ï;=ëXí÷'ˆ‡B!\tÑ'S^'zš˜fñ=~½^à/þâ÷póÍ«¡iFòULæ“ÞcCArޝ²nœ ɘº!ÆëZaª8eTPBeçÎp»Ý’)N7nD(B4Íùº\z{{144”òXÿŒèr>•¼^ëB®Xâf±X"S›¯7‡®‘ÈHÒÿ`Ïž'päHB¡a†‘‘Hy *Só}Vú:ˆ ábLþb'OªsŒÏéÁ0 »û©$I0 ~¿’$A’$ìÎ’ýt&Td¹øV…Êç…PUk§™TaÅø$"š<Ó´®‘ÅùM$MDe©óÞXÌa"nº×’éçGöh¦ºgÂJ|¤×eªpRŒ;þ÷!{%I’=HÄ`ƒHÙ%z·™‡ ™$]ŸØHÈ0’qmšÉ¹ŠÚÚ¬Š8¯7Ù¸hpÐJ´Š~²l½F /#«Šb52ôz­÷d«¨SUkÙ¢çéj&%ñiCzɉÑ+¥ÜÒ/ù*ðé½FÄPΦi%9<ždo²P(9ô´H’š¦õš@Àz>²*Ü #™Lÿ‹c‚H¸ŠºIÊ?O¨±Á’c˜——þó¥ ì"¢ÂÔã}§¨#UápªªN¨/ç 1@!Õ†aØV½^/TU­ÌÐã:¬¤C¹‡„ÍÖh^Ar>°É&)dä?¿÷ÁêÍš-¡RHëþPâs¦èš¼ „JSSÓ„D‰ËåJù?#Nª0‘H[¶l™š5ŸáD—·Bë-ÅMäà`ñs‡èºus&5Mƒišðx<0M~¿_üâ¯.A pÂá0î¹geÞe§W<‹1ªsñzSË/ËVwìÁÁìëåñL|NÜŸuÖ$wF`|Növ«õD9ÎÁ𦡣£#e>”¾¾>˜¦‰îîn´µµÁãñäM¦¤“åä\L•P®^*Á pÞy•)c­a|¥÷]â|å÷'o¤E…ªª& ‰K¦$‰³2–¨n%z8¤TŒè°†Ûò9"Ùb5 «"$W/“*IQŸÏJŽø|É¢ñO8œŒeQA&IÖub_ŸõÚööäð±##É‘Ä|G"þ=žä}±è"îqǧ2=¹‰ˆª­Þï;þó8B¡FFFŠÖ+ßï‡,Ë$ ƒåžh6½3†V‘r˵ TXדþËDöž0‚Hº„ÊðyS¤ „Êš5kìn]k֬ɸšP(„ÆÆÆ’³”¢·ËæÍ›‰DÐØØˆžžtvvæ|ßž={ÐÕÕ5c' ^:'p/D±¡âõ"YQHý«¸ˆTUë×*¯Õµ®»»’$! A×u,Y²"'çñxìDL®‹ÑL •|ÛAL ꈦiÐuš¦axx¦iBu|yK9á‹^YB8œl½[méIR˜=;Š}ûFÐÔt°ÚÅ«¸RâóàÁƒèêêš5kòÆ1Q¹ ```—^ziµ‹2efêuj¹ej dš©­Å>bÎI²*\GF²7V(ÇÈ T¿¦}|j°Z™Š‰áEkSÉ$J7’“¸†a í%¡ü-a äŒu‘=BtݺöÓ´äßmmVâÃ0¬ëSqoì÷'{—¤sšVÃ:Ñ[M\S*еL'&W§Þ´O¢:2ÙzÛžžž’§ˆ(•sd×__øÂq×]H’¿?sïÁ|#KÖ( Öò  yC±ü˜8J¹ù&‚÷"Ùkd2ç>ù*€Õp#˜å¹Bz¨déMÛÛÛ‹;Ê_o[PBÅåraãÆØ´i6n܈ÎÎN»‡Š˜°~``[·n-¹ ±X n·7nD?"‘6mÚ—Ë•s¥W¬X1£O²šf]XÅ%ITµ¸*Î÷ƒ…½V¸d˜=û8>ûÙA|ç;÷°&–O?èˆáœŸ•/¡¢iÖç8×=´.¬³mqQî?<µ^W`ݺuޱ•ŸëÖ­c2¥Hªj}Å÷¸P¦iÂ4MhšfO0_ÈÜC… …¬ß"l½^ë&µ¯J7ÚN~ÿĘoiiÁ?Ø‚ßþöÕj¯âJ‰ÏE‹Íès'U—¸ŽŒD"Õ. Õ‘pØj ³{·u æ÷')¡P²÷µiZ7ÇÎ á½Þò¥ITóB°’':¬äˆHÉ®${§t$^;ŒÉWœ }ˆ[Ó´®}Eƒ‘qîœØ]ô1ÍäÐÒéå„\u\Îc‚$YI""Ê®ëmSÝ„ð‘ÜŒ@à.¥á¯ë::::088ˆp¥ÆÏ4òŽÖÜ*åL¨äê"z¨N–B4)Q–ôùc€Iuû¬TdÁs¨ôôô ©© ¡PÛ¶mKyÎårMz ½–––”s»ÝX»v-"‘È´oý?b.ƒb¢å¸(-„³+s!½S ÃêJ4Â4MìÚÕ‹Ó§oÂîÝ»³VðÊrjy ¾+Ó<bî„l Ñ;HxfÚ&ÙÖÙãžzê2L÷¯(ãsjgN0 ’$•5‘â䌟Ï!_Òs*d;þ©*00ð¡ên 0>‰h:óv‰é>ŸUáÙÞžœ@Ìq †÷ñx&Vª²E9M+&¬Ö›^d®œÈŠ 1黓3É â¥/ÃceÞMÜ·êzrtqß&IVÂTÓ’Cx‰!™ÃáäP\‚³á{™U^=Ýw®\iSEÌ›eâ‰'þÏçí×”Ò±Äï·Z%ìÞ½@™& ÏDÎòØ0ò÷,)F¾â{´œÄgó>1w›¸ž iÉë)ãv)@Q“Òoܸ7nLiQØÔÔT–.[±X ñx<õÔ÷ÐÑñ0 ÃÀ_ÿõgÐÚzCÎÏÕuëÚyP“åܶ™†ú “L=Qr½o2}–“7=IãõÛ¶° ¸ ZgŸSG|ÿÃádåP6š¦!”8ȲŒ¾¾>H’T‘dŠõ©ÿ÷õ•Þª£ÜÛ,S¬«*ðîwïpMµ‹XQŒO"ªGbØZçð\^or’gçÒbhžLo€äsDÓž™ø aâøêR[´Óà¥BñÓÑ‘œ›Hô4éè°’#ƒƒÉû<ç°Íªš¬õTÅ64""¢ò«§ûNEI6ÐÖ4@–É9œæf«N³»ÛJºJ ¥®Vj2Y§\çånLìÁQII~¦†â®3ú`õšÕPÜóåL4àÌRÞäv»íŸr'ºŠ‰1ùâñ8†††ì¡Å(;1DP¡D4Ѳ¯X²œÚsÄ9ÔÐgœ•+Wâ«_ý+üÅ_¼Š¢ àý¯» fîQ’‹¢äŠK´ZL'†BËD –i;Šç3ÉVGýýïßTüF¬3ŒÏ©“hðEÉŸ"Þü~?<<úúúì ѦŠ,>`¥·Y¶Õ^°à¥j¯âŸDTÄ\'€uî½ÅJŒ{<ÉsàðprØ®b‡µ%šÖÄÄò™î©D²EÇÄdK´µYÉ‘Ž+vƒA+ÎÃaàŒ3’ÃvíÞmÝ«ú|VœŒ$‡è±Ÿ~'I¥Ï%HDD•Q/÷bXIJÖ©hšÇ¯79ªM±q‚Á Œb+5K•­çˆŒä<À¾â YGŸSOŒ Ÿ. ! B’$¨ª Ï·•©7`Å@(Ä›Þjb|Q- ­s™iZ×UÝÝÉÞÀªš:|¸ÆâSLT¾+¨øœT&:¬ž'™* LX•¬J2¶^ó›ˆ *1Ñ»s#ÀJ² 'ç:œ÷Vž‹ˆ¨>Õú}g0˜œŸKQ¬zÒû·þá6ãÜs“Ãsɲ•h)¶¹Çã©Ü_érÕƒö!ÙÀb2TÞDum‘>W%×Öoƒ®ë__ÔLB¶lÙ‚h4б±1¸\®šËrÖ¢övëæ³˜$©è2m#XØÐXÎÄ‹× ¼ç=oc`àãèì¼ ^¯ªª¦ 5”©<Oî9QÂa뀖žpñz“cèÃãIŽÍ[(Uµ¶‰¸Y(ć>ô(€¹Å®1>§†ø¾ŠaëLÓDww7dY†išÐu½bs¤ä¢i™'üôz­¸-vˆ=*/Æ'Õ q='&™•¯Š»U`U‰VüÅž³tXI9ñ·éXžëÆÖ@òÆ4ýš× k^ 9ñšL=ÃD²Ò]”UJ,Ó™DQ¯7Ÿ©·ýÇm8ä>4õû†òûqÉý*‘¬ð(ášÌ0¬xÉUMöë:‡árC›—2=ÕZ¾ïLŸYQ€[n9ôGÂ?þã]öë$)÷(éDƒÖP(„‘‘‘©Y™\“ÅK‰çâ†÷L§%~ =w`]{;W©X×;·iÀG4à_òtŠë£j*¡ lCˆÕ#qóYì°’d%t½°?éÉ‘p8÷¸´"9¢ëº=_ÃìÙgáóŸÿ6l¸½¨rFöÖìÙ²Ã"ñ#&'-”˜4;iøC_DÆ”ª&[W‰ b©™XÖͧ\wÝSjk®J™Éñ9Ò{©ªŽ~ôïpÙe°ZD)O¦Ù&â±öö‰“…ÒÔb|Q5ˆÄ‰¸ç1IJ\_Žò{‘yˆ" ™˜IÑÊ^Jü-’ ÎdÖ(1L<‰e˜ŽÏR`Ý\‰äE_âõΡ†ËÕËpÞ¤ ÎÏ‹!€d%·3©’~Í*#™ÌŸåœ‡Lr,G¼^ô6'®=í Ä= ÇrÛV¼'ƒ`0]ÒáôAQèºMÓ Å$\uôªR¾TiâZL‡ÕjSì[/^X•Ì9"âÖÙà-JÎY$‡ˆæ‘åäøÙ™’8Ù*lU5óû4 PÊG²¯£a¤–Ó¿É:îH¿BrR%1þ`b»‹› ñ>] «àC²õŸ XtÛ¢âw‘ƒ˜`þ’KþííÍðx<0M²,¸ÈžÔ³–y½V²4ÓÄ¢•–~Ü…B0 Ž;AD3‘ë†Côv"µwÈ’=A$$‡É ÑóBüN{²k]æÏŸø¾¾>1ÇÃÄ‘®[ËÍTŸXCj9[Di-àãT'ˆd“óó »a°¨H è@ Ù}pÅP`âÀáu0plwE±nB@Y•xÐYq«fg·ÁiÆs¡ˆùQTU…Ïçƒ$y Õ‹R^ß×W|²´ÜD¢7W/Ÿ¯øy‹òà ¦WöèºY–ÑÑÑ}ûîƒa|ÃneÛ×gõðï%"šQÄM•ÖuQ&¶Vw§sô¶×A}}@°Z‘e~-+b '®dY¶“¦iBÓ4;i${‹Ë² I’àóùìž$âõ}}}$ ápƒƒƒ)7ý†aØË§:&z‹å™3Sô:‘åd}Šª&“'¦™y><""¢z'æø’$à¹ç⃜Sôòá°5æk(ÂîlÃÿLfȬ|DIæŠqhóP àÛ”¬k~1™t®²ŠVê€aÀ[BfBU‚Õ{V ×›±Œ˜Üü&’”ìu –åO|®UkPÅ„J ÃW…Ã…Oð¬iÉVE…&TëKÜŒ…Bxæ™Â0‚ðù|PÓºÇHRöÞ&ºnM?œ/sš¶¼áá‰ëh€¤Ã É Áäû«¼›[UÙ  ÉqùÚ¿½ÉrÖhƒƒ@àn{ÒWÖÁÀ+ ŸÕ×to8 õZ"RÅ6’Ëžº §^á°T]×íÖº®cxxØ>Ñ‹ßtblO_¥3ÿ9˜fþ×x½Ö:´µ×£F I"IRJ¯MÓ I$I‚ß(Ð4Íþýù?ýS|yýzt‡CQûØ%˲ݪ—ˆhÆ "Ù¢MÌË‘‡i&ó~¢w®ž@Ó¬ŸR†¥©ŒÄ$„’$!˜¸±ÕuÝ>‡©ªŠp8lŸçDÏöùL Õ  /¤¬•¾  L¦Ô‰0¬ ‰>+ Âj`&î‹Äœ;ŽëDÑØFÌ5 ¥ÍÿˆÒF= ""ª7¢ÎDQLœ{î-ðzûŠz¿išƒ¶¯Ç&èî.ß±³‰Óð°U)üCÑ•<¿?ùw8œxdݤâZ¸îÑM*í‚A‚UІì½U ?‡Šsè¦ô²É°®“°êp½°êŽ‹¨—.&TjH0h]ügŸ¸=s%Ñã#×aº®ãŽ;àwÚí›,ŸÏEY‚px0ãû #û2Eòôç¥<ñ(ZN…ÃÉîæ†È¿†u3!îM¤Lïñ$'? ã1@~Àw FrLn‡ÁA+ùc&C¡L8¤·ÉÀ¯¬m£(Àðç†ÐÝ#ï6“w*Ž•ûÉÇ~÷Ò™1)ýtQh²¼Ÿi%1;::rv=ÍDÌ=$æ*©Ã(ìuÎn¶™Îã¦iÂ4M{üöÁÁA†¯×‹p8l÷<¿ßow±?b84¯ÈÞÜ}7¾Ö÷§PÕÔJ(EQì&D”›ó˜¸r¥õw1 %¨†ˆ¹GŠÔÝm%Në.˨jò¼ÃdJ’HŒ@GG‡$‘eápÇþ°ÎI¢‡‰è žÞˆ a9ÍiH+<îx܃äüBA}€nz¢ç}ss2>…Çíz'‰ka1çQ8N¹~~òÉ'«]T"¢ªõá°uí*æ=Öu«µ££^¯·èÞ)š¦åÞK$1vï¶ÝHž¿‹½L3M«‚§¯/µâTTû|ɹ ÃúlÓLžè½^«nRL-IÉDÆÊDy ­7š-Öz6¬þÄç§OX/zÚš‰:ÕL-…M39_C8œœ÷!ßçŠõì†Õ8eS† • =µ ¤ÙY¡O¨·Ï(}Ù²lµLíÙå÷û‡±páÍ8uêÏñøã#†‘}n“\ëÆÛù™ºH;“[ŒÑíèý!&~­«d~ŽÔÀEl‡mt¶‚G¯N«;lá5’\†¢XÇšîßGêÁEd„Ä Vר@H¶^#Ò†Û1¸€˜XI¡i¸ì©§7*õDô€ì+®ÑBIÄ|¢u©,ËYOîÙ’—¢r³£#²²’²%¡B¡]YÔÞÞŽÝ»wã›ßÜ믿Ë–}W]Õhß$*Šb'JÚÚÚ022b·º ‡Ãðûýe#Žn.Îmf»de{^µ‰ÛÓÀyçWETƒÄð—ºnU gšïld$q~¥ú•§X(d]‰k/q–~ÿ8Ó[¶†‘2D§ha4Mƒ×ëµ{¡˜¦‰¾¾>hšf÷@ç6¢¼œcŸg¢ð+_¢áiããÉ ¥jöb¦$kô‡£÷¹‘òHöÀÎô^Ñ€È4M(Šb ,–çõzÑßß_íÕ$"ª1íà uÏ"zi€¦Y£^x ­„u…Bÿ?{÷W]çÿU ½@›ô”B[ËØr TH@àÐQ`‘mAÑ­L‚WšÕά®Z\ãά.Õ­»ëÌW»î×ÝLÙ-ÞI†_UTÍAePÈAÄ ·’#e(m æ4Ó–Þ€üþ8ó9çÌd’™df23Éëùx¤iæræœ9óžsÎçýù¼?£ªõ؉1d»·×JtHOÌ +‰HÿO$â4úøýãŸl‹6Kw²CLò,ÊðäÒ‹ÌdÏx­$)N[h1D;¬˜¾á< 5à-b œaµÀèÆ8‘8£ &Úº³À}PBL¨”‰®[Ÿ“X¬ð„Š{N‘`Ð:YÎw1›ý“$ësùoÿ¶³gÒ¾ôù|èëëƒiJдÜs1ˆ²XÙI Eä/Ãú¢aÔ»†œ+Šõe&&8Ò¥‹’°†}á ñʵ&’*€µ­Ò%962 k(—«.Ÿ,[ëú /ë Ðf^xTV’a û¦ e]µd™….—þ{œ‰š–¾ðX𫶈„¾H–š.*z§*Š‚îîn„B¡±‡bìòz€u»ˆ³taÊ躎óÏï‡a¬€8"„Ãa»—è=×ÝÝh4Š^0ðéO_‡Pè_qá…ûœŒ¡¡躞Q4»6©Ï烢(žĤO~WM¿¾!‹G=´»»mmmS÷FU qÞí>Ö‹’¼¢¶ðÀ€Sc_Ì$ËÖ}ŠRÞòÀTFF%T4ÍÚ—¢ÿˆß Y÷‰ù²Ï 'qZsÜ£Lļ[îžábþEQ`š&TUµwvvÚ“¼û|>»qT\À«3=E—ãÚLT1 @ÿ ët|¾Ê^žîÄ÷€HnˆëjqŽêNœ°ç?IU1BÍ0 ûûÃ0 ôööB×uû{BŒ>ÉU¢/×è´ïÿû•~kˆj–H\ºç2å7Ý¥:EÜ‹Q§>~ÑVpعFsÄ5aX%»&"‰ØßÍ9‰s:‘£ÁÅWv'œöJ÷ÇÄ4'q¢-&†ÇoÐÑáÌ›&\ÅIA>2¬¤JVbE´wåzª `µ Lp„Š®Ýx YÛx® œâV+Àwà”,“j75Yï­8ÎÕàP[&TÊ$›Øè ³¤ŽªZI»|Q»6š¦Ù'}¿ÿ}W\ñIøý©Œ/ÿñÊöˆ–æfëÿâiºh{€° çB]|a¤¿SD/×Å‹]1°ÖwŒ`%)²’*Ðr#Ðý…1¨>X_M°‡ùý€ÀvÖziš“iAúuî6€h@¯ü‹ø$ ªçºÖ+×N ¦×µV"EǤJhPu …¬Ïi(4viªÉ0M¡PÈNbvvvf\h‰² cÉÕ¨•}¿ßoŨß_š/w¯[q!§ëºÝ{NœX>øà? ±ñ.ôõõ¡ÓÕ£@UU¨ªj_Xº·ÑjÄ[ŸèëS z랤w”쌰$'NÿFM†a·«ªuþ J8ΈpqÑ10ùâþsºQ Êšô1³’e¢ó@0˜Ùd&$ÍÄù±8ž‰Dà”Ö%%Ũq¬o„Édz?åäúþ×jâzÌï·â:8ñE“CÌ]$F™¹“$š«Ž¶¸ž U1’M-F‘ˆÆ7ÑH4Â2w‘;é*–G•!ªˆ>["ň^QED”V7 ëKQœNz€µ ÷ó§âˆUÖÙéTp¿Ža8YdÙ‰yÁÝ ÕýxAQœŽ€õ:¢#¼0ÖëˆN4î×qo[vÇ ñ^ÎcÜmVùÞ“ìǸÿ/ËΜ¢ây³gïÆÀ@/N>ù œ|òX¶lŽ=Šy󾌧žº÷Þ{ÞÿþU8p  ³gŸ‹ßÿþ÷8õÔ'qá…g~ùËGpÞyç¡­íjüä'/ ‘ø-–/_Ž à’K^Gw÷w°|ùr\vÙ,46^M31oÞ:4‘Hßüæ„Ã÷££ã>Üyç¿a``‘ÝÉ^„±èLýÔSÆã?^éô´'Úrë¼6°þþä'wàâ‹}š?N 2ÎéÜ¥ƒDÃh(äÜ–k‚uœNÙ+Àîô—G8<¹!àfúÇm¢=jýé1ψ(#šñ8ª~ÉÙvwÀŠžvî÷FÔ¢·_ÇŸÙ³#WãÚè}Ö q¤Å   ^ˆ™¦™‘„Ä„îs•@Ô$õÛ=qÅ…Ÿ{Ü\Kb4ªadΛTÔ÷AÝïô¥£#®vˆj„ˆ‘ìsбæ|“ˆ‹ fq®/LÓ¹ç ¢q._üI’«,!Sa&œsHúo¬sqÎ(j‹Ç¨:­Ó&QÞ²»ÛÚçÓy†Ò-M¢ç)`%NÄ]’$Ù ©îR\îQ*'r§)b~§‡moofµ æîÆg†= \Ϻ ‹gt­ŸÏ‡X,f'H:;;3¾?&ú= ÏÄHu•C܉‘<çJ"I v½HšˆdB®²ËîÛÄãÜ\ÏË®’ë#“³¿g0óñ¢H’œ$‰»MÓç˼?WgrqÎ(+^ǽmÙó亷Gü×®]8÷Üs?~?^yå9œ¾{÷¾„×^; ìÚµ {÷îÅÁƒñïÆC¥°k×.Ì›§à©§– ¯o‡ÏÁòåGðƒü¯¿^×_¯GCðjÕ%صë:ô~ó/½ô4þéŸÞ‚yóÞ†}ìýP?ÿù ÜÿýXµê"\}õ§qìØ“X¾üÎ=÷ øË_žEÿœ~z >úQçÍõûçž{ ‹-Â7.ƒ¦K—ZÛuôèQøýWbÎÍÍ×áî»÷àê«ß‡ÓNû,Î:ë*Ȳd—Ë ¡9sžÆOœ_‰øŒâþš—$ë—ãM/d7ìŠÑ`bbP+nÕe½i|ðËX½ú=‡ÃðûüÖÅv:hûúœäaÆk…“(ˆÁI¸’°"7‘nÖåXáNXIЬ xÕ†ý" õçxNv–ÔÈÁÓ1zZs³Óš¤(€_µF—ˆ…ï æÎgS ÀúQ|õÅmîIŽr‘e,}áì)pqTÜ‹¢´ÞDGñŠ‹7ÀJ*2 xÜá§‘Ìè"H§´ó3ƒV ïTU»—@'¬‹€À}·á‹ÿ~/þú«7Ú qQ'z^<üñã¾sϵK–èº> q‘±Ì‰£kÄ{.6§èÞѲìœß†ST5í²WYJOtNÈwŒ'Ü#WE‡ ÑÙ'»Ô–˜ëb`ÀzîêÕÖ¹H¦ˆuéíuF¤(ŠõZ}}Îc²/îó}]ɲõÚb]uÝÙ>±M¹ÚšÜåiDϽ\ñÅ&²g€bWÄ€«¨é¡hYì|Hd8za ò™=0¯ý-ÔÅ¢sþ^È}; »>tºîL âóné£5ÍÚ‰Ù8]wºÎNÁDéb%477Ãï÷C×u{dIv/rwOñîîî¼£"':aét Þ÷ñ\¼Ï¡P¨àó*ž®ò^Àˆ8ÉOrˆyÝŸ×Xú;H$@Dé=]×í϶û{€IŽ™KŒžçCªšyXs_šòÕ—+> élî~Ìd+Bf?/ßhÓBF£æJɲÑ©À0b• "‘(ü~¿]ÞÚyŽlî%îvìøžý·8Ž«ªŠw¾S®?‹·¾øñ·"àCòáÇ?þ4‘ü¼Å~NaÉÍ·á#€U®Û܉süCÎgþøÇoã=ÎìR¯ðkÄb1D"Í$ª*AQüèî¶¾cÞ÷¾ÇqÙeKAå•ýyUB:;; þ¾¦³`AqaJ—©¼÷¢Qg)ÖsÄp*÷èUµÓ «-q2‰iÏÉûƹ~"pJй¿û ™žlL¨”‰{Xd0hÅÚdN’ÅAÿK_Úƒ“Nº?ýéwìžvÍÍœøó…øõ¥CVà6ÃJ¨¤†b>1ßýÚÏxV À ¤Xúwº—x®èÉ¡¾9ÇʉDŒk´Joú6 ð¯P7Άùœ¢{  ÎNHÀ¶¬ç\ Ð2¬í ¥_{"ñž§‡— dÖ³=˜D[Ü‹ÅðìEáï'¶[©ÂV¯vë~¿•´ÌÕ«ÈM$1u]G4µ/Þ&TòÃ4.,Š2úìzoÅ"}ì:ˆ‹„I8,á—‰íð}ícøVÐØøs\ý\D£Qø|>ìúüçñ©Ã‡¡îßÔ¹çB:í4Üô©Oáâk®€ Õ‚u­-†¨õ­ëNIÑQ'ù‘ˆÓMÌ4G Í:ɱ×M–G­ä#œC…J@$+D"@\  XÇXQ WôÜ#FD»sv¨‰$àt Ǧ&kYb^ŸÏŠÑKR”ojiÉì $ŽÛ"RÐùFv­_ײD;‘tœÄ¨(+æ.K!+Dé÷úº‹ùýÖöÿêW ðz'ÑÃi¦ø¼œÜ\ìƒþÆ›ÓÒ=Hg”,º˜§®€ô·­Pƒ­ÎDš"q8CU4ÍúòÌõý*žã~àÔ”óùœïèuÌE¹œP(”󂸷·×99SF‘ˆóÎX,UUG%AÄ< ¢ŒYss3úúú:^â¹---èîî¶ç@Ï"9%˲L‰F£ðz½•ÞüiK|oÆb@p ,¤+gF©EñyçÔ€U¿^Ì18Ÿ{w)ÑH X `L’ÐXD§—XÌé0sçv|eÏç#â bÍSŠ¢ ¥¥ªªÚU t]‡ßï·GºG{ ‘H$g£vvg?÷5hwÖ„¦b]«õ8/Þñ~655ÙU(žzê)¼ýío¯ô*Î8âRh'™¦¦¦Ì±âOôbÏE×Eɫ͵;Hãdaý°®±b°:ƒa^QPØh #ýørä68óªPQ˜P)#ÏbžH$s´T¶\m›¡P†a@×u =‚íÛ?‡÷½o}ÿµ ,•È胬³`%F‚Έði|>¿°×õ"²õX„`<øž´æé/ãl¨d_3Iuæ8‘Ì¡ô—“–n p×›¸HnóP­uˆ¢ð‘#Àèú."".%IB,ƒßï·/2§Fn °'•$ÉÎp»/:E±.âw0Ä¿ÿû¿—æCSÆ}~¦(V£¤¨3/Ž£â„SÓ4{JQ·wâ'yb´•h Ê~¾¢Xñ·|¹p—œ’&Ö6ȈF£ø¯ зu)6?ð®¹æøú×ÏÆe—½ >ßüŒ/•:—WúÏÚÜîn«=Oô°—$8còÅlsî“1›r•ž`Óô '¢ôŠÈ}ŠÑbxK‹“ó”No¿PÈj÷Žý—óÝ"FœˆQZŠ2z®BEþøµƒxÿ[NÅW}ÃhQChÞ`½nw·™nÓvÅFÖ1´êxãoÞàŒôöè¹/0Ìôó8+\ç(~¿Ó‘}má>_É•Svßf_'‹‹ˆôÀˆxˆÜ t·ÝbžÆ§ÜPé )ަivÉX]×íQ$î\îFH1çžišÈHìC œwĉ(©)ÊUÇîX8e6eŒžÛ@ô$w?&×24Øß0áœée¨pÚbÄü±îûÅ×uúûå¹Ëžƒ±:7Ì?:úÉŸ°8°s˜ƒW^y/Ìy×]Œ5§¬ÁðZÝkX"-ÁYï> üöœñ¡3ÐñX–u.Ã_z§®8ÕÚ†ôá÷–}·`ÙõËœ÷ÖoŸì³Ú{Äe©øÓ ‚VÏw1awºï…ä—¬íqUKÄ{bd½o&¬6ª¨ëñ×>lg’p Μ¿‚hÔÖÓËË~9½ìhæ:p:‹}á«â·^; „Õ0bj uÿV‡ÿ=ø¿xq׋ ò¥ø„h4 MÓ žˆ¾©© ÷nÛ†úK.qnÌ꼚“»gPX N…ñ½!>«18qÂ!5‹ •2±'‹O×¾VÓ?--ÖÁ=ã\1yôz÷@Óž´/6ŦßïO—ç±lvît.¬µïÊC®euÂii‚}€Ó5Ô# óÔÊš°%]*€•”9µ€\*C2 ࢠSnp&CõExŸê”“œnO;äjÍ®RÀ0[ÑÈ-%âBPœ¸‡Ãa´´´ ··×N’hš†`0h_\ŠP---eÝÝÝöE¦¸€_ÈîÉ­·ÉZI÷<§Ÿ~z>aTj>°gÏ+PÕ£xñÅ#˜7ïF´¶¾³ðr¦i5ø‹Þ "! pw7\І¦P(¿ßMÓ‡3ÊøÓ]ÁÏ™ƒööõP”F¬Xľ¹†1ßžÏhTƒ¨ˆÝÉ–õpw9…wE ªú*ºôgÕ4»¥Z1MôÊ2bÁ^»Z—,KíGОöÀвê1©Ô kw›öÜ£¦E'øìùðF™@ÓôûÜ è—8Ë6 '÷¯i£C8›()ËNžTÌ=§;PDý_é €À÷A ô= ¸èÖ†à÷/Æ}÷í†iîG4ƒÏçÃY…Þý0Ö¹fç}VB”{€S¿y*nX¬áç]ocˆmOÏmvî¹³qqÿ˜æÉÐ4 ‘–:ý‚RfCU ÎhOÀZ–h œ÷=ƒHÀˆ9GŠøcNê &wv'ÜŸ;wy®éÐË\Ôà%†D‡QžLÔåyDG@ ¿ßH$bwÜͲ,Û={{{s¾Gâ|Uœ—º{øŠs]9çt“$)oÂê-oyK¥ßÚê&:¡‰ù‹T8pY©Æ = (³i.`¼ tF%ázNœÇˆF"IâžÈ]”Ú v¯vç"2•%F¨ ˆmnp‹ ¼À¿IVLvø¤¼š>Ù9ÀrsUëüG|Dï‰GM`QúØõŠÄEOYÀÃ:pÀ*Àù&p£ 씜ÄÈ÷tkÂ+`*Nc~¿ üAþàZù3e}â xì±ÇðÀ£àÝO^€W¿ý žO>ÇOà™Ï`hÕ¥ G–Áýѳ¨Ÿû:†††pͺ °í©»ð™wvcÞ¼yÖ÷JÊ~ 8 8à<oS€9ðð¥o| ûOÿNý]ÜY{,R±Ì»Ìy_kÀ.8ï›!’ì$1ö˜Àsº5‡î£V8]TqB @ÒY®÷äqŠ˜€&ý˜®lÆbÃ2 ÊÎ2ÞnXÕM§³@cúuDbk¿t½NJ²â|éeÌ6®¶°×\/Êv{ìu½Îãæˆ©Öó£°¾»½šõ^¬|’ø%<>ïìþËîJ|ôg QR°:›ŠdJÎóÉtC7u»¤i§¢ ~ãÆ‰—‰“%!s:‘\ÑáŒ`c¿‚šÁ„JDCŸaX$9ãH‡sò,Î X¥°DÖ1Ý9]ÔL7wÊÇâÇð;ÏïpÓOÆ?^ö¾0ÿ ¸8|±“ O¿ÅhMbߨõÒ!àg c‚±²b¬kJô òAö¥x¾+ËÕÑEà…N½Ö…BÀ¦Ûë÷羘Va¬˜”ÂkEoE÷qq 8=šDO¦ì²[ápؾˆH×@Éì$ˆø-ÉkýbžŠ#†0›¦‰o~ÓšÐò©§.Ä—¾t¾úÕz„Ãéö#1I‚(Ä›]S>r’‹E!êÐÞÿ:üå/]ho¿Ø.ãÑ××—19ü(~?Nƒs  ˜”W¢€Üîn+÷ÑÒb…zgg:DZ¢Š˽-î1ò"I”kâ1uŒd©hQ­ÔÙß/¢ÜŒëvñ•*¾ßàñÀØé”ñoi±ÖÝxjŒŸœ@Pvò9¢¼ÕwþQ”#9ÅgU”•Ÿ`ô@Gö±V[È}? ¿éNöŠâ¼žÈã›: i€´0L@y П|ëÆ)+†l÷Yÿë@`  K—þ g_z6—¡iVãQ xîÍÃ8tÒnÜ÷‰×±ýÖíøÎÛ¿ƒÔîü#®ø`–\jâXüU´ µáO³þ„•ßZ‰…+þßèÃ\€_ïþ5®^p5·þ-”ÅÀMÿqn:÷&ì^óv§ù1»¢»ð• ¿‚¯ÞðUÔý¦?ýìOqý¥×cuj5\ñ þøðñÐß?„Sî9óß0fÐDÝçëðò^ÆY÷œ…(¢ø‡ð?X1$`xÛ0^þÖËðœðàwïûÖZƒÇï×üâœ>š¤á…·¾€—^z Ë—/Çó=Ïã-¾‹"‹ðüÏcOÛ\Sw îK݇ÝïÚ»½ W\qüq¨ý*†oƼåóðúó¯Wú£Xµ"¿¸>Ÿóõ*&•DG91e*OeD#ªÁ)Ê…ˆäe ªËs¹GºKºf?Æ0 »l–»c8uÏã ˲}*—Ø ÀItˆc{IFä¸'` Ã9HŠÉ²{Y„BÎ}€µŒ%K*½{ªÖšÇ×ótëÎ ×j8+©oeªÍ£óÑò@½<å_/vŽ_ºü4Ý^–­Žnõ™át^rMŠ+&ËtÏJí~Œ¸.tOЕuÞ¶û‹_ÄʇÆÑ†<¾f îK¥ìÒ¶b$¿H†ˆ=âzL4b?ΪÏÀzK.â;Ãý·({æ.é‹Y+DßH¸{ä˜GŠr‹m:ÿñïÑÀ¹ ð¶ Ðëú~m72¦Î:é3ÄýéïÎSÕ¬ŽŸIŸ ^¤ï“2—á¾@Ù'ÃP¶ý¯<Œå»jݵoŽ=Š'v½.^ uÕ 4~à{P—o¿j-Z 3¾oÁ-v'5kÖŽ=ø’ünÀ?ϵ&pzzOp@½ øu]ò¦pØõž ø‡¬÷dH³ž/î× èŠùL`ŸfÝ· Ànï’K\õžü.Ç{Ë*'úÕI¨ÀrH¸3àmY¯3[†\¯³Küîï øEÖ2Þ ZÛ#³5×ëü.ý¸n׺vx¯Ì5¬çkd‡Ö4®ÜOœÆ(ŠSRغ†ŒÀ4ÍÑGLX×l €ðú³¯£õè=S6€óåñK{ÅÝ©³S͉ä›I%F¥Uçé3¹Ì©ôJ£­­ Û·o/ëkD£€4ðmpæ‘åt# è™Ô gø&ý]€²?}ŸÈì¯0ì¾?…¯ßq¾{ç{°tä0¯¹ _Ä'1â×ïXà50€E~ 7ýhk¶NâÏ—aÌZ h€œü‡üaÀ")z”–a¾Iqrç>±v×vöù|ˆD"ðù|ˆF£PUÕžëAÔÅ®îöBz5MF,¿¡º@»Ï;{µ¦³ÄãqÄãq´··WzU2ˆ^覱Ë\xÖYh9pïøË_0wî\»†OÌP¬ù>tÒ7·@:ù ¤½O@>%9á,ñ¹ 3b”•ªªˆD"ÀßþíÜxã¢âæÓ4§{½‹h'¥Íº—|±—®FxÛé£G¸eÒe·DY¢Šî»»ûa|íGÀ­·Ú‰bÐÊXë6LjZ4é÷EƒSÊ$ßq$DS€ñ €·¤çQz×ÑÓikÞë ýP?ë˜×ëØ´£†lÞ| ¾ øío—ã•Wæâ»ñ‹Çë0{Ínüë¿^ ãÛ€ôG@þ+à™¾g /—pÅígdÿ£2d8¥ D©×y¹hL2MW~ïJ$OIbðªA,}`)BzϾ^›oÀ³bvj6^:ñî9ël{nê^«ÃÏø f_~.öí{}ÁâÅ‹±wï^¼ûÝïÆ‰—NàÒ¡KÑ0¿Ï^ò,»ï1H†„yé_ðéOßÿþ÷ñ¦7½ Ÿöó¸ùÔ›±~ázÜòÝ[°~ýz¬^½€‡~‡Â~ô#¤R)ÔÕÕᵇ_ÃCƒaïѽ$ +_[‰ü÷„êS±ä±%˜}îlìž½½½½¨««ÃÉ'ŸŒÝ»wcîܹxûÞŽ+ž¿'œÀÎ;ñƒÀœ9s K:~uÒ¯pôèQ¬Y³Éd_|1>ŒE‹aÙ²e˜7oEÁÊý+a˜fŸ;’$áСCèééÁÙgŸ UU±sçN>|_ýêW+U§­­ úÓöQ×{MMÖ¡'²¾ËËHÑuÝž ZÄ8_e0Åÿ«¥wyv©L÷í¢Ñ2  " ¯¯‘H𦡳³ÍÍÍøÞ–-xñ·¿Åòå˱wï^\R_¤ç/t/¿¨D‘Åéþ;{¦¨;èNvdvmj²~‹mvœsAÔóu¿Gºît®H¿~GG¼^/Ïm³Äãq twã#?ý©³¿D-Hý{O"ö³ù0‚Î[žÌ=Ì2{¢ì2§ÙŸ`t¶?{Ù¯“^Æ£Z£}ôQü|ß>œræ™v<¿mùr,?r— aÙ²eØyõÕƒ#¦¦³ìù3ʹØ~1ÚÎÝéO”(I§\×½¢ÓžxŒHœtvvÚ 1rMüå©­])e¼†xMI’ð•¯|…ç¶9´µµáp—Ÿ{ÒWnžòןÀ*CänלRwâó ŽŸâÿTûªµý£LæÚS\ëëº3G$;¶¿ùÍÛœy|Déb@8Ðt?pó/ƒ`0ˆýïÇM^\¦Z£éE©¹tIâ‚5Ú?šjJ9Îm9BE0aÆfýŒ¿j€ã€ú"ø%ûs:gÊ×a¤¨×„þèý`ª&tC‡5pÁ¡#À"ƒõO!òÒr|íœoᾯ߆h´ŸÒ_@T³zV¹,E¾ §Æç[{­ ÿ4 |¨Àí“aeÒE; ½Ý¿Ý˜°{$Š^zš¦Ù=hÄÉ‚¨é,&óÃÁó)W¯¦™VŸ›€äý÷ãçÿ}<úl=æÜ”Bww·u¡è®õ㺘õ)bõÓÐr iv Ý?AËWëa¶8“P™×¯".DY:Ñx#FSe×-O7Þ¸¨lÓƒ¸«´¨*‰| ± ˜@¤Éºæîî S…²™¾.‡Õɪ®§å!Ç¿d pOxMedÀ¡Ñ +ÙáN¨Äóç@ôÛ€v9à_D¾Ègþ3Ó•NÄóL …uÜ4`oMàü3÷àÈ{ã‘?‚‡Ô‡pÑ΋ðÃ÷ü‘G#0ç%Ð2wv.<äIgâœs>‹3Ï<æcK°õ›ÂG¿üQ¨ê€ÝÛÇ4M|îÍ~|øåãŠÕÏLùáÔÊö;‰“Ù÷͆t†„“†OÂû_{?nŸ};–ÎZŠøyqœóÄ9hO;þ¸ùX³f –\°_¾ñ=x䑇q¼®Îî‘¿É5¬óÜ3êm<ûì³qþùçš„p&•$ ßûÞ÷püøqƒAhš†+bW>ÿùÏ#±Âýýý$ 7Ü`ßD"ö¶ˆ²?¢Æ0 Üuï]…B8ýÚÓñfåÍx&ö >ð@QìÙ³ÇÞ·/ãËG"{²ë| m—gÍÜô¾÷½Ïþÿ±cdz_.ž‘sî1šKždçº\²G›ˆ!]×áóùìÉWÅ|6W#|¹\ÝŸiwbG”tEÁk?ŒáçžCkk+¾ñoàóÿ8¾ü¸ýÜcñ8î9q§D"xêÄ ¼~ÕU8ÿškN÷p²2V«VY/.~gäG7dg…F×,t?F ›sË>ß“7¹ÿΖ£¤×¨eäk¨›á£&êèüùÖ SŽ÷MìÖÈ7η¦) Vä^P¾ý"æ;Oú~¿`¦; ‰NCâM’$H—\‚¯¥cZkìdºdíÕ®ýj$îh÷D÷â˜' ÀNJΤ١PÈ>7%vżDbBnQŽÏ=¡·•&ÆEIiÀ:ŸÏ¾ÍMœï‹ã¿¨¢ ~gƒÅwnöo[wÿR@~kÙ_GÌi%ÊàeÒRÅþˆã*“&D2¬j>Í7½Xíb.êX,†P(„ÿïöÿRDr$Ͱ- tûñíï|Ç~¸Ïž:aÔHÃõ[ƒÕ¹Nü-æRà\§ºñk˜\8B¥ö„RµÀÅ`*Ð:cé –-€üa@Þ™õ:®Iø"»õf@9–~]1Áaе~â»ÉDاÞt]Þï…¯@»À¥@l' Ïºû€Ø7¥P®ÌÏrΑAX'¦B8ñÿN@“5üÏ_þw÷ßÑx d^Š /a»VîÂÂß/Ä ?yKÞµ]—táÉ'ŸÄ¢E‹ðÐCá”SNÁóÏ?|à8pàöÅ÷a×k»°æÌ5øŸ¾ÿÁÁ“âCk>„W_}ÄñãÇQWW‡ƒâï|'t]·ËBŠž£Ç¿K?µ´è÷^4ôL´aDôr¯‘Ktx(hÙ¢A\ÈÕ³9â*Ic£Kü‰ÞÓ“8—©ø1¢ŠŸ¢m}²§]±XÌžÓD$Oì†ÖtNt˜ÉkŒÑ…®‡»œ»¸¢(v¹!q®*z…»{‡Ý @ŽD°ïØ1,[¶Ìy³²‡¹JcM„»Œ–0ÍÊ8B%·|ß[âkÓç+]žJŒš²qgn"Ážg¯ŠˆØu—ÌÛ#â<»„ û~ñ!¾ĵ«{ć{þLñÀ~½²%$r&Êž+´ÐD¬{9¹±’ÄsÛ1”ú}1¦iZFŠÏ«8n2QBÏmÇVP|ŠNíQ òÀ¼ ÇÄ€ãƒÇÑz §œy þýÿ«ž]åTR€#_þ2†Ÿ{'ÿèG˜?>Nûìg'?¹ H´ˆvât{§B+5gFŒPI&“H&“ðx<ðx<å}±¬Æ1Ò4Àg0I|ÂÐ4 Þë÷ ù“°ë;?Âï]ƒÇN{/ÎYs[¾ùM¬ºä’ò­:¨ÅÞ=üXô …BvI-÷É«è]#N¶ÅäììIB³'d§Üž¾è",«««ôjL‰²ÆgÖÁË+6MX1ÊzœN ;1±×ßhÀ ¯ý#¯ àçËW`ÎЭ8á9Eo_„Ù×ÝŽUsÏ·JÞ¾«®«šNœ" {ôÖpòÚ“‘¼?‰³GÎÆýÉûñŸoÄþ;öãþY5ÿç˜Ýö4¾°âX¦,ñ›¡þ‘yÐã@šœ»Àràì3—#ºÀ~@ÿ"€=€ïR ö = Ê©€þ" = (OÁªÅ 8="ĤeH¯£h¤úCÀöZyÖÜ,YCQÝÂé÷,Èa`Èk¾9ó1aÝõø(ð‹Çh®ßrú';åO?ÈHA3ÒNu=F¼Ž{=²’Yv¢ÛM,/ûñ‚„w¢S–øÔáÄ£?]Ú5¨> ¶VÒ'€¾ôñ2øŸ°'7—DB°Øuç.ì–wÈvÙ;Y–5ÖhÁ;|wäL„B!H’d7ŽØG³eÀ h¯hPß¡Â4Lœþùزe >ò‘```üà톗cÊ1l¸``Ó²MX¾|9>vþÇðÊ+¯àꫯÆë¯¿>æ±Îî1ú©Ò¼¥Š$Y'¢^]®yŒr4Öf4r‡BVD$DÒÆöE½¦9É!ÎláÓ³jY‹Ž‚X/wmþì}$fDïìÝ ,˜dÙÉÎÎP¥ŠÍBò¢HüèºnŸ*ŠbO]ʹMDùV‘ôˆD"vì ¢#Ž˜¸]$ÿDyw•8u÷øÍžoLî™s+ö³˜ÝP: ]uÏ=xu†$S&Ÿ/¼°«W;yfQeMLy’kÚ¹Bäj´q,ŽO"ÄHÿrs—·#ÂDòÓ=×evY«p8l';D=qõÄ÷…;YâžH$VÄw–ûAl{o8 ºý~À0¬¿ÝÉ$ðvŒ‹µ•=W `@Êîm”/Ñ‘,QÕÌï YΟxu}Ï%¢Q\öæ7—}ßW‹©jŠÅbv쉒mìê²,£³{–•IYb3Ýîó§ûž_@tè軿ÿÔòOPd¸À‡uà?­c£aˆìÝ õúë!}øÃÅe8Ë0UMU•PéêêBGGÑßßööv´¶¶–üuÌ?/€‹Ó'À¢M"`ÃÈË^^ŒÐ©NûA(„=ýýxùÕW‘˜7Ýx%}*IÖ}Q…¢|Ÿ(ÁðèìÚ¬îR[ìÿ‹‹PÑGœœúý~ø|¾ŒI1Ç“ý…ÃÊÄ<þ–·`Áš5•^²+i|¦\¡Ø¦8àjx\‚ª3BC|„5Íih ‡¡©é¡ÖšŽw,ù%v§Rxòš+ñÖëþɾøÊÅÔÒm÷ €Në¬E5¨aÕ¾è …B輨ßþÝ·á÷û±[ÛsÕsqåׯÌXÖÕ¸Ú>ØÎÃ<à@Iÿ‘§øÈèõp÷4 k½¤¿òYO¶âúvX‹9œT×+_“cÝã,é}Ò 'Y“]O¬—Í—k=Åíâ·h¯Õ]÷K®ÿNÒ®å‹ÛÆJÜÈpæòÈa¤ÃÉãÓgFi¿¢ãSƒõž‰ÉðÄH¨ ÿ3û-àW-â´tþlôb ÀaZ½ùôˆДÙ{VUU»>»h€½K›››í‰Xý~¿Ý¨"ÊaˆF!»n®’Uekt3‚»¿kÄœìãp ùwö¨ñ]—¹£__$)D‚ÆML,äN†dË×{Ùݳ¬™á°µn¡õX÷2ES,æ¬cV™³yGŽ”aÇT—rŸÛŠ¥q Àu¢ªê„'¦iÚ¥³DlºK™¸J#ÍÍÀ¶mr•uñ)ŽÁáqF¯¨ª*&4·éPÙÚÀÂ@³†T”¥/¼€Áƒ+½e7™øœ?ÿ¨]ñË4¯8Eû«@F’Ó]ºN\Àä_ÙíÜ¿#‘HFD¬›,ˈF£#>Dy,q-*Ö[$?%Irú÷¸Ê^A×Ñ ZIULJVy+UŒØs¹æÿQUˆFáI{a¢r%1²¿³]¹ä‰'Ë…=&ßwq¾v„p±êê« þ,Ô²r?u]Ï(s)F>‰Ïµè\JD¹•46µôпB 6A=å~üÍ9¿Â/‡zñ‰áa«´ë£Q,zo/€( iØ—ºýÚ‡í(žT UUòë²Ë.ÃÖ­[áõz‘H$°~ýzhš6nÆÓ:fÂém¾Îþ%}Ââ°ß·N¶¢+ ÍyæÍÚç5†`×.ààA9rk~ùUürÞ¸ëµkpäÈOñÚk€}¢ëî©‹û$Ö]¾@$<ÄóÄDíî ÔÞÞ^{¾ñwIÜ«ÏL)‹0Ñø´‡¼*ƒùÅ»{Ø„¶ðJ?© ù6@] „ÿ¼÷Yà$õ€4ï:¿:}u¡ ËÀÓ_¸ ¿øõ0GFðêÉ'ã/'?'Fzqúéÿˆyóæá+_9Ms.–öíÛ‡÷½oþçžÅ›Þô&Üÿý¸îº7á?8ùóçcïÞù¸âŠ_cýúýö ´®ëÏ P•ZZœ™½97P†™Ra¢ñi¿/7iÀ/4DN¬š.‚qäjHgáÿ"xчd(oØ eé ðßr*¤«/‚žn<C©ûîád—t^««Ãsï|'V­Z…ãÇãCozžüùÏ1géRkÖ,ôööÚ ¨â¸˜=¹{ÎccssfÂÐ#Bvh¾8Dw&ÅSxü­oÅì›nšöål'}n;N9›îÆZÜ«¦S€IDAT"Yâî`Í=RC$[Ü“—û|>{˜1âND"ôööŽšð\ü¥¯Ä÷ĨØnÎâìJt(,¡):¹JïeÏ1Dã¹mžsÛ,š¦e;E[Ž8vN5÷<`¹æÿÉUOü?×c³+•Lä9î×Ç|÷ˆRñXwÉM÷ëd?Çýz…>g2¯S ÏɵŸþüç?ãÉ'ŸÄ­·Þ:埫©Tô¹íf úV Ò—> ãWPoôs–‹SB@~¿ßîñ‰é6½õë*.hÇJXVýg!ÇäÖ¹L§ä_Õï“)4™øL$ÐÞÜ…ÐA:ÿ³ßºá0ðØc)tvá¿ï| ͫækƒxýø ^Ûµ wÞ¼½gŸ=sçâì³ÏƉ'ð/¼€ÔîÝ8cíZüìÁñ¶/|Ÿùö·ñ‘|±X Ï £ñØ1œœHàâ^ÀßÌŸSþïÿìžœŠ¢¡V½ãVã‹¢L¨÷¨Ý¸åóY¥0ĨɔÚðùÆ/·¡(£G›äzÌ$Õôg:+Q’³Á1Çû?xÖY•^ó²šì¹­ t]Ç“O>‰+Và’K.±KˆÆÕP(UUÑÒÒb'*ÕôÈsDR_z2sѯª/ßäæ¹d÷ÌŠ‘ŽŽxCƧsÛ*<ÿ­éøt)ô<à—ï?¼—]VéÕ-«bãS$LDC­išxòÉ'ñæ7¿gŸ}6/^ Y–í$ˆ;^CéÄ¡–]–Y”Ñ ƒ£ÎĨͱæI·eOxž}]ù_ÿõ_¹?ÓùŽs…Œè(¤«D£Gyn;=Ÿš¦ág?û~ùË_bîܹX²d ®¹æœzê©v²Ñçó!Ú Pv"@”M#§»»»‰Dì°Ùó¹ÛÄcÜ¿Ý󆹟 c4˜øýÁ~ßýîwñ…/|!cä©häwW/qÿËÌ~ìçˆN¿î|º«òŠ»†»2Š(õçþ[täp/Ol‡ªª¸ùæ›q÷ÝwÛÉ_‘ p'}Dr7»²x÷h:w§åìuë9ãmO¡Ïùö·¿{ï½###öíbÝÝïý‘#GðÊ+¯T:|ʪ˜Ø4ï?€è»íÄù0꿄΋æcã7_ǾŒ³ÏîÆ¢E/ ¥å.\xá…hiiÏç³ëóæAY¿o’e|¨ ‰Ðj?–ÔÂü<3ñV5#T¶mÛ†x<ž±ÚÚÚÐÐÐ0î‡æ-kÞ‚ùÏüþ|ÚÏ0øÚ~¼úêß`ΜÍxå•ë1wî\œtÒ¯0gÎa Ÿ„eËæâСû±lÙ2¼ôÒK¸à‚ 088ˆåË—ã`zXûòåËqèÐ!,_¾Ï<ó .¼ðBìß¿K–,±;v .,éöâ´ÓN *½+ж{÷n¬\¹²Ò«1%Û‘H$pôèQüã?þ#>ðTz•Ëf2ñù¹Ï}ÿß³8œºÏžþÿJ¥PWW‡—_~’$á•W^Á‚ pÒI'Î8ã 9rK—.…a¸òÊ+ñÌ3Ïà¼óγ?~sæÌ?~§Ÿ~ú”lÿtùLϤï™C‡a÷îÝ8~ü8{ì±J¯nYM&>/ºè",}æj<:bàõSãH¥RX¸p!Ž= I’°oß>œ}öÙ8pàÞøÆ7âõ×_ÇÂ… 1gÎ?~Üþ ‰cãÞð†Šlû¡C‡pøða,]Züdñ•6]¾g Ù'ƒƒƒØ·oÎ;ï<Üyç•^å²™ì¹íE]„D"Å‹cîܹXºt)æÍ›X°`öîÝkŸŸV*ö 1“Ž9µ¢}ÂsÛ±ãó‡?ü!ÚÛÛ188ǃýû÷C–eìÝ»çž{.Øï­¸ž¯¸â <ñÄ€¥K—âõ×_Ç¥—^ŠgžyŠ¢àÅ_ÌhÓP±˜ç¶Õ‡ç¶ŽbÎmgÿé‡XyÒ#è÷5Ì™óŽ=Š“N:sæÌÁ¡C㪫®ÂSO=…w¾óÐuÝnÿ™Š6Ÿj?–ÔÂ÷B5ÇûîÝ»±ÿþ’ŸÛVÍ•áááQ·2¹Ñïžþ]úïpÝú€ëÿ·TzÓˆjÞdâók_ûð5ñ×—*½ DÓÖdâsº_ˆUƒÉžÛ2>‰Êo2ñù|`Z'™ˆªÅdâó÷¿ÿ}¥W›hÚ+þܶÀ†JoQIœTéêëëGÝ–L&+½ZDÆ'Q5c|U'Æ&Qõb|U/Æ'Qubl9ª&¡ÒÐÐ0*‡‡‡ ÊvQy1>‰ª㓨:16‰ª㓨z1>‰ªc“ÈQ5 ¯×‹ááaÄãqVýÞd2‰uëÖUzÕˆf<Æ'Qõb|U'Æ&Qõb|U/Æ'Qubl9ªfhooǦM›ÐØØˆþþ~´··£®®®Ò«ED`|U3Æ'QublU/Æ'Qõb|U'Æ&‘eÖÈÈÈH¥WÂ-™L"™LÂãñpØQ•a|U/Æ'QublU/Æ'Qõb|U'Æ&Q&TˆˆˆˆˆˆˆˆˆˆˆˆªMÕÌ¡BDDDDDDDDDDDT­˜P!"""""""""""ʃ """""""""""¢káÜv¬ã~1ñY ÛEÅ›L|VÓ¾/æØYìv–r&Ÿµ°]4¾rž•Z©Ï±K¥¿¿¿lçε®f*îZÿÈyç7òüóÏWzµFÙ°aèçD¶£’ÛyçwÚ &¹>ã­[µm×xÛRÌ>ª•ÏáTª¥÷¤–÷ýxŸébão*·-ß÷Ìxû¨š¶£VÔÒ{R«û¾˜cg¾û§Ë±³ÛB¥!.ˆÜû¾V>ÓÏ?ÿ|Æò‡‡‡GÎ;1þþþ’¬k¹·e¬xÛåÞŽk¯½v$ÖÜ>¢ÉË›##µ³ïóÅg5ŸÛŽw¬,6>+ý½C¥1™ø¬–}_ì±³Øí,V1ñYÍÛEù•ûü¨ÔJ}Ž]*î÷lxxxäÚk¯Ù¹sgAë0Ýã &çP‰Ç㨯¯‡×ë444 ¡¡ñx¼Ò«–s]s ++d;*½hmmECCÄֽ·+ß¶LfUzÿT£Z{Ojyßõ™.6þ¦zÛÆ‹ÍñöQµmG-¨µ÷¤V÷ýdùîŸ.ÇÎjØG49hhh@cc£}[-}¦S©§Ü@]]<†‡‡‹^שؖ±â1™LÂëõfܾvíÚ‚¶«ÚöMN®ØjkߟÕ~n;Þ±²˜ø¬ôvQiL&>«ißsì,v;Ka²ñYíÛEù•óü¨ÔJ}Ž]*ñxÃÃÃØ¸q#+þ5MÃÚµkó®ÃLˆƒ“+½“‘H$F]Ä×××#™LVzÕ2ˆƒÏæÍ›ÇQWW‡ööv´¶¶´•ÞNñÅ“«ÎÝxë–J¥ªn»ÆÚ–böQ¾íœ‰*ý™ˆZß÷c}¦‹ý^™ê}8Þ÷Ìxû¨Ú¶£ÔÒ{RËû~²ÇÎ|÷Wâ{§ÇÎBî§ê“H$ÐÓÓƒ;v`Ó¦M·×Êgº¡¡­­­¸õÖ[áõzí¤ ¸Ð«ösÛ±âÑëõÚÛXñÙÓÓc_üÖÒ>¢‰+6Å}µ²ïÇ‹ÏmÛ¶Uõ¹íxÇýbâ³¾w¨8“ÏjÚ÷Å;‹ÝÎR­¿Xn¶ñâ³Ú·‹ò+çùQ)•ã»T’É$ÑÕÕ…žžÔÕÕ¡µµµ$çÎÓAMŽPE·±zIV’ȈnܸO?ý4¶nÝŠŽŽ;#—o;ªy;Ç[·ZÚ®böQ5mGµ¨¥÷dºîûb㯚¶m¼}TKÛQ-jé=™®û¾˜u¯¦íšÎç74Z*•¦M›°uëVÔÕÕeÜWkŸéºº:{bÒì‹ÀépnÛÓÓƒõë×ÃëõÚ ÎZÛGT¸ñb¨½}?V|N—sÛ‰Æg­låVL|VÛ¾Ÿì±³ØíœJÙñ9]¶‹,¥>?*•rc—J2™´G›lܸmmmvRd¦ÇAM&Tre—«1ËÕÐЀíÛ·ÛÙ;¯×‹uëÖÙ ù¶£š·s¼u«¥í*fUÓvT‹ZzO¦ë¾/6þªiÛÆÛGµ´Õ¢–Þ“éºï‹Y÷jÚ®é|~C£E£Q444Ø%0†‡‡‘H$H$jê3-z×íØ±íííÐ4 ýýýضm[ÑëZéÏt*•B[[:::°eËlÙ²¥àu«¦}D3^lµµïÇ‹ÏZ?·l|VûvÑøŠ‰ÏjÚ÷Å;‹ÝΩ0V|Öúv‘¥\çG¥R®sìRòx<غu+¼^¯]‘ ««+ï:Ì„8¨É„JCCè1<<\uÙ.‘ÁwsgómG5oçxëVKÛUÌ>ª¦í¨µôžL×}_lüUÓ¶·ji;ªE-½'Óuß³îÕ´]Óùü†rK¥Rضm¶mÛ†d2‰;wbçÎ5õ™N&“ðx<ŸU¯×k÷ «åsÛ 6Àãñ@Ó´Œò…¬[5í#š¸±b¨­}?^|Öú¹ídã³Ú·‹ò›l|VÓ¾/æØYìvN…±â³Ö·‹,å:?*¥rœc—Š×ë5rf:´™•ÌL|_MMM#>øàÈÈÈÈHÿHSSÓÈððp¥W+ÃwÞ9ríµ×Úë5<<ª†ýSmjå=™.û>W|•ض\Û‘oUãvT»ZyO¦Ã¾ŸÌ±3ßýÓåØYÉm¡âmذÁÞw##µó™Þ¹sgÎÏm4-ɺNÕ¶Œ>ø`ÆÏóÏ?_sûˆŠ“›##µ³ïóÅg-œÛŽw.;Ùø¬†í¢Ò˜h|V˾/öØYìv–òýŸh|ÖÂvÑØÊ}~T¥<Ç.…ááᑦ¦¦‘þþ~ûïZl3+—šœ”ÚÛÛ±iÓ&466¢¿¿ííí9kSV’˜¢Òª¥}?^|N§sÛ‰¬[-oåW+û¾˜cg±ÛYIÓu»ÈQMqV­ëWÎsçZVÓ """""""""""¢©P““ÒM%&Tˆˆˆˆˆˆˆˆˆˆˆˆò`B…ˆˆˆˆˆˆˆˆˆˆˆ(&Tˆˆˆˆˆˆˆˆˆˆˆˆò`B…ˆˆˆˆˆˆˆˆˆˆˆ(&Tˆˆˆˆˆˆˆˆˆˆˆˆò`B…ˆˆˆˆˆˆˆˆˆˆˆ(&Tˆˆˆˆˆˆˆˆˆˆˆˆò`B…ˆˆˆˆˆˆˆˆˆˆˆ(&Tˆˆˆˆˆˆˆˆˆˆˆˆò`B…ˆˆˆˆˆˆˆˆˆˆˆ(&Tˆˆˆˆˆˆˆˆˆˆˆˆò`B…ˆˆˆˆˆˆˆˆˆˆˆ(&Tˆˆˆˆˆˆˆˆˆˆˆˆò`B…ˆˆˆˆˆˆˆˆˆˆˆ(&Tˆˆˆˆˆˆˆˆˆˆˆˆò`B…ˆˆˆˆˆˆˆˆˆˆˆ(&Tˆˆˆˆˆˆˆˆˆˆˆˆò`B…ˆˆˆˆˆˆˆˆˆˆˆ(&Tˆˆˆˆˆˆˆˆˆˆˆˆò`B…ˆˆˆˆˆˆˆˆˆˆˆ(&Tˆˆˆˆˆˆˆˆˆˆˆˆò`B…ˆˆˆˆˆˆˆˆˆˆˆ(&Tˆˆˆˆˆˆˆˆˆˆˆˆò`B…ˆˆˆˆˆˆˆˆˆˆˆ(&Tˆˆˆˆˆˆˆˆˆˆˆˆò`B…ˆˆˆˆˆˆˆˆˆˆˆ(&Tˆˆˆˆˆˆˆˆˆˆˆˆò`B…ˆˆˆˆˆˆˆˆˆˆˆ(&Tˆˆˆˆˆˆˆˆˆˆˆˆò`B…ˆˆˆˆˆˆˆˆˆˆˆ(&Tˆˆˆˆˆˆˆˆˆˆˆˆò`B…ˆˆˆˆˆˆˆˆˆˆˆ(&Tˆˆˆˆˆˆˆˆˆˆˆˆò`B…ˆˆˆˆˆˆˆˆˆˆˆ(™P‰F£Ð4­Ò«Ai¦iBÓ4èº^ô² Ã@4­ô&Ñ$16§Ã0rÆ4ã³¶0§·BâÑ4M†1æó5Mó~š:ŒÕ顨cçXñÊX­,Ægu)åu'ÀcétÃx­.“×\ÇS^‡Ö.ÆåôUëq9#*±X¬f²¹¹Ù>0¸ÿ_«t]ÇêÕ«‰DÐÒÒ‚@ PÔò Ã@,«ôfÑ$M—ØÌõ÷L …ÐÔÔ”3¦ŸµeºÄãLÅ| ‰ÇH$’ó$7ÚqÞÔÔTÓ'ÂÓÁt‰Õ\Ï¥8væŠWÆjåM—øœ±YêëN€ÇÒé†ñZ=&¯cOyZ»—ÓW­ÇåŒL¨Ô2MÓ`šæ¨ÿת––ƒAôöö¢¯¯š¦Õt@ÑÌ•Ó!>'Ê0 D"ôõõÙ1Fyâ@Snº+§Z4EKK "‘HÎûC¡º»»ÑÛÛ‹ÞÞ^ö®¥Iá±³øcçxñÊX¥bL·céT_wòXJS‰ñÊkQª>Ó-.)ÓŒH¨Äb1¬^½³fÍB Èø‹Ì÷âÅ‹ … …2¾pu]GKK fÍš…¦¦&ûK¼¹¹Ñh‹/ÆâÅ‹F …°xñb¬^½:#ƒ:‘ÇŽ' Ù¿7lØ`ÿ¿„®ëhjj¬Y³ÐÒÒb?g¬ÛóÝ7žB·W|¡ƒA€$I€ÏçËXŽ{ÿˆõûJ,s¬=âq}Mñb¨øtǦøœ¹ÿÏdb°Ü±YH¬äŠO±ÿ$I²˲<扃{Ÿ26+¯˜x+ÊÆc©Ž•ãÝW­ñ8Ѹr/Eß(£§i$I‚ªªöcE©ÙžcµˆÇΩÕB·wªÂXñÊX­ K«óXšïºÓ½,Kg¶M¯v¢‰OÙNT½—Õ—ùâdF¶ßŽLs#FÂáðÈÈÈÈH00 G†††F$Iéîîñûý#Fz{{GFFFìûÅs{{{G$I²— GFFFFÂáð¨×PUÕ^‡‰<6÷ú¹ÿŸï=Û)^S–å1oï9…®c!ÛÛÙÙ9¢ªªýÛçóel€¿ß?2444Ò××7"IÒHooïHoooÆ}b¿ˆûÄòý~ÿˆ¢(#CCCöþëy4õƋ͑‘‘š‹Ïìx,$>'ƒS›…ÄÊXñé÷ûG|>ßHggçˆÏçËxÿÆŠOÆfåãÅâÈÈÄb¬ñXì±r¼ûª9#‘ȸÏïx)¨ªj¯£‡Gí‡\£òà±sêcµÐíêcg¶ì8d¬N=K«÷XšïºS,‹ÇÒ™ƒíDÓ¯hdddÌã)Û‰jã²zã2_œÌÄöÛiŸP ƒ#~¿?ã6Y–G‚Áਙ¡¡¡Œygg爢(ÏõûývP bG»ÿÎÈB›Ïd2ø|¾QïËX·÷œB×±íï£8@Š¿ÝîRq±*)×~Ë÷ûý#’$e<¼çÑÔ/6GFFj.>'Ó(4™œŠØ,$VÆŠOqð¿ÝÏ+>›•WL<Ž‹##‹±rÄc±ÇÊñî«æxŒD"ã>o¼ã¥{9ÙÛ“ëB½¿©¼xìœúX-t{§úØ™-;^«SÇÒê=–æ»îËâ±tæ`;Ñôk'ÏÍuÞsJM–etwwCUU„ÃaøýþŒ÷8{ŸÙC§%I²kκ‡àesïy4µÆ‹M`fÄçdbpªb³XÉÞ'?ÿùÏ‹ÅÐ×ׇp8Œ躞Q;z¬ødlVV1ñ8bQlãtŠÇBž7Þñr,¹^‡±:uxìœ~±Ẕs<ŒÕ©ÇciuÇg¾ëN€ÇÒ™„íDÓ¯(Ž{t]·³d¦ibõêÕÖUU3ÞMÓÐÒÒ‚w¿ûÝ9o_DcÝW*âDÒýþÆb±‚N$ ð÷—xž˜ÔO¬c0„,Ë=üÆ{M­ñb˜ñ9^œM&nKi2±rÞyçÁ0 {ÝÄóÜë6V|26+«˜xœ±L¿x,äyã/Ç{ŸLÓ̘ Ð0ŒŒ‰}©|xìœ~±Ẕ3ßûÄXZ<–Vo|–ëº`|Ö*¶M¿v"ñ¼±Ž§l'ª~ŒËêK <פµ—'WzÊÍï÷C×u¬^½Úþ‚'*Š¢Àçó¡©© ²,ÊvɲŒ`0ˆææfû¹ªªVôDG–e„B!tvvfü¼L®Xgñ躎p8<æíã=§”$IB8FSSTUµß_¿ß_Ðû ˲Ý! ŽúRËûl¬çÑÔ/6Ú‹Ïìx,$>'ƒS›b{&+W]u3ö©¢(c>OÄçÊ•+›VLݱ)j;Ÿ“‰ÁrÆf±±2U1M¥WL‰ˆ¨\é """"š®:::ÐÐÐPéÕ ¢ŸDÕ‹ñIDDÕªæ*W\q.¸à‚J¯FÑ8€yóæaÞ¼y•^•¢ béÒ¥•^)ÛŽÁÁAüíßþ-n¸á†J¯rUùçþgÜwß}8ûì³+½*E›.Ÿé™ø=³{÷nüêW¿ªôêVk¯½o|ã+½E;zô(Ž=ŠE‹UzUŠ6]¾g Ý'‡ªU«pÛm·Uz•Ë*‘H §§;vìÀ¦M› zNSSN:餚oDš‰ÇœjWÈ>I$8~ü8¶lÙ2íÏm'Ÿwß}76oތŋcåÊ••^ý¢Ì¤Ït­È·O:„Ý»wãõ×_G___¥W·ì&Ÿ×^{-<ˆ%K–Ôôg›ç¶Õ§}288ˆÁÁA\z饨¶m[¥W¹ê¼ãï¨êãfµKjá{¡Úã½í¶5ŸPÁöíÛ+½Eëèè€×ë…×ë­ôª­­­mZì“B·£££K–,©ôêV+VàÌ3ÏœQŸ…j7¿gÚÚÚ*½ªUéàÁƒÓâ3ÇÇÑÞÞ^éU)Útùž)tŸˆÇMg©T ›6mÂÖ­[QWWWðó.¼ðÂiñY˜‰ÇœjWè>™ ç¶“‰Ï%K–àÃþ09Ud&~ÏÌ„sÛÉÄçßøÆiñ™æ¹mõá¹mñV®\YÕŸ…j?–ÔÂ÷BµÇ{9Îmk~•ér²ïõzáñx*½%±víÚJ¯·£ œqÆX±bE¥W£$¦Ëgß3$L—c§Çã©Ú߉š.Ÿéé´OŠFÑÐЀááaÄãq #‘H ‘HTzÕ¦9Õg:í“bÍôøägºúL—}R 39>§ÓyÔtùLO§}B¹Uû±¤>ƒÓ%Þ'¢æG¨T󢉨öà˜ˆÖÖÖJ¯·£ L§„Êtù,ð{†„érìôx)•™ŸÓé¡ÜªýXR ŸÁéïQó """"¢j“=,¿­­ 7n¬ú‹6¢™€ñIT½ŸDDTíj¾äQ¹q„ Q™UóDD3㓨z1>‰ˆ¨Úp„ QL¨åÁ„ QL¨åÁ„ QL¨åÁ„ QL¨åÁ„ QL¨åÁ„ QL¨åÁ„ Q'WâE“É$’É$Àëõæ¼ÏãñÀãñTúý!šQÆ‹M÷ýŒO¢©Çø$"""""¢rc»-Ñø¦<¡ÒÑÑ®®.466"™L¢®®wÜqêêêÐÕÕ…ŽŽ466¢¿¿íííhmm­ô{D4#Œ›ŸDÄø$"""""¢rc»-Q~SšPI&“ضmvìØ††€ªªèêêÂÆÑÑÑ­[·Âëõ"‘H`ýúõðz½Ìx•Y¾ØÀø$ªÆ'•Ûm‰ 3¥s¨$“Ix½^;(`íÚµF<G}}½=”¬¡¡ ˆÇãã.óСCyCT.ñx{öì©ôjm¼ØÛ9™øÜ³g‰D¥7f T*…x<Ž£GVzUŠVŽøÌ„ UÌtI¨Œ›&Ÿ{öìA¥7f qÂ7*åˆO&T¨’’É$‰Ž;VéU!""""¢´r¶ÛŠDS©¿¿¿ö*n===öаÖÖÖœUȱ¥K—¢½½½R›A3\{{;.¿üòJ¯FIeÇ&€IÇçå—_ÎzšTíííX´hQ¥W¥¤JŸ‹-B{{{ÎÉí‰ÊÍëõÂçóaáÂ…•^"""""Ê¡Ôí¶, F•ÐÚÚZ–vÛIÏ¡’J¥ÐßßúúúŒ¡`…‰ˆˆˆˆˆ¨ÜØnK”ߤF¨tttà²Ë.C[[:::Ç¡ªjAs%lذš¦e4544Œ&6<<Ì &Ñ+6Æ'Q¥1>‰ˆˆˆˆˆ¨ÜØnK”ß„G¨ôôô ««Ë®©·mÛ6{ø×† pï½÷¢®®.çs»ººJ¥°víÚŒyO<¼^¯]óÞëõ"‘H ™Lbݺu•~ˆ¦½ñb“ñITYŒO""""""*7¶Ûf •x<ŽÖÖVx½ÞŒàÚ¸q#vî܉þþþ1k²'“I$“I´µµeܾqãF´··£½½›6mBcc#úûûÑÞÞ>fr†ˆJ'_l`|U㓈ˆˆˆˆˆÊí¶D…™ô*“!‚o,"Q“L&íž·DT~ùb`|U 㓈ˆˆˆˆˆÊí¶D…™pBÅëõâÖ[o5¤««« ÉdE­’¨z1>‰ª㓨:% £¾¾ž“vUÆ'Qõb|U'^wM"¡²víZô÷÷cýúõðx<†ªªæP/""""¢´Í›7#Ããñ ™LÂëõbË–-•^-"㓨š1>‰ˆ¨šMªäW{{;Z[[ÇíQ)^¯—É"""""X=kwî܉{ï½uuuH&“PU­­­ìiKTaŒO¢êÅø$"¢j7á„JWW<¼^/Z[[+½þDDDDDU'™L¢µµÕîp$J# WzÕˆf<Æ'Qõb|Qµ›pB%™L¢«« ;vì¨ôºU¥µk×bíÚµH¥RèïïG<GCC¼^ï¸ÏDGGǸ‚•KGG~øá¼ŸÓZ7Ùø|øá‡ÑÕÕÅŽ…4åD;Ìàà`¥W¥ì&Ÿ@GG¼^ï´ÿþ¢êÇ‹ÅXµ‡h™pBÅï÷#•JÙ«lW¬XÁ9¨"êêêàõzs¶ÁLW‰O‘P!ªǃ .¸¨ôªÑ™pB¥½½Ý.AH$0<<ŒúúzžX¥uuu!•JaãÆ¬Æ°††$“ÉJ¯ÑŒÇø$ª^ŒO""ªv'MæI]]]¸ì²Ë°~ýz´µµaýúõPU‰D¢ÒÛCDDDDTD£¤R)$ –#!ªŒO¢êÅø$"¢j6á*ñxÜž(sݺu¨««³k[nذ<òH¥·‰ˆˆˆˆ¨¢Z[[ÑÓÓc—)éïïǺuë8™5Q`|U/Æ'U» 'TzzzÐÚÚšq0óx<زe âñ8âñ8kWÑŒ·}ûv»D®ÇãaïZ¢*Âø$ª^ŒO""ªfN¨ £®®.ç}cÝNDDDD4qžA¢êÅø$ª^ŒO""ªVžCÅëõ¢§§gÔ|)]]]H&“hll¬ô6•Ô„G¨´¶¶"‘H`ýúõhhh@}}=’É$†‡‡ÑÞÞÎQ*DDDDDDDDDDD4íL8¡[¶lAkk+âñ8†‡‡±víZ{‚z"""""""""""¢éfR ÀªgÉš–DDDDDDDDDDD4LxˆÇãØ¼y³ýwWW:::J¥*½=DDDDDDDDDDDD%7á„J"‘@[[[Æmñx6l¨ôö•Ü„K~íܹ­­­Ø²e‹}›×ëÅwÜõë×#Ãëõæ]N*•Âðð0<}[2™D2™Ìx\cc#çf!šB¹b`|UÆ'•Ûm©ÜL0 @Q*½&7á„J2™Õuuu  h4 hoo·oëèè@OOOÆã¶oß^P‚†ˆJ#WlŒO¢jÀø$"""""¢rc»-•›®š6C*èêêBkkkFb¥§§‰D"g²Å­«« ñx===ظqcÆ}©TŠHT!ãÅ&Àø$ª$Æ'•Ûmi*Ér¥×`r&œPÙ¸q#’É$TUµhxx‰D[¶lÉ›Pill„Çã5D °&»w—#¢©3^lŒO¢Jb|Q¹±Ý–¦Š¦Ye¿JÅ0¦.A3áIé`Ë–-رcÐÐЀuëÖAÓ4´¶¶æ}nCC¼^/êëë3nO¥R€Í›7cÍš5¸ì²ËÐÕÕ•wy»wïF[[ÛÔ¼[DYÚÚÚpÏ=÷Tz5Jb¬Ø&Ÿ÷Üs:::*½i4% ´µµapp°Ò«R¥ŽÏÁÁA´µµÇD¥ÖÕÕ…ŽŽìß¿¿Ò«BDDDDD.åj·M$•Þ4ªB†Qºe55¾­£££,í¶PéêêBWWÖ­[‡µk×ÂãñØÉ”RI&“ðz½Ø¸q#¶oߎx<ŽM›6ÁãñŒ;”låʕؾ}{ÉߢBlß¾}F$ &Ÿ×]wݨ¹ˆ¦BCC¶oß>#ϥK—òØI#ÊÆÆãñJ¯ €í¶Ñ(à÷—ny¥L¨È²5âE’œÛÊÕ&YЕÖÖVÜqÇðx<ضmÚÚÚÐÑÑQÒì¢hüAèõz±nÝ:^lUÆ'Qõb|Q9ñº“ ³&“/•É&Tr­ƒ®[?†QÚRb¹<‡J]]Ö®]‹µk×°&¡ïêêB2™´Ë~3b%™L"•Je,£®®®¼[ODa|U/Æ'•¯; ¥tÉ ¿ßšGe2B! ·wôºéºµLUµ~ÊeRs¨ÀÚµk±eËlß¾ëÖ­ÃÎ;±~ýúIZCÅDM¾T*…žžž¼“ÜQù1>‰ª㓈ˆˆˆˆˆÊ‰×SÇ4Ë?Âb²t½të&ʇ™&ÐÒ2öãb±Ñ¯™k„ŠÏgýTÕ•ñ”b>•ÖÖV$ ¬_¿ýýýhmm-h¢{"*/Æ'Qõb|Q9ñºsêD"åaQ E)ݲb1kî“Xlô}ºn½V,fÍ‹â~?$ÉJœÈ²s[4 h;œRÚuÌeB •x<Žd2iK"‘°'änhh˜ÐD/¹&$Ú²e ‰†‡‡áñx˜å$ª€±& c|U㓈ˆˆˆˆˆÊí¶•%ÊVUŸÏJ\„ÃÅ/KU‘$îÄ`%SDY/Ÿot‚Ä0F'Tä%þàÒÒ­ãX N¨lÞ¼]]]ظq#«vÞ† ÐØØˆ††ôôô ™LbëÖ­E­P±#]ˆ¨|ŸDÕ‹ñIDDDDDDåÄëÎò“¤ê-ù%F‹”‚aXII²J¹¹·?µþöû­ÿ%|>zvjÞ‡‚*‰D;wîÄŽ;ìÀéééA}}=¶nÝŠºº:´¶¶BUU$“If(‰ˆˆˆˆˆˆˆˆˆˆ&À4Ë_²ª>ßÄŸcÖ¨÷s ÃúZ#rü~'Y#Ë™ó¤ˆÇŽ7?Jè§€> ÈS0MA“Òïܹ^¯7# DZvíZÔÕÕ€=Ô+™L–w‰ˆˆˆˆˆˆˆˆˆˆ¦1?H5Ò4+Ñ¡ëÖ\/cÉI"*n"é!I£(¦™{$Œ®[Ëòû3“N† ð/t&¦/§‚*F:‰Çãhll̸M$Wˆˆˆˆˆˆˆˆˆˆˆ¨p’4:ùPŒ@ ´ëZ ‹ñJ…B™‹9O²o¬äIggf‚$sF³ˆ$ `Ý&IÖ;¡cæò'­¤•T)_V¥ „J}}=âñ¸ýwOOÀëõÚ·¥R)$ Ô××—me‰ˆˆˆˆˆˆˆˆˆˆ¦£ìÉÖ‹áNF”B0h%>r%Sb1g$JvÉ­±Juù|V$DÒ4ë9ÝÝÎû!’9Ù}àðÚ‹¯á{ÿGÍÍÍ¥Ûð,%TÖ®]‹d2‰Í›7£§§Ñh^¯×‘’J¥ÐÑÑÇÃɉˆˆˆˆˆˆˆˆˆˆˆ*¨˜òa¡ÐèÄ…Hlhš•@qÓu+á!Ë™£Mt}ôm[·©ªuvÂÅ4Òbî“¢+VÃsÏÝŽ;¦á¤“þ€Àì?C‚c‰oâ–[ŽÂçóA×uÜsÏ=8xð`Ißׂ*wÜqâñ86mÚ„úúz´··°J]vÙeˆÇãØºukIWŽˆˆˆˆ¨–%“IÄãñŒÑÞDTŸDÕ‹ñID3•H$”jY“D^<ß-q?GÌ…¢ëVÒššr'uÜeÁD™3Ã0`š& ÃZoYž|òIlÚtÄ~\4 <øàwñûß/Ä'?ùI|æ3ŸÁÂ…oFâÄ<üyø.œ§~+Wþº®#àšk®ÁÂ… K¸‡€“ }`CC4ñN¸466bûöí忈ˆˆˆˆfºŽŽtuu¡±±Éduuu¸ãŽ;8ï Q`|U/Æ'Íd¹JZM–iZ#<üþÂˈiš•´0ÍÜÏQU«DWö}'D¬çµŽâ±š¦AQƒ LÓºopð¿pÚiïÅÝw7`pðdœzê^ýY,^ü¸÷Þ~D" Ÿ„ä«§à ÎÜ=s0kÖ]Ø´i+óç–|<)ýXêêê˜L!""""rI&“ضmî¸ãlß¾š¦!•J¡«««Ò«F4ã1>‰ª㓈jQö$ìŇ K~¸“.cÍQ"IÖ²&RöK–äGöóÂa+ábÎÁ42`Ѩóÿp8s=ÝˬףQÜïçÏ~v¨¯¿‹oÃßýÝ!IQ¼ýíGqÎ9§cppÃÃ'á­o½/½ô;üee.^S‡…‡_Å‘#_ÂOú"ŽmÀ®]+ñâ‹óJ·ƒ0„Š˜C¥­­ ›6mB"‘(éŠMÉd^¯7c~Áµk×bxx¸Ò«F4ã1>‰ª㓈jQŽ¢N“ åžô=×ã„h4÷¨I²’c•é"ëGl‹aX ¿?÷kvw™÷¹Ë)Š“t1 +i"nË^V8l­§$wßý ¶m»°ÿ/°mÛ]xõÕ7ãÅ?ƒùó߃7¾ñ¯ðÔS§á÷¿ÿ=Î?ÿ|tu­Â¯}úûûñÎç߉ÿìlDKòÏxï{Ï‚®[/¶xñ,\øjév&PikkC<GCC’É$6lØ€d2YÒ•!""""š¼^/¶oßnÿJ¥ÐÓÓÇ3îó:ÄzñT1ñx{öì©ôj”ÝdãsÏž=ìXH‘J¥ÇqèСJ¯JÙM&>=Šx<Î6*ªˆd2‰'žxǯôªP•ªD—àÕ11*e¬("©‘=|öóEy-ñœhÔ*ëŽ~N0h%_ÌÛý~g¤‰ßo%Q4Í™x>ßvX¯åÜ9B0<üð/pæ™ë°bÅ Ô×?‹9s>„ÆÆ+qÒIÀw¾óe{›—-[Ãy­ž«=XU¿ O=õvíªÃÐÐ¥øÁà©§*éþ)(¡"L;vì@{{;vìØúúz¹$""""Ê£§§ëׯ‡×ëEkkë¸=|ø0*T13%¡â6‘øÜ³gúûû+½Ê4 #ãðáÕ^•)Uh|2¡B•”L&‘H$pìØ±J¯ UX®’[“áóY£7ÆK’Îäï€3©{.’d=§¹yô2[Z¬ß²œYrË4ÇžËE×31â·,[ë]L–­$Ìxó¸( pâÄ <ôÐ`:ÿð2:„ƒÏÀ{Þó;v ‹€ªçœs;n¸¡ÝÝÖ{¥ªÀUW]…ùo™˜ÿ†ùxúé§qôè{pÎ9·ãàÁóJ³c\ ž”ÞëõfL¶víÚ’¯ Ñt‘J¥°iÓ&$“IlÙ²¥ y—.]ŠöööJ¯:ÍPíííèèè¨ôjL‰ÉÄçå—_ž7éBTííí3f„ÔDãsÑ¢EŸ•T(¤TW>†‘Y2Ë]vKÓ¬1‚E¼žaXI‹B–Ô0Mg4 `%L$ÉZŸoìíu—s'wÄkˆQ1b"Ñrçÿ†_ýê& žÃ8 Y–aš&V­ú޹ŸúÔr|îs/ÂëMaÍš¹€¿ú«¿ÂîÝ©trÈÊ ‰Òh² |üêCûŽõ:³oŸ—þ#>úqàöÛWáŒ3þXêÝ]ü¤ôDDDDD4Ú† àñx iZAµD4uŸDÕ‹ñIDµF–K7BE×$Jv©.ÃpF™tv:ɧdVîus'<²—§ë™“ÈNé®\“Ò‹ç‰Q,‚Hn˜¦“lq'^dÙQhšAÜuפRÿ‹–ô™h4 MSñÄóñÑ.ÇÒ¥/àCúî½w1ü~àýïÿ öí[‘~ k£ÅZg]pÀ>ëuê»êqåŠ[pûí­˜;÷|¼úê«xÓ›ÞTÒýÍ„ Q‰uuu!•JaíÚµˆÇãöË‘U㓨z1>‰¨E"O¨Œ•÷‰nŠâ¼NKËèQ ÙTÕJ¼(Šõ“=:EŒ†Ñu終Aëy²œ¹ŽºîLlÝz=áöÛ?K/®¿¾ Ë—/ÇG>òìÝ» ÇŽ]‚yóŽ •z Šr3ÂakY—^ziz{ {„J,挆џ´¿a×J‹ ÷¯¾ºsçöh,é¾+(¡R__ÆÆÌöx<%]""""¢é¢½½ ?DUŠñIT½ŸDT‹ü~+1¡ª…?G’œ’Uî$‡I’+Ñ¢iNâÃ=·Š$Y£d4 ý:¡µÌìõ ’_€•X‘e§L—$Yë¡i£çTó®„BÀ7¿y^xáÄbaD"b„‹†çžûº»»¡iü~?B! ¯¼tu­JÏ;s çœs~üãã½ï}/æÎ]†T èíý:ëý ‡­u:ÿü=ð§7\QœQ<ÁõV¦WLN¶œ}ö^¼úêJ”ZA •††{äI2™Ìnéñx°nݺŒ 뉈ˆˆˆˆˆˆˆˆˆ¦»h´°Iá1ò$×¼&b‚{1r$›H¤èzîÉäuÝIˆøýÖmb´Kv 11²E×Q1î¹Yb1'‰“]2LÌ™RW· ÿú¯/㦛®´_÷À®]C,¶ª ¨éLŽ,[ï“aX¿[Z ˜¦‰‹/¾þð2{ýÄH‘4 'žXÃè³K~I’³ýò€AzÅ ¯Å«¯~@ÖО"Mh•ŽŽ¨ªŠŽŽ$ $ lÞ¼×^{-¶mÛ6¡N¥R9k`f'lˆhj›ã“¨ÒŸDDDDDDTnl·EÉ1’(••+É YÉE±æIq—ù2 +á"n¯)b>AŒàðùœòbÙIJDâE” œ‘3b}Ýë¢(@<¾©Ô¹Ø·ïfÄbQ»LØk¯íǹçÎU¢L–ÿú¯§ðýï?„Ï}î ÃJ¨VrD$€Äö¸·Íz¾l'TÅ™C%úß@ô[éILQ²LÆYgUòý]pB¥££]]]زe yälß¾Û·oÇ#<¿ßŽŽŽ %U¢Ñ(ººº2nëêêÂúõë±mÛ6¬_¿~ÔýDT~¹b`|UÆ'•Ûm'Æ]6k,šf%H²Ÿ—+É!&ŸÏ.Ñåó9s—¨ª5߉;™cq/’6cM^/Ë£GɸG¡\{m4 ؽ;…G}tÔz~ûÛ˰jÕ³xë[¿Ž;îø4>ðOâÊ+÷¡®n>ñ‰%£¿gÏoðÆ7ö`Þ¼åxøá‡!I¢Ñ(WÖ$vJ‰„IÞ÷WîÛ¥ìši%RPB%‘H`Û¶m¸ãŽ;ÐÚÚšq_]]=9X4ß'VðmÚ´)gò¥££[·nÅöíÛqÇw`óæÍÌxM‘ñb`|U㓈ˆˆˆˆˆÊí¶“—«|à$@'y"ÊeåzŽ(óeVr!s„†“l4ÍJ˜È²µÜ@`ô2Åsb1k¹"ÁO>¹Š¬[—IJe¯dv1¾ýíe0MsÔè˜=»ßýî-øüçWaþüùö|(c‘¤ÑóÈdóûåJovßXäÎÌ£ „J<‡×ëECCØٸq#R©âñø¸ËjllDkkë¨eÅãqÔ××Ãëõ°æmihhÈ»<"*±b`|U㓈ˆˆˆˆˆÊí¶“Ó×—9±¼›…âNŒˆ„ 0zFs³õ[”örÏ‘"&i£P|>gî”ÞÞÑ#Pܯ'žcN"çòËw㥗Nþᾊ»îš•ñ¼_üâýÅìÙKpýõ×»¶IG4…,8zô(ž{î$(Š-½²>ŸÏ.3†fšõœóÏŸ I²ÖáœsαçVQ †2†hÐÈÏeÝQÚiS2”P.ha"¨ÆÓÐЯ׋úúúŒÛ‰<OÆmõõõy3»wïF[[[ùÞ!¢q´µµáž{î©ôj”ÄX± L>>ï¹çtttTzÓhJ$hkkÃàà`¥W¥$JŸƒƒƒhkkãmªˆ®®.ttt`ÿþý•^"""""r)W»m"‘¨ô¦•ùáž{$×cÜsÄbV"E’F'AÄœ*ÝÝÖo÷èE±^GÓ¬d…aŒ.óåNìˆQ+¢tVöè–¿ü¥çœs~ûÛ#ðz¯ÇÐÐPÆú|ç;¿Åþgžxb>R©ûPWw'LÓ´ç=yþù3pþùËÒËV‡±hÑB¡Pæ$ö‹Åìĉ®ßúVTU͘e²ä倲Ìuƒ@~øa>|¸äû¼ „J}}}AI•b²’¹–Ÿ¨¹¬\¹Û·o/ùCTˆíÛ·ãºë®«ôj”Ýdãóºë®C{{{¥WŸf ††lß¾K—.­ôª”Ýdâséҥؾ}û¨2žDS¡µµíííX²dIñ #""""¢²+¶Ýv¼ªGµN×Q(‘Èè¹T #sTà$5D‚$ûñ‚{>1WŠª:s¶èº•\q'IÜ%¿æÏß‹M›>š±„;K$ÉS’øô‡?ñ~~¿¿¨„Ša‘.À8àºQ²^WuÝ)¡‚*7n´'%J¥Rö}©T ضm[Q=ÑFâððpAÙN"*/Æ'Qõb|Q9ñºs|²lýäJ¦øýN"$µ#þöûIè…ô {¹€3 FÜ&INRÆ=:E¬‘(O=õ>ùÉOfÜ·{÷kRúpʼ$’$ÑÕõlú¾%øÎw¶" !‰à¥—žÆ™g&±víyPUñšŠ]¢K$„D‚Ä0 H’„p8 ]×a [lÅû®~Ÿ½±˜³m¾±&~)iÆ^—fÝ¡ç¿r>Î=÷Üïí*ÐÞÞŽÖÖVD£Q\vÙePU—]v.»ì2ôôô`ëÖ­X»ví¤WÄëõbxxØ“H$L&±nݺ’o4M 㓨z1>‰ˆˆˆˆˆ¨œxÝ9617Š˜ Þ=ØB×­Ñ%†aÝ®ªÎè1Q¼˜%‘¨œ‰ìEBE$orr ˜O~ò üèGÿdßþÜsÏá¹çœÒß¾ú¬¿h%Î9çÀܹs!Ëfúµe¨ªŠ={>ƒn8š6ºœÙèõ•ab±b±"‘®8ï Ô?ëŒrRÕ܉ ÉPÀ¿Pæd¯ °bߊ²$TNžÈƒÛÛÛá÷ûÇÑßßÀ ¨É–ùʵüM›6¡±±ýýýhooG]]]É7šˆ&ŽñIT½ŸDDDDDDTN¼î´D£N‰+7‘èp'8LÓq"-brøH$3ñ8I÷\+âõ$ÉzŽÍ"’)bÙn"±ãõöÃïÁààç00Ð Y–±|ùÖÄõæb`×…»0wù,ØcXE:;;3–×Û´ÊjE2GÏärÏ=÷`Á‚¨««C*•B4ÅÇê>† Þ} p F)UB¢;ß)öÔ)€  SwN(¡uuuX»ví¨Ñ(Éd]]]—ýÊ5‘|kk+¼^/’É$<‡U@®ØŸDÕ€ñIDDDDDDåÆvÛ±ÅbVRÄ=o `2Q+"ªX)Š•$%¸tÝIÆdd €ÑË5Më6Uužã.&oš&LÓÄÝwß Ó¼--:–/:;ý0 ---P+Wþ+>÷¹z|~ÿëXµjn:í4,ÿÒr@wwækG"‘ôí½"xî¹ç‰tÙ“Ë‹× $ ;vìÀgœ¸á†¬äÌkÀ¥ïºhq–ëÞ–bI ¯°<ë@À»Jÿ(¸äW>ÉdÛ¶m+z9bbû™”DÕŒñIT½ŸDDDDDDTNÓåºS”éš ÓÌ ek™îyT"+Á;ÑõÌIÙEù+1b#{ÙNâDñùœDŠ–•X#6ìõŠH'O"§L˜H¨øýÀ—¿üQ:Âa@’$ø|>D£Q\pÁüêW·chh«V­D£QȲŒÿø[ñÆ7¾Š#GŽàFyt}1^<ò"b±š››aºêpE£Qtww#ÃçóáG?:7Þx-º»»MO¦"æK ƒ‡Ã8~ü8 ÃÀœ9s`š&÷p?%§ë@ôNæ¸3,}aiÉ_“ """"""""""š1ŒI6å]·F¡†•ø…F?G’œÛŤô‚,[÷éºk¹:ìÑŠ ~uu¯ÙIIÒÑÐ0¦iÂ0 (Š‚H$UUqë­oÂoûv [nY¿ß¾¾>{YÑèbìÙ³¿xù5„BÀoxÿ÷µÿƒ¢(Ð\™1‚Á Î>{n¹åf;yÓÔÔ„ææf„ÃaHé¡-Á`Š¢àÔSOM¯§kÈK‰F¤äâ¿P–å¸CfB…ˆˆˆˆˆˆˆˆˆˆ¨ìB¡ÌÑ$¦iý«\•©"ç&F¦¨ªõ“=OŠ®g–ÛBVR%mpð,œvÚñô²MD£QƒAÄb1{´H8FKK $I‚¢(øÄ'fçL) °qã¥Þk½à‰§O@EQ §‡Þ˜¦i'S1‚°'ÝÝÝ€ÏU¿L×uhš†ùóç~aÖÈ›SU@y0ä¸3ì>wwÉ_³ Iéãñ8âñø¸I¥R¥GˆˆˆˆˆˆˆˆˆˆˆJD–G'5 !îD…˜x^’Ò¤§çI‰‘ˆe²çPq¯¦8@…•|[ýùÏÿ'†i.C(‚Ïçƒ$I‡ÃÉÞÞÞŒe¦s-¹·ÿ @öwmÛO/€¬Êv‚F$eÆ"IRæèû½P`š&~ó›ßØÉ¸·µ %¿4 üèm͵¢À ß»ï(ék”PI&“H$yçõzKÿ®•€ifÉ YɋĈ ªÖíîQ+ºný-&žËmn¶’!"¡"F­hšõ÷rÅèYÌw¨̉]ÿ½ ©sSøÉO¾EQðá{±aÃ(Šb'4܉ wÄ0€W^y¡Ð„Ù³³ÿà' 9_|jnl^ Ösc±t]‡išÉóO$/F¨\uÕUÎóÝI”nXsÃH(1ÿŒüoc?æäƒ¥@ VÐÒZ[[ÑÚÚZÈC‰ˆˆˆˆˆˆˆˆˆˆª’®[I“`pô}¦i쇭û5ÍI~ÄbÖOvI/7UuæC‰Å¬D‰¢8ËÈ5ð㬳¡C"]€ûÿ÷®û708g7.¿@ÍÍÍhjjÂñãljD ëú¨$‰‹Å`î¹ç,¼üò|hšMÓ ª*4Mƒ®ëøío?óÆSðû_¼Œ-@‹õÜp8 ¿ßŸsô‰;4‘”ùãÿè” ÓÝ+kôMËš!wøÂ軞¾èi,zqQI_® 9TR©TA#TˆˆˆˆˆˆˆˆˆˆˆªÕxÒ뺓0‰DFß—XÐõÌ¿%Éy¾Hž¸Ë„Éræ2LÓÄO~òa|üã—à®»þŒááa<ñà¸qã¸úÿ]466BQ{¾]×±zõj˜92;¡P±X ïxdz¨«[ÎÎN;) …ð¶·mŽOÜ‹U«VYÉ“Në¹Á`0g2¥P¢Ì×W\áÜèN É´ -² ÆÀcØÈÃ×<ŒCk•ôõ J¨D£QtttdÜÖÑÑd2Yúw€ˆˆˆˆˆˆˆˆˆˆ¨L:;sßn𙥭rÍw’ýøì¿Å(ñXYN=õB¡=¯ `% |>þþïÛpê©[pù¼ÝøÐ‡>„¿Ûi—Ëzá… ( ü~?úúú` À¦ef'"‘|>úúúð¥/} Fº”—yÒ×ׇÞÞ^Ìšµº+W®´žBæH’I’e¦iâðáî]PKó:£^×H—•~¹c)(¡’˶mÛ˜P!"""""""""¢š‹Yå¼²'n£P Ã*û‹~®»T˜,g&YÜ£OIJe8ýô? ‹ÙóªXëƒ,ËxË[Þ‚T*…—_þ™¿W_}µ•, @†a@u-X$Wt×ð˜h4ŠX,†`zå$É*7>ŸÏžÈ^UUœrÊ)üÕ_½1½‚(I¢Ã4MȲŒë¯¿ÞébÂ*óe¿Y(ËÄôæ_¥®ôËˤ*DDDDDDDDDDDµDÌkXs©dß'Jt…B™%½Dò$±F èúè^‚Ï—9ñýš5ÛaFF™®ÞÞ^x½^x<¨ªŠ}ûVàÅÓ–cgTUÅ¿øEHš„îîîŒR\ƒöœ(º®#‰ ··7ëqc¿’hl<Õú#ˆ’Ìk"It]Ç3ÏÃp.qF¹dÏÉ"I™£XB¡~ùË_"d”ézöÙg±aÃD£QȲ UæIóÉš þSÿñ)„šC£Ö_’$Ȳ Y–í ëUUÐü'ÆÖº[ Ð\š÷VQlܸ~1(Šbè ½»,Öòw/Ç¢EcnCgg'z{{ÑÝÝm—ú*D8 àãÙoŠ.Çeš&4MƒaöödLJX#ab]r’dmÈÀŒ£‹K°ÀÂ\è“É䨉é{zzÇ3nkooŸÒ "¢© ¥ºUFtJèí6o> ¿ÿ´Œ:¢DD•–J¥0<< ÇSéU¡iJÓ2KMèºõãî(zOú|NMð@Àºíî¶:%( ð»ß]„›oþK¥7iÊ0>gˆ¬Nc‘ømÂê•+êßÇ\)Aš8Æ'•‹ßïL¯ªNù/ÀI–ˆ$‹˜OÅ0œ^±˜sî$J„e“eëþH$b—ìš3gî¾ûn\uÕUxíµ×ÐØØY–íѪ Hßv-D¸II’ ( EÁDÄb@ðw€ü®ÿ„•A¬‹=RFÅèc¨ s‚ û­E.K/wŠ4BÅãñÀãñ ‘HØ?^¯Éd2ã¶D"1ukNDDSFÓF÷b­Ó4‹Å2ÊyiìIݪô*FÑÕÕUéÕ 5Þñ7ššœr¦iÕô¬‹|q±ßÜlÝnV¢%°®?{{dŠ8ž~ä#?­ô&O)Æç$è(MÏÒr­[ ½~±ôßQXQfúo-}_€@VÃŽV]÷ÞômÍéçr¼F(½¼€ÅÈ?¢E¬M㓈Ê%uÊz©jæÄóÍÍÖmÁ u¾$F©ˆÉêëvq[4:z¤Šišøìgß‹9s€$Iðù|xÏ{Þƒ¦¦&üìg?CoooÆó$ P¾€Ì$„%?†è:ÙíTùÒ¯Y‚¾©š¦9m6r—÷ÇБN‡“P™‚òïPimmEkkkÙW†ˆˆª“,OÉ1iÓ4!IZZZàóù`"‘$I²{<46þ Ë–-KJ á¾ûn‡‘îJrÖYgUú­#¢¬«« ñx===ظqc¥W‡jŒH’ÄbÎHÃp.ú»»J²l]‡BNÍîÞ^g¤J0è4†õ·¨ÂTçÔrc|! «ÑÅ€3ª#јžàó~|4ýÜ|k•Ñ`5Öhé¿ÝàúҿݽcÅè·púù>Méåu¦×Å—¾`5 `õêÕÓ?þô2E 1±Jú>h ŒO"š*Ñèè*ŠâTÂðû­s'q>&~K’õ<¿øîwâ+_¹ ¦ù&ø|Ö—{GGž~z'¾ÿý~tvvÚ%ÉÅŽŒ’X.†]€òa×=æÀçŒY7Š×)zÙà|°Î &»]b¸ 3à. è8ï@Ó°ô…J÷Æ¥Mh•ŽŽlÞ¼Ùþÿš5k2~T•ã`‰ˆ¦#Ñkc*†¦¦&VñÓÙÙ‰îînôõõ¡»»÷ß:ácðáî»÷ä<1!"šjhmmECCCÁÏ9tèШ’º4ýD"V¢C”“˜5 X½ÚJ ,^l%Fëb·¯ÏJ~øýNéY¶.òE©/Y¶’"¢7%à\è‹Û±¬\âñ8öìÙSé·gJL&>÷ìÙ3s«2ÄàŒÖ`%šáŒ Á©!G´ôýb^ @ÎhމŒ|ŽÂqd&(Äh‘hú'«AHŒ:ÀäËuùÒËès-«;}Ÿ¸_JߦÀ£ÂJî„ÒÛN¯ÛPú9îÞºb;ÄÿW¾=•J!ãСC¥Ü«Uk¢ñyôèQÄãq$“ÉJ¯:Í@ÉdO<ñŽ?^éU¡IÉ”ìö1úDŒ\ÑõÌQÊ;¶ÍÍþû¿óÎ;¡ô \(Âw¿û]|ðƒDoo/b±Ø¨6ó±Ú,rÎ)/:”Úpf[‘¯‹Åœ’_¢A.AXÇîÉ2zýúÖ¤ÿ£ë™=…Lk¼äo]Á •Í›7£««+£v¥×ë…¦iظq#<¶nÝZò$"¢Ê3Mëäa*¦&Ñ4 º®Ã0 {DŠÏçƒiše>ŸÏ®*Ë2N?ý6ø|ÖÄg_|1xàȲlR!"ª”††x½^Ô××üœÃ‡3¡RcÜÇÆ@ÀJˆ îPȺñb+a:%&DR%:;ëb~`Àº¸õùœd‰H¦„ÃÖ|0hÝŸ=²$;y2Q3)¡2™øÜ³gúûû+½ê¥çž+$›hTI V"A‚•4sȰ’¬‹ž¾/+ùÑ›¾¯Î’&×òݯo¦_KK/Ç€•ˆÀIRˆäŽHÚˆ¤Euß‹æK¿¢|X_z›EòE4’ɰ0‘ôûj¦·«%½Mjúö@ú6F<ÇáÇ+¸Sg¢ñÉ„ U’˜áرc•^šÑ\ ËÖ¹“8ws7#tv:ç]âLŒd‘$à7¿yn¸¡W]õ^´¶¶B–elÞ¼wÜqáõzídŠªª0$Øç‚+³n,ÃÜ ± ?“#¡"¡è²ž²,;%¿D'‹œ[äk¹VÞÿ->ÅÚiîRÕ²ŒP)¨äW"‘@WWvìØ1ª‡€ÇãA{{;êëëqë­·bÇŽ…,2§d29êØØØˆººº’o8M ãsf#)5Í™œ~‚sžåµzõj –î"I|>"‘:;;Ç6zÊ)_Ã׿þ'@cã©øÙÏd47ÿ²,ãàÁƒ•~ë¦ã“húXºt)ÚÛÛ+½”Å4­Ä‡ßo]t›¦•s’tw[ÇHY¶æ4梓Üг I²®õÄr³GŒHÒØ#HYvF¢”R{{;:::*ývW­Ë/¿|ú•Âó‰HÈ,©%æi“ˆÀJ(°z•ŠöŠn8#,‚éÀI"FqNY­púuÅh‘”‘ᔜÑH¿†äZ~µ‘™Ðo]•ô¶Òï“HÆøÓï…XV@ðt[í.3v„T‹-ⱓ*ÆëõÀŒè3®;Å(€3EMš¬Xñsüìg—"YŽOú<õÔq‹ìD‰Ï· ’d›544`Û¶m¸øâ‹qÑEAUUèº^X ¬´X 0wgU¹TQò¤Š$r]Ž„ŠEÏ£bš¦Ý &Æî´QÌäôÙ“ F¨’³ó\ºhh¥î.TPBeçÎðz½ã·Ü¸q#¢Ñ(‰Ä„†M»utt §§'ã¶íÛ·Û_NDÕÄ4ÍŒ‰±§;ÆçÌ&ê±N=ÑR£QDY/PU~¿ÝÝÝã>wÍš5¸ýöÀÑ£?ÃÖ­›°bÅ•‡­a¦_ùÊW*ýÖM Æ'Qq²Ë0»ç" …2ç1inÎìØÛk=Æ0¬ÿ‹„ˆ¨É-¸Ë9»oëœì…$Q±DY.VŠ˜ VÔ5eªéß~8‰÷H( ¹Ëje'i²ùÒÏ‹ÀJš´ÀJ4„ÇX^Ìõ“ý}X ubRcw¯htgö†–Óÿ˜¦õöEè»e-{xת÷Tzóˆh«ÅëΖë|.É<“$ë|Nœ‡éºu>gšV›¼iš8~|wÞ¹sçn…a„ñ½ï]…sÏ}š›†išƒ$ëyçŸÿmœþÌ›7×\s $I‚,Ë.G®(€¶&Ç!X£FÛŽ(a9s}ɰJ]Lðy’½oÅŠ’¯vA •\Z[[‘J¥2nóx<žôʤR©ªDª}¦i¢¹¹}}}“^†®ëˆÅbÐ4 7ÝtS¥7iJ0>g6Ñ7vj¾O†®ëeé3Ó4í Ù4Mƒ,ËPÅ™’ÏæÍËðõ¯¦i@’–cùrë„Æ* vO¥ßº)Áø$"š‘ì0 ëµ¹Ù™sD4zŠQ(ºnÍc"GÅH÷(’`й_Üžo” Ñ”Òa5Zˆ‘&*œÒSâ¾2'ro†5:E(Ç|zî¤Kw1 šâX£§°HÀvw[¿Ãaë9--ÖwB$â$ReÙúß?¦iÝ®iÖÿc1«QOz‰áu@ø ÁqDT)µxÝ)¾_³+‚»;ËÖù (Û:kÖ„BÍøóŸ[ðúëõéòâ¿€ÏçC4jMú!Ê‘‹òè‰Ä½øò—ߎG}º®;#4&HQiYŽ;ÊPÑÜ8eœ„J ¦.¡"J]Näܹ€òiÂO?ò”ú[PB¥¾¾~T¢Ä=— `U±ÃOãñ8¶lÙRâM¤™JŒ‘$ ¦iÚe„t]‡išˆF£ðç¹Ò‹D"²)â TQ¼P†Z|Õˆñ95Ä…S5“e«qi"ë‹Å ë:4MC8†¦iˆÅb0 ±X >ŸÏ.ï ‡IÌ xϬ‰ä¬žâD©À§O ŒO"¢ÑÄų(à &z×u§—¸hø ­c‰Ý€é:†dŸ.ƒ£/>'Øù¨¼ 8¥´²ë“÷Âj´aõv€3"ÅDfï×>X*%.óZtÝiLñlš£G™Î5ñx1E$hUÕJœ†õ½£(V»O4jý–$ëÿ¡3o`5ȉ„K0˜Ùk|aàž¶ÀÊtM½Z¼îÔ´Ñ%½€Ñ%ÌE‰ó~ô(¾ÿýÛð­oY%:öìyßûpî¹ÿ‹`°Ûî  ¡iZºÝBÁ§>uÀï÷š€~"$ PrÕ§*ñ¹¦ßÄ^£ÝDtÀó¡C*`ÝÃé×2Qxi³R× Ÿ ‚*k×®µ‡u­]»6çc¢Ñ(êêê&¥£]6oÞŒx<Žºº:´··ç­Q{èÐ!ÄãñšÊŽRi…B!(ŠUUašfFxUUížî²,ÛÉ•ÞÞ^477ÛÏqgŽ£Ñ( À$IÐ4 Š¢Ø=ç|>úúú`š&º»»±sçN´´´Túm(«ÉÆçž={Š*8µ´##•^‹ñYÃ_ {¬&bTLÂ&Ë2š››Ó˳zytwwgLÒ,°8¼if®ß<ðÀatvîÃÑ£G+ýv•ÝdâSLÜéñxFu *·d2‰'žxǯôªÐ4¢ëN¯îpØšÇÄ0¬ÉHÄú-J;ø|ÖïHÄy"N 9ôd—ò!ª:QX ¬äJ7œÆñw2{‚ŠIßݦI"E$K²ÅbÎ(’–ë{"°¾D?qÞZqï­­ªÖÿsÕÝ#àšš¬åÉrfg$±\÷w‰ªæ®`âž™ˆ¨RŠm·­Ô\+¦9:™Œî [#ùËGðwwfƼ'·Ür³ý«Ì—„h4Š@ €ÞÞ^\zéÖ­[‡/|¡D9c}ç‹ùÆJ ºÀý€tËðÃ)É9Ac I¨H°:h˜|yO1ò6K"‘Àž=¥žA¥À„ŠÇãÁƱiÓ&lܸ­­­vŒ˜°¾«« [·nôŠ$“Ix½^lܸÛ·oG<ǦM›àñxÆM–>|˜ •F”£G„PºÛ¡avCl,C,Cww÷¨ávápÍÍÍ I’`TU…‘îæ‡ …ì^ôîßûaLû‰¯'Ÿ{öìA?* FTóE“aX•¹ªq‰ä¥5ôÕJ¦øýþQ£ÁDÃ0‡Óå¹J·Ñ‡BOÏ«åéŸP™L|Š„Š×ëeB…¦\2™D"‘¨ÉÉ+'kûöí•^…š'z†÷õ9#5ͺ‰ÀJª·´XÇQQÝU’2“*B9&u§ÚSSñ)Ê}D`ÍiCîIÏuX !¬Þžîñÿ F—ò˜&1áNTˆ’Z~¿õ½ æ2IŸÏúnñû­ïŸÏJ‚ø|™£JÜßî¤Gv¢ÄM–¡¡±×“‰Ùüj*>‰¦¹bÛm=OÅ*¦iÍsç>>„BÖm‚¦W^y ÝÝ'áíoß4æòdYFKK TUEoo/4MC(¤bÕª®t®D¥˜þ( §2Gff(brzÃ]_Í€•(É7h' «³G!ÍEŒÊÍÒßß_¹„ ´··£¾¾ÑhÛ¶m˸Ïãñ]C¯¡¡!ã`éõz±nݺ¼É’¥K—¢½UD§;]×íDGss³=Ä.CQH’d7غ'|ÏÉÕP+²Í²,C×uø|>Äb1(Š’óñ"1ã&>{ .¬ô[TV“ÏË/¿÷íÅ$SŒµD¯»n)¾þõ¥X´hQ¥ßº²›L|.Z´ˆÇNªñ¹ŒÇã•^ªºn%HÄÈ“@À¹]×­D àL8%u„±z}Õ19<`5Œ•PœÆ˜±_j`‚wÑÈ#úÐeŸRŠ âöXÌ)½ Z?€UÖÏ]îÅï·΂ÁÑË ‡­‰˜K©€éüˆˆf„Zl·Õug4¡¦Y·uNøÚk»°oßa¬YsJÞ媪j—3WUµô癹æQ`%&?tÿ¿ÑUy$’|ÍŒ*IÊ„a• íÅøÉ#q!à>ˆëÈ™ˆimmE2™,Í›æ2¡Ié7n܈7f\×××—¤÷y2™D*•ÊXÖLê¹H1߉Ïç³G¸‰áu"Y"È9RªÙ l"©"sÇjøUUÕîy?1>§Ž¦9Ãú«©×š¨;/h©*pË-G¡(&Žù©]ÏçóÙ%ób±DQè2¼Ù 8ë¬J¿såÇø$¢éBôs™Öÿ»»d¾adÎA)Ž›îãÀ =]£éÎLÿ¨° b®Û²Ïƒªè2Ÿ@ÀŠið’§b$ˆ,[÷‰ó<¿ßú[Ì?"’¢Ÿ{÷>8fõ 1í€išöœÍe3ÞèÒ%ýåå€ö\ Â:¯0 x¬XM÷ {V'BùaËD'ðÀ™;…"&4B¥œZ[[‘H$°~ýzx<ô÷÷£µµ•傦MÓ‰D ëzÆü'†aÀ0 ø|>¨ªš3YRÉd†¢(SšÀ©6ŒÏ©#ËÖÅŸ¨ïY)º®CQ躎––\~ùMø—ùg¨êÐÒÒb'J^{í[vY/Q~O(åœ(ã‰ÅF—kĤÄ×UîMœ"ŒO"ªv±XfR°æ4óˆ1àü&D£è°zl*éŸ0¬Æ 3Çã&Yó¼b™˜è½¯ÏjÈŠÅœä‡û~1ê$tÊoɲÕè%:žfŸJºGJ÷•¨ä ¦Ö®;5-3Á/JHê:ð¿ÿ»7ßü4n¹¥3}Ÿ<ª N6]×í¤ÊXÕmJf¬¦ VrBCÑóžÉËÿÅŒP“Ê7Ã*ý5™ŽLmò¥_OBî‘*zŽJ2r§PU“P€-[¶ ‘H`xx§*³œ41±X ÑhÔnXó,ˆl¥H°ˆ‰á«9iQÍë6ŸSCô¾½÷ÂS\ßZÌWÔÒÒ‚`0hϤë þ÷?‰P(dÏKFQ_‰ÏS•@™ˆ /¼cZ›ŸDT-DïtUuæ=ˆF­d‰˜,^ô0ÉÎoBTwÛkbúXóªVC‚{2ú2Ñ4+fC!+)â.W«ëÖm½½VÜÇbV¼wv:ñ.z »G–e*–¤Ü£«ðT“ˆhF©…ëNÓ´Ž+ºnývob1àæ›áG?z÷ß3þó?ûÆ+ß%ªë„ÃahšVþJ½ãÜ„5¯I‘Ç{õR 9ø´ÎÅåôë¶äY·R‘Ò¯cÀ:¿ÉnÒ1ÍŠŸTUB@ÉJˆÑÔ3M‹/¶ÿ{ïU}çÿ¿0A!ɦâAEL¼q¢[ƒÕ²œ(xkK;¡]µÂf´7´ßtgº-Þºº3k\KíOw&íb×Ú…LëvÛºÐæ¨µ•ñÆXÔ¤˜#1 Â!rUòûã3ïsÎL&“If&s&y?<’ÌåœÏçœóþ\ÞW-Ë ÑÐÐ)ë)ø|¾Äp0Ʊ°|æYNmtÏxn1MÓ`¢Ñ(‚Á t]Gkk+dYF8 ,]zž}öûp»ÝfTŠHáPØ\+<|X>†)º.ö5²l¥ï ¬}޽ÖA8,¢SìfˆˆbHS!09&9•ýí‚H‹¡ÈSz+]†*æîó ™·§â’$kMˆ×R•ÒãuÃ0LqãÔ}'ÕM¡9‰jóQª/˜:õ]<õÔ£˜1ãë=:³ã†—Ëe:æ5ÕQ¾ µÀ€êšØ:$&ê2ÊÙépC¬%=°Ræ –I4©¯XL8Π¤|¥({‡ßï7S¹\®”–^EQ ó.—LŽŠ81L.‰Fŵµuh”LTLjr€ƒAȲl¦ûJæì³ÏÆm·%îÔC!±`q» çaL׌a†Z¨y—‡BV½ƒ¾p¹„aÅQžæ”2I²ýŸ*• ”Z…•ßY±ýÙÞב˜sZN:†b£HP„ÿLò1(í‚l;†¢X¨=þÚþæý¨è¨›nM¼ßÓу3O ûªnl{iÎk?«þž8õ ø£~q—N»¨+ôMaú…”*²ª™âñˆ@È4@C!«Æ‘Ë%dÛçŸ%™'9N–g·»°©k†a˜‘‡]7A‘Ž¡P¢îýwþwÝõm\vÙÔ~X5Mƒ¦iˆF£ÎËX㇈R±¯ýúƒ )”3ýR‚ò@ÖäAXŽL¿§ ÉÈiÆ<Ñ1Aڟׄ *Ì€0 ápØTºR:/EQ iÜnwJÃIº”!7¦BûÊÅ×j¦ÂÚÌ2L1ŒÄpÔl"TÈXBòY__·ÛmKdY6 ¯ƒ‰îIÝårYù°NÛÂ0 3\±WU± ‡ŽVˆuQp?ÿpÂ(@†RøÇQËhAAbeWÂzãß“âÇ Åß§%þžfû|CüxFü½`ü{:ĺÖs²h3TÛy¨­¬h ‰È°Œ-TËB‡•ŽI¥Ü–‘º@¸ŒÞ‘†í³ª­möï þº’]Óva|Õxœ(?¹U|€Š«ÊÙŒ4€†@ü~?ªÆWaÂÆ ˜~ùtüû”üGëà‰Ú'°eÆœøã ,3ó¡xr´ÿhhk8Ê/ïóYuN¬Fºžèè“©‹$%®i†af(Ðl髨F ê6{<ÔÕIøæ7¿eÖòë—ËU˜Œ:™œrÄúÕ…ÌŒñÌ$Ø´)ž³P>ÁÀ ´ngØN}çH†Öó¡xS­‡†ØÉ– *LZt]G86±.— š¦A–e3PAhúÖ&º¯n*4X¹‰£ÂÊF&‡È²U\]×u|õ«Ó–âþû_Ư})|>\.$IB4…ËåB(‚Ë傮릱ÄçóA×u¸ÝnȲ —ËÃ0 áóù …°iÓ¦ŒåW–SoŒ)g¶®[9óó‰afD õ™,£º®C’$H’„P(Tø±‰a¦¡"®€‡±–!Ã`ì|€ 0–ØD¾·e  ¼/æƒÐBÀ}RüXñã˜Ó„k½Em!£lïI¶ßd¤°Ï#vç2ªÐ¦Ì¾ö³; îKq-’Ó¤ÚüÑ&¬!Þ?#}}?ÕTîão;j'—™”ø QDðY©:)‡7Í‹’$¡µµ†a@’$x<3Š< ÁëõÂåJáQdnI,BšššÀ 1´Ç!žs,¹ôÃ’³A.môx„S}½ø­(V /òà ­G Ã0 Sl¸ÝB'AÑÓá°e4!gpr覺_© ÇTMÓz9Ÿad¦çtA¬]7€ay@‘·®=²&Ù0”£8EXÛÎûb Q4€UÍ®ÏÑõø^ÂÀ5 ðm)ñ¸éÒ¤å6¨0&”¾‹jŸ„B!H’UUQ[[ EQÐÒÒ’ßÂÓdmˆõ²Bh¢Èm•’A‹ÿôgYUâç¡M?)#&çïr0#Ã0 i&O¾º^@ÈßæÍWâ¼Û¶ ÀRœH’d‡÷x<…B0 ªª"›éö˜F»Wy¨ÄàЗA…PU‘2B’,£P6„Ãa¨ªjz’ƒA„ÃaSAdE®ëظq:fÍúª™ËT×uÓÈÄ0 3âˆ"1Ú‚þV`/TÛkIc{ ¸$ a4àý·¸÷úAӀশÅ>d2å¨ý¼6Âtü!HIF¦OXõÉHbw ¹æy]×ÑÒÒÁŒM›¬›–6*œ£ SH!QñÚ• •ä‘«ëVú®úz±>óûSL ‘0€a†ar‰Ç#ô¡•’œÒO†ÃalÚ´É\c©jjƒŠ½^Š©O ¢,Cz™i¶b½¯x8ìŠ{¹&$R!ÖîAX!¤øy£:Y/ú.«@ûþ "Œ¤T¢ö†XÈÐ=8O*½€¡ N‡œ#Ø 2Â!E.mæ(òDUU´´´ }®À…-“ͬ‘«Â2« }^=òÄT ž¼}HoTñÁ*ôhOMÁ& t]GCCEÁ³Ï>‹ºº;ávOC4űcS¡ªï£££>zÌŒ@!cB}}½i<¡zEÉH’Ô+D•ê¥ ÊŸÝל¬(–óCCCúüùápŠ¢Àãñ˜F —Ë…h4 I’LcP(2G¤Pòz½¦ñ—”†!d“¢…C!+݉$YÙ=¼^6šv‡FЏ&#Ž;Vèf2 Ã8ð֭ï¾û¿p»?@è9i\%úÒk㪢(–.”ŠÙõ-Tën¨•ù¡PÎȲèp0(<¡¢þâ·œÇ3ApHÁ:Γã¹–£zòµÍÄ B¯·wÚI::z‡îA-Ä}â27lPAñ„Ò‘··ªª¦R“¼Øhã¦uAJ€Êæ“Nø6ÁØXy¯ÓT’•”ƒr~K}|Ïþ:]šÍC{‰˜â‡¢,B¡=âr¹ðoÿö*zèn‰oš~‚Ý»Ìû ¢Fy¯nÚ´É4DHCà)‘‰"MUE¿V®<Œ·ß>Š >ÀÕWNHÑEFUU ÍM#QH!U__ÖÖV¸\.s<¢$I Ñ5š¸Ý½WD†a`ïÞ½y¿6 Ã0Ž!o¶pØJ‡ ëb Ïõt˾“E‘<ýúæc@DšPÊäHJZ{ªªÂår™i<ÓG’#I ’Û _ѨС44Xº–aòpz½½ó­ÓúÕ±¦ðgئ Ù ã,2„!'?¿‰Q倉°OK,ìõZûý¢(J?æC<õÙÐÀ•€a¦Åž*Èëõ&xƒç¥8<G('vu”+›>‚{oAêÕ5±;Û«J?R§Žúx½%ÞVÊ»'¥x?™pó 7c×Ì]¹¿vLÞ œÑ…Ølz<SUUM;;w.¦MûÀÌ—ïÔü@ÁwìÆ /,Æg>Sƒ›nšI’ò#³}à÷[‹Š$!¥)¡P~¿ÕÕ:Þx£ÿüÏÓQYù^|q=t]7 ¸d¢~ÛÓJ’„úúz¸Ýî„Ϥ£¯ùßåraÆ Cv†a JO¥òùDaiû<È]×Åü¿††aÀçó™sEtÓüdOÍe:RxÏsN³Óšiuofø“ÓJ($ä×í2 c(¥d•$±Nã(”ü@F»‡ÃaÓˆJYEA45í{m»qU’$¨ªŠÖÖVsl¡÷)";UzÞ={öúr0 à ª‹BVŠ/´aà“Oš°iS Âá0fÍš•h$±A/y<s­–PâÀãµ§ßxFƆMn¡3 ÁÊ€“K£ÊlYLø ¢ˆ<µ‹&úT^P¤K¥‚ñ”Y§/t%RîŠáª: "×ç¢À·+j¤RæÚΑ¬ÄÉÆI˜ +C T†1š¦! A×uÓ|ÐõO<‚¨ÀŠé·ƒ åÕ£ì;}}WGo%m Ȩ’ªù©ä.‘þ‹ ˜&o.ìkSðLÙTô‘òS®DM²IqqÅ€#G6Á‘éGw]™‚'z$ä Ñ÷x<„gê¾}ûR~V’€Ï~öSðxæÁår™FOI .Xω}nÞ ¿kšf=(o;mo»í,¬]»×ÜðÑg˜9Ü)õ˜µ0~ùË+!ËWÂïÏÜ€åv»ãÅæS@n™²l°¯ë!IvìØ‘Ÿ‹Å0 ãD’³†!Æb·[l6%‰½×í‘%4Ç…ÃaÓ(B^ã”;Û*^ª˜ór2†a˜ÞåÉ iê\¦8éC‡@QdQæõ y¶;¹ØáGmàÐÚ—Ö¼ªªšÑ!’$™†½dœrì†`0h®ù].4Mƒ×ë…ªªæš6yü°G™'GªeêTÄ0 3Ò…,ƒŠ$‰µ®Ï'Ö¶Š"Y%S7Ñ_t/­ùè'*Ä’€ Ь¹Û +íT«íœØk®Xìꯘm*¨Ë Nã~¤Ö¥êfª€œa^_Ã>‹ûõª¯¿é¦|KÔx“€VP‡×„ *Ãò’!Oò’ɤ`e¿èF• ¬PªŽ~¾‚\dX9óB° .¦"Õàã†þzG‰ôe¢p7#~nÍvlú›dÙ0€ÚZaõ•eq¾P¼¿jT„øå¾hkœÏ'V·õGT£:ûkÌ †amLós|ÃÜ<544@–e´´´ôkД$à[ßšƒk¯m,Ë ^i4Ò‚A’r×~ o¥öQ®wòÄ“eeeeöBQ”>Ó“$÷ÏëâC/SÚ°þy¡PH(°È¨b?.ï¥|¡†©­ ÀgR\O Ÿýìgss‘†aŠx¤/Ù 4êLåÆñ¬ µ0E†’“”£ä¡HGº®Ãëõšs^_^áé`å'“¶H{]· ¡’$¢ÇÈqÔíæ”tPÍ"’yûzœd;Ùa‡Ö¹dT¡T¼ƒI{m_»Û×Ä}k ã Ã0C‡¦i½¢ìµÑt]Op4Ô4 ===8í´Ó Ýôª µ©:[ZÄœ9qâ«hiÑ2N¨ë:êëëE„q($”­­–Â"Õø} ü:ÉùÓ¡_ ÃJu•ɲÐçç¥Å:t½¥{ñDKü8€pR§¬A4ý¸@ä 6õõV¨l²1×-T»z•a€Ïç3s7S:œ§ÒS=éR}‹¾j[{‘hð C ާ¼zDVdH2 Ä`PŸ,®aômT¡v’1(‘Ê+ŠD–e¡˜õùÄHL1õ’Ð\ÀXçî·YÈz,Ý“ºs{­™¼CG€ø+q¡VCC À®ëhiiÉxSF5ÔýþÔŸ—$1ÏF£VÁàLô7ä9K…-=™j„ÒuɲljKe0™8P”‰Šr“$kM@5ÆÌ3†aLÂañfÜåÒÌ#­iâ¢ØS¨ÐgÍï+ ­p74XŸÉ…™aÆID!Ö\€#ð€J]¹ÿIB€qmÂO‹¯õåÉ^Ì„B!S©AuJ+ ”dL!ïD»1%ÃÝ0B:ök‘*3Dè€ñÿ€Ð"+­x4šhÓ^šæ({À2®¸\.s®SU5!Œ«ôyZ;$CßéëýL¸çž{ }+F ÖÔåKÛ³ÏÞŒ—_¾?úÑ·¡(ãÓ~?š5­TUµ€“£À·½Àd$nÒìáãÉ:#¹3¨r¼m^ˆ=…ï é‚û3˜°1¥lPq8® …LO IöûýP XP ÂXÐW­¢BˆÈØN‘&Jß3 -Õ˜A)Àê!Q°pF‘>Ä6 ˆ¨/¬-éâçÔaZH!U?‹Ù4EJÊSHa ª<å·Þ‹FûgcŠÒÖq"Ó`´Áóù|fždò†kiiI ¨1%]zOûBR´;„0ÿüí¿â­Ý·cΜhûé¹F IDAT6,YRý¯¾ ¸\fa\—ËeŽ0 a8ŒGÎ „~ “|Šbýo“3—Kü„B£Òÿ ^o\yk;TB¾y—-wä….WTfŠ*á%Œ¢Bd(g>¥y ‡-#\,± Ñ#8‰B8,Ž+ËâµpX¼O†2”ˆÚLâuM›2޾"úèø4fÚÅÐnd±·‘ÚGŸ§¡hÊ”B_}‡ó¹°=üÔ ]q‰{Gs„»÷ø­ë@x;ÐÑqi|‰õ_â }$h¢¡›˜¬P¤ˆÝÖÖÞ›;zh‚A+Oò ±r‡ÖM¥i8†af½h4jFN¦R€&Ge§4:öèÒd]ºfd ðz½fÊ¢††Ó¹ÃívÃívcÖ¬Yhii1-dpñûý >lPÉiÇí÷¤° ×ãÅa=_¢(Zoä”áóØ&`ßÇÚ½½IÙIkiJÓXržª@p¹ðÆ1°t"2¬±B‰ÿMãédTX©y¨n­ýo)þ·ÄÚ³QÛ1Û{ä„a$ËÞ>Y¼§K–1‚ê ½ôŠø ×HŽ :Ž=…4½N{=rήî í'ƒeÆŒyé “Hï2'~þóŸã¢‹Ãç?ŸÞ˜bŽüío¸|útÌ£ûÌ,¢%± MÜ´)Š¥·ü²8#^GäI¹£G3ݼ…ò5åѹíeØ`2`Ø âPh¢¢x¤´ ƒ‰yš°òà¹!"Fúš’‹¿SzA_ü»õ:ð¥øŒ¯ëÀ3: 'I²Ç#´Ï²,Œ!®øqÌ÷_²øXÚñ‰¾K!?Pß½B†0Ho¸Ñu¬û×Å’[o„çAÙöíwÏ=8ÿôÓñâøñèüÆ7`( TI‚®i˜qô(æÌš…‡o¹%uuw\Kkj‡¶œ™ííí¨‹†)ìÆÊòFÊÇTÑ*”{=#ÀåreTe PišÛ)E™<ô­oaûÍ7cÆŒX¼kÊ/¾?ºm9¶Ž‹ªªÛÑð…ãp¿ Ý{àùcH¥‡¿?1…¹ŽÛ‹že€®§y“ »Ø·Ÿkãv[á¹õõÖpb«5/I‰ÿÇ@†E± q[¤™¶.¦¢ˆ¹ïy<âu¯ýÿKŒ‚a«9D‘x’¡#ü—ßüýAú¤õ»F¡¡e ‚߯ ]·ÄBÓÄK†;ô?ÉS&ûJ»ž*ÙÀl쳿¯ï'¼OŠYÔ&Dˆœr{÷î)ô­v$gìûx1€pèu¨ê©ð4XÅ7“¯»=ÝsÊõV_!˜v£w2}),eÙz2PjRþq]×Mt 1)/\.¼^oÊyu J§BëFRN‘í1ìé9½^/<éü … (ŠYcŒBv)ëhÈ È(Az‡(„ü˶ï(ºBê³}—2rèH0¬" ˨AǶ×_ lvÇ×(Sžû€Nþ‡KcÌicÐÞÕŽór>8€§Ny ³ÇÎÆ˜×Æ û¤nœYq&öíÛ‡'Î7¾q#> MÕpýÆë1nÜ8LÄDï]PeU|–ôGÛßá¤ëê²]ËV'^2(ÑøKו®[Ôö~Baì‰_ÏÛu×mß¡ûx[kãç§¡Éeë M•áø÷‚0ûÿ…¾€Ã‡çüfúF¬›D:ó††Ñi?ëóùP¶};n}æL´9‘dŬYâ·Ëe9fÛ™VZ6Smòw"§òá±Ôq°A%PZ …â¾ËÞDÏwòDëWiK!öÿŠI"¯ö@‹’htïƒïâùp¿ý=È—L²RXQôF ,Õ³$`€/«ÀBñc¦ü“e˨bj˜OÉenð-Ñ—ç° l”j‚”ºª*4¶}yÊ55ism¡¡PK.¹ÿÒ‰ ÷݇¿žtŽÿð‡æô­/} ‹?ùg‹C7â'{öàK¯¼MÓð­º:Äšš°ï¡‡ð? Á¶É7 êwâø?þ#®½óNȲ ǃWõ+ü¥´_:pÀÌÉ­( V®\YèGÉÊxR[ky`ËrÔT‘Lêºn¦É%¤ 9²nN<üK¼5åuŒ3WOœˆ36l 05²Œî?ý £öïGÙüù€9ñhýÓXèO†öâ°(-…a³}š#{ÞŸ ‰FûysÆ%{9JO[_O×_Ü“þšh)ôz©R„1EM Ѩ¸¿dÔ°§®êmÆúy^è9–$+ƒ^§ˆÃϤ¦ Eµß/Œ®z@m´_Þ @Ù~ H‹ãq¥µÕ* $m:h³ñÛõ. |¸}-6mºÁ`+jjjðüóÿI’ðܹ«€€¾ç—˜=v6þ|âÏ講Â'`FxÊj|úOaÞuÝ.L<ýT„ÂW¾òTUU¡»»[_ÜŠÉWO6¶¯_ó:ªÆWá•·^Á’·—ôs 6¡„3F,åA8räJ¿] è@T^hÆ~c,>Þð1JÚJ£'Æö¶cÔ'£€ÆB?qÎcçÄÑÀžMðÕžŠMŸc"àè^G£â¹T+ÝófÄ…‡"Lìé5Âá°é­ ˆùËï÷›¯ÁÁx:»®a‡ÃPUÕŒ`¦?¡õ<}žÖ”Ò$Ãï÷ÃívCQs½a߸Ýn„ÃaH’”͉ÞJélœ>æÏŸéÓ§úò:’Ù¯Ïþ¡¤³_òÛß6Åä£;âQñ÷œ\ÛˆRÄÑßôŒRD“½N y´“¡Ïn4ar®ë8vìX¡›á\ ˆµ )ËïÔ‡e±NtØ®¯Û¼Ä*\«ZPÀ/¢À›ÕåJ ­XgÀƒQÀî/Ë@‡m꽽ѼIbRÔÚ‰ ¹„‘Ý%¹ y??ô¶mÛìº^èÂöO>A׸q QOãßwÚi?~<î8ˆÊw+±úŒSL#ûqÇY‡ºQ~â¶mû.<çÌ«úš5iÀ<å,~WŠþ é<=)ÎãOÚ„x àæ(p€ƒ¼@ûCÏãÔwO“?h?Hø|>3M[Bz¦ãÃÏK~èQ,zå\ùþûfÖAct¨þI¦‹pb,rÃÚS–„>—j›0އ *¹‚¼4áÀý€zPŽÁ²ÒÇu|´ñœúç©8ÿ‡çãûMßÇ£Ÿ< Ïœ0ž¾âUÌD¹uLJ¥e艩¢Q`koáõzaÕ-8fˆl£ VÖxòΘ¦"¼mܯ¾ )¡^¯èC¼¤þE´ÛžrÛôPLŒ-Aà ¸³QcŸ™9K’ 4SºŽ]mm8Åæ9¯i.™4 Ñßÿ §¶} ?~Þ{ï0€(ŽtuáŽ'žÀáÇ1zòdÜyòÉøÚÿ7t]GÇþý˜ëõâ¯wý¾ù9,ÇLtttˆпú ËPâçø§ø@G¡â3|ö§¿Æƒþ eЦ±S¦˜Þ”Á`»ÅÊ»ïŽÁ ›Çü\Pè§É² lÚ¤#à–[îFyy®¼r¦MÛ…M›6¡¡¡þäh@ÅÈt‡ÛÛ±¯¢÷M˜€¯=ò¢Ñ(|>ž«˜·ªçãž{îLxí^£åiÎ/Ë€üеPa¥"¦Ïg¥÷ñ/^ ±ÌÛnPÉ2†R"Í*DÔ>„´¶Zi‚è²ÑiUÕòî÷û­5{(”ÕfÏgÄ8s.0m# ïôÝ”NÜ6¯f×5€|¾õ,S }^–ãŽ@£íg€ú( Œ‹i>ú_q^×¥@øeë±UU@ÿ (o˜HE¥äVDG„÷Ù- -n¿ùàk{äìÀ±#ÓñáÕ›áU/ÅÃ?ŒÛßrcÙÿÝŠ¿y£HÛ£«8éS'aJëÙ¸úý«QúÃR|ý; 1%87WÏÃÚ²µø`ÃøÒÅ_Âø÷Çã™Ø3¸çÌ{p£z#4h]2ÚŸoÇÍÊÍØóðT¸+0yòd\3ûüæßàÔ=§âUoàÍï`Þ ó°¢b~û¿¿Å÷~ïøÞÁŒæ˜øÄDÌ™;£¾7 »kvãÊ[¯Ä›/¼ Ô OãGâã?Fùòr<Ýü4fœç+ŸÇœkç`üŸÇãîyw㣫?B÷7»qVÝYØÿô~D®Šà†£7àâã¢G/˜1cð›)¿Á­Ý·âw‡‡·>ˆîîn|üñǘ2e Žt×ðâ£Û>*ôcéX¢ºdɈbßû‡ÃÂe(ø4M3•øš¦%DW¤Jç‘ǃ|¢9È8äñxÌš.”V‹Œ'Ô_r¼¡ˆY–Mc¥FI•“=9¢Än€ê…mN3×>_âg¨ØQ2ô9»£-EIxÚ¡C…¾%ŽeçÙ;;t ¶ˆÉ¡õ³fÁ¨º_†|ðuଫÐòWZK¥hTÔe´¯§ÈÁ œîDÒ=B4j…9Ò‚ÈëM G Ä`XŸéè0£IdYfÍ®’ÌØ²÷Ÿqšb1³ö žSJåCiø’.Qd¹Æçó™Y&+•7—EÁÓÍͨ7]]]˜;w.v<ó ^¾è"0ÇZÊõOõ‘Ž=Zè®9—{ f+¸ºÛ ´ÚÆEMž $Êšª&:¨ÖEeo´œhÐ ”¤íLöÓõ…üîÝ»qÈVü>yôQ‘ªÀþýûq¸²‘šȲŒY³fáºóÎÃ÷îEÍÔ©¨¨¨Àô#GPvß}€Íˆ©P¾WÂ0p{²ÓB<Œz.¿¶y'©äÁ×1UÒ8‘ì˜FûXÊïJ¡ÖvHOE #Z¨÷qMÌñÏ>¦PZú<][;€µ%%Sòy(õ„]eÿŒ¦YŸ¡ŸT硜ºäá¥$n&k@8*¼5SO>3yN™AA>œ¤Š¤l> &$‡Kcç ;±P_ˆŠ“Q²¼˜¬dïÑì4Xƒ„ÄÈ7, ÀQ+EÀ¨žžžžìS8–-[†5kÖäÿDöpK-þÛê] !XñCà Ԟ¸jÿoÄwOÌ=gšŸÁÆßoÄá߯'߈×g¿Žª ªpů‰"´ê¢¥GœŸ(Ô U€ýtøÿBÀ2˜ à `4Õ¢þH…Y7´Ïý+ÕA‰÷¡>>O¹Ý™—…¬'ö9Ö¾¡&¯%±UQ_|ùË1†Žÿþï‹o<Š"¡üΚ¦á‡¿ü%þóÄq뮇põÕ›±qc5^{m¬ŸhÃBž}Ð ‡á‹ºÌ}Â@—.=Š‹.ú·ß~Jï7kk‘hæ¶Î'´Òâ"455¡®®ŽÓ~%‰D‰DÐØè,÷cò:omµ<ð( &ä9s®Å‰3ñþûãM>E±Pmƒ^PÞLðoñŒh4ŠI'„—y4)Á{Qº®ãÇ?žŽë®+Í‹‚ŒœuH)ÝÒ"þWÇm„Üþ;ëCº.„È.c ð½òEøÏú©øŸòåBGè²Úë2К;aÝoË6dsD‘‘Õu¡9ɾµ;Pú“Ò¨&Œ ñ Ê: º«ù¶´U €.@½<~¼xd‡¶hØ›­:!”æÊ0y€ @t+`t‰”RòFÀø½ˆâÀÏðM€ûq[{í¹«)â›Ò è0S˜Ä"ö×ïGǾÓ;·³ó 6lx œ‰ß­þžžzê)ÔϪGéó¥(¿¸Ï_÷|f9™CÀï¾={öÀPÅ„æñxLƒ.CUU”=Z†KG_*Ú鉷¹ÕÊu-IºÿÚ?½ö'<»ùYŒÞ9cgÌß>Ÿyê3xðœñл™Š²]»v¡´´'N„®ë8ýôÓqæ¾3±ð+ ñâ‹/büûãQqfÊÿ¾\\E1=˜ëêê0cÆŒCp €a¦y8kÖ¬ÁÞ½{7G8eË–á£Ö˜5§ˆúz+5œ¢ä¶tEW¢•æGEQLå*M(½½WH(e–b‹˜¡<ð€µáñxà÷ûÍßäÑH%€P 744˜žöªªšÆ@ `ÖsȰab±a‡ò”oT×-eMªœ·º.Ðä5i I)hÏ™©Ûœ°Âá¸U8C4 ¯¯Z…ƒ>ÈkÛ$"‘öþÇàú¿ýͺŸ)Æ÷PÈZw©jß™÷r=Õ)ïí‘&”žË^äeÍ5×àÔ7ßq¾ö軡”ÆBzýÌž¼¹gæÔÕ™·OùÅ/pùôéx饗°`î\<ýê«8ëW¿2ǸnõjŒÛ¸MŠý'"võÕ8tÓM¦Q¥º« •ííØ¿?vïÞŠŠ lýüçqåç?/h8øÜsxÿ‚ ̶ñÚ65Ë–-Ú­ŸS2+Œ™chµM(ª‹î}d@ÌWfh¹ùæ›qÊ)§ «HÜ\1Øq‹ü?¨c0ÜqÇ/pèР( ‚î •öMˆòðˆ†Ì¬Zn·Ûª%dOCG{@9é§?ꑺ¾4ãhò¡·å‚raºâ?dôÁ*fÏ膕ãR‚•ûNÐH³€Öàáq[pÚi3°hö5ø^×$ÔÝð!.9í8Ê»ÞþÓ…óoºQœÿ^?Š"|êß“'BÿÖCo¨ï™f8×/λ@´M;PÏJƆ†ÞzP*Šô«D©¦hªTÌÍr(BYÙ|D"Gá÷Åw¿[†íÛK/}Ö4 VNh·Û MÓpÆg`ÆŒm(/Ÿ‡;ºqá…Çqß}×CQÎ3½)—³ªëÀ¢Ex[zŠüá%Λö>îËÃV(·¡Aô'Ý~ ûPÃ(AII꺬}ZfÈ]ž):4MÃï¿›6ýµµMSzu]:âhp ùs»ý·m¨u‰pèü—üõ·ÎÎ: Êü2L›vÇŽ½‰ï¿„W_8„ën½—kZZZ૯Oð8=ëÖ[±¤Y–qÝuù{´ìŽ7¹¢(€çù¹Àá9ˆn›iÂÇö#à©4•uá0 «-„_)¨øZž±×‚ E";E1!ˆ¹1 ‘ò‰rA7Æ* ô"àúPÿ cå ŽäÐr- …˜‹ G9>Åy•Œ2TÌâ5ì[1‡ãN‚ø÷¼âÜðòºé9®Ÿ§Cùm¿mƒ´X‚ûŽ8|ùaŒ[=û›÷cÂK{FDiEUQ˜ùª“®Â^ï^(Š‚Ûn» W.¾›7oÆ9cÎÁŽÿÝÊó*ñdèItwwcúôéøàƒpðàA|üñÇè訆z½ŠëW_I’ðÖÌ·àNLB*R)ÛB À†a *G!)¢Zkï_ ·Û––|ç;ß1”&Ètb˜¥£üD9jfÔàoµƒaæœL aEQ —ꦡåY<‹É'ã\ƒ¥ðÍo~{öìé•Bˆø:¾žòõt €äc%§€™={6"‘H¡ždGsàÀi8é¤ÞãEªjR–FMÃ)]q?Ýn·é‰Nõ;R¡J’U|3ÇØk2P*,UUáóù áñxÌõi04ë‹D£QÓBõÎ(¥&öZã úm/ön=ï`”säyÛ×ÖíNýêë邤^Ô¦kS’2(L˜„ª¢üë_g/Û>ØyöÙÀêÕ)ï+9í£[>°„&c )ý“ë–0e¢ß4\†|îs¸¢ý5Ë0e›ÆšÉèAÑsôy{¢†††xný†„ˆóMªŠkçÌÁ¨­[±kêTRà–[LcÈgN93ï¾óŒ3cÇŽEç~€ãUU–±5î½>sùrÀ’øœ˜0ŽÄòSã?}•¬®ˆÿ"ã¶ý¾ŒÿÿãbÉüÂC’Y5çzÕg$vÙ£ç2'<‹.—+amÔWT3<™0aÞ|óÍB7£ø ÆÀ÷MÀûg@ÐÖáð~¨j&O>-®ÈaÙªg$EñÉýËqâ­·pâsåøŸpÕŸþ„™_,ŽI:[ÛÓü›ê©âÜÃr´g©3`¦^f€ *V!¬xAt¨J@x~¶ŠÏxŽZhqJÀ^ƒÈ£è‚¬úZ¾¼±X £wîÄwÝ‹?ü6Š©SoÄYg½SÏþ5Ú.~sŸÌïcR½Ý ýa # ø|!ïN±Ï²­€ôલṙBb•jÞÖ pþóX¼¸š¶^/°`A9®¼òJìØq|ððù|ðûýæÁ0 lÙò)|êSG!Iâ„ÃÀ–-¢®®$å^PQè:°sçÙˆF'ž¸¡ðÞ{óRï¿ICj‹$µG öå´gö-þùpØ*ܚΠ[µ2H¹,"lzáPPvÏθùW3 ØsÛ‰…ä’ë{Ä®GŽÁÓ£žÆ®¿ìBOG¦M›†Oú<çÞÿ°Šy|Yƒ²_^ W­"‚: Ë5h]þ$>øõf|fÛ98kâÛÀy³ 4ÿ–ÉßÁåï†ÿ¼ìf¼²å>¸{<.>p#|WåœVh!Àu ÀX@o 7 NôÃâG%ïò( \àå¤þP±;ʹI¡¬°]*^Xá¢öë¥X×L™~€w ‹h,t}‚󣛣Ñ~"¿œ–+›ÂÀ™Ü@ÏEf¶0mº¸Ô¾q€× øž”‹iÐq ÿ ÿ+Äœõ2 ÔÀr Ûb–BŠ¢@¢Äô ñ¹¨+Ši»¦aKd Þzë-ì¼j'j¶Ôय़¿MÓPRR‚ýû÷cÚ´iضmNœ8! ût”*Åõ®-¹³öÏÂ//ý%víÚ…+®¸/½ô~ö³Ÿáøñã?~özÅw(½PªÏꆎŸ®= ÷ß@^¯>ŸW\q>øà%|íkâå—MP°(Š‚ßüæΣ–ý¤#SÞ9â¢âó'Ÿö”t~s)þwRÆ sâ !Ñ«ÀŽ;°sçNüqæÑù\'*++1é’I¸þöë1çÀ!à€íýÐ:6ÒEÖ÷Ÿ{ÃÀ$ øq+žzu *º6≟=Gî{_ÿþ×qmݵØuþé8þÏ㥧žÂ’%åxeÕ— ëcTáód°ˆ÷GïôƒÆú›"õöõ€Tømð ½T0„€:À}I׆”Êô7‰4…¶ÒDoÿ[OúM \À¦K! 3Ûwe±`â×Þ'Îé²Û&tXõ˜dX¡²D«è£yŒ0 ^JÒ÷è<ô ÆâxúÄä{œð„Rü ’ÛLÏxÚÓø0/y‘ÏÌ(cº 0âõNäë­ñSñ­É;º#¯¹ GÍâ€vCC´!j¦’$ 'tV¬X7nöíÛ‡ÒÒRìÞ½•••7nÞ~ûmœwÞy8õÔSqÓŠ›0UžŠ£á£Ø½{7‚Á`BÔdºMî=¸'áÿäÔAv4MCCCƒ©´JU ¡££#A¹CÆ!f}…dån04¯Eª¶fbìpüFÞžúˆ&÷Z6$k[X©EÂá°i´ ”"^¯7«BѤœ$£ÅöíÛ!mߎ'ã‹=»âÔžÖår%N¼^¯™ûÚD N3j9.'ôüÓÿ”BG–åÞÅb“å]Óz/“•‘ýÕ ¡dv’ë\ø|½+¤fcqû'N,t†Œ\ʧËÕ»$@:ÈÐIs†=-ÓpOÆü|Ž÷dœ'c6¼^¯™òÎãñÀårõ2Ž’ü“Á„ä½¥¥ÅL)– fO#˜ É: -G‘fþTõâÇ¡s(äDuÈ Aç+&ã„$Yá‰#ŒÊg8,ÒÛ‡iЏOeãNe<±N†Bö¦ÉËÚÖ3c¢WÝÒ ý{ñøõcìoÆ"øÙ ¦ýnðf­û¡EÅÜ¥ïÙõüóñÐc宓}-›GÖ6†Iƒ£ *ëÖ­CSSjjjÐÖÖ†ÆÆF,Y²$û'cúÓ€Ü˲i‡6Fñ™øñÇ7¢rtŽMyÊùoâŠÇþ=wMÆ…nø0uêÉhiIô ²‡–*ŠPÒSy_\Jk:Už{k×nÇ©§^„pø¡( .¿üqœ~ú­¸é¦÷±xñvüîw‡QQу… Ç Û —Ë…?üáLÜÿ~ÓHUUx½‡ iW`Ê”N¬]»€µÀ§¨aȘÀ^Ó*Bõ UÕªYÊXÑÒbF|>ñ7=ìõÈèX€8¥'³Õ@3½àíëJka¦’­½­ÛmÕtIÞ»º\ åõнom­u *Açõû­{âõZuÂañãõZ×ÍôŠs i⇗æK$EÖò©8¤52ôŒ#€´_·®ƒo@ª= œHúy@‡+ñ‹É…äh…qG5¿¶ßþ•••˜VR‚ËJNÆ5×| óþÛf•°Yþª>9€«ÕA7Ê éÂÓ-pÀÚü]'á·Ïÿþëühœ×ÈÀ#ê# ç^òyÑorbžM{*sôNÁ©Ì·þn½¡÷%¢q!©÷±SzS$&•±Ï‹þÃTíãa&é*RyhØå±¯…ˆ=O©VDõYAâELu]ԤϛÅ^aFŠAeÐòIé»^ÕïÊâˆ> hË…¼Ê¯Æébìµg±Ñ4 @4aSjßx’—CÛ·oǸqãðíoÛT°Òïp8Œûï¿7nļyóÌãØS~¤BUÕ¬#-칬S¿µµ5­pª>éR' ›Mz8lMÊöTD€5†“rk‘¯µ­½¥º!#¢ÛíÎ8;JÈã›ÒÝP-J™EE‘)åNÉÑ£¸~Ç3j„”¾G~ÿ{`útTVVš º„4[š&†nG ï@o#¥º"’‹q½ *É)ÝØ‘|Mèu:w²|ÓyÓ¢†©gÍÖ .ÀøB7bŒ|>\Úëñ£GÄãéê+šs#ýOQ[$§4?´.‘=ý`EyH’dÊn(êeØ´×ñK6êSú,¯×kf* cˆ™ÊÊn¨ˆÿP¥;žƒ¹Õís9*ÇûêõzÅ\Aµƒ(Ò-y3G〦‰sx½7xÒ†• ]ç+[¾¡¼Ö#ŒÁÈg_Ù5MŒ³ÎêÆŽ“×]wo¾ù&þú×KáóùÌE,yôìØq&L˜€¶¶ièêªÆ¨QOcòä«Ñݽ«VME{ûê„”"ô›œí(B#“e:$ªKIé{Äuëß{Š @äie_Ÿ–‘¦÷÷tø|âM›''{›è5ðú’ü¹úzÑ?še˜5K×>ñ%ïu©p1«>Ÿ8­Ãý~+¥-<aø Äç].~¿d^sJ§æñX EŸ8xðu<øàÁa_¸s ò©iþò—¿àž#·@ûñÐqáÒ› ºç ü+À} _ h÷í@èåPÎ=iüq¨WÆ«ïŒÁ¸q]èêÚˆî×§ ¼cvôœ‰Ñ==øÒ©Ëð/£qãÆáÚkÿ‚W5ãÃñãÇq¨§RÅ>\õ•sà»gjjŽâ”Sî@[ÛC8t¨3fìÆ®]Ópß}kq饓 Á›¶/ÚÛÛQ]]]è[5(//GYYY¡›’5™Þ“‘R¸s òér¹þzÆ— ýð«ÐÊ®‡ñw*ŒÉ3ÍL5/mAôõ£p¹ —ŽùΛ҉‡.»Ìô¢%¥Íü²2L;&L@ÝM7aëñã¦gë¢Oë_|ÑŒÖ OUòþ3$T›*Mi@í‹X,†îîî¼zý'@;¬tFä]er¨R±YFûáÃÖ3lx°{Ù÷u¾ä$á©Î“|œTŽd¥³½?´HuŸhiAlòäŒîI$A$öEé³¶M5niš–PûD–e³F)aÉØAÊZÍvïè;”n‡¼È)½)[ɰd`쫯ï­µixb±Æ,\ˆSn°yèº%GEäm=ÒÖù(ÜéD*Ÿ‘H--(-ML%âvŸýìq|ñ‹o¡¤äçfÄ `ë“&Éòj/ŠNs¥Çã1å3 šõ?h_IÆÀ’qú.ͯÉõGÈ`“ò™¦ê¿47¤òZ#í2m)ÝAOBUûŸ{0ï'ÃkÛáË@å3ùº3ÍŸ¤S¡ˆ©¾æ8úÕë±ÿ¶×¥uprš¹Tß¡ÏÚ£»TUM0|Òïø‡ÀúõëÎgÿ.EyRjûltuu¡²²&| ÃÐ1fÌ9xõÕWáõª4,_¾?ýéOqíµ×¢££S§^†mÛ>ÀܹèꇎŽ}˜:u*Z[÷á /Diéj”–Þ…õë×ãÇ?®Ï§ãŒ3ÎÀþýûQQQÊÊÃttuUcçÎðûeø|:®¼òJ<÷Üs¸ð „0nÜõزå(æÌ)Aeåa<óÌI¨¨¨ÀÎ;ÍÏn¼öÚkæ1ìç;¶“'ÇÐÕUýû÷ã{ß›ŸOÇ…^ˆ×^{ ^x!ŽyçœóüùÏïâÒKGãÀw°eË TTT`ÿþý˜9s&Žû Ž[ŠŽŽó<^x!vìØ‘pž7Þ˜Š³Ï~>úÝB‹O^Éjm°Ü­=¬ºÆ»gÃ崨г=ì{;6µàáZ[[M€ÿûÉOpfG~tèPÂ8W8}.ò=ï púZyX¥D"(//7;W]]êêjD"‘´ÖÎ}û÷#è£$`ÖL(眊IG÷`ëâ—ñÜsSpÊ‹»1îØ6´¸¥¥¥x¹ëRÜ\};::îÄ ðÝïþçŸ>*zÆà¿:~€)>À‡²‚]ÇïÀáÇðOÿÔƒŸþô§XµªÁÜl†B¾xzÑ(ÐØ¸¯¼²‹ÿž|òITT¬À’%‡X…[Ó†ÿ/Áí·?޽{ÿóæUâæ›…k…=Ü[ËZ¯&;€¦£¿í}‘ÎÈ›îÜ<².××MK}*}ý"I}Ï~Ùh¼Œ§ÂM«Ï’¤Äö{½½sÛÛfw~ôzÅϲeß,¯®‹ÁÝ;·¶MM0¼7œƒ‘Ï;v`ÚÏJP»û(”ÿˆqs&áŸ} ÀVüà2`ëÖ­øÕ¯ÞÆ‘3Ž`þÄسg¶tì@û˱wï[˜7ï<|øáv\vÃØÿrn\0 zõUœzõ÷p}äq:´ Š¢B’BæFQ,.ÿ®¯º¡\N5ìÑ%TæñË míϰ©©iXl\Ö­[7l$Ãåžä‚ÁÈçÎ;¾ù1>YŽ LÄ©û°äó;ðÇ?vâØ±?ák_; ï}TŠSÄÚñSñçqãPwR víÚ…É“'›Æ6oÆó/¼€K¯¾ÑM›0æŠ+ µ·ÃívÃåráô^À•¤Ô'%ªÛmNf*…7ÒgÈBžìašì†lkkJù²2a 'w¹TGJTê${½gâíªi½Ýù’ç÷p8qâK¶ú“Åߎ˅¦ŸüÄz¦É«–þNužd/~—+Ñ{7Õy’sÑØÏC¤3¨VÚ®äóx½€,£m„J2a°k[¸ãŽ;ÐÓÓƒ^x]]]˜9s&N;í4|îsŸÃo¼·Û ŸÏUUM%+Õé¡t=ötzôC©tè7EOÑo÷@ê~¤ZÛÚd*ÔÔ„ºÉ“WH¹ª<Ä —9g8­²e°ò9iÒÌœù8¢Ñ(þú׿"‹aíZ§6 [¶œ†9sæ`îܹ5jTB½ªÒ—¼’RÖ.³Á`0a¹)>¯mÊ Ò¢¿zB)ŸéL6Œý¥´Ëdã™C%Øpz¦‡Ë8“ +Ÿ¿øÅ/ i"‘:„ë®»‘H«W¯Æý÷ßoFESWr”9ü³ý¦ú=$¯ô?}‡Œ¤Éµ~ìß¡Z,F‘ºµÖÕÕ…®®.s, ÷ì)òè³ö2EQúýÎu×Í``ùò™˜9³K–L‚,WÀ0z Iñö†$U`î\ñ™åËgÆ—†3¡(¥…Žàê«'ãì³c¤RTVîÃܹ°W\(JÂáʸãò*TUµà;ßy²<>Þ÷ãcÞ4HÒ èúq\pÁxüð‡ÇãŽÃÇ¡(=ˆFçB–K`‡ I%J°`I:ÃYŸQÕ hšu E)‡®ïî§Äÿþ²LŸéA4J¿ç@QFãê«?$•Á0¦øÄöü×M@,¶K—^f;Otý“„ó¼ýöÛØ²åH¡Å'¯d³¶Ö=‰ÀK¥0&-Ç[•3q[Éëjîš×†Ã‡ïÆÉ'OEãC›ÑÐЀË.» P__¿ß7>úSoº Á<Õ®rú\bîy¼¿‰s˜c"T𛛉DnÀ²eËP]]ö¡¹à‚ ÐÓ¶eëqôè)8qâbŒý,ÆŒ9£FMÄèÑÏB’€C‡¦á´ÓNÃÞ½oaÖ¬ýØ»w/æÌ™ƒ®®.³-œ|òÉ8vì&L˜€?ü“'OÆÑ£G1a„¼öÿþý(--Eiiñ§Ú³g¦NZèf I?ÚÛÛqìØ1Ü{クá†2ùä“ ÒÿáòL¤qæàÁƒØ¹s'F…—^z©ÐÍÍ+ƒ‘ÏOúÓx»mbŸ¼ŒÒÒ÷pìØ1L:|ð.¹äSwíÚ…ÊÊJo¸á†amdb§0ù|úé§ Ýl†öd¿¶] »º— ãN*tˆòòò^¯uvvºY Àå“aœ Ë'Ã8–M†q.,Ÿ ã\X>Æ™°l2Œ…c *ÕÕÕ½ÑéEwf¤ÀòÉ0Î…å“aœ Ë&Ã8–O†q.,Ÿ ãLX6ÆÂ1•ºº:tww#‰ù{;;;±hÑ¢B7aF<,Ÿ ã\X>Æ™°l2ŒsaùdçÂòÉ0΄e“a,SC±råJÔÔÔ ­­ (+++t³†Ë'Ã8–O†q&,› ã\X>ƹ°|2Œ3aÙdÁ¨žžžžB7ÂNgg':;;QUUÅac ã0X>ƹ°|2Œ3aÙdçÂòÉ0Î…å“aœ Ë&Ã8РÂ0 Ã0 Ã0 Ã0 Ã0 Ã0 ã4SC…a†a†a†a†a†aÆ©°A…a†a†a†a†a†a¦Ø Â0 Ã0 Ã0 Ã0 Ã0 Ã0 Ó£ï¾ûî» ÝˆÁÒÙÙ‰ööv@yyy¡›“¶T´©³³ååå())ɸ…îg,Ãûï¿?à¶9±_©ú’í=*ôýq"ÅrM†Ã½ïK>³•¿¡î[ýèë9­Å@±\“b¿÷ƒ;û{¸Ì…ê “=ííí(--ÍÙ½êç€Î‹Å0eÊ”œ¶u(ú’É|™ª@l1Ý#fp¤’M ¸î}:ùtúÚ6“y0òYè~1¹a0òé¤{ŸÍÜ™m?sÁ`åÓéýbú'Ÿë£\“ë5v®ˆÅbˆF£yY;5=EÊÚµk{jkk{–.]ÚS[[Û³víÚB7)%ßþö·{Î9眄Ÿ7fÜ'ôóèyàz½ž®mNíWª¾dsœpœF1]“ápïS=ÓÙÊ_!úÖ×8“î9±N§˜®I±ßûÁÌý½?\æÎBö…ÉŽwÞy§§¶¶6g÷z¨ŸƒxÀ<ß‚ zV­Z•³¶U_RÉcr¿¾ð…/ôtwwå=bG*Ùìé)®{ŸN>‹amÛ×¼Ÿ|:¡_Lö F>tï³™;³íg.û0Pù,†~1éÉçú(×äz+ÚÚÚò¶v.vŠÖ bÐÚÚÚzÎ9眞wÞy§ÐÍêÅÒ¥K{MœéG!û¹víZSa’jòI×6§õ+]_²¹GÅò%ÅtMŠùÞ§{¦³•¿¡ì[ãLº{ä¤~ ÅtMŠõÞg3wö÷þp™; Ñ&7ІÈ~ï‹å™~çwŽßÝÝÝsÎ9çô´µµå¤­ùîK_òHý²÷cÁ‚=¡P¨èî3xRÉfOOñÜûþäÓÉkÛtse¶òYèq‡É ƒ‘O§ÜûlçÎlû™-Ùȧ“ûÅôO¾×G¹&×kì\a¿fÝÝÝ= ,èY¿~}FmîrP”5T"‘ÊËËQWW¨®®Fuu5"‘H¡›–²­©ÂÊ2éG¡ûYSSƒ%K– ººz@mwb¿úëË`îQ¡ï)¶kRÌ÷¾¯g:[ùê¾¥“Ít÷Èiý(Šíšë½ìÜÙßûÃeîtÂ=bGSSª««QSSc¾VLÏt,`¥(++CUUº»»³nëPô¥/yìììD]]]Âë .̨_N»GÌàH%›@qÝûtòéôµmº¹2ù,t¿˜Ü0ùtÒ½Ïfî̶Ÿ¹`°òéô~1ý“ÏõQ®Éõ;WD"twwcÅŠ„ükš†… öÛ†‘ c Ý€ÁÐÞÞÞk_^^ŽÎÎÎB7-š|î¼óND"”••¡±±K–,ɨ…î' <©òÜ¥k[,s\¿úêK6÷¨¿~ŽD ýÌ„b¿÷}=ÓÙŽ+C}Ó3éî‘ÓúQ Ó5)æ{?ع³¿÷ 1îäcîÌä}Æy´··cÆ xòÉ'±råʄ׋噮®®Æ’%K°jÕ*ÔÕÕ™FAÚè9}mÛ—<ÖÕÕ™}„|nذÁÜüÓ=bN_²Iï˽O'ŸÍÍÍŽ^Û¦›÷³‘O'Œ;Lv V>tï³™;³íg®ÚOÇM&|:½_Lÿäs}”Kò±ÆÎ¨©©Áºuë°aÔ••aÉ’%9Y;Š2B…,Švúò’,$d]±b¶nÝŠÕ«W£©©É´Èõ×'÷3]ÛŠ©_ÙÜ#'õÃ)Ó5®÷>[ùsRßÒÝ£bê‡S(¦k2\ï}6mwR¿†óú†éM,ÃÊ•+±zõj”••%¼WlÏtYY™Y˜4y8Ö¶6lÀâÅ‹QWWg8‹í1™“N6â»÷}ÉçpYÛT>‹¥_Lj²‘O§ÝûÁÎÙös(I–ÏáÒ/FëõQ®È×;WtvvšÑ&+V¬@UU–-[fEFº¥A%•uÙ‰V®êêj¬Y³Æ´ÞÕÕÕaÑ¢E¦Â¡¿~8¹ŸéÚVLýÊæ9©N¡˜®Ép½÷ÙÊŸ“ú–îS?œB1]“ázï³i»“ú5œ×7LoB¡ª««ÍÝÝÝhooG{{{Q=Óä]÷ä“O¢±±𦡭­ ÍÍÍY·µÐÏt,òeËÐÔÔ„{ï½÷Þ{oÆmsÒ=bF:ÙŠëÞ§“Ïb_ÛV>Þ/&=Ùȧ“î}6sg¶ý ú’Ïbï#È×ú(WäkKªªª°zõjÔÕÕ™ Ö­[×oF‚¥A¥ººº×èîîvœµ‹,øvìVÇþúáä~¦k[1õ+›{ä¤~8…bº&ÃõÞg+Nê[º{TLýp ÅtM†ë½Ï¦íNê×p^ß0©‰ÅbhnnFss3:;;±~ýz¬_¿¾¨žéÎÎNTUU%<«uuu¦]1¯m—.]Šªª*hš–Þ"“¶9é1§/ÙŠëÞ§“Ïb_ÛV>Þ/¦+ŸNº÷ÙÌÙös(èK>‹½_Œ _ë£\’5v®¨««ë93tf9c ßç…ÚÚÚž7öôôôô´µµõÔÖÖötwwºY ¬]»¶gÁ‚f»º»»{,XгvíÚŒûá„~.]º´çèõzº¶9µ_É}Éö9áþ8b¹&ÃåÞ§’Ïlå¯}KÕþî‘ûátŠåš ‡{?˜¹³¿÷‡ËÜYȾ0Ù³téRóÞõôÏ3½~ýú”Ïm(ÊI[‡ª/}ÉãÆ~Þy碻GLv$ËfOOñÜûþä³Ö¶éÖ²ƒ•O'ô‹É •O§ÜûlçÎlû™Ëë?Pù,†~1}“ïõQ>Èå;tww÷ÔÖÖö´µµ™ÿ£Î,_eQzhllÄÊ•+QSSƒ¶¶6466¦ÌMYH¨xîâÅ‹QUU…¶¶6,Y²ÄÌÙ—I?œÜÏtm+–~e{œÒ'Q,×d8ßûlåÏ)}ëïK?œD±\“á|ï³i»Sú5Ü×7ÌÀ(–gzáÂ…ˆD"X°`jjjÐÙÙ‰êêj³8i¶m-Ô3ÝÙÙ‰ÎÎN,[¶,áõ+V ±±±¨î“{ŠåÞ÷'ŸÅº¶ÍV>Ú/&7ýÏvî̶Ÿù¤?ù,Ö~1‚|¯†‚B·¯¬¬ fýª£9tf¹`TOOOO¡1XH@ªªª6ÔÞÞn†6¥jgýpr?Óµ­˜ú•Í=rR?œB1]“ázﳕ?'õ-Ý=*¦~8…bº&ÃõÞgÓv'õk8¯o˜QLÏ4¯¼¼ÕÕÕ9m«“ŸébºGLn)¦{ŸN>‡ÓÚv m+æ~1ýS,÷>›¹3Û~’áÚ/ÆÂIræÔöåsí\̵A…a†a†a†a†a†af((Ê¢ô Ã0 Ã0 Ã0 Ã0 Ã0 Ã0C T†a†a†a†a†a†aú * Ã0 Ã0 Ã0 Ã0 Ã0 Ã0ýÀ†a†a†a†a†a†a˜~`ƒÊ¢½½‘H±X¬ íèììDSSS¡/ÃŒX,†H$‚H$Rè¦ô‚å“qCù<ö%N•U†a,3¯:a|¡÷xŒa†;݇:A>Y6™\Pl{+§èŒì8yïÌ0ÅL±ONcTOOOO¡Áä—X,†•+W¢­­ åååèîîÆc=†êêê‚´'‰`Ù²eغuk¡/ à 9ëÖ­CSS“)‹åååX½zuÁä1–OÆI ÕóØÙÙ UUÎÓÞÞŽ•+Wº»»QUU…Ç{ eee…¾, ÃØì¼ZÈñà1† vÊó?3\(–½•ÓtF„Ó÷Î SÌËøäT8Be@ǧŸ~š¦aÑ¢Eæ"‘a˜¡¥©© n·š¦á•W^Auu5{0LèììDss3–-[Ö뽦¦&TWWCÓ4<ýôÓæk Ã8 §Î«éÆj71ÌpÇ©ûPžÿ&§ÊªSçx†a6¨ˆ¦¦&Äb1455aÙ²eX·n˜ ;z?[b±Ö­[‡ÆÆFÓ«fÅŠX¸p¡ù™H$’rR¢6äºM©ÚØÔÔ„ööö|]n†ù|öc±X‚GÍ¢E‹Ìðå¾dÑÞ¦|©ÚËòÉ8…\?”> Ùë´³³‘Hn·PVV·Ûõë×'|7ÝÜ9²:Tó43rèó\ˆ5eºyu ÇŠñÈlŒa˜þH'WNXSf²ȱœ2ÿ3L6¤z– ½¦ÌVV‹aŽg˜\3Ôú™¡Ø÷±îg`°A¥@477cåÊ•(//Guu5î¼óN,^¼¨®®Æºuë°jÕª¬ÏÓÖÖ¨®®NÈ;ÙØØh~&‰ ¹¹9eW­Z…îînÔÕÕ!‰äÜK!‹aéÒ¥½&J†)$ù|ö«ªªL9ŒÅbX¿~½¹XíK©MC1fØaùdœD>žÇ%K–`Íš5 s" *ÎSUU…X,f¾—nî*YŠyšÙ ôy.Äš2ݼš)C9¾™1 ÓéäÊ kÊLö¡™à´ùŸaK_Ïr¡×”ÙʪÓçx†ÉC­ŸÉ÷¾u?gL¡0’Y¸p!–,Y¦ðÞ{ï &Ž 6d}²X.^¼Ø|­½½÷Þ{¯yîÆÆÆ>'˪ª*󽪪ª¼lMMÙo†q ùzöW¯^¥K—š‹æªª*<ùä“ÒË"04cÁòÉ8‰¡~S)MhaÙÙÙiŽ}ÉëPÊj>çi†ö<bM™n^Í„BÌw™Œ1 “ }ɕ֔™ìC39†Óæ† éžåB¯)s!«Nã&Ÿ 垎™9cÝÏàà•’¼ Kö„IE$ÁìÙ³Sþ¤ %oƒE‹áÉ'ŸÄ“O>‰ÆÆÆŒÃÃêêêÌ¿û*Ä7Ð6K—.E{{{Â9Æ)äãÙÅbXµj-Z„5kÖ`Íš5(++Ëx"Š1ƒ`ùdœD&Ïã`Ÿõ|0”²šÉXÅ0Ù0˜ç9NœWâ_ÆÎ`ç€b؇,ŸÌða°{«b‘U§Îñ “O»FÎ×¾u?C G¨uuuغuë€>ßÜÜŒ+V˜¯­X±MMMhkkˉÀ ´MDMM êêêÐÔÔ„ºº:V1EÇ@Ÿýõë×£³³3Á«fõêÕPUíííy ­dùd†™<ƒ}ÖS‘jL^GùòNÍeû¦X)ļ:Ôã P˜1†a²¥ûБ0ÿ3#ƒ¡Ü[9Qg4˜vbïÌ0CA¾ö}¬ûZØ RdtvvšÅŽ’©««ë5Ù•——Ö}Š\.h› %Û°aB¡Ð€óé2L¡賟*UýßÝÝíˆ6,ŸŒ“Èäy쳞 ’K»Ìvvv¢¬¬,o •\¶ŸaŠ•BÌ«C=¾ØÛ8”c ÃdK!ö¡#aþgFC¹·r¢Îh0í*ÄÞ™a†‚|íûX÷3´pʯaNuu5ªªª …Ì×B¡ÊÊÊLaŠD" ‡¾÷Þ{ÑÜÜlzÿ0ÌpeÑ¢EhooOÈ¥ÙÜÜŒ²²2ÔÔÔ\SÁòÉ8‰¡z«ªªPWW—° ]·n-ZdþïDye˜B3ÔrÑß¼ Ùíksig(ç»LƆÉ'ÌQýíC3•MÀYó?ÃdCªg¹Ðòš‰Îh òš+2™ã†É¬û¡RdØ‹e ò¢‰¨»»=ö˜ù~$Assó ­ƒi“ºº:,Y²«V­âcLQ1Ðg¿ºº÷Þ{/V®\‰êêjÄb1tww£±±eeeYËb.Ú˜ Ë'ã$Ò=Ù>ëÉ466béÒ¥ˆD"¦ÇÞêÕ«Í÷s-¯¹n?¡^Sö7¯0׿ýÖÊñèŒa˜lpÊš2Ý>4SÙœ5ÿ3L6¤z–°¦ìOg4yÍU»2™ã¦É×¾u?C˨žžžžB7‚É?±XÌ,6VSSÓkjjjbEà éä‘e‘aœƒ]VS…H³¼2Lo !ý­s—-[†5kÖúÒ¤m7§õcrSæ¨tòɲÉ0'È«SçÒþÚÅ0 S8Be„`×L†¼o†ú’G–E†q> stream xœä½I¯n9–ž7_q†‘ƒ<Þ-›©Y€ À¶"gÁU9©Ò(•úûââÛ,òĽÑ! ª‰û­ÃÍMr³{¸þ·ãóü8âøßÿü·þ·ÿX?þúß8?âþõ¯?üù¼ÏããÏW?>ÎöÔã£_÷ññ¯ÿôÃÿóK:~}Þý£´ãølåão?\o»>ûkÉ?[ÒÎã?é!&Q?ñ~üFÙŸÞëãçÿøÿî‡ó)ïçq/y¦ä|?kä'ËfÆ™¤í-3S´»~–ºæcÉ’eÊG?3Ÿë:Ïû\ëhIæ#óñÏÌ'êØúU>~þñÑþÛhªùAùŸÿü·ó—ñiÛÇy}üe´4þøqÞåóˆ¶(ççhÛ¿üí‡øñúÓŸ¯úyßwùñØþyÞãk”úãóË žË÷\5þýü§¿üûþí_~ø¿¾ñÅÏóI–^òÓÏzNt‹Ò>gK¥¬êq_Ÿíͬ$X³ÊDÊjM嬮ò|¶gÉŠ‚-+'rVK*gõôòÙî%+ ¶¬œÈY-©œU½Úg»–¬(زr"gµ¤rV½Œö;—¬(زr"gµ¤ú­=mÔãºëèåuŒ¬ñÉfOÛ{ÄŸëÇuž=úá?Ž¿žßë:Òµ†t_ûë×tÊïþù}íÞßK÷þb×þ‡³DÕÿÓø¿üáúø÷¿iNüiŸã~6þô­!³ÏŠß0_rù…ÏvÎíÏñõÚ/WÏöù>7¾Ü¿ûÓu|>×Uüßÿô|ö»Ý?þ‡?]ïgéµþøøÿç˜ÆX8[ùñ§?ý¹Ÿo-—›¯þ=ÓÕ9*z>£ý³ŸEùÇü ÍþÓŸÞòãßþôçcþ|ûöïÿ;Óý¿‘nþ¿Eø¯KÚïý{I¾f]¾dý/ùû¿þË·z úÇýãã¿°IbÝ:zId¬ Ïgm¢W|øw´xŒ¾óŒ¿ïÜÑ/ë”\×ø|¥·óó~!èŸeNxíólS2Ö¤øš÷ùù Éó|¾%¾ïóy?Sò^ŸÇHsÕ‘Í Iÿ|FšûhŸýš’R¢õîÈµŽ‡ë˜°F‘n”aÌ7õiëôÏ« IiÆ´Pc2¬÷ç|óu}Jîû³G’¨+$Ϭn}G©® ɨÊŒ9­Cð–h´ZΑݬõ5J1 SF¥¼z4ÈIžÑ ’öƒãÿ}ð¦Qß³D65š,$}TæŒ|,ðç}Œõ6ÒŒEç} £k´V¹ž1t¦dlFÁj‰½$£ žhЧ~¶Yäû¼ÅÛhý)iñÉÆS5¿Ÿ7:P-c–(³Z÷;†ôh¯2jƒ&½Ç„>Z®–ñ… %£¿DšÑ¶×¬é=fî(ò{Fo Á˜ŽhŒÑç"x¼úŒÍÊÔ¹‚”ç⋞㦜¯>æ÷}Ƙn3ßÎþø\s³3 ||’ 7›ÍþÜïç5Ó¼ûybkXåÎç;¢hÑÞ¢Õ¦¤~¾Ñ£{ã[qŸ7žº£¶!}è™iÆÎ ‚1×Ì$ãa”¯Õ¹xFi:$}.ø£ùîxå¼Çcu¤)vïÑc¬Ž4ûÛ;:H”¯j|¼ãÛÇXJa ¾£D-ǶUxï>ÇêÏìJÑŽU@xÇüc5?æ;¾HŒÕg¼=ûÝc×Ñ)ÐMÞ(Fgtß’‘úªhÀ‚wõs×2þûPÒçx­ã»¢å(s¼f³—˜bß2F2ÞU®sØUÒæ€­£/ÕÙ^elMŸÙ^5FHž;l¯¼çË£+ÎÛGÏ| iŸ³4E¹Œö[Ç÷@ëD;Å€­£T,ߘ怽µRÒæ€­cÆíÈx|’°ñÔ,p|€¯5ÆÇ,M{ô¯5¦§ I‹±<ÒŒ.4‹SÇÙÚÚ8uÌT1^³Çô8ÇkTsÃøns¼Fq.HÞ×ãµARfo¯F#ù¯ã»ž4Œ×ñ…Ñ€uô«Ô—ófíØòE —ØBÄ€}ÆÑuÚ(E ØgL—x*ÀeØR9¯·øŒ9c¹hc¦ºÎuÎ!wœPÚ˜©æˆk :w#uŽXtÅŒ™ #¶s6kã­O[V«‡ì1Û½5ìwËøo£¤cÈŽ|0—¶^1dÝáúñ`È–ÙCr^²WTf °¼FÇ;f‘û5—×K7–ט™09ôçâÕ”Ò,¯9-öËkÁú’‚6$˜{=9d5ˆû¨Í²£Ý1@{à »äÓ±ÄÆÐ˜mq–XÏCÒ£åfÍkŸ’kl¤™ç:.¬±elnäƒ-Å\"Næ{_ÜjŒÕKì}±·_Ç‹%vtñ¯.\bÇ,vR‚%vyu囎)h\a£ðPç «upH¸ÂŽOuMÉyh…ŒÑ®‘ #Á…å5fúÙxCÂå56³Òc5Åò:Ê2‡ý5§±c^Ë;& ×ÊùwH¸¼ŽÿRR°¼ª¯]cjÀpåJtËëX¡ð¢Æå•åï\[]Úñ°¶jÝÔABvÆ!ɵ•O]\[Çr„rÝ\\ÇP› Óu=\\G;Ô’Ñ™gšQ£)xµ¶ž˜ýÆ6kkì6ðªÂÅU{œknƒ—Ç Ðg®†Åõýlnr¯«çâÊv.®þ,÷Åu Ã{6çàŒÔñÐÜÌJaq-æŸ!ÀâU˜ ÁØFrqÍ4×2«’‹kì çb1$X\cŸqá©ÂÅutê¹/DÅÅßîkP½ðê™4¬¬ž®»se/œu|Æütp?Sg6ω…Õ›©!Á 1çË빸°ÆŠ1K÷ÜXXãhVéy¸°Ž*ÍÍüÌ…5ÊÿâÝoáNød'-û¦žžÊ…utŸŠŒ+Öûr¤iXX½E¼žŽ•5óy¬¬1ITJ‡*7£×{be}Æ<5‘å `ˆ¡¦¹±²F™çgH†êÃÕíz®¬Ïɹð}±²FšŠ| VÖQ@þæÂšå«XXï†/¥£”òòÿ!H÷þP˜ À´3àÇ dFlX‰’Û­p,åØ5p,tóP•ü7~¾\ˆÉcþ¢c‰ÿJ,‰Lþ+ý~¹¤‡äÇæilP àØ±Unˆ€cWW¸%"Ž=Òñ…K[1àåABà ,$#퉧Çx;Ó‘FAà1ªw¬x<‡8‘xŒÎÌw H€Kà1бðˆÙ¬OÇ+œ"£_À0êX6Ìâ èȇ+kH±WÁvC¸ñ 06š˜„H€ÇX¹*È’˜ó‚0ãf%FßF#‹1?`îFšÈEŒwÍM§0ǧ0Ë#Œ4xˆ˜sƒ0úv%‚=7# Ñ’xŒ& —\€±çÆØ#ÆçEF’JÜ;8`oâ¨ðîD`|ºxE$ÀlA`tž@G̪Ý‘€‘d.D¦@S`¦f>¢À% )ÐýÔè¾l ŒwÝæ—fÍ…‘†øF Ìþ% ŒY@/ Œ^…æÆEIîî¢@§fa‘d+ôØ3.iË‹YoA`¶± ÐÓ¯!0Çž80Ò\ÀKr`¶80ß%ôÌdôr¦FðŒ^d¤Fpl¹S”Jð¼šÂÁ˜xÏ ÏØŠASGŒwm4xÆV‘ @¬XgìZV•à’ i0ÚÊ=À`üž%Œù½É‚ƒYvÂÁHs! q0+¾pðŒM4U„X¯ yðŒ™écÁÁ3ZDâ`Øõ`ç-<_æ£Ú禸ö¹©cÃ~X4MN†ž˜mDÞ!ž§tÆÂÁXU ÂÁEBà›&; i|3 vŸ¾…( Dߘlͱ@|#ÉÅ‘oH*í‰|CÒp"+䛨”ùÖ4@¾)9ðr|“è¹É{³#_+ï-Ù’÷–lÉ{ëS¾>¿´—?†jæ0YoöÖ‚LØÛC5ß Ø›PXoÉWN¦, AoɃ 7%0Ò[3y¸š2`Þš 8oùì½5 @oͤ7Ÿ‚Œ¤7·4Tbv®¥™¦s-u>@½l’ÞR%ÞR¢ÞšÉÍ¥4z´”4@%êÍŽÚVÔ[ó)\J]Þš1HoIÐ[à¼år^&!æ­‚†ÑéJó–$“ò– ‘ò–ò–ß`¼µ `¼5“Êå4ÓT.§)i\NSÒµœ*BÞRBÞ*9¹œÆà‡äâr:ÞI½WSù‰ór£,Λ("ÉyCò Ÿœ·&ç­’ŠÕ4Ÿ¡fHæáþO‹§ßùU¥WB͸Ð]s@_; 5zg8V¬Æõºe…Dº»ÇÔ²kôî𙀖twW­L»§Q— ¼{bÿŽ7ï^ìß¼‹FcÆÄ»ØÂ=Cx÷ŽùŸæ‘Ä»·ö¯>~o—M>~Uæj»rÊJFxWN[fïJ,kPïÊXŸî;³F­*½rÊv)ü^îì…w%æû/N~Eiää—þqrò‹3ïÊõrn?û ï&ê¦Ó{ kÓé½]¤k¿CмwÌ›ô”_¾]>~¡ÉÏðÞ.`à½aŽŒxï)÷QÞM±^Œ·¶Þ=>ÙE‹NÞ=šÎH¼œ›Rï¾åª%À»ã„8‡ÃÇð1¡î€w_Ò ðb²ßL<ï0DúXð.V < ïîKúMá]Hà&^<õlN~÷hÕÇ/¾jÝ <Ãæ^ <ïãùbàyÇ.å#énäz}næñâ¾™wÆ Í¢P«’c3ïŒ|Éš„»ûfU|wui_Åw!AÎ⻿B¼«ÉUU”ç†ç¥±8ï ßK8ï*•æ⼫Ëo‘œw…‡äfÞy…ýÂÇ‚yWxÖ¬˜7_ýÐÞg±a o!µzñÔ½Yw^cØÐUZ½l iõBRWÌ›ùœ+æÍR;H­^ þ¶iõâc J«OQeG­^”¶ÔêÅÄsoZ½«Ëû‹Z½È…šÀ® tÛ°Vïzh§b­^öiõÜÈRê-ÙP«wôRÏ­^H@$ÒêEhñI­^ìÅtÐêÅФ:ŽZ½›RëÅÛi€Ú°ãÚ)otÉöE­*À¨Ö‹§HlPëe6Rë¥'<Õz±j<›Z/$…LG÷ùkõrÄH«Œ5VíEÅá&ÕÞò.ªöV W×”PµwV^Hµ7æw‹Hµw=ÜÊY·ÒH·wFγ1¨Û‹V§Îº½°¾[­; ê¦Ú³‰œU{asÖ6Õžgu«ö U{š­ÙË™Aª½üxRíe÷—n/¸*a©÷ÆÂP•v/g i÷r&vÏK©µ{Ybj÷. í¤¾å‹S»wÆm^~1Jëo3ð<~nàQtve_§ÓåbàÙìÚ;”ÊÑo óÃ{Uö]a?¼Å{ñ¨0>£ÅˆÄÁ›'ÂÁ÷jÒ< ¯Kac„ƒµË*T8XZ†8hPã`P<§„ƒá'|ƒöY5Öƒ{zÑ`=dµ#¬Ï#Ýhpl¾ir'¬¥pãE¬aQò±À`lœÎM×W‹j)ŒÍ.èK0xƒ{¼Çæ™J:Ò`îÖDƒw¨5>ô(1 Æznþ~µ;¸ a°ÝœA ƒí; Ûè.Ћ cËØÖ€/±ùk›…g­Š¡C\’c·Z¶ˆ/ãåÂ1Â`Äúx7m_}Š Ž0˜!/ƒ±çÆæ'C¾ÜÔeÈGŽqÈG—qÈ——F‰ù2ÚäÞL<34‹c¾ŒNŠŠùâ Žù2ÊÕ÷˜/ã©kåÁrk[ï˜/±E‚1拉'Ûó%Â÷­ê¾ù¦w‹ùaˆv;Ï ^(Ÿb¾  FëfèY.s$‰0ò©›¡g gˆ#Ÿcsø‹ÓIèšÃ_8Œ£ç*æ‹9拈„y6#$Œƒ?ˆ ³ÙóÅGbÂ('¦!1a” ó¤˜PžßFB‡J0†ÿ8NYóÅ3ž°<Š "$,ci” Ë%×-Ç|Û°¯0ª@ ù’¥QÈ—GÄ¥/Y˜n×töa9íG"Œ6f¨…|ñ÷uÈ——ç¸òÅÅqȗǘ¦/¦d‡|yx’ž!_N9†:äË}+B¾øÌÎ!_^‘›C¾øèÏ!_ô=ñEññEñI2â‹sQÄó9à‹Ý_ÂT| Cs<¥€/£Õˆ‘ øâxdøâ/ã€/„ –«+ ‰0N u|ÏýLO½¥®–d>’1ÿü{GʾÇÜ¢-þž‘²«ÃÅž¯èŸñûó/ϳž²þÚ…¢ÄÞ|K¤¬2¶²Zƒ`+«LŬÖDÎÊA°ÕÛY9•²Z9+ÁvVKlgåTÊjIä¬ÛY-A°•S)«%‘³rlgµÁvVN¥¬þ@¤ì;) dþ×”ý[æÆŸö¹îg3áOß2Ûìøíñò%—ߤ:ôÎgýÿUŒê1¥¬YÿKŠ#×ÏÁíÇ–Â T}ýz êѦ†yÌÉ-ö} Ñì•'¥÷Xra|öòPòŽƒÖºxÜql>¹{£ NŸ¦‹ù‰Ï}!ºnž}ÍÛ1wŸV¯ß¡‰="èt á™Oh»cû'A” æŠýgœéÌã¨ç<ù™ö'‚iØ5#JÏS™;¬®Ž³Í¹=øŠ£ …‘ä+rÇ?ûÏ»@O퀾§‰c·9ÁæùÏ…7µãÃAǯŠÍg¿UØþ`óÛŒ™æ9¦KZ{ Été«5ŽV¦ ,‚Ó^ܾŒÒOuê*Aܶy 7÷òC2£&Ô8Œ`ÆÏt3õý¼S7_kÐê¬õ'OqÌúÐøiH¦îxŠXs?ušŽÖ¡ ñT{pL?âéçÜ}*Œñtó½¡ >h÷#Îò毱Ý?É4'þ~ØzžzÕ ,ž”8µú÷{Ïø&5öw7zæyô† §E÷A®å{Hæ6ct‡›½ê-F9ÃÿÞñ·ØyFòI¤÷ >~Ú=äS§èViÆ:;Ï8œÍÀVìdè; ×0¼$’6wž7?ܱÿ;σnA÷¤¢°Òa¬€{OLÓž—=krDSt!›wn´FÆ·²)³sOÛžOÕ©EU8pÌsG¬Ùsk®`õ,È|úÌq•jê;ÎgpÐBÉ]£™"€h¡ù޾ZgšgU÷ì™1IÐxëŽnõ¹:x鮡{ˆg¨—‚¬wæ;9â®AŸ1hnülU& †3$&t•Ëw ûèH‡ÆSÒŽÿo<Å01ƒ g·Í+±”ÄPAƒÂ´8rŠ4•]ïQ6bR UÎlšöÌCÔ‡âèê zù1ši®r·8tŠÆjÔAÜ­ÌÃ’ú<<*½co3"+A‡dúÎ ”µˆÿ[Æc’ºfÆÀ½{˜(„€ÇåC0½ÄæÆ )Îy&4c’£÷p-‹®§<³0ýÆF+è°RÒ0ZM~ý)­ÇÍOÓãЩ.Ê«AÕgœç É«òAo;ºß«wI–®>­MÛ:ÂQfŽÖàuJ†k¸øÃEÄ=ŒÖŽš?ÇyÏÑZè¶ð„[Û­… ñg†ò[ÖŸgú¼¾¸¿àÀCÏÑÚ©´{fت²Øü=æZÑû9 –UŸ=?GŲêS»çhXVãpòEš†eÕ‡ãc™– i6ùÌè÷2û>3Õ¹ºFÕ<רv\`qíŒ+ú<'רUÌ9òy®¹¸æ€yn,®1¨J°¸zçñ<8À›iPÍçÅâ§ÚOÁD!O¾ŸXÎõTû‰E`×P^LAÃÚJIÆÎ𙟳až¦Y÷© =̺ç&86Õ³)b¯£õÕ’ ‹kqM5è`q»Mæfï‰ ôìxûœ6Ç«ëòÔ;W×Ð.`ì½oåp¥šýy ¹QÞ˜ ç>X•Œ?·Án½·aq SEšŽÅÕEöP—(I”ƒµ³(q¶9«TÏ<#¿Ö^Cå2XC†Áª3,+ýŸˆž=k|æ)(XZß—;å'ÂÕß3 ƒz=S "ºÖ¼ áÅC˜”â:ŽŠ­ÔC–Ö8=qx`mlæÑÆ7YÜåb&Ó!Fh—O9§ÿ–8ÕFÀѪ­mxÒ)ÔØba›Ë+pTçT0àØ,2$¢ °´FSAà€‚‡Ô‚ÀÑTC K(ÙÀa`À;lXÈ€ƒH›@ ˜Nm‚ÀôL1Ú»ÙÑ”žÃ[û9A ƒäJ£9C #:Î7}aƒ% < ÍzLGåZo t¤*c`¬ðmÃÀP¨á]ÂÀð9áSÄÀ£Ó^Ôx†Célsaày™J‰½ [5aàyÐbÙx†Füc¡Àˆþ…-)ÐA»LgœåÌ$¤À¨&I á·°+Fñ6<ƒ¥6Œ7¡m‚ñ¦ÙÏ“{Vqà uÚÂav….+<# 4©KÕ*ž7î´2ÆþèÙ8ð¼f, åã\ÇÅÁfŒ‡6Œg:Ø‘o*$C,U‘ ù;±ºq`¬V!Î =|ÉÙÛÄçEã}q`D…|†X¬¢š`3r`æ"Œ‡:ˆŽ˜]TO= Gr`”ŽdHôÝwæÀàB˜]]¸äCt½…auynEž“’90Â~€¨`’Æ@ÇTº±Œ¾ÆÀùx#b g c`¼‰ÄI \Ò£Þ¡x>¤fc`ŠÄv^ìX…ñTâ= ‹Ódw½ˆYb ã’³ZÄ@‡¿4F=AC—'ˆñÈ»aà"!F'!£µœ˜=ù™óÛ‰cª«äÂÎ@¦\ÊLÙD@/K¦À¬¥(0Æ3¶¢À`H \jZY/~pR`V\hqSà Òž oÌ-Ì‘ ô7f§ž7ïŽ2.2 —š—·“ 0ž:6ÌnM\„ÀìJ„À‚À¨Ã¹A`uņ_èÕθäCt(XC`äŒ#A`~Qà4MBR 'A`6— 0_%Ì!Ìj ã)ôHA gQC`ŽgB`yA`$éxyy×9J˜ÕfµE!®‹sâFǹUÄÀ|J˜…²§‹s†*Ž®py0FΡĀK2`ؼ¹rYåâlÌáMôÎÏ è ¹0†7U èM¦Ð[­ß£ÚñÍËŠýæ®›8ãŒÕ¨t$_+ÏÒ$‘&ðâµ$© |tø.M`XŸ½›&ÐþtÖΙy>%Màƒ4Ôžý þšÀ³?Ò¿Ó¡mxE¼2d Œ7†‘)À€×ùR7$¼;€cÑ(Ô b¥šn ^ïö5†wTfDÀë¦W„0$P §r|ÓÆú„“o!àuóRJ#`¬X}CÀ% 0r®”`¥ºž[˜HŒÎƒŠŠÃÿª¬ ˜Ÿ[ h§U1àõÒrÜ h3`¼›ÈG ß/ìhQsôA`´×Æ€ö5Fç«( !0N°^ô<‚À0ª¬ÆÆ÷Ú9ÍÍu¥(0ì!ÏUŽ·dQ`ØP¢È¤À«U")pú²lÚÀ«]„TQàUác´!0GhÿgC ]K vÑ2Fâ¨@_ïBB`Ì à~A`H ¶†ì ž#†] 8mdñ!p‘#Ü=†¼ 0“Zj¯‹·_sü —âs†uî® ¼Îû“¬TY~1`$ÁÇÆüC%0j@Þ$F%ÑiÅ€Ñý˜† ˜c\ ˜c\ ãçf„À°†jM˜Ó!0G™ 0§2Q`LeuÓ†äÞ(ðŠý°‹ŒqQàò)0§kQ`~MQà"!Fçç»Hv½5†7'ZPhwXc Ýa…ö96.# !ÚÿÞ8ÝàæFè@ÆÀpÄr/ ´«¿10 »/B—V9›=‰c†Æ»„1ßAÇ$ Ì|„žñ6¤ÂÀpÄþÃɼ“ ¹¶Æù7$ÀÀE@ è’À@ïŒÑ  #a ÷ÆÀسP=ÈÅU!"Œ± A& \$ÄÀ¨uÝ”‹äÖâÊÛ팋„vûГ ÝÕÚv˜¯“WʼnCÐ7]`Hʪ ÌgD™DxŒšjôÈ ’cSjr3zâ2æèÆ@dÆäÀvP’‰WIã`¥&Áh?~s ŽÍ9ÉKr ý¾Å‹€èæ@‡÷0:¦…9ÐÝM˜ÝMèøÆ@Ç11Æ:6e`2q` ͤE´?¹9Ðs`tML'â@o`ÌGaôžK;X½‹c¯8Ð['s =ýÍ1Ìꦌå -!ôöÀ(x |l´õ¢Y0$$L²` ÎNò;÷á*ŒaEÎ †“¨PpÉ((F…‚×è»à>’`LWu#Á |•´Ù¦Aѯ„ª6ýÝÓ§n¥¿se¿nm8Å·¨®ÈJ+Ъ ¥à/¡ƒiü…Aª ©„ü…×ú¹Áßt~§ÂðWyñlÒŸ®÷Iú‹í¸ŒôwFÑýíæ^Fô·¼øÔAø~ö5ñ/Ü¿vü 1ê‰g£×Šñï¬]L&`ø BBþ‹=› 0bÊA?` .a2ÿE%ñ¬Œþ±Y‚†¯’0f2h$¥,H õßÛ¥²”þ/KGýŸ¿­õº3Êú?Y¥þï•–õ<úJýßÓŒÒÿY›–ú?ž§þOG3©T<ŒExÊÈS ÀÌG @kARh­¦5€VæYÈ#ÜÔF°òMh GjyTd `æ²h©k´Ði¤´~×@/@¿JÀ! XxɤoÕBËj  UX©”rÇ@]¡•@÷6kC9¿ÁŸn³0SH(õ…€:²MàS¤5¬Œ¸q’ôtLÉóäTêà2€:>N ó±0“ÍÔ ŽTf)y ™ú?]§þï–=„õ÷~ùý­üsÏ·ò/LíWðóùbjÿtAYjÿŽ/V Ñ¯0‰Yýçþê?鈭þóKõŸó‘úÏúh«ÿR"õŸÌ¬ýó ³ö/ Kû—©ÿò)©ÿ¤¬OõŸTFÒþù”7Õ‡ E©þó®Õ)‘úOŠÐTÿ©%RýçÃa«ÿT…TÿeÎRÿ¹ÀÒþiX¦öÏZ/kÿÔ)Rû§—Ú?elåßU¹¶òOóš•®”•na)ÿ2)ÿÂ=$©/¬.ðwéþb“ ”îO×È-º?*S÷gí••ºpSþÁÊ6•©”òO:¯Tþݤ5ëþ¤HÝŸ³±îÏJ;éþR?(ÝŸÆaêþ¬T´îOª>ëþôݬû³ÒÁº?+&¬þ³–Ñê¿Ñ# öÏ]ÄÚ?÷=kÿ¬˜°öOF©ý“ª"µ×#ÛRiÿÜó­ýs'¶öO;ÌÔþ¹kIû—I¤ý»’ÓÊ?ÏÊ?¿ÈÊ?:¤îïb” Ôýe6Òýù!©þ²pRýÉô%U²/JÕ_Ü#²ëþZ8u²IÝßIœÔý©ÞVýÅa$RýéJÇTýæ#ªþF¥Þ ùr¨Bõ§Z[ów1Bfjþd“š¿ÌCš?x+þ”¯õ~þÖû¹BÖûÉî%Uˆ[´ðÞò”tnëþâpùH÷K%Òý©VÖý©G¤îOuêO"ULaÍŸ{HjþN"vjþØÂßYmÆk3¸Z2^^ðc_„Œ£U'Ï!Ÿ"‹MRÞâ¶GÊ‹xÔçFy1®6;ÏàqRBg¿°°…&NÎ~,FÊ‹®|Ó·Î~q°¼Q^ºuØÛ/Â9 )/€ªBP^ÀAËO¬Han~¯†žÑy¡¸åEÿ'aåÙ<Þ”gësS^8u<ÔéÑ+¡ó¬Í”çh-¦<[’›òÊA Ãz”ŽpB¼0,Ç~^ˆ·HˆxADw2·Õwd¼rY[GÌ O”…”ç`öõ;¥Õå…ïY¾~§uuv÷³’”ç Æ<‡¤K?Å,O¿ðÒ$ÔÑ%á|dQ*¿C;K¿§®VžÑ6x±¼ýî¾2^¤§ ¡¼ýì]go¿çµéì÷2e:û½Œi’Î~/Ï“g?©]íìw]²Í”³ßØà^»³_á¥1éìçþig¿ˆ|‡4rök²“¶³Ÿ?“0Ͼvö‹ž‹âóf€0/PÏ ó"þݱYy¾»V•òö‹˜„»·ß}bM2æÅwÙ(/¢PÒIÏÎ~‡ AíìW©Ng?ÞDžÎ~±¹ÚÙO‡Svö‹æßÔ{á2Fß9{û2Ù¤·ßór¯`o?ÄŒJγ£pzûiJJo?¹)§·_¹¿xû¥ÿ•8/ý¦Äy‹«!9/|sëf曲{=_Ð`Ð{+ eÌy^ìÌyqóv¡=ÇÙ1èÅlZhÔ‰eµð® ƒ^4|WÐ Ánå•‚ 8oùÅE5ôÏ æÅÊ4{ú¹:rô‹áˆ’£_©2 ”£_á-Z‹£Ÿü6WG¿c3ñŒ*?æE³|ñó;©H??Käç‡x– å-ùù©-íçg¯9ùù¥‹œüüBYE“N®ª®x:úÙOŽ~…Ç¥£ßø6ЀØÑÏßÚŽ~îÂvôc$†ÅÏïøbã™ÕL??µ¨ýüܧíçç|ìèç—ËÑÏm!Ê‹$ô¾æ…Ó(H_˜ç‹ò¢0çfâ™IHy/楅ò–²ùЫN¼t æ½ô9”“Ÿ?®üìi'?]Ö‘N~/5éäçW ò"ŸkÓëÙ¡?üü½ yñ® ò²ß}`‹ò–²ò"®ê$Ê[²%å-qÄ<H7?O`vós‡°›ß{³Þvó{^ÊÍ/}íäæ÷ò.¨tó{##ýüÂÉ”i?¿"Í£üü¾8ùÉ;ÏN~v”“Ÿdqòk_ÔzñÔ»xº±~GŒêTñ=Ÿï®áÓöÌž×E§‘:ËýI™ðWØî†¿ !Ysþ 㢈ýbN§fŽìç;Ù¯mQ^"`,Í4 ~8±a~%ˆlóÒe Ið‹Ø¯Ò÷a…ªçIý Á¯Æ6‚_=d‚ß(‹Ü ~5b* (¿úÞ_À/B=Œü‚Uªõ‹yg MžR —§Z™‡UªÝ©ðÃ*Õn)Å~3¬ë¦Þ‹m$Tì×NÚø˜ý"¬+%d¿VÊóÎvùþÚ#?KÁ_Du¥*ð_ëYÁ_”ŸNðW;§ ŽÝmø«•ª{Ã_½y·`/ùµ ´ø$üe@Á_„'Œþ*‚R/ôiêF,4Þ$ýÕ—•课œ7MŽt.ú³7ࢿˆ4¼ëø"›c‹öR =–MÙE‘ƒHô·1µ~X¬¢MMÇç  ¦?/Ȧ¿Ü· ÿr˜ÿtÂø·ŸÿÍ%kSò9¸8Ð1V €^ €±RIŒPMø¼"@b5Ú5ßè-£ 0tG,åUÄàÛy¦jŒ8}³ðt u`©šÁE€ÑïC²…{©ƒl®MÑ_~#@G©5òüIø_ôÞ´|¥Ë¿UøçpàÆ¿ÝylN~1»Ý›“_=èdþs¤XóŸC¡›ÿê 8¾à_=è‘+ú‹€ïâAП‚uþ\Á_ù$Eøs¿ü¹»þ<¾ cÍüXÈÏ‘±2΢נSùyœšüêu;ç¥Óó7ã¼ÔWôJò«¯¶"¿#n³ìŒ«\Eq^zS,¢_-"#¡_½=Å8/]º#Çy©¸”PäW_‘Á/v>G’_i2—ú-ÁdÈ~ñIv»Îˆ÷¾y÷E+P{Gö+•‘™ýêEk³ŸûÙÏÑÞÌ~!Y‹ý¢Èh„¿¸ÙâÝT|1‹¾[—B?B’_„š¿Wý^ìHÐþ"¿hX “üÆnŽÏˆü¢(›zOwl˜û"ÐÜà¥4^@eî‹Ðs®|\POy~‰ûb¨ÃfMÜWÚ%w?‚ŸBØ™û4 }1élÑ]¢0|©ÏAåL}±3„’úâëã@Äá]Z‘)&¨ÏáëL}õ”ÛûhªÏð.šÍ}5Nu6Ͼ“ÏæÙMC?>…wiRÔ‰û¢VŠæô‹ïM@¢_>%ô‹ÁDSL¢_äSèȇÕ4êUéì‡Õ´R8;¾K¾ _Ü«!úÅn—*@Åwé²@|—‘„ŸD?n‘Ÿ7ÕߥÑk=㻌^snñfêáH~ùf‘_i¸fÅà€0â Á/ö$uSðåÔ"ð+ß|SðÅÓu¿ÒªM<~±pSŸð‹‡©$ûÅŠ ÔÃbÚ/®’ýS0#ˆý¢r} ðÙ ®’ØÏ¥YÂQqß#¡–yïB]B®JâàÒ߈I”à„£~cO|®Ñ[S’áŸ%c XÿÌðÏe^𴆵NIæ#óñÏ%Ÿˆv÷¬a­S²äC™òÑÏ¿w8êw†]¿ŽúgÁ¤múq¼Þï$øá¨þå߱ߜ—4/z¿v¡èÏT#¬©”WFšV^k¨iå•©”ךÊy9Ô´óZbM;/§r^K*çåXÓÎk 6í¼œÊy-©œ—ƒM;¯%Ú´ór*絤r^Ž6í¼–pÓÎË©œ×J=Ï߯šúí Ô×/¥þYúNPêï¥û”ú×òûÚÉ¿—îýÅþó Ô¿e†üiŸñ~6þôͳ͑ß5_rùÝA©#å1¦˜oF¥-ð×üç?9$ô¯…¦ÞâGç¿–?ÿ½ƒT/ÂÿúüŽ ÕïàùØ•Ž©z†gÓ9á¯01æ½û‰Ûê%tHæ…™cù奶£K,íe‚èÀD ú=SpÍH2C@›Ž÷uÜàz×¼ì5¶¥G8¾c³‹³ƒlù>ïÜÃŽ­7/ˆ’“3µ¿OÐ/¦AïƒhÄÓ]¡NÁØ O‹|jàÞ¡uz"\8µxc’š&gº'ò¸©ˆ¼Ý¡hxã²ïóüHç„7´¶qoÊÙxþÿ†.mÚœu‰½/îa’%æ;c¢Î4„Ò!ið3:õâ`zڜšò)3€Ezª¾¡w‚Ãý‹FH‘ÓÍèzTÀ6™v­D¿?ÏÅð…ÓælìÂЪA ÷†¡É¼ïö¤ â-ÓÉ( ~¶o\W^ºù¼qÈt2ºxû÷´\ÑTƒ¤ñ ÎkÜ|8wfï¼é°Â!çÅSp0’òΩ·nùŒÆïÅ¡î­ñ4:‹Ër éWÆqÎ|Wìä§“Ñq8ßz^0:‹K¿‘朦âó¢Í¹¿Ûó «³^ÒoÐP]_Ž×ȘA‡¤ãÒ[çûV˜¹“DØð—N,¨CÜ.8íC;¿ÞŠ˜ëÓAð¶ûÐø J3ROûÐJÅÌÛŽi–ž:o\x]kç“ëiÚ¨´zÛ5U=ó]ø6-N¡¦WPÅIÇh=›ÞõLOÓ4ÿ{#F–ÎÕÊ9k§ÊtëHqâM£¤÷Gúó¼­Ý­š¸·õ£u‘4ˆêE&J5îÞ| 9o ÖJ}þÛ¯ƒUŽBCÒ0X+uGc¸¼¬™æ¹é¥6îïÁ꯯é¯ÓpzñöòÂB´žœþ:n|ŸRó÷ím:LOIC ÇDuâUIúËÑʇÆð½—ZŽóÀ…·*K9pÄ3¿î…4÷œu*sï©ù1bÆ#<î*Ù±®®Z%æñi!Z©P)G¹`!ÊL*v^Q¶ƒ’ óЗgocªy0R_†l/Ûñ¹?òâß2¯„íkigºçÃ×ÝŠSònà2o„}—¡QÂ{:su¶Ë¼ö]úx9çuSk.#ž>l%|´Þ­1ç•°em™ø×Ã4ù´“Õ¯juÖzÞËÒÍE¢Ä¬8G©\Íʼ¶­™ÌYý^_4ïƒmka©sŽR·çŒœÒs¨”y,iÁ«^,©rÔ+ó>X6'¾ÜôDÞ Sµ¦²¯–¢qqš ]æ…°«÷^‰ aç0­¼p˼¶¬¾O¬©ÑmçaU™7ÂV„ëe‰a1Lqp]æ…°u{ÕÃ%UŠe^»zC–¸¶Þ¥ ¬©‘Ïl›yì:˼¶Crâ¡Î55ÓtÎóü»Ìë`_l7æªZ(sV.ó:ز–.®ƒmç&¹¹ª†{>$VÕ˜yfYÜD™»–B+»¥!žÂE5_šZ.háylC^¤Õ¯Åén¦ÖËã2ØûYGݼ ¶#ã¹<–y,7cSCXâÒ‡ú‘±Ê¼ ö]{I˜£•õE—ÔP½Î0CO ì†é¾Ì»`Ë.Ñ’ª:Í»`ëÚgCo4Gj¡C™wÁnƒ5î‚Å’ª–˜wÁ²kMH õݬ®Õ¼ ¶­M1¯«|ÖA?U3}íI3Dü³6Wy±¦.®©.`\»}©yìLraZ⸧ԕæ]°­w.ª®Õ¼ ¶|ä¾¹ÔS‹*Gâ¼ ¶®Ý-è1XyWF™wÁÖõC„†¶ÝkÅç]° |Ïûb´úÓÌ»`û:®jåššÄ-áK³ÏÛ`ßMŸàNÃõä %î‚í+/Ìã/ WU!Tðí\«0ï‚-kÅÛ­uUsÇ<ž¨ë·Š»`1^ÙÙu¦áïû[CT'óÒÉZ#%ž¼ÔÅÂ^Y:V,±ðÍõjHw3DÀQ~Æ>–0qh+޾ÇxbÀŒ~-,¡=åS“K?hR ,ýâEã„À×Ò%ös¹‡ää^™8ðgú‚À‘†Fñ‚ÀéÑ?7 ‚À!¡%« päóBÏ+ix† °ôNÇ A` ­,y8ÃscãKœdLŒëm‘ Xâ\ðð8;ì‰Å€#‰¶¢ã>\À°(0v—h`QàqòqSàqÐÜÇxÄ膄iÀB¢Àãb 'S`èˆù)0Ì©Žã‚^Ј(ð¸;[O¸T“x(*§)0.ñÅa‡(ð¸ÕEÞl˜§‹ A‘MБçÕ¿ Û È€±±Wˆãúà‚\É€ÇË ?fÀHól 8µá(0rFFšÄGŒÖšÓŽ0tè0b@Y—oè“g`”c^x<ŒÝ&< íPŒ€K àñR9mœÐŠ%FyÛ†€ñU@ÕbÀ£ðÎ3àñÐÃÆ m ÒÆ»æY³0Þ…$DÀã=jDÀD#Œ4Ä;"à¡l†/Ç$<Â"å# 0šS¯0ð ÄtÜKa €‘CÙ0î˜Æþ^i ÓºÌ€H_¬Uþ,fÀhàN$úë#ͳa ?”10Jxoè®o Œ{±±R ÃÈ;*q`¤™Ú|s`Öv ŽŸåY9py90Þô" 9ð( ]dŒšxŠ¯êº˜}Q0¿ŸP0Ò€B…‚‘fC2Æ(xèÜL‚ùAE‚QQÐŽPЋ$¨îh<*î’.¥%.¯!F[a{%ôk„.¬(0ëc Ú\Î ÑÇ™/!0K" ̱+ Ìþ* Œ1\7 ÌyB9ƒÄD1ªO¤!ºV¢Àü¢ÀìÒ¢À¬)0gQ`~R`GÂÀœ„žbÑ\ iˆ‹„¸”˜ùàݤÀì#¢À,Ž(0Óˆc)97 Ì6fÍE9Kˆs”‘³‹³-H‘Ç¢Àì¢ÀœAE‹¤kY…Û !Ðë¬!0_% Ì/. ÌÏ) ôpf1ƒà!pɘßáF>U«ªV A`¶º 0Ò`Uš{&4 Ð{C`4È[˜C\µ|Šw.¬}ƒÀ®‚@O³bÀ6Àý]1ª“Ÿiοr`çÎ-806;`+Û½s`›H¤ ìkJª;-„¬ tLv«S‘f] pÚºÀ8ôo`NêC«ƒ= tÖÐYè£y*c5Ä齕ÖéHè`r© ,ll+cáâQ耯Ö:©u_i] „¦.°½èóÖ¦ÎκÀØDÕuáÕŠwI¨xÖ© ¼» ”Ê@µ2Ð ‚aŠ=©_N•©´ÒÑê@E–Mu Â³‰­TÀ¾T*Öñ¢4ö#v9ÁTê@…Ù5.JD‚à4q…rMêÀË`euàÃÖÆ~Œ8FŒö¹V\ôƒAGN †®àouà‚€±TZñHLE®Õ:üOu JBAG]Ô0ïørvi¼.a²Õ±×ùXP0šX0µ°ÖŽÏHŠ“6P‡]bÁè)àŸTRã’ê@«úÈ‚ÓÒÔiu 0Õ—È,è@Ê©´ÖÓúÀ0¥l‘Ñ:õnvë]E ƒŽI›ú@ë=­L ap)¡õÖ+RØè;jôCÒ^V‹>mctWO}`˜/#éi`t¬êÔ6úÚ§F°Ò’—§¬¬\­„ßÈBƒ1‚±Z)¨z§R°ñ°Ì41¯±S¶V°ÁN>•‚1µノœJA}+]<Á Ì. ¦Ô †Ù1^MŒŽÔñ”t‚#Í»±àòYÐw>¤ZPÃ!Õ‚ÎG,q‰¯]-LÈGjAÙ-c^êTR/È[ ¬tÛˆ—7Q-è¶Z°ÑmÚ8ab©n´ZPªd«­±ZP1ÂÔÌ‘•Ÿ´‚þxV z8X-Øaº”ZA-ÆAï3­ t.ÂÁXšXâ`X˜àS ms Pè¨Åƒ6S1^/5zJµà(0•‰R ¦äIc>õÊØ†×yš£xx¨hq½¥à“Z°Ó%5Õ‚)i²µ¹÷Ö ö.Ø“Z°‹å­t‰­ì¯øïÚ×ÖT f6T vúƒ¥^P_×jAÙÞ¤Z°ß_Õ‚ùj©³ R 櫤Ô(©”åOªý.«µÍHµ {ºÕ‚.Õ‚ÚU¤Z0%T vF¢Hµ`¾ŠjÁð"ÞÕ‚Yb©ý}­ÌòI-Ø©1Jµ Klµ Ÿ²^0n>Gš+×ÖÚ;雌ïS/H+žÔ Ê'õ‚6þH½ ”j©ôSÖ Ò·|Ó B-½`D¢‹«ÕÛ©¤ö3Õ‚Ê5Õ‚UŒhµ Ôª©t©eµa­ Œ`¬”íÒ¯„ªN¼Ž¯8Öí†áI,ŒÉ’Æ ­îxk#c´ºÁÖ :cMkPh,æ â€ƒ.¥9¨Ð„€¡—ÚPqmzн/P‘áÒT·Ô}`Úƒ>ô²I{ЗhiªÐÙiZèê–ö ïìFtüç´MI‘ñŠY èÀÝfÀ4UZu,´ÅK„2¸! BƒÔÃZ!`¾X¡³oÚˆr‘BØ 46ÂZot0c`šÿÚ T··™½ÛIƒP]ò—¨{ÍL€|¨àØiª€œiª‚&@…&MTàa„*Âm £ƒ&*ˆpÚƒê‚Ë@EƒNT Ä´UÆæ?Ýô™üwÒ*ÍA3ùO¡+χgVÆ&OIøP*â¥íA¬2p|àùÏƒÕæ º¡8ù/®õAñŸ-Émê©Ãü§›™“ÿú“¥.°Ó£8ùOw>'ÿé¢Û´]$<¶ô˜•¡rÿXð/ ØiüÉ%Šå¥&ÐväÖöÊ“Y°Ÿj˜ì7jø"T1èçªaU`e*öS Óô8¸-µ*°3Cªû%ÅŸT±—À»¤ Tk¦*°ñØ*UŽ€© Ô‰bªc³¸Y„fy¬ ì—ÔqRŽòT*¡ öþŽÆÐ…ÖºRÖv†ÿHM`l¢FšÀ~p‹bM`ëÖûQØnC­ Ìœ¥ l/ lM`p0õ~:\}m&Ê•ÕùXØè[ŸªÀ ¹Yu«;2SØy9šu±X‚í¤ ÌŒ© t´6ÐÏÚÀ~ÑÎÌÚ@wJ«åö‘úÀ”œ4²i2 &ÿ•QplúÀpÖ‡ÂüÇé%ñ/V=<$þK‰Ô±ŸÿXñ/“HÈáœÊ@7¨•‹¤¡œ¤ ¿]è¶²>0¶ã 6éÕ‹­¤[Mjã1¤6°Ëâ×ÚÀñî{×6†`Im 3–2УÎÊÀø(ÈXÊÀÆØ.© êIèáam ó‘6°1²gjÛM £#ÑÈS‹— 4ûÔ”žfŸZ¸löY¶8Í>¥í·Ý§&†4ü¬Œ “†Ÿ> ±áge¨•4ü”AJ~)ìmø© & ?i©‘vŸš¹ÒîSsPÚ}¦¦ ?CûM W¥Ð#ÁÞ#Õ¶-?ÓŠS–Ÿ´†IËO_Úò“³‹ ?Ë-×D~ÊJ) ?eÀ·~>›²Ï¶9iø)«©„=—φŸ~WZ~ÚbÓ–Ÿj.Þ¬jËO5 -?3-?¥Y·ég øl EÛOšì¦í§¬EÛOY»¥íç%(´í§í:eûi‹²´ý´}¨€/%¶ý”!¥OFÎ |ï%fðéú»ÅöÓõð±[,¦Ÿ¶Ùï9‰p籠qÏ=æ=WA¼ç7§å§ìÒòÓ6œâ½·,Å{‹'—V™•'ï¹ÀÂ=›¼÷\ãž+eÜ{»L¸çâ÷ò)[~ª€Æ=Ù·‰öÜ•L{ù&Ò^¾H´—Ñž›Ø´g 8ÓžÓ˜öÞrÖŸÏ#MYÊj<­?Ý€¶þÌœeý™o—õ§ {nv[ÊØWÔȧŠøòŸ›KÄçîfäÓœ™È÷ðfŽD¾‡÷ª&òy 2ò¹06ÿt!ßKË­D>×ÉÈç:¤ý§æ?#ßûÄ®\\ÏÍ 0ßeäsE…|. ‘/3&òe!ŸG•‘ï¹ r«Ðnä{šøHÈgçP܉úü”©/ÎàÁbÂ>¹%÷Ýå‹èMKšÄ¾§I#(ìËâûÞSšEaßhvZ„’ú„:I}/Ãy’ú¤²Jê ï°úÒDTÐgÏCŸ»Ÿ¡ÏÅ5ôŵáxJÐËOÔQ1ñ”AU¨jGë%̘K~YówêÜ=­?m‘)DÓ}h´Yö-L(À®MõD0 J¼X^»`½Â)O#BʱÑ`Ødb›*ëOœ‰cý[óå4þŒãoHDƒý zÆÖŸ¡LØ­?/FMëO¿ÜÖŸ·ÌgmýùÐÇÊÆŸ/5JãO¾Y–Ÿº†~±ü|õˆÃÀÈ8O–Ÿi¢)ËOW–ŸcmÞãÀ\쀋᧼¿ÒðSÞt†—;§áça¿A~Ú»Ïq`=I°3ôô†ÆI‚î2i÷){Í £k»O[HŠmž”Z?™I¤Ý§ I‚ÑzD¸% ¸fŸ÷ý(02‚I³O¼ZëÇÆóM²ú<iëÈY0°Õç{J HÌF—Õ§Ãüˆsôó#Øê3"Ú4Ê ˜ilõyÒèãU8¤ÆÞš²úo¿7­_HÚæ˜µ²Õ§Mš‚QBi—œeõ™‚`NcÁ¥Z²úT,(€   ‚i±f«O[Ý —L‚iÃf³OeÝ# ‚iÆf³Ï ´…}ÓzZ}ÚÉ¡`l$LÛ7q o˜O«OµAp‘ýÉmö92î zV f‰mö銋—4$Á n EÙ}f’ ­ì‚išg³O—F$˜‹ó ÛìÓ¯ ¦9¡Hн6Í>ó]$Á,QpÉFvŸn ¢ +%¼È!Á4& ¦ÄfŸœq6«OlÓ ‚7­¿ï[c¤öÓr‘j¿!é[4˜Å:“ ˜ÕL»ÏS}Á¥È¶û<Àf±ûÚìSmA³O›tÚìSv¡iö©GV³ÏkãÀÅXôÖÚ*ËK[}:›Åêóúbõi#ÏÅì³m˜#H˜Í—fŸ¶0%fÎâÀÌYèm‡90'3‚`VB ˜}– ˜#\’ØðSö«áçªjqÕT!̶ ®’îáZ7ÃÏüè"Áü|"A/‹á§Í1møÙ¿xf+“—Œß\^•s¢ fÍE‚K‰[óxm f+‹óKˆ³E‚Ù:"Á% Ip‘—w=¹¼î†ŸQ¯{ó\ÊC\ž" .iÈ‚Kš¾ª¸Òð3Ö>Ò¡ÖWuÁ`VA0¸¤! 拃YMÁàòÔ{yÈâC8’¯ª°Ä´ž÷nT[\Ù°F¦Àñ©¿ûSèï  u O[³NI–Œñcý3H·yYÏVDK2ɘ.ùô#\\ÖšR°ä‘2᯿w0ëWD;ü¦`ÖkØê7Ö ê¿oq‚Ÿýs¦íŽpýKIV¶8¬ìÏ;żn²·-òï—¾Í;÷-rÊ ÖÊi bÍœ2sZÓ8'‡°vNKkåäDÊiIãœÀÚ9-¬•“)§%srøjç´„¯VNN¤œ–4ÎÉÁ«Ó¼Z99‘rú®ãÖ v¼ÿ+¸þ ÓåOûøuvüé›Ce›1¿9Nö<~wp븼é»…ÿOƒ[GT¼Zýç1SüžàÖ#ù·‚[qfÝR˜Á­Ë¯·žWó¾3Lõ´ ^¦§hÙi‹ûhošÎ•|Þ6«`óãâŠÚi"Ä{’pý`_ìyçu‰×4÷{•OÜ{h¾j ¡iö­`¸õÛ`·\ èÓ|Ïäye÷4¿'8Ç5Q¶úžlS»âü'"VÌ3‰Ä:• µ\—Ïߌl6vA̾íÍmcø€ ÷ùÀ̵qÓÌs‡y£Ó<zÙ¬–òØ‘pžÌ+³¦Õ1ÍvpKQ_6Kó²iõ¯êÓƒ&½"æ¥ImÝPÍëvîÅJG·±ÌX±SŸ1¦Ê瓾SËkSÊr<$D)ÓžZÃÓ~6×Í/÷(ôã¸ñª8 Z}=æ†)3M-@Ê8(À»"lï+— ïŠ#ªö‘'ç%|Ó5é¹X­ Mß„ ÉyÃng¬sx{»N¸&9çvÍkùf>“’â"Áí‘çÆUNcOÁvì 0~·y]’ýbjÄå›v;7ް۹yëumí Ý݆dê1fùщ[\¤u¡ûM+ËÚ§µ¯Ø sÀ‘Pbɼ­~Ž´p¿^øhdšXù§eÙý‰$Ï1o Œ:¼TzhУöwž§‡ÐX'N`–¯« IÅX½áê:¾Û‹±À‹lHÒ²}­÷N»o˜·ˆ~?‹²~n«¨Í4´Ej.jœ$ÁÅßiœÝ¦ŠgÚGÒ¶èt67nS±u¤Eo›:[Z}Oèka)tÜ[Æõ¡Õ7í Z˜`vÚ1O…[‹—Þ4¤¯(`ìuÞeòk°¦žÆÃs~l:³Ò~w¶V ­kKrZ}Ó@¿…ËÌy®å‹éê]LzÛtÅ¡Aôü¼-æ‡þ …©Ðµ6Å´ý«i×ßÂG®±8ŠÓ ÍI+0ºÅ±@Ýš4Mζ´zyÂê›þc è]qFQ˜ßaâ[»æçn®këÅű[/èóÁå£ö›Åš·wƾkMãÊØ¾V­Ó^w4\Ý¢Ó\—ž>¡É—ÄxŽt¨#êߺÚxÇ ÔëéS, *à]¡ÞÍ#Ó ðnHh7(¼³í‹èn n$™tWâúî º+­^ÝåµI¢»›èNÞ«ódÑIˆweÞ6 zÞMIAà]‰^TW¼›¡ÚsÀ»™fz'ïJk X&¼†ÛÞÍ4}Å»U¼+­1ŸønM¾’—Ô ¼›a¯L¼›I°åÞ• ø º‚GÈ5én¦¸Àˆ »M2× Uº›/Âw!Ýe@qÑ]–—p·f¸+7ÀÂ]¤ùH²›`AvY#‚Ý’„`·Jvó=/( `7‹;gµ vógÁ#»ý ÈÅÚ³>²[“€ìÖ÷í–í¦üO´ËÈëB»% ÑnJ*AîÀ@ Z)íÖ4@»%g¢Ý*Ûm’ŠšùîfÀ3ánM¸[ó™pWZç^Kp7“^¾\¤ŸæØH/ë Ò‹|ÞUw·|¡Þ"!ê-o'êùc õ–‡€z)êe«õ–$D½üœB½l ¡^6 P/‹'ÔËF¨·¼œ¨·¬©^ +zœ¶k/tPž¿.!/NB^$€Å!ÏÏ“ñ–`¼¬oIÆË®IÆ‹5 ÊÇÉxÙòd¼å0^®•ñ–`¼%E¶rñ² ñrÙ&âe1ˆxùA‰xùÉû¾„ñ|©/—"^– „—Ÿ‹„úmÞRLÞRžSüJd餺1{nÐ% ùIcÔÕÅæ²®ºº¹=†îËTçÍyRm›ª;0g'Õ 9’êèôô}ª;éDcªÓõ¦‰uºm.±î¤Mb]J„ugýÜ©î¤{bR]µBQÝIʤºÝ sÉDHw®Jºy÷)T<—yŠçNº%Ï©°Æ9S—qÎÔEœsásç+åŸp.Ú ˆ%œSû›æNz´$ÍÖMsfsÓÜ ·„¹“^L sN"–s.f9ÕÚ(§ËeåâÎÂQÎ(wÒ-QÎÝÒ(Ç8o ʵ/˜‰Â‰rD0`&bËs!O`æfòª 0shÉ3yU˜£7hŠ˜É£²ÀL• f<M®L0—|„rs$Ê-.;¨9NL+Žë¼-%9NY$ÇuÞ“×›PJ×ç`sœ`9A®Wa›@.ÓäxóÂqZ¥Ìq÷ %Çù!aœfÅÄ8ayb\¿wÝ"ÆõÉ×yÅObœí:ã´Úã20N1vãòUÂ8AxbÜ"!Æu\gg Ng qætC\¨×E‚¸”âl|9Ù¿n º,™NçIp*Y¯«I€Ë\p~Hü–ùšßÀ8ùMß,¾™&ßxœ±à[Ãâø–iŒoNc|sã›+ñ 7=$½n?Ñ6 ºñfŽÝxÓÅ‚n*[¢›%F7mQÝ ·å‹Ìmª ¹Í{§ä68¹Íù˜Ûœ¸-vüS`nk0eOnÓ3Émª¶¹M­Ü¶Ú[.™&´9WC›%†6Õ(¡ÍùÚ,1´©‡'´¹x¦6}”Ä6@’™­Ù´R̦Â$³)“d6&™mÕÌåI`³ÄÀ¦â'°!ÑšÇkÒšcÒ;»`ÍGQ†556iMU­å¢55ˆiÍ9×, ®©¦5ÕU´¦B°æßõÝÞHVó9aÍ­ñ}‚µ˜«N‚5}BÓšJdZSÏ6­ùÒš[_´æbÖô-LkjÓš_*Zó#¢5QŽhM cZS©LkˆÖ؆5ý«éd5}±šÓÕòB5% ªy‰0ª©]ŒjÕ”IM;o„‚Ízß¼J#Ù¹ÒÙŒ††½©éLQý’α4éL·'-Й.çM:SSLÆä3]`Ÿˆ¦¹‰h ˜”¦sIiŠÏ›”¦ sIi#Ÿku•‹$°^3¦)ÒŸ1Í¥1¦¹4Æ4…LLS@Ãä´ÌXœ¦Ð„Éiо—œ–ï¨)”c‚Zæ,RsÎ&5EbOTSËD5—Ù¨—2-Z·L T‹µ¢š[˨æïbTS G;ËEð¿Í¢2ãS&«)°i²ššYM!“Õ1›Õ¾0Ymlúªv[ÞeV’™X- ¦?VT{ f{ËÏæ*yœ‹5eÆ´«\4Dé*wWñ¨\åT’t•‹Ë‰aÏ(W9)ùÓUîáÅ é+‡UÀŽrCLÕ™åžCJ0yÊ-zÊåSò”»yíkzÊŵN«ÂmHNºsØSn®êÿ¼8Ê]¼´×ŽrJa?¹p^8-cb¦ŸÜxóµZRÎ8tp“Ÿœ‚"¥£ÜÍXƒé(—ùÈQ.Ÿ’£Ü}ðxÑŽr®¹N?9WAnr~Ænr7o-M?9…hJ?9åk79W nr.¿Ýäü½äüÕì%çr’3@¡i%ä®B·“\xB…''¹«Ù%ŽNr±³Y5mK;ÉÝŒ¨˜Nr# Ž#ì$'C–t’s­í$7Rv’ËwÉIÎU·“ÜÍÈ‹é$ç '9wF{ɹ¯ÉKÎma/¹ð$ìÈKn´ Udò’sÆö’s­ì%çNb/91»É¹;ÚMŽ%9÷ ûȹAí#—/’\Üñ»êÙ¦Þ‹ö‘s£ËGÎíi9u.¹Èù{ÛEÎ/²‹œÛÁ.r®£]äò)¹È¹=í"çác9÷H»ÈÅ=}T«ÑEΟ×.rYf¹È¹âv‘óSv‘SÍí!ç6¶‡œ h¹LC9O—ö=¾¬Š¶µ4òs/¶‡\ÜŒGIóx½VEÛú]äÜÙä"ç®9E–±‹œs‹œ¡\äî[¸G9÷*¹È¹%å"woþqžåç±ÿ¸|#ýãòÓ?޹Ñ;îºhØ/ï8üY®q® \ã\A¹ÆùírK]ã܈rsw‚kœû­\ã\C¹Æ¹ÕåcQ,ºÆ¹È5Γ¨\ãüýå—ºÆùµró “kœ ׸̮qþrrsÿ–kZW~qžåwv‘œB©^rŒsë:ÚSüŽpΩoƒ"y%º bB¢óu‡&º¡¢‹½©O¡Ob[¶ÝùTî÷úD1`3ôIìî>è¥!Ÿ¼Œ¢À'ŸÄ‘OôbG>Q®øä¥ZÁOtM>Ñ AøÄ1V÷DW½fÜ“±å í£ãž‘“€áoÿyº¸ú It¼`0yÎž×æ9GBÎÙ«ß8gçkãœ=äsöw7ÏUúÝ&Ðél-Î9èŠÂ@§k­’èHD— Dtá=$ºJå$:á%Ò•Î##]EHWºªé =¦ét‹^"îÓJ¤ó»Œtºi/‘.Óé"Ô÷÷Dˆ‰t:ÏL¤ÓU‰ta¤+<™aOô[@—ž’n¯Ìsåeø!ó\\6·G=„÷1ÏéL4yNo2ι=sºM+qÎßD§[°’èÜ&:¿J@çZèÜœ:7¹€Îo2ÐùˉèÊÍ#.ÏJ¢Óqv]f,¢s0ѹýLt™FD—oÑåÛEtnR]æ#¢óS&:g»º‘ÎßÜHç!c¤Ë|ˆtî:FºØñ ‰n<´jâ–/c¢ÓÙj]f,¢óÀÑùM":_#¢Ó%{&:ݨg¢s¿ѹ/ŠèÜþ"ºÌ”Pç–ÔùêÔ™Åtî„`ºLM¬Só‰ê<Ìv }$®óç×yÄ‹ëTaß)¬Ó¹;±nÔñÞ°Î}EXç2êÜn¢ºêüuDu®—¨ÎˆêÜö¢:wGQû¨ÎÕ¬ÛHu™ƒ.(T¿Ø©ùÅu^YÄuªº°Îê4ª—¸Ì½Œò¬@ÇÞá†3£Jâ8Ëß}†)ø÷?—ù<æ¦oÍÚ’Œ„,ãžúgÆB>¸~æÚò‘dÍ2çßK>ckµ•†¿—<¦D9àÇß;&s|…UÌ·B2ÿj˜åòüöÌ¥ý¡˜Ì?ë=Šú~¬±j¿v«Ùi.øÕf*æ”Ñ–™ÓmY9e"å´¦RN޶¬œ–hËÎɉœÓ’J99Ú²rZ¢-;''rNK*åähËÊi‰¶ìœœÈ9-©”“£-+§%Ú²sr"çôb2÷v@ß É\~)$óÏúÌwB2/Ý×Ì¿–ß×Þþ½tï/ö韇dþ 3åOÛÔ÷³yñ§o”uªüÎ0ÙóøÝ!™Ãýà*ߎÈ<*ÿ×üç?9þñ¯EdÞ‚%ÿ½#2—o½ä_þ`Dæ^^:°O|ÏÉ©ÇÎâšËUé‹Mj/wŽÒX{¬¾X ¥ªí¥ãÆQm†€ 4±×ƒ+4mGz=±BË„µ×k.ÑgÜ€Ò!hŠËüÌßóöÁDøñïy8†Ñ÷Ì‹DΪ Þ6o!WCP²²Ù­xÏs½óÄn¦×ð!ÄIÕ<’‚6KurÎê5,€q3OUz;py·â÷Ñ/g¹ŸŽÝ!hˆï;fúÀçYìó†F}ìUnkÍÍM¤‡ËÓa¹ÇÝð}9äì#í^Bòv„HËױ̢غ˯GP²(v¡ãMosI΋µ{t‡(vììf} ¯¼F}üÄQp)€¥Ñ=æž×¯Ç¼tÍ‚Wz,ÁÜôž±-›ïèw+>gÕû37½Ñ8óp³÷÷Â1jcãôwîzãòöiIÒ{ìEQ“†u^ §5yÌ“O…£îa„¯´÷îaÕ=od¯0ÀóÈñÌ®ÁCrž³è•.A!Á°îq’kn}#ŸÙY†äÆ!p0 óyææ7ba_Lót\ö^ÐlC2ctÏ:Oå÷àÌõA¿¿ëÜûæù4ÔfCÐ ŠwûÕã#ƒS‘5c!Ì%MU(È8zzT¡Ò¦oHÆ"Á3B6E|rV¡0ÍÝÐÆ(ÿ9O¬m½Çï¾ôñ!)8oÍ—’6 ×`8ã“7Ž_|Ët^‹†ÁÏ~ O7°fHæl¾Œò<æ¥=è“…’©Bˆ©žw-b¨tIZöAÓÆ…$ü×3ÇŒSðh}zs…dBjT§ ®òªe_Tàª44¦Ÿ!iZ–²!ÁÑovÖ«³¸üÎ÷qa>yqŠ’>‹$ˆ*ÝgEüî{`Z[ëÜ×'›¦3Ÿ{ÞÇý¥¡÷SQ‡Ëi^Œ¾ER&¸FDn6è]0† ̆d**=òÆïöhŒªýüì[ÛÄE§Ï6”â¢Ó†ÀŽÞËà’k¬g©ţÚ8.:eù óy&ÄF>¨xÜsúnýæyMÿ` ÜrzÆ A½ñ^uqÞr'ò|¦5TÀ}/6Ç7f·ˆkNg/¯qËéµ(OBÒ4uszˆ[NO¦2›‹¥ôSC2µv£1n¦x°\ºÎqÇißæ¥¸ãô^Ô"ˆX0—ÂT¬˜ºC`H–̸É ÁkN}åX¢ÖjMÃeÞs) r‰›Ng T)C‚“"kö†äÆÒI[ê—*ÄE§¼¿àEâ¢Ó†sÀÇE§ú ç·B]jÜÛ*ľÿüÈ;†„ÚÔ¥Èqh=¸²JÒ¦VX¯œGŹ‘¯A’‹hæ[yt¤›z‡äÂ2š¥á=§K­â¢Ókë ¼étnžùÔ‹¥4Î[()ÍKÎõÚÚ&.:}—{H–S)O‡¤?šî9vã¦S^¸À1רR‡óOÃIRè«Ùg›tªþä gIÖ‡d.§Ž3?$—S‡ö>[Ûð¢ÓM‚å” N”¬Q’Æå”šÙ!éˆÔÓ‡Ëiœí!ã¸é ˆŸç­>Âïלž©Ì ÖRi>‡äæ¥ÜfÄ%§ÏÖ. UmCÒ0×Üœ6âŽÓ†æ=øêŠåty¨aEÕÍ!ÁŠ*ýïôW;tës^rêí×» ts}ìsÞrºN±>~®Ö g¬HŸÛŒó;ºHçV$æÔY‡›÷xŸ1Iád>‹ª¦±dèåêŸçAÓXœÉO .9ÑÊáó«kj\ºƒJŵ3ÆÓƒ\â–NZL‚Ó…õ!\qêh”ŽGq1F—}Éo ¼lŠ;§ªa9bºyÏ-(®=´$"Å•8FÆÖWÆèà7*b\i·^“âJœ4ƒe@q3tr!´! Y5ç]ˆBV…†À¸!à¹61nI>zïù‘1“‰q ™Wbˆ+€q3F±¨íøDˆß3Ü ïK —ñ~Ép†— —g'ÃeèU2Ü,Ó DH\F7&Ã9è0.+á>’—ÁÚHpßW œ9 .C“àfŠ@vøÙ‚›‚ ‚“qý”%n¨'Á­yL‚›) (ña\?¬$ÁÍ€À—aý*ÌÏpSXÀ­y"e%ràJL®/3ï)à6—H·¥9÷xœ¸¬.ß-€’nì›·I^øëè`¸™¯p²2À_¦˜7v‡á±1Ä_×î·¾ ·æ‚›ùÜ„¯IpkÎ ¸âP¶"¸-Í$¸õíçS–þ'ˆÛR”Cu(’´éµH&Åm’Iqù¹r[ÎäÖ§r%RäÒëÜ[ ·=síoÈmÏ<È©©A$·¶ Hn˧¼jáÆ4õÒWÐSíP ”¦Ápɧ¿[@rkïÉ­¹€ä6É$¹Å"¹µO€ä6ÉwÀåí“䶜˵BÒ¿¦©uÿÝà‘HšýüÒK@r9Q‰äæSÜ\䦄Ü:¢Arë»@rCr‰„@r[š÷T?a[Êmï.Eåã¼–[ë –[Û0·¶(`nÍ0·IÎóK_Í­%Í­mšÛ$ϹõÐÜÚÀ¹í™‰s›dâÜV( ×ÒLœÛr¦ nÖ 8WØ4·Nd ¹u"+ôÂÍ!šËy_8·¥y^MˆDwàÜúys¹ çÖ‰8·åŒ‹#Ö|&7KÌ{#zÓ¡O¥[n>S©«Í7U…ÊeèqáÜúîJ×ÜìJÀ¹-ÂåfÎçÖÏœÛ$uôÀ¹u2ÎmÏLœ[;pní8÷FärÑ覻<…›#–®Ô誛SpÎû"ÑÜ–ÍôLÏ*4ºë.…)íËghÕ#Q¯þŸä½Ë®öF²´w+öüÉbñpöÄ€ ô=xÔöÀ÷32#"³–¤n©½ øÇI«>¾E²X§§"s½?ôÙm×ÎÅ&fm—. Ð-%—ÖC‡o tý‘tËoèúÃ$Ð-×Ðõ '‰nùU]”ד薧 ¢ë›“$ºvMÝò÷Î¥Uõ’èÚdL¢[®ÑUÏÉŵ®9ïuÒ$Ñ-×\ÇúDºåšÛ1¯wBÞÃ'•2.M«å}õ|GGºÖêDºåšãøñÉt½fI–šþBèeqÝ{†iUWç ×E¯ˆ„«sŒ)Uò^-Ï=ËsCâ›ä9#å9tº¤°ƒ44±‘“ˆDuÎ (¥ÎA]JpKq'ðRœCªÉän‰s2þ•8‡:GBTˆs5 nç nç8º¡]ˆ¥ù5$ÎIÖ‘8gLâÞý¢wäƒó¬Mâœó,Jœó«J›«›„6§|žÖæd.mÎߣ´¹Û[tjs6c·6‡rv´[=jsÒ—K›ÓÓ”6'=¸´9„ãbÍ¡ÍÁxSJ\&"x´`ïYzD‰szM‹síØ’âœ»Å¹ÖçlnqN†mÖæ¶Ç4@mÎi+)Ïù³Zžó°*y®i~×£Çc£SŸë¯ú®á<%:%QµBçáe…®U|dÆÔº":»6H¡«‡£Bç ¥Vè¶jQ sµZ¡ó¨³BWç‚Rèð0S¡«7¢@‡{wÎIM-ÐÉÀúœ=!¬ÏÙÇÂúœý0¬ÏÙ£Âú~Å 2õ¹þ«Ôç<‡ZŸóäo}Îyî¨ÏÙŸÂúœ=5¬Ï9e©õ9§Ó´>×zõ9¬ÜüRŸk÷¢>§äu–眱Ôòœ3ZŸsžNêsv±>çtèì¡PÝ|¥á=\(_M#è¾M»¦ tm‚¢B×*¦B‡kØ)¨Ð9ó©:ÔüÓÅìÔTèH‘7é™1­Ç¥B‡[_é¢Ú»#ÝR’ ]/‘÷c™Œ ¢qP¡³Y¶:Œ¹«3]¥´Bך†×:Kt½$%ºzq*t¨F@Éø5ÕZTèœ›Ñ ^sJ‘Ûâ«ð&£õ0¸•ÊòfByÎæ÷%Ï)Pˆå9[kOKuÎ)1­Îµ¦¢:×>.Õ¹Ö0¡ÎµÆ¤:g£p«söö±:×îMu®ÕKuÎIB­ÎµŽEu®½Õ¹vw©sðË{Ÿ‹8×ZøQvKHŠsm`Pë“ê\{ÍG).=À¨ÎÙÐÜêœ÷°èÔ%¨Î9-®Õ¹vëP缋µ:×څꜭèKÃ?PÓKy® 8Êsv̲<×zå9”ÌsñÚß¶e0Iž«z%Ïy±”:W]Dê\¯æÜ4¾‹:W%u®¾Ô9ù–Y«ÖêÜLщâœ=,ÎUŸ‘8×îLqÎ3†´¹ún6‘vkJœÃ³¼,¡a5‡ò¿°lvû¦„ë\Ø1-+¯Ô&%É9®½$9Å “"çˆyRä\’œÃºI’s$PIreÎIIÁÈ®fYY©A$É¡/m¶¬¬$ ’ä~N’œ#×K’ƒ¡~¾™ÐM±fnÊ©bvób7°w \d7 7aŽAoïü“ìV5(n7¬tH\¡®ÏƤ*×ÙäKÊr(å–yÉš3e9‡²•,‡woc·ViÈr˜+Y®ì î÷H§KY®ž‚²œ#êJ–sÖÉr­ e9‡Ê•.×n›º\ûIêr‹›ºÞôìº\{ÎÔå׺œƒ³[—Sd]Ër®Å²œodY®ý(U9·©U9?½U9¼1­Ì¶ J{kÿLU®ÿ†ªœ^ÙªœÿZ•Sèg‹r-%ÊÕ­%ʵkR”óH.Q®nEQ®×“1}ý åÜýJ”k¿¡(×J(ʵ;¥(ç~mQγD‰rþ Òä@€$¨½§*MV(e\ÙoLMÎA'­É9WEirnqIrÕÑ$É)RIríJrïù+AŠ\¼³ß†z\kéqU©ô¸ú°Ôãœz©ô¸×±ÒãZ õ¸VB=î±!*õ8G -=î)l«¨Ð%Æ)f‰q Di1®µœÄ¸ªGbœr>YŒsèÏãêCJŒSÜÌãZ ŸWV¿©ÅÕR‹sëÒâÛÈR‹sªœÒâÛ5K‹«¦W,-Î#)îµ=±¤8-…%Åi §çõ·¤¸V2×`Ö%ÅÕkJŠkL)NQFKŠk¯ Ô%—öÁ”â™RZ†ÛbJqÚs”§€¨VâÚ³H‰«w¢׺½”¸j=*qýW×­7à­(ÄUç“WMs-Áq-ĵ–W7¢ç}’…8§*!®z„¸º·„8?0u8ï…J‡«¡,®Ú&u¸zIêp­_I‡kµP‡«^#®¾?u8MOÅÊå"®ª•WoM]†äT!sUÍ\{´D¸ö$áÚÓ*l®MÅ%ÂÕò ®æ'ŠpÕà᪀\õ3ipõÙ¤ÁUN ®*¡WŸD›’ú›ÃF—þVQú›2‘•þVíBý­Ý™ò›_™ò›WËooäîµsX~Ó.¿ä7$Ëon(ËoûVߪ€â››Òâ›g‰o5ÿR|«J”Û™ÁJ{sï°ö¦v±ôæAcé 01Ü«M ÛŽÒ›Ÿ÷w"-Órä7ŸZÅt£Ä&sKl Gl‰MZ—¶TŠ-°Y‡’ÀÆ3`ëkQ LÔ×t¤i}­ ¨¯éÔØÛ#ÁØtòoͲŸ6‘ l²¼¥½”cK`“á¢(Í’¶CÆ”¤4½jBÚsÊÛM}BÚ#k? lc .ˆÖÚ$bMßÉúšB\”ÀÖ‡›Â"Kak¯D…M=Ú›{‘¶s—#6n lþ”Ø”¥6…Gÿ á•ËRòÆ»vŒ›ÔbãôD–ÛðâÝ[óü›r[Ú^6¹ ×8îBðŸ½{À½ó^@. ’%·ÍKqI(·aål ÷ …! ¹íR¼Ém×”>G¹m¾Â4Êm×õkw€{/–§î‡+ò©è‡¶ 㾿é&Ÿ.píÏtsÊÛtì´‹Ì3Ce–•ò¸çkKm»/QÕ¶[!H¤¶ÝŠ9"µ VyÕ¶ë’cÕ6%R¦Úv3F„Õ6‡ZlC Õ$?Šm:´ØVÛ”ìÏb[Ý“bЬµùoJm:K²Ô¦soJm=æ-µéÅR›ž¡¤¶Û±$µ)ñqim£aHkSÖôÒÚê Kb[pKlk%ÛÚ½®ÞŠ%¶•¬#±­Ý›b[«…b[]#µM9¾Kmk%TÛ”¿¹Ô6Ìù«ÚÖ~EµMù¬¥¶µ¿©¶U«KmkÏGµ­ÚXj›O¿¬¶)Ãa©mõæRÛªfÉmuMÊmõ$·õ’gyGÉmí Êm÷¶¢Ür õ¶vgêmíêmõ–ÒÛª%$¸Uû¥âVõJr»ÓE’[Õ+É­ÞJ’[=$·º·$7™(”äÖJ$¹ù‹[rs Knî[©ºµßHu«+¨ºµ;Qu«©nLÐ^¢[U,Ñ­ºD·ÇQ$ºÕ0“èö8¶ŠD·ºÕìÙÌKtk·–è6~•–ð¦knõ#inº$·º“$·:U—æÖ®¡æVíiÍ­®9מ&Í­Fš[µ¸4·z`knU¯4·º†š[5°57×,ÍíªÈ$Û³¼E·±’\k,‹njriní7ÔÜê7”Üêµ%¹ÕÐäVõRrSÒÖ’ÜG¿¢äæv±äæIr«Z,¹¹KnCljÉÍV’Ü0ˆÈW”Üži+L%¦¬»Sskw§æÖj¾þڒܪe$¹µQró¤¸Õ;YqóóZt󨹵K¤¹U5Ò܃Ȣ[ýj®Í)Ñ­^Z¢[5ŒE·º†¢[½¥D·VóûsI•êV¿’ìV5Kvó‹[usÁXßZª[«Uª[Õ*áí•»…7[Yxs[Ixk×Pxk×Pys¡òæßXyóóYyó„`å­ÕBå­ÕCåÍ÷.å­J$½Õ¯¨½µ»K{«{Q{ó%ímúo‰oU/Å·º·Ä7L«ouo©ouo©o­ªoê7-®ò¾ßO¼`òGîŒ*°2K(ùÄKtÁ¿Zù8"Јkæß-”q”(tiþÑB!Èó,5¨¤×‘e®…¶zÆžÓm{G•´zX¦zôçuhåýØcÿ{¡•ŸÿÏC+ÿNØñ¿û/Kpå]+ú͵-íﮫNκ–ðʬ«]ÅºÖ Ì¬«…Nf]=À²êª«T׆™uµàɬ«‡XV]u•êZ1³®>™uõ ˪«®R]K(fÖÕ(³®fYuÕUªëß³¼Gü¼ã¿sœå?3sþ} 3OþýwÎ2wþÁ¨Ykù˱–¿ÑFÿ'¶ü´`Ëÿù‚-mÌ©´ÈkCÆ€Q¢¦Þ7_d”9`Ä’'§Ï'²cfZ3ĉìbåQê3âDöRÒöçŒ#ÙódŒ¯dfö±xH‹`_7®‘CÓþ\ Ü>)íOZ ÝÃkž8ç¹ùš´4˜§bPîRòLÄæÌß¼ii™Y²`…¨F“¥7- †%åàý=BáœßNˆ-ó¦¥Áüš5-ªö÷ …s¾çµß5×vËg§¯W–ИÇ«ß+\‡¤‡g›3k>U‚çûP‡Gòñ³„Î*°<ú®¹vénðÕ«z_IHœ¸wúñ[Zàš›¿:Bâ¼¾>‘ÊÔ±¥©’¤Ös„Ô’×d“ÛK‰:RMúîôP,9¶45@²™M%¡q^ÛdûPßñžß6Nõ>¡qNØíYòÆ€Ì'~C㜭¥øHã3ì7{ÀkÖ EYžtjŸù• Ú¡ˆÄÇ>BâDÄ4þ?ö´5À¹@šnŽ×LʫǞ¶H¦ÈÏ€e¯p(0é±§­î•j‚óâ†B~%! »Ý|â74N<?ÑÖèÇ/K¾9°ŽïïÎ'²:åGhœç3õÞÇóD"’‡%¡qžsÓ›ghœ8ja§8fhœ'ö~,¹BãDv(Vœ¶ç-—å“>Ã-ÿéãHkƒóVŒ—ã@Ú£ó–ÿô÷wØœ·\¹±]ù Gâ1ÒÖ%KŽ9û5ik€×L«cŒÐ9ç76^Áo$ÊIéÈiîkÒ‹šÕW:gÿUhßž|ñqŸÙûNVò„Î9¿i‡_w<¡sί­ØÛFÚÌ}S×?·:'â»gAšàóî*yò u‰3m ÐE9¦0 ã Ù€ç¹çÌÊ3K6Þ:m kò7WHx˜Œ\tœikÐë¹CêÄÓð뢗=Ùæi»q`F +fÉ1·:q˜ T€^ò0éW²‡Ôyâ¼) |îKn؆ÛìëË1ÓÔGŽi } wi¬J²æ8fڜ߇˕ë@îRÔ|PK<˜ºôÇ^àPä܃¹KÏo]|Xòæù¸~åÒÔ|£ iØ-ï‹Ô¥qÁ¦N…Ü¥xþo*ã;"w)ž£;[¹KñüÛ®ž†Ü¥c½æÌUu?5^3WUä…â¯ÒÒ½éä5w¬ª½ž4687¦ÙýJž;[JÏ—¶çþê wé›3Bž L_Š{§Í!´? ó—"§)$0wØØžÈ_z`˱i½3éÊ€gQ„$µä2{ÜL ³3;2JÞåî4®ÅWàP¹ÓºöŒÓÂ(HóZtŽƒ; lÇ·ëàœñ¤¹Áù¸<°8ž´±m?in€¦a=OZÙ¶ÉKñ7GÊ“V¶h*NïÌ^zFæ²,ˆ%gú\ˆŸ´6h­ù¤©m˜´µÅ­8Y>il{†Šil‹÷N  ãMk[t€<>Þ4·Eê¿Üý|%O68{ý›·­eÞ46@×ËMßñ¦Õ-„ Ü9J«Ú4»mMõ¦±Aí&7MoëË1s逋”¶·¨†—ÆhΜ3ÆãÛs¿(mã@–MËØÒþ-•±±¥nŒ±¥nµøØÒ72)òNiƒë[Úàž™63Kr=õ [Zᢅsõ0+dÙYÏsô!8ÂлÓ±¥%îä5ÌZŠÑ”cO[\÷´Á¬¥íaö4ÅÅç&zìãÔ7H¼{šâ¢êWiŠ‹.‘;‹±§)nuó±_çzEšâ¶ï²§).²W&¦Œ=Mq1+^“¦¸íÅ‘¶ôh³ý8Ò·¦á¬¥88yµ#Mq«ÇŽÈZÚZøHC\ ¹Üwæ-õÖhi‰ëÞéã’}ç¶liˆËô›ÿh‡,p*–…ÊŸ Ðlò—ms9¨ºló0&ïcÏu_‹éFò»pÚN‡þD¿ ‰öxèw“;Ñï°&»$ú}¿ºu0œè÷ýjúi®<¾½óÚ%œ ÿMò»£OÓ6AÙƒ’üÂ8e£hšpmôIò»˜Bë&¿^I’_ÖˆüÂLF w¦ *ë‘_YNˆüÊpEäW–+"¿°¸!ƒülN#ð³ã¾¸æ1‡m4J±‹ /¬]^4J¸EÈ„¾°™áÒ²Ñ(áRÆ B_;™è³™Ž˜/ªå~£M‚LZÄ|M8&ó]eåAæ»Ê‰‡Ì×$)2_©„¾þx }a #\;¶Å¸%¡où{ЖÈÏ·Ë*ÁïÐWF‚¾þæ }ËÓÐ*AD‚¾2Öô5[B_o‹Cv ¾Ð×?fB_™& ú¢µH1 }ý‰úÊÕŽÌ×?L2_3‰ ó•” ¯ ΄¾rû$ó-?zõd“à['ó5]Ì×,6È|kÉÛ­Ÿ„|ýó&òõÏ’È× ˆ|ÍðƒÈ·Üê^ÌqÈ|½ó%óõÏ=h•PÝ/™¯=ð)«÷¾d¾~볬ÞÎ|Måæk–d¾þJ§¬$´’ùúw9e•P×ÜÏêIIækÂ/™¯Y%ùšàMæëM‘Ì×û où{ü°1"ôõçKèk– „¾&ýú–kd˜àÞ–Ø·Ü‹– í‰ßmµ¾ ÷õ¶÷5á’àWv侫Œ­È}KÉ8Wãr_ñä¾þRÉ}ýÅ/&(‘¹¯i­ä¾¦â÷õ®t•e_2¹¯7Ö]¦ ¼7õÉv§[¶ R‡É}ýüút˜à×»Å=meÄ›3ô…ò¿&ìüúw¹þæ2*Žk‘üzÉ#Ó×üÐ(×Â4ɯ7àC³Üzñg\k½4˵/=Éo¹Ms«÷=—Gb'¿þZçö’gµ® úõ’—ºö`'ú•m¢_ü&7QD¿~§·lT/ u«_¿§V./Mu«q^Ù&(Ù¯ÎW~ÁjŠW±qêV2N8MJa¯Ûÿ¾5Mv[ mvÝo­±í ­)HmÇCúkÃŒôך‚ô×úIÐßUõ¤¿å‰i¿ëCú+[Â_ÿQÒ_û.¤¿6Oþúkî§ýûR¤ÌwÝ8»Ìw«äZâöþúKî÷[#ÒßrÌwý4Iýi™ïºAÿªßþZÛþú‡;dºë¶Jø[Jh¼ëyWí­ïÊ·]ЍŸî/„rÞØù¯&0¸:¶ „©ýµðlÔþÊ]Tâ_ùâIü+ŸC‰-¼Å?X ={Ü4ŠýièbüMçû"þÙùNÚŸÃf¦ô³·`s •öW±"¥ý•[§´¿^B/c$(b=©ý•ƒ™´?ØNICLí¯üþ¤ýUBi×1µ¿~§‡1èR*é—p&¥ôç¬ò–þªIåŒ'é·>Å|éå&—ôW/•Ò_ˆßæÐ7à Mé¯?ßõ,šRþÊASÊ_»$…¿r•ð×Þ‰Ê_¹%Jù+G;)õRùëW :7êSJùëwJå¯\Фü•£ª”?÷F å>*á7?$Þ«g „?41Y÷›±?Kø›ÇêþpknÛ(üáñÈÐþʇOÂ_9¢Iøë×L:7Ê=LÂ_kP*å&åõ¬Ê_k‹PþÊMÊú“`m»ä?Ê]•¿jb ­#Qø+¯N ­çSø³›™t¿šÅ¤ûÙÁM²_ë%¡û•ï¢t¿r“îWÞkÒýÊëXº_»æ”±üï$ü•C®„¿ö¡(üõšÓÉØ Lá¯ÿFNÆr‹“ðW^þàysSæ»CTÏ÷ØÇqã5ïP ÏEøƒ/"g åÐ*á¯|tSù+_`)å2(å¯ß霫Ÿ¦”¿öTþœªÀÒ_¯9µ¿òô•öן祓c½ýŒ«uBükmLõ¯ÕKõ®Ýo§À¥$Õ?ôéx©þa7ùv l.âRÿÚóQý+ŸP©K ]ëîÏzéi ½•–ê_»†ê_/Iõ¯=1Õ¿ö|Tÿð+saŽhe}·ügPɨøè¸Ü*|2áa¹ÈmPÝÊ_QÃð:2ÖË;õâÔÿÊñYú_k>êíãQÿk÷ ý]kÕÿZ7yän\wb¤¯'}¹×ó1ÖNµÀÖZ[ëP,×f)€íÃPl8ÀöÞTÛ{Sì¿aÜz>J€ýÞŒ¼sJb§ØoÅà;½äV/á’C °¿ŽÝ\©úF’ëY$Ö$V/‘ØK…Çï- °¾¦4À^3ñ¸—HD@juÔ{=ÏñãïW-|t lýF îM´¡ˆo'4Û_ VþˆáxÚ¸Q®×¤Øš‚`/a8žzñÐÛS¬/' °?Ãñœ?5Àö+j€­q(¶¦ Þ§‹Øj°¦‰€í (¢Þšáx¾JHÞ2æn·f8žjP™€×̆ ºÌ>1bî.þa8PÇÓɆ£¢¥öç3fk>ζöw—™%µ?k2ÖþìëjíϧTÖþÊEÚ_»;Å¿ ë&ñχéÿ$3Pûóñ¬µ¿z‰õRÿ¬Xü+½MÚŸ9JnM)­Z)õ0Rþ$¥Xù³jCåϧï–þ¬”ögAÆòŸÄ«u‰\’K^+õïêÜ×·­þ•”w®*‰å?ßúÕ?K RÿJ&‘ú×J¤þÕ¯¤þYó²úWêÕ?}¸ÿJn;žõ'ÿÜVÿ~(¥(JùãÇ/áO­`ÝÏW”ì÷CõsE¿jý£œ‘I€ûÖoÒ$¿g•ü°úóI~% Jòs Hók%s(Ð4¿ÃhIͯɋÒü¦vÓMô“Lù?þ~H’ýZ E?Ti~MT;~Œ¾ý|ˆüOD¿º†¢_= D¿vÍ}.‡ÞýÜ4ýê7ý¦L,úù«~× |Ë5Týª‰¥úµ’sïó±U¿èRýJY·êW%·Õ÷W:àóCÝ–êWš¸T?O·VýlQª_]CÕ.%?û[Zò«Kòk%”üê%%ùÕ Hò«Ç•äW%ÉÚȈ’üêW”üzÉ­&Ë…äWE’_ÝIš%Éd‡—RýŠš_«—š_ÙlHók×Pó«¶æ×j¦æ×Kr)½lÕžš_uYi~Õ6ÒüêÞÒüêù¤ùµ_Qó«{Kók×PósXk~­fÅQu§•è×ê¹~<E¿vE¿ö4ýjf“èWm!ѯ& ‰~Õêýêîýê^)úÕ;Iôkw¢èW=G¢_õ‰~­^ª~íÞTýÚóQõk%ŠÊsêÜGª_=¡U?·Nª~õÄRýZ U¿º“T¿úVýêN ÐS%Týê=¥úµšå‘ìÖ‘ìמ˜²ŸEÙÏw²ì‡,e«ìç'¶ìç/cÙÏw²ìç¶°ì×J$ûÕÓ(`OÝëòÚª{Qök¿z޵^Ê~í7 Û³[‹£ìçµîWõZ÷«ê~õ|ÒýZ u?…‘*ݯZGº_=sê~UÖýêËH÷s϶î×Þº_=±t¿º“t¿jé~î9þê‰Sù«·”òWÏ'å¯]£°=u •¿V/•¿VBåOé߉$m…ï8›ª)|_73YåÙŸˆ;>8l‹wÌz÷Îyá» õ®ÜûH&rïeMJ÷>p«þÒaXÇ’{ßp9*|¸f“ —ŽˆÃkRâ;Oe{Kw"6¥Äw~ ‰©.ý¾Íƒ¨.%>Dº™4³L‰fç”-_Y/Ëw'ýZ ­ 7j]’øš_#%>ÜkHÐÛåK!7ÁûMƒaáaJ|ç¸}Ej|ÍŸ…_5–4>|ªUãƒA3OJÅz—ýÜÄzeì$Ö+ëd=›˜õœjÀßvb$ñ}ä"›M²žrë9׋YÏiMÌzÎcÖSö£Þ#9/—¥ºO‚^Õ)Ðsøù=ð‰õnÞ¬WV8‚½j(Ñ^Y÷÷ÊÌE¼W¶;¶òô5¾2èJâ«ôÇÈW ½ºõŠ|H,¶šyÖÖIȽQz^.KÓNO6óÜù¹E|P?YBâSh@„C>‰Ï•øê>¾ú‘ˆož¿Ò:“À×~DàÃæ—%>e®.à›vÚ#ïµjÈ{õÉ{¶ 7ïA%”«_.IÝVÞs4JóTÖ.ð]ˆ8cÉ/—¤<´‹òž¸ïµ’s_žF¼ç—îµ[÷Z qzEÜ›'œhÊìjã Ò¢å%ioÚíU´W¿íÕ'ðµZ| {YÀѲË{ñ«Ñ彿`೿/v"Q@Þƒnȇ!ïµòÞi`ñ^½Bò^=žx¯O¼WŸ[¼W%Þk%ä=D¨å¯È{8~ç5ä½zbñ^»;y¯šB¼×žçY?xOÁF‹÷êñÞiWYñTu^CÞÃܺÚxö’ϧ½Å{§½ðoÕ^®Â½^‚ÇÃrÉj‰{í âž{€hÏ>&¦=…a-Ú;íÝ+Ú«÷íAµ^MßžE{ Ï·i2ù úëפ…'ÖF¹¦…ç3ì—AÏèt2ú ;”gØý„&žúMÓ-šx>g‘Zšx~ÝBk}˜xÞ_£™M<Ñ™¹°ÓÄ«97"4ñÄóqa¢‰'žFf iâùœJÓ*Ïþ4iãù »#ÐÆó™ŽzBOD&ç5´ñ|¾MŸ9lëÛ¥¾~gv"ƒhØÙÂ`Ѱ³õVvö_¥a'Þà\»L¬á,IËÎzË0ìl}ˆ†ø §dvâš{1ìœ5Ñ`,¨Ö‰v(K\ô¡C²^¬§¨fë‚[ñD(ì:Ûh×Ù“v­­h׉ÁE9Žvó›ùd/švõ¡hÖ‰ø`Û×_[Æ iÖÙ&šu¢ÄFœ+­út˜u¶g4ëD í3C¥Ý²° Uç%(ž?C¥Ñª-¡(3iÖ‰‡9:øEÛ(bLšu¢%g&Í:ÛkÒ¬sn»9 fõ4²ëÄäM—vÕ²ëį.{yó+Ü6M»N„r;»Î î&»Îê²ëÄܦ 1i×éî'³ÎzÍ4묈u2ë¬ï$³Nüf[B»Tˬ£¸-iÖ‰×|ºw_MÚuV7–]'báí]åëOL»ÎÖa׉ßpi×Y±ûd׉|¼4ëD¿¦YgMZ2ëlß—fx`9Ô¥Yg;™uN÷J³Îš&dÖ‰^¬:ñ0ìX4ëlG³NŒÃ{1묮/³NLbqnØãU÷º­`¨“)*^5K*^õþHñªyÁ¿¯ú·u»¤Ç‰n7¨Kz¼éóßåªÇ%­–©ýÙëAz¥^KþÝë@‰kˆ?Úïç–6œ­­TÒê`™jÑŸ½žõ³ôÕëiß¡}–ÿòøÙ؇~ðµÐFÌkØõ\Ïo‚WPìñ`ýq°íï‚o‰¸~ŽøG óŸ…àþKû÷zÔxÚ7ù£öeú’%âvÖÕ£dg]K”ì©•¾j*­e¸ÍºZ”lÖÕ£d«®ºJu-·YW‹’ͺz”lÕUW©®%â6ëjQ²YW’­ºê*ÕµDÜf]-J6ëê±´UW]¥ºþXÚãŽpYÿciÿ‰Yý·“è:‡ÿýŸLÅuÉÎJÿ/biãÓïÏÿD±´ÿó÷nòŸÿn,ío€Äé2Îß¶c™®¤2·28ìEŒ5L'¹Y€Jˆ8l·ó$ ÀzòÜìûäÄ«¯$OÂ? á{îynv}›ØÉzžàvLÒƒ%o€;ŽšS£ùJò$üR¬âóØâÌN[ôóØó(<3Ïãà9¸¼ ¾’Àö ß‚?í×+™çÇAÎ_…@þJܱFòN<8{w¹ŸßÜßa—7ÙyæÉÙ…·,y²£ß¿ò’<9C³)!sÏ^½±$ÏЀ©ç|%hD_Φ9óè %|©s¹·{^›i“Œ¿’;›X'Ïç©ê£±Ø ˆ ~w}ç<ß wìGO'‚·Åñ=ã€ã—éþœ<>{äø{À-ãÈç¹Ç9óð bKÆ™cUªÁ9óð ÏÇw˜aMð½ùI4>gžŸ¡fv¥y9ßHÙ:g ]‡‚HŸq`‹²œ8ŸÝs¸xÍ{æ)ò$G~MŠ;ápvòïØJµ¶¹öDwe΂ã\O¨N(eKÌú¯$Éý”WÖ‰ùêÎÿiÛqf²Ú8zfƒâ®WNmuqªc¿Æð'·s:¼x‚æhô'ŽÚÏätŽ ‹'h§t¶3“ÖÞÈÇ ýq®äòg¦­ýî.iæÄ‘Í»ƒ!§Ü3ÓÙ~%wàOæ×A®BÎ~™Ï¶¥ÄøÆsž†_Ú¾œ/ÑžM7Cb~7½äË#´¯=R>>ß’˜Sr?_¡9ÏÂù¦Ä<'/àùÙT0§óM}yÆ.Kx~öý’ßàeòmç;¾Ìâc¸óeîŸÌŸï{÷177æ9SvnL‚dvKò8kæ%LâÏ?7Zããò&ñ±úÜx~¶ËXbn©/{R˜[ŸÁv“ÃÌ!0ngAžžU3‡Xgš#%Ÿ;M‹xeî4-Æüþd M‹1VF–¤º‰*ó2³mäóÈþ:÷T—Ñ­ru™Èl{#æÎzS]† ³óÞ©.WÞƒ¹§ºŒs÷“õòøÌ'³sg毫Ü|¾7å¨oØo*ÉãðoRÏ=ÝÌ̶ÑÒöõ›A†Îaùž™Û¶‰5ó8ž~j83·mëFó`êð.Ã]ò­¸ñó`ê¹y0uˆwÉó`ê]‚é<˜:‡Õ¼;S‡XÙú:k®ª– æ`êS¶ÂsDêDÁâŸ4ó8¸Ë›#Åe¬‰ù¼™Ùö‡Ä°9R[Ãm•™mï1•œuŽÔ–¡Æž,¹r"Õ+•Ú2$º7Ï=ò¼i^>3µmK3Ç»ÈK:ÀIrî³æ¹ñ4\q`t¦;ˆ<ñù“!µ Õb9¯:ö[¸qÝ2ÿ!i ÿÁÖâYøï—Ù.­æ1ÑüMðßB‘i5ÿ|ùâ5oZa‘Òh5?¤€ÿÂNþ ÛÉEz«’´Ù}½éÝK1¢’ÿ6ûÌ?+tš,ˆ5j?$üí‡ò¡þ`Áå‘ð·Ãüž›ð·Ããœ8˜ð‡ÊIŸð( ®þŽCQéÇôŽ#àþ%%ü!ßó%Œ5 ˆÂ áo 馂¿±_†È„¿qyÅ$üa8W³cC“›àoÌËïðwÉH~‘Fš ´ÝÝ®Kä÷5«YÂ_9¼þºq0á/Ò?ìþ*\¿àïc í7€òáwÈÝôx&ü!ŸË¾À_¥ üaUÚø;c Œ‚d¿o/jBKöƒÕÃXØïÄ6ŸD–ìWÙcÄ~0`¢ÁLÆ5„÷û…¥D¾$Ù¿›&û•ð'öýÙ÷È~0°ãà!ûµÝÏYVüàd?,Ǽ$Ù¯R ‰ýj« ö+,Ù¯íRÉ~c†%É~л¸¡#ûa}>U’«”S‰ý°È~3Ø# ý`¨!4%úÕYèçLnF?ç·Jô›ˆ,H°¢Ýìݳ É?9òÜ=ä³$?ìJ² -'¼ŠüædàOLBÎü°ùÚyó?°¾ªy¹Jzï¿ö‚~ÊyNà÷‘m%?Ø®ä÷ýŠðJò«Ds"?Ü‹-Lòë5“ü6ÙÚ'ù…Q ÿ&ù9%›É¯]ägsO‘ê~‘ü6™ŠüPóçíz‡m%¿¯v‚ѯ Ièçdy‰~íèW)÷Œ~¯’výÚ‰ Ñ¿bWúí À%ô»öB«D? š¸)ѯÒû ý`âÃ1Oô»øY‚ûÐ3ø¹Å}CV|æ¾CNŽâ>< ÏvÈ}Hç¾`_ÿQbßux1÷UÏ÷!Trûê4—Ø‹7ޱÀ>|$eaß+Ca_eöá´åX±¯˜ä‡¶YÀïVj‚¾?j ~øû'ɽñ\È) 9)ùU“›üÜïE~è39¿‹üð­sbùáiÈ_ ~8? Â%÷U÷á<Û_r_&øÕ; üê¨JäW&×B¿ëÛÁnˆ~ÕäB¿V3ÑïÂnŸ@¦¤‘•B?üê\Ðoª$ÏSÅ£LôÃÓè &<äÑ*ôÃ;Ä:&¬òiý®S’‰Ðýœ¸Cô«4—B¿ëkügA?œME‰~íyˆ~ýš#Ú†ÎÇ"?Xƒ^¼ É/ìùXInqb8Å‚yžz*±Èï½òñ’üРüQ‚ZbðV ~ýæ ~Pò?|ÍI’øá ^ý}«—°W“üp"'XLô+iFèW3‰Ð SvY’ß5I ¿:‰øÁÔñà½)Ž`éb½I~8îÕ¯Þ#ßúä$ùµoKòÃ;åì.òÃñ–ö6>š¶áoe¼Ãß©lm†¿i³*Ò²I¼/6Òß1Hß©ä,õïÀ$Lf¤ú7ìmBõoªÙê¦*pTÿ¦ì–¥þ…7‘+Õ¿íjÎ뤿ãö©~ПSh‰þ`½Š±·$B&ÿÁ*š|EþƒM1·ä?„&8D„™ŠñëÒç"þ!W_òßœJ· þkûtòޏðÿ!Gê\Ä?lÞxfNþ+c[‹ЋXoò_%¶ø·)›ø¯ªJüó‚Fü›ß•VúŽuâET[L¿ ·+¬s, 7A$Ày±I€XâÄI€µø±Iåo˜µšSâ_)4ÁMë%ÿUöbñž…Š ù¯ËdLˆ !<í\¬¼hQOÈ%þÕ>ƒØ¶Ü@¼Ô½ˆØ*K2 ñ¯6z@X„ß Öò*ÄÇŽ&¶ ­)zWñÏ~Pÿv2‰ß`ãNNâß®øÅÿNÙRüó®Ââ,É wÿv9N ËáÁâßþº^Švf°ø·‡ÿ¦ šˆUšûv`S\I€X­¶.þY ’öW›=i%jKû¯Uwó\R xTrÑm“Ø—ˆå€!ÞØò¥XW “o˜º\–ää^ªù‚@Ø*I÷RßIXÆ.¢À²©Ú0ÓWš›ÐG÷Òo®^^´R¢âF ,ë'a ºþB¨„º)ð>ðEˆ¦™’ù܉Ēá×C•“XÝZˆºè­EQ‰t»„À²cÞ’ú’јü÷ÀúŽÀê®Àj0ï›xïr„ÞãÌ%ÿ•û¢øïÛÀ©ÁƒÿÊPKxEYâ•Q ߉ˆ[KLŒ©¿Jl¯I¼‰*¹eü&á1 /.I. £g4ü65 ð’ÎE€pÿdW$šŒ€Jü?“e ž˜¢1ð†ã+• ˆ÷\Å¿ðêb K=ÞÅ€xsQk8–ž<®µ™óõ Ô‰€åôm3¤ùò?¤]šß@g]Œ>vçÂ>EÜ2öíjaß®aľmßVÑï[`uÄVFŸr„2öÀ™Ø^àfˆØ·_Ó‰}p[™2ñŒåi¿•AO؇Pr2ÅLìëj°ïx½ó!÷'±ûŽ×±ï¸nW›Ø‡>À…†Ø7À©‹Íg“È}è¥\°ˆ}Ž&›ÊľqäíLÝíÓÅ”ý xËÂ3w„ûÞ¯MìÃ>Yöœ”ý`!‘/­S ³€¡ï”äGÔh,ªòU‹\_ÊâC{|bß “ÒØF÷CYbRø»ä$.ì+\Øñ“5Kû¾ŠA0¹üµ‚Ÿ 5~M¯Iáï)»Ð?œ©ÓŽLàçƒß­Àq?¹Â™ûêh^ÜWðMî³Å€±Ï–;…}«Æ>$öµJH}ö4+ê»ôJ2ù]°ZRßvº„Ô7•ÞÍÔ§ƒbAß|.í>E}à(û}CJt&êÛÔGRö«ÃzQŸ ^ªÜŸy#B_!‰ ÏGª†>»úÊ~RÐ_d¿‹•ˆø`Á¸j~Ø˼ćí¯ ò•žbsO¿³¯\ÈX‚"‘o(DE1ßÔx²¹gw’ù^‹¦f¾WÒµ˜ÃAŒwäû¸˜ï=Md¾fƒIæÃzJ K2l¨ß%óa)õPÌg³p3ŸÔc›{Ú^6¯Y¿ ùnÅò5òa)æq?e¦)â·2ö,ðùx×Àç ”ïkò±X{†Ûy³öD]¿ŠùR¼Çûö6Ÿ öpµXzhT"Ø+’#ím O`Ú«>/ÚûæIjI{ö‚´Wè)Ú+àía¢\?ˆ˜¬…¸×Ø“’_Ùw÷< ÷04¸mîí^Xˆ{,µ‰eÄ=í–E{2É3íÊ&hɯìðE{Õ4¢=Gû0í•3„4¿òRíy§^¸çN-ÜûFžP¸çDâÞ¥CÈÂ=C‚p¯öåÆ=±§qï¼m–IÜ3³ˆöNe\)Ú³ÕžhoÚ Ž´' Ž¢½ÇäÑÞÔq²iϘ#Ø›{á_Žd÷GÃÞ%û;±fF^BÖû6‚ãìU5{s˜ {>3(ØÓ ¾yo—›¶Ïá| øÌO>€•Jø0´Dà»dô(à+Ð0ð]bù¾!.ß%[ñLQSOðÕGñžû¢yuå½)ÓóÞ×ÙÇbê‰IøIÜû®ä·4î’ö´9)Ú“!ºiϯ$ØÃ±¦ð/a¯^ɰ·Û “°çHW†½©¸»{¨Ì°W÷"ìÁ…õìMY®í¹aD{ØáÑø“®°ðÖJ‡ÜßÑ.‹!·{e~IÂû棳ÞèMØ»áн¸õ}½f7'2òxdš€‡F³Š+Ò˜3ôLÀk–t<ŒrYl&àaýÙ¯>GêßAb’ce=l9ßa ò,|çØCâ;la¸ “¬wx3"Ÿ>`ÄâÓ7¿ùáÓ÷]z,|Wá°íÓ§>l—¾Sæ…wuô™¢Þe%yô}ޱÐ]Û‘î0ÿðè;•¯ª<ú ôèCïc=ìõË£{ã, CŸ;±új’}›Ì«Ew×7Ço ݵcbùô=Ö;Iw^{ìÒU7 èÑW›!{ôñAìÚQ.Ýù|Z-w¾òº”;ß÷°ì;ì ¥˜1 Ö·"I1£;ßn³@¹óÕV™d×–v¹óyÿ'²k$;ùAìÊÓGdWæh2è|ßdW6•ræ+äÙ9 ’ :‹M­çêóB;$Le =Ù{Ù¹ÏSÏ#ëlšb1oÈv Ä™r–=˜l9áÓ³(yáeËi“~s]Y€¦-çɤW6ått%ÛrÖ%Š€¥#r›rÎáûДÓî6åt¬ÛrÚA¶œŠ_dSN³)g=_šrn6>—)§C•Ù”ó(²¢)çPºl›r:´N9ñ¹9eʹ)¬M9ëHuý^aÊ©H5¶ä<ÍD²äœ§_‰–œÕÂöáS˜yQ]Åð±%çÉtd¢ºòÆÕáóK¢£!çÜíøGCN9˜Ð…¯¬iåÂW²ãœ ‹o>;Ù…ïÔIµÀïMC¹ð•—®\øÊ A.|—ÒØ…¯]C¾k³eg¸ðÕJK°+'$l„é J°›PrY M9›Ui‚]fëð#6—L9«?ʔӡÑlËiß*»ðÕ¡bÚrB¤]d¼þºðmö3¶ _ɃÌßãì0ì^|XµyB°Ã¼$EN^|mrãSlÝrã³hºñ9ìÀ)qìÊ4_`÷u2i»:!Ø•;£ÝøìTh7>Œ"˜Üø4»$Ù}cB6‚$;´Í!ϾôÀLÅk˜$äylàIO¾G2|yò)F=ùäLPŽ|:ÛaZ·Û^:òéH[h×½ÿNúVJ¤ŸÃ`Ùo0sf¹ñYà´ŸN¹ñm÷O7>ÛbÙï°à*7>dzŸç1»ñyí ßiµJn|š×ìŇý>+ᶸÜäìŧÌöâ›Êb/¾KyOìÅwÉË^|·lïìÅ÷ tö,yñ]Cê)½øä_f7>ŸíÚq–$ÝaJO%ÝÁ±÷%Ò˜sS”bÑl¼/o«i¾ýø`-HiQ~|ö¯”#ßsY~ G>ìyo:òÙ ÜŽ|õ9òá|RŽ|6vvæò®æœûý+ŽÐw9Vœe½£d¼H€âˆs’õ¾FØø›”õqO.‚´æœ2®6õÍÛõК³ibI}ã’­¨¯‰&¤¾3zyäjåø|år* &©¯¬­D}µ û.¶Œ¨¯à“úÚI¥"¹Ü–»D}6›Q —:äô=WYnn¤’ í’ÔwZ»Ì@.—ýk„}p5c!^¤¾qÚ¸súRºãOQNÍîEÔÃ)Ä\D=¨ÐzÁûÊlFØWq)„}XIqä>Ù_ÿî“=»É¯Žc“üll]\m_ÈE¡J ~‡ô;r_‘·¹ïúaÉÙ”q_›ûÊMa\°ñ&¡)Œ‹™'ȯÄ;ŒK ì’ä׎®eɉM2ɯµ¯Â¸\ÏKNœ‰©àQ4yû%øµ[ üà¥Ea-É‡Ž Û’a\|@øƒeÕ\D=XÉq«0.ß%y.á¯É(俈ºK"Lþ÷£GþÃÉ…ž/ùýèYt½ À.þkÇ/Á8#ßlR ‡¯§xïP7áÑ Qù%ŒK‹,DÄÓÐ<€XÆV"@œ)¿‹-g¢ˆ€Hµ`ï½£Ÿg oxË-Þ|P8SÎçfYØN‚€8…¼ÄÙ:ça àf,X–>”õû¸‘1e)ì -9¿f—çÞž½äÐñ…d½ª‡XǸ¶äüF'1"`›0‰€x^xÇ^7 ¨ë½vb D—½—(.Ïf/V" æØá±-†œøêI¬l BÀ¯ÿi¹!‚û6Ùmf^{ö5CÁW(ì=6lþkBþó1´ùïÙ¯ÂÞýh $þÃ5ôQç3m šˆ(?ì8o[Û7g à³=ö¨ eO9-Ä} ÿ?šq>ŽÑDþ«Œö0ÎXOò_å&°'6‹gk@ {ˆ–ºØqö{%ÿ¡u;Ndià~–ü‡O,ÛÊä¿gÈFü‡>BC4òßs*ăø¯×“ü‡{mrð{óùì,EþCàoYˆ^ì±vÞ‹UþD “ü‡.p³Þä¿g5&ÿµ;‘ÿžSÁÐÄ•KDX9,€⹋÷2OÈ)3qàƒE©`e£b¬J¸cžó5Ÿ2OÈ΄î"@ØÏ…ŸC>v@Œ$»÷e–úO’þœkʘ"ä°× éï¹$“$ý!ð†jIú{ð­`L2ÊM)BÚ5Jbo4ââµóЀø‡Àº7S„Ô[ÿPÏêˇ'V¸¦ +R„\§-'ÿbÒ!\1Eȵÿ°ä|ÆkDdŠKæ?Â?\³-a\³g.Þ|5œ…x¾}÷*¹Œð¯uôÀ¿çPžSá¾&‘‘ø÷ت]ø‡÷¼!×ѳ·DŠÒê Q/ò:| §’¸ä°‹±ôþ“ßÕUº¦ÿî/„Ñ>ó°îP%ƒŸýÝeºÇÿÕJ&U‡ïªÈds÷º\ÒêbY«Ë%UÍ`‹ØÞÜ%U—ʪ®*©ºþ«BYË4Úå[ýoÖŠp³ ô;*¸ô¨èÓ×íȽpÁù·ë.È@°g…§þM_øP \u¡¿ÿ¦[¡Ã 2ɹ\¥ªbº÷ªJ½ªºHUõ«\Õ¦UÓAÓŽV‘.q=u«A•ëmõ°`©È¹¦v•«‚hyõGbÁR•/rUí*W…LKU,XªòE®ª]õg{ò ½Ç Ôç? Jý›nóA©ÿ躟A©ÿU}?»öo®[cRÿ~¯þ˜Ôb®üûof½ß›ÿþ{cæ7³åïšßÖõO¾ ¶èß7Ä÷ûøÏȈãáû[â#þ¯ÿ€ Çqÿíù¤4|Æßþ·ÿ€51‚@ÿïþÇÿã›`8ý\ûûüx†}äæúëA²EßÎ'Lz?$[‚d ’="Höõ/ãc]}ýíÿþãé…%*öXosý¨ú?ëï ˆ}þ‰€ØÛ†¡'NëÒ7£õkÿ3VòX¥÷=bÈœÈü—Âýœ¯–ïGPÜÁcë¶cóðM{Ó¿9ÃöÛµ*5ò·5®dƒÖaíö]søpfÿøæÛrƆÉïH¿ým¢ä:ŠðÙßM'ΘxïãˆoWømdN%¤#‡Ç·)Q ˜c‹ßá®b'tÀÕÓç)ðHÇ쉸TÌ7t„á„…=s°Ž«fÄ¥Êz2?ë„á`€JW^2#žÊ„`¤[øùWð¡ÓBÝáA?áÊÌŒÄi’1!6(áÐ…·™zLmô†7ÐıˆrÉìhƒ ›êÜü „-?P"L{ÖD ˜©„)Àƒ‰˜9¹{#Îj'l¾i •–gžÊ qžÌ„wkâÆ˜q ŸØ<«°Úû#|EÓ„*ççum:LÇ¿¡àQ\¼'›g}ó¼—ÈÓ&¢MÈ*PÞÄîyÂî#hƒ ù•'î9#¨ `nH%çíö%€¸3óŠÞ£g,R_/p¼ÑòãDŠ4yE‡mÿwa6·ÑÉtxq¼'ô¦m<ý„@gÅ8WùÇnùo䦸J”húÞkîaƒÒ0~ž¸V ˆŽûJرpKc˜=o…D‚:ŒY< ÅÌ+Üžm‰1‹ç¤7Û·˜ÈXG9ëŠ3¨øUV|Ç<1ñ‰hˆ€K¾É†tø†ÿwÍ+,ÊävtùÑÂ'†ìP~CØæÄŠ ߇²CÎ58mÏ!+£ÍpG[ò2‹¼€K âEW†¿û““Cv/ïcÈÂ.ÏpÂ!{î2^Åñ0†ì‰Óð#K"HíWœA®üø]1a* ´×7óÀïNç—‰.ƒ¶Wç‘­“Ç®a:¶Lq°óÂÅéuœq´ö]¢À8ñĈÅ#g·À çm¡#ƒÐiâÅë»#i¼ykÝ8äžý[áä'ÚOñDp\[ÓC³ÎÀ0b$g{œxaÄž§ädäÁˆÅ‘|%âoÃO:Æ;ä§!.E'ÈFƱ Fì¹+‚ΓÙ׿¹=×–#vSt¬1b‘@#k¾Ï±Ð=¢M‘ýv°½²{=é~Íž³àóÞ9bùj"î½´$Ê£÷ä¿‹ˆ,9b•…Œs ÒßbÄbÍo…$ɱPBR¢FúÛ±C¦ºHû²žìíCcÄ:VCþÛ²‡‚Ÿ¿÷Ë!«Ð$È€C¶ùå*‹îÈŽ ¸1dw®>_É‹sØ80ˆÙ+2àÆý¾qì".†,r#ÅqqdÀÅ8øÎz"Qö<䋸1dDGÜïF‡\híÊE'DKr‘E6°x…c»s‘:¯yr‘=àTo®±X¡¯|ƒ7×XdR cØÈ‹‹DñtØfb¼ŽA«õH‹ñ:”Géoc¼úãEÜ;‹±SŽý 'Ñšu"n Ø=mȾ‚‡ã•ÓPä¿.p³¿©!Æ+Nž®¼÷+ìÀhfA®°y‘ý6ÇëÈÝPd¿ñºS/ÒáBLT1Ê#ÿmŒW¬Qq+x¬÷ùéŽÁV}ë8Î\aÇÍÃêÈ;ï6^¿j¸Âž›EþÛ¯ÍÛ#ÿmŒ×ƒé#ÿ­ÆkVópÌN‚ô·9\¡Üf××'ûö£Gä¿Ñ é,~4Ž\_aï2²€ëëAÿ—qic}=hpéos´ræŠü·­ãkÑ/È{bÌeñNÈ{âëV=w.°ü/J$çÈoµç¯.°;Ï#nŒV-WVŠíÉÆÉ.‰«c´"8ÀÈ.°}”¿:¸ÀîÌy9pßþÉ1Åõ’3Xdrá·Áed"báùæv¯°ð|¨”XøýH–ÂB$s¿:ž¯m……£ÒæX¸9š¥°pSÎLRáfƒHQáæ˜~¢B®™ 7§3nŽ€**Ü`îöKƒÂÍ‘²…x˜ÜJ 7än Än(Ülw*(ÜÌPP¸m 2$(Ü*}(¡0¶ x …¸„þ; …'‚œ35hB!šëV¾8¥zñ_™FÅ’µ)Û.™0.±ÿF¬X¸DF9±b°è¢á?™°¾ ™0®y+V¬êbÂm³µ™p+c_2ái’¢w®XÕ8bÂ-g¤Æ„¸æ•èãõµG¶˜ps f2áæ˜ÐbÂÍÖèd­ eÉ„›S´ˆ ñVùbBìÚR"âN´®$n°J$Ü(T‘«ă茑Cô·n6¸VÛ 7Ç2nÊÎ!¬—& nÎ@ ÜäœEÜlØ/Ä€J* Ö âF): Ý,bÁêÓbÁMñ…‚›óP ëi„‚Õ§…‚¸&ÙA,ˆ[åÙƒXps€B±`{²àfÃs²àæè~bÁÍáuÉ‚h‰œ6Ä‚›ÓC‹ýq…‚øLy%ÄàÉ @(XS(X.l×k ÑÆÙ‘„‚­¢`u ¡ ?žHps‘`õG‘àæ$ì"A¼¨À/Hp;½J$X“!IpsT>‘`v‘  rI°¾¯H·Jl ÖkŠ#ÊÍñK#Áê"ÁöÈ$A (>JJ#‰ðÔñ¯$BÌÖç"n·âÁI"ÜCY!Œè~”7;SK"„kÊ!’áâ;]I„›³H"„¢"I„²w.áæÀBfA'–“D¸åŽÉ è‡>XQ ˆs¿üIÐk|ò²@0Œf;B'JQøÈ˜Óø(ŸAЉA‡05ÚÉ Xõßý‡:ˆç¡3Ž@–  yAlÿ“é‚vFbUê ø]r;¤^®XÈàÃX\±°¥ç W¬Ê Cup« ;"Ax®tlOcDóË W¬»ìÖ¹dÁVê$ÁªY$x+†I°Â‹ïaË`.Yu/‘ ßTê Þ‹&ž"Ag$–×@°9|åŠU™Ü¸`ÕâÀÜ&uô‡!mÓ0Að+Q¤3’à‰#…É„Á(9º8%I˜É‚a0: 6h' Æ5¹' FɤZøä¹Í«<º¤Á(ÉY i°*ÛBâ`¿wâ`;  gµIƒýFIƒýaÛ½‰ƒíVäÁö+ò`\CÞJläÁ^sò`û2äÁ8ÔJ'¶&%¶·HŒO•’y0*¦ ÎÍ•{2j€1#Äø re­Çy¹²>4¯ ¶Ç! ¶_‘Ûãû¯F®¬~O’`<ßÕDÁz<‚`¿ââÂêw"ö¾¹²Ö¯®¬Ø¶wM0~uwM°D‘`/Ù¹²>§”»ƒ+«g’`Ü+•`¢ W‘`ëÇ$Á^råÂú ÁâÅ…µî}çÂê—’Ý.œÜïæqÿ‡Ñ³­¾ñ!;þÍ]ºš,D_Œ-D•Íø7å«% ºÀºFèYÊÈ%Úøýæf—Ö*!ÎWÚ 0%›ÐŸµ­ùmA úÞMP¬ùéèŠÐ‚^îÍ }s^ôRóÛ‘!/‘[ “þIó;6™²Ù-ÐÑÛíxjs.Í︔·HšÀ(åi~ˆÌ=»ùçDB¤|+i~ÃA|¤ù!ÔÕC05¿À ,¡æ[þ±¸Ž¡<+’ýÆ© e¿q2pªT?Äh˜]õ—¢$IõCì«doÉ~ðu¤(u?ÀSnP¥û© SÒý†CzH÷“¥m¢t?ÜñЩûáîùRÒýê^ÒýlynÝoÜŽ³NÝöÎ7Í=7Z@+°³t?”ÌnÿY¼qéÙØ¯ì¨­ûU‰t?< ÉŠºæÅ}±óq¢ÞÔýðVŒDÝó+­;©û!èCŸQ÷ÓYœ¨ûµš©ûU+K÷ýÝo8Bˆt?ï R÷ÃÞ W“º 2ju?´Æ¦¸-¿†SŽ'…?» Hø³ýº•¿VBåoÜR)¤ü¡b†«¤ hõ\™€$ @[%\¨ÉtÜŠi%Pt…4• (bEä„"PD~[¸ï+QÀ*Ù€FJyŽF /.•F íÂ)é¡H™¹Ê ?¢“ ­@á·Dÿ¿´RiC#к„F Xq·N}ý»C_<ËÙE¿ï’sýÂ]a_Œ@ñÀc1Eɤ ˜F õÞ2µÃ–@‡¾0QÁ¯Å® £[€¶Gyå« Y€Öì /Ûd,š€Æî$KhZßM& ÕÀ2m¿¢ (®9:óµ×– h}K™€ŽÜ'óEÉÝu¿øUžíÈ´½m@íÔeИ¿º (Ú|.6 õ}iZõÊN#Tå èO'ÐòŒ·7`ýJÞ€U"oÀMF´²e°+à¦t_2õlŠB–]™NÏ  å ø2ûÛâ ˜—¤ù'ö°GÒÍ?½–ÈþÓ½ÜöŸþp¶ÿôǵý§‡·í?ñ–iP&ÐsûiŠ&'ºÑ´~%Ðs³¡&-@«™€¶_Ñ´•Èp£1qùÊÓºœ·4η/à&[S€z”Éu<,+ ê'àF{ßòôí ¸]ò¼³'`&K(GÀ>2å¸1ñ¥í?Û5r”›n9ÖÍå¸1Âh9nŒà_Ž€Ÿmÿ‰!õtѯ?]é(O@;¯Ú°Jè hH{ʇ¹<å¼]ž€$Tøèi¿½Ôêhý‰;íö¢št“•õg=¯ýå£Ûý¯Åø³Ë~€U"?À}û¥X/?Sû´ Håè†)'@ùÒò³ÆN€uc9º9íè·¶ šJ–Ÿm–Â>€îXöÔа  Üå›  ¬beøé ߆ŸU ?1|Þ.÷5R~âҪ݀z'~V{Òð³½Â?ñcÿ•øÚ¥üš-ÊßËuÀx(2¥ ÐÉ9 Š+,D–‰®ýMÌL¹ü™+ŒCÃ(ßF1 Ò5™´Õˆh-ù0BÀ[1òß:aŽØ Ð¨ÜF@G¡1"[d—þæ8”7½Pç´B@4ߨv6í/°ñ\|AQ;cÅp©2gˆƒÎ´fÀcœ´ãñ‘[  }, øM„T1 &æke@léh5NEÝ6±Œ€ÈVÖM?‘ ÌBÀBT!ày)f9 p8ž‹ðP—4—¢·ˆ7å&0îNëEÄ"AûLà¶)* _ñ]¿Ú»ú7Å{_ðxO§šÌÅê¸lSJ<°©a˜\¬\É'r±B¬o…ÿŒÕ ëã»øOEòÕêÁÑ4W«ãu0àQ9ÍI€xOG%•jŽxÜ2Ô"ÞÓ³@ –kꊤÀ;ù<¤@„ãÌ3QàáÏ¢ÀÑ¢Exf y¤Àš/DhÁd³„@ÜivñoÎaIÄ\!°Î¦¸fÐñ/W¬ctËÏøN *–… ðpœ}! ž•f•D@×"¬Z€Ç#ãyàá(¢@„6%ßë›cÞÉ’d@ô«•ŸC X=X ˆ®w- ø-d´+6,Œ˜÷KD˜ãf²!àq)“Ð!;Œ€ÈsÎP3D@Äù`¨"`ì&»ég,(¹v Ñ€ kCÄã\t LÄóìK@t½4—V=D@Üjëº_kR"àq3Ÿ†_ü]Üñæo7ýŒ§™‹ ê!J^:_•I½°]C<„\Ø®!úS ¢ë>]÷›X ŸÅ °"®1'¥Œ(0VǼ†ñ`Æ-ºt<˜K% £ÞUa”Ør ³xJùYñ`Ô»Z@˜ÌÕWñ`8T8}3`=Л3`½¶-œAÄ€‡²jšqMĉ=# 1òòoB`EÓ!z®6âµ×x0¸f,^€U(°šOX# Ä‹§›0г’1°žGØê!V\a WVc gn«…í^Ä@+c`},a »(1ðHOQ1`}2 >ÓdWU¿µ°>¥ðPH|3 ¸!ÐÓ!ðP C ÅS Úcg|®ª¼¦@Ï´¦ÀjaQ êy@¯ÎAÔCÊ^VÃÏöêA´/YqjYÕ[ ÛÓÛÑ:Œ_CôºiĽ²'‰½8µÆ˜£Óe„’ ¶é¼,ô†Ì(X(Ĥ´¢`u¢ ªYbÁx­ âaQF…¯´út íYm åI æÞ‚Ǫ¤ÌþãßÕUºæß ´=¡röP´UR­UVam«¤Z–=hw•´ºXÖêrIÕ¹iž´»Jª.•U]Uò_h2Þƒvù¯ ´};Ìì>}þÿ_1vÛ°Ö-ñÏ~…ƒ}úr‘ªªÚªªÇÐVUu«ê¹*EÑvMEÛéÕS—¸ÇÐv=-†¶+òUª©]äªCÛUµÚ®ÊW©ªv‘«r mWÕbh»*_¥ªþ@ÛÈd¶Á@æ¿m í?3Wþý7³ÞïÍŒÿÝ1ós¶üý1óÛºþrŒk8!}ÀÿC\ÿgM8¨úמ¿=UXq®çzà´*Â\# ‘† <#³ ìïÃm#€ ìkïn^3@‚çÕãHc„‰í|ì HûRd§Û³$"’3ÊÆ¸:_IøæÖNu œIÅ™ã›ÑýBIüž<ŽÃ¾,#‘zãdÉMy‚+¾¶›Œ+Êç†7Α'ánà”gØŠ~;p—‘€÷|ð~ˆÇtÖ°–ø¶3ÒE{gCäKuyô‡œJEïb¬åyî|ž¼Öási¯;­Õâ^‘ãÎ8)_äÎ’#Ž…'2Ê^YÎ¥þ̃ò¬u­HõÔ`üR!ËÒ·a´"wmö‚§H(ØRÓw‚ÂD½ØgŽh:ƒ“GDpÄ0¼hô3#.†êd$þ\1Tý¨Ïžñ:9xŸ=⪫ÚgDÝñ¤¡—›ÈHÁrÇxFÜl³AnÑJôÈ25ãš;ÛYš0Lë…‘áèd+eó?w$5‹ålùÜo†Ø?h>9ÈbÎbš€oÏ ±2OÝÀä>¯d×ø’a‘‘£–w¿2¾_ó=Âm"ßp¶6Ób ö’ø¿hál.d¦=Ù\¹*¼yV=‘>1/¹âI¿+˜K8RÓÞÏòĉ'ñÈÙ8áBøä¯âXfÀ¹k?óWÙ8ð=›oûà'Bæmì›{–ìÐöýN͉/ÛŽÈL?yÒÎ"Ó>Ñïhm‡Ä´_ÿ¢QW¤¦½Ùûž,ÈEõÆÁC¤¦½®åGw.ªsÏûdè‰dÝG>Ê“+*tˆ‘˜ö¼[ûFbÚw´^‰icˆž´Æ‹Ä´ÏÈoÁE˜6‡è U_¤¦1úÝýÌzÎXQ?ÚÖ­22ÎŒi?yŸ¹¢nT#3íŒE—zÒ·òaEÔ£ñ×MµŸZnd¥ µ_‘w#+í ›,²Ò>{³¬DVÚ´ËQ.ŒÈK{Gl`æ©ÿ6 ¹ Úx,òÒ¦iNÚÔœ8EMËœx:䤣$íÈIû>zùÉKf®¥ŽVIiŸˆ»OIIiSî¿òÐ,²Ò>¹ÍÈ ž\I‘r=û’ÒÞ¹óˆÛÉš¢Æì,À yS²‰„´1<5 EBÚžO®é‘6†§æ.Á{tÜìc^9>'M.#%mŒÏ‹é=ϰfäŒw°äÉñ©©ê'ºa¶Kؽ9Ù†^zÂÐ*Ç'¥ÏÈI;³ ¿ Â}çeÞÈHI{æ8Š©ÈHûpÆ,ÉuÔS^䤪‰þ+¡#·‘“6Fh+ÉuÃíÈ’;×ÑVÏ“ë(~3Sä¤Å žëÊ·Jƒ·ïk|f ™¤î3ƒXÖf9i9HÓ?’ÒÆ=ÒTþŒôÙo¶qöF䤽f>̆}f”´“½/6AçÔ/ò«0c{û*H¼²,¥‘v\mùhŸ½·²pw¿52Òæjª§«Åjª%$RÒ^GNhÙû™¼MqØãÍÑ6‘“ö}òî¡VDNÚXN=Å!'m,§ƒÉm‘“`2gd&DÁ«©ÿ~¸˜nÌß)iñ¼ß›dÀÖ6†êÎø^y–@â™xº{çb*ôð Ò¯Œ<ØùsA¬ }wH-úç7·¢>èŒ#9ÔI=Ÿ_Šú¾Þ+<"õEz×}‘")†ž ï|Š›‚¾Ä „¾¯dãÞŽÐw¾s´ úÊSHЪs+Aè ×ÛÜ4 ú OÐ‡Ó±Ü úl¨#èÛ&íi }Ž´˜Ð‡eÿ៹FA#› ôÙÄЧHÓf>¤’'™‘ù°îo óm8ý_˜ËúÅ’\¢êæb>ŒÞÈ|H§Jš$ó9ð–™Ïa¶Ì|0wâóù¶‡Fb>ÇÝ2óís‰ù°w td¾ú‘ o‡yK^d;…¤>Ü;VSRÂ&¡ˆúlÍÔ·½ŠL}ûÆÔP¦>DλêÛ^Ú%˜ú¶+w“¢>‡¢3õáWs¡>ü*w®¤>|ˆ3Á‹ÔW”Ô4;¤¨o#g½¤>Gö3õíX÷£E}0_ËQDXäb…[åù† ‚HèS|=3Zý$æZ…çÛæs 53Ú8G¢˜oÞ'a‹Ðç0i‚>ìjäBB_»$¡o»NÕKèCHT¹ïñÎÜç ‚æ>Çß3÷m9¡5î«î'î«n#ôC[åÌ ô«A.ô«®%ôÃ5agôCìÁ¡`Í BÁv/¢ ÷¬FAS6 zm z×#ÄÌZ-®´2 Æœœ·~µ¸j‰½F›ñ«'¯‘ꯩì/²"jõó."à¦}¥~û»Ó`0O®ÂÖ½‹²˜¦xÿhàÅck€;v•ï/ÿhàΨç¥ÌJe piÓ` pGãç5Ô1§SŠ£xC¿" *â ¦ýÁ‚\°dö „™Ý¹Ð ÂhðHãÑFƒÇdBLÓ Jn ~¹^Á´3YZ8hCaã îaS–‡ÜÂA›Dm‘g´•™q¿Ê¯ <®Ÿ  õŒƒíâ ­D…ƒXsÛ,´É p¶„”ψƒ67Ú*Ï8hdã`½§p€üqÐv˜ÆAÛÊm™i´%¡qÐö±ÆÁR®…ƒ6~5Ú¸Ù8ˆwϾN´¡·q°]’8hËtã íŸƒvU0bÿ¤AÛÇšm$h”)ŸiP¶œ†Ašë‹‹‘K2»¿h.7Ù•DƒRoæ5¤A˜¼ŠoV&ž ¢à\$Àã`ºUÑ Æ&ïMÄòƒ ¶?IƒðÙkDƒ(É3"Ñ ¬oSü ÂÛá¢ì—ëJ’ìEƒx˜{¡A4ÕDÒ Cz˜q/ʇ¤Á°Šù¥Á £~1“¿D¿\®P’h/ÄwIl" ¶Kƒø˜Ù‡ ƒ±Á¥2˜ëÕq2Ÿ­a°ê ¶ ~u-B`õÁ ®!T[=„Áö+ 3—ebn´³‚Y°æZ± ÍñÍ‚á‚AO†AO8‚A¹•˜a§~/B`«–,è È,Ø~E<&s#›qMž‹{ —VYÙšmâkô$eD= ”(°†‚(°•±H°žX$ˆ-P¶¹Í¶…ÿ"޵éo‹CNÏýC |ÇËíŽño0Báßä´füÃñsn­„N³Sø7¨aÿ|€`üÛ'à ÿX9Jø7nnx…ûqR þ…}‚%ñÏQׄXwòq„;Æaç¿=ü]þáòÐ_¸–Ñ”§•_ã‘LIûÉ@x¦?%J"ú•v$ök÷’h½KðçY%úW‚?ˆ ÇbþiÑÂðçƒHÃ_u ŸÏE >§üéðÒìç£Èd¿v—Gg•‡ì=UòPÙìçZ…~¥´ ýêGB?ì®SóúY'2ú•-ô³vcôóÉs%™‰ýJ¥û•.^Bà.\Möó™¼Ùo'E%øYõh* › (ÙWà‡Q˜'¥J„.'â¾Z%,º£‰û|njî«Q(î«‘*ðk‚#Á¯½ÁÏÓ„ÁÏHàçj ~(yˆ‚ϯ]Ý6ùÕ²U@ËO"¿V1ɯÝûÒª*¡Fä‡)*I•àg³ƒŸ›ÔàçéÇàWGÑ¿:fø¡¾w?hÕÄ-‚™Ba‚_µ…ÀϷȯ]äW/ä×. ù9¢É‚üo4ÀgÑÑË“]D~MͳHe}Ñ_–H´èFòóGè !³I€¼ÁÏãI€\šxÿJÌK›÷¦Õœ¸¯n-P=MØç̀ƾ&îýp“L'Ð_¡ €ošÀ ‰~ð³b’_õ‘*¦ÚGòÓ¬`ð«>#ð³q…ÁÏ‹ÀÏë‘ÁÏö?'_4øÕ{ üZ5?¿“¸¯ÞIÜW !îkßZS§ä¾GÖ5Ór_rŸ³UšûlCbG=⾪GÜWj”¸õ¤ÚGìC5´Ú$öÕ͉}Õ¾z«yÍþJâ¾^"ó?Ê#óM,â>[4™ûJÀ÷ÕÓ‰ûl%fîì„$îs®Rs_u qŸ¿¯õ¿›îèÆ>Û5Psª@wk €% ¾¶®¹VÐýÆ »µ@7…@uã߉^]BßÀ.­¡žÃm õ¾mùànQ¨·_÷¯tÿãi$ðR²#é!)ޤ7àG+Ï\”`a£%h.J¦gÒCÐúÛ‘ôã ÌEz'V½_è·vöõ{µÍ³¯ßËàÕ½ô›0åaD¤ !G¿ò㓣ߘ¸pô“_Esô“'‹ýh´_~~»aŒ˜‡€O‹›Âdû‹òïé\L>ç͘¬¦¼ye@`CÞ„Åg–òb\-”‡°Q‰¢¼ùNq)¿:‹Ï Òø/yÝu«!é¡–gñúC¯^¼þjdŠôªqDz×!ßL‘n7šržgvA“ž=÷Mz¨&»µHïô.Np•O éÕ­^ùÎs?lÐC5ç"ðEÐÎE૊zxœw±ôlõôðOøìÊoÒk“¿-ÒÃ}’B zíQz„`ÐsXƒª¡ GÐsPƒ^}(;ý¡fbþä WNãøaé ¿æ±|÷º/¤‡½¤k;ý]¢$½þìm·¿ã‘*H·?ùÝ—Ûß8xh·?»ÚíOœöú˜þBäêÒúNô‡Eë£ð\ZŸ²•ÖwË\F¸Ÿ¦; ÌL€ E€C’– [ý•Qßîa}WSOlÖ“ÕH€( }% Ы† °B£Ñ%ίAÍXxe¼×}s?ßú—Æ€øŽÛâ÷wcµý¥1 BÐn‹ßßý=ɳzÞ'ýi Ø g|Aà}‰ØS $ÞçûÃÐ󾇢¶ïÉÔ1¦Àžâ¿4¼íÉ÷³)ôLR`«…xßÚƒ“jw¥À{(hƒ(ð>ɤÀ{H‘Þû+2S°—ñü ÀŠC¼·W—A.ɉ õ‚ÍI^B¼¿NIÅ x3Œâ¼œ·´(Î biPÕãJudìu‡y¹/ýFa^`”“¿Q˜W¢0/\*ÊË”e¦‚¼œ¶-UX$f‰‚¼Œƒ-ç /—äyѶ³‚¼˜*äQúüórlüÃ^`.*[*Æ¿)µø‡9˜¡aÿ®sa¿ \#ös¤±"Íb?ÌóQ‹Ô)k^Á_µ”à‰QS=] þIð‡ÐJéc&øC«&ñþ.é_†¿KŽ‚¿zfÃß#…Ôô3_:üMÆw(ø›ò ü=ò×6üÝÔC Žêdø;oEVü=rw6ü=§œô·ôEÁßuIÌüyŠýêë‹ýð–ÏbÞYÁ–­bÁßô¾wqôs7/öÓ PìwI‚2û]\^‹ýÔæÅ~§l÷Ì~ÃV˜‚¿ïÙ³Š!føÃ`˜þÐĹ·üµKžM µü]ÿyï’«KŽkiNÅ›•‡½ôGŒ!‘¼ÜFÎ%’k-RÛ{„GÝ* ‘­s~m™^&3Ó§E‘ åÝ,½~«ìǧPìg/Íh?áOßñ„¿½Ið§› øã–ð·oø{óÓdLøë¦‰àn²ßàR²_–KöãKBì×è Dì7yÎJì÷ѦQì÷ÑQì÷Â#S²Ÿžd¿†Äb¿ÛòÉ~¶¸û­¢_ƒÿ÷D¿6—B¿.øý¸*Kôk’ÈÈ~_§öûhv-ö³¯GðØO¢Ø¯ÁÛ_²ŸÙ™ìÇ/sŸ ÁŸÁŸžÁŸ&ºà¯ãœGÂ_uIºJô÷ʘ“ô×p('éO=ý5I¤¿h°Ð/?’Ÿ†\äÇ)à‡ËI}R½°ï£®°O/±oP»#ö}4Ëöí7m;ø%¥ûr/Øg˧ë°ëÔÒCØ×¯ùû´`ö%# ûÝAû¸SŸØÇÝsaŸi”¿UꛈY˜Ô7Ü-©oÌütUqTí«W¨Ýã1Œâ|•)ÕáôŸ_—¹˜çßsTí ù»ºrÍ”tÍ´t ›)éº{H¥êô:S²,¦eY™RÊ2šüªÓëL)e!­”¥”ÿjGÕÍ=´·_;ªþƒ›éðCýÉ›ïŸdøŽªÿ8Âês8ðý9¯lÆ|¾Ø©¹XVú fYÕ 5ËÊ\,«æRYtC­¢ÒµJb”yT޼P« â†Z%)—Š*¹T–ÜP«¬â‡Ze)—Ê*¹T–üP«¬âˆZe)—Êú7ÜU›ûýõ­?qWýü•»ê?Lž?qWýgù~º«þgåýœàÈwº«þõÜþ£»êåù?¼û~õ~üÇ/ŸœŸïÌ_?9,ëo»«6ÿ¨m¿i~é¯zÆÿÈÿþw9‹þgN«ÏÒÿë¿=Æ·óøóßq_½³ÿS÷Õ%ñ~Ã}µ.]öö±c­ùô¸ã²+HwÕh!æƒøªqô5¯díŠQ„ÞÅOÙXß·üœ™ýªïq–ݯvøºò}ËÛò,ï¸ J 7 ÏeíûÜÞå3Žn‘b›Sžça]mFèùçbÉ›ì¢Þ/ÜÜÅ-u¬îÛ7Í5îgì½¢#ä ¥´où6ÉNin]²×u~Ür'Àþ¾53…¾ã¢”iˆáùžEÛ,´Ù)ùÈóº„’Ñ Ý©êB×Ý¡ ;h{ïX⺫ÇiM~áfÆ]F>3R†' ùÙ[­EÁ¶Eµ¢,³Tè_$ÜqÑ2S €ps.ûµVŠÝ˼Ú[ã}-®¸"Å”‘;ò̸äõUh)#  VóùA§ÒçG’ÊøvÛŸQŒïúû*»?GžázY_ó˜ÝÞZùtçמåŽ,+Ö+9˜#¢³–·û§+•Û¦©­˜¬rßÍÙ‹w·$/=÷íØã",ÙÔÛOîu@‡¹ììG±ÝMkJÄõ+¥„/°Ûë¾Á.2?½va]O*¯Z÷‹'•²·ÃõÔ§Ù&L<©*Ç´¥§¾&Ö÷Æ“š)/³ÖeëÒƒ<£;µû%7ÕG2ÚšW<«%eþ~tt­Ï*³ì‡÷-õtóÃøÕ×ÚNñ°²æMŽ-ÖLyŸxZ96ýú.<­›2ð´Â©d7w\ý2@Ž”qáiÍ”OëÓGæ§;Ùy«lŸjÕÚ \ÕwN^åQd[¤Ü‘Ç=¹Ö,ïˆÇ•_“n‡Èzô³GB{𼪔¶ð¼*¥Ç§µ3><°/#;"Ot!,®êE«ãyE‹"û<5á¾ñ´ò "{¿µÁDyžHyñ]}p6¦{Ùu¦L<­¬ªá³'ɺŸömG±#¾ª7ÂMt!Û"Å•ÝnnIüaÍ”…ϪR,„¬?¬7¶ôº‡Eß?îïŸU["ÏŸU #ìrL·²þ°Þ8¹Ó=„ì¨SËbÈúÚy>«7Îu‹!;Þ㪎ïj¦ |X3eºSžš²ðe-)³vÓcȶú,X Ùu×K<†l?SðmU<†lrFäùðmÍ«¾­7:u‹!ëOëãÝcÈŽ£äá~4Ž”¥§)Ø (ý²íªYÛÓ.|\K >®j¡Ç=†Ë¬ ÆqÑ‹«*· ²½öÊcÈöÚ+w‡ìcq½»gyÏóÅO|[u<€ì1fPü>GE ß֧˺YG=O {¼ÚÌÀæ~kóÜeÖÚûÃo«R^~[•òáÛªÚNì|\5|&Çs¿|\ÕÛî£}×¼ju=¯‘âad{m߸ñqÍ<7>®A·×1=ìqÇLJkIÁÇ•ËýndÇ{”Ü_=¯¨}\z^™2ñ¼ªÍ_׬ËÝ(_°•ïG¶EJ‹|\u…‡‘=FÂÂÈÎcvyÙ3Ï‹k–ó5=®ÈÓ=®q¯Hɿէu’`ˆ)…G¼Á Ú¨xé"A_gþVAðºCöI¼W¨Ô ‚Ù'¾Â.´%ä4Î6à Z ¨×½@Мc?‘ hZnÐ,AÐââŽ`E€àa2Aðëìä@¾.÷=q­-A÷+Að…<Ÿ øâÜ}‚ ùŽ‹‚ ýåÇE4$Ú ÜY Ø#zA‚ ½¿ƒû‚ûÕkI‘`Ç–HÐ\{‚HPY÷dñ—W¢à@ˆDÁÙ‰ZDÁ¼*X°YˆÞÅ’â¡$ NèºÉ‚sDÉ‚ë ;ÛdÁ¬=X°Yðß;ê" ÎPcÈ‚¥9`Áš,ØLé\$ .È™DÁfA…¯`6GÁ}Í0 î,8.lQ’›­Ò¿½`Áô¨Nt÷±%ôæÅÓtWío…Áòá) îOñ¯@ 79J 6ðã™ î< “0è=ƒÑƒk²®€Á}<÷U79ÎaÐ"V¬9½Á3Š ônŽ(6`0½ËKÇñ°ï„5;aÐoD°3`°YHhW ƒ>£Â ç‰é,·0Ø ©bpƒ ѧw9(0Ø ÍbzÓM>`°Á´"a°™%…ßs‡AÏðýüsµSÂŒ›,è,èY\)# z'ã«ÜõàíLÌCôrF”,¸Sð–' úmð}0² ? wPf°`ma°àNùâ¥Nô!¾â‚KÉ`AÏ‹° q sôn¾‚½* ›³`­)X0§Yp§àÔYÐ{lKüúÝñ¼>ˆËCôrâö}L[ ZР¿ Ü(€8˜Ó„8èu¹èK¬y}æÊ½äô8èíyâ*çÁrC„; >=ËŠºc9á¥Ä2@˜Îp„¥&a)@èU¹˜, \’Ž€Ð”w©Œ €0OaFc$–ù ,# ¬m Ì·4°Œ)€0ýÀ:–NKEÂç‹#°T ¬yõn%Öª‚K–ÀA/8XS}h|/˜8Xà`™ìÀÁ’8è-à ,ó4ès´À`_À`™éƒ^@ïÃçÕ‚¡ùÈý5ÛF€AW°^ÇçUxp§Àn‚|\õ<}üb‹0X¾“€Á2Eƒµäɯ«ò¸®*ƒå{ ÌY ,m –`ÐóÄ^"`°´0¸ÇïŽg,XÙð]ü7|Z -Ží|aðåâGÂà„Q’pPâA…"–õ$x0g&y0ƒÓgy0Ý3R,½Àƒîá«à`úI'ºCö^tÁý®™࠻ᆘ<è¡x!è6|Ž“ÓU7y°Ù§?È<Ønsÿ)ÁƒžÍî”xºcÅh<¸k'U€½=±âº_;´0€pçá*@Øž›+ÞÂtŒK ÜY&ÔÍ>Šq„éœ@ØÜÒÔû L÷ãÂçæ€p¢âwÊX6[!!>X¶ÞŠ¡Öð ­®&Râƒu÷Ie@HŸ âA» ³jƒåþk €ÐLj[Â;–Iï±9Ƀ·Íóƒ3pðŽ#9í¢íÞñI/8hNó KïAœ&Þo]3á ¹ï‹Íâ Y4(g‚¢Ášß«Û,f¢Рù¶{ª4èžö@žAƒVÓ­0>XÖ‡H´ßñÀ“oóR¥Á§ëHƒwX§´§.öwHƒ±Ú/0h|!Æ—5o:YP/Q±à«¤Â‚wë,,xOD3 æ Z1O$XÐ.¦Á‚¥}`A¹& Ú›¢WqІ> ?|ZmÍ‚Xðîý³Ãtÿ¦Pô‚Ö^H…ÁÖ–ï† pq ½¿ûÁzé‹oC¥* ú÷eh'8bF’K9ü$ÅM!Z±æÀ–BêÃwµ7ЇàÀÛÜFG9à@ëÂ}€ }ì¢`p µ%vJ‚¥ªÎïjû‚wGPi =qç‚VrÜo‚ 50øìâwõù=éâg• À@»-!üƒ-¸Ìû´,OðÛÇÏêÂêhM‰ +r`>äÀ{X(—·âÀR28І&žhuÅ&AÐêšZ]±=EÌ»I´!TRì’2` ßç”yŸ¤öF[Rª€ ßž* º ÝSìÏ žì,ÝS•* æµT@6Y" ‰€[â)òiN°#"KŠ€d vøhHPsX" õ)¨"`Ç™ò<¤¨i"°áqª€¶rŽr(Úª8òPÔƒ(3R*`6™* ÙëF·¨6ø'H°ÁñWÊ€ºJ2 ê€í%¦QlpØ%°a#;u@u\:àçC©~ð—: †B:`d;ꀭ¥2¶Kê€ ŽXRÔÛNBà‡`S)Ú÷3¨‘B í´‡QlB—B j§Øn*ƒø´f)<ˆ¥øÁëa ßKF¤Ø^",•@Ý)¶#)Rþ'•@M)j”Àï!JR ü1•ÀŸv©~‹#•@õBJào~©~q6…Àœ!Ê "…@ÚrHü'1•@õ[Jà_“©~J &E*œ)R§L)Põ ïÖ)ùÙáùûà>[=áä,Œ²÷Ù°Õ³€ÅàŽÜ§hÉ}\jÉoÒ(ÜgÚC\T¿8C#Å1„SðûhIÅaNŠâ÷°yPüÄ(Rü¸0ô Z}Ü×Mèc´Þ}ú“ÐGìOècœ¢„>£Nè3Á/ðÐÇýë},Ä|©Q’ùÌw\˜/´ÎÂ|7û’BÐ`¾‡ë„|ÄO!%ò‰PdÿÉ ‰|ŒN-ä3BYÕþÓ§Q˜Æ’ùPAÌÇ iþI×þb>[ËéÊþ“‹ˆ´ÿìò–öŸü%óñu—Ì×YM |ÿ¥(¿L25íQ @?:Ë”_¦4ý«0¡/óú>8ðLèã 1 @?Ä‹Kè£aFBß÷¶ }ܯ&ô}á[7™Oæ‹‚¾ýè‡-裑’ F É|“ù´;$æãk4™/Íd>¾“ù´§$æSŸÄ||'ó©d1ß/¾É|¦=œÌÇOg2?:É|ßM%óñ—ÌÇ1&òÑä'™OF5Á|²#ó½ƒ'öÈ|ßMz#ó±)É|ïúiÿÉÁJæ“]‹˜/SÈ|Y¡Ã—ÐgÑÙb&%ôqVûO„/öŸ4ÏJûOY\’ú4¤>5PØÇ»™öŸ´ÅJûÏL¡ý' Å}²ß©öŸóä>rÚ*¹/Í+eÿ s,qß‹`ïÅü“Fâ>™l¥ù§RdþÉLóO™‘‚ûds–æŸ.rŸ†8Í?•"óOµO柴ÑøÉ€,Í?e’ ÕOfòRýÌ|üä¾,FÖŸ´÷¥=¨¬?9¤?59­?i]—ÖŸìhZê*‚ÍÿÌøS5§ñç+‰ÆŸœiüɶ¤ñçK9‘Ü'ÛgqŸæhš*EæŸhoZª²þÔE²þT·dýÉ«Òú“¦²þ¤¥_µþ„1埛¾:óO6&Í?Y‘¬?/žâ#õ™³· RYÒšVÔG{ýÃú³×Ó€ÕfTÖŸœ×iþ ûÀjý aMÖŸÌòÆŸ4mOãO¥Ðú“ƒõ֟쥠gúxr!¡Oò‚¾øTèã1“„¾'BJ$ó™r2ß ƒÉ|t0ÌwßøˆùT0‘Ï<Dkˆ|ÊBâËŸl®E|2Ó†éç%¾Ã—Õ¨"d7Kðé…€OsOÀÇC; |v®ì·Ê{J îÝ ‘¸w#äÍßðq]\Â,¦Cþ{°¢Où¯á”Ÿ0ЖAk’ÿS(ÿ‘¬‹å'žòÄ@­èÓòsÒBó£}ÊÃ3†²ü¤Û Õ~˜~v8KN”ö#T‚.ÓOÚY‰~' R¦M4¯£?L?qœL h×â"€ }âc¸dùyó”@0íEeù¹hwJËÏ›g”dù™vž²üìtcËÏç>î~vŠgN‚y×iöÉ8\É{.‚BúS§Åi‹)³O˜%®Õs€i|ÚŸlè$þQNOñÏ6Æâ*Šm0%þQNOñ†NiøI[ƒ4üÔ  øGÓ§bøÉ­ª²ó”á'pJükpxŸâŸ:•–Ÿ÷ƒ€9²ü´ÐâUÿT²,?µÁ!ËÏ¼Š¦Ÿ4ßJÓOµG¦Ÿ ›¦ŸR¾eúIÛ™~Ò¬!M?¢Òö3¯¡í'maÒö“–/iû©Q—í'-qÒöS·SÆŸjŽŒ?i¥’ÆŸ´ñIãÏÌCãOZãO¶YÆŸšp2þÌrhý©éNëÏl ­?eÖŸ²È¤ñ§¬µdüÙ±‘—ÆŸ´¼’í'-qdú)»0™~Ê|G¶Ÿ2«’í§ŒVdû)ã¡´ýŒ¸ iú)CÊ4ý\Raú©bdú©nÊôS ”駬jhúÉn¦å'Í‚hù)#Y~ÊÄK–ŸYµ,?iˆ%ËÏÌ#ËÏ.1KædÏAi„––Ÿ4“å§LŽdù©ÚÿÊò“uÉò3K–å'C–Ÿj-?3 -?ñê(–Ÿ²1¥å'§¨ ?e¡I»Ï´Ð¤Ý'_[©þ™¡~PÕ¿Ãiú)KcÙ~Ò8¾Ø~²Å²ýäë8m?i¹¶Ÿj2M?Ù)Y~ÊLV–Ÿ²T ËOYÍÉòSËòS#.ËOÝ&Y~ªXY~²q2üÌ,´üÔŒå§Y~æU´üÌæü…å'ß.²üLSJš~¦çõãËZŒ?ið(ãOö\ÆŸjr1þD?Õò}#ÛO„Ëö3­8eûIãU™~Ê4µ˜~¢&š~r‘¦ŸÊ“¦Ÿ4LÓOVž¦Ÿ˜Ziù)[Ðbù9*VSP|W³\š~ÊÆ”¦ŸiJÓO½yÓúSö¬ëÇwµX²SiýÉÊeý©’«õç8¤¿À4ÿ\?0°Ô^Ì?ÿ`ý9NëÏ4=•õ§š#ëO¥¸õçMß[²þ¼áh²XrÐeý©ŠÒúS–²þdŸdý©i"ëÏ´¥õ§>²þdÉÅñõØPu:UxqEBu_ý§We&fù÷¼^[ñÌZA¦¤wi¦¥wÙLIïÒÓ£úUJ–Å´,+SJYë²7gí7JI‘T bµÇë1my9þE×Õ·µEíC¾[W†?ü×ó.¹Áþ«¬át¶Ëéì§ÉhÅ©>‚L8/[ÆyXRzºfIÕÓ5JÊL(©æQIôt­‚ÒÓ5Ëa“9Tм\«˜âåšå( *yT’|\«¤âãš%)K*yT’<\«¤âáš%)Kú7¼`[¬¡yµÿƒ½`ÿ ¯ÏüáUø‹·å?~ù¬ü|ƒþòYùCIÛ¶Å?[{ñÿ§ìýÂø;°wö_yÀÞÉ» V8Æÿ531=`÷î{4‹Wᾬ]/o);Öîêìðà‡­ØNáÎÐL–§˜aÏnÄ|—e/8¸3„¹ÂhÝ]§wëá®-áÝÎáqË[¸²CÁæÍ¤x²Êùª."‡ÅƒmÅ]å°ðº«:ËìƒÓM7–cVÿ¤ÃC‰TǜâÑÐù(òD’ô±:,¦I¿¥WÓa!knøj½#Oÿä,Ø×Zc¯ë~¿Þ3eÁý(\Û‹HgÁ1€Ý6®Ž<ãºá”y,DÜp¯FìiÖó•û[zèã½á-8‚Œ ‹%xWßÊc|΂•ÒÜNª\Ôý,k­ÈÌ]Ÿ#eôpg¨‹ö xâÜL‹ÛµšGMk†7Ã&AcÚ®Õ,ÅÌ=ƒÂS0ž;|æ5æÈòý™±-_¯hfip$¸vî~ËŸ(£7ø VÊxá'X)¶s‹QÕtWòµäÕà'˜Ã°â„CM1s¬§–ìÀ¨åØHïq•mZÍ#åóS¬éµv˜û½±Ž<­Å£š)¶kµj/ÌäíngÊø½ ³Å³ª©f®êZöµypÕ‹6A 9ö~=ÁBðÖ{5¯ð®Ó~ÂÍ–×ä[IÓôÖxTá„zºµË(­™f†tÃQµÿwÊ£ªºúÀ£Çh¦:ˆ'UUm \_y.§y×Q°9i€j‘iV{õ0™F+/—²~¯¾¶§Ù¡ux^n‘ò~òÀE1ßGUÅ| ª®jÏ*<•LÛ)]Ï‘Ç6­ê›mšS‰r«ÿªwkQ^ø©®w_±Aœw#¾ª Ïdn€ ϧB  Ïü¤¹Ý ÏfG\Œg‡ç£X Þ~—ÿeáÙìq[-ž)åW„7?˜Ð‰ðækVžå‡ðö;m#áÙ¼¼‚Ax%o¿‚c›Y„g›Ë±¬%áYž7X „g)÷Ax³!ú·¯” ÂóøÌQ;Ïò¸$ ³rF0TžÁˆ[ˆðJ– <+÷‹Þl8w$ij<‘„— £9A†¢†§b¨áÍ܆7¿ž(á™°û[U𔃠ÞćTðØi x:)x¶~:<3Ñ9<ó¤à]”‚§I# O3Bžn·4<ú_€ˆ—…PÄˈxš­ñ̯SÄáî:5¼o¤©áÙ÷Ôðèø!5¼ñPŸ£†7îŸÞ€Åsjxv ©áuØØ¥†Ç³D©áu¦†×_R5¼¯)áÑPJx~²%á ˜$¦„†ùEÂch­”ðXuJx½Sþ¢†×? 5¼’ ®‹RóÓþÚ”†×aØ^ÖE /ÛC /뢈×?–L/k§ˆÇ®§ˆ§Ú)âq0RÄë°É–ˆ§r%â™;—SÄëpÚœ"¤ˆ§>HÄS$âeåñ²ñ²dŠxý£ôGOy$âiL%â©=ñ<³§ˆ§ÚCÄë0ÑMsT^‡ÏëÔð²jxº†žî“$¼L¡„×)‘bÆ¥‚§º¥ài8¥àu87M¯ãÀQ*x¶ó©à™ ¯\ žz%O ”‚Ç~JÀÓý¦€—í£€§[I/(à©j xšÕð2…žª’€×;‰ŠžÚ'OsDžžV x½‹çðaíƒdF/Éð4\ðÌM\Ð$¼¬ žš,“€ú:.ýN’~§É%ý®áDEêw¼w’ï4õ%ßuØE§|§‹¨Þu˜ž§z×aîŸê]¶†êKêòH½ÓHH½ÓmzgËq¿yRïÔdªwa©w™…ê]6‡ê]â;.íN—v§ñ£v§IBíN÷?´»>)’A»Ëhw¬•ÒF€ÒzGéÎÍî<ÒúFé®O*†î²ÖÑjÇ(Ýe¥.ÝåõîÔ+Jw™é®!ޤ;ÍJwª”Òo•;®8¤Ü©_¡ÜåO(wºËTî² (w™ÊW,Rî”@åNs’ÊÆŽÊ]&@¹SèÜÙ¹ª «Ž.•;.¤ÜåPî²H(w A¤ÜeáÜiø¨Ü©óTîºN!ü¥êt—̓èŠ$޵$ÐC®3âûN›L[ë„ìGšcÐ8Ñœ–ꢹ¼47ɧÐWü¤9!Œhn?ÈØ4ÇbDsûv—‰æÁ.in"@QÒœÅÒˆºDsÊ#œC4ÕĹ…ÜÉs '­“çÌOW”CžcÄÕä9‹®qòœòç,ÞOynœœSÕÂ9Œxn!tEº ¢Sƒ…tÙ"]ÖE¦ÓŠé²d1 •L·pœ=™Î>I¿H7 %Ò5°N³ ÎZ¼F¤³°‡]&™TD—ä(¢' é¸ ¤ã+« Ý€p"÷Lé:Œé‹B:meéô$ é”BºÄG"HUH7âW"݈3ÊItÊA ÃI°º†ÃžºÌB cJ:~—tdÛtü"'Ðá +žKVÏñs–<'êÏé*ò\C`¡Âsüx$Ï©ñ×ÂÉsãÏ‘ þœç%ºðœòçÚŒç§ðQ"yg¼žC9â9xRHžkªàœ`’8×p˜3qN+Vá\æÎ)…8Ǫ@s¬G4—¥ç28§"Dsä'á\ÖKœã”-8çU Ía'#q®­ø˜œcᜠÎé> çÔœÄ9¥ç².â\æ!Îe y.¯Ïi¸’çD—à¹l1yN+˜ä9Þ˜ä9 WâHs¼/‚9µ%aŽÃ'˜ÓEd¹ÇœÉrÊB”S§…r˜D9¶N$§äXl‚Š$·_'-¬#Er(5AŽ¥ äÔÅ9å!Éé$É©n‘ÜMYP(§¢\B£PNµåôžK”ãó/”S{„r*9QŽ%'Ê©¢\&åØõD9¥åøË5xk-0§’s0ÁnXN¿gÍ.”ã` åà!YŽ-Ë),§*ˆrª„(§+ˆrÄÁw(§ åØm¡)”c•B9> B9–A”3±ÐÛ ”㾌XŽ„#–ã× ,ÇŒXŽýËeÂbÃÑN°\¶“,ÇvŠåØW±†[(§+ˆrœID9 7PŽŸB¢œA”Ë:‰r™09œqINHrjINµ’ä°£õ WÒIo±¬øq`÷ú!Ç­8(_è 2„øMrRòIj\;ùmý^ñmW}Á:øf‹ŸSŒ[ˆ |óHEa³|óÄßvÊKÁŽø¶"6&éÍ«ñ+àm't± xk¶Àä;ÿ̸ÿìðæ)­š[¦¯KÂÛ΃–„7¯«ž§+ B·Á“fB7º¹‡½^Ó¥§;°›'Ôîp ·›$·ÒZ[-$ÈÍó@W rÛÍEÌU’[mL›w©Šqe8n»“O5¶,ÜÊm¹y/¹Õ<$7•äfH\äV+rr;ˆnâA¢ÛZ » ·2Ï@nµ˜ 7ïvi¹ùU 2’ ¸ù” ýàæóz]€›OûÜÊÈÜj97‹Íˆà–O‚ÀM£r«ÅÝè¹'ÑM]próKB¹-xÚKr[-öún¤ý7e nóÖ‚ÿn«cOQà6^•7Bw‚Ûœ4Å$¸eûnëýafi)ënÜMJpã~ŽÀm?ägçnØ·QÜNnã^Cr›*·QyOn£ôžÜÆÝ¯ä6¾§“Û¸‰–ÜÆ¶·_/ nºJàFµ=ÁM-¸AèOn3ÿ‹¡ª½Ð»ñ ÜF#”ḅ,nÛ­†èn“”ä6n$·QÀOnÃ7.¹{%E†cÝâ6~ã’ÛØamEÛ¸Á’ض[v<¶/qE…ã³°-µ©Å¤6~ɓڲ5 ¶Ñ¡žŠÚt‘¨M7AÔ¦ Ûx„m4oHnÓ]·eÁä¶< n:,òܸe•ä6à›2ÉMý¹q›-ÑÍ| èÆ{'tSûˆn-¡›f@²7›ÄnªHì–åÝÔ±Û@ÌØd·L!»©ÅD··‰nÜ®Mtã­¹)à¦) pÓÔ¸ ÄoOpãv£ÀMU ܸk™à–)7Í-›¦’ÀMS@à–)7 ÁM7*ÈM"¹iÆÜ4”$7Á-K¸éÅCrÓ #¹e­ 7Ͱ 7½Hnš:Any=Èm|$"› $¹I+%¹éÆ‘ÜÔs’›Æ›ä¦·4ÉM¯§ 7uœä¦Gä–u€Üô “ÜôHÜÔW’ǟ঩CrS­$7u„ä¦J‚ÜtHnš±$7¾c nê‡Àê/ÉMWÜ41 nYÀ9þ†SèºÏSè^Q  ËȨº eC¢s‡ÊÕ¼R~÷Èsîw¯à\Sxñœ\G‚ç2ì5y.ãL“çä2XgV=<çs&úD ³¨÷U‰Û ´)%ÏÉ&yίªÄ¥/LÜi èä®\@'×Ê:¹±$Ð¥«SÝýÁ¤‹D—>®EtrØ ¢óðÅwãv1 ¤³(ÈèC ”jÕºr§¼ØÂÓy¨-ÈsÁt|KP§ÀT„ºýÆZD¯€ºýÆz±i¨ó<õèœÇño!˜Î#ç¢ò`ºLdºt6O¦kמ£‘H—¯€tBøÁÝG)ëwÀН˜Î#ßõä\FÀ"ÓyÜÊQm+=RíWm+3º.™ÎÆúϺŒ.I ó Y±öÐeðKâ¾’ç2ì'yNa6‰sŒ‹<çÁâÎÉyëŸxÉèJÎsx•<—±ºtGÊD¸ÌÒÐeÜ:]†:%Ñe|J]ÆŠ%Ñ•«@t`–H—aU‰tS“H—a@‰t5O Ǭ\Õ5Ji!˜Î{Z0]é:˜®V5c”atÉtå^‚鼘¯+½ÓeMB]‰$Ô•>êJ퀺Œ]K¨Ë8ñ„ºZ{@]Æu#Ô•®ê2b+¡®Œr@]™` º2ÈAue,@ue^€êJ@u‚™TWZ ª+wTWÚª+³TW›XçcÍ™Ø)ÕpêJåÀºÒ p]¬+C¬+³XWzXW ¬ó¡¨TWKéØ+Í”q)5êØ+ÍOì•j´‚êÊD¬ó©‰ueòÖ•2ëÊÈÖå ÖÕ"ëêŽue¾ÖÕJëjÂ8žÐÀº0£ºr¿ƒêÊ`ÕeÀeP])1¨.{PW^ð3Á¡® åDÀÃÌÑì5X( Îë„¶æPW&B@]º€ºòV¨+í¨Ë‘¨+¿é23˜.;HWK|kq ]yÕÒ•çv!¸¡7˜®T؆ºt`«nÓe`hù¼e%Źó&ñ~x Ý‹‡× \ÞI™RÝ4ÿée™ Yþ=çΛ³jJI7ÊLK¯©™’Ž”÷bÊö±Ž²˜RËŠ´ZSJY{±u´ ¿K9žRJÁïÿjÇÎ.'}¿öëüO}5÷ï_÷ëÜç¿åØù3du›±‡×ÛŸsͧÑã;D%JJ—Í(©ºlfI™‰%Õ\,‰N›YP:mV9Ì¢b2K‘ËfS\6«eRA%K’Ëf–T\6«$eRI%K’Ëf–T\6«$eRIÿ†cg;kf{Í¿ôëÜÿʯóæËŸøuþ³|?ý:ÿ³ò~Îô?ä;ý:ÿz:ÿѯó¿ðæüÇÏ—à¯Þ“ÿøÕ£òãÕù'ÊJúÛ~}»²ÿÚ­óˆÿ‘ÿýïr¢üÏÜ:—ÿ×Û„~m¨þ/rëÜUÉþ›nWoqè="`ä;j„ß v¤ÝÂs¼þÓöIK‡Îûã[²×ˆMšÕ×í;®f²€„Ø“µ¸{ž0®Ø“õµ ý¾cO–Žš×xbOÖoJ$Äž,½2¯ñvßJÞ+fß9^ã{ÃÓü‚îûzÇOßuÝ?§·›¤÷""”Kú˜ÞÃøF«}{ S#K÷o;aҳ݊f­ö{õ»æ?J¸¯ðÄ>a÷ïê3vͧÑË툄·:å]ÓþZÂŒ]²e^ËV$øÚt¹¿%Ka˼ax+Öñk/Á£Õ*c„áO昭ŽF,¸ûd%ëºÎŸðõ©„;TŽ÷Šõõ2‚_T£mÿ›Ç%ûÑ}¼"ÚÙòS¯Ñ3ÿZ,3àêµ#®éE_ø/'ú‘0ž›@;þ¾1 Ãé†S÷å97w¦´: ,Þ=ÃíðNxBè ¿åò»'6ôwÊwÓå±R[Ï«Zçl@]Uó’g˜?–2éz—ÌN·ÞÈáGG>9!Þ Äë><[Êä:ág9=´JÆ¢µ”xŒé¹§ xÙl¸f†\iÍD‹Wè•åš‚eÖý]¡XÚ¶h R}Ëgd§<÷ïg]Hõ9ZlTûYòºe)§Ýl!¯j뼦Çw²Ô4^ö/’ˆ£êˇÏÉûÀr¾•ºÊ©Žc,,êsŒ—R=û`TÏ>X$Õv–ãf%yÇ-Žêw–ÛðÑÌrûûcŒ-ŽêùÂkÖšf|8õ–m0Èb,ŽªuÁÖ )g±Hµ)°()ïÅÛ ”Á.°¦¯qˆq«,–êy,–êSÜ‘"³ŒøŠf/{†¤À,én.pÍß‘!RàѰÈöŽ€þRȀŀÚbaTߣ-&7´—ò=?îÁ€Ñ@¹ªÅ÷ÔdäéŸU–30ÓêëÇ“`qTÏ9bÞdÏgÁâ¨Î£5GK ½ïjp&?fk& r†ZÕûøM”«ÚÖÀŠ û`aT×Y.ìrÚXÕó9×ýã]bqTÏ÷Ígœ×}¢5¶àìgžçæÃ€Q¶Ê9ÊëígŽïåºïÙ…ÓÙ?mó[:Þ)½±Ì3^Ntæ™×÷MDQ­óÄí k9¶ªí½Ý^¹ŽßíT£&/nûJržDMöa:ç’½æÏyb/V>å´öû1Koß­c|»w¶V´A›(gpþ±äX‹íC‹¤z¼3o‹¤:Ï<±ÃSz‘T?Å¡ìêÓÿ¯ºp&Ñ妔…è.XÉ‚èî7Ý|£D7m• AtjÏ©žDgΜ߀­ : ½çÈDºù!,6‘ŽÎœItöp>QD9j¾ãŠ :3x‚¶šûÍ…fy[ÀÑÑé0NÞŽ trúK “?HÜ èäG–@WªX]ùû[ÝŸ’èäéDWrÑÑ»$N t5!0%°N7MX'§¸ÂºzU`]éÃýõów`î‹°®–XWÆXW[XWFXWz¬+åëJ{žû=î°îH™ç¯|z2å{ø`¾¼z¢*°®ôXWÚ ¬«WMxö,)ƒ3‰W­vüו^ƒëJÝàºÒKp]¹/à:[à\È\WZ®«)ícûXr‡›Ï—@ ®›®µzÂgÕu–ûÀ:K™¨hÁÕçä¾°®äÖ•Ž뎔Å.ðªÀº2¤ÀºÒ`]é¸c]-%°®^XWS&D¼â…uµœÕ9•¬ËáÕÕ,7<NlöêÊ5Átõšï|–Át¾À‹58Ê֌ӕzéj–@ºrŸ€teìýê² >u@ºrK€te–wºÖÍ”÷⓪”Á'³HWKnÏ'HWÞ>`ºÒ0]™Ä`ºòNv³j„ P†A/»ªHw¤àc>“…t¥ÜAG»šg@º#E SÚà=ÀÒ•N:ÒÕcñeÉæÍþcŠéJ)@º2õ€tåªIŸ»œ ºš…Nw³˜wñMŸÇI¿»áÙ¾ã'½îf¡}þhÿ¤ß]Í_à\iïêIÍ•áÍM³Ò‹«@sY `΀ê™?&¹Ã\Íñ½?Þ‚€¹#er™ˆýNÀ\mÌx<¥€¹Ò)À\­}ás {Àœ–—‚¹šã盜0gy`é}λ@˜ËæjJkçæ²W„9ËÓ… >µ'`.ûM˜Ë~æJ)€¹R7`®ô0§N–+Ëipþ†Çf tv~á®8ça­#έývð&è¤ÅP {aò+Žï t¶ˆ;:zŠBÇ'RèèG =ÏJ¡£ÿ_)t8Žg@%ÐñD¥:žb‘@GÇ`èè–ZJ ãV t<ž*nW8é™ê‹ŸPèèà }bI¡ã©T)tôŒ-…N­¤B‡ÓïèxºS¢ãñâ”èJƒ¡ÑÑxŠtœü)Òe9éx>Eº’"ÏŸ¥HG·})ÒñY¦H7oQD: NŽ'S£+ÅB£+Å@£ãÏÔèx.5ºÌCއ©Ññ|Vjt<1GŽ/ŠÔèJ 4ºXÕ©Ññ”]IFWZ.G‚˜¥D‡sqTè²?”èxP1%º’‰ŽÇlS¢+y Ñ©"*t%˧³„ ©ÐñÈ]*tôR™ OòQ¡Ë[@…އS¡ã©¹Tèò**t<¦˜ ½Ùcp¨ÐÑ•]*t¥(t< 𠩦B—c ]É…ާ S¡+åB¡£7»Tèrl¨Ðeû¨ÐåXP¡Ëû@….ïº,™ ¦VtùpS +UC +…@ ËnR +UC +å@ ËL….k§BGxTèÆ‹ })t(tê9:•+…ŽwNž^ tz—H +ÅB ã˜KŸÓ¬‘>§HŸË‹ Ï•š Ïih Ïið$ÏéY–<—­£<§¡’<§ª©Î•,¾«(˜êçÈ?qÓ,Š[öQJˆKCÀ€¸R!Î.; Ζ(ÄeBÜMDÄ1° î[d¸Oênß°~XYf0œŠp†3 ?ã{´_×W•äÖ^Y¬’áì0ÀÁpmP(ÃÑ'¡Ž®"Åpô¼)†£¯;0œ· áèŒGW‰B¸ðÀê2&¾L‰pŒW!„1“á2N·ƒ G·Üb8õ<NÍ"ÃyÝ…á,„jdÃå`8u” ×ÌKÉpí!pá,@-â‹Co˜b8FVÃqÂí_L.ãc£9C„Û øjá83áö ‹d"Ü7?9V›®<Ç!N‚û:?$¸rUÇ”m'ÁíkðV&ÁÙ =ÁY(b!ÎãzܑߚwɰÇç# n_Õ‘‚˺HpÜÑ!Á•š@p%ޝ˜D¸ƤD¸Û"Ü‹£à‰p{fü€pv|ú4³äžn/g!ˆáÊ5Žp„{› /p»”q"Ü~K=§™e)WR€p¥5@¸R;®Ôîgà@\¶†WòâvÝØt Äekqï#ËFPÜNÁŠ„WR@q9¤¸’WÚ3Ðï9@q¥ ¸÷§9).ǘ—ãGŠË^‘â²ç¤¸¬‹—} Å•< ¸RW[GHqiPLŠ+­Åíižv–ÙORœ­V!hâ2).ï)®¤€â²vRÜóñ‰ Œ+×ãJ 0ÎýC“³mÝ\|9kJ|:¹õ›g ´÷Þ4dÅ™ÿ‡jg™…â²RœE nÿƒ÷,!.ç#!.G˜gRqå*@\IÄåÝ$ÄåhÄí9Ae—í#Äå5„¸]6 qå*@\Þ)B\¶†—-&Å•º@q9·Hq¥öñ£P\ÉŠÓ½$Äåâ²y„¸’ˆ+WâJ (.ëƒ<ÇaÑù¸ £óq8µ”çãð=ÉrlÈá Ÿä^Je`7ÿÉr8­”änØp’Ýöš¦Ž`·ûûý@7õLçãØn{iÄÉóqJ˜èù:ØFÇy>N‡Èny Šì–G›t@N¸tBNÁtBîáêT'ä.¾uBN‡±tB.¯ê_™åˆÜÅW­ŽÈé—ÎÈe èíç ¹<ëÆr¢›L¶ó„œCtË#S:!§£WniÈOtã Nt+¥ÝÊU@·R.OÈ]üÝòÑ-ë"ºež@7/#¹ec‚ÜÊ4[6NätÂáÏÈeHnyî€äVJž²â«ë€\v`Áf„NÈå鲯eŒÃ|Èsq|(ó\\ž¦ã¹8ÞÉ<Ç›’çâaŒÇâ>Y[‚×øn穸,¼vÁg9Çy—§âÔ%ŠË<<×Ey<í°Æ þ73'Äu[¶ˆCøC0œ,îx(ÎŒÝB £›ù=ùS7'¸êæD«o1œ|–áˆ7b8ž:@pôA‚“í§ŽdB†ã&ˆŽ{ßb¸LÄÉ”Ç-aAœ¹`üM —Ãq3 GA W°e1aœHˆÛ q|GíB·sÄY3B\^Bˆ“×@Õ@œÌd qï¤Í$½œ( N­ ĩᄸ̈³ƒ’õL\ÉŠÛ ñ@q™ŠË†O”À#rØ( ßႸ”lq¹uLˆãø%ıû q)_âR0"ÄÕHp×#qEœ ˆ+í£'A‹WÊ¥wý8Wå+pïÇ!ÁQôÇ•”G…÷q$Ž#Z¸Aæ Œ+¿©ÀMdÆe!à$­H€Ó]§‹¨¿u¼mSëß'Fé‘)Õ·òŸ_—¹˜çßôÉü<Æ[Y>~ßÇžRœâwñŸüX™y””ZN¤Õ’˜RÊzïx—3¥”…´R–Rþ«}2ßÏíö¿ç“yþî“ùsäž—?*Õ+óùæ3©_Ç ü‡Êª—£¬Ã/3Ê*¹PÖé½e¥×eU<3³$åaAÕ{3Ê)^—QPõÍÌ’2‹:<8£¬âweUïÌ,+s±¬Ã‡3Ê*ž—QVõÏ̲2Ëú7ü3ßwxTù?×Aó¿ò&ýÇÞ‰¿zoþã—OÎÏwéŸ<9(ëo;i¾-ÔÔ~ýoî¥y/Íÿù7¼4­¸[û×7Íœ<¬>/„nãaÅ{Z¨šýÂjh¿ô=ÌÅ{kÕ2ûÀ·w ¶×Ny=ÖÅ·óÝÜæ²ËÞ F„(·¹ÏôwÿáEžføf±ob×ØÎºïÇýµe&R|×jgé´šÓ#^¼šûÎÕNi<2-ÖÏwÁÏØ}/ß¹jïz¹>Z={§\ ºÛålë §¾·íŸZîF“¢å;Wí{.ú40l«ëÕ±}·i·:¹ÍÔ¾ÇP„±éíáÝ­œEWn¶£Ü"çR–ŲÈ<uÏîClû'¨{y Œï… ‹çò«e`¿|§Ì¸ O~ß)¾qµßØ7ì%žëñ8oã±×çò«öY «) ãÛä[Ïõõ(%l¢žÍÍÞ‹L‡¾sµó`3ÜR¦wÁþAÊh‘çÁáÙç2VÓÂ&ÈcÑ·¼è’GôÚ—|˜jEý‘ãûX€1ëÀøXÀ=·Ý²b¸‚«,tÖ¡Äü·mèDކR|óÊfcüô Š;ÃÉùܾuµ+n`¼Ç>ÞzÄÒÚ)¾uUÇr?rÞ¼K·o]í<-¼ï”Õâ뫱{|÷Êó Á»ßñ;¦ÐþíOrNÅçy¾˜ =Λì”÷‰çt°}Ïë!g,Šý†wÁÜ4F7ŸöEÙf§˜ß/{”'^ ;ÅÃÎXD*”ë'£ší>Å;ây|óª´p|ñ¾b)ÓÃÐX,±ØÞ)3fBîß»jK ·ò»^ïËÃJ;Å÷®vÊ…×òN™Þ‡‡G<žÏ÷®ö‹™ûñÏ÷47iL¤Ïâƒ=vºþÃoCæöøsç ¾wÕìv-¤xÄœf;¬˜±ßˆ㜼h2½üf,2½Y?›Û|iº Æ ¡Y?Kù``½S¦¯Vml¢d …Úã*Lü½N„mÄcPÛQwófÀx9Y Tï»òi¾uå#ó ¥_¿£d\¡P­à‰”«ëÝ)¼X õ±Þ"ełۣµEˆö5Øsíµ¨ÿÖ{ÅB¡ú=Xœ Õz°"Tm±P­vØ1f¾ÅBQÞ` õý‘âÔgAñ},ª÷€zéÓ}窖C½£˜Øü}ºï]ùýÆ;¸O™á§ûΕ—‹ k¡PÏ›ÀP¨‹Ú2XÔoKìÙ= ‡ºhòX<ÔqÌG‹‡jyZÄ4Ü ˆFc/bì:­ßºŽ‚¡Æ¢2⪾¢ê‰ß®ÕÖû2\¬õÆ„áà3\­=ò¸\ëybYóLߺªwaºb»Û÷b…òLߺò”óâq¦UÊ{»²ëWÅ®Þ{»²ë)W¹²ëc[½ïÝ¿z7ßÛ•Ý£&WvËóòÞ®ìúøM´Ï•Ý:~ïùõÇ•Ýò¶~-ê]gÎû<ñU\_¾Õ—<~Oö`¢¦ˆˆj#1ïÓ⳪·‹öaj ¾«ß¹a™¯ÌÕ¡³àoZ`ƒY·¬¦)¤A8|éÚ8àï3è¡û€¿ÏC‚¿žðwFÂ_±õ ö“N€ßþû#>k0ѹÈcA~ÅŒäW"s€üJdß—§B üŠŒ ð+¢<À¯(Ò¿/Oøü¾<Ù ð+jÀÏÏàÂu]€ŸŸ&Ôµ~œŒ'ø•SÍ?/ÃeàWÎöü>³™ü¼Ü0¥ùå1g€_ž¿&øåYs‚_9  ð+Ÿ~¥ ~~亣Üz©yØbÂdN~yàçÇØo”3uÆÿ©àç"˜.œò¿ˆ‹Á~yðœì—‡ìÉ~yž=ØÏ¯Á:4ØÏëî(† 9Ä~V7,JJot¯ða¹°ëMþÕžß°\(í[¾ °¼z`¼ÀcÿÞK°Rà_mMàŸ· ù>¼ D»WgÿqcÿêEí<üOúóyƒ;õÀr¡‰VÿÒ‘ñ¯öÒðïh L虀üW{ýÂv¡äyà ¤ÄƒØøÿ•NþÉKéï(¥…bZêî÷lôw\3a4‰¸Aµ—/,Ô–€¿ZÌÃ…œFuÒ|0\h Âà¯Nšï«/ééôWº ¿ÚÉ– tëHü;êž¡˜–ºÖËiŽá ü«¯’À¿:8~ÐÈð¯ÖøW[Ó`¹ÐoX€ÿäʃôç ³ÒŸC®„åBiðÅ4;Õ`¹P*_o˜¶ ÁìtµÚ– ¿#!äÒ|©üyÅñýxðªø«] ø«ãôç)˜Žv ýÉ øq{J– uÍqtºÃn!ïJÐ_éÔ€ÙB6reiÌ€ÝBv*à¯N¾€?w´ñVú«ïê+ÝœXfºyw‡êê. zÊÉŠè*GOá ¯œ,„Îrô„MØ-¨à k]:•!ûÕ 1éôTC>_üÆÞÄ<æýê=™0ÚÍY3aµí0Û-WÁn·këiÒqŽ>†–»ÙœÓݼjÁv×–3®7w Ìws¦-˜-äX0á5—ç9˜-ØKåˆ×ä`¶PòÀŒ·´f ùùY0äÍçeÁpA-tüóR°ø¾`Ë«š€G ¬yËU0ç-y`Ï[j‚A¯Z ü+£ü+£ü;JñQµÕ@M·êÕhÿ<åF {õAþÕÖÜ0ì­)ñ fÉ7 {5€žòÁ`Ø[ò|ú¬ÞÈÃ^ÍÇ¿£nöêþå°·¤À°7Sÿêø=0ìÕk øW–³À¿Ú>ÿ2“€õNþ×À²7Ƕ9ûî1D)ê¢vU/ÃþÐ)ÿÅj¾`ºÉ¤üwÙ·lvûï—Ç? ÿ]öB™…üwí¥÷wÈ7È,ä?{‚p‚òŸ=AAß­´”©1ô¿ë~~ÇE!ÿ9ÍTô”Žæ„üW‹1ùÏ|P`3c«U)ÐSžJ;å¥{pÈ¥\Èõªÿì*h£ÿ¬ ”éBþ3[y²cÈVÎ óEdî›G‡Cþsó0ô!俨Y,å?Ë‚íUÈY,å¿lå?û>jÿ.“nÈ…3ºÐ¸,sùÏ~ß•}°V¥@oßW)ðhMÈ–²ùÏni2ä?kÅÈPK‹¡æÍ£˜CL°Ôå `i @k1˜  µ¦U ,“‹"`é9DÀrg Ö«Bˆ€e( æMÐ^@dˆ€–‚…TÀ|yPÌWE¨€ÇïÅ— `2`i1d@K¡ 2 MZ(s¡^nþî !Zë ²@,=€h6VXÙB´bˆt!ÚHP”_} é]" ½V¡ùBÌöB, !ÚS½ °” ÐÚ)`é“K€v âk)¡ÖkB´qóÁú,ó„Xú °Œ0D@ëë¤@:ˆ—hŸ  e$\,ã °´`,Ø(§NsÖ>>¶uͧ%Àz dtIn!æ´¡XÆ`i$À|è(æ‹`i$ÀÒsH€ù0„Xs„˜‡`H€µ}ë=ß6”˽‚XZLT\ J€6:Tøž=€Xî/$ÀZnÓW•­é?¾ª”5±ÓCóOœF'öÅéíŠ}ôŠKÝ/·B÷Ësê~Ú¢ì—ûM’ýDÊÒýä%WÒ_)Ò_Iô§(IR%$ýÑ·rJÚ#‡ö—¥Pû“^i’†¤ýe¹Ôþ$^Iûㆽ¤¿ì¥¿’é¯ éO[R’þJUc¥@ú+ †ô—Ò¥¿š2Ù¦Pû“&&íoðJí¯\í¯¤|¸-ÀiEéÃñªGy¨ýe)Ôþ>Ú6Iû“vEíO¤?hJ’À$ýIª’ô—yžYîe*©¦ò‡‘)ÊY2•?^Õåë{Uæ;L寤`›2¯‚ò§_ 7íj üiÈ%üéæJø“(*å/åB*Y.•¿úRú£¤Hé>¸«ô‡¥™¤? ޤ?‰Ñ!ýé¨WJÚ¯•ô§R$ý©Å”þö`­ÒŸZ,é/S¨ýit$þ©çÿ2Å?`ˆ:ö–â=€§ø—uSüSŠÔ?õSê_Iú§Ñ‘ú§))õO}€ú—×PýSŸ¤þ©ORÿ4—¤þe¹Tÿt¤þe¯¨þ鎓ûöÛxç¹ÓšêŸÚ õOí“ú§±¡úWò@ýËSþË^Iþ˺)ÿe9”ÿ2…òŸú)ù¯¤ü”áCÿ˺)æøýÒØ€  ã'PÔ §XSôiý*úy –”¡OëSÍ?ËIQ €zåHTM³\*€% `@MI)€º1E'ûåR,%S,)Ç·U`Q)f¯(ê=2^ƬðWóHT9Ôíè ˜ `ö<4ÀR.4À?Š€i{33rÆø!¦œ7ômeÊÔ#ͺçü1Õ)f(Ò–“Ñ3ôY°(n  ¡¡XRD#«XRFC·Ž `NÈ•4ÐI*€ùLQÌ÷@u `ýýãÛ*°¤0 [#Pc#P·W `ÉàY;£j¤A*Ãjd ÀTóB,9 jlD2󒘽¢XSôm¥nP÷S `I˜ý”˜)Põ°Bä*M`vŠ`iÀ’²ÞsžKÌ!¦˜ƒCøÓÄ‘¸_¸°Ž °”òÎ7`ÀìÀ €9•(rh~ájšÄ×l¥ÝŽÅwÿ$ãÁ”ùâŽ>ÎùÝi Bßc žü‹c æÁö•!ô=ö u…Ð÷8HýGê|~¤ńη¹D€:ßm–¹Ç9¿{"æ§„¾ÛÝIüGê|·™Õã"ÓùÌûÞ…Îgkq8+€Îg³å8åg _5ölæV‰'íb ÃÎëù RBæ+C™ïn”…)óYÉ 4™ïnSòaÈ|æ £ÏJPÄBç³§†‡æBç»Í¶¸:_¶O:ßÃZ”ùö7Ê e>óÄÆžÍ®ü¡ò¥H•/ÕÃTù ~På+z"U>\‰/7ºI{Œ›´g h hOáZE{Š« Ú3sê÷&çpOqÛ„{ *ÜSä1áîYoß^œ- ë)àžXoðÞ‹õFU÷ò§cž¢Ý óÛ]˜WR€yiCÌ“yŠ0¯ä楅1/?¹Ä¼rÕ1Ê}bžÌ?€yiÞ#Ì“a›0¯ëô1O&©²ðÔç^˜—yÞþcù.ÌK¤l ôÄ„Eؾª¶WMŽƒòòBÞ'«P@ž6½y¹²$äi+J—6´„¼’WÊ䕇<¡ ò²}„<¡/蚊„xò×"ÄË}"^¦ñäÞFˆ—$AÄ“Û ^b4O޲„xåšO>q®z¾ï¨»+ÌÓuZxÊ¥/{NÄ“[)!žü½ ñ²=xÙ"^¶ˆ—¥ñäíMŒG×?Bä•ky%Ç'?É? ¯\ÕÏh7 y¥@[ó7\T'üÙòþ=àï™%8y™4ºüÙûû°ò|ì5 Ôü½òQBøÓ)QÁŸÎ­‹þtÎ^ô'Ϥ?;U 𢗗‹áaH¾=¼¼ä9ÖÀ?;¡J_,î>$wãPú’1fðŸyQ8¿r ˜ü÷š}º8ÿ™¿ØVû5[¾’Ü‚ÿöÛ„1´ÀæÕWÿÙU8;éüçËYüþ{Ÿ&Š þ3Tê‚ÿöà Îà¿âQüg‹i|vÁ¶'ܾožÜ |É;€/äþ¥â_9¿ ü{?aðφß+àßû¦X;Fž¯éJ °0ò´Á¢Ë–0ò´º>ª{n‘ò~:ñàFžVÐFžæXƒZàæåJCÐ0òÌÛB#Ï÷Óiy—0ò4"ÇQ?¯ÇÃÈÓü“bÃÊÓêZ‡§—÷Õ(·ò´Ç+ Xyš'bê{aåi)ÔÜÂÊÓJ¡Ó–°ò´›‹U¬èéåj"Lxz¹µ v#Ï<µNO/›<8aäYn=½˜á9¨ ž^.- `æiߊpaæ™'íiæigÛ{%Á2e|éž^†\ÑÓKú@¡«y«—tÈ@W/ù@Ó× æ lx4«„£¡—£—ôf3Ïrã`æi¯á¯‚ »Dx+Ö©%O/Ràée1(Í<_³€f ÜC¤w•«EŽEe.&nYMÞ?>«rõRÄ„™g©‰®^òvÃÎÓ&q¯$ècA—1ýã'‰´vžå¡¯¹¸€¯—üLÀÎóuÌ–3OK –FW/K¦ põ’ÅÀÌ3¿}ÕÕËÅóác–Ž^ät6žÅãl<ß«ÑT´¯£°ñ´q"†g¹K°ñ-0ò|ïÎ#ƒaäi¯òQðH #OëÔsy–·%Œ<ËÃâVže@aåi]è½ÛÏéè¥xh +ÏzUXyî«âg˜xZSȧpóRÜÒÀÍ‹mBE¼¼Ø8Ô¼à¾È&žöP,òàà»ÇË`â™·‰&žÙ#šxÚ¤!”…‰g-ùÃçtȃK˜xêa¢…§UŽS`°ðôP »ï)gQXxæG.¼ lvÉÉË¿nòñ²“öù•¦}g~®hßi³ .rn.ŽÄ™æ'†£æá%?aÞ™÷žæþ‰‡zæ¹DH/tÇEóÎ|iÞi“¦Ñç <¼HäáåëRâèᅥ¼ó}^yo óNˆCáÛ) o8šwÖÖt,k_(Ì;õ˜ÊÁËZnïY=Z¿¶5sxEmÝ­‘rx´þÓëŠGkäù7=Zÿ±¥TÒgÿwI)Þ¨?{‰}µ,¥”²VÊRJ-Ëã1•’âw-ÇRj)ñ»”Ñ®0ï,£Ç”RÒJIJ©e÷«ÞÁZÖywêýú/÷´mkÔýÚ>\m›wl;sÚç\§ûìw¯‡ÞçÏÝrï ûËÑÿà¼øG í¯œuÿðºý«YöÎroþlŒåðÍeµâO;ÊjÕŸ6Ê*¹PÖ‘‹e¥GmU¯÷ãã°›‡máïná}ð„ÏwÇŽÚ®ÛXŸ9_ß=°VÁß{j¾u#qOgùvSØÿîå,ßömyQÎr–ßß0ê÷\Vîày£ï¹åmÛd!Çã0ß x_¤¬è÷P?ûfí>ì×–ëß›j¶ÙÒ‘§9ÌwÛ‰AŠ.,Üç»í ÅöÔšYUá÷tš·èTèR°ÿî£_öyEq,í{cO­M„´ß)·}ß}ÃvV²ºè¹ù³}ÐÝ…nàz_z‹Ë…[eû½·åX6æòÚnÞsbß~CDM¸¤;Ï[(¯)ÃyÞ6uØàá<ß÷ï]µþÐËg¾ê­ ‚|_lªuÛ¸‘â<ßö]•ï‹MµnØ­ûž7zð€‡¾/¶ÕºÑSPõD¹±©fÁOÑ<óo]x¸ñ}îé©õNÿ Ÿù*·rvð0ØœÏOGzÛñºqÕr¤·º.ôs9Òçˆ6ŸR»ª—ã×bW­Œh{.ËAgîû·ï©õѾö:Ò÷®ç°ÅžZáWx'8ÑwÛŠö¶ØRë¶ÍŒ<݉¾»Øã ±£Ö÷¿˜âDo5ÅyÌÏf‹å1¡/'z«*„–=ž> O®Ýxë…™ŠªûÝ£Þa>»gÖs4‹<¯3½åiHp¤÷(³Èò9Ò÷A=î‹(·;ÍL> sÛ£r ¨aÒ^$¾|eY¤[ï½­~ê¶YøÚ)ëŽ.p‹ò‹`·^^¡ívçá¦ågñng”ƒ',Þî<ÔÚ>‹xkKÛ›N„¾yÛl7s ÏçLß­r> {»KØÒû,îm;Zow)“·Î¾â¾<¦DòEèÛ]ÎTÝsÆ¢ºsÞDð[¯+6?‹~ûy"ü­÷ Oï¼ý«:nz ÿ"®çYHy½¦‰=‘/¢à6‹˜‡Š< ®ÂKZ<Îö½‰™qp÷,¡ÇïÏáú£ºøÎH¸Í6ŒñðΈÅco­†”žmbâv®žûuá§T}Ï;Æs™îÜm8šÁpë‹o…îÜ/ºHý"n³¹='tg˃D@ÜGëðÉæo>Œf„Äõ·Z²³½jXÕÄÓüq€#,®ðº\&;[¯9Î÷F=¡è¸×ïÁoV‹¨¸Íô‚…«ž~ö ET\ÿŠ=¸êÃ'µ£O-¢âv…êÜmkð”þEŽñv…æÜm›¯!eFûðiiWˆÎöz‹¬AqËmiw§LL×v‡èÜmuUEPÜf¡$c“·Ý!:çÊ¡EPÜ2~whΣ2VÍ‚âî /¾¹n ÝêW¸EP܇a6Ü|û‹æá.DT\ŸÒl^ÈÎ6?\µâ›º³{Rñ>æÓ&¡/»Lè³ç}ÄúlÖuà[@Ÿ Q‘Ð׸òôeI}j°˜[­|vÖå@>{ðj&òñV‹ùn®ÈÈ|å*0ŸakìòŠùÕb>Í<2Ÿ]õªÀ|BzA_R@ßMósAŸ­¥ÐwqÅ è+¥ú’b}å*@ŸmÅ8 }‰b€¾ýDá}j¡Ägâ Ä÷³+F9$¾‹àMâ3»qtʉïfdßCñÝ<ç.â{ž¸ Ç˶ oúIß}s Sñ3¯&ë ø .¡ø™¡(°°ÏÓû£$¿ÁSè’üðBŠß;Ä…¡øÙq|¼Ò)ù=ZgAò{MªÐW¼PòKÃeI~·A ùYŒXÔɯKõ™žG᚟lÛ¤ùÝY.4?Û”Ak¨ùqÃE¢_#EKõ[´MÕO[‚À¾f–Ÿ‘à¢ßÓSâ‹ÕK'ò)ú Ü…*ú¡ãý^,/¨ù=˜.¸Ï °ãJÍ@Ðg+hHlüö7î‡àwÝRÔ\ð»‡`- o/L¸F¥à÷ñd:¡ÏÀ èk#sHð»aõOæÛ.ñÌ7¤ÌçâHqÁﺥ,ó™18î¿‹æšd¾Ò)2ŸÙ]SÞ‹/•û8¿kŠ ƒùl ŸÁ!0ÏÀ`1%ô>›ž(¸ù ÿ¦CÁ϶Jo@¾\ÑSðs»nOâ+:,ˆÏfúäÛ/*±¿—gkÈ|–K/0ŸU…=m2ßyó=M’`0ŸvÈ|/Ï»ˆù}åúL_¸* ÏæÖc„¾œ ä>I‚Á}ùlûìì0ŠÜ§Ñ î³Ú'÷Ý<Ý"î37H÷å ÷ÝÄ £Ýül#íøír°>$ø÷#Àïa ˜?ºøåüJ€ß#¡‹àg"æøÙ‰@Ào AÀ/9Yà'Aœà÷>‡èWæ Á/¹™àgb"1/ÀϾx¨ à—8KðÛÍ„"EðÛ/L<2?{·g¬íÁ!Àowe¢ŸÕ%Ò»ã9ÃnÉÏ? žò3^Äý’f‰~$8\_>Aà¾2ÿ”ûX ¯˜¯ÓŸ ˜Ïbˆ@o è³þ¶Cí3Âl Ú§u”ÀÏlò‘‡à'Žà÷ÒR(Õ¾ñürõ•jŸp‘‚Ÿt~¶À8¿l¿,‚Ÿ ~·ìu$ø-ZIð»D™€?ÉDRüöƒv¡*~ïT*~×PŠÓßÃÝlÑŸø0%¿%jƒägÇSq$¿ÔËH}JýiKDô7èå8%¿Aý$øoкIü·¸z#ÿY(!ä¿ä"ñßEÿ‘<¶Ó‚e»ð/ñ ø§ý"â_ÅÈÀ¿šçÞ!2ð϶ À/Â?’<ñϱuâ_*¦À¿|iÿÒà‰øg¯BÜâŸRПíý0 è/•M@Û@õ‹Lh;„2 ç>Ðjb °Ôhw šp·»Gæ™LR'æ&QÀü’SÈ–›GÔ°Y n@3g;$¿Üò†1éÏêyPéïåsèôgÏ•EÐ_ŽéÏÖ—ýÙæµ{þ™ƒí”ùì}]U¾ýœÀõÏÉÞ|¶Áx3à[7Ì!eáiûù @ðžú«"ß~Ä– ðMF㕉§|Œ ø^žê–ç%+6Úx6}’iãyÉ ÀwïUS¾7~ ïø.j!ðé€yÏ(|±À{yþš¼—‘É{fúFžy$V¼÷Ѓ¼÷v­#iåy‰kø,>˾¢àøl*ø¾·“ƒ÷ŠQ*€ï[t‚"à{¸GCàûºŒ¾È|öy:™/1 Ìgëq,ðùŒÞP7™¯qª%ó5‚‚ùüõè D>žU'òÙH`uEæÛK¨õæ£=i0_{èT:Ÿ ÊñȧR!_.r‰|»`lÚxÞç'‘/7‰|/ƒ® ùrYNæ»+Ŗw“˜/A±amOkM"ŸúHÏb¿ äÛët6̧=|"Ÿ1p6ž²PòåF9m­ŽÃÂSV$²ðä&£ Ïlh1z@>»ñ˜¡D¾´ &òu¾ÎA|ãy$þ9ñ¥M2ˆoܲD!ñÍGFŸA|ãÑgŽÄ·´/ â+¦¸$¾4úñ[».$¾õ¤E§?ÎfD‹[GâKsg'¾a6aÐò‚øÆõ‰æ‚ølæÒ¬zߢ˟ݨSï³ûBóÌ >›è,Fž¥œ ¾ñr[2ˆÏÎì}ñY¿!Qñ[ð§BೇÜà÷' ೇï9ˆo\Ø÷%𙧆Yøì©sï}—OÞ³áƒä¼W Þ&SrŸµ ÞKëqòÞhI‰Á{6‘ÆÁ{ã»…µÁ{ù4“÷Æ·~È}cßÁN}Ï¿©ããR1€/ß-¾Ñ¸aKà³ÛB¥.VÈejøJÏ|æÚýðÙCÆ’øÊÔð¥Ýùìn¢ÅF|6Ih“Šó¬¶ÓyŸy$Á6OÁÚj N9þÑ©vRž媺ÞEƒ0a^ç–1¯„q6ÌÃÛâ?RÖ3S³bž[BRú Ì3÷y¦ÇÁõ0ÏV¯×q”ïµ—à+0ÏNrá# ̳•'ИWT2`Þ÷¦õæ÷Ʋš5Å$n×R) ö'a÷È3Ã-ü=¯œ2ãå"ˆ—Û%D¼Ü !âõA·,D<ÛÀŠˆgkìÞ:â•õ2¯âõ½ðÇzˆ—ïF2^gÅ_£{”<[è1}oº…'à•EoXsKNûšcÁä€g¯ ,Qx¹Vß [‡!aÅk¯¯ÿ‡¼7ØÙGºôn%—ÿ¿˜‚DJ¢tãèkÏÂm`sÿ°NÄ9'BYYÝU†a`vù1ùREŠ|'Äwë²ùâ<ù÷"caòÖ\®Œä»õnÕFã»õnY²—kQ»R:óüØô0÷gÛøðz¼ú¸ ðÖ;üd œ\¼å#à­÷åÒºEÀ[1=¢à¼²÷®MoM98’ï„£D|¹Uï‘ïÐ3tþ#àµ0%>q ÙKÀÃ3 Þðð©ü˜ôÚ^˜|‡fÕw÷ï¤ø®ž€x‡Áórâ‘%Žx÷HüGx×6¬ä»µÛ“|}§ùñäluxµÀ ðÚö3¯6 "¼öPD¼{æ(HÂÃ¥‰5$¼~¡$¼»FÂ[8oÏ MT™“ð°¾Êÿ3 k0¿4$¼6‚ðZü ‹§¼4w.F¶¬“ð°`)ú. /€G¾†9?Ò$¼5¦Íw‰x+¶Q„‡w'àŒ >oO„xøÉñqä\—¬ B¼…½ÍÇž‡M×õqälHA|—#‰xí;'Ä[åþ™ˆ‡™ªÐ?"Þ¥l‰xàºñ±çâæ—ˆ·–½ÆÄw{õ!â­Kùxwù{&âaÎ_ΧVBT"ÞZŽˆ÷”'f"^{†D¼ºoAuW"âá¦HtÉxë²{¯o]&º-_ƒ Þb¼Ë¦W2>.¢Ôd¯6±f¼ȸ†’ñp!±– ö=Z“8nÄx—­Ûd¼úB¼ÓFr"^«òp;úáyz›ð HxkÊŠnÂÃ.ìcÓÃÇåÏåª:å? Âkà%Â+ØIÂÃ1¥x.WÕB3^¯CÄÃÄb+Œãsø¯Ïßf#^+!ãUËf¼ÓÑ‚<%)ÈWò ~yØŠÅyûý“Q8¤ÈCB^‘¶ Ï»CÞ`XMg¼õe¼)¡b<-\f¼÷IØp2ž7ÌxpÚøxu¢]^ˆˆ×@‘ˆ7åË`Ä;Nù ñ Í ñ˜D¼wˆÑv%Äó—׈יnûQ¬SŒW)Æ{?¶“u¦Öù‰ãk@LÈÃÛ¤MT·Oß !ϻÂ<­9†¼)×!ïTöRâøô7)&<"^užûŸ¿¢¨]ä1 —‡ç &¿ÝÉ‘íÑ©{(ß#LNíu—p×¼?à„­Çñ½sÉY¢äÒ‰…ýãÒ E»ãƒ~ˆà£âý™Ðˆ~pif¢ßî@‰D¿rÏ#ú@ÓO "\¾2.e["ý•wwÑßÒ11ñ¶qù©ÿ.oz„uN'ü+¿!á_E»'þ½[ Çí¥K'>ü;wSñïîPâl_¤`[Ç¥ :$À&¶!ìX' ð  È†L-¯€M#C2.vb"69©¸8ŽÀ*.·„.k;mQKøóq…Ì{·„ªÄ~ZÉ·”¥IìW€cö³ã¸Ø¯\ìW¦±ßû©;?Μ>75ú¡'IN~>5úÍ2úÙˆ$ô»ÊÃ’è7½(ô[H'ô3o ýN[¨Å~Úý.­VF¿á°Ðo¾a¡Ÿ?gB¿øÀ£@ä‡ò˜ÈÏß7‘_A°ÈïVÁ"?hˆüà5Ê:A~6˜üný‰ü ÈM~ Dø5€øê~£~§°~…@?AüN‡õøaºÈ}3§ß©ÈEq>D´Û‘û  ËK“ûZ3¿k¿5?v•©Ï†¢¾:f4õTû°gWО±ï«Þ² ÂþQoi$ì³]ÂØÕù/ö| ûïM„}õØâ¾[™OÌ}81f ÀïÞ0$ðÃÒ)×ÍXLCñûÊ[7Ñ¿g=Ä1‚Ÿ¢é’ú0* ¢¾GÑ¢¢>ÜŒxòâh•½0©5v¶BêƒdùÇ“óÆTæа÷¶ó|"ùp7²ôåLöô቞¯aï9 t }Øõ~-{÷fõ›€>(¡³#}·µo}÷(…BŸ‡´ u.^›Ð÷\?Aßãu…ö%õ=rlõ¡sÚGêƒy5 únDUqièF“²ú æ®0½„><6I›Ô‡:òÉLê»±ÈeABTï]Ÿa`B_¿ß„¾{³§$¡ïž%Í’Ð×n9  {¾†=¼]Åí%ôÝs·é,¡¯·’Ї®Q˜^B>´Üú c/[¡ï~lµKèƒåLay„>É úîý’mòù¾J2_ZÄ>¼Æåûü˜]N{{BCpÄ"aÎÈñðr½Jþî`O^öÿú¿«ZªÓ÷ä´á¸Ív…*9é ö7—éÿO+<Þyká¿s³µå’ÖËZ[.©¶wßìöä.©¶TVmUIµõï’¯~7iè,Šï§2´e%ð;KPz–âôµ¬ØûŽÿ¸þ¨Bª¾%Iý»±ð(–·Bûݰ€¹â«Ðk¹)d•=WkŠŸ¦\ÉMµZj*¤îÏ«šRAoª*©©^ËMGl~«)|šr%7Õj¹)Hȳ5Å‚OS®ä¦Z-7… _Ÿ¦XðiÊ•ÜT«õgG¤9ç»G¶£wûÿ“ õÑ©% ½ÿÑÐùAê?ª÷³ õ?kïçáý»z_Aê_ì_Rÿ‰ïåß~÷åûÕ×ño¿š7¿ûbþzâü¾­ð±Iß!ÞßÁ‹„Ë^"rH`ë/ñûÏÿ;®ÿø¯ÿ ‹Ì¶Ÿÿñ¿ÿç»U¿ ûüøÿÏ÷û€Àûú¿ýçAÊ‘—ÓÜ_]\ôî/°BÝï®ì#‹=K{†,öõO±ßzÐÁ†bõÕ ÿŠöü^¦}£ÕÿQ—öñ'$°7äÁç.v@œ­ã}ý·“Æ@úÝ9Eú¦„sÓû]N??Â`ò~éî,ö€ÿ‰M1“¦ÆS$.a:÷—$Þ-ÆŒôó{–„¢Säë`ÃWxMˆSç±ë¾âpu"ÛœRîXº&¢ Òt¶¿Û™w_8±'Ê-)äÃ>»Ž|ÇY|æóØØfá>.Ô¹œöÚøÂ¾»$eG»`ý˜ˆUVв‰ûÄé 3ÿáò2#ætd @ ÿ襉‰*ØpÇ "ðþ½ÄY2½×Š£‘ Gp&óYáò2áÏÔMwDÝõfžˆßŸˆeË-ÜÎ&ÒfñøkÈÛ_8­e°ÊjÑEé¿4(/„Å-ÓÓ)³ðMÄ"3AÎŒóµ‰Ø!êš#vó­^ª˜#É7Vˆ¹)¿qa©9åÖ;¯8Ôž8ON4H††©®ß!°6Ã?œ§ú '™,}—‰£XéŸ0¸Oœ™Þ’ Àv~BÕ…`:â¾f(%òü3Âs¢/xÒ3ãœn^cÙe#l8'­r9ˆw=qj*÷†…§™ˆpâÑTn'tIh¾]aÁŒvdW`‚˜8ß$ý“KóæãŸ'ÎæãžåSç¹3‚éhÉ )Ý^g Lø´Ó3"£Ï„¼B²ñœ‚•ˆH›¹¤¯ê‚Ëq,9ÃHÑ…÷ J*0qB|þŽ+Ü–âGDî;Ng&ä(éIù„pæÄ©ú‰¥:I‘xà+ê(![tºây;¤bŽÏ¯Rªr^ï´N79üþ8sà&ªã‘Ÿ¼xÎ|ÄÉÎè. xà€7s(ëœÔ0cñÓì xpcÆâ¤7¡ G±1coåÛãÿÄQ!oæ ÝŽøUÜ/üa0aqŒŸGD0Ç„½ä* ³ì1r+–È×›ûÎͳ‘0í¡·NeÀarLØSºÏázudËù¹ç‘è-ú×ø÷“¦jx$\Ù}ùýÍÌè-惋ó¸ü.e«7“È÷‚ G ›ƒ¤MLWظ²YÀbL×]´Œ°½Åá—Sñž›§k¾òR½ºû89[Úz ³5¤c£àÚr²ÂD‘í^!–цab²ÆD*ÜÉÑ—ê‘ 7&«ñØV.¯è­xS‘ 7&+ÎòäÉåµýêÉå5 hqqdÃÙªE&²áÆlÅf(KF.¯õœÈ ³Uߤȇ³Õ÷ó®M˜Û½å“Ë«{çý´æl}ÇT¼áȇ‹[Þé'6ö•Ë«W¦H‡Ãmæv$²á>,áÝ<\^ß/OØp"î}õ§âéBÜß` —×A7œ1†–×+?’‘7æ«{yZ^ï\"î¹rüÇê5pÐ3¶Ú¹ry…èØÎ.¯ø²äý¬\^‘$¾suïã… qsÂÖƒ>Z]y6"m Úåör0_^ôW¾OdáewåËÞödW„Mw p®®Ô3ŽŒ¸¹º2ÁCdÄÅ„ Wë,ÈÕQ‘g6|quݘ› qsÂnô¾Œ”¸kdÿyñ›««¶ ‘3Û“œŸƒÚØ£QÊO1a7åEFܘ°8šÌ:ƒ‹«¾]‘7:ôÊí9âæâº\c"%î+ ΋ûáGWºruEàaö"Wwîuï,ÈÅfBÞÌ‹+bןüÑ“«+΃œ¸ŸípäÄùêÛŸæëDÞÖècxÐc¾Î‹aΑwÝyƒg„GBmc#).¦k„ÒGÁ™kkxÉç•®X[ñzW¶rÝÜ s×)qÏÜT¬,àù 6ÃGž¦üIaló`$£l<>αdˆ± ˜ÃɃ8W¾ŽÛ ɃãÌf&Œ¤ªl7yð’²Õ’Ç}Ë‹„<8`FËãròàÀ"Ê:ɃãÙ¢Já,”ð—88°¬ÞÇ÷‚¤¶ÄÁñ2.Çsk×Jež„ƒÛ¦œ¥‰ƒòÉ%ÂÁ ^| ßvå$Ü,E|¿E b…dVkâ Ö^‚qp³4 qpÀU)*ÂÁÍ:YÄÁužGD:û½ãàÛÎ.Ï+â ’¶28&q0rÁ2{gâàx¬K£›3_lReâàx¤œ4Çw§ÁÍŒtòb¹z[Ùì£ËÕû«!£oÒ`¼N:áæö ÒÙÒ$š4w#®X®Þk9Œ%i°_+i0îGaÒlP£€4Øi0ºKšA+O¢­~œ0ÍHà&–«#¬²SÄrÝcGÍ8ÀYŠ! ްÊÒCËÕÀÞb6 ƒí5£iùKp£=)apÀ ®‡Iƒ;O®% ¸ØåÇ4ø¶£¨mÒ`;a" ÆxË'' ¶ÑE…RIƒÑ_W§Áxô´o‘ãõFƒ1HMHƒñ#’]àà[Ež`ÄÁÖ_ÄÁLsœí&¶GŒvò€8ؾ1äÁñHrœ8Ø«$F3OÇÁöjˆƒíRÄÁèöƒ€xç„õG†8Øë$ö:ƒíí£J~½’ÛŽ@øVQfa¼âUaû°½`a´“@C Œ·÷°$ÍleI„ÑN®r$¸å<´#¶‘0ÚÉyD$ŒW,¤íèQÄ7‘° !á¶)›3‘0êä1F"a|¥ïŽ„íR‰„q¥\†‰„qÇy–K$lON$¬Á$"l7“DUÒ3CD¸Y<›HØë kí!F„;"á&ÍA!a«B"lUWXèM$Ü%Vß‘¥üGáà€£ Û8¹¼2}˜p0æÂÉ-¯œAÆAtÌÈfß:t62¶Û}´¼^Ü¿ Q'Öá`´Ÿ ã ;O8=seÉÔòJA/á`´³g;ÄÁºgâ`LNfô0ÆG;7ñäÁúö‹ÛÛn[fZ'¶ÂAO*â`»á`½râ`}5ƒ5¼ˆƒí•“Û‹ ök‘Ûµ’ësgl×z¸¾ú~ă~pò`}ÅÍƒÛÆÃVñ`¯“<ت\^•…K•°.$$ô{úÊ"B_Y@èû7Vɾùø¦›k‰ûă¾]ó`+!êã!lÏd¬_]©?:ú¹ŠÑodôq‘$¶¶F­¯÷—üü#‘ŸoÆèWÍýª¡Ÿ›!ùùo_5Bðs Ÿ ~¾ƒŸª˜ûܪÁ¯~$ðÔ+ðs3â¾* öÕo„}ãkô/„|.ñÉŽQħt E|UGħf|~Ÿ2¤øüñ^ýFÀ—7oÚãŸb½ª/Ös“B½ª"Ö_³Ÿ;Ì W?蹎A¯Jz­„Ki•ôª„ 7¨ÞP¤—w'Ì«óøÿb¼j@Œ×J¸Šò'<þ)ºs}Ó]+áúY%»‘-Šî1˜&ºÛ©1Rt7˜‘£èNÉI ïüÕÞUá]•ïê7Â;•üJ4»ÿbóÝß@ZãéÂBfJ¤ÃÒ–!_Dº¹[W„6=`ÃǦ7nXÞÒÎF›Þ„NõǦ!¤\ÀdÓƒÛdzíȦ‡‘5è×™6=ˆòhÒƒëg^\KIJeÒ;!÷ñãïÍ¢÷(äE=TÉ­¬ãþ.ùɤ×l…Šû›Ê ¨¸?¨Ó¥¿(MzøÊ²„q¡QW\÷^èúúyNoК¨°?l+“8öW!t4éA~lÿ)ìO-ˤ‡µÕý<çØ”yZ&=(ÄÉÈ—&=Œ²óãç9¬T*“ž±mуçóüDýSªb4é!ÜÝÁnbº‘Ó¤‡ 9ñV::oæ&šôÎÍ™WiÒ—SÀФ7.+ØÑ¤7 ÆDè4éA,„ÂW4éaa¢ +MzÂ2é j÷О7šXRÚóðe]I{‚^‡$R#`>R ¦=ëÛ’ªMØóвDc²ÖÍО‡Q¨äiÏÖצ=¯®$ƒÞÀ–©{yö:´è’eÈò©$£vËÜ)æÚv×'æꈔeÌJÎNvsXÔX1à Hó×Jó7x)æo@4¡Œ1Òø‰Wó7,ߢ˜¿vñ ú«;VÐßnm3ýA0?n úÃP§ ’AYŸ²„Aø^OÔ_µ¬¨¿™&Â^º¡àãǨ¿ÝÚ;Šúkí0ê¯æ«¢þ )H§NFýíÎ ¡¨?dŒôêŒÈlËFG»(yš›g¿6ãþÐ;££Ý„hPâ²âþ È8:Úµv÷‡vWǸ¿aÙ]Åý é½*î¯^âþv{s(ðs|ÿ†…²ø×.~KÖCŠˆ ü–.——'J’ø‡.ͯÿ†…Ôø7° &ëeàªä©”ÿZ ÿv«o*ðS„%tól% ük—¢›ç°(Ÿ"ÿðU¤‘‘nžè4ó1òÏÓÈnžx:?‘Cjðöó„:æLhcä_d5ì~ž±:æç9¡.•îSŠüÛyô1ò­¤AD‘oéN¨È?,ûÇ'òI<Ò K‘íÚtõ’Hv例[·ê¡åv¡â"^.¯û’Q;˜nÒ›C:NŽúkÍÐÍsHfÙQ»ê*ê{ºù‰úÃN˜Q(X,X¢qFýU‰¢þüµ›gµ£¨¿]Êbvó|g—œ1õ×ZfÔÚ;X’Qõœró¬ÞQÔê1~™fÁú•Xy+>,bùéSIô›2 ¢™‹äÇ£V½³`|Û; ¢?· â1®ãϵYÙCÖG¦zT,Üä*²`u—XIbGÄ >,ˆA›j3bÁÈ3ÿaA,5ÙÉbÁÈ‹þ£¡`¬=? úsh@×ý}4V3A\h}ô_°ÈŒïË•õRð—@ð\Sn—A|‘r@ ýÝ-ý=¤õ_$z" ¬îzòÑÁK¸°žò¡¶ü‹ºFh‘BS ÞÁAO®«‘”£A Fõݬ~µÖqiÅÿå²z ê¸HüEŸü9]_â/§üš­þr)6Òê/õ+©¿hÒ‰‘âéö¿6¡ÄÈBsÄ_ÎÁìN%þâ©`õ—ƒ.è9˜T¢Ô_Úz¬þ¢õ§Ô_æ·´úËdÚR9F‚5iíØ·„[#éù7©X•t‰ì?þ]ÕRMZ;D…Î.<[%%a­²±­’’°žpó]¦»JZ[,km¹¤ÚŠ 4w—é®’jKeÕV•ü»¥µ'ÖôË¿SZ{YSv?]AÿÄ¿KP÷÷c!ŒWððhrÃ?+ŒlÕ?•Ü”U³ÝTSÍvS®¥¦Z%5UªÙjª«f«©ªÅ¦z%7eÕl7ÕT³Ý”k©©VÉMY5ÛM5Õl7åZjªUrSVÍvSM5ÛM¹–šú¤µç»zopù_VZûÏ|/ÿö»/߯¾Žûå¼ùù‹ùëyóû¶þ²¨õ™4àÿ¿šÖÿ£>:hõ·îÿ¸«°„­Ç?¶vœfBOÜsñ ·qézbbTëœ$|VÞýLàS¸Dd拉êíÇØNtÆ9÷÷L;…ò¿;»-í2“½%'œq‚>ç^ sÞèÚç!RÍĦï“nØÿ¾+ -=¯ÛS¼Ç¸øœ‘Â8¾93KŽH<•Aá!•=>œÁ·ï:rçv5Dë¸K²`…°ÁŒTòÙʽµMFÞvœ Ñ«}ÎçÈéM³ù.}ÀÇOI LÈ‚†ý}•{SäÎ:ãȽ颉x—Õdß’'ÅD÷4í¾¿R™Pg[¡6|Î)ǵ§R÷E5Þ÷_¡+7ql·²™9·KX÷íµ#Ïg/írŽP^œÈÛ•~ø uR 6O¤ŽŠóÙº·ûIÙ_˜PòÂO˜LjÃ1‘Æ(æ*z1žé›â|öfòõ·äIQd/‹‚±rª^—˜°ÅT½O5|Œœ«°Íd3Ç“sµJp&…®Ê£”\á>·“ßÝ;“pǵ¶üÕÛ'“•_­û¾b²VÁsädõ[y`µ©üø<9YñQŒ+=P*åÙ~€àB³õý„ä÷1-g·D*Ú‡úÕlùö—T´1[qÒ–u®ð€ˆ¹gË׳Uzå”7ùXˆÿ»îœDa¿ž¡‹wä`Ë¡+ŸöäǶ]9[õ²"íÙž*RÑÆl­*ÐàÍflež9[³ Ç>%fëIÏÈE³õL]¯cˬ~! {f•+×Uk‰ÉzR¬,rÑÆdå3Ð9‰¹ ã`ÞÞ¾ZQ%>v‘Š6Œ)n©h?s5RÑÞ³MD¤¢å\e†·HF»Žö©}×à-eºS4"|Íb®jˆL´'ëÄ:™hŸ;K6–äÂZO‰L´9WÕcqaÅz•¿º¹°òkýpaÕÊ©hW®‘ùRæÆ…Uú呉6æê¼rF½%\Y'íÄ‘‰6æª4Ø#m®¬W¢[¤¢•õÜrc" çŒ³L¤¢å\u‹++Np¢çâÊzR ,²Ñ^쯴óæÒªE(²ÑÆdõ›86.­2ûF6Úž´ ’Ñb²FÜx$£…˜õâÑUä¢ÕÒš÷wÌZZ³ààÊŠ4®ÙÊÉ•îŠQpqa­V..¬0ªÄ›AB”8Ÿ]4ð!ÞXçÎ:Ï–“¹ß³`ÑðɸvOªRÇW?ÒÞÔùΉD+©¨OõùHISõX¹“>ÎÌrQ¶ùHJ›'´ôp<°û¥¸» ¸°‚¿¢àê) "íÑ·l‘öé=…­oÌÕIßÏÈGsu¿ØS°SöB##mÏfÖè ö~‚ i¯053+ÏÉ÷fä !üÏ$ÑwÝUùó«ÀOôÄ™RœˆF>ZÌT”ä°Â'p†¥™ÖèHI{ n®ª;å…"#íúQßoWU¿·8—ˆgªä 7Êç—Ä#Z'þ¬’µðˆ/{@ägÍ]¥¹WÁ€°T^DÂX¨?žù«ÀqÏL1,þH›ûtò߸OzQ‹ÿ""w/ä¿·DOòßÀ†„H•üWÁÎ⿊ý†*õÊvK€êÃù $À·Jšµ€|Î.°TSKêÔˆåÿÉŸ·Ùî €Û®ýŽÐ’RÀ !}Ѳp›”ý6"ÔE$Ì• :S#ñŽÃ_þˆ°ì` Œ…$K`» [ Þ pË]ñ/Â&‹ÿêÄ¿êá_X)³ ñý ’\¥°yÚ?ü·LleþÛ®œÐÆ¿m<ùé3þA l~ðoƒ5,EükuˆÛa‹ÿê9ŸÁ,ÿm•ý͸V¾Lòß'ñx*ñž*a„ü·Ž0ÿ¡»¶üù©zs{+þÃý#ÉÛ;Yžÿm}•̰çôÿaØìI„ä? £™ÿ6¬ÿ0Ôóe‰ÿpP”@HüC.á<ñþÁzûxñz'é˜ü‡7Ã*俳ä?Œ.Þù7œGÁÕ{â¿Htüá?ËÁ™ÿ|ÿÂ?¼ÜíƒVž3þÕ͉ÿêE‰ÿêE‰ÿê~ŸVž—‰ÿ {÷d ùÏ:ræ? Ö™ÿÚµ’ÿZÃä?Kã‰ÿ0ü¾ü‡ÎIžÿáŽóc(þ³º ùwœç7â?¼]Ö!ÿ¡wž„2òßv2úÇü‡ »¼8ño»hU0þáRù†…ŽÔ3þmØxgÃä??„ù}q'`%ÿmãûÌÖCÿYÐüç9oþÛ&ó‘™ÿü: €xð〨››U äÍþF=¡ €Vg4Båñü =@zXñäqnaÄC$«/D€ÑÙL Fm^ˆèI”ˆî¸²M R›'’ÿð*r#-t¿ˆÿ¬iþó§Ùü‡¥N´ÇUÕÏ,þ«›ÿyŽ™ÿj‰ÿj‰ÿ0“åÅþ°™ÿðíÈ·BþÃKÉM»ø¯ùÏ —ùO”Æ?OCãŸW2ãŸçñÏk㟥8ç¹ãþÕƒ ÿü‘2þYÔø×Z&þÕ þYPÔøW}AüËm‰ÙÏ˪Ø«Mö•ØÏ_:³_L½,9NOÔÒ‚¿š¨¢¿šð¢?Ün˜è¯Æè5óW¤¿ûÂ?Üá•FþàHRÿùSgþÃ2©Fü‡çÊ)#þó~ËüWcüW?ñÎ.<óê`=·°>t"À~"@¯R&@+Ášk ëf„€þ ˆ[3$Àê>!`k˜¸å¯! v•R"`u°¾²BÀúëó" O¼>"`¬q%!`}^„€.ù ÒÕ¦À'DÖºN ´¤(0öB³SàÜ1ç¾fÀ“iVl„»ÝAèËåj¿(úf3 #Ölt  Í€©'âÑ ·½†Á4:DÒvÀý¦ä·í€ ²¥!ËGîèdŒ%/•ˆûKä!¡¼6 eëâ¡Ä¥1:vň€ÉÜš‹X1ëGd‹nèè*c Ãz-4"€y'õ%"`#MÁâÀ.i>$bIÌKÑpAÜÝ•¦B‚ ãÿ‚þ‰81ª ââ@D¥äࢄôHŒ8•$Cr ü-Ó:"Döö±/Üošáë9hõËÕ {‚ab ¢% ·ÄÀ~ gÄÀ;ôp?e.&b7”ØE ¬L Ľ¸¯ÔÈ5î„=âŸç—ñÏ_Oã_Ý›ð=u¹žÞL[cü«ñ!üS8¿é?¢y’ôç0iÓ_»é¯^“èáIJ¤?GˆñEÈ-:ûcüÛo™"€^Þ €^º €5Œ€nû1ÿy—h´²†ÐK¾°¾5@/&@ø‡™OAü«1+üÓOô×nïÑšJb2ýÕ´ýÕ@ô‡2˜ájU›ø2m'¾ãÊÏisü¼2Ö¥?%il»²z& Èîgqþ,ìoâCZÔÜlˆøœùËÄÛA8‹ø6DtþhÀWæŸó­ø—ü!àóA¡€OÚ$ðµÉð·„>„áåcðaͧ1Q†¿Aq”2ü)ñlþ†aN†¿qÑjÃß ¤EþlͲáÏ÷kÃ_µ#Ãߘ²óÉòg{-Û™;[þªaþvê¹”áo§>šmuÊö·QxÈW‰Å|Öpò…yöìÈ%YÄWQE|o‰6ë$>§‚ðUÂ1_d”½;ñ…%8]æH|áò,WÐ;e ±útÏÏ·ÄÄÄÈ(®Ó2‘¯× äk “ù¢ÊÙ˜¯DÐÅ|¡Òž}Cæ+¡s1_o&¡¯Ý1©/êÐ2™Ô2æO·üQQ]È?I‚&ò…†9 V蕯’À÷>##â|•7WÀ×ë$ñ¡Îã^ä;Î#îÅ/®æò)}Ó´DÜ‹å\‹ ‘/øFj…*á°p¯—$îµ_‘÷Bü=¿ä½JJ,Þkí÷¢‘+y¯·œÀWI’|mpø¢$?¾ãä½ÞLò^ ³<¹IÞ‹ipt—ÏæÕŸ¼I‰àC©| ò^Éú‹÷zÉdXÒIòï•ä¾€ï-¡¬…€¯D_¥DðUâǯՈ&ðÅýäP#ðµ™Aà‹k}€¯®Nà« &à«™@à«ûðõÓóôê6¿Jå âsn_å,ðõføú¥øúC%ðµ‡"ñUŠø>%A|ñ±IKÜ +Þž€¯&/~³±€®4x­ÙL_}ÃD|íB ®4çàîžÀù xk |ãyW;>P_ÿU_¤™˜‰X |QÒm~­ q¯¾Û½V%i¯¦‚h¯ÿ(q¯2\ˆ÷zä½6ŠÈ{5„É{Ι)Ü«DĽѽÊX!Þ«y)ä«DB¾ÞÎ䂪õJÈבâ<3DÈ×^?‘¯Þ-‘¯"_ÿÑ­•Ä×F‰¯¼$¾ú /¿š³gü‡ä½ö“©ÅÔ\LáG•%§Óñµ÷EÉÕq¯·³´˜jx÷ú¯÷zËTÿЏ×K÷Z÷ÚÕÉ{ýWÉ{‘m$Yˆ¼%yª’¼×n¼Wýuê4"..ªõ‹ÅEÕDàë%U·Càk·Kàë%;U÷²$¯µLà뿚\T«$¯,ß{?‡ ‰WU¸U$&ðµe_û øzÉ“«ª¿÷$¾6£H|íÓMâk}ê`_%œù…|µ(ï!Î×(Ïs^”7·w+$¦ã¤NQl×C€ëÞ½;'¾!yN.»`*£åDyÐU Q’òŽmû)¼ïýóˆÞá}ÇànÁá}—°Þw-™×ß·2År…÷UÆ÷­[±yŽï32¾‰®BIyÁ8´ã!¾Û½¬ ø¾BZß7†|%ß78FMyñ9øÄ÷ásð|ãû6…öˆò,X`ʃVBÞ°(¢ ´â‘ò¬°`ʃÛýÁ¼sÊP"̳ċ1O¢<‹ß˜ò,»"Þå3lÙ“î… {PnÈÝ¢ {¸ßd&öÎi£aÏ?6ìCÎr2ì×E'2Yö0²îO€"Ó:-ËÞ±? ¤i%ÉÍ2íÔ4íAÅcOˆ£iB[÷ðÄ@ÏKɶ7!UÕm{¸ÒÇÁƒcÿøµšöÚÍж‡uîî˜VùdÜà ›{}÷ ÛNzÑ2 w4îÍqÊäFãÞ¤­Œ–=Œïot$PÖǽóØt”"ÓVî´õ¥eÓ“–=DžtæŒCH(Ò1h–½PVÉfaÙ›±1*Ò‹…ûå)$e4ìU£,{xGw'½ 5ˆ­“^¼ü´Cɲu¼<…e!' °£iLÙ»2íás‘Ö?Zöê©eÙ×ë¡+'Ã0Ú³-{˜ Ÿà¾z²ìa›Ö};ѬÈ/!±KK:”a¡œÛÇ·ª…«ƒÞ[b‹! {Cb²ìµˆ@Zöð>‰u´ìµ«Ó²‡çÊKѰ‡¾ßÎ2LHJÃú&mt´ë¡‘Œ)¡]o>ôɰ]ïí9{Ò°‡a/êúö D´Ò GÃTÓáN†=,xé &ÃôŒò _†=HÑi”†=”¬e¿J×9Yöp-†éѲwÌ]V;Zö<ŽmÙïØrZöæµ+ަ½™ƒ^|k4HÓZÉ;ÓDLw‚Ÿ¢ûd™TpßÁÓ [ö %wÏ\TÛÇ»óØìaYöP²}¼;qñü {hæãÛ øHú–]²šƒžœiØC+´!Ò²‡fž4þѲ7¯G JËÞ\2{Ѳ´”wCËž',{3Ý:êÅ,ÇšL{ØÎÌŽz1ÖæÇ¹;:eÒº×JhÝ‹mí}¹¨¢¤UY÷ªeÝÏíóÚ¹?ÎÁsim¤yßô+˼‡’§Ã^löžnÞ›—L‹2ïA/6:Í{Øæ~¬{x„d\Y÷ ­š8-ë^MMY÷p¥çcÝ AÖÄFZ÷Z ­{þÈÛºgÁ^[÷ZË´îÕ@‘u¯žSÖ½ºgY÷êê2ïµvhÞCò‹ûcÞ‡|!iÞ›SH#ódײü¥ÜûãÞ9ñ‘é¼$APøàÒEÇRø¬[>é=ÛÀWDø¼ÞÙÀW=*_}Odà«,_MøœÜÁ>¤Ç ºÑÀ×®•>Œù<Ä’Ok« |XËÒT'DëÒšGû^м7äXrLôÿ‚dµM}+¬’ÝÔwjRΔ:,çÎÅârîœZ¹À”o*«Q1à%‡+3àÉØbÀìï΀÷Á «{øçãÛ E”õ1õAwv|4^®M_B`û!»ñ«‹¼@«a}L}ˆx=Ë·³ôØ çÿ“¯Sì!ÄðØI…¹\­í¦ð ƒŒÀ7‹®+ ×;ùNšþëF¬¯Æ‹•/„€ëÝÚ쟿kžΜÛF! ¶ðDI‰¼X£B"/ï§úøDùaÔŸ‘ìE~4DÿnŸ ¿R“±ÈË)x/‘—+­ñ"ñ# „×'ȪÒù#`‘¯ðÄ"ʈ> î†LH„ƒXR+ °Ø\x"\ùã܉ª³$Bqÿà,4=ƯµK¬û¢Ýë£ñ™êmB@dwÊs# †IÖ!âæS±‘ÌÛÂÏ™ÀG ÍOŒð‡²*¢À{—aN k2)ð–jŠ)ðɦÀÛŠ.¢À5å%J ´T‘)pIÊ&(ðxNGôåZUWbwš7" ”H®)RQÉX„@Èç»-”ÕË8%K$ÄTc”!ð€‘0Û®ƒ=n ¼wë‘ë!E±É_‰«eRàE= S NÈF—xDhŽ,a Zy>/xDEb`³!ê.  $^tl! ÄYÇÇ¿³†‘(°ŽýD¸F¢@\œÞœ¤ÀêQ`u©1êÊEðžJÌJ A~à…ëäWïW ˆkÝä×:K XoŠ ˆñ÷‰ñ;rx?Ä'B ÏÙ þ&[ !×MÀbT§+œ ðÈ-bƒÀê=Aà1Ÿ$¬¾ÖƆ%K5®¸éˆXwHlUØb1b.!°ñ£Ä0B Fcº k‚ ñV¨C×çÇóS è´°f³ãFèN Îõ(Î’èžÿaBÝއћÇ,â?[ÿjÿ X}}ðþóø ÿðá¹»¹¯Ý‹ðm}ÂûP‡1wÄ¿ºeáÞqž'Yáåh9­ðâs5á_ûUâ’íÌþÕדü‡‚3â?èy§Ù]ˆgÈOŸЇ¸¥¢;7IùZ­úá´P¯ÈȰšúªJºêôÿ®j©Î¿¦V}.Œñ®åZ%¥ ­²Ò…­’R…¾"­RW¾®’jKeÕV•´¶bçÖ•¯«¤µÅ²Ö–KþÝjÕ!f~ù•Zõï´¦SŒú°œïTø jÕ¿ 'Œðôh ¾?+Œ˜”²êµÜ–…¨ÝVS¢v[®å¶Z-µUJÔj«KQ«­ª¥¶z-·e)j·Õ´¨Ý–k¹­VËmY‹Úm51j·åZn«Õr[£v[MÚm¹–Ûú4«!ÅÿÏhV¤Yý»ôšÕTïgÍêÖÞσüwõ¾šÕ¿߿׬þ3_Í¿ýîû÷«oäß~9{~þnþzöü¾­¿¬Y ýù~m~)ZýöƯþ7+Fÿ3åê·òÿüÏ÷_/+=Mhºý÷_Ѱ~«ÿS ëVøAÃú|©?|ÔÖ ­4{B±Œâlgë 5¶ÉfoÉ>j÷I‘”óØâ´ÜK:¢d?ÒIí`ìê ó}8©Gž£¼%ÕÆ;\s x©þ\û'öP¥8R‡ùŠ¡qÄ€ìóH ´¹!ÿߌ’ë aŠ‹[¦ÌÂOêâž8@ØÊ~å®û„vuij"GN^æÑ‰cêgBWô:ÏLr9#×NÖÙã›9wH0ŵßñÅèAz-8Cëу'ÒäŸ}æT­:cÏ©:Î4µ½%wNÕA³Ì;YΜ«îÐ'¥˜"wmœÆœä5û» zÔÙyœz"â æê ¦ö‰È›˜«þt<÷–sU_Êxß<œ>$M<Û‹zçîÌÛ 'ƒ _GïÌ áG1Wõ.ÄPÅ\Õ›¼ðq¹ª1ráûsçWY°rªâhdÀôÊ!2òR¸=œ(µ¥•,JîüÕZJ…阗ºœªïç6/õŒœ©ÕÌóäLEôWü3U/Sìa‡1]®¸±è ZX.ôîŸñüRɲJÜRÉ^?*Sñ™d¯ÞÅøÈÄL­’ëÊ™ºßy¤táSy|:4B[×§ÎýpªÒ‡òŠL²+——8ܸ Ð‘SÕ%ûžSUóB&Ùœªwž!\‘Iönüéغ"2É>ýI#“ìñiùŒuÕ«æ™dÏ{VY\X©u~E2Ù³ó þ¹°ºÎÃ…Õ%0‘çÂzåsÍ «{ç]mÒÿ{11ÅÉd‹f^pþˆÙê[Žd²+¯¦é Ùdc¶î39¯yreu…×ÎÌùsóšWÖ}å×ÙdÙ=a“º"ì“¿Ê‹?\Y«àή‰Ó¬+RÉÆÿÎDœdg`¾.©d¯~8ݬ,sE*Ù+?I±ú^81[ ðÏì©d£#¨usá$8¦+RÃçÕ/®¬o×<ÙÎ G­~­Å•u§ƒH¿u_¤’½óZá+q!›lÌ×¹E¯È&ûô–#›lï-˜é8]ÏüÍäÂê3V?e䩼~ÔíB"ÃP{zh‡¹"—, ö­¨²áÅtU.û+rÉrØÄ.èBžÔ˜®þxD.ÙÕ{"2»Žv‘Köî;×U¿…Ђ¾ûp„þövô÷©dŸ¼¿¸áÈ${ôJߟVN.«o+gV¹rYu‡G&YTy‡av2ɦ,Õ•+Ù™dsøÅŸÏ剚,òÈòÄ–óBÂåm´ÅïŠ<²«?òÈ>£üÈ#»>%—U¿ÿÈ#KÅÃw‰<²9Qõ”‘GöùÜÏâ²ZuHöéï;2ÉžY¶Ãk=³)3^‘GölêÉæTÕŽD²Wo‰dïÏÀŠD²Wÿ¢#‘ìÚ?%WVOy$’½F(q¸Kÿ¬ŽuAàßå']ó Ø§Æñ’!p]ŒÎ0®EgCàzva!!yy“²È€Hš´g•dÀ—7yN(T,FAà¸'ã¯Ý@r |!•þ‚À·Ê“‡þ¤À—Zùƒ8¢Àˆäß’ù’dz3‡¯(0Ò<僓6+op±ÊýXQà[rÿ–?J HËKàL Œ°½ÄRà@¦Þ|pRà€¡8Ÿ“ø–h‡J O¬"¾uw¨IÝ" |«L>ç¡@ FÜiîÿI!&NÂK ¬(Q`œSæe-Œ`Ú¼52`ÜòN’#l7›M¬È?!àÀZPø0¦Ð 'F|2ð-¡4–ð-¡Ûœ0B£¯Ž€?“Þ£™#«ðì)Œó“{A2 ãø…€ÖP7¾{ü´mˆCZ0Á›’9„‰€!+æ/!à@öä+ñ)°õ0ê$¹%FGìë† €µ#Vĵ°Ä €Ö¯¾UèL ̓¤0à€‡ÂAâÛ3ªðIa9!àÛ FÀê>"`Ôɰ›×Þ’î’Ø+oY{’ —Ê@Œ&%&¾í,Ž#`”Œ¼Á$Àxw9sãvòË"Ü6æR|+ Á™±÷Ž€Þ¹ ñr'º#L€ƽ<Ù pÛ˜HH²þ+ë[DÀ BÀ¸Á;¡0ð-¡£pƒý>Z¢åùa@©r[3DÀÈ )0ªœÙJ2 ß¥"»‘q3wÞL2`ˆ–s³'ÄíœÙN `ei0¢s3E¬¡$D+IŸ$Àö$@T‰ï„° `]ÉÈÐè@™¾ ^Õ•—"⎠nÀÀêc _•ø¯¶ø—J ¶f^‡¼G¬÷-¬÷$¬·"luH€u!`» u²`k˜èW'þ«¯ø¯^¦øýÊfÈ5aĸã•FþCI‰ÿp-Rc .5€6¢ûòÐGˆFòˆ‚_Ùd%`›«Àš Àm§ó­°Ý °Ý0%Ä;`½!`}È„€~*`M uŒ€õfˆ€5ˆ…€õ•"nF!`=¸°¾ûBÀvíG++>L8‚@\êIx#V2`k… ˆ+ÍV÷‰k’‰ñõ#»‘ë5ˆëc,¬Ï‹Яa…”€6lBÀ¶Ô kT ݆°ÞаnEX·+„sež‡‰Û¥H€nç/ÈX>Ó û¾´[Ùˆ•qþhøLž`kÃB,ÍpA`éð‹çö0£¤-û¤Ö„-uð.S &s»)S •e ĺŸ{~™Ë [à³ de <Ŷ^‡p‰¶@¬½“–?YJé°lÒÇ.[ >8 k²J¸ŒÞ´1Ñ(,¡1pl£k[àØéÁo[ –Òº![ t´GÒ$mÖÑ–-p<Ô°-p¤ß6)p 4m32ÈØËüø{³J°lÏH¯²^Ô@([ d Ë(ià²ÚxT¶À]¶@c”-ð þCÙj5[ Ì­¶Ζñ² ÏË(Ü‘-pê$Ŷ@ø§%±ÉH‰¢2ÚÖfc ÎÙ›10•D>¶ÀœŠe Üip·1ð`Hd¥ÛŒ<¶9ÐÌ6ÊdÜÌ Š±9pËÍi± ¥•Ë(S¤Ìïø#aÊxPo¦Ì¶A”9PçÍ6ºÛËè_Éèc`›9ç˸1§¬>Á·5p>2ÑÙ(“’­eØ“5Pîe ô Ú¨óy['ul Ä7%¯$k ¾7e DÐ@>ƒ¬ó0Ûˆ7•Ï`k`Yèv.­¨›È–081:r´—5P&[݃e ”¡ÇÖ@}GË8x4ZÖ@í3Ê8Κ²úže´Åœö@. et#¶Úl{àxd£“=жpÛµw*{ ] ʈ0ãD=™«Dæ@¹•9Ðö|›ßïÈùÁA/“eD á‹«Ëæ@_Ëæ@ùbØè‹ÛX?¢Ap0,° ‚î.Ûh,‡Ý6ú cƒ ¿Š6Úoƒ ¯e‹ Â&ÁwT¬¯IÐÃ&Ayª”IÐwh›`Õ¡MÐ}Ûý"dÔ°°IÐÞ"6 zXØ$¨QYß›IÜÚÊ׿üð`½=ltÿÙ(èg²Qнe£ ç«‚õ+mz·QÐëUŸô4lFA­Na,료‚ͼg£ Üdlô¥mô{)£ %£ ÓFA?”‚öбQP%ÿDÛº0𠤎Ûý“-7°¾¸²ü §v4vUœ|9„BT=ëu>Q¡›@Á¡ã⾬{„&Ù#T9`íZò-M tæDc -¼Æ@äù£õˆ]ÊñÁ@„’Ĉ00)‹ˆzwN­UÜ ‹á¥p°„.¡ÞcÛ%t›ÜQÛ%T‹t¹„âT-/.—P-ÊÆÀ 6ÎK¨6Ì¢@d.£gbC•$‘J.¡Úkn4oŠñˆÉï¢@{å [Bà†óú,!Bto~BqûçÇ!´H¸=ÌhoÜ– »‚@§±5n7£¤ €˜ô>¢kk„@”Œd³„Àm1$ÖˆAò°$Ï-ã¾ Û:Ås„@4“ü)s ¢=I…<¶¼Ce,_hA "cÉP„@\ê¢Ç–Jgl%„@gÕ5:\y„FÁ*tQàEÝ•XÔ”‘—Jt&Os 3¿™ÏXÍØ"¨´A§Ž5Öµ‚ÎúkÄG‰†;‚ óÙ•IP¹ ‚N´kD–dbA9‡S¨ÒP‹ñáÊáo‹àA‰·ä@g›-‹àÁ%s Ò¥[¦ ‚p"H|#nLJ;Ú ˆ<Û÷טÛÏÆ€ÎÞ[æ@@Þ‹¶ŽCnª²ŽûëZ7c# `#9ËFÀE ±´öµj3\VÀ‘)-m^²€‹©ò›Øè`#àNÍÈ2â„í}íW2H¾F@whYïü~Úˆ Êùª÷lôÝØ¸SÁ²Œ€~ 6jëQFÀjÇFÀ“oÓF@ediF@:Ò hSqYéÆSV@ ¬2ª@FÀIN›ð CÛè —g`Ye” õÒÖÍÖÊ“ò–vn‚<øvå^ɇìžiÙÛ¸ ñ±lêŒîïùn-‡rEòvϦ>qlêÛ(_RŒŸ«¯©OIùÊÔ'E›ú|Ð.SŸOÕmêÑ·°?R…ýÙ,aSŸÎ¸ÊÔ—Ž¥ów‹ÌdçÛ¨Õï©O´^„§ x¶'ðlÁqÌŸM§<Çá!}YýùĵÏžm…xƒ~…xSà(ÆKå·ãÉøkƃcn¶,Æ»™þÄxæ#3Þš2!ŠñŽGAˆbå§WŸvŽ4ßÉñÃ|ÇÏXáÝ~+šx§Õ¦ðNËcáܰóBÂ;}T ïüÆ»ZÖ…wÊFVx'÷–Â;}èLwø°“å´$Ýú¦;-REwnFpç7Üí4ì î`Í îôÜ„;»Õîì¨d¸óJbºãe îÊ2(¾Ó)¾ÓCßyý4ßÕ݉搜Ü=¡È™,iwOydñ”®Ï«·ÏwhÄóñþóA< €b¼*!ãÕ•yÞýòêG‚<÷`ù{j‘7ä)ë^Až_Ÿ)ÏýeÌó3ójqnŸTZnœ§–Íyû~‰óÜË=oCzû.ŠèU‚ y=ÜçÎy.xDñ0Uxažª˜òÜY¦a¯ PÒ^Dö<=æ¯Ö¿ mÝL}!ö1õQ´L}—άMƒ^)eê;–"ïäñiÍQ Îњç¸À–¾{I’E8-#‡OË­”Ã简=RàÁlˆE–I*CqQàÍÞ/ \Šè2ž» r¢ÀɈ8C ²j.@–¿ç’yPþž7—ŒÏ”ÉN¨ÄÖÅJ4Uøp¼.!¼9ð9rHwÏmc”_쟚Ò/—¢áJúåâμ¤_ühwÏ&C‡”K1tåî9œUîžê˜’~‘KI¿¸Dîž%ë"wÏr µôËùû‹_å°»'Òf|Ý=í+Yîž®#wσ驺»çNì“GŠb"åî‰ïÜÇÒ'i&ýB?ªòö´—£Ý=˱Tîž°oôÀ¿®â"wO'ØÛÓ.¬åí9ÅUòöôäí9™Í­ì|ðÿñ÷fæ“o] ¿È­{{R™FÞžî= ¿XæÅîž¾; ¿øfäî9‚ti¿èeϪ#Ïò¸”¿§%Œìï9/ÅðÉßÓ#©û{®¯¿§_Œý=íÜÞý=S§Éþž5’¿§Ç@ù{nrÌÜ>~Vö÷Ôý–¿§¼ßËßSOPþžºPù{ªoÊßSúü=gÆñ–»çÉžž~®òôdBÇòô¬väé©Ï5=='ò›§çý³ò‹ßŠ==[ VIF•§§ý:íè9~û@`û=]Å~žjDnžU 5U ¼<5`íåéž²—çÆT /Ïù1õ5¿Jzyº¯ÊËS#X^žZSËËS{Çòò´s\÷ò¼?Qõ åå©„½<çWó¥îÎ.žº´]<ý%´‹§ŸÀ.ž~„rñ´Ÿ¥\<ý·‹§;K.žÖ³‹§VŸrñôݬZTyí»UÚïZTùTòñô3ØÉÓ·“§Û±“§»ØNž¾A;yú~ìä©jOߎ}<«D>žþ‘\<ënäâYw|— Úc ÿ¾§›ûÊ'¬\<óyìß髨¿ÓcÄþžöïÔ†¤ü;Ý åß©ÅÑþzÿMÚz!ÊG2õŽ8ó¦ÑÊ‚.Pý‡¿ªJªò¯éZ/luî~*)ýh••vl•”~ô}¤?J»Y—T[*«¶ª¤µΫŸçfAk)‹ZC*øwkZ¯ûÊõ'5­»zõ‰ÕhYù÷¼\áwÿŒº…®ÿQÕ””½,)ûûa²£‡øMø§‡þÂþýSÇ-YËÚ-5-kµäJj©ÕQK¥d­–º’5[ªJl©×qKÖ±vKMÇZ-¹’ZjuÜ’U¬ÝRS±VK®¤–Z·d k·Ô4¬Õ’+©¥Açi…îíü_XçúO|Bÿö»Ïá/¾˜ûå|ùù+úËùò»–þ²Æ5Î÷Þ·ÿÿ©ÆõûÑø+×oõ_i\¿ÅoÓï'êYë?î*,ëëŸk\¯s¥8Ãü~©ì-¸Îw=–TàâB>ñõ_Ȫ=›iv!}wX/äN¼N$à ßúÕ¾%+¬HF“WZgš/s¬éP0T剔á>òJ²-½UîŸ,x¦O§´¾GƒbÁñ7üš¯Õ†ù Ÿ¦f÷½eêë8‰#ì¡LE@g¬ƒ•"¦7>) Óç3Üg*#°oÄçÄLݘ^ì†ìrÌT†[ߘ¡‹}¬u‡_ ¨wxÇ­_õe¹ñ~ö½_:ì:ñU»ØYpÜâ«ÆÜ€7BÅ~R¯¬sMúÚÑ1í†E&¼`èÉ»Y±‡wÖ ÛJX«áÌ00‘0.¬÷ÀyÕý£¤col#3˜Š±]ïD½ÒÊøl‰/FèME–Ý#¿ËgzVÞ‘wöÌóô•ÍP:ìW†Ä«°4ÒE˜Qwä½rQÈ­3] ¬—%wà¼%Ì–u#g\†SM¾ÜÈ;Ëø¥x"¤ 4Ýs÷³Velé°.vLd½ÛÊw#ëìŒ:{šÿïÈ:ÞxgâöYgÑU+sjÝ3›†o`œõÞLMÜ^\RuÏ›KjýèÎ%U=ygñ›‹Z 7òÎ\-ôtGÞÙ+×áøÜÈÊoNwÇäží^ŽÔE‰È®ì`ÂgùÄÞHã¶¶¸#ïl„R1¡Æ¤ªáèõ>‰È;uèy#ïlÌT…vÝ‘w6z‹)ßîÈ;ÑUG~›o$žmwqGÞÙ3o''32ÏŽ>¡"ñìõ-É5ÕAdw$ž:q+ç‘ j½ƒH;ûyOH;ó´¹rE­®AÞÙ˜§èÌ–ïˆê¬¨·ygc¢Ö¯ž\Qñ«8×¹‘wöš?ÊÉô޼³Ïr ½¯Ôi¯3Ï>ýê‘xöüQލ72Ï>mPDÞÙœ99vöÞ?\¹ªâ%ìYgåªZig¯ñLW*[¶§¼Òž‹ÛÍo’Ξ9ªó-¬ðêõ[CÂÙ>»nöé}‚l³œÆ±˜ÞA…9gÃÍãf²Ùê4$›]}ô0×l«q­ßzhã½r¸é&îñÛÙëÝ,|ÿ\¼iü…³OD¤˜½ud˜½TÔ~» ©a‡ô²{ŸH·â3õ6îsõo2ËžÙO±ùºáJÿôY…¼²GÃL+‹&GÞÅsüöÌ*[¬²£·ñŒ¨+PvïOŽ|²WgO| Xy#—ìÙŸ ¹dŸÞ}u«iTØìýÐWw1E¨Nê«Ç‘WÉ­)|Ù?+Um–ƒèô~}Nnz,˜åÖüéb¹㦳ÜÀa.A-anà0÷Ê: sá s6˜÷N'ÁÜ€ÍüÉ’€¹gÀÉ‘ s¡fMÖ ˜”£ÃÜÀŽ~ï0÷–l§„¹·„žr‚¹^'a®×I˜ïÙp²Ü[pæ •`n0çrÑ\”ÜY’47@3Ù2iî-¹ÄŸIs¥Ñ-œ‹vrËOœ‹:[ù‡RWâÜÀyBkâ\\ç¢$i˜8×KçÚ3çÚ“çúÅ“ç¢äÎ’ä¹ïÞÏ<Êã[¶“<% ;ä¹(IBJœk?"εK‘çJÒ\@%‰ëº^!.î.é=®WI {K&HtqeR`]ÔInL k}N ký@ k èzIÝ[r¦¡VD×ë$ÑEIºöPºV%y. 8ÉsýGÉs½Nò\}Ésq{ylAžk}“<íÎl%®žI@urOM «_ èâW¹ $ÑÕ‹èz;Itñ«•˜•DוDW!¢ë%‰týžéúµéúµéZDº]Bºö£Dºv%"]{r2]/I¦kwL¦ë%Ét½$™®ß_2]¯“L÷–0LTPׯžPׂP%O‚TB]/I¨k×"ÔÕØ¨ëêz#uqwI;„º^%¡.êŒä³„ºöL¤º^'©®?SR]ÔÉešT×~E¬ë%‰uÖÉ$Sr]¯“\×î‡\×®E®k3‚\×ÛI°ë׺¸¼VË+—×*¸¹¼âL+/uçòZ×~¸¼º]’]«C²ko‚d×ë .¯¾Ñ®ÿŠÖÇV’h¿Ê-7Ñ®>2B»úº íú=/®¯uõ›ëk]+Ñ®_ëáúªfˆv­™D»(¸³ÊÐúê ­¯j—h×K®¯Urj}u;§ÖWF¦‰îúí,­¯.Iºkc‡t×ëò&™ï°Œ¤xç :ãNs‘ð®ºKx‡åæJ˜#Þ9¸ñÎIŸŒwÕ9»jYxçœTÆ;Œ ì.á3N%Þ9ÏxçüÂ;g…2Þ9Ñ‘ñΙÌwpEÉgÞáR#Ä»ê-á]«C¼«×+¼Ãý$_‘îê…‹îª á®zOp‡žIû‘àžvRÁÃ& wx/{·Úõ–îêÚd;ÔÈsc²] ±]u±Ø®f‡ØÍl¶«× ¶óÚU íIf Ñ®]œhWoShWcMhWO%´«I%´«#´«±O´Sî5“]½o’CkMvui‘]]Hd‡ÇÌÓ{‘]k˜dçà}“]õ¨È®î`Wï[`WsU`×n`WïA`W},°«‡ØÕíìjÆìZ»]»K»ê ]}võ:v­Á®Þ ÁÎÝE®«/[p]M1r]ݹ®\çéD¬Ã‡zÏ_$Ö!»`š˜‰uuSĺúäëêÑ–†­…‰uµ^ÖÕC%ÕU}R]Õ'ÕÕ‡ƒTWNª«×Fª«{"Õõ‚Ì´¨øñ;ç1Øù6ÉuÕ•ä:û‹ëj ’ëªëÈuõdäºzaäºV#Ñ®ÆÑ®fL _(É‹ÖÓŒwñBG'»š§$;',ÙU×È­Ú‹7á®Ý&=±UðO$¥ËÿrÅž¤ÝvÙBÇug0°Û6»û‹D<Ú윲Ô6»G1?šÉ™O»ÅÒl!‹ÝsÈŒ»R—¤7.;ozh¦Å±žéž'‹J.:[rÙ9ä|'‹’¡¦ÑQ;djÍm·,vx“ “²Ø!ëNÕ¡É›äóc²Ã¯Ò)“²µÚb‡ðÔô“”ÅN‰Wm°CB×ܼË`‡ô­=2sÕ9)…fƒ]ûQìP@7IìZìP²%SÑ`Wý'ƒ]» vÕ2ص–i°ÃTȦ½Í$ÇÈ^‡:Ò^‡fòð@»z 2ØU;2ص_Ñ`×~ÉoOF¢Û`‡’ìP ל*Ñ ´Áס9‘»²Ø9¢-vUG;L—îÙÞ· v­„;'ùµÅ®Þ‚,víW4ÙU_ÈdW*“~Eã MvÕ¡":å¶É³uÑå2× ÷±Lv¾v!Ý<C4Ù¹»l²Óô(¢;À^D§‰XDwòÊÑq"Ð õ- «†tzÁtnF<ÇO]ᜟ@8§éR8'¥ãÜ‘·Esú°Íôh.šk%Ä9}¢ 窎pn2$¶pî8…›Â¹ƒ¾¼…s¾AÑœ{Ï4ç‹›æÆlÍéëR4§¬Ù¤9½lÃÜq ïsÕ¨`®.,˜«:‚¹ª#˜ó;0Ìô<.˜ÓS›åܰYN«KÁÜÁÃÌ‚9?ƒiίÅ4W%¢9 ,Ã\]J0W·#˜ó»Ìù=™æZ —U·"šso™æ”¸¼hN}c˜sXÎb9?€YÎ÷b–«±œûÓ,7éÊ_,WuV-ª³{`ö–Årîs±œ«æÜŒ`Ne–;€],ç×m–s›åüžÌrUG,ç‡2Ëé“_0ç.5Ìq/V,W·#–óë5Ëùâf9ß Y®êˆåü™0Ëi‡f–;ÆÇ³·"”óý媎PÎ_ £œßQÎ#”ócŠå&uÈrnB,çëŠåª²œïU0ç‹ æÜ‚9)ÁœºD,W·±ÎO‹d9¿‰d¹ºœ/ ˜ó˜Ìù1sƒÂ´†97*˜«œoK0WžŸÇÌyôŠæªiÎßÑœ{B4çkˆæ\C4çFEs¾¬h®Ú ÍMEy$Íyh ç4ÃEsu Òœ¿ ¢¹ªAšó@ÍÕ}“æ|œúârÑÍ"wƒÁ?ºK~¶È=Š…À)w‚áz]å¡/‚ƒ´ cêátF^wíŠG'Â=ƒ¾tF¸w&ž„´Â]»J„pÔÁ+‚ƒ¢VRÕ¨ƒÃõñ¹| •,&‚«_‰àªD÷,YEp•­Šà$+^Wq×ÉašŠánÞ¡N'hf8±ÃAŒ- cd¸·sø›YG‡ü‘N&†b80ÃAiÄöÓÑa1œNŠát˜RWíâ܆8°ÄyLÄiâ|?†8÷iBœŽz âOú8Ìù³Ìpà´n•‹[É#3œÎŠáüêÌp¾3œÉWuq~$Cœ  âî<%/ˆÓñlAœ»ØgC¼!Ywq:Â3ÄIH¾ .‡¬ î䑌 ÎF&ܽ+ØMçã0œÚ)„ó YåF~ áîMÑxB¸w4/B®®e£œ¬e”óµÄp'S…Ä!jêKqÑmqt‘$-÷y¦¸“iTMqëÎïKaT$¢@gs–)îm…†2QœÏEMq˜_Š[,Š;™K¹(îýN“Eq>?5ÆÙˆdŒóýãð½ïte¥1ŽCŒ&·ï 7Æ!ô$BŒóÍãêV„qiÉ-ƒÜ!ÃÕ‰á'Ô£è܈n1™uœ1Á-†2Áyä™àü@eS@Ž ‚—þ&„;™¸ní «ÁùÍŠàüH&¸j…ç±i‚CdMÉDpˆJã–î¤"E!Ü{3¤<ÛãÉq~ †¸ìOÜúxY¶6…o©®ø÷†oçñ[Ÿ«…Eo~o¦7÷‹èÍ£Îôæ^½ù]ßIl­€JHü4þÍç†raUkBå—F”«LŠå\©¨Àr®”|s9W*Q§½+¯TÞ•ˆ÷'Ò»²UIïJë'ȹҹlä\é”ñv®¬*r®tf\;WZ ¡œ+mçJ'Ò)-©´•Šå0,†bý «¡XµÂj(–º°Ф„K E  %‡bïTË¡H Cj(’(.5KTH Å`5«€X åЖÝî•’ (5”ƒßš’C9lF“ÊÁ…½É¡Ð i5‰Í–Š’55 ¯X E*¡M ÅJ&VC±<ŠÔPºŠŒ¾] %MwRBÑ[´ 3X[ AÃûDZÒJ¥„‚ô<ᚦ•Pàþ˜ô#ÇJPÎG ²<óãXi}r¬T,p9VJ䢤PöõE¸’½(ÇJð"¸°˜Œ“£cå3É¡TB¢‘MŽ•8zúa†‹|»?9V¦¤üßK štR”c¥"ÜíW)U#+¡àë”n,RB AÆbK é‰iP£ J®n†kAáRBqÚ^K¡Th¹¥P”M×R(È2›+¦¤P¶óà*K)û[ Å ¤$…‚DU¹A”ŠÓJ–JÕ‘ŠÒ[•JýJZ(Ê[Z(s|.²{vC\oFZ(J>YZ(J>ZZ(ÊÃ]Z(r/-eÂ,-e¡Šg• “'Z EIK ¥nER(ÊhYR(Ã1rÒBQÃÒBŽà“Jµ#-¥´-1å'-1”*‘Šr– >ŸÙŽÔP`Mî W>í¥†¢äd%‡±îBÉ¡œ—®E9xdÄßRC¹6Á(ÕP<´,‡¢dÅ%‡"µ³’CQšÎ’CIUô¿7=%Ž-=eY-=¥…-=”*‘Š;Ðz(Jç[z(êÖCQ‚ÔÒC©–¥‡¢ÔÁÖCðz’ôP8b97b9&Ì-5%b-5,ù_A߯Q`§î@×î΂(õ+ ¢húZE¹KůÁz(îPë¡(r顸'¬‡âv¬‡Â\%‡â'—ŠgƒõPÔ[ÖC €´JÝŒôPꆥ‡âž° J]Š‚(Ø($1QÅc6Qt÷ÒCñE$ˆâkHÅï^‚(n‚z(þ›r(~ƒ’Ca¨ÕPÔ)†âŸS ÅÿZ(þ_J¡ø I ¥ ¨†âÊœ²vQ EÃGb(¨C©&(†â—“b(Ê1m1Ý¥´PÜÒBQCk¡x\I EMH …ÁYã½·Qõ‡©û~ ÎÜ&ßyrö¼ëpž ¯<íxw$ÛH¨vÛ÷Ï<®‚=÷Ât}?M#îÓ)+ŒÜ ë\ë‹õ]óÕÂÇ0tþ¨…ú„ÿ*ßžyg¦ž¡Šõ Ùž§ÑG¶¹2‡Ô6øòž8E29þùüÆ$õ[à½ÕØ7#S§ Æõ[‚(ñ&Œ’< F(û•%#vÄ8Œ `Kf¿ÍEÀâ[rìy÷3çJžÌ _%gìŒÑoç£oûþ½2ç ΰ–ÜñR4~KîL:S<3‡·ßq´e )uJîè}ø~åS¢[Ççî"ÃSmóßè¹å‰ë¶Xrg¯|«oÉq5ä÷ïw¯äà{XãÊaÉ+£äÖí=ù”;lùØû=£Ì0 pBÚFJ2‹[½Ý±¿Ñ~ǃoIÊ«imyÿ[>ÀÌp”Üß_ÌäVMæ·ä¢î‘÷2Î-`WoŽsýôÆuæðž9kß’5r^n‰óoɽåp¡$…±¥öþ–<œ‰Ù›sKˆE÷<,yroÈñ–DVô¸™™0qlXjÐoÁ©)MÁh”d6ï;ßô¡O~“ß’±¤2QòH+óÈ~AbTÊøs´"1êþ£4§ß’8Ú«Ü©(yòöñïL‹ŠûKtÜ•ùV94™+?HŒz·Eã-yryÔ¹þÛ±[®´¼{®Z8P’ dU¹FÞ§†ò¢ž}æœiØÔUÈŠz´Oó[ræ2 7Á¼]dE55îžV,ac\÷âܹNJzû-á‘Î]ò +*ƒÌÙrdEm¿AZTŽï'oÿâ¹â¾ù›¹IIõ™,Y©\{è-!-*`G>$Ò¢ò8®5º÷É= JRµæÞÓÿë-Y¹vJIö-Q– *v¿%)ª{j¹¸”d¿YiR\]CW:{¢¸ø?ÿIqï‚KFR\Ôáâž÷)9R°ý*(.J¸ÝKŠ‹wÃ¥g E[Ä'ñþVê&†Ä¸(ÙrYIŒ‹.4Éqq%.ºÉqýn’ãz;Éq½ä¸;¹¨CˆLû”„ÂèÿKÞÛí|³[[^ç\Å:LvTe×§ ÑѨ‘Òw€„„ØÝl ÁõScÎ1Æœ~ÖJ²6­>IÖã×—Ëe—ëç1?J2¹~ rQ‡l’ Óa¹øÕËväâDžArK;ArýêIr½ÎØçÒn’ÜR#¢©î ä–F¡° Û2b'B9öÎ Ùy¦V%Ž‹éÊËÜC@]y2fgýæÉ˜Uð¢«ç^Ì64ü›¸îÕàvˆ‹6øaŸÍœ,™ãG÷“â¢dv«)‹vH rõjÉ-Wˆ½í7OÆðl5ÞýÇ-¼ï[H’ë#‘$·”ŒŒãY“>I®ßx’\”Ü$®#O8O £"¹åêç»¶$·´rgDÏVòp 2H¥Hn©óæR>‡ø/I.Jø-Ÿ(ׯž(·üjäv ƒ,‚ÙÌýòy”˜0×çtÂ\¼_¶ræžÙÚ½¦ú§ÞÜÛ©D±°—<§îÄz2dnÝ9y®Mœk{–×Jò\ŸÃæ¶’¹i¥¤Àyÿ¬sœšê¼ô9Ö…š4×çÍÅ,ž s}_Ì2Q­DôÜz©\Ì1á 7ÃçVAJ¶­¯7ãçÖk1I®ÏÅ›t«+Ir}toÆÐ­§$×/~ê?ß@¹åB÷ûãU“(×—\¢\¿…D¹>&˜¨+= §Ûê0ÃD+aLݺV¢\,(âéøºíWç:¥ÆÕ­¡I”ë÷ùÜ×Iž(×_ Ï»ÿâD¹>aåzD¹¾åúµåú}¾óZ®(·”0ÅDûÍùs?M”[®tO}³ðk#Q®/øD¹¥å÷\ï!P®-n¢ÜRcÿ±ÉríE–[Ú96=µsÜës ˵{ Ë-íÜÛú2$ËÕ—dÂ\Â\üf’5ßÜVOš_ æê{S0ׯOªzëMÂ\ï eJ¯‡¿#2³å¸o߸±;$·]ÛA$ÇɹÆrœœ»-ÇáEÓx.ô¹g‘ãY×rœ"­ZŽƒì³Èq wlEnˆ¤È!ù,¹±Kò£"7ïڊܾ]ë¸9I4Väæ¹]©Z‘“q¢9™UQ‘“)—¹$§”ãŽiõ-¿i»eí”ã`Á™Ã EßT‰ˆ©È¡€¸–Šœ-P%Ê¡ ÔàJ”Ë.§&Wm†&‡ü·ƒx—‡Š°…i<æÛgå`œšÊ¥D9 AÒE9l:çÂZ5#$Êõ¨ÑžUªú‘çTå`¤Ma/L(•Qªþ=gU9V©rãÒñ(U9HÅ<æ¢*‡‡ ´SãíY•sÒ`«rî­U9ûäX•èðƒ>e9e¹þ›”å|Ó–å`/ L]Ά¿Öåd>\²\]вÜú%@Q–“)µu9›ËY—ót£.×ÿN]ÎÏѺœ­­ËµC]n£ì"QN¦$'O+r`R‘k7Šœmµ­ÈᆕPƒ™,:Õ8¿­ÆµçG9¯8~òHŽ+Ñ‘Š\o99»”"§ æ%Éé]IM®)SÔäìPšÜòJ’“¥¾%9G\/InúœD’\uO’œ :J’“W@IrÕIrãý“ Þ_*m@)rÓDRä¦?¤¤È)‡A)rÂNÊqÓ‡’ãªÿÒãdò\z¦(‚\]Z‚\u8¹ºg)r­]*r¾g rH Gª£&§¼¥ÉáŒu¨ÉÉ_¦4¹R™’áb×ç«,5¹Z]Òäªir8ue+ÔäꦤÉië/M®æ¢49¹e”&W[4¹ºOir­¥’ð§&×®MM®®$M®z,MŽ[rIrPß)®Q’ÓPIr~RRäävSŠœìoJ‘«É&I®¦Mjr­5¹ÒÀ¤Éµv©ÉMýI“«v¤É¹Ã’äjUJ’«.I®î[’p‰,EInÜ’„S’ópJ‘«i.E®žŠ¹VBEn<Ò¥ÈÕ[NŠœ2~”"WOWŠœï[‚\-) ruß)ÈÕ´’ WÝ“ §ï×䔕¡9ùG• '<£×.D5®\jœŸ-Õ8¿É­Æµ”ãàâKˆ¢çù`9Î7m9Îcg9ÎëÝr\»:å¸AÆ£çéj-n;­à=çZƒbœ—ºÅ8·Å8O‹qÕ]‰q~²ã¼(-ÆÁ%Jÿjðe3Û…ÕÝ-(e˜È¶Ë&OÈ6Ž8ª1±MÚÌJƒ¯éÑ (¿‚Éoo*p( ¥‡€’´oL ®ì6)Á!4y,%¸ö“”àZ“ñ[ï.Áµ^¤‡‚«ÙP"ÒÙ/%À9\ž8B“ç@ÑRàCT œCÓ¥çàkRà¦08‡V•çX±Rà¡O \ûE*pÕI*pU-5ÒX• Ü‹5šïPÄ·ƒ’Ãú F©ÀÕ¦‡.ZM…+¤œ– \Ý(¸ *p­F*p­óýÑ­TàPS“ \ëéÃ|T S«á¤çÈÀVàÜ Ük³ÊW#Î=šò›»aùÍOÅò›CqZ~sð?Ëoî=å7߯å7O'ËoýJüÕ-¥ü{À"¿yâZ~siËož7–ßã/JR~ïx®Où­·œ¡Cw[Z¦üÖÛ½–@œVßÐ,÷[ªoí¦¨¾!6âÝ¡­¢´[}s0V«oíW¡¾ÅdìÔV¯ ªoŠmõÍq¡­¾ÁÛž¶Ž)¾áåµXQF+ µUÀOËoýW)¿ùfý­ÍÎàÚýP€Sh^ëo­ õ7t—WÔßZ«ÔßÚ•©¿¡wÔp©¿µ‘¢þ/:™<¦þ†×ú—ú›#ôSóîaý­—¤þÖ¯\»6¸vWàêÉQ«‘ üÖž å7o;–ßZo(¿-%ÜFhoLù­=IÊoQeÊoo†3Èî’=Êo­ÊoÞ²,¿õ:»wʳ›Rö)Kù­ÿ*ƒ8Q~ëWJùí•Í‹å·ÞnÊoÞØ-¿µçMù­å7ì|ñÉœ²æMÈoh…ßä”ߘ0JX©Ú¥üÖæ å·6o(¿µ'Ný­Í} p˜[2ÔTÒˆÓ(yŸ?Öꥬ~!Áµ¥×J¨Áµñ£×fέ¹C†¤ázF\ª»¢·”p%ÖÕS„kwE®­PáÚû’*\cªpm$¨ÂµQ§ ×fU¸ÖU¸6G©Âõ: ˜»™ðR…ü fS…{§Ü ž“ù?¨ÉR„ó‡¡E¸~!aòË„Zåo„©j¤×ÞTàêD® ¸6xàÚP…׆…\¯Áh£ú¢³×†…œ?â,Àõk§‡…)Ùîy~¼)ÀÕ¯R€«i/î•¶µ{ .–”5.ßz•ß¼ÇJ{«¹*í­Ö¿´·ZMÒÞb”;»µÕ”Ú[½¯¤½ÕC’öV+GÚ[M!iouOrhŹçË’W™ghæ)7Xåo„Z®á™Œ£Kl¥©E°åˆ4¯!K“Ø"Mb*U–ØÈ«åñvÈ}Mã©Xb+½Œ›*,±Áý(Å-9½É6P›N;$±ñx®$¶M|&‰í”æF‰M§ –ØtRc‰­d¼w=8´Ä¦ÃPKlÖíRbº[b¹Se¶¤ÊfUO*›ì˜­²MERe+?6ªl:4³Êf¹Ñ*[Fˆ°Ê¦skªl¸—f5Ù†J*›‚Xeó}Ies'¤²UU6{Ye³Ä)•M§ýVÙ|«RÙèœE‘M'=ÙF³˜ìÇŸRØ”µ6¯(…M){Ka‹Ó[ùûH]ó‘šÄµ:«•¸VG_)®Õé²Äµj„Úšœ6K[ãS,i­nPÒšâ`”¶V…´5­×ÒÖðcj`ÔÖ´K[k%¡­íi£\Ò󖲦×@)k­/TÖʼnðFqmlö¥£¾ÖKMg-J`SN] lum lÕJ lue lJb[ Û7.W‡5gá-…­S ›€KaS†âÙö![‰lÊŽ+‘­Z‘ÈÖD-Šl­E6Å^,‘mßdH N{«Ë›OG­±!¡Š›²a¬)•_il  f¡±}Ö–v©±í;-¹¤±ÁqrÕØäa]ÛvòMâÞ­^o­Jlµœ$±Uÿ$±é0T›j kˆ²ÂkSc“ùHÁƒJ«µ‘Ք˷XM9Ke«›«}u¸ÜÅjJwP¬ÖZ>˜;WÔEVûºÀW‘T¶ï¶•ՏЭPfS*ä’Ùàǹ˜J:St±šâ»«)f²XMù‹Õ@¿XMÙJfûÆf¬¬V÷)V«û«µ²Zû•²C\âV±Zû•ÒCÚšÆöØŽ‘Øæ™clk­Û|¥ÒÙªr[«CnkíÛZ‰„6ÍRsÞ+ÍÉ­FÔèÖ®Mt«vÅnÕ±› oÕ²àÍëÁð¦WÎï›{ÿr~µï7øpó¿ý£Ã[þÛŠdù?8†æŸëßqáÿù­á/òrÇËåßÿÛÿâßÿ—ÿ`ËÿËÿá–+ÄæÿýÇšH.3g\¯+^ã¿«6þ·ïlä7#‡þǵ££:úï|õùíê¿~ûŽþ›*ýóÿiGx&vôoÆòSÿç¿ù#üõÎ~{ÿîÿn›ÛMσÿ©E(ý\æ/Å"•í_f'4ñíÌ0Ö1ßTòwÄÃaSÏ6~4Å’¿Ï“­!,þvôÖXò·mƒÙ™"aká”lø[5uä¡@ûÕ¡c‚¿ç¬„­ûçð²d‰ˆ¾ïˆ´DÙ#a¦B¢³¤7ÿË¿«ZªóEG#Õ>ÿnÁÇ£¤Eæß-€ù@ö¦giE%½,ë-©¤µ5÷ü€jw¬’ÖËZ[.ù×о=6æ,(úóÿyPôߘ#û³Å>×âÿ˜o1“®m™®¶ZÈs¶Õ£«­ª¥¶–ðéÙVzžm-¡ÑÙV«Å¶Öêl«…=g[=8ºÚªZjk ¡Î¶Zàs¶Õã«­ª¥¶– êl«…>g[=@ºÚªZjë¾ïW¦ÂûÏ6Búïy›þùWïÅßzwþù7WÏÏ÷é_X=¿jëþM–Ÿÿÿ‰‡IZ˜ôùkŸ&?¤#½¸t´ÕSq/÷‡Á±ñfÉïæI¢Æ5)íOX‚̉„>¬1Â`aÞÖp^îøJ¾çG{@DhzPrËÄñ'&Úü3Ìp<ÆÏóç s… rä…ÒL¤Eðþ<ጤSið•„­Ð|Oýk÷@Ž¢¼ð›ÖBóÔ³÷wsvq“ÓZh~#–P¹ƒ¡ðjÛå²¼¿i0tlöð ׄ¯dN#|%a°€3±íœ™v‰ØÎ Ç7fôù‚œ„Ló¤ÅíWò¢•‹§;’¤xÑž²> Y0¯½[ £æ=ŒVŸWJS˜±¥ÑЃ•=KFõ!‘Öi3t\Š9`È…[€=K`3t b(9g¦Ò88 cK«¡ãûè<Øîõä-\Ôqâa¢ÎC/³¯$“už?±¿on07£Ë£äÉ­jÒ€i †3î í£`Ÿ¹w)~î@ôsôøfÞD”ÄÃeT¾ïïyæ#`\‡¯$­†Ž]Îzc?Ã\!2•± ¬†Ž¯9Év™Ïÿd´:vy›ýÙòv.¨¯$¬†j®ý=sŽ*i7„li}2¾Çß4¹ùþŒ•<ÙÊŒ1Ž\§o"1ÃÚoÂÚo°$Ìý˜.JŽ;—©œ‚¾Ò0øCÖ¹} ·Á9wÅ”#†ð’ØØ»;lþæ.å1Òl(€”%Ha6E9ø;¬†ðNÈÔ1·°ý››N ÇL«¡¯;šÓs„íòí±JZ M¬à¼Ðwƒ¸…ñœš{xUÅ-ì¾ÔæãR¼Ú¯$ìÿFf‚‹’+ìÿÆ¥Åò½ÑìÆC‡1Ÿ0ÿ‹ÌƒìÌÆ øÀMÝüò°ÿÃÃÈÔqlaˆAÌ*G õ*{Øÿ὜¯¹q¤k>;{‡wîà{Pi‹2¸æ!/ì……þcê±F ¡Üqͼ…“6ãH£¡1dhÄBBÆǓߙ“±¼Æñ† ªä–0Î- 1+O•„ &‡‰ˆq C1,Ç9âB~i ñ™á-œéš?ΡÇ4ĸ…áõt¦kþø^j/۹°÷&]óÑNްaäØäÉü`âA‘ó›{(ZÃ`"âïÿ5ͯ-:ÌDiˆÏÎ{¤!~³¿*‰˜±_G? 3Õh%7Ç,Äs¹md!Æ Lm>YˆG0ëJÏ|Ôá&î}íNúæ£_b×s¯­¤g~{ÈAüæ]s¡2 1%߱ɣ}J0 ñÀ™I>(¤!浸“Üa$ÜçfN¨ºó;L+âa²f‰Bܳ%aNØ;Œ+bš«{i"_SøNyÜÓÎ{Jù1¤k<é™ šŸãI+ù1n—¤k>æË‚'‚®iˆÛjzÒJ¾M`&"Ø 6’–ò½N:æ·gð¤­|›5OËãuòÚi-߆æIsy 7Ý7íåÛµÞ4˜Ç}Ÿ*YÖÿ›óí¦ÞtÍozÓj¾uøM×|4Ã!Ón¾MÏ7]óÛËñMËùZ-ÌC<#èŒ7-çq¥“%éï*°ßjÏ( UÏìI.ã°¬}û»(Œ¤µNšÏ£™ðL1™½Í¯Ï ÚÓ‡7Â,þ˜æ–&ô½´¡G‹×ºÜŒô½‡(ßíE©XŽþŒ2 {ÞÉÄh$·ÓÈòäê*Éx1ÃõÙ¯ïþ‰ Ù£?î¹§9=ê¨å´§¯õ?÷´§øH`ëè{îiO߆f¿¹¡Ö•n¨“;áÜÓ¢¾ž&rs’§`œÜySù=5‘ƒx_n|¤A}»Tä »`Ž4§oωYˆë%km} :‚©Ç0.o¨£WFŠ¿ï8ÙØ“ª¯·íéÑ4aŒñ´1¤¯ýÌXƒ¤5}á°H}ñ’!È$õ}/½BI}ß+Ű“Ô÷ýêUÈ‹¿Ó(êX ~ñ+(|UÒ=Ûy2¨ïëðø#k¿[~ðyÄ~_‰r¯ü¾vR Á/®Ä`ý ~a¦w¾ha´)G Áï+yþÄ*Gš<ì»F8¹/Jؽä¾fêCî[:x¿©Ðoû¢D\ú¦É-³„}Í©˜Ø×T7b_³!ö•LNìký%ö5+œÀ¾ "ìk¦ľ2ºö…\Ú¬ûš•±o@£%ž%÷-×zi(3 r_Œ7Ú¿Þr‚_»Í=M6}^&÷-?‘g¿±$¹¯=8‚_™ üúï´6¢9¡¸¯÷EæF»6¥Ä¾¦Øûz`_³ ÷Å\ä&šÜ½ãþà—ŒMZ<¼úKðë!Áo¹öE‹¹ƒü–þÜ·iaÐê¨Æà·Ü%ÍŽê7 ~ý)LZÙ“àuøA1iyTó<ɯ_;ɯE’_ôçéä×{˜ä·\ë>Ö¿Z<ÈÛ–è×§þ”å‘ï!ѯÏÈC–Gõd¿þdYyt’ý–:²<"…$ûõû>äÜ_×¾hñàû>dyTWº݃ú÷œ28å'ürå'ü5+1Â_õ„¿>¦€¿¥ÆÜôxàrÊøÈ32áoTÂß(«=Âß°yÙ¯_ÂßÒ°lvž$ü [Ú þú¥ÃÆ©„¿Þ»„¿fEøë#œô·üêòí6¾aqçI{wï¢íQíI˯~Zýõ¸d{äg™ôןË-Û#·KͲõø–푞BÂ_Š„¿QVl„¿~S7£½#Þ´«oWºÞå:ÍJ7ÀxVU…ñ¬ZWÞŸ»ê#»#7óиÞû‘ÙQU¡y½Í—þÚ•Z×ÛBì7hýGð[*\?àCû·‡öõ@žÇV„|Ðmìm™Jðë½}ie_¿z÷Åì™ä×{óÎ5XÁo¹,ŽªZÛ×dp$[?rßÒyöËð‹äןÀ+“#]*ЯÙo”Ùo©#³{õ†ì7Ê2’ì׌›È~mZ‘ýôp ~u×ä¾ú÷ûXl§ƒùF­úª¾ÌîeEâ«9JàëýNàk‡À×ì¯ |}÷ƃ[¾ö||}Dök±T'ð²%ð-­Èö^O™À×ï!‰¯_iÈøÞ=Nâ[ê(Ü+Ì}éÊ(Ó{5qœ2åT2¾¯®P½·ýq¯?6iþêÊßaòSBN»ÎŬ'+Ä7Îi'+Lâ+÷'_ùÙ‰øÞïóM\–ÄçÆ[$ñ•S¬ˆ/@HjI|ï£ n"¾æLFâC†=$ñ½ÈóÇkѧêe'>d)#>‘øž÷O„¹>äy¼€`%}0#“²£x<šÄ=EÛ(ÞSéâ½Öò^ Ÿx©5Kç‹¢H*ÞC^aÖxªZt—;ÒRG#ï!oKÈ{ßÊá—“xÏ—6ðJˆj>w˜Àšço|ÕòÞ÷<7•äîÔ.MÞkÝ#ï=VÄ{ñYð,ÏÀ´÷H6íá{…„Eڃו„¿'ÿæ'¯pö·]拾LÁ]nNíJÄ=?m㞟œq¯•÷`åÜu¾›aA"¯FKÀ‡|‚ö°;}ƒxH÷Ë•|ïüÞï![lú¾ÇòèIŠ÷.éñæ=Ø®ô-¿ ÚëçNÕJH{ÀHr¤½V‡´×Kr§Â1)EÚû~LIN´ÕžðDÚûêsE{ÕŽh¯• ^i_i¯z,Ú«±íUE{˜Þ+í!ŸéŠ{­„¸«‡÷ZËĽ¯Î­’[=äÇyâ¾{ÈJ佺+ñ^Ý•x/>¢€¸WC#Ük?"îÕ-÷Zgˆ{Õaá^ݦp¯.´Wöê‚=$¸êR_¿²`¯z'Ø«áíÕ=‰öÚµH{µ4E{5 Â½v­À=ß‚p¯ H{íĽvâ^Õî}͉{ußâ½ö+ò^ÝSò^û ¯Õ ðµVÈ|¾!_kFŒ½%„|˜þ‚ÀG¼­ÈW%B¾V¢€Æn9‘¯Õ òÕÐùZ2_õFÌÿD¾ö#2Ÿï[ÈkeÜ?ÆWÄç »&>‰O­øÜŸ{kà»¶?Iý{5¼, îµË÷u+îµ+‘øZ ‘Ïï¦>Ý5©¯U õµ‚_Ý€ÀÏýøyÄ}í7ä¾VÂãj…ØW­ú ¾QŽ#õù¹’úª·¢>MC_«Bè«qô!gˆùª·b>ìðÙŒ˜YXBæ«þ&öÕ¥…}õ…}Q_»©ÏÏLÐתúXåo8f˜ó°Š¯•ó¶Ç²§2üt:çÙëÓÊ^I^’öžaˆ£´÷H¶´§Ø%í½N-iïUm){™쟛²sM–”²·/œ×¸à<Îøçâ¼vi){Õ!#ÏTöÀ³Ä/){Ê.Òë%‰zMg$êõk%êõ–¯ãÇ=õzË÷»þ¨çPF½ª#Ö«ÞˆõPrv“ÎÖŽX¯ÿŠ)sq…õú¯Ž'ë¡„¨DØëí&ìÕHöžgQö걈ôúM&êµ²^ûY¯u¬×"X¯&‰X¯uެ—>¥Q¨×aÆÜö£D½^‡9s=#„zKI¦÷óêµ:D=/—$=ü)á,I¯UHÒCT»$½¥$óu"tÏ¢ì¡Dú[’^¿T’^¯Ã¤¹­N’Á$=,X¢ß;ÖK3in5KÒ«Ÿôbѳ$A%û¢ëõfôú¯’ôP"µ-Io)Ét­$I¯Ô(¹µÝ$½Þ›$½Þ sæV’^«CÒ+›‘^ÿsæ¶:Iz½Î±/ý%éõ+1gnÝI¯×aÎÜv¥$½^’¤×¯•¤×zCÒkuHzíZ$½þ«±ŽIo)Étí]IzýJLšÛ®”¤W[›H¯I¯_‹is[;Iz½3çVI^ë I¯×ع­zDIz­7D=¬)©k‰z­7D½Þòyÿ¸¢^¿V¢^o‡És[ç^k0unµKØku{½$a¯—0unÝa¯Ý9a¯ a¯·ÃYÕcÂ^¯s­cLÚë÷À°YíJŠ›U­0pVÕ!îµ·q¯µLÜkí÷Z÷zĽ~%¦Î­±!îõV˜:·µ“¼×{ól?ë$ïõv’÷Ú¯È{­?ä½^g_ç(y¯]‰¼×®DÞëu˜:·µ›À×K˜:·õ&‰¯×aêÜV'‘¯_ëë\Oä«VÄ|½F2_µ"æëuúz;I}õÎõÕóõõv’úz;×½¾sD}÷­ <Û} ûzßKϽ!öµk“ûÚ•~½d\ë<øõ’cÿqD¿Ö¢_¿úµö˜è×kÜ?öW±_¯óþØ_mt?Š‹„¿Ö᯷3×§@øë5Žs}Ÿˆþú¯®û«ð¯×¹½¦Ó©òW^õB¾Øcqòµ·\øàÿBÁpáÃ7ÓÓ‰oNd±–Ø—.|—¤»ðݺh¾W!å‡(7ûÒ‹ï4¶#/¾Cy¬åŧ?Ó…®B‡l;Ó…o(_PºðÍ9e]I¾ó´‘&=øžM9ÑäÁw;$=ø¾—ƒúF>8ôìò×Kwƒï(.=ø`’,PK>”H¥»ŽÕéC|å2‘|˜)òúK¾qL#bzð5Wzð•°<øšÙ?=ø¾ K.6åÜä” i¯ld$í•¥DJ{eÖe[NJÛ+‹i{eÖe[N9JÚCX´îÂ×"äXÛ«:÷ܱĽmÈz’Úžme©íÙ2ÖÚöm6BmïkD¾‚ÔöªYJ{ÊUÞx寮fÜ+$î±Y¯¬X¯Ø‰¬w¿v׋íèþaƉ’’aï¾EÖkÅ‚½oM=Ýo ÐäÅ_ö ^vÿ½ÑàT°×êöN=Þ¶#Ò^k…´išò›hœ$ÖóeÄz¡¨‹%B=ß‘Qoj õn»¬õv›c õdü-ÔóhõüÉgÔ«V„zä(qž|#Šóüsž‡ÒœwiM˜ón½ Èyî¬9ïÒ{㼘gFaqßóc~üÌóÌ3æòt4æ2%4æùêÄ<¿»Œy,cž*My^¦¼"ARž"Myu›¢¼ÛþI¦<} ˜òn¿nEy·’Hyž¢¼[¾\‚<Ð ( yPðYR§fy ûèqéý&È»íA%ÈóbãÁède¼»|õ6K#y3žÇAŒw—_ï¶µÑð)ßãñu ƫވñnû’ŠñjÌÍxÕ2^«Œ×z£ÈÈ~ºb„‘˜Ø‡Ðº'E¼Ä¾ãÝŒ‰}'¬ûìCɵ`_„Ä¥ö—Øw~Uà%É%S6žA~ç·ýË1äw>Jì$ô;oa‰Ðï| Çý¾­šïc¡ßù2Y»ÈïÚ^‹xI~p+Q1Éïú^²½Lò»†Ÿˆü—Á)I~ØôO±à×½ëØV¾¯¤"À$ù]óý» ø!n.÷m‚ßu–”–¡[®Sé]»±ueäžæH=@[ÆÝ‚ÌO7éüJ¦63†néu2t˵oں庆n¹.³c·\ß<ØåÕ®æøÕXb·\×c¶Êà-×­ÄF Þ‚/EPAð–ëÛðdÙÁ[áðX‚·´ûfð\i †¯9îSЙÑ[pü@`ô–øð’ÓÞ–á2¼fô–ë”w­¢·\ß·ý"½‹ÓˆÞ‚ ͲûÌð-"×’í2|ËùÈGWñ[Îoü¶Îó<®?± ÷à{}Á¿y~Sãèø7ÐZ‘b2|ËñÚm‚á[Žï¦¸‘3|Ëñýƒ½öFFÙQ+¾åÀŽ@Ëð-à’·«}Iˆ˜á[„ !%füî>—ø-Ç÷ð®n×¹´œñ[Ž]òŠßü’^ÆoA˜'A—¯ßžÁ¢ªFp9¶Gáe2~Ë„Å0 *ã· ÕÙž‘õ,\æ7YT’\µ]íd—@GTx´€¿!5¯îÃ÷]èÒb`ü–zë+~ Úòeü– ³í%~Ë7Ûܽ à‚ñ—/¸L¸Ã³ â· JWú&‚Õo¥ô}^{ôeø–‰ç&(¼ó(o*J ÷à˜Q˜˜á[æ£ì\ ß‚¾È3÷´Îdø–Ö݌ނG¼FoA(}0ˆ’ž@ÄnÁdë"ßÄœ¥eì–6pŒÝ‚:‹ÈÃ=–à-¸éÑí9ûÀ0x "<É5/ƒ·`¦ó­Ëà-óÝìâ—Á[0Ó¹)DðD?£)8ƒ·´˜O Þ‚V®€K Þ‚×·[tFï€1õfù¢•dðÄ^“ÕgoÁÉ-¿ì½¥rDo©sgEoÁ]ñ5Âè-í¾¾­<*‰Mµ]‰á[Ðc‰0|K[t ßÒ"o1~KÀË.‹‹ñ[°´Eš¿ìRýžíÙü¥1fz¢%ò6ÛjѲÙV–­¶ª–ÚZ"og[=Zv¶µDËf[­ÛZ#o³­-›mõhÙj«j©­%ò6ÛjѲÙV–­¶ª–ÚZ"o³­-›mõ˜Új«j©­$¦öÌsðÿŒcjÿŽ7þo¾Wõ~ÿó_yG/µþâêÿ]LíØJŸÿ„bjÿËoÅÔþ—4¦ö·Vâúþ>îcys d=ß8 FÉO¢ô„ ´à‡Ô{áúPìA8á.QaæKà ½¾’'³ß:Tšo°áÄ,gdþJŽ¿‚cËóµ—É%;±^y¸-Ïׯ«(^±;u®?6FGF°Ì+K¼µæïüþfläCçì_Ipý‰ÏJ^ú ®?÷ÁOôc»GžÓ¾„Œ¡Éq~u)'ïW\’Á’7À'ÀyzìÛÈ#“DzǾgþ‚G‘n¾’ÀóЉÁñá>Ž×­6ŽÇk²Ï%÷8ÖH}æ›÷y¾voùçdžâcÏÃ5Fë2W}+{®]v÷ ²¿¦Ô¶cƒì¯—§ûNþ£¿ú>?Ævç!rlˆKxäÑ䯒±ç1¨ÎÖRÄñ FÎÖcÌ+A‘gkÈë–’ÈqT¿’ïá$&#ÏÖâƒu®<,?†¯uGoäïp| Ž8ˆwgk8ïÏ‘ÉO¿y Ï×™gkmd³yþ(ÉÃrŸˆý<ò6ŒX“ÅyÿÉ“’c<,׉õW’§å‡¢ß´Ë“ûƒ_yZšÏ!aˆYI}%{e`>&×^O,`5Ð×ã<>Ž<\;à·µ³äÑ=ðÁy¼V§îÇ1ò´ü”;Õqäålg>yÎû>òx­N°¿‚<-¿˜©ç+¹ò´ô²äÎ¥zûJwž–#LUOÿèÍÃò)=îˆ#攲àÜò¬|JL?ÎÝgå m_÷6ŒmD¾?ïœ$'÷¼dpãåùðqææðÍ:¡­„Z’GßÛ,Øp¼í3{Ï+F( ò|­Mâ3Œ/¢äâ<¹š‡B\ç{ä,‘;Ø7œc™G!D¥öºö+WÂt•_`ç£XlÇ5ƒëÛûéÊãµk›j欿6EP?2ëô×;å(8pÑk¬È;êíPm ÷{dæé~H=áÐK8sOÇsâìÌäÓñlS¹9}š«™ÛDæŸîcƒÔw×SŽÌ@2!×7RPÇ4þÕoÔ‹ø$Ôg׬ŽÌBï6{ÇŽŠ9ÂçŸi¨CÌãož'u9™‡ºÉQÇv4¸2ut†7ù챡â•ÇG&£þö‘KÓÙ¨¿ß ª4G¦£žÈÉy³àÎþ{Äœoš]bÏ‘©C¾ø«;Ê!?ðWw”ã°–É4;˜Èj'õç¶Ú_&ñÁiÓdI*VCîÎÇ ú¼xNvdfꉃùC%ïú¾ÏÔÔ1¥¹[¾)?—à{drê¯/;ŸÛKõ!|ò¡dzêè.Ç÷¥úŒo]þŠêsøKõùÒiÐñ†ú|ÒòóÜ(>c¶¾YBñYzÛ™ ª'Òºî¬Bíùxü£gjÏ•Lâ̬Ց÷0S|·dÚ3ÓV‡œš_Ãç¤ø¼ëÝýM˜Ÿ-åž“â3¶|–„øli×Ç&UrP|n%¢|ôÖÜèCm5’߀á ÷²MÑ‘ؘä7ù–;ÁF«úWs¢ß6´Û‘ü¶ÝìEòC:X~`’ü¶K_"¿ùØ™$¿}^îp’Þ4ÜÔI~ûy Š6&äX¨oÇ»m¡¾±IÚLê+‡ QJô›ÉtÄsA|.HÈä¾Ê'"îûîšf˜â>Œêä¼·B–‹ûð«%É}%‡ üÆcN ðƒ¿‡—à‹`•à‡’w?€ÑN`Kð›—"– üÊOHàW´À£’?&¼ø}t­^܇¼I;œÜ4Å[JðkÍüJé]À¯²6 üÊZCàw %‡ø¬8¿cú˜àvz‡ç•IÄøÀ ~H¥Åü°kòBÉ}eL"î;¢‡Í’ûN¹ç™û¾>ñ£žÜc.rßq Kˆ}‚Øû°«óc,°Æ ü„'öáÿöû`UÃmbß¹ê0±Ý–&ö}$Çx⾬“ÜWÛ›¸¿µ~Þ³Å}Ø%9CƒûŽWÁ6~0 b…ä>t‰)ä¾ïÃ%i"å¯$qòޱ ±ß÷Â}eà(îC'I7ä¾_O,Iîû>s4õƒûN|ö_ü;v©s<¼´¸©¿X…܇´X+÷Å?dA`_û¸%÷¸„¾ÞjB~2ôSqñ}'¶Xv>¡uþ&¡Ä*xòc÷Öy™ïœróáðRd¾Ö2ß [¼•ù…|:®ã@>˜±Bßyø-HâÃ,!$&ñµQ ñ…É”Èw"= ëùð1D<"ò}}äٙϿB¾ó{KðE$äà mȇùÉÇFä;/¦•òÝÕD|ÈÄÌ…Eâ;Oñ@¸m’øÎoV¨/$¾Lß8ô‚#ñ…}*‰ï¬È‡×q~> ùV‘F滦KÈ|—âÙšù¼0Ì|0SI2ß)ã(3 ÅÈ—Á|x-³™Ïãiæ»dõ`æÃ^J LæóÐùü$E|xï H|˜À)‹ÈwʪÉÈ+’•ù¾o‚A, æRñ7d¾ö2Ÿ9ÜÌw+‰™@Ç_%óáÝ}°$¡gó">œ‘aH|u¶ â«Uj⃵ñÃ’'o€ðNâÃAüÍV’øÎ[¶"¾v“$¾:àñ•Œ!âkƒGâÃ@Ì…øúÕ“ø dñI|x˜7©+¬ëH|8\äOÊØ˜'>XQò©øðz&ðáÆøê(IÀ‡Ù¸³N†b,À‡ýs%ø|蓼‡{$ù’÷p¡ì q}áI qÏCõ÷ÄÔ6ñqˆ×‰V¤ä0ß+»N+}ß­ÑV(ˆ¯Ò[»¨‰Ž-’ú`_D90¥¾áÁ;ñÍí•M¾¤>hêg'¾ #ö…ø¾/ÒeÖú ¤õa“'Ð¥Øà{?ˆf³üŠ!ò ~‘÷Ž©ƒñÞ<¼?’÷`÷ý.¼g»0áÎ;ˆsÄ=̪$ä½ïu o. }Φk¡O¿ }øÜßxܦÜ="cÞ…ù°ÓR7!óáLé^˜¯¶g">Y_^š3[zaòÞ÷ºÕ'·t¾MùŠ-ôÕ‡Xð^}÷N„ô[pï|vUIÚÃux JÚC_9H{¸ÎXh¯Þ¢=|ŒòД´×äØÀ½3Ø,þLÚ«A‘ÈW_Á„=lGÒâöêœM°_‡[%¹E Ÿ[öΫ”¶„=|€æ {xÓY÷{ô!ÉWÅŠõÚ·1Y¯‡öÚ·aì^Â^SÀ {MÃ%ì§ q{xò«›´‡:÷*òY÷ ØÃ÷§aæW8aœ«Æ·)Q¥5¾KÆœ‚=l \o„=|´ì«È·+ã`¯¾%òᘃT–°‡/«ÁîˆO„½ÚĬòíJ›'Ú«/«|sèÒ {PhP ‘¤=í†ù0›XBØ+íM"ß •YïUÜk|0§'‘OË”¬×¥7i|Ú‡­ñ•’i‘OÙW-òMùOš÷j¤Èg—$‹|5šùšlI‘¡OXG"Ÿßãùv…>±È'g6k|8áeÁ#Ï5‚2qbÒ»ðzÌ‘H‰¯K~)ñá ÿøüª—Æwé”AŸ'ˆ$¾² ïáÉrìÈ{$ŸUヂ³j|·Ï<|Í""5>‹¾’ø¦œ\­ñÝ»…Â$¾fÉ@âÃ…¸tH|×dþS_9õ øJD'ïÁ;·$…ïܤßQà{•æ;y¯Y“÷®û±‚–¼yœg}ä½ë[@ÜòÈ{m4 |×sý>x;òüŠÀ‡kI€LàÃ<ÛÅwãg$¾ëðGEÌ5v²Ûf«™øê¦|uã¾ëañÞuè`O¼w=J&Þ+ ñìj¤^k_è]jkážÒ½àêˆ{xüTŽÈ{¸§*Lv‚L[:˜âhœ%t0…]¾0mfì{™À‡Þ±|¸mÒ릇©}:|°’(ISy ø.xH²=LýbóÁ鉆õC¦²¢ó]ØÞ/–Äø)]¼˜ïÂëŸ,IÓKªŒ˜ï‚_EÓÛ*$™ïÞ÷¦­=Lq+ ó]wiŒÉ|7¶¢=L¿uNQ4˜oçø–Ì‡ñ›Ä®„>ôFœ˜ÐW HÐwoÛèkÏŠÐwoIR*¡ ú] ך ô¡Ç<Ê ôÝØ’Xçk¤¾{Sôna_›ýÂ>‘ý­°Ú%îÅãï¨w9£°QOÎnF=„™'¤]K€ [u"Í/¡¨çü¶êüæ}~„zP½±Cmß—D=¼x4NÔƒ'´ì&õàBtª$v((l²ÑLÔÛw p¢üq„~9©›EiÂÞþ­KOööÛŸ°„=x‹Y'UI{• Z´7“Œ|•´K•wø°D¤ŽíŒ‚ðØŒ3>¼>Hˆ“>^Wz¦Ïæ³öÀ¢¼)ÂÞDx±Uà³Û’>y‡ ö`ùÇolé{C®Öâ=|ŽS,!ï5¾Þƒm íߤï]>2%ð8!UIê{ö˜ñÂ4Š{1³ iï¸lHÚ;0»ø£¤=hQ³ÑôÀgÁ=XQÈè”Ó‡­¾È{eqPâ^Yl’÷¾GNö$ïÉÅr÷îÇ`Fq&‡3òžíR,î¶£LqïÙ~XuBä’DHàÃæÆV¨î=Ê€gà+ —ºç`>‡Î°ºg«fpPÝ{üGÞƒÙ‘ âÊz±˜÷ð¡Í÷0É„÷ tÅ{ØXBÞ+¬ïÙ G¼Wg›æ=ÿðAh9u¯Hð½$Ôø¾Væ|¶¶2ïa§$Huïy|!ß¹ý°êı*§„€oZt•¼%y1ë,9AêÞ¥”À7OÛgRÜkHà³v`uïk„ÇU"¾©œPeÕY|Gyï–/¾>ll‡ÄW`žÄ÷½;xj …ÏgñVøðÒ`*|>ã7ñÁ¤p1ëÄÑÄX_YHâ»ä;jæ›~áKâ{e TfÓ¦Ÿ'Áœc,æ› ši‘ïkå^™o·å€T>¾ ¯lÈm×iWAß¾Ûr’"ŸO¡ }øÄ]¡¯05¡¯Œ•¥òa»[©ÏfÇ‚¾:/ô}(g‰d¾²‚õ5n%õùœHÔ7ŽÒô6½ú…} «ûÚoˆ}ǰ¹%±Ê7Kˆ}˜•‹ÌwA”^±¯l…}5z¾²*ö}ó‰?¾ç·Â¾ÖN`_}û ûE”gg‰¹rŸŸ¹_-lGà§]Êà÷݉Cà×Ú!ø9î Áï{Þl…ä×8ägKn“ß½Y.$ù¿M~WòóR‘ŸÒ¯›ü<¢&?ÇÆ1ùÙrŸäWÔ$ò0êH~§¹˜ü|teòóÉO'?Ÿµüìbðk˜Gðƒ ¾˜wâ¸åjæ^ˆÅ}æoqŸW‡¹¯xHÜçõ!î«sßU¶¦ä¾›Ö-Æ>Ÿo û³ä5RŸc%õ5RõÕÙ©¯Ý“¨&,x×#&CŸßÞ‚> ±”Ðw½"ú*à“¡ïÚü«„>l¦•ßc{6yðÝ·ñ0A/"ô,¬WAÔ{­3òà+G&yð=Ó@xs{‘™°‡ã™¢&ì!2ÏäÂ÷ÚáD.|×,´ËM þ ìáUr_Â"<äÂç Æ.|¯Î`ìÂWŸéÂ÷ܶõ¤ ŸÏ\{÷nc?Â^ûœ!ì5G Â^s’"ìuÿ7ºð=r:ìÝ{Úðqä"îÝünN÷=[ ûÞ=¬Ò}¯Îå%íµ:‰zXª×ê¾W#.ÿ=8³²¥=ì^lYþ{V„¤íió(ÿ=»ø…²Whò߃/kPÙ;d6Qþ{WYv¾«ªdeï0/JÙó»@¯¾µ%í5)’þ{¥À[Ú»Ò³uŠ¥=ƒ®¤‡'½j{ŽJÙý÷¨E˜ôdinл5…$íac[M9m>#SÎÃ)SNe4è5óO‚^9cË–Óº¸8s‹²×Œ"ÄyS lʉÿEÛCÃÇÂyèN×ö°ý,˜#A¹0zÅâ¾3¼Õ}‹¸×l!Åyv«²1ç¥èCeÌi3ÁfÍÉ.kNï±iÌy*l˜1¯Dy[sú R朧N•mÎyÙ^œWç2çl†£4ç¬á’9gµ,Ы™sb v;O™¤žÑž³ GeÏÙl*eÏùêxMöœ5ÙlÐYV 4è´§š :çk㕹© :íŸ ƒN;ÒÑ ÓçN6è´Ý¶ :‡¶KtÚÍß>‹²A§­ŠlÐiûtnôÙ·=ç®=Œöœûa¿?ùðéÎöœØÍ‰¡´çÔ8ØœS676çü×X ¯—Оs*w¶í9m%n{ιÆhÏiãùðÝr“='LW{ι[~¤=g¹ÍÉžÓ66¶ç,W;Ùsâã—íФÓo$›túÎ&6m¶Iç|cƒÇžDv™tÎiÁ&râ?‘ñ±»`^™LÛ¤Ÿ_«IgŽL:¿_õeÒYÞ 2é,Q™tÊž¶²·EçTz\›t–)³L:ý~´I'N¾y!štÚÄ&0ðXM:÷[J‹ÎsYt"0Í"îµ'•&œ¼p^»)ÙtV+÷ØÊßU»„¾Ð”¡O_ ݦ“¡ò$ôÅiiÓy)ú›l:wGˆÿÅþþÏͤó•Èãè-¯B€Ú¤Óé¾¥…f¡I'Nˆ\‰súŸøwN~ý)~Ë£òŸç©ã·Ø=Öñ[Ê‚HXÀ!L†X®äŠßb!_Øâ.K:‚·ùïºG>˜WLkIþÃI& 1ùŸžŠ³Bþsämñ_‹`þÛL†üW¶2â?Õÿ*¶‰ ; S®}¹YÙª]\ î²ì´gÁ_ŽàA¾sŠà²»šv¾WI{y(Yö_2í¼ ×üg3¢´ì,ËIpñém;_[ ÿ*,l;Å#5þùlÓ¶øð^ùp˜$×>âß·“¹íí2¨”ÿ¾osþ•‘ð¯âó(‚ËuÙ®”Æ%L4üÒ¸³Bÿ ……xí°NEp!a‘þ¾ „´íôÔJ¬ƒ ½v€eiH¼a·K›L`B m]Q\.[„>+ÖêV ¼uºqgYëFh;#`Í" ŽÖ.Ï.Ä¿‹qg;ª!–™‰ÐéB@À K2„KQ‘ï])ÞÄ€˜²+âdfŠøvsl²ø ¼qŒ¾8ó•š ðÞoky ââ#û„@ôWÞ{´ï|”PxÏÓXHûN™"ÞCY,lÞùmÛ"öÝÓÚ®ì;¡i/ˆ0iûe#$¼XåäIÎ#"ŒMõþ0ŠK—ØNŸˆ€ˆ½Æ3,"àý½OÔÝD@lúRËKˆ:SÀ·ý8§!Â!D_1XÁ€Ïš ™ xï"" ¾7䘈q‘ii" n|õèÃÕ± .}.ˆGÁ÷ñf‰€8R“]"à}*œp"à=‹°ïöúDÀ{LÅcIDXƒUê‹áK—û:× .9-¢ ù¯ ù­l Þ§CÌ$ÿ!ð8—{ð|tÆâÐW_üwÂZ[òß} —$ÿÝ¢üˆÿîCA•Å÷#åTü‡ sÎ@´Cm(7 þ%"Xàþþ»ßËÞ… €÷)—! ¦ÿ± BVPÃ!bpV™¯žœ‹æ^d¾ûGóèC†ú$’±2d¼™x? …!¬Õ#D;„n æˆ$Æ$Àö8I€°Ì“!f >Ø% ð¾Òø‡á»eÀ¿ûÞŒŒ‰÷«¨Y¿ûz­ûå2ÞŠÆ’ø‡:òÖKüCPyÚÔÿz;‰N¿-2êlK —Ç›˜ðï¾¥d$ÿ!)p06Ôû.¿»Ä¿q³>H[r¢£q'>tãNt†â0ñïÁ¡ê‚X©¼MwÖì#ÿá%.Æ¿èÿî«|iÛYωø‡»ž‹mçý¤[`ª½½áW½i3þÃù¾Oo•ü³KFø_ÿÊ殺êôßýAµ‘Úd›í .ùÛLµREºÄh%%ïÒ5}øÓšRIkŠE­)—TSH@ƒÍ®Ý·Jª)USURMýkE°þÞÐßýÂ0òÌÀ²Šî;+¢ô¬Ó×íp½¡Âñ‡ë/UȯGŤþÕ4øÛZÍž?ÿjFa®\±tz-5õ!‹º%þÝrµÓê¨$úÂé¡ÛQAo¨*©¥^ËM!J¿9,M¹’›jµÜ$Êïÿ«),M¹’›jµÜTäUëM±`iÊ•ÜT«õ{ç¾s¿Ï¨_ºx\k$êã¯E¢þÕ´ùaúç\ýYOíÍßYïçÔþU½5õoÏê߈Dý;^“þÕ ï·^Šþ­5ó«åo/š_·õWž >Íû{z>e‡…žö’o=?W¿«cÄ'Yܹ<ùÃŽô»ø©S…q¯wøÒ(t˜»Ä¯tTb;òï=:<à  ™lœ¥Q²Ë ˆMÖá_h­È¥dWØˆŠ‡üP––#* òLY— Ïd¢’´¸…E%2ZÙ·t’„è'Q"œÄodº¦ì{Lg»Gh;ȹ&«IÌÔÁ©ZÒHÚòÅR£§Ùõæ’J¤xfâÙXħ'–ˆ3÷K¢RþF'[ —ò»ƒu aruƒ0$ËO7 ¤Pfv¼#òq‡ÁÙaRŸH¼9ìÃw$+$ b3ó;œ(ˆ^&Ið‰Ù‘ êIË ’àƒLщ$Ax§“à)¼£„$ø"Ö“Û& ¾a†™ð•$øY;߈œÍ$"³ëÆŒìI‚oø²Õ{Ê«K ¸mÃÙŒ±O½xÜL*OÜlbIŒ=˜—&n»¶l‚à o:Ö·1hX•øFØü¬BD3OçÀv)q z|w|#Úe2^r Œ²ÎüÀ&"£â>:ÆgÃÞ9°hr ”ËIƒ²äÀ¬qÐ;ÕëhÉÄ@$ÊÝ k‰oºR˜,Ò7¬–éyÕû8vPR —n9?Ä>õÒÒ) ð.Ë–›šà¤'¾amDõؤ÷”ûolRo…aKD•©€Dq"goÊ´±C½ÈðL9-ñï cd©œ˜¦oäpÕè÷ÔߊH™ôøÞÇòO&§3i¯’ô÷F<Êl6é¯×Iú{#–$Kb‡zãF:ýµÙ@ú‹äÅÉ¢ m€ ˜ŠÙ Ù§|ñýÚ„!ü½›5ë$üµYOø«±Iök«–ì÷*Þv’_»!’_»i’ßi@ò2I~u‹$¿öH~oCMHJòC®-’ŸûBîĹsÕûÚ“$÷¡•|ÉûZ‰}­JR_u—Ð׿]BfC-™¯KBßë@ d>´q'¤’ùÐH¾3É|í½@æÃÊÚsœÈ|˜u#W'™ïëfI0êlI:d¾Zäd¾^%¡‹œÀkÓ=ï}ä”IÞ ƒÔÜpÈ{a´šÛ yïÅáLyuxš¼×«ä›UòŒ'q¯õ…¸×!ÒZÌ‚^ ‚ü6»yIðÛ†Œƒ%øÁ#-¸$øm»á‚ß¶É-Z‚°)Ï5%øÁ¬q.‚_C+ ~›]Œ$øáêù­!ÁoÛ$IJñC.–Ääæ`Ûz ®EÅo³oPÞM­LŠêÜ‹â·í:•–âW—2è9—Š¿ÍN·&½áXêTü6'”3éÕ¯¨øa¼µŠßf)~Õg)~õü¤øµ_¥â‡.S¤¤â·942?Œº‚ûå™$z¬üZy&‰fä’g’á D—<“¬9(ÅsGy&¹µøÎy&ÙêPñÃÕ7yL‡„€k)$TJnòj”àWª¸¿š”üÐ -uóH²®$½ÍìøâGLš‘zßækÒûj¸¨÷¡w„.ê}›ó¥÷ÕHHï«y"âƒ÷×¶_d­Ê‹“ø¾…ÂL>ï­D>8Ô¥BI⃵üÓå¾7òÔ,È÷À—{UäŠI:#òMdÿ\¯ÎwÈ|­2f“H }gCþ$õAÿ[©¯®$ê«:¢¾pÎ%æn²|#‹ûZr_Ý•À¯n\àWÏJä×êý"”aG?¼÷®…ýêq’ýü4Å~SưB¿jDì‡϶°_ͱßTšk¡îŒI~ðÄÍþ‹ü"DK^‰è×®DôƒóÕÝõ>Øìá…uÂ'þ‹p,Iþƒé÷»ðüK’¦ˆu)âßPx/ÑâLQÜKüƒsI¾Ù„ð©Í@ø7ƒñ/²‘gâßPwÑŸ£Îþà¾MÐ$üµVHp¡8úsÓŸ-‚L­éoÐèÛôµüÌþÁ(¥âŸç¢ù Çÿ"õlÿÆ!Ø#ýÅ{>[%þ…CrvŽøçÅlü#˜ý¼HÍ~Õ†Ø^a÷Â~ãÅý&CÄ™üZ+$¿¡_öDØ‘<›Ä×.Bò«{!ùSÜJðkmüª"¿X‘¢³] ùÕ¨ˆüZ’_ŠÐ¯Õ!úÕúµ:D¿¡_X.èWw.ô îhòk]&ùåð’úàÄò,Ôç}5v‚>6@àó«ÚÀW-÷ª⽺]ñžgŠpo0Ô²i¯µBÚcGHzÕ¡ž;"Ò«g,Òódéá´wÔ«FHzí:IzµŠEzÞMMz‘lp!½V‡¤×êôð)ó.¤ç×@ÏŸ&½ˆð“B¤ç]Ф®ÔUEzÞâŒzø¤ÌwœX¦byŠ$Ö›& Y¯z,Ø»2a¯Õ ì)îߊË-¾;ò%¹ðˆ‰ˆ‡Ðgº4é<ô@Â{^ÅÜ!àÅÇuŠk<ØŽnTírò’áa‡|(^?ö ^Mu^Û x5ƒ¬ãUéxµaKÇ«m^:^}6IÈ«íMB‚p$ýJÈ‹|~4òÌ]HK^€W«BJ^ëMZÙÎxíC€×›¡’WƒLÀ«”’WÖ·ä»^B%Oo|á]u y~ã[ÈCèŒmòà$:!-X‡BÞ./êx»òçJÆ« ©â¡Óù-# ÙÑü¾”ŠQeÏÍJÅ »åEÅÛ-gKɃŸÆÕÉîE$]=ޝE,=D©äµ–©äµ:”òÃ鱚›Q%(àOlFµ¦$æU;óà;,—ÅØ‘ZÕ¼ºÕ¼êŸÔ¼.©yuŸRóZ²]…"ÚÕ-í‚N1/Îb´Û}ÏŠí`7’\lÀº°]™ärwÚ7©‚b» ùnËÙë$ÛµK‘íÚ’í\øG¶kUw­„p‡# ò)ᮕîêW‚;.#îîà7=ˆ{¹AµÂ]ûᮕîêê‚»8cÊ«îpòB”#ܵ&ÜÕ`îà‘/%Â]ëé®F]xWÍïp2ô,xWíïª7⻺+^k™€Ww%Àk-ðZ;¼Ö^k‡€×Ú!൫ðª^ýŠ„WÃ#Ä«îñZ¯z#Ä«ÑâUo„xõÌÅx­!¯—$äµB^»+Bž{hÈë% ynÇ×JHy S^DÊ'÷Åþ™œ•ï»â³u•Vd×¢òÁ"6q’˜‡¹gÁ<œ­í‹Ê‡ MÛ‚y½$÷W˜÷ êm§¨¤[¹´éá£dýr­†ÅzÕA±^k‡¬×Krm%É{­>œ*æ7%¯äÛzCâ«fD|8®”²—{l/ÉM¶ÚñµvH|Õc_õGÄ×êøZ;$¾S_+!ñµ’øZ"_/ÉM¶Jˆ}Õa_u‡Ü×~Cîó úÕm ýZ»d¿šüb?ï¾ ûµKþZˤ¿ö+Ò_+!ÖµD€î²°U!¶"`1°z#¬v[#DÀVB¬ßëD€­„ØúB¬Áºa`][ø½_ÎnÒÙ^8ÀªBþ«â߯0¦¿zI‘þ"(Ac¿zÑþ6Æm0û©Íß Ï-ÞÃçþÝø…Æ’2ÛôI¥ì6ßÕ‡ïvòZZmž>{•ÙæáódòâðÛŠ¼â¶®èáËcï‚^Äy;ïáR×Ûí6‘XŠ_•ä½;4ɤ§ä½ÖyQDdȸ‡@.ÜB‰{¸T~Ñ’öz+I{ñ©D* ÚC+Ä Ò^DS!ÊíÝßËšû'i¯](a­pó&ì¡»”3{h†„=\‰ßä¤=ÔáÆLÚƒ .Ÿ-i¯Ý7q×b̼¤=4³Ò.%ÒLÚkS€´×/•´×î¥Ü•ï^>˜òÝSÞ/ûîùÁØwo0j²]÷ 4Ѫ“®{S™<ìº7•rî{‘%×=|xvÚ‹*éSiß=»ÊwïPº.ù¶÷`b—uä¼w(¾µ÷fí´ïB%FÊwÏëW¾{ì3‘LÎ{'gÛyÏžÜvÞûn3Õo;ï]ƒÏÎ{˜4ï¤ó¦¸(ç½K)Ní¼«]ªwé¼w3é}÷"Z‘I¯¹ôÚuïQM»î=Jei×=<Œä1¹î¹]yî=“Áž{0KŸ@zî zÊm¯úB·=_¹Üö´Ûžûb·½¡¸UöÛÃ&·úí¡$N·=„Ó|³€n{#wC^4K0¤ß²<ôäK+”¤/“üöâ3?ëÐo%éâ&¿=ì¸Y…n{v¢.·=ÂþR×ÚµÛž«ÈkÏã`¯½wÏ8åµWW’×^ýJ^{~ rÛS¤­rÛóØÈmÏC#·½ÖŠÜö^ºè—Ûž\ÅËmÏj·=δòÚÃk>U4yíùì¶çîØm¯–Û^µ#·½ª#·½ê Ýö°ÂžÅmÿBkR¹íÁt>ë¼åO΢Û^ÈmO!Æì·çkÛoÏý³ß¬‹Ó“O~{r­/¿=»üöêÎå·aãaÉo¯¦Žýö¾v(%Êo¯Ú‘ßžŸ„ýö^æ-¿=?ûíùÖí·çþÈq¯ è¸WÃCǽùîÅêB_vùîáYŽyõªëv“tr“ëÞA£ }õú³ëê¼IStÝCD<{’ë>à΋.§ £\÷<ÿå¹×.EÏ=¿iå¹×Z¡ç^ëMzî ÅA´çžô÷é¶ê¦1 ƒO»ó2ívÕïÄDà mov;¢-ÒüR‘\œD†ˆ-SOFrq"mGr±Ë¸ ;á4{“¹ì7·[rAàÉ,Q z8Ë¡ÌmÈåd|Ir9îVv 1ºì±$òZŽäâдëDÁÙe¿¶OÓ®ÓÏÔv^û¶ëô÷ŠÌ:-›Ö¡4ëÄ+®x4ëÜÝKfpÍ/,™uÖˬÓ!ÍlÖiW›uŽ[)§eÖ‰ÍfÑý¾:S-Ó¬uNzrϺ¥Ó¬Óï&›uâó©ùïµïYuŽÛI†6mYÃÙ ¸e]΀*ôÇ‘IPW2>S'ÄbÎ ¯Ç)n‚þÌXÀܲy±ê0×êÒ_|¢^ D›[Œ¾³Îš¤&Á©Tb&ÁCù«E‚óªx›¹eUÐS’ „Ý.ýÅw7mAM‚—®-<”oÕ$èÀE‚æG“ r ™¿±`jC…qAPMúö)Œ‹§ ƒ°‘[ø ÀOzå MŽãb–©8.7§`ð›âÏÇÅ8+4înÅ0ˆ‘Ìfƒ˜x]ûkG†Á©4†Aw§`P oœLdV,ȨÁFAŸ˜¿ÞPÃ3 ª¡ CÜŠF$8”ËÙ$èó‘ ƒ\›}(ã(.>¬0 ú®E‚»³˜™Ç(¸3©’IPlô©ƒAÐÏß$èha&ÁñÒÜ$øõáYø`†uÕ/6’ÙU¿êŽAÐÝzV›áFž Gô£4 º3FA¬ëlW(裠·QÐGZFAŸì}ì`ô6 î?î¬0¥Ì¸*BAE*Tl¢BAG‰0 îL¸kth ³ ŒòGdAÅþ)„±KÃåâ©YP±ŠŠÅ(ˆ<ÙŒXPA{ŠµÞ ü§`pVãÎÜÄ48˜±¦ÅpùíÔb¸¼ò €¢YxVð¤¢AÇÝ züLƒŽ[bT”ý¢Aß¹i0?; úAÑ¿p ñK§A" VXqу0 zpLƒ:d-„NÞ¿@B®hÐË4ÈU†Áе"ôã º3†A½]Z†PhA\ÜŒƒ¸8~Œ`°Z V8Á Ì~ºà×»,Ô)p â¢<†A?+à°‚¸hQW¦ò1 úR†Áºaбˆ ƒŠbU0¨@9fAGÁ1 j*U—“BÁþW…‚=Œ üÇQ\ˆ-ˆ‹B99ˆ‹ƒÊ8ˆË{‹êÄEGÒÄå=qÇ/(¸+/Žƒ¸8ÊU…'~sÞ´ˆÝ3dˆ6Iœ{ E«’yû/ÿ®j©Î?±;¦Ÿ=°­K*6¶Š*Fn•Tl쉣ÿvIkŠE­)—TS‘ÜæéÁ¿]RM©¨šª’íˆÝ3„¹÷_3b÷혰ûé úOüwÄýõ4˜` ï½ß#ÿœR˜,XýK%5åpÜj©…ãVC®ÃvZ5SÁ¸ÕNÆ­†ª[ê•Ü”ƒq»©ŒÛM¹–šj•Ü”ƒq»©ŒÛM¹–šj•Ü”ƒq»©ŒÛM¹–šú"vÏŸó?ãˆÝ¿ç5ùç_½ð~ë¥øçß\3?_”¿½f~ÝÖïØ=„y̱›¶ï¿hûqÅߊ×ý¿Ïç7ú ׈ÝÿXHí™ uÿQû_ꕉˆÚúPçùÆÐ…V{üí°Ú¬‹¨Úáq¦ÅþÍ$‰c­ mòû®~âCyDɵ¥%, 'Ρ`Iwž4ã˜P"/œ½žŒ(;ã< ž¾7ϯçˆè8½ò+kF€aœ^ŒÕ3'NuâÔ#•×ïG~WÃU5.5Gh ;>Œãôx"\u~WÓäa"Jrª,[Òê· ‡â`4ü«‚´-ûŒ´„ñ÷íÀÃO¶‚@Pæ<òûóûˆF¼&\ú̺9Ÿ ˜¯øû3Žãv¤º;󺨾‘ #³Íc‹”Dq–yeÁ‹æã¸39ö;¿¨Úo}ˆðÛ¤e®¥ï‚‘`0®œws k1"4ß37¯ïûþŽêyñ`ö»b¤5×qL2¦½ý†Ž+BN~Ãò&ÇÌãéüûÕ•Èþ}}„ P[Ò÷Ù°G˜ð—Tð¼ñEG¢qH¡{·¸á‘27¢„·_Ô‘L6¢„ã(3ëŒ7£„ƒœ¢`ÆãÛñ$rÈ‘øE•wO&ø)‚ŒïÈùǰ‘ÃùÁÅßK½¹® ~ó+6r&Gð—âó|â|lO«¨ïÏ'#„¿´ ‰dŒ!üb$G}.V¯dŒx,Yc"@øÃÈž™'0Jøþµé·uö:`iñËã«<òðE|ð—¦#‘N2âƒ?Œ(i*#>øKÈdx‡êÌ:2-ë<Ùá'ÂU¬ôH€¹EÆæ÷¶å"ÍUŒìm)„ò°<2èÅ}iÈò=®ˆ™Ž,¥|Jˆì?b8 G_IœßÆÁúÈ g,ÑÈó»©C9V÷…Õ‹©âßw¬Ðcçyȼï¹É±Ä›.VèËè™ÒjÏUñf÷Î%ê¹údî\$}Íԟߤ CH$LMMè+ys‘Bo–Ÿqç*^ÆP=3Òr!}+_xptÃ*­µ„¸‘gÔyòh"¶ä¹^x6ü-Å#WéËsÒV)ZæÕï7ƒùŸ[üù\¹Dõå=2’¿- FÑÝ‹Y&^ù±D_Bï|óx£=£7s.ÇMæÄƒƒÚÉ:W¶3ã(¥ln"'o* ´,‰œ¼±FÒ)ròâÆ£:Xò0ÿ›«‰LÕÖJ„Àyò)ä~èe±J_FÁ¬¼'ßhñ®<k"–éËÔZ‘•÷ÌIÌIyc¾ ZIyö¼#'o¬S$Í*ÇÌuŠäÁÙnä:É·ÞuÎ'×éõæ!Zdåuz3ÇÜM4Ö©Vedå=ï¶Þ¿’ÜL1ד´!„w W$å0þz×DRÞÙ‡+²ò>³wp¹™Öp!/ï}d—ÙΑ›©ïiy/¾ÖâHùˆ˜×¿„²çÛ‘•7vÓgϵúm|[Ûg"%oˆµJ99yC¬…qTÖy¹zd"9ÖêsædCNÞX«èK€‘•7תo¨sS¢Œ¬¼×\~5¹£Þ3Þ6‘”76Tx«ÆM"0ÿûä«ãd 7Ô‹G*‘”77T¦´EVÞ\ªí™µcGε¼ó°J`•7KÞÜPµsã†ê‡€¬¼¹¡—pC…’ƒªg’òƆz3øÝÁ¬½áƒª' –,V¤¢‹Ç‹]1«GtÞÞPsAGZÞ\­š%ñô¶yGZÞ\­<¥:Ž›êu劎´¼gÞÄ›UöÓ–€qiyÃÀðU+“»*BIf+“»ªŸ8óÆjõè ÷àH6sqSõp7UßÂqsS½yªs7U}®E^ÞX¬Pš®,É}·ÚCäåÕz1êräåÕªD&ÈË›«Y(Ÿ,É}bä¯f¨/1'ã$?2óÆr=Wó8ÏØYqñY#3ïÉA>òRñ‹{ãrEZÞØZoÚDZÞ—óïÎVn­ÕìË­õd˜h¤åÍåŠSÎ3K¸µ*ÁÆ÷ݪ­• #1ï©Nxzs w,×óf‘˜7ÖëuòÉ 1o¬Wó!?21t$æ}ÞvRŽÄ¼xŽÑç\{HÍÍ0òöT¿™'çác@fÞ{©òrw½˜£8Uöþ®¸÷»«bÐð“GK¿/жØöïÞáÒklžd?¸Z¤ß—د¼Ä~Èà(>LöCŽLña²¾‘ò3è÷Dtœ<ÍMô{.&qù=ˆ¡œíýž›Æ²"¿r¶ù½7þ(É/Í„¸?Ƕ&÷UÜ Žý2ê,Á¯"î ü¼é8àWa˜ ~}u% &øUH>‘_w4ú9lšÙ¯ÚûÁðia¿í Ÿ€ÙoÌqaöCôµ3ëý6ÀQò!ÙϱéÌ~Ž¡eöÛÊèf¿mPû!4ÝÈ{ ûáS'FœèI6GBè·íú²ú!àÞ¾ ŸC¤™ý¶]½b¿ –Iƒd?Çg3û9PžÙßoïÂ~qgöÃsÈÏráß6(dÿ"ûð‚­„ü‡Gs'ï%Ö [I`û 2wöOˆ’s@ÜCtXüçÐ~æ?ü(?çÅ58⿚â?hÿUi! c.‹ß—{¿° UrVÿ*<»ø¯¦‰Ðqé€52"@‡õK¬)¬‰%¬‰%t|9à¶ ÜE€5iD€ÛÆ|&Àº–Ð!ñM€Õa ®ue;$@L¾=)‘¸í¢7 #.š1‘Ì ÛΔí†@4C8JÄrÎÙ(tIC Ã"3¦ °î“ˆÇ{'ª‘kÅ€ôo¬µ ¬AÖàÑò¾@ <îo‹&šFR©Ã³€èúEkÜF øf@-L# ßúF@‡½4:d¤ÐAA€0cÙ„©KöŽè9aÄ@¬è'nôŒ4:ªÐóOˆk?ÉwD@Üg~<[»DÀò@@?m!`YVØZ# ®¼ç•_í« Äjt L# Ã‘ýö6¶:Së•û³;cŸÔèµ`t”U#`ëòÃ}õL“!# ç¹­ÄOD€žjÀšžÀm§u‹ Ðï1 ×· °.-ÄÚHzÖ`‰kŽˆ·Á“z —¼ °&’)BòÓYX †X Shƒq DóD`û ЋWXbG6CÜò$Aø§„&¦¿šŸ¢¿vaÒ_Í|Ñ_•ˆþjðDõXD¸xRè¯^b¢?¿óMJ,úÃr¥ŠþÐäû3Á7௞ˆà¯Jð×JÛN“-ÃßÁ~~iðWï0Á_ݤàÏ;¸á¯f£à¯TðW3ŸðWy-ÄÛðçh´‚¿OÁ_½« þ’1üÕüÕëRðç˜Å†?—üѵÅWPuá¾ZòMÒä²^*8ÌJ@¼´Qy”PÂßMwE ûFžþv)vþŽ;OZ,üí¸ä/Eû›Þ$9 ;(2‹Âß~0E«…?hŒI#þÚ¥RøÛÓ(·p‡ñ"U»Tþà÷Ÿ¼Rþœ¸/•¿ýæÁšp¿©óIøÛq¦—àFå¾' «â?˜[åç·ø¿J…Žø_Þ¼iñlK¨Ç‘ÿ`]JÔ$ÿÁ²+eñ ÄvÒÞNŸež“šÿì³lþs4óŸr ÿàÿ²/ø‡+å4"ÿÙÔügKóüsò6Řcá¿ý~Ø=ñ_=ñßþ}B“äȰgeò_«CþÛqš´ðfMÞ¸ø¾DùQ.þÇOÊ©â¿ïS…êˆøŸK‰Ëä¿}Ò Ùü‡i‘Úù¯¦£øoOÿˆÆ¸6Cþà MEEˆ’, ÿí@uaîU(IYü·ÃE9á“ü·Ÿ·3êᵕŠ%ÀY6“÷(ÂK‹¢ ¿JõQ Æâ^$@˜#çñ°5CÜá_žP˜¸c¯Êv‰€h%ñ–ÈW”ãy s³Â³LXÖÓîØ-iˆ‚L˜{&[Š£"@ÔÉ·¡p‡ó{r ·ôP̽ %yZ#ÄDº²„ˆžTü’kú‰1|y €­]`µBD÷žw°Ó/ÿЗ<ÿáG”óȽ$E@ŒÍ¶`»°ž¿%Éï@Ìš|é k‘ ‘i0GKè,‡V1-ˆX@o@,ÍcQýÂ?‘šÛÔ¶¨€x•½ jD@ô/¿E…€Ø•fj~D@”< |D@¬ÍsA@¯V# ×¸p‡ŸNýÉb@¼“PÄ€~嘽ٚëêd@¼#) rgmdDÀ ùK#À}Òb& PkÌàŸd¿FIަ0®ž’%Ð3ˈIœ¤)ôÛÇèjôê5Öµ€^A&ÀV‡è•iÜç!ɈêI€í&H€^T"À=lâ~iˆ’c½æÍ€x+¬ ˆk¯* ×°—pk½$ƒˆñÜI|dÀýHë&# v7¢$ÍŒ>" V>b!`•½ …€Õ!` °½×KbbASÏ#úKÔ ˆ%ž% „ñgƒ@o9†@Œ ±ˆå“W&º@è½Îˆ’D* ¿eL€õ"V»@<÷üžjˆª{ñ‹A{ \·ù`½¯D€uáW{ª^*Àzñ½aý-fô`DIÒÞÔžš{¡ñ©­IûÛZÀXûÛ »³$ñËàéøWëBøW—~¹¥Nì«-•ÁLÞÕLx3>Ýs"Ý_I%Þ¶ˆ/CUuâ{¬ïùJuó)jº=• CÈ÷† c¶’ȇ’› `"ß ?’›%±1!hj‚$¾J¡%äsò; ~ÎhÁÏ©(-ø9+˜?§ó“äGR£Ü·J}ùe¾&üAæ{™ÞY‡þH;$åÕi´T>PÕÙU¾vxoWù*y 0ý âÕ…­ðmmDðúUðÂ1’:\¾|2,ž¯Ò# ðÚXðÚµð*»œ¯Ò„ð*9°Ÿj²žLÀƒChF‡à•0K¾{O}‰ïš0K¼CÞ•‘&jÄ»^’xWÓ…w•ØDxWé„wnŸTAº«ù¢»Š.º«ˆø¤» œ.º«¼ ¤»Ê º«d-¢;'“ÜUŒÁ]åÐÝUàyÑó·î*‰ŠàÎI`¬í9 µµ=ÐR¨£¸çL9®­r\[e¹º*9®µ’Wù‚Äq•ˆ×~“×Z½ÎþÏ q¼\Ýù­$¿Uþñ[»5ò[]„øÖžñ­—$¾Õ•ˆo­•Ä·~!ªw΢bõ΃Â7LÅ—´øÖ^µÄ·6Ç“ßz•ä·V…üÖ¦8ù­½çåo¬ôo„̲½™f¾˜­"q‹Ùö}çPˆÙvÛPÉÃð•% uXE‹•掕GûO uÀ­SÛŽoó<—PwBÿ¥¨mÇl|ºæ~}»ìMK¡î|7¹ÒQ¨ÃŒº¡sámضãK|f3ꮹIËK¡îºw]‰BÝuÉê-„:<ö‹æâÃ]/.¬Ô]÷!ùŒJâ"ÑuŽJ>˜ïÅKïz¥XJª»Gž‡šãîïŵZjÞ›ÎÒ¥Ô!xR MRêÚ¥¨Ô]ïÃÛ’RW—¢Pwï7­©Ôa^Òn”JÝýMì»;éÅçüb©‰éŸWRêÓj[”:Ðеxé];CY©»@¿ÉE°³s1ÔÄúY 53-•1 u>WR”“Þs Üì§ÇêðX;M8K=äšC•õª€:ZIí„:ݱÉîÌŽz¯ŒËQo£DdG=ûTI§Ã:L4;êÉÞ½õä!RŽzvk*G=ÙÐÚQï½ùôì«+¼Ëä«wJg•PgLjòÕ“ˆ…:ìõyV#_½KR¶„:šÉyL¡®†TB¦è­‡¹)öÉ[ŒÅºÈϤ¼õÜ9{ëa3]l5ùÔJü÷R£PaýR+£PWN¶êpKä;:Д"=šÊQ±¯Ó”“"J²'Ôèød’û-W½)uR®zsûa¥‰‡–M* .åª7øê–HŸ‰$X‰t3_rRèæ7‘~¸é›o0»é +}rÓ³“®ýônCØO¯.-?½¹©:{KZ¡ÃX¥H–§s¹éid즇ƒÕ¬"7=¹[ Cð¥guÓ›{nF妧©XnzøìX:ü*Ï¥í¦7%)ÙMïâ^]nzr#.?=_Ý~znG=j-Ðù=R~zõ+úéÍCjšüôNšºØOïbÒòÓ«VÂOo;ü§¼Þ%H£CÉM“LúéM*ã姇ƒE£Ã6ŸJ•ýôìÂc?½íå¤üô·5!J~zOb*?=9P—Ÿ^5#?½)9Ø~zß"§(?½p©µ“^]XNzSÚõ9|·>‡HòTÈä¤7¥:ÛIoJ²—ƒ”“ÞA{¤rÒ›˜ì¤K‰¬#'½sW‰œôªDNzó‘ù¥œô&mMÊIï\l'½Cª“ôÜŽœôp—⛜ô¸ÓNzŠÉYNzÕŠœô œvÒsÿì¤W—’—^+áŽZ=þÈ{·]Ëye9óUæ¥7Ð]:P¢àÇXÏ`øbÛ¾ðû£•™ÁYUë?ôr£ ßjpR$EQ?F2S§ôjÔ)½-žÉã)½.G§ôÎÒÅtJ/ÞµÅN3–Ê”ÆtJ¯î¢NéU{¤Ò•·³’é*hCÒûÜœÊê”Þgr¤L.}ñ‹*¢”H—žñÐ6Št2ñ*‘.<£cJ¤“Cß>¢×‡ötDOóyѫ٧ŽèY ¿¨õRÕ½šxëˆ^ “:¢>Ii·É#z±A ^ä½øª#‹Žèõ‰AÑ“7Œ>¢#õë¿Ù ½8ŠŸãQ2Ýþ~ `F ™nžq ÁY¶ø/ÔòËùoîC;Úä¿ÞÄ+þ+3ú6Ô © ¾VÈåì­ø/¼ÇÒ*óC?øÖB¢¿ð;‚…”è/V¨Iø/3yŠøovå…çÃAÙø_¯ÅAËØž2Ëþ}ZN ÿF,ª£Ä¿÷}€eWáßçh&þÅÙþÄ·*|` ÿNº^oü{WPŸå Þõ>Œc1Ô¼öC:™ð/Œ¿Œþ¢àÏ‚9È‘Bü .:'-×!G5¿ôú·Ô»l…á®Æœä¿ñÈ!ù/êZœ´„ããË„¼ôÃŒg)þý—ÿÂé2Í2‰á^ª‚ð/\‰c<"9ò_¸ œ®äm#V¿ 9ò߸ËC ù/®>'-#Öˆ(‡ü76,þ •óËùoÒuwñßÎ0H„ùµ «æ9u\Vü÷ÈyŽøï —6´ÜÄ×*.º;Íø’=Å·ö(Äç #ñâ¿ s9¨c FÕâ¿ø~Pïý¦ÈZüW_´â¿‰ôº"_-ãb‘ÿÖËW˸u¬üM¦‘¥œµDåH¡³–ø.æä­ågÉyy“ ñ_ß¶ø/\vÞ.çeʹxkéšË[˘:?Wü'‡4 €Û·³zÑ5<‡'o-ƒŽÛ[Ë©-©òÖ26ç#Æ„pùè­%3®çmïRçA±ùq.gõâ)`H’#g÷ð¹:SÞYä¯%Vj@1Bày0PAûkÙáp»!°ˆº8ð–º80h+ž»&pqà_nTE §÷ÇÂç¡sÉâ@»J¸ï²±îôO-Œ»Z80Jwã%‰ñ hƒI ŒOÙŠçF§Ü‹·,î ËÉ00®Úh•ÉÕý#%Æ`å# Œp.vš1Ö³zqÕ¾œÕ;ãþÁUÂÀM«ja`|¡NÇÀhν``=ä>~[kˆ»¿D‚ý`D‚qõC»L~[÷[.]H‚Ñ>v Ææàp/r=‹¿–îS‘`÷»H°¶«‹û*‘`÷²H°{¹ýµL¾äå¯%ã«A°ï\ Ø#eà×MŠ{V ÖR¾P0æ’®" Öne»kyê|Y0Ýu öë*ì‚…‚‘gÒ ?­" žÛ%Ÿ*$Áð‰¾/›G¸Ž'‚û®H‚gDù2ì“ 7p2_Vù3,ŒRpt±|µ¼yW×é/×hæ+{ÄdqÉzePˆÛœÀ*Å}^ÿþºÎ¥<ÏWö¸Ï#]C¥´Wj%µwÚNi¯ÔWr·Û•ÒE)©‹ê+*V炙ݮ+ŠIVT¥ü«}et?~å+û'O×p…}–Cáßdø ¾²#œN¾Ü}R1XÎ\ù{.•UްU”yÂVI•GY•Ó~°U;ÂVIKEy®*«aWYæ »Êª\U–媲Êv•e®°«¬ÊUeY®*«\aWYæ »Êª\UÖßð˜˜ÿ~á~í1{ÿg³<¿ñ˜ý»|ß=fÿQ¾ïü§|«Çì_íŸ=fÿ™Éò?M{¿šÿñË7çûtùë7çç²þ¼Çìñ.^ÀwÙÿþoÿw˜H}Ž?rt}~÷˜ý¦õ_ÿ‚Çìÿx3èÞøû³c+çóΔ¿t™ý>ÏÿÚÿý/å¯úüf¿™ÿç¿ÅÒå™ýÏþüWFl´ÝHÉ]Œ1âœnzРO¾‘›Âá…ap¥?ÆðŽ!Ÿ?#>Ù¶ñs0¾Ü»HþÀ;ÆÉHÔ#^ÔôŽñ¶ 3Ï¢¾ äÑ‘[ªoBÌ™åú|àãÀJõM˜~××–6íFm\ïË™çFäŽm„MS:Ç8¹@Sn8ÇOõÛÏûåýp|†o ×ÑãŠM¶mÉ-‹7å†sŒƒÔÆ…¸Ñ^Nø8ü&¯ùÀ9ÆÁÍvMçawyÇ>[vñtÜÛß'™b„»Á;ó0ØÜ‹7ÝÃÑ£û¸3:˜gAd_$1¾)Qgfyp͸áC^ðÆ}ðq0߸ï ~lNî½)¹4ÏîÚ‘2/ø±9¸ðBÐ ?6Õ¨ôfñ~ÌOƈͮØg»àÇæ$€ù"Îv,yŽDý7wÞ”‡.§àÁgÌØhsß,ïè‹¿÷NÖÊÿ›0ñ¶Vïä"·€‘?ç·õ¤ÕÛ/ù¶ZÊäÛz²îð«˜ok¨‡Y÷ƒm&¥BÊûUAè÷’çx[Oî7<2—«Æo+½¾ “/+p,âÈ^VîÖŒ'üŸÞëáoq[²ÄѦG•Sïûúö2\áÊ)_שpãmU^áåð¾ºâò|[õœ®ôßž®æü3Qrì²Ý7*¿v¼­jïõ¹±–Œ|ßôdàWXÄËJGˆWxY«*·äHO¨½"o¾­c/Š»úý¸2¯÷Et¿m _‡wØtÅùÄ Å>(vìxY9s\Ü#÷³½2 ïeSóNQÎ¥C3ï‰ìDëæƒwUSÛ•qxý}¾BµÆ»zÃxêÚa¨˜uåGòÊv‡Í&C‡öGèŠàƒù®'vD¯ŒÃûx›3﹤„*³¡˜‹ŸÖzâˆ÷°Î0¼K‡2µ=–ŒÃ»tWÄáÝèº*wŸ®ŒÃ{}µ«·+6EÂL]'ì® ÃûB]¼ß¸Ë41Ëëý“+ÃðÒÍžUÌÃû&ÃðÎ¥9!I~ã¹óù í»ùa=¸1seÞǾ9WÆáþrÏôQMs½|*¹ søåËZÅfÞËz8öÄò]=h@pe^ögjgWˆ*÷æ=£ðÞ(æÂUC_ÖjÎ¥/«^Ä1™—}Y¹rÒ…50vÙ˜%·›®Â{œ~Ÿ„7]}e7tM|z¯±ã³Zü¬Æ÷eø¬ê‘d^煮¿‹µrñ£ZO$¤à|Qå#íÊø»·¿`W/*óð£Z/sÈÐûîueüÝéuEüÝkº\˜^wzÇ\;?ªZ^÷ñ 3ãïž^{à=}&Éø»Ù[ ^{EÞÃz+ÃïúøŠð»»¯A® ¿{¡yhïÃoªJÉà»êÉEüuo[-€Ñ|÷ÆË›ÄWòÇþUžê®Œ¾Ë,7.:ùEÅÉлӻ%bïÞî òÊØ»—zósZ£*ƒï²/s-{eð]º¾PL:®“«Å+Cï¦;4ºþ¿"ôî³ùýdèÝË+š;?¨rÓ{eèÝ5ÏÁjÝtn³ÜèÍ4s¹"øn¾¤r›W›3åÅìϺÐ.øÛ&â'ûí:ÈVì÷vöd¿û˜B) _æ8ð)ô‹ÞÇ)¡ß}Éá´ØïO˜¼ o×ýN‘;Àß êbÀß ÷³Sþf9ë%üÍ8©Éšó%H|áç´D|±‘Ó]"¾gœ˜ |O†EG;Zñˆ÷ž…¤OðÞsë9È{ÁY8v,Þ{î¡Ö÷ÊIƒpÏŠ!îYåĽ0ÿàÛFܳ® î…AˆÓ^äÀ±\ÑÞs¾šôžˆ8s£LÞ“hl’^\ÏÀ"½pKNú —0= ôÊ'‰@ï­S ÎëJÄyíû_œ÷ÜŒ%Ì‹,Ã)/¼¡àÅåE¹ È‹,XJòúäÅ@8X ¯;ZÝŠ*È{nRã=ù)C /ŠÁa}B^ô0| òºû y^ ¯]¾ˆò¼&PÞsÓí™ ¯\¾ˆñðÔÅw^ø.ÖĻ禭¡èÎrîÂÒ•lg•l—‘ç'0 lÅ¿†Ø.\ÏÀ Ù®o†h×Ϊ‰v‘3¡Ø. 9Ñ ×´ë,$;{î$»x>l]ž.²ÓYs]Ï;{„»žjvù®ÝvýÎ묽à:íä:¯ \kÞ¸³¾R]?CB]ÓÅȨ̈A¨³±B¨³Ž#ÔEETØ u6u}?dºH öéb´Üh^}»c]k]¿†º¾#ò\WC¢‹jða"ÑÙF¢{¦Ñ\O!¤¹žþHsñ㘵h®Ç0a®_'²Ü“k2´,gwK–³×‡,gm'˵ßv±œ }²o‡ôvŒ³§GŒë'гáJгBâz2 Äõ “á¢LÌÞD8«×Õ׎N“fÁõ¨"ÀYàº\d¹Èg`8ë22\ 4¬àÄpö0q=Épv@8Ëî Þ®ã&Á=iÈÊ~)uË8k®k!¿ÅýL@ðÍšJ|{²=HüRNz±)K5ö/øÀ.€»á˜ÊîÖD"‚ë¸%ß]´Â=é¤âÎSD¸~q„pÔA—2Vöd8ÓÈpÛ'œQ£v xÏÀ".•"`R x1U! ¼òA×^|op¼-b¥|5Â¥ë_òõ»mÿP£|+Ü¥ä»r¥[ò]øÕ¤V‡MÆ\C \ªwñy¿ R½Û`NÝ×>K½Û? 0Pê]„ ¼ù.–` ÊwagŠE®ä»m"®ä»p­ $¢z·= "Zê]y/õ®üH–zK˜Ó1®c–zWî;K½+ï“¥ÞÉûn‰waç‹ÔîÊWciwýP¤ÝuŠÄ»X¤‘¸(Þ•£Øï"åìQ¼£1p‘\{x-ñ.ÜSàáR¼«•v·Å©'¹wämj µ»òH[ÚÝö™OJwåtº¤»WKº  Üq—1B¹:ÊåSø@a“t§öÁJ’î ;D7Jw出µ»©ÍŠÒîê£v·Å g¹Ëôb¹7áÁ`”t×ÃFÒÝÛ:‹t)˜5$Ýõ t·ÅfÉ ûŒÕ£Rî¶“§-K¹‹‚±;!å.Œ‘.å®\—t·E ˆp”î"e"…Ò]Eé.î[g”îâCÜ–tWnÏ!ÝÅ-‘š$Ý= ü]Ú]9Ä-í.î`[´;õyIwåì´¤»º¥’î‚§ðÑ”tW®WKº‹‚'S ÝUG”vWQÚ]Eí.Rð¹•v×uI»«1PÚ]<_HMïê¥*ñ®o‹âݶíßÄ»r…ßêÝÃå¥ÞÕ“*õ®Fz©wQ2ÕFªwQ9ö…¥Þ…¿åcQï6… hõ.³5ßµøï¶ HåN?)Û•ÃÖ’íjB’l-s´Ë:(þAµ«!#Õ.ºë©vå7¸T»šæZµ{>F©vá!›Š×F{Ý0Ù.Ñ®ŒD» Ä4Švå~¿D»˜º?”è ÚÕd^¢¾÷%Ú•—ßí*ºG‰vq y¸¢]¸$Çó‘hW¥J³‹Œ(ivÛ¾I¢£h×õH´‹P¤D»nD»®ŠšUuéƒZ)ÔìâvùøEÕG­4»~Níú*‰v}•D»h2ä évýÂQ·ë·BºÝ¶ñd¤t»~k%ÜqˆK¶‹+°I%Ù®>–%ÛYÅ·>¨Ue»žã$ÛE  “ª]ߣT»ž ¤ÚÅñ%¨T»î+©v==Hµë»”jד'U»øRíúU¦j×ÃF²]Ü& W²§ðƒZ(Ý® –p×(á.ê‚/á®|u•p×w.å.Rb¿¨]ò©/ê‡Ûï¬dŠwÝïRïºO¥Þõ“zâbªwé­ø«Ù/§ÌÿRïúk$õ®›'õ®fP‰wy„)ýI=ñ®ûFâ]ÏZe=®ñöN° ùŽ/ØE|“Ñ ø¶k•ìfî^Ë|­ øÊgl_,#‡Ÿé2ØÔÆVó^DK"Ý‘÷¢®ûËyÁ¶ ÷)ªqOJnÙk* VãÞίm¯);¶×,-{ÍøV¸j÷¦0roÛkzk{Íëäâ³ì5/žMn{Í›ñÛ^S¡¤Ú^3p|G{ÍØ®'Ê^óž²à”Áæ}Ë¢”›áþe!>3nüL3i‹ÍØk[-6Ãõ8ä4Yl†\%‹ÍXÔêS›ñEŠ,6«'Êb3î\(‹ÍëóÝb³mAe±YÏ¡,6Ož-k‹ÍqHþ’Éæ8!}·ÉfÙ‹–É&-Úb³-+i±Yve±96™QÊbS&m±)£Ä²Ø¼‚¾2É•Áf ¶2ØT`Ä2ØTHÐ6Ø”ÕBlÊf¢ 6î±í5<¯í5W¹í5¯í5e„Zæš5y”¹¦"L·¹æNŽm¯É@Õm®ùÑžN™k*.^›kÖ-ÐZSÁfÛZSQ9i­É šøT°­5?pÿÔÆšŠ°ÜÆšŠ{ÜÆšŠÇׯšrí߯š~(ÚXSq<ÛX³K¦÷<Ò©ã)nÛjò´©¦Bˆ¶©æÛX‘•©¦î²,5A´L5r¹M5ë–dªY…ÈRsûˆ{Û绩¦"k¶©f§ÈTS1¿ÛT³Œ€ÊTS9ÛTóCÿy {Œ®Ú–šŠÃÜ–šŠðÜ–šÕYe©Y•—¥¦"2–¥¦"¯·¥æ›‚ÝYj*úb›jÖÓ.SM…nSMÅ‹lè«Î)SÍêd)zŸK¬½O-[M‹·­f™â•­¦B>·­f§ÈVSqyÛV³Þ†2Ö,«®2ÖT¤ð6Ö¬gcÍ´Ìù2îëñWÆšZì´±fÚ²Ö¬]ÖšŠúÝÖš"kMEHokM{)eï}Ý`aVÆšZµ±f¥2Ö¬Á.m¯BI—¸—+¬üz0•Áf8!E ä½8G½Ê{ ‘.…¯Ú[öšŒ R _EC)…/¶¡ç~ýÞIã«)Jß#K²’øÒ¦j‘øê")|Õ: |;µ¾‡†@%ò…§)âU>K¡ÊW¡M$óUô“’ùì"è|áÏg:öul×RúæEã½’ú"H&ÍB©õuŠÄ¾Š[Ój_uºÔ¾´é¤Ü§°*¥öÅ|±ª}7­ËJí˽¡Eí«4¥ö½kÞû›ÚWw%¹/÷DQõ¾ØÀ›e²f/ˆPÓ‚ß;i˜Áïí!H^­øÕm—â§X1-ùÑoVI~χV\-ùu1”üZ÷,ÉÊá/–÷ùá¢^,AgEy†¢<}lšò´¾/È“I¯Êã—®!¯ÎRäɨº!¯(´ 樂†¼:3V§øóv(Oç™ òtô¬OvàÅxM ãñ6xq  V‡òt°ª¯Ó ñvŸÎ èp‘ŸÈ£6(¾ÛwÊsu êwµ¶/¼«‹Dw:ÍÑt§@éMw%'Ýí…ê¢;…NoºÓ’¥ñnß~¸¤×0RtWÃAtW—î´ðh¸ÓÒ¸áNÑÊ î¸Þk¶Sôïf;K!ÛÅbéËÑNË©f»"£b»:zWgñê¢:ŒÇUP³ÖNÅvuæÕÙºo±o©ÐNÄÒh'ÿ†vêñf»‹³A³Ê)¶«gÛlWDXpÇÀè wMe‚»8¯Œ«w}•èNŒbtWí)ºãÆUѺ¸é®° tw•|'¼#‹6Þ ïÔþŠwºHtWˆUtWË̦;4ßà®Z«£xÅKu¯\xǧk|§wñú·ù®–é xÂ<\€WD ÀëkŠðê¢"<µ¸ O ù"<Í5Mx–" áÕZ¾¯òüžðª“‹ðš»ŠðDPMxê®&<Ý–¯žU^=#<´®¯î`~ûžàöÐb3 .žÎ£Å¦bæõY¼‹qÉú0ý@—ÉfYeÉb³ Le±™Ÿ ¤ÈbóýŒÅb³—ˆ2Ù¬U™L6kùR&›½•Éf/î`³Yd´9‡îHV›Ý™mÖªWV›Ý¸²Ú”zYmše'­6ëd´i5‘íz¹/³Í¶-“ݦ]%»Í»LF wmÊ'¸{{èñ“xvã2Ý´‹ÀvýœÊt³º“pg ´ß´pNê_¢»XQ°"pÒ$TÖ›u‡B;þX§_@º®°¬6oL×kó6ÚT"]þ2ÜÄ߉smQ*«Í¾€8ׯ„e¶ùe(Wö"¹+B‡ð$^mÊ•$×)e¶É¸Ãrmâ]f›e,kZ‘\›Ï å" ñdJnn«áfÛD—áfwå<(×6¢$¹²V…åæS&ûèÝ)ËÍjŠ@® ‡Åqu:A÷&Ü“)<ã ŸÅq56…qu¥0®ÖüÏØ­ã9ù¹éæ%™NJ^ Ä òAÊË9ð&ÛÍ]îZ ð>s´Ý¼ÛšS'ÄT ðÎK•<™íæOCA^Y(åŃ\)¯B‰y%qæÝtܘÓd¼)1º7Ën¬­7w ~²Þ,³¶²ÞŒÃÒ~ÏÌË|3ÜD#Ì7OLjóÍÀ‚ä¼ órIÁOæ› m%ÐãÅ@¯B»Ó~³Ú[œ!ž!ƒ 8¡½ 8Ò» 8‘¹ 8÷K®UdÀˆN¶“½ÉCN.ηՂ“Úx[pÆzûË`¯-$Û€“VŸe¿‘"ûÍ6Å”ý¦ qÚ~3Ô;‰×"¼ÙoÒª¦ì77F4Î[äyµÁÉÁ“w48éšî68¹ç+ußeÀ)CŒ¢½ê+Á^ÙF´ý¦ì'ŠöÚpP´×7U¸wm|,…{×#ɸ÷p:lÙoVWÈ~³žKpÊR¨ 8»\pÖ‹Xœzàe¿Yã¨ì7÷[®MdÀWÉ€SãÛ€s§ëý6àL¿[_†{e}Õœqf(ή]œqÂHHή\œeN ­â½6«*NÝSpªæ6à”¡r[pÆéq" ÍMÔémÁ‘⋾Á¡,8Ëx­,8e¦ÚœefSœ²:+Îq#Ú€SÚœueÀYFp2àÜéí¾ 8õ𕧆hpöE$>«IœÕ9E|úĘçüæ~%ÚI{RpÆÐAÉ€S#»ˆ¯ÍË‚³ÌöÚ‚“#Úˆ³ú¢ì8-…vœ]í8Ë´¯ 9«{dÈY6[mÉYí“%gÝyYrræ*M¯M¶ÚSÆjB¾÷Ü> òÅf¨ 7ùmí«dÊY£«M9éR M9Cÿjæ3;òä¬Ë’³í6eɹ3æYr–AèÃiZ{YrÖsrSNTYr¶m'¿¬5ØÚ’“kCN ë2ä¬gà–œ.çÙƒkCÎ2Ò,CNÕ$;Î3mÇ©›.;κï¶ã,Sɲã,“KÙqª5eÇY÷]vœj^Ùqª÷Ú’SF}mÉ)¾²ä¬‹dÈ©orVcdÈYoOYrÖ[X–œUNYrªª2䬩¤ 9Ç7÷+f^Y†œ\½Ð³IrÖ`”!g½¹eÈÙYdÈY³ 9«ÏËsg`”6ä¬;±}h_ìCû[ZAñÀEO 3œŠ$lÞìî<Òñ¶Ðß”4¼â´Ú”3Ö;ìw)µÃó”&¡ÃÄúóD±Š!}b&€Ý´þƒ-tØÿ¼)áûª]óÜ×ç„ sÐ.ë¾0¡ÆV÷¶3%­kžÜ Ί®è½Í|½ãâ„# úº_V‚ ùÚxSrPþWîk䎯—›qÓT€ûŠüÃT€7åø_ºßåD¹ü¹¯''òvÎð®B7¨2tèð&<ô¥q1á}¢÷h;­áè[r»cQr]&a¾)ÄRIT÷ ‡¹-¨Üï£=Ûó\驵üx¼ b©¶ìïÐR-•¨yÇâdîfwßϵTVmoÊ„Zz«Ç'N{Êv@.=Á3÷Ü7¨¥² |S2RZ ¾oÝn…y‡{½fÊ8òûÞ~5#¼7!ã\Fxͺg\pƒÃQ¯ÌŽ‚qÄèžïã¹7S#ß”ô[ñäÙuäyäÒºíçs@.­Î gyc÷Û~b'îöî‹WïtiùeŽr©d×û9s}_Zí^ß“ûîðdo©s¥ý¿ ­è—m´—­;]´ðuç óLv‡™äXÊÓTs@2Ãv9ÅR9a™au0¯~´3,§ŽÍ¯‰-8xr™®‰CÁ{7m~ò^/×ä9™~l3ÎJ¥o8 ñQ¼¢¥=Î8{”¯(=ÍÏÜàí†:Ý›ðà¥k‹ùy.x»9hà8·°[67u36îaŠæ $ÛÛÐŒíÐëjßL3””xCÓ·c6ÿ}u¡œj¬Î8‘ÿÙL!œáã¼Zœ)íæ9mn÷åTêõ›’¾ŠZ]b8•SN‰3Üp܇=çßãxAãe½ 3ßÏRß÷3C¹FÊ} âm=)öÌýÀ\ #ЙQxGΩ°˜†÷É)5·'fá6ÇΈ{7}ÆŸ„÷ZJ¹TSÍÕ3ƒð^æoFÞ”Mõu™†÷öÆGÞx7»® Ã{[# /Ý6âs93 ïì`3‚€Æ›Y~gá}¬'3ï™Y08¸‚‰BðªÎŒÁ;<ËßÏ0Åëa×?KŽ™ßÏ2}™ƒ÷ʘßgÄàMÇ•'cð^æ•hF¼®xnÔóFžßO¹+œî1^MÙÔˆŸÛOÏŒèžÛÞ^$gFàÞ-ç…Ïçû]‚?3ïÌ[>þˆÀ›~nîÎŒÀû,U=9‰Xóžü€vM€wd|6fDàÝÍdyf^ôlKfDàÍ÷³z/#ð¢¯0›ÏGõÖàŒÀk®gà}¼¯2þîmÏ-ÂïÆÛ»;È1ó!­3€Ñ¬D@š_‘”æ9’ҬտϘ›jþç5/ AÍ«HPó jž æ—$¨yŽ$µî¼¿àÙº4µ;¿¸f3!¥¯ƒ[‚Îb¥©ÕžZij¥àHSÓ‰­’Ôf­á)©=Z©JR‹Ifº¤VçŠJSó”Ü,•@’ÚSëhIjåÒ¡$µ–($©µD!IÍR¨©µR$M­Î²•¨Ö2†D5»Š¢ZK/Õ¬=’Õú*Êj-•¬ÖuµB¿ÒÕú"kåÀ¡„µr9Qš塰öè#[ÂZùÍ(aí©Eº”µ§ÙOÊZc\+k%ÿDX«»*a­•* k%•²&¯„µ’'ÝÎã`] kV„µ:ŒW𥴰v §¶:|ÙºšN¾µ®&=T²šœü—ªÖªTµ:ÒUªZEu(U­E_©j%Ú”ªVN)JV³<”ÕJM–ªVêJ«jŠPR²š\¶®¦Ð/ÒÕêäZéju %¬µ@$aÍ/*kUwIk—c›íI[kIêZþku­ô©k–‡êZK(’׬vêk­žI`kqF›¢G•ÀÖÅP` “l²¶ »Y›ic”ØL¹£ÄV§çZb«{ÆV›%±É2¡%¶]«AIl-]Hcký 4¶Ú—ÈÖ;¾ÙJ ÆæÂÚ¶h]­³)…:[WÜB…ÅÚdQB›5ŽB[ß’„6ì(´µ¦'­Tél¥×Ig3åB[W.¡­¬-Ji;y¨®…¶Úè-¥­öðKj«íï’Új¿˜Z[kbÒÚºs(¶UìµÛtߥµU§›Ö&eMZ[Ë[ÒÚ:…b[WUj[ëzTÛ,Ï(k>`Ém¦ýQnkÚä¶ág Û*^\©mUQ©mµ­{¯Ô¶ºK©m­ê–ÚVo‚Ô¶×RÛúUÜfåHo«‘$Á­ŒܤaIpë1[Š[=;InÝ%¹Õ]•æV#I¢[ÏlRÝú®¤ºu1Rݺ©n­©QvëyLº[w»t·~…¤»Yèn}çÞê ‡ðVSyëz)½u¿HzÓ¢òÖ/»”7Ú†Ixë>¢ðæ ù=í§œÊ[*oÖ†PÞ¬F*oõnRyë Ê[ÏQRÞZŠ£ôVCéÍ.ôÖKéÍj··’Ú[÷%µ·߬¨oVÔ·î ªoýq¥úÖ…R~kKêo=¨¿õüòË÷D\©c”àJ8¦WQ%ÁYŒ¶XϘœå€×÷N ®þÀiuÑ\Ä\X´·k,Im4‘|ø}ÎÅaR.}…så4²x.=aRn×§‚˜ èbe3\{Ò¹ ²€è€t&¢K'(Ôäòó16G]"¢ÛJ¤€.¶!<{½ÇÂs…8·ÑyÑÜÆó™s@ÁÜÎX Årqe,,WAW‹åÊq@±\_%–‹ƒ›Sò££°…r;A‹ä*þk‘\ç ÈY¡¹rG^ ·²¼$Çu)ĸÎAŠënÅíGgã,1nçé³¢¸ôèy‹×ňâªDqõ⺯qݳ„¸zÊb¸n™.¿}a¸8ÈG³LBœÕDˆ«Ñ"ˆë‹DqÝQ\ BA\º Z .½£›qéÛj¸±Šá¬n2\½"b¸6ƒÃu \—J‚Ëý_” ‚Û÷§ø­ZVü¦2 ß, ñ-­¨ŽÝêPèÖåHt‹€l‚µm¹„ì6Ýj~,vë»»ÙEd7»Šìfm!»¥ôíº›õà-V¶4*$¼u9‚·Ü‚]à-ö’ x„· '^ðfåP{ ¿¼¹ ¼U4ñ‚·î/Á›¥Þº/oVà-I»øf]*zKU øˆö= Þ,…ðV_ë‚·®[ðÖ ¼Y9„·Ô‰jàòTj›ÕCp³zHnýT„n–èÖWè–{å , [·MèVk‡B·š“ ݬ¢[·FèVÁã ݺg„n–Bt ðrvcÏÜjeVàÖeܺf[÷ŒÀ­Û+p³rnÝ7·î›UEp³‹n–‡àf•Ü,…àÖ]Lpë1A-îýðr žà–b+~Üú±Üú nÝÙ$·î'’›]t³VÝÂp?ñí îe¶#¸ÙßܬB€[wÁ-Õ6·ž4¨Ç…”Ãô8k#Á­ŸÁ­;—àÖ“}‚›µàÖoÁÍ.¸Õ|Bnë;#·õ“Û<áagËjÜÖeÛêÛKlëûHAî¹è"NØÖc‚Üfu‚Û@¥ãòzêHÛÓ'Øâ3Ó>‹EmÙj³‘FjË«6—Þ¼½ 6o °Íê"¶ežüæ Ûì…"·µ·fq[{L·Y{ÈmžàV®‚Åmöb Üž²%¸µ;d’[{ºy–D·vß+xëæ Þ:è­£ˆÞÚ}¯è­ñ ÞÚ!²à­ÜãŠÝz>¼ut Á[‡¼uÄÑ[†æ僷UÁ:„o«FøVQ7Äo>†üÖ‘.ÄoVµø­zñ[yÙ¾õ,&|ó‚‰oeœPøö´5$ðÍ &½=eV&z{¾L–wÕb·¾m±[…æ(Ý­N›‚Ýž²}»Ud ±[7_ìVõØÍ."»•ÍA±ÛSæwb7K!»y Ø­, ŠÝžoF“–@rS@7+„àVGlKv+ã"·¥ºMvp‘"·Š†"r³,$7Ej¸=er'pëknÝŸ"·²½(r«pEnÝ`‘[œuXÉ­L-ŠÜz”‹ÜêpqÉneŽQôVf'Eo¬£è­‚‹½Y›AoÝ¢·2½u)¢·²É)zëÇ zëö‰Þ*>[Ñ[÷²è­ìbŠÞÊd¤èÍj§ò6Ù­ûSôV61Eoý4EoÝ3¢·~v¢·î Ñ[·—ôVÆSEo–…ôfÅÞÊÿqÑ[%Ñ[]½årÊé­,£$»•1 è­ûôÖÏšôÖÃôÖÓé­û‰ô&ó"Á[?fÂ›Õ |ëóȉoe™%|ë¹!ñÍÚ|ë¿ߪ ¤·~r”Ýê 8á­{ŽðÖÝMxëáKxë÷6áÍþxë»$¼Y‘€·r; z³û½ug“Þú™“ÞúÒ[ù½U_ÞìŠ4q“Ñ[÷>éÍ.½õÞzÞz¾"½õ'½õ  ½ÕdõÜM—-ÚŸ…êÊEBaBÈë:BLc]Š 4a]8@p“Ê7åøAkHb]äÿr¬Ëø—a]¾ˆ_ŽuáðÀÁå5<0&¬ËÕ×c]:‡ø2¬Û‚ÐÀRâº0¿ø2¬Û>ÄM(¬³‹€uíȲÐ.<ŸRî#Ú…kËåí*p¡]y .´«˜À…vå`°Ð®ü_ íÊ…c¡]ùÚ•CºB»pþº»×~\íÆÁ§)´+·²…vòå[dWn‹ì¬Á$»r©\dWŽŽ‹ì:EhW±™ í6/´ënÚm±Ž¨¥À8¹‡Ÿ@» ÍKˆv9|9ÚÅÁÇ/';¹Lo² Qa%»ðì‚<"»\x~9Ù¥-é—“ÝsÇìbDò›È®Þ"»Émû&;Å n²‹–º$—-ÜV´»¯ÿçrßÜŽœÝ±ôø|¾þÿã::¶Þ9õ—ž£ßÇü_û¿ÿ¥ü4ÿ‘çè7óÿü·—l^jzìÿÏÑ6Ѷçhs'ý—aÜýøï(ÉóïòZ˜›¹ÏsÜüèâÔÍž8ïì$l=!Á¼ëØ}ùû|ÖF‡¬Ü½[Ag´zçvwlÚl?¦Å‘Š”Ô\Ë k쉤Šco0Ï‘¢k=áØØè»C1Ržlü Ê”bN=÷ØØÁh…ÌXk}/å]s>kkæÅ±/Uì^q Ǥ¹ill?Ž¥¢ÜŸÎ<ØmŠuñ•½¿Qï 2ŠHO S[4¿^ƒH™9Š'GPðÄe£:˜åHK‡Šq°T ®ñïJ™ùêm‘í·”sü)mÏ'›¿sdDÊÌæíØbM©‘sG—²çÑ¥Éé*ö?SnµK„älp¶#ö Ro=vjk± sÙ›C4öYSqÁ~óªƒYº˹Ô\÷›¶±–ª«üíÇîWª®Þº™²kì“LyÆòûHÛ:ù O´.?±Ì²¥öj5/Î2±Ì”#WÃñ°yOÇñdëNÓ¼)g.¡“qOÇ8mpWê¯×§Ç•ﮗƱ­Ç~Š ³£çòØTO vß0cDBJ°g§_gq„Šã:âÍÞ}Ú&R‚ ƒ7Žæ þ:ø™°ØËO†ÐA¦Hð³i¨öʆuµ÷Á3Uèˆ4Û6ß‘’_Ã:fõ¦<×;öåßÃíßí4»{K"Îìe³vø$vGGœÙ±”’ôÉ‹ßóÇé'bÌÚ¡²7áʯ¢µ5BÌÎ:è$öõN‰³÷Ò0ëy"Âìe†Ú‘2í”VH6ƒ}¯7û‚‘ƒµ%BÌ®ÓJ„˜}¼Ÿ"ÂìáC'Ìε-W~!cÍÌ'tá´flgsrг›wå…ÓšýÈ®´UŸ5c_8«ÙÃ놵ƒ5öοée“±"ókiÝ€ð²~_v÷Qˆð²ÖÚ/»-]áe¯åš{_ZÖnE¨äë{ûŸ“£Ÿ}þмމ£švÍ„áƒeáaÍjÈ„åC7%âÊnfåÂáµ¾—sœËOìŒY%W~,­˜>ô°ˆ²s¹—Go? y¸ÏºELêëÛÈÏ#kË 5lþBż=ìõy–Sš¡¿ìÓ*Ç4»©yþÞŽ$‡ø;¾Í(ámæ[ÛæçÛ°A(Y»ÃЮ–ÖÄzfý½å—²ú1¥—Ç¿q)8ú\_šÏZÊùY'•˜7Ùû*wàKi]ûúNf ¾m-æ^˜„ú>ì£ûÙ~<åTß}¾HSŠåL£ˆé7Ä]£z³7„µÇ®¦:7ûg=D‹ÆÞW<Îíô~XžZK½ëü{ÔÒ4–oóc4ñ aðD»ó”;v[“Æâçz4v‡™üÀ± EüŠw!ø‡D»ÃØ(× ä±ûÙ» Ik/Ðä±HxX@òXÕ ‰cí½—83 ŒÃˆcí»™8Ö•‰c틘8ÖaÇÚí-q¬}'޵GYâX{÷#޵{Vò˜_’<æ9’ÇÊ1y¬¼&Çü.øÕ±–ırƒI(%‹µïQ˜åÞ÷HóÂO¸'¬[Œµ=˜‘,¦$‡µ·Éä°vÐGk}±N‰u Å–<‰b3O1O¢XµJ$¶\tÊCáů:HlBeÌ„±¾Y€XuŸ8̯H [Z2¯ïmK³‹€a‘0 ó‹€aí¹RÖÃU(æwó»ÞÎËo$¶T”$¶4&IlII[ŠM³þ‰…Æ'Ú‰yë€bvQXû„‰E!\t‰Í‡y=à0/&1ÌofM…-YÆùml€Äj^ˆy)÷í] óû‡y–ä0ïZ€˜µ 楀ÄÖxÝ€E,æÝ³ºÁb~ÏcaŠG ‹ySîcm>P¬çb¡XÂ5HÌkŠY)@±%a²cŸÅ–RÅüƒÅÖß3›_÷³çóѳæÆ"A[K€±¥qðÛkÅÆÚ‘;`Ìî,f] óæÅì‰ùXŠ-%‹-)ÉbþÅ–<ÉbÞšd1acË% c~Ï7=ùö#Y±7}ùÊ9¼`l)Þ|½˜„1/†î|-KÒ˜w hlÉsïß~?ßÞNð˜?Yð˜=ð˜=Hð˜÷̤cß΂О…ž}»Ø²ZˆÇlùýÍKŸM݈Ì'òIï¾õÉì˜Þf)ÈJ[@Ö:T dÚ3—BÖ=G‰Ìn‰™‰ Éì*ªdÕ{-’ÕEc‘`(’™Ì!•ìÖ«L‘¬|•HfÝB‘Ì$0ˆd]ŠD2º,‘¬üé•HVþôJ$ó<¿VÉl0S&³š!“™(‘̪LÖ9(’Y¡É,E"Y«AɪZiduÔȪ d&«ýF s YëȪÔßÉc.ÄÑ›©ÕœYJ}Ìd¬ȤAQëGC}Ì^écòÝXúXwŠä±Ve¤YÝÈjTK«iDúXÉpÈ.ž¦uLí§>Ö/2+f–3S5®2½î-‘ ’-å@$“E•kd%½u’“JfÅR&ë)­u²ºê7B™C¥¬:â÷J™¥P)ó”IU­I±ÌôªÒÊØJeñÊ©Ìí¨•Y×µV¦á,­Ìô4he­”K+39êóMÓ*­LZµ2½¾%•Õ-K+3õIZY+c”ÊZ_+©l°(e­iQ(3¬t2n„A'ó›ùPf*„2k| eÒ줔u§H*ëb ”Õÿg‘Ø‘'<Äb ®Jûpy${xΕöäžÎWaX¬çÅ2`Ø!ý6Óa€qX zQWnJĽë«(l¦dH ‹ \¹ƒÂ¢N.¼ƒÂâï°—„E»AØ ¿¸ –!M+ïrb°òD(£>!X‰“B°rɳŸÅÚÀ3e±ô>‚,–ñ€˜;á§'û„ªXcyP“·O‰báÉåþjQ¬ÜöIëN$‚ÅL–ÖBY¬<•±pvCÚ2V*º¤1Ëm¬<æI{ŽÂ>hcÏþCLöðÙÚ©Yô±g/Tœ<Ûc }»0XáÖª€úXža5ˆK 5vw[Š>–õåo¨cïX*Ù êX:g` ä1O y,}ÿð7ô±ô' ”Üè+sáÈâ|ú*ÅypÉKPÈâmÕ@!‹Lb!(d~²s,¥ ™µ YzzaJ(dy.“‰,ã1$2¯Ù}ê[D…,Pç yc ‘eü£E"›Ÿ2Ô£DdjYÍh¥‘-)áÅþáL‰dþÙy,Þ*‘ßÖÖB4K¢y9·¾.u܈f™úºL#4Á"4£&ZÓ Í€–¡4]4ë¯Ö_á3À¿å3g¸{}hä3o ù¬IU€f°@»¨JÎÆUg`„gý Ï òˆgÍHÀ3/†xfÅŒgy·„gÝ-Ä3›„gõ›Îê~ Ït tV_žÆ³íÆ3u·ð¬n‰xf·”xV_{Ç3=áY·Ž|fÏH|Ö·-@ë;  õlA@³·Z€vÔì@«5º­_$š:Z·E€ÖÏZ€Ö’€æ)B[-ê~hï«°×y²Ï—oÐŒ¬HhÝ`ZDf¼”ò|#ZO^"´n Í·­iD„Ö]!B랈æ¥Ñú®iMmÏùmˆ”fCX”Ö]AJã{,D3¼£Ù´)H« =2Z‹nýl¡-0š _1šå!£õ3£õ÷˜ŒfÓ¯­ûEŒÖ·ÐŒVF³Ž£Uo‚Ñ ®ÈhV,Í ¤õ†N3ZÍŒfÏZŒfU‘Ñš4Àh†4`´ôv°Ø6ú5¤´QYQZŸ.ûp™x ¯Hi5á¦Uå×·©0­çˆÂ4C¹Ä4ê{ÅhÕX0Z™b´ßiÕ½i†d€4k‰ ³Ì_ðË\’Ú““w»NÊÃ_D7óaAt;ÛbÝJ©­—õ¢¶[žHmØ©-\Fº÷ù~¡Ú.ü°Å<^ëßcù+hí> }‘ÕÞ±,G$`µÆ²Z=u±ZcÉoX­™ƒ°ÖÈ´VO¸hM3å´Ò,%§?×JI®5´×ÞgÁóuĵR,ÄkVyžp­ðZ@^³òÚÁ'/\ÓGW¸V’ˆpÍŠ®õ}×bQ~¸¢VZ‘x­ïƒ¼ö^ÂGš¼V¢P)j}_TÔÎï'ÎìóK^«†¯™š#I­ÕIj.¡ATÛj«J¢š¥PTkÅGÀ¦uªD5+Àö®‚ÕðÚ½—q$%µ¾F¸fàEIíóÍ÷Ç’\ëšDkÎo“㹨ï\%,ÑZÄ¥¨YÒZ%©YcHkV7i­¿”¤5—¨(©muì¸V«YÑZ’´æª\)j•ƒ¸ö‘%¬hÍd¯ß jÝS¢5ï¦ö«*ÒšIlϺxý½ f°S‚šj’ Öí“ fR€Íž“€Í„¹Ôê*Ûû ÊÛÍ®ºWJ• æx¶ýX©HÀÖyl6F$©YB›‰_mÅ[„¶n©ÍdÖ¦¶B½ñ,=Jj³‘&Q­Ÿ8©­™XÔf µEFѰͪjlÓU¶®ŠØf#YÍòœë¢LÜfå‚Û¼”Kœêq›•KnÛêh¸ÍúFÂZ?r[O6À¶¾kq›]n³¶Û–,7 "¶Ù .]­o@ØÖc„ÜfS·¸Í®·Ù]‚Û,¸ÍÞ(r›=n)k[Ùt‹Û>}Ø Üf…Üf7Nn³Ï¹Ík·y9à6oϽ/÷$n«‡KlóKÀmV¹Í¾—â¶z.Ä6«‰èfŸ]¢›çºÙlCv³ç›ì楀ݼ°›õÙͯšú¨V°Û’vûè@ÑÍz‚èfÍ#ºYUD7¿êXo›ìfÑìfOA[}¥Èn^ÌýÝL…ìæyÀn^Ø­&Ø­¯»õ5Ån5µˆÝ<à­²oÝ>Á›_xóÖÞü*À[whÁÛ§¼Ío-ÀµQ®ß¨¸ÚkÀYݸ¶(ÀY‹[eÃ|cž—·-\q,n==Gæz™)îDù÷×u.åù›Î—÷=üztùømnŽ3Á<›ò·yJÞãò¹Â/I^R¬¨cËé×ï—)V“¬¨JùW;_ÞÞ¯ê;èþ–óåù¿Üùò/†Ç–WV÷Ë߆Z¢ˆlñÍI3Ê2çÊ(Ê0³¤ÎÂ'Í(Ç+£ Å3K²\,juÔ̲̽2Ër'Ì*«s©¬ÅU3Ë2Ë,ËÝ0«¬Î¥²gÍ,Ë\,³,wĬ²:—ÊúŽ˜_°Ë!ÿçzbþ3“è?~š5eþã—oÎ÷iô7oÎOeýyoÌïlrD8 sÇÜŽ’ÿ—úc.¯ÏPÊü¸cÞ¶´–þßÝó4Ìÿã/øc~í&òDƒM¤±?B¯fóƒP9q”kŽ™Ñvbëý½3ðU™7ÍýÉðaSÏ”##vlŒÜbwZ¸7e fGî™!!.ËE¼á‡W-^”[rBmgḚ̂ƒî¸˜‘ÁÙ>,'¢ÅvÓ“!OîÊ-)[†îˆk¸hz6„ ³”=ƒwl‡<ûny89R6uNõ¾¸îs0åAž⪽)‚-˜çʱNû0ÏØ]†µßÙ¾‰( ïï°ÒGÊÎ{x2ŠÇ[ºYÊž±•#åD$–HÉ@‘‹éý“ûro‡~íMÙ3”GÜ'–¦û'7沜ŒÂ)Ìã]· ÈÍ›’1óÆØ{ïïqä8ðšÜ˜Ëk2šN¤Ì¼‡‡Æ«îŒ}µ…ýæ‘·ðƒÝ?¾Æïð¼è™y oOcï[D¦BÁ±/VK*Ç®ŠÈ×rã[Æë‹Thðv ÜB5oË­¹-þ€¥ñž—£CwÖ”{s¹0ßXî5ðêÁl¹7—ål,9()ª+÷æ:Àá›òŒ Ux ÷ÜË×fŸñ–Ý̱ÝÈ¡cQû¾Ÿ?‹Tø¦ÄqsÜN¦s[.¶¥ôÒÇ‘·pjð™‘ηóûû{b>ÿpjÙÏt—ÄÝý¼ÜC·&·å2…o»´¨éfMs ÔýŒÓoÈÃwl|>y—6|Þ”™÷0>8>´Gp×kiÎØÙY|"´kÞÂ䌺ܗË.>x͉ÐW¡2%7æ2‡V„veÉ|™Úµo<¨hÇçïb c»v§Gp×| ±½È”û['_¢.vÝКˆí:–öEl×õ"¶ë¹tqwþ1Þ#¸kÞéW*‚»Þh /÷·§på¾\fù0åF4¬~vWîÌÅ^%¯½)3‹^ÌŸ¹/—OÓSv}–¶0°kTô0eCH¬.–‘]#…ß’`ìû[ ^gEß|S€Æ^{ .Ö%ó˜ýFLšHÁBåMy–Þ»S€^®™ˆ6áHH:³Ü¬ú™zébr銹zìá™syçØ¹#BVU•q]mD̤cË!´Þvµ<)KgŸóó“¶¾KïÍ”¦—ÆÌòð¾gŠÓÞ˜§-!qb cÛkRžö®y2_¼'õioÊs ]÷Ý“µ÷Ýs"ÝýÑwãI•z©èÚ5,9uê,ùdEu­qÿ¤RíTa]c_3‡Ññù||j9>\!GPщ” áèjŸ¬óƯÚ<íã“’µµïøœ§†ù`ž±/áøŒgíá㓪õRÕ}®³áñÉŠïCÏènñûùÞ¼UÆ®}W´ éÚíÝ6|SëÕ=Óµ¦¹cÛùQÝïM9Îõ)ÛÉjõðvâ£ZÏîØÆ%ÆPígµ^Ôc»7V}ã£ZcúØ&>ª÷ŽPÊoÊsè!°1Á”»/Žý3—Ùòˆ®›šcßë›z3OFpØ“¿§Ádu²u:öq¬wÀ-˜è¼9˜2õðrhã¦:âÏzûE°Æ°´ ¹XxÒöðw?Oùøk§ªd¿øW;Ý`¿™^šˆqÉ~M‘6F@¿™~¦™’è7Ã܆[ú`¿È©­n°ß¸¯]ˆûúܹ¸¯ˆû"ö% É}} ^àg¶4¿ò^ îëíâ¾:5/ìó»öõù`_ùõESvbì1º^0_½óõÙ{1_Üâtäó{ò--9†õ¯Ýùâñ3LJ"Ÿ? Ÿ7È5QÛ&òeôÑ[MkçÍ;Pƒ}Ö3`¾Ïd¾rE(äógä[j~vï(_ C®Á|åòA¼j(ܳ†ö¢Zx±"íE-|_I{~MžW“¬çÕ$êyÂ}æÔD‰zþ,€zQË¥<°ÀèñÒóG Òó‚Azí@B¤Wn.zååœgwÌ3GÄ<À¼¥)°¾XR"‚’81Ï‚FóÂeÙ”çC”çw̳åy= <ë~@^T#tLÆ‹>ø,ŒNY8Y’ñ¼µƒÆ=Ëñ¼&Ø^”›!žgÓ©nLžuø®ÝˆˆïüßE5úÀ;ïàW“tç÷ ¼óªaua­ݵ‹ÑwKÐ 'ÐÐ5pg×€í<l.¬%@»òš#²kO(";/VÅÖÖ›fÅݹvq }|ì| Üô×ÓƒßÔw~å<®³À:/dÒeO÷>°.òpNÕÙÕÅO†#Õùô5%/9‚:›4Àt~Ã`:ïÚYÎ{O¶¾j¦÷žjÚCÿ=}ƒO9ð9 ò–>Ò-—ÀÓT?]{ ÑyS@tK |MYãàLUΈÄsöéÎ-myôÖq 'Îõ3&ÍÙr…4÷d” ^Ÿª],iΞi®û…0g_>Â\÷ aηªÝQd¹¥¢¹/—$ÊE†‹„äžÕ‰rÝo$¹p9ûnä¼^€Ü“L˜ϪV.«öX!ÇyÏÇù ‚ãì¹äìŽÀq^<«Z=À8ËŠ[²lø`v¿ãüŽãzÀ‘â¼Ô„8ë}0ÜR͵xÌÃʼnšˆÊT¡úö/x‹. ¶F¦áuˆqáx•'úƒâÌ-1ÎBIãÂ5m‘ßqÿð¨•ĸÈÂ_ĸ(XÇa€qál˜öºÄ8 ØHŒ3·ä¸ö¥KŽ[ ~îåÀq^,8Î"R’ã¼p\û%ÇùMã•ñ˜JI×¥Ý<`œ9&Ç-U%Ç-UÝO{,g΋ÉqN’gå’ã¬y9«‰ ]¡Eç‡5« ræQ/AΞAÎü/äÚ˳@ni_‚Ü’g"úí^äùȳwUýLž#ȵOj‘œ¹`&Éu`^œ7(ç–[®>†ª Þƒ=Ï5è¸Y0Ð\{þ%Ì-̓÷àwѪ`ÎûfgxÍ ¸™0ç¥æ"Çîòù³&Ë™›f²Ü’’0×ÞµÉröÂæâ"/%ÍYdOâÜ“¡"X9=bÂ'D×ÐÛé?¸ßz—X×=Gª«Õx›.’{KŽÕ~“œø!É™¯ZrvŽ„Š\—’ §î¥ÇÅ÷ÂM1ã\÷áå¾x{‘׎(Æõ9¨ãÊ-K©qw[fæ–¢µä)ÇâÂ|Hô!®N7I‡ ©“f’;]èTT8K€W‡ðK„‹uÞ±ˆpí}C*Üû¯pî–‡9usŠpåQK\û•”GêoÕ’ßôgho}¹´·Ò6%½•¶)åͯ9¯.ª›ÿª[õD·°à5ÐÜ‚mn7¶lw ¥¹Y)ÐÜÞR´4¤æÖ=,ÑÍó@t[RæR5U7ÏÙ­†©d7»GÊn^5d·s’Ýì–(»½O[ŸkÊn!çÓ„ª›|â•èÖmIÍmœfÒÜê%“äFá ¹YPÜ< $·n7K€âV.Jr³Û¡æf­‡äÖƒ+·°TK ¹•Ó¾Òܺ jn]5·¾jnv;ÝÂ@l_D7ÏÕÍCÙÍS »y9÷¹þ†ð&–‡SZtK#„7«›Ê›§@y[R&ŸÀgUÞ<¤·~J)½½ÍÓz—Ú›_íÍ‹…öÖLéÍ/‚ôfõ@y³„Ä4{lÞ¬c(¼õH¥îÖ…¤îfÕRw³¶‚Ò–KÊä£7 ¼æy¨Ày N<[]“^~,Ïñí7\ýx NžzÛ–rÛ–Ö@ŠëW‰ÜæuƒÛzI‹³ªm^Õv|{ÉmKÁç·Ï(ÁÍz4ÀÍ—A_@Ö8òxêbÀm^ ÀÍo€bœõ̾Ë$“ܶW@V3ÀÍk†/ Ïr}–¯±Í{e§ãV¹Cü… j±Zx‘DZN¿_,2ì‚cUç'çÞéóÇ"»Å›Úö”iâNvÄs89wÄyÂNν‚;ñäÜ;‰ñȉŽÎEЬ0qt.V‡7ÏíáèÜ>i “sá'H·€“sá½G•ÇɹXꜜ³[àɹÈS)iã¥È6'ç<fÁïSåœ;"\ärr.Ö•²ºÄɹ¸êvt‹¡LC[œ;—Q3NÎc²Öɹ(—'yr®ïA'çº\œ‹{x0Ùó䜧@xkUˆº›m Jwë»ÔÝ:4Ÿt·8 .ÛMènÛ Kvëè}’ÝzçI²[›1Hw‹)H ˜k£PÙO¶‘ (Ý\ò³ÚiÁ~²-üd@Ù<² ¬à>b9·©„çŠî#”ó‹Àrmt+–+§nÅrfæF˜kW?¢¹ÚÞ͵½¯h®½Y ç:.‡p®¼z ç< p®¿‰çÚ׎€®}Š èÚØX@×~@Dt÷H–ãeTùöÅÓD:k™®œäÓͶh$ÔÕ6™Î®Òµ«“BºÚ`)¤+*ÑÕ~ˆ.˜Ax9õ1€Ðɤ“<×wØ<'"ÎõÚE8W-ÍõN„hî\d7_ 纡 LÑœr_ çºâœS<×v“º­Ì«t[ Ø¿!ºZä è>eÄÝ@'Z+ž+î"Ðu7ˆè>z‡t†xº®š±î½ŠG‰uíÔWXgŠXgH¬‹õȱ`]{Š×u À®oRdWÙu{…v}OB»nŒÐΊÙy1 ;¯d×JdçwËU>÷µj]b¹ ÌQ>ÔEvV7ÉÎÊ!ÚõÃÚõ°ÚõsÚÙ=íz˜íú¥ÛõÐÜõÐÜõä'¸óRw5K îzæÜõŽ´àΊ!ÜÙ-$ÝYÕ¤»8ê,RÝõì'¼³Æ€îz| ï, éN ‹¿à¼ZÔˆß3£¾>@(ê 7!™¤¾XñÒ–з¾¹BRÙè.%z›ˆGè‹Õ÷â.e¿v®ÒÅ2ŽÇb úÎÖà}áç „¾sÒûƒ /z—à•Ð.fy‚¾w>ý˜}ûU^a}±œ•›@ߎKè3à$ôíq––%úöû£ľx’7Ðd-¤ôí7 âK¿8¬Ä)²òñ½_,¹` ñf“Ý|–Þ /ºüÓSÊëp7´ŒoOûN™ÀîSçÒÓSÊû塯yJÙç%Ÿ'p”]®Ýe–ËÅ»LYì,³"YÂSŠWO){Lh”ºà)ÅJ¦§”D 7´ŒœŽ‹§§”pL8¦§/žR¢ƒCKÛ£§ë,zJ±;§§”xt“%ÃSJï«ÈSJ”|º¥eŽ4‘<¥ìCGÑÓQJ ¼éÌ·¤ÀQJo¡ÈQJ r’ƒ£”äÜ £”˜‰ÜÒ2á2õ¡«”=Œ:e{™Çº#«ŽÉÁWJdý¸ŠhQ•?;Þämñ•²ã‡ŸœË„ÇÎyEt•N§7?<ËyÝ7}¥Ø-ÐWŠUW)q÷§Ÿ >)¿'p•Ò3 \¥xóà+eß9Ž}Áv¢ úJ‰6¾Rb~¡ÁWŠ]E_)q›ÄÁWJMr•ÅH‚ W){¸Aãω'ð‘;zJ‰K?Jô”bõÀQŠu¥ô¼-G)1¼8kÐQÊû ËÏ ¥ÄüO"ô”•úA O)ñqÕ 9xJÙÓK§”½'ÑSJ ¬kñ”b=CO)ñBl‹§”xÜòO)QòrŒ.ºMކè)Å:žR¢…|9ÒSŠu(=¥Ø£¤§”|…éâžR¢ÿ†Û]æÈ_ô¼|œœé)ÅÞºJ±öÑUÊ~²1÷þíè'å}iô榟/ô©ï©58J‰›<˜ð|äô“²ŸÚ×”Ÿ»nRâ"ÚfÂKJ¬"ËK1è%ÅJ“”xH´jM')Ñ~')vÏt’b…ÀIŠ=i:I w÷œÚé$%.Ò©68I±1D')žNRlt¦—«‰^R<^RlÄÐKJx”Ë–‹ï :NR¼˜Yoò)·)S·ÀG/)ö:ÑMJLžôãE7)6¤ÓMŠu ý¤ôœA7)~ ܤØôJ7)½´“›ë+ºIÙ‡œöÐKŠNzI‰—IUÁKн(ô’Ò•ÃKJÜuQà­‡°zI‰{ztŠŸÓS~°ä%er·$/)ˆ’ðß ûòžè%ƒNRºƒå%ÅSà%¥¼¤TÃIJâä$¥G¹œ¤DL‡cñ’Ò“•¼¤D9n†™]u:ôågïÃm\y´’“”èˆÅÓH')1»_Ô¯sÍ')ïüÍYP^RzxÊKŠ×ýðsZyè%%ÊÙtànêMåUt“²‡çCæÙù==Ë‚óÈ;˜| å&Åz‚nRl`ÑMJ?'ºI‰‰üZܤب¡›”ըם´×wשÌã5S׿½Î<^3Ïßôxýs JqÓkÿÝRÌ]õ¹‡ /J)V“¬¨Jñ¢"F“”¿½˜HðBðÛŠŸä<ï:¦X1L²‚*Å‹ZŸ•==/j}0þ¨þå~¸c:§;âßÙá ÿš?9:nçÚGøpßï´ûÍð~6®Ÿ\+aü3WÞß|rÿjxÓžËï:±QVÏÝ(Ëüm£(÷·Í’: Züv£÷¶‚oÛ,Ér±¨Õs7Ë2oÛ,˽m«¬Î¥²ÏÝ,˼m³,÷¶­²:—ÊZ"ŽÉý²Oî?1Íÿr6ýiRÿÇ?™˜—\¿šþ¦Oî3Wxæ’û/8Ýþ³nµÿ=|rǤëÿ…[íó“¸þ¿[íÿñ+·ÚÿãïºÕ>òøøûÜaójœhå†÷sÆòèŽÅ/÷õŸË£;Ïr0ϵ}Ímj¹n¹‡»™:®žu€ç™p"÷b=÷ãlú}r— ¹: ŸºXwŸzG#ž)9øÌ@ç}¤`”8CÌ„ K›ÉÕÜùÁ¦ßËÅ”3&Ö(üü`Ëïm7[w†ÿ»w}ªèÊ݆36…6¤Ü¹Û0Ξ·Ï¸™·äñ°ÉÖÌÜmH On6Œ·›á¥ïÜ>¹ÙpmÚü8ÃGxFh`DÉHIJ9/m¿ß€Å>ÜÖ87lùÅ^ ””3üvÇ-ÜÚµ<7lù(—)#7ÎGÞÎÏ {~±·Â,Wî5DØ,l&¶üÆ.ßÜç6s¯!Âd±'â™E`ˆÏÉó›’Û #¼¦#eÿD¹o›0FÎ}Ëí†u‘°çnCìØÀÃæ9î âþ ¢ýÈí†!ã0Fvlù—­°ÕyÆ‚;ªz[¼±á7ÞYìþ¦ÌåÙŸØî—\–¼ ¹Ùå€ä<¯|‘¯ÜÊ@Bî5Ä#íç{ #|0eîèÛÔçù|ðìè7%7ìÅ+½-yöû2Àj!ØÙSØí‹‡‚ýÓ·Ór³arÉzìöE:°Ú›ò` nýŸ»}QvÝÎq¸‡‡³ò;Oíèâ†ë¸ ñycâMŽ ¦<¹ÛÅñ-O…¿Ù×çÑ[ŠCžçµåvCÔ½3Ï~ânõñuävCÔýQJî7D9¼èÌ톻…Ì‚-¿è®‡¹6ŒòºÍ`8﬈Ì;Сì,„ç]®y6<†£ƒM?kBôæ<ˆ‹"DïÄ OÎ'bô¾m”—ΈÒ{ãµä·¡zýIE°Þk™Â"\oÞ_±Ø;–þDÌÞXhÓCìA{OLWœ¸µ7?,·Ròƒ#€Oq{}’ˆÈ½ûÒÅÝ›%s¤Ç§~[ÆÂ÷¾o•¬bψßû>ºÉÁ|7 o$ܸ…“ó`èî1Ù„#$¤ƒî¦›7åþ€€´u"„o|pT,Â…\ÀÉA|3…£ü>ÂuÊÁ”=<©¡Ï60'pâC$ß|»y‡Ôp¿[~ž5<'$DóÍ1Âiì³ ×ˆçûæ9µ>A@ß%äp›mÔ7Ÿ7¿°ÏscÀ⽈é›K,¨ÆrøØ¤6 ÄôÝ"p&f€ñy&¯Â®_„ÛÄ<ÆýŽ÷y8Bbú¾yo`| ‡GΛyb×/j:™bx”‚Þˆéû¦ ~¨ÇŠx¿ÎQ}ßr>Üiˆê›s<ÆÀØ ‰Çød݈êû–¼ó9Œ š¸Õ…°¾yVcƒ&>² çå¯áØ ‰Gcn M<.Á–îØ ‰÷ga ªï’M¼–‰A}³?w I|ÄÐE{Ô7ûߎ±CïÞ@\ßh($#âúFNnìXçûr³\Hâý­;ÖÇ15ŸJÁw5õ áâgõªÆ@Ï(­ÌE¼×Kq}sQÈr!ˆ[{Ø×‹9B·§„°¾yÍÅPÄ{>Ö7Å<ô0(â!¦²?Ö×–?ã€$ ¬êʰ¾ñöIÂúÆ{SWa}|Æ3åUÄãÙq¤!‰g[æÀJ¹å›yB9uà¸ñïs.úþ´Oí¿KBµ¡6å-Ü·—gq_íÑÜwå2‰àw£Ó¾ àwçiy¿øÑ—Á/ì‘h=Lò›Û£mm’Ÿ¹Ù&ùEÀu¿“üÌîžè÷l“_€ßsל™Ü÷ }ÄIøÔŠÝ ÷EÜ~OÈ}1å KÁ}IiäGp_ØŸ°µÀ¾4ZáEྠqIŒúPd–%îÛF}æÉ}ASB­}|™Y„¸¯-œÄ}!·s‘IîÛßeÏͺÁ}!Qð¦È}ñ. ¥ä‡*ÂhÏüâP À}q¡‰Ü—1©Ùp_¼Ø;qì“çggJÜ/;‹à/K!ø…»†à—ÛÏD8€ßñ>°q à ˆ[)ù:1¹ï¸Åg‰}ñwv'±ïŒÏ¶@0¿RñRsLì‹»>NÀ¾ó|ŠéÀ}‘¹ïÜ­ È}W܇ ÷Å·@ˆ~aœ¡r€~çUèšèwæŠ+ýÎ8Îú½óäÅÉ/š'8$ùiþlò »Ö%òÛ´’ùÅ"”TGò{ß3LžE~/ÞqÔüjDùi[¥À¯ !øÅ—U)¿èz$Á¯ÉEàgPGð‹ƒHIð B vüzDà7G±V‚ßÛg,—àÊ98~]®À/L‰P®À/ .¦$øÅ~°È/˜½#ò{׸›8oÃ.Ù&´Jò»ÞÇÂA/ò{kºò‹<ó€ü®Ï¦ù”äwí‡F1ÉïŠ5‘èŽÎ‘ò³Æü®ŠQ•È/Ôy2È/6'ðEùEŸ¬äwí²zùEƒùþ“ü®P~WÀ³ü¢ë…ª¿(˜“Á/l”ø®ü¢`nü®¡sw?뛿è½]œ‡˜C¶s"¿èŽb¢_Œ$NËd?»q²_<;Nsd¿è®|Hø{d6Tð Ä$F¨ýCþ¢ÍÜüÅ'›Àø³öþ®­–„¿ë¦øù!üùU€¿xMT2àÏúðwí §€¿+ñH˜ÜKUœC±Ÿü,£¯Ø/Ö©¤-°_ŒÙ]4˜ßÔ¨z#1‚ýzDŠýâÝ_ÐïÚ÷ÂC _ôÍNŒúyÁ׉Äýú„~×.s¡ßujÃ]è=C úõsúYWý®CÆB¿˜X2Ñ/§¦ý®c/Ž öË©ja¿×b¿¸†ý€ïÃGÛR'Ð/.b¹@¿ë¤@¡_LŠ„W¢_<ÈV@¿h Æ‘Ðï{Ù>q¢/ _4F¥ýBž ú]'wwE~Ñæù]ï#%“ü®C–ú"¿ëÔÏü¦^ïÛ 4÷…£ˆÜwŠ2î³Æ’û®ˆåI¦÷Eö7¹ïŠ]R¸Ïž ¹/ò´È}×»nÓûz*÷ÅUbC,㪓uû®·‡n¶ùÉšžÂ@|SßÒ9~‰}ÖÒîß<'Ôõ?ï†[ä®qïéäƒw,’_¬€…q‰~“GrRîK÷ÏÂÀtM×^¹Kï“ëä’ûbãÔ÷—H¦ô¾Št*½/"q’« ÷Åœ\ÅX¨÷£M/Ê}a/c4ÔYðØ§ ¸-O¹ooÂÍ”üFåhaÊEãb û€ü ,ûrõ¿p_˜uî [un’ûÒ›ˆî;îQ%½ïÑg?¹/ÌÎ%°ûB¹#äQî3ò¢Ü§Í•RûŽ&Nª}1U,r_À¿²%÷M}éˆ})‡Ä½][˜Ôsˆ})\{Aî‹iŽì‹u:ûSz_o…ûÂ4Ëqé}aË`_ ’z_Ì…JÉoÔy)0Eé}µ¥ð;o½¼¿Þ°ø½«) é}µWà‹2?Sæ~S±bKð;äT°¿x_˜BÍ/ÌÔÍ/ÆÀ½h~Ï)”èZÉ/Œ‰ª ?Sމ~A|2Eîô7b:&¶Qö3p#ý­ðŠº_¬vˆ`Ä¿ˆ´Hp;æŠvÒý6á_mbþ½ƒ—OSÂ_®ð/.f ñ/‡]&þÂä–·)ݯɎôwÍïô×úè/‹}£¿êPá_ÙŠ­ßþI!ý½Ë+r¼èïE®ÐE-ˆþ¹) ŠþJâ)ú«50e¿[o™d¿ÈHºjÙ€-ú{šß¶ìWó‚详èo“ÔBú»b¢dê~ñþ2èoè.E-' þ p$ûE”d&`­¨Åm‰~ñ9cÊÆ%g-ó¥úÅ’Ùo—_Îf¿KÍûm:‡BÕ/ŒwÕÏ@@ªßséõûµ$Õ¯Öù \O–è×ʺØoúÚIô‹6•6²ß¡M¤B¿G­!úMÝ‘ÐïÓѯ–²~·´ÍB?Y¼ú…17K&ú²¶ú…1§G¢_ŸÙÝ϶„~Á'LÙðá\ѯñµÐ¯ðZè7µ­Ðo׫B¿ZSú5Ö‘üÎ[£¼Èïj‘ËÎS1HýjOè÷α+úEc>¤/¢ß¡ók…~MRB¿¦ƒB¿›7Uì×ÄSì÷”èHö4ëúiã¡Ð/Ž+(è§ž)ò[ÕCò“Fì;Ñ·°/6«‰kľ°/Z±¯Þ°Â¾b™¢¾«”¹¤¾n‰¨¯YÔ7̱°ïí@‚€°/lW¾aŸ6ˆ‹ûªç„}»Î%ö]:(ÛØÇ×´©ïækI꫽ ¢¾‹‹ê‚¾C§ úÞ,‡Rn™o„‹…çg–’È·]2Þ!ñm{­qI|‘e,Ä·Õq"ß¾ßZuHè{Ê*Ä×Î D|A—üP’øŽOI$¾>P$â3J…ÒW§ÐD|ÇY¦DRúB$™ùŽ]z‹„¾©‰§„¾0šãEú¶6Åx>ÆñÍÂ󸔿)¥o?KxòÅ+Äï?”¾wA2ä;ŽQ†˜@¾PØù”Ò·7vù‚81RúÆÞº”¾£6‡¥ôÍR„ˆ|§ÄÁúZ4“Ðwé¼~ñÞVöúŽYdÞ;‚ÃIXúnmZ˜ÎÇ•t¾S‘ÏKç VçUÒù†Ö½½V+ÐùÆ^USè‹Ï:¸×ê•„¾¡y±”¾–í„{ñq"„÷b½E]Œbß5+p/ ŠË©}CÝ ÷¶»Œ8÷»ç‚{f’LÜ;õ“¬gÆ™’ú¦¸H¬gÕ€õŒÝKê+.ìÅÄB#ìµÅ4aïŒÁâR_™] ö¢5|y{ùŠgX/Úô¬¬7J»ì½ËNP‚½x*L!ì½cP•ö®]U‘õzŸC¬×F¨ÿOeç’,±­ÃÐyóÊY²–‘Ê6²ÿñ3D¤º’A†×Õ×íöGÒ!:XÏu¡^"¹Pü]èÃzI`¨÷­>9<Éá™B¤P/íÑúúi'Qý5¹çeñ|íÍêe!DO<ºÄA²^:údñLÄíeyBBÀKº^Ðr}í%‰öÊ~èñ´³:`/+‚=¬çˆ„½o,æU‘ÅóµA°‡…÷KØKiH´‡Þ5„'Zikvy~Ãı¹áû?uù¶¨w­®~…òÐ)•/ïUŽÏïq%åÕwóæ7kmvÎÒ*œ˜÷"ÍîÄ<´L`Ç rÞùjÜçÁn(>‹·¤b Ƶ89¯¬BÉy7´QÊvÁyðŠ Ú(íݼ¸’|ïí½Ä=ÜšªŸä¼¬ KØûÀ{öŠìDÌ+â•r|WÂ!…½cج© ŸW.ļâm#æ“H{x¬ø? òe¹–˜‡µ  Ä<ŒjÇ&íÁmÏs.iþ7EûbNÊ9¯•ä›ÝE òYvwoÙØ°(/ÎñM³ )c„ÄÀkþØgHyYååaÛýœù:Èç™M”‡Á‘ë‰zÅ+£ Âĺ×3Å ‚^Î}½Œ–‘órÄè•雠׋ö ‡"¹¶è±¶é ßl–ùž^«€¢¼¢lòrÞ³¨WÄBŠz©8‘ò?¢^Ú§HyåpIyåz“òêg‚òJM?D½ïvÛE½¦”¨—„Ã|~R%êe†Ôi>§S%êeW çìG‚žeQƒÞa¶"èM?ß ôð7e*^"%AoãºK#ÉûEî Ç,’^Ã}°‘FGé…Az­ÝVƒôZÓT'Ôkx!8PU™&zítA‹¬‡ ÆóGÖ«[‚õðÝÄb²^:Œ‰z ‘O"c Â}SõÚÍÞ["=|ÓЖ¹ýF’^ù$=„šyOôúú‘ƒôZW‡D‘ö|mºΰº =üEƒôŠA¤W¾‹¤×€[ÅÓ ã† -P/Ó B=TNH´D=ÜIs3uâІ7n$òHzåTôpûµM×CŒýØt=<òLéçÃ"½}'镚I¯Ác˜æ›ç®‡KæQÆùòŸ†ÃñúH€nضÅùV P€^»7Êk0=pËùl®zR^»ôÂQ^¹óHyå‹Iy÷´ÎKÊCbQÿ”‡ 'Ÿ'RÞ=59òbD\^ÖMÓ»Œ‡$’Rƒs=:šÅxX_*¶‰)´ÁÂ/Wˆ‡âVl/ʦ>5B¼o×"•ˆW§·81BG¾ÊdÊã-Ä»_M6B<´àЖɈ„•)">³©zx èº#áeHT„—Ù F¹K[¢rzNöµõ·›ŠðJŒ„‡Rï»F=þÆ' }/+§jJ(Âs°B€—7Ÿ÷¸b{Ax­wî‚ðr0 ÂË)B„×£$ Ñ•)óæ!ÏCD< XbÉ@¼Õtósb®•ìˆ×^9ß„x™⡬L%’Œ‡±G2Ù¹¦ÔËÎÓSªHìâ”ÚÒÀyÉÇÃBõU‰kí' ï(ìø›°‡-»¥S¼¬¡ô¾yÁQ£|‡„¼+>ñn˜—-2Ê×tåcÚê¿´û."Þª³‹|zíᅧ|7óÞY_®!_çzó1d>´~a¯<òZžÿkIõwñuGžÝÇÅ.%õqAC¼ ÿ²g­¹<ަ«‘ Ö…ÅÙÙÐF}svÞÃE@5rÉEš¹x00>†0`zFÕÈejê'¢Î?v¼4Ö‹ÿ¢È¥{B4rI7™øï[jˆÉèìÌŸ)gçwÜœÖÅ)]ˆÿ²<+kçÔ›ªmíÌš¸ø/×ÊÀ«û €PñÖ†pv&°3”/Lû“:¹äÏ^ÖÖÔÉ%;~U³2ÿa͸óÒàü§ÕÈ¥˜JÉÿ}Ën.ŠÄyÀjä’ñ,`RÔÉ%÷#´¡ÄÆÎWÓg m¹bÀtÚ¡acgéÝ(k¹  Ó7¯ùE€` gë‘N ÊÖ™„-lê%n[ç÷(ì©>”æ¤ë-tåØ˜^, ˜PÿC|õRw èžëk`º1D€¨Öj?A€é–Ø ]‘Õ/ådÁîµE€p³ˆÓ.–$ÕVWØáë£"×.y•x½I€¿éa¡[f ìoÒç ÅŽ2`Ÿ©þ½ô¡<‰Ä02àjÐ˽\MQá©n{1 >ónÍ\f›µ¿©+ä·fÕÑNÇõˉ!âüîÝ\êgã[.Œ ËGëÿÛp 6Ä€£M·€ \C¿:§oC@ •U" ŽæÙº¹Œ¡õ¥W®DwI^" îV¢/p Y„€8˜ÝÛYÎ ¿[NÎ@ÀñžJßâb²²AÄá6Çþ ‹ÿpx—x£Á)ÍoêÜ[¦/ïNâßèì]ñ×þñÊvI²endstream endobj 6 0 obj 185514 endobj 4 0 obj <> /Contents 5 0 R >> endobj 3 0 obj << /Type /Pages /Kids [ 4 0 R ] /Count 1 >> endobj 1 0 obj <> endobj 7 0 obj <>endobj 9 0 obj <> endobj 10 0 obj <> endobj 8 0 obj <> endobj 11 0 obj <>stream 2020-03-05T16:33:14-06:00 2020-03-05T16:33:14-06:00 GL2PS 1.4.0, (C) 1999-2017 C. Geuzaine gl2ps_renderer figureOctave endstream endobj 2 0 obj <>endobj xref 0 12 0000000000 65535 f 0000185831 00000 n 0000187581 00000 n 0000185772 00000 n 0000185621 00000 n 0000000015 00000 n 0000185599 00000 n 0000185896 00000 n 0000185996 00000 n 0000185937 00000 n 0000185966 00000 n 0000186060 00000 n trailer << /Size 12 /Root 1 0 R /Info 2 0 R /ID [<118847EA2CA42CBB66F684EB5504674D><118847EA2CA42CBB66F684EB5504674D>] >> startxref 187801 %%EOF blis-0.9.0/docs/graphs/sup/dgemm_rrr_has_nt1.png000066400000000000000000007447321422157504600216240ustar00rootroot00000000000000‰PNG  IHDRTjûF¦Â &iCCPiccH‰••gP“YÇïó<é…@B‡PC‘*%€”Z(Ò«¨@èPElˆ¸+Šˆ4EE\•"kE ‹‚tƒ,ʺqQAYpß÷?¼ÿ™{ÏoþsæÞsÏùp ˆƒeÁË{bRºÀÛÉŽÌß(ŒŸ–ÂñôtßÕ»­Ä{ºßÏù®‘iü常¼rù)‚t ìeÖÌJOYá£ËLÿÂgWX°\à2ßXáèyìKο,ú’ãëÍ]~ )úÿ†ÿsïŠT8‚ôبÈl¦OrTzV˜ ’™¶Ò —Ëô$GÅ&D~Sðÿ•ü¥Gf§¯DnrÊ&AltL:ó5204_gñÆëK!FÿÏgE_½äzØs û¾zá•tî@úÑWOm¹¯”|:îð3™ÿz¨• €è@(U  t0–À8à|AØø $ȹ`(E`8ª@-hM œà<¸®ƒÛà.L‚—@Þ‚°¢A2¤é@F²† 7È ‚B¡h( Ê€r¡PT UAuPô tºÝ„¡‡Ð84ý }„˜ÓaXÖ‡Ù0v…}áõp4œ çÀùð^¸®‡OÂðø6< á—ð"Â@”]„p$‰BÈV¤)Gê‘V¤éCî!Bdù€Â h(&Je‰rFù¡ø¨TÔVT1ª uÕêEÝC£D¨Ïh2Z­ƒ¶@óÐèhtº]ŽnD·£¯¡‡Ñ“èw †aaÌ0Θ Lf3¦sÓ†¹ŒÄL`æ°X¬ Vk…õÀ†aÓ±ØJìIì%ìvûGÄ)áŒpޏ`\.WŽkÆ]Ä á¦p xq¼:ÞïÀo—àðÝø;øIüA‚À"X| q„„ B+áaŒð†H$ª͉^ÄXâvbññqœøD%i“¸¤Ri/é8é2é!é ™LÖ Û’ƒÉéä½ä&òUòSò{1š˜žO,Bl›XµX‡ØØ+ ž¢NáP6Pr(å”3”;”Yq¼¸†8WJ)Hq¤"¥öHµJ IÍKËIÛJGJJ·IK”aÊ8ÈÄËì—é”y"‹’Õ–õ’Í’="{MvVŽ.g)Ç—+”;-÷H–×–÷–ß,L¾_~NAQÁI!E¡RáªÂ¬"CÑV1N±Lñ¢âŒMÉZ)V©Lé’Ò ¦$“ÃL`V0{™"eyegå å:åå–ŠŸJžJ›ÊU‚*[5JµLµGU¤¦¤æ®–«Ö¢öH¯ÎVQ?¤Þ§>¯ÁÒÐØ­Ñ©1Í’fñX9¬Ö˜&YÓF3U³^ó¾F‹­¯uXë®6¬m¢£]­}GÖ1Õ‰Õ9¬3¸ ½Ê|UÒªúU£º$]Žn¦n‹î¸CÏM/O¯Sš~°þ~ý>ýÏ&   ©†.†y†Ý†iñªî¯&¯v\½mu×êׯ:Æ‘ÆGŒ˜ÐLÜMv›ô˜|253˜¶šÎ˜©™…šÕ˜²élOv1û†9ÚÜÎ|›ùyó¦é§-þ²ÔµŒ·l¶œ^ÃZ¹¦aÍ„•ŠU˜U•Кij}ÔZh£lfSoóÌVÕ6¶ÑvУʼnãœä¼²3°صÛÍs-¸[¸—í{'ûBûªƒŸC•ÃSGÇhÇG‘“‰Óf§ËÎhgWçýΣ<Ÿ×Ĺ˜¹lqéu%¹ú¸V¹>sÓv¸u»Ãî.îÜÇÖª¯MZÛé—ˆÿ2Â6¢,b&Ò*²4r*Ê*ª4j:Ú*ú@ôLŒMLyÌl,7¶*öuœs\mÜ|¼Güñø¥„€„¶D\bhâ¹$jR|Ro²brvò`ŠNJAŠ0Õ"õ`ªHà*hLƒÒÖ§u¥Ó—?Åþ ÍŒ]ã™Ö™Õ™ï³ü³ÎdKd'e÷oÒÞ´gÓTŽcÎO›Q›ù›{r•swäŽoál©Û m ßÚ³Mu[þ¶ÉíNÛOì ìˆßñ[žA^iÞÛ;»óò·çOìrÚÕR V (Ým¹»öÔ±? ìY½§rÏçˆÂ[EEåE‹Åüâ[?þXñãÒÞ¨½%¦%Göaö%íÙo³ÿD©DiNéÄ÷e̲²·7¼Yn\^{ˆp(ã°Â­¢«R­r_åbULÕpµ]u[|ÍžšùÇ‡ŽØi­U¨-ªýx4öèƒ:§ºŽzúòc˜c™Çž7ø7ôýÄþ©©Q¶±¨ñÓñ¤ãÂÞ'z›Ìšššå›KZà–Œ–™“!'ïþlÿsW«nk]£­è8•qêÅ/¡¿Œœv=Ýs†}¦õ¬úÙšvZ{aÔ±©CÔÓ)ì ê<çr®§Û²»ýW½_ŸW>_}AòBÉEÂÅü‹K—r.Í]N¹<{%úÊDÏÆžÇW¯Þïõê¸æzíÆuÇëWû8}—nXÝ8Óâæ¹[ì[·Mowô›ô·ÿfò[û€é@dz;]wÍïv®¼8d3tåžý½ë÷y÷o¯ñy02*|ñ`úaÂÃ×2-<Þ>†+|"þ¤ü©üÓúßµ~oš /ŒÛ÷?óyöx‚?ñò´?'󟓟—O)M5MMŸŸqœ¹ûb݋ɗ)/f þ”ø³æ•櫳ÙþÕ/ M¾¼^ú»øÌ›ãoßöÌyÎ=}—øna¾ð½ÌûØú>|œZÈZÄ.V|ÒúÔýÙõóØRâÒÒ?B,¾“sMT cHRMz&€„ú€èu0ê`:˜pœºQ<bKGDÿÿÿ ½§“ oFFsF×j`` pHYsNNÆÊ/¥tIMEä&>(Ê vpAg´¨“ÁQè€IDATxÚì½{œe•ÿÿ—\ ̤bœob (˜ÑYw±Z@T\ÖîAÙPé^W]ÖýF»×ýÉ*~w·[ç»Êêêv¿èzÍ´ËŠ»:å”Qq Q3"†)‚C AœJ& I¸Íï§Ÿªêžž™žK_frÞ¯WÒ=ÕUÕOU×yê©óyÎ9KÆÇÇÇAAAAAA&å˜f7@AAAAA¡ÕAEAAAAAaDPAAAAAA˜TAAAAAA¦AAAAAAA„iAEAAAAAaDPAAAAAA˜†£BP) 8ŽÓìf%|ßÇq\×ó¾<Ï£P(4û„Y"¶¹8ð<¯ªM‹}.lÄ>7µÚ§ëºø¾ßìæ 3@lwqPíÞ:“ûªØnë!¶ÙZÌç3)ˆ}.tÄ>[‹ÙÚ§<—.Ä&/‹Å A¥X,Š!¶®ëÒÙÙI.—#‘HJ¥æ´?Ïó(‹Í>,a–ˆm.|2™ ]]]UmZìsa#ö¹¸©Å>=Ï#‹Í›³Ih b» ŸÉî­µÞWÅv[±ÍÖa¾ŸIAìs¡#öÙ:ÌÖ>å¹tq!6¹xY,öx\³ ]$ Òé4étß÷éêê¢X,Ç›Ý4Afˆçyär9†‡‡1Mß÷Y½z5Éd˲šÝ'³Mh-ûœ­mV¶­š}ÖëÞ9[ûœ©EïŸúo˲ä!t ãÞé÷7Õ}´Y¶;Ù1ÍäÞZi·z™Ønk ãÞÚöÙèçÒéžI';¦¹ÞWõ2±ÏÖàh÷N÷Y-ûlô¸w¶ö)Ï¥ ÏN¿¿…4ž=*ü¸ã‹Œáááq`<›ÍާÓéq`:::žL&Çñþþþññññàs½mÿ¸aÁ>Óéôøøøøx6›ð¶mm˜ÉºÓŒ'“ÉñÑÑÑñÁÁÁqÃ0Æûûû']^ËþlÛïïïðwµujÙg-Ç›ÏçÇmÛ^ãñxY›';¦ÊãÕ¿‹þLï?™LŽ[–´yªí„Æ3•mŽ/8ûœÊ[Å>k=ÖZle²cJ&“ãñx|<ŸÏÇãñ²ó7™}Šm¶s±Ï©ls||f6Woûœ­mê}NeŸõºwÎÖ>s¹Ü”ÛMuÿ7Ms|tt48&¡5‘qïôû›î>Ú,Ûê˜&»·Ne·ããb»­„Œ{[÷¹tºgÒÉŽi.÷Õñq±ÏVâh÷N÷ÙtûlƸw¶ö)Ï¥ ÏN¿¿…6ž=ü¸‹NPI§ÓãÉd²l™išãétz<›Í–¾èô“ÏçÇ-Ë*Û6™LƬÑ?pôïJC¬uÝéÊŒAÈdËkÙŸ¾ÙWû{²eÓí³–ãÕçQßõßÑÁGµcÒTíwÖûO&“ã†a”m?ÕvBã™Ê6ÇÇÇœ}Neƒ­bŸµk-¶2Ù1¥Óéàw4M³l›ÉìSl³õ˜‹}Ne›ãã3³¹zÛçlmSïs*û¬×½s¶ö™Ëå¦Ün2û7Ms|pppÆçHh<2î~ÓÝG›e»SÓd÷֩ƽb»­…Œ{[÷¹tºgÒÉŽi¶÷UýûŠ}¶G˸wºÏ¦Ûg3ƽ³µOy.]ØÈxvúý-´ñìÑàÇ]t)¿\× Âü4¦i*„>^[¹žçy¸®Ë’%K‚­ZTÙÎé–O‡>“ý=Ù²ùÀ4Múúú°m›l6K2™,;Ç“SeX´axžPÎVYÜoªí„Æ2•m´ϩlp¡Ùg-¶RyL·ÝvÅb‘ÁÁA²Ù,ÃÃø®K.— Ö™Ì>Å6[‹¹Øg+ÚfekY^ ÓÙg½î³±ÏZ¶«fŸ¹\˲ð}?H»àº®ÏmQdÜ;=µÜG›e»ÕŽ©P(Lyoì¾*¶ÛZȸ·6š5îî™t²cšÍ}Ä>[£iÜ;ÝgSѬqïlìSžK62žž…6žn»ÅàÇ]tEé§ËG:Õ`¶mÓßß?á³hG,ÌÛ¶'äò«µ3©üÝ¢ù-Ë"ŸÏcš&©TŠÁÁÁ`¿Sm'4–Zr‹}6ÙØÊîÝ»1M³ÌŽmÛžÖ>gû}Bý˜‹}Ne›Âü0[{™n»ÉìÓ÷ý _õׯ_/¶ÙbÌÅ>Å6ëÏlíe&ÛEïŸ2[vá ãÞÖf6¶«Õî­S{Ån[ ÷¶.õx&­†Øgë"ãÞÖe¶ö)Ï¥ ϶6óý,ºXü¸KJEd®ë!´Ñ0[:äû>¶m³dÉFGG'äÅô<Ã0dðSfz~Ç!—ËÑßßã8ußN¨/ÕlÄ>›É\m¥Q6-ÔŸ¹Ø§Øf}{ P 2îm=}oZ÷¶.2~dÜÛºÌöüŠ]/ld<Ûz4úYt!Ù䢋PÑT;á¾ï‹Åèëëò,2™ ¶mW-~T¯b>Ïó¦,”dÛöŒCšæ{Ÿõh#ÌíüÎ6Ì«ÃÃŽV&ë ³}.{n7SšaÓB}˜‹}.DÛ\HûÔÛͱ³ÅŒ{ç¾ÏzÙ­Þv¦4âwêŒ{羿zíSƯ‚Œ{[wŸ³=¿b× ÏÎ}Ÿ­6žmÆvbÑ *Õ0M“|>äf3M“¾¾¾¦´ENšª­ÍÞg=Ú8f«H¶²’)Ld1Ûg«Û{£mElsáÑ*öÙê¶T}Ê=P˜-­b·ÐúvV¯ý‰ “±˜ís!ØûlÏ“ØôÑA«ØçB±¥V°ÏÙ"vÝú´Š=°ŸVÏ ϰ‹6å— ‚ ‚ ‚ ‚ ‚ Â|qL³ ‚ ‚ ‚ ‚ ‚ ‚Ðꈠ"‚ ‚ ‚ ‚ ‚ ‚0 "¨‚ ‚ ‚ ‚ ‚ ‚ Lƒ*‚ ‚ ‚ ‚ ‚ ‚ Ó ‚Š ‚ ‚ ‚ ‚ ‚ Â4ˆ "‚ ‚ ‚ ‚ ‚ ‚0 Ç5»såÜsÏeãÆÍnƤìÙ³‡5kÖ4»“røða>̪U«šÝ”IiõsøðÃsíµ×òæ7¿¹ÙMi)þéŸþ ÇqX¿~}³›2)­~míÝ»—åË—³|ùòf7¥* ¡ÿâž{îiv3ZŽ /¼°¥ms!\[ÒÌ}ûö±zõjnºé¦f7¥åhõ±m­´ú58ZÝÞk¥ÖßDƶÕùÊW¾ÂÖ­[[úþY+GÛ5½¨õ7‘±muZ}l[+ a \+‹¥Ÿ©õ7‘±íäœsÎ9¼ä%/iv3&¥Õï% ¡_hu{ÿÍo~Ã[ÞòÞõ®wÍÛ>.¨ŒŒŒ022R¶lÓ¦M´µµ•}ÞÑÑAGGÇ´ûÛ¸q#7ß|s££f®¹æš–nßÀÀlÙ²¥ÙM™”V?‡½½½‹bð6mFשÅ>/¸à–.]*×Öèíí¥»»›îîîf7¥* ¥ÿX Ì·}®_¿¾¥¯ý…rmµò9\(ýÇbàhÛÖJ«_ƒ3¡Õí½VjýMdl[õë×óÚ×¾¶¥ïMµr´]Ó ZÛV§ÕǶµ²ÆÀµ²Xú™ZÛNÎÒ¥K[úZhõ{ÉBèZÝމ˖-›×}6\PéííåŽ;î([vóÍ7ÓÝÝͶmÛèííeÓ¦Mlß¾-[¶ÐÓÓÓè&Î+­|Áƒêké›I«ŸÃÅÂT¶ ˆ}6žžÚÛۛ݌IYýÇbáh³Ï…pmIÿ!h޶±m­,¦k°Õí½VÓoR GÛ½s&È5Ýz,–ߤVÄ>«³ÆÀµ²X®éÅô›ÔÊ|m[}’F«ßKÂ5Øêö~ÖYg±aÆyÝgÕ±±±²e”ÞÞ^n¼ñFº»»âòË/§»»»å/œ©hõ” mmme³@Z‘V?‡‹…©lÄ>›A«ŸÛ…Ð,Ž6û\×–ô‚æhÛÖÊb:ÆV·÷ZYL¿I-m÷Ι ×të±X~“Zû¬ÎB×Êb¹¦ÓoR+ó=¶]¹re³iJZ½_Y×`«ÛûI'Ä 'œ0¯ûlxQúªëÀÀíííÁnܸ‘7.š9Ahu&³Mý™Ø§ 4±OAh]dl+­‰Ü;¡uû„ÖEƶ‚0= TÆÆÆ¸þúëyá _ÈË^ö2¶mÛ¨âj•ÛÞÞ>!o_%{öì¡···‘‡!½½½‹¢(àT¶ ³·Ï{î¹§l?‚Ð(FFFèííeïÞ½ÍnÊœ©‡}îÝ»—ÞÞ^ü Ma``€b±Èþýû›Ý”9#c[a±!c[Û ­‰ÛîÙ³§ÙM™32¶2¶­ml;Ýz‚P¶mÛV—±mC•‘‘º»»¹öÚkyà¸ñƃ›Þ¾}û&¬_KØÕ‰'žØ²…ƒ„ÅOww7ëÖ­kv3æÌT¶ ÌÚ>×­[ǦM›š}xÂQˆž9³|ùòf7eÎÔÃ>—/_~T¤MZ“ŽŽ6nÜ8ï…›Œm…ņŒm§FƶB³ÐcÛO<±ÙM™32¶2¶=¶må:%ÂâeÓ¦MuÛ6TPÙ¸qcY¾îîn.¹ä’ l¬’ZÔË•+WÊC§Ð4ËCçT¶ ÌÚ>×­[×ò¹…ÅI[[Û¢TêaŸòÐ)4“ŽŽ^ô¢±téÒf7eÎÈØVXlÈØvjdl+4 =¶mõZµ c[a±!cÛ©ÑcÛV¯",N6nܸð•‘‘†††Ê–iƒÚ¸qãCÜ·oŸÜ¡Le› ö)ÍDìSZÛ Bk"÷NAh]Ä>¡u‘±­ ÔFC•®»îº 'ߨØwÜqtww³oß¾`VÂÐÐ###\rÉ%Í>G‚°è™Ê6±OAh"bŸ‚ÐºÈØVZ¹w Bë"ö)­‹Œm¡6Žkä—õôô044Äå—_NGGÛ·o§§§‡žž¶lÙÂu×]ǦM›Ø¾};[¶l‘0AhÓÙ&ˆ} B³û„ÖEƶ‚КȽSZ±OAh]dl+µÑPAà†n`hh( ‹††õôôÐÝÝÍÈÈÈ„ÏA¨/SÙ&ˆ} B3û„ÖEƶ‚КȽSZ±OAh]dl+ÓÓpA˜²Ÿ¤ 4éŠlŠ} Bóû„ÖEƶ‚КȽSZ±OAh]dl+SÓÐ*‚ ‚ ‚ ‚ ‚ ‚  TAAAAAA¦AA ¾®ÛìV‚ ‚ ‚ ‚ ‚Ð(ŠÅÆ}—*‚ ,xt§Y(@,ž×ì ‚ ‚ ‚ ‚ ‚0ßTN¦ö<Èd÷ýM)J/‚0W|_u˜–©†ú;ŸWŸ ‚ ‚ ‚ ‚ ‚°0(”ŸÏ÷Ã×BâñðoßW~ÀdR +–¥¶Õ¯@A$® ¹œê@mLS-K&Õò¾¾f·PAAAB|_=¯Æãêoý +‚°Xð}H$ ¿âg®«üwÅb(ØvèãÓ‚I&é´Ú&— ·-ÕdjÃ××"Œ^G¿×í¸è¢ù?FTf€ï«L„æcYªuÕ§Rª³µ,©£"‚ ‚ ‚ 4ÏSÏ£Z0ÑÄbêÕ²Âì Ú1hšÊ¡(‚ÐêÄb*3Œi– ñ¸êûtÿ§ýu:%<®þvœ0ÓL:­>×hôk¡ „f-ºØ¶ZžË©ïÕû+Õ>\7ŒbÑk µ®ò®§»{~σ*3 • CŒô(BcÉåÊ“x\u®‰D¨B†SAAAA¨®Fž˜føªgXkÇ^:: #t0‹"¨‚°pБ":Ú¤PP}™a„Ÿêûâqõ¹Ž&Ñ“££ûÒ¥uZ-µ£EÝgÛa´K"¡þ.Ã}|á ¯çòË1¯ç@•R,ª ¡ZØ’ õÇqT§™É¨Î4—Se4Å—;AAAæ“LF=of³Ê¹—ɨçÑdRMĵ,%žh‡£e©u!|ÕØ¶rú9Žˆ*‚ ´:%š­É÷Ã~BQÅu•ÎóT?¨£Jt:.×U“Ÿ'|¯#[,KíO $ºŸŒŠÍZ4ÑÚVG¿DS)f³ðÑ~“NÚ8¯çF•LªÐ&}¡èP$Éw)õ'“ ;Õx<´ÃjE§l[­/iúAAA„ùBgKUNCÓTÏ©zVu<áú¾?QD©Ä0Ô¬êááf  Êl-:½ ö]ëÔXÕRjt -ßè²®®0ÏóÂýè¨l68´øla?ÙÙö¥º4͉þ½hûj)8oYJÜÖ¾@í<ùä}ó~žEP©¾Ù߯^S©0Ÿ›.ˆ-Bý(Ë¢º#Öù+Ñ!~"x ‚ ‚ ‚ 3Å÷•CÂ|ÿQ$š%!Švè™æäË(z½É& ‚pt¡S`MçkÖ)5ZìÐâ¬î¿2™‰…Ü£‚Šë–×:Ñužtª­BAeˆqÕj‘D÷Y:*ÏuÕ¶Ñ:'zY´oÓu£¢mŸ¾O (˜X}Lý¿bq /bÍ Íý&Âü£;˜8»g²ŽRwÜ‚ ‚ ‚ ‚0SR)å÷Ñ…s¹Úu…BèCªu‚ŸvN ‚ èÚJQŠÅ‰Š3™°ßÈdTߣ3¶è`&_x×Q%Žn‹…"K,¦¶ÑbŒþÞ®.Õjñ$*ˆh1¤ZÍqÁ%™\ø ¡R#¶æhÓ¾™º®äº„z o:'#¨¿–Ú(ÚNAAA¡´’É(O>~¦ÓßÔ‚çÍÜOT9Û\„rcZw=y8êóª–‰E}·mõÞóT4œç•o£ýÔ†Š$ù|˜ZP÷iɤúÛóÊ·Õb‹m‡uQ´À£Óïë~P§÷š)µö£­Œ*ººÔZÍ ›É„¢ŠŽPÑaM¦^X‚ ̹œzÕ…ú&Kï5:,Û²ßMWAAA˜?ô ïd²|R­¦VÇ¡.2¯³œÔŠeIqzA˜ ]~AG\ÀÂ÷Å ¡¨’L†5Nô1êúÝZPÉåÂT\n«}ÔÚw¦``šååÓiõ/“QÂL&£Ä–¾¾0šÅ÷ËË\´|JÂæM””_¢ù1§BÓªœã¨ ^„ùE‡"êYž73õÛ²Ô w®öéûÃ-AAA„Åç)_Üà`y1ãÙ2¿žL„©‰N²-«§Éówå§îë E™þþ°fI>.ÓñxXÈ^d³j¹Ž˜Ó~ð– PPêO5¢¿»>™u¢©‚ÊÐÐccceËFFF`dd¤aíÐÛtzfõPôÌ÷jyìa!SÍ6¡qöÙÙÞ@ô R×- Uxâ4*G:æ¢M$TÚtèœëªþ7•RÛNÖ_·“õ[®+}Ób¤Ùö)Âä´ÊØV„räÞ)­K+اž„§Ú×3[l;¬10td‹ ´ ­6¶Õv© ¬W’JÁÛÞöÔ´¾¢zPm"o¥Éuú&ZÑY’’Iå¿I&Ë#Q´_'šI§Ôâˆ.¯û.ÓTûÑ)º4ú}ôÜõõ…BJM̦ød5Ï«}´RÊTC=¢¾®"à¡ä{®ú,“Þ"Äà¼o~sV¿éT4MPáꫯfûöíÁ²mÛ¶qùå—³uëV.¿ür¶mÛÖ¶ Ê 3+Š£C©j©ç  …j¶ µOÃ(WàuèbTp‡TIÎ÷&éÐ # q4Íòü’•3r9µÿDBõ :—d<®T|}ÓjE¢BQ4wftƆžå ,lZÁ>A¨N+mA‘{§ ´.­`Ÿ:SÉ|ξŽkž ɤÔPZ‡VÛ:N‰QI"¡–¿öµ¿„T®áç+ªh_LT×Éå ýÑ(“Õ«Cÿ²öÙ¶òAéuu ”¾¾°È»Q´€›N—÷¦Y{Ô›ŽJ© V3¢'"Z´E«Dz¹ã@®w–Âr´®³S½ÿvéø© 1 S'öKEÈ—NÞ›ð^dÁËâàÂú;æý÷nZ •믿~²ÞÞ^n¼ñFº»»âòË/§»»›ŽŽŽºµCÏD×îd¹÷¢9ã*Ѳ6왈2‚ÐjT³Mhœ}FmR«ëzfãÀÎ;I¥þß÷1 ƒb±H&“¡¯¯kI]+õ¾±˜ZfY势Ž4Óß›L–Û²ž%Por¹p†‚»¬vŽtžK}|ºíú†« b1,&V,–UͶOA&§Uƶ‚ ”#÷NAh]ZÁ>†‡›}&ú™-WÏv-_¯@XÔ´âØVgñ<å7Ñ“Fõ$Údz{·¿€B¡€aÄPhEû]|_µQû³tæí›I&ÃI¾ºŒD4*E‹"ÚG­-lÛêØuôI”IýUÑÍZäгvug¥£M´2“J…¡5¦©Öí-À3¥Â,$!YÚŸG(¬|Þ€‡ ° ø¬ †vÎÙp$ Ÿ/Âq&¸ŽZïý}JhÙëA>¯óáuè¦î—õ`RÛà¼-Rúúú‚(•Âa‚•!: XÔöûûÕ²¾¾pÝ(…Bc"<¢³R©pÖB&ÞH!\îºá?ïWú½^oº>¬H„ÌÜhû¡:­4¶!Dî‚к´‚}ºnk¥vÖE¨uÆAh­4¶ºzÎÏÂNÊK0€z5 eC‡Ÿ»ü0M|&“Á¯³3$Z÷D—îpÕ®T*ŒXÑÚ†ÎÀ¢}O:M×øx¸O]Ãdx8¬‡a=ïš© •Ñ)š*©æ4*PžZK7@çÕ/Â}G£M¢ëé”3+·J'êVrÀæ.ØlÁæÜå ^‡>Ž˜ð­œJáõSµåÚ¸z=`©í÷û³à­q¸§oôá¼4܇ϧ! Ⱦ^:[‹àÇÃ0›ëpvtøL)mÊ…y}bšð ÎÎC~–fÿʇåIˆ[ðÍ"äm¸Ù€'€O˜°. oöá Là* Þ„ÝYx¿ ¯ï‡QàßM8øœ¥¢^, dáû§žÊ½Çǘo*¨ŒqÝu×qã7ÒÖÖVöÙ¾}û&¬_KÈØ‰'ž¨£3E矋Þ@'s8N—{N+ŠõÀ÷ý`~5<ÏcÉ’%$ r¹Æç <šéîîfݺuÍnÆœ™Ê6aöö¹nݺ 3ަC;Ö£—²ëº¸®K, B5uz¯l6‹mÛ“¦ûj¦ª¿=Ö¨.½QGÅÚ¨¬(=CA÷S¾ömÑ(—è¾5Ѻ+z@ ßGÅ™è`>*¼d2ágÑ6WaL§Ãõ¢Úo&¶-:qœòó6“=sfùòåsÿñšL=ìsùòå’ÖDhlܸ‘eË–5»)s¦Õƶ‚0Wdl;5³Û Â| Ç¶'žxb³›2gZel[,†§[ ÇQÏQÙ¬zÖÓu„ÖEƶS£Ç¶ííí³n—®9òô#KÙú×§©I¥À¿ö‡‘Ú–ï_¶ŒcÞÿ,·=ú(–ea»W¬ ‹Å`"úÇïÙÁ—¾÷pðÊ_Q9O=š­DO ÕÙD¢“^£äµ/FgÂÊåÂôëɤ²o] ¥Òo2#ª)®ÊÓ•hµI;X’IôJ…Ü=%”¤€iø–£–_œƒ–ÚA +×fà/SЇÏà1[Õ(Á‚8*òe c¸!×xð3œ8˜IØmû õ]Çg¡»ÿË„¯Úp½ C`½}0lÃ]iè6à=qȪ¯"Zëå?#øï«çnܰa+W®œÃI®NC•B¡ÀÆÙ·oìÛ·¡¡!†††ªV-êåÊ•+gýЩóØE™¬þÉt‚Š6ØýŒêjxžG.—£P(”…¨yžG*•Â÷}‰ù|žt:=!Œ-“Éi¥ÖEÆbyèœÊ6YÛçºuëØ¸qcÍíˆÖO‰N†ð—+¯¦¿_GµèY01TU·³r ¡ë¼$“ê³èñêc×ëAR<†Éê™ úÖZ&ÚÚÚ RûAEh&¼èE/béÒ¥ÍnÊœiµ±­ ÌÛNÍLǶ‚0_è±m=œB¦UƶSÕÐm&:•‘e)l2©ž‡$R¥u‘±íÔè±m5µ¢Âç²ËçÐØ±>|˜ÿýãó÷ï–K“¡öO<Á’×ÿ1Ç=öû÷ïÇ4M~½y3÷îÝËRà8Žã~ùóãx,¿ €t>ÏY)xð”¿$:YÔqBŠë†¾+Ñ¢ƒ3´v¡};:å¼®{;>ú[js£â”ÏÈÍåÊÓ}¤sJ°ÐŸeP‚ˆ“…{J³dÍ<|Î„Ç ðÖpTTÇs x¸Î‡_;ÐnÃæ"È@6»Š0æÃ}I8& o1áÛYUþ< ~cÁ˜ºð/6ô£”ªʪ¨‘A”pòaþ®Ô ›@ÞT‚ À»MµÌ$ Û›%6làÔãæ¿†JËұuëV@Þí·ßξ}ûèîîž>½oß¾º9{ŠEõ¯R@)˹=K`º‚óÑYÕµ§/‹Ø¶Q¡ÖxžG¡P X,ÇI&“¸®‹mÛ¤R©`ƾv4ëP<ÇqH$ø¾í6kiˆpÔ3™m꼘°ÏD¢<üQãºî´(†a‚Š='‰¿:Õú…éÐBF÷#Z8ÐÍÔ‡æ—js¥RaÝ—hZ/}£Öëe2¡S™ž2— ßënMQ88¨¾3™ E-lDs€ê¿u.O-¬ ‡ý=ºPœ>žx\µQׯÑûÒûµ¬pÔߊ-étX˜Q£i†û¬ÃOÝ’´‚} ‚PVÛ ‚PŽÜ;¡uiûÔÏT­Fåsg<fÐÞZQ­6¶ÕµI ž|òI¾ö¼'9øóŸ3¾ï…}#ð»|áðaF_úR–úGøŸ»ïæSo|#ŸºùÚ¯ÞÊ/|§-ÛÇý0ú|ŽùÝ^w×#|ôù¢b‹Yº'êÚ)Z ÓïõÌ*ÛVb‰žõ‘L†39 Cõ¥Z ÒÇ _õïQ,VïÃ+…¬…N+ا Õi¥±­ !rï„Ö¥Uìs&é„›‰i†éƒt½I=ñn6“þa*Zilë¢|ï:•V<Ï>çK×a‰åsæ1gr¿ÆáÓqU.á·û÷óïŸÏ¯³ÙõÁòµeË8ø¥¥|ª\ð“gsèG{8);γˇ8ôؾ]4xêÄ×pÌ ~ËáëØá8øô^n»m=?øÁ2~÷»CôôìÃuO£«KÙd:­lq÷îݼò•k¹êªûù‹¿¸†/~q4ð5Gý?“ÖjŠÎÆ×3Iõ{íà1-¸ßS‘ o-©ª.°Ý,¸ÇQ"ÇNà É\êÀ¨ ?ô`¸]Iøs r.¼Hšð|¾Õ§–=S„¤f\}ï[aã8p™­:žûò¡Pb¨¯G×"Žúì~qœMãC«;&¬]ÅÓ<=¯»mxQú©Ø²e ×]w×\s W_}5[¶l™uHØthGáLøÄ'>A.—›4…V&“¡P(pß}ßã_þåx>õ©êùM]×-H´°Ë储’þþ~²¥Fê(“þþ~òù<Éd’d2IEít:M¾”˜/cÛv6Ìó¼IÛîº.¾ï…š|ß—TaBõ¶OÒ 5ƒŠÅ"–eašfM*úzo&•¡ØÑºnš¾C8ÛAGޏ®ŠQÇ …B¡¡gS%“aîÎx< 7Œòèd2lÒé°MÑ:(z_Zуt=xÑ¡ç:µ—ŽÑß§…ýy>î[G™h±E DžW^¨>› ¯ M‡Æ&ê½N_–Í–G½FÏc4Ù/ùÚ¦^¢‘÷OAjGlSZ±OAh]êmŸ:ÍôB£òÙPæÏ ¦‘÷Î"p·WžƒKwṉ̃ÇràÀÖ¯_ϱ©‡Àýã¼èßà¸ãŽãíçœÃŸýõïÀ4¹mÝ:N9ሠ€c¾x„Ã\Ãþï,áŒ]O°òðÌÇf–îZÆ‹ÆùÃí<óýðío?‹çÁòåÿÁ·¿Ýø&t{V¬8Ì¡CÿD‘­]û:Ç)Kã>-QçE¡ ¢>rÀ€ßpUô‡ì*½ÞmÂåiøFA¡ËlU¸ý, Í€ó“pE|N¶`Ϻªh{Ø`ÂËJΓÓMx•w$ÃÙ· :Çþþ0¬fp0ì0“¨ˆ“( )ÒšGÖÌû>žò+ÊÍ7ß\öwOOÝÝÝŒŒŒÐÑÑQ×°±™†Z>|˜ßüæ7ärwâû~ tD £A öìI²bÅqÁLéÏ|æî»ï³†Ž×bH, fÔû¾O2™œ0ÃÞ¶mg”¾Ë¶í`Ö~.—#—Ë•9¥uÚ0×uqÏó‚ýëZ,ñx<ØÆ÷} …¦i¢P2™Ä²¬i£„…E¥mBýí3‘P©£€àÚr]7¨4–eÑßßD©Ìwª;‘1•ZN´J__yþMcS§ñŠ67 …9¢ïeÑu-+¬S¢ÛW­ét8ØŽ½×õQÒiÕ-äèÏ´ð¢Å U¢…- 麊>_ÑBlºËÔ÷co*I&C‘D§³,µ®¡ÕûÌåÔç}}¡XS(¨}oØðS&Þñ6ͰOAj£™c[A&Gî‚к4Ã> cæl[ýœ¨kM¶bÚ2añÐì±ín¾íÁ>^óšüñ<õ‚ã;ïylhogtÃîøýïÙ›HðÇ+V`?yßã°â6?¿ .ºÕçïfÿŽWqÌ_<Á±kâ_þåL.~Ç3<»k¿,B[Û±Ü÷ýý´]p,cqØ]\ÁUW=Êç?/+V¼5ÈÞ¡|¼ÿÄ¡CóŠWœÉ—¿ücàŸyë[Ϫm‚¯‡!tš‘ù°¢”ÖÄE‰*»l¸?£¢@ `܆‹2ªÎˆ‘„3r0èÃ_§áƒ&|Ìç›ðý¬r–œWrÂðà{‘Éò÷ö…­ÊÚ¶ržDE“1ûR&MeÏóöÌû>›*¨T£9Õl„Énª§Ÿþ]ÞþösøïÿþŤõNÔ¾]R©wÜñU8HGÇœzê~vî¼5k–²gK:Æ4Í@4ÑŽc½¯É˜­ƒ8Nõ%´èS(Èd2AZ±¾¾¾ ]˜ïûX–¬cYétšT*…çyAJ±d2¬£TX ß÷'8¿]×%‘H`Û6–eéÊ|ß'‘HǬӛU;·ét:ˆšÑç_G ìÑb”aeµiôú:RGŸaæÔË>£õDôõP)òÕŠeY¸®;ï¿q´ Y]=›UýŠNô×§Rj™® ÒߊZ(I&Ôb:M—žudꦭ/÷þþð>§ÅýªÛPh0›.P¯#WªŸÇð7‰ÇÃèM}Œš¨¹G‹ÅEÛ¥÷QˆO ºo½ž®µ¢÷§éô9ÑǦÏço~sÁœ~÷…„8ƒ¡5Û„ÖEìSZ—zÚ§ŽÞ_Ènè8Ah$õ°M¥%DÝúðk°à œð§OrÒñ'1‡gÛÛÇØ6k üýí+Ÿbù—öð|·™ð­s¸àòçñËß=ÉŽ6žf#ï{<÷¸ï³ïTÿ÷/fõ꽌Á+/>Ž_<ñO¬‚Ÿÿü·¬ZõRÖ¯¿Ó<À‹.ã¶Û~Bÿ{x䑃\sÍ•äóiâ¹¹jŽ=SÔ0xÿm˜Ÿq8mÿÇÕò3Ó°ø¾§YP(ˆ#.ìÚ|ˆy`g¡Ã ü%à§á›1¸¢T¼ý%>¼$Rœ×0Jâ‡Yî$о:c*9´´TʯFàûÊÉ6YþºÊ,W]¥ð«Ï~öÚÚ^Åðð0¦iNßB¡€ã8AôG:æŸÿùZ~ö³w²lY7ÞÅÎ;9í´KÙ³ç“\tÑ;I&“ÄãÉÀ9›ÏçËRmÍ·#X Q¡£X,2<<Ìðð0Ùl6ˆB‰¦VÒ‚O±X$‹aš&ƒƒƒŒŽŽbÛ6¦i’ÍfÉç󘦜?Z±©tŽòù|á’J¥Èd2tuu‘L&¤¯¯/øž\.G,£³³3Hý”H$‚s¬…›Õ«W— D®ë‹ÅH$8ŽC"‘Ò–éÏôºZœ‰Åb¤R© m‡N+•jj©(ŽãÌÊ´ 2ßè¾C¿×—ŒNÓê5 ×Ó…äõgº–J2Ö Ñ5Ttߣ£0 ¼€™Ž¾Ô)¯4ÑhÓœ>t]G³hÁ¤¯¯ú6Ñ´d­†xtš1}\z¶H<®Î»ëÂÉ'ïlvsAAAh2Ñg¨h&…Ìà ˆ*Ââ@ *Qî,ù@v¿õ0ÝYø]û³jAEí +VØ»7¨{þÎ?=‰— ro$-ÞØØ)¬_¯Ò“iAò´ÕK8ûE¿£¿^óš}¬Y³”o¦áõï<–#Ï<ÎÎ?㢋.âüóo2o<þø·¸ôÒ³°m›«¯¾Œñña5¹ÛóxàÇ?Æq2™Œòû(GE.]pà‹ä´ŸPõPr&ü: ?*ÀÏsp?*g,ÅàI0‹@ä¿2átÒ¥spÐ Óm¥ãêŸ>¸¨Ó[§‚9Šyá/^8ïûl¹•z㺓ßp”Hbò£%1Ï-yC÷î]ÍÊ•c€rØêˆ 1‘ÍfáBcÛkÖ,å·¿½·¿Ý.l¾¼l&º.Ê|Ê)ÿlרè ß7ª:Ru*"]ÇÅq|ߟ4­—N-ªŽL.—#™L©ÁÇ!ŸÏcÛ6¾ï“Ëå0M3ˆŠÑç4›Íâû>ŽãðÖ·~ˆ×½îEAtIgg'W\ñ1^õª6âñ8‰D‘Ý»WçL§PÓ‘–¥¶Ëd2‹Åàû:;;q‡xð{ŽsáÅË_̳xã8ðJâ&ÿè\N>üNþ“×ðÖ#6K.NÀ¯JµM¾îÀ#vI81CÇ c7ÝĆիe±3›ì5®ë>Ž«÷Î{›Ž:AEO®Æ«úS^ûÊå|Å.½ü¿;ï ”¼¾ð¬]±) Áãy^Õ×_iYÊ)ÛVõ†´Ã_×D0 xòÉÍÓ¶}ª&£œµž§œ´:sV´£p]xðÁw0:úR:;atTm£··¬‰)€,Ë&ë>T:t£èš-Ùl–X,êüUëϨÎ-^ª}äÆᕯTƒ-îüò—grá…môõë ¾‰M›~ÄI'Ýɽ÷æH$Ââ×Å¢ú鮼òf¾ÿýSLãû™ |øÃÿÃý÷Ÿ@.·ßWíü£?º…Çû™L†M›®âñÇ×säÈ'ù·»ß7ø¯ÿ2°,+¨£SŸ´µµ±yóô¿ŸPhÚ*-ÀU«#TûþÂßi>‰Ú]´8».J¦m-êìïïW+Öõˆ Åby*¬\.Œ¼Ðæµ]F·‹Ú`±X ÃJt”OôÆãûa®ÝÅoWŸ×tZõgšXL}vÞy›ÝDAAAšŒiªÉ|µÔÆ\(èÚÑÅ¢zÆ[¨ua¡+L¸/¤aÿþýŒ=ç9¬Y±\— ííø§ŸŽåºl9ç~DõÄèÛ|^ù´}h¿f&ù¼ê N<ÞùÎ3xç;϶ûçŸÄÕæe8Ž* üV?N}ÃãÿíÃü_íxç@æ¯.aü¬çÀ3Êéòû[¾ ñWÃÞ${¾üüžïqö³§rÿ²Øx±wø¸W%YúÔ)´-{ŒOû!‰#‡Yñ™t3Þí0øÙèNž-ÕŽFž\ø¾÷5û'š3®ëâû>¶m— Q<Ï£³³“ÁÁÁ Ÿ‹E ÃÀ¶í ƒT2™$“É¥6,Ëbùåìß¿^Û>#Ae``€‘‘zzz¢··€7²eË–†žø™’ÉLíDüíý_ùñɼÁ‡³ŸzŠ÷­_¥Ú#<ðí¥}Úa뺪Êd³è«©gz†º.ªœÉ¨×Í›¿Šã|={Î#•RÎÁBAuº>P&þmYꆩë5‹å5ô:©TXŸ¡X„ÇÏ`Ïžó°mÕ©èu]7V´Ñ߯D =ã¾P˜^PÉçóØM!6ZÀ‰ 6Ž£Úͪv?üð;Y·î'Üv[èÈî鹉ÿ÷÷°{÷^óš­ìØñRR)öªçK_:/˜…‹©óø×}}}°eKøœsÎå9ÒÍáÃyÞñŽ6Àçê«—ðæ7ßB_ß(wÝup¹ë®5tu­&·¸í¶?aÿþŸãû9N:é¤f_Þ ¹*ÂÉuÝ ÎÎl0 £¶B`s@Û™~êzÓ‘%®‚ׂ‰~Õë©¶†)À´MÇã¡ÐZ‹?™x¤k%“É2S÷ 9B¥’j3±Óñ ‚ ‚ ‚0{tíJÇQ>ŽÅaªæR¶z õL)Ñ*ÂB#šLÈ÷áA]#Ý‚Ý+Vðì®],;ë,ø»¿cõ?ÿ3ð‘óÏǪUuÐþÓ•à–/W“«Ãe•sä à‘R?Ñù¹{ñžnïã>ÿxr»â}à1Ò?o§P²?ï«ßÁôúƒSöÃÀ2ybÉõœÓþG°Âdç±Ç°ñÜQäî'ŸËúì9lþ’Åk,‹»m;Rø;•JaÿÙŸ…N$ÛÆó¼ Nµ$Z1£N±X$OÙ>Çq‚ÉÔ¹\Žx<d…r]7¨ûÍf)‹ÿKg8r]7ÈrcFPŽ"ŸÏ¾è®®.nzê¦y?¾šk¨\ýõ\sÍ5ŒŒŒ022ÂÕW_ (1åŽ;îàºë®kÜ/3 ´`õµºÀjàëðìƒr̃ÏòŸ>œùñó`¤ÈÑØØ¼á ›x|ýú –‡þqkE‹ù|(î áCkI$Täˆã”‹«W«mt­…L&tÌf2jPà8JLÈçÕûX,fâq5{{ÆmtuÁOüE®(›-u2…°¶¨}êÔ@Ž£öÕ߯¾Oûpõ÷G‰ ISu.§ítv]Õv-º†çëž{.góæçBI: ozÓKé鹉+®x˜õëŸ!Ÿ/ˆÅÔ~ôŒüáau¬ú܆j»ã¨e»vÆ¡CÿÀüž¾>Ÿç?ÿýÄb«yñ‹Âo~sÛ¶mࡇüÍß\E±ç´ÓNã(׾öµÍ¾´4a1quûÔ5zfŠðì?ýõ¨Š£o¸º}´V „‘gQÛÕ¢I´P½6‹haúlV]£úг٩ÅË(ú†žÓ"]]]¤Óé ‚%“ÉëèÚ,‹Û®~ž¤¦š ‚ ‚ @)ýºzÞš­˜ÒêuWµïCûŠa¡âûpqžÒ Ø»z5O=õ”¥ÕÑü•^Yë‹aJuãq0O ?‹Ç§÷D?Z}ïCt~o¯r:à­+nÄÜÅ?>wÓd.ë;¼¼ÇVÃOŸðbž=æªÞ‰ +Ÿx Nµà Ÿ8ë,¼xœ?,ýŸøú'8ï²óÂø€.Ö¢3#Åãñ²:Áºî°ž8;] aÇq‚úà]]]sž€‹Å¦Ý‡çyA»r¹\PßÚó<ºººèêê"—ËaFP3[g~Òµ´³Ù,†aJ¥H§ÓضM<Ç4Í Žv6›%“Ëåðqö}5}t‰„Šìµï«öêïªÀ|à`f^àh4€>G•DËÑc¶¬òz üà/Y»öPp,:*È4áhG˜ÑkA«ìSQš@5c ޲áJT‰—ÖùÎÞ½|~hÃqªÖì™-•S-(ê|¼QŒF¥x^XE§ƒòÐìÙµGÝŒmÛ&‘Hj½Vò²Ú*¹\ŽÎÎÎÒ²úþ%õT‡^Z–UvC­ìC}ß§X,–¥|ó}ß÷g\€L‹É?úQÝSAA„D§EŸ®¬ÆuÝ ÷~2™ œ|º ²ëºtvvbY–òõ÷·Lªd2œì**ÂB£ò’}¼˜ÐùæýÜ﵃§Ÿ~:+@9YV¬¨ž•ÄQÛ‘2`À>”#)]z5Jï+ Uʃ3MUdþóÛàÿôÀû€câìh;“5KŸe$õuþççò†_˜d}×cØÿòqXñ=Ì'߉ûIˆ_–ä¡cïã+[î!çyøÆ7xø¢óà­o‚?¨NIGdTŠ•‘pÕü ·Ür oûÛq‡_ÿú×ìÞ½;ÈJ288ˆatuuþµþþ~ ……BÓ4A"NuwA¥àׂ†ž¨«×Õu¤µh¢Smi¡Dû{t¿=´ŸJ‹'íÒ ¦£ZÝ`Ít¾ÄÃ+s"'Îé­¤æ*•"ÉÀÀ@PKE£Å•V$’nNý d`ýàdKé»Þûÿ¾Ï²ßýë"õcž¶k;}”ööÃ$x%¡ ξÊÃDŽ?þ†Qý®××W}&ET ªd2­Ç4IEZf­[VXIÛ‡®cšašŸÿü8ã •Â TTJ2¹p‹¤qƾï³aËáï¡„—UÍnÞ‚ÅuÕ7› £-ª®‡Š@%T3eJËõ?{Õ*~vÍ58^8¯íÕÑQÙluÒ×Wi‹a´X<Їé4e׌ë–H›mä¸ïûe3¢Êýd¤Óir¹\CÂÕ£ÅÁ|ßn¾ét×u'ÜÌu„Ε©Zô1êÙz€0‹)/² ‚ ‚ ³Cg˜Ÿ?›ÍéiÇ žW*g@ :;;1 ƒáÉÒm4¹ïû’úXXxTõP$aß÷áäÇã%<JQ)ýýýĈˆ0zâktæ¼[ZnùÈ:.Êi”’¥\îù¼bÞ“€ü zÊxÏy¸'‚•ä#ĸáÙËxñÝoc×ó¿çXç˜X«W`žú7êkl8‡sxßêÕ`YŒÞz+ãò'ð01\7m£†ˆ¹\ŽÿøÇ¸®K.—cllL5ßuyàx衇xõ«_MOOû÷ïç–[n![J°iÓ&>ÌÐÐP°O×uùÝï~G.—#ßׇWúNù¡ÅB¡ø›ŠÅb%—ËÑ,º¯Ô…ߣÂO´ŸŒ +sÉðT SùéþG?çÅg¾x^¿¯¦*ííí ßqÇtw‡±2ccc …Û[ Ï ÒÐÄQŽY­ª%“IžxâÜxãuÁ¬ö5kÖ°ÿ~އ:.õÙ¨Yñó…aø¾_U•›*ÍLƒdf:Ë»¶}ªÔW¹\˜ZkïÞÕ¤ÓðôÓ'3÷çPg¼%Ðùÿôµêõ›ß<¯ÙM[°D‹»W»þ}”X’@ÝK¯•d)Ï™i·µñÌ<‹¼…‚js"¡D“d2La—Ï—G°èh®«ìB§ÌçCQ&Ou7¹\.¸¡†QSÄ\<Ç.1«'žç!¡ñx<ëÔá™ú}tvC"‘À²¬`–—^wxx˜ááaFGGƒ… ‚ ‚ Ât8ŽzfŸ®ì­žÝÝßß<3­^½ß÷bå³j2™dtt4HwÓ*†Êž  í¥x²`ìÜÇoü2Ï9û© 5RÏf5ûÖ!P<”ÓÖD9•<”#7réÔ&··–¾u·¸Êå‚ýß;pV,%vx1ø_ããìþŇ9æ/alÝ:ìBA9ˆ|_9yÒiŒSO¥t©]ðàþ€™Lò±}ûÊÄ“t:M´–A‰hãº.íííA¶Ž_üâø¾O&“á²Ë.c÷îÝ$ öîÝ˶mÛH§ÓÄãqÆÆÆø÷ÿw¾ño°|ùò OÓQu»wïVEíK§Ã²¬ &I¡Püãétš¾¾>lÛfxx8È„¢k‰G Í×ÃÏ<2(QEã—.*…ÜÓ'==¯ßW“ rñÅ322Âõ×_ÏwÜA¡P »»;ˆH£··—ŽŽŽ²´`­DÔ¡¯K<¯Â‘›äØcÏ .ˆåË—ðø­¯ ‰rèš(ÛœÏ9Þ­rÎÛV3÷‹E%ð8p<¿ÿýIè`š3KñÕŠèý*Œ-\ßÿù7šÝ¼KtöL5'¿2u‚ªjZ]8ð–·Ì«x`aD‰J4‰„²~¯£Væ›b±ÈðððŒóö꩎) AíIRB¡› ²+‹U}èˆÇ)‹‹Å U‡¼êuå ݋łÈAAA„j8ŽòÕ"¨ôõõÂt:Íððð”)f4ñx<(ªÜ*xžJ-] ´„öD|¹Ë6lØÀ³Ï>ìÿž{îá£ýhà;‰~—ëºäóyÆ_ýj(šÕÀw9ß÷Éf³<÷¹Ï ²TFÑèeÖb™ ®ëRŒ:ÍæíçÏ”þQú ÌÒ¿­z&ô÷¹ÏqÝu×±mÛ6º»»Ù²e  R]sÍ5tttpã7ÖåÄÌ•BAÝHÒi(¤Õlöç>ŒèebÆi§ÆÚµk˶߱cGð^» &æø;š‰:oºétN=õû@§Ÿ~étÏ\v=-p¬êŽH…³•GÛœ|ò¾ºÿbÄ÷Õ7ŸWÎú¨óÝC –>Ê^gCØvÁeùnçZ4в”’N«÷¹\õ-t˜L†)¿ L6_¤R© ¥¾qTÞžõäŒJôÖq~üÀ^±‚µ†ÁýýßsÜþýœpÿýA1=ËÁ÷ý EW*• Â?õÍUGôår9<Ï#ŸÏ×ÎÍ=\Ëú†aÐßß„¡:ó\#GAA„ŃiÖ–þªòYq&^õsY"‘˜—:»ó‘$REXPøŽ=X¹ä!Vÿ8D›­SZÁ&t(Jqb R å =ì*º¥/«<ðž é$¬rÀò!žÄ8ò,ýÿÕGÑ4ùõë^Ç¡Ÿý b1åà‰¦+ÀI•`wüå_’¾è¢²æj_†ök†¤úºí¶ÛøÍo~ƒëº<óÌ3<ôÐCÁäîuëÖ•ù>¾ò•¯¨sRú\÷_Ѻ'Q_i´®ÉΞr‘syÅWÐñÀA-”JK´¨½Æ)ÕÊú=­DOÖFâ$ ØPT>ÚF×u˾?‹ašfÙ÷ë”ÿZ@¥Ù(ÿaXù䓨žGúÌ38eëVèžÇŠôÔ¡°qãFÇáàæ›o"Q6mÚÄÍ7ߌã8-¢EÃ%–²«°wëVr¹\™Â°{÷Uj‰üö¸ãxáM—-“””ÉfU²wïjN?ý¦†|§:êY®r0UYC˜†¡îCžç©Ž¥2ƒšgýFy$Jÿüç®Íd2$‰`ö€ƒ _ìB@õq¥åné|êü¢°cýz\×eàÈ~óå/óÃø é4›o¸±›nÂdèß`Ã3ÏðÈ•Wrþž=¼aÅ 6ýÏÿÐý¹Ïád³¬ûð‡ùÜ]wñÍÍ›yøØcéêêâì|„­«W“+0m[IJm*FÞÇ:¿ü—áóg,O”–ëv»‘cŠÆÍÄãqòù<žçÑÙÙ9¿'YAA„EÁdºH.— žõægâ*ä<]D£H§Õ±×9Ó³ Ì; §ü—&áyöœsÎ9wœŠ(óÎüºôšCyÑ-B’ SºøM •€+<µÜ)À¥®š«Ó¯oÎÀ*_-{¨8ü?·ó³ŸÅúÏÿä§§œÂYg¾¯„ÓTÎÁI°3.ºˆÊx FPOüÍår$ <Ïã½ï}/—]vgœq‰D¢LHÐ~ÏÊš¸‡W¬ÀEùT^ôº×ËŸZ¹’Õ(ѧÞû^ÞðbÀñ`Š­\YV£7ŠH*?ÓÇQé3ÓQ+ÕDí[­VÓ·P(”õË úf=Ù7‹qõ£ÁEà##Äî½—C‡‘+sß÷!“áÌîn~yé¥u­\³ 2mmmeµTZ]Ëàf˜Fo×7¾̰Ž*f™LXëàì•+y¼­ßwÎe¡F¨Ô+¢CAûáU¡¨z¾Žzæ:šú¸ÊGaÙ¬¼ž25ÀÓŬ ÜíYÔÍ`®%«Îê)úFGÉd2X–5£kßq‰A§nYa” ”§øJ§ËûŽzà8–e‘ÏçƒT¡}¥êF™ ŒêÉ ú;.4ÜrÆŒ¾ô¥Ü] ›íC#þó”S¸kÙ2 à‡+Vpï1Çð¼Í›¹ùµ¯å‰W¾’îÓNãÑN ß0øÁYgñÉM›xí•WrÏ?þ# ²ñºëxý[ߊ½jUš4†Sr¥÷:ÊVç±<ó‘GxtÝ:yÅ+(Ö†+”¶×m.D–ÇJË Ã Þ×Ç)û˜ºù:WìÜÉg¿øá`»ý§žZßEAA„–Ãóʟעh¡çy¤R©y)–œÍfq]wÚ”ÓžçÍj²ßl˜.Õ™ ´.ðÏ)X_2És/º((7Qæ†ûyéÕ!œ]ªU‚>àÕ6öö’]z¼ÁÃqà—Eð õ÷ãŽr ;æw¾†±?Ÿ}6Ÿû\œW¿:Œ’©(ˆMûg”š•~¶sg°<šjÝó¼ æl2™dåÊ•üú׿Ö[µjUÙþµ?«Ò×ú“ . ¤Çǹÿoþ†Õ¨‰ª?~ãI–ñ¤;î`×i§ag~üãÁ¶ðÝ;I¥R"ì\×%“É_*?«VŸW“mÛeítÃ0°m›ÎÎÎ2ßœmúûû˾Ç÷}FÞõ.žüâq,‹‡–,¡èÞ4:ÊsÞýnú’I6}ò“ô•~~×uñ}Ÿ¾¾>âñx]ë[Õ”ò `dd„­[·222B[[Éd²e#R*ù®íýÊ6Ò”Ræ• !'§©”~î)§°téÒ ¡eóíÂod!³z :žzF¥LENÝQ몈&ÝáPð~ÂtUsÕ­þlÃ2›7ê¸îÐc±étzÊs4j&—Ë•rê–Ïò‰Š+–U^l~>ñ;(+>_Dôå˜'y­Òû"a}=–.iÓ„gžáW¬(;ǺÔD=£=å`µuÚÚÔ¿j1Lùoé–ŽÉýÅ/¸3™ä›'žHÕ7G¿?atÝ*¯tœZX±€ý_̧þïÿå÷—^ʺÛnã[oz'þèGüq?ùgžaͲeõùQAAAhY<¯ú³{42EO²Î/T+Ñ™ç“á8Nàô«·O#3¶B+óhəဠ6¬ë¿">àAà&`-˜»KØ(ç‡E˜Ç**:D ÀuC¥1“ s·»N¸®ëª¥µ–ã°yófÖnÞÌÐŽ¡o£Â°r¹\Ð"ôk½åç?gùÛÞÆkßýn†O>™ß^y%|êSRkÙ¶M.—#™L“‚5–eñÖW¾’:xS.º(Èà±£­_Ÿ~:à~ç;¼þ•¯ä­(?ÊÚåËÉRªuûÉOÒÕUê8ì×~ò“Ÿ°µäûŠÖE)‹A•jõRªõsÑå•>aÓ4‘#*Äèc6 ƒ³Ï?Ÿ®ÒOùÀÊ•ììèàùãã<‘Hðª¯~ãºëèüÚ×øó³ÎÂ~Ï{ÈårXïxL‘LTóYS¹’š#T®¹æظq####\}õÕŒŒŒÔ­aóÉ+³¡ø¨Ý§úæUKnÌ‹*rÞiL”±Cy:šÙÒˆ*4V¸i–è!´>¥º]xž‡C(¦¨ÎspN{WÄl›t©È¹ëº …`ð åêþ’%KH$Ág¶maŒz¶At`žÍ†5Têëº|ñþûÙðÕ¯òçòàg>Dy¸Lu­È²8åâDtÕ]]t¼ñs¬j9ÿq& c¥É#–EÛŽAªÓj˜¨þ5[úg–^ûK¯wŸp?øAÖ­[Ç`2‰¿z5Ëþú¯ùöm¸±køÃ:¥ ‚ ‚ ­F5·‡ïû¤R)²ÙlP¿`¾Ä ¨…à8™L¦êìm=³»^Å™£‹Sf%„–áˆ.¢ëÂèƒÏò­o}‹úS&ä½9Tz=\T´³AÏ6Õ3I£vmšå‹¶=× <…‚Z'ŸWËMS¥!)¡ÍÈ9㌪~Ïó‚Ì+: mÝ‘#|h÷n–Äb¼øË_æã¯}-w¼ímì]½zÊŒ>¾ïóÙceY$ÔÏ?Ÿ¥’B¥NO¡2|dófº>úÑ@Gºê“Ÿ$ò—œ~“*ÅË妜L|híZlÛÆ²¬²vé „j©½\×UÂQE&˜èzÕ¾Ó²,ÒétYß­Ï»ï/ÿ’—<ø º&Žá3>ÈÀóžÇ¶ÑQïÞ]¶M<ŸÒç¬köÖ‹š"Tá§?ýijeÛ6Û¶m ŠÓÏ„¡¡!öíÛG{{û„(—‘‘FFFèèè ££c^ò¿3ðíþÐÑèû~ðÃשqÎ9çðÝ*Ë ”£¯Hè ž ó‘»s: è{*®(3)æ&4Ÿ©læ×>õÄ€¶õëÉ œãÑ®p¾¤¸8Ê>-àP(`Û¶ª?Rä …à&‘L&ƒAv_$ÜD+òáM&Üÿ|˜¬êGâ‘ã¾â¦›øá¡CìºôRÖ¼þõ\G[±TR#Wדn‡ö!ëïûô§kN´ hôØv½ ¿v`o^yˆí¿þ5|ì±8Tø-žB9Vm„Ž‘JÇA´ˆzåEéºê‚ðêì SŽø~øC[”"NV—¾ZOþõ}ŸB¡@:¦P(QÅb‘l6Ë#wÜÁÐ~ÄkV¬àÆøL×å/^ô"þç„Hçóø(Ÿr´éO­\ÉÅßûϾï} ¬ZÅP¾¢Î>›å¯y ¯þøÇ9ûüóqJmIw—D Çqxi©ÝÊß’Édp‡ÁÁêS–m`Ï“O'ÄG£í*?Ó~u- i&óië”_šM›X ¼êž{xÙßý]°üÑM›xåà WŸ~:©/™•‘Î+ú=µøÏ+Û6ßÔlñÝÝݘpñÅÏê ¯¿þzèèè`dd„îînn¸á¶mÛFoo/›6mbûöílÙ²…žžž9`&OS.¦är9LÓœ^åd”Ó«Ü€tTÙ|PMñ«"pÌ=“d±2•mÂüڧ㄃˜ßööòÏ̽^ÊdÄQDº$˜h»Ïd2Äãqúúú‚¨Îå7Œt:京Çx7‡êK `Ù®]\vÛm´sï<÷\º·oç 'žˆ{æ™@˜t®ç¤&*Y–Å›fhªu€é$àÊ1{#R6šFÚ§ 3£Ñc[AjCî‚к4Â>Ói•Í'ŠëºA:èlR èZú¹Òó<‰étš®®.’É$étÓ4éëë >› ú¹¶Ú3a8œsÎzb±3èŸbp±¨|aS%qœP ò}H¥”ÐQ,*±¡«+±T& õÏ0ÂBA}îyÊW§ëðš¦Ú¿e©õãñ0`À0 Sþq-n˜f(Þ8ŽA´«Ë4Õ6©”Z×÷Õz™L(úhq¤³3ܨý¤ÓêUïòÂc* †h0C_¼ÿý¬[·gÞ¯©fÐŒ±í^Žq,<ýøƒ¾ïpðÙ„ËÒ.+½/m3%:âÄ0ÔE»zµZ®/P(¿ø£Žaà –H¨”Tñx d¨Í½ ˜»®¼¯‹Ê†Áev£RréTíùÒ>ãÀ®¾š•¼zÕ*•Æ UCö›+W²á;ß üT:+VÐéyAD\Ôgiš&Åb±l²pU #È€ ¢þcÝ·Y–Egggð=¶m*Óù´ueYƒ‡ó àÝk×+ vàÅ¿ÿ=¿þÑèüÛ¿Å÷ý ¿N‡amáéÐÛø¾Ï¾ð6oÞ<í63¡¡êÐзß~;ßùÎwhkkcddÛ¶éééaãÆôöörã7ÒÝÝÍÐЗ_~9ÝÝÝsR<VDîO:åÏd7­¨=Û‡ªˆZ6*ÄÊ`þfÓ ­Íb¤¦³M`ÞíÓ4á3;vpüñÇ3¿ó‚ÊÑ7)ŸòAsÐ §R)@ 'S… ·ºí£RÆKïS¨›aºÔÎ=ùdÎ?ûl¾î¹jƒM›‚ã˜/꘥lƼhùr–Oñ¹®+7 ÃXT¢J3ìS„ÚhÆØV„é‘{§ ´.²ÏD‚ "‚ã8ƒ®˜¦œ¶,+Hí•-¥ 6M3ð)DsüÏÆÏàyÅb‘b±ˆã8ô÷÷)Çtíƒ\.lj'^Í™g~ÇÓ¬þ]º”D6«„bQùÆ´ÛL‹†~fYJÈfÕ¹ŽÇÃ@€L¦\<Ñe*´¸â808 #–¥¶×BL*Š*}}a´ˆ®ÃšË©Ï£n=ßWÛêu*çÂê6G£RúúÂ’QŸ³vضÚFWTPÒûÓè?ò‘øÎw®ÛµÕ(š5¶ÝWrµ,/ÂÎçïäå/y¨tE0w9°ÇÁíaê˜ZÕÓŒi*ÕF)K=-0_ÒÇñ}Û÷ñJJžïûAäY*•Âó<òù<™RXT___™•4 ÂlÚ¯¬ýVËâ§«Va¢D—ÊWô’ööòóPv˜êäéŒ*šl6[“p¼ì´Óˆ•Ú5úþ÷ó¡C‡øö¿ÿ;ϼóá÷™&õÙÏò‹þ3?ýiò¥Ò¦iò½±1:? 3›öû|À»ïƹî:þÖ4)f³_¬oýzbŽƒiše©Äôqvuuáû~ÍÑ…†aÐÙÙÉ…^ÈI'TÓ6µÒPAedd„žžž ÒEܾ}û ½½îRޏ7²qãFf­vº.,7`sEt‰žP í/Õ× .$46‰Ð/­S@hz°Roôw,VAe*ÛæÝ>µpýÕ¶6.¸óN˜g¥¸’4êFOGo4Qµ}2t –¹âŠ(TtEÖóøÜ#ÀyçѶcÿ÷øãëz>Z‰é¢Ïg#XëÔm‹…FÛ§ µÓè±­ µ!÷NAh]eŸ•nî«ÞhQCOÔë/©:ñ*y·âñxà”­fHg_ÑÛêtbZ¸Éd2 “Éd¸å–¿ç?x'ôžxbûö}·¼åx C‰}}ê|9Ž8'ŒêÈfÃrž§D‰’N«Ï´oÓóT4‰mÃèèäÇõñVž-¼x^¹B¥ÒG¬VÉ©ÚÏ\yŠ£þ“MàŸL{ÓQ%+Vf¡Ó¬±m» m.<]„å×/gÙ²e*…^ÅzÆöÒ›µÀñ(‡J¥›N‡"¹n~-F …ª=)ß÷}\×Å÷}ººº‚Éd2H¥…Ô©H£4 3òZ@ùŠö]qE°ž‰ò—L'äóù§/Œ ¹/þÇäŽO¸ð ÉsÊ›ßÌY§¬æ+^Anóf®ˆad³Ù@ë0Œ Ï¬ô¿é辩Îo¥X‹Z½½½3:?µP³ ²}ûv®¹æšào]~h¨.¾øb.¾øbÆÆÆØ¾}{Pä¾»»›­[·NP4ÛÛÛ§-|àÀƒŽ2âðŽ,sJJ×dT~¤ë¤¼|?«îÇ’ âûþ¢)¯*õ>žÉœ³ìÚµ«Ù§aÎLe› ì|6ö¹k×.†††&äÜ4 8ˆϭ\É+J§êIe£>Õóú8ðøúõóRÑÏ-µ¡€Ê½é:¹b‘ÿ>tˆñ‡â©Í›UtÅtÔÃr ÃàØce``€Ã‡þ ¶öyøðá Œ[fâ fdd„_ýêWŸ„]TûFôÌô|>ÏWŒñOÿô ¦y·Ýv„“Nz;–õAýÓT"E<^}ÑÙ©RyiaC§çÒTºaLs¢2f›M4ÛÖ6¶Ý´iSY)‰(«L8âÁ‹âðèòåœyæ™Õý"W¡rC‡òhëëQÂéë ……bša^8Šå8U#`*ñ}Û¶›K&“tuu‘Ïç{Õ½mÛ®INÕuPªM$ÍR[¶ŽÙÔ‚Š *m;v`”¾ëÌœµ‡ñõ›o¦3²þžÍ›yùÈ_<ÿ|2„AA>ðÄYg¿á’—^J¤lQPÛö˜ÓOçÁw¼ƒŒiõs?vî¹üùUWÇYVO¹Ô±Tö‡µgµ ÷CCCuÛÖ$¨´··³©”vF3ÌÈÈ[·nedd$¨Å¢g#Ìô;<8éCçW @Ü÷•#µô£ÌDPuq/™õÑÖN£jtèY ‹h¾zÍÕWÉbyèÔT³M˜½}îÚµ‹íÛ·WTî6àÌ»îjXÔ3ªYX|Š™ :¢ä©—¼„µŸûܬ¾ÛóíS?tJj¡ŒŒŒ0444éÕB¤Qc[A¨72¶šÉƶ‚PoôØöàÁƒÍnʼQϱ­®¿u¸®[×t_¨ô¬öD"a“úƒt4 ¨gËt:M.—+K)4•#÷U¯jãU¯Ò-#•Zi*)•š(’èó¦ýÎf.îéÊEÔÛNÛvttLzŽvàÒ$ ;ÀªU«Êý4p"p'*Äc-ðldºPÏdäóJ),Ô{]gr¹¶mþSm×:ª"êÇŠ×é2ÕöÐ ¯íúÇú¡¨§Î7Mþ6RðÞ-µÙ.øýïÉf³A@‚æÈ¦M|`ß>8ÀÓ¿øÉR“ÄÏ:+Xo¾'ÙVö£Û·oož ²qãÆ)#OfŠÞߨØ—_~9´WäƒeÀÓ V׬YÖ-[ª~öˆ _J„Cf³Ù²"dÕÐ)ö¢ç?,ÉÁ¿O¡’Ï5¹Œ ›²8ê-ÜÌGj¤Zhv¤Í–-[ê:Ö,ªÙfOOϬíóÜsÏ­úY(ÀS}°ö‡?Ä GvuÅ„ ,q2tÁ¯$á H©HØñÇóŠ~” 3¯AR(È÷õ±bhˆKwíâGùžçq‹i’N§Ëì~q&•k<lÙ²eBåBf>ísÕªU“Þ;¡Þh¡``` ÙM™75¶„z#cÛÙm¡ÞÈØvfcÛJŸN#1MsFïóù<¹\.¨÷ë8}}}eiÇuae]Ì~ºÌ+ÓaYŽãày·ßþe.¹äÃÀùÖ‹ÇkΊtT#cÛ¹muáǬyåñ<ÿO+ÿð[À±`,-ý­ÍkçNÈmSùÜtž83‹¸®ê’ɰ`þl _¢NíeY†a`š&±X Û¶Éçó ¾ÀTÒ£b‘ Äëýj¯•Qú»ˆÊ¼’>çœ@1Q>5è¿òJžýÃxÕÿ÷ÿqð‘GhR—LOOÏ´QT³á˜™n022¶mÛèíí¥··—mÛ¶166VÓ¶Û¶mcëÖ­Áßmmmlܸ10ÀÊÜ·oßœfꥦëÙZX™êâ™Ì.¦óÛÏU>°,+("VoQsd1Õ/8˜Ê6y·Ï§€îùêW•¡ŠžAuü°È¡n‰Òr«´Ì-ýë',ŒÞñâ³íÙg'ý×u11V(ðü—¾ß÷ùщ'²ü?àìÛoçeßýn`ï•bŠ T£Ñö)Bí4zl+BmȽSZ—Fاë–G9xž×ôɘ“aš&ù|>¨ây®ë‹ÅˆÅbär9Ç!ŸÏ“N§ƒÉ¸s™oÛv ¨¼å-/çöÛ¿ÜìÓ ´ÍÛžaÁ³Õü-÷N© }D÷3{¬<*Å0Ôì]ÏSJ`:‚P\)Q(H$¾NG¥8ŽC.— „Ì….¤ÔBôuĉHô'6j²rå'‹zôtrH}ô£Œ½àÜú¹ÏÕ5«ÓŒ0:f(¨ôööbÛ6½½½ 144Äõ×_Ï«_ýê2ƒ›Š¨366äÇìîîÂXAå8á’K.™õÁFh7¾ïS,g-&L÷Û/¤ZTކŽf±1™mónŸ—dáõ‡7ô:‰vô9ÔMÁB‰(9Ô ¡€ [úJÿ¢Ãîd2ÉÎï~—ÎÎÎ@8Éd2¤R)@L$øÀoy ôWEÂ÷ùå+^ÁÇÆÆhûêWƒÜš“ÓjÍa¾ÐliŸ‚ ÌŒFŽmA¨¹w BëRoûô¼òI± !íy0+Ü4)‹ÄãqU°Ù÷ƒ"ÍÑug3Ùw9ŽC:Æq™+4klûR–œ2ÆSÕ Ø üDýiÖ#”;kUJ:­ÄÛ.ÿÜ0ÊfÑ›¦LpÅbtvv’J¥ˆÅbÄãqlÛ.+3PK}”ÅD5Á8ŽòEÉ£üf•½P¶´ntÚ°eYuõý5K,¯¹(½ŽF¹á†ÊÂœÇÆÆ‚ˆ€k¯½vÒ}ôôôpÇwábÛ·oç’K. ö·eË®»î:6mÚÄöíÛÙ²eËœr®K‚e@.§ŸžçM¸Í Å Ú¨A„.>´˜h–êÙ¦³M˜_ûü÷ üé ?kø VßþЍèÝù{¥ ¦GÓé4ŽïsîÇ>F±X䘓Oæs²¹T#eí+_É®K/å½Gލ™¶Í}K–`f2üùà ÿàºø¾?iTŠÅÂg…ÆÐhû¡v=¶¡6äÞ)­K½íÓ÷'¦©r]·e#T4–e5¢uæ£>C5âñ8ÅbÃ0‚÷’=AhÖØ¶§¶§à¸“žf|ÕªòW¡fÀš¥÷¥·ÉË/×)”€ây“§ªÀqœ –u<üS:̶í†eTiEŒÒ¿j2R-=…aÁy¬§ï¯YbyM‚ÊÐÐ[·nå–[n™¯­­-Q …”‚ ÀÍ7ßÌÐÐP ëéé¡»»›‘‘‘ ŸÍ†3àF~eÓ4§=Ñ–UÝöæ þ·¶mÓßßßNa± *‹=êf*Û„ù³O߇=ÀÒ[omZǧ¼è—YúW‹ÜjÏÛ¼™/<ü0Åövö}ô£ þÇнf G>ñ Îüå/yìÇ?æwÝŃü §ÜzkXÔË4q]wÒk©µ‡øB3i”} ‚0s9¶¡väÞ)­K=íÓqÂú)žçQ,ñ}?x&+”Ö«U:pi̤7] ^§‘®·¸¡‹lƒÊÄ‹Å&Í¢ ]4cl»íaõ(¬xëv¯Ø¨|#Ñ"¸pù;ðߌӾè°, ˲æM×ÊÔ$¨ ÐÝÝ=e¡¡k¯½–ÞÞÞ`Ý©˜j?óe.𔚠N*óšv;WÙ`åïÉ@‚[Šî0E½EÃ0šª À-v¦+&6öùUÖšaxq+QË@Ù gœÁý_̵ÿú¯¼òJ¾òÆ7rþ»ßÍ•¯}-¾ï“Ë別Räìe—‘¾ì2€²â‚“!¢Š0°OAfG#ƶ‚ ̹w BëR/ûÔu¨r¹Åxœ'Î:‹—··Ó…zæóQþÙéÜ|)Tvƒ,µ 0³%* är¹:[yÚ0]Ç%“ÉN§ë#,=¶}êé§8qÙ!†t"û2+”oF *Jïÿ?`Ï}ൕτO¥”#7W³ägRAEûc´€éy^v4F¤,¶‰ðL]XS •}ûöÕ´³é„”FâKKçQ‡µzÎÌÅH½Eˆ¾¾¾º¥q‹¢kaîÜ t”TƒV»®F5 ~Á»ÞÅÿû¿ùèÉ'ó®¯G~ù˲°ì÷¿éM@¹H3]?”GR~ ‚ ‚ ‚ ÌÓT¥>ñÄ|þúëY¶kf&ÃÛV®$‰zæÊ£ü³©)öã¡&ê£jn6ÊM§Ÿ‘í¿ÒÙLr¹¾ïÓÙÙI¡PfíÇb1©³"Ô…NàäôÓìŽYùÔļ{ \LÉd”Á{ž*8ŸL*Uu2™LPˆ^‹ ®ëµþâz *>¯ˆjTÚÛÛkUta¢V`wäjA¥L3œÍEú£›£!:¥Qì°àåk‡¤˜*‚Ä.:÷\âñ8†aK¥ f9d³Y•b™ $r• ‚ ‚ ‚ ÌË‚cLøè’%\qË-\uÿý¼aÝ:F £L TAe]K3ŠvÅQ“é Ô„ºU 9“õ,ýÎÎN’É$Åb‘®®.ŠÅ"–e‘Éd&lãû~àÄÌd2“NFÕëø¾O&“aõêÕ8ŽC"‘¨Z¯Vg~p]—®®.:;;‰Åb ‰žç‘J¥p]ÇqÊ©…B®®.2™L  …IÛ­qK5Oc±¹\.8ÞT*üíy^Ù1êm„Ùã;³Çqê1OsÒ“ßT ï\°ïÓGïz`Ei#ÇQbŠëª¼ò º¦ –E*U].M&“d³YŠÅb‘â8ÎQíó«×±Û¶Ý”t_qjJùuñÅO›Î«··—ŽŽŽ–ŠRyqR¥Òi¡j¹!ù¾6+©EäjTnM¡ñHÈëü1T„ž¥ÕHwSË¡Iá%‚ ‚ ‚Ð(20ûáÂ[¿ÍYO<=ų¼EXëÚA9v”ØRúJëÅQµW\Â’õ¶í¦N>Ìf³AîÊݤR© Ö‹~å”5M“D"Ôg) ôõõǃ- ž¶mS,1 ƒT*…mÛxž‡aAíQ˲ˆÅbäóy,ËÂu]‰étšB¡€ã8 ’Éd¦½P(`Û6ù|>ˆ®éêê²,r¹\P×A;ÔÓét}£¿Ûóžš•ŽŽ®½öZ®»î:’É$===´µµ066F¡P`ëÖ­ÜxãÍ;c|Ý 6sÅ c®E¥šLP™.ã“Acg+e±Qj+=Ø¿º¦®gÁ³¸nK‚ ‚ ‚ ­Í!”0b~ó›X%a`2â¨t^F=¿™@**%:o»‘Ó›í˜ìœi!Ãó<âñ8Éd2È“J¥Èf³AÄH<'›ÍÒÕÕ¥²7”Òc»®K6›Åqœ2±Ä÷}²Ù,žç‘H$‚ÌÑsaš&ãããAJ2Û¶”Øãº.£££Ž¥P(Ns×uq]·,2AϤ÷<ÎÎΠM±X,ˆjÐÇîyét:ÈPQ,ùèG?zÔ¦š–o|’¶½Ï°öŒµìÖ ³À’Ò{CÙ+·Þ <¢"Q|_¥ø2Œ2§­çyAM¢B¡@±X¤¿¿Ÿb±H6›Å¶í@X;Új¦,Vj ¢˜OjöjnÙ²P£ŽFÙ·occctttpã7rñÅ7öŒMÁ½EøK Š®K>Ÿ”îzqô‡ Bí8ÀZ ƽÑ9ïKAAA¢ y*š¤àyÓ:K-”_Ñ8–fO§Œ¨o%’Éd ̲¬²TA}}*ž§²°·UJ¿”L&ƒz£z¹~ :2f*ÿ®Mý~Û¶«¦.2 £,!ú}]]]är¹ .¯iš¤Óé µ·Þ^Ž^©ŒÞ±m›¿ø‹¿à‘GiöO´àÐÓ—Œ/á w ^VZ°È O tpb1%¢@X³!r éè(}­e³Ù ]åõ',´HÚHf4M|Ë–-$“Iؾ};  Ñwww322Booo ¼4›Ó,eONÉÈŽæ|x‚Ð*ø@›¾ï,º°BAAA¡¹A‘"Wz÷ê…y”˜R‰Nõ5 …B!P´ˆâ8Žü–‹”fMÖ>¦Ù^2À‰Xû»ßÍØ`L³ºx"5Éaîlwà,¹‡ ‚ ‚ ‚ óÌ< CÍ5ta¦ …f7aQ²ï»Ëù›þ†SFOQ V¦ûª¤J±ù(:5ad2@„±(‹9ƒ“ï7.ÞpÑ **¼s©+ŸzjÆÛ».TëK6(ÔˆtVB5†x“- ‚ ‚ ‚ óÌ:,•-CRL ómÛø¾/þ®ùÆ…ãÆã¬'Î —½ ò¹Î>äyÊ9[%²Èu]R©™LÏó‚bôкu‰šÁbT\×ûNjdÑ *JñjÌ™YÉ,7“¼›8ŽÓì&-Æ^ày†êäs'.‚ ‚ ‚ 4–ÇLx¹8½aP@MŠÇ„ ÿû·Ÿ;§î=U}­™rÓMÊÉ›H¨t_U0 Ïóp]—t:mÛ‹Er¹ÂÑëº í÷kª¡2000mq¥±±±ZvÕ0l{važ¶]½†JIԜɿ)Sñ‚8X%ûAEAAA˜/û°Â£jtAZ U›ŒþbþôBnýÐ~`5ü5[`íZÈ唨2IÝÇqH§ÓxžG&“¡¿¿Û¶¥˜†F¦Èª÷qÄb±†Öñ®IPahhhÚõº»»ÖðÉÐÁ=Ù,‹3/NãûJ• (¾¯„ЩD•Þ/ƒ²ùt³OD‹ ³B<˜/Ûì–‚ ‚ ‚ ‹ŸáJïeŸ ´>€'žó$Ë[ÉêÇ—©^ ,­´r¥J%4‰8¢Ó<†A*•¢¯¯/ðKê¿©idЬzR(H§ÓÄX½&A¥§§‡žžž¦˜™à*­Þl|ùÕl­–ëËD‰*JX±QCÐþã,­ã¢„—Å~‹—ÎKÐx@Ê.g›ŽOAAAªqøs…Åá$ZÃ0D¬›o<Øõ‚½ÀJ¸7²ÜtmlË‚x¼j†X,¢O&“Aê§lVfó-¸®[&¤5‚šj¨ŒÕ¡Ò*èÓ×È: &**ÅF‰&1TèZµ’)­“@åL•Þkæ;Èj6Ç%ux0 CBë„2<àüÒýL„6AAAa>9\z•LB½°,K•ùƇ'Þö<õþêÅ8°ÁÚµ ó¡‡ Vé¾J~Fß÷)‹ôõõ‘¶m74Ja1ÐÈ4Yõ@ûŸíg¬)B¥P(044ÄÍ7ß,ëíí¥§§‡ŽŽŽÆž©Øí)á²Xœ]˜§ëª¦Y=be:â(a%º©‡\|”Ø2ŒTЍˆ˜,£X¦ôZ©­ú(q¦ò»(íÛúfÐî\©=5”‹)Û¦Zz³tZ’ž åxÀ½ðòž*‚ ‚ ‚ ¼r¬;vìçMAXHhýÃû»@XçªEÙ„gž™PìÚ÷}ÇÁ0 ŠÅ"ý¥ "¦}4Ëÿ\S„J5¶nÝÊÈÈHS=Já³M+4:ª•LIÉ0M%†Î„èí;I(†dqT´J’&Œ(É](aC·¾ˆN*qPÂI!ò·ÞƘd›ÉðKmšÉó £o¡ŽGÙeKÝä$û˜ ‚ ‚ ‚g gœñ°DB £Ë#hW̆ï–Þ˜Lœ-^A,Ãqœ21E&t Í`Ö‚Ê\a``€I?›­Xãøð«_žÓM4™TÅèc1•¢¯%’¨h8*šD·_ ,:‚ÅFõ+.ªÓYêxôº~éï*bÄCõAzŸ…Òg•ø‘õÝÒú39cné$;éâa*ÛŒ~>ûô€{•Нef 9(#È ²ÐòÔÓ>A˜õÛ ‚0{äÞ)­Ë|Û§ <˜©o‘e™‹'†Ñ:þŒ:Rϱ­‡òuú.,ÿUäM,Ž…BYê Û¶ƒ:6ñxÏóMauaaQSʯù¤··—mÛ¶±iÓ&FFFhkkãsŸûmmmlÛ¶ÞÞ^6mÚÄöíÛÙ²e ===3þŽ3€;}tγàûúT”Š3“P9 ë¨Ä k¯¤PQ-ZôÐuY\¨™’޼·S‚ #V¢™ñ´@ãU,÷Jßí£mtKŸÅ#߯»®Bi™hà “©l˜³}ú¨:b¾ï·NŽF­>Ú(c3P×B4‚õ·OAfO#ƶ‚ ̹w BëRûô6êû¼)‚ŠÐ×7“Äú “FŽm¯0À?~­èYÞž§œ±ž‘âòžçáû>žçaÛ6Ùlö¨¸„Ö£¡‚ÊÈÈ[·nå–[naãÆ€R·mÛÆµ×^Koo/7Þx#ÝÝÝ qùå—ÓÝÝ=«:-?ü0^8÷0OÓT6\oÿ¯&¢ºj¢E-–è¨ÈG>3 £U Œ”‹n= %~(hÑâM’PÀÑKëéï³ …] &Ny¤K%¤±¥U™Î6y±ÏdŠE—d©XÓÑá_ƒ„¡aýÌ,\«^x-ÒŽ©pQ†ßêí\À4Ê>guÌ£:ü1oAhÛ ‚P;-ï„£˜zÚgO?’“\æ@£Ç¶o¿¾¸®ô‡Iè˜4MU‹¡¿¿,BÅ4M<ÏÃó÷}L‡òÖzÛï'¼¡ç#ï“”¹×b¨z(:B£ˆòÍ‚ò}ꌄVd¹þžªç„0˜ù§÷§}¦ÉÈz“Fn,*ŽD÷§?«Ì~dú“­ÈºúU‹*>åh¦óãºç Ù‰lt´LrËÎ&2k¡Qi›@Õ_-öyî¹çÒÓÓøU- Öz¥rÈÖË٪È¢µPô^-Qµ{Iô×ÛU_êÍd]XÕaè03­¦F×,½ê¶ëZ1¡Ð¡Ã®ŠÛ×J¥Ø¬¿£r$áyî'¬@WÇsÚÑÑÁ–-[øômŸ¦›îú|I˜/û\µjUÙ½³f´(W¹L‡Dê¿uÈ|ÅçqäiTfµ-6Ñ ^c[Ah$[¶l™6ëÀB£c[Ah4zl»Ø"¤æslûÂsÏ¥ÿDIe#4ÛNÍdcÛ9xÉ©`¶·MÜÈóTÚ¯º>’iš­“õdRÁ¹•éé陟Ì4¼(ýØØ×]w###Üpà AÇÓÞÞ>aÝ‘‘‘²0³Z8©ôºo¢:mW-D×3'y_íï$Ê—=ŸÌtÝ”(Ú‡Vkéƒrßp屘™ßUOàל¢Ëu6§Xé¼5Å¢ Öa.Ô{l«ïyÀ #L“ŠÊ0 lÛÆ²,âH%´ˆq]—X,†ïûí3KjT®¿þzn¿ýv’‘êìÝÝÝÜpà lÛ¶;o¼qÊ}lÛ¶±±1.¾øâ²P¸ŽŽº»»ƒ¼ ÝÝÝ 122Â%—\RóÁ8ÀÁ8f ½®ƒù™Šùîvæ+{‹OP¹ÿ|•õµhRm"¿…š=aTL%•’àTÇ·X2×Le›óeŸÇ{ÇóË3Éùœ¯LçðÖ)¤t!ýÃé°#]«A×íˆ'1¢ÃLÕ>‡rôFS‰i´³Xש†I(¢è\º˜Q’0ç.8¤2¢F­F=ø¡£ZÔ¦òÎw§eRÝØ+ש5‚Á€ßŸôûyndãi”}NF¡Åÿ†ô{Áÿ±V  x&¸'€ý&5È0Àõü×s{ùÉ>Bú¼$YWú8ØŸ…Ë6ïaÙÞe¬òW…m†ò´`C«¡íÈ®Xaç®Cµªkþhô÷بk¾0Ò$ŒJËD¾§PZ/Ujw°ÑË„£ŠzmA˜;w ‚09õ²Ïã=xâ‰'š}x‚° iäØvOx+tìÀØHåˆF©TàyŽãàû¾*s$Nǜ5¨IPbÛ¶mÜrË-B¹t.Ïööv>øÁrË-·LºŸ‘‘FFF¸æškÊ–_{íµlÙ²…-[¶pÝu×±iÓ&¶oßΖ-[hkkc&,'æ³x<ÞGA:~‡NåW«V{2¸Kõò¨ö¸Ð˜Î69Ù§$>n˜½©½êíàŒ:*u:®<¡“rªþ}º‹Åfþ±t4ˆ=tß-~¤£J´Huð:„µDt›ú"ûOFö¡gè7:‚UçïÓ…ÅKCY ?Zxqi|$AeQ¥aþ=›r‡¶Ck~žézÛçt8Œ~ ðáw§âýßäŸ6ü¹o‚m8<üðë×?‰ïÃ’ÿõg¶ÝÌÀÀ~ž<þKüdçkø§_}–·®y=ç ­Â.ED¹ÿËœe¸EðŸû(»7S×iñQ°Ò×§~¯É•^Ó¨4x£„}ŒOXÃ¥³´/}[„u}¢…¹´ýj¥ß'ìÌŠ(ûÔµatêAÉ$å‚‘YO§·;ºÒ×.J1¶aæ4ûÞ)ÂäÔË>Ó>ÜôãÇÄA(s ‘cÛ6 ÌCðä“Obý¢T4Ü-yìªØ±iš$“I±ñy žI®w¡5 *·ß~;ÝÝÝSæÅ»öÚk) Mºž6¾Éèéé¡»»›‘‘‘`vÂLpeÀ½÷Þ‹aÊ¡­Þ.´4ºFöLÐ>ª™|‡FûÇjÙ¦ZÊ/(E¬ZÕ¸“T'¦³M˜›}zÀ €ö/bÕª_¨…6ÊFµhà ÚažA¥¡j%²(Gj"²LG¥hÇ®žõMQµ ;ªßj&ZôÑmNW|uD7«}]„ÑFITÔ’´ʉÏ=±Iœ?êmŸ“áûû;ˆkõÙ‡“_²“[º‡â †m«ÉC©T1H÷Ùßßa˜Üxã!>þñGø‹¿ØÅï7kþø..þ“N>’ßÌóV<É«.xœÏlnçS»>ÅÞ—ïìÀ8ÒOµLùá‚ßÞÃ¥ËMÛ„âF ü,xÇ‚û(Ú`ú`ü X¿÷ÝP|ú΃L \ìkÀÜç<0VCßû)nóE~œ?ß…>»ÔŽG¡ðfõÀ^x3X¿+ …Ú€«ÁøÄïuÞ¬,ä6‚õ>pö°Pè‚äñXé8¦‹ø* 0îßûÁzx»WªÚ6ÆKÔï¦Sá†úÛ²Ô«ëª÷ž¾:Nø¼bšj=PŸƒZÇuÕk2©^}?\×qÔ«m«õ’Éð9È.õ!®«þÙvضgž9ŽC‡–Ï›4‹zmA˜ͺw ‚0=õ²OÀµk±l™8€a¶4rlûœ8ìݺ—ç€ÚàPäÃ*¢I¡PÀ²,T„–`ÖEé{zz+[ÖÑÑÁ¾}ûæÔ ¹¤œVzÿ''üIy¥saA 'ýÖŠEfQ«º,€`*¦êª àξhäijs±Ï3L¸dé“\ù”Z ‹¥ëôWIÂ2‰òž¶âXxºúÚÉ¿XûùŒú™-Iª;Ÿu»† „­_ÚÙäÆ6Žùtù>8`du::N<ø;†v…eÁã•Læ>¾ýÓŸrz<®2e•·úÐ >þqŸ»ï>™\î’É$¾ïó…/¼—3»·sÚòwðùÛ.ä®SrÚËùÐʻٳt?z#ï}à)ŒoÀWžz†÷Ÿòýò:v>~ é4ŸãC^…³ú}ðÏç»`Œ@öÓàÝþsÀ^Þã0x)» {˜Á}¬SÀØîE`µAç{!¾Fß ÎN°ƒq<йÿ8ãªp¢q>XËÁQé̬sÁhïð/÷pÛ€U`}ŒÃàüŒÇÁy1X·‚¿ïƒü ñ˜ØË ùuþ}–~}`øŸ÷ƒ{½`AáÝÀSàæAÈ?rËÀØY°üe? Ì¿€ÄVü8ÄÞ ñðÖÀ~!8?ç'~=侩œÖÉêXÜ÷ƒ³xqéÜþجÖqœPÀÑåô C 3‰¤Ó¡€ÐÕuO<±¬ÙfÓÄQ+­‹Ø§ ´.3µO-¨ŒŽÖ¼‰ ³`>î>ðÐßÂÁ“rüyà%gAìjèëc¼JAz€d2©&Ï B P“ ÒÞÞ>A(©4ž±±1††š›ZÅÎÃÚ‘ýÿu6œO˜?]hytv”™t³éJu–•j¥4&+2ïOòY¸kï^8nÖÚäQÃmX¾²ŸëÍîpaõ£;LTÒ$Ž0´©Ù Y˜$àÝÇ~ ²:V¾÷Ä/9òôUlݺ—þþ¿W¹kÓiN¹äÒÏ Ù j …3 øq%¨ä®óX<¹—BÝð¾0ñ·š ïú‘l‚ ꔃ6Aʱäë!ó¿a¸;²Ü `ûàÿÿñèÄ”kվ헦/{8 |¨¼ Ù¬OR)èëSÏCºŸŽZ8ÌÎs›„#‚ ‚ ñ<ø¯ÿÚÏß(WAhu\`ÅCðàºÙôäcÜÍËÔ†1¡8½ëº†A,cx¸ÕÒ˜G+ÇÔ²ÒÅ_ÌÐÐwÜqǤë ÚÚÚèîî®e—uÁ¾•ƒÿøvÖ?¾^y¼¹îUhqfžái6A º¶¹&ù{²:ÈÚŸXWÝsOcOÔÄ8Ï{âyÃ3Ó(o¢ª~]¨¨lãyª0™Î!#B}qÀû%¼¬v¼•î«EöÀÊ•Ðo°ý‘÷L&Éf³œÞÓÃŽ¶6 à“0E¢a¸®‹e…½g6›Å0 l¾ÿý—ó¯ÿºŽááa Ãàò¼œ¯îø*ÝúQ®Ú}›oØÌ»_p&oÞÿެ ù-}õ(æ0Üsù=<|ð¬§Á;®~ùžäK|çkßáîÿ¹›-_ÙÂÈ¿ŒsrŒ&Gydé#Üä~ÈÁ[?ôVv}|ßÜóMb~Œ;ÜÉ_}ï¯ë£ÓíäÁ~ÑÁQ6r3^ÜãÎ_ÜÉ¿òaú¾—\}€»–Þ…ƒÃh|”G×= iØñ;øÓÛÿ”;ÜÉ'>‰c9ÜóÌ=Aݤ›vÞÄØ÷Æð þ0;¶ìÀµ\unKµX’mðìÊgÕ ÜæNÂ4ˆ6µ‹ÌF䟞=$ŒœËBú_!?ŒR^’¥6Ø¥¿ûÁx£z¥U‹¦/ÒŽ$ê†&Lƒ¨ëǸ¡Ÿ:%˜N3à98ù»'³|¤üAXxž‡ï‡±ùni\íû>…BÇq(‹är¹`\.W¶ž.ìy¹\.x_ù=‚Ð,t¬eÉÌ7 5eÞ¶ÕToÉ™)õÃs .ü l3À]Æ_ÂÜx#|7ÖÅ)ï|')ÂÔ‰…üãOþ„Ê×þ}ŒsÖ¯óWÕ`·ƒƒƒe¢ëÒ¯/e©»”uÞ:ºr]÷|îŸãЇxjÝS¬Øy7Ç\p:É®â’?^ÁyÞŒiš|Úø4;¶“¶\.„†{qÕ“¿÷‹ïÅu]úúúÈår$“Iv;4ùÖg¾Å}c÷‘5³teºH&“8?txÝ_¼Ž¢SÄ÷} Ç ÐYÀý‹•±ð<|>O¡PÀu]å´r 9–Äó=–î_Ê©÷Ê3ç<ÃÚ­å2„išJpr-lßæ²O]Fç³ÇC¦‹ÎM÷ò©ß×97çò®‘wñ‡ö?Ðæ´Q(🔃¬X,ÊùeÛ6†aëù¾<ˆ˜¦I¡P —Ë‘Ïçq×uI&“xž´/J6›%“ÉŸ¼þC¯çî¯ÝÍ>õÎO*•¶í@pq]7˜1ÜÕÕL¸pÇq‚·¹\Û¶ƒã„z°fÍ#Àšf7C„xú øýÝ¿gYç&صkÒçÅÁÁAIõ%´5ç)Ú²e ííí ¶nÝZöYGG7ß|sS£S4ñ8‹.þâ‡á(oyI$DE›ò¢ó“a„ÙáÝg=ýx¸ XT7ÌBA½¦ÓJ8TŸe2¥jØ„ŸéuabÄŠÌD„y!s.¬û&xëÁïbH>3Êi6ðü®.þô'?áÿ½éMœ¹t)öîÝØCC¸»v‘yÓ›ÈS @xâ ìU«x•a@W—T'„oWRµÀ q+8‹|ßg¥·’§‡­_º—Âï—±êñe¼tÙª²‰^² ¢$ ²ÙlàtŠrÅ®à ®Tž^€L&ˆÑ½vé}D¿Ë÷}r¹¦i’Χ¡ ø´:½_çyùä>÷oQHCöí«ˆ¿y žç©uÀþû¹Ç¹'pti'“ɰzõjuª,‹x<´O‹+Z|1 ƒT*…ïûS-ŸÏN®l6´9]¤Ýó¼À‰§…£ÿúoX>øçJÄ1mŒó VŸ½šS?û^rÂןþ;~ó®0U¬õ‹~ìƒt?Ûüqãb'“Qó|_n“‚°(‹퇋Å"Ùl–xOWW¾ï“N§ƒ{G6› D|ÇqˆÇã žN§I¥RÁ}ªPŠ0O&“‹Åàs˲p]—L&ƒeYÀßÕÕÅððp!“N§ƒöår9úúú( ÁgÅb‘x<.³“…iyúéß#‚Š ´6Ú“óÔGaÙ…Ëà‚—ÂØ˜òÿT}ϧYvn©Ð©I3•>cºI²~韉ÊÕGhñò0º¨Ðó£:›ÝEޏÀžýßç*®R =/Œ@‰ÅTôI4R¥ò)™ “ðƒ]J|$“垢 9fæ -âˆWJX„¸€ï@.«Ò°ú¸tÿ.þ-ñžêÿ1O^vÿxùåü#(N$À4‰çóØ'žô©ñŸþ”®Í›É:޲—¨=û¾²Ýx\íc†öd†r0Y0J?ÿûŸñ»eË9öÇÖ¼Je:lÛœAÑÙQSÍ´5 ƒl6"á{L:†0M>ÇåGÁ†ƒGNØ÷ùœ_uÛ|>ïûUŨ¨ã)ú¾««‹b±ˆiš¾§Ú¹ÑN,×uÁ¦ò¸}ß/k‡çyÜöý<Å#ïfÕê畟 `ݺueãI¡:¾¹œªK3Ýz÷Ýw?¾Ã0øÌgÚXÇÞ½«Ù¾}×…#GްfÍAöî]ÍßÿýqÜzë,k¢‰ ‚Ð8´À‘N§áA÷·ýýýtvvbšf™¢Å‘b±DhÑTÿ«÷©ÅÛ¶ñ}¿ìïè6 îEñxœX,¼·m;ˆH±,+ØÞ4M<Ïò,’É$©T*ض1 CEv–D‚\.‡eYd2™à³X,F?‰D"ˆŽÑÂŽÈÑ‚±X Ä#ß÷‰Åbe“t4f"‘ “Ífñà=glZ¡¨Åb¹èÏ\¤ÈfÕv¾V9Å’É„Ëfè8’DB}o´­¹œšE¡ÅƬDÓìhôàÎm­£3ÒõìÀf=„9Ž´Ñó¼à¡^;ô2ýà\ù+4†ð¥°v܃mÀ—¯¼3›å]##ÄP·ÆÓTQ'%¢îu££kûv2Ï{Æ߈kÛx”Joø¾²“®.e;ýýašöîÖˆeYœvÚ.;fg]Ïv U‹v©™6ݼùKÀ+yê©§ªGëTÁ0ŒÛK<'•JÍèáIJ¬)ûÊv˜¦ÉÒŽ[yæW³k×C³?oG9¹œJ%]((³©üÉŽ?~„ÛoïàSŸúW^éððÃáû§ðž÷ü€Ç{€[o=“tú0¦iqÛm{¸ï¾gøÛ¿=™—¼ä¶m{Šý×óxÏ{ÚÈd¾Æ£Þ?íu½}{^ÕÚ¡‚ L‚v˜'“É@¬‘@GèZ$Z¸H§Ótvª)`–eaš&©TŠx<Dê>Xÿ­S‚ †‡‡ñ}}}AÄ¥N{¦TS(¡Eo.— òúg³YºººuŸÕãY-Øèú4z\®…9ªE3Ó4ƒIú»‰DІ͛77û2nY Ø¿ÿu}Žªž‚0?,÷ íàÓZñðì…“Š)®ëþAh%j*J¿P0Vö Û‚º «Nû墂äïzVÞ Ê£žEbÕE\s¥kÑ%ƒò*IQEƒúisHR=0k=ìhÛ¡¼/•¹Gf+zXV¹˜êïáaåì­H«³óg?++ræºnS:‘HQzö], x:ŽÚwå4^ËRÞ¥XLý«LE–É@*5qù4d2™ ƒã8xžG"‘fªéæ©TŠ\.G*• R#¸®KgggêA?Hf22™ ©T*ü"ÏSÿJïõ9ˆ%ÕËt:=+¯P(i€ºººÊ¾W·OŸÃL&l§Ã)ýºÍú¡?‘H‹Å(‹Áþ‰Dp¼ú!VïC·O˜>ðW_ #ðlÇaäÎ;9ðîw“èêÂò™L6¦Ißßþ-Æ™gR¼ä’ è³$LSy…ÓiÈçË=±Õö­+›WÁ0 V®¼ÓÌÕ='{ÿÜÐkˆxðÁwDNaýjE¥ÓiFGG'¤›o\×åÒKwÕõX;…‚ºEærêv£MÐóà¯ÿz©”Ïü³ƒ3ÎØÉë_ˆ¼`Œ¿ù›ÃAÙ³X,¼•‚09z|¥ÇO:Í–Ïd³Ù²‰%Z<%VhÁ¶í`BJµšWú3-dè 6:Фr²S*¿Ó²,ÒétY HMTh·,+lÛ&ŸÏcšf D·Ñ5U¢Û§Ói’Édp_Š~Ž’Œ &Ñ—l6´W§#ÓE4²C§LÓé;u 2Ý^VM×WӵƴÔ××üNÉd2ˆnI§ÓAÛ¶.û=õx5N“N§Ë–D"eY ,úp]78/:ɲ,vîÜÙìËXa^0.x’ËWÀ+ÎøÿÙ{÷89ª2áÿ›„@Â%“ —$„1±b8‘P•Uª—‹â%ÚV“Uº—WuóÚ½® ââvK~ ê«Û »QQ–L+« ™BÅ] SÈBä2%aŒá–©Ì$!\ú÷Gõ©®îé™é¹võäù~>ýé:uyêœó<çyžA·Q^š‚6Få¡F,`† »ßÍÖæ­Å ã:žD£˜\W:þ«-°Ÿú´¶OóîRœ¦+:‚)A ï‘È!HÅÜ­y¶/Â3L(…ê &NV9_qW(_;s‡w¯YÃë¦ÉËï?¿=óL6µ´ø!ö¾ôw­YÃ!ÿû¿=}:úéOýo¹\ŽO?û,«þéŸVÂ4u‚D£`ÛìýÇ`æ—¿Lº6§µµ•ÎTЇþå_8âÅYvî¹ôœx"ÿç¶ÛüÙƒñxœž~:ôõñû‹/æ¥ë®ãæ­[ýj4eËí·ó™OäÈÆFuaüÁª¯v]nýÁ8÷²Ëü}ÿò—\ûÊ+¼ôÒKìÝ»—™3g²~çNNûþ÷ý™z3¯ºŠÙO<Á¢w½‹·mã…ŽÜ |#ºîO…öövt]÷ÿï 5›Q)ÀU¨—Y,#硸jWé26ª Õ•HTW˜ë’Àkr•*E9¶™X¬ô}zZÙ –åir¡bï'}%ÎTÀ²`þüߧ׺*cF)ìÄãlôFÑLy‚d³‹õ²pa×½“TÊkÇ>ùÉÉD<ÌP6,]‡þp*«œ¦itvzgO̳…ém$“9.¿ü˼ýí=tt$in^ÁâÅûy衳¹ÿþëøÙÏþ‹‡nÀ0à#Ùϧ>õ \0_¼Va”·I<÷½&T(­D } 7Ê+Cõu‰„ßw zŽ(C=%*y|9AÏ´`.®à:åñ¡ŽÜ'h8Wá³Ê[JÃJÏM×u¿<剢®Gpå1ª #ÁuꜽwZ§_'u+ÕYyŠèºN[[[‰)hàQ(ÏUÏ QKõMUƒ÷Ðq¿ªÎ±X¬$ŒXgÀëWÕT=”aÌ4M|ðÁñ|$§º<ò3<¥Ï”_ë„)Ä^{}7ûÛ\RqÂr¢'Î Âh˜2€N™÷:Gydqa°ÕÓñ "± ëC§hL îcàMµS4ÖHüéºFÏO{]¸jî.þEÓùä“Ü÷§?áf¸u¦Rìúö·ùýâŘŸù Él–DA±FÙüwGßgðpa&›¢üáóÍo~“eË–qÓe—ñþíÛK®µ·µy¡ÆæÎeɧ?ÍUº^r ½ð‚·þ–[¼ea¥”¾àÑG‰¦R ë8¦ÉÆB’ið×~«üô§Þ¹Y‹ Å¥ çU90Z[}Í™^8¾òÒuÝ›R­fº®'gA#ŽS VŸ¦ê¤´‡FÁs!¦i`D ×È7Ô$“ôÿû¿3sæL¶ýð‡8Ÿÿ<Éd’-[¶LðÓ=5pñšÇgÿ«¿å-³,‹t<Î\¥|imõŒ)ÕjIJ›à)¼a®Š²éKSáÞ‰xaÀÀ{6ÚÛ½çgÞ<Èç vý}lÛæ} xû•‡ä«3æÌy†;—óâ‹ï®uUÆ "M®ë9qAQìl;ÍñÇ_ äxàï i7Øg,† ï\T"¶·D".Gý_ü¾²ð7=\zé9€×Î~ø»¸öÚ•|å+äÒKçŽ*š§ LU”g…š¢ŒjâHpòIp’H0û`†`À$’ ÇÆPaü*¼‡ ñXÉëp°ð“AE9‰A&h e„WÆMÓJúËÁ0ZåÇ,\§¦iX–å_Ÿà䟠±ªü|‚Çñ󺎣Ê(?_˲|CÊ`ùÍʯqp²Hðy¸ì²Ë*ã8`šgöƒŠ Œû\سåu¦±N¯<‘LEÈÉYB™2¸D‡cZÿHÏö!hã™Ë(†§ †³ñ4S ŠùZ¢Hë+´XÀŽ?Àÿ·|‡7¸Eê ÊM^ TlÛö“Rêºî»Ø;ŽC:ö=”ñ%hüX_(S fŽ0MÎ/,K–©ÆÛ^»–÷žsŽ?C,™Lú®ÿj¶a$ñ“g‚7ÐU A£Ñ(F*E.—ãªARŸ~æ™'¬rL ÅpÊJÍ»€žñ¢àá2T(ž’uƒÍ )Ë£Q‘ἑ4Í+_ÓŠ±c‚eÆbÅiÚÊK"ˆmƒm3çà¼×n4eÍš5ãòñè Þ²E/¼À?üüçÌ|ûÛ‹±|ÆI1ž è­’!`ÌÎdJÃ{©ãézјECž®óýµkizâ 8å”â»Å¶½mê0ÓöÓO?ÍîÝ»k]q!E9…1¤ï¦Â7ºnšd2Qqp9ãÍöv øô€åÊð¢Åš¦qýõ¯òÝï>É 7¼™tz6©”'ŠcI?$õˆeY´¶¶úáŸT®” wI.—óåA ƒÍÒ 4üð].CºÞg8©Ä`ýF•»¯R½‚ß#9F¥º Br$çSÉ (x>ƒ•<ÏÞÞ^ÿ÷`“”f$ už^xáˆÊ:˜áe!þ㮋&ZŠAE#SÆ Е…Ù·ǵ 'ï JG QL`¯Sšc%B©Q%JѳÅÂÓ$©0d‚0Y¶ Žì>Þʨó¥$“IR©étšL&C2™ôcI«Á&“IÚÛÛ}O‘ààs´±Š¯ì8–eùnújÐÚÜÜì3‘H” Ä‚µh­¼aœ)®iEÅ÷`†u 5m`È)]}ÁGRóÝ›m~òí·ó×+®`ñµ×–N•'bxM¦j}ªQ††g$L&¹hÙ2èï/ÝÏu=Ï(ð<´”Q¼å±˜÷,=æÇ‰×PFßö¶,\¸›|¾8«4ûw¢Â›Hø½ÑáºÞ+Ѷm’I/´]{{û€Ð@µ&x?ðÃ9ûì7ñ·û/¼ímOoç€ëΔ`”Çu]"‘ˆo\P“llÛö=QTø­`xTl0ô ïÉ,^ãœÆk4Ë»pŘše1y±5]¯lŒB9&% îhúÄ*I9C½ëƒ^Õc´õ j’ÔHPa·Fs¬‘Gˆ‚ LUà€³¾6ävñx¼ÄQÂÄ”2¨¼±.Ç×"ù©êWUê+¥(W ú2xÜ^g9ô"S’%gÁÊ_à/¼0ê2Ô ¢­­l6ëÇ&v !«‚³Â¢ï’ñŒ·Yn þWÇzÏ“„ 8LJ_C®ÁkÆ"‘ ׿öZoÝ%Dˆâ5JÏ3bÉ1 ßC©ÄÐfšž‘-—ó¶ *2T:ÇñöQòªiÅðt¹œgXQÞUªË*5&“žÖ;+f WõPaÉ,ËÛ¿jÏÇq¼ü0šæ«4íÛç±sçLÞøÆ‚7N:í•ãº^Ù©Té}P9gB:ÐcÊØˆF½G&ΕÄé“1¥ïoàž{V+±,‹>Ê¢E§³oß?rįcYÆ0 ¾ùÍGøâ½¶mûÞ¥jbBÇqÈf³Äb±’6Vå“vWñxÜ÷ŠV}Óx!˜ïY½GCûh A×t¯Ô¬Õ ¿Þ3ç=ß{!v?ׂó·àþ?0l îYÀ/Á=²_€Øç`Õ‚UiÛԧã_¢^¹8xãÎ$Å| f ù¼]Ø&Mqr ^Ø_¥¢ˆ–ÖJs5o6„ŠÎcHO˜¶QLzé$¾k¤ïÇ‘¶Qå*Õ`šæˆs½É;mtôöö2o^­k!Âp8À›€Çïr; ,„™)eP‰Å`öõó臲Ôì¡q›¢úDÁþ¤Òó&ð:¥‚0E¹? ÓßÎåGnÑ~Ê Å¶íB˜O.ƒFpÂØ±€û¿ g7xaõLÓ$6 1zt¼ùÅœ*:#pØ4ÍÁ=JÊ )ŠXLÙ.ÝW6l»˜\¡<^Ô:E*å5âqïwЀ›Í=™L©1%ñê  6…cõõÍŽ‡s¨•Pʸ¬W[›·<ñ–·O&KÃ䙿Àð{Ê Tn¨q]¯Þeùš|g\ra ƒã8Þíio÷Œ ™L¦®ŒSÁÐEJ¿é8ùÈ+¼÷½ýýq õ×ÞÊk¯½‹7¾ñ/œxâNf͚Ξ='pÔQfÉ’}ôtÇåõ×Oá¼ó–‰DüdÍPfH)‡Õ±•RÛ0 ?ܧ Ziòƒš Q©ïÌi!A’ÛA; 6îz….¿œŽw¿›å>Ê;÷ìÁÑuv/\Èó',gÞ0 óŠœ+!º²Ç¾Üž=BìÝlø;®ùç%L[ì¥òL|©àŒrРΧ# Ú¡íŽOãþÒ¯,}ÚÐÁÒÁ5!ªl 6Ð ©î”÷;GÑ0Ãk”Ur5%†·\·u¯BªÁ¶€fŠ'P0¼øûº`F mcŽRÃËsžFj„*WË`ŒÆÐ¡ Û#A%– 5÷h¯S–-ëgÉyW BØ1{¡1ì8Ù³€&µ¶mËûP-SÊ ÷æ>3êýÕ`I)oMÓ±‹ò¨ÏÜ.‚"€~X4óYöžzjUûX…Äï¦iú¹J”Bd¼½NAöÀ%óá²A<>¹W³ðIK)*‚ªR=ŒvÒÃ`y}L³rØ9e„‰Fs0ïX¬²gÊûœõÒClÝúßWa¶V¥Y·šæ•oYŒGÛãqÿüç9tþ|ïxÁzÛ¶·O¥gÙlÑ#'—+æ_ï(¯˜D¢4„ Ú/+æDFMð––‡®¬Wt]ç7¿Ñ )™2Ç·‹p]°¬EärpÁÞ£ô±}ð¹SNÙÅóÏÂg?{ |×…iÓ¶ó¯ÿš'ÖüÇÛ²,lÛös© +*Çš®ëä y¸TŸB…a jÇñ߃jå%T)W„mÛ~Y¦iúÞ6ÁÜ jÿòp¥š¦FqÇ÷pÖGM,QËUY*wòSË‚×;˜7NÕS¡ÊSõTë Ãছnâ§?ýi­™Ð“œnpÁqOuqÖž=Ä/üº‘CõC±NƒÎkþ•£§Mûn6 œ„·o7%»<ƒÊlhýúi}X\´uøoâ9…O€èLh}7ð^¯ýt(Ú8 ™ZÙA²@âQp®÷—Ųl fO0Š®há¤SÞoÐRÞ—¢w …JDñB©0×ÞäÂla[[yÒ(CL*Py'P¶¨d¡nåø7F`¢á(F1Ç)ÙÏÊK'hD‚¢qI+XƒŠòÞq½z”xÑÙÅåþqÔyÛø†©îU\Ž4­CòéO?KE¢BN2¢È5„ðø×áM9O%­QªUý™<+„™)cP±Í'f?Á*sÕ¨ÊH&“d2"‘ˆŸ£Á¶m:;;'Þ¨’£´£(Sh8öî{ˆ}GUÕ>­­­tvvú3åÕA&ˆইá2×E³,ÌdÖð"_ºxú—$»xJ¢ NCM¦)•:ç*G“B)-ýº)ÃE`½ ML¸ëº®¯ÌF£èѨSéR¿|¥Íår¤R©’Ãßô¶qíCogÑîbT®&ðf¬º®K:ögɆ[ðDÑ uÉår^¥ùóÑ4Í»v…üO¦irØ–-,*xÈ8šæïW89Ï ’H¬æfæÂuyüãç™ýû9á?à6ÇÁq‰oìîæµK.á¸o|ƒɤç-Sè;½ÒÐÀ¡‡Ê÷Þýnfœy&Ùl–¿ã¼¼oߤ?gõ‚r¢Êf³Sjfž¦ tÓ4ϧôšê;—ƒÖVèî>Â:¨D3—›ë;XE"ž}/™4ÑuÓ¼×Üì]ÃL&æ;‹ézñxšV 5¦¼`÷ï?Ë.;]×}#ɹç~‰Å‹çàºðë_ßJ:æôÓ?ÊÒ¥ÓJdÓ»oE£†*#˜§á'?y’L&Ã)§œPb$immEÓ4¾óhl<’³ÏnĶáÁ_¤¡áY/^ÉÂ…»yúé£8ê¨}œþnžzêlb1øéOïâ–[¦±zõ|‰„ÿ.ºñÆ?sÔQûxúé£X¾|;vÂÊ•Ÿâ¤“v±ÿ+lÝ:›Å‹OäÌ3àüó?Ã-·¼ÄÅïá¨*ûl3¸Œ×àŸgÜË\ÀY­€v´fkËrwÆ?^»¦Z”rÝ®t/^+õÞ H=zÓОY<†jO#ß8üœG‰ƒ‰oÉE¡ívÈE¼6ئ8)B×ÀÕ¼¶»-Z´™è?DÜOC6å•K•ž·jÛ}Z)zºÄð Uˆx`c·pq,xÓsoò–% ûe( µ­Êˆ.@œ¢G*ÓÄ“ghQùhT^Ôda[(Z±TÇDýVõÍP´h)cJº°\œ rM+”cÊRzõ9eØGó fÑ ‹¼ṳ̂î‡C±s Þ5WaØËõ¶j[1À¸â{÷Áì%ðêŒWýåÁö+—Ë‘L&CæVjfPéï璘¯ÆÆÆ’å===ôôôÐØØ8`ÝP耻9öV12ƒŠeY¾GJss3‰D‚d2I,#‘HøëUrÕ cdÇuI˜B&gù U§JÊ7µl¤nâõÀ`² £—ÏÝÀ¶>Ç1_º¾ªíc±®ëú3A%v¦ xL„|lîŽWô#N~õÕí;Þh€òßpñô™Â·§çÈÏ8@nútR…åúÓŸØuè¡DuÝ*ò«­[YÒЀîºì<î8îÞÍúïÐu¶lÙÂìÙ³ysW›V®ä/¿ü%;O<‘ßö÷³ø™gèÙ¹“³vïæå7¼…wÜÁ·®ºŠž™3ùÂ÷¾ÇQó7,ëï§3“aÛœ{ÙelZ°€†mÛ˜{ôÑ,س‡d.Çœ÷¼‡£ž~š¯þÏÿpßÍ7óÎ /dÆ™g²}Û6V,ZÄ׿÷=>Í5ì_¼˜›î¿Ÿ3wÇÓOÅÛŽ{‚Ë~þ <òïûÀ˜³|9ö÷ó¯?ÌËûöñúg>Ãþã燅㘎Ãã»v±ó¸ã¸è¢‹¸sËš¿òNûË_xê–[¸ñÏæúë¯çÝï~7OÜ|3wüøÇd2rÙ,sçÒ:ow?ôŸûÜçx Ï8”mnö Ùjæ«ã‹ÅX¬ihŸú©Àlÿ¿½ï>ÌiÓàÜsÐ ì¾þ:»Ï?Ÿ%·ÞÊ— ÷5‘HÐuà tŒ!¯Vï¾-À5wÞÉ[n¹…æÂ¥_S“¶£g¸«IÌÊãk8Ò(Ï”¥&C×J—zÎUÁ.˜rÔ1MÏ3=(-¦&²,/:ŸãPð€ñ¶QŽãk4Í “§ž:›}ûö1{ölÒi¯,ÛÖ±¬¢—eë^„®_Ds³mÏqŠÎhà•çºQÚÚ¼òUÔ<•JÉ4M"‘â9årÞï3ÎXÅÝw?Ä~t2¦ wß­ŒjóY¸p>Ù¬WF,æ9-[V<‡LæþòøÂ@9•$íí™ lÞ ·Ýæ-7 OD—.õ"¦ÓÞµüíoM\×[üä'o¢µu<‚(‡ƒ‰h;§áÉÈŒ§åúcÇ?Üû4žÖXT„øèÉí5#†,س‡g=”UÓ§ãœ{.]@÷¿H/Þx·{ñb4`×ûÞÇÿ+,Û¶lîmý,~tOþ÷»øàÂ…¬üô§Ø\¸G~? ¼èzó›Ù¼kš3‡Èöílž;—Ÿû{€ß.[†û•¯°xçLÐìýÒ—8úÕWùí™grüìÙÜ]¸öW8ÀÎE‹X¼x1n,F¤p>ši¢™&••©™ùÊø’ yäN?ýtÞð–7ðÊâW¸û–»™yÜLt]gã¯7òÁ~çnzŽÃÞ~˜o`H6'y®ï9ßú8‹^XÄÿCÞyü;Ù:^èÀø¡Á­ß¸•矞L´°±j”UOHÆ“ÌíË–-[xuË«,ú,9ÀÌ_ÌdŸ¾ÍÏoæÈÞ#ùë'þÊE»/böK³™+̶{Ðà•¯¼Â}óîÃ0 Þ4ýMœ®ÎÊO¬ôšmÀt¼^o È»wû³*t»ÐÒ~—boO5ž)˜›œ ÀJc%½™^¶Þ¼•Ón=‹.¿?þŠ"à‘3WŸ 6,²yÛü¶°~?œÞ{:ôÂÂØBx¨°NzáƒÑò®ï¾‹½îeþUóýt! á8Ò<’F‹qbŽ™†¹Ì-ºÕªªS¢üÂ(ÿ­ÒÿP?ÖÏ-Îßy>¬ÀïÝ>Òúo¹ç-¼òÉW&Rl&…ÁdF/Ÿ[¶lá»vñÊ£G°´yéÇWN˲H¥RôööÖú’uL?›6mbÏž=µ®Ê¸0Þò¹gÏ:::°O>KÓ8aè‹6ÓsÜq“šüº¹¹™ööö’*á³2~¾—b*•¶m? 'x^mßß¿Ÿ‹Ö®-QZ©óÆÞ-ÏwP-^ÜûÓBËǶPœ©?Ò¬:ðÁçžãçÛæ2ÿϧV½ßH£ 'd–3ØÝo£f¼æ2I± ÍáçƒM}è8üpÚ(ŽÕsÀoûûùÄÉ'Ý´i„5'Ñ·} û5ÞµþNþá¹(Æà!Êx5Ü„æá$^­–¥ž¹ ¢±<Êl¯Î3è)¤ÊQÇ1Ç¢l:†V¶MùuW)*ÔöêüÖ?öœ>}Jø§LTßöá_ìdÙ)Gòì½Ï+@“Ù¦†…Jí"– §×júbŒÒw’üâÿ;¿Dß­ŒÎåw ØfÆ)5ø˜ò+á΀äb¯M –«R«TÚ¯y&ä–xm¤‹×n¶30 s°¬›åÕÍÅ{W\ÔßÏK[·ò“ãÅ] ѷݲe ‡þ¥,„P½zõ½GbìWçüœ—Xn >x•:¬å׬üAu( RðÁWJ07°jÀUãJÂLͺ0ËŽ¡f{èxBŒè¢fz(o$¥Ç!P–SV¦²ØªpzªáUFu\Õˆª}µÀ1¡Ø‰¸›¹®Ë+¯¼ÂôùÓ™ L”ÞvÅŠ0g;7A~z¾â¶ŽãÇŨ"Œ]]]lÙ²eÜËtƒJSS N°Ü¢ÙÐÐP± ²k×.îèêb÷«-l¼a?T?ðÃWåâqÞý§?q’Za¥>üPâ’-„Q3^Õ ZMÓüðW®ë‰Dü}Tˆ,×uý0Tɤ§‚P!¥,Ë¢»»›—ö¾Äg¿ýYt]Çu]–»Ì7ÄœÌÉœM!Ë5 ~f2““ gq'ÀeõF¤ßég•^áEWi \6˜f(ظÞww,¸ƒè¿FyðÃrRì¤Êû¦ÊÊ©ÔQ0Ù¾Àö¿iž× ¨²Ž•:Tü§ç¹óØÒ²…³þù,]\êŽø›u¿aãÛ6ò9>G½3˜lÂèåsË–-ìܹ“7¼x8,úøÊ©Œ”‚0úúúèèè˜2•ñ–OePÙ´x1®¦ñ·Oƒù™ÅÄ;ÔͤÇã$‰×mÃ0ˆD"D£Q?ä¤ Ù¨Ú^¥ŒRïÃ0JÞ–eqѲe¡š4 Œ„=}‹éÛŸâõ¦wÖúPî aÎS)„£ TfW2ôDE›6ñâÿþ/ÇL‘*Ñ·Ýù–}¼ý,Ž[}ÜIe @ê9WÕ­ÔÍR‰¶•aNÍÔF †ÀISŒºRI_£ôÁ0òÁ ·E]ŽØ–²ßnàøÊ œôê–í4t(2 Ï#hàPrã”NVuˆ2Ð¥Ž©Ž¡¢Ê¨s(Ï£ôH*QP老Áz©ÉÊ??Þñ>“¯¬è¨'&ªoûä¶ôþ3Ãø‡ æ õà•WJ¥/­åM2’öZÉg¥T(Ãí£ôÆÕœ›šÔÅ9€=}}äÛÛéùèGGz9CÉDômßôÜ›ØzüV–±¬Ö§7µLhÌA~'ªØ¾¼ÌJ3*¹å·O SFÐSîí2X™•Î!:pû'ßõ$¹rÌ9bS‰èÛvttÐØØˆ=g‹Ž€Y ^âð]»l«&¨ Âx±iÓ¦©aPŒ¾¾¾˪q›?>ç\z)OÛpê{9¦\›N{Yur9v_q[/¹ÇqˆF£zÒIœtúéÞ¶®ëe« TTË‚B§­­ Ã00M“ÖÖV¢Ñ(ñxœî2?ýd2éçïP³js¹±XÌ÷h *‹”w‹ã8%³iǛɊAxgÇ<ù'‰}jb“‰põ'þd4øú)_ǹޡóâÒLˆk×®eݺu_‡3Zù<óÌ3qçÏgå¾ßáκsá8Ž4œÂ¸ÑØØÈÚµkéêš:Iuc4ò9wî\Ö®]KoLð×»ÀùJ<+Ç‚ò0)7r¨WªTÛ(OMÅH˜ζ‹YÑå1Ÿr¹bÖöÄ£Y*Î覘·a´ÃÓAuJÌ 7ÈP~•¤ ,Á7)ª÷œ©uwU΢¡”¹ê=?ܵ´ð¢—tΟÏm7ß -SÁGepÆÒ·me6&ÐôD“L *êÎHÞn*¤×H0v.ÞT8¯‘P)úTcc#W]~9Κ5°~ý¯X¸mßö­²ã ;j]}!ìL@Tq¿o;Åò–3½m0ËÅóàÛ ·qÜìÙ¶UQ Â8Æê“U«V kô ¡1¨Tš™ÐÓÓã[F‡£qœ6ûþ ¥ƒÅDÂ@ZÄb<àºD–.%‹UVÞ–+q4 Z[½Àƹ†eyË ƒ¶B¶ÇJŠŸTa k†o8 v¸Ës°¨ÄíS奡¾O•$Rmmm~˜·ƒ‘±ÊçÏöÏßÍ:ÙëTyVa²«|Æ€ì_aÆŒGq]·ª}†#Ncš¦?@Ó4?l—ã8tvvú9ÌDö‹8p€3fð¹Ï}®ÖUÆ±Èæ¢ß¿Æî…» Sšs°É‚whðf˜ðÇXQKïº~ß´„ [Å•IxM‡«ZáÆî¢µ ›õ&^(ð—m¥F—dÒ+Ûq¼~²Z§ÞàÖ9ö"† eV £Ê}+­×ËÊЪ(g¬Tcpª6—“ LÁVÇ"Ÿ³òpé·º¹îþ›8‹³j}*ž¼…yZ–ôtFÆhåóÖÅ·òý/~Bëf•ýWa'á``¬ãN…ó$<ßp'œD¦ëºŒ…º 4•¦¦&6lØP²¬¯¯¯êÄFZÿ¾{k=Ô%ºʨáºd2™êãÙ†·¿DjZÑ“%›˜ÑQ…ú2 ïcš¥ÍtÚ+O•S(?úy\H&½cÆÉdéqçäc•7ïøž5€wê˜P€×— ʯ“mÐPy÷œjÞóK},òùŠ ZþÀÛ8ŽãçadŒµýäH,ÛÈ¥þ[ßüæ˜êâ8š¦‘H$ˆÇãd2¢€¦i¾aFžÇä`Àp]¾¿¿×ž„q÷§£•ÍCwíbæ {yëü·z , ¾…ß:°2 ŽQÌ´ì˜àšE÷ˆÞ”hçÊÎLÁ¥ød¬èŠÐd 1WU,•[Î¥˜[î9î/ô1oˆÀ_» ÉK¯êº^¿TõMƒý%Õgôy! ŒV>·54ðêOàW½³yãGª ½äºžÛ=×-3Á“ Ó,ÊHù˜KɘBM tÝ¢  Ê"D¡1a(F+ŸÏÌ©.ŸîxáK)æÎ‹•­Sáaª0æqgÜS°³i/sçΰβ,' uAh *---~Ìû––ºººèééáüóϯjÿ¾m0}ñX|ë­pÏ=·I&“~H­)Ç Ã딪Ž. ôdQ´·;ȹ\e…ˆmkr°hšæíS)C,Vjì¨Ô!.7¨”Û) |MÓ«ƒa”†„pœá˰íb=*͈´í¢ñg°$RƒuüË몎Sé<4Í;V¥ë«ïP<†¦•^³òAJ¥ã¯ÅA®Ø‹|>Û gògN~ßû*®·m˲hk›ß[A8‹|ÚÀâ—á·›gûÞ›#%›Í⺮ÊKycª¼bÁ crÞ‘rÌæÍbP™"ŒV6wì8–¯`od¯·@MP &x…bBZ•€Cit*&›- £¶©ä RþèeMÐMï8F=CN¶P‘L»Ž¬Û‚é@V÷4J.€ ŸŽÃ[LX€ßçõI&‹JfÓ,íOf³Åþ^¹÷¶êç¼Ï(¡ØT}=Ã\™<\´rOœj¦•OZ츎3tÝÊQý×råz¡ú¯å“§*Ûq8ó·¿ò!¿F+Ÿ½sç2ïHè}¶—•ÊsK6r¹ÞâñÊïôà2Ë*}¶²ÙÒ{4¶¨í“Éⱉâ±mÛ‹jZÑh“J•ÊIs³'{Ù¬·.8¶M&KÃF£Å1£ëzÑ‚Ç|®[ôjSõ žg2Y‡V’oÛø®P×QµŽ3xYiœ©Æ¯j<¯&I¯¥’Yþ»Üx¥Ê­$3*ìb¥²“ɆfuËÇö•Þuj]€cwLýVcÕ M$Á»‘Åkò¢…ßK˶S¹¾x}nQ õÎxȦDO„M§>¼Ý_nY–Ÿ£ZÂi õ@h *à壸òÊ+Y±b›6mbíڵ̙3|R'à%8css>ôžA–eN8UÇ­Z4m`ìjÅP!½r9¯ÓÕÞ>°£6ÔÀI‘Æ©ß4¡³ÓëXÇbB¦9¼g8e›axõomõŽS~¾Êƒ'¸}°ÞAƒŒò *7Úd³ÞÇ0Š¢rÃP6ëí¯ÔåƒÕ±x3¨¨ò2™dÇ!úè£l™âƒN½|.ß :ÛÙ½paÅõ*‘ £g´ò 0ã'ðÆW;ÙZ!†m5èºN:&—ËÑÙ9zbÔÄ y'NF#›;vË;^?txÍK¹ae¢vý¢ÆÀe <…ʦ¾8ß„WSž×Œg|ñ˜S°,_Ë‚›ð´QZ¡ì»48Õ€spüRøqw1i‰ëÂÏ,˜‹×¯ŒÅ@3ŠI ŽÌü?\‡YÀínxûÿ1 ÛlØÌÆ ]PíÂ…Í0G‡}.ìwáÛmÞþpvZp˜Gðå@_÷Î,ü:»ã€—€³SpµQÌ¿> /ذ˜®Ã^ ¾òÖåðÖý² °¾­ ~mxë à6ìvàż%êõ³ïÖ¼óŠÚ`¶ÂŽq½eÿ¬Á£ø,]‡=œ Ã|`‰×îOè·as’“§¿…Éç]F#Ÿ>|ûå×yàÒç8òé^¸þ Þ ×øîvïÕõc"M+{”C†óôŊ㲂1§h/3 æMT2 oµã€˜sÆ—‡±æTÜXG‹‚UŒìg¤R8«þ gó Œ³ôö)¤$Õ]ûÌËpß³Òº€[´Ù¶Kãð›Gà7Ïa¸×[‹yC«C/€•ŸÂº&±ímØq [3½Óß¹ûòÜ]‡’øÊ,r‡Ò·Øÿ³ýf÷óßÅ=ão½×æ ׌ã·b~õ¸^‚ó³Gp¯ø V¯·>ëúWq{ŽÄ»î‘Øoב]|-ÑO’»v'¡Ïí%zÆìÛÀáÅ9•ÎúxáX°íé1×û…Eè:XWÝ> ç®Ff3æ‰;ÉÞ­ù·(mÇÐÏøæüÇÁ4I>ùI bçŸO÷ܵIa4òéëy”ÑN4&Ĉ]éx¯ËtáwŠB>tÇ!SÐ×(gÑžÓ§Ò€¤ñ ,Á0a&¥óÇ©8ù×u]ÿS®ÏR!{µ ç¥òº®[²^éÆÔd'Çqücg³YR©”ŸQ-W!}Õd`Ý*èM ÃÀu]¢Ñ¨Ú7N“ÉdJʈÅbÄãqR©Éd’X,†ëºèºî—¬³òXˆÇãþ$Ìl6K4EÓ4Òé´ï¯Ž£öI&“þqR©š¦ùåD"2™ ¹\Ó4ýÉaàolÛÆ0 ÿ;›Í’ÉdüPýÊ_K4åýïÿ¨Ÿ­za,ãNðºkoxüqŽþD©:Ú²,4M·Ô‚0ÑLËçóùZW"HOO===466Vå6¶fÍæ¯_ÏC­pþÝ—‘ø÷VTD¨B¡Nn¤¼SÂZ¿‘ f/•2&‚ÉH°šNœ­ThìoþÕ¯XÚÚê'"›ÊŒD>;::èèèàWXËGι“–_,¨hÌTA˜Ö¬YÃú)ž¸S1ùT×%oÝλþòܾò…jt]—l6ë˰ʙ"Õ Úˆ`‚Ê©ÊHû¶_üèYóЩôþkž³>ñ‰ZWô¨ììA”ÑCeouá\Ø­{)5×ÂÓ<½Ó…–œÙx^5ñB9±Â¶Va?-°¿:¾Ii¶y»°_/ì™ÅÀŒÑ1<Ù ¶g ‰ÊÒ Ÿö4üÎò 1Ár•–L EН\áÐÓÈ)ìÅø0¿IÂé&ìtá%NO=ÔùýÑÏ%áp´b\™la»VÎùÝï8¤Ö¶<œí®¸‚·|øÃœöž÷x áàïûÛi<õT 47«ã8ÌÎå¸ðÜsÙ»d ;çÎ% ¸ñ8Çô÷óO«Vqä‘Gzé¹C++jyÝ •³ÒµYº´ôá,‘(Ë#ÝØÊZM VJ‚„UîaõB,/?h!V/Ìr/"¡Äu=CØ`¡Ü•EY?˜¿xò…xõä“‹ÀTˆBuÝÔKXÝuÞÁ0…åQOT˜BM£««‹»÷mÊ *öô]¼í÷•T"‘HiniAG&¢oª_cáúÌ{CåxÅÉd’\.Gû`9=A˜¶54°ã÷0¯ïÕŠëKf‡‚0é8@êc:wÌœ{†ß>›Í’N§‰F£$‰ðz| B³¬¿Ÿ# ³P…aM7bªRÕ*»l+ð—¿ÌgÑ«yf±ÐOãÅšÊH¢¢çr'ËCå(ʪK\­ñÁ0Š“ìG37i4s!F“òp¤]Mùq¢Q/JÚD+T±‘`#Ø ¿£D¹ ƒã8hšFkk+©TŠ—]Fg&ñÑ(©ÂD†\Á³!–x`ÿ`ùòAËþäw¾Sº þìA¶× €öGÅ™;ωó„ï~—{9„Ó§cPp,4MßÉÐ-”­›&^S¨DZý· [媜KĤ»{è‹U¥V …r‹ bC‡0TÆŒ¡Ž‹ã–¿ƒÂR^FÙ³pr¥cU7UÞ`u+î¾Ã‡Ž„á9§ØÞÐP²,Ê$=¡®˜2•» ºN×u2™LŘ’‚ L½sçÒtÌ=z^ü ×uq‡ÖÖVº‡ëÄ ‚0q€ä¿qéÖªÆ«Ž®ã8ÞK&cwì˜xÍ  #fúKGóÁÝWqØ[þÝÏe®Œ'j¨©RJBi8©jÑ¢‡ˆF‡µF¹®ëç¾Pù3·ÞZVÔäæ³ÓN;Í·owÖ¡‡úÆ“^ú±\á£"4B1’¤…7ó_E’TÑ&UTJýQEÉÓ)uðTŽAN™R ¬wÇDŠôþÇbþþÁ}µ²2UÊ0Òè—ÁWe!=†Zgþq‚‘+…ú£ß†CÝÃÛ;®d¹eYbPêŠ)aP±³fÀ‘ƒ4ž–eùÉ«A˜\öýï6Þ²{SÉ2Û¶ý¤n‚ Ô};8†¸®‹eY~BG§æ@„ñçØ;xù¨£>"µ “͹oÚÌü?¶3¯º+ñ&/FåIÌ2ŸO&‘Aré~²uÛ¶K"—„ÕÛ:˜nKõÓUl¯Ìà0TÄK+PŽ[(C/”ñÄ¥˜ÖËÂ3Œ´Q4Ö¨Ô]i¼tbÊ0¢>Ág6ÅÔ_P4À멎G¡<oš¦Q¶F©H•cQjRå(ƒŽKé9ë¡Ö«ë ŒIÁ´kÁ²ž8ýtÎÙ¶mT÷û`bÎ ˜¿—Gvï¦7°\&ë õÆ”0¨Ì~ánÞôÜs–G"LA¨!Û·îâχ•vÙ Ã •JI¸/A¨5»!ñ6ÈZÖÊ\.‡ã8´µµI›*ÌËGÅõ'ŸÌk]A0Î/yqÁæQL\.©!œ¸®ëçÒÏëd²=OjÅ`½õ¡l¼fÙvf…²´À³lŸàïñ4SÕ•3XÊ0åõ4’(IÏdPê)“-¬¯T÷ ±)x h/”ñëÇcc I½0xîZHL{‘¯z4‡–»®+…„ºcz­+0ìuá‘×çóì’%%Ë]×%JÂkA¨![{Žàè“æ—,K§Óþl!Ajƒ ô? ÝüO€A;±Ùl]×I¥RbL„I`Û¶ml=»ÖÕ¡‡<ÿ<;gÎôsË0SÂKk«rZ…2 C”¶uH0ÄY9Ê#¦e$ þWeµÖE¿c nªä—¯òÖ¨²Ú·Ù{ªHJyãûfGÛ|`Å ÿº:Žƒëºc(Y&Ÿ)ᡲãðV~$—ËÉ xA¨!Û ÿ:‡œ\š”>Šl B±c§Ãî{ ߥòIx/A˜<=ôP®¸âŠZWC„ lž1ƒ×Ï=My²uA&Û¶K&É$[AgÏûõ?•,sç ñ¦SÂCåiàÈCf”,Sn¢´„ÚÑ;w.oš³›Ý³fùËT"@™$µgßmÛØ™?¤¢ç‰eY,]º¶T&“£Ž:JŒ˜‚Rž\´ˆÞ¹sk] A†¡µµUú¯‚Bþ÷Þn^}µ4Çn.—ýPwL •å/¾†6}W‰ær9LÓ”FTjÈ!ûaþ!sJC®ëÊ !A.Ð÷4òktýóÖkš&9SA!À3Ï<ÃE]4aå«'*ž¼mÛ†ã8%c]˲üå®ëú!\×Åu]²Ù,±XŒd2I4%›Í’J¥H&“¤R)?’ƒã8†a~ˆO×uÑu½d‚¢ÚNÓ4t]'Fq§d½ª¿eY˜¦é×Û*äjK&“Äb1,Ë"’ËåˆF£$“IÚÚÚÈf³hšæ×§¼ÎàMœ î ^xÒöövÇñ·WߪœÖÖVR©étÚ¯›ª»®ëär9R©ñxœL&C2™ôë¬Æ2º®£iÙl–L&C</)[G2™ôûOêzjšF.—󯣺6ÊX­ ^ûh4J:öËŽÅbþ:ap,Ë¢³³S´‚6¶Â ÏÏaÅIE=­jD^…zcJTfŸq÷½é×|Åø?þ2]×evŸ „€ß¾²ŸO~çr9À#Bm±ãÝÏ÷¿Â¿T0š¤ÓiÚÚÚj]MAÆ¥d N4R Û RO)ò Ãð••ÙlÓ4±mÛW ·‰Åb%ŠOõ_)M•ŠŠYÓ4}¥¥Ú6N‹ÅJ½ª¾JYŸ¯u%ÆÂÇ/¿œŽ]ßcᯮ¦ãåk¯ì ÂD²nÝ:ZZZdàYFGG÷lÜÇϾ¾‚ïlxd€2F&ƒ5kÖ°~ýúZW#t¬Y³†ùë×3ï¡ý±HÉ S)w‚3^a¼éèè ££ƒµk×Öº*¡c4ï-5[])ïãñ8‰D‚t:íZ5Móg+…eùÌõ £Ü(¢ 0P4Æ(ŨmÛ˜¦é×Cµ÷Áí‚unÊ¿•’?ØWÄû|t¸®ëÀ†Cú¶•É{K)LÓô"étšL&ã{(…90æöVF'º”e¡6Hß¶2꺨vHžQa²‘¾íà(ùüæw¶pë.ÿôé'ýI-bP&ƒ‰èÛÖ½‡Ê+‹óêæÙ¯¿;¯ É(5çôûžãŒÿiþ3àŲU3¸A¨1/À·þý\UªœÌårg¦ ‚P{Òé´¯˜M$~ˆÛ¶Ñ4ÍŸ…®Œ¤Cyk«ÁkùŒj%û껚A®:Nù÷hö©4s[)ÆÄ˜2z‚3ð…‰!›Íb­­­%ž†a”x¨çX×õq «9Y²!Jj!ì(]„¬„ðñøŸf1ó ;|ù´mÛ7Ô B½Q÷€‹?ÝÍÌççÅlÒÙ„Úã>ÙÀoúá $áÁÞ‹/Í?¦”²bL„p¡œJ^ƒFÃ0DQ.5Dåä°m›X,æOR £Á»¢ð„ñGŒ)‚^vÌ?—Ý%“d2¼P¯L¯uÆÊ[þð2ÿuùáþåR-Bí™±ÿU^Ÿö:àɦeYµ®’ ö>¿‡K][2“\TA–e‘N§ýA±XÌÏ7 òŠÌ BmP¹NT»L&Së* ÂAeYd³ÙZWC„Axôöxá2£Ñ¨¸\ BHpÇï׊1EÂ…ã8´¶¶ÒÞÞ.¡…!DÄãqÇ©u5A¨@îYØó_ÓX¸p!àMJü)B=:ƒJOOôôôTµýÌÇç3 ×÷J‘N­ L#•OWwؿ䚦‰¢V&˜‘Êç_7÷sô²c¯C+á¾ab©l‚çÒÙÙYëª Â”g4ò麮xs Â$0RùL¥R­D&Ñ´v÷^Y»eË–aY™LFô·B]*ƒÊ† X¹r%7Þx#+W®dÆ Ãî³ã¸¹üw¤ÓiFA˜@F#Ÿûf?ÀœÆ½"Ÿ‚0ÁŒF>ŸÛÖÀÛ>±˲ˆÅb¢„ `T}Û;$ç˜ L£‘Ïgžy†l6+žc‚0ÁŒF>e¼)Ïhd ë°œáä¸ôôÓ%ב0%•AeݺuÜpà ¬_¿žþð‡\}õÕÃZ¦Ê=/F#ŸSzèWËTy¦§Ò=F#›Óþ<÷íaé´?“.ä Óø3ìmI=<ƒa—÷-[¶ðòË/k™¡IJßÑÑACC---455ÑÔÔDGG«V­t¿¾¾>¾ÿýïsóÍ7óä“OÖú4°aÃk]Ayâ‰'èêêªu5†$Ì×ð‰'žà±Çã´ÓN«uU&”ÑÈçË/¿Ìþðüq¾þõ¯ó /Ôú4æg —ËÑÔÔÄ›ßüæZW¥"a~¼úê«<÷ÜsãÞh†‘ÑÈgoo/ þ˜ï|çX¾öµ¯…®ý ó³¥÷Çèyùå—éììdß¾}µ®Ê„2Ú¾í /¼ÀM7ÝÊ{7Âü Ž”°Ë{µTsO¤o;¸|¾úê«lÙ²…?üá¡ì׎„ƒé™®†»'ªo[ïÏ^5Œ¶o{ÓM7qì±Çrì±ÇÖúFM=ô«eª¼gª¹'Ò·ºoûìô>Ü»Þó$[¶x}Ý0½ËÂÞ–ÔÃ{!Ìò¾yófþøÇ?²téÒq-74•®®®¿¡¡aX+á!‡ÂgœÁã?^ëS¨ÈòåËCmI|ýõ×™3gN¨ëæk¸qãF¶mÛÆ´iÓj]• e4ò¹k×.=ôPŽ?þøÐÞ¿0?[sæÌᥗ^bûöíµ®JEÂüþرcO>ù$¨uU&œÑÈç!‡´iÓ˜?~(ï_˜Ÿ-…¼?FÏ–-[xöÙg9å”Sj]• e´}Û×_{ï½7”÷n$„ù)a—÷j©æžHßvpùœ6m[¶lá¾ûî㤓Nªõ)Œ‰ƒé™®†»'ªoûúë¯×ºªÎhû¶÷Þ{/‹-bÑ¢Eµ>…QS}àj™*ï™jî‰ôm‡ñîØ÷2söþ=³gŸÊç"ìmI=¼Âx_úÓŸX²dɸ–ƒJ__߀eÕX·î»ï¾ZW]¦<£‘Ï}ìc|ìc«uÕaÊ3ùüùÏ^ëj ”Gú¶‚^F#ŸçœsçœsN­«.SéÛ B8mßö÷¿ÿ}­«.ãNhr¨444 Xæv‚p0!ò)áEäS‰Ȧ „‘OA/"Ÿ‚ND6¡Hh *MMM±¯¯/´1Øá`BäS‹ȧ „‘MA/"Ÿ‚^D>!œˆl B‘ÐTZZZèëëóc®uuuÑÓÓÃùçŸ_ëª ÂAȧ „‘OA'"›‚^D>!¼ˆ| B8Ù„"¡É¡°víZ®¼òJV¬XÁ¦M›X»v-sæÌ©uµA@äSŒȧ „‘MA/"Ÿ‚^D>!œˆl ‚Ç´|>Ÿ¯u%‚ôôôÐÓÓCcc£¸ BÈù„ð"ò)áDdS‹ȧ „‘OA'"›‚BƒŠ ‚ ‚ ‚ ‚ ‚ BØMAAAAAA„°"AAAAAA„aƒŠ ‚ ‚ ‚ ‚ ‚ Â0ÌøêW¿úÕZW¢^ééé¡««ËOÆ4Øz€†††¯Oººº˜5k‡vX¨ê×ßßmÛô÷÷sÜqǨ“yý„úc,òYkÙ¬¦µ–Ï0ÔO¨_†’Ï0=[£‘ÏZËfØ®¡0u˜(¹­Õó8ò=Ùç2Qí´¼#ꋉ“†I>Ç*“y.9Æù¬/&rLZ‹ga"Æ®aj;ÇZW‘Ï„ášô÷÷óÒK/…¶íûظ««‹gŸ}6ôzÛI×­å…QqÝu×å›››ó«W¯ÎŸsÎ9ùøÃù¾¾>ý­·Þê¯onnÎßzë­%û·~닉“ÖâY˜ˆ±k˜ÚÎz¼'a',×äºë®Ë_wÝu#®ßdÔ?ìcã«®º*Î9ç„^o[ ÝšTFÁóÏ?Ÿ_¾|y~Ó¦Mþ²sÎ9'ŸÍfýÿÁ¹iÓ¦üòåËóÏ?ÿ|ÕëÇõ`¬0Ô/xÍúúúòçœsNþî»ï®ª“yý„úb¬òYkÙ¬¦µ–Ï0ÔO¨O†“Ï0=[£‘ÏZËfØ®¡05˜H¹­Õó8ò=Ùç2Qí´¼#ꇉ“†I>Ç*“y.9Æù¬&zLZ‹ga"Æ®aj;ëñž„Z_“[o½5ÅWä—/_^Ñ Rë{ö±±2@*O¥ú†E¾k¡[“*£ §§‡––šššüeçw}}}tttÐÐÐ@KK MMM455ÑÑÑQÕúñdݺu455±bÅ Yê×ÑÑA__—^z)sæÌÁ²,Î;ï¼aë0™×O¨?Æ"Ÿµ–ÍáêWÍúñ`(ù Cý„úe(ù Ó³5ù¬µlVsD>…Ñ0Qr[«çq"ä{²Ïe¢ÚiyGÔ9& “|ŽUþ&ó\&rŒ+òY_L䘴ÏÂDŒ]ÃÔvÖã= ;a¸&+V¬`ÕªU%rXmý&£þa÷ôô°jÕ*æÌ™à‡#Ýš‡TFAKK ëׯ÷ÿ÷÷÷sÏ=÷øWWW×€¸w ôôôTµ~¼èêêâž{î!‹ X^ëúõôô°bÅ 6lØÀš5k¸òÊ+KÚ¡ê0Y×O¨OÆ"Ÿµ–ÍáêWÍúñ`(ù Cý„úe(ù ˳5Zù¬µlVsD>…Ñ0Qr[‹çq¢ä{²Ïe¢ÚiyGÔ9& “|ŽUþ&ó\&rŒ+òY_Lä˜t²Ÿ…‰»†©ík]E>†kÒÔÔDKKKża¸§aŸwÞy¬]»–þþ~:::|Ã…2@„A¾k©[ƒÊ¹çž{X¹r%---¬Zµ (Zë‚oÒpëǃþþ~®¼òJn¸áßšXíñ'£~===¾ÕòÒK/¥±±‘5kÖøîPu˜Œú Sƒ‘Êg­e³š:ÔZ>ÃP?ajP.Ÿax¶Æ"Ÿµ–Íjê ò)Œ•ñ”ÛÉ~'R¾'û\&ª–wDý2ÞcÒ0ÉçXåo2Ïe"Ǹ"ŸõËxI'óY˜È±k˜ÚαÖUäs a¿&a»§a+zzz¸ñƹçž{|cÊpuûØ}<ê(•QÒßßÏš5kX·n×\s ×\s¿®’õ3hánýxÍfijjò]Åúúúèêꢫ«+õïA½á†hiiaíÚµ¬ZµŠ 6 [‡ÉªŸP¿ŒV>k-›ÕÔ¡Öò–ú õË`ò†gk,òYkÙ Ë5¦&!·“ýßÒ5Üúñ¢¿¿Ÿo¼‘o¼‘žžî¾ûnî¾ûîPÔ¯¥¥e€1ø¨:LÖõê—ÑÊg­es¸úU³~<J>ÃP?¡¾L>ÃòlV>k-›aº†ÂÔc"ä¶ÏãDÉ÷dŸËDµÓòލ?&jL&ù«üMæ¹LäWä³þ˜¨1éd? 5v SÛ9ÖºŠ|$ì×$,÷4Ìcã 6pã7úÿçÌ™SrÜ0ÈwMukU¥®J¸õÖ[óçœsNþ(ù<ÿüóþ6ÍÍÍùx ŸÏçó›6mÊ777çûúúª^?Þ¬^½Ú?^ê×××—onnÎoÚ´ÉÿÎ9çäo½õÖªê0Ù×O¨Æ*Ÿµ–ÍjêPkù¬uý„úe8ù Û³5Rù¬µl†ñ õÏDÊm-ŸÇñ–ïÉ<—‰l§åQ?Lô˜4Lò9Vù›¬s™è1®Ègý0ÑcÒZ= ã=v SÛY¯÷$̄嚬^½:Ýu׸~]ÿ°UýT™a×ÛN¶nM *£àºë®Ë/_¾|À'( ·Þzk¾¹¹9¿zõê|sssÉWÍúñ¦üÁ Cýn½õÖüòåËó«W¯ÎŸsÎ9ù«®ºªê:LöõꇱÊg­e³š:ÔZ>ÃP?¡>N>ÃölT>k-›a¼†Bý3‘r[Ëçq¼å{²Ïe¢ÚiyGÔ=& “|ŽUþ&ó\&rŒ+òY?Lô˜´VÏÂx]ÃÔvÖë= 3a¹&ƒTj}Oëal¬dE#ÌzÛÉÖ­MËçóùqõ·|zzzèé顱±±¢ËÐpë†ú©c444ÐÔÔ4¢:Ôúú õMØŸ­°Ëgê'LMêáÙªõûc,mgX®¡0µË3¶çq,uìs™¨v:l÷DSåY«üMæ¹Lä7L÷D;SåY¨§÷ŒÈçäökö{†úuuuù¡°Â.ß“y Å "‚ ‚ ‚ ‚ ‚ ‚0 ’”^AAAAAaÄ "‚ ‚ ‚ ‚ ‚ ‚0 bPAAAAAA1¨‚ ‚ ‚ ‚ ‚ ‚ ƒTAAAAAA†A *‚ ‚ ‚ ‚ ‚ ‚ à AAAAAA„aƒŠ ‚ ‚ ‚ ‚ ‚ Â0ˆAEAAAAAaÄ "‚ ‚ ‚ ‚ ‚ ‚0 bPAAAAAA1¨‚ ‚ ‚ ‚ ‚ ‚ ƒTAAAAAA†A *‚ ‚ ‚ ‚ ‚ ‚ à AAAAAA„aƒŠ ‚ ‚ ‚ ‚ ‚ Â0ˆAEAAAAAaÄ "‚ ‚ ‚ ‚ ‚ ‚0 bPAAAAAA1¨‚ ‚ ‚ ‚ ‚ ‚ ƒTAAAAAA†A *‚ ‚ ‚ ‚ ‚ ‚ à AAAAAA„aƒŠ ‚ ‚ ‚ ‚ ‚ Â0ˆAEAAAAAaÄ "‚ ‚ ‚ ‚ ‚ ‚0 bPAAAAAA1¨‚ ‚ ‚ ‚ ‚ ‚ ƒTAAAAAA†A *‚ ‚ ‚ ‚ ‚ ‚ à AAAAAA„aƒŠ ‚ ‚ ‚ ‚ ‚ Â0ˆAEAAAAAaÄ "‚ ‚ ‚ ‚ ‚ ‚0 bPAAAAAA†ƒÆ ’Íf±,«ÖÕ8¨q]˲°m{\Ês‡l6[ëÓÆ‘ÏúÅqœr-²9µùœZT+Ÿ¶mãºn­«+Œ‘Ûú¥R»ª–‹ìN D>kÏxŽKGÒïù ?"Ÿµe´²9Ö¶S'"S©$“A%—ËMIAŒD"ãf ˜HlÛféÒ¥¤ÓiZ[[‰Çãc.Óqr¹\­OM¦¢|Ö‹lŽ…d2Issó¹ÙœZˆ|N-ª‘OÇqêk4˜Šr S_vkWAdw*1峞ž»ñ—VÛïù¬D>kÇhes¬m§^¦¢ÇK6ƒe•×F/›•–M”|'/ƒ½Ô=Ó4ÍÿVØr‚×Dä3ü %ŸCɦZ_I>kÑvËOù¬F^«-o,²9Øù¶í þ7 C¡uÆXÚUµ>,²[ïýÞÑÊîHÚUuDvëƒZ÷{GºíPÔ{¿w¸qé`´­å²©–‰|†é÷V.c¼ú½ÕžãhuFci;e\>¤?;x9õÒŸ=¨ô¸ù)HwwwȧR©|>ŸÏ'‰ŸïííÍkš–okkË÷ööæc±XÈ···ûëÔ¾íííyMÓòÝÝÝù|>_RN*•pÓ4ýzŒdÛ¡ò±X,ßÛÛ›ïììÌkš–ooo÷שßÕ”cš¦žÃý¯¦¼jÎ/“ÉäMÓô¿£Ñè€:W:Çt:]²\Ý µo{{»ŒX,–7 Ãßn¨ý„Úù/ÙTeU’ϱÈf¥e%ŸÃÉËPïŸX,–F£ùL&“F£%eV’ÍjŽ'Ô–¡äs(ÙÌçóCÊg-ÚNUÖxËg5ò:\yã!›ƒßhÛÎ|>ŸïììÌ뺞ïííõÏG?ciWƒëÃ"»õÞï­ì¶··Ú®ªrEvë0ô{GºíPÔ{¿w¸qé`ç7”\%›ù¼Èg˜‘~oå2Ƴß[í9ŽVg4–¶SÆ¥áBú³ƒ—SOýÙƒI;% *‰D"‹ÅJ–éº^òÐ…@=„íííùL&“7 £dßX,æï´A©ü_.ˆÕn;@‰`;b#DÕ¯æ5åUs~êE¨Eõ¿üØåç˜N§óš¦ zoÕ1b±X^Ó´’†q¨ý„Úù/ÙTeU’ϱÈf¥e%ŸÃÉËPïŸD"áß;]ׇ•ÍjŽ'Ô–¡äs(ÙÌçóCÊg-ÚNUÖxËg5ò:\yÕœ_5²2žmgooo^×õ|gggɵÂÏXÚÕ|>|²[ïýÞÑÊ®ê#WjWƒÇÙ­/ÂÐïé¶CQïýÞáÆ¥ƒßPr=T¿Wä3ÜH¿·rãÙï­öG«3mÛ©Öɸ4«‘×ñ Y¯¶3Nc®ëúalÛ>h&ÖciW!œ²[ïýÞÑÈîwÞ9d» "»õˆô{+SË~ïpãÒÁÎo(¹¬ß+òn¤ß[™Zõ{G£3mÛ©qixþìàÔS¶šý¦ŠwJ&¥¯&6é`7EÓ4LÓ¤½½½Ö§1e0Ms@,¿j_,å÷©<†¢ad2t]'ÓÙÙYÕ~Bíù £‘ÇqÐu½D–MÓô÷­$›j[‘Ïð2œ|Õ¡J>ƒƒ¡zF++£m;]×õï•ã8är¹ƒ!|Œ¥]‘݉`4²»uëÖ!ÛUÙ­G¤ß.&j\:T¿Wä3¼H¿7<ŒV6GÛvʸ4|H6|LöX´ÞäqJz¨èºN6›õ/¾mÛ%/çh4êϬ Îq]—¥K—–$F†a¾µ¼kšË媲¢:ŽãßµŸišþzÕ& t]/鬵ŸP;D>ÃÇhäEɵºOj¿`B@(›£=ž09 %ŸCɦZ/ò9¾ŒVVFÓv¦R)ÚÛÛýa¤R)R©T­/ƒ0 ciWÕz‘Ýñe4²»|ùò!ÛUÙ­G¤ß.&j\:X¿Wä3ÜH¿7<ŒV6GÛv*d\¤?>&s,:–ãÕŠ)顋Űm›¥K—ú/æh4ê¯7 ƒh4Jss3º®—X½t]'‘H‰Dü}MÓ,Ù?LèºN2™$“É„v–‹¦i¤R)š››1MÓ¿¦±X¬ªó‹ÇãèºîψO$·UÇX¼xñˆö&—ƒE>ëA6ƒu©¼¨Mð>†A"‘йQ²©î“ÈgxJ>‡’Mùœ¨zŽFVFÓvF£ÑP_ apÆÒ®‚ÈîDÕs¤²ûîw¿›_|±b»Z ‘Ýú@ú½áb"Æ¥Cõ{Ã|-é÷†‰ÑÊæXÚNumd\¤?>&s,ZzÜi…D2SÛ¶}wÚ …Úu]ß•Èu]LÓdÚ´iôöö–¸þ9Žƒ¦i¡~ÀU=ËÏ1ŒŒôšZ–E:¦½½˲&|?ar™êòY/²9Vy™,¹&—JòYl‚Èçx!m 0RÆÒ®‚Èîx1ÙíªPH¿7\HÿU"ýÞð0Úë9šýD®Ã‰ôgÃÁdEëQ§¤‡Šb°‹ïº.‘H„¶¶6 à ™LbšfɃ¬ëú„%ö â8Ή’LÓÒÅIÕq¨˜€Ã•1õ¬®£½¦£uó ³{ØÁNØås'B6ƒûŽ”Zȵ0ñT’ÏjdêG>¡>ÚNµßh;¸K» "»a‘ÝɃ“‹ô{«+g¼ë5\}Gƒ´­Sé÷†§ííõë}¹ÒŸ­®Œ‰¨×Pû†©>†Ò•ÁÐuL&ã?¼º®ÓÖÖV“º¨ÄICÕu2ʘŒ2GS‡ÑX$ëÁ’) NXäs¼d`¼ei"Ê›Lyù¬_Â"›pp´Ò ã…ÈîäÔ+X–È P-a‘σ¥ß;–ë#r}pÙ„ƒ£í¬"×õ…ÈääÔ+XÖdŽEëQ§tÈ/AAAAAA„ñ`z­+ ‚ ‚ ‚ ‚ ‚ ‚vÄ "‚ ‚ ‚ ‚ ‚ ‚0 bPAAAAAA1¨‚ ‚ ‚ ‚ ‚ ‚ ƒTAAAAAA†A *‚ ‚ ‚ ‚ ‚ ‚ ÃpH­+0Vn¹å–,YRëj1/¿ü2†ap 'Ôº*¡â‰'žà™gžáØc­uU„ƒ˜çž{Ž}ìcµ®Fè¸ýöÛ9æ˜cj] á f×®]444pæ™gÖº*¡Cú¶B­‘¾meþò—¿`Û¶ôm…š"}ÛÊHßV¨5Ò·éÛ µf"ú¶uoP¹é¦›¸à‚ j]A¹ë®»B]¿-[¶°eË–P¿ôÃ~ 7nÜ ƒÎ2:::¸÷Þ{åÙ7ndÑ¢E,Z´¨ÖU©H½¼?dÐ9û·ã½ï}o­«1(õòlÉûcôlÙ² Ô÷¸V„½o[-aGBØå½Zª½'Ò·­ŒmÛüô§?ףּ홮ª½'Ò·­LØû¶ÕR}àj™*ï™jï‰ôm'•JqÉ%—Ôºƒö¶¤Þ a—÷_þò—|ðƒdíÚµãVæ¤Tzzž#:Q€IDATzèéé)Y¶bÅ æÌ™S²¾±±‘ÆÆÆaË[¼xñ¸^ñ¦««+Ôõëèè ££#Ôu û5\·nÝ”˜©6œl·©F>ßüæ7³}ûöPß»zx¶ZZZhii©uU*R/ï©ÀxËçüùóC}ßêåÙ sýêåý18Øú¶Õögp$„]Þ«¥Ú{"}ÛÊ{챜yæ™SâY8Øžéz Ú{"}ÛÊ„½o[-õЮ–©òž©öžHßvpfÍšêg!ìmI=¼Â.ï7ndîܹãZæ¤TÖ­[Ç=÷ÜS²lýúõ´´´°aÃÖ­[ÇŠ+Ø´ik×®eÕªU“]Åqeýúõµ®Â„ù¥¡û5œ* %›€Èg sƒõñþ˜*lòYÏ–¼?ÅÁÖ·­–©ô †]Þ«e*Ý“j8ØÚΑ Ïtø˜*÷¤ZD>+S}àj™*ÏôTº'Õ2Þ}Û¦¦¦ZŸÒ„½-©‡g0ìò~æ™gòæ7¿y\ËœtƒJICdݺuÜpà ´´´ÐÕÕÅÊ•+iii©Êâ)ÂØJ6AäSj‰È§ „éÛ B8‘¶S‹ȧ „éÛ ÂðLŸìvttT´ŽŽ|mjj¢©©iÊ¸Ì BØL6Õ:‘OA¨"Ÿ‚^¤o+áDÚNA/"Ÿ‚^¤o+Ã3©•þþ~®¾újN<ñDÎ8ã 6lØxñÖʶ¡¡a@ܾr6oÞÌš5k&ó4ÁgÍš5Üu×]µ®Æ˜J6aôòy×]w±nݺZŸžpÒÕÕÅš5kxñÅk]•13òùâ‹/²fÍš’ra²P¡^yå•ZWeÌHßV˜jHßVú¶B8Q}ÛÍ›7׺*cFú¶ÂTCú¶Õõm§J(¡¾X·nÝ„ôm'5äWOO---\z饬_¿žŽŽ®¼òJéëë°}µ‰;ëM˜º¬_¿~J ª†’Í–––QËç\úx”ÂÔ¤©©‰õë×O ¥äDÈçüùó¥íjƪU«hllœ³Ù¤o+L5¤o;4Ò·j…ôm¥o+„éÛôm…Z2Qý¶IõPQåÖÒÒÂùçŸï»•3œ•S„ña(ÙD>¡†ˆ| Bx‘¾­ „i;!¼ˆ| Bx‘¾­ TǤTzzz¸xÍ™3ð„¶\ûúú$±‘ LCÉ&ˆ| B-ù„ð"}[A'Òv Bxù„ð"}[A¨ŽI5¨(W1“¯¿¿Ÿ{ĵSÍJèêꢧ§‡óÏ?¿Ö×H¦!¼HßV†gÒ *àÅÝ HA¨CÉ&ˆ| B-ù„ð"}[A'ÒvŽ/ãéM’H$ û•L&Éår8ŽC4%“Éà8Žo˜ nFÏ#¼Pcš¦‘H$|!œˆ| Bx‘¾­ MM *‚ ‚ ‚ ‚ „Û¶ýß–eaYV‰A£Zb±­­­D£Q à jœ±m›\.G{{;š¦ùž,¦i–ädQÛ*¯R¬»»Û¶immE×õ¯AA„ñ@ *‚ ‚ ‚ ‚0‰Ø¶]óÄ캮éu’Ëå1FSçL&ãDÒé4ñxÓ4I¥R†Q²m0ѽ¦i´µµ ¨G9š¦ùáÃLÓ$‹‘ËåÄ "‚ ¸#AAAA˜DlÛ.1Ô‚¡’ÊÃÀ*Ùl–H$BooïˆFýð\ŽãÇimm¥»»{Àv¶m³téRßÃ$‘H [~¹aFÓ´AA„ñB *‚ ‚ ‚ ‚0‰Ôc~]×Gì¡bYÉd’ÎÎÎ’r‰‘H¤â>©TŠT*…eYd³YâñxE£JÐ Unœªµ÷ ‚ ãC6 ¦ ºªywPs)\4 æÍƒQÌùbPAAAaP\×U-]×±m›l6[bD²,«bYÉdÛ¶iooÇ4M\×%™L¢iš_å}RnPQeªºÖ£ÑJA¦Žã@F‚m{µ*U\®i`YÞr€\¢QÏÐ’ÍzË&s.…TAAAA(¡ÜƒDå=j}yÒz]×Éd2$“I²Ù,š¦ù†•%H,£¹¹™ææfßp¢r­†Ass³¦,æK×uâñ8º®ã8Žï#‚ ÂøaÛEÏE6ë7”AÃu!‡Bj3tÝ3ˆ$“Þ¶­­‹yÛ¦Rž¡$÷¶sœ¢áIJ¼ã9Ž÷;¸,ö +A'UU?µ,›…cŽÿë AAAA|òùü˜Ö +±XŒX,æ'–×4m@Î…®ëôööúÛ†á{§tvvú˃Þ-–e¡ë:íííX–5dù‚ ‚ ŒždÒ3€†÷[×=Cˆã!®ë6²Yo}6ëWr9Ï¢ëE£‡ëzßÙ¬·® 0étÑËEy¡D£Þ¾º^Ü_׋FeÔI&½2²Y8õÔ Y²d׸^1¨‚ ‚ ‚ ‚0¡Œ$\Ø`ÛWÆHC’ ‚ ‚P=ŽãFÒi/Ü–ãxž&ÙlÑ Eå7Q†ð  õÛu¡­ š›½ßÊèÒÞîýW]÷–g2žáD• Åa‰„·Î²¼ºAqŸ[oíãøã÷ëuƒŠ ‚ ‚ ‚ u‰x¤‚ Benwà3Ix,ãå(#ŠÊ¢Îsf8t½Ôp3‘ˆAE„ºÄ¶=#J,æÅ\Ìf½—ºr5AAAAn\ uí`±aöµ½ð™º¹ÅZ åM×çrEC„ãÀ.à×iøŠÝ6<äÂìÂúGÓÞï#€¸¿vaæSæêð¸åZ²YxøjfGá8 NnõÊØ–€—mx& o5áÁœgDQž'ª¾úD]˜#Aê åzèº^ŒÅlz{‹É©TœGAAAFG2˜=Ðuh4ŠV˜>šL&‰ÅbèƒhR²Ù,º®ûIâmÛ&Wl®i±XÌ/KAƇRˆg †µÊ1Р⾃û¦ ÛL”Ý ›-æ‰F=Öã˲àGÜeÃ.fšð(0]ƒï&aVög¡×‚O&à|& ÙõoY^ƒ#tøb3 ‘†íœƒ#xÔ…™:ôçàCô»`µÃƒÀW 1¢™^ë ‚ T‹ëBs³ç˜ÍzqUR+ð¬åŽ3úòAAA€t:eYضmÛd³Y–.]ŠSèl§Óiÿw%r¹–eùÛF"eY%e ‚ ÂxÒ\ößÁ3ª¤l`™úv ë³…Opž®]ö 5°ÿPXeÿÿèÀÕ¹ÒešVL¦žLB$/šðÇÓÝgÃf ^s¡Û…MüÑ‚=i¸0˜ åàÌB¤–‹Mx² ~™…ÏÆ¼òÏÖዦ~ëò(\…³pB;ªÁÙluàò6øN Þ«Ã2 2Ä x ñµ·Ö;öNºÁ幜gUâÚž¢°@¼p¿ aÛ6Ù±c¼j ˆAE„:Áq¼÷©ŠÁØÙé5:å–q±” ‚ ‚ ÂØI¥R´··ÓÞÞNgg'†a (+ª%™LÒÖÖF*•òËŒF£¤UÆ[AA'\Šž(.žD”—J¤ðÛÆS¼g Ëì¶­…õÉ@9Kñ¼ZÒ…ï\`=…}‚8À…e¶‚;ðÿ²Å|$óæyÇü§t1ˆë‚†¹…ð]ë³^h/Ý„-.̰!ïx-è°È…K¢p¡éEo &y×4/D~9±|\ƒ«ux­Þ\ã•>¡{“—•î­`³Á |¬ÂùÛeCßwðååafÇMãnߎ4›&ÖsÏûéOÉ>ù$‘À½óÉå°ûûIêäîÙCäµ×˜ÛÛ;†üêêꢱ±‘9sæøËzzzèé顱±‘ÆÆÆZVOZ*É&ÔN>mÛkpTÒyèãØ¡N$¸ƒ(XlÛ&cÛ6Ñh”D"a%Ë Ã ‘H-dÀD"¾‘Æu]b…L»º®û¿]×¥µµ•¶¶6 7"D>!¼ÔcßV©çÓ=O, ZøV†/Œ—MÑc–9=URxŠ{U¦ÚF)ò5Unìö‚Ñ& ¯éž‰“ò¶ÇáQvSt¶p]øaŽ4à—.œ¤Á¡Q8Þ…ÿIÂìÌtà|–èðS>ãÂÃ6\“ðt]±X1RK°i+O_Npµi´k””U¸^*TšòüÐòyô°gÌ ·°¾"ÍÍž•¦R?"ó.ˆ®ãΛGëÖ­/½„y㤀½{1ûúÈ65y×ùÌ3q–.%u÷Ý8gœAzútbóæàD"´Îœ‰ ¤úû1>ýiœÕ«ùç/}‰ï¾øâ¸>g5óPéééaõêÕlÚ´É_¶aÃV®\É7ÞÈÊ•+Ù°aC­ª'-•dj+Ÿ–å½à«÷躷]&ãyÆã%^‚PׄQ>Að¾­ „“°¶Éd’l6K6›õG"lÛöÃcÿ·¯}†ó6±m˲°,‹d2‰eY¾qb$Äb1Z[[‰Çãd³Y\×E×uŒ 3¤Ç!‰H$ÈçóèºNkk+®ëúF“|>O4%ûaÃTx²ÎÎNÚÛÛÉf³lÛ¶­äs¹®ëŠ1%D„U>A¨ÿ¾­2œ8xŠ~Ï(` SX®–)O Ûå Û¨VO_¢…e*T˜UøŸÍÁ²^®“­º—§ÄH‡rðß8,‰Â6¬ËzÜÌŒya¾îÏÁù:¬2à(>¢Á‡o¥àмƒ+cpg[é$ãJÑ[J/†ÅP¨Dó>®ë)Ô‚Û®UôG?Â)\›Ì-· õõaÉ×^#¾q#Í@rûvš]× 3“Nƒã`=ù¤çѳt©W~k+¤RÞ‡l:ÍÒC…ٳɮXAòCÂüÃhÿøÇIýë¿‚ë¢íÞMûªUô>÷‰ . óÏÿŒyÇ~²ÜÛÞFlãF2É$ÆþýÄ~õ+–>÷GíÛ7¾X¾F¬^½:ßÜÜœàüeÁÿ›6mÊ/_¾<ÿüóÏ[Ž Ô’ë®»®ä9®w*Éf>?rù|àò×]wݘëÓÙ™Ïëz>ßÝ]Ýö½½Þ'ŸÏçÛÚòùD"Ÿ7Íe S­/ùœj×E¨?ƫҷ¦ Ò·­ÌT|o 7 #oš¦ÿÑu=ßYèHùöööA÷7M3ŸH$üÿmmmùX,–×u=äMÓôË ’J¥òÑh´dY"‘ȧR©¼a%Ë£Ñh>•JùõéUƒ€Âñÿë¿þ+ä» ‰h4šÏd2µ¾´cbªµÒ·¦ S±¨—¾m°%éÍçó‰|>¯>JÔ^XgäóyÕ$ ­°ow>ŸæóùT>Ÿ*ÌÍÂ>fa›Þ|>+|º=}äó‡FóyÌ|~ºî}N‰æó3´|~QÊ[²‘ÏÏ7óù™¦÷ÿüT>²8&^Yííù|ª3Ÿwz=Ö`TÛ¦m;ýôÂêÍÿðÛß~‡¶¶|>+þ¶ËmmùÔÏî)ÞL3ŸïíÍ·ñ‹yòù¼ñøãùháÚi}}ù¼¦å{W¯ÎG{{óú¶mycß¾|âÖ[óm¿øE>ú‹_ä£;wæ£ù|^ýõ¼ÞÝo/\ß¶|>ßëºÞÅ0Mï"¤RÅc&Þ§³3ßý‰Oä[·æücÞxùå|÷å—çóšV¬ow÷„ômk⡲nÝ:šššX±b…¿¬££ƒ††ZZZhjj¢©©‰ŽŽŽZTQJ*É&ÔV>ãqÏÛ¤ÚšVôd‰F=ƒw&㿳Yϲ¹yX}Íoa0Â(Ÿ‚ xHßV‰´c#˜C¥½½D"Q’\~$D£Q2™ ÝÝÝtwwÐÚÚ:`;å½R^×u1U`øº®—„ +÷<9òÈ#‰F£¾gŠeY~ˆ0¡öˆ| Bx©§¾m0M‰J:oày,(¯ð¼Ox^jY´ði§èÅ’Âó@I¶±,ø¦ã-û²Žåm›ú,вžgU^/ä49àxŸ tXƒ].ÌÕáIÞhÀR’½-æ+FQ÷eš0àš§ÓÏkTµyŽã`Û6éxœGû[™ëºÄãq\×õ·yàæ›yè©§xòóŸç÷ßþ6ïúüç‹ ±J áçÍóâ†wb–å}ÇûØ6‰|ÄÛÆq@Ó0·o§íñÇéüüçiËåÈ'“ÄþúWZŸ|’æõë14¶yó0- ëï¤õƒ]G{ñE\ :s&m>ŠY¸Q@›;·è:cš^Bðþ«Xg†~啤^}•ì’%¯½†þÝïëÿÒ *]]]ÜsÏ=\…U\¾ ôôô YÞæÍ›Y³fÍdŸ† °fÍîºë®ZWc\L6ÕºÑÈç]wÝźuëF]§lÖK U6v–`X‚d2I4Ú xïúxÜ+Ï6kVmˆÇÇ^†à=³kÖ¬áÅqŽ“YËóOù|ñÅY³fM¨]´…©Ë† X·n¯¼òJ­«2.HßV˜JHßvbû¶õN¹£,Ë¢¹¹y@9‰DÂ×UM{öì°}5u1M“\.G6›%Öm¸/շݼys­«2nç#}[aª }Ûêú¶]]]R_•<^%•w)æûPaªžñÄ `Èz¿•ÅuAs½í v r9x¶_äî¬÷?ñl Û²pt!‡ú4HCKÁ bšÅœ¾äà¶NÏ&ð…\“‚'ÚáCfÁ>P¨›ºä¶mû’]=ÿüwç‡í\ºt)étšÖÖV¢@ßuבÍfùÊûßÏCþ0Ùl–«/¾˜¯á üß÷¾—g¿øEvíÚÅŽÿø~úõ¯ã‚7ãØ²JÃzE"Þ'õNH×=ƒ‹móœ¨v8‘(3fD¿÷=ïdmlý˜c°çϧÏ`d‰Y³hïì¤h;å2ºN{áZ+WV¾Á±XQ)¨iÞÿh´äØè:í+W’9üpo™2ºà'¢o;©Iéûûû¹òÊ+¹á†$ëëë°}5É/^Ìúõë'ó4ÁgýúõSbP5”lÂèåó‚ .`íÚµ£®W:]lPª!›Íú±ž‰„£¹±ñnR©ûïÛ\n`­Z¢Œÿã¾ÿ_=MMM¬_¿~J(%'B>çÏŸ/m§P3V­ZEcccÍg³Ò·¦Ò·š±ömë×uÉår¼D†C×u?_KP9gYVŲLÓ¤µµ•D"¦iX–Ekk+íííD"Çñ ;¹\޶¶¶!¯r­€çéR¯HßVú¶Bx‘¾íÐLVßV™Ø3=S¢…ß0PÏ¢.‚¤Óžž>ól ®[ÔÑärÞº‚“¶]ðv)@ÃK‹yÛ57ó’d³ðŠUô6ñw(Ãq²Ù,+::Øsüñ|ñÞ{¹ôoDw¾±};ݬߵ‹çrÌÍçI÷[é»ïæ’Ù³iyê).Ÿ?Ÿ¶·³ëÐC9åõ×¹¥¿Í4¹}Ëþñï ³»›S_x™Ê bÛÞÌ^îEe¨7M¯Â–åP‚Æ—TÊ»8ÊkDí£N0!zÌ1˜e§©}6P4`'Æ—¾T WèoLT¿mR=T²Ù,MMMôõõÑÑÑA__]]]tuuÑÐÐ0`ûᬜ‚ ŒCÉ&0éò¹t©÷®ÉxͶmÒé4†aÐÖÖF,£­­L&î]?,ñò›¬‰i‘H±N&‹^•®[4èX–·]2é-—(B9a“OAŠHßV‰´ãC$aÚ´iL›6yóæá8N‰Q"¸~Ú´iÃéºN&“!™LÒÜÜL$aéÒ¥är¹ŠÓ4‰F£,]º”H$Bkk+©T Ã0ˆÅb%eD£Ña <š¦F+† jƒÈ§ „—°÷m‚7ˆBÍ“Í~«äòê[/ì§t.jÛ.+Ë.£¹Ùû¯"b)CŠa˰,o]÷ 1†?kó–g³ÐÞ^,»àD1$jrp6›e×ã³mÃN=òHŽâ v/\H,céöí4¼÷½$[[ùúÙgó—w¼ƒS÷îåêo›Ïž|2ÛàcûMÇa4|ä#|`Ñ"Z>ûY>ðµ¯qÚþýì>ë,þøÍoO(ñ ¶í…ˆQ±óÁ«…axË‚V)e|Q(“)žL[›ï!4iLr?©*àY;o¼ñFÀ¼»ï¾›¾¾>ZZZ¸göõõUeíœlZ[[‡ #õÆ`²©âbN¶|Úvéûx(Th¯L&S1¶²ã8%³à4­Ø˜Y–÷¼—óÜ`•Ëg? ½Àq¼z¼&ÙE"ÅXªa^]׫ŸãxçPÇûꚰɧ E¦BßV¦"ÒvŽ|>?¦õíMR,#‹a:Äš¦a ÑùÎd2Äb1?ŸŠÊ©’J¥ˆÅb¾—J0×Jy}‚Ç—±{øù„ðæ¾í%qøj¢¨;Wá½lyøáÐÜÌÝ|ü[ß‚_þ®º t9ñ8|ଈFÙ’LòèŒœéºØ®Ë©§žÊÌh´Ô%ˆòB¢ûÍpÔixÍ‘0©•r7›5kÖp饗ú ”´¥¥…®®.zzz8ÿüók}JÈårär9"‘ˆµ½½½nc±  /›---“&ŸŽã½Ÿ«UÜ«¤[mmmƒÌt]'‰ÐÛÛ[À•zˆ@eƒJ6;²cj¦‚jPÕ²l–’c‚7[¡µÕk› ï8é´×îX–×@§ÓÅÐÙB¬Î¶6ï;hPQÇUn¥™ÌÀóQ`[¨öU3(R)¯ì\®8ù õ .Ê84ƒJ2騰f*ß™:ŽzfÂ$Ÿ‚ ”2ú¶‚0‘¶3œŒÄCd¨~½~°wë‘OA/aïÛ> ì,49¼ü)J«¼Q TŸ¯Âs%“Eg‹æfO·Œ*¢&ª¨!¶í• 1¹tw{û´¶;¢Q¸âŠOðÄ7—Û.ù½èÉ'iضÍ_–N§ý–ß8p€;_{ o¸ßúzï{9pË-,Ù°%íípÓMpûížÂG¹Î+¯½Öû¯i|<“)*QT›[¦2 ƒ\.‡kd-Ë›˜¬Nt8$6½Ï¤{¨ ÅÚµk¹òÊ+Y±b›6mbíÚµcjÖ 5Ë]%гmÛÿˆû°0Õ™Lù,Wú†Š/F‡œå–J¥üü*JV•±$è2ªŒ ª©&‡‹ ߥ—óꦮš)¢ŒEºî•½zóf9X©¥| ‚04õÔ·„ƒ i;GŽ ARŽ®ë˜¦I6›­ë$ïBxù„ð¶¾íL î²à1ÓK8¯áy¦¤ ß¶ VAŸ¤&ª*ÝŽ¦õ*Êh¢Òˆ(]Gp™ÒKY–§¯PáâM;l ÝÝ‹øÅ/îçå— ” ðį~ÅYŸøëþîï˜óž÷àº.÷þÛ¿±xÿ~t]gñ3Ïpø¢E̾ùfÀ3Íéëã¬/ÍuᡇJO8ØÎ åÞ$åJ«*<9MÓIJ¬âÄc Ï"Ë¥æ2áIPT˜³è0Þ1‘HÄϧ–L&Ñ4D"A.—#Nûð¢Øhš†ëº´¶¶âº.‹/fÉ’%ãZ÷Py¨¡l,Ç!™LÒÞÞ^â^¬”´•:š‚0™hùTžÃÆ•u¿WŬÓ4‰+Ë Ecˆšà8ÅÆ1›-”÷Iéñ‹ž¶í•¥ŒÊS#vK­¯Ô¦•) Ãó\Q¹ÀÔ1Ô:eŒ0M†‹VµM<î}«üaA¯åô8Ñ´RCS%Ô%T¡À¢Ñ¢ñE]KÃ(†9K$¼sŸ7:;KsšÙ¶wž†Q4D©ÎKggÑ[(ñê4  cû)‚Ȧ „‘ÏÁÉår¾R¢ÇqH§ÓbP&‘OA'µ”Ícp’îRpº¡Oç¯ü1TÔ5Õ4K'‹u;Á¨PÔG(‡l¶è¢öýíooö7bÛ6O>éM.P)Yà° ¸áŽ;ˆmÜHdãFt]çí3f°rÿ~œD‚ÝW^É©üïöílß¿Ç4ùàÿü³÷î…[n)Vh½ELÓ$‘HJ¥°,«èÁtä°ñ¬T1¼$50&ãŠmÛ¢Êض]bPq]w@¨l6ë;7(š\.‡aÌ›7Ó41MÓ×Í»®K2™D×ur¹œïtÓM7qüñÇëu A%Œ¨›P«5•J¡ë:ÍÍ̓v6A¨årôZ ˲ˆ°QÉés¹ñxœË.»‰_ÿz%šæµUÿ÷wsÚiï!“™¥ÂOò¦7=‡m?‹eY%F×-æQÞ"šVÌ5¥‚†Šõª¼<è¡© Áÿƒí4ˆ(ïå…¢Xº´Îk$†çe¢Œ6ŽS¾,Hp|­iÞ5Rõ~ J*‰›Bµ£ÝÝžW‹Š]ª®}0á› ‚ ‚0¾¤R©A#1 —”^AÆ<t°² ôAu„Ê­®r·ª9ðj‚©ãxº“ÿx7'œð"†±Äé¥ÖAQ×ñµ¯} Û~?†a°ÿF?„ëº\²u+w¼!{ßûxòÎ;1ð¼e ‹áº.¦mC,†mt|÷»v䑬Z´ˆ--E%ˆ²ä(W˜‘*lF@ÊLAæïšÏì=³½Øiv¡ÒqØ>m;³˜Å¯ÿòkN<ñDÞØýFnnº™E/,â[3¿E&“©*Ÿ™2r477ÓÖÖæ Ô„gÃ0|Ï’t:=À br¼¼öÚk\qņA"‘ð½TÔDk¥Wú>MÓ8ãŒ3ˆ®ÿž={ÆýŠA¥ r¹m‚ø+ëZ4•:‚0FT"öáĨµµ•\.G·Š75‰ñxœT*E:ýyñÅ;ø›¿y ¹\÷ßï°qãÿ°{w˲ áüî¼óTN<±‡yóæÑÝݦi¾×ЦyʈQÉÛd´Œ&Š`¹Ñ¦R}T¹c™ðlï3Ï+TMfpßêYÀ‰zßàµÑ…äqº÷_í¯QŒ{jʱ4а݄6|Ó‚L!L˜ UVéüAA„ñǶm?‚ƒú¯Âj¨IOÁ‡¶m“N§ýY¥‰DÂï‰Düñ´Ú_ÆÕ‚ Â`lÓ€bÅèét1¬—Šn¡–©IªA#‹ãÀ¶mÿËw¿»„t^ýALóþq®¸b7–õ+–Ü»Ží&ý꫸®ë4ÛæÓ °Û4Ñ4×Þõ.Œ;ïä}'ŸLÿ¾}XÏ>Ë\e$ÉåÀ²0tíê«q]—j–¨J®kšÅ0"*ÓýD’ƒå/,gú¼éðcØ{ä^öµgù,½oìåÞ#îåo»ÿ–ºOà¿÷þ7ç>u.}Óû¸˜‹¹ãÇwpåW¯,*vÊt1*Ü–2¨hšF2™ôçr9‰†aÍf™7o¯¿þ:óçÏǶmt]çk_û?ü0‰D‚ææfÎ<óL¾ô¥/±xñbß3¥££ƒl6K"‘Àu]¾øÅ/’Édزe ïêxÉd’X,ÆîݻٱcǸ^>1¨ C$A×õ!-o‰D‚ÖÖÖZWUêšjòd(ÀÑΈ‹Åbþ Ïu]?¯ èd2&ÿ÷ÿ^,£»»›t:Í%—\¼›övM륩iMMEc„¦•æþšL\¼¶ËÅ3F(û‹CÑ ‘¢8É H¥HiXt (CKT‚7;°Ø.ØÔ+£J„¢ñ$†—,Î-”¯âªsPëìB½Ý@Ù [¸æ¶×,… /üX[[1AAÆÛ¶,Óu×uý!®ë‰DÈd2˜¦éç9T3LÕúD"A[[–eÑÚÚŠa~>R•Ñq"‘ˆ¯(A„dÒë[€Ù V3œ[hßjð²^tæH$І•H¤4ï¬j²’É$¦i2kÖYÀÆs<üð¯±ígœ1‡Ûnsü6϶m²Ù¬—ûC×ÑÇoÇÞºa®ºê*8áOaäºÌÕ4:;;½Š¨ä²Ñ¨÷_%Ö-kS}‚z®ò˜ïCà8ΰ¡·âñ¸VËq~òîŸðÑÓ? ÇÃý¿¾Ÿøö8_{ík¼pØ µøSsæ1¼ø§™ÿÙùœþùƒÇ{œ÷½ú>f}w7ýæ&N[|4çÿï§¹äë—Õ²uÔQãú\VmP¹úê«Ù°a—^z)===¬^½š+VÐÔÔÄ=÷ÜCOO7ÜpøV°Vär9ßêX ’˜^ÆÆ`IÛÁ“¯ææfLÓ$Sh©¼Ôw¶ðÛ-ün£¨œ¯–JyY:;½ï={îÆ¶g±_3¹ÅñƯ*Å};ÐJÑ¡êaRô´°(L”ÇGðhq<#I𢷇ûº2…å J½BÊ ®ËÍeÑBYqŠÞ$*™Û`¯eµÃÜTa¿ñ69ÏÏEEc”W° ‚ uÅ`söÚù=±aÊŒ*¶,‡JÐÈ¢¼¾å“ U¬ùiÓ¦•,޳e‚¢ ‚PNOGñ p³ÿâ ¶gÀ©n1ñ|:š]ažý¢§ç~N9å$¿íÚ¿&ɤnÒqßp^›eYV!Ô»—H=ŸÏ³`ÁÞ×ÒŠ|€þÿwšZZXñ®wy3ƒ—.õ¨Œ"J¯dšEO•„v0ƒÊPõ²m›ææf:;;ý0djrƒJä®".éºN6›%‹±mÃ6VÝ·Š‹¯¾˜Ü_s¼ý±·³ðú…Üu×]\pÁ\»¾'s²L•Ų,œs®üՕ̾q6žögÖ>µ‡Oÿ8N?À».࿞ÿ/º3žwŠa\wÛu|ôÀGùQóè5½)Çtûþ~½½û»cá³°¬ñÙqNúÊIœ÷ÿÇô“¦ÃSÀÙpzÛéhGjðï0?:ßS fŸ¢âÇ?í§C‘µÂ¡æ¡œùÌ™ìc߸>ŸUTººº¸ûí¶Ûhjjàž{î¡¡¡n¸9sæ°jÕ*LÓ¤§§‡ÆÆÆq­d-°,kD9ªIÆ#Be\whF_18ðÊá5°JaŸÁ3Ä(NÌ3|¬Z ÁpYïÿYX–Åž,t½òUH­æÂñ),Ó usÿ]І…J†žžGI‚¢a#SVå2ÒHšQŠÆ—¢ñ'5вFÂhêZ n…ej¯ž%åñ´cDZx†‚ ‚ ÂP“ UòÙöñL6(‚ LyÔäÙ~qà(`>p¨ ÷'¼q<^œ`YˆªÅ¶mho_E2 >º•+çNÛhšÆK/y®**‘Êóaš¦ïU©<)Õ¤‚·œ{.+>ò0MæÌ™ÃŠ'Ÿ„'Ÿ,Æ3ŒÊ‰pƒÉåu½ê˜ñj’¿ªS0RK<'“É išÿËå8âÁ#Ètf˜¶Ô›À‹ÅˆÇã$Ì'ådV/ZíM”8ÚdúÕÓ‰F£hšÆw¿Ë—c_ö½]”‘Iå;qÇO(¯ÂuÞ7ï>Þò±·°ð…üÃþÿwöÿ㬿=‹†{ØÑ±ƒUM«˜½a6Zü!Ž<þHföÌä—Æ/¡æÎë)¤>„÷Ÿ¹Þ> ÈÀÆ\Ð|AQ4XÒ°ÄS¦9xÊ,å«”mjrŽ¢2p)žRêãÿ|VeP¹ûî»iiiñ)à…ÿ:ï¼ó˜3g466ÖµA%™LbétzT®ÆÍÍ̓ÎâapÔ¬‚ÁÈår´µµÁ{?¶ã½73”'‚Ê{ÏS¥µ°]5óÞTƒ­ÞÉÊ`ão]²„—O9…Ç5èÔŠåE©l´)o&‡;¾^Ø'FeO‘±?Pa-iˆÊŸ‰Dü™À*Š ‚ †ïûhÀsix d<›„ŠiYžmÃqŠ:€o~³ÓO÷Œž‘ß%›Íúm”iš†A.—cÞöíhºN"ã•·¾Ó4I¥RóÍÌZ¶ÌS0ÄãÐÛë)Òé¢òê“ÖÀ4 É…v}LŠ–t:M4õÂw¥]úÞÔÇ’O/áï<ÀŽ[w°uöVz»{! ®å’13,û?ËxÓ)oâ¸?kàÜô¹p›wÍÐàÌGτ͓ƫ¿ÔDˆ¶¶6Z[[}”rÝv°ÝVF€yÍó`qaE†b,~uœf<%” ÇÒ^XfR¼^ÊТ”mʈŒdSžXgx%ZAyÔ°­aô7fª2¨444p÷Ýwûÿï¹çZZZüeýýýtuuÑÐ0þ•œ,TgO:w‚0y$“ž10ƒJ2™äg÷ÝÇ¥xïOðòsVç(éHÔ{Y…ºRÞ+–ÜÏ?΂D®¿žÔûÞx3Òé´«R &ƒáÿlÛö]&-˰~4X–…ëºØ¶ã8†¦ió¿ ÅX=^lÛ&W˜…¡:$•bf—ÇÕž( £˜O%¸LAA9Ã…èÊçóþìÕX,æ+ª¦M›VÒÿScl5+8¸N•SíqA„ƒË²°%¿ì„Æø*ç»ëz:%]‡íÛ·óì³íèèþ¤w•oÄ0 ŽÜ»—/§RhšÆ[7l`U{;´·ƒmsÌæÍ|kÏNÉåà† «Ë;òBøF0<Ãij‡÷Û1áF¼™¼Cðèoeã76k‘N§ù䓟dÁ£ñê¦W9Ù9™7Ïz3÷þï½ôÿs?æJ“Ý/îæ­‡¼Õ›1ìòÿÆ>þøÇ=ÃAŽ¢ÁÄ¡û]ÍNzÛ—+ƒ”!%‹‘JU7Í·Dÿ¤Ù¬g¶R.©j惺F•ÎSªÔ \ÍrT†$Ó4é?÷\ì9sÐ ×+QeRAAa|qÝÿŸ½s£:ïþ×€oØXa°›@< …KHF-„R'»¦MHpv“¼!äâ—Ý^’´¤iwóªIHÚ¤»4%—¦4 mnÐ4Hb4@±ðŽm0[|Å~ÿ8ûÌήVòJ–´+ù|?}´;×3³sfÎ<¿çÐÞÞfyH§Óض=ÄÑFŠâj4FS b«iJÀ&WýbÏ+Q¥«K‰*=ö.Ü@/½´í…åÔóȲ,®¸÷^¬BŠsõjq’-ª ¯?á„b1©jÿ’¡R¤Ø@ƒ­¼s]à¾Å”'RÃC ñ: õbͼóæñž÷Ðóo=|äñÀèììäÂk/¤Çéa»‡7žöF.ßw9³Ÿ˜ §ÂÜåsÕö zN˜> ŠbŠ2–…ïPL¡• XX·‚©¨«à:&;Ò¡b¬*§õ2al=yë¸o³*A¥¹¹™o}ë[ÜxãtvvÒÖÖÆÚµk•úkÍš5477sË-·LÜÑO0âI>VĘÙÒÒRëCÑh¦ÃÕ°t€¿]³†8PRÐ},X# c”ÞïG³ÝL&ƒã8´¶¶’H$†ò¥þ’å$“I\× ˜l6¦=1Æ÷ý0úDI{¶±‚òÍm)Ûáb¼=ü¢"Q¥mçóy²Ùlx/ííí%NÓÒÒ Ö†a„Ñ-’‹3ºýÖÖÖ°\´øšišáºƒ³f‘èé¡ñ¡‡Âs­_Ð5F£Ñh&Ó4Éård )Ó4CÃŒF£Ñh4c%(ûRÉÖ*Û‰iÂË/÷óóoVN—(‡÷X,FÂH࢜Xç|òP#”a(5Ʋ˜mÛÅ´^G›°˜‰"<àO3JÔðQÏ¡4ºB-‚G•–ªnë[·‹Tbï»ö’Oæ™ûŸsÙüÕͬþÜjHÙÍgÂ|8êô£˜mÎV+»°?²?ùžB¼$DΑUØg42$šb«™@“NMk¨,_¾|H9€+VpÛm·•¤ÿšjˆ‡õx%'_¹GŽF£©L®B!”,ðµ={xý¿þ+?ñ‰ð90VÆKVH$X–…뺣")‘ËåH§ÓaT‰¼lFÅÇqÂÓ©T*Œ>)¡„°º®Kww7†aL&I§ÓÄb±q‰V‰Çã%(ßò(¿T*ž7A¢lD òù<™LFÕÌ)3åQ,r쫯Æ:n¿=Œ , 5†©ä¢Ñh4F£b±˜N›­Ñh4šqevNóá\vV2`½¾Þþ$—ç~G6›åÿ ¼-[øXXär9Œ¸…¥l gÂÓÏ·!v ߇OtC̆{<ø‘(„Æ\]x¾IÊ,UãCjƒ8°þÂõœcžS; ÿ7}nÏ42gÎ>ðó웽×îzV60ã´¡c¦7³4¿½UدØÍDœ‘ÏB%¡DDBÞùÝwòÐ×mV-¨ô÷÷së­·ÒßßÏ‚ H$,_¾œ Li1Š…ÆÃÃ9‹ÇuîW¦JòyˆÖº*¤„ä­wÞÉ9{öà ž õ`YÖa R!H2&Ê ‡¤1WĘ|>O*•:¬û›ÔB†T*Qí~“É$Žã°qãF ཽ}D*£«VqÕìÙăƒbzPøû8ð0æãÖh4F£9Òq'gJÍÀ‰$N—|7M“X,Vâ°˜N§‡K ’nv¸å¢õ¥¡vŠÔh4šÚà¡ô±Ä]>ì  -7V2 dçàìÍsضnžçñ…×¾À¶­¼}åMê¾þHž _Ÿà€Ö·mÚb°Ô„¯˜ð*З€W Õ(» £Ä É!ŸBDäðÁ͹dÛ³Üùã;Ù¼|3s^›Ã"otÁ¼ÏcÖ¬Y<1ï ÎÚtî'\N9îÎùü9ÐK6-)Ö;IR*” -$o¡Å’Q2)¿ŽªvÁ5kÖÐÓÓÃòåËéïïçºë®£¿¿¿Öçd\Ïü’÷_£ÑÏS!š‚Dl]³†_êSá ÛáF¨Ô¶m3000b±¯ÑÖr’´`QñE¢;\×¥¥¥¸ÜjU Û–—éñJ¯%m’4gዬԧ©D %˜t£Cî¿òJ6u)Ç¡ èl×åøóÏçäüÇqi«F£Ñh4Í‘D´¶¶–étšÖÖÖ ­*E„=Ï kò•e%Íí¡¶“ÍfCѤ|^{{{ø}<ÆËF£;ÅlY.Ê.´ß‡W\86€Ë*éÝ&XK`Ñž£yê®§H)Ž9æþt柰lÙ2%FlKóµóà‡qø7 .Ȩ´^¶­R{Åbpc—Ú`øR 2ÛJ†bÞøÊ!¿ Øñ¦atȇ>ô!Ž:ê(Žöxþã­ÿÁ®9»øâÿ|‘®×u±÷œ½üý¿g×çv±ä}KØ{õÞ¢HÓUøoåYÞ J#V4uCU*===ô÷÷óàƒ†…èmÛ¦³³3¬¥2Uiooâñr¸˜¦‰çyZZ£™DµÌ,ðÎÝ»ùΈaªx%ÓKP™¤È{%Áîîndzp,uQz{{ÃÂðãA4M™x–ÏN¸‰:dHºÐ%…¶Ú…Ú3âiøë_ÿzâN¼F£Ñh4Í4%cY*]ŠÉdH&“$“Iz{'®zl&“)qjooSÃVƒÔL¥RÇÀétšîîî’}$“I²ÙlÉñj4fr(—ég¶+ƒu܆3‡1×Þÿý|`æ"~Ä8åÉS8nÑqœ¶ÿ4˜\×͇f ȨZ(ó|˜‡r0Ó#¥”ð,%\¸¨Ú'Åð‚AIÞ h}O+7nÄM»p<œôG'ñû_þžkç\ËÅ»/&±2AâŸàÁwÌl´›Ã+¬©)UG¨´µµ…b Àå—_>æöõõÑÓÓC__ßyýýý¡€3YT;0«Ó4q',̧ÑLFê›0þý3Jë9ÀywÝE"‘ °w1T¤×”bY7n¬(âJ1x©Í2ZQD겈¸áyÞ¸D¨ˆˆ-/»å‚JWWWÕ¢t ø›¦&ºººÂíuww:Ò§Þ™ìþ©Ñhª§ÞƶF¡ŸcCœ^*½'g2|ß'›Í’N§I§Ó466ÒÒÒB>Ÿ²x<ÎŒ3hmm £ED iii¡±±qHš¯rF;ö”èêD"çyUEžTj&Ý?5šúe²Ç¶EQå!ŽàRK¥ˆ¯èÿž†OàÙ£ž%A‚‹·\Ì%{/áoþ­ bŠ). à<Nöá÷žª"ù¥༠ˆ¯€Qü\Ɇ"Y6Ä*ÓÈžìá¢w^ÄÂ… ‰ÅbÅçŠÅPñD‹)“Æ}ï¸oÜ·Yu •ñⳟý,===477ÓßßO[[7ß|3ttt°bÅ 6lØÀÚµkY½zõ„µÅó¼ É“jYñxÓ4I¥RA@:½]Ä[ò¶&‰ªë$h4ÅH}&¦:Nñá˜DEQ>ñë_ëè®qÆ0 z{{C¡7•JU}Ïñ}?ü= ÃÀuÝq»oA0ldÍh¯ضõ«jÑ?5MuÔÓØV£ÑÑÏα#‚D¥1ŸaX–ÅÃ?Lgggè%â‰išØ¶MaM<18Iԋ뺘¦Ioo/¾ïÓÞÞŽmÛáø4šRLj¡ŒfŒ'ïØ’B¶ŸÇ4M‚ —Éd2Ö&f$Õ7 éŸA ÒVæQϰÐîyãVÓHSJ,;¬œ×ãyo²,+Ì­´‘©UÿÔh4‡¦žÆ¶¦È”xv–4 å1¥àõbšêOðýÒpoPÛˆZŸªÙÏ(¡Å0ŒÐiP"BDŒq't0”ù±X,ŒbÉd2¡8S>t'ôøª°–Ú+â°#ûŒ¾_är9lÛÆu]²ÙlÉû¸—Núvýõ.f´Î`ËQ[øÉÜŸ°šÕ¬»lq·…GÝ ~\¥Òåyy ðÎnÒ*ß|<ë}x“ fŒhFÐì‰Dè â @oooø[®išüYêÏtôI±½q;sÌ×mV-¨lذ5kÖ„ß%´«<üë¶Ûnvýýý¬^½:L&nÇŽôôôÐÐÐ@[›’‹–/_ÎòåËééé™O„t:ã8ãžî Ô`QÒÕÄãñ0:E"UR©Tèé-1ét:L6mÒhFb¤¾ LHÿô}õŽ˜Ê©èy~A0!‘cšÑãûþßÂuÝÃŽ(bÝý[šZôOFSõ4¶Õh4E¦Ä³ÓóJÅÓ<´ bÛC•J¢K¹ r¨ý”!ã´á‚€ã?~ˆø`Fè¼#éPf̘Q²Œ#Ëk¨äóyÚÛÛ8äi•Zzñxú¨yüñÇÙ{Ì^^>ð27lº,YNžw2K9æR¨‡â©t(A;^~ùå\~ùå ²aÃzzzX¾|9mmmÜzë­C¶ÙÐÐpÈœ|[·n¥££ƒµk׎ª-žçMh4ˆ Ö2™ ---aá{Ã0°mÓ4K¾‹·¶öÌŸZttt°nݺð2U©o‚NÇÒ?×­[GgggŇ«çP‘)&„"£fâ1·š”_å/ž¦iâyÞ¸½Œç¶Êéïï§³³“íÛ·OÈö'“‰èŸÛ·o§££ƒ¶¶¶)ÿÒL=zzzp§¤6ßT¥žÆ¶Íx Ç¶cÛŽšjêujœdÛêïp÷S†8ü•¡Xðýë_ÿ:%ó¢"Œ¼çVJÕ5ÚZ£’Ù¡*¥ÔgJñ0N§Óôöö–l?•JÑÞÞ>ês5YÈØvëÖ­µnÊa3ƶÙl– B§Yß÷ ‚ ŒÄ’÷®xzl[ÝØvõêÕ‡´%û€oÁ• ¸Ê‚J¾œKû–r*§Â ì^¼›]Gïbý{gqN`¨T_^  NžWp2(¬hYEuƶ‡:$Dˆ¦¾ìíí ÓOjtêÑÙÙ9!cÛª•åË—y2Zúûû¹õÖ[éïï‹Û‹7B”jD›yóæù¤ˆÂ8‘HnXQ.£…£ÖJ´´´ho™:¤­­M›6ÕºãF¥¾ cïŸMMMCÄXÁ0àtK…tÊ0R^t4‡¼H ÏóH§Ótuu…Ó$ún¼þœ°ãÏ™ÃIqVoŒgÿœ3gŽN› ©ÍÍÍ,_¾œ^x¡ÖM7êel«Ñ.zl;2#m§"0$“IºººB'Dß÷Ãt'Ë–- Å©™"b(Q&›Í†¢L´¶¶ŽÚ%Û­füéº.¾ï‡ÆmAÒ~e2™ÐA(ŸÏ—¼WëpT+dlû›ßü¦ÖM7¦ÊØV¢œ¢µy$u±ˆ"ñxœ\.G{{{áµqãF’ÉdX3(›ÍÒÕÕÖÒu]·DØÓL]ôØvddlÛÐÐ0ì2ª< ¨KMdRÉ' Ož5§­á´WžfÎkÛ™ÿæ×sÎMçۅ畦·Œæ ‹à'xŽS1‡”mG|ù¬™z¬X±‚x`Ü·{ÔhWÏˆŽŽ:::èììdpppTÛæöÛoçÎ;盧³³bÇ:”Ê 0þüQ¿tмämhª1Gk¨Tj¯<¬¡Tt‘Z0šÚÐÖÖFSSS­›1nTê›À˜ûgSSS˜·œl~FQL‘²Ä¼è4ãçya®PÁ4ÍqI÷5,X°€¶¶6æÌß<™µd<û§T4µ¤¹¹™³Ï>›Y³fÕº)ãF­Ç¶Íx¡Ç¶#3ÒØvº!i·ZZZhmm¥½½–––ð½ÔØ0™LÒÞÞNkkkIÍ”hԇ̗:*‡¢½½3f0cÆ ñ}ˆ]fÆŒ´··ã cåïø±X,|×0M“\.G:.9®‰J>^ÈØvþüñMYRK&clëû~-R ¾ï“N§ÃïRÿ¶½½½ÄÀšÏçÃȹæÛÛÛÉårtuu…×R4%Ô÷imm Û¤m9Ó=¶ÛŽÁã£IŒÂ—£üÊÙ)pÔ¸lÛeuúQ3ï¼ú¦ õ¦ˆi;”€’H@ww±Ë0H•> Ê"Y…$=äx¥>×L>Ë—/Ÿ±í¨•ŽŽlÛ¦££ƒ¾¾>úúúøìg?ËÛßþvn½õÖC®ßÙÙY²Ü‚ X¾|9ýýýáÿ(;vìwcÔ1©7ï“èà3Jtà'žÖííí¡‡y:ÕŠÍhˆÇãáþ£õ^4Óƒ‘ú&0aýóä‘õhÓL,Õ Ü+¥xÐÔ†ZõOFshêal«Ñh†¢ŸãC&“a``€L&C*• ?‹Ê4M6nÜH*•¢««kHz¯T*Eooo8_rË—G)www‡ïçòM•4Ò2bÌ.Ç4M<î#‘H”WWW7nÔcßIb2û§¤é©‰\ûŠˆ+’"NÞUÛÛÛÃëF®)¹ö$½{%Ãk*•¢µµ•T*E"‘ ‘HÐØØX"àH›5šZQ«±í.^çª:ò¥¥À¢|aÛ°±™·w,·~ê­œwÙyÅÒiˆÚHS©aScFïÑú_Ññx¼¤tƒF#T-¨H4ÊÍ7ß̃>Èm·ÝÆm·Ýƃ>H"‘ £££jQE"ZÃü˜mmma‘#Py3ûûû¹âŠ+Æõ€=Ï«Ú3¦D;q<§½½l6K"‘=‚ —s]Çq–á¾Qµ5™Lâ8N¸?ù<²Ù¯|ŸZZZªZ.jnmm­¸Œã8Ûéyñx\{ƒ”1\ß&¤~ à&¯-Ò75‹eYa:¯á~®úa²û§F£©žZm5Meô³s|C’ä’¯„Ô­„iš#ί%r\õضéÎdõO±ŸTƒØIlÛ&ŸÏ‡5n%Í£.w4MsØëHl4‰D‚ÞÞ^2™ ™L&ö@‰4â¸ÇkýóhŽpj1¶ÝåÀ˜3}¥ƒD}Î¥þÕC0xÍ ô*/X2YR§´¾ØY‰¢é,MÓ$“L&ô}©T*t”‘PU •¾¾>n½õVn¿ýö!!Î ,àú믔Ñ^>WbõêÕÜyç¬ZµŠææf6lØÀW\õ[»v-7Þx#+V¬`Æ ¬]»vÜ‹:I´G½"ai§xØø¾O2™ s½zžG6› ×[[[ÃéåFPYW¶)9@AE›APQ`’¼ žç…û‘±ëº466’J¥‚`\£EжÛ0 ÃÀó<|ßóߦÓir¹\(2E½é%¿©QåÇljÅb466‹Å°,«ÄÛDC‰D"Ì—8Ý9Tß„ñ퟾ŸIßGœØtDÄä ýi¤~Ç+FÌijÃd÷OFS=õ0¶Õh4CÑÏΉÇ0 =v׌‰É쟞çU•æ]jyær9\×%›Í†iâÃ0Èçó£JoYV(ÌÈ÷(†aÉdˆÇãá¶%­ûd¤§×hÊ©õØÖZ¬¡:ȶuÛÀÿmü/¿òa–-[øàxÅó¦©R}UYG5j#•¾A‰MU;™j†£*A¥§§‡¶¶¶óÅ^ýõttt„ËÇm·ÝF___ [½z5mmmô÷÷™7^ˆQ¾žïð¨AÓ4Í’jÉ%ÛÝÝad³YÒétXpÚ0Œφ\.LK$Äãñ’hIƒ&EÔ ÃÅ“\.‡ã8¡¨!yg=Ï#™L†ËõF#!uŽã`F¸öööpÿÑ‚†Ùl¶DLI¥R¸®ŠLÒžL&3$µ™xÝ‹Wˆ¤O“tSÆçº.---áyÈd2Óþ…a¤¾ ãÛ?}¶[Åt_ZL™|†Kû'ýO§_«/&³j4šÑQë±­F£©Œ~vN,–eéñ»fÌÔSÿ;‚ˆ'ÃÙ6ÄÖ2‡KE%ŽÈþ¢é‡Ä‘Õ²,-®h&•ZŒm=ØW&[Y¡‹½üèËØ¾ÍŠ…7c|ð°›à‡™b*Ø‹:BYɼcÛvèl.6D±MjES U *;vì¨jcÕÐI˜™Œ‡e=üD ‚ bþW¡···äA.Ñ@˜ãOÂS‡#™LÒÝÝFt´··‡ùk£E˜¤]‚DpX–>ä“ÉdXp´žíŽã°½±‘ýÅ/ø÷¿ý[îÚ¶ÍÏ?Ïù×\Ãsæpò×¾†±goúó?çï|…ïyÄb‹,ÏãÝwÝÅŽƒù@_}sæà³7m¢o×.Ta«Û²…mgÅò¿ÿ{’€ ÐÝ <úòËüý–-œrõÕ‹³÷ºëøø7¾ÁÊ÷¼‡ž¯}-ÈäQ³à©K.¡mÿþZ_:㡊lŽWÿ| XB¡à”œ_ÍÄ#¢i%ôoQ¿LVÿÔh4£§–c[F3<úÙ©ÑÔ/Ý?彦RpɆ!ÙÓH@Àìƒg1û²WÕJå}VœçGHó—Ífq‡ÞÞÞ°Ï;ŽC,;,GqÍ‘GU‚JCCCU¢JOOψ)¿jM:®ûè”D"QUøtTLñ?ž–J¥Èf³,»æÒ@¥ ø£ûïç¯çÎ ·%9qåæaY ¥çÏZ²„o½ãÌݼ™í­­átË4  Þùþ÷ów¼ƒ£y„X,VÑk##¬B;¤=ÛV­âœ“OæŸæÎåÁÿûyâ¸ã|î9ö|ô£\ÕÔÄ™€{à ð쳸¿ù sÚÚð Ûq€¬e±Ì0XõÚk,›3‡Ï¶}ëÖ­¬èêÂ.¨ÔÛ¿óÞ³r%†m¹Âþ=ÀúÛ¿%ë8Ürß} ¤gÍâÌoäfàÕÏ~–ÀqpóyüDB‰8Àþå_h8í4Žö}X±¢Ö—Δâ©F¾K¤‘frPöò:)â‘!yB5F£Ñh4f*"¢I%ÛJ:m‰D¢j1e¢ëLvuu‘N§ÃZ·ÝÝÝ$“É0£È‘Ž\sd²Å†9Y¸(¿ØX˜˜,˜ù™™¼¸àEZÍVöíhV)½ÕÜÌòÍ›ùZSÙÂñŒ´Šb ¨ArùÃ?&h•JHú²p]™^ØöþóÎãÚÿ˜§ï¾[ýŽ£„L†w¿ûÝã1LsþÇS ?s:ÖÑ)5Bžç‘ÏçéîîÖ/˜F£Ñh4²ÙlX§RÆŠ---¡€‘Íf‡­ÉW¾I±R>½½½=ü.5,£Ût§¤ ò'Ëj~´¶¶–ˆCétšÖÖVm@;4æPRZ[[C¯··7¬I[ c©c2–u,Ë*i;(‡¸X,†ëºäóy<Ï#Nãû~Im\fª2àÂÿÁÓ‘ËùÙgŸeÛkÛøÕÜ_ñêY¯‚gýŸTzPõS†écÉd |&ø¾Occcí%iÐc±XX?I£ UE¨¡X’ÏçÃh”;v088Hss3·Ür —_~y­gXÆ£vŠƒ\Š„ÍÐhŽCáþd'F{¿0=*VÈçj“t5¾ ‰–NvЦŽwÍŸÏü+Xô½ïáÞpC2Ü™—Ü…Ñ}È@¸’aw¬ÙUBn¨á~*œŸ+—, +:¢âðØÀ±…Žãû¾6â×Û¶q'¬¡T‡¡F£Ñh4æÈ!“É”¼ÿµ··“Ïç«6>‰±7•J…iB:ëw Éd’l6[â_Þ†Cµ1J<Dz¬!ÛK&“$“É’÷PÍôCœj ॥Ó4I¥R%×áXÞé'«@|ôÝÌ4M2™ ‰D‚t:¦,“:0AèÂõš)ã@T§ÿÕî_±ðë 1M>qì'”Ñô{q¸ÐT¢J6;ì¶Äv'жmÓÕÕ>/FªY­ÑTCÕ‚ (Q%‘HÐÓÓÆ Uˆ¾žÓ| ®ëŽh, (:dhå¡¢E”‘Ý>æÀu19ò –YE‘ÅE òX–t]²%ˆ aD¶PŒ¶¨Çì}£pÎÞ°î*–‹¾5 ‘_¥ÁM*•SnÃd2yÈf¥È—(±X,ÌgÚÝ]ÍÑi*¦]ŒÐÔÔ¹¶¶¶b†~¡Ôh4F£ÑŒÈho$mQ"‘#ZFÚ†¤b<ÏÃu]†ÌËd2´´´„…ˆ5Ó›h¦‹ñH5Zf¬Nk•öcš&]]]ø¾O{{;AÉdhmm¥»»{ˆp©ÑL%\·|°ì¹eœ¿é|Ö·NMH\ˆª¡2 Qm‰îÊf³ÚT3®ŒJPX°`—_~ùh”þþ~:;;ë6í—ëºÃÔ¥PûEØÛ¾‹2ªÇQI&€ÖVðÕÁ?Ÿ†T ²Ièê‚TLmÃ,¬Ó‹ªíáPŒ¡ð¹¼ §P÷—ê£\êÓ4« ÿöåïìâ~¸Œåzm_¹¾Gz?3M3´MÄb1òù<ù|>ŒÓh¦0X¸•GÇüîÒ¤¹aË °"²B&SÊRy$“I6nÜXUÆf4ŒZPŽþþþº­£"^.é‘—:°Ì‡çáÇ@×F%Š€ªûaÙ<Äbªß껾¹ä óÄ¿;ª}b£êTƒÁôS zŒ‘êÚŒWN[wÆ+=W,7¯©#ØVøyuê´Ú£Ï¿F£Ñh4Íä32¶K’(Õ¾ •§q£¯{s¹¶mãº.Ùl–d2‰mÛd2™’ñiy,Ëq¾ìëPhg¢éMy ’ñzç9”(+ÑH—W¨ÔFÃË”‹†Ã!¢ |–t·ŠÓhê,ðΛaÓ®H¿ÈÂ}‹ï#3aà¤B¤a†¢'‚i*/÷ Hä–eY¡€v"ÕŒ7ã&¨Ô3¢L–ãoKÂIꋎ£”r!$Š¡g†–¥þ`¨0šA‰)Zû™áÒ°G½ArŠŽã"|¤ã3 ïa‡JŧÑh4F£ÑhjCy}’|>O{{{Å4Zå8ŽƒaÄãÊU1‚°0¸¼ëI*PŽVÉd’x<^âÑ?Ö*ÙlvDñG;ÉMÄx:¶…lVÙ¢æ€tZÙˆ’IåxkÒZ˲P´÷:ŽÊP”J©ùù¼²'™feñ¥Úhšh4‹ïûd2Òé4¹\N5S˜\0Sõ®LabÁeƒ4v6ª/Uôg%cMWW—ŽÜÒŒ;GÕº“ïûCYyàJó°×Si» õ ¬D&3|¿ÍdT:°è˜L‹)##žDåÆô‰Á«ôûkj‡¼Vè+#E)i4F£Ñh4šúAR Uƒ¤û’"àâ-,ï­­­C¶J¥ÆÍ.‹…Q2åø¾ëº:Ý×4&jkˆ wÕà8*ÒÄóŠ6Ç)Úƒòùb”‰ë*QIJ ½]ÍÏf•¸âyJtõ?Só”{¹K“‘æwwwã8±XlHÊ¡X,F:Æ÷}r¹étš|>_’¦y´…ÇóÄ?xð`˜þ¨¥¥˲0 #,Ú­Ó¿Lo¢õ{F^®˜¢KÒ¼{žúÞÕ¥„ùîºÅˆ”\N}ŽÇ‹v"ùÕq‚@‰/"¨D±,µ ¹ä‰¢£®iÅPÓm[­ãûÊ€/íÈfÕº©T*4ðg2Z[[ÇU¤<\|¿ôÜD¹UÈùަ×÷}uìííêÛ¶Šì‘ôi Î•8JKcúÏlVýÅbê·éêRË´´¨séûÅõeù PÛnmUûÎåTGý‰˜ö¼žO~òîZŸæ)KúÇ` ÎÿªS_àª-WñLã3,5—ªÄóÃ[]×Ų,Z[[éîî&‚!5·4šñ¤*A¥¿¿Ÿ¾¾¾C.×ÖÖVëãB4:ÅÞ–‡7— S #•ª|“)å—`Å›{,Vy;šCç«Oñ#“ÉèÁrá{²àš`ÛºXžF£Ñh4FS’™L/ m°¯/\`f ž'žöÐh4F£ÑhŽ`&ã½Ð0ŒºñÒ×L•2!$“Ê®30P:=‘Pï§â+FúrL³Å"AÑ_ ‰tn¾ˆ5QÄö$BMtIE/Q’NL ËŠŠ86ò'÷à8jZ42£½] ’ͪmŠ€!BI6«–‘ébËeójkÛÄÉ'Ï#Ÿ_FúüÃ?ôÓÑÑÀ“OGkë  h±JÒ¤µ´kÇb¦i’L¡X”H@,pÿý›X±b†QŒN9å”}\qÅÌP\ò¼¢ î‘G1ŒoÐÝ å¬³6qàÀÓd³?#•JaYFí£¢Sòø¾O"‘ 7I¥ÀóòF€ãÄ8㌕ÖËu%F®3“ ^ã§?}C­/ý)GX@öW`V#<µî)~Öø3æ¾s.+­•L•¾ ‚JkkkXR —Ëé4_šI¡*A%ŸÏÓ××Çm·ÝNëèè`õêÕ477×úFÄu] à ¼1¿>D=¢áÂËójŽ„ºé«Œ¤Ëç‹bK´ïçóE‡Ñi*¥)Ëç‹Ó¢Ç”Lªé]ƒ/‚ŠÞ?ù|^†:‚¹>¶ éô *~áÏBU7Óh4F£Ñh4ÍCÔ!uÃ(¦Ì;Œˆ$":Ê6SUMf’‘ì.¹ÜÐõ C '"òD‘”cP*´ø~1CìOŽo~ó äóÙ¬mÃç?ÿ¯{ÝF.¹ä!6lø ¦Ù HëÖ=ŲeßâàÁ×áûâ3Ÿ¹ý×¼ï}÷“ɘÜÿY¸îÅ<õÔ6b±¿$º»=.ŒqñÅMÌž½?þcÃ0hl„½{¯ãž{ndݺØ6¸®ƒëªùž³f½—3Ï ð¼“‰ŠŸxâ¿r×]ˉÅñãßB{ûwÃãïêêÂu“äó>óæÝÆÝwÏ»•-[zxõÕUx^6ÜÏŸýÙ’É|'‡¤þkoo碋~ɶm/óôÓ¤Ó×A˜–ð©§Vñ½ïÝÅúõ÷a[¶\ŧ?}.MMÃ3Ïü¾¿SO}ŠxüOÂëmÙ²eükÀLâ•>}°–@ìD0fÂowÏå=+ßÃÂõ ÕÌTJ]ä‰D¨Nú¾Öäíîî&©¯¢£5“AU‚J%n½õVÚÚÚê^PX?#Î/’p_•™Ÿ*•uM© —ŒÅŠ!œòPL$”Ð"!‘²Xž•Ê÷ÕP¦KîLyø«‡‘Ú‡x(½è•Lk»Hd´¨–x'ˆ’_Nt}l¢pˆUA´òs`ày^‰'ïû¤ÓiššVàûjÓ,~$$´üþ'ž2à‘c—uÊõÏ+þfrœ"ŠI®R9tD‹ŒE&:Èeüð€Îv¸v£ŠPIŒUMŒâ  ”É5è¡Ba\àPº‹_œÂÿTá³Qئf4F£Ñh4f 5¨¦ÓÅÈÇQ¶ß/¦|ÊåÆ^Ôüp³‹W²5Hú«J6©¥Rޤ¦²mµM‰81Œ&>ðÇ8çœyÀ÷Y¿ÞaÖ,‹ùó“H ÐÔÔDd³q|ß'“Éð«_=Æ×¿~/‹}“[ny'¾¯j ¬gÆWÙ²å\~õ«/pÝuF àyAà8÷Ó[(fbš&ïz×÷ø‹¿x˜ÏþR>ùÉ«9ë¬Ùa}% 2x| †¡¶eY7Ýt7_ûÚ³üà櫓ñ'átÇqhooDz¬B “»îº‰öövÎ>û¸ñÆ9ë¬%üìgðXÄb±ayãñ8wÜñ)æÍ»hÁ4ÍpY±Q¸î" ãc'мë]ßã#ù9ç·Šûîû©TŠX,†çy|å+_áä“O>¼ âƾ¬»œ¶Œ… iliT3M3T3ÛÛÛôþù|ž|>išºn²fÒ³ r8ô÷÷Óßß ­»"óš››ÇE¬ñ}Ÿœ@láða–Q$gc¥é£E„’hH£ìEh¡@<¢mÈ狞ÑN ä¡/bG>_üîûŃ*²\N…xJ­Y_òbFóg&“Åó! )•|”Q¶<î¿ÿU2™/óñ¯bpðš0'©m…#i«ˆL² ×*‚H{LS­'‡;9VëF±h˜ä$•eòy5-‚ª®µÍTJýŸî÷è‘úftþXûgœ^ø } 5T<”ð!^>¦(œˆ¸’+,×ZøœEåÞ,|:…iÝ…ÆQXÎG‰-Naºˆ-S™b4²fŠ2ÑýS£ÑŒÉÛj4šêÑÏα“N§1M³¢T6›Å0 ‰étšD"Q2®WÚl˜‚¥Ò2ÍDõO×u1MßWvP6P¶±´¶ŠèP­h²”[•.чE©”Z?•’h›‹ ÒÙùφAooo(654lãê«¿À˜ …ƒX ~ÿ{H$."Þœ}öWpݯóÓŸ~6\>šR/VŽóå/_ÉùçÿœÏ|æ^®¼ò¬ŠG*•*I ÿÅ/®æÞ{?Êúõoã‰'rá}C¢GR©T8Í4ÿŽøñoá´Óžâ‘Gþ‘³Î:ˆïüƒÚ¶Íü;O=õu íXw·RšÀë®»š5k¾Ç}÷ý K—~Ÿÿø/*òå#ù==={qL"“5¶•KÝœYø’€yßÇ1§]^®;ÁÇrÝi4“Á¤ *tvv²bÅ úûûY°`ßúÖ·X°`ttt°bÅ 6lØÀÚµkY½zõaíï÷sæðûæóå*3LID9cTäY!EºÊ£N|_ é´Ú§D¯ÅãÅ»DbHÔ‰D Èm$"E µaÛê{kkñs>¯ò†f³ÅB[PŒœ±FÄ–XLýɺ2-—SÛM$JE¡|N=uÙìѼå-»xì±¹œqƃìÙó7<òH#Ž£òuJdM4ÌUŽC¾çóÅã”sÐÞ^Œb‘0XQä£çƲŠ9B%âŠQ+¹\Q´‰¦QËfÕyŠFö´¶–nß0`ýúó©0þ›rŒÔ7q韯z`ÅÚFUá£Dˆ£%¤ˆxbí…ÿò,5QBKe⡯°ŽD±HÍÌè˜Ë,ìÔC=Nmi³´ƒB»â…ãŒQ…ÜÈñ»…um OQ2Pâ‘SXÎ+¬s8ï¶yŠb´CÚ›–‡QXÎDGþŒ‚ÉèŸflLöØV£ÑT‡~vQÑ$Šd°m›D"A6›Å¶íplAèE.†¯òe4š‰îŸ*BÙ-¢—°dèÈd”³d=–Ö1Íѧ…R†¢ºÅe—-à²Ën²Îùç/"®äo|pH*n±£”sâ‰ÿ‡£þ–5»ªv½îu ¹ä’'øïÿþSò u"‘(¹ÏsÌ_rê©û†Ü3¢‚ZÖ` PçŠ+NäÄÿžÇ¿îΛ±X Û¶yÃöò­o-©:EÔ¥—ÎçÒK/åÉ'Oá»ßý£ÑýHSˆÉÛz(³€óKHd`û3ÛyaÎo9·á`2ȹnxQK¦“|>mÛø¾¯k¦hj¤ *ýýýÜzë­Ü~ûía{Û¶éììäú믧££ƒ[n¹…¶¶6úúúXµjÕa§ë{Ë[8æ‹:õOñXˆ– Qo?¢ûH§ÕÃ\ŠY– õY(FO (!/>,7n,n³\ íê*Fsȱ¤R¥!ªR”l$$­˜ <6n,õ ç`<~>MM[xË[¾Ãé§_Íþç+üã?Îæ’KŠa¨r®åAÝf4ʤœƒ+ãHD ÏEÏ}ù¾ËsIÝ&¿‘e#ÉQ:0°xyìHp¨¾ vÿ €¹£-H_ð(ÂG ‘kœòh¡EñD°•"T'’Hú¯ZàRšrL>÷R*†dQ‰ˆ&^aY‹¢ðJÔh,+Q8έˆWÕ’§(‘ÏB%þø¨ßGD·ð8‘ýuQÅ2@²ðÙ§ø;«ÖAïã“Ñ?5ÍØ¨ÅØV£ÑýìLÓâýë8Î°ãø¨˜’“X¦Œ‰îŸ^!ņd¸ˆÚ8Ä!Ÿë•Ñ–œ•‚ï£]ÇuM¾øE³â¼J\pÁL‡QñüóãŠ+vŽª®ESSSÅ6Œ´·½í´0‹ 0¢ b†að±Áã¯àª«ªk—aÀ™gžÉ™g21õ`ë€ZŒm-ÀÒ°…,d?äZ”ñ¯¬žµeYäóy‰†a`𦮙¢© U *ýýýttt”L»óÎ;‡„´­]»vÄm´µµ…àòË/gÇŽôôôÐÐІ’-_¾œåË—ÓÓÓ3fµó™íÛüÞu|hJÏ+ŠŸAPj<r•D€®.ÂX™LÑh/bG.WºžÜ+òùê…Yn$¢šmFéÀCÖ1Œ¢è#Óo¸a_ûÚ²oß|ãk¹öÚy@éyîTkç%Ã(mgT¬’ßEÎCGÇÝÀÔQ©oãÒ?=àõæ(®b¬ïªry‰Ì8ò»Žf+´çpîYŠ1’J,A1²$ (Jˆè û.'*\$*´+:˜Ž®/éͤY£xÒ‘c¬v0îPŒ*õ]»¬Ђ´¢ûê¥( uQâ…¶å Óò Ô¦1“Ñ?ÇJ…Ofš3Ùc[FSSêÙYÇÄb1\×"¨Èô(ZLÑTËD÷Ï °m;Lq^N­m ÁX¢Z$CÊhlÑâ`;.»l†±`ÔmmÐD$yCêùGŒ^X“ 4Ó•ÉÛJ¢‹Í>dNž‚ΆNVÏ<ž¢´Ðq H¥R$“Iº»»µ˜¢©GU³äÅëëë ÿÚÚÚèïï/™Ö××7âvÚÚÚ¸í¶ÛÂƒÜyçá¶Ë͆††0gßplݺuˆÐ#ü•`=ÈhÆs’f+.æÛ”Ô\…ÔW‘hÓ,'¢ƒ€hY¯±,زe†apÅpíµo©u“&„ŽŽÖ­[Wëf6#õM`Ìýsݺutvv†ßWú˜;rÈKáÿh¼lÌQ.?DàH2T´ñ) é²ù‰!鯢÷"‰ê(¦è’ÿ>ÅÈŒñ>ŽJ§=E±NŒ9ŽöŸ¤[k§Õ’¦ºˆ–X…ã0Q‚I¥A¿D±DSƒ%"ÛÉö[>ÀΗžûþþ~~üþó¶ß6Î'qò™ˆþ¹}ûv:::Æ'Ïou=ˆ(êzI×úÌiꕞžÇaçεnÊa3Ùc[f¢ÑcÛÑmyß”¿tZå;”Η˜²^:­¾—/ÝFtùJû‘œÃ‘H$p"îè’Z¥Ü3[Ä” ´˜2AˆƒëÖ­[kÝ”Ãf2ƶOï?.¬«©ŒÔ‹í:£=§#Õ„ŽòTmÕ`Û’å¥úær£·õuu =zl[ÝØ¶|¹|áï_ÒàïRðým߇§ ª]2©Ze¢I>Ÿ¯XG£©Dgg焌m«ŠPY½zõ¸{êÜyçtttÐÖÖÆêÕ«+¾8V26oÞ¼ŠÌܳçpuÛಪÛ%…ß C¥xš,±3Zd$Dp‘uêu€ ÷¶D¢Úð‚©I[[›6mªu3Æ•ò¾ „ÞBQªéŸMMM¬X±(غ}¢!¸Q¬£æ‡QiF2QýÁB ÙB»2÷Ñz AaPe‰Ìcñ!êÑ2œwËd† ‹˜“)´Ñ-´Ù.´O"Fä%ÿ«éÞ±QN¯fY‰F’ú-¹â¦ [tí"Î<Ÿï/üþ$žÈ‰g¼úçœ9sÆ/­‰:ÿ^…ÏMš››Y¾|9/¼ðB­›2®LÆØV£™hôØvd¢cÛÃe8[PwwåÏÃQÉèXÍzÕ,#Ŧ%*e¸â¿Éd’T*E6› S±hÆñ ÿÍo~S릌+1¶õ}Ÿ¯ÜÕʇ^룫o,kô‘b/ c‰6 µLá¦Ç¶##cÛ†††!óT„JÛßnâéïâšE×ÀË«TŠPG~\Ó4±m›l6KW×ô¶7jƇ+VðÀŒûv'½(ýàà 7Þx#ýýýÜ|óÍá c¥ŽÕßß_fV‰ùóçW|é¼×‡ÁOËÕÿç„Q·±N5¦Y]ÎËèCb´á™šñ§­­m|<¼ë€áú&Œ½655•,³b •OlùDш1àÛ¨ôOõF %ŒÈ€ÐF‰-ÑÁ›¼?FêöÔå±D‘z+"øDSœEï1fäÿdXËïs2ð¶9Úžæs™;w.ÜñÈ$6tâïþ)/ãB½$éÚHût°Q¿ëj"477söÙg³}ûöZ7e\˜¬±­F3è±íèÆ¶G¶m‡i¿Ç!—Ë )œJ¥H¥R˜¦I2™Ôè'€ ÐÖÖÆ­·ÞZ릌 9¶ÝxÜ)Ì>úh~lÀÙ¨áéh|¹ŽÊÓ¹Oä~&Ûnåº.©IÌ˥ǶcÛJö¸“ ˜û7sùåÀ/yò¸'ᇠØã•£‡b”¤ã8U¥tÓh@¥¦kjj÷íV•òKèèè೟ýløùŒ3Î(ù«æ‚¾îºëhnnÆuÝ’µ|ùò!á_;vì³÷ìMY˜yài®ºj|<ˆ4šéÎp}ƧÀÒHQÀ%³—Sb¨šê´+i³2ÓvMuÊkÕX(¨^߃%%˜9Â|“ú¿–FÁD÷ÏÃÁy$Ï'€–=tÀ<ÜÓP¢Œ”+¥ÌÓh¦“5¶ ž7Ô+4Ô_>èt?ÍT¦žŸS R†K÷Å;±X Û¶I&“µn¶¦Î™Èþ¹ùþ€¿È“dQþ{š# mp;“9¶ýr3‡~ðì˜Ý6®2Uzž Þî¶mãW“ÞG£™`ªŽPùìg?ËÏ~ö³’ðݶ¶6n¾ùf:;;¹óÎ;¹å–[FÜFgg'ƒƒƒ\~ùå%žOÍÍÍ´µµ…EŽÚÚÚèë룿¿Ÿ+®¸bL¶ 'å+Àwk{†5š)ÀH}s¼ú§ìs€œ¹þL%H$Q‘“ñ J¹0T¯bÊÈdôϪñQ}¶à(äûàow¸·CïC`<A; ëØäJmœCíC_š)ÂdŽmGK:­ûºº µU94Èûg.W¬ó™Ï+ÏQ©ç7ѵ5šÉ ®žSIû•L&+¦û*'—ËÑÚÚJ6›TqÍÔa"û§lùá…XTCδv¦/œF3‘LöØö\µ ~úŸá<ëÐJ£¤Æœ–¾ïãº.¾ïkÁLSsªTúúúèììäöÛoÊÕÜÜÌÚµkihhà3Ÿù ·ß~û°Ûéïï§¿¿Ÿ5kÖ”L¿þúëY»v-k×®åÆodÅŠlذµkײ`Á‚1Ø/bykË–ZŸ_fJp¨¾ ŒKÿ|´à©þñ]W£ÙJTÑé€4ša™¬þYg ä»!ûXQ÷¾x£êÞɸ2äW€ñï¨Ô`>*JEÒý JXM­”¦Ì;ÜöJDStš6!')î<ŠN2M–—O©ÂruZÃL3¹LæØöPd³*Õ4¨÷ÏXL¥6 ظQM÷ýÒZ| ún6«Ä™j}fªRWÏÎi€*Õ6 ƒ\.G{{;¶m‡Ñ+íííC¶Ù]M!Í´c"û§ ý?3°ÿ½8ÍD éôkç‘ÁhŠÒk†2Ùc[×w!|üÎnkhà’'žPÚ µ¸,ËÂ4M‚ Ði%55§*Aåg?ûmmm#æÅ»þúëÉçóôõõ »œt¾áX½z5mmmô÷÷‡Þ cÁæž²_ßH5š*9Tß„Ã€çy<Ýø4ËÌejF½×ÑhjÌdôϪñ€,ø«Áþ$wBîye„-Ïìºj,ìûà<Ý÷ÑŠzÓ•ñoõ†ë¢ ùö%ËE¢b 2ß.k…õÛQieû"šˆˆ›),ï>Ër’"£Ž3|ûN–•ÔIé¶¼Â_h6Ö“:C…¨<u3}™¬±íHø~1…WoïÈyÊ+½{ÆÐ:~žê¹ÝÝ --ê¿ëŽ­ ­F3ÙÔÕ³sŠrðàÁðs"‘(ÉTaÛvè].:?:½Ò2š#—‰ìŸ?waáÒ>àÍ%ÓS@5„³Ñɦ3†.4|XÔdl;NÜö(ïÿË8þÊ+‡T²Ù, "!5šZ3æ¢ô«W¯fpp°dZss3;vì8¬G‡ü¾G½ü²V,5šqæpú§Ø^^[÷;ß¼³Ö‡¢ÑL;&Ôä Þ< ‚Böƒ{+ |_}¯d\µ,åõÞÝ­Œ½ñ80¼< ˆˆ"iÀ¤¶Š%2/FQ`õ&œ¡-b—µQ¶á–}¶(F©H´ £0M<ò¥¾SY. (ì‘mû‘í…ƒ¡¢LTØF3í™È¾ÙÚª"Mb16^6Ë‚H¤X*¥D‰x‘e4š©ŽR4šúe,ýó×ë_Á8ðRÅy9ÔÐ,‰žÙ(Å,ÌÓh4Õ1^ÏN7v‰™pðÀŸøéOá'?~´âò±XL;ÎkꆪŠÒ744 Jš››K"Qéëë«õñð¨'ð;-¨h4u‚Ø38Ðy€¹»çÖºI¦ ’Iå©NpÀ3 ýtpûïF^7—SbŠx¿wu·E}ö¶PŒ ‰¦Ô’´_="ÂFTT¢pA¡m–‘T\6Ea†Èú"ŠH4‹Ù–GÑuÑo C#f T¸ñ)Ö•q)Š3E‚²¶¸eûÏö9na99ÞlÙvœÂŸGé¾5Ó‰þÊ畘’ÉL|ÔH"¡¢_2ÓÞ®j´HŸÖV%œj4FSK^~ý1¼­mCÅyÊ/&G±®Š ó²Õî@3%жÀ©Á’B-¿`ì>ú15°Í狹j#A@:&ÐNMPU„Êå—_NGGwÞy'—_~yÅeòù< , ­­­ÖÇÄ ¼ö ,ëïkÝFƒ°ï‚ã ¿mfÏ7öT^Ðó”EFÓhjŽç)íi"Ì|pîod>¾9r«ò÷©ã`wÀx r)ð|È~Ì× õ‡à>±½¨DïG…6Øk°ø…zIðÏ€ø‡ w¸ Ö!Xî" Ü„®£!}?°w@þiN¯Œ9º Ümà= Ý6Ä7ƒySAü™ÿÜsÀü)¤ÿŒõ`œ ìÔ=lóã› þ àÌóÀü ðÀKàÚ`¿Œuªm±[!Ø Ö¦ÂI*O &bQA(ò? ÞFµŒù8ð)à80®„ ¸Ü{œÀ°Ÿ>æw! °2—@zxX'‚¹ ü_A° ŒAˆ½œ9Àvð~Ö`¯ƒìv°ÎëÈïöƒ¹8R'Cö>Bê£`´©ë ûqö‚ù"¸ù,\a¾ço­õe>å:)–¥¢E&Ó^ ‚ì7Vý9™T2Ù¬ú¯5FS+æ®{݇pÞ“”_R[”¸’¥М@ -©Â÷hfYPªþÑ‚ÊÔ`¯{¶A0ã+¼zÌ«g½UÍ(ûý²Ù,ŽãÉdtJ7MÝP• ÒÜÜÌõ×_Ï7ÞÈõ×_ÏêÕ«Ãð.)XßÙÙÉ-·ÜRëãàá4,~ö(ÝÑ4šzc7ìÙ³‡}ó÷)K¨ïOÄåVpõ]÷gfÒH§Õ86+t½‡Þÿ{H*cU•%Kj¿Œ,²H7îêVûÈ;ÊÛÛ«ºº» ¼' ù{/ä7 æB0>¹s!½ ؉+ Þ¢J¥øÿ öQJ@~ öiàÿ+X«Ô÷Þe`ü!t[œl‡Ø]…F5ÿ~ ì}á&€ÍbiHw‚óôΆÌMÜ< \œ]7÷0g÷°žï\ðÿÌVðûÁü£‚fò}Þ­·‚µ¬w‚ùIð¿™^ éƒ3 ÌóU3cø B$‚¨[(*ÚëJpgƒ¹Ì÷ƒq·:çnð$~ö‚óÈn7äï[`‚ýà€õÈæÀ\ æJƒñ µ¿Ü0_RçÅD]'ÞOTÍ·(A‰ÍàÜ£!· œ» ëGÀ`6‚ñuøå£Ï±m˶Z_êS)¯ê#¿jI,¦þ¼‚…É4Õã;›UŸ C /F£ÑLï:§f€IDAT0àÂiíªZ>ú˜’²žyŠ™ec@kaºøùdÐõWê-¦Ô?Ñ Í¦ lxÕöjeu%–8޲Êd2ê<®ò²º‚²$uuÕú04šiO<à©®h¿GuÕD!%×»¾·pmaÙ4ÅðÁÞ½0s&½3föY¬ˆðB#E°¥Þ xµÇbjšiBÌZ!x‚ÿó#Ð-uT\Ñâþ.°¿ öµ(÷B¬ta¹$J1Uƒ.à²ÂŸƒ¯E¥û*¯}(ß °_†Ô¥`x`É8Þ¦X °ß¨þË zLrHÄJ—“U3× 6þÓ_8à?ܽ©ÑΣï©7–*êÆ¦˜žÉ0À¼¹ð9[Ä2× ÝvùÏ)‡d_[œf¹pƒ ˜——·¿gözz¯îÞ‘B¾©$"F=F¥µUMO&+¼×h4f"ã´—¸è¢åcÞFùP0*º*C«¦>ЂJý#¥Ìc÷bÏ™{w\4ì‹O.—Ã0 RÚ[GSGŒª(ýõ×_Ïõ×_OOOO8­¡¡¡¤–J­ñ >µÿ­½Ù5šzÁžuÁ8n"Ëjïôbj/ÏS‚ŠX‰B—x îÐ9õÝ÷‹L&•…¦Ö.ºÍ4$ <Àůƒ¿¿NŸ Ùëà™¿VÑ1”F£PdÝ:Rßü& ßÇýÌgh½ä¬™3ñvíÂÒë×Óõ½ïʪ¾YÀ€êêÆ_¦y„uLìÁÞ@bJé‘qvwáT‡-K¶(ª#éµvÄQ>T3ž—dÝÃa·e¦¡÷a €ìS›àÀ¼‰¾}†º½û)°žŸØ}Mw,krS{.½7_×UbPKKÅTØF£ÑŒ;s–îªu4u@ww÷áoD3¡x€Õ ]_¼ž3™1sFå埗·, Ó4éíí%ŸÏãû>¾ï“J¥H&“är9Òé4¹Bt@ù}2*Ö ¨çy††×AΤ]"šD—Éf³˜¦‰ëº$ ÑC"˜˜¦‰iš¡P$Ÿ³Ùl‰ð‹Åð<Û¶KÂ|E$2M³b»4ccЃ= áµÏA¢þïn¸øRåE”ÈçÕu]Dm†É”e˜?ù ]ßùÜx#à›¦ªŸ‘É(kªe…UÃ(ö—QæÆ H}­Ögm|‘H•©ŽSŸÇR ä6XouSÆB4ZɶÕ#4™Tߥ|Z4ã§F£Ñh4£e»ó 8eB¶o¡f<ŸšÕÿ¶º³\×ó[þô¯þ´â²–eiû®¦.™v‚Êv`Μ]ÆâZ7E£Ñð€s,¸¢ó Žyó¯Æ& T¢`eòÒi,ËÂ÷} –É.xÑKÔÃÿ»æÎ?úh(b°7M“ûä'1MÃ0BqÛ¶9úž{`ö좠"žöÃåaÉçÁ4éÿ«¿¢ù o…Ã0ð³YÞÒ×ÇÜÍ›!—ã+_ù 75aÛv(úˆÀ`V,†ã8$ LÓ$›Íâ8¾ým>ÿ½ïqÚߊB*+Iº/yd»ººp]3øÕcñ–k¯%cÛ6V6ËË'žHãöíÜüöÒKY¸reY"íÛXH†/âI2™$•Jáy©TªDØð}?Jd äû~x.ì²ë¡· Nù¾î”wŠëºØ¶ã8ضëºá6‰D8Ý÷}=ð%I l6àŒwAp"Øà_.ÎËóTdXY1„a3Ù „mTš0° 3•*--bšJHI&‹‚J2©¬¬"`S„a4ÙÃ4“K"¡³0ÑòbÓ ¹6\âñ¢Èâûjúx 4FsdDÆŸãÖü5šñÁG ”Ïu°ÿ¡'y{ãÛ‡Ø3@9bæóyR©”®Ÿ¢©;¦•  gžyËz7´ ,=]”>ýò…ÿ‰ÂJÒ›¢dê¡ Ê:(‹~Šj4c¢m 2÷þè°ò—$“Ib±¾ï“N§Cã»ã8%†(¦”ÊX;¯¸‚óW®ä>ß'óÉO’.õ3™ –Åq?ÿ9ÿšËÑ6{6ŸÍçÙÒÔ„eY¬ûÆ7˜÷½ï±þ|~zùå,‰ÃN,†eY$“I2™LÁáyžj¿e±§§‡ø§>ÅçÍ㪯~Uµ5“á•nà;w2{öì0=šnRAÀ§^xæÏ§é=ïQ–§¨U9W†èB©f¤Í‰X Òinøò—ùëï|§X´¯1°yófZ^z‰¥³gs~a`ãû>¦çñ¡—^býYgqÇu×…‘3ݹäóØA ¬aAZÃLi¿a(˙몶”[ ÅÛ²Â:f‹Z"‘À÷ýpÀeÛ6A0ïŽ;¸{åJæ{.sçÎÅíëÃ0ŒÑ¥r;ÂÉ`ß7àÝ?‚¿x€õHÎO¨”\cÌ_›ZQS£°/—²,]’ Ð÷Õg¹æ £˜Ì4‹)÷ µü4Φ«ñ\36Lsú ¶]ª•f³ª[KF@ßW7¹¢Ñh4šC±Å‚³ÎXUë¦h4šCþö{9jï³¼þ¼Ê¦é B§R¦Þ˜V‚ŠœkÁóî: Œb’,ÅØÌTá{®ð?²îd€8Jdq) ,1”Û®²’æQ"M¬ðß*,ïÖ•ýʾãU±ŒF3p~ žbõûÞ7¦õãñ8]]]X–¦ä’HÃ0ˆŽX,F>ŸÇ0 òù¼zœ>ç]v'¶—ol ‹›5zø>±\Ž/]Ê®ºŠ¦Âr×ü¿ÿÇ+ßú'üîw¬¹ÿ~¼¯|…0rÅó<òù|˜f+‘H#>,«dzù@À³,f™&—,E’Þ+õÕ\-^ú•¬H™ _*DxTòä «K‰âÞ58çóJØðÖI$Åš ¦ÉyeÛ(7M³Y>@ùdn¾€\¡žˆëºX–E>Ÿ'—Ë…5 r‹±íÒ’RP<69f(nK¥J»Ò|Ç)Ö­qœb{Ö­»„¶¶ýµþé5fTœöiâL\Ê´£Ñh8°Žz†O 8aç —Ó©¾4õÌ´Tàcßîãè?ø…&ÒÞ9\_7(M!V æ_3iô ÿ÷Ïò¶9{Gµ^,#‚° »ÔF¥ýÐFt˜¦INWÄÖLÀ¬àæÙ“»_ñwH¢„%¬$¨²lYÔBµTF©»zTŒÞ'L³XÄ¡±ÚŠU7jyÖL8Gbº¯‘KOº«ë*A@Ê(É%íyª;ˆö˜J3QŠhÝžˆŽ£¶-ÝL‚Ù2µ½L¦˜’/ŸWˤRÅ®½Õ¸nQl‰ Ò&n¢mòýbÙ3ÑO‰ÒuEÕ[™m«iÒ5%û¦|no/Öá1ÍRáFÚàû¥8å|Ás&?Õh4š©Á)ë_!˜½d¶¯GAÍøàjÀ²«Wcwÿ¯òrbÒhê‘i%¨<âÁœŽE$Œ³Ç$œx…bÓét:ì´ZÕhŸ}Ø<ÀïUwˉÇãär9’Éd‰R¯}qÊD¥h4UpÇWàæÃ+•2f¤´Y• ³•¢‚_øìP¬»Px±«i)xï3Œ¯Ãpý¶|zÔý¸sÔ;[¹Zéû>Ùl¶ªTèM­¨™ 288ÈŽ;hnn.™ÞßßO?ÍÍÍCæŠþÎ|––-ÃG‚TÀ÷}\× ë!ø¾O2™ ¥“Ò‰ Š ¦† ×7alýÓvz°ðÕûxûÛ«Z'‚ •JašfÝŠ)Íd3ÞýSð\ ´| ’oV–»ô;±çåP‚‰Wø“Œvá#E¡¤Ë¶1Q™3=ÔãÔ§4%ƒˆ/VÙ2FaÛ"¼”¯'eÓºL3,ÇÝni‹¤‚xl÷næÌ™ƒUhsÞu9ã‚ xáŸÀ_³èÙ²…¶%K0#më{é%çx¬¹›Ã}ÜÛßϾÈïùòË/sÔŽ\ÕÔ¦j3‚òTšÃÂïæÇïØÁi êÜÅbø–Ur? ¤žRÁšìº.–aà8ŽŠÌd‚Ã0¸ÿG?⪠À÷},Ëb×/ÉàÍ7³øï`ý·¾Åɶ뺬س‡¹ó7,XµŠ9ÿ8Ç>öA°uÍÎ\¿žgW¯fáÂ…ü~Æ 8ê¨I¿Æ&’ñÛ:§HÍ‘ ´Zp¨²bÕ ÊŠLÔ³S£Ñ>ãÝ?—,ÙTëCÒh¦ a·-áÛ°~ñzαJ•P§Rè±¦Ž©™ "E¥×®]Nëì줣£ƒ+V°aÃÖ®]ËêÕÕ›íÂ9¯ÎcÉóG¡b±XŒÖÖVlÛ&‹aYn4ÙðD¢íÅš:¡Rß„±÷OX¸kç»ûèå )Žãàû¾N©¥ÑDïþ)ø@ã±Ðû¶8Þ®‹\CJŒ?ƒ¨Ÿ„Üò¨¨JrB¢Gâ?ù›¿á+Ÿû Ä©Tj\:¶ïûxžÔþþ‚ïsuÍÈÇXðižïûA€iš%j®Ls]7¬C‘Ïç±mß÷ñ}?œî8¦iâû~¸Ã00M“x<¦C“ö»®ÀmÛ-²œlÇuÝð|Ú¶]ô€…ðü˾<ÏÃ4M à ŸÏ“J¥ŠFÏ+ÙOxž£Qð®M¥RCΙl7ú;˜¦nSΙ,'ž¸À¸8¯7Fê›pxýóŒógsàÞOß9ä²®ë†×q¬^Š k45f"û§°pð¤_JU½Îdà8Éd’…:'r_‚€„iÒŠJÿâq.$ü³)›Í†µ˜b±ù|>¬Ë”Íf± Qvu‘ŽÇ1m§ðL¼Ä²Ø˜Ë±2cÉã“:åš_xÿË_&‘H`š&Ùl6|¦]iš°aWf<®ž›K–„ÏZó¼óÂ4WGßs‰Dß÷Ãg‹çyd7‹ÁÁóØ~Ñ\¾¿u+v!o…¿gzŽ>ÿÏ3«Îa÷£[JÚ"ËUjßN=•/ÌœN“ûgôù{iá%Ƕm À9ùdbzçÍ+î«üØ ÿS@¼ð?‡zrŠéÒºËÖoص‹_ÌÕgFå ˶z*ÇO“¥‰Û¦RcO٠αU6ÍCýf&¥iêÊ—Õh¦ ýìÔh4cg"ú祗þ è0–sPI§(y_%׫äs•ܲVd¹ ðÝbù&˜«Á»ÒgX› ³6P ™/›bXt¢0-iŸ`9…ï1†Ô”€Â6Íaæi4ãÈDÙm…].\´l=Þ±çË{šFSÏLº ²|ùr Þ“B__ßE³¡¡¡â6ÊÖ­[éèè༵kyÞ¿~ü«jG¶Pµ»»ÇqBã†tÜh݆ÞÞ^<ÏSÞ£…¨•¨x"„D:Hˆˆ¦i’Ëåp‡öövå©jšd2œBŠŒ/­ýoxá tÑöE$1 ƒP,å *Ñ–e‘ÉdðííítuuÇÃu3™LÉóOÒvEŠÈ3!z)† Çï~ñ‹ ;7BÛÖ“ùÅofsÙÙ&t?£7 '(õÂû@†b­›r1æ_-Â[´ˆÅz5w­[GÞó8iÇŽ =ÎÉb"ƶç]¼™/|{)ïæ‡ Pv—eƒÉþ h#² ÿ3…e£µ‚$%^²°¼Ø‹ì²b¯ÉP´ePö$ÙV¬ðm‹Ø‰(ÛŸ¶™:ttt°nݺiá,4QcÛÎÎN-ºh&ÛnݺµÖM&blûÜsϱtéRllõPÊR|É€%K±xÓ! IÑû E1¿WÄÁ:ø'°» 7€à;~'$Aì`] †œ]ŠE…yDÚ%¹uÓóçz…í”äÏ+l+M©GF¢°ÍèC_æËPÎm"òYöKa9Pˆ(•¥8è”ud{ò»ˆ@¨d(Œ¨ÐF¹LŠ×J®°NY6:À•ßL~¹>LèÛÕDZÿt,ǽõ8¦e·]½z5ÍÍÍ,ÝæŽ]<¼àaþÀþfɲbwí‚r *âj"ƶ5«¡RÎŽ /ÕÕ„ŒÍ›7¶¶6~¼àÁ¹ûÏ­jt/éKœõío³æÄ!†a]0 Y¨¶…zˆø$2(<\¡ÔCS‘J…Ñ÷ìÙæMÓ¿ðÝXûgSS;O:‰sO„ûž½÷šïvÙhßÒhñœ‰ ÑÓ•±ôÏ9s攄fû¿…]?3²¨p8Äãqr¹\x/ ‚ Œ‡Çqèîî’®A¢D¡ø<µ,‹7†‘œæ4ÈôÊÃÓ¸}ïÜz3pw­›S5à 4bp/çì¥K¹bæL^80±ÂQ­9œ±í¾ÆF6ˆG¬†ŠP¬Ô^øÞMÑ6ãQ´'ÄãÕWé~ðAŒææ’\bÑ‘oœ¢¯ØlZ( 3iŠ6&± ‰3­UhWœÒI>£8äLÚ™£h£ð"ÛÑÔ–¶¶6=¶¦¦&V¬XãÀ¨2ÓÊ»–G©WI(õ<eT–Ÿ¼ Ú;Œ¬gPú®§™VÈØö7¿ùM­›2áŒul;þ|ZŸi…ï¢29†>X5Ôúƒf1ßãFµ›,½Ru=Ó„D¦ðŒ‹î/š#Ì:Ķ˽ÊÛ$÷Ù‡‡Høqôa+"…-"PdQîDažiŸˆÑPVƒRA**ìÙv´˜¡[hK*²ŒEb“’ADÙJ̾›” a¥ Ù¶S”e‰ìG¶E!&N1BHÚdG–KEö!÷eêÄÞfAãîF{Ûc¼6ÿ5¦3‡k·mhhÀæþw;-ǵ YVœÏ5šñbÅŠ<ðÀã¾ÝºT*y&ô÷÷‡ÊèpÌŸ??TÞzõ^žüö“¬dåЃâq‚®.|ßç/ÿò/9{Îþð?þƒ&ךâÄ÷•ÈbšH@!…Hyª+`TÞô•¢3€ðÆ}Ep<Ë–-S7òhU^õ¶Ň–lVnìy ‘bþ y ¥ ß%¤T<d:¨‡® Ö»€VЏ¨wDôáçP|ã–mË<7²q¢Þ yJ3²‘eä˜åa/ó ¥!³DÚ ³•6˱D÷!b“L×K/Ò¦èÿmmmÓ&üHŒµ655±mÑ"^~õymÆ]˜æg†]6™L’Ëå´ ¢,X@[[·Þzk­›2ጥŠ ê¶7û.`ÑøµIÒhIZFI…™ÏçÔ[¶m‡Î ò­Ö)ú,Nµ–÷6V|ÓåâàÕZ7eBinnæì³Ïž6dÃq8cÛæôlœI‚û°mÈšE›GtÔš¿ë.bwÞ‰ñ£©“ƒ¼woÎÃmix“E—ï\uÆ—¿\2t2]—|[Éce#¥ÃÅr†Ë%ßJq)ö‡vŠCNqöŒÚ“e8Pê[ŽŽ€_ôØöÐcÛ¹s—ÃÁƒ‡Ø‰\œâ¡.¹“”z›'(*‘1ŠÞì.ÅwA(}Œ:ÍIj!±êÊû’D¥SI§–ϺãL)ôØöÐcÛ矞¹çÌ­,¤L0©ÂŸ´¾—½ëJø±*|fIŠÚ£+%,‘ýpÛîÞEñÁ ¥÷‘TÙ¶*¥N«‰"í}*zÜÑW»ì¿´]¼QäGŠC¥ó&s¥ÛZÊRž™ñ ¯öLï1üáÚmA] o\ Žçî½+)—Tòyõp«&ÓŽFS Ë—/§©©iÜ·[7‚ÊòåËéìì,™¶cÇŽª m `ÎËÛyeñ+J<£l@6«þjŒHß÷•R)_¼iªÖžííj™Lfb+„ŠÐQÎpÓè?º (ºý•»Ê@ÚŽl7_X>:` 7Õ¤8¡ÜEÙ‡b©+²œx6Èç¨Ûbô¸ìÈ÷¨Wõ ¯ô€Œž‡¨'ƒ${õQ&º]yi‘—"ëHøiÔÙ½à=ñÿý¼Üör'iêr¸ýó¡G›xãksG\&‹M sf²9œþ)ö˜3æ€õúñk“Ôç‚bŠMÃ0ÂZ]7n SbjµÈo››ùÍà—ùƒ‹.ªuS4ãÀáôÍÿMÂÅ¿†ø½àïÛÁóÏÏÆÖ·Âå)X‘½KÇ.‚S®„w~nÀ0KQ,ó,øD¦`HMÀWóp¾]Hñ‘€?H¨ñÎùï `aj³Å‡{óÄþ Þ~6æ¦×à†XqììûU+eÂPŽ¡Ý‡ªâÛE[³ø¹H&IM&ËÊ0O†…â‡#©)åE–e;Q_›ò!vY׈´/š.Mœxahà·ù²‚J|€d"&Ee8*Û»Žd.ÇßhvÙŽQ¶®—8G³®<¿xñ!Ó©ÎáôÏŠÁ¯òŽ"Š¡Ôl-Zdª›¢÷ùpðÆ0ó³l¾\ÝeÛ‰¦¬‘÷"'2]. ¹X’…6GÓ券x‹ƒœdE$¥Iiº¤òºòŽmwPö_:°œÛh;¢ËF×ð¢Xó‚²yQOóòuŒ Ëz‘}I¢¡€åé€dºœ¯(ÒÑ%B)êè'7’¨3_ôPœ?oï<¦;‡Ó?Wn\ 7Õ®íbΉ¡ºP+EmBLSšJ6¨C1–ƒž¬5–ýÁ™¨×.êÖüD¸4³Ûj#§;¦Þ©A¥­­;vÐÓÓC[[}}}ô÷÷sÅWTµþzNì?Àãçý”‹[¯ƒ®®âËžiª‘o,†maŠ‘C†‘‰Ø’H¨õ£:Ô4y‘´'.Mʘ©$Îd( ‹„á½Fƒ bßQ¢nÃy*DnÑÓ«0­šÓ_i™è>*¹ZF/‘aÚ¹ø³{çµ)ÃáôO8nFÀ‹§íy¹# 5“F3Nÿ”¨õU¿Û€qÊà-£Þym)I¿å8Ùl–ÞÞÞPH‘Ô~À´^šBŠÑÏ|\÷ð7¦©9cí›{çÍcž¹OAþó»åŸðÞûiŒcæÃŸm,ÍÁL«8žùÊ/ ‹Xa‡X›ð<Å”A9À7á=]yHœÀ/=x _Db×§aFû€í>|!¥ÆÍQD5f¶¬’I)ß'aš%v™jGÓ­kø@QHp óĦ-NúQ§}±Ë)!Cì¯Ñ:3ågÓcXÖïÁ3‹6P –Žl)Ør—€€=ÌM,+¤gß§¶c„öà°f‚·O7ð¨éæ‚b;’`îw®úŸ=Ø ù`Ø/€µ œÅ`înðg@°hk8¯±8­h—οÁ,^c¼röeÄ÷ü®Ê_cjr8ÏNÓ„\ù{C4u—¨T]¨\ž¶çP¼±^·Í¨ ßd¡Ñùò^(FÿhÁn -“Ž'©„ Jâ¤I–)ÖÍ‚ âM4ÄL B‰êQj¼§<(¶‘ 0 ÇåFæËö¥MÒùåø¢žðrLPL•=Ç¥ j4µQ´pT–¢p%ÊnTäq)©ÍQ’=Á,œ‹rozÞ±þ£»6¦ cíŸó÷Í/¡jˆ_…¤=åB“,#Øvéñú¾Z&z,–UÚÖòmH*µ(é²¼]åû‘ãiÑvHR4ŒaQäüEד¿BdÓÁLλïã]t {ÓÃ韯îä+ßnÇ!‹iãªFsŒµJ]ÈuÝ _~iLû– ¤–I4ÿí¡ ¾k"ÆÄFÃj&•±ôÍ=ÇK`Þ™¯Ÿû\Ѧ¢MÔ»f4BØŒN3àvér^WÑ(áRpמˆÃï=¸({(;sÀ›Œ].œÌ6aQ®¸Ï{<Ø›‡K ØfÀo€ÓR¡Á´`Ѓý,+ج/5ˆÝj‘ÿ($nÞÀ=bOÓ´ã”}ØË_ÆÁ&dMä>õ4†¹Vúð?<+Kÿ!€z0ø$ð/@³Ï`†˜w8ÄþׯºñyX ±¿8§h°¶Ÿ»ð`›ð[Øv5Š‘Ú³\ø–' Íƒn»¸þzZøO ÞîÃ.MÁ£˜æ÷º<­·ÅÈüSvï&ظ,U´Ö=äÃ+.Ì À à ޶ažY,´Ó‘'ûÉ3HÜõ Œ¥»ØüëÍ<óÉ ºÀꇱ>;ÓiõÛû>˜yŠªZÕ$ò?мՓ×mn„yÑ Qg l¹r'ºè²r¿ŠF¤D…ÜJY³EÄ‘6”3œg¸D…D3+TòŒG$CAù6£ÇT~ŽD@ªöþ+é²E *¯§QŽ´9š¶ºl¾³ÕáLQe,ýsåÀJêíÔDÇ$“ŸDYš(1ZûJkÅË6¤~ÙhG§è{¶Ôý-Ÿ„ÆlIÙ‹ÅÂïžçaÛ6žçaY¾ïãl3¦iâû~¸¼¤ùM¥R¸®[òP:bÉô|>¾?A€ëºávÇ!‘HÏçÃÿ±X Çq0M“X,:qù¾c>Ÿ'—Ë…ë%“I2™ étšD"A,#N‡ÇÅô²íh»å]'êêyÍÍÍ<ù䓵¾ä&œÃµÛzÀûφ¯ÿ_òñâtÏÃu],ËÒ™K4S‚š *·ÝvÛi«W¯¦­­þþ~š››G6öÛZç²|ïcÃVÌçóCŠÅÃ(¦+ß^,¦ ð# ˜S©‘ &–U4þòaÙžÑH™r‚ (¸ni:4Ùlk8ƒWù¼òýHûd""•OtZ¥sS.Ò”*ŠîÇqŠËeá8A0Ôó×¶‡ *Ñe\·² Rx€.zí5ö3}•J}ÆÞ?\8õÀ|NæzÏçóxž7­ê h4Åx÷O€+ð^ÆxߥcjS"‘k¢T[E3Ã¥"ÕÔ=ã5¶ÝûÄ<á£}kM´ÎŸ+›o¦ÔØ+:Ž’pŽëSIÁ'Ò0§l[¾ƒoïváÝ au{¶[€{·™Yê´}’waE¡Y;£`aá–Tì§ðÞȘó½Fñ¼ûÀŽÞ_>¨ð—”Yêœä{p_’Ø–Ü teJ­^¾ ü§«ÞV™s“§¹p_Þ›+«—h(/õ?pÕ1®AéúŸ5éý£,\ œUpÀ²Ê¶‘-㟨V/Q å¹Ù"õU®5a¸KvÉi>•ïg§\ù¿ÚŒùµw›b°#£r˜U{»úŸJ•ö…x¼øÞ$ïJQg±ÖVõÎ$ïoåx唿çÕ £õ©Ë!Œå±)©§GCl”댵®òpE£¦!ãÙ?W¬üWÚ—§èTYÈ\R2?.µ+”÷E×eûþ'Ï>û,ç­Z@‹ßýêWYýóŸóâþýÌž=›¦‹/æñ«® ņÆíÛY±bgÿò—Ì™3‡ ëÖÁW¿Ö]üå/“onæ®»îÂøÀ¸ïé§éùÜçH/[Æw6oæ¥»ïæ¹E‹X½d ³-bË–-œý†7°éG?âÓo}+›W¬à†+¯ä÷ÞËê˜ B ¼rß},ZµŠ}ûÛÄl›ä¦Mär9Òé4©TŠÖ–¾vÝu¼sî\æÍ™ïPŠ”ïû8ŽÃ›nâäOš­çÖoÞ~;É H$,ضóÖ­cÉ’%¬Ø½›ÇæÎÅíëÃ4MŽøa¶øÃ >ü0oÙÂý¯¾Š¶móÊ·¾ÅŸr Oÿæ74]z)÷ìÙƒõõ¯cÿrÍ5<3c—wGßswßͳ§ŸŽmÛ4~ñ‹|xûv–|õ«|xËõ÷‡LKK _?ïrûí¼ûo¤ÿÑGyó/~Á“ü ÿøÄ$ –Ýs‹_y…9oy ›wïæÞþ~~èÄäó,êèàáÓOçM«W³ÿÜsYpÙe᮹çNß±ƒ;w²t×.¶mÛFßÙgóÕÇã#矞‡-Ξ–…wà wë¶mÃ7MüÁAxáž^°€³~÷;^=÷\.˜9“íÛ·³pûvؽó±ÇðO: {Ö,Ì•+Ãìrë~øCþì½ïeñÇ>VtFM$Jï Q1JÎØÓ¢Ù?ÄyWò!F²˜lúö·yñ”SxjíÚbôAk«ˆÅyÕ²ÂýþÛ%—pÕ–-,XµŠ—/¸€ß67«s*í‘ß7rOó}ÓqJÛòß:Úæ `ß§?Í«?ü! o|ãÐùr½DÚ@k+ûæÏgæ¨sQؾÛOô¾Õ˜ Ÿæãoêä1û˜°ø¼¼[Z–¥ ÒkƉÛÖUʯáéý`þÇ6^©0¸‚€|áf~Ⱥ)f\q]øó30ãC_Ö<Ï#›Íj¯v¦†<ùë½¼{Åüª–u' ½Jj¢D‘tâe$!ô:|[£94Çÿ,‰§¿¯N‹òµ•©Ö‡¢Ïö±ÈoûñáF•F݈)š‘yþùÅ´·Cîý°á!n0±Vg0† E‚¿ú<·˜MXl–ù¼8Ë›ø¾ÚðärÊf•Í0“)ÍŒìûJ·‰Ç-‚ ›LF­“ÍBWcïÞ^•a:xéûd>ü,Ùo,€í!ØæyŬÈÙd@êè¿$ýô‡0÷?‰þ5Äbê²t°›Ç<îEÜîƒØí3Èÿú29#Ì´l7>„¿þüƒÝ»ñv¾žX²1Ì~ûÃA²7þž`æ‰ó÷ün'™[æâô4…‰üž-xëgÁqÇÁÌ™ÄbŤ™ ¤oÜûöaœªÒʤRêœH¢Ñ“D—ôýÒD²-!“Qç+—SšSÈÀv¼‘ PëHШdѶ½F÷¿BòÿC°çXºº"¿ÍÀ46ª`£ÛÈ~sQ¨ay^13uï7ÿp#u¹oÍ&ñg1Mˆ]ù*Þoö“ø“8wÌÃÛ¸0<¾ÄªmÌòµ6,¯sTç*Ï.1ŒCm˜nª0–M¦ÓôööòÐÍ7“.ü°’ `%j,lÛ6]2þìk)pMÙ>ŒT R)†‹?¯ ®ÈH|p)ðÛ^P©²ä/d8‘§Íe’biÁxí5‚~ï‹_Äœ9SÕ [¸káBÜ3ÏÄ@‰(Òl€«¯æ¬—_Æ X×ÅC|I­b1ÌX —¢ïB¸œa`Ú¶Zζ±Ÿz*<.Ó4q2 ÀÊd8êÙg‰vZ8ßëíUÇR!KÊûDìO$-ö÷4MóÐÏÒhv`f,FÃó+ÒÝÍÌlväˆAÍÈìßÅŽ­OaÛ7„“$jK¿/j¦ ÓBPñ€Myð÷|°BçËçóäóyF¿qFsXœµö³¿bª½hF3ùxÀ +fqñ)ïq9 ½¾ûî»éííeëÖ­}ôÑ,[¶ ÏóÂùÑp¹¨"¹’+ ’e}YFþË6%Lß²¬aÓvJÎdY_ò;—ïO ;š)ÁsÜ”;ìÍDûÅHAþ‰H*i9ÜòT©¢¹Æ¥ÏIšÉ+.Ó£¹Ç‡Cæéšj‡¾ÏM»vÍaù‰ý¼ëž“Ø9ïhV_­j«Ç(ü¶yðšßÌBæÏ‡ç\X°y3§Ìz…eËyôÑ<ûìS,_¾ ×íã¤åË\¶•O=Å7¿ù/¼ùÍÿÅùyžzªDLijZeÍÆqŠ6Eß‡ŽŽ¿`íÚ@Ëò•R° údþ¥´_A@:msþõ…¯ÓÀ½÷Þ ü—^Z,šH€ño.Æ®]X-gÐþù«I}`K‰ÍÑœyÆóë1vƒ±p±Óë†0[YþÛ³‰™±3×ã>{:æ¯a®h'86ê<þ#X¢Ò.»ߎdC¡Ï£{n6ûx;Ûà/þË:‹®®Bl'“õ‰ÓÅÆ·¼Ó?©ÄÐéû`çý˜s7Õ,+m+Ñ©;‰ôiDY32™â9Kið<ò³¯ÄùàRzW?[µÑ¿ñL6‡EÑ)•VJ²IL©mð5ØøÎBú=»›’ ßövø)¤ŸþÙ{–Òuóðω0ÓµñÌïøû‡¦}£1ãyU‰Óííí$ Òé4¹\.tðëD’ ÷Ž:YÙNJ²7ä10 Œÿú¯Ð¡¼üNôsùQE·,bŠ|6Qþ*¦ˆ,"¾”Î/[ºÈ¶¤T‘Úi¡p#m)XÔŒŒ¢%Ýü²iÑê¸fdþíEæ%P²Ñ}¶i ÷Ù0ð3™’àXlj¢¡¡ÍȘÀÁ}û¸{ÛÞóe2=vÑL)¦… ü~?øKà­CçNG¢ÑԈƋwsα·b8d^:&‹é§FSC¾öy¸øÆ¡Ó%‚Ì0 \×Å4M¶mÛ†iš †Ñ)‰D¢ê>,…*¡hð+/V9Üz5 A€mÛ¡!·Ü»A„8e?žç…gI%jšæ¨ïabà.7›¦I"‘w4Û“"™Qã·I û”smÛ6ù|>l‡›eYá1FâÃm¿üØ£çHîï®ë†ms»k×.víÚuؿӴåµÊˆœßèï 9§£ç¾üw©V¤(ï?"ÈT*h+"‰üÆù|>Lá)븮¶5Z¼µ’Á?:¿éßåÅl¡xËý¥\d9éÛÒöh]ùy¼•öW~å²ܗdQAYÒ—ÿ.Q!º¢÷½j)oK¥m<÷Üs:Ý×0ìÚ5‡»>†wÍ9šÙó 3Gÿä˯𥿞ñË8î=­K9fáJ®y„_Ï›ÇàïÏS¯¾Ê{,[þö­Ì;—Ž9†GæÎå˜cŽá±™3i~á~qÂG¹pÖ,ž>p€Ó:ŠÁÁA>öÊ+ütÏnolä¸ýûÙÉÿüjw’ÿœ;RÛ~jÁV °ì¯ßÏ66rá=÷0ë©§øã`š‰|qF£ WV®\ÉwÜÁ ¯¼ÂÊ{ïeþ¾}ø¦Ék«V±lpÛ4ùƶ×Áºu,T¿÷æ¹s9î —^ŠïºxÀìM›XáºHÁw羓㮸,‹'Ÿ|’¥»vñòSO1ÿ…x¨±‘×ïÜÉÜ}Œ“çÍ+À÷â¢ê >µ`KOÜÅOûÇ\ÐèèþŠDÒ/UBÆV™L˲BqäPãÐ#«ŠÏ#•÷ÏÞ2 6"ߥt›DË8…¶IûÜHû¢Ù@ŠJ9•¡(’£nd$VDTŠ LѶHws ZN©ŽÿÙ»’Ä;ç–L‹ÇãÚn«™RL AàÒëà„Ûv™./ £yÑÐh4ãÇÖ®½ÌÜÕ‡eýE8Í÷}Z[[Éd2z«ÑÔš]`\\ü*PÇqBï¸îîî0uf"‘¨h¬†è:bÌ«æ0\dJ$“ILÓ$w(ï½Ã@R‡Ê øXˆ^‡óøO&“$ òù|8v)¢'*p” ¢Fór£¶šƒ "ŠÈ>£ˆ18‚ÐTÒcDÙ´i'Ÿ|ò„ýfS™ ýYðºâuæ8Žã„çß²¬‘#‘H„Ñ$“IÔKw¸}ëg|ý!EùýÊ¿ƒÊ3­©ÌãÉq¾Â•ÍàöÁ…Þ˳Ï>ËìÙ›øèš}œ}öÒ°f³Ù±ú‘|žîeËB/é„ix,"^ÚMMÅuÞ‚´/X€<mÐ\eJ§ÓA@&“ÁX°ŸˆÑóôÓeHLž>¿‚ÓO'[´ˆ[~ücåi  ’ò}ݶm|þ{ßã·-âÂ}ˆØ½{7[¶láå™39y`€~÷;îzøaîÞ±ƒsßúVü]»È^x!¦ï3§ ¢ïÞ¼™g￟3Ï<“9sæ°}æL¾µr%K6mbáE±{÷n>ºp!gÎËœ]»˜³k[ššX²s'O<ñlÙ™gžÉ–¦&X°€]»v±ýôÓ™½i¯~:ç<ñÛY¸iwΚÅ1…TCþ¡1{à ß÷ìÙé۶…íúìúõ,\¹’× ðÝÈï°}åJ °ýôÓÕ:sç²{î\¶Ÿ~zØÆß/]ÊÑ¿ú /fîܹpÚiìÚµ‹=MMÌÛº€ýû÷³ý?àu+W²{Áö¿ø"Ç,^ÌœãŽã¥‚ص{î\ŽÝ²‚€•+Ãsgœ~:GŸû`­»AýR!z$šºË÷ýaÓÕjê‹ò_r¸ˆª˜^¾½Ô0ëT;b‰ ³NÏsÏѳcÇdž¦)‡¼eüüÌAî*ë‡ù.§ÑLÓBPqîUþvÑÝ@6œîû>íííX–¥ ^k45àùŋٿþ5žÙµ¼dºDéÁ¬FS[< {ö:°ÎŠE"‘ »»;4æ‹A¼ÞŒ£†aLJ &Ã0»8bTîÁ(­åû>Vù~…ÆF”0e-]Zqw×.ì·¼¥dš_X7L…´woq±«ü8] (´Ñ¦4B`Í_ý¼ë]hã8Äb±ðyMé¥Ñh&Ÿ8Þ…ü&8/òž#Ñ×õö®©ÑŒÄ´Tšg÷³ÿÂsK¦†QbÒh4“Ë®9s˜óø.ûÙ‹H$Îqùñ|­‡§B5cwI:Òür'…j]†Û¿aJLÅúf…mêø JÅr*•Ê÷SÍ9Ô#®ñ!›ÍÒÝÝaZLÑhê„í>¼vêS%÷±f?ÐhjÉQµnÀx°;€£ö`Ó’%%Ó³Ùì¸äQ×h4cg×+àŸ^:€ÕbŠFSìZ¿?LÒÞÞŽmÛ%F©¢Å”ÉAê?h4RwF‹)M}ñÛ7¼`{Œ}³_ •²™Ú·F3-‘BóÓÁAE£™.À™—¾À?l>±dºã8Ú^3嘂ÊÜÞð\‰6N›{\£ÑL'œr,çw^ø]rÁk4šÚâ»Þ…uÜΰ@s4eˆã8aNvý2:yHqÍ‘w×h4õÅ•¿ƒU_XUë¦h4šˆÖ®Óh4õüôª}l?晇=¡¢™ŠL‹”_» 8qÖF ãŒpšišúET£©1/540ãµùìš³+œfÆ<Ïfòñî{Î&ŸÏÉ£oYVÅÚš‰Ã¶m²Ù¬~¡Ðàºîa×íÑÔ1æ¹®[Ò§ËSÏó°, ß÷CÛ÷},ËÂóŸ'“É ÙG6› ÇÑë%‚c—ïû¡è›ÏçI¥R%ÛH$8Ž^«r G¯Gi»l#“ÉN§Ãﲎ|Åb%Ç,ÇÝV*•*¹ÖåX£ÛïÒ>i“´OÖž¯òvʲ•Ú-mŠ®/mÍçóá>˲Â:r|rŽ€’ååwךt:­ß75š:å•çgòׯÿk~ÎÏÂ{¾F3Õ˜‚ÊþßAÓà²p'å4Mmyeöb¶ÿv/æ{ÔËA>Ÿ_¬4Mí™sîb®xû>øW.¹\®d^{{;7N¬ÁH31JiŽ\öîÝ 0.‘Jш§JÆx1žŠV>‹q°ÒA¾‹á*NcÛv‰QÆäÃRÅ0é8N¸îînÚÛÛÃï±X¬â6d<‘L&éêê"ÓÕÕE2™$‘H”,EÃd,+isô¿¤œnT*5ÄP,d1†Êùck>Ÿ'—ËÇKŒ¯Ñåe›" H;¤@kÔ€+Ø®®®!Ë•³´y¸sañxÛ¶1Msˆ±W3”—^ziÔŽr®³Ùlø{Fû¥išxž^©TŠl6K.— ûr#~Ô°nÛ6ñx˲J24Hÿ“¾.¢ƒmÛaÝ´¨@ê¾ã8NØ>$ ¡´Kú¸lK¶!ëÙ¶ÞÄX&}F‹èç ÂïÑmGÿËñ%‰P$’?Kd}¹Çˆ= S’É$™L&Üvô¸ËÛiÛ6žç…¿¼ÏDçK?’c2 ×uCA'z¼ÒßåÊýX®¹6¢÷>˲øüç?_ënP÷èèj¦NÙKÛÁàу%“õ»f*2ãàÁƒ3µcÍš5ܹà6VÿëOøÊÎ?Ô`Ãó¼!Þ¶ÍDÐÑÑA[[mmmµnJ]ÑÓÓÃ?ý¾™ß|ºþæºÐè =n5“Éš5k¸í¶ÛjÝŒºcÍš5,¾í66­ûÂoóø–ÇCO>1îÙ¶­·5 ê;ééé¡§§‡µk×Öº)uÇ{ßû^Ö¬Y3¢ó+[¥ßŠaQŒv•¼­e¹\®d¹á<â-Ë   dº´K Yâu=œñYÄž©'âEùï!ç­ž«QQm+ÓÓÓÃ?ÿó?sÒI'èý.†ðd2I*•*ñ–¯æš?Ržš±¡Ç¶•‘ó"ÞT{¶h¦>zl;<Ò?ßúÌNv¿ÉçÜw={ŠSF3‘LÄØvZD¨ì:ÛOبh<§··÷ð6ªÑh›Ù/¬çÏéÞ è&M½ñ?wÀžƒ?-é—bª7Ãà‘‚6hfÍšUQL ‚€d2zb‹—º\3–eÑÝÝ=d½r#ÙvùË«ôyÙ^Ôû:ú¿«««âö 4ªæPÏû©z©ôÛD=ßë m^}õÕaû§De³Y2™ ©TjØ~9ú9 ÑŒe§ÑÔ//=q,oZñËGœz?i4Õ0å•y{çqÆŠ­,9v ^Ê_ô4Mm8ùŽ'ùß_žÌÿû‰òx-O)¤ÑhjG°.:ë@‰w¹x¬ëdM}‘L&±m;4ЊHM_£Ñh&ž .¸`H!]‰Ú²,+¬?¦Ñh&©£EI¦ñ 8æhxaÿûSÇÑ6"Í”eÊ *}i>—½K}–<¨¦ö/¾ÈžÝ'„…µ¡V£©ú¼Lzÿw0#Þëõêe­Ñ©d³Y‚ •Jé@M!5;b±˜®¨ÑÔ¾ï‡)15M}3¿ /¾øbI½*fª2å•ß½þfô±#åjÖh4“Ë#[V°{Ñ6€°è¢F£©6ÿï^þuË|>Zè—íííúªÑÔ’>H )Mý!usDìÔh4µÇ÷}í¼§ÑÔ)Þoàä…¯0ç¼×ÂzGÍTå¨Z7 œþþ~zzzèïï¯jù=ÇËq¨¼{íííÚ¤ÑL £íŸÐòºÇÁqœZ7_£™ÖŒ¶¾é¿ûyi÷¯°mÏóÈårú%T£™FÛ7¡˜Þ4Mm¬Õh&±ôO×uioo'“Éèþ©ÑL £íŸú}S£™Æ4¶Ý 7ýI†àû¾ÎŒ ™ÒÔ• ÒÙÙɪU«¸õÖ[Yµj‡\çÔΗ8ëÙŸ„y¥5Íø3–þ9óMs\¡KêܘÍÄ1–þ¹û7/rò[–ÊCHñÔhÆŸ±ôM ,j­Ñh&ޱöO@×IÑh&˜±ôÏ®®.-rj4ÌXŸ>Ûyòû'cÛ6Ùl–X,¦û«fJSW)¿:::¸å–[hkk£¯¯U«VÑÖÖFssó°ël9i3Gó;Òé_k1E£™@ÆÒ?·oˆÓN;×uúfüKÿüíž&>ùΓH§Ó¤R)á©ÑLcé›;wîäMozS­›®ÑL{ÆÒ?ï¹ç¶mÛ¦Of‚KÿÔh4ÏXû¦sàhÎ9úvlûø®«ß=5Sžº‰Pééé¡¡¡¶¶6–/_ÎòåËéééq½Y³^Á^u‰D¢.S•tttÔº #Ò××7*o¬ZPïçðH`¬ýóÜsÏå”SN©Ûè”z¿¶:;;éëë«u3†e*Ü?ŽÆÚ?gœúw,[¶  î´SáÚÒ÷Í¡kß<î¸ãH¥Rµnþa3®ÁzïïÕ2~“Ãe¬ýó²Ë.›bо¦ëéò›ŒcíŸÓ©0®–érMO§ßäpkßœ½a6wäøs¶ÒÚÚÖ¬êýY2®ÁzïïO<ñÏ=÷ܸn³n"Túúú†(š ‡ÌÉ÷ôÓOóóŸÿœ={öpÏ=÷Ôú0†pÇwÔº #²iÓ&6mÚ4ªÜ‡“M=ŸÃuëÖ±yóæÐ(9]Kÿ|ì±ÇøÉO~Ââŋٿ­¡"õ|mº¾xàšššjÝ”ŠÔóýcçÎ<þøãlÚ´©ÖM™pÆÒ?Ÿyæöìé禛ž`õêÕu7ªçkKÐ÷±³iÓ&žxâ N9å”Z7eBëØö±Ç#sþùç×ú‹z¾GK½÷÷j©æ7ÑcÛáûç‹/¾ÈøCžxâ Î<óÌZÂaq$]ÓS…Cý&2¶oƒP=2Ö±m<§©©iJ_Sa \-Óå>SÍo¢Ç¶#_¯ÎÝLÃÆ§xÝý\d]Äí·ß^ëC)¡ÞŸ%Sá¾PÏýý‰'žÀó¼q»Õ ²cÇŽ!Óª ç¼öÚkihhàì³Ï®õ!TD”[ÍØ©çs¸páB¶oß>íÓÍ¥¶µµ‘L&ijjâÔSO­õ! ÛÆz¦ÞÛWϼúê«477³gÏžZ7eÂKÿüÀ>Àk¯½Æ 'œÀ 'œPëC˜’Ô{ÿ¬çö½øâ‹´´´°bÅŠZ7eBëØ6×õضZêù™µk×ÖºéÍ´Gm5šúDm5S‘‰ÛÖM •åË— _Ú±c‡.:¦ÑÔºj4õ‹îŸM}¢û¦FS¿èþ©ÑÔ/ºj4õ‰î›M‘ºTÚÚÚØ±cGX̨¯¯ïÿ³÷îñqÔç½ÿÛ€c ðe‰/DÇdÄ]†F¢¤Êè`à×Ò¬”sNOŠ…ÝÓžÓºùÕín“Ò’6Ý jsÜËIwMë´I{°¶åœœpª $(4„+@°&vǘ%.6Ðïï~gf¥•´ºìîH~Þ¯—ìݹíw.ÏÌwžÏ÷y†‡‡¹ñÆÝ4A8éû„ø"ö)ñDlSâ‹Ø§ ıOAˆ'b›‚›”_Û·ogÛ¶mlÞ¼™½{÷²}ûvV¯^Ýèf ‚€Ø§ ıOAˆ'b›‚_Ä>!¾ˆ} B<ÛŲññññF7"Êðð0ÃÃô´´Hؘ Ä ±OAˆ/bŸ‚OÄ6!¾ˆ} B|û„x"¶)1TAAAAAAâFlj¨‚ ‚ ‚ ‚ ‚ ‚ ÄTAAAAAAf@AAAAAA„AEAAAAAaNýÃ?üÃ?lt#+ÃÃà 2<m›Õ´¡Ñö‡ö ‹—éì3N×Ö\ì³Ñ¶·c(,je·ºkaßõÞ—Z=§å±¸¨å;iœìs¾öWÏ}©å;®Øç⢖露jñî§gç|Û*ö9™8“±±1žþùØ>;âþn<88Ⱦ}ûbï·­»om\˜wß}÷x{{ûøm·Ý6~ýõ×ÿò/ÿòøèèh0ÿÞ{ï æ···ß{ï½eëÏ4!ùÉO~2ÞÞÞ>þè£Æª}{÷î-;†ŸøÄ'ªnC=Ÿ°ø˜}6Ú6«iC£í3í/ÓÙgœ®­¹Øg£m3nÇPX:ÔÊnu=Ö¾ë½/µzNË=bqQËwÒ8Ùç|í¯žûRËw\±ÏÅE-ßIq-ÔâÝ5NÏÎÅxNâN\ŽÉÝwß=~÷ÝwϺ}õhÜß?ñ‰OŒ_ýõ±÷Û6·&‚ÊøÉO~2~ÁŒïÝ»7˜výõ× …à{ôDîÝ»wü‚ .ÿÉO~Rõü…D_Ñ +틳ÑÑÑñ믿~üÁ¬ª õ<~Ââb¾öÙhÛ¬¦ ¶Ï8´OXœÌdŸqº¶æbŸ¶Í¸CaiPK»mÔõX û®÷¾Ôê9-÷ˆÅC­ßIãdŸóµ¿zîK-ßqÅ>µ~'mĵP‹w×8=;ã9‰;>&÷Þ{ïøoÿöo_pÁ•FŸÓ¸¿kR <•Úûn„oMj¨Ìááa:::hkk ¦mÙ²…ÑÑQúûûY³f ´µµÑÖÖFUó’žžÚÚÚØ¼ys0-íëïïgtt”;իWã8[¶l™± õ<~Ââc>öÙhÛœ©}ÕÌ_¦³Ï8´OX¼LgŸqº¶æbŸ¶ÍjŽ‘Ø§0je·ºkaßõÞ—Z=§å±¸¨å;iœìs¾öWÏ}©å;®Øç⢖露jñî§gçb<'q'ÇdóæÍtww—Ùaµí«Gûãþn<<…¹P+»mÄõX+û®÷¾Ôê9-÷ˆÅE-ßIãdŸóµ¿zîK-ßqÅ>µ|'­÷µP«w×8=;çÛV±ÏÉÄᘴµµÑÑÑQ±.FÎiÜß·lÙÂöíÛ£¿¿?.´ûn¤oM•y²gÏn½õV:::èîîBµ.Jô$Í4!cÛ¶mìØ±#P«ýýz´oxx8P-ï¸ãZZZغukpáN׆z´OXÌÖ>m›Õ´¡Ñö‡ö Kƒ‰ö‡kk>öÙhÛ¬¦ bŸÂ|YH»­÷õXKû®÷¾Ôê9-÷ˆÅËB¿“ÆÉ>çkõÜ—Z¾ãŠ}.^ú´ž×B-ß]ãôìœo[Å>'÷c·sÇwcÍðð0;wîdÏž=˜2Sâþî¾mAeŽŒ±uëVzzz¸ë®»¸ë®»‚y•ÔϨÂ5Óü… P(ÐÖÖ„ŠŽŽ288Èàà`,ÚêBݱclß¾îînvïÞ=cêÕ>añ2Wûl´mVÓ†FÛg\Ú',^¦²Ï8\[ó±ÏFÛf\Ž¡°4©…ÝÖûz¬¥}7¶jñœ–{Äâ£Vï¤q²ÏùÚ_½÷¥Vï¸bŸ‹Z½“ÖóZ¨å»kœžóm«Øçdâ~LârNãün¬ikkc×®]Üwß}ìÙ³'6~ÛFûÖDP™#·Ýv---8ŽS¦ÐºØ&ž„ÑÑÑ@éšiþB166ÆÎ;Ù¹s'ÃÃÃ<øàƒ<øàƒ±h_GGÇ$1ú}º6Ôëø ‹—¹Úg£ms¦öU3!˜Î>ãÐ>aq3•}ÆåÚš«}6Ú6ãt …¥G-ì¶×c­ì»ÞûR«ç´Ü#µz'“}Î×þê¹/µ|Çû\|Ôê´Þ×B­Þ]ãôìœo[Å>'÷c—sçwãÝ»w³sçÎàûêÕ«Ë~7öÝPßZU¥ë…2î½÷Þñ믿~üÑG-ûûÉO~,ÓÞÞ>þ裎ïÝ»w¼½½}|tt´êù Ím·Ýü^Ú7:::ÞÞÞ>¾wïÞàûõ×_?~ï½÷VÕ†z?añ0_ûl´mVÓ†FÛg£Û',^f²Ï¸][³µÏFÛf¡°ø©¥Ý6òz\hû®ç¾Ôò9-÷ˆÅC­ßIãdŸóµ¿zíK­ßqÅ>µ~'mÔµ°Ðï®qzv.ÖsgârLn»í¶ñ»ï¾{Öí«uûãþn¬Û§·w¿m½}k"¨Ì»ï¾{ü‚ .˜ô5Ð{ï½w¼½½}ü¶Ûnooo/»àª™¿ÐL¼°âо{ï½wü‚ .¿í¶ÛƯ¿þúñO|âU·¡ÞÇOX<Ì×>m›Õ´¡Ñö‡ö ‹“™ì3n×Ölí³Ñ¶Çc(,~ji·¼Ú¾ë½/µzNË=bñPëwÒ8Ùç|í¯žûRËw\±ÏÅC­ßIu-,ô»kœž‹õœÄ™¸“©•FŸÓÅðn¬mEÿFœý¶õö­-_Ðx!`xx˜ááaZZZ*† Í4ÿdhŸþ5kÖÐÖÖ6«64úø ‹›¸_[q·Ï8´OXš,†k«Ñ÷ù<;ãr …¥Å|®¹¸]óik½÷¥VÏé¸a~,•ka¾öWÏ}©å;nœÎ‰0–ʵ°˜î3bŸõ%îÇ$îç4í RaÅݾëy EPAAAAAA˜)J/‚ ‚ ‚ ‚ ‚ ‚0"¨‚ ‚ ‚ ‚ ‚ ‚ Ì€*‚ ‚ ‚ ‚ ‚ ‚ 3 ‚Š ‚ ‚ ‚ ‚ ‚  ˆ "‚ ‚ ‚ ‚ ‚ ‚0"¨‚ ‚ ‚ ‚ ‚ ‚ Ì€*‚ ‚ ‚ ‚ ‚ ‚ 3 ‚Š ‚ ‚ ‚ ‚ ‚  ˆ "‚ ‚ ‚ ‚ ‚ ‚0"¨‚ ‚ ‚ ‚ ‚ ‚ Ì€*‚ ‚ ‚ ‚ ‚ ‚ 3 ‚Š ‚ ‚ ‚ ‚ ‚  ˆ "‚ ‚ ‚ ‚ ‚ ‚0"¨‚ ‚ ‚ ‚ ‚ ‚ Ì€*‚ ‚ ‚ ‚ ‚ ‚ 3 ‚Š ‚ ‚ ‚ ‚ ‚  ˆ "‚ ‚ ‚ ‚ ‚ ‚0"¨‚ ‚ ‚ ‚ ‚ ‚ Ì€*‚ ‚ ‚ ‚ ‚ ‚ 3 ‚Š ‚ ‚ ‚ ‚ ‚  ˆ "‚ ‚ ‚ ‚ ‚ ‚0"¨‚ ‚ ‚ ‚ ‚ ‚ Ì€*‚ ‚ ‚ ‚ ‚ ‚ 3 ‚Š ‚ ‚ ‚ ‚ ‚  ˆ "‚ ‚ ‚ ‚ ‚ ‚0"¨‚ ‚ ‚ ‚ ‚ ‚ Ì€*‚ ‚ ‚ ‚ ‚ ‚ 3 ‚Š ‚ ‚ ‚ ‚ ‚  ˆ "‚ ‚ ‚ ‚ ‚ ‚0"¨‚ ‚ ‚ ‚ ‚ ‚ Ì€*‚ ‚ ‚ ‚ ‚ ‚ 3 ‚Š ‚ ‚ ‚ ‚ ‚  ˆ "‚ ‚ ‚ ‚ ‚ ‚0"¨‚ ‚ ‚ ‚ ‚ ‚ Ì€*‚ ‚ ‚ ‚ ‚ ‚ 3pÒ*…BÇqÝŒ“ß÷q×ud{žçQ(½[ ö¹xñ—ÕÚ§ëºø¾ßèæ sDìvñR鹪§‹í. Ä>ÏB¾—Φß+öÄ>Ë\ms¾ÏN!žˆ=.=–’Mž4‚J±X\´†ØÙÙ¹`"D£p]—ÖÖVr¹]]]¤R©yoÓó<ŠÅb£wMXÄ>'™L†öööIv-¶¹´û\ZTcŸžçɱ[äˆÝ.N¦z®‚ØîRBì³±,ô{iµý^±ÏÅØg㘫mÎ÷Ù)ıǥÇR²ÉÓÝafÇYô#YºººH§Ó¤Ói|ß§½½b±H"‘htÓa^,ûœ žç‘ËåÂ4M|ß§¹¹™d2Ùè¦ BÀÉjŸóe!=Â\9YívºçªeYUmClW¨5KÁ>õ^*ö)ÔšÅnŸs±Í…xv B-Xìö(ÌÌ’P)‹´¶¶²lÙ2R©Ô¤ Y«ßÍÍÍd22™L º®KWWË–- nâšÎÎN …ÍÍÍ477S(Èd2477ÓÚÚZ¦žÎfÙ©Èd2Áÿ®ëÛŒ¶½Z¢íqgÆï³ÙÞtû§o$étÃ0*{0VÚ/×uƒs£·9]hXô<Îf=¡þ4Ú>Â6aáì³’íÕË>g²—©öIŸ3Ã0‚ÿu'¶ÒqÒë‰}ÆŸéìs:ÛÔó+Ùg½ŸP;û¬Æ^«ÝÞ|l3º­…xvF¿[–%/¡‹ŒùŸ·m;ø?‘HLjs¥ýÊåreÓõ¹Ðëöõõ¿‘L&Ç-Ë –›n=¡±ÄÁ>Ê6õ¶ækŸ•l¯^ö9“½L·OÉdr<‘HŒçóùñD"Q¶ÍJ¶YÍï e:ûœÎ6ÇÇǧµÏF<;õ¶Ú>«±×™¶·¶9Õ>ÍõÙ9>>>>000nšæøÈÈH°?Bü™Ïs5:?.¶m›þ^ ÛmÔsuº}šê¹ª·+¶»øˆC¿w¶ËNÇbï÷Îô^:Õ>Mg×ÓÙæø¸Øgœ‘~oåm,d¿·Ú}œ«Ïh>ÏNy/ÒŸz;‹©?{2ùq—¤ ’N§Ç“ÉdÙ4Ó4Ë.š¨è‹°¯¯o<ŸÏ[–U¶n2™ ÖjPú„G¿O4Äj—މƨ‘̦Sðj¾W³½jöOßõCQŸøÛ÷+—ˆ1å¹Õ¿‘L&Ç Ã({0N·žÐXâ`Ÿ e›z[óµÏJ¶W/ûœÉ^¦Û§t:œ;Ó4g´Íj~Oh,ÓÙçt¶9>>>­}6âÙ©·µÐöY½Î´½jö¯[YÈgçÈÈȸišã³:>Bã™Ïsu|<~¶[é´¶Û¨çêtû4Õs5úb»‹‹8ô{g»ìt,ö~ïLï¥SíÓtv=]¿Wì3ÞH¿·ò6²ß[í>ÎÕg4×g§ž'ï¥ñAú³Sog1õgO&?î’Lùåºnò§1M3øìû~Y¸mtYÏóp]—eË–q 3š¸o³!zªù¾P˜¦Ioo/¶m“ÍfI&““Žk¥ýšmžçߣ!mÑP¿™Ö‡Øge*Ù^½ìs&{©´O…Bb±ÈÀÀÙl–¡¡!\×%—ËSÛf5¿'4Žéìs:Û„“Ë>«±×… [Y¨gg.—ò,|ßÒ.¸®+Åóy®ÂÉm»z®VÚ§ûï¿Úç*ˆí.F¤ß[™Fö{gz/jŸ¦³ë©ú½bŸñFú½•iT¿w.>£¹>;5ò^¤?;5‹©?[ÍzKÅ»$‹ÒW“›tª“b¶mÓ×××èÝX2ض=)—_µ7’‰çibE˲Èçó˜¦I*•b`` ªõ„Æ!ö?æb/žçašf™-Û¶¬[É6õ²bŸñe&ûœ®C3}F_j„ꙫ­ÌõÙéû~p®<Ï£X,NzyâÇ|ž« ¶[ æb»‡šö¹ b»‹é÷Æ‹Z½—N×ïûŒ/ÒïsµÍ¹>;å½4~H6~Ôû]t±Ùã’ŒP1M“B¡|×uËnΉD"!Lš5âû>­­­e…ÙaYV ƒ:¦Åb±*Õó¼àüèõlÛæëa:Æ4ͲÎêtë Cì3~ÌÅ^´]ëó¤×‹„ɶ9×ßêÃtö9mêùbŸ Ë\me.ÏÎl6K___ðgYÙl–l6Ûèà ÌÀ|ž«z¾ØîÂ2Û½à‚ ¦}®‚ØîbDú½ñ¢Vï¥Sõ{Å>ãô{ãÃ\ms®ÏN¼—ÆéÏÆz¾‹Îç÷Å’ŒPI&“¸®KkkkpcN$Á|˲H$´··cšf™êeš&étšÎÎÎ`]Û¶ËÖ¯7¦i’ÉdÈçó =®sÅ0 ²Ù,íííØ¶Ód2YÕ¾§R)LÓ FħÓéŠËêߨ´iÓ¬Öê‹Øgü˜‹½èMô§³Mû¬Uûçb+syv& -»H™Ïsâg»Q»]¬×ä\l÷šk®áðáß«•Û]H¿7^Ôâ½tº~¯Øf¼‘~o|˜«mÎçÙ©™¼—ÆéÏÆz¾‹.F?î²R!™%‰ëºA8mT¡ö}?%ò}Û¶Y¶l###e¡žçaFÃ/~Ý–‰û±Ø˜í1u‡\.G__ŽãÔ|=¡¾ˆ}ƃùÚK½ìZ¨/•ì³Û±Ï…BžÂl™Ïsâc»‹Ùn¡þÏUaq ýÞx!ýW!Šô{ãÃ\ç\Ö»Ž'ÒŸõ~]Œö¸$#T4S|ß÷éì줷·˲Èd2ض]v‘›¦Y³Â>Q<Ï›¶P’mÛØ¶=m[ªÝF-Ú5æsLçæç𰓸Ûçll³žöY ÛŒ®;[a×Bí©dŸÕØ&,û\,ÏN½Þ\;¹˜Ïsâg»óÝF-Ú5[êý\â‹ô{Ë·³Ðíš-Ò¢H¿7>ÏιÏùž±ëø ýÙòmÔ¢]³¥ÞÅ—´ 2¦i’Ïçƒ/q±M89žò  ±Ýú´+º-±A¡ZâbŸ'K¿w>ÇGìúä".¶ 'dz³ˆ]/.Ä&ëÓ®è¶êù.ºíqI§üAAAAAAXNitAAAAAAâŽ*‚ ‚ ‚ ‚ ‚ ‚ 3 ‚Š ‚ ‚ ‚ ‚ ‚  ˆ "‚ ‚ ‚ ‚ ‚ ‚0"¨‚ ‚ ‚ ‚ ‚ ‚ Ì€*‚ ‚ ‚ ‚ ‚ ‚ 3pZ£0_n¿ýv.ºè¢F7cJŽ9ÂÙgŸÝèfLÉk¯½Æ«¯¾ÊªU«Ý”)‰û1F‚pR0•mêybŸ‚Ð8Ä>!¾HßVâ‰<;!¾ˆ} B|‘¾­ ÌL]]ÈïÎ;ïä /äÝï~7»wï`ppp’Á®Y³fÆ¢N`ëÖ­õÜ Aغu+<ð@£›1o¦³M˜»}>ðÀôôô4z÷„“ÁÁA¶nÝÊáÇÝ”yS û<|ø0[·n-ÛŽ Ô *àÈ‘#nʼ‘¾­°Ô¾­ôm…x¢û¶htSæôm…¥†ôm«ëÛ6z÷„“žžžšômëšòkxx˜ŽŽî¸ãvíÚE?Û¶m£¥¥…ÑÑÑIËW2¶iÓ&víÚUÏÝ„€]»v-‰—ªél³££cÎöyÓM7Å>—¢°4ikkc×®]KÂ)Y û\·n<;…†ÑÝÝMKKË’Í&}[a©!}Û鑾­Ð(¤o+}[!¾Hßvz¤o+4’ZõÛê¡¢;:<¬££ƒo¼1›ÈL*§  Ãt¶ ˆ} Bû„ø"}[Aˆ'òì„ø"ö)ñEú¶‚PuT†‡‡'…x­^½PF;ÑGGG¥°‘ ÔélÄ>¡‘ˆ} B|‘¾­ Äyv B|û„ø"}[A¨Žº *:TLçäcÏž=e¡zTÂàà ÃÃÃÜxã>F‚°ä™Î6±OAh bŸ‚_¤o+ñDž‚_Ä>!¾HßVª£®5Tº»»äÖ[o¥¥¥…½{÷ÒÝÝMww7 òšmÛ¶Í›7³wï^¶oß^6RA„Ú0“m‚ا 4 ±OAˆ/Ò·„x"ÏNAˆ/bŸ‚_¤o+ÕQWAà®»îbpp0 ‹††uwwÓÑÑÁððð¤y‚ Ô–élÄ>¡‘ˆ} B|‘¾­ Äyv B|û„ø"}[A˜™º * òîM…¤ 4ŽélÄ>¡‘ˆ} B|‘¾­ Äyv B|û„ø"}[A˜žºÖPAAAAAAXŒˆ "‚ ‚ ‚ ‚ ‚ ‚0"¨‚ ‚ ‚ ‚ ‚ ‚°(ñ¼úý–*‚ ‚ ‚ ‚ ‚ ‚ ÄŠb|æå:;ëצ†¥AAAAAaiáû`³[ÞqÀ4Ãõ CMÏåÔgÛ†B,KMK$”Ø’H„Û¨´ÍZ ‚Š ‚ ‚ ‚ ‚ ‚ sÂó” âûÐÞCCåó\W ɤB,KMO§•`’Ë©yž§>§Ój]ßW©”šW,†Ëû¾úMÇQŸ]Wm·XTë‹på• ¿¯"¨‚ ‚ ‚ ‚ ‚ ‚0%™L¹bÛJÄõ>¯þ÷¼P`q5MG—ø~(Š8NXûÄuÃô^ù¼úlš*¥PPóm[­“H¨ï¡Ð’H¨ÿ C-ïûjù¸†K/]Øã 5TAAAAAA˜- 8ŽUR)%bX–úìºJtÉå”°¡k›˜¦ú+T$Šã„Ñ$Z<ÑÑ(¾¯Äß#Y’IµŒm«ÏCCj=ÛV¿¯·ÙÕ 7†ÇŽ­dÕª×ôH„Š ‚ ‚ ‚ ‚ ‚ ,atJ¬éÐiµ@‰®S(„µN´8bJHI&ÕwPÑ"ަö*TÔ‰®‰¢G‹#ßWß-+ü Àl6Vt›@M×íÔ/ËRÂΩ§þб ÇQAAAAAAXBxž3 %8tu•×6Ñè‚î†Ö:ÑßS))¯S¢Ó{™¦ú?“QËë”\ZôПµð¡—Ñâ‹®“R ]lÔïDÿŸˆm«¶e³¡è2“p4DPAAAAA„EBT¸Ð´¶BooX?D×ñ¼0 –®mê³Otĉ®s’Ï«å µl" 0Z(1 5-‘Óyi±eQQcaC•ÁÁAÆÆÆÊ¦ ÓßßÏððpÝÛSœÆ"¢¹êúúTŸèU\Hk„SÉ6¡þö™É„éõ:;Õ4Ï £Q´ˆR(ˆ "œ<ÄÅ>A˜LÜú¶‚ (äÙ)ñEìSâKÜú¶Ú?4Åå_/¥lZ8@jâöKQ LT2¥õÈ´jüÂŽ£¢BtôI*¥"B …Ò_gišžç—NžƒR¼ºP'½Fþú† *ÃÃÃÜvÛmìÝ»7˜¶{÷nn½õVvîÜÉ­·ÞÊîÝ»ëÚ¦\.ÌSW‰Þ^Uì'š'Î0–ná䤒mBcìÓ¶'ç’Ô"Kôa¥ýB¡º‡k#hoo§(Ê«0OâdŸ‚ ”Ǿ­ òì„8#ö)ñ%Ž}[-D@Õ1‘bq²ÝEùÛ‹„"È¿?ÎÀÈ]¥ií‘å¢IˆÊ¯ôW \|骣#A¢Ÿ=Où´ õ×Õ¥|ÊÚ÷¥}Ì:—.6¯SoiD‹¾¾Ð'­k¥è϶=Ù_mÊ¿máoêíלJ¡>… Ó´(¢O\&râZ Õ1§´l¥ŒéeS¥?¿tR»àÿ￱æ±ÇtWV”þÎ;ïœ4­§§‡;vÐÑÑÁàà ·Þz+´´´Ô¥M®;Ùy«)¦Vì’ÉPE”\rÂb§’mBcì3—S“BA=´¹nùC!ŸW’Ç?J>ÿ&®Û\·ã•Édð}Ÿ|>LóK!4†aJ¥pÓ4q]—„Ž™,­›L&1E‘ª$Nö)B9qìÛ ‚ ÏNAˆ3bŸ‚_âØ·}KÄg«Ç«Fý°žw¤(M×Ñ$Väøî‘#x§ŸÎQ”Oß-­Fi9³ôÿš7ß䇯½+Wól”ÿÜ7ß„SN)ù€Œ`¾ã(_V&Š™ „Q&Ú äºj]÷$ŸW¾çBAM+ÂùCC¡ï9š‚K‹,ÕRÑ÷](í˜I¨%£ôW-þËQˆŽ˜é*ý–[ú=‹P\ñ#ÿKóüÒÿzléûƒ8¦šþáÉ«ß?%»-øŸ–}Ïóã‹.šÝAš†D¨ôôôÐÖÖÆæÍ›ƒiýýý¬Y³†ŽŽÚÚÚhkk£¿¿¿æíq]•—.žZP™ ÓTÆ1]„‹ ÄJ¶ ³O]€«X ‹dåóJ×Ñaž§þ²YX»6Ë/üÂ_éÁæK.—›r^&“!“Éà8NÉðÝÒðˆT*EWWŽãàû>CCCôöößÇÁu]r¹\°î쎋'Ñ.'!q³OABâÖ·A!ÏNAˆ/KÉ>uZjšºPPŽQAX¬Äµoûó÷繋^üDQ´ Þüÿ=~˜ªˆò¿ÛÀ9Ï=Çÿ=xvà{gÅ)û÷ã•–‰j Ê÷ïg=ôÏ=÷\ð;pËáÃàÃðo½ À—¾ôá›.ÜSªwR,†ƒuŠ®L&Lµ¥ýX¶¦çÒû¡E–drr1ø‰bÊ‚øˆæ3ÓÑ!:dÇ.qÕòzYª£‹Ít•¦E£Iôÿ.*j$9)D~{Ÿ¯¦åP)½º€4°¿S­3œ/y0ةĔ_-Â;2Ð[úͬ«¾ÿ¢©6ð púËÏñúªU zÈê.¨ ²gÏ’Ñ8¤Òô‰Šæš5kfÌÉwàÀ¶nÝ:¯6ES sÛ†m«‹Z ª7¹\ŽL&C*Už0êìž­[·òÀ4º ÂT¶©çÍÅ>xàzzzfÝ–L&¬[äûê!b*¿¤ŽNéí Åã8 ~³ôy~Ç£X,Ñ'ß÷Éd2 ŠÅ"¶mÓ×ׇišxžGWW­­­ø¾ištuu)FI­M¥R‹E:;;I&“‹E …¹\®ì·ÊG&°ñB¡@*•"“É”-£šh› …^\s Õ˜ÁÁA¶nÝÊáÇݔ۟…´ÏdzuëVIŸ 4„Ý»wÓÓÓÑ#GÝ”!Ž}[A˜+Ò·­MßVæ‹îÛ8p ÑMY°ýY*}[ÇQï©ÊŸ”É„ƒ»ª©‚-,z¤o[]ßvpppÞm{lÛJþö/Q,*Q!šò«PPöxúùcP³DÀÊO¿ê;ßáÇÍÍÀš}ûXýì³èàŽ4pKÎ(B¥äcÿðemp?¸ô9ι÷»¼ñíØ}‚;¸Öþ)ù¹7x°Ô&ÉqBµXTÓuΈ”͆"ŠNý•Ï—§çšo†ií¥õ§E­$éè]x&Sú{*ÿÙ E”Biúïzð>'Ì‘öfFm·´Ô‰è~ËWóíÒº›R*Úäg4uÁ¼×ƒkhñÔ‰yÓƒà„ïuà….¸Ú…'uÂLàC¶*F£‹ÓØ6»GÞä…××ÌûÚ›H]•±±1¶mÛÆŽ;X½zuÙ¼ÑÑÑIËW2¶iÓ&víÚ5ç6é {``~ùâl; ãj^àlC¾ïÓ5Í“ØqœÀÁ«ÅÏóèìì FÉ µa×®]ÜtÓMnƼ™Î6aîöyÓM7±}ûöY·G×3²,õI$ÂÂZÑpNýðüÊW¾Bsss Zäóêþ9›K_‹¹\Žööv2™ ¶m—E‚är9<ÏÃq²Ù,¶mc–eâÉÐÐ}}}äóyÒétYНÞÞ^,Ë"ŸÏ300@6›Å0 <ÏÃuÝ Â%ÚŽÎÎΠmZ¸I&“X–,¯ï¾ïŸS©…BB¡€ïûtvv‘3®ëây^ Ì477—ý¶þý®®®@ÄYl´µµ±k×.Ö­[×è¦Ì›ZØçºuëØµkÝÝÝÞ=á$¤»»›íÛ·söÙg7º)ó&Ž}[A˜Ò·ž¹öma¾è¾í¦M›Ý”y³˜û¶¹\Xû µU‰' ÞYu‘çDBù—úú”s4•Rþ½ÎNX¶L­S©îƒ°x‘¾íôè¾m[[Û‚´ñðÊ•ØY°p"2Ý÷a™Ï\vþíMž{õÕ u—áûüñûäíõW¼å§?%løÈ6V|ççX¨ÌV6ðSW`,ûÌgX;>Žéûzä"¾ÿcåèux,=ÎK?ÿókðx3_}x9þ íË9p*c. Ùåæ-Kµï–[^ãŒ3¾…iªiétX4>“É™“ª-'ñì瞀Òÿ­„B‡OX &Z¯Dn÷ 8 „ŒtiIÂpŸõ ûêÀêô[ð‚oÔ:® ûsð>çBS>í‚›þ<[(¥ìÊÀœ ¼ê¯ٰ΅¶¼Ç·¦ÂP u£ýZ1¼éþ·’3Þ÷•jv[BåEÓþ¾>ºoèæÅK>¾ ×^”ºÖP) ´µµ1::J?£££ ²fÍÖ¬™¬ /˜ÁMEg§ºPõ;ÕE-äã8võÅ4CC™/:-eYär9ŠÅ"¾ïcÇqÈårôöö’ÉdG­Q\×%™L’N§§M[T Ïó0 #ø-aé3m¶µµÕÕ>uçRÛRÔž&`Ò¥£G222@kk+¦©J©|÷»G¸ä’•\vÙótuu‘Íf) ¤Ói¬ÒÆ}ß§µµ•t:M¡P``` r¹¶mcš&¹\ŽñññImÖ#7&ŽàHOHdišf0M×Méíí(‹8Éd2‹EúúúÈd2ðÅó<ÚÛÛÀ÷}‰ÙRܧQ’Édpÿ°, Ó4ƒ{‰ilÛÆ¶í2ÑÖ0 LÓ Ä \.‡iše÷=ß÷ƒ¨Û¶I¥R˜¦‰eYض¬ëû>®ëbY†a”ÝDŽꈓ} ‚PNû¶‚ ȳSâÌb³Oߟ<àÏ4•hR,ª?Ë ßUõû«~åqÝ0eµÞ–ÎÆ ¯EB܈SßV‹!nQ •¾«¿ø4|sŸÍß çFR_¹.œ‘†osÊ[GÙ»b g8@ñ—Ža¼ç§<üðrLÓãØÏ~ÆÕ6pßËáa#‰?WÚÆ}ò¹wð±ÑÿÍÖÁKàÀ•¼øõÓà:e»ÇÿíMÖ¯¿™SO}‚ƒ6_ô2/m<Ä~÷lÚ mòuJ9ËJ˘¥ßÖ„Uü¼_ì…+|x_6G ¸¨Ÿ3á×’°¾mxÖ‚³ `Zê¦yºf© ¹¾¾ß«”û¬«K©M?v˦dR„è1²í0Z"ŸoÒš3 N{í*à…½>ë^”~llŒ;wÊð|ðAFGGéè蘞9::ZÓÂF¾¯„+eÇ0”À¢ÕÁ(ž§æ»®K&“a`` â6m{v)¿¢ŽNM&“ F«†#Z`Ñ#Ö-Ë¢P(`Ûvà¶, ÏóÈçóNL6ŽãŽQ×u'uù±ððžç÷·“™¸Ø§ “‰SßV„yv B|Y öéyå"JoïäwS‚:’”  ÃPÂKô{6ÖX7ŠGâÒ·Õ‚J&¥lÌuaì6òú9§ó¶«Ô2ßÉÁïäá¥ôð%‘råò—x…5¼¾go¿…ÁÁO;8å”?À¼óIþú-Ì/ÿò‡øìgÏ ~/•‚3ÎxšSO=$èí½‡ƒ_À0LN];ÎM9x›MçrúØéÆÍ´ü*¸Xϼþ–gyþÁs¹üŸÆJ ¾¦o*DwÏÁ± Çh:Ô¤Ògý{^°Õ¶.ízÃú%ET´H¡Xº¡eá«Uè=™T©¶nKA:¯–ßlÁ+@®¨œýͰåÈ»3­ë˪å=n.ÀUÀßàž‘É7ÍlVÝ í`—~#‘‚†Þ|'Š%ÛV¿[É!oÁÊc+üú¬« 21U¹=‚ÀqŠ“RãDI&Õ9œ00½ÂöTQé\.G6›  :išƒ7NS,I¥R†Œ¬×)~¢NÞJN]Ó4inn¦¯¯/ˆjÑè Åb1•žÍfcÖ‚išAí= ]‹.žç5#¢Ú¨HT,ƒõ*í|5§óž 5c&Ûìè訛} êX,ªNëT¸®Ëwþ”~ôš›/›§¯ßlvˆcÇÖsôèÑàÚÖª¿ã8ø¨¯ýJ‘zÙz ÅÝž™°,+hÛTbN 6Q"‘Hb²çyضM>Ÿ/;FEGþ†A6› Rœ9ŽC"‘î{ú^§ï‡íííÁ=0*kô½r©ß7âdŸ‚ ”·¾­  yv B|Y,öÍz\¡ÔK€®§; å7„¸·¾­\Ï~ůì^Íñ’ âûð­` À5yø)pîîÝ\ð++øÞ·NãÖïÒ÷Ê ÝÛÄÚµã47·c¿Ï Xü‰ÄjV­zœ®.xþùosÎ9kð<8xð Ö¯ßLkk3‡½›cÇÞàÍ·žÂƒÿ.µáÄO–óîw¿Àcü'K‰&¾—?ÎñãòÓŸ6sð”Q|÷}€Ÿ>òy^{ùiþêò=¼tÞ嬢X,200À#¿õ[ØÊÀÀ@yªõJ¬0Óq9ðÂ/ð[ÿΓ¶ospýAšw4C€7÷½É=Þ=\·ú:–­XÆyöy0èA»Ÿ. *;|% ø„…b@ݘÚÛÕ mÜWŽðLFMßëÂgýRX¥þtN³|>Tžµøá»ªA¦ ·”¶}³ªÊ™Ñþœè _í œú7Édåå 8üö…¯­[÷•騾};Û¶mcóæÍìÝ»—íÛ·WÌ©¹d2•¶S…\š&är ²cRGm˜¦ÉSO½Šç]_ÉdÛ¶ƒs§ÿO$A-˜‰÷-ðöM+Ô÷¸œÛzPÏç§ Õ#¶)ñEìSâK£ìÓóB¡#ŸŸ¹Î®=Ó€Ú‰†Ú¾ ,6êi›>JOx´œ¾òàƒçJnÙ& ÆøtXð^ÀÿØÇ~ë}Œ><ÂsÍÀó ÀæèÑfŽiæºëàÓŸVö~Î9÷³fÍj¾÷½½ìÛw;k׿9ýô°yó«<ûì­¼ü2¬];ÂËw¯ ~äÕõ]n¾d%»wŸË\kÂ+>¼gó9l|ð>ŠßR~ÇôûÀqp3,•êêißÂúÕË‚½¿ô¯¿Ä¯üÑçðÞbñ~ƒ/ýë—°Í’ð‘º`ÇÊl;¾ÃgÆtMÞ|óÎ<~¼ûAºï¢iu?¸ðÜð~N9ã!N=í|ÎË~ ~Ó…c~)÷˜ÏáS_c¥ƒëÁˆˆ!††ÞYV˜’˶ռövõ9› çO¼ööªP&úÒMsaÃô¦¹©>sÙ3´Òº ×gC•‰7»»»éèè`xx˜–––š†tºn¹ø¥™NPyæ™oó“Ÿ|ÎÎβߎãÉd‚º#ºüÃ?ü6MMÇñý4‰|ùËÇpœà´Ó^ä?x˜7ÞøŸ¼÷½¦¯ï“,[¶¬ÌñWÉYišæ$g" Ó‘N§ƒá]p;=Í“_×dÐÑ1½½½KG—èmé¨à–eµ´êjYV:MÍÖõitJ1-€hÇ·.®°šööö =RWWW %“ÉÀœËåp'uôñÓ#⥮CH¥b¸õ²OÏ #þ4•B Õ÷Û1MØ»÷ÿÓµÐhÛ6ɤ‰ï«ô‹SùÅ-M]ôú«öZÔB£ÞïzPM¤K2™¤X,–M‹æÕâ«N¦Ó©éýѶªï9ù|žÖÖÖ²h¶‰÷>}¿Ð÷šÞÞÞ@¸Yj4Ò>A˜žFömA˜yv B|‰ƒ}ú¾tëûÊ78ØՀù¸ŠEå—ªö·¡4²o«³WüÔ‡=ÿ²ŸSßþoXéªNɪÏOw 8kÿ~ Ëbllœ§¾rÿšKÉçU:/2^×=xúéòôÓÉ\ž°cÇ.¦­í\Î9çGùè÷îý2ù—¿À«À»W~“ Þ–(i Ž3Æßþ­SòE%)˜>=ò2?Îå8|úé|ö•W8ÿ‹§Óþ½7øÍ¿œrÖ)œuQ7Å—à3k×råW‚“^*s»íø65âÿ.ÿ¿ÜrÎ-œsösp±¸îèWø)¹$ùI^ûú·ø•gU¥/øÈ?ü-[­OÁu>¸J->xñÅ|ñ©§H‹a^ÃRz­L&Ã;®¿žT2©Bô,K‰'®[>âYûat1ø‰D£P¦#Z¥Æ\óÀ5ì:¸ ÛŒU„ P·ÎìT©½¦Ê}yÏ=û¹ì²Ê¡¨#=ÚÛÛƒ‘å¦iây+WþþìϾÎ%—là»ß×õxè¡S8óÌÿƱcÇøÔ§®Æ÷?Œö7æóyþÇÿø@ஆ‰õ¦#êxUûïUh&-Ü]mÊ }ô:z=í­4’Þ0 ‰D5 S‡Uªë  `g2™ ÚEG­´··“Ífƒ4BÑè˜b±H>ŸB¡8v£i†„©©‡}꨿(úzÒ9&s¹žçÑÔtˆ|'¼6Óét™Pha¡ûÅÂlÄ-˜.&´ ­£Ån¼®ëNp³Ù,™L&XV×”ÒÂçyAM—D"DÅ\wÝuÞݺ!Î Aˆ'b›‚_Ä>!¾ÔÓ>s¹ppölÜ–U^#e6ضrì67«Á¾2¾SX,ÔÓ6Ÿ,¹:>ï‰kÎ`UËËŒÝó&íÞ)`)ÑÅ´ÁËÃ¥OŠ=ú¿ùƒîn6n|™¯|¥ÀG?úwüñCK˱,åóÕÁ¾o{Û0^Ì?þã¥üîïfÇŽÇ7¿Ù„ëÂÞ½jÙ矿PµZ~–„÷¾7д«´ùñf\×U~Ô¢Åe?ù]>õûŸâ/O?,`î<ÚàÔSOåWßÌŠWœÍàŸ€ýÞ¹|ê^Åç?ÁòU/qä-÷rûµïâ[Ù3zã/²þ÷_ÿ}‡ÖÖæÉußà/îr¹íÈ·xôì¬×~PÓ„®.¾±w/Ïœ8Á¯nÛÆÿüÇä ÓT ²ÞRê®W¿øE~ü[¿6Ö‚‰>`  þ¬oš‹€µ#k9ÈTêëN-‚MôKê\àê«Ï¦çr¹ ž@4í–뺜yæU|ÿû+ùþ÷ßËglÅqþœßù~Ž{/?øÁK:t—\¢FÌ+]&ÉSO©;¶bQ *†¡°¶=u¨él¯~%å° ê•6GG è(•™Ú¤Súèc0Q ÒÂŽV‰D°^kk+‰D"HÔÞގ뺓¶á8NPç¦RýaáÐQ…#IÔéâö•"ä´ø;ñÞ¦Óê´h™L†²z-Ñ´…šsÏ=·aû)‚ ‚ B|ÉdÔ@ìdRùçâœë;¦m«QóºØöI”­Xªâ„Ž ˜*2ä…ïÂ)W¿ÊÛÏÚÏj+ô˜€—ãS°kçN•VüýI~ù—ÏÄ0À÷—ƒmMSùZ=®½v?¯¿þs<ï^~yÚ} —Dþ×1¾sî>:ŒóèOއªuR Ƹ"}E0Xœ|?ýgð+ðí²)X¿ ¹_ƒ¢þ¿€õ4«À±àþÎá¿ý3,;üZû†x÷ÕÝpóŸðþ¼“ë2w¨¸ÎR¿é8Œ>—>û,¦6r¬ë_~9HÅõ+/¿ >Š{ñÅÜõ ¼°aoüú¯«,ù¼ÊW84ŽÃW~ï÷ø§Fösj?S)Š$ÈÒ4Ûü†1agf't,è6O:AEG4M¥CLÉžŠ¤–Ú°a>ðć?ŒSŠlÐuO²Ùlà ,LÎ?ÿl¾÷½‡8ÿü\w]ýà8kéêR×n¡ þúúrO*u4˜øŠ#ƒÕW?»šMÆ Ü|ðf%¢¸¥öé¿>¸y}ižd€N”˜¢—w< VBþ÷À,d! Ùs!ÿÉ ÿî¿nç/ÿû§ñO;D±Hñ}TC2™ÐqVTV®\‰cšlذ!,04ć?ö1zGF¸ô®»a¡Ìש žîí…l6¨GÝÞÞNgggPß¶V¾#]×Ê3h:;;ƒúÚ‹E<ÏÃqœÀè8AF];Û÷}2™ ííí9r„Ÿýìg Úöª#Tî¼óNvïÞÍwÜÀðð0·Ýv›7o¦­­={ö0<<ÌŽ;jrЉ>7%&Q'â~á×Èq1ßzúi¼o} lÇqxéöXvË-¦¦&:§*¶‚º~M>ô¡+*Žž×M7·nÝ#xÞ47?ŽaÜL4óT6«ôÅ¢Ú®.²N¯&›ÍâyÊðMSu ´Y‡†_À(»è¢¤Rê7ª®u=œ›§žz%/¿ü$Ç7á8¡ê¬ï!¦i’ÉTWÉ4M²Ù,­­­ø¾eöÑ´`Ùlvш‰qE †}}ìÓ÷I§ÓØ%;Œ¦×ƒÙ ¦9¿Pê¥è°¯uÄÚT‚W´¶ÒD&FMœç8žçU\f1Dà ‚ ‚ ‚Ð8t¡ih¬˜%‘Pþ)ë*!§j¡¢ÿ9^üüz^tŒSÎSQ"ccc¼å=ïáÚľývÎyê©ÐGPrCØï1ñ}pŒµ¥€1å'UµØU±ù[nA9‡µ«·è#tš6«ùVIP+-¯…PUðåiSE«ô¢ŠÊ'Ö# X&éžNøÛUÚ®¢ ¦«°mŠÍ3tÅ:nqì¡!Ò_ü"©l¾ñÐÙ¬kœ¸.$“ e³S¦+ÒÇd:_‰®cígßp…B¡¬ž¶mÛtuuƒÓU¤ýÒÙflÛž”Ò=“É`Y‰D‚ÎÎΠ”ƒrtvšlIà±,‹¡¡¡ kP2™Äqºººèíí¥··—b±H±XIJ,Ç ü¶:uüªí«Ø¸qã‚^ŸU *ƒƒƒ<øàƒÜwß}´µµ°gÏÖ¬YÃŽ;X½z5ÝÝÝØ¶Íððp¬ ûÙvùx—PPq-‹ñGÖñc`Ó<¹n]°Üá?y?ϵl%¨$³YJ—ü$fJ½5Å"ŒŒ\QqÞÄâhúú-•3ZBÓƒ\NÝ@Gr5½?Þ„Ƥپ*¶ A-£a þÌfãÆ&Þÿþå<ýô¥;¦ÚßÙ©Žã¨ó­Cy'j`Ú?®÷ÙóÔç¡¡¡à7„Ú£kaé¿(žç"¶mO 1œ*’¡’mV#ªÍÄRqØ×#Ý×tQ&Ó=€§[tÛ§‹nAAA˜Šd2>BJ´M©”*‚åœ$¶Çyý¿¬§©©‰CMMxžÇ‹/¾Hss3/~ÿûtvv²Âó°TT`ý$šÁý!ØË!ñép»–1ÙÇj€ZW£M K9¹b„÷ÿóûáY5ýPÓ!ÎÿóÁA¥ñ2PBÍCíðK#jwvÁ•i°-µ$*R%¸¥‘ò C}ÖEß³Y>äyAôIïEÁoýœsŽjl´ÁG GFì{¥Ÿåïþ·}ûxpóf~Zž¾í6œÒrIBÿPxþÚk)|ìcôõõ•ù]LÓ¤X,244D6›Åqœ@¼ˆfuÑ%1t=ê¡¡!:;;I§ÓA4J6›Å0 …½½½ø¾L×þ íÛ) Á@ëT*E>ŸĘd21Åb‘|>_Ñ'”H$8ðñœöâÂV=©jk>ø ˜*ý×–-[‚Ú---´´´Ä^P)ÔuçØaú:(>Ïf9ôž—ðifÅsÏa'“è8ޝ¿lÃAÙ L-¨ÌÖ¯§ŠÑÃÁƒßnžqùlV9¢3˜PG˜\'È4L{{' BœV®¼„L&,ԭņÖVõY BªxS¸=rL‹Z„)·k»¬Pt-Z‹a´€ëªï¶­ö«PPËEྯ’LFµ7Ÿ‡#Gžæ+_áñÇßÎèhxtTŽÞ/-:¹®Ú®ŽÄÑûŸL†NýR Á@dò}رã“47?ÅW4._àRFç­D5Ž9’"´éj@@TC+¦N÷t­˜ZSôúA¶ûdÛvð0AAA˜ ]]êýÞLsr¶A8™ÐeG´ç ìËÀ©kǹôCkùªöô'Nàû>cccllkãµ§ŸV)©00ŠF ^$^ó 0Þæ#7û? kœh±CʵJ˹¢ÊigE\çà-(ÅB¯ëià‹&\ç‚iÁn^³ÔüLFmÌ(y£éSt¥ÎN•¶Å0”óS&¶m ÊE’(o¿å~ú¥/•Çv`¨T8cYxçÇÚ‘Š@Ê0ðm›Äø8íË–a—¢Gà¹W_Ûfû;Þgš€ti;ßþö·q]—O~ò“üõ_ÿ5ÃÃÆ¤ë2 #È„T,1M“|>ã8ôõõõ‡††å“r‡d2Y–‰f¢ï(𡦷·w’È£»w†›ú3—=ÃÙ/ž½ ×lÕ5T&Š$ýýýlÞ¼¹lšWâJ¡ ®KË …8|ø0—}êS`œ˜PµzýÁƒ¸®ËŠÌQÖOPO¦zÞéбÙÐÜü8® ›7?5«õÒéêRéßMM‡pxòÉO¨}( ‰„²ñtZ}ׂ¶ePÂDg§úÓ‚ˆŽþ(CÁCw|ßçàÁ›I¥ÔôÖVµnss(:9Žú¬#ItČ޾ã¨NO.§>÷öª?ÀóÏãøñ&~ô£U¬[÷ÓȾ†¹!Ì‘¨…”b1Ì—:4¤þW÷±®.µíp—_þ]R*øþýç¡c]ËF˜•|û©T ˜:"ÄE ›Ç6lÀó<Þ|sm¥ÈIÊm4n£&¢µŽiD”Mµ…êAˆAAA¨ýš71E30 uT„“ˆº× Àj`í-¯qüÊ´sÞyçqáòå;vŒ½+VÊ ÿ¹Û?:„2¨ÏXc`*m<…}[@¥ô*–þ2„é‹r(åB›÷¡éPûÎݧ¦ûpï¦{•Ø2¬w• ”n¶á|nô`­¯æƒºùh'«vJƒr”êÑàÚ‘j“V‹rß– ëy£ÿüÏ|ot”B¡À;öí£]5‘Ïþô§tù>—9Â9·Ü¹ûöÑ|ä}ïã·ÞʵÏ<÷æ?<ñy„"ðÞ;8~ü8¿yå•Ü4<Ìß¼ù&­¾OÊuY¿~=k×®å _ø¿ò+¿ÂßüÍßpÕUWa_üâƒL"ZÑ‘&Z\±,+ «vÓü:–eUå3š¯_©!*kÖ¬áÁ ¾ïÙ³€ŽŽŽ`ÚØØƒƒƒ¬Y³fA¸ära”¾]àÅ_äË/gÅ+¯ð⋪8üúõëØØÔ„ïû¼ñôÙ¬üHy*¡©žu–5{çíúõ¯pþùc¬_ÿJÕëXÖìú–eñ ϒÉ\Á9çÜO6û;e£õ£‘ÑéºÈ}.§¢@tÍ–èqÕC2©D%¸º;¶Ã£O ŒŠ™ˆŽTP¿§k-™fyM”ï|çý|úÓû8pàÉi÷]ÿv6«~§«krTD:]Ù£oÓ¦g9thO=u6Ï|åÈWJ¿ãÂ_fTd (§S)bƒSQ],LWW(œd³êsg§r–êÚ(ºVeáEê|í‰'0n½•¿zí5Úþõ_ùîç>ÇGþð¹{ÿ~^2MþËÌ‘D‚·z*WíßÏøËK/¥ëÒKûøÇy䳟å6làÈ·¾Å'/ºˆo8À©ÿ8m»vñÊÍ7sõ 7ÿú×I ñ;¯¾ÊË<Â×\C±PàŒ[ná¢d’³o¸Ž-[Øø¾÷ñÈÆxíí\商Á³Ï>K2™$“ÉP(è+×uË"G\× j#O7ÐW—œ)éW”.ò”ûüœÒéÔ:Z‚ÉY¤ô)^;²–SÇN]Ðkµª•-[¶0<<ÌwÞÉž={( ttt)cccôôôÐÒÒR–,nXV¨øG•cÇŽqà 7оl¯¾G…JqÍ5Áz¾ïóÆS§«Ï”rëQ®žÎ—K/=ƒO|âÉY­“HÌîaÛÛÛKsóãd³pÎ9÷W˜_y=ÛS‹U6Òi%‚ŒŒ¨ö$“°oßí¼ôÒrÖ®]K6[E3•Ýè´\:ÂGGÎèÿ+±víôG³»æ´ R­_yýúƒ\vÙ·=‹ßÿý††T›ÒiuLÞùÎÍê÷…r*ÕMÑù+¥ŠrQé¼ú€u<Â]ÄU_ÿú¤g/êy˜¢d·Fø,‹;õHû%‚ ‚ ‚p²ÍbGô{q¡0¿íÂbÅEéÿêB“ÇîŠeC}¼ï¼³ÊÒ¹;ŽÃ[OSñ}ûG¹}ßíÊÉ›@ !}(o¼…òÂ'KŸÓ(‡®KXûD§øÊE¾'#ÛJÃÁ›ò¹ÕŸSß“aÚùI!e‰D8 ];RujŸ¨ÒФþÒŸ‰ð&Lòÿþõ_S(Ý .>x?:tˆ/;Æ‹W]Åÿ»¿ãOß|“þ0ÛŽç»—_ÎXO÷¾ù&oþþï“jogYs3y`Óo`Ûššxø=ïÁ0 š››¹êª«¸nõjn^±‚ï}ï{‹EÒé4Å®.þqëVÒ@_"Á®—_¦|nÓ&ž¾í6:ï<ž:ýt~áw~‡/~ñ‹¤Óižxâ 2™LòKŒÿÍ¿ýÛ`—SÀ—-ã×þâ/‚ýÊ¡LgôyšKËfP¤õ@i@ä u–þôé‹f¢rÖÒú]À'?¹‚§~áÕ½^«ŠPiiiáóŸÿ<Û¶mc÷îÝttt°}ûv@¥þÚºu+---ìØ±cA·èè Û.BÎDà$“´—_§ë⌌ÐW*<ÿ¾o~“ËÿëeàòË‘ÌýçÿÌÙgŸÍ‘ï~—ï¾ñOœz*FdÛ~éô™ÀG_}•_-¥tÓ§EghÓ§uÄŠ_Z_»û´0Yšg÷»–.èuZu±¶¶¶@mвyófvíÚU–þ+Žèz;¼°†~˜¦¦P<9ãìSÙ™ßÔÔÄ㞦ÊÓTt ¢Å6–<75…Ù‡ÅêûÁ¡CMÀ‹³^o6¼ñÆçX¿ÞšU]ˆ©  O…mÛ|ûÛßaíÚTGa¡¨v­Õ~³$¦è«U×úŠžéªò,Ö³mu°mõÛ™Œº\WuXu PQWqØÇ¼AAA¨„öyÆ= €a(ÿ«Ð*'#ðR6¥aä£'Êæù€±,,6Þ¨r GÚŽpŽyNPD>ˆNÑÎ íµ×¾ÀaÑ=Í&PJó6]wßþ§R_ŠE><6¦œÌ:ÂD;‘´J×@Ñi€"¢ÆñC‡Èd2ôõõ‘s Û ºëÂí™LÛ¶Éd2X–…aüù{ÞÀ2”èpÑ©§rK)wþcúPÙq2Qu…«¥¹¹9HÍUÉ·ªI"ò=S:dà®] k×Ò¸–Åy›7óüмõ‘Gh¿æzKm¾ì{ßãÆ›nâßÖ­ãøÈÐ¥—â¡-š¤QEívua÷õ•eoÑ­­ §ÊBéh¥²7ŒL؇3¾üe¸âŠÙ\Š3RuQú©X½zuìÅ”/8ðÛXm–×=¹ÿþûY¾|9ëÖ­ ¦ý?Ÿjá#g¥©©‰s>ðɉØO^Š0´h>ÔÃ)hš&¾ï×¼ŽÂ±c8t¨©¬XüB5ôZïÏÕW?̹çî«éoœŒXÖäú)žçaÛvP,M˜¾Ò¡¢)Nÿ~O›Y*EŽN )¹\ø¬‹F³Ø¶†u ±B‹j"ª‚ ‚ ‚0Ç™]ÊïFbšJrÝð½UN´¯ÖŽû0RPå¢Ú$ 6ÝÀµ×^Ë9÷Ÿ£BL”óÈ&tئ S~i2„Þ{½|ºÔ í¿æÞËå8l¬ÔPŸ+FFÔ|-ª‹ê/m2[¯¹†d2‰çyd³Y2™ X–U¶¯¶mÓÛÛK>Ÿ/[?Kn;ãŒÀZï:³F©}‘¿ÞÒùéY±‚!à¼{îá/&¾ÏEwÞIøêyçñÚ?H.•"×ÙIÇßÿ=i¬4Åb‘d29ÉÇÓ9f…6y„%&Òt|á3 U-¨è*[·neÛ¶m .xcjÅýÀ «<Ý׿:Ä9çœÃyçL;ê)ãòù/}iòÙŠ ¿óÅ÷ýšB½ îÜsw*]V­÷EX¼8Îä±ß~æ~ùÚkqP7i­‚ë›ã|Ùv˜¢²·7 «Öh%‘ÃÂ5QAE§ ç©}YLÔC rêpPô}@¢ˆAAA˜ÈÄ÷º8£#i´VNõa ôJ¿Î‚ V¯VÅÎ?&À|hí‡Xþ²Ê"¨,:7¼Oyx†}ˆê:ze¢îÑÙ~vœPÕôÖ¬YÃîÝ»ëÜܹñLVV¸®W®\ISSÓù=õÑLyº°…f65@¯¼²¾TCE¦&™„gžùã _ä¶/™óÞýnú(¨¼Š•¬Äó¼i#®tý1M±¨:ÖQ“3ÍògŸa¨bù¼[V¯~€óÏ?•d29¤Se&“ªæŠa(¡%“™ÜÑ­&d»Qj©¦ïi9"‚ ‚ B#˜øÞW \× œ€] a®ÆÔô2™øÞ„9ãÃȾ7ùÎæ•WöNž¿Îl9“SN=SWK‡04a6ã:]7tÜxže«Ó‘LHåuÏy畦e•¥)Ùô'—_øt …BpÈårADF>Ÿ¢0âB­Ú¦I±X$•JEï§ZN#Û¶?•®-S(hnn.XÇixÚ÷ª‹Òwtt°zuX{Ë–-sþÑÁÁAFGGY³f mmme󆇇¦¥¥…–––…ÙK Öš*ÌŽ=ÊêŸÿœK.¿œ«Vñ83×@9/ µ¼Ü—JdŠÆ¶n¿ÝZti¦ÃuÝ%? ~:Û„…·ÏÎN0Œa55ñ[?ý)ÇþÇÿ`GSåQš:„°Ra-×u§&Z–NçÕÛË´èMú><õÔïð¾÷õrÏ=çˆ靖×U*½½jDQt€„1zðƒuäûêÙ­ŸÃÙìdÃ÷Õ¶}_‰; M=rm6ú!·”¨·} ‚P=uïÛ ‚Pòì„øR/û\¨Wø®®.ÒétÙ`XíÔs]—L&C"‘ª¾ï“ÍΦ4t9‰„z4MõYýžúžÉÌü>+ó¡Þ}Û•:” §n:ÂO<Áû*ù+FàÚç¯åÁ瀳Es!ê°´íòQ³ ”B‡_z‰±7ß ðj( $“I2™ †a`š&©Rêß÷) ¢B"‘ ¡:ÔÊ/dš&Žã”¥4«D2™Ä4M à ‘HƒrÓé4©T*H ¦£\ô êb±8¯{ì|©ZPY(î¼óNúûûiiiaxx˜ŽŽîºë.vïÞMOO›7ofïÞ½lß¾îîîùïdÄ£zêØù|ž«¯¾šk¯½v’²Æ £Y¢ãªf`u_ø]‹+â*œš¥èH]j‘DQ¦³MXxûÔ£…ІÅï]~9ïàfÀÒ¡”¨Ô_´m›\4w×4´C¨ßô¼êG*égËsÏS6Ý0T'¶µµ¼3«—/ÔçÎNõÿÀ€ÚçLF |ÈdT´“J©Žëº\}õd2JøI$TŒïW_HÑu'ïŸç©m<ûìêYÙ¦ŽbÕžLJý*ßÔç®.y¨–zÛ§ ÕÓˆ¾­ 3#ÏNAˆ/õ°Oý³P¾B×uƒ3ztyWW¶mãyÅb1p FGYÏÛVï’é´Ú]¨>V´µ¯aÎ4¢oûLå„õáÕeG9>Uñ1À³ÜKKÓfcjÅ¢2(í0™˜QÃu•a¹®õÚÚÊ?Ù6#=¦ÉþýûƒEÏ#“É`YVPóÃq’É$–e‘Ëå1 ÷$s~ضÍÈÈÈŒËEÅ¥è vÛ¶ƒãçyär9’ÉdpßÕµYA]•ÁÁA|ðA¾úÕ¯²zõj†‡‡±m›îînÚÚÚèééaÇŽttt088È­·ÞJGGǼÏSxýõ×¹üòËyç;ßÌׇÞŽÚJP9Hyìå¶é”–_Èd6žçÕÅa_¯ ®©~tG¦Öû£ÐK-’H3“m jŸ:º£·ŠFšþõ_3Ô×Ç]³ Èìše«E³áÅ/àøñÇ9ÿü1TÀ©Ä×UÈÐP؉O$ÂÑE}}j¾ÞåBAÕjY·î à օP|ÉdTÛõËî\ƒêض)ô³_÷ðÀlß¾½lºe)Qà·ß|³¦7×k¿ZR÷¥çr«}Ç;xå•W¸öÚçs«ZG×0+õ«gÄ0`dä š›ÇqÊ÷£‘-Ñ(Q-´èH‘è:z€ÅÄ—Û†o~ó'NœÉ¯ÿzù:ɤêC ” >ºQ(„ŸMS-¯£Ròùòu®¹æ0ž×\¶¾þ ÕÓ¢‘C¶FäèPöÎN5M_;:šæýï?ß÷yòÉOP,ªù†_þòϸï¾'xûÛÏáŒÇ‹ZØçáÇٺu+[¶l‘ô&BÝÙ½{7»wïæ‚ .htSæM½û¶‚Pk¤o;·¾­ ÔšÁÁAzzz8pà@£›2oêÕ·5ÍÙ¤ÓõOR©TP”O@ 'Z,I§Ó˜¦I:üZdq‡\.WæpÕ477344„ïûU½÷öVŽ´Ñ™00[˜€ôm«ëÛnß¾½b½$€£üB2°òö•\tÑE¡¯Ç+ý ¬G9a/^'tôLd¢/*šèyº@‘¹™Ï+gC&Ã==Ä/Ú6~"A«ir4•Âu]Î<óLvìØÁ¶mÛèëSu!& 'qª2‹QP©D5ezzzxà¼o[• ÒÖÖ¶ /uÃÃÃìܹ“ááá ¸½¥ÑfÓ¦MS¶Íúz¡=bG'Nœ€Ó¦Þí3³ÊF_˜0ýÂì/}žøL6QÑ0ó¡^!Júa~2D]Ôƒ]»vÑÓÓÓèf,•lænŸ7ÝtSÅN×UBÀãŸlæ#@Îuƒ=µB×*sPƒ¼Èô(¥´pêk7ndè9óÌUÿ^«çÚ“;ñ>JÔIR~/1M%¨@˜þ*ºNÕWˆ¶W?û}r3·´N~Âïxœ8q&MM‡*¦>«tÒiÆ*ÕqÑ‘/yöÙÕ<û쥉sTŠÆ4Í%#¨T,P«~Û¬k¨ Óßß(---ÜxãA8X5èÎÀØØ·Þz+---¬Y³¦âoM¥^VƒïÀß»€O<ñßúVŽ;Æúw¼cÊuöeà,;ŒPq}E 9ÙùªY,Ï0Ã0’[NXT²Íîîî·O×…§–gž ¦Õ2=\žÐFuꯨ b£D %Bø¨²K6Мm™ýò 6+ÛîTBÀHV‰7;'î;JPñJÚ}ûnç«_¼Žm£¿c*’Õ4'‹Ni%Þh<^}\[&PL‡ç©’ÙD­Ÿþßüækœ8qæ¬Î•®ùaô‹˜*µõ´ÓNãk_ãÅËG†:&ú§_nšUâJ½ìS„ÙS¯¾­ ³Cž‚_jiŸ:Åt5ø¾çyÁÿ¶mcÛvmRi0j5>í´L¥RAý•D"A±Xœ÷û¯iªi ªÇ,,qÕ·}ÿsàÀÚp‚ƒrˆdÀH¢R}][ņ¢Šc)’PN…T ·”.ʶmÞ|3§û>ŽãP,•ýþÓ?aš&Éd’³Ï>›\.G6›å¢‹.jÌIY –’ 2U°@.—#—Ë‘H$H$ìØ±ƒK/½tA»ê* ÂdlÛ¦§§‡ÁÁA¹óÎ;¹þúëÙ¹sçŒëïÞ½»l¹Õ«WÓÖÖàÄ0±ÑÑÑy6zÞ‡s÷íctt”Ç322ÂÊ•+Éiº,à8•k¨ìw¦ÿÅ$Q,•t_õf)”šÎ6·OË‚¦$lĶmLÓ¬© µÏdé¯Ð„Žæp#óôw 8ëý?2üô=ï ¦kÁÂ2~ÓC -•nSÝ/Î9ç~Nœx~Ò(#ošu #,êE‹Bïs¦ §öbpªAG¨ÌF‹½âŠ–/ÿMM‡ª^GGÆê}™*ú%Še)¨¹ùÇç­ZõóêSêmŸ‚ TO#ú¶‚ ÌŒ<;!¾ÔÃ>gzuw'p(ær9:;;I$ŒËèšsŲ¬`´z"‘ “É`š&Ùl–|>?o‡f"¡ÞÏtýH˜º~§ TK£ú¶G=x܇þã[ËgD®ió•òYSº'|? O+Â\éÚ@J»$p\óÔSA”šeY$“I²Ùl`§¯¿þ:;wî Ò.tšÃ¥DWWžç144„iš8ŽÃu×]ǪU«ôwªTzzzؽ{7wÝu=ö»víb×®]<öØc$“IzzzªUÆÆÆ òcvttEŽ@åÍæÆoœûÞ™pEÄGûâ‹/–EÒL|ÆÀsÀ«þdü&þ)ðª&N×ETY*ЧÆmUòEÆT¶ ,¸}z|Ç—?ÿyLÓd(Z]¯Æ˜¨¨ £ô9‹Fôçdd™JP9Ú¬j|êŒ3¥€ŠtI¦ë*MÓèî·žçŠ4ndž~$àÏqðàoO>^¥u*YÔÀ@X/¥ªý7•³Ë)¬ ÊW‹mÛ;¶sÏÝ=«¶‹å£¬ª¹UÏ;Þ1R}ã!õ´OAfG]û¶‚ T<;!¾ÔÚ>§ŠPñ}Ÿb±H*• ë”> í#I&“$ H$A1e=â}¾£Ä C½7år*kA±¨>W¢Ñ>ÓÅ<6µÒ)Z⮡†ôm×þ;8s ¼öÚkÒ/:;('͹À;ÕW‹ åSôÉrݰ½vztv†ó L“ã>J±¨rôõõÑÛÛK.— ê#éZ׫V­bÇŽв”XJ%!´@”Ïç1 ƒt:M6›å²Ë.[ðߪ*å×àà ;wîä¾ûî›ʵzõjî¸ã@…0êÏ•èîîfÏž=A¸ØÞ½{¹ñƃ¢aÛ·ogÛ¶mlÞ¼™½{÷²}ûöY¥‹â8°Á†c/ã¹çžãDw÷Ì‘aPAP¹Â†Güð7†zE¨Ô+¢£^ÂÍRN•6“mÂÂÚçC\nÂSž×ð㪭ÂB‰&YÀ½ôRž§“Êiºl “0"Å!ltßUGµø¥åÝ ÓA‰º V±ôûùÈoèþ±SÚ¶>r•ž:Ú¦P¡½##W°ÿþŠëèöUb¶§jÍš¿™õÃy6âÀ‡?|€gŸ}–M› ºØßÅG½íS„ê©gßV„ê‘g§ Ä—zØg29Å;’ëÒÕÕ¤ÝÊår5àgY–eM*Tm•Ò ÍÇ9kšJTñ}%¦ø>d2jÿ£ïnj€\­Óƒ‹aÖPíqåß6MÕ.ß/¯ ®ÅÃPÓ|_-¯ÛšÉ„ÛÔóµŸÜ²Âù®«æ%ª:m´ç©méiɤòµGÛÜ×îÓÁ –¥¶Y,B:]¾½\NeŽÒûbÛðÌ3³KuWÑ·í.¼>Òð 8ûìpf–0¥È¾\«ü-e—³ã¨“êºå…” ^Ù»—Wóy ÏãŒK/%‘Hà8Žã`šæ”å×­[Ç7¾ñ >ÿùÏ7ú-8K-‹Q½|ŒU *ýýýtttL›ïŽ;î §§'Xv*víÚÅàà` ëî£ƒáááIóf‹Wúç'šOÐ4ÅrÑ‘â$àjöF&9ÀH©†ÊD±Ð^S,˪KèX"‘¨‹±ø¾ßpÇ­™Î6aaíó;.\÷‹ûØœˆGè—ÉdA%Š6ÑÓ§³õ,¡Ð’+ýY¥íz‘íE¥?ýÙ%¼†t浸¡çë#å—Úe¢R“EÉ”~{(ò›…ȼòþsËJ—M‰Š8 qf\×­i*7€C‡šØ·ïvZZ¾[Óßi4õ´OAfG½ú¶‚ Ìyv B|©µ}¦R•S»®ŒXv]Ã0–‰"N“Édhoo§¯¯oΣĵÿØq”ƒ¿TÏ …ÓT”`óýP„ÑiN£tÏSÛ+ ðÄ PÓ2ÕÃP¿­}܆¡Öëê ·£§çrjÙDBÍO§ÕvÔö£µ<óù0GGèèÓg¡P¢k˸®ú‹ÖšÉåÔ6LSý¦Þ'=϶Ãåõ1ô<Õ&½M}Ì4Jd¹Œ»ïþ·†\K M½û¶Eàœ?9ÁÏO;Ư¾Î0QEm“Un(rá=z”µzðµã¨‹ÇóØû÷ϧŸN2™$çy¼áy_q¦ûA2YmC„“ª•ÑÑѪ66e:afA;³>BåºÛÖY¼åå—áŒ3f\‡Y<¸L=šûd§“zÝÐêáŽ3[(ûVëc#Re™•f  l½š.nuÑ‚Š^Ï&ŒPIG~Ï-}öKËéc¢#L´é”_Z\)Vøm§´m‡ò”bEBaFK(ë×ß©:—¶šÞ™¯c¦ˆPŽƒa*ÍZŸãóÏãÊ+?ÎE-­Q•¨—} ‚0{êÖ·aVȳSâK-íS ža– œó}?x¯·,‹V` A句aÏç) ¤R© µÐ\Ñî ËR):ÒÃ0TF{{(‚hA@ïz)ëQðÝ0Âh“¨àÐÕ¥¦Ù¶Úžž¯¸ (AÂ(–,‘P‚‡i†¢„®™™J…ÂLggØ&=­P… ½.¨ù‰„Ú¾iªíi±D LÙl˜ M 4}}j_ åg } …pÿôg}’IµlV­k°qãqž}vSC®¥ZP÷¾ík°ïg§ðÖ+¾ÊKü'¬O¦ Ò©¿Þ ¬Œ¬£OÈÄ Ça÷îݤR©PUËfÁq¸ìøqþÖuq]—_ÿÎw( tvv’Íf±m{J¿ŸaSF¯¥Qõ®«TÖ¬YS•¨Òßß?mʯºãÁ¸'~x‚¦¦&Ö:ç7mg|Õ¢™îÑWp¼‰‹Ã|¾,µ¸Fâ§[pìg?Ã|ï{Ý`rtŠ&*zD¿O‡AyZ0}k×é· Êk«èâõÅY·´‡PãÕ)Ätº/P¼Ñ¿£…+²ŽgrÀK¨Ñ§œòn^B‰-Z ñJËu–Öé*m#*,QÑ.>JD)”ÖÉ DŽOÛpÉ%Aª2ÝÆD©]&GþÌ&àÝ55Íb AAA–:É$\õ·ËëüÇøË–Ó£éÂõûJ†0ÍrcÚš$—ËNÁùÖ3Щµ´pQ,*Q ¯”Þ@ׂC:­þtt†v}háB§ÑÒÑ:JC§ÑÒ©±´oÛ÷Ãt\ª-z™|>ÜN2 –¥~Ã0”¸20 Öu]Õî\.M‰0*§¹9Ü_(O×¥SxéH–¨Xáïéeuê4ÇQ¾wË KnèïŽ3yYÓTïxÇA{lé*õæª?ÚÏ+¿ÿ6~x\½ß/•fô¡œ°vÂJZ Ô'GŸ\Û†ñquâR©ð¢¶m6vu‘Íf)‹†mÛÁÿÓ1_ÁS¨ÑÁüõŒ8¬JPÙ²eËŒé¼zzz‚"Eq@?&WÐ4Áá>qy Ø` ¥¯QêD§«®lWÜîå,AådˆN©Eà†xoÑUóm¥¾¿DkªY¨Ô]‰ ËèÏaTJ´K­£A<”@¢³Ú¥?½Ý¨åPQA.ðÇ6mþ ¯ø-ž°® YjC{é-ø¤PIPtqJßuW"‡@ôú~¤­]Àøø8àxdŸ=B!%šjÍ@½ÌÌ„sôcrüâ‹iž¸òJšKí‘@\AAA89ñ}ø¡G’¿Žyô(®a`ÆÈ­ž¼Û;¨w‡Â|~l0M“\.Qž/z‰DXOFûšG‰é´ ô¼¡¡0Ú"—SëE£O,Ë¢««‹|>O±X\4~)¡2Ñóçû~ÝÎgU‚JKK wÜqÛ¶m#™LÒÝÝ£P(°sçNvìØÑ€CW™Ç=hÉ«‘Ø«Ÿ}–±óÏç´ÓÔîFkèûêDAeï„íåú‚Ð0YhÑ©|…iš Òˆ ó)'”ãOfà¨çÍ{ôM=Ñ…ægK´NSzÂtþËEE…èÔ`]„BK´ø¼M‘Jè*­«—5(O¿•´; ìwà{ôqìØc2Âh‘‘HÛ¢ýI›0˜C(Ú@yDŠ^NÿïO˜íÃjñeâjޝƒêKéQdËš›±|ŸågE¾tL¢udAAA8yp]øêË/³òË_æü–Š·ÞŠmnƼêtɹ¹þÐbš&…B¡&)Í'ŽqM§Ë#QtmiáyJ,Ђˆþ_gŠ,Ú‡mYá´¨ëDê×ó,«\xr±G×èõô>LtËTrÓh‘h!H$&¿(Ñýظñ8oûá…ùá“í+yåð[X~Öi¼ucA¥ÖÐ9Ïm «þ›òÔÚ¶º˜‡K_{t:ïûé4$ 2™ Éd˲0 Ã0¤.Ê`¢_±^~ƪ€íÛ·P(‚h”ÑÑQÆÆÆhiiaÇŽlÙ²¥Ž‡lzž.™ì¿r?ëׯçDS«W¯Ä)ñàqí5Œî„戗qâ=UôÌrä¦$LÅ—ø%¼E–4o¦Z"S¡£2 |PE‚P4±Q"F1ò]‹/QÑa¢ cE>€ÈúšèQ6€´ÿ²~=??òž Úe¦ö&|¯„NG¦"ÿOD GsÁ˜p¯=q‚«m›¯½ë]X¥cšA‰6 ÝAA¡þø><í4¶:Dîþˆ§žÊßüÒ/±âÐ!Þÿ¿„Y â10Ö0 |ßÇu]Ç©y†Œèî¨(¡£I&þ¼a”§òŠ2×N•UKFFæ¿h{ç3_˜}9¼ôüi¬X½‚Ó×TºQN’ Š2épëð«ÎÎ0ì)™ä¥¾>2_ú–eQ(H$ضÍÀÀ@E'Ÿ?¹½õLµT©ZP%ª$“IúûûÙ»WÅptttÄ&ÍW”Ã.œž„pÕUWñò²ee©¿l‘S9÷¦Ò´ϘzAˆ>êwãóOÿ´x,)e2[lÊÓyM·\ u™­@kNø:ÞeÀÅ·=ÍSÿxiUËëZ-Õ´¿•°æ‹Ž¦™jÙ©úž>a”Iï„cQ©Ë—/'›ÍÒÙÿliýiÅsAAA–÷»púÛc®2¡µµ•?^¾œoþìgœ{ûí€zßÐï#qægY¶mãy aš&®ëbš&†aàº.¾ï×TlÑQ*•X(¡Bêz •X}å ü熞E¥â˜˜ŽÍó‹Ô4ÃB6¨{kwïR{éÌ9­­­ I (àˆÖ•fÇ)³]aõêÕlÙ²…íÛ·³}ûö@L¦§§§ÑûpCšm•òkýúõ¬[·n’ ¢™êþÉl8M¢Qan8ÀxüñæEW_g®‚ŠIõ…Ö(!`¶]äh´J5Ü4t—-_^õïhQÅejAÙD¥Ù@¥Óí©´NzŠö¥å½Òö&sêmRMAA„“‡g€ ßúýà}Ó¶m¾ôÙÏò¾)¢¢ï ”G½7z¬¶Tt›‹Å"Åb‘®®®à³þËdª©<)‹‹5¿øïÞ4Ä?í&5áñ),¥õ (U”J*LX»–\.‡ëº¤R©@XYl>¨Z­1âyÞ’:.±+J_ ÃÃÃìܹ3H Ö(tÑç/uÁy}°råÊÙn°â1zA+.°Ìƒ ×ãÀF·¦z„Qµ$Ë yA§`ºˆJ¸®JmXí£&š¶l:áÆœfýj˜X›Ê›a™`˜,ž¥õϘÅqAAañâyð¼-ÿôwX÷w€TÇá?½ç=<‰zwH¾sÅa –®A«#Pr¹œªÿ`‹EÇÁ²,|ßÇóG UãGƒÕ°nlš°jŠl;¬£â8J`öïÜÉï—Ò{™¦‰mÛ†!5B¦`d¡Š"Å„F¤.[’‚ŠªŸr扌P}ú}èŸu¡}Ž¿+ÂÔx¨ç<ÓK29»s`¡j»Ì¥~ÔlE•¨h3„*t?W}Ûúí׿|œAAAX8«è “°fæb%´€bY]]]$“I’ɤˆ*¢£Hé]Þ…7_ÏÙ[ÎòWJ3Ϻ§XÑ4Õ_Ã0H&“tvv’H$‚(áäÂqæ“'evT%¨ 3888ãrukøTèA×ǰނ„©Ÿ}âî^LTŸ>Ô‹Fn~7úrcV˜_iº ‚ ‚ 'ÇW÷ïgÅŠÙ­7SýGÙÕ“¬:ÍM±XÄ4MÇ!‘HÐÕÕEºTW¢Q©p–*:Ó†W Œ‡ sQ‘)Ó¡SmضúÒé4®ëŠé$ÇuݺÚfU‚J¡P`pp]»vÓzzzèî¥¥þGi¦2T •çž{Ž·½ë]ÀÔᛓG]ñà9W9Ÿ-Ùªa”¯?ñÙÀ*÷¦IãG-¸Ì¾ÞÁ\Ö„jq n„PWæRÜq¢^mÊFAAANn^ôàÐ)‡¸ýö…óÈP©‰âæªM$$‰@4ÑEë]×¥X,â8NP”àû~-¢X,’L&ƒu •À>“É`YVð]OK&“8Žƒa†mÛ“¶©?ká!™LNÊN¡×) Á|½¼çyضM¡PÀ0Œ`ÿô:®ëbÛ6ÅbPƒ4õ:®ëâº.‰D‚b±´¿X,’N§ñ}?˜žJ¥ÈfU¥ÎT*E:¦P(N§1M³¬mÑ6A(¦èßÑ©¥¾ô¥/ñÖ·¾µÑ—Å¢À2„~Õ¦~8f>Ø• M€-w5É ®ÇB¡ â¡ÜëÅœ‹Òïܹ“ŽŽŽX *Ë h2áØ aʯ©•JÎ:ßW¹7IÂWR@ŸŠ(óJËû„NÂhÍèE‰*C¨‡®A˜ªÆ+ý-ð\MÍ• f²ˆã”~£R[Wiû½³8n¥uúf±N{é¸Îæw„“—GrpsZ)ÇÂÒ'Íì^< Ô=-™f¡îÓ­#bp qQ'_o ‚ ‚ u¢- ç÷1!çHUx¾G}.…FïÜ$‰@ H¥RxžG±XÄóÊ÷Èqœ@Т2 …Bà Öd2úúú‚íE Ã0H¥RÈâû~ :h!Bw]7(žËåH&“¸®¬§ Ú1žH$ÊÚÞÙÙ?z¾ã8A-=M .Ñöêu@ù ô2Ñcáº.…B×uÉårÁ6 ÃÚ_,ƒýÐiÖ€à×uùÌg>ÃÝwßÝèËaQàOøÿÊ¿‚‡¡l4f™$ÚÙ é´J÷UоÒç ›ÍŠ "P,éí­Ÿwz΂Ê|fxx˜\wEÏkii™³X3æÂ‹.}ÇÑ9Õ5Û\ØÝ MÀÙE(xJTåÒi½&¦÷2 €Né{Žðá¬ë$K˸¥íi¢.¾e*ñe¢ u*Ì~T·ÅìjxTŽð/ÓÙftþ|ìÓ¶8ôX·±%;Ëå-&ŸÊ™N«…°OêaŸsÂ',pÓŽ*¸S¤úQ‚°¨ußV„¹Ûg§  nŸ.p Þ¼@•Òw–þ þ¯š†aÐ××Gkkk9a´‰ɯÿשq´p M¢Å‡L&Dièeõ¶£ëèmA(`D?GÅŽ\.DyD—Õ"JTÔÑ¢O¥mF—-‹S éý‰þ¦N —´@zÐ‚Žº1 #8ú·µCßóÛèKaÁ¨WßörüðÁiò¼ :åá‡æÌÒõ›Íf) eç_89I¥Rض]×´o§Ô{'{zz¸õÖ[Ù¹s'wÞy'·Þz+cccìÞ½;˜wë­·²{÷îYoßE‰)oÙôk×®-{”Îæ°®·`Û$“pæ,ŸÇºHroé¯õî+}B (}¥69„ù83@sé¯P”™8_7I '^iù ¡Ð¡o'TÄJ%Š¥mû‘íU‹ŽØ™k¹!^Lg›0ûtQ¥î¬Ì› ªpQS_à¢CߣX¨S=•H<Ûú.‹‘ZÛç¼(¢4.á%ú9®Ãùa¨ußV„¹ëg§ œäÔÂ>} É'ˆ–˜9”È2ÄâzÏÐ)² à N“ËåÈd2 r¹–eÇF§ÄÒ©µtj+í˜ÖiÁ|ßj²$“I,ËÂ4Í V:"HtôŠeY$“É`9-ÒèmÛ¶¬£ç[–l3™LóõvLÓ,[G;OutBt¾>Ñv$‰Ió£íH&“$‰ …—ŽœÑíK§ÓÁ:z¾mÛA›o¹å–%#¨Ô³o{¡ kßu|ú…’Ièí…ñq¼öZ€ ª(š®N89I§Óôöö’Ïç翱YPוááavîÜÉ}÷ݸ·m›Ý»wsÇwÐÓÓÃŽ;èèè`pp[o½uNiÅNø°üªWXß¼žý‘éÓ=+Í3QbÁØ,óÉèZJk®Lüh{=˜×#|hgP~â,¡?JG·h_U‚°NAº4-ššLG±L®gà”~Ã.mÇŠ¬¯#lF&´Yç:LFÓ˜¥ÏÓ¥1«y#ć™lXûl‚`tǼpQ¶.”A)Š}¨ ÑGŽ\tK‚ê´ž¬©½êeŸsFçCH> tŽK¦™œóÖ!ÖÔ«o+Âìˆý³SNbjiŸ&àâŒM¨ˆ(ªk¦Ì&z\ÐuA´˜bšf ®èÔXz¾Ž¼Ðëºd³Ù ¦‰Ná¥E†l6¤ÛÒ5Tô<ß÷#›Í– )ét:øMÃ0H&“ø¾lO·Wo3›ÍmÓmŠþŽþ®‹’ëuµ@äû~ ªèÈ-˜hF׿MI¦Å}\ô::’%ŸÏmã7xòÉ'} Ì›z÷m?× é ÞÂÓ-q”ëZ=QQL8¹Ñ"n½©ZP¦§§§lÚž={èïï/›¶}ûöi·ÑÑÑ%À–-[¥¿¿Ÿ5kÖ¡dmmm´µµÑßßOww÷¬vê˜Ë/=ÌeûOðí ó¦oN1-‘†Ï§Tš¢j™mM‘a8iTxȦÌ)F¢h•^7GÉR¤ŒnŸž=ž”¿;[šž*ýßÇÂekÒ¢mÂ4jZó(~âVL.Lg›À‚اä³P,zs»Ùy¨‹I_,ÑØë,Ê´˜b––MÏò7„X¢ï3'§FVûœ‹’%Q'(CxC7 íðdTÁ„“†zõmA˜±{v ‚PKûõàyon94 Ô€V—Å‘æk&¢‘(Zd˜øuF ©DÊÑ‚ôшŽèÐËNü<±†Ž©E ZF·££a¢T“áBoC·ob»õ÷hN¥ýÐ)Ð&:ëµø]G·m{’ot±Rï¾mñ/`ì¥ê“'éÈ b±H_ßb”=…¥BUW­Î‹788üutt0<<\6mpppÚíttt°k×®àûØØ{öì ¶=QÑ\³fM³o*8ÀÖ­[˦]œ‡'NÐÚÜLÓÃJÎûJ·æ$%qÁSM-Å®h{¦ªG’E=ÜmÊ…‚hT‰2ÜÈgí˪”šK¯£‹:k ¥ß±PÌèŸG¢Å½N忎¦æ)”ÖÉ£|Ý](±I·­ %&-#ÌYÚŠ 6h-Ík-M×A‘éNd\iz†P JE~7G˜Fm:ÜRÛôo´FŽq'af€­[·òÀ,ÈuÐH¦³M`ÎöùÀB¬´·ä1­’iµN_ êhÈi”¡ä)¿à£9í„EËlÇ ²uëV>Üè¦Ï›ZØçáÇٺuëìC´Ô5J†ðA¢P÷¢l±õ@•ÜB„Ý»wÓÓÓÑ#GÝ”yS¯¾­ Ô éÛVß·„z¢û¶htSæM­ú¶ÿß°ÿá—æœ A Zli¾¦"š®JŸË6NF,Ëš¶¸µišeó¥o[]ß¶’ÏØ;/ñRÕíÓiçt4– ÌDOOOMú¶UE¨tww/øH={öÐÓÓCGGÝÝÝ;¦Õ„ŒmÚ´©ÌØyðT Èã‚ .¦G Z ˜8 À4K"LŸ¨Z™ÊÍl¡FIèeÈ~DE‹0ªD§ùJ£|\]¥iY”ÿkâ:úv¤E] F :u˜NtäGš0ZE§6K¡|i:E׌ÑíÕ‘5:RʼnüŽIyx­hŠ”ŸÎEÖ±) Ò#Kt 5-¬T°)íO¾Ô– aÍe}LtF©]»v-¹—ª‰¶ £…¢TcŸ7ÝtSµf¦M0Ú#P§ò”Q'-Y®Ú´A6ê¤gJßõ…*,Z¢u¡ª¡­­]»v-9§äBÙçºuëÊžU-ê¥ñ Mïa0ž‡â߃ýõ ¥@yŽKᤧ»»›–––%3’OS«¾­ ÔéÛNO´o+õDú¶3÷m/»é&ú> Æå$³Ä%,]f梃D¥o;=•ú¶Úé Á©M3Ößó”C¶t>2åä1 C"T„ª¨U¿­®5T@©›Û¶mcxx˜»îº+[³fͤe‡‡‡ËÂ̪áQε` 8óÌ3§]¶çœaÀ=u¨k£Óh™3,£‰Žšˆê²º ;‘õ†P ÊÅ ‹pð¿MyÝ”èíI—ªÐ"Ltz4xS×ué"L6±†ŒŠö˜èãžè§ÓËêߢ#h&=OׇÑmÒA ZŒÒ¾úJ×A%­[‹n¥Ï©Ò¾]ÉÒ`*Û„ùÛ§>öÙ,tuya¸I˜ÏI‡iñÄ#Tö2ÌÞ«sÌAx ‹Vµ*­÷Ä”P ÄÀü7±h©¥}VEü+Áø ¡Z_ qL­³ ž—©$pøæñ§Wð7³6 ¥ìDÙåÉ9ÐMXÂÔºo+ÂÜhø³S„)©•}¾úê«°bnm’²Ö‚ ¨ußÖA¹öçÀ?ïì~8½|!×U/˜]]Ê‘dÛø¾O>ŸêîB#©>Q*LæÎ;ï >_xá…eÕºí¶ÛhiiÁqœ²‡f[[Û¤0±ÑÑÑY6ºÖ‚s’p¼©iÆe«5¿zD9jSµm2&¬V‰žsÂ:I”0Q©æw§*‘G 3ºFñTû<1ÊÆgòoإߞ?]§lKF¶Ñ96.aÔK5DÓªéöö±´2IMe›0ûÔÑW™Li¤G‘ò4@:ܨå5OS^|.Ñœú‚µCª: ó¿MTïr,Ž´D•Ú=•`¤{* A†ÉS(ýåJóu~>¤ Ÿ¤(CXÄ|bÛ\Âð9¡ŒZÚgUxÐþ!È| e[  ú¹ÞƒàûËÁÀ€Dtæ™ÌW¿zT­[²Å×¾õ#½#sn‚ Ä•Z÷mA˜ v ‚0%µ°Ïý¼öÚk'mš*AX(êÕ·Ý—†ÿ G^¯*­«K¥;ˆÔDr]—B¡@gg'¾¿”¼qÂb¤jAåÎ;ïd÷îÝe†ÒÑÑã8ÜqÇ´´´°cÇŽi·±{÷nÆÆÆØ²e ýýýÁŸ.z¤‹Ê›9<<Ì7Þ8«zÑ…^¹øâFÛYaMø¿V¤©,Nd™9¼Õ¤<­V5˜Lí שÈôrSaLX6:] #F…y3 „®”ê Ót…ÞîtË.V¦³M`A쳩t Ãk-è|oÑœs ôPÕ›ž™"*<Ë&Œ\)Dæëb÷í„#éõÉÕQS¡‹qëZ/Z4p ýD×÷˜Ý…ÓIXT(Ú6Mo{b;õ2©*Ç)Ýö‰ó¼ Óµ ìÖ®ÑÂIt›F©-:\MçøÓE”(ýn¡³^ 2úüèJZt©’K~vÉ,v<©‡}΄ÿ*$~ Š/¢l¨ E%¤ìh9Äþý÷pÏ=c¸n|Þå[ßúGŽYÍÿù?/qÚicüëžCüÎYÿÊS›Ÿ #Òa P¾­ ³'ÏNA*S+û|΂Ôïþ¨¦m—.¬°Ô©gßvE œÇ¡ùÕæÉ3µ˜’L–òH‡uz{{E8NU)¿Ù½{7÷ÝwߤP®––¶oßΚ5køÄ'>Á}÷Ý7åv†‡‡ž”÷óŽ;î`ûöílß¾mÛ¶±yóföîÝËöíÛY½zõ¬vhļÞ3E_DÓQ5ªÌÂĺ!µ¤Ò>Vý±Y|&†ÔzÌn0ýtuq¦Cû³+•˜ŽJm3*„=.6f²M`Þöùœ àsÅÈa(’vøÏV©›-YÔEG"tÌ'QÂÄ¡!$PNüÊÉŸ-}vKßu¬Ò6u3"Õù¨ú—ˆ¬Ÿ&tTaÌÒ¼èÍAo«HXÀÈ/ý¶Ujkki9]ȨùcË"Ÿ£ájEˆ%`ä ¢ÞÒt+O+’Ñs§koiž;Ó¡qú¸Do$í„‘,ZDë-µGÿžIy¾/}NôoTŠÏ÷Õoþpãürª7õ°ÏéÈå X„^FÆÆ¹óÎopÍ5×Pxì_‚Û׿Ìcý)=ö§$ ¥V®Xqûïoâmo»‹]G/âˇÞËÿúµ–­€¡«Àø:®-,zêÑ·aö4úÙ)ÂÔÔÊ>_tá±9‹sÏ­]ÛeL¼°Ô©gßö Ìe0zÉ(°®|¦eã¨t_%\×Åq)H/Ä‚ª•|ŽŽŽióâÝqÇ §\NßTtwwÓÑÑÁðð0---s;hAÓ¡C°a0³³=šzJ̲q舓”^° 3;éó©ôûZì©TÇåÙM›ê~¬š™lægŸZw0ç_t>|º4!Aý’ÕN<±Y”PÐY¡ Bq$rö›¨‹G;ûµøQ T)û˜¬ôi1ÄE QõR+zZ¤éBB/a‘¡‰jgºÔžhJ4%8è”[ùÈ>å /ú\i}Ÿ0 Þ§‰¹ÿtѤ^B¡CG©è"ãÃÆ´p¢+ÈgJ¿oF%L<Ö}LÎwh”¶](ýÞDµ9QÚר𥣄tXœ®×ñ­¯ŒØSkûœ¼HÕ †©þ˜mÝÃáÃ×ý+°¯…ήßÀÄÄ4M²Ù,®ëâû>ÿøçx÷»/笳6â8÷qæ™=üÆú{øÉú (>z~Îå+Ÿþ4÷|ï¾{ïwøðÇ>Ì“w>É¥w] ÄLpÑB¦t„õêÛ ‚0;öìaFjiŸà]ïªMßqª ‚°”¨gßö¼,˜¸»Àå3“ɲt_ "TL³–CA¨ž9¥ïîîfll¬lZKK £££ójÐBuf£‚а8ÐÝžÙܵ?z.>yíó -ÂDÛ¨±€û.¼¬×aj(sµOx—oñßÂÈÚ‘Úªf³!Kå-}qh$…j³I¹Ë„õ§» *9aõòZ°ˆŠ'ZD˜x¬ Ba"º­#~Ò„Q4WžÅÔ•Þm& &ÓåðÓó£âG/¡ÑLõ;¥H’I¢‰~c±˜lx:w¡>G”þ×…LT'X‚Jµ,´3Èÿ]h}Ìÿ C,èèã;Å,7Â'Œ‡IX[i^¶Œ|>tnuøuWWž·Û¶q]—d2ɽÅ߃ðÁ+ç2Í -»‡®zˆçÞú›_ÝÌÇŸü8rïŸÐù­NÖ\ÏðKÃ\ý¯fìkcüÏïüÏÚ<-Pz”‡­FÑQ×óŽÙûNâæ¨õ}ufª’m«A€qÑ.¡žÄÍ>A™­}þg ž~çwj– HAP,Ô³óù"=z”‹[VL”STš¯ âI&“!™”.!T%¨¬Y³f’P2ÑxÆÆÆlôþÐdÂÙ§¿Ê™®½èÐ~Þ™j¹D™KíîKãV¹~¥ÎS8P,„BzÂd6ðó3†X{ÅÚF7¥œ©HùÈg-DÔsdút¢ÓTùÓU¬£ë—L·ï E5†¥S¤M4L˜:\T Õç$A|„ºENîIxÃã4À†Îu¹×Â3¯Éë7½…Ë/?BñÚkùÄç?Ïk<€mO¾s[–)úÅÖ¶mõÝ]ÓþÈùÚçacÛå/]ÎÁëyåú~ÚÎÚÆ'ü?üø¶Çùo釹fYÏ3…:ç:â©tÍ».dnsYÿÚ þâÛ›ë9À¿¾‰Ïßò2Ë/^ÎËæ[0ŸwŒŽîçW~å\rà àl0Ÿ„t?ÿ¤o€Ì!5 ʲ€<¤? ÆÓê·ºº”ãÙ0ÀÞæePüCðw€e_£ ¼w€ùc0ÿü»Àº“òŽ«®«ÞA&:É=/l¿^βÔt=/ê‡ð}µ „©Œm;œnYê³Þv…wŸ²yú7„Úáºêœ8Nx.\W÷DB¥ñs]È—žsÿú¯Çéî>Î'>ñ6oî祗–óþÏ…@Ž_ýÕ›ùó?_Îe—=lß²,Ç!™Lâ–.-¨†ü8ŽC"Q¯PTAádf³ »¿úЉF7E„*sáèYGikiâ‘éCÿ8\wzé@e-p]˲¤vŠªT¶lÙBOO{öìaË–-—) ¬^½šŽ:–µÃ{ÝÊc¼ ðpMÚ#Ì‹0d6Ìv”ˆQZÇ&¬‡®oÉSÕT©u*²“GŠðÂñ•üæb ÑÔ£Ïmj/BÔ]Ã$EãŠFMd>íеV$¡ñ‚á¿v÷€ýAàwáŠû!s­š7°v-§îz …¿ú+Nõw9ãškøè5×A™‡ÖðPŽUÇq0M“d2YædÅ‚o&š‹ÏmÚć?¼3oÜ{1{é©dþ~{ ¤?wÍW®ã©ïÎ{¯x…{N=•äMã4rœ?zå9~5sߺöýûQNöt;Ñ»Z¾ÂÇ^¾ßû«ïrÙ+'ØøüF~utoûæÛhúO?ç]¿¾œo¼ô,;W/gü'#ü½µ—/äïäŸâñûƽäqžzêËØW| ŽB.ÞÁ¼²΃Àéà컬ó£ðÆÓGúÚZþfüÞ}Á)xƒÝ »¿úÿ¼»™ÜMËð÷<ðóZ0W(ñʼI‰úÁóÂ(ý¿m+'¹û˜oVƒõv0™ï€µ²]ÿ¹4Šr9ôþGÈü=¸/•ŸUm.†âq0\ȼÆ)`žæ(þ.¸¯ƒµÌÞ—Á¯¬3ÀødóL0ߩǀfÕv×UN{íÀÏf¡¹9m Ò ¸û_Úx×»NŽèÎZªô5ãû¡’H„â eAGÇOY½úôG+øó?ž^ØÍo|—K/mác»œææv~þó÷°rå—ù¥_z?6—_þ]V¯þ/üìgßdïÞߢÎ<ÏÃ4Uº?ÇQJ½NùaʾD"뺘¦ü¯×©$Æ ‚°ðh»ŒMMA¨ŽÇNmtSA¨’¯lú Ç[Þ¦²¾Ü?$“˜ßý.LH;–ËåDLbEU‚JKK wÜqÛ¶mãŽ;î »»;ˆPÑëwïÞÍŽ;º3p¸ën~™åcËáSÌXé]Ì1>è2³yµN2{?ªY'ò+;„†+]‰9üŽâ§ Ã_9³ÑM™kŸ,f T­Úh) S˜ÅE Zäø.Œœ÷ýÜü.È|®yí5ò/½Ä±M›øPo/½¿ù›|hÅ <”֨ˋx¨û¸ ${{ƒ £J¹nµOçc;[}ÈéùS•¹ý–šÔ—8‡‡í‡yâkOpÊUð—ƒÇ¸âÈ|¦ý/X÷ý+úÁä™'ø•µkHœr*/ÿ7‹³? «ïõ¸z×Õü͹ÃÙ?¼…7›ð­¿ú—œøu>øÐFþKóáŸÏøg~ñ‡Ã´¯kåžs¿Æ»÷ÿÿì½{œe™÷ý !'B2©!Bj§ ˆÔePP©öDT„¬Ò­¾ëâ¾í^÷Oëc·äYDŸU»ÑºúH¦•õD§UD§8f8§HB„3$LBóþQ}WU÷ôÌôzºzr}?Ÿùôt类«îÃᆴ붱u¯,ÄîžEúC ß[™™½2_ƒèû¡åƒÛˆµ$ÿã»?¤sا1=ÿƒFñó/¤ ã2¼ µc ÿ¨JÔk!$îËÿŽc~î* vb+G>´·Ú{Íâ8®PÒÖæ %¦é~O§ ·Ëd2躞D5عó"®¸"Ê?ÿór^}õ ®ºjïÿ*LÓäMoêgûö9ìÛð~ô#€•8´µ-£«ëÃ46fX½úíÜzëÇ•K <ŠææfÀ Rt]ÇqlÛ&‰..¸ C’Ífq‡h4J"‘ ‰`Û6ÙlÖ«s³Ù,¦iÇimm ££Û¶ fú&‰¡Å4M à “É`†ŸBMqðà}Æ?V»‚ ƒŠØ•ƒwnz'‡¾þ*Oö÷»DÕÈ ÔKÍÍÍtttxžÑ‚ÊΡ²víZêêêÈd2ÜrË-ëX¿~}U½Ss€þþ~Ž?x<,yû©2ž8(•ãz$ÆD"‚+¢€ŸûZ *C!ÝüñáÉ&xèW÷¢i'U»8‚ÍÔy¨UòzQÇ' ûXØ7Ž˜Ÿ~|øÔ§þ…·½ó4Í™ÃÜ—^bëC½è"Ï«0Ä^~™äž=°d ÆSO‘kh€Ù³Ià§¼)5 ›Ÿñºg^‡þ¬NÃE 0 ¼äA¾uð[,:éQþúò~þÒýú[aβw2gëÈÂþðx$³I˜ ¤aëû¶òÂE/pÇÀÜð70ƒ\‘¸"pYö2¸ÐàC¹±û¿vóò“/»6ÆmWÞÆ™³ŸàÞ{ÿÆGö~„¿^ôWžøö\´ÿ"?úqÞþƒ·sôÑGsöMgÓ÷>fa6wŸ7]·wqìïŽeþÚùwÇqüëyÿÊ‚ 迹Ÿ«vrÅC'òróË4ýz §Ç¾Ïo¾öpàü#oî{ž“¿x©+~ —ÂÜ׿rA×ÜÓì}ç>ýEÛ¶‰:Qœ¬ƒã8ž§¶;ù¿žú 'm^Ë«¯nÂI8ÞZÇ£IÚÚÚHüØÂ4Mo?Ã0pºœ?çg3Nδ··{ƒrÞO¥rç˜î/¼dÇ^~æež:øWöý;¹SOâ–Þg8fÙlÿ—íÌ;0_[¿æÂ×.äŒ3Ψöã^“(!Åq ½ÝõR¡ØÀ ³•Édp÷™Ðõüszƒ«?ÿùyàƒ|ç;ŸõŽû¦7Íòœšæž#•‚%Köñ·¿}˜\Î?'¸Þ1©trf™¦éÍ(looÏ—ßÆqo–a"‘ ±±‘öövr¹ñ¸¯Ž«A_A8ÜPáM4MóD’h4ŠmÛ$‰Ï0]×Éf³X–E2™$‹á8›7o¦¹¹™L&ãÙUss3š¦y¢f,#‰Íf¼ý#‘Žãx¢L&“!’L&I¥RžZ6›EÓ4âñ8š¦yžk†a`ç“ «zBí#•dÆŒÝòœ BÈqp»ñ‹Â’ÌN<±È{®g2… LÜ>ˆš˜#aaTI鯽öZ®½öZ:;;½euuu455Uû:<Ì$lìïçv¾V´rpü(¨âú«Y™R7W”ŽñbDTºE7_·PYß„+AFÂ@;SG€P9)Ä;eÜsªŸ‡™‘|•gÛ<~Çlþæ7Ý•^èÝîÛ³‡ôEÑqæ™èozD£Xßûö5×9é$ìbsçÒ5ÚXpòœ¼ÀýÒçç@Vþi97ûçLàSOµÀ­ùTù~~N?ÿtˆÃõo½Þ?¸ªx‚®ˆ:ýž£9—s8øÑƒÜ½¹o˜ËÕë¯æ4NãsË>Ç‡Ïø0 Þ°€£Ÿ8â0W›Ë\c.\WhWÀ?ãºî$áôäé™Ã2c™{“îÍOêI¾—êƒÔ|þaÏ<.>þRôÛ5®0®(¸£Ð+ ›Í’Ëå0 ]× fú[–ÅUW-á‘G~mÛhš†eYÄb1o`®««Ë„ †iƒÂA°T*Ekk+étÚ(Ó4Í #ãåÒ0uoù•ï^À·ÖÂÝ·ÜÍö{¿UPî›o¾™¾¾¾J<ÊS¥“¥R®¸-R)×K%—KHäÐ4dÒM0¥¼S‰‰D‚®üŽŸüä©|ï{[ Α!O˜ -ö‹_´pÄGðÒK~¾•Ô^…Sý]Ã0hkk+x.‹;ÃÉd]×=±.“Éx¾¹\Ž®®.é@ SÛ¶=±"•JaÛ¶—ƒLå+Rd4%›ÍF‰D"466ÒÕÕå‰éjŸ G‰57oÞ쉫ʓÅ0 ï}¡lN‰+™L†Í›7cYmmmttt‹¹SÒ2™ ‘H„L&㉴A/4åÙ¢™®®.r¹œ—L8™Lzõ– | ‰iŸÿ¼½ÚÅ¡ t`Ó±îÿsŽ›}}n£Òq \®s¹ÙlV¼™…Ð1*AEO”¡Ø`Âò_Çü¾ùpb~¡…+¤ü×kå\ ñs€­øòh wQ ÎåpG˜:p“{8 $Y¨)‚cªo3ú|,Â(è‡mu›€÷V»$ÂTSÔµŒg¤^ðˆfüu'¼Çv6ëÍl/EÈvwC:íxæFŒLûSŸ"»w/éï~—Øg?ëFŽ:÷\ôcŽŽqÈçêùÃQoìäœïíàìß¼‡¾–íÔSï®Ó\_pÎÆs†>®†_!]®J§Ó †Æïoü=daÁWøû©²éïF‰ó¨eª22F˜;o'0Ÿ Ïâä[-tcd¿ÍH$2dÒoÃ0xôÑ|‘òÒ¦i‰DˆÅb˜¦‰¦iƒßÝšü€[20â^,Žw‡Csžf[ýéœtÒ½ÀÕëÏ;" :ÂÐÄb®pÑÞ>8¤@_߃$ç:Þ ¾bâñ8¦izë.¸`1?üáâQ•#DÂÿ­-ËýnÛ»ßãq×S%u?#‘wÝõ,û÷7 {ìh4J&“¡½½ÝVáÀZ[[‰D"$“I‰„7c>NK¡¦±m›ÖÖVLÓ$‹yïc%T'“I²ùzXyY–E<G×uººº‰.j?…U•í+%‚+A#èfš¦'š›¦É®]» ʬë:ÉdÒòÕ9,Ëò<Ñ<ñ>•JÑÕÕEkk«ç¥¦iíííd2ITŠh4ê 2Á÷òªQ­B)6mÚTí"‚P&}¿àþú`ù¹ðô|wQÑ»]‰ý‚6Æ$¨„™ 0ïüBO’6 Æl0è ¦+’ØùO?¿Ê\É/‹ºÇ •ÿì@¼U¦ÜÇÄ¢Pl& ÀÍ/¯çz®ïá¡yOß{ö}V$`—ãPßÖF$ñZÇ5Í`Fsåʃض;Õ}Éxúiô HâVÍ÷߯¾Êæ/~í‚ |wnËrG_Gš"DƒýGïçæß¾“èÜ'ùð·ÏªØ}Ñ4Í›ÙïÅB&âùÓ.xåí¯@¸åˆŠ«Áë¡„²‰ºg3gþ’ÿþïeœwÞ²Šgª£’Ìw•Ž[[[óŽ6Gq¿7ÈZŠbáÌà Ms=Q†áj£–åŠ>ºî *ŽãÏdÀ¶ÈåÜuÃ=rÊÆŠ=¤"‘ˆž.‘À²,ºººH¥RÔ××{ùTΕ[Bí<– ¾ a ›ÍzyO”§I<§±±‘t~r‚zÖoI×u/'‘N‚Ÿ©Tªäù”gKõ®P¡ÃŠ ÚNúK78ÀUìm¢„Àó|TBŒz566zb‹²åd2éyÄ´¶¶záÃR©TÁ{L >*wL0ï‹Ê/3œÍO¤‡Lqh³á0†•%—ƒÆF‰=!µÂ4²å¼-ÌÿÈ×á‡?tû†EïH˲¼¶ „‰)'¨Ì<æŽ<õI¡p.hç‚Ö‘/Q^È›4®˜Ò†;p’ÄÏžTŸ_&^gSw°OgjMÞ ÀtX~Ê¥z\5 ¨:U€7sM„ÑsÛ­púÍÿärî`N.—ófœ’ɸ#¼ñ¸;]ßÃC×!Å¢ë×Ã[ßê9j$Äk¯‘zË[ˆêº—ü V®mCk«Û˜n/r3)tLÓäüóßË_v÷€VW¥‰|Õ0þSÀ¹,Zt7äÃU¤ØùA­J³pám\xáBfÍÚ5þƒ¦ärž©yd2ODÐu7¿ù‹üä'¯ ë勊y3¶=¨ ¸ËLÓ7aMóM7sϺf­Ìw´ ãñ8ÍÍͤÓéAS¶m‹ÅÈf³ž‡Ž¤Õ4­ …[^ÃË÷Ëå¼Á^å ¼Ô@´®ëƒAUn òÈ4M¯ÃÌG¤fðÛ¶í-F£¹/Ç!“Éxmõ¾Uá’”§Ž*¿h–'&*þI»xWy§¯A'—ËqÇw„:"A­¡Âf©¶jGG™L†L&ã=Óííí¢gño‰D Ó4½|–eyÖjv¼Ê7 9ÔÞÞî%äVƒ›ÅâšõžËå¼åJ¬p§`@U ¤ª<2ÙlÖK®Â-†á Þªk<„`ø¤`ø¥t:=(×à‰HêܪMn˜¦Aï}ą|%J8 ]‘H„T*å Ac¨äí*1ýPTzB‘ò)U†¡¼À†õÔ5«¶|õ̪gZÙ•aD"ïÞC^ª°a†ax^.­­­ž€‰D ¼[ºººhkkóÂ*ÏM•“¦±±±`%®666z‚‹šÄ¥ú Jè R‘H„D"áÝ»d2é‰G¶mÓØØH<÷åi£8u=JpI¥Rž€# æ’Kú°¬ñ÷7A¨<;,øû/—Ðô‰9ô/^ 3f”ÜNB< aeÊ*60OƒsÞ·ÍGí…9•Á±Õ±ØáPÉŽ“@#¾È’Ù×)q„šAº•aWnÝ>xfüÇŠF£ž‹0´êÈW¶jæ%àç@ÈcYÙlÖ›:Ù±9Õì;•48c<“Éx3ålÛ&N{a Tç²Tys¹œ—ÐW͈ vÊUG¾ÜªlÁ™ƒÁsår¹‚r«x×ÁNkkk«×AUáTÒRp;ÔÁcišF,ó:«ª®fF“† KôZÊCNÿ+|,Ÿ{>—ËFùèÁƒ®aÛî(èh´%FG5ü<ð ÷ D‹ZÔ”ö‚󙸋Fa5M£­¹Ù{4­t’‰açÎ ùö·ŸbÛ¶QŽŽ‡5@,9.ÆFñDtõÎ+å]4·Ø0J{¨ ‡¦jœêÿÆF÷Ub¾¸ã8®5^<\2R5S|äòhÞàd}}½7 Á<¨iÏë$X÷år9/Ÿ‹Êû0T] þL|5]ªNR!—Ô¶ª~+Î 3\ûDÕëÁºW1TØ&÷z]Ϙà5ªgkݺu£û¡ÕþÈd2ž7‘ã8Þ3¥(ý‚ŒÊÛÚ Æ,‚¦­¤„ŽÑ¾Ó‡T†‡t]'‹y÷'™LzçÊ»RÝsußÒé´×–Tç)¾Öbe Êc¨Ô{%F°ø÷Ô4D"ÁæÍ› öSâk2™,¸f]×éèè(m‚û(±&H$áßøÆ¨îÿáÄÚµ¨¯¯ì9$ð L3çbÎöíôŠV3€IDAT/_^r}"‘ð&Bؘ2‚J 8Æ‚ú^sC~Q1=ssþ3ߘ%ŸØ>‡«ô$óÿ«Xëz`¸Ó‚-%Á„©€šÌÚ÷“éè»%ªŽE,óþκTa.TGF Ü[–åÍòTá‚.üêSy¾¨Ù«ÉdÒëv`^_uî"‘ˆ×ÉSñxÜüPS5“Q ¤¨óêºN*•òfª™¤*¬G0왚駄 Õ¡TÒX,FGG‡wÕyS³ÝTùT˜'%z¨j@O•=¿>‹y÷\ ªSÚÈÅ¡fkªŽª àfªr©ëST5‹6èö«žöAÍ4V×ñÊ+âö_6¿à=Ç}õ°ðos½RÆÒb€GÂb†A®½Ý C "jP¡h § ·Icc¡W ¸ßÇßÏqBëÅrꩯðÊ+Ð×wrµ‹2!(‘[f»l6øØºáŸººªÚn”úéÓi¼œ*A”L,æn£LYé§Ã/”/¡5x‰DÈfýÐd–ñxé¹iš$“I¯S_n¢RC fÀZÙ×h¹ƒÈÂċż|>Á¶])¼¢nÿ0ÿ{„2¸Ün…iâ»ÓÛùu^¨=ų»ûè¸}ÒH~[ÕO ÃÄkÇ~ƒ½Øf¼J{,ïrõ\ަ-­l9è‰RÎ>ÁI7ÁðyC[Mî)µ~¨sª6y)ûooo/é]¤Bû•²·¡ìV]O©å‹/Õop¸Qé6ÇR ‚P„}–=;goåÜk¯%·woÉíT=%%…02e€­9˜¹÷³gÏ´®âæ§ÄÛVÁ6“ÛXVÒx~™ŽÛ€M ‚Š0%q€ót¸`q?÷ޱ"TaN::: b «ýb×zÕQ¡Ô¬R5° q¡lÆãqb±˜7˜ŸH$<‘Â4MoûT*EGG±XÌ‹_ßÖÖF2™$—Ëy!” ¢¼-T\wp½OTH‘¶¶6 ÃÀ4M/Ž´ ;~§@ÅOV3âb±˜Þ,R¢££Ã»oª|]]]ž¸âù‚R,óÂ1¤ÓiïÞD"/ùiWW—'hc»;É*ú ”g*S°\JS£`ÇG_5šÔ9ÔþJhQ³7ƒ KÕo©òCضÍÏ~ö³j›@M`[îôóضÍÜ;î nÑ¢²C|Œ(Á<-ËýS‘ˆú \ñ$•rGdUÞ—TªðzÔ¾¶í®K&ÝÑÕxÜ?N6[ZPn¤·XØ)…m»eÌo÷º×ÝË©§¾Æ£Ÿ€ÌãOr2‚³ÿ…Ñ£Â}år9O°®µeP .Ê4 Ã5aÇæfWd‰Ç}“ŒFýõA“,WLpwÿT ¢Ñ$šæzŤÓî¹U$¶6÷øÊ<-Kå‰zm.ç.SáËÔkÀ²|1L]«eù:®2{u šæë¾šæß塤¼wlÛ]¯ë~>u,÷ ÞO•KÓÜíÔ2µ^[•{,¡àÇq¼6f*•"“L&½Qþ†ùÏlþ/žÿ x¤-^¼˜%;–¸•ó.Ü>£Šò¤ÆØ£À@þÿ6¸|Óå\¾írØ‹?Q/8n4;_†\þêå,¹}‰+Ì(›Ôòÿgòÿ›ÿ×/{=Ç¿z¼[i[ù¿8~_X‰=EÏÑhOµíX¼Çâq3šøàd§rϯ¶Ñ2T¹Î:«ü|YÂÄR[5° „ûˆýîïŸæ6Ćè/ˆ§»f¦” 2Ó„þz$ýGá-KŸ`¨¸µã¢ÔûA|f&é& BØò˱í—Íf™»s'{-"‰x®ûÁÄœÁÄ@Aˆ,%l8ŽãÅ!W‚€ê¥R)oÐ_‰Ê£D…hnnö–©øÅA1E Ñh”ÆÆFÏCFͨ(PTÞ2@A¸uM¥f¬Ï” ÆÇ5 •ôH cýY'!àXÛtÝí[ øË::ü4JJóTâB6ëšçPùWÍ;`‘Lºf¢Ž£Ê©ªlÖ=_$âš«mûÙlá+@i¶j;uÝ*:¡J<¶zU¸ÂŽ¿­mjÄʹ®øÜʼƒû)Ïu|Ãp÷O$Üc¨}ƒŒe¹÷¡½ÝýT¯Ó­[#´´l«Üƒ1Qž±Éd² ç¦i4Ýn.uìÙÀgAÏG1Èœ˜~}çlƒKþŸKhÚÑn½˜3 ©„¶¤Ûm4q_I š†c×Ë/Ì™üÃj_C‰@á,…€ &Lÿçé4\Ô70ø=¬^Ôì‡|òO²bÇ w¹jÂZø3*Ϩ¤ÝB꺎îè~þQµ!‘ÿ_M04ýíÝ›…/@eð'/yô(3ü`¹e¹# gýøÇœÜÑÁ¡×¿žÈ '°å–[Xöú×{Û›ºŽY4‚PæñPÿWÊÁÔÁAþ `ÐÞÞî…“2M“T*åy‹(¯ …ò¤HŽ4²S‚âxÌÃQ‹{4…˜áïûO%ñ­$*tYº†óf„‚pùyj&u>an<>9‰ò˜øc6ªY­æ¨è™*’‰g]¦é²7r«iþ¨¤®»²K½ÔsTlñ¸+’¨¤Áó«ÌDÂß¿£Ã}§%…ÓÍ £ðžš¦›&ÏÃçÿ‘F >ãzÐn,,C0Ö~ñ ‹:Wðzƒï  ð£¦Î«²ª2f³î_{»/Õh«e¹ËŠï±m»ëkÜ“&Œ( @ÏéÌúô,ø<þÌñ\þOUy:…Œî@dЄmüå¾8ÓÎØE™ ‰ öjÑu÷‘ÍdÜǵ£Ã×#•ŽØÖæ›®27õÈ«LAlÛ}tKU…Ѩ/¦@¡9•û¸Í(¸ñkµ¾Þ]¯¶Q¹dJMÖTÂ*C°,¹œ»®øøùÈ$“î=R¯?å%£š1ÁWÛºuY eÂÛ©ˆ•müè±ÇØcÍÐxñÎ{ÙùðAHÁ™³ÏäÏßüà‹-Á Žç/ KáL º¢]КßF¹¯:îñ<1B½'ÚáïþGRvŠs¾}lÅÏqšÊo—Ætwý’«—píÉ×ú9Qí@Sø!Ó”¨’‚7¿ûÍì|m'4ã¿7£ùcFp—o¢«–®r=Žñß½kÉæ¥ªØœþùœrÌ)n9ÔuçíýÌçϬÐÓ\û´µÝïÕ‚ „›Ä&øÈŒ“ÜqÜ×]Û¶½È‚F¦” ²+ /óà•. —£f§«üŽãN§+bA5ÞaŠá }sûxÓPô™LÁTPÞëÞ·¼…>ô­ýý|æœsX¶l™¿O6뎔O~,âF\.çådáã¡gÅd$[O…Ñ2¢´š](³WƇ= –¼Îý_¹VW#ùŸ’ÅŠÏœÅÛ°€zü*³ý’KÐm›þ¤UwL&?ÑÓ‹I&É’XÒ4ð*¿, dtÝQ©Ïr€¦ëÄ7oÆÁO‘æÍ&6M4ÓÄùÅ/¼}-@3 œŽßË&—þ⠯lê3ÈÞٳٱc·õžåmG‹`ÞuꀮF˜eSa:`›&ºzÒ€?âÎ_£„›hÔ^”­)!KÅ3 î«b*©xMà{øäGwüèG'óѪ9‚!¤.{ø2.o€Ëó+ÛñÃ쨿àÜaÉoŸÅŸ ž°$‰F¨9°2¥Û)÷15@Ya†,4Íœ”‡† {¥¢ÿéºûèuu¹Û+g­RÕöpÂÈDV]#+.A‚×YL<΃…CUëѨ¯)«û2Òy„òIÍûDxü”6®Û»—ÄK°²o:Ÿºx:ß?^¸ò{,Ù¶ÿ3rç@#;…¥Þr ï}Ë1žCF©GUùWª±üÆ6ˆOsë U?:¸&®"†©cm¸¯‚äzˆ]æn«Ì]ÕÁWŠª'“€i@ê*_°1ñ'< AîC]è¿fô$ÌÏ̇â /6î;g¥ã|Z`Ä ÷"Ël®N«ŸF,œ¾Ð½ÉŠàþE]†3gð¯çý+\Ëà Yyï½÷–~})מ{-|ªhŸÆüM+Ñ-YÙ¼ã á6r‚åIçŒxÑæ?5£%4øXà&ãþˆMw4•wSC'Ws¡1ápÃöïk¼oÉs^&Ø ±m›ææf ,„šª *}}}ôööÒÐÐP°¼§§‡žž­Ž0Ý‚3Ž<ž¥óç Z?\D˲¼Ð@©Tª [lÛöî*RI«¯LòªÌP¶ c³O ˜ñl;~pŒ»0‘pG8LÓÿÌO™ z4ÜÞÙÉO÷;Çaañˆ„šjÙÚê‡íQ3°'X,(N«–©HXÃ*Qœƒeª3Ñö©xêpîsÿ·m»*bÊpD(Y¢¸ã) û•¯xHÕlÝ8“9Éå·âG!°î¹G!vÖYÁ¨&ž £ãVÏ*Œ<ø‚ÅŽ}û8~Ö,wáWàÿwÿ~^yåêëë½}ûôÓè—_Nïé§{Çß²e G74pàÀ®|åþ°p!Ý+Vðböaöž|2­¸cN‹ž{Ž O<Ñ+¯ µoÛfÍâ˜-[¸÷¤“¸yûv¾´d °ç¹ç8â˜cØóÈ#Ô½þõ8p€þþ~¶/^Ì^`ùôéÐ×ǽóçsùž=üEÓp’I÷÷3kÛ6ö-YÂK{öpÎÁƒ<ùþ÷³`ÁŽèíåŒï~—_ïùñ™wÒI,ܱƒ·\=yüq>¾e ßÉ{ÈèºÎ=÷Þ‹¶z5Ÿüþ÷95ßúúUWñþ]»°tÙýýh±ýSLT™È¶­ õ´íÌm<Úô( ZÑ~Ájn¸¾¦ƒŸ¸zs‰õÊ°Ô  š-­á )ÊÔìn%ÂÄñgÛùïêxFàü¥Ôà "˜sD5)‚Õu)°1š×íXª»àý8\çT¢îlÄ5©GWìå½ÿöw.ùÛ߸йНD#x@‡ýüÝÌÝýÆù—•mq\“k£p€i(4 kÚà(W~=¨„%Ð$€Ö+Üeq|í@i²ÅçU)?³IßÁ$Šû:¨ÇwæÐÏr_9 Cw›ìª>Ìä—™»üºTM`P©_4ƒÁâÃ<ý±§±n·0“£ØÉ„™¥ßOCüXGí;Š£Ž?jðú†lˆÀt{úàë þ E?è’Û—ÀQ%î ç}ô¼ò¯±˜hû<œú‚Pi&zÜÜwýéOÁß÷﹟Õúj p~¹ã8lÞ¼yÊŒYS“ª *™ü ŵk×zË6lØÀºuëX±b›6mbíÚµ¬^½ºìc4à–SnáLþÉ[¦ªÓ¡†B3™Œ—ÔðBú¨ÄqÑh”\.‡ã8X–…a•hR!¿&5p]J$r‡\.‡až›¦i9)ÔýP®x*7ƒR‘ƒ3ÆÕýTÇT!˜Ô1Ý$ŸVAHO% TçUåÎf³D£Q/¡¶º&u-j–u°œ¶m{Û«äÜê3’Éd¼ïê¼ê9ÐuÝ»Žâc¶´L°¥lÆgŸ{£f>†®ÄŸ¡¬i~/?ð¬hšF$ñ´ëyƉD\Qeóf„¡‘ðXµK%ì`O'¬œd³´³)‡åAô4 Öí*êÆªûîÃéë#ž=M‚—˨Ý4½Á¤¶¶6’ɤW¯@ìË_¦£½Ý¯ûX,æ ©ºÎô… ùæå—óБG²üÊ+Á4±ó9œ”'–*£“Ͳ۶ÝhKñ8Wµ´ Í™Ãy·ßŽýÍobF£ä >bÛ6ìÙÃWÖ­cÞÝwsÔÊéÔíø»¢Q–mØßý®[GçŸN§‰Åb^Þ$˲8õCâ}}÷ƒ\¹’\.‡išnÛå{ßóâ½[–åÖ‰¹_}ÛÛxßã³ã”SèRùP§lÙ‚ã8î¶÷ßïM6ùi*Eª«‹ûV­âõ‡qÛÊ•ÜÿòËüãܹŠFq‡;Ï>›“`N4Ê´;ˆ-ZÄÿýïÿfå)§`Üv¿ú*ºmóþ X·n‹«ýpM0Þ¶Ý ÿñ¾|ø£§yŽå Ò8€®FX-»~•B%–V‡õ±ð§Æ«eê„*&‘šþîþÌÀ6FÑq'€¼®„2Ñu§Ø ˆ}θýUÞuöv–6]àæ"É7mÕ#ùÙOŸ;¦2”Ö@‡b$­,IáxWR‚Ç)u,×Ù­1ÿ©ÞG¥úØÊ¼m\%…¯Ë¦óÿçðó¦© n”/HGýÈ^*"VÐÁNE²òç;$x q=îéÈñ¢kSǃ@~™ü*ªVÐÃGí£öKª Îùû¨gZ`'u,u/øàuÞ¢À Tib µÜö÷Q)fÐà‹ïú"ÿ‡ÿ3â3Q+TªmëQaa_¦2•·Øû t ð®yÛK®O¥R$“IT„P3é‚ʆ èììdãÆ\{íµëÖ­[ÇÍ7ßLKK ÝÝݬZµŠ–––Q)žÍO7ójàûHý5Æ'8ЯGÔ z*•"{9Šþ'åB“‹½÷„½lÙ²…Ó¯?Ý«üûþÐǽðÔ­OQ÷¾:>ué˧{¢‡ã8<ö£ÇØvü64Móâà†ÁóÝϳhæ"ÖݶÎËÑ•ìâwÓ~G$ᘎáÿ>ñ™¾pºwí±Ö˜ú,‰x‰:_0ÔŽ˜:kîY|ì}ã_üè°é—›¸ãŽ;xïëÞËöíÛùàeä„í'pÄ–#¨¿¿žû￟½Çïå—Ÿÿ%÷n¼—ÍïÝÌÆ{7rÑѱxñbî¿ÿ~Î=÷\6þ}#¯;ð:^;ñ5úg÷óÁÓ>Èë_z==÷`Y©TŠk/¾–Ùý³ùÃßÿÀ•W^ÉÉ'³m“›PséSKÑVj\vÚeØŽí•YÓ4Žzì(OlQIg¼zu‡êxòÉ'Wd:ªó(Ž=õXÞxÙ¹ó‰;iÖÊ_ÿþ׉}ªÄp¶ ã³Ï]¿}ì!WÉdÜýCLÍd2ž5bÌLÜÏ@åTg˜/A•²Oåyê‹ /ÿîw|󬳸¾ŠYê] ¾7•ØÇñØj]\×±€…[·båEuµM$AÓ42™ ¹\ŽH$‚išÞ¤Uw&“I=ÑÆ²,:::<âù_ýŠovwsYOWD"D"¯= ÚñxÜkC…à¿ö§ÏœY ¥Óit]÷: ­ÀÊ¥K±o»›ß¿¸Šý?ìçãŸ>’I¯½¡&+tuuyû)äK€sæ™¶ÅaýÔw#.ìÚ§ŸæKûö¡ëú"«Ú'N»áãMÓM€Œ;6‘Z´ˆT$â…{ÐfÌpw>þxNzë[ùÌÖ­\0w.ÿkæLì™3Éœ{.i åßþÅÿó?U{Î&’J´m#¸wz?ÿñžã8 ?®t{àÿ8þŒïüAJ5ð—ÈF’îr•ªO…óQž\*}òÂR¡üSøã6`äx›Â°w¶žÿ?’g|Ì£ñs#¨ÇKM?÷¦ºã’FòËÒ T…UÜvà8Å^9*§Œ ¡« ¨r(EJ ;ˆØO+ZŒÿ§¶WßÕT}evÑùŒ¢íÕ´|çTÇ·‹Ê©®Ã¤ðÆ+¯ u,5 ¬Ê Fyƒƒˆ4KÞ1ÕyTBñüõ\øâ…h9@­S©º³Ý†ùYÈ~>ñ_w±ò«Üÿ8xÛ° •IF;ýHÃÒ5šsÆq=X‚Ñ»†sªS¡Ébø)UÒøÂ†zŒ“øÝçY¶Œï~wS]3¾é€ÿJ ¦béÒÜs©üðêe’ŠHþ:Р#â§²2ñS£¨ëËá‡Uï]?üš2Q=Pu­ÊV7ÜðjÁ0£J€ª[rÔ(¹pRɾ§W¹%qo¢ ©T3õ^TqUÕ÷p˜« TJŽÛ怇—õqÅ‹”Ü&KHo!ôLº ²bÅ èéé)XÞÙÙI]]7Ó¿©©‰¦¦&:;;ËW;“Ðû^f”±©š…šL&I¥RƒKƒ?Pǽp?õõõD£Q/i½j$½=b±étÚJ¡s‚^Ñx”¾?ôqçßîdÆ_f€]ÿÜEÃþÎzí,žœ÷$ß{ò{üë)ÿÊüÏÏgÞyüéÕ?1g×öÌßCî¬×켆Ùý³Y´hýýýÜÕwút.ì¿gêŸá» ¿ËŒÓgðž–÷ðžyï!5#EŽÆKm3Û˜Ÿž1HêI·•­|¾U+6?;Ñȇ_Âká^øù yå¯À/aArï¿âýè[u–³Îþ Ë—-‡]pî²s½™>Wï»Z!6Íw_Ýêþö«ÿuµÛòÜœ/O–÷.gû·Ó²°…ÈÿŽäã¯ä˸VÜ¿¢°ŒË4D¼º‰šÉœtW*Œ… HlÃÉÖÉlýýVzz{8cÿègèp'D3Q0aîæ¹¼ÄKã1‹P0”mÂøíó»ÀË8oKÔªMewc®@“I7€úHIª¡†¨”}Z¸ƒ[,ƒCcV•=îÚÚÚèèè •rGUÕ„‡ÆÆFÚÛÛ1 ƒ¶¶6Ï#±££ÃF”Í¢ëºçõ¨êùl6K:.XÖÜÜìKM>¶Ô{H‰_¸î:šòAŠó•zo]?sæ þyñ¤Œ4 /]Ê'ØÂ 3¯bÉ®G†œ¸1ÔàÜhíLà™SNÕï’¤p’ŠŽßµÀ:o„SÑq[àèÇáåE{ÙÝ¿»äúD"AGGGÙÇ„j0é‚JS“›D­®®®`yww÷ E³®®®ddëÖ­¬Y³>´2poý¼‰ËF,‡mÛ^¸§‘Âß!uttËåhmmõf¾*o:Ì0 b±¦i’J¥hoo÷ÂŽ¨PFÊã8gËÿúÍÿ‚cÀXkxCÛØÆ~c?¶móÃè Êvyær0a±¾ØÌa« üE,Ü™· †¯MÌ©B¥Þ[ÅãÒÃdG<š£éiîaá{òÓ‹~ʧãŸ.Ü®TK8x¼¡bZ¤cq0`ÈHeTn}ˆõC\{ï½,þôb|kuËêüÆOÖ¬YÃÖc¶òïü;µÎP¶ c·Ï;ç"žºw)¦9¼@¢f;ŽCW‰æ‡DÓÄ;E »»›uëÖ±sçÎjeB˜hûܹs'kÖ¬aÁµ×mi!¹´ÿ?þq& Î[x’‘(åÝ™H$<‘¢­­x©sÎá+Œþ,¸ÏP)LÍaöIPÚËf¨}Ôœ½Rë£ÃìcíÓÝÝÍß~ð채½ !•hÛþö·¿å'~ÀTÔƒ§Ô¹`e©„ê`®ž ¢[!ªÉ–Á•ïþJ¡»“r—Râ‹Äëñû ça ·òTñð”#aÉj– 6°AÚ¶C¢Æm×®]‹ÓÔDo?,õÌÛKˆra"Y·nwÜqÇ„§j¨Z•bz{{-+ÇeléÒ¥|hýz¾Ÿw£Ÿ>wúˆû¨xì‘H¤` ¥LÓD×u/φ:^{{{×I.—#—ËÑÑÑA&“ñ‰©ØíÁxæ¦iz R3MG -6†¨,“‘¨í-? þ‹8ïvÞ]ñs•Mq¦Æ2Yöúe$ÎO}v'ÓúõëY·n]µ¯¬âŒÕ>ßñŽwð›¥KùÉÊÂH¥PùnÌJdÍÛ*šV˜Áv´46ÎÏÒÚêSÍW^8¹œûç^àøÎ-ŒŠ¦¦&Ö¯_ï îSœ±Øç¢E‹X¿~= à u˜9Èž}6‘ ¹W«úO…ÜR¹¸R©étÚ«/MÓ,˜‘¤Þ Jø(ö q‡¶¶¶’ž¦C1Úº²8ðʳ¼´ç>vüÝÕ.JEY½z5 tvvV»(eÖì‰à;€?ùJ‡µQ!hb}Ô2%JKy%ŠŽo”8–Êe &Ü*ç•¿@u…•£Gß1£=¿N‰8Ê[N Gm€>Ò+ýp:¸ãb¹ü±Õ˜TtØ‹Ü}œüº6€K|¯ w€R¡Ùõ¹Î{Åw QƒŸ`ÄÜó=x”S¶ºv~ÿ`¨ Dà8‘üú6|QJÓœ3žH_y™ä®ö—©t6mz©q@ç(ÈåýÓ~88#pÊIÇÎÿ J 9ô™ÏpÞo;âsZ댧mû×ß̧ý|øÎóßá‘OTûR¦$£ G¦Þi£ieçK)wŸÑv'‹óÔ”{žâ}šššøé×¾Æ[¿õ­)ߟkÛöÌ3ÏäçœÂŠªx¤Né žÁ.¨Ró¢ã>ÕŒtð ÅÛ*‚1òŠ“µåËůœÔ:åÍ¢Ü@UhI+.Ä«8Te”-q®bÏJ+°o.P¾`¾™‘tåš\Îv‡Aä&iÛÏÒ¥KY¿~=ÄŽ¶ßÍ%<æÕXjR&É DqŽ®‰"4‚J©™ ===ž2:ðGÿ¾(Åi[›;™Ïݰý]ï¢õ _ðn^ýú×9ê¨|RÇq'# èuÏ3EÓ4/4˜w¶l©Á›àÀq:&—Op;ÔX]ש¯¯ÕW˜Q¢Ùáʸìs?üËcûùæQ¸ é‡èÄb±ñy¦ ‡¦ù†ã¸ÁßS ºî&¹·íÂõàŠ2¥Þ îöÙ¬û i–˹×ë8þÿÁë·m7ß‹ã¸Ç .Ï'€Ã¶Ýrå“c{d2î:u<ÇNMÝouíº^xŒXÌ¿®âëmnv—Û¶{ìH¤ðø‰DáñŠ=T®œ‰Œ3ž/÷±¯¼2qÇ )ã­?uÀ^àþoÛö„ˆšjrA0ŠjÇò Е+wÐCd, çt:íÕ·µÎ»>g|'ÎÁ§ž>Uíâãd<¶Ù¾ .=á×üûÑo)ã‰ãùÜTº ð#”@¡°¢Ö•J&]J :ôÏ©þFÕ îŒjô\ ŽÑϣ奎{‚bEÔq”p¡áŽi%ç ŠGÁYè1Ü1. W IãS™ø¢~´À>)Ü1°tþ¼*©w_øQo± þdVHåaHæ¿73‡;Ü–¿6Õ*j ”3>(اRµß®+?U9“ùå*<\sþø›ñs4txøa¨røÇJ3VûìŸ=›³¾7_ÝÏ"#<9RwT®•±ì7Ô{h´ûŒ¶e5œ³Â²¿ým WZ[ŒÕ>—÷-¼°’ÚÓh )ŠÀâæoP°iƯ,‹+n¶LyǨJXåäR®^ |—' ßóFÅö ÎŒP"I0¹ª˜#užkgàx 5ëA­SÇQ¹Ä” ¤f´S˜ Iý¯’)Så” œÛl¯„'åõ£\PÕkZCÍôèÀ¯WܸQ^FÊ¥WÍ\ÈåË«fqB»5õ6ÑÙ6µ•ñö;Ñøõq‹±?¤·éºî« B˜  ÒÔÔĆ  –õöö–Øhׯ€Gá˜3gÂo~—\â®H&ÝÇü`¦ D£Q2™Œ;pœAî \lÖÝ_ v:Ná &C{|'’Û¶±m;´³fGK4õ¼y¦‡³˜ã´ÏW`àÈW©Ÿ6mH1%8ØZT²ú¡Ðu·lJ€(í£ÞCU캥lw¸k²m×ã%¼]ГÅ4}Á!ˆòˆÉfÝó_Ÿk‚Ç Š2™Œ{Ü]Cô::Üû¡„’â2˜¦ûîTïL%ú(2wÿ\οž XœÉøžCÁû¥®Û¶]ÁÇqÜýÇ]¼ÎDÂ=F{»û¼yQê¼-[˜êŒ·þä~ˆž šáç/Ê3S…¾ N@H&“èº^‡l¼L†çådðÂÙgóÅ{îáÛï{_µ‹"Lã²Íe°|·ëuœ\¬-‚5’æ8™Œç‰ Ôc»²Y7·˜ãTu@G‡?(ØÜŒ®iî±óíÝÍà¾wc1’êý¯ë$ïqöI[d2èñ8÷sû—¿Œ±gûÿÊ•è«VãÿÆ7°ëëaÛ6ÌË.#~ÑEnùqÇ'tÛË¢=ñ:ØñÞ^Ø´ úû‰š¦·\Ç Òù ‘={@׉êº/õöbnÞ »v¹÷ìœsÐ.t…Œ]»ˆÞ¿{o-Âèëƒ .ðRéá8D~Ž;mÛ6’ùºWÝ»ôöí÷ÝsçinF{ñE8åï·QãF±;‰>òhqÃðöOnߎÖÓÓ§“llÄyåhhpÓÀôõ¡ßwŸ{žåˉΟïîO %Ê#`Ì™ƒ¶e í¦é†³m÷·Y²cÛ6÷wÓu?Ñž=`Ûh'žH»¦yBšJ¢mX÷¿Tû¹Gb¬öùÜ¢E<ôh›ïpÌI¯«l!Õ¤š¡°,B`©úTM6˜"uäHHæÄ©ÃXíó¢.‚ŸV¶lÎøáVåÌ;UBIp–€BýŸÁŸM¥ãÑ¿T¼JzL¡Êë&¸Ÿ™_ÞÁ`…°¸‹¬\6;ëŠÙޝö{©ÿmÜÙ*l»ú®fظÂF¾ÐÓŒu¨1ùÍCü_ŠF|ÅVݯàlˆÀ=èî솩­§Œ¿ß™'õt³™_ï´NE,˜*c‰ÂÔ%4‚JKK ½½½tvvÒÒÒBww7===\vÙÈùPöÿ 8Œ={xröl…® ²uçy<ãi 5ñ:¡hš?ÈgÛîw]/œYþLw5Û½Œa~û2÷ ;òœ:ŒÇ>·vÁIÇ<ÏÓ —•Lo‹Å°,‹H$R™p_å ìu¨ ʳd"“Üëº+0”:¦¦|®‘ÊTêÝ͇|4­ðÝXÜQéݺïÂx¼´ -Pïz”z/*%\–|ùîX³fÊw°Ç[²Úþ²_Ð:¦ÿ<ÜvärhŽƒ–LBCƒ›Pû¾û¼wATM‚H§ Â2F~ücïÐh`²ƒWæ\Žh Ì‘;áË_]ǰ,ŒxLÓµ°,Þý£±õ-oã“_ŒÕ>ûgÏfñ ØóøZËÍ9–H¸Ï¶®C±7vk«ï ¬&§D£î²æfw{%š(b±ÂI/©Ta›/•rÿ"ßóZE P}Ypí;Ø~jmu?Uw¸¶^.7ôºa<ÒÆ~¯ò*ͤJx[ÆŒÕ>Xý«Ê昙tŸè‘&ê§[‚{?þf1Ê=3ˆÊ1×4ƒ•§Ž¢cªXžÃ½*Š…'5“"˜À/xý£8ªÜJÐÒð“̆Œ»ß™Ç>¶=ýK4í …Ëó}Eé' µ@hpãš]wÝu¬X±‚M›6±víZæÏŸ_Ö¾ ÔÝó aÌÄãñÑÚªÎI$â6®F K”˹³¥U¾†à  ¸Uv AK&ݬ|§ÐÜ-±£Ž«Rù‚ÆàN·¦¹Ÿ™Ìàs¤R~ƒ_œ5®Ê ¯R|þhŠxÛ.cµÏí‡à-/î`QÓ¢’ë•gVÕÄ”r(¼š(ªéÊ:1I‡dÊ!øªQeš#¿“ÆjŸÐthÓúxòÀ¾5†ç²,t]§¹¹™x<Žad³YÒé4š¦4ˆ§Š'IE1Œð . cf,¶¹ùÕŽ<0à{p©v%øalƒèºë©7œ} õŽD†^Wœ÷«øý»m¾RõwÐË2x¼`½W\F"nû²Ø+8X—ÄUë"LÃyT—¯‚”ë›JÞ'4›-œ$1Ò±ƒ¿I6ë–Í4Ë»¦övW„+ê8å¿ûúh™7©ÎXìó¹E‹øøçá[îâO-æwù}3Ã(|ÞlÛ¿ÏÃy—BM,Qù‚}¾‘ÂCÇãC÷òYÿ¹‹Å «¼“UD†âwò|V‚CðÙ±,÷xºî®^¯ã¸÷A Gííþ¾êúÀŸP»Û)W…ž ^“eùáiƒýYÇqû³Ù,öâ Ðø’£:—®c÷/Æy×G0ân9ì î¸{ö™-³Ð ìö.Ïlœ+?‰~þ"´«Þ‰óß¿Æzçç½×¤}á5h»{ÐN9gÿÑX¯ÿ\~¹wYúŸ~€ýù u"öôåèë¯w‡ ¬Ö¿ÝæÍÝÔ¾óUì—ê\­,›"÷½­îã°÷Qœÿ¹«¤ÓúTe,öyXæ\O“q¨}Qn_ ­Œ}ÇÒ-0ÆvŒà¤®‘pgÐD0p4]ÓíóüóÏÓßß?†‹ª-Æ3n ®7lWÄŽ9¢`y&“!›ÍJÈ/¡f˜6000PíBééé¡§§‡†††²ÜÆÖ¬YâõëùãGà¯X#‰|ð¸:sr£lÖmŽ&·I0 Îhhmu„9¾ð&¸IMs³•´q·«:º^؉I±¬ÂPE0XøQá‚TGµx¶½jÔƒ.È4 ·QÇæ—(¨”ˆ–î˜XÙL†%W_MË5 £³ÏÎÎN:;;ùùʵ|䪟rNâï¬üÄàĉDâðlü “š5k¼xSÑØ§º/­€ùàþ¯‘{CGA2ørQ_Ó4§LØJ¡ò¨:¢RIÃÄhÛ¶W¯ú:§=û>V&Ÿ÷daʲnÝ:ZZZ¤m[Dgg'ßüéËúÍ[™3ýgÜðƒw¡×½äO¢›Ô€y.çvg¢M÷¹§ ,(pøUz¦êîD£n—E­Wª›“Lú]0å|¿äAš?vé´[érjI0™„ܯ÷ùéjõÌ-ò¢Çvtø)íûÐŽ›Aû¯æxŽ4ñÓAÖ1ÑÏšëi°JÓÉfý4„êuƒöË`?{$©ç>Tpk“I·»Ÿö5²Ç|çà|O/I§Á¹á&RÝïD[éæÒP:­š™O«ê:ýœõúé3='%ލˆºJoN¥Üsë û‰Ú€ußA"7µºm¹ûE}G!¥Á*S]£þâ}˜ÿ|úÓ¿ÅZx Ù_Íö®À^ÿG´C/a|e•û[ܾäÌÈ6§<§ñ|DDîºë.žxâ-U±—Éf,mÛJÓŠ«Øøi: `僲tþü‚üjÒQ.—+ VË-ËWåçuÇ›ˆdÛvÁñ4MÃ0 /T¯:N6›%‰`Û¶÷]…ßF£žGy"‘ðÂà«Ü¿†a|ªó«(*¶m£i™L†t:í3‘HN§ÑuÆÆFÒé4™L†h4êåTTåL&“d2™‚ò©üÁmmm$“Ib±˜·¯:]×Éd2Äãqï³­­Í›7ÓÖÖæ}ooo'‹Ç=a$xßÕ} ®K&“Þ˜a4%•J‘L&½kŒÅbÞ÷xÄgÌà’Gågçž‹óÛßòÇÓN#söÙ÷ðÃìùË_X¾|9—<ø 7HoÛ6™L¦@ŒPƒ÷Š è¡D˜\.ç}WílMÓ¼»ª/­>•@24MóÖ)EÇ4MO˜ n§<Ì•·@PÄÑuÝft]'™LbY©TŠ®¼ÑG£Qt]'‰x§·¶¶ǽ{‰D<w5©+xŒ¡î°+ï§Ž¡¾oå¸W"‘@Ó4/®ºWê¸ÅŸÅãj²ÐáÀXûäÖ?›ã?¾`¹zFe‚žP+„ÎCe´(•}¯ÿåÛ Úf¶mÓÜÜL{{» ÞN&£‰Ÿ[ q=‡Ó,¾Ñ ÿùÌZ´ÿù-÷?ÿöAÛär9lÛ–BÅ8œ÷ö±jãFo›ÖÖV’Éd€(Åaá¡2VîÆA¹ä‰˜2ÉLµÊrª]Ï$ðR]sŽƒÆ÷ƒ˲d‚ Tk?Df.๶NY5Ó,8N„‰çÔW^añâÅÕ.† Å<®sÞ«¿ç¸Ö7²c‡»H¥í¼ðLÁðQAÊ©6G V ÒòL6-ÞŒt¼Ñž¯ÆÇ£…‰`¸PÝàMÌd2€+fÃ\utt ëº& 4qèë³gòeî_ozà‰'bŸx"Ü|æ6®Ø¢ã†‹ç—EóËt]¯y1(«O0•Å¡|ö;0kö.öy¸$“IyF„šbÊ*_>LÜ Á×¹J’+Âä²kÁ.Ü Ëú~ˆï;†ç,ƒ±‚P]ôÝøD[œ²&´¶¶z3ùÄ~¡rœ¸s§L䄲¸¹›†'ÿƒå+îᨣüüÏý!U£ T¡òÞ¦RͲ÷Moâæ|8,Ó4™}óÍìºê*¶¯ïïG?å׳%è]Nþ×¶6?¯k:n^´=“ÁŒÅÀ4‰.^Lâ@Ç;h";v`Ür μyO>‰ñÔSØ7Ý„¾b…üàùç¶É{»¨Ü³Ê¥+ÃϬÇC¿çìúzr ééÁxç;ÉÔÕaàæÉýéOD~ÿ{´þ~,Ó„3ÎÀX²Ä/C&㻨)‚÷ 8ÿm0Ž r© ¾Uâ¡à=ÌfK»Ôñƒ/[S1HññUùÇ߯ÜòŸÃ0«Þùã/ݶÍǃ0<‡ y/¼°`ykk«®Mj)!¨8ÀÕÆ&n¶ç®DœN¥Rär¹1%Úaü<”ƒ×,ÌŸ¢‰×˜ Tí%0›”ð±˜\.G&“¡½½½d‚HA&ddVBÈisô‘`Ûîše¹ù3Ä\!”óÙqÍ5ÌüÅ/èûýïùÛÓO£9Ž—{ƒ/|/mßî%F/I9ù_ÓiwÀ½”§I o«¨-’@óñÇ“»þzL\ñ#ƒ+p@>ñ}?|êS˜K–`ö¡C˜¸ã_ª%n~üãd-rßß=ož·¿‹“{×»Ðûû‰îÚElÕ*˜3‡(Sç\¾œææfØ·ã±ÇpêëÑ€ˆ:×å—C?ΑGb¼ò z?Jþ0û꫱çÌ!ºmöœ9ätÝóØÉ,Y‚bîÝKfÉÌ]»0u%˜¶Mæ¶Ûp>ô!"}}83fÍŸ[ÏßmÕ*Œ¾>÷X?Œ™ËaG"8€¡ë8—]†5oz?z?¹ãŽó«Y€óÖ·bê:öœ9Øsæ`qä×Åû75¹÷.¿ gœáþ?>Î÷¿ñè£8Ÿÿ¼·¿n ëtþýïô>ýtEñ©@ÿƒðâ9³è_\(>u”YBÆ”Tì>x sǾ°½@‰¶, Çq$?ƒ Tçù=ìš5«`Y0!ž Õc/Äù&±|ÒÌR¨*¦-ˆwŠ T’e/½ÄSóç#¿!|,zî9ž[´ˆS4wü´£CÄA+–e1íÌ3ÉÍžMúýï÷BzIODü¼b†2iÇ>‚%±cÎì£ÆÆ ¦qÊWÆ Ÿ·eÙ2TêukÎù¶.Xàÿ¿lí¸"IAi?Þ0æÌA;ÿ|À Ofå·ÕóÞ*&nÌ Wr€`œq:[¶Ì"ZqÈñÇc<ÙüþÙeËhÃLZuè 7 ÏšåævÌïË?äV®ôÊœ;ã bø9i,]]'’/³ž_gåÿwp£Øòå?^"pb]äí¯®ÓÎÃX²„ì’%î=:ûlb3g¢î‡fØÀø‡ŸüdüÏÓ&ìÚ÷n}’Õ?ä-w‡X,&á…šbJ*ýOÃQ};¹òþÞøFo¹S$a® T=¯í£ùÄÇ –9Ž#v)UÆ^Ù?ÙT‹‡IR©†aˆ*“Dç¾}t_x!ŽÿP‚ L0óﻭǃa€D&„p“Íf‰D"|ö³ŸåÚ2’¦O6Ãõ†•0¢×ÕlL¢Cì3F™Ë#ø¢Gò"K‰2ÿ.KjºøÿüäË¡öQâÆ饈ã{hùý‚‚•“ÿßɯ+¾æ|‘\fÏ.Ø.øÿúGå¡rŽq˜sZ=8s¶WFÜ„Iäˆj`"èßçL櫓µµ`y.—ófÖ ‚0ù<µt)Ó÷AÏi§yËœ|c6l ZA8Üp€†Üú÷õ—KlÛ&‘H‰DÄÓS&‘… é1&Bu¹måJl™`P€ã8^ŸÛ¶í’aAÇ!—ÏA ¶QÛ©>»eYضí+—Ëì—J¥¼ujyðs$¬`Œ¢åÁòo¯>K-Ëì8–eyËÔq‹×Û¶=èÚ‚×`Û6ÙlÖÛ/›Í\ç+¯¼R퟼&PmX•KWúžƒò ™LtFSTÙ‚ù”u s+kÏJd©;m÷n7ž0<=/1gû¯ Åb1 )-ÔSÂC…ça`Ú‚‚EmmmD"™Q+UäÈG;íž^¶Ì[&"§ „‡›ðúúg¸`Ae¨A*ÇÌ™3Å‹SBÊsÏ=7©³–e¡i¹|"mpëg]×±,‹H$B&“!™LbYÙl¶`»H$â ÆëºîµÃÕÿê¹\Îx6M“X,F:&‘HxËu]Çq à ‹yy(t]'—Ë”%‘HN§½í4M#“É ë:±XŒd2I[[›WnÓ4ÉårÞ§j{¨c«sƒ›¸8{Ë•(¡DÛ¶1M“T*å§½½D"á•-™L’J¥¼ýâñ¸·}"‘(øžJ¥¼ó©ãŸÓ4=±Då™ þ>mmmÞv¶m“L&½²g2 Ãð®AÝ÷\.G6›%z"ºO>ùä¤>óµŒzvA÷Þ>›+õÂÀ¶ñx\ìU¨9¦„ 2¯ ö6îD×ýàb‚P}y€äŸgðÝ»¶hY™LFÜ9!XÀ¬9}ôíy®d}é8í¥’k ‚pX¡ZK "«ÎàÌjÃ0¼_Û¶Ñ4ÍóN 4ªSÃ0¼ÈâíÕ±5MóŽ­Õ¾êSS Lªó«eÑh”L&Sð©rºY–Ur°Ù4Mo[UÆà1Ôà«ú®LÕà¯|VÇWåH¥RÞ`u$ñÊ,g$48¨œYäWÇÆ+”ØN§I¥RÞ9Ô cPPÎ,~…âÙøÅ×P¼OpwPÔ†{1M]×½ÁPµ\ FÁeêOm« ]׽倷^[í›Ô~jÛà²*kp½º_Éd]×I§Óe †±QÂ:·Z§ö ØßWµŸò P}§«®ºªÚrhyÇ;ÞQV[6è± ìQ iÁðXÁû®ø•í %d*Ô ¼iše Ú÷páK]ÇHáG3)J•c,! ‡»îRƒnš¦ú¿öÃ]ÜúãgùÚg^ôÚ±*¢ T’J´m§„‡Ê28õT÷R,Ë"‹ynÊ‚ T#î`Ñ ¿À0>ˆ‹º „ k/ q À.ÕŒj “ áömZ[[ioo÷„53]ÍÆ æ4€¡ëÝ`!AƇòöikk£««‹t:íyâ-“ˆÔo‚^ž¯¯gÞE; rv‰ŸP«QíLýÛw²téAﻄú„pÐwpM;aP2MABÀ+pÞÒ{…þQ!JAJH±,‹Í›7{ᜂa§Äf¡:(ûÔ4Í›7K”A¨"–exf ‚.îý l߸óQU B-Ró*Ǿr,Û~»ó6·C™H$$¤ „„§x…׎x   n· ÕgÛÖ=œúÌ]Æ»¼<20+á!‘H2YHÂHkkkÉí‚ T‡àDAÂǾº}Ì|­Çû.¡¾„Z¦æ•¹¯ÍeÞòÝ^2ÊöövQ8!$lÙ3À¬…Oz S¥+áá‚ï?Êc¯é (™LÆKL,BuQáƒDH„p’Éd¼Ð^‚ „ƒL&C<¯v1A(Aj<ðÖY¼wû4À4$ù„Z&t!¿zzzèì줧§§¬í¯;ÄÁièºN,ó’ ‚0ñŒÖ>Îz•…§/òf¾ ‚P9FkŸG?ºãNظ¡¾"‘ˆˆž‚PFk› Ée$•g,ö™Ëå¤m+“ÀXìS& Bå‹mÚO9XqÎR€‚Ü‚P‹„JPÙ°a«V­â–[naÕªUlذaÄ}^š{"³NÞåy§ˆÂ)•a,öù² ,<¹\N*KA¨ c±OëÙc9þ‹Üÿe`H*ÂXlóµ×^£¹¹YêMA¨0cê{¾ô–e‘N§«]|A˜ÒŒÅ>%| Tž±Ø&Àƒïá¤ûž¦¹±‘X,&â§Pó„*ä׺uë¸ùæ›iii¡»»›U«VÑÒÒBCCÃû¼rì³sÙ&2™;ˆD"2 $b,öY__Ï)§œÂ«¯¾Zíâ ”f,ö9{îNÞò–×ÑØØHWW—4j¡ŒÅ6¬„I`,ö¹mÛ6Î=÷Üj]¦}ôQzzzxâ‰'xÝë^Çüãj_Fa~¶òþ_ÙvìØÁ©§žZí¢T”±¶m-ËbåÊ•455UûÆE˜ŸÁÑv{/—r~iÛmŸ[·nå‡?ü!wÜqK—.­ö%Œ‹Ãé™®FúMTÛvïÞ½Õ.jÅkÛvåÊ•,\¸E‹UûÆL-´Ëeª¼gÊùM¤m;|ÛöÈGžçì_ä7½“ /¼/ùËÕ¾”Â^—ÔÂ{!Ìö¾uëVvîÜÉÞð† =nh•ÞÞÞAËÊqç|üñÇ«]tA˜òŒÅ>?÷¹Ïñ¹Ï}®ÚE„)ÏXìóÞ{ï­v±aÊ3Ö¶íÃ?\í¢ Â”g,öyå•Wrå•WV»è‚0å‘¶­ „“±¶mïÞòûü_­ö%„š_uuuƒ–¤r ‚09ˆ} Bxû„p"¶)áEìS‹ا „±MAð  ÒÔÔ4È{{{%é˜ „±OA/bŸ‚NÄ6!¼ˆ} Bxû„p"¶)>¡TZZZèííõuwwÓÓÓÃe—]Ví¢ Âaا „±OA'b›‚^Ä>!¼ˆ} B8ÛŸÐäPX»v-×]w+V¬`Ó¦M¬]»–ùóçW»X‚ ö)aFìS‰ئ „±OA/bŸ‚NÄ6ÁeÚÀÀÀ@µ ¤§§‡žžÄmLB†Ø§ „±OA'b›‚^Ä>!¼ˆ} B8Û„ *‚ ‚ ‚ ‚ ‚ ‚ a#49TAAAAAAŠ*‚ ‚ ‚ ‚ ‚ ‚ # ‚Š ‚ ‚ ‚ ‚ ‚ ÂLÿ¾ð…j¢Vééé¡»»ÛKÆ4Ôz€ºººQ¯ŸHº»»™={6³fÍ Uùúúú°,‹¾¾>Ž;î¸Q•a2ïŸP{ŒÇ>«m›å”¡Úö†ò µËpö¦gk,öYmÛ Û=¦•²Ûj=•°ïɾ–JÕÓòލ-*Ù' “}Ž×þ&óZ*ÙÇû¬-*Ù'­Æ³P‰¾k˜êÎñ–Uìs0a¸'}}}¼ð ¡­;ÂÞ7îîîæé§Ÿý¸í¤­ câÆohnn¸æšk.¾øâ÷¾÷½½½½Þú[o½Õ[ßÜÜÃP>¡vÎ>ÃôlÅ>«m›a»‡ÂÔ¡Rv[­ç±ö=Ù×R©zZÞµE%û¤a²ÏñÚßd^K%û¸bŸµE%û¤Õx*Ñw SÝY‹¿IØ Ë=¹ñÆn¼ñÆQ—o2Êö¾ñõ×_?pñŇ~ܶck"¨ŒgŸ}vàÔSOØ´i“·ìâ‹/Èd2Þ÷à¹iÓ¦SO=uàÙgŸ-{ýD¢Œàƒ†òïYooïÀÅ_¹\ŽK/½tÄ2LæýjñØgµms¤ò•³~"Î>ÃP>¡vÎ>ÃôlÅ>«m›åÜ#±Oa,TÊn«õk‹JöI'ûY¨Tß5LuçxË*ö9˜0Ü“¦¦&ZZZJæÅÃoö¾ñ¥—^ÊÚµkéë룳³Ó.”û®æØš*ãdãÆ¬ZµŠ––V¯^ øj]à4Òú‰ ¯¯ë®»Ž›o¾ÙSË=ÿd”¯§§ÇS-¯½öZX³f÷àW†É(Ÿ05­}VÛ6Ë)Cµí3 å¦Åö†gk<öYmÛ,§ bŸÂx™H»ìç±’ö=Ù×R©zZÞµËD÷IÃdŸãµ¿É¼–JöqÅ>k—‰î“Næ³Pɾk˜êÎñ–Uìs0a¿'aûMÃØ7VôôôpË-·°qãFOL© aï»ODEP#}}}¬Y³†uëÖñ¥/}‰/}éKÞºRêgPáiýDÉdhjjò\Åz{{éî»;å÷A½ùæ›iiiaíÚµ¬^½š 6ŒX†É*ŸP»ŒÕ>«m›å”¡Úö–ò µËPö†gk<öYmÛ Ë=¦&•°ÛÉ~+ißÕ°­JÔÓòލ=*Õ' “}Ž×þ&ûZ*ÕÇû¬=*Õ'Ìg¡’}×0Õã-«Øç`Â~OÂò›†¹o¬hjjbýúõÜvÛmlܸ14ã¶Õ[AeŒ\sÍ5444Ëå :p¶â¡··×SºFZ?QôõõqË-·pË-·ÐÓÓÃwÞÉwÞŠòµ´´ Rƒß‡+ÃdÝ?¡v«}VÛ6G*_9ë'‚áì3 åj›¡ì3,ÏÖXí³Ú¶¦{(L=*a·Õx+eß“}-•ª§åQ{TªO&û¯ýMæµT²+öY{TªO:ÙÏB¥ú®aª;Ç[V±ÏÁ„ýž„å7 sßxÆ ÜrË-Þ÷ùóçœ7 ö]Õ±µ²R× Üzë­_|ñÀ=÷ÜSð÷ì³ÏzÛ477ÜsÏ=›6mhnnèíí-{ýDsÍ5×xç Cùz{{š››6mÚä}¿øâ‹n½õÖ²Ê0Ù÷O¨ÆkŸÕ¶ÍrÊPmû¬vù„Úe$û Û³5Zû¬¶m†ñ µO%í¶šÏãDÛ÷d^K%ëiyGÔ•É>Çk“u-•îãŠ}Ö•î“VëY˜è¾k˜êÎZýMÂLXîÉ5×\3pã7Žº|•.Øûƪ|ê˜a·ì±5TÆÀ7Þ8pê©§ú è­·Þ:ÐÜÜi˜ìs¼ö7™×RÉ>®ØgíPé>iµž…‰î»†©î¬Õß$Ì„åž %¨Tû7­…¾±²uŽ0ÛNöØÚ´ õ·Ç[w áGl²ö™Š6yØ *Ùl¶f ±µµÕ«$‚ÿ‡˲hll$•JÑÖÖF,÷1mÛ&›ÍVûÒ„ öY$ š››KÚµØçÔDl³ö)×6mÛ>¬ïÓTCl·vªnÛºˆ}N.Õê—ŠmÖSÅ6K}+cµÏñÖBm0Ul²Vì±LE›<²ÚÊ'—Ëy3[‚ÿ‡™¶¶6âñ8ñxÇqhnn&›Í‰Dª]4A˜PjÑ>Ç‚mÛ¤R)6oÞŒ®ë8ŽC}}=ÑhÃ0ª]'¢î„JS‹õ¥PSÞC%›ÍÒØØÈ´iÓˆÅbƒ^¥„××דH$H$žbhYmmmL›6Í{¡+Z[[Éd2Ô××S__O&“!‘HP__Occ£§ž–»ÝH$ ïóšk®ñþ/GÝ –!—Ë ú^j›r7Ü5©—E<@Ó46oÞ\P)ªc˲¼ßBs8×°àï6šý„ê3œ}g›j})ûÍÕ‚}ŽÆ6GsMåØK)ûT¿‘¦iÞ§jÀuoÄ>kj×£Ýv(&Ò6K-«–}–²Írö+¾7j¿à2Ã0D­aÄv'¾Ý[î5µ^FU·ŠíÖ.Òî­^»w²û¥Áïb›ág0000°k×®MÓÚÛÛvíÚ5F€ŽŽoÚ·££c@Ó´Í›7 '™L:iš£Ú®TÙŠÿ/g?Ó4½ë*þ^j›‘ŽWÎ5¥ÓéÓ4½ÏH$2¨ÌÀ@4صk×@WW×€¦i©Tª`¹º÷jߎŽïÑhtÀ0 o»áöÂÅpö9œm kŸ£±¹Z°ÏÑØæh®©{)eŸÑht ‰ ¤ÓéH$RpŸÄ>kŸ0Ô£Ýv8&Ê6K-«–}e›Ãí7”m*ºººt]صk—wMBm!¶ëï7‘íÞr¯i<õêÀÀÀu«ØîÔ@Ú½þ~Õh÷Nv¿t`@l³VOÝ\û,¶Çrí³šíÞ‘ìs¢ëNé—†iÏúûÕZ{v¬}ÑZµÉ)-¨Äãñh4Z°L×õ‚(hê!íèèH§Ó†aìF½}ƒZ”úñƒßƒ‚J9Û•Ãx Q½@J}jÙpÇ+çšÔ‹OUˆê{qY‚†ošæ@*•Ð4mÈßR#hšV`„Ãí'„‹áìs8ÛÖ>Gcsµ`Ÿ£±ÍÑ\S9öRÊ>•-«ßJ×õ‚}Ä>kŸ0Ô£Ýv8&Ê6K-«–}e›Ãí7”mªßP×õ®®®‚ã µ…Ø®¿ßD¶{˽¦ñÔ«jÛRu«ØîÔ@Ú½þ~Õh÷Nv¿Tl³vOÝ90>û R­vïHö9Ñu§ôKôgýýj­=;Ö¾h­Úä”ùeY–çþ§ÐuÝûßqœ÷Ûà¶¶mcYÓ¦MóþjÂåh‚×]êûPË&â¼íí혦I2™$ºÅ¿0È-ZÓ4lÛö¾ÝÙ‚îr#í'„‡áìs8Û„ÃÏ>+a›Pž½ßûÛo¿l6KWWÉd’Í›7cY©TÊÛFì³¶‘º³ôuµ¬ZöYªîi¿¡l3•JaŽãxa,Ë:l“&Ö*b»¥¯»Ô÷¡–—±Ô«™LfغUl·ö‘vïàë.÷ûDžw²ú¥b›µÃxêN˜ZöYÍvïHö9‘u'H¿4ÌH{¶ôu—ú>Ô²ñ2ÖöìHûN5›œÒIéˉU:Ô¤i¦iÒÑÑQí˨YLÓÇo(£+¦øw)Ž™hét]׉Åbtuu•µŸF²Ïá^žÃÙgp`_ž±ØËöíÛÑu½À–MÓ,ØWì³¶‘º3ŒÕ^†Û¯”m*[vÇ{Ú¶M6›ÔaÂØnõÝW·ŠíÖ>Òî­.Õè—ŠmÖã©;Aìs"«}ާî”~ix‘ölõ}Œµ/Z‹69¥=Tt]'“Éx?„eY/êH$âÍ­ Î"q‡ÆÆÆ‚„FÂð†á)ÄàÞÃl6[–‚jÛ¶÷{¨ýLÓôÖ+£‹Çãèº^ÐXn?!< gŸÃÙ¦Z/ö9~Æb/§žz*¶m{¿Ú/Øû¬m¤î cµ—áöÊ6“É$ÞŸa$“I’Édµoƒ0 Äv«ÏXíVµ™‡ª[Åvki÷V—Éî—ŠmÖã©;Õz±Ïñ1VûkÝ Ò/ 3Òž­>ã±±ôEÇ{Îj1¥=T¢Ñ(–eÑØØè½l#‘ˆ·Þ0 "‘ÍÍÍèº^ €éºN<§µµÕÛ×4Í‚ý']×I$ž¢§þë,MÓH&“477cš¦w£ÑhY׋ÅÐuÝ›yÇKn«Î±téÒQí'T—áìs8۱ω,óhíå /dçο›abŸS©;ÃÁXíe¨ýŠ”mF"‘Ðß ¡<Äv«ÏXíV ”ª[Åv§Òî­.“Ý/û¬ÆSwBøì³Ø§²}޵îT÷Iú¥áDÚ³Õg<ö1–¾èxÏY-¦åÊLi,ËòÜkƒ³¨ÇñÜŠÇÁ4M¦M›Æ®]» ÜŽlÛFÓ´ª?ðª,*«ú¿\wåj—»Ü{˜ËåH¥RtttËå*¾ŸP]JÙg9¶ bŸãa¼ö2Yv-T©;«‡ÔƒÂxÛ­aaºÿBevou‘ö«0ã©;!<ö´M•ƒ`ªÚçX÷»® ¤=[Æc‡[vJ{¨(†ú!Ç¡µµ•ööv à ‘H`šfÁƒ­ëzÅo)lÛ6Q’iš˜¦YPUÆáârªý*Q–Ñ0ž{8V¯°»† >¥ì³Û±Ï‰8¦Úo´Tî…É%ìu'ŒÎ>ÁµM5ëe"í³R¶©öÌý„Ú'ì¶+õêÐLÖ»S¨Òîø²Œi¿ C1žºÂgŸÁrÁÄÚg¥êαÞC±ë©‰´g'¾,£e<öq8ôa Ae(t]'N{³®ë´··Oz9Tâ¤áÊ9‘ûU¢,}?Æ¢FÖŠŠ)ŒLXl¦®}N¶½ˆ}NÄ>'çxR MXl7,v;ÑÇûÆJXl¦®}Žç~ˆ]Þˆ}Vþx“Øum› ‹=Nô1Çc‡[ö°ù%‚ ‚ ‚ ‚ ‚ ‚0ލvAAAAAAÂŽ*‚ ‚ ‚ ‚ ‚ ‚ # ‚Š ‚ ‚ ‚ ‚ ‚ ˆ "‚ ‚ ‚ ‚ ‚ ‚0"¨‚ ‚ ‚ ‚ ‚ ‚ Œ€*‚ ‚ ‚ ‚ ‚ ‚ # ‚Š ‚ ‚ ‚ ‚ ‚ ÂY팗·½ím,]º´ÚÅ’;w²hÑ¢jcHöîÝËÞ½{Y°`Aµ‹2$a¿‡;wîäãÿ8ï~÷»«]”PqÓM7ÑÑÑúß.Ìå{ùå—™={6³gÏ®vQJR ï­[·òûßÿ¾ÚÅmmmÌ;·ÚÅ’Zx¶äý1>vïÞͲe˸ñÆ«]”Ðö¶m¹„ý a·÷r)÷7‘¶mi~ùË_òï|gJ< ‡Û3] ”û›HÛ¶4aoÛ–K-´Ëeª¼gÊýM¤m;4oxÃ8óÌ3«]Œ! {]R ï…°Ûû3Ï<ÃÕW_Íš5k&옓.¨ôôôÐÓÓS°lÅŠÌŸ?¿`}CC #oéÒ¥¬_¿~²/£lÖ¬YêòuvvÒÙÙÉÚµk«]”! û=\·n .¬v1ÆÍH¶ܦû|ÃÞÀÁƒåÙëÖ­£¥¥…–––j¥$µòþ˜ L´}Î;7ÔÏ~­<[a¾‡µòþ˜ nmÛr û38ÂnïåRîo"mÛÒ,\¸·½ím¡®›Êåp{¦kriÛ–&ìmÛr©…6p¹L•÷L¹¿‰´m‡f`` ÔÏBØë’Zx/„ÝÞÛÚÚ8xðà„sÒ•uëÖ±qãÆ‚eëׯ§¥¥… 6°nÝ:V¬XÁ¦M›X»v-«W¯žì"N(—^ziµ‹0, ¡}i(Â~§ ÃÙ& öYZZZÊj T‹ZxL7û¬…gKÞ‚âpkÛ–ËTzÃnïå2•~“r8ÜêÎÑ Ïtø˜*¿I¹ˆ}–¦ÚÀå2Užé©ô›”ËD·mÃ>I#ìuI-<ƒa·÷%K–pì±ÇNè1']Péëë+¨(ƒ¬[·Ž›o¾™––º»»YµjUèì‘{¥_®¢\MÂ~§ ÃÙ&ˆ}Vƒ°Wšµðþ˜*nöY Ï–¼?ÅáÖ¶-—©ô †ÝÞËe*ý&åp¸Õ£Ažéð1U~“rû,M-´Ëeª<ÓSé7)—‰nÛ†9„¿.©…g0ìö^ AeÒ“Òwvv–|:;;©««ó䦦&ššš¦ŒËœ „¡lS­û„ê!ö)áEÚ¶‚N¤î„ð"ö)áEÚ¶‚02“*¨ôõõpà 7pÚi§qÞyç±aú»»l]]Ý ¸}ÅìÞ½[ŒW¨lÛ¶­ÚÅ7ÃÙ&ŒÝ>·mÛFwwwµ/O8 éë룳³“½{÷V»(r-0±ö¹wï^:;;G´aA¨===<ú裼öÚkÕ.ʸ‘¶­0Õ¶­´m…p¢Ú¶»wï®vQ&äZ@Ú¶ÂÔAÚ¶åµmÕ±a2éîî®HÛvR•žžZZZ¸öÚkyâ‰'¸ùæ›Y·nôööÚ¾—¦={öH§S¨S¥Ó9œmc¶ÏmÛ¶±iÓ¦j_žpÒÛÛ;e•Jاt:…jÒÓÓCww7ûöí«vQ&äZ¤m+L%¤m;<Ò¶ª…jÛîÙ³§ÚE7Ò¶¦Ò¶Õ¶-µ¿ TšM›6Õ¾ ÒÔÔT‡¯¥¥…Ë.»Ìs+¦œÊpÑ¢E¬]»v2/C<Ö®]ËÊ•+«]Œq3œmc¶Ï•+W†>–¢05ihh`íÚµ,X° ÚE7•°Ï °víÚÐÇ‹¦&---D"æÍ›Wí¢ŒiÛ S iÛ´m…j¡Ú¶aÏEPÒ¶¦Ò¶Õ¶ {aj²zõꊴm'ÝC¥ØEzþüù€k´Å†ØÛÛ+'“Àp¶ bŸ‚PMÄ>!¼HÛV‰Ԃ^Ä>!¼HÛVÊcR•ÎÎN®»î:/n^__7n¤¡¡––ÏÜg===\vÙeÕ¾G‚0åÎ6±OA¨"bŸ‚^¤m+áDêNA/bŸ‚^¤m+åqädžlõêÕtww³jÕ*Ø´i«W¯öܦ׮]Ëu×]ÇŠ+Ø´ik×®-˜© BeÉ6AìSª…ا „iÛ B8‘ºS‹ا „iÛ ByLª ð¥/}‰îînÏ-,è¶zõjZZZèéé´N„Ê2œm‚ا T±OA/Ò¶„p"u§ „±OA/Ò¶„‘™tAܸ{C!)Õc8Û±OA¨&bŸ‚^¤m+áDêNA/bŸ‚^¤m+Ã3©9TAAAAAAjTAAAAAAF@AAAAAA„AEAAAAA„PaÛ»ÝD ‚Š ‚ ‚ ‚ ‚ ‚ ¡"ƒ\2°,w™e¹ËÍÍ“W¦#«}SAAAAAA¨mlÚÚ «kð:Ë]‡l ÃÝ6q…‘TÊ]¦ëºÛf³î§Q ÃÝVýéº+²˜æàs9Nå¼VDPAAAAAaH,Ë5À;t ˆÇ}C×Ým,ËÝN‰ ©”+pD£î>ííî1À]®¶·mw[…®»âˆ¦¹Ÿ–åCÓ\1ŶÝåɤ¿]"á 7‹ŸFKËÄÞTAAAAAA’DÂ÷W( †ÞJ$ÜOåb®·J<î.×4w¹iº¢‰ãø^&é´»¿iú"L4ê~Ã0ÜåA¡%‘ðÃp­ÖqÄ…|üãÝzDP¡&q€©vAAAAAa aÛ®($—s… õ©lÖ÷q7ŒW6ë~:ŽûG‡û[›+zd³~¨®HÄfâq?ì—:&¸Þ'êXÁ2©sª¿¶6w}<î :?ÿùÖ ¿7"¨‚P“X@†BAÅÉÿéc:¢ ‚ ‚ ‚ ‚ Ô&Á\àŠ ™Œ+F(OŽööáaÛ~Ž%Œ¨}ÚÛý[àn»ßÇ@”°’ͺë•p¢iîg$?˜—LúçUá»Ô1Ôgðµ¿B‰+ÊkFy·¨¼,Ñ(¼üò½@Ó„ÞgTA¨)²¸b ¸*à +fþ3t!¢Š ‚ ‚ ‚ ‚05I$  p=4ÚÛ}CÓ\¡Ay›”JÒnY¾@b𮡄\Î]—Éø‰ä3w3T(.u %zD£ÐÚêŠA¯’dÒ=NPøQÛÃp½`‚ߎ9¦wÂï½*‚ Ô)\±$h€_¦òUÅóÿ§«]PAAAAA'*<–òü?‰Ê7¢D•‡DícY® GtÝ]gÛîö*Ì–ÊkbYîru.µÜ4]%˜ÏDQì=®xR¼¼XH©EDP!´dóŸ è|ÏâŠ'Ê;%‰+®ùmAAAA!¬är…a®†"› S!¸‚ùMTBvâJm«Bx˜© ž”BAB‹…Í@WP‰ãzªÄp½Q4\1…ügWhAAAA„°ÌW’Nû‹¦ù!º”èÐÜì'tW"I.ßqüPZ™ŒûiY¾—ˆ:†ò6ÉdÜõJxI§Ý屘/°$“…áÀTA-®P¢’Ï›ùïàz¤_V,ˆKþAAAA!,X–Ÿè]Ó\aC‰껕O¬rŸD"¾à‘Éøa½”çG*å†ßRa½"w]k«+€D£…9MÔ1 ÃõlÑu¹:fG‡/¢¨²çj9ÜAE„Ðbã 'm¸ž)¥<õaöAAAA„JÒÚZ˜ E pE %ŒhšŸËD‰'*œV.ç.³mW0QáÀ”I*å®WBˆò> &z/.‹B_×]‘$)½M͓ř]!ލæµuwwÓ××W°¬§§‡ÎÎNzzzªY4A8¬)e›0yö™Á}÷é¸ï?Ñ…ï2AE˜ºTÛ>AiÛ B8‘ºS‹ا „—©Ô¶µ*||•ð|’¶6}s³»M&ã®SBˆeùž$Ù¬ŸçÄ0|!E‰.~òøxÜý¿«kðöáiî>Ñhi1%ŒX–…£n® 8¸?¨ ¤ÿáæÈT¦LUTzzz¸æškØ´i“·lÆ ¬ZµŠ[n¹…U«V±aÆjO[JÙ&L®}¦ð“ÎlåþÚ(·„Z! ö)Bi¤m+áDêNA/bŸ‚^¦RÛÖ>‡iºbH"áþ)aÄ+ƒåç:Qa·"WI&]#÷ÃišûÝ4]±D…é Š)Ê3%)OL JW þHYÒÇš¥¹Û_™‚ÖŒÊ&—ß./®H~ ,xä†GØwÔ>~æ ?sçž{n‹^µ_7ÜpàeëÖ­ãæ›o¦¥¥…îînV­ZEKK Õ*¦ v”²M˜<û´q=RÚÇq ñP¦&Õ¶OA†FÚ¶‚N¤î„ð"ö)ᥖ۶NÌ ŽÛ+lÜñøñêJ$1ŒÂP]Êc¥µÕÅ¥iÐÞîŠ-mm~îµ*å'†WbLqè.M«Prølþ3’¿a› ØÉßpåcÃK«¿ÊÑû÷3ëÁ¸ãŽ;xGöôÏîç寗Yü‘ÅÐ/ÿîeö7°å[hØy4»úO☣`çþíúú!p`‰½„¾¾?0ÿå» ù“,Y°„ oû*­¿leîœ×Xð“.z—/‡–– »œªx¨¬[·Ž¦¦&V¬Xá-ëì줮®Ž–üÅ555ÑÔÔDggç°ÇÚ½{÷ˆÛB¥èììdÛ¶mÕ.Æ„QÊ6ÕuŽÅ>·mÛFww÷¨Ê`ãçJq·B¿’±,ÿÿ¡0pßÕÂáK__ìÝ»·ÚE™0&Ò>÷îÝ[“nÚÂÔ §§‡G}”×^{­ÚE™0¤m+L¤m;ñm[A˜TÛv÷îÝÕ.Ê„!m[aª mÛòÚ¶¥BûUŠâ ¶…Q¢ÀÛÏm§t„ ÈÁçw æ@÷3—óCue³îwåAbš~x/•>˜+%u¯œ|(…ã8X# ¢©›¤þÖ=GnÈ–žÁ¸Á/?ó2ý'ôûëþÍr›ìË~¶ýr´Âô'§³ïÉN^=óUöÿç~^üè‹ô­ëãÉo=É–Ù`Wt Ò xù¢[Xºý)¦í9cÿíR^œñ^\õ"KÛÇü¥¿aÛ¬mÌ¿ï ½gÓçÿ„o»ƒ¶eõ,šv9sŽú4ÿøÚ-Z4q7•**ÝÝÝlܸ‘h‘/Rww÷ E³®®nÄ qÏž=ÒéªÆTête›jÝXìsÛ¶mƒÜ·G"‡/‚§Rn…eY®ª®ëd[›_‘ …*‡7½½½SJP™hû”N§PMzzzèîîfß¾}Õ.Ê„ m[a*!mÛ‰oÛ ÂD Ú¶{öì©vQ&iÛ S iÛ–×¶ííí”òK üñÿ~J •Š#Èø×¢q¦ŽÜŸW^²YWD±¬Âÿ•H® ’Jù‰ã#Wd±mw+wÿÒi_XQle¼ûLfä!™L†ï_þ}÷šm›ÇÏ~|è—ÂW™T.µLy˜|9ß³ü››É/OåopüýŸdÎöwCvþŸìùÖMøÿ6²å”-¸÷~òAúúúXx-G|€'OzS7É¥rh3Û¸hÆœ4ïïÌ\ðÛ¸v’œôC¶/Ø 3Ž<ø, ®]e™wïGùÅ›`vŽº¶eœøò—9iïO˜ý¿ÿ‰#þßÓÓôF¶Ínaï 'LÈó¥˜Ô_}}}\wÝuÜ|óÍÌŸ?¿`])Ã*ÇelÑ¢E¬]»v2/C<Ö®]˺uëª]Œq3œmÂØísåÊ•¬^½zTe zªŠ%‘p•{ÛvcK꺻̶»?Kò©ž444°víÚ)1‹´ö¹`Á©;…ª¡fµMÑ@Ú¶ÂTCÚ¶Ã3–¶­ LÒ¶•¶­^¤m;<“ݶulHèîØ’J³qn,Lܱÿ?ÛðD æW x$Žÿ¦ÃGMwÜið@^dQÞ&›˜H(n(¯DÂýnY® ‰¸ãWŽã.O&ýrNDØ®\.7X˜NÀ'ÞÁ+½Âê[Vk‹1ç›sè} —ûî¼<ò?Ö~ÿ†8ùÕŠ–KË/7óëZÕ lvm<™úß/Øp®wk0=³ Øf0»¥›Íóhøé_Ø3ýyp3÷læ–iâìŸÍêï®fÓ©WqâÆoòÀ oç¨?ÃÜM°ãð“>øžÅ-çqô¢'8ú‚£á4%Æ–p5,ÌQŸJQQìÎBGŸ4MxKNÐ8êÝïvÕ.€d×ãjâ‚}¹Lª‡J&“¡©©É›]ÑÛÛKww7ÝÝÝÔÕÕ Ú^fÂä0œm“bŸYÜw¹…û¾·²Rj¾®»ê¿R2WÕ 3ÌR³¡–ƒ} ‚PiÛ B8‘ºS‹ا „—°·mÿã'Ça€ÇhvÇ–¼1!v¥\ A%¨Äé9ß #ƒ'lØ $Suà7y‘av~R¯®»BÈ~Koîg:퇨ïêò' «`åâ8N‰ u‡D¿eÛ6_ùÍWÈård³Yn?ñvW=ÊB˦Þ´ýMô¿©Ÿös“ ¼`òìŸåô_œÎK O³íŸ¶±å[Øù—ô¡lèÙ÷GºÎìpoR¸$Q8ôô!\þ ‡ž>ÄÁ§òÒ¼:ê|†C]Ë ¯þ ü"Å¡ºCìÛó¿[úS=öjx(DZï:•¿}þiê·ýŽY]ÎSË~ÃW¾òQV?p#\í°âµN,àÍÿýß7ÅÝ_a— Ÿ‹‚fÁ‡ ÷Ó¶Á0H&“î!¸3®Áý1”2uWÒ]žLº*¤M.¼ã '=)}__·Ür àÞwÞIoo/---lذ¡`ÛÞÞÞÐ%6„©ÊP¶©âbVÊ>¸,|ÏÂLÆOä¥iî;1…ÆF÷ýi®úŸJ ­ê+‘=›à¾9»a²¨–} ‚02Ò¶„p"u§ „±OA/anÛÞ‚Ç^~Š[>±Ü[fáçáµóßqüɵ§ga‹ûlhHA΀e9Xª¹¢J–üØ{fD`§‡4øNúrPoB¯íŽ?%“ðÍŒë°E‡ÙqHæ'ÿª±þHdp”ÑæDI¥RèºN4¥ï}Øx€úT=¶m3}ët¶þÛV¶=»¦#š8î˜ã¸ëûwñæ%oæÁuòЫÑò“¾ˆ]íbͼ‹`þ4¼ÐÀ‚ °ÿáyôv>Äüƒóùÿ|댛9Ã8ƒ£ü'kÐûÍ•<ûÁgYò­8_‹Ù¼kç»øñq?æV¼—£¦ïC›qûûW9ïÀϘ³ì“Üu+__ñ Þÿ'.þõÙÿº×1cÿ¹ÿuõüðÏ&}`Ô=AÝ‘O»ª”¦Á÷5HDü™Ò¦éÞ$¥:†û—Ëù3¬ƒËA—Ÿ êÇȳè¹ElcbCÚNª RìâµfÍ®½öZÏ=N) ---twwÓÓÓÃe—]6™E„Ã’‘l³¥¥¥bö©„;ÿ¡À;ð“t¥Óx³"÷]<J@ÉRèõ"µF5íS„á‘¶­ „©;!¼ˆ} Bx {Ûöàë~Ä*p'ѪHð)Ü1 Åïy›ã0§3ðR6|Vƒ's°?§7¿Ì}ÅÌÄLÐà .1áëùdì[t8ZƒI×›ýÐ󧘰Ҁ¿¦ ®¾Ÿu óO¯nãQ–ŒÊe(ö<²‡·¯~;÷í~vÞ±“=3ØœÙ̱o8–Ï=ø9ræ¨o®çÈ3þ‹GÿùM4<ÒÀŒO®çœKÍw£u[°ü6æŒÃóáœõFî>ö\á\ÁŒ½»9Ðx/Ó_Ê7º÷qD×VØvŸøG^÷÷¿ó…›÷sNì–ü·Îœ½{Y¼i1ßÒ¿Å‹ï{;6í`ÎÆÛ9¡å z†‹.bÏÛÏãÚµoeþ?l„D‚—]“su´®ÃÎ\aÉþ¼@¢0MWPQÈÇ‹ w¿ãniœÐgqÒ=T†cíÚµ\wÝu¬X±‚M›6±víÚ’15A˜|*eŸ*¯•…ë©¢FÄ÷à RìRünUµ¯M|¡F¦2R B8Û„ð"ö)áEìSÂIµmóÀ£sØõæ}ÄðE+ÿ§á‡÷âñÌ·Žc °3¿i¾}Ó[Î`›5g{ˆy-'±7{2«L¸$êNàMuÀK|Í‚FÀJÁAÜI½Ù,ì2áz-Ð5ø{“KFA) ÊþÇïù1ïXÿ4[ãý»ÞÏÏ?ôs®Þw5Äà¬ÿsæË&?ÿ8s¯™Ë\m.ú×uæø:§¾r³.¾œ9ߊ3pÌl´¸×ç gÃ5À·5´ÏD¸Â²`Ï\ˆÇÙ¹íN½úJøÑù|íWâê÷¬à _ù$ß{ðAþŸ38åŸÿ™m—_·öìAÏ'†Y¸|9 |N^@û’%DÎ>€¹¿½Æ½-èiðsåE¢êÃuU˜Ó>m&ô˜UTÖ¯__ð}õêÕ´´´ÐÓÓCCCƒ¸t B•(¶M¨œ}ª¼W:Ä7™È–TŠQ!¿lÛ)à8®÷`{»¿ž?~*5|ÎA¨&Ó>AÒ¶„p"u§ „±OA/akÛ8p€ošÃQ¸Z¸cJ*2É6\þËmÜþøYÌËÀñü<é䦛š¨ûû+À<þú׿žÐÍ ÚÉ,Ä3RÉã#гIÂ~´ƒ£Ï]„®Oã¬,ŠÃUÀ™šÅ;7mâ„äÕ˜¹M1QÊý_»Ÿ?9ÀÊVº 2¸aZ€s;Îå–½…ýícÔ[Ç?úæ?6­CãééOs„q§;§ƒ ¦eºúÍÂå•ÛÇlí˜Ó‹mÁEÀÙ¦{lÝpgçr@’IÞ î@Ú‡M>;Ë¡gýzöýüçlzì1–,\È)šÆ’+\q$óãð[8Ñ®®Á×ÑAX©ù_å •¥ „—JاŽ?³Ü l´.’™Œ[äsU•IJÜÙE¡aÊ õ§ „±MA/bŸ‚^Ä>!œL–mª”ìZpáò>6ëxÎúº¿^aû3päã¯9Þ€‰e¹¹x—-;ÄìÙÝ̘ÑÃÉK~Í?|ø[Üxã1Ìœ9Ÿ¾¹îX‘KŠD\ÁÎ'›¿é¦¯pÂ×¾LçÉ Ø›uµ •~‡msõ>à 6ýè±Çøðg”¾ œ4ÿ$lÛnúðM|üùóôåOóèÞGYuÄ*>²÷#Ôß_Ïö«¶3ÿ7óùãÿÈEÎEœ²úwð,…['ÿ¹KcöîÂ=¸Ibl š›¡«Ë½ˆT"?f¸3ŒÛÚüò´µ¹Ûi ޶MZ…YºÔ<Ëåü›bÑd²9¢Úáð¥T(.]/Ï;Å;†íî“N»û©¼+–åoóxÖßVAAAA/)ò æóض ÷׳{útrõî8O á'–Í‚;wY–ÌÚÆþýw°eË<þøã{ì+Üwß·xê©™3g/Gù' (-ÁM*ocšn”¿üåÇl=k.?Ðà©(@&“!•Jñ‰c—³èûß'—Ëñ–ççñ|¿{6ÜØöà. d`ë÷¶²²o%´Á¥G^Êœ½s8ëñ³xÏ ïaçÞÇ9þÇsÛÊÛ8úΣ¹oé}\ôž‹\ñÄÉäg#Ûp\Î fäØ÷ãoÂv¶äÀÚì JÑ4÷Oå-Ñ´Òƒb†áÞ€à Z4êïßÞî~Ö0 v-˜ðc†ÎCE„÷2 ’Éøïó‘0 ß3%u¿·¶ºëÇWžÒà¡ Üwë%À‚ ‚ ‚ ‚ áǶmؽ˜=oœo„z ìÌOÁ|௽ˆ£Ž:Ž{î™ÃC]ÀùçßÄöí'00°™ ¦OïömöìYI}ýψF?E*Ùl3ŸÓ£µµ•ŽŽ,ËÁp ¶8¯òÒqupùá/ˆD"\²ð.ûãe¬Ø¸‚ºêŸØ¾ý °â~·°*Yp ^n|™ÞczYª-eé‹KùÓ¬?ñfëÍ,µç¸Ú iºgw³xïG€_bê&»î‹òRÓè¿ Žs “ÍöCpé:¯ußyé%VmÜHÃw‚æè:[o»§Ó4é»òJ>£¼O‚&ºî‡q‰D •)ÆŽ%;&ü˜£òPéììdÆ Þ÷îînÖ¬YÚ5kX·n]µï S„rÅo]w· ¾÷վɤ[7܃S¢~®«l¶ÚW'‚ ‚ ‚ ‚ ‡…«(¦ížáæ± .8QÖ487ïœñþ£pÿýõÔÕ=ÍYg]È–-GpãËùÙÏ–sÖYóàƒ·qÁýœvÚ ÇâŒ3¾N&C׳¤R)Û!›Í’ËåøÇ™ÿÈìíý$Èð ½€k Çâ€IDATæ^êU«˜ó®9l67sõŽ«é™ÞÃî?Îp… ×£$o=ÈÒÿµ”þÅýlÛ÷K:ò2>öÖqëü[Ñ^Èpבw‘~š9 ¶³yÞ.¾·õ{Ì›÷$ç=ð¸­î%Ì_›ð÷¼è0ïÅywìfž:q!ý_èç¾Ëîã¢ØEì[²W_x•Gg=Êsïäý3ðÖYgçøÏ9ï¥÷‚·sߊûH' –E;÷óøYsÌkGpÿ3Gò›×^ãŒ-[¸}ÉžzñE.îêB3M>ÚÝÍÅ=DÓG>B6—sÅ“Fs3ä…íê«K{Ÿ ¼Åb14MCÓ423ÇqÐuD"mÛ8ŽC{{;ZH€©9ÓÃ¥b>íáÓ&<)}Y*ÝÝÝÜyçÜvÛm¬]»€7RWWÇÍ7ßÌÚµkY¿~½'ª‚ ‡ƒëRåÑ 2š\¹œëq|G£~ÈHÓ„ï'ýu¦é†AAAA‰º™¶æþøÇ^~¹ž£Þäzeœ¨Á‚¼ÈÛý|ÖÖ©«{š_\Å+ϲmÛ6fÌ8åGN礸KAòBøìgÏðăˆáߟüwr¹ñxœãfÇWßÿU¾ºà«<ý™§i|ø§Ðèâü»ÏgþSó¡°`úƒÓ¹ôÞ/qÄQGpסWxöžàóÛ>ÏÏŽøÛÎû~»þo-æøY³øÆ¾}ÌzýŸ¨{Óëùì‚]H€iMäS¹Y°€y„×:Ä#§ŸÎ ùïjj"ÚÑÁÍÝݼïÛßæ´~L&C4¥«« ]×ioo'N“N§Ñud2‰¦iضM*•$¾är9r¹Ùl–l6KWW¦ibš&ñxœŽ|¨°h4Ša¾ÇËP¿ãH$J®knn&—Ëá8¹\Î å6©TjØíÊñR™hÊòP¹óÎ;iii¡©©É[ÖÙÙÉ¥—^Êüùóhhh ¡¡žž&ù2A¨%,\AEŠQÚÛË?N$©”/ ”ƒ*‚ ‚ ‚ ‚ ág`ýq|ùügxêÂ9~ÅAz30߀¥9øk`Û×z^ã”ãz‰?¡³€–Î{Æ6Øú³üð·“ŸÀ›wÑuÃ0À‚ú—ëùÆ’oð)>=pþžóá1˜óõ9\pÿîlà ìž±~ ´ÂÃÇ=ÌEÑ‹8ôC8sr÷›ñ·³ö²ñŸf“úSŠ[êo!ÖÜ̧båæt]ç±iÓxÝcÁÁƒn¬ú\ÎØêèpã›e³¢[¦i2MÓhWÞ$Iwư¦iðž÷p4N§‰æ×·Ô”˜`±X ]×±,‹x<îm×ÚÚŠ¦i´··cY†a iš›s%€:–eYXù²QáÁ"‘±XŒl6ëícÛ¶÷®€‹Å0 £ œÁcµµµ‘L&½Ðkš¦y×Y°mþ¯Ø”ò›¹ûwÓ¨± ¢ì_Å"Igg'«W¯.X¦ÄA„‘ppåŒbÛ®¢e¹¡¹ÊÁ0```tçM§]Q%$Þ‰‚ ‚ ‚ ‚ ÂlÙ·]OÏ`îÃGsúé0Ï8‹§,8Ú†eËáôíá¤Y,:êLŒÐ_€V1=úpp¢l lvE”¶æ6oý{Oz¯û¨2`çŽÔSïncÓKžd¹µœ»¯¿›'þò‹þ²ˆ»¹›yÇ ðÜÉ39z÷AÚnÒiùú/yúOsðÛ߆ÛnCχb9ãÃv¾”§ˆiú‰b¢Qwp,%ªD‹¯¢eÆÌ·,‹öööAùP,Ëb×®]îå–1g©TŠ\.—/¾é‰)‰D‚H$B4%›ObœH$Ð4 ÇqH§Ó´¶¶ÇI&“466zÂJ*•"‰H$ˆF£žpÇI¥RD£Qï<š¦¹ž2¦‰‰ŸºÆ,Qæ ï¸Ý'‰{&ËTêêê¸óÎ;½ï7n ¥Å/I__ÝÝÝÔÕÕM\éA˜²Ä cI,æ £ñ6 Ù¬;#!QEAAA!Œìر8žg=9½sÙÙ0›9{çÀÑûÙµl+o¿t&[þxGí9›·{G Éà¯pƬ3\$‰›`#F¡°’‚÷o~?s_› çQ81s"ìÚóÛðÄmÿɶSÎÆ|[rpûôÛÙð« ì=a/fÄänî¦åøã9ê¦g8êå—ùoº‰Ç.¾˜M×\ÃZÛæ{øÃàP)†Q˜×$q·1 7l‹¦)7~D"/?J1åˆ(ALÓ¤µµ•t:až8ǽãëºN&“ñ¼P”·K.—Ã4Mt]÷„ ]׉å¥h4J.—£½½}P¹r¹ž0£®§ëÜs±êëÉà *pëSOñàòåä€ÿçÒ^.aú„ÝO(SP¹ôÒKÉd2Üpà ´´´ÉdhiiñË©uuD¾þuž3‡ì¢EDÇC³ma€’é¶ÂùîÃ)¯zÁó×0Œâ?÷îå…²2 uáÂ.·W[[ë§ü’Ñ-ÅÄãq_<‘È} ¶“©È:жinn.H+"ºæƒo½…>i&ð¿ûöqc:ÍÿüǰãObÚ /0ôÍ7ùõy‹©Z³¹G¯i§ŠÒWTTpçwRWWÇ 7ÜÀ„ üâôuuu¼ç=ï¡®®ŽÛo¿½G;§P('.˜â8BàðDø^‰±Bï !Üxщd³":&}±¬nB¡P( …B¡P( …BÑMŠË˜}ç!¨L¨¨»·ìçÔSobçÎìŸ1ƒ-[fðÔðwóõò¿à< n%…!ö‘Åõ^–÷Šá§îÂñÖ™bD‘ßœ÷×[þåWîåÔÝ»Aƒ—w_Á9eeüå¿þ‹©O<55$¼ôVº®3Û²8õsŸàvüx2ååd¯¹†ô­·Šˆ”p¡ö>òêu),Ø>òÔSùU!÷âú)í¡w"Ê&bF§R—i†â ¾+†a0|çN@Ø—‚qgŒëÑëÚé*óæÍóó£…™?>+W®,Hÿ¥P(GBê&–%ÄøÞL¿U|›’¿é‘ˆWG¤«ªé+û"õ˜B¡P( …B¡P( …B`#t i}nøë&F­ŸÂühf6Âm£`ölŽ­eÜî_¿åßq\è5"…!–äC°b‰Ol n²¡ÎxT–~éK¬¿ãîºí6¦í}…·Ö¯gìå—óÅHÆŽÛFó Hso½Uœ¼—aÛÔþìgT­\‰ö±aüío¸¦¿ï)òÛ—^´,í]Џ÷·îÛßæó7òŽÓOgyK C*{¶X{oá‘Ðÿ:B±k lŒ ››ÙòÚkŒX»Ö¯ãðgãÏì;i_ö§Ó‚J{”——+1E¡P½-^”Òjr¹ E׃¨ËD"¨¦D…B¡P( …B¡P(оAfè" /?4„O›±Œv¶oß@ÙÐy\tv¤+Ð><€Ldú®ð«Ñk<‰Hù%k³Þö&¾7îÆ¯·?ýiÇáW_eá®]|ò?ÿ“³g×4Æu–0$¹®ðÎõŒG~Z-é1lh?þ±€™4 ëg?º'¨ä½.–²oÙø%_°½SÍzûäÄ¥$‹U–üò—œ»p!æé§óÚÆÔžrJ¿~ÞÁE|\ÄG¨y×¢þ£Á¹çpæªUâúf2%ëÅô$TšššX±bMMM”——ÇU½…BÑ-l‚H: ˆìëq4­­`"EÓјJPQ( …B¡P( …B¡è;lVt`âóÔÍžþqP,{ߎ÷ñ{`䨩xv(ìB):µ]Gˆ'BU(Î'ÖXâÀž ~Û÷¿Ïº±cYôñsþ}|K×¹ôÅÖÒ„Y³ùá !EÖ>©¬„LF“Ú´©áWH)/§»ñ áH“ð2Í;µ8B@Ñ*ïÔzëœ $C5OÆ<Ø›c—‘bZ”@òüýþ‡ÉU›6ùÿ»®Û¦nKoÑ©*K—.¥®®ŽyóæÑÔÔÄ5×\CSSS¯wP¡P Nd®^»E4*îƒÅ‘25˜m‹—$™Û&“b¹e®W( …B¡P( …B¡P”Ffèr²0l솽"Œ2¾Ýh#Lo˜ÎIO`ÎÎa ™>D(A”‰´§'¼e2´CÖIÑ¡éñÇYsá…b;Ç)¨o2ÌNÚ·d2ÉÔ×^ãî†6_r {öìá¡Å‹…W°a¯.¶t|­¨]œÛ8¥Ò[—F)2[Y ¡ÉàùW3,F8ŽÀøC‡Ø2cF¯~®I:_«%ë›ÜGF¥Ô#>ÊRôv$J{tJP©««£©©‰ûî»eË–qß}÷1aÂVy¡4 …BÑ]2™þîAiÒiqO —ŽJ§EûXL¼¼{Ñ(Ô׋íkjÄ}8ŸöI§…À"·W( …B¡P( …B¡Pˆà’4B4xÌò0ÂqyûÕyûÅ1Á†{á¤Í'1î(0ž˜æ2‚âát(P˜K -Q±|Üg »B¶Xý»ß±fÍlÛ¦ªªŠßýë¼üòË|òùç)++cÆŒ¤]—OœxbýJm›fP¬÷Q$ÙÎza.çb…NKóN×Á/óRP7Ø@í¡ëº/¨l¼ï>†É«dÙ™žFÖÅ)Æ¥­Ðb!„!Ý;Ç mk"wx,Ûî“èèBʯêêjÊËËýÿ/”*^7hhh`ÇŽL˜0¡MÚ°¦¦&ššš¨¨¨ ¢¢¢O.‚B¡t46¡çƧüÑ´,!Pär½{^0¡Öwö§µ¶Vˆ"Ù¬èg*«·m!¥Ób®‹ÿ ±^ÓĶ ÚÂŒ®Ž Ù¬øë8bÛΦ=sÑŽü«8~è«ñ©P(ºŽšÛ*uïT(.j|*—þœÛn÷Šdz¡ €‰‹†ÂŽdÇ·ëè§ÔH‘U×Û³ÀËí<òù<ŸzöY6oÞÌykÖðdÓ4Yôñ£ë×°wï^{åž}öÙÒaq¥ñ`ÐZ. ¯§¼õ ÒxÕ Ä… ø$}“;q¼0aA`ȤI¤ j´tíLÚÇ!ˆ´)Ö¹ ˆB1ŠŽ)£kR”®S ˲0½tkNPé)nºé&êêꨨ¨ ©©‰êêjn¾ùfV­ZÅòåË™?>k×®eÙ²e,Y²¤¯»¨P—t46¡gÇgøç­/~ëd®<í‡ –BŠ#2JÅ4 …DBˆ"á4™ò|b1qO5M±ëŠe55âÿtZI±˜ˆnI&ƒ{°m‹í¢Ms3D"¨“Ï‹ý:‹túK„q]q^]Œ†UxôåøT(]CÍmЉºw*5>ŠKÍm¥‰¢ïÕáŸkâ˜#£' 6ÌÝùâ„ ÐF†#{Ï…Û躎«ë ½ñFÆß{/c·nåòSOå½Ò0ãºâeÌniáŠ+®è‘ôRÒ&¥!„YæÅôÞg¼÷Y„à"âDv]f0ëI‚Ki#lg2[ÞÛ®3å†-o{)š„‰yç\ﳌ¸ Ûë:{¥ à ŸÏãºnPÔÛô© ÒÐÐÀC=Äc=Fyy9MMM˜¦É’%K˜7oË—/çöÛo§ººš††®¸â ª««•7‚BÑËil=6>-‚Ó¾LG„MJÇ…Îb‘Ï·$1Û¹“ÉÈÓ‚¦ Ķ…x"#UZ[Åö²þŠaˆ¿R¬‰ÇÅñ“I±L/ŸíËû¹ë ÑD¦ý”)ÈdÛŽ\ïÚZqŒXL´-…#]Úw±¬ªJ,Ëd‚ˆ"]ÇO$Ä6Ѩ~¢Q!úhšèw<.–Ëþ¹®Šr9цm5idôŽiiÒâqÑV¢+*Ø ¤/ǧB¡èjn«P LÔ½S¡¸¨ñ©P \úsn+“}.¬ÉÂÐ}“ ,ìÒô™áîæQP†°Ö›´µðg³m7šwÇ]gÄ7¿ÉÄÆF†lßÎ9ûö±aɦ?öXàÝšJù^¯H&‰w6­È &BTÑâC¸ðºN:Ÿi¥;üüé§ýèŽJ¯?Q‚Ꙙ‘,ò<²Þ>ñ¢BF¨Ès·å"Ÿ!m²tÍVF *}YO¥ÓEé×®]ËÒ¥Ký×Ã?ÌÃ?\°léÒ¥¶ÑÔÔÄ’%KüÔarÀíØ±ƒºº:&L˜@uu5óæÍcÞ¼yÔÕÕuØæ®]»Ž¸BÑ[ÔÕÕ±iÓ¦þîÆQÓÑØ”çÙñ¹iÓ&üÿ-ï%âGˆ=ã8*Ò"¿d¾K­ ƒ~6¤ðê,ºD¶8ŽC>ŸÇq CÅ"Œ:±,q]¢Þ]HF¸È¾HL&M j³Äbâ}.'Ä”tZˆRÐÈdÄrÓÛ˜_ärÁ±åòª*1‡°mhl %Ëû§R¢-ÃbŒ¢‘¢Q.>žC©”èC&Ô˜±¬ þL<.Ž)ÏM Bޤ]s]¨¬/y\¹ˆídßï¾{/<ò4ûöíë™/X?Òãsß¾}~}4…¢¯ijjâ…^àÀýÝ•95·U &Ôܶks[…¢¯hii¡®®Ž]»võwWŽ5·U 6ÔܶssÛ–––·“–œ—òBTÀ†ÓÃ6£fXؼÓ^ rºRʦ$ !ÅØ¶0xüö#áFŒàé výõl=÷ÜÀó3D*•êc½‰¤x6¥¼e=#ã_Û¶ÉçóçõŽ› °¾‰¬m"û^—F¤Ó(¬ûb{Ë Ägk!¢Q’”Îs4çFÉårÔ—HãÒÐÐÐ+sÛNE¨L˜0ùóç,ëŽúxá…rá…ÒÒÒÂÚµk©««cÞ¼yTWW³bÅŠ6mN˜0áˆ7ÄÝ»wSWWçh…¢/,M?@ÝŸ›6mbíÚµ¾§‘Ìõ( gÉ„£Åu]*++‰ÇãhšFªü•:ÁMZ†,vFÏ±í ŠÂ¶mÿ†SUUEÔS>2™Œ¿}>ŸgãÎ YϺußçÏ^îo¼MߤôöÛålß~"¶=±Íñ5 â©B¯„Tªmú±p´ÌQÐ H´‹)#R¤XR[+Ä‹I“D»ánjZ ¶Èí5-J²Y!”ÈÏR®³í¶Ÿ±iŠãȺ4²=ÓBŒë ±$— „$)ɨ—°UY)þ&“¢­ÚZq¼Ï~ö ÿüçh¦M;ö•ÞŸò¡Syú)úƒ¦¦& j󫨹­b°¡æ¶]›Û*}…4fîÞ½»¿»rÔ¨¹­b°¡æ¶›ÛVTT´{Â…ËÇV¤âÛϰpõ î?u%£eŽYÀébý݈•v :›Fb†üG°5 þñÝïRñÆÌH¥˜±e ›/¹„wTT`¬[Ljŋ©X¼Xú(ÒA¦úêé^a–eQSSC"‘Ày9‡­UR‘v4iZÒƒä_ÝÛ·2´¿ŒNÁÛ7‚MŒ>_i“kµk×öŸ 2oÞ_p3(ÞÆ0 ¦SVF„ Ì0 ¼¾w/++Ã>´};W=ù$›îº #—c«×ÆsÏ=N$ò4MÃu]¢Ñ(®ëbÛ>ï8Éd’7Ì£ùìÓØXsÍÍ;èó‹§ŸfÂ#pÁ}÷ñÃ}ˆd2‰ã8Ì›wÛ·_ëNô…Û¶ÑuÿÝ·«¦O'¸É$‰DMÓ|aBÞëÂÊ6’FÛ›•8\·m=]/L&‘éĤ@& ¢iJQê3–ÂH1ù¼8‡p*3Ù/]/ŒÜ‘äròZŠ7?ÿy9••gP^>x ’=9>'Nœ¨îŠ~CLS†šÛ* jnÛ1¥æ¶ E_PQQÁ²eËU„”šÛ* jnÛ1™Û†‚¼¾ÿE^¤œa¯þ&Ê †ƒñ„õ~p íVPoii i”H&y÷¡CìhiH„»v±¦¥…¿ê*ZÃ^›aÏÏAˆ¦i~DGGˆ´ù) ë Èú.I‚È•ð>IÄG¶EE½W%¨)ìçÒÞ,Y²¤W¢»\C¥©©© ”²¢¢‚‹.º¨KJ¬hZ¼¢>L˜0¡ä±¢÷O>Ÿ?¢¦P‹”›K–,é±ñi#~l5 o]º/Ùa¶mû‘ù¢ÐÌ´ê™L&‰F£4^|1ó?ô!¾xà˜9“¯·´0÷Ùg±o¾™3û[öïßϘ_$S_ÏØ9sxpëVö?u†1œ_ü"?üa ÇqÐuH,†>q"³V­¢ªª Ã00 ƒh4ÊO —÷M}—]ˆ›V<çî×_çàoð»íÛ™ÍbÛ6®—OlذÓqœYüæ7?%þƒ/Ô¸ì2f|å+ÜñÜsìÈf}á(‘ÈùuW¤˜’N§‰F£<0f N<kØ0á9`Û8ŽƒmG1Í ™xoù93KÍ £mDÉ‘)Ϻš*ÍqD´K1íÝë“É@°)î[m-|úÓc»ÿ%`ôöøT(ÝçXŸÛ*ƒuïT(.j|*—þœÛ6þÏfŒ>…3ö³A.tðá§íes^?ž¹áe–ù¡ÒÇS)fy&¶neZu5Ùl–ªXŒÉ\€ã8<ûìY˜&üõ¯·‘J¥hll$‘Hð±ü€û÷sÊ)§ÐØØèŸg>Ÿäk_[Ãüù/’LVQYYéŸ÷ý÷ßÏ¿~ö3üqlÛ&‹‘N§¹ýöÛyâ‰çÙ¾};ù|’I“&‹Å¨©©á¼‡¢šéº.Éd’d2I:äùçwÔ+!^Éâ_Ùl–X,F2™Ä²,¢Qñù¾õÖajjj°<§£:7²(}OýÄê:ÌšõLÏ4ÖôåøT(]ãXžÛ*ƒuïT(.j|*—0·¶}'½g(çœS,´€f`1B\™ƒHùUxnÊ” o¹GËäÉl™1ƒ‘+Wòì³Ïòâ˜1ÙF…Ä]r *"Ú$C¬xŸzú6YÐiAeùòå¬ZµŠ›o¾™gžy†•+W²råJžyæâñ8Ë—/ï´¨" µ´´øù1«««ý¼  òf655qÑEõ÷5ð=ác±X»Æ@…âX¦½± ôèø”™œòùî ÿétÚ7ЃŸ²®‰®ë$“Ib± Âÿ2™ µµµd2²±·ÎK>ŸG÷:ÐÜÜL*•¢¾¶–;¾ò.;÷\,@×4>_]Íþ¹£°mx{Ú(ª€B ‘ù$'ÌšE*•bÄ~DÖ4ÑuñãdzæÏføYg‘F(ø6кp!Í™ SO=Çqøõ 7°éóŸÇqfÍZÏk¯=/úe¤5x"Á´iÓøÀ‚,X°MÓH$$ Çá‚ N oö˜ÚÚZZ[[‰ÔÔpõÕWóÂæÍÄb1r¹¹\Ž ðòËã9ûì.¹¤Œææfq]—--ŒÝº‡ ²GÓ4 {ìÖ­{ÚûìòTUU‘ÍfI§ÓTUUá8޹—N§yà=aÄñÓ ÕÔÔPUUEUUU0-Å›sιŠóÎ;è¥÷r°,«SÛî³§ýF_O…BÑuŽÕ¹­B1ØQ÷N…bà¢Æ§B1psÛ™¥¬ñ-Àã+þBDM•hšÆ»Z[Ù÷ë_sxâDvÉ_7mâ‘§…=cÜå—óò;ßÉûgÌ « DG J`Ç“)¾e°E£”¢S)¿X±b÷Ýw_›P®òòr®»î:²Ù¬ÿ¾K–,áá‡öÃÅÖ®]ËE]äç¡]¶l7ÜpóçÏgíÚµ,[¶lÀu²m›ÆÆF¯nƒmÛGÌÓ¦P+ilBÏÏ|¾°ðy{ÈT]áñ&ñr™²¦ëºî×S©¯¯÷—( /÷K&“är9]¸=!~$€èüùÜñ‹2¦}|C/Ýï‡5Êb[Q„³ÀÆE‹`óft]§©µl›CŸùŒ_ÀËFŽÃ®#Xð0rÿ~ž›5 €Å‹âÜsM0È{íš =tp¢QrÑ(ç÷ž}¶Ó‚EÃÒ2'òHU•çôÎmæÌ?3yààeÕ4\.‡ÑÜÌÞ†þ¼oŸýäµ7ïIî¾»I“.$’Éd0 ÃOW&·‹F£D"®¼ò44­•SNÙD"‘ðëÁd2lÛ&N“õÒ—I1æ†æqë­ÿâÅŸ¥¦æ.¿Xš¦i˜¦I"”×Ôu]b±ë×_‹ë.ñŠÝ‹Tl–eyQ2ƒcbÔãS¡PtŽcyn«P fÔ½S¡¸¨ñ©P \úkn»Å†16ì‰ÃðáÙeB©£$š LC„FF;*¶móèúõ\x≌ݿŸß~ä#œyã4Ÿt/WT0øæÊ•At…¢tJP©««£ºººÃ¼x×]wË—/÷·m•+WÒÐÐà‡……CÖ,YBuu5MMMmÖõ‘H„T*ÕF(‘F:€T*E2™ôˆ Å`¡£± =;>KDo¡ ë–eÇ1 £ ŠBbš¦/tDmmm˜RŒ†V Ã`èŒmXÖ~ö~t®¶GÜÜ¥ZŸÎ)+ã™Ã‡qÊ!Cx}út&Ìš…åmŸZßõ..\À—†òrönÝÊTÓ,ø]± òO:‘DÞî¥p’þò—÷’ö‚8²Þ¶VèfÏžD¼ó3z/š¶—Í›Åì#é«2iûx€Ÿ¿ë]ä3™‚ëzå•góoÿv®k\7­DhHmm-‘H„L²Ù‡€B1Ä0 t]/Yd›ŽSƒã8Ôz…Q\×Ŷm_X“Û¥Ói Ãàÿ¸]_—¾´•t:⯗…Çw¹TØ€¤/ǧB¡èyn«PϨ{§B1pQãS¡¸ôÇÜvŸ S»z;îM{€Úd¡Ð`ŠxoR”Rʲüâós÷ìáºóÏgüš5p ̺öZrñ8W~ë[Ì¿ôR¯1ýèrÐ+Ž{:eiÚ±cG§ëHH Ó‘0ÓŸ7KY´¹XP)ŽFÑ4ͯ“ P &ŽTL¬§Æ§mw^Pq‘2*•JaYétšT*E<'ŸÏcYV¿³Q GŠ03‡|ïmX{&¾Ë_EˆRô°Q$ÚìÙØ1£ööÛ‰óJûÊʈ ‚ ¼>}:§NʧŸ^s/ª8Á$,Žø×/ôÞ’†lìÐ>vh[Y0, DFïeúô@PÉ{ý“‰ ‡µ´0kÖ,0M*½ó”Dš¦‰èŸÐ5ˆ…ŽÛv:Ò~zD)xG eŠ*ÒËè”h4êG´†ã8Ô××sï½ßÇq`çάX‘)ø]N¥R,]º´S߇c¾Ÿ …¢ë Ô¹­Bq¼£î ÅÀEO…bàÒ×sÛŒš¾0ŠòïÙ ïBÆ[ÛiÀ²Àq ›eïªU¼:~<“ vþÇ0û„˜±u+´´ Pôª¡2a„N‰*2Þ±ˆã8¾'´eY~}¹,l|•in’É$‘H¤Ð«\4R(ÚÅ4?UIÂÅÕu]'úi¾‰DhâºnÉ(‰£¥!4 }ê<0ƒò!Ûýõ:~¤):B¬0‡”4MÃ$àíòrR©AJ/3C¤ß’Q:Aê1ù«"iÂ˲ÞviÈ!ƒd¦÷~ÓÛ3Y½zëצñÔSýå–×÷Å‹S¾`iïüòa¶BD’5a"^Ÿj½åUÀ$ïï‹?ù‰H¨ë$.$âm_åý}þÔS¡¾ž/^z)Yo™F­¦i’Íf‰F£Ø¶ÍÛååä½§Ÿ‹eÁŒ7³¹¬ …B¡P( …B¡P(ÇïFíØ{öôÂÛ„˜2áÈíÌÞ°E×_Ï´‹/ÓdÖáÌڳ‡¹ŸúTŸ¢bÑ)Aå /¤¡¡¡CÁdùòå~‘¢c ×uÉçó˜^Ê˲0M˲üüþÅu¤ˆ"|’X,FUU•/Ì(Šiäw]è(ÀËqÒé´1–J¥ü±hšAÊ)]×ÉçóG>ðQ²gÆ‹œ_ó SNÚ\°<ú[O h„eÕ™"|þÔDÑBFØëE¬üéCò—‡Å!<Ètdò}ÆÛ?,ŽèEÇ4¼e[<áfä’ ¼«ôÏÁò¶Y±d »§NÅõÚˤ³ ”"*%ãµ[뽚½uo{yT×O˜ÀÒƒýõõÞõ:púéPSãF‘'ˆ”i)j?ÿÍo²í©§ØžÍb»ÿÏ;q]X{ÂW¹é}ï#‰B¡P( …B¡Pt ñLå8Éÿ Eï³Î†s®«e÷È‘b4µî£ÐÈ"‘Q)’‘éÞ{ï%™Lrßœ9`èªlƒ¢‡éTÊ¯ŠŠ ®»î:n¸áâñ8K–,ñ‹µ´´ÍfY±b·ß~{ŸO·ˆÅb€ð|O§Ó¸®Kmm­_ôØuÝ6)¿dZ×u©¬¬ô ¿²~C$Á4M•L¡!ãH,KÜëJ¥ý’Q^¶m“J¥ü1¤ë:®ëŒ)MÓ|‘¥7™4iãÞ_Çð‘퇽Ê_ ÅV1áª.)o!¸8À£_Ì–7Þ`õ¤I<ÚG+j»å‘GÐj»¹è8xðých™{ˆçžx¿pŸÃ`:®×žìŸLá%÷‘ý³½óÔBëŠÏ_ösôÞ½ì1)ÍÂD½—ûéÆ Žü°ÒÜÜLð‡æfÆíØühÎd´§àЮq¬:”¤×NÏÇ,) …B¡P(Šc4ÂN+£ìï%3È(|ùL!í¸òÙËèâñ Å‘94á-¶n=ÄsÉ(|Á{žw@ßëmÎ*Ú)lX’6!ÏÈtíµ×Ò0=ér„» EWétµÞeË–Ífýh”;vÐÒÒBEE·ß~;^xaŸO—‘Æ[Y9Nûudî~Çi¿€¦i477SSSC:¦¶¶MÓÐuÝ/˜­P( ±íÒõ¿d½!.d.×cYV›º½ÁKgœÁ…(pÞa@¢‡þ¦€ììÙŒ?tˆÅo¼î‰ÖÅv)bÈãtE80¦3gñÒåc9á7˜þ‘½ëå±4ÚPèdéFïÝËËãÇÖ-ín÷¾òá¥31}°¸¢¼œ­cž}•túTÆ¥axmEEµ]¸6 …B¡P( …bp‘¥­£›K2„HR¼ŒÖ×CÿÇQÑ* Eo1rÚJÙ”&v2GØ# Ð7EäOí亢}&ÃÚ={x@Óˆš&™… ùðøñÔÔÔ“BJ'kí*¥S)¿$Ë–-ã±ÇóÅ“%K–°råJ,ËbÞ¼y,_¾¼¿Ï§ÓÈš)2½—¤¶¶ÖW@5ÎuBÉÌd2466¢ë:š¦Ç}z™RL¡PR© :%‹ùBI6›%‹ašf›¢ñáT{]×ý±Ö›”¯[ÇöI“˜¾wo§¶ïN¼Œ”——³qÑ">3{v»Û…Ï´;ÞQ2~ÇΘõLAu Ó„·ít®yŸ‰Íͬ^½šƒãÆqÛpA{ñp3‰¶K)ÁeÒYé­µiºhˆÈ×kSýê* …B¡P(Ç'IïUŒŒFi/åpñ,!#ó;®Š€W(z ¼µá„Â…6°´{¿Î¬ãˆ½¶ÍIO>é§Ž¯¬©áŒÅ‹‰F£½RoW¡€. * ~^x!Ë–-cÙ²e~Í”¦¦&V¬XÑßçÓiÒé4ÙlÛ¶»œ.¨”6R*ˆÅ0 "‘UUU$“IÒé4¶mûBŽmÛ~ˆNžÒÞ.3Z:c¨…øM”ï‹Ûì(G©[Ô^gŽéíçvaEïáeÙDÚ<9ÇAÓ4 ྾¾Í~Å"K<ï“耷&Làä;;µmwÃÀOÿÎw˜´zu»û›F¨tG¸ùòúõŒoii³<Í‘£­p#S~uVºš9s&oŒwÄ}d½™þKz•¢Ôò]#FÐÜÜì¯oD…â+ …B¡P(Ç+y„½Á¤mémÝ{žR(=Ïþ×G3uÑŸ9pà@°ÐF¢÷2wÅ êÓúh8-7’H$0 ÃO oÛv¯;ß*Ž_:òk°QX4Þ ¦ £ýº "É4 ÒiH$Äöº.–ÕÔ^÷RM¥‚x4×uI§Ó¾¨F±mÛ7 ÇKå? ä <;dak&'iÄdEó¶~+i[Û½—a¶2G©îK-‡ÀØÆFÄ6)Ì}ÞG¦E 3ŒC`Ä•}Ô¼—:ŽütdM¯]pfΤº?¢c‚ptAxŒ…S{¹®K&“i#œ˜¦é§èëk–üóŸ¤?þqÎhlìÔöÝ &-Û¼™¡_û,YRr}8Zw!£lžzê<`µ¿<<¾Š}8Âÿwu:RVVÖé}äqÂùŠô#S‹ +ŠêѽýßÑÍë¤P( …B¡P(ŽM’‡±,#§|®Ïþ)º'¨X–°ùÈä òÿhTØŠ@¤·ÎçEªki2”Ç—BQ’Jà¤O4±á{³™pò3¼A¨vm°¸¶Ä޵µ`Y<ñÄœôè£ìp]t]÷_}å|«8>9n€h4J4%™77y#,%¨äó" EÖ~°,±Ìuƒ}Ói±¿eA±ÝUÓ´EbYVHØ /O4õ=÷-Ëê1Ñ%I¡§{)„A3‹Ij „ Û{/×5LRj½÷YA£'J?Iá£xY„@ä {؇šÎb‡ÎÛñÎAeÆÞâZëf΄C‡zà,?Á8+&™Lâ8Ñvr[ÊšFýÖwÃè´wCwçʆa´{þ=ÉâűjÕµ]Ú§«ù‚Ç:ÄÚ9sÞ‰º3Å8SþÖt¤;±¹ÆgìÖ­àÕ1N]” ¢P( …B¡POHgJá„–ô–å½—|VkϺ"Í3†!l<¶-ì>.üÝ€‘®O "ál Â^”ɶ£TJ´‰6$ÇûÖÔ@}}éçb…âxÃ&ý|6å{÷2lôh±Pz“N™דž»·´¯š&‹#^°€ ŠTK¢èMŽ AEÖ1‘ƒÉ²,† ûº~…Ÿ¾+• <JÙ3ÃBŠ9c±à&[[+nЦé§ðkWœ cÉdafÏ|>O,£¾¾žX,æ×è)AE¦ßêÈ4A#£ˆ‰F{uÒÞºpÏâQ+=å„¡·³L7Q´NF™t…âºáš5ùS‹ÏiùO@µŠQé r\Ȉ“t:ݦžQ1†a”Œ\é LÓì¡£”èÚ<þøEœp†No/‹6v%>hNK õûöq褓ºÕG­fsäâò«W¯føÂ…%×í<ñÄ»n …B¡P( …b`“§0M²t­D<ã§ÿ–u­]7°ùH[ŽiâÉ.œ,&B¼¬Ã„MS'òùײÄ+váLF.†!„™lV¬SB‹â¸ã0LÓ̘¦*^؉ÀÍÀÛ¡íäD —M£¹¹™H$Âý}ŠãŠN *uuuÔÕÕu¸MK‰œü…´w™J¥¨©©Àqn¡XŸ7Êöд@L1vAÜøÒi±4*„™lVÜ£Qq•û·mSCÓ4’É$©TÊO fš&±XŒT*E4%‰àºnT’©ªJaD°ÈÔ]‘hg¹˜Èôv€]âè›8"²ðUØ›EÑ} # ®ëˆ(µ`XFÆôûö•qà@ç³å§Ò•ïÿôéÓÙòüó<ãŒ.õMF»Éº-áߪR‚ÎÌ™3aݺ’m™À_çÍC¡P( …B¡P„SvK4„°Rü<‰ˆ¨‘Dß>D²£5G×7Ãm˜f`ª¬Nº¹\ cÛâ½tøÕ´`{ÅÀ¶U·ž@>ïï>”‘‡O`ƈ‘bÁ. ‘ò«`ÇW;7ÿïÿòúi§‘L&¬-I1xé” ÒÔÔDCC÷«à^úŽãÍ:Lœø1,«¼ä6‘HÛt]!²ì;Nþ+ëòyqƒÖõ¶0µµµTVV’J¥H&“D£Q_d‘^ñ†a`Yº®÷ˆ—¾¬5âÔ‘­1åhŽ’*jóX'å½GO>L&BP‘“*i&]ªXýøC‡øãÉ'—l/,ýË_àê«{û’* …B¡P(Š@{Ï-~×tz+“9rV‘ÞB:èjZa•H$V\WاjjDŸMS8ïêºØ66'Ó,tþí :ʺ’LŠCGƒëŠWGŸƒã;B4l'íê2•šÄ,+è—m‹ÿeô\îºÁwÀuƒÚ7º.^¶-¶•YhLSl—Ï‹ÏÊq‚ ]û5“w¿»cGtE[ä³ÿa#ÐF`¼—ñ‹ãÀ'ƒÁö{O;²Í›Ù´gõ×^Ë=—]¦j¥(ú…N *K–,aI;E’dZ¡¯}m('®"ŸŸÔ®’ÜÞø‘¢W$.p¯×†ô4bJ6+ÚH&ŰT´ ¦O?Çq°m›L&Ã?ÿ¹}h¨ßîöí“|Õµ¾¾ê¬t„CY!‹ÆÛˆ F•Ÿ×EÚ«dfzÃÿ×ÔXt]ôM  ÚsœBÁ'›ûêzVÍ0‚3R´ñÉøÇËåÄ6²/²<ž¼¦)ÎI^)De2¢M]Äyly¾^¹b¿FŽì³¦‰~g³¢)ÊH!E 3ÍÍb?iç{ôÑÑ rJÿ}¡Žq&~`?üœzp¢X°‹’á`O¿ý6üèG,˜9“ËfÌàAÇ!›ÍöYút…BÒ)A¥¥¥…¦¦&棩SÇA×uy¤œ~p=¦¹¨Ëm$“ßle Û€T½û²™´ËÛššà¦ÃÚnçÁý77]ŸÅúõ׉ˆ›Ã=÷|‘]»ZÑuMk&{…lVçk_»™3¯ðü]4]ˆ%£²0&î¥ïJÂ&<çÀn0áÊ"ÛµŒL9v(ïŽôèƒòŠc±¤{ŸtZÔLI$d³ÙþîÞqCw ³×êÌö§}v—Câ‹Û°9rÍ'…B¡P( …B¡h/K†ŒîÛ\kkfʦD"QÂýÕ4aw)5’Ï‹——¯,£,‰ "Q¥±1âñ }¹O¸¦L.'D¨PÆ%ßAØuƒì,2{‹¬I#kÅH'eYCÆqÄ>µµ…Ybl;8)ÞÈõ–%Úkl ®A<.öI&Å25âù!ûí¥Râ<¤]Ïq‚W®È«XŠC†Q…#³Ï$“¢ýptÑ‚<ýôÆþþú³ìzf$—rÙ3÷ ` ,f³)HûõÐâÅ$/æφäºnÕ›V(ºB§•l6KCC+W®ô—-_¾œ%K–PQQÑßçpD4Mcýú·¸ðÂñéOàÛ EzBD½¿ ‹ˆXÉÔ{ÆH†ð}>£Ã–˜ªC:;['ò_{£·=,ÚóB¥úþѾÅ#Lãðá2}ú“äóûùä'wó£ÅYgm¥±±ž1ïZÈ–“Ù½kUQØëŠNdªÁ#ÀN &ëÐ`AM>Pìe¨£ëB>Ú)Õü|>}”7.M < ¤’¯Ò*:BloÂæº.ÑhÔ7ðw×Яè}ym:'Ò†±(tD1¼eíqòÉ'ÓüÆ "T …B¡P(Šã›¶Ní2j¡Øh>Å¢'J=¶µ×gÃ’ð~Rø(®ÅbA”‰Œ ‘˜¦ä²ð~µµ"ZDŠ adôJñòtZôM Òö­ë"Ê£x{y.Ðö33Ͷç(÷‘iºJ­+uÝt]#¥lñÒÆUŠššÒûŒˆ²²}Gþ€>áúÎwÀû&oååw¿S,ؤi+x.¾²YÇÁ²,¿T‚eYª~Š¢_è” RŠ+VP]]=àÇqÐ4={.æ/Ñøío;VJd“b:=¦xQ‡ÓãHß{ È›ð"ÍÚ ü¸Þ„Éo¼ÉÏoû#n¼ˆ·®†ÕšhO¦ ‹F§¡iWã8ðÜs‡ùÈG"Ìœ¹÷¿?/Þ¸†}o¦å¡±pê}Üþ¡%üü[{øÉOêÈçó¼ýöL9{/¦.ç¶ÃX[DZ‚°Ï°p“HÀöíÛÉd&°dÉš›'‹mä$$((„;VU‰¨ !-öš{KH!F†xŠÏ)˜8È›“\þm”‚N8ÿ¥zä>òÿD¢ý‰H¸/оAŽÛ.½^ *ƒ®FÐ눇 PI*?JÄ„«˜ÅãÆ±àÉ'y÷³ÏÂâÅý}Ê …B¡P( …¢ŸpiÙžLÖ¼èhZ×ëúšf×mY2sJ©cµ÷h.Ó‰•²£´w¥¨½sm¯oíÑ^ßd“® i]ß'UZzŠ4óäȹûY°u3|QCÈúm·ÁܹN£™&†aL&‰ÇãG,ƒ PôÝTކ¦¦&ššš€¶…ìåºŠŠŠkòùùä“ÙÝçÕW_m=ùä“[×®]ë/;ÿüó[³ÙlkkkkkUU•ßæÚµk[O>ùäÖW_}µÃ6‹û¦¹¹¹uÁ‚´FçûX_ßښɷÓÚjšï—ð^=A}kk«j¯¶µµ•ÖÖÖÆâó+Ú®3Ô¶¶¶æŠ–†ÑšH´ßJsssksss›å™L¦hÍår­‰D¢Õlç"Åã­­³f­ó“J¥Z ÃhÕu½ÝcêºÞázI.—kM¥R%û'û(ûfF›í[3™L«a­^ã­÷ßÿ|ëÔ©·^{í½­âæÎÝݚ˵¶Fk«¦µ¶¦R¢[n¹¥Ëca q¤±ÙÚÚõñùä“O¶ÞrË-þÿZkkk"ÑÚšó¾€FWf1ͭ⋟imm·¶¶êÞÿ¦·,ÑÚö‹®ð1M³µ“?ÿ‚ÆÖÖÖT«øì*Ý#Žzc|öèu©õ^­­­F«Ÿ™V1Šv(¾G«ôõÜV¡è Ôܶ4ƒåwKql3î½9·•„ææÖVhmí„I¡Óô¤ÍG1ø,÷ˆ¾œÛ&ZÅ3>õ­­#.?,l; ﹿ¹50‚67 cRcc뙳fùvE…¢³ôÆÜ¶Ó*MMM,_¾¼`ÙÃ?L]]]Á²eË–uØFuu5óæÍó—]xá…ìØ±ƒºº:&L˜à‡’Í›7yóæQWW×mµó®»þÀ† ¿#îü>2²B:o×ԆΨÝ=%ˆ‡{™±ÈD¤ +•ê&AàÑJé·©TªÃúíyG£Q²Ù,Ñh”h4J$!ŸÏcÛ6†aøéœvìø%S¦Lâá‡ký¶lÛîð˜Íƒx¤íLÓ¤²²’D"AªDòP]×ýtS2òƲ,lÛæ²Ë lÛÆ¶‡2fÌ|¶l9›h´]ß“HD|/R©ëøÃºð) <:›@ŒOùÔàéd ¯MðåÚˆ„yÙ„<Ý«ˆ~q,ysèˆß:ëh:Fé‹ñyTXˆñ–#ŸÂ…/¥lFD­”Êé¦PÃôõÜV¡PtŽïT(Žczs|Êif>/R@u¦ng19~ŸGÇ}1·uJ L~`?ÛÞ;JD¨ÈA,ÓºÛv6xlõjb±Ø1eÏP N†vf#™¯¡¡ÁUWWÓÔÔT°¬¡¡c£ruu5+WuLZZZxøá‡ý¶‹sïM˜0ÁÏÙ×7ndéÒ¥%×ÕÖÖ“Ln§+å\WÊ#!¦˜¦xuƾߓ6¢âHí‰& Ž>«‘išÝ*®iõõõþÿñxœX,†ëº~°H$Â3Ïü€§žº¢@˜9Rñ¨T*URé*R0I¡ ]<§±±Ó4Éd2ضí‹0ù|ž»î:BP2!©dΜû¸ñÆÿå]ï:ösÚt46nÏ|åË—ûå’É (ý¿s²hF Â(A()„ÂþzÝ{Éýº˜u°cYÇæ£@W"ÒXºt)[·níïn5½1>·nÝÊÒ¥KYµjÕÑwPŽÕ,`û7p^G,Nh}1&Ç=2UÀ¶mÛú»+GM_ÏmŠÞféÒ¥<øàƒýÝ£¦·ç¶ E_#ç¶7nìï®5½5·ýäç>çÏý5­gÅ…¢#Ôܶss[i3v>x¬3ìÑÃã]±mÇq|wÇqˆÅb†q\¤ýVô Ë—/m§"T–,YÒãž:?ü0Ë—/§ººš%K–”œ˜v¦¸ÑÌ™3 {˜Õ««¸ùæ® †!Ä“Tª0*Eåc<2Ñh”x\Äu–îZ.b"$#ÅŸúØdÞ¼y¬\¹rÐ%{j|N:µÝ{gWq_÷?Ao€š™àþ ÜÑPk#Ær1 ”¸©Ä¼²¢¢¢M”ó±N_ÌmŠÞfåÊ•ƒN0è¹­BÑר¹í‘ç¶ŸüÙÏ|ß™iD¡è ÔܶcÚ›ÛJÓÆ©_ÜÊV}Vi{ŒmûYMÓH¥RÄb±’vF…¢½5oëó¢ô---Üpà 455qóÍ7û¡b&Lh³mSSSA˜YW°mxë­v«ˆx.×õ})^HñáX ˇš4M#—Ëá8®ëFÑ4Ͳ9ï¼óú»»=B{czf|j^B555üø}?FÖpÚ.¨BåÓ@£·,ç5ÐÒ#~!Èt$¨$FÍÛGŠÄu÷×W¹ 1ËHyçá""t,ïÿ ]‚ ÃèVTZ¼ˆ ‚…("ªÈ ]³¤×Ý['?—°^¼öô¢eÒ;¡ôöøì4.â3 = &ÿì€ÌÐ.ë%¨] Ù_y_M1k½ýÓˆïKXë r“)Šc„¾šÛ*Š®1`î …¢ ½5>åãBwì@Gƒã8=ó|¥P úrn«k~0>ÚÁFÞØ²m˲|›œBÑŸt*å—dùòåÜtÓMþûSN9¥àÕãù5×\CEE–eÜ4çÍ›×&LlÇŽR;ÛãÌ3ЧSÇÑu½ÓµPŽt]'•Ja„fgš¦qå•Wöw×z„öÆ&ýø”6òšñ¿ëºœ~ÏéÁŒ7é½jØÂØ*ç¤:]7¦7†Ú0)L6‰Â¤ ‚"i¯/Y„°’ìı¤‘¹§½ï¥È£yýÒgY£"ç½Ï"„Ùט÷²Jï|Cd2™.Enází_ ñyyŸ+¡<êõQ~¦–·>åõ7íí/÷M{ŸMÞ;–¬Á!Ï/¼¬3ŸÉ £7Çg—°)HÛå8`M{?DΆè7¡q“HŸi­§"ÿ@P‹P(¤JñM~§m‚q$ãÀ]Ú~æ2ª¬£~âK¶‘í+Çl¶ƒ6ä1¥ðþ=Ãm!ðN1xé˹­B¡è<æÞ©P(ÚЛãÓu¡+:GBÖXýå/ÉöíÛq‡H$Bee%555TVVúÿG"‘6ïÇÁ¶mßAS¡èôåÜVs`ÂζB_ØZÓüB¼†a`š&©TJ *Š~§Ó*7Ýt=ôPç~uu57ß|3«V­âá‡æöÛoï°U«VÑÒÒÂ…^X WQQAuuµ_䨺ºš††ššš¸è¢‹ºub7Ý´›òòuý}}[LÓuÄäàüÖó…È‘DD7äˆC ¢ôdú-Ýaz¯!7êõCzÏGÌäÓâ¯s8ÝUŒÀ ?îm¯yïå9Éó G`8é»d¤GÞÛO -“íHaH?J)%0D§ĘZïüäù$AOèA¤@ÔÛ®Æû«{Ç“)»¤ÁXö_¶£yïBŒRq¼åy‚´k–×(Bp G¶àm[:ŸdÑ52½þÊë'#\ ýV6\]wu~‘ú‡¾Ÿ&$nÚ_çH-÷Ã"2Tê͆!‰²€ñ^pMo· âó¬ñÞ˱¥ˆnqÄw+MðÙËÏZŠ1R| K™^Î@7Í‹NAU…×RT‰{Û˱"¿³ò˜5ãK 5rœ†—U­ßÝ(GN7¨8æé˹­B¡è<êÞ©P( è­ñ)+²ž³K¢›s0˲pÓ4q]×Oÿ½§ºšÇ￟ڛo&“É`¶mûµ_]×Åu]?RŶmlÛ&‰ išï˜Ù%Ç6…¢éë¹­¦Á.Ê]Å+"ñ·±Ñ_dY–%†N * ¬ZµŠûM(WEEË–-c„ |ó›ßä¾ûîk·¦¦&šššÚäý¼îºëX¶lË–-ã†n`þüù¬]»–eË–Q^^Þ­ûç?‡rÕU}ç©P£ilG5>e ƒ®‹pè…Í cº! }ÃxONå'Eý *d?\„Uîó‘BV¥á6O Hd<ÙeŠ2iÌ §Ã2 ŒÈRÔð/·¬’@È‘žýákSC[#­†0Ës¯× ¼ýå_Bý“â‰<¾ì»LÏ%¯ƒŒ”‘ç’ò®¼~Ò€,‹ÉÉöÂb’|~†ð¸Æôú%E®(ЃwÐêWŽ‚È‚ÇOyœó8ï(¿<ýKoÏN‘'Æòà^±ûDM¤Ì¨8 Q×!†úz¨ªÛ&â!7^ ºô\Äg'ù½‘‚ú a Å·T¨ ™"Oö»X ‘ï¥(ik&E=Xîs¹,I ´„EÕpäqdÄ›&¥@hyý‹Pø»¤œ¬ŽIúrn«P(:Ï€¸w*Š’ôÖø”~5y»kbJ:&ŸÏS[[K2™ôë}:Žã§úN$XÀç￟jk}Ñ$ìDZì1oš&†aÏ‹˲ÐuI“&ÑØØ¨<ì’¾žÛÚ6<¿ö0²p…ãˆÈš¦©q£0tJPy衇¨®®î0/Þu×]G6›¥¡¡¡Ýíäàk%K–P]]MSS“ïÐ]Æ;ØW×P¡8æ9ÒØ„£ŸÒê8‡Þ}H!£ϾF 2’#Œü_ÎÊu‚tTÒÈ›"ð”O„ö ·¥vã¡õÑ¢~„“°18EÛÈ)V”rÌQÅõÙR^?-㯉7dݘbA#ì8î¯LÖÞ5M…þ_)#Ó~×®2½åRP’íIÁÈ!ˆ,À»µ▷φ¥8Öé‹ñÙ~Ô‰ѤøõHý¢ŸÛ•J­ëP[+¼Žr91'öž'‰ü/Ô´sE›ùsA;Œ›Àù2ZÅPì_xý§×«!Ó¢àü ìЮý5°6‚õè«€³À9Ü3À8Œ±þ0 œŸQÜfȾÎ#àl†h D‚u?¤lp¯‚ôõ`oƒè×AwÀþ ¸ç@üEÈ_Ñ—@ûð8X.¸ß‡ø¯À½ìõà<%®‰Yï‰8átx%pÐeD˜ÎÿkAO‚µXÚOwƒaã8â3G9Ž8¶ëJ;Xâ¯ãˆ}¤!²Äö®l红MÇïeD~"!>cÇÐ,baˆg£×_ÍÞ½£{ä{ÚŸôåÜöhŸ_>/>ÓD"øüäç­žOƒ‰þ¼w*ŠŽéÍñ©Q8÷i|>mÛ$ òù<¦iRUU…®ëÔÖÖâº.UUU†A"¤Î\vÙe]òÔ4úúz_¨Éår$“Ib±†aøÑ- Å@¡¯ç¶–-“ÞÞQ¸"•j39µ,KÅ€¡ÛEé—,YBKKKÁ²ŠŠ vìØqTê‰éºÐÚª*Ú*=MwǧtØ–ìs6ÎéÔ^Ý¡½±L g¾Lç íÛÙþ·wœŽ2ãµ·.ÕÁò(mÅ #…™cRZL9:2ÈÅÛYÖÞ5”Q?¥×Ó ý^ŽCzÉ@³¼FÁ¹²ï€üdhü\Çû†Š £ðÁV×!ò3Ð Œ¹ùÿw8¿†ÔDHnžƒ„ ÙaÀ5àN†ÔßAû(Ø€ù ï+ý4X _æK`¼ Ž ñÛ û}HŒã\ü¬ìrÈU~ ƒ½’w€±ri°2 'Ú5¾ÙÿÙmos!dྠÚ&°GƒþÐfû&d? Î%¿ ìpŸZl6 ÆT`6p/¸•¼ Œ9ÿ$ØIˆþŒ×CwÌm/¸SÀ}jGA² ´w@âlÈß |ÜEྩ¹¶Áà AO‚3Dœ³Û ‰w)ÿ/Èݱ‡èt°‡BôDÐõ*h Ý Ù_‹ÏJ; Ñ]ÀT! WŠãÙÁü,°¸ œˆÏزÄy¤R"B©þ÷b럠ïÛ–Íå¼lì«áѯô¥¡Ö¶½ÏL DLÛ¯LF|.†!jšIqKÓÄg¤ëbY<^Z$U(#JHQ(.ÝŸ«­Â9¨¬_"k»¦Ói@*ÑhÔOÇ%k2È÷2E—eYär¹.õ¡‰DÂ|I$¤ÓilÛ&™L¢ëº_hÛq¿N„Læº.ñx\yæ+ G{ï” 3Ö'ÁJÃ’kßÁúâäD1^óù¼ŠE§• &´JŠOKK ý}>€x€œ1ãEUÃC¡ ÞÒ£îÅÞÑ{û»KG&lL’…àeꩊŒ6)µ\F­È”^Iú_Ì:ù —7áÔqŠ¡ 2Áb`¯üf0>ptmÇã¡:+Yñ¿ŒhÇl”©êjÀH€ó0¾ö½ }UÔe©ÉBj ØûÖÏ÷öɈè6‚ùM‚zA^ ¹¸L#æ¥ô2P;Æë\ÌíÀ­`¤ H]Î `<‰_"êý´s!!#Õ4ˆÿjN§ ÌV0ÏÇO+ ?‹{‚f<|H‚ó1Hî„Z²ŸâKíÐï(¼vá´Ì¥m¯m.”Š,Ns&£‹l0"àþ2U`~›‚5¦ |ìu AÇJs *£e¢`~Š ­Ÿ°O:ìr Än7Æ>п )µ6~þ­u<ñÚ¦û¾ÏÈû+ˆ4{R<ÉfÅ8K$ASNóù@xI$Ä˶ƒˆ£l(¢P9* …âXÀþÀ…žãb±˜_sAÖFÑ4ÚÚZ4M+ˆ>Iå ë !E®¡")öX–å (Éd’\.G>ŸÇ²,4MÃu]噯4HAå ÷ rhÈ!`xÛ¢œÈ·†/H*…N *^x!Ë—/çá‡æÂ /,¹M6›¥¼¼œêêêþ>'¦MÛÌêïn( ÇÚÅM»hýdkw§k„ë„륙¤˜®mr,#Ó% †s`Èz¶ fˆ€=jÿ»gÚ—säâךŠîÖM†·¾pÁ¨†äS`¿îP0£ÀM¡†B©ß|!T~ïÃã8||Y³Gþ½çVÝ»™_)ÚÖ 2-Ðw€[ú¯]™š¬Xì“ÿË‹$~éƒ^{ÿ-úåݸ°aa5|žrY´]8UTJÐ §&,n¿¨¾ªæ‚»ìëA¿²íú]ûw±ï­}Ý8Áãùœ)SuÉè’úzuR_l{$¿¢âÈ1ù^F´ärB ©¬éûdú¶ðM&Å~Ñìl P(Šã†¤¡Â»'%“I¿°|2™$’Ë北»®ëèºîGÏH,ËòS„I᧪ªŠl6ëGÐ(ƒ½|âŠ&^«ÚÌõ=z¿ñ 9ñÇb1?ŸB1Pè” RQQÁu×]Ç 7ÜÀu×]Ç’%KüY°~ÕªUÜ~ûíý}>€ðº{î¹]~¡0…BÑÿhš0ÆŒy| OU5Žú•ÁäÜ!ëÆëB×Dñr°~æ&°¿Οû8P8ºJ’C|‡³`îëÝÂø•õC$íEkµ‡CׄÆRõr`ÚAÍ¿ÿGznO5 ý ¨„èe /îƒëÛ›hÀ\p? š}Ô­)<"Í%£RÂõiºbcÑu!Ä´–ðo0 ! €ˆN1M!ª$â}2¤s“Qf2]˜B¡P(ýI؉=ŸÏS__ï§Ì2Ž‘•iš~j2)þÔÖÖ‰D0MSÙ¹ƒ)¼wüÿðÜØO°ûùM~1G]Ó B¤3™Œ*H¯ptº†Ê²e˘0aÙl–+V¬«¨¨`åÊ•&:Åq`Ê”ÇÑõû»+ …ÂCÓ :ÖîÚß]QÔ3xD“ H¢ÇˆÅÀY™ ® ö°#x¼Ëâ ¶§(˜fï©/:"d8u¢îˆ±ì(ÛLåþ^×*òÖï̳»ä çžOF vÇt55ÏõwW EˆlÌ °›««û»;Ç7ƒ+¢ãh áŠ6HMD_ U_ãÝàü­0PÒiaÝ•…zM¤à²’`|’#Gô)˺H2D \W|-jŒ–U(ž„Å M˲ٮ‰Åé¾:³}4*~J}GS)ñ"k²„Ó„) …BÑÔIGD¦d³Ù^©©ÛW ‡ Ãhc@ŽÇãTUU‰Dp]×u1MÇqp‡úúú^ñà—uglÛnsM¥påºnÁ±å>é<]×q]—l6ë׳qÇ‹¤Q]n^>ŽeY~j¨R¢šmÛ8ŽƒeY¤R)4Mó÷‘Û…ÏÓ¶mòù¼_ÇC¦] §`Ëf³,X° Ç¯ý`g¯»víâ}‡Êyd.0Í+þú¼t]Wõ±’. *’‰R Y§A)ô ÅÀ@úÕ¸.t²zûjnÔnìïn)ŠH$Àúhÿý °Ÿ…ÜýGØ©£ÂŽ#rIµ¡U×Þù¥†ƒJÔ”Tt“#¥óêê´WFštÓ j+•:~s³X/Û•©ÀLóè„F…B¡P(:‹¨ënûbCO2nc¹Ð|[×uªªªp]—h4J:&‘HøýÑhÔÿ N§‰F£¾˜`ñxœ|>ã8äóy_ ˆÇãd³Y²Ù¬/H8ŽƒaD£Q’É$š¦ˆÒgÛvÁ2¹¿-¤("÷-CLÓ,E? §¦¦¦ /r™TlJ§kW("ŽãÀ´m›8骓ú»; …¢l[)¹O&˜+À¹8d·,ñÊçEÈJ +iMM º®‹à!]‡hÇ+ª©¥Ó"Cæ'’Šˆç2/=Ý:KG±‹½åú‚£9\WR6 t5 BÑË’Æ¡öéNP˜Œléj_:Ó.P$"úïºb™J§P(ŠÞBÚÌmÛö‹¹÷$aJSÊÎeš&‰D‚ššb±˜•‹Åüå®ë’H$|±#•JaÛ6‘HJ.—#›Íú"…išÔ{áé2ò,lÛ¦¾¾Þ/¤¸áºnÉ(˲pÇOUÖd?;c×K§Ó¤Ói¿hyW„´ÊÊJLÓ,è›ã8TVVR___ò™DøMÓôžT*E]]]A6ő٣ÁÈ=#á/ ¸~LšTr;å0¯ˆ JAåä“wràÀ@ðP(xóüíÝì1O!éy“J¥ÈçóD£Qß»&¡\ÄŠn“ÿ:°¢_ ˆÿ Ü3ĺ=·ÝÆÎÿú/¦~îsÐØˆ‡˜¿ŽÅO¯¹†x4Ša<ôÒKœ°n‹æ÷;wòX:ã8¤R)â©”ÿÄkÛ6F6ËþýûÙÉðX2I,ãùûïgþo~#,°2üÄ4±m]×}/ºT*ånÃÅ;¥™ô´3MÓÛ?‰Ëåüß"×uI§Ó¤R)?e‚Ü·¯K’IQ›B‰ ‰eùû ëˆ•Â4»^çD–Hê ²x}6+^²þЬµ¢P( EOá8²®˜sܯ–Eê5M+ˆ^!’躎eY$ ?RE"Å)¶ÈöJ‘ò¼~âE!³š¦ùíhšVrÿî<ÿwŹ*‘H`šf·jlÄãñ6ûéºNccc»Füðö]‰%ˆBåªI0vlÚÔFP‘‘EJPQ D ðòËOqæ™ÇÇ T¡8VH} FþûylýÔÖ£j'Nûá½¶gÙ çn”¼? Å1ˆeÁŸ_‚;uíò@}ùá‡ùqy9wÇãT)àÎSO¥qáB>ñ쳬ùÃhyé%NüÊWØñ ¼ñFþø—¿°ðObÜÈ‘üêÄI& ´ÌýüÈáìûò—I¥R\sóÍ|{ˆ<ø /ŸwÏ^~9S?÷9òùï{ñí´Í]î«|”idRˆÖ.êCL³ëÑ%º55…çPU%þærAÔK4ªR‚) …âèÙ¾}ûqe|íÈùG^‡ÚRíÆ”Sô¡»ËÛ»~ÇÓw¨?þ9cïz›Kê.Áºsœ~z›í²Ù,–eµ ŠÀ T¢QøéO0Œ‹ûüØÊ¡P´Or\[öKÌ%GÕŽÌŸ™Ífýeº®“N§±m›t:M£ç9ø¢‹4n‹‚K2™ôÆòtäuUSSãØH„Ã¥Tô¶ e„UÕp&0ˆ;‰|ž¤m³õì³yâsŸã`MK 473láB>zÇÜû½ïqþ}ìõ 2:sæpó½÷réøñä/» xaÁÊ6n¤aút²gžÉ×þû¿)_·ŽE×_Ï?‡ ãk>Ѩÿpãº.wÖÔxüqß{N³mÞþò—9xÎ9¼vÿýýiÖ¬YìGåªK/åägŸå«³g3þå—¹ü{ߣøÂèÑþ­Õ™:•ª©SÉRÒp§O'6}:QÀjnæ^ÄíØ€hÛÛÞÐ42¹yÀ÷Ÿ3M†Ýr Ãl›–ë¯gÍ /° Ÿçü_þÐÒiìº:Œµk¡¾KÓ‡‡|kÇŒ} &NÄÕ44Ä÷±¾Èš«iš/®†á¿‚n´ŸÒ ”·_Gb®,$úŸÿ¹XÌäÉkˆÅbd2™£Ž‘)ÍÚËJ¥ÚüöÉH™*¢R@±B…5äoc\×u_¬ Q7Üp^xáQÛ`'™õa$ $cÀõÖ¥"ɪ¼å…tmo_1v½vL(c! o½†è‡:¶îí'· GŽ”D¢ýBö©Tö˶Å^føñ··Ó‚¹®8vMè«ìG*%"rÔmD¡P(ŽÒiX³f,žoB¡ÀŒsahë^»øN8ùú’ÛÔÔÔta¥Pô'ƒNP±mÐ4G<ÍɧÎÅÆ@<ýåCË¢pð»yûŠ·Ù›ÝËâ²Åì+ۇ;—ö1úõÑ¢­¼·½|8ÌxÇù 0Ô[Ö;¥|‚U(Žö¹k6NïÖþŽãø©x¤Ñ^æ\×-0úÉÚ 2ýLÓ#=Íc±X‡¸LÛ“Íf}ACöK¥Ì‘ûÉþÈš Ò\/¥ñU Òð(ÛÍf³~¿dš"u#’|>_ ^„sãJïpäiš¾‘Íf}±É4M¿`8ºEŠ%Rà©©©ñ…'™>Mz­§Ói¿ÿù|Þ/Ä'=ë¥èaÛ¶]d½‹ÚÚZ¿íh4JMMß_i´Ö4úúz’^:(YTP~>–eùá\½R(r]×ÌI&“¾úô¡ÃŠö±î…5°pwïFûío!ã×ùŸzç;YsÁ\öíoó³SNáSsçråäÉ0]Œëâ Â:Ðì½ÛD›‹¶Kzk†à8Apu †Àìz¯ŒibyBÃÝ·ßÎiK—ró{ß --hÿ8,[†»oÚðáhÞ1´ pª«1𛱇жè[·âìÞ3y2ÚÎþrÇëK~÷n´mÛ0çÍóû  ¹.¼öîÌ™hå帷§¥£¹fÍÿ{ëô={È¿ñÆèÑ0mšt óä7¡ëpNcŠßïÝKY2XtK=Lx‘0t ËB™ÅH¡¹”Ð#ëŽâmGB‘L£Žü‘Û_z饪pçZVŒ`ÚEŒyWÒã#†CR,Iyûit í-Ó¼õµˆïgŠ`J,¿¯Rp‘/9.¢¡í ‚1ì„ú•ðþw4pµ`ìÊï»hF0ν€2R)!ªHq%•iÁGÔ^ÉçEi%)ÒHF×Å6ù ¸n  HжEdLmm°¯®‹vÓé ÖŒe‰¡˜Hˆ4l2êFFíd³¢_Ž#ö•hšè_:-ŽË ¡Lö‚3ò},&ö‘}”Ë C¼O& kÐD£¢-™’-.Œ J¥„`$·•×@Ó‚ëÁuظ1Juõ¦^þ†+ EÏ3qb}·Ó?)оc§ ´fÎ/×°ñz`aÛmTm\Å@fÐ *×_¿‘uë¼h-{^ñÄæ ¬>ÒJEXLÒ!Â){O+…‘îúE×óë'¹ÝOšòÉ‚§Â4âIõJàýºÆ Ý;Ž´9¡¾„Ý2­ƒB1qíÞú®]»º´¯ã8LûÃpöï÷… ŠâI¡!ŒL©cš&UUUÔ××ûâ€a~úž\.çžv‡\.G2™ô‹ÚË÷Ò`(…‡° øÆüp-ˆ\.G:&Nû„aþ„ ØK<œ‚G 2ª¤¾¾Þ¤ð + “aƒ¦ôàiˆäö2}Œr‘HAÃ4M}IFÕ”2–†û_¼>ü6›Å¶mêëë òžï ?ô~å:¹¼øx²†\>Ã0øÎw¾Óoíñ‹ýlÎz^ècÇ2æÜsyÇÖ­¸»w“zç;1ýì³™ò¯q}¹ÿ…?q)¶$n³aziä…ö;|ñÅ$>ýiNxüq´Q£H——ܱcÃ[o ëáþý¸¿ÿ=îÕW£ÙaÃ07oߣïßw‹wû¶Ûˆ¯^ óç“?ýtr]$<ÿ¿ýmœÕ«áê«1.¿ëá‡1æÌÁÜI-]еhöå—£|2ÑI“ÄíÿÕWIÕÖbíÝ‹>bÎÙgã,ZDp࣯¾ À­Í_áoÝë}(v[7yiíÕua5ŒÂ ãÒzÛž‹¿gyNm>©# ÅÕc1Õâ@à“9!VÈ1µŒÓÖwÇBl+E”ðúð7 Ô'.·-õ)¹À$Ęìì·EöEóúª…ú/§¾R`‰LÕuïkþ>‡Hžvàã:¼mÀ“0Qƒå0ð˜§1F""’'¢‹e !j³$“ØJ‰í*+1&Œa)VX–hÇq„xAz°hT ÕD¢°Œ”I&´)³’JG׃¨)Ñjj ÷i)Ñ™LÐg),9Ž8ÿ\N´%,Kl[ªO>R‘ˆ¸.²Ë—çñ i) Å1B<?ùÉ&4mVwE¡PñÌZ¶>m•SßéU¡ˆ *AÅq ±±UEb€,£`R:ijïåóy,ÇâG¿ÿ€ŸFæÚäµÄãqNËŸF4Æ:]+Ln·TÑÐ(âÉR÷Žg¸ã…ÉrL!½Öej!À7NËoõÔ5 þß„÷» üàðav|á L=õT¾øÅ/úÆQL³×,éŠä±Â£(åß°FŽôÿO„Ú(@Z&uM×ýõñÉ“aòdñOH`ÐóÆÅ?®K"†‹.ûýÛ¿a|á â·ç(ìãÌ™ðßÿMÔu‰&“âé^þz*œz*†ãˆIË"‘R4ØS§²ûàbï|žC‡µíwÓ \ËKåS’ËkjÄß°û}6+¬ÊµµÂí=li•1š&,­¥¢bb1ñ7“)z¤Û»,Bò*;, ¾hÁ¤”ðÒÁϯåÿ´9ˆùc*ˆ0 G”Ä%˜s&&A‰#мÕ])Ykø/E‹Ú2(xâ⊌‚±ð;`5àèðgo¹ã σq˜DtÈ%`s®KÃaþ×€G²ð¯$l× û|0nŒ„˜—؈¯÷­0ÂÆ ¥¤0%£PJ=Ï;¡m|±H µ:Ùp”´­Õ"ƒJt-¨'#G·>^èÖæjA„OsqømûNǦWóE`ïèÑ]øÄ …b`ÍÂ_ÿº‡/|A=(64>4~Ô¶ˆžmÛÔÔÔ(1E1 t‚ÊöíÛ™½avçÒnyHƒ_6›%›Íúuâñ¸_; ¦¦ÆOkÓ•ú˜žçy>¨×àXŽŸ*H×u>tˇ˜ЦÆC¸á:áÜ亮cY–o¸§’žú2mŽLE$Ï7l\•ËÃ){d½„h4ZPPVÖw€Â𦵩¹îS¸@¸Le.š®!Ëá”HòúHÑKö%‘HøêµL»$'Û0M“d2é§4’ël6ë Cámåy˼²(°L?$¿wïÞþþêx†{6õÍe›ƒ…2—…iI˽ÿezª?ùd¾ôŽw°søp~rà ?ìz)“Ÿ‡ Ñw—p*©° "£L,Ë*ˆ® ‹º#F{‹‡£QŠ£:Žæk¼Ü¹^®,Å ÞD¦>S¹Už?¸p`6åš:”«çÏçâêj¢YœÒ4aÜïíc„ÇgØJZj¬KKi{c¬¨ºwaÔ=ÝÔyóåñ<Øã©4’Ëš²}CÓ„qTÓ|ß YOC‹F…áö‚ ÐGŽ„éÓýOÄãhû÷cTUáüüçA³|ãW^‰=~,)Úð¦/ÊIć,SÍÊ\v ñ×7Þk_ùá&ààÿ=ü÷gþ›ó^>Q›F1ÄBÓÊ&ž½ìYί?Ÿ¿Ÿþw^Ýù*sZæ0töPü׃L™2…üówrÙ÷þ93.áÏ%á(Cy/üÜ©§=WuC¢_x¾ …â©\j†–gÁàò²8¡ÁŠ<¼' £5¸99ða¾‘€].¼á 2Ú- ¸zõƒ÷WFÂÙÞ{)‚@ ’Há'¬ki¡õP¯ˆ8á_Òð~Q‚¬Âr¿¶#…*›Âà{yáÚ:áß ™®-,åB\ÐSAj8€^y%ç74ýY¡P(úÛ†áÃw*§*…âaÌÁ2¸Þhã×#Ó‹«(wÅ@¦ß•––vìØAEEEÁò¦¦&ššš¨¨¨h³îH¸.ìߺŸk¹6pQ=UUUd2?ç¾,Î*óÿË´AµµµX–å{«'‰‚43„„é½.kH#¿¬1N§}í4ä¿uø-~xáÙ6s›/(HñA ²³ì‡4îK"æy†Å”t:í !Rdðבû†…›°À#…$é‘/_*eˆ§Â)ƒ4M#bY–/ôÈëp- )\Èãe2™‚‚Ôr‰dd@"‘ð…ÙŽ|ÉëËå|1EÒ•56$2­’ܧ¶¶¶Mÿdƒ¦iüùÏæüóÏﯡÔã´76¡ûãó §¿o+ö›ÞÇF7il¬© *À‚_@9ò«_¤¡*@&6/&›-Ì·ÑH¡°±D›îÒ“¥"SŽU¤`³ÜW$Ö´¬áÿùGžH>Óä Ÿ¢£oÔY¾v¹H/™ðR;~*ŠsìͳXð±LÌLäù'žç[g‹Cã1ï’y<ýã§¹ºìjV¯XÍç§~ž)»¦0â¢lÛ¶†÷6P¶¹Œ“7ús+l›Ê¥K‰F£¼þ·×™¾w:«'­‚T—rÎiš¦ïx#ç^~ºJ ƒÁÿô2º%ÄsžŽé­‹†7,šD½—8«ÛsGѤhë·U}"û'ƒˆ¢øñ>6ÈQ‰t—‡ÔÎô¢í5„ˆdˆLry×·âsð#_B}µ½>¥C_£0ËW¬€êÁ“ò«7ï …âèèéñ¹mÛ#ý}J Å ¡7ì¶’2&¾ç0Ð6‚Y:MMÆ …¢·ÒÚÚÚÚ^¾|9ËBÒ«V­bùòåÌŸ?ŸµkײlÙ2–,YÒa;K—.eåÊ•€°Ïýã?‰Ÿ®1ëû³Ž¥bÛ¶_'!“Éthd”‚F2™$•JùÒ¨¾ùî»ùÂÿˆëº~ý…°"£/䃢@ˆûnÜGÓ)M´,jiS›AÖt0 Ã÷ò+Žd‘Qa! ¼NýõË—/§ººšêAòàYjlB×Çg]]uuul[¶ŒýY¨úíVž?ëVRñ¸H€^å¡êª²`»4”w¹¨ ¬ÖšËõ¨¨®u¢8vß#=5>K]—Ñg 3DþóÜsúéÜúÚkþý®¿‘õ:BF†û‰D|Ñ\./ G/J¯¼ÏÊß)ð†¤Ã¼Ï‡£[ÃëlÛö4¤Ð"k"bŒeYÜ÷Îÿì5“ÙûÍ©|륇ü9à·‹Åü9„¦il›9“·>øA.Úµ <‡°@$£Aå¹:ŽÃ·¦McøÉ'³ùÉ'yùðÛG‡JáG®‹¿ë]ÌZ¿ž–E‹ø]»øÇ¸q~FSÈ573§¥…Y³fÂXû‰ý‹?^{-ï©­eNYÂØ«xúižâ‰6ßåc™žœÛþkêJ>bÂWd¤ILäüO:Öd2ᔉø‘ÕŤÓi²Ùl§\×eÒ¤I©/}«¼T’^?k–}/bÓ¦MütÆOI)?ŒbûcÛi¼®‘ú\=¿[ý;ž+Ç<ãðšs¯áó·~Þ÷T´mÛw¾)Nãy<¤ýlÆ=…šÛ–FÎmÓï–âØCÍmÛ¿.¯½¶ˆôjäzq«S(ŠŒ÷ˆÞ°Û‚¨Ï7$3ozŠÕï?«Íö±X¬×³i(Ž/zcnÛç*«V­¢®®Ž‡~˜ë®»®Í Þ~ûíTWWÓÐÐÀW\Auuu§O]‡]{Zh^ØÊ,}V‡ÛJ!$œâ©#R©”/–È(Àx¸kÖ¬6õd›íåŠGÍœasH["•U{ý‘˜Åëå¹t´BÑM8ºñyò\xŸ;’çA¤éÊd +°†Æ‚ŒÌŠÅb¤R©® *©”UdåÙB‰)Šþ¤7Ç';èÐm ë÷³õ‹_ä¦[o-!ú™òOŠ«Òƒ]F}Êôwù|Þ_'£'mÛÆ²,_lˆÇã~T¨ã8¤Óijkk}Q%¤Œ“÷˰óB8â4|o /2jR®+%ÀJÃo{×4sÎO_¤þ±©¸½™è¯¢%ÅaaI^+¯íð1äÜ@ÎE ÃÀÄóš¿âŠ VMÑœ%ÜÃ0HéE‹HƸq\î­³Þô±I“HLšTÐ×ûöqÎwؽ›¯••‰Ï ñ}û?gœAô¥—úúëÕ+ôÆÜö€ géÞ+úÈ*™:VF9Éïq,ó?÷öæ†í -¥Ð46þW²Ò¼$l]Ê >ä¸u¹dÇ%p%~‰ù‰YÃ5¸êì«þÒpFäGÆ! Žæ0yÍdʯ(ç¾5÷ñÄçŸ`íÙkiþk3ëŸ[Ï’mKØùï;ùMæ7üòO¿dÕ[«øÒÁ/qÂŽؼo3Ã/ÎæÍ›ÙõÜ.Æ1ŽMÓ6±à‘ìÛ·w7§~òTqMå—_†xÈ_&lÚ³‰­ÿÚJÙIe¼]þ6£6bÎÆ9~>®'Ÿ|’Ìb¿.ÍÆa™2b e—”Ѳ¼…òï•‹¶Óù¹¢°õï[™úÚT?šh÷M»ysü›¾ éç“¡*iØý¾Ý ýåPRW•‰vÂQdñ/äeËo¶0mÓ4±ÞôÚñ¶ßýünÆþt¬è³\ µgÀLwæ ¨IßÛ÷N…BÑ}zc|F£"ioâ} Å€§7í¶‡¹õm&Zrý@pèS(ŽDŸ *óçϧ¢¢‚¦¦¦‚åuuuL˜0ÁW‹æÍ›Ç¼y󨫫;¢Ú)1 øÕ”U|麟wj{éßYï¶pZ¬°Zjš&…5ºl|M.$tUÀUÑ?´76áèÇç/“pò;_ÿ´3Þòù|AJ7Ó4»#M$D±d²GE…¢¿èÍñ ÂŽ6óL ÅáÖ×4?*²· GPʨ ˲üt[R(‘u´jkkýšfát”ÙlÖ¯›%SRJ/vMÓü(ùV[[ëß§Kg¸~à×T+¨ýrV(v\è®»ïïçàð+8éå—Ñ´“¸}w½óe¡ñ®ÐžG|qˆ~˜»,àùÝ»¹fìX™4á¿õjê¶níVÿ½1·m¶`q‚À ~Ý7E§a/—˵©ùUŒŒhîtü(ñù—ΖË/JŇ2³ þ3´ot[_6.ùÈ% [9Œ²kʘaÏ`Fv†ˆÖÑàú—¯çÑUò‹kÁØ{Ʋꃫ8áù¬{zã·é}c7›xÇØw0òÔ‘Üû‹{yöŽgùÇÍÿà³Ã?˲ñËøüžÏ3vìX¶Wnç·/ÿ–éµÓ™¾w:gN8“'v<ÁÎá;YüÆbþ_ËÿãŠû¯àí™oó‡7ÿÀécOç×/üšß¯ú=ß8åüõ¯åýcÞOÙ¼2¾~××ùXëLjãͼÉË¿}™ ;6p`ìÎXu÷μ—÷lx'dN MšØ¤ÓæNcõÝ«™>}:/ÿãeÞ÷üûØ0{›ÿÏf<½€oe¿Å•s¯¤.]ÇgpòΓÙü·Í쾓ñ/ç«u_å®Mwñè„G9á='ðöÓo³Æ^ÿýíßÀÖ‰­œÔ|›Ë6³öüµ|düGXôÈ"žøì\0쾤 l8¼þ0ß¹ú;½óýèCzûÞÙ›HÇ9NeäVq$¥Bq¬ÒãS×­^öÑ7¡P xzÓn PéÀÁû8<¬mÂ$é0¤P tú\P™7o&L(XÞÐÐÐFÑœ0aBÉl˜7úácÉ$¤×_Û©~HUY/£ß‘Õ%¥íWV˜”©t‚J“r{i•Wš”^vòU*A´t«P÷GÍÒ¥KÙ¸qã H‰ÐÞØ„îÏ|Î=†-â•1«;H4Mò¬.‰œ4Ö~1è£!Åšâñ‚‚ÒØ¶X.QýNCCË—/gë 1ØöôøÜºu+K—.eáÇ>ƨ‹/æ…-ð³×b{i‚z:*K¦ó‘íº®Kee%ÑhÔ!„ëoÉmeôZ*•ò×u©ªªòËá}¤¡9ü»#Ýû~_L—œr »V¿ÊÿÙ~/ðo½~¼ÞÆŒ˜"Yµj«V­âä“, ôÆÜ¶É9ÎH?:Ų,’É$¦i’ÉdÚ|‹#ŠúâûÚm4Ú ¯“CÖ€¿ÁeÆeþÿ„4¢Y÷ÎÂø²Álc6|nÔoàtN/hr³ü÷—}Éd’•^ɶuÛ¸õÓ·¢ë:‘H×u©½0µàbûïOwOÛ­sÉårþ5~Ÿõ>b±õÏ×£i“&M¢¶¶Ö¯Ã¨=¯‘y2Ã¥Ú¥~ª²%,ñâ5Z i@(!hï_—¼l®ëŠ´‚Ñ)­sŽ$2á÷âß êç¾téR6¾½±¿}G¯Ím¡Ë)]üTŒrº¨‰Ï­¦¦†õ®gö‡f³þÑõD*#œvåiüô7?EÓ4ÞZÿåo—óÞO¼×OáN‹'äÜY 1²Þ£L'¿[2¥t0ÏÁŠN!ç¶7ªñYŠ­[·rË-·0zôèþ>5ÅqˆšÛvÎn»lÙ2¿íaûvÑ:dX›mÃ÷4…¢'X¾|9>ø`Ûmû­(}1;vìh³¬3!c3gÎôsñÙ6ŒÜ3²MñÉ0Òóµ¾¾ž_ý*Z,&B[ C4Ð_Þì&")r A!¢˜±Eº”Êâ¤o™—§Úß Ò %e¼T¤ Âüó¡í¤«©j7ZôÞõ9ëý•¹´¥7¥—¡à³ÛJñÇ-ql=tl¼6=/Å‘H¦/ ô^ÚÑŠû)Û ÷S¶«¢ŠXR¨ VaX¹r%?ûÎÏúãÓ§tw|~øÃfÝ¢EDÿ¶~¯¬Ã‡6YkÈu{)Úu¡²Rˆ-ÑhûEíEg„`6(;Žˆ!ÇÛÖf‘±å¶-öÉçƒú0r½e‰6l[´1"gG¼Âã¢Ð¼yóX¹r%K—.íï®ô:ÝŸS§NeåÊ•"U0Ú†Kÿ)ÖõV½ X,Vvʲ,âñ¸_t0“É”,¤Ó ×VÒ4­À°y¬SóÊ Þ9ñ‹.šÚß]éU–,YBEEuuuýÝ•^åhæ¶SGúó*•R,ahûc¿“?Yº®ûQæc ľL&sÄù‡¦iÔ××ûFm‰iš477ûÿ×××ûë‹k?uÙ&ûþÛÙkÑヮë%Ó¯\¹ÒÏ™>˜9š¹í²e˘4 B{¤èáº. k`ÿO÷ó›}¿aÙÛËÈëyVo_ÍÙ{ÏæÛ§›¹³çr×´»ˆÍ±þ~~~ÛÏùõ›¿fnõ\ ¬@<»ÙðËÙ¿äçå?g˜1Œm3·1ùÏ“iúF?\òC^þ*Ÿ¸èL{|®y”¸'ï䩪ªâ‡ú!3¶Ìà»|—ÅãóŸÿùŸTÆ*ix½Á¯Ñ%ÓÊT–2•fx~>Xî·Ç"jn{ä¹í'?ùI,ËÏöÂ>"Ÿõ¥½D>ïKûFšb–Ÿ=ñIDAT À[ÊÛV®Ï†àÙ]ôÓ;½íeªDaKHzÛ¦r¢[‚´ÕÈÛ¸|ô*uÿrPίÇjnÛ1a»­Ì oŽ?Ì¡áåm¶•5¥Û+ Pt•Þªk4`•Rž MMM¾zÙaߌ :ŽHýã½ÿûßOÒuI&“"‚4$¦Óuü}½ÁìW{ÓÈX‹¸Q'ž{S”à¦*…‡Á?A ˜¸¹ Mo_)2XÞºTè½—¿™8p!/EX¸EGÆCä$¢ÆëKUQÿåD"jK¶+…ÍÛ_£P$©ò¶—Ë ¯q¯M™óZ Gròâ„ú•m‡÷>Ü1™ ?Û:¡ÿe%ÝðùäÅß™ÓgÂù½÷µÍøt€«>Ïì^Æ ç'mÇYˆ^½ijšxòu]1®ÓéBÑÄq„àbšb™m QDöײ„SÊ`q$qÄ4Åñe[v‰`ñH$ˆ~‘‚LØ ‰ûJ8|\Û)η‘ÍŠóL$ E!Çç'IšÖö·.ÛézÐFøZÈkjÁ1ÃÇq]ÑGÍ#¯s±h¥ib)j_ï|¾°Íp_“ÉÂk{œ<ôíø4€¿€…£hWÐè*Ò(#SvÕÔÔH$ Rg†ë¡HºsìÁdÜRU…þÒ=¬­þsû»3Š£¦»cóõÓNcâ[ˆyI¿öO ®+^¥Ú•¿÷Ç ]¹¶GJG:˜~“3Gsï”þ3a6üs^÷(Y²|fÇgøãÞ?rŶ+X4låÃËYôµE¾!õF÷FÈ‹š;3?0L¸š«(£ŒÓgðÆo0·6t'ðœÀ®åZÿYg²;PqFŸÝùYv¼gïýê{Á‚ÅéŰÎ9牺£Ãá"ó"¨ýÚÏÿx˜Iÿ>‰»/¹ûF›µ£ÖòÑ}”–-Üzë­|ì]c΄9|ì㪓®bÏž=d/Ȳå-|ïçßã7u¿ñë8IF I²¾™œ È(S©ºök™é|?ræHcPFªª¼úÇÝŸŽã0iû$aSÈ8«ŸÒ K¥ÐaØ p°”_MÏN¢O"°i$œ4¥#³†Hû†´¯H»…MàLêzm$½6ä{¼uq[ê[Ø6…Lø}¸Ö–DÚ>Üëd_åþÒU§´ÀSª}iCq»¸:ä†íZZ;íèGX×^Šû*?Ÿð5”ý‘ým/û‹üLŽ“[OØm]`Dh'¦eb[“´¬M©P tŒ 2oÞAÓ„¡¿X¼Ñu(.ºFŠÝ=fxßRíÔÖ ±@ 9Å¿#µµÃ0 ·‘âDñ6R@‹Eëtöøñ¸xIÁ¤8âÅuÅ復‰—¨ÂÈH]}-å-\,F…û],l9|çØÏ$Žf|J‡¹èdÎ×ÈzuŒŽ–H$â§’©k¢Ñ(ÉdÒ÷慨ÃñÊÔSOeêâÅmdž☤»có¤^àðk€Éd’h4Úþ¸”Ñ“¥*+ÅwɶÅoex)° ×R˜ÏfÛÞ+¥ð^Ñ-ï7Ù¬X ÚòÞVœ.S¶ mç× E/s4÷΂L¯ÞsÂ꯮&nÇ1âÃÖ #¦Ç(ÿy9÷,¾‡²²2%6bÀLf–lÿ·÷sP?X¸P/Ü·Øx7êùQœ¢8ÉyÃz4£Ñ‹$ka£8}Óé˜ç™Œ¾f4¿Ûþ;FMÅlc6».ÞÅwþN®°¯Z.háŸü“)#¦°é²M|fögØûo{™ëÎeÛÓÛXî.綆ÛhžØLY¦Œ÷¿H}k=¿ªøoù8««V3²~$Sš§°§l›næWcÅÃ.`Ïö=4Lo`sÙf¦ïθËÇ1ê®Q¬²šµ£ÖröÞ³{úX>øåò‘7?”Sؾ};'Näpñ¦‹™vë4Ö}y#và]­ïbôÞÑüýÀßi=¿•óëϧ¥¥…;fÝÁg6|€ ³7Pqy÷>r/_öë|vòg¹£ù¶ž¾•½¯ïå´×OãóS?ÏWš¿ÂŽ¡;h8­Ã0(¿·œÝ»wð¥±_bùðå”——“kÍQ9¤’êMâÙðÕ᯲|Ñr$x饗=z4oº˜ C7àê.Ë[–óùMŸg\2ú~9ì—¬+_Ç´iÓXux_ü×9tèO—?ͨ=£ø·)Ç~JÐ#ÑÝñé8ï{ïûà+ˆ1SK[~)?¸(!¼­Q´Ge#h-*/2-„í+¥­2ˆÐð…¶šð´/ØX‰_2ΰ.B(’}“N¤a Cà›@d6  H±S©‰¤«tX•×CÚ]r^a>éø+E«”·¾ØÑU¦ðŒØaW:»†¯eø˜v'ŽYüùfCç-3«H‘+Ea4RøA`ÿ‘ÿK›R&tý0ïÆy¼uê[ fŽÖ.âòíû4OÜÃŒ± Ö'“É>«ç©P FP©®®fÇŽÔÕÕQ]]MCCMMM\tÑEÚß¶aÒ„í¬øÿàÂÐI¦÷ö».šëbF猷a#h{Æ ïAÐY°@<„{°g³A: I±aRzžƒ˜×ÖBóyÑNØ»½¸ é™-i4÷3.Ü'•*|à-öîÖõ m‘ìN¸¯òºÄã!/ï=•êxRž×ÇK¬‡`ÿð¶Z‰íäòâÈ(±_©‰Mx?y¬T‰vrEÿËýV„£Ÿ‡÷Æ=¡ô:™Ê$5R`•¢/BN£Ñž3¤–LâED"¥Gz‚ö&>º~äHžRBW1]ùž'ƹ£Ÿùß ¤¦:8Cœ.{Êh™Ã(HÏÛ¹Þ¨m¤P PŽjlî2äiÌd‚9f$"æfò^!ê|^ü>†Ço}½Ø^ Þal[ì#$‰„br¹¶B{:-æxÅ÷9O5MѯâÈÃd²ío»ëŠåŽ#î2jQ"£65­ðx2RÓľášr+-Ýá(Óp§\& Âsd¹N¶)#ÝÃsk9G—mFÛy7ˆv-+XžÛ[Và¨ÕžØ$ë¶ß÷Òé@ˆ G«ºnpRô’ç“Ns| ¶Ý§8úus4ã3üQýæšß°ûùÝT©dÏ­{0Ƶ~¦þxj—†º“;¾;Îzm°Ï­wÞê¿Ç8¸<´¡÷5*§œ)ÿ5…iOã¯ù¿bƃ߈ÉödRn L˜Á ² ”QÆé+XxÇBνü\ûE,¶m>­}Úïû|æƒÏßôw‚ø*Œ.ƒ×F6qö¬÷úËmÛÆ²,R©T¯¤ŸV(zš#¨€Èkvà 70þ|Ö®]˲eË(//ïôþã×âÔ7ï‡øÓ%×ËÚ£i…¼‡J'K=ÄÞ/Ÿ %†QøVªÿ¦)Ž#½Â‹€dÊ!Ù^)ïõðY{ÿb¦˜hT<\VU)ŽÚKK$=#;¡äù?ðWU^ð2 )|ùp,¥ñ8Ü÷l6ðДBTñg8iRð ,?ϰÁ¶‰f³lEéDwÇg‹ #Çn¡L?©äzÇq¨¯¯Wa}…¦ #›bPq´÷OgÇX¦|xöwí.ß#mÛ&ŸÏ£ë:¦iúþpäÔ8Š"¤ÑV1hèÎØÜ¹óDØ/þôE1†ä%™ôVЇ aô/oýÞËz`Åß7™³2Ú¥xŽ)3JývH¡¥Ô\Øq„pS܇l¶Ð©§Ô9•'Ò)©2ŠSÖ2 GÊcÉ(›âë›JQ–55¢Ï²Í\.§"‘ÂãË뉈÷aAYÖ[“BXqN™®¸T$g>/®œãJ¤0"¯wøsJ$ £äy†÷ ?+'t÷Þ)ƒlºõ .ªÛÅ 3?# m7¶ÝÖ4Mñ™ÉñþÌ,«ýaùŒ"ׇŸGú‘¹ŸiÈÚˆ>%ýmÚy.é}¬Ãé¿9çæ¢zn^ç†,åãǸËǰàáŒúÍ(¿ãço÷ñ¯}ܯ¡‰g*þ^mÛT…žÕš¦ñ©'>U²Ï7ÝzÖųΜÕfŸðüÉï{Ö¹ëÈçóÔëmk*-Y±Dv¬ðÚ4le»¿|NŠF£|ãß8ªÏðX¡;ã³l_™xÓ‹¶XùuÖ´ ¨Dè©2h¢#ä\¹ÃgàŽD ?ÜÀÆYl,.Âéø\Ï©8¼@Ëhèè~m0¹nÛÛ˜~Út³ØOãg{Q욦aDE-D™ÎOÓ4_D4 Ãõóù¼¨—+kùßi˲¸äîKøcö˜¦‰eY˜¦é;[º®‹ã8XX˜Ž‰c9þ±¢Ñ(étšD"A:öSʱ'ÛÑu¼–'êF1]“M·nâ›?þ&ß°¿áGB¸–[p­d=ÉâƆaÍfÉår8ŽC2™$•J‘N§1M“U«V1{öìÞûò Žú¹Hí‚/Ÿ´«`¹eY¾Í¶¶7?ŠfHkkG9núž¦¦&ššš¨¨¨èTØØÒ¥KY¹r%Ù,¬ù¿ë¸ù´&?õ§6Û9ŽC6›%÷ŠÚ9P²¿‘)!‹1M>|—HI±|ùrª««©>D•®ŒÏºº:êêêøŸ+–ñÍÓ^ãŸYηn»­Ívr\*½¼Gte|Êë’æ9p÷œ'±'\‚®ëmŠ(·‡ëº¤=cœ|0RcYÑYä=¢·Š$º:·½à‚[˜µþËÌÿO™vñ´c¿}GŽ:¥Ž.Àx܆|¾ë‘¤±˜4º’º¢ªJ0]yf±¬3º«¹miäïÖ/~±ŒLÖ|c%7<û-F\ý x—Vjœ¿b1!¶ž‘ˆøn$“…Nx®+ö‘©T¡­H&SéÉÏ|°Î´;§õx_¤=IF^Û¶í§®N&“¬ëœqà'ÎÖ­[™8q"›Ÿ|’ðÊêÕ|åc£¦¦†T*E2™$û)q¥8!Åù¿4æ‡ ù¥`†_«H¶!½ý³Ù,‰D‚X,V0§"ˆÜN Rp‘â‚I¤  …Ó4ýï¶ÜV¶'×E£Qòù¼¿dò¯<_)ìÈë+S‡Ï[nWüW^Sõç‘ò¶mSSSC}}½ßÐåµK¥R~å²bñ7™LúŸQxšÛ¶Oøw+ž¾ƒ®{ýæûÉa,Ëò¿ƒÊ)OÑÓôÆÜv@E¨Åè:l>é¶|ýF&­K§Ó~dJo…Ž©€´"ÛÄ^åoº7>Ÿwaõ„2öŽÝf]\C¡Pt›îŒOvیɻà ㈩÷¤ˆ’J¥ü‡&Çq~Ê>…¢éêØ<é¤H¼°ƒ/Ziî¼õùþîþÑÓUÿ@NóÐq«;©»I:˜æÝ}Hwî¦ ÷ÝÔÂ7çòø½OaL|ç¹çp«ª ê)k{ö ÷»Øßÿ>š®·u4Ïdp.û"μπ~-–ÄŸJi¤ÍZ¢Xn”x\è'šø¬iëf¢MÖq~¼ öíÃ<å—˜÷^dƒûÍq,÷ðÌy›K§‹°mܱï@ûÜ'±5SJÚ–¿™½®ã‚ɸš—ήø¢u™¸ ½d ¥¶wÝÂÄ ²o²-ïôüdár¦áG»‚š8úÏÉŒÚáu|IÂZfq{š¦cºßVØ6.û-ƒùd_åqäö†”±:p`lç.ê  «ãsaóB¦Íø¤Ý ³“8ŽC>ŸÇ4Mjjj¨­­õ û2bB×uÒé4ŽãDZm›T*E4¥¦¦Ã00ÇŽå[gŸÍá·ÞB›>'Þ÷>î9’7æÎå‘éÓùPm­ÈâU[KÃí·cÕÔÇ óò¸¦iúC± F Å~).¤R)*++Ûd…2º*¼¯ëºÄb±6‘ÍùåþÅÆðÎ:\ÉýÂ"JGÛÿ ×g”ïåùš¦I£—õ$| :ê[{}PÏ=Ý·ÛJíߢ…Ëd4”Ê\¢8Vp‚Jwqž†‘»&3ÿÒµY'o0½90ð£ŸBѯLuáOS6(ñ ïºn7ZT(=ÉÞ3‹aã›°Ÿ†#ÿ“ ò¡±GSh* NÜy"S‡þŸt¢z¨T( ¦ ù†óø×Îâåˆ`0üâÅD©LDêýUcf°ä÷¿ÇÎÃ1ˆh°0 ¼:ë é7Ý϶Z°C‡3t8/ Ï[°7¹,|Õ…Yøq-$,jÂâ‹ø.à:p¾ ?K¸<\hàaÁ÷[5œùÏäÔEà†8|/ #£ðžII^ùó0ZÖå¤ÓörцCÜ•†Àò+§ó·Ì¦¬â ûþ2œ³µçøGæŒxu8''`uÞ9jGŒàÐé˜2±•C/U°Þ…S30âs»xiÝÛž=”/ääoä÷.à’ôžÌC °pãF^Ü>‰æïŽgÖSo2éïX;'Ęø¾Ý4o=@dÁ6üû;84j懲±]:c?³^nÅú¯À·O½Ÿ‡«b<•‡ ÊÞ·›g_É»öoá´ayjÿ|FlEż2þêÂ\=¹™õŸÜÍ‹7Måý Þfëĉ¬v„núxi.‡N?Âa`þOÐÓøH l8ñ᧨<‡×+Ʊ8÷/ ©d†£xöÐ!p]–ÔÕñßÃÏ‚¼Í—¼Í_~'ïÞ°g_(ã‚ëêyöEÇ× g×-såÀ–ØœõűóŽÃÃ_€Ù­CK®Ëçóž$ …¢ï±~œ;ýˆb ˆI®Üî˜OC¤P PÞÿ&ëÇ>AÙ%ƒ·¨©Bq¬²nÝLV<¶…² ÆpæÚ!|‘¾ä*´,üÍ€VO0mÀm.̵á#)X üM‡¯¦D}ä$Â8šÂˆºÌ•À~‡ïj0)'ga^nÕᦸkbÀ{œ.ö™dÀO4ønT[Ÿb YD=ëŸ÷Äà—\YwjPÉDÞÌÁW~÷DDz¸ãZQ â6æqËUð›šQlº Þ]Ä3ç¹Å‚;rð-cÚ¦MÔZ»új¶8ðK]Ý¿c3¢–Dx39‰G,ø²cãðS ËLÞï·€U—¾Mþ„)üt„èû͵ÐhŽáÉûÞæc'Žá]ñרŸ<™*Mì÷ ÏÛvbé-z¯4A-i°u¸!²$uhN Ãé÷½õFh[ÿ¯·ÏCÞ±ô¢¶ã9˜\ìí£f=Ü üËëtqÊʾeÄ>¦·½†°Q~ ø+àΘvõÕD½~Jão%óösD >êwÔ;ž­Á™Àa¦ùýÔ€îr†p&åF£> £Gcz}k¬É“ŵý¿åÁ1›E?â$2PãõAó"ˆÒ^?4 ¾ý»¡ÜÃt¦àxþ€–繇©8×CŽaØ@Ì„ZS\ªQ£H̘6c†0ZçľQDóC|($ž†A&“鵚F …¢sØ@|¼8æÅ‹ÿÉ´¹\N ¡ E/sâÎl:T5…bòúÆÉ\øÌŸ™÷¡óùt|Ù,œ§Á7jáL]ÜW¥)5J "@­÷7ƒ¤{B‚B‘Dí/ѽíåvá÷ÑÐ1Sƒ Ñvö o/jKkg]ªh»RçYÜÏx'ö)¾6ÝÙ§½óìhÿðù˜ØG+Ú®³ŸÑκâÏ3,¸…÷¶³OøûîÝÿ{÷ÛÆuØü'Mœ&¡*ÇMºÔDZµÑ P]×’KRþQ µY–4F$¡À€ŠDÃP!1 Xå*H0×AP@äNÍ"û£E$LL¬5$fÒ®¼µi6ö5kœxfxv×I|ûC~gRâã‘wïõýF"R"ßݽï½{ïÝ=årétå«Ç¹CCCþ¼Òzp°ùdÑUnž>Üh?&4ÛÅZüMÂÆïµ˜žB³‰Ý›'n¹xè¡–¿³ý³jËÓìt—©S(¼ò À[¶¶d‹{ÞÄØ¾}¸rõµr¹Œ\.Ç[J“¯ô̈́ʯ]}ð—Ïç‡9hK$Ñ»ÿû!þ¸G¯{-‹µ<žˆ¼±· äö~ åâ¿5Íd¥Ra;Jä¡÷n¼¥‹eƒˆø›à:¾ôÆŸâî1`Îl}Rz+*=APœÝMÞbOÈ}Åbápxë¡î±oO¤€ÝÜ‹Ž/æ/ë^ç³uÉoötÿòý´|üÆ÷ënP,Q.—ÙhÉvý xë ïX?–Ëeäóù.>ˆzåýŸ_ÄŸ])7œL)‹ˆD"œP!òØåË—™9"E™{þ·\?ŽÁ/[1 "ÍÏÏ£R©`bb"R@À¹µ*.fë^ŸŸŸ·®$#ò‹¾¸Bå÷€‹¡OÔ5’ËËËXZZb‡”H¢Wï¾ccÃGÕ?¯{—rÉW`¼ T¯¿ÕäÛ¹¹9>ÇÈcçÏŸgîˆõËOþ§â§ð|GvQ<%Îô®Ýbpp°îõr¹ŒJ¥‚p8\÷;âob±˜u£x½X,bpp•JÅz]ü¿øLñ°u˦r¹Œ¡¡!ë»ÅkÇ*•JÃ×k¿shh•Jåráp¸îdÌÁÁAkjßß?88h½žÏç­Ï/þ¿\ÞyÒÊößË&–E¼V»Ìâä–t:-»*øF,c[J¤ K?¹‚~æ%üýÕŸ+• ÇnÉ—úbBeß_ú§~¡ÁkL$ $‘~ôý›ðÍØê\är9är9?~\v±ˆv½ €ýg/`Oে¯¯RA:æ¥×DÜ~ûí®Üã] Öú ét±XlÇŸTœ˜˜Ø1xY,­¾¥¥%ÌÏÏ#‘HÔ}V,C.—«„¬ˆ²Þˆ±XÌȶŽÄkâØ¾\.cbbóóóX]]E:F"‘Àüü<æææ0??o•iuuËËËÖ€(P?([ûYâojÿ»¼¼\7¼}`7‹ayy«««8|ø0677‰DêþV †ær9,--arr'OžD$±þnnn®®LµƒÆKKK8|ø0VWW166†ÍÍM«|µë·Q¾ÚϨ]ÆÚò‰mð / ÊŽ‚’~ûÎoñÅO}±«Ï(‹V=DýÊårVù›››«Ûî¢?~Üz.a±XD,C±X¬ûÜÚ‰Qÿjs111aÕÛÇ[ïOLLÔM‚[µ“ ¢ÜÅbÑ*çòòrÝk3:88hý<99‰¥¥%¤Óië»jó%r)–«6år‰DÂÚ'äóyT*ëþûbŸ”Ëå‡166f-—د„ÃaÌÏÏ[+âîáp¸î†vì&''±¹¹‰ååe«µû-±~DÙÄú²rÖhŸ"êE,«ÛŠõQ;ÉB­‰mË[L©çÒ{×cÿý÷X?‹}3Ÿ×I~siš¦ìBt#ã¹[áƒÛÏá÷Oì°u0²¼¼ìé íÜ}©+•J!²ã¹M¡PÀ·o¸¯ýígñ/ÿü&&&vœ•Fä¶x<ŽcÇŽÉ.†râñ8¾zì àgKŸÃ믿^÷¾˜ãýLÈ%…B…BÉdRvQ”ãd¿%7Å ¦=|ø0‰DÝ™×b@N ¢‹¿Ú3°ÅÀL$Ög§Óiëïæææ¬ 1˜(&Zr¹œ5X811Q7I#΃¦µƒŠâ»‹Å¢uEëö³¾ÅYðµƒÐb0¹ö*ØVǵgÖ×–­ÝznvÂVí:«}Ml›NΔ®-['u W'“ñض±B¡€ï}ï{xôÑGm ÔŠ}1Ñ766†ÕÕÕÙÛ~µ‚˜Ù>¸T{5Åv"wco¿ŠÄŽF²­8©Ë€³úÜéw‰õìÕU ½êñض1±^Ää'SÈk<¶mNä3ø»Èð¯¯`ii©e»FÔKnÛöÅ*—®{>qÙú9ŸÏó x"<ü£×pé«ã066¶cà–ˆä((ü0ô¥ú‹t:r¹ìÊòDÔ1(&7&''­³Á777­É‰ÍÍ­Ó|Nž<Ùö3Û ŠA)qÅÚö}ƒ˜À¿'þÛnB¶]çÙÎíAÅ€«xÞ>Ûj@¶öûíp¶ú¼F¥ƒƒƒŽ œü ¯Ì÷Æý÷ßßt VäS\ $ø‰Âá0Î;gë;šmÿVõÉIq2àÜéd€ÓA2'õ¹Óïòzõ†¸2ˆÔóêÏâæ;/XÍårœP!ßê‹ •‹“Áüäõ_BMDrì}΀Qùb±Ç€D*y8Ѭ;€´|Α:Ä­lÂá°uk)ñ|#q’B³ ;xÕ(QwÄÕX"Ÿ›››u“H'òŽ˜À$"õÜüÑ~ÜùWïXí"oõE~¶GvºuËå[p[ª‚îÜZ”b±È@)âÃê ^ÿàÓ¶ÎzÏçó²‹DDWßþÿzç/êzr¹œõ@T"’OÜ{_Ü?ÿøñ㎯z ¢Þ·ç·ÎÚÜÜìø¶[DÔ;ù|étZv1ˆ¨‰'ÿ xå…k'LNNÊ.‘c¾ŸP€sÅ[qûùó®Ý?¶Œ­î‘<Æ[Wpiïl5š<ëHç^ªâßÿïyë’ëùùy ñ¤"ET*ëD„¥¥%Þ„H1ccc(—ËX]]å$ ‘Âá0ŸÿG¤0—Ø{¬…ˆüÊ÷·üzïÆ÷pã§/!àã—.aýÛßLˆ šÔIb˜Hœ×· @ ñ^ý—¾ú·¨y=õoQ?QS'nˆšùï+áÖÏh(—ËÈårÖý׉H¾{~ð&ôÎÖ]rÍ["5”Ëe>wŒHQ•Jóóó¶žQDDÞ™œœd“HQËo/Ï݈‡|€­çMLLðªkò-å&Tt]‡®ëƒƒmßüÃ]¸bšØ·o>vö,¾~àöÂÖÄÈ ¶&M¯¾&&ZÊWÿM8|õ½ÊÕ׊W?_L˜„±5©"&OjÏAïõ»NóYý“ öP©TxÖ;‘Ë:Íç§~ó`xëêÎùùy„ÃažaKä‚N³ l ØŠË‘{œäSçææøÌ""8i;Ëoøp.„r¹ŒD"Á“ùÈ×”šPÉf³H¥RA©TB2™ÄÔÔTË¿ùÝç?½Ãoâ̙˘}ûmؿߺÒd×&:Ê5¯Qçœäóâ'ÿ·~á«X^^æåœD.r’Ï—ÿpøæ[ÖÀh‰zÏI6ÏŸ?ÉÉI^Bä2'ù|õÕWqöìY,--É.>Q_s’O˹ÏI6àÚ{¸gÏ«ûÜç0?3ÃnÉ÷”šPI¥RXYYA4…¦i8tè¢ÑhËÏ÷n}Ÿ~à.Ü÷ƒg0ýÈ#hv>‚¬ó4MC(’ôíí†jµj{VYÕ×áná$Ÿ÷Üsî»ï><ðÀ²‹ßêuK×u È.JC~ØìNòyÓ]ÿƒ‡úyäœ>ÞÓÏUfB¥Z­îxÍÎåLýpK"Õ9Éçc=†Ç{Lvщúž“|>ûì³²‹MÔ÷xlK¤.'ù|ðÁñàƒÊ.:Qßã±-‘šœÛjÚÏe¨ç”¹å×ÀÀÀŽ×ÚÍr‘7˜O"u1ŸDjb6‰ÔÅ|©‹ù$R³It2*¡PhGUèÑnÁ|©‹ù$R³I¤.æ“H]Ì'‘š˜M¢k”™P‰F£¨V«ÖÃŒ4Mƒ®ë=¿ÇuŽù$RóI¤&f“H]Ì'‘º˜O"51›D×(ó H&“˜ÅÈÈJ¥’É$€ìb˜O"•1ŸDjb6‰ÔÅ|©‹ù$R³I´å:Ó4MÙ…¨¥ë:t]G0äecDŠa>‰ÔÅ|©‰Ù$RóI¤.æ“HMÌ&‘‚*DDDDDDDDDDDDªQæ*DDDDDDDDDDDDªâ„ QœP!"""""""""""jãú'žxâ Ù…ð+]סišõ0¦fïÀÀÀ@Çï÷’¦iØ»w/nºé&¥ÊgŠÅ" ÃÀwÜÑQ¼\ä?ÝäSv6í”Av>U(ùW«|ªT·œäSv6U[‡Ô?ÜÊ­¬úèF¾½^·Úiî#üÅÍ>©Jùì6^.‹›}\æÓ_Üì“ʨ nô]Uj;»-+ó¹“ ëÄ0 ¼ýöÛʶª÷5MÃk¯½¦ü¸­çck&9rôèQ3‰˜ÓÓÓæèè¨ùðÛÕjÕzmmÍz?‰˜kkkußîý^:}ú´‰DÌ'N(U¾R©T·l—ÁËõGþÓM>egÓNdçS…ò‘µÊ§JuËI>egSµuHýíÜʪnäÛëeq«æ>Â_Ü쓪”Ïnóç岸ÙÇe>ýÅÍ>©ŒºàFßU¥¶ÓÛDuª¬“£GšGí¸|^”_õ¾ñ‚9::ªü¸­Œ±5N¨8púôisxxØ,•JÖk£££f:¶~®Ý¥RÉ6OŸ>mûý^£¶b©P¾ÚuV­VÍÑÑQs}}ÝV¼\ä/ÝæSv6í”Av>U(ùS»|ªT·œäSv6U[‡ÔÜÌ­¬úèF¾½^·Úiî#üÃí>©Jùì6^.‹›}\æÓ?Üî“ʨ nô]Uj;ý¸MT'{¬­­™ßúÖ·Ìááá†*²·©ê}c1)&x•W•|Ë[ã3TÐuÑh¡PÈzíàÁƒ¨V«€B¡€D£Q@(B(B¡P°õ~/¥R)„B!ŒŒŒX¯©P¾B¡€jµŠ™™@ @>ŸÇÁƒÛ–ÁËõGþÓM>eg³]ùì¼ß ­ò©BùÈ¿ZåS¥ºå$Ÿ²³ig1Ÿä„[¹•UÝÈ·×ËâV;Í}„¿¸Ù'U)ŸÝæÏËeq³Ë|ú‹›}RuÁ¾«Jm§·‰êTX'###˜ššªË¡ÝòyQ~Õûƺ®cjj @¬Û‘qlm 'TˆF£8vì˜õ³aØØØ°*—¦i;î{700]×m½ß+š¦acc‰DbÇë²Ë§ë:FFFÍfÇ1;;[Wi[•Á«õGþÔM>eg³]ùì¼ß ­ò©BùÈ¿ZåS•ºå4Ÿ²³ig1Ÿä„[¹•QÝÊ·×ËâV;Í}„¿¸Ù'U)ŸÝæÏËeq³Ë|ú‹›}R¯ë‚[}W•ÚÎnËÊ|î¤Â: …BˆF£ Ÿ‹¡Â6U½o|ðàA$“I†B¡`M\ˆ ò-sl*]ÚØØÀ¡C‡F155àÚl]­ÚÔîý^0 ³³³XYY±fí~¿åÓuÝšµœ™™A0D<·*n«2xQ>êæSv6í”Av>U(õ‡íùT¡nu“OÙÙ´S擺ÕËÜz]ÝÌ·×ËâV;Í}„õºOªR>»ÍŸ—Ëâf—ùô¯^÷I½¬ nö]Uj;»-+ó¹“êëDµmªbßXÐu™LÖdJ»2¨ÞwïE9¡âaˆÇãH¥RX\\Äââ¢õ^£ÙÏÚ®vï÷B:F(².«V«Ð4 š¦)Q>`«¢®¬¬ "™Lbjj Ùl¶m¼*ù—Ó|ÊΦ2ÈΧ*å#ÿj–OêV7ù”MUÖ!õ'7rëu}t3ß2²åF;Í}„ÿ¸Õ'U)ŸÝæÏëeq«Ë|ú[}R/ë‚›}W•ÚÎnËÊ|î¤ú:Qe›ªÜ7B¡Ž;†§Ÿ~ÊŒÛÊ[ㄊCÓÓÓƒÈçóu3tÀVeÛ¾ªÕª5ÓÕîý^1 ™L™Lº®c}}ëëëJ”/î˜A¬ý¹U¼Zä_Nó);›íÊgçý^h•OÊGþÖ,ŸªÔ-§ù”M•Ö!õ7r+£>º•o¯—Å­všûÿq«OªR>»ÍŸ—Ëâf—ùô·ú¤^×·ú®*µÝ–•ùÜIõu¢Ê6U¹oœÍf‘Éd¬Ÿ@Ý÷ªo©ck¶]OuÖÖÖÌÑÑQóĉuÿNŸ>mýN$1Oœ8aš¦i–J%3‰˜ÕjÕöû½6==m}Ÿ å«V«f$1K¥’õóè訹¶¶f« ^¯?ònó);›vÊ ;Ÿ²ËGþÕ.ŸªÕ­Nó);›*®Cò?7s+³>ö:ß^.‹›í4÷þávŸT¥|v›?¯–Åí>.óén÷IeÕ…^÷]Uj;ýºMT¦Ê:™žž6=ÚqùÜ.¿ê}cQ>ñ™ªÛz=¶Æ Ž=jïøWеµ53‰˜ÓÓÓf$©«pvÞïµíK…ò­­­™ÃÃÃæôô´9::j.,,Ø.ƒ×ëü£Û|ÊΦ2ÈΧ å#j—OÕêV§ù”M×!ùŸ›¹•Y{o¯—Å­všûÿp»OªR>»ÍŸ—Ëâf—ùô·û¤²êB¯û®*µ~Ý&*Se4›P‘½MýÐ7Yß¡ò¸­×ck×™¦iöôz²èº]× ^2ÔîýÝP>ñ…B•Aöú#S½n©žOÊGýÉuKöþ£›¶S•uHý¥›:§Z}즬^/‹[í´jÛ„ºÓ/u¡Ûüy¹,nöqUÚ&Ô½~© ~ÚÏ0ŸÞR}¨¾MU(Ÿ¦iÖ­°TÏ·—ë*DDDDDDDDDDDDmð¡ôDDDDDDDDDDDDmpB…ˆˆˆˆˆˆˆˆˆˆˆ¨ N¨µÁ """""""""""¢68¡²‹hš†B¡Ã0¤–C×u¤R)Ù«ƒHÃ0P(P(deæ“TæUý%"rÒÎzÙþqC»]§ýRæ“üÊo}+UÆŒj©Üw&ò3¿íŸTà •]À0 ÄãqLOOãÈ‘#…¦iÒÊ£ë:2™ŒìÕB$E6›Åèè(Ž9‚ÙÙYÄb1©yÜŽù$•yU?Óé4âñ¸ìÅ%"œ¶³^¶ÜÇÐnå´_Ê|’_ù¥o¥Ú˜‘ zß™ÈÏü²R'Tv1ãøì³Ï"ŸÏc||³³³²‹E´+¥R)$ äóy¼øâ‹…B<+€H!…B–D>¦z;Ë} ífª÷K™OÚ­Tͦêm:í^œP‘$•JÁ0 ¤R)Äãqd³Y@&“A<·Þï–aÈf³H&“€™™IU½®Ÿ†a`vvÉdrÇ{ªäÓ«¶™¨‘N뺌cÌVíl§ŸÓëö¯Õ>†¨í2¥Bf§_ÚÉg1ŸäGên»¶Rõlú¡M'ê5¯Çg¼èrì§3œP‘$“É`vv…B8rä:]× …Íf±°°Ðõ÷”J%@(ª»ïdíb³3q2™ P­VFQ(z~–‚a˜žžÞÑPÉäf݃V ÃÀúúºu°Úê¬8¯öµ˜OR™õsaaSSS ?O•|zÑ65Ói]—qŒÙªµË­ö¯Õ>†¨í2¥Bf§_jóI~Õ¬î¶j+ýMÕÛt"7x=>ãvc?»Avv³ƒbjj ¬ÀÅÅE[ ÇÆÆF×ß!f,:d½¦i­ïN&“MË`0h½ ] ìÈȈµÜDªp«î¯¬¬`zzÚ:hƒxúé§´Î"àÍ>C`>IenÔÏL&]×±²²ÒðÌ7•òéfÛLÔN'u]Æ1f«vÖ·Ú¿vû¢nµÊ” m˜~©Ï`>ÉZÕÝVùôK6UmÓ‰ÜäeÿO|¦9ãØ3œP‘( Öý\; ¸ý=¡P(4}HÞÌÌÌŽ†Xœm0>>Ž™™[Œ©T ãããÖ%ÍD£Qëÿ›ýn§e¦§§¡i‰„»+šÈ7ê¾aXXXÀøø¸ufM*•Âìì,Ž;Ö¶L^ì3æ“Tf§~vR÷5MC6›ÅÊÊŠã2y™O;û'"·8©ë¨ØÎ½ß¿½ÙǵÓMÛà‡~)À|’9í[ù%›ª¶éDnrzLìVc?ÞℊÏD£Q¼òÊ+ý~&“±F`+H©T ¥R©.^•IA4E*•B4å ùN§u}}º®×U³²²‚X,MÓ\¹´’ù¤~d§~vR÷×××°¾¾ŽõõuëL=ñù½h+qšO¢ÝBF;Ûëý‹(—Œ} ‘›dôK™Oò+/ûV*Ž9)—Œ¾3‘ÜêrìÇ[œPñ]×­‡m×è€o``ÀÖì¾E¯\Ôi™q)ÙÆÆÒé4H¾ÓiÝ×u}Ç™ âçjµªDæ“Tf§~vR÷e –8Í'Ñn!£íõþE¼FÔodôK™Oò+/ûV*Ž9)—Œ¾3‘ÜêrìÇ[|(}Ÿ …BƒH§ÓÖkét@À S¡P@*•’VÆÅÅEd2랃Dýj||š¦ÕÝK3“É `ddDza>Ie½ªŸÑhÔºu2™´n+L&•i+‰üÈëÜ´kg ›Í6ílÖêeûggCä&Ú°výR»Ù˜Oò¯FuWv>íŒu’Ï^±Ó¦Qïpì§3¼BÅgjBd—x—hˆªÕ*ž|òIëýB¡€L&ãxÒI™jE£QLMMaaa#_é´î‡B!,..bvv¡P†a Z­"™L"tÅ^”q;æ“TÖª~v[÷·S1ŸDªóú³]; À:n÷ ]/÷/DnS¥ kÕ/µ›M€ù$ÿjTw{O7ÆŒ:Ég¯Êe§M'ò#·Ú)Žýxë:Ó4MÙ… ÷†a=lldddG”J¥xàIä‘Vyd‰ÔÅ|uNFnÚ÷Æãq>ЖvUÚ°Vùd6i·R!Ÿª¶íÊED$¯PÙ%j/×Ü®P(¸rL"j¬Y™E"u1ŸD“•›Vǽ™L¦«3l‰üH¥6¬Y>™MÚ­Tɧªmg«rÉÂ+TˆˆˆˆˆˆˆˆˆˆˆˆÚàC鉈ˆˆˆˆˆˆˆˆˆˆÚà„ QœP!"""""""""""jƒ*DDDDDDDDDDDDmpB…ˆˆˆˆˆˆˆˆˆˆˆ¨ÿ|~+…Þ&ãa%tEXtdate:create2020-03-05T16:38:18-06:00n;×+%tEXtdate:modify2020-03-05T16:38:18-06:00fo—-tEXticc:copyrightCopyright Artifex Software 2011ºÅ´1tEXticc:descriptionArtifex Software sRGB ICC Profile †2tEXticc:manufacturerArtifex Software sRGB ICC Profile\~=Ÿ+tEXticc:modelArtifex Software sRGB ICC Profile1(‚¡!tEXtpdf:HiResBoundingBox1584x864+0+0û8²ùtEXtpdf:VersionPDF-1.7 7ji»IEND®B`‚blis-0.9.0/docs/graphs/sup/dgemm_rrr_has_nt12.pdf000066400000000000000000005166431422157504600216710ustar00rootroot00000000000000%PDF-1.7 %Çì¢ 5 0 obj <> stream xœÜ½K¯v9r¥7¯_ñ³uzóNN Ø 4 ØîÔ¬Ñè$ h•lµ<ðß7#ÖZAʬ.†¡K~onî7ɇ+"øß>ÏWú<ö?üïßÿËþÝŸú¿þ>ö?ÿöOøS*éùü)¯ç“fÏgåò|þíÿð¿ÿÚŸÒ³òWYŸ>ŸçköÏ¿ü!·™¿V ËŸÃ2Óó쟿v‹¨@Ñ>ÿ÷öµ×µžüùé?þã¿ÿ™:%µ¯aòã»âSd>³í'ã%Z›_éUOX®zhS=úyêÉO._ëua9õÈÆzâçUOëk¼ê ËUmªG?O=ö¬æÊýóÓì—ÿßö£ð†Áÿüý¿|þ‡¿ÛMd~RþüÝ~cøãþó>¥=Óž¾ö³ûüÝ¿üá?ýðüñOyÔý ëÍþùUJé°Æ?ÓìûGú!ýR»lí«»ì/Ö›‡ý»þç¿ûøÿîÿÛÏ5ƒôì"Wsüñ'MÔÚ_Ÿ_O}•RUãéùkÌS• wU§ªºKEU%ׯ‘®ªhxU…¢ª«TTÕfÿê媊†WUQ(ªºJEU³Î¯Ö®ªhxU…¢ª«Ôom?«å²ï¤ï7üìç|ÚO¼Æ?OîûcÊûÀØýÞb¢àƒrÅò_(–&Ê•¿PN§­¿ÚÌþÓ'u»£ÿ¼ÿïþ?ÿá7u„?é¾u{?þJ/E~®ñ~«åWÞFùò÷aïâOöRfÁ OÝï´à…üû?æç«æ<~øŸþX¿V™å‡ÿùy“kŒþ—øãÿº?Õú5÷§ýÃçŸÿn?­ýrKš?üýÿTž¯ò”þÏ8üßþ˜××OúáwÁ'}í=+.÷÷ôG©ïËNûÖw¥iàòÿἺ:ÿüÇ?¶þÿüñOÿlëõïÿrÊýVÎÿßeü·«ì/ýû*~WÝ¿Uý¯ç÷?ÿëϵ,´©ÇÚÔç¿ò‘`€[_Ó»¨dŸ¿Ö¼`©ËÆÍ´ßÂð¶‘¿rwKÞÿ‚¡eÖW÷"eŸØ-eìAbêî¡ÝPëWëfÙ/­º¥å¯ÇËô¯9`Y_ÕËÌ/z߯ÀF¥GÕŒ]á0KþªÍ-3}M»š}™ ¼ª<ÍÒíÂͲûˆaýõ~¥nÈûº’Éé+û©rJÖ‡mKå]æ]ø±'±¿a¿à¼ÿÑìaíXý.sáè[òŽ©É.kÆnϰÌ/+±Ç2\Ýî꾊©EEzù²kÙ%ËtÃØWeEÚcß [¦uÖÛ²Û&δûÜdÏj?³ŽjVùêVfW—ý‚‹½U+ÓÛHa™öÊúÅîÍ,{À_ö@wï9ý¦Êž/T{cñ’˾áiWÈeÚ[î{ ·CÍR› KÛR1¤Òü"ú²6‚2ýÙ_+,¥Ã²'8^f79¿…bƒ´¦*Þ}ɳŸÄJºï²ž/3dÿƒ†w]fI^KÝMl¿}íËöÁ2ÕÝZfG™KöÕ×~Ĩ§î/hX™ý^ÔSÚWö2wU÷[ìÃ,Ù§@©îÃ÷Iû²›CÅm|µi–ÎçY»u]Û²›.¾¨:vãµ2»}hÙ}•™•o³Î‰ÂãeͲî´9Àî£Ñ¬›}‘^¦ò’Û³ìoÛ2íƒ4KÚwÒ~g(²x·"»5w¤­ØÝlÃä‹ieÙ·ºûï=Óó{huØ·êe²ßykÕ¾Õñì–Þp¦=[Vf79aYö±úÉñØÛèö±Žg?7T¼o8Llx +Ù·º-ê:Úî¤öÇ:žÝ­=ÞŒûãŽ]f±3éûëìQL¾™¾¿ìfOkÚô–ië¶ ›W›¥tûZ·¥ðiõýò½Èâ÷–ìki?ꄊ÷´|šaØ7j†ý¦³IÞÀͲ¿.ÿv¿£ËÛÔþZ·%ó£ß“}­ãÙ]-ËÛøØßßï~”öµn˾9ÿöiíËûEM”Ù϶Z™ý†ð‚ǧ]án¾~òQ¼WÖ'£kÕ¿Œ}Pã×9v糿×mé¼äa­~™eZc0ËîX’•±I¨?‹1ö-ÛÕXæ¿§}MÃúmÜÔØ°à†‡Ox,Lývý¼^›sT{ZÓûd· û\÷ïvè'2,)VfKÕ/fî1hX™19äX·œ­ÌЛ±^¸ÛÓÚçäQÖ¢íiíËB«˜ûSnö(v«@ûZŸ‚£ŽÚœ±¿Áa£F‹9lc–‡ofNÌ{³}0øÐ:l`°,Z·¥Ø)·e=>´Ÿ’—YɆV¯÷°’­»ˆÍnÝ’mhÝBŸâ*>´îƒ†j©>´úŬ ‹­ûÜ™7¾š­#—deÍÒ}lÝ–Æq} [½ÌD™ÝQe/³84­éc붨#XË_äÈ™ŸÕ¾\w™Žž~[–ÝÎð4¹%ùè:r]xÈ×m)ö$ÍR|xÝ–^‡»>VíWäÃëþ®’5V³xëÜ_E±?˜¡ûðº-l^ÛâÃëȽ£kØÒ‡×mÙÁO^÷Q˜œd;ÃãEŒ®Ûâ£ëÈûûO~*c[û^mˆw¬Þ­Á‡ý]¦c´ßoÄG×m©¼À”½M<ZA¶oÙ>ؼωߣ“½ÈmaO­O°6¯©š›°cÏ–ñeeû~:Þî* G÷É—µM³L`÷¹:äì_†[ƦlmѾؼ¿ró~WþÅ–Ý1ÀÛ° ‡zÛâã«©~ 9ûøº-ª8_GÙ½¹Or®>Àn˾µ;ºæe’}pfi>Àn¢möQš¥û égO0øøêñäãëf tf9OŒ¯Öy9 ãkq¼€ãkÙZý(»x^^¹]»}°ÅúX¿š’}|-6±¨0`|µ‰”OPöW€ñÕ¦MþéåR1¾õëû«ÄøZlŠ£ÆW«m½tŒ¯0Ù7ƒÖÎ…;/»UŒ |pÉlÙ-Í¢, °~=f¨6ÅðFú`pß_ز¿&léjÈ5c€-}`œÙŸ²°eW“QMÅkç.´ø[8ÇÚß:Æ×²[sʼn:Æ×‚0ËÀøj“ÌÔaÁøjÏ÷T'ÆW»`4¥º0¾nXå›iÆ×Ò3Ÿq{0¾<¹%Œ¯VÓ¹e °» ái5Ì<í•ãçôoµì¾ •VŒ­ör;Š4Œ­v¹ –îc«µšŒóv ®Ö|Ö˜mM«]/){v7Ù±ˆòŸŒvå†>ö|ã@ ‡÷7<&NøjÒzq fº7b´¿9Äyq`zƒà60«> ˜ðÑ_ (þ9 ØÐ*.ôïä&Ak¼ä>‘`ú"$ ‰÷PŒ J =(˜tQpw¾ @)ܽ{ç ÙM´µPÂ!QÐflŸ›Í€ZD‚MÐ$¸-4wÛÁ8 ؆N ¸?¼‡äGìZlì^ ÚÉ? N›âû-§ Êçî:Дˆ‚s£&ŽBA³€óˆ‚s¨ù ­ˆ¶‚6_ë 6¢àœS(8÷ø†Û Î) ZEœ« ï œ{tœ¤C° Oü`! Î51c|4A´i1Ê·¥p̓(¸±øa£% v›?>„Cª¶Em (¸ šé®A.@ÁÍÉ•‚(¸-m…‚›®_'QЧHÜ–ÎAô“Ï·e’8È‚û¨G° [À dA? YÐÏŽ6ItÚÇŒ”0¸-/‹0èe|U0¸ï+MÁ‚~ŸÀb²à¶> ° Š| nCÇ4M(èÇꈂ^@ t–•H‚Û²ø°H‚Ý&öèÜ–ÁFAtKºIÐ-è<ˆ‚Ýp†(è´ ¢à¶t,j‘qÐ瀠Ð}5E†‰…ûøqÁN‚¾t‚fCôå• vC"Hp[_7IÐ-< $¸-Õô©C‚~9‹–Á…›Äσ$ègÇê#IЯ͘$è/IÐo‹ô DÜ–…iPp[&Wˆ‚nÁ8Dܯ>ùùèj´P¢ /6á’‚þ,¦×KÜE4è½ò#PÐ-¨$èañ‰$Øí¿<$èËZ¬$¸-ƒ‡$èTìkpK ¸‹,Îö‚ÛÒ0‰!ºó{iœ¾¤†ƒÀ^&Ñâc«_žOŸÈ~¦vq ß¦eä@· `à6H^-.è·¸È|Y×þÆM¸–›ýr8 è– ìúQù¦@¿ÌrI^†ø ô³g”i\fŸ)ÐßæÆ Àm(øV\ Y0Šãù ž3 £ žŠ…‚×QDÁsOBÁsòvÕqénH/¼®o¾Õ Áøžƒãu ^–tUÔ#<õˆ½ûû\ 8CIÆ( xYÚ5¦éú{L ¼Î=®1e¦ÆTµqàiŽâÀóbÈçÜâÀs9ð6œQOK S‡A·Üz , ¸¶âSm·è,¦ˆ¯zH‚Þu€ûæ\ nbÁ•ºIлÜ zcX¥3¸B' ^–ÂÁ5ÈE‚n¹IÐ;~i\ÃÒ5¸ê] Ý1rhp ËÔàšùö„‚§ŒXÐ,/Ee> š‚_Öàš¸¨ œ™ª¦HÐ `k‘ ëN/tè¢ÈÁ•$hÂâààšÈãáÛk>¶ŸÁøßß}B} ¼áÏ\,ßZ`‚âì—ɬþò#íð· ù-f¡KÀß)#ø3à-fŠÕþÌBP Q§€?{€HÁŸ] à*¤@-…ü™ºÿ¹Ù/-zûm ýFÅ~Û’Hz¢¬ÌË+ô$ö³ƒp*²ŸèÊ!*M¹ŸŠýÎAb¿£fŠýL´…WhÆ…Øå9*øÛgz‹{:ß^¡û¥Qú»ÅÀÏÍ~F9ßÄÀ!]Oì·Û-ÞÞå_,ö3€1ÄÀÉéÎ%ö—_¨ÍÊ 4û™Û%°)Ä@.…-0Ñcö¥Bù»´ÀñÖçTÅ¡&:`úM,%ò³°œ\äg!Rè·ž7ù-Œüvk†èJàóÈUSä·´ð!ò[“rXß¾ÞFá‹•æ÷ˆ"Rú{%ðIrûÉé(v5Ÿ›þöëÁr@Op¨„@Óÿo§P·P> !+ËG47¸šeÞ^¡Û¢‡B  §I »¹ b ûÜX !p×B/Q¬U>K )!Ð|Bqf :ÇÑ®á!pÏñ%„(_§#î™q&ìq±rWüPäb%†ß ÿìr°dB 9VÊ$¦ñö õzÐ „hí´')p?¾rù„nC•Û¨¤ÀˆH)p× wÊ÷(BÉLR`–ÿxH¡v;…ÂJ“˜¢v”@ë·i¡˜éžB`VWB`–{vIÍ/„@fq”„@‹«z 6ÂÜ>¡Ý` o/„À=ŒÐ›SB Ý (B õMo!Ð`èsàÏ.†Ð&Ð\â &JÌz/¡fª×¡Ú™?ú-¼¥Ð1ä]ä·Ì-×* Ðøù«…ߤ4À}ÞI÷Pj€6'…4'Ðî$Eð³zÖ[ÌC5STdÛÍ7E(ƒDÀÌý¨€]¸>É€» æÃ¡ÊÁáè€yJ¤”h×÷¹Øïœ*dÀp0 0 CÜÿ%‘IÌü. ˜§Ž!–î¡” }wBܧʷ3¨_ñ¤ê°„#ªdÀ’ !:ŠÐÎô–‹cCÜeÒ þ· hËêŸ þüŠvRm´ºA»}8H" ÍÀogP·”ÛÔ¯æå Š7CÉãj©tû Ðäƒþì (¶!Zw E@{op;Ï[ÜÈs;ƒº¼ƒƒ$šÿ‹ýÌÒÀl·åvuC%–!-Q"`¡KÁK“œ'°ès ЦFÀ/‰€z ¡–Áf, °Ðéh€ÖyáLÔ%PD" 5Ô+ÐD z~ÊÁ¦Rg ОÖí z=­ãÅ„ Í$TÀÂÈ€£nË|¡Ÿ…Ï,TÀB§È£–‡M=TÀø8CÜeвÅ~ûÒçíz[È~Ýðf? ?ûm*àó3*`·‡ôÁÉð“[¤›(I°†6'lRÙD‚p6 ìòK  æ Üñó¦À©A1(pr`´¸T#à‚wçýòµ¹hyyƒÚÔi¼ô?ë~1·FS4ßúd’×”Gô1Õ4†.ØlïŠ ÜÅæ‘ÇSéñ-ô+І`Àñ´$  èáRãöÏ>šA}`ÀñÃ=^ ÷@ô¥G²Ií€Ã^!½4Á€Û289&"lèŽ ô œÛtì™+ù 8l@³!"(ç’ÿFÎò#7° Mô’qûƒŽ¼[ÃþÀ€YÑè!ŠÐ…¼äêD„O?à­2tÁþ x&xv0 ÇM`&L%¦‘„À=?_”Õ ÷¹X/؈=^ÁvÉ´08°Ú:îçpà°Ï >¢ ´†ó ´o ­„¡ö ð¹*4°vzà*2°ú‡}pßO—û%íêˆÇÀ@ûŒó­úå¿ÜAýbrÈÀ@{â/ ÜÏWË[ ´¦¨R``í4IZ“EÅŒ ¬ãÖÿ†MIž[ÿÛu0+¢½Í|ýa×WP`-ú,hÍNã ¬æßJÞCP`Ýã-x1Õ( gfL ·;œ‰1ö‰| ôS߸ÏTøèh/2ßž Þ±0äŽ!eÉÇJ!Õ LÅÀªøæ ¬‡È ,+H!vÅpÌRH`±ù:ð!•é""кVˆÀœ"kÆ¢Oú FÚ]’.Xm% 8LjÀš¸Õ扞Š!·)°êËŒhÀªIÑ€eÐs5¢51=x™QûCÁ%GD Mg‰ˆÌ«*Z‘Y9@˜5tGH Íµ½ÿx²³íéüóÎú³'ŸÉúç“^H–Èšö˱ˆ Ä'ûÌý ùÖ~Z÷±œ¼d¯œ"W^²b³¥ñª',W=´©ý<õTËtÐ^÷–Sl¬'~^õt,%^õ„媇6Õ£Ÿë|kÅF={¦]¾µúsùÖRûöÏïùÖ¶µýRY¤+Ê‘®èçšAmêNÚ«ïmÕ¢}*¯Bªê¤RSUw*5UuJ±ª»PT©Ô¢ª+•ZT¥TÕU(ªŠTjQÕ•J-ªŠRªê*UE*µ¨êJ¥UE)UõWä[³.ê±õÓÿßå[û-âOúŸoÝ߿ҋE‘Ÿk»ßjùÝiËl±YâÿSiËö÷}Wý¯Çlµ~m˜?Ìc<¹Ëò_Î]¶ªyxôùùŸîƒjñ”þ”3æ˜Åru¸šÿЋ¡d¤QñEÎŒ2Ös1BÝq¡äY æïÉ è…kC€a¢x8ºõ¥ØJÓ„ÏŒÏöfˆù{æëk‹û6Ý[æxÍlË÷PŸï'×èsÆÄ<ÅV}†G$0E±Ü u˜8UŒ¼`Ž{þ¾äjQ&0 d•óÐRæc‹´t5Ú?Ö\÷ä›g ãë¶¾TäòrW<òjú\ºõùd1np‡³ÉtŰÆÎ071‹MÌÖañh YÜófŸsà\u@uxtÛ†Íÿ…éc©=QÌ/:מ1× -%£[fZ¹pãuVêÔiKµ4+¸™4,èzË~ä{¶ðñ€ Óö‹N ½ôÕ—ÒÌûË㓘‡n[ƒRÚÆhë–%MD[e²2 Z‚æ°tq–vÚ©3•†¨ÇaíSíýþÝ‹ÑW…]D.mº<ç–—g‹L–ì*3lD÷)ç“_L|Ê?à ?{O ™H•m`[Ìl/ù¬àÄÝ#‰·eðÙu[bò2L·-éãÅKŸžáÊW¨}z¾§yžßm¤Ì¤xe Ò~$)˜ÛâkÕÃ@Üg㛚}žŠ ŸáȾˆëYµð°Fq¯5/ƒ»¶àèeôÅlø1>ôÅpÔ2ò;) zcÃãùÌ gêžYÉS]ùM Ïeéäü×ôìVnH8í\‡VŃ2ËûϱåUX8aዳŒŠÙ“eq)ºØHbl˜•çbù.’¥3JL/W¬ÏñÌNö•㨚‘)&1d{[–ÝÚ~`ð*ægæ‰Rçƒ2¯²Z‘žŠ§²u&/Ã(¦bù‹¯æ3[qáË SçÞ­%³ˆËhÅz‹M¸ë,Ø©b@/žýÀ5Á¯ÇÓt¤Œb™‚ùSî‰]ì*îaçº_Œ…Ë#±*Ë‚¾á¼˶2~ÈÅô!äuª4ŒŽ´N“ˤÅz†îE:?ž…ÔVnÉ0LÿJMçñÕçñÕ9W,œ 7ϳoߟÌîº5¥Z-¹Ÿ§RHÔ§øˆ:L÷qœÜÜ_Ö ËfÌ{5 eÚ„6’"êÓ}DõŒC¾`TŸQÖÉÆðé–ù ­S¡iu%ÊY›ký{lqVwÍÀ…jiù|¹u®±Tûô‹óøâ5§äÞ ž-È?øjŸ>´®;ÔT|Lõ£j®k#rXµ{ž×©Ó+¨Ú'Ë5…Z@~ÛõŽ?#ƒéª}HêÄ€òjiç ?Mœgù˜ qÇ„ezsaÄVg½žœ*’: ½Íœ}LûÛµ-+–\½¡WKueߪ­VgÔSýñûrjÇQ¶Òde& 4P‡-ñÔÝT_‘Á™‘ÈÌd,&Åâ470\¹.Z­1¬ ¢Ñ”§b½UÁ™Õ’wu‰Q –…×ÄQ¸zr,­ÛúåY*¬Õ± YPOMXpåúzµö4DÜti.0¸@QqLjZÕµT[Âzë‚›K5åªO,751¢š…ƒT[xD©H½ëÕàì¡´kU¬Ú¥û‚k¥3Ou)€ËÁþ&mñx6,þbáÆ—}…p©Lm\r͘üÖŠì üÆMÉè”÷-“K®ýÚžˆaLµ5C¼‡:1¦Úü /Ø$›JQ`à\ cjõe¨Ú ¨®ÉÁ’܇Â-¸˜7𳨸-Pý¦üa5‹^\#ögÓ*FTÓVñÙµæ#ªig EFÔª”{µùƒ–ÚÆT³àÃhcª­6â´‰1Õ*An ƒjíÈœ²&ÆÔjɆ*,Sëàjú~dSÝâ·Ô³'&£ècªÍ]Ñ©õ‚1Õ–:ñ½÷êIü<°4 ª®§ùMt _ÞòÑÍu“a+Z@ù†ªö<ÑúÄ j7ÜÄòAÕpÂ1 ƒªñù–V¬}’º/ƒª]±¯ƒÄ¢„¯sceä·¥+;èçCØ7öÃ,ù°_â@zØ©f/öËh¶û1YäÅ~…óÃ~lNþFõú{:Æ®CÏ þŒ^`‚¿DåÀ_¢;ú¿DOº€?é5þ<̓ý³8ö˾` ðSäÌ?Ûð˺¿?sJD ü¬§ üÌ7 è%ð+å;øÑm€_¥ŸL€ß,ôÙð³©f‚…àg2n% ülò‰‰¿ÀψPGîsƒß:¹oJþ î3,ù“û,57øVÜ7[SrŸMsÓ‹ûŒœI‚ä> i -’ûf§'p ŸÇ4|.ò3Jü`üÜS 3`‚Ÿ[ŽøY:o¶<‚Ÿ§üF=?/C’ø¹;U¿ÀÏȆ¿W ÷yF4ö!EZùò󈟻`ù$òsOy4-’ß¶0•žÈÏÝÎQ ÀÏ xœ?wyÇ‹"ø¹»8@•àç–~ƒ\çp?÷)SüprÀϽ•q£?¸_£€Ÿ»/Xüܯ }ÁϽI‹C¾·81ÐÏ]ññýÜ ïèçÉĈM`?TKÒËð mZ‘!ûy2ZÀ~žô ˜Döó5°R ìÀ~H/Œü!õÕ ¾¸>ûy-¬¿ý¼ §röóJøvÉ~Èåwöó\5¸q²ßI-%ös ú ²ßµDCös_><.²îÜðçÎ|X3$ü!ÛÏ Èªýù¹xÉÀ?·$°ðï¤þù’úLò²#”À~=Ä=ç¿n®˜ñÿ¶…îóä?ÏJOøoî…ó/òÊ ð°>ÿlý =¤ðo[a!üóŠ{À?Kny'ño—AwôçEO¤?³øT…ðçõfÐàÏ- eöˆX áïy¥&ø{´’ð÷¤,üY¢ýú‚¿‡KÂ`¿'3»v°Ÿ—Jö³óbF$ö³—5Hƒ`¿ça É`?Kúï«^Á~2#û=.Õ|.ö3WR ‰ØïQÎ…`¿'HIìçç…&b6ƒÿ¬ÌVÉOf$ÿ™QòŸÕKJ#ÿ=òÚ þó+^‘ÿ¦± ü{ ã;ÿËÖ ñÏš;¦×â¿§2ˆ)øÏ|‰ÐòÅö>ÉfÁ‹øÏöDÈ/þ{ ܧ‚ÿÌw¼ø/¶MÿÙÕàñ‰ÿžFrñßS«j!ÿÙ©DþóÜFþ{ “ïÿ=šZÿÙQ¸)ñŸú°ÿì!XȶL†%ÿÑ÷êâ?sK&–ÍŠmã ¼>! Y:-@@;îKh5ƒ…„€öÀˆo@À.|>¶¢æÃ8 ùïé̵ü÷4,»þYg%þùΠ+òŸ]+éŠü÷4ˆúeȃ…ø÷4:ûþ=ý4ÿžÎ)Qàߣbÿž cáŸ-ÌÏþÙj>0øçOîsÑߣ`\ÑŸÝSƉHÖó£ÁŠþì‚ñpEÜæÞÅô;”&Ü¿0 r ½5VM årvp· âž°ré<ø¯rÍ6ðÏ*PÂ?kýŸ›þlåsÓŸÉo8Fôw,¢¿ÚÄz¢¿J~úÓ£?ô×è“ø7˜|ôàßòt\?!@¸¦^ha¼yÁªA€)ñ"@Bƒ‘mÞEe-¤?fK ´I$ ¤¿ZÄ–’þÌm5‡ô÷-ÙRÒ_{D¤’þ”ˆ=¤¿ÌúGú³e0¥?¥#½¤?îùs¤¿!ö é¯Q/å¯2ÈYèñ¸q Ï@ D@Ÿe¼Ä?Ÿoa¢)Œ„šÁ€–òuÝ è=?^úÿ¤_„ø—“T9‰Oã5“—±ùÈ€>_ôQükAxÿlôA½ÒÿÊóIÿË"‰ ÀEYáPà®Kÿó@—Ï¡ÀaSP(9’ÿ\®¤ØùÏ·HzSàš*# Ü÷Ùn ô ‡Ðr$ÿYOŽ"E#UãSý³¹ÈÍ€ûÔ¼^j6«L9L­ŒñâŸ,"õÏFªq# O1@0RÿžX­‘ü÷˜î€#RSäPe«öŸC€ãÑ¢h¨1è„úç2!‡*ÍNCþK …õÏ|£!!Ký3ëòRÿlìBgHõÏæ%ë&@Ì)öùPeÞÓ“H¸¸ICý³ŒAAêß3´¢&õÏ&E<ŠêßÃ\—¡þY<–Ȥþ™{wÆÕPý{ãžBþ³0,¬Iÿ³‘òºô?›IáÛ•þgÊ31–`ÊœœHÿK¤ÿ¹3!ŠdyÆ¡C’ü÷hG€ÿLÏÆ‚¼ä¿dcÕ®¸Sz¤ügü¶nþó&úRÿ|ºˆ"Ä?‹,/õÏbÍæ‹ÿB”?ü·ÿ²nô*=êߣÀ™ÀÔÒ74ìÃŒ‹˜2@í”/þ›ÁŒâ¿}—$D@»£ùÿ<ú•ÓÃÀ€‹Î×'ý†î 4ïþ瀀z€ö-@ŠÚžd¸'\bœÀÁ|ñ€©3OV ?"àÐÜXУEËç@u^8™O*Ђ?;qhÁ…í%¦BÅEhQ¨x/Àô0èà"K`ÒbM ½æç%¦ªå  ߇0:²€¶Š£H€ÁŠOS. "@k;xW"@? hí‘úšpq­ À4˜Ö'0õÊoSèÍäFL¡H‹­¡`ý&pÑ•-0GõÍÉòÂ?ÛÓ ð.üK™»SþÙ㣢&ü[ÂHáŸE†‚ìHöý±bÒŸ5~à2éÏ;2°éÏz‡¾S1ÎBþK–*¼HþóÀcœ˜h¯-¿Ð¾p¬ Ù ]˜ž)Þ#š{žƒ0)«{`jt‡ L…Q.A€‰™M­SD-ä¿Ó Ä©s _üg] Ö¤€I“o`²…kœhiTe`L Å`C3Ú=¡Y S£Ð_HLv Ï?äô1Û¾Ì}Zô¹5ôé[}%êôiéP_á§û %‡ ¾(ØgaoÕ¯ˆ&‚û ƒœ÷ú0\.Ÿ90.ŸZ¥>.Ÿ…WCì+r… ì+LéDì£k¡¾Â½Lî§ÜÒ‡úžHÝo [ƒúä#t¨/kÝ]Ôg’N3§¨/O¹eõq#µC}eQF ê«r5<Ô×9aê+Œ×?Ô×¹­aP_ã*ëE}ܦàPŸt  ¾Š½|ôµç»¿§¶p8Ô×Ç›ú|“¬„ËçP« —ÏÉáü¸|¦G¬.ŸR åñ™™!ë@_bò}³êèÓæÉú´alx|&î”{<>‹æ}û™··Çgáh~AŸ8: Ïòîóí¹ïP½òù”§Áa¾ªÅŠ€¾,¸ è³åf¨b‚¾"¯Uù|>U¶|>}Ñð }µK ô1ú@_6BŸJE}Š, ì“‹ÍÁ>­û”î÷`Ÿé‰Ÿ›úòÔÅõq‡ C}¶pûrú<àÔ—“ÈPØgA oìËú\û*“Ãì+Keˆ}8;¹Ï®¹Sç#÷eöb}YîÆÂ¾Â˜¼ û¤ôûÌi7.ì³õröUy·öU-¥öÙ¡MØ×Ô"Ä}¶^J‘‘Üg-+¸¯U ˆâ>k ¨YÜ×ê7¿Ocët —§µ¸Ï×VI?£8L/~M"S€Ÿ*>äÇÌoA~M(Að{”õ!ÀïQÀÀ¿p ð«p\>àW)ÝOÉJüìò!üÉWâ€_— à×™Nâ~å­üõIÿÇPþìÒoðóUþøY'æùé-òk‹ú¤?=¼Pþz Jùë\¡;à7 %Ü¿>¥ÆøeαCù"‡Pþ,Þ˜(HåÏýQFÊ_øuFmðëL„{”¿.wÜPþZ Jù³ñê?W.@?›5£b‚_ MÊŸÍA_žŸ§Ý„ò×$K„ô׸Z~¤?õÖ‡üìë ÈõT‹m†EÒ_ËbAI‘¸GúÛ–J ¥?}ã‡ü´ŸâÑþ×ABúkL¦Ò_£üIh/é¯=œ}ø5iAGúë‚1Ik“Gùë”ÎCøëIõJøëبîP_ˆb¡û Éj¡ûu=ÏÐýl»TИt?)?G÷kÌqÀ/d§Ðýz¤I÷;~Òý:3ÏÝOdº_'%AöÓN”—ò7Åy¡ü-<ª£üIï åÏb¥èç)å¯Ñ{ù(Sð%é¯MÊÎ!ýunH{I)PpÅ·ŠÖÒ_¯2I] ü‘þ˜ÉïHMþ!ýÉ!$´?m”Ú_Ȩ·ö×ÞÚŸRJý|êŒGáò7ûiÉŽóçøîü:ÅÑþ˜éÒþUذ[Ý¡ÀNÿÀ€@ÛþŠŽž„ÀÑ9] òŠ ÔæÝ‡g’3¨(PévƒM5fX¢À¥œJNð$š÷Æç0 u¢Ÿ€>1¥'(‡)ÃPZ’ƒ #0Ä+/¿OPÆÍÛ !â?xnÜî € ùÏ'ÿ¼ÀÎaª( ‰üwº$ñ:Ž‹ÿ|™3ÝüçË®¨üçk£/þÉfÕ·ã§/¸àú€.¬Ûñs[Ö7Ù/éO’ýlíE¨úÙ|…~ä¿£ˆÿRa¢º@[r{`ªtc LÐLEI»týÙÊÓsI~¾Ši¼èϺÜ>GêÌ ðg뎯€?‹ƒc0_ÓÒ¤|Á_ê”DŸå¨! reÉ¥.ö3 æõï7¸¡Ø‰÷ëJŠ÷kC¸¥x¿ÁÅ'Þo*8âýfW=Š÷›zŠ÷½F°ß”H­`¿ÉtP'Øo%Åî ÆþÛçÓ-‹.MθÖ÷STiÄû-‰á'Þor…ãÄûQjô³Ù)EA¢ŸeN$²ý’©Z„A.M.ÝTü=qvI~‹Éžýlnü–üìzp§d?;kb?›,×›ýòÃlªGò[ë[ÀŸÕ‹^\ìgWÜo§Ïm©T›Å~f¡‹§"þž.”æ·ÏõôÀ~iqi9ØÏ,ã¥ù¥Šù{èÑtbþž"wRi~zGô[œÓý²ÒgúÙ1˜ýì‚1¥úeE.ûeåÜ:¢ßÒÄKìgõ@|ûyŠMÔLø³‡\^ðgÍ‹~«Rý–Ü„Bõ³Ðpá/aÒuÁŸ7&¨f„?«ýPýV“û¥T¿õ(ªß’‡Z¨~6«…ðg™DŸ—Û§‰ªžË~¶ú’ýüñ}.øóY°þìú_¢Ÿõôè$ûÙ‰i‘è·$j„è§Þ#úM¹1†ègêìçB?ëÄP‚ägºfJò›’nBò3ÆÁQ’ü&€Bò›B\‘ŸçeE5 ?+Bª“ä7›¸J’ß b“ä7嚟w¯˜?ë‡_àç—÷?W(^àçšÏ[òó›Ï§w¬Œ¤ä7ó7ÉÏïó~v9tª”ä7%›KòÒ]Bò›bI~CZ’È/E ¼?z]JñCQ€Rüät~?Gñëònûi轿úÍåÓ«y¹|ÚÉ!~†æ7¹¬~4¿¡ÛúY=™* 4?…‚†èg ÍÀuý´÷pˆ~#äE‰~ÞÂý,7æ+èO‘õ—æ'u,4?í*}4¿¡–š_×rZh~.Í/Âî¤ùu½¨Ðü ë ¼Ió ù64¿^­'ѯ7]T¿h×Gõ“[·T?ÍØŽêg ŒñƒêªŸ-½‚þ¬ Bõ³‰,¡úq;Ð+!Ùž¯wZ˜zÆçäß‘%Ò‹ýòA,¢EB²ŸÖ},'q×ë§È•¸«9ˆ¾ê ËUmªG?O=½ ùÉu¯a9õÈÆzâçUÏPúì¨',W=´©ýü['$kžŸ0ýBB²ôˉþ'$û™Ìb“„d?× fElÞÉ õ½­ZC4ÏÝwF2Õur©®;Ù˜ê:¥T×]*êŠdcQוm,êŠRQ×U*êŠlcQוn,êŠRQ×U*êŠtcQוo,êŠRQ×_‘•̲.®Ýÿ|V²ükYÉ~òÒ>+Ù/ûž•ì—Ê}ÏJöómí§YÉ~K¯ø“Nè[øã¯teQäçð·Z~wV²fSê=fýlV²ýþéüó#%Ø_JMöÊvþuýùo¤ì2þó/6›_ÏWÖ,¨ø"F]ãÏ}îÓÊJˆð}(­7KZ\[î û‰zd,Kn±W-ŸÏ›g²˜ð•ñÒ,'E*o°”ŽßÖZ⛨Ç6O Á= ÎÕæÙªGõîë±™¹¨›%MP,FÂA6í¦/JƒarÛD««Ó+‡îð{úVŠAa¨µÄ±®Ò5m[&öŽh\ßl-w,ÈÚâ¼×ܰýünËÌ5Ò¬Q® žrC>alBç†æÊžµŒ'ï›GLæˆÞÓÉ^9‹;n‹ÇX`{6”Ù¥{E|óÀÉWñÙDé·uˉݹàk®Û d¼¨ž¶ŽHtÛj=g„c$¦,Ú÷À1G lË@8Fæ€ÞzuG5¸ØøÕõ–±yJáΕ­÷Ž9yÁ g[<…Ç)w\ÞpŸHe~pÔÌŽáX´-ØwöjDì<ôñT:æíÚHž¢;êÀà1PØÃ–<¸ sÉ´á[̸Sƒf³iCjpøÁ‰,dŽD¾È±§ŠD…›AX Þf8hc$¸åØC£ea££ªosÌ·œÊf60TÄøV /;ö1æ±`ñ5’Îôëf±©‰ðk´}˽ƒfcnZ¾)Ycþ‘fù<Æ·q[¿fÑEÕ½¡¸l´[Ÿg­ðÐj4ZKÕWZý HŸòm¸:CÇÏÉb×,€Gw5Xß-Å}˜¡ß¬u{$Fgªf‘ùIeüÄ ‡pûjiãþFî …÷ï-“¡5~5¢žax`±W6q Õ´!¾Þ{ÍBËóÄ© ,½A;'5°^¨}‰íÌÒYfí^*ñÎqòÕð©vPðþtU3ügzð¥vbi·‹ÅçàutK·WøÊ”Œ/µ7¼Únž+™EeêÀ—jePOkøR;—л+‚ùUf`@·z\œÙ–/Õ¾êê–Yñ¥BQ0ËÊøRmvMË—ÚÙñvw•­ðló“»k7w¼ñÞ}# ‹Ãv(2Q‹¹ÂÃËÎzˆÿÝûŒî2DG>pô)AýþÌÝ!·ÃâJHw~O8ª£ –œÜÒpf¤¯BÍ(³0¬Fº€Îe¼Œ£t÷Í€&ÊxÐ-=¨ƒAÝ7š8 ï7ÃÑÔC¢¼wß hÁšëćj[ùÚn@<ˆÕ óŠàäÇUoÊ «žP–‰aÕcÁpî…aÕ¼ AÔBH+ƒgá›yæéèûDºÏÝ7hÇ´ÀAÌëY8ªLlJ¦•¥nÉÜücµÕ~¿-O¦¨§?ØCp$½c\µ[÷‘«ûv@õUƤøL}í¾ØÂzC Dê¾ øì¦[ÞùŸ=ï]zÍX¼ºå›,ãrs÷Ý€X¦£æÊu0OB÷Ý€ÏE ÖÁ`ºïÄfšQÏÈØ•l<³!œIý[­ÜÀ |VhE¾P¿[ Håñ¾}3 ~MLú,Zï›áàÈ6KÓÐÊœ|ÁÊv…Š^ÿ-¹Ë. ôÍ%^˜Ð\¨éßÁ@l‰wQ ð)°~½ P¡º‡nÿxPy­>Üàï`¢Sû!ÀĽ ƒ-Õˆýd‚÷’;ˆ­ŒnÌŒO8˜9œ̈I=¨ÐÖ€…íÀBï逅3®€Jºx°VNƒ+¿èC€aDS,lœL §¼ß=_-¾i:sŽNåmœÖ{{“NøH\8‡&å@+:N¥é ô”b/ôT`Ÿ‹ÿŒY ùoNz¯ÿYŽïüâ?Ë6^ü7}²ðg€™½èϽˆþ ¹ñ|If(@0ÒßTlZàßÃq-ðÏŠiı+ùῇŽm‡ÿž¤«ÿ™šŽÿÙ×Þÿ™ïHNüg–7ÿ=C”&þ3h"íqœ äþKô×;ü—²jÿicíà?mˆ}ø/‘–E€™ù…fJœ‡3·Ü9ˆMœnÔ·sãcÌp¹;˜õÔƒµ}ï!ÀÂØ²C€±h¨]Ê:ü,ÜSë`©$s`yt* ò«KâHXFXF¤dÃD9°Tá°²O=h÷ÿ¹ °>œ¨j)ä`¡Æ!ÀÂd2‡­ù à©YX]ŽÐö(̉+½KVf™8X™6?°"^÷`å×X¹ÃÀZ U3Ê€ÀJ”uêò•îË+…V=®€ÀÊX—•ÑÖ+Sžl\Ù=h;ƒç Ù Ú”ìÅ€QBتNM4§ œYØè(t°5­PìAÀ6 ‰€IÛ6Ñ{`c´ó!À& ÔrÍ!@KÙ£D€¶µ×›£ëšåM€™&Úõ `ë¼u`æÔ›cð_L^ƒÿöþkœGþkÜnãð_k¼¸à?9ëþkøüg¡`;ñ_ëb;ñŸtÿ5µâà?ô‚7ÿÙ}¸Ä» –V‚ÿl*Ä"ÿÅ'ü‡ôâ¿VÅŒâ?Ão&ÁURðŸâøÿ™gÙçÆ?m{°.A­°qrÐ*ÞØ€-ñ±*áÐAÀ–ÅnBÀ&ò lLX™µò à±Û#´˜¡ˆÝÞÍ€•¹Ã€Úlø0`ûÖ!*< ˆ› ¬zWÁ€•쇫Úv0`åh{ °Ò3ý@` r*›ÿ@K’…KÖ®s-v«…È'ÔÇX¹ÍñÀÆÁñ¦ÛO °!ú0`«˜”lÜô0 y([5¿#…ÙáÀäsæ›3‡‘Ê%<¨˜¦‚}7*8,ذ±îAÁVI“"Aë pŒHPáK‡›ä£ ÁÎA‚-}'AFYjk‚ùö*ˆÚj…?‚ ­D½¥À)Á&Hp6Õ#\ˆÖ= ¸Ø4N.ßFf±As-~ƒ MÅ0ý ®üH™$ Q€'©–ÚÞ>d@«&°0ï’ìyd@¦|8*àî`a¨Å˜#V¦Œ>"`áÖG´]g¿‰€Sª¥DÀÙñ}pØJìZ°wq–D@ þG¬tLz"2ZœÝ êãX5ÅÙâÀѾq ‹!8H:`cŸ$ôxè†jÀE¿P8p‰Ö‚÷É©ñ‰-Cð›µJ{8Ð Œ'Ügxcàšß1pRÿ8hki8•0prÇáBŽUcJÔ#N&!98VPǪY‚ 9V-úÄœ\ö<8©œÌ]s@p1"õ€ ¹†n\$…Óš‡'“Æ\ŒE:Èí•*"0pQ©03­ÀÀÕ¤ò å\~0;€ßhk$°Ç#ˆlÅo\TGq 9§~n œ$Ûƒû'ÁPB æ‘Ä@Òê(# \Mb¡0peQ•0pV Wƒé•^Jàsa gÀ„èY3"î3Q²Nû”“Æ%Òë\è‘f¼p ’Þb Ÿ|¾9p1ÕÝá@®>7ÊÍ[è™î^Z §º=ÞQàšRõ„‹y4'³e‹‘ýá’‘ÞèDêHP8гZ㾃—™Ú”˜ôì`*p §ÁÕýña"GÜ–BÙ*8p±>8\*ô´˜•‘¯Û"z>lœè§ÊŠ÷O:8µâQ¼g GÄ@φˆr 7PHÈä@¿I| ÁßDÀ•…|€À“zZˆg÷9 è ñ"É€=ÉkúZ8®*„H è N@|d@?&½d@oŒ`7  ?K2VÒ°ÊMSóÃ=˜èÇ=” U àâÔñ  ½%Š‚DÀ9„‰`@8Á€ÞÐc’½™S)ú†3p‰‚—éÅ€^3:t2 w,ôš±ö ¸˜!1Ð"Ô>7Næ2 zË›"z{4¥@ÀÅ=gj†qprSöƒ€“›_ ý‚©ú‰Ó\´B1àbœÎa@‹z뀓ٳŀþ¸h.®X\‰ê¡pe¨P‘ODÀÙ¤ñqOÚy~u€‹i5®¥£ŠÖç;ÆHFôÏâ+пEt%Á€ŠXû YÌ.îs'­÷5¢Vp_)œ†÷•!ŸÊà>Íûüj‘È&ð«Ü©é_e  ƒ~•]þA¿Ê¸÷ƒ~U“×@¿Æ°ýžoè‡ ¬ƒ~‚Ù@?%w?è§íuú5N‰úÅ™Ž(·ý¼¼@îýZ—#fxj&ì׋´:‰€}|»ù#šC ê‘ 8¨¤pty·RÜE^^ f€\pOmêË Ôh–ª›DÀõ艀K- DÀÅ´¾Gܰtˆ€+Ë"pq&sDÀE—£.ŽÖG\ô²:* öû9ø$éu@‹^` •oò`’j¸&µQ¹&†Ô~?€‰j3qLX5;:`’-¥&yÿíòve>ÞC!ýe¾‡þ”ïÐ_ÎRø„™™]þå$ÒþiËãKÔ †ð/·ï^ YÏ&d@ñý‘ƒ`…EJuà_A4é¡¿¢(èOéýÅRGÐ_M¶™ã’µtË€²H”øø>ÐGœÔ C\R ‰JDxð¯ (T—@NøW5 ü“÷ð¥NÉn¡Ò×âR™ÿàŸ=PÔ#üÛ5ƒ”‚ÿl"‹ø67ÿÉãùÈ€…»Wþ³å<œ=dÀ….ç’™6þ’¥†P®ª— HgÑе<: w¦¸tÀʧ|tÀ¸šKÄœ#tÀFëÈ€¢•#jºpd@à–Ø¯„“gh€š=„XäV`aŸ£Væ_<ôWøÍú+Kª8$@f¹–(_ÜÐþçK¬L•}DÀ:¨†(Iæh€Iª`h€V/ Pxu4À¦Ë P­üh€Q&4@ú)¼4ÀöM”Ìz4À"P PâûÑ'éSØ…¹ç×ËÔ”c`[x€ÊÏöx€æï M¨<@3ï $À¦¾/$À†¯/PþáGTwt|@Õ‰'ÐpÄ 'P¦r¾À)Ö p‰"à TÞàáú¨âpMÄñT CœXúÜ"øÐŸÍ0ß î(Ðo0ÇQÿF“B(ô³4 Ÿù1ÝÅE~L_sÈo=rËù zèõo,Qf?+ªÏ›üöDè7¹9ÆA¿U¥.î܆õµPÿf úµï. ý{–PÿöQtæúíG§òŸÒ…ùo • ù›¼üŽ,f—¨'û†‰bŸ0ð‚’ÿØPš–þMÿkœ®ýK+—¸¾û‚jÃæK¬Š ¬H ÔFd5Ô›ÂÀÁÍz±c``<œÀÀÁ•úƒÑHGù®F# Š” R¦ 5‹‡–Eħbq` ÌàÀÁÜŠ‡Ge‰ûÐöZ„2!6 zÂÀ1T0P-ÿ` ½©7ަS… ˆ—jçØCCÞ‚AƒeF™ À!×»£vA•(phY8º¢ #ûIÚvÖoppóâ+$¾Û— Qà˜bRa r; ¡/FH fbA‚ƒ!«WHààœï„†E$8PyBG*$©›®@ "ع}B¹áè dNý+$0Î!]¢Èè?ÅêÕxÀpx@æµ; ¨¯ãŠdŸ~ÅEÿE<`'îžxÀ8WĪœxÀ(ñ€z'Pã‰ì"S´ô®¨½ˆÔ‰N< 9ñ€zɉ¤£Ý dµ+PŸÙ ì 4Œp@ú@ŒHÍ(r â‰@ÁÁ„W8 ^x `ÄežpÀĆ}‡Îïá€$J±`—¶.´ ë8SÀ`—ò0¨O:`p(¸êÀ Ý÷¯p@E2Ÿˆ@fh=4±Á'"°ó Þ ÷ dŸøŠ|»ƒ×}nÔ~Š *7XPÁ°‡å™}± Öm^Ÿ›û#8T< –3N<`•ËfÄö·Ð~…3hX„ƒæð @Œ€@EMv­žÚ=…ƒrñ:8Ø‹O…ƒ½‘EEƒz ƒQbñõw8`×÷~ÂÕõp@Nþ¯p@£'pPX=á€Ì™x…vúŸp@!o° ¾Õ+­ÙhÏ|çÕ™î¾õ9ù{hˆe¿xKèïEN³aŸÙ¼«>–“ûK6¦ŠŸ'÷׬ØÉåºÄ°œzdc=ñóªÇöj¯;¥áª&UÂ_ë#B7ÑÓa´î»óy¤·Óì¶ ïrÒ‚Ð=¬·LܯÁ‘d°ù‹qÞNg£í©úÓ°Êz×ðA!s[²± ¨™AN£§ŒTm`·-ž-{Üùmö<¸3—ööä¤bµ¼F·½ 2,.+n 6ÓˆýÆ{X@-ôM½ûÎM«QqÖk|/y×O¹{ÞèÓI0¨Ø¼ ³üî¹RŠT÷ÛÜ–å ¨vU^ñÀfmîã‹ÀcäŠ}áà2Æ~ð£iaYô£Á>EcX`dÇ2±ßÒh¾%!">pæž°G`›º:ì“âÑêx½|ïQ!ÃÖ™Ð3­'šÎÄYÛâÎîhãÌ9,½]ò2ÌÉ>¯h¢¶ÙOC-¾2}»ŸŽëÛ²*}·½gž¾åWL·›i[þø†cwü˜¾åϸOe[þdY<8 ,ˆmüì¶åo9fÎŽýQGuUÝS×ì[þLx £mW,àP–é[þp[Ó†šWÂ^ž‰®Óöü)p7Çóò-:\f™¶çOFÜ…O‰¦oùãá ¡ YOQ¯ŸÛ·ü鍯u—=âúÀêÛ\âY4l£èe|¹hÚž?Caù3üú|ÏŸ ®fø¸ê—ƒæî[þp¯Î†Šç„_vÁÖ;³aÇußvÕÑfÚ¦?EðÎ}Ó{Z…žtÓ7ýᶦ eìŽY†Ïãýñ >q)«ß\-Û·ýñfGîƒ2½À1»ÅÕŒq™D¦ïûÃÍ'ê™ ŽÙ½zwiÕw*Ã[°]îÞ¶úã¶ ¸c®Ãöûñ]£èg7m»Ÿ‚h NzߎI;½Z–AÔaÓcÛDŠa0S½¦¸™¶Ýoû8|3±Íë`ŽÞi›ý¸W°ü±ãLEŦUè®-ùÓBeè2m»ä©^Õ&á›X¡ÍOwÛ®úàÆQNu»6{µK^ŒÏœ>í4•î9}SÀÉ Bsú&OÃd#ôC6_ó=Üé3må{×3ÓâÔž®§J›[ ®FOméj3¨Ãò _ál~á%¸ ì´iAÂYÜq|šï¨ï×Å…çm°mz¥MO ‚¿£Ûõüi8Ú»ñ||¯AÃô}¦Õ›®Í||'yt{\HHJí3ÍÇÄöy0'dÜÖRÊZjøm™Ä.¬ó9Î ë¸Gâ…u•ó±Àº‡>3ë&F9X÷0óÃÁº‡>qug*ëÝdëãeÖ%.Ö¥*øÖ%†q¬Sžêƒu)MX—˜·ì`]½Öåú`%MF=ºÌt ë2—úÖeìû~°.`5°.Óïý`ÃèÕeºdÕeqrP]f®Þ ºÂ$‡êŠî)¨®0ÆÁº¢g\gÏèÍuÐ%o®+ì×fÝ9\§–Øf?`WèrÀ®2£æ»ú|»*  ²«M8èdW™“ê]¥ÊdW—jÙUЇìÚƒQá]¥“É!»€ë »s”È®q翃vö)‘äÈv®‡íN±‰9Ÿ›í7ú¢òñE€à;_Øpñμ~ð´„w–È/ŽˆwV×'¼³+Î/¼ódùä9. ÔˆwVí ï,Š Ská9a~#¼‹„w¶^‚"¤;s|ÓÝœŒ!º³YËî¼b3îÌàãIÀ[üT‚»s5‚»S±àÎ=QáÎÖ€:ê!ÜÍ¥·+¸3Ç*à‹àÎŽÂL’pg‹@h„»XKÛyì.Ol÷0¹q°M·Èdd»XnÛy=øXÉvgyIlç1eøX%Z7Èsíl Ê6Ž«ûÑvP†6C°C%nWÃ¥Åu~OøàÉu¾Ô…©"¸®³ÿýsp¯taY\ç'ÂìŸ\çk_h5äºëŽÈu^&Ý\w®ó«AË'×y™b×¹*Ð\ç××n®óƒð2Éuþ(0·'Øy~¼(‚öšð“ìàë pØyîILµ v~zU‚òS^dç§Âzɲó•@¬×ì|%d‡ˆ<`È'G§ßAKïÚAãáí¼^th0Ä•lç«‚ÏÅvÓ‡ûÛ!•&pÐÙ— ör¶;ñqd; 忬üÞ:WKt(‰f¾ØÎÃôðÞ!‡%io(F—¼»7w¾þ‰áx‡m8ü¾€wœCºó»h¨ÂéÎO²h€Oa´‘ÓRv¢§;7$œÂéqŒF§;Q$A:Ýùe²ŽÅ…чki ;¯ÝèWà*§;¯gÝy< ÐéÎWqñ|WáÆ!$3§;ÿ;?Яע¥-zÃ-¬‚îP%.‹Î°çÓí¥¡ËÝY üš_ŒðË¿-@ òƒºÛƒÁ7ÑŽ&´ÓÞ7í‡üƒv{´k\œ=h×›h׸ÉåA»&ÕLh׊´A¡E½»8&Ю=ß;…´ á*ÐÎ>7Ù5M\ƒìZ’'²«ŒR9dg•ÉDvšq²\® ¹áH³K i ÍÎ6FIv–Qn¬ó«É/ÉήOO’]*Ì5’]ªEHÉÎŽÂDT’]ªLí’•o´ÛG1û…$»¤XþììÓª·dgÇ@òdgÏœÂ%;;Ÿ$»Ô¸MQHvv}è¤$Ù¥ GÉÎ,@2*vVM»ÑnX æÏ’ìR+\`‘d—4± Í.)õlhvÖcÀ@ÉÎö^®7Ù ‹AG&ÉÎÂ+—dçûG»’•Àz…$»ØO:$;ffz”ìRc}HvfI/ÉÎÎ d—ºVT¨Ù%Å2H³³xžv4»¤;‰v¾¯¶Ÿ—¢]ÒŽrí¬Z'E»¤X‰vI®Üí’‚—%ÚÙÎâ< D»¤ð6¨v±Ë¹T;«¡Ùù¦ì‰?.{‰± ÜyG~ wi2fYÂn²óCê…v^é­ÛÙUáMR·KÊ Ý.).HºÕ˜(Ó¹n{Ô‡n7(t;»*¼AévƒkH·K“SDévl…³P·KÑ3!Û!¨ðÏG¶[™£d»UÙH$ÛMF|K¶³êvxš¨’²Ýªì %Û-¦C ÙnÁÅ|¿pNy‡èšü ƒè˜Ãè":æv¹ˆnÊ+3ˆn‚è˜ ÷"º ϳºIiäèØg_@Çþøº.á+€Nwp€®S9DGÑ5ÞA]c@þ!ºÆ-éÑ‹ˆ®ÕpÊ$Ñ5&=DתjÑ5ºÒ¢kE–$ºÆÌ·—fÑAòÁÌ‚¾ðÁ,_ß\0…çÇ3ÓU2|0³/|0 Ä!Õ™oÎ,©.ŠH©Ó¾DG© Š¥®eùNJ©;)uÊ6p”ºSFJ]#m@¨‹ó„P×rЄº–]êŽ%„:U*îœ7tºc‘N—¿Óœ!K4Wé´qh®ùJŠæSŠšë”sƒæúa7Ñ÷;=4× Ý?æ†HR0g}.,‚¹!g_Áœ"Í :GÍ-铇æ4E<4'·Cs9T9:aNdó:>˜‹æñÁœ¤ÏCsIÞaáƒi›6Ý4ç>eèÓƒæRÑåˆæÂ×*h.1AÕ¡¹ôÐuS4÷„(GšK’¯Â sáÛ˜K¢Æs D?0—kx`.®.`.ùJŠærˆ}¢¹¢•è ¹Ô8 ÍÕ$¡Q4×\9 ”+Så*2X’k¢Æ ¹&!H®rS1’\k‚)‘\—÷’H®Ñ‰øœÞ\$W$ŠäTãÏÉ…oV\•¶$×´0(×™Ëò \g2ª@9»KÌ›„r‡{År ÿé ¡æü(7å‹åÌ٪ߘ^1&?„¹§¿½/³öŠä¬Òv+tþÈ¡2ˆäeb ’3n§¾%’{’€KÞ—«ÉgSÞ—S¸á}¹äOÞ—‹)à÷åb–ã}¹èàqPNÊÙÒáËû2=äÈqÓ…ëåBwz0®È½U—%­Æ•¾˜Ä¸L‡ƒq©Ë¥SWRøYãŠäöÀ8m¾v8®ÈW48.ÉY,8®pŠp8.sNu8.¥¯[¡sÏ/×K»QºUŠã27Õ8§-ÙÇåôæ¸$o¸à8í¬v8Î*œIWÔYÇU)ÑÁqIÈ—õÅq–$ŽØŽ+Ì#OŽ ÇÕG@EŽ«’»Åq5Kâ#ÇUî¤×Bõ#ÇUFíÇ1m^`\Ëô&gÞV Ob\—û*0N±ÏáÙ¤IÉÿ²K×’ÿeSÈ‚ü/-‰ Œþ—{áÙØóÈý² ›å~Ù%|Áý²Et¿Täb¸_ö qO¥Ü,ïËè4Iqçò¾äv1á|Ù$ñÉù²j±“÷ #ýsPœõð±náJe 8»(b/£'q–_š.¡€8ۆ렄8› P®cˆjª"CPœ9Šó$Œj}8 ú¼Ñ ï×o¢›tD?D·ºÜ&Itá°Dgj?u<?æWT]ì)¢3u½¼4ºû…t&œÓÑ“HgÊ8Vù‰t ~xâ9ÓŽ.'ž[EŠ˜xn)Î)xnq'áÃs6Mc‰ç&'Y‡ç–”«à¹xVÁsÊÕuxn-EБç,&¼¼:S·€fâ9+óPϹ N" ³Ïy$9ðœ=½ùâ9;Ð ]âZÏQè¶t:<É[¡Ë9âì¨Ðeæ9 üŽB·9ùZR¡SnØ#Ñ)í‘蔌óHtÁ†!ÑUJG£S¶XjtÂÏÑèú”›'5ºÎ¬•G£Sž•Òèl! Ä&n„Ϧ4ºÁ‘ìhtSîŽAu‹ÉcEu¾-@~Sݺ‘»|ÑyïÁx8 ËRhD:ÔJÉn`¢˜èö"¦;Ú˜Îçë,¦ó2¸K0Á¹t®J‘A"ªš‘ÎG,æé0ÇwˆÎûí~ð> }n$©zè†B¼é&“¯ÎÖõî°:ŸN…t³¿âêÜ0ï¸:Ÿ•b¾Dgdè]zÿö04 ¿Ý.}º¹h‡5FͲt6¡ÃØ! ³Êà®$ ³9é[³jæKž;31M9Ë èlª8_@çœ@gçä¹Èt©jñULgÒFzÉsG:ÔÙšÿxA]êq”“%5Eê|!Ù `:ûýVç,AÖºÝ.·%H‘Lg‰‰˜.[‹£Èt¶ZL5‘Lgh¾˜Î­çíxég¿ƒêFZKZŹÉ$¥G›óët¶¾û¼Õ¹©/!Ô¹Á}VŽ:7´,¢Ë6®ãä”ç,î%ÏåÔÞò\.]þ„º\«Íu¹9-êrr—$ÔÙûÁm ê²VIêìØu|A>P—{Sà¡.Eµ êòD~£`:{«¸O1]6WkÜ™®(¤8°Î2œ\Ž—û·üIuö’ó-Εœ¸ž$ª+… tAuy†FªËC=Q]y(~êJÎòù$ÔY“#æêÊqú$ÔYr30½ ®$$ò¦³Œh˜BŠéÊ^„:k©o¨³it©$Ô“%Ý@¦³vùÜ^—ÃR¤14PWºTrA]±m!èêJÕz‡ ®X·_MB]áÖ¾ÁtEkŒÁt¥1ôDLW´]˜˜ÎÒ¬µpºÜU(R˜LWöSFdº¢T~b:;j8™Îαn¦+]'d:Ëö†'K¦+ÖYÝužë oqqg„ºÊ}7Àt5Ë7œLWÓ7¦«‰!b:ûªµ:gºú ¹Î’Éa\&ÒÕ\T˜Î’ËÑoLg™äÐÏ8ÓÕ¤¦J¦«ò!ÒÕp†!ÒY:^6™ÎJŒËçr—h„<2]­! uµ•wD%¯ëwD]µÌî·4g•>ás9,o]¿¡®šïªÔÕX%ÕYÖàFƒS]µ]Áü7 Î?w@e'^ŒŸs¨óN š# ®Ú~~È©¸ö„µ¿ÒÌìÁ½¸‹ld³‘%Rkýâ1,Á¿ÿ©¸ÒcAõ®:,'ù•lL®?Oú«ôX²áüªG–»Ø¢þ¼êÙÓ¡×Õð÷U‡[T~ü­ÓpyØ{ýù,\¿šY˳pÕßž…ëIÿ½Y¸~Ò4–]uûܹ‘¾·0o?Ù·¯R¬éä×bMw~-Õt ©¦»”jŠüZªéʯ5E¡¨é*¥š"¿–jºòkEMQ(jºJ©¦È¯¥š®üZQSŠšþŠ,\¾ Cÿ…$\ý×’põ_IÂõ“Vð I¸v¹ök'ûÞÖ¾'rúž„ë7t[?¾ú¡ŸtR?þ\[½û­_h¨ï:~w.÷š-?Ÿƒkßü?þcd¼úK9¸^é±Î¿þ69¸úÏä_ÿûsp­îk§«}ߘ휰 qM6^} ‘þC?Å=0z¼‚…W»$²úBýÄo<^Át|±g§£DÃdz¿¤ÿKô]#'  ³Îm@¶ÌZkø Õss9½¬aû Áàóþ5w-ðèýsú…gfØ#8"ûòÔI-;Óǃ–1FüxÌrÂULŒ^…‹GkX¬ >Ÿ_óÁþi…)ž—=`fšm`6.<-»Àƒf{á9´b{y 3~O¢‡ý¦Ýíñ ¶ìVìˆç÷`ËÀôïé(1"Š75} <^%ËBõ˜oËgÄËbã´Ûñ3nœ–-=zT*㤗¯~Nª­e˃ÜÁÎçÃËÖ=Jµbš·lQÏ£h¹ïÆòu¿¶¸Ã!m!xè´}`¯ºý~yòòO¤ÝÚ._súäÍc|¹eÙÖŒŒ¢ðG±ûËGðñ( —¶Å–Y>'—Yàb3™e[Å4ËòËWé¶4²Iråõ¸WËœq}Ãc"w—Y¦ßâZ¶-_—½Å‹§äòl§‡=W{ð2W—æwÍ[¨Æ%D,ióTæÚëKì Rݶ˜3:Ž*,cê?ŽrÑm[*c;9‹V‹<k4˜¾ÊE›mi>HZÕÜÖ»ÞÎÝÑâ®lÃnQÇfà gì(¶ÛqF»ñ®Bûj´Ûqƾµ¤–Üײ¾TÛq¦£ »Ûq†ƒeå!~”ÊTn Vûˆéîex6¶ß ÷šb'ÖÜiìì>eøæƒ¦åý^™–ùÅÂ&¯o¶/:® ž›Á³Êè–Ûs¦£…=gLýÅÏä#§‘yæ!ŒŸíM/ÊöœáÖ62 a+é>Ô"ï; ¾k›áy}AÊU¥¾hÊi£®ßfôÌÎÍ«SæœMl‹ÒöÉ.·SäYç`$­eOÀµ `·•Y² –¶¯/œÙ6›á¶÷›ÍTÞÀðLŸ®p%ÖÂpÚÑÔ,/-w`Wi»Í¸ž70F~—KÑYìXl·÷älc[Výâ[ì”m·O5×uîI‘s>êŽ&ãjgfÇ2)rNN1¶…µ³ë˵\.ÚL<\»˜ki[\.œMm\[ͬõöùµÞe^«íè·eú€jKÌÛ¹ô­˜:ì>‰Eý§'¬ü`WiRA&ؾàwB†3mXn–á>–h‹–ÜäE'a#Ê0·©­ê ÑÙÃ`U³ ÓÙÃ…Éz(ÜÃdç“| wŃr)ŸY†:J$k&Ÿ³w{²·ðEËd ×}à¿éˤUQ„•˜+Ò„›:üX‘3©Y\A:;óXKy®}»KÚ­_'9Ÿ·ÉD.’Ë@»Cr ˆä¨Á¾HÎgÜÉùÄ?@ŽÛÕ£_^€\¢Çâ¹ü,;|$Çu!—8Žƒ‡ã†NAŽ3…æÍqé UãÚÍÁ8æH>WÅuÂ8v˜Ä8èZÆúãè@8.A=—1Í8(Ç0àƒrtj”«ˆ" ’«Kç$ÉU¦Œ>$÷ˆ@r > ‡ä(uÉYÂç9E.ȵ.#ȵ*L#È1‚#8®qGìÃq…¯G× ›„8®'á#Ò4 ‚r.Ír½kf*_“Rx@®O<®rÑ“‡ãe›Ãqƒ DÇ zóŽ»,ÈLÔ‚ëÈq£ª?Ç]eÈq#zqqܘ9Åq#:ävS Dä,ˆ•ØF› ªî¹©N1@npóèŽY5õ#ÈY-ãrÊ#g2ä¸HÀçñDà8Ã`Þ%0ÎiãbkxbœUÂI'1.ò"‘ãì^-9ο‘ÇÙXþâ8Ês£e¥§™‰‚㌊u8ΓâÈ‚¤fr3#ÇÍÅÍÛÇ=EOŽ›«‹LÈqsÅr9Î]Ü` ÆÜ&ÆyZn¼bÜ\K,Ž{²Z¹8îIOÜ.ÃG{²V"rO°³@îYBœò9³¾‰D{†æ<¹Gëâ¸Ô‚œÈqéacÆÙÆJ<ˆ—¨Ù ãýGÆ™ç«%ÆÙˆ‡»Æ¥¤,ŒK-ê!ƥċÅ!.1ð@\ú¶q©©7ÄÙõáÜ€8å :—S`!.u1… ÎÊðjqIÔ.†“GÄa8K7I‹ M½&1\ªº`0\ΚP âÒR·'ˆKS_† Î|0È_¤¸RE×¢¸Ü4÷Æå¤îS—“Ö¦ÄqÊÖs8Î’9./5Gp\f ¦rÚ†ý€Ü®—{\ÉQ† WPzH®9‹äòR'&”Sö¥ƒr9ÖÁ„rõÑ3ÊÉÝR(W¢Qå¼·pI®4õ°"¹ZÔJDr•‹ò‡äJS¿!’+90(WšŽP®V}AB¹’ÿB¹2tã@¹²DˆJ“TãÔ$¹+B"¹:µ#’+Ì6H®f!˜HœMuˆJD¹2žˆruªí åZ<  \}4T åZ×$”«U3¡ÜYŸÊÕõ ¬š“"ÊÕªûʵh%@9?ª‘•>-¬rå¼D%%|‰•ŠˆPÎ-ùF9¬s +ÖGãúˆrØÓçnX•ò!”óŒþ‹–õQ LÝå”, ,çV×Ç ÄZ㘅õQ»L‚Ú3Ԗпæ|½±ø –»›s¡…룓_¢”K{ñÞÞ~G¢­à¹æ.DÏ8s}Hc#Ìunx07ÈØs–r€:`nh.˜ëLÃ4g Ÿ æƒæ†.C0§}N‚æ”4”47˜ƒ#hn ôíAs½ëÒœ•xÑÜè¼*ÒÜ©“4§ô¦AsƒIöƒæÌÿää4g{g~.˜ëtç"Ì™°Š0§ ]sƒ“Áì(sJÏ07Š‘47˜o#h®…4ò–ÃÜ`*€¹Q$oæ|,¿U9îb0§l­sƒ‰*ǹAs#ëÒÜà>;·*÷æèÁ,Y.D:Â\ÈzRå<s±ª\Š2„¹‘4>Ì%­zŠæú’Œ4ËAsF§ ¹G]'h®—ŸÐ\%O4÷h€š{8cÌõ¾€¹¤ µ`n<¡•æ~ æzœ\0wn\07R  Òôò&sIÌ5Es×¹Is}htÍu6ÂCs"#n†nKÎ"Îלë!Ÿ ç®Èüh½]8wÕJœ;×"žéë%Ë]7)œSzâƒs}é] çúT;ÎÙ#§eµÓȃæìZ„B¤¹ó\Ds#iÆ šù›*gÃÆ(œYʉp…0þÞrt./]ÎÊ´K—»kÎÝgÎù£yér×ã#Î]†8=Wàœ] ß7yÎûpBxîz¿ºë èìzú¥ËEZëºëÛ ÐÝgÐùòïaÎèn`X]·@!Ð]Õè‡ËŒœt–»z›ù"ºë¦ZM¯GC¢óCkº®èÎõ’ç®6,GÌh¡ä¹ë͑箎˜<¹ÙÉs×»%Ï]ß%yîzâä¹H}<çe`¨-ºš—*wuĹÿ‡»·ëù&Ǻ»Îù÷á R†ò{Õ!H€A M¾AJBAàóSk¯µ¶]wwÏt!’£¾/·ÿ®*—ËöÏk¿DÏ|d¹c çŽuB8Ï}Èrè™û£Ë‹pîz¹³NI —ñÁ9Ìêsá\ŒšÎT8‡ûÑD,œÛoJ4w6³¾S–hîÁ¹\•çŽÕF8w =áÜ1Ûçâ¡DY;@¨ÖáÜñ)çŽÎÎ~þù ÄsÇ!ªx.^•îxMïW\çn&~ª§øþôuˆçò¼9yîø0ÅsÇÈÏO%ž;f¿§}?oñܱ¼<#WÕòá¹Ø ª„Ë6ÎíÕ8yTRsY çÎvúõݸçânX0rY-â2Ò\l«Df¤¹(QAf~ÌíoÃ0TÇÈ<…¹£cÌrÇíÚðÙ;ãd¹ã±m…:%éüÈZÉo°>9ñ­+¶©g':\—øŸç\#IpHG¢.K]1`“àÔ„4%‚ëʺ’×¶)®Ëw0®+bP"Ü®1ôÿe‰)„ëÅM áúeãM!Ü®!„C$†Ãí'Ãõ‹'_Ép( „‰áúeÃIVZÊJEîqAût^*r— #­ÈeƒV䬞¥"—×°"G¥­ÈÙÒ ×n££®+’ .`ˆÃ%ˆG‚¸¼ S\·•ª)n×ÅuùMŠË»0Åí¢8ÜÇâv›‚¸}ß÷·Q\W8lŠs²ÚMq¾Ê¦8·»)®§a)%â/QÜÑŽ(Îݸ) ¸öx7Å©6Äõ´91ÄÍŠâzɘâÎ’;G qGA\³UÎCm3œÇ«n?´îhV–•5[VªçlVÙÒœÐf•m¤é¥Ì*÷A¿Í*kµÉ‘Í*÷A5Í*û•ò–Ì*÷/í*aö÷µ«¬÷Ïv•= ÐlXÙÖ_>z\Fºßv•-ÛU¾%¾ÙUöžVŸ²«—šUöÇ/ÚrÜ»oé_³Ê}¤j³Ê>¸80µúÆcÃ>SY“Ye·a˜­*ûÖ™6«¼­êIÃí ¼¤ÆÍTãÞŠõkV9ÓpÐjÜ\©ØIizi5›Â¯YåL“?«qëJ½KrÜLeÀr¶¤/éqŠ<¾å¸•cžrÜøšT:èøÖâœDukqsm˜£wW¿|kqwÎ(ãÖã [»mh1nuk[ãV7ÅXŒ›wr-*»Õ.‹q¨¡ßHŒ[ï$ƭ⽻Ÿu%J{J>BÐ[˜“½ÃP¦É«ØþÌjÜ“§ITãžÇ¶Õ¸[ã·÷¬´Â z ¯SŒ ›«ö¡74,†!½m+,Á[˜€Yg x;l¬o;ôÅÖâ €Ö Å=·ÏŸ¬Å=ÍD°ý¨Ô4~ xcÆWãÜcC2—¼E3–´¸§ÿÅÂ[ýË™vKqÏ´HJv‹Î’¡0á-.5O)Î! o‡ù™à-ZÑ ¼EŠ–‚ÝÂØlØÌò±¹\9*£?MsµÛØl˜Ô©Œ4×”·oÅD:~û°×Ô•é-ÑbKv‹‰ýd·¸’ë»ÅCYâs`¤a­‹ì^¤~»fvb·xwZõÒ¬2·d·øÕ³µ¸¸ÒiU7|ԮɟÈ-^‹6+$·0ç³q¦Œ*¡fÔ.?ÕÄ@·ÿ¤n£J'øµQeé_%ŽyoO%Žñ-UGF•Îæ»*› Ò¨²&Ù¨²ö4à”QeQômTY6&ÚªrXûº;¦î&4(‰j4ª¬=RB\—oÙâºrln!nØô>…¸.îÔáz|Z†³dúÂi%ÆÍÐѾG[AqœLÏ6ÇÉØ:9.ìÌqi†gŽSXÜÄ8'¤IŒÃJòñ t”—†zÆ8üäƒqx™rˆ+ß?o›úÑ·,1îæ`1ÆÁ …„*Œ ç“ã°k'Æ¥úoŒ³loŠ{„„[)Š8ÿw“"]N%ð8!+¬lȼ¿IÄE ™QÒ,d•¯†ï?6ÄaÃCªÄ=7—@2\ä‘‘%× [iÍp±L Ùh òÌYå^üÄp{EÃŤ»$¼qùñl.†‹É‡¯‡óल¶º'Æ+äÞpÿÉ•ç}Á÷aWFÄUW÷”bO·Â…ÇAiÍp‘È[S+.‚D¤š–/›,á2Ô”na:Ò*C„‹8¯k qqicßâº3Z |‹ëN·‡.¸~n‚5½uÖá¢Ä"[á²3l4 †ã”,1, .¢ Z¾k\vFóBTº«º•ѽÑv–“ë6ø’ó&ž™æOä¸hÇòÝÝì“oÓˇ ÏLÛ0r\´lj»¸ðÀ/d»ÇEvò~ q A³ì€A€×ò¦—5twä¸ËË!·l¯9”µ<µrï˦–‹ËÎ[wSâò–Žv7—ûö&$!\Í[—’—§aIî­ÓÓk­Ðšÿé^’IrGLÛS’\ÜÍGŠ‹ ¸6âì´æŒþ$¹ ¦ßLå1/Þ2ä"s¹z¢1hn—U*A.Ú°áå£TæË¯Ÿ aÃD[s"”-F,+ÃOMŽ‹ð¼2™#Ç1{ÌÉq;{Œ9.¢©™à¸·á•J݈°°y`C”C”Zþ¹˜¡¦i69މÖO ."ÒÊ–Ñ[m’x1;BKÙ«G\³©ca~„–R9.šÍS‚{ë$‡ŽÈZs¥Ã9Ž5$ä Æ+«3Í,ƒã"h­}Ü‚ã"D­>dr\t¦[&Ç!Ûéá{µ½%ÆEä9Í3óÒ›óã¢Äæ‘ \Û6nã0iÙ𒇌4õä¸fkéŽqwi9L‡ö¹#ÈEVÓ¨2Jt>@{K–»kF[ÆãßL'Ôû×;.bí ·Èq¨"æÇ!˜°%7r‚ëj -%$é?‰p‘×Fos)'IOo\é¶äJ¦Ü"aKÚk ä0@}m‚ÂàY6$ÈaÖ·1$I%¢‘Rü˜‚”œd¦û€Hfsó“ŒÇlL’c >(E 6KÛ¦2B w›Pg²±äF‹Ø~,PŽˆ®ªBŽC³¨Ò”Ì™TIŽ+Ãt`ŽÃJÖ>‡'Ѐ$Çí”5Éq¸e am²·KÃý ôÈqˆ8]ë).¤ã@bîÙ8’ ‡†‡ (/fˆI»o\ä:R‚BvAPD´»–/A®Üã«Á½w£TÑ r¨c;‚"6Žw\¹ïmd©”B5=èrˆ?hE ‡3Ýš£Q¿ÓN–05ºí9ôÍó!¹óè‡vëiR Žäv'ÿ8‡TL÷¸H¡#Íîq‘ èD¹îê¢õ®7÷øŠiUJEK%ë·¤*®ðÄѪ5+[ÖßGܪ(qhþqĽªö{ZpÉÙ˲ýy´ÓŠŒö3ºähGenÇþsÇÑz÷ qóÅѺÿ¿Œ£õ+ƒ£àŸåÇ'’ÖO£,†Ð¼>ãî¯ÙÖ%‹m}bi©­£–ÚúFÜR[Gœ,µuFÓr[»–ÛúÄÜR[G¤,µuÆÓr[»–ÛúDÝR[G¬,µuFÔr[»–Ûú"j•BoÿÿLBjýžIì¯ßIéSÖ_uà~¦±ßµßVþpX­Rwù?ñ¸ZÇ óoÿéÓzûXêþ8ÿ™.¦$Ì·„ ÿe¼{@üce®qp…œ›µx•9<³w+V-EgRoI§UKµàW"ãJz¶Pšº-¶—4ÕÚ§,Eo™G¼ƒBnNŽJR9XžP®}×!ôÕþÈRÔ‡Au\—ŸAȸî|Þñ(2ÍécT…Ð#cÌøÖ°Í¶¡¹"cLÿ–ÈhûVòß·d^ù©em+Èû[°†'­ÕI@o º)cÊ÷R²Ú¾mžûn)›¥ÔY‘4F h·R‘4æaK%u9¦®„¤17ÅÃÖŠ¤1Šÿ§†û“áÿÔÌà²zO¬S6ÛÇÅWuø?}ySVÛ·Ï&ëû€¬¡oaÊf;/„1ñÝŸ”€Þ:äIbÌ0ƒÕ @o¬È³¾Í´ÇO )Lë­hŠo‰”ÑÛÂ{]’Fhº¹ªŸH½­ù×%qôöék]RGoŸØÕ%yô¶|ToÙkãÀA%RHq-•È^;#MÔ[éQÒô·æ„[é=ý­8èí˜ õ–Nz+ô@½e®}[ô¯·ì]oS¬· ^ïœnY¼ÞRëÞ™¼Þ xYê#›WçmzKdôzßY§(œÖê#³×;§–GöÚûÚL_oæeDÁòí•ÈöõöÑ`}d¯Á(ë#ë×£Ž ¶oG¾¨ `:2Ù¾%ôµ+,`3üG»´AÎ'h—l`o%Ø|Kd{{i—¬`1ó–È 6{¯]²ƒÍ(!í’!ì­\ä(á²zÛÉ ]²…½ïlgqY}ž@[q¨Ñ݈C^üÓqF³2±èÞÔ›ÕF}ÆÜ.¦¨÷øVªæUfòºüþ«ÃŒÚ…¬1a è2‡}¼"ä©Ìã ¶U¹4>ŽY’Tlœø½ñ·øû‰ü.‰}a)ì»lš›Øƒ­[%\Ÿ²kcßåð‰}×J‚ö]é¤oì»V2¹ï-Ñù±¹ˇîX܇Xj‚Nß®~OYÃàWx2ÁÏá¡7øÛ'ø!‹œJ4¦‹UÑ?ÔQÁã*ŠÒfî+Ž’Ü·ÙÚ܇äLºà¾âh ~oIÕ#ü°Å]âZ{3ƒ_±ô›à÷–h"6û9zÚf¿R½3ü•æÝ#á¯0ÍÔf¿Ò’Å~Å¡=“ýJKÈû‡Mö+Ê¥¶Ùï¨#ö{K~b¿â#…d¿b»îd¿b›±rêèo±_é&Q³_éy%±ZŠýö›ýŠUúd¿ÒóWb¿âÉ~ÇÕÅ~oÉ\]ys‰ì‚ýv+f¿ã7b¿}m³ßYòøôœ†?˜AªÁ_ñ<ðWl÷ðw”þŠ-7þŽ–µâk þöo e¸o ÅÑZþòx*áu„d‚?È B=Á_ÞþŽk þMp³ßñ£Õ¿?û9ààf¿â˜ É~ņÉ~ûWf¿bCÃd¿ÝŽÙÏ9µ6û¡Dת!öÛnöê§»û¿û!ݘRìw\IìwüJìW¦…Ùo_Ëìw”ˆýö““ýŠcÐ$û5Ä~ûÚf?Lz*û;L$ûíg0ûw,ø+Ólbø;îXð·{ÇðWd*ö+ÓÃÄì·bö+3¹NìW콑ìWf’—ÖÝ7f¿Ý7f¿£±3wF‰Øo7,ôÛp¯Oß™üö#ývOý²Õ óVŒ~»Ã~x!™ÐïhXìw\\ì·/%ô+6èû!œÿúí_8ÚhŽ!“ßqÇÍ0ùo‰’üŠÎ´üöK2øí'"øíwoðËþ7÷í÷jî;~$ðÛið;.}ï/Yw>_­¹o_ÊÜ—}eì+Þö ûöø0öíÞ4öíQgìÛýkîÛ÷kî;êˆûR{Hî;®.îÛïÉÜw”<ù .Z€_Ž˜¿£†À/ï&Á/Ÿ*Á¯LsŠÁ/;4ÁïhYà—óU‚_’?¿†ä¾|pqßѬ¸oÿDØ—=œØ—=“ØWl¢˜ØWãvcßQ§õï<“Ø—3ebŸG_Rßî>RßñaßQCØ·»ÓØw<”È/Gu’ßîN“ßnÇä—P’ß~(’ßîa“_ÎäI~G‘ßî,“ßl&¿ÖI~nçëÚð×âûä?[ùoöš8ª=$Œ€Ãñ GêfF@gxÙ8®T…€#•4#àHWz#`·ë¼ pX£I<~$WÒfà ©üÀýÔÀ³ä±{ƒ´6 ¶ÿÜÂß%â¿QR@´ð÷˜… €Ã~ˆ €ö½8„¿+u½Àþ¤XhåÏnr[ù+>MåÏuón»Ýë¶øç—™xüJØm»)ìW“󎓻͓»M„“+‰»]û’ûJQØWÒ°Û…1 °[À4önD%ÂØS&Ü·gÄc î€Ç¥€NO»ð¨#Ü7#þëvÓLþSí}¥D'üë+,ðïý{Z \®¡uÒø—Íšþ>ßD}%£‰þÞÇ^_úë+DÑ_·ùqÒߦ¿>“íDÝi!Dïß&ZÑ_Þ°áoßžáo÷¸áoß°áo÷žáïø•àïhYð·{ØðwÔý%Ë#â«üán¤ó‰þŽ:¢¿ÝŠéo×1ýõ¯ìwüDè×—·zF¿£‘^>Øèw´"ôÛmô;Ú]ù ê=ýŽv„~ǵ„~{ÔýºÜt“üö€0ù?ªí[CäwÑX[?=‚ɯ±o÷‹±¯wkƾ£aßÑÆ¾ãæ„}¾Ð³~ê^BßîJCßž }û31ô­úŽvD}{>3õí—dêÛ·kê;Úõí®1öuû<‹ûŽ;÷u#^q÷›ß}»çL}Ý®êI}û2¦¾=‚L}!‰w¢¾£eQßî>cßÑòüéþì¹K×f_Ûmr<üö4cðë=4ǶÉû3ùík™üöµH~G G·±ºwåhðÎ9F·"îÛ·kî;nÅnÔ¬ãÛäDeêÛCÈÔw”8ÄMNbß¾cß¾cß~#ƾÝƾ½2ûv¿ûŽ»Éôús¹kµ&šùzO¹RÌ——óåW’Ì——IæË[IæËÞMæ;~Õr!_æË¯-™¯︹™«¨KD|x$Ý]¿·r?ßñÈ×鲺‰/_R_¾È$¾ I|GöÓgœÄ—öqI|G¾™ψ|»ïŒ|ǵùf—8òÍ.qä›,1òíw`äÛÏ`äëN““È—“Š/»ÏÄw4+â;~âÐ7ûfD|»Ÿ=©oò„÷ïDôÚ×—ø„¼æ/)!ï­³DHEKVã5gKÆkžÚ’ñš³Ò%ãµf§3ÞQGŒ×,Å$ã5»ŠmóÎmjóÎý«mßé’çÛnÚw6/$å¡#„U¢¼ãWÂ<\[Ú›FôûŸþµï<~%ÌsÖy»ÓyÇýóŽ:ëù¶+Ì;jó²$1/Ÿ*1ï¨#Ì;J„yy7‰yÙë‰yGË]u¾ìš¤¼]E—Ï”w\G—Ư‰çqeA^ó$——o*!¯ýBæ;Kîo+¢¼¼aCnÆšÞõ} yÇ¥y9ˆòŽ_‰òöC™òŽ:¼ݲ1¯9&‘0o·bÌÛ×6æ¡ÄTWý ióùüô æ¼}7æ¼ýªÌyoËÝ%ŸAb°9ï¸qÞÑÎóŽæ¼–ûoƒÞ¾?ƒÞþ•A}ó5ñ<~%Ð;Jzûþ zÇÕz{àôŽ«¯þy½–Ò¹Ao?·Ao_Û ·Û5èí»1ëí>6ë5Å~JÔkVHzûÿ ôÒ>A¿Ð­ôà¯_ ôÚôNÓ ×¶V(ÐÇôÕøÚHãH^³¹çí»__Ï9ªyÍ~߉y-5 cÞ~câÂ};:"='IÛ¤·ɤw”ˆô²{ z»gÌzûâd½ýf=Ô[‰õÚH–ëµTtÍz»7Ízû=™õZJsB½ãRB½–&¿F½£ŽPï¸øÍfù‡8Ošóö™óv‹æ¼æ|œÉyû˜óܬ o?!o÷¬!o?Œ!/_¢ b¼6“ßÄx-ϬÌxmúùÍxûnÍxûÅ›ñÚôK4ãuÄxmZ›Ÿk›ñöýóö3óö2æí¹Â˜wÜͽ?â¯]gûéí«›ôö÷fÒk[v+ß¾1éí;6éíž0éWéí¾1éí÷`Ò;Zé%ëûšõŽGëeWˆõοW¾ÑŸXÏßV¢^^9Qï(êa‡­fß4›éåC&ìw#ØsŠÇ {ùL‚½Ý¬X︱^Îf {ù#³ÞnÕ¬·ïŬ—TÉzmS›Xo_ܬwÔëåæD¬— `²^.­Éz¹&ëåÖ3Y/—ìd½¶iêÊ…TL&ÔÃÍèGV÷áÓêÞñ·Ô½[ ÎV÷v‰Õ½]buï(‘º·ä‘ž°g.û1À6øÍÐåNðìö¿žà‡¬ëÝœ§Ìì®iò{,6E;+šqŒ}þt¬;ŸQl=)ì)*¶°a žM؇xœZ&öíxœÆ¾`)ýꉢ3‘ŽØ‡ßØN³dQ«gÄ>L!R…}_ë£î¡Ž]ÿˆ}H¡¦ü¿Â¾Hºý1ïD_Ìö!zí°1'CˆN›Oû¢þIêà Û[ðQÑ Z—‚ˆÞéGêC€PÙ@ˆú0 ÊGÔ‡ ØJ´e2g×!õ¿ê )ó}a_D¸<±/"ô™à‚û"œ–n&°/Âúöû"p—æ}bßBT-íç‰} #lËy1ˆè¸¾Öiʶ›}ÝkSßÂôzÚv¾?ÙvF¬§ë”öf`ù’EºmÅ,ê[x­¾EÑŸ›êŠú"ìÑ:m;#‚‘:‹Ô˜N·¾-4·¶?ÑJFè;âÿú"–Ï8ŽG¤7Iè‹ÈB²x!ôEÔF½]B_ħI/>Æžé×ׯ/Bãhú""ŒüTª"@5ÚôE»NÅêÎ8*è[ïWmÖÐ7 $¡o^é³'è›Wr úfIÿ@Aß,ö½1ôMÅwßзK }SÁšÄ|3]Í|s;Šù¦’Œ|ÛÕÈ·]F|»#ßt†D¾Ì”Ì·Q }³î¿oßÿõõê›5¯-ê›¶çHêË I}³ä¯D}è µ,êC_}-;gú“üv;¿ãWU®²_yoûàšûö#˜ûö{1÷aò5å‘ûŽ›÷í5÷½u†êˆû¦ãD%øm?]ƒßt &ßñwÉÄJÕ(øøô±üöË3øíabð›éœjð;êŒLQ¾äçÔÔ›üŽvœŒE±z~™}$Ùo—ÿ¦ã'þíWeü˼_‰G;¿í†mÜc¸_ž p?¸ pnç¿)Wí¯ÊwÜžp¶ŸûfÊC&À}{&ÀéPÂI€Î‚· p÷¹ pû€“VD€{Ìš÷ý™3ŸP`¦ÑIÜ/Æ8Ó=Ù¸Gº p?ƒ p:4Xàîbàþ:L€3—àñ›žó÷WëÛ÷gÜOnÌüzI€3³M€xW_×¾ÝëF@xÕ£@èù&pˆÿöœ¢pëm⿼JòŸ_âßLÌü—a’ÿÞŸú•³ÎÛó4ù/;Oüw´"ÌWˆ®‹ó_öwàtœÂÀéÀu €_óΩ¿§· €Ø*}í;sÔÀãJÀL¶—¸»Æ¸ïظeœŠ(¼ 0Çg`Î"ÀélõI€™1 pß± 0׉$À·ŽÎL€³'}®üš•Àç÷‡¬Š¹Ø»0¬Íóç "ó/w¼˜ÿáÏÈ^ñŽÙ?ýuÿÿYøýßdæX&|}ÞÝñ¿ú—ÿÅ¿ú/ÿÁÆÿõø•09ÿÏŸÿEÃ~kqèØ—ùow3ÿû{µó«Qzþïí¶ÏíþÏyÿôë¿õ¿~ý¹þë]ú×?ÿ  ôí~{å:÷ü?µô[!z¬Ý¾›è "L‡3bN½;’ˆS©’?àéé¶à‹x÷³-•ü1Ûa770÷hn:„îßS¦Ý¶oõÓ„JþØy‡›ëWPÉÑœJ¾q÷Î8>‘¤†S†Ïiê×ðO­üñ¸zq°ûBqõþé×.rþ±¸zï¸/Žfø|'5dÿ(,[Ð3šÂ1Èì™QÁ§Ç-rDüˆx Š3òÈ|ær ú†¤Z6d,÷ØK>}–"­Ã[R y¤_²ž©ÊA×·UûÂûHØÜ¶ã€7\U”!þ-qˆ4ŸAõ«+þ“ÿÈåÖµó_\޽ܝɴjÈÚ¡k/fÀhŽ^Я›iÕºCÌuœÄ.ž“ë¦U[ŽdÜË1¼‘‰UJa8Óêƒþ^x’© ô£:xíFxŽ·¤ß4ã¿}ÚÙ‹ÎQ_º¤¬ÙßOŠg­gÞ‹ÏQíÈö–0vðÝ}{ ‡§êóvqMÄ{ø¥ÖØCá[!ù{wH쎧y¡g®ÕøÀ# øZŽÐö ‹O”ß’ˆÉ<üvûûÄïßÃ)Ûz›‘¿·’¿Y¡Št¤SP»+T‘~Ûu°·›!k/Ejêï´G¨ï}ë-ôK1¼•ä-Q¤7›\÷§¨ñ”<çíﻋ—Мú£÷8H}ï&Ÿò½øû÷ã`×½Ç1êBB v<Þ£ûåké3d‘É^w3—Ÿ@=ÜWÈ"£8ä`ïwÈ"Ýg(½‡Ôñ6ܲʪÈÈ }\¡ŠŒæØ}Ä9êBâ}¼ã…ƒ÷Ò5§¨k(Ï[ÐBÁ4°F¢¾Ï³ÏèŸ`zæqˆºFu$¹>f¨"ø±f¾‡¨ GÚny=~ßðŸ3N£»îç Udd8û·Cq¥bõûý›»¬bçµ>K¨"£;ÊQŸ•{³ÌÐgä“x?ÃÛWšqŠú~t]rÕÛû“»¼K‰£ò7Ðl¹cçgþìÀ ÑM¬ˆÇŽÖ×=ãõ-i:Úê34½]ì´Ù£¢³x†Ò™?já^ ¤nÞ_&HÅSR|îÈ …'Ö™B*É£_õÆ'PðÿŽRï§á(ôI¤ô!h`©˜4„‘F*>Ôê{‰#Ô5KWŽà`1jºš‰#ÔÀYžvwÙ­ì,}ÌÌ%µð‰Ð°Ã"7¸|"Þ™OjAùàqbGF©…$ \ò;SJÅÝ])’-d Ñ#D’,ÜŸ=‚:³J½í(HnGŒÍˆôï`öi¥Þ’'oO‘·‹ãtuf–ŠwIÓá÷cf,î˹3:ÓK½7˜ŸËS§¥ßÄ)j | áÈÊßhZS‚©¾üÂÆ€CMo[¦ÐWn&L *}»Ê1Õo'rêJ25ÐÑ*¹ù5¿{¶ªG`¢)´SuËÚ}ì!1”hjð,`D.?6ÊÃP–©¾co\ag*§ˆ¡,S¦7úU°u|sÕ%\Q‘³g±$ì bªVÁŒi¯ÿE·6oAÉ›e’)ô7uèq…™Á{ûÏ<”ejt§¦Ê2…ná°%Ì Þ}ƒ£Ú e™j͹wG 3ƒ÷Ûžš5†²L!ߌª„•çJUéS“ˆþ+ƒ÷ÒV†’LAÉ.Ñzê7;”dªßO>Í z¦zJ2ÕrZ`¾â”;”c + ¿ƒQie ߥ²LÌ;4"ËÖC®iCY¦zÆÊ2…éJo²ÒΦ޶²L D•j,¡Áûý˜Ê2…/cJ;¬Jü*‡²LEš"ýŠvñUò•gŠ kÀÎ3˜ú\I¦0‹è±í FjôCI¦Ní»J¸¢.§J2Uß­VU;´3ÀÆöVɬžËu §4S£Úü½³•S~E;ˆÍ®;ƒÍ¶®­s‹™×î´3ÀÜ­£Šî(º¿û õä¾ûþùÄHÇúùÉ-ɯXšúU›‡%ú™¬6úYT2ù½ƒÕ@)ò» 8Éïýʵ%6ú•ê=¼Ñ¯8 k¢ßû’«aèûÕúU\¡_s^ôD?Ð’ZrÍm^Ò…~‘WR%D¿¦$ÂÎ[Úý2 ýXºØÁ`Å_WuÌçd¿y$DmEöp¶¯ ö›HáCNìªuìé½›êÐq"–"• % mtœ€B© MZÄ:ô#úMDZ`Õ¹•‡wx¥û!µŽ–;±_äC‘]‹¶Mêa±ßå,šÉ~èV]Iì‡ó\mfÄ~Ñ‹b6²2à¬û•È_Åfoj%1ŽèæÕ†"ÐöVòÃD›‘ §´úÕŒ(iôÃ䱄cD?pÓt WªæF?(eb^¡HYO)ô«ïÖH ô«ïè3Býjæ4úÕ·÷Ü Ñ¯U«éF¿æÄ¤‰~-W[³Jn£ÞÅC^G’1üU3°/¨cb$ü¡D[JÁ¸ýV.ÝúÎì‡Këãûìµkûá OD!ökXY@ôtèKúáÐVP$ö{g/­]f¿~9ç“Ù¯'ãJö«6#ûÅ£ªÙ¯§U»á]¦-°á/CsþzwXaÃ_G–O•þ^œË»!üaÓ^>ðבŒLÏ@øëÃ6 †¿žÁå oû‚¿ž!ô °ÀR þPÇ­þÐù[‚?ì팙„¿ —÷†?¼Ž~Ð^˜9D=£ç&ýoÜL°ìÒéŽéïdÆ—þš£%ýl {Å;cîƒÿºã¿ÿzš ÿ°%ÔWOþC.·¢¿on¬Õ'ÿ= Ïâ? ’z]ˆm €Ýñ“7êÄ×ü‡Õ͈ÿb?å’›»'9Lþ» ‰ú4…Ø(i”ÿF·ñ{â\dÔ¬ðo8æ®ù£Dâ?°‡è>ùÏ6É-×óß~w⿱Ͼ!ÿu[·%ÿAéí‘ÿp"Ð?ü@-L¶<4oP €(ÑÙ’p¬‹Šþ¦û×ð‡%ù‘ÎKü ø¹8á/¬HÿÝ0ÚÿpÖcØ#þáˆCˆ`üƒ-“‘ø7sßgüCÚÍK×"þÍ«'jÿ!¬ÚΙ)Ä.CW>w¶"\Rå6¬¤¨$>æ ó?•gq k ê4€JÕÞvB'NÕ'>¶êL|¼ß5⌑À ÅKí'Î+tià„©´Z&ÎLŸˆ#`‘šðq,*à¼V’Z½ù·€‹ˆÌ¦zs@ôƒÞ”³zwÉâ#ll$Î<ß5¢·|i lMEF@\K`.œu&Ogsˆ þîb0àlö40Î ödœï âJªBœÅN @˜¹šöâ3Ä(`ÿ¡ÿ¦XŽüûÙ&b%ÿáþæÁXõâÄwÀâ?ŒXºˆÿÂ.÷ÇlŒ¨Ï'[&¾›Å#46Ÿ¤ ûLeO8”8p¨Ï‡ƒ¤'b¶Y çH˜sz¤‘0'œ·'V#àÊåÂø~Ú‚3Ñš6€On¦¬þ§TÿZn¹­þuÇ>N|_¥VR«Fu7’ÿ.?¹ð¹9ñ a® ñŸˆ(,Ä¿bCüÿ.GLÄò¯à;pà»]š§ø7‘¢U»àôiLເÝ'N¤ƒÕŽGذ§ÕKý>“úW6?‘qÁÇZ_¡³ˆƒT›ÑEbu`x¥|0|b |ÌÆ=œ‘ʈ|òÚo ¯>R3¢Ïµb[ý[¹ÿ¶tCK„ìGþ«ÏÓ XrI1ÂuGø)„¡êóa@8i ˆ#›¹X xÝöë!b•Õ'%¼†’¦'Þ9b€#±[Wkš’ÿ°­Þkä grG§E™–…üÀðØb#·Úm7Z§#"À`ÞF^jEê¼h\²ˆ·qFÀgŸ¹«uBÀ’@¬ëNž"bTKUÖš¢G NL\Uù{íégDêe=¦ÉyÅê–ÿVŠ`&À™g3&@xoª V(u¨çà&T ÖX×!¬dYîÍ¿CBó[ Q£>aº¶аND€p?Ó/#`C&r°š0G„ µE"`˳q# ¶“ê!`] ©k„Ñ»¾V 0F ‹S©Úß7À•'mVk(Šß=žÏLD€måY °õŸ%ÀV'ƈ}ªVQ`uv!C Ö/ ’OX<;Ê“!p–TLË ×“KêX1Qrï. Ä\TB ÄD.GØR«7¶µ¹pv¾Ý¢+‘q ©¯(°] :¢@x€ ¡Dû+K œNnd ¦." ì9´¡b ib5"`¯[K$b…˜õ˜|ŠŽëŒ€`NFÀ†·Kt°êdð‰€c“%pÜF  ŒD#"À0ZP‘!6 °Ïù&@˜â˜©"“jñP>"`{ŸDÝ+lÝžiF@Øb ÃŒ€éï’X}Z—àciÂ8FªµBÀX*…KDÀ?U>y N)o°c’P "`w¦# >Ë".#¶å¤„FÀ6rìgž.˜1îuqi€OMÚ”8ìž`³7ª4À«'J¼.JFÀã™,Âùˆ¾ð› û*^Òû2™±›]•û.‡y'öÁÌɨXM¶,Jì{Kž¯ô×}džÜ×»CÌ›ûF®"æ¾îÉ}#-TÌ} ±—¸o:ðArßÈcBJé$™Ü7gòš¤¿•Èaé/›¥ô÷ÌŸ¸ï|©bßÞÈûªb]%õ5Ÿ$øU‡˜I寥¹•¿þlO*3ÙÖà—:r‚ß©üV^Ià‡­þiõ9Ÿ'é[fŸp5Ô4¥¿å=¥¿Ë™U·ô—‡Ô”þjÚZúÛïÛÒr̪€ÊßJK¼ƒûúÇêN‚V¥üµ–l(éïݦPI¹*øH'mþ£ÁçÌs|z-2îõ̳mÜ îùˆ~0͵|gÜë6t3î­–R¡p/?±´ù4b›öÞoÆ;ã ½w~´$Úƒ©s± xûLà{ØõÞÉT6?6ŸïŠ£‰õ°RÌ⇭òϸç´,‰{sîD{¤áß™ö` àíá••,ø]Î>”ŸëJyOŸËa¤¶ÅgMƒTY|¾ä_Éä3 È÷`Åøî­…{ØQŸ&ŸÃq(ÓäG_, íõ 8oÚCÿ>ÚëÕN¦=,ñfDÒ^åõüz/Û”v4˜¹¿ŸóIñîJŠ~ÒÞcÏ 4ù,‰Ï6ùl¶ÑK“Ïiò9|niÜ ö°ˆúG²ø|»Õö¦¢½æ0i¯Øx$i¯ö´@ Ú+NG”´×J%->‹eãBY5[|þ^çó~ñ1~Œ>·gÅïÒîv£ßÔa¹?§´ßŠ_K8\°Éf B¿å9<Ñom/A¡ßë¾ÑïýLêýTìƒ~OIg ¡ß$ø nT« %¿§lOFN»¶xè·ðÓyJ~N,@ô£¶dÒ»èR÷¤³a°ß*õI‹Ó`¿wá|möøcYU£ËÂŽX1Sð´;-‹Bõ‹à£úÕ4W°Ë¬þ$tÈå¯ÁÎI8H—?ì;|í©³Éú…¿8Ò2hr€·'-WÉ~°N®³ONÙßì7Æ“Îz×¢LXÄ~s;wˆýp¶2?ð‡M¬‰‘ð7c ˆ²~dmŽì‡­åóñø[ÅÓ´Ù1¢tm ß< N‰~Ø %ù=9ÔìñWFy^Z¬R>±Ç–/‹€Z­ì%°=þ’DÄ~ðŽköÖ¡$¿ªNö‹u]Í’ýÆõ|¿±Ý%íï·Ò8Nè X±ßØÎ‚?8Ø|>G70ŠýpfùŽì~²ØÒ?ÁØÖî§+œþ–òÈ'ü…ÐÇáo^9îíð7¶S þ–= ïԨdzÉÛÞéñw?‰N„?XêÜÍod|OyüA`¤ÉãoÙ…Vô‡/¡˜õhã×ä‡!%;Gôv$jç‘}JŠÒôøÃ°ÿæjõl:yü=ég-úƒ•Ë×ão®k—ýÍ;½_íñ‡H*!þMhÐj™ø·í͈ˆ,gQü7·T'þÕ4õ‰ÿ`kdcRòÂ4ˆ§ÅóéøÈ3ãšÿfÛšùS‰ /É!ÜY@ü›·…òßt‚=ãß»úþ;½÷Èb§âŒ®úÿÞÅÏ#_ø7÷ñ©ðo>Úõ˜þæ{ÁòÑûVó„/ø›X,Tø[×JkN±ŒHþ[W=Šÿ" êÿbϪ„üãË%±¦.,’þÃ3݋υïÒö±¦NÌ*ˆ%uõ´t ü Uéë:Pù«Âüðß*Îûcþ›O. â¿óW@ Jã)pá’¿ùÎB×Gî[Ø5Ú0ÖT\ë9ô¾•¡ŽSïËc@¼*»Õç\7òzÏÂùoÞöé7ÿ­¶½óÈhÆ&@|3–g?»Ø¸Jâù/¢;~œþÐ{_ÄÇs[Û‹5uU;Œ¤Íç¶Í$®º~À à0ïÅ’ºFñ€˜5¬+‚ñ‹D€3ýZM€kËU"À™–`&ÀÕ½µM“ÏG¡à €èßòÀ˜·>Ÿ+CNW:†ßýFúø…ÅçÝþòqùCß §mñy?v†âÓ•Úk‹ÏÛG@Œ½ñ•û¯k@„Ôô#ÈâóNbð‰…mñ¹5W»ÓŸË§g濵¸Ç%uxn4ÿEÄOýJŸXÿ„rÀˆjO.©-Û&ŸÏLw>™|æÜ—&Ÿï0$†Éçh)Wñ1rš|vû1§Éçä¡û-,â7??Þ5!v´ÿþ¿ˆ@°ïNÆ%ÿ.K&>ºØVü¯ãw»–뜿ûaÃ~q…]r˲ô¯¿¸Æ¿?J†Îçè]˧­,9ÚRÙÑV–ì¶"²øóyò,Ùm¹l·µK޶à/»>meÉÑ–ÊŽ¶²d·õÏ– ìŒ>ÆA껑Ú!§°³ì Ôv|1þ3¢Ü·’¨~Qá¬Îë¬û›í2,QßqË~9, 6Çxýë/Æ0Fç {¶³–›ŠEjöÝ” Φv%7uÖʦrcM©àÓTVʦŽZÙÆ^ަTði*+eSG­l 3½M©àÓTVʦŽZ¿wü<Áß¹'’ï4þSȲþ·B–ýâ}ÿzȲߪææÚß©çÐfýo³_ Yö;fÊ_›~9/þõoÌmg­_Å¿lëo¼lÏßwƒ÷ò/ð‚Þ¥;^bSÔúðåü÷Æ[®uýé¿ûó»öµ»ýé_þ9ÖôµJTÿóy?[œêß3¢‚êŸÿÕÛs´Êý§ýçñ’L»ÚŸþCþüÿü3ö½ï"ø§óVÄ ÉÙÅ<îβöÚæ»²}⮵w­EܵùwC®µˆ†6ÿôÿ\ï³ðZkßËÌŸšþ§ý÷ޱÖGŒ5Þš®r¨1b¼'.%Ž»Þý–wJaRƒè߫ޥa‡J¸Á ¾oÉâ¦èÝH²ß‚Û‰=FXL%’ëöAÛÛ›‚k.”É`pãn2T}ø[PæÕèÊ7Jà]Pç±5`-áañ–8ãW‰€Aœþ=Î}z„Pn®È`®:=´:N­•‚¡ƒ:"š«`D"©Ž45JÕŒÀÍ(x2AWÁ.ëÅØ—9¼-;ÂËqkZïp…ï;9h!£N¥·+N:Â8Œv¨¡ýNŇ­ï+ê°Nzœ·Ñ“NÇá-"1ôˆwÍ_Á•u}›‡ó/Ô¯¨£25z ›M6ŒãBtÅ …èÈ×÷:L/qÇ·ÝpôBW¼ïnêÐÄÐaÒ”abþ‚ãÊcÓ(¬(oIšS•ˆ²†Nް(|K¦M¬pŠ:8ÕÕÑg˜»¼%;vXÅQopõ°]=:÷åêôŠG0¥·+­GǬŒøÞa åã’鎀:ÖZáKÒá½¢S0:ìHßc÷Í_+Âñ-kDHèz`q4ì¯:œiìœjè0޲Eeøqä·±!! !`\­¼#æãâFdŽ:2 ÿШâ}pbx¢Šågø¾Ÿk”ÃVFÇÉ€Øý³˜·N5Y;ÎáF„v`Á»ã„<‹ ÷t<VœWÅØÄZñ±Ú¸)kác…=ŒÌZñ±Ât1¶A‘\ kìHØ2¦«ètgGr-|­H›ý[kkœ„…A$×Â-Cg•këÈ`-‘[ Uã"µV°d—Çl¤ÖÂ× Ï>'Þ¾Ö:^¹µâk a“uJ¬­ïÅ ×Í ¯3|­uÊ8%²kák­KSbÅUñµ¢NQIøö˜Æ:^á…ϵⰚíÌX[ãAy;tÓD3ñçZ„è%'ÁȬ…Og„ªóÄÂ:àfTØC—´Î»kØ+£9`Gj-|ªØšÅ÷]a?‡g¼å€™µð©ÖG‰àkD~EµÑ¹¬ÂÌK—Õ:å*iµð¡âì4&‰H«Åuø^—U ‘è•p‰¾lœA+œ³âCŲïRq|¨^‚j§Áÿ+´¨ƒÌZøPá¤Å7>|©í’gdÖ—ڬ;Ff-[„ 'kŧŠVÞ1RkÝg_Áê¦Æ9FãÎ 2ká[…jÍ/ ÆEøVÛE¶H¬…Oµ•ËíÞ\WqÃ÷0ÍÁ§ŠƒÛ‡G×U¼ä8ÕÄZøTqÇüÄ~Ÿ*Ü™t`Iå%>ù8KÜZøT1=ƾ¸KŠÓñ8äˆÜZS[l¿* zâSElY¶3caÅ7VxñÉ…5Np¢`ÅºŠ›‰mHž¯ÀÊðâiÊï ¸vBàúr{¿)ÐÙ‚’}D¼)Ðyrþ&r?}bàøb`š‘Ÿ¨Ì–‰6|Úh×ÚS rbàm×¼ º1ÐÒ—9p=v)6"‘•2‚%:|ìæ@©–ÆÀËf /g§2çý6oÊß…DyíŒÐ’•TJX%%Ötd1¾“ƒ ÏØr01p×1v{^%:âDR`ó‹I „BG¢3¦sVb`f¨66SBb`oi F ì-ƒ;Q"áU9Œ 0þ:ާF Ä®/CiÞ3íã…ðé©6 Œ:6µ „l+ub`”ü8(ð^FYS ,ÏÅ—²²í‰±å´ß'1ð^6e6YÛå0¾WØ¢Y ¼ùYl -ÚÂV«·Àé}…/Gghb`GØ•C¯–vD ²Ñ‘ƒÇ90Är‰ûCnöˆ?HÂ#Æáwê¢ÀŽÜkÜ—‹;öÞ9ÄÀ')“ãG|wäÀ·@Q„QÀ»¾%ž…¡:T«UðåŠû]” F ìÈ ÌΆÜ?N ìaE¯EuxqQ`-Ü'ƯėÄÀ·Äç/ÂÀ±DX‡Ø‘½×Ô‡ÕªÃõ‹# [Ž b`Gü>)°?Cél=Ò lFÓ´%ì°å3 ãB4¤ÆÝaáâ‘M×6Çø–kÑr;) ’Å#›î€3¢@þŠ˜J Œçäé‹(0އDФÀ÷¹<#Š£Ÿ‚Uøè¢À8S"ˆÆÍpݲ!†}‘Í’lq Å'öÈHÂ#F Ç 0ÌDh‚- ŒÃ+¾Q`œ^qƒ" ìÏÔdb 솚£„»7‹žøUŒ~c ëüH ì0 ½ˆŽ|wNh!†KçÍ£‘&2äÒúÌaê#F «ye^šØ‘.[ðH Œ:ÄVa`ôÄ eyñ¸ca`<åÅ:Ä@Ö!x£„d ìxg‚Gbàq‡ÂÀèÊ’ÀÀx*n?…o‰EaàÛúKç«S®~fÀxlr¬ðèa1`Ô!Š£wïb@\H7'ŒWÇ· Œ:[&FÉÍ’¡óÕeªF¥¯.™½›; ÂÉÕâÀ¸CnßÅ©1ŤX§¹šxtŸ8&ì‹•5®D«ZY_ÄuøÂ…‚1È?BÁ8f ;LØë‰‚o‰¿P0Z&Õ‹Ù;?6 Æcê„‚|5ä(¢`ܲ®hm…w‘J´¶B—%V­­K'–BÁ‡Þ!ðÓÚêPÑBÁ¸áÂV†WÓ†Q×f¥ÅÕ!DÍ‚QÂoQ,XNŒNn' Fe±àÛ¥:í3 F ?±` /“ŸVWãY0Z&‹£¿.^}hu…"Ç«O®®Ù_bÁ£Û ƒQÐymIº“4øÚÆÁp 8qðvÈÔÄÁÇfÂA,ãâ8áàVË„ƒ€¤õÁÁÛz‰ƒ@:!×,€ÙO4)ž>¢à}i3 â7ãƒclW0íÆŠe¼9Æ,ˆ‚òaÁøÑ‡#¨øOš`Ó.z³ ¥uÃÉ‚—ýàÌ‚—×ÓdÁ }”,xÙ++Y0{8Y0û3aðrTÄÁ«î„²„Á«î­„ÁËé' ƒ[A5 ¢Dx(Œ:lY4¸ž"¶–ÿŽP0JÈyDÁ£@(¸S„‚G¡`T±M¬XûGFÁý+£à~$£àQ"ÜiD‰E„‚g Qð( FÉ£àƒ‚(™D‰CþpÁŠ:E0êÈòÑ·š%DÁõØ¿Ó(§2jŒ 탂ñ£ F•SÜÇÍñá>ª®÷ÝãÉ\¾–“é,ŽL^h pÚömK€·#X[Ä £HZ[t@)i€óÉ N[\ö•˜ÞßÖv=@{Zÿã`9 ï^™Múœå#'ýï®érFýÓÉúî»Ø›Ìúßí8E¦>h¢IQß}gÈIQß}gdMë·…SߗʧõÁôWÖ£¢>¤¾¦cêï¾ÔY“_™©%K¦¡\£ ŽòXÄÔ‡–ë)B å-›únOôa#/íÎ ÂÐñ7–/® É|°^ ð~ìÎnæƒ6*¢²x]Ix:¤ÌÐü)âRÄ.1®E=%@¸±K€8#‰YÜ%–/gÈJ ‘¥Oæ{å"@d âÝH¼œŒ4%ÀËAÁS’¬^N—›àåH_©^N¨“à娄©^ Ê— ‚?žv !·ò… ̆-^Yàåàì)–ê–-¿½”ß±Êi>%ÀËî–‹-LS,În °8}Xj€Å“qj€ÅAR¼lDž"`qÌôm„¶EÀLž"`‘.³EÀ÷Z?‰€å²4gðRhÉ-ÅBÚ" Œ\>ð‡«ßB=‰€ö»O°¤‰¦UÀ"Ç•T‹ÒHn°(–ÔV‹"ÎlÈrÀ~%ÙÒ2 «-9ïmPFÖËü‰üp!ê©–æk€Ù©åDß Cëo °Ls§4@û>l ÉndùI Ðæ [,:ÄÜ2`‘÷þ– ð· X¦U7«€ÅŠUª€Århª€h†Df°ŒÔ¥y l°(.ÜV‹‚Åo°(2ÄV‹tŠ­1mð½úP‰T@GvJ°XçJ°¦ ¼°pP ÍC¶˜™`Qª-æ¨N °¤¼g °(­Ó–ósI ð}TËR,ršÙ`QÄ£­ú£ß`Q±­ÅçØ`K¤ˆ°Ì™+5ÀbúO °tkwsØÜü‘5Àb3èÔ˰õ§5À¢ýéÖs¤èHÀ[„í8­–aT³è pk€Å2tj€E‘t·X”æzk€ÅF·Ö‹bym °È¢Êˆ D²E"btù£ñØ6†!ëO"àOžÈHL³hë¡‹Z,ÙRÄññ „Õã!J¬  ˜`•QÈÖñ•}EÀêímŠ€ÍyRJœàt6ù§¤xË*5À HaÜÛÃà#ªëZ¬úO$¸Í–D‚°$ê„áÆü8ÂF©~@,à"U‘ ômåA "~vû(€Ož"äf'Z‰Ÿçq Yp Qî%M® ÿ»Y0¼§”¤‹,8®e¯,± ½“d!JפܽÈÔN±:noSÕbÜÝ' Žrµ¯=hÄZ¹O{ÐQ2†Š`p`¥u´3º. Hž\þƒ/ce:Âà@tºqÂ`8£("ap 6ÞuÂ`\Ë!’軀ô:· ÑÓhdZ z/ÀgH!RȃßIW GŽFq2x0œ\œ"Þ Hs<8»9*½.çÓµ[ >ca¥üËÈ€-ò Œû;y0AƨK +#™È/UõäAºû°eù ‡Ÿ«ýáFÄ¡l¿@8BÈOŽÈu\d$Jì)êiýô „ëN•# =° â–X®õòa×@ìyÄ¢r „‡ÍsÚ„„ßnÒéÂP[ZŸÊ5°FÌ „QÀñfÏÀðå9pD‚/Ö‘g âò”g ‚òìX«Lºíˆ8†íÔGä&EÊ3°vË>ò „KÐ)Ìs25¥c ¶hœ»ìˆ° =™ð ãëÞrÅÝ.KÙ’·W Ì8¿^ër‰½1àOkÐèsqž¼oÙFo¯ÀGRz>Jž’^¸c™_¦WàmÛO;^:n<—\ËÒ1pÆìˆ^¢–ŽÃ>•Û3°»Ž=×2šÚ3ðV–ƒô ă–S Œ’ûãˆ~[§Žv×éù³¾žï‹¤(ÏÀù¢Ò3pæµåˆïcžæ |W' ÆÝ¨Ž\«¤k ¢óN×@Í®9 Ò5ð.F8»"5Ó©Æœ³N=0¼d9vÒ5p\¶ì´kàðwo×ÀtCM×@'²JßÀ™¢#B mÌÐl å'üO„ åÇ8ä’3ÄÚoÿn×r,4Û/¯°KvزŸ¯ñï’¶¬a µ>meÉÑ–ÊŽ¶²d·1¨Ççɳd·å²ÝÖ.9ÚÂÖ³}ÚÊ’£-•meÉ?wh6¤cèã,4[ÿµÐleüôÏŸC³½¥ã·ê2šQÍhF¿6,ú ÉÉŽõó Æð|*¹©uÍMQ×ÜÔ®¥¦ÎJÙTF]Ë¦Ž¨kÙTÖrSG¥l*£®eSGÔµl*k¹©£R6•Qײ©#êZ6•µÜÔ?š-’ð„Ín¡Ù~ÏLùkóÑ/çÅ¿þ¹í¬õkƒø—mýágpoïšöÿ§gï·~6ýO»Mÿ奅ûO÷.ÜaÎêßsÖ@ªŽr6ó#;{|*Má,Â{=ì†Ða£¶d^а¨rVMcÃ6a:¬ëÜ6jÈV£ä¹h¦v+Jæî guÅ hØý„™šã7¼Yi¦v+püû¤X*ìRbSÖùç–±¼ê´!K5%o‘ó ZÖ"[6iyƒHCEO ¶ŠxI<¡}X°¸¸…:q_?"8Yã5î¥óYmV[{:h›‚·´N/…m€ò–°…;yLëeÑ +ïHC¨aâŒ%v±|KОŸ¼åP¢"ö˜­è ÆcœI=ô¡æ3)qMØ(°`…8ÂüÍ;fà²áù&{¤˜ˆsÞ‡UàÏ,‘,NK’N„¯®NÛ rÓ‘^q±J-<£­ Sô–<<£mLíÓF‹@9qÔËVz¸$„sgœ¶AÇÏžÉî‚;<ýö¿ÉQ®°ÎjòR’óUCýP(Ð…%7 „â篞I…8£Îä™ê@6EŽÅY ã—™¥7IJÇb[á¬!ʬ¾Uñ búã'8çŠ !ºð ´‡ÄìqüÖaB †É+‡e(ô2Oä“€úÆfVñ{K<h‰,)º»;Ì^âd::tÒrs %Jœ7¶ÅÄÔ6+Д?ZK–7mQzŠ‹óG5Î!">XtÌÂyT„!i¾%‘Ü2¢oqbYá('Õq¨ÑÖ¨<­Í?B으*Î[9s#¶ÑÃÅ‘o»âßwå¹lS|û¶z,Z`ÇaÚh¨ ý~åqî6 ¿ð-ߥêPV.ù A W=–F”Å“oö~„‡ˆhY Ð`-vÝ<^¬Ãƒ­}¾Únž˜ ¦jAÁ 8½3?Ø;ÝíèvÞ>õ¡lã¯îÉCY“µ›g £æt«•Å#Ï8iaÍMYõ›‡ìXu ÕàŽìˆøcüUÓÞ®i²B£GǶ|nxŠwãq€?´€ l¼Gm@ {~¤Žï§K­)tÔKä0š·®Å| ѱJˆF#ŽÂ™³·_×d\à©CãHa¤¨<…ÕÛZG£Î‚‡-Ó8à„G#žõ,Mh‘ˆg=J:Ø/æÐ‹_ÅL)Œfl…µ ô‹ÎAìoç¾xÚƒ“±›%±˜F;•užÏy¾wˆFqÚskrŠF-Nn%ðF £»ñ´gòW5Ó‘i%#‰¾Stg3‘Òm@.[*ˆµt CÎào–ÓItâöD^··.TP´±H_g²H À6îΓž"·ÕÈ_„/ùLcå‰üEwŒ>}RÈ_”'=±VF£8éY²7íÐ!ÊRŸw–Äz:´Ý@I[ŒÕ§Õc=ü 5B·ÈñÃ7…¡‰¯» >RÝqÔ£ôÈa_kÄ’âBµeß„ÉZÇaR°F²$FïGVƨ±Ÿp2vË\8rE¨©…¥ƒj#FA5ªpHà O4ÑÁ+Ú,ˆõt4[ç"ƒQ|«ÈVÉÇF#|«Py¿mÅz:°¬³"6çh©Û#Û%:k)gu$1·Š$V1‹ö~q=m‚‘F#tÍ#ÿðHb„µ_T"‡‘~ÒY£q=pþ…%\O»Ý?#‰¾UüŠýÙTÜ¿ºHý4y¥¦.¨(aÃ4#} –¾¹ "Ogä0ê‹?Òípç:p”ÉL1&dU9Œî~J±‰FüT… ˆ,Fñ©Þù«ö(ïµ’)²á[Å)åäF,©Ý™Ž"‰¾Õ÷Ë¡ÓGü¢ú5 :ÃGÉÍË0zÝ舌ð­bïʹŒî¨sk MšEœ†Æ‰Bä0·ù ã~ke±vrͨã9kRJŽGX¬Ó¸°¾W·®Ÿûä1¾9žiü¾¨f'óÝågæãN`3_R`2Ÿwë›ù$ÏÌ7¸ÌoäSÉ|Ka–7ò-÷m䃢Ch2ò-)bùn#R"ß- Þ|x?âCÁäH|ë&Y ÷Ò›ßÄgו¾tØ!ð…_oùqߢýÌ|ØAá€Ï6ðÙ}ß;ƒ³å¾wBà6&‰ïz Ž&¾RÌw&¾"k_ñ.‰¯ü‚ø £…nâ+ WœÄ†F¼_X±]ßíYÄćpk¤vÆS|Wªûú‰ø@ÌÜßù2*Z2_øZü8†@"_¤·ú îöA¾Û©°ùn«Ë‰|°Œâx5ò…÷‰ÈaÑXGȾ.¹i•–$Fæ g ò™/<"ø˜b¾0\#x‹ù‚èy<"è ÿÞ ™/œ&8LÄ|Q…°&æ W…‹¤HæÛÎ †¾8à¥}tC.:hÜrý0ôE;$ à&Úà‡öŸÉ/Ï2“ü`´Ô?䇜 äz“Òð)M~‘áC~¸]]äwEBLòCª…ùcƒße«ê¿«*¨ÉT<¥1ù]EæI~W•¡~’.Ä9Âä‰ xm‘~Åanò»ÈLæ>\šÓˆ¹w×ùqá‡jîÃáð Z‰û®æƒ&sú“#Ô܇‰JÄ&îÃD%~÷Å ³DàwÕ¢£'²ItšÀÖeƒ%S'ÕdGq¦¿°WM''sßµiQÜ“æ‡ûPg’ÎÄ}¸rüÈØ³6öŒ±ïjò5Nì‹ÛU ±çüâ}ÈžÉG2öí4ù]Niœäûq¢_¤6gÐ/:‡OEôC5£_´B®úánx8eôø/§ÕI´Ói¶ò»Ã˜%ÿÝaìòŸƒB%ÿ!TÌÍ€öá?”…0EÛ‰ÿ‚YD{\¨@(üCÁýQünGOüÄôâ‡î!ÿ™l'ü»Ó{+~E–ç©øydnÅÏI5SôëZð¶è׿P¢ßœnԢ߼]Á¢6¤_ÄzFR3Þ²ß ˜*K2àc€J\f,3 ü_ø2Í€PÞT"Œ­òa¥ÿAÀ ^œ ˆx·jƪ_5™ŒkÕ¯+¬Lª~˜»ˆXVýº3U¿¦ÀI[õC‚æ¯ìWd¾·u¿%×—­ûM¥%?t?I™)û mÙ¯[·JÙ¯º+Ä€ïÒtI¦F ß§¹o‰|dÀˆ×IÅŽ eY ÄÅ©9[÷Ã/•Ï«•Ï Ì€p@¡ÖcÄÖ£žÂãw’ØŒV•hµêÓHjá¯)ÀVþ*çàdÀP@þã ÀŒ‰»u¿®ÜL[økrcÙÂ_½hˆná=¬™ïi…Q¸üñZøƒ— Âß5аÌÚÖ7¾kØ pÐ$¾ï8Îë7ÞŠ<žòL¡'…<É×TŽß”ÿ°ls[þòM&”ú‡mï7 б2Rýƒ÷éÝò4\^Iê;?õk°0–êß•³¬Õ¿Ô†ÊKt’øwÉÛ xKªJœÉ–FÀw"‘sa,øXG_Y]Êx?®c\Ö´§B&ÂY–Ûp#`ŒGŠid@ f>g2 6Ÿ„71àªf73 ¿¶ƒá^Ø(À‰1N—b@|w‹×6>‰ofÀµÜŽ1pNi‘¢@|6ãCûí™Ñ÷—³“—?ͤ@[À'Â%†·l „#MÿP ÆdùPà“xi ¼‡A1¾ï÷ÊûdT3’Z…ð å”d „廯ˆy ú´°Þr¸ØèìRɸ?rs LzxºaÄ|ž0Æ4ÈsàmQ89ÐÆ“1ë‡áÑÍH,«¼}@“¸|úbÄÜɃs fõÑñ¡Ã“ý·Â™mö‹|?±ßúØ{Bž¢d´Ù¯ÙN3ÙojŸºá¯ÿdï‰:õ#þ¡„'ÕI—ÞÓ¦?ŸBmú»,z$ý]Ó†š¦¿KNÏ›þà=óQÿâeÞ™öžRïÒÞSAD’þ.mú»šï/èÏá³7ý]Õ¦§¦¿«Zƒ3ý½s ©hÓ_µÞgú[] ”ô·|üžôwk'°ÀGþ,ý)ú¦¿¢@s‰0¨Z&þU3lâ¢ãMa˜Óè³jºéïQ+¦¿ÂÜkþÚ2þÒÈk›|NõMÂß°ydÂ_3…ŸFŸMÃ_š$'ýM?SÒß­È ›þ »³Ž>ފ̘FŸ x±éÏžF›þe\Lú»•y[}^Ê—ô÷ŽP;&ýU‰ þªEB[}æ°N«OÄá•lõY«íK ͬl0Ž•ùR§ÁÜfŸWÿ*€qB,uÏfŸÅÃ?ù¯È†7ñÏiv7þ]ÓÊœñ¯ñ/ÚUÚ}†o,5Bã_éIú‹êIþCʦ'ûá!X’ì×þrª|â'ù]Ë€fòK;ò$¿+yÑäw¥hô+Å¿’ágn“)~¥ÛªÓèçùÍ~—bÌmösÖàd¿œ´Nö›D2±ß5¾â_ÐÏSü#)“­L¥Zmkû ²©DôW¢é¯˦¿·=~ÍI…ŠÜ†¿êã‹ i¬jøKëÃ.ÅÏ;á¯*·Ü†¿"ó“„¿úü õë‰ýš¢–$ü¡†˜ÒðW¼¹Hú+J´é¯<¶Ø4ý¥&=è¯J“3ý¡+l *ú«Ëèiúk©–™þšŒø7ý5ï[6ýé9 qvþ¿+ ¶ ͶŒ ­俸4÷tþä‚ð‡É¨|àïrLÎMMé˜6ýùXiÓr´žà>3HúÉÅý¡¿P0$ >™S›Ô‘ô×”{dÓ_ëîŒÍœnüÛÏeüÛª§Èþû€M§IU)9“þš·h©$õ¿Ô¦ 8E¸>†Ÿ(áKHú«2Øôç…c €°ûùqÀFUÎÔÿšb£nø³̆¿jÉ7á¯:RÿkÞF§þWä$ú“?@EtKø«Êž¶á¯>ú|·èO>ÀvùWaæÎÃ_S<œ XÎxqÃ_¿l×i °ù J  ’Ö›ó­N}¬I͇@I9lSÌó‡Ô›Ûn °Évk€Šºbú ‰Ÿ>ü "ø—¹3E@¿ß-N“¨EÀúØDÓô—ÓÖ)ΟT@þ­êØúPÉôœô×”ËrÓ_³‘ÇV=Ť èÐY©nÁ1UÀË·,ú³ƒÄ¦¿&Ž­6›º§ Ølž±½oË_èbù»Ã˜m#Ðçt¤UTv | ‚ÓžA„KüŠ€øºˆ†Á¦ÓÀ ‚- ‚]¶¸»žÁ¡nƒàP, ‚#Ý ‚ŽÂ»AÐÇokfÁm9f„M•˜“ ‹‹ Üx†¥ÌÇõߟZ›,nYÄ´ÓPÉ“ÛK"•003X%f:´Ä@$6ëC-X—¾sc`”ÈÄthÁ‚Ë!”ˆéþÇfÀødù‹5SŸ§h,¹² }¸X!šÊiú–,íYÉ€q¨7O¤ŒpZƱ£”»ªåjÝÆÂ¦å*½qLõœf QGö¥C‡•×ex#ƹòÇ 4NJË q¤ó•Ë»1£­ž%@D–ç_œ¸žà[¢@>öüC|@Ù… qtÅ‹ qnÆÞ1–ÖMŽrýÃ9Ð}𯙢¬>EøÕGŒ³@9ŠãÌé#†+¯þø´² ª¥O«j‚À¸å"oÙ‘x>Þé?eêÃJ|Hï¿aײôþëÆ|{ÿ éý7dÞ!ï¿~òì8|°’€CFBÛpø<)}¡-Ò3}=¶Òp^þUúZáM@†n" š}~û’»ùW‚¢8½+‹Tq ¹TòÈ]×Ts .-Í*àìI}R§,…“ËX.¢e1ž8Ï&_>q`üЬhÑš~?b‰0sÒ#¿XY1õqè™1‘]§ ˆZ“¦ 8ªÉË*àH2”è´ÆÉ¨òuÄ ÿ| AãR*ÑÂÚ×Ï* &ÚBSs ã1eJD •%ƒ ZæIEª€oËÆ>-¬Ýç$V»5!ƒ šááŠ@üè ‚z÷Ç¿;E@Û ¦ØËO† ¥)ëHr êL•x]½ìß·¼®Ú÷q«€~W©v9ælpX†6bpñZæÀâLÛɸŸëøVÿø¢ŽÎ* H¿éW?T •9Kø‹G£8UÀFEà­ß¦˜n¬)âüåÇAع<@T‘í¥5À&7Ö-* è–›U锿=!%åGK€}é $%Àöu,uúÚVë£+DÞ‹5(†¦X•‡s €U‰Â·ØDâGü²wƒü|cäÌÔ¹Ž¨<.9ãýöïv-×ùÇâ—ýò »dÇöúùÿþ(Ù±½@³}ÚÊ’£-•meÉnk»|žáÆþãŸa—ôÜŸÿýÏÓì(ü·¿9„þvx³ÑVÌ¡ôloùȳ=ÎU#2½ßl±$âó„KzX’~…Ç\ÒãÏÒ™¯pÉ…$ ̛†5¡ð¾%¡o†³ù-Žbö_¬‚ÚÊ•×YgÄÖd§ ˜¬™°ppã0:B×+YÜn_M'·Šš4údSt'g»÷ͤg—˜ÎøTášÇ«ïæ®ñàÖ¦²c®}8î üzKnå¤eçuòàR㈒ú#žÙd›ûðàfçŒ~óà¶=ny„ld Hc6&¥°ó»Û¼xp;äø–Ä1c_,¹#Tt8Z¶ƒTôÆàíÌë¢ Ï’çÖ[¢Ttq™Y3ž-‰ÄcÖJ ž¥<ï½]òß(<-KVúoð-Ìv©QróW£21ý-~‡UaÁãÛ36á Í.žï}\ÊÇ.žw¥ÿsùZwdÖ ÏÉvhÞ#q„úö^WØ6ŒU"²IX D á(ॅIºœðGPŠ~„Ïte•Æd‘x,ŽÏÞ’‡9ÏèãÝ,šð\Ùîì4áÙ%@z¥èRÁ£¤gЦ?r3,xàÀ~:‚/ùµŽûŠ€$;ƒÈ€ƒRU°8“1 åÃ! Šú4þªe=“V;0XÂê|tâôGo˜%#ÌÂâW“׊`æ¼AV™7ý‚«G1üðÿDÉù™CI2û€‹}øo8üÏÀ+ ÿª\¬navéCg¨øïø©…&ŸïÃŒ«±¤7ºpÔ¦oÖY·œ×ù¹B©7%ÎKHDz”)@t@Ä(r^?;’’ů*[Óãp¶i¬‚,Gÿ¸øûý6Y¦=ñg¹˜AÆ÷;!i„op½INºwØñTyõÌÖZ°±YX… ™¤Å²F¡ËSœNLØåÓ_V0Öó³òZ±]×n®êOSÚ– SUºñ+úÄ~8_ 7øme™V¨›Í°¶}ØN Y0(®ËÃŒLCrÊ ¤˜‘ih°Â‚‡Wr:Ÿ‘hh°Ý‡%8•ç0ü œãݼôà†ÍÄi÷Œ#ÙÉ’XÏ&Nˆãƒm24š‘jH]Á*7—Ötíš…ÎмT<R U'àŠ:‘jèf3ÁÓ³Òz(J¢C+ʱáx¤ ‰Ïµ)¡ÙŒTCï//² u–°‹‘ ë1ão¦>Ξ@€µ¸²| f$rpÞý®P'þ¤úWaß™*Û'ÏÈ44ÙHLd³1'#]F;‘i(…³q`†Ùãd;ífÎ3»¯MdŠOµ)ÛÕŒLCÑWñ@H3Ù ÓÌÈ2¤~ꬲ¸ª¢Ê'¸#ûÇLôe¤’9hãÝÅo2Cœ‘dH–®«OS(ªI†&dzK¸®æé Ó¸8R 1•¨üþg¤ZüNøŒH145§… 9#ÅÐÒ•¢€q£ÝÎ*‹‹j|(¼ÔíEUp8#Åròó ˜|ðH1ôpúŒýÏŒCZb‡6‘cˆ9Õå‘bH³4r MµÂ*]«jUbò‰CöŠŒ­êŒCóÇŽÌ:‘b¨k)ád)†¿„£)†â3­2Pž‘bhýع'R ÅgZmFŠ!æÉ‹? ×Tz‰gœl-âÅ„=Å[Â%5#ÈÌH/ôp³ÃF»WT¹BÌ9¸¢Ù•ÏÈ.4~ì¤yé…b5— ÆŒìB ÃOÙ…büL×¹µ¢^Z»'BÜï@âR‘^H™ØÌU´¢z—2#½vHqÃÈ._éûÕÇ2<¿&‚Îõ4îF%ZO«c.fL`ÖZÞÍäzн'ÜÈ.¤]ìc¦òÔíd¼3ò î ùœëQ³œÇ#»P„êÜO¸tÇøý çÒÈ.¤t½•¿ª\PÃ]9ž;Ò Mºó½ ½Pl€"“GK[P^kTm€u¼š˜Œ¯nñ¸â÷…:;ø/ÎÄâ?nþ7ÿ)÷ÙÁ´¸;ðÏ,—8þ"Úÿ-¯ÍK™ 7.…îÙxËVrà-G® €·ç@Ç'ÙxËèß»‹ïLQ?Y" {ŸhƈØe¼? X3^{ 2>,1 š(g¼†¡ÌxiöÝ)™%À"ã¹ €ŽK¶°,®´«²Jm¬> €¸°jÌ ›òYm„É%iÊØVòž°+Ú&À^ÕI€PHš&À®p曇‚_m L¾ °+ÐÅ&À¡Œ½›‡¦õM€CYp6NùVlD^x²›pN—§ìÙ€à€L(ÄŒAR#ÞsE€ñ›¿…G@Xj 5E€(á!… $>ù+`@éIÓ†‹ &ŒvâW&@؉ñ͘Ñrÿ Øœ½e„åXØ ¸\"Ä’vóZ$@Ì^— ¸^Ýl#L€øÍüàý<¦ØÇë÷ÀÌþ¹Æ‰`ÀK {s–ÞxÉsà¥bàU ’ÀK&ú±ì±ŽðRõ €N³¾ð2Нe²Ld.RñߥsðÍx|r›ùÏ)Õ7ÿ9‹øæ¿";ëÍEsïæ¿ëÑÞ#ùß [6ÿ¡«YbþsvôÍEô¾ùQXÇüçt¼›ÿŠIÎøWydã_‘ÿÍÆ¿ÂHˆ‰å6pÿŠ7–Æ?§IÞøW´ànü+J–ºñ/‰:ñ¯Ê¡rã_‘Ñïæ¿ªykó<;næ¿*µÍŒ·ù³QÎX«Û1Vn¬îãÀª´È €ö¨<ðöíˆRŠ×6VF¿Þˆ¤^¼3`•ÑéfÀÊè÷«Î—6V&%F@¤ š[ÿË—=e`U¨ •© ,ÿ/w“³K®láa}b7ïmh;ùONÀî3CvC%øBðüáŒXkE0wUSut!@nU}ÜL&3_&ɇ+~ëlê ÊqYH§·„ÀʽJB`ePå„ÀʰAü%V¦>K ¬"±Ä@ÑPb <Ï’ãíVÇÄ@øõ‰ùI9ÛÃY!!ñ+.¤¾X—¨+ pñM2½iB`ã©_B`€Y@`-¿ƒ@:|]O·/â¢`Àx„‹½ Páƒã¤00О[~a —~+a ͸JXF98°2½Ir`¥Cjp`¥¹cr`Õ80R°'ú€&–É«‚•>9°À™01°2Âkr`ÕX™§:@Ð튕Þ"8Ð~»úá@kø|8ðTFŸ ô™%äÀœ‹íOŒ>q /[ µG«•/Tè“¡?·80ÏÄ~£úfUºÎU©!úÇ0œ:W¥Ïäßz–$è!ëo<: š¿Ãd V+ N†=¡HÐD²¯h”å@,h%åÂ&›šÄ‚æ7AB# n…œ ÜòÙ ´xe”Á‚Ö0’,h@¶‘(_Êm†ûŠH‹{± Ëqà3‰––% ' Ž&ª N¤*IœtiNTfùDÁý)…‚–ó Wã &QðTuY( @t‹f0Ò“ëÕ“ZàÁ*u£à‘–(¸óB „sHà‘‘` ÍÒ ‘ Í "Aß[þ¸@ÐÎî Èž_AÐbˆaG-4W܉hQqâ@?àE 9ðG‹ðZ4UÜJR bÕ¦8–:J!OS l´ M)ÐÎfQ")ðˆÎB \“ø()P®û)ÓJ%°ë« %P1ŽS ÜUÚ ”ÀÁpt©Nº¤8‹Žh÷ª¨#%Ðl A†TG`©”Àñû¨ŽG *%Ðw¥¥ŒO!ÃçæÀ¡Ç ìºwˆ”8ƒßÄsŠ'Å–w´&”_Drà`l“ä@EÝMŒƒ™8±ƒ œ\{-ë6€Í9ÐÒ¤ƒÖÄ“fõÉ“,ž8˜%-9°Óo79p-8paŠóîâÀ1~Õ~“-¿í—ßñ7I}ä@3G@qàìâ3à`IJAÐNìKµHpæ‰‚Úø‚àäáT‚ M__°Óm"ApÓ %Ap3;V‚࢛D‚à¤Ýc‚à|~ÁAÿ€Á£Mt€àæyK‚àZ¿*š=gQ‚ œgeœ ¸yx– ¸è÷š$¸´ ”gL’ R' ÊÈ'QpC.ú¨'.îßçÒ}Ä6m¡Ž8ðl¶àÀ-Y<@p1OS‚àâ*™ ¨™"Apâ ¨ì‹É›‡“É[úap $ÚüóãÆÀ©#‘ÀÀw8aˆF,K |8h+ÁrÝJ4×7Ρ†Å›Ç“É[›ìÁ÷VÄ3à*b:àdäŠÁÉóÀAe£ ÜP€àÈš¡S ¸èi™ hI£Ð°@Ђ¸ E‚»ë*‘à:z*‘  ?›Pp=B8¡ ?À—P0Þ` `¡àx(÷‰}Öß1“€@Á¥é&Pp2T@¢à¤[r²à “U² ý_ÜZ-‚—:(”–(8ƒ€(8èæ–((wÃDA{&›Pp†¸'”[¢à¢ Z²àä¡u² ñ$A£þþ‚Wöøìâ??ø ΂.þëÜ'ÿ=´#¸ø¯ÈÖ2øOV~ÉSr\ðh^ø÷`Úºðïùù ýÙ˜ýqEú«:MOú«Ü{ý1LNÒ_Y*ý)•WÒŸy%MA+v$ýUF¸ºLA¹b&ýU.A—)¨”µ4]å‰ 3ïe Z$(JT˜Ù¤¿.©-è¯Ã}=tÀÎÔL©ŽþÑÇ#Ôü)«JÁc|&ûM&MPÁSœ»ï'Í¥ 8is“2 M\(ý­G†«’·;eÀE™(TÀÕIN³SÜœhRܰۺÌ@I'4ÀM—ÀÔí»ÆQTÃw(|R7ù&DÀàW)næ®Iðh”‡x¸B¥xŽ„9‰€»Ýd¿çù…ý\R£Í§LV†ìK[š¬œ¯èiº*4@®©žŸ¿H€*¸Èy¿G\ãß&ø)Xæ%ŠBSÔð{þæÉ;—8yò”à{O €SÒb€Köž!VÙ{†¸…y\œ^xÃ5ä¾f­â¾"k4êG–œ¡ÿ!6XbŸ"À^òßx…üÇä’ÿ` û¬o€³[þÃÍCþ2äö•!1ä?¥\柌sÉ! ûìˆþÇM}¶›øR_œ§ü'KÓÐÿÛSÿÛ|òKÿÛ4ö”þ§Íy`_•ØWh†réMöª¡ÿqRNì+LxséŒoØ÷À˜ ©ïIƒPR_–ˆúа9¨¯0&FRŸÂõ&õºOõ=´œIê+²Âõå5¢¾ÂcŤ¾‰ƒúJ#õ®I}…>I}å‘5gØ€–û~…òx€s˜%÷•ñó+ÿõ$öƇOì+“­ˆú “â$õ•É/&¨¯Bå–•s`_a‹Ä¾Òùˆ}1úû 3ø&÷™ðWþ q<¸¯0 _r_‘@pŸÞU`Ÿ;°O¶ø‰}eòÓTŠQ.étOž§bd¥þW~Á¾²¹áì‹è2…ÜØ—†™—(†Z`_ ä¼ô? N`_Î¥ÿ…ª¨¯6 –—þ‡šûϯ¨ÕÙ;P7ú§$({’K¤Ï÷%΢!Êä;@ôÐÿ/óÒÿB ýO#) O> }µË†RÐíõU¶‡® pIG¼@¼®u` `åS¤8ÄŠ¡.~x©2$ò¥j¤¤(Éœ `!çö) ð¥"þé%j¤§¨•!À%~ Px*€Ì½ùQ)$†!(þFij‹m=ý Ý.\¡ Jd©‹ü& °ÊÞñVçWdvˆ‹‡¤¼ ÀI’,óW, P{ €¨’¥p>‚›ƒÔÿ8µ_ú_Áþ4å?¦Ê¼ä¿¥‹€³Ê`3ä¿ÃÝ\à ŸBàf0À·[p@ ´Ÿh)ýOÃ%ÐÏaÐ`œ‡þ·$…þ·¥Ò@ÿ«ôi ôïÇE€aChãôk *sü7>®€nóã@3qhò_«¢Ï5B§g¢ä¿Æ²)ÿµ)›S鿀 ý±hSÿ“ûIê ùRÿS ÊÐÿÌ–ÄÇõêý­ ØjJûë¤çþ,Ù ÿŽ“¤ò×é„‘ÒŸ1É‹þ<3( >%ý5Éq!ýñ@0ñ¯w©o’þ:%œ”þzìIúëMò ¤? ‹v$ýu† é¯/uGÒŸ¢å„ô×'á)°o"¢°3Vl`×YN`—5lJýP«ƒy/°ˉ%ê$vÆ~L4åìë˜-‹9( °Ë48PQ‚»’‚ÕA2 Bù$vfÙN´ãž7vé.)ýE«bÀ.O’`À®à`ÀN“ßdÀ®Å7°Ë)°/ñ°S9Mì´N Œ†ƒ³èRþ–ì0Cù;<2`—Ê ¨ÜÁ€n7€ º”Øå©‘ÊŸLqû‘™¨°3ç^"`?&…€ ùŸØà?°ñ0ëˆp*°s!Nì:’ìô„Ì*b@}­Á€]Š]0`Œœ`À®½S0 ½S0•0Þi0`´ ¨¨^)þ)‡K2`ß²ç ?@ÆËL ìa(* 웈' TT¯¤ÀìŽ0°oÀÀ.å"0°‡±ëÙ÷› ì4ÈO T¨ÇÄÀΰ‰¤A1Hƒ;ƒš&v®‡I[Ø€À.ƒÞ ÀÎP”‰½ýâ èÓßµê$ö&MNØåøþb˜„íüjÚ™†$0ÐNÄQÐÓ¬†^}Â@[}¿ê_˜:¾up.h+9z#ìL×–ØäpØ4—Ú6è%Ì:âÀFä d䯤@… K ´uuHm‰Ö‚Å ÂÀÆ<(0lfƒÛCÍ)(°IÊ lrŠ l•SGP ü’Ï3Ó: °1ªFB 9Ï‘o8 °1‘BB`K,$6Í© ú:‚›¬'‚eÞ–hsèeq”hßO‹v@`°2Tb*JKE<[ÇÓPg›eü"ø°àŽ[ö§We%Uù÷Â-ÛóìûY’¡ÀT–‘…²$Cmíüél”d[*˶²äjËÌÇç¹Ypµ„¢«!üw‡'3e¶Ù;¹Ã“ýÄ韅Û,3*üîK5Y¸hfo¢ë¶¼Að¯`|íyƒÜNž–_Ûò͆†}eß»Ôa Wwòîxâ ƒ–ñùzâ 9졎 oin¿=qÐÀE.Ùß/˜X^M”ÁçjyƒüsµD(Àêê**n´±º†¿Âž”^e¨miƒèM3X°ñ§ŸÔoKä™M¥u[Æ ƒ&y ¯È§…¹ÆááÅ7ˆtA~‰9mKä¾ ÌP°‘-È}C&.1Õõ‡'TEÇ=Ye=åî@ì‰Q+zq,SåÃP{¹§§qÅòææäÈèå ØÞîßéhÁ¶žš‹‘3·mé*Ò‚¹ùåÞ~ré™Vñù¸á3º…qµ]jõÌ« — &¥Å¬a[†~úÞf[ô[¦’ÅÛôÀ7?—Õÿf’XårÝn\ûÃÓ•¢Ê[wû2jÌìµÝ©50!» Ráaöõ°¨G}'Pä$Ã|í§ÿÈ@é§÷ÛÅ|$²ÄÇ{\[õð Ø²™´ÒßÍqiÕ>bhéð$/±‚ÛNà¼ÅÂBØëú«Ç.Àsï™àÑ„ø¼ùóËw–ÝæËw‹éÅ’ï“#^|ǰ}Áw6DÑŒøî-Y¨B¾Û0L¼Û¢0áÝÞmÏ&ÞmõNxg%>âÅ sy=ðÎ𳺈w† ýÃw¤>ÙàY쉞ËþPž1êÃ’Ã@ÚSWðìûÄnZ€g¼S>€çØÊ_‚®ÞÃäéx,{’ïžFžÞ=]è&¼{—7ñîò‘t÷0nÒ݃- w ;àîÝc‚î ó™$Ý:þ&ݺŸ%Ýn]’î ö; w…ZáÎL•Àz‚»@lÁ™%Ö7Ü)tÂMÀ4ÁI¢aÁ]eÌÈ„»J·é„»ÊÝNÂ]…¥I²]¥Ëb²]eŒ£d;åQN¶3³£/ÛUu9Ø.¯Ûe±%k%É‘íãHÛ™øÛ͋횂í”Õ9Ù®1X²²'Û½_LËÁvnnÉvnxÉvM—`»Æ0‘ÉvM›º`;Y%ÛuÚ„ÛùUhGp×éÇpgçXÛIwvx€¥Btç'@%ÐÝîL¬tç™HÁ`¤;sñ¡;?ƒÀU¤;«Ó?tgu°³Ý™CÖ>Ñ }àÎÖn¼ Á—àwVÒ?pçqñQ°òžŃí¬J,‘í¬nål‡ÁvI_ ¶³R%Ùnš¹ÛmØýü–lg'&DD²™ b%¸óóšÜ…ŸUÀµ ¾"ÛÙÁKÿ°¡ÔÛù¼‚:d;+ÁÍÅvV‚´àÎnŽîîü¸DHºó]Z&ÝY6xtgS¸\tgUnº³ÓlvDwV§èΚ!Ë‘îlÆAtgu®"Ý™%žSt1ƒîÌWŒuHwV‚ ´èÎJ0hEwvT?tçGC(!Ý]=$ÝY  èÎæóvÓÕîìä Ÿ8á.޲îÌ4ŽðD¸ÛHÙú[Òwa.º³: “îl)©ä=.®›É<ƒîöbTïÀ;‹"‰á•`W-¼Û0÷ú-ñÎúŒPxgnl?…w^çƒwVP-¼³çÂéðΟ-ïÌí’î¬]üx¢;+A#¤»«YÒ]Dí ¼ËãAá9ò´ˆw;ßï—;RBžU9P»yìy¾cFix¡e…†W'5¼Z)«„†Wë/g:ZE;Rñä½*Þ»C ¯Óß U¼>U"¯Ó+ U¼¾(T…Ч}b¨x»Í„¼Î˜îyñ<“òv‘ú&̳4¼(æÙ9æí&…Nœ·›TFqž9Jz›G1 ziâ“ó”Ó>9o#æ@bž ¹ $aö˜æÙ·¼ Î;4ê çæFJÎÓ,!Îó)WóâλîC΋p£Áyn©†' ç9rKÉy&<Î SÉ=;Í'Öô܆ÿ#â…µl€ÞýÙzaÅ çökh™ w”Ç7@Ïý?"ÞUl г™½ê&Ðó`DÏ¢šzgð г€XÏôìó³@ÏÚÃŽ çÇ‘ ^Dï г«ú-âù#’ gG«Jz8×ÄôüL+Aω‡RñŽŽ%ãjÏ=?´Åî 7Ì-€ðÐó§ÎôüNöz^ÒnÐóM¬‰=?y…DÐæMÀþôƃÙñ· ½·ÎT‚ôÆÓq(Ðö²©¾ô†%—®ç¤÷ÖA:]Z ôPpe ŒŸÁìµ½aŽ ôÞ‚ÁM5AhV!½a¾DL€ž—à"pž7ƒ…›œ7,•9çGÉÙÄyo ýz/ 0†¤@o y÷­yÃ&8<'!ÏhC'äyx|A€¼·à yÈÕõìa.òukxžÖ´å7Ì—ˆHç^QLL2Þ(“‘‡Èxo’éñüÔ'²’I(xïÇ廢ø]’ï¼(0ùÎn‘‹ò]™Zst8å;ko…ò]QLLÉwV€Ñ@ùΞaç\¾³»à¢|g—<)ß™ƒ—(ß•©Ÿ‹òõâPÏsù®¬!ú-O˜¦¨ß•¨ý®¬ôŽ:ì¤~g·%{A¿³6nù®,êKïŠ4*Éwæv«weÉt†ê-™F¨weU ~Pﬗõ¢;o£Ó¤ßÕ;»+ælªw¾êþ…à`¢;íKt<ÿ¾ˆŽnkItò£N¢kl%EtMŠL]œü‹è¬àc•é6z¨B¢k…‚¡€Î\Q>@­Ð5pPМL“æ6m+æèPwÁÜ–Š0·d´)˜³«¿&™¨s¨sÁ¨s•îA s®Ér!ÙËÕ!.#ËÕ¡*a‘9~‚d)êNƒLÙ;¦A&H.ƒÌñ™¼SdvÒ{ \¥j$W¥šÉ)šUµfçñ¸QGö˜K’’4;{%í£ÙÙôä6s¶¤Aæ e™a™‡©°Ç<Ú~‡=æ‘5L€ÜS°%ÇñÀ$9î‹Ç="Øà¸ÂˆiŽyŽŒArÏúù带cêย=K€\¥•n‚\cðw‚\ÕÆ%@®IÄÈ5FäLÃ)hP\ﺉ(®1Eobœ=^W9ãš 8…q¯qqãF•¥0Σ€‡þÂu™ ÂuõW÷tÑ·ÎéÕ HpF¼å’ê@³h—gív–8Á=“®IpƒnApÏœ’½Hpíü@^$¸gmÉg$¸Ç¾\E‚{–Œ]Epò(ÁY;ý6Äæ‡×o©Î[¦,H„³pÐCÄp2˜ÃÙ× JÃ=ë¨e0ܳó;îÙ2ˆ%ÃÙ“›ˆpÖáCñg­ôÅYl„ö¥¸Gv¢Â8ëÛ!Æ1~Âo‰q6)Ñî’÷(cd`œ8Ÿ÷Æ Œ{¶Œ>…qÖN¹-1ý8€†â¸òHàÇ•.”ÇXãžÝøQÇ=âUqœ`œÛså Ž{N‘4GŽ{*'9îÑ+ǽ³9g mˆuï»|a\ÑDNŒ³—‰3$q>€ß‚㥸 Ž3³£K«ól” §\Ær•ÙÉrmÆÿ"ʕÿäÃðÉa©ÿ-I®ê!ErJ $×è^$ט‰1HÎdÔ ÉUiÔ"¹F Wî28Žáæã ‚Æ)9|`\¥ãJ`\Q¯…q ÄçÂ8³H»Í0mPÙ#Çañ›8ÎÂ4Üf˜ö"a¹N›¹†p+ÁqJäW 18Îló/•ÎoÌŒâ8Eµøá¾’éºÛ¯ÜL7™{3™nÕ <2l’éÖ–&'¦Û\g“éL ùq!ÝnòÒ)M ÝîáVG¦Ë*dºÍääÉt‹9µëæM¥°nÒš8¹n.Év-ÍEèì&®›”ø“ëÖCá,¸NFÉu‹6ÜÉukÉO\gFñhG\·ŽHO`g[¯«lì,Q M`·O ÈÎ^$9Ždwh{‘dGƒIb{ôˆu¦Lñal뮫Èu¦8¯Ÿ]Ä] ®óôˆíè  D‚Áu‘Ž0¸.|nR£S.¼à:g äºƒ ×E«Ðè6q¥D7ùêI¢S®Ø”è”M%%ºA¶”èIu«ˆ«DuÊ'‘T÷®ÑÐ!ƒêÞ·Ø¿T·-5©nÓ^(©nã 8¡îÝÌ}œìL“¢w˜Î­ñÑ,.µ$"[Ê×é|³NW½§û!Ð îÝX.6Dº·dc‚$ÑùYu›E¥áÑùî[€Pç&c4 é†AÚºÕ9¿¬sBkUؤ{K˜ã5Õ¹^ERç&0§:7éé+¤óÍk½˜Î è 'unIoTç6}PS;Ë®rØnxD/?9{7 ç5ñ§ÙïýpÏâŽ-P3 :jØ ¦šÿèƒ%ÛŸa=z]Å™'¼¼[Äž¶óNÆ8“VV²åC¹x'ÏåìÙþëø ƒr@DxXåìŸô\)èŒsLÚoÔ©~ô/‡É÷ïúHœh*Ùø›¯¡6zøÑZô-étñ£çè[2àã·»^§5x;´K&¼üÞy…/¯®pó;ø1놟ß>0+÷ü¦½Ä[rèØÇ $÷##p÷壩á[Rèî×ô#4·åò:ÏÙþÈPVräϧ:}ý¬—ÿÞ[2ºùÎÛ¤Óö¬ä¨Žzèö=OÞlúý=íÐñ¯áÈÐJèùW¢Š¥°Ù+ :l)lüãð® èÖ·€®<£xKÚDçŽF¹e°)¸h£{–Á†‰Ñ /ÁŸÈ^ãÐP°àýg¡Õ𞘾ƦÎg±þ6—óƇ€<¨|ié`ðÛxK \•ËJèx4±X¦‚:¸»%°°7›¼ª3 ^áúFª5‚¢™ýúgék”®‰wZ¾jZâ:Yâ˦§b»î¹…D3,a ¥ÆòXþš‰«Øó×Ð ãý»ŒŸ †ŽþMÆQj/ÝØPbª•% Uš>Ë`Cƒ9ÎÝ–Á†Fuª3} ½»Ô®âŒj)lèÔÅÇœ›QÑ*Å4[HÏAµ~M >·Çþ-¨(9?þÁs[þFuãùkŽ^ß’î«©Kg¼=o{ÓâbYl¬n°åÉäC¯â݇Ã*3ŸEí¨qØãíkªQgáåR’L ÄbÊ02¿ÿ Ôà÷ÞtÁVï·2¨GŒÃ+ÞpÂuD^ÕŽ2¬pDn8âšBÆq¼]SS3–’Ø(ò›•ìxÞ›®¸ŠD÷–l_T=½3{CgÜAÿ+Ùx†¡ÕÅ<Š›®£6%Lô‡oÐ?B”ðö4e,î~úÑØ÷W ÁR5¨„^uÆFع¢·ef˜þ 1ÞÌÊÑãâ5­I&¥Òö²ó*f±K+Ž&›¨ƒqRÆfr«Vl'P+ÅóØüð¤ÚØ(ØéÏð^uØJÃ=iòcç<³óÏ¥pý§Ø,…ÀyƒÊmNz‰rÅí„n’Ã=.’«¸ HŽù/’û‘góÉ&Æ!hUR&ᄸþ+Ä5ü® qKDEˆS®tBÜCµ!!ŽS« ®ðÄ1ÜQBŒç“áh) W†8 W1+®Ý’§ðR‰pœË…pœˆẠ„pSÄ‚“I} \2® =á(ª$ÂÑG$®òH„cô£@¸FûF"\#5%ÂQ*H„{´ˆ áÚÑtG"®í¨#†ëZžÅprN2\§“ ×i?ž שԋáúÑ‚$†S࣋ážàG2\ŸÚD‹áúÒR,†³èH“%`8…H†{;ÅÝ­n/Â7GÎá›%@8»F˜„³½ÔCäÙ¬8X†³{sÛBˆ‹HHAqn¹È«@q[JxP\D0 гrl9Æy¬¤ÇyŒq2&@nK+»Žrüäl‡È/œ ç‘‘P޳GPpœq<Ï¢Èqµ“ã"Ä89Λ»Rr\„– ŽÛg©{ä8+ŽóvX°ÛçCqûq qˆÀˆ³*ÜÚ:ÄÙm6Þ!ÎJ¦SÑ’¦ºBŠ»Ž@HqVÂÍ8)ÎÚáè#Å…ÍdRÜS4W‹âž¢Ó4R\˜D&Å™eIÏ1î‰ß_g8Ä&bœŒ%ãÌXçƒqoíãòÜa)|Ò D#ƽíô/Æ•GïB'“Íĸ<qŒóÐ'ü§"‚¸'ƒqOÕ¹ž îí ‘C÷Ä€ÄÅîiú Äp¥kBÃ=[ƒB WâGÃå«ÃYTQážør…påÚឣñ(„{4¨EpåÑO ‚«Dpeh:ÁÙžŠ„D‚{bƒàÊÑq°®l |\>5 Î:ů[Wº†š®”è1 ÎLžØ .ODp¥9Á ê ¸Bƒ¸$¸Bé$¸BC±$¸‚h pñj‚áÊT"\A}D¸FÛÐD83¸Ô1Z‹†‘#ar– „‹!÷t .:#„{ƒ+)6(îö7¢p‰ãŒ/z»8.’eäLˆÖãìïs+r‘([ç Ðø‘gp@ñ wä\#º5¹Ä‚œ¢Å% ¹psÉ…¯1H.ò¼ˆäÂ;9`β€þ¸X®îæ,h.® ÌUzŽÌÕ*ñ‹0g\D‰Žj/ ÌUš‹æ*.&É)doÜ[Z¦PN{SŽ‹’ã²€r\\’,+XN—å)(Qÿ&Ž æÈÅÕ¹¨!‹‚\á±K€\eÞƒ91¯@. rõ ñ­âÕJsçî5)®Æ—(N}HŠÓO“GMC§{$©߉pº„üVã Oüv52ÙCŠßjpŠßl\|ùíº1ùM?Cò[>ø­>ZÄoÉoÉoo(ÙĺWŸß¿Éoõ Â#¿]½!¿å»¿Õ!.ߎNÓQ\¶#‚«qt ‚»jàjù©ÞXÚWŽàpùH¸ë*\þ˜¸|\>¶îêÏùœNhà®:¸J÷8s–®Õ_žA—÷Àå3à®:¸r~ŠèÎ/¿ø­Æá°øMëHòÛõä·¼JüfE†"¿]%ä·÷¡ÄGä·«ù-_…ø-û#~ËŸüvÕ ¿Õ¢Óñ[¾ñ[ QCü–?Œø-Æ£ð-;,~Ë*Ä·Z¤ ß®‹ˆoÙ?à[~Ë·ü„oùf„où+ßò͈ßò·Àå°ÁqeI€+;T·gçÞ#ùÓ©à-›¼©É-ŸFä–}¹åó‘Ü춪£`¡ñÞDnùn§¢…ÍMNnw» Z$·k‘Ü®vEnö‘–êúŽÛÕL¯zýCŠ\|€|(‚Û]gÆw¬›¯zmW‚ÜüÕ°Æž1<>èv½¢ÛUg+¼L|D·ëÞ[fâ©ÈnWÉn×ÇDv»ëŒï %»yÿX°ùFÉn÷E»éxщïOO v3ë)¹Ý®›ì–ÍÝ®WCt»V÷Óæ·‘Þô_ñín…è–_6Ñíz&¢ÛÝÐÍI°½™‰nñ ·œvDnW…ÛÖ‡€Uc9¬Ób9}(áõ'F¹J´œâÏkicɬ±#c_ÀmR2Ûì>jfs@wö¹ b ¶]7"¶mŸrKl»:Klû”œï¶Å‹ùñµ‚ÕŠwöf5Î dµü“°VØó€5¸^°ö^rnûÉHt°VD!‚µhC°V膰†‡‚µlƒ°f¤3>0I°V] åM”híEÚ[w;´| á >SwS…ËxrQf£îvFeþ$ªe£ÚsDv¤µ«`©ËTîHkÏ‹‘Öz­å%¤µç`ã´æóçkú¬öˆåkY@^3˜éäÃ/xíÙB+òš¹f~l'æ( ^ËFÉkYƒ¼–ä5 ÀZv’°–í‘×ô¢’מ£=xM%¯ñÝ$±eíº†ÀvµKf{bN³=ÁD`¶À³¢®©³¶ë6¶«„À¦_:-z+^ˆÅkÙŒxíÑü¼¦q›¼vݪÏψkY@ZÛ:ì Z;"rL2TÂÚ‰ãNÁÚi:{¬Å1?YÍVNáPáéU²šÁ¾ &O×5aÍíçXC“”ÁÚz‚µSBù¬]'Û„5;§æ/OXû”,©|¤3PAŒõð\pÈZ*ì%wD5?ü šðmχ¶>D5+¡îæ’qf.sÉòÈœ3Ì%Œ’e.igm¼ÊÍ%ËÒÎAæ’Jišæ’¥Æ54—,K(){É2õT²—Lc=LÖù‹ÖfÕü¥ÂbRGÃa1i)œe ‹ÉfX0™|k¬«Ù‘îó5šlE‡ä2š¬;zL£IåvM£I…£H£ÉÞ~~XíÀ]%°™ì±­’Íd‹GÍd¯ư™laÁ)›IERO›I³0'dÑfÒbèd3ãO6“=,Òd39šK6“£†,&›ÉÐM`3Ù·>UÙLްð“ͤ¢¸§Ñä8q&Ç”+£ÉH›I‹!öa¶»ªms†"G›ÉQeW µm-¨mÊ”šjÛ ›x©mï½)œJmi”H£Iå£MµíºŠF“i¬'µm~ˆÍ,êô’Úæ{MJms듇Åä<°ÒÚÞÎÃb2RbÛ\²´•Ø6kØRl›>U‰m³kàKm{ØùZLöù«Úf™‘(”Qm[òo€Ø6ãCbÛ©mæqOåjÛŠ“[2™Ô¶§¤a0YC£Ü–¯BrÛœÒq%·Íª™MrÛÊ’Æ/_f³Ó˜4 &O˜fÒ`rm}ªa09Ãô‘rÛÚ)®AnÛB8hm«„&µ6³m&ò¸ÖVOð¥¶%H¢ÒVghoTÚ*³[¦ÒV‘h1•¶JC¶äµ°< dë ò˜È6÷/R›Yƈ •œ]v&d¶)K”`¶É(ÉlS–HÁla·ÐfQ%d h›S2Ÿ M)ÂÚlŽøñ·bi¿!›âÍoÒ‹Èoëçm3éÞV·Í¤N~Rj«2ª”ÔÖ~¡· .© Ž©´•¼) l*m<¶J¥_¨”6 €¡´Å„·p#¼1íJà›ùäá â›B‰ˆß"‘øÍ¿Wˆcà·ØÙ€ßì[}ÀV5 ø‰R¾µÍ ÝaìI~³/·Þ†“a|.~³ïÜj›MwûVÛ¼½Ü\ƒDº¸°µÁùÄ ôybznÅ-fœÇ¸>àd),€‹ùSgsÉm8y BüfWÀ¡‘üfQ£¨êß,L)ÑãD>4)ÂYüYŒ"œ…- u…æ‡lÌá1³¤©be*䯕 !3ŸžÈ†dÈÖ Òº›?ç‡áüõq^à › %n¤ê1¿N`k¢ám1éáà„V aÛºNÒÀp¶«AlËÖpÃ!LalW\å3kfÆù“÷ã2¯0ÎÃÂÎt|CÌ]B›c"ò‘ã<ò‡"0ΣÁ•ÛfÒ{,W³i„ZX‡oµU;aÜ[v³›amÍ«àv|óç2*´mØVo¤åaVÉжæe@ÉÌ9.ƒòŠãüÉy@Žóg·ã›Gá"»ßØäç$ Í!·ͼ½Þˆ çç® qžEˆ ΃ʪr0P¼r@Ü=@qž¼G2›Cœ¿`Á Cîu oÞJÎà8/y¦©~¾6“Ãù-?8|ˆï«ê£ŠÔ}Lµªàˆ7Éyj "7¸¥ß ²Î@jskdÉDB¡vÂSÇÖ¢¼qzdNÖ…%eÀÇš‹´Ÿ b®¦á»Ë«+§…UêESs[Ýp£æ ŒèDîG]Øðð“S3Êv&b«™Ì–-+€¢XKÿÃý£U@[€Æ#ú²£`ÑçãÈ`è˜ÙÜH¨·ó¨÷Ð@&oI…áh©ºõ¡1€QÁC™<ç–.ŒðQ,…WQ¸‡b* M±±,vÄ_P‡Ž!vÿ1×}KxŠËŸÉb¯wÛBc(–„éàÜÖ›­Ï“^‡%[î ²Þftã·¤69(€|ê#ëm:[ Ï{'·‘õéüû°Æàyïâ)G}d½=³„g¾‹BOµC‡Ã’…’M»Qy/W‹S¾¿uíF£Ä(žyñðƒWO·a%¢ßj°ç}Þ|çoÉþôØw͸Ý+4 ¨+.´eî+€ÑdÖZ‘>ÓK:Kh¿Ý$*Õ²aÄÓ˜ÖJ `¼%uÎ#:6£µÒ‚[yßS¬ŒÎÞ¿™šPR­Æü›_Ê,U5p2R-•ÌÁÏË÷g©dø 8ß©–Jæo¡Z*†ÍÓ¦:;´È_¥’©(Y,¡ wW\„j©d J*[¦wgðñ·d³]œÃ×Iî˜%’aÌιJ$Ó·ž“iw”H溨=§Ë$S?3ÖBœV‰È«¨›^Ý¡p¡'Þ’óã {QµÓ_û¢x:tW׉ü6õÓê›6ÜãáCm ¨#&Mî¬B u=7„lÖM Õú‚þ*C¨Õ,Ù1ÐY‡&Ü£è#ÛRGÕ›Ù”R‡ÂHÔM-ÕÎwX‡Æ°fö€þZÃÚ.=<4‡1'ÂÊ¡vh;ªæÜC#îÑôöb‡4¾zh0bz<4‹:ûª‡FoIå½i;˜<ÜJ°¦Ú Åû:4 ÅT™!ÔB‚`ºk›ÇƽÛCûØ«„²ƒÂæ[B Ù>ÒšÈè§oMd»¬2ÚCYØé´‡²C£¼=4‘0(í¡ìPÈÉf©dØÿÉ«ÜPv ƒýyÔ5vDáiË­4fÍK Íd-(ŠJŽ‚¶ #…f²y‹rÑŠ¢‹Nª­(º¨ÎØ[QtQä¶¢è¢lUÁE㾊K#Õ šÉ^%4“Zš%‘aP¨©­*.ìEš%‘)ø}pªØªâÒ¨7µ±û˜ú[UPš¼QÇj:fÔQXš¼õä×Çiï¾ ´ç·&Œ‚öîv@{×U¤=«ÃMÚó{‘¯@{‹ é¨‘õ®EÔó‡&~õ®Îõî®õ>%KQ!ù²ˆzw;R¨ÙF¨wßý,õœî¨wý(D=?)ý Þ} P/NSEz^…ô¼Ãä¯~"°%¯K¿·Í$=/á­VÕ#zIz~ó‹ô®Îœ®Þñ™z×Û#èy³¤$i…GIÒ»ž›¤gux‚AÒ»Þ9IハQE¯þ0¬¨µCªœ¿ôO‘E·>˥Тñ²–b‹*~HïzY$½«å­ø¢1̉z÷UŒ0šïÂYïê/Yï¡d½«7d½Eö'èÝ]YM?_Aω®¥lä ýؤ‰ò®””wý¶Ny×/BÊ»ž˜”w·Ò¹”ž Ç¾Ô¹/åEhÖ ¼ëë!åÝ÷ZKo÷ùPÞÝã_¡HêypM'&=ñ%·åe»¢¼ü,Ey>®°—'æñ‹ñò±…yùÊ…yV2?˜wwfõï+æÅW*Ì»ot¦~ö —ÃA¤—CF¤w½¢ž• Bš6ƸI/ç&‘^^‘Þõ2ôîÛ¬¢—«Û¬­@uöüN3b½üpÄz9Ÿ‰õrX‰õr­ëùCÊÚ÷ ì]OIØÓk éÅŸóù~ŸÂ¼û+¾a/ùA¹õè0}¡žù4’Ï.”Í…¨·•³3hϤ¨ªE„ ö¬€âiÏ›A`ÏZùJ{V…8EØSŒáTöìÖ_e¯ q¤½"¿)J{ŠCœÒ^YAi”öò‘BÚ“‹QJ{;;¤½ù íY _gh{zîö²;)íI{\å—7 iﺆÒ^°ö¢•ÐöÊЉ§´½¸*Ľø¡BÜ»êPÜ+òÈ qï­Ããjˆ{Ežˆ!î]%÷ô[†¶g!?¬çïŠ@mÏê°{ÔöJ‡¢¶WÏ8´½¢ü¡íf Jm¯„ìm¯„® mOƒ:´= –PÛ³g’Ú·Ô=¶2#,6Õ I{’CÙ+ò¥ eïê.•½¢÷¡ì•Ó\Ù˲—­HÙË'²gQÙ •½Ò%÷JÚ+]²‚¤=Ë"¶ÃId‘MsH{E™BÚ»Z¦´wõçÔ_þ>êŸJÒ^Ö‘¶§„S©íå¶—ïOÚÞÕµ½|_ÒöòÇ“¶—ÃFÚÞÕÃÅOâ彫å½Ä’÷òKÞËÞHáËA _>ƒ>ëñWáËþ@á³wÃ?÷/ ïj– _¾>)|ùc’ù®W#…/Fº>EðH/û+/.’¾—÷†¾—÷‘¾—3‰ô½|Ò÷r KßËç–¾¯FòÞU…òÞÕ_Ê{Ww(ïe; y/ë@ÞËG’¼w—=ï-y/ǹä½ë*Ê{×(ïeo$ïåË‘¼—?¦ä½ÒC¤¼—Ó,ä½Ã’÷Šü²CÞËþIÞËŸJò^öFú^¾cé{E†A¡ï•°˜¾W”%ô½ÆÒ÷blAÞËJò^¾>É{9n$ïå#y/§:É{ùSIß+a3#}/ï%/û¯„ &/@ú^vFú^V™ñª/+VUþ,’÷î’ýË y/'$É{ùn$ïew ïÙõ¿k:’¼wµ¢\Œtê^Ža©{9j¤î]·^±®rö–º—¯\êÞuÕ©ŸWLqïús}'›Ðö²JÍEõ}ù~CÛÓ\Ò^üL¡îÅOê^Àøb'_þ¸ÐøråmKèË·%è‹å8 ïQ¬‚€¾ë챠ïj™Ð§lႾ‡Oƒùìõ†È|Ù¬˜/ŞìsÉ|ÊBžÌ—[Ì—YÌ÷Œ°´Ì¼|]b¾|(@_þ¼‚¾‡aWƒù®“ùòí‰ùòûóå7$泇’¬WâkåUd¾üÎÀ|×ßd¾giîôåW&è˱/ê»®RRÁpMõ]ußtiŠÜ™þ|©/ŸAÔw—|g2Q_Q_~A¢¾üÁ…}ùœÂ¾üZ…}9¿û®Þûrö]OEì‹Hî‹vü¢Ç~1/ù=²# ò‹=D_¬~Ñ›@¿«7#ÖÖõE¿«?D¿x_d¿˜M‚ýâã øËÞþò©1&þ²Ç‚¿G¹„þ¥6ú‹ôw•ŒX\ï5¹–êoBÕøã8ðï걡ƻþå;þ=Š»ø;·À¿Ä¿µ׈ùF…Ù?áß“èIü»ÚYñM;»ý a‰‚`£P°í@+q‹pka=,F°Á‚c†/ YP¸‚ïD?4¡ Å£’ȈhŠÿ,øî¶¾–ž–aPuÈ‚oõuì³Ð…Q‡Á)óÚ€Á¼“`p=a9I|7´åcëi%‚JŽïy~~ap*EÀà»”ñ'iÐÌ$Q@´$$HÀ`r Z'› f4[Á ÕáÙaÐSu côÙQ´Ð_²¶ Z@¾òÿ,ÉÅ)Ò Méû¢AËF.ß?РgG`Ð"šqj' ZX ©•€AËÙ¼>âŸeÊ–›!`0ó: -(f Ãà)4aðìðo Ú*Ð/Ç>{¯ããØw,†ÐGý³ÐcçVÿ®ð_„AÄ+ã‡ý„ÞÂQ†Ê·gŸ—ÌÛÖs<‘éž0è÷Z·±ç°àfàïA@0¹Ò9 ާµp¥sšƒ8 úEü½Á‚L9 º¹YУˆ©Ž³à°%òVÿÆóÎ|24uôÐhT*£Dõ–èW*«Ü(èQ®hô0brž# š« ˆ‚]Q3Ó±¯É0*û”ß6ûØ90]½Â«/ÆUxõõ(‘c_û‚`$ßMǾð& ǾðâIǾ0§ ß>þŽ}rõ“c_•e_8ö…ë (0oŽ}ñž.Ç>yäɳ¯†§<ûšŒJ娗 ˱¯EgäØ×4æÃ±¯Ë0ûâVáØ'?Ãðë£KWøõ©/áÖ×õb­¯kÆ·¾ð& ·¾¬#·¾šžÜúº†P¸õůn}áån}]ÂÝúÂÛ:Üúâ=„[_¼½pë‹án}#\íäÖ½ ·¾WÉ­/ï.·¾øÁíoè]\n}ëFÀ®`^Á€ùÜbÀt¸ ·¾2šÜúâNbÀ>ÃgO~}]®“bÀôF ¿>y" óǦG(ÝúòÖrëKM x=°‡|¸õµ_Œ=­eéhd@ë%2É€é{*´ŸávìËþŠ{8+‹»®Ò±/¼gÅ€9Ä€ñ²„€ogº<ý¶¿”°+äu `×t/Ì;Ñ­o† °Óa)Ðâ{}0_°°‡{¸°GàÕ°‡+zxõÅS mgþõêSÉñ+ÿ™¯/‰ü®”ÁwÉÑ#|ñ¯Ïäˆá¶ø^‘}EwˆáøŽÐÄ¿¼5é/¼ŒÓ±o†pFú³™ò·Cá/œŠþl<|•¿|ÁŸ9=L>ï›+í¼Ò—þÒRðNÅá×ðwÝIiçg8êþzzÔþò ‡{_zïþâK üY䶯ö—ýüÅðg.â( û…·w°_ÿÕ½ÏHŠÁ”"¨XóÍù+Î`„ *Æ’OP±?½î *Æ:ÿfP±n›ú}‡(¹‚x±ì %W@°îA¬¯–ð÷ÝŽ•Ü­àï«ñÐ/ŸX%W;,»ZŠ’ÿö b½¸ÿ'ªØŸ†ü*Í2Ã×?;öVx'æy‡ú‘Â~?šaÛúñ ÛôËx²7Â<Ÿxbh뎆¶>1ÀØÖUk(ìOŒm]1ÀØÖLme-µõ‰'ƶ®`l뎦¶²–ÚúÄc[W 0¶uG S[YKmý;‘šyÈÚ/ò§‘ ì¢|ýa4°ö/‚|ý4¬ý‹z öë¸ü—AÃþÂÌõßÍA4OýãGò/s×äß·õ÷ƒ†uƒñþ¢ aÿõG7ù¯7hX³ä6 Ø6E°Qk§ÃƒÂ¶ Xåüdç‡û™CmxYØkLê.ÍÒlбœËô‘?°‚k4 Ï…g©ç„ýB,>¼ÇS ‡þÐØÂ€N””P*qHÕÙˆŸ*`ÚÂI¾ìš"1÷§k:ð7M¦|ÏßPª½–LPêb©þ,¤x‡•šÝÎóŸ`# @U¬Üþd–ê >Ö-röDþšÂ’‚ÌRï­Ào RÙ{t xëßÁ½ð”¨)[V· ©~ S¸Yê…§D†Z¼j ù–z/<%:b–·ÑSß=ñëpLT /y•Ÿ•Žú(ªò»fzDòj¹ÇxÕAc£¼‹ú,\ƒ#”^‹G1®M–ˆ½VI^§ì4Þ’ƒÕD±{m«²½ôêçD£U%èuxHr;1zXÇŠF[òùïv“iW)L¹õý»ó„´×íñÈÛVþš·ÄƒÛñPç%¾)zKtÒ›Ÿѽz+‘¼e¿%‘¼/Y£õV=Žñ;HõŠßIÁ¡ìôÖ=Žq·Hñ¼Êû:úQHºþÎh…?K›•| ²ËãÛ!Œê,K>|ëïñ9#ëM§¬Ãƒßsï~X4ì<Xð–x\r;žZ¬ã‡E£ç¯Ù«Ç%ïöºPàÇEo3Šèð–lüSÖÞý´è-9ä„· â ”æ}G~ê;¦’Ÿu{IÖŽ`á÷å§¾ãQ(¤þÎþv:Ë«ŽŸúÚ»Qú¾c€zÞû#ú¡ïˆT]}øqÑ@ v/¨Ïû§E®.üÛƒ[”vówùT¡y~V4ü Œ­ôƒA9úð³¢aÿ,™[&9ZõágEo÷”ƒà-ñSßax÷íŸó˜;îuüÔwLE{_¨¿‡¦Ik>Üv5}t³ø©¯E¬×5›µ)ûôw(xPòqäù–xf‹,_Ùr÷ ä³0³Ê[â‡EÃÝø½Xòœ÷ìbŽsÈ·]¹QvËŸã?ÂѤ…:^Âç¶:ÝÚ­²È¡3üèo It†uœÏ°ÜæõíñAø˜Ž4:cI ÝòèØ#X–"܉tÆwân™tìe¡è–JÇ_ —-Ë¥3¬{“|Ø‘LÇ?~Q¶PûÇ §éŽ€*o÷”•ÎŽoI—ÕZGF(h¨Ý Ä*îΈœ:ÃF? ti?CbuäÕñg˜,i CŠaGf´Â;yj÷š¦éxÞwóèCDrJ8Þ‚ìg³õÒ$…ô:o‰Î×ûF|àwÞ‰Þ¸œúŽZY­{êH›oº‚t$ÙyçŽÊ¯õ”9•ß&rì¼%ñjŽ«©ÃÌ9!ÍÎ;—HþCÒ=+Z+igØ Â×w\N}?!ÙºuäÚyKd”Ö‘lçmçè;;_ôŽÝ îøÑýîm4 æÛéqâ’ÔÁä ½m0ߎ]…3ºñ¸œê_CAÒíLå‡s¿·f.ÐÁt;3â]ŽÇÕÔwø=q'K·3­7ãq1ux¾ ¶‚t;3¤ÏSÑqëÍg:üåñ8˜ng*Énñ|V§È¼k0Ýάʀ7ŠË©ù=¦Û™uIý›ÂÈžngZ€NÖp5Õ‡Nƒév|ªc—S½>&óíLÛö°ÎƺjGÔ¬s¸®²·®¥¾¿¾ &Û µÞ—R±ø¡·Ì¶cËáÙvÆÒIú`¶±µ¹̶3Ã.eÔÁoY ï`¶Ù59Ž )Õ~l•@Jµ´ %RgœŠfÛ±«øSVH©ÓoiL·cá{Í”ÔY™6ÌþöUÕ.Á«jRç”Çø`²9ä~4”T+á›a²±d{?”Ô±5« fÛ¿Œ,ªSÇâ>UqÆç;fÂqdúî9çbBÐùÃTBæww)u¼f°8QnÿCìÃýWþÃÇpóßó ÿµŸükŒÂ¿ǑĿá„‹ñ~‚þ,e0/"ýíØ&‰þ¶¤0ÑŸÇÜ!Ú)+€ý !ŸûY(jèÕd¿0¾ö+±ëû¥à ö+[û3ŸÇþêA¡ä¶Ÿä—ÈÏÃ*’¬@~{>ø³<2”VÑT|;ö!Q1‘†âff²ycŸ§Ëãúìó4ºóÆ>7Q Åí÷ï¼j"¥°-Â(XL§QOês*åk!õ=a¸)ê³ü$|áN}“ôÙÚÂ7Iè3…ïŸÐgà*tlÌC¥œ¤‚>ËÂí¡Ï ñÚˆÔ5ü™}öKð¢åùEvÜÐgéY¸Ÿ"ô™ ·„>SO¸ß#ôË/IôÙäÌúªgnñ0_¸¥b¾š+;™ÏEQ /NÕdR 1ŸÍÖÜgùêT)æ³y÷Ë|ukôµÂF@|Öi‚#‰¯¥©ñÙ" ñÙë ¢ø¼ïŠÈg/ˆ›nG>£wn¹‰|­*ú–¯õªACä3{®_šmƒØ¯Y¾8â&¯Í„@ Ÿí+?È×LÝ%Aùºo.¼Ä×lÞ⽋S×{!_;Êò$ä³ó‡<_š…qa+@>;:à„@ä³£LÎ*D¾v>B>»j~ïźE Ÿeaã»!òÙ«„,C>Ó>ºð`9A¾¡x…|= D„|Ûmò^Ï'òžý¢ü0È{Gê^Þë–ÊuŒ÷zH`â=ÛÏ’|É{}+Û‘xÏŒaê‡÷ü'&Ý÷º­Ä„.ðž%„kÂ;>;KØà³ püY|½) ÏGî|Ha‡?÷lŠ#Á{=à‰÷|’,Á{6÷‡÷ì`ƒ¿yÏ}ˆ\À½ëý÷Ìrˆ4Ú³VB¤=k…‡N{Ý4yŒiÑ^QEÑÞ¨ I´W˜Ì0`¯Å± aÏ~m.ü„½ñTM ‚½CM±žõWÀÅL3…–GB½Q•  ¬gÝå”AÖ3þâÙYϾMÎb½¢ •Ázfüɰި²C Ö³Ùíõz,b=™dêEž7¡žuõ õì¬IÐÔ³‡ °óåtø‡ø[’ÞhÊ&Ò³„„ÜâõüÖÔ³C@Q%XÏN’¯ë%kF°žÆÃ¿ÁzfÖyo°ž=‡¬g^õÃzc(†XoÌ„)°žeC$W’õÌlÛÀzÖ¿‡u{艬7Fìäõì’ÂõÜÚŒõ–Ò>ˆõFlŠÅz¶“?ì Yo) z°Þû#o¶Ü›¦1ˈ{S™’÷â0xoI‡ ïÅÁuðÞ‘sxo„ú’¼7D°â½·7â4ò^ b!ï9‘Á{†¬W÷ÌO-ƒ÷¬?>³Î+7ð½¿2ï-à‹T/A|E¹@‚øŠl}D|~'Ò‰ïÈ{AÄ7Ãû2ˆoKK â{' L&A|ÆÇìˆoårñÙÙW‚øŠ© ¾Ë&â³S¶µü¯GKè³qt3ß.¡Ö‘ùŽNäÄ|ûý è«áÐg1.œÐgKuŽr¾ÈYÐçIUXB?á¦#lQŸ%øàv€Ôgþ <•æ÷..\¬¤ùõ81”è÷NEÔ’$ú™¡2 ºKs:˜HÍOH©ù%+’ûLžøpŸÑÏìÄ}s„ÄGô[rô[%D5Š~U{Hi~]! Bó³Õ]vø³uã‘ÂÇôß5KŽŒøy²_j#b¿®¨ É~…ŸM°ŸåÌd÷u…àHø³TFø ù° }¹ªqÔø+aŸ/ú³nV |¾\YÒTéï½j}éÏ ÍHv ?[’8lD¦©ð*П­‡ó¦?ÏLN¾2üë'‚ †æWdq&ü«Ki¾…նʤ)âßê¡ÿÌAa }½²%‰Û}òŸ¹KœægŽÜÕ’ÿÌÔ¿ùï ‹\ðŸe çùÏÞDО/XvC©‹ä¿:ù¯Fî! 95ìègÉ7 D@KâÊM,О“' D@³b$dŸXãhÛü¨~æeð!@;$x$ñ=Ú¼QÕ v›Î>¢_›2‚ ¬Ü ÝñAH¸@Ø[˜C¬ïe3DÀr†XR¯ ZY²1 Ðv íC€–ÒTbE¿н0°E€-bô‹[{‚î@€î«ñ!@ói$R` ûj YXòG –Û*´ù‚Ñh³Œ@ hSé= ΂Md3`@³•lm'¶TtÉ€Õž•×€ë˜I|ßj¨0d@Õ\È€6Áq†$ša+«Íö´-U6j~U¡ˆmŸ°Õh ØŽ<Å€mj!lE&ÄbÀºOR¡3`]ÊÀ 4G¡ñÑüÞ­a Ÿ3 åP%1 #«`B ¶¨”üêüùa@ÓÜf@Àvz´ ´’0ÐfY*w@Àú¾Mé‘@Àj–I½Ï(Pmqà©&Ð÷ÂB0à;˜ž– 9ê}¹VKï[=8 hS$?f2`ñY’[“í°½‘Ö£³&`}ïÍU" ÝñpŒXGAí{÷u܈ wˆ€úpÅ€~ÆBvÚDKd!öˆˆ$ôc,êr`@[b*KÀ€ùë‚ÛK£Ð{(1`MAJz_Slí`À·Ç‹Z°êä@ hOEŒ ö°õú²ôa@{ª­_Sí0Q%}ÂHP´ðA¬Gnù‚@ÛBHkLÁO2!!ÐÖ–/Z‚" Ц ‚"!ÐÞøŽ ÝßKì¢xí<¯²Fãg¸u °y2ôß’_ðÒ°!Vû-È$Àºƒ5I€¶ÉãI€S[± À:ƒkA€fº4Èn ÀnþO¤%#ÀÞå"*ìÎÝE€f¢ÅAL4ÏÀ!Ð×T;;V`«rÕ lZ~’{¨u3 iÈ„$@›\X´cªÆ–ûè¡7‚m àA °G|%`[Žÿ*¤XR_·õôƒ}õç/Ô§=ÂM}妾ˆ›Ôg{Yê…Šü(깨¯he ê ;– ¾'‡¢¾ÜˆúòûÉLŸ]% ¾&C‡4õ,:ÀƒÜwñ%±ÏŽUB‡ÄV¦3ò RJ’Ü÷þ²Üû–>åÀ¾F|¾K¾#ö=Bûlý!3ûj %αÏ8K °Oò™ÏÒÞßvžÝ¼·ÊúZœÃ^‚ŸZÐ÷®[<ôÍ" Ì7•UÌç wî`>÷Ó¾?[¤dFIÁ/â—„à÷È·&¯*Ìx _dò Å·ä³}¥$@ ~¡GHð«ýPüfÞPñ[3Šß #D)~Kyhoä3Ïb 5ŠÈ×ÂÒ—Èg%ì‘ÏlkIf >sd—¾â+¦ø]Vž†Š$¾ûÖ >+‘e(ˆÏ$JêÞ$¾Ù´D|æ¾%\"ñeË">Ëâø%¾jˆˆïaÚ‡øl‰<—§½bâ‰Ïz#òK+ÍÞùjïòÕðåò™!²lA|fx,QÌgÄ(¤5 Ÿ­òü„|+L É|:ìæ›q(!æ›+ Ì·81 ù¬Y~†D>;5LùÌîù ŸËËì‘ï‰ÉGÈW´×HäKÏ‘o(¤Ï0‘w"òÙ7!Lò5‹ã‰Ÿm$ª ?øl¡%Hùl,“H…|ƒ[˜ >K#¨'>ùw‹øÚV">#¼‰ÏŒe÷ â3ÛñÙŽT¦– >ÓÃçÇÌÓ¶>R+Ž(€Ègh Bä³-””AC>{Waö¹±N›S ŸÝI‘Ï÷|d?ßyJä³—.PòY‰Ì1|­uq¯šBàÖ†¾¬<›B/h ¦ôщ|­‡1¸˜¯„M‚˜¯h˜ ùìU‰ð`ãY¼^6ž¦[òÖd¾ØàôíxAŸ³}¾¿Œ<}Z—ÌWñ‚g@ Ï"Wì/ôÕ°Pô½s'AŸmÌ… ¾•À ê3ÜàÁ$±Ï6~œ9ˆ}¦áG‰cß%“;ö…`6ž3ä$ÙxŽ0ØõÍÊ©¯*ÒBR_ òõ¹9ƒ8ð {%,6A}~‚Ctê³Ý-‰Ôg ÈùPß»MâÞGÔ×Sx!õYö¡¾‹JE}æ¦ù±ò´»s#.ê{ž GPŸß‹,ê³§â»pêó£6^êëu…y&¨ï]9D}Fœê1¨¯B¨¯Ça ¨¯‡ŸuP_Ó-¨ÏÞ×ÇÔÓH¨ìkiv ì{t¢ ì» IÜgÓ"[!øÙà üüNð³êÁ?¿J˜÷À\eFo~=üL&¢¡$Á/ÒÔüìŒécëÙÍ à>ó#YîÏŠ‹¨üÙ¤ÄQù+¡ÒÊÖÓŽòYî3‚;_î+%˜ŽÜWä.¶žïp“©ÛzZ~lÖßjÕ ¹ÏNèúÇÖÓ6<çïÆKôUäcîyÂ.“‚óGú“ÔÇvCöŸ”þä tKôž6™C§ô7Ân”ØÃÀDصFˆWP‹0zÈ€P2èdX¨¤¿¡ Ub@›vׇOz;€ß0 6À€>cŽ›}î7ÞBðÇjˆk΀£Ô8¿º "/<„…2«C]U¹¡§®w?›ZŠJ|Áªaë.w?ã$B ÝýüC½í>ý]JÜý,˜“î~F/çæ@?”žw?ó‘’£(.|®ý¹½‘®ÐTEæÇAó_jw?ó`cp`?ñ+ÍΧ|8ÐÎaê‡M‰ÿràpÂñÃÀÙÓ 8wZ˜ÒÛo¯x¢35—öÚü& £·_¬žáíWCÿ’·Ÿ}õì×#b¸úÙgˆ÷ô› ’`À¾Ê[ ØÓQ’ Øí`îÀ}…>B4onÝÉ€y¨%4Ó0u‚ßIW;a¹ú­'ä9úú™× 66ÒÕo*ß\¸úÍpô"ºëÐÕÏL¶XBW¿?\ýFHzrõ[ ™¾~;úCœ Þ®~-ˆ¾~#pùúͰ\$š‘JùÈ~³†fJœ=<Œäë·Âã hÆ8rEÎçW_?7a;`ÀéÁŸ¼àty®,©|oFDˆ…j…'“<ýLýxú]ŸОI6œôôOxä­K<¸’§_ C2 ™Mñ»t´<‘ š ÒüX~ΡŸIŽ~f>(SP:ú1¼Køù•pK“Ÿ_‹C9ú•Ðx.G?²0 ÐüÅ–tô:8šŸ§v9úõPùI€é#´GÛÑo^â!ýf•JI?¿þºÀöRËÇî3ýjÂÍïÄ‘©ÜüÞor²à\a5Aœãrüƒ›ßêጴޭ®' ˆ€6‹lA}Aµg<%ÎØ) §m¨€€ÓÖp•ø‚ºJ¸ :Î'GDÀyâø“hDûcû9·‚ §™ª~L?}ôˆ !æ#  Ë/Î4M&Zwš¤@¸ù­˜Ð!ü4“ÚP£5p¾oq„?«3¿n~Kfáç÷λr¶£ŸßI÷;:úpD“£ßûSQå£_Du G¿÷ÑB „£ßûÄ"àzGªÄA:úY°P/ŸßÑ}øù͆äç·ƒ-åç·t2$\fnñÑýlÔÊÓý¶’P†£_üP"@û¡¤òÑÑ϶MT A€÷@€Ö¿Gž}¾ªÎØÚ†ñçÖÙ›Ð'8rÐ~¼ù1þ\E.® Àëg ú ø:û½¯˜Á$Àifœl—ÆŸ²êþ­GTxú½ÍVÙyÂÓo'FÒÓoé# O¿0º W¿w”ÈÓ-?ÏÌ¿aù9Ó“Ž–Ÿ+Ž dù¹ZzÿaQ]qBþ³1,‹Mê~;„hòŸEjÔ½À3¨Düg1 ¥Òò3Ühùùκ7-?·"d‹ÿ̵ÝñÀÞ;=g'ŠP¼úîZ½«ÿëÿŃ]¾£K%¿E‰ñøý“ë²–êÜ×ý€b¿»C– žýãw÷ø_¯³‰TP«á!<®¶¢äj‹eW[Q’myÜäóyò(ɶT–meÉÕVßn…pµ%W[,»ÚŠ’lë¿)H™/¢ïým•}g‚ @e›ËþƒaƒZFÃÿzïV"Õï*Üu}¸îºÚ.õŒböûaQ\ÍñúßaÓïߵÔT³hÌ#[âßwCQEí\u¢ ä×ÛÕ > E¥héªM™K»»Ä‚OSQ)šºjES ¾®«)|šŠJÑÔU믎sßlïnÕDž~ ^ÖïàeŠ"öëh‰Š¼ìϪý¼ìÏêý¼ì‡Ø/û ³äÍE¿ŸÿñOæµ»Öàß·õO~Û ¿¿ý.ÿƒý@»ñÇ1‡…w§å?Îÿý?jŸÿñûO˃ð”ñÿãZx ö?Å¿þ?ÞoÖô‹=ÿãù¿ÿ×÷ÕÙqõü?ÿó°÷þßÿ'.þßþÓv½ë)ÿñ?¿Õ Í׈7ü÷ƒ®Ù9–Å´¶{¿“è'èZË k̓®Íoí­gQÖ,Ú¼ ÿN”µö½ÍÌboõ¿òï °ÖÿB€µç¸aŸÿò°VVè-‘¸™ö®fn7Åä‡GHÆ>º˜Å‹W‘¿EÞ*V :3x÷¹o cV³‚¶*Cîèeø ö["3’2ÝTÍC/3•ÂM½%ò™-Û}p«)³¥oßÍû²¦Ü îÿYWDƒªp5¯F­ ÓØ·D»fÿØ«0Zæó@þ5C XÜ/_ŽßWΔCݲUóVQ,üÌqoç›WѶ³š5úÍxÔÅöêo ÉÌvß>)K®ÁøÝÛ“â½%%²—º#TÍ„4íq ¯2+¾¯»OÕL”jzìûšª¥­Ç¶ÓÝßWaA%™ŒžŽÕ"Ô±;šÕiŠ/oZê²:H'óÃOÒª‡‚Ç út¡ô-Q‰ö®Åë("˜¹$[—m|àæÛ…ç÷yæ¥ã…êi>¨ ¸ÜP·‡ñýÍOÇm|T }G:-.x‰é=üµ“yæzXáêi4ä˜n{ݺCœ2?á÷ßêyJ£zŒªÅÐÓñ˜GШ',í¸ò%àj0‰ó6Ê«¹§Hfw¥¥:±+bOß§‡MÑq類be¦öÁ¦Vàw†•ÈÀiØû`­à)Ý?X“A¸û7dððÕó—<ì{=KašF÷`zo=‚Åo±ÖJæflfuŽ~;µÖ2r°Îò”@ÕB0°Îvëˆw°Vi”Ç-Çšet¹ÍrWà+ò#M«SæÃMTm‹õ¾Q ·Y=¸Q{\Eò·ÝiO—áÙl~&Ó,›¾";Á´*Ã#\ØùPó?dS šµýßuÁtSýöL²8Á+‘_´¶¼k³p8š3ŠšV§ëàÈhñ±:vÀàíØ‰Âû±6ÏXâ÷Zï‡|ìUÍ7ÍÝêy•,³@³¾sès5÷cl&þ`­îö±¨{²ÄEøf»rôg ?`kæÄ„Ÿn½OX¬ŽÑøX[f­o-¸¢˜ÓÞû­6Ë‚ß`m;‰ó9m·gûÀQ›lN{?Ö·dpù`z¬f~ExÉ,³Y"÷OSó–Ý[a9Ì>²Z•&!Ð<òÞ_ÄK@óžÚ ¢"”Ç6ÙVòð[ÝÓm#š9>aè»ÃÕòD0ÊãuÌÇRÙØV1•øâê%ìνšJ©Í)oÙˈ`Ç>+ЙM"Óª å$·)Ã_E%‡[Ê 1Ñ?üR«ó)¸7–ËÔ½ŽY,gб:S »I6{_K>­–4h[w„,À§}«%‚™Õ¤}«fë…h’¤}«e1˜ªg ²oÕÜp¼á·ä˜ЊQ «›é¡ä`am• 2ÞQ" ß%Ôf" Êá( àÛ29ë½o6ÐÍ>}‰€ÞC" ßð‰ˆûB `=ÙDÀjîøÒ€€nOÂ\Gôúhä;G@wÞè-„9   è'ú3ÅÛEôSáy«¢ë‰{2`µëV“½KЪ$>¬­V¶ÃÀ€¸QßÔ½î[ñQïôèô>lðµõ(ÿ¾ðmaÒ~"à=Ð[. è ú¾ M×ô;Àfž è-Ø–‘ýê|#ô–ð¢ºÝ x~å'!Ð[°¯%¾-ÚPý H„@ïƒ'J|[˜”ŠX-8´A´Òztó%.蔋IÃoœ” ôS“Í€Ÿ,®6NÇQà@¿¹’)ƒ>åuà!`ÐçÒ>€AŸ:aä b"'b‰5/=ŒCôXiHƒ¾øÚZ.± ”ôE£aœ®%–yÚ„ƒ¾èräÉ5öá­}}‰.¬±{rn•¦»±ü×R°w潑pv©lBÂ¥ &!áŠÂêBÂÇ„„‹>ƒÃàDøŽBµQDhìô•—ÂN‚•­;€pIV \2D.QPáÚ*è) \ʪ ,ç© ê’“NœDØ¹Ë "ŒªÔ"ÂÕifƒˆp)N0ˆp©(BájQ””D¸”¶3ˆpµ,é "Œòæ"B˜F"ô𜟠S2^-BkY \‘ÅN@è-89‰p…¯+‰ÐpÅ$« ˆpED´païv!a$$ô>YÐÇQ†5_¶ü¨Ÿ ¯‰„W ‘ÐZêG¼ú ýTt‘ƪå§R$_µòäDÂ|~BBïBÔÊÏU}„„W 0o\H˜?©0/OT˜· *¼†!^G‘ ­e~¨p͈$^÷@,Ì7GXè-·*x%,ÌEXèg: ¯>ÄÂ|ì«XxD,¼[|ÑÊ·KX?ž¨Ð/æVï[ ú›ƒba,,Ì£„…q*QáÕ…T˜¿•¨0"^g"æg%(Ì—@T˜Ã ¯¿w|¬x'…ׄÂ|š‚»eñcU‘,AaþL‚Â8·˜0oIL˜OFLx C&¼ú ï–+îJL˜ïš˜ð:ŠL˜_¢˜0.YH˜—L$Ìë^]€„Ö@Œ$æÏ-$Ì‹æ©I„yu"ÂìB ¼N|©xEăWËéñ¥öÆåjàÀÁxÀéþª;¼[öo÷ëÖE™«*7Ü‚Þr낹0 .U¦ ôYÔ¹µ¬2¾7P0g ¡ ·Ø­«’C…‚Ö[—PÐt¤/ ZŸçV½Ïü  µà‘ ­…#O®¬CÃL-­ƒò;YÐP þ½³ËÏúŸ'cKþs×›ÿ†²áÿMú-ÿMCðßT¼ŸøÏ¢Z„À©Lë€S$){-V§Z ¤EàdŠŸÀ©¨àT 4)Êß*ÁGÄ‚ b}RTpiðß”'kðßÕÂUJÉ‚ÿ¦,ôâ¿lÿ½Ï|}ù/‡ÿM¦$¸Áù‹ (•&Aeô ü;ª¸øwääüwÂwSüçô¿ßz Ò†¤¨*m·¸é&*APyGCTu½[ø€R<4â§"餤©4¡šm‘±ù’#C_H‚-2§I¬`NIÐr2+ò2CͼY”k¤É’$‰)B,'j£P´ðàž4AF Klòi A°¥Il3b !¶ÌxIA°ñ½‘$Ø–\D©6¥ Eð„ID¤fJ)‚]f(‚)ŒSKì*¹’`W¡»âÂCŒ"¡! v¹B†$h}`’íż}Bý !³‡$ùÉ% öp•$Øi3I°«€sH‚æëŒ«‘$hy) ö FI‚C&žÐñl/ø³>tç”&8”í54ÁAÝ5$Á!7½‡ò|„$ùC̸ŠàP´».Eðí÷1Á÷ØuÓŸ‚¿¥Z”7(‰ðgå¶þì0J(‚CŠt(‚ƒÙÂB´—§ µÐBDM»P§²‡èQÑøY…>‰SQÕ?Ï¿ùsqŸ —tqŸÉÜ磺Nÿ“Ügƒàã÷YrK¦õÃB)îÛò’ îsYþçÂ>»Lâ>¿À"¹/Ýî~;ÊtŠüü|ÈÏú` ùm¥³ ò³ËÁþMägçê%p+ïW Ÿ [¡ŸŸý'ÉÏŸ|4I~v&ðs?hz?sx>àçŽ?ø¹ïºü®¢ŸµœÛÔ‡YÞÈ~vªóa¿=‘#'ÐÏœ¤ ÒÅF>~–x€Ê ÑÏúÀeOènÁ~–˜žsd?ëÒ>ìç-·è£|„@7uhÁíP°Ÿ¹BPÀ#û™»Ý?É~vÅØU‹ýlœhEöó‘Ád?s ˜!01‚ý¶W¹Ðo+z Ÿ_NEô3?úž’ýìÖ¡‹ý®Û"ûí5¤×ýl\±ØÏNN÷J°Ÿ{|tÀ«…ìg-χýì¦Ø‡ìç§b —ÕEÏ«`?k9Ðb`H«d¿½˜5ØÏŸè”ìgç‚ú+öó§ós¡Ÿ;ÑÜ¡>ð÷Ï*GæsûÙÕÐg´ËÑf|ÙÏHoÈцeƒýì6 ³ähÃllÁ~Öç£Ú]Þ¡ÞpnÐë­ùåk"òÛJÁ“"àdnûõ‘‡8™ 55À9äG* PÉfC\Ï/àg]ðBJœ]ãJltÄÿW²±%º»ßG,´n¦¨¥F¸ÿ žðZbБ€\¯J мûèÎI4ï¾þ‰ ÜÊ/%4ᆵh×:$ùîË÷s1 m|¿ m3 hˆÝÍ }È€¦ëÎèZôÍ€¶¦ÐóÀÝ G^ dÅÀ@› ÊÍ‚Ír@ÇØBÌQ` ]s¹}BýÖçÍ‚þ‹Ö›[SN.ÅÚkúÜ>¡Í²¬¬h˜Áëcl =/…fШBíŃ¥H!‚¶Ó›ŸÁ'gˆ í­&Bˆ …¯oŒ`)J(¥älüIä¹CGùÉ´Cj¹“¬ýõqÙK}þ½älþº‹šÙWš·ØÆ vÿý=Û‚»¨ æJ†ñÅÖYB©Yj¼ÇûÐ4éûwQÐÛ›Õ:t=)Þ`Æ)z§¸ÑÃcÓ=È¡ÏM0Ñ—?°Éaʲ‚aÌž “íÆ1cÁB»Y€Ì‘Önr³ ²ï,3–áÌûùñteξì 1Ç š5â0_™Ûà±ùs3/KÝ5« ³ÝÌ[`îlÝlSÌEVÑòÒ¢ –ÈÜOme'‹›yéXñ¶h™ËûÝ"/u®ZG‚i÷ÀÏÝgvP-lV‰ »oëÔ¾»HW\—t¢iVÕŠâѹNùZž^?…²¿OÜDxêu‹V³ò-®PlÒÔËY Åa–š·å@¢8¬ üÎêž<Øc3]x÷½î…ØLô…±… ¬ÒÌ… ¶ÑgNľ/‹oëß7 !¶Ð> ´ì‚ØÂNèmÙˆ-lZïK±…Vé×ïbšuÊúØR†–âñãÞ‚WÔª $ÃCž/îytáF¸a³¦¦h|u– ~{Z>›%ž÷ØÂCŒ|_ÙØB9#5Ëdlù”Gg2(žH"†WÐ’bFšQáÁQÛ‹ˆ¸•_ï<î­æYÄ𸖧ÌîÝéKñ¶,Ä–`o«8>6KCއ³ªg+oϤ ÙVsxõ–‰‘›'ákfhÀ½{"FëBWƒ¶PNË’yùŸ>=4«â‚oÕ]Qýßi€{á{ÀšŽKÝžßÿ½°å8?šåbáR¿=žËÙëýÞ½¨X³J0øÍË3AY†…÷ti¦ áµo´,ÜŽ£V3_!ÏUùc»³ÎFƒoYš»Çx—“Os?ËòÔŽZ¦Çó57€``3JfäÂÈ(Ý,ÿ9~[ ÛHŠupªãàØŠœ ›Åw/¤®rFožÕo"ý–[BšGÁ–+÷Wó¬~gÂn•Œ†çÖŠ£š×ÿhE¸½’Q¯56Nn6);»½Ã~W.áT´à“ç‡äé¶0D™™hÁŸÏjM×X«¸S¹m‘Ò½–Ñ8Ô$¬O·¬' ~hÊòbFƒ®üïÊ ná;wt¤³ê8¤ù²ê†[ç|›M…)Õ½–df}[6d‹‘nÞ2}Y}2eÃn’’§n;ôóZFcᑺÂÛâËj³2= -Ç}i]Œq^¯eäÂJc&¯eÔ\{Ù¿¡Kñ”5¾ið¯ÙJAWÑ¢ãÕŒ–'Øšx'»‰Ovî߯eäÉ äÖ‹™YÁìÃßmcëßðåó¼kAT©C‡ì޵1˜ÊëÙÇje† ú_X›©‡>Z#d‚Z|½’‘§‚’ÃE·±x¶(Η^Éhºõâhœ¶ jÃIÞ+ O®Å4T^Éèl˜3|å÷JFö±V-ˆ^ÉÈ>V«p‰ßÉ’V!C”½˜‘ søi¾ iÛû^ËÈ•"ÆÈw«³éyÛâ6ƒï¤NåF£ndëyÛ¶H^ÉÈl ¡€×2:‰´p¦3¹©§0¥×2ÚÌ…{2kxó>L2àåŒÇWÕf¬Ï´Ý+áužk e»y¶2¾Ô«¹y¶ÑææÕŒìW( §òbF[ º´ME…5¯gäÖÙ‡¤Þ,«^‘§šXVÍRý°˪ÔðruÔæò‘1uôeÕj}b^°zFö­š:YÀêù·z4›X=#ÿV7CV¼ ‘¬–7ÐG˪]3Þ +id«[×½Á¶>‡VA­¢‘­Uóá¾²šeØíï^Ðh Øß;†q{®Yý¯…•õ]űxx1£C‹øƒÓl¬¬fuåÝ«mœÇþ´Š?n—Ì:ìÕŒÜ.;XlçݹbY5 s€U3šÆRßxu+²ãvYæöbFÕÎÕêјwýÏ5µÑKÀ ùWú0%•2²}°–ú,_R›Jw«CQ)åašž~®äazšKªa†­`k(ï‹Õq“ìD„{(ì ߊÿÝg7úÍõE?úú\èG÷B¿ÁÅ9ѱ!ú1à%ѯ3ÅO¢_§A¢_§Â|¡W¿d¿AW‹„¿Á$ JŽð'SwÒß`Já ¿¥.áOYÑþ&SÖ$ü)|„ô7é:žô7éäôgZðI‘þÖÒ°¢?O¦ ¶"ýy@>Ž"ýYýÇ£H¾‹n‘þ,¿6P@ôgüêßiПít úþ,•îBôgTÛ?ôg}ȧ¤?ëS {™»‡.ô·Lº&þÜ dGúó¸ ßžý=\Œ“þjÀAû¡»aПWº’þ,EÛÀQ¤?ÓÊIm¤?káȤ?kªˆþ<,}H»2ö:èϼ«ˆN¤?ßõûsýYPÁ¦þ °¿ýí† ÑŸÉôχþ¶*ÑýYA£‘þö(jýæþÜóÿf?wÇÇìxœ ì‡rðØÏÝ™7iìgãtئØÏ}óˆi`?w“'tý¼e\ìç®Ý˜MÈ~p3ÆÀŽî1ÙØàSOúõ:þ…÷¡ð/» ÿêÞW…îzKºþ¹ó¦Dú{’1Šô‡Üe0П{Pâ×'ý!o þy~³ƒ>À?Ï\‚Ÿ’øç™¿úî\‡œøçYÇ€<Ä?OChtüóaðĉÞ‚éøç.zøáˆžc o9ñϓÌÿ<Ÿ¾^âŸg¸mþÜtCéÏóÐà¦Hžá é\è/E‰þürH‘ ?Ï‹ƒƒH»„.€? nüyÚž rrøsçÄŽÐ_f#"ýyB¥ýyú¤П;núó”AØ-’þÜí‘dúCú_þIoŸ¼ýU+y712èÏ[€Œ€?äØ+þ¼KG àÏû, èïmÙ0 ˆþÞ&ÓA‹þÞ–ªqœþ<Á?Žý½;×ÅôçƒàiI.´A°‹7ú{ÿÁ€þJ`v$^ èïa ø¶Ð8+|[˜\ øL²CmÚšW$ûßÉj'û›õ‹&êGMÜMbž8Цb%$( 7ýüwÓ!‚@3ÛC–nο [¦ÿ€ÀÍ2¶ (ÒwCà¡smBàad ÐH¢²‹•mó`Ò&ZÔ1µFRà®ôz6c\)ÐbY1¨$À¾~ÀYI p0J€¡ž…¸5!.d´M6µ¡Ê©!î*L”¸$”„8™W2г"âúˆ€¾­üùý£ÿáéŠÊ™ˆ}#*ò#жhx2)ÿ}éï0²:µ¿ÁTR©ý)3Ejï{MÒ”ö׋QÚ_ašñÔþŠDÐþðQ„ð·™Ü:…¿…BΩû í9¥ûY­¶¯îW™§’èç‚4c¢_{Š`%„¿µ…‡þÖ#h#ú™v9qÙϵK\„?s¹À‡ðG'Ø€?Û-?ø³G…ðW¨Œ‹ýl'ƒ!t¿Zƒô¨ûUV• ö³¢HiÉ~¶™ÿè~þD‰¢`¿c;.t‘ôgîÓ?¿Kù néïa ß`?»Åþa?»EPÑÏÖÓòQþžQÅZTþ¼(Ž"û™ J½Êßó0š Øï(ûc°Ÿ½Fä:JæiGÒß3¥gKús'¸ô÷”„úY…ê~+¾„ôÜJiä__ŸÝ%Ž‘ðgÕ§¡oJø34‚-%ÈoS·JôÛŒèáÏ^L3þžI] „?û)‰uþ¬¼¥@¡Ÿb¶ý,F×CáÏêXc“ðgw »¶„?;×¼…?û±èKù3—}0ÑïLª þžÕ؃ºß³(ã‡îgÕ·`t—îgg†ää·µ»ò;,2ºŸü°ºß£ÈÌÐý÷Nòs¥Ÿ e?»ýN!ºŸ%KQ÷3ùpHÙÏÊ üÜàP„îgɹu¿çañÐý¼'2Ýï1ÝGP÷{̃CD~!£J÷{:?ºÐýùY‡îg‰ºŸÅìáç—îgçêàEê~6òs“Ÿû@@ƒð÷<ÌoŸMÖí&?ü*áϼÈ‚þìùì)ü=‰¦þÌmƒ§‚ð÷°ÐRè~ö†Q£î÷¤†GÝïy/só(üYpÈs“ŸÏxÈRþ¬å! Bù³2mý£üY YÊߣ:‡¡ü=]š””?›pWRþžÚ52•?÷Ÿ¸ÙÏK¹ÝÂß3‚µ(ü=Jâèg (üÙD¶ØáφÅ(ÔýYÕC÷{Æ¢@ºŸiÜäç3qûè~Öò@u¤î÷(,=t¿gÓRºŸ}¸@é~Œ£¡ûÙÜÑ€lÔý¬E,HweAáÏýe€mþ|öƒFáÏ–œÆ­«,áϦk¼ ù3}_NŸ,äw9}în§ÏöE¾¹u.ê~ss۟Ÿ Û!ü‰'RørR…ð'FIáoÈsTÂßd‰‰d¾Št*—×'ûùšî:½>e.ä³wæçB>W’0L8}î_d?ÓaB¾V4nø|Náò9˜#]>Í3—o†—ª\>Ur3\>ç– '—O¦¢IÍOD‰|SˆÔglƒi~sKÏ“æ§2y©ù©ŽKj~;|IE}¶¡ûx|š¦Ò¿ÔW Có;Ò>üÊ„‘8Éïa-Ù ¿EdüмjåñYF(|Ôü Áˆ‚¿'”Ci~‡á¿©ùºl$øÙeþ$÷¡†’èw¤C‡èw˜ø3E¿#w¾ý¬ÎWôÛ[®›ýŽtýýŽÔ®¿‡±…~ﺾ?à·ÏÑ©~æ÷„ë£èçAÀA~Y¿ T?¯Z Pä÷P ð+zäA~vgà3ª~QH%T?{ÀçK~Vï&?”n ‹'ɯ0EB’_áŽ)T?»Ë ʤêçVj|´N>;XPªó°úIêJôSÙ™Tý¤Kõ³gQnöóg§ª_øUûU‰ÐÁ~µ‹Ç$ûÅBö+”Cö+)Rö“ô–ìW™µ.ÙÏv{Gº_]C÷cHà¥ûIþ ݯsËtë~t³”îüºß¤Fºß£U?t?¾p)ûÙô‚ÁߣícÀŸ…£E²_a\í%û='t?†š_ºŸä†Ôýè·é~r9 ݯ??¿_¢kD¦æÇd7)úU:t‡è—ê¢D¿· ÕEýTŸ'E¿Â’—è7~£'5?«ð‚1¤ùÕ.Nš_¢±ÐüЍNšßC+tj~¥ÉOTšŸ}† Ci~ï“;7ùùMà7 ͯV©uÒüjP¦4¿Êt!úÕúuùô›(ÑO2kh~váä<šR+k§æWÅ)¡ùUí@Có«Ì™‘š_¥Xj~u~}>ý›ÃAÒü*}üSó«rRͯÊvš_]BS‰~ŠëLѯÈßX¢_„èW–Ôºªuõç÷Kñ«¬»“Š_•wl(~öÌüê‘›¦?Éì¡÷µçK}þªái†Þgž@7õ]g’ÜWinM¹¯n:¨†Ügf[°™ä>]M¨}­PÉ“Øß~ˆ}öŠüüžb_•‰)Ä>E%PìkÈRbŸÊ†§ÚW9Jí«>}„ÔW˜Ð!¥>-©õ™£ñÏï—ÔWˆžR_efµ”úZHJê{/¿Ü¸wy„Ôgþ·€Di}…™Rë«zé¤õÙ†a¤õÕÒWÓÍÉ7´¾‡jSë{4OJë³­¾}i}¶çÚˆeýÛÉË’ýS?ì'¢ö³}/ü9Å~ç!™ˆý¬,*ö†b?KMÜ?>ŸŶ?>Ÿ–eŒ¡…d?KV6_d?oL‘ý<¡¼(É~¶ú Ÿ+j?ùí°Ž‹üX»€kŠóÛÚÏ+ÎÏîûší Ï7ÎïL €ŠóÛåëëéapؾ‡Ü·‡”;ÆùYJ å¾¢¨””ûÞ÷äöôtÃ)î“Q~%Ü#ÊÏò¯£~E• Sí pu¹Ïnºä>K½#„"ýŠí‘À‰ŠôGŠ›"ý Ö®H?yaG¤ß3èª@?»ytQ ß#s’"ýž£ "ýZ¡i-"ýÙp"үȗ6"ý®çéWBD¤ŸÙßy9Šô+EJ#ýž 4Kn¦WJÁoTºq*Ðï¡b~7ÃègËüÍ|þY²E~q›è÷„–§@¿"ú™òù|ýJ*ÐϸÅÊ'x€îHC÷€Î–MíŸù±†ý[Q‡’¸÷Á·ãê}…‚—ÀÔ†Nù ¿§Å¦zÔàkòØŒ‘+ú¼èºâC›·ÅKéEõ8(΃Sá ³Tú8àr¶g]÷>øÄ,eïabË1~Òæýnéã7Ýéž,~“ÓlcpÕ¡õcºÒ@ùÅ¿§ù¼ü·Ë§¥û·æQ<À!³y¥˜‡Ábóƒt¡šžŠ®â¨Šs-¬å>.جDŒòÇ7dŠô–‚£Žçç𖃻8‡ê"}~¦™†]], fž^OèÛ§VÈ‹e)§å‰[pPp³ÅôrBô&ëèb®ä8į×Ë ±Á%ÊiàŸ?qæ9™I±éÌ(æŽ0~K^NhaÜ’åNƒ£íøÓË ­ëÜVM¨²‹/žÓË mœÉ_Ùiå„ .6Žªž¸> ÞÐz„ç7 Ó±œz`}CËöoÕ¬Ö ùpÌÄ‚z UiùÀ½Ä«[XPݕßoE$úøÓórBt?ñ‡É£¼Óë M´´,¨!ÎO%w ÄÛgUDNýŒÜÜ•ïºä†Œ<þ»øb3½ ÐFdB.»øú>½¦ŸÖÄ© >‡¸œíŽopŽÂ%,©Þ§:<ê%…ô<»·”J…‰¦Wšt¡eÑ `ba›^THî<¦cA ŸéE…Ö稱ø¥²êôô¢Bü6Œ³*ª:$W™^Uˆ/VAË^üPéÄ4½ª^>?•Ujt|ò¥lL!Þ‚iËË ÑoÌÍöÓê ­Ÿô´œ^Vh|†iç·y_°—br7ƒÏ]'\ýwò²BLzê6„ie…:"ÆY“¹4­:­¬¾UL^VHÎŒ-‡«¦/+Dï'|¬VV+SöM/+ÄÉÕCXzzO¯*t0ƒûR6'êáb–÷ ´²BtÅ1Cë*ýI§Uâå«èô¢BãZ€¦ª|Zî¦8'¶‹ ÝrÙ¦šõ=óô¢Bô¤u'Þ¹J¡ ,7ãÓ‹ ñcÅAËê–|zM¡…SaVµšB¾ý=“¯‰×Ú8 ™e«ò lR’¦×:8~òµ´®rS?½¨ÐÁ–m­«EwuìÛé…˜ìe AË*÷)Ó qoÁ m®ßø^v㲚}š–UÍÄn† _ÝDËà²úþ.x¯…Èá…úwó™}ØoþÂ~Ì.t±Uƒ‹ý´ùLöcpQ²_GÐt¢Ÿ# ôcY² ý3•è§äÉ~¿V¢ß˜Ü(‰þ”#éÏJ^ü\ð7¹Ø&üÍ& üMš¯þæ\ þƒÛþóØü-eeú³=<¶§Â?SÙ øgÿ„4⟇ùcâŸìö†çEü3ÀVøgj}ùàßûú/þ©®:ñïAáæ¤?›Nð‡õ7“þ Ú“þÌíãˆþ 4“þ*Ó4$ýU:$º3$Ö¡>ÀÂ/"°Ê¦ Xµ»lÜæ&Vc$*~+10[ØXc01°M„}ˆ …½ ñ„ªžh‰W€ ÂÀ>„“Â@…6%îWíiú„CvƒÀÀÁJ~‰£ ÅÁüÁ¦íÅăÉSï9Ðë€c`r =É襠qä@ëB2$ZÈ ”hEVˆŽèA0ÞGè•wAUäÀ(´襔?h¼ƒâ@; gÚÙ] Ü î ô¢Ã`E‚ 0Û }䕲"8Ѐ(¯[¼ƒ©Èªdh]°P ½Ð-ðh¶ Ò%10B·€î]Ä@3U`{" ´´là9Rà–7BP Ä $æA„ÀHh]€Yd@»¤@ÇO. ÜÊQ¸•Ù6(p+ÿdP E = #N` õ!Á¯£€Îh]p&` mÊ­Fa mÜx"aàà×À@ëÓ¿(/«À@ëCÄ#ú&”% |èošø°Pgbàó¨…h3Èùp µ,ô>tl ´>xSľQÄÙÉWF2䉂vyÀ*‚à†ð}‘ gÄQ$Aßdû°"Á«…$¸•+4Ið©d: =-t!n1 ÜtAL|˜;@0wæÁ<·@Ð~ª‡hÈ¥õlXÿ=©¢_ Apc¸Ÿ"Æ#Ì7Rh>ÈøÄÅ#¸S•zÀ⇭Ïùp óá@û>ð‹­÷ ôÛDŸšÖ>«²°¿Å6Ìúpà–Gœ8ÐŽV í <-‚àÕ@ôy–ØÇ…UöèÁÍõ$8P‹ÒMýâ@ún¶_ÈÄÒMçâ@f/º8õz“å˜/Ž8Ð'_\ 90_  _O‚ ý ;O‚ S Ú‰°ˆíムnå£ô‘A”$Ak?$è3FdØ Aûðž1©YÂàpkñ ƒ‹é†7]Ñ=vUœ2að(‚Ïû‰íƒ’ L Òˆ½Þ;ZHƒÖçxý‡ýºÀAóÆ%ƒýçĹɃ¦ÐaS/´|ÈÔF´ÌÆPJăþ“ƒÑȃ}Žíeˆ–Ôk“‚(5PRR ltñO50´´Pgå# 5p?‚?©ƒÁ<©Ú>}ˆƒæ 5M8xhƒ"nÎ*Ƀ‹®ÃɃ.Œ—È "pðŠ"¢A–,¾iPŸhÒànº¸CA ®¦Ò XADƒæ„Mm’4‚FÐ`$ýM¤ãmÂàF*ã`AÛûXÐr¤Øˆ‚æìÍQ‚†¿!Ã%Å% j3(h™´ˆ¡DAËa $ FªÙ@AkÄ-ôÈcQ0tœ@Á× Íý‹‚†J‹-´\Ö.8$ znÞ FœqH‚…‘ù) Z(ÓO’ ý}@Rk×ÅH¬K'’"ت7)‚•¬©–.PŠ ¥É¯IlŒëMEÐÞ-ЙAK/>R+ãŒS¬2Ý„$Ø©’+Å’”=fCl‡¿gH‚zÕ) Úúö’$XYt,%Á†` T-¸˜'EÐlê4]ö-MNŠ`Û:JŠ`ëÄ›P+#y.E™Ñ.E°é\Rka¤"Ø옊`Cʰë&™† XŸß>,蹬’•.7åÀÎ4s!¾1ö¡6ìCT wÊ–³ï+N ‘’‡˜.ä@†ç¥ØŽ¤3É-±¯Ä‡ ñ'äÀIh5phGrà`ÎÔûCÅPj`’©Vú‡¤87¡8R¤8èkžj >˜Á.Ú‡‹[ œ,¨”jà`†øN­…Ú1°³tb`C°oR`ëâ3&¥8î8ŠŽ’Ø·L©ýá©$6f4¤¸$¯NæFJ5Ð r€Ì$vzX¤Øù%‡Ø ’j í~¿ 8i-O¤…=ÅÀ]$ö¦mñ ‰Êåœb òô¦¨<”)Úï„>[WЭбĀƒÓ`ˆ“e°S ”Öb`glŠ­.%6ºï¤8µ½1Pù¼S ò`1°3ë\Š•lR lÜí¦8˜T6ÕÀwÖ!(J ì‡Pß‘1ÝH lK (9°=Rö(ê‹5°1Š=ÕÀ^É>‚@›aLJ}îû¹ ㆈºþ$ÀX#»‚í“©Dölp*Q E™‘¨Xý€@û` 1° C lÜ=¦ØYÇ!ÕÀï=еKÅ#žN‡´T›,}¡¦zL5p0/ÕÀ&·‘PRB¤85ÙÆ÷b`ç»ÿä6»°¯ÒÝØ7iEKì[L'˜Ø·¾Ì·6™Ì·™¯&™o3K2ñÅ|7O½O àá:À#Î Ðè(äk4¢'ò1sjH€§Ó§1$À- +$ÀÃõ?%À¬& ðH-¸ý?È!úv\ ¬‡Ì÷°¼Àå*14˜¯T#æ+í·h{öŽa„|ÊÈW˜C:¯²œn"_¥VMä«K€'ä³-ö×´Õ <2_«ü$¶-¿RI€†ó„>åìLèk#Z}mI&ôµ)yO`Û¿}ÀÞt9Rm>DILÄ”Ì÷î:[}C®z¡ªk(€ª¶“ àdÐR(€SêP(€“E)û&‹§8õ¦‡8‡ˆS à¤sT*€“iòRœ dKPÁ•©*–2À%ŽÐv{l¡r1#@eqLPá´¡®&z”h†¡øâð6ÀÅ~*€›¥¯RÜAgRm¢UIÜ“Pw ßPZ*7 ùïHX”ü·Y½4å¿M«xÊ›)?òè;å?9y‡ü·» ”òŸÊ¦þJõ?èoÿBwJõ"Xˆ»‹æBüÓ®&Å¿-ÿ¦Âÿ´ ñïÈO+Å?™ŠCýSòTÿÝRý;L1šòŸ½Üä»´<éŠ!NýïЙ%ÀN ýÙ²Cÿ;òÒ ýïtîBÿ£‹ô%ÿqÓðQÿ¨õ•Ðàåê_êRÿì´$ÿ)˜:å?sùÊ›¾)ÿíú«ü·ŽàKòßî‚”ÿ¶D›ÿÄ¿!ÿmÖ-LýOúoè›zRÿÛ¬žàç{ ’ô¿Ðš~ùâ„þ÷¾¤í«ÿ-¦ ðóòèýÏoG‘ü¬ÏÕ…þWÿ ÿÉ,!òs¹G…þ÷üöqµ‡ñ«üG&É,¡ä·±ãúý–ÿ„.)ÿé= ùOyK.ùOi)ÿ1åa Ÿ½µãã¥ã/ý)A/ý¡ƒýR¦Ki/P/Ê-BK¹V.‹xê[Ê]è|æB¿GºSêrLOýOî¡ÿ…Ä•úŸ°$õ¿- ý/äÉÐÿö/úŸ_Ä3¡ŸåÏüøzdAè÷È/5Aõ*¥#hùíC~éh~ Ò‡Rÿ“òúßÄ…#è#EPúŸr|A˜áÊÒI?PÀþíº¨Ê´¥ýžGG]Ž ¿ €]:b€2#¤#hø¥†ã„H/ÆË”‰l?ž ˜)VÉt!J0OÅÅ.WPh €z•RdîÛ3 ¤¸ä%ôW–HE•þ!ÓÙE‚nhýàÂW{ €¬ü”$¸—âæBäŠt €¢ÁàÖC ŒÂ¥ ž?Àà‘ã¦hÐÖ¶mÆG‹h°/, þ# nîÆS Ê”ø Åõ…بO¥(e1@KH D“ØèY4ØŽ"ûDƒC*QÐàÔ9hpÑ©5`оNz>Œ3ÚÒ,—œVš.4èÂ×O ™ÉçOéb½‡.+„8Á t1± »º£KSì3ä¥þW©Šåå,è¹’>î –øp~@Ó&pbÁH;› ’B§¨œK”š`)Ô½ƒž’ˆFL+$ÀÊ”x!†Ä`á#—Èd z 0O `‘E#@åXNPÙ±S,]ñ~R‹OC´øИÀ2åB*P©sST”N*€…I8S|ŠÀO `‘Kk(€‹ß](€**`9ºI€…IaRÔ#°l…ÓI,r¨NÒ|€…iS¬L!–`¡CW €Êš mg¾!ŠJÐÞcœK`Y¼ée‹T©ÿyΆþ§'Aý¯ò§þ§”l©ÿéù¦hË  ™yR¬!ÁITîä•¥ô Üܱ§È¨ÐKŒÐ œ"Ø ÜR1#$ðã jƒ`‹—ñ€GÚ]èç·óÙ…Xñ#Àú%Vx:\ K×\`‘Œ(°Ò’ `­H €¶Nâr¥ÖB-/âõS¦¨€¢ká&;ÀZ$J¬Ï/(èo9úH¬Ô9C|„†xyH 0‘XJ¬R«CŒ§ `}„}Rë#-O `¼Œé*ïÇPë#ò’˜#K̳K¬,½›`% °j‹`E‰«T«vâ!ÖðB=J!„’X¹ú¤¨,ñ)Ú°sU}> ˜×›ú¥BT¾á+"P oˆ€y®ˆÔ¤!t³¸B‡â#$PñˆÈšÍWHàT8]„2.3"“•SÁ}"A9fD`Q‹DÀˆå̈À.GÕˆ|8û„(/•+"mw@àaˉèÝ_¾[¡ª&‚L} ôïA„}"¿$Ø l8¤-*"0ÜIEêŒìr0 diÆOD *H•4.§'h´\$Ø!Á”üi/}>DÀðöð¡ýþ ì\§2$¹@.”ßv’ ^dÆî_HІÅ{A2g$ bWrÅnypFLà¡14TÀR”‹L2`iÊAÅÙfλž­|™Sg[fÏy%ñaöì/ÊNêòïe;[¶áÙ÷ ²%3©-“ eKfÛe}¯‹–Km9V¶\cy4æç¾Ùp„¦k 5ügg'³Â¿ÍžÉì×)Ri +lj.æê£Dú±æJ?¦q¢“ºúÄH‘|,Fº’i¤è¤‘®>1R¤‹‘®Ôc):i¤#=™¥ŒÞÏøgéÉ~I6þ4wYû{©Ë”“ì×Lwu²¿Ìqö9ÉþÆlö?ÌL2yýãO_×_'´?}]ÿ0Ò¿œÌ|î÷ËZÿ'ó‘½ßì¿’ìíþgùÈÞæwèw±>ë3·ü÷òO§†¿ÌG¶Fq7/å;gÀÒµìóé9^€aoËò]¥9±T´Xh-£À}¿õîªï*íYû®òý'ç›jùÐ}ö¶,Ÿy^Nõ™}Ù¤YÃÀÑbÙ`}°èþÎòwoËòõa ßá; «‹Þ1k–ÊÈ Æµ¼-n/~[úÿ^Ãbyºá¼;—Ãê¢'þ{Unw~ÑJw0;—¹Í ëݯÒˆé4ÖÄ͸ßËï͸ÑÕ}s ŽZ‡†UZfÞÛóZ5Þ‚':[Øà­ã-ë)´¬Òˆû¶XV¹WY Û|xÞøãYæ…èDÞ‡RèfÃ*oË¡›ÍÁVoYªßV>ð Zî¿T`±íh™eäÙ¾ì'‚— cQׂ1ÝÃE Z¶î<ôcâr̘ÄxÜÂÙ¦º[Ö¹ÐÇ!a¹Qؽlx}»ˆ…î®Ë"ÏGG‹ßåFÄ<¥˜ež*nW-tî[æ—â¾<•¼¯²×¬]cÎi¡rÿ½Ì©¢2Ï{£‚ƒÛ¤yùнÜÅÆõ¯EµÛ[§–í ÃÅÆ¯ÆÓ8Ñ ÇwÉ‹¶4wºÁ«æEÜdžH¸Ìn3–Å/ÐÝb½‹¶‘æ|çB`g¦›eÞ•Õ“Ö <½Š·Tµ(÷6”·a¹pÏ’ëàu÷X—ƒA,–ïÇ]ypýˆB^;ß?H³âÝð¾oÝ?Tq/ÞRÝ=ÔýtüÚV}ш-mA·§ ;·W)ö>óö2»ô¯Yh8t¯y@áÛ²4?L\7ÑùÇ=€ýÁ0»Ð½¦Á€¶=ßüÁQ-xÝ;Å_ò],Ê â’OŽ»€’ÝgÀ'Ùmeäzà7Uê¤lO'¦÷Mîˆaz¡lO§Ë·åàCÝ3Ô‹EªjA¾ß@‹H@Üy‹Ñ§eãC݇wA ½Tß§Qd&¸]7++Z6éµCÞu’þlÐï÷æFvП7¨~$°×?™¦g[‘ á³ùöAìâŸê®¨:ïð·p)sS©˜ž¶ÕZ4>lôAî}¨$8ÕyÂVƒçé5‚nKÞV#hÐB†q”Äbø¹¬FP—­p¢«ªõ)8ª¹¶€B<Þб¨ºÛ­?a/Ä(•ƒaÆBñÏJ'ÕíU‚…âÇÊMäO¸m¬ªkqÐ⫪O¸˜ƒeÕ+þø™:ªTºï½/lÛëÑÞí9Ûêù¯÷Žƒs{ w™¥Sò¶:ApØ&—=šo½Ï«Ûêº2£atúk3kÅî«ê âÜ^&ÈûllÛ·• r[Í`ùö2Aö¸&5v‡réîxá¬N;×w>u¯4Øâà O6ç~ý 0%»÷0°¨Ë‹éã•‚&Ng3:VÕó¾ˆf`Uµ£0Y­ ·Õ¬ÁÞk-´à—±ZAÛûL¬0ÛkyV'ÝjÞ§bœƒeõlf#ÚV.Èë5mÚs¶— ²ÇµaTÙ^.ÈKÐ6½½^w¡úözAá—™^m¡žCSôözAÖå N\V/È?Ø#äörAö(Ì=Å+´<›öƒ äörAN¥S• òïõЦ·§K®ª˜“¬Z Eáa-OÈÿÐim[¥ Žlö˜/—ïš©;x–V(¨aë¡Eu‚¼=ll G‡ L ŠYÄë9[C1¶W zjálåù‹¬A³à»i@‰nÛ¹/ïÛ™½=ã–©Ç5mOÍø6po½më³Ñ3±9Wô@Wýøtm£QX/ £áøEW­6{°®•ߤ§¡ùAUt `Â*ªà75½£¾µ¨Ä4¯Û}ÑOŽlÐÆã—ÝiÝnìþñªBxTP€¼m^‚Uh`‘k‡—¶ý/êL`ñ°à±ƒSàÇ9®¤zñ­CLIµCXÊ}R} |ɲ˜ú½÷ºG‘ 6ÀÆ2è\ñwS]Xç.a¬cxer]gÑÖ于(­ ë¸ ¹°®°‹¨nб2¨n0­@RÝÀzP7è ”P‡­ÉuƒßdRÝ8jÕM~1IuA˜Au“k|RÝ ÕÍ.>ÕMG'ÕÍàEQª®'ÕM¾5Ius‹Eu‹òFRÝâ†(©Î€dç üEvöÁÒvçÎD;eßI´{„Îv]ÍíúÉÛ=ô²I¸3W½Ÿ‹í¬š8N$¸{׳€;Ûè÷w&Ü=ÚÕÜYú;P™àî¡qÂRä%ÜÄØ%ÜVL¸+]—#¸³—ÎÄv…®uÉve‹Åv…>ÆÁv…!Évx™O¶3½×ÿÚa·üû…v(töû…vé’ìÌcåKv•9Ò“ìÊEŠìª6AvU[ý@;Ó¾½AdWõÓ‰ì<[@vöÐÉÎì%XÜEvÖgåh>á°D;ÏàöÚåå íì³'eíì Ã–M+ ½×í,{?Ch íìê° íÌÝjƒ·ˆv»1 t ÈÚ¹ºÈ–E+LåÎZhg}°³ÛÙÈ´Û=†!Ú™™7*´Û¨úö{ ÝÕ@´‹<‹B;ë‚ÚåAB;o’íÌÄ¢]ÍóA;ÛV‚ÖV—U12ÑÎî D-´‹P±`;gØ.AÛÙQ˜hçÙÑ…hçÃxÉÎÒ>Þ`ç‰!½‡À΂Ô@IàºÝ !Â:kÀW\g‡ì×Ù^_³¸Î\ò0ˆë¶J9×ÙQ€q݆[ÌïÉu橊w_\çŒ>ä:Ï@‰{ ×y¾IÀâ:Oóá:³¼áé ììì`+rôˆhäºHv)®ÛƒAˆÁu¬ú{r ƒ/H`gç€ì²²ÀÎ[`Øyo`\å¤Ç0¹5–76l‚`vp€G®óX¾†r®se'è\ÖHp‚qˆs{ã €ë2Ð\çc`Ñ[H­9¡gë|HòçypÙx;¿J—vÈßé#ìP¢ƒ ç7Þ:n `ç'%v)†’4$;?ËMvb ²ó¨B̧@;$ûÄŽvÈŠët´Caœ£Ý=ÆÁÒ9iw&Ú!N\ö`åœLK´óHEÜÐÎí±Ä,G;dßdù'p°›k]Ì"ÛyΩxI¦q"ÚùuãG? —Œhêfß%/:Ú]`êšOù/ä º{÷07ÚÙþb°ˆv¦n<Ðшv¶ ¦‘ílûDlg-B9.AÚ…î®aw¶W¸áÎ;VnÅη?%Â]lAîl1‰{\€ k~Ü™èCŽpg÷}>’µlE¸³`C áÎfg(ˆd;›f+ºí|º¦†¶³‰—d¹µ5áÑ4a»Ý™ZlgY†IrEK¤²Ýî%ô9.B“3W°]$ßMÅn ix’ì3·¤d·XJ!%»EPJv¬^žŠbzS±³à[܃$»M+A(voW²ž»ÃH‚ ;ÜùÝQM\»ðÒHvž÷ƒ€ì¬÷(²3 >^‘]Ôz ²³©B´ÈÎ,ïèdçù•~.°ó4à/‚Ýéì"®3T1Šë ÌÈ~;K`5?’ÚIqະ×Y Ž!ÖY¶ü’Â:KFTq5ĺ'½Ä:ÿŒK¬ @\g9c¨û‘ëÎb|JpÝÙø|ëÌ$ #ÕÙ¬X>Tg-Ø‹êÌF<>’]Ô5;!ö(¤:·‘Hu^–š—ª{êH`›Z±)ÖÙ¤üÜX÷S©ÎÏ r!չ˨¥Ôq °®=É(…un&Ä“ Ö¹­ë¹Î-ž-àºf¸`r8ÿpL9\÷ö)\ÉuÞ2o°óz´`÷öa2T×%ê쬬ÿ ªCys?‘QÞüÓ©ÎK ¯K°ó.°ÿ“꼆ñsS—ßà3P—Kn`APW§eP×9ƃ!ÕyhI¤:/vÝnÁÎËc“Fªóíë¦:¯ŽÜnª{[´i"Õyéw ¨{†T÷ŽOçtQZ¼P÷60ס®•Æ/ŒL÷6Š.`ºfUÐñéÞ–"í L׬š:~k2ÝÛGß2™®Ù›K‘L×Ê`1]+)ÄtÍê«c[L¦kÓ0ÝÛ‡.ÏbºV”ZJL×¼,û u>v¿„º÷zz¨sNu;Xi€uÍj¹ƒ­‰u­¨*4¹îm`FGwÅëš‹À\×Êbq]+*ø ®³>øÓ×ÓwX êÞúšuïûõHâÔ5û^ÙàÚ‡Á(@º·ÁIBºfq*xñ‰t­( SH׬B=Þ2]³y™îmY¼>0]³B÷“â/©ÞLç·€m9™®Y |2$ÖÕ‡…C¬³ DáÜÐêê#IœZ=/Ò½# N×”êj˜‘\ª«ö¨q<´:¿€´ºZY HZ]m,!$­ÎzTд:‹&j·Xç‡` ˆuõ]!*\¬«J±®Væ”ZgO³4Õ:;B¨u•Ü ©Î¦ûŠñ ÕÕpÕ¡Tgs;ÿ>ºhB€Û¤PW‡æ, uµËŽçJ]íÎ¥®öEË•º:dÛ¢RWÛ+¥Îž ^2*u†…Ÿ3\’e  RWƒÑåÅünHößÈ–„[ Û,d’ÝaèU t›ÁD©Ð1aW tG‰¡Ð" ÝÞ2)t‡As!ÑY¥J r”è+9…Dw´]‰ÎNýs+t‡î*©Ð™bâ7 ÝflG*t'ü7¥Ð&GJ….Ô™Pèâa…B—#î>áèò/·K€Tº]êQ¤Ûå#l’ÛeI ÛŒnL·KΗÛe¶Èí2Î$NeˆR ÓïúÜ µPú\úÜ †>Çj—>Ç=Zês–`åãwiž¬ Ôç¸Æ\úœ^ÑÔç42õ9F¥^úÜ „>Wwësç«Ïmf¼¼ô¹Gn•ÒçâWH}.îI®—kJì’ëåbâßt½\tŒI×KY™ÒõrWj©áziI¾Ý^r‰”@·‡ÆÉ=Üë§@÷þB0æ„@§")!Ð)»F tg ©Ð©D@’3ò&ÈUº'ÉU­¯r«e\eZ·$9’r‚œÒU‡<ç „o’ vyÎ2+bK!y.Ò †>gs~ûø^šïV(ésgJE¡>gç&:QŸóGOoÌo®"Ñt¹I /ÁRè,¶|Ü$çç†è(…ÎÇ(R¡³d•<9:;ª³ /eçKó7þM]!ÁGΗK–åp¾ ·°p¾\U¢œ/ƒï«Ðý|$:ky>Þ—‹…aÒûòÈÚÞ—[VÙð¾Üq”¼/-¸}ä}¹Y$<½/7³—¥÷å,¿ÂÜÃLié}¹ŸžÞ—‡¡úé}yöΗ[>já}yºNE˜{Þu~½/cœþß ¹ÇawΗG39_:vÍ=–~Œ#çËsB³͙ɂ-r¾TØRÐÜó0+|:_†œh.ÝÛDsO v#Í™?ÛsÓÜ;ΠæÌîBY0÷4:ŽÌù<ã d¹§0ÃXÎßþ°œåM¨—FçÏæÜ"ÝÛ¥ñ¾sæÃ‡m¡`îi[æÌcN®–€9ó£ØGž³[ž{Úø…çÌZÓn‘îz:óY£hH¢K={ôÖHtæu)WD÷`¢ÎÙ¤üq½l.UèiùüÆGNÎ=eª…8g¿.ô áœY—ðDÃ÷²3EVú^6ÆJÏù£ïe§SRø^æ> ïeþIßËNh¹^Ú¼‡t½lGò]/;Ku„ëå`LL¸^Ž @º^6®\/ߙܢ÷Œvr½ìƒo\/‡°U¾—ÊH¾—[Úð½œL¤¾—öbè{9¹õ çËA—ªp¾Ti¿p¾4ïkxWºóåªRýè}9å&#ï˘p¾ç·ïåàA®—³ ®èz9ˆ>gïøWŸË.Òçæ“IŸ›S^”¡Ïuz6†>7éqés[¡ÏÑg7õ¹µKŸ¿ ]TÉJÎP `$NYB3¦n³BÆÔ©B!ƒêÎÒŸ ªSjʪSÖÉ蹜†@WälÝ£Êè˜Z+º\)…®)Ì2ºÆøŠK¢£3á%ѱ4VJtF-_‰Î*.¡4ºU„Òè–¾ð@»Å×84º%ñ74:ù„F·éÍ“Ý\r¥F·«Rdwähwx&¡4™;°Î7³û¬ƒtv«t.ƒ­[¥ƒ0FWKÊt*4|ÉtŠ4™®)º-d: [B‹d:äPú=è{Ž›îÜ‘ŸtÔéß”Ôé:s‰„N×™(+uºÁ ÙÔéF—C¦tº!»}ètñC§[  njó:Ý¢M"u:Û%â¥Óm¹zJ¦;K’éŒÂ …Q¦+@7d:g ¡®0}+t:ËÞ… …t:žH`ÐéŠYtqu:KÍÕ?:]in¥Ó•*¿5éte(²D:]KZuº»:]YЇÚ•¥_7tº=¾h×ÊdaËÔé–¶-¡Ó-üN¡nn…ãI¨;¬UœBÝÒF9”:{ÂèC¥îhORÝÖ@©Î%НT§0î”ê …Ñ¶«Eî¢Rê, øElWíÿïÀ:o)ÔîÀv.Üu;¼hWÃ{UBi(ív¾t-OTlW¹DÚÕÁŠ/Ávnši‚íìò¨°‘íê¤éMlW‡ÞH±kèB¶«*ƒlWҌڙ½žÌH´«C¢ÐÎR½0fŽhgjEBIuKAZB;{ŸiB;»ÂÑ®n¦GK±ÎÞcJs@»ªµ5Юʫ&è®î@7ÒÝ»Óà×Hº«,òpg_NýÀ]=Š·ÜU-ÛwíahFÀ]{¤  îì \·X×”GSpgã® ¬{ÿ÷ëšU»îšrŠîZ=ò¦Ý5“ÖîÀºöþäøþIwöAÃÈ@ºóAñ·Ã] ƒ›Ã]+E¸kíði8ܵÉ‚»6‹ÂæwÍœq ›îÚ”¡’pg§¼ÙÎÆ$Ê횢[‰vmÈ žh×ÌÍ1Ñ®©2–Ю 9ßíl†·T׆ ˆp×Â)‡tg— Ò]3½ž‘À»fŽÐÁ€wÖâ]ÛÌÏ)¼ëE\ëxg¿0 tgS ñ@wméّä@w–Ó èΞ ©tgw¶n¹®ÅÉ“îšÌ¹W¾®3ÍIû'3μˆæÞ²‘áF-wæ­¿<,;±Ë¿—¯«<æTÒïDKfÆR[fÞÉ–ÌUžáµéï±Ôr…¶{,µ\c½®ÏUñïko¹FáßÿÙ¹º*1ÿiª®š~ËSuõ¿Ÿªë)ÿ»©ºþð²œikÌÏDé××ÎߨêŽÝW/Ži¸8Е†KãD sõÑ(‘„KÃ\I¸bœè]½4R$áÒHW®):ÅHW/I¸4Ò•„+FŠN1Ò¿‘ªË’¶ÿi¦®ùÏ2uÍ’©ëoÀ_dêzûv²_ß³_3<ýš©ëoÌcÿøuJú³Yëö¶þ2‘ýÅÛú‡‘þåL]¦K½ëÝŸ&êzÄËÿü¯‘ë?JÔõvþ_ÿÅüz_¼½²iýç$êš–¨ëþï'ê:sxXƒ›úgÆØ°¿½ ‘ÚŽg.äá·  hp+¯Çe;Àžy†°ÔÎÛàq –Ým g==öFgä œ”QÞßÇã,¾Ú¿Û·ùÚ&iû,³¾üxy;ßÂÕÛoJàå§]£ ÚyâÛ¡XÝùŽu쌋°½¢–0Ë/ƒ–1ÄÆb¶XÒûX¬íºB–ªÄ'û¶älO&ëÁȇ ŒDö رÐÇq"¿{Œ'GÜÛ$pÃ8j8Ô³ 27×Â!³úeF;‹a¨ðƒ“.8êæê=fÂsïŽ%ññÚ‡ó<,ô°néq«ÚO÷Oµ‹øÁ, ¶3%×±41Ì¿…¿­î:t Ñ+TzÌ.Æx\·ƒSß'âQ*ް}\‰8¦.O„‘L\…›,ŠrÜ "¾Ñ<¦²®žÜÊcF)%eÄñÛb(üã¡¢>ßX l·•ïoKE¸P¥™ømi°ÞZÂ.4tÄ )šÔZ*ö1wÊÛ23Ô˜%ömAì+³¿/ µloãOÄw¾ QC²|¿-VëÇ“~ùñnÞxjŒ°³–íw ??ÛàÍßhAwF~[jû±šã´â·`fÎÆ–-ÿÀÙKŸß¿­ ßGK\q™0Þv†ÕZËVøÊ`‹“üd`ãÛb¦DÓL^±¥°ƒ"1yÅeÖsŠ—ÇýD2Lðm)´Ão\M­ˆïS£µlü½qžÚá'ì[:BüãoÞ–¿ÙôSšM€A~‡}&£ü¨‡¾-‹a~ßÝÛ²#Îow¶0Ð&†·åx`ßà `0=`Þ6[ŽBù*[ ¢ýÖÃ׳ծX¾Æ–V5W [ŽÂæ ûtü­x€QÄñ¨‰¿Å<7Ö‚Ùn–—¼lWxÌî žkx2V³æÀŸŠ¿›Õ¬QÝ=e5köOí½-‘*™ö¶T„þÉüa-̈†²ooC›ˆìëXÑ ,ü·YÚûm¾LF5k98Ñ‚5¦pJ°Š5Ô98 ÖDæ5kAàa1¥·åàkÞ¬DôÂÒƒ À§…Q€\`­a€‡)0ß–êë¥ $ƒGùŒ‘©¸ßËjzVV¯†±TW<ÂæU;îm™ µ§NôYÏoLàÆ­ g>«Wã‰Õ;æá·…kd*U¬™ÛâékçóA9«Ýë&ÊÙGL#Ê=[Û+¡ÜÃÄw‰r&‡@9Ae¢\éÚ”‰åTÝ*Y®L­Àb¹2´MËY6""YN™¡“å$µ&ÌÕ¦)Z0ge~ˆ\„¹Z¹3ËYe*œZ,W›vib¹r´šŠåjæ"ËÕ-zËUMôÁr­qK+”«‰ˆD¹z„=B9å(J”{[¸ãÊÕ¥%N('´D9ca"–£\cæ¥D¹V´Øå+Ý$Ê)ƒR¢œ²h'ʵ¥EQ(×¶`T(×a…r ­K”³‰€àF”k‹’S$]¢\‹Ç ”S´B¢\/Úóˆå”(Y®ï`0²\ßz©År½r¯,”özB9¹ë%Êõ—G<¤BJ’ñˆäúÑfP$g9¾Ii$9fýNëKL+³T”ä+‚ܘúzDrciK&’ë[ .’3ÆDyÒŠHnTaºHî=†X(×L,B¹1µûÊ™pL(#Ê®·O(7}?B¹1µoÊÍ0aåf\áP¾s~ÊB¹qø@Er¶tòD$¹YôŠäò ’ܬš-IræI'hT¾¤¢k!ÉÙÕð«›Ê˜Ä߀(wK¦r&ÍžD9»n”Ér‘®$XŽž~Þ–»L d¹ÈQ,gfЧE–‹ BÁrtE–»Ì%d9#N±d¹ËˆA–ÛÚ¹ËÙo)NËmy~ËÙ¹ êd9ÏÕDrëaRáS'ËÙÈB–‹òd9»‡çÃr[©Árnùà¸`9—l”Û+ìc¤¹ë¶Ò)Åm’æöЏ•P)¬K¤9;НiÎÍ,d¬Á‹šÛ»‹žHsÖ‡‹4g£ÌÍÙ?pb#Íyf6`Q•‹lÀœg€úÀœF“$an¯­'J˜³£¸JFSÍþÀœbøÎy·6­7„¹(#0gî˜0gW#ÌÙá”0·åµ4ç?qé¡ oŸh.ìX‚9»%ñ`ÎíDì˜ Þ€¹-·£€9»1`În¼hνLx9 ¹¼qÑœ7Ù²Çýö‰æÒ|'š³·¯~hÎ,™<Š4ggêìšKS¡h.±hÎm¤PŽÿvJ®ºãI÷èì ƒjâ@åHtöï¾§ÓY~3ífõ:,T…‰ýÅt<놺ب ê\GA@mJ;ô:@çüöêÌÙ›cŒ‚?N ¨³†DÔ" ¨³“âÖIu>$°Tg Auž¥ ªcER @PÏ~ô@¤"Ô©þ ˜n£bg2uµé|WÀtvW¦s×-œLçOê'‘Îþ&'éìALœ•â\¡ù‚â\a´jˆsÊMâKÔ„6W˜})´9+Gñç,¿ëÏ¥Í=‹âNù_S›Ó[Ú‹Ú¤6W»x® ݃¤¹Ðò’ç¸w ž[2 ŠçJÂÄs.qÎå0¹ª @à\$šëZqƒæºö0 ¹'Œ}AsCóºhN iîºÒ\©fO~Ÿâ»-a”æ}á\2ªpî ÃpÎ~{b!qN¿‘pNiˆçä‘›<¡œÒ^&ÊÙûøE99è åòÊ•"Q.'"¡œ OY.–ƒD9ËÐ@’»ºääA’$WFœŠ$w\‰DcÍÉå·-’Ë_I$—/¾H.?L‘\þT"9³²I.W‘\®"¹RÅ"¹üœEr×8«~~(‘Ü3ãúv®§h Èå©Erù‰‰äòbDr9m‹äJXErùˆäž©OJ$—ÓH.¨H®춦] 1.Ia\®h¸ë&ÉqÏ”UKWм#Äqù<ÅqyÛâ¸FVp\Þ€8.?q\)²?‹ãž48c5åJ)ŽóiÓˆqñSŠâÞkežXK1éѪýÑäòãâ Œ‹§WRë#ÆÅ^)0®”²+êC•nÆŠZ¿_K`ÜÓC5ÜÜ"ž/Æ©HBb\yø„ãâ× Œ+rñ Œ+MçÆÅ§÷P&þRqºmϺtiq›q*ÔâÌUðãY¹Yì;ä¸Í¼€!Ç…¦$9n‡tF9ÎŽ„4F=nÓ‹bœˆ‰bÜÛÐПbܦìbp%NQB‰ã?R†ÛÔkC†ÛÌp:\@nwa¢<*¥>…GexLJ‡Ë¹¿:\øCJ‡[_Ž ©Ã1“oêp ÒL..Š:\Ü©t¸uب=y"à›ùµq?J|;VûG@wà0×eï'¿™ ZÀoæ¬ÅgC~»|ËÄo'¼áÈo~.Òøíºbò›y¿Ñ>íüfS!?ò›Í…rñ¿Ùü©3ßÌcN¾™à7;71•üf[¿ñÑâ";Dð›yÖçn`tv¿¹Ÿ@pæF“ƒœ»-ApGѨApæ'&wHœõáçA‚óç¸ 8[è—.·JõzU*6½*UÅU^•Ênq¹UMr«lžƒÜ*[8¶É¯²íÎåWÙÂkB~•-< äWÙTåWÙbÒ—_e[ÒTäWÙª,6ð«lGz¨ü*-Hœ|D¿Ê:ÂC’~•-}/éWŽmr«l[ÓÜ*û”¡Bn•MʾÂþèM“Oåx4*]*{‘f—ÊþèÃKeûÊ£r„§ƒ<*Û–ˆ<*ËÑL(§ÊGÉ©Rþ“ô¨áß!Ê.ò¨´) ?£<*ÇühpÆ-„QyTΞ-ð¨œá"Ê®ò¨œI„ô¨|ûá<*G8È£²3ÇqzT*Þ8=*g˜—äQÙÃ|ÊÑeª‘Gå ? yTÎó‹g•¹ Ë£Ò$Vž‰•kÒ£rÌ<â[ç%|«ÌçH|³íòäßÀ7¯,H+áOv>*œo²?.•ž¹  ·H€ôæù‚?ôv·€Þl`yx‚Þ<µ*Öow:V›áŽ4BÀ›R%ÞÞ¬ÏCoIÀ›õÁï$x3’hlaôjŽCx³>çoqÔ¿vK ç5ËäÄH¹Cwñ9KS /K‚ÜÑZ ç°sqÜá¢^{â¸Ã7Pî(|J(w¶49¢ÜÙÒäˆr‡Hs‡YÿB‚{˜½,€îÀð œ"nBSú©PàlŠû(p“aö¡À©ÞS(p*ßDN™kC‚Ó¦Šœ¢BƒÓ¾14¸Ó¥—çl^øHpgkÄõh¡_7ιw?.bÓ¹Ÿ›áœùàÓ£ÑpΦ2œe™ârKš;ó$ß±´ù–•š4gçç¬Lšó\³Ÿ9Ë[õ¥¹c;:ž 4giN¹¥y{v‡(š³CŽ–X}»4g-܃‘æü¨ÍY’y?‚ælºþèp–"@`Îf}Þ&aÎÒh)sX|N ÿGOÞ{‰…0g§–?äDzMÛ¯*hn#Ú>ÑÍaÅÀo¿JO¢µ¥º=ž¡°†ß`΋ŒÏÛ¯2¾æ¸õÖá|Ü’4çcð9€æ¼ŠÆèU B# 96k×Î4ç ½x— 9OKÿМçi•OçfžM-¤9ôI9î>hÎËžKXsšóc¸åÎe*Wᜧ`=·ç `%Ù9Î5{»ÜÖ‘(¡ÙçüŠûÍsžvÝž•~TO9Îë“ßž•YQG8ç§æ·œóŒ£óƹfk:_àÒŒ*"Ž•Ïs€sYáG8çȨêudà´¼]·ç¹.Ÿô¬DþLüé0çyAùæš}ÂBK‡9O³*ÇÏÍ4œM ãaÎÐGÀrH犆‚<œ}{€ržÅôƒr~5Üñå<[ÈeÆW¡œ,Òä”óTmÔ¤€r~KùåP±ýF9G^ŸŽr,…$Õyäüw”Ó¢§¸´æ çNù6Lf¹]9Šƒœ·<7ȵg:äÞÏc‡`æ ÷ö¹u8ɨæ9Ľÿ>Btˆ{Çè1ªCœª€?Ovkß²þFí!«M bºÛ(å çÃ>ò°D¾Ûõè›Ä5Ké·nˆk6¿?òž´…ôm™šüsÞîìã·ç—#²sóq.Ê÷ï‘zrþ³QYÉ}Îä$×,Ÿ ÒœäÞ–¦$ç÷nJ/õñ§ôaÅÂ\Þù²œ'÷“†ÿf–­Zµb|þ}e³ò–+aÿ¾2bUK¼?£¨åm÷Hj¹Æj……xòŽÕrŶk¬hùÏβU,ádùw³líÿ“Y¶þäu)ûùãʳõË«ç/Õ|>/ã?b¬+‹†º3mq¤ìÃ>Ù¸8ΕE‹ݹ¶4RöÒPŸŒ\ëʣűîl[+{i¬ON.ŽueÒâXw¾-•½4Ö¿‘oë]†'ýÿŽ„[gVûÇæ§?›Ãþñ§¯î¯óÚ_¼ºë_NºUŒ=ß=êÿϳn]3ÍÿŸÿBª­÷IÓ »HzOC:dÙtJ°Q¶WP’ Â<«ëvî¡•?sÍrOöÿã1Ö\- Ï~Ñ÷Ó• g3ãœZçåÖ›GM˜M™³l:¬& ­×kþñHjF@l:¬%«ó>Z}¢è°Y¥xv‹ÅöÈ€¥œÞ–:ÃgKòIµôËïÒmz¾u¦³a†÷‰ÚÒMr(°àµ`â=Oµhã…Q¬,qG‹F9´òVnÀêC€#±j’lÿëC€#'§jåeŒÁ¢?À‘#Y5›ÄDìyëƒjmrY­F©ƒ&eö€?€§ã¸î;gEˢŗ9ÐÞ– žÃâ]oËyþ `©¶õ¦-¿x5¢¹·jÞã3P¨Ú~¢e²»<2 TÛ§Ò` û@-rè–e¢–ó/cÏ­O‰.s(<}òÔôxä[ßÞ]ò|¯e‡÷º¥ì.hÁ‹\«œº›~òZ'0KšÒžTËIÍ4i`éZó¤eŸFGÒx#,µ5O3!•¹zj:N¶DŒ=¡Ú\Eob˜j¥G÷ûZêš]j'¡?·êš¾û÷ޤÊ«¾ ôç~Nt©g¿Ùw€‡%bÞ–?RUT}[:ýH…ÕÒO´„ß–#W؇GͩŖEw?ÜPÛEþ|‰,‹0½0'¯WÞÜ2;Õþ4ù0òuíéÍ ËéÛ²å0I¡vys˳öÖäÍ»xTgʺÊ?·â^8#ôôç®l™áHZ8ˆü¹ÿÜòÁä»Ú÷/1µŸ1#è3žt#=l‰˜ €|µš3ôjåÈ£ÞÑcïß-üHuŒœ¹³¥ñFzscê®Vr†‘RXZªJÎDN…j›}ÆJqšSÑ™²ôùXÕfbèì“þÜXß½åøŒ; ýH•§ZÕ™ƒŽbUgú÷¨F?Òøx¬êLÃQüP­êÌB¬ÄÕªÎÔo‹¼¹•3¡ZÙ™‚Þç¤?·eoÇï0÷úž[îÜqÅVtæpÜÖ£:œši [äÍ}â Vt Ø’T+;Ã>üšWŸÊ&Á ^ÿ/wo³ë9®-ùÍû)ö° ð-Kâ‡HžÚ6PÐèîÁÍ{úÂðûÊ‹ÔÎUY…ƒFwOΩÍ䟢$Rä±>¤šžJ€rF˜ðtì4X£é7r^ÜÚ•÷"üõÔ¹/^GöOþ‹×á©:dÐm?½“£ž%Zk† º¡dèWˇQ_$fÙ~cÆõtÛñŒ0öcT+2è¶›âm…%º«±\µöåËè_IJ]u¦½OÉaÛÕ_WŸç»Ý)9õ²zv4“%ú‰Ul4«JdÑ Ç´_#ïzڜۖ‘FSU;'=¼)²ÏÈITSÁÙDOŸ5?Œ{°Ï0™†5Øn(JsŸ å°£§Xd®ÓT-ªcGÛöD:¹ûݲ½%âž<³ß§jä$ÓTUÁ]ÝA_j\ûÔ(È7£î©wvuyEÉD£¤³Ä®Žs•ä,d3§]§N ËiWÇÕ°]‡6Èå´¯£'j9íë¸Úéê¯k¬È5\ñ#™Ê|×±¯ãªc_GGD)ב~Äz —}åY|Fös=`½„k…®á' D.Q;íž‘)Ü_>åÝn鲫c>OÎD‰.dWÇUGö²nùg#smð×;ÏŒÑ2á¯:~¥àïÙ"ô7üU˪ XgT"øk–$þšb$û!(Ë›ýšG.ökWÖü!à™Úü5†P^ì×xûµ’<&ösŒ±Å~­yÍ~Íá!“ýšCW$û94Ùb?Øp©e±_³¤›ìך½óÍ~­ù-˜ý¿Ú쇱üSè×,"ѯuˆ~øÑýZ÷2eôs0µ…~ÍÁ ýš)=ѯyØýÚí-±Ñ¯Ýù¡ßVGè×n©‰~Û¯„~ˆ„Ñ~ä¥wÈ™üš«.òk·;lòˆüö ?ˆ2b/‚JÔ__FOò‹:, ømä>hŸ/îÛ¯Dî c(ýŠÜ‡’þâ¾½Ü2ÞŸî@臒!@+ʳ1ôD~Q fI~(>ˆü¢äE~{Ã$?åúÉo¯Cò‹À}ùáïóE~Q"ú"ùm­ý¶ ý¢¤ªdºê±Ø/ú§’ªÙ<½EûíW'û¡Dø-öÛ¯~××=þ2Ò|ÂßÞîìyQ öCuXìÍÛÈ~ÛmŠýâW‚4²ßÖá`¿½Â_¼]»5wÏu8Ý3Þ‡û§‡%þ‹+©7俽òJôòÄ[;â?”‰[ÁU^}ýE2$‘éo{z¢?ÔÑëýů^ôÒ•Hû¯HQG¬·4«ù¢¿ý.IwW¤kÂßö¨¨ G%øÛnJð·×)õÓ ümüm· øÛº'øÛûCøÃ¯îüEPMÕ÷»7³zœkð þ¶k þâ˜øE[oDëa þÖÙ²áoëŒà/Fo\ð ëR²™íG^ªÏwgd5»]ÉáH§¿²‚¿håRÉðHÒ†à/nAà$ÛÙu›‚¿íêÃQIóêÛ] þöVûµå‰WÇç'øÛžào/‘WdWWä¹uEN‘kDˆü¶é"ò‹Û¢ãÕŠÈo{"¿#jWΑەd¾ÆšÐÏÝúí–wäviƒ¯ç"ôÛÞ€ÐoÝÑçŽi{Üæ5Ño/¹2w•‘“$^ ä$‰vuò’ÌQeð[w`ðÛ¯$GIl­Äy$¿ýWãÚŸŒÉooEÎ’Î|’è·õFè·¦²Ñí¨@¾’‚dq_¼4>;qßötÅ}ëU›ûö¾tõöÒßr”\w$îÛz"?I÷DN’뙈ùÖ€2ómOEÌ·†ª™o¯SÎ}ú¶¾ úÖ3ômcÊ’üV‡Ð·×¹s׿ÀkqßÜ—ªPrô'ö…5ç·úÖ¿ úÒÛÂÌ7¦‘ÄÌ7°ú¦|BŸ“Ë,胟‰ˆNÐ7­Ê$ô9æð¢¾y( ¡o“Ü}s“÷¸§ò]Ø'áš°oë°olàô=¼©Ï!Çõ²(ïzýDзzgè[wièÛJ}«/†¾Ñ¬„úÝ|Aßv-AßVGзžŸ¡Ï!+ }[ A_Þ”™okVÌ·J }ë¦ }ëéúÖk1ô­×bè²NómÍŠù²wF¾U â[ÏÎÄ·—ŒãÒE|[_6là[¯ÉÀ‡{”X&â[÷Hä[Íùö’Ûw 'eä[Ý3òmí ùÖ£1ò­·bäÛ~%äËçkâÛ~4sª„È·:cä[—6ò ¹N'ñåÃ3ð ¥!^À·nÛÀ·ºkàÛ®$àÛêø¶þ ø¶÷ƒ1ð­V |«Žo+ðm¿ºrºŽˆo/ɹleQÄ—ÇÀ·5¼œ$U¥Ïw‡»Y%Žw³Jð&ŸƒyoÕ1ï­:#cÞdñÞ^2>}iÈ{Ãù‡’÷Ö›3ïm¿Éø7Y§ç,¬/±oÿÕ8>}jŒ|[ÇÁ)^ |ù@M|ëG$¾u“&¾­Äþ¿¹ÔÌ•–ÂuìœÝ›ŸS,è[ÝÐ7ÒŽÅз¾†¾­ùi" úò7 }[ÉYß RBß(ò…IêËר·•Ô\R]Ò®÷kHìÛêôû}‰}~1¢¾­ÂÈ5Õ·0ך*l:ÖšjÆ;߯!©oµlìË——ä·ýª~ZS“ü¶kµþþbŠü¶÷ùéI~[Ñ?=bÓ_>Ã_î?þÖ [ÉŠó‚¿üð&üm¿üåJø[·`ø[·`øËQœð§…áO¢~-ÞCÌòî!ø´ KCú>׌¼‡G,]MÀw;vKßí t‰|+ý¶ñÄròF¾Ûiàùž’.œ³g:æ§‘çjÙFž—j§‘çjgÞ¯VÒÈSÑqùVgŒ|÷eÃU#ß}9 ·‘o5#â[}1ñm ‹øÖ|[»"¾U垯?Å{Û ‰÷²ä=ÿ(qoˆöòQ&ím­ˆöîËh¦½ÕLÕŸ²Œ2ìå›NØÛ.$Ø[Ü™ïÖ?ëm?ëm½ëe3F=Ù—˜óV«æ¼Õ*9oµiлÀ%AokE ·ýJ ·µ+ÐËw”¤·•õVÿEz«@ ·~cÐÛJôV_ zëôÖôö’™ÃCŠŸ@/;cÎ[7iÎÛšçmÝèm%½íæ{ šôÖoLzÙƒÞú‘Ao/™ïçkÎ[Æœ·úbÎ[?æmæ­*÷§ÞŠò¶V…yë'¢¼ÕS^V1ä­v yë ywM†äÝ5ѰªÆõ¦¼»& ón§ HÎÛ~%ÎÛ~%λk"§8/˜(æ´ywMôäÝ—·Z%ä­;4ä­¾òž¯Èñ²êŒ_½u½Û& ywMÀäm- ò¶þ\DßVû]‰òÖ¯Hy·&å­·dÊ[ïÀ˜·•ˆóÖ•Ìyw56›óÖó3çmWçå{2æ!3®:,Ì»Kv00o«!Ì[%Ƽ۠jÊÛªˆòœínQÞú‘ ïNt5ä­*b¼­]AÞö#AÞúQŸï ‚¼UAŒ·µ*Æ»Ìxù##Þj׈—¤D¼»}²çÜ&â­§mÄÛÚâm¿q²Áu%!Þº…±2Ç»d%toVÆA·ì”ƒù+#ÞªcÆÛK^ƈ·5"Ä[6â­ÎñV3"¼U À[â»íBâ»õôÌw[oÅwnFx—?I¼ËfïÖODwwIÝå %ÝÝ ±Dw[‰èn»”èn]Jp·ýHp·ýh\ûÜJº»¿£»ÕaÓÝjÅt——6Ü­Gc¸Û~Têç:‚»Û‰î¶:‚»­¤¿;l¸»}´•pw+Þd²ÝvOb»g w«3†»Õ°ánû••=Û”ü‘²g”[ÊÞõIÙ[%KÙ»ÞÊœ×d7*¸»uêó‚%é…Í õLðz¡8LÁ§õâ£"غ”¬½ÙL¨‡€Xý…zH"Õ^¨ù‹XДˆ¨¤^S"¢þÛ ôâCôòæ[Y zÖÐ_ ·×™­4ýýzñ9“àFÒ3-[Ezù`;’„JWé¡Äf•D½ˆßeøS®ö¢Qo{6b=DùºŒvô<˜2 ë¡3n–°‡[£ ö\ #ØÃMõí1ÔW(”ãˆ%í!Œ…6©¢=ÓlVûTôœiŠá 2”¦qoúŸÉz¬PŒ(Úl-nÖC‰¶,b=|×Ý YQ»ìCHÖ›wO—7ÂÞÄ·ãÅ{XÞºêÌÍœsŽòÉo/!ï¡DJ©xA°ì’ç`P/cNÄÓ°¨"AÁÛJ9‰æ°Á¯h/–™B÷"bÓ½[s>kˆíy÷ Þô÷¢†?â^¬Dê.q/‚/¹€¡hÒ®Y´Qˆ^²^„˜’+qïùÕa£PÇJ{ß+h/V/‰Á—BAÍ’†£ób+“ Õ¯·1gDÊ9^Æœð´y§ýøÒ¥5ùV‰ùRR´#ßq¥Ñ¥ù–¿¥ùŽ+M@åÈw¤§ùС¦<ù…œJG¾Ã‘³Ó‘ï(i„)G¾UÇŽ|GIg99ò©ÙÉ¿ÕäÇwäÁ9ýøŽô¦³#ßòµ#ßV"G¾Ì•Ž|‡s¤/ßQóÚ$¾½7òå[¾©öå[7n_¾Ã™Ò—ï(ic¾|Æ99ò­ Û‘ïpj‡tä{Jì¤'G¾# íÈw¤•ù¶–åÈ·uEŽ|Gµ¿²ùŽ–×’#ߺùV»vä[ÜŽ|ö’“ßQ?{ñÎí’^|{Éô ÌïÅxéz(I³ÍËo@Ï^|Û¯†Üxõ¨ìÅw¤O¦½øŽô”´Ÿ³i/7¾ÕŽÝø¶:rã;ZšvÎÏUäÅw8Hrzñ­Ga/¾£eËïH·M{ñ­·b/¾íäŇμ½ø–G³½øVÿìÅw¤»½øVíÅw,®|ú[^|GK¢“ßÑýøìÅw8Îszñ!¸—z#/¾c“ñ4™Ó8Å^|‡³5¥¼¾½øV{ñé»O/¾­†¼øÖ•ìŇ[Ç;|÷Û/“ͤßz{öäË OéÉ·¼ÏíÉ·]kÈ5>ߌ=ùò Ê“ï追Èoe›IG¾£'Ê‘/»—Ž|ySéȇ^îtNVØ—ÛÞõ¾…täÛJœ~•È“okgÈ9þ0 N÷ÏR¤\ùVoìÊ—9èÒ•/_Cºò­+Ù—/³I¥/ßö+ùòm×’/_ºü§/ßz^ôåË4téË·ýF¾|[ùò­gc_¾Ub_¾ÕŽ}ù¶ùò!n¨xÐy WIyßù2[:ó­þÙ™o+‘3_æKg¾õŒíÌ硾‡+ó*ï8MiV(1•¼B‰ýðw[(1Õù›¡Äê3Euó Y²…îRÙ(K¶0`•‘«WKü{o%{+ü{k£äÖ»dkGe[KYòO%VéåùŠ%öÃ@_gy6åúq°±§2ÃíÁ€þ$>Ø÷c  Nÿýñ Øôi<á‰(ùÆ+ŠÛÚb±©=öWsW×iûºÅS;[ä/5´GþrK«–›zES[[ä/µµGþr[«–ÛzES[[ä/µµÇs[«–Ûú;ñÁÊÅÌ!À³ëÏb€•? íõ)TXù“z¾ìç1ù§¡Â~â«õûwߟ¯¾Q¿=Š?}·¾Åß·õ×C…Õ#bü*ìß¿ öï7TXÁá´Ñk`ÿ‚ÈÁAÛüÙÁaÞÃÇÜGTGakd—ÿ¸±×¯C£—8“ù ÿ+ f¤êÈ{N¹H8|j=Ò(@ÛŒzœR%e«¶ÿ¾Eoñéw†‚É’Ò¼7*©òÀ¿u%Å{*Ço. ¤bo{±¤R›#VDyÆJ;Çg=!õ– òSÀÿG+Ó^ ñÏ'^Iµ3Ê?L*âÅžJs©$SÏÜ,¸ËNU YÀ¼íQH5ÂÓ[}}†=Š;ÖgZq8´ ª§Š2ÊSÂÈãýÎ ¹¨ç`ÌbP±®>#òø³Îê@ï)aÔâé@Øõ:ƒU¿¹NÆ,~.ȽT½®=ŽŸò ó)‰˜Å×á˜:õ*zü*Ž©\¯8)*8kj§Eèñk8àËSA‹1y|­¡ÇQ•{Æú hüÆgIõ0¸ƒ‚¤K*ˆ˜ÅØ]:vC¥\TKœ•‚h ,8#ô87*‰Ðã8ˆ*úÑ!‹±ñ¯>ÜAi—SKÅø•¯ñü*ÇìóøxêñA•qÇ+›ò!”ˆÀWj±ý”DèñŠpõêJ•Šca]fFèñ+–×ÇD±ø‡ "òø3v^„Guâ¨è¹Ôðsx®ÎKkÄÔ8(*ˆð®‘W[D,®wÓ6¸ÖÁÇëíhOIù¢ SíÜ|üyÃ~¾uÄ©/Jô|k¸ñOIûâèY´8+*Ø–6õ¦Ç±ouè–Úâ¨èy\§Gc»ãØOMW7ïàÒ)um³ò-ä|ï®såG¸“ƒdzØô3N}±°ê9ô+¶Võt¢£ÚËÉy:ü$z=sÐ!Éž}u >ÏšaÌ’·t¨J?=ªêt\:ŠjÜ}“‡7ÍD9%NqUež¼N™*'®ÃcÍÊ\9‰ x^‘,gð5N+³å<¿²Ï]Eºœ[¯R¿Š|9Ïü?tˆ^‘0Óy ø1§çpÁß{¿¡‹ZeΜ‚ ø¡™~`› cÀÊ´91ýµ(„£JŠ?5Lœ‚‡!5ΞÑNõ"ÆÔ9¹#šK"þxéV‚*ÓçÄçˆHEþœ‚о„L ó”Xw«Ì ó\»fIk¬ã|.•It Žàõ1GïnøS™F§`5ÓEÜCsÖùÊD:¸‡øs28p¹s†Q^‹¯'åÅ:Oü²Ue&‚m½Vˆês6üªL¦7©oÄ 5„'ÓéD‰~jÁ‡UŸ,æÓyJìSW™P‡O†!¡dç nQ™Sç¹éKQG˜G³Ýá‰Sêðµ–„„%ù<@Ý•ØoÔ\%þB¥‹ í÷vl_Ãߊ>$ö‹¬¸Z?È~L>§Ú„ãQ‚¿z/\%üáZº+Á_Íd„†¿8%+‘ÿêçâ?¼©sã¿ç‰xˆÿêŸø¯GÒù÷©á(þÃÓÒ‹ÿ`\%˜ÖéHÀøzˆ €ípX Jš®N„–>×A€a_Å £ß²S%$À†± ß²!.#¶ÓéÚL€--ÿL€­8© ð!oqE€øšmøì…µ×1"¢6òÀvúp̈¤oØN'»36ìðKÀ†í­ ‘ØBÓÿ¶ø¯Õ, þá«)Tþ=@¤µŽø‡¾TA$ñW6¦ÿZ™&9Ò_+‹!•â(SÝÿ`'.ÿµg‚ŸBDò_X½‰ÜÈ(èDÍü÷`‹IXüת8ÿZ†ñ5ÿáJbZñ_˸jæ?¬0¦=ò_CÂeQ#ùwoþÃ뵈ÿZêBæ?¬fúñ§¼ðUNãÞ÷d·rã_ëÅdüÃê6TBüCÊË&J#þáQŒÿ!Ûfyñ_»K^›ü‡Wå_‘ÿZ³)Žù¯Ê8JþÃúÛ6þk¹§K93Ù®øÙ@5έ};ä_ ¶0œvlý3Þé%a¼­Àˆ§7êfÀ0Ž”èt/SãÒ VŒ´)"u‡"†‹±iÅFŽ aשlb7 ’'\b7à( 5ÖþJn_¨ýÝÝMkõÊ Küë¹ÈXü[‹¿Å¿aÐMÄI¯z#¬·UE`I@Mñïüí“öwhüïÚß¹ñß̰Ë)þÕ\¢-þŸ$b?+p3ößÞüKæ¦òßa¯Jó_dÙÔŇÜ=–bHíÆRÖ"©ý±ƒF¥¿‡Í>IG¾%óßí¨À;êm¯™('„ñšD»@z¨@É¿k6üjª6\à¿ Z튬ü]^Rúà ¦ß§³U'fDïÀk)tÀÃÉ €ð¬h/DâÍ.áŽÿŠ)=›À#s·ÃDñßs~Væ¿™'*æ¿ô=2ÿÝÏüw.…Cü‡¼›âSñ²uê,Dü‡Û΋ÿpÙ-—ÁìКïâ?ØfêœCü‡i__ò¶3¦QÉW.‰ÿJñê`þ»°s|ñßÕìn`þ»àZ%)üWÅç3¢ÔÃà?Œôó%ÿÏðÖFSüwÆjÄ?|=ºK¦wdz1VÿެŒ=Ï5Ä'²úùïù4{ç)þü1|’ÿp›§y/sÚƒÂüwö£ÄøÆ˜íÈØS™íŠò‹¸wK9Pð÷|µýüÁ‡ÃIþصd؃ÿT’ÿ®^?ñßõŒO×!ÿ]Ç‘˜Iþ÷L¿âMJFÂ¥¨¿6´‚ 6S®#D†²7¦Ð6Ì)ÿu§Nù¯äbª^/¼ÒLjwk$^aߎ Î4Ê€x:‰¶çIÔ€íȳ$à:v3ž—Ì,þ=ˇ)RâßåÔÒæ?|H§¥¾Ã†ƒ{â¿ ÆGê ùï*ùzÅqhoÚcöái£ó¶qš¨ä¿©_‰­HEýá–¬!Jýë-9NêÞ¹J¤þ­9(úÃÆ·½ä¿ëÎá(ú»ÖY§èïBîøý]iNúƒ¯ŠdÑGeÓßY>髤ðŠô‡ã’"ÕPúßHåÉú_oIšÒÿJO$ý•Ó‡Ä?LÕ„½“SՇƿë¶#«ñ¯#÷ D7éËÐKþÑ€á‰ô‡Ã'ñ@Ê>Ú6ÿ û‹ÿJujÉ—‚/ÿ0 çKýƒMƒž¹øGŸí¥þµ¥g™ÿžGß­öQÿƒïÝ‹ÿ`#€ÿÕËÙ+ÌÐ\á”ô?ôPœFýO§O)ÿ]ùâ,ÿ6ø0þaÈ–—ü‡‰©Ûþu-êW¿>|)ÑüŽ]"ú+©+ÿj&ÿpø%1ð/tF¡ñû™þ¿‚-j…øWмüRü{šª"õoú‹oúÔ:T"úÃ^J"¢èïiØÌ(õoj_â_sÖr‰¥e³„¿’vn)þ}Rþª<Ðþ,`Ø¢½p>zÑ^I3íe öE{ÞË‹öîšjž¿ûNft(‘SñéoÅoÔÔ ¥ø´þ³â7–'ÉoÙíXò›5>{NÇ-ùÍ‘B\UžN¡/“c&ði¶gà»Îï|W~oøúo&ÀÛžå¾_w šTü¥JH%ů[ê´àwðÁ=Ýêõ¾y'ËIïÃÊ'ä²àçäA‹÷Ž„9Ÿ 'ø`¿¨v$ø „­öyFkµïéÖ3«}ð“\r_&LîÑlǽðøê;î]p™7… ÷Î;9M¸·L²¬÷=ËQyé}GO#¨MïÓš,½Ïní©÷]v$7ïÁíÊZ£xïèIXâ½3Åeó^ž¤&ï]þ§à·®eÁËÌËÖ¶²oÞ ’T€U¼ïÁ-¬¾Ì=Qrï!O¢|¨cSÀwØJ'ºøNßYS&$ðű٠|Ç,‘`jYŽÀ·=ßYJÚ‘ø0Þ5*|X½-$øN¤I{ ~ˆ`KR߉c–—½'ZÖVØÀ©Nü$à{¾zþêÔ@ |Ïo4cør+â‹q"ŽÄ˜ø">ìRÕ"¾§£oÁ`fCR_øÞ ï|8Šoà³8v\Üg^¶þœ) «„´ X¢=L>eÊÚó¾?©}åÈ–€“MÏNÀ>Õð]K›'ð¼Û\‚øðä‡!âƒ÷£áÈ·½^!êÔ7òÝ9ùòYùîÄ9#Õ1ò9p†‘X¨ã8!_¬"ªs6ÚH¼¶ %óá¶ßŸ—ÞïH#qßs±éÚ{Ö’Ö²÷ìÍšöžÃ†…iðù ÙbpÚ®¹oÀ3lQŽå¾SYËÍ{Ø=žbBñÞ‘;MóÞik¬ä½™Œæ½ÙÓ¶Ôöž‰Fæ½QÒš³Ë~Ö<*{OŒ)„²÷¬‰e¶÷Lg£´÷lž»iï™I |Ø‹‹{|%c&ð¥Åï¾–²¡€oZý&ðaÁ“%â ÂR Ù{Þ-iNöžóLñÑöžwj€2øÌÈà&¾0Ö}’ø°$Ÿ/â+é씟ø,¼¿’éD|÷™­ùî#áMÈ×åÙbâƒU¸Ì‚E|ØUÔñá@äcƒÏn'•4ø¼óÀÁŸÓ fâƒW’JöžËž—Äã0ÛÒÞóòäN{ϲ$7Ù{Ö4ŸòÁB£DÈý^#]È÷LZñ„‘¯¦ÿ“‘6º”ˆ¯Õ´îò•<¥ òEœ›o‹øje›øžý >Õ†¾êƒË¿Gl`Ä£x ¿ó /­) »S$‡Ï*—ÜgKVàŠÞ²ä¾©ï[Ê}iG›rrJ¿0²2«Dr_U\Õüâ‹Êê}Ã)gà}åÿ&’öªŸ:ÙýÍ»¤pGú›#¥Ò_Ap.-B¤¿`Ó& 7m Ó,ø÷¬Ž; ü+ˆ‰e‹ÊÀ¿°YÜñ¯ ü–¶öÀ¿°5´,Ç PP ìü÷lS4’³ß©•Lž~çÚGÉÓï¼SÈ‘§ß9sÉ‘§ßU–áÐÉd[íeé<™Ä‰Ô²ã¦¨µä>|/Þž~Ø}i¥µ§Vöÿ! Ô ÿâ³ó¿kèÌÉô‡OŠ!ü…Û„:wûèÅÒÞI ²þ›i«Tžm¦› ¤ãÉÍ­›ôNñM›ÊÏ/y±ßZ_ÒÏï^üe?¿™†›òóŽç+?¿r'ÊÕ¯:Sbºú=ýóµåêwæ~×®~W:[‰ýàÎd?>²®¥;·¯ßH;3ûúÍ8ìëW-qÙÕo‹ÐÕïNgK¡ß³x¥FGôkÈô®ÎHë«©!Yë›Ëè‡_Ùú“è‡ÃVÛŒýž…1uE¢Ì›æ ýZMÓD¡Î7òkËãMä‡zöý#ùÜìÖG«Ø…¼,=[æÀ0øÁPéÅ} ù^àÃÈ&%!DÜUt¥)›”Ë(è÷l)­ŽŒ¬`ûK¢îãE~0¹,ìùõ "dòëg~óD~°Sê/G?ôRp"?<¡{3õD Í ‘Ä6³*É’n"òk-é[ä×3ÞŽÉÏÓÆ”$¿6sˆˆüÚ¸"¿£‹—«_»GÊ$?ܹu»vÒFª¼ÐñÄ4¨…~Í^)&¿^ÓäBä‡GQÌ‚A~½4ÿˆàAv§?¼žÄ¼?¼©·Ô‡ c×ËÑul· ðë5%x_DZ¢­?üzÍõTà‡Ñc·>‚_¿DA‚&¡¾ ?W3düÚrqøááXM#øA1²Gðëø~*ú‹üúóÙ¼^jîʰEòë5@})‚¿>šEC².¥¼Ø—R¢_L¤—¥'¦„ƬЯ§¿*¥¾\÷RêK£_¯¹E¶¡g®tF¿õ¢Œ~°.!úõ[ÂhÚyNÝ€Á¯[›øA5©/ðëÕŠˆ¸¯U^fž}¤1ž¸ulÓ *¾ —ASù-òõ •o ùzIC!_#>ghKŸ?_ïYÀ׋b |Ÿ—Ä×ÁAhIàëÃë}± ¯ßw ƒ¾^¼I3ðEÌ¿ðá³cœ#ðõáC _¿šM*É{{{Y]’÷ðÕ1Ìøz[—&ðuŸZ¥Â‡mÇËÀ³—úVø0r/[|Þ|¾5->É{=ÍäÌ{=OÕÈ{=OâÌ{X¬ ’÷úÆrä½®w"Øëð²“öða°â'}ï—Ÿõ½i—@²^›dbwÞW’ö:nC ‡qçºaãã|Á^›r(2ëuÇ­Û£†3laŽáAÿí?DXËgV»ä[–\Ç©èåÿù~·j¹Îþ»¿5ì»+d ì~*ïãÓ%þm+y>ÕÝ«Z$<ÝšrÉ֔ж¦²d5á‘çë¾]²šrÑjj•lMU¨‘¯¦\²5¥¢­©,YMý“¢‘ŸG×"AÒŠ1…mdý¥)2PYÁÄøŸ¥»œqê» {Ý0¬¾÷º?l—±‡ê Röý€€É_ÙFêïß^ŒËçú,u{-75¸ö™zÙ” ö¦V%7µ×rSÛ‹b6傽©UÉMíµ²)Ø>]Û ºàÕTVʦ¶ZÙÔÝ«4z5¥‚WSY)›Újýìè»ùC–€T<çwŒ²úG1ʾ{ß_Ç(ûQµÏ1Ê~TïsŒ²¯‡Ù1Ê~âùÕ§èû/âïðUÛk}5Š¿oëÞ vãû̆ãVÇj”3[‘À Ïÿòñ+þýºû/ÿûó<JîGÛ û¯60Ï´ýß²lýë?ò_¿oæ¬[á¿>…pȼ7îüøô1nž•»#pzôîÿü1¢®Úù?~}ÖâgÉ»~ù¿òBÿwþëÿó|Ràt<ú/¿¯ÿü_q¥géþå?þú/8$}þë¿æÿß_±û¾ó—ÿôT;Nw(^þ_û 4„Õ†Ϩï°oe…}+ö­ÿiķˆoüŸ­ð¯Äy+ïËôUütáß×ß+Ä[ý‰oˆ®5ø!íëóta0w!Éß- вG\ –ûÙóÔr`gÐ[” îzNœ«?¶²æüpú͹JZ¸WÞaó­’ˆEv#¼_l”d}_8¶ä•qÜw?%°‹}Û‰pVOgpøÇÍ,ÍŸÚXp•›!´¶–\ ¬¨Á¨Ágh’7vlJå|†“Ò]ÕÂuEX*D:PíÂ펜~º†’A Ø*™}àìüà|û ÖÝìtÑetR„ÏFó8\W,wsyn?\ÑÙˆôyB†ýìê ›©HÚ¨˜³GÄ5C^ý*â=Â7²0b{€0’+•ID¡‡½UaÃfO÷†ã¦•y*éR¹J@Ða]!e[œêÀIG#ÖåÏq¤¥’ÁY¿‚D`ûð³¹ÑÂaôŽpã)¸–êp㻉ÛÍZ`ìQ¬Ìžq¯=(?Opöp;¢[øÅ ¸²6G?ÃZqtÎaGÆóR»­ó#€ô„Óá¯n|»áú#‰—®Üº—¸Ÿ!Qrاwâpq„5¤NEn,#Æ·À?B,"J·ªöG,P<ÑÓÚÐí*øÌÌÈ›rX©ÃÌÄ©Çeç7 LÁ¬WE<8ètyæÕˆäŒá*ha‰dò–Z¤¡J(„ìg`8Ên’ÐõEwÝF0ݼŽìËŒSëß.•„9¼Žôž@8Ïô„¹XçÅÁ†OÇ"Q ñ¨ãòÙÃá”G @§§“c·—8…ƒ¿»'ÏUªÆ ¨ï™œ8Äá&ð)ÁQ¼ª4{ë%\•ó·Ã¾àüÐé”~fµG;Ž zü3ÇdŸq–…pèG;7“A ™Œîõ>#‚D¤Táp—ê\‘ò'G|Åø°=sF†¡èË£7ÿ MÖ©aò;ÃU†Í´8À˜pWàwó~Æç‰ð3ÍøQƒYçÓcX_pxÁfó™šήáIkãÚºÐäþÍr#ÑóˆüFw‰h؃íò냩^PåðŒÇ\&'ô4Ý6"m>SeÆÖ‚aQŠ !”{0“Ÿñ+ùÊè™›pår»0]}ž´DŽm€Î39OˆñQQ Jì/Š9ˆ÷qHáA6¢gœGF´}xJ†ì$à÷LN™ü¼`²\è/ÿˆs¯²˜gt^ë#Ú3/óD‹ß¬±bÎ8¢e+føª±Ù+æÓSŸÐ! Ñ31Ox¸QfÀ›x^ÖÓU;y#è…:8S`Ã#ÖÌóHçqôìŒç¤âÈDÔQç”àv¡ö1ØrE*¢¦Õù+Bs<¨8í‹TDÏäD ÿÄÂy¢ÞÅ‚ ç‰ëµ(‹bo(+<À®hAÎù‘Šè>yÝÊ’;–Ίp|N#QGK©¯cÆÒù”ÜYKç‰ 1À#Ñij*rØTDutª™ˆ:XägLDxøQr±N‰µóDxb5\cdŸˆNV —‡¢$&ÊSkç‰Dl~Cø[i%®óŽÅóùÍÁWɈïIÍŽX=Ù=6;cù|Jt˜¹ˆFç=ÅüC."4x–/"Ñu¤ý_× è©¤¢eøv<­*?Í l|^,‰óÈHGÔnv™—j±‚Æ¥Øn¿8G-íD6¢˜£U2‘(æèó%ç¨@6¢˜¤Ï·¯ðJóâ$…E[ž±‚Æåðƒº‡¸Ãq)¨Ç½ñM5V§Û~ˆÄØâ5ÈÉù‚§à§/²òlDµóJqèÙˆb®6‰Ú‘(æj“ibd#Š¹Ú”ÝÙˆ8W;ía"Ñ*ø¶³crªÚ©0òÅTí DpU&¯9qÒÎAÅTuä£ÈGS&eQpuÎÔ[®Û‘(jÈáéˆ8Yù|‘hð1¨ÍÖ9U›T›HFSµ)ÇH:‡Ze$Á3]=/ĉ©ÚdôɈbªvù†D2¢˜ª]ª\$#Š©j—HFsµ+è’q®VʼnŒD1WÛÁOè…œ«r=ŒŒDœ«:/¸¨ÄTÅfŠ—ÂV˜Ãñæ•úà\m NùˆÚö%ñaN¤áÒOpÛ¸®½¨Ëýg¬ÓþÌXw%ënïûÖ5Úm\ç*‹ëÄF×¹ávÚ]%Øå3ÁnxË’`—{²D»L½f²«Þd%Ý=ãÅ%¤;ˆ<ʪc¾;«àÝÜS%àuaНz3ž|WŒÉ¼ç3;^„‡ VÎZDÄk–ó“ðJr£¯çf. /·K&¼wßáÝÈuÇ:B¼[¡rð20ƒï6³‹ïîè#KÈw÷-Ó#ÑÝ=lt.¸C(]1,D—„<°º¶Ô¢¼ø E%XŸF[$IÊC¬D˜0Íp«/Òƒ‹–@¤‡ßðž…z#ü| ND=À†ž‚P/rŸV•ÄâŽ^;é5wÔƒ£—€_¨YZÉÝB½Þ:wÔÉ¢:D=´# "êtLƒD=äm=Ɔzˆ_bö#ëáÀoB=6è‰ õ|xÅqd=´«*D=œhú õp%Hˆõ`Í¡'ØC5C֋®¤{ëEÁ²Ͳ„¬‡ÍuÁ:Èûë…%‰à¬§,ü`öPSçi>< 2’øp!#³¿ ï.ÄÀWHKéÈ0’¾iÝм‡ãMlñÞEv±„º†—ëÍSyŒzˆ0Ãý#Qéo9 Œzó0‰ôÐ(×T“~Tô#’^$Ä-ì I que‚Úå^œ‡v9EÌyqi‚9ræ<\(>ÍÆ¼håfb^T4b^ô÷VI¬¢ˆ«S…‹ÁyñäÔ=r^À óàf©+“ò"XOvÀ[Ë€‡q›gÀ‹ éü‘ÏÕiTIx¸öñ"<&´—†·Ú1á­«›ðV—Íx8¡“ú&ÈÛJDy(™/ÊcôQ3^éÞsòð ä] òŠ÷tf¼’É2‰x«‚/ x%½UÅw«ñ.ú)›[âÝ^B¼C‰ö¾Â;”‰wQbOéÀ»ø•üpˆw(±í6>­ñ·Ì²ciZˆvñ·ívceBIqøš‹´Û06V¦¨!³P,Lø[ü*°CÉK¼‹›$ÆÒˆIvQGæµ$»½„d‡"²R$ÚÝt×ïîLG/´Û ˆvQ0võ­ð- íÂÐýÚÑn»´ÐnkFl·—îövî$á ìö°Û[ ØíUvQ ²‹¡ÝÞ[²ÝÖŽØn;aÛmWÛíuw{ÂÝzxb»ýRd»­;b»í&Äv{ÃÁvzT⺸ A/°nû›Tw—ü¼ ëbl;Öíuˆu(á^Á\·—ëâWE%7gçj‡\×"l‘ëö*亨R?Öíý#ÖÅMñÛ(¬Û~DªÛ ¦ÖÏì¨n»4©.néEuÛ¥Iuûoˆu{»ÄºíÉë¢×BqÝÞÁ..õ»mÎ ì¶ûØEÉ®ãåû6×­+ìVo v(i»Š‡3á%µ’Ãî¶ßîâ¶¹É#Ýí?!ÝE³·xë'êCIwÑìÇb»h•d±ÝzK†»|׆»õä wùœ wÛo®áééß­œy!ÁÝ^Ò´z6­6†»xº}ƒ»íJwñ'îÖ€1ÝíUf{ORãÝÖañ]N.ãÝ/Æ»ýGåò5ºÕã5GMwëwÛ«ÝíÝëÓsT£Lx·fŠñnkx^ž¤nfNOR•ï¶þ ðö*×¥Iê*×ÌIÊI ÂÛTkNÒ±3Þ^§å2ª Æ[Kˆ·7CÆ{•ä:ªÍîIª×"ÆÛKÎÓ“4K†g)›âíUJùmû,šð¶ŸÔñÛû2­{Žê'½xŠê'÷é)ªÇ"¾ÛƼøn/™Å“T%â»í¹ˆï¶q%¾Ûuå2ªW ÂÛëðövjó<õµZñ<ÕÌ%áÅ—ç%àí%·SŽØè·ø(øÏ±í\w\;Ø]iK)®+%¶+×¥ú»R“ÑŠ×%YÍu‰¾šæº²D¹–ËÒY_ÂÜRûK¸Û~5rY21Z¸kÞ§pgbLáÎ_þ%ÜU­\©Ûå=ìJÍ슽‡Ìu[W%[~™ê’UÖ¡¤º’V¦ºR?SÝö#QÝö+ëvÓ[¾Ôí|Ò°,3«5ÃÔíºõ‡év÷\¦š\™0ÔD‚b:øÞ¿,3ïˆÔ,©NÚ]Æ\ÖÁ›îÚB1Ü/®›%í;išyø&ÉnÙ\Ù8óX)«$ÝÝ_Hwi¯)éîH ÐÒÝéÞ¤tçàÊ–íç7•l·ØoÉv¾Že» ,gÙn–R¶»ö‡¢Îþ$¦I´ƒríÈ] „ÿÜË03¯„r!Ú¡\f—Rí°ÇT€Šv§¿7)ÚÁˆºîh‡åkh‡¨Ýú‘T»+aĪ]ÔZµÃ:)ãS©vˆÊ¹fÙ®XÀ°jU;|@v³ÌQÒÀѲÝ5Òt“²]:ÉZµ+ÍÒE»âJÖìÊj¡4» wnÍ$âQ³ƒ/òK³ËŸX²CúÙã%ÙUh[±³qS*v°±I±ÃP/Å.’ä‰ó¨ØaóÈï‚»š¶ñVìjN4)v8Ë›/Å®Ì4פbW¦Þ‚]¶¶`Ws%±` céuéUo½.2…½ô:˜BÈÌRzÄÙ{7Î Iš6ŸÒëjÚí[¯£{·µ:HÀo­F¾c‡:´¡ãku-ÅO‹uÕúPŠuˆ=~l–™Ãvb©ÕUG¨”T¶6iuíøu¸2},Õ¡s}×êPÂAh­®]©ïéЮ¥E"]4£+éPGB1ÝpD3]X²Ÿ;Ó-ußL·ŒÛ uhØôE¨C¥ÇÓ-;C]¼Æ¶AÝh²ÃŒÇNeÿI C‰d(¬ ¸ÏÒ0Û‘?rψt'€üC¤‹*B/"݈¹$y.–ÎHÓ¡:„:ˆ½ÈtxN_âß¶’’¬`ÿt¿šrÉ֔ж¦²d5ѤÛë¾]²šrÑjj•lMaÓY^M¹dkJE[SYòÏŽ¹† víyt+æZý*æÚÙ>ýçç˜kOiûQ]º2ÐW;¼þ }õyøb` ^•ÜÔ §æ¦öpjnjÕRS{%7µÂ©¹©=œš›ZµÔÔ^)›ÊpjÙÔN-›ÊZnj«”Me8µlj §–Me-7õ7b®¤3}ÖÓÿùb®ýÌ7ò«OÑ÷_Äßÿà«¶×újßÖÏÇ\Cz‹~•=æšB¥Ý*mdů"®}º­/z ß1×þ^ˆ3Ä>}xé¿«gÏ×joúßW1BœýöPÎxb®8gןÇ9{"îF˜³‘³˜®íÔSËÇí3b˜WGúÇÒÙ+/º¿ó ?2õ'º'—êÙoŸ¬Æ—¤ï?{Ä£ RĬ—±^] ,"†ñL?’2CJ>ÁHüRÈXý']•>ç)!¥ JlÔ#1ΕãH?.Õy~œÞž¥ŸA?yçÏ?¸Šª<_Dì†+‚f×8"§I}ŒË5Yge'£õ(i9ânibDPö3‚hQ9ˆ ñO퉧Á‡×ïˆb4»lJ";aëÙ³†»/Y©ÝûvÀÝÁ‚8£žÕêžg™¡Õ‰šSÁ‡ŠCGqÑ+à ˆøûü̓§ÏEÚJjN<Oäã¥ÜÜIFŒ*>(¤`=)Ž]J„‡ˆ3zfê.w„µ‰zñç¸x–|ðcò ùT2Êk¬¢øHqÌPbE|$¥m,ˆâ±gÊÅØL¶I|¦hËT0;Λ]ãô "œZ®ƒÏTåÜ)ajQò…÷bôd8>–ȉZù«ƒýÁÚdH>nø¸…T™lîß ²SX0«"Ðf ü &æâß“ñgº²J—ðü<©&ÄÙrÁ˜ø3·»‡üIMZF@GäOšq~/³ªÈŸñgœL&ò' \ü¾Ü›vr'ÒM• ÆŸ™Ϲʼ;ãÏÀ_Ÿ-ˆ;q"éú쨣Dò‘A©…–¡kU4ChàÃyÆ"ƒR“ØÂ*L™už§¬"…ŽrNåTˆ J#ªTD ƒµD¬g»­:€z\¹'´Ÿ©üÔ‘D©wª8¿ “e6$J8¡BÕ‹íŒXN)xðZ8CCçÅQ\$QŠ#ªSùÜ#‰R AÒtdQEu5Q]:n!Ž×"R“ŽÁq…4J˜«8Å/f¤Q¢ê3u H£4BRB!¤QйŠèƒ-÷Âã©›çU‰™âtjx˜#R8pè øîøöî[‚†Y> ÷ØYQÔheeÖƒ••Þ¨X/hYFÖ ÿ n×Åz÷¬qb=˜ ˆ>{Èf®$ìºé.g؃Y òL{`úrŠöàÒ¡Ñ#ÚƒåAQ3{ðÆ8vÚ gg„{Ý”xž|½pU4÷À&¢gáÞˆÑÎK“÷"[¦€o\Ž’eàïH)>\JoRÀ7.Y™÷`¤¦Á*àƒƒÃx¢•«Ç$¾ø#_x#lÀ‡¿iGmà[¦ûA|hBÌHàCP5§ˆù–©¶™/Ì»ùÄ|a[ÎÑ+æ[±f¾0µ¬;ó…qsß™/ ŽðFä=Ç™¦•:ãòÉdþÅ&¾Ñ{öÄ{>}aH|‘Ž_^ª0bŽˆoĨPA,Lø‘ˆot»0ùÆíèF¾qçTòáÀ…Fă}uD|hFƒHÄ—, âC‰F‘ˆw{I | nç=ÒøÈ{0c¹÷`:Ó„n{##w{c*­šh/þ¾É[¤=XÛÄÐ4ìE¤¸&´‹5t8%¥YAÉø"ÍzèŠÄQ±^DU3ÙÅŠwÃý„Pqè¹éáu^;èMá!oÀ°àþXŒ}çTŒ‡^tG0ãá ‹£EŒ7¢ÕÔ‡øJþQ@^俣ä!pAŒë#>!^\„Ø"ÄCd7ž±ò—JÏU‡Ëtq) s.šòð+žZ›òÐÿŠ”‡pbœ÷¦<ibyxöM†<„ùrļ*Å. òÐ ÍðMyè ? ¢¼yÉkÀ‡‚"P È›—⌘ñ`KËO/âPñ‰ñp¸Hsz3ùÉ4ãasI2ãEgªJbEH.½}1Ú‰#H#Î$ù)3ãÍ ˆcÆ‹“L5CÈÃ¥4fyÓñTÌx¸ö¯ãÁMXŒIx d<Ä·:Yƒˆ‡(cºŽG¦gݽÓm ñpi}„xø Õ¾#ÞLo[#ÞtX^ä“÷&ä¤ ëfÆÆמk¨@BÞ‘2Þ\à-ªƒåø¹CðH_$Óå®ÂH~Gí$ãòÌY2ÄZþŠH4áHÑAÕÝ ébaépmÝpªxpï§ÒgÉ¥)È‘éfø_í*Þthz!–f'‘nfÅñ°ãúø¶‰x§œ+LtHÈ£ˆï;Æ‹¾ "ºXû( éfÆÉX"ÎX)ýYÄ™ðWD:\]_{!2~_/%¢Ûñм,ïšZÑEuø†ÿÕ!¿oÔT}(›ˆ‡nj{o/’®ü,â9¿KŠxÈŒÄC`ݜ͸H®Cê)B²¹nvÇûO ïp|úÔðŽrsP¤†‡[‘Ò&´C&nw3—:ó]N”ðR3N /SwXÂCÒ")vÒð ·sw#¼Cdö ï þŠß áA*§te /’ÚP_\7Hñ"»JÈw·Õ$ãò:ðe[ÄÃKá-ZÄCIS E¼ãà¦&5¼#…ã‘ÊxçSÈ”ð0 øÞ,á^gSÃCîxžHËlSÝ ~šî†×±”ðàÂQe ïˆ7³è.>|Vð|êڼȨŗdºK‹¢TðNáEwq—|OVð"™ÔÇ¢;æ¹zÑÝ3—E¨‚»yHÑ“~‡¼-’¬ßÁ?òPIèw¸%j@ÖçÅvÍ„»™poý&”p­ßavÍ—~‡Ï“Õ:êwÇ9Mn‚»iÕl7½íJù.ò)},¶ c [Vïp%)sRJºƒÍµ6 æKº ×"Ö‘t—f)ÝGjj”î2uWJw1èyqÿ¢° Iw°9¹v¼{Jø#µ;8ºªYiw°xiÂ9-§‡ÜÚ–Sj³Öî»Æ§v—¢R»Ã—]ºœ´;,j"1iwë›aí'‹ðâê:-Þŵ>’ðâa©†´»È…Æ*$¼éÐ_IxÓñ·S»ÃZÂkíßAÎÓÔî®xlÿlÃ:\eǺjKQ]ÉiS–êK%ĺê vðí/°ÃZ ¹.øä¥ÙU'I°SVÇĺ*€#ÒU…ºJ¢«iVh¤«:NZ6š>ŒIÍ<‹6Óm%ërC”b7áÔê|D•Z]‘¬žR]f½M¢{ÞjÝ¥:è3†&1Ýá“‹d:$—À釕I¤Ãá'«‘g”±Y3ÑA9_H—³’éÂÛ‰%‚:g]K¦+#íNÉtƒghšflŸyúéêÊö‚ºj,7ÓUÛ:éðeäŽÚÖ™g$ÏÑ8³9»fgöK¯Ì¶™K¡L¢Ë±a¦ãÓB­òê w·$×Ý–rÝð@Ôæf“ê†÷«R놶z©Ö ‡LOµ.•€TëîùÆ:H&‚_«u}&´I­›ÎrœjÝÔ9Šu·# ¦Xw×$©Åu–â¤ÖÝŰ$µn8ÿRªuãø„u ŽcëžÞ/¨;REÔa]Ø3CA¸–V‡M³ TbÝp ëว”X¯›T$±n¾A‹uOU£Åº)÷öÔê§¾´:Ü «H«›êQ«› UžRBøq¨Z«Žì–ZÝpà¹ÔêÆL>¤V7Ä2)ÕMoI©›Žv’JÝÌó-+uÓ·©ÔÍ<—1×aÙd»ÂºL^“JÝ´¥®…ºé³A]äÚ!cŠé°·ã¼2ÓùÉ´N7KÜIÓéšÂÝ å´Sü&Ñ×'Ë‘$6\(}$ºÃYLLt+¯L*uÏ“²Ä&¥/Vòž¥:› Y©›Gvf)u¯R©;³Ku—•€ÔêRçI±®X¡1Ñeêž$ºÃQøR±;gRŸ;›Y°k©ÆI°svŸÔëNëqâ¹Ã¼¨×¶çÙ;K~â¹C®ð©×6ÉXzÝHÍzÝù è ×o½î°YÊÒë Öë€N׋èŽ%½‰èǵIÁ+|ß‘nÝ„õºcu‡zÝá°@‰tKì$ÒEJñº#]|©™I°ËüRF:Œ< ìŽË–œ":ÌÑë¥×-Õ9éuG3ŠI®;ì«` Ã¨Ÿæ·Ó³”/Û@·4_Ý‘€l¹îH%SL·>‚bº•ãËL‡kkГéâ¶%½‰é0çÛK°;lº‘‚Ýao¥ìrÌ[¯;’Et§˜Ô@‡Mì:¥ÖáÝÌ—Z‡¾°U‰uG·Ðc±±ênŽRñx‰uÙkuPÍéb¥â°Òej3Ýöi²^wX?¢ÃGQ#Ó‚×e*zkÍ—ˆßc÷vj]2Ú¡eÔ›B]¤›Û»0qà»Эôm:”ˆÖt¹—0Ï¡`¾»>6¦»,™n8^B]GN¨‹,€.AÝpZÛĺ©#ˆ$»åg&´‹T¢òÑ#Úa¦íØÌl¹;Ç®×mnd;DBãÉ»Ðn\j”ë.ÇŒN¹®äæÝrÝÞ‚†»° |Ñ] LºÃ (/Åî¾²ŽðîÖ,MºC0Éþ¢»a]Êt7¬€'ÝÝgjz¢»g‡b%Pt7¦0ñ'À›bŸú&Ü›–פ»øfóoÂÝÊŒf¸[©õ’î†C»ïb[©:VìFšM¶\šì 'ÅîX–¡Rìp:Â*ä»\½Òõ»)’ìN[-ß;o—hWÓR¢mhì{‹Ÿ—j‹9ÒQµK#b‹vÅQv¼ÃWÜŽuMgð®b®³Æ.”ÓA#¤¿{WíÂí§ît÷”5ß–j—{ùÞÕ°ë]±7êr½k¿;ÝÅ›Ÿ¬c×»¤ôt½Ãýø¶‰vC'ÿK´[ ÛóÎ)n—ç])Æ7{Þ ½ÞåxwڥϚ¬6vÂ ÑæÚ4»ßŽðVC;Þ… Å6kvw:ôY³»} žšœ±)ýÙñî¾íT'ÑŒz툇›úø¶)v·L–bç¨ÍK±»ä·˜^w‘½þåu§®]îŽX•>¾mzØ…êœõºûñméuÍÚJêuϰ½7¼ IוË&%Û)×Áý—MX®ÃÉ?‘Qx—îK¯k Í•NwáÙJ¥M^wxÚÇnIwÓ—×>š’Ñ,ØU»\¥bW§t49Ý ïž›¨¿©@‚rÇóG)ØU{Ô¥`—ý“`WËo/¼{†æ”Ü%§;<<‰oVìpfýñmì,¥¤bg§ß¥Ø!å8e>ùÜ¡3Cvô¹‹O)ëX±ëå“Ï](vl9»‹>X©Ø!¬Jès:0$§;Œô—ÏÝѸniv¸âÆwñVèT–š]X ~|[š]Õ»µË]®K²ë »¶Ivßö%ÙÊw¾$»êÑg—;é£A ]îÐò[²{ÆJ{kvÕyjv!||Û4;Üŵ”íäçwÄÏR¶;4ÐS¶»†Å3dÎ#‘M²¾î»Qf|`Yà©}¾U;¨4oÕî™3ü8-ÕN¾¦)ÚU…âÛD;¹*-Ñf}ßvÍÎFѩٕ[ï25»#u½Ôì†å¬ÙSujvíþ¬Ù!õòÇ·M²«~šÖìÊ)>NÍ.²]~|[š‰ÒßîhZ<—f¹ß6ÍΆ2i–‰8u ©”qΞ­ð|GÔéÍóÞbø¸dWöãß­Z®ó÷âœ}…,YaÀ>_âß¶’¬¥Ê«)—lM©hk*KVSa¡Ï×}»d5å¢ÕÔ*Ùšº¡{5å’­)mMeÉ?;ÎY1<î«8gçã‘}ŽsöEÀ²Jœ³¯ÄÙ|7õyøb`2ùÉ^Ëm­fnkaæ¶V-·µ×r[+†™ÛÚƒ˜¹­UËmíµ²­ b–mmQ̲­¬•mmµ²­Œb–mma̲­¬•mý`gïˆC˜¯ƒ]ìì»—þu°³UûììGõ>;ûz¬}ììg>”_}¾ÿ,þþŸ¶½ÖW#ùû¶~>ØY šš{°³ýõ_px”?‹Qvf°³ãsسç_W½¿öìOaê·¿ö Ç6׳:öìy³ÿeýçʘcûì©üÿý Kš9æö_Û?ÿ³£ m…ÿúÃéðÇÑZA†9~äàPãÉNWx§µ‚óµ;üÜyÿ”DŒ_¸µó´¯Õ#ôRì8¨ÛÃcáR|ÙiáÙõXy`ÔCá)‰Ðý÷ås®çÍ„Nhý Nã5\ÔcÙjGlÌÝǃۧd0iv¹Fx¾øJ0Ñd> :µŠE&´¿ÙîL¹1³•gësñ(:v”Ï.µÐ-DøS‹x³èü”ŒÈºÑ}P×Oßà,î:%"|ÀŸã`˜]áêMÑà)qÐüQ cº85Šþ¶ þØ”ñž=sXà…?¶~tŒÃ¹à[+n4‰jm" ÷8«n²š-3>%LÇ“ÑÖÛv;C®‹~!Ím”ƒn!§4ݧä¦cHáî·õAxÂgZí‚„©+èÅvœ°)!ÿ¾C\¹œÊ¯õ;”¯!Lh^%ÁÕ5>¯ûpþ„.«ð6¡¦÷<¶gÌU>í>¯Vž.òÀ»E°¿Étgñ¬1f/:^swÜ"#e8º5[ã<&s5 -úYWµŠÓŒyÜH¯ô ÑyJ»ï“ñÝtnÓ+¯ž[–©çÇY`${ªQ0#†ÐJäÓÝ%"G;,³®kËVÔ£"¢„¢Iƒ¸p–¸šö4(H×Ö3¤E– óD¹!¢]tèæ=Á!|Væíao^-D'½ED¯Ì^äFä;Š 2W¤ƒ’ã‡3D þ6–(Ôù+Ï(Ÿ6ž7†ÊÓHƱÎAvªÏ-ŽòåçÎç=‘ùbâ$v^t…Yœø¢ÃËOnî—Jæfdºø£Þbn6YÖ6Ÿsåìj°…ÆÌĉ¸ &f·®Ñ`†Ùô b~?S•‰RG(‘ê–ÔaE<é¿îŸÀöÓBªEă$Ô÷°·¦÷ºý“S% Z˜þËó»ÈCp…Õu‚‡_s”Oû-Ưøíy>,aþ²R:uD%«´~ãñ`é¹…ŽtI˜ž$àtmÒûÿŽ‚ë¢¯¿^Q?#0ϸ«ÿ.‘t`Üé:rôh‚_ÓÙ’øŠ.Ób·-Jýd=ÜïUpÇÌç0ödÄâ¹,ɺäÇóæž46 }×FD%ÌÎîÌÄ="ÑhBGGôœ“>r4éˆubtÄöÁì¼i¦Ú#SÒ ÙŽ«kLI‘y¾Ù‘*©ÆQýë‘)©1 R%•x T½zdJ¢ àP»#–ÎPÿÔÝYèêoßbÃmØ ,ˆµ3dz^»œ±vFœJ*D¶$Ʋ¤iGÆ$LÐÛîF=2&)¶G2&a†ÆY7KZ¬ž¸ ~z;Ò&!¡â­`=²&…äÝ\8‡mWzäLš¡Ñs‡Ó#gR‹F—PçW·GÆ$Vàç²#cÒäƒâV¥GÆ$†M …FGƤÁUTR¸xN%(êµrí„;‡P$Lºi«ÀéWWÏ;f$LâÃä¼A¾$djÃou|IcŸÈ—TËþ#« ¾€¢;pt½€H—´ÛžöH—D·óGW¬Ÿfœ£‘-‰5¸tw¤KêûhˆlI=žŒÞkc€:Ô¡}NlI}sìëH—“T1ñzdKºãMºáÁ%4 Ø Ó³„¼u«„KhD_Œ_E¶$ *öÙ’NŠÞ\OzdK¢1/¿¥ýâzK¤í‘,in1r%Uº­² ÅjsÚ™’ZhõP!Q ™™’øE¤BG¦¤ëÜB¦ôÈ”Äð'zšÙžû—)2%i¡å¾O.¢·Ï {O¾ã³££@ìùcŽzï‘*‰s”Ïfí1E/¼Gª$Æ6¡ÕT‡?öÍ:ê2£6ñs"2%ñiRï‘*IUØîà2:ì\ÜïÉñ¬W=˜f„wõ` —Q|Öã¥Eš$~Í|ÚyiuÄi’8ð4Gá::œ”ž‡&7Ǹ.Þ¸Ž&[ ã{¼nž«ü\ܳî°Òìp×½J¸»½Û7Ü¥3jÂÝ9´÷2Û6"[lçx‹íróh¶FÌv—–åd»Ë¹C“ížO xhwyW‘hW’h„vEÉí’ìŠÞ^‚]é J"» k–hg'Ž$»ÚøìªÇg‚Ôþ"»&½»¦qŸ\×’U vØ«„`AËÔ.ÁP©ç-°»oÙ)‹ë0úù)7ØÁNj»ˆ/?×1™™ÁÆ‚º{8¡î‹^ƒTwCzQ ©˜ê_‘ênç»2Ö!Ö— c]˜b±@\§;ÔG²£ îÈóCÝásC6´†º£}‚ºôZ1Ô=MPw:V’©Î]BÝY}a1]Dif«‚ºS_­„ºÓ GBÝå`Iu§øËÑU’ßDt—v$ÑÁîŒ'&ºËäItåZ%\Š2Ë%Ñ]wVÑ•šŒG¤+Ú'Ñ™ôèŠ]pèŠC$Ñ’'ÕU'ÔÕÅD‚ºˆmÿ±1]µa\2ˆ½Ätµ%ŠéŠOWÌtÕ†\ÉtU!òéªÃÐ'ÓÕÎmY2]µ7ª¡®) T2]sDw2]Í]›™®é ‘.´a’.2(’¢Ät8Xà¦ÂP÷ N_GP×äSžP‡”HPP».ýÈPgЄºV³DPת{,¦k%RL׺6FºfGŒdº¾ÀIP×ìÉ`ªëŽiX×l†X—„ŸX×íÞ—X—ŒëzÒ‹¹®Ëý0¹®Ûv1¹nãTq]'|™éêg¦ËFtÝ-é”ü|1]Ï Ž©®;qR]÷Y”©®;-zRÝ},ˆ ªƒÓ¼ªˆê¨šêz7|™ên¯ûIuyÜ™Xw;ob]¤ ~a]w^ñ…u ýŒur§]Twi¡Lªë2›^PçsßEuŠý“`¶:dCÝ:0ØÝö%ØáxïÉ`·žžÁî¾>ƒÝÓFp×%¯ëî|ÿæºÛAÏ’ëpGãÍuÕ@f¬ó'ÃXwç¡Ê†u<²ZXwzoš\—[ýä:G¨I®ëÞS$×õ‘œD°Ã!ÿ×ݶ´7×Ý>PN®»/á°®'këznÒu] ëºÝëz²ubÝ‘¼(¬ëÉ3ƺ~ûRƺž8k¬Ë”Éuݛ̻îxfIvèϵ£]×–$Ñ®·¼6Ñ®“ü„u½e“º®lIuëž“êòÓjª[çp¦:|[_¢ºnS¸¤:D‡áP4Õ‘tën¤ë9€Œtø@¿ˆ®Ù.?‘®Í„G!]ÄÕâ¯Ät-G]0]óP0Òáßç éºMá“éºã{$Ó­ÃH3]¿’×ÄtˆNÊÛ6Ó­ÕÃL‡ïzýØ‘N‰ÄÿBij¤º+Ž6¨+†ý„º&oÃdºv§f&¦ëW’– ®+\g2]·CA2r$–—^w{iO¦»í}“Pw;ÐmB¾j÷Nu]£ ¡îv*C]ø¿ô:ØlªŠ°nœ dº1Ó‰uÃ>ÚÉus¡ÁcFÏF`‡LõÜ™Šë@.®ƒL&ÜØÅ^»ì`ùJr§»Ü`¥bw]ÙŽ»ËîšVì©·`É®ûˆ–’]óÂ’]nL­Ø]U§±K²»L”–ìòh25»<NÍ®;²Vjv­.ÞãúT¾&U»Ü´ ïÂSPâáãu¼oÔψw§†kÆë¹ß6ã5ÿ3ä!Ƙ!ož5Á7cûb…švJÊ˳ÈÄ<NcÇ<8d¸rˆD°HÌ‹±j†˜¼/ínÊIÏ>ø½é¤eÉyÓ;˜ä¼t¡6ç…c(ǧAoäó4è͜޽™ª­Io–„L¢Þ©>õàC¢fÔKgL£ÞòNÖ›Û½D=œÒ»~Çõc¡Þrp1ê¡1 zD½ðˆ“‘õÂQñVI¬SðÈá·P¬‡†­’õ&·D‹õàT¤OÖ‹8Ål„¬‡I `½åÁ“¬1¼TrÓ½Ø~· {öÌNÖ›yè,Öƒo´NmÅzüwg½¸Áñb=;¾'êEªþH¨7ì kÔÃ\r²Þò2ëEpböO°nÀÜ”öž›º_^†BëŬ}±ž÷¹¡^Ä®;ê…¿w{¡<1Ú õÖÑ¿P/bÿÎõ¯o¼4<ëuG=ħí’ëõसPîoVýÈz13Ø.Qß~ó!Q7é+E,]_õðaÑP¨7¯Ü| õ"¥ÝØ5¼yúÄC¬ÃUFÖC8]áŠXoÈ4ëaĘÛ{¸ø¹Ã^ÄÉn»†‡K¹„½S̰‡xÌÒ{¸O݃`/‘ ¹N­¥Év—Ò#q°‡›Gö"þ/Ǽ`/Ní!*]°uÉ-‚=”ÄÇÕ°7«ó”öbà…ÈzÓi:z3-ÛŒzcðV, “ÞtŒ%ƒÞŠšmЋŸu½ø^»ó7æEÔ—H¤ËÁNz3<¯w/ÀlwrŽÞÉ¡CëèmmP°7íš°7óƒ,ØÃTçÉ„XAçb½øÚª²^,oñ’„{áÆÚ¤éq=ôѸ‡†}mòÞŠooÞëÕóïe ã 8›îÉÝ£>1½)»â…{{Ÿ žpo[…{¸°F¯p/.| ‰{Ø•#I{1bîöðÅ>ÕŒ ÂOE¾ý“èg;â×Ë*³xãhÄ« Ó•ˆW*+¯9éh"^ë> 7ã5IˉxÍÑ,ñú•ø&Äë¹W3âõ´†3âuy@%áÕÏ&™½ú„݈çÐ ‰x@ ±¤¯'ñp´y½¯ÓfÓ™y™4ȼÓÚrd깤EæLL´E¦]Ó—E¦ã,“L+[î†ãó¤p7Ó„ÑÂݔ˧…»él)ÜÍáÇÂÝÔ?éîHS7ãÝáØ¯‰w‡í"ï"×í ïNÅHº;ìŠèþ¹ÒâDw‘ŽŒÝe,ƒTïN{–&Þ/´;¨.ÑîJYÊh‡ñy¿l2‹#ð¦~WRz£|WÆ=å»Ò Ü"»Ëq„’ìRË2Ø(Jý®8ÆO x™™'¼ÍÌTÜ%=B»šV¾F»šñãQZ›à®6‹mb»º *¥áÕ<`1Û•<0Û9Œ«Ñ.ƒ&Úå©È{!x‹x¨ûEv-_ŠE¼fÓYƒ]+æ"³¾.»Ì3Í'm—©(yË,óLŠ“„W§¯³$¼.MOV™g€Ú*óô•m•éØá)áµÔÑ-ái±\ÞbÛQ¶ÄHK³5èÒð®ü‰5¼j"5aÖüú’ð´Œ-¯$QÁëÞÅ¥€W­šêzOÛM x¹ëLÁ—~çdÐK¿Ë Y¾“éÉRðraO¯¥h& ¯4…”„·Æƒ%¼æÔïKÂSÄ’¥àåѹ<›rJ¿[ö¶ÒïÖc±~×môjù¦&o£Ì^Î,ß-FÉwÝ«KÊwë®-ßAÏ{I¾ëÉM–ïºW¾ÔïzòDêw÷êÂ~¹½ô»® n©ßõT¬ß-Ñ4õ»´l ý.“I,ý®¤BfýÎÁH—~7W‰¼Ú,à-ÍÞ鳘ðœ@lð,éYÁkš©à9sÅRðŽ´ï´‚§X.»a¦Â"¡Ôé"h”Œ,m˜¹D> x&Ì4Ì̇µ 39|Ó.S1—YfJªi–™fÅÖïÂb‰–€wÏv™›©¼áýDzËtðùe—épkË.SAS–YæHÛGéw™›,±îpnÅĺCyC“êò„$©.í¶Eu‘‘ÕWöNXwôäRcìÈŒuqpü²ÌÄbjËGcÝô*c®;–”¶¸Î¿×IS v6 Ioæ82Ø^÷SÈNc`ç¸rÉu§c&Ø= NAvy¾`°C$‚û vÉð»uüi°;¼›O°Ë=ªÁ.Ž…£s vÅg$»3Ou¬ãeðÛ¿ mQ•÷’ÇQ yŠÛº„¼”RÈ“TÊx©·t<t¥Œçœ‹KÆË­i2Þ\DGÆ‹M”„=2^Hµ,ä]¶ŸKÈÓ+7ãÝÎB·d¼Óþ}B¼;w™©â-g8!–¯ãe9Ó•'U<™‹¤ˆ·Œì¬â=5Å–ñ.yǤŠ|ºv¿»ˆ­þYÅË+IÄ-%E‰xÓZ!/ÎÇ®ááL¬^¿õæ y½'g òzšÂòîäeCLYØýÔð–÷ž(Ï¦Ø yéù’w·ôçäÝŽCœ7¦/!ïÙekxaž ‡„18ÍyÃF=Éyikœ7l™bÐyS½‘z—@/Å‹]³(Òv°JÒöø4èT· z£§Ñ¨@/¶[/ÐÃX[k"² zc|½\“’ôrMJÒË0uKÅ;ÒkO¤7”æ!E¼eóiïÌÞHÄÓž¤‡CC©5¼Ó*¤@o¦šž6 ¯¼]ðV‘^.-‰zÓ!ßõ† õF~™õ ëÌë9v²Þ<ÒmO¬76ù.Ö/~j zÓ®ÁyóLO5ËwÇ2Þ¼xÔú˜å»U²ô;-`½éãNs^Æ&MΛgbõ»4QÛ<^ôò %è´Ö3è¡;²éMG«LÒóèXúÞb‚Þº’@­¿@oÚÐÁ çèî z3ÍûR¾»Rèák*ŒèÍâ ‰ô¦-¥“ô¦ Rõ¦x’õfª‰)ß¹a£ÞLÿ£Þê±Qo^o¼y%׉ô²9o:ú’ÞzÕ"½|”½™{x“Þz¸&½iµ?Iou%ýï.YôfzAô–¿ŠAo*¸fr^ÆOÎ[J²9o»¶@o–dJ/½Io &½y%AŠôòáè¥D‚ÞêAoõÅ —m˜óVçÒ/o)=ðo¶ zù¹0çáìÚ]<Íú²Ô#M7e“¶‡Æ¼ÌÖœœç°Ä óÆ?­¡ã;ÌK]Èx^Ùç-;qžòZ/Îs¶æz%/mлÓÜÓþw9ÓosÚïÊÞôªÍó6<ÝB‚ÞeL2ç5«¬ zWš\Ú/Ýë쀗p(3ÍáhóÀ{sÞ†ªvÁËÃtÁË#§tÁ;䈘xiœ¾ÙjêË´yॿÝé4ÂÛj®gžxé(g¼á#¾ôÀKJN<³ÄòÀ[¿2æ™ým®¹œ`m®9W‘µæ=#EGž'Ø\si¿©…4}ŽÓoYbÊZs(¬ÆrÀkfïÍOßÒtÀó^m9àY×Lȳíínq°EÛó¹‡RÁÎ쇿Z•\åïEA»#%Ý~,YAÂ\´¢­’$lDhçW_]²šrÑjj•lM…%Îë®Y°5Ä’­ü³Ã–AÈ+ϽnaË>wú£PdC¥­g…ïþó¼›o…8{J¯Ÿø£÷ôŒÞóýh¹Ðo¼bH}wxrز¿ê¸¥™Ì-í‘ÉÔÒª¤–ö:niÅ%sK{\2µ´*©¥½N¶”Qɲ¥-*™[ÊJni«“-eL²li‹Iæ–²’[úqËqhíâ–}ŠÖ¾ jV~.¦™ƒ•}ƒ÷£‹ý0øÙ‚•ýÄÇì÷ï>L_|»~ÿrÈ~þž}9d¿kéç•Áì{”¶*ÛãŠ}wì•좎ÍöÌö¨Xù_žE”öqnÿú]<´§ìËfN7s8ŠÙüûQÌ"‡ø³ˆý·Œbö| þJ³§úWQÌžâüŠ@8xòÛ‡ô_Ï?üþ0ŠÙÝ0^®ðG‡xº} /‹Ùw+¡\Âûœûó§äƶ9vF¬òì |ˇ¶%Ïn'BuÃÛœKÿÝž§~ÕX²È OÉÏ,ÌU€Àá-¼Ë«šÁ5¾Ä»!g(SùQí}J LFBÁ¨Ñ#ÐSP\pÀý<¶ OÁÿßÝÛ$k#Kzs­¢¦š|F‚ ˜VÑVkiÐimw ý›èáîàÉ̪¬º·ejMòˇAðÀã'B G3‚‡WÝ¿k³0¿ÁÖ·8ÞA®aÍü8Õ÷[ÀÉi7b=üÜÐáa$+ŠçÆ¶Ø 'ö©+Eܰâöù[²¸;¬t£ÏbKlS |îÙ3£KÐw¡xrsxhçã-YaÔü¸#0„Øì–·½ŸüÄ‹¸Ãs„¼ñDÔ·“®ñ'kí7M€¤êyBf÷îš=¶ÄDľÒO8£´(áMcGúzÂá$°àÁbÒHˆLý<±G%\M>Ø~®HEÂ%ôgò³†v{""¬„†öÑŸHo+!{ < ÇX£/~‡ƒ¼zsäaFDæ —á·À¦ Ox?°,ò•áÛƒ}ôž'=W¬™éüO*¡ÿ>·Ož€ÈûS¹mþödöòÖAÇyÈÂJ‹nI<0‡[²%Šç¹Ú ¿Pâyò¤S ‘ï),’#Ö`X–‚lmúÞÝÀ ó#õˆzD„§ã^ÎÛЃ^ü¦ËN¯iÅæýß°+K~{VlÑ*ôÈW¸/0<]<ω„ÇadÇø·w|¥8‹voóh‘%·|4©^A¶—Mg±nLaIˆPðö鬰!·Ã H9ò¦‚Ö‡ ÒÉ+…L(|-© Ⱦ$󈤇a;tè°;¶è@Tú>ì;ØNë1м/¤ËˆŸØûôc¯2RlºÉpÇÉ÷Yß; ·×wÚy¸'†¿; bpz 0¢‡]›rbwŒþwdè÷ý\44*λcOñÖ|K"U&|œ'ØŽn±]9Ïp®Ùn—³ó)wÎß’I7áæ×ÖΛnÂ6i|ôÂGkϺÎiFú#)çÑä?Z„g¤?Œ¦Óy\0{fò2HD)ãæ!Ï ÖÚYjF$ÑqtÖ‰ H7‡K÷¸&÷‡•Ãb"Rl>i€ž‘ÿˆ[yçE7„ˆ3Å® èXÄ[Bþ#|¢ï`ÀokFþ£U\„fä?ê%=ÛŒH‹. ªøtºôÕN¤@¢ç‹ÄZU\` ëb~~‘é.v×):m˹=1#ÒgEg@¤ë,2ïŒHO˜óë9 ,Ç3–©y7LŽ£ï"2¯ÙÚ|F¤ù©%\MCíæ >#j8%ÎÛ1aóÍ-Ì ¨šûÚÔ`P3÷''R ]Q Î)(/ê«@$XÇ+ìÔŒH4Ãç&×D $Ø\²B™‘‰mÜ>™£ÇD ­=¦‹ ¸wJVœH€ d,ˆ2˜Ö!¼té'&R8èC‰ HxšRÂ' Á¾ l¦Ø˜óèÊx­ k }5ø5E$dfp¸)V¼J=àÈ4"©º² ­¨˜ߌ$H´Sˆæ!Ò¤ µÄ)Þg5¼w>‘ ·#©ÎÈ‚ôsÛ p" L †MçM#yÌw9àOá-ã·øîÌvùzüû…éÞ¶?6èž®û>¥ûÞh=˜™ûh=Îå5ÐüoGµ©Ô¶cd« Çñ8ûÛ! N¤>zO%h~G»ãýå•ùIJámñ´­òDÚ£ øUÇT‰4ÛÀPømðTf݉Ð4-×pïuNzt®Û5@ ~oÙ±åæ 18ftIî»f˜Ìh‘~C~çQ¾Þ;<= 2Çzê/fîàCfŽ£µä‘>ÃÏ#^,W }‰hŒϙUD®—‰O) M-¬Z#–¹ø³tü‰¾àŸÈm2WȾñ{ª`F2‰c1Ê\¡úFoC{#(à †´F‘?I âÍ"x{þ+ÁÉ6³=uêž–ºÍ&6ÅÝÀvU’ØdcÛ¥E¥­ÙÒÂÀÖÜßØÂ äo›×š?™äµ6%“š×.­:’×.æÙL\»è„k˜8æ×.E^NZƒùº J´v Mì‰k—VDIkvGJZË”îIk˜¡šJHkÝÑ¥×î,i­S—LXëòÉ2«uË1ÉjÝa¼ kÝûïIkÝkƒ¤µž­5­ %¼JXëÓÜ(VÛGÕ†—ÉjíªaÑ,Lªžð)TŠb¤–Éå’ÔÆ“4'R+LjÔá v[½MP»%ž›ÓnÙQ$¦Ý2‰IJ»m2hJÃ!Ú…0¦%›ÒîZSZ"HCgPCÚs[4¤Å1.RZд`˜&\­bZè* LÃ1¼KayÈm¤48ápgB†‚§BÚó8z¡!íí3’àiPœDƒd´päá¨(FÆsà¢á­¹„h@MxB4œ¤)Fˆ†ŠEI$4LvšW…hè{YŒö× /F‹Ý€øMB‹)SÍ#¡¡„P$@ƒS‘æ|Zd7庌€†­ih{ÿ@€ö¬¼Gêå•hØdPù Üö1 E¼¿«>¯èÞ4ì1h .BÃ΄–"4ã"ZØóM^ŠŒÎU—,–Ö8kÛ&}©.Ó†´z!íY¹&¤arWFÕµ”#¤=+Wà†48°Ç[£Ekû‡Ñ9¬$£— ˆh;0b"Úá8 ‰h‡£¶™ÑžåŸ„´HùÎci‡ Á“ÑÇíHH;F˜ íxÌqd´®Ñ¢¶`´Xž±›‰ÑæáM3Úá-&3ZÂ~FHÛA i¥y‚´yÚÖy rÄ´¼H."¥a·H/A”†Q[¿(mž¶Ì4¦Eþƒ¸oaÚv_3¦¡bµX˜†Šµ$¦!^£a*ÖÓ¦EØG¶8( áBY6Oæ;¢ÅÇ)F‹,Bmž‰*b4œ$"#¢! ä! #¢²ž3¡A?×c¢Íf[D#îOK^!¶ÌôŽÄh(ù‹Ñb[Ã-öâo ÑÂÖ± ÚbÅ¢^$´íngB‹uÿa…}$ïI€†;‘Ðæ•ëk¶Ô4î‹Ð°=¦¡¡^Ž4ì²¹FãiÎ`/BÕµBC ê¸$4DÜœÐð[Í  M«â⳸•^ ·b @CÜ $ŸáwW›‚ÏpFònAÃ&-n[Dø|$ik!Bà œhá¶›€¶=hp-,|;žÄû©\n/ù,pÏÊV&ølF’<ÁYfâœÅvå¡‚­ÍM8‹kD—#›á·Æ ²ÙN÷!8 Û‘VÀ™Z@0‹·8 `6»<ƒËÐx“]€vK]}€Ùìä%ÏK¡ä²ð³äl¸äxiw|qÓa ;c»ÕÞ_â²97î_1–lö„Uda³™[þ†³É d³9~²ÙtJíd³i?æ„3ÌgUÓæm|›­ãËfËú„ÑlK%B³iÞd3,IÖGL[Žšx&îšÍÛô&4[‡±Kd¶“ÙLFh†¡X’Ý­©Å_–Ñ,2çPŽ#™a 8{%3L Å„f8F¢Ù, ZÒ0-!Äf3Ñí-˜š8ˆnﳞbI¢ÛÛ*Ã¥t5¬‚oïUÆçßÈoñ“ó´„µööuO]­A]'QXó↛„µ†! Ú-a OŸÍ–t |PW ÿ0Ö)Óéwü{h)ýc†%³°Á’æ–xF`»åT˜Ä–æx¶-UØn;Š&°e&Ûx82&°ÝC`bÛF}F¶ÛN{F¶û´\`d»íq•ȶ«1²íjŒmÃÉá’ÛÞ³–ÌÉm·í’Ûn{#¥¤æ‘0%µ[Ž[©¨Ý)8YQKÑ&íSê²¢–±’·d '6€<½æNȃ> ÏÔËli7Ïmi­%%µGÌcI-;ƒ%µÛf¡–Ôn;ܤ¤v+‚ÚV ,¨•3$¨í¶¦¢f£TÔÊ1RÔPÏGP»å¸+A-š‘bÚ>=Õ´¯Ñã~U–Ó†3Ï|ä´Vqm?”Óò)‹Ö"Š eôx;Uh=ÞϯœA¢¹‘b£Ç'¿([="Ÿ‡JVX«ž×"¯$«Gø»Ó˜RFÓ®diôˆ„Þª—F½±Óèñýbœ´y\#BÙ<ÞŽ8™6«§|&›Ç9³kÇÖÆdó8GŠX²y\VR׎ÓÊ—hí<ÒXQFéøŸ´Ö?iíTdㄵóÜøFX;>Y­¥Ì"XË# kp'½…AGK H°†:\BX[M¡þÌjqUKVÛdnVÃ1’òˆjè&j¾P &VÒÜHjè%²¬$¨…]ÙUA-ºÖÇæV2\äŠÓ .‹Ó°K ë.qÚrÊÀ4ô=Y² ÓîRˆi诲U¦¡±«Z<ÂþʇҊ͒(m•*)­lÓ`¦“%ôÊ€’Æ´u;|1 gYa#§a«ë9aÚzœ¡Íœ†íˆÓ J2—Œï4óµÑã¼-ÔÉæñQ PQ*Ñ>¯M§ƒWÚæq9‡zÚ<>$›6p¨øÚ®kñ¥]É-=i,¹]ΞšâÂsȈ=Ì÷–’Û‘ª—$·+SrKHÍmëiÖÜC¢%·eœ³â–jš·'ÑS‚Û{ˆ¥<+n+­ ·äFÚ·âvß)bYq»í–X7IT!¹e Ê”Ü2¨cjnšhRrË8/[s“<°%7'1ÃE¦S%· ù¾%·m‹æf“B‰n^é§æÖd2–’Û•ý7%·'9O’þ¡¤·0\à!RÜ !ˆê¤¸õ™ŽuRÜ2o—7Äûc½Üžs3[Ó Ñô(Å-Sg¥â6Ó ÀŠV—¤&1„PÒ˜· nžŠÛL_!¥§Êp':p\ÃÅ’ªU†‹Ù\œG†+«A\±fÄavŽŸD¸PÆ8/ábvæ•ÅpQ"G0)nͻé¸õ˪7x¿UŠ‹jF5‹|ëéÖά¸]ž¥Sq{GŒ¯à†u ¤·<Ø<ëmØÚá1ÖÛín½-ÒÁ²DzÛâN<÷»BÜ{ÀñÛð©¤Il‹'ÈJ$¶!“ÏØv í°Å¶ðe‰Ä¶å­×Ûðî*ƽ%÷± ±íÄ*ý#¶|ªëZÈ<7K¬¶­ËgImƒT5?rÛyZ£µÜ†cN p’Û" ™8ÊmçÕ~}Õ¶ÑìZGµ {gªmÃKg«m];W©¶Aëy*Ç…¶r|Õ6˜[”,·So&å¶ûIn“Üöxé›rÛce'å¶ÇkÙ”Ûæ-É0å¶gýúF¾%2YØz¦¶Çzè. $·EÏ¥Ž'½mÙòØz[ Çß(!ÍaϽUÿµ8„”hšC 6¢§q_ÄùÑÜZØçE‰x®Åš%ä9èjŽxWçã2Ï¡žYy.Ä bÍ ¶»Q šƒ KGÑD²¤i®G_žig ÃDs!q±DsønIlAs­ßZ.›æoNF•¢¹æD²Isín’ÂMsmHÔ4Ì•CsÍ _ sS'qŠ0‡âVÁäß9ÕæÚãá_0‡°vwÕÜÚÉ·À]‚9Œ ´ÜÌ]‡ÕBÁ\›ædÁÜ……5Û]nyûQ0w¡£‘îs×a™U0QóŠäy½3ÆÄ0W xæ®s~\ÙÞkX]Ì]ö[ ”CGqd‹ ®­¹]Mñÿ­¹]Ým–æv ¦Ý"²_a¹÷Šã(º]í sçÅ0¬¿¥èvÝ]“›D·ˆü¿©¹]¾Ån¡¹]÷áð‚ñi³¨¹]w³‚FÑí‚÷l1š<¯H4Ê‚Ý0øòjn¾UÖIÑíº×¯j4y^Óv¨Ý.Lí H•‘¾ÖÝïO°š3,Z Žã’³ëOOÛé/ÒÌsb.ï ¸dGÕrÑŽÙ³Kv\­w:…iÒ§*•ÔªXT«rI©ê](|ÚÄߥš((•è÷u”¯Xôö? òõwE¯þ׃|ç6È×ïúɺ#ÕC ½ô³ÇEgªüs”jÚá»TS ßåšöA®©¥švø.ÕTÃw¹¦}kªG¹¦ ßåšJø®¬)ÊšÊQ®)Ãw¹¦¾+kʃ²¦#ÈWx}ßãëþG1¾îãëw½àOb|½Çt±Ÿ}ígȤŸ1¾þÂ0ö÷Ÿ#Ò Zÿ£ûcû“û»šþzŒ/lŽ¿+íâë8¤Öÿ‘Q¶v¼­ÿ럄æºÿ?á úÒ»òøÃ_ïûþ¿öÿþŸNëŸøzþ¿ÿw¤¤~é½üßM€¯û|ýÇ>À׺aå®áí)cc;´uù¬ð ç&ߺŸÈC¬,@zðùŽ̺W¤!h– Þ,è‹ñRÖ;§ðçŽåÆzΈ¦.5q.×謭3ZD³ 5gÁAû 7mîy­ˆäÅ$í ÆØÜeZÈ«ÐÃÝšZå‚çî kýREÂ?zW¯ˆ)nÑün+”pòhIá'Í=¾—À3ü¤ÃHe…K[ÄþÒE§¬3èf²°¯;èîÌßpêÙaE³m”±Â¦·¬ÈSU &Vía¢Š‹Gع GÃËsJýöâ2ñÐéñTS‘‹çúÔ\<ô4ôí ] ‘’ñPðáÀ 4¢Ã¡¶‰ÞlîE(5Œ(Yá0è¦1úË@*žÅmºEæâÁ1êZÈÅ3™•PoÉx®P‰\1’ñ<áWxëq#]·s†&z+Æ[€5k˜Ê5} HÆ3Blêú*G?wä7üœqž/áZ±Ò†àÀCãRÊ»¼òsÄ8á4é©`Ž_4Ò»5Š0OŠZØ?ÂwRf9(ˆlqü,\ëÍÝôß½G^yxúŽ7‡‚çÒM}÷HÃÃ\mþ<†‡ÉrüŒ‡§S;”„d›Öƒo 4Û(Q׸)Ù>²| àË[Ï b‹LwzhÝy3 ü[›Øò óУ÷q°Ñ·+9·Ó=) OÚ¾%mCêÓ®$¾™4á-¡`;åŽ/§’5= !g˜Yzššt÷ÍŒ pøéaûè Gùw擦̟â{Tžé|­ðÔ‰9sí'5éô»+%S÷ÀÌ;·îÁ½Òæ]2›¼%ˆQ÷¶°ç¼¿b¤G{¦f€1îœ`ÊÑ?×^!ÚF¦;_iĬ¹Îü†‘„gF”?w,„kÅS’¦Í %óórûC ËP•`}w ×¶dLª§öÑø*ÚÇ Žs᯾s¥Ÿ¡à­¨FK—0š¹Ø˜['õG·%#â¥ú ±(¦ÏðÖ:#s ë¥jëŒæÐ©³Á«±Ôl¡^ù ˆ¶a›ròáÒÔ£±· Ù–Lê¹§“¶°'U«x”š€Äãs9[Þ_àU ìjuÃj XÌdx’ɺVoÉd]pa&óØLæ)3Ö?˜L˜·™L×0“Ù±pÙËÁ|Çø`ÙiD0–¡Œe â•T6Ô’Êœ¦2^_D[Ž‹ˆ%$kIIdIl"2ªB2¹Æ2[úËÒÖ½bY´×TæÑ6©ÌŸ_b™2¹'•9•©ìöÇG,ƒü¥ŸôîX¢ss b3ÙE'˜9ZW‚Y“™†Áìq"aƒÙãàš&3¤YU¥$³'Ñ‹dö8m3ÉìqÀ!£ÙãXXF³gå°-4s ¨D³Ù6ˆÍB¸ÿ Ùt¦˜D³Œh6GÎb³é¼Â›Íì?.6‹T^•ÍâJæ®`³g9®“ÍPrêÒf‘ŽÞÜh†nkj!›ípMf³gÝû˜`34ÇkT²Y<2¬Í6ó™ù3À,°69Œ1­§W7³£åòY`†a^++™#/Ìv@'ƒ¢*%8ÌŽ‘·`†•¡Adv<ùŽÍ ° Ï X йÄ%Ÿ²}O<;7O ÏΞkpñÙQZK>ƒ¬mÌ#¡!3­ú]ÚiËý$4„KÎÐΖý[€µQ¯íTä«´ãÉU‰Í±'ÐΙ,"B;“â³cs±ø¬6÷aÜ&½CñÙ¹Ÿ­ø Q‡ÏÎý‚„hÈ¡ëÑÚ‘{ B´v'l‘ÐÚ• sZë¹f¡½ÕhÅ/BkG~®AhȨåëÐÚõKýI€{’*! µf0 e ¤´ëÈÁD€Ö6f ÐÚ]Y€†hµúDhˆD‡"´‚ôAh­o´"¢]—WÐ"4‡!J@»ô‹pÖf¢ÙìrFð„³z;„³«çp$:kÓÃHÐY¡}Úµ±[ˆ¦vÏbïUìE>»E+ùìºwä³~úæ„gדû\³ޓî…gl”xÖšgizßEh–ÆŸ‰fåB³°,/)ØÒÆD¡YøÜ|Ðl7^d–Q“Ízó—-2ëöÿH2+»AfýÉTd–a\ͱÓ"›Ç_lÖ¯„±Y©Fp6¦÷Äfã,$lÉN?l†˜¦zÂb³¾? °Yìx˜»ÈfãÈS±YŸ»„lV¯D6Íó’Ðl´&¡Yßß“Ðl<¦c‘YÄ`aA€YÝ7˜½·‘0göeÙm¿?ƒÙ+o@`†ÛÖ«%˜Í{oâÌî¶k0C{õ”!õ>ö-—ŶNÁØúÎm(qYÙ?—ᘥ‚À2<ÞKôX†àV¦£ 2\X‡¨l;cšÊÐ~á¡,\&§J‚ÊpˆfMaYdCxtÌdZML³½'.CkÕ…fèBD;rY,¼‡)¬éùûÂJÚgÞ‘¸,cý ¼Œf£)³¸ÙÌ1gÉf·Ãä›Íà™&ô"›!enÕËn¯&Ìf°˜H‘Íî'Ñ‹pv;A´áìv’ÃÙ= ‚³{¤F:Ëfœ½+©3‚³[ìf³{£álƒ†è¬L6êo›ÌnG#3ÝŽÆo:»–tV*âÙí•<ñìvÍT͆™Ã²YÞ²ùÌ· h#%@³×Jšn$ u-Éв ZÊbâ³ü-«Ï‰|Vù¬Ü5ù¬¼#âY½iâYéc·bÕäã¡Õwx+RM@B«•’о%œ/÷MBûsu5Η"¢ÕKõŸ_­tnZ¹!Zíq´ÜÌ5ŸÕ«¬®æ'X§ w¬!Îó¦_ùìsÖ7SŸù¬4–xVÇâYiþýóLHgõ€{þè<„³OK楞a¥o7TËšZFE3ܲw&Èfñœ¬€µSûàÏÎêX¾®ÏÛ ›ÕE«ÉgB2+–`VÞ¹¬ä²rä²Ú»Èe{¡J.Û×–í:De»£ˆÊÊu…eåõˆËÊ…Åee´—•oY`¶?wqY#Äe;¹¬ <â²ZÉò¤©¯E\¶gDYy ²¦Î÷#,+É­¹\ù'q¹ŨoÛ N°Øp9³œ@ïÊb#%ÁØè g1÷à7%)¢ØÈõ¿Pl(u¨Il8ï¦IlÈ›Æ à&0ÄJ• ±‘¶‰±}"±L*j+GĶé¡Hl¤¬dëŬÃÖ‹WrMš/ ¦NÖh.’VÖl[G­lÿ]ZY„Ųˉd±Ñ,¾ÅÊ D1»ù™ÄvƒHbñLbû&ƒÄêϘ^p…U¥²l‚P,›(Û¿Ibû7Al¤Ùª@lWHž° b¥M±rÄlõ!Äò¦Åa¾BbX¾‡ä0Ÿ’6¶í€0¬–Ãj 1¬TC m[=ÃjÉý£-İZ-9lì5Œ@,»N’X¾¨$±Ý‘X©X$VKHbå$‚X¹’@¬^©ßßß±Ò^Ù/Ž™³ÒÉ2(~êd™†4u²+÷XeÀ8ÎmÑ~cX2’JÖŸÜ#¦ùbîÍK$Þa1_D\*+WÔȶá—$²¬ ^±Û‡-d›#R$Ã1¶£¤H6¶~!‘ì>rz–H“ÈG$öº9k| à$’•Z¤’ÝÛ M*e+ŒÅ…l I•ì^ùœ¤’½‘+™ì¾s\2Yi°„²q§­#u²ÌA*lîþ.¡ìÎ,l¶-¶Q(“ŽD²g³´D²·¢³(’Íg!’Í; »$’­Ç‹xidó°U4²g¤`Ù<¬‡H"s¶Ô”ÈֳϠD6·Il‡šKì=Wk*IdëNc6IdkB…lÛü Ù*~ "·¸§K„Õ9âB"¬Î€Õˆ¿.,ý¼é˜›ó)V>jßÃù®¦–×8ŸŽû×ö=‹wé”Åéaè+º±®jäÇÌjæXo\Awðqp»e6®ŒÔƒûVš›Œ¸…ð„ã<æj4Ú!·TRƒgýùyû(óoÝj tµëçïÞ* Jüý.²Ú¹€j%*©Õ°¨Vä’RÕuÒj¡Ü¯JJU**UeÉuЭyxþ{A·æÿ›A·þ §œðð9¿a·~ôºèO÷ñé‡ϺjH-Öõ ¼¥ºÊQªëž‹uÕ Z¬ëzKu•£T×7@—ê*aµTW ¾åºöQ®ë¢Ku•ÀZª«†ßr]û(×õo„ßzi,b»þÿ$þÖ_Ôþþ»á醰¿ÿa÷ý9¬ýI÷ý]]=W¤$;F µÃcýO•±¾þI-ó¿ öÖy® ÒÿŃo•Áô¿ÿÇ¿q !}9§0þFTk€IkF?d~kÖOx®ˆ¡¥½ò3"Æ0Š–ìvàÛÔÃeÛ–Ið¾À4hÿ 3¼hÞºBI˜åôÃN±qÁ²lx4iµ`¿l$p KÖnWp”„áBçÒd®§ÄÎzß?­º‚Ò¢C„k_Žøs.Y-8ÄÕ[Òn™ÈFõ\²Zi6…}»'¢lÙ™6ZI[÷–DjL”Há8‘6èŒl}>éáFõ´îö–pZ’Ú‰}$ìùš’OäÓá!\k¿S¿·ªv¢!µÉ¬†oíù¸Ò‘s’»Õ@¢i>îj.nW?V}ÚÑé"®]ü†dºÚ¯>TIZË£³I¸i­=¾N¨ÖŠ-ÌŦ«ë­¥vïb”·j"Ø8ücÚfö¬–{ i[ïjîö–Ðá…b ±¼i1§}Ívv²J¶jïäù±÷k§lȧ ¦7º¨è5¶SFäVx’–¬+Ÿæ)+òoÛ¹hʺ,—¶&;òÛpí½q¡æ!çˆpjÚwmH¬¹â·¦]tÍWfÐ7¿œÔ霟A=ÞÕ.½ó}©»éôÍÈëIýón9=ÃŽüÉð!­!%áãDøfä“9ž áWœãÇpÑŽüÉO²!€3£ p' ]´#GTš©“®[áÜůßq—{KFX=×å- ó£'E±†àÃ#¢nàÓ㈩á½%aÔú¤µfës(òžÌjZ_aÖúì/paÖú¤éè[v­åêÈ Ã YÒ®øík#Έ’¬…Æä£¾4¤ÏéŒú×tiÚ’?O~üHŸÃŠ}É#©‰yb1öd´ ¦Ì§Ï"?çŒKé3PæSäVG»þvµHŸ3J˜ ”Ä$Zºèôxsoèðû]"ÎÇ,,=_ HŸÓ¾çМÜß‚§é ä…hP¾»È=ŸOϼiOþìá¹sÖߘ’f©d}Ÿ®P¸žDsòòfA·l¿ç ÄmiŸåaŒÚ ò–Pð-—¢à‹‚Kì² ¾]þ§þRûÝéJ¾¥J¾åº“åON“šïc›˜6iO^¾¤IÑw·%2Ÿî«Lj¾¥ š“?O>ÙIÝ÷qb.ÄÐ?úö¤mîcÑó-™þ„5ÍNç>ªMZçî¯hÑ:÷ñ¾}[´Î ¢¥’ùù të4`xlÔmtË÷°h¿€›Vï_4Ó}ì¶ù–Ѐ¡TCC](Á— u U‹¶º8GC3óæ”’ëˆx£Óøu(âh>¹ëPÈÑ|PסØ6ýt nã1à:Ü&ïñ:Ýæq»…·Ùµ(¼g‘Ø€óçÚÍ{ºš§UäuDˆ›\G\Ø9d›®Sãfºw\Ìšapø¤®SAnrp1mN}'Íw³7\'×Á±«ËK´ÞEÉR54ßÝOæ¤õn¹ÉófsýtOZïF [CëÝZBë]”è=ž´Þ-%F6Ëœ«Ñz÷ÉÕÒ…¼9gª¯FëÝr)äÍ©•Ðv÷ÉeÚż9;bÐÕh¼[¯Ã½¥OÉÔ+pwÒçKù«A»6×1¢cÝñš^f™ëΕC°;öo’]KÛ)“]ÆûJ²Ã°b²‰ìZ¡4¢]ËhF»He÷a» –lçÈaÉvÍvÍÎó»6’žHwˆ‰"4Þµ ãh¼ÃªÉ0G¼ƒð,äb¯n{Ãt×îÄFÂ]{ÒKpWO"ܵǫVÓàÝ­Ý!c‘¦è®¥i€ñî4N±Ðá(×ZèŠî°ñ Ù@t×2§é9ÿæ‡îZ1Þ5eÝA¸O‰î°®iîêuw°Y¹?p×l·`¸kiYgºkiR`ºk'Ôt×åMw-mMw»}w-c£šîj éîrÌñ¤»z!âÔ%Ý!zïù¡;Tcr#Ýá˜aÞ‹ÉéR ³R ŠŒo¬˜Òíð êY íêD;HÄZi í®Ã+B¡öò´ºÚÕ¢]­†hçHé‰võ$¢Ý•Ã…Ù%§YމF¼øÛ•;Û]g®OÅvù Dv×±!hwy§Èd‡.m¼"ÙÕ’]iŒÈî²±‹ÁîÊ(+»÷·–âº+mI v—ÍÃÍuå2âºýF„u~õ„uWië®s³±w´TÒu„’`WîYdWC²Ãð7¹îÊ1æº}GºË#¦ºòÊDu¥-¢ºò¤Du— ‘ uW‘1Ô!šÖêÊ-‹êJsEu×™Œ,ª»ì¹aªË{ÓÕJRYÓ$:èÊ  ÛD‡ùÇuãÂáñƒq#C“›ã½XÕÈ·øI…q}kÇ™`GŒ}=Uº'…?«tÏÖä¤Òe´ƒ-Ò:-Òå oN»)©Ñek­Ñ•Kƒâʻő^öö÷æ¢(nŸdŒƒû«¹HžÅTÁ7Ò9Ñg'ÿ¤8‡Åôº2Å ›â¶˜iŠEn#Å ?›â, !nüN¢}ki„¸ÝX1\†$H†þúÈp ;®ÔA„[à•¦áÊ-Šá†Crá2‚C"Üh0‰p£çšA7¶*ŠË¢¸òDqÙ- q¥€ 7šùF ‡ Á:‚7LJûñ9$¸±%'!Ü9 áFfe0•[ „¢b‚+oD·¥nßndP\iŠ®ÔÒýõúÑŠàJoÁmÇ#\mÞÓ?_ 72Ûƒ®Ü³ ®¼zA\©GW:Œ(®ÓrC7%ˆ+]3 ®ôA\¹AÜ~œb¸zÇßÖë¦ÞACŒÛ}HWÆ•j„qåÑãÐ󬫵ëóšÄqµrܾa\=‰WCŒ‹x¬–ë Ém$¹R1A®t¡ÜîÀb¹rÁrõ7a®¼Á\¹%ÁÜ~šb¹ýE åJk…r£o#Ê•î ”+\(W[ó86Gž5“Â?Ir¥¡Ün®Xn÷L¡\iŠP®œC–+çåö…Erûa åÊCx2RN^G¡rüPžŒ•ãë*VN¹Ë)Õ*\Î~&¹rŒp®Ô#œ[íÏ•æÏ•æŠçj½ºzL†Î±Š) +oQ@·oS˜‡“S{æä·õ.ÓT1ø-b\Ú¡-ø áË|Kà7TÒ«ãè5‹ßVxª ª‚ßÌS©‹`RŠ¡ýWòۺƶ¤ €[¨-q-—´ò¢ƒXÆ"¿!¦ÈüðB´©^à˜%A¾­—D¬ÈßÖh¹Ž#¾¡ŸY£%¿!X«Ê¢hr$½Eã¤ÿ¼!ÌØõq›Cc’%ÞöÌöd„7Ì´ê1€7SHÑ[„áºkÃØ µŒ‰oïgoãVáÛ¼¶³ùí=Ʀ¸·ÄƸ¹»ƒn^¥„¹mK=D¸Ù·ÿ¨0q?7÷6´®\H7ÈWîR‡“ìZG‚›×v¤#ÁÍžßdÜtâZ\¤°W%D¸·d}n^[8$ÃÕK“áÊcÃÕ³ÈqX"óÍ ã¦úDq3“š›âæöw Œ›Û1P7YÔ·S›âžF0#ŒÃ…ôµ ãÐþŕŕ)Š+ýL7·cš(nî((nöTgDq3'TSÜüÛÜÌxÁ¦¸¹ý3Eq³o{NRÜÜÞ⸭Ù‡zØ_qsûg âæv÷ ›Û׎WZ'Ž›ék'ŽÛ—Æ•–ãÊe„qåÙ ãæøigYë!ÈÍíù'›Û«3HçØ’’$Wk!ÉÕZHr¥c‰æð â·XnÞ©~åkü£Í•ëˆææöÎ š›éõ'˜+W47·{šháÛ„Q¹¹]R…ss{ çÊÎí7+œ›{ÒÏÍí:.ž›Û‹6˜n¦/ ®Ü¢°nÞiGIª+·$¬ÛMÕ•"ªCTs«p‡žÿ]n>¹_(¬CœJC´Ûg‘íò¥™íò†Ìv¨ö•åfºúîfq•#ÜÕë[™íf:EšíöK3ÛáÚCËR0Û§õ„»iC³ÝÌ5Œá.û\úÍíÛÛÕ“”~?±]=FÉáÜ~–B»ì D»9ÓS™áŸ¢ÏM=}Û£Šìö;5Ù•¦ˆìpKíCvåi‹ìÊ-‰ìvsìfúoìÊ ØÍí{)°›ÏF‚Ýœ?¹ùlÍŽ\§¾Qƒ]¯¾FÉÊ@·ƒ©älìOÏ+ÁÆtÌ¿l¬¿Ÿ$ît_Á%%¼—ŠJÀ ,)‘Âz³.ÅïZ j%ü]ªE´r¿*)Õ¨¨T”%ÿåÁÆú xªÑÆþ4Øy!éEûópdïï8|×X:ÿ$‚Øï_ÿµ®YŸÇ·+áy(â'Î몱ÁX×'6˜ê*G©®oœ1ÖUcƒ±®Ol0ÕUŽR]ß8cª«ÄS]56˜ëÚG¹®Oœ1ÕUbƒ©®AÌuí£\׿Aì‚ÿíó"ˆ9H˜£zý³(a×? þõ#˜ØõOŽóeöËLì/ ZÿÝðóGCÔßÿ¸'ÿ¶þ¸'ÿ¾®!˜X%J‰%ö/D û«ñÀþ;‚‰½“Ësÿ'âõw6?úÿBñÀþãâýÇ¿ìýJO‡š›?†9»ï¯ý™BÆ…îw¸–{ .íp,׊"¶-Âk\&TK>À—±íZóúx©^kÙ¥Âk„‡KEªý¡Aî¢õã¤Ü9íUßæìqšÞßæMlÚ8é‡b<¥ƒÿÛ ©A^Ùý^bg³td~ûŽÍ=61åÝ#îëßf˸a±a‘ž+ ÷-‰\Ã1þß’Å„ö™¬ªŸGd+xnþ:#½Õ“ÑÖÞ’'v íåÜ_pŽìIÝp“ê}BÁ·dEb€a~¿îØ¥ºrÉÝψ}=¨ËgiŸjÊHé-X”~iã¶Ÿƒ-7{ ÷s2Ør¦{'rÆM‡»„ÎZŒ·Œ|aQз…°Å¦´“Á–5â-i ›!ŒY XË+¹"j:¶.‰V½Å&Õ‰å8{]oØü<±-¨KÅ&Õ{Ò±*Jî›~Fd1–£ïÈÁ–ñÖ›K&oáýœU;UØ7ò#í-b§¿Ä¬ðнÇ^GaÅßÌ4ݾؽÇVÕyÅ#¢-cß‘ãNï÷ÁC–v¼Þ’ˆ¶|ÁˆO„NÍS]gF°å°Ã’¡Ó¯#g_lï”Áªû8"túÕ¼c×GìU‘¢€õ HKW:ü¿¿#Úr¼-¶f\·ÐýùŒØ©zK®_.ˆÈé×m¤>b£êľ­zþ¸#rú±QõÖâDQoIDN¿Z•óá!Ýý~D&²w¡åÄLËm ‹wd…x+™ Vßïóæ ¼^Ç´Xô]×ü¥‚+§·¹|¡;vª°à>s÷›7à8)}ÞrGÔô Áö›Jp݈ìÇßOM¿Baˆ‚Ø¥ŠW¿T犨éWzu&õyoùñ€Æ¬>˜| Òúà˜·‡«70¯œ]«_¬ƒÔ{™Ùç­Ù %:uÜÂ; èûBvløä#‚¦£—éÃf~°¶ŸKD³ÃsÉ—Â?ï£èÊÙÐcCCߤJb¯êŒývÖ ïà±8Ø™ççD– ’÷[qÓ¯;»³ýœÈ¡^t?q—: ó ô¾Mg¾Ìîú‘ðG,sèÌøÃ¾Nz"jú‰tLK%‘»;§n€AŒ¯ÈRÆ’Pl£OèKY kŒ‹sƒ¤3õæC‰ž}øývEõyæþ) ^!Øbæö[aöŸ3d•„`=‚{3ù°†ñ¼B±Å|¯,€0)ibd Ìvî|+ÛhïTÅ¡ÚbÒÔ¾DׄlïÏa0 K ü>Žm£Ssof0 Ðûžœb¡ÛÆYì"ƒY€0CfÍÿX;èkÌ„5–òq„p·y©äŽñh®GȶQï£zcÛ*>¾…q„r‹Ùï— b× S¯–uƒY€bç€+²qüšÓ}0 PÌ"ºÍ3Ô[ «J”1˜c¼ºÍ8C½ÅŒóBKzüžš<Çê-¦U…õLíó•B½Årâ×¥FÔîÐûuV¨·X>üânû`" è¾«Ðo1s)ßÊP& ´‡‹„ÑBÀÅ®v(®5tLÓµÕ>åB-®7\Ìûš5F‹…q<-f™L„QQ³Üh¡àòù©¦êgyŸ-\ÌB¾s¥z—”Zˆn ël]Æ58£ž7”¨g&”¡|@}X_×Ç=rU±„Ê㺠ãâwÓ9Üyʸ1:e\¬w(õz#] :à_Vïþ¹±%Iâóç˜ÀWð&ÚÎGÄwîprB¾Ó‘‰¯9䬉¯í "¾Œfàk÷Æ;ß•>¬Š0òL†Ý2ðõŒŒ@à{Ÿpþöv’Èiâ»Ë1A|ˆàk¬"ñ!Ê«aߎu'à m© 3^¶ð=0ëà$æ;3à€™ï:²Ðw9ʧ˜`ùø€`¾®-â¹`¾y{*&ñEÂMñ‰Y`’%‰|Dzƒ˜oíU ‘¯˜ù`Ãc'òÁã1œ½Kt$f1O“ù S™íÍ|Ør ¡ ÁT ¡/r±p:ôíC|‘ˆåQ Óëà8r+QVóB=ˆI¦†ùŽy²ÞÔE|‘éK|M©Ôø€e¢%^›ˆJÀ‡K}€ïÕ|0§ÑIä½suƒ„xÜèŠÁ{0‚9T-yê> óÞå©0ïI¾°€a‰€o ým”ø G>Œ•_ໜõ,C·Ž!ð5øèàÃËÑUÀ‡AâkXª^_{{ ¯MâìäcŒ|Ý‹h#ž¨ȇ½ƒ/ò3ñMÈ·)KÄW0ˆK¿®ß$>xkŠE|{ÛÂÄw!(®Jˆ|p¡S=B>èÝ‚5!_$l‹!_ši$ò!ÓJÄ|i“Ìó‘V0ßÝÙF¾9½Ü4òÍÓÝÆÈ‡4p:†Ì‡íVñ½˜«5Áº˜/–¶:‹Ì‡5ž§°g‰ûÞÑШ`ìC²'CîÚêøp_¬,n•L®Äœ€1¹/×xæ>¬bŽ/÷ÁÆàË}ƒ§mIîà  š‡–ô'Ä}(ˆûú!0$ôa¹Ù>Ð×Ñ›t ¡»?ЇÏH_‚ «j}Q‚>Єö¤}½{›Ėuì]˜¯‡º?»‰Î”lèëûËõaª:}=Œ&YBèèúp% 悾w¸3ý úÐ\­}X,5c ¡ï¹’Îú`©#}h&BSÒ} ³D}Ãf†¾ž³¿¡ïNvóÝ— „|3·Ì|²ûe>Ì>jž˜oo—óÓØ’ù×P<'æ‹Dœ¿mäCŸK"ßr–ÃD>ˆúª†È÷ž­geäƒ(^òÁ M+÷@¾ xD¾éï$‘ozŸÅÈ÷Ö¯Ñ3™o9·§™ïýW_»™¯\[Ì7"-=KÈ|ãtÂ?3ßÈp—É|ØWwù¨_W"óaXæ{¹NŸ¥™oDFy–(#Ó• ~1ßȰ¥f>L Ý%1¥¤‰‘ù4ó¿‘ùÆa 3߀‰ç¥\IME]d>Ø>â92ßÀ°¥ZÈ|8æT-d¾%”ZCæHB§%æH+¤ö‘ùPh\Ìf‰º:™S Z,æ‹7#`Ñ ©§˜TЇsÄÌ‚>´ÆØEèà 2 }˜?Ìb‘WÒÛòáùéž„|xZ·ÚKäp1Q ‘õ8|#sФ¢Žñ‡­ò!Ý©îÒ:ü%Û¥% ˜©2ÍQÍÙ†A¢¾k› ûàü"çþÀ¾…ÌØ‡¤&V •Êe¦®Gì{Zràrz1†±ïÉ`¿æ¾yüúfæ1÷Á¾h|„>Ø› üÂÔÐâÛ 8›È}ð¤éÌæQé+ÕPè;殆Bß™u-ôÁZLË: }P N?Xtõ ~+·‚ûà²Áoe02ƒßLgƒßtįB~[M~x{:$ÀoÞW*{ѱçȸÈ?øNÈ(ÌZVõšÍ¤õX„‹­ŽH¹4¼l±ï¶>kðëÞ*Hð;ï䯿µº.~kgûÁMä²*ì‡Yyº$ØoE~cõôpZÐwaöñ:É~í]-][ìØê þXÛÚÓ$Ï5H¬'*ø;zn° þ"ý¨(-è"¬ßék9:ý­'s’‹þ°Ö¸/ýÁ–N-6ýÝ~㢿33U˜þ€¢jŸè™DŸÜ‡OBõˆþð†Íd¤?$‘Ö&‚è)Tµ°úÃg¿>rßqƒ è~á‚¿Ž ¢ä¾åà•†?d7® þÆÊþÐÕ¹H'µŒìwâži„?¤>=ŠÜwÂLB¨GøCVÙþ?dqÕÂSð‡üÊzæ‚?¬!5ÎþeIWüÁJƬÇ/›;–cªj=7nDí<ò,Òß™VÙ¤¿ómÍü(~Èøjø‡¡KߦðÞ²ÀÇ\Éè.á_Û%’üÞHÏË’_óÔoüƒ+L+ª_{?€çƒíLá_¬ t ñjÒùÁ¿÷=»Å¿SÊGöí'*üƒ?•Æ2á߈8ð,!þáíYÂ#þ°TÍ8«bfÑ(ªE¢ÿa&õSü×"½J‚ÿZx뱄ü»sùVêâ?¬máä¢çʳ€Xˆø±ÈgnÕïí¡Ý%”ý.»+™ñ.-/ñ!úJD@ÜÕc%00²U~ðÄ,L$žèðÝ“œ>z! 0F߯0%h# ¶#>ÂJ×B¼¼ˆ4bÑêCˆ€í1˜±¬Ö¸%lïXo¡’ˆÛÔ!S3ëá™a—òݵA ˆ7g¤BY5ßoìüè~üµ\B&ÿê~×Õ5r/x%}t?ÈügÀ)1*! âk?šYñ=!ª®@‘ø®zß)üÝ ‚@Ü•4F ÙUB¼"Ò+Kìµ„Ž„@øÑY@캧ñþÚðÆ‘!¦¶ëð&¼umAàp÷þ°eö@ì¢@%üÁ®NE„)‚AŒˆýºëðØ›1@  Ø3ÕSbu`Ü$—ñÀ-%ˆd@,3Uðò0• x8ábê~wDS÷C/I÷HÄbÇñðï' }DfMûªÍº©+³”-Qv½„@ÜŠÚÅS%¦@ÿ¤ê·¼æÝª_KRª>pªß‘Rµ#æWm~ qgWAÀ?;–býA¾Øç ƾ{ÜØ—³ƒúvS__–½L}o‰Ã*ûv¤esâ?î»3ƽ¹ïÎ%аï~¶ hfðLuØ÷l&’Þ·×G´ïì[¸£Ü‡D…)Ú2«¥Ü‡îi%öá›ûÈ}ÀÇ«Ê}3 -~úÞù!ŽÐweR-C¶WÌtTûF&Ú¤Ú7r»RÐWB }ïd`¹RÐ÷¤S½©æ[_½[‚¾4±o»„Ü÷¾+Kuüà$tZÞ Áan“à’·µ¼™(ø]éøfÁoU÷- §é,¸/&C×BîÛ9¾Ì}+}SóË©ù—W,©ù=^ñQóCÆNþ”ä÷¾@-ÃRò›©Gû jŸ^؇-F¬ù¹ÅnÍï8S¾öͤcœmÒ“<ÔžèœÐ’ D?¸¬×(úáœÃ619+ÙÂ>tÜöÁ¾p}ûbß‘2‘­<ÏÜw7ö­žÆ—¾™¶aÆ>컫DØ7Sã%öÙ̒̇ Ĩø½Ku ¦‚¾V.y(¼¦” /¦|5—Їõ½V¾‚>ˆ³ZÍúÚÙD}Ç•š©/X‡±·7ØÐ·N€¡o6ž‰Ë¸ØGƒŽ 'ú }@1}΂>x™oc ïŒ”Â,ô=Ûˆ3 ozgÙÐ+_=AB&´æ‡p¶Ø”çÀ$èkëôx)胟€IÐ×"(K}‘P%Zœü€>Ñ4¿¦Ç)âkÛŽNÄŸÅçcèÙrÍhâC‰ä&_ Tâk-7èD|¸Öú~x4zX4ôì^s›ùàê8>†ž-y£@Èw-[%'òõÄO!ßÛy¤Q ùZ;!–o¼…|ѧKùB H‹#òÅ[aˆ¯¡Mb._{>¸‡íá”qïN;UãÞeÇ÷Ľӫ¸Ä½¢5÷Úq»× ÷°^ÜÃZØ„EÜCÉS¿òj…{åi ÷ áƒ{XÄÉkƒRóžC&&ïÁ^X%ä=,Z5ê‰÷’®g6›c[\´ÆžÞy ÞÃ2Q¢xïÂJTœFÞ»rï#í<Ñ/t–xoY0MÞC›T"ÞëÞÅMÞ-)‘¼Ó3aØy^·:¬yû¶(%ï]=WÊâ=¬z] yïÚ•xóŸ¥8zïÄ$ïÝ=éɼ7½üOÞ[I‰â=P€h®Ç=-Ë0â=°°ìÅ{0¤¿?†žW&ª5ïžïÁ,@â«xïS2y+å;ñÞ“¶‹É{ÃDjÞCº—Äó»Ò8ô’ãÄpkÄ{X‡t›ur§¥¢,à»Ò€ÏÀ‡‡¿TBàƒ'B7Þ6¸à  Eà»2{³~»¶­ à{—$ÞdéYP–žíL)ΖžçF@î¥"r8ŒÀ‡‚í1 |à9±¯-=±PÍb¾+Ep3_3º$óýcéya¤sÄ|ËKZz^šù°‹ÜéÜþ×C–þò¼òߥ>–øweÔãß“!ï¨úµ¢ZõK/U?3¤T¿L,úƒÞïC–Ýø“¸He%Oü›gZ€þL©‚D0|Ô²Sšß;5%¥Aó+6¤?„ªúŠ~PŽè·`"ªjþ5ò áï„ï»fdÒßKx³‰¡çÈ*‡ø÷./‰áCgº ü{™i8ü;1kJ!ÿ…J é‹üÇ# ÿÎ3_ ÿÞõbÿNÄ™°³^à_lk†“‹_Kûs»ø5 Èvè“ØÐ) ÒÞ»:6Õ¤½gÄÔ¹ÿpÏÿˆkQ@ú»°hÑÅŸ0ËY-ñÞ$:…ôw5GÛ0ý…ÒÇâóJßôwe²%Ó_xç|è/;EúÃø%Cô‡ [çÇň§Nôm°‹þ`?¥›ýÁæßdGú ï&Ýé³, ’þ°ˆø¸øÁ,O¤w¤G‚‹ì³vµFì÷~GéCwÉ#‡²`²³é&.ÖIˆ}uì=APZΊþ°Ç}~èo„jÎÒ_‡ÉõGòƒ¹Êõ±÷„ñŒóŽaÓÙw‰þú=SÄPŒÊôð„}yÕaüÛKQøGžcmS@`ú-YJô68:‹ô7¶%¼èVCPE£§}¢è–1–ï@˜þÔcEx4ý#ùÁêêùÐßGzð‘þFf 3ý™½¢¿xFÉoàk–|GúW޲A£H’¤?ìÐZÎ#ý•/\8¶—œp¼ŸÄñ±øÛ÷R8Þ…°6(€ãN2ÞGV ‡­.Icå@ô‡€‹þÆLSô7t¤¿ÓŸÍ;·ß2!éï>º;£èýÈòéï>ÒUô7f²‹þî+m”E¸59ð¡×ìHüCgR¯Þgz!Šñ¤úÇæóŽN–GKtàØÆî"À1SXÞ0‘Ñuõ¼D€÷ž‚o %¢; ‚ÅÙ“8VZˆqç¶.%Æ'¡à=rMˆ7Ó?xc:û˜}F‹u- ÂÙ™k‰€8FÆ €xS«Ï‘æ&@4ïø(~¡²€x§ µð†¤mð‡[ÜFö»3”°Ùïnw’’ýîsþ`¿¼$í‘ýîëJª$ûáÙ¤ÛßÃ'|'¿’ýð!XO#ûÝiBöC×±F>¦b¿c±˜MŸSÆÙF¿[l-îCKî¯Ð›jñš„>µÚ”*æ%sOÄ‚ÐY2÷D8k{1e¤,*î»±*>™{†ûKdî‰ÑÜ÷ßþ·ÿ³I‹Mendstream endobj 6 0 obj 168745 endobj 4 0 obj <> /Contents 5 0 R >> endobj 3 0 obj << /Type /Pages /Kids [ 4 0 R ] /Count 1 >> endobj 1 0 obj <> endobj 7 0 obj <>endobj 9 0 obj <> endobj 10 0 obj <> endobj 8 0 obj <> endobj 11 0 obj <>stream 2020-03-05T16:34:57-06:00 2020-03-05T16:34:57-06:00 GL2PS 1.4.0, (C) 1999-2017 C. Geuzaine gl2ps_renderer figureOctave endstream endobj 2 0 obj <>endobj xref 0 12 0000000000 65535 f 0000169062 00000 n 0000170812 00000 n 0000169003 00000 n 0000168852 00000 n 0000000015 00000 n 0000168830 00000 n 0000169127 00000 n 0000169227 00000 n 0000169168 00000 n 0000169197 00000 n 0000169291 00000 n trailer << /Size 12 /Root 1 0 R /Info 2 0 R /ID [<71AC548E602BB071C59558B99FEAF1B1><71AC548E602BB071C59558B99FEAF1B1>] >> startxref 171032 %%EOF blis-0.9.0/docs/graphs/sup/dgemm_rrr_has_nt12.png000066400000000000000000006117761422157504600217070ustar00rootroot00000000000000‰PNG  IHDRTjûF¦Â &iCCPiccH‰••gP“YÇïó<é…@B‡PC‘*%€”Z(Ò«¨@èPElˆ¸+Šˆ4EE\•"kE ‹‚tƒ,ʺqQAYpß÷?¼ÿ™{ÏoþsæÞsÏùp ˆƒeÁË{bRºÀÛÉŽÌß(ŒŸ–ÂñôtßÕ»­Ä{ºßÏù®‘iü常¼rù)‚t ìeÖÌJOYá£ËLÿÂgWX°\à2ßXáèyìKο,ú’ãëÍ]~ )úÿ†ÿsïŠT8‚ôبÈl¦OrTzV˜ ’™¶Ò —Ëô$GÅ&D~Sðÿ•ü¥Gf§¯DnrÊ&AltL:ó5204_gñÆëK!FÿÏgE_½äzØs û¾zá•tî@úÑWOm¹¯”|:îð3™ÿz¨• €è@(U  t0–À8à|AØø $ȹ`(E`8ª@-hM œà<¸®ƒÛà.L‚—@Þ‚°¢A2¤é@F²† 7È ‚B¡h( Ê€r¡PT UAuPô tºÝ„¡‡Ð84ý }„˜ÓaXÖ‡Ù0v…}áõp4œ çÀùð^¸®‡OÂðø6< á—ð"Â@”]„p$‰BÈV¤)Gê‘V¤éCî!Bdù€Â h(&Je‰rFù¡ø¨TÔVT1ª uÕêEÝC£D¨Ïh2Z­ƒ¶@óÐèhtº]ŽnD·£¯¡‡Ñ“èw †aaÌ0Θ Lf3¦sÓ†¹ŒÄL`æ°X¬ Vk…õÀ†aÓ±ØJìIì%ìvûGÄ)áŒpޏ`\.WŽkÆ]Ä á¦p xq¼:ÞïÀo—àðÝø;øIüA‚À"X| q„„ B+áaŒð†H$ª͉^ÄXâvbññqœøD%i“¸¤Ri/é8é2é!é ™LÖ Û’ƒÉéä½ä&òUòSò{1š˜žO,Bl›XµX‡ØØ+ ž¢NáP6Pr(å”3”;”Yq¼¸†8WJ)Hq¤"¥öHµJ IÍKËIÛJGJJ·IK”aÊ8ÈÄËì—é”y"‹’Õ–õ’Í’="{MvVŽ.g)Ç—+”;-÷H–×–÷–ß,L¾_~NAQÁI!E¡RáªÂ¬"CÑV1N±Lñ¢âŒMÉZ)V©Lé’Ò ¦$“ÃL`V0{™"eyegå å:åå–ŠŸJžJ›ÊU‚*[5JµLµGU¤¦¤æ®–«Ö¢öH¯ÎVQ?¤Þ§>¯ÁÒÐØ­Ñ©1Í’fñX9¬Ö˜&YÓF3U³^ó¾F‹­¯uXë®6¬m¢£]­}GÖ1Õ‰Õ9¬3¸ ½Ê|UÒªúU£º$]Žn¦n‹î¸CÏM/O¯Sš~°þ~ý>ýÏ&   ©†.†y†Ý†iñªî¯&¯v\½mu×êׯ:Æ‘ÆGŒ˜ÐLÜMv›ô˜|253˜¶šÎ˜©™…šÕ˜²élOv1û†9ÚÜÎ|›ùyó¦é§-þ²ÔµŒ·l¶œ^ÃZ¹¦aÍ„•ŠU˜U•Кij}ÔZh£lfSoóÌVÕ6¶ÑvУʼnãœä¼²3°صÛÍs-¸[¸—í{'ûBûªƒŸC•ÃSGÇhÇG‘“‰Óf§ËÎhgWçýΣ<Ÿ×Ĺ˜¹lqéu%¹ú¸V¹>sÓv¸u»Ãî.îÜÇÖª¯MZÛé—ˆÿ2Â6¢,b&Ò*²4r*Ê*ª4j:Ú*ú@ôLŒMLyÌl,7¶*öuœs\mÜ|¼Güñø¥„€„¶D\bhâ¹$jR|Ro²brvò`ŠNJAŠ0Õ"õ`ªHà*hLƒÒÖ§u¥Ó—?Åþ ÍŒ]ã™Ö™Õ™ï³ü³ÎdKd'e÷oÒÞ´gÓTŽcÎO›Q›ù›{r•swäŽoál©Û m ßÚ³Mu[þ¶ÉíNÛOì ìˆßñ[žA^iÞÛ;»óò·çOìrÚÕR V (Ým¹»öÔ±? ìY½§rÏçˆÂ[EEåE‹Åüâ[?þXñãÒÞ¨½%¦%Göaö%íÙo³ÿD©DiNéÄ÷e̲²·7¼Yn\^{ˆp(ã°Â­¢«R­r_åbULÕpµ]u[|ÍžšùÇ‡ŽØi­U¨-ªýx4öèƒ:§ºŽzúòc˜c™Çž7ø7ôýÄþ©©Q¶±¨ñÓñ¤ãÂÞ'z›Ìšššå›KZà–Œ–™“!'ïþlÿsW«nk]£­è8•qêÅ/¡¿Œœv=Ýs†}¦õ¬úÙšvZ{aÔ±©CÔÓ)ì ê<çr®§Û²»ýW½_ŸW>_}AòBÉEÂÅü‹K—r.Í]N¹<{%úÊDÏÆžÇW¯Þïõê¸æzíÆuÇëWû8}—nXÝ8Óâæ¹[ì[·Mowô›ô·ÿfò[û€é@dz;]wÍïv®¼8d3tåžý½ë÷y÷o¯ñy02*|ñ`úaÂÃ×2-<Þ>†+|"þ¤ü©üÓúßµ~oš /ŒÛ÷?óyöx‚?ñò´?'󟓟—O)M5MMŸŸqœ¹ûb݋ɗ)/f þ”ø³æ•櫳ÙþÕ/ M¾¼^ú»øÌ›ãoßöÌyÎ=}—øna¾ð½ÌûØú>|œZÈZÄ.V|ÒúÔýÙõóØRâÒÒ?B,¾“sMT cHRMz&€„ú€èu0ê`:˜pœºQ<bKGDÿÿÿ ½§“ oFFsF×j`` pHYsNNÆÊ/¥tIMEä&>(Ê vpAg´¨“ÁQè€IDATxÚì½{|ävyïÿYrÛ%‰½2!–iR9Àæ9¡L¸6š² ÚíјžÒž,e5@K·iÝJð;ì)KÛ3*nËžÑÒîBéh § qψ)LK2‚ë@H,’K¬µ³a7ðïï<’æ>¶Çžñøy¿^~ÙÖm¾ÒèÑ÷«çó}žgÛòòò2†a†a†a†a†a†a˜¦<­× `†a†a†a†a†a†éwXPa†a†a†a†a†a†i * Ã0 Ã0 Ã0 Ã0 Ã0 Ã0m`A…a†a†a†a†a†a¦ ,¨0 Ã0 Ã0 Ã0 Ã0 Ã0 ô†a†a†a†a†a†a˜6° Â0 Ã0 Ã0 Ã0 Ã0 Ã0 Ó†-)¨Ø¶ ×u{Ý ¦Bp]žç­ùX¾ïöí^Ÿ³JØ6ß÷Ú4Ûçæ‚íq°éă €ïûM÷w]·ézfã`[ ÖÚw6³W¶ÕÞÂöÙ_tó½à¾tÐ`{í/Vk¯úS~ݼ°].›Ý.·¤ â8dŸàyFGGaYÒé42™ÌšŽçû>Çéõi1«„msócš&&&&Ú4Ûçæ‚íq°éÄ-Ëj8ȵm;´ó‰‰‰M=ØV7?Ýè;Ù+ÛjïaûìºýÞ p_:h°½ö«µ×fý)¿‡n^Ø.—Ín—[RPaú‡t: Ã0P(P*•àºî¦6(†ÙÊø¾˲P*•B›¶m»k³†ÙlÛF:†eY ×›¦‰|>B¡€B¡€L&ókf•¬µïle¯l« ±ÑïÜ—2ÌêY½ò»(Ã0É–TÇÁèè(¶mÛ†L&ƒ Âu¤|ŒŒÀ4M˜¦YõÀõ<étÛ¶mÃÄÄDøO¥R°m###mÛ0M###­RPW²m;èXñ6·ZÞéñFFFÂvÔ.k´M§Çlu¾®ë"†$ óóóÐ4­å9yž~WtÌf3zh»•îÇl ­lØ\öÙÊ»eŸØk§Çku®ØJ£s¢ïO’¤ð·,Ëuß+ÿNÙ6{ÏZì±™-[Ç׫¯\­=®Ô®âý¥¢(ÐuŠ¢Ômçº.$I‚ªªá¶Š¢ð̱ „ûÎÎŽÙ­¾³ÓóÝ输hf¯l«½ûÒÎŽ¹Ñ}i»÷ÎfçÄ}é`Ã~¢öÇÛè¾X½Ÿh%ý)û‰ú¶ËöÇë…ÿ¶lIÿíò€3??¿ `9›Í.////†± `Ù0Œå………eI’–óùüò²®ëË– …Âòòòr¸žö- Ë’$…Ç4 cyyyy9›ÍÖ}†ªªaV²m;,뺾¼°°°\*•–%IZ. M—wr[Ù`·ì³{mw¼Nε[ivNº®/kš¶œËå–5M«º~Íì“m³÷¬Å[ÙâòòÊll3Ûãzõ•«µG˲Zîת¿$TU ÛHd³Ùºï¡ÑvÌúÀ}çÆ÷žïF÷µÔÚ!ÛêÆÃ}iÿö¥íÞ;›÷¥ƒ û‰Ú¯}éòòêýDËËËMûSömØ.Û¯WþÛvv²ý·/¨†±¬ëzÕ2Y–— èÈÐÍG_P.—[V¥j_]×C£&苎ÿ_knÛUFk´¼“ãÑ@½Ù²FÛ´;f'çKב:Hú?þâÐèœÈ}Ït|]×—%IªÚ¿Õ~ÌÆÓÊ6———7}¶²ÁnÙg'öÚîxœk'¶Òìœ Ã¿GY–«öifŸl›½g-öØÊ——Wfc›Ù׫¯\­=Z–Õr¿Výeü8µÎF/ñï›Y_¸ïÜø¾³ÓóÝè¾³–Z{e[Ýx¸/íß¾´Ý{g³sâ¾tpa?Qûãõ¢/¥ïf5~"Ú·QÊ~¢ÍÛeûãõÊÛÎN¶¢ÿvàS~yž†ü²,!ñÜÚí|߇çyضm[øÓ!Fµíl·¼t=Z-k´M7eù|ªª"›ÍB×õªkÜìœjC§%I sÎÆÃÚjóe¶ÚÙXZÙ&°9í³• vË>;±×nЉ­ÔžÓ­·Þ ÇqP*•Íf1??ÏóªrG7³O¶ÍÞ²{ìG[¬mãJÖµ¢=®W_¹{ìd¿VýåJ®ÛêÆÁ}ggl•¾³l«÷¥Ñ«¾´Ý{g³sâ¾t0a?Q{zÕ—ÒqWê'²m»eÊ~¢þ‡í²=½ôß¶³“­æ¿xA¥QÎÒ8­¾ Êkº,"yŸl6ÛëÓTU­3¸N*µß[<¯¢¢(Èår0 £.çb«ý˜¥mlŸ½d5¶òàƒB–å*;VUµ#ûdÛì-k±G¶ÅõgµöÑn¿Výe3EixÜõ¸3ÕpßÙßltßÙ ¶Õ‡ûÒþe½Þ;¶ÏÍ û‰ú—ÕÚ«ïû-ûSöõ?l—ýÍz¼“nf»xAE–eض^xÏóBLÓ´°à€º‚=š¦Áó¼P% ‚£££U™ÕCÉøõu§£¤ïûá÷EûQQ?ê@ À,ËU3üZíÇl,­l`ûì5«±•«¯¾¾ï‡ßíÔ6³O¶ÍÞ²{d[\VkíökÕ_6ƒ^Lã }߯*ìˬÜwö7Ýw¶‚muãá¾´Y¯÷N€ís³Â~¢þeµöJû5ëOÙOÔÿ°]ö7ëñNº™íòì^7`½Ñužçatt4|ÀÒ@EQhš†‰‰ Ȳ\§vɲ Ã0J¥Â}UUåN—$ ÙlPU5¼¾º®·ÝW–ed2ȲÎD0 £î¡Jǧï¬Ù~ÌÆÓÊ6¶Ï^³[yÅ+^‡~¸ê;U¥é~dŸ—_~9ÛfY‹=²-®?«µ•ìï/ÛÍËf³H§ÓPžç!›Í®:lYÜwö7Ùw²­öÜ—ö/ëñÞÙ¶ÏÍû‰ú—ÕÚ+9Üõ§ì'Ú°]ö7Ý~'Ýìv¹­Ræz´XÛõ]m¸W?…‰muš=Ù>7ƒ½Ç÷[)½°i¦;¬Å7ÊÀö¸rÖîØùÓ[¸ï\ûñÖ똴ßJY¯ï„muãé÷¾t³ØÒz³ßƨlŸ½‡ýDk?f¿ù‰úÍΙ•Ãv¹öc®—]Ò¾›a¿õfË*e¹\.ÌÑ&Ë2òù|OÚB”Zµµ×Ç\6®†Õ*“ý¨h2Ídûìw{ßh[aÛìØ{×Fîó˜•À¶Ú»6²Í1íèûìw[ZÏc®¦ l×[~±U`sØV?ØêZ`;ß°]öÖ.7út3Øå–IùÅ0 Ã0 Ã0 Ã0 Ã0 Ã0 ³ZžÖë0 Ã0 Ã0 Ã0 Ã0 Ã0 Ãô;,¨0 Ã0 Ã0 Ã0 Ã0 Ã0 ô†a†a†a†a†a†a˜6° Â0 Ã0 Ã0 Ã0 Ã0 Ã0 ÓT†a†a†a†a†a†aÚÀ‚ Ã0 Ã0 Ã0 Ã0 Ã0 Ã0LÎîuÖÊ‹^ô"¼øÅ/îu3ÖÌÉ“'±}ûvlß¾½×MY3?ü0.¹ä’^7cÃÎãÀþýûñ«¿ú«½nr_ñîw¿_úÒ—põÕW÷º)kfPîé­øœ™››ÃwÜÑëæö/yÉKð¼ç=¯×ÍX3gΜÁ™3g°sçÎ^7eÍ Ês¦Óïdqq###øèG?Úë&÷×_=ÆÆÆzÝŒ5³ûœ~§Óï„Ƕùä'?‰#GŽàòË/ïuSÖÌV»§7<¶]?ÿó??¶ÉcÛþƒÇ¶k§ßǶýÞ—l†çB¿ÛûzŒm7\P)—Ë(—ËUËÆÇÇ144Tµ>‘H ‘H´=޹瞋£Gnôitééi$“I$“É^7eÍìÛ·o ¾“NÏczzz oíl3¾M'ö)Ë2î»ï¾-u/ô;[ñ9³oß¾^7µ+tÛ>———âž.‹(‹˜ššêuSÖÌ b+>gel tß>ážæ±mÿ±ǶÝöÛöûضßû’Íð\èw{_±í† *ÓÓÓ˜­ZvôèQ$“IÌÌÌ`zzããã8~ü8¦¦¦099Ùòxƒ2ØŸœœÄððp¯›ÑúÙÈ·âytJ+Û°bû¼âŠ+ðÜç>·×§Õå^àçÌæ¥Ûö9(}çøøxGƒøÍÀ ÜÓƒôtÊôô4fff0>>Žr¹Œ¡¡!;v CCCmmwá>§ÿ¤ï¤ZÙ&­ßªöÉ÷tÿ1(ßI§°}6fÆQƒrOÒwÒ)ÝöÛö;ýÞ—l†{pPì}%l¸ ²´´Ô´#œžžÆáÇ‘L&177‡½{÷"™L¶¼q.¸à‚>…u¡ßc%ôs(ßV=f B3g¶oßÞ리™õ°ÏíÛ·oúÐlfó’H$066†óÎ;¯×Mé*³³³aÚƒÉÉɶ¶Û Û2½dPƶqjmhß·6ƒÇ¶L¯ ±íùçŸßë¦t•nÙ'm™^2HcÛõôÛösfp_—±í†ÖP«š‰L&±gÏž0l¬–r¹Ü6Û\À/LÏH&“1 ¦•m6ëø:±Ï]»vmÉ\ŠLïB2™Ä‘#GzÝ”5³öI/ Ó ‰ž÷¼ç D fò8pår‡ªJƒÐÊv›Ác[¦— ÊØhn›Àêí“ǶL¯¤±-Ð}ûä±-ÓKilË~[fÐ[AeÃ#Tæææª–Qa±±±ºð¯ÅÅEžaÀ0@+ÛØ>¦—°}2LsÓM7!‘HÀuݪ—Åv¶Ë0ÌúÒÌ6¶O†é5lŸ ÓŸ°ß–a:cC•b±ˆ„9ùâ¹2“É$ÃQsss(—ËØ³gO¯¯à <­lÛ'Ãô¶O†é_fff°´´„Ý»w£X,†?år¹­í2 ³~´²M }ßÊ0ÌúÁöÉ0ý ûm¦364å×ää$æææ°wï^$ ?~“““a®Ì©©)8pããã8~ü8¦¦¦x&Ãlíl`ûd˜^ÁöÉ0ýK¹\F¹\ƾ}ûª–ïß¿SSSmm—a˜õ¡mvÒ·2 ³>°}2LÿÂ~[†éŒ TàСC˜›› ÃÂâ³ &''‘L&Q.—ëÖ1 ³¾´²M€í“az Û'Ãô'SSS˜ššjº¾í2 ³>´³M€í“azÛç``šfÕÿ²,CÓ4H’®×u²,7Üß¶mȲ UUžçÁq€$IÐu=<³±°ß–aڳႠ€–‹Ø ¦w´+&ÆöÉ0½ƒí“a6'\Àšaú¶O†é_Ø>û˲ (J(z¸® Ó4Q*• Ë2,Ë‚ªªMÇq ( TU…eY°, º®‡Ç²,+<³ñ°ß–aZÓA…a†a†a†a†a˜ÍI6› #L •JÁ¶md³ÙÇ4M …ªce2X–…\.×ëÓd†©cC‹Ò3 Ã0 Ã0 Ã0 Ã0 3Xt3šÄ0Œ0b¥Ó41::ŠmÛ¶!N#"mX*•ªÛöŸøLÓ„išÁèè(lÛîõåbfÃ* Ã0 Ã0 Ã0 Ã0 ÃtŒçyáß®ëÂu] …G×u¤ÓihšEQ iZSq†j­ H’F²d³YA×uë¶ SŠÍÏÏÃó<¤Óéª. Ã0+†a†a†a†a†é|߇ïû=mƒ$IP¥ézÇqê ŠY ¹\ªª†µS2™ TUE6›­ûüø5‘$ ù|¾ãs¡ôaªªB×u8ŽÃ‚ Ã0«‚†a†a†a†a†é|߯+6Y–[ *µ5TlÛF*•Š?KÓ4hšž{&“A:Æüü|Ývžçatt4Œ01 £mº±Úó$©*†af%° Â0 Ã0 Ã0 Ã0 Ã0}‚ªª›.zB–åG¨¸® Ó4Q*•ªŽcF]="›Í"›ÍÂu]ضL&Ó4ÕE´ÔFû¬&’†a†à¢ô Ã0 Ã0 Ã0 Ã0 Ã¬Š V•BK–exžWW$Þu݆Ç2M3ZTU…¦i¡X"IRØ@ÔO‰ *ñ³Ú¶2 áÂ0 Ã0 Ã0 Ã0 Ã0LÇÔFPÝ“Vëk#IdYF.—ƒiš°m’$…"H£ú(º®cbbaÚ.úLEQ ( &&&Â`”êK–ed2Ȳ ß÷Ã(†a˜ÕÀ‚ Ã0 Ã0 Ã0 Ã0 Ã0±¼¼¼¦õqaE×uèºFH’Ô´v‹,ËXXX·U%ŒL€R©®£×u!Ë2 …\×my|†a˜N`A…a†a†a†a†a˜ž±’\­¶]í:†a˜Ná* Ã0 Ã0 Ã0 Ã0 à ‘Â0L·á†a†a†a†a†aª­Â0 Ó-8B…a†a†a†a†a†a¦ «T–––P,177×ës`†a†a†a†a†a†YWV•òkzzGŽ$“Iìß¿ÄáÇ166Öësb†a†a†a†af0M³êY–¡i$I ×ëºY–îoÛ6dY‹Ä{žÇqˆš'º®‡Çb†é7V¡2;;‹™™=zG D•ÉÉIÜtÓMXZZêøXsssuÛ—Ëe‹E”Ëå^_†Ù²4²M€í“aú¶O†é?ÈþŠÅbÓul› ³ñ´²Íøz¶O†ÙxØ>77–eÁu]xžÏó`Û6FGGáû~¸žþn„ã8p]7Ü6•J…ë\×­:Ó;ØoË0Y± R,199‰d2Yµ|ÿþýH$8~üxGÇ)—˸馛ª¶Ÿ™™ÁÞ½{qäÈìÝ»333½¾> ³åhd›Û'ÃôlŸ ÓLOO‡öwðàAìÝ»7|ñdÛd˜ÞÑÊ6¶O†é%lŸƒA6›E¡P@¡P@©T‚¢(°m{ÅÇ1Mù|Ùl6<¦¦i°,«×§¸¥a¿-Ã4§gEé¦W°}.ÍÒ{­Ã0 ëzÃužçabbÛ¶mC:†çy ×MLL„iÄR©TE322¦,3M³J ‚©T AôúrööÛ2LsV,¨$“IÌÌÌÔ£Ÿ™™A¹\ÆøøxÛcLOOcll¬jÛb±ˆááá0òell cccMÃ?†é>l`ûd˜~€í“aúr¹Œd2YUCp÷îÝX\\dÛd˜ÒÊ6î;¦—°}v†ëº°m¾ïÃ4͆¿mÛ·‹ÿÝ­}ÚE›xž×uáº.LÓ„ëºMEV躎t:L&Û¶dY†¢(uÛú¾T*Ã0°¼¼ Y–‘N§Dbˆ¦iX^^†¦iÈd2ð}?LOV*•P(Âs—$©ê<ÇA[¾~ ûm¦5+TvïÞÉÉIìÝ»ÄñãÇ¡ª*¦§§155…¡¡¡–ûÏÍÍavv¶î!;77‡D"Qµlxx¸­ÒùðÃczzº×ב٢LOOãŽ;îèu3ºB3Û¤u«±Ï;C@™žP.—1==“'Oöº)]¡ÛöyòäILOOóà—é ÅbŽãàÑGíuSÖL2™ k ÀÒÒfgg‘H$xlËlJelÛÊ6Û2›Û>üðýnÊšYûı- ’$AUÕ†¿E ·‹ÿÝ­} qÇeY°,+ŒYMdG.—C.— ꩌŒŒ •JUEžÄ?SUUhš@¤£¿©Ð½aD”‹ªªa”J6› Ï‹ÎM×uxžÖkY(4Hc[`ýü¶ÉÂô‚™™™uÛž½š†Pz*B4>>Žd2ÙVLYZZÂpøðáºmi6BœZCmÄùçŸ_WÏ…a6Šd2‰'Nôºk¦•m«·Ï]»vuµÆ0݆fÎ4„o6ÖÃ>·oߎd2Ù‘3L·I$ÃøÃ^7¥«ÌÎÎbzz:'7ExlËô;ƒ2¶Sk›m™Ím¿úÕ¯öº)]¥[ö9ˆcÛxú,UUþn%xtcŸv‚J6› ·„ ‘J¥°°°°âóÕ4-F|ßG&“A:Æüü|Õv½RÛZo]GyEH’MÓà8t]‡ëº¡¸Ó)ƒ4¶]O¿íððp¯OÙ‚Œãßÿýß»~Ü *år333¸å–[¯SlÛÆØØX˜aqqsssnhXår¹* ´\p¿t2=#™LÄ,˜V¶966¶jûܵkWÛmf=B2™Ä‘#GzÝ”5³öI/ Ó ‰ž÷¼ç L½x–Ëe:t(´-Û2›‘AÛÍmX½}òØ–éƒ4¶ºoŸ<¶íââE§Pº°R©TuÃ0J¥:>‰?iBt’¾KUÕ0í—¦i+N÷5Hc[öÛ2ƒÆØØvíÚÕõã®8å—®ëÃ)kÚ±´´„#GŽàÈ‘#(—˸í¶ÛpÛm·all¬.ükqqq f0L?ÓÌ6°}2Laûd˜þ妛nB"‘€ëºU/‹l› Ó[šÙ&ÀöÉ0½†ísð‚ LǵdY†çyuõZ\×mx,?H¸q]ét:Œ4q]7U:m“¦ið<Žã„Q2[öÛ2L{V¡bÛv˜7¶Ñìˆ{î¹§é¾SSSUÿïÛ·û÷ï;PR@“É$æææP.—±gÏž^_#†xÚÙf2™dûd˜ÁöÉ0ýËÌÌ –––°{÷E‰D‚m“azH+Ûdûd˜ÞÂö98ÔF¨ª¦ßj¶¾P(T-“e¹\¦i¶mH’ "ù|¾î3©~Êèè(Eçyág*Š]×111®Ó4­­ BbŒçy+„ öÛ2Lg¬XP™ššª3°n155…`||Çï¨È=Ã0Û'Ãô/lŸ ÓÊå2Êå2öíÛWµ|ÿþýᘙm“a6žv¶ pßÉ0½‚ís0X^^^Óú¸°¢ëzX¿@X8¾¹\º®‡õTâ5U²Ù,t]‡ïûUëjÛS+ì4o˜zØ6F°bA%ÎÜÜÃ<î+åèÑ£UÿONN"™L¢\.‡³†Ùxjm`ûd˜~í“aú‡vØ6¦7t2 í“azÛ'ÓŒ•D‡´\jEfõ°ß–a³*AeffÓÓÓXZZ —% >|xÍEúØ ¦aûd˜þ…í“aú¶M†é_Ø>¦aûd˜þ„m“aVQ”¾X,bzzSSS¸óÎ;qÏ=÷„…Änºé¦^ŸÃ0 Ã0 Ã0 Ã0 Ã0 Ã0L×Yq„Êìì,&''199.K$8tèŠÅbXœˆa†a†a†a†a˜Á¶í°x|Y–¡ª*lÛ®*PÏ0 3H¬XPY\\lZpˆ 1 Ã0 Ã0 Ã0 Ã0Ìàâ8‚ €$Iuë|߇eY,¨0 €ï-Êm*V,¨$“I9r{ö쩪—233ƒr¹Œñññ^ŸÃ0 Ã0 Ã0 Ã0 Ã0ëD6›mZH~yy¹×ÍcfX–ømÑ2ßd¹z;Ï[(ây€ã¹\õ² âÏ$©ús=Oüß@¿í+®¡299‰d2‰½{÷bï޽طoTU ëªp” Ã0 Ã0 Ã0 Ã0 Ãl=<ÏC*•ª[6::Š‘‘˜¦ Ó4áy^¸.NcÛ¶m˜˜˜€ã8á~©T ¶mWíË0Ìʨ˜Zˆï®[½,ÄOÓ¬ßÎ4ÅþµËjeÛõm¨=¾ãˆíl[¬s]!ì4jGí9ôúQ°â8tè&''Q,±¸¸ˆÝ»wcÏž=,¦0 Ã0 Ã0 Ã0 Ã0Ì€ãÕz8!j¨A7æ… ‚©T ¹\ªªÂ4Mض UUÃu†a ŸÏÃu]¤Ói(ŠY–áº.dYF©T‚ïûH¥RPUµid Ã0ÕHQ(T/óýêÈYn,¼ÔF¨Ð¾µ$q<Èd¢ˆÇÛ»®X®iâoÚÄa ëb™e‰¿kÛ·Q¬JP€±±±ª”_ Ã0 Ã0 Ã0 Ã0 ì€S³¬€?²•õqG¦@Ží—P;‹[àWö«Ý¾ös”Ê1šà8N•pš¦A®ñpÚ¶ EQ išhV6 »â9u²,èäRUš¦UµÏf³$ Š¢@” LÏp]‘²ªŸÒG­'²\Ÿ¢‹ŠÚeÙ,J‰´_’ Tû$„ÈQ+¦ø¾ø ±E°¸ntÏmgÛb].'ÄE‰DmH¸Ñu±>S 0:~åÑÒºoWX• R,1;;‹C‡ˆê§èºÎQ* Ã0 Ã0 Ã0 Ã0 ³ZôÊO-±YæPZìÛh{t°ý ökVC¥Vd ‚ J‰²÷}žçaÛ¶mUû±BÒVñ|39ïu]8äu}íÇìꙌŽóóÑÿ¡"ËQŠ® !‚ÄËŠjœâûB¨ Ú*®+„M‹¶!ñ„Žë8b]>ƒdÒ’$„ztPÛ,K[Qª…jµƒRŽ)J$æØ¶8F¼>KüÜ_óšî_û *sssØ·o&''Ãe‰D333(‹¸å–[ºßJ†a†a†a†a†a6~mÑ… ’$AUU (? ³vH¨­ñ±Éd€R©úܨ> Õ!!Ós!BXV$@P¤‰,½C…áUUü¦ú&†ÕZ¡ÿéX¦Y_‡Å÷£ã`BÑ%¹œØ–ÒÙ¶ˆ¡ó"ñ„"fhËËâuY\7Š`¡E©¯÷Ò-V\”þ¶ÛnÃäädÉdÇŽÃÒÒŠÅâú´”a†a†a†a†a˜Mƒ¦ip]AÅó`Ñ4 žç…õX‚ ÀèèhUaz†é6”Vª_¡È‹vP”EpØvAâ8âãâ 'ñô\™L$J¨jY’ÏG‚„aˆ,šÕ?¡èZFâI>‰- ”ÍF5\EüMm2Œh‚"PTU¬—eq\`²Ùè|¨í´ž¾WªÑ vë*+ŽP)—ËH$uˇ††8ÝÃ0 Ã0 Ã0 Ã0 à 8©TªáòÚhªŸ211­'¨~J*•‚¢(ð}?¬£Â0ëÕ‰§·ê7(º"žŽÌ4£ú!d¤;ÆSI’X®iQ¤íG†+È„³ÙH˜P”(õm[•V,ˆêÏP1E‰ö*ûŸŸK)½H¬¡ý:V\øÐõÆuQ(ÅmkšÕ5XèZXVT¯%“ÞÿþîG+TÆÇÇ133ƒÉÉÉ*aevvsss ņa†a†a†a†a6?íRt-//‡A]סë:‚ €ªªØ¶m[XWÅ0 hšß÷ÃâóŽÓÉç2L+\Wˆ ¹œˆ’èGA…"KjKÑ2ŠB©MëE‘ªý­ëQª/ÚVÓÄ6¦)~A}G\@©+“”Ž"]€HŒ±íè8š`P"ѨRZQ'¦8T±¼­¥’ø\j#¥4£¨Z÷·û‹¸âŠÇºú=­XPÙ¿?Êå2TUE2™,..bnn‡bA…a†a†a†a†aA€T*…|>EQ`š&TU­*6/Ë2äN½­ ³è¶“$!*ô›F@©Åu#Á„ÒbQ”ЦE‘)T§DQ¢º#$ªÄ#9€êš']@ ÿ@‹EÏHRƒëX9nK³¢c¶Ä®lS#îP}—0bæ¯ÅõÉf£ïWQ€o~ó\xá]ýžV,¨À¡C‡099‰Ûn» 0<<ŒÃ‡³˜Â0 Ã0 Ã0 Ã0 Ã0 !–är9X–þŸÏç{Ý,f‹Rq±Pm”Ví(=—㈔\Ùleâ8b *”ÖŠêP‘yE‰D@ü–ˆ’Ìϯð$@»©ƒí±mK±Äàȶ>ÔÒÒÎý§s±]Ý^·î9Ïù,ÞøÆ7´1¯‹DœßüÍGpûíßÇUWI¸ð§Vù­5¦#Aeff333سgvïÞD"±±1Œuµ1 Ã0 Ã0 Ã0 Ã0 à š¦q]¦çضˆØ 6ú–´ízA…"D(Ú"“‰Š¶g2bª‘"IBD¡Bó†!–Ññ CC– (q¨®Éªpè-Ö{±ŸVŸá#ŠRiÁ§†>…7^ùFlÇöÊ5 à8|߇ïû8ÿü' i¼ΧýwÓ4!I^ñŠËqùågØÕ•ïèHP™œœÄž={P,qäÈ”ËeŒaÏž=«Uæææ°¸¸ˆáááºýËårXøž#^fcie›Û'Ãô¶O†éo–––°¸¸Xed—qÆÇÇ144Ôëæ2Ì–¡‘mlŸ Ó°}n~ÇWÉDÅç×Ó4«þ—eš¦U¥3Mº®·L!æº.\×mºçyp*¹”$I‚®ëUŸ1è ‚ß6"±B–…áûÕBÃFÖP¡#Ô&Ç©®’ÍV—Ÿ˜ˆêx^$¦PJ/*,¯6HƒUUD¾ ²Ü:½XKÚ *€ˆPi'¨À“÷<‰_KÿTU…®×4“ÉàÐÇðÔìSÀo‹gŽmÛÈf³PU²,ò,X–ã^òÏ#¬Ç<ÏÅ+^ñ ôDP€¡¡!ìÞ½»wï ŠÐÏÌ̬X\9xð ŠÅ"‰Êå2’É$:@DÂLOOc||ÇÇÔÔ&''»z Ã4¦•mlŸ ÓKØ>¦ÿ±m055.›žžÆììlÕvG ë2 ³þ4²M€í“aú¶ÏÍ ÕE ‚ QLÓ„eYÈårU…廉eYP%7\×…iš(•J¡0bYVèhmu×u!IŒšŠÜäœ%ç®ëº°,«ê3™AñÛú¾(Pîy"%–ëÖ‹TGd# b陌ÿùÏchh(,n?99‰±±1LOOãðáÃH&“˜››ÃÞ½{‘L&ûZñd˜A m`ûd˜ÁöÉ0ýÍÌÌ ŠÅ"fgg±ÿþªuKKKìb˜ÑÊ6¶O†é%lŸ›Ÿt: EQ‹åOÊf³Èd2Èd2(•JëöÙ43H¥RáŒõNð}®ë†ÎÖZAÅ4M …ªÏÈd2¡X4È ’ß6„@!IB´p!¬l$¶- ªcBµP²Ù(ºdb"j3 *$þP¡y ªwÞ†. @+ϯlWƒÑNˆi†Ài³0‰¯š¦Áu]bÕë>ÿa¼íþ·áãþÇÃô]’$Á¶mäóùHÀT€o|àðf<¼áƒo¨‹SUªªâô—Oã¬oUe§²,caa¡ ßf5OëÆAÆÆÆ055…[n¹¥e”J¹\Æääd¦I·¸¸ˆb±ˆááá°Ã¤-Åb±ë'Í0L5­lÛ'Ãô¶O†éoÆÇÇ«Î84»a˜§•mlŸ ÓKØ>77žçÁu݆F6›…ïû°, ¦iÂ4MŒŒŒ`tt4ŒHŠ'NcÛ¶m˜˜˜Sl‘H2::Š‘‘‘ºT_qV5â8N˜^Èó<øä}2 £a:¢Acü¶®+J¥¥ª‘X±ÔÞ¢¾-ó¼è³©`|-$¦ÈBHi{ÛueÒà¼ë Õ[•Ÿ6,¨ BT‰aÛ6ÇA&“ í鮥»M*Ùlžç!›Í¶í0ZåÛÛ/Û]בÍfá8\×­03›¿}3~÷ ¿ÛÜÞ}`ÇoìÀEoº¨J@R¿ò+¿²²/³V¡R,Cã„r9== UZAQ-KKK8~ü8ŠÅ"ÆÆÆL&qäÈ‘ºsxx¸.of-§NB±Xä™ LO(‹8qâD¯›±fZÙ& l}5öyâÄ ÌÍÍ­ªÖ캗Ϝ9Ó리™õ°Ï3g΄/ªü²Êl4årwß}7žxâ‰^7¥+P7<<\µ|ii @”6ahh¨£´<¶ezÉ Œmæ¶ ¬Þ>ylËô ž:uª×Mé ݶOÛn,$H4ª)"IEÁ׿þuÌÌÌ@×uÌÏχâ‰,ËPU5œµnòù<\× £^dY†ëºe¥R ¾ï#•J…#^,OÕB‰Ïzï¤ýT;EQ”º(]בN§¡iZX¦•h3HcÛõôÛnt$ª3B7ªÒ­ÌtŽ¥ôR™bYQtL£È“8º.¢TâP¯xÅÃH§ŸÛ:ºB‚ˆi'º#r›m:œFNŽ`é5Kò†EØ#€7 ¾ïã[ßÿþþÔßã×þê×ðÿ aTY&“çyð<²,Ã7Di“JÛ¨R#{+•JÀh‹s¥s4P%2ÍÍÍ­ËØ¶ã•ƒbß¾}¡¡”ËeÜtÓMDg8;;‹tt¬r¹Œ#GŽ`vv6|Y¤™¶q:é{ì±¾UC™Ág^:ƶ ¬Þ>Oœ8ãÇ÷ú´˜-Í A…è¦}ÒKg»Á/ìårsssxüñÇ{Ý”u?Ïd2‰ýû÷ãž{îÁáÇ1==ÝvÜÊc[¦— ÚØ¶«µOÛ2½‚ƶ=öX¯›²î¬Æ>ylÛ_Ð"Ir¹$I #B( ÅqáP­x¼UU…¦iUQ,Ùl6hâuÇ ëœ¸AGm#g.Õ}©ýLÈåraÊ Ë²022‚T*U%äÄıízømí¿žPIâF#MLUW~ÜZ\W(Š">3¿s9!žØ¶UÚ¥ØÒõêö|ë[ á}G!!D„V¸Ð>«í6Žã ¥¦pǧî„uˆJ¥æçç¡ë:\×E⇠¼ãìw`ôä(ÌLºcJ¥r¹\uª½Ê)’ Ú쳟L~üøºŒm;ŠP¡zñ”^³³³ÆáÇ144„ÉÉI¨ªŠr¹ÜÖ ÆÆÆpôèQ,--aïÞ½H$ g&PÁûV\rÉ%m#cf½˜šš £´F¶999¹jû¼þúëû¶@3Ø$ LMMann®×MéÝ´Ï;wrßÉô z)tÑ€l6~Þ{öìi}Âc[¦— ÚØ¶«µOÛ2½bǶÍX}äØÖ¶Å´÷8µQ¦Y]U»6—çÕç!ªÍ!ÔÉçÔ IRK#<ãϨ+L/IRèö}žçaÛ¶mUÛĬR“ŠÙµ5TlÛF*•ê¨N‚ã8$ ét:l+µ%Þ^MÓBÑÅ÷}d2¤ÓiÌS‹ƒ8¶4¿íü|ãì©°¼¼¶c;ŽBt=ŠJ¡Û8Ä2*B/ùl±H­TÝÓ€¸ï ÀëºU÷f0Mº®C³4 ]p–„΄BˆÈ¢Î(¢Äó<üýÒßcHÂï{G(ùXqß÷1S˜•²€=*×—Ry5lŸ‡º4bU¸@ÆËàÜKÎŽ7ж†×_¤›ý“Y\/_(˜œœ\±½#Aå¶ÛnC2™¬2’b±ˆÝ»wWåÕK$-•™™,--…Edž††066Î@˜™™©Ú~qq‘Ã5fhe›€èLÙ>¦7°}2Ìæ¤\.cii©jü¼‘i†iÛ'Ãô/lŸt½}ñ„vEØ¥­8ÒÑçÔ iLÓ¬sºQÁ÷|ä#u}\„¡¨••¤êj†,ËG¨Pº¯¸c×4M8ŽEQàº.LÓé…bÇ7 ©TjÍmíwÅoÕè›elëFÊ/ÃÇ÷n¬E…ã¡_jÂbëðëUÓ4¡(JC±RÒÅ¡«0rÅE•ÀPG¥8|G*’ˆÊ¢Ï„`Iu“æççqúe§±mb>øß>ØP`Ìçó¢M.„¸Q1ÍT*]×Ãè/Ó4‘EVlÓ®v‹ (P0wïÞèV *ôzò‚'ËèK¿&&& Ë2®¿þú5ϵtœò«Ö@(ÿ]œN:92N@䯤ÜïÉd2 cDTL¹\Æž={º~Ò ÃÔÓÌ6°}2Laûd˜ÍG±XĪlwvv¶/_:f«ÁöÉ0ý ÛgÿCC¼5 œÆétº®ãª«® Å@ˆ)T{@èާì­s·£ö¸­p]7œõ¯ªjø£iZø¹4 ¿6 XÓÙõÈ øm=O_µ#¦›uLT‡‘Φi¾‰7$ÚÕFŠø¾FH5BUÕІ¢sÑ"¾ïcxìØcííFFUª,Šêˆó¥÷| Ÿxú'ðüóŸ ªêår¹P<Ù±còù<Þö/okxž£££xðÁ+ ¢ÆKå\è<=ÏÂŽÖbP…®ð×gýu]$‹çy˜zä$>sðžÊS©-#IRÕ3ª›t¡2<<ŒÛn»-üvvªÂ-ÉÈ…€“““˜ ÃÅŽ?Ž={ö„aÓSSS8pàÆÇÇqüøqLMMmÍ™ ³Á´³M€í“azÛ'ÃlN&''177We»“““œ.ˆaú¶O†é_Ø>7Ùl6tž*ŠI’àº. Àa¡Ó7“É„ÎßxÍ”xÔ‡¢(ð}?7ÚQ)¢ª*²5Ñ:¶‘e9,z‡"nH4Éår0M¶mW9dãi•AñÛz^ã_µ¤R탸j±í¨fŠ$ůy° º¢HTŒ zf%E_ü~ŽÛëñÇÇ%—\‚÷?ø~üÛÃÿ†ÿóáÿSe;žçáßþíßðk¿ök Èð#Ñ3‚ªûÙó<\ñóW ñÏ <öÃÇBñÐ0Œ0R%AÂŽ`?ˆÚæyTUÅ׿ŽS—ŸÂ}¶øgØU×#€lAE×5C$úüÏÒÿ„’ª¬L˜"SÞ~×]Ø~å•xä%{ñ3ÿŠ— <ü{C~Ž\'Hu‹Ž•Ý»wömË`rrÉd2LÆ3fãhe›Û'Ãô¶O†éâùÞ‰C‡µ´]†aÖŸF¶ °}2L?Àö¹¹Éf³¡xÁ!.VȲŒB¡®®Mf4M Ó!Å×/×¶ Ô`˼èd›8²,Wí£ëzX\@ö2ƒà·Õ´Î•Õàº"ÍWˆŸªbó>D4"ñ¢T*…÷ø©ò)\à]Ûá3A@Ó4¸®[±¸jé*B ´m†a@’$|âŸÀßýÝß!™Lâ’?¼÷\p®~ôêª6J’„øÃ¸ýöÛqøã›ñM¼øG/†÷çòù<‚ @:F>Ÿ…ÏcaüòqÀž¯>™L?þññÞ÷¾²,‡Ñ*Y­"öÈ< c Ñ4—ËÁ÷}躎ù[çqæ¡3øÜ½ŸÃ{Þ *²,Çq Ë2Nù4v¨;„ âG5Hdõ<AààyÃs{üåã<÷Üч¶]úÙ fÐi'ˆ²}2Lï`ûd˜ÍI;Ûe¦w°}2LÿÂö¹9 Z(­hµ^–åpv{¿±UR|5b³ûm3™•Gž4ò¢ÈÇ|?*@ïºÕµZ₊eYð}_DuÈ2EÁw¿û]\‹kC!Òó<är9H’F­8ŽøÀ5ß¼€ˆ ²mø›¿ùœsÎ9xå+_ XÈ.à¥êKqï?Þ6ê-..âŽ;îÀÃ×?Œ¥¥%|ù_ÆÿûNhŸ‘1Éd¦iBUU!¬Ør(’Â6MÓÄÞð†°FQLª“á9Ò>ªªâïßý÷xò©'¡MjX˜YÀ×ܯ…ë3™LMsÿã÷ã¹òs+ °U–e…uV(MØÇ†>EQJ/+á‘ï?(ÿÅ_ 0:žûSü ~ó'?ÁïÛ6þëåÿ¿ðûqÎOŠ ¿úUàÆ»zu$¨Â˜…ÉŒãèÑ£U鿆a†a†a†a†Ùzlµ¨¦p]9Ò ã|¹\®ë†EåE,ËøÚ¿| ßú. ÃÀÈÈôŠRC®ëp'NœÀyç@ˆÙlwÝuÞùÎwâiO«.‡¾ô¦%|âÏ>ßÅï†Ñš¦áöÛoÇ9眃OúÓ¸ôáKqçkïÄö˶bÏÒÒt]LJ>ô!\ýõ}§~îû·Çpnp.‚ …JÉç8àüàñ`R™ Å"Ó4!Ë2$IÂ÷N~çŸ>TUÅ-'oÁKN½Š¢@Ó´°v‘išØö½m¡_¤Óu=nHl½á/nÀ“o2Œ€»ú¿_ Ã0ðÚJäÎcA€G¯~÷]v¾rÍ[à ¸îºë0’ú_øêwÿWÜuW×ﳎ‹Ò—Ëea·m’/arr2T(Zƒ¢.EÁ対O›|ˆZ=RG¿çyxÎkŸƒ/út]G*•‚eY(‹U" ¨¾Š]ã»pÑÒEa×uáû> ÃÀ³žõ,H²„{÷à=G߃\ð¤Ói躎K/½4¬UR(°´´„œûG|úmŸÆÓÞÿ4AUUÃóQU’$á¶ÿóüúë_×]úcl¿ýt&Ër(ö\ðï`üéã€û®¸C÷U_tËÂ…O=…'Ÿ|¾ïÃu]üçGþŸþ…O‡"T\ĹâŠ+ª„›Ç„äJ(•JáañÔ…ObU¡PÀÎ?܉«î¸·ÿû]¿Ç:JùU,Q.—qçw†…èUUÅÌÌLXK…ÙX–Èù7?ßë–0 ìŒx¨,Ã0 Ã0Ý#•ïëUÀ•a†af#XI`”ç ÿ~3·?tèåxüñÇëÖ“B’$üÌ­?ƒóþÇyçdxžŠ ñ:AGû(`h!ø¼ò•¯ÄGf?‚_þܨß]×Ã%µÌSß} Žãà»ãßÅ_+ MÓ0::ŠB¥€Ì_ýÕ_ác7| gÿçÙ€\ÑõaÊ-Û¶ˆH¸öÿ]‹cò1Hž„‘¿†éhâóSCC¸ñL gÿí7°°°€?ê/ i¿ EQªÄ8 ;pß[ï¨,H§ ÀOÿæopzïi¼û-oGùÔ)|äÿûF¾0HÅ¡ZdYFxáîï·\hr¸üÞûïÅÙ¯8˜«®ítΟŸüðƒü «÷YÇ5T’Éd(¦ÀîÝ»»Úfíø¾øiU7ËuÛ‡¾¹®øVö Ú(§}X]IâC†ég|ßo(˜¦†ÉʲÎZ$) yUU5,àÖ踎ãà‰'žèõ)2 Ã0L×Éd:OgÑ ßÑë4^ö<ññ…/\ÎèÌ0 Ã0ÌfÄq:PQ”êz+qá"ĸ(œwÞ \}õ?xOÕþT÷$ôi¤…sŸRoA¦ò ñ¸€å[Ðu=ôoAÏó°°°€›¯½—~íÒp©‰cs$3‚À ðο'?}Ö²MÓÂöH’„îÀS²ˆÜ8묳Ífáºnx®a­#  ç½ù<È'Ä1ÂÔ}££xͧ À÷à#ÀÒÓž†Ýq J ö—G(S œÒ»nÝ…+/¸Rü“ËŠ‚€Ä¯øˆ}¾ûÂâú³în€I’ªR›!‹°­ßø‡Àyoy ðžHÀ‘eK·,áœSçÔ_$xík_ÛÍ[ À R~1ý‹iŠ—*Ç(Í P6*ªÔÏbŠªF¢ÊFÒ®p”ï 1³UXaÛ­¯Gtv†aºeY°, étºj¹mÛEÈf³‚¶mÃ÷ý0l³T*a~~²,‡ùJ Ó4‘N§‘J¥ŠÅb¯O•a†aºN¬ë[5é´x ±? þ¾÷ÞË{}z Ã0LŸcšf8ý˲ªÖ™¦΂'‚ 'Ñ5ZÏ0«e%iL©À<ñ®wÁ»Þu€kù¾(:ÿ«¿úE\rÉíuûWM•ø¨J}%IRõR@8ùù“áþ¶mí8`UUÅ£>ŠKO\Š{‡îâK+aK;žµO}õ)Ø•"íq2V–]qŽêâ—Sœ‰5¯;ñºêH¶-.Öd`HW¼øÅxù^|ÚNi׿°tÕ®zà*úðhůK¸ìøq¼ò÷~O\ìmàˆë *'jkâÿXˆ2Ÿ“ª®Ï3Ÿ³m7r—‡ß¼÷^<ëYÏêüÆèT6 ÍA… éz{A¢P¨W`é8¦)~.ËWK\´!a¨Ù98ŽØ¾PhüéyÀè¨ø×£öm[|NˆÏªDš1 ³AP%vÐ,ˆL&×uašf8ƒÖ[–…R©„\.EQËåP*•ÏçÃMI’ I²Ùlªêº.&&&ˆÔ|>l6‹$O±e†a wâ{ÊdÄ£tZŒŸ©[Îd€RI¼:ŽˆJ—e1V~õ«ïèõ)2 Ã0}ŽeY0M³n¹ïû0M³ê=в¬*Á$‚pœ¢(uëf-t’цpÝêñÔ'?ù3øÆ7^Çî¸ã'Qœýƶn_ʨâÈ‹óÙfé~L6P*” ª*Ç  JSuå•Wbaa_ºøK@;¥+"HN\zß¾õÛ3xÈ⋜&/ñë2bBe‰b2µ¨J²p¬ærbp ˆˆ5ºN·Ÿ{;v=´«ñõeñ¥e³ÀÝ%@ç$˕㢠ª’$Ä9¶¼Â½÷Þ[ÿÏ•qùwéô–蘎S~?~ûöí ÿ§‚ôsssUÛ=z´ëdÒiáøo•¦Ëó„h±°P½<Är]ï,5W*%îíÚзL&Êèy‘è"IQ*ÓŸ“J‰Ï¢uô{5¨1?/>×óÄçRº@|.½Üâï|>j¥' å8ŸÇ ˆ$QT»eE"T&#öcfuÐ €ø, šyDù.E szÒ`Û²,(Š‚|>ß4œµº®‡Ñ.$°Ä9÷Üs{}y†a¦«Ð8·“IA4N¦˜¦)þ§±&§-KóMozÀ®ög†a¶4²,ÃqœªÔñø'ðs?ý9\©\ÙÔVNŸ>Ÿ^ñÓÖÇ«ŒE÷óÔ/©Ø¥6¿¹â†\ùqP-ž„/ö·Rù_F4“_–…07[©ò“ÍW‹6¦øÌ‰ÑQX_û=u -MŠ6·ú~$J[ Zß™ŒÊE‚È®¡NpzôÑGgÔóR Ï|ð™xøž €.ηíHPÆøøxÕ²D"ѽVla‚ yn?LTµ~›¸˜Ĥ(r¼°EgуŶÅ1)ê#^¤>ÿëz$¨PAË,+0V“r€DU*“Êa¢}ÔæJÍ#hZ˜b/DU£—>Û"Pü9?EÖ”J MņaC5LôšÐ/L(Ç¥¢(Èd20 # 5%¥Ñ`AUUX–Ã0êŽÝ)ªªÂó¼úÁ Ã0 à (4NnõAã[]RZçóÕ5i‚MjÊå€è¼ Ã0ÌÖEÓ4¸®['¨ÐòZXLaÖß㙕D©ï}ï¼øÅŠï|ç üá.à‹_ü*^ô"ATMú´*µlÛÆBíÌ÷J}Ô¸&LÓ„®ëXºk =‚í—moÚI’ð!åC"¢£ÕöXt†®ëí£YPi—Ûþxáÿ*Ä`‘D ¯²|R¿VY^ëS½×ÃNËÄí—\‚‡^ùJŒ¤Ê؉ÕÛ´Cƒ}hýŸ™ÀU6ŒGÉH•í*×úGÃ?Âéí§ëýBðÓ³~ŠSלêàuNG‚ÊØØGž¬¤œºncc÷¼H0!Q@–ÅïTJÜGµþÇ\.Jiˆ—%ãŸAÑ!ñAÈr$ºÈr”ŒJFÑ$aVÐ\nÔ^ªƒR(T?ì‚—¾ô7±mÛPuaôº®C×õÆéµjð}?ü¹arr—¾,Š©A–e¼uæ­øèäGÃÚ!!Am"dÐÉdrI:A‡ˆH‰_ª=>ð?LàçÜZiÒÒUKb»¸ùo°\s<‘8¤i@Ö>êÖ§v¢h›Ê3ê¾+îÃéí§ëÛgyp²3:NùE”Ëe‹Å0åW"‘Àž={044ÔõÆ :”¦ª‘zJÅÔI|£( ŠÈh$PÄ ÕS™˜ÛkZõ½GomçXGQ#µÔîçyâó( ƲDû2ñÙTç…ÎM’¢sˆŸ‡¢ˆŽ›fÓ5›u'Ë­…”ZZDœBÓ„ÀÃ0Lc\×…çyÈf³H§Óá` ›ÍB×õpÑ«±Ñ(—'Ã0 à (4a(“?”Ž×²¢q<#B+âï J»p†afèÍFBb3º›=·ãû hK»Ïi¥<¢¨”Úô_q(‹MÔ[mv†iÅJKèzTRÀqÞ E)áî»ÿ ÿþïÏ‚,Ë-Ó×ÕM -@±6Pj°\.‡t:ÉgLâ­7¼°ÑTP©¢ÕzÕâD=Òn<‹êhyìF‚ŠÜd_¯æ|î‘?/ˆãTTàÓ—n‡Ò~Q&¥·f7i´q-eà%ßx î½üÞ†‡œyÛ[»™í À •ééi9rCCCa °#GŽ`zzº®cÿþý]nÞàBaú†Q_pžÖÅ;0Št"¡¢Y´…¢D*‰ñ°þFÛÕR+p4¢¶¤Ô[$öضX&J"ÂÅ4E;\WÌ–k6¡¼Yj®õ‚®S:½òdw†³ˆ¨¨ ‰§Ža†a˜Þ@cê\.ª3H5:ççW6–e…a†Y ªª†i¿ÇA.—CРÈ¥„–e™LªªŠ¢Ó ÓE:IçŸJ¥Íf¡( ~ï÷¾ƒ“'¿E9ž'vT¾ï7̤áyMÂ6iˆè _øR¨Î+ùN²Ù,.ºå¢¨Ž¥ÔjÀm¯¼Mü‘Góº#µé·T4NV;ÁFAëTb„àbHHÑ€1h²o¼æ *íjô=5Û5vHÐQ\¥¯l¦W®{ØõЮ¦‚Êzð´N7œžžÆÌÌ :„;ï¼GÅÑ£GqçwB×õPla:#^²*T_çºQdÇJ^|(_r§èúÊs ªªx±Ëf…@dš¢óóâJFÅ. …Ö/y½êSeYDôPz5†ÙJxž‡L&ƒL&ƒ ày&&&N§¡ªj83CUUS†a¦‡ÄýTº.Ư”¾6ž¾—a†aÖRâé¾AË5MƒªªÈd2½n:3€tâÓ$œ<ù=œ8q™L¦êÞmV£5¾oðío[º+q߉¢(¸ü'— QBGË(‘Üóñ‡!ltB³¨Õ‘!R´]Uj¾ÚÄ€ÿYóáÍ•,ªk¸4«ç¢@D”´£U­—8±ˆ™÷ÿÂûqß÷ux±ÖNG‚ÊÜÜŽ9‚cÇŽarr²jÝÐÐöïß©©)Øv'W…„@B"ãÙemôc'Q#Ý`¥ å\¦}u½q¤G.×ßuJ²Y`aAˆ@Ž#„!g%ù f“Bùl5Mƒ,ËH¥RH§ÓÈç󘟟G¶Ÿ —a†aŒ¦“+é|)Å/‘Ï÷÷›a†\(íW&“išî«–\.ß÷ÃâÞ Ó-,«ù8Šð<~eõ9çüþ꯮¨ŠHQ¥:%ÀC•àR]uÿ3îÇo=ú[¸ñ~œ>|étºqjòŠà@M8û•„R­¢Ia¦ê䉦)fŒŸôë÷ ^ƒPô©-… ºÀ£èÜ m¢ZH‘£ë]õÙNl»fŒ¸ Òè<ãèÀ•½™Oo¬HÛ‘ R,‘L&166Öt›ýû÷cii ÅbqCO`3BÑ$¦ÔFC6*C@bE¿:øk‹ÙËrãm6”wš ´Ñ÷ÃQ+ÌfƶmLLLÀuݺ”ÏVUU†MÓP*•Zæ e†a¦{¸®øñý¨"?i9ùªâ“–¸»f†azI<íW'PM Ó4Cgk*•¶mÛŸT¥îÃtŠï7.yÇó<(Š"î;˜¼ªª†)À‘š«J PW¾VP¹â§WàÃoù0îûÑ}8û?ÎF>ŸoÜT$4JdYÆéÓ§E{ÔGŽ„'ƒúhŠR¡: ª ”Íêº**-TÂs‰o¢PßY¹æÑ&µP=:VUð€W½¹¤šùYãµZgͶ»Š»páS6Ýä×îð$:§£*‹‹‹,™ìv‰—ÁÃóÄOÜö\WÜ«TRdÅ‘e!ÄlQb3àº.Çã8( UÎãlV8™o½u/xÁ ðªW]ˆ\îÚ†ß ÃllÛ†¦iá}?_¹™iVP|ÀÀEÞ†afc±¬¨|¡ Þam[ˆ%®+Þr¹•G’3 Ã0Ìz°¼¼þ­ëzÕŒ~UU«Ò%Å·oCË­g˜•àûŸÚh‚zœ  ª*Çà¹'ž  „¢*Zøc?úþ⪮‚ócúé‡ðYé³7t!„¹òÓ >Ê5_Œ‹q+F¾w™X`BŸïÄ,U># éøŒ)„ ryú>ðƯ~Ñ««÷G;û¾H?ÈâÜõØñ›µƒê™ÕÛÄÓLJ×ÓƒVZEÉÑAœ÷9¿u.xïMןٱ£ƒ‹·2:T†‡‡;UŠÅbG…éËå2Êå2€z†Ö% $‰®Ÿp/ñ¼èžŒãûb–Y&ÓZ0Ñ4Ž’è” AÃ"g®ëB’$˜¦ Ã0 ( Ç뺂 ü­iLsþð¾úÕÛ°°pmxìL&[;}út¯O·k´²ÍøúA´ÏAÂuÝp–,Ëa$Ð}.IlÛF©Têu“™`ûd˜þfii ‹‹‹uöǶÉ4¶ŻA¼°¼ª ñ$›¬‚@¼#øá‰U«£™mlŸ ÓkØ>¦?Ùl~[WY–H…Ú òƒÈ²Œã?>¹o½êè¼îu¯ƒäIxå^‰“o;Ù²à|ˆ!~Ä»|׿ã˜?ÿZìzúhõvjÅyìûÍÓIü‰sA¶Z´ñ}à ‡ï?ƒ33Øqþùb¹  @ÇQ*³zjŽOYV ]JÕ"L-*"!¥ÕuU •|ûëÀ{›×¾Y:TvïÞééé0õW#¦§§‘H$ÚF©Pqûññq”Ëe áØ±cÂÌÌ ¦§§1>>ŽãÇcjjª®fËfÀóÄ=^…’ÉDµF⨪¨Ûáy­CöWZ,~«âû>lÛ†mÛÈårUa§©T žç!ŸÏCUÕp]*• UÓÚÙù—ÀW|×^ Ü|ó­8qâcð}€‹/¾7Þxc¯O{Í´²McŸƒŒëº0M²,#“É@UUxžWwOK’Fªäóy.2¿ `ûd˜þ‡j NMM…ËØ6™Z‚@Ì Tñ>›Éˆßù|}1yú¿¶.!³2Ù&ÀöÉ0ýÛ'Ãô›ÑoK“×Û—\×E>ŸGøÂ-_ÀK®y .Ãeí?ÀNNœÄƒ>X·Êó<ä?‡•Ù?vþìÎΕF‚C:ÿ8Æ]øíÊ2Qé‹$I8ˆ/×P¥4ضp0kj0ÄþVUàk*¾uí«°ûk_Õ­D1@¼4‰ qnÍj÷Ð>EE¹h}"W®‘]Ù§M"•÷=ÿ}ØH:T‰öïß@×uLNN†Nœ¥¥%ض#GŽàp›œdårGŽÁ-·ÜÖcQU333Ø¿?¦§§qøða$“IÌÍÍaïÞ½H&“}£xvJ*%^ŠH8™˜÷»a4žYF!i<ëlí¤Óiø¾ß÷‘ÏçÃ4G$°¨ª:“ã …¦ÇÌf·½mW]u?¾úÕïâÐ!ªªÂ²,†‹.º¨×§½fÚÙ&€±ÏA#LLL„)…B¡adVUU‘J¥Ëå¸NÊ&€í“aú›™™‹EÌÎÎÖEj³mn VAbšBL1 IÖ›V¶ °}2L/aûd˜þd³úmUµ>P-”ÁC–eH’„ùð¿à§Þ)‚Vn‘,ðø‡Gâžn=ykÕ*Ó4¡ª*~çüðPea£(‘FH)²âîH]'“F$Z¨‘Ó+i¸Q`{G ®+M‹"M¤ÖŸýê‡?‰oýåwñ­¿­u;K‘"”ª«~eÛl‡Ûyh]p^0¥Ò†{‡î»4ˆP¹ç/Àí±":*J TmÛÆu×]UUqÝu×áºë®Ãìì,>ŒÝ»w·<Ï ECMÓËå:º¯E$IUQ+ƒÆÒÒŠÅ"Μ9Ó리™õ°Ï3gΠX,†aÜ ³‘”ËeÜ}÷Ýxâ‰'zÝ”®0>>ŽÉÉÉ*VßwöÛØ–ie ¡¤TK1›í_1¥X,âĉ½nFWhf›tž<¶e64¶=uêT¯›ÒºmŸ<¶ezÉ m×Óo»´´´.m¦ºÔ­°, ™L&Lƒ®( ʧÊx2ñdÛˆŠ'ÿIÜñ“;pßîÃÕW_‡~ŽãÀ²,¨ª Y–±k|W$nÄSZÕ*iT˜ž|4µO<:C’Äv7¨Ñgš¦˜­/I±ˆ4>V…Û/¹éâF«úÿBü°!„’Vb‰R9§šq±_[¿¢Ó²½2Ú§ûjÃÜÜn[Á¯£bjj º®£X,âøñãD.½N‹Ñ×n»´´ÎH˜››«S4‡‡‡Ûvˆ=öXËTdM…ê¥Ø¶xibÖ¥ò ‚ ,ªmÛ6E ÈZM^´|%yb­“¹Y}•f(Šßÿ;\sÍËáy¯ S³‹EŒŒŒàYÏzV¯/Ïšhe›VmŸ'NœÀñãÇ”™•C¡¸}H’„ P*•Vt?K’¥ThÀ7‚ÊzØ'½töÃl"fëQ.—177F;ov¨®Z>(c[¦5¾/& R¾nš ˜Ï‹å²,"Rh2a»b©½f•f¶ ðØ–Ù|ÐØö±ÇëuSºB·í“ǶL/¤±ízúm‰Äº\#Ç~Øf1ŸÏ‡:Eªª8G9§u$€þð‡8òÔüÜ•?‡ïœü¾õ­o…“TÃhQÁy ¹è`Bˆ ´!@Ôºsj÷— D’ªz+•Ït2â£Ò@µHÔÄUô¥‹¿„W}íUÀK+ 4g¶ëŠPêøþ ‘"&„ÀѪ$E"Â&Þ„Z¥ýjñBÇ[Ç_—±mÇ*ÄÐÐvïÞ©©)LMM…†V.—1==ÝñqfggÃаÉÉɆEï;é/¹ä’º|›½ÄqÄ åEv: óbšâ8LÓ„išH¥R$ ¾ïC×uLLLÀ¶m¸® EQËåBµ™ p¾8Š¢„³üWBxÉK^‚t:l§¦¦pýõ×÷ú2u•ZÛ°jû¼þúëû"Ÿæ `YVe5??ùùy,,,¬HL!½nJ"‘ÀÔÔvîÜÙë¦t•nÙçÎ;«úp†ÙH’É$4MÃ…^Øë¦¬+ƒ2¶eZcYâ3]yq´m!¢xž˜,â÷Ąخß3mâØ¶<¶e64¶½ä’KzÝ”u‡Ç¶ÌfcPǶÝöÛ®—Øéº jNÇ"$¨Py<ݹ$IÈ*Y!J´q>ù䓸ø}cŽáéO:.ºè"¤R©ÖÅÏI`i„Rów£íÌûÔú—I4Ñõê™ü€¢è—&~é{‡îÅŽ»w`Ç™â"šÅýš𦈚v®¤ þš6L5¯¢}úÜ5¸¯&''×el»¢•VPž½v/€KKK8pàÊå2:vxf&”ËåM7ûÇóĽ­ïC¦ÇqÉdÂbñ€˜oš&r¹|ßkC†  ëzXÄ@ÇNer$¯Æ }ÕUK(•¢” ýþR¼šÙ&08ö¹™*1«ñ_¾ï#×ïS[™uí“a6l›ƒ‹ç‰IS†!Þa%šTebýÄ„ˆF¡wmUíß4_[¶O†é_Ø>¦·l&¿mÓv±:T;¥!„ Ñ"ú®®ÀsÎ}nÃmxâ‰'Âl8! ª#A$4.L¯¡Z È'%jE4CF}¤‰BŸÛÀ1©WŽÛ&µÖÇ^÷1ñ‡ª»rÀGÐÜÑÙI Ú.æ¶’e¹±ø$·o_·¸äûßÇö.—jXq„ÊZ¹é¦›H$àºn•Chll¬.LlqqqS…kšfÖ¯ëõ"!Sçy˜˜˜€eYÐu=t"Û¶t:l6 UU¡ëzÕP’¤ðÛ¶W5Û~¥‚ åü“$ñ§Ó+Ú½ïif›À`Øçf#•Jabb¦iÂu]¸®Ëbʆí“a6l›ƒ E g2B<ĸßóDÄŠ®óóQlUmŠ‚ÙxØ>¦aûd˜Þ²™ü¶T·ºa„†ïû#$!p´¨¡âû>dMàœSçvíÚ§6‘Qc$~ÜFY[3Eð€ œßOS­ÙßFÓèè±ö´ðK?ôøC˜úÔ”hÿ«•Ö³Æ;MÑEŸ_Á0ŒÖÑ<]¢®NKŒk¾ùMœ×å´_*¨ÌÌÌ`ii »wïF±X ¨èåDÞÌr¹Œ={öld×L\@16HiÛŒø¾ÇqN§‘ËåP*•ÂT\TD>ŸÏ×ÕD©EUUAÐüáØdŸ•¯YQE–ÅÃ{he›Æ>7™L& Íçó( Èf³Èç󫊪b6?lŸ ³9aÛ¦wl6¿m4É Ó'<Ïkí3lá׳, óË¢þìŽw>ŽãÇcjjjÓuò<åoF°m;?2™ $I‚$IÈåráƒê£Ðòõd% µ­v?E‰f%nvÚÙ&€MmŸ›«Rœ'›Í®øe¶O†Ù¼°mn~‚@Œ÷l[Œó=Oˆ*zÍ{¯ª Á…'TmØ>¦aûd˜Þ°Ùü¶Ž#•:Ÿ}€°Ø{ÓŒ6:„ðÐ@ ‚¦iÂ0 Èqð¯Y_ÃožûÜçB×;@!T´rí˜&p1€çÖ¨D¢fõVšÑ&c’,Ëð}÷OÞ]?Ø%ŽÝNTñÐ2¢§—Ȳf=Ú:TH‘lÅÒÒRÛãñ5crrÉdår‰DbS…t:ÏDk„çyÈd2PUét’$…Q'Ùš|h²,ÃqœºÂò­ ¥s¥)¿J¥ÒšÏ•‹.Z﫸þ´³M`sÛg¿bš&,ËÂÂÂLÓ„ïûÈçó_0žYlŸ ³98zôhÝ2¶ÍÍëF"I¼ |£1¿$‰4_LÿÑÈ6¶O†éØ>¦¿Øl~Û h’ò«RÅE‹ú)6„€  _hB¸ëºQéŠ{æ’Û/Áõ÷^/ŸóåΧB¤äj%¨è:•ë#O[tZÄŒ6_M~§Ó—þEžd±¦ñë‰,ËpÝÆŠÓí¯}-’×]×ÕÏëHP)—˘››k»]m^÷Õй|Ÿg¤b†½¦iaJ*• Í“Òlæ==äV235ût U/Ô_øÂ†tÏØ¬öÙoø¾Ïóà8²Ù,&&& ª* ­Š1LØ>¦?aÛÜ\A”ÒÕ4E:ßÚu"Ø>¦aûd˜þ¤Ÿl³™öþ+ïÇ÷^ÐZP!H¤t: ÂzÎÂz ×.àÙ_~6ðì&ÇiT€~Õ‘"µcHj›‡ê‘fÂILü #lZ¡°:¸::kú¼&àFNNîHPÙ³gÆÇÇ166Ö³‹ÒϤÓâek«M*‚ ,&/IÇã8p]7œi¯(JøêDôe¹/ëDH’T×.IÅHßô¦^·ŽÙLø¾T*I’`F(4®$2‹a†a˜îãyb\/ËBXi$¦0 Ã0 Ã0ýiµóR]×Å9·œƒœ÷”(×eÇ Q!„ ŠüÐDÍå:ßL À2°tÕŽ «?NoM¿\3pl”N¬Y™èxÁyÍ£ZòQ/T£EEk‘£S7S»ãl6r²}GEémÛÆôôtÕ²ééé° îV†ò)÷¡°n8ŽƒÑÑQŒŒŒR©R©lÛ‹hkš¶ªÜu†a¬ØÖ»Þ Œ²‘УªÀ½÷^¾îŸÏ ¶mÃ0 ”J¥PŒd1…a†azï‹—rúa1…a†a¦?qÝÆÛmÛÆóŸÿ|üÃÏýJ…RiR‹QDî¸üX–Õx‚wl÷w|ãõÛxp™ üS,$ÄÏã6põ„P~€¨@|mõZ¡¥•ÙBã”`ж– ³:V]”þÈ‘#H&“}æÕ+,«^ tlÛF¡P¨{ˆÔª¾¾ß©…Gt\Øiû¬†FNoU>ÿù“vmH˜Í…çy‚ ´MÓà8NWjø0 Ã0 ³v|_LRñb^ Ýr‘ç Ã0 Ã0›Zm#Üwç}¹r$Š•JUE™xž³¢ªÆÅ”l6Û°Àüj•~¦‘ª-I¡Â4&¤Óé0žçy £R†a†é=¾/Æôމ) Ã0 Ã0LcYõÑÄŽãà/y‡ø§R˜¾žçá™Ï|&ò¹|˪ªb¼xîÎú•2€ÿ/V BÓ€…àXcŽãÄ 3—«w&kB µ½:„XäBDجfEÜ™ö° ²F)SçyH¥RH§ÓPUŠ¢À²,8ްèt: Y–‘ÏçÛK–ex^'6?,¨0µðWõÏÐ4 Ùl†‘…¢äP*-‡‘N®+úQÓÛÓ~–%Ö¹®øß4E>w@ümYÂù31!ö§cuª_’ã(“éõUb†a˜õòD_§ÑÐT–]ý#§øÛOoïu+f ±í(û Ã0 ³r|¿q­;×uñâ?x±.´/ÀG?úQA€‹ÞtQ½ø’NWŠêE‹~tù0^øí¯Š&9d±ïÓ1ë¾ѱ¯v£(–ZttV@ž°°&AE’$hš¶¡uG‰U§üb„Cr³gîñ<¾ïC–ed2™°†‰,ËP¦iVm³ÒôZƒn˜Šœæ—Î- õ¡š&:uI^ò’%üÇŒãâ‹AMR±M&#8¹\T×0ÄrMý«ç   ¦)–ѱòùHh±í(E§,GÛÓ ƒö Ñ^Š„4MÑ[–¸—UUì/Ibv,1 Ã0›êïr9ÑÊr4¡TëEô¹Ô÷f·B~iz™÷PŸCÈëí¿xÖ/âÄ'zÝZ†H‚ ëÓs‡Þ!,+Ê‚‘Í¢ê=Â49ŠŽa†ÈdêÇnAÀó<("Æ4Y´Œô8ë™àeÏ<ƒ7ÛÇ zX˜>DUÅàñ§ð5$<ùKOâ‘¿¿ÚöÊÂĸë^È7tÊ•m:™›NEä×ü„kù®Ž•r¹\W˜~vvÅb±jÙÔÔT¯Ïi] `tTîfÔ lÛ êŽø¾Ó4ô^Ùl¶*­E£PäÊFÕ*Ùl,,ìÀ/ƒ 9bñ’cÛÕbÆË_þ8üqC¸ùæÇ12ògx≳p÷Ýo‚,ŸSu,z~”JÑ1ãÏ‘ùùúϧ'2¿xT(õß´ 6Š"œH€x #D’Ä>’‰9މ.ä`¢hŠþ¤ãú¾ø,J Jí¢ˆú¬l¶Z"¡§“k\‡ 1S£ž'>£JÚr Ã0LÏR)1i “©¤³öEd¢7 ᔤ>‡&lº!n‘_[ªümCˆ%•¾>ÄKv%78&õ¥Ae?£²ŽfÉ+Žp¦$‘ìõY2Ì@çÚ¶+Ó&Š2§ Z4ÛZ–ÅØ6•Û©ªØ&Xcj†a˜A€&“ÖúdÇ©¯bBD«4àøwÿξõ‹0>úQ1nºÕFÈ1£ë²k°%À0ðú_=žºw0uUç÷dˆ1YRku<1®ëDëØbõ¼ûŽ•D"D"¹¹¹pY2™D¹\îuû7×8›íåËu]˜¦ MÓàº.2™L˜’¨Š¢@’¤–¹áyÞÀG¨ÀUW=Ðë&0]†RmÕÎ\õ}!HEyøH¥R€o|ãxôÑÿ‹Ï~öýMï{Ii4WC'æ'IÑ "¾½ª6Ž6Qb©ÍL•„zñ£tª à }3Šf¡g#9°èZfn‚ž͸K«@°MQ†afó@(”ú5J¥Oí¥(QÕ—3¾=DÅFI1!ú8ÊNýñòíU–™/î™Êo À|ey®ÁgåÀ0Ì* ÉJŽ¥O¥"M.RUñœ¡´½ô¿çEï…‚Ø—&#¥RQ¢ˆ‰\…‚8Æ™3WôúÔ†azMþlT‰À÷}1I\AT¬]†75ð‡üÜü)Üý· e|ð\à=À­‰:‘$à¿¢òŠ¢oð)¯^Aé>J'Y@|D6LßÒ‘ 299‰ÉÉÉ^·µ/ð<1`êË—¯†íõàylÛFÈçó°, –e!—Ë5,´ÞMÓ:Þ™`‹L¡Ùµë!<úèÎ^7ƒY#bDªŠÉ ™ŒˆôÌf£( 0M†aÄ¢·~·×§Ñ=*¸,ÇįF°ñ¤€\<²¦2ó"®Ó® Þ›ï^qm #³eµh±jþÑ5Ö÷Ò €sÀ¤p–ÉOÒ3€Ñ—ò â¥S–ÿ4àü ¿´â8û ^›ym¯¯$Ã0 ³ŽÐ$ÃhýY›ÖIRj!zb¿ŒHø—!úC"„ñ⯠*LªVþoÕ^:çf¥Y8a˜Ž ‰>®+Æ™$š¤ÓQAlj"Md9Šv“¤(¥nD²ÒiñNá8b<›­Œ±m;znŃt\zÅ  Yª |ò“Ïìõ%b†é™ŒðÛÐ$š8žç‰4V>Ę«âo@“É£O.݃ñ7¼!:pÊ×l¸$W§ÖÒEøíÄÚ§_²žº à*Bit½ë ¸®['z¤ÓiA]×!ITUE&“ ÿî”vQ,µH†¾ 'N\Šï|ç,¼æ5½n ³‚@Ø5u”¯˜f«Æ;ç\.ª{B¤R)xž‡ùFyº6iˆN;>ÐðP=“£"ž ‡hà" _¥kcW~ò¨ž}!Ê€bÄŽWù E÷‹Õ†áHZ²“JM¢óç LM¢y€¯Ò-€3àR@Y2þãÚŽÆ, Ã0ÌæƒRâÔöÛ õD¿¥A¼tS” A…F%ˆþ‘^”mDâI¾r¬Zá$/¹¨(Z»|š Ãt ½PDýŸJ‰wE¢†ãˆõäÈsœ(½m* (ªM"¡¨ž”)IÕ¾…øë3¥«Íˆ¡ëÀÇ>v~¯/³ApG“Ïø‘Ï0âyf̨Á÷}ዤԨ€wYh(xüßOý¥ðИÊPë…ŒÓ‰ÓØžë&¢º& ñƒöPD2Ó׬HP™žžÆÒÒ:„ééi9r¤j}"‘€Ky^ R@ûUL±m–e…uO2™ <Ïk˜Ò‹ Îo[!åׯüÊÿÃu×qžéͪ¥ôŽ#^nòùÖûårñcð} «ÍßµÐ,Œ¸zàBtìñÙ¹4+"nš”"¤;–„H$¡mòˆ&´QÙ7[–…H5BZ“‡((AÇv*Çð…ã•cÐ2½r¼Ä…–ÙӜȀ]€nøKqèœìÛ÷ÇŽöúÛa†aºÕý¢™ÞkNÃëCô?$†Ä¡i¢ß¡ô[ze9幦ô\ˆRliˆ&P?JÔªýÆ!4µ¼h$¤˜fäQØl9ˆfø~dïÖÅ#ȉøä)I|_LÚ‘$q|¸×ç³.Tê¸÷µ˜bÛ6 …$IÂèè(TUÅüü|ÃÈ]×7¬ÀüVŠTaú“ ¾Ó¶œJEh³YÑo¶³mß÷R©FFFN§ë‹­')TÏ”ð!fYı!ĉxMéDâB† 1 @Íñ Db Ͷ5cÇs‰t/ú8Ûfíœaa Í* X–ÕÜÏI“[Àqðõûï‡ã8¸øâ‹ë·Uù,©Å1é¸:š¦«Ú‡ É E¨ÌÍÍaff·Ür ÆÆÆªÖ% LMMaxxïyÏ{pË-·ôúœºm¿vb¶m#—Ë…Ñ)íØPG0Ãô ~Š|>Šâ”¤ê™aíÄÇq`šfe[…B¶mw'ú* Ññ¶jÍšu9p|Í|%H‰GšÔvØ&¢œœªE‘LÍö”ž„"S”ÊOª²Ž–ɱs¡EÛWŽ}†Uù_E”ö„„Šn)!‡è»ÒEáįM­/I¯´…s Ã0Õ(•¢™è+ž·ã"šyh!š$‡è“& ú%»²mQ´e³$#&p¹²A¼¨‚® ¯˜eU7Ü4£ TÈÅu£°Ù8äÕcbY: †ÙÌXVä,¦wíÑQ!bض2™Jý½B$¬ø¾XG…áe¹:%"ˆaˆãåó‘@á8‘ViY…‹f»f˜5‘N‹û0~ïdz#PjjËêAí/†é#d¹± A€ ¢²µÙ6*>_óñØÁƒxÞ'?‰k^ô" yCõ£ˆäªnÒ *4o ª7øIz˜ E¨ÜvÛmH&“ubJœýû÷£\.cnn®×çÔUG8bû-s•mÛW©¢Ý©µú±MÌÖ^¦4MدªŠx%z"‰)¥R º®‡_º®¯üþvP. ˆ:à8VÍ2ЉTöÍÔ,§tXñÏ!‘%.t(ˆfáR:Љçx'ƒ&$‚Ä—Qº.ÒtDùãiò‘£ŠÚgUÚ÷Q-%¶o|P-êįA÷¹Ïuå¸ ÓǶmº"™k‘¸BæaÑÄF*“ËåÄÿ† /bûR)rºQý ú›ÌG–«Ö Ó H,ÉçÅý¯áˆ{¶P¿=NÄlaL³ùdXÏóªkD× *•”®ÏX\ijÏ?C¯~uól:µþʬшxÆ œ%c‹±ê¢ô“““XZZªZ–H$°¸¸Øësê*ž']ýÔáyLÓ„$IÈç󘘘ذô]+…Ó}1½Â4…íÒÎÕàº.,Ë Sé+™D‘ñ](•(d4Sù»¶¨;‰qƒÄ*”Øö”Ç]Gu=ÐþYDâGmû€¨HškÕ*ñE}PäŠQ³/7½œj¨Eh»TljOmz¯\e»8žÃ9ÔÏé“ç5Ã0 ³2(•¥á¡4(TëlMCKêk5ˆ¸C5¾ŽrJÔ~(Eœ†øi$€hZuUj]¯VˆyriŸu"‚plîy,Ë‚ëºÐuŽã@–å0ÿøÐÐÐ?aétTxݲ„9X–H×çy‘ã¸v6þĄ؆"^Ä]–£uš&LŒRvÅ©55~Eeú*4_Û4*>Of«âºÍ#´\×…7Ê€A6SñüÁÁ·Â>;H3¿A<£‡‡(j¹òÛÐQfKÑ‘ 2<<\'”Äk©ÀÒÒÒŠ¢S–––°¸¸Xwœr¹Œr¹ŒD"Q·®Ðl˜~!N#—Ë…ê«®ëÕŽ>£ŸÛÆ4¦™mýgŸ ¢‘« Õ''ƒçyÈç󫻇=ˆNUE䜡ôZñÔ] D'NNT~gQÝÓ`€ÄQÍê¸ó±Ï âh4ÓV‡Èý®ÅÚB…Þ³±ö¨ˆR¡P»ãz•ØoŠrQcËðQk>3¾]©æ:Ì£šF!´[ì³Ùí“a¶d—qÆÇÇÙaÝ×3ÌK%áH„¦¡iK+†ú¾Nð}јøÌ Û364­yõéð³j*dËrûÜÁªj·#æiv]ªª†¯t]¯šˆåydYFe†a ŸÏ#NCUUäb^çééé.\ðþ‡í³;xžˆ‰fQQuEãEà©,m7>ž¢DÛÔRëL£mââ 3 ª}ºn”jN–EWS(ˆ¿) ³Ñd^IŠ"­f£è¿­ï·&ù¾_]Ú Q¤ˆ¼S=èÏ–5‹úÒ!ÒÀvÒ¯(¨ÏÂl :TvïÞééiÌÎÎb÷îÝ ·±mCCCH&“}°]AMMM…Ëfff0==ññq?~SSS˜œœìÙÅI§Å p~~íÇZ-¾ïò,ø¾I’ iZU([®ã”UUeAeÒÈ6þ³ÏF3f5/T¶mC–ed2™*Ѳ-D†È¹OÑ"ñtT4+ÖBäÐÑE€Y§O BP h^|DuPèxTä„êº$6¢A@<¿'‰iD‘+¨lŸ˜±K¿²l9ÖNjOœZ_‘TiS-µ3KˆÔ*L[6³}2ÌV„ÆÏqŽ=ÚñxyP ‚¨049ˆ<¯~vyÓ—çø‹2M6¨Mï@}T Ñä€N"' ‘‰âEzrÍø¾ß0å¨eY°, ²,C’$(Š‚t: I’ ª*$IB6›EP¥*м“ú‹ƒ ÛçÊ ¡+f³‘m¦ÓBèÈdÄrß lg³Q“x u-®Á ’}RI-ßçó¢«Qák"— ÙÐø}–S~1M¿øm]·y–SÛ¶ëÇG45Æ«>ü*Ìî­ÙÍkäQäIÜÏÓJkÕ&3Øt$¨$ ìß¿Àþýû199ªT°~ff‡n{¬™™‹EÌÎÎbÿþýU릧§qøða$“IÌÍÍaïÞ½H&“=™i›ÉˆŽ­WïžçÁq8ŽÃ0`F–¿YXQŠ$¦ç´²M ÷öÙI>rƬTÇ ‚™L&L¥×TL!1#.6PÍ êŒ=‘‚ Ç£²ß"Q„аÓqmˆŽšÒ‚©±eq¡†ö 5ÒJè$µfYmêøOQ8 ¢<òr;µ³ úS Àk`"Ua’N‹œ@”[LQª È÷ô^`YTU…¢(PU¶mÃó”VP°od ÒQQz@(’SSS˜™™ªª¸æškpÍ5×`ïÞ½(‹8zôhÓè•8ãã㘜œ¬+p_,1<<v˜cccC±Xly¼S§NµÝf¥Ø¶4®6eÐZñ}¦i†ak”Ök3‰)[…b±ˆ'Nôº]¡™mÒy®Æ>Oœ8±¢T€Í t­Ö§RQáù•bÛ6 Ã@¡P¨SF!œ2E/ „”ZÁA©,scÿ‘°Q+€Ä‹ÆÕQ#ôÂIQ&7QUNZF¸ï®\’þkìC¨¦Ê¿Úb_ßÒŸ|ÆØ®¬k4X}Ô÷«§&ÇóËøñ>€ï¼à@ ¨ü¸® ·²Ýÿ÷«¿Š“o{›h{Pý,--¡X,âÌ™3ëÐð§ÛöyæÌ‹ÅºT ³”ËeÜ}÷Ýxâ‰'zÝ”u§X,®øs=ƶýBDŽØ‹)D¿œ†èw }`¢ß*xÈým!«ºXÁî°ëßÈUU4Ц SÞ•EYA€t: Û¶aš&2™ Òé4|ßÇüü< À$IaНùùy”J¥02¥áE_ƒ4¶íä\WjŸÝÛöAÍœ§:„A ÆÖT,žÌ¶…í–JQ™ YfE‰¨À6 &݅ƶ§NêuS6„•Úg?mƒ Š&¡™õ¾/l§æÝI†H¦ÿ´±ízùmkëpwŠç5¶òã´ªßìû>FþìÏpà 7TvŠ­l'^r:¯`nnn]ƶ+*J¿ÿ~ìß¿¿ÊX†‡‡:xšAÛ×`m‡9<<ܶC|ì±ÇP,»:sAQz7+À÷}¤R)èºÎ›€Azélf›Àêíóĉ8~üøŠžh—Vœ ^®fR¦mÛpî„‹þN@ªTÄU”ê”WäWQÕ5‰·‰"Râ`*ÞŸù`Äö'( …j¥ÁÄàëQ:, ÀÅ&ð—p* ’E³H¦ØOÓ€é€kàè(0$—Ë€'GoÀ2€ƒ†x[¦Ñ{ü˜NWÚ(‹7xØ "ôæMI³ šÎèºâïXØŸã8ØsÎ9xbß>l¿ì2œsñŘ߹ÏQÕPTÖ4 —¾ð…¸ôÊ+ñÀ•W íÝ‹ à82/~1æççñȧ>åOÿ¼úÕøìK_ ×uqóÍ7ã]ïz.¹ä’5Ý{ýB·í“^:9Š…éårsss›>z;è¥ñàÁƒ(‹ê(-ÂzŒm{M¦ò2êyÑ ÷ãBô«ñÚ^q,ø¿6p^E­±mñCÓä3ÑÕæò]í¢‹ÐD×uá84Mƒã8Ðu=L×EÎY–£É¶ lÛy»©ðõ¿äÕ‹çŽi敨0HcÛV¬Ö>»5¶ÝH‚ Z’(/„N‹á\.Чš„† %q'¯$µ.ÍRÝgqqÅb=öX¯›²î¬Æ>ûilkY¢»)•Äo]ì¨$p6‚íª´±ízùm‰ÄН‘ç5· Çqê£SbA€ýÀð¦7½©¢VBÔFq¥Io%`ÊXŸ‰¥Ì†rüøñÞ *Äz¼àÕ½ÐQGxÉ%—Ôå’_-¦)†–µqEí\×­ÊelY Ãàh”MÂÔÔÔ–(ܹZû¼þúëלOÓqÄO­IAµ²ª´!bŠmÛ( Ø9±SÌnU¬Ê¢l÷C¢HBX9yIˆ"ô"I)²,G=?(íˆSûÁˆê«¸®ø<☿ái«’OA¼åæ}*ðø¾]Ц3ÑÎ=÷Üõ¹&}D¿ôŸL¡ˆ7N¯ÒWŒáèÑ£áÿÉd{öì¸è“Zh"„\ †t¡ÍSECLˆI*¢ûØBT'…";UVez½eU÷{ÔoR$e£ÙQ=šÞkÛvUQy˲ IRX$¾P(´t4% ¶ÏçÅ ŠD§-Ê Ú' ›fT÷D×… Ò|2J奪Õæ¦ØLöéºQÍ ÇbUD‘•¾§R¢„FLLË˽>cf+³Ñï47¤‘›#“É Ðl&¼ @ã¯wŸ>§ÿ·ÿ­S ü6&fMô 266†™™™ªe‹‹‹®éyk(¹ªÏóÂÙh¶m#›Í¶í–NE†é½²O yÎåÄË!å ­Í.µ XøÎ>þ¿ÿ U¼ÙÞ./ ¢Z)ÐÄùl Р¡órULïÛ)– 8•Jò¶ œôEª­Kå(Q|o.32ðbˆÆgÒÀÈÆf¡Ê³%4x{Ü)²®—¸Á5ªœ:”zË©ÔlÑ*#†a “ÉÔ…ØÖŠùŠC‡ æ6Úf]ž{4z Ðëþ“é"µiÔ‡¢Sm¦ø :9žãó1ÈA­µ8>³®”Ëe,--U½dJ*ˆFÄgèæóÕAácžîiz<ÇSjâµE£>ç®$=ÀŒETôªØa Tß }¤¸>|ßGa?*IdY†iš0 £w©}©*ògìÓ¶£Rt…BF‘)†Q/˜MRay¦‡Ø¶xpêzõ—•JUO²ÚBl&û¤hÛŽÄ Í$‚Tõ™5°­2½f£ß;m»q„—mÛÐ4­¹Á>ô‰ANÊj4^4 ÞŸf ô ’L&ü Édsss(—ËØ³gφ|>åt¦ [ëIH¥RÈårPU5Ì‹ìoç³ùè•}Æk”ÓLšùºš”žçÁ4MüÉ}‚¥Ï.AýõÃÀ !”,ÉB¼ø­J:/ÀK5à=2(Âécxµ<à¶¥üÊeEcoT€íðúÊò0—¹Í §:":ÿ ptš¦ UUÃÔ"äì1 –e‰4[•‡ ëº¡H’$¨ªŠ B‘¤U¾RbU3n™ÑëþsÝñ!ÄüZ´NÔÖSjDây·ñ¢zt¿²œ&[y!é2¢çê™û´^¹NF¥=”؃VPYoC¸©±¶é¨®õÄt…b±ˆ#GŽà–[nÁÐЖ––0;;‹ýû÷÷ºi]ǶEÀH.W_t·Ê¡D÷¹Zù-Ð*ã_êku†K<àû 6.'o\× ‹ÁÓßÂÿÍJÚJqÞâÄóù|U±ø–€^1:Ú:5è²ÙíÓ÷£‰G¶-„^Ö+5£P`m[¨M­ÍR}"Ê©Vûbâ×<×h[M«Nµ—J‰/a~^I¼¬uü¶«ÚŒVû4ËÐÌ0ÅF¿wz^cMÙ²,Ìýâ\ã÷0ßÇâ¿= ßÿÖ÷ñ½¯y9~÷aÖHß*€ÈÙ{àÀŒãøñ㘚šÚ™4ÞÑõõŸìæû>Òé4²Ùl8‹ÈöÉL;†iD/ìÓ¶£(U’$œ3+*3dK,!}‡°½/߉sì/—ª@ Uˆ§Ù :Dç,)Q¯ÀÛ„ÞIjC<%VhÖRóï r¤ÐìXúMyFID„à!IR©TA’ÉdÍf¡ªjèôéÙLÚÕ"Ëböìg÷º%B¯úÏu#.ø¶—AuF/Úä :ÛžUY×M1#;°Ó ŸÎ).Œ¸5ŸEš|åÜó•ÿýJÈ1] ’ Ÿ=©Ê¶TÛ)]Y§V~4Q…ÚdÄŽ/W·"Yè˜NìœZArvÐùzçææ°wï^$ ?~“““}_a¥PM3Muß[úåmTê Ä–¥2Õ•êÓéÈCE)}?šv¿A8ŽY–áyÇ #8•J Ë\.Ã0‰A¥(E»‰}'¦ˆF QE–{.Zm›Í>'ªÍ@õO(^³y:í(1%.D¦½Ü“ðA¤RÑø]Q¢‡A4ĶŠ"þÖ4qËãLzðQN5Ï«†b{Uj¡’ÿ?Ÿ‡eYð3躷’Ó8躎S眃¼ð…øæÅ‡œ¾ñoôúj¯;›Å>'š˜Û-WN¾Å¢TjË<¢™>f£Þ;›•½sªªbûöíâ=§Ö&2l+=€ßùØðøøãÍ? æÖa˜ÕÐ3A%ž“˜œœD2™D¹\F"‘ذt%”êk=ßolÛg­†Q'¦0L¿ÐÈ6·ÏtZØe|¦Oõ˜$à+û^|üÍpƒ¦' ø%ào àÿ!r<„cPGuŽÍÚri –eAUU˜¦F½ÅAš¦AQ(Ц"Ñ4-\t©ŽÓ¦Ž.¡)šï{_¯[ÒUúÅ>×$ÈÞ};tQ? ÉAuJ«vÔ:üIØcŸƒÊ² ˆ:=<D«ÙN¯i‡‹H Q F嘢h âE€Téy“‰7!v•k£Ç>?]9zÅÛ TÚ^@$ˆÐñeTç .A8ºÊñ”ÊÿÄsö?ÍXûè9©´“ÄT®Ùc.Pp ²¢ýð‚S/@ñ­ƒ]¸:„¹¹¹0¦¶Í2™h†¼aDõÑ[âÐ}Àõ£Þ@µ#3—FFÄßÔ7uYÔ‚ ì#)ý.Ež¨ª ˲ày|߇ªªQ½5P³ê=g›ºÏ¤4C=ª1Ó+6ƒ}ú¾ø¡:Ÿ²™ÅÌÕªþM9Îñ7=KâÏzîA”¯IQ„·š(ÄŦÈrÏ‹ Ê{~üÒK1ÿÙÏâ7Ý_’°tÕU¸æÔ)üÏ4Åä¥ÊsEQUHžwtŠ¢Àu]èºMÓàºnXS5¤ÓiüÓÞ€ÿõ®w¡øøã¡ÿà oxC¯¯ö†ÐÏöIG®»1éâ¦WôÒoÛªýMçß$Þ5tT§4®Ì–w¯Ö°w|Wµ‡aºL_E¨èIg¹¡mÛ(•Jý9+a:d£ì“œ3Ýx¯¿oæ>è;u¼wø!ÜðÅ¿Â[% P™þs'ê²äøŒûK²ÎˤPš«ª*Òé4 Ã@e9C(ÊDQ”:—„]ú{`äsk@¿½lv9êÉIéöÈ¡¯#:”Ø:Š¡¨ŽF¢JEL%>\Dh2¢H@ˆ&ªÓhÂæ)=–!N¤‰^å˜)DâbÇETd[‚.R±ý¤Ê1'EÐv$ Äoc§²Œfbå+çVjˆ„#Ä®»Nrå';EåQJ0TŽ“AbVÚšG$¦|Â~Å^ªFV´;U9ØÀgàìx‹¼±². <<ÿ>ÏìîýÔ§¬W¡Î^BuÍÈ¡KZB[Aåe±úb†!²r¡¾NÃt™¾T6’ ³ë€õ yö<étº?ó%oB<Ï gÜSê¢Vו¶c6Ý g6Mï\|þåÏÞ.¦ö]®ÔsV9= ¡.hØ1…94ÓÕ÷ý0¬•Š¯Ñ¬Zz!£¶@4C¶ÀñàL¡ÉŸ²õ¯ä©ÊÊ‘4`~†åe€úGˆ¢)d»t òˆí—‚+ÿ0 ü}p5 \H>l¼ŠïDàŸø(¿ H¿[™xjÊ(¼ðÜëù2@~ $ï[Þ(%À;à£x€”¤<àÜÇÄ|Ûð‹þÀ5b™çøm@þ"à} ®×cÇqÙe—áÁú ÊåkpýõA–7 øfTØ[¯L¾ ÜÈ·d•ÇWE\RU4~yˆ¿ÈRꮡúù(Cˆ&a#¶ÿ”hrEÊܘ>joUùÊÕÖG<àÝzä¸Ê‰ÏØyc —<ÿù½¾U™¡´^”áFQê Ô³~Õî5Ë%àöŠ::T÷SÀ 9q Ãhž#¥K¹SLÓ„ã8•scFY–Q(Ž …|ßç1;Ó3*·kØÆÕ»\7 Wï$§’ªv^`"fßA„‚‡,Ëð- ¾ïCQQ‹ì¢q¶®ëa„I¡Ph¡ŸØDÑâí ”¼Lÿ`Ûâ§T·%—¿e˜õƒÒ\ÖbÛ6ÞÕûÅ;!M`Ë0Ç‹ãw¿[¼Ê˜ìš--¨ÑKáz@bJm1ÊAê1˜¦ ]×ÃÔA4 µmº®‡ƒRrÓÿ¾ï‡³zâuEã80 #ÜDz,är9X–Ã0—cZoÛ6 …R©²Ùl˜ÛÚuݪD’$Uý L}Díbz‹ç­!ßÍ.àxÀAßù_ß{®‹ìyÜ@ÌP£ßñÜ´2Bgnëx+нOâ …ö“³‡ Ûæóù*û¢Ùlê–|³f6ét4ÉÓ0ÄL>÷³€újÀ½#ÚNû) þ |ðžh/¼ïΗó'€¶_ØNÅ«©o ³ h†üsû¿ÒS€v p/ð³.,ø­ò)¼Ã> ×– ëÀ‡ì]奀u+ ==ª9ëºÀKë1Ì~ð)l¿ìø—wà_®]Ä—?ý<ÜóÑâÙ³‡o|ã%¸Ú¿Oýü÷øþvî\À#î‹pÙ§ñÁþ zhþã?ÅòÎk±øÝ¯ãË¿ñ5,,\‹Ü;¾‚¥OŸ…g>swÕu{ÍkÀ'?Yƹ瞋k®ù æænÀE…Ó§O¾üå;ñýï??|>$IxÛNŸ¾–u°sçNLL|_ùÊŒŒœÄ®]Âw¾sgŸý€¡¡{qå•_ÇÞ½{qèÐ.\sÍ7ñŠWœï}ož|2k¯]À~ðxÁ3®Ã«~í9‘S™žÇ¦YÉÅ‘„|-ïS÷BzÆ5*™Q$Ôœp:¸âú€*¿×Gñ‹ÝÒë[•iÕj°,ñÛ0é,@ù+ˆ>•ê‹ýØR„p7)©¯€«<àò,ðTî£J}±.¦¾;:mÛÇ‘4N-•J+rL²˜Âl4ä8’¤ÈÖ(`bàð«~üd?ùéþõࣸkâ"Ü®Þ<ôôê™Ù”¦'~ëçWö1«l@øl [$¢—>ºç9Òd ˜<5e£I§ÅàWUã5ÀÄ[„DUý<@)˜¯¼˜Þ¸»/hÿPŽJ%õ•ï(x#ûZ$².\ñ_váœKOÞ÷¾'Ìaǃ;pú²' ‰Ÿ·ž¬´ê†X Ÿ0`<æxÉÔ];1A`?þó?ߊç?ÿùøÊW„ëN ¨ªZq¿9ÖNqŽñɾïãÔ©KJý-.»ì2xÞ¹øíß¾ wÞy'ÌKŸ‹£Ÿ{6~fi §ßñ×xÛUaø—®ÆÇ>v)¶oߎ~8ƒùÙad–?ƒ·<öF¼ë}§0|Å;pÿý“xÚӮĎLJtÖßãõ¯û®=w'¾²ïz×$øö·ÂW¾r§Oÿ ^õªÿÀüüzh.½ôÞñŽ«ñ;¿óÃóܾ};ç.þÉð€ßïõmË´€44 Ò7iæ¨à6ð! %@¯„wþÝëÝ÷þxžÛ¶Ã>”&ÙÓx)вµRv1›šD亢ÏËfWY/p3‘N‹ßqO™$‰‰O©”¸ù|½ˆBø>;xÓ¿ñعs'^ùÊWâ^Ç ÓnQT÷ÈÈHø~Ië(cýÐ|%ïê9Bï¤ñsÞºùÞº½gÒ-˜ËE}\>iwÛ¶‰`'˶©iýS¯ˆj*ñíÀ 2d‹µ÷¹eYÐ4 ;å‘XbÛazâà üòñ_鉃^Ÿ³ز‚ŠïwVëºð}fʼn7??¿¡Îx Y¦èrÀ躎T*…|>摦™9ô;ˆ Y–C§.G–åÐñKŽ!úŸDúMAAèZ¯×JÎ5¬d†`»ÙA4PnuÌx;ãNªT*Ã0ª {3ëÍÊk+¨P-˜?(7Høê¥¿Œþç?áC?þ0^õ·H T[ifûQx²CÇq ( <ÏC6›E©ò¶L6À÷Ô:áûxÞâb¯[±e°íH¸ë.œûœçàËÛ·‡mq*PÿúïÀä»Þ…ßÿã?F6› ûã믿š¦áe/{YåºÚ¸ê _À®} Û¯¸?=qßN$à½ùÍ„s笻îÂÎl/úÑð“¡!Œ?ú(.üýßÇÜöí¸á†077‡»ÏZÂ3w|ý$ʹÿŠ9×…¶ëExûÛ€,˸ÿ£_ÇÂÎ(]ûvüòÝÇØy-¾úàO` Øö‡ð߯Çq³åâ«_}:n¹åxæ3ÿÏþqá…Oa×®q¼ô¥gðØcßÇE% ËCe³³³ø£?ºÏþ.;v étÙl¦)áú×ãÇ]ÔëÛ–i€m‹»†!nõ*GÕ" !¦”Jë—?·‚ã8¡ý†F{–J¥°¶G—0›…LFØ9s7íü-߯?š}AÐþÙ,~øa«8ͨ·m»rXñžû¼+¯Äo¼þõp]ð§¦Ñr'ŒHëDP¥h”µÐL”±m¾ï‡czÏŽ¿¯A¾k{žÓ4áû~ø¾ßÒõj4e›éÓö6?_](>oÍ÷…¦Géii}?Ù&™wuÌ ãº‘ Æ¡g<& &ôxžp •J¡VͪÀËÕUa˜udË *TﲛР(ŸÏ¯{ø/Õ¡hJ-æº. èÊÏ*IR±±ÚAã@„3{^$w·¸tÈñFÎoJ–N§Ãë¡(J˜Š…Y;®ÛaÔØLä,à…ðÃxaßütœÿÈMø»3Ó•—;lHäI-VE"A’fÇɲÌÑN,_ÿz¯[±e°m ÿç•\* ?èdÓ>„#6UY/£ZàÌ Ë ø¼ÿyxN4ÓT–eN”bCQ”ж!ø§ÓéúI Aåpê“ÐSQˆ À·.¹ϾùæÐÉqï¯ü ž56†ŸÜ{/®9ç|h|ÿåÿ¶mã·öìÁï|øÃøË×½þ=÷ວ= N*¦î»wh×ÿó?ã§ßøÔoŽa„“dJQbÛPy¸à‚°QUH§aÈ2à85 åPìÇŸü àû¸R–×Åsãç£ib}…K¢K*~W%VŸ‰žM4Ó_ýÔ§ª.ïûøÿY$ ªªâ¹ªŠÙ7¿¶möÙlAðæÐ©­ªj˜ Ų,ÜtÓMøÎw¾ƒ;ï¼###$)Ì3_*•P,Q,{}Û21âµ5Mt¥u³åk |º®pð­CÿFi»HÒ#ú– ý ¨ö.S®$Ǫk¼OŠ{}Ói±_Ììê:ìL’$…ý|m*æT*¾“åóù†u3kßOµ5æC¢hrkPd¹ëºá{a&“ ÓOÓ癦 EQªRYg³Ùp2^&“A.— ÷gHp'Ìæ@“UUÅÄÄTU…$Iø•¿Ͼûnœ9s'ßþv:)h°G“U !fuºž’Ñ׎V|_¼xKR$nÄgy^wÛ,‘©iFqñôWÆhú P=[’ÔkYŽÚQ(Ôû˲±Äf©žxTI™»ïÆ—_ÿzA€/|á ¸ñÆWw™Ê„ïæø3 ²Þh_pEØ£ÀS=ÿâ¿"=R‰á®Íû¿Žd2¨ªÖ< ‚ LyÞ˜Þpñ©S½n–ÀuùÙ€üûJ‚ ”·À™—ÁÇã¶ nÃä“xSêM¸õwoÅÇN| @4óTÙ¦„Ά¦µhækÅÎêú^׃ìJ_øÐCáDÅq#I$מýmwíÂÂÏþ,î Tf¾kš†Ç^ûZìzê)ÌmÛ†3ü ®­´MUU\ð‚à}pEåãêâ^ÞýnñÛ4¡«jôLÒõÈÉÔhöl>ŒŽŠ¿Íú ã¬¢o¯uDÑÿÍ¢EI}Eµ‚¶Ïf³-#†˜þÀó„ƒWÓ*éùèë P]_¬VLVœÐ&…‡¬Œm O_Ž×ê$T(*‡Þ!â×–"­ÉÁK¶ã)Ñ(­P&“ k¶e³YضӧO#™Löú Òðm»ºvz_ IU×9²,ñ`$ñ]*‰w%Óïi†Qõ>èû>|Y†ëûð]Ïö³ñÓ~ÿøå/‡ý¹$IÐ4 A —ËEác‘µ¥+M}ßG:'-˜¦ UUÃú*$nP­Búü `šf¸.—Ë…)¬-Ë …@<Ï,ËB©T ë7‘èO;¨ë:‚ ÛRK£g\Ü&=Ïû+©Ì‚ Àfg{}§lL³î•¾%Ù¬ØžÜ ýF<`šaÇŒ ÂwHXÀ±s Ñ9€xñªôM¾,ëÔnf˜fK *–Õè” ÉdàyTU]‘ÓŒ ¦ôªfŒš¦‰R©„‰‰  äóyH’~VÕŒzýÊìÕºi”Ã!^ð¯öÂÄGñA_ˆ¢3t|߯¥ÙKä,ª½Ðl% qÕqE&ÛŽMµ#j7Í›£'ÓŒŽCñô­ ‡‘®7žºBž† ÀvÓ„ú;¿È2îºë®•Ü6L(¤³¥ }3¦S@`K:ð9°Gþêdœ ÿÙaì¸lǺ·•jŽ"—ËÕ9|X<é#Tø×íu+¶ ÆK!Òze êHÀé?:[þíüóÿŒgýƳð[ÿý·àº.¾rÉW0ôÐPèÈhêt'!¾¶Jh&ƒ'øCœÞ¾îÞ[ÇÇÃc|üþoºùfô›D º÷)ê„޻㢉(ÿ?{ÿßÈUßÿ¯Ü³ÉÆÎl–d#’Ì’ ±$ãMåCSȸìB[ÀTr ùÀ.e¥ÒÛB¿.Ò‡–ýÑ퉨¥ í4˧ |>X*Û%kêá’иaã 7›$O“(K²¹ì¬„ÜþýqtfF²n¶$k$¿žÇ>ÖÖe4#ù­9sÞ眷”³L€Èý«t­/뿯Òq.7!¤úf¨ú—á€{ï½·å}¯I§Å9n¹5‰dQPûfMSœ«Ù´¢^eÛÅþܶè_§¿út¨vñßK¿»í¢Õ¶æ*rrB³×k²è|,ó–ã¨CŽf‘õä:ê²Ñgš&LÓÄ‡ÞøF¼å…p-€XqÓÑ£G½¹rQÁ|¾tˆ“L˜Þ™¶|ù“\N´0†‡—ÎþÄmræ‰ÿ¹ò @&L*5ˆë½þÑNÕ¨jcÉåBýÕ¤RËVR¯£ËßréêÅŽƒG. \õÏ# àѼøŒÌ8È›y<'ÜZ­"G¨E£Qd³YwDZ:v—%à‰» è:¾ý…/àÝÞæ8¢3VyH‚Xf/ Üö²Ûðž¡÷@UU¼ùè›ñ{wÿÞ{;NM  ˜˜¨õUïŸm¨ëâœSì8DF¾xþ¼çóŸ–5L4 {¿úU1ôÿ°ÓoÑò1)KeG4ñG„C2)~N$ëô±mNÅUåxã^ÔãÉÄLâ"Õ€W'Å7+Å·Ö¼Û­Ñf3 Ã]>Ç4MD"LOO#ŸÏcrr²'’m²FZµcñÏ>—u”ä,9B_Ît÷×M#öå¬tYBÎ~UeIBÙ‰+Û'²VvûgŽÕ¢ë:*-æŸÌhÅ/ùw)k^BÃ|×»J¥pÊå—C+ò[n,ËYR€WkDÆI$qg{Èd\†á&eý¹¼–Œ/ùx9PCÖ[ª6óÅŸ|‘¸„`÷3Œå'Sˆ¨óܦ¥ Ì?ßýÅïˆÀ_¥?÷N¤Žã¸ƒAˆ:aÍ%T¢Ñ•7fËg¤¤R©º£UåZârjñ×¶oǼã¸>Z2KC×4è†üÍßàZ¹ˆ§_qÉ)7™PžJ¥¼+ëJ [yàÕ.¤ycêÔ ”v^¨÷@'@PÈQ{“)DÏÉyàIà{ÓÀ00?:ááaD"|hòC-Û9cL.ËåÜéû€}Öõ„ˆZ$Ÿ/Ö‘Õü5 ˜ß7Œ|Ówû–ë²PºTPy}“òŽÙT ùâ¨lSΜL&KŠ·:Ž]×KbÒ?*”"ÔíäAòÏZ×Å¿éi7$ÜõÞýlÛ«Ó‹•®?= (r ŒCœk5ˆ•µŽd(U #üú˜¦éÖ>Ñ4͵H$ܘ òLNÙn÷ï¯y¹TV,C¾¸,&íOˆø;€åŒY;AnGÎP÷ÏrÅbnÒE¾~¢¬}ÎvHw ÒŸ½‰8Û¶ÝdÄGî¸ï*.;‰DÜ%Ò˶#ÿŽý³Dœ²Y–òïxxØÝžªªîïþÙ,J–Ê’1"— “É—òïÿlqÿl‘Vž§î"g¦°HÔ]d»×¿ôì±_?†ðXg><Q‹3å-ëÈA®ÔIk*¡bKW©jü¹†{%§WsÏç?Ÿç;øÎw¾ƒ·êSî™éâš³ßóo'üg{9ó£Zb£ÑD]DQªÌ³ f¦ÄìÑ€W'UÅ­¸ôÛ„D"Ñ’µ2å2$rùŒT*垘ËãœD‚mÃ7Óÿ(p"Œ´!Š«~,åK¦G²ûÏm¦)NÊr Iß}²CVvœhšævúø ×2©—9Ž˜LœHTnúÉ2<²\\Ä4Å}rÕ™„)a@Ô:ªÔn0¬½çXŠ‚ï$“% ]׉D±tWµNàòûåR?ÑhÔM¤†á.™%,þä‡lÈí—wäÊï-ù»¿S·^ç.;{O•üãª1MÓ-¸.—€“ÅÒåRÒ2q—-ÎŽ’I‘h4Š\.Û¶ÝíÈ2±!ëøÈÙ#îlÓD"‘pã$—˹Koh¨#¬Zý/¢j’IÎNé%rƦlÿû.^±òŸ!´þYlå b»Âª'ò;²üµqÎ9çtú-ëZ–Uló)˜ÿ½y|ø«Æ?;çÓ&p÷$ ˆ$=,pv u\O'Tä –%..óù寇)kÈ‚sJùZÅßåú}·¿êU8ñ;ßvãÐ~ë·€ûî+íô•I¹ö´{Å%M¨‹Äã¸úá‡î\¹b\‚oI£×‚X«=‹bçŽ 'C:™„išÕ U7HŽ$• 9 …´½çòŸý¬Ó»Ð“¢×©§å *p¨ï~ø÷¡ëzi|Ê¥»Ê†Ð[ª §8j[Å`¤ÓЋˋÈÙŸåñÈNZKd]“Zãheécd»ªLˆÙ'Ë8…Êaòç|>?}òI@ס¿ùÍ+Zòg¹ür–‡¬9˜J¥`š¦›Ð‘3ÛäRZþZ 2q299éÖqÑ4Í]6HÖ~¼™!r) ÙÙ"µV›2Èoµ.ïd|úkŒ”ÏðEàÓé4>ó™Ïàë_ÿ:t]G<G$qgHÅ"¿r9-y~–ÛkDùÀ'Î¥v“ƒ zõO-kîØÊ2‘`•e}å÷‡œ…ÖH’Âÿã_îÒŸ|-ONÈÙ¬òïoKT«§ñxÜ´\ž ñÏ`óS¥ý– ÉŸ–mùÝ'ß/]×K’9ï~÷»ñ| uø!.°m ƒ˜…’v~t'ÞüÁ0ðÉO– “¥xN¡NëÙ„J:-’)².ºe-©¯d2鎒-¯Ñ`Û6~yà 8÷òËñ'çŸX,†ÉÉIljô‚²¼F u§Hg~øÃxºÓûÑEl[Œº•#g+Æ¥‘H)^¯9Žã.ñµ’z)†a¸£PåE¥®ënCŒ£A‰ã8@ô*@ˆ¿øâñ8lÛvGž'Ý¡! ‘À1ÓÄäô4´â²"‘HÄñ*GzËÑ݉À/0OÔ~/¼p:~ô£•ÕûSUˆÙ’QÛ(_ü§¨3ÙYvÊ^±mÕ­Ý¡-iËÊÎù:òµäëËý‘Å×åE´\òÏ»ìü‘ “j³XëÊY4LÖÒŠÙKå%!•¼åô¤: ‘ÌL«WˆºDißs“ðbT->mcnÛø;Ÿýüq<ôÐCøÉ?Áù1n:å&üºòë8gË9¸zájœ}öÙøëþÇ?p<¶Ü¹3_šÁgÿà³8rï|ø²ãg¾Çÿðxœ÷‰ópóÅ7ãœÃç ¢G ÈÆ²bÒ€QQ#€¨ ÕÛO¥¸O–o?“ÅŸcÅ}–?Ëd®Y|NÌ÷<¹,¨R¶-ù^*Å׳Š?k¾m+¾íùŸ¯ø^+RöºùâÏÅÏvq{ZñuÒ¾çÈ×¶}ï¿ w5"Å×´‹?ç+ì—U¶ò˜ßû$ßÏ|ñ½P}ïàÕ´²€Ó_8½•Å=Å4»w|ªfDµÛn»màúë.I‚øgeʤF#3"Óéô’d†Ÿÿ>™¼³Ñªñ'4ü¿wó5wÄ7z¥ZRyÓ¦MxòÉ';½«]Å0Dßm$¨/‡ønœL[ ˆy÷»ß ¼îu¼>¡V×Ï%Z©žK¨X– +)2Ζ30Ì0Ä’%¯Ä\,†…ï_4M÷î³×]‡ß9ñDœ´a^ü‡@dn®«OÔ]Gÿïÿ>* D““UFЗBîãÌW¾‚ýÛ¿…®ëËîlM§ÓÐuÝíh)¯ÂN”Þ÷ãóÎëô.t/ÙaP ;çßëk@ì×HLtx~ôƒÄ__p¶=ýtiPk°¸ˆt: mnÎ핚eFÔëšZ1Kž*}¯ÐàuúBUÎâð×A³6eAç•άÑPÞ©"ë5Ès³¬A"ÿ—³FdŽ¿{¤Þ²·E\O›Ún³ïçIxüYˆróFÀ| éÉMY³âñ(;ÝïBıÜÿýøfê›Xp=ž}öYDnŽàO¯øS¼ôÄKˆ©1ü@ù~Gýh?Ð0óª<~Ýãxû»ÞŽÇþê1¬{d¢WEqîçÎbÀ5Î5Àç§ÿüi¬¿s=ðQàúë¯4àóàQƒÅ×/vjA-,¿WÒÅ}” ™(±à%dÒ@&A6ßùÝ#“'2a’‚—0PŠÿ¢Åç«(M’¤½÷¦$ÉaßϬoŸåga¢ôûPî[ÀßgèOì C\ÄŠ¯cÂM0Á(î³LšÈYyß¶ýÛJÛyïï— 8Û÷ú2A%ÓòmÓÿÞ=õîVþ5÷”• ¢])™´¨4{£ZrÄÿX-#ÿyÖ?ÛBΚ”É’“OÞ€Ÿüä lØÅYgýN=õT¼ùÍ/ Ž[&”4MtTûÅbÞmºîÕ[“ÍsY“Í0ĪXLô«9Ž·œh$â=·É‰rñ•TJ žTU±Oé´×''ÇJ躷ZE6+–.õK¥¼ûå¾ÊÏ×ÿ˜d1›Íz?Ë}‘ûjY^ébßX ÷yòµåûgYÞ±”?ÏÿšåûjYÀ/~ñÿáðᯭÎ`—³¿ØwéÓo™˜NóóßC2™_Š„œyœÍfy IÑS ÇEç³Ù•L‰” .¸###x׿ÿ;²_þ2~gëV¼á£…qᙽão±‹.‚~ÑE>tê 3ÅáNïDH&Eƒ¨fl&áĵm†aùŠwìÀcë×»µF¸ËpÉY"å£]5Ms— ’…×ýŤ‰ºÅ½Ÿ} ’}@ê{âÚÓ¶¼¨@s€äpéãUP.”¿”mÌ—8µ¶eãßÿýßqÜàqø]ÿóÎÑ#Gpã7âŸÖýþ÷þÿßNþ¶{.½D»'Ú'BQœö§ájõjw{~éBoã¿’eþÖc=ðÖò#3‹½—1oÆŒ Ñ©_íÔÃ’RéÁC|_ÉÙ#(ÛV­:þŒüŠÐP{†œÕˆäT5rtx‰ÿ¶åÏþÏË Qé’¤|ßüŸô½Ÿ^ŠÈ¾ø ÇûÙÂg±[ÜÐÚ2™ƒHBÉä”LÊ™p;k‘†7 Ÿ|¿àðÌaüüðÏñ“ŸüO?ý4{ñ1|óoâ’§.ìûï}ØyÑN<²îœ·î<œpö xé‚—°áØ=ó¨{,¿îô×ÒZ.¹-U•Ë#]ˆ+¯ô–J’µÓTUü.¯¹Çï$— •·)Š·=@ܧ(^@>Mù:òyr’j¥ËëTÊKJÄbÞvä1Èדo‡¼<Ðu/”î¿m‹mÉ}–uXåýþKŒjo³âª?$§ZWÿy•ÊvÈ×û«¿ºßüæÃ+úŒ×ã÷õE`nâ;ø×Là`HæqßK/!vóÍKf-ûg2AO%TlÈå–—L‘¶ãããxå+_‰7âCúÇÁùúâà8è³m/GÇÕú¶¥5ç+7ÝT2P–²>DN´+ FœÉFlÞè.@p‘Éçó¢ð|$²d:‹\;]vÚ&“I¤R)w$ƒ\'\¢: }= ÿÁbïíƒò?g3`žr¢¹«€E qÊ·¡m>‚Äô5°m CCq¼npoýîw±îÊ+ˆ%2eZ¹&5áã: D¼Ûrô¶<_ªàôˆwŸÕýy`&<ƒ)c –ãÀpîì,.¾øbœyÑEn¡t7ÙQZúôÓOë×cæç?Ǧâ¨YÇqðýðö+¯Ä×þë¿pý+^GN: /wÜwß}¼$©¿¾I5þs2ÏÏÔ­.ùÍo#ûOç# _u‰Ñ ¾üJØöiˆÅŠm–åö>šwoÎ8ÀÅ%Û1“I|ï{ßÃ~ðüò—¿ÄáSNÁ¹×]‡;_ÿû¿7<~!>ù`||o¾ür|èê«M+=¿Z4·.§#:‘ý±%{[ý4­t©>9ÜÜ_?@~Ÿ´ÊJ¶µ’Iä+ùZ©¶o­œÄ¾’÷³Æë?sò3-ܹã_&Ο(‘ÿ;¾ß‹·ÝñÈ8ëKgáÄœˆÏÿô½Ô‡ÍÇmÆË_þr¬Çz¼vãkñÖ¿x+BC¢Ýl¦ÅëÈeÛžðúâö¬âëª3¦üŸ} bæ“Sü9‰Ò¿ ¹,œ ‘ø‘3˜|uÏÔ€( )IG9[Â/æ7#â1ø^§8;U“·Åב3ÊdJtyž,æÿ²b{%½_ry?Puß>Û,š|Ì0 ÙÉÓáâ~?5wÆ—.7hÅ¿}͆˜ÕÏS³ÅŸ(Å™qªo©<Í¿þÙ¸“†Š·Ée-@QÅmš\ê/î{¼|ÏdLÞfÁK"—/ï8 Äò1¼ìe/kîox° @â;.‚8¥ó€ª"HÀ¶md‹«9ŽÃ0xmI¸„J¡P@¡P@(B(jøyé›{È~ î—»»©‰Ò©Â)àØÇŽÁ²,|ð§Ä{ßð^\û̵0þ@Œ²[¯¬÷ž§@œ±4­¥í*êGÎ?Í$TVŸÎ-@ôý¿DîmŸ~åu@Bõ.xì¤;<ä¹çžÃwßù]¼ç±Ç‰D¼%;âq<ý²—á±bòS×u·­¥ O°<ÑÒZ¶’øLÿêaXÌ!q÷Ü5†‘¬Žˆ;rv†a`xxŠ¢ ›ÍBUU<é8øhqÞ»\¨ZÍ¢µlEmÛFfm$J—ì’ë©«ŸWÝeBÊgÈ%H’ɤ(<]œ5244„\.‡d:ìà [(vdl g* >üÁ–lçú »Ãe4©-7>Ïýù,R¯þôG œú,0 Äbç–þ‘Õum:€¹ŸÅŸýÙ9¸í¶ÛðÈ#ॗ^Â…¾q#¶j.¾øbüø¼óp•?ήº 0MŒžupçâ¶ò}òuäÏr­I®ÕcÛÞþɡؒ?™Âs8̲ϟZqí%€YœB69YR—sþ÷áÁÄ<€çž{Ï^w„öN =ŲJŒŠ•ÎLR vq …":ßËWS°ËÖ†rt`ÒÃ)³ôulˆŠÜþïÕðb,˜óO—ÀÒ5¨Ô²×‰¥k]%‹ûšò}W$“^òÕ h@.å%%RVéë¤á­±/e¯“0]¼6wŠûjø^' ñ}uÔ÷¾E|¯#ëSÅb^›H/¾Ž\_Ïð¬ïuäþÇ}S‡èš÷ùä öó o°JÀtÊûþÌÈûŽ7@W€Iß4˜ 3Õ}ÿ£XxrkÁJûmáÉW=€ÜA@¹èBq›ªÙ, Ã@Þ—ðÃ'€7jÀKŠw¸À68xöÙgaÎÚø‡oÅñß;7½ù&DoˆbÇs;ð¾÷¼(¶UñWQ –ó²ö2Ëí'³ý@iÑ=IföÍ‘ú亩Šïñ¨ð¼V¼Ž<·öÒëøF˜4ü:åïw#¯#gR”mç‚û/Âèy+ÏôûîDäÔ@»ð¿×ýVéHœX Üq¾öµ¯áöÛoÇèè(æ>þqÞì±÷?ÿÇqܵÜeÝ’H$UI™p‘ƒäEkªe6‰ºÝJâóÈùçcìï«·?mÛÆŸ~ýë8餓pÛm·á„NÀgœ‹.ºñx?ûÙÏ*.yUù º^E„zí`U]ÚÉ»’×!ê€?Ëg`n}.9ðàmÙ‚s¯¹oO$°~ýz'åuË•×lëkU»XWåƒTuécÚñ:±XýïŠzßšVy­«F_GÎÔYîëÈuÆ–s<*êïk$R{àŠ@M”Îð+ïýk“=}éÓÀz^3m[së#pæï„ráKnO&“0M“““nÌ& Ö¡@ TB%“É`ïÞ½‡Ã˜ÅÈÈÂápÍŒç‘#Gÿ͇‘8íSP&‰S^vù[ßúþ¿»ñÌ~„W¿ð.øÅ/ð¯¯|%N{ñÇÞFl»´–®•® +§A–“ç.K×CUÊn¯ö˜â”Ð~ˆsÎ;çêç.}L _ÇM2UzL‹^çÛ}¿¦þÚÒâí:žV¾Žojç¿~û_ñ6¼Í{ŽœÆë§Š„Ê/ð ôºåÆçã?ŽMûǧ^ aîg—–4BlÛ†iš0 Š¢àõ¯=vÄã¸ÿþû‘N§aš&²Ù,4MÃË#|[¾Ý:¡Ž7ÕSSSËEP½ò™´ÊrãóÈ‘#H& H¼P^ÿ:÷öò$Êé§ŸŽÉÉID£Q7™â¯‰ÒirtT8ÜýYí^ù›î¥Ï¤VÒ¶õ“•2rõÕWãâ‹/ÆüÁààÁƒˆÅbˆF£ˆÅb0 ªªºEok%<åíí¬-ÆsNðôÒgÒ ÍÆ'˜¦‰¿ú«¿rÏ——]vÎ?ÿ|¼õ­oÅßüÍß¶3ˆÓÁÓ+ŸI«¬(>‹É˲`†;ÛRÎØ,?'ÊAðÕSUµ¸zžæÖû’ÿçóy¨ªêÎö”?뺣¸µaâÿâ2¸¦iŠÇg£”<§ø÷9é4~ó7Ÿþô§ñº×½nÉëhš÷Ôõää$†Ói÷÷H$Û4Ý:¢r)NYÃÌ}Îðpés|Kv¶ò9¯yÍk°ÿþæ^§øž·rß²Ù,âñxÅçøßsÓ4‘H$ðþ÷¿»víBÖ÷Þþ…ðÔCaݺuxöÙgñÃK/Åw_ûZ<ÿüó¶[é¹Óùü1ħ‰É½}nßL¤hš†T*å~.%ËÓ®‚ ŸKºáúj-žÃŽ[\\\ìôNâx÷îÝ0}ÓGFF0::ZóCyýÅ¿Óú=è‰Ûqøç?ÇÜÜyä<ôÐCxæ™g ( ®¹æ\rÉ%غuk§³ª|>\~ùåÞ•¦e2Œuz7Vå8~üããöÛoÇ»Þõ®ž.x¾’øÌd2˜üû£P§_}/î½÷^<ûì³xðÁqþùçã„NÀÕW_gžë ¶l ^‘Å^ù›^Kß3?ÿùÏñÀàßþíßðïÿþïÞݶZI|^uÕUxõ3¿u¯ŸÆ‘#Gð“ŸüÏ=÷N8á躎/ùËØ»w/¾üå/㦛nÂgœÑéìèÇ?þ1fgg{¢¨u¯|Ï4ò™<þøã˜žžÆ/~ñ |ô£íô.·ÍJÛ¶Û¶mC¡PÀc=†ÓN; —]vÖ­[‡õë×chh?ûÙÏð†7¼÷Þ{o Ï™ÒZ:çt‹F>¶m«Ç§iš¸ùæ›aÛ6~ùË_–tnìØ±_|qC¯kéoº[4Ú¶ýÒ—¾„ƒvzwÛj%ñù–·¼O?ý4,ËÂE]„3Î8;vìÀ§>õ)¼ï}ïî]»°wï^|êSŸÂ;ßùNLOOã¼óÎÃÏ~ö3pϯ[¶lÁ—¿üe¼å-oYòÿ]wÝ…Ë.» ÷Þ{/Î;ï|—]v™Û6¿ï¾ûpÞyçUý½“zå{†m[O3mÛÓ¿þœ|Þs8é†/aaa–eaÆ Ð4 ?úÑð—ù—Б¿Ý ŸKºáš7ÈñþàƒâàÁƒ-oÛf†Êììì’l`? …BÍç½tîc˜z"‚£“—Áq¼ìe/æM›‡qÞy畉ãŽ;®Ó»ÛV+‰Ï 6àgÊgñ½#G°ùÇ›ñÜsÏášk®Á–-[°aÜvÚiX·nûø_|@0ã´Wþ¦×Ò÷ÌSO=…{üå/;½«m·’ø<÷ÜsqçOoÆóÏã¯xúúúpã7âᇆªªøÀ>€x¯}íkñ£ý¨Ó‡XÕ /¼€¾¾¾žˆÏ^ùžiä39|ø0~úÓŸâÕ¯~u§w·­VÚ¶}á…°°°€·¿ýí8óÌ3qÖYg¹÷½øâ‹8çœsܸ òßÌZ:çt‹F>¶m«ÇçqLJǧžz*¢ÑhI;öñÇÇã?ÞéÃjØZú›î¶m_xá…NïjÛ­$>O<ñD<ýôÓ¸âŠ+píµ×âèÑ£xòÉ'Fñä“Ob÷îÝîï/¾ø"^ûÚ×Î9çÞùU¶+ýÎ9çàÉ'ŸÄ9眃_|<ðàÉ'Ÿ÷Ü\þ¿¼ßÿsµç¼ð xå+_Y²íj¯S¾Íj¿wJ¯|ϰmëi¦m;Âqtýð]à•¯|%n¸áô÷÷ãüóÏÇ«^õªŽ^sý\Ò ×¼AŽ÷{gnyÛ60 •ùùù%·52ÝêöÛoïô®õ¼•Äç{Þó¼ç=ïéô®õ¼•Äç×¾öµNï6QÏ[iÛößøF§w¨ç­$>o¸áÜ}÷ÝÞu¢ž·’øüÒ—¾ÔéÝ&êylÛyŽïôHýýýKn«—å$¢ÕÁø$ .Æ'Q016‰‚‹ñI\ŒO¢`bly“PXˆóóó- D´–0>‰‚‹ñILŒM¢àb|ã“(˜›DžÀ$TÂá0æççÝ5×fggQ(°mÛ¶NïÑšÇø$ .Æ'Q016‰‚‹ñI\ŒO¢`blySCÆÆÆ°k×. bffcccèëëëônŸDAÆø$ &Æ&Qp1>‰‚‹ñILŒM"á¸ÅÅÅÅNï„_¡P@¡P@(â´1¢€a|ã“(˜›DÁÅø$ .Æ'Q016‰˜P!""""""""""" šÀÔP!""""""""""" *&Tˆˆˆˆˆˆˆˆˆˆˆˆê`B…ˆˆˆˆˆˆˆˆˆˆˆ¨Ž>ò‘|¤Ó;±R…B³³³€þþþNïNÍ}”E› …úûûqÊ)§4|>Î……<öØcËÞ· W¥ciö3êôçDÝòžôÂg_->›¿Õ>¶zÇQí3 ÚqtƒnyOºý³_é¹³Þý½rîìÔ±Pófggqê©§¶ì³^í¿ùz xÙË^ÖÒ}]ciä|Y©@l7}F´2•bè®Ï¾V|½mÛÈy%ñÙéã¢ÖXI|é³oæÜÙìq¶ÂJã3èÇEõµ³}Ôj­nc·ÊÂÂ,ËjKÛ¹«-v©/~ñ‹‹CCC‹Û·o_Züâ¿Øé]ªèÿø/¹ä’’wÜqGÃÇ„ã¼ùæ›o¾ùæ%·×Ú· W¥ciæ3 Âç4ÝôžôÂg_éoºÙøëıUûž©õñ8‚®›Þ“nÿìWrî¬w¯œ;;y,Ôœ‡zhqhh¨eŸõjÿÜ|óÍîëÝpà ‹þð‡[¶¯«u,•â±ü¸Þö¶·-ÎÏÏwågD+S)6»ë³¯ŸÝж­vÞo&>ƒp\Ô¼•Äg>ûfÎÍg+a¹ñÙ ÇEµµ³}Ôj­nc·ÊÌÌLÛÚÎÝ®k*þ?´™™™ÅK.¹dñ¡‡êôn-±}ûö%'ÎåG'ó‹_ü¢ÛaRéäSkß‚v\µŽ¥™Ï¨[þWS7½'ÝüÙ×ú›n6þVóØê}ÏÔúŒ‚tÝ¢›Þ“nýì›9wÖ»¿WÎ8j yAäÿì»åoú¡‡*Ùþüüüâ%—\²833Ó’}m÷±T‹Gy\þã¸á† ÃèºÏˆV®Rl..vÏg_/>ƒÜ¶­u®l6>;ý½C­±’ø Êgßì¹³ÙãlV3ñäã¢úÚÝ>jµV·±[ÅÿžÍÏÏ/Þpà ‹lhz=º²†ÊÔÔúûû‡ÀÔÔT§w­â¾VšVÖÈqtú81::Šeí{«Þ±¬ä3êôçDÝöžtóg_íoºÙø[íc«›µ>£ G7è¶÷¤[?û•ž;ëÝß+çÎ |F´2™Lto릿酅Þr}}}…B˜ŸŸoz_WãXªÅc¡P@8.¹}ëÖ­ WÐ>#Z™J± t×g_+>ƒÞ¶­u®l&>;}\Ô+‰Ï }öÍœ;›=ÎVXi|ý¸¨¾v¶Z­ÕmìV™ššÂüüŒatt´¡ãèôqÊ/žJëÜÕÚ·………ÀWµciæ3ªwœkQ§ÿf—£Û?ûjÓÍ~¯¬ögXë{¦Ög´ãèÝôžtóg¿Òsg½û;ñ½ÓŽsg#÷SðÌÎÎbbbÀ®]»Jn錎ŽâÃþ0Âá°›”zAoÛV‹Çp8ì âsbb½øí¦Ïˆ–¯ZlÊûºå³¯Ÿûöí tÛ¶Öy¿™ø Â÷5g¥ñ¤Ï¾™sg³ÇÙªý—Û-W+>ƒ~\T_;ÛG­ÔŽ6v«  b||èëëÃèèhKÚν +g¨ÈŒ¢_µQ’$3¢;wîÄ}÷݇½{÷"“ɸ¹zÇä㬵oÝt\Í|FA:Ž è¦÷¤W?ûfã/HÇVë3ê¦ãŠnzOzõ³of߃t\½Ü¾¡¥°k×.ìÝ»}}}%÷uÛßt__Ÿ[˜´ü"°Ú¶A8vœÝöQãjÅ&Ð}Ÿ}µøì•¶írã³[Ž‹*k&>ƒöÙ¯ôÜÙìq®¦òøì•ã"¡Õí£ViW»U …‚;ÛdçÎ…Bرc‡›YëqЕ •JÙå f¹°ÿ~7{‡±mÛ6·Ã¡Þqù8kí[7W3ŸQŽ#(ºé=éÕÏ¾Ùø Ò±ÕúŒºé8‚¢›Þ“^ýì›Ù÷ W/·oh)Ã0000à.1??ÙÙYÌÎÎvÕß´]wàÀŒÁ4MÌÌÌ`ß¾}Mïk§ÿ¦°cÇd2ìÙ³{öìixß‚ôÑòÔŠM »>ûZñÙímÛ•ÆgЋjk&>ƒôÙ7sîlö8WCµøìöã"¡]í£ViW»•B¡öîÝ‹p8ì®H0>>^wÖBteBe```É1??¸l—Ìàûù³ŽõŽ#ÈÇYkߺ鸚ùŒ‚tAÑMïI¯~öÍÆ_Ž­ÖgÔMÇÝôžôêgß̾é¸z¹}C•-,,`ß¾}Ø·o …<ˆƒvÕßt¡P@(*ù[ ‡ÃîºnnÛnß¾¡P¦i–,oÑȾé3¢å«›@w}öµâ³ÛÛ¶+Ï Õ·Òø Ògß̹³Ùã\ Õâ³Û‹„vµZ©mìV ‡ÃKfÎôBŸYˬBáû¶Z¼ãŽ;gff‡††ççç;½[%¾øÅ/.Þpà î~ÍÏÏ/Þpà ‹_üâ>Ž çöíÛo¾ùæ%·×Ú· Wù±4ûáó šnyOz峯ŸÍÆ_'Ž­ÒqÔûŒ‚xA×-ïI/|ö+9wÖ»¿WÎ<jÞöíÛÝÏnq±{þ¦ûzñÙ mÛZmÙ•ÆgŽ‹Zc¹ñ”ϾÙsg³ÇÙÊ÷¹ñÙ ÇEÕµ»}Ô­lc·ÂüüüâÐÐÐâÌÌŒû{7ö™µKW¥€±±1ìÚµ ƒƒƒ˜™™ÁØØXŵ);IÏA(ÂÌÌ FGGÝ5û9Ž g­}ë–ãjö3 ÊqI·¼'½üÙ7A9¶zŸQ·GtË{ÒËŸ}3û”ãêõö -O·üMoݺSSS¸á†088ˆB¡€·8i³ûÚ©¿éB¡€B¡€;v”ܾsçNŒuÕgD­×-Ÿ}½øìÖ¶m³ñÔã¢Öè†Ï¾Ùsg³ÇÙNõâ³[‹„v·VC§÷¯¯¯cccnýYG³úÌZá¸ÅÅÅÅNïÄJÉ …Bž64;;ëNmª´ŸõŽ#ÈÇYkߺ鸚ùŒ‚tAÑMïI¯~öÍÆ_Ž­ÖgÔMÇÝôžôêgß̾é¸z¹}CËÓMÓòõúûû100ÐÒ} òßt7}FÔZÝôÙ׊Ï^jÛ.gߺù¸¨¾nùì›9w6{œÔ«ÇEž ÅYP÷¯mçnÖÕ """""""""""¢ÕЕE鉈ˆˆˆˆˆˆˆˆˆˆV*DDDDDDDDDDDDu0¡BDDDDDDDDDDDT*DDDDDDDDDDDDu0¡BDDDDDDDDDDDT*DDDDDDDDDDDDu0¡BDDDDDDDDDDDT*DDDDDDDDDDDDu0¡BDDDDDDDDDDDT*DDDDDDDDDDDDu0¡BDDDDDDDDDDDT*DDDDDDDDDDDDu0¡BDDDDDDDDDDDT*DDDDDDDDDDDDu0¡BDDDDDDDDDDDT*DDDDDDDDDDDDu0¡BDDDDDDDDDDDT*DDDDDDDDDDDDu0¡BDDDDDDDDDDDT*DDDDDDDDDDDDu0¡BDDDDDDDDDDDT*DDDDDDDDDDDDu0¡BDDDDDDDDDDDT*DDDDDDDDDDDDu0¡BDDDDDDDDDDDT*DDDDDDDDDDDDu0¡BDDDDDDDDDDDT*DDDDDDDDDDDDu0¡BDDDDDDDDDDDT*DDDDDDDDDDDDu0¡BDDDDDDDDDDDT*DDDDDDDDDDDDu0¡BDDDDDDDDDDDT*DDDDDDDDDDDDu0¡BDDDDDDDDDDDTÇšM¨†Ó4;½kšã80M–eµd{¶mÃ0ŒNµã³{Ù¶½$®›ÝñØ[GÇq`ÛvÅ盦Yñ>ê,Æj÷jæÜY-VýÛe¼vã³³:uÝÉsi÷a¬vÞJãµÒ¹TÞÎkÑîÆ¸ì=½—k6¡’Ïç{2 ‡‡‡[ÖPl'˲°yóf¤ÓiD£QÄãñ¦·iÛ6òù|§Z ã³[b³ÉdCCCKâš±Ùݽ¥ÑxL§ÓK¹†a¸1>44Ôõà^Ó‹± ô~¼6{ã5hz1>»%6;yÝÉsi÷éÅXz?^«K^‹öÆeïé…¸\³ •^eš&ÇéônÔF‘H$099‰ééi˜¦ÙõÁDTK·ÄæJÙ¶t:ééi7® ÃX³  ¶^Çf†h4Št:½ä¾d2‰\.‡ÉÉILNN"st-µ]/Çk3çÎZ± 0^©ýº%6;qÝÉs)M/Ç+¯C©[uK\Rek&¡’Ïç±yófwÜqˆÇãKþhe&|Æ H&“H&“%_À–e!â¸ãŽÃÐÐû¥><< Ã0°aÃlذ†a ™LbÆ ؼysIu9­EnÇ¿¿JþoääáßÓ4ëþ¾œíÕ:>ù¥‘H$Š¢`nn‘H¤æ1Z–å~6r›µFôø?Ç囉ÍJ·µ+>ëÅK­ïŸX,¶‰D³Ùìb$)Ùf¥ØläõhuÕŠÇfΕ‹‹ÿ ¶*å¶ZÄg#Ûlg<Öz^­xôÓuÝÝG¹Ÿåï}ùchõ¬•s§¼¯‘x]KçN¿JqÈxí¬vK;›r[Ýz.]éu'Ï¥kÏ¥•·Ñ©si½x]ɹT~6ì'êì¿­¾Nôß6'kµÿvM$T‰Äb,+¹MUÕ’?0È?Fùe³ÙEMÓJž‹ÅÜÀ–äïÿ½< }l-JD¼o9)OøüÞÈö9>ù¾É¤ü½üµË1N/*ŠRõ³•¯‹ÅE)é°­õ<ê¬fâ³Vl.../æÚŸÍÄf¥ÛÚŸõâ¥Ö÷O"‘p?;UUëÆf#¯G««V<6s®\\lüo°U±(·Õêxl$>Ùf#ǸÒx¬õ¼ZñèWÞÁSéÂÁÿùÒêZ+çNy_£@kåÜéW©3–ñÚYí:—v"6嶺õ\ºÒëNžKמK+o£SçÒzñº’s©ÿ5ØOÔØ[};è¿m$NÖjÿíšXò˲,wúŸ¤ªªû³ã8%ÓqËkÛ6,ËÂqÇçþëô”£ò}\)ÿûÐÈï­¢ª*r¹t]G*•B,[òžV:ÆòiÓŠ¢”¬9ëŸÚæŸ6WïyÔ9ÍÄgc³|WªRì­V|Ö‹—JÇgòù<¦§§‘J¥077˲ܵ£«Åf#¯G«§Vj=¯VßPCÒ¶m÷ó‘Ï“Eýï„›H$ ªª;*¡Þó¨sš‰OÆf{¬$^d\ËÏI>Ï_X›+}=jZñÈseg¬4>j=¯V_×õ@6|TUE2™D6›m(³Û Š¢ •Jahhº®»ïg,kèøâñ8TUuG"$‰Š•¯qÁ,ëy´ºš‰OÆfûöu¹ñ"6þÏQÓ4$‰%›òsb|G­xä¹²sûº’ø¨ö¼ZñXï½H¥RˆF£Ð4 –e!•Jµl ;-ÏZ9wÊýí†x]Ísg#ïãµsx. Žf®;å1ò\Ú»x. –•Æk­si%ì' 6ößO«¯G+鯏<®X@fM°,Ë]oÏßhqÇRä8t]ÇqLJ£G.Y'Ó¶m(ŠØ?v¹åÇDË}?MÓD:Æää$LÓlûóhu5ŸŒÍÖi6^V+®©½*Å#Ï•«/ˆç=ùÞ©ªÊ%J ×Ïþý r¼®ö¹s¹Ûe¼vÏ¥Á±’÷“çÒµƒçÒ`Yé{ÊëÐÞÂþÛ`XíëÑnŠË51CEªö!8Žƒááaär9hš†d2YqýÆÕhðض]³`’®ë5§:Éý«5å¸Þ6Ú±_Õöu¥ïçJ§{qš ÍÄg·Ä¦Ì°·2>Û›þç.W'âšZ¯R<öÚ¹r-Äc3Ï«†?ÁÒëçN¹Ÿ@kÛ¶A‹Õv}Œ×ÎZ çR ÷¯;åk¶c3X‚~.‚¯í:—®ô=åuhoaÿmcÛhÇ~ÕzÞJå:¶ÕÖTB¥UU‘ÍfÝ?bUU‘Ëå:²/²€R­}]m¬Æ6W²+ÉL9£Iõ%>[­Ž¥vlo5ã…ñÙ=‚‹ã±]Ï£Þ”xe¬• Jl¼îld?×kãuu··Úã݉q¹:ûåßÖj^vS\®©%¿ˆˆˆˆˆˆˆˆˆˆˆˆVâøNïQÐ1¡BDDDDDDDDDDDT*DDDDDDDDDDDDu0¡BDDDDDDDDDDDT*DDDDDDDDDDDDu0¡BDDDDDDDDDDDTljÞfýßÿûqá…vz7h {üñÇ¡iÎ?ÿüNïJ üøÇ?Æý÷ßsÎ9§Ó»BkØ<€w¼ãÞÀùÊW¾‚³Ï>»Ó»AkØ3Ï<ƒþþ~\}õÕÞ•ÀaÛ–:mÛÊ~øaX–Ŷ-uÛ¶•±mKƶmulÛR§µ£mÛõ •T*…w½ë]Þ¦:t›6m¦M›:½+M»õÖ[ñ¦7½©Ó»±jÇqèÐ!àEg™ÿ÷ÿþ¾ýíoã-oyK§w¥i½ò7½¿gn½õV^tV°{÷nÜtÓMÞ¦>|‡î‰ —^ùžiô39|ø0ôÄg×jŸùÌgzâoa-žs‚®ÑÏ„mÛÊ,ËÂ¾ð…žøÞZkÓÝ€mÛæ|úÓŸÆÞð†NïFÓØ¶ ¶m›ô¶mÐÏ%Ýð½ôxoGÛvÕ*…B…B¡ä¶ÁÁAôõõ•Ü … …ênïÔSOÅØØØjFËe2„Ãa„ÃáNïJÓfgg{â3iô82™LOŒT«›þÇ4Ÿ\pÎ=÷Ü5õ·tkñ{fvv¶Ó»Ú­ŽÏ“O>¹'þ¦§¦¦055ÕÇÒ+ß3~&òq½Â£þïØFb·Ü\Ð kñœt~&½Ò¶ªÇfù}R­ø<çœspõÕW÷ÄßÂZû›îk­m ´6>7nÜØÓlÛÏZlÛ¶ºß6èmÛ ŸKºá{!èñÞŽ¶íª'T2™ &&&JnÛ¿?Âá0ÆÇÇ‘Éd088ˆ™™Œatt´æöVûÚ"Èx˵ÿþNïcjÅ&€eÇçå—_ŽcÇŽuú°Z¢Wþø=Ó½ZŸ½rî rÃw¹zåoº—>“Fe2Œcpp…B}}}¸å–[Ð××W7v{Ï9ÁÓKŸI#jŦ¼­Æ'ÿ¦ƒ§W>“F1>+ë¥vT¯üM÷ÒgÒ¨V÷Û]ÐÏ%Ýð7Ø+ñ¾«žPYXX¨z"Ìd2Ø»w/Âá0fgg122‚p8ÜPÆ“ˆšS+6Æ'Q'1>‰‚©P(`ß¾}8pà€›¨ÔuãããØ¹sgÝØ%¢ö¨›@ýs+µã“(ØØoKTßñ«ý‚SSSmjj ýýýnÀ ``` g¦Ì]µØ”÷1>‰:‡ñIL…Báp¸dÖ×Ö­[1?? vìQûÔ‹M€ñIÔ)ŒO¢`c¿-Q}«šPYXX Šá^z饨²e ÆÇLjõÖʶ¿¿ɺ}å|ðAìØ±c5ƒÈµcÇÜzë­Þ¦ÕŠM`åñyë­·"“Étúðh šÅŽ;päÈ‘NïJÓÚŸGŽÁŽ;J¶C´ZäRO<ñD§w¥iáp¸dŠûÂÂ&&& …êÆn5lÛR'õJÛ¶VlÊßåÇ'Û¶Ô)²mûàƒvzWšÖŽødÛ–:©—Ú¶íì·í¥PÔ=2™L[Ú¶«šP‘#vî܉ûî»{÷îE&“ÁÔÔTÉh©ÑâFkq­6 †ýû÷ãMozS§w£iµbÀŠãóMozSà×£¤Þ400€ýû÷cãÆÞ•¦µ#>7n܈ýû÷wýz·ÔFGG166†³Ï>»Ó»ÒRî²£££uc·¶m©“z¥mëW›@ýsk5lÛR§È¶í\Ðé]i©VÅ'Û¶ÔI½Ô¶mg¿m¯Ôñ¤î266Ö–¶íªÖP‘)cÛ¶mî´±r…BG´ jÅf8f|uã“(ذk×. ìÙ³§d„Z±KDíU-6Æ'Q§1>‰‚‰ý¶DYõ*åS¼úúúˆ -Ÿ&6??Ïu3‰VA­ØŸDÄø$ ¶íÛ·# Á4Í’Žžz±KDíU-6Æ'Q§1>‰‚‰ý¶DYÕ„ÊÔÔvíÚå®Éç_+3c~~ÞÆ9;;‹B¡€mÛ¶uú="êyµb㓨ƒŸDÁ5>>Ž……lݺSSSî¿B¡P7v‰¨}jÅ&PÿÜJDíÃø$ .öÛ5fU—üÅìì,FFF …033ƒÑÑQw˱±1ìÚµ ƒƒƒ˜™™ÁØØG"­‚z± 0>‰:…ñI\…B…BaIù;wbll¬nìQ{Ô‹ÍFέDÔŒO¢àb¿-QcV5¡{öìÁìì¬;-Ì?Ê`ttáp…BaÉ}DÔ^µb`|uã“(˜ÆÆÆj¨®»DÔõb`|u ã“(ØØoKTߪ'TÔ,XÄ€$êœzÅÄŸDÃø$êN,ÔI\ŒO¢àb|uûm‰j[Õ*DDDDDDDDDDDD݈ """""""""""¢:˜P!"""""""""""ªƒ """""""""""¢:˜P!"""""""""""ªƒ """""""""""¢:˜P!"""""""""""ªƒ """""""""""¢:˜P!"""""""""""ªƒ """""""""""¢:˜P!"""""""""""ªƒ """""""""""¢:˜P!"""""""""""ªcÅ •……LMMavv¶ÓÇ@DDDDDDDDDDDÔV+J¨d2lÙ²;vì@&“ÁÔÔt]gr…ˆˆˆˆˆˆˆˆˆˆˆzÒ²*Çþýû±ÿ~@8Æèè(¶oߎ………†·5;;»äñ…BSSS( ~oˆÖ¬J± 0>‰‚€ñI<2þ¦¦¦ªÞÇØ$Z}µbÓ?ã“hõ1>‰‚ý¶D•-;¡255…ÑÑQ„Ãá’Ûwî܉P(„™™™†¶S(°}ûö’ÇcddûöíÃÈÈÆÇÇ;ýþ­9•b`|ã“(x2™Œ»wïÆÈȈ{áÉØ$êœZ± 0>‰:‰ñI|ì·%ªîÄN½ðîÝ»—Ü–Éd°wï^„ÃaÌÎÎbddáp¡P¨£oÑZR)6Æ'Q0>‰‚¥P(`ß¾}8pຮc||;wîdluH½Øxî$êÆ'Qw`¿-QuËž¡‡1>>¾¤^Êøø8 …ën#“É``` ä±SSSèïïwg¾ ``` êôO"j½J± 0>‰‚€ñI<…BápØí€­[·b~~ž±IÔAµb๓¨“ŸDÁÇ~[¢Ú–PÙºu+FGG122‚Ý»wcffº®#“É`ll }}}5Ÿ?;;‹‰‰ Äb±%·—g4ûûûë®É÷àƒbÇŽ~iÚ±cn½õÖNïFKT‹MyßJâóÖ[oE&“éô¡Ñ4;;‹;vàÈ‘#Þ•–O+ãóÈ‘#رc§hSGŒ#“Éà‰'žèô®4-»5`aa…BlÛRWê•¶m­Øض¥î#Û¶>ø`§w¥iíˆO¶m©“z©m ´¯ß¶|`>ÑjÈd2miÛ.{ɯññq·½,B488ˆp8\7™²°°€]»vaïÞ½K+G#ø52eì‚ .(9­¦ýû÷÷ÄEU­ØVŸozÓ›066Öéã5h``û÷ïï‰NÉvÄçÆyE(ê¹ÑlÈd2n;¹Rû€m[ º^iÛú•Ç&À¶-uŸ^jÛúµ*>Ù¶¥Nꥶ-ûm©×´«Ý¶ì„J¡PÀøø88àžðeÜeæçç1;;‹þþ~ô÷÷W|-ÿ4P"jZ±900Àø$ê Æ'Q°É ÏB¡€={ö¸Ë 06‰:«ZlŒO¢Nc|ûm‰³ì„J,Â;Š \¥Ûü°oß>"ð<ˆùùy·6‹ßüü< ­’j±)×Åd|uã“(¸¶oߎÁÁÁ%#ï›DU-6Æ'Q§1>‰‚‹ý¶Dõ-;¡b†@2Àüî»ï¾ªÏ-Ÿf³cÇìܹÓMÂÈ h8Æìì, …¶mÛÖé÷ˆ¨çÕ‹Íp8Ìø$êÆ'Qpcaa[·n-Yæ! 16‰:¨Vl2>‰:‹ñI\ì·%j̲*cccm[lll »víÂàà fff*rOD«ƒñI\ŒO¢Î( ( KÖ´ß¹s§Ûffl­¾z± ðÜIÔ)ŒO¢îÅØ$–Pñ›Åüü¼»Žûr•OïE8F¡PpG'Ñê«4õšñI ŒO¢à¨7Ј±IÔ d|u㓨{°ß–¨²%TÆÇÇ‘Éd°°°àÞ …°wïÞ¦‹1 ‰‚‹ñI\ŒO¢`blã“(¸ŸDÁÄØ$Ž_¦Éd066†»îº ÷ÝwLÓD8ÆöíÛ;}¿4ybKרtºô÷JÛQÕ¥ Ë·—ï[Ðf®œ¸’'íÙ³£££˜ššÂüü<¶nÝŠmÛ¶1™BDDDDDDDDDDÔa¶-’©”w›Lžèºw›e‰ÛEÜ.ºîÍ\‘·išxœÙ¬÷»iŠmÉç©êÒdM:ímÏq¼íY–¸/—ó›LÓÓÞïŽ#^C×K÷c5-{† LMMa||;wîÄØØÀ0 ,,,tæ(ˆˆˆˆˆˆˆˆˆˆˆÖ¨ò•–ì²íÒÛý áa‘ЈÇHDüЦ)~/_̲Jg˜¦¸Í0Dòfófo–ÉÐØ†¼/¯—N‹Ä‰¦•n˶EBfhذAÜ&÷¯|ÖKù’b–%ö»–=Cevv;vìÀèè¨{[(Âøø8¦¦¦pàÀöì)QdÀ?K£Û9ŽHTÄbÞmš&’ÀÒ™"ÃÃbæJ<.îSU/’ÍŠ÷FÎn‘Iy[:-nO§ÅkÈY/ù¼7ËEÎz‰Å€D«bšbŠL¨ø÷Gþ¾y³—\Éf½dI2)¶)÷Û¶Å>ÄbÞë9Žx®<Þ«¯ný{½ì„ÊÁƒ1::Š={ö¸·…ÃaÜrË-ÁÔÔÂápë÷”ˆˆˆˆˆˆˆˆˆˆ¨ ²s¿[*Žã ¾÷Üó÷6YXÞ²¼¥°òy‘Xpo™­XÌ›ù‘Ï‹÷@×½ä‡eyïK.'’‘ˆ÷Ѩ—¨Ñuñs2)¶‰xÿ;Žxl,&öG&KäÿšVzL¹œxN2é-!æßÒãþìÏðÕ¯þ!&'ÿ†áͰ‰D¼äŠe'ôë8é¤ÐÊtŲ*…B¡PhÉí}}}¬¡BDDDDDDDDDDU©øy%“"!÷9ãÞ{s¸å–gpúé§#3?TUgnNÌP9|øçxè¡¿Å;Þñ4EBC.ÛåOn( pôè2" ¨Åmضé&O #Žx<Çq044„ÿq¸Ê{oÁñW¯#N»‰H$ˆÅbˆF£ˆÅbPUŠ¢à„¾U-Mô(Šx¿åW~ÐòÏrÙK~Àž={0::Šƒúûû±wï^&Sˆˆˆˆˆˆˆˆˆˆ(䌊htõ_·| ­JŸÇ5×¼Ã0г3DòGQ<òÈ%øïÿ~O=u^óš;ñ®w]‡DB$RؼùÖ­û lß~:{ìÿ¨< GÖJY®£“G±Aß[µ/V»O$p¶mÃ4Mhš†ŸççÈçóÐuñxܽݲ,Äb1Äb1˜¦‰XiB–eÁ2qföLÀ÷ÞåóyDŠ…]t]‡išÀ€ioy³éiqŒýhë?Ë%T```­ß#""""""""""¢“ÔWS<.–ü²¬Òe¨,KÜ.—ÝJ&çŸßƒßù—á…þ®½v#Þð†—ð¾÷€¿ÿûS00°ˆcÇ^={€—^Z‡¿€Tê0 ¶­Ã¶mlß~:t]G¾Æúb¶½ü¥¸’É$Ô»UÄìlØnB#™L"›Í"N#ŸÏ#‘HàÂ÷\ˆ­É­ÐuªªâèÑ£°, Š¢ BUU¤)\ñÒ¸ú}WרO?xú¸Þº¾$¡299 Ó4Ç‘•ì-Ž7CEÞxÍ5?ЊôhpɯññqŒŒŒ`ß¾}Kj§Y4êoo7ÿò^ù¼˜£ª€Å«dRì· úý÷ëÖíÂÛßÞ—½ìeÐu ‘ðË_> ÓÜ€lVÌ0¹øâ\vÙà8’É$lÛv·+gmضd2é.³e_,[~ ˲ðÄO`æå3îR_©T ‘H‘Hº.:‘H'½ì$ì~ón(Š‚T1áiTU…¦iH&“ÈüJÏþó³_ËqÄãq„B!œøƒqø+¥KˆÉ¥Ð¦§§ñ/ÿò/¸óÎ;‹; ÷ýxë[ߊ7¼á mùlš¡2::ŠmÛ¶ajjÊMª `Û¶m+š¥2;;‹ùùyô÷÷/y~¡P@¡P@(âbD«¬VlŒO¢Nb|ÛÂÂæççKâOÆ¥ßàà úúú:½»DkF¥ØŸDAÀø$ ¦^î·µ,¯{3ÅÒËmÞ\:ó$ŸÿdÒB.õ¥ªâ±±˜øYU½¥·¸öÚÛñ º;sevvïz×_8¯yE‰¹³YTUE:†QÌÜØ¶ Õ—)Ò4 Ñhš¦axx‘HÉdsss%k”mÛøÔqŸÂ{œkwr†H,C"‘àÝ‘w»³Jòù<,ËB*•B*•‚eYØøÎøæ7¿‰õÖzÄãqLOO»¯uýõ×㤓NÂé§ŸŽW½êU8ñ»"…‘,¾Éf³îëŸyæ™xðÁqßý8鬓p—y¾ÿýïã®»îÂ+^ñ ÌÌÌ ní •†—üêëëÃÖ­[±uëVÀÄÄÆÇÇ—\Ù½{7¦¦¦ …P(‡±gÏb&L&“Áàà fff066†ÑÑÑ–0UV+6Æ'Q'1>‰‚O^ÈŒ¹·e2LLL”ÁÁAl07àÀƒp(y‘HÄ-D/¥R)äóyœvÚiø—ð¿à¿Þò_¸à‚ 011?ù“?ÁøøxÝZ-˵â*þäÊìì,<ˆøÃøË¿ü˪‰ù¸o|ãèëëC¡P€®ëÅÀÀ2™ öîÝ‹p8ŒÙÙYŒŒŒ weÆ“¨›Ô‹MŒO¢a|Ûøø8¦¦¦011;w–Ü·°°À ¢©›ã“¨“ŸDÁÔëý¶Žd³Þr_+)Ê^‰ey3M4Mü/“5ããÿ«®úmœwÞ\U]š|I&DB]×ñ[¿õ[Å7xqüE\}éÕÐR•3`¯ ½Ÿ9ô¼÷Ì÷âw}Âíòw÷wøçþçÖ|Ð> ÕP‘¦¦¦0>>îþ>;;‹;v “É8Ps–J¡PÀèè¨;MSÜüü<¦¦¦Ðßßïž0eÑû©©©–4•ª›ŸDÄø$ ¶ÁÁÁ’§ŸÝGD«¯VlŒO¢Nb|S¯÷Ûšfi]“ò+‘Ï‹‚ó¦i» Y/åw÷®¿þz<ùäðÃà8tÝv_ײ, ã…Ž 5Q …BQ”’/©T Gu%%œúû_âHUU¨ªêÖRi”ØwÛ¿°e/†cJî·mù|^ü¢…?/–/©ã¾_yض ˲°iÓ&„^ ¹5Vþñÿ?úÑpÊ)§àãÿxÉþîÅÈ#U÷ïc£Ç®þpãÕ7–Ì`yÍk^ƒûùÛ§á„ÊîÝ»±cÇwËB¡€íÛ·A411]»vÕÜÆÖ­[166†……LMM!“É```ÀÍl–Ÿ0ûûû—¬›YîÈ‘#nB‡hµe2:t¨Ó»Ñ´Z± `ÅñyèС’$,Ñj) Èd28vìX§w¥iíˆÏcÇŽ!“ÉtUã—zÇÔÔòù<žzê©NïJKÈxìïï/¹}aa€hC_z饨²eKCçD¶m©“z¥m TM`åñɶ-uŠlÛ9r¤Ó»Ò­ŽO¶m©“z©mÛÎ~Ûzkÿ,9ƒDòMê¨É¶mwÜqî2…åÛÿÈGeÅ‘N6ˆ×Ð4àŸÿùY(ŠŽõëC8ñćN§144ä‰F£ˆÅbxÀ•Wþ‡]¹¼™# Üd‰¢(°,Ë->ï2‹ÿ|"‘ÈÒ„Jºø¯†Gygüâ ^VÀÉŸìÞÇa"‘âñ8îþØÝ8°õº®»IMÓà8b±"‘.»ì2ÀŸ»ªªâ¶ÛnÃW¿úÕ%KzˇÕXžíâ‹/ÆI/; ÿp#ðÞÃññqœ}öÙ¸ôÒK_ÐPBENù:pà€»¶åÄÄúûû±wï^Œaÿþý˜˜˜h(@ …öíÛ‡‰‰ ·CHŽ´õkdDÂé§ŸÎi Ô1áp›6mêôn´L¥ØVŸ›6mÂàà`§‹Ö 9ræÔSOíô®´L+ãóÔSOíª©ÙÔ[B¡pÊ)§tzWÚJ®9½sçNÜwß}Ø»woC=lÛR'õZÛ¶š•Æ'Û¶Ô)²m{úé§wzWÚn%ñɶ-uR/¶mÛÑo[)ºŠ5̈eµt_] ù‘%,ËB4E.—óf`”ÜX–õë×ãì³0= hš ÇqðÈ#wàÛßÞŠXÌÁÌÌg‘Ïç1W¬\?44]׉DÐ×wßüæ199¹¼Z¾Y,röŠmÛug²,IVÈmÕ˜íòŸÿùŸ˜™™Áƒ'<ˆ;»çΞ‹³Î: Édº®#›ÍB×u躎Ûo¿o|ãqaÿ…%û¢i"þiA:=S´D"Èf³8á„*ï?Ø5öQ6¤7 ïõ}¢† €×ÝsO[Ú¶ %T<ˆp8\2sjj [·n-™& Õ300€ýû÷ãÀnqûJÕȶ֯_Ï‹Nê˜^»è¬›VŸ›6mª¹ Q»ôõõõ\B¥•ñÉ‹Nê¤P(„Ë/¿'Ÿ|ró 0³²‡±mÛ¶º¶lÛR'õZÛ¶š•Æ'Û¶Ô)²m»~ýúNïJÛ­$>Ù¶¥NêŶm;úmeÿñj3Mo–Êð0àÏ%4R>N#‘H ‰”Ô)‘R)à«_ýg|ø×⢋ŽBUh4Š¡¡!œuÖ<NÀoýÖ ,ËB$¢(îWr6J"‘@*•ZRä½þΡ¤ð»T’0Ñ$ ’>KŽÅ5 £döÊç>÷9lß¾wß}7âñ8N¾ìd<¼ña(Ž‚~ðƒPUÕ«›Q|~tt—]vÖ}u]ÉK¨ªº$Yb«6žøúî,–l6[;©dÕ¸]&ÈTïqçÝqGç*ÀÒ¬ãÔÔÔ’Ñ9õ‚c||ûöí+yüÀÀ …‚û¿ßüüvwõß…\.‡X,V’À‰Åb8ãŒ3Ä/y,Yn¬„ \¼p1TËK´hš¶4±$WðRëlORP2{§J¨ô÷÷—Œ˜˜˜€’Ñs ˜­;…k||Ü]S>' !»EޱÌX¡PÀ¶mÛÚû€ê± €ñIÔaŒO¢î355…]»v•ÄîÄÄDà/:‰ÖÆ'Qp1>‰:«—úmóy‘øÿ–;Ķí’Î}UUñõ¯ßÓô¶yøðahš†Çþä±âkæ‰D iÅ{ÍD"ëνÎ]ŠªYŽãà‘u”Ì<‘ ŸÒBÌÖˆ‹Ÿ“Éä’¤5<øàƒX÷È:wù.ø‹¿ø ¬[·###زe àš»<ð6=¿©âÒaš¦aýkÖ{3gjÕ©Q»7ÜûŸ¸¿öÁF寫l϶ÛóÀÅ"0v¸Ç\Y­A'6ò ­[·Â0 ìÞ½áp†a”L×ZXX@&“q× ¬fttA(ÂÌÌ ¶mÛ†ÑÑQÀØØvíÚ…ÁÁAÌÌÌ`llŒ#ˆVA½ØŸDÂø$êN£££˜-‰ÝÑÑÑ’Ø%¢Î`|㓨sz­ßÖ_„Þ4—.ñU\y«Æó­’%ªt]Ç_ýÕ‹H$€³Îz7Ü0‚W¼âmˆÅþýõã–—Ý‚üKyLOO/ÙV,‰ -aYÖaŽ|æ®p®‘ð‘3] À®ëP¡âÞóïʼnWžˆ;®»‘÷âŸp·•N§1zÁ(^øÑ øÏýœ«ž‹+¯¼¯ýë1:: MÓ`ø ÎÄãq\þ©Ë«ïœœCͺ,Ð?Þˆ/ú"öµ¯úã´²ÿË?ähx•ÜgHˆËß'7O¶æÍ® ¡„J(Â-·Ü‚]»va||ápØ-N?55…;v  aïÞ½u·µÿ~ÌÎκÓÂü£ FGG‡Q(–ÜGDíU+6Æ'Q'1>‰‚oÿþýKnÛ³gOÍØ%¢ö«›ã“(ŸDÁÓKý¶–% Ñ›¦¨R^š#™„»$W9Ã0J–û€³Îz%žzêSÐõmxÏ{îÃÓO·ÝVL(ÍWm½ }öU.úÔ-üÞÛ¶‘N§E-–ï¤ÄŒ—— ¼g–†Û¶aš&bj GŽÁÓ=×¾öµ¸B»pÕUWÁ¶mwFË…o¸ø%pî³çÂ0 ,,,àãÿ8²Ù¬;ãŽüê8Žƒÿzá¿pµuuå$‡L¨¨K’U«U“~sè7ñîÑw£ÿ®~àÊ*ó'¾b‰)¹MÇr9@Õ¼÷6‘þ,-¦MN™Lsoz %T±F»¿(488XR0¬ÑmUÓ IÔ«êÙd|u㓨;±€5Qp1>‰‚‹ñIÔ9½ÒokÛ€®‹¥¿, h´L‰mÛˆÇã¸ðÂ+‘Ïg‘ˉÛãñ ñüóçfg/ÇŸüIéìœ÷¾á½¢Ã¿ Õ‹ª7 ŸÏÃ4M7qòÓ‹~ èÀ+­WºKlåóyضX,Ó4qà[pÁk.ÀýÜ3½Ïõ§?ý)¢Ñ(TUE.—µIbÀ H¾=‰¹¹9˜¦éœ—KŸ)Žû°^s‚¨UR‰¿†I¥ ?G$vpj×FI˜ôž^B¥¸î{+ßÿk¦ÑÎB* 'Tªéëë[V2…ˆˆˆˆˆˆˆˆˆˆ¨]ÅbæŽSyy¯òÛâñ8TU…¢(ˆD"(þ[¶ˆ„L$"&;D£Ÿð*¬[w…Û—ïjÑr^_¾éË8ýէ˜!£ª*’É$ÇAB€M›6á¥7¿Ü)jª¤Ói÷>UUaöîÚ‹óp´ë4QG¥è¹çžC*•r&0耶ÝBó‘ ¨—~9à’§. TN–8ðr*¼Ù*•ÈÄH²Á7GCåä‹]öþÿµöë6©á„J¡PÀ¾}ûP(Ð×ׇX,ÆDDDDDDDDDDþÚìr†I¹dÈfÅÊP¦iÂ4Mwi+‘¸Ð iÀ† ÞÊRŠ¢ N㥗¾VšPÑÑXç}¬þC~åÄ_ó¨ëå,ËB2)² 2¹"=°åä¾Ã‡¾ÿ!ض UUE­–¢T*…oþå7qݵ×ÿ€/?rÖYgyɰûï¿ç|ûüÑ%T}çx3ã'gü¤úòe&Ä,^¤Úqûg¹8¨>ëERá¼/ߎÿöš^^­–ã}àŽ;055… lß¾…B¡}{FDDDDDDDDDDÔ Ûöþ5òX@,••J¥`Y"‰á8òyq_,æÍfÑuŽãà;ßy¶tCZý× fuÔXöËq|ð§ÄÇö}Ì%¢ëº[ËÄïÜgÏÅu¿qÆ9˲J’) in¼ñF߯½ý‰8pñÄ8¾ö‰¯aÓ=›ªïàtÛÆÍßÿ?@®Æ´ù~ÔZfÍ?»%‹Æ fñ=L–½¾ÿˆ9Ç×àF—§¡„ÊÔÔ …8€±±18pýýýoËN-ÇæÍbF‰®×~œæK‚˜¦éΉD"0M1sÉùs"‘Àôô4®¼²¿tcD½š/1SÃuZ†††`3:¶mÃqDFáCg{éߺ³eä\åN™9†a@WuÄ"K§€(Š‚‹ßx±7;Ĩ¼[Žã`ãÇ7âÀK’2%l}~õùça'@H«¿Ì™†êñçCé*+OÊèÅ÷:ï{ÃͲבKifº–§á*áp}}^±­[·¶e‡ˆˆˆˆˆˆhõÄãÍoƒˆˆˆ(4 P/ RO>Ÿw—¿Òu‘HŽÓøó&g¦h€eYîòa¶m##ŸÏchh—]v6·ÁM¨T³nÝ:X–…çž{®ú¬^"¥ÂlÃ0N§±qãFœyÑ™µ÷_©^½gp[ ±°4©’L‡}Õ®]˜Þ/`¼(àÔzkˆ­LÓE鉈ˆÚ)ŸÏömX–åNKD"uDDDTãˆõÅE ðSU1’Ó0"xõ«tz÷ˆˆˆˆ–ͶEû&Ž­ýXU•í 1;%T5MÛ©7Ã¥DªÇ‰TL¬€IDAT83+4@ÕTär9$“IÄãqd³Y¯J5—ó››› “ZyÝ÷Y¡vYÈ>õJß(p‹Ô—°@"—ð~ÏC,×å+Û ¥ËyY–h|þÑ´wÛð0›[ºïvñ5–LœIWÕù€4ö>.WÃ3TˆˆˆÚÍq$“ID£QlÞ¼6l@:†ã8îÚ¡š¦!»…Ùˆˆˆhù C\»Æãbmð|^$Y^ÿúC8ãŒ_tz÷ˆˆˆˆVD&B”:“dBÅ4Eö@&c€¬•DéVÜýßwã¶Koñ»!CQ7‘bFC/SBÆ0féãä Õ¹¹²D†Ž¥ šdøšQZ§D/nÓqÄýfqЉ¿NŒmqG$Fl[¬Ç–L¹ð¨ïEtø´¹tÙ/•ëÓ¼À5–'“û÷L{â6„²ße²Äÿ¼7U}¦Ž¬ Cõ%¿ ¯¹ó5˜™G+-«(}&“®ëÈd2˜Åìì,vïÞn¸ûöíkéŽQpäóy öm˜¦‰x<ŽT*…¹¹9¤R)èºîQÓ—±fˆU¬øfÛ6ž"©uZJçw^§ß:""¢¦Ø¶HˆX–ø?›ýl[$Pl[¬N‹ëÐDBÌ<‘×¾‘ˆxŒ\âK×Å¿T#£úˆˆˆˆºˆiŠvO5ù|Þ]nüw÷%|ä#ëšQÞ2]ÅY%š¦arrªªºõa/½ôRq§|l5²›#ŽÊ³B‘Lð× ‰¡´Š[þn–´x®¢(°,Ëëƒ)ïZñ'?ê”ÑPšl©´Ï €\Ù}Õ–UsPºœW5ßãâ(ñ"%“xæŒÛqâSËžSRSÃ[Ëd2Çž={0::êÞ¾°°€ññqd2ÀÎ;[ºƒDDÔy†a ‘H Nò,d³Ù’Ú%š¦•ÌLi„®ën´z‰‘ZdRFªVW…ˆˆ¨ÅãÞu¬¿Žg6+)€M™Ï{+%øiš¸ßªåi’ˆˆˆz‘eÕžeÇ‘Ëå`YVÍ5–÷¢À·Ч÷áÎ;ïÄßEÿ¶m#•J!QÑ’J¥¼å·lT^žKÊC$HÔ:+P¾œkyB¥øú‰Dº®{}1I”Î qkž”m«Ò¾ÄPš ª–,Êÿ/òA¥5`üû(»y4TŸÉ#Íöý^ÁÜÀ467Ðà›Ø˜†*³³³Ø·o8€Òèëës“(†a0¡BDÔå,Ë‚aÈf³Äì@46oÞ쎰(·œd ’(–eÁ4ͦ*åû"ëµu»dR$B*Í&QÑa ë^¥ÚDO9;…ˆˆˆ¨—9Nõ%¿òyÑ£/û!dŸG³îyôüÇÿW<}Ö_º±H¬ò@OY8=‚Ú3Tä `2è ö—”/½xË€ÉÛ|I“’ý+ŸU"g42G…HŽXÅŸ«%Ab†à%TjmO²P}É/ßËt…çy)ÞËkhɯ©©)„Ãá%É¿;wbaaSSS-ßI""j¿|>t:h4êÎÄŒM”VâPU¶m—B[!§x‚tÇ-nODDÔä5Ÿe‰I­kýDB\'VKº‘`š&b±XÓƒ:Ë]<Š—ßôr¼ó 6þh£»GÕ~¥Ëu•{ lÞ ô9@.ކåP–Œ°€/G½ßÓi`Þ©¼œVyâ$ào†K×O³Q¹Ž Нk@$@"¨œÜP f¤ÈüF­¶«êËùU[ê¬Íš¡2?ßXá–p8ÜÐã …‚[Ô¾ü9ò¾P(„P(´úïÑV+6ý÷3>{“\K4‘H ŸÏömw‰LP¤ZÜ[£i Ãð ¡­€ÜG]×1<<ìN©í5ŒO¢`[XXÀüüü’øclÒr ‰º'ŽS;™B©›ã“¨ÓŸDÁÔ­ý¶Ž#–G­Æ4MÌÍÍá¸ãŽkÙìÇqp×ø]øµ_ü¾yü7qþéç*oß_8½Ö •_8¢ àSUXiù­|q»²Û&Nòe¸+äcK“Kr?6pvÙtÕ—ßJÀ›!Sm)/@$dä>Öz\ "¡Rm™1? •ë§@,†#_ø6¡µš¡ÒßßßPR¥‘Ù)™L###Ø·ovïÞ‘‘,,,ÆÇÇÝûFFF0>>ÞâÃ%j½/}éK¸ï¾û:½M«›ã³›Ù¶d2‰|>¿¤ÞˆŸeY˜œœD,ƒ¦i°mÛ}N»–ÐÒ4 Žã4µ}EQà8’É$t]o*9TŒO¢à3 cIì16i¹,K,áešœqÒ*•b`|ã“(xº¹ß6Ÿ9„Ê÷åW¶òF™ù|ù|çž{..»ì2±ÒG±öHź®rà%*ù—”˜¦¬X¨’Áp*<_-ޞϋ.ª lô§®›X:Ó¤<±‘NWļ崱?Õºnä}Õ»œŠûÐÀc‘ 1à%`j‘õf*QU<·n]/¸< %T¶nÝŠÙÙÙš “L&ƒP(Ts–J¡PÀ¾}ûpË-·`ÿþý0MÓ-j/·±wï^ìß¿·Ür vïÞífD‰‚êá‡Æ¥—^ÚéÝhJ½ØŸÝÈqÄãq ömw9/Û^z6ò/ëˆ$…eYH§ÓÈårmÛÇX,†\.×ô’_ñ¸˜Û‹³SŸDÁ6>>Ž]»vaß¾}KîclÒråób ¯JÅåiyjÅ&Àø$ê$Æ'Q0u{¿­m‹œA%þ¢¹\Š£”& ª1àS.Y]nstt§žz*&''K ª×"k”Tâ_åËñ^¿„?¡bÛŃ/¾¶lL¦R"Q"ß9jç4sékû~N×#»9VúÚ*/&Éú)“uÓèr^¼Y7µ(VyVwC •P(„;wº'<ÿ¨Ø……d2ìÛ·ccc5·S(–ÔbÙºu+æçç155…þþ~7!300€ÖdYc¬¾t§þãl6pÓM_®ð|1’=cÆ ¸å–/ûž':;î8˜¦Y±ã¹ÕŠMŒÏ.•N§¡( r¹r¹¦§§‰DJRyÁ49C@K×-§(JÓÛD"H¥RH¥RM'f‚ˆñIlƒƒƒ]Rk±Iµ8ޏžu ×­–%*mšºæT‹M€ñIÔiŒO¢`êÖ~[Ëm©HDä*)DZ³H'ï –,ã%WÈð÷g¨ª*’$ ¨>ÛÃßçp¤Bߤ\~kxX4&K¦æ¨ÞÈœá²çe³Àkëì`*%§¢¤ˆ=€úEêÕ ¯Y.‚ÊI¢JúK~5²_-ÖPBÆÆÆ0:: Ã0°eË躎-[¶`Ë–-˜˜˜ÀÞ½{±uëÖšÛ‡ÃØ¿¿ûûÂÂ&&& …0;;»dí½þþþº™Î#GŽ “ɬî»Fm‘Ï‹5£kå0äEg<^ýþíÛŸÇ{Þs'LSDZcÿ½ä1ét–eáùçOõ×ð{¿·ßúÖÇÁðð0ÇÁää¤;š¿¼@·dÛ6®½öZœ|òÉ~ëšV+6¬8>:¸) Ý.™L"ºEØË¥Ói÷>˲Üå»$]׫ÎPñOy•ã»aù,MÓ–ìg¡P@&“Á±cÇ:½{MkG|;v ™L&_Z{¦¦¦ÏçñÔSOuzWZb``ápýýý%·³mK’ P:-Ú«ñ8`¢]+'WZ–X.»ãêÊd28tèPgß°©›Û¶Ô}dÛöÈ‘#Þ•–hu|²mKÔKmÛvöÛ¶s&‹m{ý…•ÆX&‹3.J`6:“ÄúÚD"EQN§‘N§¡iš— ÑáÕ$ÑP}ù)WŒ‚¥‰9ÂÆ¿ð†à †XÂ+ Çñ*©”˜bšâH¡B=ÿöt`{D<ƆØP½@¼ QëĿߵ4š(ÑP¿˜¼Ž¦%ßþó?ǃßúVs© á„ ’*ßøÆ7ÜäÉèè¨;¬^2¥ÜÄÄFFF‡1::Z±FK#ÅN?ýôšËŒÑÊ529Ãq{\>_ýqŽ#)ª*.(Ëç8â;%™_ŽÙ,ðüóÏW|L(ô¾úÕ½¸æšÃÝwÿú¯_-yœišøÊWCÓ&¿ú«§ãÍoþ9~û·?¡¡!$ $)äó:r¹ILOO#‹¹Ë ùY–…‡z¯zÕ«:ú9µZylXq|nÚ´ ƒƒƒ>¤ž‘L&Ýz#2ù744„ááa !Ã4M ‹³²,*ï§iÚ’¡L°øªªºõTº‘9sê©§vzWZªUñyê©§"®ˆ ­ ¡P8å”S:½+mŶ-âÚvhH\ÿæó"‰"WQÈåÄ5­ªŠká œrÃá06mjuÙÎàaÛ–ºlÛž~úéÞ•¶cÛ–ºM¯¶m[Ýo[)Ú*jqBF¥A)ŽãÀ4MLOO—= biªz³IlàŸNü'œuüYP©T ¶m—Ö`1QštÈWÙ®ŽÒdKyÓ¬<ÅæÅðO“"Ù‹‰ƒ•3läãåRíå Z5ù>f‹ŽVÓ>Y%»¤£±$‰ÿ˜êÍüQ –kd&O­ú( |ôQ\Þ†~¡—û„¾¾>lݺuI¥P(`||¼î²_ صk …öìÙã^0V ¬B¡Pq ¨ßúõëyÑÙù¼ˆ©ÅÅê±mqqhÛÀädímÅã"æýÅ5åè„Ãáªë2w›Vǧ¼è$ê„P(„Ë/¿¼'fÕ¶íÚ&GJš¦0dY¢]97‡’¶iÐJ…Ãá51›m[ê6½Ö¶­…m[ê6½Ö¶íÆ~ÛxÜëWl0'~ô£/aAÌÉ¡æL‰Onú$FNÁ¦'Å€“d2Y¿vk±0}Å¥ªüÝ4þÙ$²žÜ7?À}ª—4–&#ü‰YÈ]…H†TšåVEÃÔ0€Û˜±ÊkÏF  1ÔŸ¡’ÅòŠÎ×Óä •³Ï>šmãÍmf‰eÍP©E.ªgûöí…B0M³$ –LÿšŸŸçƒJ§Å—ŒY#S(g‹hÚÒÙ"–åÝ¿aƒˆ·l¶4IR‰e‰Çù·%Gëišx¾ÜÆÔÔ'ñè£Ï»£÷¢Qñ}‰XÈçó°íaüŸÿógxÛÛ~‚›nzW_}n¼ñ›˜žvððÃ¥Éذá~ã7~¸í¶l;‚ÙÙu%ß2‘“LŠŸçæÄþض·´˜¦Y¸óÎÇJŽë?ÿóg8å”Þi´U‹M€ñÙ ¶mÃò­"“òï;•JannÎA‹Åܤˆ¦iîÔJdBF2 £kg¢¬ŒO¢îÃØì}2iˆ¶­e‰Û6líJÿ€¢\ÎK¢trI/ŸDÁÅø$ê¬në·•m±DBІH&»SüÅè—ÐP·ó_7ulÜäÎ$Ñ4­¤¯ÆÝŽ¿K%ʳ*Êgz(ð ÐFõéÊ,õQk¿³ ‰‚‹ñIÔ9ÝØo+W¹Q_£ w&…iš%Åä]:ê.ùeš&®Úx•xl1¡‘ª4ª\&pd"ÁH””¯æSÞ_ë_òKÓ*wèÊç5²<–ÿØ¢³oj‘˃Õì#ëäÑXø ×Õ4àë_oùfW5¡R(P(°cÇŽ’Ûwî܉±±1Œa×®]ÄÌÌ ÆÆÆÐ××·š»Xµ•ò~¹D•?þäÅ^.'jb;rÙ¿|^| ÉבuIïvÃXzq¨ªb{ª*î—_b†!1r&\2)^3•Z:2Ï²Ä ”ÉÉI$“Iär#øßù}˜æýà.sä'§ØišVù À 7\„o|ã;ˆÇ¯Å›Þô/ˆÅ¶¯èý×uŸý쫊c:†ë®ûr¹Id2÷èîŒJ½ØÀø\ù|ù|¦iBÓ4d³Y$“ILNNºæ¡i‰DÅ%¿$9C%Nc²Öš}ÔqŒO¢îÅØìMrÆv"!Ú¼Š"ÉE¹œ7‡‚‹ñI\ŒO¢ÎèÆ~[Ó\Ú¿ @°#võ~YgÄ‚›øÈçÅ’H$R\%ÇÆÅ[/ÆeCi­Tx=ÿýåµQ¤JK‹ib_KF®WÊ«¤à-ã4–´¨7›D¾ŽúKkÅŠir ®U§ë¸ýûßoy¯íª&TdðU3::Šp8ŒB¡à޼%ÑŸLVN¨$“^ÒBÎ>‘Òi‘ÔH$J2ñ!ÅãâËGÖ6’äúƒ©”7»¤Ò>(ŠØEñj©È%øTÕKð$â1†!¾µüIÃ0J¥ iZ±`T¯ýKÈf›ëèUUµXwˆFo…¦}rEÛQƒƒŸ„¦¥ËÉdª§jNÔ‹M€ñÙn¦i“‰9ä|YËt: ˲*˜¯FUÕªIFÀ›¢*7n—:ƒñIÔöïß¿ä6Æfï1MÑέ4 TÎV¡`©›ã“(ŸDÁÒý¶±X…‰ÅÂè–jU] €—ÌO+öض|>/úf’ÅÇ-·î,æîï:Lbé¬9ûÅÿ¸JÝDâC¶5 ,-r_¾]õ ²>J#Ç×mÉ”6j(¡255U·8áÂÂBKv((ù¼Wƒ¤\2é-UNΙœ\:DÓÄ}r¶E$â-QPþ=SéuËÉu Ë“6¶]ú|±„˜øRòwàÚ¶]2O×u$“ɪË-‡\ÚHQ¶ éζ1MsMŽêg|¶–ã8nbÃ4Mwy/?92¢•I9Û«‹Ñ¯eŒO¢`blöŽtZ´ËË!Q÷b|ã“(˜‚›–åÍ.QLf˜¦Y»ÏCAIB"™LÂq¤R)o™09Ë£R2¤–J‰’J"XºœW¥×Ò°´ŽJ-1›xý˜x¯`¢±å¼@ƒEé …fggkþ+ K åRsä’[±˜øÙ_ó(™Iò„‡¢xuO*-­%e³bÊô´—D‘Ë{-‡iš®ø:•¾³òùŸÇÐÐLSœ§§§+þF"˜¦ÙÒxÐ4Í]ZŒ ""ZËLS,ÛÈ]ù¼hC·`Ì5É4«”QÅ¿»þ㮚µh]ÅþV]׋ŬÔAZœõR‘).)‚úËrÉŽßò%Ã*)Ÿ%SkvŠ”nà\îìjl†Ê¶mÛ088ˆNïïš!kŸÈåºlÛ«MbÛâÿD…?xY»ÄqD¤šòû,Ë[Ök9äèz9Ë$NCQLOOW\òÀ²,¤R)w]Âx<ŽX,¶¤ v®…U<5Mƒa ן¨µ˲`†[¿…h¥dm”z‰O­¤(JÝ+DDDkA>/ÚÚÃÃbfwµö°L¸p< Q0D"KÛf¶mãø›Ç™7œ‰k®©þd™ˆPà&Q‰DåþÃâã*’]+–%²<²Ï0 ‘¬(Oú˜¦X6HQÄc‹5_ÜÄFµ™0r ¯D¦^»4‚úIù^ôð씈aàp‹'44CÅ0 d2™’Û2™ …B§ß“®fÛÀæÍ"ŽÊ•ˆ—…ß-KÄ\¥/ À[·¹‘¬¤ib´ÝJr–e!‘H`xx¸X«dº®#/y¬\ÞHUU(ŠÃ0à8NÓ‰ŽzTUu_·ÙíÈDPCn¢*Òé4t]ïhB#‹ñˆÖ´|Þk'¢mî8bpRºl4Ÿi.¯}MDDDDí5<¼´o4ãðáÃøÜsŸÃõ¯¹¾ú“mˆD†Üý/w@åZ´rµ %õVJ˜&‹µä:dÀÒeºäæMS,49):~õ²m Wy¼'rÿëáÌjÌŸuúﺫ¥Ûl(¡Rɾ}û˜PiB>ï]˜•/1 g£øãXö»¦Óõ‹]Æb•—ÛªFQDb§|F›á¯\_²ïy$“I˜¦éÎ8™››Ãää$EA*•‚ã8nòAò//¤i’ÉäªÌôÐuŽã4½ä—œé’bµQZY%»ÿ˸!""¢Î‘Kë^MAYc0_á‚™ """¢`pœÊeæ¦çpwôn|óKßÄOxcõ È„„\zÛ¥ÕœÊÁçµ*0¬Šuac1јÄ ÿfe¿«¬Ñ @CýÙ&rdmjØwí×0¿eKK·¹â„ 5'eº^ZEÞWžd‘¹€\®þÅÜJ½‹åÄl$“I$“I·³KdÇp:†¦iH§ÓU"º®Ãò˜L°È/(MÓJ¥Ve„¼¦i-IÜ躎l6Ûtb†Ö™@‘KáE£Q8Žƒ\.Çc¥Õäbr.EQËåN§ÝDм=‘H¸…ã«Ñ4ÍMÆÀðð0"‘ˆ›@YíBØ­˜  ( xSCn¹åËøÂþŽãàø$Þô¦7¾üåk‘J½@éò}þ?OYÏHvòض8oË%ùGŒ •‡HDü/¿sTU<_þ\Î0¼e³Y®ODDÁÖêÚ%þóãädõÇé:04$ধ¼Ùß`A\˜[Þ&¼5´mxëtÃ[?ÜÿžÛøNäe"˜i.íó°, ëׯdžË6àã‰×^ë›I`¶h8vÒëðrå¦ê•¼ŸMVÄ›u’L—š.­C";ƒóyÀˆÿ¡ÿ+\­¡j¶$ oY°jtˆÙ,›ÕBmÁ–r˜¦˜e¢i¥ gÙli­‘Èð:9[X½aŽ#öÃ4Mwé.î,“ééiw´}#IMÓ`³E²^ ¹ÓZpãŸÁoÄðð¿áôÓŸÆÇ?¾»w‹N›_ýÕ·À0¼eDr9‘‰ÇEüÇb"óy/ù‹‰ÇE£â{C&\äsMStøÈßýK”d³âyª*ž+WñK¥Äãä’&–%Få*ŠøÎª6Ò£dR¹ƒådˆˆ(ÀäÔŽ‘ç7Ùì” åà¤hT¬Æ ω՚§©”øWm€BÛYp—¡@"áxI‘<¼ÑŽòÚ< qa‚¸È–KY˜ð–’‰•lñ¶ ÍúC™C£µ…;‰hå,K|ñršˆÈSiÀ‹ã88÷ÜsEÔAÆ0ªxÿzÏüÃñ›Oljo¸ª­V.àž‚×Á;/½ŽxÉÉI¯®I9Ûîž~Ûl øÏÓÕâ?õ ÄË6W’*…BaIaú‰‰ LMM•Ü666Öécê8ÓAíïØ4M¯æP99JhÿhqÛ¶Ý¥ºd‘uÇqð±â YÜo'ü3;t]ÇÜÜò«†ÉZC‰ªRbÁ0Ä푈øÿÓŸþ%^zé%¼ã'ÁqL|ûÛ—`ïÞGðÆ7†`Û§—,’J‰ï§Ü¾¬¤(Kg¨¢ó(m0ÈeåÅ•¶‹Ñ{ô¨·mÿŒ”Dbib§¼Ž’L¼¨ªxxÜëX’µšü£Bdq_ÿqU[×T¾—†!ö©êWD¥9 Öw[ÅÑËg#"¢®P©}œN‹óÿã8â\–Íz·%“âqò\)Øvc³NÚžL‘É™üHÛQ"éðÖí6á-+·t—QtÔ¸ÈÖá%düÇ­ÀJ’«ò9ɤø~’ßMr¦ºÐ$RÙv±6qñú!™ô>MO{0‰ˆÖºdR´éÊÛˆ¦iâÊ3®ôn‰‡J Š¡9ìùx›¾go<W›W{“£äu]ôIÈþŠ[ÀG‹£B CtdÔêÈ• PE‘ê‰)…úDÛ.¯ÝG«®¡„J(B(Âìì¬{[8fQú âqKºîÕB±mgÕfž¨jûG›X–…d2 Û¶¡ë: Ãp*Š¢¸EÛ[YÓDž×u]d†‰º€\vO&4Mᮋû¦§EâÀqÄmùüÕXX¸Šò¿qçÿˆ¯}íÏÝ:;åöŠR½ó¦Õ!â?§WÛv$âíLΔ¿º..ÞE|OÉ¥ Ð^ ˜ÿXs^"Çüwñ<.nK§ç¿Ü|1Éá8ââ0•ï§ãˆÇËý–µÙ”Gç ÆÊŽÁDIÃAî¿­¡Fž<ù%“âv9»StÈçÅÿ†!Î2qâ??d³Þ@§’óF«™‰C.Í gâÂ=Z¼-q!­ râC«ò³ŸRös½‹lÙ¨ñ戆Xk:ÌY*Ô[äª ’m{ßþÛTؼÙ[Z×0¼dìä¤ØÎæÍâú^.ŠÅĬq9£\ÎÂvo ‘|N2)ÚÕɤxn.'f D"Þìrb%ƒ¤øÉO~­Óo#QÇåóKûQÇeYØöÛ€×oÔ fôVèê\ ¸D"‘†k®­&yñ$—à¼òK’}•â8NcrrN±7'pÉ9¶^Z(]ŸQ5 ¢0 ¯`ÿù§ÐÆÄÅ*}®òëÅœ|$€» 9  ÉŽ¥ûü?ßkœà—â÷Ø¢xžs `ÿ! üžøÌbÇçd ]|÷Æ¿¨¿óÌYþˆˆ¨ ›7‹ÎH9›1—çoy-“÷þæfùï~²“³aÄù) ¯¨J"‘€mÛ-íV¹\®¤& Q'Ù¶è?3Q’I¯À; .‚1fš&4MƒªªÐ4­óÉ^qZ÷€±ô„,þ+œQ¶- ÞˆZy›Sö\¢qâ_Ï9Ž¥£@,xÿs#e·e‹·ÉçÊíú×ue= Ý(Yq¡«´w9ÈFÄms/‰4ðk?۹τˆˆš¦(¢ó2õ:3[6¡:ŽÊçÀ<Äyg¨ø˜4Äy,Qü9q±k›ƒp0ÊÅAå ¿òÂe€·†¥ü¹ü1þÂf©Tio¯,–vôhiÆ  ¹]ÙÒu¯p žc Ûö/ʉYrBV>lØàý>4ä-Ù%Ûøþúr–ˆ¦‰ûäÌt¹´àä¤Wä¸Ò%¬LÀÈï ó¿ÖÞËýÎ’!^ÉÉ'?Ó鄈¨c¢Q/É^β,Ñ/£¢tàJ%ýæÐ ÷wX÷ëJ7 @  )WiNyû±RßK¹XË®‡4>މ‰ ìÝ»·ÓÇÓ¶-.î*uÄ®FéÇqÇá8t]G¢Øš3 ¹\®â2^å·i𶢂óõpv …¼ÐòMÖZÂ?¬9ûkÕþ¾ã(]ZDÎ ñŸŒ,Aƒ8ÉûGNXÅß+]¤É™&Žï~Y«D+n;_áñ*¼¼€·>¨4Y¼/æÛ¦\#~¸x»Ü¯D–|¬\²Tƒ·½Vü7„ÒµHýÇT¬÷…/¬ÎGDDDí‘Íz+\ÉZ-›ý­@ Pl†8ÇDà0õŸS¥ixçT­l[ */¯UI>ïõ˜Ê)8²J5 ."òyÑx‘Eü–S€QQD¢ERÕʽµBk†¥9Móf{˜fq°Œê…„LtÈ6úæÍâ92±2=íÍ0‰Å–æËg´É?sÿl‘òçd³•¯ jÕC$"¢ö’ r òŠ\¶m‹ÝåÉb_B¾Ø™qÃÑ£Øà&uÃÒÈš+²ITmé­D„lN©¨?C¥¬ u·†f¨ÌÎÎb||·Ür vîÜYr_(ÂØØFGGñá¸ÓÇÓr*q'Èz(š¦!—ËÁ,®_Ç¡ªê²j¢°p<õË]rÍä• ¼ÌçóˆF£°|£8“É$TUm>¡’Dýµ1”ÎAñ9q”ŽˆÉòÙ"*Jg‹ØÅÇY¾ßË“2acùž›†7ÓdH¾Áðòqr;ÅÚ)%³Z”â>É%ÆTßãåòa Üš,%ïMÂ÷Z²Ó*R|ä64xkÕ/g9"" ¤dÒ+:š-ÎJljüÏ0Ä9lD%q¾HAœ{äù'1¡Ò…q½æòð°¸8¢Q1„^—dý@ô y…$YØAþܪ„DzÖ<#j ™4 ‘$•K¶$“ÞlÿlÃðJù“ss"Ç(gq¨ª·¤V¥¶~ùóÁˆˆ‚)‘¨Ü”+ˆXºzG€.úO¿ºw/^ …D¹ƒJÝ9)”¶õdßH9¥ý/$T¨§44CåàÁƒ‡Ã¨ú˜;wÂ0 ÌÎÎÖ|\/£_Ñx‹ÅV@—ã8H§ÓÈçóH¥RnÇ®mÛH/âZY…¨%“¢FUW>[Ì0 躎x<Žééi8ŽÓ4—?£KÖ$ñW8ÅÛý#m7C,"gÁ+r›ðÝ&—Ð’ŽrT­L¬øg©ÈQ·jñµä%ò5ä~%áÈ@ñõ6û^C&2äŒÙØÅwQ܆œ‘/þ¯ú^'ŽÒŠ ÑÁ¥Á›–+G «nó¿W xÉy,1x³^8Жˆ¨+É‚Ì@õ‘âËæ@œCä¬F9S’ç³FW0–뙦èÝ•­åP{ÿ:Cºî^4M$^r9¯øiù…¿X„,öFÔ…Ç[iN®N'g˜¤R")“¦²À{¥&~å3L†‡;}”DDÔ.¶-ƨT[q$×ì}ôkââMã~û·qü`£¦•®¾á…7ÈF&N*‘Ueb¥^azê)+.J?::Š………’ÛB¡æççzþÂÂæçç …Jn/ ( …BKî ‚|^\ûÄbÞ¨¹Fk.4Ã] °H&MÊ;u5Mƒa%E艖£ZlÁO¿|ñä¸Ò¾Û¶aÇqk †Û¶ëÏL‘3-ü5²Xmùò y,íÔ‘ë³K:ÄÌ‹¼Bf”.µeÁa!-21"“/rí÷,¼‘åEåÓ¾×€¹âýþé©2±-Þ/o+_>RáØrðf§¥‰#½ìqåë—ÊçÊÇÉ÷Â?“EëÑÑ!½ŸDk…ŒK¿ÁÁAôõõuz×IN؈ÇE[{9«ZÕ%g^ÊÉõÎѨWÙZÓ¼©2r„†/—æ’…àý¼†HyQ†Db錕rœ=ÞVŒÏöÛ¼Ù Y¿D’ùÇH¤t–‰¦--T¢Ô^Ö—º㓨ó‚Ôo+Ï•ïËC×u¯Ï´ÂŒ’Ç_ñ8.ÿáå8íï®ðÚcV…©ðêÇÊÁ¤ÕÚŒr@«ìÓ¡5¥¡„Jÿ’DIyÐ,,,`vv¶á6ŠÃÎÆÆÆÜÛÆÇÇ‘Éd088ˆ™™w)± Èç½u]åÏm(;²D2™D:ÆÑ£GÝ%¾TU­˜}•E²YžVªRlÁO)ŸçG9ès%,ËB4E,Ãd1c‹ÅÜØ›,Ï¢úk”"ùa@$d(ê'Zÿzœ&¼“°l¨ð’!²Vˆ¬!Ržœ°ŠÏ•³64xËjùghÄ|¯-_ ÿöÅÇÅýÕ}ó×@‘õKÊgš˜(M%Šûâ ¹,—ÿ¹© ·ið’5þÛÊû›"X:U·•pÓíñI´Öd2LLL”ܶÿ~„ÃáNïZÇE£¥çiY!kSûÚþ­Ç0D²#•òÿñ¸ÈøÈ^[ÿtu™©Õ\­ u ã³9¶íMÒ’íny,oDª×<òwŒùg›-N¦RWb|–rž2hõ©ßÖ4«ŸOLÓ„^' ÿ…¾€ÔRÍ Ñ!š¦àõ¹T[-U®¸!—$§5£¡„ÊÖ­[ÝÚÖ­[+>Æ0 ôõõÕ=Ácjj Kê±d2ìÝ»áp³³³A8ÌH[ÙPT¯@^»Ù¶|>D"á.ñ•ËåJf«ø%Øú¤ª›@ðãS. k¥¬t”šL¦”Ç™¦iH$Kg§˜Iƒòι Vù’\¼ˆqbö×8IÁ«;2 o©°ĉ:o‰,¦ëŸù"þ$l|(M² ïK”=.ÒÆ€¬‡R¾Ü–¿† Šû[>2£R£§ü6­ÊãÈÕíñI´V-,,¬é j¢QÑž–©GÌø^ö„ŒòA ré9€À8W`:p{°µÒ2|'3™$‘Ëk©ª×Ëë¯gâÇY$]‹ñÙ™/T¯Š\Õ.›×Èš&â:ñ–ÃVvÓÊ1>=²æÐô4O9´:‚Öoë8¥éKïK²gýÙÿŠÅÇð¹Ê¾«òë!ÑWRí~?ÞJ ´¦4”P …Bعs'víÚ…;wbttÔ Y°~||{÷î­»­ÁÁA„B¡%Ó7§¦¦Ðßßïž0000€©©©@Œ²•Se§R«S7Å0 Äb1¨ªŠh4ŠéééªÉ¢fT‹M øñé8b­å¹¹•h“…æÓé´—L‰£¤£?‹‰e¨ü…jý‰™<± NªþP5…¨"“þ‚ìùâ6åè‡<–¬×Š·çQZ8׿„Нm¢tfˆ¬_âdÂæißÔ™<)ŸiR®ÒÌòeΨeº9>‰Ö²©©)ìÙ³§Ó»Ž#þÉÑëþñ é´Wn¤!IˆóžÿâUÖ{s¸4ìLq ø¦¼7ñâç§¼½¬€-wN&Q*]±g™ùï5ŒÏRr²•\Þ:/M˜ÈÎ,Eƒ Gü.1Uëì"Z‰µŸòô¤(Þ„I¹ò$Q»­ßVÆ@%ù|~é WߊŽã b2—¾ï/ù:,ju­æÐXBý@¶a©gßèÇÆÆ066†ññq躎K/½—^z)FFF055…ýû÷W½â700€p8Œþþþ’Ûggg—d4ûûû+vù9r™L¦íoTùz}«‘Ó°m¦i"‹!‰`rr’É”€Éd28tèP§w£%ªÅ&°òø„ϽÿýøÅã¯ü#@ZŸÇŽC&“ÁÔÔT§Ö ©©)äóy<õÔSÞ•¶’µwïÞK/½[¶li蜸ZmÛÕ$G³‹¯zYƒ=™ÿäÒ@õ7off @Â3Dç ;hÞjïÔÿ_8ê¯W¼‚‡¹\ésU÷MO‹ÿ9œ¾§Ú¶µ¬4>W«mÛ•šqñ¸×„ö:pãq.r’–¬b^9 òä “)íU(ÉdpäÈ‘NïJÛ­$>»¹m›N—\q)—ÕK¥¼2]L½Ö¶mW¿m½ÇU“ÏW>ÇX–…t:-¾Ö‹ÅÄ ìQZˆ>UãI²^-gžt½ñññ¶´m—U”~çÎØ¹sgÉIª¿¿MïH¥böL;ýôÓWe¨¬G¹šâñ8‰„[¥Þš€´úÂá0>ÜéÝh»•Æç¦M›088ضýrÑ#‹]®„mÛH&“øÛ?ÿ[\ÿÖë½;Òi`“ås— X"Q2 ¯H™ŠÒZ(r_ükoJrö‰Ÿ‘˜9©˜,I+âKg· ¼%âÍ’I34ÇTqÕ;=-ž›ðˆ'½5ÏM‹¾×PUà2P‹É"ù…¦øH°ôê‹ó&“¢EoÛÞ—¡¿Ñ‹ÿ‡‡½eR 1ÃNÓ€d/¾ø"Nºæw‘ìt:H$‚ááa¼ÿùç±éùçqæ™gâÓ‡ãQEæ8øúý÷ãºË/Ç=çŸ_ݼ·¼éMDÃÉvÄî¹¶mÃ0 íÛ‡«t†aàCï{Öÿä'xýÏ~†þcÇÚö÷+‰ÏSO=•K‚QÇ„B! à±Çëô®´U¡P@8ÆÎ;±ÿ~LMMa×®]…B5Û®«Õ¶]-ÃÃâÿTJœ¶ä¨vy›e5˜Ë°!’):Äy϶ÅùGQJ—ãútñ¤+‡Ú§Š3RR©ÚÛ_£½Á†a@Q¨ª Çq‡1>>Þ3BÕ¬4>Ûݶm‡tZtFÙ¶sr9.ÛÍÞ¹x樽ðø‡Ià5ðf¡ÜšNŽˆÎ€fS& ê@J÷F/È)¦ ˆµ7+-ÿ¥¢ty,À™À¯)^'ÐuZiÍ•lq­1 €mxo€ àŸÀÔª/I"ÕÔÊËm:ŽøB,o°ärˆÇãˆMOCQX–Å4ňÇ{N: ªãÀL§‘R8ŽEQH$‹ÅL&‰Dpše!¦ëâû°øýgÛ6EAªJo[*•¯YÜÞ×Mêè(âñ8¶lÙ‚ßZÙŸG×XI|Ê‹N¢N…B¸üòËq¬ÇžØ¿¿û{8ƶmÛ055U3þV£m»G\g³¥§ ÿW¹[ˆZÖ‹ òò r&f¾å5-quN{I¿D¢úÌÊ!×—ƒ¯lÛvÏ™š¦¹3;5Mƒã8ÈçóîÏòñ‘HÄ}Ž¢(Èçó…B8ãŒ3:}xmµÒølgÛ¶äêuªêÍ ÓuѤ’°ÑvN§E|ʘäè÷`“õj÷íÛ×é]i»•Äg7µm-Ë[¾kxXôñjš¸M$¼ÅVzK«o­´m;Õo+gFú™¦‰H$RyÙ£@ÔV1MoY×–Ö}­…+¾v½lÚ´©åÛ]QB¥]X>s~~># äÔæV2M†aÀ4Mhšæ^È躎X,†t:Ï ŽÏxÜ»¼A©‰DsÉ”¡¡!Ñ¡¯(ÀOãÀ©‰b²Âþf¸S®ðð[y`ÒþY.T€ÚÀÿ—~¾\lÿæw¥x1Ùq¶¤^P> :Àßkb .«x…›°9üÄÉ_2}?ËV„,Y¤sY‹Ï¯ŒQ\ŸÔ0 ÷ù^Æb1w¶O$ªªÈf³°, ‘HÄ-7== ÇqÜd±œž+¿ï*5ˆÔ£†å}þÇÈmD"ìØ±£­ïIt:>‰¨²B¡€………’‹Ì¾¾¾NïÖªƒ‘4­ÊÄ4¼Ñ~²Œ—1tºøóæâýYÿb_NëT`s±2o#Ãå{pÖ‰\ÞBQ˜¦é^?ض ˲܄‰]L&És±ªªî¹ºÖ€­l6ÛsKÎUÒ‹ñ{Še³0IÿLnùñ³U¯Å§ey‹†¸L¥Ä¬¹”—웬—R~iÇî!ê´N\wFåq¡¦i"QãDö™Ï|?½ð§¢ŸAà Ž5P{v QI¨„ÃaÌÏÏ»£fggQ(°mÛ¶Ží“œJµözÌqw9¯D"áÖm€¡¡!äóy$ ÖK¡Àèd|Ê‘:ÃÃ¥ •z.jŠJÞÄ_ÿõ_ãÆØâû; àÍzqFHJ$VƒèÔ±£"Àu9à—Š¸íU 5-:…Ôb+9¢œ®RÄÏ–¼EN€Øn â¶S¼É.ô¾Uá­ÿî·Š+ý•PÕõÿ?{÷W]çÿŵ´@ÒJl=¥Ü9uPP9YZXQ‹3ÑuW›•Ψ»ÚU£3ëo©ZWwfbW÷2§hpյɸí®7¨æ¨‹,Q P.B”¡@¹ô4A(÷üþøÌçœ3“¹%™dÎL^ÏÇÒLfΜ33ï9Ÿóy>ïŽH$â&O¢Ñ(2Q¯LÞÏ߈QU£¹Y*’ÿ{Lþ[©fdW—·Ê)•Äó'°áu—ƒøžP|K!d” ïûD’‰×Ù|_X(¿ #ÍÚÈÈvìØ]»v¡¥¥“““ؽ{76oÞ\ï]›W²¼P8\¢Ã6ñ¹3_Ns(÷³ bÌÀxŸÏDøZ\ô:}´¹ ɆUU‘Éd`åŠê«ª MÓ`š&lÛF2™37“Iض]ñÚÁ_6˜×B3ħœfYâß²š‚¿J+Q#j†ø”d‰êpX\rj¹‚šV:FÝÙ› oI0¢zXèëN9@§X·€DRÌ7Þˆ‹ßw1®úÐUâ†ÂrCaˆJ"0©B³˜„ ¾ß²e :;;166†¾¾¾ºD°,qÂ+,S0W‰D½è‘#³ý_rÊK}QÐÔ+> C &ÇLFä.Ò³œz™Édpæ¯ÎÄ1'ïnÿâÆô{ DçŽìœ C\‘n ÑdþÂóqˆÎÏQ ¯·³3*:5ux­d§Q¹¡E P7•JMɉD ë:2¹(r$k*•r“½º,ÃåS¸ª%Õroˆ%U¤ó§‰Ôh@‚ oÔzÐ8ðJJFî§?žc_þIä~û¶䯻ä@|ÙÍrû ¼òGò6@7¼‹YZPó=o7òK&9CÈŸ-BþÚQ4+===ÇÆÑÞÞŽ±±1ôôô §§§Þ»VS²¤iz@%×D±á­"ì(ÞgÍJˆršJîN2¶š(Á.K^š¹Ò˜€e©ª*LÓ„®ëîïþEVMÓD2™„ªªÓ.0I2sŸ²“IUógqâ66Ÿ¨‘5z|âœhš"6uÝ›16ÎLÊÍ“…¼î,,M)†Qvé%K–`ݺu¥7,¯Á2 šµº%Tü51¥žž„B!d³Y´··×­\‰m‹Ž ¡¡Ú.DŸJ¥à8δÜ~,óUœã8n½gÇq ªª[vHŽ”÷“¨™LÆåÇÝ/]¹=Û¶ÝíÈ«+-ÍN$B"‘@<‡eYnçs<Ç¡C‡êýòÔT±ØêŸ™Œƒr1MÓœåzF©vMN"±s'îh¹-/¶›ÀÙ¹–­?ÖS¾ßu¸$éÝ&o×0½¦VÁs/ðâþÑrm‘îîn$“I8ŽÃ0`4Msg™ÈŽ_… ”š&Kª!‹³G OⳜTJÄê¬ÞÂÂY€ˆ7RÁ†hÏ¥\‰‰ò3:dRA*–hHA$.F}û–Éý]õm_î¯ ñaC|O¨ð’-þÇÉ¿9¹mû“/ò{ÈÈ=ÿpîoQx£þ£¹¿EsMæöEî“|á{¼¼Mž(_3ØÎ½†þï7™t–ß…_™Ü>¤€ÕKVãöÓoŸÃضmÛ†ññq·B½cs¶Ö®•-ý Cĺì,’_ÛeËùK}.RhÛ^Qùûî—k—Ès§aÈd2nòD¶K¸‹¿b°‚œiâ8ލó]B”+×\#ŧey• /iÂKÇ€(¬O\L"!¾ó†‡«š>dlÛF4…¢(n_ÂÃ?\ï£]Ÿ… Ñ–§³Z•׳¬¹oƒh&êÙokÛâ3_ìë2•Ja¸Ät­®®.Üø·7V˜†Å‚÷ÓPs Ô u=YZ–è¼µ,Ñ8­õ`/Ã0Ê&SšìÈ• `Z–åÖkö¼“¯Lløë@[–åvêÊõedhY#@Þè>¹&ƒÑ'ëCG£Q·sXQ¬]»Ö]ÀÚ¿ö‚|^Ó4Ý€²t‚œ-”N§ÝRHr±OÛ¶a.¹ä’z¿ô b!ãÓ4EcTö³„âófƉN@ÚÄsw} o8ì†ÇÆÐâ´ŽX‹ŠEy2•£¹ý#€Âð:4ýá›Äô䉂)Ó%g“È’e@$˲Üœp8ŒÑÜèÞµK ÉZìuÖþK¸ÉébÓq¼šÐ3&g`ÈN" "¦dR3 ¯îm© T'÷Ÿêû]n7œÛV À¼D†ÿcoAļæ»ÝÈÝ×—ð‰æž#/1aC”*2 ’ÑÜv䬶¼™#Ißv­Ü¾Éc•#¦†s÷KåžGÍÝ/™ÛLjïuˆC$y-ˆY'2ù’ÈíGØ÷ÜksÿNæ~W!f«h¾íÉd r çþËäîgå¶3”;vY‹¸;÷|q䯃!_ÓœÕ÷­žÅ¤ñyëjÈòAr=OÇU5ML©*Îą̊ø,˜æô¢ØªZûÑLóÄq·sS¶=eûW¶Aål9‡‚)Èñ)cOÓ¼Á~€èœåGj†dÂjÉ:j²W\~ÑÉ2rºA*åõr‡ÃâþrÅqYÛ À#ßþ6– ãGùÞùÿýødÆ-¯uå÷…ü>‘×щDŽã¸×¥‰D¢Þ¯æ‚ r|–"Ï%gjÎãž‚b¡®;‹3±, ½ú"¨1Õ»žò‰F£8öG_ö›À_²žÍŸÀ%Tê©»ÛaWËÑ>±X ¦iº³)êIÖeží…ì°•‰‘H$‚¡¡!twwchhÈõ.ŸÃßÙ+“¶mç%>drB¾6r޽§(JÑÎ_yù<ò¹ ÉÛöä†W+©&·Wª£YnCŽ”¿oÙ²eAßÃÅBÖ‚–oó¬âÒ²ðüÏû÷üF”7âÝÿv-NVËÍ*ÑsW€²“ƒk‘ßYG~碴ý>2‰'/¶2™ LSÔ%“IÀ¡¡¡¢e¹Ë6,Ûá°ø÷ŒÎx¼„J^‡¿pÔ Ñ‘?‘È@îwÙ¡ïÀ›Îm›Ù!Ëeµåþ.KwYð’.r·uA$ äìÞì YŠÌñm_6ü£ ”¼¤ŒœÒ ï»ÄŸ ’·Å!2ÙxÉ¿8¼ r?÷äöE>NÏÝÏ(xÎpnß4ß¶ o‹Á›õ2”ûiÂûÎ< ßôÜ1i¾}HÁKÂÈ™/£p“1?ûÝ“xòÉ{ñ6¼m†ªÙo‹‰¾Åd²Ì×´Í À­6ðÅnࢨøI™Ìô+å:&SäŒÙ^•3™åí²iY–›4‘‰“rí{&Sh¦GôÙ"$l{ú 1ª’m‹/.9NÖ"µm‘Ô•2™üÙq¼»»½²ƒ™ žøÀð N*…ÄÁƒøÜªUøáM7!œHàˆ½{ñg<€‡žGþìg¸¶»¶m£sÙ2´­]‹§}»ï>¤ûúÜï ù!++8ŽƒL&MÓF§]›¾úÕ¯®÷«J>2ï–Jy æ /h1‰DŠÇ“aˆªQàiäW€XbáSÃÃÀþ.àë³)kBT=&Tr2oÔ]-®{,ËB$×ÖuÝíȯYÚJΉD"îŒ ÇqÜ™%©T Ñh©TÊý=#“É ™L"‘H N»‰•¡¡!¨ªê_a©‚bëÄÈפ’™$ŸŠ•ý¢Æ%K̸_EÖŠFÃÀó×_ö:üîþW}úÓ¢Ãï^xé´7½pð‚É-Íã”Pÿ¬,É0 7™(¦i"##NÃ4MD£Ñ²%Bˆ’m‹~‡d2D{Ik!bÏŸç®Ü¿ål1™8‰Ö›çuâ&íRÀyZà€¾°ß+76èw™qÀ9O$z4 P¯ŒoÚE€žë(v;¿èÿ 8ŸÌßÚY€þÀŠ•Û_ѱû-!ŽÑ¾°ßØbIM40r‰š´-žGQ¼ ÀÍ€®x#Õ4 ZÞ@W'7Ã&šëó±,ñ•eßY9ºع¯¾pXl߆8¹ÊI¹™%–ååJlP k«Èÿ.”‰d™(Iúîg !W¾Æ±ý`¿°Nœ·öOø& a8H¿ˆ= Ñi›«ª àÜ `¥x#˜7ÑÓ-#nS@u% Øßð @¿Â[ 4ÔGË4Gt\)Jnqígç@» PÎÌõ÷¾P?8¯Íµt@9ˆÿVÕ\¿M;ðøãc} bÛŽ#þ¾aßð‡?üçéçn½u'}ô9œzê«á8ðýïߎG½Ë—/Çï .¼ðlvØÛÑÑqmm@UÏCGÇ#xä‘GË—Ÿç>7à]|ÈÄ\",íRF&nEô5Éä—ªŠ¿Ë¾)Eódî…Mî5ÄsȤ¢ˆ×S®¡£(€ó ‘ãö/‹dÛÀ§>µûö­¬÷G–*Ÿ›hÔ×¹›€Œ gH¹Y]¹ÃÍ›E.SCwÏarv´L’ضí^m]9<‰ »ív93¥X¾ifR`ø«Cɤ8—Ëñ±,qR²m¸'U9HNã‰ÇÅí†Äãxúè£q,¼…š¦Á4M1ɲ­-¯œ–cšpŽ8Ög>å«_u“¨ çZ–å"Üÿõ¯ãKoxƒûý÷õ¢Ç«ìQ¯GÿÍ™£[¨˜å*´˜‹+Ã0°õ#[½RÉ€»þ¤³ñ« /æíóÚ¡Dóˆ ˆ‹~Ù4×<ã8èîîv×ßXHò‚0•J!™Lº?‹í‡ì˜=p@Ôëð_\úÊÛÙ𣅔NÏ`Ðj&ü\¦Tàô8po׿ýzœö©Žî\‰5¯XâÝ·Xi ¿IÉ„¦,·—J¥ÜÎÂĤLXÊ 9ÿì/¢FÐÝíÕxWl þ7^)ë6@ÝØç™å²¾0—Ê}€~€×äêNÇsï 0,g±”aYrGÆ4@Ë•Ï3ß4˜¦ MSaÛd2b°¬I®ÿ¹­nÄò×ëúÜŸƒª®D,–ÈëtUîWòêžÀ7oðöCvä(Š‚C‡á…^À÷¾÷<üq¬Y³kÖ¬ÁcÝ€ƒbõêÕÈfß‹‡: íí§âw¿»õW;pàÀ¼â¯ÀøÆÇDZfÍ´´´`ttË–-CGGÞõ®wá_ÿõ_ÑÒÒ‚;Hªz,¢Ñ(þå_~Œ}ècøÜç®À3Ï|‡~/FG¯‚ãxI9£(;ˆ5KƬÄßøn¾y)ÞùgÀ/o^ŠþÂKÀ²eH¥òG%?²ÖÏž}êð ìÂÐU•³b,±q0¼úÔS3M¼ñoXò+Pd¼†×Á›wª’³äº9Z®,NFÉ•¨Srõ:s÷[€ö£L”Èò\2öUUE<wËÎVÛ6—¥h‰æ“@d"Æš~ŒŒYàÿ=•ò2î°v­x1äír==Uõ²M¹Ø´, GLNâ•·Ü‚š3‘Àucc0ãqlK¥à|üãî÷€išÐ4Íáí_óS~O”Rø·û·XQ‹×#‘ðŽMΤèK!(Ø"‘Ú—Š¯„§&Z,d…F?¹æqR/øƒ Øšw|¿WT%‘kZÍ#&T ²sUà ÇK®ÃQKrV‰,Ï%Kx¹£j¢eî8Èë‘DaXdǽûèº7M»¹ `¥cÉ:‹üá²r? ·á8Þ09<¹ÿýŠ=žj¦««Š:шÑш'€—ÃÀº4 høñaKñóÑ!ýÿ„n~2¿ àuÍy&×<‘?-ËB<‡ªªnÒ„¨ÙÈÙîWq È< ¤þ5Wþê ¿Pî’{ FY¢ä¯Œ•V°¥ŸSŽÇã°m†aÀÈÕD—IYºGvÊÙaŽã »¿â¼‹ÅÜNÇqp׌k?ô!¼õ“ŸÄ%¿ŸÂ'žˆg–-CëÃci2‰„eáÉ'ŸÄ5×\ƒ×=ø ï냢ªøÛ“N“/¿Œù—Ág>óX–垟mÛÆC=]×ñüóÏç•!ºá†ðòË/ctt¶mã‘›oÆ ÿïÿáÖ–d³Y|5™DW,惪ªHª*޼óNü×ë^‡ÓßóX–…ï>ÿ‚+.¾Û‡¡¡!XVGìÚ…{ï½g_x!~~ûíx÷ +W>…‚#‘ðJ%KM,‰A”â“çQÇñ:>€eYÈäs.\¥g g‘,D›œh¦äÚÑè"H¦Ø¶H–Șohw·7²qhHüâÎuë°3‘€®ë°¶i²,w¦·¦ièZ³.¸Žã ã;–çÑG1<<\v6™¼Fž¤…œ§i Ø6€J~‡méèÀ‰Ÿø?áì}÷»p8ovœaüî ËòJ|Íh`øgû5+Ù]XÈý^´\jmÞ"Ø ˆv¡žÖEE’X½‚ƒEPÉd¼>ý¹‰]×g]æKŒ$UóF¦ËÎÙpŒÅbH§Óîð™LÆ]O¡h£Q}Ò´ü«âDÂå“Ɉ–¼¿5 ;9d‡p8ÿE’õäÙ¼°È¯\IQŽDŠÇó/´e¯›\$°ðñ†!öKRUï?ÿ>Ê}¶íéÏ!×Ò…FUuú‰x¯‹\eÕ¿DBì‹ì,«¤û#•.½tn rYV•#oäâð#pûà ]8ôç‡Ð¿«O_õç¸F~žŠÅv r]"92V.ŸL&F9Ê•LÐOÍýbЀ´o˜à³3Ä,ˆÆ®_ÞiDĕ쌥94MCWWWÞ,J¹‚ìd=pà€x¼\€67²Õò•¿ÿìg‘±,|ÖqpðöÛ7M¬¸újw«n¸ÿŸþ ǽðÖ¼ô~¸nŽ:ê(,ûíoñsÏÅ)G…?qN…ÞÝ UU‘H$pjWÎûö·ÇÁ®xû¿ö5ŒmÝ*:oä9OD€mÛ¦Û¾vì±øú©â…TUª¢‡áLÛN9øùÏ®.¨¾ï–µk×bÅÓOãµW]X.ºè"ôæfܤÓièCC¸û;ßÁ¥+Wš†KwîÄ{¶mßÿùŸchhwÜq¬l###PUÕíÄI¥R8óÌ3ñ›ãŽÃ +Vào/¾S¯zþãg?ÃÊŸü¡PhÚL;Y/~8÷>Ú¶ð÷¾‡ssçl¹”î[GF022Rï-å$e½Šq b7oÝù©u’J¥ ë:,ËrgvÊŠ1®ª*GqÏ‚, \¸Œ\ÿ1Nã7¿ù B¡P½wµ)Y¹ {CC Ò)Zi œ$³±Åz˜åBL¾5Bî¾â |kl ¯~õ«±îÊ+±ëÒKaÛ6ž[µ ÙÁAœ–K,ø×:’‰ŠBòkk6ƒ eÃ?Jì²XÞ+¦iº3Îä+Ãá0,Ër÷¡««Ëm·Èk¢äG‡aÿ«^…W¾óxô¹ç ùÖ;F£ˆD"Ð4Íå.×oÊd2xê©§ê÷yXDÇËûÉkT]ÏM¬ÓåiNï!j6¹êyd0N‹¾ OÆÜ騨ôe˼s€ÎN¡±h*²/|xxn 96™LV݈“EÜ©Ær½Yª@. ŸN§ÝÒ]C¹Îü=¹©Ðiy …gÔîn/™Q˜LÄï©”W‡V®|(ŽzÉÙ8ö›Vÿ¡€®—ŸbàkLUÍHÇÑÑéSÇ ·Q‰¦@±ãI&˧\$€j¦âF²f¢Cç™4þô•oâ½ÿôn|ã©oàÄä‰ ´¯4MC$qKì AQ®1D‹Ræ@üVˆD‰ ‘¼trÿVà•ŠB¬§bÃíñÏ‘ f9U×uD£QtçÉdŸx'q+Õ%“)ÝÝÝ€mã°óÏÇóoz~üì³8ïp¿eÁÎuÌ8Žƒ 7ÞˆÞs®9ë,œúÿ#Á5mm0 CœŸ‡†ðЉ <ÙÚ UUq¹ãà¬\Òô3%â{h(¿vàaÑ(VpW QUï¼ã_D×ot]'ŸŒX¾Ü»­Š‚úJ<Žçq~•3rßQ²mrÖ_þ¥{ÿuú”]»Ü¿½öµ¯Åk_ûZ¬ZµÊáãäÎoòûÌ0 |<•‚¢(ˆF£PU™Lmmm¼A²ã[n;Ãq·$ša<55…ãŽ;ná?¨À[ç&ç^Àל´ â7QŸ: 1ÒφW¯ºFäZb²l :2u]G"‘€¢(yký1âµ?J ØðwËYñx©TÊ-o844䓱)ËŒ†uëÖÕû0›’37H‡¨m{ë”ÈU·åy+‘𪶿ΉªÂ̕۳m׌!ùªWá_y>™ Qt“ý_ò3[jv‰ã»î*¶°»œmZìñÝÝÝH&“ˆÅbH&“îLnY@YLn?N£««ËŸ¡¡¡¼„®LtD£Q·ý"Ï}òš@QD"÷Ü™7ë¤ðÜî+›144„X,æž[ýɥ矾ޟŒEÁqÄÇÞ¶E—€ãT.j1ßâ{ƒhd]‡X§/ÀŽx݈ÿ[.ËbÂM¦È„u¸R#ÑùI\òÉ8å}ïr³IågIÍÍ^,,+§išûy—%¯2™Ì´ûʲ[òvMÓF±víZ¤Óiw•išug<Êëqù½"cG–ÅöW‡ð«´ ý‚ãÚœ›ìÌ.¢:H¥rmÛÄ Z¸iÉMp>êàÕÚ«ÝëL93…ɪ§E—P‘×rTÞLd2†ÑÑQwêmQ¹µKîܵ Ë—/Ç‹·Ü‚>øAX/ípÞyÞ…ha…<{ó,|é4&¾ûÝzïEC“U —°à­±pŒlÊ-\©k¸óÄ;qeוøæIßÄŸwÿ9Vi«j²/þ2^£££îèM©Y:~ˆjÁqr#;ý‡¶æþ y‹®ÊQèÑÿŒâ á/ä?Ø0D/q$’·xƒ[KQ8ŽƒH$‚ø…º-pGTËøÜ¹sg½_ަS‹òýa‡íÌÉí²Ôˆ¹;ùÖÄbÞ€YUN±,o ¼tZ„š{ KøKˆ™žS¾'ÉDKË*ÙNµ, ‰DÂ-/%×H§Ó0 #Ðe»dg®\ï@&0äl™O9kD&ei»H$’·†šÜ¦?1"%þ²|R¹¶gÃ6&wÄmÉó5lÈfñ׎ƒM÷܃_uw»ŸíµK.Í –%ªåùY–Õ’Û“3£d99 QÎÑuÝMtÈ5Kä¹]Æà%úüsS©d~¥db`Éc)U”æLž+MÓ[HüýDª*úŠ‚XÙ;¨ß#Dµ`ú××Ì­Û·ïÂ}øÆ›¾ë–|8¹ ø»Q@{¾ ª§E•P±,qñ9<<³ö‰\'EQwšqÁÛF&w1Z¹O à”÷½KŽ;J<މ—_3R$v.4UųK—Ö{/Þèh‘˜4d FÍ~U ÊÜýó?ÿ3ÒW]‰¡¡!hêÜâHv„ÈÔ²þ¿¼pc' Qq¶ D®â/ɯ8îBÕ²CQ®-V´k07bº'Wg]³m·¤ž¿£r´H½6 G4e2zdˆ”«“N{zäR;ræJáKîþnBÌ>©Å[’‹ÃH$â–›à.ª,gyú;@ªt—‘î/A§(Š›‘·' $“Itww»ëŠø;„e -ù–ײ,YáñKx¶%òÊüÒ¢PÅd®yã/ǘÉdÜY 2Fd’CQ<¦iøæI'áâ‹/v“¡ò1²ÜVwwwÞÚX€ˆÛ¶Ý2Ø2äŒ+BF~þ g†ÆÒ¢>oX–·¸•4›Ñ @œå Ëò)rYYùU,—õW¼ šDBœÏsxÔ“¿T©$ׂ€ƒÖ{^4 1 Enî¸?úìDÙÄ®.@Oq cfФŠ^#-¤E•P1 ïY Ù)¤ëúôuR Ã-×õü±Çâ†w¼€¸8zÔq€Ïë|g:^2yr“¸`š¢a+Ë3»,ˆ„ÊÜzíŽã ;£££³mfÛ¶;rV^dÊúâDTÈ…@| oƒÛ1›ÉdÜ‘®ßüò—qñý—7ÊÒ7"ݲ,˜¹Ã0 å:eäÌOÙ³¨;SšH¥rkT\&S]íö‚ð9Yw: ‘èÌòà%TfH.H$`š&¾|ÔQܵ ÷­^í®Ã‘L&óJ÷Ô:y"³.ü]Ó4w­³D"ávú¦Ói¤R)7AÇÍ•$’ëúÈÑòr …,!×<(ü>ò—0"ªVµKhÌ…,--“‡™LŽãࢋ.ìß¿o}ë[qÄGàoþæoðÿønÂDUU14W’ë¸ãŽw}#MÓN§¡(JÞl ü¹Ú_Þª K×T³Þ)•%óQ¶í-p]lrdádzšžy3Nç™<ÏÊ Üõô,_‰:Yпޗ,·'Yp¿—üäc Éó­¼F¨æ1ò9å ,¿ŽŽ7âúë÷î»ï>(ŠåΖ³mííçà©§Nwïðà÷ÑÒ²O?}&Ž?þxüðâ‹Çã±ÇŽÃÙgÂoû[¬ZÕ‰^ß—gu†‡“øØÇ>šL&§ðY|ñt\´¦iÝ­(ÂR_‹&¡bÛ3Ëæg2$ ìîëú .ÀÁ¿ÿ{à¼óà„ðm'qžüÒ—ðÉ/~Ñ÷¾–e¹iDT^w·ˆÅx¼Äd-¢#ÈŸLéîž6ÒµvnÔ{8F$ÁÐÐ[Ê‹"D3cÛ@ì@_ „ï·=pÇøößý~uôшÇãbä¶¼zÍ—‹*ËŸþÅËe§& O=õ „Ãs›€HtFr¿ËÅ=‘»½B[8•[dZþ‡‹ÅÜÎááa˜¦‰/äFµÏ–ü£;åˆwÙ¦Îd2îL—p®ýí_Á¿º¢(î¶ã8Î[ˆ½°Ì˜Lô±@óͶŨòZöýÈFÓ4ñÃþ°lÙ2sÌ1èèè€ã88óÌ3ñö·¿Ý!"-˜¦‰öövwd¯œR¸øºŒ ù{Ô͢E/•³3­JDþ™`Ðѱ;wž‹³Ï>ˆC‡Ž9æ^óš[pï½ç`ÅŠ£±zõ¿Ã4Ãxùå'19¹pþù`ïÞ#ððÃ'ãùçgŸ½ mm1<õÔS8餓pàÀœw^wßýw€ÓN»¿ÿý{qèÐ…hiiÁ¡C'ᤓîFgçsøõ¯[ð wáŠ+ÀààU8æ˜CX¹rxà4wÜ;qøá;°zõE8å”›á8à©§^¯|åeyä‘xÍk^÷½o)>þñW£µõe|ô£?Âe—½§œr.N8áp<òÈRôô<€GYŠo}ë(¬\¹o~óØ»W”÷ûrwß}-ú!–.]ŠdR|ÇÀM7íÑG‰ht…»æ|ä#ûð‰O¼€ /<K–,Á¹çŠ~ˆT ¸çžýx÷»ŸÅK/­vÇ9ðØcÿˆü^ŒŒt÷D€·¼E<ϪUmزe©[f5n¹åEìÞ½ }}õþä4YI“mØ(q2€èªê•‚7s˜ç$ ‚E“P‘k¿Wbš&b±Âá0~±nŽ¿öZÜþÿ€Ï8û—/‡“H¸ùd2éfFÙDTY$"úXKŽºµ!Ê|)¢¢ùÃÏ|ÏŒ¸ ¶VCޤ‘¥¼ähÙÂQuDT†“¹õŒ«õN ù}‘µmw~øÃ8ÿ¿ÀÛÞúV\½{·ûДeye» ¿þÙ&*íøãuÒMÓ+ê^8*È4Ūê­e¢i€£äÍît•ÈÈ2@r¤§išn)Ù¶D"H§Óy%{ŠýåµäzdÉdÒ]Œ]Î õ/-KgÈ5“üƒ“äÈøjf«ù#þۉêͶçVéÙ4M$ <óÌ3øÓŸþ„§Ÿ~˜œœDgg'^õªWaÛ¶mÈd2Ðu¶m» ”b±Z˜DtcEÖEâà@j`²úÁB%Säy¯ØívA­¿Â™òzUþMþ.Èd…ýLGu-®¸bt]Ç­·>¸à‚5øÉOÇ#<‚p8ŒµkÛ´áøãǺuë0<|úúÖB×/p»-o¦ç….ô=Ë¿åŽ Öån»¼à(/„XÂp)€Ór·ý·ïïÝ% 8ŽãnøÐ‡ä_ÞOŽó=î,ß¿‹­“ºÀGònñÖù÷÷¾þVáŠ+¦oIÌ\QâÝ= @gÞãŠ=ÿí¹óÎû°w¯ oD Ub€ñI ½ PמÅcßü/$n¹Qôµª*°g2™ 2‰„;ƒ˜(š6¡"³Ë²µi–dš&¾þõ¯ãé§ŸÆ»Þõ.躎Áƒq^_lÛÆÇ8]™hNdR³d(Ù¹ÿLI±vQ*•ÂWÞð¼æ´Ó°¦HÙÙ(•ÓŠåhÖX,†t:ÍR^DU2M õÿñ+ë! ñ5 ½l´—L(g¯AlmÅÙÐÍc ¼ ¸õßÿ'oÙ‚sÏ9/Ýr Î}íksÛ²þÚìþQ–"ªÒ²µ@›¥8¨zƒT—«À°|ÿ°ïã̇ÎÄë^ñ:<ûì³øÂÚ/àéW>ï]Ó&NCëý­¸ÿ­÷£s¤Sôëerñ¢A|O¤EW¼vµš»ß ryŽxnŸl·YÀ˜ |>wž–÷×}÷¼5˜R¾¿Ûƒ0àûé=ÿxógçöO-¸’Û¿„o{fnûò9üS|Ïé¯$gÛWøD{Ñÿu€A1µìÙuoÃçq=†~ò÷3(KY2™BA¸„J6›E6›E{{;ÚÛÛgüxÛå„TUœLåÉ$/~b5M›7oÆI'„uëÖᡇB$'¼ÿøz¿D2Ûø4 @qr51mˆ ˆ(ÄEƒ¼°°¤+i!‘› 6:: Å¿Z DcU–ðêîîvKèºî.´É† -F³ÏÄåÏ"|Î=â,ØCâ|}ëˆ]s!Ì?]ˆ°ò†·îÞqŒ›èÔ4 ŸþéO±úÜsá8޳rt»¼pbít¢YÆæ3%fTº!¥W¨€­{çÑs€{޽ƒw âÿºÿÏíÜQUê[ÞëzÑYbò<šH$µmw¶¶išÐ}å¶TUÅêÜZyÞ•3Zä¹—ëQ#™i|žÿÒSH\u8æe„OEôô[¾â½p^³ znÔµ¶äV87þ8ýtXœýòÄE© ‘0ùÑ÷qòÍãxâÉ'ðØþÇpÞqçáË?ùo|¾ý»X¢,Áw¾þ¼ðÇ >ï'xÀÉ-Àñgã p ÐÙÙ ì²€³à>ÿÀ\¢‹y@tÒ?g¿p^n;Y™…€è ÿ±þdƒRð8=÷Xÿ׎ /‘ •xÇw›/¥úžW>Οlñù_ Õ·?þçQ žGÏÝ.ŸÃÿ8ÿï(xÃwµL8É×VGþ~&Zä±Û¾c´|ïÇ"2ÓøÖ¬…÷:Ê2—217 1y@¾ÞpënÅ9Ÿ8Ï,yÿyòbé#K;òUËÞ'Üžºçç*p÷ßݳ¾uVþËϸŒ ÓsIß~È„™¬æ•Ê=&,î£+: ˜>ÑÁÿ8 â3•)|tûž3ã{<Î÷œÓöÕ€÷=à`zÑ<É"Ûð?®ð5™ÌíпiùÛ(·¯¥žG.b^î5Iˆ•ÙF5Ïãß?9>¤àyNÿ‹Óqhé!,sí·5¾„? „¿ÀÎÍŽÂÀú±¹ IY¾}±$娱*¡288ˆþþ~tvvbll }}}èéé©ê±–D.†>Œ~P~ÀT9Ê$·“ý‡,îú—»`›6nZrþë#ÿ…Ã~~Î=ñ\£#¾£ÈÃAî´ÈÍ6>í;€ÔßLb´íÀÓŸ~­{ qwŸ…ç‡{{ÃGV¬@2™ô:d, ··µaʲ‰DÜ /ž`i±›m|&θΞ{ uî…6â]*¸Cïÿ¶¬‡2-kcÐu£££îèvÙé*“g…(ß\Ú¶•È’"¦iº Rëºõdé¦Ý‘}ò‚ÔÿŸL~ÊóªL¨Èd‹<×2¦©™Í&>O=ú ¿ýkP×È•Ù[¼þ¹¼kEí‚#€#^ƳwíÂÉîÁî¾,>þüóxüñÇqÄGà /ĕ݆+/¹‡5k–á }Ð/ò6Òþ`äzëÖän;GÞáëQYb4á ÿ éùùKLñø “t1›Mú¨¹ûD£^âÁŸ”ðÿ[v$VSV°ØãüÔ2¿‡‹lCvÊÛŽ¼_±K‚h‘û—{žRkM©÷)4Táï…¯S±çñßVb’ÞmknÃb0«óçÁ€`«¹Ù?*v?¦iâ¼aì[±ËÀcÖ xèˆ ðËÏl„¦i¸B½ªã‘µ8ËqUÄÛyï>%¶qξÕ-Jäɲ(¦š_Å4;׃/å°“À°/ À2Äß4 p4@K‹„ˆ @µû»Ó >°ÉüY¤n¯¾ÜÛpŸ§ù4 šŸ} ¹ÿå:¾,+71 ¤µü}ÍËtІóŸÝâñçhÀ¡Ü¾Æ£Þì­¥€'2À‰ ÐR° ™à²ºÅwU[Á¾ÊC¶|û ˆ57–$d…}U}ûê8˜–©RÃâûO>|]eÙ6UûêÉî‚×UÓð§3®Àþ'÷£Ù͵m›8å7ˆ® êreæTÈUàÔI$Ðu3S(°›šššª÷NHçŸ>¶oߎP(„ññqlܸÑ]8¯”ÞÞ^|eëºÏ~éW~Úk÷Š/ÈzÒ¶xþÁ{ðÀÀƒÙ±óå'`¿¨ÂHxö”gÅŸïûRî_ã{¼ïaÕ0ð¶ñO®4}X6 ïS8]ZŽ*u>Ï‚?ÏÏ>õ3÷ñã …ÐÌfŸ###Á­W_ˆð)¿AxøíEë2†LnŸx<î®Q¤ib±þmãFüÛ-·`ë5×࢘43½½½¨÷nÌ»™Ægoo/®~ýUˆ|¨ ÷Ÿ åÜåy·,KԪ͕ôyÕ«^…~ðƒH&“n êºÎ‘è4kòÑ×ä+wζm[ì{K&Nd ¹ÆHKK >ô¡¹k—Äb1D£Qw6§,W"“%þÅ܉ŠéïïG(bÛ¶@¥ï­_þò—øío‹ÁÁAÜÿý8î¸ãpÆg ½½o{ÛÛÄ5'j[J‡¶mK·m _ÿ ¹žŸ¦iî,Kš_r°F¹µfL"ˉÊ÷H–*-l¿Èö|oåï²D›¼¯ü]>ÆÿÞË~9XÌqhšæ>§¦iî}$ÿZp~xòÉ'Ù¶-BƧù–Û‘ú50üÈ«ÜB¶m#‰@×u$“Id2†Áª#TSóѶ Ì •‘‘´¶¶º×ÑÑŽŽŒŒŒ”ÍvîÝ»‘3îFôÄŸBûÄ2@Õs@¾ýíoã§ù)&~ñ ´<ˆ¿8ã ¼¸òE\û‘OO_Èá€/¡òÙxþÔ_`úôZ¢®«œÒkaú“bÓ‡ ·qûÏnû^¹ÿ•8S?³ô6 §Ïây¦MÁž‡çÉ8„µð¼?Ï|ÏŽŸïÀæÍ›K?O.A³üÀr¼ˆÑÌfŸ{÷îÅÿò"œ—CxÏǼ—Í×°µmnÙ¹`- >é´a{·r]]ô÷÷7EÃhppèèè¨÷®ÌY³¼'µ0ÛøLe!º~™›L‘I”ÁÁAttt  ¡½½ñx‰D{öìq“žA1>>ޱ±±šø¯§fùL7Ó{2W³mÛJrÁx˲022‚×½îuèèèÀ\€h4ŠD"á®]òéOÚ½àŸíš%µÆsNð4Ó{2WsÏ?þñÈd2xøá‡±sçNyä‘xñÅñú׿ï{ßû°~ýz¼êU¯ª÷a–ÄÏtð4Ë{R s‰O˲`š& ÃpÄãñiãòïþN}ÙÙn†;0Á¿>g©Ç„Ãá¼s²ÿ§an½|Œ¿ÌæÐÐ;[´»»étŸÿüçqÙe—¹÷òyTUE"‘ÀððpÞcåóùQÈ$‚\gTÞG>Oácdû¾–ùð‡?Œï}ï{îk!×X«æõK¥RP¥äct]G*•r﫪*b±˜û{a"GþÛ²,(Š’÷:ÊçF£°, –e¹±, »víÂÅ_Œ_üâH§Óîó×M7Ý„N8¡Þá3¯æ›Î—ïDâÆ£‘þŽä>Ÿ‘HÇwÂá0EAww7†††<áôsI#\_-ÆsX`f¨ìر###y£ z{{ÑÑÑQöMyÓšw`åCa¯¾újüjÇ£xâÙÇñòÉ÷bïÞ½X±b{ì1œ~úé8òÈ#±zõjÀ²e˰jÕ*,[¶ K—.­÷áNÓ,ŸéÅô=óÔSOáî»ïƾ}ûpóÍ7×{wçÕlâóœsÎÁ‹ûÞ‰gŽÿžyæ<ûì³X¹r%~øaD£QÜyçxÝë^¾0Ø·oöíÛ‡ .¸ Þ»2gÍò=SÍ{²oß>ÜsÏ=xå+_9m!Öf2Û¶íë^÷:Ü~ûíxÅ+^xÍk^ƒc=°nÝ::t§žzj½¯¢ÅtÎiÕ¼'lÛ–ŽÏüàøÔ§>…?þñ8á„pôÑGãì³Ï†¢(8ï¼óê}H3²˜>Ó¢Ú¶íÞ½{qË-·Ô{wçÕlâóÍo~3î¿ÿ~<õÔSxå+_‰±±1lÙ²Å}]ùË_â²Ë.Ã-·Ü‚sÎ9=ôÖ­[‡àСCXµj:„N8=ôN=õT÷ç“O>‰N8aA®SÙ¶ ¶m=siÛ>vëÎXþ߸¯íkxê©§ðâ‹/â”SNÁ™gž‰Ôõ³ôsI#|/9Þï¹çÜ{ï½5oÛf†ÊÄÄÄ´ÛªYÜèy~ó›ÿÁç]'Ÿ|8ýôÓë}83ÖLSê›åXª9ŽåË—ãàÁƒyS@›Ñlâó=ïy^zé;xà§ ý ^zé%œyæ™8þøãë}83¶˜>Ó¢Ò±<óÌ3hooÇsÏ=Wï]w³‰Ï}ìc¸ë®»ðÔSëñú׿8ÿüóÝ¿¿ë]ïª÷a-:ÍŸ•<þøãX»v­[þ¦YͶm‰DðÆ7¾W^ye½aNšé3Ý,Ƕ­g6ñ©i®¼òJ¬\¹]]]õ>„9YLŸéFQmÛ¶Øg·ÙÌ&>ßÿþ÷ãÑGÅ 'œ×¾ˆD"y?ßö¶·ÕûðfŠÏJض-/‰àW+?ƒ³ÎZ‰Î߉׿þõ8å”Sê}8®ÅôY/A~ W­Z…3Ï<³æmÛÀ$TZ[[§Ý–Íf+N¹úÄ'>Qï]§E,È_µ4›ø<ûì³ñÅ/~±Þ»NÔôfŸ½½½õÞm¢¦Ç¶-5"¶mKÇç©§žÊ¶-Ñ`Û–(˜æÒ¶eó–êe¾Ú¶‡×ûÀ¤ŽŽd³Ù¼Û&&&ªÊvÑüb|ã“(˜›DÁÅø$ .Æ'Q016‰‰‚ŒñILŒM¢àb|ã“(˜›DÂaSSSSõÞ ¿l6‹l6‹öövN# Æ'Qp1>‰‚‰±I\ŒO¢àb|c“(€ """""""""""¢  Ì*DDDDDDDDDDDDAÅ„ QL¨UÀ„ QG|ö³Ÿýl½wb¶²Ù,ÆÇÇ­­­õÞ²û˜ÍfÝÿZ[[±dÉ’ª£ÞÇ999‰Ç{lÆûÄã*v,s}êýþQ£¼&ÍðÞ—ŠÏ¹ÆßB[¥ã(õí8A£¼&þÞÏöÜYéïÍrî¬×±ÐÜã˜cŽ©Ù{½ÐŸù|“““8餓jº¯ q,Õœ/ÛÛÛg¼oAzhvŠÅ&ÐXï}¹ø zÛ¶šóþlâ³ÞÇEµ1›ø Ò{?—sç\³fŸA?.ªl>ÛGµVë6v­LNN²¬yi;7´©µsçΩ®®®©M›6MuuuMíܹ³Þ»TÔG?úÑ©ÓO?=ï¿›o¾¹êãÂq~éK_šúÒ—¾4íörûÔã*v,sy‚ðþM#½&ÍðÞûLÏ5þêql¥¾gʽGA<Ž k¤×¤ÑßûÙœ;+ý½YÎõ<š›|pª«««fïõB¾ô¥/¹ÏwÉ%—L]}õÕ5Û×…:–bñXx\ï|ç;§&&&ò=¢Ù)›SSõÞ—‹ÏFhÛ–:ïÏ%>ƒp\4w³‰Ï ½÷s9wÎõ8ky 3ÏF8.*o>ÛGµVë6v­ŒÍ[Û¹Ñ5lBÅÿA›:ýôÓ§|ðÁzïÖ4›6mšvâœÉqÔó8wîÜév˜;ù”Û· W¹c™Ë{Ô(ŸÃ…ÔH¯I#¿÷å>Ós¿…<¶Jß3åÞ£ G£h¤×¤Qßû¹œ;+ý½YÎõ8ª yAäïå3ýàƒæmbbbêôÓOŸ«É¾Î÷±”ŠGy\þã¸ä’K¦ Ãh¸÷ˆf¯XlNM5Î{_)>ƒÜ¶-w®œk|Öû{‡jc6ñ”÷~®çιç\Í%>ƒ|\TÙ|·j­ÖmìZñ¿fS—\rÉÔ 7ÜPÕ>4{4ä*###hmmE(ttt ££###õÞµ¢ûZlZY5ÇQïãìììDOO:::f´ïA<®JÇ2›÷¨ÞïO5ÚkÒÈï}©Ïô\ão¡­\l–{‚v Ñ^“F}ïg{î¬ô÷f9wá=¢ÙéïïGGG:;;ÝÛé3=99 À+7ÐÒÒ‚öövLLLÌy_âXJÅc6›E(Ê»}ýúõUWÐÞ#šb± 4Ö{_.>ƒÞ¶-w®œK|Öû¸¨6fŸAzïçrîœëqÖÂlã3èÇE•Ígû¨ÖjÝÆ®•‘‘LLL`óæÍDü›¦‰õë×W܇ÅGÖ{fc|||ÚE|kk+²Ùl½w-<ùlݺ###hiiA__zzzª:Žz§üâ)Vç®Ü¾MNNî¸JË\Þ£JǹÕû3;þÞ—úLÏõ{e¡ßÃrß3åÞ£ G#h¤×¤‘ßûÙž;+ý½ß;óqî¬æï<ãããØ½{7víÚ…-[¶äÝÞ(ŸéŽŽôôôàꫯF(r“‚òB/èmÛúeÀ°€IDATRñ …ÜcD|îÞ½Û½øm¤÷ˆf®TlÊ¿5Ê{_.>wìØè¶m¹óþ\â3ß;47³Ï ½÷s9wÎõ8kµÿr»…ÊÅgЋ*›ÏöQ-ÍG»V²Ù,:;;188ˆÝ»w£¥¥===5i;7ƒ†œ¡"3Š~¥FI֓̈nÞ¼÷Þ{/¶oߎþþ~7#Wé8‚|œåö­‘Žk.ïQŽ#(é5iÖ÷~®ñ¤c+÷5ÒqE#½&ÍúÞÏe߃t\Íܾ¡é&''±eËlß¾---yk´ÏtKK‹»0iáE`3´mwïÞ7" ¹ ÎF{¨zåbh¼÷¾T|6KÛv¦ñÙ(ÇEÅÍ%>ƒöÞÏöÜ9×ã\H…ñÙ,ÇEB­ÛGµ2_mìZÉf³îl“Í›7£½½½½½nRd±ÇAC&TŠe—ƒ˜åêèèÀÀÀ€›½ …BذaƒÛáPé8‚|œåö­‘Žk.ïQŽ#(é5iÖ÷~®ñ¤c+÷5ÒqE#½&ÍúÞÏe߃t\Íܾ¡é Ã@GG‡[cbbããão¨Ï´]·k×.ôõõÁ4MŒaÇŽsÞ×z¦'''ÑÛÛ‹þþ~lÛ¶ Û¶m«zß‚ôÑÌ”‹M ±ÞûrñÙèmÛÙÆgЋʛK|齟˹s®Ç¹JÅg£ óÕ>ª•ùjc×R{{;¶oߎP(äV$¬¸‹!2¡ÒÑÑ1혘˜\¶KfðýüYÇJÇäã,·ot\sy‚tAÑH¯I³¾÷s¿ [¹÷¨‘Ž#(é5iÖ÷~.û¤ãjæö 799‰;v`ÇŽÈf³¸á†pà 74Ôg:›Í¢½½=ï³ …ÜtܶݴiÚÛÛašf^y‹jö-HïÍ\©Øë½/ŸÞ¶m|ý¸¨²ÙÆgÞû¹œ;çzœ ¡T|6úq‘0_í£Zš6v­„B¡i3gš¡Ï¬f`áûyÑÕÕ5uóÍ7OMMMMMuuuMMLLÔ{·òìܹsê’K.q÷kbbbê’K.™Ú¹sgÕÇ„ãÜ´iÓÔ—¾ô¥i·—Û· Wá±Ìõ= Âû4òš4Ë{_,>çõ8¶bÇQé= âq]£¼&ÍðÞÏæÜYéïÍrî¬ç±ÐÜmÚ´É}簾ç3}à 7ý܆Q“}]¨c)7ß|sÞ>ø`ýG47…±95Õ8ï}¥øl„¶m¹¶ìlã3ÇEµ1Óø Ê{?×sç\³–¯ÿL㳎‹J›ïöÑ|¨e»&&&¦ººº¦ÆÆÆÜß±Ïl¾4ä¢ôÐ×ׇ-[¶ ³³cccèëë+Z›²žäâ¹7nD{{;ÆÆÆÐÓÓãÖì«æ8‚|œåö­QŽk®ïQPŽ#Hå5iæ÷~®ñ”c«ô5ÊqI£¼&ÍüÞÏe߃r\ÍÞ¾¡™i”Ïôúõë122‚K.¹Èf³èèèp'ë¾Öë3Íf‘ÍfÑÛÛ›wûæÍ›Ñ×××PïÕ^£¼÷•â³QÛ¶sÏ ÕF#¼÷s=wÎõ8çS¥ølÔã"a¾ÛG ¡Þû×ÒÒ‚¾¾>wý¹Žf3ô™ÕÂaSSSSõÞ‰Ù’ÒÞÞèiCãããîÔ¦bûYé8‚|œåö­‘Žk.ïQŽ#(é5iÖ÷~®ñ¤c+÷5ÒqE#½&ÍúÞÏe߃t\Íܾ¡™i¤Ï´|¾ÖÖVtttÔt_ƒü™n¤÷ˆj«‘ÞûrñÙLmÛ™ì[#UÖ(ïý\Îs=ÎzjÖã"Oâ,¨û7ŸmçFÖÐ """""""""""¢…ЋÒ-$&Tˆˆˆˆˆˆˆˆˆˆˆˆ*`B…ˆˆˆˆˆˆˆˆˆˆˆ¨&Tˆˆˆˆˆˆˆˆˆˆˆˆ*`B…ˆˆˆˆˆˆˆˆˆˆˆ¨&Tˆˆˆˆˆˆˆˆˆˆˆˆ*`B…ˆˆˆˆˆˆˆˆˆˆˆ¨&Tˆˆˆˆˆˆˆˆˆˆˆˆ*`B…ˆˆˆˆˆˆˆˆˆˆˆ¨&Tˆˆˆˆˆˆˆˆˆˆˆˆ*`B…ˆˆˆˆˆˆˆˆˆˆˆ¨&Tˆˆˆˆˆˆˆˆˆˆˆˆ*`B…ˆˆˆˆˆˆˆˆˆˆˆ¨&Tˆˆˆˆˆˆˆˆˆˆˆˆ*`B…ˆˆˆˆˆˆˆˆˆˆˆ¨&Tˆˆˆˆˆˆˆˆˆˆˆˆ*`B…ˆˆˆˆˆˆˆˆˆˆˆ¨&Tˆˆˆˆˆˆˆˆˆˆˆˆ*`B…ˆˆˆˆˆˆˆˆˆˆˆ¨&Tˆˆˆˆˆˆˆˆˆˆˆˆ*`B…ˆˆˆˆˆˆˆˆˆˆˆ¨&Tˆˆˆˆˆˆˆˆˆˆˆˆ*`B…ˆˆˆˆˆˆˆˆˆˆˆ¨&Tˆˆˆˆˆˆˆˆˆˆˆˆ*`B…ˆˆˆˆˆˆˆˆˆˆˆ¨&Tˆˆˆˆˆˆˆˆˆˆˆˆ*`B…ˆˆˆˆˆˆˆˆˆˆˆ¨&Tˆˆˆˆˆˆˆˆˆˆˆˆ*`B…ˆˆˆˆˆˆˆˆˆˆˆ¨&Tˆˆˆˆˆˆˆˆˆˆˆˆ*`B…ˆˆˆˆˆˆˆˆˆˆˆ¨&Tˆˆˆˆˆˆˆˆˆˆˆˆ*`B…ˆˆˆˆˆˆˆˆˆˆˆ¨&Tˆˆˆˆˆˆˆˆˆˆˆˆ*`B…ˆˆˆˆˆˆˆˆˆˆˆ¨‚E›P1 ¦iÖ{75Çq`š&,˪ÉölÛ†aõ>,ªÆgã²m{Z\36ã±¹TŽãÀ¶í¢7M³èߨ¾«k.çÎR±êß.ãµþŸõU¯ëNžKcµþf¯ÅÎ¥òv^‹66Æeói†¸\´ •L&Ó°ÙÝÝ]³Æ`½X–…µk×"•J!‰ ‹Íy›¶m#“ÉÔûШŸ)‘H ««kZ\36ã±¹T©TjZ#×0 7Æ»ºº¾Ül«i®çÎb± 0^ƒ†ñY?õ¼îä¹´ñ0Vëk¶ñZê\ ðZ´0.›O3Äå¢M¨42Ó4á8N½wcN"‘âñ8†‡‡1:: Ó4>˜ˆ€æˆÏÙ°m©T £££n\†ÁÆÕÕbǹ0 ‘H©TjÚ߉†††0<<ŒááaÄb1Ž®¥šX¬±:—sg¹X¯T;Ÿõ¸îä¹”ê¡Ñc˜]¼ò:”‚¬â’Š[4 •L&ƒµk×â°ÃC,›ö–™ð¶¶6$ $‰¼/`˲‰DpØa‡¡««ËýRïîî†ahkkC[[ Ã@"‘@[[Ö®]›—EÉ}KI$îO˲Ümú÷½Zþý1M³âï3Ù^¹ã“_(ñx ( öìÙƒp8‹ÅÞBÅg¥x)uLò=SÅý©ªjÑÆƒÜ~5ÏG ¯\<Îö\ Tÿ¬E,óÕÄçL¶9ñ8“¸òÇ#hš†h4 MÓòîgš&E®ëîý4MkØÑbÍ€çÎ|‹éÜ ”ŽU€ñóq.]èØÿ\:ÛëNù>ð\Úüx.ÍWÏsi¥x­Å¹T¾Fì' ¶fí¿õo·ÖçÑzµqKÓ¢è¿ZöìÙ3`*™LNMMMMÅãñ)Sñx|jjjjêÀSŠ¢L M8p`*N˜Îû»|üððð”¢(îvåv’Éä´çÑuÝݙܷÿ¾˜ŠF£S˜RÅý[5ÛÑu}jxxxêÀ¯f{Õ_:žÒuÝý‡§ís±ãJ¥Ry·Ë÷A>vxxØ}Žh4:¥iš{¿r£úšK|–‹Í©©™Å\â³Xì-T|VŠ—rÇF§ÂáðT:ž ‡ÃyÛ,›Õ<-¬rñ8—såÔTõŸÁZÅ¢ÜV­ã±šø¬f›óåW.ýt]w÷Qîgák_xZ8ËÅæÔÔÌb.HñY,ö*>+ÅK¹cŠÇãî{§ªjÅØ¬æùha•‹Ç¹œ+§¦ªÿ Ö*å¶jÕÄg5Û¬ægåW.ý ;xŠ]8øß_ZX´†¤ëú´`«ö ¥ð}*¬¥¨iÒé4âñx^­ÅJ£ú™K|26çÇlâŶm¨ªš˺®»-›³}>š•â‘çÊ…7Ûø(÷¸rñXЦiE·9_ w*çÎàYèsg9Œ×úâ¹48ærÝ ð\Úìx. –ÙÆk¥s)À~¢FÂþÛà™ëQ ñãrQ$TTU…aî›`YV^&,» `˜¶€O8†eYnÆÌq¬]»6oÑ1ªžlHú_ÏL&SUCÒ¶m÷ý‘“‹úÞ 7CUUwTB¥ÇQýÌ%>›óc6ñ"ãZ¾OòqþÅé±9Ûç£ùQ.y®¬ÙÆG¹Ç•‹ÇRä…©BÛ¶óö¥…Ãsgð,ô¹³Æk}ñ\s¹îx.mv<—ËlãµÒ¹`?Q#aÿmðÌÇõ(Ðøqyd½w`!D£QX–…µk׺_¶þF‹¦i‡ÃèêꂪªÓ²_ªª"£»»Û}¼®ëukø¨ªŠD"t:]××u¶EA2™DWWt]w_Ïh4ZÕ±Çb1¨ªêŽDˆÇãEï+ŸcõêÕ3z-¬¹ÄgÐbSîS#ǧ<†™Æ‹lØøßGMÓǧ5rdlÊ÷‰ñåâ±ÑΕrŸc<–{\¹x¬4",™L"‰@Ó4X–…d29§²£4{ç/ ×4¿ŠÅc£+ýû²Øâq>ãJ¾¦ªª²DIðÜ }îœév¯õÁsipÌæõä¹tñà¹4Xfûšò:´¹°ÿ6úz´‘ârQÌP‘J½ Žã »»CCCÐ4 ‰D¢hýÆ…hðض]vÁ$]סëzÙý¨vó±_31—×s¶Ó½‚8MŒ„¹ÄgÐbs!ãs>bÓÿØ™ªG\Sí‹ÇF=W.æxœËãJaçO°ðÜ™¿Zï×l,ô¹³Û¥ê,†séb¸î”ÏYKŒÍ` ú¹f?Ñ|Kgûšò:´¹°ÿ6ó±_3Õè×±µ¶¨*¥¨ªŠt:íÖkSUCCCuÙ¹€R¹}]ˆm,Ä6g³³ÉL9£I•%>kµŽ¥ùØÞBÆ ã³q%Æã|=ŽšGP╱J”/(± 𺳚ý`\/nŒ×…ÝÞBcŒ7&ÆåÂì—[ y=ÚHq¹¨J~ÍÆáõÞ"""""""""""¢ cB…ˆˆˆˆˆˆˆˆˆˆˆ¨&Tˆˆˆˆˆˆˆˆˆˆˆˆ*`B…ˆˆˆˆˆˆˆˆˆˆˆ¨&Tˆˆˆˆˆˆˆˆˆˆˆˆ*`B…ˆˆˆˆˆˆˆˆˆˆˆ¨‚#ë½sõîw¿]]]õÞ9{ê©§°dÉ}ôÑõÞ•9{â‰'pâ‰'Ö{7ì8öíÛ‡÷¼ç=¸à‚ ê½Ë²sçNüïÿþ/N;í´zïÊœ5Ëgz1~ÏÜsÏ=¸öÚkë½»³yófœqÆõÞ9{þùçñÜsÏáøã¯÷®ÌY³|ÏTûž<õÔShooÇUW]Uï]œ«®º gžyf½wcÎã9'èª}Oض-îÖ[oÅ÷¾÷=¬ZµªÞ»2g‹í3Ýض›O~ò“X±bE½wcÎØ¶ ¶mç.èmÛ ŸKá{!èñ>mÛ†O¨üáÀG?úÑzïÆœe2tttàì³Ï®÷®ÌY?®¸âŠzïÆ‚G&“Áääd½w7pzè!<øàƒxßûÞWï]™³fùL/Æï™›o¾¹Þ»H·ß~;z{{ë½sv×]wa||—^zi½weΚå{¦Ú÷ä®»îB6›­÷îÒ“O>‰P(Tïݘ³ÅxÎ ºjß¶m‹“¯I3ÄçbûL7¶mçæÀ;ßùÎzïÆœ±mÚ¶ žPÉf³Ó¾d:;;ÑÒÒ’÷÷ööv´··WÜÞòå˘3y]:;;ÑÑÑQï]™³P(ÔïIµÇ122‚eË–Õ{wç¬RlúïSM|®Zµ §œrÊ¢ú,ÝbüžY¾|y½wµ&jŸ­­­Mñ™nmmÅñÇßÇÒ,ß33yO—-[†U«V5Åga±}¦ÁbkÛµÏãŽ;®)>ÓlÛÏblÛ.¶~Û ŸKá{!èñ>mÛO¨ô÷÷c÷îÝy·  appýýýèììÄØØúúúÐÓÓSv{«W¯^èC˜•޳‘ôõõÕ{x³P.6Ì8>W¯^èi3Ñ,Ÿ~Ï4®ùˆÏfÐÑÑ؆ïL5Ëgº™Þ“jõ÷÷cppÈf³hiiÁu×]‡–––бÛÌxÎ žfzOªQ.6åßk|ò3<ÍòžT‹ñY\3µ£šå3ÝLïIµjÝotAßÿFø 6K¼ÏÄ‚'T&''Kžûûû±}ûv„B!ŒcãÆ…BUe<‰hnÊÅ&Àø$ª'Æ'Q0e³YìØ±»vír/tt]Çàà 6oÞ\1v‰h~TŠM ò¹•ˆæã“(ØØoKTÙá ý„###Emdd$¯‰ÌÀŒŒÔû5"ZJŦü㓨~ŸDÁ”Íf …òF­_¿ÊÇ.ÍŸJ± 0>‰ê…ñIlì·%ªlA*r˜­[·âŒ3ÎÀùçŸÁÁAÀøøø´€mmm­¸¨ÓÞ½{›ba]jL½½½¸þúëë½sV.6ÙÇçõ×_þþþz-BãããèííÅþýûë½+s6ñ¹ÿ~ôööæm‡h¡ÈRO<ñD½weÎB¡Üß'''±{÷n´··WŒÝRض¥zj–¶m¹Ø”¿3O¶m©^dÛvïÞ½õÞ•9›ødÛ–ê©™Ú¶óÙo;>>^ïãE¨¿¿^Ú¶ šP‘#6oÞŒ{ï½Û·oG?FFFòF#HÕŒHX½zuÞɘh! à²Ë.«÷nÌY¹Ø0ëø¼ì²Ëe-Eª¿ŽŽ `ÅŠõÞ•9›ø\±b_/–šSOOúúúpâ‰'Ö{Wjj÷îÝnÙƒžžžŠ±[ Û¶TOÍÒ¶õ+ŒM ò¹µ¶m©^dÛ¶YÖÁ“jŸlÛR=5SÛv>ûmƒ¾5§¾¾¾yiÛ.è*² …B!lذÁ6V(›Í2àˆ@¹Ø …BŒO¢:b|Ûää$¶lÙ‚l6‹mÛ¶å•A(»D4¿JÅ&Àø$ª7Æ'Q0±ß–¨: >C¥pŠWKK ´…ÓÄ&&&X7“h”‹M€ñITOŒO¢`Û´iÚÛÛašf^GO¥Ø%¢ùU*6Æ'Q½1>‰‚‰ý¶DÕYЄÊÈȶlÙâÖäó×Ê …B˜˜˜p§qŽ#›ÍbÆ õ~ˆš^¹ØÀø$ª#Æ'Qp brrëׯÇÈȈû_6›­»D4ÊÅ&PùÜJDó‡ñI\ì·%ªÎ‚–üêééÁøø86n܈öövŒ¡§§Ç­sÙ×ׇ-[¶ ³³cccèëëãH¢P)6Æ'Q½0>‰‚+›Í"›ÍN[D~óæÍèëë«»D4?*Åf5çV"šŒO¢àb¿-Qu4¡Û¶mÃøø¸;-Ì?Ê §§¡PÙlvÚ߈h~•‹M€ñITOŒO¢`êëë+»@u¥Ø%¢ùQ)6Æ'Q½0>‰‚ý¶D•-xB@Ù‹DõSi11Æ'Qý0>‰ê$ .Æ'Qp1>‰ê‡ý¶Då-è*DDDDDDDDDDDDˆ """""""""""¢ ˜P!"""""""""""ª€ """""""""""¢ ˜P!"""""""""""ª€ """""""""""¢ ˜P!"""""""""""ª€ """""""""""¢ ˜P!"""""""""""ª€ """""""""""¢ ˜P!"""""""""""ª€ """""""""""¢ fP™œœÄÈÈÆÇÇë} DDDDDDDDDDDDójV •þþ~œþùèííE?FFF ë:“+DDDDDDDDDDDÔ”fœPÙ½{7100€@(BOO6mÚ„ÉÉÉzQMÍ8¡222‚žž„B¡¼Û7oÞŒöövŒU½­ñññi ˜l6‹‘‘d³Ùz¿6D‹V±ØŸDAÀø$ ###%ÿÆØ$ZxåbÓÿwÆ'ÑÂc|ûm‰Š«Û¢ôÙl›6mÊKÀ bãÆØ±c6n܈ÁÁÁz¿>D‹N±ØŸDAÀø$ žþþ~7þ¶nÝŠ7ºžŒM¢ú)›ã“¨žŸDÁÇ~[¢ÒŽœéB¡®¾újlذ!ïöÁÁAd³YtvvVµ­[·N»­¿¿Û·oG(Âøø86n܈P(„öööz¿ND‹F±ØŸDAÀø$ –l6‹;v`×®]èèè躎ÁÁAlÞ¼™±IT'•b๓¨^ŸDý¶D¥Íx†ÊúõëÑÓÓƒ7bëÖ­ƒ®ëèïïG__ZZZ*n£¿¿yÉ—‘‘´¶¶º¥Ä:::ÐÑÑQrú'Õ^±ØŸDAÀø$ žl6‹P(äv¢­<11ÁØ$ª£r± ðÜITOŒO¢àc¿-Qy³*ùÕ××Ó4±yófôôô ¯¯?ÿùÏÑÓÓSñ±ãããØ½{7¢Ñè´Û 3š­­­kòíÝ»½½½õ~i‘êííÅõ×__ïݨ‰R±)ÿ6›ø¼þúëÑßß_ïC£Eh||½½½Ø¿½w¥fÇSËøÜ¿?z{{9E›êbppýýýxâ‰'ê½+s …000àþ>99‰Ý»w£½½m[jHÍÒ¶-›Û¶ÔxdÛvïÞ½õÞ•9›ødÛ–ê©™Ú¶ÀüõÛŽ×ûÐhêï¶íŒK~ ¢½½¡P¨ªŠßää$¶lÙ‚íÛ·O›É"G#øU3elõêÕy'c¢…400ÐUåb˜}|^vÙeèëë«÷áÑ"ÔÑѦ蔜ø\±bÏT7===hoooºÑl»wïF¿ÛF.Ö>`Û–‚®YÚ¶~…± °mK§™Ú¶~µŠO¶m©žš©mË~[j6óÕn›qB%›Íbpp»víšñ“†ŽŽ· ÂÄÄÆÇÇÑÚÚŠÖÖÖ¢ÏåŸJDó£\lvtt0>‰êˆñIlòÂ3›ÍbÛ¶mnÆ&Q}•ŠM€ñIToŒO¢`b¿-QufœP‰F£˜œœtG*v›ßää$vìØ@Þ 7Ü€‰‰ „B¡iÓ3'&&¸°Ñ)›².&㓨~ŸDÁµiÓ&tvvNyÇØ$ª¯R± 0>‰êñI\ì·%ªlÆ Ã0Ü’æwï½÷–|lá4›ÞÞ^lÞ¼ÙMÂÈ h(Âøø8²Ù,6lØPï׈¨éUŠÍP(Äø$ªÆ'Qp brrëׯÏ+ó Ëã26‰ê£\l2>‰ê‹ñI\ì·%ªÎŒ*}}}n€cbbÂ-;2W}}}زe :;;166†¾¾¾¢õâ‰há1>‰‚‹ñITÙlÙlvZMûÍ›7»mfÆ&Ñ«›ÏDõÂø$j\ŒM"aÆ @Œ(èïïÇää¤{[{{;¶oß>£ÄJáôΞž„B!d³Ywt-¼bS¯ŸDÁÀø$ ÿ@£b›DõQ)6Æ'Q½0>‰ûm‰Š›qBeddýýýèëëÆ ÐÒÒ‚l6‹;v`Ó¦M¸í¶Ûæ´C H¢àb|ã“(˜›DÁÅø$ .Æ'Q016‰€Ãgú€Ý»w£§§===î´®öövlÛ¶ ­­­y50‰ˆˆˆˆˆˆˆˆˆˆˆšÁŒ*%ÿƺyDDDDDDDDDDDÔŒfœP …Bؽ{7ÆÇÇónD6›Eggg½‰ˆˆˆˆˆˆˆˆˆˆˆÀ¶ówñ_á} o ¢¯¡ÒÓÓƒññqlܸhmmE6›ÅÄÄúúú8K…ˆˆˆˆˆˆˆˆˆˆ¨¤Râg<îÝfš€ªŠÿfÊ4]ÏÿÝ4dÒ»Í0Dò¤ð6MÂaï¶DBü®iõ~•<3ž¡Û¶mî]»°aÃttt`óæÍøùÏŽžžžzpÀ²¦ßV83Ä0¦ßO&^ ïW(‘Èÿݲ¦Ï>q@Q€®.ñwù|… Ëš¾o±X}_ÃY%T¸‰”¾¾¾¼ꉈˆˆˆˆˆˆˆˆˆ¨~§xr#“™~›®ç'Ld"Ãÿx9«Ä¯0¹ašâ±ò?@Ì0±,±­LˆDò,2ÉSlßäì?Ã/¼}¡Ì*¡222‚­[·º¿¢¿¿“““õ9 """"""""""¢Eªp`ú,“bk™$“"9!€˜=¢ë^‚ĶÅþí•z¾xÜÛVw·øOQ¼Çg2@4*¶í8âï²L˜L¬Ø¶HÀ¨ªø·L´ÈY,¦)@Åf°Ì·¯¡2>>ŽÞÞÞ¼ò^íííÄÈÈvíÚµ°G@DDDDDDDDDD´ˆuw{öx¿g2"ñàOL8N~"¤«Ë+¿‹G"âok׊Ÿ±˜XÃ$õ’"¶-3<ìÍÑ4ïï2ñ"12Y"·#·)ï£iâ>Š"ž_×ERfÏq\ò>–¤ÓâØä¬—tZ$Wüë±Ì§'Tn¸áôôô`Û¶mîm¡P×]w6n܈‘‘„B¡…Ù{""""""""""¢E¤«K$3Eü.“$¦)þ-(ò69ÛĶEBð)ª*’2xIUõ(þÙ"ŠâýÔuñ·TÊKž$“Þ‚òr‘y™$‰ÇÅý††Äí±˜¸¿m‹;ŽØöð°·oþuV4ÍÛN*å%\di1y|óeÆ%¿²ÙlÑõRZZZ¸Ž Q.èäÏq‘xP‘h0M/ÙŠÿ Ãû]UÅ,Y2KÓÄ64Mü7:*î§("Ñ‘N‹dˆœe"3òþªêퟪzå¼TÕK®ÈÙ'££âßrv ¶¯(â6¹€¸ /2)3<ì݈¤ŠL e2^ɲ¼™6µ6ã*DOOÚÛÛÝÛwïÞñññ¼Ûˆˆˆˆˆˆˆˆˆˆˆ¨²HD$üIƒTJ$äm2ùˆY þEÝÃáüµPFGÅ}d‚D®‰"gy$“^2D×Å ‘tZü®iù³Kp3 åþ&g¬È䌼o2 8›%7{Dî³Lþ(Š—¨)fxXütÿžõfÐÈý’‰·\ÙY@â;ù Ý«êü¼G3N¨lÞ¼Ùlº®»¥½&&&0>>ŽmÛ¶1¡BDDDDDDDDDD4rö‡œÙ!ùl—寑È3B‘Xð—ÙÊdDbAÎ ‡ÅŒŽ¶6qùXY6¬LnÈû"týˆ~HÜ&Kl9ŽØ®ÜŽ2æ=§¼-Ÿí‹ WÎK&‘ElO&L4 H,”÷yk¸âß»v…±fÍ“5}ŸfœP€mÛ¶¡§§7Üp µµÛ·og2…ˆˆˆˆˆˆˆˆˆˆh†ä‚ëþrX€H ÈõCð„—Éùw9ÛÄ_® ÈOÎ"QÒÝí• ó«´þHøMb{rŒÜ¼}Îý­ð8ò*÷ŸŽòt¦øéŸq–eAQ¨ª < X·ΤH4Ù¶8þ;ïN9åÙš¾OU%T188ˆ 6`ýúõhooGGG:::jº3DDDDDDDDDDDͤpAøRäâîá°øw&#’,r¶‰\€].ú.·—Lz¥ÂÊ&2 ÏbÖˆ“+æKl¨j‘ò]Ü$HIFîg¥„Š <ýf˲ÉÕK&“ˆ~ 0&Ö[±mñzÇãÀGd„fü~•SUB¥§§6lÀÈÈvìØl6‹ŽŽlذI""""""""""¢"l[¬Mâ/ψ‰­TJ¬ybÛb–…?i"× Éd¼…àýkœÈ$J¥dŠÿ¹gÅP@É{N@€RŶ¬Jûèà¡ß?„#;ÄY8ËÛÀmÛÐ4 znúͽß|Êò£ðµ¯=‡%KÆ;H$Lœx≳<ÐÒª.ùÕÒÒ‚õë×cýúõÄ"ôƒƒƒ³J®Œcbb­­­Ó“Íf‘ÍfÑÞÞÎbD ¬\lŒO¢zb|Ûää$&&&òâOÆ¥_gg'ZZZê½»D‹F±ØŸDAÀø$ &öÛÖžãxe¶üd’%™¥»äº#š&fX¤RÞÂï†!Ë\åÖ61ÄlŒŠ˜–¼uFf¬Òã,L›bš&lÛFÔ—Mšè™ÀÑÿw4~œù12™ †|“Éd i‰>páÐý?ÝÀ5òµtà84MC8ÆÚµk144„3žÐ ³O¬R ‘H¸ëšÈm½ôÄKPUÉdªª"‘HÀ²,X–…D"×¼æ5¸àÄ Œ&F¡iººº0<<ì&SਣŽÂ‹¿ˆWî~%Ž9æ˜iÏFëŽaõ}«¡‡u¬¹MÞß.»ì²™½¡U¨:¡²uëVôööºu,³Ù,6mÚ@ÑîÝ»±eË–²ÛX¿~=úúú099‰‘‘ô÷÷£££ÃÍlž0[[[§ÕÍ,´wï^ôööÖü…!ªFoo/®¿þúzïÆœ•‹M³ŽÏ믿¾ªd+Q­É„ÿþýûë½+s6ñ¹ÿ~ôööæ ’ Z(²TÀO>Ù¶¥z‘mÛ½{÷Ö{Wj¢Öñɶ-ÕS3µmç³ßv||¼Þ‡7o2‘ 1Mñ{*%nS¯´W&—¬Ð´‚&³EººòoO§Åïþì‹2*üÝòýçã8ûaC,&_ÁªGW‰Ïº/ùÒÕÕ•;6 ©T ¿úÕ¯ðÓŸþ{÷îug­D£QD£QD"X–…p8ŒsÏ=W<§ (ŠRt‹ôµŸ| ‡ÿñðò $ÓJ’õ÷÷ÏKÛ¶ª’_rÊ×®]»Ü»wïFkk+¶oߎ––ôôô@×uwa¢r²Ù,vìØl6ë®Ã"GÚúU3"aõêÕ¨ù CT¦º¨*›Àìãó²Ë.›V—h!ttt``` ©:%kŸ+V¬à¹“ꦧ§íííM?šM֜޼y3022‚-[¶ ½½½l ¶m©žš­m[Êlã“m[ª—flÛ–2›ødÛ–ê©Û¶ì·­žiŠd‰®‹ˤÊÐP~¢E×á& Ëjɲ^þäIUë›X¨\¢K*H–„Ã^)1oGÊo"•Jaì¬1l~v3.².BÊÓrâñ8t]w“"OÿàiÀO®ø >ýˆûxMÓN§¡ËLŽÜ'Gs‰ƒV|?Ê%™4ä%™æ«ÝVÕ •n¸¡P(o:æÈÈÖ¯_Ÿ7 L.XT‰l ìÚµ »wïÆàà`Ñ‘ Õl‹ˆj§Xl`|㓨±È˜•?¡P6lhª‹m¢FÅø$ .Æ'Qý±ß¶zr”x·ø·ªŠß5Mü;³T49s"1}šVÅL”b¢¨nø(¦%^äþ剉Åãc±˜{“\L¾«« º®cûÒí˜:o >ú(ÇeYPUJ.;“ÉMŹôÒKñ‘• Óç(Šâ%S‘\ £òÌÿkSÍ/Õ$£æ¨ê’_…YÇ‘‘tvvæÝ&“+¥ bÇŽy÷ïèè@6›uúMLL°n&Ñ(›ŸDuÄø$jLÙlvZiƒJme"ZŒO¢àb|ÕûmgÎqDrB»^$Eü‰‘hT,$ŸNÛÕÍ8™¡ý¿®²Ä¹ À·Æ‹ã80Msúý‘ñ'= Àã8…¦ihkkÃÝð_¸ñÆ‘L&144Í·ÐK2™ÄE›.òf»Ø(M–K¡<*Yâ>ºïoz…ç­ª*­­­y£vïÞ yÓ-'''1>>^4cé788èÖÄ”‘S7å"G€(3–Íf±aÆù}ˆ@éØÀø$ª3Æ'Qã‘%Jü±»{÷îEÑIŒO¢àb|ÕûmËs ¥¼ü”3¦/6ˆÙ*‰DB$0”ꞣZ{ïÜ+fx”£BÜÇ·¿rax¿k¸w¯ºû¿»¶m#“É ‰@Ó4D ¦Ï(Š‚žz*ï`‘™1ÓöMÉý,—ñ¿n)äÍzq™ð/V‰ûÔPUk¨¬_¿†a`ëÖ­…B0 ¡PÈ%099‰þþ~´··ç•+ÔÓӃݻwcãÆhooÇØØ6lØ€žñ&ôõõaË–-èììÄØØúúú8hTŠM€ñIT/ŒO¢ÆÔÓÓƒñññ¼ØíééÉ‹]"ªÆ'Qp1>‰ê‡ý¶•†oMˆuH,Ë‚fh@EËMÙ¶ Û¶Eb£šŽ~"‰P€q‰Dñx†aà-ê[ðèÈ£X©¯,]æJ–Ó ‹ÄŽãˆTU…išîl”¶ƒmØ·dþæõƒ?ê„eYˆÇãy³O¤d2 tçö³ØóZ¹ÿ’IŽrI%÷w¥×Föý»Ôq^›VÆÅ`†JU •ööv\wÝuزe  …ÜE]FFFÐÛÛ‹öövlß¾½â¶0>>îN ó2èééA(r¶ç¢…S.6Æ'Q=1>‰‚¯Øb›Û¶m+»D4ÿJ-„Ëø$ª?Æ'Qð°ß6Ÿm‹¤‰\ÀÝ4Å‚î–%f«$“"‘ö`OɃeY"¡b¡ü‚ê’‘ÛNÁ}Çqg¨ªŠW¾ù•8æÐ1b»¾ç• UU¡:*îÜu'Î=÷\œµò,¼?ùþ¼}²m©T ¿üï±&¾P6­Í] eZBEΈÑP:¡âønÏ t™®Lî~:Ê'šº‘ŸT)\sŶ[2À®¸˜>¤i€:›EiªWUB5Ú‹ÕWëììÌ[0¬Úm•²X’(ˆÊÅ&Àø$ª'Æ'Qcª»DT?ŒO¢àb|Õûm=ÝÝr‘y‘ H§Eÿ}"LL<€—_Ž`hhèöþr/Vë«aÛ6E¢(°, Š¢ˆ„ ’%i1[$CUUض==qQ0ÃÂ0 ضh4êþÜwö><òéG°\YÀ›ÁbYt]‡¢(X7¹7Ýtn¹åÄ2Þbóòùb±Âá0Ö`H’ôÜ,”büû•‚7ÃÄO‡7»F–ó*5³DCÑÙ8%Éä‹¿ÔY*üE¸"Û•HNØ3_ŸŠ,J_JKKËŒ’)DDDDDDDDDDDA%—¹ùægÑÝÝí®Ÿ¢ëÀ½÷¾€ÃûgD£Q791µg ‰DJ‰•ÖeòC–Ú8"A‰D‹Å`FÞó^ûÀµ¸»óî¼ÛdB&#»·ÿáÅ?¸³;2™ ,ËB4E2™„ªªxüÅÇñáþcý‡×O›¢i’ɤ·FŠ‚¼µVŠ¿(¹ŸIˆ$I±û¾Ûµ Û”‰”¦Ï<)FC~2ŶŴ¡—¢À£ŠxstXeˆ0ó¤ê*Ùl;vì@6›EKK ¢Ñ(G QÓpÑW?4|÷»wÀ¶m˜¦¨&ÿð_°ÚMnÜpñ PUÐê´É Û¶á8Ž»æÉW¿úU\Ôv^ñ»W@Ó4„Ãa÷~~guD ³$ƒL&ƒh4 UU§-ßÖÖ†cO=ø:ܪR£££îß-ˇŽüVï]-fvI0¸3cüå·*Í(‘’¨œ€©v=“b3OŠQ ÖeÊýÛq€t:?Y÷dÜí]ðË_âÈW¿zŸ‚Òªž¡ÒÛÛ‹‘‘ttt ›ÍbÓ¦MÈf³5Ý""""""""""¢z±,ñ_*A:= ‰DBL~H$Èd2î‚îpÞÔy¸mÍm0 º®cÏž=PU‘•Ðuáp§Mà¶—oÃm?» š¦!bxX,’J¥Ü5R^¾ÿe¼úÔWCÓ4´µµ!‹å%]R©R©~ÿûß{ ÞÓ3Éd«_Z-~ñ—á*E‡Hh”K€8¾¬Œ…ʳ@t”žyâ_%ŠÒ‹×&Y4ßójšxSäsÉÛþ')*Žƒ=Tý_¥ªf¨ŒŒŒ ›Íâ¶ÛnCKK‹ØG]Çàà »8=Q†˜Ü૞•Ƕx–eá°Ã¾†U«†°g˜ "g•ø×=YúìRœõ­³‰fÜ™$þuHÒrÅvà}ïÃÛ¶¿-÷<6ÞøÆ7Â0 üú׿ÆÞð„N ¡åâ\•¸ ¦iâÀD)1MÓ`š&,ËBf2ƒ/­û?ápèŠ=©?ÿz&•8ÉŠ›Â@ Ð ‰TÛÌ@$L :þÅæUkQ|Ý“ÂOTÜæ8lj+µÈöGÅÁÿè¯þ ¡ã¯bG«WuɯP(ä&S`ýúõ5Ý""""""šŽ(Õ.þIDDDÔd¬ ¥ªžxb'n¹åŸñ÷‡e­€mÿÀG`š&’Éä´Eä[>Ђ³Y“ÏŒ*M¶HD\•“J]]å“*¶->Û•¶5L³üßå~ùï'÷WÆd,&ÊåÙvéã4 “†‡+?'O±…Ûäí‘H¤Þ»GDD8¶-®2¹šÓ¦)þJyíáD¸å–×Ô{W‰ˆˆˆæeª*Ö.÷ûë¿~ ÿ÷·ãßÿýV¼øâñ¸âŠU3Ø(*—¿Êua<ýû§Ý¤ŒªªH&“ìÌm­·á¼©ó‡Fá8Âá04MCÑhznt¹¼ïm/ßVzp€W>þJï÷aq›eYÐuº®‹„Jxà„`Y¶}mÎ?íüiÉÓ4Ñ÷bb±LÓÄ÷?ø}ÜÓ{b±t]ÇÞö6¼õþû±'½HÀí¯q/¾ùE|ê¼OaÉu×áè3ÏÄçßñ¬[‰;~q†††Ä®:no»'tìÀg¾úUÜ~ð þç°êÑU¢ƒvÏ`xÿú×øÞ¿}_ë„ã8xã)§¸û8âŽk¯ëÍè:pNþ‹³ê'«püŠ,<¯«ï[]óÏPU-厎Î<©™Œ0 ‘4(‹‰ "yñSªÄ•eå_<ùû qeÛâyä¨6Mó¾d2`hÈÅfÞL‘¡¡éÓäR)qa‰ˆý–÷/üÎik·G£bßäly,rÖ‰ÜoÉ¿Ír†‡+/¸™LŠ× Ò "Z©T ¦i"²,¬ÍzÇãÐ4Ím $“IضíÖÇŒÇãØ³g;S¾ùÍoÖûpˆˆˆjβÄÀ£áa¯„—®{íY9»;“mòTÊ› ˆö¶iŠv¼lŸËÁ|oyË­VÌxŸˆˆˆˆ¬òˆ¾Æ¯}?Î<³û·+°sçNtu½¥fÏ•H$‡¡( ZolEÏ_öxk™”*ª‘îì¾³ì"îpèäCÞ/°ÿÔý°m;o}—/¾õ‹0{OÜ‹¡¡!,K,ÃûÞø>ühüGàö©Üü¦›qÓå7AÓ4œhŸˆ+ßz%þ¨üñxJWðóŸã‘7~wÞy'bf ápCCCbfŸLâr@”{ 8騣pÕà ,]Ç'݈¿³þ.ÿŠ,5qÁ‡.@vK–eáó¿ù ðÔæÖ¹ÐÑâ/i¤B$œ*-¡V||þ„?Õì=fPòKÊf³qK~µ··cÆ hii©éŽ‘ÐÝ-’ … ^RÄŸÌ(•`³?ä¿åÔ69íOnV¿eùÖJz³;Âaï¾r}Uó':d2F~9É1CCùI!9{E]×EÆÿüÀôDŒ,ÿUIµ U¯u4*ö]&<‰háD"÷ÄŸL&ÝQ–eAÓ4¬]»Ö­3*G:ø r”ˆ´Å=÷ÜSïÃ"""ªÙ~WUÑV–ë Èߺ.'‰„×n—3P ÉT…Î9ç^ü õ>T"""¢y¡ª¢Í”Ɉ™½ªúK|ùË¢᳟}ßôç«‘„Häú! ÀmÛuK…ýÙëþLü1’³OTU¹þ Dâ DbåØS…išÈd2kaüï§þé^òèè(Ýô(ÖŸ½ÃSÃb›°ô‘¥°rÓsb±’É$V+½¾8Q9I-é50U'üÙ øŒõ ÿj8¿D™L¨øûQµpæŽkpÏÊ•€3^ÍEQ_õ×GýïÿŠm›p°Ï£@¬[£KïZ œWúí9²Æ³¯g´(}?t]G?ÆÇÇ1>>Ž­[·â’K.™—^ƒR É;Ž˜}2:*.€lÛ›Š&g­èºHTø)Џ_,–»üüûï'¨÷Ï|I$¼\kDÖSV±?²Ä–ãx³T±]]ùû9<ìÍ`ñÇZ,&ž?™Ì?EI·ÜÝ͉Fűɑ}‰DéÙ>DT=Ó4‰DÜi«¶m#‘HL«å x¥¾üTUE8†ªªE:v“*…N1#"¢&eYâ¢?íz9HUEÛüÀ¯ý xmlYÊ«®¿!"""jv²m$»l;ãÐÔu}æ  bñwî¬ ÿâñr è:B$GL¸‹È—ßQ¸k£L£ËÏ[˲H$ð­}ßÂ9/œã–“V®\‰óÎ;ÏÝD5ìŸmÛyk°¸R¾çÎu÷mìÃ÷>ð½é}/*¼¤ ü>|&‚}—_Ž.¾Ø»Ý€HI%E©H Ãáaï>%/þÛŸzê)Üwß}Eïvë[n­âÅž™ª*ýýýĶmÛpÛm·a``¸í¶ÛFÑßßϤÊ,Èu= Éiú~ò¢G®+¢iÓï#œ” Ë*ž´‘ɘ={òG¬É2_€·`ûž=ÓŸ'÷4²î aˆ :ÿŒýf]‰ŠµkŶKÍ0™M"¸Väh?¹e1±B4ŽãÀ0 ·^h&“AWWb±lÛž¶¾‰išn£Å²¬¢ÉMÓ‡1<<\ïÃ#""šWþÓ¤m‹ö¼`å“{mrYÞ·Z…³ˆˆˆˆšm{åRãqà½ïýÕ´$D9V±N\¸ýöÛEù)Èd20 #¯_#£ý†v‘¤PQ¾T•,ºGé²_*H§ÓÐ4 Û¾¶ §~Zåp€åéåÞ¯²Ã¸p LüèºÛØ\µl–=ºlú6uä'TÎL{öàÀyçyÛ—Çå¿_ÅÉ’hÈý,±®¸Üæ{~/~wÆïpÇ wM†Ý{νxñø+¿63PÕ|—ññqìØ±»víBGGGÞßZZZ°yófb:“ü7UG–Ï*¤ª¥KyÅãÓ×,‘t]$?dy®TJÜ-•Í+à_ ]U«»ÐÒ4oÍÙ€ÂßåZ,££ÁZ«D–*|ººâ÷¿ë׿ˆW¼âHÜuתzï*Q`uww#Nömضí64Mƒ®ë0 º®#«_ØÝÝ{¶mCQ˜¦ ]×K/òV„ã8œBDDMŲDûZ–ÌöÊðf2Õ·íË™Á©–ˆˆˆ¨)Øv® äŠ ìßÿÝò •ÜRV…듸4àsK?‡í'lǬ¢(HŒrqKxåî_ræ €~ñ€×Ç‘€Xp¾À¢É(TU…mÛ8 GM¿Ÿ\k$ïE(Ø/`ú,0ÄZ(U,·à>‡™{­¾,žPî—ÿuBùe¿ŠÑÄPX_…GpŸs!T5Cedd¡PhZ2ÅoóæÍ˜œœÄÈÈÈ‚ìx£³mo!ô„JW——‘dl¯][:™"É™+ѨHˆÌä‚KÓòï_Me4Z|¶LaÒVÓª[$~!Åb1tww#“™žǣشéÕX·nyäÇî,˲`š&LÓDwww½hAƈmÛhkkC[[›;ë$‰¸ ÊÇãq·¬—®ë°m;/I¢ëz^Ù/Û¶Ý5Sfʲ¬üQDDD H®e(¯Ç›9-k}G£ù³Rˆˆˆˆ¨<¹>4à[ÞÕ2Âå:ZQb\-tßÎûðáW|/·¾Œ<ô˜¦Y|ÐgÞŒ“2ýþ/Þò¢H T³è:DÿJTvæ›õáß ùkøo÷“k·”IüäIúž'WÎÌ_…Äe›qRnfµo ™ríÞÜëxÁT¹£µQÕ •‰‰‰ª6 …ªº_6›uµ/|Œü[{{;ÚÛÛôÅXH²oR×ó†!… 5Û5“ƒxñTjø .ì.GÏ+Š‚H$‚p8Œt:L&ã–&’÷ ‡Ã…¢(8?áÆÿ„oû_09ùKbT¼mÛèêêª÷aÕL¹Øôÿ½Ùã“òe2D"LMM¹·Ù¶h4Šp8Œ®®.$“Iw ¹`¼®ën¢C×õ¼FJ8F"á 5MÓkÌPar¦Y1>‰‚mrrÓâ±I¥d2ÞÂð©”ø=×ÃÃÓgÈvµã¯d¥b`|Õã“(˜š­ßÖqD[Ë¿ô¯~õ+<üÓ‡¡]ZÝ”]MÓ¦õ;øË•í.´N§ñ•¯|o{ÛÛês°5T.6,ªø$q“q”Éd¦M›”kžÈ…Öd™.»`Êœ[¸î‰œú™H$ÜÒ`EG/Ti63[ ã“(øŒÜ°·¾¾>÷6Æ&•bÛâ ×€hç‡Ã^»¿”zµ±U±ØŸDAÀø$ žfì·5 ¯BP8,ÚYßúêí¸òЕثí-ÿà0J®õa¢Ñ(núÉMXÿšõø•ó+ü÷ƒÿ÷?ùþÊ;%“EÆ•¶?ü ‰_ܵL îdæþó÷Ë%¶íÔ¿?ÜUpG¸ø±‹Q’iŠ‘>ÃÃ@^Ò£\BESEgž¸}JÕÎzÑ!.•ʃØÑþÒë±Ì“ªJ~­_¿ãããeËyõ÷÷£½½½ì,•l6‹;vàºë®ÃÀÀLÓÄää$Ýmlß¾¸îºë°uëV7#ÚLb1ï³-×P‘‹"YVñ (¹žIÊe‰œybY"‘E®ën™"ÇqJ¥0::Z4«¼gÏÄãñ’É”¶¶Ûqß}-8üðÃsetŒŽŽ"ã¾ûî«÷áÏY¥ØO|.VŽã ‘HÀ0 X–…D"˲ ë:†‡‡§%Tü%¼’ɤûïÂûåD(0<<ì&nüõEªæe£`|Ûàà ¶lÙ‚;vLûc“2ÑÎïꥼb1ñSVö“—‰’Z¬Båc`|Õã“(˜š¥ßÖ_±Ü¶½¾Ö¿þë06ö øÎ£ßAûÅ툇+,’–>²4ïfÿú¯—_~9Ö¬Yxó_¿¹ªYîš#–>û,ž=üY:æqC·l¨¢î—Üæ&‰x/ÄjG48ýÂÀiÌèð'A C4NE$4äÓË$N)ÑÜ>$PžŽê^#bVO…."EQðñS?>«Á¹³UUB¥½½›7ovOx“““îß&''Ñßß;vLUP(›ÍN[‹eýúõ˜˜˜ÀÈÈZ[[Ý„LGG:::šnM™<ٳǻ-“ñ’,r„—J¥`Y–;’EêêêBww7b±†††ÇFÝKww·;ûDUÕ¼iyÕX³¦K–<ƒK/Ýå&¿d§ï9眃‡~¸Þ/Íœ”‹M‹&>#Û¶‘J¥ÐÕÕÇq`"‘TUE:†®ëîgÝ?û¤pM”bd¬•¢( Òé´[ZÓ[¹À|>Æ'Q°uvv¢§§gÚZƒŒÍÅ'“ —ôJ$Ä5©¢ˆRò?™Há‚ùS*6Æ'Q½1>‰‚©úmåšÕòߦ)«¨*ðÛß>…mÛNE&“ÁÛ}{Uë“âÀQ:*¯ÿžÊºK×ᘠmÛX½quéíúo×P4QpÚàÿ^qŒ¨Â‘Éánà’.Ñq\)a`šÀ 1à¹ÎåpX:”?r?‘º»ðÊ#þ ¿ýü7qÜ /än÷mDz¼ú²þDK¥×Kƒ˜)â»_ÑòìQTL’¸÷Ó+ß×ß7U©ŸªVª*ùxS0 Ãpg£LLL`rríííØ¾};Ö¯__v¡P(oËää$vïÞÍ›7c|||Zí½ÖÖÖŠ™Î½{÷¢·· ò‚Í•ãLŸ¦/Ë~9Nþg–ò†L&ã–rÇ]òÂ~¨þþ~\ýõ5oÛVPDÃ1bddccc¼`Ëf³èïﯺq¹{÷nô÷÷# ¡§§ýýýÓîSÍâF«W¯nˆ N9 ENé÷Ó4‘d)‹•œ‘bš&EÁè註ðµ\ÃAf…“E˜ )2]iÔ|920c1‘á^±bý³ÚVPÆ&€¢k(UŸ—]v/8ÂqtwwÃq AÓ4†d2™'rAùRÛ±®²€ûB”ï*–äéèèÀÀÀ€›ôlµŠÏ+V4Ĺ“šSOOÚÛÛ7š­Öf{îl”¶- ±˜Xÿж½Ÿ–åµ5  @"%1bp¢t‚l6¹¿åª]¼ÿMïÇ›w½û°¯Î;<¿Ø¶¥FÓ¬mÛbض¥FÓ¬mÛFí·µ,@}D¬©.צ·[8ÿüÓ‡‘H$pƵg÷¡øú$~ àOó'üúó¿Æ£z—^z©»Ö¬;Õ.ØN ÀŠ'ü·9ðÖQ±,@QpÇŸýÖÞùz/çÖ ç' Ô‚ý–ÓplˆÅáË­Á­iøð'bÇ ;°dåT~Quˆ6£ûw¹×kÓT²œü´mVSö+^Å}ʘ¯vÛŒ*ÐÒÒ‚õë×O›"ëìUÚÑÉÉIlÙ²ÙlÛ¶ms3DÅF&d³ÙÉ^.¹–O*5=q"/¶³L&Ó4ÇÝXÓ4ÝÛd²DQ·l—üœIç.àuðÎeô|:íÕÄvœÕh‚A|%chþølf‰DÂ]T>º3»äZBéÔÌd2n2²p‘ùRf“P™il.†aŒO¢ÆÃØl^™Œ,ÿ*Úð².w8ì­w˜N{íûo玴4á]twA,®ÚqñnØ‘lI‰gNÌ „&hÜ–Áø$ .Æ'Q}5z¿­eÉC@w¦p¹…Œ[Ò<âÜûÎ-»8ºã8°m+÷­ÄžÛ÷ çÏzpõ/¯ÆOúSÜtÓMØãßxábír!ùÂ®Ê ò¡÷' Ðu¬íîFêötÖBƒHÒÈî›DP 2&²ïEÍ=¯…Š3@ZîkAÛò¶Ê/jbN5mÚ]@Ó*Ñ"¯O©j •ZÚ´iÚÛÛašf^‡PGGÇ´ibUe;ƒ&•’íâw˳Rd €Â‹ªÅžLD§¯ü²¼²ãñ¸û…W¬cV×uX–5«y3}ŒV‹¦‰÷4î»ou½_¾š(›@sÅg³“ë †á&SöìÙƒááaD£Q7ff7Š¢ “É@Q„Ãáª%³‰Kÿš-3±Pu2ë…ñIÔx›ÍIÖåŽÇÅu¯ªŠDŠm{É`Ú÷rP¢dBÀaÛˆ‹óDÂ$q†å—†(Û`BÌXQr­÷«»pŸDÁÅø$ª¯Fî·µ,1˜]{; uæÏöÆN§ÓÞ»Ô¶,d2,]º§n:'NžˆááalݺuúÓÂÙ"aO>hE~Ï@Ô)³,wˆ¿ÿßKìTî§ãÿÔ \)~¿¤ï¾e’û.ßç-N¿ÒS¬‹‘û]ë5ßk86¶ÚÒôµ2ã*s188ˆÉÉI¬_¿>o*\{{;B¡»ÈQ(Âøø8²Ù,6lذ /È\ÉEü[×ÅEW2€©þu}]lwv :}»ºº ªª; EQ˜¦‰X.€e2¥Öf›|qgZG¯¦É„Êžo3HÊÅf3Åg³°,Ë©U¨«« š¦¹÷)¶ŠeYE?Ïåȸªúq‹aæÈB`|5&Æfã³,Ñ®—ë¤ÈÓ_8ìÍHÑuï¿yåŸu’‚¸°M@\¼Ë„ÈžÜ},ˆR DÂÄ_¯Û¿Ÿþ*ŸÍ=.aÆ'Qp1>‰ê§ÑûmS)1èE;ýw»\vZ…œIR„ªª¢ZŽ´©m€-úEŠö)Z¹í$}Ûí†h‡ù&7ˆ¶Ù72bÇ‘›ÉqZ‘RàÍ:QU ÀGÊTI垯LžaÿEû±ò'û€sºÇà®2•H’¹mÎÂl—]˜ Ye¡,hB%›Í"›ÍN«û¹yófôõõ¡¯¯[¶lAgg'ÆÆÆÐ×ׇ–––…ÜÅ9Ëd¼‹ªXL\lE£‹{¡y˲‹Å‡ÇÝßãñx^g¯išH¥RÐ4 ñx¼ªÄ‡L¸Ìt¤ýLGÀË/ÝÂÇ) pê©¿èu¥ØÐñÙ º»»ˆ“E4Í;¡†]×+–ñšËº&3}ìLï¯ëú¼$R㓨q16—m‹…LÃao‘ùîn/™ˆëÞ;˜u21ãÄ„WO:1³Ä¿€¨¼Èê"Çø$ .Æ'Q}4z¿­mçÚiˆöP®½$Ë}Ub­Y5G ç~¥—›-NÎ&ö·Å˜ždIè²€ïU(Çî/ç+eî/“)er¦iâÂåg¿¶?-ß°ÕrÛšaÛ²h"k,tÕ’ª*###Wšœœ¬¸|¥ôôô¸ ÜË‘·Æ0Äô2Uµ“c1ñûbâ8Ž;ú=‹¹‹e2ض Û¶‘L&§}™ùg«Ì4fœåÞž©+¯üÐàu¦+Å&ÐñÙÈÇA*•‚ªªH§ÓèêêB*%†ÈÚ2~æËLãr¶å»(㓨1[l“±ÙXäóŠ"Úôɤ[yŠ"I™¦;€pf³ÏÜ¥SXçÚ„(Õ%éá²L Jw(].§`(¹.㓨þŸDÁÒèý¶îØR ¢Ý¯,úèhAmS¢ U,Éx}“2!‘Ém³ÚñŸ2­â¾JuW gӘȟ…\HÎ()Ñ£( ,ËÂÒW/ÅÛîØ¼¡Šýô½®ÕšÉº½sµI•ª*ÙlãããïªÁÊÜA ÈjYV~9€Xlq”ùr'/¡!×m…eYî—V$¢(%³–¯3>íK± ;ÞÂ|iäøl$‰DŠ¢¸³OEA"‘1å"NdòR®‡2“uQfZ_RÓ´YÍYˆ„J8^ðz™AÄø$ &ÆfpÉÅä1ŲÄÈÆX,S)÷’)%ùG"ÊÅ;ÉÞb¢ò~òÂXޤ´à­k"›Ìòµù³Q4ßöhVŸDÁÅø$ ¦ Æ¦e‰’_CCIŒ\/•J!Oˆ-*þRZ9†aÀ4M1[.$/ÛmźEŠuG„!•*r·ß¿Ã%î§ܯ⋂’ UUaY.üó cªÜfrϽÀ’Édð*===èéé©Û‹Ò(,Ë— …¸@kö„Jww7ÇqGÅG"¨ªŠh4ê®›"U3+¤d= ™o³)F4S²®¤\,-“ÉÀ0 ·Tž?y(+‰D¦i"‰Ì(fš€PÅ}Π™Í÷Qw·˜ux£Ü ñÙptA”„I¼‹ô!ˆ ñŒï1iˆ Ódîö8ÄÌÓKK ³NˆˆˆˆŠÈd¼2È@ då¾ö)#“#¹$ígUU§÷aê(=;£X’ECõkÔ #?QRª»ÆHÒTÛ5…SéþqT·à|€Û¡ Ý'tx5wšœœ¬j†Êbgù¿'“ÞEZ³Éd2y¸‰D‘HétÚ2›E‡†‡‡¹µ¦iL¨Ð¼‹D"nmÏx<Žt: ÇqÜ5‡ŠQ¦iBÓ´i З#Kñ5;Ó ±&ŠO š7MÑ^—‹Ìû.Æg€XçD¸ˆO@\t¦!.²åEµL”è£ýõ¯åïQŸyÂÓ6Ñ4–%*y]"ª«âaÿþ ººº‹ÅÐÕÕ…LÆ7úEvŨí½bŒ“³_¤ÂÄF$’;x ¾›(܈cf%·d¨lgÎPU Ã0Ðßߟw[?²Ùl½÷?0ü%šmÛhkk+q¬‰TUE<G8†®ëE4…ªªÐ4mV%x‚˜L‘8žjÉqD"7N,Ë*32©‡‹nGÓ4wFKµ ~–‰ˆh1É-9†pèêÉ•LF$Tâq1£<™œa[>…ü™&)ˆDÉxåºtß2i"KF$á]  #°åˆˆˆˆ‚$•m»¡¡Üšê2á #_)ÝO"Ë‚©Àáwîöojš–¿îGÊ÷˜rãÆKµ#ýíÅDÁŽËÛþç•2ÛRrû-ËUÓv¿evµªJ~³cÇ„B¡@ÖÍ[h±˜¸ [Àuvæišîâ×rä»üò1 ¶m#“É N»·9¯( lÛnªYA-wDÇ0 †EQ`’É$R©4MC*•Ê;y«ªZ|zjfŠ5""¢Z°m±6Šãˆ„ ®[5MüMQrÞ3å@\ÀÆ .Œãȯ)Í&#Ѽ³m1Û8o©f™ôPõ"B)±Þ·wàË{€¦i0 £ür ò×Ë“J-¯£Ì¬ð¯ -“**ÊÏQ ÚŸaoÿgËqf¸Â<¹ªš¡B¥†á–HÌ}[õ–J¥‰DJ¥L&Çaš&b±2™ R©t]ÇððpÕ#áƒ<ㄨb± ÃÀðð0†††`º»»óÖ(™IrDÆ"gåëîÉÿE¶<]ªjÉ ù# q¡käþ‡˜•EñÅC‰ˆˆˆhÞ˜f‘ưë‚]@øÁC?¨ØW’H$pçä8ÿ„ó+¯ý¬!}Ë;aC ¸q‘å‰ÅDg±š{Œœ¥"Û‹rª´¿1†hcÚðf«#.ÌI8žÕR $Ìz† Š".Ò}p¸ã80 Ã]ôZUUüÿìÝ{|W7þO¯IhjgÒÒ¦“vÒôfS.ãÐRJéx›ÀÒ²yÌòÀCÂ’·–õ"Áïi€p“Àl ,HWÊ.,µòpÙ6áñK¡¢POé‚ÝÒ–Ì6! ´™ÚMÚ¤üûãÌ™ɲ%Û²5’?ï×˯IJ.3}5gÎ÷œïqk×®…a°, ªªÎhÍ…šj-¦iú3À‹ËÃu]hš6ë“ÙTë«-6ɤ¸®•%¼jjººÞZv›\%íý./ Ã`Y."š5×>©kY¢AUE¿›iŠr6DDдÉkWüƒxàS`ìcx×IïšúÁ6] ÿ«ïÿÐ^Ë "ÔtÄ(ª h:°Ì=âË]׃F¨ à# ©€©Š8Š2yÃuL^se*)ˆäËú¢5MÃàà ûmg‰3TæH®ÒŒ1äÈøžžtwwûëŸÈÑñªªâðáÃÈd2Èçó3 2MÓ8uŒb´Ã›ÞôU\ýmP¥´'à¯9³LfºXülÊÑY–5ãÇEY:-)¹œ˜E^S9^@Ä(¿ð¬ qÑœƒ1˜ƒ¸€NA¬Ò„m"Z8¶-’&RùR‰Ù¬H’ضø¾ÄwXO¸¯ãˆûÈebå©§Nkô®EF29ù¶»îº ð•ÿ÷¼òØ+k{" Ai.×_¼²Ï$ÜÝGPÉfEcS~ÁŸ£ŠÌ÷ð°hÊŽb À/lñ%.»at½òâ}r@O5*f¾@}ñxœ•…f©æ*ÅbqÒÂô{÷îE¡P(¹­¯¯¯Ñû´ d#§™fGY–…D"á'NdÙ!EQ¦œM"+œh©…|“Z™ãˆ  p>Cž{ãq@U]X–…ç<çmX³&L¦mÚç3kœ²)¹sÅ‘DDÔ*d»\ ”‘Sžê\ˆEF-ˆ‘‚Db¾D9/ù; œ'" I&ÅwÏаv- —>L&ÅàcÃIMmýáaqý ûéÒi • ~7 ñÿ¬·²\÷)“÷}ä‘5Þe"¢HÛ{ÿ^œõª³p›u®Š]…ÕX]ùŽª ü‡ w)Ä@€ëMuŽÇÅùð0VÄ`@|9? y-¹³o_™ªáùR°²ÕäLµK%\³¯¡jJ¨ttt £££££þm±X Åb±ÑÛß0²x½dÓ4aÛ6lÛ†ã8ÈårÈf³~Ù!™ð¨Ö±ªiÚ¬½f‡-5«JI 9‚Lž7MSœO Ctàd³¢çÖ[‡/ùÝøð‡¯Awwo|ãÅH§ƒÓ'(—)_ÃuÅsÿë¿þ–%î§ëâ®(ÁZe¶-.Êöí <”oW52.™ð$"¢VaY¥•J'•ÖB$Iò bæ‰<ßA$Ylp ù•\âqÑÖ–¥el;åºAWUÅc'¸6Ím9«»;(Ghšâùäã C¼V:-n+ÿSàÑGÏmôÛBD ×OðÐ=„ÄU lûÆ6|ë“ßíº ÷;þ¯ÿ€£Kbî]â†8#'Ú†@iÝX×_Ζ|Ûf¸±†¼ÛγPuy–wl 5%Tz{{ÑÛÛÛèmm¸ðšA²¥„Šã8~Ò#ŸÏ#NCQÄãq¤R)ضx<Žl6;ãi]Uf"j!®+’™ŒˆqYã8‘'l¹Æ˜,{Ùݬ£ôÓŸþ‡ÿ—\ò|íkxüñÿ‡Qrô¬¬…<<¼ÄãçøIË÷¯)_Ã0Ĺ\ÓÄö)Šø{¸s>/n Ïž î3ó¢ðëKå먙¦xÝðÅŸiŠ× wrɱ;ö5Ž<…;5ËKQ—°!$ ˆ}*^\ƒË’µŒJíW™ø×ñÙ¬øÉd‚ï@|§d2¢.ï/Ûï²­nšb@“¢ms¹öI*´‘å 'ÃÛ$/­MSÜ w Vê$4 àÎ;ïD°ª1µ:ÇŸÁVX·—¨ÞL³Ò XÝk»ÑñtTUÅ™ãgNJ¨˜¦‰kÎ<'žt)þ÷s³ÿó?qåÞ ÛÈ™Ë@pBˆ#è Êd€—(ÀïQú¼¦ˆps x´†AçŒõ¦ÀEég ›¡™Œè4ŒÒ:Цi"‘H —ËùI“T*×uýõäº ™LfV³Mfj¦ë@5Še&;b,K\ø¨j,‘¿g2ÁHà …{_Œ“NÇ;Þñ+?¾ÿò/›ñÝïÁ׿þ,z{ŸÆ§>4€s9ø³Ud¹ME3NäwŒ\—É4Åãl;ئdR\„ÉQr‰„¸=•Ï+/ØäÅ\øBRÖg^¹r¥¿ïk׊vBxv‹m‹ù~¸®¸ßÄÄä÷Mn$›Ã¯)Ë"f³Áw¦l‹LšQ#;»BÕd {yÝè@Œ,ŽÃo¼8 :ÞãØø "jyr PM Tœ‘"™3Odi/"jyù¼hîÛ'Ú”‰„h‹ªªh3ËA@Š”ÓJ¥Ä÷J¸ÜV<.¾sd»8‘¢TU|ÿÈ6¯h%ï§(“;ÀUµtaùð÷Vøÿ©Téú+’¢¿øÅ¦F¿µ´€äõ[¥ä Ñb”LŠïe9¸´¼ÛѲ,\pÁ8÷Œs‘ùÑ? Û€Û¶axÓ+?…O~kM0àTñîGq¼ŸL¦4{ã"Xo}:¦Ÿ|rQÛ‚óÔf”PéïïÇøø8¶oߎþþ~ìܹ³äï-½Ð±¬{*8FD.ÈlÛF:Æðð0’É$,Ëòg¥TÂD-V¦ÌŽq,gnjšý#Ö> F­ézPâOÓ‚!ãq ›ñ¦iÇÁ…~—^z1®¼X¾|9¾þuK—.Ôø•‰YM¯íºA£@–,‘iñxPfÀ¶Åí2±#âäkÈ‘u¶-þM$‚ßEì÷ë_1€`„že‰¿ËZó²“JþȤˆ,C&ÿöO¸^{ÂôFò½PÎâoϯüÈ~H…FmX»! ‡Åïé4à˜À  ¿>iw7°¯ PC_Ykc€±Æ{.„fÅhÞs{_{ö&@[<÷ñç6úcGDDu"×)€Ã‡ƒóqʼn—2/Ï!q,¾AݲáSm˜âÉÞ:jr=¥|^$/äŒ9 IÎþ6M1`hp0hßË2¾==AØ„g{Ër½2T¡•™E-û©BNQ¦ø^£EǶƒ5vØC‹«(S—û², ÿú¿þ ®‹N¾®ëXrñ’Òê D[ÑD€q¼ÇgÊ^, 3[ÇÄ@°ð=5½k½ã¶mÛ000€ŽŽÿ¶X,˲°eËttt`ÇŽÞŸyáº" šJ¥w¢’L€t:\.MÓÉd iڔɔ…¤( “7Ôpò¤+'²o!™¿Ëáò^á‹›LFü”κp°mÛmpûö탦i0 øÀ•~­dE^üâ«°jÕªŠÛ•ö-sœ "GÚÊd…¬¯ oá{Eñfu8uàC~úJ@ÿ`'(õ¥(@êù€Þ”ûÒ4`õÊãt?‘4|€Ýâ"3Ÿû©æƒdK&$Þ¬<-(ªüÐÿ ˜y‘üpѾÈüUð\š à`ÝÔÞ÷I ݸßûj8°½õâ\HmÒ/ûï|_<ü<À=p® Ö¤q]ÀùwÀùAðÞ&ÿ/ßœË:ÓDD‘aÏrTžiŠïv9Ažû Pl§Ä¢ +½5ˆ_:DÂ}1uPÊ7¬–õ MS4ˆäH¢™êã'cßqÄÏÚµÁG\þ_’ 9»\&ae¥ÃfšËÛå,7Ù¯¦ë•óšVe6Üøë¿þlc7€T&T˜í9”¨UÈr‹á>”0Çqàº.ιäœÒÊqøI×u‘Ëå`š&.¹xò‹è˜<‹¤Rò[ñî+ç¨\J¶\„ú’injš¡2::ŠìÞ½%ëèè@__ÚÛÛqà 7`÷îÝÞ§º“µ™Ã¬^k=‘HÀ¶mär98Žã'.t]Lƒë®P£9Np&ŒŒÇEŸ,ãÕÓÌZ‘‹À‡KQÉ2Vù³Ñï5¬¥ïííÅøøxÉm«éñããã+)!ÅbÅb“þÖ(r]€Fq¦iÂqX–EQ044EQ`†øÂ ª“©bˆf|V"KÈ™š&ú!dË‘ €¸JrÄ+Œdݾý‹°mÀ§a7BQVLùÚñ8 Pï´ue _CüÍÿ>Y ( ʉ*Kígâ~ò¹ ñ6o‘;q’w嘷?®¸ßЕ€²®ì5Ó€ò߀9 .Ðýªðƒ__ôëÈױ܀~†ø]7¼úô†÷š:ÐtÀy P.Ûáœí%~\5D‡ìzÀ}Bó¤ê¼¶÷“hcN·Äœ A 0Z4jJ¨´··OJ””ÍøøøŒf§ä½Ô{__ŸÛÀÀúûûÑÕÕ…‘‘ôõõ¡···ÑïQC*Žã §§š¦Á¶md2¨ªêgSsáÚDDuP)6èÆ§äºbD¼`3Œà¤[¾€dø,^‚Niì×cاïÃÏV|Žs=V­ÚµRˆ7@T.ˆ€8Éà&Ä 9zܸ¯jÁïÊ\àbïþ^^R]e¯”÷‰ýÎé4@½À\…`&KP7ÆeÀVËŽwÂýFh[¼‘¾ÖÿÔsõ5b&‰Z@éèŽ8 ¤Ü¯ ÊÊíÞ6[£ƒ@=ä¸I<4÷Uoÿ-””`Ñ/ÔSÄcÓ@âS@ü:oûåÅôKë> ÷!ï-H®(·J; l·«ÿ‰x.M¾ùÜ}.\ÏàBhÖø$Z¬úûû±wïÞ’ÛvíÚ…X,ÖèM[pù|°žW¸ƒSÎH‘çKùûЛ!Î ÄyÄ8oFùbµ§§tˆ¼m‰9ì¸R IQ¼ÚžeKGh¨*¬\v>/:4 ÈfaZ–_ 8‘H Ãq¨^‚%•Jù3Û Ã@6›E*•ŠÄÚ‹Àø¬/× ÖÊËd‚»†!r‰rSx†IX¸³8ÜÜ./qÄÉâ°XâÓ²ÄgZ–YŽÇƒäc¸DÀ’_´ð¢Ôo^Óvêû8¢¯´BÿíÒŸ-ÅÍCÙàD4Uù|mmmUOp( Ø»w/¶lÙRò·þþ~ìØ±±X £££Ø¸q#b±XCGÚ¦Ó `š&Òé42™ âñ8lÛælš7ÓÅ&Íø 3Í`ªÿи`Ëfƒ“n­5Ûƒ5P\|ÿµßÇßžø·ÈårèéV¯>.F¤tèx3;JX39ÚCýrV‰¬ß©A$7r'koƆq£x,,µàe Ð,‚“»7ZB{Ø{þðl“nïïò»KÔ%€ª{¯÷q@S€1V þ@}€K¸âmgÞ{þxð† äG<îm£\ø×“9ȼ1ØwMóž#_z¿Ô½ÿxêK¼û•}÷f²€òþÐkÀ`_€x ÿ½÷þ»À£-²(}³Ç'Ñb5>>Þ’@³áºÁ,•pµÚ¤7ø@–úw†8çÅ!ÎC‚sgôô ‹p©- ´¶:Qš¦xŒì“=̲ÇL.Xæ¿_®XߤÂ0Ì|>|>MÓÐÝÝ-p³Y躎t:ÁÁÁi¯TU]ô³ŸS3Í ^}¹dR$CdÅ9™ǃ]Ù¬hçóÁ‚ïªZšPåe-M§ÕãS& ]7HžÈÓŠü—3R¨Q¢Öo[iúr²-@ô³„Ö3q+V¬>mf¨v€‰)žpb}ØZò¤ Ú®j ÷¥–QSB¥££[¶lÁÖ­[±eËôööúÁ"¬ÀŽ;ª>WWW:::&Mß, hoo÷O˜èììD¡Phè([¹ÐÝB²m–eÁ4M ù_ L¦Ð|š*6èÆ§$€ærABÄŸRó“xÿj"‰nSnCÛ¿µASŽüŒ³€vˆ«ü^°ÄcJ*s@æ'¡ÛC“¥¬äú%áÑIÃ(rê¨1:7l' ?t€CÞï DTyÇ“LàÐc€%|9¥÷‹ÿÀ?ŸeÕû{"ã½& ”64ïï¡çÊ.웡¿ ݯB¢$<òjº†’ñþê‡1<’KQ€®®[\Rý×ÌñI´˜ lß¾½Ñ› ŽSÚ9äº@2!þC¬.ÄÀy.”æ«,W²žnä…¬¿bÁÔÖdR4@µC+­„LŠ/V,ŸÃuKËyy²Ù,òù<†††`Y,oöI<‡eY~ùßàýu*Ï¢¥)1>+ËfE¼Z^ùY9*¸§Gü«ëâÿ@0¡Jæåz…rqùò„ g—P­Z=>³Ù`K~uSÔD­ß6\Ud*¦iVì3õ- €žLiÛ²Ú9IÎ’®e"o—‰ Æ¨y •¾¾>´··#ŸÏcçÎ%ëèè¨yô€\ؾ½½½äöÑÑÑIÍöööŠGaû÷ïÇæÍ›±k×®º¿9®»ð‹Ñ;ŽƒD"MÓ&](QôlÞ¼û÷ïo‰‘3SÅ&0ûø¼õÖ[L.OT/®+~ÒiÑ wÔTÁ0I"¹°H$øýV}5`Š&Š·¯=ëÀjˆÎoÍ¢“džH€Èï О-{~Yª$`ñ\x·ÉY%Zè¶$ü™+€÷ÿ4&Õ×Ë“')ˆ™4r­’ð6*€r€“-áís8ÁÇäÑqLm!“*aeï¹r€e˜Q'˜¼Ÿ«ÑÑQô÷÷㤓ø§¹?aƒÕ;>:„Í›7cýúõLºÐ‚“q.¸à‚Foʼ’k nÛ¶ …Bmmm5•E˜Ï¶m#Évu6+ò¹z0¾‡` \ØS:¨§tZô^…{®ä Àå³Jdop.¬‚ªiA½•LFÜG–Û*%Ö´©¢O¥Äc¼ç6M®ëúƒªä ’t: ]בÉdà8ÇÁp…²`õJ¦´RÛv:³ÏùnÛ6R:-rI<.&R)JÐñ+C¥Ï>ûì–묥æ!g:‡Û“­¨X,"‹aË–-صk …¶nÝŠŽŽŽiôóÕ¶m¤l6˜¼¡i^¥«,€m·û üiLž™2×Ö4Ñ Pñ»\Ä]®k"‡ÜâŠ]Nu” Ù&—=ÍR­µX+?v]Ù|ŽãÀ¶mm]×K:â¡×YˆÙê‹¥m;Ûøœï¶í|‘“¨4Müß4Åÿãqr†‰LœTR/4{‹©m;›øŒrÛÖ²‚Òxš&)³7Û¨u}©ºÅÒ¶mD¿­mO?;%›ÍÂ0 (ŠR±dÛvЖ’%d-@ª5­”W§¦4_í¶%T¤ù±TiÔm±X¬K²f6 cò ¶z3½ÑoŽãÀ4M?kºX†¤èŠZ|Jr\w÷,œ€HŒ(@OO>þŠcøøæy×`cn£8Ñz Â# \|ñÅxÉ+—ïAÐé#K~ÅQº`™Lœ”Ÿ¨åmáP×½çÌ!˜ ’ÃäÅÍÊÒ²¶|y"§Òw—w!¬¸€=† a4_ΙûS°„IuQO¢ÅNv~I±X 6l@¡PhùÑÿ€¸–%9­=@Ê+G—%6³‡ bò„™k˜8NЈ×u1Ä>—Y9ÜÞ_Œ´lhb¥Õ~ý^³i£klÛ†iš~9 Û¶¡ª*4Mƒa~2…ÎbˆOYÍNÓDÅ0ÄïŽ|¬åšFª*~Xa𢠕â3Ÿ?™L_³-BÒÝ LLÌî±DõЈëNUºùåº.LÓÄððpiu(žRÄ—Ò_‚®ëÐä´0U},Y<ªáy‘¦0«„Ê|èììÄÀÀ@Émccc YP·–RÊs%œWº®#—Ë!‘HË|QäD)>¥t:øwÆ£uÒÁ“É$^ÿÊ×cÃ%°AÛ f{È’^r1xøÁg–"˜5"“'Þ߈“­\L~AY¬ò¤ˆIk—ø ݇ûTÊ×W™Ê ÷?¼ÎÈ|Ò·j•¤ŠeY°mÛO$;Þð­|>UUaÛ6r¹loh¥L>k^y]×KFï.FQŒOª£òÙpÔ4ŠÅ"ÆÇÇK.2ÛÚÚ½Yóʲĵj2)~—•²r!˜™©AœëêÙ)”Í+–ºn0"JÓDƒ>™C‚ç±qïz³Wò^bÇq¿„—¢(0 ƒƒƒ°, ©TŠk#6X«Æ§œ‰"Œ—´ crÛO† G½SÔ4k|º®ˆ«x<˜•b¢3¸ysŽ1£F[èëNÛca¦*÷•N§Ç'õ¡îÿÉ~¼ïëïÃ?õöV>Ùeö6R‹ˆLB%‹allÌu0::Šb±ˆ 6,Ø6ÈÒÊÙìü®bY²ÙlÉ‚ó§èŠB|JrÝÓ}#‰D0…zJY”®bÅÿ]ÄÁsâO/ùrÿ;Ôl—±/›‡¸Miði‹±Ëä‰|,>ŸË¤Š[v[yŸŽ\|~ÈÅEëI޶µ, š¦Áqäóy "ŸÏCÓ4¿¡#K& ?‘’ö2d¦iú¢x<Ã0ÐÝÝíÞ5 ªª"™LB×u¸®‹žžd¼RxÔïb¥øœ7á2wQ'c=ü=ÇäYdr=¤p,†fÎß1 ˆ­z®¼w›z.â{EÞÏô¶¥üuË4•¶ê¢P(`çÎØ½{7ÚÚÚ0>>޽{÷bË–-Þ´y‘ÍŠ _õ9À7k3½ PÎÔƒ(ë5¶-F8UªéY^ÿAUÅì’J£äýêxò“¥zåBñ€hß»®ë–’ÉþòzÞ‹éüe­Ÿù|Ð6–k¹nå WašÆµNfMÖL«ôîLY+¹fÕ¤ãÓuEÕHÃÿwÑ«(õ›ùÅB&Ôh yÝ麢¯gª±0ù|®ë"W¡øäè“0â^wãë¼…ûÊî“‚HK4‘I¨¢®ÙÖ­[ÑÕÕ…‘‘ôõõ-èHË J#ÏÇÌ{¹d6›E&“™TƆXeŽO)›Žr¤]Õd :“(YtìíŸx;2oÊàÿ*ÿ7(ÛˆNÛµ(] ^¿þˆŸôˆ#HÔ„Uå±ÑDºŒ\¬•mÛþwTww7R©òù<2™ Òé44Mƒëº°m™LÆŸa’ÍfýK6›E.—ó“#²“I×uÿùu]÷GïJCCC“F„N®ë"‘H CUUäóyÄãqVËb•øœ2©0ŒÆO¹vPÏáÙlR"±:Tv›ñ}Þ‡DDõãB$GäÇÛ†øÎIzû/·Aóž3º_&´=Š÷wÕ»¿¼_OhÛ4ßvè5 La=¿»Â‰›•ÀÒüÒºš(êííÅèè(6nÜˆŽŽŒŒŒ ··7’‹åΕì[L¥œC“@FX{¬–N[9 1Ü©(¢®ëâä/ˆW”ÒáŠÕ:*ç<5S–ì’IÇq iš¾Ñuš¦AÓ4–ªlÍŸr&˜ì´••­µ$J½¼ ~€IDATm¥9Yól6ß ‰DPC-œ±’BUƒiB¦YúýW_  Ë[àFQضG}´Ñïà¼k¦øtÑ_+(òt4?ýIÞ[¢…»î´,OS}eú—CøÊ†¯LºÝu] Æ[nx‹Ç©9”T.!š©†%T*-HÔÛÛ‹X,†b±ˆŽŽŽ-W"¢ÉäüdþmÛö;üt]¯X+™k§PLµXX#ãS’uŸ3™àBÑqªô£¤!:$5`äû#øFáxýÿz=Ü.´ŒÌ()/µ^_Ä…¸_ùëäÐøÞYªÔדÏça\×E2™D.—COO ÃðÍuÃÃÃÞsˆ™ ¹\nRç‘®ëpÉdÒÿn›®4—LÖTú~¬V1•J•|Þ‡CUU|úÓŸnô[]WQŽÏºéFilÉY^Y”Îì’³Èæ£–L4”ϱ F4ÉÛlLžA÷~ò³r%™’É"É!;”5}{¼ç4B¯m"H¼ zÏ);®e²& ñ'ÃaÁBß)ï5†$^äþhJ*J3é(M‡J²¼¡\J÷^G®#å„¶_~‡&½¿@ûíXº¼õ“*Û·oÇèè¨_¡©c³œ×±Óý@ír—Açı—¥1³˜~vŠëŠ«ælVŒ Ôu1m|x8HžÁº(³é­!Áá8EñG<¦R)¤Ói?qbY–ŸÌÏçóþ¹×@iRÍŸÝÝÁ‚r×ð0KM«|6‰·Žé¤‹þ|>øîQUq‘!ëJª*¾«öí+ý.’÷—âôÃ(mÿ¦Ópr9¿]íº.òùm;…—J•žX«Æ¬ ¿SO¹DÞ<ó÷Ï þñxÐq(*òy ˆŽO¹X®qU”F0Jˆ~2%Æ#mm¸ûòËýd‰¦iX»v-2™ º»Eé-9;Äqtwwû³H\×E&“™²£H~ŸM5WUU -ÔFŠ¢àþûïoØë/´(_lÖLή‰¢Ó6ƒ‚ä§L–ÖÒv̺Ç­`¦™ìü•÷· ¾ÂeÉ9 $… 1«"˜Mb#HÉY(ï6ù}#K~Y¾«r:&Ä÷,'˜@iBgØÛ9»D&GdR¡ç—ßsš÷¼=(]»Éõ¶-î=ŸÚ™HI{Ï„¶9îÝ.לB0ëEE0cgŸ÷ür¦J8ûgÏÓ)Zæs¡Î†qk3½З™¸¥IHoFè6Ó ŠÊËÎHÇ'úL&A(ë\—'O꘸%»ä “D"UUýsZww7 Ã@&“ñg_J•ÊKPsj†ø´,"Žã÷Õ×®\ÿdò»%ß%òÍ“SµÃeM3(1˜LŠrÇ÷ ·e3¸rÝ?¯ýœÏçá8R¹œHÈzIY˲ ëº_Ö¾õÈ#xw"QR wxxØŸ…"+ÉÇì«°pÀæÍ›ýÎ.˜¨Çg¸Â Ñb²×rM9×uñ؇û®ð&Õ41=ŸÏ#wbN\¿pÀ Í£È%TÁ²Dí|,ÔlYÒé42™ “)D³àºâº&“©|Ñ(Ëè²CPvކg—¨@6›ÅkÏ{-2JΕ.5.×0¹tWÁpiª5Nd¶§'ëð—ÑtoHhÁÝl6 Ã0õjx©ª Çq ª*Žã¸bõjäï¾™LÆ¿ÏÐОúæ71<< ÇqüQqñxÜ¡[’,1ÍàJ^o£mW¶-®ðå"9òXö¸ni™ÛæÉÁÊòùåUÊTïI:¼ÿŠRrÛZ*M)W†Wã7€³Ð2Ê]É$JÊ»¿…`æ‡ÒÙ*‚Ù².îDò@–¿J"˜ "›÷þ?zœœ%#(2±#“0™Ðm€˜-Rž˜•Oy?r-'3ô8™ÐH"øŽQ¼ç|5ˆJ¸Üƒ¼_˜ŽÉßU2I.Y(/>â¡çý_>. Ù3 ‘‚Qùk+Þûhyïi&ôº9øÉC×ÂþÂþ9}|¨ÀNÙ?™[€Œ7ð»¤tf¹ð×·ìØ´í (¶¦Õ¯À|r¯l6ë/ŸÍfáºî´Ÿ8…AöñËf΢.f°v­Hˆ(ŠxCdý_Ó Úœ2a+ߨ¼7õ²|ô•¦Ó{äÅ…·“ ÀÕ4˜Ù,t]Ǫ \r _ø‚Ÿôë%É™$®ë"cíÚµˆÇã~{Zd’lÛÆ¥ÿøþÜç&}çe5Ú˜´.Ç *¿Ùö"K¢yÔÓSy1úÚ ã)+Þµ"|çU 8áG?Bß‹_ Üd¯”£ÝˆæÇ¢O¨Èš—S-t4étÚѶ.ÄdMiIvôÊÛäElyùÛ¶¡(Š_—Z’Ó£åº r„\³A–b/`-×NS§e٢𚠮ëúÛ&ÂÕJ Qã¤Ó¢~ª*”GpB•£¨]‹¦iâúë¯nÔœêÍNÉ)£´T*¯N%×(¨´ºl œ‹=ÓΡžž “IUÅžw‘vÛõ×ãe'ŸŒûøeËð—ú'¨ª ×uñ…} ï|øaœ{ç8pãX-/Ê X»;Þû^œ£ªââ,›Åñ{ïų7ß \tÔpí4ÇšN‹Ç…/ìdÉM ê"†ˆ, ëâ`… üÊ‹[]¯¼°°¦#år˜e‰÷XUƒBªá/ìLF¼wéôÂÍ·§ª’Éàã %.Ô+¬JŠ+?âwÊe@b 0¸ 0ïªñ³ýó€ú|À}p-@y€Ìw8pWî­@&¸ï²Oî³V‹ŸÌjÀ~`> hò#Û8ȪÄU á}d‡U ±pð)ÀÙd.œWöFÜ›ìbh&NšÀ=Ï;†¯|å0>óÜ•˜¸eïþá /{ÚÚÚà8ÀSKžBïþñì?<‹Ïþb¬Xq×\³ß[ö?qìØ2ÀªUpÍ5»ñÛ×ãyÏ;†ç?ÿ4ŒŒ,ÁË^ö8λw?üaž|òI\yåüô§Á¢>x>®¼rz>~x5.ºè·xùËÏÂ]w­DGÇ8räBœwÞÎ9çIÀmèí}<°'©ë ë€žN_éTh tý 9ûF-»O9™SËnÓÅWÂw¶ãÉ'[¿äWËp÷nÀýø-û†×?9“Ž$Ùѹ€ 3Ë6Ÿ-.gŸhšæ—쒣ȉ)å¬ú—Á;4 ¶m‹„­mã‘_ý g~øÃÀ§>…ÕåÛ㜿ú«’ß—äóÀ=÷”îóÚµb›Ë“)åïO¥aXåS‡Â_¨µ¬Š*)ÊäçÇ«w¾år%³v¨qÒiqøeÙq9¹ Rm€õúŠ—;Û¸o²£€ú@üoõ@æ@&.úT¬›ýÀyp¼Ùhê[í€òYïEßdM@;9 ÀkE]òÛo¿ÿ`ÕÄëÐùêlûhk» <ò,Ž9‚uëÖáÁÓü½ÿËfÕ篆ò¼Ÿyë&(0ŸÖ=º—wþá~Ž‹/~°ü%Ëqú3§ã„eñÅ/ËN´·hø-€5k¸®ë-÷ àä6'C|¼å¹å︽ìÝ»×_?Ž×¼æìÛ÷Wøæ7 °½7ïÚkáŸßb±‡ê«?à‡òÎu_ÂÄĵ½gŸ}\÷\†ûî»K—À =zÇÿÇ_‹%K¾“O~ccïÄêÕ,[v>xÚÚÚ (Àš5àÙg¿Œ?üá½8å”#ؾýùxî¬xüåºïÿ Ü}÷8–,YÅ:;âk_ÛýûÏÄù矈“Nº¿ùÍ\s ;•"//~Üå@Ï€» È™³œ”©ª3;'ÔÈq8Žã¯E yçHÇKîÇãqhš]×+®åÅd EAOÙ„”UðZ†epd{mp°tQÙôfT#“ ¦ªçrA{Ð0‚ZÝ€ÿpê©§B½é&|ó©§JëÉY$‰D¿Vü§O} €øò×FªtüŠ)v+<³¤¦YÑñ8Û«MFV~‹ÇÅežªNm:ŸdHp,(µº©ú€Òé4n|Á“s™Š‰+^v^xàû@*|Àµ¬TAókQ'Td»®ž'D¹˜³ã8 ]; <[D&2Â¥R©òù`ý9 GÎÉy‹åÉ‹PÇqüY!@0²OQ?e‡uyIÞ.kOËß«L 2j¸è– WyßðÂÖ’¢(þßå…´ü»Ü&¹r³Ù¬_: Ê(ÉÒH,#´p*ÆçZø Ü* €° ¢ŒŽ—øÈÎá%/y ®¸ö \‘¹BÜÙ4;d†€´tÄâʵ§Gü_ÓÄEž¢£â*u¸$¥CÃÿétéô7MÃS‡á¾K/ÅžU«0¡(pC³ØöíÛÓ4ñõ‘†§—/‡eY0ʳ„|:‘d„aàÌéZÖåWãröKùmûö5ï^¥íN§ÓĹ¯½ÜJ,+€®ë€û! ûf@9ëÒ4os%¤^ QþI†,™å}”S²DV7€¥¯å^éú¦ûöMàx ²ö•â¼÷=çœ#žÈý«oãotÑÞêψšyî¤}Q”XÅïùOែ_¼Y]¾)ÊõÉdx­"EQüó‹\”VQX–…«¯~;n»í‡°íßû߉DÂïì1  ¯þº Jض¿öYûó'±téR\¸âBŸ=Çßñ6ØöOàº.^ÜÖ†+¾ñ ¬~ÿûñÈß‹Sßû^<ÐÖ U]Ç9'ý»pñI_ÃÑ£G1|ø"|㉷â¾û|õ«'âÀ%øÌ–Á|ÏC8õðaœöÌ3¸kâ¥x™ná¦_¾§œr§žzþîèÐõä9xò„ð••kñì³?ÄúõÏÅyç­ÄÁƒ÷à’¥Kñ’kWáÉ¥œ¡5Ž('J°oÌ¿ŒAqº32€zÆ N®+z¡æ!‘"ÊÈ5ò<)GŸgZª'šZ•LB¢IÚÓ#š•á‰ÏMɶÅù°|}M+mƒÊÙÏ’lïêzðXE†ã8È&“þàż¨ªjÉ¿MÃ>ó<|íµþÀ»ð »°òkÍùøÞç~_…¶…,ÕK KVZÎfƒ$Eùš étPõ˜¼–çB“°šúû¨ŠJËWA¹ÅÕ·¯nô4ŸÏCÔÅudÒÞßè½ Å`Q'T²ÙúŽü1MÓŸñP-YPO²SF–ÔJ&“0 Ã_hS–»’ÓýQ:ü„Šì ,Y{@66eÒ¡•Gò•'ZÂäŒ˲ü޼x<Ž[o½±X¬Ñ›ÞRG\Tf2:näâÈIq Õ (üæ8H'ÒP=îªyOHˆ®®‹ »òM F»ÉV³\ÌR®ó¡("A"7êðá)÷ÁŽÇÅì©|ÞŸEåžz*R×]‡z£geÉ.y%ë."‰Ws¬Õc˜R«]Èe2@<ŽËÑÂ&˙ˣ2 }P®ñnKC$<åz&å“äú%¡$jÞÊÃ1ñXÀŸ™%Ë<À]wÙpÝ0 £r"^.´äHõÉ5db$tíº.nÛ¶ ¯:tÇ œüÐCøÉ›ÞÕŒ‰Çqhófò¿ÃǶm¼øÙgqñ¿ˆÓO?Ý/y V> úÁ+r9¬Ìﮪú6®YƒŽ·¿·?Ž%É$®üÓŸpüÍo†ê}߆!Ä5×®‹ýããø3€{ß5²œÉWÿú¯‘Þ¾O?¿xàÒµ“úúð3ÀoC,ËçÑÞþ2üò—b&§µLÁòãã–ûÿÿë=ïÁÝßü.¸îµPÿœ@"‘Àž=¿Æ‡^ö2ôÞuþmõj¼îÃÃû~{ô(EÁ‹Ÿ]‡üò—xô⋱çé§ý±¥Ûoð40ø6 ±È\-â·¦Ùܲd¥¢¥{ägÒ_ìlfLÓô×:‘ÿ†gžÈS¢fcÛ¢9*— j¢±-‰„ˆsÇ)]7ñr®‹/òuL<Å÷¼ŽëâRo`\ßHÎ4àJÈd2þ YÚuݪ!â;"¼Máßå€F¹ÖŠì”¿Ë}–çpY®:|­.ŸOV] ™ ÏšN¥Äeª–žšä`[9Y>‘ïJè…c:i10+̈́ΦmŠkµd7L"ß½ð… ’æÄõfý'E•8abbb¢Ñ1›7oÆ®]»fõXÓ¬OgÛ¶‘N§ýΊT*5okrÈŽ$YÞ@6ªt]/¡×2k‚”/ø]>_–g’¥—Ê¿yåš ®¬ãPÞè—úª,¨nxˆk…ƸmÛøô§?|àLª”) ( èëë«ù1r”žÌw”N¹ÀñDý~ è UÄß{ãoñçñx|rǪì4KBpªr`f§¥R)X–U2»IÓ4–k¹œ#ZY½ß—tÚ+¡  ›ªVáÇﯾü+¼è“/Â’mKüõ‹,Ë‚eY8úÛ£øÅ¡_€ßÁ/;LdçBùùͲ,$“É ¬ 6fíZ@Q0~ùåh{ä •‚ëu`œ86†S^ûZœuá…xôÜsñÇK.AjhÈ/ý¨ë::¾ô%Œq¾vÒIþírV§¬›nƤ¸–ɉn¾—ïÞ|oxë"…6<èRÕÒ¿…ß/Ž#ž¯!ÛsXá—_}ò“¸í·¿Ñ9b±Xï-þ¹Ô9 ȧó¾zµ_„ʲ„æÐÐŒ{|dÇ£Œ«p /UUýÙÑáŽJ …Úº L wPËï-™ôýò—¿ŒO|âlÛ–™MÛ¶YiFàFb¼š\·.œ ³Ìt]üMÎî–Ãû{zJÏWk׊Þg¯@$×')/Ñ'“'ò<¯iš˜m’ÉøÉÔz¬y)e†Q2+¤»»©TÊ_Lí÷t:]’Ä•ƒ9äÊð¬WÓ4ýRb’¢(H¥RHz3kø¯--˜¦éß&gÑÈ÷&—ËùeÄø÷ÃøÃFZ"§Ò¹ÓuÅÇV.¿3Ýì/9†N.ócš•Än¤Y4ÝhÕëÑŠfÒ¶M$¼Ù`.ĵb@X«®×{=]qGMCwD—Z héïïG,«kÛvÑÎP‘}ìseÛ¶¿þ†,5²Tl$ÊY!²á˜Ïçý†dx!MyÑSKY¬Y“«O÷wÙ:‘#Ãd"B.2—^dËéßÁ›)Fÿ‡_Ó²Jg”/fšÏ‹y›eM^Ä0œ‘Åü%YÊIÖª©$ŸÒärjº÷zš¦áå/ùüƒE&‘‡kÒTæü6‡L:Ëòrm¹Î¡õžN§ýÎ[ ˜]/gÇÉîK/½´ÑoCK’¶Ž#&9‡›©‘Í–ÖÚ•ƒ‘䵘<ï)ŠŽt‡‡ýëUpTËî¹£‰„ŸL‘Ÿåp²AÎ0›JxvF¥$~¸”–L|Èä«ð ÿ&cB^CËõ>å÷Ïàà ÇAOO_[Þ7ܦÏzk»ÈköpÉM¹~§¾^íÅD¡нÛäs—Çy<ÇÚµ¢óP®M*:›9ûº&r\¦œ U¦‰K~™L©ÇÀÛzËç[ $ Ñ4äiGs!* ȯîx5þù†wÊÀ¯<’vÝ­D¶(*rÒÂ\ã®Ç[oapp°æÎSÇqL&ýšèƒƒƒþˆ˲ü‘±rг\¨½j⤼³IÖ­–rdQø"TÎk•ëDx%rJþžN#hC£J$“A/xøï^g3¼Ž.Øöä:¹š6}§Žœ_;ÕÌ€LfúºmåÛ[Þú •éZ%ò5ä,˜0×Eû£‚æ&¼A¸l²ø#ÄÉÔ€8¡†âÇx¾†lw7.úµw¼åpùòÚ̳$/Ìòù|É:òbªÒ…"Ñb‘NêÝ€òDL¦Å¿;~¾ˬe8ñ²±îŸ×á7Åß@ߦûù|×i×á‹z…Š"ŠW^.Ä;~íÝïÆ‡o» × àCŸùŒ_J#“É”tPÈÎY¾òÅW]Ur{¥5¸¢Õ¯”e;£Phô–,:Ù,ÿ  Ôķ€áOyMÃÙæ(ª|^ÃåR`Í ™œ[,%»äˆ|ÙÁN˜ÈÛåšH‰DÂïÎf³þ€-¹F„**GòÁ€«p'°ü¾“#7s¹œù8y›lÓÀþýûý–µÇ—K²IšJÕ­‰ZáRU8r浪Â6M(ÞÚEòó&g|Èϱ,Aù75®9ž)"b3‚uÂòù|Éâòá5Ae©kEQÐÓÓã'{zzüY­r=MYfKÎ7 Ão׫ªZ²Öf¥Y1áµD%Ùf(ÿ ?®$ ì8Õ-zÏžyÛê‰äz“U'g¶„—iŠ Wš6õXK"š_ƒƒƒótñïÝëîÆûÜ÷áºC׉ÙÕ6C•ÒéEÑŽ¤hZ” •l¶B§m\×E6›õ;SkY¼.›Í"£§§ƒƒƒ~}¿¡¡¡’xáQ.%‹P—'"€`D ,‹hKª¬v(Ÿ#üw9³CQ*'%ªí›¼ˆ–S}Êzµd¬j=Qø’¬Ôðu]üõw¾ƒ¯}£·®©¥ÓâíT^Ùñ~öA” *cš&ì|»ŽÅÊ×¾6x°®‹³˜§-ëµËj²œ^2™„®ëÈd2~ÉyòæIœ+Ù/0ì%7ÅÀ7?ðMÜ~ÑíP©Ðþ‡†“Œ·¾ò­XqÞ (Iêr¨Ö4¸Þ¹RvD:ÞÐÞl6[2Òºï[ßÂiŠ‚ÔºÒiqŠ“ce C4ëdó°d܉ 1³3¤À´ î†¯Üc€ú•9nl_–ÿd²T&Rd9\Yò§¤Æu åÉä(|™ôÐuét©TÊï|–³Gd©9{D~§É$Èðð°ÿÅãq¿#¹–VSv—ÊoOx3÷8«v~e³“—‰Y á9÷ދϧÓ~8~‚N×uV‡LÂM%<J&0ägLVvmìd29©dµ\SÊ]Ë™k2(G$˵?ÃÛ:òÅéåv•ïOÃWЬÉ1urâäLȦhg§-~Ž×tàgðŽGÞoýý·D}Úg `\´¹dû‰¨Q]BE.H6›{étÚ¯s^ý¯|¥Ÿ8 'ß³Hd’0üØðshšÓ4188˲ü$`"‘ð¿€Ò8q"?‹Ó•o)Ot„·³)’ Š2¹5Õ•<'Îf¼[T“žD‹¿½Q:Z~þÁŸ#³3ƒuGöGl _Åc‰ÇüëC¢FZT Y·¶|"G-Òé4Ç™”™ê¾~Ýöx™T*XÐOž¥]W¤_ #(«•Ë–J•ŽÖ-ª]KõðêÕX~ß}îœÓ äôå!„8™âjÔ4ñ䎸ÿèQ¼ôïDnp0M, 'S¤iZÄr&X6›…a~¹% “p';ˆùOÙR›õï¨âÜ';O Ã(MšØöä@·,@Uñ˜e!“ËAójùËÒå#±›¢£„¨Nd2%\±5™ &ËÊqrÜ\ÎÎü,`¼ÐÿÃ{¢—=ñØ•IÓ4ñÒÁA$ÁŸ2 Øñ…8Ç=‡ j¸–N¨È¯rQ1×¼.z5¦iú£Ö+Ž–Éfñ«_ý k®º ß½á¬õFì躎x¸¼a”vð*JPŽhºÄ EÞÞúVÄ.¼°Ñ›ÑTl[Äeh èdád €c_ø~ùË_bϲeÐÿõ_‘œjAç*䢫á BŽt'ªõe ¿^(nŸë×-t¦ÌÀ”uôwÖë¨ÉçóHyžš¦ùk-fO=uLÓk&º3À4 ³Pgê]@ú§@î=âqš hÿä=¦Nd©[9²]–¥2jYƒn¯%Kêðg‡È‘ðrý2y»œ9^›D®)"³ªªú f>|®ëú3gÂ¥µ€`‘r•ʵŠZJS ˆÒÄ  y› dÞÇYˆ¶­ŒÑ8D‰>b#ùÕûÝöþâc'gQÉD'?¸nÝ:¼èE/Â{Þó<þøã~©9Y"%™L"•J!Ncùòå~ŒÉuCd22|^NU¹fe ÜñºcÞDu1ùzšjiÙz“‰YI®•UiýÙ¨õµäõCµ} ·/€`m39è¢8€ç?ÿùuy®ÅÄuÅe£eû†Ä7å"Ù}°²O5‡eYø›·þM˵Ǩ9µdBE–c·mqBÍå‚ÜZO°ù|Þ™óþ÷¿K–,ÁïÇ»ºümcþ0tMÃýþ3^lYHzsÔü/ty‘RÃÂsD‹iŠüG"!£ₜòB4t»ëºèùùÏgUB$\Ï]’#æ8⨠¯#WþßÙ ¤¿ä @ùð½›nÂ}çÿ#¾wöÙXÇýF¯¦iH'“PU¦i"•Jùk*d26ˆ‰ÊœzêQì“#ôdgª (ÿŽ £Uóf¤ä€ø¿êQˆNZb@ …K…KÖbæ…Ÿ,•’ÉYí›\sDþ?|›,ñ';ˆå‚Ñáuòù¼?Æ0Œ’RD’±(¿[ÂI–í¤ºÈCÄšQš6 q¾‚HˆØëŠi€ý€ó=Ÿôn³½û¸Þóxñ¬÷¯å=·áý_¼å–}l–X‚ƒËbté(FŒ`óÓ›±rõJÄ.ŠáõÇ^Wœú 8¿wðôžÆ#?|ÝGºqç×ïÄ‹_ýbÜóœ{°$½—_Ž6» C,`Ã@Ð]¼®¼V¶ä$½m•á¯{Ûˆïšɤœ·r1aù^Žۆ|¯ÉçFè¹åóhÞmyï6@~2ïý /ž_~ŠwLäWƒæýMõî—ôî#_+î=BÛ¥†“ ÝVþÚòøÉd˜ƒ æz…w[¼ìµåßMï9rÞû)ßThŸäû“.{õeõþD· Ëjþ±ªár|nÙèÃO|âi?þXÖžIq+ŒT”ƒ”ÌÜ”ƒªÍ,•÷Dil™l­…¼¯Ü—™&\ËKÊ}·E~ò“qüû¿ïeY8vl{l%V­š\Œýá‡WcÕ*_ýꃡ[OÄŠ'àÞ{ƱcçãÊ+/ÅòåOã¶Ûþ€Ç/}éKqðàA¬YóFG—âœsÎÁºu'áÈ‘SpÿýÆ9çœ8ýôgpÎ9OâþûOÇ3Ï܇ç<ç÷õø,¦ ¤ß ÄÏRã߯ ›ëPkÞ:Ю¢À2M–ú¢Hi¹„J>/ªk•Wæ /Ü9Ùñjš&ººº°sçNܹe ^öâã'_ÿ:– ã‹É¤¿ø«i8WUqnµb§-LSÄæÐÐ4kÅ›Þ×÷áº.3Œ}õ«0>ýéšËf„;^TUõ²äÈw¢©™YÀù=ÿ Z(ãS®WÙOñ7ÃEl¾ûeëñ¿û®Ù¼Kß÷¾’çJ$0 Ã/5’J¥ü‰hz§=up6DçcX8QâµiuÐr:ã˜r4;$/ä 2FåLUUýAÓv~”ÍNq]¦iú‹L§R)¿´V2™DÆ[÷L>§|Íò…Ö§ºH–>Ó­Ÿ@´öÿärX¿ôŸ#èÿwåòšL ¢sü:ïÁ:J× ÜCk¬üöÔßbÏïAÎÉ‰Ïø3Öç]ú<œÿãóñø¦Çñ¸û8îÑïñKyµÝÔ†ƒ‰ƒøÎ½ß)9×¾Ê}•è¤ÿ­ø½ m¢#_ó¶Oæemlà &¢£_6©Ã_ÿ|œ»?ÖiÉ :©±s–¨vŽS¶~‘,cïß<Äʼnw”Ïç‘Ífñ¡Ë.ƒcEY2E&@ãñ8òù¼¿Š\P~Ê2}Dð:²Çô ¼À•"yç£Ððk¨ƒa?sRÙWAç90Mߨ¾_{üqœùïº.. Ç_tV.JÍY`D3wôÔ£@ÜÒfpcyy-Ë, C€´×’É”$SÞ´ ®¢àOwÜÇ{ ?|öYüª­Í/áóÞ³ÏFN&04¯8œôtÀ¶qxxý×áÙ5k`{e·TU…Lú¥ûýQµ¹\Î/¤ªª_J‹ßÔ Îj?‚l`y3ªUG èD;·¼UYhS,³.ÙuÇw`ÿþý€ÎÎNÜwß}øÜç>‡O|âH¥Rþ¨\÷–Ž(÷ÿïý“º¶là‚‚ÉIÅû ÷áÊ^UÀ_ xJå—À*&'¯3Uÿ×tƒŒS3xŒ|íÁiþ6Õ~¤Ê~¯öúÓ½7S½–LØ„ÉìH—%ÂýǸ¢sCQK“p*ð^ý° »@“ÅUˆÙI’ülʸ” ¾09ÌXóþ´üO8ôÍC€Ã+ãÉ¥OâÇþ<~~wèw8°êþòû¿ gmàþÓïÇ‘SŽÖ& —¡,ï3ª4ób.\P”•e·^Žw½ –•ÜZ~i\©ozb"øÿTýjáj¥ vµTµ ß§–ûWWY×)ošTjª„–ƒš’¦…Â}(ªß—Äà=%è_ðnÈf¬…ã?Œ=„ýÏÿD»7ê§§ÇÔN%‘K¨‹E‹Ettt £££æÇ9^cvhÁèÙP´QZOZ—k)üû¿ÿ;V¯^o¼wÜqÞò–·àu¯{8ùÝ|s£ß¢È˜m|vŸ äÖª1Õݸè‘["‘â-l-G¹ A•ÃFŒä‘£_økàZ(´¨Í&>í»ÿ‚¡ô Ô{Þäßžéø ²Ÿnδ¸¸@5M==b-‚ëo¼gê:²Ù,TodºaS®A@´˜ÍêÜ™ÍWõª:¹`º\­\~ö3|#›õgŠÀ¦ç?Ý>ˆåçŸKb1\wÍ5%Ïsä»ßÅ]÷ß—žw~úÏÿŒ½èEˆ{em³Ù,6¾øÅ8ç?À’%Kpî¹ç½÷^¼éMoÂ#^É>IÎ0)_Œ¾Ô fŸ«Öü ê/O…ò¡¯¼ šýŒ\ÆŸÉ@Ô¶õâPŽ$r´aضÛo¿?ûÙϰû¿þ ‡N; —9‚ËT+'&ðÆýÈŸqr¼PÀÅ_úÞ (@>/úããñÒÞ¾tzòÐïò¶pOOéïñxiÏd>/¶µ<¡JóKÓ‚÷˜üïºâØ…gí-‘Ù3>šJÆA¿ŽÒ2m ðûßãÁÄí_¸íÿ¯O<ñ~÷üßá Ë߀ç{:–wG€ñsÆ¡ë:Vq5Ú.n׬eaå—ñ“¥re8Á £‚dO¥‰ ´üŸLÂ¥ÌtSÊSì²çˆ‡î3QfÏEéLVYš.¼­aá} —É«´­²^ùþdBïü›î“.{„¶·üqñÐÿåû2\¶­ò5%9;̬ðš3ÝÖ„÷ÿÁб‘RÀšŸ­Á¾3¦*ÅÑZfÛ/îwõz þ®ÒÛ]w^wÓMÈ|ç;hÉKüYÕ™L†mJФH%TÐßß®®.ŒŒŒ ¯¯½½½5=6y5`œˆ öªœÞ+O²Ž© Üú»[qö¶³ñÄOàéSžÆÈߌà™ûŸÁéŸ?o8å À&JL+­+¿°Ç´HÍ6>ó¯´“-á´ÕlGŽÁ;·Ývº®½¶d¡ØÇîº ·<ü0^á8þú ƒƒƒ%‰Žz¥ÅnVñééȵêº×—þMU‘Ú)Êäó¦Ÿä|Ï{Þƒ+¯¼Ò_—H®GÀZ¶D•ͺm[e†¥iÛ°½¹¨ª¶zuÉZc²‰eY¸À~Çå•Â4M™Lù={zãñôÇ?Ž MÃwîõgx~øÃþk®òþmkô›JT'³‰ÏãÏyrƒ^ï¦öŽÊw„mÛøâ¿ˆcÇŽáÎ;ïÄ_®¾^x!ž}öYô÷÷ãË?üaIé’zÿú%ðTUÔš™N-ìÕFå¡ß4¿ªÕ#WUqì§öçl1³:ªy o³.]×Û¶aæM\üõ¯V­Z…¥K—⪞¼ðö·3IœÐ´3« fo ýâùÒcãbr<:^¯½<Ì®.jI¹Ò×è`¨S¿Ž `¨ìuÒeÙò×1òA‚W>G&dBŸ?§,9›ÖJ_g¥ÉY€ö…¾;4oUqYO«Ç êbIVY²Ù4J_'g{5ÄÑÿ–…háXÉ‹aª*Þ÷µ(­'®8á„ ,†ªn %Œãù þ™ª W¼Nø=±ÁgHUSö…¶µÂWëþ®ý8T8„V7—~[÷& Û8Šá~Šò6ÿv[בH$Édü6¬iš¼Î¤H‹TB¥¿¿;vì@,Ãèè(6n܈X,V5ãi¾î(”ñ"âWouRñÌc÷¼c?þ1<ˆý·ã`g'¾vÕyøêW¿Š+”+ÄÂ'"ÓnÚ'¦b}¶ìE+Œ˜´hœÒÑå#ÊGh˜<µÚëT…Píu*BXŒ¯~¿Ã #Nõ:ð^'¼XâÏÇq Öúµ2gŸkXƒô/c蜀qʤ‹‡[¿ùM<ý¥/áá‡ÆE]„øu×áO—^Š|>Ý;©Ž¾þõXwÍ5%u݉¨ÔlâÓÔ åÄCÐïݪſ+±š¦áõ¯=ÞúÖ·"›Íâé§ŸöogéK¢éͶm[Îôâ”5Ù5MÃÙgŸÏ|æ3øÿïÿÁ0 ¿ä^ww72™ lÛ†®ë~ vEQüR#²Ó¶¦õRˆZÔlâóزe“:Â]×…m۸ᆰ|ùrüüç?ǹ瞋îîn¼ô¥/E*•¹çž[rμꪫ½ûu•f'."³:†˜Åå88ðÄøÙȾÖÓ×uý¶ë_æ3þ‚âÄ{nÏ*ÊäºOåí]¹°Çt¼çxà°|ùr<çŒ3ð×…ëý¬]¹ÎÊ•¸à‚ pÿý÷ã‚ .€ý›ßàRo-EQpü9ÏÁÉkÖ`ùòå8räÎ9çÜáUlpš¦á¿½ç8xð –/_ŽGŸxǽ®ëBÇa«*4MóÛ–eAó¾·TU…CñÚrÀ”cY¥I¥üßUU÷ó’=®ëÂÕuX€_¢ÐMC6›åFS)¸†áoXétÉc²ºÃ0üÇÀuËòßM×aB×uÀW>†a~pÇK¢ÉÇ(ŠÇë_÷± ÖmËf³0 C Bq]ÿ}u Žã”>Æû7N£¯­ |2Î9çÜu×]xîàΧžÂ£>ÚèЙw³nÛº@ö½¿C|Å/¡¼ëZq“WÆ]–DUEQ¸^ E^d*…BíííˆÅD‘ÙÎÎNtvv¢P(L›í|âŽ'‘¾ï1 ½íûÀÿ'=÷݇ßX~ýë_ã§?ý)–,Y‚N8ùìgñ²“OÆuO£ÊsÌáu6oÞŒ]™]óþ:uÙŸøÔ÷ß¼y3ví*«O[á;Ý4LÄ0Eqä1›ø¼çž{0ºû/ˆ¯¹êïÿÓEkg³p·Ür ®¸â ,å+qÆgàUÅǾnÈwiöy£M.oðþWü,4¡þþ~Äb1ÿ86³V9&õ0›øÅ~än½Žë±müÇüñ’—¼Ï>û,¾ýíoão|#R©”¿fBÔÖ%* ( èëëkô¦ÌY«|¦[é˜Ô㽘MÛ¦i²,Üwß}¸ä’Kpæ™gâ-oy n¹å¿£¢½½ÝŒ,{)ÏÑÇsNô´Ò1™«¹Äç¯ýkÜ~ûíøÚ×¾†gžy<ðÞô¦7áyÏ{Þ÷¾÷áÊ+¯lôîUÅÏtô´Ê1©‡ÙƧ‹D"ë®»¯}íký{;òyÄ/¹¦iŠÄ„7PA&)âñ8É$ýµÒ^9L+”Ì(Œ¼O:ÿf³Èd20÷ï÷?)aF¼£é/} ¹7¾{òyüù™gpóÍ7ãï|'œ'žN: ê9çˆÎýK/…åí‡Ü–ÁÇa\z)~ò§?ù÷Ã×l§¼où¿¶7+¥|Êï~½ðcä` ™„‚µ¡t]Ç>ð|÷»ßõO8~|ø12á$·G¾®¼Ÿã8þ}œ)fpÉí‘ïµ¢(þsÈĶ|y»\§JþÍOÄ8&&&°sçNLx Ì(Š‚Æã·Ý†•kÖ`í±c˜€sÏmtèÌ»¹œ;í«wÃ:v†s×…ešøÄ'>X,†×¿þõþÌëF ¢ú¹¤®¯ã9섉‰ð²S³sçN …’°yóftvvNû¡¹ä’Kpâ}Ëñ§3ÄŸÿüg,_¾'t–/_Žç?ÿùP«V­ªeêСC8í´Ó°|ùòFoÊœíß¿kÖ¬iôf,È~ŒŽŽâرcøÐ‡>„¿û»¿kô&Ï›ÙÄç?þã?â[ßÚ‹Gy§žzÇGGG}ôQ¬[·K–,Áòå˱dÉœ~úé8õÔS½›Sj•Ïôbúž9räöïß§žz wß}w£7w^Í&>/½ôRü÷ÿ7Ž?ŽÓN; ÇǺuëðÄOàòË/ÇÿøG<ïyÏ‹t\â8=zgŸ}v£7eÎZå{¦–crèÐ!<üðÃ¸à‚ ps ¯U7Û¶í¥—^ŠÑÑQœ{î¹X±bÎ<óL,Y²pÆg4z·j¶˜Î9Í¢–c¶íÔñù­o} }}}øóŸÿŒuëÖá”SNAgggäÏ••,¦Ït³¨µm{ìØ1üæ7¿iôæÎ«ÙÄçË^ö2ÜsÏ=8ùä“¡ª*Ž9‚¾ð…¸ÿþû¡iþøÇ?âÌ3ÏÄ#<‚ÓO?ü£„mÛèaÛ60—¶íi¿Í῟“‚ûÌ/ñœç<Çÿî^³f –,YÒÐ6nÔÏ%Íð½åxß¿?y䑺·m#3CelllÒmµ”C¸çž{½éD-o6ñù¹Ï}ŸûÜç½éD-o6ñÙêâDQ0Û¶-ã“hþÍ&>ÿîïþ®¥“LDQ1›øüå/ÙèÍ&jysoÛÞÖè] ª›½R¸dT,½YDÆ'Q”1>‰¢‰±I]ŒO¢èb|Ec“(™„Jggç¤@›ñ¢DTŒO¢èb|Ec“(ºŸDÑÅø$Š&Æ&Q 2 •X,†±±1 ¢~o±XĆ ½iD‹ã“(ºŸDÑÄØ$Š.Æ'Qt1>‰¢‰±IˆÌ*Ð×ׇ­[·¢«« ###èëëC[[[£7‹ˆÀø$Š2Æ'Q416‰¢‹ñI]ŒO¢hbl 'LLLL4z#ŠÅ"ŠÅ":::8mŒ(bŸDÑÅø$Š&Æ&Qt1>‰¢‹ñIMŒM¢&Tˆˆˆˆˆˆˆˆˆˆˆˆ¢&2k¨E*DDDDDDDDDDDDU0¡BDDDDDDDDDDDTÅIýèG?Ú蘭b±ˆÑÑQ@{{{£7gÚm”‹6‹E´··cÉ’%5ïG£÷s||úÓŸf¼mQܯJû2×cÔèãEÍòž´Â±Ÿ*>ç ½oÕöcªcµýhÍòž4û±Ÿí¹³Úß[åÜÙ¨}¡¹ÅÒ¥Këv¬ús _o||guV]·u!ö¥–óe¥b›éÑìTŠM ¹Žýtñõ¶m-çýÙÄg£÷‹êc6ñ¥c?—sç\÷³fŸQß/ªn>ÛGõVï6v½ŒÃ¶íyi;7µ‰&uóÍ7OtwwOlÚ´i¢»»{âæ›onô&Uô¾÷½oâ‚ .(ù¹ýöÛkÞ(ìçg?ûÙ‰Ï~ö³“nŸnÛ¢º_•öe.Ç( Ç'jšé=i…c_é3=×økľMõ=3Ý1Šâ~D]3½'Í~ìgsî¬ö÷V9w6r_hnz衉îîîºë…þ|ö³Ÿõ_ïꫯž¸á†ê¶­ µ/•â±|¿þöoÿvbll¬)ÍN¥Øœ˜h®c?]|6CÛvªóþ\â3 ûEs7›øŒÒ±ŸË¹s®ûYÏ}˜i|6Ã~Ñôæ³}Toõnc×ËÈÈȼµ›]Ó&T´‘‘‘‰ .¸`⡇jôfM²iÓ¦I'ΙìG#÷óæ›oö;L*|¦Û¶¨í×tû2—cÔ,ŸÃ…ÔLïI3ûé>Ós¿…Ü·jß3Ó£(íG³h¦÷¤Yý\ÎÕþÞ*çÎFì Õ‡¼ ûfùL?ôÐC%Ï?666qÁLŒŒŒÔe[ç{_¦ŠG¹_áý¸úê«'òù|Ó#š½J±91Ñ<ǾZ|F¹m;ݹr®ñÙèïªÙÄgTŽý\ÏsÝϹšK|Fy¿¨ºùnÕ[½ÛØõ~ÏÆÆÆ&®¾úê‰={öÔ´ ­M¹†J¡P@{{;b± ³³( Þ´ŠÛZiZY-ûÑèýìêêBoo/:;;g´íQܯjû2›cÔèãEÍöž4ó±Ÿê3=×ø[è}›.6§;FQÛfÐlïI³ûÙž;«ý½UÎQ8F4;ýýýèììDWW—[3}¦ÇÇÇåÚÚÚÐÑѱ±±9oëBìËTñX,‹ÅJn_¿~}MûµcD³S)6æ:öÓÅgÔÛ¶Ó+çŸÞ/ªÙÄg”Žý\ÎsÝÏz˜m|F}¿¨ºùlÕ[½ÛØõR(066†-[¶ñoYÖ¯__uCœÜè ˜ÑÑÑIñííí(‹Þ´òä³mÛ6 ´µµ¡¯¯½½½5íG£÷S~ñTªs7ݶGn¿¦Ú—¹£jû¹5ú3;Í~ì§úLÏõ{e¡átß3Ó£¨íG3h¦÷¤™ýlÏÕþÞˆïù8wÖòwŠžÑÑQìÝ»»wïÆÖ­[Kno–Ïtgg'z{{qà 7 ‹ùIAy¡õ¶íTñ‹Åü}D|îݻ׿øm¦cD37UlÊ¿5˱Ÿ.>wîÜé¶ítçý¹Äg¾whnfŸQ:ös9wÎu?ëµýòyËMŸQß/ªn>ÛGõ4mìz)‹èêêÂÀÀöîÝ‹¶¶6ôööÖ¥íÜ šr†ŠÌ(†M5J²‘dFtË–-¸ï¾û°cÇô÷÷û¹jûåýœnÛši¿ærŒ¢´QÑLïI«û¹Æ_”ömºcÔLûÍôž´ê±ŸË¶Gi¿Z¹}C“cë֭رcÚÚÚJþÖlŸé¶¶6aÒò‹ÀVhÛîÝ»7nD,óœÍvŒ¨vÓÅ&Ð|Ç~ªøl•¶íLã³Yö‹*›K|FíØÏöÜ9×ý\HåñÙ*ûEB½ÛGõ2_mìz)‹þl“-[¶ ££›7oö“"‹=š2¡R)»Å,Wgg'víÚågïb±6lØàw8TÛ(ïçtÛÖLû5—c¥ýˆŠfzOZõØÏ5þ¢´oÓ£fÚ¨h¦÷¤Uý\¶=JûÕÊíš,ŸÏ£³³Ó/166†ÑÑQŒŽŽ6ÕgZŽ®Û½{7úúú`YFFF°sçÎ9ok£?ÓãããØ¼y3úûû±}ûvlß¾½æm‹Ò1¢™™.6æ:öÓÅg³·mgŸQß/šÞ\â3JÇ~.çιîçB˜*>›}¿H˜¯öQ½ÌW»ž:::°cÇÄb1¿"ÁÀÀ@ÕmX qД •ÎÎÎIbll,rÙ.™Á g«íG”÷sºmk¦ýšË1ŠÒ~DE3½'­zìçQÚ·éŽQ3íGT4Ó{ÒªÇ~.Û¥ýjåö U6>>Ž;wbçÎ(‹Ø³göìÙÓTŸéb±ˆŽŽŽ’Ïj,óGÐ5sÛvÓ¦Mèèè€eY%å-jÙ¶(#š¹©bh®c?]|6{Ûv¶ñõý¢êfŸQ:ös9wÎu?ÂTñÙìûEÂ|µêi>ÚØõ‹Å&Íœi…>³ºY€…ïçEww÷Äí·ß>11111222ÑÝÝ=166ÖèÍ*qóÍ7O\}õÕþvM\}õÕ7ß|sÍû…ýÜ´iÓÄg?ûÙI·O·mQݯò}™ë1ŠÂñ‰šfyOZåØWŠÏ¹Æ_#ö­Ò~T;FQܨk–÷¤ŽýlÎÕþÞ*çÎFî ÍݦM›üc71Ñ<Ÿé={öTüÜæóùºlëBíËTñxûí·—ü<ôÐCMwŒhnÊcsb¢yŽ}µøl†¶ítmÙÙÆgö‹êc¦ñ•c?×sç\÷³žïÿLã³ö‹¦6ßí£ùPÏ6v=ŒMtwwOŒŒŒø¿7cŸÙ|iÊEé ¯¯[·nEWWFFFÐ××W±6e#ÉÅs7nÜˆŽŽŒŒŒ ··×¯ÙWË~Dy?§Û¶fÙ¯¹£¨ìG”4Ë{ÒÊÇ~®ñ•}«vŒše?¢¤YÞ“V>ösÙö¨ìW«·ohfšå3½~ýz \}õÕèêêB±XDgg§¿8é\·µQŸéb±ˆb±ˆÍ›7—ܾeËôõõ5Õ1¢úk–c_->›µm;×øŒê~Q}4ñŸë¹s®û9ŸªÅg³î óÝ>ZÞ¾¶¶6ôõõùëÏÈu4[¡Ï¬N˜˜˜˜hôFÌ– ŽŽŽHOõ§6UÚÎjûåýœnÛši¿ærŒ¢´QÑLïI«û¹Æ_”ömºcÔLûÍôž´ê±ŸË¶Gi¿Z¹}C3ÓLŸiùzíííèìì¬ë¶Fù3ÝLLj꫙ŽýtñÙJmÛ™l[3ïU×,Ç~.çιîg#µê~Q JqÕí›Ï¶s3kê„ ÑBhÊE鉈ˆˆˆˆˆˆˆˆˆˆ*DDDDDDDDDDDDU0¡BDDDDDDDDDDDT*DDDDDDDDDDDDU0¡BDDDDDDDDDDDT*DDDDDDDDDDDDU0¡BDDDDDDDDDDDT*DDDDDDDDDDDDU0¡BDDDDDDDDDDDT*DDDDDDDDDDDDU0¡BDDDDDDDDDDDT*DDDDDDDDDDDDU0¡BDDDDDDDDDDDT*DDDDDDDDDDDDU0¡BDDDDDDDDDDDT*DDDDDDDDDDDDU0¡BDDDDDDDDDDDT*DDDDDDDDDDDDU0¡BDDDDDDDDDDDT*DDDDDDDDDDDDU0¡BDDDDDDDDDDDT*DDDDDDDDDDDDU0¡BDDDDDDDDDDDT*DDDDDDDDDDDDU0¡BDDDDDDDDDDDT*DDDDDDDDDDDDU0¡BDDDDDDDDDDDT*DDDDDDDDDDDDU0¡BDDDDDDDDDDDT*DDDDDDDDDDDDU0¡BDDDDDDDDDDDT*DDDDDDDDDDDDU0¡BDDDDDDDDDDDT*DDDDDDDDDDDDU0¡BDDDDDDDDDDDTÅ¢O¨äóyX–ÕèÍXT\×…eY°m».Ïç8òù|£w‹æã³y8ŽS1®Ÿ­ƒñØüj‰G×uá8Δ·,kÊ¿S40V›Ç\ÎŒÕæÃØlŒz^{ÖÚ®e|6?Æë›m¬ò:tñ`\6¿VŠËEŸP1M³i²§§Ç?i„ÿe¶mcíÚµÈf³H$H&“s~NÇq`šf£wæã³9¤ÓitwwWŒkÆgëhÖx,¿VÇéÔÙl¶b#7ŸÏûqÞÝÝÝ2 áVÔ¬± ðÜ)1V[S«Äf¥ß£ªÞמµ¶kŸÍ¯UâµÕc•ס‹ ã²ùµR\.ú„J3³, ®ëNú”% ¤R) axx–eµL0…5c|Άã8Èf³öã:ŸÏ/ÚEOyüµr<ÎE>ŸG"‘@6›­ø÷t:ÁÁA ahhÉd’£k©îxî¬~îd¬R#4ë¹t¡¯=ŸÍx.M¬ò:”šI3Æ%MoÑ%TLÓÄÚµkq ' ™LNúËÌøÊ•+‘N§‘N§ý/dÛ¶‘H$p ' »»»ä ¾§§ù|+W®ÄÊ•+‘Ïç‘N§±råJ¬]»ÖÏ¢Öz¿jÒé´ÿï¦M›üÿ×ròoƒeY“~¯tŸ™<çTû%¿4R©@QìÛ·ñx|Òó„mÛþ±Ï7Ýhy_yÌfòXj¬éâsºØ”¯Ÿ3‰¹fˆÏùˆMùþU‹•Jñ)‘¢(þ¿ªªNÙ@;Æf´µB<†cQ~æÂ¿WÓlñ8—ó¥¦i0 š¦MºŸeYPº®û÷Õ4­iGˆµšVˆU€çÎZÎcµ™ÌåºSþ= ñ9—si-×™óŸÕ®=+Ŧ|ßk=—†c`|6³ù8—‹»Ÿ¨^±~.^‡..î¿é}§¥¸¬uŸfÛÆ•ïýlΣM›‹È¾}û&Ld2™‰‰‰‰‰T*5`"•JMLLLL>|xBQ”‰ÁÁÁ‰Ã‡O†1`bhhÈÿ›|ìÐÐЄ¢(ûö훘˜˜(yžL&3éut]ŸÑýj!·­üÿµvhhÈß Ã˜Ð4Íßæ¡¡¡iKÑ1]|N›ÓÆçLb®âs>bS¾gÕb¥R| M†1Ç'r¹ÜD</yŸ¦ŠOÆf´µR<–Ç_+Çã\Η’®ëþ6J™LfÒû]é~´ðZ)VåsñÜÉXms¹î ÿ=*ñ9Ûsi-×™óŸÕ®=§ŠÍé⺖؜˜`|6›ù:—NL,î~¢zŪ|.^‡..Qè¿é}§•¸¬uŸæÒÆíy´ÙbsQ%TR©Ô„a%·©ªZòA ƒü° Mär¹ MÓJk†ÿØpnJ~¿‡O”µÜ¯s HùERé÷©n«öœÕöK~ʤü½|[Â_º®Od³Ù EQ¦<–òù ØP¥äñ2§z,EÇtñ9]lNLLLŸ3‰¹fˆÏùˆMùÿj±R)>e,Ëc¥ªjÉc¦ŠOÆf´µR<Î5¡ÒLñ8—óeøyÊ;w*],„Û@Ô8­«ò¹xîd¬¶‚¹\wNLD/>ç’P©v9_ñYíÚsªØœ.®k‰Mù\ŒÏæ1_çÒ‰‰ÅÝOT¯X•ÏÅëÐÅ% ý·3½ït¢—µîÓ\Ú¸³=6[l.ª’_¶mûÓ%UUýÿ»®[2=7|_Çq`Û6N8áÿ'ÒSªïw¥ß§º­¯;88]בÉd`Ƥ÷±ü˜4mZQ”’z³áimåÓæª=–¢aºøœ.6ÅŸó›@m±RþÞßrË-0MÃÃÃÈd2Ø·olÛ.©=U|26£‹ñ8y¿ký½^fµ«]{VŠ`ú¸žMlNõZŒÏhà¹tò~OõûT·ÕãugÚOÄëÐÖÆþÛÊû]é÷©n›«Ù^V{l«ôß.ª„J¥Z¦å¦:P²Þ鄘Õãÿd2™FïVÓÐu}R°M|åÊKyíDMÓËåJ¥&ÕV¬öXІjñ9Ý—(ã³>f+„ªª%±¬ëzÉc§ŠOÆft1o¶ñ1—óåT4M«ø¼óÕFµc¬6ÞBŸ;§ÃX޹\wŒÏz˜¯kÏÙĦ|ã3šx.m¬ÙÆ*¯C[ûoo.q2Ûóh3Åæ¢J¨¨ªŠ|>ïÛ¶K2cñxÜ_ À¤¿Ù¶ígÏ\×ÅÚµkK6¢éÉFdø=4M³¦F¤ã8þñ“ úÁ 7•JAUÕ’Q ÕKÑ0]|N›òïŒÏ¹›M¬\pÁpÇ?6òqá†íTñÉØŒ.ÆcãÍ6>ær¾œŠ¼8 /Äí8NÉb¡ÔŒÕÆ[èsçt«Ñ1—ëNùwÆçÜÌ×µçlb`|FÏ¥5ÛXåuhkcÿmãÍ%Nf{m¦Ø<¹Ñ° ÀmÛX»v­ÿ¥nÀhš†x<Žîîn¨ªZ’ SU©T ===þcu]ohHUU¤Óiär¹’ÿ×’ÉmEQÉdÐÝÝ ]×ý÷Ð0Œšö5™LBUU8ŽãJäkÈc3“ÇRãLŸÓÅ&Àø¬ç6Ï4V^õªWáСC%ÇMÓ´ªñ¹fÍÆf„µR<–Ç_+ÇãL>_V{/2™ ‰4MƒmÛÈd25ô¥ùÓJ±*·‰çÎÉ«Íg.×@ôâ³Ï¥óqíYÞ™>“Ø”÷g|FÏ¥5ÛXåuhkcÿmãÍ%Nfsëk.´¼…dÛ¶ýz{áŒëºþô"×u¡ë:N8á>|Ø¿Ÿã8pŠ¢4üƒ/·EÓ4ÛË÷)ŠfúZ–…l6‹¡¡!X–5£÷~.¥Æ¨ŸµÄ&Àøœ‹¹ÆÊBÆ5-œVˆÇp,ʬ­óWò½SU•%J"¦b5¼-›ñ\Z¾í<—R5<—6ÖlßèÅ8Õûo£ý°Í›‹j†Š4Õq]===„¦iH§Ó“ê9.DÃÇqœiLÒuº®—l‹ÜÆé¦ËÇÍǶÌÄ\ÞùLõŠê41*U)>k‰M€ñYç”›©FÅ5ͯVŠÇðv­syÜtØù]­«ÃÛÔ7>ç+6£ÖFe|FÏ¥õß–™˜í{µ§úbÿmý·e¦ÑÛ ±¹(*SQU¹\ÎÿP«ªŠÁÁÁß¹€ÒtÛYÏÇÍǶÔûý˜mV2êMªMTbhÝø\èXal6/Æc}·eªçšM|0®(Œ±Zßm™ê¹s4ŒÏù¾¹¼Œk’«õÝ–(`Œ·†¨Äf«Æe#úa›-6eÉ/"""""""""""¢™8±Ñ@DDDDDDDDDDDuL¨UÁ„ QL¨UÁ„ QL¨UÁ„ Q'7zæêe/{.¹ä’FoÆœ=öØcXºt)–.]ÚèM™³C‡áì³Ïnôf,Ø~:tï|ç;qíµ×6z“#åcû~ò“Ÿà¼óÎkô¦ÌY«|¦ã÷Ìþýûñãÿ¸Ñ›9W_}5^ð‚4z3æìرc8vìV¬XÑèM™³Vùž©õ˜9rçž{.>ûÙÏ6z“#ç5¯y Ö¬YÓè͘³ÅxΉºZ Û¶•}ÿûßÇW¾ò•–ø,,¶Ït3`Ûvn‰N;í´FoÆœ±m=lÛÎ]ÔÛ¶Q?—4Ã÷BÔã}>Ú¶ žP)‹(‹%·uuu¡­­­äïèèè¨ú|صk×BïFÝõ÷÷#‹!‹5zSælóæÍ-qLjÝþþ~œyæ™ÞÜ9«›áûÔŸ«W¯ÆYgµ¨> Q·¿g6oÞÜèM­‹zÇçã?ÞŸéB¡€B¡€¾¾¾FoÊœµÊ÷L­ÇDÞ¯U„c4ü[Kì–[³fMK|ã9'êj=&­Ò¶¦ŽÍò¿IÓÅç™gž‰×¼æ5<çDÈbüži•¶-Pßø<í´ÓZâ3Ͷmô,ƶm½ûm£Þ¶ú¹¤¾¢ïóѶ]ð„J?öîÝ[rÛ®]»‹Å000€þþ~tuuadd}}}èííöùZ¥±‹Åjú"jëׯoô&p?faºØ0ãø|îsŸ‹Õ«W7z·ê¢U> üži^õŽÏV9wvttD¶á;S­ò™n¥cR«þþ~  «« Åbmmm¸é¦›ÐÖÖV5v[Ï9ÑÓJǤÓŦüûbO~¦£§UŽI­Ÿ•µR;ªU>Ó­tLjUï~Û¨‹ú¹¤>ƒ­ï3±à •ñññ)O„ýýýرcb±FGG±qãÆªì(O)š‰¨ÇL4û—i«íG­¦‹M`æñÙJ •Vù,ð{¦yÕ;>[åÜY먨fÐ*ŸéV:&µ(‹Ø¹s'vïÞÎÎN€®ëÀ–-[ªÆn+k¥}n•øl¥cRMµØªŸ[[?ÓÑÓ*ǤŒÏ©µR;ªU>Ó­tLjUï~Û¨‹ú÷L3|[%ÞgbÁ¥/ ?…Bíííþ¹³³-3eŽ(ꦊMù7Æ'Qã0>‰¢©X,"‹ùB€¡566`úØ%¢ùS-6Æ'Q£0>‰¢ý¶DÕ-hBe||°mÛ6\xá…¸ì²Ë000°ííí“êö•;r䃗¦P(àÀÞŒ9›.6ÙÇç0::ÚèÝ£Eh||…BÇŽkô¦Ôe_€úÆç±cÇP(ªÆ0Ñ|(‹¸çž{ðÔSO5zSæ,‹•Ô ÇÞ½{ÑÑÑQ5v§Â¶-5R«´m§‹Mù;0óødÛ–E¶m9ÒèM™³ùˆO¶m©‘Z©m;Ÿý¶ò¹‰Òèèè¼´m4¡"G"lÙ²÷ÝwvìØþþ~ …’ÑR-#Ž=Ê‹Nj˜V¹èœ.6Ì:>8€‘‘‘Fï-Bccc-“P™øäE'5R±XÄèè(Ž?ÞèM©«½{÷úez{{«ÆîTض¥Fj•¶mXylÕÏ­SaÛ–E¶m=ÚèM©«zÅ'Û¶ÔH­Ô¶Ï~ÛJ'šo###óÒ¶]Ð5T:;;KF"Äb1lذÁŸ6V®X,–L­äì³ÏF__ßB¯¯ýýýÞŒ9›.6c±Ø¬ãóòË/_”µ©ñ:::Ð×××£Hç#>W¬XÁs'5Œ,Ð*IƒññqlݺÅbÛ·o/)ƒ0]ìN…m[j¤ViÛSÇ&0ûødÛ–¥•Ú¶@ýã“m[j¤Vj۲ߖZèVo >C¥¼ÐÖÖ@mùޱn&ј.6Æ'Q#1>‰¢mÓ¦Mèèè€eY%=Õb—ˆæ×T± 0>‰ñIMì·%ªÍ‚&T …¶nÝê×Í ×ÊŒÅbþ4V@Ô8+‹Ø°aC£ß#¢–7]l`|5ã“(º0>>Žõë×£P(ø?Åb±jìÑü™.6êçV"š?ŒO¢èb¿-Qm´äWoo/FGG±qãFttt`dd½½½þ´é¾¾>lݺ]]]A__G"-€j± 0>‰…ñI]ÅbÅb›7o.¹}Ë–-~i–éb—ˆæGµØ¬åÜJDóƒñI]ì·%ªÍ‚&T`ûöíõ§……Gôöö"‹¡X,Núͯéb`|5ã“(šúúú¦­ ]-v‰h~T‹M€ñIÔ(ŒO¢hc¿-Qu žP0í‚E H¢Æ©¶˜㓨qŸDÍ©ZìQã0>‰¢‹ñIÔ8ì·%šÞ‚®¡BDDDDDDDDDDDÔŒ˜P!"""""""""""ª‚ """""""""""¢*˜P!"""""""""""ª‚ """""""""""¢*˜P!"""""""""""ª‚ """""""""""¢*˜P!"""""""""""ª‚ """""""""""¢*˜P!"""""""""""ª‚ """""""""""¢*˜P!"""""""""""ª‚ """""""""""¢*fPG¡PÀèèh£÷ˆˆˆˆˆˆˆˆˆˆˆh^Í*¡ÒßßË.» ›7oF? …t]gr…ˆˆˆˆˆˆˆˆˆˆˆZÒŒ*{÷îÅÀÀvíÚ…]»vb±z{{±iÓ&Œ7zŸˆˆˆˆˆˆˆˆˆˆˆˆêjÆ •B¡€ÞÞ^Äb±’Û·lÙ‚ŽŽŒŒŒÔü\£££“0Åb…BÅb±Ñï Ñ¢U)6Æ'Q0>‰¢GÆ_¡P˜òoŒM¢…7]l†ÿÎø$ZxŒO¢èc¿-Qe [”¾X,bÓ¦M% ˜lܸ;wîÄÆ100Ðè÷‡hÑ©›ã“( ŸDÑÓßßïÇß¶mÛ°qãFÿ“±IÔ8ÓÅ&Àø$j$Æ'Qô±ß–hj'Ïô±X 7Üp6lØPrûÀÀŠÅ"ºººjzžmÛ¶Mº­¿¿;vì@,Ãèè(6n܈X,†ŽŽŽF¿OD‹F¥ØŸDQÀø$Š–b±ˆ;wb÷îÝèìì躎lÙ²…±IÔ Õb๓¨QŸDÍý¶DS›ñ •õë×£··7nĶmÛ022]×Ñßß¾¾>´µµU}Žþþ~tvv–$_ …ÚÛÛýRbèììœrú§täÈ‘ª÷!š/…BhôfÔM¥Ø”û9›øâ“m[j¤VjÛJóÑoË5·©FGGç¥m;«’_}}}°, [¶lAoo/úúúð£ý½½½5íÈÞ½{aƤÛË3šíííUOˆGåE'5L«\tSǦüÛlâóÀ3ZW‰¨^dgf«$Tꟼè¤F*‹Åñãǽ)s‹Å°k×.ÿ÷ññqìÝ»lÛRSj•¶ít± °mKÍG¶m=ÚèM™³ùˆO¶m©‘Z©m Ì_¿­Lš-¤‘‘‘yiÛθä×ÀÀ:::‹ÅjJ „cë֭رcǤ™,•«–)cgŸ}6úúúêþÆÕ¢¯¯ýýýÞŒ9›.6ÙÇçå—_>ãï ¢zèèè@___KŒ"ø\±bÏÔ0rT[«% öîÝ‹þþ~¿\©}À¶-E]«´mÃÊc`Û–šO+µmÃêŸlÛR#µRÛ–ý¶Ôjz{{ç%Ù>ã„J±XÄÀÀvïÞ=ãËçóèììôGWŒattíííhoo¯øZái D4?¦‹ÍÎÎNÆ'Q1>‰¢M^x‹El߾ݿ¨fl5ÖT± 0>‰ñIMì·%ªÍŒ*†a`||ÜEP®ÒmaãããØ¹s'x{öìÁØØb±Jî;66Æ…ˆÈT±)ëb2>‰‡ñI]›6mBWWWIùŒM¢›*6Æ'Q£1>‰¢‹ý¶DÕÍ8¡’Ïçý’vß}÷MùØò)^›7oÆ–-[ü$ŒÌ€Æb1ŒŽŽ¢X,bÆ ~ˆZ^µØŒÅbŒO¢a|E×ÀÀÆÇDZ~ýú’2²<.c“¨1¦‹MÆ'Qc1>‰¢‹ý¶Dµ™qB¥¯¯Ï°ÑÑQŒùeG檯¯[·nEWWFFFÐ××W±^<-<Æ'Qt1>‰£X,¢X,bóæÍ%·oÙ²Åo336‰^µØxî$jÆ'Qóbl 3N¨bDA?ÆÇÇýÛ:::°cÇŽ%Vʧwööö"‹¡X,ú£ˆháUšzÍø$ŠÆ'Qt„UÂØ$jŒj± 0>‰…ñIÔ<ØoKTÙŒ*…BýýýèëëÆ ÐÖÖ†b±ˆ;wbÓ¦M¸óÎ;ç´A H¢èb|Eã“(š›DÑÅø$Š.Æ'Q416‰€gú€½{÷¢··½½½þ´®ŽŽlß¾ííí%50‰ˆˆˆˆˆˆˆˆˆˆˆZÁŒ*cccSþu󈈈ˆˆˆˆˆˆˆˆ¨Í8¡‹Å°wï^ŒŽŽ–Ü>00€b±ˆ®®®FïQ]Íx •ÞÞ^ŒŽŽbãÆèììD{{;ŠÅ"ÆÆÆÐ××ÇY*DDDDDDDDDDDã8âG׃۲Yño*ÜfÛ€ªŠR¿×UÕÉ·›&7ú]™™ÏP€íÛ·c÷îÝØ°a:;;±eËüèG?Booo£÷‡ˆˆˆˆˆˆˆˆˆˆˆÊ˜&`Y¥·9 i¥·¥Ó“ïW ׉ÒÛl[<Ÿm‹¿Ëû¹®¸Ýq€dRl›ã”>6™òùF¿k¥f ‰äG¥Ù*–U:ÛŶÅk†ïošâv™ I¥‚Y1€HšÈd‹m™Œ¸ÝuÅ6d³bv‹ªŠíÉç}ûÄß+Íz™o³J¨ ìݻ۷o¬ŸbK~5e‰dD8¡.½%g“ÈY!º.’Š"’(==âÿ=="±!“r6‹m‹¿>,î—N‹äL<¬\)'¦)žWQD"Äuƒ„‹ªŠûÛ¶xŒ¦Ûæ8bÛE$y’IñY®Ì²‚çÖõ…M¬Ì¸ä×èè(6oÞ\r[GG …6mÚ´p[NDDDDDDDDDD´È¹®Hn„©ª¸=› fv˜f|Pñ#gÈÙ+étPšK&<ño>/’02¡žñ’ϋ榉ˉ™\.H–†H Š„K<.þ¯i"Y’N'œtw‹ûËD‹®‹mËçƒõ`³]ÂŒg¨ìÙ³½½½þìˆÅb¸é¦›°qãF Äb±…Ý """"""""""¢E ™‰ ɲÄm‹$‡œ ¢("áàº"9‹Ûe™/™ü ”DB”ÓRU‘ÄH¥ÄßeâE–í’5 ±-2ùaÛâ6M÷1Mñ†!^#\,Ì0Ä¿Ž#^Kn£$·C&‰$UûW¾è½,6fœP)‹èèè˜t{[[Ë}Í£|^$0d¢D&+ä칆I.¬abâ>+WŠÇ[V0{D CCâßpɰtZÜ.:á²bš$yt=x=`ò¢÷S‘¯N¦b_ävÈ’d‰D°É烵W€`fÎ5×Ôÿ½Ÿqɯ®®.ìÝ»Åb±äö½{÷btt´b²…ˆˆˆˆˆˆˆˆˆˆˆ¦–ÍŠ$AX:¬sˆÿËã³Y‘,±í`m™|IŽLF$ drch(HD”':ÂÉ“IÀðD²B&<4MJ%2A3mò¤PÔPÙ.E©¾Os樘‘I# XÓEΞ‘3tž|riÝ7gÆ ؾ};z{{±gÏ@{{;vìØÁd ‘G.æ>U‚#̲D²Ä4ƒ5IE$@äBíŽ#Js…g²ÈÙ'áuU¦S˶L⨥t×J‡ëóÞÿdmh*¬½âº.oGä¢öš ‹r`ª lÛö^\}u¡>ã©)¡200€lذëׯGGG:;;ÑÙÙY×!""""""""""jét°–I˜m—.Ô.g¢Ø¶øÿáÃ"1P¾ {<.þ¿o_Pºk¦f•P€,€j3RÜžÇò~ª<×ðøÈãXÕ%·;Žƒîîn AÓ4Œ¡àƒ¯}ín\ziýó5%Tz{{±aà ìܹÅbذa“*DDDDDDDDDD´(ÙvéZ$rAtY ËqDÒÄq‚RTŽ$XdBE."/ŒïîÏ!’¯ƒ"͸l‚ä̼Q1e™®àM«þ4ù|k^¶ZÙB/===pCCCþ •{ÿá^\¿Ù|ªªÂ4M<ç9«qÕUG¬­ëîÕ\ò«­­ ëׯÇúõëˆEèf•\ÅØØÚÛÛ'=¦X,¢X,¢££ƒ%ĈØt± 0>‰‰ñImããã+‰?—a]]]hkkkôæ-•b`|Eã“(šØo;sÝÝÀÄDð»iŠ™P‘3HdÙ.E‰¹Þ ’(Ž#þ&×I$‚„‰¢Ô/ ¢isX°½Úãlˆ*e³TÂå¹ÄFO~ôIt¢»»‡5ÂÒé´·Ö<»ŽéàîËï†eYÈçóH¥RHyoêÚµkaRO¤p蛇àº.âñ8âñ8,ËÂ7Þˆ?þqs}Þ8ϬÖPP’\Åž={pà 7àãÿø´‰•mÛ¶¡P( ££Åb±X Û·o J‹õ÷÷£«« ###èëëCooo]w˜ˆ*›.6Æ'Q#1>‰¢/ŸÏúúúüÛúûû±wïÞ’ûíÚµ ±X¬Ñ›K´hTŠM€ñIŒO¢èa¿íÌYÖäY"á å‰ M Jx"±³XñXE)-å•Ë•%Tz ¡:@ÙöÙö,“3qù*÷Q¼û™4À²,X–EQü$9r÷ß{?&Ü û —t:x<îÏJyúKOcôÔQüâã¿€ö^Í/ñ% Âô¦úüCæA 1Û{óŸ÷¼çÍbg§6ë„JX­ë©ÈÄË~ô#´µµ¡X,B×uôöö¢³³ýýýرcb±FGG±qãFÄb1f<‰æYµØÀø$jÆ'Q´  P(`ï޽زeKÉ߯ÇÇÙDÔ ÓÅ&Àø$j$Æ'Q4±ßvvl[üÈÅäóyñ#“#Ž#~€ ñ®`eÁãe¾appòý&•öªeqx"RöØTj‹ÒW(1fÛ6LÓD&“ñg¦;v £ö(LÓ„¦iþÌ@$ÔϾñl\wø:@¿;ŽMÓ ªjIÂä”SNÁŽáøâ7¾ˆåoX>éµ5Mƒ¦ixö‡Ïâ¬÷œU¶Ÿ)œtÒI³=´S:q&w. ðÅæÍ›±yófô÷÷W}|±XDoo¯?MSÜØØ …ÚÛÛý¦LÒ …iŸóÈ‘#UïC4_ …8Ðè͘³ébSîçlâóÀmôîÑ"4>>ŽB¡€cÇŽ5zSæl>âóرc( “J)-„b±ˆ{î¹O=õT£7¥.ºººJœartßL°mKÔ*m[`úØ”û:ÓødÛ–E¶m9ÒèM©‹zÇ'Û¶ÔH­Ô¶Ï~ÛñññFïÞ¼ð&Úùë£ÈuQäZ'rÍ™\Ñ´Ò$ îcYÁ¬”±ªüÝñ~ÊÌvAúÇ>ó˜(Íšuã8\×…ªªppcËŽáßûlÛF.—ƒa0 Žã`íÚµÐu×]wŸ2 Ã/ÑeƤ×}í®×bù˧ݶ“¾z.þúÅ%û;:::/mÛš*Û¶mÃæÍ›ýT±XĦM›ˆ Ú»w/¶nÝ:ís¬_¿}}}~c ¿¿~f³ü„ÙÞÞ^õ„xôèQ^tRôÊEçt± `ÖñyàÀŒŒŒ4z÷h’ ¾VH¨ÌG|ò¢“©X,bttÇoô¦Ô…ŒÇööö’ÛåEã¶mÛpá…â²Ë.+˜4¶m©‘Z¥m L›Àìã“m[jÙ¶=zôh£7¥.êŸlÛR#µRÛv>ûmå€ÀVcYA /Çkž ‰„…eI–ò…äË)J0+¥f6ª'TjMœ¤d§¿‹ëº¸wõ½ß?^’´Èf³þì’t:Ý?Ùþî?ãŒϘ”Éf³‚*ëéðŸKÓ4är¹Š¯ÇE ±éÞ‹·æE‚&ôžŒŒŒÌKÛ¶¦’_rÊ×îÝ»ý{÷îE{{;vìØ¶¶6ôööB×ua¢é‹EìܹÅbÑ_‡¥R`Õ2"áì³ÏžTo“h¡ôõõÕ4;«YTŠM`öñyùå—³ž&5DGGúúúZji=ãsÅŠNèg– Ú;ŽUUÑÓÓƒïü¯ïàÔ‹N\Qæ+™L"—Ëù%ºR©ŽÝs gþ¯3ñýǾ·ámþóTšy»†m“ïæÝ¿Òûù=·E‚&”xéíí—d{M •={ö ‹•LÇ, X¿~}É40¹`Qµ€êììÄ®]»0>>Ž7¢£££âÈ„b±XÓÚ,DT•b³··—ñIŒO¢æ"cVŠÅbذa …kÂ5ã“(ºŸDÇ~ÛÚɵQ4ur9¯TJ$Y2™éŸc¶å·`£ö(U’ÇŽÃ_–ü÷Ú÷k¡@ÌJÉf³PU™L§§NLJù®Ù pÀððpÉ󘦉+Ž_×-y^u﫦N€€‘ü° !Sé0ámÿTÏ÷€¼/.ž'9Ë÷sj.ùUž$) èêê*¹M&W¦200€;w–Ü¿³³ÓÀòŒÑØØØ¢_؈h!L›ŸD Äø$jN²üCXµ¶2- Æ'Qt1>‰‡ý¶µéîë¢bf 1yvŠm‹‹Ÿ0q JkÕS|fww]¶mòJk…}áØðÌ'Ÿã8°mŽã N#‘H@Ó4¤R)躎•+W6Ùà/0–Édðº×½Nü¢aúY4yï>ÓìC2™Äƒç?(~ѧy¾ÿ²"+cë6Ö®]‹µk×ÖùÍÔ”Pioo/™º¶wï^(0>>ŽÑÑÑŠ˰¿&¦|Œœº)ë‚¢ÌX±XĆ æmç‰(0Ul`|5㓨ùÈ%áØÝ»wè$ŠÆ'Qt1>‰‹ý¶Ó“k¢¸n0;@É"í’®—%YÔV¦«ê680Mï^÷îŠ ÎO’ ŠõKòù<’É$L³tAÚiƒëº%¥¹r¹œX¿$DQ,;¸¬¶×õf“”'pJ$Ä?ù|Ùl°‹ëº°, 7œrƒØv'_2Ë&ŸÏ#‘Hà¶mÛðĪ‹ñØ]!™Lb÷îÝ(üCº®#ŸÏÏý ¯ ¦’_ëׯG>ŸÇ¶mÛ‹ÅÏç‹ÅüQãããèïïGGGÇ´S½z{{±wï^ºØÈÈ6lØàסíëëÃÖ­[ÑÕÕ…‘‘ôõõq$Ѩ›ã“¨QŸDÍ©··£££%±ÛÛÛËõˆ"€ñI]ŒO¢Æa¿muª ÄãbÁyE •øRQ½t•Žê‹È× §§©T œø žüù“Xæ,+I4X–…|>ÁÁA‘ÐpdWq‘J¥J¥JŽãà·?ý-®¼†n H$ǃÅãC2™ŒH ¹˜¾ä˜ QÒ+'¶9CQ†!Ö\1¼ÇkÀ7}ŸÿÙ爵VdbÅ0 \õ©«ð5çk°, †fàÀñïóË‚•¶°Æü2N:ñnüú2ÎþíÙ0 Édmmmu/YSB¥££7Ýt¶nÝŠÄb1A¡B¡€Í›7£££;vì¨ú\»víÂèè¨?-,<Ê ··±XÌ_‡…#ˆÎt± 0>‰‰ñI}ázïÒöíÛ§]"š•b`|Eã“(zØo[Ê4EÒDæzzÄÌ9KÅŸ¼a×ðdæ”P‘ë™ìÛ·ð«úNHœ€5îÿ>ŽãÀq¤R)˜¦‰¸ÇOwý/„~“Å«?–Íf¡ë:Òé4t]Çå¾\ìƒ ‘Œ©$çý+ˆ¯@Úü/›ñoÿGté]@Zl·®ëÐu®ë"™Lbhh'ýÝI¸ûš»±vÕZ,Û³ CCC~™1Çqàº.öíÛÅRpyîrôôôàðy‡±Ò\ K±ü™3áY-½'žˆ—~ð¥@Ð4 ™L_ùÊWêþ¹¨)¡ˆ핦çtuua×®]3ÊôL7‹e±$QU[LŒñIÔ8ŒO¢æ´Øê$Š2Æ'Qt1>‰‡ý¶|^$Pär!Ž#,Ù¬¸M'j)çUK⥂t: UUý#ù|ö¸·w½ÝO¨ÈYŠ¢@Ó4¤ÓiXrç=vLÝÄ[´·øÏ—J¥H$ ª*4Mƒb*Á,›2–eA—;š0QÎKlÛ³MBÛùŠ£¯Àío»…l ضíÏLDɰžžì¸gv>.ÖìùXûÇü…ïÇ®ëþã$MÓð!÷C8é?OÂù!ý×>/–gñH·¼'¿°'üñ"\‹ïMøk¸Ô[Í •b±ˆ;w¢X,¢­­ †apĵ Û³Qt]$V\WL|H¥ÄÚ)º^–PQQ[2E­~—¶_µáÜ?‹'ßø$‘Ü'ÇmÛøÄ‰ŸÀþžýøýÎßã;ÙïÀu]?±!}pËE"EAÉöåÉŠÿþöãÛ¿þ6Òio0ð‡£€ã8°, ¹\®ë¶m|åÙ¯àÃø0Šg±Ü^MÓ`Û6Òé4Eã8XšZ 0.1ðƒÿ/¿xÒ>jš´‰íJ¥RbaúÌï÷¾Æãq躎%‰%H) ÑxI¡ñþqœ0vîxÃp¥|LÏü}>N¬õŽ›7oF¡P@gg'ŠÅ"6mÚ„b±8[FDDDDDDDDDD´€%H˜¤R€a”&Q††Ä}|)ˆÓQ½ûMS,NcéÒ¥XqÞ Ý@$QQê«»»š¦á¤“NÂ~ðœóä90 £¤<–φH¤èâßl6 ×-ÝÇqðä“OâÈ‘#øÀï>€¿øÅ‚¦iþ6ÈY(±½«S|÷¾ß:é“Ðu¹\Ž#‰×4M¼ž"f”^q§}ó´Ê;«•ý¿Êû'gÉ@p}6Èl8cì ñ42Q$ߊ|—ÞqGý>žšf¨ ‹EÜyçhkk j ø‹Ó539;É B‰¯’ úú(.€,DbÅ{nÛ¶aYR©\×…¦i8÷عAB@.—óÿoÛ¶Ÿäh»¿ K–,ÁÁeq¾{¾˜éQi» ^óÁï<ˆü_ò°m»dÑyÓ4Ñ»²Y;‹{¿q/.>p±ÿºåIí"/¿âmøéOŠWZßÀiW}PU úk²À?ÓdßÄ>¼à—/€ö÷jo…g£ÄQ2ƒ¦„ Àý¾Æ¾œöoÚs倎Т6GÀç¬XÕ†gfþ˜VÍ3Tb±˜ŸL€õë××ySˆˆˆˆˆˆ¨Qxà5Þ """¢—ÍŠ@¬›âֲȼd£úz.ü¤A:F:ÆÇ?þqÜrË-ˆÅbX»v-TUÅÒ¥KÅ X–…ÁÁA†+VàW¿úŽí86©TV>Ÿ‡izS>TÀƒíÄðð°ÿwÓmO~D”»8v±¿0ý¤/púÊ`éç?Ëüc<ý÷·#Á›”J¥JÖyÑ4 Žãà·ýgrVÙ{áÿÔ-ê©yÛXq†ŠSá}½À—K¦]õëpþƒç—Þ¯0lÊ`>ÔœP!"""""¢Ö’ÍŠNÓ×´wÜqi£7‰ˆˆˆh^YVЗ/¹nDq±ø|Í⨺>ÊøIãxä“àî“îd2\tÑExä‘Gpß}÷áðáÃAɪ ³],ËòK€À)Ÿ;çž{.ºîÒ¥÷uÉd»ïÞñuãH§Óxë_½ †á—ëéémÛ¸øëÞ:'Ó­sSñP+Œ—ÇK(áÅçeBæ5ଟ–%T²Yà¬8š}ƒŸ%+›¦¢TØM¾¯ùªxì±ÇpäÈ‘ÒûÙöé¸íµ¯Á¬ *DDDDDD‹€º8w –%~2à9Ï9ÞèÍ$"""šW–%ÚB€h¥ÓÁÿgf³SLÓÄOŸ/I¨ ?~Ü¿¯Ø~‰D€HØüùEÆ«ßþjÀE]äÏ>‘lÛž\*¬Ré-×¾¼îI¥2g*ü’eËï¸oþÎ{±ú–[‚¿çóâÜ\öºWhÀ?—MͱQù}Uƒí”Iœƒ–$t cÒþÖKMk¨ÀÈÈ6oÞìÿ.¤-¹ß®]»ægK‰ˆˆˆˆˆ¨&¦):2^¥ƒtZ  ñ¯e‰…V3¡jëÖíÇÿ¸ºÑ›ODDD4/,«´ä8â'—m¤|¾´mTM:F×ñ.<ùä“x©óÒ’™*Žã P(àúë¯G{òV>¹HÀOd|ô£…ã8H$¢dV€8¦˲Éd`YTUE\.äJ&¸ª %¥xûfÁuÝ`­GGrg2H.¸Ávb‰a¥‰×»o(wÓ^¥—ÞˆÙ#¿v€O§Åb3ºwE¼±ÿçÙgÑ÷ÒáÿüúË€û÷¢L—¢x RC¡çÊÄsz¦~£m;˜6ö%¬$¡ñüK¿¹´ÎŸ g¨´··£«««ä¶ŽŽtttÔ}ƒˆˆˆˆˆˆhö\W$PL3}é8"yÒÓ#®cóyq]š/¸lÙ±Fo>ѼÉçE›(?Ž zKr¤R€ªVY€Þã8²Þ¢+À¹sÒìŽt:w¾óx÷»ßU«Vá§ý«‹+™L/s£ª*t]÷Ÿïàkw †a —Ü€HXdÄãlÛ‹Ý;bƉ¤•×,ÓÅ}EëMÁñá’a &ÏR±,àEñÉ3>â¾®ˆdJ2)¡yˆ™%ªŠw_~9~õì³À•à{ò1qñf—'DX…©gÈ$ÁÔ! %Ûr×Ê»ppÙÁ ¸à¿.˜Ó祒šf¨tvvú3OŠÅ" …‚?C¥££6üÿí½}x$U™ðýå3Ôˆ0ˆ¬3 P%®"RYVAgíëªÌì:ݺ:«F»WPÇ]·[ó®Îê+v¾Ã.úHº”UVaÜ”ºàCÖ¢NDÄ)"Â(L‘ð5€2ï§NUu§“t>»;¹ו+Iw}œSUwûœûë⪂õ‚ ‚ ‚ Ââ’Ï‡Ž€¶Z0Mõw±¨æµ¾¯ (¹\ì4¨Gm_;×>å”=<÷¹¡"‚ ÂòÄó”NäºJÚ½;þÎq¯R.—)‹ Îøò<øðƒ‰sx”Ëe.¼ðBŽ<òH6lØÀQ£Gñ‡—üŸ_ÿójãHH.—#N“ËåøÔ‡>Åå{.ç•_yåŠ`X¡qÄ„GoyÏó"#‰aP{š2X¹:X/•—ïCÆ‚=u¶Mði[)›ÝÝðŠ :äåãŽÃ:í4ÈÔ1ÆÔKÖ—‚OøðùšH“|“(DCÔ¿'ù$G¯;zòñ.öyuï?ó£÷þSc7µANù000ÀöíÛéèèˆ"V¶oßÎÀÀ™L†Í›7/hãAAA„jŠEe$±,µÊ8’ͪÏ]FFԢğ۶ÚÇóÔw¥Ò, ® ‚ ‚ ´1¾;—hG“ä}¡Pýÿt8ŽÃÈȦib¸?8ç<ï¾çq‚ßÿþ÷¹å–[¸þúë©T*twwó“×ü„Ë7^΃kä$ã¤IÇ3 C¥âráÛ|›Ïõ¹é`Å*)+Å7?ðMrÿÃqEGò¨Èª+Q{dºãNª[22¢"JÌ:Û§Âc&•ÍJ¥oWk@©w‹9X›øÿ›yxCþÆ­¶|AœÆÌ†³:Îâë¿øúäã]`òØÑqôGCOc÷µ6¨ 088ÈÖ­[éëë‹>Ÿ˜˜`pp1ª‚ ‚ ‚ ,Å¢šäëô¦©~»®2Ž”Jêo=wM¥ÔO©T}m€±íÙ·AA¡ÝÐå7‚ ÖêéAS<Ïò,•V+ ÐõÉ.žýµgã>îòýïŸ3Î8˲¸ð ©T*<û¸gsô™GsôïSbM>®išÜ{ýªø|N/¦iâû>cÇñ‚}/à¼ÌyäóùÉé¾4‰öSÈ ú•¼Ê€Qõ’ ?Ï .red©½¾nx~Ý´!ê“ Ïe÷Wûqª¯$ ƒÊá‡ÎÓÏxºîá‚c9í‘Ænlƒ4dPeûöí\ýõtuuU}×ÑÑQÊå²TAAAˆ PÑ$®«&þù¼rÔ)*Âz¦@œþk&,+®­"‚ ‚°œq]¥?éèÝ…ˆÎu]76Z„é·N=ÿTþðÕ?°cïî¼óÎ(zPÅäóÀS(ƒ…‹2Ô`Yû~¾/®m¢ S`YÙl– xÇùïÂTs¨ô)€IDAT_SaEŠI#Eí9\”á%ÓÀÅ0Tÿ£m§Ò1µDŸË™¢o™š~ßïÁ¾}“·K¥;óõgò“Ã~Ò@c††ŠÒÓÓÓ3ɘ’dóæÍLLL0<<¼dAAAXÎèÂò:M—Ž,)•÷¢¬E]AAXîh] ”>ešó;ž:¦£Œ$ \t€Þ÷QöìÙþ} £H-Óœß0 öíÛG&Z'¦>†­¶O¥RxžÇYÎ_E­¸®[¿ QäH²€ý$´±bªãT5:¡ù„Ö£Ý×mƒ@Ù ®A—J)û€iÎ>:å?À#_¯.h® *¾ïS,ùÖ·¾Åk^óõ1Á iPÑuTjñÅC 6”àU½“Soé(ŽèØ>XAÂ_RÊ¥.´7ëN\W½Y­$“òn0Æ Ÿé!ºöÉtuúuO¦Lg¦·K+ŸŸz[‹%7¨4”ò«³³“Í›7³eË2™ }}}tttÊ£ \.³}ûv¶mÛ6íqÆÆÆ&··m›ÁÁA6oÞÌÀÀÛ¶m£§§‡ÑÑQ6lØ@OOK{Ua…1“l"Ÿ‚Ð$D>¡µdxx˜;wF2©Ù’hçBN»\Vi'ÜÐi°TRþTjîçb¦“Mù„f"ò)­ÉrX·u]e“(—•AehH}>ɘâ¡ögˆþýÖg¾ÅK_úR¾qç7Èd2†ëºlß¾ÞÞ^vïÞ­ô]‰ÓnÙ344ÜgÒvއ'>|› §† £øÜ¤ÚˆàyÊèðôƹF\p¾¯^÷¡ïî¾êóæ¡š¶¤ÂÏ ñ~ÓK‚°O3E 3GoS²À…>|o†ƒN“•줻î‚.SÒP„ @?}}}”ËeÎ=÷\lÛæÜsÏåÜsÏeçÎlÛ¶õë×O{Œ±±±IÅíׯ_Ïøø8ÃÃìZµ*Špéêꢫ«KŠÜ Â0l"Ÿ‚ÐDD>¡µY·n}}}U2 "›Âd²YõjÎkÛÊù¯TR©¼ZÂÌÿ­ÂT² "Ÿ‚ÐlD>¡5Y붆¡tªb±º^œaÔTf\øw]—‡zˆ½{÷étß÷1 ƒ³Ï>›Jm81(I#Q0öçwØQ£ÞcOSö€râí•sx‘WùŠøózµLÜù ôˆÆtN]å™3Y_¦çu×^;¯ýëѰA”Qå;ßùNd<éëëcÇŽ¸®;£1TÑú;vDÿOLL°sçN:;;dÑ\µjÕŒ9ùöìÙæM›üÂB#lÚ´‰o¼±Ù͘7ÓÉ&0gù¼ñÆhv÷„eJäóy<ÏÃ÷ýØøÂ¾À…^ÈÞ½{›ÝÌy³ò¹wï^6mÚÔ’!ÚÂògppxàf7eAèêꢧ§‡U«VU}.ºíÊ$™âÚ÷UÚ ÏS9»õwÚ°¢ ck£¸3|ïQëÂݧÜͯݼ ¸€L%› º­Ð~ŒŽŽ²iÓ&öìÙÓì¦, -Ÿ¢Û Íd9é¶‹¹n;::º$}(—cÛÂŒÎ*5úPÑÚB>Ÿ'ŸÏóºç¾Žƒr0¹\ŽT*E¹\&•J‘Ífã5ˆdú-y2Ú.bG~$)•à/ÆØÕ ²˜ËÁïþâ»ß?«—VË4yü™ÿν7Ü;ù»ÞÞ0íXH½6N×·LƒÛ6RÏÆú\ÈõÎ>W[ÈÀÀ£‡>§}§cV€ŽŽÖ¯_O?ýýý‘erlllVÊåÎ;£Ð°¾¾¾ºEï ;餓ª„]4žW¿nSߟœ†p6ìØ±ƒK.¹¤Ù]]Pje˜³|^rÉ%ô÷÷7»KBâ8½½½¬^½ºÊPJÉéîîfíÚµ‘¢S.—I§ÓäóyŠÅ"Ÿÿüç¹çž{8þøã›Ý•e¡äóøãgÇŽÑ1a)éë룿¿Ÿc=¶ÙMYTD·]š¸k²YåXè8*W¹¬ &ɺ(†§ŸXP´N›¥ÚcTº†,±7c1ü¼ ô†¿8ùê“)þ¦ØÀÉÚÑm…v£««‹;vpÒI'5»)‹Žè¶B»±\uÛ…^·­‘¶Ð‹aj¯‘w¨IOU,éîî¦;,Â’ËåèììdÕÓ«øÚ;¾†aÜpà |æ3ŸÁ²,ìÈ;†êH—úÎ+©šíÊL6¾ØöäqЬ PŠå-|#]][Ä0Àá¨ýïÁšÎ‘JÑñä·yÅ7†1ÍDƒôir_¥CæiÌâë™Ó‘cæ´hW[ª_¦ÙÀÆ“Y,Ùl0¾gftž½™̉‰ ¶lÙÂØØ[·n 2õ<ÆÆÆ–Dà„ÖÀuã"QSÊX:]ZÏSÛ¥Ó*¼¯PÇšêû±1E^íAv]õI§Õ¹2ZYÛ”©dD>…¥Áó< ÃÀq\×¥T*áº.½½½¤R)LÓÄq|ß'•JaÛ6–eÑÛÛ‹çyX–…išÑ÷®ëò»ßý®ÙÝZD>¡ýÙ\à c6«tËTJQ*e4Éf•^jšqêëÂl<ýfÂ!N­Ð ì&žtw£&Á¥pÛ jB\AMtó¨Io5¡·€<ô¡‡8üw ïÉ×Jˆ| Bë"ò)Í¥×m=O­Ý™Y(ìžac µ¨Ÿ0|ø¾ÏÐÐP•1â¶·ßÆ]'ÞÅ·¾õ-®Ê]Å}÷݇çyÕ†Ÿêz()ꧾʣô2#цzuTjÑF—J±,á¼$f'ùÙ•KFXýÐê©gÜй†Õϸ_õ#àÄ"d¥ÄÖ’A霤éÊ„ýld»FйÚZlQvÁ *²qãFÖ­[7Éó®««kRxæøøxK6&ã8ê…5ÝÄÐ÷ãÜ…SHóùØ€Qo;=Iõ}eL)'T|_?´×ßîÝÊø¢q]õã8jR›Ë©vúÑÇ0 µŸe©í u~ÓŒ.z;×…ßþvyxÀO%› ò), ®ëâ8Žã`Y¥R)RBòù<®ëb–e‘Ëå0M3*úæyù|žB¡€išU Žïû˜¦I¡æE?ùÉOšÝíAäSÚ‘Í•6¢h‡ÓŒ£O´.© ,µ©¯çvBâBžjrk£ $)”ç šp§PF–"Êh¢'·ÚÈOèKñ)þë/ÿ‹®ç¶ÎâÈb ò)­‹È§ 4—v^· ‚pÝ®‘ìP:2%iñýI‘üÇ?rQp'ý×Iü×ýÇs ®ë’™n?¿^;Ìší)¢u¼±²é×9^Èê‡VsÊžS¦=äÿµ_ιß=—W ž ¶7_­Ô_¸M…}én ­ÊÁ§…¸å’KX»ÀÇ\RƒÊàà ¬_¿¾ªhQgg'===Q‘£žžFGGãâ‹/^Ê& !:]ÖtùËeõcÛÓGGx8Nµ\jC‹e©cärêxÚ°âºqîiýž2M5õ¼8¢Å÷•ÁchHMVµ‘¸vÒ긹\õw:êEkhH¥dH¶µTRçÐÆÛŽÛñûߟG:ý`³oÙ¼˜N6E>…F‚€b覫 ! ¢NÒé4¶mãy¹\ŽR©¥ôÂó<<Ïcdd„µkÕ0—TNR©©Tj’ÁD£ .Ë‘OAhOD6—/ZwL¦îšJg.•”~9Ç´Ï1zR®"Ú OÚu¤IŠº†lª= §0ðŒ?{œåŽÈ§ ´."Ÿ‚Ð<Ú}Ý6Ò·t*¯éô/½M‘j} "gO×u¹äS—pì—Žå™÷<“KŠ—J¥&S,ª ±³K’Ú”¯*zxè^«<鳟n›ì“NïZg™äп>”f^8å÷ ÖQ¾uâ·øëoýµº/,L}½Œð¼:Í-;×ÔÌX gzö>ïyímPclllR¡ÍÍ›7G5Y¶lÙºuëØµkýýýttt,e—=º0ætFÇQ#¦{Ö%÷÷}eø5‰tœÉç5ÉtÂh1˪®i”ͪÿkSwY–:¶ãÄçÊd&§Ëåâ †QmHI24¤ú’lG-¦©Ú`ÛS§³,µMÄçÒFœW¿ºý'3É& ò)LIôööbÛv¤t¸®EŸär9òù<•J%Ê1š ?›ÍFaµ@´9‹ü˜:ªe¹"ò)í‹ÈæòÂ÷㈓FSwé,S5éÔ¿“Ÿ{áo›8—~¦#Nt”‰^¨­Wš<·Mc¹ªW"Ÿ‚кˆ| Bsh÷uÛh!@ ¦ÑÁníº•±Ž1.ÿÞå”ËeÊår´®àº.©T ß÷9ñÄÁ†cŒcÚ<4©Æ+ t6—Øx¡ µú]/“*)`«[½P[/jÅb²‘h ½Î²,~ýñ_sžžÒ§¨Ý÷È!ðó+ÎyÆy“8õ(ÑXôÏBcÛ±"Þ"4dP®²LÖcbbbÆãhᛊ¾¾>zzz‹×U†‚ryòóªóD—Ö[lj#6ÒéØâ8Êð¡'‘é´2FxžÚv¤N‘(ÛŽÏ1]ôœiª6Ì$K†G¤L7™mdBœ«™ ê´‚—\r Ð3óZ˜™dD>W*¾ïã8år™Ý»wW}žÍf ‚Ïó(•JU^étÇq¢Ú'ûöí›tìT*åMP|¿‘˜×•ƒÈ§ ´õRò‰l¶7º&_¡ th5­‚æM/ñ$Û'6†Ä5MʨE]ÿÄ&6žT˜\ÈT˜D=Ù‘OAhD>¡µhçu[ßWëÑ²Ä õ>~{ÕoùÉêŸð—øKŠÅ"###ႪeYQšò(5X¬‘YXR(=m¦ÒeØ^„¯'Zë%à(Pmh±™2Ä4MÌטJwœ† xêè§”NÚH?¥§.µƒN9 ÇYÐB„ó£!ƒÊØØ£££3n—,’;WZM ÛU’ËÕ7Dxžú^j ªÅbl`Š :J$1Rª …³¬Ø“ɨH>+iÄ(Ô63M@‡†hˆF “Ú¨"̑ϕC¹\ŽŒ)©T Ã0ð}ß÷±m›l6K.—‹"Nj©T*Q±øÜ4X›Æk.‘&–eMi„yä‘Gš})— ‘OAhMD6Û—rYé‘ù¼Ò“3™¸®^ÃÃU€2ŠØ¨z'ÉaOG¡dˆ#N ¨Ù  'ÉE"Õ^eO½ ÔEäSZ‘OAhMZU6ƒ ‘G×››‚|>ÏÅk.æ¾=÷ñ»§~Gîç"cŠçyÑ:ˆÚ˜8Â#Y®êäu>Ó5îf2¨<àÁsFTÍTzfÐÎé:ýëT˜5¿ëày'¼ü„ÙÕriVÈ<²’œùƒpøÉ'/hs2¨ôõõÑ××·¨×E¨OÀÚµÊ1UĆN{54¤ µ‹Ê R(¨í’5G ®¢ °ktú­|^½”jkh uL}|M­áež)ïAXÇÁ÷}r¹\d”H§ÓX–å5M“l6K6›Åó¼ÈbÛÓ»%˜¦I¹\Ž“Ť^Š0Ã0xøá‡›pUA„vCGPëáÄ÷ã´²IjÿŸ„žÜê(“ üÌ ÿîFM’SÄ)ÚÃPOÖëÃ`²ç èÖ‚ ‚ @Mè!”#Ë8ŽC!UàÆ¡y÷ÞwóÌ7¢ï è_¿µÄÔŒz%“S±Ö#£™Îh1UºØzdˆëïÕ6/ŒÀ1MSm×HYÚf¥ŽÕ ßsä´ŸýŒG^ñŠmRC•‰‰ ÆÆÆèêêZÜ ´ñ¼¸ÐúT õ£1t=]ì]§ËJ^º»Õç:êâè‘|^}V(L][Ô¾3Eƒ´P;A@‘w]˲H§ÓxžGd2™I „ŽPÉd28Ž£B_g`.µMæ¡bšfÝ<¦–eñå/y‰¯¬ ‚ÐN$k깚®8mV]b-£&ïz(󨟳ºî?•Çb£Cáò-&‚ ‚Ð0z3*-§®ãI¸®9‡žp ô<Ö.V@¹\&ŸÏW§4×K >“£5Sétå°Ú1•3L@©„ç©wÌ 3¦2«bšÈ“TUAkZ[¯œgZø½Ï{G-p“2¨”ËeFGG«ò[ Ð×××’a^퀮WR,*ƒE=GoßWy›GFT‰eÅF×­N9 å\6²Ù©ë”€²Ú6’ «…ÒÓ ‚0Ot/†K×>±,‹r¹L©T"‚º%–eQ,ë{jLeYx^#n1¶mϪ =PU»EAfC²¾ ãÄÎFU‘Ù>qqøhG”ÁDO|ËáÏÊ`’,_‹¤¢AAX0t픪¥Œ:F‰|>ã8*-¹Æc‡v8¸Ðífhhhòú‚^ÒеíêᢢEj—2¬ð;­Cj»@ml‹8’dº%íÜ`©`ùè-æÉßA¥Û·o§§§G *sD§æš*¨ ž–cËR“=ÛŽó9W*“#KLSS`zcˆJayâû>†aÐÛÛ ¨%ºp¼ã8d2™(µ—.´±Qbªô\s‰61MsÆ´` qAA˜ é°VI¥¢æµÉt^UáŽ<ÙøÌGStaNå5X/5— ‚ ‚°(¸®Z'­ªÇ\@éoIcàºn¼NÀöŒsËÜB¥R©ïÜ© :ÍV=jÓoéè\¡zm,)«½Ü ª£W¦Ën¥k³¬4–‹AE˜;: W¡§H’Ï+ëj*T #Nï“ë“ht1y©W"ËÏóp]—L&3ÉøÝÝÝ€2¤è¢ò "?R©–eáÖ+¶4¶mO[\¾Iƒ ‚ 4“b1N‘ëºJÿöý©£¹X‹š´º(Çd!Ò€xâ{& ‚ ‚ KBÄÎèÑz»‹28Ô¬›‹ElÛŽÓ—çþ+ø/NúÏ“°¶N±v‘Ôï:øIg×(}«]øª vèUcšqØLÙTúdŠ8­–ãLVB͸MÓê”9T”JÑ=ä–K.¡çÜsô˜bPYbt‘$mDñ<5©Ó#årllIbYj;†`*$òD–/AN§I¥Rd³Y* WZ×uÉçó‘!e¦4XþrP¦ÚÐRûàƒ6» ‚ B“Ñæ³Yؽ;Žæ®òP“oÂËCQr(Ç jòj£&ÃÉ l )/¢3ËLº‚ Ë×Uk¨“|?uª­0¢X;› MΕåy©g¤ªg’$S‡’‡O_IXk‚>…ÏWª÷ËdÔ"oª Ž¡uÅbQ5º6;ˆM\GeºD:š¥eTiV¡ø¥¤»nv–+ÚP’¤\V–SˆŸÓ¬VŒ´\բ맴à3$ Ô{4¾¯zAø¾O6› Æû¾Ooo/ét×u)‹är¹ºåëáºî”é½– #‚°²X»VK’ºu¨Ô^¦©tì|^Uvï#Á˨ ©.ï¡&³.qŠ=‰Öž€Ë'µ I}}1Œsèötwï~õª%¿.‚ ­J²¦ô$L¢îº}ÕH1A‘œD‡3'—#uÖäópR ެYÈdÂ}^|ì"jq¸Þš6”¤‰ë©LEŽúEë—+-¸¶Óp„ÊØØUŸíܹ“áááªÏúûû›Ý§– ®¶–˱•tò6M•ç¯X åtŠg¤‘ò‚ ,-¾¯d=©jÌ´m%ßA ä[‡ŸzÔ¦íó}ŸsÏ]ͯ}Ã0¸êª[xâ‰;øÄ'¾ÊYgý‰‰‰=är9R©T˜0…çy†Ág?ûeŽ?þ¤R—5ÔnÓ4ñ}Ù–»ÁHAˆ)—ãZ(Ž£þ‡x¢­Çåü{‰ó\ë¨5YÖ—êz)“•5y„eŽëª÷…eÅ:û¾}ê»°!™ÌÔN¾G¼é=ÇQkÕü=“QÆ]³©TJÔ N¨âúüS¥ïö<µn°yó‹›}ÙAZ†l¶º^:âƒ0 ¥ö嚇߯ÿú|°¨Rs¥RqýßWÅ5#D¡ÉÿZ+ÖGÉ©7Àõ $FÜ8]Å@- MµV‘C¥œIß4ÂmdÉ£i4dPéì줳³“ÑÑÑ賞žÆÆÆšÝþ–C×9ªöj1Í©…|õj¥8Y–D 4ß÷ëžV4ž7ÙÀ© C­Ž£¶Óã¬ã¨1ÕqÔ¸:4¤&S¥’Ú7›U¿õ„Ë÷cCËúõìÛ÷9¶o¿û«¯^ËK_z3'œp>ú##†:O6 CC9r9x÷»ÿï|çëÀ%UÇó<õSÏ[C ‚ Âr£XTQ'SR)5–ë±ÑìVA&Q½]@ÞFWLT„Je6g¡ÐNMž§Þ ™L\È8—S¿-K>‚@½?J%µ}6«ôÿb1^ËfãºL©”úÎuÕ±òùx~¯3TìÞëñ¥RõþÚùʲÔù‚@ýíûñ÷zñ¬gý¡Ù—R¡eÐi]«0¨JÍêû>®ëƵSBüq‚Ïe9ö”à ;TËå8´¹RQ‘Ì—†;™@¶<´çûT%zQIŸÚbjcŠn{‰ê¨˜©e̦ÒA¥¯¯¾¾¾f·µåÑ^%ºRooœZ@+Cõ(”&kœ‹ïûQîDÓ4q‡ Èd2u nA@>Ÿ'•JaÛ+!1¡J–{{•lj¯2ÓTaöZV]W}¦'`úÿbQm££SLSmŸÉ¨mµ‡ZÀèèãü-Ü~û÷Ø·ï9ýô{ùÊWþÀwÍ+^±˺’óÏÃ8‚bQµGOúGµ1®¾D&sHUԩ몟ZƒÊJ§ê¼µÇ ‚ê÷–6*%õ”z†}=å'‚ Ì=NëÑZ'ˆBA1U㌇2œäP“ÕnÔdX;3ém‡¡MÐ5Fµü;Žú_OÛ.?ï¼ðS9ÝÌäé^²L*z?-&*ò¤#ˆÔåk fU”~``€‰‰ ¶nÝÊÀÀÛ·o¯ú¾³³w>‰AÛœ|>VÄ V€,krzŸ$I° ø¾a“¼ï=ÏÃu]Ê¡»¢išX–…çyQAªîînR©†aàº.N¨ùêâÞÙl–¡¡!‰dY!hC„ãÄÑ'…Bìͦ=Êôd,âhOm<Ñ¢©Øv@:%•J‘J¥0MeL¹çž‹¹ãޝóўŋ^´šCãU¯ºž .ØD¥bÐÝOò´±Äóâh·BAµåg?ûßFœ~LOÞtÊOý.Ò“¶ØÀ±Çª:¦ ùŽÒ) ôyt:ƒä»Ê÷ãTZßГZ]âIdò³bQí×PÆ1‡8 ±AȬò8™B‘~øáf?N‚ £½¿óy56é49šhLÐNzÒ›#öøÛ×ì^‚0Ú¨4&u>ÇQ:¦ŽNÓÎù¼ÒÁuý¤BAéžÉÛÚQJûÔéÏs¹jÇmHÑär±î_o_;÷¯]—«}WÕ®XVåR‘h9A„*ÒieÈÖõ¨ë­)Üwë}ôƒXc¯á{ßã+g}…óRçUoä8¹.ÿàŸ¡ *úR{Äze#é·rL®Ó"´- T®ºê*nºé&2 ­¡§§‡­[·288ÈÎ;Ù¶m[³ûÓ4tñîD¾eËRJ`i6VËJ‹EŠÅ"»wïnÈpáû>ÅbÃ0ð< 0M“B¡@±XÄ÷}U\ eD™2ÕQ©T¢7L”«½uäJ²}¶mGµ+\×Ë2D§êKN~´¡â¨½]r‚§Ó$#Î2H§ÓX–E¹\&Ž=v;w>Ÿrùá8ÇðÛßÂ;ß ž×É!‡¼‰³Î:+J+¦ ½½±7\•*à‚*Ï<ýšÖÉR)N7P(Àk_{"¾ÿ'>ö±3xôÑj¯=ËŠk6iE§/Ð^~:ú¦TŠ#Ú¨¡ú«Þ}ʘÜù¿ƒ‘_Å×8ý:ùgÆýd }DÞÂù·CæF0ÿCýàÝÅÁÈ'LìÅ7T JߢG¶ çŸ~³)AaÐé3õ8µv­z×g2‰ µªƒ¢ ò>j’›eù§òÒJCm© ´A ävddjg½vÒNNÉï …ØqÉ0Ô1+•8’C; íÞ­ 'zNÕ¶ª–jIMã¼Ά!©ÀAjÑ)uMwèÿ¾þØÇ>ÆK~)G:Gò…»¿À¯ùïÉ9ŸâQ¶&ÃAR(ý1ÉT>l”¾©×{ËágÓc24n¬ZžƒÙhtt”ÁÁA®¹æ6oÞ\õ]gg'ýýýôõõqå•W6»?MÃu••4I*%ŠÐLxžÇÚµkI‡.ñCCCdµLœrËu]º»»éîî&N“N§éííŠj FFF‚€t:mÛ 122ÂÈÈ•JeÚº¶m³{÷nvïÞM¡P •JUõßù|žµk×R Oåóy¾öµ¯‰ü2B×EI¢£.4:q-I£‹ö˜xõ«?ŽeY …¨ü›£ˆ& Ô1Ÿzê^ûÚõ&¢ˆ´Ö²PƒzSŠ•Ëà_¹ý`Ÿ†”]b$ç`Ö“Çž8œ‰‰gpôÑG“ɨmµQDoìâ»â´ &¤Î?+ã‹ç}d|¾¬Œ(~Ø®Š ™×Åý2¯îà{q*ıýG(nÓ“yà=CíS.ƒû]È>¼¿ƒb˜æÌý"Ø/†àê¸f•ïyðÿ!ÞW¿FžûÜç6û‘Aæ€^xíîVÿëñÈ4¡d+[Éîݱ÷¸á£¼þ<Ô—Tú®Ý(À!–oáN× ¨vw«sÍñ)‹„®¢uWˆ#ºÓiõÝÚµq*]ljÓbÙ¶2Âè´ºét\ÿ¤PPº¬..¯kkºR‰çäÉô`ºfI+¢k«‚ Õè,!z arÝÛ€_õK^}Ý«)‹œvñi“ê‘äóyöÞx#[Óߪsª£Ht½½ZRÌ-ÚD|²— E¨ÜtÓMôôôÐÕÕ5å6›7o¦\.3:::ívËZ§¯rYýè<ΚVUК‰ŽÉçóQ1øJ¥FŠÅ"½½½øáD0•Já8¹\ŽT*…뺆Qµfhhq_†A©TŠÚ¤#S‚ àæ›oæYÏzV³/­°@Ô›\io¶8wq}ÇO¹X,âº.{÷~‰u뎤Pø øP*”ÀP Èe'Ÿ[Ÿ?• ϹrŸÖ…Þ|.Ê"€@G<Œaõ9ÊsÎ0Ô÷ÚÃbh(\[qÁxL5þŒ3ŽR^vÝ``ïŽk>eÊàýLýŸË…7OëzuÎbÌK!u9ä?§@Ã*ÊñBO˜3÷ƒýzÈ~¬óÃÅ/¬`é[ (ý9ªv;ÿJëÁûäwƒUÞ®ô™Ìß÷1(oã|užü”¿«ÎÉ@êuü¦ÙO“ ‚0['Žr,•âzºFY©„ÊA3 .0o¡Æ ]'e¥à8j%zhH)!IOAh:‚Xë²½½êÕÑd¾¯ì~ZgÕéjuä‰þ[Kÿ­ÓléÈèdJ\]ϤI( ‚°?ôy®}îµ|øÓŽ¿(Oq2]ƒÏ ¦“;½®ã!Æ”FC•õë×300ÀÎ;Y¿~}ÝmÊå2ôôô4târ˜8µ¿¿?úlppÖ­[Ç®]»¢Ú,­„e)eO§ùÒš—år9*šËåBo{§ª–¨9m8Éd2Ñ̶mr¹\d€Y½z5™LfÑÒp ‹C=Ù„öÏÅB§âJʺ–ƒR©„mÛÑB…eYj@uࢳÁ4Q;”ˆe~æ- þ 5Q¹:uøh1ÜF? ½sð]TÊXp¸žÃ€Ô—Áºe y7Lð¼€Ý~VPç°žëIÕ–Üÿ£hc¢í…W»Ôg…¯£Šý&·É€ñ^pn^æ³þVØ7—ØËÃNëOª¹w@þãaÿz‰ò•š—Bîp°ß¶-Ö ‹ UPýÈ]é/WCÆ€~ôÍ~|‘OAh/´þœdÇŽ ëËË]ËóÔ¢«®¡ÙzQãS)üÛF©9žp¾¸®Ìt•l=«÷ÂðÎJ¢â}±¨¶O†´ õ‹+ê§R±±&¹šœ$—‹#W4 ¬®‹Å(R<•JEµ-ËÂ÷ýªTºŽãpöÙg¯ˆgTäsf’T…BœaβTºkm[ÔQeµÆ© ÏÄ\œ—Ëœ\Pˆ|*t„X&£†1¨KI+­Ûºn¬FM%Z§9æ˜cª>·m›Õæj>l~¸z‡úN9ÔšK¥‹NW–N§=ŸK=¡­iÈ ÒÙÙÉæÍ›Ù²e ›7o¦¯¯/²Bê‚õƒƒƒlÛ¶mÆc 2<<ÌÎ;'¸`Û¶môôô0::ʆ èééiO[×­6¦ -°b½0lYCCC‘AÄu]Êå2©T*ªy¶m322m—šBKž.­—ÐzL'›Ðúò¹P$³p°5@fk'eÈûù(‚ •Þ*•«.vfAåʼnÿÓÀjQHÛužMýd@…Œöä:"Å%NÏ¥ n8ÔÏq”ñgF,ÈCÏ?ìâö·þ>]í§ÛmCæ0Co㨨“°^Kd,I©È’¶ÒJ‘HL€+ÿÞàÈäÛ—Ø·ð?Ä!²X†mª±Å~?ºG5kNÁ9`Õy¬üîw/f9 ò)íÉÄÄÄŠ\J¢$ÉÉo¹¬ÆÛL8¾Bµ=5hûþÆÎµ ÔF¢èŽd2êo­¤ÓjBP.ÇÉåf¿Š¬ ILG½ZG• ŠÅ"©TŠcöíã÷?øïüú×1 Çq¡·· Šw‡JÕ…‡L&ÃÛÞö¶&\ð¥GäsjtM=¾«TR"¡³3$ÓßBu:/AXD>AÖ‡L©aF–‚V\·m$ Q¯_ÖFŠø¾¯ÖIþ§ÆÃuª’s:µl™8Ze:ÂlRCeeqp£ö÷÷ÓßßÏàà ¶msÚi§qÚi§±aƇ‡Ù±cÇ”Ñ+IÖ­[G__ߤÂõÃÃìZµ*0»ººèêêbxx¸Ù׈#ñ!.HÝî¶]ü=vïÞM¥R©Jï¥k•¬]»Ã0ÈårŒŒŒP(ꦫEŒ)íÅT² ­/Ÿ Mô覈Â@³YxóK¯â®÷ßÅ ï~!%=¢{Lγ¦è2ö'> ‹fb  É<ðº.ÄQ)Ic‚AuÚ/›34Æ }$ngÔ§¦M:²Å‚ÿû¥sða/ÄÛ`ÇûšÃý’$ÚP’ØŽe$"±A•!'ÿ ¿…ꨜ ja¬öõîgÛygâ“èáG–’V[·-ã±i:t&\¢õ— T:S ø²ðõD(I0ÍÁº+4p^Lê¯qËšY¥ß¼y3›7o®–U«VÕ]à™ ½íªU«ª>4`®ZµjRÞÌZöìÙæM›Ø±cÇ¢^(^¦ V·K«dÛ¶ño¼Q-fצ'jIÂÅœŠ–míë)†ÓO_Ãóÿø|N¹ðNñO‰÷-âôTºîIž¸0™F/ éÔ_ÉÁÛD Ö&q¤¨¥QÚ.Šáw^õ¾æ(ÕF‹B؆\Í9< ö¡ÿ5´ óMT§ƒØÐ“|- 1Ù+£Þ;°&\Ö¸{v·aA<mõÌl`ïÞ½ó³ÂmKÄi½´Á%GlÄÐQ%^â3ZªS…AœG>iŒ±PF˜d¬®µ’ï QÚ.¸ûÀÁj»d*/PÆ•Z¯`³f›±Î†à‡sÛw¾tuu±cÇ6mÚ´ô'_bæ"ŸÇü²X¬Ú:v¹GQÑÓÓÃæÍ›Ù±cÃÃÃlÙ²…ÎÎÎiué¥Ðm—‚r9^ªòÝñnâZ_Ét^¹Ùœ¡m½Ñºm>_]M×?ÑÉèAý][Ù´Qg¢L¦±ín¾C¸®‹eY‹ÅÈéɶmvïÞMwwwœr´†ä¶Ï?ì0ð< èŠ@O¥R3êþ+E·«|¶‹nëyÊNñi*1Øž¨3×éà+ñ„o]V’n;ùlWÝÖ÷•l‹J&-K}¦'Is$4Ÿ•¢Û6kݶÖÐ_½Ö Du÷œ¢ƒišœöõ¯‡ž=…j§×™äK§ò Ú˜ÅÒÛædPY êyÝŽÍÉz¹ÐÔÖ™\j|ß'›ÍNJÉ•Äu]ŠÅ"¦iFl–e1¢c´Ãã$kŸB£´²|ΪKÖ)ñÿ]#oÿÔí¼û%ïæ´à4ÞÓÿžó¡ëù‡§_©<tú,]7Ä&®5±!C_t ’ä¹…è£Ï|&Õ>©Š 1P‘!NÍ~õx£ÎÿµŸY̬Ḋs xöÜvõ}ß÷Éç󌌌àû>¦iâyžçaYVä©[»Ÿa”ËåÈkw¹³,åS˜?Úè+4 ½ø¥éééáâ‹/fxxxùzÿ;à¸aÉ/»NDw2½e–Øa`¾è4]¹\ìÊ›Ë)7|ß«gg2j;=>–"¯˜ªs’Éd°,‹ÞÞ^ …år9ŠÏf³QäˆaäóyLÓœd<±áŒÒ*/g2ݲ,Iɲ\åÓuÕ¢lÄw>¯ (©ÔÔ¾K$ ‚ÐËU>5ž¯1éò\ŽUé´2¤TÕö$6‚ B³hƼ³Xœ9‹ª®÷\«ãär9•îK‡c‚Z£Y‹ÒAóÔϼ‘D"Ä)hƒJWWƒƒƒUŸ7=o¦öX„4È “N§1 ƒb±O’ˆ=Ù’ßAMØ’¤$>T˜­*Ÿµhož×|Tª«±Q¥ >ßúý\U,rÛWoS C ¶µ¬2Çsi\ >KlÈÐï–ËHü?„¨“ ›6ÊÐ’lg†(45¢Þ䶦N »™Kõ>³_æßM¿6 \×òž–Ëe†††¨T*ÑÂ’6ëïõÂS.—à ].“ïIߟ©zÜò ]äS˜Êøk×|“%ú¦É‡¿“FÓ4Õï=˜l\Œ±±1&&&ª&™ÍnÖ¢Rc/çuñó¥ëzùÄi&MæþìyžRÒS©8MW¡P]Â0ÔjUr&nÛqAˆEÄ÷}ljRlrÖÐ5Pôßår™\.‡çyUNPZŸ÷j†k]:"Gƒ¡¡8JGVà&±äS§ô²,õhëG=ÔÿZ^‚G^”å ŸS¡ž:bLËk2 Švæ­µ‹=\h6͘w–Ë3—\ˆj§h\|p/Üý†††&{ ¤Ps'A˜-cPéééa||<ò:ellŒ‹/¾¸©íÒáÏÍ ›ÍF/†B¡@oo/G¬†¡¬­@©T³iÐíÂÜhUù¬Åó”ÙŸçW¿úÕÒ]Ø&Ѫò©S,µÆ‚VF¯&‡œlørM³¥Ì'?;e„µÇr©N»WD½» ‰}Ó¨÷ÒÚpýîÒ‹ØVâx:lÝÿî ÿÖ‘¸Ax|ñÈš'ÃÃÃl߾믿žŽŽ&&&عs'›7onvÓœ|8>ú{ t9d^K{T×~j߇[ ¸ÌX‘éÇúúúeÆ tvv²k×.úúúÚ²XîTè"ºæp?¥‰#QÔó7]$¥¼-K-ôk]M§ñÒ.÷¥’úÎ0Ô‹E×EYð>)ƒ¿®c’LÅešf!iÛvÕßZo,‹†A*•"“ÉA4¶iC‰.œªÿšÉõr®˜fœˆâ0†lHÑ´“|jñ}µ«sÉëŸõÄ@2<‡è(/ý^ñ}õ>qu‘’9Ð'ùiAIn—;í$ŸõH¾vƒ v2Ò)½’òY.7þ¸åóq&4Ÿ¥šwêWõtϼŽö­­-·ÿ~.¿ürŽ6Ÿª¿£vu2aÎ4Í R¯ Q__===ŒÑÙÙÙÔt%A ƒvÏ2•ÎÜÏD/×uëFœ …8`‹£ÓUíu]wÆüÏ:'*¸–eE^íù|ž\.G>Ÿ<ütM˲"Ǿž¶mGß;ŽC±X¬Ú?›ÍF‚…B!:¯öLzÇëÅbÛ¶ñEuÑx›Ép‹ÈZöt$È_üÅaxÞËåêÉä¬È/Æ‚’µJø¹® ¢ SM@kÓçM…Cý´CÚ ¡:¥ŸËäˆõ‘´ûi¯§¡pÛ!bJ‡¶_GÌùágqôŠ+—¸.úü#ÄŽ“ï%+Ü?“hK½¢U!Ž¦Ë…ÇÉ&Ž“#NM8ö[ׄ*¦•…³KðÏf|ÍtM) ðÊȷï à©DBxé¿Þýo9iŽIû°uëVFGG£tÍ–Í…Äûd·BæIÈœ™ðÊðK3ñ“afƒšv¯wÝxælYÊuW‡ž&Ç›E¨Ò«£I<ÏÃu]R©¾ïG)¹t]¯¤A¥R™4­]»¶j|¬$¢g´á_Oüõ¾‹ªÛ'+Žëð…Z'¶~¯ •øv‘OßWãj¥¢~‚`éþÚßÃç´ÑÒucyÐϽ¶NåóêçóqJÁ%¦»»›J¥2é ß?†apÆg4ûÊ. í"ŸI´¨9g±Ûçê=NSD§b½ž…¡Ùë¶¥ÒôϽ^L?ýéOyÕ½_œ<µÅ2EË®ÝíAKE¨-3X‹K§CA@wwwôÿî)¬8Ú;®•Hzãår¹¨Æëº†M6Óé4¥R)Ê­Sé4A½½½ ‘N§) T* È w꺹\˲¢hýòÔ‘(0uÁMíošæ¤ýµg ^ ®ý©T Û¶#/E×uÙ·o_³oÃ’Ñ*ò9®G—dŽƒ`#ä?¹×¨ùQ΀5WÜËõ×°æØ‹é;õÏù_½à†Î±dˆS!öЮMŸòB·£ã´g‹žèi¹µ@ 곚¥/\~96*ÄõE;v042Â%>ÊH©Äƒ÷ßÏí§ÆQ££7ßÌ‘Gº8ŽÏºáaN8è ¯ºŠ£_ÿzÎ;òHþÖ%¹åßàäÁA^8>¹V*¡ñˆgøzÌó&+,Ž£>×7%iXq]µ¿þ>YLX³ y£–7­&ŸCC äz®5|è( j>³P†ý½6¨ÔÃEFP‹¸&q$I(>TPF/ñ6<‡C§ÃÒQgÚÐZ©Rå†Ûjo|}Þ€ØøSJ´A‹¯6T‰óïNœßJl_ëEe2Ù¨d…ýIª 9â4_z›LâxÚ@ã†ûY€[„ר°ÖŠSž”…¿žåÂé8ÇŒ#ˆ~S„χòl r#ð™2œ†át”ž2ÞÇžSÞÓðóÔÎ,f¡Î¦@úL(œ …sÀþK¦žN÷ú.—ÕÏȈzaÔK’­]ñ ­;A@>ŸÇ¶m,Ë¢T*Eébu P•:bª4©TjRÝÃI—%× KáŽÝSR,ªk¯6s¢òeF+˧Ú¥m;ÎÚ¶‚|Hæ¯êBÉwH&_L=Yµžƒ7 ÚÙ¯ÞÜ<é„Õ©§ËåräȧSàjG>Ó4 ‚€t:E^kgAPï mð])´²|ÖR.«iO²þÉLÉ-Ä0*´+K1ïÌç§‘¡È«ô€ŸúƧ¢Ëå2Žã0ô¿2ðÕ¡p]³/•°Œi9ƒJ3 ¥SéõÁÅ,¹¡ Rj7Ng± &É=Ó¡ #ŽãDÑZ© ‚ òr×d2™ªí´»6ÕóÄ3M32œh£D­1I:*5¹±k &¦âÒûÍ¥žJrB­g2ø. sAG¥èuƒ PQ{`‚6ÀoŸuçÿ6Åëßózr¹×öçQÚËmnH‹‰ŽPIŠg>§&ÑÚ³~®´¡PP Úû-‰ïW!´ìkƒçÅûéïÖ®…L†_?ø _0 åܞϓJ¥Ø{ÁüÕðÀYgqðSOQÂqÖ]q÷¯[GߦMê¢|å+CÃf´ôåópï½Ê¨¶õ²á—¿„?ÿsèîV7)‹:ÿD:­ö©}¯xžºNÚµ¤6¡·N"lYqLo½È£¯Om‚á|~rº¡éh£¦i6YFGI$ˆ´‘ Z|×FŽJ;´!#Œâ~Þm`¿¼ÏAð °®ãíá~CT§Ò^IJ¶µ!5ŒDñ¯ÿu`} üÿ æ†ßwypŸ°Jà‚.ൿa€™Ïþ"´é´^_®óåêÑr`<#/-£fg,±SàêH}¹Lð}ÓWᦾVµÔÞ‡ ÕQ5ÔìW.ÃHþ)ñÙk,°MøP©ºþ‹ ¼Åbh.TDM¸%q’²ºn”àÑÍ/âøßþvž@aQ)Bþ0ÿÌÂ,³W–ËêáN¥Ôû^¿óõ c IÉžWÿ­ëwéô•š¹F?Ú¶¥ýj fê‡^`ÖŽBÓÑþ3®Û sÂr$ipÕ¥\®¯ó9Žz~u8€6ˆLU[I3Ã…®goooTçTPô<8NGŽxžçU½gT³*шœu½¥äš€®¨ÓÚ¶Í7ÞØì»#$p]%¯¹ÜгG ¢’Ì; îâ~Ê¿)s¼{|4'1 ƒ!Ó„᳕†Ï%sA * tÈbÕMÑÑét:2> E©x<½b²‹ELÓŒ”½dê*«P(N§©T*Q›tèb±yí¡÷z=5TèíZf²)´zÎdÛqj¡\N->b€÷oàÞ¹2jõ˜€ÿz迸ê‰]obÒ8b“]PtÅFÇQ¿“)_´Ü÷U~F™Á´ ºÀ&Ô¤ýòQƈäk?Cd8q `¬ÁsÁû¤^ ågB°üPæÍ=à?^̧Á>¼µàæ1àÿI¥õsÿ¬ €Ïƒwœ:6´ŽŒ@>LKV©@>›hÓ>°žûHp‡Á]©4äo ÛŠêCá.(ß Æca?×ÜõÔ]ò…Cxõ«OÀ힌 *=ô‡¯9œŸ|aœ¿¸ï^þã?f|ü…{ì÷øÉO¾Æ³Ÿ½g<ãØ¨¨p.§ö»ÿþû)߉'^Ëš5køå/ÉÞ½{yòÉÙ·ïöî=‚túHzzÖL²M^xáu|îs/á¨CÆøˆQæÖç¼”Ÿï>‡G»—ß.ŸûÜßòðçòØÞ½œ{ÍU<ëÀN©çÕ®eôÊ‘öŒÑÅ2u¡æ|˜7V+v:••þ­'š¥R Ã0¢‘zõ[¡hûƒž#•ËjÎT.+@@ö"(mÓ#*ÄlÝCa}ß÷I§Ódþ!éׯ‡cLŒO'"2ôZ¼a¨‰Yo¯ÒX-KMÒtÕÝ5H…²4ÔFfhCCÒè¢I¥ðwïŽRâ•r9åMLÓÄ5 Ìp!H/üèZ&µÑ^zqh¶/®¶™ŒM•ï=™’N«…:yO5dÝh¨vŒöKÀWÀùðïSÆ î‰ÀF0{À| ÌW†‘§€Ñ öOÀèígVM¾i3R©þ|¦À¥¤ .ù·Žu7ZlJÖNA½W áo]MÃì…³ÏNa©ÐÞjày>™ŒJe©k|ŒÀK_ú\?üp,Ë¢»û_H¥Ös衇róÍØ¿?ÝÝ{¸ð ùñÌ_ýÕ_qÛmoaüî§ÈOf7òð3Ï §ç\¾ýíoS.¿“žïOð¦GaÏyçñçwßÍÐ1ÇpýõsÕU~ýë“yò»ÏæàÛå•Ïåw¿YÍIëÿ…þç«øÕ¯^ÂÁŸËù翚ï~÷\Ž<ž½ÿzO<ñ¦érôÑüùŸŸK>^àá¸ðíoŸÅ}÷ÍûÞ÷=~ýëu<ç9ttü;[ÿí<ð@O?ý4–åóò—‘ÿóþ‚#Žø&o|ãfN8ánä?WΚýÐ u pÞ Á¿©n(}%ÌTgN±C2=eooì\É(AÍd&¿§ç tkã‡6ŠxžÉŸþˆŠÂ{žÇÈÈÈ´N< V·ÑÈiA¥ÂXaÚYô¼lS%=µÅ(•RŸ»nìäcqýA52¢ôò¤Û²eÕ­X¬ÇcmÉårø¾¥êÒÙ"’©¸"õùØg?Ë!ï|'ëÓé(k‚ã8AÀöøV=ø jK¨pDóe×=8´+©ÞßJB—ÚYäì”ù¼ø +õU½ÛË­¯»÷:U{š³}(›t¸” %5_+0Ë0jA˜=bPAé<ù|]]lÞxž‡çyQ.åÔjÇzñµ\.GŠ¡öœ)‡<3BꎄVBG÷û¾úñ<¾Co7Ìšå?ægP)hrDé{ö¾w/•Tøtï§cùÓEŸËuêõâ½ëªÅ ‘µø£ÓNÍ–„\éZC:ˆnã8”Ë娮NЈÁC&g!µ.œŽOÄ…%¥*×­×~õ}`^ö9 Æ]`õ¡Þ0’A×ù(¼%ý4ëžx‚Ý»wsÔÚµ|óùÏçŒ3Î`ÿþý|òÏà9»vñë“OæUïx_¾ì2ÜÇcÏž=\~ùåÜzíµlY»–Î[oåà׿žïîÞÕ,¢|°Á©3q‡—š‡_ä¼óNÂq¶“É„ësë­på•Ï5×¼Ÿ›nº‰B¡À9缑ÿïÿ;”û·/6«VŒe•ý¯zÕkyÙËÁ²&0Œó{±¬5¡¡é&2™„zF_h(~ÃÃw2ñøãÍ~d…:¸WA~;dþrW@N§Å«ÅqbòT*'u-×£ À³N{“+þjOq­ûÖF›hÝv!uoAXHt)9 OûŠ´U¿Ö¬Õ¹´âîû±b £Õ2™êÈ4ÃP:wmÚ9mHŠ–EÎ4«"ª“™´Ñ¤X,†§*‡‡ÈP.—)—Ë‘ƒ’žCkÇ  Såær¹*ãêcÿüÏŒœx"¦ã@¨«Ê™G’»»•.šTRŠEõ¿vø±,u^P+…:"§æý¤×¦ª *´ù¼’ßÅÊl2Ó¦A„e€öe­ìëy[÷må±=¦Ê„iØo}ë[Ùû½£03Î@"ÆGa‘Yñß‹T/p þr¹L±XŒ<]†††f4ZÔ°«%›Í’J¥¢<Ðù|žJ¥‚çy“R ´ÌB«®%qš‡ä,A¾ÐʸÞFS,ª·i*¥n–^9Óèvߤ¶èµïWñö¼êZ ÎuŒ®>~² ®«Ú¡1Œeƒßšø¾òÄ ƒ­(aµ ©1H}z7@å-À¨Á3¼uE¿ÈI·ŸÄ™OžY]›G‹átBoÛÖõ™qÛºmöÉçóÑ$.¹è£SýAlÐOÖÆ0Ô;¡UÞƒ+ˆ*å·r¯Þ¾r×ÛQi³rÀ;PFPr„ß%DÏq\\ܵ.¹\.ªá¥ ÚûÔ4Íès½Hb«â"Üý…/°ñ oàÓN#‚h\‚€s*Ž9æV¿æ5ÇjÃ0Øuà <ã{ßãÌÎNöÿïÿ“Nsãe—ñÖ·¾•W¬[Ç_îÛÇÎ;oûÛ\œNãÞtÆ[ÞBoo/CCC¼ï7¿áÊM›x^¥Â[|›ßô&þtÖYX–ÅQ7ÞÈ÷w¼ü¸ã8âÏþŒ¿Ðy½t "Èju˜&%õ‡p¼<1|¾ßV{jÞW7‡¿õ{P;Z$Ó¦R©È{7“Éÿ÷Ï™gžÉSO=À'>ñv,ë,k×®%—ËaYV4¦Y–Õúœé½PÏ€ñàÕW³æ'?Á]·;<¯‘œ w|ë[œŽÓù|Û¶1+•È™*åûئI6›Us`ëe—qÏ>ÀxhXÒóÇqÈd2‹Å¨†h²”Y–žlV=º–R*•æÆ×ËÆ*Ëé|pòù<7<}G ¡>Èfù·7¿™'œÌߢփҨy¥ ,2+Ú J×[È4ÇŽãà8NC逨‚öˆÑ C©T*òtÍçóQ:Û¶Éçóär¹h¶®ñD+¶Óq’Aƒ Nq7.>T+É h]0¬ûPµ­‹n'C¶k=´E+¶D'g× ym´A%—«Ÿƒ[‡ëïê)¡:nV{QÕžC{CiƒŒh1KFÄ‘cæðw‚1#W€ujáõQð¾u=ÖÄIðoAJ¥Þüüç¹õ=WpÄ{`íߨ-â½Ó =IùLNâlÛ–H°¥Â¶ã÷—°d”Ë`?þãX»ÂÿÆL”¢kPŽí.T p” ë…Û¶£ñÑ0 …ûñ ~<8Èÿ<ü0ïI¥øù£VN×®UïnÓdÍš5dR)޾àN<ñDî¸ã^û‘0~ðÁ/})>pßþý¬h¼=ýÓŸæ”óÎãWÏ{—\‚¿oÿHµ¡´7—#¾S>÷‘±Ñâ?þû¿U;>ð6$/Ô;ß©~¦Â¶Õ¸4ÕûbS´gnò½¤ÿÖï,Õœú¿µ¢ë¾k£‰6ëßµQÃÃà /H_„Yâƒ÷mÈ2ÇBñ{z&ÁЧTª=yÌjTæ‰.Þ¬õbh©TŠþNêÕ-ã<Ô¢è”G:Z'J+êºX–9|hg.fÔ©-Â$,¾¯ô”ªå¦ÚHªÿö¼¸0|†e©Ï´q¤TŠ-Éyb¡; „:rÒ0 ³,˜a„¦Ö£µÃÍ}Çadd¤ê= ŸcýP•¦S5µ:Cd ۢϫß1 æòz¾­#ÉMÓÄzâ‰èo]_T·Õ²,¾¦Ôzoo/…B!ª[X.—«ÇC×åûöñX˜YB§ëÖc³–Qm8ÒÆcÇq¸ûî»›ý¤¬‚ žNäóqôX¡0ýËR´K–3Ž®Ñ:Dβ”¡Œ3Žàˆ¨ŽêÝçžËGë„0‚J/‹ÌŠ6¨d³ ç ä% DkϘéÐÅé+¡÷ŠVžR©T”ª@{áTtÁëð˜…B¡:ŠU“ 5“¨í’‹MÚØ‘,¦]§ÖA‡e×ö)“™ÞÓ¨&,»îŞɵ£^"þ$µ+µF㳕pñ­îçSõÁuùó¯}GÄ‹oQp]5+ sp«„Z„í…ÜïÅzúákwslj·ò–Þ·`Û6?>æž±?ìßÄæ‰žà†¥Ð0×U9<‡jÛÊ‚O‘Ç’P.BepQò™C)µeª *¡¢»ÿ£ûùî/¿Ë7œoDÑ:EW±·—s.º(,¦˜f‰éûðŸÿÉË×­SÿêS\R(DE¨-ËÂ Óæétz?sR'žH6›¥P(PxãÉd2<àûl°íjƒDcÛeá¿ç„¿utǢ֛͸%³Äq ü6ð†Ò%Žö‡Á8{›¥1Å÷ý¨^¨±T;é]÷¤6òd9;$è÷Ä‹¹õ²ôû«X,FµaÌÐë]/üær¹*Ão©T¢··—R©¥Õ‘=Ɉ?Ïó¢EîB¡À¿øÅf_–eILÎ ÕrègÏ0ÔÜ2›UÆ’¡¡8›@-¦ …BTOL:’Ű–h|-‚è9Îd2Q4·:\\ɲ¬*ƒ¼– -3I‰~èã;ŽC*•ª2ŽèßZÎ2™ Žãàº*Ö¶í(š\G\j'GPòª³DL‡Žx²ˆ¼m³&ìÃT:…n_˲øáØÌ'dÅ 3'oO³§uõ|?a¹aÛ`ú¨´])ÔÜ2 Ÿ?ùó|ãšoÀ?¢ad„‹º»¹úêj½I;í Â"³b *:by¾™v|ß'¦”Êd23æiÖÛ ÞsÙe€Q3*†¡J@x^œ$3aPÔ Ä¶ã…—Ú…Ã™ µÆŽzHHñÌØ6«þîïx¤ÙíXèÔAgx‹"Ȳ¨t7aEÜ!H]ý?<ñ³ èýõ³9ïØ/1ò•0¤ež ž:m—^è¸XµöN«7ÑZ] YXTtŽ[…Âé`æP¡Ö>±¬êú(fìΪ… Û¶'¥­¤\ŽÝxu}iâ‡òN§)U*Uu‰ô‡mÛј¬3FÂ7½³œi…å…ÕÙu´wût°ª)$§R¡úw-˜—.]Ûóù<®ëFN :O>Ÿg÷îÝ‘“B#Ií„Öô{H×vÒhÏzÏóÔ»¬TŠ<æu=D½ÈAEñb±väÐ]Gƒéß:zL¿÷ô5^N׺X»¶º{K’œOêô‘…®çá†Gc{5z–~Þuš>Iây…B!Š˜J¦ßÒzµþ[?÷ú½P©T"݈Ò}ê6hƒ¢60j9ÑëÈVÓ4£”–õ¢Æëéóõ :jf&æ«_LUCÅ4MN>ùä…¼ëB k×*9ÕenAX:òùpÚç××táÞÓïåí'¾Î§:£(ê|±X¡@–˜iPчæY¤HO€f*6ÿÐo~ÃáÛ¶ñºÑQ …•J#à߀O}J½1§:‚D§ÊÒùŽj™*šBXrŽÙ·{›Ýˆe@>¯y]²&“Ê0] ƒ*&_‡àr‹Þ/ªz% eÜèîdõÄKB“i3„FÏ€¾üåf·dY£wS·€­³7åá¡âCdÒr¹Ç]|·½ý6>vÔÇ0\#òþL¥RX†¡Þ÷«jx–…ÕÞÓ:f*•ŠY*•J´˜”I‰ –ÉšÎ:XË÷c˜t:v×j£eûjpÿº2›Žz*Zl‘ *žçáºn”G×=I’\¬Ì-t1ÃFG¿éE`­ÿ'=às¹\Õ;ªT*E9ÚbCJ2U‘F/ ëk¦Iêúý6“‡¼Ð:hÿ¸–¿e‰¨k)AmÛŽ y:Â6X¬^½š{ .¸ Ñg/ŠšÒÿëz¡ÚX¢ ,Ú°¨ :5Ž ‚ z_è4XÉ´’µ:ùtór©±$L‡.ïªýAX:´P¤V€n¸ý ·óá/}˜í›ß_ÊCOa’A_šÁŠ3¨è YSÙ)¦C–K†2×› êmôêWóê_ÿšg>ñ½ç=Õžw:ŒZ眭mP*5çžÂÒòÐêÕÍnBÛ£³× ©"Û†ŒÊ}©Ó9yÌh¤u3Š¡Ç«6~Ì=©ÓÅ"K¥Ò$¹N.\ˆ1E ÿ÷`Ý ¹óQ¡Õ¡XäÍ9J§Ÿ}=fëôq†að¾÷½L&ƒëºÊi"ÛuÔ ÄuLf2êík­µúþŠ P‘DÅÏ í¿£3Ïé$ Úˆ’Ë©qV;*´¸_–%‘Ú”%ªµùþ¿ŸÏÿý9î#W Ÿ pŠÎâ¦`„Xq•tzîƒcoo/¶m³oß>•ÓÕ4!›å‰#ä±{ïåCüíç>y­­{Õ«xü_þ…Ž /¦˜¿†9g…öåÎ3ÏäØßý®ÙÍh[Êåê t• *¼³"QÈ:é4ÇËÇS)ÜÐCn.)]ܱ··—\.å —QAhŒüëÁ¿r—¢7“Èݲ,\Çá˜J…B&£N9¥ú¡Àëúc:ï¿^ŒÔ‘)3¥Ñ„åJ±¨u’CœNÙ¥)Ôv®›P%]àpâ” Ê)A;dÏC¤´Ç9ÀÛï¾›«ïº‹ƒz{£ÈM)¶T œÉ¨d½]cD…Ö×u£öëýt¡kmHÑi÷íÛ}?Í6 íÎÔ¼Tèh 2~èZ=étš5kÖpÅW`Û6/zыرckÖ¬ámW_ÍÞð†††"YGhkcŒã8‘¬è‚éÚ°¢:š%Y^d¥éôôÎõʹDh ½.V¿S©Ø!¡V“kCá«¿e›š°œ‰Ò½;(½Õ†›¹™£?ýk¯þ|¨°ñCGAh6+Ê âûjíúŒÎólÛ6…°àå2÷®YÃýO<Á÷;Œ×¾å-X–/ÊÊBЊàg/{=Ï}n³›ÑVx^uNwÛ®™K”‰<" '“!ŸÏ“9ë¬9’h™íîîŽ ³ær¹(ï¸ “}-ÿ ¥ÿCù ð™ù·]»( Ê«´·7®å•ËAèÁª#N’auÚ©k"Ї~æñaAN•¦+V€*Й yJV¸‹7“‹Es\Ä-—ËQ ¶J/ІÁž›oæœsΡo‚’F‘ ¢bêÚÛ=Y3A]¯T*¤Óé¨ÎÄ)}ô¯‚§J¨ ±ë¿a¡qÝÅYÕ& ÆUß÷¹ãŽ;X½z5===üò—¿äE/z{÷îôßJXwLGf qÙe—‘Ífyê©§¢ºF:Z»Ö±!i™*ú¬VŽÄ˜2–¥"v5µùÈõw†1síS!¢\V ³…ÂüS¼·Ž£ŒE‹é;›Â÷:5šÎF¯ƒÏ“ûû¾z„u¦P¾ÎØ”ü[£÷×ûšæäm’û™¦:¶nŽ>Jî7Õyt:ý£í˜ºº,§ç©u }^Jp8úègsøá‹wo–3ù|x]]”1¥¢Æ¸÷ýãû¸îì³áâ‹á* »eY-Ÿ*VX¬ƒJ¨ÁµÑÁG§÷úÝ¿ÿ;Ï;ê(>ðÀœÞÓVòù<…B²ç©´_Íî  ´ž§”­èd2u6åM«çoAÀ½ßÿ>?ó™)ó°O…ÎyÞÝÝÍÐÐP”gYê+ÂpÀß ÆË¡ô3Ô­ïsÇ+_‰ ¼ùç? ”^XoÈó< ß<\ut]”Z/a2k{ŒÏÞM\Ó$*ʉþ_ °³`¿+üÞB¥H˜å’ïûxžyµkOv˲‚€R©4YV]Þþöi«ôX¬Si’i€’5JŠÅ"¶mWEš¦µC®'Óú­èÏõûH&ÝB3©]|› :-—NÓð¥/}‰“O>™g<ã8p€W½êUø¾Ï7¾ñHž<Ï#“ÉDQZZÞ’ Z&kSp‰d Èå¦O±Ü¬K€ï+cÊÈH¼Ð½œ°,Õ¿r96®èyu©¤ü™‚ N£ñ\;—ƒï~÷nn»m5§žú0/yÉÙ¹óYUÇÛÛ~ÍÕWŸÀEíã¾ûŽà®»:xüñÇyê©§xîsàòË÷pýõçêœßüæ~FG•Á4•Ñჼ›»îêà”S&8õÔ‡¹å–ñÇ?þ‘Ç<:ϾðÂèï›o>nR_Ï9g·Ý¶š‡º×¾öp*•ðÄO`pÌ1Çð£ý€[nyÏ|æs8ñÄûÙ³gÚóë_à%/ù!?ýéKxï{Ï¿üKõyN:é.zh5ããÏfÕª9æ˜}ìÙSUÿïÄÇøÍo~ÈÝw¿ññgGßëýzh5¿ýí¡¼îu6û1i+<ò0Ÿ†Ò*”ÃP 0 Ý›&“Éð°®m9Œ@–ñIhVŒAE¼ž‰ øèG?ʵ×^ËÿsÚi¼rbû¼óØÕÓÓ›7c{–eEÞñ²0+áyJ±+•ê6=TTЉZ0 °|ßç†w¿›#n½•L¹*•J”×]Ry Â̸.ظcà¾2kÁ<0!'¸?†Ô;¡PTÛ_¿~=ç~÷»Üºao»î: ^@Íf³T*•(5ˆöOŽ™bL„i(09º$9v†sÉIëm3 w¾ïG'Ú¢#O´A£Ô '´¬Ö†B¡@>Ÿ§T*‘N§£]{PZ-˪ZÀ®š~oHD©Ð’x(ýUG‰ˆ£ÅÊà?öˉS˜è¡Ï§:_ˆŽ:ùæ7¿Éèè(###tuuqÇwð×ý×üô§?åœsΡ¿¿Ÿ#<2J¯eïyÏ{TÔˆi)ƒ«Qm@©¥jQJ»`×ÊbPÓÞ©®î›ö.ÖÛºÄï2}]‚Äu¨56iïðä>„ÇóÂßAâÓ½‚ðû ñ·ŸøÛL|æ×9Oò3ݽOm=dÝ_#qn/±~F’}÷çKö¹?qLy NK±F/*:Ý–¡ÚÿõT£Ç¾ÚBÚz\ j¬®Éñ²ö¼Aϫ߶mcš>†a’NûX–I±×[Ó¨šk&6¨¨ñýÈG—‚ÕíÞ³.¹$Þçä“ÕO’Ûo€ÕVªÝ꘦Io¯ŠÝ»×àC|9þìÏâóôöý]{Pé×N>Y]£ßþ6 §ç–ªï'&ଳnO\K€E×[_ÃsιÏóyýëk£êN£[À4M‚àOÀïkôsx㟊þVý¼3І…ŽðFGG™˜8ržO×Ê ø ßV/äNû/ð Å2ÿÓŸ0M“L&¥km…š|‚dÙTtÍ6× ‹P¦‹N)—ËÜxãÜ|óÍ\vÙe¼ë]ïâ²-[8Ô0ÂW§Pa.hï¼J%LY’˜hñÔF¡GÉd±Xä_/½”¿X·nR =ß÷£Ô]Úû]+?µÞª‚ LMððG¡Üév‚÷Ú_“ÞñÖsîÅúÕ]X«&÷Í×a\xV$›_éè ã‡?ämgŸ)º:]v:htaV„˜G}ü2dÃ<:ÏDr¡3›­ÎKQ(T­ž<ðñsð׾Ưžõ,ãÿþîwüësŸO^×ÕÅÚûïgMÒ°iÛÑ*”뺼ü#áGúO=ÅÓ>ÈÏN;u–ªJá‡òîû>™L&*@¯ÓøÕ¾tZ-Ñ¥…væg?;üù`ï÷00;Á18ƒz˜çsÀÕL@åsÀý¨…óðñŸøâÌý‘½{÷òØcñýœø àG—ýˆ7üçøð™æÉÎ'é ƒ#6¡tç;€Ã€W ’mMÏÐÖdë'“¸fõÚj æ/ùð»RøwÒ`“!6¨$OAÍqò‰vÔ^³°­)OÒŠO…mCJ¼ôµÖ÷ª X3ÞÖ <öÿb?Ýö÷Ýw¿ê÷Lœ2QU—H§’lÄ1HÏEµó‚ž«êqPGŸM5g.]¥Ðzyä‘ 7»mAñMà?™‹ÀÜŠò¼ õݼçqÄë^GéÓŸŽÖ|$U»ÐŠ´œAellŒ±±1:;;éììœÕ¾Å¢D}_S,kúHYzä?þã?Ø»w/7Üp—\r ©TJ„Uê0Wùì}1ä^öFb/¶±'V °b#‰N7244„V­×¹ÕMÓ¤X,R*•¢â±: ˆP„•Ì\äÓ+BúC2tÙÿKåþDŸç^ÿBx!XÖYØ6Qý÷ãïÇ4ÍhÁôÙlT Ŷm)"/u˜ÓØéû±#A½ü˜ÚKÈ0»ùf~ññó½SNÁ #FLÓäÏ^ñ ^õ«_qh6Ë–|€-Ñ¡}|ÇaÕÉ'ó…ýû¹à‚ øÂ¾À_½æ5¼ÿã ¹¯¾ôRžq œp ¼Ð¶ÙP§©2ö íÌlåó-{öò‰ŸÜFpد°Ž¹ŸÔÁ7clþß>ËAf"¯<üîPÅ\±×qøêm_åWÿÛo¿¿ý-Ï~ö³™˜˜`ݺuüóK^‚Yx Ap¡ya˜%ŸØRÈ$äÍʇù~ÂÿóLžüj7p} 3C ãlÁSˆOøð‰Bœr7I½²äi¦zd¦Ø^Saf†f8F-¹Ž1×¶6¢Þ$÷ià3]×)úëüÃ%\ÂJ`¶ò™úŽ»ÃñRßk›ê#öïßÏ/ùKöïßÏOþ1úÑŸ8÷îs}ñ(¿ð`NÙs ë[Çóž|GÞ}${ß³—Óÿítu mìòÇÔ†6‡h^m£‡ï*-g·ÃöìØèSýT 6š‰ÏzÃÿ3‰sêcX‰sëô [|5`­¡¶ù‹îF}VkP|܇#Lø„™±¡6 HX+OÎ4á{fÜ®->ÜgÂÓ¬öàmÀ–:6~ÞîÁC+â&¼=€w[ñyÞî ðL. ×ä¾gÆ}{Ÿ˜ðÞ\.*”€‹Çx%p˜­Œ¢™°¿ÿîÇägYðßFµ‘¸¶W«k¯“6 &— °ök¹÷ø{çô¬·óY·uÞ Ö_Cî¯Ñd…>*Ë•JñáBbQY·gS;W–’–2¨ 200ÀºuëØµkýýýôõõ5´o¶2w@¡‡)½;üq\Ãeìæ1ÎúÓY¼àpSú&Ö~g-ü#\À°5 ·”âÁ*ÌS]5À%À^ †+,Wæ*ŸùóÁÔeÿPJÌ Uþ¡‡â§ïü)¿üå/ùëw½‹ÒîÝQZ’K￟üû¿³%L’J¥¢Å\í$©ƒ„•Μä3€ô rþæ''Ïês9奞Í:QQèw½ë]¬[·Žl6K*•Š<ÒA¨ÏœuÛ)ªu:DOlÛÆ‹t&‹É?õÚ×Rq]*ù|”ömÜ ÀÌdxÚu9%“¡øŽw0tá…€I„•Á\äó§¯{ˆ¡›Ï(ÁßOÚ&Èå(ßúÖ·xôÑGùÝc±æýïçU¯z«W¯®›Š6Ê¥ÇÔ™<¡±â 3£‘óB˜ÓøùFÂâ"z­¦°5nºY—¯~÷»¬zúiÎî]³†CN»ã›9LÓäå¼<ÎS­ñ}VŸ>Rcàê%:¨5¢}ûªSsfWÇí0M(§`(±éVòÈ#_}/Á­÷P9þÍð}à]•*ïÑÃ_ÇøC}ôQöïß}è¡|äÝïæ¯òEÑ£6Jf=†2’h]×GYå“$C†õ»Ù©³Ma»8ÊKâOÿô'ŽúØQ‹zž)·iä<9ªÃ®§8Ï£×<ÊQG5÷ó,Uf8Ï'=À±ç;ãy^yã+ùcÏYîÌV>{ì1Úu0ÎïeäòS!d!žçñÍk¯eï7*Ï׿˜ç½ìeüîðÃéííŠV¯yó›ù÷O} š˜3stt”®®®¦œ{!cÕªUttt4»)óf¹Ü“…b¶òùÈ#P<ë&RÇŒõã “^¬Õ?§Ÿ~z”ŸÝ²,†‡‡9òÈ##£f³™˜˜`|||ÖžQ­Èry¦—Ó=Yæ¢ÛÖ¢åQGižxâ‰<ÿùÏgíÚµ”J%²Ù,™L†îîî¨~˜.ÚiF”j+‰N!2]í’ù"cN뱜îÉB°òéû>×\s \{íµrÈ!qÄœsÎ9¼öµ¯åo|cK.É3Ýz,—{²PÌI>s9çŽã(烵kÃZ#*«Áª„<žþTaYx•JUÍ/Ïó°Â:)†a„ãªa¨z$¦iâ…õÂô>N¡@*•ÂuÝh» \®rn(çrd2ÊårôûMÇÇç?ÿy6lØ€ŸJaæTØ•v póùhÛB¡@>“‰þ·m[mÖp‰ö±¬h›\.§êŽF¼ib†ú~ÔŸb‘T*µ­hšär9õ.‡ëº˜¡~¢Ó™y‰ó¤R©¨¶šþß5 ¬pß(Z>¯=Bç-Dz( ôööFuÙRa_lÛ&8ÑÀËå°m;ªÕ˜ïíehh(ÚÇ1Mu /ƒ?t,qG×qªT¢}Šé4©T ÏóT{,‹Õk×ÒõÄÜsÏ=œ~ê©üS¢Mú…BÇq°,‹n¸g?ûÙ,wæ—]vYTˆZ×kµúa2æ´ËéžÌ—¹Êç¾}ûxË[ÞÂc=ÆM7ÝÄgœÁ“O>Éßþíßâº.gŸ}v³»ÖòL·Ëåž,s•ÏÏ~ö³\{íµAÀsŸû\ÞûÞ÷Êy .Ü÷öö’Éd¢hN?¬G¦ÿN¥RÑ‚¹vdÐFƒ©ö1 #ÚFÿö}?2PhƒŠÞG4O¦ÍÕ¿ï»ï>=ôЪ퀺ûUÿÏwŸd˜Ú}uZ|ý¿vÚÐsÃ0¢céãŽWýŸ<–ÞG;n%·ÈåTÔP¥R©ºŽÉk¨#r¡ÑIï£U»(©v+4%Sˆëÿ}ßçñÛnãûwÜm«Ëôùôµyä‘GøíoÛlñYTæ£ÛæOú6u,æ'ÖËå¸çž{øÑ~Ä¥—^Šaœ~úé¬Y³¦)k@­>–´Ãüj%Ža8P3ضoßÎððpÕ Ø´i]]]Ó>4gžy&wÜq†aðä“OrôÑGsØa‡qÜqÇñ¢½¨ÙÝj˜‡zˆÃ?œÃ?¼ÙM™7{÷îåøãov3–¤£££<ùä“lݺ•K/½´ÙM^4æ"ŸýèGùâ¿Èý÷ßišÜÿý¬]»–‰‰ LÓä°ÃãÐCåYÏzV³»7#Ëå™^Iï™Gy„={öpÐAñÃþ°ÙÍ]Tæ"Ÿ/{ÙËøÅ/~ÁÓO?Í1Çá‡Êi§ÆÄħžzj³»Ô0û÷ïgÿþýsÌ1ÍnʼY.ï™FîÉÞ½{Ù»w/çœsÛ·oov“¹ê¶ÝÝÝüò—¿äŒ3Îà9ÏyNÛŒ•µ¬¤1§]h䞈n;µ|Þpà ¼ï}ïã÷¿ÿ=/{ÙËxîsŸÛìnÌ™•ôL· ê¶O?ýô²¯)0ù¼è¢‹øùÏŽaœ|òÉ{ì±<ðÀm%«¢Û¶¢ÛÆÌG·=þ¶Ë¸å¨ízè£<ëYÏâØcå°Ãã„NhºžÛêcI;¼ZYÞ÷ìÙþ}û\·m™•ñññIŸ5Îô³Ÿý¬ÙM„eÏ\äóÃþ0þð‡aq™‹|þà?hv³aÙ3WÝv¹/” B+0ù¼ôÒK—µ‘IZ…¹Èçw¾óf7[–=ó×m¯lvaÁ8¸Ù ЬZµjÒgcccÍn– ˆ| B+#ò)­‰È¦ ´."Ÿ‚кˆ| Bk"²)1-cPéêêš$ˆ­^tGV "Ÿ‚кˆ| Bk"²)­‹È§ ´."Ÿ‚Кˆl BLËTzzzgxxPù{ÇÆÆ¸øâ‹›Ý4AXñˆ| Bë"ò)­‰È¦ ´."Ÿ‚кˆ| Bk"²)1-SC ¿¿Ÿ-[¶°nÝ:víÚE?Ín– ˆ| B+#ò)­‰È¦ ´."Ÿ‚кˆ| Bk"²)Šƒ8p ÙH266ÆØØ6&-†È§ ´."Ÿ‚Кˆl Bë"ò)­‹È§ ´&"›‚ЂAAAAAA„V£ej¨‚ ‚ ‚ ‚ ‚ ‚ ´*bPAAAAAA˜1¨‚ ‚ ‚ ‚ ‚ ‚ ÌÀ3>ò‘|¤Ù˜+cccŒŽŽ°jÕªf7gÚ6ê¢Mccc¬ZµŠÃ;¬á~4»Ÿüþ÷¿ŸuÛZ±_õú2ß{ÔìûÓŠ´Ë5Y÷~*ùœ¯ü-ußfêÇT÷¨ÕúÑ´Ë5i÷{?×±s¦ï—ËØÙ¬¾ógtt”Ã?|ÁîõR?ú|wÜq ÚÖ¥èK#ãe½±ít„¹QO6¡½îýtòÙêºm#ãþ\ä³Ùý†¹Èg+ÝûùŒóíçB0Wùlõ~ 3³˜úÑB³Ð:öB111çy‹¢;·5ڔ뮻î@ww÷7èîî>pÝu×5»Iuy÷»ß}àÔSO­ú¹õÖ[îG+ôó“ŸüäO~ò““>Ÿ®m­Ú¯z}™Ï=j…ûÓj´Ó5Y÷¾Þ3=_ùkFߦzÏLwZ±­N;]“v¿÷s;gú~¹ŒÍì‹0?î¹çžÝÝÝ v¯—ú9øä'?.:på•W.X[—ª/õä±¶_oxÃŒ·å=æF=Ùh»ví:pê©§¸çž{šÝ¬IlܸqÒÀ9›~4³Ÿ×]w]´`Roð™®m­Ö¯éú2Ÿ{Ô.ÏáRÒNפïýtÏô|åo)û6Ó{fº{ÔJýhÚéš´ë½ŸÏØ9Ó÷ËeìlF_„…AOˆ’÷¾]žé{î¹§êøãããN=õÔ»víZ¶.v_¦’Gݯd?.ºè¢år¹íî‘0wêÉæísïg’ÏVÖm§+ç+ŸÍ~ï Ã\ä³Uîý|ÇÎùös¾ÌG>[¹_ÂÌ,¶~´Ð,´Ž½P$¯Ùøøø‹.ºèÀM7ÝÔP–»´e •ááaV­ZEOO]]]tuu1<<Üì¦Õmk½°²FúÑì~®[·Ž¾¾>ºººfÕöVì×L}™Ë=jöýiEÚíš´ó½Ÿê™ž¯ü-uߦ“ÍéîQ«õ£h·kÒ®÷~®cçLß/—±³î‘07èêêbݺuÑgíôLOLLqºŽŽ:;;Ÿw[—¢/SÉãØØ===UŸ¯_¿¾¡~µÚ=æF=Ù„öº÷ÓÉg«ë¶Ó•ó‘Ïf÷KXæ"Ÿ­tïç3vηŸ Á\å³Õû%ÌÌbêG ÍBëØ Åðð0ãããlÞ¼Pòïº.ëׯŸ± +AžÙìÌ…ÑÑÑI“øU«V166Öì¦U¡Ÿ«®ºŠááa:::èï璘¯¯¡~4»ŸúÅS/ÏÝtm›˜˜h¹~MÕ—ùÜ£™ú¹iö3;ÚýÞOõLÏ÷½²Ô÷pº÷Ìt÷¨ÕúÑ´Ó5iç{?×±s¦ï›ñÞYŒ±³‘ï…Öctt”;wrýõ׳eË–ªÏÛå™îêꢯ¯+¯¼’žžžÈ(¨'z­®ÛN%===Q@ÉçÎ;£Éo;Ý#aöL%›ú»v¹÷ÓÉçöíÛ[Z·nÜŸ|¶Â{G˜s•ÏVº÷ó;çÛÏ…j¿>n-ÓÉg«÷K˜™ÅÔ’Åбб±1Ö­[Çàà ;w£ƒ¾¾¾Ñ—m¡¢-ŠI¦ò’l&Ú"ºyófî¼óN¶mÛÆÀÀ@d‘›©­ÜÏéÚÖNýšÏ=j¥~´ ítM–뽟¯üµRߦ»GíÔV¡®Ér½÷ói{+õk9ë7Âd&&&زe Û¶m££££ê»v{¦;::¢Â¤µ“Àå Ûîܹ“ 6ÐÓÓ8Ûí 3lBûÝû©äs¹è¶³•Ïvé—PŸùÈg«Ýû¹ŽóíçRR+ŸË¥_‚b¡õ£…b±tì…bll,Š6Ù¼y3lÚ´)2Ьt9hKƒJ=ër+Z¹ºººØ±cGd½ëééáâ‹/ŽfêG+÷sº¶µS¿æsZ©­B;]“åzïç+­Ô·éîQ;õ£Uh§k²\ïý|ÚÞJýZÎú0™r¹LWWW”c||œÑÑQFGGÛê™ÖÞu×_=ýýý¸®Ë®]»Ø¾}û¼ÛÚìgzbb‚M›6100ÀÖ­[ÙºukÃmk¥{$ÌŽédÚëÞO'Ÿí®ÛÎU>[½_ÂôÌG>[éÞÏgìœo?—‚©ä³Ýû%(K?Z(KÇ^H:;;Ù¶m===QF‚ÁÁÁÛ°ä - *]]]“nÄøøxËY»´?IÒê8S?Z¹ŸÓµ­ú5Ÿ{ÔJýhÚéš,×{?_ùk¥¾MwÚ©­B;]“åzïçÓöVê×rÖo„úLLL°}ûv¶oßÎØØ7Ýt7ÝtS[=ÓccctvvV=«===‘];ë¶7n¤³³×u«Ò[4Ò¶VºGÂì™J6¡½îýtòÙîºí\å³Õû%ÌÌ\峕îý|ÆÎùös)˜J>Û½_‚b±ô£…d1tì…¢§§gRäÌrX3[0– ðý¢ÐÝÝ}àÖ[o=pàÀ»ví:ÐÝÝ}`||¼Ùͪâºë®;pÑEEí?pÑE¸îºëîG+ôsãÆ>ùÉONú|º¶µj¿jû2ß{Ô ÷§Õh—k²\î}=ùœ¯ü5£oõú1Ó=jÅ~´:írM–ýŸËØ9Ó÷Ëeìlf_„ù³qãÆèÞ8Ð>ÏôM7ÝT÷¹-—Ë ÒÖ¥êËTòxë­·VýÜsÏ=mw„ùQ+›´Ï½ŸI>ÛA·N—«|¶B¿„…a¶òÙ*÷~¾cç|û¹×¶òÙý¦f±õ£Å`!uì…`||ü@ww÷]»vEÿ·ãšÙbÑ–EéúûûÙ²e ëÖ­c×®]ô÷÷×ÍMÙLtñÜ 6ÐÙÙÉ®]»èëë‹rö5ÒVîçtmk—~Í÷µJ?Z‰v¹&ËùÞÏWþZ¥o3Ý£véG+Ñ.×d9ßûù´½UúµÜõav´Ë3½~ýz†‡‡¹è¢‹X·nccctuuEÅIçÛÖf=ÓcccŒ±iÓ¦ªÏ7oÞL[Ý#aái—{?“|¶«n;_ùlÕ~ C;ÜûùŽóíçb2“|¶k¿ÅbëGKA³Û×ÑÑATF×Ñ\kf ÁA8ÐìFÌ- -64::…6ÕkçLýhå~N×¶vê×|îQ+õ£Uh§k²\ïý|寕ú6Ý=j§~´ ítM–뽟OÛ[©_ËY¿fG;=Óú|«V­¢««kAÛÚÊÏt;Ý#aai§{?|.'Ýv6mkç~ 3Ó.÷~>cç|ûÙL–k¿„˜V’³VmßbêÎíL[TAAAAAA–‚¶,J/‚ ‚ ‚ ‚ ‚ ‚°”ˆAEAAAAAaÄ "‚ ‚ ‚ ‚ ‚ ‚0bPAAAAAA˜1¨¬ FGGfbb¢©íc`` Ù—CšÆÄÄÃÃà 7»)“ùZ‰¥|§’ÇV•UAbæ2®¶ÂûEÊlts!IDAT'ïa¹3Ûyh+ȧȦ°´ÛܪUÖŒ’´òÜYÚ™v{?µ8pà@³!,.lÙ²…]»v±jÕ*ÆÇǹæškèêêjJ{†‡‡Ù´iwÞyg³/ ,9ƒƒƒ D²¸jÕ*¶mÛÖ4y¬EäSh%–êyöíªóŒŽŽ²eËÆÇÇéììäšk®¡£££Ù—E„sW›ù~yÇ+ƒ¹ÎCeü– í2·jµ5#M«Ï¡i—÷S«"*+mqüÎw¾ƒëº\|ñÅ‘’(ÂÒ200@&“Áu]~üãÓÕÕ%^‚Ð$ÆÆÆØ¾};›6mšôÝÀÀ]]]¸®Ëw¾óè3AZ‹VW§{¿èvË;FXî´ê…Vb1žÇ¾¾>vìØQ5&‚ZPªÎÓÙÙÉÄÄDôÝtcçRÉêRŒÓÂÊf¶Ïs3tÊéÆÕFYÊ÷ 4öŽ„™˜N®ZA§ldÚ­6þ Â\™êYn¶N9_Ymõ1^ƒ¥^ŸYìyŸ¬ýÌžg6»+™õë×Ó××Y·nÝ ¨cçÎó>‡¶Xnذ!últt”­[·FçîïïŸr°ìì쌾ëìì\]·n]ÔoAhëÙß¶m7nŒ”æÎÎN®¿þz`zY„¥yghD>…Vb©ŸÇz‹&Z±‹ÞSÉëRÊêbŽÓ‚³{ž›¡SN7®6B3Æ»FÞ1‚ÐSÉU+è”ÌC9F«ÿ‚0¦{–›­S.„¬¶ê/‹ÉRÎùô1CÎdígnH„J©UÈj=aê1<<Ìi§V÷§^˜¨ö6¸øâ‹¹þúë¹þúëéïïo8<¬§§'ú{ªB|³m“fãÆŒŽŽVCZ…Åxö'&&¸òÊ+¹øâ‹Ù±c;vì £££áp)Þ‘O¡•häyœë³¾,¥¬6ò®„ù0—ç¹­8®Bû½_!É\Ç€v˜‡‚ȧ°|˜ëܪ]dµUÇxAXLæª#/Ö¼OÖ~–‰Pi3zzz¸óÎ;gµýöíÛÙ¼ysôÙæÍ›`×®] "0³m“fݺuôôô000@OO, mÇlŸý›nº‰±±±*¯šmÛ¶aÛ6£££‹Z)ò),yçú¬×£ž¬½ŽË;u!Û/íJ3ÆÕ¥~¿@sÞ1‚0_š1] ã¿°2XʹU+®Í¥]͘; ÂR°Xó>YûYZÄ ÒfŒEÅŽjééé™4Ø­Zµ PÖ}- ]¸h¶mÒèP²;wR.—gOWšÍlŸýz©ôÿããã-ÑFȧÐJ4ò<ÎõY¯‡–ˤ̎ÑÑѱh * Ù~AhWš1®.õû%ÙÆ¥|ÇÂ|iÆ´Ò5Õs.²)ŠV‘×VKEAhE$BEAAAAAa¤(½ ‚ ‚ ‚ ‚ ‚  ˆAEAAAAAaÄ "‚ ‚ ‚ ‚ ‚ ‚0bPAAAAAA˜1¨‚ ‚ ‚ ‚ ‚ ‚ ÌÀÿ ‡¢ØÁhã]%tEXtdate:create2020-03-05T16:38:18-06:00n;×+%tEXtdate:modify2020-03-05T16:38:18-06:00fo—-tEXticc:copyrightCopyright Artifex Software 2011ºÅ´1tEXticc:descriptionArtifex Software sRGB ICC Profile †2tEXticc:manufacturerArtifex Software sRGB ICC Profile\~=Ÿ+tEXticc:modelArtifex Software sRGB ICC Profile1(‚¡!tEXtpdf:HiResBoundingBox1584x864+0+0û8²ùtEXtpdf:VersionPDF-1.7 7ji»IEND®B`‚blis-0.9.0/docs/graphs/sup/dgemm_rrr_kbl_nt1.pdf000066400000000000000000005454121422157504600216000ustar00rootroot00000000000000%PDF-1.7 %Çì¢ 5 0 obj <> stream xœì½I¯/9–ܹOq—‘‹¼âä¶ ¨ hˆÜ ‚UÕ HÊF©zÑ_¿yxÌìÐï{1"h!•¤ŠËçº;Óvhüé3$ûüïøÛÿê?Ž¿þ¿?äûŸùëÎ5§?—•>òl#}¬RÓÇ¿üÓÿ÷/ýSN«|ÖõÑgJŸ³üí‡òÌò¹¥üw¥ÌœÒþó—~„Kx~ñ|ü?ìgok¥òñíüÇóCnýùLõÊ3Ròó9ìA~RÚÉ8.™i>»dγŽÏ>î|”råƒ4æÃ?#ŸRrú¬ù~G¥D>LC>ú3ò±wœ«ôoÿc´ÿ±‹ê|Pü¯øÛÇÿñ—ýiçG.Ù%íÿø‘kÿLV=î²ýøËß~øO?–?ý¹ŒÏZkÿ1½þ3×ý5úø±ýòíÇþs”aÿÝþó_þíÿú/?ü‡ï|ñœÓ¾äª%?}Ss¬Zôù™Úë*f5RnŸO‹¬˜pg1«û*eUÊü,ùÊ ¯¬t‘²º®RV­åÏ9¯¬ðÊJ)«ë*eÕŸçó¹ÊŠ ¯¬t‘²º®RV³¯ÏR¯¬ðÊJ)«ë*5ÉdW_eÅ„;«¸ˆYÝWýÖJ»ú¾ùØ fìFº¿þ©´ïÊõçñQògícÿð÷¿æŸ«…ɯ›~Ùךÿõ2^W-»æ×}m(?—ßó¯ûÚ®Þé?}än%ôŸ÷ÿûÇÊÇ¿ýM½ðOï^õ›>÷§ï5Òw?üý&ú%—_øºõó|_û¶¶<«à‘çn’Õ?ð¿ùSIŸ­”ñãÿù§ö¹ê¬?þ_*Ïg_cüøïôÿ~÷BísæÙüéO^é󽨈üÖ¿§ƒÌûEó®§yíj:üQþ1>Ã_ã?ÿéOOÿñoús:>ëõßÿ%®ûìºóÿ]‰ÿr]ûsÿ}]~gÝ¿dýÏñ÷ûçïÕ¯ÉêÇÇE‘ØH™ÖúœÖ©ænƒZr±¿‡‡].{λpÇþÎk´6NJ)ûóõµ[eîž°>»u±ñ£= Ú×|öç|NBkÖíŽÒÿ|ÊgÚԺǰê)ë³í vSÚßò¤ônýÄh»Ã5£}Ö±SâÎsw–åc<½}fÿÕÜÕÜ)©}&¿f_=vG·«Åç:OWö¿e»¦×Ï>OJΟÝúUk|ÃSÖ-åùœç™Ké6\Œ¾«ØÉ¸Ôú¹ì’¶>³_²ûî¶ b—ÄgËž2?í’ýTÏy‡Ý ~V»¤N{_KÙO1-¡¢ðÊÈŸÅ.ÙÜ–§ÌOk–ïl'ež"ãÉ|©µ_&{Æóüª¦lE0Æn—ÃöçØ¥5ú°¹…¥ì ÈÚ%j¸xJÙŸ¹Z6õÖ–²¿Ñ´|ö¿O™»‚Ù¯xóÚöDf_3÷µë”hÝW8öü{Ö¾ËÍF vº‰“2÷ Æž'ñ^»ƒ?O¼ É3Þ=C:eQ?ÏÆZ¸Ý»Û; ã ZcÿC>ïÙÒcÅ?¬ OOÙzwRûW;åüª•3¿ÚO¼ëÂò”a“±ó«~¾LÛePìšf_Ț͆vBáÓ´'ÙWÛ—Lk7'e|>Ó_Üsñ™å¾wóÏÐFùlÓ ½7OÙ}]Òvë;ïÝæðá:o5ûöcî/^ÎÓ<©Ø=O¡×æ)ËÚêÎgí1ä¤ä£]²Î,r·»všêÜOYÎÓ<µ|fÿÉXž°NSýt –²+²Ê¨ÖÏÓNkµ×^§<ŸÝöש~¨lÏž1Xc»M ›]Ÿ­±ÎçÌìŸÙìö}†µ4KYù´Të|¡ÝAYK»^´sŸîß}_Óüú¡NëÎ;[#¶†ú¬ýpÍSæi©SͰïi°µÔ¹ËgxÊþÈvÉÃzÕwA×STêtßÝ™=Ì®¶Ïyྋ¨ 4›_²ë©µÔ¹Û°÷ »s=-uªùô9OK»bx…í»‹²–¯9R=MuîzÐÏ{Ž §©îbcÊ´wJEq 묦(ï'¬W9MuÔuJg´äMuœ.ø¤Loª;Ÿá×<7Õýìç‘Çî£ò¹¤Xs´”a½àU»Ñž–:÷ÿößlr9'”ðX˜]îñéLK³µk¨ÖÓ¥á)ã4Ôè׬yCåP1÷øsªr¶; ÕºÒå)Ã[ªjÅÜ]Ôi©ÖéxÊ„NKl?Ó:"+­ý½5[å²Ú5ÞÓ­î#«©7™5|dµŠ<=ays­§g²”ék¼÷Z>°Z#:EIÉÖùœ!ã¤ìuúkžÉ@IÙVu8%Y'kAIÕGÖ=1þ¬ÓSÎÈÚö‡~«æ#ëFbŸ ”ôœ‘ÕºïSG‹MPÎȺÛÛã¹tY­Ë©~§á#«ˆ§¤é#ëî·|*PÒò‘Õž7_>´Ú×ôkrÂкsž’«·×ÝÞÒ¹ûž‰x{e§³S0´6Ÿd”=zsÝ_hyJ³ÉòÕé”Ýï{så|¦ØÄë´W›ø¯úY­Îçv†¬aÊn|§Áf¾ø®ëÞ`w׃|FV’eÙßÊGÖñ8×`åâ|òÓ-팬˞z{ÝÙT¿¤bdeU/¥qdm^‘wÊî7N œÖJ-åÁÐÚ‹×É=GÃØZÑoe9v–3?^^—¼^”écë(¬LealUy•åc똨ÿ¥&­þe66 ½î!éT¦Z|p-è…vWÎ÷$ƒkc¬ ƒ«Ï¼-åñÁu³³Õ©“‚Ñu÷Oߪûè:ö'Jþ|lAŸSêîÏGñôjQ'X]NÂòñuÒ÷whÞ` Œ=ËõvL 3;¬¡ÁyœV0Àt¥¥Õ3ÀîY7Ô0ÀZï—´3À̰K{||j1­ûø:Îb×\GÁP°S|pµŸ ’éƒëÀ,®´åcëØåræ×åI[Y Oò¡uÿ|þ'ûÐÚ÷zu|Š­6Íð‡{ª­œpï„yšª ŸÉÔ|díìõwö¡uXŸç)ý ­mŸÞêÎÊÉ™®£Ž3¶Ž¾ŠE ]ÛOÕûÉÒ/ý_‡Â`À=ãèíÅ€{<ò¹'pòåÉ€S“;0`?ƒª§ìgÊà æ ¸S&° Ø—Í[üÇÀ“â3a`àž"LÝ}ípú|°JÉ/pÜ„š0U"¦=íó)0ÙdÑ! ˜8”SC‹&1bÀ´»×éÜ‹ÒjÝK ˜m1Ãoå ˜VåÀ7¡} } ²ãÅIÌ< Ìì7D€YÌ@Ì¥t‰€Y¥I´7x ­?HñaÊÞÀ‡~àyÝ@€V3@‰ ÀìspâŸeë¥ ü³<ü+ÿöscÊüÛLÂLV Ù) ø·§ýLþmÆûN\À¿=íÇ+ÿ²fÊÄ¿xò_ÎD#òŸUvÿþä?k!ý€óÐzH€û«¢±wÉò^ @›#<ž30s>#ŒÏ@ÌZZ ÖS)ˆ€YÕ…L´;ù\™˜Å£DÀ̾Yh=г0'V 2`¡íq Ï10³Úóøb1Ðò®­—)žÜM†ho1_hup9‹9æ¶Ð@ÈV¤ýæÀ¬®Žx=8Ðê©·2 }9o dÀÌ9ˆÐ&Õ>&‘ãã½É€ö^Þ¯çƯȀQ“À€ö¥œ³É€V­›§¬­îÚýq!à• 0s:+ÄW îFü9ü'@û‰ç þ³îÇþËZ§$ÿYÇmÀoÄ™ëMâ?«ž`0ð_N´þS;ÿÙó-¤`TíKð_²ÏÆùïJèU#Ã*GñŸøé¿ÅÙ–ý‰ÁÖgùì›ügÄiâ?µnñŸõY§A‰ÿ¬ñ¾ð/Sÿ©Cÿe®eŠÿ40ˆÿ¬¸üC€ÿÒîaüoàŸ=ØÎñÏÆ?Çg⟪‘ð_ð/Þ‰ø%Aü3eŘüg=³#,ùïºü·§X˜^“ÿìÅýë‘ÿìË8p‘ÿÒ~™"ô‘5‡d þKûýp/ðŸMѼ–’ÿödø³ø¯À9¨Ìù/íÉtÿÙÍyËñ/- I¿4HÄ¿Äé—ð/± þ¥>>ýПÕLçgÒ_öþ¬¬ý%¢? 2ð·$þ%.Á ÿÒX¨JÄ?{‰3J ÿRcQÿ’Í üÇ¿¤:JüKZÁþ%vdâ¿ÄGü—l¶æO´xFŠ«éÁúº0í‚Lž0qv%´Ñ^˜0¦EJ ˜8Ù&5B`â .L•Ÿ˜8±$&Š‚À´ËÚKx= $Ùµ0w1löÊùÿïÿþÍó­_¸Øí‡uÏZ‡OM}€…­4-ƒx8É3ù¾X49–¨I#•À‚nRBàî1Ë%î Ó šáSB`±™«S 0Oa! pwÞˆ‹f¾¤À=¾ 0/" ÐnÐn´üq'BàB‹%îQÔFA`ÑD˜X,tÅõDPàî­}aTX2‘”h]súpµ‡¨Ä@ËÇá‚h]¼Ï+ÈvwG$r`©ènÅ… b •hvxÚkù¼œ$x=Ž“`áš“H0>0HÐê€W%’` u$hÙ¼…@ûõ%Ú(å¢(IÐ üŒ{‘ ºz •qCŠƒ`‘M,À‚ö+Ÿê÷ü“D‚àžÎÏ‚ÅdfÇ*‚ ý ÄA WÒÊ‚ñ9‚“m OL´{ƒ‚ö|¸7AЦ·/-pó Ÿ† ÈåÊA6"qàÊü90ž81·œâ7r –[ÄÃAŒ¸§>ùr¢(Œûã@`äB”°&œì:ó´€ÀOy‰›žð]ú•8pbJ8Ø{ˆ99 ”'\›ƽȃ+;äÀÙyp g âÀ1I“DA½•PÐÄ"—Öˆ‚[ŒP°³ÅwÎ?  ¾PppÙK(Èia à˜„:¢àÀ4Ppçó¼äÀxu¡ ¾±Pp O 2¯HppÝ“$èE. ܸKþ-f)vÄ@=¬0PÅ ´ªê÷% ÚŒÊPpÿÊÄ‚‘3YsÂ`Aæ,Y0è,¨¹¥XpbJ,ÈŠMÔŠ–XÐÀê¹µ@}¦`ÁÉ‚ûÞÝu>² Ë"Xp¼„À+[‚ føA.í2¨%@P…%”À# Ý$(á4Hk?A‚lA$A­  r [(H%:PÐer 5B‡,bàƒÕéÀ@¬¦Jufép¤@iD¢@‘¶(PŸVh ÚKŒ"'fIs¤À,f!^¿"rm2(Pë Àl¯ç ¤@ÍîöIdA`àb¾ÄÀàhb`æ°¸Ÿ š8ðL²];z ¦ ðÊhKØ.¿ ´Ž€@›ï;s¢¼MÔòt@ ÅË8á9ö¥5B ÇxA`æHÈŽP˜÷Pï `ÀlAkžÌIäH\XY!Ze›N›D@ÉÀDÀÌIºÐR|QD Èi{0 >&д ”Á‰5›L‘ H‘%Ðp U¬@@• pAûˆhwR,Pÿ7°ïK¨×[þ[ŒÓSèî2Ò:¬GgB@ a€_rL!õ©°~¶ö€‚>:¥!bø%MaH~Ic‘´¿A„ä—,Æs¦ü§\òŸ¦¨’ÿuéñ+꺻ô?Múˆ~‰ƒ=å?MH~I*Êüô"¿;ŧ+ä§E+‘Ÿ RÏK´%PýˆÔ—xXŸ´HD‡7 _ÒÜÈgOë ,‘/)¬žÈoDäK Ý%ñi•ZÄ݈/6|)¨Õïú €/R|Zßð©~÷"ƒ¼m¼we ދΜ¼—Š#Þ‹â#ï]¿ïÙ½Àà½xOòÞõ<à½ÄÙ°€O¯EÞK¡9ïY#\/åïJqä‹oIäSçCä‹ÁÈ›ÈÏKäK yòiÍZÈg„‡Pùâæ >ÝJÄ—:'›$>»"¾ëW…c*§–$¾Ä Rÿ$/Hý“0@õ/ ÄT_⊰ˆJÀwýÌ—¨‹ùåi1_Hd¾ÄÝb¾!£`¾DYVÌ—¸FÌ—IæKµÅ|ׯ þ=/ó™FÒì郪ފÌw= å¿]+ú+úÓ ðÍ}öe*âA1®6H侸¹Ï'‹‚¾¤ IB_¢t.èK ¹éo7 ϕʟT)VY<…ÊŸÉ|×K‚ùR„uBùkXmó% Húkb52ŸT)I‘ ¥?ÇlŸÂ%ü ZoáÏqXŸ”6 6¬¿…?éÌþ÷Â#BøóÉÀÍ|-£‡ðG`¿„¿úb¾$^'óqvŸÀVŸڄ?ÕAŸ¤g Ü<Ô§²ð§O%áO‚¿¨8GäSäjÈ~.…ê—Põ+˜•òE™RõkÄM"_š” |£B ƒAºvüå¯êÞ®8õ-ï™ ã GyÑÄ< ôé1¯pµƒ˜WwGå8гšš_ ‡ÚsÞà mÞÃ&&Ð{4&ô:ÃðzµD ×ÙÀz»LÉMÜë·í!JÚë·ô+€Þ°¦é)=›P=ïÍ~¬Ø$= ‹n¯@Oîj³_áö möÛµÃé{ýö ѵ&íõ[õ‹Ä7EÓŸßë'º÷ú¬¸×O»â´×O9oh“ Ao ”Dœ7Æ×@Ï!ÂÕV?íˆáV?ív!çõÎ-Yà¼;[ý]FÔ³Éf{)|OÁÌ”¤÷HK$é 9Æ“ôíÊ$éµ2^Ó<Ÿ¨÷q&PψÊ5ˆzMª.Q¯íÑÔ_‹¨÷d.XõžÌÍJD½¦ùQÏzÆv+|vé;Ô³ñSôZçÆH’^ÓZ I¯iIÏÓï ЫÒ zUÛ¶zM2I¯qù_¤×´¹Š¤×DN½¦M£½öL*~½¦I:IÏ ¿ê5…õšÂW‰zM»¢€zM]Q¯a*#Òkš'õšBr‰z­@Vê5EÏ“õdþ Ük b&îµÎðnâ^ãÖá^cp/j-q/¾y¯)<š¼×j Þk6±’÷ç¡ä½¦.œ¼×QMÞ«±s¼Wõ0¾¦¦Hà³ÂI¯ý~Ó _ã†'Ÿ}šþŠõlœ¾øc)É{­3<€¼_†¼g¥"ï]7ï5Ææ“÷£É{ñ¥È{M¡ à½Æâ^Ófcò^Ô?òžª(q¯i(#îµòŠôŒoMÖ³÷)/Ö‹R ì5)M„=¸`¯1’G°×Øó öš6löšfƒ€½ûø{u—¡_ᬧú ÖS¿!Ö«¶º‹õšôÂ^ý€=}ZÁ^Û¯’^°×…HØk{ÖÆ öׯ{ÁS‚½¦8IÂ^‹QÀž:cÂ^höZDŒ:ìU®l öìS¹TCØ««}½ÊíMd=–ç+Ô³r˜ìUé¡„½x¯rcx¯Jê"ïUÑy¯¦çK¨gå`&à+]aœ¾ð à«1U¾(R_U˜¯j;€/žÀgÿ€èO_e¬–€¯šçÙ€ùJHƒ`¾ÊV/櫌5óÊ/b>»ç ù*„| 8"¾¢ðm_”‰Ïæ—ÞhH|…ói_MŠ¿ñ•ɺâ+ÒI|E»$¾rvúØZ¸áXÄWR@â+U â+œžŠø -MD|…3Ÿ=¯ý~ŠWô)ÒNÔgítêÛU] ©ÏBÇö÷yô ÷‰ú Æ%B_QŸCèS į‡z¦oC=}“ÝKóã8"ÍOñ1ÔüØ$#ØSÓ@{J$ ² Š£Hƒ-aqР¶éˆ-˜óEƒÖ|Eƒ…ˆA"OÒ IÁÕ4üÜ5+œl¤‚Á¹y½>ç#‡‡ÁY¥Î§ÔÀàÔ¶Âà «Ðà ­4X·÷›æý¤ÁªX:â ¥¼>mIHƒU_œ4X%/‘W¥åipÙººCppUj3ÄÁ5øõˆƒË–=gÇÁ¥Y qpqõŽ8¸dwA\ò !o¢—ò·*-eȃ+¶‚‡YñಈޗõË¢“ qp©—4nâàâáàÒ$âà’µqpuîI"®Ýö Ð—¢j‰ƒ6ßóÕààR•$.Á2xÐ g½>¯Mü_/ó—eHñ øÔöoáÔÞNáÒ~(árš! ®Æ2' .9Ñ­Rx—C\’¼ˆƒK¢#qp… ppÙ¸æ¿r\ꈃKü\ßààB”ppÑ…4¸²î\rJ" Úó® .Ù¯—ÙƒK± „Á%; eÓ_0xÝ 0hõ!¡€Á(tÂà’jŒ*A\¡: .ùà#ÒàJðX .¹ò—V,Hƒ+\[@ƒöy_0xý0¸è¢!\´ð .Ûaý¢ÁU¤‚½-DƒëâC§Á•µí4¸dÔD\™€ƒKûˆƒK»rƒkÃÏxE|Úoó+äsiÝHî/“” „‹38áÊrˆ.­S’ £ê £'®f/>ºªLÃþ%0Œö/\} ûöôbÂÉž‹LxêÐkûßÌô[¡ýËÂ&fAáu'Ú¿hb*û®Î ­”ëKTšÈ„+8 L¸dš!÷—ØÈG÷ŽÜ_ä!û¬f†ûK‡¯Z¸¿p³¶P>4‰8Qš¿h{Í_*VE„#ø”æ/¡$—ù‹â5iþÒ 4DÂÁ7 v™çÈü…}øeþR¾„}Ž0v¡ù‹Ödþj$ˆPKÓ"B¹Å‰ÍÃ/¡÷KúÆûEMïɆBë÷Ò „Zhp(¸˜4Øõ±Iƒ]Û^Iƒ#¤G¿D hð‰°PÐàôM|ºˆ8øh›+qP"âÁgº¸#|hB!”ךp°Q oˆƒÏ¬Œ ulðDƒÏƒ”„Á'€0Xiý(|äÙCl6%xy¿<´7 6š k¸¶ÛþˆÎ‹`Á&Þ& 6†Škð"XЊf¾Ì_*ç¢dAí= VÉð„A-v…/±7±ŸÂË»žY·Mk³†øäË–)òØþùá^ _„àø_Å{³ÀYÅ‹¼#%ܰ™ƒZýnØ{îo¦Àw>J¹òAó៑O³e•y»|GJäÃ4ä£?ÿÞîÜuÖÓÊâïéÎ=d›]Àÿ´ÿ·Üo¿|ÝmÑþë¶þZ…¬~ØÄüu³ ãmfuo3«¸ YÝ)+o+«Ëx[Yé*fu]¤¬d¼­¬.ãme¥«˜Õu‘²’ñ¶²ºŒ·••®bV×EÊJÆÛÊê2ÞVVºŠY]©iÊx›YÝÆÛjϺ Yýwn[†L{ûßîÜ¿æÎý[zãŸÞ½ë7}ïOßm¤¯þøû-ôK.¿Û»î=ÿ¥|±w'vgýÏ‘l¹~nú˜?ÎH sìòëæØ»L÷4ÀF#&°Y±sù¹šˆP7°²ÚB¹»ùrbµ•é³É‰GµÕëÞ}Íú,U,‹[];Ž=YLÐ?°æ¿S¦ÍÊÆÃ-ÈÕÖTm¶ûЖ¦šf³Ý‡(ûE“­‹ï9wÊ8³ÝÎ=9ÕBwlº;N»øX÷&¿ÆhíòiÝ Ã§»„+ûnuˆ…ÊjŠÏs0¿_/ù”ùñ‡³x‚îëŸx¸Õ|‰þ¡õ¬iv÷7=³ÉzD¬ìXw ®¶<MâS¼X|eᬲUSÐòð…¿—)qަè†ëÑ… _©ãUS»Ÿêph¦š0|–’h…\›­*W ^˜÷ Êž-4_Kâf¾=Îç³–/ºã¬%Q·ØE¾ÿË.ýðfæ‹Iœ©V‹q9hJ”Ú)Ë“tïÇdÔì+«g¢_[ê:ëwØJ¿§–«IÉW“ªUª9|‘ô@o}z÷Õ$FYì*P}5‰‹>Õ*žMymAÖÛÃcË]Ë_Ë¿ÍcK³í.SLîbͱö]íÔ {¯+ÝöÞ·²U~_û…j·gë°}Eìƒèt½U7‰|­ÙV„Ö2ϺËîÜ«¯&qGʵÒi°‹qH;eúrw¶ì!æ9 –+µïꙊ'B¨Ã–*°~èblŒ:«I4êֻΊÚ0ë‚S½šÇ!ÕaË]géìY‰ÇYqb7dä‡õˆä7Н&qb5Óõì+*ÞŸ+Ñç®Èã,QQª¯¶œpÖ}a µ–¯$ʪ¤Õ~7!ó|ÙSÎ¥š­äi®\êªÖÅ,~yS´^ä4Wn­fSÛ_MÑÖNs¥4_ÍTõ4× ‹ìj‰7W,CWóÑ=Í•13õ8Ÿk°ôQͤ™K¿^Mæì§¹ª M[Ñî›[ï3®åí°¼¹RÀ¨ËÜ]NSLhTV¸Þ\a?\­cyòµVXí¹NsåRµg?Í•ÔXÏ]‡·†óÀÈpÈ#³š*1 Nøoœ…ŽrƒW˜gÅò~šÝMåW£ZëŒZ§û=£WK»Ÿ:·´‡¨çj. ±ª§Ù9qÚ6ÁvõR-Õm5{mk'^8„ÊÐ,rÚÛ*f§øàº(P5s:m•C`³í®Ó ºµ³Ýg\­w§øàª5åf›9›´‰fK]¤ñ•fûUOCårO³ À³ú}ÎØÌ•ñ4TžfÐÌïê4TnÇk¶ûøÜ«ª-ûjV´—f&mù#Vñ›y̆ʮe€Éó¨þ‹áëb\l3ŠÓR¹øØÌw£b ÿ¬N4ó9-•=ÍêÓRMÛÌùå´Ô!ª™µÊi©TmšÙºt¬ êj¥b`åñ{|æÀŠóšIÝk¾òy0°&˜´Ò1°Ò<·•ÑÞ"M++è›…%œ–ZžÐÊò•a?­& ¬x[ÍX]Ý WÙ‘4›û¸ê3½V+†U¾Ðjðª’ÀºÁX⼋=3ôU:A{ž3 .Úq5[¼ô 0¦(íá/ü¯áã餿ìNY0æÇ>§öLP%ß´gù€* ö]–i`±S|@•ó÷ž¶ú€*·÷Öˉò?9WO©FßpJß)> š¤å û+[+êúãã©„˜fkWsy|¸×h[Q®ÆŒ{j}œñTçûëûx:Oµ§Õg<Œ*Ú >žvªK¾d‘=ÆâÈ.mdOeG­™ úÿVclñŸ[xÝüÇÝâ¿Éˆ=ò_7QÂ'@À>aÞGþë’=É}Ñlü×ÕG‘ÿzŒÄ࿾¸!”ü×wî‹ÿRø/ifEþÓ"ñŸé\¸—|s¢àügNØëæ?Ù>ŠÿUœÿ2MÈÄrÿe:ƒ‰ÿ2eñ_†¸%üË‚ âŸLf…òVþ)šKø—¹ë]øW¸Hø—áP/úËzIÒ_Q ýA‘þh&ø+&ûêMb¿BÛ±_iÅû ±ŸÉÎäd¿Bu±_a(„د'د¨ò‘ýŠf“d¿¢ïBö+´Iûê(b¿ÂÀw±_aؤدp—+Ù¯0ÆYìW8f’ý ×AÅ~…{ÌÄ~…×b¿" #û*Hb¿ÂM>b?!Šý,À«½à¯00IðW¸GðWhd%ø“™žà¯¨…þäF(ø+tK&üîEüš\þ C¬EøràïÊðŸ—ôW¸÷OôWÄ7¤¿¢Õ/Ò_²'ø+”z…NÞ‚?…¡ þŠ:-Â_9Ó&‘_Ñúɯ/‚ü w•Šü w­ü Ý’D~;„ ~…{~…#´À¯pC¸ÀO«¿ë€_áé0¿ÂÑ¿›%ßÑÂ?.î+ŒøžÀ#ð+ê0 ~…‘ˆ?U+_áê'ÉO?ùYy¶›ü,!9Õü ý2D~…ño"¿‚1TàW«(ð»2øÅÀ}ìÐ ì+ÜS%ìS— ò+\œúiýVèWx´”Я`“ȯpäW«.ò+T`H~…"¿">äg þh¿Â5:ß•ð»àWÀ¯P¨ø©æ üØÅ}Ä„}…–„}…§A û®{û ,öA±¯ÐýاF(ì+š\ûØ0D}V4þI}q ¨¯ÐŽ]Ô_€ØWèž&ì+\³ö•ñb>õ2b¾(*b_¡eˆ°¯Ð,CØ­‹Ø‰Ø§Ž†Ø•žØ‡§ôEý ô)_ÐGè+"BŸ}#-B_|}BŸ œÌ§XاîKØgÙ,¤`(U!÷Šû }ðÄ}êÅ}EËRä¾BUCÜWÖà¾Bƒq_¼çá¾(‚_T‚_48‚_i"W€ŸF4Ÿ"A~šTü¢ü4™øE©ü 7ÚŠü´oFäW´öBò£O³À/ àWC~2ˆ&øž!ð‹@ð+Z> øÉ0Xà'#Æßa†ÚßÙŠw±Ÿ­§Œ[û;n,>‚SûÓI4ÿ £ÚCü›ƒ×Püƒaò¥ýQZ£ö×è&-í¯éAûÓ/±_ Šû1ŒIè× !ôk ó$úi§Ð¯i~ ôk<5Qè×*ÎÛtôk< Jè×—'ôk\Pú5M™‰~ ¸Ð¯1¨Nè׸l ô‹§#úuÕúéÈ-¡ŸEeè|Ž~óدiŠIökÜÄ$ökÜEGö³ÂßÃÍe¤¿&¶&ý=<¦Wô×xø€èïñ-¢_£E€ÐOÛÃ…~vMGŠT»Ï„~MÒ/ѯIe&ú5ZýÚâôœè§måB?û•Ïlj~Û/‰~WÐïìˆptôkj D?Kq@¿ë _c̤ЯqˌЯqíPè×Ô¢ˆ~Ë ýâ¢_“èHôk Õú5ÎÚI~Vë¼þ‘ü¢!’ü‡4’_‘üÜHòk8 Oà׸ƒ¦€:€_ãÈ.ðÓFtŸ¶M üâù ~!¨"?½4Á¯q¤ø5¢€À¯qdø5aýG±_|²ßu دIcû5ÑÙ¯ÁõŒì×xʬدo‰~mJÏú5ŽþB¿¦µ(¢ß•ôkÜY+ôÓ ¨b¿F9Lð×Y-øk’· M „¿FËeÁ_ ðÇîd¿Rدa¡Žè׸$ôk!Öýä!ôkÁ”`?uèb¿FG3±ß•à¯1âBôwåú‹w ý5îÙý5‰‡¤¿R è/îNük´©'þYçAøg=ºS/ðOçÙ ÿCžÿš ˜ü×B_œVYÄä¿ê!ø¯I¸"ÿÉüDü'çñŸœC€Mä@lRªH€¶/"@õb"@Y‡ˆO×6«“eù!TßAl´EÆÓãGdÀÆSÄÄ€ËFbÀ+0`ã¡ËbÀV)Ó›$/b`£Y§0ðÊÈ\oN lZ !6z‡“ã­HM l!!¤‚êË‚QÁ+c€ ¼#‚r; Fµ 6Æ»‰]gD‚Ú| ”φHP6 "A M"AÛ8P_$Øà×,l<á XÕ€ ‚g#;6 ÁFÇ-  =‚2yʺF ¨y¼@°òüx ü&‚-±K$6ê/ÁFs1 öT›ä]‚ ¬LD‚Â’ U;¿@°qo A°ÒÍX XÕ÷1 +#5Ê ûð_1Äúù*ñ~HöI¿Šû\”÷Iï4¡_Ö"6ÑOgYˆýJe‹ý²f˜d¿Â³ÝÄ~ægà³<²_¡£”د°x!ÆþŠ‚ÄB|Á_áAº„¿¢è)Â_Áî8g¿"uŽì’ÙOK(b¿¢Ø)²_< á¯0¦EðW·Eø+<6PðoMøÓE¡ûqwà¯ÐGPðwÝŸ´V ’“(üÑ•&”?¥?úG…ô‹½Pþ({‡ò'6ò§À7)ñ+)Šè¤òG³ŠPþxLò¥üa¯ðÏf0®×HùãyN¡üñ€³PþÔ¬¤ü)xÊŸ"¥ü©UQùÓ;HùSÕ—ò§,å/²¡òWÑIå‡4‡ò§àL)èÄBøã Â1 á''„ð &á˜+á&H!üÑçGŸ¢%ü1\CÂ_óS—B÷ o yãù¥û¡öIöƒ±L¨~ܨªŸ´B©~ÌEªŸH©~ ê'YªŸÖ•¤úÅ­(üñù¤û©W“î§^Aº@!úñäêý˜@ÕO°T?®ãIôS¹HôS•—èÇ«ýh¢ýQBôS(…T?†Ï„ì§Ø\É~ñ”ý RócSh~´® ÍE'ÍýUh~lnÒü"š_ùFóck ÍOëÀýP¡ù±WͯÀ)>D¿¸U?öî¡ú±K ÕO!©~<.T¿ò5à3Y²!”ì§G–ì§Ç¡ìOCÙ/žæÈ~å+÷•DIDº«Hè~‘-u?4Êý4•ìWqHGÈ~<°%t?Œ÷¡ûi¦)Ý›C÷cÈÓ¥ûqZ.ÝO¯-Ýè’ýxÂwÈ~‘ÙO.Ý£Jè~t¬ áÃA2Bø‹k(ü©®IøS’öGW°Ðþ8è†ö¿ôe®i†öW`ãÚO¸ í#´¿²¤ö—;Hù1O!ÿ])P³òÝŽCþË’A}™§8„ü§J ý;BÿS¥ô?†á…þG?¯Ðÿ8#ýO/*ý/+Ø’ú_æ2©/k%GúŸÞا3DCÿË’ýßè´ó ý/K‹¤þ—Ÿ/Ÿ% Ø—aïò_vCAŸN õKæË‹¢µ¿¸µ?¯$ä³¥òéè.!ŸNØ“ø—$3‚ù2Õ‰t4 ñçM†øG#;1Ÿ¢ûBü›ˆ_úŽ'¶HïI§Õf‰| ÁéiÊGЫ‚‚^c8¹@/t*‚ÞCS„Øà'eƒ ×Çz]³mð !  g&BýË?<²ö÷i²Ëý}'íï£m9o "^˜7sw8ohÅšœ7`,Γ÷†8o°Åö>EÇ’ó&¿·8oJ1#çÍ"!œ7©uó®l€yŠwæM (ÄÆ1kcŸZ<7ö‰×cc_Q8§oìSŸ«}‰ûUµ±/Á£%6öeè%±±/ˆQû™ }öìûDE[ûèPEÚS íMK’ö® ‚ ½ÉðÑÞÜŸBÚ› ß<öö)¢G{ûÔ±·n>±·O*‹ööÑp/ööq'zlïãJCìïãVÒØßǸ±¿¯|•ù´T¬ý}{,c_¢fÜ‹DĽɰ Ç=öZ¢=ë¾ÁH{ÚÛûRc0)·÷±ˆí}lô½¹b3VŠÌ½ɰœØÞ§Yä=y±Åö>¶ûØÞGK×ØÞ§ÒÓö>[\¸U¾¨¾©™(€o2(öv÷‰2È{f3ÐßÛû´·Hûû8ðÇþ>mù"ïM†=ˆ÷†v ‘÷ä×&ÞÓ˜(Þë¡89¶ò=É{öÍÂ=¢i‡_Òn=îðã Ä½ØØFܳ?Ö ÷d(ܛҙ‰{ñšÄ½¨Ä=UdÒÞi“_jèH{΢½–8´²•i—ŸTI{ƒþ\±ËO*iìòãî6Òô{k{ƒ‘N{׆Cîò»Â?}hô_ˆ]~‰!™Úå*`oðø›ØåÇ@½!™Üå§¿ä½Ìàê÷ |6ÓyI|}éVÜå§Í—±Ë_¼gs‡ùÒø­1É{÷Ž÷š÷ºnDÜ{Ô$Ü£]Üï0ÃúŠ÷Kïã6*Q WÍ驊ô”*B ¬ÚÏ! $B Y“:üK¨¡œ8h¿!!PŽ#¢À)Äs ¤¢ 0àñˆ€Ëã…S>÷xiœËËã%vÒãTˆïBŒ™œ^$Éá¥0òJ/Ü@/6{|1àâÑáð¢x79¼dEuÒáEB‹^švýÑá%v.Òá¥.åðBHà çÔrxÑÎ!9¼Œ‡ûõèð‚n? ^8v]/”®dðò ^O#ƒ.„Á ÞÃàEñd2xYr› ^8¹ ƒÅÊàeQ+¥Á çað‚q\þ.Á‰—¿ 6ýa  þ¤½‹Ön{ŸªËÞÅ&Š·½ËLœ£w cgåï²$­Uê€Àý«ÄMuôw }þ.Ü–A K]þ.ÚEG—þäïBÇ@`øˆ¹;þ~Öß%4Gb ㈕0ðJJ+V"ª00vÞ ¹ " dàK` Ê\8òW—E%†° T^»ú¿ õ\<-#0P5_¨•a ¢U…q+b j¤0;\ÂàEo. ¤Ë~` b‘…œMÒ6>0ÐB뼈ڋO‹ÎÂáEš^dJ"‡Íä𢙈^‚It¾ ¤5ZP »  @¿_/ò|q Œ&M Ü)hxAØîÈVOÜ?úw \4œO/@ ðŒ«Ñ/€gâº=ð<´Åcñòè&´xIãÍ€–éÇ €š éî(ãù»È†Gþ.šÉßE[à€RIäï"  Ü/Äú"â¿á$ÿñ°zñŸ¶œÊÞ%ö.<%PyÀëåÀEr!5»Dy\b¼ˆždð£Âà…Ö[áñÂ( Ëã¥P¤¤ÇK %=^Ô/Ø›,”Ù‰°7îþƒÇ‹¬cäñ¢Å`ìÊ£Ç Ý¸¹þ/ßl÷[ŠÅ$ê|„ @œ© ‹ P˜¨ÓC—¶éÕ“µþ&”-ÿ€XM Ë ¬–ÅK­&/,NòŸ[Ãå…ݲøoñ 4ñß’ì%—u ä?­ †ËËäªùoÈìˆügÏãU./ZÆÍËT¬(m^hV.<)xÎÀÉè6`'`:m^Â͆6/"VÙ¼ˆŽeó¢èy §—öcç½ÌPû9ëa\®«L‘£õÏÿ—ð‚?àý ÉÛÀ5RÂsši°ÕŸá9ÝÏ!M·—v¤D>LC>úóÊçœìy{iGʕҘÿü{{`?Çêýù¾ö7ÖnqÝdíû3üìo¿üS­õ——Iï×*dõÃy›`3¯°·f^·¿5󊫘×}•ò’¿µòº ®•—®R^×UÊK×Êër¸V^ºJy]W)/9\+¯ËâZyé*åu]¥¼dq­¼.k奫”×u•¨<®™×mr­V­«˜×±Â¶sÖîå¿o…]~É û›Êø}+쟻ì«öÏf÷Å û×ò{~ãu_›×W—å¯VØ¿¥SþéÝÉ~Óÿôݶúê–¿ßP¿äò»­°Ÿ=£O»Wû®ö.¿Æþ“Œ¨ÍûåZÿuýóßÛûJüoíwXc?uœóÂöè`“46¬c„†ôç=g¥>p¼ücÖÕr­«>¶%c˜Ëw’?ÎD81:î±m&6NŒ/}lsJ¶k¸’ÿœ“b-öÈÏ3´sM°Ø#ú=ÍO Û)˜=çéç w}l¿Ô Xºüc[çìõØ>ºúümà;Ó´/zl³²oúÇônO«Ç©rÏ÷ó¸ÀQáôýÜ~ÏcaæÇù§šÏS+ÌiàÜñX=\ÇÊÛEvÊôÀ7’ï³ÿ¾qÉî±¶œkœj÷6yÜ[üÈVÀ,6RÍcGÀt»„¾ÏcZãu–éÓwûrs~—~¢@¹}ñé{.a'ÃTÜ=½?Hœk­ûÑÒ™ WŸí”qf•;Nžn‹_§8«¯îwñ³})t=fxn3a;±õ,k}p?gÞ>ÞnOÅïùÄÆ;#oOY!þ¥Û™·Ý3)žíS¼™r¡¸Û‘·§™>0MíçÈÛîٺѼ™òó÷säíðk’ÿÊd£Z÷säíðïrÚe?IÊÕ^ú9òvÞ¿²Ðî\£gég‹Åô)ü½­‰¦v?àñÑ[þÎÐçÈÛæ'UÏøél«GéçÈÛS\ØkÞ3Ùý½Ï‘·¨}Ýï=}D½^aU´Ut%ÝŽ¼=mUüy{Š=?³§¶îëo}¼nPzºÆ~*fñ—ìH™8|ž>ÝJí4Tª“ýx;½yŸªÝ¼µ£ ÝYú9ðön¨½úÂìÉù¬JösâíŠ#»û9ðÖFT¬™î„y7°sÚísõÝN»]¨4~IIp{Ão·Ãn'î#êôsØm÷¾üÌ+ºvëã)dž~N»w›³­ä§¡ò¤²~N»=*+„Å;ûÑÛØùÓáϼK.#œ·F>¶öu¶Ã±Ëš3ûÀt®ŸÓn—Ïü-Îi·VXôÞévÜ-¼üšgS}@-41èvÜm¿6IõsÚm÷9–W5;íÖß°‰¢?~ºÅ(Œá×S3õ~Ž»žr( Ûq·ÖT3C0ú9îv^¦`ÝǹÁMýw»ÜøÌú9î¶¹·ñÁ€~λ=>À!Ïy·Ïë½ÖÉ?­±f•(Ö3€ OÉ>ªÆ§´€öãvLᯟÓnû…6ÝŽ»g«9ÀÊW0¬gãõn«´ýô~ì‘´æä­ÿ·cýùvÿ¸BøÇxáß þMö›Ä¿>é©@üëæv>rƪ –Ð\ˆ]‡Ãÿú䩔Ŀ®XGâ__´¢þõ¥i$𯛬àóbÇ¿¾åâøwN€züÇ¿¾è¬Aüë‹ÛSˆ]Jñ¯¯9<¢Žø×ׂÿ’(ü×á_òÒ#û%}²_âLIð—¸eRð—D\¤¿ë§¿DÇ Ñ_â?§¿DÅRô—,tÀñô—hå$úK4ý¥ù•þ’êéÏ6éø¢é/±Ïý%v_¿{XÑ_¥“þ}…D‰ƒŒèÏRÞô—Û"úK”:E9Á2šô—è7'úË Æ Ä?ù©‹ÿrB¤…ø/±¿ÿeî[ÿ%:‰ÿ®§ÿenDÿe 3ÿ…€™r¨0SÆæG@`¦ç…(Ð&è^UH2'æê'Æ ³8 ÐÆŸ ˜P.Œu#2`¦•‰0“PÄ€Û©„€™#»0s^!ÌŽ@ÀLg!`6=ÎoÌÜz)ÌZ #fn^fõ«@À̉†0¾¥z] ”ï¾Ðr­ÎX`ÀÌù*0ßsÐ\ã`1B ¨“Ä€™~åbÀ :*@h'dOÏx=2 Ð~fMÃIY$A ÌtE êÈa`ŒÊÀÀ,¸ªˆ3œDQ¤ÀÌ>Q`æ~Q`&œsð 0nEÌ\ÿÚƒ>/ Ì´Yf®mˆsÃÎdQ lPIñĤ@+?>‡@kÍÍo´PŸ¨ãósÐ 0sN#Të¤ErpàÄ&wq`ÆZ–0ðʘ¿ÁÀ¨7ÄÀ 0ѬˆQ³‰ÑfÈ™²ƒ`|^‚`¦„@0²% fnå ÚãeO j‘\$˜µV@Œ&DŒNÌX×^?fÆþ í½ç £É3OÊf®¤ 94ÕÑŠ3÷Γ3gVâ@ SâÀ¨[äÀÌûâ@³‹ß ˜–Èhïã90qs¿801þB˜“-ÇÐêõ˜ ˜9Û&ñ7IÐ꺿a0sÚKÌU78¶ò¢Ã`æ‰&‚Á4à "Ô¬L0˜¸¯S0˜ì#L”„Å‚I«“dÁDI±`bd«X0}ÂIhMLtO &šå‹IbAM$Å‚éáG' &ñõaÁDã/±`âbÁ41–59 &5{¢ M…}" &ºi ÒÓ#PPˈBÁ·­ßa•ýÒû[ \¾]B0¸Xö„Á‘¸a–0xr ˜;æY”3M4%–ÈR`AL¸”À¢•*òZ%pIÃs%°Ðj0”ÀHq%ÐVÍÇK ¬´Ó“X¥xR ¬ SÈE? •±Ýå0 ¬4Ž“XÅRDÁÊÞ]4xÝ4X9ŠV—ƒ•Ë‚ÁÊHhÂ`+÷: VÚ‰ ›¨DR ƒC G!ƒ5€‘R Aƒ×¯(2X,´@q lô¹ -a!¡*…4Øè Z -C ä†0Ñ`ãRª´@Zä…(ž¦(Tj OJ5PËR<j 7À„È3PB äÚV¨4* AQÁ¢ÁÆ^%AFï†$(I›4XiÎ.”Xš ½›Iƒò› MpJ6„&È%dñ`£wBh‚byi‚ð<6Fˆ†$ˆž;A† —õBÔ(raR4ظç)A= õÀ¸`°…®H=;I¥r͈,بC„É~¨ å 6JÕ!2P;äÀ)b ÊS5ô@zˆ›„²`<Ý?Ä‚v>Ârš ¶Kþslš.‘W Ä‚&dbÁÆèÞP5 ¶ÐÁ‚ñ`AëK|ÆB¼~DI=†$8ÉZ„Á¦I a°Ñ™G0ر ”9¬h°áü9Á =RCär”X°irIl\ ªÊŠ7KÔK‘­2y‚³`Cœ†P°ÑA((«ØÐ5Ù”È1G(ظ%¬Òƒˆ‚XC¤Ã±X°Iæ" 6± YP}‹X0J‚,Ø~.l ²`T%²`ãQ΂23 jà 6f‰m–Ä‚´7 Fë 6nQpQï% 6º÷›P,}…DA‰dÁhwdÁJ·v± ýÊ_‚,XdAÅø+ö¸‰+žÈ‚UxA¬Zþ! Vn2 jþ%¬Z¹! Vîà Vîò VZ¼‹«XÈ‚•ÔDŒlˆ‚•.ÜBAM)„‚UòQ°Ò”Š(h2{b\ÕâP0Bˆ‚U‹XDAÅ: C& Æ5dÁ€ *fG,X°?_(ߊ(Xµd@¬ôf Vî¶ š&î°E¬ù…‚ׯ€‚¡’««ƒ‚U“(¨Ø»¥«J¤2!¬Üª&¼S|t •—,XPbAÎEø86©ÿŠ]vàŸÇºÝøÇüǃˆ…ŠFøãÔ A{!¤1”[ E™g¢F (#"”FÒÊ%á_¦ž¯@Ð`QâK—ø—Cad h†ž¤8P-Þ+”Á9ª(Àˆ¥¤Ç0P=¯â@Å¢š>.ô»EJALA ÜòQ Q€ŠU‘+ tH>tö³øK({9„2Eìg¡NÎd¿"T%ûÎÅ~E.öã8|…*Zìa«d¿BÓ-±_á!CJƒ'±_¬ˆý8Ghvd¿,ÒûÆ1ˆýì|; ~ŠJú)$èCô‹WúÑF8Ð/S²%úî¶ú ~ ’úÑlSè§`a…‚r‹YÇš ?Ή#48Ñ ôòÓ £AÅc$¿B÷$’_Ô.EƒÆÓü°WàäW$›’üåèÇ©ªÐ¯H´úIÅûI¥W0(G ±ŸNüEST0(¦õÁ~ZÃûÁµbAYiþŠ–¢EAd ?v‹þŠBëD¬l ªHJÑŸæÑŠeÜ’‚A5æþô‚?E)ø+‚EƒâóF0hÄu2”« š8«ŠhPqœ³_јìWxvÙ¯,Å”2”®·Á~\¾ö‹{3ô"=„ƒò¥ ÙýŠ ˆègû¨¡´1T3Á3V4¨* Ù¯HÖP4¨¸SÑ z°_Dñ‘ýЦðŒeûŽhÐx<П•¨^Ò_Y_…ÀBW¦ˆ n¢ˆ­¼¡J("ü]qœ€¿˜œþÊ”¤øSßñ <ÌFðW$ø‹øEÂ_áV„òX‡?‰‚¿Â“1çSH¨Ú8á/æ—¤?¨.ú‹[“þ¸DðW´œCø+SÑžŒe(ŒàÏR^ì Œ˜LƃbÐŒpP1¥ÂA¹ªpPÆE8¨ä†ƒ®_(4Rʃ5"Tq¹ åN˜†ƒf2”«£Jg+ëæª€jŃ^4È‘•+5 U…TL(æý U,Ç y!¡tAúÉÃ]è'_¡Ÿ¶P ýtpŠÐOÇhýÌ|’ÑÏûo‚Ÿ<Ü~6!^ <É~òçøSüäÍ-ð+ZÓ ø­@*T_ÜãAéÓñ jï?v?-±)”Sr_Qç,ð ¨øåI&ø]ÏðË<Ïö;–Ùíu[…yÑ^‡¢ ÚÃ)À{ŸIÞãN&i})qÅ>íRîQ)íi_´§@;Ñõîû´†bŸ8M´WpÖ¢¶ý9_ õ?¬Ç^!Xï ñĘÄv¬Ç ákÏw.ìùœ(XO@%Ü‹÷(Šöxü|ÐÏ: Úã!{A{tríõo6ý‰¯öš(´×¥¾‘ö"4”´Ç#Ø †äž?®‚ ö w¢ì…HØÓö(ÁcU{×#ö(9ö ƒ{…«J‚½Â¦€½³)üã†=EæöJì×íéœÑ­ÍƒöxЃh¯„ìÚ+â6ÑG°—qŒ«`Þöb=ǬǎN°͇°§{%B<ô¹¿ðxÉ|: M°W"ÕaO¯ ÖãTZ¬ÇcæÄz×+€õJD²ö¸j°§µÁž˜‘°§“zö„Ø„½hØ+œÙ ö®_1ìSã û¤I°`Oç"ˆöt.‚h’W„}*âËÃ>5 %íöÃA{‚D{ZS'íé„"Ñ^ öTÆ÷IeR¸£¨pU â>yqÄ}RyޏOñyOßS¼W‚°À{ª¤÷šxOÅ#ÞÓk1îS1低É{6d¯wà'Ïï•àQ~Š{ø©ù¿"?õÄŠüd}D~ŠHù©gVäg¤0òóâ‹Ú£ÈO­0òSaXŠü\ MEè')B‘ŸS[ùÌÊÈÏ`.F~NíÁcä§æ<¾+&ñeMæù9.¥ÐOÎ^"ô3rfè§8–Äo¡ÐÏHaè'g‰ÐϸC?á?…ÈOÅ*ò3‹‘Ÿ”Dø©ÝTä=ŽŸ<Òû ü¤‚®ÀOMXø©BWà§>¸"?yfgD~ kù9©ÈO¥(ò“ `ùÉ=(ù)Feèg¨i ýìØH ÐÏø C?M¨ÐO¸¡ŸÒ¸úÉɇ˜/3úFÌwüÿ@xØUS´…|9ä4F~†pÇÈOï+òS¥ÈOkVk@¾+F~ ùI8Wä§¢ù©p mäy‹± 0 .¹ v± P;Ý´ PÒ˜¶r§£vjUQ»éÆ»¥ƒi F'E~ª'Õ.@®<*ðSK" ü¤ëÜø‰0 Å}"@‡aŸäy…}j?b„}jtŒûd¦ ûTóUاš”Â>µ˜ °OJ@ö)=ZaŸŒÿ¶ÙWØçá››µñ-t¿¯›¿ƒ‚ßHY¿ j;X_ð‚Aø^‘ŸŒZSä'ä@"œ³k<`PUŠüT¨–"?³x‹<¨mkâAÁ‰x°3ŒM<Ƚ¨Áƒ{-)+‚Aú©Y°€Û¥#ô“ëú"ÂJS¡Ÿ k‰ÐOv{ráP„~Š=ô3¶ÒFF ý”,ªÐOZ‡„ Œt<ªÂ"©ì«ÂƱ]aŸ´ްOµ”¿þMÔg“6IåûdBùÓnH)®É¨Onh  »Šú¤:QŸ"õ¿aÔ'ÖíBùã â¡ü)ÜUAŸq'}Ò>”?FRKøSíTÌgG°°„?=¯„?­DÈ'¡"ä“«AŠø”ƒŠt?ƳH÷›_öÿEÜ/>%pKö³yäk`•ª¦€O ´2Q,sD|rÝIºC$ÃF]„|¢×Ýëå¡û©[޾‚>C™¤î'õ7‚>¹Z¢ OªÞŠúT„¢>¹ÐaŸ\P• ÌÒ;†}í 6º*‡ð§¹z„}Ê)FaŸÇªC1Ÿ F‹ÏC†|R(RȧyÁú¯Ï0dÈ'ÑU!ŸšuDÈ''ÄÀ¦iC>¹F.0ü ùdD¥T? Á¡úI\"F\£">y`FD|~Uý8"à3&¯€OD]2âS‘J„À¦…o…|JîTÈ'ýÐBö¾Qõ£LNl 3SÄ'C¤úÉB1ŸÁ.˜ñEõk4͘ÏÀ0ª~*uA`yi~1VÀ§Œä£é¢> ŸªY øŒÐM|J6Œ^0q/|2ˆŸ—É€O5|J3€OéyWÀ§—pD|¢ÊÊ&äE `¼w|*(”.0<*æðéeC¼òaÀ'gYWÀ' !>¹¬£€O­g)à3|að©ÎFŸòî`ħv„*âS ŠøœP ®ˆOª5Šø F|JUħŒLñ)EGŸÁeŒøäÌ%B>G˜¾`\åööùý*ä“co„|Ê݆!Ÿ²Rȧ,„ò©s¿òÉ3z"äóy¾†|>ìò©°x…|>ŠŸ†Ã•b>eD1Ÿ\×QÌ'A[!ŸB>µÁX!Ÿ\ÀÏ&ò©ß ù´#Ò] <‡k¯¸B>UsˆU=1°ÒJA(!%B>¹€/Œ°r`„nMµõ¡J!Ÿ4Jº¼³Ç³öË=uÚÁ ·Ë1äƒý³?Áü÷?`œ} ûçu¤„Q5Ó`«?èzž£^¨”ȇiÈG^ùœƒ:_oŠ„+Ob&øëïmš=¬oµrøM¦Ù·=öccÐðÓuÁ7ÿy®]²úý¥KÝK¶ËKöÛJ1þù²ûýR·¬¸lÎþº†9…Y6sºÍ²‘S\„œîk”“¬²•Óe•Íœtsº®QN2ÊVN—Q6sÒEÌéºF9É&[9]6ÙÌI1§ëå$“låt™d3']Äœ®kÔ`e‘Íœn‹l6r]„œþˆ¶x4Óó¿m´ÕFû7ôÏ?½{ܯÝñOßm›¯.ú» óÇï¶Ð¶ã©6býϵжÑt ýóîš~…ö¾ü{Ú;9²ž‘Úý×-´Ç“ÏÔ²¯ãRñêÄf4žšÜlŠk¸~Züü«¤ñØ6³†9ÀžÅØ×”Î9‰¥¹¦€_Yޱ³~X¿žŸkgýxìЫègÁäHŸÈdÏŸï-û‹69`Àçè¶rŸ/ù{§,«@'¼êñ_•#äž ƒê)¶ vdt¬;ŽM+uÀm­;åŒÅ'D§ù5Ïð¨ª{£÷æQÜ\1º&â8R ‡á£[´F9GyÖu…žìI`ö°Füí”u–„¹ÊyŽ4õ¡óQö¥ŸåŠûÃ"ä0ªxq-9·9E5ZÇNŒc˜ `ö©[ölúq¼2‡ã1F÷88Æ ›,Ìr­Œ±²Ç1éœgê!«èFÆ´…°yßËN}ìXa÷iÇ•ž88®{î”s¸á)+¯Žó`Åõœ‚{&à ¿ÙÓg[Ù8WFß óœ%wÍ=8=>ŽÛ¶ÀS¬õçÄôì)‡‡ÎùÓ猳|Ž:aºêœÃv<8ˆ™Ø¹D'\•k‡ÿ®á{HÌÏ&~”åwâUÉ5ç$óZ=ZèðÑ9Íh¬Wʾº\^Ø~*׺_ÒNˆ;ÁúnvVc÷·0а¤spÚsÕ*3!\×þ¢iÞ€ õî(òÓ¦Hó®xÓìø+ʲû5¶vÊ6Ó3í¾é´Q8“-WÎv€Týˆ P;e¡Â^mZoçmKýÓŒþOÅúð4½ÓD¹-q×åÜüql3 BQ­]OO\', gö¸*ði æ 1Åè4;´W#¦ƒf„³Ïeßñ´ÒÈ·-o¥´ë˜vLìi¥Üí8Mm^¸Wöœ=9¬hç ñÄ5g¥gZ÷|Z)M‰öàY­ŠÃÓâEN+%8N‹Ó9­Q]óô«ë Ιçâs ÆžYÎçæRà<ÕôDQçiŒJ;Ï!¹ÏGD¥M;%÷´RJ4󜒋X¶#‚LÛµqZi¼À¬ÞJO6O€yñkNÇ3Ï1¹(¬S‰ œO;ÕŸSrO¨6ÉMÛò{j†¯Å<§äNœâùìuªðl»]>ìžç”\+¬‚%“yÎÉ]¯”îê•ó8ªb{§­¥çõ8*dóyŽÊ=?Ââô´U¿ö*Ò³~wŠ2Çl*¥õyËžrÆì!N[Õ½Á¶×¶³rsùoyÎʯ_uŒ§*®sVî|Ý|`<åˆ?ÏY¹ë~œuâ Î%ÕßaùxÊ+ÎI¹Ï­•[> 8ÏA¹˜XLOÀxªûžƒrûýŽOÀÊmúó”ÛýFg¬™vPîzU­sP.æ'^Cí ÜY^÷²õ¯qW;(wÔûcžƒrçÝêì Ü^ï*pÊ=ÕûÊç9(·ÝEqNÊ]wÝ:Gå>w'`g守…Ÿç¬Üç*bCÇ™ï7?Gåö»ZÛQ¹#ßßû•Û?â “iGåzkÕ½4¬^ËNÊEOá¥5Ò¼ol§ä¶»’Û!¹xÁì9XOúÙÕ<¸øºÞÇ-\ v<.j· œŽÕNÇíwm¬oþêv8îóúÁJWõ³ƒq›¿Ò‰C™v..ùL.¦‹[½|04òÁ×?Cõ´CqË]­&‚ƒ¹*8çÅï< Ïë5í4\ìI~ӂóy^µ GáFAØQ¸õ.]œ„ÕÖNÂ}·H8îæ`çàæû¶†=ýª}«b‡…çvî«øíÜuÿB(°Ú×:GÈ_ÃÆB(0EºX·Á açÅ¢ Á]¹Òƒnè·:b 榈݋[PÝ}̓¡5®y0´Æ5½«¹zé€êîkœê®vª»s^Z5óÕ™“ÏôAuWΠº;Å©n§4PPÝ}MóÑõJÀè?z0ºÆ5£k<ààðÊ×ÖÝ×L ¯‘ÏÁºëVŽuWQÖ]?p¬»p°îº‰cÝ}Å!»“àY°»þ>\w Îuw݇TÕ©Á:‡?§§¢ãºûߨ]:Ø]?p°»¯8`wåá`wÿä€ÝÕ÷:Ø]%á`wgú¼êƒÝ}v¯„õÙ^ ìî„…”¬ƒÝõÅì®Û:Ø]‘ƒÝõàv׃¯úz,'»;ËCvw‡ì»¯8dwçáQªNv÷C¸|©_üƒk½ªo©N"€¤ºÐ$Õ¥o¤:¬Á„T‡:”:M÷¨Ô…(H©QúRêB„R'¿{*urx—R§C8¤Ôeú+H©ÓRêd›/¥.seVJåì³\*u™ËØRê®{A©ËÜ“/¥.ót&)u:zBJN4T¿¢TGÓ*u™‹óRê´b]æ*ŠÄ:ð"±.^œj]Æ–‰u×%ëtĺ •J]æ’”ºÌ®CJ]¦™§”º¨4Tê¢NP©“Už”º¨%Tê2ð]©ËX¢‘RwåáJÝà‹Š™FÖRê2×/¥Ôé@")u™«XRêtú‚Ä:º#­N'õH«‹l(ÖÉPbZµºH€TeG©N'UHª³”æO­îº7´ºLÝ€Z]fœ¶ÄºëV.Öe.“I­Ó^(Éu,©uz©uê4¤Öé+H­ËšvR­»~µ.kYŽj*ŸÔºÌˆp©uW äºëWë2cÂ%×e.P¯ãæ?Éuñ4Ðë2cã¥×é„,éu™k!Ò벆êuÚx(½.kÞN½NíPz]Öl‡zv'J¯Ë_éîüʇXêuñZÔërÀ;¢%ÁN§q¹`_“‚]¼;•'õº, ¦^g—økS¯‹ ^—¡×]×@¯»®^ECÁ.^›‚]<1;;"Á.Ó·X‚]¢Ñ—»ÌÍõì²ä vL¤×E‚ËuQ8”ë®Çs¹.Êœr]<åº|¹.ž…r]¦A­‹;Q®‹ZC¹N}¾äºøx”ët€œäºë!×e.JJ®»î¹NeC¹.š京õºøàÐë®K ØE‹§b§*JÁNÇÌH°‹·¤`—¹tD½îºôºè¨×åiÎźÌõjuQ§©ÕE@­.s%NZžŸR]$@©»r©TùI ÔEWM¥.:TJuÑ?QªÓÀ+©NïD¥.kJ6FS©‹o¥.3hÖ•ºhPê®w¥.*<”º¨ºëâ B¬‹±b]T/ˆuñä뢇W6çÄ8Ê‘áˆuú ëÔâ ÕE_­.ª&´ºøJÐêâµ ÕE¯­.s“µºhG«‹ê­.Aºé!ÕEÍ€T¯ ©._Ê\ö§BÓ…Rw]àJ]¼:”ºèO¡ÔÅ›.ŽÜ^4ê¢T•R]¾oús‹ðpT£j8¤º(+hu1‚V§¹Ó¯øTG¼åsÆÐ›â‚ÐHqŠ#Å%ÚˆâÏ8Å¥çm™¸Ñ— §SšÄp‰@qW .ñühBœqåÏFˆÓ±R‚¸ÄØmAœN0Äéè)AœƒåÓxBœå3oî¤tÏ—°=X —¸#I —h_(†Ó¹¬b¸D›41\¼(.^—xè® Nç†â7r ââ3âMq‰æB¢8™8ˆâ7‹â¢pr*rœNÇÅ—!ÇE 9NÙãìL5¿1îú0.~Tû}cbÜ•‡c\|&b\â~LaœsÆÅKã¢ãâsãâWä¸(Nr\Ôbr\B“ãâCä¬^g„X:ÉE½&ÉéÄ7‘\ê¢4œÎ‰É¥.Ls’»²ÉE…ÉÝ ­•5I.ñd(¡œ~%”Ó)pB¹+ \â %B9=±P.qŸP.ñ\/¡Üõ<@¹ëî@¹Ä þB9Ù,”K×%Ç%F¡ãâaÈqéDë ââù qW 8.*9AîJÈEE‹Ò#ÈÅä"¢Ü•PN $IîÊ$Ÿ›$A’‹&Ê]×å®G¹(r \<ïA¹x! \4S \ P.Ê(§É]y:É%î!ÉE‘€äÒÕ­ñ®o ¹x÷CrqG'¹xm \<#P.î”S ¹èÁ@rñÐ 9›ñ;ä®›<ã~h\ÜÂA.Š$w%8ÉÅk‚ä”@îúÛÇKîš!ÈEÛ%Èñ”S‚\”Äòþ€‹"¹è2ršv䢴rñ¹+»nU%ré.b£.{”ïØN¼¹MÚK‚û_yŽümwˆå1WƒšFx£«[ÀÛ¡Ó/ î-ÁaÅî’à@§¡ÁeªÔà¤Pƒ‰‡'ñDœIp X ޤ\æ¼7$8˜$8„m_\ch$%¸"R¤Çå…àB¤GgÄà¸%$8mÕ“§jpʘ\yí–Ët‘NÅÜù±!¿é¶’߃4©ÀIÅ£'¥TœN pÔB#c‡þ&‰Kú›¨‹ú›TFèo|g pz\ pô§®À38¾Qèo8©;ô7}Déo**éoºwpB0 pnP!Àů(ÀéîRàø€RàTRàèÛ \ÜŠ œdf)púPTàâ*p‘Ž»¹B㹡Ài—$8Jå!Ái—$8š-†Çb Î;déo|íÐßX'B‹k¨¿iÓšô·xêo‘õ7¨ô·ØFNÛ°(ÀÅ&6@[8í “ÇÐéo*éo¬~¡¿é5¥¿±}‡þÆïú+[èoÊGúxèoz éo*éoúš®¿E&Ôß l¥¿©°$ÀéCI€‹\)Àů(ÀÅP€‹§£‡&ú›¶JÓ­¤¿éVÒßôí¤¿Å5 ·+êoÚ #ý­ Ø⛾ŠÔ7}9ÊoŒ ùÛ»¨¾©ð¤¾)EꛞM꛾ŠÔ75]Éoq å7mß”ü¦Ê'ùMO,ùMe%ùMµDò›¾‹ä7ík‘ü9SÛ)þÁ©¿©’þ¦¤þ—P«p1 ýM[Y%À©,$À©”%À©¹HS™JÓK«‰HîJÁ¸¿¢ §'” §'” §»K†Ó›J‡SiH‡Ó7¦?¢)ÔáôÈÒáôÈÒáâWâTÛ%Äi…8eC!N¯éBœÞ‘BœîB!Nµ†B\ä!ŽgõHˆ‹+ ÄéA)ÄÅm!Ä©6¸§}_âTª.ÄñL!)qº%¥¸H€ÇmÜTâtG)q’Õ Äi«•8}%*qª±®ÄÅŽ7(q<ÉCJœ “R\d ).²„§W¥§â¦§ºL-N·ÂEaP‹‹võL’§í™Ôâ*,x¤ÅE–Ðây'-NMƒZ\üZœj´8̇t Ýú꜔i(´ËnÜ ÐÊo¸N['Åuðß Ôé”,Rã‘j¤:Fª+RAäB[@y ðXaŽ™ÖUmê!ÖUªÉÂ:,(¬«áo¬“±²°®F\'°® zˆuµÂóVX§£—…u•îñº*k bŽgÖÑQT¿!ÕUÖ>R]•Ù ÁÎŒ‰z ç@·/¢\ N°Ü Åv5\OÀv• PlWi5!¸‹B&ÜÕ BÀ]¼8é®F#è.Š”t§“´Ew•]ºÓ]•ÿ 鮉eNw2tÝE ÝÉœ\xWƒ+wUƒx§°…wUašÄ»¸†xW#šxW¿‰¯äÑ‘¢;ˆ*¼«ßXF³"ÞÅKïäl(¼ÓQ‘Ä;n(K~)pC¡;hءиWxWcðNgé ïªòä‡ÂM¬á‡ÂSÂ…g%‡ m–Â…¸„ íÝÃezLsø¡ðŒ—ðCá±gᇂcAä‡2i¼"?= Q†ÌNhˆB‡Ó0D¡Kt¢ 1 Qè|†( —C”È™†(CXHCn†(“&/ôCÑ­ä‡b”ä F?™†(4¨ CžŽC®-†! Ï !ÊøÊwbÂ…Zw¢D QxšQ¢PECªèaˆBÍ<QhþŽ(CÞ&tD¡ñg8¢PWG”Ž~ Q8P†#JÈwtD¡bŽ(‘G†„#Êx3^a@A¢0Ú! Q`~(’>å‡BïøðCÙ )è`ˆ"Å\†(q+¢tâ° Qª†( C­³Ë%ž‡†(Rðåˆ×À…±*a‰Âcd‰¢Åwy¢ ™™Ð¥ã¼¹0Ey 2š¢èkÊ…gä„)J¤Ð…qaŠ¢2•)Š>¹LQx `˜¢¨eŠ¢š,S©F2Eéé“'Šª›,QB¤'Ššƒ{†õzü}åqR˜ƒÿñ÷6†^æ˜Ò¾ï ý«^Ͻýv_è>ÿ1ô7õaÙ£>·í×ju*M9»n¯«SX>#§Ûò™9ÅEÌ龊9Éò™9]–ÏÊI)§ë*æ$ËgætY>+']¤œ®«˜“,Ÿ™Óeù¬œt‘rº®bN²|fN—å³rÒEÊ麊mU–ÏÈé¶|VóÖEÌéC¯Ç ¾ë ÝÉú›Ú÷}_蟻ì«/ôÏf÷Åú×ò{~ãu_›ÖW›á¯¾Ð¿¡kþéÕ×~Óÿô½¦y÷Í?Ó.ßyün_èµçä¥ßz¿ü_ã?ÿI&Ì¿f ýrlþ{ÛB÷ïÝäŸÿ -ôêï§OØ¥ÀÞÐÎ08ÁG;ÁÂUr=Cþê£3’èÌ*öˆ_Ì]Ïßë­“xBÊNð_дFòßZ#û‚/]f×(¾àËÕNð_ÌÉöÃõ³P͹çþˆõ,Ds~´Æ9?s@nÞγ Mw±=/y>oÑfbõca±R³Æ¦Ãsn2"åvÂ<ý/W„Ö°UØ8—xÍä“l.$¯i›>Ž™â™Ëì„“%Ðl™Ûsßcô墨ÚtI³¼ ãN–ÃoiNòµ[ÓSÿ¾µ'ö5šg1|!ºb}bÍ3™QV˼ÓÎ ÊÁžðØ,›+öËÜ[Ž-ÌÛöÎgÙÖ25à#=Ü >ŦŸõZû—ç=k5ŸcSé_k£Â±JÆùç;Á'ÙtÀ^ë€Køø.kÈç ïyäÉǤì?—cÁlí,ÎSsÉtw!æ3ögµî”œÏ£W?`Ó`¼ýè’âóì ºRa¾ ã€Ò|¦M5ÀR–CZÅNy|¶MGárV`B¼ÿ>ÛæF K™ŸÀÒ3þï”éóm:Wï[ ü€õž}&?K²á@_K™Î ä³j'·-ÏÖ‚2º·'Ÿe'òµÊ`)ó< ]aøìï<Òa½ÝðŽÙxó•`·üáôNØýÍm¢½SV"èŽgzòdz³éP˧–2‡3TzCÊúRËíH×þz);Ò5¿>L{|bþxX¥%pGî¿qž+x§ P³Jºjx²g½SÈ™%aº:ÿçZ^Ecç¹Þë@;¥tÖ#Ô ;ÏõùKÿrÖ3)ˆÙßÓß@Å`§¹®XÚ)½²Žä;Ò—7p@}Ýi>|æŒe)ØÝçdǹZOCÃvK™×*Æþ;û˜iߨsi ;¥ú¸Ù!YÊøÒUöæ#'×ývÊãcg4p;Ðõt6 ,2.–œvÊx>óµÄ±S ãF#ë¾L¥ Ð!ãr+LNƒ U*â‘Ë—wEà±ô;¥Œ×ÜNÁj›vJó¡”+§–²ØTÑììP×ü*A;Õµhl'Œâýò­Ǻ}þwÂôá”+k;e5ƒÆ7°#]çëy'²ˆ*1¹n¥ÖâD„œÜ6ñ.];ѵ¿êŒèš_õÜNt}^MwU¼3Æ`;ϵ½z§Å£,°ho)g@ÍÜY»Sº¨Q46×ǺùBÎ3qu‘ “•“;Ïõ¼æp9' >~ÚÌ‚•¼àŠŒÙ+fþÙ†GV¿µ H¯Ur[¦JœÓœ9¯¥ ŽYù<?ÃÀ½zaC˜HSYí­û´‚w¶jrwö¸J^™²ø|ÉŸæØ…|ÄzüNÉ}áãÏÇ• _–²8íBéh} ßouƒ&ÃM‹xî-ÌZÂuC‡#Þáú„0„;>Ð~ùA¸>éŽÚ¾u[³vˆq|ëç´cG©ƒoÇÜ9;(?ÌÉdÄ3õv~;&ÍË3=üÖ'ùÃoÝšRò{~;–ÈÎoçBÎoð6¼…G-àí8˜:Ó8¼…½+à-<òoa”yà-Üoáñvà­/:Þú ø;ðvN§Ïþƒo'aú3zë‹‘ ·¾éx;4¦oa xÛ Øžqàmÿ ­ðÖ7kÞî„Ão'Á‹Öù­/Ú”ƒßN‚³²óÛù‰ÿâà[·œ¼Ê9¾„æ´vðíN8øv'+Lx§ƒÞÎßÏEo'¤sèí”f%¬epœ;‚–ÜâÏêf dPR›]ÀišSÛIAìÔöJ9N¹×c ·´hiä{°í¤àÖ³ãÁ”É¡¶ëç¶“°*R¦?~¤nÛ)ƒc‘sÛ© Lv¸í\ó€°·íðÕñ-i²CÛI!Öu7½®9ÔvR0@;¶u«9ÄÛ^7>Üv¯sÛý+ç¶“‚‰R9öÏ×ÅM@¹yùíü=nn»?€sÛiU˜d:·½îó¸h½8·LœÛί0+rn;×3§û^)ëyåâÜv—°sŽj; ÙMA-FÒ?“cÛý­Û^l;ÙtàV|ÌgÛ^)½°e–Û^× äK&›îzÝi¹=èõ›åþ ñ+ç¶“2½hœÛ^)%³ˆñaœÛúâÑlä¶“qn{¥<¾¬Y W9 ÜÎ߸àpÛ0Ü'4&š N!µ½2]Þ’#űí¼S²›…ÆK:·_EÛ®›;¶½.iïŠæØ¶SªìqƒmGl{å2| ¼~åÒ£¥T@äô¡òJo¤8·!a"áÝzÛîêÙáÆ{ÁUM¬æüU¼†¿j«hë)¬E7´Ý}„C›º8'¶û8±½å¸òr›‰í®á¾¼WŠ‹¿W pæå Fb»ï=àÍ{¥´Â œáÎ{¥<?§~Õ1€FÊ(_þ^ì*ÇÍl¯kV{7G¶»FOX?špé½®Á‰Ñl'|z#ãºØÏ`Qiª7.yÚ«²N8õÞ)“Ï2ÔÑôÚ^O»^†ÆÚîÁÔ¡íL°záÐv×+‡¶ûyÚî²YõݲÚ^)8²"F‡¶»hÚîfêÐöÊg&6S^3ç—ŠîÔv]s¨íjÈ ¶«Óµ±õÙ®Ù^™4NMd{ýêÑpšu½ðh‰ýÌ Ù®Ïríu¬¸SÖ»²ÝÅàÈvÿ ‚ÿ+eñùÖl1ý›g)o'z)oæœÖïâ’Þ:%JoÜâMé-sAPÒw9Kzcཤ7Æ"Hzãp%éM²Š´7Þ…Ú[•¶v´7ºH{ÃJ¦¤·&ÖƒôÆ5Jo™‘J”ÞBÿså-É`®¼å6Då-ó˜"WÞò`I@yˈNváÍòŽBwËŒê¥îfÇÓ³\wË ) ðf £Ó£ën×/\wËÓO”ìÆ¸[ÊnyI&3ÙÍþ|.r; ·ê–ÉÞ2C¹)¼] .¼Ù3¸n á-«NAx³×€læÂ[fœ4…·x1oZçwá-/œ¿Já͞±Â[¶tïl)¼ Í9!¼]kPÞ””·¼¤eAy³”„|\y3Y7¿”·¼B"så-s5Ê[f,»¤·ÌÓ $½Yá#Á•·<µìå-ÓûAâÛõ0ßîß ŽíM mÔÞôþöÞeW{äXÓ›û*4Ü´ÀLf’ɰ'l@×`{àÝÀôýÃŒŒ÷\•J%on 5Q-þü’§<=ñÆAÚ[mf\EÌ–ö&\Ú[c•)‰oí‘Ö–â[9â[<ÒÐKñ-:ö¡ßÊÛ„øæwµµ·ò ½Åë<²?þEƒ9´·¸>6œÔÞd¢„ôÖXRLÒ[4{áNRzÓ“ôV¾5¤·#¡.Í„îy[zk ½ô¦±*é­q2—ôVÞ7¤7¿^(oåÕAy+§¤ðÖX>LÂ[ôy—ÞnY2 ¼iÌBx+ýÂ[c¨ˆ”·ò­¡¼5®HRÞ4Iy+=Ê[|º‡ZÜÃQÊvRy‹??Ê[t’ð¿€}ó)ÓŒ”·F“ ”·F«¢•7&£”òÖ–ôd(oñPèŸÞê‘ÔÞJ…öV¤öW?@~©½Õ#£}æ ho厡½Õ#×ÉûÃK‡ö¦i]Ú[™b¡½¹'Az+s%µ·[¶«­½•^í­14HÚ[cÐÞÊ×…ö7 eÚ[éIÐÞÊœíM᥽ÅCA§€öVú ´·2ní­¬ÐÞ´(J{+}Ú[[òé ö&³?µ·vWŒ«s„·Ø"@±‡ðV¼ÞʰƒðVúùVÞÊ”å­ (Hoe €ôV¦(HoeB‚ôV~é­|Hoå#@zk¬ÊhéA)Rßʺշ2V¡¾•§‚üV^9ä·ÚJÊoe€üVÞ:ä·†X5©o¥C}kŒÒ“úÖÉøPß 7B}+Ãê[yÅPßÊCI}[|éP߸M”øVzÄ·Ò…¡¾yìR|ÛNPÞ¢W­Êpe0QyãW›û<…7/ËÞ|kÞ“5Kxk ¬“ðÆmªt·˜4•¸\P‹6·fÝœPwóŒKÝÍ u·r3ÔÝðZ ºyìStSæ‰n‘mÖYÔvî©¶úKÂvŸbÛÃ¥¢6&(—äT zLJ8¶ÉçÔvÒ’ÚImMȤ¶C^ ¶ÃþŽImÑ5©í@mzBÛ!/APÛñÓaòÝälLj; —Im½pˆmѯR¶ù'À¶wSS4·÷߉DÀ¶ƒNrÉmœÈmåü䶃^]䶃Þzä¶rO nn3¹-~qVɃ†‚›¯ºÁí@ r[ü3@.ÁÍïà¦Ür·Ã¾Š n‘¾ò(Š[=àvP%'¸E£¸J‚[4 ¯Ë·8£Üâßgõ˜,-$¸é€ÀMéÊnºu[=’àvØ= à¶gœ*¾ù¥ Üj; n;ι¸L ÷¸Õß$¸Õv“Üê9InGu’Ì1:´3¹émŠÜôI„nÇY@­å3¸D7&&¹©+ˆÜØnÇ)и§äV¾Э¼a ›ú¥Ð­¼  [´3ŠßdyÃ`·Ãn«›ÝJ«`·ÚF²ÛaÀÛQ¼/ÞÊû¼ò8»ö¼»•Žv+Ÿ`³[yy`·C.¾@·re Ûa§4 [y&°[='Ù­¼MÀ›F˜à­ôÀÛAÏgÁ[üªx+ßðVï8áÍï ìV.v+·vÓ"v+ÝìVìVz,Ø­ž“ðV^Ά·ò"oõH›Ø­Ì5`·ò¹ÁnåfÀnåÀn~7@7̓B·ú£D·òLÝÊÝÊÄt«GÝÊàºqݹ• r+÷‹T»¾;ÛAgx[N ·òµAnÑÑø›«§†2È-^9,É­<È­tG[LGr õÛ¹•N r«w¸SäVžäV:>È­, ·2Ù€ÜÊ3ÜLÁkLx+oðVfÀ[½Ö5¸hñïï’x+ýðV¯ðVμ•n x+_ðVÏAI ß à­Ü1àÍ« Ø­6<¿³7Ø­Þ^²Ûab°[™ÅÀn‡Õ)°[éé`7íþoå¥Þâl€7?Ø-¾…°óúœ0´¤¢ƒÝÊÜtÓþXèV•ìV†Ø­t-°[™£oîèÉožÈo~Ÿä·zNŸü ÎI€sG"À}ŽÜûL 8œ¿/ NS1®þh} œ{Î#žwHª%ÀùBŒ•Õ×&•gb„-ï÷7: ÛÒ͸„ê²Ä6ÆdXl£`ô;qnM¡[ŠsË´ÒÚÞ) ÀD­ ÞùÒÚXUJZs KkS(µ6+z[kƒ×…¤6FIkc*+imT]¥µ ˆ¨µ1þ^b÷|Û$ Rlãǵ]rœ„Ø&œIµMìB¹Má_”ÛÆC¹r àJn“ÊH½ÑÒÛš!ÁM”EÁÕÜuHÁMMRqc)nLa.Åéõ¥¸ÍÜFsÉmnr›@nCÐÚ|Á­µÑ\Z=˜¥µ ë_ÐÚ†52hmžÐ©µÐƒÖæe€Z›½ò©µy¢Öf¯vjm%dí„+µ6>¢µ6G¨Ql{[cÅ6›PlshÅ6ïo)¶ÁÚb£å ´9ŠJ›\»¡´9‡J›C%¨´ÑÛJÛ’R[¹7hm5¬- ƒ~jjm~¿ÔÚÌI±9z,¶•€´-¶ù (¶9Jƒb›—>ªm~TÛô.)¶9"ˆb2§Xkco·ÖæoZ›¯C­ÍOH­Í=†Z[¬áðބ֦KSkcÑkm¾_ŠmƒÂ%µ6›º©µùHmîÐ)µùÂPÚJPÚÊÝBisˆ •6G*m¬t`¥Í=J›Ã´¨´Í%¹ J› )µ•«o©­œ©ÍwL©miËñçðZJm¥Hm>B©Í‘Q”ÚïG©Í÷G©M/™J›_r*måBPÚJ#PÚÜí©´q!³ÒæîH¥­DØAi+׆Ô6$&Pj³¯zJm\Î,µyXRjs»”Ú<”)µ¹Sj+ç@j+í@jÒ.)µq³ÔæÏ@©ÍS)µ±Ž‰¥6Ÿ`Ó:n©Í¿¢Ô&‡N*mž?)¶aš¦Òæi„JÛØN¥ÍÏH¥ÍϘJ›†2…¶òmCB0…¶!=žB[=’«©Ç…6?4…6w m¾= mv¤ÐV~µ…6…\Ihóg£ÐæWC¡­\ B[9òpâÏŸK)e6/À”ÙdÀ¡Êæ¹*›;gªl”TÙ|ÿTÙ]I•ÍáTÙJ¬d69Êlþ*”ÙÛ Ró3AiÓ¥¥´i:•ÒVbÈ µi²”Ô¦ÐNImzLIm%zR›æ'Imz]ÒÚÊBk+®˜kÖBZ[ù ´6¬Jkã«!©yÈImÓ–Ú¦¯+µÁI"q³.¬tŸlKdC"ÜIïÇ s{$_ ÎíÑ~nK2Òíq‘ v{n„!!Ö푟!bݹÇ!Öí¡:ÏX·gÝŸ\%×ãh¸ˆu{äç‡X·‡^"Œu{¨4+Öže’ÞXWÒ[¦8c¬°$»±­d·÷÷±oŸæ(»1Ó-d7E×Qwcmaén,.ÝM2(u7Öõ•îæp:oP¡ºt¥ê¦ð¼TÝÏGÙÍ »1/¶d·Ѳ’ݘeW²ë^Kv;0–%»)þ޲‹KvSÜ e7½†ìÆÉ’Ý|²[SÄ.e·Có&e·¦(oÊnÎTݚ±©º•†¡º1S¸U7–϶êÖ”e U·¦ðvªnåf ºùf º• At;´u¡èæÛ£èVŽ@t£6nÑí0‘AtóíPtkZCRu;´îPu+wÙ­i3HÙ­)(š²[9Ù­Üd·¨² .…ìÖ”2‚²[“·QÊnn…²CG)»±–—e·¦ü”Ý®oTÝj\ÚojÑ&)«nåÞ º1jÕª[9g«ní¶dÚ}e7ß e7æ2²ìVÚ즦êV~Õ­4 ÕÍ?‚èÖ”n…¢[ùÑ}~Í­œÍ­<D7Šn,ËeÑÍ/¢›?-E·ò+ˆnÙA¨¹µ¦"ÐÜtÇ)¹•ë@ró PÜXUÎ’Ûáü'Üü£G™ÔÅÍo†Š›¯MÉÍ©”ÜüŒ”ÜÊ‘Ñ>Ÿ’[“k4%·&ÿNJn¥HnåWÐÜÊÝ@scØ´E7·CÑÍMŠnž)ºé+QsãþÇš[iš›š›o˜š[9ÍÍ/š[9š[¹ahnå–·æVîš[dfñ@sk¶þã3Psso¤ææ§¢æVZ†ææ—NÍÍ[9š[içF+£Æ½Õ§¢æÆJƒÖÜ|„š›ß 57/ ÔÜ|-jn~Njn¥hn^}(º¹¦è槤èVÎ€èæ§¢èæñKÑÍߊ¢›bjn:@É ÞgVܼ|Rqó2LÉÍc3%7_˜š[s"hnþ¸ÔÜÜA©¹5'JææÏMÍÍš›_57Ý47µ"ÍM¯\š[s†hnjWš[iš[=ró#ŒO¶’é,¹éåHr+Í@scrAjnêÒÜÊ#@scnkn¾57?E7f´èæ»QZ[ì.J–æÖîµCûœ¥óì™ÀišqDi—ÿG8…'ü+‰š{ßÙDÔ2þ.‰‘÷æ%Í?Jbå•eÖ§©mä1µ‚?K;gË8ãòŒ‹m}Ò:£­’ŒmÕ”ÍlËg±­Obg´UÒ1£­š´™mù,¶õIíŒ[2g[Ÿ´Íí> mý+i›[„…E•¯ÿ‘·ùò6ÿ3“õß¿“ï/Sóßs¬~¦ëߨßVþtîæA­ÿ÷ž¼y•äÍÿñ'’7¿ï˜60¸µh”:Së{$s .9­]ÆÊá"«÷OŠø8²÷ “Ù²Þ#Ûy꾂{½o˜ŒÐkkîmÔ°ðÙÛ†©˜ž¶®Ì¯Íp[i »”Uåý¦='-mtVZÄ®rËQXèŠàî|È' bÁE<Ò6_JÌמ4ˆ]—¶G‘îae;)ª¶'-b—£Lž±iüV*÷ȦñÛ®MÏÜ4~Ëͯ=ׯñ[.¥í¹7ŽG]ü(jE=:<Ò³6Ž¥]¨…Á7Α@?Ò"v+ã_Õû·²aö#-b·\¼úÑ7ßÔú‘1_¼oÇ·8Bÿ·~Œ+ïÿÀoæ¦ñ[.^ýHƒØ½à[G6߬mö¹7ï1?óÈÚ<¾˜Eû=òì%ã¦M=Žl¿B.ޭʱyüVHk7ªxRõ(§yåí ˆ…è ~Ò#AÁÌ»Ka®·4ˆÝòIì[€Éëd¢æÞÒ"v3ÕÀ{äšù|¨ÞÒ$¥'ÎYÇ£LàÄݤIìŽòNù&"Ò*ž`â@O›Xü(ù­¿Ï¯œòi´Þ3ÉgŠTŠÏç^vÖéhäà—ŒÌÔ»‹Pkî‘®6ž bå½dÂåû¦€Þ#›á§“÷ž±[ªïÒcq„³Ä»³ùĵޟýh{ÿÞ&1_(Êéí^Ä4 ýL‹ØÍ*pï‘íß¶K,&T÷3-b7 ½GÎ+{ÈÅ^tŽ=–oÖP{Ì–ã”3Ô{d£øMè=rm¿¹éxÜû†›Ú]Åoßß#+¿sÞW~e¡ž×DZQ<Ô ¼š‘V±[ÉÞ#›Åoqui»åÑǹi|ËLhy|Çò›Åo¹.÷‘V±[©Vú¸Îïdóv‰…'JÒÅ‘MãeNko÷îûxN>ºÑ<6Š_ŠÐ}l¿»>ËÜ3àçW=.CíèýûÜ(~Ós2Žl¿›:uT`9-£7δ‰EUP¾GÒ"æ=K_éÐ{ÉO¨¯´ˆ]^Vºô^Þ&¬ £—R_©׫§WïÅüâýIQøbñÃ÷HªÂ——¬§í×Òa·ìOêÂåBOÄâºð“ÚðµwDyàÎ' cfR.Ïô¤A,¾>æÆ'åáKެåW/ÊYýI‰ØÇŽò«—vGg(âûS§ØyäîøÒ’p)_óÄ{©_ W>Š/yœœG*ÅS™Î#¥âK[ÀóH­8>Bv´óH±8üÁ9©_ŠÁ9Ã=îþØï‘Õó7WZ{M½4uŸG*Æ“EXÚ‰ê«Ñ Îi©{Ë|¢üꥅãl)_òû<6È~ª–’ñ¥íÅÙR2¾è z¶TŒcÇl¡_r=[*Æ¡t¤#ÓÙR1¾è=t¶TŒãÊw—Šñ%¿å3НöڑΞŠñ¥0‰3Н¶¿ìbÛ~•Šñ¥m๋¯^ZtÏžzñ%·µÕW/íΞŠq\)Çí*Ü=ãKù¹e%:ÎtÅøg“>“ý®õÓrtÅ|€DÙÉ~ï*DÇÃÍ~;ñéÄÙÒ¸‰û]+nýÞ5“ó#Ðï φYÙïzäôö{Ï¡_$Øoÿ + 9ï!b\™|”¥rÉ~Û}XìÇòíÿ.öÛÞ- Èd¿íƒsVö»eyûív€Å`¿`¬–ìwƒÁ~’Љ~Ö\ˆ~V̉~Ç¡Tß›ýì[@ö‹V&Ú}N*TÞZ À~¶å“ýŽ.XûÈ£,ö³šCöó 'ûY û½qîûÊPHö;”>™ìW$û2€Ÿ½~å~ö øY÷"ùYÜIôS6¡ß!ˆ'úJËJô;˜³Zèw(—3ÑïP²a¢ß¡äÂD¿z-xC”k%úJIös¸Y²ß/ð;˜šàW®ðSÊß¡d”¿Ý)pN‚_=’äŸ ò;2¿ü>’äw0¸È¯¼«M~‡ò4’üCЯ<3ÐïPªN¢ß¡Ü’D¿ƒ™fI~‡,H$¿C™¥I~‡¨’üꥒü¥GMò;”6’äçF’ß¡\Ø$¿CNº$¿CiaI~‡’a’ü¦>%ørÛ$ø)R8¹ÏÑ“ä¾zexCøƒûÊS ë™À}å¹Á}ÇÉüRD¿rè§0z’_ ¿Òg7ùÅß'øìDà#Sþüê…’üJ¯ù•òsØ(ɯ<8Я^ Þ* Dô;Tí‹èçÇÜäwh[EòûIÖ<òó§ø•¯ ð+Ÿàç¨V‚_ùà¿8‡y#@9ò0¸+Ë¿C;‚_y€ŸŸÜWž Üwˆ™€}eÈûʽûÊwö•»öÕ»¡ã¯Û¹ð‚ ˜ˆÞ,g |³\ iwÊ# ïŽÂyÉ}H&÷•¯°~„“üÊÅñ„-çÞq®©œð+÷ ð+kÆb½€Ÿ‡ ~µ$áñí€üÊs?LÃðÛ$¿2 ƒüÜ#~åB¿ÒÑ@~\ÔæâÑÝûÊdì+SØÃØc†–“ûÊÊîÓëLìs¢bŸ™Øç›!ö)Á‘°ÏODìs>bŸ;#±¯¶ aYÖˆ}‡ª#ûÜGû<0ˆ}~5ľÒ.°O£’ÔWÔ§¥‡Ð§„G‚¾ú#ø +y¡ÏŸ…ÔçŒ3I}µø û+€új»K™æûŽ‚kGûÛ÷ÝûüP >/¹¤¾òú6õ•›õ•ê+]¢3;ÏÇJ‰úJ÷£Ÿ_ÖŸÈmÑ/³#Wѯ)ž¢_³¼´E?GbQôs|E?»Rôs˜E¿æ:FPýÚeE/U¿OÕÏaªTý”½•¢_“$AÑ/úHÃ9Ïý—RÉŠ¢_üfó2’’Õå%ú5ø)ú5„tˆû\Ü礶ä¾r3?e”ø•jR¿èÔG>YøÀ}áá´÷9'¹/.=?Üçè&rŸCŒÈ}MÅ®~Mò'Á¯Ùœ»Á¯þà×T#àçAðk*Eðów!øéýüöˆ~M•¶ˆ~q)êu‰~í0ýš±M~MeÊH~­Èwˆe¶† òk,GðkE½Kðk*¢Gðóø!ø¹ƒüšmÀ¿f;<À¯¼Ð ~õŒd¿ò­èw —„?§&ü5Uh#ü5« €¿V´BÆ3ÓXAø«ç ¤Ù6ÿ å;þšJþÊsþš Ѐ¿vÁÙœìçñMøs*IÂ_ùT€¿ò*Meç¥Ïnø+¯ð牎ðWð×T¶•ð×T/’ðWF&௴ ú+Ï ú«-ï€f…èÿœ¡–øçPt⟃ ‰õnîÅg8>øWFð¯Ùëøç¨|ò_iüW:Áæ¿òÜà¿òTà?š’ÿÊÀÿ5Õ$ÿ9(›üW$ÿ•y üçpoòß磾çÀòn€M6^ ã €åk‚ë¯0Ü“èe”ØTöè(L`ùV ÀÚκ¿wóü(„MlE$cT3•|`iؤ1Ë3Å€èP}`ýÕÕ¸y¡4y}2@ë ZFi—õ2¤^ËS‚˵A€e­F6L@ÀòÅ7–~¬í:® ™OÑìÖÌhc" —. C‚I€å¹A€å 3GûžX. ,O¬í%(Àµ†5ë ƒë¯Ö¬°kR SË*þ°Œ½*P ‚–“}ä@ÿ„¨NMô¦˜XÄ?Kȇ>ìÜxüÖêøIÿ!÷9ê†Üç UrŸƒ¡È} s÷*Hî+q.à¾A³nkÑÕtu>ïg)\ë.Þžåï‡áÏÊ{ðÛ×þŸ?‚µ~–›¤ø9`†Š_ù¿r„’%©*ùM!ù)ò’ŸI~’ê$ùuùÒPò³ðBÉOŸW’ŸÂ‰%ùY £æÇâ©Öü$¢¤ä§iÉÏ—¦äg¥ä§F¨øI‰‘âgœ…èW¤‰²oýʈ~~7ýê‘õy‰~ÂYŠ~êý$Iôs;ý„ýôr$ú‰C©ùùö¨ù©j~¾4¿ò÷Í3øê~VÞ¨ûéeI÷ó9Ôý|u?Ýu?+ÎÝ1Ðóƒ~Ž)—îÇx`È~‡’ýÍ,ÙÑoRý¬èAô“h-ÍO ùùF¨ù)úZšŸ¿?5?¿i~z1©ùùµPósŸ‘æ§›¡ä§ïFÉÏÍPò³ÖMÉOOMɯü’Ÿï75¿â1 ÍÏ£Ÿš_iš_iš_=²¾Ÿ€’Ÿ_0%?BÅO‹%?½MI~úQ??7GÅÏ®TüÊ9ãG&)~îTTüü ¨øy2¢âç×GÅÏ·Á¯¸Ü_ ~¾?OÉüÜe(øù™¨ø•#PüüQ¨øi Hðó)üt¿ÔûÊ)ÐûʯšÉ@rŸý?(÷©UÊ}>µÏýŽrŸ_.å>ÿjŸK¨ö•Aíó{¡Úçf®ç3÷Rìó ÐúüE¨õ•V¡õ¹«RëótA­ÏoŽZŸï—b_9çüÎûûÜ)öùþ¨öÙñ[jŸ¯µ¯\ j_¹Ô>EîJíó9TûÜÕ¾rN[Ÿ7AµÏwC¹¯üfȆçŒûÇýQñ+GùÜ~*~úœüür(øùãQðÓìÅO)ÅOû-)~¼¿r@ )œ?ÖQÉ}åä>ÿˆä )µÏ?‚Ú§)j©Ä> R‰}Mûô¤öù5Pí+G ÷ùÅPîÓW’ÜWZ†ÜWÚ™?–RÈ}êE’ûÊo˜ˆ3»ä>mœ%÷ùÉõ®Gm’û|Ôû˜Ö@rŸo/å>ß å¾rrŸ&É}~5”ûô¹©öijtT16ä¿‘ ZªÒò¸;™žJpwÊŒ”p7J°Bù\²‰¡|…ÓÊ'ÍZ¡|Ãn¢ˆå“qÔ±|’ª@wSEIw{%Ëíåh:žt7U¥±|̹%º+¿a,Ÿ½.Ê}Gʧ” Œäc½"±Ýåtã`»ÈÁ]lwí ÿn´»äÌA´»ÞÞ2J$ß%™›hwI%&Ú]R‰v—ýã€vqÎùQõìk-´S…1©zJ¿#Uï‡;g+^–`;ä’ªwÈŽLU)â wò)Ü-ykîÇîqC¶S­/±u)²Ý’ÛU²|€ÅvK*d»»¸o悤:yb;G´íʰÂd;GÆî,”î¬Uîl’N¸s¤ á®üpw‹Ó wJ²-¸»ôy w¼w4æ‰ívJ¨@WI±ö\Líí §I“?€þž˜ô÷H“%ý=*þLú+ßôWÏIú{¼PþvùO&—Çù?@³ilú{ìÆú‹ÕË<èïq†Ðßc'ÐßóÎLã#íEòó“Ë%z÷ü$s‰ŒèLJÿ-ÈèÀ3–lþÛùôɃOÞßAƒ>øï‰­H.ùïQÑò_ùâà¿Ò»ÀóA€ÿo¸Àjâ‘ÿâêßl.å97ÿEpsûÄô-37ø¯ŒðߣɎiO?!}OIË’ü÷” ¹ä¿ØfõÀ÷t¥Úü†Þ¢É1-‚Òÿj³‰1ž¾÷(k*ù/ÁÑÛÀ‚É"¸€‘Vø èﱉjÓßãPWÐ_™Ç@q„Â\ÒßS„¹¤¿GaÕ¤¿%û#é/ž€<˜ô³z(èo=ä ÀßcKàoÉBµÙ¯\ðçéœð·j ø‹"ß\.±â}ô½Ç9l±r [þVI,“ðû8ì·J¶—d¿ „êι!Oö[f°ß*9Yþ"ûïødr‰¥ßðçWö[·b1Á~Ë}ì?"C&ü•W úóššô/vNÐ_Ô„Àðý•. ú[QXöªº‹m}òz£­’‹mÕ\ÜlËg±­O^o´Urq£­š‹›mù,¶õÉë¶J.n´Usq³-ŸÅ¶>y½5È•‹;Ûúdìv—çYhë_ÊØ}Þ[Þø»ÿ0c÷?±ü:o—¿ÿƒÙß§üîDøÿ"cwô¶þ;ÊØý¿u‘ÿøW3vŸI××Êy!åwnëÄ{$òÐäÎ-,K‘ë-øç\‘&M>ïßk§IC‰¿÷Ü5ÉéÐv¸¼69OZì:óМùó»+(wi°;eÜÛ/ŠhçG솄Ù©xÂíGŽãH“Ý%#Å8ÆYs*Ž# vW"ÕØsIZ=BÕiƒ¾ñ‹»çn‹Úø8Ö6ܲ\ð¹k¢à®(±é}Žp{¹’XÒü0Z;253¼G’,)v´> $Ž–¶:£Ç{äá¦2-£¥­NSí{d¦•@ÉGK[Y}D 2ðnàWi«[Ê;ÚJ3Áqòvžž&I¦-~<|‚üü£wþÑÛH“)“¥ŽÞͪ‹GÒöžÐ8ú™6‚ûùþ=ÍtÛП·ÖgKs$E¦÷H2…’~¥@6þÑÃL·B Ìoýrú¾{¹§Œ3ǰ¥|¯ÄX¸qÂLf}iiz§kÌ{ mòËg— 5ã `‰åã°¼ÓèÿIËûnn˜Û²G¯ßwt¤á}œ<áN»»;ëygþtåÿgZéViæI_瀙NéEÞ#iwW&³wÓ‘v:eï§ÛO0`,†º›ÒÁ{dK4ÓÅÇNò{¤Ùý [q¥Ù]äüI³»D€þŠgö* ƒ±`vvŽñ¤Õ=äüè c óHAä)Ëo0ÓRglï/ òžzÿ¾³‹“xÇ<Ó@ðð³LØéäâ9¢¢ÁJÓ3æ®I;­)c^ƒ]äÆ9i¨ ˆÿ¼Óè®`£1WäE©cÌ'î¾úuôbÿéY¾[8AÆDy0Ôp„Sá™9·ñ"“qH|]SÈu": ì#²±ÞÙíœ;ÝÁ@Çrå·ä9ד3ÆÂÝÞ°ÀvdÑÝâù~w®í¿l…/mS㢙ŽÖ ‘ew·Q£=r¢¯ÏÏÊ»EJ‘ý®¶¨‘µwKÒýõ ®Lº.Õwß?iÛQ~74ÊEÏ“‘õwKá€xGZE® ;ò Œ(Á»gJMÿY†÷¾¥%Žudu‰ ñ®ƒ"å{$¨Ëb9PŒwi"ÙÅx—r Tã]šÁ@5Þ¥Äv#TЀºË”ã^¬âƃ`$4 äÊ 9VV º¥}Tåu¹„ñXK©" Tæ½å&<žÐ±]>c 2ï­ìÚãI{I“ÚB¶§rTç½½=P²å´åóíôä·ŽàOjd¾ciÙÌ×äSGæk À'ömžùp_[þUr_רוg‹Ø×åBGì닞 ľ¡‚šÄ¾“%è…}§‚2û†OÉ}ãdç"÷÷OîÞ.€û†‹’û¦¦%r_XÆ^Üò>!4¹ï]Hð]À}—â6È}C3`rßô;÷MÜ!÷ÍÅeˆÜ7µíù• ý¦”i¢Ÿëý.98ý¦jF%úE Ï$èeÀé èwô 'ú]JÃHô»üØ@¿Ë›°ŸÓú“ý.ß ØïRb0²ßmûÝÊŸðw-}]ÀßmSèï–é¯Þêípý%üÝrÆ$üÝòJ%ü•Ûü¹áï–FFú»¥¯'ýÝî² ?oDH7+{þ ­þÊ6 𗈃 *ÜEø»åAø»¥Ðþn©ÿ„?—üi‹ ö[²‘ýbÑìÈd¿ežûU„Lö‹Þ Ùï ÆLö[6€ýê°ßAõŸì·äè–ì·äCø+wú³+ éo)ýé¯lÿAKa¢?ƒ1èoÉWôg5;éo)è@ô§´£Ä?ëïâ?0ÈLâ(ü“«¦ðψü[6L ÿèx@ü+7ü[òõMü³HNü[ªGü+/ø§­ŠðO©2„æ¶›n2Šÿ–ͤä?Û„ÀÅÄBþ³-'›ñŸùŠ(!.­¡À%ïC`½—Àå5¸Ý€TÀ%gàB¿Úô·”žô·èLø+ó ào)#ᯠ]Àߢ?¶ào)’\ð'O9ŸK~f„¿bÙÝð·dx$ü-U×"üÙ1Šðg—&Ó’jþ–ª§þ–< K¿à0OŸj þäà.øSÂ_|½kÃCC¾Ù¤?›¯I°ý–¼S…~7×w¢ß’?¨ÐO^ü@?9+ýlû#úy‚%ú-™ ˆ~ÏAïY¢ß’èW[Nô[*ì#ô{|$Ño™ÀÁ~ži’ý4àˆ~åö€~‹I‘E~2”Šü:ˆ3±/¦Iì[ª(Eì«7’Ø·T¥Ø·T<‘Ø·ä8›ØWº8°ÏyrŸ½çÉ}ñáÎIî‹þ;ApÉ}KQ ä>ö!Bß\BÅ ŽV˜ È|Kñàd¾z¿OÿK‰°î=àcHè[”œ$–³àÙŸIÓmìÛŽÏ¥ø/ìsj`Ÿ]É¡ô‰¥}*]úš RRêë—¯„„ËKéÙ¡õ 9Sëë*²*­ï¦†ZßYh,¹oH örÛJì›r¸#öÇÌö]T"I}SÑ`¤¾ËšÔ75Ç’ú.>©ozOê»mÄõ]6$‚úîB†}–䄾Û[@ß%'ôÝêbBßý¶~|Ä>Ì%ôÝEDßÖ@ès¹YR_,HχúdÑHè³í‡ÐwÙ è ;Œ®€¾[Ë„ô>o7A}··’ ¾¥Ÿ¤¾{¨GP𓺻¡Ï$A¹O~åd>É|Ër ˜/l^€·D>ϱD¾»ˆ{û&½+%÷i™ ò­ŒMïiMÞÓÄMÜ+z&poY]îyìKìÓL(±ï o¥Ä>y“÷Êž¼í<±Ï›ò޺ˑϼ,µOE˜É{K!¾¢&ð-…ËøŠX à+ÄWö§”ûlÀñ=‡U8È}îžI|šÑ…| z&ó…ê û™O£ÒûšizŸ‚DÈ|ˆèð™j%öM#€Ï#¥ˆ}¼Ë®Ô¾"°ø,iø¹N ød'ð9šÀgH Ü'»€ÏF”ûlë"ðY–ð9zKÀ÷\ºã¾Ç.$$>w6ßcÉ…Äg‰ÄWÄfß#‹;‰/ºÜ¾‡!K¾Çž¾Çdà‹åš—^±/5yïñï=ª}NÞsày¯¸\÷Ô0p¯t{{ïÙǼç]y¯hî¾G)] |Mo¾z-ŸÍj¾âAà{ä‡à³×E"Ÿ\ç‰|§Å|Eó=—é-™/Ne;É|6Äd>Ç ’ùR%äS>)"_\Q àç ŸÃš„|ªKä Šy@>•µ%òyšóé}’ùê9É|I"ó=²ú%ó=JùJæ{"3 ÄÆnt7óÉK‹Ì‡yŽÀ÷- |rž"óù;‰ù(sùiD>‡Ø%ò¹w ùGDäs ™{QŸqÄ÷hññ=·žÄ''_i‡Ä'£ªˆÏrä&¾ò@¾ò ˆ|²ºˆù,ƒùÊÇîŒ[¥Õ‚Ø÷pÿLê{ŒÐ ¾GvRßö"Xú謑ÐWOôIQ«r ôIö!ô=Ö°}òÄúö  ûü]À}…ß ~ªßNðóš ðSdÁÏsÀO6~©}4RþQnnÓÞžq+í9'iO¡°¢½þïSI×{.‘h¿Nní×ùXÑCu“ΠðëdäP϶1 ^·Y¨× ‚%êu»S€õº÷d½S5 Èz§$[²Þ©À.ÂÞ9˜ÖŒ°7”c´7¾<ÒÞUˆ´7|Ç ½©¨aÒ^îAóÀ^›¦2@â“q‡´wÙ€ Ú›ÂÀÞ´vØ›6kö¢´7Þ`o*p°w©t­>[a)ñY]ì]v5Û´wY¼!í)— iïfN=ÂÞ¥T’øi~ÉzΠGÖ»ç.…ï²i²^ѾRá“{`ï–Lj>Õ­&ì„”ÀGß)ÀÞí·Iس² سï aï–›‰ô=9ˆ÷Œà›÷wk¢ïY¢¤s§‰†òž¬4Ò÷z.}ÏJ,õ=C¾G¿Ë{œü…{E™KyÏ.˜À={žQÞ‹¨Æ¯¾'Ï3Ê{Ï/´§}‡ä=Ò^Ñ,¡ïé èÛ©,’÷ÜëáÛÉL5Ö÷4÷зӽ°g? |—Œ2„=s>syÏ" |ò·ïyËMÏ®zÉ{aœø¼·LFä=«êøn¹Û“÷ æød-!îy;úž’² ÷d]–¾gyœ¸gïnê{–„€{Å€BÏ÷ĽÓpÏ@Ϻ0¾"»mÞ›}©ï¹ËRß“ÙZúžé{îmä½&Ò ¾gMŠúž¯E}OZ‚xO³”÷ì/™òÞ%|ñžŒ ä½F®¾§(b |L%ði™ À§M˜xÏQ¼§—CÞ“–x¯É“ÀçžDO‚‰E>uY_—©ƒ"Ÿ¼P¨ñÙå—Ÿ [ÔøüP>wQj|SôNà³GIj| »ðI… Ä§ ‹â=ñ>ÆKˆö¸3³ÀW$¿‡ùÆö ¬øä|,ï6Bà“¿‰anâøäè.ÞÓ‡ïi“Ƨ^.Þ“#$%>ëK’øhà…ħ$â½iÿOH|ÅG”¼wI„w§½ÿ(ññÀgŸAŸ‘µH|ÏÇ»ÓN ¾ë|1¡ž_à“[€5>nÕ|êÔøü(óÉh-™ÏNà;ü+È|7T ñž<«ÊïÝTù$Õø40¤ò¹óøªî‡EÕx•Ï]”*ŸA—À'µIBŸr ø<ƨô=?”¾¢KBéÓÚBàsI}|ÎßÊÑ]%½¾¾wÃ. È+GyJϺ!¯&åu=9‹”w:i(ï<‘ôŠó$j¨6îTy·77À¼©]>(ï*LGÊ“T±)ïVú RÞÝ-&å”7É à³é]|ò¾åQ„šžêL‘ò"ªç$ÔÜ{Q÷Cß%3êÆ¼ 0Pøg2Þm³µÂ÷¨fKÑSºu…ï1¸¢÷ÌfŠÞãŠÄ[Ž…dô^ù¢÷ #H~¿* ^Œ]€ =+/ŒÞ+b=ÛjÁçh'FðQDð½-÷g‰ÆÉ>‡C‚ò¶x3¦/—$oRÁ'ÇvRž“)‚ÏÑM áó&˜÷¸cQÓó¾!|výæ9£bø”Nºžl â³ÌC]Oóä¼çHQדiKº^ñy„®çwÌ ¾î#ÐõJ;=Y¡¡ëÝÖ ‡Ö$2£ø¬2"ŠÏÚu= ÈŠâSu½ç‘†ˆ0>j“®'j§¬çÏIY秊4Iï±.MÒ» YÏ]”a|¾=Êzhé=r4£ª''Þ’Ã …½¢ ô¼Í§°§tŽŒâÓJa¯Hi zåÚö¬:ô"Á}2!ìɦHÐ+,@aÏÁ”ŒãSD„½Hæ„¿“ôžâW aÏѵ ½òu)ìY/éÅÊÉø:{JO¨H>{š’ôd"¢®ç;u½y|ùœ‹PÂÞ´ŒaÏÑÖö”¯PžáDzö·¤²ç×EeOɤìy%éi{(iÏîÜ)í)½Q¯<QÏÑ”öT˜SÒži†Òžã(íI‹°´§®Ô+2"Pï±ýŒ¨g<ݨWÞ µ=/]Ôöü­ˆzv ¶gSµ=w@j{FZj{åH²Þ#ÉMâž>Àz”SÜ;ÍWÉzÎk(qO¶%žUm‰{E`;•ÅOŠ{{ºú÷¨íEP`ÕöôÒöLSÔösGÜSÂQi{2ç ÷ •’ê©ÔAÞ“I¸ó úžº›õ=óÝÖ÷¡ûÍ÷ÈYÛúÞ)ïR&¦U˜>‡°o}x/Ê}‚ùds‘¼×ÌLK+¯ZÐÞc}7å½°=á7 ½éˆ@¤¥½…Ø ½GvlÉ{«ëW÷Ì+”÷Š *pÏÞ‹Ô÷ä%Þs(!xïq4d |6 €÷ŠíÿÈ{ÅAO yï9nh¯Þ{ìÂKoÐ)E¼g¼Ç2D&Ywû¾~Ê H ó:€XÎI¿N {údé—_§d1ûu²À‰ ðèj'!ð¼8HNA¿N×P»×1‡‹ îÌá⸻M¶f3…‹Wfqq4Ó¸”0AP W+R ·Ð¤@[Ê™ÆÅûFR`9Òyð#‹×"¤q±ï'r.d˜ÇEykjrÌãbXd'Œ *m¨HÐ>˜Ìã¢ÊËr픿¼];å¹µQ°¼   £x‚²q­{)— œ6ÁrD¢_§ü°å×i¯-úuJhN ,zpì4¯FÇNo¦HÍJ<;‹'(P†tåq‘ZI<‹²×hºÆnŠZŸÍÛéÛé¯F,ª"Ä>åÑÊ>'çNëër± íâHçNTB ueB ¯•8 …Pû ªÁ¹óWµÏÎÉ„@ïi vÊ$ÚzD,’ !P~Q ö¤ÀU›­·ˆåEH t;í‹^(?b. Bùvêã‘=˜Iá@%Ï )P™QI‚T¹wJ'¡ÜWÜ2Aò5 Ú÷È©•è=.!”ôFžZŸ¬~ €×ÏD.Þ M@9m •6UX|=€QvÂFòßý‹cg!K  ‹¬atàP¯Ž¨tÀ–@Ëÿ@u+ ‡¥P^ä@í€Ò@[Ä€Ç2&zð5Ëm9 6‹“À‹™…ÀÞ6‰ÿÜaÉE9#ÿék&ÿ•X=òŸ™RŸêÿ–iüg«øÏicÀ^^Ȫ!þÓ²@ü+ñ†À?ûÔ'þ=ý‡o§m*Æ¿Ÿ¹\l³þifþÿJàŸwÿÌAä¿’7æúº’ÿ”‚Cøg5þŸd.…råÝ©?áŸ6ÿÄ?ƒ‘ð»áŸ”'ÒŸ£¯’þ¡`úS”é¯ê‹ÆÞ0èOÑßiô'ðÏ7Lþ+4þ³/ù¯0XÇµé– þ+Žšà?‹¹ä?é½Ä?¦>ý7R:wÊ5’ô§œÖ•þà˜Iú›v–tQ’ƾã/Åv(ú“x.ú+tú+Ôú³û$éO‘èO™ÎDZrDª& ú+Ñ‚,Jâv6ý¹—þü©}Rn‹’À3»æéŽâªïk‘Fêéÿú?í"ï„Gþ]G®w{¿òþƒßù,žS÷'v¿Ëx,7¾‚Ä×ïA’ì}Œ×ø¯åÈ„ø=kÇÄßµ-)máXiKGÜV”¶ ©µ<¹Ž¸-s[>â¶þ³’f_;â½¼€þ²éÎ2Ë<À§ÓXŸÎs}ÝJìû;' eêýå„Ìÿ:œû—¾Ð"8ó,]èï¿t«è0×®¡WÏRSYTÊ-åߟ†xŠÚñ9læéd!Êvx 6䓨R=KM¨œQn‰>Mé$5UÎRS»|JyO<ðiJ'©©r–š :žÒ|šÒIjªœåQsVyWwX{»lìYßåý“ût6îsgã¾þ0÷¹sd_ÿößþÚW=øgÒoŸßË\?šþÿíÌÛãŸÈ¼uËWÌ­/7µÆAý¾ÿ±}÷^¢¥Ig„É(‹·°J½é»'GQÃ÷äëA‚š®Þ-Lٻ鄤ö’Ë»ÏØXÔFœ{ûüngÆ®·0¡¾§D$ÅÞ´ë [û•Zl6L¦÷{$ ¼{gÓ¢Hy'Ѐˆlæýù»ë™a…ÉÝO{g’;¦â0ï–û‹.-ÎynVÖiÛÂ<'§¼(`ÿ5ç|rWÚûvi›á”VœVœÊ}©Þ±{Z>T¬: c†}eæÞ…ýŒS¢¨JSs¼n Þågç»U”ZëócØ~}}í h3"pí÷e_qλƒ@„È®wE;H%²¸ÍG˨¾#î»ùóóžïvyÄr/Ï9÷ë~[~XXõÜöÎ9‘­/²YÅ9/‰¦Üq†{ñˆ#'ƒ}²<÷ ·÷àΰÆ9áoí„å*<,!úÎ ï››vtÃí+ cFn,y¶ÛÆÜ liu®ž‘Þ±'ÛŠ6ÃþËpØhÍHä½?T˜ëó£sïùgLsô@Ù_m†é…I·f$weÚã;t0÷š3ì*’÷ãNgdÀ¥Â)9ÎÙjFÚ"öÚ½³8B"1Z÷»9˜5F댬Ìb³^ÏHrÚî÷·^žûå¯=XoÄ—gb°Þ‘aN‡Ï¬;paòþ–³®<kÇ·k—¯Ø—‚z_{¸^¾øÚ†À¶7€Ü‹ý1\¯w‚qg}„9,Ò¢tëµûè‚Îr½ÓT ×û8ñ9¯¾=æ•—FY{¼ÆI»Î+Çëâ=G¨OŒ×0ìÛ¹^ŠÊñzÁèz͵ÇkŒÀ¼vØuã”wzJD¼"ß_‹=g×ÚåfÔ®CÃa¦sÞ/Ÿ¹Çiœ£îO³Çk`ûWqï1^#b*Oi[•Ü—Ê­c¸^êEš[„Ú+†é½ÏY ûˆÁ‰áZΙ»²òž©ÐÎ;SÅpÎY2:yÜñ<Ó)%†à·•6ÉN‰1»ç)¶®a–ÚÍÆŒÑ­¤Í*ìÿ o"»úN ѲW¤A*Ä‘ûʾ”_32õ–}iáÈ&³ò"™SÛ¯ë䯢4Ùž'úö.pµ7ܳmh!1^#]ogÂ!7Æk˜™Óò äÞ·ïšvûÀ^]g¤RL¯€íE·OáÀÚ׳vÿðêõ¥o»ÝÌ;Î>ºã¶ãå\è8azœW>f¾®m‘Ù眸v,×ãÊk§TÆÇ§e—LOͰõÄ€>ŸÃ* ûî›/ryrÀúÈÊõõw®äaÜÛã•kÁ.î»Ç+ׂ÷Ⱦչmûsi¹¾¾¬¾h»¸oŒ×+ nyäÄúú¾¤GöúQ‡»{õíBüž2û“–]Ý7û~lkg?®\^Go¼™+—רCtg³w.¯1½o‹Î®íÃ5&ê;¯ôäò:ƒ?Ïyry¹{/M»¶o ×HXº·Å»¶oŒ×÷–s¢Úµ}c¼¾ÿÃc¾«û¯3ÌîyäÌåõj˜J{Ë©x¦¾f®®1§íÞÿÉÕ50ìà¼÷Œ™«NhØ=\¹ÅÚ¥}g~ËÝõweß$MLn»²ï®'&¥]Ùw×3/Z1öm°Ý¥}÷hå¢÷L¼²›ÉO¥}/t­üº}äê£le;ÑÉâÎóo3¹ºF-Ñ–G®\]càÍlùÊÕ5%å§Ú›äÇóè®ì»Gk©Üo«?¹ºF¤ü QÛ7Fkl·K?½ºÎØq åòz‘íž}¯®~çgvÌ=:¶=þÝFæêº3=íû¾{°žXñvaßçó¶¢°ï¬zÇQØ7k¬²ÙõÏ;W×ɽKûÞýÓòÊÕur¿·KûîÑÊ!Þ#ÂxÖä®í»Gë‰]Ø®í»G«t¬®ï@ÛYvmß'§Ñ=sEiß\]ÃþºòH®®m濉Õõ=²ab÷Ý«kÇ:ùvŠ\]'W×]Üw¯®Ü‰÷H«Ã5¾Uví(î»WWõ¥¨îÃuF,ÿÊ#¹¼Îýdæ½ØÝfÏÕuª»E†®­‘x£BHê=Z{GG‰ú¾1\çûÚò±bFˆá:õv¢¾oL0ܧ9%:`hYÙ̽—×I 9ç=”ùO'å î& ÆN;eÂ`$ðÏå0¸+Æ‚÷r5Âõ"Wž„Áëlš°ƒ©È%d& Ž%  Ž]>v/3ÀÁ-‹õë‘ÄÁñp’&Žð$J—4âàÑxuààx‚·ƒ»Â)1qðà4(<´G!ûÂÁà 'ÚLcY@]êÄÁð÷I×Uâà{.â`˜fP¼8Ø8¬…ƒ¡_µ¶(>œ¨ŒÏš;â`Ô…ÿâ`ã ÆA5Qà`åÿ…µ€ƒa‡FZàà»ç†ÚAl"~à`\*¿q0в>pîÚ+Öö$¢Ø‹†p0Ä2™Ê+üÈÙŸKV#ïÛ8S,Íã¡àElÚ"“ãRlÚ›`Š8XÎF©ÙNwà½bE’ †_æŠõBŸÒ§æŠµÓ^@ûÛ+VÓØ#¶5Îö·ý˜ÜFË)½£È#Âr€°]4 ãà€0¼ÇàÏ ï1¨kÂ8çþa|ˆ”´ „-i­aÓð$¶ÁÑH lFDal2 @ªj>at”œ„û@¡Ÿœ@Þm9 ›0—@Ø41›ð <èONl¢a»s¿+Œž“£“<è»!Æ÷ìlÂSò`“E‚<s¾-ð ‡=°Å²”Ï@³Y°ɌF Œ»Iû!0zNÒ Ðß—@èH ŒÞŸ;0vµ¹dýTB?°\ @Ød ú›¬•$Â8'al»Óo˜D×JšJ Œ;þ¡»$€p×NˆFéd4ð஑§€c5È9‡"aƒ™EDUÙPI„ñÚŽÆZ~}ˆ0~5î@„íÄÆKHÛ‘óƒ„Ú ›¶ñ@ÂíUýAÂ&ë˜ð ]^L¨}„˜0¶Ó÷‡ ÃÙèÈsÀ„­c:jr6™CÈ„qäL"TÄ„MÐO&<8¹Š ·Cù‡ ãs ‘ ›‹Lè÷&lb1aìJó7‰„-6åy! a;°ÆLs‘°åÞ¯ á¡ñI$<8‹ µ}!áÁI‡D›ï$.a¤»’ä@„á¡*4_Šu@á! ‰ðàäJ"<¸”‹ÚÆI„wB"ˆD8ÇÿϦì¶DxÆÃU‰ð:°Ì’ ·Uò$B­ ’Ïô¾ Bïùù*„±“«PøŽêv”cOua“½™alAòÒ‹kVË=BÎ "ÂFí…ú`3¦µ*“£ÕÜŽ“c¹‡°l·Õ@,XÚ$›”RaˆYÉv „^a„ –aldÒ„¾PÛ,¡hY@ ]!®Á´éB!…€Ðíâ•€P2²€p  „O#Êß”{m¡¡x™@xÃÔb |.eEÇ‚%IX@¨ €0,?×Ç‚õÜÊ® "|ΟD¸Ÿ$B_D¨ž"$|†k¹äŠõÐ!$ä¤b$Œ/ûEÂgþí£Æçƒs-Ö«k:\0Ö«.;€P"10bP˜?2ëC¡®L”D'4Ç‘OîêŃ';©xð„[€pÖRã ×Aã Ø]8È„qP&áàI€žìÄAÉ>ÂÁØ‘U}P[<ã`lN<‰ƒƒ}K8x’“„ƒ²8 eØê©ÄƒzâAÝ €P¦¡îG@¨O# ”aO@¨çraÊ@" ´: Ô+†8™(E Ô7ö À/ ¤ùÔ@¨·# <ˆÂ³#®N@¨ê½ eðrkm ¤c ,G„úêBŠ+BÝ!‰P!"¤A\DØ9û‹!ј)L˜O±(‰P)"Œù—J„E"BF¡zŽˆð#šyqa_”àH„ÚÝŠÙ²‘Pš‘°Áše$|_cîΈ„n÷²ÉŒˆ¶Á>b"¤UÖDØ­bˆˆµEöÜYõ#aÌOù#!5Mñ A<(5A<ø~˜ G°¼v:q“u3ÄÁXR2ò͈µÏ 6x$˜}„4x°EƒmPê îDM_lÏß>ú iB4Ø`£5 ÆR˜ “…h¢AÂEƒW8Óà‘bàï0xX€# ’‘ƒÜæñVVIðàÞÀ$¨WN<¬C‚–D‚5‘à!I0®Þ¡æÚzÐâc4j FnÔE‚ñ+°!Hð¸Ùµ@‚mT"A¿O  ¡‰(xÜp{6 ÞìæDÁƒ{a£ ÷ÂFÁw½JY(sAƒ4 ‘oŽLÁàûTy-Áà{ '¤Ô,¼9|ƒVúƒ1˜0H+³aP Whà çÇ?ÊâMŒ`¾ñ|t$ÔÒK™ ]DÓÚLú“tFø;hÉü@Þö;è‰Bö‹þ²>î¡Âcë2ÿ¢({ÔçI(£ø¶*£ès¨ÎÐH=0×Uãß!‡â_8Ì?ÿd9þɧÞz }J„qäùèn‡ø'»…ð/~Õ?zà!5†øWŽÿâ©ÆÇ=ô nAúóÀßA•ZðWîðç øs+`¿h÷›ì§ùAìÍö¨Ñ'öÓ°ûEÌåé×3ÙO_—èwÐ)ôS¯&ùíG&¢Ú«SùÈï éTäwhwNò+¿ùùɉ~‡¥5°ßÙ‚P¸—'7CöÓCýüˆ~~çD?¿P²ŸÙ¯Üد´öÓè%úƒ Ù/NA)?°ßAï±_ló êýâ3Àìç$·“ýtq¢ß!}èWÚúùn€~‡,VD?¢ŸŠèwDì%Ž`y€i’_ôÐ$}’Ÿî—àçkü| ¸ï¹ï’“ûIÑä>7ìócûÜ­}îXÄ>!‰}îŒÄ>?±ÏƒŽØç^Cì;rŠ óùË’ù|e2Ÿß&™ïà¶\ÌçKæ+7æ+7æós“ùê‘d>)2Ÿ×$2Ÿ_˜¯x4Róâ`¾rÌWŽŒ®¡Ê#\U1àÉ|‡|È|>Ìç7Jæó3‘ùÊ9`>órœ"ó•sÀ|Þñ‘ùÔMÄ|z9d¾ðÇGÔ@æ;¤‘ùô¥}Ú=úÊ@ŸæfA_¹@Ÿ[&ô¹Rß/AŸ“ÐwПXÔ§á+ê;ÎÛ~R_¹8¨¯´“ÔçwAìÓ´Eì+wî;äHîóÝû4áˆûbfK;rŸ\­¬r‹û4¿üŽ“ Áï‡ÁïrIðÓÆNàW®Eð“/ëâÊ*ÿÒ‡+ëùCŒlPà¼+«$5€ß!éàgOQ¬¬2Šýd úÒª…~'„£ŸÏ!úƒ Gô£ÑÍ" Ì-B?¢¾ÈOÆ"¿½Àä±û`A¬¬´Ô™ühÑù¹’½› ~ 82øIËøÑ•Îà'ÀOvm\?YE~Œ­5ø5¸éüäp*ðkð“3øðÁ'ø‡B„ÁOw(𣱇Ü'_pqÍ6ľCj#±ïÀŽì·ryõ–ê“ô¨¥ôäB• ÷Þ ½gzRh(õÉ—RRŸ}; ( «£iOU8`§î¤pÀ¡vÀ{§ü£Øw£p@ÁªÂcIXï9ˆ¼7¨"÷Æâ®Má€ñŽáí™ Ó|·›Gå½IU_¼7etïMIä½)·RàÞäÄ&ÜSpoÒË\¸7qÿœ !îEqã|ĽŽ€{sÉI¸7BÞ 'éó|ÓÊ"€/œé‘ÏÀéõÒÀ7åûDâ+§$ñMév$¾©>@â›a¥A¾¸\˜æ:þö¾Yä¿\—¦œŸ |S²+‰/’Z1V®Kó¡³'ˆ/¼ÎYe4—¥ð1WÍν,Íç'ñÉ]Ä·«6#iO®K“–/_0‘ÊÓgÀ‚Tj_`¾\—¦´z ßu '̈N[B¾ëàŽ•È¿‚3*oJÍ%òM ‹@¾i‘ñ€rP< F0™oFŠ€o<`£»,™/üÿïÞ7åŽGæ›t7ôùƒúæÃ.ŶIi1¡ÏO¥x@.Žìre< LÙìòEe8 ‚ΨA­p@¹À+Pa˜ŽdŒ´â}„ñ€úÄŠ”Œ©x@…2P xrp*ÐG(EIá€T%Ø9(+žÃÃðŸð‹Ìà?„6z†+*ŽÃÝÃñ¨Hð4 ;»OŸâD(OzÅj}P<`lŸ íe< ^†âÕ³~“1fŽŒl}ßx@Æ29P½Kñ€¾ã¹·t< ïñ€ äs<`?È}ú•-¹1 P~`D? s¡ß¤k‡ ÏQ@ ÷ýJ !Ðo2à^èwÉÃŒèwçˆÀ &m‘_t¯ë#÷ÅŽíù8€Æ×KR@ ãÿ…~úÂB?]Êñ€PÂ~ާT< D7‚Ÿ£›è1 °Ñ““íþáþ9o=ÀoŠ~¨fÝ(ˆ–‘U l|Yä>­Vâ¾XÿçÇýs^ ,d@ /΀@¹N’û…IîsxÁ/© ž#øMÚ¾~QsT÷Ïɽ­Ào2@…à7›ä[Bð@~“6A‘ßTÔ%É{ ߤo#í3ʈ@î…~SæE.]ä{¾ô¥øÍcP™øÅ)çÇùs2JCà7tƒ¿ЈÉøMGû%ùÅ;OwU’ßdò‘ßX¤EÆ2‡ÀoÈçVñ€ŒøMõu‚ߘvÍåuÐ ,ðŠÞ$ø½T“ ÁoÉÈ\¿!5–à7š@òë¾ß©øb ßɽ¤Ðï¤ÑŸIë-÷ÏìÎ&äþÇ7@añ*ŽP( FV-äƒÞð\6*šßLÈ`3!·HfB c1aðÆøx€*êfBy2‰ ;ÛvE 6.(Ê‚B(t?ÉpdÂaÏd¡H92aÄžŸŸ1C‘K„“VAá9¸S žò%"žÔÈ„§ä2áéP>0a¤—žð Ík˜÷À„Ãè&úd¡02¡‚ìÉ„Ãn¬`ÂÌÄl$Š\"úfˆ„>‡H8œoL“ÉñqNö&FK0á:N&ô&jƃ‘ ‡¼ÿÈ„ƒ¾.b¡™pX1Žv)k.YCr˜0ò! g ˜pœ¤a0¡¯M&N=&ŒW{}dÀ!ÏC2á8˜ „L8äïF&2)‘ ‡’• ‡BåÈ„C“™pü„Cá¥dÂÁ›˜pØOL¯gÕ1å0áP,0á¹t ˜pïÀ„þÂd¡­4¡pÀ *&ŒeG!9’ CèÅ„ƒÖr1a|Ðë“#fh¯O&dâ !áø ãvH& }'ºw 㔣Bá/ ãK%• ‡RP‘ ù‹L8d‚ ™)È„çbW"úm‘ O¹U“ ÝÝÈ„ƒ´b&T,5™0–ø?f‰ä@è‡$ž´f Om¿ „1†ŽOD`ìË9“~óÂH­ oOá©]<€PB@xÒ¯_@xÊÓ‹@xÒ+^@x>J#"J <ƒ! <OI <åDH <á <å„I<™‘J4¨4ŒÂAoâ Ç!qpÈTC<9­Ó OZ§‰ƒ§¼X‰ƒ§}9ƒ§ýQÁƒšÒŃ'å‰OÅ$“O‡ñÏ["xð”Ÿ-yð”}„â|Ú<æ·>â|Úç.¡Qs†ûHi ÇJ[:â¶viœUs†ûˆÛâ1·å#ÿÙy¾ÏíRòüçæù¾•s¶MÀÿŒÿvÂÝ_ûÂÙ%¯O6âŸý*zLLàŸ“Ô“x«%'ñVC<‡íø6ãÞl§¦ðfC> -Õ“Ô”Rx«©’Â[Mé,6UNRSJá­¦J o5¥³ØT9IM)…·š*)¼Õ”ÎbSå$R¦ðfS5…·G7ÏBSÿJžï˜ÎŽçüy¾ÿ(Ï÷?3;ÿý—yö·æâ¿ÿæ(ý9?ÿö(ýµ­?bûìY/áÿ¿¶ÿÃS\4ý·—NÖ¿-tšíþÇi¶ß7–¾qgâh©È‘F‡»ó]ÿwqˆ¨­Òr¹Œ¤¹{Öê=²Ò/Ž™^ß÷¸ÍNwröµë˜ìÂ,hggDGØÞ#Ûˆón?¡õžgXÃVšnVi=wÃ4ú½OzÄæeµŽÜ©ýΰ"¦>ÒyNÖit&Ë3̈ȘøàÀz&­2ñ ¶uƒwﻃÆw‚ØmV=ßíÖ_v>àm´<±ÕßÙ°WžðŒ3)žAgLœäÒ3pùÅðy3¸í [Q¿3‡ñçôvz']¾³0…!«ñÌ_Ehränf×wk¾‘a'ŽÞèpŽwbœqλôâñÎFv <'k•Í›T|†ÕsÅ9ô8ÃìâE“Æ»ÞG§÷L×ç–â”3ùûÊ£òÙ\t•{AaìýðbJ’3\”®½8,´;³Lî\ñÒ÷ݼ»È\@˜"ø%èýé碾yF¦ÉØ—_ͽә‹ihΉ㢠Åuæ.õœùö‘½>žÛc%ιï ë?CXŠýp‘ÏŽÂplˆA»½¹¨\½œÓ²–E°ÊG¢Ú{€{†½WÏ Ë™yLç¢~s†ÃÅÚ§À)ïŒÜ¢¯xöí³sÓëCd;#aoŒ×¥NpÝûã ^/†Äx}H”g¤¢Žñ‰óC\™bŸ³×Ö3ÒÀÇx}˜õñ=²‡Ó¾ú¦à—k毋jþ;ˆú¯‹þ¥çÖ°x]4Ÿ‘I<ÆëâîâÅÜ碃ɵMc¼.¤@?w&ñì]7ìÔJsÑ…í¥ìÝ9OD†õ®‹Û¡3Êe>»‘ÅsÞ âÜç Oþ;ä·ÕìmÒÖÿÃ5ÊæŽ>ÃuQn9ãIÚ>îV/JŽ=\ %g4£uÑ-ø=òìÑÍlÚ>£ÏÇhª“O6s=Z×Dùwj{´.¦rz<9Z©‹œ+¦á8Ô3j,îѪ†Ÿ0ʼnI}“ÇHÜä|F5Ì #1?w”vÚ£õ‚¾¾ òîѪYéÉ—;oòö®É»G+Ù]“wV:²œ(Xõı«òîÑJÅŠd´‡PËvÖ.A¸GtÎêQÎmVd¢ßEy÷`eÃ/ö_9X™‘zå—ÃÑ]“7·ºðaØ5yã7÷™ïo—ä݃•Q£Q“7sý¶ç‘¹W×¹èà9"ÐpVNA»*ï­ÔÏFäáiûU@5ÚUy÷h¥óÆ{$WWM€»*ïÀÝãnWåÝÉþ©,íª¼{´Ž…§ˆàäu–‰>ªòæhí˜w]Þ=ZÃ>›GÆ^]]ŒvYÞ=Z9yŒ6÷êº-êy¥+W×›9ŸßUðˆ5 »$ï^]' û$ï®$ø]’w¯®Lä»Kò.¸Tîþ%yá*Gª]”wg#æR5zÏÕU.Z»(of#Æbô3W×ðÙî:».oŒWåpß…yŸXé ¾ óîÕ•"Í.Ì»W×°Ïd;w®®7—‚]›7¾ ­%#Ê“äê «ê.ÍŸ÷H=wœG.®7ü2v]Þ\[1M½G°¶RˆÝ…y'ÎI;KæÝ£•ö¨]˜wVªg´"ì1žÍÌ++]¢weÞ“ÛÞpmò:óR8°r¬2 ÅØ–³xWtâÞ…y÷`åÄ:Â^Í*QŽäÊê +ë»,ç©r”™l—å]³ìD¢,oV Q»0ï¬1h÷‰••á)».ï…Sr<‡¨¼Çê„ܮ˻Ç*#LGÈÌ{¬R'Ùuys¬bo€ JÊC(TàÉ´‚ÀtLýÉù3éoH»#ýÉOVô“6ÐßЮ”ônÏ©W‘þä1/üÒψƒy… Ñþ)¥ø7˜(Mø7`Šý j¤¿A+èo°þé¯\ô7˜£›ônoÉ¢¤¿A8Ñß`ÊAÑ߸¤$‚þ ¸Šþ«Uˆþs²‹þòHþÊC¢/áoHÑ ü z" þ†tÂßêAøBuÀ_9ø,>Bø+¾cÂß é_ðç'ü –ü©¦›àoÐaTð7X–Hð7`ÅûEGLÈ!û n)Å~Š ü «l ¿¡]:é!„¿Á5\ð'Òß þpô7`1ü M+„?Ÿ~CöSl‹ØÏLöšöÈ~ƒÙGÄ~ƒ ®Ä~CÓÙ/œMsæ û 9Mý·%ö’É~Œc ú•ßý†\€~C³2Ño0ÞQè7XëEì7~‘ÿ%ôt„úyÀý8¡Ÿû=Ù¯\ì7˜#DðWŽþbÒÂsþxƒb?ÆIý4Ï ý|F’ŸâºD~ƒë³ÈONèÇÙHä§IWä7,ëün"ò4jŠü5O‘_¼‡TªH~ƒ™^E~z3"? 0¡Ÿœä7X%‚ä7ÑDàáv‰¡¿Áâk¿ÁØ?¿o‚Ÿ¢ä~Lƒ#î̶+îÓûüÈľqƒò°š2Ÿ¸OÝYܧA îóW#÷)RÜç/Bî—tApß`}Jrß Õ[Ü7. —É}ƒùvÄ}ÞÚ¾A·aß9اá&쌮ö)žPØwJ1!ö :å û´köi“ ìósû·rÂ>EEû†ìÀ>Íz¾q!ªŽØÇ¹\Ô§XgQß +›¨OU¿ÁPpß  Tà7„<?­?Ec‹üD"òÈz)òÓJ)òS4ÈOK”ÐO•¥…~Ã\ôS´%ÑO‡B?E@&ú ©_D?mlÅ~ƒ6e±_9çá’ K¯àÏSáK˜ØÏ@ö;u)²ŸÂõÄ~Cnd?Å‚ŠýÜ#ø‹˜‘<ì7¨…ýÆ/ºß`Í)²ßùè™À~'¥#±ŸBZÄ~'%4±Ÿ°æRg“÷VV¨¼Çp0óÞû pòîɇHnŸ )íöI;…pOÕ0„{–`ˆ{Ö¹ˆ{–ˆ{*ë)ÜSýñžÊŠ÷”ÏM¼g=¼ˆ>€0L’¿É{i;„|¥Ý@>™…|1ŒB>Y<„|2w ùd8'ñu–ˆñ¹a_—{‰/d¦çãõÙ£U¿I1‚Ÿ|%øÉÛЂqžÈgÝÈ×™¤KÈ×àu"½oq¯/½å‹D|QâèøÍ/ÿ@îkKÞ¤’ûD›¾†=€€ÏŠ%/’1äç–Ú‡2\â=V±´ÖÇfI{~›¤½Æzh¤=•íÅ•ó7 {ªÓ)ØkÜ; öTŽI°§*I‚½Æ„v‚=}²^“S7YOõQÅz4 {Mj>aOu±ŠÐG][JŸz,aOU¹{±§’ú˜ÏF´×Ã7¼Òž^aOå¡öd4í¹Çöô©I{~wÄ=âžJ® ÷TN¸§:§Â½ÆÂ½&`âžû"q¯É:BÜSñgáž*ä ÷Ê&ï59ß“÷T™¼çg ï±`pE¼D{¬F'ØSy\ÑžJ‹öT—U´çÛ%í¹’öâ ®Òç^DÚk\`E{n>¢½ÆÄMÂ=½tò^C’!á^£I¼W€÷(D ÷twÂ=9]ˆ÷TtO¼§mâ=­{â½ò+ðkž ÷4t…{Z„{*4'Üóʼn{Qâ=ùj÷ã|› _£ó‹€Ï¯bŸ_'OßMÀ§‹">-#VúX5ÆJŸ¶iD¾ÆDŠ¢>MÌ¢¾Æ€kQŸVTQ_³W)¨Ï¯˜Ôç/EêãD,è³eÐ'§AŸ¦|BŸfA_cQ_3A5®¨ä%RŸ ù‰úb}©Ï©OZÔ§:Õ¢¾Æ´#¢¾f'RPŸ_ ©¯õE2%J{XV9K‘úÊP_c ©O…+…})„}&]aŸ¦ aŸjd û<™ûü Ä>e˜öyäûʵ.¬"+p_“×(¹¯±T¸OS«¸/ªŠç4DîÓmÉOOîã¿Pb_ÔûJ#À>y‹ ûü"ˆ}*´)îk¿8|ªÌ½¸ÏÊÜ'·3qŸ–hk~¤qŸÜâ,ú1ÁÏïœà§m(ÁÏŠà×Ä®¿F»4?Ô›´äGûÁo¤Î6êmõâƒzd¡žb¹ÄzÚ[“õºœÉz'ÓNŠõ”ºB¬§f«uhŸüqÚÇ ‡ö9¡}Œ´)¡}ôdthßMQ…öÁTBû°{udß ÒÇÈ>éÅŠìc¢5GöY‘CdŸRN(²ÏJ"ûÞ—“x È>íT‰z‹ÔIÒ³J¯È>0*²{W‘ÞÒS`ßEûIoIQ`Ÿº1IoÉmW}ÑÞ7°‹–Hï9…IÒ{˜}…¤÷°Î€û–ùözA…iuPdŸ>ïF½‚¯Î‡B½ç`˜YO¡“D½Gjºû¸mê=Šð%ê=šjˆz|xÙ73]•û0Ý ôžŽ ¤½§³›+®yòz-´½çà…Ày1“óžC*8ïa<—@ï鈠éE\xšVˆzSÖ õžCÁw ëá*¬ŽÖ'±Za}ú¸ ëcz-¡Þí¾Ãú´Ð)®O ¢¸>¹*õ"¤u~¼:—øàwãúâÚ§N½:¬O¦°>ÆT;¬&‡õ¿~Ãúèxî°>&£úôLd=½cGõñý‰õî¨>†{:ªæEõ±ï;ªVbEõ1§™Xo1³y²žÂ`Åzë?ĽE#­Xo94¬·ä©HÖ[VæÀzwl½S™ë- ‰d=MÍb½¥B²ž¢ÛˆzÑLÆtõbˆŽÀ·èK-Ö[ŠKbP×õ vYõ1‘«XoRÝÖÇìÔëST©ÂúDd=Ñ;¬O µÂú³Ç¸¾ÆGÅõI“T\ŸXÊ}ºgöAœU\#w×ç½D½ËlŸ>IߌëãfK¨wGÆ­Ôá×ÇL ŽëãŠèÀ¾(FÿqítX®û® ŸƒÓØÇÜ ì£G‡Pï–,MÔ»±ksdŸ\nIz·”V’ÞbY8‘Þ-?B’ž#Ï@z‹+žPï–{êF½{м£Ð¾%'R ÞͬB½‹B†Pï¢áC¡}v÷Ì…õâæK wýÙ§@л4Ù§§&èÝHzë”;²9ßzaâ ìô’ó.)’‰y×óqì qo|/²ÏækqP§jRÞäÍþ‰,Ù¢¿°´ß_ÇNZMMÄÑŸìärì¼È1rì¤NnúSèOF¢?e**E8%¿$þëØ ÿâFü»¤x‘ÿ´ËÿÈr(Jä”n¤vl<¨’o¦Ð/H$ Þ‚P;F`AB¬Tá’×" ºD€òfzÙ2¼Mè¼1B@a,PAšB@“Úñ‰?7Òßøùzv:'‡°Ozˆ’9™»bI€Šé1ò¡D€ 12¨ÇÈ¢HFÀÉ'B@u?!àÄraDüó'¹Kû à$H™`À8¤ä‘õÉÅ€ò¥2¸¡@ ãF¢~Aàø)÷•\(„@e>*%ˆ .IÎî¢/ªì.ôÃerã…)•ÝEÙHÄ€Vón˜$îš,œÝ…–ewY¨RT²»PZ_cv–wvÚtÝE­ p<‡xÓÖ¥ô.Ên¥ô.2/uu¦w¹¦w‘ÝÂé]¨Â2½K‘ÞÅÜÅô.Òî•ÞE©¡”ÞE}‹¸,ç‰?+䎰p Ý÷Åš?ÄÜЗô.´üˆo‘*9P>q vâÌï"ŸDq ½æÅò R~ŠþÎïÂoUò»0µ‡@nÖA&AP»~ öïA¥1 rw$d©“ '&çwa-#“à;Zæ/$x×ø>uåB‚ð"*ŽH ¨­@Pj#AÐÙh‚0™-l’­—‘…­äÀ0Lä¾K()G¨¼"â@Í4!Q;È(mNÈtaæ@–›.,‹æÀ‡YXÈ2ˆadê‚Â=Äô›5>‰zÂ@ZúŒjFÈl4¢@é"¢@õFR Ç‹0³¸1P¹;˜ÞE / T^ b @é]è¸l ü)øÝô7úˆ(i9H·ˆ]é]œ7†¨¡* dhž³»Æ•ÞE‰xH·¤våw‘ƒ«(IÐL(Žçü.²¥0¿‹¦ò»Î’5ˆçì.”X‰€Næ"”H-TŒ³»èJdÀ%ÓšCN(©[¨ŽFTa+'wQú$!à ‹)¹‹f‘YÄ xˆ ‘ÜEq®äÀKÁ§JîBp$ª"Ÿ1pû±”ÔØ;Éö'êµk@Ü%ù*Ô׿ÿ;ŸÅsþµÔØï‹ëñâ|q jsZXq êk×rªi¶}Ämñ˜Ûò‘ÒV”§5Ͷ”¶p¬´¥#ÿÙ©±çÎ ?;5ö/‰­3óõPÚßß9áO¤Æþµ/d²ùþIàû³_EÉrËõ,µÅ¼×jʉ¯ÕÏQC>‡í8í5ªy¯Ù’ÏbSõ,µ¥¼×j«$¾V[:Km•³Ô–_«­’ùZmé,µUÎR[Ê|­¶Jêkµ¥³ÔV9Ëc•©¯ÙVÍ}í1γØÖ¿’!;ê<ãù ÙýeÈþ¥#þv†ìß;íg†ì?hîçPùyÚÏ ÙtÙŸ#ëgÂ埲ÿ™Iúï¿L·¿5%ÿý7ëÏiú·ë¯mýé Ùs[Ÿ®ßN‘ý¾ÿËÿù(?õåÉþ$³þo}½„öùç?“1û=ý3f—ƒÿ÷ø³w­¾'&¼²ÆÚô±f†aì.9´wÁ¡3’ž…a1Ö÷Îsß_¿IvE¡‡¨˜´9aÙ\‘ôŒV†¬í8›(©ð̬¯´c‰Þ˰ŒÅŒ®ÚL»v·Ë;Î*~CÅkÛg×>5…vX]\™>bßWŠ](æýmZ~w‘;ìæÝ\¹Í36Wû¤Úž?óÊ–·’ñîp®LÿF¿Ä9Ã0vZ¸ö9ù¶¢Hèo‹.š,9ÿÃíŒe¶ïsà™ÅããѤ{ÛåGÛó¹ç÷ή‘îQ=¯þ„F?ãć¹"‰ÕÌ‹ï±Û¿luKƬÉýþ’f* -³ÓÝÙȹíÎW·kg¯–¿Ú3¯0‹]ùù£¹±¨œ,Âü±,MlÛ‚òŒüÕ6m¨Þ€!©ÐÎüÄG ¨úüfíB;ûG+ïøý"ýÓ½ÂÇáºjφ†söæ`>a»ê7_“£×oó„eìþ9wLVù O˜Æ>ïâ™ÛÌ]¾Ö3,ÜÍçó‚íýy‘¤=Ÿ; ÎȧÈ÷þlç§z;áØˆñ¸Í¡ï>Ë/®£°»Õ÷È›•®_V¯jãOŽW «Ø>bÖ{dC¶;׻hÕq®#Œ ½¼ˆ+2KwÞà¶ÿ½Gn XtöwÆÙùdýŠ_xî»ê ÅkÍ}jÃQ47Ç+úÉ}àÚY+gi&ŠæÞù&6,]»fî,}ö ŸÔ«Þï.š{•>{EÑÜÙêKßEs¯z¡ÿ‡½wÉÕI²õ¦’ͪÆMþ :$ Ç ©£ TCó‡hnëaÜ'"2"UpjEl?ü¤Ó_Ÿ›Ù²{¯­¥ivÎÜ;¯ü.¥Ñ[™§®3÷®MÁh­öÐkçÌ]9~·-ï ퟽¸FØT^Gcßkòà¹4úΙûä5{Ouí¤¹£Ì0WdÍEÁî;gî,óÂIs»gõk§ÌÝí ³ÄI2rq…wËÕ.®¼s¤ÌÝ‹+s‰];eîUß)òoíŵÁ;þÚ9s£E>|EÎÜ\\õ«8©¸s)ݳsð~k§ÌÅú»w®-»Óóq޼æâÚÊjn.­8¾vÊܧ¶ÞΙ;óVû<í-Á”°OF®1w–æŠl˜bä5é¥6F$\!X² g´×èkg̽²#m;ÁQṸb™¼vÆÜh å\ö¿W†\;®þÎ=N6èGhÞ”]ãÆÚª¯Éˆ‡ÂkgÌ]¹˾sûÈ[åXÝsŸÜ¹å%'–VŠ\‘1wDÛ^;aî¾®×ÜåãaüƵæFI&ÿ’9’é¹L];aîUÜ®H˜»—Vzz];aî*½ùe"aî¬<š»vÂÜ»èJ]‘0·ÕÖÚùrWýQè´ï±JÃÀµóå®úVWÃÊ:1_ït¹ÑX´^^;]n\îÑûÍ#_îÈ ç}xít¹ósïíþQsw Ö3¶®H—»+¬×Ζ{å{²Þçʱ:4ñN—{åãíSÁ+N"©ƒœ³ßN—{'ì}Èugº†·ŽŽ.÷.ïÙr÷Xenök§ËÆ¢2Üš{¬RVïÚér£µ˜zâÚérG–Ì,X9VãÔ2«Y3Ç*e3¯{«4kjÙŽûpÄŽ{¬ÒÊ|íl¹W6Möµð˜[h¬{ícòÝX q… ÕÆÑ²5¢(zmSÙžûîܳùŠ^V1Ûxo¹½Â7W&àÍp* Ï·ÍÚ”‘wŽ$-p`d£IZà@麋w¦˜6€ ¬x"ÁÅ“ ïž$¸/i<#¤Ç˜I¡+&Ahš©6edß1’\ÅÐs3Þ84R‚¤` ÑK(–5>¬'1°ìi[NüLx,˜‡ãÄ@¾%(pHv¼!pÂwA ×^C ™Ì€+ÌŒÇfÀ÷š‹¨–8únçA'oBà[‚ VBà<(ÿk¼ B|kži7#nÕ¿lA ††@ªÇçÁQNœ=Ìddd”” Є@ÚÎ ô5R•†¸Ÿ% o=P¡3rù5êì8ú]{o¤ç­!0Ç!°<3 pßèHô½OA pëq$à±Ý2r+eÔñ‘šBÀ@…|o! ãNŒ€Ìe‘ Aä?nÅçý3òߟп"v亀‘RÀÎùZØ9; »k€éÌ€ZïÀNá`ïN'vªN »LéDÀÎÙXØéù,ìTvÍ=DÀ>~"`§§°ëX‚Øu,A ìBhR`‡w¤ °ü8ŒŽ€ÀÎSOB`‡R¹°?‹–¸`ÀÎì2bÀ®m2àÐæ اÌy`ÀÎs 1`Lòi4 v¦NjömD§ý„@Í>¢ÀÎøzQ`GP› °ë¸Ÿ8lÏúišµC;cB`§¤4!°ÃÅZ 8¨Ž"Ô+5„€CÛk"`§’p;° ~‰€I¯…€Ž0BÀ.ƒ°3îMØ…¤DÀÁ˜?! „É€^ìb@us2`§Ïº°ßº °Ë´DìôZvÈä‹cÊÌí*0fÕQ€Þªß;Õ”…€½ 怀]F!"`g ˆÐ=‰è·"ö?¬©ú»ößÀNõz`§N“ÐýžØÞ.ì<­!ÿuîÂÄÚ\ˆÿ"ä4wä?%ÿEà¬à?M²â¿.k ù¯CZø×¨°$þk2‡’ÿ:í’ÿb…lYþk2»‚ÿ:ÝIÅ¡‘⿎¢ðOñ_Ó’ÿvoÞü×E¹ä¿Æ³CñŸV}ñ_g8PÛ> Z`“MšØO™ó€Ê>Cì:®!v€ãj€ !þkPLþubÿšÌõÄ¿FQNá_£gé¯=Èh!úk´2‰þ# DM3é¯Q0Kô×DüÄ¿&¢&þ5†É ÿšæ(â_ƒ²MÒ_c¼è¯Q®Tô×ô#úkšáIFá_£M‰ø·Ÿ.yô§,~¤¿·œeÛœ–‰¢mäËÃäŠ|4•Ú”g0F>æ 0òQmÎÈÇ3 #ÏeÄ|6Kù: ûÄ6Â>†G ûN|%aSÂû(Hì;itöI/RØG¡@QŸÒ[ût‚/ìÓ^—Ü'Åmq_`jš*É}ÊÐ%îk<3÷5ímÉ}Êo(îS4q{°°¯TœØ×„Ä>å·KìSJ5ZDI~’»ú:p!úZ3‰~'Sÿ†~vÁ½»FFî Êdá®ØÂÇsŽ4e ÷Œ„Â=$÷¨™asì÷z§¸';€p' â=m)Å{L=%Þc†Â{zñ=Á|ôm)ÀGÿ@ŸMv>™D|vÀð)¯¾J¾Æý¿€¯1¸QÀ'˜€<&>zÛˆødá$ñŒÑñ9VÄgs‰OmCâ;éxfâ“;›ˆOΩ">xø8øNv.Ÿœ}|\â |ŠX#ð);†Ï‘x>ebð)û‘€Ï/ àSÖŸ¤þ |Ê#.à;¹ðIl_À§„=">eñ¹þùNáÝ=  >·ˆï´Ï(ˆOy€D|š^E|ʨaOìÕE|~Ÿˆø”_AÈw u‰|§ˆ^Ÿrj%òÂVy|ê€AŸzQy|êµ€|§XWŸì(É|§²äñIþç rø´½ŸÚuËáÓ0IO¶°=>]3=>Eòø”™D.Ÿ}éóIIHA_Ô¼>!J5aŸO‡|>…^tù´.ŸÌYb—OYîàñi³"=>éùlOéñ)¦’ǧàGŸ6îÑãS´&OÙ¸äñ9e”£Ç§Ž™åñ©Ö’Çgœ%Òã“gLöø¼ì O× —O¬Èåó‚ ±OéPìòIÑaû|Ê@%ŸO™µäóÉ®\>uÄMsŸiî“¡<>ån%OÛãÓÌIO±ÀOPBðSò{|ÊÐ)O™¬äò‰Àx|ê侓–19|2ߪ°ïDÞnû{Ê%Où·Éß“­)wO…JÉÝ“Áv÷D ˆ˜ï”Ë›¼=»ÂûèíÉܪb¾“GÈöö4­úäLæ;Û7à¯x:“ùüùÁ|áÄŒÐ=0_¸Ôf·"óŒÑóÉ¡ßîž”côа·'Í`rö¤3™Ïµrödþ5{{ÊÊ)oOÅKÊÛS6wy{ꌉÐWJú™§åíißSx{Ò¯ÉÞžÜØÛS‹‹¼=…Pòö䱤½=å.+oOM³òöäJkoOMQòöä ioOM‡òöœŒê–·§Säî9.Ú éîéèBº{öI?Rº{?ógÿJº{ž‚<º{ʸ,wOZìî9@ÅßS ¥§MÈîžr 'õ:Ø!õpâú rÚÅÝ3ÐÇÛ|mÓßr YcfADŒš9o„¬Œ¼=OÆÐ xGä±QËŒ>9Se%5 nÖeú£Ï¢PÐ"2DAžÄÜd”ÛPP¾BAò¾QÖ¶ý)PM((„PPÏ,\½I‰‚Œ ŠpåòI·w¹|Ê—T¶?òáò)š”Ëgƒg”]>)$Ï“6 y|š8éñ)Ü•Ç'e-M‚ Ä’Ç'ÂQŠÃçõÓáS^–røä‚`‡O±«>Õ÷íð)Où|¶qÅÏNŸ§Ì…rúTh œ>}‰¼>e.¤×§ïM¯OÿŠ^Ÿtijק¨]^Ÿrú•×'㔊Û'ñVnŸMWÜ>a³£Û' ìöI½Ûþäk-·O¹UÒíSƒÓnŸHæ"·O:fÙí±ÛÅëÚ–Åë—ÈéÓ”túä½>/Z/åôÉÄvú”U[NŸŠ•Ó§ìŽôùd;}Ndšvn»íô)£,>} ½>µ{‡×§Bíèõ)ãA°#5“>u¸(§OÙZÈ]ô#§O[úäôÉà@``7<Êç“ñvúÔóÑéSÖLú| eåóùqøì¶éÑáÓL(‡OžÍ;M[ò÷¤‡ Ü=En ÀÎÒö÷Œ'¯¡Ã§N¨I€)¶ìðÉ|”vøÔQŸT™·Ã§î.‡ORåðÉdhvø¤¥RþžTv…™Øß“Ú ò÷ä1¶ü=Õžô÷”–ý=;ukèï©smù{j_)Ïp;HV¢Ã§}BôÇDâ…i–Ã'MNrøäQŒ>Õ=åð)c°>éS`‡Ovù{ }íïÙá—O‚<>Ùmäñ© ,y|êãÊã“§söøÔv_ŸzI»|rpØåmòøÄÞÌŸ ¡”ÃçMgD9|ÊwSŸ°¿§ H€]Vh ‡¿>å[L‡Of•ÆÇ½ŸŽ¹£Ã§Îäð)s<>9“Ûã“S£>‡üQéðIƒ…PQ vø”‰^Ÿ2‰Êá“~Íò÷ˆ;c¯ìïÉ€Ûý+JÏ{Iû{vL À⎠d,Ð~®ò÷ì vå ¢à5Àp.ÏN"‡O Û»,ÓÀÎè`sÙá“Á}à¿.®ü=5È]Gò÷ÔA‘ü=©o ‡ORÊá“+â¿®8e9|Ên*‡O g9|2÷‰>)ëmO ÙãƒWV?J-íû¥ó¯hê !‘*pŒ‚ªˆý»¿òE¼ä_Ò¾c§³ê \bÁj–Y=Ö%¬^;kÐçaUâºXæº\Rê á˜ùyo”š²¨TÄ‚ÿlí{Å®òþ“"ÚU.{Æ‚tK$x^ºà—ÿÝ×>Òÿý£KSTö’¨ì¯ÝäžmëAU à.Ú+öîŸkTå³U‘å³Y/a5¾‚µX:›ÕTélÔã‹PQ½F5I8[5álÖ¤‹XS¹F5I6[5ÙlÖ¤‹XS¹F5I4[5ÑlÖ¤‹XS¹Æc—’Ù¬©JfkÈó"Ôô¯ÈjG6¤uÌÿ’Õþg²Úb¾þÇ/sïoLÏÿøÍÁùsÊþÍÁùKMYRûŽ]Õ»ºþÿ)©ýÎPERû½ü·$µßâ÷&ï|øÜ÷¿-ZRûúç’Ú÷|×þPGDÂÕ:›ÑCêžp½•äpÔû–Ü)8 j|ÏðEçîÝá´”G¼Tϵ=ávIVóRÓJ‡- î yÄ„é{F.…”ÜÚ{†cÁLIÅ™÷Ùî_[tqoÚî—õS1vöûÆ×ÙR‘Þ·d‡6ƒ;f¯ŽköQã»!8(Ö5/lqDÊe¿%¹z?´iÜW8(V-ÉûŠÃ1,Ù×½3ÂÛ鎄™©; ƒÔiU·<"†î+Çž¿YüŽš[NõÜÇ“Já¬æŽs³™?ÚðöŽž÷Qÿ¶ÕM÷ßqò|›Á[ò@Êž‹wäMpØÔî÷ƒÇÏ ”wŒ¤qYÍ·d¥@Qî;Pú®7Ï4L»š#gc«¶ñ!Â=Û8…;²Ïœ+5>ó’ÈW¸åáÔ;™#kÜ¡à7Gžû_YOŠ’²ÖÑS‘.E÷N,•϶P°bË\š*RýlqDÿèÝõ¥)Ö°;R.ma }‚‚¨{§vG‚Ã-ŒÁ,Ow¤J?î"§qGô âtϹé¡|¨Ð¦Ý.Åw¨?î‘Ê`¨;tûç’8{>wš3*ÅÛºžúæO×kâ`" ö ë/|ÌOÅñoÅú=¿ç*÷òÊ ð|¼u„-µj®°Aõ³ÜzZå;­­‘Rºù +Ú¡‘ý]Þ5¾AsO³Âb7×çi®;Gª¯‰²§¼æ %šÔÖ¯¢7@u}Ÿ±¬°®Y²L½<_Hݵo­ðGjõÂUòº>%ïuÖÆÚÎ(W}ÞpU<>Qg×dƒn—š’#f…OFŽSŒÜ¾1 oåãÅñا±Âð•šÃ°®ðš;×·dAÈOÜ’üËóµ8ÆŸõª'¼v^ÝÚVĨó€Ta±©y¯W·¸ú¯8«à@ͱóê®zIÊ´îpeÉh©Y0 TÜ9NéºvZÝOÏ‹£ªëS°°¦êµ#µî¬Õ>XRuE$ÖgmàX÷ú”œXRÕx;±î]&ë¶VŸ†@,Eé‰uOHbgÅ+ªou5ST‡c«vØÈ«ûŒ2Ÿ¯W·.kçÕŸ›?¹¢ª3U{EfÝúx;¯îg€E^ÝóÓ‡w^Ý«>Þ\QuÍÄŠª޼ºO«ƒeçÕ-d¹"­îw î´ºŸ™/ÒêæŠŠc¢µÓê®zóH«{õú«V÷ù›eÇ×N«;j«ï¼ºÏçW½k°¢æqp°âGƒË*޵VäÕýÖW÷úÜüƲÊfßiu¯:^"­îÕ>oó±—ëuo GWrgêþ¶ãzÓH§ûy½È¦Ûë/bgüùÅÎ¥[.ˆmq}¤Ì¤[qaÕ÷¬ß3䮿瞣v‰p–ÿx~±·°+²çÖÆßyîó¹4½1ŸñÌ[Æ&¸¾T¤ý´d$ü>öNš[«|Æß«ìýÊœ¹~ˆH™Û>Äî÷S†áº‚n±ì:˜ŸþÔ„3ë‹DªÜš d%ÍÔ⿾Ùs_Ÿ>Âà ?UìyëÃã#nyþ¬2¶pîNÿ‚s‹ÒÂ9%¤Î)M¥pnõÉàÜb8¨pgóÜ¢¯xnQ?™@ÙÎg^ [ô–"Ð)oª€n‰$ tÊo* SviÝŠƒõü€nÑ›T@·èˆ, [4 è]Ðt‹3ºE?_Ý¢£˜€Nšà:ÿŠ@·èK [ôvÐ1u*ynåîž4·è..š[‰Í•k@s‹î:¢¹r hnÑ=N4·hgÎ-Ì…sK¼Nœ[´QŠçÍuâ¹E‹¸x.îu¡$?óæ9? n‰út¥Ý¢ €NéltåÝÒQ™¿ Ð-Kèü8:¥=Ðù^:å Ñ-¡Etå ¿‘Nù…t~S"ßHç%Ò-Úĉtþ¾Dº‹³ˆNÕ éJ Î?Ñé-Et‹A"BºE³ÎÕ€è\ [ •Ðé+èjI]¹€NíI ÓtòE$ÐùÖ:%SÐ-Ɖèʯ@tåÖ :%}Ñ•z€tµ$‘nÑRHWžH皉têÆB:ÿŠLçæ"Ó¹1Zÿ¼&™®ü$™nQð]LWžLWK’é”-[LW*Ó•0]¹˜ÎmC¦óé¢äù@]ù ÎÏCª+% ºR3°®Ô®+÷×¹€ëüäºEr]¹7ÀÎ?"ØùN;¥›ع‚Ý‚ú½¸N³‹¸®Ü \çqF°ó'Ø•ÇØ•kvzäºr+pŸ/±ÎWë|#`~B¬+WëÜÀÄ:ÿTW.Õ•j@u⤺r °ÎŸ›X·´I'Öùæ :êÏIu‹G‘‚:ÿLW~¦Sƒéü§ÛDç·&Ñ•gÒ• ])I¤[<'Òéa6Ò¹•Àt~0_LçÉ Pç·Ôùc€êüT ºE7:R]¹Ë=?&Õ-G'Ô•N¨ókêüÚ€:ÿP§]©Îó¨ÎO ª+u$Öù56ÖyQÖ•ÇJ¬+•XWjH¬sëëܺÀ:×®ó]Àuj,`ŸXç»>O•ë°®$Ö•‡H¬ó-’êÊC%Õ•*ëü‹¤ºò‹¤ºÅÓ¦¿ u-°{Rûûãu‚ÝÏãu€ƒ4vó 3ÁÎbß»wF$%Ømö¡ÎBò»<“;N€Ý¹‹¥nÚ¡ì”3…\·5÷a`K®³>¹n+ê¸nÿ*[\÷–\©^C®sX¹n×Óóq’ëö5€¸½øìŠq«ÄºýR¹iÖ9‰XgñpbÊëœ9‡X·3$i¹Û\WZ hçˆ/¢]y> ÝŽÌÕP§<4$;»£’ìvX8ÉΉ HvÈC¬«•$Ö9Í ±Î‰ˆu;;B‡Qî̈&ÛÏëœccÝþÉ“d•XW¾[b5ëv¿‚90±®–$Öíj@Ü‘M2žëJûë F¬Û¿Êà `S뜲‡X·³Œj¨Û¿zqëJ—ÖÕ»'ÖízžŠu¥ý€ue%Ö9'±Î=?©n§À¼ˆ<£Öù;ë<êˆuŠ@$Ö¹‰uVP$Ö¹ŸëÜÆäºýefµÔíñ²òìÜ6»Ý~'lwOŽUMÒ»=VÓε¹®<ÀÎÀ®$Ø9IÁÎ`çnB°+°«õ$ØíÇéÕVç®D°Û%@½»ZO‚]ù»RÀÎM®Ûiò-ÀuåV­#É‘(˜\çή«¿H®Û%®óÒA®sü&¹n7ßYmu{&žù«äºý¼'¬w £•p]éà:Ç’ëÜuå%€u¥ûëÊKë¼xëJ{ëÊWH¬«·Z^XQÍÊ…Õ(øpaÅdB¬ÛÏwU{]i `W%bÝ.iyMÇÊÊåŽ\×ì?êê“Ë*» Î¿„:Ïl„ºú 목3©®tâĺò1ueL%Ö•;ëêÖU}:p]@»ý«Übì¼Êìʷؕؕž °+½`Wú:È®Ìm@»ò„@»òê@»2ÒÀv¥MÁvåÛ$Ü•©tWštçÍ é®ŒÐÝ~õQ v¥ Awe¹æ‘k;è®Ì£÷Îó¨xWzuâ]P‰w安wåïö¸ó'0Ú1ñ0ð® ÁÄ»23Þ7FdâàÊõÔ÷|ñ®´zâ]Á‰w¥‰ïJçJ¼+ ‘x§Í4èn?…îö~â)t·‡jv´ »Z㦻²'ÝíÖ^Yå¦;ï¼AwµŽg|[;鮌뤻ò “Þ•wO¼ó{ã]é$‰w;á×Ì*7Þ•A–xWºgò7[à»2zàœìŽ”€W¾"ü™Õ‘þ‰šµ¡.“(U¨£uG¾—_0Ó´k‰é¨²e¦ƒ\¼‘®‘Iˆt #¤cv`!S”éúNcàMt @1Ò1\×HÇY#[é| ‘N'¤£Ì³‘ŽjF:æý2Óõ_˜Ž!øf:¾§ŽI¾Œt›j"]—ß"‘nÈHG9#³éèo¤ó5D:*™é| ™nÈ«“LǼWfº.MbCéŒuCNĺ.@#Öu±NõëÔ1ë˜ØXçŸë| ±®ÓÙVX'õ°ŽQ]ƺNDÖQêÝX§› ëôNÂ:uIa¾§°Î%Ä:umaµgŒuþ±Î¿"Ö©{ ëüÌÀ:æC2Ö©÷“ë¨Mh®£6޹®s ×ñ‹›ë8 v¤G®ë¢8ruðÍu]4H®cÈ ¹® 3Éuý‡ÁN™œu]ÀH¬cß×ñ…uº±ŽCÜX§×Ö±Au]f?bg%cÞ[X#SPç{êüJ„:µž ®”ê8kšêº¬_¤:ÕœTLJÔ5xØ êd¨kB/BšJP§†ÔéNdº.{™Ž¹æÍtLEh¦ë2|‘éts1n.¨ãÍÅt¾„L×m˜ÃÂêŠÉtþ™Ž³”˜N=XLçé|'2Æ¥˜N¯)¦SçÓõ¦ºÝ\°Ÿ‘é\™Î×ëØ8¢:ÿˆT§~$ªS?Õé=Euª˜P§aG¨ÓK êT ¡N_AP§‡ÔuÁ¡N¯ ¨S« ê~l¨ó¯u®™PçG&ÔùW„ºþµÖ•KÄtªFL×a:g1]ÿ…éúO¦Ó‹éú/LÑf#: N,¤ë2êé|o ˜H§FO¤Ó“éT‘N·%Òu›ðé4ûéø2Itn|æïqZDç‚MtúR$:½%‰N_ŽDW žïC“èô!‰tTˆÒi"&Ò¹`bÏâ‡Y6‘Žz¼B:êF é\%NuéÚ$Ÿéô ‰tÌ%¤Ó«éºMxOm^"Æ!‘N¯F¤Ó'$Òù)€tý'Òù.@:¿ Žõ*ÕÆ¸Ô›.Á®>l›šˆãf&p6ÆA†Ç'ÿ@aÜýa¸{‰p²áxe„“‰ çx5YåDud8Y{l–#:ˆád2ÃÑò$„£gl±Ê)4NV9…½]>>l?Ìr²Üá\Î×áG†c†21eÞÍpÏCçI0œÌ\b8Š4›á\B† šJª“Yî¡ wRGB wr¸»œ~†;÷ZNùÚ…p.!ÂEîðV.‰[ç›á”à>NùÚ…pJRN„‹_Lä2SžWî„sCáNÊr áÊ5@8?î¤t·Î÷"ÂIÿRç{áüÌB8úä áJ=@8}\©W0 îdv.œÛW~‚Ó%"8½¦N'‚ÓÓ˜à8„pº—Ž/e‚sà®Ü WW*&Á)JDç œ„S'ÃT”#é§‹áÔÆb8õ1\ü P—wRv]WJ€pñ£dK†s â(K ˆÓ˜ÄÔ¥ÄEIž6âüZ„8¿!Î5·üàx'BœŸWªÄ•Ûâ¢ÞŸ€¸r !i qL+ˆ+oˆs{ â•FˆS¨!Î]‹çÇÅ1ü‚ç&Ĺ©qn B\©8!N J†sƒ‚áJµ`8¿7®–<«¬† WJÀp¥ õ<†ó§ÃñÃá<\Èpš±Åp¥0œ[‚ W®ÄÕ’'Ç* qqsÙâÜ\„87!ÎOLˆó×$ÄyØâüÄ„¸R3!Ž©Yqå^€¸ò«µ4XqÍãµ5ß‚ç%Å©ëâ\†ss‘áüÁp¾5®ÜzrqÕ..®ú!Ž’L‚8?Íš®³2œ çwÜ ç€áüÀp'bá<âÀpåÉp¥ !Ίó÷!ÅÉžxߟ6Å•ÅQ™§¿Áp~0œ/H„s3á|G"Ç ÎO‚+¿˜wm'\ùA\¹gœW®ÁqWK‚ AÂêrY~‚ó«ƒà|ÜIåÝ$8¿®$Á•dÙð=’àN¦ª!Á•Ÿ$Á•Ÿ€àä¢ ‚Ó ø ’Ó&»¹·•ì˜gRdwÊÀE²;í ´S:±]³q lǬc¤»F‘Xá]1&Ý1Ñ£à®Qipרƒ*¸“ƲàNw‘/·í„»&¡ Â]G’îšÉ t§ —¢;‰5‹îšüûHw];\ÒõšwLø,¶‹=…PN¤F×!Û5!Ù.²w#Ø.ÙNéÅv;±]3‚í:eÏÅv!î7?l2нFÓùˆvR“ÚõÖ¾h×…SD»ÎPh'Me¡]àí”™[h§œŒ‰vîD;©wíÜ#ˆvú($»¶2+À®Ù!`×èL®+÷×5é©ëš½)Áuº±®ýâpÙ$ D¬‹{Ãê¬krž%Ö5;SëÜÈuVq]£ *¹ÎÍK®cîOb]Sp%±®qÖ5za ë”»[X§L¾Â:f[Õ5ƳŠêb!Ä5d伩°¬k̾#¬SžQa²Ê ë8C‰ê⮿e“ ¨Î÷&Õ5(¾êØxbºÆ°Y1_’L§$£‚:%…ÔiþÔ5ùê¢!æêü]u ¬b:åÒÓé"RB 锇]HWJöÇFvP!]¤»|JÝN( ïK òC é”TH§ì«B:w+2R‹é”‹ZL'=P1]cž"1_‰L结é$*¦k Ô¹7ê”íWPRcèöÍ3LWžfqIE^ B]c¼º N MuÊN,¨kTÔÅ5GGÙb©¹"Ô)Ó¹ Î_˜PçþHª+×€êÊ5 :¥óÕÅ[¤¥˜T§±¢ºò¦Iu. Õ5ê“êâN†8,ªL +ªs#“êüæ¢:KŸ€ê”lXTרR/ªSšwQ]c'Q¿©Î3©®MOê"©ûÇ4§lâ:>bÛ‹XçyXGÉ\QÇ©N)9DuÊj+ª+Oª+%ÀºÆüÄ:M´ ºháÛ–9¿¨Î3¨Ž Œ u¾' Î3, ®1‰P篨SòoB2'Ô)3¡Îͳ¡®1—©.¾ÜÇÙÒ­¬s×5¦õ"×yô‚ëJ vJÁK°S’ð»ÆD¦»Æ@;eö&Ø)ß2Á®\ñ`ídoØù“ì¼Ìì<3ìs·ìüÍ6Ø5³b‚]©!ÁÎ °‹w…Y-ÁÎ=`ט”BB·\ÁuîI”Æ8¯)JÒÏèE)ôÝAôû(eR–TMèßý™/Â%ÿš’ôyì\gõ*±f3ˬ˜ê«6¿HŸºXRëʲZKJ]ïŽëóTø»Ô³KJ-øû?[Eú ÙšñÛ"ÒÿTú^DúZÿ’Šô/=ä¹Þž=?Š·?ûÚîFmÇæ–«X¢Y‘¢U/Q5¾µXÕT}hÖã‹XQ½Š5Iš5}hÕ¤‹TS¹Š5Iš5}hÕ¤‹TS¹Š5Iš5}hÕ¤‹TS¹JÖúШ©êC{°ó"Öô¯¨HljQˆü¦ˆôõG"Ò¿ô¼ß‘þ½Ë~ŠHÿ“ê~Ž˜Ÿ—ý‘þg·ý9ª~êÿ‘þSõ?~κ¿51ÿã·Ææ¹úwÆæ/5ýeéçÞ*Y¿©!ý6ÄÿéÿýߥØüÏ4¤?òÎÿ÷¿GZÊåÿ“4¤¯ßºÉü‹ÒÏ53ú>÷[e.£]ö-É´3qý¹îk+¦ÁµõÝ ¤¤“ >WÀÅ©kžs¾§¢Ú„ö¹TT#«<÷™’j¤Úçn)©V •¤÷îê¹Ãù6 §öÜïÆ ÊÒùÔ÷<ÿf¡é÷ϵ›Î5¦ê(7ßé9?#Bä¹ãëo[Õ÷ÌŸ¬•S:üqžû™)¬?¨gP(äëù<‘ˆýüÖñ(ß’Qeß¿gÿ;tG÷è~K®ƒïÀ‚Å&ηŒô™?Þàw ”ºQè-yûÚýùQ¸p}^©óï×çáÚ‘¦Êàûw“¤(ÓÖç6‘­g|KFû{Õ|K¦„E'®™’ÍWÜØý}”[⢸d}ÅE£äþùüOU³=~H¤{L”<Ñ·ä„Æ¨>ìNšTo™){^2J>o5n v¢©úÔãD5Wû(vFÉóÑG}K>šÂïßë+6ú–<çQ‰aG™ã^¢9RoÔC'Ãö2‡½%-Gi!ˆ’çG̰ŸWˆÄ°ßN‰a¿>æ§÷fVØú‘ö{É:)LÜO”Hx”µ>RÅçÑ|ƒH ûý‘öú|îH {Ö›GVØo OªA£}#'ì÷ "'ìóùN‘¶otß^¦-kþ|jújìDNØëóm¯c}¾c$…Ÿç½¨ì«ïYa« m”Ü\¢pɘ\NT3EkñJ‘ö;J/¤½(×ÜóÇ0½ø¢^?×ÒÐ{ývòEõ_ýhu>>Dý_]ò`%=8G>ØšJã-9s%¥FÁ[ÒÎÏ,J´’b|úwòl°ŸWz˜ôâÒO&VRD’¾%×üñ±‹Æ6éÊOÛŸû{뵸г䙟/›žú]cKñiÿsgƒ­Û‡Xÿ>j‡9wÈE½OLíŸO³)G/™ó»ÛŠ’×'Jîƒ/½ì<˜ò[Ô3zÈ·^f¼p½ÏÃWÈù6ªùnÎÈû}>ýÔ’\M5Éù¼ûá?«M€»ŸõÏ·Ø?à^ð;àCBˆpqž„‹3˜;0.à£%,%Ã-f“áOÉpáXp%=%Ã-ä"Â-Ø?Ip‹–ã$¸iν=nÑI‚‹$A€à…Hp˘'­bÜ¢c n1×, NªyIpåÏ$8© &Á­l WÒW•æp–#À-R øm‰ZÀo‹(A~“6 ùM÷Øøæ €oK¼|[‡Ä·rEâÛâþŠü懿-z‘ß–!rB .ùm™“ß–¹rËfrÜàw·¸å9·ˆÐ¸å-1nfJ‚[×$¸Z’·¼gÁÕ’$¸å•uÜò´ ‚[^±Apõ7Ipõš$¸r ny=Á-8' àê% p‹G¸E7*Ü¢+-®^‘·¼ÊàÖ“ Ðpµ’$¸Åä±"¸ò– ¸X@OÔ“çŠAp¥šMp‹ÞP"¸¨¤ƒ‘nÜ@tIpµ$ ni) ÁÕZ’àêáÖƒJ’ßêOàÝÍp‹¡D¸r®¼ n1±½Ž7&½Ñ |«?I|[T"¾Å5 ä|c‘ø­ ðÛ¢¿1ø­|hò[yð[-I~c˜‰ùÍ×ß­"|+€øÆã›_üÆøó›+ÞøV*¿1Çü¾{xº…á§m,®Üçzp¾Î-A€+×àx"k‚óól‚[Ô€4ÁùiHp¥}5MpåÞ@¸R®\_T€‹•a€¶ˆ¯»®tOœ¾ ømZÈoî!¸2xp¥OàÊ”B€sÀÕ_!Ñ…Ûs\½çï€+×àüĸŜJ¸2Ü p~>\¹”}=š pj@ò[©ænŸ îçÇG ¾¹¿ß|gâ›{ñ­”ßJ ðM7'¾¹[ßÊ€"¿•jæwX’àÜApeŽ Á•;áJ½@¸rͳ8—cž&Ãù^d87Îà ·~2\¹ ç§!Ä•k&VSí`qe­!ÄùqõVS @œëIŠ[Œ¡Å}Jr«ÎGŒ«×t,¨.?Tr\½fNÖ ŽÓ"ǹےã¼Hã­bŽc9Î%ä8ÿŠWJÀq~r‚m„q‹çYA&Z¦¸çùØá.RÙ¶ÃÑ—U†¸)̃%N¤‘7ß]võ4ÅqÇŒ›}Ýq[¢bÜ<˜O·eªs žçØx€Ü|7f9ßo³F@ÎbH9 ã¦DÇÀq[äúØ­ýTTÃǽX.Àqó Ë8ÎZ:›ã¶þR’FrܾGbZŠÇÀZ•gÑ.PÜ<è·ŒÛÒÜIĉqoöÍà¸úHw*Œ‡ð¹9nJ‘ ·ë¸`x;þf±o€œõ½r~‹ä¸ÒPÉqµ`sÜ~‘V8nßó(v¸}Å“•Δ© —(8®´NrÜ~Œ#+MA~Ðä¸ý•ãüXä¸)Á.rÜþƤ¢3#þ‡'9n_óXψÿ¡Ã¸Ä8K[ã,ÎDŒûüjË. ñAbÜçŠqVq#Æíš7ÆYä‹gu.bœ{&9îó«Íqõ’ãö'ÀÎ"9΃&9N]ƒW81n¢Þæ¸O%›ã>7Úç¯OŽÛõÈ6·òñl4Û W§íXt×› ÷-YŸgIs7#ȹ§ä>wž)/3tš ·¯Á*,·ûÑYYÎ]–,·ï>a<|æ§'ËÕçK–«-œ,牄8·{u«Ö¸òé’æ>?©6£ŽŸ0Ws5N.8`N–«Ÿ ß÷ç“å<áå¾%?­]ÇÅéš&³s|_ Y®ŽÜd¹)µ;²œuÖÈruh$ËÕö ˜ûÜzÃ\ý’ sŸ^?aÂ\ý¶ sžŠ sµæ„¹ú«„¹)‘FÂ\ýº su^›[¯Åý ZW’çêø¸!úD "ò\ýB†ÝCçÊ`¸!ûäÇM𫝔8W8pîSíýpÍ•%PBÕçNšó.4Wk½;$ß:8Ù æj‹'Ì•×Þ0W& À\™|s~:°\Y&Àre'–›/%Ë•™,·; .ˆ¶A Š(W†2PnJg6QîóÐ@U¿Ê•) (çæÉ}.i|¢àá0½„ýæ‚Ô)özФ·çØq9à´‘N€».ì‰ p÷;ܳ~ØášqÈo¸•'%U®åIIÓ)eµ¡#¥ àHI³¹)i¤…#åóA7ù†Ò‹’Gpb7 ˆÝÒ,v;d)»Q$Aìæ°ƒVÀnÔ»eÓ Þ|9èí¸ée zÓS’Þx*zãè§¢7GÉ‹’gO¢7É€ÞT%éMU’ÞôÄ7*Åß(´#|sÀ7}"â’„oþ ðâÂ7ž@ß\%ð-Â7>§ñ͇cÄ7þÈøVJ€o|Vó›ÇÈoµäáóœÊÉo|#ò›ÇÈoåNv¤Ä–ŠüVžüæ£9ò›ïM~sÍä7 ß|6K|ÓY“ðÍ7O|£X€ùÍ/E~+·¿QaÃüVüæ“Mò[¹üæò›NÐÀo®E®”Z áJ);€\)µ„Ñ•²ÙÀo¥^ð›?ù­<})í(igJÒ#)}÷çë“õΔ¢*úRš‡èKY\'Û‡a9S JåLixügJZçäKy˜ß>.šô¥Ò•R•>Ïç§%Î¾Š§2·Wx+~<ö£TC?Jì4‹#%ïDGJíi~Ï‘RM)GJs#=)åàôž”²ÓË“ò»}\éI)ïE:R¨èI©÷†'¥ŽäIißJzR÷èI©¶’'¥ŽfäJÉ/WÊþ%·ò¼ô¤ôwJOJ?í_ò¤ô5°Ä•kàJé–ùWJ;AÒ•ÒFWJ[ýèJiã!])‰vt¥4+Ñ•Òî 7Or¥Ô—*®”ó‹nÅ6´–b]!»Ù¬tó|Etó<èV†ž”x~p[ù¸­ZÝàF©v‘¥ìä6ÛåFé_ÛŠ…Ž”² ’Û~âÜRä6/7¢'¥Ý/mÅ$#ÜS( K©–Ir›olS5À65¦°M†za›vâ6=°¸­üŠ®”yq[©‡¾”œŒdƒ+~‘·r¯[ £‚›†ŽÀí§ ®ìpnêŒ"7· ÉMk½ÐMýF¾” ¿¡ûlcÛžÖ ®1Ápm¬Ÿö¶çø¦ 5ÒÚ ùiáš| ÉkLãf^Sˆ ÐY ¶0›¼êlXlŠIcä›Ì‚d6A"ßB¬ [E@¾Éo¢F¾¹oìF|“å‘oºG¾é |ãžIo´:+ðÍU2ðMÖ3¾Áä‡À7½©ßHÜ |sØß2–Žozl¾qúqàm• |£ÿœ"ßÇù&7ÇÙ>Óˆ#ßrçÀ7š;ø&£]f~E¾qä;ò­âÚ(Þó {“%aošõö¦sA…½i¢eØ›=UDk‚†½y÷ao^ãövÙrýðtWØ[5µÕ‡SÌ›|&ó&G@żɑ!oQÈ›½ò¶D…ãú^Á7{b2äíù¢šûI z )èÍn  zó+0êMõ(êMM‘Qoþ&B5ÿ¦­O­BµŸ>“rX/QorÖdÐÛO—Éçë2YŸŒ˜fH$¦É˜¦]­0ÍnÄ4{)’Óä #N+TÖ~`‚8Mo-Ns 9M¾b5L3…Ôü«$5{c’Ô\ QÍ¿!«©ÏˆÕt`M}Q´Æ,XÓ ¬ñÉÕ~D¼]ÕÊVS¤æ!©ÉDIRóP©Ù£“¤Æ'¨iÐ ÔJ @Mï,RÓÍEjþÕÀ7¹ÔÔ¯J̶–"µ%J’šïô»¤fú|¾«å'èíþ š¯8µ`2ÊŒ¨ækˆjú.´±gG¢š^A¨æ¢šqލfWK¢šT¨Æ©i|‰Ôdf©Ù’Ao?llÞRSÍ zs ƒÞJÉóãD¢½}¬l£Ráý 2.Ao8n ×¤ù¸½)Äíü±ÑÊV¸‹AojbZÙÌ ¢5“˜ÃÞÐ^ {Ó‡­it(ðͤxéìóþºMz>R䛟‘oxIÒšƒÏHkPÑš¯aÜ›¬À´±¿ÊŒ{ƒ#ƒÞìúHVQÕýå 7ûaÕÌ„z#I2èMM'V} êíGÈ›Oé5Т…˜·âäȘ7—Ô\ƒÞ|ͬK©)ͱjŒxóO@iË–¼õÐcÀ›BH *àM×(à}Åorí¤£¤ßˆvB6ð/H;ËÖvnuÈ*ÀÄx¥ëªé…otEo1èà™«“‰Þ¨ñ,z£Sôf/DÐ °¢7€Þ¨{&zsÁ¦7¹Ö‘Þ&MB¤7šp…ož¾1߱𠀢7ý‚ô”QƒÞJÓÞü'èz 7ª2ŠÞ¨d'z»:Q ôR²z£(¨è²’¢·¿ûÐå!Eo½ÉâJzS ¤7ÊÊŠÞôb¤·· ×¸7ß”ô3L€Þ.v-Ò›ŸøæJo¾bµïŸ¹êPêTøöVD×BuMp|#\ù®”áØ$F¸kÙ…2ªá L‚ãÙˆ Ž’¾&8jКàÊq.!Äù qìZ†¸ò+P?«)*Ć8¦ë"ÄùñqŒH5Ľ%ÔLÄQj×ÇlÖ†¸r ÎíIˆóÓâBH,•Ò%…Jrññó%Ä•_â|BG„!ŽC×ÇÞjŠãx7È•§È•{äJÉ3?í@s·!Èùrúpä8ßšçK€qnMb\©ç§#ÆqŠ2ÆQܘW~ŒCP³)®<(ŽÊƦ8=/!Î`8÷hB\©ç—$ÅùÞ9N²¹r@Î Cs!Èyb!È•§Èùã’äÜX$9?1IÎõäüÄ$¹R2Îïo@rîø$9¿IÎÃ’$Wž$G\£cÐrþQÎÝ&QÎoI”óóåü4D9®*¶ºyB"Ê•{å¨Ðm”sëåÜD9¿QŽzkd¹r'°Ü{#ÐÀr®…,ç/E–Ó2A”+Õå|k¢œ›‹(U|“œÛ†$ç–H’óW ɹeHrå7 9݈ çE³›/Çù•hus½ óX ÇQýÀÇM9ÎÍ@Žó­q.Å•;ƒâJ- ¸ò¼9Ï ~ó¯$`rÚÈv²]_·y‚œ{YÎïÈà7÷"ÂÜuÊu0Çmža®<`®< `®”@ÁD=0§{‹çôñ›X8§†ΕçÔ§…sz`á\¹D)U¾D§ÑQ½™D§&Ò1=„cß\/‘ÎOC¤ó;éôñ„tj g–"ê|ž÷š_íÎÞrgdUg”T}æßÿ¯â5ÿ¢®skA\®ýä]RôKñwÑ`n‘Žf}jaI­'ËjM,)uõ3'ßòÆ,)u¡¬Ô¥’ÿl]ç³{dÿkºÎëÿs]çßè#ç:öH©ÊÎ?úÛîI×ñéÿp]ÖmFUEÛ™5éVTõŸ³žªÛœ}ÔQS¹ U}5 QWQnF]Uß™uù*ÖõQF]E»uU…gÖå«X×GuõfÔU5žY—¯b]%hŽaë7g]•g}]…ºþ•ç3AØÉ<ÿ±Ì󟙼ÿñË4ü[Sõ?~s°þœ¾g°þR×_–z~ûÔ3èÿàZÏ«h=ÿÇ_Ðz~[šd`Ë€=y0%™"çÔ†a³äC{ÿÞ9ÍfgFŸ(Ù§ÄãÝÖ²–¾]y†7klWžI'ü·d¦ü<³BDÉvå‰t6p÷ u¯˜ú˜|ë-IçôA©·díÈÆi'¡•êœ-7++òEªš™Ï÷¤z¤³iYËsîÈÆÙ“š×3ÒÙô<éŽÓáx‡9ø4Oú§ÏHuƒ_Ú8%íwÆin\³ã\âè5Töí µ9ã†?ž±÷Šwðì‰IóÆ?ïµæýÎòÃpá Ú‘žé–ùÞ’•S8rE½%é™^¯i;¨1ò"¶,HÏôëÝ çyP‹èœ"€ ÔŽ±ÿ¾Ð(íeôxô«Cõú-IÏt¿ð[²CI.Å ¶ãÞ1פW{©(_MÐvûxš…-z‹¬ìû,2-NÞQó€þÌ»éùìÒíýÝ~‡øV%Q¯BaÛÙwLÉ¥ðªvflñT¼b;çŽ+‰Ä@¿Jßô¸.¹&_!ñàW;êBîÀ·`ù®%#‹ãœ`¡šgæ=`>i-c‹g/óš÷Å£Ú‰8^€úoIÛá%¥ÚH`/ S[‹–ûpÒü–Œar1¸&¶¿#ßàaï|?ïÜÈK%Û/vJi¬Å4=\&¸Ö2ºx†2?o‹P—lM­elñ”gGëÇ•‰Ž…­glñ”mõ}©i2u„ý–h^¸¦_9JáŠ÷–ŒÉ1ud{õyæ;p¦yKž¥†ÅÖ¯+[áMoɽŸ˜öØÖ×ö~˾vLc$¼b-\/i\cÙxðtÏ^RçyéN[<#”0빎Ÿ9š=D×XR[çl¸·Þñt¬1Åí7@º·dì%u6uëÈã¯àù;ò¸ÆWèHù–¤‡úô\y\Ϭ]ëÊðâq»dí%U]öz°¤rm‘Çu/©zäq_¥ñ¼…7G"×yÒºÐ"“kÜKSf$rÝ@ÔøéîÌ63=/Ü3WÔÆ‹vgš©Éù#ñMÒ_qó$ý9Ú:éÏa}¤?Iˆþ­Dú³w#éÏž‹Ä?…~“þóðïÐÜKü“\ðïðŠ ü+¸ñÏøä?é,ˆÿJ½à¿roðßQ¨q@a`ýà¿ÐĦüWïm©B7#}/¨K<ÿIþ+}üwh¾!ÿIPü'•Cñ_ýÄ¥t†Eþ;ŽG¿ð¶åIù/Œ€7~•üWïu!6Ríµù¯Ö»Nj8 ³ÿJ¿ÿÅRh†üïðÁ¿rkà_”`‡ü‹‡‹ÿJoü;N:Kÿê­¡-å['þÞÿâGÏÿzs ÿjIâßqrž%þ•6þ•×þE ‘«õ|œ,ÿÊKÿ¢äùàßqNa%¤¥è*ü+O þ«5'F š x0Ý‚°ô`” —l,ï ,OŒ>Ûr €Û¯ÖékË;ãÍ/”$Ö{!DùÔ‰ °^})·àÀÒ6ÀrðS’~ï¦àq<ÿð_½$ù/lï8š>‚Æ‹/°[`½y`ù ›ëßI€ez†Fªªº`}_øW^ø%íƒQ ®EaU¼mþ ¡Uœ—ÿ¢äøðŸŸøWF3ð/ªí(DO¹54zN:g’ÿŸ˜‚ÿ¦–_ËàØxø$X&`éh ÀÒÍA€õèõœj†¼Ty>(ö¸ƒ‚Ëä, ”¾-ÐoItÛý4DÀZ ”{tÚ@t¯&z¶&z "úˆ€î³DÀz¯ª£"à¡“u" [è¶!F½óƒ€Q3É >¾7°Üxèìˆ XK á£Îž ¨®N¬V­SDÀòñ€€q£¬-¤nðá¬@ŒÏ ,ƒ€–ÞÀò,@¯RÀú›©u•×\ˆì²ÀZ,ÏA`Úö¿$”bÿ;täEû_QXÛö¿CÇ[´ÿ7Åhÿ;˜Gö¿CÇ…´ÿ…Û7ªMóßÁd©2ÿ6”ÁüwØ,óßA õïp&XÿqNZÿDÊÀôw(ò‡¦¿Ã¹«`ú;EÓß¡XEšþjIšþNAÐôwZ˦¿C4BÓßñ‹éïpv¨mú;dT õïPà­‡ÏÖ`<„š4 U£ÐõÐè'¦ðС-€QÒf[›JU´ºiMÂ>xûÜLÄ>Eb_1:û•,ês'Lê+·õéìLÔç†#õùF¤>,bŸØ'%aŸ”i„}~ñÄ>|bŸÄ>4rŸÄ}žîsw&÷) SÜçsvrŸ’t‰û4õ‹ûüÌÉ}~orŸŸÜ§ÀOqߢ‡¸ñðÂ>À û<Úˆ}nbbŸ?±ÏŸŠØçkûü Ä>×Kìó¸ öù4Øç-bŸ‹Ø§5MØçæ"öIlAØ'ƒ°OÓ^R_yPŸ†Ô§Ã>BŸ[†Ðçç%õ) ¥¨j§†>7 ¡O¶AŸ‹Ðg¿ƒ„>¿¡Ï#“Ðçf õ©H}n_bŸ'bŸß›Øç÷&öùñûÜgˆ}þnľòp_)÷ùø—Üç)‰Üç™›ÜçIîóç%÷•p_-ùÎÄä>¿7¹ÏmCî+×€ûì€AîóÈ$÷•{ƒûj ÖS­tä>wr§`Ÿ¦°¯Øç€}ê7Â>ubaŸÔ „}šn„}—aا,ôÂ>m…}åîÀ>5°O3º°OM,ì[Çß¿ÔçKH}¾©O=RÔ§¯)ês’úlv$õù¥H}ê9 ¾ro`'QŸŒ¨¯< ¨ÏÕûT ©Zˆ>9RŸ¨ÏíMê+÷õùéH}~iRŸf$Q_ùÕ­UUéaÿ@º¸zž?üØe!¢½Ï: =™AdïÓ$"{_¡­®¸¤-Øûl¢½Ïš´÷Y!€ö>‹ÓÑÞ'½¯\Ca+é ¤½ÏWÐÞçw ½ÏOC{_A9Øû¬i@{_ùì}¾Khïó¯hïã·•½Ïïö¾òØûJ í}†'Úû´!–½Ï8ey«¿çÇJH{ŸÈGö>—ŒÏ;Ùà‡?iíó×ú¾XïSé’ *ævšûÊKÒÞǸÌ}F.šûÔI{å«lÚ«í’´W-£'…ˆ¿´Wßàœ÷æMÚ+ ´÷ùÕ:¾Ý´÷±a>ó£ô Ø–Ú´Wí¶I{EÀWÛ!¯Þ:¯¾B_߾Ͻ¯öµjøê+$ð}îõSáj_ù”òVz˜D¾ÚG:å­Ô#’ú†eé@}E~Ô7,3ê«Ý>©¯˜áA}Ÿ_]×w:ÜØW‡Sb_ùrI}õ»tJ\‰“úê‹j\i§›ÔWo5¬q…jzÿ1LÇÀDƒ_ŒEÀ»2_­ãêÿ¾Ñ°ÀO"ßçš%¡: ÂD¾Z’È7,ìäSЉ¯ö´ ¾Ò˜ |åfÿŠB’÷>7¶¼¾@_­†êVþÉ{ŸŠ-D¼*ï•Æ›Ô·Ò%{傤½ZkÒ^m•¤½ÚÞI{µ½“ö>7Ï7HÚÛ²Y³ùªWFÒ^íáå­Ìˆë;½^”"ñĉ{Ã:dà½úĈ†,o~SŠX5'ïÕwHà«ÓJß§H•z ä¼¯f8€ïs§Õt¤û‘Z$åíì‰À°C«é]¯|ñÕ´˜Ò’@¾÷êß7ZtU%ˆ‰ögZÔtÕ ¼. A> e]õu]5'/ »úažùcžy(íz~q¯N°Ï¹>]ⱺ+‹WÛ^} 5® eÔxu e®\ ZrS3ÞÁSshr­¨¤°ã£VÞ+ï Þûü†b¯øTÀ½Òk€{–À½²Š÷>·¢à+_ ¸÷)¹Ç§ŸlÚ+Ý´WúhoØ ¸Wæ<ÏoOî•…¸Wz p¯ CàÞ§ÈÙŸõ´ò+ç¼¾O|Rù•/yRøUK’‘¼³¥_ÂÝùÝ—÷ê·LÞÛJm'lxP âú³q¯¾t£ð«pÌ϶´7žB„ˆ®%ë;Õ(ÀSÍoèWðèãRcùdzu,Ÿ6á…¢ÏêJ[^”Ó–×bŠ’´å5ÞÓ–×8Ò–×bœáFiËk:ʦ-¯+ myM"'4æ5…«Ð˜×n…îmc^“8íyí¦Ë;íy]Þ!´ç5tўט;Iö¼x -ìyåi`ÏkòU¦=¯¼9ìyM:´çµb_ {^|å£:tî§ù˜óš#‚`΋‡!Í¥9¯É•æ¼ÆC YóÞoÚé¼¹O c¼Ò¿s@¾ÛÚ¾¶1ïTª4óNÚÌeË‹X×O4ß»ñ“#iÚò¢&6ØòN{ƒÀ–W*NSÞ);:­yåG°æÕyóçñcºsú„—Ö<©0Êšw/‡îõ†Ís0êi5‘QO‰ŸeÔŽï£+ç­@õ:“dÓëŽÃ»jzV™ôJ°é¹ÉiÓS·‘MoØ‚wþh`ÚôÆÈ+½FF½rÍ6êi&‘QÏC£^¹ŒzÝð£Þ0¨ç&§Q¯åÎë/(`ÿ2`®â_ }þ•º°7hÎK)ùÿºÂ-ˆ½@câ_l—n ·ìµªß$ò_wÖ(òßÍwò_þ“ÿº&Jò_müë?í{ïO¦¢î€Å}2ño„ÌæÇs‹±âšìÛ½Xüÿ†“Xÿ†´‰Ã)«€õ^‰C®Ì‰Ck ñ¯èç€ÿFWø2øoX4ü7¦\æÀÃqXÀþ¶ëü`Dˆ“#“‡gúM€cˆ{@€cTûÞ~,:à¿1†ó %¬&ÿÕj“ÿư?jàP3pHr‡×P«%0â…¯€E¥8ŠJL`÷©0phÿ…îýQsE&ùohP“ÿFçù/§}Ü9‡·mÀ³oñçŒøðþñç“"à¿1üþ°$ÿ ïÚÀãÝ@Á!ü7´x»äT €ãÝôO8_½{`|©‡ò-íÇßx. à¸a—8´×ÿ oò߸âþV,ÿB–ÉõWÉ£7ÑÞ…¸silþŽpÿÅpAâßP*tâßnñoTÚ;óñ¦<6“ÿ†·Îà¿Q$V’ÿÊàØüWüW> ø¯Ö’ü]¢}øoĦ¼K†¿-Ô>ü7¼?ÿYNøç¶ý Ÿ,þÊÓlú‹ûP‚%é¯|&Ðß( ™ø7n‰!ÿÊçÿBrÉC‹–Ä\,kþ«Ï“üWºøo˜Ÿ7ÿ•§ÿ »Õ†€1èÎjæû¬$– 8¬ ,s7pøÜXzÅ\4Ê6ÿÅÅоä¿xm"Xò_yMð_4: 8à¿ñTKIþ:›%ÿõGDà¿Ø5£¿£âä¿P“ûð_½÷õ|Ÿ7ùoøXtZ€µh¹äJž €CÁ.Òr¹Jx_.©>[ÚXº5°|nàð*°KgŸmÕ>XëIܲ–5—ú4Tsábþ+/E5Ï6©æ"0’œ‹OT€Vô#åkœ‹8|ÌŒ—Z ÝËUÕIÀÒm¨çb"ê¹èÜz.Z‰¥ç¢ç“ž‹H`¨ž`0è¹hý¶ž o¤ç"±fé¹0Û§õ\Ôm¥çr;0/ ðÔéBàà4+9G°»Æªä\€JôæQr.㇙¯ŠÔ=%‡N®¥ç¢‰Öz.œÂ¡ç"qH"`ù0@@/nÒsÑT,=—ËtÉ€åi¨çò~C*±$v(KÏåG8_LªçWÏE‡’dÀÁ DÀ!rÉï]¤æâÎFÍÞàÆ¿}³ßr›1-:‘ŠÙ(ù(fÿîïŠb6®ù³½ƒJªBõ÷ÿ½”µëÂQëRI© e¥.•ÔºvÆÞRSþ]뉒ZKþ]êH þ´KJ=(+5©¤Öõý^õ Öº¾_§~¯ÿt%ïØ­¾+ÀGÊ;Ô·w²Šõ‹¼±å¹ƒ{û}Ùï3øü¼~Q4þQÃü#1ðªÞ¿ÕËú*ßæ÷Ú V>Úߨˊݨª(v³&]ʪòwÖSõº³¢^7j*W¡ª¯ö7ê*zݨ«êu³._ź>Úߨ«èu£®ª×ͺ|ëúh£®¢×ºª^7ëòU¬ë£ý­/½î¬ë£êíþΫP׿¤êÝc±¿ÿKÕûŸªzÿ‰æ7§ñ_–“üÁ’ð¹êw'ÄÿwªÞqøö¶Öÿ8ªÞÿñ[7ùUÕûRÛ»éþÌ"ïCqµÉCç-6¹ŸyævmZ2PõçŠ+„Â=4Â÷É[Üû²²÷gå©·úCŽþ½½Þ!.ô7áÂØ©›6Ž<ÐkŠqF›6mÇ‘Gz]‰MÆ1>gãÀžŽ²Ç6¦‡Ðéð°þzö1Ž;ea'u-GGATµ¡àNd³ŒˆÔiU9tD}h8 çãœgêÂ.ªb¿%)Ñ,î~u¦’vÕ;ǧ@³ä&ß’}”pIóA=nÉz½»ü}”p zäŽ3Oôn*¨¾û$áŽ3ôn©sí“„Kùq>û$áÖIÂ[²O.EÜŽö.pó–iùÅ’}”pK’æÝŠï£„û¢ˆ÷[òä+¨A[ßG ·´_,Þèg xš6÷QBþ_å‘^œ1 ß´k%Ü™-Žôêk%¬ˆz(ÙèqË‹Íæ{'RÙèy¦ïÀ’s&,I“¿%û0á–Øíx `¿ƒHrD§wxwd~5öaBÈ46\3öaB$úÌûñNqõ×FœÌl­†Zî}˜°Q°Ïnbã‹™–CY#l5ñ¤%:FéítUJöQÂM÷Ë1òHo‰íƶ,Dƒ’_Z܇zË úÞ=®àÙÌy¤W`ü,Æ H@nÄ)ñÈWš¨ekVÏ%U݇;ñ“׬}”°<2·üç[¢Cç2W>1ê uÒxO3õõgÞç;â‚ ˆ3Oô–„ ÇÜ–„÷5‹Í<Ñ»ûõ–ì“„˜xó4vÌ<Ñ[a Å­¯}’°äóyË4+ôC! ¯ “„"àqŽõGhÅÇ+x¼\GÜ©3…ÀØ’îq§SsèÀÇ+„3&$èû·’~æ~‘kÉ[²O–úZ¨èßùNy:22ƒï\²KHá»ß€¾álÆÙæêHâÏ/ƒÂÈ,¾sŪƒ‡yÎ|­™Ç÷}`µC&ò‘`6ñ~D&߸F½:3ù¾£ÉæÞFÚùêY™Ë÷½òÆ#rùÆ„Ó^6D$ó}Û—‡‰#†ùÌw¼ð,;ïî5(¸÷šºäa:2Ÿï ó):M$ôíÙxa™ÒwWŒ¥.rúÆÈçtdRß÷蘫öG¸ù8™ØwîCÅl‰Èì»ëÅT“©}çÒyãÈܾsíÃÔ]0s0+YÁÈä¾ûGèÓÑøýÓ±2½ïþ*y’=V¦º½æg‚ßw£+Á;–\‘(2?2ÉïÛê'Ž'ŒÞ7ϺGæø·[ïI›÷½{à.ÈÓ¼¥ÿI‹÷’)xd–ßÝëѾOZ¼—t‚3éZ wæhHÚ¸g‘' Þq‚¼pï4xß±@ãVañ¾’?3Õoi—-õ䊟fªß÷ž—îdر=”ÑŸ™êw¯j)ÒƒCŒ=?ÝøUæÝ²n§ÀèFÀŒ\¿ó–»óMýÓàí%vf®ß=™£‰ÏK+jNïóD¦+ \Î3mÞ·öo3sýÎØ‹O–,vó\gæú­ïÐÒæ}ó´qf²ß·lèfäúÝÛ‘† v®ß·V¡fæú‘Â2wôÛ1$®Q4åÌ\¿ïpÙîð½®3sýî~”ïô%É‚;ŸŸƒ;£ ²…ÑV™ë·vÐï%ùß™™~÷èÁigO‹÷’JÜÌT¿{,ç;{Z¼—2fæú-“Æìiñ^r·˜™ëwwü\fæú·æÆm½ÛCÛ¹™Ù~kèañ¾µëLDªz°—¾Ó‘Z')7—£?­èmðÛ=çsB60¤É~7i‹èwkÇžèw[Åè·;?~“ècž¹Ño,™ú€~#ÖÙ§¢ß;iÓë è·gà†’d?ë!ƒýb¦ÄŸéB,—‚ßá…bƒŸË~Vy"øò='ø²üšà×Þý7x ä×¼¸€üšv¿îÝÀ¯)"€à×å#”à×5à ~v¸ øu q‚ßðþàg©z‚ß&9Éoh :éÉC>¹/vÎýÃ}SÁgä¾!ôOî›’w#÷MU ì ËðÝrñ)å‰Ï;3ß-,ŸI ħô;$¾»‹@|Þúˆø%J"òÝqÈçY…È'k¼Ïûp2Ÿ”ÑÅ|J*$æ3!%ó•+À|òVóÉÕP̧­™˜ÏOCæ;µ«&ó¹Õ}á‚Öô-¥ßôù”‡Ô'Ï=PŸgFQŸÔ'×yaßû0×ûNµû|V ìÓ5Ä>w~aßE2!õù|ÔgÆ'õyhŠút`ê[Ê.Gê[r@õ™¬7õ-ÏÝÀ¾Õb_4ڊܧ¹Üw+êNÜçÖ#÷Éá“ÜWŽ;À}w~·d“~‹íÉ}Ñ«/p¸O.«â>1r_¥3pŸ<{È}>H#÷yÜ‘û–¼NÌ}<HîÛŸõ&÷ù•~Kîå¿Éæ#øÝ:5!øùü€àW6þ?ù]üÁð§õ xÉWU†¿¥š 3þ¼©¦áOùdø£cì~n,Úý¤Y»Ÿ—dÙýÔ?e÷ÓŒv?›h÷}º(³ŸN—döSÜ•Ì~ò´ÙÏ·‚ÙÏ–4û)ŽÎf?½Í~C'βûiw"ß±(Ïhþ¦`G†?Ó›-Ãß-%þ”ÈUQv?›kd÷ã±Ì~\meö+¦A˜ý"Ø&G@ €döÓkÓìW f?Ÿ½Óì×Ô4I6Òîçæ¤ÝÏÇF Àb“ .ÚgiöëL?,³Ÿ$ê|d@­]²úiß&´U7PUbÀKfT™ýD’d@í=Å€î"`ÀGÑgb@Ÿ—}ŠAÔž,ð9lÁÚÖ|<Á“=AŸƒÝ“>¼³ß#¿_Ùý”.Pv¿'ï"@:àÍM ;à£ý«PSÐç‘@Ï–ÀGÉ€ï@ ž ½Ö=’7°I€1—èCA" ’a ‹Í1ðñ©PA@ 5ð1Þ㨠À‹*0"@™‚D€77¹I€ÏA[6Pj>@'ðߣ0þ¼tEfËÀ sªü'Ú˱,Ñ4ñŸ¼í€êV@s¹Pk¬Pá?ÀeûP~ó@ƒÐ%`Á» €&þ  M ÀG;1Yþ¸ŽˆÿB› $þsÅä?Íïâ¿wÔœà´ä?Ïâ?›pÀ²]þ¾áOó§øO±Ãâ?¼ÀO1)Cïîб €6:• ”øèÔŸØeèÞó§éO[ M©ñ#💋ÿt$*þ³Å‹üWìŽÉö¤â?yû€ÿÜû€òž–k€š×€´u‰ÿ|öAþ[<}%ÿÅ–]þ>òE(ÌU ~[¤ŽfÂd¾¦Dæ«5óE˜/É,;t·/˜¯Û4æëvNóa Læë²“ù†½×À|C)É|S É|Å%óÍÂomfÀÐùñöœò“ óÍBxÉ|ÓÛ.0Ÿ“À“ùÂ!º³d/QSr3¤¾KÉäI}S¡ì¤¾bîõCাëê›KûXPßõ õ]þV ¾KÇy¤¾K¨¨¯8‰&ö]:¡"öU³Þ6üÙ£ØwÛh ì{w8löÙe•†¿â¦ î‚þlj¥áïÑŽ“†?›¸À}7Õd÷³y{cßm»í~ÞŠÑîwóˆMØg¿"`ß-/aŸœ‚i÷ÓŒoß ™†?eù“›-´¤å¢5²üy/Fã_;Å—?;¨Òø'åÿbŒãN´þéDà§ÓFYÿäø$ëŸ4ÿI€àgƒÍvæ%ø)G´Ì…ê~Œ’±ùÏ3ÉO§‰$¿p²š4æ"%¬¬¦NZÿ¾þž·4ælý£€Èïè¢1ŸíÙ ¿â MëŸDD~:ù7Ñ$¿Ò€iýÓQ¶­<­•õO€_9» ñ¯‹K@~·´Heüs/!ùéà‘¶?í D~Ž ùùø"ÉÏvQÚþL%²ýÉDôó™ÑÏç²ýùi€~öÍ&úyA!úuºGÉåÓÖ]¢ŸY?ö&úùtE.ŸZH‰~:¶Ï§f ù|aýkÜ ý ‚ýÜÛèó)¥N±ŸB—áóéžE§O¿·¬ÕS„?Om„?/Ç„?u?ÿØÕÄ~r/û)äÜÆ?7È~Þ#ËøG“»ØopMûÙLFö›’ýšþû©“ˆýÎõÓø÷بös=„¿ë) ð'£±àï²að§Á ãŸNFlü3ì Û4üðH¸7àO“–àÛk³OÉ~ÕZ ö3L“ý‡"öS¿ûÉêDÛ_±ÑmôãQ¾ÈÏtCò EüäÇ…Cà§C‘­ý?¹… üBå‡áONµ4üiN0øÉ¥7Áo0§ÀϦ@pŸXÏš d=Ikˆõb¸~Ì{íè*IÖk<%êu{rõ õ¦}Ú€zÃk@½é¸ Þ,Ñ€z—7Ú@½‚@½bÿê]ÚôÊþ¤wIÙ…¤wÏ$½ût˜\’žÍÅ$½»X“ôV¡¶ ½{0B ggg‚ž]Ò z圠w;f ㉆ŽÐ[v»èÅÀkôVñPMÐ+kÖ½rЋ¡Ñ?q}¥€Þ2sôÂF€^Ћó«uoÙ œWN°ÁyË›ÝÍy>Ž!ç=Ê®NÎ+ÛKp^9Dç­â.™œWœ·ü©ÀyO ÙKγÓÍ{ï?4øåräƒúÍy圷äAKë^ùIb^ÙvóÅóbQ -9¯ØÀy¥%ÀycŒë+¶ºä¼=ÛàW;®Ï±aà¼ÇVMp^ñ>ç=>#¢ïÖ¶œÊŽûÞRŽ9aÞ-h¢}¯øg:Š$XÁ¾goØyqXöõò,MÌ+Ÿ˜W: 0ï)Ñ€0ð)Æ ”÷n@yµš¤¼GH ¼bå=ž~6å=öjå=ͼ–”÷؇”÷ʤ¼ÇØLûž6Ф¼GìIyÖ ¼G~c°ï žƒ‹ò”tHö=ÍÞ <[áhÝ+,–÷8’Ö½¡™Œ÷ØMëžIyÀy~CÞc'kš÷†Ây}yâ>y<¥dßÓ>†÷ø\ ÷8 ú|í{T÷"ã=¶¡§yÏ=Œ÷hgFÆ‹Æ* Æ{ìüBóž­Íd<»CмW/ïñÊÆ{| Æ+½ŒWFTÚ÷F!º–ï ï±Ë9-|4ä•/ Ÿ½Kaá;uÌÊ+£”÷˜àò¯%€¼Ç§i›òyÞòP“òÈòâç‡ò⹿.žÅôÊ{ì}Ê{„㤼ÇÑJ›òâïóÚ-}|\<㚎Z`á“ó5)ï9e7å¹mHyάIyå‰AyÍhá+—$ä=cÉ[s\Ÿä•J’ñ®ÕD¼Gd¼§ÿÁ¾W¼M“ñ“‰xÑã®â=Æ ^ù4ïÉ6ŸŒç>CÈ+¯È{äNÈó #å=r€'å= a'æ=6&å=Ò#'å=r¢yOš¸¤¼Çl»)Ï()ïᆘ”ç™™”÷Èñ†”g_RÞ#þä=ò9$ä…#,³€<0ž$2žµO’ñБñ¹±ñbS°>q}š ÿмwÑt‘xÙSƒ-}L#dïN&1NúLÜ$úÓÖ_ôgQBYú¤HKŸrÔÉÒçíð¯[gøç5ÎÊæ,üÓ\&ü; „ÿ4ŠˆSÞ òî´çñ¯„‚ÿŠ×(ùptî´K¾ðOˆüó©!èïÒñ鯊¤´O¤«|;/[áÛiAúv.=áßÙßNŸ}Ó¹“B©¢?ŸÃƒþnûÜ’þä“Oú+–‚¤?³ U]ä-ú³a’Îúü9ŒT¾Ê)ú“+½œ;Íé¤?¹¤s§­@t+ᯘ>Õ¦o§Ñžš.ÒüJKø³·€àÏѤ¿7ú3:¥s§B‰EVªþißDü³1“Î:Ôþ9¦ŠÎò_þyFçÎBSÀ?ÇjÑ»Ó&ñÏ–ºwÚ"A÷Î"CüÓ!;ñÁîrï4 ÿ<š48| þY‡øçN@ü³0EZùu âŸïD+ŸM tï´PñÏj1 ?Ÿ…ÿßE÷N÷$âŸçúwzŽ"ÿÙ‰1ý;í±&þS¤•Ïd,þs$ü;mÄ•§ísôï”ì­|Z*äß)݉ßã¿Çþ¼â?™D€:ÅÊÔO,-D@íÿ‰€ÚŠ K Pþ|"Àõvy¬p$äÎN¨…BÈs.òŸäÑÅ15ü;yï ÿtÒIüSW#ýÅâðÿtpïNù‡ÿÇ#üs%ñÏ~:Ä¿c +ÿŠs¤ðO'uòîô5À?í·ŒârâŸ?SøÉ•\î2Íþãdø³Ùð§.Mø³;2áÏ­GúÉÂgWXŸNhá³™?á. ß2¡ý¦)ŽìwÈßìçØ.Zø¬›"ös ØO“†ØOú°ði–ûË!ÙÏ~¤`¿FË‘ÐOpò“‰\ä§`x‘Ÿí˜$?õ=¡ß°&Ðï´‘m£ŸÌg4ïñNäWPp¿YÈO2Ù•üH˜ ?yHý¤Þ ô³-äw˜¾@~VÉùÉòEò³S)Í{^ù±‹üd±øé¸€à'#ø™f~ò¾ø«ÀOž¼É}Sä¾"ðÓ”'ðóaÀO1™?oüZñ℃µàwÒó\Ö=‘ŽÈ¯Yãe[÷´œ‰üñHò³]ä§o[e½# hþÖ¶3TXõvÒ‰gªäÿRIOÂúÿñ¿óU¼¦þî/ÈzGz€·a|—DPÂú$´wïñßKIÃ2ð^µ×J]*)u¡¬Ô¥×‰pb¿[Þ\%®‹e®Ë%®ë?KFû…¢]bA|'É-8Kuànaënåëë–Þïï\0$àûË);,ýK_x!4V6w¡üÒ­¢ÃÄiÛø\¥ªbj³T…‚OUºHU•«XÕÖòO9¢¬Šµ*_ĪêUª*hæ*5åߟŠx‰êñ5ªf†ÀUi'|*ÒEª©\¥ªÂè)íÄ‚OUºHU•«¯þ¶&öï]öSûŸT÷sŒü¼ì§&ö?»íÏ!õG¿¡‰ý'fçü2ÏþÖ\üߥ¿ÌÏ¿=L­ë>tàÀû©ã3ÿ·øÞ«ç·Ž~±CÞßúþ÷wAm\ÿö?ý{ çü·ÿåßß-ØÊÓÿ«þõ{g£8Ñ\׿ýãßÿÛ»­™÷ÕÔ^]™;ðëÝ…Äz¸ÞÍÒG™»[™»oeî럊r¿×…wˆf_µð¯Hq÷ïmJÙµþ‡ÿ¶ ÷ø*ÜÇ;Y¬˜\Ãqíá¨nï÷3§Ü¥œo;¼¼Ý¶×Þ^œ¡çóN£q>teÁ;~¼D’pöؤì|-¹m9Ç>Ô쑌.7Ãï^,vF=Æ÷’'ß½Ôò é³wgÔã`'ÏxÎw£ùâ_ïn—i÷d7öºsí)°ÇQ3nS~Ÿzž^,+~5˜õ'ÌôqM¸Ôgf s§ïó…`dÀŠÝò;3^ÿ{o“¬KŽ3gnå¥I"HÆ:j 2 Z ´ëàî@œ›õeeYY[d9¹‡oü3ȇ8lÙÐ5¦Ï¨ßÏî`‘×÷¶\ïÍX–Qº£ÅˆcZŽ>KLûZâ´pyTMZFïÃ]¬)g~9¶É»_Ôù²É÷^¬wª‰ŠCæ†÷Þ/[€eñX¡³oVÒæ;o¶Í~‚Øæ .÷°/Ö–é^tZz¸*ÉØxt!gúRç´å T 2ôÝÄòÎQÓÕ$ëwKì†Kƒ¥‘¼wËÖP‹õ}ÏÖc-ƒÛ,Ÿò¿‡š,³³m(œ–]ÂEïסù­h,kÜŽ=y•–Qg-/EjyÝ8aÚl -æ3j;¾Û|ª5·ï5|mdZwÀÚÀ /ö±Ù3l²7Ý.‹.\¦BÌ­Geµ‡n»ï `ª¯O7§åÎ/fíÚ4pšUíž›Kø±˜»}üöȼ—uعõôîæ‹¦së‘¿øj/Ñ´…ÆyL‹,Ø]Þ_ÝV’“q‡ß-† º›Ý4ÿ,H¤F;=“_¬¿n½÷û°þj :®å…-¼Çþ·ëù~+@F¶¨²m¾Ñè‹ù†Ó’@Fï—Êú«Ù¨Æ¶EÒ-ßfÁ­ƒ5ŸîÜAOvÐûІxsÖpýqÚj~`äzçÅ—ß­ —nyAvCß#ÆbÊŠ@‹iëZÑ]-¥æÔ6+=ë®nË-f>Ûm^¦å÷Xwu_Í-¾>-á?VŒ¬W6ÜÒ8c˲þj ÔÁÜ;2Þüw4ë;Ó¢Ú|¿–›wp~~Öµ­·Zd\¼6Öo·o2ñ›÷#eÕ dâÓæI7~;ùA´wÕ:«-ïÇ{mÞ+np¼nÝj7ÂVïâØÇÖñ¦yD`/OL87gª^Ø:«ð‹e&{í¼³¾Ÿ¯XŠò‡ê÷óÂÒ³û÷¬8T¬r[¯÷Ö÷ûð ÅÑlžÜ-Ïzo½°Nc¸Ö[íeóûiQ‡mÆF4lï«eïÏÀÖç­¯zàp\ÃÁ\{òõà««<–óð dñnûŽkŠÁÃ×¶â9Å­1é{Ýõ52‘½×çdë–ÞUß× –ÊM™o=Þ™+bdµÓeE‹±žj§-_4Ýñ£­°÷TƒãlÞO”÷TõK«3ä=õâ§äybdÕkãE€½§ò6QhèÍ>$zà»~ؼptU|ž½°uU u÷«ð"Àï&^®n{Ã#«ó{¼åö‘Õ«·ÄÙ¬Y‘Äë{W¹FÛ1²šFåka^xõèR'ZžYõUð:ÀÞUÉM^øÙÑå}Þáu€½¯ÚdÀeu€£³êWƒc+ºƒWöÞªsîu4ÍO$î…UöîÊwçm‰±Õ$Æx6ûZùï‡Á{«[ïúí²BÀw<ìä`hÝ:ôƒ¡õô˜íy`ï­¦nø ccZЉU½°­œ0Œ18¶î˜Êy)`[9Í㊱ÕnŽ÷;óËíñâµRÀ7î„_äœ1²æ»e)Â1²òM·JÀÖ_o~Ú¼°õWK,ô¢W¶þº.¾‘^LÑ·1B{-à=brp¢ëŒ/™×^uj÷>„KÝÕ¿S^ Ø»ëûªúàëµ€­»úæ×iµ€cdżÒk?ñ™÷Ñ ²|d]w|è®'";†9üÆD¸ãþyåS»£üö+<éá÷CåëÇ^ Ø'ƒÝþ:Y9B{-`뮞Éî-–±ì#ëûAˆ›lÕ€­»Z.ä‰m"ª~ÞfÍï·ý1¸Þº;æ«åSᆅ¦añ$Ö]7ç^غëâ¼c˜]pL…Ÿ½ð L¸bÇ+FW“'GœàöÑu¹Ìñ¿ÊÂ]J,ãþ‹ÆÜbA‹áX•Íö;ÂlÈ‚þE©,hƒüDƒXV”ö—@px%“hÇß…äÀq4¯Ž³Û¯„ÀaŠp. p<‚7@àˤ÷¯$ÀaÊE Ð °ÆÈ&à$@‹ н$ëø E!£’mLCíb`»1ÚoPÏØðØÈíJÚ‹QÊCœž_…ÿ,’•kÁÒÿ5#® 7ðŸIZÏ-¶eA€]£:ÐJ½"ä ØŒ#c`Ós#ö¶ø+`ÓûB´ÑN} @+ lš’›…T –ˇ)«Ë| í›UÓE`TŒR}PØL°FÜNŒRv´`‹Qª‹A À®wØì™1FÃG©Æ¯–Ðn¢+@€¶ç›"¾Ræ /k\¥ì*‘}”j=D€ùb[ V!ÀfÄA³—?ü§dº§?ÎDÀ² °yôF!@»Lˆž Àö4èU@3b„_°yM÷Âù0Évk <‚ÿì€Âþ3­6"nÈÍÆŽ 2ð_>< (5í€MëPÀ¼{@»7•l @KQ ‰˜Ø´lA´ž2'°iyØ(,m?±âE´•Ùó!@{I£w›Ÿ ØßýÅ•“[¸óM'Z7‹µ Ol%¶øÚ“þìGJ+è/ï%éÏú\´þšVTH#¡è¯i݃ôWöúkœ^ˆþL¾Å%ÒŸ}2ãI]ËuÄ¿æ1hÿº–¤ˆMdDüÓ‰ôgGŠÁ„ø—ŸkòŸ~üË'@üË×øg'oñÏã‚À€ùº’ÿ'Q⿼òŸ}ã³Fþ+ÇÿåWƒü×´øEþk…ÿÔÃÄMó[òŸ¾â¿fA‡ =Œ«èKþ³ Ýþá¿öÞÈ? þ³ø’€òŸ}.´`dµ(œØ øO_ ñ_»69ü×NLd„ö#ŸÿšæÖÄ?œDÁ?í†ôggÓb7 ?½¢¿&¢&ý5¬ñ þì2óÑŸ¾Y¤¿r Ð_dþ,'@ôgô¬ãªz½èÏjÐ_úk_ô³³‹GIôk ô³¨Ÿ¿úY,58cª–1¦ZTgüä×Ä.$¿&#ùÙU¶úµwTnúÙ¡ZPØÏÞØ€L°ŸM(`cê…AAð×(hþ<ð<~øÓ¤“ð7,¤¨ø³=x‚ðg÷²Õ€ï¤³ _ma`7^øU(Ðâù@“ ÀÎÕb mgC 4KrȉÁ¥Xöì\š©],“ûµ~è€Ý–»™ÀyÅ—¤Ap ez„dAì–O{ÚíŠ%vqàÅ÷‚ص8Nì"^r`Ÿœ;‡nq`ùQp ½e›©A1½Ô‹"¼¶ìÅcÀ²_Ýô œœû;?÷ ‚óþ!zh-¹|̲äí"£c–‹†¸1h•ó¾¯ EF€àûÎÈ(-;ÖÅ”J´º¤‚ Í)> h/3óbв7™5í|Ðê6‚6U}HÐb^‘´§ ÁÎï¿HÐf·ýƒ‚vl䉻ä#¢`ï¢[ `W˜Q0·! viîDÁïøUPж´d¨x¿€‚Ö°>Z`^9P°s öT‚ÖIèDÁ¼;DÁžê P0¯(Ø9» ÚUÝP‚:Q°lCÌm€‚IS¢Á÷|âõ" v)p¢A])pÐNð#v®Íó1;?®Bã­ù‘[ „ÂŒ0v®çó–mî·‚@hg}O@H=¦!æuI„yta'Šˆu/H„Öã‰0E"ìL Oô+aW¬ ˆ0ºH„yM$Âr !$a>pa^‰°l"Ì™Dh'«9"B®„$>øJ‹õ+ag,ˆ÷B@Ø;VÙ„’¦„¢´àA=ñ ­‹Ääš<¨û'ÔUŠ=“ò˃‘@Øçh®é,0÷# ä*›ˆÐ®9s¥5Ä ¡Ý­ö%B‰rB§ÿQåÀ²‰ðí“Á4 Âm<ð¹0)J¹Œg „ìA „z'„Zr+™K¸É„ïºÝÈ„\/K(”¨$(ù ÉÏbB1C2áV ˜PËdBv&œÔíÀ„bc1á-J$ÓýªH¸¤ ùÕ”ؤ 9ÃK$¤¢#=к[ˆ„8‘ Øn¬ê%rªH¸„{£ð Ç&6† Ø‘D¨Åa¬…åÂÁëàùS l8!1°q~,1° ÈfâAËÜFƒh"ˆ Z  0=ä8h¹ C-°M¬ÎK ̇@-0W¨6N¥6~ê ¶Ÿ8è/@¨Þ÷E„«¿²êÆ[¥ÀÉ%u…ƒJ£ jJI ðÉXÏP-a“›”R }öU LaØ4Ä“Kä)(°i&C ´mb N ´Uˆk ÀÖ’ù(JÖ6Í%vÑ$Å@›fÂAÛh¿’›æ®’ü©Z”?¬X®çJ Ä1(Jh×Ô%jÎ'!ÐæÊÑ´góh ù«@RŠõJÂ⿦h3é€6¶}"Ak F§¸Qû¡nIPáhû¡¿ƦN%‡ì—{‘(T ûå~%¾¿bY#ŒM¹gŠ€<¸4À®ØQj€œJ̽PÔK/ ðݦ3Ë•M^²št%jI€q7©ÿiÞ&ýOWMý¯4`\Ò‹(ÐnklsÿX«LPÜ7Ì´Ù}Á}¾zy¾à 4& 0N pP¸–h¹îËýHT瑘-”sÏÕ}$&tBÔ”Z`R(%@½~’»IJ€z$jõKà R, PG'÷qÄHPópbŸ}cO  NìkÁWûÚoØ—ª€ú2’ûšX‡B`îÜ—s }ï{òP¤¨M@}M<)P'#ê¦JÔúòNˆút'H}M@.0ƒR©Zö”ÁGâÂú`—°S¡ƒújVVuu™5òIÌûrÇwŽ©Øfå˜c¾„@õ{ zx‰}ÄïÄ>­ïKlXI!0·¡¨™Ž„ÀÒrþ€üЃςûÆ£P®¿w¢ÀÏß®V}A{ øÕmüüÛuÕ@Ð|K ~ãIH ðsUåžøù¯ ¾ Œ¬'¿?ÿU`2À¯nàç-”¿êÂó‰M©ƒØgrv„Žö5)°Ï'l ÊàŽ¹¤.Üç7 8Ü7°1ç5Å$p_ýUpßû`NÜçÛÜ•ûŠ8î{·:ûêŽûü)ÜhñÁµî8°¯\(¸o<‰¡Á}¾M¸oØ;-°\'¸Ï[@cÎ}>ßA_]‹8KpŸ+N•û|\pŸ· £ë!ûü|C¥öù»‘­RsAìóó h—È” bŸ·Dø!°Ï[¢§H Ø7Ì# ú•Àƒprßx$V÷yCˆô@¿÷G ” ô«»¡(ýZR lR ƒý\@Œ%˜Ô¹i:Ai©R |?=O9^R`fÍS ܘæ¤Èð2I÷Á))Ð$S äúA¦>#ñÏœº{HVaoA™RÖ›7‚TÅzãl“õgJýS’’RÿîIE’¬—¹‰LýË0O°ÞÒP/ÅO’Yoiæ¦Ô? Iû~š\Ö>ŸkqVÜÛî’RhoH¢íÝftü¡½¥©ioŒÃ˜Sfþa¦ýqõB´7*‘yJ$!íY]à 0ÀÞ`–Ô¾[§KÚ³e´77DÚ»IÚóLÁn ½±uÊ|·Â˜|F 9 à›§ â[Z‡'ñ-æEˆø.Ɖø®Láñ]ŠÌ#ñY ¼â@|—¢ƒ‰|W¬“ä»Öä³zYfN>‰4g2º.ò]Ò¼ˆ|v€oÞߥ7Èw)nÈweÒ\PŸåÊÞŸÄ¿Kª&¨ïÒ<ŽÔwIŽ!õ]|O}×P( oH¤Ø7€/±ïÒ2 ¡ïâäOÐw5&Nú¬%^ BßäHÐ794ú.¡ï"8ù¦BÙÀ|“¿˜oêëæ›7¸´>Žvb¾©C2ßÔ«Dæ›ÌRóM½ýd¾©€u2ß%YŒÌ79‡ôÑOBÌ7 OæËœj2ß•2˜/wäˆ ¾É¹‹ˆofPjßÜJ\ñÍ…üL_¦€SèZ:$ñM}(ˆ|6‡éäË‹$òåÓ%òåéù&í„|Së”D¾©´S"Ÿó@ŠòM}k‰|SÍD>sM XòåãòMWù¦^b ŸÙÅã&òÙ÷µb?}ZDV½bˆ|Së±ÔNä³1ab?ç-MÈW~Rß`@‹¤¾1™‡­oîÌô‹±u2(WZßd@´¾Éœi}z4ÒúlÏç“û7°,*©o2˜FRßû!Å|ŸRߤRêÓã“ÔgßœÒ7ùE¥o*è•Ì7˜l@æÊB£Ô7•©o†D2_~î¤õÙü#àœZßd¦ˆ´>½“Òú&—¯¤õM©WÔúŒo¾©y»¨õM…SRë›_Zßd´´¾ÉUi}vÌPa)ö N %ö évûÌ:5Àbßä:¢Ä¾!AbŸ=™û#öMéÜû†Þuª}c#Wjß”Nµo(s“jß`¨¸Ô¾ï‰}ƒùŸÔú³q¤õ)ôNZßÈN­o(2›ZßÀè*©ope–Rßü2Pë³iô ôÑuè5¦Ü7¸l-¹o(¾—r__:=È}å„!÷u­ýPïë’4©÷wtD„Æèšû¡Þ×òK½/#¨÷u½ÈÔûº™z_ž3õ¾.Ñ‚_§#Á¯ëÛÁOá^éSEþø;îÝ)þù¬¸ò`ÂyPÊHð`ê’ª, òàdjÅ¿$Dð &gr‚á‚…pðâoE÷WŠŠÀÁû *4¸(w' &ÅWø’m47ìõ ÝSf, Ae3‹·à8h©û1ÊÛ4x½HÜéœL÷'N¢‹ è1¬)“òà”µp¦ œìÂô§ …¬ÝÎø‡dõuýÿ´ª@1¥¾ónOÚɽ.ÜG<šhŒt„Góqáѽ ž$9á‘Ð }Ò Þ—l‚‘­Îá[D˜î$B+Æw>" ÝZ¹;€ð0ÑA@ˆ,t€9Œ˜' P„LÂ=`t:2¹˜óÈfý4Ù¿™ÀX¶p@'M`Lkù•(xäàD´Á-ð€QBQðÜŒ& n%ÐÓlF0òt’ŒQОå3¿œ(xŸ(x´ü(½ZiÃφL`R3¤ Lâ+M` ‚÷2ÑFN2ô€QT¹<`Ò«…0\À"ne¦ÌÁí“ Ì¸ðüe£…E™ÀÈH‹ ˜™&0|v2aÎKšÀÈï@&0ܳ@ðhvG<\šnæL¤ L°.q AÐLà% x¸Ê%4ó`)M`dÌ"˜®´E™ÀèØ4áʃ@Pæd"Á-¼% î%[àæH+\L« ÞŠ?# .öz¡à"¶ —r€‚Kñ}ra–€\`ø„…‚t„ ÚR7„3àmCp´€—R¡H‚2¾ ÞœcŠ—RäH‚fÓ^ Þ$‚à­ì7‚àRî%ApñË*¼ÿò€a¼“@p ´‚7gÙA+±·Á%§"€àb\˜@ðÂP ¼’ Á·¥ý}/ÝcràÍÅ0qà­øGrà¥U‚ ÷ŸDÀë¡) @ðR`2Að:È”^ p&^IZ ÁKh¤½š@p2ô89gNF!¯ &^Â@Û$1ðbh 0Ц£÷'ìs(²š8uzÂÀ‹PO œ\ë!ÙY‘sɈøÂÙœ‹ë„À!é”x+K8ô¸ J¾%Fbmqñ~góíëÚê…%î^|bÙRݸÿùïr+nóï¹x¿4àá(y„lI·l¶¥ƒm¶¤[ö´ÊQÁ³¥ì me_jÉ}yÁ›SÁ³%÷ŶÜW¶ü§]¼§×êxþ³.Þ[†²ýÖü§ý;ÝtÞ~á!-Õkøç{eoŒMÕ?iW2èÖ®ŠA·v¥­¸«²w•ÝÜU5èæ®r+ìªn¤]Ñ¢[{J‹níˆÛp?¹‰v#ƒní§tkGÚŠ{*iW2èÖ®ŠA·v¥­¸«²QöRtsWÕ ;{7·Â®þïÙmŸÿ×Åû¯\¼ÿ•¯ó?~ûÎþÙ·øÚK~Ÿÿ¼—þ¾¯¿íŸ=GTCøÿ¯}öÿÎOœíõMÎ;Ù˜Úã¯=´ß;kåWÆ"v)Ëxçô>÷¥ý 3ŸÎaUW,Î@×LH<4bÙ2)õÞwÔ÷UË9^ðN¢Z("\Ýpé¡Ù\t@'sµÄ8v5Â&Â7²_\˜™Fܧ=D›k¹Õ%–áse0Ë{P_§÷_ù´ÒãyjˆÉÛ°cLÀtÍæÁ\ UÜ6a¬ƒ‰sÆ @À÷Ï^ˆpªV‰Ñ——iïÓ7âû¤ïôprv.{ç±;¬iâóžþVˆ\.~ïâ°…93FœÄ û?—xgœ;¬© ½xZ7xôó³X·œ¼ Îí‰ïL|ÙB£[Oûœò}:W8!2 òé{8!Bzx #´å½ÝVÉì=—XìzéàòIð¦@ìØ†É<¾èáÄ ë¹w2¼|à0‡TŸA¾,æå”ÒÙôEÎÀJmémñNúµ¾W·by‰ëñî›NGðøÑ{qî‚È¥¢·å„!8u÷mZaZJWPNòÜ$Ò'ÊîsÅjÇ çÜ<ŸG$Ô]\KÅ®XR½¢áòÅÕyèV÷¶˜–bð})oX ƒWß÷rÆúÓ$‚eW¬JÇ\xEÜÓ<´”x™ÛûéAØ´rÖM¨È_Kë¥7ß–½”¶ìïë}{7•õû G¬.aåß=1}¾.Gl,½ÇgÅ-Pc]ÕñÐÍØcy k,Þkú¯´·v¯në¤vâ±é0î÷Àb¯UVæÝ*4––tܪNÛg¿Ç·áGÆæ*¾´d57c›(ý›ÎžǾ?-/ôûÒÒ…Åœ÷_#––ìMžÑâk†Þgxlñë)âň\qôEXë§ö˜âÛéU5]Á˜ì«ç~(ĽL«î6êrÝôjX±ðÝÒJ·…¿0B¦ ó¥¥lW,3€ÀËëÞ½,M÷Ë•L/¯{9ÙcAÊË랺¤gõumÐ)wÙ¢ä?’ iÈÅ +Æ4¸ž¦’ ï»ß®A@òº,¡])\x]_øÅõúº± IΩÉ~BêõòºÞU^HŸ xWå[ìv½«vmsLjªçàv½«æ¯ö„bƒ× ìzWµOZbHµó™±ŸÇcîʺu&Tÿ‘ås{_e®«WØ=³,y[…Ý謴§ñ»»ÞÑËüZF¬úzŠ—ØÞŠoÝe¶÷",®{…Ý»ŠïØ×Ê’¸×× yŸs¯¯ëŒ\ðúºsŃònæõu½»²ªÕ×îJ½Ë+ìzwµc?‹è0÷£[…ÝX æÑÇÜè®±öïv£·r]Â*ì>§ô¯°ë½•áQ^a×{+W…¬Â.zkìöô?p /[° u/°»Ë‡î²U(ïª: Zñ®Juîm‰1UC€××õ®JbòúºäŒ¿º:lû±ÐÏeƒ”!.)óÕwÔð »ÞU¹ÒyÍÝe]ÊV¼«rA÷²'í£*^½Â®wU.Q^Wë(û4c)Ö+ìÞñ£¸WD…¼3 ×^`÷Іø{bTå2º•×®ÊhQ/°]òÕea­ÞU9Aö»k…ôŽ“YU‡Z6FU&û]6Çm£,ë{…ÝkG xE}ítÖ=[…Ýybäm¯°{fÎ\¬ÀntUzì{‰Ý]ÍÕ/ûäö'.Ý?^b×ÍÀi~ùÚ}¸ƒo4`dedÏuÇ/ z}ÝZ/¼6¯ôù/—1½¾®­T¼¾®Ïÿx¡$‡+ ñò[…]뫲—¾lâÞ}éøçv׈ðt×h.+?à‡gv}Ìl¯°û`îºb›;†ÖË¥h/¯{ܸSx+¯kWŸ¯ÜѲ}\ݨžp­(½Zn¸Y‚cé;zÔzÌ1­Ž… g¨Õ×î1¬.}ß¹r"¹è_µÌúE˜EA¿} ô€~^{%˜ è·é±Aô‡OD¿q(Úý†…(øM&û#@û‡qvd¿ñPÂ"û‡• žÐ35ÀŸ¥—`® øó4š˜gþd HøS–½àO„¿Æ˜ÁŸÂ‡þd (ø3· $èOŽÈ¢?™üŠþ:KÈþdl"ú“ײèO~cÂ?Zøˆþ:£ãD£ºð¯S¾ÿuƹ‹ÿä”-þ3I´×à îâeÿºž7ðO&oâ¿N©Bü§h4ñ_gð£0/صd@좠µ\ÀÎz`çzP~rÀNß`§ÍŠÐ¢Â€wÀ®7 Ø1ƒv­ŒµÖ+ì ˜*£GØ¡.ìüÚ ¥Ò-¾/v þS¸¡ÐnúÄì4qÊÑJhî{ñV;ß…€ùæåëGì àö+Ž(‹:`g´p 7þɶPøgÛÇ'ø×À€ySˆ]âŸì…ùŒˆ÷ð¯3ŽIø×)Ñ ÿº¾#Ä¿N™YøWÎø×i:Nü³M®þåÍþu*È¿NAVø×x#üë µþu­iÿ"²Пºá¯s$üõ-düuæ‹ þº¾º„¿ÒøëHDûu†9ˆý: î ¹—‚¿~ð5"üu; þ:BºÄ~ºb¿Yèו.ôÓ+!ôÓcúÙìŠcýrÇ ?É­"?}+…~ìý"¿Î|3‘_g‚©È¯ÓŸä×A~} ô‚üì7; òë˃ü:3[E~ôoøufµ ü:¯~A%?ë1Õ%øu:ö ü:³I~e??}LE~2hùYËò+Çù•=ƒü:£¾^]‚¿Îyá¯ÓfYð×¹ô(øÓÈ#øëLïüu¦€ þòéþ:—b¿ò#°_>²_y5ÁOU6~™*¿ì§¿<ÀÏ:î høÉû‘à§!Bä§!Bä'X‘_g ¯È¯3GQäט+ÇÒ'vìë±@æËÞE擟ª˜/{?™¯³Ú§˜O.º‚¾ž èë\oôÙŒ&ÞBŸÆhB_§éš ÏF£}òvôi(ôu-£ú4}ôuÛôÉISÐ×™O)è“‹­ ¯lè£  ˜O• Ä|åà`>•ãö©‚°¯´A}œq‹úäüIê“稨¯1gJÔ'jõÑÞOÐ×øŠÿ ·lq_ÌÝ ÷= k˜ä>™?û²ü†¿N‡íTüèš“Šß­CòÈ$”â7˜Æ(Åo$“Jñ›R(ùMVû“ägd7*õyž`d¤¾)DõM-“ú”ÁFꛈ,ôM9ô)USÐ7E:„> J‹É;¡ojjF蛚<ú&3Ó}“–ÉQJÐ7ù’Šú&ßAQßÄœDÐ7¥‚ùfÌ |“Uë|“^ü$>ÿ¤£!¨Éù‰orùHħp5ßä*”ˆoÒ—JÄ7m/â³¶ëC|ShNâ› Õñ1«UÀ7A|ÊâñM©>$¾) ˜Ä§iŸ²XI|Jbòå£òÍ„7 ßd¯$ñMf¦ˆø¦fº$¾©™8‰ïýä<ßüMñ›ÒsI|Ê=ñM:óˆø¬%î‰Ïnqì™Ä7.$>EŠøæ’Ä7Å$¾|#}“F„‚¾üŽ8ôMz²ˆû¦Ö È}“yQâ>¥•Šûò]#÷)û]Ügw8–È}“EÔÄ}Êè÷åU’û&½QÄ}3%FpßäL[Ü— rß„±oÒSاnâ¾ÉðbcTÅ}SË|ä¾yÁÞ@ÜgÝ.ž'¹/¿ä¾ünü¦4*‚ß—’û&Ëè‰û&OÉ}Ê5÷éÞü&ãc~JØùMºâ‹ü¦’_ùÈoÒJä7¥ßý¦t ¢_^ѯ¶ûMV(ûMÍœÉ~ &ûÙn0ªjeì7Y#Vì7è§ü}¡ßHÑìg-ó#úÙW+$>²Ÿ¾cb¿™JØorIFì§®)öãû(ô›ššý4¹úÙ« bXÕ ’觉ŒÐoÒz„è7ÅD¿ÁÌ7¢ß ñ°Ð/ï8Ñoih@?M„~C 3ÑOã±ÐO_ ¡ŸýöG*Øo$ ‚ý¦(ñoÒÝOø7YaZø78•þ ¡2ðoÒÑWø7èIEü)êÿ”/ü›CÒðoèʉ´MýÉãG8¨a™?,”qQ" ÝÖ„€ƒß6!àà²|" Ý>„€C(OƒÒ pèµ%:Ê“-%D€JŠJŠr¡1 P_-  /’ék.4²Jä@%â\ 3w’™è”¨^E#D>ð_×'Šü'Ÿ-ñŸ2á €ƒ˜$Ì5" • t`ž P…'2œ"Ì_Øc û¼”@ ô”.ñ_z¢*SzÂýSÔ'ÏhQ_c]QŸÂ…}ª÷%ìküœ ûè¯.êkÉx ¾öõ5­_Kë£ÕŠ´>I4ÒúbþI¡O“~ }¹‹ú2úX·'…>µH裕º˜¯)tMBÓ†Sè»$ýùd'æËó!óå}!ó5†­ú×™D}*ï&ð³7>J_9z€_“(Fðk €_“jKðk\ú'÷5Ü‘ûšŸÜ§*|â¾F q_ã¸'îkš‹“ûÝ~-¡àgùšýëÙ›HîS=q_î˜Ü×X.ŒÜ×XPIÜפh‚ûèÍ-ìË+ ÷•½€ûJ ¸¯)”ŽÜ×’IðkŒ¢øå£"øÙ 7V~~f(¿¦È]‚_ö!‚_£DLîËþ@îË÷ÜWöîË×ܧ â¾< ‚.}ù1"öå+LìSÍaŸÊûrÏľìQÄ>{± îûTRØ—½ŽØWö ìËï±Ou"„}M²'±¯qöNî˹/wîk$q_cå0qŸz/±/@}y'H}2)õÉ|]Ô§.FêË/ ©/ßOR_aúZˆ‚úò­!õ5Ö õéWÄ>ýHا;LìÓ öéÂ…}åHÀ>^¦¨OU^E}º(Q_i9T%>ª¢GP_^©¯iêFêË=“úJ ¨/EêËsõ5Eí‘úôM'õå%õéØ×¸.!쓟¶°OÎú¾–Q¦Vʰľ¼Ä> m¾Ü±O£€¸/_r_ù¸/o¹/o¹OóqŸº¹¯\ÄáÀª‹x;+b0Á}í7îË{JîË#‘ûV…}yzľڂ•f:Â> B¾&#öå%ö©K ûò­ öµu°D}ys@}*Ü ê³´¿ º€¾Æª„‚>™¾ úT…FЧ’Ì‚>MLD}-åEPŸº8¡O…1D}*Ò êË7›Ô×è=,êÓ€"êSMQ_cÙ?QŸÊ- ûò«DìSí b_ÙاÒ}6”µøØ×È$¾&]Ø×˜l!ìS a_c 3a_>bŸ\ý…}Ma¸Ä¾Æ´za_3¸ ÉاÊ!$¿´&ù¥³~*ý ¿, ’ÚH‰à§C‚_V %ø¥ï:ÁÏ Ò㛩”bžÌŸØc öL):ÚƒAMÂÃEŠÆÇ"ÂÞP Ÿ4¾ƒ‘ž°'¯KÁÞE“˜ÌêKQ °w§¢Ç¬>MW•ÖÇÌ4ÂÞRh"ao)ô”°·4WfV_"³ú$´0«ŸY}Œ­@Vß3fõ5$UdZ iŠ÷=?Å{‹ñ ™Ö§ ŽÒú4÷SZ¿˜™×§œ-åõe óúìC<¾à½M7GñÞ¦·¤xo1=3û4‡dfŸ.¼·ã­Ì>|y3³cdföÑ‹&3û”¾¦Ô>f®dj_Æz2µOÉIJíc„·xo3i'Sûø­ïÉÚE¼g¯ILO |ëQÄ%€oÑ-PÀ·Íà³g~€oñóBà[’NI|kñŽ’ød$â[tíñ-®ÿ‰ø#ëE|ë‚‹ˆoÑîLÄ—×@⻸Ä/⻤‘ød|#â[J #ò­pw*È·.hD>Y× ùn%Yù–ž‘oe`©K}úl‘ùÌr­2üÖ”ž æ[¢w2ß ;C!ßââ‰oÙ"lP!ˆo1#BÄw³´‡ˆïæX!â[ɉ >kÙŸO;ø šñ-é­$¾…´ߢÔKÞ“•=yÏî.2åÀ{‹I;â½Õ¥áøn¦W‰ønéÃÊîÓù’ø®çG|ç­à ßq£ ¾Õ¤êø­†D|åª@|ùÒø–ø„ħº$¾›ÝYÄwk<ñÝðÝ솾;Õ8Ÿî±ˆïfL³ˆïV‚ ‰O7GÄw+X“ÄwÓ¶\Äw3Þ”Àw³¸€ïN™ Àw³Îˆ€Yàâ½›Ñ(ä½›!êâ½[bxï¦dú$’’öFfnÐðSGÚK¸7XEM:Ÿ¹¥ó™ãñþè|)¾Rç*þ†+¶00λb }“E´Ô÷ÇÝ¥‹ú€Ç“™™¨r`±e!2T$90³ìÀëp9W ÈŽ#܈ðnxÅ·ÄbàÖ\xd±B Ls ÜŠ"Ê=:1ðA·0P‰¿Â@Ëœ†¨F ` F T.µ00 5ˆy ÄÀS Èïmb Œˆi–@ L»``º9Èàåâ$ x’²ÀG(K”·©8ÐRŠÛ×âåá“"ÚË‹e&,Ǣŋf’â@Nðeñ"‘/RÈäðÂФà ¸‹/ò­¡Å‹Ðdñ’¢^PàæÒÿøísûgŸäüigýù™þóÎúû¾þ¶?¶ ÷ûqûSƒì÷nüÏüçÿ;õ_¹d¿ÿŸÿn+sÏyŠ©uùßÇ/ûÝü/ý²Kãÿsý ¿ìÛ¦4ÏŠìùs©“u&Vؘi#»Y›1žé¶üæiög\þ¹]¦°m¨ËÜWä8½³ûÍ[;Ñâ`ÿ¶<6ëÎH©ûš+ãˆú·ñÈ8ª{·Õh¹læƒÞ6ér? ªM÷;·q? ‘ÝWx;{ÍŠMl‡Å¶ä¶*)n£Ä€Û„ÝX'†:v›Ž²äãè|Û4²÷bxñ¶¯%Ó™ ~¿/2¢šÿ56½¾éŒŸX"†mÀûm áéP”¬nÓ¦mŠ<”~Û(kõ&¡ï̶E6ÔÆÆ·×|÷º©ÀÌû>nÝT[^.饆Émò»gCq%ùm9asÛ&é^N”yM·….<5¥ê¶¨φ¢”ò¶lŸ!« î½._Ž˜ƒ‰+ïD|DAQJw÷ “ÙwÏ›'c:©Ý+=Éõ>°† ´¸{ëx 'ŠÅéØÂ؉Ç[dá*VMqp•ó¶úJÙe¾Žw[hQè$ Ã{GÚ[Vî½m5“É‹>Êßx8cyNÿTùõ¶U:›<нC&¡ûmë;7RñFlcCÿ*Y’÷¿¢L¢»mÁñìR°ûö…û޳/Õt몙=ø¶<¦•{l ц³ƒÊümeʬ«"ÐmÖ©÷©WáËënB…5™Û¼]­«Z¡O½Í®ö¹êM¶2eWÉ€¼­4ÜñÛžè·&œq »}ÿe=uP•»­Â Gö©Ï«ó¹"Òeî'ÖÊ ?¶,¶âvù¬ã¥á=õ`Õãm9ÑY™ øö—;:+çsÍè«$«ûy{­÷U®Ý> ô„QÈ&÷cžJW*^œÇÖÆ<4þ<-º*ým9|/๣«2žãí»³œÈj½EWEGXDë=•nòËCoWÆW—‡u·¹…]wª²~ëò ¹O±[ë¨ʅÐå†Ê¿T[~yÜ»LS—UÈõCóàrm.4.+ëó_½'^!×cêw,/«kÝÕŠzÆèr-Þ>DË#½G`øâîò¹Ö[õÙ²xë­y(/ë&ÁÈ X¶”&˽ž-ÙyùË$®=ÃØkǯVŒª  ®ënŸvÅÁ­D®gÂÃñay‰Ü;nz|<¶'®è\¼@®;¡ql3A8<á°„½¼B®žp˜²ÐO ¡óÝ:ñÎg¡¡eå¶ßPžž/h 3.nºÕX‘køë•µ'Ž8ÿªgvâ_¸Wü£G±øoÓ¾Sü·¹Ä+þ3‹ö'€ ü·&,þ;4X"ÿ •!ÿ ý ÿ#`ÿ ð ÿ½;’PÁãÊÀïh†ü7.™“ÿÆÃWü÷¶ Jü73ä¿w›xþ{‡5øïý"ˆ€o –Þ‰€ï¯0Rdz|€ïT-DÀñÐ}• ø¶À盘™1„@'ñU!°1U†8z¢¶Öˆj€À†%1`c8p<4H6=p0à» ¾ bÀÆ A1 å£88°õŸ ØX¾X ¨ÔUA`c6zŒ …PA “ŀʮ6~KÉ€J´6Î=B¸ ° ù òi¶<@ 2ž Ó1 ¾(b@›³£!+zSˆmhD€rJ6ÚJ‹u¯€áD!úkÆI¾¢¿v#2‹ø×8¥þ5¡ñ¯mdc ÿ=S„²¡þ5&¡ÿåCៜ)…M Gä¿\´"ÿÑàRø×’4yÄ?TÀ–èبsdµ°ÑÁYhqì!´+Á` À•H€ßO ýj°qM¨©ÐnLÌ* €vyÀÆì`ãÇHh¡"ýC€MÓ6 m&6:^“›`‰X6 lL–ý‚UÏ@ Øèõ,lŒO6ºm‹[R,°1MA Øè.l¿1 Ý¥/6Žb@{ 1]!6F˜‹sÌ›L´Bë16ÄÖ ›Öˆ€MhNÌmHâ™(°!Û&!Ai 4£6šÔ óyó¢MLO´C˜6. [²$ °1ÒW(ËÝ€ÀÆ¥BQ \zE¹[R`»9'êÓ& Ì>D Ô]Ø. Ì;A lôé6­nË‚›–yHKÆ¢ÀÔOl¢%2`Óê°¡~…Ð|„'šYR¼÷D@t"@ÛkJæ×Øt#l7‘¨Ú(@£ïm€°1PL˜“}`£?5p<úÖéo þ‹*ã„¿ÆÄ%Ñ_ã”™ôgC_|ŸHÑf¢?%Ì‹þ,#pJúcsÒæ…IpR'ü½S>¢2áO¾„¿÷š¹nDø³<{@dÀß»¾e„¿–IøƒÅ¬à¯4ûYÞ}¬,ýdéöÓZ„Ø@±Ÿœ@’ý´Tö $û5>j°ŸWÿ‰¥:°ß;å‡-Ùï݆Ÿ¢ =xbŒÿîÙEtB€‡ž "@›ùP/|8Á¦ýðEh‰{€oKû•ô—E¤þ M¾©þu6•ú7)õO–Tÿ³Ç¥þ ®¼PýÓz±Ô¿”•¨þ N”¤þÍ”à þGrÔ?+µ‚‹Ô?IÍóþ€28•¨|& €“™[åÑ)pâ)pÒîJ àd0*áoò(P²“5l–b ø“ªÀÉØ~Áßô/¾Ô¿ÉÐK‘ßdà†Èoj¡ä÷Ž-1ùM.Õˆü¦æþ$?å7‰üh!,ð›Zg ø™'*x ä7ùeùÉ ˜ä7¼*ò›,LòSîšÈo2«Eä7ùÑùMú Šü”0&ò›ÌÒúM}úÍL4±_¾„¿É5=ÁŸœKytŸ݋¸ ÒŸàdb8p¦ œbr  €²bNšîåY-œàœÔ€“fÀɼUàqeÂ+´IáŽ=ƒéÂ,œŒ`Ê[Z˜˜]‘8),NÖ„ª’€Pÿ"À üNiF’Ù€“Uœ€Ê{2ÜL8‰÷À<6øo&X‚ÿ&Ä“«”â¿©ùojIžü7o.öƒÿX9@øg×<ô7YPJô§2¢¿rПì ES(@ú›ˆÕü•Cþ¦Øð7i#ø›R˲ü©c þÔë²Õüåùþd#ø“;?áorºMøSéÁßdVºào2ÅFð75—&üMIn€?y¬ þRø$üMÆ…þ4þò* “5y„¿¼¤¿I•ð§ï†à/à ;mIe€?}vÙ[“Ñ8‚? A‚¿I[DÁßLQð§áDð'Ûë”%vþ&Ãh üå÷†ð7‘v#öS5 ៾ßÂ?•˜ þMš£Šÿr¿3uDàŸ>Õâ? áâ¿Éukñßdb³øoJÛ!N&õ ³oó%N²ùohYüg‡º+ÿ•hòß„oKê’ï©ÿq…_˜1@ÀÒÌ`"àà ¾p2RM8(ô3„ X[V#ù–¨˜#)€ ´*:Gà` .1`i-Š‹Aˆ×% ¬(WnQàÞ“åà/ ÌPzÛHƒÉyRe[/ph¹ à P–Aã\–ü í$¿X¶®äÇ ìŒýTd¥Èþ‹ÒþR#úÉ•Nè×è…Ÿ±ŸôÉØÏlaìg‰ôäe„eè§&l ý„G†~ÎúÉt² ýäž¡Ÿïd~à/Š»•¸OÎ&÷Éõ\‘Ÿ*þ‰ü:³D~%Æä×¹>’¡Ÿ4aÊÐOFUdì's—3ø“+ü)xbð'¿ùB¿žšÍ‹¿ü)ÆPðçd°%c?YŽ c?5§Wì'S3öSÓjÅ~Æz?éÞŸ“d­ÀO©¨ŠüL¨dä'£V2òS/„"?Scä§äME~& "ò“®ÆùIße…~2),C?ð‘¡Ÿ0|ÎÈO ÞŠüÔR€"?¥ˆ*òS¤ÈO½ÓŠü”^ÇÀOVxÍÀOq±?ùá+ŸÔ)3ðøÉô~2ð“ ïŠü”þ©ÈÏ+ã<1D%á2òSÏW‘ŸÊ?uQ ü¤p~2_3?9¯ÊÈÏ+ã<1D)|B‘ŸeE~êtø©£ØO&«+öSøÈÐOÆ ô“¤˜¡ŸŸÈ}ª¨š±Ÿ\HVèçÝHZ‡'œI†~j2©ÐOŽgègþŠ¡ŸšÜ*ô“£M†~v©ú©O±ŸÚb?…¼ŠýÔT±Ÿšq2öSqVŠýä½`ì' 3øS!S þdÿÎàOæ¤dð']à3ø“B&˜2ø“¶²ü©›£àO–ÏàO=>*øOÁŸÈÈØO.Äeì'mûIÓ—ŒýÔýcì'1^¡Ÿ±l­¸O~ð3î“~»úÉu” ýäº"ÁoX'E ÄÒdÀ(C?óú©îAðË ”B?õÀúÉ®›¡Ÿ´çÏØO&´gìg' >S©‘Fè§ÄÅ~Žóü”ìQb?yÃûI‹ÙŒý”ŽBðëÏæaPսɨO¼øâ>.Gfèg }Ju™Œûä5gØ'‡öIåEaŸ]Ã>GDþù ]…|ƒk²d¾42Ÿê0‹ù4UóeP*ƒ>Yk(ƒ>9SË O¦7dЧ`ˆÈ7m¨ OdÐçx’AŸ´aÌ OÁ8¡¯KLôe䪢>“èõ©àzE}JƒVÔ§Ö³õ)õ–ЗÁ¶„¾˜‹øº–yH|iò©å_×r‡B>Y#EÄWvÌOC_øº¾‹ ùÔº…B> ò©(s¾Î‚¼×Å÷Šøãïuã‹÷:…ñ^×™¼×©‰÷:çw⽞*$xuAþÄ6;/â™*âq%Å=.8$âi‘YˆG µD<Žj‰x’B„xÏCñˆ—T%S!^Á52ƒÄxž/Ù}ψ'Îâé†D¼Zf÷)BU”§Kåm©pÔ÷øË?•ÊûÝésæ€Åÿò”ÎÆ“NDÆë ¥ãuåS‘ñ2V’Œ‡ \M“ðÄ5$¼¼ D¼®;^gð¯+¿‰„וÁFÂëŒûäu®d òº¤ZA^£òò !äu&Ïò:Zy]Á‡„åu†¢òÊy]j!¯§f Èë’ËÀx=%60^§©¯3”XŒ§³!âuÅ‘ñ4G"âu:ññr ^g7 ¯3Dˆ×¥÷’ò:]Ey™¹EÊë¢sRž*FflgÆm2¶SsdR^§G(¯kÉC ~\èåõ ,å嬓”×éˆ,ÊëŠÓ#åeþ”0k{yµ‚„y–`¢¼ž$Ê댚åÙÛ>>~=Ù”§1R^×b)¯‹¿Û)퉘×YÕG˜—óo’^iêu–*êuÆ‹‰õòœÉz~wJñ£+B¦ø¥ê†¿ݘâ'ºR€§b±à™ }Lñk¨CžžÊ V„g""#U%Í(O…Þ*ÇO  óTªrü´ˆ©0O…N(ǵ²2ÊS+7Šò”ð«0O©ÇŠóÔ8”qžDªˆó¤¨ àó¼©o”'¥¥ŒòTPª¢<9_Ì(Ï$7fø±ufø)W~ZèÈ$?Òß0Î.ZŸO+JÏH­ïgžß“pF”ч@K— ‚4Q 'ª âƒ_=e CTÚZzâ1+ÐS2ˆ=Ó žÉ© ô”L§@Oª´é^’ Ha„ ¨ZÎ ‚ ïNd K:½(½IN/Šq Þ7OI‚Jü À¤ö1Ý=Õ>ŠîiõB&’ÕË–¤æV/Ì>Häúaª}çg¤gºq(Ò“Qá)÷éñJîã¢h{w%ø)gS±ž™§ÈXOö¥üªeü”c¨`OVW(Áž¼çüD´üäêAÁO« ü¤—2Ø“=;?Y•HðS˜¤‚=Y =?Kñ“ÛŠ‚=±Âš±žÊ_U¬§n—b=>[c=lŒõÊÒ óÆz*5c='uBÄzÂ¥@O¥ d 'È ôTÞ=ÄÉ8Où2)ÎóßèIë‹ ôÔ=Ï@OmÃ@OÂIz*Í1=¹P—žJô@ÏÎHøS¾·=µ—ž°íÎ@OF¬+ÎSaîŠó?²ýJˆâ<•2JÝOLQ¼³·Û†W“Ôcå!ª¡1ªö?ýUnÄMþ=ãìmÓS-iPͶt‹Í–4¨>^&ès²jÉ}±-÷•-e_Ïû¾?׆²§h*;bÃÚ4Û W§Ý“É4»Úc[q©µe |/mðÛ?}ÛG~¿ÿÕ¦a"»d"ûûk²oƒÁóñüýñÂÙý²9ügíIfÙÚS1Ëæž´÷T¶ážÒ*›{ªVÙØSn„=Õm´'ZekGi•Íýpî&·Ð^d“­Ý›lîGqGeíI&ÙÚS1Éæž´÷T¶É¾K‹lî©Zd«Ës#ìé߱ѶÚ#çšÿ_í¿°Ñþ¾×ÿøíÛû'ŸçüiçüùÉþÓÎùÛžþ¶…¶•ŸzÞAïÿK í÷ õw,´ßÍÿÌBûm~wmjñÞÿídcZh¯¿¶ÐÞwμSçÚú1³’*݇ÏÙƒsÑ·e‡#ù~ß׎T¢·Õ=uS XžìûÝápC€÷¶ª±ûW]o/4ˆl_õÛ^7„ŸÇÿ~<Þrv.±o+å|‡”åkÍÛJÒ»¾ 1p[…WLu»­ ËYåº×ð}ʤï|ìR,‚Ë^QÅÜÃ;œ>ß–=’Ä'{™vXcÔ¶Õ ø8\‚•òv!œño˃ÕbàɶšS®p2nd[YóéÁ21ß~g‡=$N.¡½-O„ !xfï¾Bâd åmÕ¤F‰ÚV(‹1iÛV`ÑgÊD†mþzá Ž¥Ìm†ëÍ·ÁŒq[?º|?˜ˆ¾-¶à(·³÷^1Uf2ù¶Yß_=ç´ß–Seúvl«{ØO½ «Xȸ!‡„m~ï®p2êg[ÍÇûŠŸr¿ÿ\ø;ÉBèÖÄßɵ­O§?éÛp¼DTžïygÑ‘¥ÝXOZ¿²jè6g?Ÿ*sá÷m9Q}4[Œwp'|]h?ïï}ªÌUŸmN~ÈÊ…ý·eÛÿópÑè‡Ï¸ËŠ•Á—F³ê²ÌÉoN†¿¾n„²Føë6»Ž¨à¸w­!Úuƹ¼pâkÅÌkßfûበˆÍ{Ÿ›_JÝä}U‘}÷Ê]TV´8NûÆDrˆZìËŒmü³qÌåeÖÄŸ·å ¨eˆï178§ÍÉ1Qníø•ý˜oC-9ümyjM~ÌÝÈSò|ÙòBÛ“]ŸýØ*Ùó9Ö³‚ku†ý}ö±cÿë}ßj¹üyLÇF¿®ÇBN"5$V ¬X3;è˜òîL;"²çXxAëõD,PàZŸ–—<½£ÒBáØgq"t§·OtÔ<›³¢£ê÷0ãòm|õX§èȉýX'^°vu0?†ªís«ìÝWìÙ»÷ñ´ïXÁ=^H÷®Ïß°Ô÷ð³ã Jß±[hD¢—w°ã…t×g3<@fÒ‡²Jºõ­>¶Þ‰\:Ös`6ŒŒ±c:ŒwTj}Çm¸Çšá"Yöã•tO=[ÑšHöòÐñRºO½ë^K÷úÝVÈ×õÑwývùºÐ±jºqþ¾r¼šnõo>×è«xû½˜îù•)vÇŠézWåzâñbºÏ¯Ì4;^L×·ÁbܱjºÈ¶ˆƒóû8p¬šîˆ{îñ2Ç‹é®ÏVÛ‹éÖ<Âs_X™J~¼˜®ßvØ…+¦ûŒúIºVä|+¦{ÆçX¶H¶ë㳪rÞ_‘úx¼šnÍí8VKv!1Ë'&Ç«é>ÑâKxÇ«éúíÂ2îYñdÓ°èx9Ýû³ÍC+Ò6ŽWÓ½ë…[5ÝÓëcðjºë³ÍÆÈª‡çÕtW|ÌfœßÁȪÏÛ‚’L…àX1]|,âmÛ.$3)æXåÁëó›#×›`E9g\_œ‡Sä¯LÊ<(¢[öá.u‹¨¡;~¬†îª7`o$Î8Ɖá”KÏç3h@1ëâ«nm¥sŸúp²?£ŸUÎ=õKb•sG=ÃQž³ÕÍÅ­¼bH¥LqÎýý͆ëÇÜ\ŽqZ Ï5%é ^nÙÇ#'3UÊåæV.™¡¾{¬Z.rüœ4ŽËíõ°V+wÕñù™Oí™§†•'lerŸz÷¤„æAM!þ•iPçAF¨îÖ;ònY…ÜšÈÉ%}hþUslÙ\÷õYïBä<¹Î]®]¯$×w"ž×£Y(¸nØ@ë¼¡Çœë¼æÒj ®‡ßjpÝÛ€QŸ`—æÙ;oˆy4Àîm[Ù½-xL$»qøÞ“ì|› ©;ßÄß‚Ý84µ"ØÃ¬‚Ý»Mã¯ì†×Ž ²F ¬÷Àî[ÛÙ™%ø¯ÄºòpÝÛB ®{áêÜSü Ìs¨İp>ö¼-½ uÞPç»Yq˜€:;NŒ+„ººç€:ߨ‡¾„:ß&8PW÷Pç6èA €º4F'ÔyK8 Îð ¨óm|ÚìPWwP7c_u~'îØk@ÿ¨PW® Pç-±Ê¨«ÛÔù¡Fì9 ®ü PW[êüW  „¸0°æŽw ¬¹ßƒU¯@ ]y¯våÂvÞ}hW[:V|rHveÇ »rz”;óü@vuÇ7V^7À®Ü]ZûìÞK“ìʃÙ•[dWÎdW>9Ave¿ »ò}Ù•ç²+ç²+— ²ËËØÕ-®¼[»rQ»ºãƒÁ5OùÁà h‚7œ:ÇVÞ€]9À®|vå”ìʱAvÞ}dWnÈ®œßæèº¿`W69·zëS¸®tÖàºò-6®+73¸®\rp]9jpݧÁ¸.Ï"°®\n`]yëÊã ¬+ç½÷ýÙÃÁpеuǺ2RÙ•¯s]¹î »rÖAvå ²ócD‡ ²Ëë °«q°+Ÿj»ònØ•§`WÏÊÁ®68ØÕÓ|0vò¬ìÊNìʽ °«?q°+; °«?áG!î~€]9­»révå ØÕ]:ØÕ†ûËi9ØÕ-BÌÔ ü¶×b;ä¸WÑŽER´ã‚CŠv ÂLÑŽùƒE´CÈGµ‹¹;U;–S”jפ¬Pµc=›”í¨ìK¶Ó&’íDÒí¤H·£ºã½S·’רÛ1¦9u;® §n7¥äQ·ãÂ[ w4$Ü!Þ.u»<u;I4îÆ ‹A¸cZ wR` ÜÙ& (w²Š“p×\žÂ.“Âà$Üuq7…;]u»² t»Îe év+¶Òíºøºr S·£‡qêv¹ u;®‡n×¹¦+Ý®kqº]Ùt»² t»|·¨ÛåÍ¢n'xévk‰Òí:#év¥º]ç’–t»>bˆvòÇh—‡¦h§tuévùfQ¸Sº²„»|)Üu,’S·“[‡t»ìdÐí:—Ž¥Û©Eº‹t;íXº]O- º]Ùt;½ÖÒít ÒíÔ3¥ÛõÔä Ûuë’n§›#Ý®K?£nWκž&u;=IwêÏ”îòl(Ýuê-”î:ѤÜu 0”î”;+éNßIw¥%ÝuF€Jºë’•(Ýõó ÝuJT+åNù¬Rî:-ФܩS…r—G¦r×S" å®§”å.OÂ]×?…;õo wôîòiS¸ëZÞ¦p§¯˜„;œº]þˆºz‡t».õ…º7e;}7$Û•cC¶Ëk l§¼cÊv=Õ?èvyÿ ÛuŠÄ”íô¦QµËGKÕNßw©v=e2¨vù¨Ú14G¢MÍ®ìš]Ù 4»¼$ŠvÙ)ÚåûJÑ®lÑ®§ø`Pågƒ¢]—Ò Ñ®KŒ h§!T¢b”$Úe¿¤h—_:ŠvúâK´ÓÀ+Ñ.ûE»|g)Ú•S>9ª‚ÿŽª¼rªv¹gªvšÝHµÓè,Õ.{U;éTí:c¾%Ûuɲ”íÊVIr›+?ª”íòSAÙ®œNÈvÙÙNî¹!Ûéõƒj—ïT»Ü D»²Ãídz@ÑÎŽ°c!Úå¥@´Ëá ¢]Žq.Ú©".E;õ×ìòÙA¶ËûÙN¦\”ítPíº}ŸC@ Õ.Ϫ]—l ÕÎ>Ü! Aµ+[Ü»|2 Úåû Ñ.»D»ý!Úeׇh—û€h×™æHÑ®§ä¢]>@ˆvÙ Úiª¢§6Ôìzo_Í.Gjhv=õ¶ÐìòN@³Ë+cô5•kHvšÂ*^›=ý/¬¬33Ò‹+ÍQ@—T÷hížRÝC/}Ius±%Õ=4X’V÷МˆZŠ6I«{˜¤C­Îæ…ÿ„V÷Ð(‚ZU¼º#žZÝs$²A«{˜’,­N5°¤Õ©r–ĺ² ĺGAëægK¬³¬ÓõëºJ¬{X'Ob]iX§"°Òër?Ôë&7S¯{˜i-Éîy¨9A²+›@²{ÄДìÊ Ù=”AHvªF&É®œ$»GOÉ®´@²+çÉî‘6LÉ.[(ÙÙ•‡HÉîQ*%»ç‘@É®luv¥ÇA²Ë“d—×DÉ®ì’]¾”잌 …dWöÉîaŒ2»Ü1»|•¨ØåŽ)ÙåÁ)Ùå¡(Ù=PѠוA°+;`÷ÐkE‚]Þ, vùÎB°+ ì²ãA°ÓUS¯ÓÙJ¯Ó«&½î¡Q‚ôº‡¥¤×©»H¯+û^÷Ð\[z]myÐYQÞSz]i^W~½® zÝà `á\cè0õ:Þ ÑœmQi.{‹ä:ÝPÉuyz”ëTØ”Z÷0ˆZj¸Ô:}ȤÖÕ–ƒ®ªý@®+§¹.ï åºÚrÐUá^(žË+§\§ž<§:Ú’ëòƒçÊ&à¹Ò Ëg@¹NŸ1Éus$וÈuúdJ®ÓÇFrÖE%×å±(×åEP®{hL)¹NÃä:}ü$×=PÙ Ö=(Ï$­._$huåt¡Õ•MB«Ë'@­.7¡V‡ãR¨ËŸP¨Ë›@¥Nß)ue›ÉQU-PêʯnŽª:™ÅQ•R]9ŸÍQPIueÏêòqCªÓð#©.©®4 Žªø‚Jª{èD,©·:]ÙÉÍ!U?¹sH–-©È–P—½’BF uy#(ÔåÑ©Ô=å8ž~4º‡†aÒèòÆQ£{Xà€ÆitŸ¥Ññ8‹ƒ©Îks0eï£B—/%º|fèžM …îa=²PèpPÈsyÞçlw^(ò\ÞcÈsÜAˆsyUçÊBœË›qNÃÁŽ7,~}0lò¸0÷Tp+{‚*—[C•Ë›UN#5U¹üì@•Ë÷²Ž M.krüŸ!È• A®œPry7 ÈqÏÅilìj\žÔ¸|àPã°HqùšAŠËnãRÜC›pJqÙÑ Åe¯‚WvR\>bHqåȻ՗RœLΔªËûð'fÔ)¹EìæGr“TFÉ&€)¹ TŒOÉ +Œ©¸eh$7ARq“õ\*nÔ(©¸5V‚“âÖ¨8RqkäÅͦ[H;ƒâÖèO.ÅM†zRÜ]H¥¸5z«JqkKª·–ùuPÜKÕIqk(C'ÁÍÚGp“ 7›!þ ¸ÉÝ[Š[ÛRÏBqÓ‘(¸eCèmª´-½-·€Ü– PÛT]j›ª€Km+û…ÚfÏi…j¹­ü r[ÞÊm®’Û‹¦InkKùlÛÍ%·•m ·5Úنܦ«¤Ú–÷j[^Õ¶ü Ķ<ŠmVÆÛšV/(¶å} ØÖX:Ub[£çµÄ¶Ô´)¶åQo³ó–½-N½M•ÒÛʱ ·±¨»ä6óœAlÛòÕƒÞÖX[z[S´.ô¶¼9ÔÛt+¤·5zJKo“ƒ¦ô¶¨R/±­üb›NNb[9Ä6ŒÄ6ÝO‰mz$¶éîIlSÏ•ØVŽN:Ó%@lËÓžét ¶•ß@lÓ["µ-D¹M¶L’ÛÊ6ÛÊ¡ ·•ÓÜÖPBj[^8Õ¶²c¨mÙB¹-E¹-–ð,¹­1SxF£&Éme·À³Üñ,[ˆgº¡ÔÛòFPoÓeSnËw‚r[¹Èmzó%·åùQokô —ÞV[0¨2y[z›N‡z[žõ¶Ür[9ÈmåH!·åo ¶•#‡ÚV ·åN¨·5§Kokágú¿RoË“¡ÞfÛD6 õ¶¼YÜòu¤â–çCÅ­´¬¡Îz#o.·² 7;Ÿ˜Rq+-PÜÊ•†â–›PqËS†â–×IÅ-;+·Ü/·ì¬TÜlÆÑ+¤åDŠ[-Žª0ê—ÜVv¹ Ljmå‚ µé Ô–o9¥¶ü¥¶ü”¶² ”¶ÒJ[vK*my먴µM%šJ[Þ*mùh©´iú&¥­ì9”¶<(mCiËCjË=@j+{­­6¸ÖÖèÙO­­lZ[Ù"´¶²Ehmše†ÖV~Z[>`ÛðB@iÃ_Ùò·Ùò6AgËN ­±2u6î1D¶|i!²•CÜeëØÚ–h› áù£¾EPØd#H…- °á×í,(¯å݃¼ÆíC[Ó„=´µüA\³ÿ”º×òŽA\Ë×âZiØëÇ)‡¸– ¨kå'¡®éFý #é7éÄ]\‰šÒÅq]v„¸ŽZEb8Õ›ı<”NþÏŠš¤¯.ý1Àp#“ïÀpÊô%à …ø‘á”x,†“+€nÐz1£&åèA†“›Niäb¸¡h=2œÌ§Åp*#,ˆ™nˆS)BAÜPh*!n é 7+O€KV" 8ySËë„n¦éu"N•× £q*“™^'ypDO¯“Ü3½NPÍ#­NaN'"b9h/r:ÑeáýW…p#Q 7ÝéD -§“d<8°w§Ó ˹¤Ó »ŒNH?ò9¡…aúœÐÂ0}NX¨,}Nt7ås¢«–ω@‹6'ʵ“ÍI¢mNôpåt¢¥ Yü$8Ù—§Ó‰ÒétrIO“Ó‰,Vàt¢—QN'™:F§%tÉéD㕜NJ œN”;!§“ûA¶½œN”e%§E½Ëé„g˜N'y†t:a‚ŒNh›F'J Ñ W¯ŠÑ èu’©lð:¹`dš^'LrM³¦v¦Ù óLÓíäªépi?™V'Šz’Õ Š¦Ó ­lÓé$Ï…N'¬—N'—Ô4:È»RN'1ÚÊæ„Õ?`sBûã´9ÑéÓæD¾ ²9)¦&°9a ä´9¡OpÚœ\?d²7Q”4íMdJö&̽‰ºHØ›È9Š'ú~Òá„Öqr8a 9œ4æ¹2VR/Œ•TL Nš²ÖàpÒ”èæ'Myqp8¡}žNªŠÉá„qr8iÌCd°$½åpBŸl9œÀZ['~48i˜gÉà$wá_…Æsœ4¥½!XRâ* NòUéoB^Q¬äËþ& Ÿ\ÆJ2´Pö&¬™Qì ŸõžPµû|§ ÓõQÙ‹²¥;ÿÓŸåFØäß³ƒîÍ’-®zµ¤ñ2ÛÒö4[Òz¹7+|3>ûbKÝW´Õ}±¥ìëf}Î —ýxKÙ þþO[A›Žjq0æý—îÎëú× ×ù·¬ {CžµzqÒŽ{õ}×ü5®ß—­¸'™¯|Ê|ìÿ²8. <ËJmüÊ`àw*‹¿Ì|Öã5v =¼ ±øKèv[Ôv}Êøì‹¿,’úì‹¿ ÿy"µ‚Õkžý†×ÂÄÌéÙïpgêÊûP=alñþy˜§âYwïŒåþ¬û¿÷pF¾‡NâåF_ýEØÔÛpü+Ìð’g?·ÏéSõœ™J4ïyŽe üò² 'þôCKø*IBï´ ¥j(óCÅøxOæ‰è{¸ï¨B­-^Tô:È\zŽ l¿²^üÛ ÒÅ{ÞylÜJ˜õ<–b'}@9ï ¨ÅöN"ixSïä.R•¸ü÷XËq|kÞ–÷í×€€Ã·ÅêùÄÔÐb_‹`ކc=‡(´âlÜ¿» ãÛâ åyÿ }ï8öƒ-| ¼õþ9oBÜDË…ôBHÁoËÔLг–àfÑÛ°‚›YømÙ‘bXÎå9—CM–»ãÎŒ§Ú’¿ßÃi†ë,ÖòÄ;¢çïÕ‹$õ¶¼Ðˆ«ìØÏ „Χb5Òv¡¾·åDç~î‹o¹ËKoËŠ”Cf)ZËÃmx>ä½qìi‡ ö|[žþ£§Z•×ëÓ}¬Êë‰_µ¸£6¤ÏØæŠýX•WXûã[™×o>Þ5+óº>Wee^{Y,x[çu^^¶lE^;CZß– ¬VC•W bÖYˆy/¬Ìëü|¬ÌëŽcÅŽ­Ê눯í™h‰á’Á±oˈñ’1½oËœüÚpÏßX²¿/¿¹o^OfÍŸ§·cØD¹"k½n«ñŠ7=5^;“{³"¯.÷"™ÒZNYbxÿîwôTT/{[çËBdoËlxKðçþñ¹´¯X)ZøÉíèèƒ>+ñ:ʸa-;Ö¸:?…VãµÿÊ o DÝìmñŒß|ÑœpòÆl.dél¶¯øÙ°!†RÚ[¼-cÇ%ÀPçm[oû=PuólÖµòVȺô¦[°²•gl¶­°8Ày°ºÕ!2¾-ñåý©ÀÙS­Âëóù’ Ä«#Õx=ÑÒâ¬q1›ÈZbTe’Ã;}m‹×€_Y×燇ÕxíŸçi5^ñ¦ãúÌõ¹&«ðz}Îï°›¯±­:x"öâhh^OY9[öüq­Äëε?kÀ Š©øÛòüT»—xU-ºnó ®CûTÍZ¢'²xp·!òˆ‡i£R\ÂÔ~®Æ‰Áý\ƒøó¾ùžs' ËѼãÖËâþbZeoñÕû¡Û;R_a{ña ÚZž87`O·ÝÄù³¿w3Š8eáUkC¯gG…×r,­õÄôü_õ}&ÇyŸÝuqkC‰”Û̈"Êm¾÷@¹ô€Ê =ð‡”{¹¬…ÿÙEõð?£”s3瀉@9we^ñG¹·~e@¹´`v–Kf°œ[+Ÿ³V¡/X.’Árîý;cÎriL –Ka°\Ú®‚åÒTÐY.­õsi)é0Wÿt˜«¿w˜Kƒ?À\ZíæÒž0—æq€¹tTÍÕÃ>á ÊXa§¹q%šó†ðÖÃUA ¹q#œ{ø^ÎyC/8ç?™ ·á'Î àܰà’;Žâ8ç ñnν °«qœó?™Žso Z€sÞpŸ|Öîæ{ 0§¹ü iÎ[Èn#œ‘Ä@˜óMðq ˜«›8ÌyæƒsÞò$Ì}Nn‡» cqHsï¿ÅŸ':ÿtŽóíEmˆ¥œãô“€¸zˆ€807Í!Îw²ˆuÇO½´¸]éßÄ}¶XáþÉ€_BÜçWqÞ‚i}@Üç’âÞmêIˆ«¿ ˆóm0çnûœ¿ ˆû¶œø3­ ¸ÏWX€®ù‘­ñîž q^2 dÇ"jÞ²Ç Šóm0c ŠûüêñÓ½xó‚âêÛWoyPœïó– 8ßÏU)î³g§8oÁ,%(îÓrGÏ+ûYƒ³‰ 8߸0÷þþ}ÂÔfƸ†'œAË‘ž°Ím‚â>-=ÌAé\BŠ«w4(ηÁ:CPܧ劅Î}“ìƒâ>{¾ŸøH÷iÙ1H–½œè…ü0‘â>Û<èÊaPCˆóàuP\=á ¸zð 8»ðøsÆ@Yvr¡«€ ¯ÃWäCpõÖÁùN­ñôy&¡M–‡÷94Lxó¢áò›W_Ø@¸O ŒxKËl¼œqPœŸÍ‡â>-÷`W`ËŠ¡3¿ Õ*òª‚âê‹¿P®¢´¸)oÙ/ªUä^6lyóŠ«¿Ú0æÍïp`ÜçW°æ-{¾ßns=?Î/0î³Íºøõĸú|ãê=Œ«]#0®î%0®¾Ÿ+òŒlzó[}P´¢ü F½y>q9Ÿ Æ}~u_ßý¬·l±Îk8°ë-G:óç5À°7ßìÀ¸zwãê»÷iWIÀ¸:4'qÎÏÓz0œ‚†Ú¬½ìVv vóÏÌ Œ¦Èv&»}Z®öý΀Ý>Ǻ1œ‚ˆoåÞßÊ ~+ó3ç·ÏoP¨¢œÍóðüVå·òÜÁoå[DýþÐV‹üæ-`_h”ê'Ãß™ ÷DœYÑâ.¤š;ÃÍÆx=0œ§™Çÿ†'(¡wàs&5.u/¨qì³Rãèz-5îP¥‚׸îŸj…+¨qî!ǵGÄ9ޫߒã(IPŽSÍXÉqê’ã¸*"9ŽË"’ãèØ*9.·è§,ÜK£­ô¸A¥ rš%DZŒ“ä8ÆJŽc(§ä¸‹N9Žá”Òã”'=N*aèq,z%=nJè‚Ç"½Òã‚(AnÞd<rŒ– §§ —û€ CCéqÌL—Çànèq¢têq¬w$=Ž'‘zÜЀB=Ž1ø©Ç!;å¸k~.”jÜ¥¥mÊq´ZH9î’rÜ¥5êq—p©Ç]Zä¥wáÜ Æå)ÆÝ)[AŒ»´¦N1޹)Æ1<4Ÿ<=Šq…×âô|R‹»¤³@‹+w Z\ŸR;©ÅñÍH-Žk<Òâê~B‹+-®Ü«ÐâXgKZ\yÖ®Åu~ %ÆÉ7ŸöP€'Y‰qì×ã:«Ä¥7%mBŒ³–Cy.Ö ¯ÎÅfãÊm —§G1Ž¡É)ÆÑDb\Ù/ĸÎÔ‰qå±PŒ›Zl¦—·‹bœV:%ÆÑ“b×ÞRŒ+džwý&Æ© R‹ËHqyM”âXžR\>JqylJqy•”âjË÷#B)nJ¤ —WM).¥JqSb¥¸¹9g§ÇOZjqyÿ¨Åå5P‹»¤AŠcÞ¥8z‘¦Wv ).o¥¸ì—”âòVP‹»©@-n¦xH»]½´Ðâ:KR‹c: ´¸²_jqyk¨Å•ýBŽË—r\y0ãÊKL9ŽY’ãÊ‹9®žëÉ?Ô¥BŽãXžrÜ¥èŠÝ4Žb¿ãú”H=®kåz\¹;ÐãÊ•C+wzœ}¾ŸW¾~Ðã4ÐCÓ\"õ8Î?¤ÇåË9. Æ•#C+÷j\éòPãÊk 5NsŠ¢Æ¥jc^æ…@+ß|ªq9ŒQË{~hÍ«þ5®SCH5.?´Tã²ûB³c‘ Bëœ`K+{†WÞÑgÖé™Ô¸òéxnùg?l‰qµqibœ<À%ÆÑ“^Z\éáã:³˜%Æu–n…×™($1.ÏWbÜHì7¯`ĸÜ(ÆÉ¶9Å8Z¦KËûI=.ßjêqùy– ‡X>èqr,——ß|êqù(©Çé=§×™ö•AÔy.ãò­–‡Yî_x:+š2Vz Áu,ô  R“`TrÞIîaå4ªpsà¨ÂÙx î¡ãU¸‡«KTáìk`º°>£ìAî!DS…{\J îÙßpÊ·qˆà("Tà®P{ÜTàž}( †'Cj*pC@¨À=R4]+†g ‰oi‚MÎ ®Ÿ¡ÀYà   î9`p¶Á»îQì#¸‡1'àì$"2œlµC€{PŒ—úÛ“á•¡¿Yg…ÞÒº›úÛ“š¡¿•†Ðßò$ ¿Ù½ ¨‡þVŽú›œ¼©¿=ŠÊuýíaØ#õ7Y8RÓ¤¿=GC!8; >Xàô $À=oî}œì@³cQÈ îÉPHpb B‚ÓJ‚{2쟎D¸º“Ðáìd:\Ù1t¸²cHqOFB㇆±R\¹LHqå¢\Š+·RÜS".CŠ“»¢¤¸r âÊ-†WR\¹ÅâʆWöìR\Ù/¤¸'c`\Š+wR\¹FHqO´A‹«¿ -®þ*´¸ò ÅÕ–ÐâêÙ„W[žûóœ Åå+)®\4¤¸ÚR\¹yâÊ£ƒWR\m¹¯ï9¤8}&%Åé›)îAôµ”8Û`V„«OJ\9”¸òA‰{ŽæŸPâÊsW÷J\¹((qv‚«B\~À Ä•¾%®¼{Pâêù…g¹…½„WÞG(qåŒ!Å=5).Ÿ8”¸rp(qÏѤbÜ“É.Æ•ç 5®Ü¨qå Æ•›5®î'Ô¸z ¡ÆÙÇ<ÞYˆqvÿDl1vê¥p-®Z\Ù¦»º PâÊK%ΜPqnPâJw‚W®J\Ù1JQœüV{áb-ŠlqÞú÷þñ¹‡WNB\ùj@ˆ+B\yg Ä•» !®t9qù Ã•—:œ]fÁ7ߢW|ûìö`LU×…W.:\y ÐáÊîÉP}èpå†Wnt8M˜¤Ã•è:\¹éÐá>-‡\÷¡Wožñ™| ˜)@‡³zQ™Ã Ê72\yo Õ[ ®¼~áÊ t®\6”¸ú›[cêúˆqåÖ@Œ+·z\yàÐãÊÍWÆ(èqy¬är/”äòH”äòS’“I±$¹¼[”äò1P’Ë{CI.ï(%¹z~»ñó Q‹B/HrõØ(Eq~ \¹”ä²;P’+gÌ”Z†5J’«Û —{þŸg[t‡šÑËP»Þ¬u$½ÑR@Úp=áQ¨D8d…Hz£¤7:ËIz£U›¤·Ü"¤7ÅÉKzKÐréMTé­ñQd&œ@Joí<ùþ#•·¢ÿ…òÖÄPÞé¼åQ]yk´ òÖX#”·ÆÌ Joáÿ”Þ² ¨¼¥Äå-7áMål)¼å¡»5ÈBwSuÛÐÝ´=d·ÆÔÊn¶õ”ÝR…ìÖøa¡ì–·²[£‹9e·öÿ²÷n«º,I–Þ}?źÌ-ÈÄÃ]HÐ-„J”`÷4’ÕUJP·ž_afc ³®µs:j¨›Ì=}ÅïqôÃçc˜9#K(»å}@wkŒ¡îÖWÝ-2©¥îVjÝ­•(²ÐÝZö€ÐÝta©»Ù®!À©ÞZÆAyÓ#Lå-c²¨¼•(o¼b*oÜIDÊ[ã^©¼µ + ooƒÅ’µ·,¡ö–VÔÞäÙ–öÆôÒÞZ†¢P{+5C{Ë€ªß2p‹â[)øÆ")¾exÅ·r&ˆo¥â[©â[‰GƒøVÂÏ\|Ëë¥ø–át!¾±¿“øÖ2¼ â[K–‡øÖ¬í­@{+×í­]Kho-C+¨½•@>×Þ¾„Ë#¨½e½ÔÞÚæ NíY]R{+lÐÞòIP{c®˜ÔÞR2öÖ2H”Ú[¾ïÐÞÚùà¶SCz+ÕBz˧ö– (Å·¼<Šo%ò â³Û¤ø–—Gñ­ñ-¯0Ä7ë>pnˆoùˆ)¾µ‡«Øß´÷xŠoL\”â[†SA|kϧòÖçÛTÞ´ÄNá-_.•·¼#WÞZ Š‹á2£ƒ¨¼)˜EÊ[>*oå˜#·ÊüTÞôº!¼µ *dÜV OoÙURxËo‘›[ìPwË/„º[¾ênyOÔݲˠîV~Ý­½Aw+õ¸îVBçrCx¬`Qwˆ Ý­¼èn¥9QwËQ‚º[ÆòRw+QoÐÝòéPwËè*ênz¤!»•J »e£ì–˜º›*¡î–!ƒÔÝ2Œº[>=ênƒGÝM!‚Ý4¹JÙíK\éí)»å‹£ì–²[ ƒì–A”ÝÊMAvÓgNÕ-#û¨ºeFÕ-?tªnºËÝò£¡èVé º•@ºÝJ £ê–Á‰TÝJpd·|ß”ÝJÍÝ` ÙM£d·Z‚fÈîH²›”d7=OÉnµäð-|ªnÔœRuÓ`.Õ­„äa îBuS¦T·Z#jFèQuSó–ìVJ »é–ì–q}Ý´¥ÊïÈö,”{>8¡,”4ÓA€óTlU€»¹+8 )À1¦Pœ’ P€ãÅà¨îJ€ëâ6pÈÖ(ý6Hp2ùQ‚“÷Ü VE NæQjp–W4à\@ƒ“%\@ƒc¶Rhp[›Iƒ›¤*—à”C…Ü,×&•þ¶ó›@€Ë(<p ¸¥ô%à˜ÃTòBS8î°+Nqyà䪥·˜}†Ü .뀗G@€cBT p ö£§pÀà˜wU\þÜÒd€ÜJr‚·4ƒ¤·4ÚR€[šQ€[ìÄ©¿-õ‰Ôß–&8ÔßJÅ®¿•SC+¿þVê½%n*!Àå1àò‚)À-Í)À•pKã¸õ…ãꆷ41¥—×GniJAni6@®ü \¹+pKÓ+ pyŸಞಠpå7.ÀåµP€Ë'Cn À)À)’’úÛAP³å­šÑ¤><êoåäÐßJÉSé¥þ–·D._¸­9¸rÌøL¾—\>` p¥ÜÖĈÜb*êoù¾CÛš¢Q€Ûš­P€³TOŸÜÖ̉\þŠ\Þ&8½êoyrêoyÔßJ ô·|Z¡¿•# ¿•èoåLÐßeúÛJ„þ¶4×£þ¶”W†ú[~[àV’¸|àò C€Ë×B®œ ÜÒ⸭©¸R/¸¼s pùò¨Àå1Tàì"oíþø %¸|áÔà¶&µáòú(ÂíþU„+õ@„+ ®\T¸ý%©‰×ÌÄ'PáJÍ®Â•ëƒ ·•°"\¾:Šp9LQ„Ë®ƒ"\ŽáQPƒË3A‚Ë‹¡·¿ \½¥ÐàÊo Áe‡D ngbhpù¨Á器Áe„5¸|áÔàÊ1Ðàòú¨Á峡§ .o\~”àôð¨Àe3¤W® \ž\¾}*pK«;TàòuS+Ç@Û•å>ª…—ñàò–(Àe'A®. ¸<5ô·rô7=èoü‰ä·IF ¿é{ü¦j%¿éž$¿íä)ÈoåWßvr%ä·RùMó,ÉoŒü€úVN õ­üê[–P}ËQ}c`Ä·¬˜âÛN"Ì,¸-Hî·&æôÇz¾­wšû¼ß’'æü~RÌÈŒ—ÿ“rmþœÿþM…ÿ÷þL“©Ô˜—u)ÿþþÍ¿ÿoþ`ÍÿáÿRÍ™ŠóÿùéÏïv°ŸÃz)œãßfÿç{Tòà £ÿòy¡=/ôuö¿þø‡ü¯ßÑŸ¥?ÿôgO‰ ýÕ‡ññSýç¿û©›gôõöþñ§?Ê6½ê‘Ïà)™Lÿç/§ù¥œ¥t×\ŽoË·­È­íßK~GºTuÛŠÈGU(ù}›¨Í²ö·YkCɯ‡QÃzyãózPòcÕ¿²™âçyQòûNP[?_/J>Ò´_×¹×g6Þуj2O;JjÆõ_þ]Åcþ`¦öÞm©$ëÇß%#º—”ŒÄø»dUïÇÝçµ–Ôz¢¬ÖÄ’R—§æûH“¬’RÊJ]*ù{gj¿,uØõG3µßÿŸgjÿÁ7rÝÍG¹š«ýË÷æ_Òn_àÏYWÉÃŽºj¶vÖ•G±®œîQWÍÄu}äkG]å(Ôõ™Õue6vTU2¶³&ÊjVwÔS²±£¢š³5åQ¬ê#³;ê*ùØQWÍÚκò(Öõ‘Ûm83²G]yÛÕöuêú#yÛ¯+Ôükâö_IÜþ[:ë†ÔUÿüÃÆúµûþ…Æú]]¿;yûåɇûíÙÛï’½ý¯k&ô%{ûû¤ùGçæ"b˜îp*q¯£·ÀvÌJ!zYþ>+Qª«·Ä•i™pÌpegÞªdº°3í‚2,éÜxK¸E¡•¸°3eо,K‡uV›ü¾%aWZ#vßn•X wX––™½¯ý­wK쿞p,-éÁ×s¹WbÑ.ú¸¼j<Ë{º[%¶Ížð+mnoô–LwJئ˜¸K Õ²c”Yó2´}ï`g"“g»SÂYây>ž“iØÖO§²­Î¶"ú/³ÇN«„™|®çq£Ä6]Çé-üJ›ïà-pŸÄBöv%ÛQʳæ½%}Ä0@oaWÚZæ~KÜ*±;‚±Þ³+mæÞ{ÿ^î”°­@Ã#Ö[ؕ깷{%6£ÌÞ’³â.yt3‡Ù-Øz2~õøÐ±«Û=éÇ[¢(Ön)î!tŒnšã%‘= [J\»f[8(ñz'V#»AÚ=h¡¡_aXÚ4y¾%«Å=àÍõ+ K¶îŸp„ì' ÇÒæ&yoÉíf‰­ŒOý ÇÒ¶åHœêq³„!~Õ󴵎Ðß;¯&лí’eGXàp‡;%6Dâ·`úLéñþí6 Ûçw¢’°+-Y9ûÜ#î€Üû5ÄLð Ø-Þ’›·0PóóÇ›áÝ}>#nA_çjî”X‘~òýÓm[ƒn1[_¯´K}uë’•6«Û6̾ÝÐ@ÚȾ­´•|·Û>ÌÖ×Ë¥ÞW¸•ò¥Ø>Ì^1ǸŽ}˜·m wd€Òë Ò±sùBl'fŠ˜>¸c'æ­Pîwºj¬p‘î#ÃG-¶3†¢ßtMí{±¨Û'çï€ÁKݾ;0k¯ö|-J%ëÄ€5CŒê;¼J&Q໲}˜¯Ïj®dŸ¾Æ}Ÿx¿ ³’]phÝ6b¶[à–,Vét9 oý °óÒb·½˜ÏÇã²½˜í-¸÷;G•︥ÿ›‰nK¥ÖrÌ×±”š«Ÿ0èÛàŽ1ì„C)!\?áÑ× ²!Û!ê·ï°+Ùn±6áùO#u¿Ã®”ÕÜaÓ·oÝ‘ïÄlOCù6ýÅÐß’°+•Æ|‡Uß>P¼¹;ìJ[V$ÏNfo!' wØõ÷Åì»þÚ7Õ~ýœ õ' ûKù[ûŽ}›b¡½?fÙ_Øxõ /ËGö„YiåŒà Û~¹Þ'ÌJ‹9*}}Ä!胟0+-‰rxn? §Ò¢ã- ïþ²˜\œ'ÌJkѾ6š¹÷óû-fÅ‹ñoIø³]Œþµ°…£•<Ñ r_”ØB¾^îhaâ_ŠÆ-\üKý¿}ø>kÜéÁ½NW´ƒzÎŒYïÁÜs4sò¯‘õÞO´SΔÜXmwìÛ0oî`¹èÓ6‰m˜s:í¹JN¼JœêŠ©ñâŸáã_s£¡xê,ï*)^Œ+|üV žÕµ½E2¡¯‡Ì:ÓWøøm̈i’o&3> #ÿ–Iß·)ùèg÷Ê-Ô¼Bj74vŸÿ ¢Ö cSGàë¶&ð¹û ç~¬Ve¾ï¹õïÂRa xg“2ñøÒ4Gâ{ëaŽ$Ÿ‹gê™á©‹ Ä—Ž0_†‹ù¼ „~fÈëy/mä½b–ï•J|EðÍÀWT9_zÞ|Eƒwà+æ_Qe|E!ðù™n\ÍAŽ„Á{žWCMðÞÇ-<7o\ÖÖ§ŒÞë#áÈ{^‚¿Üؤ<Ìà=OJr*ï½%L8Þ«낳)o*€ÏkÆL⢳éÞðS0ß;€ TH{>”íJ{µZ£½ZiÐ^}0A{ʳBÚó;Zä¿0SäP´ç%˜SíezÒ^rRÓakÊS¸)òTð5•Н„9k{v"ÿ3HÏÏÒ*éy f=zž)3£AO“N¸×Í"‚ö¼àÁ©V8)Ê©V8)”´W?£=Ï´òTÚó‹£îù=Y,M¨"XÏŸí$Ù]_žm°^¦t!ëùçÁ_ïG%îgÊK ØË/åàY`¶ E–ÀÌTN|ÂG¡¼Î ½ú‚ô2“I/Síö¼¡“”®0RdÍ{õÜ{õU/˜™”O°÷q&˜™4xö2Siïã\'T r503AãÓ˜Zƒ'‡›éh]Ì`OOø†•ép=¤Wø•)8¤P+9•ôJî ž—Ü Æñ0¤Ws°r¡6¤@Î'~`àÏwöóñ$rhåë?H¢¥ÔÍ ½Úϸø•s¨WÏ}ÃÇŸw~ÃÍ”w~ÃÉŸçº:"$¬üZ¶½™N»‘õJ¨;PïãÔÌ©¥¿™TK7~3«–^ÃÍ´Zê|xúu9ój©i<×ç“y2³îú)OýÀÚŸïûa6½ï‡ùµtã³ põ°WR^€÷J6ð^½Í‡ùx.ç½®üVä½fÚâ™À{þ$Nå=/Yø“ma ¸W.¸÷q1ë3=h¯ùš¶Š¢Ì×ô}Sç³"çyê6–Ôùš†mê|- è|-‡<} ¨|-çøPùZ®¬Cåk9.Aåk9q•Ïþ¾ð›…ä!â¨|ù8©òéRÒ‡hZ ‰¯ž&$¾–3JH|-§øZÎ¥ ñµ¤ H|­à[÷7ûùüa ‰¯å_Ø@âk…ïBâkÚïˆ_K!_˵mH|Na*|ùÅP᳊±˜é _« x>¾Z_Kô…Ä—m›_¹`H|{…Kâ+· ‰¯þ*$¾ZsH|Mû„Ä× A‰O[¾Kâk¹d ‰¯–„ÆW(d¾¦ê|M:Ôùê¯Bç«¿ ¯- QÐùZ.U»Î×NB¯Ü7„¾|½ÐùZ.½@çË€}ê|ù#È|M”ùÊÕAæk¹ã:_c”e>å’ÌײE™¯iÕŠ2_KÅ2_S„e¾–«3ùÊÅ@ækЬ¡Ò×È)¥¯ÔãJ_“¢ ¡¯|#újI}MQ úêÅ„ÒWn J_S_*}ùü ôåÈB¡¯iõB_S>ðúʉ ô•硯–t ¨G”B_yÝúšBô(ô•ÏB_- ¥¯\1”¾zöPúÊ[p¥/ß„¾r„¾òiAè³÷‚¡B_yúÊ{ÐW ¡¯–„ÐWÏB_ÎZ(ô•oÀ…¾–F}M®c }åBè+úa6®”ÒBé+ÇÜÜ GŸ5”¾&Y‰R_=fìÏZ‘+Ÿ ¤¾òŒ!õ•'©¯Öƒ¼\ùz!õÕš‘š+ïZ_)ÖWj†ÖWž±k}å‰Bì«G„ØWK£+¯b_y›PûÊÓ‚Úg%ƒò^ûò-Að«Ç YW¹«§ó 1QwÁ/›8?õÔûòò¨÷5F·KïËQïËWE½¯)æ‰z_~\ÔûÊÉ‘¶Kå¾zª»ù[IZ÷‡Ü—Õ’ÿRW„Ü—œr_y4ûò‘Sîk¨øiÚOÁ¯)œ’‚_ýÑöÇy£HÜ%¾ àWî‚_­%¿Æ]n%ø5)#üò{¤à×´¥¿Zϸj;¤àW^¿òž øÙ¯q¯ñúxî}óFÀ·rÚ¯„$ô]Ï |Q¦næ.XRÛ®õyD(}ö ¡Ò§Ì©ôu¡•¾ž†ÐPú”*"•>í¨!¥¯œ JŸeÛ@=”ú´a¥>y¡õiCi}][³QëKϨ´¾D1j}Ú±€Z_9Z_©Z_^ µ>z‹$õõ%“(¤¾R±K}å öåC§Ú×µ„Eµ¯'IAíÓÃ’ÚWŒšPûúðû¨jßÐB\¨}åo¨}]«TûJ½Pû´M„Ô¾R¹¯Üä¾®¥CÊ}×É從nIÈ}] J¹¯Ká ¹¯'BîëŸZ_#Sëë"bj}]Z µ¾.ÙˆZŸ¾*ùÕ›¤Ö—‹r÷˜’Ú'ã3Ô¾<Õ¾<Õ¾|+”ûò‹ Ü—C¹Of8ª}åGPûôÝKíËWI¹¯œr_¾ÊûÔKHîËZ¨ø¥]‚_/ò^,P¦E”‚_~åüJÅPüòiQñÓ#§à—†‚_^Í™Ÿ@ï+W½¯\ ô¾|œ”üòJ~º*~ù¹RñËSQñëRCBñ+G@ñËï•¢_1sBô+Ñ//š_>Mj~ùSóëßi~y 5¿žÚ4¿|6¡ùå[¢æWŽ€æ×¿ÓüÊ™ ù•c ùåáæ—7Nͯü š_9¢_> Š~ùU„èWþ†î—õR÷Ë×@Ý/ÏDݯ•¯ÿåóéP÷Ë«¡ðWJ ü•ë9TY3„¿|‚!ü•3AøËz)üåSøÓ‡CÝ/ODÝ//†º_>ê~åè~y9ÔýÊå@÷+—³ñˆÏ§î——Ù¯TÙ/ê—†ª_ÿNõË»¤êWŽaþ®M9$õéÂ$õõT ×óùmKëÓS‘Ö——s÷úLDzš’KêS#ÔËQêËz(õå-PêÓ©©ôå}SêËGK©¯³öç× ©¯\ ¤¾òH}½r^÷¥óåO¨óå]Sç+Ç\H÷§Î—w:_ù „>53 }å}¸\ª|ùT¨òéQRäã˜ôƒ}rÝh>“+Z^WjXìq‡ ìiëQJy³1¢G{‰ Øãœ ØûNÉ›EEDÀ^Ÿ Ï )o’ñBÇ›ÚqŽ:Þ<*:ÞÌt(®ãÍÜ‹:ÞÔuIuéh!Õå]]¹7åEP]>b]ëÒ¤C¬K ±Næ®_6q*“º¨NÕënní(¬ÛO*|­3÷§‹³ÔÃí¡hhÖ¥?X—î$b]Þ¹.<2rÊñJ®Kû¹®üŠNÎä-p]êŸrr~vÅ"NN¡)É.W•å䤇$œ%z9Óyi'E¸òr äååTû•—S§ ²K™U^Îôˆ‚ìŠ d—V’]Š”Åι>Ñ®X>içÔ¹ˆvéy&Ú•chçÔ}ÂΙGíR•S¼*;§îAvάw+1ÖªÁ{ÕÈJ´K_¹ìœZÝ!Ú¥,?§¦šôsÒÝ KçHØ{>sð¥¥SWL´Ëû$ÚÉd@²K…Y–NÍ„eéԪɮ–Ù¥a–Î<‚–NÕ+KgÜ󞘂ýœé±djºŒž×1%sr]ÚÓåçËÏI§¶ìœYð‘3ÝœZ·“›S?¡™S­›X—æ2sª™9³„fN mÄ:%Öe¿B¬ËÞˆX—.rb]F°ë²Áë2 XWKbXÍø’]^É.{Y’]ŽvëA´Ë`Ù9±Ãk²]Ž„»4îÊÕ€îRî&Ý•sîRC•3B%ˆvñ'¸N¿ÚÙt§;Þéê…wò ï(†‹îÊ©¸mjSèŽ×´Ó¦×B;u^`;uBb»RÂÄͼ¢]^ Ñ.o‘hWŽaÞfÉ[d;½V±®Ÿ`Ç?™²YBVP^°¨N>>Q]>X‚>]C°Ëš vƒv’úv¥žq}Ö°ËçD°û*à}¶Ãc Øi¸Ù¦~GVµ¾˜øVâÓ^ß$¾Áí @|Šëñ•Ÿ€ø”€Ä·r?k ßú×+qèä=‹CŸ Z,· ß."c _&ñ òm˦Yï$ ùNn8ä;öC"ß‘dCä³±pµùlH£’Èw¾KÑr”@„ÈwKä;™¬ÈgT§®g×'Ë ‘ïHú'ò噈|ç½(¦N ä;>ð‚ ¾³.ú…{ódö ¸7íÛi9ZNÆJ¸{ód€Ü›Ç¬ÔîÍ“³-¸7™õPK8-ï-0ü›'Kà߬Մó$EÀ¿Y.þÍ“'ø7ÏQº÷ožL¶öÍÃÍdß<Ú•öÍc« ,q›ÉÉ$ðožg(/ü›G{“Ñ¿ykÿ2ú7OÆäÃÀyÒú§M}hÆ4ç1ïò„Ó¦BúÂÀy2:γÇ_*ïù“©"Þ[¯ì5°o›Ç3‹»LÊ}þy´Y,í›Ç’Üdh9ŠƒûæÉŒ<°ožœR¾y2ì›'óLÀ¾y†höÍ“)o`ß<9á‚}ÓÞ rÓÀ¾yÒ›û¦Ý9XöÍ“#·ož¯{ã¤õöÍ“+$ðonÈ(ÿæIì†3?Qø7Ëk€ódr"ø7ˇäþÍ£44pùÄià<%iL8ÏVæ 8³£33nÒÀy\Mÿæ±™e»½ ׿èß<Ê4@ÿ¦}ç ç3ÿf­% œ–—›Ù]ÂÀy2Ï œv I. œù<á߬þÍÒKÀ¿YzY8O&Ø€³ž* œ§-Ûú¨Σ,4p:Ù€ÛÂÀY:L8ÏPßçÑIç±= †ó|gà</ü›å«†ó´OÿæÉôD0pmŸGgy 0píÁF§ÕƒïN;†VÌ0pMmiào¾€,8rdÐÀyº:8w®ŠÂÀy2ç—8ÒeÁ½Yÿ9Ü›§+¬îÍr)požKà ܛ¥ÿ{s¿×HÙ0Ü›¥G‚{s+5Ý›»%†{ó(ËN¸7’aѽy.Î×hß<“ú]Œ©—R–À»™·DïæQÚ%z7ó-Ñ»iß £ì»yl3†óæiBÇðnZÓ`páÝ##À©Zl–Úp¢ðnnùÔ•ªEºrµdFe˜7l94o% wó(7½›'sÀ„wÓf©ÄÉðnmÞM»é…#»¹3Ù ¼›Gy›éÝÜš‚Ò»YÞ$¼›§¥[2¼›6‚>UÓóŽÉpàÝ´>)tÜ»¹• ‹ÞÍäp´nmËGë¦õErbX7wæ‚uÓ»?ÔÖÍÍWW³`w“Õ´¦ »´d @ÉGì_ü]É‚cþ`ìïÏ ’šuúóÿ\JJëù6tCæ¬K%¥.”•ºTRë² ØjMñw­ÇJj-ñw©cµ0n–§Ç’RÊJM*©u}¾¯úk]Ÿo§¾¯¿{vn›©¾ÃéGzn˨m¢Ã¾¿KYœ)·Ç;+ý—Sy¿XN¢ï²©aý­ß_2uÿè+wy7¿ôŒ±ßÑG>oÔUrp£®šƒ›uåQ¬ë#ŸwÔUspG]9¸·ÆÕQ‹êÖ|Þ¨+³p£ª’…›5éVT³y£ž’ƒÕܬ)bUù¼QWÉÁºjnÖ•G±®|ÞjñÊÁu}dêÎïG¡®?”©ûesyþ5S÷¯eêþ Ì»ñŸÿÆðqÔ/vˆÿe™º§íuÿW”©û¯?ÊÔý×?š©{X ‚gI÷})kGÉ·dúŠ÷‘{`XήmÙÝPk<Û’½)ztø"õ·²éÚx`áP"Éab?öšÇ´çy°lkÏãÓ[«Šùßû¾<Þª+³ùF.c2»×Ûò;† ñ%¾’0彘-Öô––1ì3Š|„1+›-Vô,¡&O½"ç«q‰’í+ {æÅœN¾BÁ+ æ£B5w¬$\”¦mV¥W\°í‰ûÞÂ=¢›~ ®Æ|©øÑ…¤ËšøÎ«¬|Ì ëyšq¿%Od­˜®¾ß}ä\–Gf^˶´æyaEOô–<\Üî(ÁŠžøt^w,$0‘Ѽ_H¸åëzK°ÀUýÙÛ‰µ¥XDýŠ…„›(?{…¥±|K.JÆBÂì#$BÌŽ=%"˜}ùBÂÍ©·à |̾cAÉÙ}=Kæ³ß±ˆp¦ n.¼órŸXEÐÚñ±šw7&]Ÿ/=ùp(ôxKbq>?ˆÑcA¹o§íæt¾•õÐ9¦¯"ÜÚ¨ù-‰Õy¹æûÅ×õ²9v¬ÎËØ2-ßþc¯‰¢É[â«Sæˆå¼©-«çÛmøô@YvçDÚe‘ï4c Ýƒö±Ÿ3ÖónùÙ¦YÛü¸Î:g¬è™Œ„k~OoS¬ÕÍËy71òýÛ—nµÌ¹½-ßK­{îCñ߫ݞ¯ÎßüDæÝ9uAÛ0³ oD²t-Ï¡þ·mOàŠ› jœ ëyÙù¬Þ¬†ã¿ûjž«i8b̸…ÉOoÅjÞm‹l(ðu„{aƒí¹°–—MÙr†Ú (ôm®XÌ»e뛞ÚÙªiº^7x¾×GõmZ>ؽQ,º½Ï³G½øÌ-3ªÝP§­1øÂ1]Ó²AŠÊsX›·¸Ö %Z›GfÉÔí´’8c#mX±Â6-3ýއõàòl-¯¼%ÛNÛn 1íúŒý´Ç-årÚ†Úþþô&xK1›±Ÿ¶÷*±XÌ“=`>!w%gžóá;ŸP¼íÛBÅXËÛ\ª›ï‡ 1ó Á;%æ›o—µÜù¸à­÷´oû*w”@ð¾(%¬–‚wÜÂj¼Ñ¼WÃbžb#±†ñNG(ò­Ø{{˜0ð+èÝ$VóÔË¿VÃŽ$Êç¿R/KÃ_ z·Tü{o—ôüëjJ¡Ž_]ؔķ·ôìI"`]Ø“D™¬×½[K€ë‚Þ­äëšØeåB½Ø“„éë–$rx­ [’pú·‹yòf­+ôîÅ+ñm·ÇV_¹.ìG¢Ž{ŶÛe¯†ÕCì^2²®ØxÛ÷¹ˆö¾º‹Ýš3¬ØxÛ—Á£©¬Øxû½ÎaVÇÜXÚÊ·ß3qö¹:6$¹(´¯ØyÛ_SÌV¿‘B½”Du9 Vµ{i@]’h}«}q…çDÙÖµ;óù¯Øyûe&vk„Ü=dZ±óö[Âï~„Ü=dÕ\±ñ¶^&Nr·ïgÄäxiñvÅÞÛ%&w¯l¨\]É/x†Ü=%-qeÒ þ›v'öù#üXÛhC¾LÑì;™‡À¹ï(¯¹‰ÀÿcrßQ2np_¿3ð(¸Ïõ«¸3pßK”bºpî›ìt£®/~apŸgÀ¸ÜW²‘’ûš"R‚û2} ¹/Ó&û.…Ÿû.€È}—¼ü¿+!àw)õÁÏt…j ð9Bƒüºí4  òë[ü†4‚ßÈé.Àop‹rßP &÷ä pß”Dî³ÍÛlà>ó4pipßœYs€ßRz ‚_†øøM)ý?Ûb¼Ü·z\pßÌ)¸oå„Ü÷ö¯|œà¾ÜKƒà·”‡œà÷¶v¬gø-í¤DòÛ²•ý–¾a¢_v9D¿wòür^ SoAÿ ¿•ã>ÈoçÅ€ü¶:’ßΉ>Èo+Æ'È/·à!ùm5o’Ÿ$;‚_nBðË®—à·s ðÛÙè~[>c‚ßQ‚ß–¥Šàw ªç‚ ¿­è ¢Ÿyð€~Gyáˆ~[«UB¿†!›äwòy‚ülV,„€¬Y1ÑO±WB¿K§rô+«$@¿“´ ôËÑïd‹û•EÂ_ךà¯L2 `¿tБýÊ ìwN‚RÃÀ©Á~²‰ýdYûÉÍ%öSOôÓ8Jô;ÚŽèW¯%Я@»£_A ŸQXªú%#"ú…ð‰þášð÷v6 ÀŸý—ø³““ÛÙiþr±Šô—k4N]€mÑŸôw&úK"ýU\ýå2èï–A@ô—_ éOî8Ñ_Ž ¤?9Iú°ˆƒÖ2á_~±À¿£1Ä¿BÿÀ?óaå øw „Zƒ%ýq?*Â_iu€¿ ry½þm€¿|„?™K¹R øËå*²ß¢É‰ð§åu²Ÿ}ŽøŽÈ~J’+öËÝÙÏ Ù@ö+ˆöÓ=‰ýÔ ‹ýôd2„þlur°ä¡Ã³áW·\éŸ$üeó&ü…µþr%‡ð—]á/mŒ„¿\y$ýå—Eú;Úøôw÷d;ºó˜¹ë"éï(\†ø—KÄ¿4bÿlÅ ü»å|#æû%Ú»"»¦9“hë0hnÔ¨èàQ„) ð$z€s“˜ëÚ$À\—#e‡$ÚÝ;ýÎZ¡…”’òÿ¥â&©$À;ÉxçÊǠṋƒK{žGm˜¶O" FZàQ>X`½7<—Jhx¾x¢™†çëƒeû= ¼?¶ƒ(Ô7àCÓðÉM®œ-£‚GÓëzŽ9ž¨ü)ÀQÊŸ*#u©ü äð§~)ÜSXÂ_NÉ€#qÊpåb1p¦Œ\‰FÀ©fE\)¤§–D€;‡àʾ¸ï/Ê_î&å/õÀ¥~]ÊßÅ;¤üå˜Ö:)$©üiV,·@åoiZÜ©­‚·2ã‘·>eH9ÚŠ×ü@À\~ î"BúSÈ%0´DÀ2à·fÆ”þ4ðn©×Òþ¼‹‚«”DÚŸ¶8$æ( °H•Ôþ”xFÚß^RÛ ýÉÈMÌ8iòW–Y$µ?mF+íïÊ35X¤T  MÑT€·Â¡¤ý½ÚŸê–š©ý]z¿€òòKüK¡ x´m¬Ô¿”i¨þip" i}TöÀ€2üKý³Ü’øÕó%6‡ hº  • (‘ê_AÂC‰8ÎCñOqW"ÀœJýÓÛÞÚù2å?­‹8Iù/|´ØAù/ÏÕ¿”ž¨þ)Ò@øÐmJ¼ei&Ú‰ËÞ¹ôFùÏúœ ò_Ò;å¿=BþSØä?M=%ÿe“’ü§U 2 ÷ VðË`¾ €Ù‡’e &ÞIø`À[³e2 ¤12 fžRsý† ˜¬A0—¶È€Š³æZÐJpÅ`À;}.dÀlAd@ÅæÞŠm*$I ˜ýðÖPþc"`d"`ª®@À;—»À€w.µQÔ L `'·æd„Àûf<!ðN > !Þ©bó…ƒÓÖ@,„w&—kЇ‚ï'é2(ðV°*(0gû À›ÛËo%9"ÞLHI¼µ*I¼µ2ðÑòÐ^ÂTG ˜V2 ðÖ›PËKDÀ[Ö'"`_ `E, `ùU  Wã*õi·QŸ†9Ù=3÷yø=Õµ§ß3ÕCø=Oª|A}¹ ©/7"õ]’°I}—"~ˆ}—Ò û®ìôÀ}—R¾û.¥Ç îëiŽ÷u%S#÷uÆ?ûú'ó‘¶Ò`¾þN&xmÁ|C ÉÉ|#í~`¾ÙR èÚ½†Ðg±ÀJ\õK€ôMm,Lè{ï” ª€¾Yœ¦}3磔ýI(ûåTƒ²_šQ}C‹4’ýª²_ZVú–RÓú&s JöSÇHæ[)JQö“§!e?fíì§èDÉ~9S£ì§èqÈ~Jw)Ù/§¾”ý’@}[)%H}+gFÔý UA÷Ëë£î—“PßÊ™$u¿\Þ î—ºßnê[ŸH};§9þr%žÂŸŽ%ü/$„¿<†Â_Z¨@}[4DÝO©¥û¥ÃË¡o¯´„B÷+Z!t?u–ÒýÞWÕYrè±ù`¾Œ&ó•U ê~¹.AÝÏ¡¼€²_ö@¾ÍäPýòùä±IÕOÔæÛ酤ꗲ>U?ÍÂRõ“m‘Ì—~cÊ~K–t2_ú(ûMj|>]ßi~èçH|‰óýdž"ñ¥ïIª_>pª~iæê'/Z> ¨Aô{RЃè·e}–哚”Ÿ²K率¼— OZ>U $¿\º”ä'©K’ŸôZð^Q©)ù„æ—ÁýrÉ„¼w1D?m+Þ“D ÑOR—D?åÞè÷\2oÂñyË ú¥W…À—±.>Z ¥ú)ÛT?åš…ãS¡ïRýRa¡ê§aXªŸÒ@Hõ“.Õ†DI~š¹Sò“G~OÍ$€{r}HòÓ&É/ñ‰~OÙ¡%ù¥(CÞS%ÉMâž@’ŠŸüXò{*O„?…Žï)/‘p樂‚Ÿì’W¦7¢i¼×¾ú=s¹Q¼§ ñ^ºÉ{)‡RðKš'ð½mã.‚ß­ J ~lÊüNJwLpÄ…ÄWÄ2Ÿ|RüòS#ñ)Õ…ˆOë€"¾‚]üÒ^‚_:~%ø­/–Ï4ùÊ›!òÙž8(à§Eh!_ã’õ¾ÔÑ©÷(Tu©">uÄüÊ-d,¾PŸ *CgGZ>¿&óþ%aOOFô]Â5 ž©èÅÚùH[¦°wiƒ {Ê~BÄë "ž}a×GHßTÞ "^î IÄ[©ñ–RWñl.>?¤½ |}’šÉw6Ó¤\|g LÐ'¶úrÒÆÛïKlˆ>Í,xsjŽ­€¾!çä…áH8 Þ­ôÐõòžx¹J@ÄËœ/ÒõRïâ\Ú¦®—ò%#ú’³€x·²+¢ïI}!}ß9;ËÊÏ–çGH_™'€ñJ-`¼²| ÆË5´ é£ V}šv1¤¯Dým˜PätÄK›ïNÏ&@j Ä»szÉ ¾´2¨Ï2n¡.¬@*î ˆwç<†Âžâ@ÓÇå;ž:ÊzL¨O¾»•’Fª^:—¨ê¥4 ¾+|g™è0­¡ª—ßøî.ÊT½5¤µ!¢/ãõÀwéÛ QïÖš¢ž:– éIsõ´OQ/g]õ ["¤/çXõòj êeS ¨wÉ¿*Q/e>G¼œ‰3¦OVªzé cH_U½¤ªzyÁTõÔÙHÔ“eœ¢ž2ˆ)¦oÈ0(Q/ƒäÚçsª§¥0Þ=(U½”Ò©ê%€RÕËð6©zšwSÕÓTª^:¬CÕË0P©z²3RÕK·7!OI-¥êå·ÈK™B²^Út×'Ø!ä• =ÈzE´ƒ¬W¹õiœ¤¬§d„’õôÝPÕËGSâúbßM±=(U½\y¡ª—kTõW2ÈxI〼[AR€¼\Ó£¨§³yùSÔK'/)/—ͨꂃª—ÃU½´SÕË+&å)¨(ïÈ"ªÞTœ,)O¾|‰z‚f@ÞLOQ¯Jx!ꄨ—KYÅÚù×WÆtªzWºH¡ê]úØBÕ“ )U/'ù”õŠLY/eézP[%ëÍd­à¼;]h”õŠÐGY>e½ùUÖKã$u=Ùe¤ë•3A×£“¾Î‡ß´D=eBå‰Wõ4Ï’ªgCŽª—S¨zÂÌ“.-Q¯rD=9úHyi•ª—œJU/#aëT0Œ(o|§ê¥Ÿ”WÌ š(•5èzi)¥®'Kt½ÂtÐõR¼”®÷ÕÖY¯”§8 Qžü©ëi‰º^R1„=q)…½ ƒ$奥”ÂãyšÀI×£[Œ—^ Ü”õdª“¬§f™—Ì鲞C§uÒ”õd•&ä™ÖSd½ß”Ø;áo¦˜êi>%ÿyxJÀ™Aý—ŒÊò)þS{ÿenCòßJÃ(ÌþNþókJ—•Ã"øof\øoe*ð_Ñ>‹%˜aGÌéò||ÅtHþË $ÌèrifOþËp!ftÉ["®¯_Y1–™œà]mœÅú=ŸÙ€¹6OÌ€1 z Èƒü§AøWÌxÄ¿ ½PF—„»«%¦*Ìè’XAüKg3ºä=ÿ4ˆšÓÕ©µ;á_ùlòn3£‹Œø§ô¢òuæ¨Nü+„_gJTÄ¿œ*Ó×™ApÄ?…¥(¥‹f´¿œÒ%]KÁÊ œ¶N5 ÍÀ’<¶N¥¼–­3ƒ2€-È) ‘ÿJä\iTFÎ;ÁZþ3mlþk‰•à?-k“ÿÊ ù/¥X¥t‘ÐEþË \ò_¶xò_ Û»úå \IOÊé²¾ætI>2)rÚ:%83­0ß³ºd«#¦˜(+ ðQÊc`†ä3wÑ/ d x€yãÀ<ø¯Äíÿ—ÿžœ&“ÿ²AÿžìIèê,ú"ø/µ.ò_ÚÕÁOšÉ©‡ÿž”É)ÎÿîÌãü·Î×о›Y}ˆ™ºü÷ä ù/‡ ðßÓäŒ'ÿɺü{RÉ"þ•Ô/ÁO¦l"ÿiTpü{#GA}jìd?ÍBÅ~I_d¿K-—ì§}qÄ~% ìW4Ê`¿œ¢¤£Sv°ß“)œ‚ý2Ï Ðokˆ%û•t-0tû&Ø/ÂÁ~Ojüd?ú,‰~OΈ~¹j$C§¼7D¿Läè‡W î+:¸O¹¸¯hÉ}Lªà÷È$ðË`#€_6/ŸB½üò;$ø=% àÇO^Ü—ª ¸ïQºß#Ÿ‹È/¥&ß“^Rߣ5M’Ÿíú²?ȯãä—™MH~é ú=T±E~Êò{2ôä'ôÈOÉï‘Òð{4¬üè>!÷åÇ îÓh*àÀ}ù‰€ûžþ•û²åû¹¬Å}%”0¸ïÉ Or_~|à¾Gc°¸O+Fà¾bÖ î{ ÷= ü÷}j¿G>fr_Æ©üž4üÊWNðƒòMêû.–¯^S_Þ3¨ïIw,¨ïVîCQeÅšÐÛë½bÛ!Á6íøçã{M¼Ä’ÿ¨’ÞÌâlñÿ¿Ë£xLýÝïHè=- x”3¨ÄÂmæ7äÎö"žâŸKI¿GÙ´âíKU,)U¡¨T¥’¬Ê¶¿±‡Xî›%Y‹²ª,ɪþ^Ù³ßqá½ß婺<Ë,SÌf=2Ýõ>Jòû Leíýî€Èÿ:3öwŸÁËž6¦å×óów_”}+Ûûñz«zÞ9üûßY jUy«ªG±ªËܾ§TÅ‚ZUĪêQªÊ²9Í]ªBÁGU:HU•£T•Y:¯YªBÁGU:HU•£T•élwyì,ø¨J©ªr”ª²Õ“YŸ >ªÒAªªõ[?Y3àŒs}3d¶·ÿ™ {þ­dØß}…?N†ýK‡}M†ý+Õ}m'_ûš û×NûµY}¶¥$Ãþ óÏßu³?êŠþQKý®{þqSý¾®¿ñ¢ jïd΋mÆWõNH9ÝßQúOß~²ïgÿé¿{Ÿ‡… ·U ÷OÝö%}{¬ÿVeù¯ÿ¢ý¾šk–Âz —C‘ üúög»>Óqì3ôÕ²†ÏðüÉ\}î?ý»ŸÞÛæ-úèõ¯ÿëÛYZº÷Ÿ~þéÏA}v׫üýÙÂ-àämÜÝ&E÷üÌ>2[øðláûW…HÿS Ozðñyšòñþ‹]Â_óïÌ >CfðöÎXÞ[´ñrg?ÿ› ¯X0x»`Ã<[›¸c’haý›AÚÂß}R¶«èÀ¾5[öâe Ý÷[bI}Âu-_ݼ|O½+JëŸm+9xn®íÿe[‚qÿÇã;YÚ†PX¥±Dk/g_몷§g³·j®À8—Et¿Ý¨í.‡­©mqØÚˆí çWØ/——.[zÃCïܵÙpc»HùÔÒ®lÙH’õŒaÊÐ{¿—¶Ê¾ÌþûßGc Ù*4·ß2±}YÉÃ=¯]›³µažéxzB[X ´ï–jÁ¦æËñÛì·‹I^‚ýß߇»-Ýýûưyè‹TïÍØ².S´¿SÑ÷¶ ø1,ÄâXÁæÎ?Ý·’¶µ6fê{ôÛ®Ï %i¶ŠÂ}s¦çs·¥ Š/S½@ck&Ü×g{B>#v éðïÌj¾™]ð ù©—mãæâQ y£![ŸãŽGûxlåOÂÁ²¯ÊVÄ”(½[RA[¡ãZ²O½&·;do.÷ — lAI–›¶Ù¯º¢´›Ý°­’1VàXïìO”Ù³|l+ç\ù:¾gK©r <öýTÔÝ+éÇ02uZsµU[ÄÄ¿<õÙ¬XD¶eQå5º|“?°ã´Û»|q•iSþâOb¦€åÍuÚ*$PÆb¶žMœ´EyS¿ ÅšëxŸM|+ö¹}?ŽAÒ¶|ý=Þ/h÷v¸³aÿó¹¼­N[úx[ÛåÏŠ•˜øcmuZCò‹±d÷ÖV­$^æîž†‚ÕZôŒ5Tûîヰhk¨öÖãú-°ä‰f«gûý‰—mñ)v)ætó'µ÷ކj‹Qò~î犗Ï礲'ÕÙ!Y\‰·T_¼°sòîúX<£ÇW¼i 梥ò,Yÿ´cú öµÝ¥¼¡6¾lÛ*Ъ9üüú,«–7TÓ|¢3Ìcbrÿ`cåÅ„&o¨†Ùñ+'â¦Bë²ÄÞPMô‹jîå 5óÄÜ-í-1ƒÁ¼¢»ŒîÛs÷X¿ö>µx•ê}ßFgc†o©ï#‰nÃÄWo©zy Fï£5› l-uø¯èˆÍmH…þÚáôg$sYÄeÏþtÐߥ -鯱 ÿ®«+»wŒRM Ä¿KóC⟠ÿôáÇ0eç‚ügëúà¿r ø¯=à{⟠œ€=àŸíÕ‹h àŸÍ˜Ä'F)½:âŸ-bA¶ô1ʶ÷ÝLóéƒÔ…~˜ðgMž‰LbŒºôþlyÄø3«”-À_9àïöþlCâ¨ìg3%ØUz0¤?ÛŽø|Ð_³ýǰ@ö.ïú3‹^€ø/¿NòŸ½¦(Áö¶×ÿ™­/$ið_¾òß%š"ÿ] òŸm‚wü³0»Øè€ü× Å‚À–ï$&öä¿K Iä¿ËåáÂÖ£Ç7CþË«!ÿ™¸ŽjÀ&¥÷þ3ãdDß“ÿ,yg¼^ð_¾òßÅ!ŸüggŠ·Kþ»lNÚ þ»D+ä¿ülÈ×ìðïíÌð^ˆî@IàŸ}ŨøgPü—ýùïÂO—èžð—_áï–þòC"ü©Ñþ.L%È~—øŸìg/%VÏÀ~vž0G‘ýìI}²_¾I²Ÿ5Ë8èw‘š„~vKÑ;ý.-öý.NÖ„~öhîô³“ÊýÜÐøôÓãú]¶°Xô{GÌ0úÙ—¿Pâcª:¡ŸÏS‚ýÌU3E¢Ÿu-'Îô³¾/&ìD?û"p ÐÏúÀ ÐOÏBèÇaMä§Kä§æ"òSÏ!òËj~z?ë‰{Tò³+÷Us‘Ÿ]X0ÈÏ.8&Ö$¿öܬøÆ¨Ê»$ùå#&ùYsè×4Õ&ú©sû53\~ÀŸÛ§ãWƒ£êˆþÔ‘ þ̆Oð×°œ#ö+‡€ýš˜œì×n´h±Ÿ9¾ãã"û5ó÷ $†ÕÆE ²_Ó‚á¯í=á¯iƒð×ĸ„?›°þšåêÅÀêÆ¬¨ð×Dܤ¿¦•Ò_Ãr·àÏ…9‚¿&Ú'üÙ9ýš–ìg#ÃŽcÀ~mOÜÙÏÌeñ(À~m~Ÿ¦ $?kWpÈÏÚ90äg­xb‚üù›ägõö Õ›Ã*ÖØD~C‡È¯ ~m±·!ø5®ÅŠü¬ôkjAD¿¬ä×8 ùy¼…_qŸu®W‹üÄ ¿ÇgôÕôö—èI~O‚pŸÚW?‹›é¡C 𶑧П™ãb2% ðý?¨y”¹ú* p`jOP­À‹ Rí*¡åAÌy;À+uC(€Ö÷÷Ю;–@©–(€9RÌáŸèw÷¡Z‚ ðjT6A€6rö’sŽÌ! ð₎ÐÞÆóA€šÿ³ M#±5°”í%BP&íW1ZÙp &Ü€# ]2N©|sž´Ñ0>?2 = ÆÅhÕ/í!ÑJ3B1 … ˜ßd@>.2 }мˆ™¥4 2àuMíÁš Èî`ÀKD/Ôd ¨™O@>.B ·· 0gÙ„À,ú€À›æKP`Šn¢À bAù7 ­U ¨ù^2 Ua2`»oºPÁ€V?©P¿Ú°}B „XR ­ijêO¤@ ¸IrmxíŸ(¹ ØnÞ(1ÐÖ Àx«íÂÀò#``£¿KX®Xê)­è!j > X\3!æ-ˆ¹\(,%à@;ù2¼±^ÃO]¨GJl\«$æ=›¼à@«å“Û;r_’íá<¨™8ÐJ>dÀ&•ŸhOkB Ì›"f5À@»šÜ˜¯Š$˜kY$ÁÆõV‘`- lÐi‚ù“›–3‚¹dGl2½­˜l\ æ“ –° .(Ødâ _ÅhA´‡_QÐ*†’ Ô u›BÁv¾¢`Òí€ó€zÄÀ¶ Q m´ ´¹r¬ë ÅÄÀ&ŒÈ+6:&Ä€vmø P+¶‚Àöü—³ZB ]L%˜L ,5ƒíVÎ'nФ@›–?qLP`©†¨¹0(0 )Ð~‚ °IÛ#nÒ00ïI ¨ëÎïP³n1àæŒZ HTpcå/! Ó)¸õ>KlKÌ+$n²7!pbršhSÀ8˜z!ãhB Å™g,ë&r²š 8á‰H’ˆ¼ ÅV“¸dÀA^äD@ µò~z9OIä£ kÉ\ï rÊ–¨¥ aàûMè}V©ÊùDÆõ’UKR †‰Ä@NØ/*èÂ@‹%ôaTm0"%6³8°QIÒ FÐâ¼@œä@ÌòˆoG´g‹ñ=L÷·…ýÞVõè'Ý äW¬0Plý‘è÷X„ßú='åÄ`?‹{­º?-¹ìgï‘çö³ø¹˜ÒSù³°ÁóçcÓÀ+¤?ÜÇ ý©I[Z`(7–eÈ}u 1Eò§ßöy.„V°¯þ&°ïIǦSßcª¼¢A}ÏÃÑÐg¯) Ï¹€—A}V ”WPŸ5Pà8¨¯ÔWK‚úyt}ÏÛç#§`0Ÿw0˜Ïn©Å‚ùì9Œ€x0Ÿs Bô•gÐ÷¸¬}lWÁ|&ÏvüíCÓ#/)ˆÏ~ñ T_Öà«>2Õßï•Ëï=Bàž]l¯ŠŸGq"HÙ‡¥òyö©Ø`½zæ`½rqzå)õòD@½üM^ù;@/» ^ù €zùUõì‰ýõÊê=ÒJAzå ‚ôÊ‚ôÊåèÕ‚'š¦8/æ˜!§çYÇj8/›+0/(ï1ÄlEìË— È+u8ãYk6@¼¼VÞ#ØàYÁ EñÆP¤JƒïŠÉ|Wº'ð]yn¼<5ø.O ¼+AwVm‹‡º+tWOt—m*à.¯lWÞr°]~@»ò}íJ‹Úå²3^Ю\-ЮœhW:X ]¶L ])²+ýÈ®\L€Ý#”ו6®«g°ËZÀuå9×}ÄÈ™¯>¸®tÉà:«váGÁu¥q‚ëJ§ ®«¿ °«ÇØÕcìê1v9Ï#Øéu“ëò"×å F®{žêì´w½|œ9ã×ek%×éûÖ•Ù°îq°èaèäK"ÖÕK»1tò)ì¬w¹pîC§êÙi $Øå»%ØÕuŒüòvúfÈu—«ˆu-PÝã]OСS=Íù/¨NŸ< .?B]>L@]9Tgm`›œ ªË¯Pg×?Kuöxü( .[:¡N½7™®Äài›ÄÜHWT ]­÷Áè™·H÷Hº ¢Ó¨@ ³jñ Ë7ž³q"Oàœ½Ä œ{¸ÐFœ+8g—ãq.;pâÜc1ûèÍq®œ;pîÑ’ h.»Òœ5ÿUÝœöï§*ze°\~—r¯ÅrÏþôr>û!ÊÙ—;•€rVë‚ß3Pî͈ٛ,·‰0X®þ(Xîñ5Àêå4ß&Xî‘7‘,÷ØÚÜÁr–5íÀ,—¢Yî1šŸ+XNA¢Ü3ÍíÏÇP. ‘äÆÖä¤Zäl=àóÞÜ£÷¡Û ' ·çâ[ kSŽFš6€‚7V›ðvô\o–ê_°›íÍ‘ìfé©6ÎìvNòÛQÓ À•g€³z6âÿàêõÀÕcà<1,¢pÇcì£ ®^²\=$ÎÁL WÎDÕnÉ{HÕn)Ú†ª5sfC‹õÅEËE»u)J/V—´]jvKŽ;jv¶Ås;ÅêâJ…šÝ’Ù‹šÝ¢“’ÝbúœXY\’R)Ø-iŒìW‘$Ø­6eÓô•Å¥€'JvºEJvv"DßA²[½)ÙÍG„ìm>’ì–„JJvÖC~ú6ר$OHvK!Ž”ìJ $»¥ GJvY3%»ò+Hvk",€’uÆ”ì¬dœ»,“ä‡qs)Š”ŠÝâZ­;úGàÞ²Tu‘{ëýˆãqQ±[X"—`çÏúø¹¬ %;;&ž»Å¸R v‹¶ vK¢ì–wèßéüµF3„`·fC*& vKr+»ÅŒìò.)Øå3§`·&ÃÌ(Ø-Z—¤Ø-F²H±Ë‹ŠÝ’±€ŠÝš W£dWJ ÙåS²³Wo’Ý¢Æ ÉÎÞ'œ¤ì¬yÅJ 5»eþ’o‰v×R-$»¥xTJvKHv‹²Ž$»%‡Œ"÷Rçƒdg_Eû°o–hvùuQ³³ëk‘{å¡Ù-Ù¨Ù-ŇQ³[”!(ÙYAø´(Ù-بÚéó’lg=8à-d»¥È$ÊvëÂGJÙn) ˆ²e£¬xç=â‡wÓÞ\ MºÝJG*t;}%Òí¬ƒé/u»)ou;}mÒíæ™A·[ŒR–n7厤n§¯_ºÝ²ÿG$"â¹èJÝnI- n§›ºõeÁšíØÛI¶›rÏQ·³®—<‡q•Þév6€ LºÝ¼á$‘n·˜ëAºÝJå ºÝ¤Bº¬!”Q·[ *£n·Ì,Ýn~¸ggîÍGwÝn²9P·ËﺦÔí,jþÓ¼¹º,ÝnÉ+¬È½´aB¸[Œ ‘pgCûøîfF÷A¸c\·t»‰À év*#D»©[Šv“aš4næKÍneX4» Ó%;›±„(FÉn.xè©ÙÍTè Ù ÅÖQ³›ò=R³›\X”w“é2h/Ãø Ú)°9ƒö­-ÑnR¯¦fç™o?4;%ñf7èzf7|ýã[ržÇù£„Q{ ¢f׉/Òì†ä`Dí¹ynFíÑšõ{Ò€KÀ‹%¥¸—Ë›Tð,é‡w³ß ƒ‚—‹ã4oÊŒ“ù[X¢ü-xÒiÞd×é[”ËCé[&%š7»‚镾En!š7‡R (}Ë'uIߢÔ,Lß’VM¦oÙ²j2} ×-JúÚÓ`ÞJŽAó¦Eåï½7'Ì›Cêò·,ƹмÙ7=–toöéÝ›&¹7-·y³ß ¡y³Ó "óf©æÍ¡éÍ›CÎ8š7‡&©ÊßÂÞVîM…ò+‹²н9nxœ•¿E€A÷æ`œoæo¡h.Ì´JàžT8¤ì*Kã| 8ä‚" ZZd z–Hî]æzÅ$Á1W ¨hz …à_æMëò¹iãÌ™ô08ög_ÖBT¦²àÐôŽ,8ø™- ^û`ÁqD‡Ìß2)ÿdþ¾²à`¢à`܃P0 Z†òSE=O"Ë"$Ál‰$Á!bZ5¬M¡‚CÙy‚Céd‚ù¬H‚#¶€­MD-Á‘¡Á¡$IÁ¡ÞŽ 8)$Á‘ìÂP’à›$8èã ŽLÔçHT. ‘`©&HЮ88$˜ï$ÈÁÁDJà’qvLà2•®… \äñ&Z½ ,p ÅñÇâ9кýhJàbîìªïeÚƒÌàBZS—A瀸h¡‡8” ‰8s Tž†Là":¸è¦”À%KÀ… 2 sø;­h™¿EVvåoÑ'K És‡‰Ñ®¯ù[òæoÉ`@æo‘‘Kù[€¢ü- yÈü-\µvæ¤Ìü-6˜I”¿E3~æoá"—0°kz¯ü-šb+‹2~(‹æ÷Êß’5mŒc”¿å}{aÞ#f=ÁεåÌßÂå½Ìß"Kò·\7a‘ \4GVD + Ô¾%C »Ì†äÀþ|áÀ<ҷЄ§ì-ò«)}Kþˆù[ œù[dX#vÉ›ÊßbAºœÌßÂq|]ònMár>,œåäJá‚O›0Ø9ç väÈ.J;¤ .\AÍ.Rx•ÂEna¥pÑZ`p#þ\0ÈÉJ¦pQô'S¸ˆU™™¾‚’ü:Ûg6Xß®b]%ÿ,Kj’ï_þ]ÅcþXrð |¢<ƒJ2 7‹21n–dîa’s¯yÆURªBQ©J%Y•o¡s×<ã*ɪX”UeÉß;9¸©©¹ÇäàG‰`¯¥øŸöß™÷ûÏ`ƒ¿M_üõ“²Åf걪ÌûͪjÞoV•G¡ªz«Ê¼ß¬ªæýfUyªª©*åýVU%ï·ªÒQ¬ª¤ª”÷[U•¼ßªJG±ªrªRÞoUUò~«*ŪÊAªJy¿UUÉû­ªt«úÉÁm4moÇþ¯ÉÁ%9øoéœþ®›ýQWüó[ê×îùÇ-õûº~{rpKÕ·û¨ÉÁ‘ÓûüjNï[þ(5ørŒ¯û½…ŸÉÁÿXön›Ÿ]çÿÏÉ»ÿšµ%ïþËËW÷û U˜¼û¯gð~¿ =#,mìÞÏGQ¾-ã¸<£ZØ+‡Íd̹7è-¶Vدâ²¾Y2q ›W]³wÕé}ÔÍçó\3œÊz™` C¹y~ï±Ç|ž2±ï9< +fFÃpÞçóœ|ÃnŸÏßHª<,3ãÁZZz\ëð5¿†‚™Ž1?|yÉ„¨Éë;¾R¤L¼cÜ-þ}ÄîYŽ™FsØ"¥K:L 5lqqìÈŸW‹ÌÞ¶«T0é0íÃ%H+Ó÷È í£Å°ÔÊ× mÅ;ýa)„]Ö¡L2,­³Ë:›s7;é¡_Æ-™Æç©Ž©ã K_=g¤¨^Q-ã¹G ‘ï¼gÂ1ÁW7MدȎû|'ña™Å ± ”ÆwdÚ±²Ç!ý aÇ-ïQò„K`fñ¡”Ym†)¤Ï.v’aÚ¦k°|QkùLÍ] 3Ù;$XfHzßÿ€ek)cÝWH°qÐoÉ Ë¢ø^4Ûa™`öÎU]ԎǾ"gÈ®½%÷_`Jq6ÛöÓ¶&÷{ÊûÊ«?­=}§dÛ- Ok¿ï,4X,¿ì vܱ ÿ~ï#\rx.WÖíÜñç,"ï@¹¼¥.¬Œý¸£É×–Ý|¯No¨ÖR}OÏHΛ·÷XÞP¥ì¾­§‡þªoöØ:¼8.ñ Ëyf¼„'ê±ß‡\=£š˜§À>̈wÅ;³ú•k…ÍÁÙÒ6ë ±¿ÇåÞ=¼Ìõò–<ÑRÇùKTúo¨‹Ké¾9ðóDÓµ½€Ý*A{fì#Ùk ³]ä¯þ˜8¹íŽàV Úwb÷V{VÞ!ßçÎ[*Ÿq¯ ,YÝ÷9œ³ø|s?o©4çøÞWÞ&ß[_y|÷·9ö«g<Í6z+çöýÇv8T|ÝÖ·:s·õnGXÞœí;ì-•n"ßwøAçÕ¼ï0$X¾íp´Tø†oÑ‹ge„57 dºrSfsÞw¼½hºfXo‡›åzCå1Ó1½¡²Çô}‡ýCBgèÛs¾ï/Ø·žáˆJÆŠ† 9Åöþl§¾ëp´Ó'Æši±ÄÞN±Tîû{3åºä´Hö0!6^îcê¢%}"uF61ßwxú1±pàÛ»S‚K ¾í°·Tt¾íð=Jû±m‡£¥²;÷‡½¥Ò)ñœ>¤æ“±}‡÷ÇÓ»–©‹ù)|Ûao©ô¼c_óO&þ;ÔNmÍ·v™˜k'¾å°·SS*â~žPu˽8šðyøžÃÞLù1ÌÞ;š)ÆeßsxúyôêbêßsØ›©)eQ³­ÞUão:ìÍ”‚ªo:|ãa^qöƒ•fkßvø³šªÍJârP凜6ŠfÊ{°uFo¦ÜðdÚêi˜šÐ{ú¦ÃÞL9vû®Ã> rÐð]‡}@¥ŽkÙܧ‹dnåÁ<Æ÷Ž ŽÓôÃh¨ü>mßá]½ŒÓfm×ü¨ùÁˆJÛœ #*¾ñ°÷s‘|ßaß>€Úï;[ØŒã.­]sXOɶ~àØŒ_ÜVÙÑÙ¦Ã7>¿èvèÊüѾï°Ï©º¿ÓÖUmû|ßáÝËèüŽ)U™ Ò÷^Õíû?p’Eó‡§KɘÛúÆÃ·ãDLÇmßa›ñ»-ëŽT9 |?€Tg´xÛuø”Ô[#ªö}‰¥X~'ûÛðŽ´ŒÔàý­i»‰~W¬+ô³Nî Ð ô; F!úŽý#“I~¶uoËýn·HÆ1~7r‚ßÍ2rßM%€Ø÷X¦ß``ßã“Éë[bß3ÎOìSð ©/£º@}½„¾ y"ô)­¡Ï& -xÈ©¯%&‚ú‡0QŸi–.ˆú˜¤CÐ׎%èSÎBQ_Ó<ŒÔçcxÔê³üDûƒú÷”õ)ת¨O)‹D}J$$껡€>%v&ôYAû€¾‹· æ»(£‰ùL ™O pÅ|­]̧nb¾kê0ŸÒä ú”ëOЧ\ù‚¾KóuB“àŠù”ÍXÌw1Gˆ˜/!ó]…ïÈCc‹˜OùmÉ|Ý‚¾|æ„>¥™ô)µš ¯T èSveqŸý*^¹Oiè~J·'ð³ìaAZà>å6÷]Ô&Å}Ê]'îSnq_~à>åñ÷)q¹ïb7,îS:Àà>%è÷Ùs^‚û.7ÁOiô~J,ð»Ø} ü®KèðczuqßÅUÜwÑÊ.îs›eð¸ïâ4OÜ—í™Ü—7Aî»è&÷]´øˆû.ÚñÉ}ãÄ}“³Šû.j â¾ .aóW‹ú.jʾ|Ûľ‹"¾l«Ä¾‹“Pqߥ¥rŸ²H‹û.*²â¾‹Þ&qߥ¸ïâÞâ>u8例¼ÀïJøùI{ù]š$“ü”oQèwÑ=.ô»è¿ú]Ìn%ô»fT¥ä>»tî»例ëG⾋ %â¾KÓ_p_^¹O} ¹¯òܧOOè§$uB¿–P ô»4&ú]ôÕ‰ý8Œ ýÔ1 ýÔ ý.ú·„~ù…ý4ºý4n ý.zº…~j©B?k˜ñ©ýÔ„~宫1{$ú1'§Èï¢ëKäwqS‘ßÅÕu‘_¾\’Ÿz:‘ŸÒ‹üÔèD~åW ?d"¿|8$?õH"?é"?}׿ü~«ÿ?e„ø)=¾ÀïJø]ô— ü.š~Êî.ò»´HCòÓÞ"?}’?¥=øérßEÇ£¸O¹ùÅ}¥q‡ka_^0±O)9‰}ú’H}Ѓú®„@PŸ]~©¯q»:aßÅthâ>ËxIîSjEq_cqßÅ`WqŸ2UŠû7¾÷)¹¸Oi<Å}m¨ܧ}6~†ü—A~iqÈ~ÀKôkE~»nŠü# E~–Íp3Ìÿ7¦í&üÅJb²_ÿ“ýða²ßåÞÐ` Tʆ/ÙO3É~4o§ìG%FªŸ$ ª~ZÒ“ê×…™Tý´)ï‡ê“ ©~’ ¨ú)^„ªßÐDŽªßÐŒ(Ó­T?M‡f*ÀÁU€c}•ýdŒjç6àR@L.”³X8¤åZfÇvn“)”×NØ9{®ùeªæãæ\táB@‹ŽŠ•"`çž“BÀÁŒ¤B@9”…€rW û#ÔNB@ºáE€æ“„8Ú&É\ À‘ìÜ,‰X @€)xƒiHv&UvÑ1pºÉò"‹ÿ:=Bâ?ís'þÓæØâ¿üØÈò= ;5 ^/ùo0cøo\ÒçÀ2K“ÿ_"þŸS]?á¯sÑ€?…t þ†€‡ð7]$øÓ¶‡‚¿|,„?…Bþ: èÏ,ÊÑþF,¸ýäMú ™/‰~C+KD?í¦(ô³¾2w€~ùª‰~Šî úi;E¡Ÿö8ú™“úSò+Õ€ýñ!öëZW"ûu¹È~ù# Ÿ"„~òc ýäœú ióD?µl’Ÿ¬""?I~rœˆü†µA~²¦‹ü"ð̯+ðSˆÀ¯3 UàG²¸o0ƒ„¸O{‚Šûúƒ %¡_§5Xì§½EÅ~# ìÇ¡Ÿ¢2„~ÜΕä7¨Í‹üCèH~ƒ;‰üdä§øšý¸Âš¢]ý"¿‘ú¢_gh¯Ðop ¡ÃõD~å¶@~]‹)$¿lv@?mº*ôëbi¢ßÁ®âB?EWý:Þ…~ëžB¿ÎtÞB¿žòÝæˆŠé›Ð¯kEèG¯—د3šØ¯k¥‰ð׸‘ðÇp¨„?lb(öëô‚þº=È(üqvNöÓ–Ó ÜÂ!à¯sDüi™Nð×ׂ¿óU}‚¿+a ð׹ʞðÇÍÀ{$²ßÅ Y±_®Üý¨Rý´-Ðk˜"? X%-_.i‘ü®ÝxHŸVüý&ö˱gæÉ~töýJ®nòž{ž/À`A›§²Êæ¹.$“Íó,éÁ{™yUÀg”þL_c_-âkT|}€¯1tJÀ×¶%àkcÅ{ÊË.ÞS†uò^ÞG½v‰5¡÷q‡Xáž.Žª÷QuÞ§™‘ô>y¥÷ñb¥÷Ií=Mé}š’öšÐSzŸ é})ËöUâÔû½–zSqˆöšÜ˜¤½&}%hïy˜Ý´÷XÄÖ]¿Çá$à ´×$X÷òj€{ÏÃ̂ĽçaZC➇&àT{§™€ãScGÜ{ù5A{MKÀ=;äêUñËŒèä½RÞ{ÐÝ’ö2Ó:h/“­’öžG{Ð^Ö°Wn°W°÷øRaT ÚkÄUÀž’º’õ”Õ¨WO¨—騉zÊiMÒS¾gžöé5v¤"½&·.IO{ß‘ôÊ! ½RqÀ^ÃÜT¬—mÐY¯‰¬Ézƒ±X/¿f²^ãÎob½&™”¬gõÐó‰5ɶ`l&ëåÙÉzÜfB¨—''íiïÑ^k2œ‚ö²¡ö§Ó¢½l¶ ½lÙ¤===À^ùûQ @'ëeÖSz¡^9$X¯|¬`=}à =kj ˜¨÷QrG¢ckƒõ2×4Q¯4Y Þ£­&ÈzÙPÈzÙ7õ²Û!ëe+ë=Ú—ž¬Wë Ø{|ïí {µâ€=;&:JÂ^ö^¤½z}A{é=!íÕ³íåó"핳ƒöê1A{å\À½ú«À½rÍÁ{åäà½À{ùÈ{µäå=~¤=åH&ìehÁž¶¬ì©aöô5öÊýö4:öý4„½ú«€=å©N™ ¥d½Ç'ã•õÊ'ë5Íáƒõrè$ì•/°§Ùa¯ü°W>PžVî{¥dh0Åë'ì•sì•· ØS†²^¶^²žö$!êå&¥d½òlÀz‘óœW¾©à¼ò‚ó´¿0/·œ æå슘÷øÀÇL ¥ÌçNÌ{\¾Ôa,Íc6S"(/ß“ò2á<)ï£$FSzÞyVé‹ yÚz†Œ÷xr¤øQ@ž6{ ãå8NƳ.3òúò”±›Œ—ã8ãer|2^Þ2O©ÐIx–~£$/7"á%Oð²^^îýCÀËÞ$<ËÎIŸÓùð›$\ÕÔY^,ïñ¼\(qÄËtù@¼ÜˆˆWäˆggê ñ¬Ÿ"¸ñßð®ã?æQ™D¼/Y¼‰u–âµ}`¥siUÇ{gN\C¦Ž§ÝY¥ã]„Péx©¤ëSqÝTÄ ¹n]Š©ØÍ›æ‚Ýf’ Ýfn<ÝîX£ÙmZÝEv;õ¿ »ÍÅI¡Ýá^¿D»£¢Ýárj ÝQD Ñî< >!ÚÝßðÆ$ˆín-ŒSÉ»±ÿ–ÐÎÛ€v·ŒJD»[Ž7¢Ý-Û#Ñîf°ƒÐîÖZ9Ñî¦T,´»ß| ´»õ^ äÝ"' yw£­BÞydžÚöÃB»Ã(* y‡+ÏòóaHȳz«d÷¾] ·$»ý`^BÞiŒð!ÚmìP™ñ{Ü¢!ã÷¸‚$%oë*yûV(”¼=«Œ·õÄ)ãmoôßvצ·A:Þfžbéx;-£Ðñ¶…KDÅ@»-…¼M…„¼\·Òñ¶¼‰Ôñ¶§qü–pwït¼¡€)âÝæ´Kx·¥¹+€O_€ø6í¼ à»ùÉ*€OŽ<ðÝ K|Ö}#Þ)ÛpÆïÑ2‘ñ{ñ,½·i¾dðžâ3x"¤‚÷˜æ=ƒ÷Ô[eð’Ñfð^*xqï¥@Èà=ŹÕà½ö¡ä-æÌQðÞC÷eï1œ˜Á{êã¼gÝÀ2*y´ÌdðžÜ¡ ÞSÜ¥‚÷ä¯PôžÈ]Ñ{ š¬Ñ{­žâã2zï «r‰ÞCîÈŒÞãr{FïÅd.C÷ô¥È=Æ )rOkøŒÜS$œB÷—[b÷()vMGBž²0KÈ›L÷šÁ{y­3xO‘o ÞSD]ï1IÑ{|2½Ç࣠ދO?c÷øaeìž‚š»—vŒÝË!v¯ö#v/~ã¡{+ú!éx[OKÆc»Ç†]b÷h¨Rð;¯ Þ“;JÁ{l”¼—% Þ£k:ƒ÷1ð¼7>d¼RÂཋ¾5¢ø¼§oOÁ{R €vSÁUÔñ†¢0¼·„m Þ{À«D»ÉKïyHη‚v Îà½86ÑÎsŸžÏà=iå ÞcF÷ ÞK=Bžå‹Ö¡à=© ÞãXH!o¦BÞ+BžR~JÈ›ìÖ2xOR2…¼ùÐbJ!oª-PÈ›Œ½–7YJ!äÉ÷$!oÜ|‚ò¦Ü‹òÆ£h8ySa”ò¦®™BÞL¸‚’7-L%o(ô“JÞP¨-¤¼ÉuAIy3ü\Ê“¬M)o(VJžòóJɳT¾ñ©SÉjÂTòäQ‘’— ŸJÞP€$•<­„;ØcJ)¯3lIRÞPÜ,µ¼~É‘ -¯S⑘×»ˆyòÙIÌSòiŠyƒÛÆHÌKݘb^—‰˜b^ç®*™Ÿ ãÔïHá-]¯9@ìÜŽKFÎ)y@FNÍ3€ `'¯ÿ:~øÊ|@ø³¼ÊÏ'üÉoEøÓÞ‚¿õÈ\ ø[Šƒü‰DšÐþ”K†ð·—Ü €?KÒú¡ë‘\À_cÖÁ³ë þŽbœþ" ‡ÛFˆþN1mÆ€ud#ý¥Â ý®šAG“ Òßf'ú; ­!ýÍÈI‡[,þŽp€ôwÞ7z韈àO¾8Ásù&ý¥E“ô·è­$üaÚ ö;ôË‹ýÇd¿E9…ìç ®ÊzvAå„¿£È>°ßáÞb¿ÃM|Ä~F:8&ðïpáßá>OÄ¿ÃáßÉØ:àßa6Sáßažfáß‘ÑPø÷ž‰žÕéÃǹÉNÂ?= âßJÓ&ðO{Ð$þ1‹¦ðïd8 ðïp·áßaòÐ_~¤¿cêurž·%Å éϪméä´Oï YKŒT‡ò:é¯\ðhU‰˜Õ=‹öGú-!7#ç€'‘x€ùE·%žö5{Ëáž@+H¸µ~A<²Nóá-SùóaåÜÏCâž&lnÎä€[Ö`)æBð4š0ÁÖ Cš%Úb.¸R"<€û޵&!à&“w:,Á€›;6·fdÀ-³p39¶p3“¸pçÅ€[YÈ€[v02àwGÁ€[³n2àVz2à–eŒ¸™œL¨!R¸å.nÍÊH;}–A›Þ)Bà¾H›™ES¢›0PÁAÄÀ¡‰ÀÀÍ}܄ֵÆüh ” Ü _$nM”‰»5â$0p8‰…›=±0ÐÎþaæÜl«¢ÀÍ`RàfCL äÎ;¤ÀݰSš(p+~Œ¸9ÁîÅ[QàÎx@Pà–q”¸¥" Üô…'>J ÜŠ+$Òe/œ À"îN@ ­@î7çdJ)epa¾jA ²Y—Þ‹ »´$fvfpáÄT8(B‹)›dîf%œÌ¢.JÏ!ä¶(™ÀE -Jà¢Æ+Ô¢“¸ LœÙa µÿ›ОÉg$ŸLµJà’[üé4%f­d@D¤$2½ prG¤$@›E}z9µ¼ d4Y MÁÀ™ÙZ€˜° '—¤å~WþÚ[€éu&&© µO@Ì €C @f€Ô’¸{Ù.-™Z·oQqJnX–ÔÜ¿ü»<ŠÇü±ÄÝˈ窙fU’)²Y”Ik³$SdoßeªæWIVÅ¢¬*KJU¶kά9ÀURªBQ©J%ïÄÝËÖ¯%îþ.íväåžJHü üŽÄÝßËr½rM-üõ“²eúªZ=ŠueNnÖU“r³®<ŠuÕ£XW&åf]5+7ëÊ£XW=Ju)+·ê*i¹U—ŽR]å(Õ¥´Üª«äåV]:Ju•£T—òr«®’˜[ué(ÕUŽR]JÌ­ºJfnÕ¥£T×Èß틱ïo~œ¿»ÿ­üÝß}Œ?ÎßýK‡}Íßý+Õ}m._ûš¿û×Nûµu}M¦ü5÷oé£þ®·ýQüóì×^úÇ öûº~{þîe‚ÌÛœJþîúéÏ6khã×Ònϯù»ß²ü×ß‘¿û_ÞÂfQýëçï¶µ£övÐ?Làý¾Ïÿ#ÿóSöì_ËâýüŸ~²¡ç~Ê•þ=ù¼ßÃ5Ÿw)ü§ù;òy/[O'ù ì^â*;­¯ äq$îQòØÿ¶‡|*¹lyÿ¥ÏÛ·kŽ’w¨5_§j™>a6>OTôD‰‡—>ŒàY–ÊnUé²ms«7¼ZkÚâÞ“qoÁÉ: V.f< C̲—Íoo?°¬Ä^ÉWxůbÕÑE|ý·­îÝñáøªÂ2™'ÖÑ;¿muïù–iîÞÏÏ& ñ+_Å\÷¾<¾’ÉÞ‚;Rëèßo/5âéĉBêñg>âò,RåŠZ|ä-¹£¹Òß³ž·“º®ì‹ïí±Å½šp=o'åÍU߀m\;‘Ò,º-Ëùôzã-ïÝõ¦ž0`eö¯·äŽæÊżeþSo®Ì#±ÌÎéÍua%v™sÔ›+=UË|¹×Ç©l b•[ÛïˆÖ寣äDs¥î¸-Λ+•ÒíIl®8óÇØÒž€ˆß’í•Ùy·% ñöšgŽøJ,lKô×êÝ–9hÒ¡lÛâ¹?Îþôh¯”¶oGüÔc,­’·WÄç²/¼nÏÉ·âGùm}Ëù–9×¶oG¼¾e–¸m-cÇ{qØÛ¾ñþ–¶¶ýÜ,íÛ÷#Þ¥mÛx"fµÅÕÜW4XˆYÛ¶#f{½¢äÙh¯¼Ûޏ#¡V¼>ߎ wŠÛ¶#¾F½Mߎøþ(1¸ª×Ù¾1ºÀ'j¶¦1£¤Å¯–¯ÖX¶ïFüñ@m/¸QF”í»¯(qȽ•²nÇ1†W3uú1å~á‰N”Üh¯øø·Er{d(…èíÛ{²¤†oÀöA|zé‘·oG|J‡·-×Ì=JüîöíˆïÒló'œï܇ÎíÛ?¥ÿؾñŒsù”`û~ÄO‹¶ïG\‡Ï=âSÇ'à›#™OF¶mFü\õ<¾qͲ¶m3âÈ[wø«ñ•¢÷¶Íˆ½½êê|3bO\Û¶͈½½Æpm%ã+3Õl[§]ý[fݾñ]Æi.xò³ÇØ*ߣ{´WßÓ–' 0¼"êmûfÄ«ÖëV«o¾öã›{r16zK ½cÐy¢Ú‰á•°mž´È0‰iÐö½v™WlÛtÀ[+SŒnߨg#‡§º1¼"²à »/‰Ÿ¥rðXðÑw%¬<΃? >µeQA𙡅q@ðQœ^q`ýäN3)pî[ñРÀö¬>ÓB–%#XøØsHøÌÌø ðÑø¶/œ ðéáA|œQLØÞe‚@;­‰k»Ì1 Ý®Å€ìÄŒ€v¨4ÚŸÛh_m!`ûêË&¶¥°â; Rá\¤h ¸()¸ÐqÌ€‹Ââšíon\äòcT #à -&ÀÅCS¸¼E€Ýà"{h`ˆT¸h­3.2".¯"ÀîࢸkFÀšéÆÅ•6.A€‹Ô#à"Ë#à"Ck#à"w#à¢<FÀEzFÀÅL/¬Í*¾C! çk#à"#àÂý¡pñ¤+\¤ ÀEž&ÀE€ 0~BŒkH€‹w‹"ÀÅü"\”͸4ï‘—à=.S^äE€‹y@¸ð\Ÿ"€‹ Û¸4/3p‘¯p1Á9~—¦Fà"`w pn‰þ¤ÕøÕÿê¾øWQ¬A¿ÅD!üëŽþE ñ¯·¿~Lá_”ÿ–Ÿø·(öªðoáiéo‘}·é/ÚBú[Ì¢¿E–Ц?°ýµ«²è¯xÓšþ×ôç‘%ø[|l ø[GÕð·0F½Ù¯{Fì·ˆf„~‹NN~‹Ž|€~‹ü¾Ì~KÓÙo‘•Ù¯‡•دûJì·TF&\Cö[š!É~ý͉ýn6Œ~‹9„~‹,t~ý1 ýz` ýÌ~»N­ÿm:–3ümχüvÙQ›ü6E¢·ø·i#còëQýs,k“_?$Éo—˳ɯž2”Èo»7éx$?S6ùmþvD~›Â½˜üpÙè·ÝbU±ß¦øœf¿Ý°*ösˆQ³ßæYBì·Ë?Áìç°üf¿M'nb?»…™ýŒVì·é$ÏìWQe¯ûmò41û9ƹÙÏáÀÍ~ûbiì·kû`ö³!ªÙωÌ~vì3ûí>“ûÙ‚Ôìg R³ß®Ùo×""øÛenøÛ½òOøóþjä|Ô?‡#7û•3 ë ûíJØmöÛ½ûûí:ûú9¶¯Ñϱ¦~ÖlôÛ½áú9ʺÙ/~Eösðn³ßÞ¤GöÛéX`ôÛåã#ôÛ…"¿]>U"¿Ý²€ÈoW“ŸG¾É¯Û+òëžüEÍ„?Ï&†¿Ý‚—ào—Šáϱñ »|þ Š möÛ-£ˆývŸˆýv°‹ýÙÞðg/bÁŸƒu›þÈô·+[¬é¯[#úÛu4gúó¤díoó~PÚŸ—ÓŸâ¡þü=›þvyâ˜þvƒ‘èo—IŒñoWœh㟿póŸR1ÿv}ÿvùÐÿºû„=d… oüÛå¨mü«ÅÞYø×cKøç Æ?‡“7ÿ9`¶ù/K°´:¹‰ù¯G¿øoS4 ó_¿`àf [¸É5U¸YnЬ/t¶ à¦`îÛ‚±¢nfqŸçCƒßö+ðë¶üº-²ùT̃_M½â<§ê©~›| ~î^Û|>…}›Í…}öýv…ƒ¶èW–{6ùÔ¹ocŠƒ¶ø”a— >åùÖŸvŸ¢¾ÍÌdƒO`|š¢lð©|,À¾­qMŸÃH'‹Oåû6YÓÙàÓ0dƒÏ‹SáÇàóK}«­àlðùüýV%\k{O¹·½§ÎöžÚ’´½çMs‡¶÷tÍ6øTÕ¶ø´)Ÿ,>™¶ >o†£²Á§2ö´Á§Öæ6ø”¯D|Z4·Áç­ËŸ7ýÚàóÒœ*êó¶¯->o}‡¶øô›±Å§ îmñi¡ZÔ×Æë¶ø”V[|ú ËâÓçt¶ø”±,>»ZY|ÚŠÚŸ "aê[c ,>A•,>OÃØgkSQŸ2'úìVeè[=!ÙàS©‹ }«ÿ}öð1ô­ÚqúÚWÐçTþÕË,>]’ÚâÓ_ oUJ ÿôM‰ùV%h‹OOQb¾õWÌçDNmò©Ãú0ùäÆô7â~›ó˜E4çyДÖÃ:…1ï¤v‹|m§i‘O»ºù$fô, ô$XOï {túIÖcsÄzëäæ§¤5=°ôê¡Ýü”m Üü´¶›Ÿ‚³6é™)MzFH“ž6DMz ];õdán~ÚõÌíæÇn~›\Åzí.H7?ž7êyŸ Ôcp¶&½ö”“Ÿµ“žÅZÞ íåg)Ö^~:5ùxù-”ýäåw ÿìå'OP{ùµo ½ü$ÖØËO–í姤çíå'=뛆=Ëró£±O{ùiŽ2ë5ÊËOûñöò³œ½üv¬vzv;5굡¨PO/×>~ît“^ã—|ü”7®}üÜ5öñk>‘5•&=O»øY—‹ŸÎÚÚůd´†.~~Jûø)gûøiMj?¿'“žóÛÇÏߘ}üü¾íã׆™òñSÁöñëzäã&ŸZ•Ô]&=iëvñ“W»ø)ÔŸ]ü㞟Ҹg×þ}­× ÷úá^+ D¸çƒ˜ý³(5îiSlÚ³ m<›¯„{J×6žŠäØ6ž¶[3îõ¯dãÙØ(ÞS@‚æ=íTÚÈóz$ûÉÈSǺmä©Ú6òlCO ¡§Â9e0Ðj_›lÊÎóâ ŠpŽâbCOÁGzJÞní,(CO…hÁϪ’? ÍülthÁ¯ 9%øùWmìy9ö ÍQ´˜ãW2ödö—üÚnh“üܾ6öÔiˆ?© cO™ÛØó¢¥š)p³dÚÆžŠzÓÆž—hM‚Ÿ°[ð—T7 ~cé·v¶“±§`{*¬‘?Å©kÅopÏoů ¤ø…i§Œ=}'{ÊúX¸)Æl+~–^­øÙVÀŠŸ{ÇŠŸE^+~2JjÅÏ«âÀMhÍ›¢Q·±§Í€mì¹tô{Jþ´±§õ{þŒõ²;ê‚­=UkK~vrokO3¬=-»ØÚså`osOÛÃØÜÓ»l›{ú ¶Í=µå·¹g Ž2÷ìšmmîÙF—2÷:´¹§Ìeîiâm{OFÁk{OÚG·½§á:í=é({O;äØÞÓæŠmï);MÛ{6†ÊÞÓͱ½§dé°÷¤›™Í= ”mîyÿõR?ÂîÍöž:sk{ÏŸ Øv|¶÷l4¤½§EÕ¶÷t‰í=Õ]¶÷”‹rÛ{Ú¸í=÷öž‹âB5 ÚOS,X‰C¨ÒÞs±'Ÿì=%¤ÙÜÓÈ)kO[{êH+¬=¯³ŸïÛÚÓ8kO‹,mí)¥­=erkk϶۔µgó¤­=m“ikO)¸¶öôKÚ‰#¬=uØckOË,¶öTÚǶö´¢,ìÏ×Öž¶°µ§coëÅ?)üívÃ#î¶^ öËîöò±§œ+ÚØÓä*Ü%ÛÖS+{{@eê©ÇØæ¿6õô}lêi˜´©§Åb›zV(†¯©§LÚÔSN=6õ´E«M=åŸÑ¶ž6<•­ç¥Yß¶žÚ•µ­g›¢ÊÖÓmcOËmì©¯ÙÆžötµ±'³µ­§|ÙÖÓŠ¨m=9¯m=ín[OA¶ì‘_hë)/f«~Ê“ÕoUZ«~-ÑÛÔS§åmêikU›zÚ^ĦžÿmêiD¶©§g›6õälcKOšDðû|¿ O°×13eGtYd ïßýU_¤Kþ^üï»v<#oà’Ž´­¢zÛ%i{ÌTGŸ¶ª¤«RQWÕ%QUÉ›çç©Q¡$êQÁtìﻼjßgý3±¿3Ê÷Y‹Ñí¸Æçå ~õ¿óÚÇ!‹ÿÕ¥0Q¿Eö×#ä>·,"ÃÿkÕ[µƒÿ\£š:æ·jʘ߬©/bMyjêˆßª)#~³¦¾ˆ5å5®Éñ¾]SÄûVM¾H5Å5®ÉѾ]SDûVM¾H5Å5®É±¾]SÄúVM¾H5Å5®É‘¾]SDúVM¾H5ýhà3ó ÿ+øDÿÓõ?5õþÆìüÏßü@ÎØ¿ùþª¦? ¼ÎwÂÈHàÂû·B|ÿ»€ÿ«ßÏùŸ.<þóÿöþkå/kü믎¿e¿YÍ¡8áÏß^›Šã]åÿ¿ŒþÎÂ%Nø{ùoÅ ‹ÿý¿Ôª:|taÇ ¿þ8Nø}ÖØØæ©p’÷ô1Êë>ß×ñ‚À3‰wEÉ] P$ˆâvŸïÖæ]V+µàWuøLOœ¿ßÌ®ÜAîÊÈ|GŒ»±©- VtŸµóEDŒ wzwÔˉÈ—<µÓìWw%!Ÿ‚ý¾Þ׋È ð–L ‡Êºg®ÕÌó”»’q!òqç®\QˆüÁ3Ž»R&]ä~ƒVQD«ûªsÀ(#è¿wNùÇŒäÄCô»2Š!šJîk:êü2ss.¨¦Žˆ0“£îJx6%!€ß•(á´ð÷û¼7ÃÎL>»+Ë܆+æþ® !n¢ïÊ<¹R5B÷UÚF)B+n]B¯9PO^Ÿ_]Šãû®CÀÉõÅKŒãƒa=ÆÂ=<ë|KÆLDZÈ×îÏé=¨¹”éahî»Â"H—í·dž$gÉ;¦NkžŸ½À³1HFîç˜'ù«:|~éHC÷sÎsãxÒ ór=Ÿ’{a<-àÖ]ßöõ©·ÎWÏÐ1ï#ð—Ž*tOÍ.4fh¿0OKFÍ™_+M]G}(ûòí¨ð7÷ý)yGëÆ£“qÇ/ŸlTh¨ùµêìi”=ÂüZuþ¶_ëÉà£ôi¸¾×X)àú^uø„>;ÊŸ+¿½Q†{ ”Qf}7c˜Í¯~”9ÎosL˹ësIYo¬qZ6*ù™ÝU•—ï%uxeƒËöøÙbŒ©½ÝŸ_•ÈÉ.½PsŽìŠr&@D-Þ¼éùµºÅå™qeT£1£µ%W·¹_Ù=ûàâ*#óQ©3¨Þ˜™¯|ªÊ|=ç±quõ­*ó±¾W\²squƒ+ññºå뛉GþèâÚêjæ=ŸöÝ\\ûÞƒ‹«?‡™÷øø<ÃÅU Ó˜y3êÛ¨ÌÇŸ7>_ù*ññú3ñ1{kÅ5‡VW8¥Ž™ùøÊAQ™öÄ”ˆÆÌ||çÛ¬ÌÇ߯uf>¾{•øøÞ?-~¸¶J1•ÈòúÌ×ʵÕãxf>εuÌÔÇŸ¯q¦>>³9•*ôÉ=SŸÙ9•úøûÁÎÔÇŸxÝ‹?X^ssyõ ®´®ú`Ù¨æ}I¥Û=c‘~ F¾•J{|ä§PYgóquQ˧¾é5Ÿ×#áñ¢ƒÐQ ?oŒùŽ{ž©|ÇW>Ù­‡{.¦ï¦áÓäE³ c4Æ0¯DÇ9YWšã£Òç&n ˆãݤжæ]CàºUãüXIU/A.®ÈUµüŽ ry @.nMË’ƒ«i×’ËzN®¦ý«‹«©{‚$—¿Éå5ƒ«©¬·…rýœ$¹ºdˆÛ¸˜úæ$¹¸Inl²¤ÉÅ­@rY H®Ì"øý“äòGÕ®øæ¢%\TûWƒ‹ª&P€\<@.º¦@.êÈEÓrq°\^1Y.ž,—WL–Ë:&Ëe³.¬£}Å}Æc€åªFd:™,—?Ÿ,`¹,˜,÷)xþ1òëÌE«s½’沎 s1³ÌÅ´˜Ë*'Ì} žowæ²`Â\`O˜‹Væâ'€¹üÉ„¹¼bÂ\<Ú³1`®×°\Þs²\Þb²\¼!°\Þs²Üp"%²\þd²\ü…ÞënÌ&a]Qp>HoëeÏÍÀóKŠuJO<Gû乎àMžkøm±î¤M²Å:zPµVÇHŠ–êd{ßRÝ £×Vêý*[©t^m©N)´Zª“Ù^Ku "ÚRL«ZªSH’–êžU:¡¤:F|h©Na‹[ª“¿^Ku²I·T·*™¤ºÕJ§´ºUQÛ¤Õ­ ½c­.j¡VçÈ­Õ ºZ«[ÉZ]ÜŠZc*´V÷hHH«sÊãÖê(%R¨[ñÒB]=%†ˆ„ºU†ìêä5inU†'èty`În•ÒéV…ï±N·ÒÆÔ2Ý*³|Ët«_2]w¯dºUæË–éÊû¿’L·Ê¾Õ2=•,ÓõÝ%Ó91¥eº¨™2]·G2]”P¦[eGn™Îá[,Ó9¬…tºîRétJÐ(™Î -ÓÙãÔ2Ý*_ËtQBÎnΠu:ùbX§S†AËtž–éV¹ Z¦[¾²eºGg—–éäÀÑ2>^Ët« ~-Ó=–Á(Ó­‹ô5¨tÝ«t¾‘TºU&£VéV…h³L·*p¹e:}VéüY¥‹j¨Ò­²EµJçïÐ*]—H¦«š©§Q¦sêÇ–éäúÓ2Ý£ÓÊ)Ó­ŠÑg™Î³†dº¸e:ѱLÕH¦“Seº¸F2ÝCÁ¼e:Eú²Lg§hËtÝ–édÃÞ2“X¥ë×`•NajZ¥S šV鉘Réºw¤Ò9 ¦TºhUº,¹ñµº5TéüY¤ó­%Òõ8—H·.–Å(ÒÙa¼E:…7²J·*·^«t~Véæ/o™ÎoÆ2œ–éºD2˵J§ÕÎ*œO­ÒuS¥ë–JçÞ’Hç%¨E:EÝ´H×?:{U½)ÛiUÕ\'‘®gQ‰tŽÕ"[*]2Réú·Jǰ‚-ÒuÁð§úÕèV…LµF×-¦F×Í“F×™4ºUîÖèz"“F×Kƒ4:¯JÖèVùH£ë!J®¿ù©Ñõm¨ÑùH¢óh¥J×/–*]·]*<ú¤Òii”Hç-—DººàB£î3×!ªtñï¥ÒõSR¥ó (Ò9i°Dº~MRéä-m•ί–*]7‚*ݪ\Réâ.gîb¤ÒõH¥J—Ú­1H•®;—*79RézP¥ëvR¥sgP¤ónF"]_ 6Þ–4ºAS5ktе&®ß85ºn65ºÞmȬÜC•·Ô¶D×DùºÍrHÀ(·þ”枊0³$Êu2&Û]2(„­.g`b¬.σG²ºœQÓêò™i%Âêò™1èS˜«K$øM”{.Ù2 åœRL(÷\Ô@rSòŠäy äê-A®ó äœL÷(õ0î¹­ñãâ7À¸Î&Œ+·”…­Æuâ[a\\ŒëL_¸¼db\P("Æ=·'b\Þ W½yS«Æ=·Ub\þ —7Æå5À¸l0®BO<*È·fˆ$WõHYÉ9`…@.z$÷Ü-ðU4¾IîQ`N‚\^‹¾"É=w+‚ ¹¼$OM’Ë\ôI®Z#Á $W%TIrÏ-åE$5“äú©ry @.:˜ A‹o W”äú›#Ç9339îQPaœ?JQ\¿#Q\w°(®ß¬(®¿JQ\U|‚µq2f â²^@\–âú™qÝw‚¸ç–ü,ˆëa#ˆ‹šq=_ ââ¡@qQ/).kÅå@qÏ-EW—õ€â²`\ô1îS2ð¡òÅÕ%OB\ÔKˆëiMç™O @¸GQ&Á=<ÿ=—äò[ ò[¿iâ[ô ñ-|«‘ ƒá[ ûÁz€où+à[”ßúqHoѤ·‡@7¯"·èE’›?+[¼R‚[–Ü¢ÞÉmy¸-^1¸­VUÞØ¿!·}J°Šv-ä¶GGµÂ¶~!¤¶gúíâ7 ¶¬Ô–wµy2´U5'-'³åoÀl1\Èlѽ„¶x‰€¶g†cÌÖzÒ-VëGªEƒÁjq?°Ú§ X­wÎdµ¾#P­;¤ ©ÅšS¤–w˜¤R‹QR«[îKHpYÇ$µø H­û Ö­§õ›§Å N‹Ï³@í™6Œ¡¿Å÷Pk: ¨Å7PË*'¨eð$Ž+&¨õÚFßc7ó7¢j‹Íjó7>¾ÇåHp6ݼàÒcmŠý¿¤Î¦Ì”­³)¢}ël§N륳)>Yël ùÐ:ÃÀ´Ð¦8VÚ”d¹•6ëB–ÚtÌÙR›5Km7£ñü+©íY$¬YjóÝ%µ)öTKm:¨k©MèÞZ›"Ž…Ö&.kmÊOÐnqT¥èg!ÐNq}×è§#‚vŠã9cûÄ=öe“Φ£ðö‰{¾qo“o–Ðf_±&Zds'Ø!N¡ªZds·Ø!Nç«¡³ñ½âôö‡ÓIIûÃ)çýá(tIdÓ™£á;±ÉNgÊí §Ð(í 'Oóv†“œÒÎp]T6Kv†ÓóXd“ìÑ"[—Hd£NÓ›[c³ƒ©]áÜ-v…sÛîùé -¦Æ&¡¡}áüä ×õÊÎRS‹lò|“+ÜÓžoÔØ|‰\átJn…ÍâI+lR Zb³›<á|xÚ›„Ilñ+JlY"‰Þ,v„ÓÉ´6JêíçóLùÁ)¾l+l þÒ~pn¯ýà4øÚ®¯±Â&‰ÃŽpϯáÜçv„ë9ÂY °#œÏñSbûá §*$6Õ,‰­%+xÂùRbÿÿžÂÖǤÿJaSgÙÎÔ ›É ›üì×B˜áô¸6«4VØæ“›m°s¼kƒÝF_wƒ]\B°ë§ØÕ€€»¤È®›#²ë1"²ë§Ù9{¹É®B§?Œi²sŽq‘ÝVcP1Én[|+]@";'´7Ùm ¼c´óÇa´s‹Ívþ8 w¤€k¸Û Öp·)€áÎ-4ÜÅÝ wޏi¸Û[KîœíÝt§‘"º[§Hw›ÎÅDw[B!Ýù›îêGçÇ~ÒìMwq én³·ènSBÓ“Ú›îúe‰î6‡*ÝmörÝmŽo ºÛ”œÒt%¤;§¸ÝucDw›Ù‰wÛ»a~sÄ»MYÕŒw£Æ»ÍÑg„w=(„wŽ%k¼ëÁ%¼Û”ìÇxçõÃx×ý'¼Û:b ñÎI ŒwN~`¼ëöïœ)À|·ý*ÎI¿sòÝæ :â»M9BÅw=ÞÄwÛܺþ[ãݦÔaæ»(!ßmÌka¼shãÝÆHÖ¦;ç-7Ý9=¶éΛÓÝjî6Ýy¯/ºÛ|\#ºó¾Ãt·1ï›ànS8xÓ“c‹î¢€t·ÙÂMtW[“%ãæ#€º…w› Þw•lXêÜpfnŒuáRï<ûïÖRYPjlA‰Al·µ5"Ùn ÚãÊ*cl¡]·NlçÝ•ØnkkI²]u 0@l×!¶ëîÛyØíâGD;'ïÚõ8"Úm¶S‡ù¤ ’h·ýD»­ ,vÞr í6Óíúýíº¡D»¸h·)P%Ø.~¸‹/¸sªkÁݦx‚»þá®Bº[mŸOºsÿîú‹#ÝmrØÝÕ´¿u˜ïàm@éÞ%Ý)Ó³í'뤻¸è®ßé®ßé®?hâݦìl»þZe@i\ölé® éÎI¢Ew=§‘î6y˜‰î6…[Ým>Ë#Ý)_Ží'Å”÷ú¹Þe`ÓuæÆÛ"ªJ2‚õïþ¬/â%/îõ‹ÜE[y•tŒiu|×.é(Ó•-lÄý·.ɪP”U©$ªšáˆò¡çßQÍ,ˆJø÷tÌë§NZŽß yý‡a¬¯ãχ¼¾ÆßŠyý«Áñ\e„ó‰Íûs˜ÍTòÏU¬©£Y³¦Œf­šú"Õ”W±¦ŽfÍš2šµjê‹TS^¥šÍZ5E4k×ä‹\S\¥šÍZ5E4k×ä‹\S\¥šÍZ5E4k×ä‹\S\¥šÍZ5E4k×ä‹\Ó߈yýœsóÛ!¯¯òúW£ï·C^ÿÞe?C^ÿAu?¿šŸ—ý yýG·ýùeýŒ*ü3äõŸ˜©ÿùsÒý­yùŸ¿õ}þ˜ªçûüUM>äu!ú»¨FÄëW êÿê Ó~:ÃaÿA¤êëÿ?¯ëìâÈ3ÞõûšÿÏþßÿÃÑ¥ÿ(Þõ{ñÿý_^Z–í‰ÿû‰wc°ã]Gì¿ïú¹Î%àÝŒWOÃjoÁó˘²Á6ÿ¼ë<ñqt¦w«3­””-ó¹žJ”ôÌèm¸à™FJ§â“=÷#%š =÷:m”nxîmÚ(Ý ÓðL#% ÏýŽÉuþ=á¹ëö¯Ížžû\çŸlã}ŽyüÎ-Ý»›»ŽðváþæØÜPãXæù¼üŠŸ äö¶©ve~R:ç/vû t#íÒŸ ·6£nÓü-`•óÐî©,3N7}fÞ=aµÚϋӳÑÊUöÜSUP–ªgÔqtÃ(Ká_fÐlôÛ({6 Üá†-•Âj¿¿=«'¥)<æ|FgŽ÷_êRÎß÷OȾJXún[!)üSCcÆé>p0ôTúÌÙ*F]yž ¾ý)8 )wÚS£gC+¦ˆóÌ8ê¿Ì  Þº¢Ží¸4üä“=SáTD‡ 8†óhâÜ.4œ‡4ï{(—¾_qÅX_ÿÁ8å' ô*”yÅe¿>Zc R¯’¼Ö ‚|Äæ3(Ç[ ä W,üÍŒÒ9¯`Á™WêB• ÄkïUB¦xóÕ±ûgPײÌGU%Í;ñ­UWžA¾×6íï”`½êƒÌÛ´Mû•®uÛð´[7Ï Ñ1|quì¶u"ì©fÈÖ{u€^Ãj¯GDå]qÉÊ{£yÏù¹ÑÌÈõKÇô¯’ì[Wª²ã—Ž_ÿvüƒyâ¡Þ5|>‚N¼ªäA#]mý¤ßøÑ‰ï¯¼_Pu¶R%ÞÁ7·ßß÷VizçCÑD°bƒ¯z„¿y=†k*Oïˆ9¨b•z ¼Såé½qzƒ*€ ¼3ŠJŽ4…¨šãøÌ2Œ~Å—Ú×ÌÔ¾Ê2_Ñr/4†”jpF&ꮩL½ãÛš_s—T¦Þ%o³2õn¿8mB@žëã,Ø.#µÊÕ{~K¦‘ŽòîÕßCOÀ—P©zŸÏ¨©T½;¾åÁ[ßX1wå ÆcÔT¦Þû{kÚZ”ö€®©T½sªYÕ53Uo}§i•«—Ÿ_îE{‹ž +Yï÷K­d½O6¦rõîŸ[¹zžûAW®^¦·ØØ#÷L]¹z×XXÞZ#GÉ´½PÏúûÖ|?PrÓúBën%xç:zë¡nÎÏÓ1—L‚«ð\âµu¶ßÀ Î!³¤³Öªj'ÀewƒàòÎà†LxÄoUÀξåO&½eC&¼Õw3È1€·OI´>4 Þ>WTÔæcÑ»» ¥5ºàÁInc¦ëb“ܲ̂ nŸ»Lp3ëK&¹•8º‰Ó&¹e5Ïùi<ÀmÈúGÜVuàNÜ–·}®™Ü÷¶ ÙÉÛ²mÀ¶üͤ¶1wÅKæg;3móGÞøP@MQÛ§ÚImcÚ@±q“Ú²Ô­´eÁd¶1l“&´Åk³#ym(†pÍÿ|>ó/¾* Úð1 P­®ÙV¾¶“‘_„jy“Ijº (-»”–•Ó²)à´OÉä´q(]8-;œ6êF”–c”M¤¹©ÐÆ´]c•“Ð>Í@0Ḅ–#¤->hZ~%´±?žƒh1óÏrÊ å å—@ûÜjZv?­n~óV“Ïr@ŸÅ¸že[€gÙµÀ³1“¢¢V-‘Ï•x–Ÿ(ðìS2ñ,>@ÐYL8«ßœºÓup:ä|Ql–Ãlöiîd³!ke¡Yþhö-™ e– Êp(™°,î*ËT–—Tpíø6ey‹ÉdŸKn~p¥`²˜ÀdŸM&Ën“©íà1ÿ5a,§+ÀX £b±X×€b1Š@b9Ì@b½ß‰EoIJ–ÉayÅÐêÈG…õÂâ „Å4JëDÓØ/l(Ñ£¬ –$°˜ H`ŸZ®í;ÞI`1‘Àb†_ ìóHÏÃáÌ‘Iãë#~õGDúÊ*@_Ÿ’ýæd‚éå/„¢–ŽVyF—óÇyi_ö¬ !mZS¯¨£Éþ!„4D.“Æù^2Zÿ»t4“u´PÞ £]ûWGS\&éhŽ‚ÍáŸH_ﮜÛ%¤9tñë‘k é+”;ÈhC[mÒWíì‰øõLç›À¯’P2d<`U%ö©Àª¤ Ø#/òW¤“}%£ù‚É_Ï£Ù“üõUL‹nŒ}Ú?a,çÀXÏñ‚±Çç¶€±œŸ@cŸÄ”êwË) 4–íÅCÆrÆ>wBdÕ,¹Ï_'h¬:ÂW¦â©cõyn|kÀ±è<ÐX|{ÔÊb˜Æža),–M‹Õ#Ý©,ËGeGŽeãn¬›€±œ/³!› #«ñp&ŽU¶k""xl¦9Bx¬Ü:i;¬ê‘Ǧ§`óX߃<æ£ð˜OÄc»Ùˆ@¶›¿Àc:ZõßÀ1ú ÇM-Â1MˆÇú©&u›ÉcQ{§ ¾`YÌFÎÁ²™¡9±º'A–@vÀL06ÏUC {tŒ#kÕ c>  €À±Ú‹Ð<ˆ<Öç1â±÷šEÌ{×€G¿yŒ˜Ç<ÌcY3€ìhã™Ç ‰ìØÉŽ6¸‘ùD›@–?Å©8‰,IdÑ8™;ÛDÖ§y²>v$e½Åcqp,މcq^JËkÀcq>M‹ÃZòXõ“Çâ,‘@Öç‚“ÇR¼½ÞN ë“EY´–DÖçʲ¬@§¨$²8)%’…Ô$ËÆɲä9óiˆdqg"YˆY@²h ‘,L2Yô-¡,KeY*k!—P¶÷®ƒPêÔç@e)›Êº_Heñ¤²x&RÙOQìó#@Y܉TF‰ ²rl—Š, %brY7ŽX•X–r¸loV"—¥Ì.K= \Ö/›Xm!–¥”,‹ž!–uÏL*ËŸËâËRC˜Å!˜uG̢à fÙ€Y?¹lï÷ä²°B —E[ÈeÑw³x&‚YÜš`–jÈ,ë¹´b¶pvÿ˜bHfY3Èì‡Nöýûþ1ˆHfQ/Ñ,”' Y¨W ³~‘$³x’Y‘³~Kä²V!‰eñ“[‹¯‘,550YÞL×ÊâBY 1BYŒBYÖ*Kq T/ˆT=±,>#rY¶\¯ƒ`–%³˜ f¡²ÌÂòƒd–%@³½Ï̈f¿’̲w&›õK#›¥&w.?^é,~8‹g"å€gŸ’ñcx“ÏR‰Zr£j> •‰€ÖoW„–µ€Ðú͉ÐÙ2Þßö ϺµÂ³¶ž¥Ú> oœ9¨Äg-c Т„€ÖÃA€Í'¡ýJ;ËŽ‘?¯V‚ß#-,ãÆ²±Ì ¨ì´,[•AX¶¦<æŒïf2A[#Ù“DVžß7³¶Gk"£-!‰¬‘DvØúpYˆ¬Õ-™Å*™ß€ˆl·+€, @Ö¿ ¹«d²dµQy¬Láaü“pL§kÂ1}pÂ19â±¾€¯x,éK‹‰Y‹<Ö•ÇT`³œGë–Æœ~Æ‚ÖcôÛ>·l3AÄ U$&ë ƒX?›@Ìí‡E;ÇòíTqÛõœù¿Ï`aúG C?@X·T &ç²K‡økÿ)Ší}à,þjý”ütþêA&þêÇ!~%=?FŒø«mûˆ_}Þ þ Ú"õéù«_1ù+í É_aªØß™ØË}(ôÒÁˆÀ«w_¯þ ¹+¬É]ÝrW˜û¼ÚbÜÕÄ®>]w¼‘»Âr‘ÜE³C0Wð+v b®¾+‘+žÆÈeÊsM—%RÎòùЄ\ô#n¹ÇD[ÝnÑV¿YÑV·C´¥W#Ö J"kõˆZ]@Òr“³üðÂ,² «› Ä: Pëw5lÆê7-Èêg#då5Çó ¢¬ÖÙ@YÙ˜{ûŒŽF-á¸~2âs|Ç»H«'Ò Ú!iõ­HZm|Þ ¥7JÐJü!h¹óÀYa~¸þãˆwCÈŠ›Ü×®cµ£+îAÂê}€«%'V\BÀRK„W}càUwˆøÊ#¼r€«(¢«>Ç]ù7d«³MÇ·]«ÂWX’«Ô,cU ±*pXµ‡vhM¤+ÁʃÆ`ÕFŒä*½Ýj¤Òžè/„w¶G«ˆÁd”™¬õîÉZõ:!µF\1yk8‹ykÜötpÛ~K ®1ÌSð³(/°¡¾–?˜¤r¹ƒu ò³½Á,‰ËÌjt{ôŽ`mXHO°(€'"L³ë9t{B«ê,¥‘³*¤ûÖvˆŠC.ÎR aÖ;NdÇΚù†QΚ Šn­,˜+KMOÚ!¾ÛQ¸ù´ÖÕT¤U¡Uõç\Z˜Ù©IkU¦[¡Öb#R¢–â7Š´jÀãž$­EùtEZqHkQ ^¡–ôHZýwÖº ÌÀY«Ç&9Ën‚-·Á åG7h9Á°A+KZY3@+ëh½õëpŒ¤•õ\Ù‡&­ü HËo´U‘3õ+Ж:´åž0m­»w†¤­ ø(SCЖRL¶Ô݆­umãÃ#‡‘i+‘´å‘cÚŠû€¶ì½iÜŠ'må[QBÜêæNÜê:H[ñÄ“¸ÖÍIäŠ@\þ´L\ñ†ˆ\Y +ž‡Ì¹âµ’¹²uÅ]>æ2xu%䮸 ¹+.vå%à®xd¯ø(È^Yøªt÷*|)J‘Ù+i²WÞì%§\³WŒ²W?Ñ+z—ìUéÕe*öŠïˆìÕïžèw"{Åø!{)–,Ù+ï þŠÆ¿¢–-€åA`qcX\C‹—Dë[‘À² XVs¬?þü:]-œÃ¦Ë?k†Åk#‡e=à°±xp‚X ‚˜¸ bQ I,>ÒX?6i,/EóHcÑ5¤±¨8Ö„4 ±˜C‰cÑ3Ȳ) ²¸1©Ìkœ©,žšXö9'ËúC!•Å­Heq  ,ï*‹7@,ËöÝÛ§ëˆe1Ë¢ˆeÑrYÔK.óŽÃ\#„\æ­ŽÁ¬Wr™wæ2i‘ËbL̲V Yô8Ù,*šÅœB6Ëæ΢ÂYÜœtÖ΢bâY\²_ß @gqè,æ^òYt ù,›>‹jhy -.¢¹„®?VP!Z!š?5š§UZ?²Í­G”-Kiyo@šÇÍ߈­Ç»­[KB‹ÛÐz£Åiý¥Éiì}À€ˆÓ¼®wÙ,g<Î}›; ÔÌ’ ¹üû¿ë«tÍß Õ¼m/ÓDýø;‚"Ï‚IÊ¿#®òV?ŸJX’Õ (+RITµ¯sÂÍçeITÅ¢¨Ê%ÿÑ¡šg¬ïõï…jÿÃC5ÿÆðXÇR_È'Xó¡6Q%ÁøÒue fÔõ ×̺â*Öõ ꌺ23êúlf]qëú†uf]Œ™ueÈfÕÕW©®O`gÖá˜YWmV]}•êú„vf]™ueØfÕÕW©®OpgÖ!™YWnV]}•êú›gV®wßó¿"7ÿAäæ?3wÿóW³ðoÍÔÿüÍöçìý;ì¯êúóÑ›‘+ãÌðÍXùhüfG‰þƒZÆ@øæ™ä-úŸ<~óˆøÍÿý/Äo~"==8hŽ9¤âóxz0hï­{똩™¦z|ÿÞ-R¡Y×1#‘vʾ·d¿‘œcÑdºþG–‹·äDäý‡iéªäAö ï[*´ô¹¸Þ„îÝhUçÅL+¤‚ip;˜wæ-™É””hªÚ4ã :­^ ¤9…™{»·’±±µe43¤)‚áú vïvïj©ß3Óš7µeÐ?¯Y”oöU¢?2Œ õæsϨ¡›í«¤Z7Jo-/®z‚¡ØžkùiÏk¤Ul b÷nƒ‰ºªyF”D¾’­Ì8ƒÛtuAɆL#Cáë¶±{7{@mñ½v̬CJ¥T©˜fÐÐ*™+a¥ïA%s¯’G`áÊ?„¼\ÊçRÉ„fØÐ̓hCzÑxðmæRþÜý…„ùs„Õþ ‰|Ôåïç?Æ:Ç_•°g€ùïl8ÆnCÑö¶Á{ûý¿£tÁ#(lè[‚l>3¾U — »šmEðÞèÏJlùGo 2ú ú­>’õÓ¥â÷Fçläïó7’rÙ5jÛ6$öQÚžÊt9ㆾ,å¶­2œñXÍqãÊò%'’ûDɵi˜ó6Dï¬ijÅ_Y‚ø½›RãT´íÓ}¢÷Ö…%ûri CTÞvDï®Ù·£„¹ÚªŸaß{ß‘è§ï½øœkþÀǰŸ+žAVÁoɃgÐÐ÷x„®ø>¾?H÷ÃÌšU0£†n÷Ãéçíqäûé¾:–]Ÿ*Ÿ¾Ó2þÜ ©ú–̰¡³[ÑçÂ÷V͸÷±ï˜k|«cæ`»øý{h®9y¢÷öl³× º½Êqt zoPÇ=£†Ö>xëqâÅ}'×5T)E+åÜ êÌ|U2ð®¦2Ï^¨æbÉÆ-¬eGR®~¦Á{k0¢§*íì‡\y#ïñZigwLÝX66¦Íknäæª|x¬‡ygo…Lß*ñì|…Lß”xödj´J—y¢8¦+ïìù™Z*ñ,ÓBªd»¼„J<;мä@–®÷ËC¨ó­òÎÞŸÆTÞÙ™y!poõÌÃ’{Sû]‚U)=«÷·µÜƒ¨RÎ>X>9¡*ål× ´ï4¯Õ‹\Pûš ªþd¢Ë[/àF2›ÊñÊOý>±œöKº/®§«&ˆ{¦<ìùö¾±ž^ÃW ¬§·ÂÆo÷ƒõ4K°ž*sm}3XO•$·u¬§JáZóþ\O×þ´Ç†õ´ßRξë7Ô[þ7åœí—2µb;.½ëÀ½µ«aw$®˜ÒK¹¢J¸†õTàm wEÍú|’W8kn-XQÏ‹¾ß’Y滋çAþŠö+ƒÀ½=!<Èa‘• no4ø9± Fc···jÛƒDΉ\%XP#x{Æ©Gà4§¤³St¬ûRÙ,ú»Ý—Å_2Ä­}A>‹ªE× ¡Ewè¾ £E•\¬)-œÍó-AN‹~Î}AR‹º×¹³+ª2¿%Hk±LYù–ÜXQ•˜ó-9çî•p–{_„Pßd¶ØixgÆY¯XûŠÌug¬O»2ΞÌÓø– µEõžªáöøíöÖŠÔù+ä¶èA±¯Hn±Lu÷–̰Ýë͵[ƒäÕà‹õ"¹E¼ËÉ-â-Ì̃ŸoHnátÁoÉŠU±›÷ ¹-¢·oöf¸ßú{è[ÅS+߬WÂ}cj‹áZ¯å3•ïÛåõtckq®³ ±þl°g1ßã¿ äë0È@¾qKä&æ37k™Ì7LÈ7òFù†#€ ùÚ¨GÈW¿b46ßPnC1_ˆ0„¾OÉS'ïÃ>2€¾gíæúÂ4ƒÐ—Gú€¾‡ff¾G¡Å{Ï sÏJ'ï…í1y¯<(À×."¾gûß§Ú |ŸjŸO"%ñ^8‘÷ÂP–¼Ö·ä½g&fÝMiÊÁ Ä{áÎ5/ü‚|áÙIàûÜé_Q_Û°‘÷ÚG‰¸ç ¢½°d&íeµ ½6ä%íÙvn²^9¬3JY¯]ïÅzmøGÔËÎêu\¡^<ÎJ‹z;Ë“ô>÷†yÇ)30‘^Ø’ô¡Öûi;º /Ì' yáÙOÈû–(ÁBÖå•íÕ¾³æIyUòðGׯÖ/jíê£â yù<€¼Oɳu$1Þ3÷ä®ÉxŸwœÖ:ÉxUB%™Œ÷ÌDÖüÕd¼|&0ÞcÃE1Þç^“ñªfªŽ„¼OÉ}ÌH‰Tæ y9„@yÑ{€¼º‘~È{*=_ÂA {Ítd¼º3¿{2^Þ÷(í7/_-/šÄ«Ó&€ˆW%C×Àº#žŒ÷œºÉxÏyw=“ñJ‡Ö¯ywR—wäUÍÈ3/ŒW7âŒIÆ{NÄä}J`ÝQ{Ÿ%!/Æ/>' ^>$ïóHñò±x÷…“ðÂlœ„÷\¶°!áe¿€ðòÖ ¼jî–„÷xHÀË‚ÉwõÌšóxÙ/@¼jŒ&Q ^Œ"¼ç´­ ïñ所——ð¢ÀwÙýà»lø®šÂ5˜ˆ¯„—·ž€Ï ¾«yöüÍõ±'ßå·¾+“f­i7¨ö€¿™Š°› ¾Ë±¾«k*|—5ÆQíþ.¾û\OQgÜßÕ5~oÑâ~à»ì`ðݧ5p½l‚@¾Ë.ße{ÀwÙð]N;Åw9 ÁwÙð]õ:=lxÙ£¼lïé“ð]ýw×%°lV`Zá]‡®Þ}Ú#~ʉwñ¾‰w}gÒ]Ü™t¯…tWm9TÂÐ>~Q¤»èrÒÝsÚR‡t÷i¬œ/[¥îâµLºû´o<œC.=Jµ¤îb'Þå€w6HwÑ5€»~d»ì°]L“d»lo±]¼$²Ýç :Ç3ƒí>Í…¡óå};Ù.š´‹„hû²]¾Üb»Øtí²1€»XÌwµÇW[`ûðÐ…t3½,&Ô¿!–´øîaJ™°ÉP:ñÝcx—AÔ€wUÒÝç’1M;tðîy:ð.‚ó彩Î;ôÊâ~!%2ç¢# izŸ¤[Døõ–Egõ–EgGõ¹XÔ[¦ñ念¦W—PXc:ζm£¤—µ@Ò«{3n9%½eѹ†4='kµ¨—×”¨W~¯€¨W¿‘ÌQ¯´YidLÈ©D³õœ'Ö¢Þb›U‰zÝ{õ*Ë× {AÔ[o6¦ª·¬:‘ª—÷fFÎŧsTõú¤êU½\¨ê-Óõ%À¼J MÅŽœ÷(›9/KÀy>ªOU/‰¤÷4¯ô{g õòFLɹøŒ”ª^tU½¼ª^©z=¸¤ê9‘°U½x1SÕS.b‹zyD½þ¢$êuÂH‰zKu"oU/¯ªÝEà{šj¨ê-‹Nç¤êe ³r.>žªÞçoääìÖPÕ[f®/”0'çô¨B T½z½D,æätžY‰zÑŠzu+HŠzÑ]õêWjT½èŠ©êec|=÷ øûSŠø<÷IÕ«ñ\šª^܈ª^|/$¾Ž3+âs„y"ß㨒õ²^&åtïQÕ‹ÆöùE½ei²ð=Ã_ E½h./ ¯LjùÕøòšmÿ¼IªzY/ƒ ÷é‰Ï.v&¾ø¾I|NÄmäË0_<e½l˜/¦(2ߣ „¾üЯ…Ð÷ôùe½N ,è‹×Mêë`±Â¾˜£È}OŸ5‘ûâ9É}уä¾xüzJ%÷E×PÙ‹I–Ê^¼*’_Üšä/†ä]Aò‹‡"úå5`¿¼ð׿“ýÚÜ‚èGôë­Ð/(Ñ/îCôë­Ð/:Ò^ôÑ/†ÍD¿ü “Ñ÷3RÚ‹ÏŽè÷-ž]KÚ‹ï›èÏ@i/ÞÑ/[ô‹»ý:†°Ð/ÞæD¿èRÓûND?Ç*ùõÈ"øÅ{!øuÈg‘_"ùÅÌGôs„`‘_^òsc~}_ÿDäça$ðk)Cà×ÁŠ~YÍñ#h¸À¯ŸÀ/K~ý üzï ðëW ðë®øÙEà×#Dà×ãJà}Còë"ô˰_±_–€ýz²†®×cFì—õ2i½§aéz^´„~=¤…~=Õˆý<ö„~ñ”D?';!úe%@¿xD¿èO¢_^ö‹~ ûeƒo…ÿSñªÛˆ#&€OII |0Mâ+»ÊÔóÚ}ÜÄç¹Kr^2ëy‰wÛ×íUÀ×àà{œ´UÀN`¾”ˆÜý @ÏsnXñ^¶Žz^ûCIÏ[|ª-=Ï)e­éy²•¦·XF ð~ѾÑ/‘À7zÀHÓ[Z1¢^»óIÔ[,FHÔëmxo$AÔ[––ç ê-}àÞ±zQÔ[ú(Ž¢^–”¨×=,Q/€é;cñî}n4q¯µZizKË?¤½~¢½Ú“{Q°*¼‚ZØ‹—Y¯M²^þ9<zýФêEÛ¨êõK’¬ý Ô«µ4A¯BEè@ —­¥¨×¯zêzýÄÔõ¢`b^UzÊPsæìïRõzèJÕ‹¶RÕë~ä壪LU/C—í¸äÙ>MU/Ø ¢^  ^v E½ø4½n-%½¸1%½@5(zYðüè| zÑQSЋn"ßekÁw½·#ÞÅ3SÐ ^‚žõRÐë'$ÝEà.î<áîó÷àÈÖmà­Mº¦–—íÙ N²Áª »Žnb)/údßÁ.^Á®›6•¼øB^t±.o¬Ëk€uÑĺà3P]P@]~ƒòºÈt y÷'& ‘.ÚF¤‹¶éò7Ðñ¢WˆtÝ8]¼"]–€èº¹ºÑ|NžËæçâ7ãG¥à¹¾€:^72^w a. ¶ãÇ &Ëõk&ÊÅ"E”‹N!Ê5‚䢵墭L‚7Êe P.Z ’‹KHrW<cŸ^4… —Õì?þÈÅÛ †—×äb°Pà bÇEGQ‹K€qÁ~ ¸. Äu/á¢q“áâ GÔ·%Âu7=Id5o¦ô”(Å-γ·Ã·¸-=³»Cˆo= Io¾-è­_è­!ðÖ-½}JžÏ¨¼õ˼å™(K®ôûù·¨ìÖvsÝ¢àÑJ¹>‰n½ö“Ü:œ”É­»‰à´î?>\Û§k¥±\àæqÍ.ú€Ü O}‚ÜÐRÉG¶ Ob[4…ØÖ?"¶Å[$¶õCµä/d©Ïû€ÚúýÚâ6×ò1Älq M•üFøjQZÅ *£øto¾nq£§];@ÀÓ®=—äi·ËþTžv»jåi·ÛóKžvûL°…xÚÓY”%Ó3àØäG!aî˜kú¿µ.wLˆD t¹cÚ¯±dêr‡­u¡ËíH]î(ñ›ªt¹£|>ºÜa» sGù½ž Ìáòeî˜âXòàšû_»ÃŽ5æŽÊ›œ¶Övgç5%ÌUPŸ·†0wÈéGºÜÑnTÔåΨË}ÖO]îÿ6_¾Ÿ‹¦LrZŸ›ÓâlbZœnÓœðÖ¶—íÒEÓË8ˆ¦éeLÍä´vב(×^}Ôäº)Ä4§ª¦u~AÙ^Ž0“œ‰>Oœ6vËdäÊí†v”À´è&bÚXå'@J{WJY’ÒÚ¹„¶—JºkÓË·@F#4½¼/³ í­\kiN™lJ«+®ƒõe^ë˶V!¦Ùd\”Öm%¤µmµ¤¸°·"¥å@iv{"¤uGNFk+ 1Úô*!ÓÒ²–—ÝX^¶ù!­M?DiúwÚtga .mÂE›Ëë´×­ix<< íRFlZ˜,’Ð.[± ѺZZMu÷D´0-$¢E5d´¸9!Í~¾´¹<¹Àh5,%ÑÁè²Ç9íD\4¹L#̹ð¼—ÐבœKDiÑ÷¿kpÙ‘¹…imc51-þ¤½¥íIia¦Õæ–M2· »NPÚÂ0íô±£ .Ûdœv9Ö”@- ÙÛàR†x“ÔÂ$“¤vZk'¨…5¶ .ûÚ[F-4¸ ãI€Zû,Êâ²k¡Á¥ ÉiY€ Ç!þ޽eØNÒà²û‰¤ÖÆÂ2¸tTB¡Z©Õ¢ãÈjN«—| 6¸ôo€jÑ-°¸ ™—ñ°ZZŒÒâ2’9ë½­µÅeØ`þžÅå§dÐ.]J礵èÒZ¿ÂZÌ„µÜkƒËŸ¢[›^“Õ†—°ÃŽ´–¦”Àµ¸÷ï˜[†S€Ì-Ã䑿–QBsËn U·~Ù¤¶~ÙÔÜÂøšÐ†±¤¶èR[w'©-ìí`mÙLCl“W†¨-ÌIm6 ´…A©­ƒZ‹ÚÒú’¶–mmGÉ-K@mûÒ5ßr[pƒÇö} ÚZŽ6 ¥­¥‰Š[\AÅíH î¡Iñ#ß5æïUà–×Z@õ”²¶´s ¹­#QÜâp[ÚgÂÖ²?k[;xHpkH‚Û‘ l-±ní£"pó°£¥eDBnëoZàÖi%EnѽD·¨–––~h…¦bH„¿%Û†–L‹žDgÓ&!Ý:ÏQ2‘n[Ä|›}½×Oð”ÝH*¤«kîÒuÔ!ÝÜ{à€tëUqZ€tûtzC ˜nïèêdº}W1ÝTZL·Û•WL·ïU`ºÝ˜bºÝñ Ätû4ÜE ˜n¯MQ L·;œ‚˜n·ó¶ n—³¤˜nŸ>„(ÓíŽb¦Ûåp)¤«ý¡ˆLW•زr2Ýî@Dºý‘»­noëšZîí}NSË£mühjÙ7‡©å>IÎ?aiy¤]å´ ©[‹ai?‚¡å† 0´¬hº—Üçî¬Ä¶áSްdDø”hçTÉ©h) žÀÏ=--[)2|J=´‚œ |ÊÞáh>åɆ–GÛ6ÒÐro–¥¡å>óU£†–õæ6™^ÞhÞ¡Þ¢¡åá˜2´Ü§‚’2´¬#v--ã-ÐÒòh¦§¥eÅ~PåÁ3xE¥¥å±jÜËÒòh»^ÆOÙ ¿Y0 -¶'¥¡å1tQCË㇡e¿ÚY«ÃÐβ^·¤0ØYÆhgO@CËzîÈih·¦¡åñvÚ–7Ç€j†¡e–ÀÐòXÏ4åÍ3¨;í,ߎqt†O©~` †O©ÆðW4´Œ×MCËzQ%î½Æñ>å°Ù¹â§DŸÏø)GÛLÂÎòXä.;Ëcn×gì,÷Gñ¨=¥BX 9ai¹+DŸÃ§ìb‡––{Ç÷aü”½< X0ð¶ófø”#4®mÿŒZÆ;aø”÷ŒŸRwâ§Ä8bü”šïiDËø)1]2~Šegï›áSâ=1|ÊÑæì3|ʱ´Ï§Äc3|ÊÞaYhg¹W ûåæ„ˆŸïŸñSj8©fÄO9¼¤*„J#<7#¨Ä”Ê*^~@%F'¨ÄF3˘žhf#‚T¢÷@eóGP‰{1†ÊSCå°3…b¨Ô3É-1Tê¡¶ˆ¡€1Tâ±C%Þc¨Ä$Á*5¥*Ž b¨T=òjC •cå¹¹ì,ñOà`FP©uŽ+#¨ÄJ3ËXÃAewÜ5™YÆšÊ*{£™e,Œ (#¨k{¬!‚J# r\Sý~g•=L&afyxƒ§*5n>È7[#A !T¢ÏB¥»Tû¢(‚J6Tö™Æ*=ð@¥?xPé1¬*Õ{r`[½¤ÞŒP‚*µI‰}±ÿP•ÝaÁ@e÷ẨÌÅ­A•êÑ× €J^ƒ*ûŒˆ’±}ƒ*»ƒ)‚ÊîÅPé)J1TzúVO ¢Ò›3–Ql†ßÞ+9ì' ê‰/$Âo³ä~ûwá·yÍß ¿ýë;¨$^oñߢ$bg]ñȪTU±(ªrIVU9¡²¢ùwVSY þŽ*Îeâ^vK¢EE.ɪ¾ï*Þ^Võ}1ùªþÂOõudTð ä]Çÿ×øU”äŽô]|´o¿A;˜ëW‘Ôpþ«¸â?„ÿÖðÚG¼—ßë`$eù†G]úu}B³®¸Šu}È£® ýº>¡¿YW\ź¾aÄYW„þf]ú[uõUªëFœuEèoÖ•¡¿UW_¥º>aÄYW„þf]ú[uõUªëFœuEèoÖ•ÂUW_¥ºþN€ðýÝÙî÷ÿ þ‡ÂÿÄêò›“ø¯Ö’þ‹õàsÕïΈ3@ø1w–ü/Dÿ³1¾ÿ¯ þ®Í÷õÿ"Æwí%ßóÿ<1¾ÿûoÅøŽÂ¿ã{¯`^>þž„1o—½Pf Ë_î´ÏH¿Üí÷µ—Ö0ÁjÓßÊòÆ pï†òdlÅ](3ŽÚ¼¿ûj:N=8r|IOñüjž© Ûqk…›K¯»P²â°Ãß— <òõ-ÁiÇ6xZøb:É ð¢|MÁ:í/@œxtÍÞ’yÚqlåš§§ྠ7O;.Û'½ûÐyÚQ'¬fÌÃŽëàqìKEó¬ã'1ö…ÈyØq_ä—·Wbß ÈoɤË8ün¤ëïC±ß=ñÄ£ËáÍÞ’yØqù¬õýÌ']'ÏYŽõœg×;Klü¯»Ò³džu\’{¬8q¼*ܺs'ïC‰»^˜‡÷ fÇ’yØqí:{?¶åFçñ¥Tøz„2Dû¶mžv\Óé•%ó´ã² Û±íó´ã¶9Ú±áÈñöáÛQáFkít|ØcÑãuûÉ+‚n=Ã¥œc«3ÇÛütT$ö/ŠCbÙãå½Üg‹wœ9Þ>…:öužvÜý2_¨Â@òÐ!e>ƒÑû(U¥úK4tìÇ<í¨t¨}û1;nǺ8Þi¢ã1±_ó¸ãî¯e¿çqÇ}èLü-™Ç§£m;¯U_ï±?ó¸ãòÃqàÐñ:ÈGAY=‚M §Ž÷¡ÀþGÙÎa²sD8v¬¬g[ïÝ1Ž8ˆ:Þï…ì½²2ä#¬öšŸómË©·džv\õ}òšûÔ[`ŸcwÜ>9ŽgÁ[}ä[2;®÷+Ɖìq.ó¸ãöéËqâÜñÖyûÛ¾¥úÁЉCÇÛ‡<ǹÏãŽyr‡Ç>qèXÉÙæ<æqG%nS=8tŒÎ:¯yÜqo~ð§Ž÷!±ç-yôt͘ô=Sl¡ä™Ç÷¤gI™b¼­‘þöþ¦ã¯×:;î]Öwǵa{ú~³8C>®}wÜNjý–Ì㎻?¡ë˜Ç÷4%F Žk¤ß¼æšÇÕ;8¶¹V"<öV¥">Ñ£ ¯À±cÕ‚£–£’ß²ÏçäØG:âœÈ*ñÀSq­@FâùT&•’¸žÁñä$^oË Ge%¾ð->üÕÉ)JØ1;= Aà@j╜¸žá™ê Åï5^a*Eq}­ï‹?xo<ÆsV¢b>×Dd*ž“&¿è±Î•µÎ|9)![ñœ²9Vºâ9CÔ<°8?W¤,žïŠ^å,®ç”Öp iñ[âÑUY‹çš}ùÞ3mñz^~ÃY•vÙrH\œ#çaž¥J¸²äÆXסÜñ”4ÝÞ? yñZé7<˜qVž¦H_ü©Ò| $0^+9ãà­!Íß½h#…qÎ8Hbœõ@š¿|fx •ñ|åˆ{<ÏçSHd<—Ež ”ù{“r"‘q|Cç²yiÅÛ<‘Èø­G'Xæ†òí³ÞùŒg‡.¼7Äù^„Nä3žƒD¿‚8ùLûDBã¹â«Ú Î_2e8‘ÑxΡ8D>÷Òæ£Z$4žãóæÐæ§’†ÇFFãõœNý,™+ë‰iøD:ã¹ÝÙX „ùËjĉtÆs7Æ ùŒßM©çÎ}²³VœÈh<Ÿzã­K™¿¼ÌêÌåòÌræKN<ó°y–Ü2VúS!¿€WMy çxØ"À9-Ë@€› &–\ØDXëÔöw ÀûRààA€cÛíª»}€£­˜ €¥f,€#Agõ$ÿ=½½!þu¬'àß²KóþÕ|wðÎÀ¿¥7ÁÄ¿Å3„« ëEexrðï¥MÌä¿Íb²øoß” Jü·ynÿuJ ðß>ð7øowšñßn‰Wügkñ_‹‰ÿŽMð_«Oâ¿RºvÂç Ö­ïCü÷Î\2‰‡ãåÿŽ]8Cú;Ã>éïð4,ú;lø.ú;âBôwÈ¥÷õ^]ÜwêCöÙ»ÎØgµÜØ×cÂ>ëÊľéß…¿‰}ýi ûìàeì»´I0öõ'ì+ã–ûdUeê뛓ú†wǦ>›ú¢âI}N }v"4ôÝšKÅ|M]b¾ñ“ù†Í£Ì|œ>LøŸ’øFF_™ñÔÀg[ß°$/à‹n!ðÅ;!ðÝ}TEà»}ÞEÞ}`#Þ»üŠ÷zï™Ì{}„3y/æò^þ†À€Eàë™GÀ׳“O§[⽞<Å{eóÀò^c-y/>nñž‘÷*"áˆÀçZ |·_ïÁ|¾CV¿¾Ûg½&>'xòÝÎ&DäkTò½Õs+/äsþ+!_™y]ÄO _O>F>¥¶ñõ釉Ï+‰Ï6Ý"¾z1lŽˆÏç$¾[;._Ÿ¬™ø¼%ñ "‹øFƒ‰¯æÏ‡lIâ{”YUÄ7¿P´FÄç9#Ÿ8…|Ãçz@¾^„|wÝ€ä«Ã! äkHòÙäÔÈ×-&òÕ4¤ùz¨ ùzªòUÉM#óÙMÌw7ÆŠù6 "_/˜B¾ÛÛp!_¼pR_0úngvõÝgp࣑Îj°9¾¢ }Ã:  ¯FÒÃ+}C¶Áf¾>€Òà˜å¯7õ=JîkáïlÈöÕŒŽCÀ¾±Û Â_øÙPøkn á($á¯-Þ(üÕ4²$÷ͤ†œn)ü­} HáÏÖÒý:9žt¿ÝÓÀ¯3€üŽ>¶#øµÑ«Àï´ïžÀïèÝ ÁïìÉ/kùNª+ò;EIù]©óAùó ´ò×§Ö“üNv —þ|Ð~îT?çÁövµì×{Ub_œÀJökº•ìׂ‰d¿ÀGpßi?~Ê~MÄ¿iáÍ+$û?e¿ÞŽü./ ü®&Jª~ /Rýöá›üî–¶&ø]N¦'ùÅ6I¢_CœÐÏ'ÍB¿Ñ½Eô»{Øý¼;°èwÈœô×t-ú³úNø¶7ü½oGê"ào´B/øs CÁ_mèÙ`ÁŸãþªjë‚¿Ë'„¿±5Ú-$:þF¬àïô«$ü [úþZýõýÙ?Rô—­ýÙÊ`Ò_‡8Žô7š!AñÜ¢¿²¯&3ŠþZB#ýµÂBú-“ÿFŸ* ÿއ®Æ¿nñ/Þ9ð/ ü7|È-þ«}°äEàè“8œFB#lÛ 2`%t$$’G›ˆ½ Ž9¡Í‚BÀáIK’ß%EÀh\àè# àð¾@Ø›ÞD@‰‰DÀ^”ˆ€£G¤Ðñh„€ÃGB ÀX$ÀÑ+$ pLó)”€GŸÒ’G+Ã$Àî*àØœH8Ža/ïâ½ ×üJñsþkà°i¼pøhI8Zú*0’°‡š0 Xø®`KIÀ>}Ùà‹ÿFc†ø/dBòß©ÃRóŸC;‰ÿ†m} €ƒÐ-þ-Y‘ÿâæä¿áÓ²Vü “ÿÆnzÿ3’ÿÃÅì‹÷ÿ=Ò£Ä-²‘ÿêWÒ©ø9²øo„ìþûÐøïlpòŸa™ø7|ôaü«ðA(Ày´ÒIúë©Fô7ìŸkúkj#ýÕ׊=öÄ~µóþè}ÃRòD¿žƒ~ òb?Ïåf¿[F(f¿Kb©Ð¯¹Xèg±Çèçs;£_H€Ø!׌y~دhug=“ýÆiûÉ—Ô×'ùd¾CA)„|ÇñCæ[ÿñÁ½Ã^q–ùÚ 2ŸOõ¬ó)õ¸h¯,{ø<’ùäk•Ïj¢D¾îZ©|—7 Rùì0j•¯­Ú òõÉ/aïô"d™¯‰\2ŸUT²ÞÙ»(Ë|ÞZæ³°BÖ« ”ùÚhL:_âöÎ~ÕúÌ«„½³‚„|`ïjIŒ°wõx–Ðצf„½³-Y%ôµ¶"¡¯¥J }§úã ê]>"·Î·úG ½«¡˜¤wõ×DÒ»1¯T¾¶º%è] [Rùzc=Aïòˆ–Èæ•ëõ5£±È׿‹ä¼: âî\œ×öm6îôx•Ê·Û2—œF…Pùz‡lãNïÉyW“³8¯YAœwj›bÎÛ>“Ì×§=àó–HÏk”•>I[é»4ý‰ôîFe^¨xTú¼a5êù„ÒJŸey+}ž’¬ôYÂ6ëÉÅÉBŸ÷Øf½£­={m7`¡ïÖI„>v6í5‚›ö´›ölÛcÚói}+}Ľ±XÅíYS$ìYJj¡¯UFÁÞöú®¶#•w®¦ Þ—ëVúxôô[AÄðŽÎ(FÂ|¼°É¼*´¡Ô2âݺ8ÜènD @ÒÝf³2Ñݶ†cbŠW"ºë”¶¢»³§wÒÝá©FtW»"9í‘îÚrÒÝåðCvãkx"ÝÍeýcǹ÷¦_n|aë)7>;ÍînÇO±œç(;väk[Ò]¯%¤»Ûà w‡£ÆîjQ“1(ÝøzëH¸ Gùñµåá®–Ý¡,H½1\5‚µó&ßÝ} .=¯]òxaa3ï¾t(À«Ïô‘Ù&Ö£a^ÊñF¯srãk>%ãõ‘¦¯ZÄx¡ÞÀ¯ýÈx£·xd¼65"âù°Jˆ×vB¼Ñk7¯'#!Þhÿ'"Þ=ìBÄmzHÄë3ãIx£Ï'Hx¡ð†¥O^HB¼Ñ^±¼°#à…ÈAÀ>àÕôF1o´àÀmÉ7 o´CoìÞ.Iͳ /Îҥ浚OÂ}D S3©y½Ñ•š÷ø€„7Ú5•„Gð <›1ñzˆHÍ;,ÕñF;tYÍóp%ã>¨‘š×'(d¼ÑÆgRóN³ !¯ú˜–ÜRóÚHaBÞø• ßh%å&©yáæÊ6W啚"#QP^Ù)gå òFÛCÌó‰± o4eKÌkqž7Zu%ä/@^öó˜PbÞÕ‚żö[“˜×*:!ox'i1¯ç¾ yçôó¬ùŠñ¬QKÊko3Iyý”²å´#‰o8fª¥¼vh–”w ›TRÊkóCIyáy7µ¼f*™sö3IÌk?x‰yïÜý|oÌ„(¡˜×CVbÞeïK2Þè3<‰y·ŽG‰xC¢…¼¶¦€C1”<вRòzÍ’×-RòZ°”’çб–òÂÞ“R^/Þ’òÚ÷WRÞ݉ ¼Ñ¶ò+ÁR^“¤<×"¶嶖WõÑòFpµ¼VˆHx=j¬åÙï˜ZÞÝžƒóÎE>€¼ˤåÇÀv8µ–'#qñ]G¤å5}HËó žµ¼€,ðݰÑ2µ<K‰ï†mØx5G¨jyGët¼ë²(oø˜×Z^Ó›l95'XÊ«˜ _)¯¢Ö}¥¼Kâ¼x)Òòºy¼þÀ,浬%1ïléŽb^ëe¼ê>Ý‹b^ )M9} e9ï6TKÎ;dyA=/ „7Žöá  ð†C9ð†Íx£–xçÀëUL„7ÚSrÞ©hx6å´e/>Éy- “ðÂà—„7ävþW‚›üêómïpHt¢_}ÂãÃ~?޹!ÿˆ{¥š¢¸¬‹, EÎSå.àlÊY§øÛ"b M9{¥w —–ÿÃ¥­§Ã¥OêÃåò±,áïpIÛr:ì©c¸´·¼c¸‹g[*ˆ‹½Å¥Ï½M'ü]m¶/ús€_àßz4æl†pK5¿ö!þµ®!{N{Æ:ŒË!2Ñ_b:Š‹Oâ…½P—öÜþõé½¢¸qEÞ þ•Õ1\Ú¯Gð×vo²æ¼½É5goÊeÍÙOø³¡Œ9ò”ì×Þk2ælbT—Þ€‹þZüýµ§”è/¼þNGä‘5çÓÑWÃEF˜“ýÖÖòhÊyu(²_:öá$²7È”³]émínø“ ¹-9ÛüÏìç›à¯¥Á_[EÁ’ózü7ᯠÃQ`}È@øëYÔð×í%ûµÐHôë)Âèg=Jè×^œB¿Å''ýFËr$¿öCú]? 9G ý¤dÈÙVgF?ãýZë7ú­Ö ‰~ýõ ýútè×ÇYB¿¦rZb7ùy ,ò ëO‘Ÿ1DäIôëM±Ð¯m ~~ý"¿ŽN"ò ¯C‘ßO3ÎÞ¦˜ü"6 Éo“„%ðë…Fà׋†À¯Éþ÷À¯ˆ~w%­8Û*RèçHÎF¿6§6ú €D~m-!òk[d‘ŸJ~m±.ð»e˜Fðë¹Tàׯ¿Ò=¿VœÞhµ§exßa£qƒŸ¿KƒŸOi ~mJIòk°üµௗ`Á_O>‚¿VBí øsÞ3ÁßÓNû‚¿>¾°çùÓŽ³•D²_¿;±_›ý<$Ì~­‰ýš1Ì~ö;ûYVúõÞ›èWáÅe1Jôó1­Ñ¯!èç§ú=v]ú—Éè÷8¨´Ñ¯«úÙ±ßìçE³_ÇS!ûùà>ÙODFöóËû=ís&öëX3f?A‡Ð¯Í…~uB¿ý‡¶×ß”Ñïö‹"û=ÞH˜ýlþböKü‚½Ø¯%`±Ÿ½šýt€aö³í´ÙϾÍ~mþ)ö³Á¢ØÏþb¿§•O³Ÿ_دï$ök9Rìçó±_;šýl‹jök>$ûù,Êð·ÿ ÞÒFㆿ>30üµáó9Ynøešý¬Šýd*ûÏÿô¿ÿ§ÿ¿‰endstream endobj 6 0 obj 180368 endobj 4 0 obj <> /Contents 5 0 R >> endobj 3 0 obj << /Type /Pages /Kids [ 4 0 R ] /Count 1 >> endobj 1 0 obj <> endobj 7 0 obj <>endobj 9 0 obj <> endobj 10 0 obj <> endobj 8 0 obj <> endobj 11 0 obj <>stream 2020-03-03T12:16:20-06:00 2020-03-03T12:16:20-06:00 GL2PS 1.4.0, (C) 1999-2017 C. Geuzaine gl2ps_renderer figureOctave endstream endobj 2 0 obj <>endobj xref 0 12 0000000000 65535 f 0000180685 00000 n 0000182435 00000 n 0000180626 00000 n 0000180475 00000 n 0000000015 00000 n 0000180453 00000 n 0000180750 00000 n 0000180850 00000 n 0000180791 00000 n 0000180820 00000 n 0000180914 00000 n trailer << /Size 12 /Root 1 0 R /Info 2 0 R /ID [<902099517E7CCE7BD72AF3B46174C714><902099517E7CCE7BD72AF3B46174C714>] >> startxref 182655 %%EOF blis-0.9.0/docs/graphs/sup/dgemm_rrr_kbl_nt1.png000066400000000000000000010440771422157504600216150ustar00rootroot00000000000000‰PNG  IHDRTjûF¦Â &iCCPiccH‰••gP“YÇïó<é…@B‡PC‘*%€”Z(Ò«¨@èPElˆ¸+Šˆ4EE\•"kE ‹‚tƒ,ʺqQAYpß÷?¼ÿ™{ÏoþsæÞsÏùp ˆƒeÁË{bRºÀÛÉŽÌß(ŒŸ–ÂñôtßÕ»­Ä{ºßÏù®‘iü常¼rù)‚t ìeÖÌJOYá£ËLÿÂgWX°\à2ßXáèyìKο,ú’ãëÍ]~ )úÿ†ÿsïŠT8‚ôبÈl¦OrTzV˜ ’™¶Ò —Ëô$GÅ&D~Sðÿ•ü¥Gf§¯DnrÊ&AltL:ó5204_gñÆëK!FÿÏgE_½äzØs û¾zá•tî@úÑWOm¹¯”|:îð3™ÿz¨• €è@(U  t0–À8à|AØø $ȹ`(E`8ª@-hM œà<¸®ƒÛà.L‚—@Þ‚°¢A2¤é@F²† 7È ‚B¡h( Ê€r¡PT UAuPô tºÝ„¡‡Ð84ý }„˜ÓaXÖ‡Ù0v…}áõp4œ çÀùð^¸®‡OÂðø6< á—ð"Â@”]„p$‰BÈV¤)Gê‘V¤éCî!Bdù€Â h(&Je‰rFù¡ø¨TÔVT1ª uÕêEÝC£D¨Ïh2Z­ƒ¶@óÐèhtº]ŽnD·£¯¡‡Ñ“èw †aaÌ0Θ Lf3¦sÓ†¹ŒÄL`æ°X¬ Vk…õÀ†aÓ±ØJìIì%ìvûGÄ)áŒpޏ`\.WŽkÆ]Ä á¦p xq¼:ÞïÀo—àðÝø;øIüA‚À"X| q„„ B+áaŒð†H$ª͉^ÄXâvbññqœøD%i“¸¤Ri/é8é2é!é ™LÖ Û’ƒÉéä½ä&òUòSò{1š˜žO,Bl›XµX‡ØØ+ ž¢NáP6Pr(å”3”;”Yq¼¸†8WJ)Hq¤"¥öHµJ IÍKËIÛJGJJ·IK”aÊ8ÈÄËì—é”y"‹’Õ–õ’Í’="{MvVŽ.g)Ç—+”;-÷H–×–÷–ß,L¾_~NAQÁI!E¡RáªÂ¬"CÑV1N±Lñ¢âŒMÉZ)V©Lé’Ò ¦$“ÃL`V0{™"eyegå å:åå–ŠŸJžJ›ÊU‚*[5JµLµGU¤¦¤æ®–«Ö¢öH¯ÎVQ?¤Þ§>¯ÁÒÐØ­Ñ©1Í’fñX9¬Ö˜&YÓF3U³^ó¾F‹­¯uXë®6¬m¢£]­}GÖ1Õ‰Õ9¬3¸ ½Ê|UÒªúU£º$]Žn¦n‹î¸CÏM/O¯Sš~°þ~ý>ýÏ&   ©†.†y†Ý†iñªî¯&¯v\½mu×êׯ:Æ‘ÆGŒ˜ÐLÜMv›ô˜|253˜¶šÎ˜©™…šÕ˜²élOv1û†9ÚÜÎ|›ùyó¦é§-þ²ÔµŒ·l¶œ^ÃZ¹¦aÍ„•ŠU˜U•Кij}ÔZh£lfSoóÌVÕ6¶ÑvУʼnãœä¼²3°صÛÍs-¸[¸—í{'ûBûªƒŸC•ÃSGÇhÇG‘“‰Óf§ËÎhgWçýΣ<Ÿ×Ĺ˜¹lqéu%¹ú¸V¹>sÓv¸u»Ãî.îÜÇÖª¯MZÛé—ˆÿ2Â6¢,b&Ò*²4r*Ê*ª4j:Ú*ú@ôLŒMLyÌl,7¶*öuœs\mÜ|¼Güñø¥„€„¶D\bhâ¹$jR|Ro²brvò`ŠNJAŠ0Õ"õ`ªHà*hLƒÒÖ§u¥Ó—?Åþ ÍŒ]ã™Ö™Õ™ï³ü³ÎdKd'e÷oÒÞ´gÓTŽcÎO›Q›ù›{r•swäŽoál©Û m ßÚ³Mu[þ¶ÉíNÛOì ìˆßñ[žA^iÞÛ;»óò·çOìrÚÕR V (Ým¹»öÔ±? ìY½§rÏçˆÂ[EEåE‹Åüâ[?þXñãÒÞ¨½%¦%Göaö%íÙo³ÿD©DiNéÄ÷e̲²·7¼Yn\^{ˆp(ã°Â­¢«R­r_åbULÕpµ]u[|ÍžšùÇ‡ŽØi­U¨-ªýx4öèƒ:§ºŽzúòc˜c™Çž7ø7ôýÄþ©©Q¶±¨ñÓñ¤ãÂÞ'z›Ìšššå›KZà–Œ–™“!'ïþlÿsW«nk]£­è8•qêÅ/¡¿Œœv=Ýs†}¦õ¬úÙšvZ{aÔ±©CÔÓ)ì ê<çr®§Û²»ýW½_ŸW>_}AòBÉEÂÅü‹K—r.Í]N¹<{%úÊDÏÆžÇW¯Þïõê¸æzíÆuÇëWû8}—nXÝ8Óâæ¹[ì[·Mowô›ô·ÿfò[û€é@dz;]wÍïv®¼8d3tåžý½ë÷y÷o¯ñy02*|ñ`úaÂÃ×2-<Þ>†+|"þ¤ü©üÓúßµ~oš /ŒÛ÷?óyöx‚?ñò´?'󟓟—O)M5MMŸŸqœ¹ûb݋ɗ)/f þ”ø³æ•櫳ÙþÕ/ M¾¼^ú»øÌ›ãoßöÌyÎ=}—øna¾ð½ÌûØú>|œZÈZÄ.V|ÒúÔýÙõóØRâÒÒ?B,¾“sMT cHRMz&€„ú€èu0ê`:˜pœºQ<bKGDÿÿÿ ½§“ oFFsF×j`` pHYsNNÆÊ/¥tIMEä&>(Ê vpAg´¨“ÁQè€IDATxÚì½{œe•ÿÿNHHÉ$5’ÆÄn1GÔjYÅE{¢ë5»Ð½êºèn¾v¯ß¯«Ý’]Eý²v‡ÝêoÍ´xCnÛ¥ÊÈe* d) “„ËTfäFÒ¿?ž~ººgzfz®Ý3sޯ׼¦»ºªú©Ë©çéóyÎ93r¹\AAAAAAa@fV»‚ ‚ ‚ ‚ ‚ ‚ µŽ*‚ ‚ ‚ ‚ ‚ ‚ C ‚Š ‚ ‚ ‚ ‚ ‚ ˆ "‚ ‚ ‚ ‚ ‚ ‚0"¨‚ ‚ ‚ ‚ ‚ ‚ *‚ ‚ ‚ ‚ ‚ ‚ C ‚Š ‚ ‚ ‚ ‚ ‚ ÂL A%Nã8Nµ›!äñ}Çqp]wÔûò'7bŸS›JìÓó';bŸµÃHíS~—N-Ä&§.SÅgU»Âô¢¥¥…X,F,Ã÷}šššÈd2„Ãáj7M„aâyÉd’ÎÎNLÓÄ÷}êëë‰D"X–Uíæ ‚0JÆÂÁ$Âð¬o­±]Aœjþ&û„Á‰}ÊïRA&š)¡’ÉdhlldÆŒD£Ñ’pZ­v×××ljÇã%³C\×¥¥¥…3fÜ¡Pˆt:M}}=õõõ¤Óiâñ8õõõ466–(§ÃYw(ô¾ŠÛ<ØòJ÷W__ã8ýÞ—[g8ûìxÇÁ÷}b±†aÐÙÙYè:&×u ×Jïs ð0½Þp·&†Ál&—}fƒµbŸ•k%¶Rî˜ôõ3 £ð_`ËQ|MÅ6kÑØç@¶ µeŸ#µÍ¾m+gŸãÕwŽÔ>‡kgÅý§~oY–üȸwèý ÖVËv:¦áô­}íV/Û­ dÜ[Ù>'úwéP¿I:¦Ñö«z™Øgm0ƽC}VÉ>'zÜ;Rû”ߥ“Ͻ¿É4ž~ÜÜ£³³3ä‰D.—Ëåb±XÈÅb±\wwwÎ0Œ\kkk®»»;‰Dr@.›Íær¹\ás½m6›Í†QØg,Ëår¹\"‘è÷¶mÚ0œu‡ÈE"‘\www®½½=gF.›Í¸¼’ýÙ¶Ëf³¹îîî~ïË­SÉ>+9ÞT*•³m»ð?—´y cê{¼úºèÏôþ#‘Hβ¬B›ÛN˜x³Í\.7éìs0¬û¬ôX+±•Ž)‰äÂáp.•JåÂápÉùÈ>Å6kÑØç`¶™Ë ÏæÆÛ>Gj›zŸƒÙçxõ#µÏd29èvƒõŸííí9Ó4sÝÝÝ…cj÷½¿¡úÑjÙî`Ç4Pß:˜Ýærb»µ„Œ{k÷wéP¿I:¦Ñô«¹œØg-1]ƽC}6Ô>«1î©}ÊïÒÉŒg‡ÞßdÏN?î”Tb±X.‰”,3M3‹År‰D¢ÄôM§/L*•ÊY–U²m$)³F_àâ÷} ±Òu‡(1m -¯dº³/÷~ eCí³’ãÕçQwŠú}ñà£Ü1i*wõþ#‘HÎ0Œ’íÛN˜x³Í\.7éìs0¬û¬ôX+±•Ž)‹®£iš%Û dŸb›µÇhìs0ÛÌå†gsãmŸ#µM½ÏÁìs¼úΑÚg2™t»ì³»»;gšf®½½}ØçH˜xdÜ;ôþ†êG«e»ƒÓ@}ë`ã^±ÝÚBƽµû»t¨ß¤ÓHûU}}Å>k‡é2î곡öYqïHíS~—Nnd<;ôþ&Ûxv:øq§\Ê/×u a~Ó4B_^Ûw=Ïóp]—3fþj!´¨o;‡Z>ú| ô~ eciš´¶¶bÛ6‰D‚H$RrŽ:¦¾aцaày@I8[ßâ~ƒm'L,ƒÙ&LNûÌ'›}Vb+}é¶Ûn#“ÉÐÞÞN"‘ ³³×uI&“…u²O±ÍÚb4öY‹¶Ù·•,¯„¡ìs¼úΑØg%Û•³Ïd2‰eYø¾_H»àº®Ï­QdÜ;4•ô£Õ²ÝrÇ”N§í[êWÅvk ÷VFµÆ½Cý&è˜FÒ¯‚Øg­1ƽC}6Õ÷ŽÄ>åwéäFƳC3ÙÆ³Cm7ü¸S®(ýPùH»†a`Û6Ùl¶ßgÅbadضÝ/—_¥“¾×­8Ÿ¢eY¤R)LÓ$ÒÞÞ^Øï`Û K%¹‚Å>«ÇHleçΘ¦YbǶmiŸ#ý>aü}f›ÂØ0R{j»ìÓ÷ýÂsÕó<2™L¿3Bm ãÞÚf$¶ëyÞ }ë`ã^±ÝÚAƽµËxý&±ÏÉ‚Œ{k—‘Ú§ü.ÜÈx¶¶ߢSÁ;å"TLÓ$NN¸ëº…r8.Ìú=¨ÃápÉLß÷ill,)2&Œ˲ ê1¨ó›Éd*RQ=Ï+\/½mÛ@ÐÁÆb1LÓ,yh¶0± f› öYmFb+§žz*žç®™Þ®x ;}ŠmÖ£±O±Íñg¤ö2Ôvåì3‘HÍf –e‘H$H$Õ> BdÜ[ÛŒÄvõxy ¾u ~Ul·¶qoí2^¿IAìs² ãÞÚe¤ö)¿K'72ž­mÆã·èTðãN¹•H$‚ëº466ÆápPçp8LSS¦iöS¹LÓ$‹ … ÛÚ¶]Ø^†aH$hjj¶íÂùD"Cn«UKÓ4 3÷b±X¿‡©Þ¿¾fm'L<ƒÙ&ˆ}V›‘ØÊ\ÀîÝ»K®©eYn§ísÅŠb›5ÆhìSlsü©½ g»âþSfËNdÜ[ÛŒÄvµã \ß:ظWì¶¶qoí2¿IË!öY»È¸·v©}ÊïÒÉŒgk›±þ-:Uü¸3òEd¦®ëBh‹Ãluèïûض͌3èîîî—Óó< ÃÁÏ80Üóë8Éd’l6‹ã8ã¾0¾”³Mû¬&£µ•‰²iaü}ŠmŽÒ • ãÞÚc¢ûV¡6‘qoí"ãWAƽµËHϯØõäFƳµÇDÿL69å"T4åN¸ïû„B!Z[[±,‹x<ŽmÛe‹W1çyƒJ²m{Ø!Mc½Ïñh#ŒîüŽ4Ì«Ãæ+= §²}N{/Þn¸Tæ…ña4ö9ms2íSo7ÄΦ>2îý>ÇËnõ¶Ãe"®‹0þȸwôû¯}ÊøUqoíîs¤çWìzr#ãÙÑï³ÖÆ³ÕØn¢˜²‚J9LÓ$•Jr³™¦IkkkUÚ¢ ' ÖÖjïs<Ú8FªHÖ²’)ôg*Ûg­ÛûDÛŠØæä£Vì³Ömi<ö)} 0RjÅn¡öíl¼ö'6( ÄT¶ÏÉ`ï#=ObÓÓƒZ±ÏÉbKµ`Ÿ#Eìºö©{„Éa?µ2ž¿a§lÊ/AAAAAA„±bfµ ‚ ‚ ‚ ‚ ‚ ‚P눠"‚ ‚ ‚ ‚ ‚ ‚0"¨‚ ‚ ‚ ‚ ‚ ‚ *‚ ‚ ‚ ‚ ‚ ‚ CpÔ¿øÅ/Nô—öööâº.½½½œp %ŸuuuÑÑÑÀÂ… «}~aZ1˜m‚ا T±OA¨]dl+µ‰ô‚P»ˆ} Bí"c[Aœ T:::¸âŠ+ؾ};›7oæ©§žâ­o}+›7oæê«¯fûöí|ç;ßaáÂ…¬Y³¦ÚçH¦ƒÙ&ˆ} B5û„ÚEƶ‚P›Hß)µ‹Ø§ Ô.2¶„¡™‘Ëårù…¶m³víZ®ºê*z{{¹âŠ+X¿~=—\r çž{.×]wÍÍÍv‡†††÷wÞyç±zõêjŸÇÙ½{7K–,©v3dÿþýìß¿ŸE‹U»)RëçpÛ¶m\uÕU|à¨vSFÅ`¶ Û>¿öµ¯á8+V¬¨ö¡ H­ß[{öìaîܹÌ;·ÚM)Ëdx~tttðàƒV»£f¬íómo{[MÛæd¸·äù1:zzz¨¯¯ç†n¨vSFÍtÛVJ­ßƒÃ¡Öí½R*½&2¶-oŸÿó?ÿÃÆkºÿ¬”évOO*½&2¶œcÛJ™ càJ™*Ï™J¯‰ŒmÛžuÖYœ}öÙÕ>¬©õ¾d2<jÝÞŸxâ þæoþ†O~ò“c·ÓÜrß}÷åšššüìío{ɲ¿þë¿ÎýèG?tŸûØÇ&ò†M­·ï¾ûîË]{íµÕnÆ Ôú9¼öÚks÷Ýw_µ›1*³MýùpíSî­ÑSë÷–\ã‰a<ì³ÖÏ‹Ü[£GžwÓml[)µ~‡évM¦Âµ›®cÛJ™n÷ôd Òk2®ÝtÛçÜÈs¦¶¨ôšL•k7cÛsÏ=·Ú‡5(µÞ—L†{«Öí=ç6nÜ8¦ûœ5‘ŠPWWkÖ¬aóæÍÜyçÔÕÕ±víÚ‚²ÙWÑ\¸p!]]]ƒîsÛ¶m¬[·ŽM›6Mä¡TÌúõë«Ý„AY³fÍ Jr-PËçpݺulÛ¶æææj7eT f›ÀˆíóöÛoj÷Öj»4k×®­éœ¤µüüèèè`Æ ìÞ½»ÚM5ãaŸ»wïfݺu\rÉ%¬]»¶Ú‡ØZ¾·4òü9›7ofóæÍœzê©Õnʨ™ŽcÛJ©å{p¸Ôº½WJ%×Dƶ“{l[)“½ýšéôœÑcÛmÛ¶U»©£f:Žm+e2Œ+eªk½/™ Ï…Z¶w=n;æ˜cÆt¿*¨€ºQ¯»î:š››éííeóæÍeÕÀ®®®š¾(‚0•È6ׯ_/ö)UFìSjÛ Bm"}§ Ô.bŸ‚P»ÈØV†fæD~Ysss?UM¿_½zu¿0±žžžšW a*0˜m‚ا T±OA¨]dl+µ‰ô‚P»ˆ} Bí"c[A¨Œ TÖ¬YCWWôöörçwÒÐÐ@ss3===…¹ŽŽººº¸ôÒK«}ŽaÊ3˜mbŸ‚PEÄ>¡v‘±­ Ô&Òw Bí"ö)µ‹Œm¡2&4åW]]ëׯçŠ+® ¹¹™®®.š›› EÃÖ¯_ÏÕW_Íš5kغu+ëׯ¯ù¡v‘±­ TÆ„×PY»vmÁ(.\X’k¯ø³†† „ d0Ûìû¹Ø§ L,bŸ‚P»ÈØVjé;¡vû„ÚEƶ‚04.¨ƒ¤ T¡ìOìSª‡Ø§ Ô.2¶„ÚDúNA¨]Ä>¡v‘±­ ΄ÖPA˜L8ø~µ[1|\WýO§!WÇÑÒ¢Þ{^µ['‚ ‚ ‚ ‚ “TÆÏƒd2xŸN¯3™j·N„JÐ6«×Ž£^»®²ãx|âň¾bŽëªeŽ¡jW&£^§ÓªÝÁkÃÓTïMSm«ŸIÕ>ã‚ ‚ ‚ ‚ Âd¡Ø/æºêýtœ¸+‚Ê(q]õç8Á²bÅq‚Ï´s§¨ Òi%,Ô×+»M&UGÉ(M$”¡E–‰è$¢ÑàuSSð>™T¯]W½‡U]"°mµÜ¶aÆŒoðóŸo2x^œp8C"–=¶«púy4¾s&£ÚS|5ú| ‚ ‚ ‚ ‚ µI±Ïi¤Ûû‰GùÕúQÂa%®Œ¼m¥Ï‰L&XÖØˆ%úù‘É(A'»ï~„pXµ3Vˆadðý$®"­'j¤®îkÜzëGÈå:9xð=$“ILÓ$ã8--õÜtÓ_ñão)uõ÷&“Á³£¾^½×bR<®DM:­ÖÕϘáv˜‚ ‚ ‚ ‚ ÂÈ(öñzžò g#Ñâ†öGkÔPþí?+‡m÷_7‘üX–5‚ãt“<Àüüò8°& ß×þ+”¨âPzžøè'‚ª¥ŸÌhÁÄ÷!%“ÖÖàsý?Òí@°~]¬èߡڟPÂauC:ŽZ×4ƒ÷±˜Ú¦xf½Níãûj[ÏS3ËõòH$P$ãñ`&¾aTûì ÂÈÈd2xž‡çy8ŽA6kó·{ˆÙ³»8tè9þð‡?päÈ{™5ë¿™9ódöí»•ï~÷=,Z´ˆ¦¦¿Å0 :;»Ù³'aÜãD…B¤R)"‘gœq9§œòQ\÷Ša‹*™Œ²C2,• "×´íe³À™Í§>õ2sçvpÞywóóŸ¿ÇéÅ4·sÒIÿ„ã8˜¦‰ëضM,Ã.êÑÒé4áp£È 3™ Žã‹ÅH$®bçÎ߉¨g“m«N'SíiiQm(î„G O®«Ž#‘Ò‡e2ê˜ôyÑ‹e©õGÒ™ ‚ ‚ ‚ ‚ T›d2‰mÛX}œ®ëÇÉf³cþž_íßM&•?·¸z(?¯eŠMêMؘ?ù0ǃ7ÙÊ¿s«£ÖÍd”OÈ0 ˜@ø±ÿ‘ öí¡Äʤ'Ûj_¶çmuœò~ -ì$Á2?¿oW¿öÀ7ƒïKçÛ4ÛƒS­çåÛxƒO&¡) Dƒ ÃõõÊ¿Uü=ã*à¥%pê ‹NFí¿´ó7¨v2Ö×+eñgj†ypC‘Ö3áC¡@t)ŽNÑ!U©”zï8j}× ¡Z|)vj¦R¥Ñ*±˜z‰¨ÿ©T`x}GA¨5´¸‰PˆÄ¸å–o0wî>šš<Ö¬iãw¿{‘™3ßÁÙg„yó¾Ä9ç|–t>øÁ»xüñß“ÉdÈf³¸®‹išùRÝüÙl¶ÐaÞ{ï¬^}5ï~÷Û‡õk‡>!P@-oiîne_Z°H¥‚Ž)™„G½—w¿û%.»ì2Þüæ°sçÍœuVœÅ‹Oá7¿ùWvïþ9]tgŸm‘J¥p]·DD)&¢w\„eY¸®K,Ë «×\Sú¬*Þ~E"àº,ËÂ0”b²k×g†¡¶ÑÏ× žC®«žoŽÁ³Q‹0ú™‰Œ.êGAAa*¢3’èI´‚ ŒétÏóH”ñ§Óé~bJ<>¾I§îË×Ï-öAkÿW±ÿ¹ÎPï- :Þˆ 2 ô ‡ƒ›.VL§ÅÑNÈhTÝĆ¡fvkÛkj .²v®†Ã¥ªžiªõ"‘Rq¤µ5pZ&JpÉfÕ6á°ºYm;ˆŽå(-¹Ò7´iÝ∩½½ôØ‹oø¾Ëµ! ÂDP¬Îkǽç%ø‡x#¾¿›|¤›þðXþüçÿà]ï:Ïû>;w¶‹%°m%p†Ã1‰D"˜¦‰YÆ«_Üa†Á»ß½†¶¶…eÚVuý݉ ®¦©žé´Z?qy×»Vó•¯ôð³ŸM(âOº•7½é+|êS«8õÔ—ˆDöñ‘ÜPh—eÅX¹r–ecÆ€bÊ`¸®‹aœzê,n½õMÌ™ãÉ´‰D°¬™Œƒã8lÛv1«V­âC:LSÓø¾O$!•Jáyi<ïvî|;®»ŒPn¾ù>n¿ýv~ðƒ1sæçøÊWÞâEïãø 3ft°nÝr}ôQÚÛcxžA2©®Y:]úAAA˜êxžò娶ú­¨}-¾Ì0omUÿãñ@PÑ)—õDX=)Vý–‰j‚PLKK ­:•ФÓiÒä·Ò™PÊmà3¿”ëº$“É’¶éIöÚ¯ê[Lx܃x=üc ~âÀËÀ?Çá>ß é8ô„á‘$,2áÀká ÖIpeæÙp¢¡„•K#°Å…¿µàÝwÀ–3zóðCÀ²ïÖÇáö;0,Z™BúÃJW‰_÷`e‘;ªµÎÂ6,+ÊÊôæäCLÒ|d><š²9…Ãp³;}°ÂðG|°’ðÓ$3ð„ ‰|ª0à9\º\X <â¨ggg§úîX,(·ÑÒ¢ÚxÿýgrÜqóin»{L• ÑB†ã(CwxÚçjšX¡×ÕâCßP'Ý9jƒ ‡ƒí::E‹. ÇÅßU\Ç@«{ZLÑm ‡ƒï/^_;3õgÚ™iÛÁ,{5+½´Ý¡PÿYìzQ¨[4z¹yóæÍÛÉœ9>†?~,±˜‰m›|øÃ[pÏó ц¡¤JD‰ cºÏÛßþZîºë%`I¡ }"¡lE„×b¤a¨¼•oyËþ¸û‡ì®‘¼t/MMM44\HOÏ78ñæßsúõ×ó…»o&VFäº.çŸ_üâ)‡ƒŽ³Q˜¦‰ïûX–ÅŠðÒKÇsë­ß"›Í’ÉdhllĶmÂá0ííÏ“N?Ïÿžp8L,# áû>žçñÛßtt|ŸU«>Èc-çÖ[¯Ã¶m~ô£Uüô§ßçŽ;þÏûžçqÎ9&÷Üó>æÌù §žzÿû¿=œqÆN\÷ôÂóE‹M"Ê ‚ ‚ ‚0™Ð˜#‘à÷ŒNï®gk÷:–ŸÐïÿ'¤o/|f¹(¿þ#œáÃÑ;aÏà¼sàñݰçFhÉÂo¾Þ¤Úkzði`W~¢óG¢ð²;"pº °ԃ›ÓvaÞs°Ò‚Ç"p· K[¡- ™$ü  ÃÐíÀ|[ýu&á•8x¾ŠBùpăí.Ì»»°0-iXG Xé@×JÈì†ðU_åÔ3òw.¼Ùƒçþxïÿ‹czŸIQú јab±à)}b± W_tš/½¶/më:t«Ø¹èºAç¦S…é×:ú¤¯h£f×oC¹”^:$K,*®û¢;ìr3\wøt4Œ ‡âôx±üË¿\Ë‹/>Ň?¼”·¼å±B=blÛ&‰”ŒšÎÎβ‘)aÛ6»w[hKCÃ$“^Á>µ-*±Õ'•rرã Ô}áuùÆL¾´ÿ>ÎëéáèßÝÊŠÎã#W_Í)燋‘Íf±m›x<Þ/”È×Lq˶×Z€zÔ¬‚  B'‹·‹Dàä“grå•WbY‰D‚îînZ[[ ‡Ã„BQöì‰ò>g\~9Žiò™ï|‡¦¦&\×å˜c>¹þïx×G—súéâº.‘H„lÞóžù¤ò?]ÛeÙ²ßñ…/ìcΜd³ÜsÏ=¤ÓÁóKR ‚ ‚ ‚0YÐiŒuĈ®«ý®«&¤–›|ªÅ*Ù¶ƒššú÷j&ø`b1õ¿XtÑ)§õDÝH$ˆZijRÛ'“Ê·SÜæÆÆÒöhŸÏD¤Æ„‰Ä¤âºïû8E7½ùI¸†aAùTB¡®ë’Éd‡Ã%ûÔ‚Jg>$¢o‹ëº455•|(›»}×~ó–/á¡ü5Á$Ó(ð5ÎKÃ<z|ø‘>+?'DáÈEð¢ ÖÀ¦÷Âm·ÁcÀ÷÷B, ÖøÉW!›Ëó¾ÃónHÞ\ Öx, =ð2ìNBä˜}ꀙ?Tۙ߀û™?w?ÿ^xw nJCcž. ÃÉ6œ†:þêXØïƒý1xÓ¯á±?Âò×Ãå‚ã`v;ÌÌÂ àø“ Ã‚g|8Þ‚fÐp… ñ¼oû•.¸ôJèþ_õL|_X‰0¸pÂgÁ}œTª0ß‚ŒC. eàM-[8ñÄýczŸI„J…h‡lq´G1:êC×J¨³NÍÕwAìÁ¢Ô’ÉÒCm£#cúŠ-¶= ‡Õ`@wð :ùh48>ýÝíí¢ZiQ{êGr •ÒWL5‹àoþæ£üøÇrÙeK¹ì²ñû~0 ƒ¿ú«Ž>úßY°`‹ý¯¼r ŸúT¡ÐX¸ðJ¶nÝI:} étÛ¶9ç}¯åWçŸÏrÀ¿òJî¨ï5*Œ1ßwÌ4iûö·yå…X¼`A¿ï71®8j_­¨ÐÐ&@ë¹!T'ýþSN)Ìœ0 صk9ŸùÌò~ûòã,¨?m/;>} ßóÙÂï|'öÏŽã847ÏaÇqsxÊ‚n?w¾S=LŠE]”MÏʇÏãŸÿù>öî­cÏž=D".ÍÍs€5êâêYQ?Z¼AAA¨6ú÷¨T²ÙÒÔê:¢ÄqÔo]ë@ûYtªhíSÈRì³Ñó⊥Rô›L¨S±ë¬ z½ÆFµѤ8óŠ.F­³«§!„Zåkix¿=xŠ;WßèyŠ#I:öí£éÄ%œÜvà€ÊèÜwóÍ,îíeÉÑGãyÑh”¹¯{;®¹†ž;î(ìÏó<žþû¿‡•+±,‹?vu1£¾Ë4Éf³´´´pÁ—³kÿ<–ÅagBmÓ6Iÿá ÿf ñk`á÷wËxê‰#4Ôï€cÞBý/žç¬MÇsø$ØúvXêÃ[VÀ_ï'ÿÑ ðÍÀ|Þý0Э1`;Ê!dAëïÁ½8(C(gO¬ÁÜö$اý l>ûáþÿ æ¿õ}0L0„yÿ×%Á3ÁùOˆ~"‹áG—Ó6ô‹—Á&ÄÛá÷SR°ö,K—n€UÇÂÿm€í†o­~ïþšò]Ý_DáŒõ`¿žmƒ%XHÿpzþ8v¸Ø‡m/@öûê°ê}xÚ‚‹¾{+8ó!¼ ¾|&„χãp{îB®zçãcz/Š R!ºüh|ƒ…QêZ(•¢ B7W¦.8]ŒÎÏ©—ëˆÏ ħ3 :[½?ËºíºƒO$$M˜0<ô T9Û]ÒiUä›ß\ʺugpæ™ó+ôFB•B«µµ•| —ÛoœX,†ë¶ñÈ#·å#=NÆ÷ãÇ[¶pú¦Mxgœ¡Šc¡DÐM´Šþ;(QäCsæ`-_Ε¨d_aTðÂWp^ooÙ¶¹Š´í?’ÿÞЊ|þþÄßrç+‰jä¬7 þ¼ôSÜüò]s éTŠ9!østBë=K°xÄ­ëÓx@]Ýa^zikÖ´qï½ïä÷¿ÿ)7Ý4Ÿ«®ZœçtЮ¾Q€];JAAa¼q]åÑ“H[[Ëg$‰ÅT„H,V:15„ ý7Ú3ØzŵUŠÛY,ž€š´ YPú¦“×>(=X§!Ó“Üâñ .A2Y^lÑõ{‡Já¬ýPãù»]˜úlÌÀ,>;ˆ}üìgçC{ÇqøÁm·ñ‹›n¢µµÛ¶q-‹Y§ž (_Ê£/¿Ì+ÿñ$}Ë–qϾ},{åÎzàæ¿ø"=ïxÞÁƒ¬8å\Àð`ëÖ¥ú$šÆqÌXy&¹§g½ò Z‰ò+k?Š,áíéƒ,?úUÒ‚u<|» ø{ù÷ßÏçóöóÖYs‰~Þý7ù烋r¥QÎ& 弉u“uµŽ©œBŽZ×2G>Ñ,Æ.8í_`û'áÓ‹ÁÜâÑ5p„z!öÈ#„ÃgáÜ‘å] 柀(D? Ö‡Àÿ9ó£œ[>+¯þŇ6—Çž>†øt ˜¯ÚÓ"ðî°:–ð¸ëƒªÿËànƒÄçóÏ«¸:®›ðñÇÔw’OÇòdžç2~ ŒËÔûX pœíÃK'3æ÷â„ *]]]tuu•,[³f uuu%Ÿ744ÐÐÐ0ÑÍñ.ò¥;/Ç©ºþ<"ÖyÄãqîøóŸ™ùoY¹€¬mc#¨câS\%ÀBõmˆ")T¨§“ÿn ˆu?¾òJâùe·Ì~ûš¶g~ùå|,¿,¦ ”èÏu[LàÅŸÍï8·°?°—/' T߇Ƿ-×`Co/Û.ºˆÈœ9…´\ûçÍ£gæÌB6§g΄†’Àʧžbö 'à{Î;¯0!ÖŸ7…õõ4Wfà‘GNáå TíZÓdó¬Yì^²„}É$Ñh’zðòK9žÞ’ƒ™pnf¼ö}Ì;õÖ Û˜1·§¯~Š~€øÁaŽŸ·o·Ïà™ß½†ô<°æ€y*„?óùwàÈ‘#àC*š÷ðØ1ñÜš?sá/Þ£7ªr| øë4¼Í‡¦|æoXÞú'ŒÛöc­: ŸXÎÀD¥O4_OÃmÌ•6ÆBˆìý¸þfÒßãÀœr¥!rê;ã€ækÀè…³ÿ.ÒÎÀ!VÊ©D~›…t-Gž:Ÿ®ûkœ5$ Hèc8ˇÿ™O8<;pšÙù‹~)n7óÎ*Õ†ˆžxë —ü9¹åÔ.Þ|ÙѼ4kl% T6lØÀwÞY²lÓ¦M477³yóf6lØÀš5kغu+ëׯgíÚµÝIJØöøŠ:4s¸õHFò=uÎåÒ„wú:B'‚îîÒ}êSÇQ¶îÈõlޝ’YÂÄ3˜mUµOÀ«®z;áp˜l6;¬Ú'åÐe|ô^ T4¨þÀAu®*mVq”ä/òöóQT]•¤i²råÊ‚ðÐ^´¾f0´½Ï{› rE›dØ÷9pÛmdÎ9§ |DòëT2.Oä¹>ÿ¾5Ÿ…ê@Û •£-¸å–϶×éÉ@<«òíì[I÷[Zl1P‚Š äÃÎϰêƒËyچǃ÷ ƒmŸ³£.¹¤—|‘ /üï{ßbŽ;îdÂa5(Ö5W'HI8]ê¯Ô²} Âtg²Žmaª#}§ Ô.µlŸ:2Cû€t“J°¬ÁS¶WÊ@5y5}[–òµ”ûmdYÿF§±×iÅ’Éòéà›šÔrËR~ßWûÐ%!2õZOŠ+Þ‡®-ªÓµ¶ªÿ©TP;F§?ë{œŽ£„-étñ:E½ã¨¨]g&Smð¼à:9ŽÚ÷P3ÂÀÔòØö•çÁköÇ—‚?Ü×¾´“%KN祗Ž ­dÁk^ƒ}ì±üxˬînêÎ:‹?74ðH~ËwîdÉ’%ä€ ï¸ƒ§Ï=—í‡óþ3Îàp]ðÔSOqÃg`¿ôáÅ“.àÂ3p·žu»~±”…ßøZ>þnY'90'´‡?8'Û°ÍWŸ;“†×âw?;™pý“³Ù· ã±cÞR>rå<îXø{_<Ä*ðwÁ +^`Ï!ì=Ëø÷SÿÏÛŸ'bÂÚ¸ÿ‡¸·þ^Îlýð‹ùàÚÊÉ£ïûó}èváò K¶ïçÈU|)±Õç/'ÍÂx­òZéG†¸°"†¹²¿3ú'0!ñ-`¥³µ£ÌSßiŸ‰?oÉ_§­[9æÁ4œbÁI)åTÒÎ.í`ŠÀžÖ=´íjcMxMàd ÷»ÄŽõà[aØe@–àá‰À³@,ÌÖÏh¸&²`f Ä[1/LÓÒóžûæ±½sÌÇ>ö±Ü}÷ÝWö³¦¦¦Âg[·nÍz꩹gžyfÈýMÙl.×Ù9þû·íòŸ†1à¶ÝÝÝ9˲r‘H$—Íf ˉD.›Íæ:ǰáíí¹\,V¾ý‘H.êZ[ÕrËRŸ™¦Ú®µUç ‡3é¸öÚk¼§'ƒÙf.7|û¼ï¾ûr×^{혴í¼ózrápxTûhÏÿOär¹pþ¿ËåÌ¢?#—ËÅr¹\w~Ýîüûöüº­ù÷v~ÝwîÝ››³}û˜c1ú;Šéìì,|,—ËYù6׺³}ŽE_*Lv™ïÎær9ÝYËå"ù×Åëuæ×3‹>³‹^Ϲz_®¾ÞÍùí?åVþèG9²Ù\4™Ìår¹\*¥ž©T.·téöÜâ†Çs»úºÛ²å/¹µk7æ>ýé_æR)õL¹âŠr«VmÏsÎgs?ýéKƒïDõãÍXÛçT9/Âäe,ûˆj3YǶ‚02¶-ÏTzn “—©ÒGÔòØ6S¿KLSýF™ ´·+_ÌphmØ/cš¹\wwÿåzýXLÃPë™f.—H¨?ËRŸwværá°j[$¢ÖooWëšfà7 ‡¿Qk«z­ýIzÝlVí»=ÿ£¾Ø?×Þ®®—¾nÙ¬Úg9¿Uñ±§RÁ{Û.¼ííå——c*õµ<¶…\®ék/är¹\nö±r«.Sþ˜dÒÍÍ™scî”Szr¯;¹Yÿ|(wTOOnþÁƒ¹-ùKîŒ/97÷•Wrõ¾_ðiDr¹Üâ[n)ø€ÞøÆ®Ü¢E¯Í½©5›kÏ©{,‘Èå²Ùlnéöí9;¬î,åCùuw.·(–Ë{ÑK¹·­|2¹y¿Æµ§ôä.~)wõr9:s9Œ\îâ+r¹Ôª\îÈ¢#¹Ã çb‰\®ó¢îܽox9—³s¹Û/¼]9\ªqáp8÷ÄõOär±\ÎÖÎâîº)wËy·äº»»sߘ93÷ü¿ý[¿óôÄõ×瞸þú\Î0rqFîéÅ‹s¹l6÷òñÛs¿^wC®;c§R©Üßþüræ†úîXN†Ò e¹\à´º¹¼Gê/k׿v{¬ÚGwÑ6Å´ær;Þñ‹ÜoÎ??—ëÌå^<çÅܳóÞ¬v—&r¹Ef.wFBm—7êýý¨Z?šßYgg.wz8Øw$’ åŠÇ¤r¹¥±Üö•«Æ|l;sÂdÄ•Ø`Øùcq‹Ž3‚ŠÌ±Ù¦½èµÞÎÌŸPÅ\ÔîË ˆìœ¿¸—Ù³÷ž+uuu<ôâ‹´á_7<Â~ð^x‡N8œÀSO=ÄC}ßüfVaæÑ‚°páSlÙRχ?ZZÔ~\WeLqœ JGgRÑ‘/¦©üPÚ¤ýlѨŠÈÑ‘9Ž£þg2¥ÇØÒl“ɩ맵<¶]pý“¼üÌ,®¹æQfœÓɳ»TmŒŸþô%,x‚cOz'¾m! ;Àáº:>øòË|oåJ=úhöÿr¯]´ˆú-[”_Ç…ƒ7-Uþ fÏžÍþýWÓtß›Uf/ðA.‰¥pµóÃ…5Áƒi˜•¶ÏâG…•ìxa?Þý'Þôf¸°áuåóþÃù6ÌHÏ`æ;f’ÈÀ² çò–ŽºuÓ{J¯rÐÄ`î³ÏrÊŧ€«|Äx*Êäðö'yáï^À0 þpüñtÝs¿ç=ø¾çyü×¶m\ü¹ÏqdáB<ÿ<‡Ï: ?™¤mÁct¾’Ãɇ›yžÇuG~ N>Oß=IålÒF  À 4K^yæÃŒ^ä^hlÏcåÊ•ì[¶ ²Yîûå÷ÙÿéOCØ êH¸.XÐÚÕIÓ_þ,X°€WØÊ‘‡ŽÀk|8= O¤áèL!üm»vñ_GEïÃw«}ìwa­jïo_y%ÿPÊ;^ŽÀGœsƘߋ*¨ôæ‹*_sÍ5œvÚiœ{î¹lÞ¼€ŽŽŽ~»páÂ~yûú²mÛ6Ö­[7ªve2A‘õ‰vØkÁÔýaJ ‰F£…ÿús-ªD£Q’É$d2Ç!‘H‰D ëd2R©‰|Ohš&žçáE™1c---$“IÂá0V^åÈd2ضM8&N¾ßu] …B455 …Èd2D£ÑBhå×¾v îkeNÇÙ¾ýÞB*°âú[ߺ‰ï~w7¾ï—Ø¡F79“ ìÔ¯eeݺuÜ~ûíÕnƨÌ6aäöyûí·³aÆ·K‡ë>ü$ö(F³:­b'¥)¹t-P F± ÎÿÅ€×.Z4âv „N+9± Ö}üZ×4QbR+R®MÅÛê×ZDñó:Å—‘߯¶Ôºåؽà fä¾½çÇÎ;ñ€xgŽ?<~-Ç?Ã=÷Ìæè£æ/½@:Ʋ,vîü%>ú2¾·Þú&þò—zÀàðáÃ%íÔý~GGëÖ­c÷îÝc~}&šñ°ÏÝ»w³nݺ’ýÂD¡S¼ð Õnʨ©Õ±­ ŒÛŽïØVFŠÛnÛ¶­ÚM5µ<¶ÕiÌ'cÆáÖ ±í…“ÁŠÇ—;?‰„ItËâ¹ñ¸3ŠÛišÁwë4d‰DÞK§‰×t;;ÕçÚïÔ×5 EË jÝ$JiiQ>%ýj"°®ãºêuK‹ò[VàCŽD‚:2}æ&—ð¯ÿúþõ_*cÛÐcÛŽŽŽQ·ï¥OœÂ«¯¾Ê=Ëžå´«wrôê¼á ?¡«k/ÿøÅ¬¸þzî 5ñÖ÷¾žÇ×-âÞ˜·òÿPŸV~Šßù6ðóŸ?Êò'ÎkóçÏçâ‹/æMoš«®÷^po‡?'.dïïÁ4Õ3âäwÜÀ6œVXáÃŒs9?7›pê\ˆœÆQpÞ#çaÝ gÿæEÞû†û¹ |ƃ[âÊùâÁ¼cîSN¦@†—N})ŸJËá²;”S% †róƒòï³fÑ´g^s 'ΛÇ)<ÂO.¹„C÷ß϶|€O^z)Û¶m㼋/fæ7¾ÁâÞ^<Ó¤÷¼ó0 “‹?~1ïºï>núÖ·ð<¿lÙ¢Nn"‡°ààã³÷§?UÆ”7¢‚6¯HÚs?w½ñßJ‹F™&„Büä‘Gزg¸.Ù¸‘x€Æ–– {: x¬ùövΛѾvÖÿaîÊ71³þ×Ðé²ÿ-o&w0MùBg'g]=_¼ùfîZ¿2þï'>ÁON;®já¾ïŸÿ~é%z6n *Àƹ~ÞkÆÜV&´†JWWÍÍÍ\uÕUlÚ´‰¶¶6®¾újèééé·~%ÅV¬XÁ¦M›FܦtZŽ~˜N:²#™L’H$ˆÅ"xìØ±•/ÙÁ4M²Ù,É"9<“É¢BÒé4¶mFioo/Ù¯çy˜¦© Èê ó@(”8bÛ6‘H„ðÕä}ß§¥¥Ó4éìì$“J¥0 ˲ Ñ,†aÐÔÔÄìÙ¿áé§ï÷âya|_wx®ë²uë*Ö®={糟íÆ4}¾ð…›èí} Û·“L&Qè@]×å›ß<šÿ¸‘;`>®kâº.W^ù¸å–_W½˦M›¦ÄªÁl³¹¹yÄöùÎw¾“õë׸]¿úÕº»qÌ1wbÛßñ~Êo.&•Õ+™ h!¤œDåqœVÑç6JdÒ"Œ‹T¢¨Š>ýÑGó——Ñ3ó8víÚUØŸ¼zèÇ75²ýÇq É¥îØcy~×.Âá0?ûä'ùýüùtv¶rûíÇrî¹ûxõÕWéîîfÞ¼ÕìÛ7WMnÈ7ª©IÍ”Z½z5›6mšNÉñ°Ï%K–Œªï„ѰvíZ¦ÄLðZÛ Âh±íàŒvl+#Eƶã?¶ÍO€¦È}2©˜ˆh-6ôÍ82Xß/ïkÓ‘"}Ï·aµ3u$Œpt„Ë@ÇZìÒ/:rE׎iiQ_¢Ñ@Œr]åƒml öQ«×‘HP+&“矿ˆ?ÿù|ÞùÎïŽÿEgjql«r¿ÌGˆËÓÇÇÊ|FÆÆFLÓäŽçžcÕÿÈÏN8wþâ455Ñ4cŸ;÷\>·x1‹Þÿ~%\üå/|×.^÷º×w]®<á¬D‚/}éKÌxËwøTçؼy3k{zXué¥,xâ xÛÛÔI0 hjÂ?x›î¼“Ïæ à±ü€o½ò ©H¤0óùÑð¥Û¿Í»Œ€ãÐsÜqzë[Ys–móøí·³å•Wx]GÝï{­‘D£|êÆùÎí·ã™&i×åò׿ž“-‹7Yµ'yêÕÿàËâCÍ+9é¿¶°èÝ‹¸¯çjö¹.Éd’T*EÏ-·°cÕ*®ÈÉnûÁXuóͼ1檯Ö|1+×uÙ¿s?¡ÆÐ˜ÛÊ„ *z innæÒK/-„õ¥««‹Õ«Wk›t-]ôÊuG·? ¢Ë÷ý¬zéašf!´Êq,ËÂu]~ýëxñÅ+Ù»÷E"‘‘|ìeqš£L&ƒeY…£X<ј¦YX¯ZQt]˲SÂá0‰DÏópÏóJ¢,Ë"™L×Ϲç~œÏ~ö*b±`¿Žã‡y꩹\wÝ\Î?.uuOòÕ¯þˆÙ³ïáoü5<ðZ~ñ‹<÷Ü_ÓÓóM`%Éd’_þò:À#¾/~q.óç¯Ã43<òȵ|ã{øÞ÷J(Êf³%Q<‘HdTQ Ó‰Ál³¹¹yÂíÓuÕs|Þ¼œ|òn¸áŸ†ÜFTåÀצÉ6Ú;!ÅèE™ZÁD¥>è³Á(žø¤kAM Oz?^þý«û–1ïx8|ÖY,[¶ 8ãÈC<ùulOÃQ+V°2Ýžišœyá…XÀÚµ3x꩘7ïšÇìÙ³yýë_åØI2¹ ßWƒñ ^SjÍ>A¨Å±­ Òw B-S‹ö©þ:ÊB(†C{{y?›öÝ$Æ8Nù¨›¾…ì5:E§1ÓÛÆãAJ´dR¥ƒ`â}"DÉh÷˜b´¨ûñ<µßWç¶U›N?ýÕê^œ1¢–ƶú§}2 v\ Hná@û9Ì\¶‡E‹qhÛ Ìx_Ž£~®®£‡òS,>æ§~÷»pùåì÷!áA܇’°wïßðÔSpÌ1ÏÓ»gqA3fCØ׃ðéê»#« ¹>}|ÜÔÌæpñŰ É`,ë4H¼œ ìSÑ)üÔ᧯y†¿Žü-?|ú‡´üªEÐ^ƒîövêA9«¬$Ä}N~úiî¸ývøìg¹ê³Ÿ%½w/?|Ï{¸ö”SøÙÞ½Ô…BÜÿÿAב#×ÛË}”g׬ámW^É—¿þu®_¿ž$âºüÕûÞÇWÿüglÛ¦{Å Žn¾ùfêêêXµjg]s Ü|3Ç}ô£ì¹þú@lm…h”%é4/Ξ]HçôÚ_þRMÚÏd¸gï^æ‡Ã|7 €ãð‡£æöƒ1Ž: 'Ų,LÓäŠþgœgž¡;“aïìÙ|æ‚ xaî\ê[ZˆX–ò‘Çb8ñ8ñï§Ùþè£=ÆšcÖðè ²ˆE|ñæ›±,‹D"iš¼ÄjÏž=ÖŠpÛ¶1 £%ÒWÑuT´ààyÞ€¢K1±X +ƒ÷m—eY…vX–E$gŸ½(ÎIÏŸW“×bÛðÝï^Èå—_Î׿þ=æÎ}™Ì .¸à öîý)Ÿø„ c~ì±¼éMËxýë¯Çu]^ûÚ÷QW÷ ɤ X<ðÀùëÔr©¯¯/Ô‰IöIvé8NAÌJÌ6aâí³©IÙæ¬Y?å®»Vræ™å¿'ª’AÕGÑ´Ôò1Úè’©"¦hЍ‘§QÜük ÔŠ°LakÞáð|;M•SãÇÜÍ“+E§,æ©8`š<}òÉ…í¯ºê®¾úO\wÑk˜u 9ê<.\ÈâÅÔ€v A÷d§ÖìS„€ZÛ ‚ ¾Sj—Z´O²\Ä”ÁÑÂpH&)›Ú”ï¶Ü9×®ªá\Ó,/ΘfP+Y§ +¦\*/~¬XJ$‚÷étPëEÛå—OþTÓP[cÛ$Ê_HÀã<–í†óÀ‚ºkv0çŠÈ}þh>²ñdâþŒL¦¾0Q]§mK$^}u–?x³Ï"™Tþ'kðDlðžó)à1ð_…O8žý‹öpÙÒ„—€¿ ¬·¦Ê#¦s³?“äþÅÿLøÞSß#÷¿9ˆÀ‘…g󯧞 (_&¦É¾}ûØ}ûí¼ÿÜsiíîÆ÷}¾sì±ÜUWÇŽ?ž+gžy†Ïýú×\rüñœþù¬ZµŠSÎ;ù |îsŸã¬¿û;‡©»â –ÍK"›eÞ¼yD£QîîíÅq"‘·Ür ™L†Å_̟׭ã˜5k˜³jU©3<•¢%¦)/8Ã_ܼYùS=CgžI&“!ÊPàºüeÏž‚Ÿ9‹ÅÈd2ô¾ÿý|ö{ß#‰°ùÅ™wâ‰\²mv8\â»ö}ŸE¯}-_þÁ”ÿÙ†íK¶ö‡ þÞ´ïsêÿý¿˜¦‰eYø¾_ÈΤßk_ñÙï=›còµvÆ’ Tt¨˜ÎÉ×ÛÛËwÞYÚ©Ó?tttÐÕÕÅ¥—^:níñ}uoh…VÛÓiøøÇo è”F£±%Nê•ø¾O8&’WʉùÃP³°wî܉iÂqÇÝÒO )®{2TÄ…aض=àzZÑ*•`š*͖ѧ7ÓiÉB=»Ò8ŽS²­aÀ›Þ4—íÛ—ÐÝÝÍöíGË}6ß6“‹.:Ä+¯¬Â²à¹çþ‰L&C"á°M"‘bÓ¦—9pà;¸ù<~º>L"‘ N‡ µ_@ H---d†;bš0˜mjŸÅà,x µ˜$`FT%œdPÎ|]L>CÿúYÓâ2ƒ}^ º~ŠÞ—Ùçµæ¢O„yûû}ç ‡³/?`{ƒ /ÙpÈ€úúzÎ9眠M|å+°ó‰œòÅý,8·‡»î:‹£Žú8'ž¸¿0°×Ëd2YòìœÌÔ’} ‚PJ­mAPHß)µK­Ø§þ© ë{LʼnYcŽ*.M\,u×p…›Ü[ºL¹v—ó5€òIh¡EïW(×Q+:˜þüÄ÷³}û’Ñà Ƕñ8ü΃îÎs÷ÔCöüIEżò§ƒ ³Þ»4À>À'ŸÆ+Œç©‰—Å5s-ZÄEûžçù¯!²4Ÿî°ºÁ{F«/€øŸÁ›±epJï)¼fÿ«|ô¬]|jë§ „Ï€Ä;PN¨íˆx…Y¥ÏãKÇ(GþÂÍ_²oÏR÷Ö·pÝ»ÞÅ=÷Üß￟},xýëñM“t:ÍÜŽþýøãÙ´w/GV®dîë^Ç•W^IìíoçÓkÖ€ça¤RyÛÛ8ï¼ó âÀ‡››9ÿoþÏó ¾híÖbƒišõo‹Çq >ìt:ãy`ÌûÈGˆD"dÂa\ÓÄÌ·sÅŠÊïâ8Ü–OÛ‹Å ßiæ×åC¾þ‰'XöáÓÞÞ^’™) ‘ʇŸ¥R©‚O{ö¿Î.+glúÎm·±æÝï.³ždŸ=“L&é]ÜËÞ½cœòkíÚµtttpÅWÐÐÐÀÖ­[Y»v-k×®`ýúõ\}õÕ¬Y³†­[·²~ýú’™ c‰žÍ¥§?e"ÒjÉ>A(¥–ƶ‚ Hß)µK­Ø§öEø~é$[a`tݑበ?µþ ™é‡½.P?å>ÓéÁŠ$ߢRô9°¬à;ÛÛ±oßäTjml«§Iï÷áÏwÕ1ÿ#;Ù#½æ0€sº»I×׫ô㇣Æý-XsÀZ æ½–þ ²fÄ.÷DH{j².Ýê/¼Ò‡Áz=xûážÙ÷бðYvìùü Êõásqxk ÂðôûoaåIDLØì6M>ùâ‹üýÁƒÊa™H°íâmxŽGïÝwóŸgŸÍÏfÏæ¿^xkW¯æ§ŸÎÍO>Éù?ûËÞô&ºo½•·þÝß1óúë9+™dß¾}¸®KʶÕ͘+Š'“;ŽÃ%—\Âm·Ý†a…Iè¾ï&º÷,¯·/ö¡8ŽC"‘  )qdˬ3 “ø#‘¡Pˆºº:îºâ Z[[ ê-Ëê7Ù¿©©‰ööv<ÏÃ0Œ‚ ¢EMqût›ôçÆŠnkkkIF&]b£»»€ôà˜ß›*¨|ùË_¦£££V¶víZš››éêêê÷ÙX£Ãûvœ=h/½´‹ûï‰|$V¸!õ…Ìd2…š‘H¤Š+™Lj§„‡èêêž$›…¦¦Ò¶m“L& 7ëXàºî°fn#˜‚`ZÑŽG;;#‘àsÛV95‹Ù²¥‡¿þë[yÃ`Ûj¦ú '|σýûç•DÚxžÁ]wÕK˲ˆÇã´¶¶ê¿xžWHǦS§9ŽC(*Z1Ń©Î`¶ gŸŸùÌ.V­ºŒC‡ºû‰xiT‡šB¥õÒéSS(§}%¦è«AE[Œp<6-É>ؘZ±o0àð3Çp`ùrv47³àÕW ;YjÁIèuaùÙ»X¶l ®{Xd»r¶ ¯ýóÔ×o&™Œqã÷bÛ`êù°sçþjŸÎ1£VìS„þÔÊØV„R¤ï„Ú¥ÚöéyÊ¿iš"¦ ‡"=Ã4‡/ÂŒ$ f0wÙ@Ÿyžò –óÆb¥%,+¨Á¬}ÄÅÛ½ím/rÛmÃow-R+c[Ø“¿í¼zèKÞv„ ‡Å‡NÔw×××ÊÿcßX`Þ î›ƒë•LBëBp/‚–ŸŸÊy<Â…õ«1~7Û€èV° °ò¹Ëý»Á~ìàíÇŸ~œ%½<³-ÿE¯5àAþp]VnÞ +W‚éÁ¯²$óº» 3‡3âqN»ç¼ /äŽÿïÿcíí·sÑÏÎË»v±Ä08mÿ~Î:ë,œx"]O>É9çœS$lÛ&ã)»råJ"‘étºUh°²zŸº6uKK ±X¬0±^××~îb‘Äu]"‘çÁqœ’ G­EX퇅B$‰‚Ÿ¼¯€Rü^§ëºelr‡d2Ù/›ÒŸÏü3%…FÏ„ *À ‹&j0kÛêX.bñyÿÌcñÍU«øú×_déÒËH$®$.fSS@!Ê¡8ê#‹ÑÔÔ„çy%7Ñ@èÔU1”(S :¼k¸V+Áó<-–’L–²×‘)êxJÃ8 Cut¦¹³ÎZÏÓO+õóŒ3ò—¿,Ë·C 3–_ùÊýlßîs÷ݽ@‚•+W–Ì|І¯kÖèz0:J%™L’J¥ð<¯eÔ÷kuv:*ÀÅÄ&Â>·lÙƒm|ûÛ+ Ë”Xb¤òŠ8òõUëkeA_' ,œ$†³£¢ý  ¤× Î’%Ì?tˆ=õõ¬Þ·ùf¸°ØgÀÉ'ŸÌ²ü6ºÎöüŸ†Ù]\°1o»póæý,_¾ ÃXÊ\Äž={8ÿü§«}ºÇŒZ°OAÊS c[Aú#}§ Ô.Õ´O=Ñ3}Ý×u ul‹ý Ú—P©E˜xK-–/ Qc†òcŸvÚ^^|ñÀ;ª}XcB­Œm÷ä‹¿îðaItІñaéAö‹0Êgƒ ˆëþàúßU4Í™`¾ Ör¸sÇY¹`ýV€æ·õÁ8ÒBê?Bñóîåï&’ëÓ@Àd’ý;w²}åJNH&ñlÓu!cîM7±oÎöÍË…÷ßÏ¡¯|E5ñØc9æ-oQên8Ì>ÇaîܹœóÙϪ‹¢Œ¶m²aYê-ƒ^Gû>u-oÕTcÀm´0R]bä ¾ûQ‹Ÿqå&êëe¶m—-¹ k]ëvf2|ß/d*€ÂdøL&SqF&¿Œ‘†Óa¶´lùX† ­¡RK8NK±˜nTqë*¶â[«V°{÷A¶¬]Kšà&,®Ý‡Ë¦Ðjoo¯HLÑuJrÜ¥CßDɈáD©(cп¬BÛM3è”@‹'Áv:§!ÀöíG3{öl >ô¡¥lÚôy ˜!æMçóóŸŽŽ}Ôׇ8ùä‡ûå=5M³0Ñõetè—Ϋ—Éd ç¿Ü±L•: “–xã¿É»ß½¼°,‰S‘(0|Ç¿`1¶5eÌü>ËM<*~rͶK/ŸõÒKÌóáB VذÌTíÓݯƒ$íÎªïØæPZ$þÝï®cç{¸é¦¥üèG/ÐÓó0Û¶WíS-‚ ‚ BáºAŒÑíÇ%ŽÅ¾ƒh4J4‘ÿE˜b±K”séIÙ¢‘M‹L”#È€Ckv±`ÁT¾å³÷EB‰#¦úo/s‘ò19Ï@gTíŒÙùTbz®©¢S°QÄÀü˜s(™ºô²¥„Ûò ÓEvò¹Å^ùíoiïî¦÷î»!_äÁ·¾•ën½•Çwïæ¼‡æ<Âá³ÎÂu]âñ8s¿õ­’ÔWCaÛv?ß°Në:ðÁšc°’©TŠh4Êi§†ïû$òÑ&:h ¥¥¥£âP(T’ûÖ¯Îf³ýŽI?“É$‰D¢Ðf-úè×}Ñá‹÷QÌ@¢N:.I¿û¤Ý#¼fÚ *Åç¼X×{ ¥LvwwsÉ#p÷#Ðéš;·àà‹Çã´´´‰DHd³…¢Øå¨dFÂHÒjÇq*®Ÿ¢). 4ÅnFÁMsШ4|?ø¼\žK-€¥ÓêúrJ/»v-gåʧ¸è¢çÙ±ãS$“¥×Ö²¬‚‘ë÷ºø’{tJ¶r†¨ëàè×RÔ~üÈdà˜cà8NðFõgY¤ÊX3V‘í ‘$5ĺó ,`öìÙÌš5‹Ý»wãû>ç¤`¾§sQã @üÑOÀ…-…ñ‹€<þø±ðÐJæÿ7þŠ žàÈ‘«}šAAA¨tQjǧ¸vF"<Ï£©©‰x/‘ wñb6}ðƒüdÛ6núÖ·h?çþáóŸç¨[n!‰T4ñ¾/ÙlVùÊl»psê6éRÅQ:­Vkkë þÜ––®½öZ¾úÕ¯˜âÏÊèRŵK T¸)ZôóË0 Âáp!8Aû\uö§b<Ï+µïñ’L&iii)d…êK<'—+2ö¾Üi/¨8(§møûo|ƒ9GŽ`çÞplÛÆQ<ÂCGŽp`þ|><{6pãç?›ï-Ë·mÆ¢‹,Ý×X¡  WÀ®3Åù&û‹•~¦_ÇQ‘)}ÇçœÓÍå—ÿ¹s÷1{öi,_®ŠÖ%Ê¥8kmm%“H$ ç¡o!§¾Ç® ]‡Ê©c™:E¯k×…W_½³ dÇQýX~2‚0ÆLÔ9ÍgÊ~÷Œ|®SÏó˜gªëý~X4pµéýbªÞJ±ÅîܹöÏcvÝ <õÔ•˜¦ÃÁƒÇ"‚ ‚ ‚LªëcTž¶$¯,£µµµ0£ZϪÖ~„bƒŽ^ÑûÐèô7}Éd2±Æu]‰Çãø¾O<¿Ä8`šê^цZÖ×o%Œ…*}ï+Ì›7•vjöìÙ@‘Ÿ@›WH‚9üŸ æ›QÎß¼XFE©A½É×MÁ$p^8VQœ¯.XøE=L“ýŸþ´òCD"üäâ‹éyÇ;xáðaZÛÛ1P¶ÿã-[ÕyÆ4 ÙrÊsþy0!V× I¥Rý"CtéƒÁÒeù¾Ï×¾öµ‚HRÜ=!½o˲ú‰B}'ï÷}–Åb±Â„ûp8\¨E®‹×·¶¶–wq´M8&NÓÒÒR(Ù`Y©TŠt:Ýï˜LÓIJ¬ÂþÂ鱯¬ÅûÒß©#c±XYaÊ4ÍBTMññÌÿóüŸ˜¶‚ŠF‡ˆ¹ÀÎÕ«yõχxøážB޷׿þõ<ðÄe¼?]MÓäÝ=FDzeJYƒv !1–h•®Z…Ñ*µïâæéâõ‘H³Ò0T¨˜8æÍ›GSS¾[<žhmmô¦ÏI±z´·~BIû5>Ø6<úè½X–E©‘2]XºcÐ?bÆ"TŠŸVúõÜ¢e>p𯀠‡ÿñV–/¿sΉñ®w­æÕW_­ö! ‚ ‚ ‚Pe\W9à ¨°¶q!¤©©©ßdÊJ&Äj±COòL&“d2R©±X¬NGϰîììÄqœBTK2™,¤Ç±m»ÄqjÛ6Ñh”T*U˜YÞ×W1>¦©Ê`ë…ñ§ÀƒcQÿÆ—ùú9ç°råÊRÿë!‚Y–:H!‹Tæ*?oìØç£a‚Ô^ð)/(îþWniº×U¢J<®œÚW˜É€çñ©odÎŽd;; uF´OQObÏf³ÃÊÔ7 ¤R*-Ö>žç‹Å >ÖxI&“):ÂDOÀ,N#>Úï¢}0ºP½¦\š]°:•J êLÔuaA9;Ç!•JD }<žç‘L& "®Ý"™7†f üâÂÐ.Ðy>ÌY¶oÀõÜåùI”sVçƒù/`]’_^ì ô}µc“Rç¢ï+gq&£þ‡Ã…Z)‹o¸—7mbóCñꫯj,×=ñ†aj—†A{{û°kVW›bÿ°®ÿ¤K%”œo×%öKíUü,-†a””YÊw=Øçú¹Çyð¬é9·gLÏÛ´T4{PNÛVTGr̬ž7§Ÿ¾O|â…›aþüù\ö¡ñÚ)=U: 0f)¿b±X¿ð¨ñ®©2 ÖæJ#Ñ õW޾“3|ß/•ÓõV´ÎáûÐÝ­–J´Û¶ Jpq>>mÐz†I±²}ûö‰?ÉS?œõoxé%²ˆ 2Õ)®«²sçβë"Ë|¦ÓS¿e 3»fÃ…ó9á„ÿÀ÷%¹­ ‚ ‚ ŠDbpA%N‹ÅˆÅb¸®K(*¤WÛ' GuDI%U‹}<•Ö9îÌt]«EGÂ$“ÉBª±¦¦&<Ï£©© Çq°m»&LG¶hš;I$*ϰ"Œ-Ç™€ sOî¡§·—ËTÂïb—^Áò|(¤9ñóDòéýn$Y4É$¼.£–û¾r,èºÚžunÀü²xSétšµçžË²7½©u¦íßÌš+âñø¸O‚hâ¾>–p8ÜïYå8‘H¤PFÓ·h}1ÚwZivŸ¾Ç=ÜóÐ÷ùÕÙÙI8æ7ÏüfÌÏá¬1ßcã8ªG:¤¸äøã9÷¤“ø=6³fZXn·-_ÎÉCåâ+Z>–˜¦YVÑ›lÊf_úàH~Ã(ŽûÚ“ïû8ŽZ®O—³X´´@*Uyýß´8¤­XPÑ…áôõÚ·o_e;Ê¢¯Ï²WÎáOË—‰@)LVïÜYöG…^Rî~(¤Ì¿÷€ºº:v÷Ìä„W_Cw÷÷˜9óià¬jž ‚ ‚ UFg*,#ŽðJDa#Ji£÷9žèöꉺ%©Âú¶CgäÐ-‘H„t:뺴··—9‡C׌™Jd2ƒgGÆŸ f|ÖS³ÿ—ž² åÔYWê÷¿½x í(ðPZ;ÿ¿ïDꥹ‹례Jk£g~§RêAáy¤‡Ë¾ùM–ïÚÅ·¿ÿ}æ47óö–ÚÛÛ1“Éq<´ 0Úº(CáyÞÑÅÏ Ã0p‡X,V¨ùT zºïûÃ:gžçI¶&Ó4‰D"\xá……L&cÅ´ŠPÑé#O³'.jþãŽ+ÌŠ?çœs ÛèZEËËìϧԡ7žLvae4XÖÀ‘-:MšSôiÒö«eÉde*  ŠÏ}߈€_|±Ú§hRãûÈu³ø‘GDL™&ØÏàÑ D´•ÀU‹ñºsrÌ~ík™7o'§žú<¶Ú‡+‚ ‚ B•ÐuV‡J÷UìˆD"ãîÐKLÓìW¼y¨:¦iâ8‰D¢ ¤hÿJßYÞ:Âeº¹ç ¡— ÊŽøÐùùÓú¯¸å€Ý•¯£RZQ²ûwõÍl§ý{®«¦8 MS9-‹h4JÛd ƒ›¶n%V]»h¼H$V?¥RŠk©D"‘ŠÚ×÷UêûÑ©ÅFšF¬oÛLÓä­o}ë˜ *ÊPikk£««‹µk×ÐÑÑÁ† X½z5ëׯÓÆ5žÛ,8ß q†Qpš_|ñÅý¶ëZÊìOG”Ù¨³ñd:Í(GK d³ý—¹H¡Y÷ýŽ£¶koWËXÏ.Ðá²ÝÝÝÕ>=“žÿž5‹¶·Ãe—U»)ÂPܽF,¶PéP às‹s÷,ð-ØìÛ· Û†‡~¹Ú‡+‚ ‚ BБ)‰DàG-GßóµæÌо³É‹S• ¶M2™$ãº.ñx¼FimmÅq<Ï+Ì.×)ŠÑ"Ëx§(ªÓx^sÕYíw=Cýҥ̚¥\׫ô€µ(§€öõ™ôOqQœo•,UÎBÓTyÕÕ‡!&•¯?¤S_¥Óé‚p<o±Fî_־󱪗2PÛZZZH$CŠÂÃáÌ3ÏäÄOÓ¶V¡rÍ5×°nÝ:ºººèêêâcû Ä”;3«¯¾zX_ÞÑÑAoooɲ®®®‚p3Öø><‡¿5àèG-DßLguV¿íz†Ûéô–;ú3ÖÅÚ-K…\–C;d ƒ‚°’J©g¢ÞζG?»@Sñl ˲¦d •r¶ ãcŸ¿w¡îÁùð_ýUµ[¨¶m(ª Õ}F€8Á3Ú¶ƒçroï)SvFÑDÚ§ Ãc¢Ç¶‚ T†ô‚P»Œ·}º®šh9” 2ÙD”¾ ×IjÛvᘉD¡¾‹ž …H&“…²©Tª °Gª¤Ói’Éñžb\$å×ÄŽm‹ãŸ°üÂ;øèG?J]]]ðÁJ#T TtÊ@ØÀ¯òéŠÒé Å4q]—ïìÚ¥jäïéL&CK‹šRïû>¡P3¿îX:øb<ÅŠÑ2ý-Ë¢µµuRDV$¨tttpÇwð“Ÿü¤…rçw²páB®»î:Ö¯_ϦM›¸óÎ;+6(-Èlݺµ°lóæÍ\qÅlܸ‘+®¸‚Í›7éÁÞŸfÝßý.Éd’X,VrÃ&ý‹ëååв×¥TZp¨R³Û¾F­#U|_Eµø¾š•2çª4†Qø>ß÷§d„J9Û„ñ³Ï3"@ŸAÂô †ÈÔY•¡Øº‹ÖÓ»©«{’ºº'ñ<عsuµsL™hû¡rª1¶ah¤ï„Úe¼í3“ ê«j\×-© #0¦ÛïQ˲tÞF":;;Éf³¤R)Z[[±m»pît{PhýºøÜú¾_pLëÏ4Z¤)ÇXû’FŠž ;™è±­¾#öú°Çƒ÷\Z>ÁvO£"Röç—')Ÿ2(_GhM+§`&£"S<LÏóرt)˜&ŸyË[H§ÓxžWRC©¸®Òt{F£…ÖñÆ4Í ®Æ‚Š•;ææfV¯Smmm\rÉ%¥°¡¡†††Š•k®¹¦ß² 6pÝu×±iÓ&n¼ñF®¹æš1U<_kA´SE“èÚ)Pêǃ”QÅ”Ü Tº™ékR噆1° Òwv»¹.„Bêµï5t†ûì8œÉêPÎ6aüì³kq/öG4 “ƒñš{±zõNŽZú G°`ÁóÕ>Ì1e¢íS„Ê©ÆØV„¡‘¾Sj—‰°O±B£#*´ã?NŠÙÐcMñdÑè›ÆKÏÔÅbÄãqB¡–eaÛvaf:&Çq§PŸ¥©©‰xÞ)£×ë‹ëº„´§žç  3µ]ÄEQ½±íeXbÁ+¯¼BÁ=ëϯ¢D’E`?ÍÀÙâ{Â÷ÕŸç)‡o>½×Û‹Å¥«V‘ɧÅÑ…Ô’(®éŒa5+t8åœø@Å)¿JÞ·µµ±fÍš’e%aXƒ°aÃV¯^]²}[[ .¤¹¹PiÄV¯^M[[Û˜¨ïCs Þnê÷~‰òXÉö}±ó2þèç__ʩĺ@}^tÆ0JC5[Zårç{ßû^,XPíS4&”³M?ûô<ØýËy“>¼Z¨-v¼üF^8á|zLX¶¬£ÚÍ3&Ú>A¨œjŒmAé;¡v™ût]¡Rìt‡ÖÖÖB4E-; k Ã0 ‚J8.‰^I&“ضM6›-¤uÎf³d22™L!e˜Lú *Ñh´ ˜ôRÑBK&“Áu]|ß'ãºn¿Mñx¼0!6 ;â%âºî°£S¦Ò$[¨ÞضøŸ9€w NÚ|`‡P•À3ÀéÀ6TÚ‹r}}LÚA¨S~ÝÝÝø¾_¸§R©¦iþ £GŸÛñŒ<M]ÞÑP‘ ²pá¹óÎ; FÐÛÛKGG .t_ÜyçýB…:::ú‰6 .RéܶmëÖ­t¸Ç…Òø¡‹jõ=ñ‘Hù°¾rýk•>L £¼ ’H$4× êªô]e4¦.Äpíµ×òÀL Ae ÛÔŸÄ>o¿ýv6lØ0àçwy0»îT„1ÃÌËÁcŽá_¿þ¿<üð¹ÕnÒ˜0Öö¹{÷nÖ­['éM„ª°yóf6lØÀ /¼Pí¦Œ ÕÛ Âx±nÝ:n¿ýöj7cL¨ÆØVÆ‹ŽŽÖ­[Ƕm۪ݔ1;ž‰Ûûx”£\MÊt‡d29ígžÓ4 ŽæX,Vx­Ói!Ŷm‰–eœ©¶mÓÞÞ^R¯Åq¢ÑhAÄÈd2D"Ç)Ô¯¨¯¯§¥¥¥ Üd2šššð}Ÿd2‰ã8¸®‹çyD£Q|ß/DÃèÏ€‚°S-îxž‡ã8´´´ š%JgÅ766òÉO~Rƶ Ç¶OvtPA(>ðÔf±»wǾô Bñz`^~Å=À ¨t_å”Џ±˜r(êe–á0'œpB! ¾·2™Ì´SÆ#ºK£³ý„B¡q­S5T Ä† Æel;«’•.¹äÒé4×\s ÍÍͤÓiš›› )½½½lذ†††’´`}éííåꫯæºë®ëÍÒÓÓÓoý¾†ZŽ+V°iÓ¦A×I?ô¡‹ Ì4Í²Ñ Ž£l«ïõÇ{lH¦“1D8\yÈ¥0éõ Cm_| GcljD¢¶úþÏÿá‘G©öé5ƒÙ&ŒÜ>ßùÎwê.•cžÇ…¶`—UûSXòºgyvïkXóŽwð§;'¿Sh<ìsÉ’%Cö‚0^¬]»–†††)1¼Zc[A/6mÚ4%ƒjma¼X½z5›6mš‚ûDŽmóå 8Eµ;S©®ëêoI£üµa”Ã7ËôÎPbYVY¬ŽòÈaª'4ë}èÿÉd² Ò„ÃáÂ:Z` ‡Ãd³Y<Ï+qΦR)"‘MMM†A"‘(ˆ'ŽDò£QÈ¥ñ<¯à0ÕŽp‹òÙ& |´&ʇ”ÉÿwQiß§+¶m8¼U;\ú`FYßP8&ÓÞÞÞoŸÚ«÷©}0ú¿¾†ííí€òñe2™‚ÏFGVø¾_WÂá0‰D¢cšf¡ÆK$! Ò”éè…ãû>†a`šf!í˜N •Éd‡Ã¼ÿýï¯öåª=¶õ=xôê×qú—öðÖS’\fXÏ.X?wÊ rÑ…BÊ!ØÙ©þ Deýéo~SˆŒÒ‘*ÕJUMÆó˜Óé4±XlÀúG“™ŠP3"ÊzY³f ›6m*Iÿ5½½½lܸP†wÇwÐÓÓCsss¿ðÌžžžŠÔÎJ¸¸2od®ëŽË ã"ê5ÕV ]W ž:;•xâyª(}k«*Z¯SUŠ®¹3•È6u^̱¶OxÎå/½TíC¦ÆŠxùƒ ˜û'8xðØj7gL˜hû¡rª5¶ap¤ï„Úe"ìS§/ÆqR}ÃV€(ÊŸc”F¡$Q¿]Å×ÈΖe•­Ÿ`š&‘H¤¬@3Ð$V=1ºolÛ¦¥¥¥_„ŒaxžW‰”J¥H¥Rd2™’¨–¾ûÓBK1Žã¶ÑߋŪq)Æ•ªŽm=xuéV¬XÁ›ž],G€êµ±#¿\”x^ð§SÖ¸n¿ôCÅu“ššš R•Ö×žŠŒç¤qm³ãYC¥˜bÛo*T¢®®®b1¥o˜Íºuë¸êª« Ûk´¹¹™ŽŽººº¸ôÒKG}.ð¯8Ó  >¤žD%¾ô±‹ÇèÏdŠŠÐ ~5±,ÕJ8Ñöäº*B%îþú?\§’À2”m677¹}~5 'áœs¶k«} „)Ä¡3Ïdÿ¼yì°À²2ÀªÝ¤QQ û¡2ª5¶ap¤ï„Úe¢ìÓ4Ÿ(Gjßßõ>ª¶ ´°ŸJLEÖiÏ@ÎêrâÖ`ëÃÀ†eYeýfZÐéëdµm›x<>à6åÚfÆiâ&;µ0¶5k§Ÿ~2¯ý~µ I`¬s€ð$0»h#σLFý׎¿ xRáµaÄãqÂápáë:ÂØbYÙ|ˆ`6;õ*W,¨tuu±qãFººº¨««#‰ŒyHôúõë¹úê«Y³f [·neýúõesjŽ„ÿ/ ¦T¤mÛƒ(Þýg1ÀЂÊxk™“é]ÜÖj×uS4ž§"ûLSE©d2*5X¥”›U1••JkûÜæÃ‡#ÇÌ8®Ú‡&L!,àéN`åSOÁÉ'ãºÓ#êxöŸ‚ Œ±MA¨]Ä>¡v ûli)­¡¢kfh|  ˆ¡D“0PY…DP‘HdسÓGRÇ¢\dPþ©d2ÙoRµŽr)·Ž`(÷Žãô‹\x衇hiiß“YŒgßižG/<ÂܹsY´hnðaø pLþý)}6ö<•Ž&›U©¾Z[Õ_2YRÀu]ÚÛÛ‰Çã…ttÕò[Nuª•B­æ"Ttñ³K.¹„¶¶6>ö±ñ“ŸüdT¡]}‹­]»–ææfºººhhh³°1p3ª3ugÐ jšå‹ŸOA1mZašP­£u¡úJl-¦:ŠÒ÷¥\Á°±¶Ï6„v£»Ú‡+L! àÈÊ•¬8t¨ÚM7&Â>A5¶axHß)µËxاïõq=ÏÃ÷}å87 ’(߬R†™¼B&:¥ÒpIú¥r5’A9W“ÉdY?à@"Ì`L·:9¶5φcëÎ >˜ ø`i×Ñée6Öžó†ÿ­›nâÓáp!LM×ÅÑÏÇqhmmVײ˜‰L5U©HPikk£««‹‡z¨ <Ú¶ÍæÍ›û…ƒ–ñÌ@¬èÙ:ØS—‰é{_µ´@w•ü¾…A •cYÁóU?/‡SKŲ¬’ZwÊ“)rh,+ût…ÑtsÚ}'+hqE?C‡ÞÇt.R5ÖøÀ ¯Æ¿èÿK/_íæ‚ ‚ ‚08Žò­:Žƒçyü¸©‰{,¨ò aDL™.†1`ý†‘D' ¡rúé§{_B)1€ö‹OûQ¡d  ™RtšÍ}û”s¯©IJÖ3©û¤çÇãd2šššpIÞ7£rªQ’¡bAe²â/¹*ÕS4ÅqœAŠp¸|Áò¢…¨Õú"ºY}}ø¢YM,pÐW\ª„±ÆEýH2gŸÑ)‚ ‚ ‚ (l[ýyžGgw7Ïy&_œ7¯Úͦ­­­âÃö;¡þŒƒì]Q?/úlýŠ™€5gN0K:™‚aÐûñ³ÿÍo((¦i’H$ˆ §˜òeªÝ¿Õ:ži!¨¼úЋø¾3dt (á%î¿<¯ö‘L.j5|Ì÷Õ3V ×úvÐÍ­ÑfOI–-?LMu\¨ÐJ0ã섳Ÿªv“AAA˜@‚r ñ8ËÛÚªÝ$Acp>úeϪëÿYL ò('žö)Y„ä‰@sœÒº*®«ò¬º®Z/.©$Œ w»pœáñÆfI÷%Œ-*:TÉo}hGµ›$‚ ‚ Â’ÉYF:ß÷>ÖÞpCµ›$ ìzn»¶ýªžUŸÜ«¢R4§ÔSyúiX¸0QL³_Ê- èÂëz¯LæÆ’Š"T.\Èš5kJ–M†~nþ/×3“ööÖ ù>¡¶q]%`›¦WÜ¢‹æyJh‰Ho^õaÕ²[¥~Š0®„Só›j7CAA„ D×Oñ .?x«Þþöj7I„AØu<¹ æ.ÛÇœ9s°7z>üJTñ#€(uä%J\ … ‹2™ †a`Y---… ßRŸº?µZ®a2PQ„ÊêÕ«k.ò¤âÀª(<ÿšãÁÝqÏ•çÐtç—9€¸Œk dšýS»9NésÙ÷ñE[<µ೟•“+‚ ‚ ‚ Œ–÷}4GN<‘—.…¥K«Ý$A¡g'Ü,.ZB‰*{rzƒ2ðL&È㉔̊¶m×uq]·¥H&ó–gª *Y~bØ5TºººØ¼y36l`Æ lÞ¼™ÞÞÞ =A•âk xî¹ +í2ÍþËAÕÝ ;ÿ}Ñü€$ÐB¿ÚIB à8ꙫŸZ41Mõ™i*q%™¬vK§&3]èîn—‚ ‚ ‚ ˜áûÊ×zëܹüõóÏW»9‚ TÀ¡™¯rèÕC¼úê«<°bAa¹ù2Kú¬lÊY§µ†Qâ´Íd2ضïû¤ó3©#’Ó@¦R*4׸ÜQÃT6lØ€mÛlØ°ŽŽ:::¸æškxûÛßÎÆ'üD …ÖÙzz>ŽeYÝ$¾8Ù‡ƒI»?Ln,‚TÒÀ ¦—¸2‘7òpÑ‚‰e©ÿúù›ÍËgà{AÔí‘ãç$`ÕªWªÝAAAa áºê÷þ¶Å‹yçË/W»9‚ TÀœ“^á5 `ü݃jÁ)@ÌcÁš§Y€uî¹êi–Î|o Ê<º{#J‚¦Ñ×*ÿÜA4r€FJ…ýÚE[Jí¯øÿtP>AAA¦Û_~Ì Â¤á±ÿÃî—â¥gž ”=¨±Qý/K\×¥¥¥…L~†´ïû˜¦Y³>Ial©†pV‘ ÒÖÖFss3«W¯p«®ºŠÞÞ^ÚÚÚ&ü cÿþýX–…mÛEK $¨ UC¥]OEï¦h-Zî¡¢U´O·åÓ&–âÛÁ0”hÂJ×LZ¶y°ê”Ö]Êäÿüü­á:(#²PÓŒüg)”áeóë¸ùåZH 7óòË¢ùÿ.J™¬ªÕ[}ž´pýfz‚ ‚ ‚ L, vDàì_ó}ËÏ(A{<àÀÑXõšçXª©§8UûâûÊyWTÅ0 LÓÄó< ÃÀ0 2™LÍgÍFO,#“ÉLx–¤Y•¬ÔÓÓSÑΚ››+Z¯££ƒžž.\ØO¤éêꢫ«‹††F|`0Ë€={¶ «ðµç©¨„¾‘¡ñ¸ª¯Q)iTº/P¾ÝbŸ­Cð\pòŸõí˜>Ûäø«Ü:Âk‰ ~J:­žËªíê}*¥–•³É©XÔj0Û„±±Ïg=8ª’] eH‚p/%”„óŸ»ù×)‚Ü{}1óëh&…2°¾ëö½eµÚ8À~‡ƒŸÿNº¦ñPB‡?30B é…‘_–È/‹PªÔšù}ésC~›ÖüÿP~xþ}{þÜÚù÷BM3ö)ÂȘˆ±­ ÃGúNA¨]ÆË>?‡ã/Ý˼;Ǽ͒À@˜.L䨶¸ä¯÷sü÷søÕFþ?ýA9E<®„”>‘'žç‰DH§ÓqEê§L à ‹ …H¥Rö½ * .¬HTikk㪫®tk®¹†¶¶6èêꢹ¹™/ùËlÞ¼™ 6°fͶnÝÊúõëû¥gÐuÔÝXÖÇ&ì„‚òM¶R^LÕ>áp~½(*ZEO€÷Š^û¨‰õQ߯“ÿ‹1¸ÿ3”_§Zp8L,«Ò·WNqmœÖÖ Í—Žó<õÚ¶ƒÔ`Z' 'li0˜mÂØÙç ÎÞrÓà+5¢Ä‚êFÖùò(QDWk~ÝrâH_"”*á•¡…Žj–Yn¢ 7šßG˜ ÍX„ /`Š@Mu‹ö•B $Aa¦0ÁCßǺ}&ÐY´/½ŸD¾ íùåÑü÷$óÇ訸NQûm¡‡2ç žoO_8šo»Ž–q*¸NBY&Ê>A>9¶¡r¤ï„Úe<íÓuáªø %Õ0Álß¾½ÚMª1¶}àgÿ¶b³Œ:%¨, ¿oE;ëÊÌvב)Lîžj>»±dªÕ–‰D"8Ž3¡×¼"Aå’K.aÆ …Ô_娰a ƒF©tttpÇwð«_ýŠºº:ººº°m›µkײzõj6lØÀu×]Gss3\qÅ477XñüCvv,«Jμb3´O×B=ìüŸž8¯}Å ”Ÿ8òaêš,ñüçJýÂ>Áäsí‡Î0<ߥ;‚mb2ç)ôý’ÈÁé´zvû~PÌ~ª0”mcfŸOd`ÕþyG0eP¢Eòïõ-Õ÷Py(×HƒŠ,‚‚÷Z8(!+NCæ£Ä‰(AT (a¨»hŸa”ÀD Zx)>-ůõù£Œ½øŠÕX݇¶æÿ· xŸ}ë‘o¯ŽšÑ)ÕÜüÿ8ÁK/×BJ&ßö8H£ÏŒse"íS„á1Ñc[A*CúNA¨]ÆÛ>/NÁKÏ<Ü1n·ÉÀ%`ß¾}Õn¨©Öض÷ÉÙ<ñ†'h¬Ï×G98§hÏSN¹2¾FÏóð}Ã0$*eÓÚÚ:ú ƒŠj¨444pÕUWqõÕW³qãFz{ƒú½½½lذ7²~ýúA÷ÓÕÕÅÚµk©««+ìTJ±¶¶6.\XdV¯^ÍêÕ«G]“å裇¯§PFE€òiÚE¯AùµÏWG°$&´ƒò‡f(M–&˜°®;¿^%Î T’M—Yˆæ·ÕƒŸÀ÷©ÛæÐ¡ËRL•ðWöËuK# õòtZ=˧ƒÙ&0¦ö9Ó…¥Kw ¼‚Žª¨4o]¬ÂõFK%|è”YÕSGhd ¢?Zó¯³ù¿rmÔ¢ œ”¢Ïõ¹i/óy%Â’V[5áü{“@õPBI{þÏΟc-¨dQFŸ PtÞÂd~ÝA^SþsýàÓQB6êá”Ìï£>¿½Ÿ8AÚ2ø6 ˜HûaxTcl+ÂÐHß)µËxÚ§ãÀÓìܹsÌSWžH^&/ÕÛÎ=ñ—q‹ýÅý?üÄ'‚ÙÍehii!«ÜÃtFÎÓØPQ„ PKÒét!¥§§‡ÞÞ^¸îºë¸ä’KÝÇ%—\Â%—\Boo/[·n¥­­Õ«WÓÜÜÌÆû)š .¤««kÐ}îÞ½› 6ôs\à 1èpŸÖ ±íþõS@ÕÚ˜(Ì¢ÿ‘¢ÿI”SOŽoAeõIçÿ²”¦Ó}"ùíB¥'t4 ǵºõì -ª´æ¿¯xB¹—ÿ]ÞÂ(Z®AOt×§Oû[õ52‹öQ,0M$®ˆ&¶ ¦©žÓ®ÔÔI$ÔëDB½×Ñ)6làÁ¬¸~P­2˜m‚š¥0û|ðÁÙ¼ys!Ôê†rúûüZÄEݬ>ÒÙ7Øp¢—*€ ‰Ó€IDATš‰1ø”¨‘…ņx_|<Åb¿t´ÊJþ\è‡Y´]qÛttÕg?Z8Ñ%-éh]&VùùêêêbóæÍìÙ³g'¦¶ûܳg6l ¹¹yÒ?¿ÆÝ©é Åã= A Œ2!ª"ÚÚÚÈd2…j“™‰Û ÂD cÛáma¢ÐcÛÝ»wW»)£f<Ƕ³g_Ê65+™ü‘Âä¡­­\.Ç+¯¼Rí¦ŒšñÛ®]»¶ßöz¢ø« ÷³?×ËâîejÁ‚¢•,Pùú-K9ìú`Ûö¤(9P+L7AeóæÍã2¶­XP%ªD"ÚÚÚØºu+@ÁÓÕÕUñ¿®®.6nÜHWWWA„)W£¥’±c=¶ìI¹; Ïg»™ð‚a×í_€Þq ™^Qú‘Ð×\ü8è["B :c®Ù¢koCH“%˜HGù% Ñ‚‰æ5 ß'HEæç—YþM=±Ü/Ú·®ùR,˜Äóû´&·ë”gzÒúD¢”bÍ4•xÒ7’Ðó ©)X‹©ûÇŽ•aSÎ6aäö¹|ùrÖ¬YSxïKQùKrê0)Àq?Òô\ãM±°¡b"¨†Ú8:· ~@ôœé{~ŠÓ¤£Å)­ªê{ÔC¤à¡¡?3è41=sf*åKûœ;w®¤5ѵ}†²-=3A§³ë»B5'âyPœVo’ÒÐÐÀêÕ«yî¹çªÝ”1c"ƶ‚0ÈØvpúŽma¢ÐcÛx ÚM3Æcl»mÛ °vüâXúPµQ˜&444°xñbŽ>úèj7e̱íÂ… û}¦ý ‹/:ÌÙ·á‘7樔_šSNÿX¥)rÞ9NÆ"NKÍ”a’L&qgÌ£ùj5kÖpÿý÷ù~+JùUL]]—\r ëׯgýúõ…|ÚØ*aõêÕlÚ´‰Ÿüä'ÜyçlÞ¼¹¬a ¥rÌŸ?¿ìζü¸žeË– ëøªUúCG– '“”M5RI³‹×ÑQ,ºÖ´Fû3õŸn›S´½^'R´}qÆŸ¾þSíûIdr‚ ³Mõ&õ†º‹#ÓéRÅ÷•ÒÚª–G677³|ùò*µ~ì)g›Àˆísùòå…<¸ îƒòÉ’:;úæ/¾jõ™®E*6Ñ‘#£=)‚k¯Ó©i…X‹4ÁÃD+·éwYw¸ŽææfæÎ[í³4fŒ¥}NkA%Dm’d=-ž º“Ö5’´¨häÿÜ>Ûçsuú4¥©ì†ƒÎÁ™fÒ§Àkhhàu¯{Ý”úÑ9c[A˜dl;8}Ƕ‚0QÔÕ©±íüùó«Ý”1c<ƶøÃñ…z ‚0hAeÖ¬aÍY¯iÆcl;`tº¹ísY¾|9sÞX¦ú‘öëöqØú¾—ÏÇŸïðS ß÷I§ÓÓâY¹zõêqÛ[P ›7o.]êêêX½z5]]]…ÿÅôôôŒØÙ³Ë…¹ ^eåʧ†½mßô^¦ ã-tŽäö ¢N†ئ}AÃÑ,”O¨Xxi¥4úE‹.zÒx±0ä è I:ÂE×z1 ”é‰Ìôäû*©o*FËR(–¥"S £zbÛD0˜mcfŸ>Я ÕùçRˆ@1I0zñKçþÓEšLÔýÐ’οŽçÿš Ki‡v’A—ÉÄDÙç˜ÐW ðr?Æ ÄÓbeJ¯]œ‘áý5íßÏ_´è»ôò¾ù)õ}ã/±üû(ê¾sÁ= ŽÕtp¶Ú§ç)%z%8_…è{¡¥¢Q%ØrcêðÏ‚¨ôg(ÆPms{Õrïï!úÈ|·üæñøøÖ„9¶¡r&Uß)ÓŒñ´OÓ„y2I]FLUƶ쟹¿ÔÉXÌe—Agg{•õ$NãyÞ”°lÛ&•JÑÙÙY:ÙY¨˜ T@§.jßÛÛ[ÈÙÜÜ\(r*ofWW—^z鈾g`œ¸sD¹áŠ‹Ž'“Ö=†ÛÚáN’/.*E?Ó†21þ+ïS*|þNÙÒMi™½oíWk"¨I=Þ†Š,¾MtêEÛ„”¾‚ÚDÞÅ@¶ Œ™}nË_äÃ/йëhar2–¹úR©Þʉ!Ôƒ"L&¬8¿ O0û?艋ª}†Æ„‰°ÏQS|þ5:JC‡)jqC__-ZhQB^ }C:“ù¿bu^?cŠ¿3B Þ9ùÏ“Eï]ðö&øÿ™ŸCÓ º2K ñBˆÞõÿéÇ y!¸7¿ 27BËÛÀÿXÛÁ½ÂO«ñ¿ù[0àï€ø¡e78õ½’ïUâ~± å šþ €óVHÏôAÓ× å „nð™ÿ'ȼZaÆ ðbj £k ãÏDmA“¢ï„iÊxÙ§iÂK Lùׂ0žLøØÖ€ÙË_-Ÿ²§·n»­ðÖó<|ßÇ4MR©TAT†G"‘!j”Lh<ÚÚµk¹óÎ;¹âŠ+hhh`ëÖ­\z饅¢~ëׯçꫯfÍš5lݺ•õë׸`é! tÖ]#T|B!H¥ò¦–=Ãð#TÚ+X¯oÚ.]t¾8*F_¾ÁFÑ6AЂŽhií³ß±ÒO-«DäVç'ˆ*…öå×Ñ)§Úsg(Û„±±Ï'Ç¥ÿEÈ8IAÆë/þÈ .xŸã ¿¬%ù%Än€ÔgÀÊç°´žóëàžÖ*¥ ùï†Ì ÀÈþ˜Ïß&˜QЉwCÜgO€o‚o¤“t ›SýPz„?±/ª1H<öeêPÝfhÍ‹ÿ^¸ ©+ }3x[À> ¼à˜*:&V‹ÛDjµNÕ$c"Ƕ‚ TNÍ÷‚0Oût˜÷†—eƵ Œ‰Û:>,^=:‚åÚM—zôQÌßþVE©ñxœH$‚ã8†A*•švEÖ…Ú "A¥­­­ @„V/‡bÓ¦MtttŠCÃÖ®][(pß÷³á²Ç…•‘§€•ÃÞ¶µU93’IåpŸ(1%3ú] Iq$Èx¢'Åê´ò*2ESîq§}aú\´¢Uzjòsß}–d2(Nê¿ë¢I&aÂau/˜¦J¥2ÕR4f›06ö¹À‚4áðžD6xŒB&L "”½ÓyÃF©°aÀ߬ü ïäÕ>¢Q3ö9bt§¢E%|”ŠdZ8 ÔÂi¥T\ÑáZU‡@IíÇ%(ÒEÑzº¶ŽÞ&/Òd‚7ÌŸ@úy  ’uÐú}0O‡Ä{ÀiƒèÆ|¿ÿgHî†ìýÓ=šù÷Ö7Õ÷e;Õûp2ÿ æÍ”ŠÄº6D,%n¤Žÿˆ^£{°ƒ?Oµ×0 ²Â_Ìï€övå$°ì>f`ªÃL<¬Þ¶œ î¯!öHþŒ[¡õÇà>©>…‚þÌ÷¡±1A#¿CFÌDmA5Ýw Â4g<íóÕW_­öá ¤fÂǶ>>_[ñTõOÿÞ1÷í+YÕ0 ,ËÂ4M à  ‡ED&œŠ•®®.:::†\¯Òšƒò ƒôÕ)pÓ.‘NÁ ‡ƒ4OÑhÿ(†±Fû'â 'ëŽ'ÅÇaRÙqéz¾z]f”,Uô¹.³0˜fàhÒ¨©ÊPE6GkŸ;ðùuŸ·¿Þ7AÐ t_ ͤõ Àƒç¿ò|µfÌoû1ªÓ‹ƒ´òŸé‡ºêè¢ùeZtÑ)Ûôû¯ëœø©»üü:Qa6 ñ¯€ôg!õ:pOÌÇ,€y/´& ݱf°Þjr!ôFˆ¼ü—!ü ÿÃÇíSÒ¹YXŸ¤¼˜¥ |d³êXÂs yS^ÀyRÔ·©ýz·uVÿÝTÙzx?óƒ`,ëG`Õ%ÒÂaU7.“ R` #c¼Ç¶‚ ŒŒší;AûlÃÿàcÉŒ=A:¶uáØ«À?÷É&žÉ¨¿>3¿’É$¾ï‰Dhmm•BU¨HPY»vmIøe­ãÇæC$Æ"ô+ž:ÉuF•Ähw4èI¼‚IÇzbs¢Å%FûìÆ2 ”^oË žß:ØTUÆ“.¬˜{˜î׎eŒ‘ a´ÁnìÑ$}‹`iÁ#L tD(Uï-‚(-¶Ø¨k–OÉU’ú+¿ÿŸàœá8¸ï¾ –î Bj;ÿëÙV7ľ 1qèAì E“".Së'?Ýß,jšÝÕk×­°Ï×!˜Å 4[Á쿞…Š:1Mh9OíËEg+˜á52ÀÌ‹Aæþà³ùÏZ a«s×øàï†ÖŸ©È—ÌÔõiiQ‘ºž§D—D~ÀàûSg,$‚ ÂÔäKq˜ûá}'ŠƒU& ><õæcú/w]õC¥5(`F!å—eYÄãq‰PªBE‚Joo/]]]CÎ ¨<`— 3Ǩ0ÑTª—¡'óN„Ÿ1Càoªôûtª¯âG¡žÀ\O0qYg‹À§–ed¢J_1;î¿LR¡Œ 8ríf¿`raµ›#ÂpqPQ&ºŽM¥5m´à¢……¾ÏÎÔƒ<þ¹ý$,5Nö~‰ÃàÚ`lÿÓ`ì# ñzà3¼¼£Àr!›€bg)çØ œÿš~ãê|»ÚÛŽ<ÕÛ¸®;øÀ܆½³÷òœ÷܈'oX–-¬÷ªóËŸ?s+¯ýå*üöÐç%‚¼b>[Õƒ!¶É6p?n¼¿‡h>•™ï+‘Å4U{uô®žX0•ÆH‚ ‚ L~ŽY²8ªÚÍ¡R|èY4³ÿrý¤è‡a…Bô‘H„D¢§‹ Ó™•¬”N§Ù°aCɲ 6ÐÕÕUíö—ÅÞöæ“J¡ÔM&bÅDh:Š$?¶¢ãÒ)¾Ê]5=YOJÖ)öu¤ \ƒf¨Ú4Ùl©C¨oÊ“D¢¿ âºê/Ÿ€“9Eð€i8ážKy{÷Û«ÝAF‚KP#EG“c­ªð»›2)‰èK€V©4CW±Òiõ¹^‰ã¡¯B(þÞõ{à¼óz‰^£‚înõÜŽ¦ÁõÁÙ ÖŸKŸÝÞ *”PÒ¹ïû8Žƒçy$“IB¡PÙýyž‡ëº`ÀWïÿ*Ñh×u …BÄ‹:½_t2™ ---8ŽC2™Äqž~úi,K­¿cÇo!æ—Æ8¤Õq&Qs·Cø ”È’ï%ÈüŒ#̪H–pXEÙ·FT¡{q*‘%™Tÿ%jSA„Z سgϤò Ât%$}hø~®ÿ‡®«~àõL2™ ‘HD Ñ U§"A¥7n¬IAÅî÷ nÏ–Ie`&j’o¬Ú C´Ŧ²c 7Èç ”¨¢S|õ­E¬3ÄÔ÷ù,JP븜‹m¤¢ˆïCah<`‘ÝÝÝäÎÉz‚ L Áƒ4ŒSÔ÷ž¡î™L <ÇãpÏ=]*2ÅW"v*¥þ‰ õU"÷B6 ö—Õûdr /¼ðÞÂ:šT*Ÿšj'´œ™L’t:ã8466–ˆß÷ …Bd2âñ8…¼¡PÇq ÿmÛ.ì«©© ß÷‰Çã´´´L&illÄ÷}\×¥¥¥…D"QX'ÒÒÒBSSD£QÒé4ñxÛ¶‰Ç㸮K:æ/ù?úÑ×…BÜ~û±|ë[;ˆF£1&ÓÔÔD&“!“É”ˆ=áy^ æè4j:O¦Nµ–¢0[Á>œ…`2»ÇÀœéÿΣ™‘ËTdO*©ÄBà? ÉϨkÜØ¨®»Pè´ÓÚ}_ýO&û‹`åÞËGA˜l¼ ÔoÙ"5a²à‚ñÙ2þ¡–õ¿8šJ¥ˆÇã"š U§¢”_“ höàþûçó•¯HŠja¡&ÂŽ%Åò˜GS¼,CÊ_ûùt4‹ö ôwFZ„×q$ØpÙãÁïN¿Ž¯~ü§ÕnŠ Ã! î)`y¨üŠ” yL§ƒ‰D--J,ij‚o{ë×?ÊãŸQHEÇI$¸®‹çyضM(¢½½½ ˆ†ã8ùBê*G®#.¾øXJ:Æ0 LÓ¤µµµ Žha” ¢ €öövB¡®ëbÛ6‰D¢6žN§ B‰çy¤Ói2™ ííí†Q^º»ƒšP‰D‚P(„a´·¹ÐÈf³˜¦I¤OÇǹøâŸþô>öíSÿ›šš Ç›H$ˆF£…÷ñxœX,VÖa #fZ[[±m;¨Q£CFËô{á2A‘zëSàÿ3ø{ÁzØŸAÍPˆ«ß5VZÝ v¼_ƒ÷ojy2LTÈf¥Ÿ¬Ž“¯‹“Qö ©h#Ç „“–%ŽÙ¶²Y+Ÿ2/Uëz^`ËáðèÚ#‚ Å xé[ÏV»Â4åÅ_¬v&W> [g•™ëoYýŠ[êÉk–e•d„j0åÍž={€c«ÝŒiËxKY&¨â-Ë ¢|Ò©ÁtÍÒƒ3Gv6•£O×—Ú>]í¦‚0\|HÞÖ E‘” Ê *¦ ¡Ð®»n.©Ô\ C9e[Z®æ¿ÿûÛÜx£ZO§ÖÒÅ}ß'‰àº.„Ãa<ÏË‹)f!:#“‡Ã8ŽÃ[ßú$o}ë“8Ž à „‡L&C"‘(™Å”N§ ‡Ã†Akk+étº_þÝH$‚mÛ˜¦‰ã8´´´‰D †eYýR‹†A*•ê'rtvvzzõwG£AQšp8L*•¢±±Ã0°m˲p‡D"ã8*õX¾-Åß™ÉdúGé¶R+ƒãO=–¯/ÓF+ÐÖ…¨Î´Õ‘š¨!x`þ7˜ùŽÖû+ˆìïò`ßÅÎya|(¤Î‹(!%S¯ C‰*šrcËRëµ´¨×ѨŠþÊfÕµ …ÔçžÔåñ<%Ƹnu¦Ñ÷’LA&šÇã°Øk«v3„iJñD+¡2.0à¨7Àý}?0Í~‚ ¨ßMÉd²ß5A˜h¦œ ¢ëû÷ïǶ/Õ¾„‘cd,QÅ%ðé9¨¢öi”ŸÔÄ\é¤8{…¾WþöÞ=<’²Jüÿ ·nj¸3dÁ —¨ˆ§£à]´3®W\¥{Ýïê ¿Y»WW×˺vˬʺ‹Û »xÙ “^/¸*£ÝŠ DŲ:(¤ÂÀ€š†˜úýQ}ª«;¤“t§«3çóß0t[–åRd ~™ðÜ4ÍÉÉ Ëq’ÌòöX,x°—¼èELÜtSõyŽã_Ob-¥R~à ~ȆÙqêºn¬Xá{݈‡ŠÔO 7bXJ$8Žƒã8¤ÓéÀxâº.ÃÃÃ8Ž‚b±X%áXnêçlY~•LÓW¤“òàÕzà‹âv¶†Q éêËÙqÀ£ÏpÏò{8žãÛ]EQÄq|ï”Ô9Ôý¨g³¾5óW¯[ôöúŠüB¡@*•Âu]ÞþêW3±q#O~þóôww~¬OèCd, Òin¿ýv¿ÐtL3çöýˆ§_ÿzŽËåˆÇýŒöÀþ~.yòI~ar×]üùO~?îkqÃ+™l»²t_nÈ0üI*!ÖËò·‰v8´Âƒ²4 PàÂl–—=þxµqD–øÛvÅ@’WX–ÿ#I-jµÍ®Ë!Ï> ÀYg}Ãð÷›¦ÉaÏ<®[å‰bF`\1 #Ø.Þ>©T*u&yR¦ë”Þ †¬Š˜©sBÇÔ¬¢ˆÅ!ûf ï¿é4XÏAá^?ïÊ[]Y×ÃIiÛö_9ÉCÔ,jCRËÿÓ…ªWL³²èD¾ à{º¸®ogÔ0bŠ¢(J+8ñ=ÏÁ7Û] e_ä´ÓNcÛ¶mí®FÇqÏ]pâëŸb’A%«v†ò"½:‹á¥ 4””¾»»›îîn¶nÝüôõõ1::ZµmëÖ­í¾ÖÅ¡«ë_+Is•¶ÐJ=I Q¬[³-<×7¨$±—„ô1*¯„äZé-ÿž-²"[iœ[þw Þó4!½¢t ¥²îÿˆ_ ˺v‘ÍVgȺþúǸ÷Þ{Ù¾ý.úûW ÜmÛ®ÊMò®w½‹½?Î3gŸÍH.ÇÈȦapÝÎÍ«iúKÛãñŠÆÕ4YÚ×G\Œ©”L"Á3Ÿþ4®ë²í¸ãøùüG%‰‡¬Z*•üÿÃKöEÓ ÃJ©TI|(Y×§¨».ärì÷¹ÏU†€¿Ä?÷§R•:„µÊ±XŃEê™ÏCo/+wíÂq`ëðg±Ê / ÃàŠ§Ÿ†|˲øøqÇA2„[¹};©TÊ÷òI$&­Ú²m›‚S¨›7eZRÌ|Ž$»¯‡œâ“½ Œ{ öZ~ Øß…co8¶oè>‰„áð_­(' ÿÕv_<ŠEßÈ#uííõ·år¾ÈˆqÅu5„ª¢(ŠÒ\üH%­ôPQ”©8üðÃÛ]…ŽÃv€Cw4v|ÙCEQ¢@C*ëÖ­cݺuí®kÃ|zF5Ýûá*õõÄ2¤Š¢ ´ñuE¾í-N%çÊLd2•EÇJc8À‘Çïá—Ïÿ%ra»«³ÏbÛvU. E™ú_æ»!Uö>H&oçßþí¤R¾=Àuá oø¾ùÍ›øö·'(‹ VìØA®XdÍÓOc AB…—þìg˜+ó©Tõ꣰w‡û†1ºÈrüP²y`²¤PðTÄ !È9¶]q;”ßá}ïhd¤RžeU×]²| õB{I\$‰Ñ$ÛáÅOâ8pðSKýëõöòþ/|ƒ‹EH$0 ƒ+^÷ºàŽãðÞPx0€÷Ÿq?ü0'ÝsOCƯªU¥`Èf³A^–9c1mÒ4Ç’æ9`œÉ†12„aF`÷Ü/½/#6¿(ê‹jE0¯„’ÿÕ—×Þq*c)1´Èq¶ío“û¿ØZ]×?Fr¹ÈoEQeßÅžøö/nM‰]‚¢(óçŽ?V<½Âߎ<Å@W ¦JThÈC¥“¸¯çÅàÍG¼¹Ó[Y´XøŠúFÔArœú?ƒ¿×Á÷RÀ7®äü<,圻U”J•Õ»v-kw3t.ð!îî(•ðJüvÅét]7PçËŒR©äŽ(•J¸®K¡P˜´ZC¶ z{{Éf³$“É œV´U>Ÿ'›ÍVÕ»P(ɳk‘¤ãJôp pŽc Òü꫟elì<Þÿûg¹¡ß:ûlv}ñ¬?ç$ÒÇGê‡?äÃGiš|ô…/¬Šh‰"ŠÇY«-•&o‹Å*‰ ëÕUr—ÔRÏÓD *â‘R©ÜÔa¾1¥Þ~ºØ¢ù®E2~ å¤Ý«þË‚?3Ê^5##¬|ÝëX±cGu" Ëòs£\pAÅ@亼ylŒ—ïÝË©7ÝÄk~ö3,Ë"“ɰñÏþÌ?®¿ŸÝW\A6›åþ~40JùEW·ïÀÀ@°­î70ô•L¦l§ZQnâ8ä¿ wíDNºç$”Ù!Dm‚z1°ˆqex¸òw,æÿ=<ì‹\2Y1¼ˆ]µ··bß”×2›õE:öÏj¾ØÓ¿·íúÇëâEQ”ÎàIzî¹vWCQ”yÖ…µp÷²»ý ªêλlÛÂ+J»™URú7211Á§>õ)6nÜÈ5×\Sµ¿»»»!ÅØèè(£££ôõõÕÝ'aÆfËv >dÂæ?{Â7¦H6reQ3Ó'Ur§@%™}øó,QK$׊‹oh‘5̵ÇCE·çº‹'lÉt²Þ?ù|Æ…ÿ¼ë,þÖk÷m ›eõ¶$·Îd2äóy\×%‘HP(ˆÇãô÷÷cš&Űt×v˹zzz¦T*aÛ6™L†žžCH,#ŸÏ+ÿ%„’$ó–< 2¸_r¹¶m›¦I*•b``Ã0°m;$ﮡ··—L&ƒišô÷÷“Ëå(•JA²ëR©D<Œ:’Ë!™LmœH$p]7hwðó<ÈŠùR©„a“®/÷$嘦Y5€Ú×¼mZ)ŸU”íˆÎO!¾ãɧ:a7¿x¼Ÿ¯—à‘£`ë9ÿÀÃýïà´cŽák^È‘¿þ5Ùo~ãä“yõOÊ©Ÿÿ<Ù·¿½’ȾFFêo¯‚ë”#dÅ5×`ŸwÞì×Åâô”ZLÓ÷¤™í^BŠ5ÈO¿ Û†Á%ü½ÔÏqª=v$L™“ßû^_‹\öŽ9qhˆ\—ƒ LÓ$³ÿ¿ý_}Ç;8ÿÚkù¿ÿ÷ÿˆ½ò•\ðƒpým·ñ–r¾g`€ç®¾šóß÷>ü"|¹. ¸®K.7»ÄtâA ‹ÌlˆƒU€/­_FßÁ&ˆVÕZ9¶$½Ø#áW=•ªŽ”'û]w²3X±XyßÀ7®Hª¢|¾â,æ8¾=s`Àÿ?ìq,öÏÞ^ß S(TD+•ªöš‘2åÝCW8º_6ë—‹ùFžx¼r|2é—é8²ä'=¹—LÆ?F"J{”Jþ1áz¸n¥ åXè8ë‰qK®iÛ'>©¯ë‰'.žÅB Öw*“Å53­&çD— ybÊ8PŽqÇq‚cÜrxLù;_‘)cÌD"mÛ¸®œW …`a†Œ‰ãñx0®•놯!c×X,VUv6›Å -z·…Ì1äú©T*8GújðÇȉDÓ4ƒT‰D"({1Ñlùü½ {öìi÷m)Ê¢`!ƶ»ˆÃà3e¹f«,òR%*4lPùøÇ?Î7ÞH"6£¯¯O}êSlÚ´‰Í›7sÕUWÍXÎÆÙ´ikÖ¬att”åË—ó•¯|…åË—³iÓ&6nÜÈš5kزe 6l˜u¨±'løælgïOúñœòTb€«qeÑaÐxšÖÆñ=Qj *üŶq*š“½S™Ü.¦“M`Þòù„ Ë»v,ø}¹¡¥¥ù|žT*E:&•J2Çq( QA&€±XŒt:M.— Œõ”¶aCAøº†aׂTĸ‘L&‰ÇãU×CB*• ê$FÙ'õ¨°•J¥*Jx‚&HrmÛ¶Éf³qÅ0Œ`â™H$Èçó @1êÈDѶmŠÅbp?á  \S&ÀŽãL&I$$Ëù à ›Í’ËåH§Ó8ŽÃððp0É•Dá•(¶mœR©Äààà>±J¥ÕòYE9á”ý9 Ì€XD¶[¼ò}|âïŸÁŒÙ<ýŽwpòOÊ o}+îÒ¥˜§œBïÉ'`_1*I›ÝtÓù¬]ûlÓže»Xо3â„Ǫ®ë’Ífƒ/n–Œ½dÌgšfðMÈd2ô—ÝäLÓ ÿÈ‚»†Œ¯‹Å"A9¹\.øVd³ÙÀP €ááaz{{1M3ð4 £ª¬t:M¬¼ “J¥èïïÆÔ@°i`` j1’Üóàà Ùl–x<^õ[ÆðrŽ$A–1¹xˆËß0Œ`Ì,å×û~Æb±`áV0¶–ã³Ùl0fN¥RÁ¸·¿¿?§_pÁí~šB«äóàS'&ÍE™ 5¶Û ÃãÌç?Ê ðį]^—N§ƒoý¾0÷W:¯¶lÙâ­ZµÊÛ²eK°íÊ+¯ô.»ì²àÿ|>ï½ñoœ¶œx`R9k×®õòù¼çyž×ÛÛëÝzë­U×|à¦-3\Ïó¼“Sž·nݼŸ¼è'žWôõ©/ïm§2“lzÞìåóÖ[oõ®¼òÊàŠž÷ÂcoòŠÅbc•Êå<ϲüƆ‡ýŸZ†‡=Ï0êîK¥R^.—󆇇=˲¼ááa/—Ëyƒƒƒ^*•ò½X,挌x¹\΋Åb^*•ò ÃðŠÅ¢722”“M&½/¼úÕž72âÅãqoxxØËd2^&“©ºf,óLÓôR©”—H$¼L&ãÅãq/•JyÅb1¨ƒçy^±XôÆÆÆ¼‘‘‘)ÛfddÄK¥yÓçN±Xô‰D¹é+íÓ ¤MåZÂàà 766æÅãñªc‰„‹Å¼ááaoxxØ Ú<{ƒƒƒ^.—óÆÆ&àkûˆN¤ò9m»Œxžgz^êEñKyž7ìyÞ‘_ýŽwÀ1OxËÎ|Êzá ½×Ýy§wí?þcÕéÃ^¥û5Êÿ[埸çy‰ÐöÚoñ\°W¬ð®9å”z­å¼ó>ì}ík?óV¬°›Rž|Û„L&ã†áË].ç}å¸ã<Ó4½b±èY–åe2ï©eËï¼Y_?—«ÿÉö<Ï[yün/ŸÎÏ®À²c[ÏóÛ²ü‰ž™LÆô†ë<éór¹œx¦iz–ey–ey¦iz†aÿ†á¥R©àG¾ÉµÇËû–Ëå‚>Öó¼ ?-‹UßýN$Üåy^<îyåÛôR)ÿYMÅà`E&ä÷Xç&Å¢_n<^=| 32âÿLÅØ˜ç¥ÓyÛÖ¡vlÛ.FFFêŽyÂd2ð½b±Èw,óâñ¸gš¦—ÉdªÆ«©TÊ‹Çã^"‘ðâñx0~5 Ã3MÓ‹Åb^±Xôb1V%ßù–È8;߇Ë9ÅbÑ3 Ã3 Ãó,ËòÆÆÆ‚câñx0f–q©|¿¤~–eeÅb1/‘H}™Œ]ÇÆÆ‚ï_<®/åÈø_¾Ua¤ŽáíòÝ çGFF< (ò,/•JycccA;ÈyrNis¹WÃ0¼X,æçÈ74|Î+^ñŠv¿‚ó¦UcÛoyÞ¹ÿõ‹Æç›s 6ÿ"”EÊ¿øE.jw5æÍBm=ÏóNNxÞÍG<éýÅÕ_ñbããþ ªŽBt/­Ö‰(‹—+¯¼²écÛ†ø!ýË`…~ǘ›×JÌóˆ¿üå¼wÁžHë¸dÌãÉ'ä‰'žhJy®O<³ëè~”ÄÎ ½eY|rýz2™ Ã¥’ÿmt]øÂ¸&™ô£ÁõôøßßbqFW‰éœzÿÇfhh¼ÝM>obl ¾wBªÁØy¾¦PùfÛ6¥R‰b±x ööö‹Å¯ÁL&C, Þñ ”¾SV´‡WýJHYYžÏçI§ÓÁ*s §)«¼Å Æ0Œ`…»”ǃð—âUÂÏÁ0ü0_ÂLÝfxX#Þ4ͼUy<ƒƒS3S¤ Ào|ãXÖãÍ«XXð¾³Hž¹D"Aooovq œLBÈŠÇ0ø"ÿ###gÃàà`àuX*•’zcÌþþþ`œ c,ù[1—eYʹ¼,Ëbpp0ƒU*•ª¼×b±cccäóùà> à ‘HßÉõ'ß97“Éß.)Kþî¯I.%žÞ@à!-ÈýæóùÀƒ%Œ|ÃcJ9gÅŠAY¦iây^ð,òù|à#í çÔã[–E2™ ¾£‰D"¸Wñú«­›eYüüç?oÃÛØ\Z%Ÿß³á‘ïžïþ]»oQQ:–…Ûór¸ (›ŽZ >:åäAƨ‹-ì¡ÒÙÌ*‡J˜uëÖ111Qµ­»»;èëÑ××W{obb‚Í›7sùå—³uëÖI±÷ººº‚˜}SñÈ#°qãF6lØÀîgaÕWñŸ¯¿Ž÷ï÷µ3’#¯1ïÅ×ÜÔNzòTÇ{ S•Q€Ù„W¢ÀtóU“©óêÖûd›&<ìq¸í3Ïîi÷íÍ‹éd˜³|ÞvÛmlÚ´‰uëÖqø©ÐsÜ€²òUuK`ýR)0Œà8¾¦¡V{48è+óÒiߨâºP*ñÕ÷¿Ÿw]qŸM§ýIe"Áß-[ÆO—.åпý[]¹’äƒ262RÓ¶1«ìö(pÊa$Q4ÀÅ"¹ýö£ÿóŸ'›Í’*+©\×eE2ÉÁ·Þê">ô!óóÄ$ ÿz‰Ø6_zä‘ÉÙmK¥J‰ã!d³þõe2%ÁÒÅPŽý!ôôTB•JÕƒ‰MR;PI&‰årÄÊ“Åx4dPéêêšd(©¢‰‰ ¶nÝÚð…7oÞ(sÖ­[ÇÆ'ÓHr£C=´ªQÌ—@צÇ9liYi›ÂO°kák…²øF‘z“Ò,¾2É*ÿ¸øšÉÅ"e”¨d/ãkTrµì{s¯ÈcúÇbRÿ•°¨W®\Éš5k¸?'-Ù[Ù™ÏûÊ} PžËU œ¼¹\Å R^ú©žV–¯“J¥H—JðªWá8Ÿ+•xÛÉ'ó6ÉšÏû†™lÖÿ‘l³a$³k2é+ËuI–J`šÁ ÁºJÜÚ ˜=j‡¯%ÁÑ%à9øÖ%¸y±èÿ-h¥ÜzÊË‘¿Þ½½õëRžœWD$c®xþ$“œWžÐç¥R~›¤R•ìºa/¡|ÞoÛþ5 £r¿ ~ÊySd5_AxX–Åðð0¥R‰¯ý댌ŒðÃþpVeDfÉç²eËèëë›|œÿA´áÜ8|xùsÏqÎm·qÖÉ'“Ú»—Ò™g²ëïlÚ=‰¤ñ¿¯1ü.×Áÿöf˜lwÊUCk½·ÚÄ‹–nkI¹õr*‰"'ìÏç+ÊŸpûFå›—³Ì—Éf+Éjd^’ÛËD¨»»›Õ«Wó裶»©›J«Æ¶ád赸®K:<0‰Ä$Ï$ðŸ³ôYµÊ»ÜT…Ï@íÊi1ÄL¥ ­G=E¢x²ˆq(¬¼, '‹088ˆeYAÎ)C~Âm‘ÉdªP˱¦iVåŠH§Óus ˆò5œSMÎÍçóU†I¹®°ä1`Ês 1ÅcG¼|Â+ÿňÎ'!ß?1þ„^K$w›Üs8w, ò¤É}Üxã,Y²„Êè·óiÕØ¶ …*o²°tdd„R©D¡P`pp0È–±°qÄqœÀSE°Z$]=U8{íö©˜jÕ°ÜW½œâ)^ïœl6[Öì›êúõ 0ý7N¼éfÃTù¢fZ9]Û~² ¨Þyõ«‹×¾öµ|ë[ßšU}£N3Ƕ«^ÞÅS·ÿ–õ·í¾-e£»»›“O>™Ç{¬ÝUi*ÍÛvuuMÚwÊöýpw> /?¯î¹fHÿ¢(saÍš5üâ¿hz¹ T.¾øb6nÜÈæÍ›¹øâ‹ë“ÏçY¾|ùŒŸ‰‰ Ö¯_Ïèè(ŸúÔ§‚ãë Öèèè´aÆ;ì°ªk½£e,%Z—Tùw©üw?0ÚÇW"™åÿÓTâD9@ŽŠF>‡¯Y—÷ɸµ¿|ŒS¾†b blQÚÆL•zCiÿ1Ê?’T¹eÁË{>ý '<ÛÙ!¿`jÙ„¹ËçÊ•+Y½z5%`Ù³0rhݹU¸ å ™L0S©T~KVÆŠ›ÿ¤‰_,V &Yba²â^ê‹ùÆX¬9õŒD’©9«6‚È„8›õë^ >¹\}í›aøÛûû}ãŒLTãqÿ:Òbè žìÕNpË8” NÄbþßÓÇ‘ÐA‚Ü»”UNJÔÅuý¶v˜Âè"“öïÿûŒÍÆ×!º4[>Å 2 ÜãýÇòŠ x×^Ë ã㬿à([¶:HÂ1Úø¡ÁÄs°—Êw¸lë "zƨ[Ä‘üouŽJ±pW_ â°Z‹C%2h»"„>üðÁü|Ïëùû•_« ªõaæ‹YÖÌ1Vš…aøÞ%µ$Í °nš¾q&|_¦Yý,ŠÅÙß·eùFL¦bT©ôô÷W{Õ»ßtÚ/ËuƒÐiù¼¿_ 8½½þu¤ÌlÖWâš&ôöòwË–ñÞ“Nj^Ûµ‘VËg@ ì;ý­ |ÿÓŸ&û£ñÂ'ž¨´m‹±ð×;b)R1¨äñ¿Ç½åíNy›|³ø]w©üã–÷õ†ÊO9|GÕxù\1¨K-yÅÀN¹Lù[ =âñèRñ¾OG‘䩤ëÉCeüáƒ[ÞÆÓ166V¥¨d•ñ´¡–$·JX íº¬¸ælÏ«„v\d«ÌZ9¶-•&wWH< Âáºö«Ð%_ƒŒêya?NH¥R¡0l0Cc8ŸÔWÎÖn‹ÅbuC Õæ“ófZiY¯^r^øÚr?ámâ}3UDYd m>NÚÆu]>÷¹Ïµä¹-4 Öw6€íÄ+K<ƒÄà ªˆÁûê<¦2¦Äb1’ÉäôÆñ@îSa—÷‡‹q*ÿ׫ç$äó_îl_pä ¦>n†!ÅOèwÂõ;Ιʘa, ˜³¡¡ï­S®·Qñb ¦ x–2€(‡d]Lú‚VÈçÓ.<·dG»oMÙGY¾|9+V¬hw5šB+ǶP™»p°Çžý~æÚ)OzE‰ çPÙ°a]]]äóy®¹æšª}ÝÝÝ\wÝu3z§lÚ´‰‰‰ .¾øb†††ªÎïëë ’õõõ±uëVFGG¹ä’K¾Xu,wO³ÒD–­ðEü%±S lb4Ì=¬)©½¼h‡z©Œáa\|íÍÍ}ŠZÊÂ!s™åm àÊãŽëxƒÊt²Ù,ù|ä»pÜqOUr§ÌÁ˜N§ƒ ¿L6D!ÐPG[³Ú+ò´BIVo•rø›9#RØûg*,Ëoÿi'üå-õ”M‰„¯¨-*F²|»Xô .¢fì5¯á?þqóÛoYùœõ?ÁoÆïÜÉoo¸ÿzê).L$`9SšAx øÝ«¼’"M¼UÂ_€by_8d˜”“ÆïŠå+$oî`¹|1J2Y!Ç–÷—uËuÊ—¯)‡rT¼cÄé•P™&Õ©ÛŽŽ;œvÚi<ÿ§ÿ\Xå1#Ljn¥•ÓŠD"Q7 ‹„[r‡‘zQËÂz—,!•J‘±,NZ¾ë”S*2jš°}{ ï`áhõØV¢E†¯…Å’;h¾Ì&IéLm6×d§37WEÀLŠÛZz¼F\óÈ#œw9íf!ûΙrƒƒƒÁ3o§IïŽãö>~ÜÇ+ÒøVíëà„³v+nU´Tàwª'.¡œ¡çž|.—žtiÅ-T\AËy"ƒŽKV”=åN¹ö¿ƒ”ˆ Òñåÿ“åë›Ðeú«™{ÿ§×¿Ž¸€Š(ÆÊåg+×~Ù!/àÂÿºÐ/S:=‰/ïÌãßð‹7½9Ëç_üyÿúFèœA*slYDƒco9¶Z†dNNùœ<•…—9ÿ÷9ËÏñŸ™¬®ˆQ‰"O¥Ó—°ãfY–³¡66¨ fú©¬Ü+ë$^0þ}æQ¿>⎛­<ƒN§•ò¹sÿ;€7´û•}ÓN;Ç;\/­ÛB%Ðëagj'œvü”Çf³ÙIá.% Ì*)ýå—_Îå—_^%T]]] »=ŽŽ2::Ê»ßýîIånذ 6°~ýzÖ¬YÖ-[ذaì–ždÁÃ7=<õ2ÏHQ?0{«‘Ah]d ÖêÄTÊK¸±*ƒH‡€Kn—8“Wã8Sl“Ae³­S8Ë"@æ!Ò„þ£J+vìà‰f%J‘c&Ùæ-Ÿ÷m5&•pN³tÙ”Øð©T*G#!0f…(Þ;$ôIÇ`š3¯:·¬ŠÉTH˜¯zHˆ!1º¥R%4[ˆg>ýiŽ}ÃÚÝ2óf!äð•8ðèÁ`[pË3mó=Ãà+®hw3ÔEò\ÁdƒÁÔF‡Ì ÿ òFg©o2TŒ<¢;ª-'ç7'ÉrÃúm…¼å½¡}^ø!Výý3üî°æT"‘ŠÞHô\P1ÄHTRqŽM0Ù3[êyùÉêuÃ0¨J~&N‹ÅH$<ô³Ÿ±mËÆO9… öìáé¡!–N°iõØv` úÓÚÓÓC<WcŠ¢ÌÀ‚õÓP(‚0_A2õ²·aX¥ò7T¢!d¼æÌ×ðöß¾½²R@\5¥k»$‰LÃÕ˯湻Ÿ«Ìí¤tñçŒÃþqÁü·)±jˆ"?¼2A¢- —ë–úáÂî Ù{î^ø‡r½ å2%G©‰¿H0Ôi}ñk_äˆ7ÿZÓ@ýåº RÕ™.u—’Z‘òëTÛeÈ ˆ"•• Exž÷<ä´ßœV9Ç*×[:pi—²‘iÕ¿¯âìSή“(ß«t¼nù:²¾ ¯ÿÚë¹ç¨{ürÄM5OÅ $†’Ðኯ໷b¤²ðýåÿ3TeãÖ¥¹Kyôå¿S™€ŠqkÐ*ùÜœxâ‰Í«¨D3Ñi£²±z[áw×íeÇá˜r¿„Kœë‚Ei%sÒÏä‰2"|S±nÝ:úúú V'ÌøÁáµÓ¹þʫ݉ãk;e‰ÇœÉBç–àò]މY©¯P;—Ì€¿Øï/êwhS9«;pÁ¡TV5„IÕü]þÿþ·Ü{‹ËA×T½š@î9\¿rG¾Ô^ÊîûBeÞ>.ÜVFeÛX߯ü»WVŽ 'u›¢ÓÞýÒݼõÛo­§–¢2g·s¹Ã¾Ý¹¿¬i·°»l‡Ó*ù<Ø„Ãoº}úƒDîäùÉóÍã¦D^¬ò6ynò•˜²òìÄÔ¡¿ëMWóT{]‰AnªÕ0.Õ†ÁÚ}¢—Q”yÒê±­°Ë'ÙâÇÞŒy^ýü)’[l_ m«t‘[V?t€#öÛËÃ?<§óçƒmÛA¢9)Ÿ$h{­FÈb²&D´ûÒ1ÛTò·a½b‚ ùáQ=Šå,‡lyûë>Œm[¶ñ’âKücMpÊ˟̳ҰâQ#ù_¤nr«y*|¦|/²lV¼k¤óO‡¶Ëj+9O\×åïˆ|7k£¸…ÿ>õþû9¼ Ž¢È\åÓŽ? š"¬jÛ¶qÛ¶ÉåróSðÎrJi¦9³Ae®«×m»®×ÓYgÕî»^0æ­ ÊBÞ€b ò1¸;Ÿç¯}-/yÍkÚ}kSöPiewÃ×y4Ë·"¬C –÷ì`Ùi÷ãô¢içÄáEÄy*sò"xªÈ"ci/Yk1db#á…èïïòOضM"—ãÏGF°Î9‡X,F©TâǦT–=ô'ÝsO“Z4ÚÌU6k»«B¡ á¥É4Û’Ïçq‡R©D±Xd``À¡¸‚Š'†| §øÐÿÓKÿ‰£N=Š ¹°zGí¼04!ùôYŸfÝ߬ã8ã¸Æ*Z^ðv\bŠãëu1xÛηÍ.æ¤Kw.]#Z𪷽jVÊá‰S'H’$aÌ¢‡ËÀɽ'3í †VÞµ’•÷¯¬nƒÎ]úê¥<°ûN7N¯>G¼y˜ü:œuÖYìyzO0½.çBÜžh¿Na¶òy° ødõF_!9kŨ) Z%DÜ0•pr"[2`ãWØE9¡*þ J²Šž¤ŸŠžDÂ剒<èþÐ5%Ô\†Ê€*qaųLÂÅÉõd[p~PÞ–Õ-KÅ{Jô;²ÂG®+‹]ÝÐqRgY Kèõßá—y®Q¢ós»VZB³úÎçÞ²dZÝN©TR¯l%²DΠ2_–?ç5Õ,N+eu‘mÛÁ*Aù-I c±¦iÎ~Â[»Êg&ÂyíL—l6K&“Áu]z{{‰ÇãAüsÛ¶‰Åb øa"úSì9tÛñ1<æÀ Vz©TªJf)¥R‰ÁÁÁÉIÀþ=æóyb™½ý NüÒ‰•ÎWböÆjîM²üf¨Ä>‘ì¿T2 ‹áFâóFíÏgÇv–>ãqÁ#ÀA5–>„(é’É$Å9æ^©BW8,>¦x/?üðv׬s(cÁ#XŽÃón¾™ß^vF\+‹<[ÍÈ<Îu§!Cð)Å1n~¼ªñ²ãø]fméáÅ”¢¹ø•ðð0û.6lL?@2™ &<Ùl6HÂÍf‰ÇãQEØ} Üê©óhÕÅO©T‰€èº.…BááE@_Q ª™åóy>¸çƒ¼ýïߎ™7yåý¯äè£ö?´ *á=ëP^ó»…ÓCõBù¢ÆsÞsÝgûÊ-éE_Έ%á* €›©x¹×–ÐHô-9F$Lé×7\¹7“æx¢DŸq$’HQö;ŽgøÇÏD'üw9/Ñ”±kÃë:F¨äÕUç8&ɯT»&¯ò ×]®öø ×»DÅk¨žÇYøãS,ߣ´Ÿ‡$_Rmè´ð³“E¿¹rýäÃZþ¨lýâVzefàÙípÔ/Ç|9åâ¸YçËU”dQTî>~Ä¿˜G’£!“ɉUᆠZ‰’H$(•J†ëº Ê’ZÅÄÑ-•JÁoðÄ…BÏó(•J$“I ÃŒ®ëJ˲eJ,#N3<<Œa$ê„Ò©õ”©UÄ€Ÿh¶T*‘Ïç,‡Û1M3P`‹?’*™L!˜LÓÄq¿¾+訂ë–J%^{çk¹tù¥ÑF”E¦i·âþvÇ7æØ¶ÍÝß¿›·oó¿ºÒA¦©h€ä¶%”X­®!OÓ5nõ”WÊÔlÿ>ŒÜé±z–9ãñxàÖ´<{^Q&S«nuàµÀÎ[náã‡ÊH‡'”þ6üý/tAz>ŸúYé›mÛ&‹¤ß“ñ,tr$N~*•"N9EÄ"ý~ØØ ^ÙlÓ49fG7;—¬`é#8Ž$4N$äóþL3›Í’H$‚oc*•b$“á¹®.úoº)è“Óétп×*âE & éAŒ+áh%¦Ï”jï°Ç°l—q„23…‚Ÿ>Ÿ/ÇëŽó¦DÂt€?ù—ÿйë¥c({¨ì¿j¬÷X¬3×Á 4å_½m °…‡ÍwV)èe:#„õ}²8¼QQ•ˆÊR®èvkç+’ÿ¼Öð=¬lê][ 3ñй©šòÃL&s:Ýv_oYoZWÑÿüàmuΙʯ/M%œg£½Rß°1B… T 2r²È?‹o@©­›´_­Ó„“äx«|ÍÂà×>Ý`m÷=^ûWÒ=|oÅ›C^¨fPVà»ó+¥½Ì9)†®aj8õ{Ę –S︩5FãBlRù8Õ~ˆ¦Ëa#שϧCÚ¹±&nÏŸKÕ9D"î(JTYT•±vNð†9*€$$V<g`À÷ /•ph/ 9$Ê—Áš˜ÿÙl–|>O©T ÊŠÅb¸®(8$¬–l+Dñ!†1ÚˆB&L<>»ª†aÍfãlËçóUÛÂÈ5Ű$ÊÛ¶Éd2U«uÅ£GÚD¼wâñ8…BL&CÌŒqËWn!sY&PDIâÆX,Žï„ÁýßÏK`¥U^"ñ=cT’9ÚT\Asåía×ÒÇL3hV,ý}'—ÁŽ¥;6Š,Y²„‘‘ª¼SEi儘ç¸pÔý÷óO?Mü²ËÚ]«Y‘ÏçƒFxaƒ,8{wÈ¢ˆd2,œ~¹vAC"‘ög2zzzIJ¬`±„Û/pß,Û¶M>ŸÆâ}‹Å‚ë}ðð7²t¿Wpô²z¿ÿŠÅ"Ùl6;HýÅ‹V Ùþ~J¥‰\.¸N.— ¼$œ§|KŸ¼ùfþóôÓÉtÆ$%N•U¶WÞw}òÉhÌ íPK"‘ ›ÍªA¥Ad]Ž÷&!¼ê£w§t"Ä^î÷À^]>ödà×À=ÀN°\Èœî ÿ±¹„#[„Wººœ:¾@}Dç`‡þ®çá+ïZ8 I8ôü`¨ »æÜðªp—j=ÇT:Y¯4YÍ$ìüžÜ×êdQª\oštõŸ-õu0ávSë1&aþEq+QRDy+ÿ‡£µÊ 1¨P­6®³Ï¦o÷³OSý'öçŠíW€ …²vܾsrGŇ©L]ÂN÷â f¶ëÀf£Kd†cg*G®· ðfyŽ N?}Ví ŸÍÙœ#†ŽFœÂÛé-½N=U¢ùŒô¼Y¶Î¾ÃÝŸíâMGû¾ Z”h°¸s]X¢+j›ÇvxìIXi=œ0i·Ì­4Še•Aå·Áþ'Ü?ëpJK.¢tÉårç†(!Šݩ”Ãñxœ|>ÏÈÈÈ$¥ÎØØØ¤ã¥¾b¨§<žÕªÄið_õê0SŒwÓ4ƒÚàà UõJ$ ,Ë ¼|Â!Í …‚o´1á‚O]œ'J°b±ˆëºÁŠÝ|>„,»ånáyG<Ïõ|ÎWÔ„Ývå+nž²Ä¶PÞ'h%l˜„CL=\ªãeÖAƒn4ΓçÂ[dõÁG7t¼÷‰DÓÞ}EQ¦Á„ì ܳþdÓ&ÎÉçIÎÒ`ß*jCmç†išÁâQ:‹çc8$§ôí²€!™L’H$¯R¨ôÅÒGŠa_®+ ízÆÃ0fÌï$ãŠð9µß·U¯Øã‡†8åq›oìñÇ ¦ia³ä<1üäóyúûûÉårUaŨ"†ð=sÒé4ñxœþä'¼à¾ûp_ö²ºc&Qð=öØc¼ÿ¸ãH8˜&iª£:„#n6Ld(Ó㺠"xÔ7"–+«ü²àžÎs`¬€Ò `»» ¯û5`é«î?x>w€³?Øk þ[0¾ æ 0OÎ+‡ßîï¡t<Äw‚1¥•` Ö÷À9ì#¡t.ä„̽`üœnp_ÆÀü5p¼ÿ“8ÌìóÁ]^mÀ(ÛsƒäËaÈ„¬‡Ê¯Þ»&÷Î/!„•Ÿ%üH|C‚Dj‘ܽ¢ð†Ê0Sêe„þ¶©È@­q¤ª½Å׬xƒMõ5‘{K3Ùƒa€ê\Åø+óëì%¬’„ ÕÜpÆy/á-ün¶w±ïQ~¹ž:î)Þzô[¹aË ”>[1d¹Àí§œ2é}üÎáðOBTõ‰b¨šžTB•Íö:³]ŸÃ9Sg.‚í'2×fÚ'8õþSá3­+_ú.Yl :}UK4•Ëáä½{É}‹,jS/%Ê,*ƒÊ’?…K~t °»ásòù|rKÂy„•"¢x™M¢{Ó4…K­‚fºsâc1U®–T*Õ÷@ø>j=s€ YXY"çL¥lïñT£xÅãq– ,`Iq ===@µR+N³bÉ ^±î¬ú¿UR8¤’ôüYKŽŠ½Ì¢…$þñ²4¯@%°±,Ë•[ÏRíë®ÌÈýY8fø.x×ÌQ|65Ì—¢(Ó“…Ì¿À£0–Æ\»¶mU©5îçóy²Ù,###‘]r”Au_$á´2™LÕ‚ñ”ÂO·c6ß f|¯n>ð@ŽéùgµÏRÖ¨~ôÔ›¿æ/èy1XGøSŽéf~aO'À×,šÙ©4Mé‡7½ûÃpÝuí¾¥H²k×.~ùü_r–uVË®aà.%Dž:Â(Ê8ˆÃs»&§ =­.®U¢Ì¢2¨,ý>ìçÞ‡i¾ ás$Š$c¯§Ä*tE3‘xçõŒ Ál FSöÀ ‡›),Y8lI>Ÿ”e===•¸ïåQ¨$¸ '§ ‡qyÓ{ßÄæ ›9Õ:Õß)a¿ÒTbrRYšþ$Õ)+KÊd¢ž¡b„‘ežSÅiP¦f?8ð©ÇXvæ™ ‹ÅÅ©¢( Ã_„Ë (”óvµ‹þþ~Éf³ÄãñÀ;R ïâi’Éd‚Eñxœ\.G>ŸúY@ÐIñóÎ;Ÿýìg|òÀ¹¬¼M¼lê$¦¯çeRÇÀÇ'… “Lúés÷Ö·ÒÝ×Ç+:Š‹Î9‡“2ÒÉ$ù\ ‚èâû©¬Ô ¯ò¯EK¨Aez ?)ýòÛŸ…¤_z(‰¥?Ôß_›7µö-Ÿé­¯  `¸D˜0×S­å­mÁª 5^/žx¼úø€býò$á/• ×Y°Bõ â…“@ˆ÷q¬|œEjëSvq±ÊÆ ó‡ÀÛBm ‰#Ä %FÅ$Æ ßà!õ »¾Ø¡mšv ÔRöHMÝÄ# Œ ÊVŒ&ƒåãÄ0S;5q}ÃÎØ#å2ä¼"•¤ákö€‘€T¹Übu™wnü.}ô«!>÷â?ðå“Nâùò' /o\q¥§4‡Îéí•–1½è93 žýTÖiJ—¡(ÊÌØOÁ~qxlð1àX Z~d¨(QfÑT\`ân¸þ¤ëýd€ «àÅ›¢ÐÅ–'BâÍ×[9;ád™L¦®’H‡¹e¥Ÿ¬Â•pi§/f$1âr ø/GxÉ’hä‹]N&_båýýåŸ*“kyDYÃʱÛîæŽ>ûíæÎ®e¼±%­äê$%¨¢t< ¸+‰þ~þõÞ{ì²½½½ ûéb%ü¦x-†ÃZÅãq²ÙlÝEámþÝ8þøãY¹r%ÿýßÿÝÐ=I8°Ù./“ÉyÞÄ•Éd8ûÓŸæ°îî`ñ‚„V«×›‹®[œl*Éwë!F°#Ž8‚£n, 侊±®\ûc~ôº4 ª'š3åM3íÔÉM‰gºØ:áíµÃgsšc%c·JÂûdˆbÔ9GŒ$S1U]Y'5•U̪sÜT¡Äî3-ÓÏU3?z€8|éõÛ¹f|/ïX¾¼áS%dT¥¹¼oåývö1-¿N8Ô©‰ÿùOR R圩k1¥–gàˆãáéýž®»»‹Í¥QAÅvþ VºÊß00¦éÇK¨³3NŠI´îdC:íÇZýe‚B¡à·0 ÿ§ÞjOÇñ,Ë?&Œëú?¡Õ¥ñ Ÿ÷Ï3ŒÊ1a…ŠëN./bd2úûûç¥è™î\Y][(Èçó Û,ËÂÁÁÄ„bÙëÅŒaì@YgYV%8·,ñ¬,ËJBÊÛÃûdõŸ §=vÏ<Ûî&4Ûî\Ê~íœö˜l6„¢içêxEÙqÞ û {ï½—#O9¥%×O’°w„„¡²m;{ 6®ûÄ úÜ®.N J0ßïåàà ŽãL&ƒ¶¾áýïç¿7oæ#¡…Žã Pê]3\ÛàŠÝ»ydÏ®~î9^²e ß;ë,ŠGá;"¤R|ò“Ÿäƒü`[Û;ê<ø/ãüü?/cUÆ4÷í«è 5Ê!‚ù'òŽîîYjÔüV¥9œ}Ð3Lœ:ÑÒk„,%—–¬ÕÂ~|5BžJ®-É&‹Š²Os <ïËOòà’ëî–BŠeAÀ8 N¬“¬2†ð!¥ïýá¹o|ÜOfÎíašÉTPj1M¿œàÂ5•ò5(|CH©ä—)¤Ó¾ÑDÎËÕ,% 8b±ÉÆ“RÉ?*÷Kæ8þ52™ÊqRV¸žÙ¬_¶1§r|<^ݶírÂF¢xÜÿÛ¶+u •?S‚Þù ±ß-Ë V7 ®ë+™%1¯mÛçC6›Å0 Þú›·r¡y!dàõ—½žún¨yÎL=áÕ`ÇÞÆa-»×ÅÀ /]ÂG~ò¿üÍ4ÇHÞƒÙáE™??XǬz‚‡—®ÆZ³¦%ׯBùF'c<~€}6ÜßšCáŸ/¼å lT6M³ªÏöÆÆ˜¸ãxË[‚mâšÍf«ú]×uI&“U¯‰;î`èŒ3øãþûóããÜõ²—ñ®»î⩲A%—Hpíµ×¶­;Ç__p/|üwÄzŽ›ú@ÛöÇ…‰Dõx±Tò÷ÅbÓieOøÜBÁ?*ûjö„råaÓ_CQ!Î3ð®îæØ„YTEi +·¯dÛªm v½°]>ì,)+¢¡é¡:rc’ŠqE¼{kËP”ÅÌØá‘›örâ{ëçkK&“-Õ'*J3X48ù 8ìé’—Jù ÿZ âqn=ã ÿãqßóžêÕASM Å@þþé&ޱ˜?AÍåê×!• êQE6[©÷tJåðþz‰ì £bqÝʱáÐ[ŽãO˜ÃÆ1ðˆA&ü³íŠñF§¿|Žƒ¡\Œ&‚,NÅà"Û%§“Q>Ç ÕS" ›å:ˆ‘¨ÑQ¼[¾^"T®]¾ß<òôTVùo‡J´u©›A%»UsN£K)ÄHF†Mö¡íòÜäïXM„ƒÔs,õj˹ý8á¹ú‹’K¥RUøgE‰*m“ø‰‰ ÆÇÇé®q‘ett”îîîIû¦c» ¿ºi/½`úÏ»„€j46yù¤…YµešþµšñáÉÙTñ♊ùº×ÉŠIè´QJ¥Ê$0<1”IœL¬ÃmžÍúêB¡âcšþdsp°rlÙ(s¾ër~¹¼X,†72Âc×_ϲ3Ï„+ ‘àôçr×ïâ™=Ãÿ¹še÷w|ú oào÷ìá¤uëXÛß|ÄÅãºn:LøÝÙ¿ãÈŽœÿ3‹SÉ&ÌM>KÀ’£ž›öÛ¶5F¦¢4@³åFVÁÛúãkI»)‰ÝÅ‹app°j0¼¯†òZl¤R)zzz0 £*ü—eYA®œ¡ Ãà å}×î¿?Äãq2™ }ÖY<¸qc»o¥©4sl;ö;|ìú­?¶/ ï4*§µž!09ÔìBPo=aÆ4+F•zÌä-0<ì5ê…MsjƒR˜D¢2þ”ÐjB&S?dZøSµµaøcm×õëX¯jBÚNb&£V*5ýX?—«Ì;ù¬Ù}çWþ v|b?’©Y„©­™ã%$œ² ï|øx™óÈœ.¼?š&/V {qɼ°Ö¨ç8O²ÚóÃ^b–59 µÌÍÄ£­–l¶rõrš¦ÓÕFÐÚë»®_ 5íº“CÊ>iËð5J¥Š÷›D†×_ žñøä…†"—áú…Ã*Êþzå6J:]‰ò ïF¸þR¾¼"Ë…g>ôÐì¯aš-ŸQk†¿Üá"AÅc¤HÅѯ¬·BÇYuÎÏàDÄxÑSÞŸÀ÷~‘Ü-"ebôÉâdœòµäï$¯‡jƒŒÚ&†ÙŸ§9½DÅ(áP1Hå2ìrÝäÿt¹n±r] ª .’þÖ¨ù£O"t-Ùg‡Ê {ùØå{ —/_1:…%;llÊá°¬P^»{7›Ï<“÷ÞrKËÞvÐl½­prö.{ŠW¬˜´Ï²,Õ )Á~íºp>ŸgÓ¦MUÛ6mÚÄ¥—^Ê5×\Ã¥—^:iÿtìþ œô'{¦<Çqp‡áááÙåi%o)µ¹YæCØ»£3å‰iƽ$“þ`º¶^™Œ?‰¬}29–º…Ÿåà ?ƒƒþPž‡h„bÑ?nd¤úþ ƒ£î¿ŸÃþë¿‚k¯û‹uœû«s9uÿSYvüñÐÛË;3S^ðN>÷\ÉX™¨„Ûèíí B×,VêÉ&ÌC>o‡W¿ìn^7…‹J>Ÿ'›ÍêŠuEi€¦Ë'€ ÷ÿv|£ñ|dQB-:Žã‡~ª]•®LÏtž¥cxxxR3ÿ¬ ¬[˜x<?00€aÛÜþùí¾¦Ò̱íùq8eË7ý±TíØGi QBJ¨ÜÙNÎãñŠ‚³Ö{EpfµH˜µFëØŽU˜â™¾(-šÝw^·^úWOß_JȽRÉ_V;ǃ…ü„ó^ú•ö½¬džSûœÄà(?aãŠ\_Œ4õº®ï¥å8“bÌÏ(ÉÉT{L6ëÿôöVï—ƒ1!›ì¥&õCB­ È9ÓÕ?™¬üÔ–_*ùÛÅ(Uë­%†Pñ«‡„¹–{ªÅqügÔÓ3yå§§grû™¦¿O¼àjï϶«V!ãÛ1O>Éb¢%cÛAr BµçƒAE¹Ååº.V©„U>ÇuÝ`¬mR6Ôúó㉠ŒBR©„™ÏC9§¬á8¸¥’ïE^*‘({L ‘Íâ:ðàÎÄK%¥ÏÝv/Û¾»¿Ÿ—mßÎÐ]w1è8¼ìK_Âq]þê†øÇ›oæóO>Égn»ÃÞøF¾÷ôÓuÇd‡n¹…]»vO&ùÄÃsçÓ°mö¼ûÝà8¬þä'1óy¼ùfÖ|éK˜ù<çÜv'Þ}7qÛÆK¥èݱzzø÷›o¦ûÆ,{šÚ®Ëù÷ߥ/ì1>ôÈ#|ç‹_äwíâ}÷ÝGÏí·sÕUWñ†={8"•₟ÿœO=ý47MLÊç£û¿ ûoä›wÜÁ'®ºŠ+ï¸/•âþ‰ œž>rÇÜzë­üãÍ7óºï}¸ç±æ®»x×]w1~íµ¼zÛ6v­_ϲ­[ùÅÙg·ûµj*ÍÖÛ +ÎÃ×>Éž:cB³t¢ŠÒj¼æúë¯÷>ðx«V­ò®¼òʪ}½½½Þ­·ÞêyžçmÙ²Å[µj•÷ÀL[Þe—]æyžçÅîñ¼ñïç^8屦izm¸åÆö ¦éyÅbk¯1<ìy–åyccs;ÏóR•S©”—Ëå‚¿ßpá…ž»b…·ý‚ òollÌóR©Tð“ó<ïk=ä {#žç Ê£w]/wçž7<쌌xxžwÅwz™LÆ»}Çoë÷¿ï=ð“ŸÔGÊ×+ïûÄúõ^jÛ6ïï6l¶ ÛöƒƒÞb Uz[Ïó¼ÏóθÊóNø‡„UqÞØØ˜722¼wŠÒLZ1¶]ð_kÖ¬¡»»›ÑÑѪíCCCtuuÑ××ÀêÕ«Y½z5CCC¬[·nÊòž|òI†††{ ¡Í+xÓ ›òX 3Y[ŒÀ9Æž–5õêÀ9~?‰f&Ã#^È®ãçƒü ¯~ûÛyú]ïâÖnà¸W½ŠkO9…£Ž:ªõ÷¹L%›0wùܶmÏî|„çxާÎ8£î1ÅbQ½S”¦311Á–-[ؽ{w»«Òš-Ÿ»wïfhhÈwÓ¦›±w<Í?¼îAxÃÙà8¶mcÛv]e–L>hqÌ1Çðç‡ÎÁ?û\pA»«3oš=¶=ô‘Cyâ°g9ߨP‰“©D‹Ç '†­¤e2 ß1HRn¦Ó•ëærÕÑû$š–Ô-—«¤˜J¥ª#~åóÕÎ@†á×Ãog38§R¦8öÄã–_—rÚ¢L¦º^r_…‚_¦D4ÍJ°‡X >ûÙ½ìÙ³‡¾¾Åá¡ÒбíÞÇçÙ“Nâ€o~³ºÿ¨¼Ôµáåðp‰¥ò ‹Å f⦛xôÑGÙo|œ;N=•ÇÞólÛÆ²,NúÁxÁ}÷ÑsÖYì~øa~ñ÷φA:fppÃ0x®«‹ûÏ?Ÿ—ïÚÅ3CC,¿úê Ä®eY<÷å/sÔÈŒŒpìØK?÷9œ³Î¶mŽÿéOù›XŒ~ÙËXÚß‹qã¦M_²lY•—Þåkó’PΰÀKCÞ•ñxÜ&Þr…²ÇO¿ïñSþHš±¹D‚ÄgÀÒ¥ðæ7W {m$—B’IŒ²Pþݲeð®wùç\yepØÃ·ÞÊ©ÿ÷­ÒÛ®Y³gùr–~&Öì©:¦P(`Û6®ë6%µ¢[·nmÉØvÁ *«W¯ ««kÒ ÖÆÞëêêªÛÁ†Ù¹s'CCCL¸}ðÄ#ì=÷ܺÇIøe2`À4Ñdp|ìÍ7ûqß_ýêàZ÷‡?@?]¿ü%=õÔv·@S˜J6aîò¹mÛ6~}‡Ç‘Þxݤb¥²»q®ñÜ•EÍøø8CCC‹Æ ÒlùƒJ__ÝtóÌ:ó-kÎý¤ëºs2Æ(û&£££üä'?aéÒ¥|ä#iwuæM³Ç¶;ÚË™Çßî[SöA“A¥UcÛ[~rgŸ}+Æu¿„ã–ú;æ²Ñ¶+iL„TÊׯããF8 ÊÀ@%â—œ')I2™JÄ®xÜÿ[ô¤¢KM$ümmJôÌb„€ŠqF"fÉ0>›­D7]íJ¢ÉÉ5³Ùê0¦Y¹ŽDî*뱃´!í üß©TEß)†“0¢Ký± IŠÅJ‹dp°Í«Tªü/Ç bôð7þO¿ÿ±èÿäó~bè‘û}±DËç+†’Úëù*úÿ\®rÎ%—lcÓ¦MüøÇ;gýžE‘VŒm_uÐAòÿŒbŽý®eù/Ы_ _ù —ÔÞÃLÆÛáaÿE­7ÎÇ9xºo—eÍœ_7|ýRi²€Î´Ð¶Ö=‹û³$,!LÎà uë<1Ø9~ù¹+É·TSß?,YÂÿrã‹d±m«ô¶ÝÝݰ|9Ë…CV=QuL"‘ §§gv饶lÙ²8 *S1>>>i[#ÉŽ=öX6lØÀÇ>»ë1S7L:Æu]¿3$úIÊ”&œám,Ëšüa/yζùÍÞÐî»h9s•ÏóÏ?ŸágŽcùþ÷ÕÝoY–z§(-¡»»› 6°uëÖvW¥åÌE>8â6lØÀ׿ +Ž~‚Fp‡|>O&“Áu]z{{±,K)ʬèëëcýúõص1åsí;Ÿ{î"í•¶°aÃ6nÜØîj´œùŒmK÷ïû»åØW™¦–ò™å¼xA„Pñ|ˆÇ+Æ1B¤Rþ6ÑûÕÓMŠWJ8‡º¾ŽJjë]{~˜°®±žž«Þ§*\~=]lx­s«xÔL•†¨^%‘´[mýÃé4Ui¤(sg¾ýç϶oã˜ç=‰yÌÌr(‰3Å»ld!B;*‹’N8ûÝÕh)s•ÍýŽð8Æz˜å÷ÜÓÅ„¢ìÌU>»ïb¿7zzáS#^ bÏ1XL5%q+æEw7ÓôF‡ÒS¥¡¸aLmL™Ž™>—íºÇ¹èÕ÷èŸÓ2ç±­m7d|p'H/akK¥RÕ!Uê*“Ð0¬óžw¸€{Ý^º¯=¼j{"‘À¶mÕ )Ã~í®€°zõêI£ñññ†¬+^מºÝ}ñxœb±ØÜUÊâ è÷zFæ#Ÿ·ýœ;OŸÔ1º®‹5CŠ¢øÌ·ÿüÍžyé²­ õ‘ŽãP(0 cJC³¢(>s•ÍÏÜÅ—}U_Üî[P”EË\åóîÇ,–»;8餓;Ù9N%Ì¿„æ²,As±Øô´Š²¨™óØ6“iÈrÖßßiš¤R)Òé4‰DB½­¥æ;ïîÙq$Ïî_­¿M&“ºØVé("cPéëë bÞƒ›ott”K.¹dÆs]`Ì®o-PcŠRŸjPi€ùÈçÿ‡¬®,¡‚´³T”ù3ù¤ûà9ûцúIÛ¶I$d³Y•_E™¹Êæ‘÷ÝÇßd2ñ¼çµûeÑ2WùüÍI{ØÿŽûyË[ŽªÊ_Òß_ïZ»HE™;sÛÎàAÏçÉf³ cš&†ahE™óšw–qvÂ)]ðäa‡Um×Ü)J§™_àÇì]¿~=kÖ¬aË–-lذåË—Ïxžý$ìúý³|ÈÓö%“I͈9©(û8s•Ï—<ˉ?þOàÁ6Çq(‹ªU”&1WùÄ‚­xé’û°fðëïïâÚZêò®( 1WÙüý³Ï¢)饵ÌE>Ç[Nσ#œ}ö¹vX%üð°zŸ(J3™óض†B¡@©T"‘H9Qt±­¢ÌùÊæý?cl;ÇœtRÕvÇq.CQ¢@Û *×]wݤmëÖ­£¯¯ÑÑQº»»wû=œ¸âY¬ÕÕ  )¤ŠEiœz² s—Ï]?çì§«ó MH¯(s Ùòé ÂÒŸ‚{–;íqù|žÁÁÁ`ª²«(“iÖØöäÇgûÊ•í¾EY44³ï<áÖ‡9kdx-Žã'@ש¦¢ÌfmÃ8ŽxU hî?E™%MÕÛ–Y~\ôê_ð‡gO¨Ú®óK¥Óˆ”‡ 0çÎrÅaÿ7i[¡PÀqõPQ”&1ù¼kɑܳ¬zm<WC§¢4™¹È§³?<ïù`ÿÊ&3EÆ[×u) Ú—*Ê™­lÞwä‘üì”SX×îŠ+Ê>Àlåó¤àð#Çq]ß;E£)J똫nüñk>Ÿgxx8ø_Q”æ0Ù¼ëj¸÷·'ñaÏãþò6;œ”LQ:„ÈTæ‚}üîöãY{Nµë¦ÆàS”öcüø N}ÞUÛt…¢DƒÒ›¡ë{·ñÔ Íf4¾´¢, =ô†#Q”ˆòò½ÿÊý'íeÁØX»kÓ>DùeFÂq öٶM¬N´T*aš&®ëß7ù»P(ÇÉçód2™ Ixø9ß4Í ,Œã8Äb1òù<©T*8β,lÛ®ºžÔIV@;Žœ/uµ,kÒ·7N‹Å‚c¥|QÎKù®ëºÛ¶ƒ:º®K"‘ T*Q*•Èd2d³Ùà~¥ÌD"A>Ÿ'S(ˆÅbÁ>Çq0M38î÷¿ÿ}»G`ÛvÕóÔ~UQ¢ÁãOÁ™+nç}§®CÍœJ'³( *wm‚ÞØ3iÅ{OO*m¥Í,yž9woð¿ëºªœU”ˆ°ýŸg›ÝÅ«ßZ?Šëºº¢OQ˜£Ž:ŠOúÓí®†¢(uøÁ9ç´E1+1Äb± „®(⥿ÃF>Ÿ'—Ë‘ÍfÉd2 ‹x<(émÛ¶çr9H¥R¤ÓiƒóÂ+ˆ%¡·a8ŽƒmÛÂ?™LR,c€7¤nr¾ ¤ÞrŒiš!CîUŒ¥R €X,\_Œ*á²K¥R`‘ÿÅð!çÛ¶M:&“Éå†Û*•J×u'ðصm;0øH[;ŽÔAŒ4¢›H&“X–—Ä#û¥-åÿx<Žã8ôööáVå> Ãà°šDÎÊd\× XŠ¢D‹³{áÀ_ùù¯¥7 à¥SX•ÝÛŸäÔå÷VÝN:¦X,êJEi3Þ’eUÿK[ ¤(íç±½Ç3Z7_6›Å0 Œ*ÊsÐAié@©PQʶ°2V¿‡ÏÅt­aºöaÅnxŽ”/ wQ&˪~QòŠr9¬x–úȹšvzüñ¦Î/Åè L&C¡PöËóŠÇãÁó”ç+Ïݲ, …®ëž¦iFIÂ- šä·Jä=í"I<.db؈SoÜ c{9^ÆÙl–T*5eÈû/ç'‰)‡×›?ˆÁEÞáðµk¯Q»M ²_~×.Ê”rk…Éö°'NíµäÞ¥¥nµÑ4Âÿ›¦9)ߤü} Õy”É„¿ÏŠ¢D‹Go|˜ñ;¿[µM òŠÒI, ƒÊ“K÷ãñÃ4«š£AQÚË='Ä©—>‹uª/‹2ñÓÕŠ œ'÷rôÃcY/™´/‹©RWQ9¢´Ïf³$‰@QoÛv ¬/ ¤R)òù|–¦öw­ò*«Ä3™L°‚^Vƒ×þ. UçB%TNøXY-/«çe%¸d|!ãB¡œ[,éïï¯Z¡60„ÃÉ}׫k2™ ÂöHÝÅ"÷í8¥R©ªíR©TЮµa~ à¿¿Ÿááá ¥}Ã+ìå\y6R†a¤N²Ú^B)ɹÒÎ@Õª~)CÚáW¿ú}}}í~=#ÉØØØœæ˜Ùl6x'Åà!ÏO¼ Ä!ì¦ÖX ¿ÅxR1ÔcpppV÷`Æœ^ÓS¦»ÖlŸËsi¶¯^[Ïe,%Tenˆw–¢(Ñ㑼$ô½–±‹¢t‹Â òôk¡ûºŸbšLŽ—©(JûØöõ0¾äË£(]T>%ìzt9Ó|GÕöt:mÛžOQ:YÕ6.ˆò`` 0FŒŒŒ†…l6[µº;l ‘04²R<¼š»ö·(tÃ^–eU,Ë ¾)¹\Ó4ƒÿ§S„Ê1™L¦j•½¬¢—òë!ÊÒÚ•ù|Û¦:W®+ŠÓp˜žZD‘Çéíí%‘HÛä|Qj•rˆR¡VÙ=Õ ûzçÈÿµ«îkë.3ü÷ÆxãöM^øÂ6´0HŒUb`oƒ°’w*e¾®ÒU”¹ÎÓ£(J´¸É…ƒOØ3ÉkWñ)È¢0¨Ü{%ôŒ/©Ú¦¨¢Dƒ§ØüÇÕ;EQ"Ğ˖rÊÃ;«¶Ù¶M<וBŠAdÑx$Èjwñ©M¬,† _#¿Å8ÐÈ õ°GÃt¿Ã„'ÊõÂ|Îeâ<•Ñ¥S&á¹\®*”“Ò™yä‘SÎ3Ç ÂeJ)ñ*ê”÷TQ:B¡ FIE‰(¿ºæzºž úD™w*J'²( *íñXq”Ÿ`ζíÀE_Q”örðŽ8oàö@ ’N§ƒ•Š¢´Ư؋õªj%e¡PPç¢DB¡„’ü¢´¯ w]¦Ê;¡,Òé4€†R”6£ùS%Âì9„ÆCzVQ:‘EaPYy±Kÿ±¾‡ŠL.Ei?¿=…'~ÆÇ|ÅÏlc5+ŠÒ:ìÇ`ïcÕbLÑ~TQ¢ƒmÛ$“Ir¹\cAQ”hÏç)•J:ÆU” ¡ƒ´ŸT”ˆòü•l;ð·XÖÅA7EéDökwšÁÿñlÐi–J%U)JDØï¹]þÈ#€ŸlL’¤*ŠÒ~Ü‘‡Yûî;«VLë*!E‰Éd’B¡ÀððpU(/EQÚO:Ʋ,5¦(JDp]×uÛ] EQ¦à?þºÇN þ—Ü}ŠÒ‰t¼‡ÊGÍØ—c­WzE‰ÿæ0ºŒG?ІºP”èpíC;øÃ\bŸñ!ôôô088¨E‰Ùl6HÄ®(J´%Žm%:èjwE‰6?·‡¬|ð##h˜L¥“éx•g ƒcu±,‹þþ~í@%B¼èæ;y×£»ÉçóäóùvWGQ”¿:‚£÷ú«øÇ¡X,ªbHQ"‚mÛ¸®«ÆE‰ ¥R)0x*Šòù¼ö›ŠaÎyï8þÙ‡T?¤t<‘3¨ŒŽŽ244ÄèèhCÇŸümœ|A<וµŠÒBf-ŸGžÈs'ŽeY:éT”3[ù|ô™9ËÛø+áÕåZQZÃleüI¦ö›ŠÒzæ"Ÿ†aè">EYf+ŸÅb±ÝUV”}‚¹ôίÇùíWŸÇq§G©T"—Ë©Téh"ePÙ´i—^z)×\s —^z)›6mšñœ'÷;“—bN§Õ˜¢(-d.òÙ³÷ò'Ûuµ¢´˜¹ÈçwïÁ|Û2 …©TJó)J ˜‹lîÙ³GûLEYæ"Ÿ~-Ú;€IDAT¿øÅ/ÈçóêÑ©(-f.ò©(J뙫l~vxŒ§úæÅÇž®ú!eQ)ƒÊƹꪫ¸îºëøÊW¾ÂÇ?þñ-ž'ì}˜‹Ïy˲"9°zÇ/–å(õ6ÜW˜“|žp+W®$•Jµ»úu‰ú»5ÛU M'|?öæ"ŸñâÜsO&ŸÏGnAB'¼[úýPa.²yÐA- ï”ÅôF]Þe1=“f0ù<õÔS…|ê;=Ë3is‘ÏÅ@'Œe±¼Ó‹é™4ƒ¹Èæ#<Âw~u~“ï?märF½/é„w0êò¾mÛ6þøÇ?6µÌÈ$¥¢««‹¾¾>V¯^ÍêÕ«bݺuSž÷ëý~Íæ»6“Z’â®»îj÷mLbÓ¦Mtww·»Srçw²uëÖvWcZ¢Ü†wÞy'¿ùÍo8çœsÚ]•–2ùüãÿÈןþ:ýßAüÕö¿bûöíí¾IDùÝ?QÛêÕ«9óÌ3Û]•ºDùûñÔSOqß}÷5½ÓŒ"s‘ϱ±1ŒUÿÀ?ýÓý|ò“ŸŒÜ-Êï– ß¹óÇ?þ‘ááaž}öÙvW¥¥Ìul»}ûv®½öÚH>»Ùåwp¶D]Þ¥‘g¢cÛ©åó©§žbÛ¶mlÞ¼™“N:©Ý·0/ö¥wºS˜é™ÈØ6Šsªf3×±íµ×^ËÑGÍÑGÝî[˜30n”Åòiä™èØvú±í“»füû‡bs/7¯¸3·Ÿ©oYÔû’Nø.DYÞï¿ÿ~~ýë_ÓÓÓÓÔr#cPÙºuë¤ÆïêêšÑJ¸kÙ.ŽyÑ1Üwß}Üwß}í¾I¬Zµ*rŠª0{öìaùòå‘®c”Ûð¶ÛnãñÇgÉ’%í®JK™‹|îܹ×p9á¨"ûü¢ün,_¾œG}”;v´»*u‰ò÷ã‰'žà®»îbïÞ½í®JË™‹|pÀ؆ÍêcWGòùEùÝôû1w¶mÛÆ½÷ÞËYgÕ”¹Žm÷ìÙÃøÃH>»Ùåwp¶D]Þ¥‘g¢cÛ©åsÉ’%lÛ¶ýèGœ~úéí¾…y±/½ÓÂLÏDƶ{öìiwU[Î\Ƕ?üáY¹r%+W®l÷-Ì™N7ÊbùÎ4òLtl;ƒwdz䴧߯z V™Ñ{/¢Þ—tÂw!Êò~÷ÝwpòÉ'7µÜÈTÆÇÇ'mkĺõ£ý¨ÝUW”EÏ\äó­o}+o}ë[Û]uEYôÌE>¿ño´»Úвèѱ­¢D—¹ÈçÚµkY»vm»«®(‹Û*J4™ëØö–[niwÕ¥éD&‡JWWפmQŽa§(û*ŸŠ]T>%š¨l*JtQùT”è¢ò©(ÑDeSQ*DÆ ²zõêI‚8>>Ùlв/¡ò©(ÑEåSQ¢‰Ê¦¢D•OE‰.*ŸŠMT6¥Bd *}}}Œ1×¶nÝÊèè(—\rI»«¦(û<*ŸŠ]T>%š¨l*JtQùT”è¢ò©(ÑDeSQ*D&‡ À† X¿~=kÖ¬aË–-lذåË—·»ZŠ¢ ò©(QFåSQ¢‰Ê¦¢D•OE‰.*ŸŠMT6Åg‰çy^»+ftt”ÑÑQº»»ÕmLQ"†Ê§¢D•OE‰&*›Š]T>%º¨|*J4QÙT”TEQEQEQEQEQEQ¢Fdr¨(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢D5¨(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢Ì€TEQEQEQEQEQEQf`ÿO|âŸhw%:•ÑÑQ¶nÝ$cšj?@WW׬÷7“­[·²lÙ2–.]©úMLL`Û6sÌ1³ªÃB¶ŸÒyÌG>Û-›Ô¡Ýò…ú)Ëtò¥wk.òÙnÙŒZ*‹‡VÉm»ÞÇVÈ÷BßK«úiýFt­œ“FI>ç+ y/­œãª|v­œ“¶ã]hÅÜ5J}ç|ëªò9™(´ÉÄÄ>úhdûŽ¨Ï·nÝʽ÷Þy½í‚ëÖØßÛÛë]ýõUçÏ´¿™<ðÀ^oo¯wë­·Fª~[¶l©jÃ}ìc ×a!ÛOé<æ#Ÿí–ÍFêÐnùŒBý”Îe:ùŒÒ»5ùl·lF­ •ÅC«ä¶]ïc+ä{¡ï¥Uý´~#:‹VÎI£$Ÿó•¿…¼—VÎqU>;‹VÎIÛñ.´b³ŸIÔ‰J›\yå•Þ•W^9ëú-Dý£>7þØÇ>æ­]»6òzÛvèÖÔ 2xàoÕªUÞ–-[‚mk×®õòù|ðøAnÙ²Å[µj•÷À4¼¿™È‹~±¢P¿p›{k×®õn¼ñƆê°í§tó•ÏvËf#uh·|F¡~Jg2“|FéÝš‹|¶[6£Ö†Êâ •rÛ®÷±ò½Ð÷Òª~Z¿C«ç¤Q’ÏùÊßBÞK+ç¸*ŸC«ç¤íxZ1wRßÙ‰Ï$ê´»M®¿þzïø€·jÕªº•v?Ó¨ÏÅ)žzõŠ|·C·¦9TæÀèè(}}}¬^½:ØvñÅ3>>ÀÐÐ]]]ôõõ°zõjV¯^ÍÐÐPCû›ÉÆY½z5kÖ¬ ¶E¡~CCCŒsùå—°|ùrJ¥_|ñŒuXÈöS:ùÈg»es¦ú5²¿L'ŸQ¨ŸÒ¹L'ŸQz·æ"Ÿí–ÍFÚHåS™ ­’Ûv½­ï…¾—VõÓúè,Z9'’|ÎWþò^Z9ÇUùì,Z9'mǻЊ¹k”úÎN|&Q' m²fÍÖ­[W%‡Öo!êõ¹ñèè(ëÖ­cùòåA82Õ­ù¨AeôõõqÝu×ÿOLL°yóæàåÚºu뤸w]]]ŒŽŽ6´¿Ylݺ•Í›7“H$&mowýFGGY³f ›6mâÝï~7ëׯ¯zi§«ÃBµŸÒ™ÌG>Û-›3Õ¯‘ýÍ`:ùŒBý”Îe:ùŒÊ»5Wùl·l6ÒF*ŸÊ\h•ܶã}l•|/ô½´ªŸÖoDgÑÊ9i”äs¾ò·÷ÒÊ9®ÊggÑÊ9éB¿ ­š»F©ïœo]U>'…6Y½z5}}}uóbDá™F}n|ñųaÃ&&& b€ˆ‚|·S·¦•y²yóf.½ôRúúúX·nP±Ö… ?¤™ö7ƒ‰‰ Ö¯_ÏUW]X½þBÔott4°Z^~ùåtwwóîw¿;xq§«ÃBÔOYÌV>Û-›Ô¡Ýò…ú)‹ƒZùŒÂ»5ùl·l6R•Oe¾4Snú}l¥|/ô½´ªŸÖoDçÒì9i”äs¾ò·÷ÒÊ9®ÊgçÒì9éB¾ ­œ»F©ïœo]U>'õ6‰Ú3âÜXåšk®aóæÍ1e¦:D}îÞŒ:ªAeŽLLLðîw¿›7ò©O}ŠO}êSÁ¾zÖϰ…k¦ýÍ ŸÏ³zõêÀUl||œ­[·²uëÖHÔüõª«®¢¯¯ 6°nÝ:6mÚ4cª~Jç2Wùl·l6R‡vËgTê§t.SÉgÞ­ùÈg»e3*m¨,NZ!· ý>¶R¾Û![­è§õÑy´jN%ùœ¯ü-ô½´jŽ«òÙy´jNºïB+ç®Qê;ç[W•ÏÉD½M¢òL£<7V¯^Íu×]Ç7¿ùM6oÞ½m»ukjP™#—]vÝÝÝ”J¥* ø/[íC,]3ío\sÍ5\sÍ5ŒŽŽrã7rã7F¢~}}}“,ˆáÿ§«ÃBµŸÒ¹ÌU>Û-›3Õ¯‘ýÍ`:ùŒBý”Îf*ùŒÊ»5Wùl·lF© •ÅG+ä¶ïc«ä{¡ï¥Uý´~#:VÍI£$Ÿó•¿…¼—VÎqU>;VÍIú]hÕÜ5J}ç|ëªò9™¨·ITži”çÆ›6mâšk® þ_¾|yÕu£ ßmÕ­5”º^©âúë¯÷Ö®]ëÝzë­U?<ð@pLoo¯wë­·zžçy[¶lñz{{½ñññ†÷7›Ë.»,¸^ê7>>îõööz[¶l þ_»v­wýõ×7T‡…n?¥s˜¯|¶[6©C»å³ÝõS:—™ä3jïÖlå³Ý²Å6T:ŸVÊm;ßÇfË÷BÞK+ûiýFt­ž“FI>ç+ u/­žãª|v­ž“¶ë]höÜ5J}g§>“(•6¹ì²Ë¼+¯¼rÖõkuý£>7–úI™Q×Û.´nM *sàÊ+¯ôV­Z5é', ×_½×ÛÛë]vÙe^oooÕ ×ÈþfSûbE¡~×_½·jÕ*ï²Ë.óÖ®]ë}ìck¸ Ý~Jç0_ùl·l6R‡vËgê§t&3ÉgÔÞ­ÙÊg»e3Šm¨t>­”Ûv¾Í–ï…¾—VõÓúèZ='’|ÎWþò^Z9ÇUùìZ='m×»Ðì¹k”úÎN}&Q&*m2•A¥ÝÏ´æÆ"+r(ëmZ·¶Äó<¯©þ6JÀèè(£££tww×ušiÿ¾P?¹FWW«W¯žUÚÝ~Jgõw+êò…ú)‹“Nx·Úýý˜Oß•6Tóyç¢ö>Χ® }/­ê§£öL”ù±XÞ…ùÊßBÞK+ç¸Qz&ÊüY,ïB'}gT>–¨·IÔŸiê·uëÖ VÔå{!ÛP *Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(3 IéEQEQEQEQEQEQf@ *Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(3 EQEQEQEQEQEQ”PƒŠ¢(Š¢(Š¢(Š¢(Š¢(Š¢(Ê ¨AEQEQEQEQEQEQeÔ ¢(Š¢(Š¢(Š¢(Š¢(Š¢(Š2jPQEQEQEQEQEQE™5¨(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢Ì€TEQEQEQEQEQEQf@ *Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(3 EQEQEQEQEQEQ”PƒŠ¢(Š¢(Š¢(Š¢(Š¢(Š¢(Ê ¨AEQEQEQEQEQEQeÔ ¢(Š¢(Š¢(Š¢(Š¢(Š¢(Š2jPQEQEQEQEQEQE™5¨(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢Ì€TEQEQEQEQEQEQf@ *Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(3 EQEQEQEQEQEQ”PƒŠ¢(Š¢(Š¢(Š¢(Š¢(Š¢(Ê ¨AEQEQEQEQEQEQeÔ ¢(Š¢(Š¢(Š¢(Š¢(Š¢(Š2jPQEQEQEQEQEQE™5¨(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢Ì€TEQEQEQEQEQEQf@ *Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(3 EQEQEQEQEQEQ”PƒŠ¢(Š¢(Š¢(Š¢(Š¢(Š¢(Ê ¨AEQEQEQEQEQEQeÔ ¢(Š¢(Š¢(Š¢(Š¢(Š¢(Š2jPQEQEQEQEQEQE™5¨(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢Ì€TEQEQEQEQEQEQf@ *Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(3 EQEQEQEQEQEQ”Øg *ù|žR©ÔîjìÓ¸®K©TÂ¶í¦”ç8ù|¾Ý·¥4•ÏÎÅqœIr­²¹¸Pù\\4*Ÿ¶mãºn»««Ì•ÛÎ¥^¿*ÛUv*Ÿí§™óÒÙŒ{U>£Êg{™«lηïT¢‰Êãâc1Éä>cP) ‹Rûûû›f h%¶mÓÓÓC6›e``€d29ï2Ç¡P(´ûÖ”&°å³Sds>¤Óiz{{'ÉµÊæâBåsqш|:޳O·Ñb`1Ê-,~Ùª_•ÝÅÄb”ÏNzïš=/mtÜ«òÙ¨|¶¹Êæ|ûN%º,Fy„ΑÉV°˜dò€vW@™¥R©#V¹ J¥H¥R¸®Koo/…Bx<Þîª)JKèÙœ+ŽãÍfÁ4M\×eÅŠ$‰vWMQfd±Ëç|iÆ¢Ei‹Yv§ëW-Ëj¨ •]¥]t’l¶k^ªò©´‹N‘ϹÈf3úNEYh:E&•éY´*…Bžž–,YB2™œô²Šõ{ÅŠ¤ÓiÒét`!´m›–,Y|Ä…þþ~òù<+V¬`ÅŠäóyÒé4+V¬ §§§Êz:›c§CÊ ×¨ú݈u3\ŸR©4ãÿ³)oºû“E*•À0 FFFª:Æz÷hÛvðl¤Ìé\ÃÂÏq6ç) O»å³Y².«¶¾0wÙ¬·­Uò9“¼Lõý‘gfFð[±µ„ÛDå3úL'ŸÓɦì¯'Ÿíè;Ãe5S>‘×FË›lNusí;Ãÿ[–¥“Ðc>ýªìŠìvú¸w®²;›~UÚAe·3h÷¸w¶ÇNG§{gš—Nõý™MßZ+›²Må3šè¸·~Í÷6zsÕͧïÔyiôÐñìÔåtÊxvŸÒãz‹‘‘ð2™Œçyž—J¥<ÀK¥RžçyÞØØ˜g†788èy‰D¼b±ì“s‹Å¢g†722âyžWUN&“™tX,Ôc6ÇNà% ollÌö ÃðŠÅb°Oþn¤œX,ÜçLÿ7R^#÷—Ëå¼X,üŽÇã“ê\ï³ÙlÕvyrn±X ®‘H$<˲‚ã¦;Oi/QÏfɦ”UO>ç#›õ¶µJ>g’—é¾?‰D‹Çã^.—óâñxU™õd³‘ë)íe:ùœN6=Ï›V>ÛÑwJYÍ–ÏFäu¦òš!›SÝß\ûNÏó¼ááaÏ4Moll,¸%ú̧_ ïŠìvú¸w®²[,§ìW¥\•ÝÎ# ãÞÙ;>îi^:ÕýM'×Óɦç©|F÷Ö/£™ãÞFïq®:£ùô:/:žºœNÏîKzÜEiPI¥R^"‘¨ÚfšfÕKy ‹Å¢—Ëå<˲ªÎM$Á¹a”<ððÿµ‚Øè±ÓT Fx 6[A”x#ÿ7R^#÷'BéåÿÚk×Þc6›õ ØòÙÊ5‰„gFUÇ8ÝyJ{‰‚|6K6¥¬zò9Ù¬·­Uò9“¼L÷ýI¥RÁ³3MsFÙläzJ{™N>§“MÏó¦•ÏvôRV³å³y©¼Fî¯Yifß966晦é Wµ•}æÓ¯z^ôd·Óǽs•]#×ëWÃ×PÙí,¢0îí±ÓÑéãÞ™æ¥SÝßtr=ݸWå3Ú踷~Í÷6zsÕ͵ï”}:/:žºœNÏîKzÜEò˶íÀåO0M3øÛuÝ*wÛð±Žã`Û6K–, ~¢àfT{?s%Üüß,LÓdppX,F&“!‘HLj×z÷XëmŽãÿ‡]ÚÂîr3§´•ÏúÔ“½…’Ï™ä¥Þýåóy …ÃÃÃd2FFF°m›l6 L-›\OiÓÉçt² û–|6"¯Í YiVß™Íf±, ×uƒ° ¶mï³ ;‰ùô«MÙíôqï\d÷{ßûÞ´ý*¨ìv":î­O;ǽ3ÍK§º¿éäzªq¯Êg´Ñqo}Ú5î‹Îh®}§ óÒè ãÙ©é¤ñl#ç-=î¢LJßHlÒ©ŠaÄb1ŠÅb»ocÑ‹Å&ÅòkôÃRûœjc(Z–E.—Ã4M’É$ÃÃà §´•Ïè1yqÓ4«d9‹çÖ“M9Vå3ºÌ$ŸÓ h¦“Ïð¤Fiœ¹ÊÊ\ûN×uƒgå8…BaÒäE‰óéWAe·ÌEv~øáiûUPÙíDtÜ-Z5/nÜ«ò]tÜæ*›sí;u^=t<=z.Úiò¸(=TLÓ$ŸÏoÛvÕÇ9+D€Iû«F\×¥§§§* 2;,Ë ¬Åà·i¡PhÈŠê8Nð|ä¼X,ì—Ž0•JašfÕ`uºó”ö¡ò=æ"/"×òœä¼pB@˜,›s½ž²0L'ŸÓɦìWùl.s••¹ô™L†b±üX–E&“!“É´»”˜O¿*ûUv›Ë\dwÕªUÓö« ²Û‰è¸7Z´j^:Õ¸Wå3Úè¸7:ÌU6çÚw :/:ž 9ÏõÚÅ¢ôPI$ضMOOOðaŽÇãÁ~˲ˆÇãôööbšf•ÕË4MR©ýýýÁ¹±X¬êü(aš&étš\.ÙU.†aÉdèíí%‹mšH$º¿d2‰išÁŠøT*U÷X¹ÆI'4«ó”…e_‘ÏNÍp]g+/2  ?G˲H¥R“7"›òœT>£Ëtò9l‚Êg«ê9Y™KßÇ#ÝÊÔ̧_•ÝVÕs¶²{ÁðÈ#ÔíW롲Ûè¸7Z´b^:ݸ7Êm¡è¸7JÌU6çÓwJÛè¼4èx6z,ä\´õ¸Kʉd%¶mî´a µëº+‘ëºÄb1–,YÂØØX•ëŸã8†é\êY{Qd¶mZ*•Èf³‹EJ¥RËÏS–Å.Ÿ"›ó•—…’kea©'ŸÈ&¨|6 í•Ù2Ÿ~Tv›ÅB÷«Jg ãÞh¡ãW%ŒŽ{£Ã\Ûs.ç©\GÏFƒ…ž‹v¢<.JaªÆw]—þþ~±,‹t:M,«z‘MÓlYbŸ0ŽãL›()‹Mëâ$uœ.&àLe´¢^SÕu®m:W7¯(»‡íëD]>›!›bYo¦|¶B6ÃçΖvȵÒzêÉg#² #ŸÐ}§œ7TÆö-æÓ¯‚ÊnTdw¡æ Ê¢ãÞÆÊiv½fªï\оuñ¡ãÞèôsmÏù>•ëè ãÙÆÊhE½¦;o.,ö9ì¢6¨L…išär¹àå5M“ÁÁÁ¶ÔE'MW×…(c!ÊœKæb‘ìK¦25Q‘ÏfÉ@³e©å-¤¼¨|v.Q‘MØ7úNí•f¡²»0õ —¥2¨4JTäs_÷Χ}T®÷-¢"›°oôí@庳P™\˜z…ËZȹh'Êã¢ù¥(Š¢(Š¢(Š¢(Š¢(Š¢(ŠÒ ökwEQEQEQEQEQEQ¢ŽTEQEQEQEQEQEQf@ *Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(3 EQEQEQEQEQEQ”ØÿŸøÄ'ú¢ضÍÄÄÇsLÕ¾ÑÑQ¶nÝ @WWW»ÛGQö)¦“MPùT”v¢ò©(ÑEǶŠM´ïT”è¢ò©(ÑEǶŠ2= nPÙºu+—^z)>ø ›6mâÞ{ï墋.`Ó¦M¬_¿ž|/}éKtuu±fÍšv·‘¢ìL'› ò©(íDåSQ¢‹Žm%šhß©(ÑEåSQ¢‹Žmef–xžç-äc±ëÖ­ãòË/gbb‚K/½” 6pñÅó‚¼€«®ºŠ¾¾¾@€K¥ÝÝÝS–÷_ÿõ_œ|òÉínGeæü#–eqâ‰'¶»*ób:Ùf-ŸwÞy'÷ÜsG}t»oMÙ‡¹ï¾ûxë[ßÚîjÌ›fËçw¾óŽ:ê¨vß–²³sçNººº8ÿüóÛ]•y£c[e±¡cÛúòùàƒbÛ¶Žm•¶¢c[Û*ÑDǶ:¶U¢K+ƶ,ä 1>>Îå—_ÀòåË)•JÁ¾®®.úúúX½z5«W¯fhhˆuëÖMYæµ×^Ë«^õª…¼Yñýï?ÒõÛ¶mÛ¶m‹ôG?êmxÛm·tô¤s:Ù”ý³•Ï¡¡!~øÃê»5n»í6V®\ÉÊ•+Û]•ºtÊ÷£Ó'­Ïý×åå/y»omJ:åÝÒïÇÜÙ¶m@¤Ÿq#ì‹cÛF‰ú;8¢.ïÒè3ѱm}ù´m›ÿüÏÿìøïì{ït'Ðè3ѱmgŽm¥ÆÀ²X¾3>ÛN=¶Íd2¼óïl÷­MIÔû’Nø.D]Þo¸á^ÿú׳aƦ•¹ •ÑÑQÖ¬YæM›Ø¼y3Ë—/gݺue³Ö¢ÙÕÕÅèèè´eyä‘ôõõ5¶nÝÚÔÖl†††Št£Ü†CCClÛ¶­ãWªM'›ÀœäóÌ3ÏdëÖ­\rÉ%¬^½ºÝ·X—(¿[7nŒô÷-Ê߉‰ ¶lÙ‚mÛí®Ê¼i…|Ê@¸»»{ÚÕDí"Êï– ß¹3::Ê~ð}ôÑvW¥)÷²¯m%Êïàl‰º¼7J#ÏDǶSËçÑGÍÊ•+#=¶m”}éîfz&2¶ýå/ÙîªÎ›}qlÛ(0n”Åòiä™èØvú±íH__kÖ¬aùòåí¾ÅID½/é„ïB”å}ëÖ­üøÇ?æˆ#Žhj¹ nPbùòå\~ùå ñîw¿›R©Äøøø¤ãéwîÜÉÐÐPd_üë®»®ÝU˜–(4„(·¡L:;éd³»»{Îò¹mÛ6¶lÙÙIg”ß- ²’åïÇøø8CCCìÞ½»ÝU™7­ÏÝ»w}g'Q~·ý~ÌIdÅ Õ\îe_Û6J”ßÁÙuyo”Fž‰Žm§'êcÛFÙ—ÞéNa¦g"cÛ;w¶»ªóf_Û6J'Œe±|gy&:¶žc=–¡¡!º»»#ÙFQïK:á»eyß²e ‡vgžyfSË]Pƒ øÂvÕUWþK111Á¦M›èêêštìèè范Õc=6ò/¿²xÙ°a7nlw5šÂT²¹aÆ9ËçùçŸ?­ë§¢´Šîîn6lØÀÖ­[Û]•¦ÝO3åóˆ#ŽÐ¾Si2!jwUš‚Žm•Å„Žmul«DÛêØV‰.:¶Õ±­]Ö­[7£Õ\Øo!o¢¯¯o’5Rþ_½zõ¤ïèÕŠÒ)L'› ò©(íDåSQ¢‹Žm%šhß©(ÑEåSQ¢‹Žm¥1Ô ²fÍšÀü8 ›7o¦»»›¾¾¾Àüg£££\rÉ%ín#EYôL'›€Ê§¢´•OE‰.:¶U”h¢}§¢D•OE‰.:¶U”ÆXÐ_Ë—/gÆ \zé¥ôõõ1::J___à6½aÃÖ¯_Ïš5kزe 6lˆd|=EYlÌ$› ò©(íBåSQ¢‹Žm%šhß©(ÑEåSQ¢‹Žm¥1<‡Êºuë¡ìêꪊµÞ×ÝÝ­ncв€L'›µûU>eaQùT”è¢c[E‰&Úw*JtQùT”è¢c[E™™7¨Ó ¤¢´™äOåSQڇʧ¢DÛ*J4ѾSQ¢‹Ê§¢DÛ*Êô´Å ¢(Š¢(Š¢(Š¢(J4I§ÓUÿ›¦I<Ç0Œ`"‘À4ͺççóyLÓ$‹`Û6…BÃ0H$AYŠ¢(Š¢(Ä‚&¥WEQEQEQ%Úd³YJ¥¶mcÛ6ù|žžžÇ öËßõ( ”J¥àØþþþ`_©Tª*KQEQ”ÎÀmqù¶ 0~ªž>=ÅöBÁ/Ç­9×fö”ÊõhjPQEQEQEQeZ¦ ï5R©‰D¢î¾t:MOOK–,a``×u±m»ÊËEŽšt:M:fÅŠôôôÌÉð£(Š¢(ÎkÊÆxG>W‚‹“•ýÉääsÜÜNlüršô ”¯!§Š!DŽÍ–÷Õ+ÚajC‹x¨dñ..r W®W6ÜÔz±8@Oèÿ|ùüB‹ÚYs¨(Š¢(Š¢(Š¢(ŠR…ZÒZ*•(•J‹ÅY—“H$ cYñx|JãŒäZ)‹†A2™$›Í‹Å‚bác%GK6›%‘H022‚mÛ TåpQEQ”NæŸ ð¶|¹Ü~4À ¤Ó°¾×/†§pÒ°,»øµ WÛ°Ÿ —Ùpœ Ç/ï%ýpç°o”H{\ؿ߭{#Í^¾’†’ VÑ¿v¸Ó]nõ±a¯Û†æáí9ÿ€?KÂId2¾‘& $Ð\jCÚ†ï8p!ÎÀhÎv!Vn ÛöÿΖ¯ ƒÎ0¾!¦¨AEQ¥ Ø€A¥#QEQEQölÛÆmdIh 1MsZ¯“pa.uÎårA$›Í’L&‰Åbd2,˪:6œWÅ0 &Õ£Ã0ÈårÄb1‰…BA *Š¢(JGñ6üÔ ßPñÁü¤; ø-àÆa‹w•ÝC>gÁ/óð€ c6œƒ1ßEÃ…ÝYXiÁ?–à úãðUà¼dû`û†‰×·`‡ ŸÉCéµ` ÆÉ<‡»C.&YàkXå!B _ßeSÑy•JðÀ³8Û‚ãØêÀ„áw¹ Ï/Á÷‡áïó&XQò 7˜poþ/‡9pB þ2ÏÚp| nö¯™ æ+GEç¶kÙ²¦?'5¨(Š¢,•Î$‹ßAºøùT»+§(Š¢(Š¢,¶m·=){,›Ö ’Édª ù|žþþ~ÆÆÆf}­xÏäa… —˜pãäRp`Áß–0á6ÎÂvâq?×_ž Ÿ¶aµ çÇà{ÁR >iÀ¿¦à£8HXþÿz½~ó^xí¿>'¹p· { ðª8ØØeÁ8𜠫-?¤ØxN5à ÀÉÂá 8Ô†=%¸Ý†°Ô?¤`7ðŠ,¼Ó€ïdáð3á‘=ð&ü†¹Ï†^ .ŠƒU‚üý°ÿé`°¥à–²@øEJß@#£—C Püí‹Y{ÞÓM}¶jPQEia/”4þG¾HÅQ¬õ&~b/± +Š¢(Š¢(‹›©ò‡DÓ4gí¡R*•H§Ó W•“J¥&åD$y}©T"ŸÏ“L&ëU©ZãT»½EQ”hãR­x—mPÑË„ņIã/Š {aÔêrÄ "½½ ü¯ _)gÁÁ|2fÊ?÷ßl¸ßçl¿N…rݶdá.6a§ gO• ;ïêƒï¹ðž8Ä÷‡ä·àÊòóŒ Js|ä×ð›ÃO> Ö•PÈ„ýÜ«àà‡yø›²¥Ç} V¼~ûO°ûø• §¾Ì2ÆJ°'{ pkÙ%ä ì2à«YûRàÈ8ƒ•.ü܆dnvaÔÇᣖï)sO ~êú¡¾˜€ôõ~›l(ÂE&ß‹&õ<ˆ}Üô—à£Eø§xG *ùú¶Ïû¡ÀŽ6à'7ŸïúMSß5¨(Š¢„p]×u«Vë½ý†X±cÿô®wÛòøpßÓD°ËÛdåÀHy{ßý°Tþ[¶%ð?úýø—FŒ*2elFÈ0Ç&æUEQEQ®ëÎ)„–išØ¶M>Ÿ¯2"•J¥ºeI¢ùb±H,Ãu]Òé4†aõï“ZƒŠ”)uíD£•¢(ŠÒ$:ˆP¢b´ýÅ*SÞ/‹bI´ž/Ÿ'Fꇊþyöœž×ÛôuFýÀ36xø—ìŒÃÁyØiúÞ¥áHÓÏ'b|–¼>lBr+Œ½NüSxü*¸áGü30ÆÁ|~ú=àíPø>¸øFJ`âçüðNø‡¯ƒã«pËQpØ¿C6 gÅá ž+w«±Uð›.xæð²׆ã2p€ Ϙþ=ï±a¹ç'üF¸Îž¸¯cڜߙ~;@aÄ/g/ôöúá¿dL`zËk,Ü«áàçÃ!6X²|å½bÿêÿí8p” ¯7á£Iß#çåérÒû¬þ+pÄû&šþ>©AEQ?„eYô÷÷“¯l6‹išôío³ãöÛ¹Âq(™&iüÁ¡§1MÅUSÆï4î/A yÓ_É o¹O Uþÿoø×qC:ô¾‹Y>¶¿\‡ÁÐu]fo`q]¿3ñ;[EQEQE&yHÞ“éö×&­7M“\.G:&ŸÏcF`‘ü(a‰½½½ôöö†ɵbY½½½Á§p˜/Ó4I&“˜¦‰ã8Œ¢(Š¢8@’Šq¤€oý‹Ÿ¼\"ˆÈþ0+€W:ð}&¬ŠAÆ,—¿­×8P4Átáì…䘯ÿ±€#ßð˜ /u}ïo'á¼ÜïÂvÛ7À Ú \ ¹$|n,;¾ø9(|V>ý4ŸÞ¾oÝKáì¥$à>Ö]•´Ž£â:S3 êï¶¶Á®‚e`®„ׯüûµÿì>(üÞp1ìZ ¯ÝÙå`àyˆÁ¿äa4çì“VÀÛ^ä3Òi±n"\œçÂÍ ¿q H|¸œÈÞ„7¿by‚ÕÂÃþŠ“‡¿=¾š.‡jˆì?#îŸâqÿDz|V2Y®CÂ÷RŒÁµ#˸gÏ¡ô5ñRƒŠ¢(ûpÑE÷pÿýÿ†ã8Äb1Òé4©TŠw®_Ï/{÷îåÇãã,¿çÒgÅîƒÆqò¦É0þ7_¦%*³ÚnãYpRð@ž‹ûn‰1ªÝJ“Iÿÿ.V/ ùÆéÄM*»ƒody³½¦¿}¤æš%üóe sͰ'J6ëSda_>ﻃÊ>Çñ;'€þ~Èå*å(Š¢(Š¢(‹Ïóæµ?lXI$$‰ ±¼a“rž¦i266kYVà2<<l{·”J%LÓ¤X,R*•¦-_QEYü¨,^-P Í%PÉi[(™¤²`Õq`‰®×àtN-Täœ"°6›ò°×…Gmð`…§à_-øœ N n,À_eàËiÈ< Oý)?õîvÈõAÜð=Pz{ᢣž#¾ºF÷²ÓÛCüç‡rú±¿ç‰ÿ[ÉOwÿˆÏœ‡iöÀX¦Ÿ£Í*Yò½>ÿêÞ·±ä¦±òÃW€7õýýø¿¹ü20^ÿû|¦N%= ùÏø‰èSÀW\½ìÀ<N;ʯg6 ^Ü;!Yëÿùçó àžrã•òPHT⣅ydûϸЅë-ÈøIí­r,ü·¾a)L\ÂÄøCÂŽ¨ñ¸ŸøÞ0@† ¦é?Ã?¿ï÷üç7õSƒŠ¢(‹qÛ4˜Óu]¾ýëý(¸‹÷½é|,àT*áÆbüÛý÷óÜg>ÃØà \|1oþòrîMY8ÀŽ+øËcŽáR*« àÅJ0Xþ÷öÂkŠ0æ@º‡¹¾ÁäiÆÊó:ËÇ­XïÃF>œ€ï9¾kh–ŠÊ‹\øìÄ2ð.œŸ…lÑw5•ûÍGöÀÇ2°Þ‚ÝIX“ƒpºéwz##þ5óyôK©|³äÿv]8!îZ(ÀlxMÜ?þÕ ¸ p˱8³Yÿ˜ÁAÿ·mûW¡à—£QEQEQa6á¦:v¦2f’LQEY| bö—Pìb<‘Ð_’?ErÜž_ÎSr/~ÂóÕ.ü¸o²á´˜oHxÐ…#mXOÅ(càðŠäm8Ï{M?©ûçsNÂ%qH–+’º³ý šOÁàYÐûUˆ½ Ü-`|^yêïvåØcïä¯âŽÛÿÀÊ»Vrà«Ï ï¸>vmÛÅ5×pú•§óþ¿Ÿ/_‚¤{Ó\sÎçxúûÛ±n°ðæ¡§¿ƒ±4Áï¿ù{.úùõpÇÕœ=~»þ}Ö!ËýFÈCfú¯‡ø%øaR ¿‘;ÁÙ 9Ó¿iéj­0øb|¥U2/¢âú³Ÿëÿ+? ë" ,³ütN2!fU§ü2Ì"¤L|ëT’ѸøÊ¯0e/˜X/«<ä”åŸä+Ç9üÙg›úŽ-¸Aett”ÑÑѪmkÖ¬aùòåUû»»»éîî^èê)Ê>ËL²>&Šò)+l*q-%L–Sþ;¼÷¶Û8lÕK¹üÓgs½y6/.@á¶pÈßÿ ÷lÛFÆuùøÛßÎY<‚†lÊÿοø§?å¨;î ów‡ëúƒ1þ4æýNZŒ#»³ð¥¬otxe~†K‡á#À÷’P°|ãƒY6r û†odYí@Ö„ÇÓ~¹‰üýìÜù[þøµ#ÙÿÐCy`Ë·9ãŒ#Xúg/äËÛŽã•9¿Ìµœl쇗˜ðòÿ’,Ÿ÷ËËd|“‘¿ÝÒqxCŽpá«¤Š°%ïZ^9'äá³e£É)øü¢˜_F>ï„r9¿þ¥RÅÅRžØ¥JÇNâ¦ÌL§Ë§¢,ftl«(ÑDûÎ}õHé%ºtúØ6ªË%pftùPɇ+¡Ü]àÙ4œnÁ6¬ÄløŸ³–;úï þƒ÷üì"þzìËüöM·ð¯îâ­ƃ§ìÏÈÈóx·»ø#w¿â\wÝu<ýôÓ¼ÿ´Óxø»ßååÊæʶÊêÿ†Ÿ­ȼ•JlùøÊ±JeB k–2[nÌ••³YàŒ8l³![a’ó]U†þú{t/9ŒÿŸ½w“£ªóþß!@&©MBj¸…DÍR#àâ¥Z.ºâ‚Õq×yVºw]]Ü}ò³ûÙ]qÅU»4»È²«ÛnP×KºÐ.u§!bœ‚8„Sd 7Bèß§OUuOÏLO2÷œ÷ëÕ¯é麪îSçÔ÷ó½`,J”e‰--¼[‡Àç…5ó9öæ;awÀî×}œc÷_À1Ï<;(fD{t„˜"…iK*„pàj8p€Þ—÷V½‚Ç– TjÊ$6làºë®£³³“žž.»ì2:;;§¤â©PÌ4†ë›0õúçŸp‚ Ÿ1àéjèä÷ hÞ ,ß¹“­ÿøxžÇ[³Ͼ‘Çù Š_{wß]&qáXþê/¾Ç}ÝWòîw? Àõóç3ëL8· Š…½q¾ãŽ‹ÉçÅ=¿TcÂòB<9¯Gèz\oD«¾Ö>ö?Ñ6aÛ6v®Ÿw¼cwÞùM‚àW"Ç¥aàû>¿ûݰý³ʹ?€ùÕ üÃ?lÁuÊÖ­ÏrõÕo#›ýçŸÿ®½v š¶„?ùñ“ô¾ú/]{,wþìTR˜f™—ëðcª¢¼:xdSµ©¸d˜êrv¿ñ —ŸÛŒxLÌhð´7„PÕoÀ“û¹ô/¯¡uýÍÜÏlÞg‚a gÏ[pÀ£uYïgG8‡‡>û|‡Ëø¿þ5ß|àî¹g _?Å`¦[ÿT(Ž$ÔÜV¡˜š¨±S¡˜º¨þ©PL]¦ÛÜÖ!Îe#œC"’ÄÖäaaN¤ñ’˽˜™8U¼aˆµ²ÇÃÀj VðXAÎ2Áýè‹ oçóœh/ ìÿál‘åB … ¿î!½o!¯ ^ů>õ+^öÔj4íxŽ[x€?¼ôÖ¸k˜Ãö³Ÿ[çßÊ,;sï~øÝ|rÞ'éØõ( vþœ·b .XÀ–üMÓhoo缇Σõ­ ìY³øúÛßÎkz%¿ß~[¾6‡¹/ü>u¡¨¯–1s"g½ü¶eJš~ÄBírx¹?-rà»wsúÇ®äW{ß3æ¿»£&ú‡ÞÕÕÕ°£uuu±pá¨îZµŠU«VÑÕÕ5ìþžþù×Q(Æ‹®®.¶mÛ6Ùͳsj<Ôþ¹mÛ6zzzƬð›®ÈÃ16Ìöa– Ç–áª2,µà5àû|ùœs°,‹r¹—r¹Ìš5—qî¹Çð/ÿ²M÷sù÷ßÿýœwÞ<Þô¦Oãyà»P®¦·úÇ4¸|ûÛôõ=_Â0MqÏ®ŠìÑÿ^8ÀÜA>Ÿ'›Í‚Ӽë-o! C4M#öìù[®¸b>™L†ÞÞ^t]Ç÷EpêÁƒÙ²e'—\r¹\]×q‡L&âE‹8óÌ¥TksröìÙ<÷ǰw÷ã|ík«p]—Gï»O´ èÕáÂ’˜h,6¡ÓQqÑÓ 8ʇùx·)D¯º=Õu·¿úŽ“FÏç¹/ÿ,k~ücŽÿ?ÿ‡-¯‚—~ô?¸ÀÃ;v°sçN~=ë>ÀÛò-Ž{Í‹ó ç>ð{6ofËÁƒøaÈË^ŽAÈ¢þ~>¼{7'~ùËB<lÛfû¾}¦òhNõÅÕ6F›[ó°xÔ'¾ò¾÷qôÁÿeß¾}ì[õQ>í…°«Z¬WÓÄu¬¿Í¡í  RMo’ϳ{ÍlŸÿC\ËâàK;¹ð]BÅd}K ¶m“ÊfyþŸþIˆ&÷¶CÇ,øv5)›/™Ÿ½ :\óôØ®­âÌ[~1æ¿» Tdç¹úê«9ýôÓyík_˦M›èééÔa.\8‸{÷nõЩ˜4fÊCçp}½nÛ¶Í›7I]„Qÿ/òð¢çWë€ü´,"/>¡Á?›ðÒwvñ]«Ä»ÞõkLÓ$†tÚÀ4Å}\¾t]ˆ Vu°Èd¢û;¶-^¦)îﺕÊ"N9åF ñY6›%ÒØvZ'Àý÷ß̽÷~‰ þÓ4 Ã|>¦i”Ëe …–eáyAÉd¢Â™†aVGôË/ÿ/vîÜÉòå"G©®ëQƒûî[ËYg-Š®Ëy«VGöß¼÷½+£H—½{÷â!„xC5-å %Ø_Mé¥!¢"C`… VþÔŒ£Dd}“PtßG×uô0¤·»<ƒoz´µ¡û>›þðîyúi^|úilσ,{埱í/pìSm´¼yûáqô÷ŸÅì¿ècîIû˜3gŸú÷“xùIÛÁƒ;ïÜÍüÇ ¤ÓiÇáPÙµk׌TÆ£ª‡NÅdÒ××GOOû÷ïŸì¦6jn«˜i¨¹íÄÍm§:ù|¾æå8Nu®/‚`ÈíÇÁKxÉø¾í˶íš})FFÎmwïÞ=ÙM9lÔÜV1ÓPsÛææ¶»ví—6WÍü‘°¢ «ÆŒ pT ìùxµ²¶-ìó®;Üær"hÂÝÚ °â©g8kÉQ÷v6\qÒ lØ4KïcÏ£{0g…¼áõ_çá7üˆYßžÅÙ¿>•Îú-;[ppxvÖ³¬|z ¤`ÙŽ‡yü¯óÓöŸ²³e'Ë>ºŒÐ¹ø/.æ3 Íý}?–e1÷}ïãôcŽáÏïú.û»ösðàÁÈ>ò‘t²mþ] lÝÊo_ö2¾ì±,8p€–5kH—ë[|kÍZÞx/Ǭ½L“Eû¯úÕ¯xÝÕWóbµ8ûöóÎãß—-£»¿ŸÍlÙ²…³N> Ø¿Zü–ïýÌgxèk_ƒ¢Í¦—ÿøìgiooÏ÷!—ãÉ[o¥\,²úïà‘çÛØ³}3{óþâOá&h®ë2ðÿÙ,{qŽz„;ïz/ét|Ÿþ“OæÅð›|ë3ŸÁ0 ž.߯_ØÉC+ÿ”ý×\C©TBÓ4¾ñÔSøº?+‰/kSÕfTµOaYP.ãžça?]Öʼ?<4æ¿» TúúúèììäÊ+¯ä‘Gáºë®cÆ Cv¬fBÆ/^Ìúõë'ò4Šˆõë×söÙgOv3›áú&pÈýóì³Ï³|š.°ßëÃ+rð6C ‚º.D 1X>x÷#,:úimmRH™â^# Ô# Ê‹"—eÅ©»LS|~Çßã­oý—_~/…BÃ0ð<ß÷Ù¹óò(’Ä4ÍH<‘Q&¦ibÛö <Ïš—g¿ë®/pÉ%’ˉÿ-ËŠÖ?ùäE5)»–.] À[O8¡f{{zðÝßÿ>!qJɸþLáás5¸RCeÍê6T·3€s¿÷=LӌںûñÇiiiÁ®½új¶Ï›ÇsGÍyóæqÚ9çpÔ†^|i¯<«ëCGó¬ NìÜ3‡s63¯}¯¹àv¼ô'ì>÷(ÀºuÿÁoûGÂ0Ķm‚ À¶íQÿ^ÚÚÚX¿~=‹-“ßßd2ýsÑ¢E¬_¿~È4 ÅxÒÙÙ‰eYüñ“Ý”ÃFÍm3 5·ž±œÛNulێ渾ïã8íí푈"çiCáºn$¨Ø¶M*•Š–yžW³/ÅÈȹíâÅ‹'»)‡šÛ*fjn;–¾—÷qÜþã¸kå]|þ„ÏóÒ—¸nîuüDû ¿™ßu .äéãçÖ[o%›ÍòÕ¥_eî?ÿ3{Ÿx‚»ÛÚ¸ÿì³¹}öÓ´>û,¥R r9¶}ÿûÜqÇ<ýoðíûîã†Y³øî™ñë×<Ãsü#iÛ&Èd°m›uëÖqíâÅìüô§™ÿÚWqÌKÿͧ~5Ó4y|÷n6â,¼ürN<‘l6KÛðÖϽ•§ÿùxþá1 ƒb±È7¾ñ Òé4¶ç‘ v¶´ˆL/šÆÃÿþïœü–· œ8<ÏÃu]ÞýºÏ³òÀœ1ÿ½Mh •U«V±qãÆèÿÎÎN.¾øâ(l¬ž¾¾>V­Z5‘MT(ŽH†ë›“Ú?}„—ÁÛÅûåÕúStÇq8þøóùæ7EdG:-„ÓlîX2}—ôL¨§»»›ë¯ÿ~ö³Q(|MÓÈårø¾mÛX–…ëºQÔ‰iš†‰)ò³b±XóY¹M.·>Jë%FȽÜtíµÕ¶käóyæ~á ì >õ÷—^Ê1}}mmè‰kª‡Ä&¹ßúÒž¾ï“ÉdÐu=zÀ¶¨Ö‰Ñ4ælÙÂÞ£fÅÊ•<ûì³¼tâýì_z>§¼â<ùuà%˜ãCËyRŸ<@¥´†yGÁKËW‚†¡±eK%ª+sÓM»Ù°a™LX#:ILåþ©P騹­B15QcçØP(¢y-@*•Âq &ÊÃÏç)—Ë5ûÊf³Ø¶=äW1sQýS¡˜ºL·¹­°GÈâò:" àOÔ“õ}‰q6ËBŠU4 î¾û6Ž9æbr9¸óÎWAÏó<¯~âK¶mãc÷ðð[xÿ¼÷3wï\44ÎÄî;ï$›Írý5×ðé•+iyè!foÞL¡T¢ÃóøåŸžÏ˾ûOì|Íjô¹sÁq8ê­oåü»îâ¦ßýŽ“Þÿ~Ü/™\¹ @YÓð}_ØNêmNÕ±ûmU[ €ŸÉðü׿ÎÏÞýnœs{N?ß÷ùùÀÏùWàÉcŽáÿøG>ÔÝͱ¶ÍÖÙ³ =˜3g;vì CÊå2_øÂ(÷•Y¼z1'ΞMùöÛq]×Ù½{7ºapÑu×ÑÝÝͶ/mÃßï㤼›nâ‰Nàâo~3¢¶išÆÿý—ÿËìÙ³ ‚€0 yðÁyæ™gð<]×yÃ'>ÁÓ×^Ë=÷ÜÃ'øC{ì1¾õ­o‰š+U1g‘±ˆoÞö)–ñooÂ#Têsζ´ÃçªU«…‰íÚµKS(&€áú&L^ÿÌ—Úp•ß*‹È‘oåÿ(¢áío_E¦ärÍ‹)Í`×^{5ÿû¿ÿ]cÜ—"C¡P 'ÃJ@ww÷ ý˜¦ÙPP‘_¡PhZ<¨ß‹|–,YBËΔËeZŸ}–Ûþó?) ¢R< ó®»FÜoñÜÚÚJ:& C‘ò«ÚvÃ0È‹[óöíãÙöv._ÎÜ~CÅžÅjàG Á):œ]„~âí,oiᬳÎbve„¢BÜ—¼ŽÝ/¾’§ÿ7{÷.åÖ[ç³oßUQ”J ‘#‰©Ú? …šÛ*S5vŽC9 ¹\ŽL2ì:ïûttt0kÖ,ÒétTg0ùyGGnbR(ÅžöövZ[[kR•IÂ0$•J©tc“ŒêŸ ÅÔeªÏm=¯ZûáÛ†,à‘¼X^.ßø"„`†ÂF$ëéÚ×€¾_ØŽN=u€§žúFdCÊ~®•ç÷?Ï×_ø:«¶¯âÌž39îÒãØ¶y½‹zé;½ æ¿@KK ¿^ñkV®\É[¾È¢þEÌÙñòz^8&»ÿt1'¿åd4à¤óÎcÿómófÖ´´°ò _`Ñ¢El`ÿõ×sÅãi–e±cÇYyçÌyï{! iY¾œ9ï}/ .¸€ýË– ›“¦!=r¥˜02=ÀñÇÏý÷ßÏk^óžþýïé}Ë[èîîæ/Ž9†/¾ø";—/ç× j÷Þ{/ÿ}ôÑœ~î¹´´´ð‰O|"rرcO>ù$_úÒ—X÷†7ðᘻï¾;š;<óÌ3”J%\×åC'~Ó2Éd2|}þ|ÚÞùΨíAD¬Åb‘¾¾>lÛÆu]N>ùd\×EÓ4LÓäïxË—/ÇqN:é$î½÷ÞèüMÓäSŸú{÷îóßâ„ *]]]\uÕUQN¾n¿ývÚÚÚèììŒò‚‚ÈÍ×××ÇÅ_<‘M<,êóÄ*Ó…áú&0iýóð*Øž‚㪡˜2lS†!étšŽŽr¹Ÿý¬H‰¥i0ÌrÈhš6èaÒ4M …B$ª*~µFÉhitšË[Z8iÞ»ßxŠ+Ø¿z?ÏfŸåØË)o=…£>wÿ³ÿï8ñ?ªa2ŽH‘-[VLÄ×3éL¥þ©P(j™is[…b¦ ÆÎç¾†ŠŒnéïïõ¾,ËŠDù|œN§éíí­YO:óÔ·#ŸÏr\Ôu½vN[7Ÿ^°`ATã0“ÉàyžªÙ2EPýS¡˜ºLå¹í€¿¯>ÂŽñ#;vÀ «è ©†À}`¬„Ü/aïë÷òû×Ãìßíá‹Ý'ó·Gmà­ÇïBGgïW÷rà'è^ÖÍžm{8¸æ æ.à‡+Húýi–ö,…w$”j‡Þ^¶Ýr oÛ¶Çn¼‘¦ÉÃÇDz/™ÿÏ÷ñŸžgœÁ¶³Î"µz5Aûìg™}ÿý´¬YÃRMƒ¯~@Œ‰®[[ÿ$9æ&ư±²!U*Þþ‰O Ÿwçýò—ܵb?Þ²%/¥èáy¯{Ýëèèè C2™ _ýêWyôÑG£¶H‡Û¶1M“ãŽ;Žk®¹]×éïï'ŸÏGëÊýÊ´aÒW !¾ïS*•jÎSÖ–Q/²NJ&“! C,ËŠê 뺉3ÝñQ¶Ÿ¾}L‹.¨Ã,šêƒe†´··“Éd¢ ¡ü¥r—N§£0ã¤*&¿dÇq°,kLsÐ*cÁHÅÄ&ªþ,ª«ŽeYÜrÂkÙ~מè{ ß÷£B§3©Ò? Å`¦óÜV¡˜É¨±sl©0šA¦ KÖ”‘&2MY3ûØ·oO<ñDÍçͤï2M32ÒHC‹bj ú§B1u™ªsÛ]><®x.ô—!‚‘‡”ˆLeh›cqå‚åXÿÖƒ_}‚ûgßOåñóXþÜË9maÈ7v}lè¹³‡òA6ܼ?øqžXó{xá/_àè®ïRþ¿ЖÂÕJ÷M×eö~Ķ%KX:w.x/‚DÖ=ny}Ô°®ë‹Eòù|ô¼+#Ì\ä³v{{{”éA:"f2:::¢Ï-Ëqî¬iZ”c}¦>?( ÅL&Ÿ)¼~Âöp¼ g” ôcƒë‚ÿ[ ͳè¹ExÜ|×_üis÷ÎåOããó¿d¸÷Œ8ûþ³álضs+÷¬D/è,]º4á)ZMµÑÑ‘8Ïó¯z›·mãè-[hyä^cšÜÿáã».ÿ¶q#¶mÓ–ÉðéªD¯•—Fþa˪5”Lp4¥ŒÉf³55K$ÃE‹Œeö¥d´ÃA¶I Aïþò»ÙsÒž1½fJPADùW!'pò‹“?9é”?ÀdT ¥“Ñ/ Å‘Ì/X6IJ‘TêéÎx‹©Ò›À²,òùüˆëËðÈÑ2Ü7”ŒPj"JÎ2Õ媟÷Ì›?ý)X:††±ž(Ïð\϶m·°råµlÚ´‚eyð ¨(…B¡P(ŠÃ¤R©Öò¤°"eû‘œ{ŠÅb”=iÄ) ‘£b½q§¾=ÉãÏ„z‹ …Bq¤â8`àC>Ì×`¿'ðœ/´rYˆ.AÖË€ýÐK7ç>.ŸúÞ±¼nÿJîyñf¾Ä—xû oç!â½+ß Ãì³gó»å¿ãŒ3Î`‘[ÂæçÂRŸÝRFl„!x{Ï<“ °ò#aî›ßÌÓ]]ÜöÙÜŸçFQ„ac›Öq¬Ÿ‰uÆ Ã`«¶•—žxiL÷«•QJ¥( ÑÄm¨Z}¸$–eE“G)ž˜¦‰ëº£ÎG«PÌDþükƒL^žçÍøè­ñÎéíþ½·õ2þ|ÞñŽóù;g«—t²e`€_üb/ûöÍš¸ ªP( …B1ƒp'ªu’DŒÇQEÞ …B1îücÖ–ae‹ !œ$ËÈ*–ÿó³yëoÞŠÍ…;.$‡Æƒ¯~àg³ò³½ù‹çÃXðñ㉌ §Â¼“O¢õÍ­â߇ÐLZ[[ùMr_G/fÿ—¿LÏ~À?T#Q’µPÔ¸85yàÜXpú‚1ݧŠP©Ãu]ÚÛÛ£{žçEu&ØaÒÞÞ>Ù—F¡WBàK¼èÇé#mÛ&ŸÏé¾@ ÄU#f¸ôbÙl6ò´8E"î'SÞ´|9 ~·jñ~—e ÷žãá]ŸÅúÎl]Žmïà¹çNcÛ¶mìØ±cB®¥B¡P( ÅLÃuÝèY8ù ‚€ °m{²›¨P(ŠŒ‹Èb"Bå|`£%´ß+ä.…¸ƒ½«ÿc!>úqvÜÉqËŽcùÁåÌ=ÿ ÞÚöZ44.ùð%¼gã%ðd(Œ¾‚•Ëä¤=&“JmóØcáû>{,–eñ™–N}÷»'ûò(&¡’ÀqlÛ¦\.“ÍfÉf³8Õ3ýýýÒY¨Ä$6N“Ëå‚×uUÑzÅŒåKìwàý™XPñ<0 Ãpø<”3„©Ô¿7uÌ«Áèð !&U’yÀÞþ·ð.(ˆu8þ•Ìj ¹àüÛ8í´—±eË„^6…B¡P(ŠC¡PÒÙg¤¢ô …B¡PQ¦Š"ì4ÀÏ‚–ˆa6ø¿…7¿°ŸWœþ+ºöÅ-/ÍáÙ—nåÕm¯æ«Ï|•«V^<|þÃh„Kt02àë±ñÉ4E!ן â½ïÓÿ±aU#3!K<(Ž,T„JÛ¶éîîF×uŠÅ"š¦ÑÛÛK¡P÷bÑ’ä„Õ¶mŠÅ"®ëbù|ÇqT{ÅŒäf.4ãÐÍ0 ‚€R©Dww÷„õÁ#ß÷Ç$ýàXÅéT'R&\e@!Öì `±³w¶Ä+kÐãÂQoxÿø2~ðƒ¥~ý …B¡P(f:¾ïGäÿííí´¶¶’ÏçÉçó5µú|ß'N3kÖ,:::pÝØE&•Já8NÍö …B¡Pü܇9>k¥är"xd÷»Y¾à ¯xâU´ü¸…c÷ïæ˜£A¯æÊ8ÿ¸óEÖgVÞ¹Rl,…Æ'߇|^T¶7M!¸Èå¾–…†¤Óé)嫘|” R%t]Œ¶º®S(Ðu}RŠI£f&“!r¹…BÇqÈf³Qˆµçyض]3¡¯ë£DÅx½¼7áçy–eÕôKÅø#ï…‡ËXe•-yÔ…·û` 8Ç€¶×Kk&^y¿/”±k×QìØ±l¯ŸB¡P( ÅLÁ÷}<Ï«yÉçB™Y! CR©…BÞÞ^Â0ĶíèÙQ.7 ƒJ¥B¡P ›ÍFõYdZ±îînÊå2ŽãÔdmP( Å‘‰ÜÂüŽÑDÐÄN¸wÞt'F«ÇûXÊœmsXrÔî?ã~BB|êÏÿÍóÂÓó×Ù¸ø¼$Æ÷}î¿ùæ(]j®ãº.{ñ 0ŒÈ6ëûþhš¯˜áŒ*åWWW}}}¬]»€žž6lØÀªU«X¿~ýdŸÏ!#£@¦AÔÔŒ°, £Ú‰e;=Ï‹jK躥“ë'÷¥iZd$•뙦‰išQ\Ó4‡4ZËI°¤··w²/‘b†ak3`V­çò!lªôÉ™ŠçyƒÒ8Lµ‚Û¢j*8ÙÚS€?Ñàö›ð¤è°;„Yó_`ñ1wŽq+ …B¡P(Æ<‰|&ˆi‹Uý  ÔûÌYo[¿º¾Nm>T^-ùë7:ŽôTYG¥¦ U‡'‰ã8†=ƒJ'Àä>’NЦibYVMQ{™Â0 5ÿW( E §àËa%‹· 8nÿqûæòóŸsöÑËÁgNÇ1¯¤d”ÐLiã4@:ˆFm @&ÃÛnã0Ä( xô§?eàþûù¤ã ë:žçQ.—'ûR(¦M *W_}5›6mâÊ+¯ ¯¯+®¸‚Õ«W³jÕ*n¿ývúúú¸îºëš>xOOmmm´´Ä)[úúúèë룭­¶¶¶ ¹žçáºî”ȃgét€b±ÔæçËd2躎®ëضeYär¹(˜Ü‡\î8š¦áû>š¦E¢‰ïûÑY¦+•J†©®r!cŽãÐÚÚJ&“‰&ÀŠ™G£¾ ã×?] % TˤÈPÿ‰ª]t$’ìëIÂ0Ae, ¬Úº,¦)Hëð°8ØâÁìwì†àÀ“Ýôqa¢û§B¡hž©2·U(µLɱs¨G©òï‡"3Â>†¢‰u†ª¡’Yê êô‚ À÷}fÍšUóy2 „ŠF?²™’ýS¡P“;·ÝÀü×I³h„ð…·vÁŸÿñÏ …Å€³.ìçU `Å›­ÁãŠT\Wt®ë¯ç¾¹s٘ɰwÆرݶyãÎÛׇQ­ë«ìŸŠzšJùÕÓÓÃm·ÝÆÍ7ßE¡Ü~ûí,\¸ë®»Žõë׳qãÆHTi)ÈlÞ¼9úlÓ¦M\vÙeÜpà \vÙelÚ´iB.‚çyär¹)aDÌd2X–E ½sLӌڙË墉¨ŒZ ‚€t:M>ŸÇuݨ&L©T¢\.cYV´]×éíí¥T*EŸˆH§Ó8ŽC±X¤··—L&ƒaär9ŠÅbš DÛ%#íSÖ×TžÝ1¦Qß„ñëŸ!¹nvõ™êk¸¨)Åá3Ôµ•kS‰jðI 2oêc §É³2pìòƒsÌ“Ýô1g¢û§B¡hž©4·U(1jì†{vÓ4 Ó4©T*5/eœRÀÌèŸA(›„bF2™sÛ•2Ç•:üuÕDá>÷Ýwçÿè|öìÙÃ÷wŸ[VÞBŽËV/cÅ›WÉdD]‰®Ç)¿òy¥¢iüÕcñºK.M£ô–·†!a2pÿýüxçN4Mò¬ÈªP$i*Bå¶Ûn£³³“U«VEŸuuuqÑEE*¥T&¥J9W_}õ Ï6lØÀu×]Ggg'===\vÙetvvŽ»7‚T¦2z´íé~Ë[h»àÌÓOÇ÷}lÛæ¾ólMÃ*•IÀäM ~+½Õ È"R,k°ª+£c4M#ŸÏGQ+¦iFQ,‡K6›òè& Ã0jcGGG‰#oš&ù|>jóP×Ðu]²Ùl$6)jiÔ7aüú§ÌX`‰€¬HPQ¿&‡ñHÇ›³€û€%‡Y AeÞ¼í3.ÏéD÷O…BÑ¥:“)ÉŠÅbtìdÁÄŽŽòù<Ùlˆ‹*Ú¶M.—#•JaÛvTFѸoÂøöOèÊÆÿˇ-ÅÄ" ˆNE‘Q£q5Ó«ã« Ÿ­æ?æœçhm½'Ÿ|Ï<óÌd7̘Œþ©P(šc*Ím EŒ;T*ŬY³½’Èú)ÑóZé0˜J¥H¥RtttDuTG6Ó½J¡P¦L–Y4d¶Ù7êEF…b:0™s[ðòðpv9°TÖ³aéÞ¥üÙ‚?cÞ¼yl[²³D]°¢>J€ãˆ_©xd³"Í@òâk^ƒïûQ‰騻iÅ î~ê©Éþ Sœ¦•… ÖtÛo¿ êDôôô°páÂa÷ÕÓÓÃí·ß.B°ê>¯m.\8b ±­[·²nݺC¾¶mO¹ô6I|‹ íÕ—S}•€{ZZØ1>ïY¼˜‡?ðLÄý¤»ºbaE"Å[Ã0p]—ŽtͲp4ÐQÝ&¬¶Å©nï;>úQôR‰”®³é3Ÿáæ¦Î)¬7H¼tÖ,ž:p€\.y+¹®K.—CÓ4R©Tô¹S- %ë¸Hq„Q¸\.S.—)•J˜¦‰ïûAPST1—ËÑÝÝã8äóùHl‘5cšõÒ_·n·Þzëäý@Æ¡ú¦\v(ýóÖ[oeÆ îó+vúÂ8Déèã‹®ë5õ’lÛŽ¢Î¦Cý¶pŒ&D—%†p89jÙ~î»ïsô÷w3{öìÑjÊ2ÖýóÉ'ŸdݺuS:}‚bæ²iÓ&6lØÀÎ;'»)cÂT›Û*‡ƒšÛþÜv¦P.—¥é’/™Â ÄóW&“¡T*EÏX@ÍœR~žËå(•JQ­P`÷~¹\žÒÏç“EOOëÖ­cëÖ­“Ý”1;Ÿé2· Ã|>O>ŸRIÑDÚ“dæŽt:M8Ž¥•—ë{ÕZ ét:ªw«˜¨¹mssÛžžž¦ŽŸ‡0:—>‘œöÜiœ¸õD¾ûüwY|ìbZ[[yàôhySÂÁ_ *º.„ÈÿJtŸ Då4M‹"-e¹ÅÌ`Æ ã2·m*å×E]„ã8\}õÕtvvâ8QDÊÀÀ6l ­­­&-X=\uÕU\wÝuƒ¢YvíÚ5hýfBÆ–/_ÎÆùxž7(µÔd"„ !^ˆk ÚÕ¿BxubI2–ĪnWJ|¦U÷"D§ú–ØXiö÷ó.MÃAˆVuv⸙D[‚êö% 8ê(>T/@DüÔÅÃj»¬j»ƒj»ºöïç™|„KÓiÜ+p-—£;—ÖúÓüí™g¢W'Ö!ðõK/å=‹“¼ÅÕâez2Ó4#D¦“m,—Ëhš†ïû5¡ºù|žÞÞÞ û7nœUÃõM8ôþyÉ%—Du—†â×6ÜU}¦RbÊÄ!£ÒlÛÆ¶E/—›©`:uÐu!¨üq/1áÚ·t)†a°gÏ]ÌšõÊÉnæa3ýsñâŇ5v*‡ÃÚµkikk›rž¦‡ÂTœÛ*‡ƒšÛO3sÛ#0 I¥R”J% à ŸÏ7¬…(ŸÍ‡ÆªU«Ø¸qãŒܧÛÜÖuÝ(³‰ïû‘ƒg.—£££ƒb±ˆaضÕZHfïž¶mG†[Yü:“ÉÔì˜2éèÍ£æ¶ÃsHs[ Z€“ 0GACØuÔ.~±÷¼ž×³lÿ2î?î~^óÊ×À5Émµ8¥PF߇b×÷Ñ«YQžü»¿Ãuݨ†/0%L‡ÇxÍÛšŠPikk㦛n¢««‹«®ºŠ… F êêêⵯ}-]]]\wÝuÃîÇqV­ZÅ®]»èêêb×®]ôôô ÙÒlûCEb“…O1"‹°ú™Œ)TדØÕeFõU`p*0«¯z¤°b‹*½ÕWX½áÈ€T9ŒgˆW·O(WoÇ\|1¦eñ®+¯äšýFN§úW¾÷ˆ£S~òÒK,¾új.üЇøÑ²e5ÂÕã~ùÄy誫p@Üä ƒÝ‹×\—ÕçŸÏ5?úÑßg‘7I½è" %öööR.—£É’ã83®þÂP ×7qëŸ!pLX¢°‰CÖ êíí¥¿¿?ªE4Õ°ˆ…܆ç‘xŸÉÀÞ¥KÑ4½{ßμyçMvó›ÉêŸ …bd¦ÚÜV¡PÔØ9qèºN±XŒÒ5‡aH©T:ü+f,S½Ö§è ‚ F$”N˜†aD¶Ã0(•J‘ ’¬§†!¦iFÑW¥R‰þþþ¨˜}2ªÅqœAiõ’íêz†áPÉÝŠÑ1æ¶Ï#Ä”¾ÐEüÀž¯ì¡¿ÜÏÓ/>…ÅÃ}Šp×Ê»¨œ•ˆt”‘)¥’R¤ýÏ4£÷²¿È¾|¤ØýcKS* <"å~\½z57n¬Iÿ5Üpà €èx·Ýv»ví¢³³sPxæ®]»Æµè˜ïû£ò’ :õL’!|„ÕWUHŪ~žAò½B„ØAry{õ½\æÒ¸ž@’áüÌ­êþS@1ñ¹V=FH­p"ëh#œÿ?Ï›‡œðØc|wÁÞ[m«[=ŽV}ùÕ—üó×¾Æß}îs´š&çs &uu¤ÂŽ8öeŸþ4§V—å«×äÅ7¾‘¯_z)ï½ë®h;¹Ÿs/¾˜»o»-š g°×4-Šb‘š\.7âv3¡ú¦Ì‹9ýÓ..$þ÷<å¹6ÈH²©^Cj¸ž—Ôt S€b?ϵ·ÓöÂ#“Ýü1a2ú§B¡hŽ©4·U(1jìœ8dÞy…¢Y¦jÿ”)Á{{{k”d ×äój©TöùU×õ¨,P“îÎ4M<Ï£··7JA.ë °W¥Óé(Q† …Ai˜òù|dV(ƂɞÛþð w.dÞºÝý³þ8‹Ož÷IþûŽÿf¸Ð-¶WWßÞ. –ÅöíÛY B‘1ÍÈp SøÉLEõ}Z¡h–¦•¾¾>n¸áúúúhii!“ɰjÕ*ZZZšSêÃlÖ­[Ç•W^m/ÐÎÎNzzzèëëãâ‹/—Ïçó8ŽÓ”÷ŒLßç"Ä!8H Wýëב"„A,€¤«Ë¥0á#ÒeYÿ¬…¥àªþ•SSb1² 2²ýö“KSÒŒ‘{îyå+iu]²k×’«KG^K½zü‡!‘ÅĹëÕk"ÏW^W8ñì³1û8úœs8÷Ž;8î‚  Ó\Îhmèn¸k–.Å ŽÐIbabår9 ÍM¥RôW´3‘‘úfggç¸ôOxÈ&ú±»®;åRðÍdfÂÄ!ùO&“v.ëyžç ¹ž4Žƒp2Êd2SÞÉh¦0•û§ëº˜¦¥êèè@Ó4 È¢H’Ž–#E÷Ë4Ëœ3e½X}K®£iZTcE¦Ò“}жíhYÿRÖŸ­TdPB‹b4L…¹í³,Õ!Üú`ÀŽ;8wç¹|üÁ³mÎ6VïY  Œ®[S;eU:ÝІ¥R)êãaÖ¤èS(š¥iAEæê¼è¢‹èêêâŠ+®àæ›oS%rýúõ\uÕU¬^½šÍ›7³~ýú†95ÇÏó¢¢åC! §;Ä6µi¶|DM)’H%™õ2)&H!%KmtˆÎ`㾜Π2úÑ5Êl@F‹‰¨§¢ßx#áÚµXÔFµ‰¿:àz¦iŠT\uëI±D^‡8õXòš¸€±d ŸZ²„|u¹ Ø '_õ*zöîÅûÛ9oÅ æT×±‰Å°šë^0AÂâ73Ó!MãÑ?óà•Õ/^hêAf☠ùyå3}ý¯fïÒ¥<«Cÿ=Ó¿†J3Läø©P(šGõM…bê¢úçðÈÚ(aF"J>ŸÇ¶í¨fÄx`Ûv”J Ä3˜ô&–ˆ,>œ bÛ6žç¡iÚ 9¯¬!( qžçaÛvÍ1“ËdôÏT*Õ5‘i¸ N$#E…FϸCýÖd!{˲¢~&ÿú¾Õd)—Ëø¾ՖȾ+IÚ1‚ ˆõÜ­8Æ«oJû« ,Òá,‚ŸTúp⊣uO}ªðèþaXõZ×Du}P$ÔF£äóyÊå2žç©KÅ!Ñ” ÒÕÕE__¿þõ¯£Žbš&›6m:¬â.õE‰Ö®]Kgg'}}}´µµ[H§G2Žg‰Óu•‰ÓU%·2©O†CŠSeØj4|£ÞK-2šÄñ}ÅsHáIölÛ†aèº>HÖœÚL¦J“–|HdtS‚Äk/0+& Ž’QEµÑ1&𦠙³t&Ò¨`ØxôÏÇuX_»üja0ÅÄ1“&Ñõ÷³SO ^ñèÀ9“ݼ1e¢ú§B¡=“5·U(ãÆÎÑ“N§1 £&EQ¡P ›Í’ÍfÇ5ª¼P(Ô<«§R)ÇiÚÓ>‚(}’뺃iHK#›ÍFb‘bb™ ýS¦·—¿1™âK\%¾ï74ÔŽ5A4\¤ýD¶3ùÃ0¥à¨iZ©"ÏÃ0Œ¦³µ(5· ˆ³ÐÜãÁ9¬~ ‘‘òÓàûN<åD¾ø¦/ŠlÃ\Dáy5R, òyùÏÿŒ?'N¡gš&™L†r¹\ãH­PŒ–¦#T:;;kTÇ‹.ºh\4ƒ¥ ã 0¸ÉáÄ'LuÓ¥<çÃÝGð‡0Œ'#x>y㘦Ùp²` Òu öߟXG~æ'ÞËsHÖ¼yþ/ÿ’íK—FÿKa,L¬+Eé ’'Ád~Ó$žçáº.§žzê¸|S‘±îŸý´U¿ÈFaÊ E³ÔGÃÍ>ûlNõaËÃçOvÓ& e R(¦&ªo*SÕ?#ë94J—R(hooǶíÈQÑqœ($ilö}Û¶q]Ã0ÈårX–E*•²¬h™LfØç€Ñ»äó~&“Á¶í!ÓIr¹œ*ì=بþ)k*$ƒINþ¦åoh4¿Giwã ¦i¸®K¹<¸2n¡P2ÚÅu]\×%“ÉD)ì¤ÈÔˆ ©T*Ê¡PŒ–ñè›É:ÊךðÎ!0Îçó˜¦Y3FÕG)£å¨ÉnÀd0\HWQ¬]ÖK9’8ã}ŒàØ6=¿øÅ)žddÐpèQÄ"þ®tâ7.q˜—þäOXöðÃ5©Ú’⊇¨qã"&L¾¦‘Œ™Ñu} Âsäà‰'žç+73 |CšzÈQ(†Ã V´ž;w.<¿õÄCÝ¥B¡P( ʼn$=§ÉôÈ¿ùÍo"A¤··—b±H>Ÿž™dÚ!Ã0¨T*Qt‹Œñ}ŸîînÊå2Žã ŠõrŸ£‰ †b]×1 cP6™Ò)›Íâ8ŽH?]]Wqä!SÈ5SåPMf€á~‡2ê¤Ñþeú¯dm)ªÔŸ[±XÄqœškÐÈÞ¡PL {¤ïLx@ëžÎE¼ˆûZïã„]'ˆ5àuzœêKF§è:»|Ïç;‘¨±ÍIýÎcÅ'¨$sF&q€vD'Î „•#MPq¿ ³¶ -ò8a ôCML†’)À4âH’(mµ¢É––nZ¹2Ú&$B„bVÿÏW?«Šáb¿Õ v²Hbø¾ÏÝwßÍñÇ?Ö_ÅÁL“! õ)‡Ãž¿c²›¡P( …B1ßÏ‹_~×¶ärÏÅv“Áàuê£,š9Î(Ik‹Å"š¦E!R¼¹ê¥§¿išX–q¥§}²·ÄuݨΉ,ÆÝlôˆ¬1!(“Ç”‹Å(µ—mÛ´¶¶’J¥¢c)Ž,¥…މzn­€3Ô3µ,\_¿oß÷ ÃŽŽ‚ À¶m:::Èf³£ŠÖ’66…âpØ€_Uªf·ÿÍß iZ4>Éó‘²OqdÐtʯ͛7G…éúúúèéé©Y¯QþË©Dµy&ÅÉ]D‘v©õgaa:2ç-CN‡òòð}?š´hšÖ0bHŠ%£AN,â¢ö&â;–- ¬ ê¨Øˆ¸Ïàš9…B!*î& Á…aÈQG¥•C ù¸âyžŠPQŒ­­­HeïNU\V¡P( ÅÄ÷k]ŒAõj¦)Ö“HA%‰®‹½£9N#ßÃN8añVzÉ‹¦ ç³Y³fÕ¬“|Šú*ŽãJ¥¦ «Çu]4M#NGm•mI¶×²¬è4²Ù,étšÞÞÞæ¾?Å´Æ÷}t]'ŸÏ™5£CEˆ Ç¡þ¦Fó|,Z CCÕJ‘µTLÓŒÒÉÈ0™ÆÏ²,Â0$N†!ÅbÓ4q]—0 1 ƒt:¦iQŠ2)쨩ŠÑ°Ã‡§<1<ýÀ‡§žzŠWì|kZÖ°wÿÞÁZ´·‹z)Õ{ú^ÿzœjš/ù;TN¼Š±¦)AeáÂ…¬^½ºæ³éšk¶Þp›FÌeÑy‰2í¹\ŽT*5d*§ ¢‰H#¯$uVF‹ü „@C§1“­2ŠAm-±"§òÒƒ*NG^,º®3{öìɽØÓ”{}8³zqƒ Pù[cƼyóhmm%ü{ÿ¢ÉnŽB¡P( Å`šñ’©¾ iŠ×á§˲Èçó ¢2e׿øE6lØP³,)ÂH¯àFu d –fÑu½iyYC")Èäóù¨Ž‹L#–¬'!#i¤óœbæ#ß–eªŽç¡r­ãàH©Çq¨õ êÓÉ÷2˜¦id³Y ÈÒú™¦õaMÓ( Qd˜Ìè!žb±EH±ÓqœÈ9µ\.+ÇJ ²K,¨þÎ /Æ@MÎU›R2*KÚñT•b¬iJPYµjÕ”r´•ûL¥RJd9B¹Ç†Í!,Ì€Ï,|†Å¿]ÌÀÙÌyl—^q©Q‚W Å÷EÔ¥®×¤³”i“öH}¨kF]C¥¯¯M›6±aÃ6lØÀ¦M›˜ìóh9 €¨›¢|âc&jÈJF§Œ¾Óúi{²ÖŠÈ[«–ØÞ¢6º%6-\Ⱦ«®ŠBX3™ ¯~õ«'èÊÍ,~ìÁ Ÿ(ÌX¡K¤úÜË^6ÙMQ( …B¡˜vÈ´[ííítttJ¥hoo¯I¤ë:Ùl–T*EGGGMÍ”dÔ‡\. ³#‘J¥˜5k³fÍ¢µµ•  1ÉufÍšE*•ŠŠÑ×?k& ¾º®GžöÉór]wÔbbêãû>Ùl6ú? ÃȰ?•úF #ZGƒ‰òúH›‡ì·¾ïG"ŒeYQZ}Š/™…¤X,’Ífq'Š’B¦tä=BFÂd³Y<Ï#›ÍÒÑÑA{{;ŽãÏ磘 p]Çq˜5kÖ :I’t:ݰ¶¯ã8Q½§0 I¥Rxž‡ëºQ¦‘:ù|>v“5u“Q9ííí<÷Üsãü«˜ÙìàD J|xÕ¯^ÅÞ½{Ù;7‘êË÷EDJ6+ÒYˆÄLD1f2™è79šz@ Åhhº† À† ¸á†hii‰R€Ýpà lذL&ÕW^9Ùç3,íííÑ >@D''»QSŒñ“9bd¸õd’PêÏ_¯¾ê[˜N|&'é–e±uëÖI=—éˆåÃ9HÛî!…N+Ca×Gºücƒa©P( …B1‘ r¹\äm^*•jÄ ]×)—Ë‘gzý3^.—‹ÄŒäòJ¥R³^2-Xý²F4³N]×k¶Éd2d2™ÈÐڨ튙ëº5©~lÛFÓ´Q¡Ÿ4*<ß,•R©D>ŸÇ¶mŠÅØjÖH8‘û*ÚŶíAµŒå¶¶m×D¾”J%lÛÆqœ(%ÕD ‚€L&E¾ÈH#)ÐÑÑA¹\& C|ßǶmLÓŒÄQ'Ûä8º®GiÌdm™L&9Jñ& Cr¹\”:Ð0ŒH\úþ÷¿¯"k“à·iÐËÀupª*[ÙÊ »N¨]QÓD±•0)¿ 6%ù½éº®œwãFÓ‚ŠŒF¹æškX»vmôùÀÀ@±LYQEÞôK¥!Â8>Z1ÅqD_•Qe3qÎ5Ö§T?¨JÕ¿Q.Ý©€R¤o’ŒPñˆ ´¹™øåO !ð§1ŽwÄ’¢›^z"Teõ3V( …B¡P C3žïÃ-×u}Ê•¡mæA$¨ø¾ëºtwwÏÈçÏÌ(ë%t äòfR¸Ëu “R¼¨GÖ4*‹5bP²ž‘<ެ¹"EÃ0j"Ê,ËÂuÝ(â&›Í†!Åb1ªóÄsñý€bQÅR¸ñ…¡è‡Ž#þ6ÂóÄrבeé´HÝ'ÿïèˆ×Ífk¢ÍŽXê'¨2”³X,N™ ŒF­M9Gm•Föæ1°O•s˜ŽÀÕhÙ1›tøÄÂÁèê\VÌ$Rx˜Lüêù@p«mêS-à†Sݶ£ºm¦ºŸ<ª.Kí‡p½ê§îw …B¡P(G*ªC1ö|>O:d8Ÿ(°¦ÄøGÚ¢¤+¾µëÊèŠ ¨ÝF®gFÃkåº.ÿó?«ÙÎäþ’¶0ß‚J† LaSyè¡÷“N‹÷A ìlb[?²¹éºÎ±Ç~M3£ˆ¹ÿ €Çû«H<3Œ2ó7ÿD©T"LÚÛSäóyŽ:êÿÑÛ»ˆL¦hìßÿHìIžg: º.š“N:]×éîîÆ0 „¡¥‘’vŒ0„÷¿)O?ýgãÿÏ`ZMx¥§Km͇+~wÇœ~ §&ÊLxžø‘$Dµ èèèˆ"“LÓ¬~ojœRŒME¨tuuÑÙÙɪU«†\çÊ+¯dÆ ѺS ™ûÑE8h'µ{ÛbI&#þ•:µT‚T º»…Zͱ,!†¶¶Š}†X–ˉeÓ…ñžVA0êðìñF£îÈôpÂmvu² 84~æÁ*(ñ¨ñH(¢a@Gˆ 9ª_â 3_¢K‚dUÿú@¶ú^ ¥êg"TÉÆ3 *¬¶C«¶ÑL´_¶Ù¬¶C^*)†P=ßLâeÞ:£ú¦ú^î3‚%·Ë&Ž›¼ÆzõXR‘ŸÔrÇ‘÷¼0qüI@M› …B¡P(ÆY#A¡˜ªH£·LáÔßß?ǃ 6£‰ãˆeCuÇvâf2aK?fY‹;ù8mÛ5ŽúØ6ôö áAf\ Ca«J®cb?Ò‘¸·r¹³X¸ðKÈ4¾¦)¢J,k ž'ŽeYBô(•ºqœø8¦)ÞËç}yŽò:üô§÷ñÒKsqÝØY”Ȫ,b› þžçŸ?ÿùŸEÕT]b® kÖ,ˆ„Çß¿ ºÖÏ?1¾_dõjוm…;ï\L*58ÚÆó`Μ°côô¼€tÚÀ4a×®дÚsr]aCüÌgÞÜ9™ÊÞs„M#€½Çì™eß©T ½Ê嚆†A†hšÕ½Qã”b¼hJPÙµkWS;›ŠBŠ$Qt‹Zû^:-–J5T‚@ ½½ñgɬU¦Y»eÅûž.H›ëxÐ(ŸæT ÃðB’A ÕOA؉+ªîÇ!óL'Nº/¥!‹eXÄJ©ü¢¼êÿ!B,( D!œøÕm’ RØ(‹YÆ—Xœ(Vÿ·Ñ"Fµ±h¡#Ä¡:e®znYbAI«~Nu¿õ!WÄ )Ød«íq¨Pä±òÕÏåúFu]£z>òk”âJšXtq‰s,NP´ŠS( …B¡P(Ž\dÚw™ºi¼ Ca’–%^¦Û“D»bG]ןKÁE:æJáCF`¸n,„8ްEÉHŽbƒ\öù¼°OõöÆ"Er?B@Ñ«5QÄ6¶-– Â^É´2{ö1lÙB$ž<öØ)€ø? ãs’ Úæºâ\¤àãû>A Ú/#bt6mZˆcŠhñ>Ÿ¦)¶ù³?ÓôX¼ø=œ{î·p]-FtýD\žxâLL3¶³k<ûlóç_ϵ×ÎÁ4ãúå½½‹hmõiÅÄvå2|âð£0 ‘Æ4Åuþ»¿ÛÕŒ’ÛÈ6~üã=𫞹„/Î÷µ¯=*ÝÚÛÅ2Y+ù‡?\-“Ùln¹e%AàWk°ˆõå²cŽù?þ®1éS‰žÛî̳ÅûûZïã;/~‡Ë¹¼ñÊ…Â AE:qOVZ?Å‘GS‚ÊE]4b:¯ 6ÐÖÖ6b”ÊÕW_MWWmmmôõõÑÙÙÉ5×\·_½z5›7ofýúõƒj¶ òF(³é@<Ød2µBÉX †"†!nþ†Q›VÌucyl9ØÊPIz)÷—´?ËAOÞ" 3yîñÀ²Äq&*j&ƒ1©á2ÖHÇ|›±›¦"ÃõMÛþ9ÏSƒ|þ"T¤1¾L\7åPh¶¯ËTbq‰Eœž«êDñC±‰… ! $OQ¦ø* „•±øa™Äé¾’íV•c°ÂX¿?ˆÅ+ªmϧD“E‰¤¨’!ŽXqªÛv‹#2jâº/™êK'ŽÖñªçT÷aŽòÜfÙ? Å蘌¹­B¡5vyéþ^E×u,ËŠæîù|žL&3bú^Ïóð<¯áº²H8E$Ÿ ÇiXÌÚ4ÍjÊŸÆËëè²X5ˆTeÖtJ#1C™ˆþ™t¬=¤!]FpÈŸšLOeY±h¡ëâ}±Û—L“(]–´?9ްÍô÷ [ŽL/SpÉL'2J½½ªþtDô‡xïy⽌X‘?séà/#S #>žŒZût½]LןO?ýæÏß &²ýés9±ÎŽg±sç¯EÒhZœ’¬ž¶¶WsƳ"ñIÞ,KˆHõÙÛ n¹¥…_<žzM)4·æ3™J t–-{š&®“mÇö4™**™™FÔAר±cY͵XºôLxàôCþ½M%&cn»r1d–‚s7´žÐÊšk¸såœÅY"L(Y\¾mѲ,t]WbŠbÂhJPikkãÊ+¯äª«®"“ɰvíZZZZÀqn¸á®»îºa÷ÓÓÓÃm·ÝÆOúSZZZèëëÃ4MÖ®]˪U«Ø°a×]wôôôpÙe—ÑÙÙyØŠ§ï‹0>Y^! c½ž¡ÆÛz¡¢äà"÷)sSÊ0K©êû¾xårâ3Õ"=äý@z$Û!ç¹r°÷¼Úãæóñà'Ã2åº5ô<\2Iç4CÚ»ëS¢I‡ý™ÀH}Óþº ¨kRÙp«eÊ,˜˜B9j…¿ú¿Œ:)"Æ‘&õH¡Æ®6‹‰ˆTI2Zý²ÙûAr=‰“D *òZˆ Éó «í³ÂJ¶º¼—X8‘i̤à¢!¢mdtÒÄD÷O…BÑ<“5·U(ãÆÎÃǶ횢Ԟç‘ÏçéîîF×õ¨0ôHkÛ¶£9ÉgBÛ¶±m;><Ïöíhÿ „™?ÉHË%a’J¥Ã0Qòù<¶mS,UnýIb¢úç!gC ÎPÒÞ.l8–U›á¤TŠí<òg]®{¶ÓuáHÂþ"›"‚Æ"„´Ý@É2òØ2uØp¶dy"‘N»Åfža‘)¿^ˬY[£Ú)0¼]É4áÛßÞ˶modS“Ñ%õ·Ë‚Ï~/;v,$ìhZc;^.¿øÅ,vï¾¼éì2™ <òH=v _\{=‡B×aÁ‚ xî¹Ó¢º3’ÖÖŸrÉ%'g7wA§(“5·}òûàlk ´liAC㥽/‰…Òˆ+©Kå•Ïçñ}?N¦PLM *ëׯ„—ˆŒFÙµk´µµqÝu×qÑE »¾¾¾1Fv¸]»vÑÕÕÅÂ… £—U«V±jÕ*ººº[í ÃUú§"#ywhqÄóÄM±~¹ Ý r`éè7~ÓŒ ¥Ó±w€ å”y5u]x2XV,„HE(¢xV²)ÕÿBA72ü2•"½+R)ñw$Ae¨‚jÉPБð}?ÊÍ9¶O¦ª˜Ü(ˆ`& *ÃõM`Lûgì’©º†Ã¯¾díƒ8Í—¬12è! ¡Q¨[>˜¨çÁšÜ¥ b KR‘‘9 ¾GqmÓÄuX2EÖi‘5rä÷oׇ‘ŸÍp&²*ŠÑ1Ys[…B1•´½$EÛ]7!F2ÀË´PÛ“F²yÈÔ`M4¿&•,ß šG´4s ÎcïÞ¹¼ò•Í ž'뮼zÈ(–F<ûl]ô[ÞñŽÆí¨Ç÷aÛ¶·­M]™zí„ÞÆÅ?ÕÔùËëvòÉg±ÿêQÛ§ “6·}Ø úÓðàâññ9w‰HõV£46ø!yžWA©PLM * D•L&CWW›7oD!úf‹Ñ_tÑE\tÑE °yófºººXµjÜpà ƒÍ… Ò××7ì>·nÝʺuëØ¸qãëø¾ÏŽO~Rdq†¯i2”’}8Ñår|\ÇÇèï‹nÉeR8‘‚J½¸Z(Äy6A,—ê»ÜaÔzK4:?Y$ bñ%Y M†nÊÂhI1H¾{ §þ'=Œ’ÈLNV’ßK£ï& ãpT)2Mf¤¶lâºuëØºukÓ}`ª2\ßá¥p(ýóÖ[obA„ rv&ÛjÑR8‘EÏKÄFùdý‰bªˆ&S ¢Ð¿ägD•µiº’I±nYr[Æb‘G­ØR‡†¬ûû¿çÉ'Ÿœì«tØŒGÿ|òÉ'Y·n]t‘2Aõe"ê %kiÃls„ßS6mÚĦM›8í´Ó&»)‡ÍdÍmŠñBÍmG?·=’mú$×u1M“L&ƒmÛA0ì>r¹ax¨ù|kñ}Ïóè¯Ï Õºí¸®;mÒõôô°aönÝ:ÙM9l&jnÛÌïÕ÷ãôèÉš(º>ØØ_.ÇQ*Í"S¾7"·ñ¼Á/#1š®#ÓÅ×§”‰ãŽ;Žƒ×4]_Ø0à±ÇÎ^l:½¾®ÃÁƒkX½zMMºü‘¶ƒ›j“t~üñ—qûíojúü ðý;yÃÞ†i.‹>ß´i[·neçÎÍ_Ì)ÊxÎmׯ_ß°^Gƒ1¼.{i§^x*ÈRÞò[÷#’©-˶íiG1~lذ[o½uÌç¶£TZZZ¢–¤¯¯M›655¹ìëëã†n ¯¯/ÚO£¢÷Í„Œ-_¾|ÄNß÷ çÌaOZü?Ü\†_Ö# W Éœ˜IÏÙËË“ù1‡r–‘‘nrÞ—ÌwÙ̽C†yÊýÈ”cçû”ÅÁ¤‡ƒl§3\7€‚`°ð“¤Ñ$Æ÷ã´fA ÎUvsœXà‘…Ôä$DzÒ›Â0bAHiñ¿L±8Ü@_-í F‡"foܸ‘ 6¯bjÒ¨o¡÷ÏK.¹dÐ=!æj4~ ’Ñ(2–,x.û¬4®+ǃ©A£þ¥ ñy¡Á¶òùv¸çXcˆ}å?&ŸÚè!´èšFaãFÖ­[7ÙWiÌËþ¹xñbe¬MŠ!Rä)å4D$T7"5A­è×Q]æ&¶•)ðìêÿ¹ºcÉu²Œ]º¿iÊÚµkikk£««k²›2fLôÜV¡/ÔÜvxÍm•{÷.eåÊ£F\W^#]‡ûï?È-·Ìiú8žóç_ÏC\óùÚµkù×ýWNÏú´^–U{’¢@óy!°d³âóB!®#kº$ëÄÈ\›¥’8^2Õ—¬ùÒÛ+î•A 'òÜåw$-'ù|,†Iá:×V‡³mñWÖ’‘ÿÛvÒ›¼Fú>_ýêÈëI{aÀ·¾u£)»¡ëðàƒgŒJT›®L¨Ý0×Aæ+±ïlÿYu?̺TCa’ÍfÉårMÕóR(Æš1TšaÓ¦M på•W"ÚeÕªUôõõÑÙÙɦM›jÖßµk×a6 ‚€Ö®E2MÞ(yL%±s4ÞpȺÑ}g¸Ôäúr–%¢BdôŒ8l;ŽÎ“0ÃM(¤à%ŸBA¼OΉe]ÛŽ=G’‘;²°šl§L¡&#ol;ŽrÝX¤Ò´Æõn†»/Àã‹Ë/ŽÍ—2I ×7A ¦cÕ?w†p¦Ñ H 4Rv# ˜Ò詘º˜L^´PHœ2,y¿Îß¾/Ö¹ãô;x#oœÌ«tØLdÿœ1¤: $D!!±k°A,†HáDþVÿwÑ'Ý\º þhÛAûw°û€oC8ŒÙ`ÿ%”€ývЯŒWBör(Éç‚m 7Èí ¼ë× }ÂKÅçÁfÐÎŒøG*Xª?&cn«P(FFcC}}ÇqH¥R ÓhÕãº.𦑮Z_Ã0$|?vª²,+?‚ ›Í’N§éMxAj Û¶‡Æ*µ˜bôLDÿô,3ˆŒ™új4¸îè£m’5iš%™‰¥YdÚúf„(y}u}tmÓõá÷ÿÌ3Ï4ßà)ʤØmoÿ=Üt:ÂQÒað}½ÁO©T¢££ƒ\.×tm/…b¬9nŒ‘``` ÊÙÙÙ9‘7³¯¯‹/¾ø°Žçû>§žŠŸnn€jpH¥&úJ?#Õ?-år<0 q*®\.“›eÔL£ïC†³&ï§–%>ó<ñJž—cdŠ1‰’ÉÄ"K¥"D˜Þ^1á±m±<•bK>?ñßÏD3T߯´nV b¢ARÖJ‘5#åPL ¤ 1 uïÒÀø Xà±›¤Ž-Õ?Çœ!ŽŽ†Ñæ?‘c»¸—€˜•ËϤ8’O¬o î1¹Är)œxàþ¤߃Ž%Ðq ßw7äÏ‚Ôíà~ìÈî†üF`!˜ƒu!d¾æ+ ûJ06CîrȹµPøÐBê:¼?…޵ƒÇ߇ô§!XÙ7€[‚ôyàý?È~¸ê¸Üo@û°ßo×Þ.^²^šb|™è¹­B¡hŽi;vNat]oZˆé¾r¹\dì’i¿<Ï£££cоs¹\S…Ä›Á²¬(J¦ž ¢"ÆŠÉa"ú§î\W8¥jZ\—6“‰Ó‹7‹¦ ›Áx7I[Æh…›ÑÚ“-kôÛ˜æèmH‡¢]JÇÚÑ\u2I[ÓhÒ¤Il{èe͈ÍÓ‰žÛÀ¢…€;wîd`ö@baÐPùs]ß÷éîîVµS“„F¨¬]»–Ûo¿= Û¼y3_|qT4lýúõ\uÕU¬^½šÍ›7³~ýzZZZë˜a²ùÛ,e±-Åè‘uO NË%‹¹v®:Ò@X_¼Þ0„ 3kÖàïY×…©\®4ɉPý„H B2µ™¦ QE¦/3 اæ\X„Ÿ?Õ­Nöå?,Fê›0výó™êX=,9cf‰8ÚACE§(†f„ûƒ‡7tL)&²62²LÖ"‘bÅHÈ QŸ¤R·¼>핬·T@D£T‚ˆ\&£Od /)–È:'®§¼Ç!\þ1P¼ü6°î…ü(¼¸roó­ÚæëÀ€ÜÍ ÖFp|0—€~~õ<.~¹vHßæzàÃ`vç:wUÛæ‰sèý>ø‹â¨Iòî‡ògA½Ø&›…̉9þÙ ·áÆúS` ¤~ ô!i$^”­­qºMÈÓeN¥ÈÛéÌdÌm ÅÈL«±sš†aT—d$<Ï#r¹\M”€Lû•Édð}?zŸÜ®™ý7ƒh²Ù,¥R)JétšL&S“:L1qLDÿ ‚MÓpÝ8W¹g¬èí}ÔÄD¡ëC×ÔŽÑž‹¬¯;ÚcŒv›C±u;NlÃi–fÅ¡d-ÝBáÐR²5ÚæôÓOý‰NA&cnW¯¶ÁC¿|ˆ‡˜,Y±Ðqj<ªÇÁ0 t]GÓ´hÜP÷sÅDÓ” ÒÕÕ5báP©^ŽÄÆééé‰ÂÂ’¡ak×®¥³³“¾¾¾AËß÷y²ÿ8þؤǫŒ~P¦)¼g'Ú`Ó(ª%–)#Y$AÐ8Wúr_2ߪÌMúÖì0áÙžûù|xïÄžçx0\ß„±ëŸ/™õ,¾¯ÇœË¨BóŠæ9+Õ? 1 ¶ý¹€Jub‘C:ÉïN¦Ö"ñ¿–XO¦Ø2ªûÉ#îÙêþõêò ±½l‹Q}Uküx?ƒì- ¯mÁú[ ³ô Ë!èíTHÿ¬½`ýà‚‘m+ýmÝü W´#“œ»Ë¹„÷Ý ¸úY1q$ΡÚïÀ˜ ékÅ8îƒü÷ {pfuó"‘(T”‚R7h¶Ø—þUèxÎ=W[l4 ãÔ¥Rœâ¶c@Å¡3Ñs[…BÑSzìœ&¤êÒ4È'Ã-/—˸®‹eYƒê”X–E>Ÿ'ŠÅ"ù|ÇqÐ4-r¶*2?RjˆT•J…B¡@>Ÿ§½½Ã0"㛌šQLãÝ?Ã0Ä0 ÒéZqBв†ëTé¶áñNgëûÂt(ßÿP‚ÊLb2æ¶Á.À„û¶ÝÇGþhíÂÄC˜ëº†ïû˜¦©îåŠI£)A¥¯¯žžž×ëìl®4÷p‹Æz2»mÉ懳š^_Öæ°¬¸.Ç ‰Ú›P,KL\&z"0”€#äúöÈ:*ÍDĸnl ÚWÍ¿ÿ ûΟ3±'9ŽŒTLl,úçlÜÖ€zþŸ •Ø8ªP4KÒð~1ýó5It„!‹µçˆ…ŸX ‘"KòFO¬—K¼7ë‡ÄB+ŽÎ­,j™¤®‡Âq`¬ûXÈü²%`”^†xþººï@ˆ@®h·~?˜úQÕh8 ! œ-†»oi`¼©nLr¨-b/ÓVSçiѬÌÛ æšjÛJuÇ”×™Äu …P¤ ÿ¿PúB¸ AÓAó@ÁJxîÉzbét|nÒé@e@=9·U(Í3eÇÎi@¥R9äåÅ! rêº^³]&“‰ Êkš6Èø<‚wÞHËAÔXÉårQê¯R©¤ ÒOƳŠ´nƒÓŽF<Ï)•f¾a|º2•œG[gº2‘s[ ð¼ î¸û>ÚûQ±ÀqåŒ3M3J=©îåŠÉ¤)Aåâ‹/fõêÕ#xS‘í ?È«FYü*„¢iBÈf•qáP˜^r’52§¬ ³.x°%íìý“}Ó8­0oß¼Ái}ŠfŠ©Qt„"Å!ø1!C\ >Ñ¢G³È—‹_²ÕåR¨É‹idMȼüYy90²7Cî#`zÐëQ5CuÄbŒ©>Ym@‡DͿу¡8L ^Uœ2zÀ¸Ø=ÔŽïÍê¹Åõ {«×6]½Þâ1­"êF> š¦ðÒ C1’).ÃPŒySùV¡P(ÓŸ±Jñ5š¦MÈqS‘¨qö él©l± ÅÔ¡R©pà¶y÷‰ï-?áížx ñ<MÓÐ4-Jå¨PLM¥w‡ 6Ô|¶aÃúúú&»ýÃû–¬äS£ˆÓ41À–Ëâ¥ë‡VDK1³HÖ‡¸ÓLXZ½?²`Ád7qZf–üx¿yëo&»9ŠéŠT¦2Ý–Cmd‰{3@„/ˆ÷X¼?ÞEþ>°oo?¤î‚àz6@xÜ'åJb_Ρý °W‚6þ| æ9ùw辬\õ8±øP@ˆ:Ð_mŸL)6ÔµQ9õA›dÁ9Á3ÄéÁ†Ã$kôÿªFÅdªçjGÅxDÑ8‘‘±Á²ÀÐDÔJ±ZoÅq„Ak«p4ñ<ÑÒÑ!„…B¡P(Š©†ŒF U]E2™éáü{¤žÒµ¬ZjBæ'–…n‰a†ëº“ÝdÅÎ!¥¿á†èììœÒ!ÒA0{û9\0JѲ>_c±¨D•™Š®~0îå, áìWÜÊIû”2Þ !pGþï+Ø»bñd7G¡PŒ€/#=ãhˆ1Ôq€Å`º  ù/ƒ¹Z샺?éÿÑ%©«€g€ybLvî…L©<O@áëÕÃŒp^ÊZxSƒöqRfbÒêÄ)° |"p/°}û­ÖŠix<3ñ^F÷HQI ,¾8¶Œ$² ñ¹YNaAÏ‹òyá\ £ye¾iŠgžf‹*¦¾Ÿ¶}䤱P( ÅÌ% CfÏþë¨VœB‘Äóͤ<`À‡Î¾9ÜýôÝûºcÄCFƒ02ß÷£ZX ÅdÒT„ÊtåÓ·`þ“/ö~dÁ2ÅÌÃ0í»]›2ðÁüô¦×qü‹/Nö©L |à)žþyN˜ìæ(ŠCA¦Ür¨†!D•‘hNÇé3ÓiH¥„Q^Ö&Ëÿ ¾ ¹ÏŠ]•«Q+¥;Àükè~Ê¿Ÿçràüì7‹ñ¸x«ˆ¦(!óivBúÐÞ4úS&¶†ÓnùÏ9ðG.[“Œj´L¦_3¢—ŒX‘ÿëˆô`25š‹¨ãßï ` ƒDww’Ž Òx_¼ 8E¬[ë(•€•“}aÆžQMÚ0Ÿ» ŽV‘Ëz‘+™êrèF4>è ÚbÄw.ÉødôŠãˆÿm[DªÔ§SéÁ&×ßG:-^¶-–0Œ…°RIôÅr9î—BôT( Û¶É7¸!A@>ŸÒ­Ø¶]#–„aH*•" èÈ|ý: Åxò裳ÐõÚ¨Kh%.)b ›'öRÈú¸ãÁ–-[&ûô¦%¸°ñŒppضd[üQbº®ãº®ŠPQL:3ZPÙöä ¼÷ª¶…b|yõ«™ì&L¶ÀèÜÖ9ÙMQ(‡Š|ê,"ŒïÕynŠHÃs_ÃQ$õQž¹œxÃzMÇ™ XVüwL ¥†ˆH"ùÐX¦q”L†8ÊE¦+ƒñzÈH[š ¤ß Þ‚ù ôênߑΒxžŠ|OÂP$Û¢ˆt)c±ÄuŲBA’)/r9èïë¶¶Ö aA "Y::âH$YW'™×÷¦P(¦/Òp•ÄuÝH(©GŠ)†aPœ)ƒ³bÚ±cÇ2N\½ŸV £úJ#üF’>í>±ï‰ÄCLŸìºÏ39÷ë,4'tÒdŸÚ´e‡Ö€›'“iX) CÂê$3T“MÅ$Ót •¾¾¾A…éo¿ývºººj>[¿~ýdŸ üžyð ¿ñ8X=Ù­QÌ4’v®þþE€JùÕ }Àû^s6gOvs ÅhÑ÷Â8Ÿ¸J'ÖlVD¤Œ›Åuc塊a ,¹#¹›Éªià’Q-Ç7Æçzâûâç)Óéµ·Ç?ÇÞ^±Žì‡a(¾Ëüs­Ç0â}:Ž8ŽŒ&“µVd)–Éud=–lVD¾¨”¹ ÅôƲ,<ÏÃJŒ»®ëFŸ'QbŠbªðÈ# Øÿ±ã)WÿOþR=âið'‘‰ítDÄŠ†ð©–•£X]7_}¯JoLo‚@Ì_Æ:ÀA *‡F\X„eïZ†iš|àá‡Å‚ÏNš¦aš¦ŠNQL šTÚÚÚhkk£§'NêÝÙÙI__ßd·H^¼e Ü4Ù-QÌD’“¨8MÂû#—!¬>ÏÌ;ÙMQ(‡‚¬Å!]ú†rÃsÞrù0öÝézŸË‰È|RÒb/ÏâF¹O¾¥>k¯9,Kì7ù?ÔŠ-aX[©Û4ãB!Io©LF\€¤…ZîG^ : Kž'Ž[olò}ü[–@a®;²Ñ»iúÇ`²ÎJ%ñ™–ü tÐîcs@?øP½lž'N7ŸôýèߊãÄ]@¦ï*Ä5n¤+jÚ rX …ø§¬ëqW2 Ñê»B6+ö/mBà)âu3±O×ûL¶G¦$³¬ØÈáyb?²;Ê”e͈4²ìƒL(ÿÏåbáÒ0šÓaÇ“¤¥8òÈçksø†èÒA¡\‘ŸI,+1¥‡u]It/¨_¿ÑqFY3™ ííí‘@A”Ê+)¨$Ó|)1E1ÙœpÂwؾîÒè™]þ•™ke ÿ  "ŠE«þ/‘Yn;ˆýJ”OüÌ ÔØ;Uð_æá”ÇN!sC†%òá¡Áàžç %©PL$M *k×®eíÚµ“ÝÖQqÌÒ½÷‘~4mÙd7E1C‹l,G¿wá÷÷>Íѧìšì¦(ŠÑFº%†9w`´? éLœ;+ŸÛÕ‡¾K Ùx?TÔçȨ’|ÎÉ|·Ú”<„Ç÷-0=àFж‚‘†àIÐA¡?øÁÂñmó E¦ÞÒõøçœüêRMõùç%Éè#I½ýÔ² R?Q]ë··ÇÛÊ´`2ÂEF/¥Rb[™š¬TÝEþÄåO^¶-©¯J2YC[FD%·wœXTÑ4qÍR©Xä‘íµíø–†±ñE 1ò&÷mÛµ]ZÚr¹Z!HÖ±‘‚‘ãÔÞ"Â0 óýXx2ŒZ 8y»KŠOâ\W¬“±¤#?÷}q>*ƒÆÄ1TMþšqTh$ˆ4³]3ëHo`•"ÿÖ“ÍfÉårQ±ú̘y(£§»ç | Áçrè*G­è‰eZ⹈( ¡¢P(Æ–ghÙ;çü˜Öû~+&anã„{º®«èÅ”¡é”_ÓÅ ¯þÒ%¨(Æi¾jm}v²›2m˜¯ÁóŸâé}Û'») …b4„ˆ'Ï"âiÓˆ=[k ®2†^ZL¥AE¦Ê*kÝdeåì¤5Ö¶c ¥®ÞÆ4…¥6y̤US’ËÅ'²D6Q¿MÄVÇz×5™¾+‰´ˆÉu“Q2Ò[¿é2,dê±`™0nîûZ­ÅÚ÷ãk™t©K§ã‚5IK«,n‘lËá`×XyËïSÌòàŸÚ;rÿÆ nÉ­äÏþñç‡ß¶# ÙšÌ"7éFÜ5e²$2µXý¹È¨Ã‘ô¶ïîŽoÙ¬ØVvc™‚L׋¼É.Xßµ\Wdô“uaÂ0.X+SÕɨ¸&£täq“È[RÔ­ƒX’í+•â 7]£ ±nR˜‘P2pNŠ™Œ¸v2P@¶K^“l6nO¡ßž'ŽÒéX[–Úö?ø:;U:[…À4Í(í—뺋ÅA¹ës¹¹\]×Éf³˜¦‰®Ü¿“@À—?AkÃår(ª—‡‹«E€§B¡%Ïpê½<=÷‹œuò{ãÉIƒhGÛ¶±, Ó4áH ÅØ2*AeÆ pÍ5×°aÃn¸á†šåmmmƒr©N{Ž>š…Ï<3ÙÍPÌ`Ô-|ô,3áéã¹û]K&»)M!=ì‚ ˜´‡Â0 ±m›B¡@>ŸÇ4M4MÃu] u®A iù|>zØõ}?špA@:¦T*©‡\ESHã[”H:”â´=ÑO0 cë¦L©•Td¥òúÜ6–»ƒx/Åií“ÛÕ@éê^o‘•.æÒbYO£üG#yÔ6òˆªßw²­šÖx›z·äªˆcxb“ì/£û½>Žë Kh¡[}“"Š|_(ĕɓÑ6[nG“Ÿ­Z3¥Yô;Áø8p „y0 À€ð5à– p5l™wå[–7¿SEd”ŸiŽß„¡ún“ì2ÉLÉgíFA\Í[v)<'±¬¸K%?—b„lW:]L&oII±¹\®:êÏ)Iww¬+ËTiõéΤA¦}Kþ&ÚÛãèAYòI®'ÏGÊ%Ï=¹gžYÈOìÛ/Z1m±,‹|>O.—k˜î ˆÒ¯HÑ%›ÍRó<  ÅÈh´~r¯œì¦(¦(ÉñP1E8ØÍ‹³žŽ'…uãG‘mF¥ûRLŽjvÅ«¯¾šM›6ÑÖÖ}ÖÙÙ‰çy\yå•´µµqÝu×5µ¯¾¾>ººº´O.;Üú,/[¿…•sæLÔuTÈgýK.¹s²›2f ×7“Ë¥ÀòpâžÙ´§Ú'ûT! =ÏÃuÝHÈ‚€T*uØb±Ì9Ýè˜AàVÃZóU7Ül6‹ã8øUX™bAÓ4œj>Çqð< ÈçóQ; ÃÀ¶m:::Èf³ø¾O{{{”×:ŸÏGÛE†„aH>ŸÇuݨý¾ïãº.Žãàº.©T*ºN²Ýòú¥Óéè:º®][Ù^¹Ï0 £‡ï ^«úky$2žýs(²Ùê›duN\ãCºoCœ_§šÓƱ¬‘ÕT×…kxr?I«a3.øÒE½‘%µ\ú‰éPr#Ö’Ý(7ÒPm1ÍHGòw$¢k“ù‰’y‚ä_y ê…™g(‰L36žF.Y˜|¿0ìz^"«Z˜û<ü×ÿëå‘W?2~í˜`Æ{n+#4fš˜r8ôöŽ^@©§þÔ ™Œ8®¼…$…Ù5ýºyÍÞ $Él„rûd/•â(šzdDe qf¨õä>ÕÐxßû~ÀI'í;¼‹;E˜Œ±s¦!Ó~e³Ù†é¾ê)‹A€-kˆ)C0ýÓq๟Ÿ:n…㧆û°âpi;Ã3v[€Y:œÕzgîªÖ%vœA—|>ïû‘­D¡˜ 4¡ÒÓÓæM›¸ùæ›YµjUͲ¶¶6Ö¯_ÏÂ… ùøÇ?ÎÍ7ß<ì¾6lØÀ¦M›X½z5}}}´´´pÓM7ÑÒÒ¦M›Ø°a«W¯fóæÍ¬_¿þj·úÝNW&bn«PLjn;üuyã;*í×?<.í.WÄüV1½éïŸÇ‡™2FL”ÝV²äï+•2•J‚˜ð–?˜5G Åè¹í!¥_»v-5Ÿµµµ±k×®!·éë룳³³&Ê墋.b×®]tuu±páB:;;Xµj«V­¢««kÔjçàèçŸW¹õÂßxgœñšÉnÆa1\ßƤ†À’3àà#‡^IV€ ‘’F&ö®÷–NeNàû>¾ï“ÉdÈf³5ÑÉ4YÉuu]'‚(’# Ã(‚C4Ɉ֗)¬z{{y¸«‹£^ûÚ(U—çytwwGû×u|>E•‹E:::(—Ë5‘ÉÔ ²ÖIn”î¢ÍDÍ ·m}ú†¡Š¼ 畘Œüi¶H\£ˆ¹“ËåÈf³5Ñ8ŽãDQ8rù]—J%:::°,+Š\™)cÀDôÏF½À\°#Üñ ð°äÞ—øööíä~¼·êmšA¤Attõ}€è÷%@ú¤†ˆ2,~u9€Ãˆõ·g%A.œr#˜kkoyÍôïCI_–LÓ&‘ˉ{pry¿Íç…+Ÿm‹Wwwã¨?ˆá¨nöøãÓ?Be"æ¶“ñ hYL~: ?3±O’É; ÅÈŒgÿÜöðq×¹m²OQ1…Q)¿†g¢ì¶ 1µW€fÂê‡WCfeÃ/'3“',ŠiKS5T.\8H(ikk«é`ôôô »ŸÎÎN6nÜX³Íí·ßN[[===5õYäqGÊÉ·uëVÖ­[Wó™çÃK{Ÿ˜¸«h#,Bò}ˆ°Ik‘ŸøV_éêÿvÝöŠiźuë¸çžorüñ/NvS‹áú&pÈýóÖ[oeÆ €ø¹ÿÅåðÛ—ývè CìÊea•ªîB*% zÕO™KÓÏçy¸« ‡Î•+ ‚Ó4ñ}Ÿ0 £ó j’†A&“¡P(Dù¡å†ö}p]LÓ¤X,òüâżðÎw’ó<>û®wDi²€h™L†R©„aQZ«ÞÞÞA"‚¦iƒ&‡,ø~\7‰çŪ%A r9¥Rƒ“½×ÿ?ÁX–}I‘))èÈk+S³¥Óiz{{Éd2d2.»ì2~øÃòä“ON까ãÑ?Ÿ|òIÖ­[ǦM›†\Ç\¹€wüÙÿd¡´};¹Í›É\x!ÖQGaÛÏ-Dʯ±h¢#R$´"†> èŠÕum £ú «ÿŠ”¯&ÿ‡âyµ]û>™Ï‹\õ÷;M«­¯R(ˆa…Bl!–U¬“ ˆ”bM†áoÚ´‰G½þþÊø_Ôqf"æ¶A ü§ž7=0™á¯žuëÖqë­·Nv󛉘Û*IOOëÖ­cëÖ­“Ý”Ãf<ç¶{_öGæŸöÜdŸ¢b £ëƒ—™kçΓ}z‡ÍxÎmëmÆ7zpÚfñ˜ñ…•_hhÿ‘¶…âPÙ°aøÌm›T.ºè"zzz¸ýöÛ‡\ÇqZZZ"¥r$n¿ýv.»ì2:;;Y»vmÃÈ–úŽÚˆåË—×tv€—YpZÛmÃo˜GÈ¡Š3vu)–Èp€pÉ ˆE’᎛Ú‰]v³ÄâŠ!>ï;WÜxüËääZ”õ ’¸®yÝK‰ö'Ùè:ظq#—\rÉd7cL©ï›À!÷ÏK.¹„õëװÇÛþ£Âó/^,LZN"ÅW£»ÂsÎjtÏó¸ìMoâ“?úý¹oûÂÈf³är¹H,Ñ®S(ÈårB<±m!*H‘&I Ãc>UÃýüë¯gßI'±ù¦›Ð«F~ aà×ýî¼ô Àj$rŒ„çAGG¢*xõš¥R¢Òs£eù¼˜€Hc)ˆ¶äóqqji••¢ËåZWZ×ë¤Râ’úïJÇ–×i´ø¾ØgÝ~¥•¬%CGáHË4Mܪð¥ë:^x!===,^<ý=à“ŒUÿ\¼x17nÒ“(†ügà['Aøä ûùVöT*Ë–‘¹ðBt„R 6Kµ´#êÄ‘' —Xl!¾ÕÏ‹Õ}µ#†[ág ‡Ô™S%¥I¶%<+ …±,+Žl–LFôõRI¼¯ŠIÞwÂPÜK†`íÚµ|üã—pÉ%Žó…œXÆkn†Ó#âA!˜bÊp¨¹íð$ç¶ ÅD²jÕ*6nÜÈòåË'»)cÊXÏm:i¯;öØqk¯ªà0ý²›k×®eýúõœx≓}zcÊXÏmëkroýÆSÌ}º—-Ï|iÈme=\…âPY¿~ý¸Ìm›JùÕÖÖÆ•W^ÉUW]Å•W^ÉÚµkk¼6mÚĦM›¸îºëFÜ×ÀÀW]u}}}\sÍ5‘³páÂAëöõõ êpÍð5³ÂꋞÖYÕDˆE„("?³«ëÈh‘"B8qïKˆ‘Ó¯~ž©þÕÖ ‹8׉tö,S[ןöÚYä,âGË~Ķ•Ûð¿! f§w§)ÛåšÂ}£¡Q±mYÀ¶mr¹vÕ`lY®ë†aT0:“ÉDE¥ƒ ˆ¼þei)¨Èõ¨½R€ ‚ &]’bú0Tß„±éŸûBxÅŠ=œôº“IJˆr:-¬£IY£iØšF×’%üÇ_ü¹êoÐR—_Îö}ûøÈÕWS®¼wßv—.Z?Y:¢~æûñ±ëE)>ȈËbM½W·,膃óg˜¦Ø>›­µ²-ªçC¹,þ:ŽxéºhWrÃZlÊdj WKc¦®7.ôíûC§J*•ıGœ“l—Ìe"ÉfÅz†Qkðµm±]ò;moí{Óéø<Êe±a`hFõ…BAWžL3.¬JA¹ gIÊå2ÿøÇ›ÿ]Maƻ֣g7¸gÁ²e0Ûü«åm¯ïVGë%E“zŠÄÃàpf{9”Ê—†ð?Љƒ7ÃÄ_¹Ï€XœiÙb!†e½º_1|ËÖ¯¾ªþ äêÚ)§ r¸OÚHCÆ£Ô)P5$X¸ÀGÇãÙoG‹¦ÅÛÕßÏdþy3ÍaÓ±ü‹Ì›·oüÎqï¹­Êr0½ë"·ŠCg¢ÇN…BÑ<ãÕ?ŸüáI,É>;.m6ˆç¤ ÅLf"ì¶î8Ž÷?þyîùÁ=`Îi¸Žçy‡•â\¡/𮡲~ýz.\ˆã8Üpà 5ËÚÚÚØ¸qcSÑ)W\q«W¯U²jÕªA©GvíÚÕ”Ú™Äóà¸7¼À›ZZb·Va ñVš "ßHšØ”ª®ÓžXî!Ä”lõÿ$ÕñO¾óIo±,aæ‘D’P ¼€ß<û>è~9…9ضyS¿ø//âÿ\ÔtH r_²ƒã8hšÕ~(VŸÚ<Ï‹ö•Íf1 Ïó°m»¦FB&“AÓ4lÛÆ0 LÓ¬[¤QÒ²¬¨Æ„ÜÖ0 lÛÆqôª—GG¦i¢iZtLß÷gLí‚#‰¡ú&ŒMÿ\¤ÃâUÏÆÈÈ„QŽ2jAÖÊø—o|Ã0¢z)VÞwO?]ç’K[¦’`ýï6™úf8¤p0Ô¹Èûäg¥’økÛbY.!í«Ù~¥i#[àd$P=Éë—ÜG&#Ä iˆ5 ±®ï׊)®§þ‘ÖtZ¬/ÏI×c‘ª½]¬+Ey̓CÖoÈdD[{{Å>ÚÛk¯­ã Á QÎ÷}ºººš»fSœñîŸ5 ÿ/,]ç™ð»/dÅ;Å'œ@áß×4½›Cñ#’¿pÙóüľìê_$ª!†îq6Mùë ë;Õe9âa_Š(Rt¡º/ØÇBféÔªå´À­.“ŸC<Å ú™¬)#×É F!±p$Ûš¼^žì]zhßÝd!…[ßý]вIòyÑ“¢Ì a<ç¶2ýÛ *¤PL:v*ŠQ1^ýsÁ8¦ûR&Ý™Ãt&oÆÛn+9ðì,þjË”[¯¤Pº‹ŠPQLEFU”þÊ+¯äÊ+¯¬1P-\¸°i5rÓ¦M pÑEÕ죭­ÎÎΨÈQgg'===ôõõqñÅê„tž[{§|åX°\–•þê_yóÌ1Øz“tµ­ÚƒR€k»‘¸ ëz$ØgØd‚ ®ëFâF*•"—ËE¢‡ad«žÕ¹\ŽoÝö-nöo¦X,F¢Åž|—r)ǾG„§:Žƒïûxž‡eY„aˆëº‘˜"Å™Oв,R©º®cš&žçQ*•ÃMÓÈçóäóù(õQR´Éd2èº{ޝ¥>È8-ÿ—u º»»IW½øe!mÛ¶) „a†–m÷v*ЦÏþYù«],Ý»w²OQ¡˜¶L„ÝVrÊõóéÿ«wqpÁÁ†v¿ ¢,: ÅTcT‚ФÙ:)õôõõÑ××7¨ˆü•W^ÉúõëY¿~=W]u«W¯fóæÍ¬_¿ž–––QÃó eÿ3œsô9ÂB!-0Òj‘´È4a§·m;t]Ƕm|ß":,ËŠBÐÚÛÛ±,+]t]Ä)`d³YJ¿)ñnýÝ@,LàÂþd½läA”†+)ÐHD“e¤Koooô^Š24®P(4Œœ©iCH‘'¹MRœ‘Ñ*©T*Š€Ú¨dÈ^*•ŠÎ'›ÍFqy½ë£]¤(”›AEˆ§#õMà°ûçÞ-°ìèm,Ù³'N÷5Š<&2-ükYÖ 4wS]Ÿ8±d¼(×K꜒Çh#}@f“…°‡Â0„“$ŸBÝ q鞈þ™äç÷À²óaÉ¿ a!üË5c^¸q¬0¨-MÖ :£g䨖t-ÐÛȲk½#ìO«®#Óe¨w„àb"‚`!.ëv½o Á8öAlΊ"oäƪË'ŽÆ™Rèúжœ7Ì0'‰ñœÛ†a㌠…bd&zìT(Í3^ýÓóà¹kó¾»O™ìST(¦-a·•ü!/íùK÷Y™¡G¥üRLEIP9Tdçеk×ÒÙÙI___ä0Z~@Ë+žåÀ«À» F)hzUëQ>Ÿ§T*EØeJ,9¢“Ë×ÒØ+…‚îînlÛF×u4MQÍÿa†&Z áãS.•!€´ŸFÓ4a"Ú%[]WF¿Ä¢LX]žŒž™tdÝ£b±¶Î“ë²ü–[èzÍk&»…‡ÍxÎm«åêùV¨PÉLôØ©P(šg<ûçì•{€ãÇ­íª(ýÌ`:ùeN4a·•ôÿv­¸§<Òpy½£¸B1•˜PA¥Æb2ûüŽœÒ{|ìж—Qýýýd³Ù(âÄu]Q(ý•ïe .)\4U¤½šèÝò,À4Laq¡d•„¥E&m¯VÇ]í®æó~žc¯=¾MléÉ»ÅV«ê¾îØ×ñë³~MkªUXa2Ä ãåúõ•~½ê{™Þ-Ð0 Fœ,>YÝ7™^žV"“¼¶2²G SòúÉ´iÉTc…Bt:M†d22™ aF"•ã8d³Y …™L†l6Kww7®ëb†Êµ8ÆNÿ|ú°èéEœr £öP–iîdÄSa4ìG¦Eýïi§qÉd·g‚cP¿½îôwõc<ú(†5u# dMYe¼õOÆJ´ÉQ+¨ÈH›–ãö3ç/ðíDþ»z^ÒGBF¦ØÄéÈâá7‚Û‰‡b9ÜO*aƒò­–Å ý( _ñŠÉnÝ„p¨}3fL B1eQBŠB1u9”þ¹Ñ¢qoWžÚ¹–bú¡æW‡ÇXg–ýù2–4\žN§)ϰtÁŠ™Ã”T—{|8þÜGiÙòÆQo+=àeT„ïûäóùšBñRΠ+#.FMØ2$“«Ëj»I¡BZO2ðŠ8¶x,¼oˆõª¯ù½óyõ§^Mow¯RJ*£1¥@ìº.¦iRÔu¼óqþû—çqÌÓâÄ‚ Àó¼È™CraHP³Xˆz,ß8p€¯ìÝ --Ñ!ÕÑ!j™F䣡!†ã Tƒe˜‡ gÞüf˜;—·ND;¦1*ÃB¡P(Íaвwàðw4 ɧQ‡Ø‰%0{hˆùÚô˜E+“ÌK/ðü1–¾½± RïT­PL%fœ ²SƒwÏ^3ªâÒh+‹¥Ë‚ðM¥êšdŠC•¾›Äh·×‰Óåˆ#^dôŠ´âÔ'˜OŠH&q´N¼óŠÿŸ½w£¼ÿ?¶ñÝ–=ÂØ# #î2‰h „U€«“]“æ4°jššþœì~“æž´»[Bi›hIBnm±¶¡%)·h —`q³51cC@cÉ÷«~ÌžÙÙÕêbÝv$ŸÏóè‘4—wÞygμï{Î{Îy?~úôv´z£ñž‘Ph@s¼2ðŽï¼ƒo=ð-âV¼È°&ʰào×uý¼7~L”[§qty"UoÙ1¤cc±˜ºMòö ËëKQ”ÃÂÙoœ üΙ0š\“ò¹JÃu]ÿ{ßÔÔTdŒ—þ!™Lú†y1îZ–åçU|J(„'4MÓSX–E[[›ß×Äãqß“R‹ڶ›Ë±ñ÷]lÝùÎïìÄqöû×”cb±BNµx<޼íÖ[ÙúÞCbTQe쉄ÿ\¼³yÄe7bœÙl–d2‰eYEYù¦†áÕ£Ñ(Žãõ bXI¥Rض]dLÏ1v”öâ!\ôPšoÍqb±ÍÍÍža#cê¢w­ÂжëH§k±,‹T*Em­÷wkk+¦iÒÔÔä‡'=c×.~øéO“Éd0M“ÆÆFÿže,ãäržL¾¿ûùÖ­|¶ªŠ›fÌ ‡·6A&þÁÐ`N³­­M=8+Àá Eƒ©íJ‡\.žS/çåq‚ñ ä΂Hp»Á­¦ÎI¡ÔÁWÜï/”4„ ¥Æ áút‚Ûú«O&P¯4…H¶ÂP§éMùzô·N)vÐ ls×°KöBÆØxpã%åˆÈ)ÙnçËÊ .Çr;p^c~{0ªo°þÁUÖûßóŽÞ»—†!¶¢(Jؾos6oNøÀ ž>¼A÷!”¼Dè"Vìz ±Tó¹mÅ5ÅHMšõÿÆM¹ ŒeÞ5Ü·€qIIy¹Àµ›½ó‹žÊ‡ÙÊ×9¸â!B¡ŠSè0¤Kºü-þÒuŠÒ±HþÜà "G¡3«½t0Rl`¿¬®vîAÜÀ9'-؉Ú:˜gâ–Ô£ÜßF™}åýÁFàšÁÁ”¬tû’U2 t KîZÇ 'õ*óû™cC÷+J™t•݇`úiÓ‡¬À¯¯¯ð¡ËŠÒI³s¢ÞF0h<žÑKW (ÌRehÁ¢è"¯Ó»ßÃàmÑ·Á2¸à– Ø{Í^ù¤Õ\øH·´´Ëå¸íÿÝFGo–eÑØØH*•Òùp€÷]þ:oºwß ÇÚ¶M&ã©;\מbŠ2YøðbØþ*·4¾ åÂoI޳`’Â\.G6ëÍèZ[[Éårþ7ݲ,?¬c<÷½E Ãð÷—öûÁo~Ð@Ü.F†R£¯„üŒ ±§¥¥…k¯½•].\~Ôv¢ó‰DÑ5š››}ƒ‘´‹ì—{•Pc2¶Éd2¸®Kss3‹n½•ã¿üe®›;××´QPºË÷Òo~“?ÿÔ§*ý ‘ض÷SÑC8{ ; 8æf0æƒs"¿³œ÷K½áNoè”Ì yïÁ'òî“BñÆNÙÀ .ž’G<ƒ¡(^”A°-ïO¿×…UœB”Há·½Ò íxo[r˜o@ó2 –}Ʋõù]­AWAêŸ'—ßm9œ œmO‚sŽ·¿ß‘]I^ÂRï¿pQh‰2F”,V?ç¥Wþsk÷€uG }³ö Œ‹kñ†¿©À¡^µ×´!P¥¤Œ …€ÿ¥eäwo^º”ÓÚÛQE™HTŸò"ó¦(¿S ’|N¢hÈwXV•ˆÑġЩÕç÷µà…./5ˆu;o1€–CmñºÍÄO!ýI`:D×@îvÜ×!ñÀ"0_Ç”%¿%^«ô§’Ì%hà(52¸{wòeɽKò—h~{ÐBŸÎ—‘ Ø2/÷˜Ì—§°  ý– °*Cþ—ÕÒöŠ3bŒCŽ\CÜA))?hðº|Jž_©_6ÿìÜÀ5ÝÀyÍò$·p$P¦Œd\“Í¿¹B{-ܸ³³‡ýþiÌ7`á¼iœsJßј,Ó…µJ˜™T×…åŸÛÇîæÝC>Ç4M_™!+Q•ð1h~YÙ!³øàj(äriƒuoYÇ%¯]Rè¨ë çYY‹ãêŽãÐñÿsï™Ëí;oç¹ÌsTg«éêèbÓ¦M,8iŽãÍfY´hQ¥›'ôl°áW?:Šï.™2¤ã›››1 £(¬Ž¢(cLÚƒwýG¥+R@¾[–å{ ¤Óiß›¤ººÚeš&mmm¾aDŒ±¥qw Ã(êë'.ïh.¸(gtYºt3‰„ËÓËžæ¢Àör“ 1””öÙlÖ÷*ƒMpœã8 gœA|áB6Ýy';þ÷¹ù»ß%ûµ¯ÏçƒùΆ L;å<À©þ0/8ÀÿvvòŸ55þ¼²\z5eô0 (}ì2ÔÉö@ôAˆü ¶±0Á¾ì³Á™ ‘Ï+Á4!þ# qQD€VŠ`p>+""+^¡`L *2ÀWØXµ^üz_É" “B^?Q|Ø`å E1H‰R#¨lÉR¼r6¯¬rª)(|DQâÎÇ;'B¾ Äü²d{’âU©Q Jœ¾bÈ qÿåŒ(jÄåÅ¥0Þ´Àˆ‚!«veŒ*ak¥}dåq¬ â†À>±Ì´xå¶ÞÆàÊ@ûä•BF3¢Hk ™\ʪ àØ‹ŽåëÇ|/v}‘Ws¯òyßàŠ—®à«ïý*¤aó¿læCg~ˆx<ŽmÛ\~ù啾ûгŅ%'læé7Εƒ›Íf1M“t:MGGÇÊWeh‚þaÖÎ^˜;·"Up]—ú|2u×uýÜ$‘Hĵ%a9-Ë"‰øùH$·ÈDæ=uuìøÃ˜{ñÅC:Þqœ>É;}ãg³Ù¢Pd÷­X}â‰8wßͲ¼g‹ëº¬¾â :::°êë1^º_ü‚Ë®»ŽoR˜ƒf(ÌKe>©ÓžÑà ¤1²) Ṡ í‡`|ø }”:`Uåÿ¹OQð# q¥\ J€¡"×lÍQ OÑÖÏ~Ñ, òz:Œ;Áp$ý([ä0?ù(=J¶±|Ýdeo3ÅáP(Ù&«~Å(¬i”«£ä>Ü|›:±?ÁòK¯•÷2Ÿþ‰BÎB)ÃÊß«¼šûi…p¹²ÒXž] $,˜¶úahЀ_Š¢L,:žŸÇiõ*xWÊwôp×Ì–öW# Чޮ´9°³…âÀµùß  ñªÂ§9I±=!Ká³oÑ'¸GyÄU £A†ZÐ0`¤i0ŠÀn °]yÁ@!ÏŠD‚ÈRȱœŸ+Ã'—ó¼=\¼ùK¬$žbþ’!RNY0–J€á*‚¯ë`ã9Ê, ì… FM”<·t¥o¹úCåp”qC=6™¯„S)- Þ6ƒ}M Fi\EQ&ÇNï,SB²ÒÃâvù?Nq÷#Î6Á(V) NŒPè²ÄTR“Èú'Qˆp5v“Ðc1xߨŒ+{¸âÇr }ö©.H™L*ƒÊ6`é¬ÙLß±=cJ&Á é4är|ióf/tÓ®]Ddg.MM^ì0Q6´¶+–ššÒŽÁíÁ{”{)ƒix$f¾ê²ºwnd.&&Žã°âc+hÿE;÷^r/©TŠœñŽºæ(>õƒOqÙe—¼Ž“˜­kw²pçQ/%÷UE_îüA/g¬ÛæùcR~&“!‰øßWñ@‰T*Ecc#¾)^H®‰Î¹ü ¿û]Ì1ZnÙl¶OxSiã––Çñ½x OÓzé9çpGSMßÿ>‰D¢È`#ŽžMõGð hŽãø¹È&“ák¼0Œ|"ñgÁJSl8‚§#Ž¡ ‡%é°^ÒÂË ÁDÒâ]TNÛ)KÒ3Œê úQG¼½`lµ¶ê'˜Ã¡Ü1£Q’üLãÊxµç$àÀ|þÉ?5Áèï5ª22lE2²’T$±À¾…ô#ÝRÒsAÁÛS%ÒfÐÁQ 6Í3¸æAʉ–ì“Üe êé·ƒ¹ãÅð#ucO0/üx‹\ÑÔ±áÍÑ},ný{ŒãжËBQÂΤ2¨‹ñÑ·½­°3ÁB ‰ÁÀ0<ƒ@0®ŸDâqÏÐ Æœ ArB”3ˆ†WFm­÷wé=d2…kær^}ƒûÇ3Œ¸n¡¥ ñÚ±m¯<‰ßžLö5¨D"^9b|)]ñ*Û¥li— ±˜WËòŒQA…Š˜²Yo»œ›ËŒ8R áɶ½rƒÆ®X¬`ü‰D¼{ÃŒm{çƒÑ¤o\Ï¢|2/2Iœí)˜ÎúÚYì½{/§œr ÊÀ,}«Aíöc€—û=FV¦+ŠRr°ïöüð’Ñ7¨¸®K6›%‰M;::°mÛÿ?•Jjž’‰Æ /¼À†çŸÓû(Ä©ëº466ÒÚÚJSSSѱâÝR.I¤„oò] \õÈ#ÌyöYÇáo~ò®¸óN>±b…FI8 6æ«ÿ}Ãt¹nqÖúrãÊpoÁ‹WÌöÆ„Á±^.7pùý-Œ ÖQά.²àh±ïPŠB¾–þÐaTxi¤ü:CÁx’¢8§,1Oâ}XåX1 Hx:1²JìYv.  E#š¡ØÈ&1„äØ$mª¼?n`¿äß‘°tÍÂʼn‡¿hB¥ü$…ro¢1MáYàåü`î!Yv/I¸ Ü_”‚X (R?Ñø&÷"û2{ëI"nÑèF)äÙRŽì'¿½žBÈi¢±–ç— œëPHl¡ÆZV*Ï·ÍIu'Ê+9Ù3e çí862!;‹¡ØÊ­Û7ñ^Û`$Èàí‹1EÄD¶¥ñ^Ý6 )ÎÄÒD!•X’‚§KÅ0eŸ/Oìúµ ÉÀù6ž˜HNA©“|’‚¢-ÑDE´ZòÛ¤þÁû•AÒ.’#PRÌÈgY Iê6I'mùÆi§qåÚµcùŠLìÍðÐßÂ7þ˜:+Ûg¿ê…”‰À¤2¨ÔDáÀ}ÌþøÇû”u}îs¬kjâ{?ûÙÀIÎû#(Ø¥Bnšo˜H¤86ôõX)Å0<‰xr”ZeKÏ/MØ]êARJðüàq®[>¼Ë`å *ýôà)5؈1Ç4=ƒŽüŸ$Èi&㕬s$âfR©B››&Ô×{¿s9Ïžñ%/x0I»ˆb@ê+F«5—Ôþ‰ÂLc&üîQæ/Á¢MÛT&“IÍe¤(®‚ýÝ1ÿá†Q)/›Íúaº\×%—Ë‘J¥üRÉdÓ4±,«È#íHwï>ï¼óØwâ‰LƒkÂ@c˲hmm%‰ÐÒÒRt¬x±HÈT7¯,—çkY–e‘p]Þøå/iùЇøðK/±kÝ:’gœÁÒ×_'‰7A5Ž>šY•nðã8° ˆÞüµÛ×ë8›-x&›¦÷;è‘Ëycñˆ†âE-²pGˆFûŽƒ¹~"È\êˆç¶eõ]è#žßàýnk+\GÈÈ‚˜ææâ{L&½û .Ø Þ£œ/cn(6 Ù¶W†Ô;›íëÞ”WÏXVÁÓºt1R6[XÌT:NÏu)#8vOniÓôÚ98¶/nY˜TêéÉÆ·Ì6Á ,@Êå óTjp£šÔ§ÔSÝu Ï*aÉ–-‡÷Â*ÅHx6ƒ‚°µÌ1)¼¢ä²xÚ?Ñ–N³$¶Zİ"†Ñ^Jò%9ß xɹ,ï¥Ø“C .~¬ F1zôõ´‚÷Ú¸Wy=ƒ‹Øšòõ´($”hÃÓN¦(h]ES[:•‘NSðÜÉÚBÊM³?¤ÞJQÚ!H3ÅËðƒçÈó Ö#FÁðLxáŽ)mÙ'Æ& OÃÍ—a•ßç_76žÄ“c~²•wÿݱp}¥k2±­DGÊÉäÿç÷ÕS0,A!µ™ˆ[Ð>H¿ B§YýòI[iø×xôì³Gðž}ŽÛ¿—}S÷õÙWžXQÂJÅ *===twwSSSS´½³³“ÎÎNjjjúìŒöÿ„ÞçÛÀüp¿ÇH,öL&Ó'äŨ3\…ˆLn;´¬¶¨{,J¨–ÃQ ‰gMWWß2JË1Í‚KðƒœHx†–àD¼ k.W0ì46&¿¥ïŠmç'ÎpáÕÒqõäIžÞŸlÂðå³ëx}Ëz,«ÿÑí˜Ë£¢LÆB>Ü?ÁÅ> ŒÑQq‹—Icc#‰DÂO(/¹Ë |N•#Óä-oy‹×Uhe–Nú[FÉd2¤ÓiÇñ=W$‹ã8tÿìg|bút6¬XÁÒ3ÎðôJ˖јËщx:¹ÓNãc/¼P¡†Fsl›H@ìL¸# ˜Mð¯Ž7¦‘ñÌ`c§ gq9ï࢘þ¬_¬–UlÄ)·_<óپï}*åý 6å΂÷iYÞ˜.—+xL1͘OŒ¥ß$ñ¦¶íòí!†(9&x~°-«ï~9?+,¦*}N²-ƒ-Àßµ *¦Y0à†gœiiñŒHâ©|F™ŒwL4Úw1•ëî%›å´?ü±“…±è;ëëK^o›‚Æ/“ÿ‰Óÿ*ùàëTª7 žÓŸ˜ŠuZöÅQ4å®Ý_׬Cin!sç÷GZR¡? jj€ÿËÔ—Þwé¹ÑÀ9åŒ4Á6(÷™ë¯.¢-.m#“þ5ÝAÏ¡—þ± keyïb²0šò9õÐTv\Ò ‘c+}[“kˆû‚b˜¢ÿh”©!n›.ÛdƒFqæ•O†xí8ŽƒašEŸ Y ôƒ;8»¦Û¶± ÃqØóg†eÛ¼ûÌ3ùÎÁƒ7{6ïÛç)þ]×%nš¾S`ð>·mÞÌo^}uüÆ80z[€==pÊì×øc×9£dŸÎ•‰BÅ *™|îU«VùÛÖ¬YÃêÕ«Y¾|9ëׯgÕªU¬\¹rÈe˜ÿ³üüýTd5¬Z<ô—¯%ŒÈä|¨Ï¯Ü}Yô–©¦RÞ„UB¡uuç‰l»0‹²,Znh¡î¸ºJ·Ì¨QN6adò9ûLxmËÒßr!ÇqÔCEQ†ÀXÈ'À†£`ÖòÑ­§x¥ó¦$«Ûu \Q=BH4-ÊsFÉf³þs—|)õB.`|âõ×énn曚øv{;[·n­ô­Œ*£9¶½) æw€““°ÀØ0ÑIƢѾžÌC½ CâõÑŸñGÊîïÍi‚K®]ZR£U¹zšæàF'ËòÚ& |ø|àÜ`½Å{§4”®0X;HY–ÅëW36™œ*Ãh÷ŽÓ7P€Z*‹÷Ñs˜!‡Ž8T%PqFS>gîÉâ‡Ã'+}WÃÇuÝ¢1–`Û¶¿p%˜Ð¶m,Ë*ÒoI 9.WÚ¶M$!›Í’H$|o€L&C<÷CóÊd9NÊýÝ׿ÎåŸÿ<δi¤Ói,Ëòs¡Êø0‰L&ýó à Ó‹B©›&õõõþÂ+˲|}€œ+‹¡%úh‰„Þ+‰ø¸ çƒL ÄÃAöÉDÐ0 ²(.™0ÊIΑIäk‘í2éÂÄS&^âU!á«‚ˆ÷…L¼"‘HÙ$‰r™ôɤQîÏ0Œ²ÞyõU¹<7Ñh´¨½ŠŽ÷NâóW_M2™¤ ØÛÝÍÚîîJßʨ0cÛWëŸî‚¹áS”# § Ç€±ë;%=#PW•£`HÉ )9.¡|X<1¾=…„๚8ا¸®·ø+øÜK½$§Ô§t&SðZ²íÁÃ>— ‹ö¼Á.lÛ¶o’ɤïip×]wqÌ1ǰ{÷n6nÜèË·¬Œ‹•„)•{YI&«Û‚Æ‹ÚÚÚ¢ãÅcš¦?©jjj"‰yÂÈ„2Hmm­ï=#.ÿ¥c1¾È5Å`à»®K2éEZ–‰™xjȽ۶íl‚Æ›à„®±±ÑŸÜÆM“M›6ñËLÆ?W&‰AC‘§lÛ¦±±‘æææPä  N`K#ÅH¤c1Î>ûìI3鋱íE_ëÞê¾9;B„ÈH9£d†JÙnšfÑû\zŒeYE+jù.«Õ-(ÛA#¦|7DËKË yE±bÛ¶_OQN‰âK¾gÁÕ³Á6)½npEf0O‘pò¦“a%lLn,R¬É÷Í0 ñ8÷¼ï}<œLx_R·D"á¯L–³mÛ¶1{oÆ“±ê;%¥PÈ™!ñh‚=ÉcdYØ+VàFQ2cË41Z[ɾþ:8©{ïíã0‘›3{Þ<ìãÇìê‚×_gÓ¦Ml?æ~·` >ñ ÞþÔSÌÛ³‡7fÍâ¡éÓ™¶?;¦OÇÎîíåñÎNž8ç–lÙÂëRµq#çuuñú‰'²éýïçø7Þàéãçø .à¨]»0^}•Wvïà„C‡Ø»u+GM›Æ?ÎCçÇ ùðË »º¸üÿþy{÷bŸ>öùçóáŸü„ÎcåÙ³ÎbÓÉ'sù“Oòúþýl9î8vµàVUëÒÕÛ˶êjN}î9v̟ϱ¯¼Bý¶mÜÿ¦7±gölö̞Ͷêj¬ßÿž®Ë¿øÏ8ƒ/½”iðæÇã³çž‹üáÞ{ɽöÿ”HpÚÁƒ¼8>‡ÞxƒmÕÕì›9“¯ýÝß1åàAæïØÁü;y²¶–My¹›6s& wï¦~óffÿ×ÑsÕUü~Áî^¶ŒcwïæäçŸgÝñÇófÛæ®H„³7nd÷âÅþ³š³kOY‰ûï§mî\v-^ÌS'žÈQÛ·“úÕ¯X}á…oštÏ™ÃÒ½{ùÃîÝ\üê«Ü≜î8ÌyåÓ$ÒÞÎc'ŸÌG‡[Ž=–eÛ¶1Ç0p ƒ§M“ïÿó?WZ´F…±Ï…] 9aïý®‚áÑq¼p‡™Œ7‡Ç ‘® µµ…И® ‰NÀ @&áøö.[Æã?ÎñŸù .½Ó4ÉårœñÈ#,»ûnjæÍcnW{.d×ÓOS__OKK ñxœîO~’“Ö¬aÁI'ñ¹êj¦]~¹¯ø_v÷ÝÔ¼ýí´,^ MMÞX.o¨°,‹¶x¼o+—ó¢Ñ¥R¾¡!•JA6K4aï­·òÛ½{™išXyƒ@<Ÿ#Ëʸ,€€÷x$o̸.$“DòÑK¤Nå£xD S,%4».Ø6f.çµws3äs)bÛXš3ïÒÛ˜¦é…Z—>/¿¨5"åÛ¶·?ï±iäu1¥cÿy¢B2IÔq¼g/‹fƒ×—E³bX.É g8Ž·?_n4°×4MÌ|ØÍOÿüçüòÜsÇ_˜Æ€±ÒÛ /þ3t—xóˆÑKÆ&ŠvÆÝ RWçil,XP´½½½½EsÁ‚e;Ø ¯¾ú*«W¯fî9«Ø¹e?<~ §—9.—ËaÛ6---(ʰ)‰Ÿ½úÁY·hSézýÉ& _>×­[Çš5k˜Æ•<^UÝg¿ëº´´´ô«_Q†Kgg'kÖ¬™4J¡Ñ–ÏmÛ¶±zõjhhhàà‚œwöNàÍeÏf³þê2ð”}™LÃ0¨ªªâå—_æŒ3Îð•ŽýH£Ñ¨ïEô,'“I‰Äa­JŠÅb8ŽC[[[Ù\LåÊ 7е‚«âú3VˆUÊ1M“ÚÚZ‰„ ’5H:¦ººšD"išÞн¶6þsÿ~^Ì+ƒeÂ.õ®”2%dƒ žB©Tªì÷5Nûa ¢Ñ±‹I¥o4Ó4™5këÖ­ã裳k'c1¶ý]b/ŸþèÌÃò49 Ê Å !0Ę…Ä…BRPyפ<ðÂ÷ɪXèëµ$ÆŒRd»üM‚u£Ki“d2é4†B©AAîS®kY±XlPcd©7[cc#@‘×”)†gi¿H$Bcc£¿êW ¥ò]{Íårþó ~S„ew/cÉÃKxüúÇÉår455ùF^1ìȵS©Ô€ V¤®µµµ~{JÜ|óÍØ¶Í{Þóž!¿{ae¬Æ¶<ò,¦yöOŸÅ:ëG±` äÖ"»r%6^¾€x"›HÎÚ·ÓgÌà+»w³dçN.èéágS§²uëVf½ò ]],‹Ç9pàSׯgêÑG³oî\ænßÎâ;¨úõ¯Yì±ìŸ7Óž}€?Ú6‘½{±m›û¾ô%ö½ú*ÕÕ|¬µÕ3Xš&=§œÂíØAÓ¢E¼ÿÁÙ3{6®ëò–+¯äÿUWsâoˇ׭cÓÉ'sþæÍÌÚ½Û7`¼uófr¹ïŒFéjiaÙ9çðù÷¼‡¿xî9>ñÔS¸®KÕ¥—òýw¼ƒ3^ëî»/¯_Ï.¼©ÇÏÍ7²­½´iòÿÝy'Çæ=+Ö¬Y¦ÉKÇCww7ÍŸÿ<Ówì`~>¯ÖcðÃK.á/7mòs2Lß±ƒêÇç_Î9‡®¾šÛ·óώúNàwïxoÛ²…)gÅ›vîdÎÒ¥|âî»ùã·¿MÏœ9¬XµŠS¦MãÀÂ…üòê«ýgùü²e<¹hïÍ/ Y¼{7OlÚÄ3g2ç½ï¥«­šÇ#¶q#³òÆ¥)'ŸÌSÇCú/ÿ’ݳfñìò圴q#÷¯[Çû¢óSŸbýÿȵ›6q1ðèûßÏMW]…ùîwãÞpïÈ—wúìÙ|gÕ*f]v—\p®_Ï#—^ úÿjš¼óî»ÙüóŸcY===l<ýt’ ò•®Q`,ƶÇvíæÐ¯¾ ?,°¬r!¿ £(7«|G¼±Z¾ÅMy%oIJèJ¥|¯Û¶‰þË¿`üä'à8ìëìäÆÿüOÁ9nÞØÀw¾ÃTàtF|ÆÍ7ÃÍ7×—À•Òp%‹„¯üh”™Ž?üañ¾DÂ3 •˧&å56zÇD"åÃouh¹\ÁøÞß’{6˜×K°•®Ûn¶XVáIŽ°Ò±{¾OÆq¼k§RÅ•TÊ;OÞ…ƒ ŽãÝc <-«PÇtÚ ÿ.¹zóm°yýzn_¾œ£.d20VzÛ•+Wzçï†ÍÏo.£ÈxHäKQF‹5kÖ°nÝ:ß8ZT,‡J)ÝeÂ> Åelîܹ444ð›]°ìÅ×Ù}ÑE}Ž Nhe4ihh`óæÍ•®Æ˜3\ù\¶l Ï;LéW±"«Ãe4‘•3ƒ­:ž G>gÍšUäšýø/qblqÑ1>@}ñxœ––_ØÑÑá+@ƒ+©ò6YïoÕQj°$Øe¨ô€»´Î2ù*|ûûÆ%‰"ošl6 ¦Éƒ==´þìgþöÒñ‹üßØØˆmÛ´µµÑÔÔDmm­¿Ê=‹Å|…«„Tåk<÷cR—Æëåqd2I&“¡µµuÈßìr*ïh4Jgg'sçÎåµ×^«è³kF2¶íÝyÖGËïã¦|ßD1oš¦zCŒ›ªBþŽÇãýʨë‚ßMÇqhmm-:G®oƸ‡ë”%£Épî!‘H”q$hlŠwHF¢õå¥ –ÇýÐ-âÁÒ¥!M‚Ì™3Ç7žOfF2¶}챸õV0oj!û¡³È^r:Nu5æœ9D¸msÛ¯~Åÿ^x!3wíâоÀΣÆfÓ ƒ\þ;û–ü;t_àYØ55ä]€rHXœL&Sôn ¥?}?ÀYgÁŠý#ßþT~EüeŽñÓU¼ã¼½ÐX@>šèYgùÇ_T—á<úIñþ÷s[ɦwË"‹çßzjÙœA¥™VmÀ:é¤Â†`®úº÷½¯Ï¦ùrÙ,Ïæå<ãš ðƒôùf|àŠë4H¿õ­ðéO^rèíÛ·óÒ$ —9ÃÛ>µðŸ8ù}ïcVpG?²\ì"ýšäÛ•ç”L&1 £(Ïgu:üWÔ˜&5¦Ió%—_È0/Äú`ÞÆåúÁä} H†qx9jËõaÍÍËËh-ÞŽA&XïþƇãáHô}ž¦É¡¿ÿ{–Þ¿ŽmûAô¶b yý½pü#ûx1°ôÊ4M?̳¢Œ&Ë—/çÑGõrCcP)·2¡³³Ó·ŒöǼyóhhhàG˜Ò»‹ªK/ísŒ„ÞЄ×ÊhÓÐÐÀÚµk+]1g¸ò¹lÙ2^›v óvõ”Ýoš¦v˜Ê˜PUUECC·ÝvÛÈ 9ÑO1¨ð Íö?ùçç9’PV¢P †Í‰D"~ˆÇq*nÔ#o”ËÓÒÇY< $¼Q.—óÃLH¢xIßÔÔxʶ¦¦&ÿ9Ú¶í‡3 £O¾9IöÙŸçÁáPSSÙgž9i<Èúc$cÛ]oL+äbÈ#^ g\¼#F+,‚(áSì[P ãMXG•Ë#Tî˜Ñ½èàu1•ŽmÛü\² 3–|™{> Í3aóúõ¬½õV’y¥l$áCû÷ÃôéX¿úUÙ÷Al—®[!fY`äS¸f!…Šeyº@ÇñYËÿ¶Á‹¦“¶ QuòQ{€Â‚rÃðö'…B(<>­­…ß1ÇâsŸû ɤ§Ç ©aLÓ»Véú•Tª!'‘ðê,Mà8Å×H¥ ûó)HˆÇ x¢ÑBJÛö®{ÿçrÞ~Û.´c>j“_GIK#÷ …Eìé´w\s3ÄbÞvi»TÊ[ˆ.u”ûŒD וöÍG#"Žcšqêë½kJ´¦ÖVhŒ™#ÉùÒvÒfŽcù÷çºÞùÞ±Uüw¦Š…giXîØvñÔNªV|}ÐòÅÓZÆFâAXÚÇ g¡Ï„c¤}UI­#ÛMoëÿßnªŽ¾öŽÉd2e=úe¤ÔÕÕ±,¿Èc4 A¥®®Îsÿ ÐÝÝ=äÄFxNe[Ù•bÑhôÈè eŒ‰|Î7 þ`žÔW6‹µŠ¢>#í?ú“Ôœ} PxŠót:ÝgEx Ý`rMY ¯Œ’f¨ßDÃ0ü0=âSš»"ûÇD£Qßx"F˜t^ÃdYVQ‚T1Ĉ·‚„‚*çõ5P˜·#™áÊæ+¯œÉüžàþˆÍf‰ÅbD" “y$ã2¨QE:#é;#XûeøåMð›™`¸.±÷½T*UÖ Ìq Ƈ\Îû[þE†”¼ÁCÒÄã…6¹œ—¿^¢ÒˆáAòÔKjÑm .…”ŽS|MQø—[œ]èþÏ£««…T*Šëz†Ç)”!çJ¾ûà­KbàëË¢~Y‹‘OÉ€m{ûÄ \«4$äžÅh# íÅT”Þ§m{ûå“ÚÑÑ·J£DIû»í˜åìÑb)Y§P–ÖVïø 1)è<IÁßÞã@٠瓇áÊçUýhÿ^yJsßÉB!EQg¤óNaߣxjÇSDZð{L$:ÆU&¡1¨444ÐÝÝÍÚµkihh ½½ÎÎN®¼òÊ!ÿæ°èGSÊNèc±åFHŠ¢ ‰‘Èç wÀÆ'Žâ“ï(Ȧ(ñJÈ(ŠrøŒ´ÿüŸƒ—R³xºÿ2™ìW6ÇñCIµµµ©1t ,ÙvˆÇÂ`¡~$4àçM(}Ö’ÏÅqœ¢ñS0ŽÝ à)ŸD5•Jù¹#‚uÕŸGÕÍ='-`ÉYo@$â1;::´¿<Ò±ðŸ+£Âpåóå——ðÊðûwÃUë¡©±ÇqH$ùŠ„õxJþ|z_ ŸHä圊‚ÓÖ žWŒA}“l ü;xlðïÃù$ËÂÄ`ä¢RýsédŸyJ·ë\Î@!”GÊÝGð¼¡|.‡£·ãÏáp8Ñ„äãM1t {l[æ%‘ÜRÑhÔÏÕìOË¡¥(J‘Î;rÀÔ×ñûÙ‡¸1ð!–9¨¢LBcPXµj7ÝtË—/gýúõ¬ZµŠªªª!{ÿÿ‚?<Ï7 Q[o5íxÇwV”ÉÈpåóñcÁ=°µ‚°¿D©Š¢>#é?Oùäb>¹Ïû[rõ'›†aà8©TJ)c€eYd2™a­ÎŽÁ¢?ï]¹~i™âA“L&‹Bµµµ‹ÅŠBR‰‚QÂŒ¥Ói?¿Ç‘´úl8²ùæ=›¹fý§qÝ’L&iiiÑþRñ¼Stõ¨2ùܽ{S®åØKèü铆AGGÙ¬2JÂr§Ûï ùì©(+#ÁÞæ|™ÄŒdl[ŠŒK‚‹JE£!›¶OeÙÊâLª·U&3¨Ü~ûí}¶­\¹’††:;;©©©9,·±ž§áÂ9OöÙ>É+e2SN6aò¹˧?‰e^j"zE£.ŸÀw>—Ëû;N—ÁoÛ6¹\Žl6ë'¦WFIŒ†ïcs ¡n¹z¦R)’É$‘HÓ4inn&‹ù«´Éår¾ÁÅq\×õ½›žþùJßâ¨3ZcÛêmÄš²‹d:í‡ZSeøŒfßùÆ è¨^Ä•î+ü·“áþû3ÄbžJkk_ƒÉ蜧Œ!“±7‹±­ Iå\×Õ0ðŠr˜Œ¶Þ<³úµ>Û›ššÔCE™P„ÊCvgy̧ºxã{‹¶IŒp5¨(Êè0ùÜvï&ÎܾµÒUW”IÏpäÓØ —Zø¹4Êõ™®ëbYÖ¨$è`¾©x®¡Oe¢:ƒÊpéüêÞÿÞâ5‡“ØUQ”±áÅ}3çÎ)Ú&ÊYEQ*‹ | òp*™L¦¬òVrehŒé±Ç0ŒPS†Ê`¶rc°D"ã8\pÁlذ¡Ò·Jþ4>Yðsâ(Š¢'ÿŒíÆItï;gý~’xEQÂ…Œ_'Ò¸JQŽÈÁ ??ó–)þ¶L&S´PKQ&“Æ 2kΞ>Û\×="“ *J˜Ø¾{*³7¿P´Í‘àÒŠ¢Tû•.žúÝ4?éhÿÿ\.§aƒ%$üñ‘]L}a–¯"¡Òé4-ËDQÆÛ¶Õ+LQBÈ//¿’í¿þ-7ýšJWÇq|å»ëº8ŽC4-RäCAA/ yù[Œ¶MMMEFAŽ“±@"‘ —ËùÆ… !EÆ÷étÓ4ijj"•J‘Íf±m»ÈP"Ç&bŒòÅp!ã1n”[”e±XÌÏé%õãŽÜé}ɵƒ÷(†)GþIšššhnnîc cl—¼sÒPÐQD£Q’ɤojmm¥±±‘T*UÔ6Á|fÒ[¶l©ô«z2™ ¶mk’kE !Ýß<È¡ì,ëÝþ6ɱ¨(‰IaPùý¿mà„ESŠŒ'±X¬(–·¢(•áàs˜_õ'ÿYQ¦(Jåy¹ã§œàbÛvC§äTÑUòŠ2þ”*6'#¢”û•Õç¢*Yû[õ-ŠNù¿ô\(¬.e­¬®Ž—ö–kËç\±Íf‰Çãd2‰„¿R>“Éø+ØE)*×|er°R?)K»¥eÃAQ~¥«çEi\ZOY©,ûÑG¥¡¡¡Ò¯H(¹ä‰{¹ãÞ;àë>â²DaŸÉd|{<÷ß­t:Mss³oœ…»<{y?å9—¾'òÌ£ÑhYψd2I$’KVÛ¶]v/`I(,¿ÅðÇ‹æêRž(¼¥LùÝ_¨¦Òãäw[[étšh4ê_GÆ/ý­|£‡”1”ÒÁ{/5z—ž/ãªþ¥”¶•ü–ï…eYEÏMäóž{î´žG:–eéøUQBÊ” zxjáSÜh|Ìߦ‹ˆ”‰È¤0¨ôžr ‡žy±hâ)EQ*ËÒãÁïït:M*•šôJ"E™(¼4uï88“_”„¡‰¼æpP”ñgß¾}£ÖO•îÁp5¢ÀÅmSS“¿ú¼t%{¹;ÍÍÍ466ÒÚÚJ,£¹¹Ù7H_\yDÊ ++µ³Ù¬oÐÖ_V|ÿb”þ¬»G‚«è¥¹'9§Ôáºn‘AB 5rN4õ•á¥÷'ßL9_~d»(Šå\YÙžH$|…¬|{å\i—`rå`ˆ"Û¶}å»”-Þ…R¦Ü«”-«ùË•}üñÇWZ BËË/¿<,ùL&“Ež$–eù ’8;8•ðˆ†aøÛ»ººú-?¨è—¿SP gÓp¼Ì‡Ó^à ÿr¸u s~8‘}åðqG½«%¤¸À3yðµ;ÕÔ×׫wŠ2!™ÒÛÛÛ[éJŒ„ë®»ŽÝßήÿÀÏ|6àMr¹œ®‚WÆ…Õ«WÓÐР+ùJøø_úçUüüÇ9U¤æcPƓ뮻ŽÛo¿½ÒÕÒ.'}ý±'þ‡£/ÜX¤ˆH§Ó¸®«ý¨2fH±jÕªJW%t|èCbåÊ•C^]›ËåŠ~EÆ ›“H$|o… A!h8 æPeÞ‘‹Žm˳víZ¾ûÝïrÜqÇ Ø?:Žã'Ø#J"‘P™RFÛ–GÚ%ªMQÆÛöÈgnË>vÁL–Ÿ¾Ò_, cSEKÆbl;)Iþ ] (•A¼&E [Úº˜9çX?2‚„«T”‰È¤0¨¼²ãg¹³/žq.—ÓNTQBÀì{ˆ¾÷I?ÜF¹D’Š¢TØþ3èÜú‡"å©„úR%Hø)Çq|O ÷¤ ˆe|y×»ÞÕÇàiÛ¶Ÿ+Gç ŠRYÔLQÂËoO>™Ó/ÚêT4¼¡2‘™Zé Œ‹ßÒÉûOÜx9œØ®Š¢Œ>¯ý±†'µÄO®¨ŠE 6ppCo‘b(™LèJ!E bLÉf³D£Qš››ÕÛSQBD:ö›«g§¢TñS%œl}b&[6uø‹÷2™ŒT” ˤ0¨<ýícyãÜ7ÏÅSRQÂÁkGW1µç5Àë,E ëö$—}âQ…OL¯ !E MMM¸®Kss³Q%D¸®K}}=ÑhTÃ{)JH0 C½¬%Ä<µê¶a¸®«òªLh&…Aeƾýþ ø–––JWGQ”<zÜ úÀ~Ç!ª±SQBÄ£¦òÊ/ú•¦¦&ÿoEQ*‹ëº455ÑÒÒ¢FNE !’·HǶŠ$ôž¢(á¤Û5$¦¢ŒÃÛsƒ×VÞëoSƒŠ2‘ •AeÍš5¬X±‚Ûn»+V°fÍšAÏ™òë£8ï•͸®Kkk«*ƒeŒŽ|ž>kÕógbš¦æOQ”1d8òÙ³k5Æ!@Cò)ÊX1ÙÏcL=SelŽ|îÞ½[sv*Ê80ùÔù¦¢Œ=ÃÛ>ÔÖÁÔßâš½×L&uœ«LxŽªt‚¬^½š[n¹…††ÚÛÛY±b ÔÔÔô{μ©.™2t:­¨¢Œ!ÑÏS§¼D÷IÝØö&í0e Ž|Îrþívb±˜†ËT”1b8²¹oß>Ó*Ê80ù|ꩧعs§z§(Ê3ùTeì®lþðÁi,›·…3®:Ó1Õ;E™ð„ÆCeíÚµ,X°€††êêꨫ«cíÚµžw¾ù,<³‹x<J\½zu¥«0 íííC¶(Wа·á‘Àpåsþ óY¼xqh“u†ýÝZ³f ííí•®F¿L„ïÇ‘Àpåós¯õrö%g‡²ïœï–~?”Á®lΘ1cR,B˜Lï`Øå}¨L¦g2R†+ŸoyË[B;®=ô“噌ÕÏÉÀD•ÉòNO¦g2R†+›/¾ø"<¹ˆ¿zi>oÿ‹·‡nœö¾d"¼ƒa—÷çž{Ž_|qTË ‡J{{{‹æ‚ ÉwgÏüûÖçS÷|Š|°Ò·Ñ‡{î¹§ÒUÍ›7³yóæÃŠ}8Þ„¹ ×­[Ç–-[8å”S*]•1e8òùÌ3ÏÞšfIïœÕN¥o¡,a~·À{¿}ôQ–-[V骔%ÌßíÛ·óì³Ï²yóæJWeÌŽ|þñäáe—R¯fåÊ•¡…ùÝôû1|6oÞÌsÏ=Ç 'œP验)ÃÛ>óÌ3Äb1.¸à‚J߈ó;x¸„]Þ‡ÊPž‰Žmû—Ï?ýéOÜu×]<÷Üsœ~ú镾…q$½Ó…Áž‰ŒmG[!F†;¶Åb,[¶lB¿a %¼¨|*J8QÙT”ð¢ò©(áEåSQ‰ʦ¢„Р¢(Š¢(Š¢(Š¢(Š¢(Š¢(Š6B“CEQEQEQEQEQEQ%¬¨AEQEQEQEQEQEQeÔ ¢(Š¢(Š¢(Š¢(Š¢(Š¢(Š2jPQEQEQEQEQEQE„i_ùÊW¾RéJLT:;;ioo§³³“ššš~÷,X°à°÷&íííÌš5‹™3g†ª~===ضMOO‹/>¬:Œgû)‘Èg¥es(u¨´|†¡~ÊÄe ù Ó»5ù¬´l†­ •ÉÃXÉm¥ÞDZïñ¾—±ê§õ1±Ë9i˜äs¤ò7ž÷2–s\•ωÅXÎI+ñ.ŒÅÜ5L}çHëªòÙ—0´IOO¯½öZhûްÏÛÛÛÙ¸qcèõ¶ã®[ëU†Å·¾õ­ÞúúúÞk¯½¶÷²Ë.ëýÀ>ÐÛÝÝíï¿ãŽ;üýõõõ½wÜqGÑùƒíM^zé¥ÞúúúÞßþö·¡ªßúõë‹Úð‹_üâë0ží§L'c9'­Ä»0s×0õñ™„°´É·¾õ­Þo}ë[‡]¿ñ¨ØçÆ_üâ{/»ì²Ðëm+¡[SƒÊ0x饗zO=õÔÞõë×ûÛ.»ì²ÞL&ãÿ|ëׯï=õÔS{_zé¥!ïMäžXa¨_°Íº»»{/»ì²Þ{ï½wHuÏöS&#•ÏJËæPêPiù Cý”‰É`ò¦wk8òYiÙ [*“ƒ±”ÛJ½c!ßã}/cÕOë7bâ0ÖsÒ0ÉçHåo<ïe,ç¸*Ÿ‡±ž“Vâ]‹¹k˜úΉøLÂN¥ÛäŽ;îè½ñÆ{O=õÔ²•J?Ó°ÏÅ)žrõ ‹|WB·¦9T†Agg' ÔÕÕùÛ®¸â º»»X»v- , ¡¡€ºº:êêêX»víö&«W¯¦®®ŽåË—ûÛÂP¿µk×ÒÝÝÍ 7Ü@UU¹\Ž+®¸bÐ:Œgû)‘Èg¥es°ú eÿh0|†¡~ÊÄe ù Ó»5ù¬´l¥T>•á0Vr[©÷q,ä{¼ïe¬úiýFL,ÆrN&ù©ü罌åWåsb1–sÒJ¼ c1w Sß9ŸIØ C›,_¾œ•+WÉáPë7õûܸ³³“•+WRUUà‡#SÝš‡T†ACC·ß~»ÿOO÷ÝwŸÿrµ··÷‰{·`Á:;;‡´´hooç¾ûî#÷Ù^éúuvv²|ùrÖ¬YÃu×]ÇM7ÝTôÒT‡ñj?eb2ù¬´lV¿¡ì ’Ï0ÔO™¸ $Ÿay·†+Ÿ•–Í¡´‘ʧ2ÆJn+ñ>Ž•|÷½ŒU?­ßˆ‰ÅXÎIÃ$Ÿ#•¿ñ¼—±œãª|N,ÆrN:ÞïÂXÍ]ÃÔwŽ´®*Ÿ} C›ÔÕÕÑÐÐP6/FžiØçÆW\q«V­¢§§‡µk×ú† 1@„A¾+©[SƒÊ¹ï¾ûX±b ¬\¹(Xë‚Ò`ûGƒžžnºé&n¹åßš8ÔëGý:;;}«å 7Ü@MM ×]wÿâT‡ñ¨Ÿ298\ù¬´l¥•–Ï0ÔO™”ÊgÞ­‘Èg¥es(uPùTFÊhÊíx¿c)ßã}/cÕOë7bâ2ÚsÒ0ÉçHåo<ïe,ç¸*Ÿ—Ñž“Žç»0–s×0õ#­«Êg_ÂÞ&a{¦aœ ÜvÛmÜwß}¾1e°:„}î>uTƒÊ0éééáºë®cõêÕ|ík_ãk_ûš¿¯œõ3hálÿhÉd¨««ó]ź»»ioo§½½=õïE½å–[hhh`ÕªU¬\¹’5kÖ Z‡ñªŸ2q®|VZ6‡R‡JËgXê§L\ú“Ï0¼[#‘ÏJËfXÚP™œŒ…ÜŽ÷û8–ò] Ù‹~Z¿±š“†I>G*ã}/c5ÇUùœxŒÕœt<ß…±œ»†©ïi]U>ûö6 Ë3 óÜX¨««ãöÛoçÎ;ïä¾ûî Þ¶Òº55¨ “k¯½–ššr¹\‘…¼—­ô!twwû–®Áö===ÜvÛmÜvÛmtvvrï½÷rï½÷†¢~ },ˆÁÿªÃxµŸ2q®|VZ6«ßPöÉgê§Llú“ϰ¼[ÕÏJËf˜ÚP™|Œ…ÜVâ}+ùï{«~Z¿±š“†I>G*ãy/c9ÇUùœxŒÕœt¼ß…±š»†©ïi]U>ûö6 Ë3 óÜxÍš5ÜvÛmþÿUUUE× ƒ|WT·6¤ÔõJwÜqGïe—]ÖûÛßþ¶è祗^ò©¯¯ïýíoÛÛÛÛÛ»~ýúÞúúúÞîîî!ïm®½öZÿza¨_wwwo}}}ïúõëýÿ/»ì²Þ;î¸cHuïöS&#•ÏJËæPêPiù¬tý”‰Ë`ò¶wëpå³Ò²Æ6T&>c)·•|G[¾Çó^ƲŸÖoÄÄa¬ç¤a’Ï‘ÊßxÝËXÏqU>'c='­Ô»0Ús×0õõ™„™°´Éµ×^Ûû­o}ë°ë7ÖõûÜXê'e†]o;Þº55¨ ƒo}ë[½§žzjŸŸ €Þqǽõõõ½×^{mo}}}Ñ 7”ý£M鋆úÝqǽ§žzjïµ×^Û{Ùe—õ~ñ‹_rÆ»ý”‰ÃHå³Ò²9”:TZ>ÃP?eb2˜|†íÝ:\ù¬´l†± •‰ÏXÊm%ßÇÑ–ïñ¾—±ê§õ1që9i˜äs¤ò7ž÷2–s\•ωÃXÏI+õ.ŒöÜ5L}çD}&a&,mÒŸA¥ÒÏt"ÌEVäaÖÛŽ·nmJoooï¨úÛ(>tvvRSSSÖeh°ýGBýä , ®®î°êPéöS&6a·Â.Ÿa¨Ÿ29™ïV¥¿#é;ÃÒ†Êäb$ï\ØÞÇ‘Ôu¼ïe¬úé°=edL–wa¤ò7ž÷2–sÜ0=eäL–wa"}gT>Ç—°·IØŸiê×ÞÞî‡Â »|gªAEQEQEQEQEQEQe4)½¢(Š¢(Š¢(Š¢(Š¢(Š¢(Ê ¨AEQEQEQEQEQEQeÔ ¢(Š¢(Š¢(Š¢(Š¢(Š¢(Š2jPQEQEQEQEQEQE5¨(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢ ‚TEQEQEQEQEQEQA *Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(ƒ EQEQEQEQEQEQ”APƒŠ¢(Š¢(Š¢(Š¢(Š¢(Š¢(Ê ¨AEQEQEQEQEQEQeÔ ¢(Š¢(Š¢(Š¢(Š¢(Š¢(Š2jPQEQEQEQEQEQE5¨(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢ ‚TEQEQEQEQEQEQA *Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(ƒ EQEQEQEQEQEQ”APƒŠ¢(Š¢(Š¢(Š¢(Š¢(Š¢(Ê ¨AEQEQEQEQEQEQeÔ ¢(Š¢(Š¢(Š¢(Š¢(Š¢(Š2jPQEQEQEQEQEQE5¨(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢ ‚TEQEQEQEQEQEQA *Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(ƒ EQEQEQEQEQEQ”APƒŠ¢(Š¢(Š¢(Š¢(Š¢(Š¢(Ê ¨AEQEQEQEQEQEQeÔ ¢(Š¢(Š¢(Š¢(Š¢(Š¢(Š2jPQEQEQEQEQEQE5¨(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢ ‚TEQEQEQEQEQEQA *Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(ƒ EQEQEQEQEQEQ”APƒŠ¢(Š¢(Š¢(Š¢(Š¢(Š¢(Ê ¨AEQEQEQEQEQEQeÔ ¢(Š¢(Š¢(Š¢(Š¢(Š¢(Š2GŒA%“ÉËå*]#×uÉårض=*å9ŽC&“©ôm)£€ÊçÄÅqœ>r­²9¹Pùœ\ U>mÛÆuÝJWW&*·—rýªlWÙ¨|VžÑœ—θWå3ü¨|V–áÊæHûN%œ¨&“L1•l6;a±±±qÔŒ•¶mjkkI§ÓÄb1šššF\¦ã8d³ÙJßš2 ¨|NL’É$õõõ}äZesr¡ò9¹Š|:Ž£m7ÁQ¹˜ôׯ‚ÊîdBå³²Œö¼t¨ã^•ωÊgå®lŽ´ïT‹Êãäc2ÉäQ•®€28¹\n¯d‰Åb$ ‰®ëR__O6›%VºjŠ2"&ƒ|ÇqH§Óttt`š&®ëR]]M<¯tÕÅçH•Ï‘2‹e¸©r;P¿jYÖÊPÙUÆšÉ Ÿ•š—ª|*cÍD—ÏáÈæhôŠ2LtyTgÒz¨d³Yjkk™2e MMM}^d±~WWW“L&I&“¾õжmb±S¦Lñ?âBcc#™L†êêjª««Éd2$“Iª««©­­-²žαý‘L&ýß¶mûeë>T‚õÉårƒþ8å tò!I$†AGGGQÇXî¾lÛöŸ”9kXð9ÎyÊøSiù Ù„Ñ“Ïr²7^ò9˜¼ôwOòÌ ÃðË ¶\;Éy*Ÿág ùH6e9ùï¾ÆN>‡"¯C-o$²,k4úÎàÿ–eé$t‚1’~Uö‡AvKå6XîhËn¥úÕþîépúUi#•݉A¥Ç½‡{lL†qï`óÒþîépúÖRÙ”m*ŸáDǽŌö¸w¨÷8\ÑHúN—†Ïöe¢g(=nï$¤£££èM¥R½½½½½‰D¢èM$½½½½½]]]½†aô¶´´ôvuuõÆãñ^ ·µµÕß'ç¶¶¶ö†ÑÛÑÑÑÛÛÛ[TN*•êsH$â×ãpŽ©›üÇ{»ººzÛÚÚz Ãð÷ ¥œH$âßç`ÿ¥¼¡Ü_ssso$ñG£Ñ>u.w_étºh»< 9·µµÕ¿F<ïµ,Ë?n ó”Êù-Ù”²F*Ÿådo¼äs0yèžâñxo4ímnnîF£Ee–“Í¡\O©,Éç@²ÙÛÛ; |V¢ï”²F[>‡"¯ƒ•7²Ùß= ·ïìííímkkë5M³·««Ë¿%üŒ¤_ î‹ìë&ÿ…ìVª_èžúëW¥\•݉Gƽ‡{ì@Lôqï`óÒþîi ¹H6{{U>ÃŒŽ{Ë—1šãÞ¡ÞãpuF#é;u^.t<Û9i<{$éq'¥A%‘HôÆãñ¢m¦i½4A!—°µµµ·¹¹¹×²¬¢sãñ¸nÐ%<ø© õØ(íƒBr8ƒ2À€åÿ¡”7”û“¡tŠòéµKï+N÷†ÑﳕkÄãñ^Ã0Š:ÆÎS*Käs´dSÊ©|–“½ñ’ÏÁäe {J$þ³3MsPÙÊõ”Ê2|$›½½½Êg%úN)k´ås(ò:XyC¹¿¡ÈÊhö]]]½¦iö¶µµVû(•g$ýjooød·Üt,d·Rýê@÷Ô_¿¼†ÊîÄ" ãÞÃ=v &ú¸w°yi÷4\4îUù 7:î-_ÆhŽ{‡zÃÕ ·ï”}:/ :ží¿œ‰4ž=’ô¸“2ä—m۾˟`š¦ÿ·ëºEî¶ÁcÇÁ¶m¦L™âÿ„ÍͨôÞ‡`; åÿÑÂ4MZZZˆD"¤R)âñxŸv-w_¥nцaà8ŽÿÐ¥-èê7ØyJåPù,O9Ù/ùL^ÊÝS&“!›ÍÒÖÖF*•¢££Û¶I§Ó@ÿ²9”ë)•c ùH6áÈ’Ï¡Èëh0Y­¾3NcY®ëúalÛÖdŠ€‘ô«pdËn¥úÕr÷t÷Ýwد‚ÊîDDǽå©ä¸w°yi÷4\÷7îUù 7:î-O¥Æ½ÃÑ ·ït^t<Û?i<;”ó&‹wR&¥JlÒþŠaD"Z[[+}“†H$Ò'–ßP?$¥Ï©4†¢eY477cš&MMM´µµ é<¥r¨|†áÈ‹ã8˜¦Y$Ë‘HÄ?·œlʱ*Ÿáe0ùh@3|'5ÊЮ¬ ·ït]×VŽãÍfûL^”ð1’~TvÇ‚áÈî–-[ìWAew"¢ãÞp1VóÒÆ½*ŸáEǽáa¸²9ܾSç¥áCdzác¼ç¢M'¥‡Šišd2¿ñmÛ.ú8G£Q…Ðg_pÕˆëºÔÖÖ%T˲|k1xmšÍf‡dEuÇ>r^$ñ÷KG˜H$0M³h°:ÐyJåPù Ñ‘kyNr^0! ô•Íá^O’ÏdSö«|Ž.Õ•áô©TŠÖÖVÿDz,R©©TªÒÍ  ÂHúUÙ¯²;º GvO=õÔûUPÙˆè¸7\ŒÕ¼´¿q¯Êg¸Ñqox®l·ït^t<>Æs.:’ëUŠIé¡DZm›ÚÚZÿÃFýý–eF©¯¯Ç4Í"«—iš$ ýs#‘HÑùãiš$“Iš››+Ú®ÃÅ0 R©õõõD"¿Mãñøî½©© Ó4ýñ‰D¢ì±rO<ñ°ÎSÆ•Ïð1y‘Mð9Z–E"‘è3¸Ù”ç¤ò^’ÏdT>ǪþÑ•áôÑhTWËNPFÒ¯Bød7(·õŽì^|ñżúê«eûÕr¨ìN tÜ.Æb^:иWe3Üè¸7< W6GÒwJ›é¼4èx6|Œç\t"êq§äÉLJlÛöÝiƒj×u}W"×u‰D"L™2…®®®"×?Çq0 £â/¿Ô¥ô>&‡Û¦¹\Žt:Mkk+¹\nÌÏSÆ•Ïp0Ry/¹VÆ—rò9Ù•ÏÑBû@åpI¿ á‘݉,·0þýª21Ðqo¸Ðñ«Dǽáa¸í9œóT®Ã‰ŽgÃÁxÏE'¢AÇ0QR$!‰ X—¡–1õ:FÒ¦Ãuó ³{Ø‘NØåópds<ås,d3xîáR ¹VÆžrò9Ù„‰#Ÿ¥ï”ó†ƒÊØ‘ÅHúUŸìŽ´Œ±¨×á2Þýª^tÜ[\Îh×ëpÑñ«Dǽáé;‡Ûž#}*×áAdzÅeŒE½—ñž‹NyœÔ•þ0M“ææf?N›iš´´´T¤.’8i ºŽGãQæpê0‹äD°d*ýù-mY‹òÆS^T>'.a‘M82úNí•ÑBew|ê,KeP*a‘Ï#eÜ;’öQ¹>²‹l‘ÑwV•뉅ÊäøÔ+XÖxÎE'¢üásÁTº*#b Ù[>ïºë.~ýë_³lÙ²JßZ¿„ýÝÚ¾};3gÎdÆŒ•®JY&Â÷ã¹çžã{ßû^¥«1bF[>?ûÙϲdÉ’JßV¿L„wK¿#¯_MM ×_}¥«2bŽ´±íP û;x8„]Þ‡ÊPŸ‰ŽmËËçºuëø¯ÿú¯Pm‡Ê‘öNO†úLtl;1ǶCe"Œ‡ÊdùÎ õ™èضÿ±íÕW_M}}}¥o«_ÂÞ—L„ïBØå}ãÆ\}õÕ¼ýíoµ2ÏX»v-ÝÝÝÜpà TUU‘Ëåü} , ¡¡€ºº:êêêX»v-+W®ì·Ì7ÞxÃ?'Œ¬^½š÷¾÷½•®F¿<óÌ3´··sùå—Wº*ýö6Ìf³ôôôTº#b Ù”ýÑO@åsd³Yêêê8óÌ3+]•²L„ïÇoûÛJWaÄŒ…|nÚ´‰|à•¾µ~™ï–~?FÆ3ÏT†òLtlÛ¿|Ι3'ôcÛ¡r$½Ó…Áž‰Œm÷îÝ[骎˜#ql;T&Âx¨Lôg! å™èØvà±íôéÓ}£Ë@ž,•¾ç°ö%á»fy—¾óè£ÕrÇÝ ²víZªªª¸á†X»v-×]w¹\Žîîî>ÇEÐæÎÚ‡„~2,å0æ6lhh`óæÍ•®ÆˆH6kjj†-ŸË–- u<Í0¿[@è'ëaþ~ÈÊÛ¶+]•3ò9kÖ,B9 …p¿[‚~?†OMM uuu¼öÚk•®Êˆ9ǶC%Ìïàávy*Cy&:¶˜°m‡Ê‘ôNO{&2¶}ì±Ç*]Õs$Žm‡ÊD•ÉòÊ3ѱíÀœp 444„6}Øû’‰ð]³¼/_¾œ³Ï>›O¥r¨|*Jxѱ­¢„í;%¼¨|*Jxѱ­¢ ̸æPQEQEQEQEQEQE™ˆ¨AEQEQEQEQEQEQeÔ ¢(Š¢(Š¢(Š¢(Š¢(Š¢( ™ Øv¥kË ~\29~uRƒŠ¢(Š¢(Š¢(Š¢(Š¢(Š¢L`2™Ã?Çu‹ÿwH§=cŠã^YõõãGéù®[ü¿mŽM§½s³ÙÂ1®ëcÛ`Þ1¥õÌå uν5¨(Š¢(Š¢(Š¢(Š¢(Š¢(JÈq]ï§Ô#Ãq ©©ïñ¶ím/çå‘ËAmmßrr¹‚A#h©­Øk%ñŒày–d2‹yumj*=’IÏxRj| F²YïÜHÄû;™ôö‰aEþÎ弿#‘âº:ÎØYÔ ¢(Š¢(Š¢(Š¢(Š¢(Š¢(!¶=CBЋ$ö~²Ùbã†m{F1¸d2žQ!óþ/gP±íÂ>1ÐÈqâQR__ø?-.'+”!†¹¶i—'õ¯©§ìkmõîIpïz‘ˆw|"áí—sr9ï˜xÜû;hŒI§ u Ô ¢(Š¢(Š¢(Š¢(Š¢(Š¢(ãH.WlD’ÍŒ&±XÁ0‰x?¦Ylhq°,Ï‹¤©ÉûI§=£„x”bÛÞ~)ß¶Ánû‘µ Ã+K +Ù;ÀtœX!Ô—eŒ)©TÁP’Hx¿ÅÈ#u²,¯1´˜fÁ{eÄã…úŠ×LðØdÒ;¿µµÐFr)k´QƒJ…럸"Ý´‚1á’Éþï„!1¢(Š¢(Š¢(Š¢(Š¢(ŠRžþBOI¸*ñ"‚Š„»’PX¢GÎå¼pZŽS…å8ž"÷ŒbpÈd ÛJCbWn<îƒó;H]VgôÈd¼sÝç í=Œ— –*œ›ëñŽC‰x Èõ’IÀÌBÝ,Ë;_O5¨Œ®Û¿5±?Ä•*+x/jЈbÞßÕÕÅçg2…¸xâ~%/ BV.~ž¢(Š¢(Š¢(Š¢(Š¢(Š2z$“}Á—Ëa’ÉÂj‰þWŒ#bàhl,xjäryOŸƒQÑ]Þ>1ª€w^ÂëxÏc#r˜M`Úàd=ï• Q%‘(œ9ìoBæHUóÞöhZÞ Æ,hú64Ÿy=u.¹nïïH¤PfKKa›eAhÂû»¥.ˆÃnà­qïÞÍ7 î@W >Ñâ•!uó«›¿GñjcO<ž¿^Y™Œ×^àµïc½™çž›;ªÏX *ä4ÎÛP’܈…QK^4×-üÜ…c%Ùx¯Hr ±Rš¦'TMM Ÿ$ÿ)…'×”²ûó€QEQEQEQEQEQú'¸Ð¾tÁ»ð² Y úئ&Ï8p–U8&“v>—×áUÀ½à×õ !+N„4-\ß² ××1×õê‰xõ—¸sòÓÔä`ÄëE\«k3er0˜l©„|Nt’É$Ñh+Ыf³Y"‘FÙÁò8ŽC6›%“É`n¾—ŽŠÐç˲mÛ?Öu]\×%“ÉÏp2™ MMM´¶¶ÐØØH<'“ÉÐÛÛ[öÚ®ëZ?eìQùT”ðæ±­¢Éhß©(áEåSQÂK˜Ç¶’{c0Eµkˆà¥ð(‡ƒ§´OãÙ JqËœ›%Û%¡»„¸’"’ßc]Î+lþÙž›F<ÑÅë±jªþ Öo†—Ž~3Ç öIànLÈí„©|‚½ÏÏBîÀ¼üsZ‘äê â@.å=Yãï>¹ÓÁè†ìY`nìô‚3Á¯,øyþGÉ? ᾄ—_^lÕwqÜ *«W¯æ¾ûî+Úvûí·ÓÐÐÀš5kX½z5Ë—/gýúõ¬ZµŠ•+WŽ[ÝÄH´"il,DR)ïáÙ¶÷·)::¼cƒ‰ƒ$a ¥8NÁH,7.`Ä …¸s‚(PS)³O¹’¤GY>@‘H>Þ]®àsÎ9¯sð Í”)W”U²:y+Šišü÷o£¹y!‰Äà4%Ü $›@Åås äO\×Åqœ"I)ŽãP[[‹™·nº®K<'‹aY¹\Žh4ê—“ |õc±®ëbYÙl–h4Jkk+†aà8étÚ÷6Éård2š››O6åÿt:ã8˜¦I.—+ªo"‘À0 "‘ˆ_F.—#FillIJ,lÛ¦¥¥…l6ë_CîO®§Œ-Y>e²æ±­¢Éhß©(áEåSQÂK˜Ç¶¢w]¦ü]JûCÏ(bå‚8ùc%އäNOä÷ÝãÀÿo×]4‹ONNãÙ,×%›5èèè~…iFqœ‚6ó£ßíÀ[æÀËÛ»xý¿ ¦ðÔ†ƒÌ|¦vNa×´]ìú³£Øùô4–¾vÝ é¿cdN‡Ô~0ÄåÆÌÁËgìäâÆ­l|ìéÕSYº 2&.|ôÜì9g6ææ©äêàâG÷Ñø3˜÷!øä;`Ú\øýÉÿ4.Ëû„|V´ì†ÜvÈ=•¿iìÏ@Ôñ¼E¬Í^Þ“Ä/Á¹²¸»Á ¶ ‰}!ÌKÁWñÎ'ÿοNôŽž¹yI@n!47yyZ˜ î3`ý!¤ÐümHÞÑ¥ðÍføþ,hù:d¯†ègóX,c1ï·µ ž;º{ÔßÅq7¨ôôôu”AV¯^Í-·ÜBCCííí¬X±‚†††q³xŠI9$œ—ä;±,Ï‹Ä4½ß©”çÑ!† 1¸˜f!¼VssÿJ_ËòÊÏd<#‰SÀóL)Eô®bÄpÇÔ°²Ø¶ÍÖ­Ë€¥ùã ¡Æ‚¸.¬Zµ}l-³gïá !IpÉ%¯rúéKü{Êår|ö³Ï‹/~žü`1[·neÚ´M45ã'Êå¿j‘ÀW-™L‰Dж)áb Ù„ÊʧD­êϳ+öä/›õdµœÌ.®ëR__OGGGÑv1JÔ××ãº.}<8b±˜oÄhnnö=Djkk±,‹h4Šiš$ r¹¦i…𪯯'‰FÉf³´µµ]ò,"‘ÙlÖ??xŒx¦ˆ¡D¾¶myµ€gT‘㺺ºˆÅbÄb1R©ñxœt:MSSŽãøFŸd2é·…iš¾÷ÜGð:A/ñ®Q¯—Ã#Ìò©(G:aÛ*Ê‘ŒöŠ^T>%¼„yl{ç“/rúeˆPë.JÕŒ¥AÎ܃`SÑ6"ï€ìñ`Ì„øÝ;¬È=ö`ݬu0œªé8gCKŒ‹€‡ ²Ñ&õÿ,rçbhþ=Df@òx¼ø`ÑüCÅ«cöw°g-Ìž½gÔßÅqÏ¡²víÚ²‚¶víZ,Xà l]]uuu¬]»vÜê6PÞlÖSض¶Œ"‘ˆçmÒÖæ)zãñâ}ú+‘(ÍU9W :Áp[²Ê½´>Aêëë±m›\.G.—öm_)úÐCñõ¯k®yÖ÷B9úènb±XQyÓ¦=È¢EPW÷qÎ9gË—¿^8@Í 7¼Á–-¿àÄ«ø·{={žÁ0²<òÈøéO·â8±XÌ7ª8ŽCuu5¿ùÍ+üô§w—½÷úúzÇñW»+•¡?Ù”}•ÏdÒ[u Þ`ýáºÞq"²Rápo×uÉår¾gGð½”Y±XŒD"A<'›Íú‹êêjr¹®ë’H$0MÓ7¦¾$‰DZ,‹D"A"/ðAcC*•ò½VÊ¢Ñ(™LÓ4iii):FÊD.û3hJ½Ä’J¥|o¹–ã8D£QÒé4˜¦IGG‡ï-“Édhll,›ß¥±±‘d>&b&“ñe^:a”OEQ<Â<¶U”#í;%¼¨|*Jx óضç`¯æ•ãÙlù@²N>‰ç¤ÁÓ³·çàÁ'Ÿä‰M›È’Ï͑ߟràÑ4¸Yø]Ö;ï~vš°É ^yf6à_møìËÂã?>È‹/~’ÇŸ>ÄK,b§µ„—^žÁ«¼~<üñ%H|Ô[ ¼ió^.ûÍTιôŒý{yÛÑ{qïžMõiûx׿¿Ì_vM%ò4lZ3‡³7‡ž„È&˜Òõ+>róÓ0VÍŒ/žýÏüæ/Îä=?Ûû¶óä”Ö|ôñ‡Àü7¸â?àš½{±²Y»ï›¤WBcõÎøÅf¢OÀCO½•gÝõ4T=™K=/c3´»]÷ÝG<ƒŠá;x<ßXIÈ ?÷+îZ¿ãÝ`èg.ðò¯ÔlÞUíµäpŽ^\›w=†½)Mîà®ã(0ë Ï;ƽÌ¥@uë¡7ÈÝëz¬]°ì‹sù‡+RðÛV-äÞ ö,ˆ|ÏhïfÜ7oþhó¼ó $/‡ _ƒ³Ï~~ÔßÅq5¨ôôôð¥/}‰ÓN;óÏ?Ÿ5kÖÐÞÞÞG`,XÐ'n_)¯¾ú*«W¯Q½²Y/Ñ<ôï¡{‚4Š˜¦·­¿h7b‰Ç‹Cs•CÖG£)“É$~8/€-[¶ðàƒ=¾Åq\×%NcY±XŒúúzLÓôW“ÏŸ?Ÿx¼ËÏÿòÝï~Ž\.ÇŽ;ük9ŽÃ¾°?û³Ù˜&̘ñV¶n]K2™äÍo~ŒíÛ/ä’KÞÏÖ­sùüç_dÿþçyþùýüû¿ŸÃ{ß»–ûï?ȵ×îå”S®æ¹ç<æ­·îå½ïý*[¶ü˜_þò \Òé4étšd2鯚oll$“ÉøJ×þ¥÷Pk‡ÂvõêÕ¬[·n̯3Ö $›0|ù\·n]Q9‡‹ä&2MO6mÛ ÍW__0¢@ÁÒ4=¹³í‚4“ñαíß›X,F6›õÛ¶í{étšÖÖVZ[[}ƒHSSÉdÒ—?É•F‹Bx~˜¯r!²"‘Èa%Œ7 Ó4ˆƒŒà8ñxÜ7Ü”"õƒ‹ištuuíO¥RE†)KþoÉá"ò'F1ôØcŒxÊÛ|8tvv²zõj¶mÛ6¬óÃÄXÈç¶mÛX½zµNL•аvíZ²Ù,Û·o¯tUFLXǶŠ2\tl;¶c[E.2¶}õÕW+]•£c[e²¡cÛ¡m;n(Ø:‡Gþw±Ÿ^¡t±yxï›AƳdñŒ ö¦áóÝÝ|áʼná924ãT΋ÀI6tæÕ2.TgaÆ¡.Üé3iÖ:@VÎ{žWþc1``üÕ.æÿÈ¥©¦}` ?±—¿^¼“§6dëëð—ÛÄëærörúÓ§óÁïlä'±½ì? N~y*ÇÎ:–ªUUl8qf"Õðæß`×ðáÄ Ô¶ü#ÿú¾¹<’:ƒw>ÔÍ–Ï\ñÇË´ .ÀébÖÖº-lüîwù܇>ÄwÎ=—××­ó #?ý)+~÷YRßðôÉîI¬÷ÀGNë%ˆLó8úäÿ÷^À3T¤<£Æ%¿~†¬¹óáéû~ÈÛ–-ó\~@Ì…^›½ù×/`îölf»Hœ=ÿ<›H$‚‰ç™ßo}íiÒé4&à¼X¼lY¾û/üÚî‹v3sß.vÔuÂ¥ŒŸ6âî†è6¯~®ëù¿ÿ#ùäBê«ò†´k¡éÿAâ ðÌ¶í´·ïuYWƒJgg' Üpà <ÿüóÜrË-~§×ÝÝ7žÙP\ÆæÎÛ¯›èP‘p^Aï“R2™¾+äãñ“Ø÷gœ "F((‡c±˜¿=—ËÑÑÑA<ǶmâqøÒ—®â‰'ž ú¡…,ËÂ0 ‰­­­´µµ‘J¥ˆF£üêW+ùêWÿ†êêjöí{.ŸÛÅS°nÚô36sÍ5Ï’Ëå¸úêSü<.S¦TÓÔÔHkk+ÿþï+Xºô£,]:ð¯o¼ñ]6on ÇyÓ›Z¨ªºŸÙ³?ζmžIòÛß>ƒûï_A*K–|„‹.ú¶¯ v]—l6‹iš¾±(˜Âk“œïã8õõõ$“Išššl×\.7¨qf4hhh`Ù²ec~±f Ù†-ŸË–-cùòåî—t’¦Î0 áó’É‚ÑDBï]sͳ@Žx¼`T‘üA?ýéÝ\tÑÌåRÞ«ææfZ[[‰D"¤Ói_ùßÓs5™LAè£Ñ(‰DÂ÷d9ö“()ú†þȆ{ä: Û¶¼®„&( —xÜC˜IÄxcY–ï#•`è³X,–ÿŽÅûܧx¶ˆÜÊ÷¯Ôð2Tdå̬Y³†u~˜ ùœ5k–†MP*FMM uuuÌœ9³ÒU1aÛ*ÊpѱíÀŒtl«(ÃEƶsçέtUFŒŽm•ɆŽmFƶ ,qýmž‰;c—gá´8¬)ÑÓ~7 »ÏŸ ?|Ùu|~­õvlËâÕÕÀ¢d!ƒ/|áN^~f Õ6,2 ó„׸òö]t9°à3Ùúì, `O/œZ»ùS1ëÏzùXõ!œÿšÅ3¦Ñ½øi¶ß8?ëx…w¶N¥{ó4¾ƒ³ïzžó¶,dæ]3Á€‡ßú0_<ý¯!­œÍìÏ ž>ýizõxÉ_°ø‘¦îÃDZâ±´67sîoð–+¯„C.«ªVñ¦Ž^8á¦nÚD2›äÿ.¿ürb±_»öZÞ¿?ŸyõUÛÛYÔó =/ ·oçè£6a®²‰ ¬O&©Ú°Ów²øÅ9tàFw7Ö¦M€§Ÿš7¥›š ëYóñC¤æÀß¼ey±ž& §ôôðÖÿ-ѽOb‘×C¹.Öq[¡µ™oüá?‰Åb||Ûi0á}ûöáº.æIÖÎ`šD.†ì9àÚ6þë+Ù9cû{…ODá\s Xç|í3Ÿáã·ßNhÁ3Å·ƒ±ç9¢GmcßIó¨>m:Ûݬ'ãjP©««+ŠÃ×ÐÐÀ•W^黕2ëå¼yóF4鬭õ”µ²ª½dqô°q]—•+7¹ŸÉ nÙÌk Æqª]¢¨4 ƒ¦¦&êênaéÒ›9묳H$D"ššš|£F$Á²¬¢Uëâýò…/lÇql •øg>óS®¾zŸúÔv"‘H Ïwîç>·(ä‘î†a0sæfþò/K—.eáÂÂêöK.ÙO4 û·góì³shnnö“a~²mi› R5h8‘<,btqK4ãMMM¾7ã8‡¥˜.“eÒ9lÖÏeË–QWWwØõÉd ^'’OÈ4½÷XhBøH$ÒGVú+k$tuuyàåO¾K¦iâ8‘HÄ÷¬ü¿³Ù¬ïmW__OSSÓayí©ªªš4•±Ot*•¤¦¦†3Ï<“3fTº*#&Œc[E :¶˜áŽme¤ÈØvÞ¼y•®Êˆ™ècÛ‘Âp]o! 2¹Ð±íÀÈØ¶ªªjTêØ5s&›3pa^?ÙØ·ÃÅs;9õOÁ~W47w±ß…ß›ÊsûÎâ´$¬È¼\žzê v¾r4õ&,xáû_ÛÏú_yúŠšC{ÏÎñ¾sà‡=»øâŒìùÍ6\5•YÛ§òïÛ«X±ùxN˜r€oLÏôéÓ½úœ ?9w§??‰3¶uùVŽû³ã°`¾ Ï 8öÌc™¾c:DÀ6l~¾þçD"êëë¹ùæ›Y<}:wöôðòŽ—q#.óçϧº¾ž£»»q]—ã?žû￟T*E³eQ=e 3¶æfþ8µž S^çÒƒydæLž»î:>óÓk‰¦¢¼|úË´ÿñ,™3‡?tvÒò¡‘ýЇoÑûìýõƒ;¹ås[0l#›e‰¼ë¹d2D€ã~û[Þ±w/Æw¾C÷OÍf™uï½t¶¶‹Åxß¾}Üè·¼ç=¼÷î­88$“I ÃàÅ'ŸÄŒ_ÿÚχñôÏN³ëò?÷w¼zñÅìÞ½ÛS¶´Ð Dm›t:Í_œpS—.åÛÚ¸ôïÿžx2Iä[õ´ÜðQŒoôræì'8ôµãyn”$Œ»‡J{{{Ñ6¨ººº>‚ØÝÝ=梂ÊSÚJbøró£ †ã8d2Ö¬ù®Ÿ4^”„¹\ŽX,懼’08_ûÚ­d³pâ‰üdÕ¦iú!xdå÷Ê•+¹ð ilô<@$äZèÛ†'Ÿ¼€%K~H*U0¨\sÍ{9ï¼ó8÷Üs‹Î—Ð`b`ò’Í·O[[ÿò/×øÿG£QN:é$¼šW_=>^’Ï~ö >ö±c©©¹ÎW›¦é‡÷±, Û¶±,‹L&C&“ñ•Ü’°Ûu]š››ýk¶’÷BºŽã`FÑ1Ùl–¦¦&\×¥±±ÑVCQ6Ov’Mùlj*ð ïý3ŒB.1˜$Þ;)²)¡ºÀ;Æ µ—!‹FùàðÀÝ466å%’÷¥Aãä¹ç~ŽHÄ +b00 ÃG‡ƒ¼¯ÖP?6CĶíA /£a¾Ì– ¹'mž ˪† ‘EŒ¦­­­¾÷ITÂ&ŸŠ¢ãØVQí;%ÌLdùtÝBøé¡LzÇ‹n¥¶¶°à5HéÂÞ`xëþ(]wæ8^¹¶=ôú)J)aÛ½ë×oÄ1ƒ%Q˜exï'“câpùƒw2íž‹9¯«‹l6Ëã?Îï~÷*,ÛÊ”»v2íž}lÌôLK–<Í1ÕGqñô}Ø6¼|÷^ªfÎäÙW—qÙ´^.úçÝDGðÖ?-áPä îúCkÖðÊM7°tÖ,þ¢¥Å[À›Í²lëVbõõlýÉVjkkI$üõÃó‰ÿ0¯ºŠ$pÇw¾Ã¦«¯æœuëÀuYü©O1'¿àǶm¦}á P_Oã”),:åþíÑG¹øüóùæ7¿I÷Ê•ÞÃM¥¼|Ôlftïâü2V#a\ *k׮妛nòcòõôôpß}÷QSSCCCÝÝÝþª„ööv:;;¹òÊ+Ǭ>¶]¼Ò=ñ”´åÈdàæ›P©'J¿ÚÚZ2™L ”—¶Ê0 ßP ûÅ€ðì³ÏbY^bx1¤”®”ommåK_ZÊ»ß=˯·¬xï/Ù4ò¿õŦibš&?üá§¹å–Ù¾õ4HPQ-å ¤çM¥RüË¿,ã¼óºØºÕ{ÑŸ}ömEÊáÓN›^T×uýº‹RÚu]?œY4õÛHVãK˜£àÊuÉ[‰D|¥té*yÉë ÏÀ{®?Íx„ +É&0®ò)ñF £o˜½\ÎÛ¾wïÝÔÖÖö1D˜¦ËÎwÑÑÑA*•â²ËÞÄ‹/¾xï[,£¶¶–¦¦¦²2dÛðWu{öÌàµ×.¡¹Ù«ƒw?AýH(ÜÖh0•`.–rßÊh4êÇI§ÓÄb12™Œÿì$„X$¡­­ÍÏ-ÓÔÔTÖëìHÛ0ɧ¢(Å„ml«(ЇöŠ^&²|Êü/“ÆÆB®Nù[ (P0jÄãÞñ²7•êk I§‹ Ù¬WV2YQ4ÄÈ?Ù'çHþP)Ëu½ŸÆFeH„ql‹y¿¿ó ðx5ûþr*{óê›i¦—„Þnw`¶ ¿ó–ΘÁ ë6L&9tè$6lXDZuÿÇôæ3ÝqÙãÂ7¾±Ÿ .èaöìg˜1s'uˆ?þñq^}õÞ¾äM§0…ml¿2ƒ9ºvñÚ%¯ñÞÏÂOÂm¯àKpÌ­?ଳÎbÙŽ9Ðì¥ùÁ'Ž"~ºwÌ#}Ä×oe›wå£ý|üã§®®Î_žÉdüü²×¾ï}D"üþ÷8꥗ضm‘¦&R–EõãƒãàGoÚĬW^ayòm´Më`Ê”)¼´};ÿ‰OpåŸÿ9---œ»`oûò—Y²g÷¿þ:9Ëâ/ÿñùÞOpÁ“OfìÞÉÂ9Ø¶ÍÆ xÏ–-toÚĶ_ý 7ïE“L&innæ¿Þþvö~õ«$ ŽÞ°óŸžEÓ¦‘Z¸_~ðƒœ¼i×özž¸ürf|ô£ÌÝ·7`ç#;=ÙÓC}m-‹¾ÿ}ˆDxí쳉ï”ðŇâÎË/ç´/~‘c?ö1Þ÷ÓŸ²ëŒ38ý¯ÿš7,(„ºÌ®½<ü¶·Œú{9ºÄaåÊ•´··³bÅ jjjX¿~=+W®dåÊ•¬ZµŠ›nº‰åË—³~ýzV­Z5j.aýQšh>ór©”ãî»ïfß¾)ýz‚HÞQf³Y2™ ÙlÖW655ù†d2é^ý~{ ’I§ßÕéžGaåÁPõ·r¼ç5Õw©B2Y~õƒi·ÍPÞ;Ü}÷2>ñ‰¿'—û2›7Ç”ÁC6 Ñh_²E"‘ˆï¥ô8ñêÑìFÀ»'Û¶ikóÒ555ùF)ÙgYŽãH$ŠÎ“°kÁ$ÚA²Ù¬¿ê~23˜lÂøÉ§ëzré8…°_BPô\×åž{ö‰,áÿw?Þ†a¾çImm-¦iúyKÀ{¿î¸ã~>ÿù¿ûÝ«|úÓ/ÓÔ”ásŸë*kÐÈdàÔS·óÜsgÐÓs àÉ^¹W"—+Mzƒ×à7E ¹†QÈ…„õ£M†”±ðø9h‹ç6äçU‘ð}‰D‚t:]”F’׋Z©Ñ*è‘Ü6”¼2‰0ɧ¢(Å„ql«(ŠöŠf&‚|–ÎCƒÛEO—HxÆ‹¦&ïo™ÇŠÃu½ãâqï›LÒÒÒâëžv¾ë]\ÿÙÏÒÒÒB"‘ÓäœsÎaiCgåóíé4Ó-¢¾º"æ=û¬÷m›ÖÖVšššxö_þ…sªªÀ00 ƒT*åm$*Êý–Å <ýֲϞƆb±˜ïD`µ—qâãÏŒú{9®€¯}ík´··ûnaA×°•+WÒÐÐ@gggŸ}£¬(]ñ>P¸þ-[¶Íþ¶(ÿÐÇë!•Jù7NûyÿÁC!üM[[[Qø¡Vª»îHcv–SjD’Âp\Ewì˜Îw¬àÆá¼óZñýÚð:õtÚëèMÓ*º_IŠ-ÿK( !RH>@B0|˜$§O$¾[—cÃ𹢬-×î²}²T``Ù„ñ“Oì¹n±A/™L3³Ù,ì"—ûŽ:j»ÿüÄóÉ4Í"//ð:ÙSN¹Ëò“W^ùŸûÜBr¹…~òzYé#‰íoºiwßí­X²äaà¼üu¼AfGGa€›Ë¾!bqùå†Á9—^Êßü&5O?MÕŠXyj.—£µµÕ×û:¨üRÂã‹¡ã,ð>*‰Ÿ®̼rLâillôs—ê·‚‹o[ZZÈårD£Q\×åµ5lý˜¹mTßÉq7¨&ò/ë|°3„þCZmݺ•SN9…|äÏhjj*z¸â‰‰DжG"¢Ñh‘r/øÐƒÊaQB–* ûc¨« ×õîÕ¶=CDéË'd¦¦þ½uºÎÊ•›hmÝëÂþýÅIó¤}e¼÷þVÒ‹!¤ÜöB¾ £h{i~9F®%žAÁçRNÁ|¤åX,Éæxȧ¼#úËûÛ&“ÉÉL.—cöì7‰À£Þ \à‡Ö³, È{‡ÅËfÚ…U?÷Üs vþYÑ#¤ò¹®øïÿžÍcÍ/[WÉ-$«DtÅ%;/ |e{4êɉëzƘXÌëCZZÎãmoû-6TñÔS'û9L³`¨P1έòú–ŠŠwmk\B~”r†K˲H&“}ö‰wYÐC¥ÔÀ2Ùƒ|*ŠRž0ŒmEé‹öŠ^Â(Ÿ"+¯³#óæ]²/™ôæpAJÿ—9ZP—bšÅó´ WI^ŸèŸ#Ñ ÄsE"@!œWGGa¬èr$ƒ¤/QQÉ‚E1¶45Ê—E€MAÊ‘¨ ¢^ æv£“$÷éH9t”óêÏ›¨Üsé”XtRÎP®=Q ÓØvî'ò°;;ž9†ý/Ã)_y†ãn<Óß¿×lx!S~÷8—^p)øüîwÇs çS?s ÏšKb1Ùw~œ…ûz™?cö_nÿ2-[à`ÕAÎÝ{®CÌ€%w-aut Ïî}–êïžsÀܶcô<ƒ ôɧ+š]ÑOJ¾YðÒ˜¦É§X›×mΜ9“‹fÍâ²Ë.#¹mŸ»õVf^uÄb,p¨¯'òôÓAËå°–-ÃúÉO Ê¢’ˆ½½½|ä#ÉS¼íÕÕÕ†Áï¿ÎÜ{î¡gÚ4ˆDØœÉpòÉ'³aÃn¸ážxâ vN™Âû–.å×[·rðÒK‰œ~:—ò“<™NC4ŠˆlPgS.$¾D’t@á…g›ˆŽÒm?ˆGxúÁ?_›~•Wê^Õ÷r\s¨„‰Ãý˜†ÍgÌ$)ð$þ*•êóÂH®Ãe( ©Gš6 tõxž9Ãé_~y àµñöí§–Ü›·úB”Ê  B9e°x"”B$ïJáÞŠ•®–eù9X$Ÿae¯!¡Æ&³’6lär…_‚xe€t.GSSŽãÐÕu±ìÞ},ò„MÓäÎ_Ä0 r@h$Ï_U…Õ<2p´,ï›.¥ùóç³ÿ¼ë´^È’LëÆ”]SøÜü…$œ÷½ý>Œm0í[Ó˜³lŽg|ˆxLJÍWmfÝ9ë «t)Ñ©æÿlllô£àõ”ŽãÐþ›ßøáÌ/¸óN,Ë"³èÎ;™“ÏIsàíogÉÎ}ôÑ\¾hKÏ8ûŽÄL¥hýÿ(XME±Ï”,ËâÌ3Ï,ÚÖÕå…¼?î=ïáÜù»Å‹ý¨@›7oæÀ|ûÛßæ-oy o~ûÛ9éŽ;Ø1}:/YRt_¥ú¤ÁôK¶mûy`†Ãpu=Ö4øè£›9î¸ã†}írTÄC% È»WJéû×ÔÔDss3[¶l᪫.Š•ûZj¤ ©‡Â’•CV8HWšs ?›Ï0t­X|å+³il<¯l‡)>xRGÇà®6A+n)bé ®äf ºmÛ~­­­~"zIboš¦ŸKEùÉSøáofÆS™={KQ}#ψQÎP.2'eɪ¡tº¼ç×õ×oä¾û6²eËÀö¢}’³¥Ô›®8?’×fÒÇÈö–pÓw×^¸°‹íÛÊ×Ñ ©©PW‰± žœzž3…{·òææÂ÷Äó|ó~‚çþ`b4jð®l&¶WEQEQE9$tUpͧ,ô’ÑT ˆqæpt„AãË`ˆ‘ óHÑ¿Êú·¾•ßæC§éK_ò ?,Ë"“Éàº.ñxÇq†å@`®B{40`îܹ£^ìë¡ÒŸ‡Gð#뺮ÿÂ<öØ|æÏsÑ>ð”|åb»²êàp‘ÕöÁ0Yƒ1œÎ@gœñmlŽ:j{¿ÇŠG@)åžM9ƒJÐÀQj©”ãå9¹®[”Û¡\;˜¦I2™ô“Öçr9?ÏM¡nÉYT•‘A5lÛæ’K.á϶láµ³ÏÆˆDH[ÿýRZZàØ}Ì;¸uùr–Ý}7N<‡âx•ð’á]#X¾xMWôÙ¸ñz¶oßÎôé;ж›fyc  Áfétÿrõ óyì±·sì±»9í´?ôÙ_î<¹F.W=YA\IFýý—_~'¼ÀÃ/Áu !#¯-Z[ýd³…•;2PN& ®ç™LñJžà`U —£÷~¸E—~ä›`Û6MMMêY¦(Š¢(Š¢(JY\×ó^PWmm}C«—zŒ&²ðu¬Ï ž's¸r[dN,  £xaŸ•L³°è®££à \Ø'ÆÉ%*ÚÚÂ"=i{ñD‘ce¿¨Ù o_&ãÍSÅÀ%ÆYhœÇK¨21XIxïL¦0W NSs¹B´‡l¶PÉkÌ5“Ëy×.Îåà®»–ŒþKr„“°`ûCÓ™öaoaèi§ý}3w±páB.üõ¯Á†]M°gÏÿQUåEã8öØÝ4ÌüàðÊ ¯kš{h.û/|™Kg2ýSÓ™sMÞ+%o<¡™"oŸUªã8$ó Ì\.G²¾Þ_Œ½òøÙ'?I2™äß}”sªªhkk#’ËqÒ¡Cü°¡A‰”.Ù,6Èf £ææâÕÆbù"åŒÓ§O/ä¯5 z-"ÇýŸrˆ~'›ÍR__O6›%›ÍúdCR*Œ»žÆ„ÓþpÚ¨{DTzvÅ®}¶ÿ{ÇŽ?PSãåñl½z þbÉþpb‹u^d.h\€b…i‘؉vï>€ªª ýSÎ]Vbˆ–«Ï@íVIfü¿tŸl‹D"þ69G’¯“ÉdÆ$™·R¸û†l6K,Ãu]v¼å-lüå/Y¼cMxýÝ´® ˜ºr%ày ÀËW]źª*JŸ” lÀ(9Xº¥K—ù~d 'Èë×ßø¼óºØ¶­šØÄ¬Y»‡tàw øw4ê 6ƒž0–U0V¾ôÒKlÛVͼyûý¾YòÇ“%J]eà)7ro¥q€¡ðü‚ߘÚÚz?dÙH(õRéïû+9w‚¹”EQEQEQI°nšž2}2¯›,Íár¸¹r+[¼E‚I‚óI ù.!ͤ.™Œ·O ²ð±¥Å›W&½²j$dv$âÁ‚ž.‚,”ƒ˜DÀˆBPµ#ÞI]I *ÁÐg²ÀYÂo‹¡%†W^™UéÇ<)yx¹žñ$'^Â|‰TŒ+A"xÆ)*ŸDt¬÷Ì›çç€=ý]ïâÊÅ‹yï²eÿ™ÏVŸ˜&s¶n-(wå%sš€y55ý+{FSxóÌž={ШK’ ¡¹¹™X,F$!‹ù‹ÒË-Ü/ÕJ ¡,ò¯ˆ'ËarDT ðQv)È¿§b0q‡ÓNëô?úò"ò£ÁPWsË ô¡"‹„âq]·$‰û(7.ÐÓs ñ8ÌŸÿB¿ÇHÜÉâ6ðê;T›…<‡rîv¥yTJ‘PbAO— çŠ„s –!®mÊè“Lö}¯ïÞº•_üèGüݯÍÒ¥KyþÞ{ùÈÃÓŠ×ï½~ýõÄÍW]Eoƒ,*j¡L°ðd~8œzêvÞüæÇ†||*Õ7¬Ø`›®®…<ÿüÙ‡U/q£.µ-”Š„ ¢_|ñ¶m«fÛ¶j¼ºÈÐ#±tÙ'^'2ˆtÝ‚ë¶m{÷*«‚Ê«š›2¶<ì‚ÛeUÈDè„EQEQE_šš tÉU2ÙÃ5̎ŽÆã…\,Átò[æ’KrŠBÁø"Æ•`©{0”v!KÁÀ!sV '& û%Ý„èÃ$ÇŠ„7 £`¨ÏœH¤pž”×ÒRðŽ‰Ç½:˜&|ô£›+ýˆ'6Ð}êv\Ù ?œÉ²eËØ¸`®ëÒÓÓÃ’íK¸è'ÇB.óƒ\Ô~4)xË[Nã³`ì‡ÈN<ãH>”—ÇO<ïÿ”“‰¼þæë_ÿ:›6mòþÉ—L&q‡÷.[æ{m¬;xL&ÃÿüÓ?A$ÂÝ·ÞÊ_ÜwŸ§W”—[\œ$a®Xÿ, ,‹ÖÖV¦OŸ>öm{˜ºIFikk£¥¥Åÿ‘|·ÙlÖ÷Ø‘¨!¥HÚ…Áö-v-õ6<âr¨Ø¶çR(yl ^[ÙlÓŒ’ÄSÊJL¸L&ÃÁƒÿŽm¾òpG+Ü—(îË ÊÌÃy¯‚n¡²¢;x 4šTUm “9¯ORúÒzIg$ر|_¦/`ý¶‚!¿ú¶¥åo·,Ë7ÌÈǰ¿ÕïjP}$^m°É åCâš½{ytáB¶O™Âõ×_Oúª«üc"–Eø›-[ˆ{,&…~ÐÊÿ”"o‚x¹¤òG)VÊ /Ìç©§.ö=JÒ»Œ*GõK—nçC:oÈåŠÚ`ƒbInŸÉÌcïÞÝìÙ3»Ï~YU$Õɪìæû{Z[=wmqé×ðÒ}‰DÁ(3’?Ó4}O3ͧ¢(Š¢(Š¢(J)¢tFÑ)‹NFÆúþÄø!^(àyââ8ÅÞ+²8/ƺâÁRJpnZªö Îmå\ÀêêâˆA¯™@$$ѧüò·œ_] ³gÍñÇ/ÛF>éxl>G?¿.ñþï™6 €0¿z>‹_ÚÁþoìçÌ…»™}Ülxh„s[ð£³{Ì“ðŒ#žH”¾A=h9Õn~µîyçGoooÑ.×uypõj¾qàÿmÛœ¶x1'Ÿ|2ßûÝï8ø½ïÁ† ¼íoþ†£\×Ó3¥R…ø‚¢¤ ê“ó1õ"€Ÿw …v8a·JõÉÑÇ0 Éf³¾B¶Ÿ°C–eõ»/ˆ8ŒVT¨=³÷Œzq*’£A>|A»X:¦¹¹‹Ÿ>û¬úIV9Oz²œ(Ý›››Ç]igÛÅq‡zޏ5F£QZ[[‹ £Ч”Ù³·ðè£ûølƒ¡ÀLÓÒ@Édù0v`î¿þ+7,\ˆì›;—›Æ” }üãXxžšƒaR0¤æð 79 ß‚4PMñ·á¤“Ö°cÇÈV ˆH©¡Á¯—i²lÙÝ\rɽ‡U®J†r}Ë‚?û³=,\ØUv9™”0aA/·ÂàT¾ ,è W¸7ï'˜dp8D"_Ëɽiš~‡k†z¨(Š¢(Š¢(ŠÒ‡ 1ŠåÐE•C§¿v”…³âÑ!á¸Àû_¼„JŸ ‹¢Ë]/èÁ2P½¤nb4‘¹n¹¹°i¼E‰ÅûJ£Æ¤RðŽw¼A׬‚?’yúoö@ ¦¾qÈ_8k‚yû½t ö2Ø~Ôvö®ÝËñ÷ïéþ‚¡ºˆìó*<¬¢•w41´zlذÇ󢕨¶Íþýû1 ƒçöí£zÛ6žüþ÷™ú³Ÿ±å¸ã8ý­oå„8ãæ›™yÆ…Ð<òò÷÷" –º„‘H„æ~„St0---D£QêëëÉår}ô1b Ê÷t´ó¬üòƒ¿õ69â *’ËÆ[©|D¶mÓÕÕÅæ3Π©©‰x<î'%¯®®ö“¤æñx|Ts¨ •þŸƒáuZFoËê›|m¤ìÞ},§œòâ€!¿$\㔲âŽ)18ûÃu=7Íýûçå²ÿc3zI{”†ÿ iš¤R)Òé´æg%Äó+è©‹ÅÈuÏ<ƒ…'¯ÿ?{ï'GYçû¿!„\È­’@ˆ‰5„‹ ¨Ô€ì€÷Y—]Üš¸®Ø•îuϺà1K·»+ÇÅßzº%ç(ëþV»ñw@—=k¦WVôq»Ü##Ê"fä¦LB„©dÈú÷ÇÓߪ§{ºgz.==™ÔûõJzº®OU×SõÔ÷ó½LÖÖB‰56êyšG=Oå×ôPÂŒ[þ{)°³ôÖ¬Sʯaû-_†õú®iš,[öà˜·kcK£yï½+صkňmÔÑ‹ÌËü\®rYÉq[oð,"°ò¯©×EíG¨ÄÄÄÄÄÄÄÄÄÄÄT£§”ª&²š!3ŸÏ“N§Ã46“A¾ž‡]̈Œ.zEFC~by¥tÝÚö§L&J Wkžhij3fLäóð⾓À„KN Ì&b= ŸYÈòW—̃…G²àÈYÀÉ÷œ¬Òë ÈŠºmß¡v:“:ìÛ·U«Váû>Ùl–^xÃ0øÆw¾–ÅÍçŸÏÊ#G8ðÆ7²ë–[8ñâ‹£ J7”èE†FB¶šÄxm%#Ù¿ûûû±,‹T*E?½½½Ãö#µfFJå4ÅÖúöûÞÎIû&7I×q'¨„y‰Œ´»w玲­ Ó4Œ<·‰†aP,[+åÚ‘‹d²iÔëa¬‘_’ޝ^¿•PÆÉæÛß^Źçž^w¾Þ&‰¼I§£”‚òËf¡««r]×Uçáö³hÑ»¨‘šo܆A6›­™Í4M,Ë"—Ë‘L&éììä¾ûî›ü“wá8•4PÈd8ý8÷tuý8DNÕŒõf[KP±ËÓÓ¨û‚C¹b;÷ý÷®`Ïž¥cÚW5c­ÔL–,䪫¢<¯ºÇŽNw·út ýþ“JEýÖ÷Õ2ÕJII&¡ÜãEðŽ4e|ßç?þcò=bbbbbbbbbbbŽMÄɶžç…éÝ}ß'™L’ÏçôàÑ6”÷µçyd³Ù†½©ƒ ™LÒÕÕE{{û¤yaÇ"Mäøßˆ³p(”d\’4dõ¨eþ«õ:úÒKqʯÉ@Ò¥ŸüÔa8k7oxâZð`çÎØžúÁ–ïXÎÖE[±°¢Âòy”÷¼nÕû¼¡oß÷ùƒ£Gyù—¿Äu]Çá׿þ5Žã(›a&Ãí=ÆÀOð;ï?ÿåôÓ£ô þ– h$ìΠδ!Ù²ÙlEà‚ŽÜ'3ãÈÞS÷rÊS§Lê±w‚Š<ñ‰gëÖ6Ä[¶È4£šžyÈ1ø¾zP^vÙÌž}úˆû«ú*Ëô[ˆ¨3qªuÄ»Âhoç‘w¾3ü-2ÀHg{,‘bPB=gM õ<Íió%*Æ+/7û¢þI9ÖZy][ÁÁƒóøÅ/Þʽ÷F‘*õŸÙ¬ê‹Édíý^$Ç'§ˆÄÝÝQÊ/a¼µBD«´r?7M“SO=µu':&&&&&&&&&&fÚ ©ÅG2SX–EWWÙl–L&C±X$“ÉÏçCáÂu]’É$Éd’ è¬Ê£¾ïÓÖÖFgg']]]ø¾O>ŸÓÛ¶Mgggh<Ìf³áö …]šWi>ŸÇó¼ gB½^lr2=La\·~ŠmT*râíêRO4ÊäÝï~‰5k¶·úÌ\^}í5Ø9ƒAe‡ XøòBÎ>ñl8ý*rÀ¨\î”§¥€qšt|ßçÒÞõâ‹\óÅ/òæ_äó²$—SiòÇßý.k††À4™wð`tU#9ïF#&ßH;p×uCgöZöT*5©i¿ž¾ði­84©Ç1&A¥§§‡M›6…ßûúú¸îºë¸îºëظqã¤6¬è7Wù¹äÍd2*êä-êøª¶fDpT£×û¨‡ä–+#­“ÉL~ˆâ¡C_­ð~¯‡ÔTú’£šLaÛ‚@¥“¾°cÇU,\øÎº“äíI ¨î̶m7%RéxC·…»À›_|‘D"mÛ$´ ³ÞãDnÄãE/dŸ!¬;†I¡²hñbœx+]l%»wŸÀ9çìuYIÍW¯ÝRS TßÔ»ÚwœË®]óI§£õE‹N&ìVcÛö°Fµ´’šñœsΙړ3-‘tÓõôL&CaU©L&ikk m7‰D‚L&ƒmÛ¡¨‘N§éì줽½=´H$K:&“ÉÐÛÛ®W(‚ lººº( xžG2™$›Í†‘2…B!œ'‚‹ˆ,Ç{JrÓlܱ_^ƒ@‰lÙìälݺªÕ§aFày€ ³Í€¯½ÄYeÇwÁÁaߩʖ±âÐ V.XÍ ÔºdQŠxÊŽÃ0xý›ÞÄ™rôèQÖlßÎ'gÍbi{{è]jš&Ë—/ÓdÅßý]«OߘhfÝYÃ0*îK²/É•ÉdH§ÓὯ½½½áöŒµ®Õö5Û9xæä¦oXP¹ù曹îºë```€k¯½€µkײyófn¸á†1í¼¯¯¡¡¡Šiôôô„û™Lºº¢Zrê `hh(|Pòì'ÀæOU U£Qã-Ù2RXk:=>ÃæH4zqËaKZ2=ç¥çE©„2M Ó6=wî\ŽYP7¬S í‰1(Fò[Tÿ&FÍjõMhnÿ™yô§?Å4Í0ÕÞH4³NF±üà•GV²}û=ïyí@[¹­ D—±tŸDέફvð¦7ý”7½é§\tÑà¨ËKAù‘B§¥ÏŠÇ(áã©§.`Ë–åa¾Ûl6J:Þ:k–eUÜ_Fº2™ .lÉyn&­êŸ111£3ÕcÛ˜˜˜ÆˆŸ11Ó—©êŸâÈY/Ñ„¤à¥»»»âýß4Ͱ.€ïû‹ÅÐÎ)¿,µµµËåÈår¡£ '¥R©âýÅqòù<¡Ðbšfè4èºnµ"Q*z2PFJÛ¶q]×uCA¦:jf¦cšÐßߘ³°dpѳ1M”… rê©{[}&VŒmƒHÀüÓøð{úù½w-Šfî ‹…/©÷üÇ–>ÆÜ¹s•'¬¤!±PÆ^ •‚¤Q3žæ¸Y(š);?ÿyþϼyl]´ ƒûW®T7]Ä”Ëdx«Kqé)`²‹¿ëÈý3NãºnŽϲ,Ç!—Ë…B!X<ÏÕöšL&[."7$¨ôõõqÿý÷s÷Ýw³aÃ6oÞÌâÅ‹¹í¶ÛذawÜq›7on¸C‰ ³eË–pÚ¦M›¸æšk¸ýöÛ¹æšk*¢a&‰~¨I8Þ Ãà ” íåešá«‚±xØGü‚©õŒoôxô4@‰Äð6ŠÝ´½]ýÅ¢ú m[­{õÕWó‘,ω^@[oËXR´é×ÂðöÎ|A¥Vß„æ÷O¹¬WýàÓæ<ËíþÕeª¸ÙQÓ UãLnÝy"6‰ªÃRMP^Þ4a¡¥•±h QЉ²s§J÷õ‹_¼•gž]lÈdT«7ДÚ+&-_û÷ÏæàÁy,YrQå± ¬…mÛ#枌h´éL«úgLLÌè´bl3:ñ³3&fú2•ýsä¨{U¥P(Œh˱¥–S—(™L&4êΚµl’¦8“É„ó%͘Ìó}ŸT*U±OTÄP™H$Èf³d³ÙP„q]7œ6/tß÷‡Y%ŠfºÓÖÖXji©.ﺓÁ™gœq)¿Z5¶}ŸË8ð/§ËÙ¼å-«Á-Û`VMiN P‚  r¸Û¨_’þKÄ•j&U¤ËK§yà»ßåï~—ç¾üeòù|XDý±¥KYyá…`|ãì³Õ…£;Ã)ºšm“†µî›‰D"¬Y¥ÛrF+\ïû~S£k¡¡÷÷ß?¬]»6œÖÓÓÃW\Á¢EJ)\¹r%+W®d``€•+WŽºÍ›o¾yØ´7rÛm·ÑÑÑA__×\s  mo4äÞ/B ÀÖ­[aÍfÏž.÷ÿý ügùZÒMv=¾ê‡Íì"¾ï7äqŸJ]¬©vC3ú}£‘RÄZïí­lW&£„Ï‹j8ÈøÆ²¢°Lf$5[å}mìX}C©£>÷Üs“[H­¾ ÍéŸâ%êáø{O>ÉsÝiUŸÆN<ë0¼KèYì¡î'TJN¿<- J&äQÊràC=ÛåŠrQÏ}¡VtW¡¼¾_cÛãe×®]ÀÄ£7¤OJ=$P}ö™g²zõ³<¸¤byێª«ƒ²Y%Ê4"¶T÷ëV{'LSÙ?cbbÆÆTmcbb#~vÆÄL_¦ªú~T´¼š H§Ó$‰Ð€:ŽãÔu⪗<‘HÔ$º¥2º†ˆ)â*FÇl6t–è–þþ~ à —Ë‘-§w£B¡€eYtvv’ËåBqf$džç…‘7ù|>,&-ÇQ(0M“B¡ènÔ0A„Ñ8rÎ'’ÊÆ–Ñ%´C”ëö6Û‰úX¤cÛÎß²<‹.ºˆ«¯½vüuŽC¤è¼eY¤R©º÷@Ó4CÛª~OÓI§ÓiG‹`™ T/^\ÑA6oÞ v"PuHúúúX¼xñˆÛêëëcóæÍă¾¾¾a¢ÍâÅ‹GM!¶ÿþQ;o6« u®⋃ƒlÛ¶óÎ;PJè#>Õ ò<ò²T 5ãET»Ñ«˜# *â­Ñ*FÚ¿`}_=åÁ'Ó 5]ïoz”ËdR«S?ùä“:t¨u'o©×7eÞxúçŽ;èëë«;ßóT ».Êi´ÊEÇÂTÜDçj«W?Ëü7Ežêža BÅ–F¥ ìD tE–3ËóD)ÃdPoÛ6Ùòü|yG[n"ìß?›={–LJ}ÛŽRðI?®5æ4ŒHìL§+£ì|¸ÕM™Z1¶‰i===ìØ±£Õ͘Z1¶‰i2¶Ý¿«›2)LõØÖ÷+Kˆ(„)³ Ò±r:"ÆÆT*…išÃÉ2™L(ºHª"1VJMI ÖÖÖƒBÁEþéÓ$%š#µæK21zvvv†ï·®ë†Â„6Õÿ‚ ÛªFB¡P¨HÉ$õc:;;CG¯#ï•£ŸÇH|yê©á[ß:ÀM7]_±Œ›ˆ*é:†8ÏóøÎw¾Ã?þã?ÆcÛ:ÈØ¶V­¤Z¬ù›}¼zêÏ9é¤}ÑDØ,ƒù»æÃb%¨œóù¬yßšqçË¿ü¥ú£,òÝÿÈ#<ñĘÀwÝ…µ"ªÅÔFl4ØøÄÞª *ºS»~¯’ô`ÖîîëëkÊØ¶!AåŠ+®```€›o¾™Í›7“Ïçéèè#R†††Ø¸q#+W®¬H VÍÐÐ7Üp·ÝvÛ°h–½{‡oj$dìå—_õ¥3”Ñö®‚ò½ääeËX½z5OÌžz‹W#&º#Ú´êìý6P±m»á4G–59uŽtZ%¨Hí…zû—yžE¢H´¨ßµÚ˜«×^›ÌеZÛêé陂ÊH}Æß?wìØ1,®àûê·üÞƒrÆøåPá±"êt³yß'ï®ø.CWٳܔHÒ‹Š2u‰¢M‹(áÔx Keº/}@ì–—AEjªµ•×s‰"X„Ã#æª1ûöÄÞ½§2oÞN.¹d|Šó`G)÷ôè°sÎÙ7,FïçÕ¢Šëªiú8µÞ¸¥‘ß{ïÞ½3FPiFÿŒ•˜V200@__ߌ~6slÓ,fŠ ÒŠ±mLL3‘±íË/¿Üê¦L˜VŒm§ÒqKꥈºÔð z4J5™LÛ¶I¥Rá'Öd‘(3@‰²|u4‰mÛ¡¸!ëY–6åoÇq*„ÙŽœg‰æEjÖè1ù|>܈0žç…ûÑÆ÷ý 1(ŸÏ“Ë){™DÎT§’ýë <ÁÎóÂó¢Ï—VôëG_Þu]^yå•xl[ÛÖZ¿øñ_ŸÈ¯_úV¯Öê³ä‰ŠV˜¨|ê¢o-WùšY³ØÓÖÙ,¿·k«?ñ VíkѲ’Zã¼?LÇÕ.kÛvh 3 #\Þ¶mÚÚÚhkk Eá®®.Òétà [¶liÊØ¶¡*+W®äÎ;ïä†n`Ó¦Mttt„Åé{zz¸îºëX¹r%·ÝvÛˆÛÉçó¬]»6 ìÝ»7Œj©Ù2000¢@°lÙ²°-#aiP~¸g,YÂÕW_Mÿ’%<‰2Nê?qµ@r ü)†ÌIÖ3€Æ ‰!z,¢Š^§¤®;ùéÿ‰H¥*jä%JEmWýK$ÔÀHÚ.Q,…‚2ì† “š¸Ñ¸Þ kÆ #È>V©o®]»vÜýó’K.aýúõ5ç J;ýÚ'8k÷ëÇ%Œ˜¦IMÍù(<úÒK,8I«J ±‰DVéBÒ5M*ý J•çÙåmyÀ‘ ˜½?Dã‚n"Q¤uo’ûGTg-_žæ@¸¾Q^¶H%#œtÒ¾q†¯….¨d2pÏ=KyöÙ×*ö!š±¤ì–Nt™€IDAT“¾*ße;étT#É÷ǵ²råJ6lØ0#¼H›Ñ?—,YÒг3&¦H„óL Z9¶‰i6l`ãÆ­nÆ„iÅØ6&¦™ÄcÛñmëÙ:R©mmm ¥]ŸŽŒö,)ÁÄP™Ëåð~âycÌNU ›C+VpFÕo= Ò$X,TÚ³S.ºˆE[·2UsEæéGiE¼ˆ¢W”pbÕq‘6ˆ ÛŸ¾|9{ö ð Wq§o7'v:òs¤Ó°bÅëxå•W*ú<«ûb.§¦‰€êo×a´rù‘ )Z–5íêðLSÝ?cbb§cÛ˜˜˜Ñ‰Ÿ11Ó—©ìŸb?¾«"è‰D¢fÚ¬™J"‘ Nc™L& ,Ë"N“ËåÂ4au"N²Žˆ 2ÝqœÐ‘Öq‚  X,ÒÙÙ 5  «†aT,/¢Žã8¡QT¢cÄû<›Íâ8ù|>,j-‹áÕ4ÍÐȪ·Oÿ.íð XF׈AŽÑ¶íPpJ&“a»óù<†a„m:ï¼óf¼m¨™c[IptÑ‹œÞy¬ûÉᨸ¬S¶²‘4`JÆŽ-[8qíZÎp]ÞöÏÿÌ«_ü"ƒK–pÍÎô}þóüñªU#F¤´ºnÇLÇqœŠT^–eÑÝÝ]ñ]0 £á´_Í aA¥‹-jXL©V$¯»î:®¿þúp}Q@;::èëëc``€+¯¼r™L*ƒzeݶmííá|ÝX¹Ú†¹TÒ>•†w£ïAÕçT’HŒmR ©;R‹L¦y¢J#ƒ“Fö]m”•>ãûÑ<ù¬>ÎÉëËsÏ=7™§¬%ŒÖ7;::šÒ?»»¡Í;Êo~ô£q…Z˧ټZ#}²ñÕçœÃìýû¹¼Áu¤‹_H7ÑEIæ ¢bÎ>õT–ý-GçŸË¿›ð&GP1ÍÊ~ú‘,çg?«=ØÐµIUåg´¬(¬޽¡ÚKˆŠÇÑL¢Uý3&&ftZ5¶‰‰™øÙ3}iEÿŒ¢áÒétè u¼ˆ)‚î˜&≤ÓÏ…ã8ßå=]Òñèïíú߆a„bŒˆ#¹")îuGUNlÛ&™L†í÷;¾ôw¼|>nC所#é·Dd‘öÉ4‰¾‘”b–eqÙegððÃ6¦é†‚ˆnI#í–z*©TŠ‚–²Ü0 Þõ®wñ裶ú'ž0­Û”Ž,ü-ïxÇ;øè¿¾IMÌ£ŒóÀ˜ fuäé§yd`€}ë[tz÷{¿Ç“O>IæÀ^]´ˆl6;j9†©ÈÒl‰ìhc±ç´º0}ÂÊÀÀ·ß~;,Z´ˆD"1jX×XÙ°a7ÜpëÖ­cË–-lذ¡fNͱr€Hé<ãÀN^½š N9%œ¯w…_äa• /W]Wzé$—á^ããQFÇK>_il”z}^ê´¢/–ŠLZP²ŽP,‹\AÕqš‚ï«co±k ÔbÍš‰§;˜ìþY(@gç°,^I§Çm/‹ãZo,,ß±ƒgžy†fýÒR¤þµq¬ç—ÿÕ;{fy¾¤;oÍ{ßü"gÎÿ®2Ï =Aò¨AL7‘c¡„h(ÝX@Y£ 9µ´°'ŸìaÅŠÚ"™mGÑiroÊd¢zI ÄãF2êµÒ+aºÐ¬çgLLÌĈûfLÌô%îŸ11Ó—ÉìŸz½U1"ާvçL@7›¦FöWV%sD&“ Ód9ÇIRï}Mjjy¡ËïT핞H$ÂèùME0‘¨‰Rq‡t:F–è©Ì,ËbÞ¼€›|ßk4¤R©0:Gÿ ‚`Ø5dÛ6ô÷÷·ú'n:Ízv>æBÁ,X²XÕA]²d‰š)e—‚¹gbûYºt)ÿÃ?ð¡k¯¥;•Â4MÎ÷}^µ,,Mø«FÏÀs,Ö\š‰˜¦I2™hI–’†•ë®»Pê{zz¸öÚk¹ûî»'ÚuÇwT|_¿~= °råÊI ¹^à(/mP¡k§q}Â;b@„J!f*ý¡GòÜ>Ö0ŒÆýù›J Oæy‘0¤G­€2ÊNÔÞšËåf„ Ý(Õ}šÓ?7ÿöNyñE\×ö¹k÷ïßß´mÛ(‡‹›Ï8ƒ¡q tõ®N«ês;×q÷£äµ9sÂéê>'C„‚ö]uÿóP·Ãh+·[]Õ‘'`Ölx^$’Šª ÏåÔúA ¢˜Fb¤úLeªúgLLÌØ™ª±mLLÌØˆŸ11Ó—föO×Uïòª9žºÇ;ã1‹q³çºX,V´IÒ‰aš/sÄÆ õ¤mét:¬í¢ÚIEm—D"Q!˜Èqèû­>¶žž^zé¥ÉÿZÌ”Žmˈ“M-ÍŒ2HdSÍ…»_÷:®ùíoÕ—²q÷¾ÀG-â_/»Œ_ž|2Ùl6çF‹Ö˜I©¾¤ŸëHm•=¨!A¥§§‡}ôÑPy´m›M›6MzÑÌf f÷jçöèÑ£¬Zµªî²ï([õÛ z#OoAìúSijwœ™#¨€òJ J Otã­mC6«KåúR€Z§:be<Ä ´b2ûg&__¼”ö—^â`-ǶY½zuS6m  ÙvÁöÏž=¦\6jl1RV†èµ¼<î{mΜ0Ò$Kí”—-¢¢VЦ‹¨R(/£÷Š$)¿¨d2ªŽÊE]„eµ ?^CõÍDB¥d´¬(·±çAg§ZÎq`éR(•ꛄpÇ4çù3qâ¾3}‰ûgLÌôe¢ý3Ô»†î åºîˆõc¦?µD}šDèÓ$²Dtd2M·Iår¹Øþ3 ÍxvîCD–lXÍçcä‚Ç£/¼á^xúi2÷ÞËI·ßη¿ö5~pä'NAÆ“é†Dvͺ»»Ã(•©æÄFìèè¨ãºâŠ+ZÒàñ°K92Ⲥa›v]‰g¶ä «¥¯Oµ¶áº¸˜ &SÁµ¬H@±í‘ÓwébŠªïìT‚K#éƒb¦†t~tÒI\øÂ ÀÔ˜+V¬àÒK/’H´åË—iyiÓH÷¡êîòºÿú îo&‘ˆb¹%òTÇ (ÆÕ–÷ˆjµ€úmUßËÖŒ<’z+¾¯îg‰„š&µžäþVŠ0¦&3Á»"&&&&&&&&&&fò卽zj¡fõ¥çŸ¾Õ§ä˜ÂuádöÏžÍï­X1íSªÍ›7w¼ãMOK]Äš÷½oLë8Œmla;¿ñÞð»ˆÆêþ–eø=Í@ (R(ÎÓÖ¥<-ƒæ8R®g$$‰¢]@Í“ÃP}4•Š"Ê,+êǺ·çUn·â¸¦± 3µF¥Ý ™LŽZl:æø#~œüKðà ×)‡[öym¦s¸ƒ{½_Î÷}eTÈf!橳ÎbΖ-øAÀû—-`Ñ»ÞuìBc"<Ï#—Ë‘Íf›–®mÆ *ž'¼þ(»víâÙgŸåÀH^Ñmëò÷¢ˆ}þl#2" ÕFǩʨ×h!w©ŽjmÅC)“‰¼Ûu‘U"[\wxí•É`Þ¼yìØ±cÊ÷XçUæ>ôPEnÓéÌhý{2.-qÊëc},¯" Íû”ºfMmºMe„ŠÞ.P÷DùÛÕ–sµu}àg ¸FËoêWÑÎô{Y2õ]ÃP‰aTÖVñ}5]"ÏbbbbbbbbbbbbjáºÃSÇÆó˜˜é‹i‹ŸŸË²eËàÚ (F‹‘í&O=õ‡zzxeË^]µŠ{ßö6ÞýíoóŽßÿýh¡qJ …´v3í¾˜Ïç±mÇqÈçótuu5e? *[¶láºë® ÿmÞ¼™Í›7WL“ÂõÓ… P©dæ~vO?ý4ƒƒƒªcÖÁ‡Êк ra:FÕºS•tÆ0bcb-\·ò~˜É¨²çEµšqŸX³fME:¼˜Ñ Ø ( *ÓÑ.›ÉìŽSѵ_›5‹WzV„Çe¢#"茄¤ “¨}º…ŠD¹Õ‚ǵ™R%\¶œòË0¢‘õOËR¹Ž¥ßB$¦ˆ ¢ -111111111111:⨥þvk Lê1Md¦ÆeÞ‘5œøê«,xuš˜AR 3ʈChH„F‚Wð®>å^ûÄ'ð»»yíÝïæ¯¶nå… * c$›ÍÁŒ«Ã4“úïûäóyR©†aP*•°m›'žxbÒ÷Õ ²xñbÖ­[W1íX(à*‚k׊€ªŸröÙgW,£›r `© «ìè»0{”'í̹ü&VÔ5Èf£¿;;£ôARŸÁq&?í×¥—^ʹçž;åÇz,cYpÚ‡÷³bþüV7¥aFºlÆUR‹nÆœt̘¨‚ôï\Þ·´:Ø5ŽEIqèŒr^Dt©žæ£RŠù‰H<‘²D"zá©ÕGešëFÑ+111111111111µPލ.Ùlß÷+Œ†.êݤ½ÕŒi)3Í3ÿXæOÃ’pôèQfïŸ »P¹Ãõ”#¡¥±Ø·oÌžÍ×_ÎÕŸþ4Ýt‰Db¿w>ŸÓNs|ßÇqœŠû}"‘à¾ûîcß¾}“º¯“YhíÚµÜqÇ­>/cFÒÇ´ç±k×.f_tѰeªûäc¼Ýƒ—¨@wy K1­QŽ•{~³òÔÕ£ÖyáXR#º®ú»Pˆ ²Ç@¶©G>Ͼï5®>á„V7¥a|ê÷ùÉê’Ê £™˜ÀÉvÀ«m{€•ÃÚïP[ ‘å2¨Ñ. *£O D‚‹0RðÞ§~L¡ ÄÛžšO¢S¤;÷Á˜˜˜˜˜˜˜˜˜˜˜©Ç¶UÝõ·Jÿ‘“—AT#ÒG½ÃÄ>[11-â ú8iÕ‹¼¼ú|øÊ  Æ…Fßÿ³YûùÏY·jçZVM2ÅÉ« õ1Ów”Ú–eñ‘|„… Nê~Ç\Ce``€M›6±qãF6nÜȦM›šÚ³5öìÙÃК5£/ÀÎýlyUç­Õ]TZ¿,ÍåXJ÷5•7Èj2T‹$z]ÏSÅê}¿yEêcFÆ÷ÁeÎ1ó0’¨zÏðcã("^Ý1‡×.>µæ¼Ã¨¼çÙÚ§ˆ%‰&Qú0¯j{éRô])R¯O—ˆ]PÑˆ†‹‰‰‰‰‰‰‰‰‰‰™ž|ë[0MÓ4q]Û¶qNÔûˆ‹zOé*ÿÝÙêFÇ´„c!ùñÀÁ½êó”K(,®F$Ý×hž§bÜËç¹êª«8tèét:´L4²Ä0Œc¢öïñH#‘GguÖ¤ïwL‚ÊÆ±m›7Ò××G__7ß|3ïyÏ{¸ýöÛ§îl=ò¹gϨËZœaVP€e5•êŸ,[ž&©ý=T=f0Ýïùb(ŸÊÊ P÷PÃP®u«m«š º÷»ÔW‰™zlÎB:ŽkžgA0eýº¡•¾¾>n¿ývî¼óÎ 1`Ñ¢E\ýõlذ|¾YñãÃqàwÿâeNÚ·¹sç²|Ç ¶1Ï×þxÌþÕ3­U§¯µ|B›ï¥ûóˆÄ•É:CÓ]PÈdš] ¢Ç^èº)Pª€}õytÝXh™ ¾_€…Ï<`ZÄ* Ì+ßÇKùSOù%õR Jÿ…6ß-ÿm¢Ò#‚º/fÀ-#\’¬³Sõo‰fQó¬øZЉ‰‰‰‰‰‰‰‰‰Ի¡C‡xæï ßI²(ÛL‚Ú„ô÷—jº€¨º8æØERÂÅ´žŸ<Ê‘e}¼þu¿Q.bX‡39XehͰm~ðƒ`Fø/æøbª~󆕞ž:::X»vmÝe®¿þz†††èé陚3ÔïÉà >‹-bîܹ,]ºˆÂ8õpÎÑlè³ËŸÕÑf6]}¾]Þ¶KVê£ÆÉò2yêj®G|OŽˆ% D‘Z‘^†¡¼Û µlµæ *SÃ<vÝ{o«›qÜ2oÞNÎ?ÿ+“²­ê¨¹5ɧ.ªH±Gˆ^hDpðÕ÷µDBõeIfY*Z%“QŸq‰‰‰‰‰‰‰‰‰‰Ñqxá~Ãï¼ü26êÝ#ËÈve›i¯šžF½Û$»Ý&fz“H$bAeš0ôì|~ÉRæ,Œ&V½ëëe¸.?ûÚ×øÄ×¾ŽÃ•§Ÿ(Á,TbšEC‚ÊÞ½{ÚXGGG«§‚]ÀÖ­[Y¸p!¯;çN:I¥¸™¬‡ î‰]=ÝCõ}›(Z%Už&»å¶¤‰Ä•ZjL‹±G&F®3#µV²Ùáóâº*Í%`péþý­nÊqËc}‰yóvNúvM†G÷DÅë%ý¡©ÍÓ£üô.+Bs>_)œˆšN«iÕ‚J:MLLLLLLLLLLÌqL>§_É7N;Êæ’"в¯GõÞ"¶š.”=&CcebbbÆŽÌ?oˆÃ‡³fß5q ÕKp].Ù¾\.Ç íí~ê)e{ˆ §u) ¸îÌ©%%'¦²ôDC‚ÊâÅ‹UNéë룧§‡¾¾¾aóèééa```ÂwІ_ïêaÙ²eÌ9ÿ|-ZD­î4ZsOdê¯gÔ˜õýªÈD‚ŠUþ—etO‡,•©ÂXóÔbŽ £þy2ͰVPiÕ ^ŒÔ7arú§çÁ‰¯?ÚêC™$ªS~é©EXäÆ)/'5Vl†ß‡óDb‹žÞK"ÌêQK$)LEÿŒ‰‰S5¶‰‰ñ³3&fúÒÌþyŸs_~0|Wé%zO‰êݤ hC½Óô‹)1ÇS9¶mæ-;Ì¡C‡xÿÐû£t¼öveÈËfÉçótwwsòû߾㌥Ëñ…ïû¤g7ª£÷}ʢΪJ|ÅW°qãÆ0õW-6nÜÈÊ•+GR¹ùæ›éééaåÊ• ÐÑÑÁ-·Ü·_·n[¶laÆ Ãj¶Œ ^÷º×Õœ•B ðà*¾U5ùi` u DžÚzHšÔW‘‡yåíàjße¾ö«ÖéîfTäØŽ×Û‡m«ô]õæ%ê³Ú»]ú]2 Ç[íª‘ú&L^ÿl³`ÅÒýXݱ·@«˜Ì°×Téò«µ'¹7fË‹^]@Ýël”˜â ŸòišJTI¥ê÷ñ™ÈTõϘ˜˜±3¥cÛ˜˜˜†‰Ÿ11Ó—f÷Ï“ßy”ÕÏ÷×£;Ñê$ˆjáJ¤}LÌñD+ƶ;ï;‹Î>‹çy~l+8žžD"¡lqÚ™ÁADÛ¶'²¹–S‰4­••+Wrýõ×sà 7H$X¿~=‹-`hhˆ|>Ïí·ßÎm·Ý6âvúúú¸ÿþûùáÈ¢E‹À¶mÖ¯_ÏÚµkÙ¸q#·ÝvôõõqÍ5×ÐÑÑÁÊ•+Ç|`צ,̹i0%tê>=¸×%´ðY¬S…MmkPç‘X"‚‡tw¿<=KTo@ê°HzYWGÂQe¿¶¶üñh¶¶mõ¯"”X–ºÏVG¤d2p j¹B¡²6ËLe´¾ LZÿ¼Ã…ƒ?š \A.úF;`€ê@™—Ÿ$Ž¥~6•¡¯#ýlò’¶K›n•?ÿ‹+µþgª?ºîðH4×Uý5fV©©ìŸ111cc*Ƕ111?;cb¦/ÍÏýö(Wœ08ê²µÂ×3ÜS“Vm·Ì½gßËU»¯R®Ψ± çE)g:;•Ï4¹qíZÏSâ€çÕ7Æ„‚ƒã8†qÌ *­¢¡”_@¨:æóy.¾øblÛæâ‹/æâ‹/fóæÍÜvÛm\qÅ#nc`` BŒ‘·wï^zzzX¼xqá²víZÖ®];j±ýû÷×\æ—`ÀgœÑÖeúÛ±LsÔ)uˆÒéÈå+Æbù_–Hx) j­ÔJåU@µ/_þ')Å ¨¢jK.*Q5­‹ÊÔbÇÕÅë=Oy¿[–2ÎzÞÈ^ð===ìØ±£Õ‡1aFê›rœãéŸ;vì"úŒ¥y;GVõÈC©^î%±õ¨¬(a\…6Hñ¢ñ¤€šN…ÎÓD3M¥úš$Ê›ÕItsÈkç0¨}Òþ‚òDÈd2Ñù’åôûÜ$¨«6êžT C[¦úô»DÅëàÃs^Ô4Y–rH)h ³eEõUdÀ7•fôÏXP©B®#½? ÉÓD ±7 ê§rÿЧ‰È«‹Ç1ôõõqèСV7eÂLùØ6&¦ÉÄcÛ±mcb¦Û¾üòË­nÊ„iöØÖóàÈ›ŽÆ©c¦ŒxlÛØØv¤ÚÜóæžÀ{¼·±FJJ ͦ”ÏkŒÌ§+9™ª´XSW#ÝÛ–-[š2¶m(å—΢E‹¸âŠ+† (lÚ´‰ 6Œºn¿ývÂíÔêX„Œ-[¶¬æ>/ËÀclß¿†Õc9À+'ñ//¶z*ÊC˜ªK/CrZ"; ²ËPÑ02\°«ÖG[^êˆ=Zjˆj!ˆð!2y†EÅù_nY~yÿ "Ñ'A$â˜D6$)L=ÖLNÍ@D“¶6(•T4ŠÜ{õT`]]ÊP›ÏWzÅoذ7¶ð&—Z}Æß?/¹ä’aù4Ìì¡ÝpÍ¢Ú+¹DêžT/wQS‘èB²‰.0uA§ËÓõ0­€(„K*¥W£*Êkßíò:Ò¹’åý˜T„ŠÛ€ÇûQ´_þL¡:¬ºðÝr¥ˆ“äÿ³«Ú’$ e³ªæIB_é´rŒNy~u%x=VÙ¨›èODÆ]9/ùr›åLúY`¢73Wþ;kšD”Òð—¦7•Q*ð<ÕGm[]Ÿïz׆åE:™ýsÉ’% =¯Çôcýa©«Î÷Ö,ÒDž ‚Ü[ô‡O²<-_n³7³‰„Y›( D~IÿrËëËýFrÊr¦6?[þ\Šêc-v”ÿÃc`1˜Ì$Ñ`*ƶ11SA<¶™ZcÛ˜˜©`åÊ•lØmë¡m¿÷=X0khRëFÆÄŒD<¶™‘ƶbºXøÇñâá³™½v6°¸vº/P†ºª߆aHhi-b1uTR©ÔÄ72Í‚ ¦¾~ýú¦8’Ž)Be$¤³5ÂÚµk¹ãŽ;¸ûî»Ù¼y3›6mbñâÅ5·9^¾_6ºÎk˜g Ä“êiÕL•£Zp[­ØyÄÆÓHW;© ¶,‹H¸DìÈ9¢œ-Ay™èEÙ‰K([wJGw±K‰ J?oIm;~ÕtÝYx*ÓIºEljê1˜fTK%‘P‘…3µÆU­¾ Ljÿðààì'ê{ Y(#£„Z™¨‹ÂÔæ‹Â—*/W$ Ñ’;cbbšÖ?w¯žü\¡3¦jl+¯‘A·Åi¿s‹Ÿ]<ò ’:Æq • #f¢@ÐL*¨@¡P ««kJëÁLš Ò›6mª]-ZÄÚµk?uöîÝ;îÂF{|X28ÈòåËǶbg®ÔÏž¡ÕvåF»8ÇB}çs@tC§n'›N‚H„Ä!¿zÛ‘½*•H·ŸIÙ ±uI$ŽËä;ÍKñz¹—d2J<‘: A‰Ûé4$“µ ÙëŒÔ7Iퟃ>,ùÍ/*=†\¢š(DFM¹&ˆTC‡ÊŽ(†[ˆ™/úöÒDiÃ$MX‚H‘}‰ #G,ýÝåO¹Wȵ°º•Ê»¾®Ge¥¤ÎD®‰$‘iB/ÿp³ÜîjðVݲÐõeè\‡zZPx ’CÐy3¤CúmÐu?$Î÷@ú&È& í@ç#¨‹Y<DðÕ‘ûZ–H¼)ß—¼Cåv´QyŸ{–~Oˆi:S9¶‰‰iœiÿ쌉9Živÿ4LØ¿û'q„JLÌ8hÕØöÐÜa+õ#S„L&,DŸ÷} …B\Tý8Dz, à •JM©°6¥‚ ¨Î)…ˆ†††Â|a^PPy3¸òÊ+ǽ¯%ƒƒl]´¨áåmC¥üz¶láßZ6:^Z6þTgç™LÆR¦EwvßÅH뤪ŽQlOQTL=ÇF‰'õŽElÁíDúòbWÊe.çþ<‘3®ØÂ'ƒd9ú@ Òƒò€qER†J3$é†fõú&0iý3`ž OPýö½ Öµ›ÎLUÿ7rS—:DYTŸ“ëB®E½.‰&R·DRÝ9TÖ ’žÜ¤_IñE–‘(¬TyýŒúô¿ù•àü ÞÎ,ð~þ2ð÷€@êÐõCHÝ ÅOUÞç³Ù²Fš/‹"¿§ÚVhS»J$Ê5Ë"i±¼žM¹moÁA5-“ÎNu}ærå4’‡UzWiÇ”„ôiàü©Z¾XTíèîV׺DPšïPâ{ dî„ô“ê9üØÿŒ=ÿ d.ƒàÍ`/ïu¸qj.™ÎTŽmcbbgÚ?;cbŽcšÝ?¾ñkwîlõaÆÄ“´dl›‡×Í30Á_0Òry: …0 Áu]<Ï#—Ë5¶Ÿ˜˜I¤!A¥§§gÔâJ¢^ŽÆwÜA___¦‡†­_¿žŽŽ†Í+óB…§Õ«C •å„ÁAø Û]øD¾Q€¼„MÔ`2 ûz¯Ñ˜HàêxÖ'c È4°&&f8S>¶ua~ç ˜o€`ÙËe³XŽƒa˜¦‰Y~ŠÓûÅ´‚†•úúúF]®£££¡®]»¶î¼ÉÌ=z¨tºn”Õ¶úgßȃ1Ei3š}§ó±ìGl]“<%û¯Îj'6ný4‹ó²…²³Éßi¢Zäb¿ÕÓõë÷P(D¿¾¯„¶6e(3Mõéûʰ6Ó4ŽÔ7aâý³Ç‡FÀ*ȼ°õ0¯Éì* ­ëÔr`v$´ï:yjw ¸´ÆöjEÎèÔ:VDÆ{ôÐ/“È -Ñr<ºÈ‘CEÏHDK¹>DET€ËŸ­Gèbˆe¾öo„H¹¼ß„g,e`îêR}ögØà¦gfZ¾f÷φÐ#¯ 2šLŸVIu—òàþ/°Ú¶õ´|2MjÀÏñ? ó3|Ì—!ñçàÿ˜+Áúkèútß~εJ¬hs¡_%K¥èoõ ‚úbœahQ(–¥žuSµJÈfmÊ6$Æ} ÿ ùMѲ‰„Šd‘}åóª-ÍÃÁ¶o¥\HE?Kê¾r0 Ù.0ÿ¬­^ ‰$˜¯EIú´˜†™ª±mLLÌØ˜ÏΘ˜˜š4£züú[sùÛki½F™¯115™ª±màÁ)ÿåUxG¥jÈÒ¥ê…Í49{Û6‚ ›ÍbÛv\?%¦e4$¨\y啬[·nÔÞtÁ÷awæÏy.¹˜`jÿ„2BL§¯±¹J*­FÑK7ŒeµÐt¤.°>O_Vìß¶6OlµÙ~òDvâîÏ“iFµR‰HTcU{{´œÜ« bÆÁAàŒ¹”'A€úÑšõüÓÓT5J=åPŠÊך—ŠV0zTÌd#J"N`xGÌ3<MòìIM 9’6¬«¼Ž¤jk§2šF„³êû8­ç ¥ý8íàᆴªEá£^¤|_õçýû·7é„§¸¨(ñRÐ#¢FÁóÊ‚Dœ…wAòT`"¡„0ëk`ä€.ðßF§B¶¹"t¶©e‹½<…ï@vØË ñYèJ‚óÃÓ2ö?7zût1Ý÷}òù<M±¨™hê¹P7*JÒçÕÙ_±=O,K#ǃüŸ€}k¥¸Ñ~R©áóÔIfÔþeY`½Ò_ëb(!¸¬Ï€u>X”xu1«U_ª8ŸâÕ;‚ÅÄÄÄÄÄÄLC¬˜ß4õXP‰‰™\<v¿þ”Šéaö}åùæº`Y¬yàîw]‰D™ÓR*JŸÏçÙ¸qcÅ´7200Ðêö×$`þ›Ž2wîÜIÝn­®ÚªÌ2z©‡±0Rú³É¤:Ú¤V;tô^z°‚¡Í—s-©ù%{‘ 9í“DµÇëaÊ8•HD†1³œ6¨³3š¯÷­ë3"GL˜·¦œPŠâ4‹ñl»Þï*výÕ&¥¬Îxr֧ƾjyÓëżõ¢FÒ±$ÚEê]Hj& Ó#V´Y0Ï€_þòýStBD@‘y£<ˆ‚ \ÄUé­\W‰ÔÙ§ û8ô÷+c}g'x?‚®…J º!ù¡ë^©áº*BÃq"1Á|Øÿ·þí©Ç¸ñÆ'I¥ Nã× SJ&“A@aÃBYÕðÌÛ»·Õ͈‰‰i]eG½mo¨cžï®|2~ôÖ·’H$H&“± ÓRÆ]”þöÛo§££cZ†H›&,þð~î[^1}¢ÏZ¶‹VeÄð½–I-¦êv#ÂM­ý5:MRòWc×XGÌT’yFjë5(ÇÚê”`Ýå•2U'T"U@óô{u:­ràÇŒÇ ðÖR*ÇR‹Q:ú1õ—Îé1¼.K½ßD¦Û Ï¡(ÄüBDÅéE\õs’]ºR@>AZ‰u&ªï>íÂ@lô<’¨~à£n´~yZ 2T¤…m«¿%Mâ¿ÿû÷ß¿2L¯%© õ™Ê©ßò©§ž"›=/,¾sçA>ÿy矿l˜˜mY`_ …¿‚îî–e±c‡‰ïû$“IŠEu‘û¾iš  …¦iâºQÜ©ëºd2òù<¶mcY¦i’ÍfC‘¤X,’ÍfC1E>-Ëâ _ðÈd2d³YÒé4–e–eaY]]]‹ElÛç;Žƒïûxž‡ã8†J_WìVŒ³V—AýzKÕ‹–$òÒÝ©ÿmß/o)[¡û«`ü ¡xšý(8ÿðo`ÞÄÔ‰À11111111£ðˆ³OÛŽeMŠ»[âW3yÌ5`AG‰ýœP!-­×÷zˆsçâÌÄ©1Ç E¨kx<û Ì™3§áu1ˆf¨mÌŸ,Í"5Q§~½Nv³©ÆØÔ¶Êõs+je6 òµO}Yƒ(+I¶ü/²ó6:ò<%²Ø¶2Ú5#•a¨ù¡×n̘øÐÆ©$fêOçwˆŠÐË6rÚ<=¢‰J&‘+‘ªY ¾,*è8'‘€…–ºg¨ÂôO{jÚgŒ^ÿ+¦|hÿ]ðÿ–(D°êAèû*Ò¤« ¾ùͳpẺÀ²ò Âg>óض«D[ýK&“Øv€m«¨Ûv¹çžó1Œ,mmm íôõ}€Ïþc¤RÐÙÙ‰çyd³Y–.]ÊÒ¥KùÏÿÜÆS§Æ0 \×%ŸÏ“Ëå‚€ÎÎNÒé4mmm¤ÓiÒé4ÝÝݤÓiLÓ¤X,bY½½½¸®‹mÛär9R©T(xtwwã8NÙR,)‹ô÷÷ÓÛÛ‹çy˜¦‰ã8twwÓÝÝeY¤R)LÓÄó<‰Dýâû>étš BáG¢W|¿|^çE‚Šïûu£m&J&9 ضú{ð%´tÿ;ô:àÜ ÙçÕožÿ¸C×SÐut]Ù·‚¿Ò¤oDuÂøþÓ®JÀü3w6Ås=ö!‰‰™|ž*À’ï¾V=?à8©TªiïG112î•éÎk¯½ÆòåËy©jz-}=£}½Ú!“™bÐPêó #Îå­ Ô³§&PÂGÍ"T5FЇLâ©.ˆCdßÑéGB¢ «‹Ô ây}Úi-:‘Ç CÀ©¿ÜËömç‚«/husŽ_2¨Z'â¢:TJ[_ê­ Ïy&‘," HrÕÐ[g’2l ˜€oÂŽrS2ÀW30?€%üöǧ·ê,Ï,|ðvÿ5•j  ‘Ï«û¦º7ÞÂ?ø{¼ùÍ‹H§Ó†çy¸®‹eYø¾aaDˆDmtuuaÛ6Ùl–ÞÞÞ05W6›%ŸÏ‡bŠçytww“ÏçùЇ¶óŽw¼Àöí†a`ÛvøéºnX°0ŸÏÓßßaô÷÷«H9뤋•dYÝÂd³Yúûû+–1 #ŒBÂmV{Eº®‹ëºa4ŠmÛtvvbÛ6¦iÒÙÙI.—ÃqÔz³fÝM¡ð*–eÑÞÞ®cÛv(¾˜£„° …0Òf4$íXt\åº)$ÁXY5­»[¯5£"6Í `|üƒdd^X-7®ˆ›˜¦")©¥ßêcÏSbŽS®íãDï³R)β3Ýø§<ü6ØÑêfÄÄÄ4È¡çàôófQ³ä¥ä‘VÞ«âbô1­fÆ *ð3>\s¾^—CŸV‹z†ýñi )²ÞìwSI¯>v ÉúSëXk¡;½g_ÕÛ'j}Õ‘,#aÛÊhP'í=ž§þ½ï}“îf*ƒ.¼ýÙ³¸à³LRÑ‘˜qÑÅØnbò[É£:ÕSµÂœ#ÊÙ× ¢:©¤/|ý†§§Ë×Ùn ¢šMÒß¿”†Ý6,öí{] NðÌ"ÀM@â«\>|~W—2ÌJD@[›|ÿXExˆP"®ë†QÉdÇqÈård³Y‰D8_ðŒ’7&P3­ŒëUš¦¥ÍO…tZ9;î€ây`~TE.¥>‰Çß”˜Æñ¼² ¦áºÑ˜¦PPQH¾½§‚MÊõ>Ã(2Ï‹¢r³Yõ>+¥‚R©HHM¥¢zI¦ ¹\´]GI›l?‘ˆÒ«N…ঠ{zZWˆÅ¡˜˜˜˜™Â.Î{ãó­nFLLLƒœû^xrö`Þ𙾯þ•=¿‚ “É„bbZIÂÊÀÀÀ°Âô›7o¦§§§bÚ† Zz@Pðà¤ó_aõê7 ‹PÈ68Ò»“Eeqô™‚xp7‹ÆS˜éŒ5òG„”jÛ¼Åp{±ØkÅø:š¸"éõkÿÍd”q!fl¬ì‡7¼å Í-FÓcélq"˜Œ¬Êʼ4Q'“~JÐI”·+‘.z>>W[§¯<¿,èÈ&«uÏyXžŠ•É ð5Èg!óUXÞù‹h^>³f ñ–·¼ÀΧÐÖv9™LÓTuL$ª¢··Ã0Xºt)Žã088F§ˆá?+râ±lNYаM3¼)‹0ðñC‡”¥·¼®a¡ ây‘5”زÔ:A þUßðÓið<¬bQÍO&+*ćÞQÙ,ʼ”‘ó!í’in6‹™Ë…âÒ—¿¼•¯|åvíZÁ /¸áy¨›L&Ctuuú»IDÐdxoYV…c؈ˆÎcà}̇ w¾ þN0O€ü,XõöçÓ3mèìT¿W&£OqìÑ XTcÛ^?n$\W]æýýª‰jšÐÞ®ºQ*¥>E8ÉdÔ:…‚jCooä’Lª6 QT”w"y^$òXÖð(šÑRäË2®«ögJ”ö[Vå±Aã×zLLLLÌôã\~Û Õ͈‰‰i€;øß7À›¾^'åWÕ`OÞo …¨Îe11ͦ¡·Ù•+W²råJúú¢\ô ´ºý5yS~sB¼!´»ÕEFz‹ËMœ©ˆ„±¨]vÁbx´‹Ø€}¢ FÔî­uŸö¼H(jòAÎ ö&aÅ¡qÚVÓÍØƒníïFUf=DL"TDm•܃"¨äˆ„Q<ѾË~ *•Zéß™7 smØyç§üôÎ4‚_ƒýFe4]¹ò¾?€iš¤ÓJPéêú:ƒƒ½<ôŠœÈçó8ŽC¡PùâA¤ÒZ©'¬#†ƒ:;9%0ûûÕ·­MYD˲p]—»v±¢§>õ©hÝtºò”‹ºDÝ ˆò‰åV_'ŸòâÎ_KewÝhž鴲̚& <8gGÿà¶t-]Š£›”ãð_|±¼Aß÷C±H?G’>Mj«Ø¶çyiÆ|ßSƒMRKl,8)©€ìO ø2¤·÷á ·¿™üé/&­Ç+A Ä ÉFçºJ´èêRB.§.MÓ¬ü C]¢½½ïK‡ªÌ @´¡XTû1DïV¦Y™bN¶åûêZËf#‡DÈ"gô¬j;’~up0|º»Õ± j~o¯:ÝÝê³³S—lVmO"¯Ê·|? ¦säŠD¬ÕBÒ+êóå>áºn˜®P¶ãy^E8™÷Ž˜˜˜˜©æ‰'a¾´³Õ͈‰‰i€\Ž$aÝ“ûé}ï)•3Óéaáñ–eaÛv˜Ú8&¦•4$¨¬_¿žõë×·º­ ±É·>Vé•0“ºš˜q¦ó1É{öTØÍõº+#!¯”ÊëißÓÔN7VïEZê_e³ðÉONÁAÎf½Vb÷)»YÁŠV7åøf<7ê)lC‡(ÊÅ$*r/Åê¥`}Õ3åO¯¼)–”!]´¦$©ÁŸ/À;M˜ýÆÀ)ÄŒ¹9ºàÞ…Aè½0áOÿôgüÉŸläG?úw@qóù~ …¦iVÔ‘ú aŽ¡ ¡Gpd³j \G†!ˆ^àC¢@Ê"ÄŠ{ïåì;ÙÿļÒÑÁ"]èÑDÛÙ¬²êŠ›{>¯¶%ó¥8D:­ö'"Ь#ÛÌU=-Är›ËEbŠÞ†²õxE¡ßþ6üéŸBg'oZ´ˆO­Yu%ßçô²@îkÏò½eËøÍ]w±öòË1DÌÉå P৯¾ÊŸ¼óÜ48HþþOÒé4ÿýúëùÒ¿ýÝÝÝA€ã8xžGø¾?¡—Žñ–óy°r`T×U¢ÚBæá;»‡øÁüCãnSŒº¤«/qr¹H¨8%iºÆÂX3+ärª{¸ní.^oûÒmz{+÷Y(¨[B±¨þéé»Êd\uÕ+üþïïcçÎytwÿŒW^YÎ?ÿóÙ|øÃ?Å÷_À0<^~ùsÀOøØÇ.gÕª'H§ï&“É`jŸúÐ6>ö±e\~ùÃààE,]ú\ÆÑ£¿eÅŠ{±,‹L&Cggg(<'“Éa⇠ý¼P(à8¦i’Íf1M3^EÔÖ ·J B¹GÈ<˲BÅöíÛéèè˜Ä«5&&&fjØÿó¹üÒ3[ÝŒ˜˜˜YpôôË*gÈ»›†§üŠi53.ßÂ>`vù¥<Ý«–Q}*„ ñ²nÔF)ëLWL¦&µ˜¦ïn`Y9oí{eïõˆ2 #Ùž$E…ïÓ pf×>¾súw¸ˆ‹ZÝœ˜‰Ðh:ݶ¬ßTxX€RB²¨é¢:ašJ…Dw«îs>djÜìÏsà)àì ŸNkõ;¶(ß$ƒ÷A×ÍÑF ÿò/§ð ï P€y«_²NÅ÷ýáuDÒiõ=‘ˆrÿèó%ò£·70¤Hƒ&˜JUŠ®[á ?gùr~÷»,–ä#•Ç‘J•‹w¤Ô¿êH˜ê° Ýš+ËV¯S«ººƒ¨ž.‘0bI÷ø|2fôul›óOú€ÍOw_ËOÿ—<öØc¼ûÁá‹_TÇ^üéW¿Ê½?ý)þÎï„)ÓÎûÜçX¼b·\{-×¼ø"×þÍßðå{î¡P(N§éïï¯ëÍÞ,LS{N¦T-–Ô‡ÁIÀ™o[Àƒï;8¥í™)èÁRh%ß{{#ñk¤qŒ–9oÒ:A’×Úó< ‹ÓN;túÛá<1àA0LèSQÞMgçaº<‰ÆøøÇoÄuwÏ«b[¹\Ïó¸õÖ?cÁ‚‚?çòË?Àïüΰn̘æÀU“È4M®¸â‘ÏÿÏKòüóV &)Ÿ}6O$E®¾úÓ¼òÊÍ,XðÇüüçK™5+Ï›ßü*>˜äŽ;yíµËxàßrë­?aëÖEìÛw ÷Ý÷ç¼ç=/1þ^xá,,ë0‹ÿ5ßÿþ›Ãnü®wÁ¥—îç¹ç^æ—¿\Æùç'Èdú¹çž{ðýïâû_`×®Cüýßÿ–K.9-¼•†T Ãàoþæn¾ýí¿¢··—¶¶¶°Ö“ôs×uÉf³á¹+j^ž¾ïÓÞÞN&“!‘HmmmtwwcÛ67ÞxcK®í˜˜˜˜‰rxÖ¬V7!&&¦A^ðásÁ7öî>SB”µwA˲0M3Sb¦cT6nÜÈÐзÜr 7näöÛo¯˜¿råÊ0=E«XnÁ †öÌÃü pãèëØDv¿Zv©ª9ÒËôI¦# ” ÒH†x)^­¬ïB‰1ʦë£2 ¥\ùÇè"ÊTnˈŔ±ò3æ?tV0c«b&“á7U‰TÉ (rã“ÈY7ÐÖõTŠÝ àT¥š9ØgÁYÀ£yþ²Õ'âÃ:Áû $®ƒÄBAkÉ’^xà ¸ç÷ûا™çû¡¡Îì ÀÿÿÀxÇ;0 ¼KOÅJ€ûY–|2KøCÞöå/óðÐn¹ˆý?üÝßñßþò/•å=†GÚÔ P(àº.¹–­…Ô§°$?§Šþì×6cÔOQð–¤ßËdÆŸ¢JD †½¤¶µµ‘ËåjÖã ‚€ÎÎÎЈ/µ‹<ÏÃ0 >ô¡!¶o9\W")tqÏ÷ýp= œ’ʲ>7lÉd’BÁeppß÷éììฅóÎ[M&3<‡™Šâ‰®aÕ £{’ëº$“ɰ]Åb‘l6 Žcpíµ`ÛŸÒ¶¹XÁïÿ¾ÚŽœž›n‚w¾ó~–/ßÁI'½ŽÝ»¯fÃ5¿ò.(ÿ˜Ï¶mk¸ï¾U<òÈQ¾ùÍÏóÒK²fÍiaʶtlÛÀ÷%Šç¾üå·Ý݃ÃnERÃÊ«QôO" õßmpp0œÿÄæMošK¤s¬#´@x¡V¢7 …¾ï‡_R×,›U!Ò¦i†‚«Ì“mù¾O:&‘H`Û6é²C‰eUе¦i†Ñd–e…b§D¥%‰0mªÜ?-Ë ÅãL&C¡PÀóŒ|’ûDõ¾Äàe”ý©$N‡Æ¶t:]1gÛ6®ëÒÝÝб¹\.¬ù–N§ÃTxòO„ FDÉçó‹Eòù|xìîî—“{§1'ûÁDÒúI»³Ù,¹\.sR©†aÐÕÕ(Qúç?ÿy+/“Ie²û§ë«G¶ú°bbfS1¶}6 ó×=Ékí5ŠÒ׆ï:11Ó€†•¾¾>6mÚÄÝwßÍÚµk+æ­\¹’ 6°xñb>÷¹Ïq÷Ýw¸­7²iÓ&Ö­[ÇÀÀ‹-âÎ;ïdÑ¢ElÚ´‰7²nÝ:¶lÙ† Æ\»å¼¶ìeŽ,\WµúôÆLgª_ýS({leøÛnAÆRßk!éìõ«™‘²d¤¾ L¸>œ½—9WÅ‚J JÉE«ˆÝ9AeQz^ä»’¦OÕY»#ÕüãÛ¿ÜÑê£0ÍîŸøàßÙûÀñ*Dz—žNiÙZ0.xê)vœ>ÎùçÓyè©9s°€äM7ê~*EYÔ=V/›P)¶ŒU1 ~üÊ+X—_>9'Ún$Þ±yFÑÉúAàº.Åb‘ööö°FQ:ëÉ=Ѳ,R©TèñK—.%•J…‘^‚´Ãq:;; ‚€þþ~²ÙliRí9-‚´mÛd2™0õ¡iš´··“Ëåp‡d2I&“ …¹_[–E».÷Ýw_«/¹I¡ýÓ²`é^Àz1Έ3¦jl ð‹×ý‚=Ë+E™ê‘žëºbvLÌ´ Ô·ÞzkéÚk¯uZ{{{iË–-u·ó›ßü¦tÎ9çT,óž÷¼§”ÏçÃõ~øáR©T*mÙ²¥tÎ9ç”~ó›ßŒØ¶ê6¬N•Jkî*Q*•Š·—Jr€v©TJ•J¥bùo™VläLCÌV7`C©TJ”ÔõÑ_þž+ÏË”ÿQ,• T*K¥t:^·Ç*£õÍRiìýóá‡.Ýzë­á÷õÅRéÛŽ–ŠÅcµ×5ÞÞÞRwwwÅ´D"QÊår¥b±X2 £b^*•*år¹Šiƒƒƒ¥þþþVÊØ™Üœ‡˜ò¿\IuÊTy\©T,E7ôÁRÔY»ËÿÊT?#ŽEšÑ?GïÇ)%‰R*•*9ŽS2 £”J¥J¶m— Ã(†Q2M³ÔÝÝöÿ\.WÊårá½À¶íRoooɲ¬’iš¥ÞÞÞÒ`ùI$%Óþ¶™J¥J™L&|VUÏ3 £â¾288Xr§T,K–e•ŠÅbx2Ͳ¬ð~•ËåJƒƒƒ%Û¶Ãýô÷÷—€R*•* –LÓ Û&Ç#Ó‹Åb)•J•,˪h£Œ©«±m»”H$j¾›8ŽSêíí­¹ŽœC9Fù´,«æxĶíð|Wcšf¸ Ã0jžçþþþÒ™gžÙôk®Ù4kl›-–J‹ƒM{ß,–¢ñjLL5­zFL6S5¶-•J¥KzK¥]ú£Òµì*U§S•=Mžw©TÜcÆÇ­·Þ:écÛq»­_¿ž¡¡¡Ši+W®dïÞ½u× £££"ÊåŠ+®`ïÞ½ôôô°xñâ0”líÚµ¬]»–žžžñ«gL05Õ4šæ*fì(Ïö$ÊùÝ"r‚÷¨LöW.´={ì{ØŽÔ7IéŸ{|8uÑKM- ¦§&$d^¼æôZAÔÌ?Uˆ‡x©º²ºººèîîÆ÷}²ÙlèA(u@è!(iVººº*¼ö$-ŠîÍW(ÈçótwwWx‹wžŽL S •½ý‚  ««‹^-•‘¤7c’ô£žW¹‘Õ JH¢"Vl¢z+²É.TG•j9¢N:µ&šÊTôÏrt*¤ õóû \îzê«Üýl¢H½ ¹·\pÊ)ÌÙ´ û«_ ûm˜£ À4é.•¸zölî1 ® O`>JÍÖµÊÎì?w?O¼ôïå½­:Ý“ÂTm“É‘k¤XV@{{ç°ûuõý^hE*ž˜æ3R]#éÆ Åò¥/mÖŽ¾Â4fJŸ“„뺸®ÖõÈ ©Á‘ÏçÃôTzI"‘£A¤¾¦ºÊf³ô÷÷WŒËd_À°û„DfT#5=jeUÜW$‚DR VG{HÔKõ=JŸ.Qr’æE¦É>½M™L¦b›õê€É8·Ýõ^DïrŒò9Ú3»Ö½¸:ÝàHËÊq:tˆcföÏSöïoõáÅÄÓL¥Ýö—왳‡“O>9š5S0§R©Ð^3hHPY¼xñ0¡¤:OÞÐÐ}}#çÚíèè¨È½744ÄæÍ›¹þúëéëë¶ÍÅ‹‡9ûê±}ûv®»î:î¸C¥tyÁ„esжõU8cɨÇÖÚä1Ó©‘mãO¾ÛÐoÂöeÏ1ø¯/=6©oã¾aÃN:ÞpF€ižÛ´ã”&zh>Ÿ_î|ß Bêß%@&“ _dÅ 5žºP#ù˜ååPßžž Aò3KÞvyi”|Ìííí‹Åp}H’É$–e‘Ëå*Ò2èù­%w³þâéy^Eî|9ò’(i$§s.—#NcÛ6©T*4ÌJè­¤Vôù|¾æKbWWWXôSòV×ͽ rE%PÖy±ŒPs¨¬ÇByž¯®Ù7²{÷î¦]oSE3úçîÝ»¹îºë¸âŠ+*¿åóh–ÏuøÙ«¯òò—¿ÌÍË–1ÿãÇxãyãöíØò»Õé#6P*ÿ=Ru)ƒœ"ÌÚFõóçQ‚KU£EJð¤ËÓDŒu©Èe`h˃ºD2¨Ë&¯}O]>©ò6d\P@itRš¡—èÒÓÅáE¨ÑG_xåiH·=öXø÷dнbX“´+'÷÷³°zzÂÜò`hV×ÿsùåÜðíoóí¶6þÔ N:­rjX–²ò[–Tùn˜M›6±iÓ&Î9çœI;¾VÑì±­dc“ôÕA¦çšh-“˜€ÿú_¯cûöí|àÿO«›2!¦bl;xžÖÇñ§çya*©d2:ʘ¦I2™–îDR¡ˆ^vˆQ«V‘Œ«÷µ–‡Jñ šzëu—½_éËIM‘zçRŽm,ç,è)ÆÆÂX÷SkÛ^xá…cÞÖt£YcÛí=_eöekhfÊÂØœS‹xlÛØØvÆ •e$ŽÂ_z#‡O2¢LÞ]]5=DZ‘f6ff°qãFî»ï¾šµº&BCOš+®¸‚7²yóf®¸âŠšËäóy-ZÔp7oÞÌÆéèè`ýúõlܸqØ27ZµjU(¦¬öÍ=ÀÊWN…Ú‚ÏÀ|TÁúø3¦9*óþgˆ"T ¢Ú[ 8ñÚ³8sõyzÁ ̺ôÃú&P3ò¬‘þùþ÷¿?|áìû1œ÷Ô‹@óñЂ  X,†Âƒx›É‹j¡PÌ…B!ô¢ ‚€D"Š ò"'9äõ‡¹xøe2–.]J˜«Ù¶í0ç|¡P¨Td_Ò&Çq‚ ¢ð¯`Ûö0¯7ñHÌçó¸Z‘jy‰Ô=Å“C^šåÅV ¬²®´ÛqœpÅb1\?•J ȤÓiR©T˜³[^0‰D-#/Ÿ@xl’·ZD˜š/¦ÝðÊ_a>ó#K´Edý.PYÀ>‡²vç`í¼µÜqÇ\wÝuM»ÞZÁdõÏeË–U<;C|p·)AÅÞ»m§?ðó¹±\…&yµ'ˆÄ 1•dˆ¢^$²E‚‘¨ìŽD±¤¨Œ@I£¢^r(a¤H«“¡@%ÎäËëµeÜò~DñˆÄ“€HôÉjó¨Ë¶ -g=O"1&(Ú/½¬áÓ ÿxO¨)ZL<èJ îR@W':;;CÁ´é³–ï+ñDî©tvF¢Z>¯Â(FyáY¿~=+W®¤§§g‚G5½hÆØÖuU¬ew, ¡(-Ï„˜˜‰rÇwÔ¼veš5¶/…B!¬!"QÉQìyétº¢Ð»ŒÃÇ©)LX–:ÀT#u;j1V#¿î¸Ó(âäSk‘¶#uZ]GÆÕc¼“ó>–s 6zô¨–±¬§³vm<¶‰eË–q~ǧøâWŸÄxë+MkïØɘãxl;2Õv[aöjXóã5l? —¾¤¢å5ÇêZ11ce²œ`ªiHPY¹r%×_=7Üp×_}x³€¨`ý¦M›¸í¶ÛFÝÖÐÐ7ÜpÜrË-¡³xñâaË Tª— °» ?ÿ'<ÞTžè£\`Ï.¤òIè¡,býj¹&‘u'KäÒZ=~’±h,˜Îä5Å!V’Tf2€¡²Õ¬ï?ÏæÜe¿hu³'L½¾ “Ó?lƒgyÀe“Ò^×uÃôU‚^dR"C‚ ¨(4)ž¼’îDÒjÉüT* .ò‚+ó%F_F^n¥@šˆù‘ËåB‘GÖ“È]D0 ƒÎÎÎбQ‰Ä¨F4ý¥O^†EÒ_<»»»Ãs£/ïº.Éd²BP‘¡ú4ýÅ7›Í†iÖ䜉ç¥x[J¡Ô|>FIDM>Ÿ'“ɽ7K÷Ç»+CWîÏ)¡’Ë©@”gjÐìþâÃì‡-¸¸÷ӟ濜{®ĦÓÊpÞHÞ˜qR`CO!V«W˜DàõEddƒ5–±µe«ÛãE²äÞ–jS•Jw&ÏŒ"QÄžþ, J#éO¯]Ëà[Ë?Å/ËÓd(’.o¯~’‘I$a:¨B¡Nc—nkk •‡ç¦\è× ‚J1ÓT•¬“I•ÛËq”W™ã(aå8¡™c[è­aÊ}Ò4Í𷉉©dÊž ÷]q0‘q¢¤Êª£LªÇeõRøé2jG€ F`àXNžéiø“‡À øÀ ¨Tú«sdB8¢k$d9¡c¼ûÑÏ[#Lå}s¬û)ÙL¡ýskù”Åžì11£ÙvÛp?s`뢭pΘ5ŸçöÛo¯˜·råJî¸ãކ¢S®½öZÖ­[7L\»v-›6mª˜¶wïÞ†ÔÎ ^ãµ…Ì2fEÓ’À]Àà[Àœ'7R™{_rv$‰ÜGm¢Á¥äûèFY7 Ê×ï TE‘~/öÙfÌ´GRË"¨ ŸEXáÁ‹Ŏ?juk'N½¾ “Ó?—þ9ìw¾ ü头WŒH‚îá'b‰išÃÔ’{³Úø/ùª«½|EPœÕâ,^ÝÅb1¬"‘0zDŠã8ዤ¼PU§k5øÏf³#æmžŒó&/·µæÕ²,2™Ì°¼Ø D¬ÁÁáæi9‡Žã„Æ>©½"é’Éd˜_[÷Ö”È=}˜ˆ/Ã0P÷k )H… Ì òÍîŸ:¿ÿWPúO˜àûŸx‚ŸmÛÆÍË—«î4ó€AE";GB@¥>I>Ÿ'™Lªˆ`ýÒ‹êÑ…ª;åyD)P³åy&`ƒÍŸþìOÕ²í¨ˆ8BäVöT8Å?ë>‹O}óSÊ×É ‰ÔsbZ¨÷cq>¤<Ô%¤_nGRÍ÷®ÀÄäÜÓÏUË‹H“)ÿ­«,çÏ\õfUŸrÞÎyjžž«Ó$ %•‚jZ¦³¿qväT#Ç#ó«ÞÙ×~L3úåóÖMŽš(Ÿs0'ôÞðõlLyIÈØS<'äWkÀ ðzöþ€¨œÐ^ž^>g«ç­žœ ³Å4£î à¤e/7­Í±Ls¼Ðt»m™eo€5î¶_ÿ1ø×o©è”‚h¡3SrÉ믿žë¯¿¾"ŒmñâÅ «‘›6mbhhˆ+®¸¢b+W®¤££#,rÔÑÑA__\yå•c: ³ÿ^'ž¨M,Û- €wËÊMU5jpä r‚2ˆ‚hÔV^NQ’°]òDA$¢äQ4‘E¥@¥X“eFySÏDä=Gç#|ýðáV7mÂŒÔ7'«>›ö Κp[=ÏÃ0 ²Ù,ù|žRIUi¨OlÛV<jçkq¥ž×ŸìWÄýÞÝÝ]‘7ZOá5V2SàÑíû~E]—F0M“l6;¬ø§ïûuÅÙžjB–£‚ü6‰DÇqÂÈ)šÝÕÕ¦)’¶Jtã8êÞ.…)ô—ÖêœPÇ8SÑ?÷%Xú>Șðm»Ùäû¼cÞ<æßu—²êN3?ÝVÔÌ–‰ý¦Y¾¬J€9ûûØÖ[cxÔ‹¯è‡6Q29ö."[Ø“j™Û«óë‹O<¥¥¦TØ>©ÝTg{QKZŠDÃu+ÅÃP/JÉ$Üxc“ÎæÔÒì±mµƒrgg'Àp1EƧbhmäqâEúùåO)>dr=Ì«$×|ŠA×ay—ÑSòJšG—Ê‹\Ïÿ§‡›Úz~Õöå’"R)¥s¥µy’÷OÿRHÉ©s.Çz.Û©|vÖCO1+ãEÁqßø8–aE¿“ ð©Ÿâ’]—D…½ÒDéNE¬°Qã òµþï³ÿ_üµÚ¸>ô­ç£cA† Ûߺ¥ÎR5Mî¢ÞëžåkÍ4M%t”#`B‘&Yþ.†ÿò5~þòóÉá¼/Ÿw”ÛcDmóaÊwVýã*Ú?Û÷DÓñPGu±³N8ûì³éîíæ…/¾ÀêY«£ó$’;ÓG×,Û´Œ[.¸Eµ]AKqÊýæâÇ.æ…Ã/Dç']>WòpN ìr.»áOþc3ˆ–[€R2ÀctàÊ;®äJ®TëôÝßM¸øº‹'ímÍêŸÛ“No^QúØ…!æx`*ì¶ ^ æµdûi»áŰ{·Š~‚ ®B¡€mÛq4vÌ´c\ÕºÆ[Èe``€ay?¯¿þz6lØÀ† ¸á†X·n[¶laÆ ,Z´hLûxös0øPíbó`­/¿³èÉØåeB,µVD[&Eí(yª¶£ÚD8Ñ XHÄÉjëu¥­‘¼SUºŸäSŽ8*é*bÇsèP«›7aFë›À„ûçIÏÂÎswN¸­ét:ôð“h×u‡y-èû‰¢§ïªf2CʧÂÓX¢Mô”?P«À<(q¤–LjDU‹0@M1Ç0 2™L¸Œü~†aÐÞÞ¦“mŽã€¡R¸õ÷ö¯i£<ú.hú)m:SÑ?ÈƒÕ ó¿S~=ú(š&™fEÛéÆT€ËÕÚlߨ¹Ë_á™ýgpôâSjΗ¡î¯‘&ÊÒ"A´I"gf±é6,é{‰º" ë}[ 7"{žGgg'Ï,ZÄiÕËçrÐÕŲ{î×½®Ég´ù4sl뺕¦Ôý ŸEbPO–㟺0l”QQnÃbàOjÄëÝ Ò³Z~~OÛ~gùï¢ö·Uþ— ä‚”{³<>ŹH¶«{Í‹áS.jWD¯¡A¼·EX±µýRž.B‹xÄ;D"H;•†l'­µÁ&0dü-ÎQú{ƒ8Du•×s´}Š—¿U’ãÕyGs™+o·³¼]éÀ‰ò>zËŸÒ¾¼¶O‘$š@~ù]í7–èqðòP7‰ò9ÞsãNåÔ†®ÓéÊ”=;ëàû>Éd²b\„B¥Q0ø§7ÿSô{jCÌ n¿€Îyó3ç« úp¶z8V¾ÅÞ»â^ÎpÎS³f–+ÿ¬Ê&â\5åæñµ/rÙ·. èZÔßU5‘ÄNÛ¼ò™W† ²µÄSæž=—ÄE æÜ<'º¿ToExë—ßJzS30ᯩÌÓ¬#÷M–ül WÝ}U$ØÈ¶k99–_ü–}eçì;~H¥8ùè÷Q€Î»ó<>ùÆOV.'Ž™^ù7•‡wNµ¥íÎ6æ?9î«<ÿXP° ¼Ÿ÷é·žn4«.6áÕ{þxg«1&æ˜e*ì¶?ðápÏ~µöWÌ^¿^ÕPI$*Éb§ñ‹™–”¦¿ùÍoJ?üpé7¿ùMCË_{íµáßÅR©¥¥RÉ–ïåyò}ÚÑ_*•œR©”)•J¹R©d–J¥ÁR©”*ÿ“ïfù ºK¥R¢üÝ,¯“+ÏsÊi–·—(ÏKiÿô“Õ_Þ^±<¯_[®¿¼~y¾Þ¦Þò¼Tyûú±ÈÉî-ÿ)ÿÒæËÓµiÓœTùPª§•J¥Ò 7|«ôð÷º‰SÂXúçÃ?\ºõÖ[Ãï‹.,•lÛžpúûûK™L¦dÛv)•J•º»»K¹\®ÔÛÛ;ám„ã8MßÇTašf©»»{ÂÛ,õ÷×ïÄ–eMx¹\®”J¥Jƒƒƒ¥ÞÞÞR.— ÷Y,KÅb±æ:ª¥Òç?ðù&ÅéÇXú§þì É•J©«K¥5åSšJ¥J™L¦”ÉdFÝ^+é/U>ŠŽe.È{¥w^»«tÊßloøØR4”pJê,ϧÞò?&˜¥ÆÇBŽãTÜ'z{{K¦iës™L¦488X1M®¢a”J¶]úëÓN«Üøà`iÏÅW<#f2ãÛ¦R¥RN»¸ÇQç_.z#Êß:Ý%µœŒíä»>æÆúhë¯ú[¶)ŸtÈœ¶n5ƒ¥hì)cY§{SUÛ1ª¦†´³Öcp°¤:KbŒç¤TÞ¦QnÓXÏé`ƒËë´»Tnw®¤¬ò¾0Úv¥ÍUò[o½5ÛÖ zl[‹þþþÒs÷_–ï.E·«Ò`©´í¯·…ûï.©îS¬Ú‡ÜÖr¥Réo¼¡Ò7ÿhKøsÖjOIÛOªT*å¾S*uÿ…ê’2]ïÆ²Þï”J™çTû{Z*¿­¦Ës=SngÍ1Ü e¬cÛõÅRéô?øLSÛ4ñ·Ù˜™J#ψ™ÂDì¶¥’ºï]T,•^ÿáWÕ;C©vß[Oõ»FLÌXiÆØv\*ÍDÂ<ÇËi¿Êë~¹ .X1)푺@Ý49RÛ²¬pÙÑŠD‡˜D¡Ø¥¢Wá•OÝIj¸ˆGY9Zæñ¡ÇyuÑ«´¹mÌùèçÌ瘿k>{~½‡¿üÊ_òZÛk9ƒ#r„¾oöqáMRZR⡹ÑñH³/µÁ€Wßò*¾åQ.ý_—Fyj;‰<è$‚‰òø¤ty™ Õ[¯W+Ų¬ð8DÔÑ3™LbF8Ï0 f}ò“¼»|œ®ëVŒžyæq#¨ŒÓT‚Šçyüð½?ä=O¤ Æï•1ÕŒGÌ‘ÔC1“‚ïûê9Äê®fõ]«áI¸øÄ‹yÓÁ?€Û|#ªË‰Ñ~Ùç>Ǧyóø|ù»”ñß4éþº[°zu˜ÍOJ›èD)‹)/—üã?fÑ+¨dþÓÛ%õ@ …Dä/×KT^¶Qý$ô¶·½"Ãõ@ÉX};sÎkÿˆ •™ê ʔӎ/¼ýüUì°ÿ–Öju I‹)þŒÝ4öŠ)B’83ˆ¥g—ßÑÔö%™ÿä8$+¢~ºxS`¸¡dxÜöÆ76ÐÒã“=>pâ„73<ãÁ‰÷œ×Ö_FwZ‰™nÌ8AeÕ[20GÕ´˜H·K1Hîp×uCÀmÛäóy,Ë"‚0ç¸xiú~”Ý]÷æq¡P§Ial1¼5kHQæt:M?A„Å·«}×uÉÝ™cË+[¸`Ý\m^îÏ4L,GJ‰…BÏóX~Õr–³<ô7M“Ýú!@å3L&“¬?u=KÿïR®I]£¢ìTTÀ³JWÊY$ü€ew.ãÕ}•EÆ¢HDé'•—]t†nbQ×¢J·¨_m·nÕÜæpá…O ¦n‡Ç [Ÿ„CûO€…ã[_úI>ŸÇ0Œ8‡æqNõ½4N‡õZ,Ë¢³³³æ½3fÊ.­'ê…~Ç÷¾Çëû[V|ò“­nÙ„gâh^MétšT*.—ÏçÉçó˵côë-™L’H$ˆ) ŒöaDžýRsÄ÷ýpÜ ¢Coo/d2™p<°û‘_qÂ)ïç´ßþ–®®›°mÛ¶iooÇ4MLÓ ŸïrÝë/…l–”eÑ©#ªÇ’ò½«ü™¥²F¶”™(jË똦ÖÚRŽãÐÖÖ³'Rë ÔX#fld³à8°ë®]¬xÛ ¬\ü싉™v”-þŸùƒÏð½ùß C³„øó¹8k6œEmˆá\÷¥“²F=ån)—ò@R’H^•ª‘ eô¯]ù®=jC§^[• GôŠ7š? ‰^jí§Þ“Y/aT¯diõ>:æÌÁM$ö»“`4ù=E¢X„ZÇ_mƒ×ÚêsZ½_[[ߨ±Ž¬÷“µkÇÐâã‹·¦à—Ý['gcÓΑ3&f&±Ó…Sïcéc1x饰`¸M-™LN8«FLL³˜Q‚ÊÖ²ûÌÒ¥K‡ÍíY…BÛ¶Éf³ð¦i’N§CÀ–âHE­X¯mÛ¡áW„1¬†A*• ‹ŠŠg§ì[RA@>Ÿˆ _‹·©çy‹Å ƒ†´·â‘^(ÈçótwwWI¬V~ÅÃTŒ"Žã„étr¹\Xܶíðüü,ý³P(òMÛ²Á&g$² ›Íâº.ÿtÆ?ñbß‹|ù‹_&•JaZ&ímí‹EÕžnxKÛ[èïí' À° 5’O¡ÜŠ¤Ø¦z{èFÍïeJE•§Ÿ^@GÇÔíïXcß68üò c^¯P(àºnhèŒC=cª±, Çq*Šeçr9 …étšK/½´ÕM¾ÙecºßŒ'ñÁx‚ºä>2Öã©7}ßë^7Æ­?Üý™#¬yëVÐo¢IÔÐ! !K”?õÔ–ÿFt#vPÞ)ò]:íx~ø˜˜ão‡úÏü‹.âs<ÐêVÕEþgq0ç"Š(òŒÏçóáz"€èÏjNLÓ ä.)ºtçÃ0*®=jÆšöÓ0 \×eýK»™5÷wè_Ú†S¾_J;Ÿ˜¦zmééĪC¶eYVØGD8’µl”±L²n.þÑxþ³Ÿ¥ïä“9ˆz¤š¦‰çycýw¨EhYV(^9ŽÃ²{îaÙ¡CS{ácȰk×®]¼éº7Õ]NrëCdÒê2ÿ½^A€Bå‰2‰éÛƒ|µ‘_þΡ<ãõ:½åu“DKúÃ0©ù C¸jôE#ž/¨¨ÓPkÒv=å´O·|Î$µ’#&Qz}{•bœ_*¥Î„¯í[>e±ã‰±v$¯ù$•Yp¥Du] ÊÇ¢×ÄvÉ9É”÷%iäZZµj=JLƒ$À½ÕãÊOþ-ùõj’T‘ûÞÁƒ,<ùä)kJ³m¸ÓÕaßΛ7mÛ7™Çyø”SZÝŒiMç e'>ýÆ.tÝ€%û…Ü|¥N­¤sˆ¤ wËË~•JUZ¯ Q=X±GÈÍ"¡E¼^y¾ Oe›ÕýÂÖsåé꺮êÇBNÌ4'8x°ì½ÉÀg [F²òÄ¢JÌteF * ¸ðì9ü†WÃix©È‹¿ˆb|Ñ=He½Èr½hÛ¶‡c®68çÈž†SuIqcñ¢1c!‘H„ÂuLƒà_‚sß§¯öÍ7·ºE!žçU83Hô¦I)"zš+©»$¬’¦ÇalQ6b[+¢~«Fj3Èyl$ý¤*ý¦"gjýN%v=ý®‘ Šdñ¬º|8ôº| Ÿ>t/ÿòð Ìþw5YwKû½uëZÝÊã›±Gµ«¼÷Ö[áŽ;ZÝŒéMõP°‰lQZr õà›ŸRYýÑ‹ Ë´¿ëÝ´õ¯ä—“›²„GŠ'ƒÉðü«"òˆÒ-ùt¹å}Kˆ+Ymßâ û±‰ì"Ò½øOJÛ¯•Þ$•õy%¯¢ˆXi­rþÓÚy–}H(wõ¶EÄ!ˇU[VÑwV1 0Îÿs(=w>’6î”ôÂq½Ü˜éÌŒTömƒY'aáÂÅá´Ñ^€ÚÛÛ1 £"ï¹ÿ…ZÆ•É&•JÑÖÖÖTƒÍT ‹EÅaÚñü2™Lh,IŒ.â=+©Ð$g½ïû‹EUôö}³Ø÷Í}¬0VDJ±.¸TºÊ?½‹¸â 9¢ GªÕ scÆÄÓ.ÌÞ3x©ö¾é4Ø6Ï>ú(m³f©Ôqe/t«Ú0Ðêô_¾¯*ËgÌ´!RÆCo€[-Ȧ½QšIWWWXÄ\ê9ŽFUè‘‘ztŠ‚8èÏ›é|md2¾÷Æ72÷·¿eqƒâs£b³woo/Éd2|6KdŒž¦+Nã8Žª“N‡)BŽº€O,ZÄù÷ÜC§aT”K3LsDC°üÅûÆövæÞsO«Oû´%À<ŽþýQNûãÓ(9»êöþòôzõÈÅžPïuÔ *®l3¶2t6Ã#Jª ú²Íf“A C“ñÚmÕÕéšÆ²N#Ë[Uë€úk¥![Oõ´±´-f °á²£äæ-áÛG†ø½®q Œ™2ßDÌL!Mô€4ˆ²UèÑúMs*ÒsÉ Yœú«ž H–¥_<&,¢‡wõ±Pc»’ÓUÄ={‡¤NO…fv£ÞI"DæYå¶×;gâùÑ…ê”ÒÉW ‘·…xpäQ!¦©ò?ñ(‰¶ÏNmY]D’el­íDƒ·Ü&]䆂6OÈ–Û&çí¼$ÊÇX,/gÁÁ3Žûò8î˜ Ûþ+ìL?†Q3°*“ÉLëw·˜˜%¨<ø}8åÚg˜3»¶GUu•TV OË©Æ0 z{{gÄ #—Ë…ÂG2™ £nêÝ …BM!IÖs]—d2Iÿ°¼÷òû¹)—uÞ:?šóGc¹ê]¶ºS)sÆI!b¦’¶ù œðãrÃÇ>ÖêæÄÄÄçxˆ®v-OcL}ÆrÙµ“OÖÐ?]õ½Ú$8‘KÇ)ýÞ!xuÞy‰DÃéâcbZÅŒTöî…†^h(¥å?~á \øÂ |ë’K˜[í ZÎïM&£ ––y‹ëºPˆ¦ ÕÆ¿lVe9™/žæ¾¯¦U‹ âq/ËZV¥a´\s%lï+£¨Ðâ4D¶m‡yÒG»Ú¶=â2ºAG¼“mÛ¦P(ÉdBC[Ê_Ž8ò<Çÿ¿ÇñWéÁ’É$ž;ÀÇÖ}Œt»*nex5žo؉VL”w‚ž#T"U²°êÕU%®¡2Á¢çžS×¥ë*£}•7y¸®[·¾#‰žrýØvíåÒé¨ÿT÷YËRíik«@õ)ÛŽD êmë߫ۜÉD‚@õõ­··ÏSû­—þOÖéîV÷ êy#'i‹ë*Ä4£óRk=Û†rÝŠaçMÄ©|^ TÙ¬ú¬nw(QÆqÔùM&£{šG9Ýž‰ZR@Àq¢e§Cª·Ê??ó€Wö35É0¤×ÈÂ"ê]]]tww‡BJ­çAÝû ò,Ö~ðƒœñýï·´ét:¬M#HaHIrV4 ‚ Àô<úËËû¨Gèš¡!>ÑÙÉG·láë7Ý„U_3™ wÝu—_~yKs:cÛðË#/òÂ_^ÇmĶ¡˜˜iÇaø?GrF_Æ5×´º5111Àv²ï­ûXÄ¢¦íÛø&b¦ VÕgÌ”qd¬ž?€•ÏÃ7›£9˜Q‚Ê’e`îxùÈø_ÿ n¿Œa(ƒœnäëìäÿÙ²…Þ%KxþŒ3†GNˆ!´³S}ãNuÊ˪4 V“Ï+£ ïGÆGA<Í]W»»+ …£ye˺…Âp1% ½]í/"¥2'ûrLúþÖè¥:T êZ.Z‰%龪1M“ÞÞ^ºººBA,N‡NÉd’b±ˆã8 –^vÙyó°€û~òî¼ðB¾ñøã¤/»ŒÙÿãðÜ#´ô8§3^<÷ó¸æÐ$‰)zm.˪¼ÆF§ºÆè×¥žs¼mÌç£gËXî²®ž~3‘¨Ü†çE5ÁªÛ©Ÿ¡ú00@OOOÍy#ñ'|ÿžX²r‰ &X¾<4Ñ#:>ò‘ ƒ|C4ó%C<ö;;+_Äš…xÜtü‰„2VÖ{1¶íÚ‚Œ¼¤ÊKa:­„—B¡ò…]Ω³ÔUÐ)ÔºR„;™Œþ†°Ö„ Û¶ÄÛ=™„ÎNþùãÇ({Cg2ÎÞ¶+gÏæìmÛÈd2äóùÐC:•J…©Êòù<]]] ‚ê¶i§å༃œ´oÆh“uû&Œ¿˜;ú2"vÅÖ)`ºžãjca d uïqWOÉX½~¡ÀŸÿèG­>ªI¥ý–_ |ÇïðãW^™”vf³Ù00‘HP,ÉårA 6q_¯ALÍ8`FÕ Ã »»[ÕT)ÿ†ÙrÔ["‘£N‰7Ì›GØùásÏÅô}úÖ·è_p¬\ÙêCT&sl{Êᬞ‡F«º®kåójL•NŸßÞ®i¤ŽV­ñ–D=wvV޵ rÄikSÿ$‚[§­MÙÚÚ¢_úúííjÞÒ¥jýjñ"ŸWˈ°PÝ9¾dRµ%™ÞFA–ªŸ "J¤ÓêŸ>.•úcú¿ê6ú¾:‰b¯N»™LFG²Zç¹­-Šø®Þ¿ÔnÓ·)çTÆÓÕmÊç£ß§ÚIËó¢ñs:c!›~›ês:ƒ˜ìgçS¿…“—èüá[û,ӯנ†ß¼ç ¿ŽÇ‚8¾éõùjíCjÖjÃhÏ´Z}­Þ~ª FˆÐû´ïGý¬ÈñÕ:~yf×j›¾^­ùrnå³Ööõó?ƒ™Ìþ¹k×.J•šÚ^©—EE«x([<åïnùÓG•èHkÓ]mÖöb*ŠÙÇbJM&Ûn+<¹ÞpÒSìX¾|ؼ â÷Ęc‚–Y%½Ï† Âi›6mbãÆ¬[·Ž-[¶°aÃÖ¯_ßÐööýfŸs„ Œ¸\¡PÀ²¬±yU{‘5 ËR/B½MŽ7¬WØ»V{Æ‹ñ‚áQ.‚iFé}j‘H¨<Ä õ²'^‹’έ­-qdYÓTó ƒ«Òi8ÿ|U‡%ÆZ¼y„w?û,/~âôöö*ïÚ Àìêbźu€2ðî¼ó¸ûᇱ,«nZ²'.}‚ûšV<ÕÔê›0þéÙ{˜534âbÇ{ªŸ˜q"éÚjQ(pßpq«Û8‰Lzÿ0áž‚wÎ¥Bð/’*N‡Q€B÷dEGÍdjyÏO1¦i64N²,+SÕº‡;(C‚ üóW¿JÛâÅJpþúñÇùÏ:…(U&sl»{>~ö'À{£‰A  êz4¯DA¸îð:` ®¥ÑÆ•£EæJáHèã¹j1IJFoÃhQÝ2ßuÕøo˜£‹=z¿‘í‹h£íMsô4£‡Ñr}ËökERÊþ%½¥Œgs¹‘#„ôã®%ÈJ8Áó†G‚Êy™ÁÆ‹É~v¼§š¯2þÛ&£q‘Pf•QÄòÞ#QMúu#²^2©~kýw¬X«Ó`‹ãšD(9Ne?ÁNú[6«®IÙ‡Ô»«®Z]sTï¯ÕÑȲ}y?• Þ‹u§™êûD6 %Òôþ "…ô‹L¦rß"‚ʹÑû¦ï«ó§§÷®¾Çˆ€)û×Ï.„H4[õ¹•Ôݵ¶/msõwuúîÄdöÏ3œÁšKÖ4¿Í¨±M'J ±Q ('’$•u×ÛÊËD‹ È •µPžŸ)ÿ @‰1Q&r¯¼éPaP¢ |ßöáûþ°éz”ºçy˜¦Yakñ}ÏóÂTàR3WGÖó}Ã0ÂÔ³’ÚÝ0ŒŠýêµZeþ½wÝËÇ?þq^\õ"fù̺®‹ëº$ òù<©T*¬ñ˜Ïç±, ×uI¥RaJc‰À¿ë®»fœ0Ùv[aõoƒ¿eÕyÃ#±«ßcb¦+S.¨lÚ´‰žž6oÞÌõ×__1oãÆÜvÛmtttÐ××Ç5×\CGG+ð`\xœþ‡Xþbýeººº°m{ì¡Ù†1úËæd §Ï9Ö‘s<‘ófšj}Ù–^F¢áÕ.=Í‚þ"© dMÀ”m‰g¦ã°Ü4Éf³¤R)žûÌgøÝ^~ñE¸ë®pÝd2¦{ú§9õÌS[}Æ'ÌH}&Ð?}ü¸öðáš³óù<¾ïÇ)b&Ÿîn¶]w]«[1)4­äaO À„«=Ï#™L†^E¹\î¸($ߦ 2–‘ñ^Ô˾ñц/¢žçqÊáÃtÔðJ;iÆØvëƒ%λºìe«G-T§š5ÍÑň©¦™m™Œ¾ÑêñöH$â,¤GÆ7Úq˜ªY>ƒiÖ³óoWvìçõ¯ÓÈ 1@„‡Tª²äóꤻ»v]β3X(ªé¤Ԛӗ­¾VFùl[­WïY=šPiY£§‘‡8IK'≠ëK Wý=o´mË{ˆ6cIs¹Hd¬ 2ÚñÉù•”ƒ:£åÿíÜŠÀ:ZŠñc˜fôÏGLIñ J§]\ÉiKàƒ*¿Jy\—¤mÓŽjr8tèŸÚ±ƒŸŸx"—/[Æ óæñÊŽ\¾t)§ìÞÍesçÒ]*±téRì àÃ`áæÍ¼õ­o…Bƒóæñè?ȹsyû¿ü s÷wyrþ| ×eï©§²àïÀxàöž}6svìàÜ'ž`O9Uþ¯n¼‘wûÛl~æòmm|úíoçË>H"“!‘Hðý矧½­þçÿ䢛nbî÷¿Ï›-bÓêÕœ{î¹Ì}ì1îZ·ŽmÛ¶qÙóÏÓwàמu¸.»V¬àËwÞÉš5k˜Û×ÇÁµkxËK/±«ìи.ËçÌ¢HvÉR(ز|9O|÷»üí‡?Ìÿ¾ÿ~ÖéKÌ* +‚뺼2gëV¬Àu]|ßÇu]Çág/¾ÈIçœÃÏÃqætÌa뢭¤“i2™ Éd’‚ë²uÑ¢P̱FO]l–íEÕö=ñì³Y¸paó/¾)¢Yv[aEzþëC¼ï¯þŠÕUó╘c…)TÖ­[ÇÊ•+‡…†õôô°xñb:::X»v-k×®¥§§§!µsßO`Çsy÷á‡èùÄ'j.ã8étZE*Œ•©èÐ3t°4!ª«Z©Ê&òÛÈ€¾«+p,ß'›Í©ÿwÿþï3ï?`ÿw¿ËÞOäÈÊ•AÀÀ°òOþ>ùÉVŸ¥I¡^ß„‰õÏ`6Ùw×Îû%Qcq„JLL}šÕ?‚C`¾þäOÞÉ¥—޽¦Óé0e_ooo\%¦1›IÚÍB¡€çyüÝßýûØÇZݼI¡cÛ’—Ï>yˆ÷ö¶¼¶NÌ1š8¦ašõì|v.Ìšó=ÚÛ/Š&Š1¾ºîŽìkõa] ­W×r4QDÏs· cïaY²µ¨ñÙ¼H+—m$®Î¾<Ó “HÀ‰uÉ>õ ±òÝ0¢s8 5ß•Óib¦Ráö$ˆÇ0¢€œP1 |'…_UFJ‚P$¡^PÚjšª Ùl庶E¥ẅ>|ʤÿn­ ýóÁerÑ,‚ àêŸüûýïÊQ$…¾e1˜ËqÕUWár +Ö­#?g¶míø‡$ ²å(pË÷ñËë%€;v°îÐ!N<ñD^~9ƃ’zï{9òòËÿð¼ýÏþŒmßÎ;.¼wž|2[ï½—U/¾ÿ8=ïz{žžÞD‚O<‘ÏnÛÆŠùóùèu×Ñõë_Óáy|óškxßЫÒi¾ù©ÿŸ½{“£*>þ ¹“d&. †1±˜ˆ@ ˆã* 5\U4ïöDWYÈ®tûú¾Ýv¯ûŠ.®¾Ý0+FwÕîø/¸ËL +*ò‚ʨq /d@„)†‹ÉTfr'~ÿ8}ú2מKO×Lžïç3Ÿ™é®ª>U]O×éóÔ9çv–_y%O‘åËùÏK.áŠM›°Âa~ðÓŸ² øÂ²e|ð»ºø0°à _à[À{|Ÿ/_ÎK_ü"g=õép˜­sçæ’F‰~”kûúX¼x1{¯¸‚'€¬+¯$ „‰Üðhçöõ±÷¥—HVvýÃ7ÞH2“¡vÆ TÏݛǎ³?ô!< ;æÿö¹çÉ. *„Mà^À´m5¼Z8ŒI¾—OôÒKq3Ƽ¶6bj;—_Î?¡p˜ZÀÇ1'™ÄAM§›È¾Ž[PÆ'ÿå_øð¿ÿ{ÙοÉT®v[PÃÝ=ûI¨Ú³¨¨ HÏq<Üè0Bɤ'Tê²™èêêê¢Ç;;;d4«««G“oûöí¬]»–7lÂ_2—óÎt9×uI§Ó2ÜÈTW®F÷žžÜŸzÒ]ÍÿÎwxøK_âéŸþ”Û¿þuþràîŠüjÏ~Ó×Gí]wÁw¾Sé#3nCÅ&Œ=>~øa^0.dþœ×1ÿ¯ð¼ïûD£QéÒ)&\gg'ÍÍÍìÞ½»ÒE™Ÿ»wïfíÚµ\wÝuœö5ô¼Ëç­ó^à‹­?uÙtüê ±$SÆ¡”a‹¦¸P(Dmm-¯zÕ«ÈdÊ;Îùd™èºmWW‡æfT,™fù‡‚¢ÀÚµkÙ¾}{®±d*+WÝöÉC¢vï©,¿êp~>Hß/îY£î­å$ Cýïyê²Ð¿„mç;FèŽ&‘H>¯£:!«Ñär‰TQ}_5æ·µåGÓ9 Ð7âñüHczt,=Uˆiªåõ(dz”«h4_öÂçug•x<ÿºúoÏËÎ¥GèÓIˆÂõõGd:ÿßqòƒèÿõö §)‰ÅTž'•Ê]ø¼ë¯£;ŽéÊ ©,VïA(”ߦ©Q3Èä¥GéÓÕ¦ÂÊ8)M'¿ôú:¢§ŠÑÛ©ãYÿçÓéâQÝÔt:U„B7°vmšénÌuÛÏ~V×\Sü¤6¼_¬öïUJ¥r‰Çqr½jmÛP×Õë~5M“ÖÖVàq(ºË^o]¸Ã0ruê±0È÷ÖC Æâo=‹VX’ЛÛ0û­cõûÛbýÂAá Oý¶‚m' –/Ü/è)Øï(*!b¢JfÁãÑ~ëè¿#Ù×ö{ý¿uˆìöÝ‚ÿmò=brû²f nßÎö+®`:o»-ÀN !ü"{,î…¢ç¤ÓˆBB £ÿ]%0 •ÁîLèîîÎeFKb+Îð°¾0F£Q™§AŒ‰]Pc¿À²ˆD"´¶¶ò¾?ü¡ÒÅ+»ñÄçoŽÁ¼s_äÀycÓ4ÍqU"…ã¿~vì;À/máϵµ#.«'^,œ°Qî"£eš&»víªt1Ên¬±¹ÿíûYv§n“B”ÅXãsß¾jŽ5f8s×Aü[>TÜ:YÀuU’C÷²€|C¿îm åÜ “ :ù0T2`0céÄ?XB¤ÔåGs/Ôh«ú¦Yœü)eêÃP‰¡RémŒ¶Ý®ÿTEƒD=¹ðþV£Ñüa'ƒ1×mu÷ŸþoŒž‡¬à„w‡X,Fkk+®ë’H$hkk+jÌu]—øA2ÜMp²7 ÇòãqHC%~ú+l†/|wJ9æfvýÑÞÎY˜ê6²«öí£mšŒŽ0”‰h·õç³/Óºôà€çlÛ–á¾Ä”˜„J]]---Eõöö–>±Qö“ÑÌvq,‡ …Br§Ÿ³Á*RÉdÓ49÷Üs9pà@¥‹XVã‰Ï}gÃÒSŸæ¢+¯ð\,#Êü)BŒÃ¸®Ÿ.l[6›,8N×ò‘¯‘¾ïã8–e‡åº*Ä0Æ›Kþô8oùæ—¸@æÒ¢lÆŸ‹»”;^ä­o7`JÇÉÏ«q˺}¨¤„\ZEÿsk¢5SŘë¶z¬¹Bž§‚3›µô}ŸÆÆFœúz6¯XÁ¬sÎᯫ«¹éÊ+™SpàÞ§¶×ب°¬â ¤ç©®C…¯—Í„÷ʲlº«T*¥¶§?8´tZ=§Ç¤ëŸisœâîo0°Œz̽P(ߪs¯ß>•1]Ð+Jw5ÓǪð5 ¶a WÎþI¯þÛèÿƒmc°arõqµ~á¾ìGÛòåX;v Þ5LO¶dšÅWÇQÏéI”úo?‘àõ[·rä´ÓF=ÔT2îv[TBåÐŽY°tàsr¼˜J“Pihh ··—öövèì줻»›ë¯¿~Äu}àtöƒg²éÍ-+B”@'Î=÷\-y¨œ©l<ñ¹ÿðÿtzÑžç‰DrI)!ÄØ'>½£°øø,^8svI¯•H$ŠÆ‹B m<±yiOË—/¯ô.1m5>{ÙAîÜËÙg¿)×¾éûªMRC%£•1>c¾~êñÖ ÿojÊM”Î6¨Çãqëîc_ù súo«b¢!=æ^áãýðÕczœ¸x¼8‘ º»Zÿºµe©”¦¦Á»zŽ57T½Ü²òãûéý*\¶R¢ÿvú‡§Zÿît#mC'O’É¡·¡'nꟴ)üp,1¤'8Ò˾‡:)dYX†ýçRÐ8é×èŸÕÔç‹ã¨cÚû¦Éþyóèíëc:OÝ6g?Ô.~ç—gTdÔ1Õ&¡j\³uëÖ±jÕ*¶nÝÊúõë©ÊNV5˜ñàË>eÀs©TŠdᇵbLÆŸî…çv¯Í=f†$S„˜@cOÏ„W›³8Òû‡{ŠÕÖÖÇ1õ¤™Bˆ56k÷ïÛ>Bˆ’%>ŸîZÊòÌv.TqzBtÃ(nBŒÏ˜®Ÿýçô3MÜdR íåû¸®;¶ÖCu®ëeAOÏðÛéCCo¨»öGêºTøüP™Þ‘ÆïëŸìè¿ü` •Ñ–s¤×0Íïm£¨h´Ï[Öðõ²PˆÞövŽNóùaìu[Íý¼tÊK\Ð/©%mCbª©XBEOHThÍš5444ÐÝÝMMMͨºÍ=ü2*¡Rx¹Ñɤ×B”f°Ø„±Ççì·Bü‡woÍ=–H$0MS&b”&:>Ýnøý}pñõ ›$I$ÒÓSˆLdÝvÇܹHÿ!&ÆD^;ÌËyÕÏçþÅÔDèòUSˆ±™èºm!ÇqH¥RضMcc#•Þ]!¦”‰n·82Þ{Æ78pÞk‹O§ÓÒ>$¦”@õPÆv±|®¼þO|‹ 5 ëÒ)“^ 11ÆŸÏo:Bï®âf¡P($w¸ 1ÁÆŸþ˜±OMº9Ô˜µúÆ!ÄØŒ66WîÛÇŸ—,áòJ\ˆ“ÀhãsùÛvrÅ·šH$ÔMÓR¥¢<ÆšHÑ Ã bš¦ÌÍ ÄOlöùðÝ…UÔ/\˜{Ì÷}YHL9§Œ°ýoƒ‡=¬'ÍBTÎÁcfVW=–J¥¤K§ññÿñ<ÏtȯT*E*•".“c 1iž˜3‡¯œsN¥‹!„Äêïm`Ù¶ßbÛÉL빇…˜ÒtÖ², ÃïžBÄÁ±c»ŠFJ¥R¹â…˜*×Ce,¾?àeÞºg¬\™{<‰Ð:ÒX‹Bˆ²:´s§^t¼è1©Ð  O¼tœÍÿ}Öƒ ì8Žô&b’½øâ‹#Îi$„¨Œê;9zþù•.ư<ÏÃ4MÇ)ªsëÞ¦†aàû~îsFßè¤'Ös¥ù¾çyضM*•"âû~ÑQ…¯‡ñ}?·ž~\‹ÅˆÇã¤Ó鯧—×C¾xžG:&™LÒÔÔD4%•J‡q]˲p]·¨ŽFI§ÓxžG(ʽ^,#™L‰DˆÇã$ lÛν¦a¸®›+‡ïû˜¦™{,NmÇuÝ\Ùõk¹®‹mÛ¹9:ôñJ$¹9;b± nút˲reè_f}ŒõvÇ! ‘N§Y°`A¥O±)Á²,é•"Dí~œùÇEÙ¶-u_1åL‹„Ê®ÀªÃä}Ïfr •T*%à §>ÆŒª—rÿKï!‚cדG¹,ÓÁ9CôN …BòeTˆIvÚi§I¯0!êç\0)ß/}ß'N …r‰Ý8‰Drë¡P?;Ù¶ëºtuu%¢Ñ(ŽãäO`è»-ËÂ4Í\"Áó¼\"Å0 ÃÈ­‰DH&“¹å,˲¬\2Á0Œ¢zC8¦±±‘xÓ4ééét{C%pF3Ϫ~íá’Ýý)…¿uÒj¨ãÚŸ|WŸ¡Î!!Dåmûü,þzÕªÜÿžçÉÈBbJš •£o\È‘ßì-ú"!w#QyÏ/]ÊÁœ‚y…ú¡¤ç˜ÁðLï<.ý,ëEëa)ä ½S‡Nxèáv,Ëì(lTÇãEþ…ðz{º=•JåîäÖÃéÆ}=ÄnPÕ×xýœNʹ»² õÿú9}‡»Nbèrè»Óõá…wn›¦I4Ų¬’oû78®S8LŒ¾ã¾°!T7b'“É\Yõä¦iæî¦×¿û-<ÎÀ€;ñõñlkkËýÖÇ«p=øÑ ®áîü×åè¿Ïñx|À„ͧŸ~údœ²SÒ’%KJ–D¿'žç‹ÅŠÏû÷þ( ß@Û?‘!„(Çqr7ô†!ßE…¨=œ¡"x~óÀÌÅ}¹zj"‘À4ÍaoÊ"¨¦EB¥gåLn|ý©€j°í?®°¢2NýÍ©¼¡j¦yÑ€á-„•åüÿîÌäãRé#½S„=ä–¨ðK§ŽU¹¾ Q:>ulJ, QYzÈ¥.+ÄäkݶÇÙÅ™o:†ïûrÓ˜ò•PiiiaõêÕlܸ‘Õ«WÓÒÒ2â:³ŸšÅ›÷ìÃqZ[[å*D™Œ%>¯­ú3g5ôຮLr-D%>ÿ6Ãi×–û_Æ~bâ%68@cc£Ä¤e6–øÜ·O}ïŒÇã•.¾ÓÚXâS†û¢üÆ›÷~ûÏìž½ŒóO9ŸH$RéÝbÜfUº…š››Ù°a tvv²zõj¨©©rW¼è:ûe©”Tl…(£±Äçüùó™¹p¦Üy D™%>Ïyú/¼åßWP[[KWWW¥wAˆii,±¹hÑ"ÚÚÚ*]t!¦½±ÄçŽ;xÛÛÞVé¢ 1í%>…å7ÖØüòo^fʼn]\òÌlj£Qi#S^`z¨´··S]]MCCuuuÔÕÕÑÞÞ>ìzó_1Ÿíçn'òN¾µk×VºÃjoo§¹¹¹ÒÅVÐáÉ`¬ñùâÙ/²­w[`'ë ú¹ÕÜÜ<â1®¤©ðùq2k|&^ÑÇÞ½{Ùp;Î-ùü#klÂôè16ÎÁ Ç{©¦Ó{2^cÏ‹.º(°õÚÑs:x¦Ë{2Æsýœê¦B¸TÓ圞NïÉx56;;;ùõ}+øü“3YÿÅõ«çýZ2ÎÁ Çû–-[xòÉ''t›é¡ÒÙÙ9 £Y]]=â˜|­]­$ý$×~êÚJï ¶oßèëàÁƒ:tˆÎÎÎJeHA>†=z”åË—ç.*ÓÑXâó§?ý)›¶obqïb_ûx¥waPA>·vïÞͯýk6nÜXé¢ *ÈŸdûöí¼øâ‹•.JÙ%>Ÿ|òIVŸXͲÿ»Œ×¾öµ•Þ…‚|niòù1¾²íÚµ‹óÎ;¯ÒE)«±Öm]×åòË/§®®®Ò»0.A>G+èñ^ªRÞ©ÛŸÛ·oçßø?ü0+V¬¨ô.ŒËÉtNO#½'ºn{ôèÑJµìÆZ·½üòË9ýôÓYºti¥wa̦B¸TÓås¦”÷Dê¶Ã×mg9‹×å«úµõµüÃ?üC¥w¥HЯ%Sás!Èñ¾}ûvvïÞÍë^÷º Ýn`*½½½+¥;gO(!¦‹±ÄçÇ>ö1>ö±UºèBL{c‰Ï_ÿúו.¶ÓÞXë¶øÃ*]t!¦½±Äç»ßýnÞýîwWºèBL{R·"˜ÆZ·ýåfÿúY¥wAˆ ˜!¿ª««<6R–S19$>….‰O!‚IbSˆà’ø"¸$>…&‰M!ò“P©««ˆ½½½2é˜ ñ)DpI| L›B—ħÁ%ñ)D0Il ‘˜„JCC½½½¹‰€:;;éîîæú믯tÑ„8éI| \ŸB“ĦÁ%ñ)DpI| L›Bäf€õë׳nÝ:V­ZÅÖ­[Y¿~=UUU•.–‰O!‚LâSˆ`’Ø"¸$>….‰O!‚IbSeF&“ÉTº…º»»éî¦Fº 0ŸB—ħÁ$±)DpI| \ŸB“ĦL¨!„B!„B!„BM`æPB!„B!„B!„*I¨!„B!„B!„BŒ@*B!„B!„B!„#˜ùÉO~ò“•.ÄTÕÝÝMgggn2¦¡ž¨®®õó©³³“yóæ1wîÜ@•¯¯¯×uéëëãÌ3ÏU&󸉩g<ñYéØ,¥ •ŽÏ ”OL]ÃÅgέ±Äg¥c3hÇPLåŠÛJåˆïÉÞ—r]§å3bj)çwÒ Åçxão2÷¥œßq%>§–r~'­Ä¹PŽï®AºvŽ·¬Ÿá˜ôõõ±gÏžÀ^;‚þݸ³³“gŸ}6ðí¶“Þ¶–cr÷Ýwgêëë3·Þzkæê«¯Î¼óïÌôööæž¿ï¾ûrÏ×××gî»ï¾¢õGz~"=÷Üs™úúúÌc=¨òmݺµè~üã/¹ “yüÄÔ3žø¬tl–R†JÇgÊ'¦®áâ3HçÖXâ³Ò±´c(¦rÅm¥ÎÇrÄ÷dïK¹®Óò1µ”ó;iâs¼ñ7™ûRÎ︟SK9¿“Vâ\(Çw× ];§â{tA9&wß}wæî»ïuù&£üAÿnüñ+›#•¯”ç'Âpñ„ò‰©k¸ø Ò¹5–ø¬tl–rŒ$>ÅX”+n+u>–#¾'{_Êu–ψ©¥œßIƒŸã¿ÉÜ—r~Ç•øœZÊù´çB9¾»éÚ9ß“  Â1YµjkÖ¬)ŠÃRË7åúwãîînÖ¬YCUU@n82i[S$¡2 lÚ´)÷__›7oÎ\ƽ«®®¦»»»¤ç'Jgg'›7o&x¼ÒåëîîfÕªU´´´°víZÖ­[WtÒW†É:~bjO|V:6G*_)ÏO„áâ3åS×pñ”sk¬ñYéØ,åI|б(WÜVâ|,W|Oö¾”ë:-ŸSK9¿“)>Ç“¹/åüŽ+ñ9µ”ó;édŸ åúî¤kçxË*ñ9PŽI]] ƒÎ‹„÷4è߯»î:Ö¯_O__ííí¹Ä…N@!¾+Ù¶& •qÚ¼y3«W¯¦¡¡5kÖùl]¡Â7i¤ç'B__ëÖ­cÆ ¹lb©¯?åëîîÎe-o»í6jjjX»vmîÄ® “Q>1=Œ6>+›¥”¡Òñ„ò‰é¡|áÜO|V:6K)ƒÄ§¯‰ŒÛÉ>Ëß“½/åºNËgÄÔ5ÑßIƒŸã¿ÉÜ—r~Ç•øœº&ú;édž åüî¤kçxË*ñ9PÐIÐÞÓ ~7Öº»»Ù¸q#›7oÎ%SF*Cп»OD%¡2F}}}¬]»–ææfî¼óNî¼óÎÜsƒe? 3\#=?R©uuu¹®b½½½tvvÒÙÙˆò:Q7lØ@CCëׯgÍš5´´´ŒX†É*Ÿ˜ºÆŸ•ŽÍRÊPéø JùÄÔ5T|áÜO|V:6ƒr ÅôTޏìó±œñ]‰Ø*ÇuZ>#¦žr}' R|Ž7þ&{_ÊõWâsê)×wÒÉ<ÊùÝ5H×Îñ–Uâs  “ ¼§Aþn¬ÕÕÕ±iÓ&xà6oÞ˜vÛJ·­IBeŒn½õVjjjp§(Cêdëÿ&ôööæ2]#=?Qúúúظq#7n¤»»›Gy„Gy$åkhhA,ü¸2LÖñS×Xã³Ò±9RùJy~" ŸA(Ÿ˜Ú†ŠÏ œ[cÏJÇfŽ¡˜~Ê·•8Ëß“½/åºNËgÄÔS®ï¤AŠÏñÆßdîK9¿ãJ|N=åúN:ÙçB¹¾»éÚ9Þ²J|ôc”÷4Èß[ZZظqcîÿªªª¢× B|W´m­¤©ëE‘ûî»/sõÕWg{ì±¢Ÿçž{.·L}}}æ±ÇËd2™ÌÖ­[3õõõ™ÞÞÞ’ŸŸh·Þzkîõ‚P¾ÞÞÞL}}}fëÖ­¹ÿ¯¾úêÌ}÷ÝWR&ûø‰©c¼ñYéØ,¥ •ŽÏJ—OL]#ÅgÐÎ­ÑÆg¥c3ˆÇPL}åŒÛJžß“¹/å¼NËgÄÔQîï¤AŠÏñÆßdíK¹¿ãJ|NåþNZ©sa¢¿»éÚ9Uß“ Ê1¹õÖ[3wß}÷¨ËWîòý»±.ŸÞfÐÛm'»mM*cp÷ÝwgÎ;ï¼?…zß}÷eêëë3·Þzk¦¾¾¾è„+åù‰ÖÿÄ Bùî»ï¾Ìyç—¹õÖ[3W_}uæãÿxÉe˜ìã'¦ŽñÆg¥c³”2T:>ƒP>15ŸA;·FŸ•ŽÍ C1õ•3n+y>Nt|Oö¾”ë:-ŸSG¹¿“)>Ç“¹/åüŽ+ñ9u”û;i¥Î…‰þî¤kçT}O‚,(Çd¨„J¥ßÓ©ðÝXÇŠ~ ·ÛNvÛÚŒL&“™Ðþ6"§»»›îînjjjí24Òó'CùôkTWWSWW7ª2Túø‰©-èçVÐã3åÓÓT8·*ýù1žkgPŽ¡˜^ÆsÎí|OY'{_ÊuÚ{"Ægºœ ã¿ÉÜ—r~Ç Ò{"Æoºœ SésFâsrý˜ý= Bù:;;sCa=¾'óJBE!„B!„B!„b2)½B!„B!„B!Ä$¡"„B!„B!„B1I¨!„B!„B!„BŒ@*B!„B!„B!„#„ŠB!„B!„B!Ä$¡"„B!„B!„B1I¨!„B!„B!„BŒ@*B!„B!„B!„#„ŠB!„B!„B!Ä$¡"„B!„B!„B1I¨!„B!„B!„BŒ@*B!„B!„B!„#„ŠB!„B!„B!Ä$¡"„B!„B!„B1I¨!„B!„B!„BŒ@*B!„B!„B!„#„ŠB!„B!„B!Ä$¡"„B!„B!„B1I¨!„B!„B!„BŒ@*B!„B!„B!„#„ŠB!„B!„B!Ä$¡"„B!„B!„B1I¨!„B!„B!„BŒ@*B!„B!„B!„#„ŠB!„B!„B!Ä$¡"„B!„B!„B1I¨!„B!„B!„BŒ@*B!„B!„B!„#„ŠB!„B!„B!Ä$¡"„B!„B!„B1I¨!„B!„B!„BŒ@*B!„B!„B!„#„ŠB!„B!„B!Ä$¡"„B!„B!„B1I¨!„B!„B!„BŒà¤K¨¤R)Ç©t1N*¾ïã8®ëNÈö<Ï#•JUz·DH|Nžç ×ŸÓ“ÄæÔ7šØt]ß÷+]d1$v§–Á®­»Ó—Äçä«Ô÷R‰Í©Eb³2ÆŸã½vŠà“˜œú¦cLžt •t:=e±±±1w‘(ü;È\×¥¶¶–D"ASS‘HdÜÛô'W¥¾—JlN=Ó%6û?¨ÆŸã½vŠ©aºÄäT‰Çr˜Ž19«Ò¥s'wgKáßAÖÔÔD4%âû>õõõ¤ÓiB¡P¥‹&Ä„šŠñ9žç‘H$èêêÂ4M|ßgÉ’%„Ãa,˪tñ„àd‰Í‰2 LBL„“)v‡»¶–JbWL¦©Ÿ•ú^*±)&SÿxœÎñ9×N!Êm*^/Ei¦}•t:Mmm-3fÌ ‰ 8yu&|É’%Äb1b±X.cèº.MMM̘1#÷®566’J¥X²d K–,!•J‹ÅX²d µµµ¹ìi©Ë$‹å~ßzë­¹¿KÉn–Áqœÿ¶L©ÛnŸô‡E4À0 ºººŠ.Šz[…ï뺹÷Bos¸®a…ïÛhÖ•7\|›úùÁâs417âs4±9š}*%^‹Oý†‘û­+°C‰Ï©§Ò×ÎÑ.;”‰ŒÍÁ«T|›¥¬×ÿØèõ ³,K’£S˜ÄîÄ×{Kݧ±^WQ][%v§.©÷V®Þ;ÙßK ÿ—Ø ¾ñ\;õóAˆÏÂØÔçnáÿéd½w¤øœèk§|/ >©ÏNÍúìX¿‹NÙ˜ÌLc]]] Ç3™L&F3@&f2™L¦§§'cF¦µµ5ÓÓÓ“ ‡Ã ÓÖÖ–{N¯ÛÖÖ–1 #ÓÕÕ•Éd2EÛ‰Çã^ǶíQ-W ]¶þ—²žmÛ¹ýêÿÿ`ËŒ´½Rö)™LflÛÎý…BÊ dÂáp¦§§'ÓÑÑ‘1 #“H$Š×Ç^¯ÛÖÖ–{p8œ±,+·Üpë‰`.>‡‹ÍL&3l|Ž&æ¦B|Ž&6G³O¥ÄË`ñÙÖÖ– ‡Ã™P(”I&“™P(Ttœ$>§¾ \;G»ìp&*6{¬Rñ9Tl·ÞP±©uttdLÓÌôôôäöIL-»ùõ&²Þ[ê>纚Éd†¼¶JìNRïͯW‰zïd/Íd$6§Šñ\; ŸJ|öÇRã³’õÞ‘âs¢¯ò½4ؤ>›_oªÕgÇú]tªÆä´N¨D£ÑL8.zÌ4Í¢¨0ôIÚÖÖ–I&“˲ŠÖ ‡Ã¹u sQúÍ/ü¿0¡RÊr¥O êÁþê±á¶WÊ>é>}AÔÿ÷/KaàÛ¶I$Ã0†|/õk„ÃáŒaEA8Üz"X†‹Ïáb3“É Ÿ£‰¹©Ÿ£‰ÍÑìS)ñ2X|êXÖï•išEëH|N}A¸vŽvÙáLTlöX¥âs¨Øn½¡bS¿‡¦if:::ж'¦‰ÝüzYï-uŸÆs]ÕËvm•ؤޛ_¯õÞÉþ^*±9uŒçÚ™É/>Ç“P©T½w¤øœèk§|/ 6©Ïæ×›jõÙ±~ª19­‡ür]7×ýO3M3÷·ïûEÝo —õ<×u™1cFîgJt9Bá~öÿPMÄë¶¶¶bÛ6ñxœp8<à8ö€Ý¢ ÃÀó¼Üÿ…ÝÙ »Ë´žŽáâs¸Ø„“/>Ë›PZ¼ô?ö=ôétšŽŽâñ8]]]¸®K"‘È-#ñ9µÉµsðýê±JÅç`×ΑÖ*6‰–eáû~nØ×uOÚI§*‰ÝÁ÷{°ÿ‡zl¼Ær]H¥RÃ^[%v§>©÷ÜïRÿŸÈ׬拏SÇx®0½â³’õÞ‘âs"¯ ßKƒL곃ï÷`ÿõØxµ>;ÒºÓ-&§õ¤ô¥ŒU:Ôd¶mÓÖÖVéݘ²lÛ0ŽßPA×_ÿ÷¥ÿ˜‰–e‘L&1M“H$BGGGIë‰à)>‡ûð.> öÅðÆ/;wîÄ4Í¢X¶m»h]‰Ï©M®Á0Öxn½ÁbSDzïû¹ÏOÏóH§Ó¾°ˆ`“Ø­¼ñÄíp×V‰Ý©O꽕U‰ï¥›SÃx® ñ9ÆŸã¹vÊ÷Òà’úlå'>Æú]t*Æä´î¡bš&©T*÷F¸®[ôA …rwŒž+¼‹Ä÷}jkk‹&4ó,+—!u ÓétITÏórï‡^϶íÜó:è¢Ñ(¦iUV‡[OÇpñ9\lêç%>Ço,ñrÞyçáy^î½ÑëVd%>§6¹vÃXãe¸õ†ŠÍx[y㉱|ïkVʴq]—ÚÚÚ܇m(Ê=oY¡PˆúúzLÓ,Ê€™¦I4¥±±1·®mÛEëO6Ó4‰Åb¹Œžþ;¨w¹†A<§¾¾Û¶sÇ0—´¯‘HÓ4swD£ÑA—Õ¯±bÅŠQ­'*k¸ø.6Aâs"Ë<ÚxyÓ›ÞÄîÝ»‹Þ7˲$>§¹vÃXãe¨õú7èØ …B?¢4»•7Ö¸Õƒ][%v§©÷VÖd/•øœ:Æsí„àÅgÿxœÎñ9Ök§>Nò½4˜¤>[y㉱|ïkVÊŒì„2Ӛ뺹wQû¾ŸëVäû>¶m3cÆ zzzŠºyž‡a?áuYôx¬úïR»+WºÜ¥CÇqH$´µµá8NÙו5X|–› ñ9ã—ÉŠkQ9rí¬¹ŠñØ­Œ‰ˆ¿ QRï­,©¿Š¡ŒçÚ Á‰ÏÂØÔsL×øëz×SƒÔg+c<ñq²}‡Ö=T´¡Þß÷ill¤µµ˲ˆÅbض]tb›¦Y¶‰·4Ïó†(ɶmlÛ.*‹.ãpãrêõÊQ–ÑÏ1k¯ w yƒÅg)± Ÿ±M½ÞhU"®Åä úµFŸ bSßõ2‘ñY®ØÔëNæzbê zìÊuuh“õÙ)*Gê½_–Ñú«Êx®¼ø,,Ll|–ëÚ9Öc(q==I}vâË2Z㉓á;ìI‘PŠiš$“ÉÜÉlš&­­­“^=qÒpåœÈõÊQ–‰>cÉFN•,¦YPb¦o|Nv¼H|NŸ“³=¹Љ”Ø JÜNô6%þÄX%6aúÆçxއÄõÉMâ³üÛ›l×S[Pb2(ñ8ÑÛO|œlßaOŠ!¿„B!„B!„B!Æã”J@!„B!„B!„"è$¡"„B!„B!„B1I¨!„B!„B!„BŒ@*B!„B!„B!„#„ŠB!„B!„B!Äf~ò“Ÿüäd¿h__®ëÒ××Ç™gžYô\ww7TWWWúøqR.6AâSˆJ’ø"¸¤n+D0ɵSˆà’ø"¸¤n+Äð&=¡ÒÙÙÉêÕ«yþùçiiiáÙgŸå-oy ---¬[·ŽçŸž/|á TWW³jÕªJ#!N ÃÅ&H| QIŸB—Ôm…&¹v \ŸB—Ôm…ÙŒL&“™Ì´m›5kÖpÛm·Ñ××ÇêÕ«Y¿~=×]w—]v6l ¡¡!ÀŽãPSS3äö®ºê*V¬XQéã8¤Ý»w³téÒJcHGåèÑ£,^¼¸ÒERÐáîÝ»yÿûßÏÛßþöJe\†‹M`ÔñyÏ=÷ÐÖÖø÷.ÈåÛ¿?óæÍcÞ¼y•.Ê ¦ÂçÇöíÛùñ\ébŒÛDÇgSS ,¨ôn i*œ[òù1>dåÊ•Ü}÷Ý•.ʸluÛRý Ç{©J}O¤n;x|~÷»ßåË_þò´8N¶sz*(õ=‘ºíÔ¬Û–j*ÔK5]>gJ}O¤n;tÝöu¯{^xa¥wkHA¿–L…Ï… ÇûŸÿügn¹åÖ®];qÍL¢Ç{,S__?äsW_}uÑcï|ç;3÷Ýwß°Û¼õÖ['sF-èå{ì±Ç2wß}w¥‹1¬ ûï¾;óØcUºã2\lêçGŸrn_ÐÏ-y'G9â3èÇEέñ“ÏÉÛ“­n[ª Ÿƒ£q²½'Óá½;Yë¶¥:ÙÎé© Ô÷d:¼w'cÝv4ÇF>g‚¥Ô÷dº¼wå¨Û^vÙe•Þ­aýZ2έ Ç{(ÊlܸqB·9©“Òwww³jÕ*ZZZX»v-ëÖ­£½½P]Êúg4«««éîîv›Û·oŸØ ÓÓwXUMM •.ư‚| ×®]ËÃ?\ébŒÛp± cχ~˜æææJïÞ‚|n444 {§G¥ùó£³³“µkײ{÷îJeÜÊŸ»wïfíÚµ´´´Tz÷äsK“ϱkii¡¹¹™½{÷Vº(ãv2ÖmKäsp´‚ï¥*å=‘ºíÔ®Û–êd:§§Š‘Þ]·Ý¾}{¥‹:n'cݶTS¡\ªéò9SÊ{"uÛá¯3fÌ`íÚµ¹yW‚&è×’©ð¹äxonnfÇŽœqƺÝY“¹ÝÝÝ´··SUUÅm·ÝF{{;k×®Åqz{{,_Ê ½bÅ 6mÚ4™»1*kÖ¬©t†USSèö1Ü´iÓ´øR5\lÖÔÔŒ9>o¸áÖ¯__éÝRÏ- ðÍ ~ÔÕÕ±iÓ¦iÑ(YŽø\ºti ¯A>·4ùü»5kÖPSSSÔx2UŒuÛRù­ Ç{©JyO¤n;¼ ×mKu2ÓSÅHï‰Ôm§vݶTS¡\ªéò9SÊ{"uÛá]xá…ŽÏ _K¦ÂçBã]×Û¦tBÔ‰°aÃ@´}}}´´´P]]=`Ùîînêêê&»ˆBœ”†ŠÍõë×K| QaŸB—Ôm…&¹v \ŸB—Ôm…Ù¤ùÕÐÐ@UUUÑcúÿºººÝÄz{{Ÿ…b:.6AâSˆJ’ø"¸¤n+D0ɵSˆà’ø"¸¤n+Di&5¡²jÕ*º»»sãæõõõ±yóæÜxp½½½Ecóuwwsýõ×Wú 1í ›€Ä§$ñ)DpIÝVˆ`’k§Á%ñ)DpIÝVˆÒLê_UUU¬_¿žÕ«WÓÐÐ@ww7 ¹±ÖÖ¯_ϺuëXµj[·neýúõ2£Bˆ‰7Rl‚ħ•"ñ)DpIÝVˆ`’k§Á%ñ)DpIÝVˆÒLú*kÖ¬ÉeuuuÑX{…ÏM…Iw„˜N†‹ÍþÏK| 1¹$>….©Û Lrí"¸$>….©Û 1²IO¨Ã¤•3RüI| Q9ŸB—Ôm…&¹v \ŸB—Ôm…ޤΡ"„B!„B!„B1IBE!„B!„B!„£âº¥/ëûƒ?îy‹¼~: ŽSé=–„ŠB!„B!„B1¥yÞÄm+‘¸½Á¶__ŸO”¤Óêï¡’,‘Èà ×--1ãû’PB!„B!„B!Ä8Õ×þx:=ºž$ ý×ijzY€TJýý¾Hñó:ãû`YÅÏédÊ nN _ΉL‡$T„B!„B!„Bˆ®·GaÏPËF~y×U ˆDbäᴼ˸AHªHBE!„B!„B!„˜DéôÀC!×Í' yÞÀa²|öÚð©|&75ÁçSj}ÃP½GfôÛΣT×ÃߥàÝÙrD€ÏøÐcÃÜpvÛÀ‡ËÃê5ý‚òé²øÀn¾çÀq#ÿŽ“ï•2XïÓ„Ï$ Ï…mig_ó®4<ÐW¦T¢Å:,xɆT…ß7I¨!„B!„B!„e"àº*áP˜4IP[ ßwà®êÅ¡“'>ð3.µU‚ÂG=ߨ}!ø¡ÿn¾åÃ_Ù`uÀ·= Iõ>‰¨?ùªLØrxW@}œš‚—ØéÂ"P‹J`ü>¿ð࣮ZW'ƒößõáª<˜†Ç ?É&|rá\ب’%¶ ßtà'>Üã@(k»à†,ðá•<9 œÞ O¤ÔñH¯1á)W•ßA-*™TxŒG9ºÙ¨ÍšŒ“F!„B!„B!„˜Îb1•$(ì‘N«žŽñ¸zÌG%KÞ…GàÖ¥á ^k¨^%sÃðx#ñà ih°TáQž´à´á%>Ü _³Á²aw\†‡Rð½Võzû=¨z|* O„`i&|÷røèV8öEøy\ëÁ©&˜!øI"_ÖS\ø×8.üÎU ߇£Qxʃ X…ý 0x[ ì0´™ð_!øŸ µOŸJ©„йIx.¿oƒÃü› Oð¬§8oNµ¡½ ¾çÁNÌ4<åÃ)µê/ ÃU)µo¦á†:>ºpy.V•á=–„ŠbJkB@¸ÒB!„B!„Ó’æÊä9ÇQ=/@õʈF‹Ÿ×=Q@5øûÀ›xOâ1èÞ–‚½iXlÀÓìöàwM*Y2/ ÷9ðu.¾¼¨~ìú;¨IÃË&Ì ©¶±8PïÁ*vY°Î‚³€„3gÃ}¸)›¸y* þ;!ù6hü&Ì»þ+ž/wÂ…g~‰«¡æðv[%f§á˜G|xÁ…¤ _2á(ÐgÂù«àw>´9²á<WûþXÞ‡Ã6íÊ¿VÚ‡ÆãðÔJHú°òKp÷Ûà>ÜÜ+L Œ T"È3à,~hÃÎFX‚ •ìXjÀþ¬ºvâÏI¨!¦$ÕÝÏÈþ–„ŠB!„B!„/5¤€˜¨^$ß&¥sÉd—·Tï TñŸÎêo‚•¯k5Ä®?òUÂÂÞ¯ ‚Ñ ‰_e S5|µCß™‰j\óó!~6ªK‡“}Üó0Oþ ¡‹Ôrá0<àÁ©.D“ù6:Ûj¡çƒÀø© nŒ½êÀ™!HÆÀÓÉž!Þ”p\=2ÉeµîÑ ~ià/ÙßkÁ±Õ°c!+_6²Ç0‚ç£Ðùßµ4Lð¹3é •îînº»»‹[µjUUUEÏ×ÔÔPSS3ÙÅâ¤5Rl.S‰øôQŸÿ¨»R€îÊ>' 1]=>…8™IÝVˆ`’k§Á%ñ)DpM׺mÿ›pÓ¨¶z•O(lSò‡}p³‰…> ¶XjÙ(°6 ï ƒTV¹jø¤àÉê…²Ù…Ýõðµ.ø/^ ÎWaÉpŠ›°à J¨Ø1`›š>VÉp^ îA0ß‹š…=®›ŽsXÿ  dÙ`XªlVµÚ1+ ܬþ ©ÔN„Õ²¶N˜øÙ£³I*›ªá —=&ÀÌv5 ‡á2¶{ðŽÂƒì¨ƒiì>Æ*‰BSvÛž*o›Î¤ÄPÙªÐF>ÃâC(œ-‹_°ý˜:¹®C~~˜µ"®*G2 ¯A×)—p/Lèù4é •ææf6oÞ\ôئM›hhh ¥¥…ææfV­ZÅÖ­[Y¿~=kÖ¬™ì" qR.6ŠÇg=êâ` >? †tÌ}Æf?»sw1]=>…8™IÝVˆ`’k§Á%ñ)DpMǺ­ƒÊXä(.Eíòj‚Tk¾wÊV¦à8°°-èsÁtá³ 5”Ô©<Ÿ×âðû4¼Á‚ƒaø•+-øl :ðƒÓÁŽƒsp)pì?ÃGT¡œUY’+³ôÀ¨û¥lá!×¥Æz¬྽÷a¦Þ˜aTrâF`;t?ÚMYÃÅ›«8ú«!žãñ»ÓG냫ÕÉ:±bg{Ù¿mT\†KïƒÖ‚¹•Ôðàà;{°È܈ZžìZ¾‹eî²|÷žìãj\2µÏ»¹›9é9ž¡ö1}ítvy=Î6A’IfxùK/3³w¦zÎ%¿ýBz,6® Á=ÿ²ŒïØ3¡çÔ¤'TúúúŠ.”…š››Ù°a tvv²zõj¦TÆSˆ©j¸Ø„Êħ“ÒÊþ ×%Œš Þ$ßsEˆé"ˆñ)„P¤n+D0ɵSˆà’ø"¸¦Cݶp(/Píî.ù!¼RÙçõhWž¤á5ÙuuûÓmžšjjÞ”Ïg“'‹€»°,­6ty¶d¦Þ±~u>\aÀ÷\¨6Á|lŒ íªIà=ÀÜ¡ g^‘5J8® bÝñc¨ KôXùŸ³fŸdwÂó˜ç£û(ÞõaÿÑã<õ§ØvÝ6.yí%˜W™¬Ã켃=15ñú]q5”×WLÕ&5/»î›mØŸmh:ÿ8à@ÃgTΠ­ ÂKàÒ]ðé(|,ü˜½¨$Ľ5Áœö H6© ýÂU`ö Çn=!°¾‹jð .<úžGÁÇvxó#o¦çÒú¶÷ñø5sÙÎm¤b1Îâ|~|íéIöð¾½ïãGßÞÈg~ðulêk9üÞÃDRÎxî ªîSÉ”C_;Äáe‡³½U|pœÜ\žç©¹ILT‚ÆoÛɱ{å³O:Ùƒ‡gyìX¶C%<êøàº°-‘Ënþùazuð ãƒ`B؃wÿönªöVqèùCV‰™¯\óöþ`/‡æÞÁiU_áwï~·*ËLVÖëBB,w9ð&‡‹ö\Äs_}Ž#GŽ”å\œÔ„J__wÜq¯~õ«¹ì²Ëhii ³³s@ÀVWW·¯¿íÛ·³víÚÉÜ !rÖ®]ËÃ?\ébŒÛp± cχ~˜æææ1—ËA%¹”6Œ×êî}÷ä?»ÅÉ¥³³“µkײ{÷îJeÜÊŸ»wïfíÚµEÛb²è¡öîÝ[颌›ÔmÅt#uÛòÖm…+]·Ý¾}{¥‹2nR·ÓÔmK«ÛvvvŽ»|)FnßÑI}c­ž+Eçüìß79ð›ìŠÁ\Î5`¡ ó]8᪶ùX¶÷E"é´j³w8÷‡púk!z¼fDÞï} ÚU/f÷½`Æàc&|²“ÜXõþ9àüˆ\c•ù[À÷Z`9X…³y6^Ècí~ž­~–sw@œ¤Ã?îùG¼°‡ištttp|íq_p˜¥¯_Jõÿý¿¸®ËοÚÉìîÙ¬ýÖZ:Z[ùrO¡Pˆc·#si†t:eYì}Ë^úNï ~Ûñ.öÝýQøËÎïŸC÷Ü£vØ÷ijjR‚_ýã¯ð< ߨÀú¿¬Ç»4yMlY¿%w°¾»ìƒÔ­«c×-»rCˆ=uï½ì4Ÿ¤çU=àÃÌ™39ç´ÓøÀu×ñÕß•¹ËæÒýênlÛfÇÜxxÃ0XyÉJf1‹93îÁ8 n<|X½™›p– µµð4lþËáÐÓ·sÆË_åðÏsÏù÷”¥n;© •îîn¸í¶Ûxúé§Ù°aÍÍÍ´··ÓÛÛ;`ùRºŒ­X±‚M›6Mæn‘³iÓ&n¸á†Jc܆‹M`Ìñyà 7°~ýú1•ÉC%ÃuO×Üa–õ •R“sy^~øG(N®ˆ“G]]›6mbéÒ¥•.ʸ•#>—.]ʦM›¦Äx·búY³f ëׯçôÓO¯tQÆMê¶bº‘ºíðÆS·bÇÑßüÿgÖÿaoÍ}´_v/ówîäðç>Ç_s”EYÄw6}Ó4¹ûš»ùõ›ÍñÿÁ·ÞñlÛfqr1³­+à%—&ß§¶¶ÿǰãŸn‡ªüÔá/æ_àcq|Ó`ÖŸÃè2ÿÄ*KÝvR*º »‡544pýõ×çºõ7R–S11†‹M`Òã3•ý±Q×*>Ö8ôò‘H>©âûj}×B©]B…ª Å§"Oê¶B“\;….‰O!‚k*Ôm]Ô0ï‰ìO!Ý–D­ZN·}x RuàlÛQ(¤Ú’îÀ™éÜq™}Ål\³F½V{Š+÷¨ Ú-Ëâé=¿âÐðíÛ9ôàƒì}é%LÏãÀ¬Yko§ïÜs1 ƒH$QXuË*R©¾ï³dÉÇ!•JñÀ?ÿ3¿|ñEæ<ø †ç±ñ®»¸ô¯/Å4Mþçå—³èÌ×ò™K>Ãé]Û9cÛOyñ5¯aÏEÑpßçXxôi^yâ×Üôâ‹\ôÈ?rüèðÎý×üü+u&Ø6¼÷½üËò帩gßt6G—v®àg™C‚Ó›8ýþû1M“×ð)ª÷ …yR·"˜äÚ)DpI| \A¯Û>ñÄü|ÇŽ!oœõÈß\CÍe޾ñÖ„‡ÒjÈ.ÓT7änٲ˂pÂsÕô¶­þw~–ö1°ÎUsª˜K˜u*ØŸƒÐ&õm™6•8‰ï*cd •LØ»z/-/g‡&ì‚”“"e§ˆÅb|õ«Àìw=ÊoªÃóÏ?O8Ʋ,âñ8žçÑÕÕŽC2™$ãD"4¿ûݘ¦©È|êë¡Ú‡¥>x_ÿÜçø÷_þ’š§Ÿ†Ó#ù¡]²–ïÚłݻùô§?gÛühɾö³ŸQ÷¶·ñòÊ•¤Ói¢Ñh.¡³æ·¿¥«£˲°,‹ÿþêW ‡ÃÜõOÿÄŠÏ|†_ÿéOœ?g„ì|ùežº÷^R©/_r ÆNùí)8‡ Îzö¾ãþ󢋸éu×ñ"¿ä¼ÿþo–Þs/îÞÍ9ï?3^ÞÏ÷Þ O«7!"³bÅ fç;$“I~³æY^þó%¼øÆ³Uâ§Àó³qìÔc~.NjB¥½½uëÖåÆäëëëcóæÍÔÔÔÐÐÐ@oooÎÎNº»»¹þúë'³ˆBœ”†‹M`RãÓG%Ÿ“€ë¨$Ê®´J˜èÏ|ý['H¬l¶Ú4ÕÅÑ1¨OÁì4t8jÌËÆÆÑ•Eˆ R| !ŠIÝVˆ`’k§Á%ñ)Dp½n{üøqvΟŸû_ùåMÀW=xy8£í¾´jW²m5ßÒ3ÏìŲàòËÇÁƒÀ¶U.Âý/µ|<®nÔõ÷µŽ?}œ5#|-XË€ì¸`þaÔ‹$`Dz¤IslÕ1õ˜•-TöyºÔcŸøÄ'ð Bðè£ò™Ï|†üà|ö³Ÿ¥¯¯ùówrþóç³õðV~ô£á8¸.¿}×»0 C5†eç3ñ…® ×m¶ŸÊÓg/b)*gQ8}X™† …ÜåÁ#&¤}rÃj:ô<<`aÛ°eËÅÜü†Ï¾Ä¿‚=Œ×¨ yqðvªu^œó"7ó7Ck+Üô…›0O‡Õo~ ápÒilà‡†ÁÁ?ü÷Õ¯æ"ßçžÛoçôÓOg¶î5dš<öŠWð½¾>.Þ²…™¾Ï½_ù îÚÅ,‹+ßñÕ˜¦¾\R)ªÛÚht]™3g7ýÍßp÷ÝwóÜE±Ä0¸ÿë_§ùÀþå/ak:ÍáŸýŒêK/Íc²ò’K˜ý£A*ÅÌk¯å”ûïç7Ýă±mmmô,^Ì+_ùJõš Lèø:ÿöo¿ç“¯}-þ?ý¡Í›p‡¹\ ¶ëºØ¶M,㞆õX¿Æ¹¾Ë/çàÀ4Mzzz=gž:~*'üO¿ÕÈ e7&5¡pçwÒÙÙ™ëVØ5lÍš5444ÐÝÝ=à9!Dy ›0yñYØuÓóÔg½þ¼·,hkSŸûMMêoÓTŸ­Z(¤’城B¢zzàœ8üo•<ÇuÕ5$‘P¿SÙ¤M$’?S']šš “XÆDv ÎÂ×ÕåÕ—ú][«~'“ùÇ…­ Ä§b ©Û Lrí"¸$>…® ×mÿbœ?ÏÎ?VO~þÝ—]Xˆº96ìfó!ÕîsÁ;8ºï( Ú–žüÕNÞ÷ìû  Úîs{¶ÍÆëñìÆ-èøC—¸„* ¬íð³÷ü ÿqŸÞGzyêøS¼Ðùïýâ{¹ãŽ;8xð J ø@‡Úćv~ˆÅŸ\Ìßþíßò½ï}K.¹„Ûn»£GrÑE±eË~ñ‹_`š&÷Ýw˜޼À#u¯æŸ»º0"Zž}ß²8Ç4yòK_âÝݼ³¶–Ÿ>o±,¾5oGî¾›Ù[·òáuëhmk#‘H`nßÎ{ï¹Òi ßÇqþõé§¹"&žLªƒJñ©+¯äÐë_ÀŠ+0;øÄÏÎÍ7ßLäòËùæþÀmÜsöÙx?ü!Ñ®.×ÅqÂ_ý*&päß «¡Cóæñ¹û7z{{ñ<#‘Uoy ±XŒö¡ûÄ«¹á†ëyëw2wî\žI$róÁ˜¦™w TB)ô\°,‹Øÿþߌ4Ýü+où;zžÉ+^}Ö„ž‹“žP5îÞPäb)Då ›09ñéû@tàs…‰ 8)L°k¡|, —g—>¤.¤‰D~’1=½m«¡ÀZ[UÅ4ÕçµëBGGñvu"T‚ÄqÔúzn—X,ß“&ÊÏë’Jå_£Y…(UâS18©Û Lrí"¸$>…® ÕmýìÏ÷†q žÏÛpí+vâ8¤Ó6Nvy߇}ûÞÆ[{?ÁïïÄxþ,Œ3fî4ÁW‰R亽ì­z†¿[ü*v­ÚËß¹G×3]¹DÉÃöÃX·Xünßïxç£ïä÷?ý=ÇkŽð›ßü†šÕ5üã?þ#÷\vÏ>û,»víâ‹_ü"­­­|ò“Ÿä{ßûßþö·ijjÂ0 ~ö³ŸaYÄb|þóq¡ßCS3·oÇØ½›7¼þõ¼wËÎ<åŽÿð‡|þûßçö+¯„ÆFžºà~vø0¿ùáùÉÃsË%—äæ …B aÅb455ÑÚÚJ,SUá0¯¼ùfZº”d2Ém·ÝFω\ð ßüæ7ñ<ÚÚZ~º|9;–,a¿ë’6M‰áp˜¦¦&’É$‘ïkçN\×å²Ë.Ã÷ýÜäõ<ò‰Dì(U«®¡Ï÷yï{ß‹iš¸“›ýîB¶,‹X,†ïûD£ÑχJRæ—ÇÐõlõLlBeRçPBˆ‘¸À•œ®GGkk>1Rȶó=G²Imtãòp>á«kH(]]*ÑÑÕ¥z½èÏäúz•4ÑG-§_;Q?±X¾÷L<®’-¾¯–O¥Ôÿ]]ù9_@ý­ç B!„B!„JŒ|ÂÄîܵ €S_yØ–}RÏûx𜎚¸$?´ûüùG9í´^BçÃì—b=·½ÐÃ޼\ØûÌ^µ1Žî<Ê}ðÿž›ÅÓO?ÍËî`Dzê.]|ßÇ0 ÞøÔ±C65WªäÒ«_ýjöíÛÇ»Þõ.vìØÁ]wÝESSßÿþ÷ùå/É©§žÊµ×^ËE]ÄÊ•+I&“ضÍÍoxƒêÄq›Žº‹×uyËK/ñƒ‹/æì‡âÿd'~ÿ·ßÿžš+¯Ì£ n¼‘T*Å5kÖPM¦†Q”¨ÐlÛVs±h¡sçÎ¥µµÛ¶Y´h{jj¸äÙgs‹˜¦I2™äðd©K,£µµ•p8œKz¸®‹ëºxž‡mŒó<ß÷I§Ó„ÃaN‚ËÿçåêP;Ñh×u‰D"Äb1f̘‘OÂ@nÞÏóHë;™³§R)K˜(yñ¥CŽM ŠôPBˆþ<Ô {= ›¸Žî ht÷* ¨ÏÁ5ÝûÅ+ƒÌqЇîjmU ‘x¼x^=¤˜.cá6u¯–TJmGß1ašù›tO=œ™ãäŸB!„B!„8YxÀÑ£Gáñeœö¯/plþ+ø´ÁŠøqðUN‚ƒg³†<ÿÂ\w>«Wïåæ›ÿÛŽs͆kø§çz°Î„cÇÏá!âo|#÷wòðkæ­ËÞÊ®§vñ?VþØŸØñ î¼íNxîn·oõ©OqóÍ73oÞ<Î=÷\,Ë"™Lªß–¥–<7ýû¿óúgŸU7Œ|Cð“9s¸éÃÃÈ%(Š´µÐÕÕ5 ç†aª×K–išƒoø—_λ²ïܹ“-Ï<á÷¼‡ÅË„Ãá\r$cšf.1‡©¯¯Ç¶íÜó¶mãº.©T Ó4s¯ïeØ|ßϕٲ,<ÏÃ0 :::ˆÅbj¨¯ìqíêêÂó<ššš‡Ã¸®K"‘Àóöœý ^…_§à%Þ“€HöæÕþðYtW3sf†±“<ÏË3÷2B°.x÷aümPuA/yßÿþ÷\R} »zv±£gsNŸÃ¶k¶qNêμâL^|Ó‹ìpv¨®0íCUë«ð›ü\ÃþÇ?þq>ð‡¹ñƹøâ‹ùØÇ>–[Þ²¬üµ¦ÉœC‡˜ó⋪QȲÔݵ­­àº|¡ÃOcc.‰RÈä®b˲Šz¨„B¡¢ËP.¾øb|ßgñ—¿<à¹P(„çy¶cYñx<×+&žmÌ+ì cY¶mcY†aÐØØ˜Kšèuõòžç‘H$ð}?—Ò ™úúú\rÊu],ËÂqœ\BE3¦“<˜¦IuO5{Ø3¡ç¦$T„à¡Æ¼„Ò'oFK2K_rb€V‰•ê÷P`²×0R)•èèŸL‰ï«ëä`½gtâDo¿­M-gÅÂéåãñ|/=”˜iÊ$÷B!„B!„˜~ô`!.j÷Î#GXдþKCpÄ„×yðkÞcÃïw#šË}÷õðÖùKù׃Ç9õÔsGÍý,;«JefLøçê̳“§N{ŠûÝûiµZYvæ2æ?6ŸSÿß©,ãr0 5ÞŠ£ï²µ€6p—¸¹á­,ËÊ iõ¹o|ƒÍ™“Kœ~úéù!¶êë Æ¤·Ôð%–¥~ô$¾†‘O˜ –üÈ Æ=M õï¡ÒÿÌP=Y,Ë2)ÍŽ»ïñR°-H)L²è¿û—ömR©žçÑQ0±q<Ç÷}ÇÁ¶í\—Âđ뺤ÓéÜú®ëbÛ6ówÏŸð„ŠÌ¡"„°)N(”b4½TlÀÏ^³|Ô…y8z^}AÁ#Ò‰á>–¥Êošê÷PÛ×Cé^Œ#'ÇÉ;6‘úÏY#„B!„B1‘tSJÇÏ‘>ó'ž:•]»–3ß„ƒ'`ñ‹°Ä€]»žbëÖ’ú¨OdÞŸ¹rÖq.»ì+œqƘud¿åâÜÌö/yœx&ΙÏij=|ÛÎyÿ9¼|Éˬzû*ÕØ?Ĩ)–e© ÖQÃ]¥R)B¡óëêøð­·ÏŽßÖÚª¶S8Ï‡ëªÆxàØy*¡bÿ¶B!„B!ÄxíÇè:ÁìkNañý=ñ–p¦Ÿ9 µ|îs°lÙTýå%>pÆëXòìvë—¼ùu…á¡îà6¼¯ñ}[ !fY°üíËYþöå^¿p‚÷ßþö·?~œp8Ìüë¿ÎÎ+òØ÷¿m\þ»ßå'âõýÜ\)„ꥩ)ß ¢{¥”*.©w 0dï“þÏõŸ¸Þ.qû¥–! 9$ÙPe,œ›e°mF‡iäÒûÓÖÖ†ã8¹ŸÚµÐ4a»H!Dè.œ %&ÝGÍ&—¨¤Š›ýÑÉŸ|Òò=0}tI„PH]K½á5žk˜ï« ôk»n~þ•R¸îн_‰ü6…B!„B!Ê*ÛH3÷ô™6^sñ€ K_Â[ªÞ¢tLò“öê† oø×ŽÅb¹ùEBÀ[!‰päÈ>ó‘äÔ ݈ÓXÛVÃ~i'ie²è¹a´d2I4å÷¯û=‡Î?4¡¯% !DÅø@-*yÑžmì/wB¥0wm æ ¡®«:‡P˜\IOMRâÀ0T’¢”!¿ô2á°Jt¤Rêg°^1†¡–K$TâD_cl[­kê& ÏË/Û¿G‹ëªõõPbº^àûùºƒëª¤ŒãLÎñB!„B!Äô´÷O'XòË×p܇WÍâ¶Ú8»»Ø·çež˜}ˆópÑxîK—Põ–*Õ°£ÛslTo•8Å Cƒ°,+×»aûÌ™¼¼oß|è!ÎÿÙÏxÏO¨ÆÏS ”pxÊ‹îN±òŽD'R ‡üõ>†ÃazOëåÄ¢úš£J¨´··ÓÒÒ’û¿³³“µkײvíZš››+yì„SP •Ìè"?O×d$ìõ_…LTÏ”VÔµU_‹ÃÀ¡IL¨”šPÒÉÛVëµ¶ªÞ£Ã?ÛØ«D¯êæŠdRý¶í|P¿õuIOvŸNççhI$Ô¶ÓiI¨!„B!„bltsÿ¡îÙ,zW¦ KC05‘ü…O\À3ñªsº°ÂV~r^_ý>ÿ‰óU# t”þÚ¾ï“N§illÄ÷}^úû¿§··—cÇŽ1çNª¶lQ ±˜j$1Íü]«S€iš¹Þ7Ó!±bYžç‘J¥rû5JN¨ÜqǬ]»–îl°»»›[o½€ºº:6oÞ̺uëFõâôõõ=ÖÝÝM{{{îu„“o°Ø„‰OŸ|¯K×-ÿÜ)Ÿ|~°—ÒCk’}>;_¯‹æ'§/çe2û0Z…“Ú%U7P u­…òÂY–JŒè¤Šãä*–•/§Þ–îÝÒ¿‡«˜x“ŸBˆÑ“º­Á$×N!‚KâSˆàªTÝVFþÔSOqâ¹Y¤R°Ä†Ëf°sþNŽ;ÀÙ3ÎæÊ§.Âvì|&‰jØ)ì™2Hã8D Ç=G%SR©¡PˆÖÖV\×åõïyw-YÂ׿Ìaá•Wæï.'}¸†–€1 Ž|ß/úªò}ŸH$2`ȯr*)¡ÒÙÙÉ#<Â<Àúõëؼy3ÕÕÕlذõë׳iÓ&6oÞ\r@é„ÌÖ­[sµ´´°zõj6nÜÈêÕ«‹zÃ!&Ç`± åOß/ž›«œJ½T´R|C"¯õ ©ŒeÓ½E˶ï;ïû0¾Ÿï­bÛ*qÒÖ¦’)–•_>WG£ª¼­­ù9UdHÐòªD| !J#u[!‚I®B—ħÁUɺ­Îì>þ4ËÞ÷2–GMà|è©qæËgðƧrìµÇÔ¯Qòã¹ûÙ¿=òc»÷£{6€š3å_>ô!‰‰D‚×|ë[œýË_bš&†aPUUŶk®á=Ÿýl¾!¤p¬vÝH2M‡„Šã8„ÃaÂåžC À¬Rzä‘Ghhh ®®.÷X{{;×]wUUUÔÔÔPSSCww7555#nóŽ;îðXss36l ¡¡ÎÎNV¯^MCCCIÛBLŒÁbÊŸ.êfX,ßd2¸”–X1Q×ß§Óp±g¡nlHeëët)Ûò²Ë¹@#jØÎÉû¨ÏÓ7S¸îÀë}áü+¦©êúñÁ®±®«’-©T¾G‹–HLÞn'“ÉŒO!ÄèHÝVˆ`’k§Á%ñ)DpUºn;ë_sâׯeÖâq¨ìÝpäÈæ¼<€¸ ˜sáäæOÉñP 7CŒ„²ñŸþ‰xACÇû~øCv}󛘦Éßgé=÷ÎNX»{÷nL=¼—6Yw‹aY–E*•"™LNjr¨ä!¿úG{{;«V­*zL'WFÒÜÜL]]]ÑúíííTWWÓÐШaÄêêêhooŸ´ƒ!ÄÉn°Ø„òÆg:’Ÿ?e2„Q=OFó1»ÌR‰3MuÓC ÕS%º¨GJØF uc„“-C¥¦I¥ò‰R‡êšT˜˜ÑC}éÄXáü+ƒî91¸Jħ¢4R·"˜äÚ)DpI| \•¬ÛêÞ)söìG¯ ïÑÙX>G€*øä‘OÒýŠn¬ßeôQ3…,&*‘EÝÅ;Û4ÙúÝïææÙ1w.±úz¡¦e©†ªt< /¼n¸¡’o‰B(¢­­mÒ{Ú””P©®®. Í›7ä‚ ¯¯ÎÎNª««‡ÝVgg'›7oÐ §³³s@Ò¦ººzÄ!ÄvïÞMssó¤´©Ä#ÿa$&^ss3[¶l©t1&ÄP±©ŸK|nÙ²eÄ. ž7¹‰}“Ñ%SffÉq_­«ozH¡zšèë¶K~˜NÍqn¼ývÒÀC»vå*:.¹ãàM –d·íüŽÅb¸®;`¬OÍu]‰õõõùmÅb¤R)b±»víâàÁƒnyãUc…ã@GGîîRÃ00¦ÑðÓa2úRµ´´”¥n[RBåºë®£»»›;͛7“J¥hhhÈõHéë룹¹™ššš¢aÁúëëëcݺulذa@o–ÞÞÞË—ÒelÁ‚E‰“‘B¨ðG7Ò&PwÅ×¢G+•ݾn(öP ½±ì¶õs'O(khh`ùòå•.Ƹ ›0öø\¾|ù€;Žú›ìÏñÑLRåº.&°#¥†%;á«Çnß±ƒ¯ôõá¯îîæ‚;ˆ¡z­ÔoþÕ¯¸­¥×uyûüùüø®»XÙÒ·gÌàÇÛ¶aø> vïfáÚµj½¦&êëësµ{ŸzН:Ä»wsçSOqÖ׿ÎÚ_þ’Ó·mcÃYgqåÙg“N§‰‘Íwüñ\ø¹ÏñW¿ølßΡœÓöï纠å’KˆÆãÜûÔS|ýÑGyè¡]\†žñõ‰‹/½«§‡j2¯~ýë\xóͤR)Þú¹Ï±øÒK=nžçqäȾûÝ´´<Ëþð(¿û]ù!ÀÒéô€õ=¯xˆ°‰¦ïœ™7o^ù^d’”#>çÍ›'Ã&ˆŠÑõŹsçVº(ã&u[1ÝHÝvx¥Ôm…(]·]°`A¥‹2nR·ÓÔm‡§ë¶#Ý€_Èæ¸>sÏ›Åü æŸ“ÅÇ«;P¡ôqØû1€{žx‚S¶mcÖì»ê*Î;p@%TL3?üF¶ÄtI¨X–…ïûxž§Ú¼¦Á*ÃYµjUYê¶%%TjjjøÚ×¾F{{;ëÖ­£ºº:79}{{;—]vííílذaØí¤R)êêêèíí¥½½ÞÞ^:;;‡ìÙRJöráÂ…'ݗΤFÕ€B%_“¨ä¬Sð“B}¶8Ùeaèá†b¨ä‹N’è!³ÛñPŸU6êç>[†ããetÙt²&è¦Ë—Îábs|._¾|Ø$«G¾—Ãxyž‡çy8ôÒë^ý{ƒD"‘Üc‘H„H$B}}=&°"ªza¹`|áÖ[ùÈUWñàŽüê?ÿ“¿|úÓxÀ'wîäâÏ|†=ÇÓ±x1oÛ°«V®äÈüùüyÍÏËâÖVêëë9ðÓŸ’ùò—Á÷±m+æÛ?@xñbfýÍßpOC‹sÞë^Ç{|gV®äýçœÃ¡ŸýŒyo}+_zé¥\/´ßÏšEõ%—ðñ÷¼‡½_ü"óÞúV–Þ~;?}Ýë b‰çQõ_ÿÅü¦Fž=±ˆ/¥`dzÕ,¿åÎùö·yúÿ‘{ŸzŠX,Æ×o¼‘6‹Åè»öZ^±a‰D‚ýË¿FÅfmm-MMMôô$Y¶ìç@š÷¿55ÿÉÙgÿ;é´zoûÛmD"R©ŽãÐØØH"‘`ïÞûعs'±˜JVþw£UUU5m*åˆOùÒ)*©¦¦† /¼9sæTº(ã&u[1ÝHÝvx#Õm…(]·]¸pa¥‹2nR·ÓÔm‡§ë¶¥Lá;=8CwøªÑc~~¹³3/ÂqTäÎs„rx/-‘HÎŽ?þ¼y|àºë8¶j+W®dÙ7rùý÷«ñÌuC•N¬L#†aày^®mlº'TêêêÊR·-iRz]€Á»V­ZŦM›Jþâ×××ÇÆx<ò½½½444 è>ÝÛÛ{Ò^uÏ=f¡3: &ß{NO¤mÿŒJgôßz»:=ŠÅK€®‚íëäL}öµâ¨ù(lòIšÐC¾·MG¥ßœij¨ØÔãb–+>'êÚT[[K4;«ºm¼ŠF"‘\Ò¥±±‘d2™»¸®K*•Â0 ÇÁ÷}|ßDz,Ça¶mÓÓs}–OE£¸®K8æÃoz¦iòŒëRõÌ3lðý\†û÷¿Ï+Þô&ÞXðÁýö]»XwÍ5|¤µ•Ž5kTœÎK8¦¹¯ÓZ[ñÙÝÝ|íöÛÕ¾œuœuVn†øÛ/¸€Ÿú½72cï^Êdxï²e}ì1~ûÛ1 ƒÌœ‰ÿùÏsiu5ÿtÊ)„N=•ËÞø[^—Y̶ǖ2¯³“÷\ÀÁM›˜·cí»vqùé§p×ãóÑ•+9xü8©7½‰…ïx€kx˲hmmå‚ Äq<þ1æK>•¶6›U«cÛ¶Òé%|ìc×\s÷Þû=Òé4Éd’¦¦&úúzx衯pÅC"‘Æq¾€ëº´µµåÞ?ß÷©¯¯§«« ß÷§Í!cQ©øBŒLê¶B“\;….‰O!‚«’uÛÐèÁïRpÆñ3é~-pÕHxB-óø’Ç9»ê,8‚j°Õ˜XB^à¦_þ’ç³ÿ`Å æ?öÏýáDæÌhöNÚlÛËtÖÓÓCmmí mg¢4%'T†¢ï”(…îÕ¢­]»–Ûn»-·¾Î€644ÐÙÙIww7×_}¥Ñ˜øŒ¹×êC$;Ç3¨DG+ÅÃÿ9¨$Ë`íÑ¡ìë넊.G<û*á¢{±ôORIJÛÕ#&ê$‰ÛoŸ¬ìc­Ùíèž&Ùׯ2ÙÇôúw—|2FïƒNþ„ ö/Dñ°b:­ç”OŒÏH±ÙÐÐP–ø4zÂóÑÐÉÞD"1à‚H$ð}Ÿt:aضM:&•J‘N§sÙøp8L"‘ bY¡P(׫ÛÆ-Z”KÚ@~¾’p8œËìÛ¶ëºììéáÄ›ß\tƒÄwÎ?€Žq:ž]à™ª*N;÷\6>þ8§Ïœ9ä…Í4MýßÿæÎ%õÄ|wÇŽ^y%swìp0 ƒoSüqlç|žÙ¾ˆžÝ»Yúše@>AzêSO±wõjnÌþ¿oåJ5¬ÙìÙ|ú¿à;òÈcñhw7ëL“0÷¬·²æÚã|¼}G=õ~9òÜÁól¶o?—U«–sàÀZ|ðwX–Åßþí:6l€ï~÷¾ÿýÔÕ½–O:Žïû$ R©–eaYžçQ__eY¤Óizzzrû¢—Oó O¥âS1²“©n+ÄT"×N!‚KâSˆàªTÝV·¡üüàAŽú ùÈÙ¿àƒÉ©ÕOöKás|Ž¿=÷0»`¡a6î8ª¡Â49üóŸã=ÿ<;_ñ nzÍkxñõ¯çüÅ‹á‘GT2å$ …¦}ï”r*9¡ÒÝÝÍÆéîªŠp8<áÝׯ_ϺuëXµj[·neýúõ%u ¢ªgE“ Š“#:Q`‘ï…QØëÄ@%ú‡öH7öëdÃPùÆùÞ ýéÞ,­ý÷ú-o<¦¯Ïn·°?“>z82?[~/»»‹Ó€IDAT¿¡ìï ¿uÒE?çSÜ3¦BEG%¡ú' Äø”#>{um !3æû>Žã …r¿›XKÏßÇscEÚ¶MSS¡ºêÆãñÜ…¤°q^/·ðøqÜÙ³l['Wôvt NshËμþúãÔy{iA¢àÌì¤ñC±²Ýz¶Mç‘#´|þ󼯶vðeûýâÀ,zvÌåà,õñ¯˜+^z‰g®».›ºWœœõ†7p.°èØ1¾ÝÛ˶›nb0ÿò™,0g2σW¼5çö1{v7»v-ç‚7Í`[ïL ,|Þð†Oð‹_À©§.á‰'¾CUU×ÛÓtp]77,›eY†‘ë–ë8N.fšæI5™Úp¦ÓõSˆéDbSˆà’ø"¸$>…¦rŦ¡ÇfÔ?fXæÁºÒb¤ÙWg̘A&“Éýèž{8øè£Ì;r„W]…¿w/מ{îØîî‚*ííítwwó›ßü&—y´m›–––ÝÁÆkª^,TÁ%?ïˆîU¢óõ`.ù>ª'E•4MÿžódQSØ¡p¶4ªg„K¾ZÏ¡ÅK¹ésb·;ò_:qÒÔÔ”{,‹åæØð<¯(9¢‡öòF3}Ú‚ÓûxñÅ9Ð×7â²:q© vGÖlCýè·@ÇÖùïW ›ÅçÍâa¸Ò†n~è™¶zßu•DBÝbYj~€P¨8¹’Në¡Â¬!‡ó²,‹h4*“Õ !„B!F¤ÛÉdј}LÏ‘«Û+¤éUˆò)üö~fäq–YÒ Ù!¿úß8=Ôì'–e±dÉ\×åÊ+¯äÆ÷¾—­sçž´Cƒ‹ò(yRú­[·æ&¦èîî ³³³h¹Á&›‰Dn¨˲Ìë ƒ_7ü5ÌÐT6Úy†¢çS)¥ŸÏ`ÃŒueÛ¨ŠŽžKÆ-X^¿3z1éN‘¿³Ä%?OKaýœNघìãã¡.~žW<Ì“V[[Kkk+‘H¤h˜§T*…ã8¹IÊMÓ$N%TÊ{³àà(æO«ùóU_Ž… –í5žq€—_~™}?=ƒ³ÞrVÉëé9‰ú¿]ú³Ï0`iH-÷Z žýÓ"fy³_}Ý.\eÂ=,‰Ã–ŠË;;²ÛöUÂ$=K:]œlK¥ÔkX–5`ø·AËëK‡|!„B!Äàt"TÒ$Tð7@-Óþ!„Yá·÷=ÿ÷*¸½àQòä÷¿»wS·q#---ÔÜr étšdr4·¢ 1¼’z¨TWW³jÕª¢Ç‚4AØdð×XÜŸïû8ލ†Á±Œ08Ô}âzRë¡ùU¨>Y'T —·È÷<)œ“E?W8&jˆâ„Jÿ®¼)¤ÇÊDÓCµ…Bƒ÷²ô}Ÿt:]4l—mÛ¤R)Òé4Ñh”d2‰az¨”ËŸþô'æÎ[–m~ìß¿¿¬ûqÞyçñÊÈŸyqî\Î:«´„Já<-ý´UðØò°Zî ³ ƒt:͉yg±¸Ø€:–dRoϧaÀƒ€_ÐkŠÿÖoq(4ëßEŸŽã0gÎðsÅ!„B!N.1T2%‰ºa34È2Ñ!BL¼£úÎ,®ß_üäbJ ÆlÛêÎ:‹åo;s·n妛nbÞÞ@[[[ ¢t%õP©««›¶=OJåºnQ6SOx¬{¤<û¾÷ñè£òxÃ0ˆD"†1 áO7ëáŠLÓÄqœAçzˆÅbEóLEzBø¡îì®×G){¬s “3úˆë×Õs¨è¹WB¨$‰î½RXý˜Ì¡R^:Eèº*©RH7Žëž^–e‡1 ƒD"AGGGnþ =ŸÑDÍ•2”°kùr–-[V¶×°€Ã\À ¯|eY÷eáÂ…<—|Ì…KK­ÔN±º7˜mBŸ¡z =·ötšÎ„þƇ¦Š”iÔP`Ï™jÝÖVÕcŠ“m:¹bFÑûmš&¾ïHªèa¿^óš×”õx !„B!¦Ÿüœª­ ƒg¸¤- !&Â.;pè×'X~8+çé«|üñBžMMÐÓÃ]ßþ6´µñ¿fÏæ£À7lË1gÄÄ*yÈ/­»»›öööÜ_555\ýõTUUUz_Æ-‹F‹†òJ§ÓD"‘¢qölÛÆq‰Dî.ykÍ Ÿ4íêꢾ¾>—<ѽLÒé4¡Pˆ¶¶¶ÜÄÙ=Æ êÎüH$’›l»««‹ÚÚZB¡PÑ]øúùɸ3<Ê=:aá÷úµúqZ˜ щc=~jÿ2N`/&Žã÷@Ð|ßÏ5†·¶¶bš&¡Pˆt:išEç|8.{2ÔP\Ç€E'N”í5 à¯æÏ§oþü²ÆÍ¢'xqî\Žu޲ßl‰ûLªùâ~mʼn Q½PLÎÉ¥n Kýí§A¿¥…C~9ŽÚî€×Ì~^÷ÿ, …B'í|WB!„BˆÒ¨vY¹W]ˆ`Ùî¨ùæŸ9z”EW­„]äõh H¥Ô™¾Ï_ô£¾áþòŸÿɺ|dðqæ…§QMJßÜÜŒmÛ477ÓÙÙIgg'wÜqW_}57n¬ô¾Œ[:.ºËYÛFÜíºn®1W÷Béß …rCÙ¶a´¶¶ÏöbÑÛò}ŸTJM–H$°,‹¶¶6ººÔl!­­­455åÊæû>±XŒÆÆF|ß§±±‘ÚÚZššš5<ØH,ÆŸpIRÚäpúµâÙ¿“é^.ºm_'Xô™àSœPÑ•01vª±¼.$•J‘H$r ÌÂD¦iš’'ƒ=V³f©Üó¹%Lä>Zƒ•¾œ •sûú0>²e_Û1ªõ†öÎäo«`=•ÀS)Õø×’È_Ü4=™öH ‡6J8&»^(ÊÍÃFsËé¹a 'pnllÌ %¦{¨ýKH$H¥RE •º×P4äØp '‹ŸlÆ(^['Pœ‚2ûä} ÷R*CŸº®ëg]]]¹!ò‚bþüù¯©aáÂòT’t')_%¿ÐœUÇ8òùSG]Fs˜ç``¯-¤ÔôÇ…]°žzOµ÷'àÙ…J©St"¦ð Šþr¡¶ëšˆ.åsU!„B1}¹¨ïY6€íéiS)Õ.‹å‹Åò ØÐí½…‰ ½^SS>)àºùméö&ý;;Ê<õõ*ÑØ¨þojÊoC߈V_¯žó¼|oÿ%KÔߎS<Œ²N †Ú®þΥ˪ËoYj»:‰“J—#‘È'ttâ¡¶6ŸxI$Ôúét> cšêqË‚ŽŽ|y´TJm+É—9VeÔÍbmmêØèc¬Ûç&Šã¨cW¸ß… /ýwWüøÇ§qäÈÄÏSz²ØŸýnoüÍÔç^q»žE¿6¾DBýØv.™‚e1kÖ,Þõ®wî&]1½”4äWoooIkhh(i¹ÎÎNz{{©®®¤éî»›ššjjjʶã±X Ó4ñFUÂjýq<]“*ÃÅ&LL|ö?v…ç¼[ÎÛJÆ¡fÏf/_^¶í›¿'#^f¿éE^þàè†üJˆâ;F “+N¿çtG„Ç©þû9.Ã¥>Dae wà_†?ùÉ»¨ªúÈI‘P™ŒøBŒMê¶BˆäÚ)DpMV|êQ(ÆÒ´‰@2©Ôw…Ô†t‘¶6ÕàoªÝ§¶VµE"*‰`Yª¡_÷ñ<õ˜aäF&"Rë¦Óù$N|„BùÇô½†…ÍT¾ŸHDý´¶ªÿõómmjÛ­­jô<• ¶­ç¸L&ó‰ýw}}ñëut¨}ŒFÕ~jVö˜D"ù×Ö “¦&õ»µµ¸mL7U¥Óù!Ÿ #ŸPjmÍ߬ÜÚš_F÷Ô),—.³>n¦©Êù×Ô½u|_•]·éµ¶æ×Óë2Y–*O<žoã+l®°¬í}Ï<³bÌçiÐLvݶ÷ `/ôí϶?ž)^f@kc(¤Þ¤p˜m÷ßÏ_××Fñ/¾˜ð%—ºä’JF1•”P©®®.)©ÒÞÞ>â*wÜqíííÔÔÔÐÝÝMCCwÞy'@n.–U«V±uëVÖ¯_?`ˆ±‰âº.¾ïóÀ§ó§?…³©ÃÝï8êÃß4Õ­žÒá})XŽúà‡Õ®¾°–Bû5Qãû •x1 ƒDöö Û¶‹þN¥RD"‘\Rƶm:::rà –0ñ"w{p$–r›ç0pÀ-[.Æ> &4š¬øBŒ^Pê¶Bˆbrí"¸&+>—0ºtâÃqòsfè¤É.>•€,èéQËë)wuƒ|(”oãÕ7Ø66ªïA¦™Ò+RÉ(îqª½É0òI„¡F>1aYª}ªðë´NÜè6©dR•©­Mý®¯Ï'S ïC3 •¸è78JîutoœÂ¤ŠÞ·x\ýÝ?AÑÔ”?V… ÷ѲTÙtO]¶ÂeÂáÁËjŸLSÝËFc¦Ë«çÂá|’ªð†èpXýN«¶½ŽµM=L™>Gô±+üZ_¿¿¬ÃŽM¦ŠÔmOÀÂY°`Ï«Øp€‘Ç×Ù<Ûfæ™gúÕ¯TÛc@Û•Ä4“)ÁsÏ=—9ï¼ó2=öØËÜ}÷Ý™«¯¾zØílݺ5S__Ÿéíí-ÚîÖ­[3™L&S__Ÿ{­[·fÎ;ï¼ÌsÏ=7ì6o½õÖRvaÓ43`e “éèÈdZ[3ÃÈdÚÚ†^§§'“ ‡Õ²™ŒZ¯§GýéÊd¾Ñ•ÉD£™L<®~›¦Zf8]]êw4Í´µµelÛÓþ”ª§§'÷Z™L&cÛvÑÿƒ ‡Ã%•+g,Ëʆ‘‰F£¹Ç[[[3–eelÛÎØ¶éÉ´®ìÎ÷/ÓD‰f&BG&“If2ÙîÝwß=llL#Åf&3úø|ì±Ç2wß}÷€Ç£™L&Ѧb§««+d¢Ñh(ûù?VÑL&cf2™‰=C•ŽL&3™{ÝÖÖ–Y⺙%®;ºõÆPNkˆuìŒ:žýéØ:=™Éœc«ÏÕeV&C4“ùt2“±íLæcêóÕ¶ÕçñÂ…/f€L2™ÌDû|(ó5"HÊŸÓḈ©m¨kÄT¤º­E궃›.Ÿ[bj›׈ɪ۶eJkèèPí2¦©¾g$“êw4ª¿³ªåÖ´eríG£¡Ûôß…ÿ¦§GµMF[›ún4¡ÐÐe±íÁÛÆâñ¡Û͆jÎikSÛmÙ’ÉÑ­cÛ™¢ïƒú=„Á÷S·íYÖàÛëÿ>ëíG£ƒooº\#*U·½rý‘Ì{Þ²'sþ™‡2d2™¶wd2™¨j;¶&™Ì|íž{2Éd2ÓÚÚšI&“™ŽÑ©˜öÊQ·-i•ššn»í6Ö­[ÇÆéëëË=×××Gss37ndýúõÃn§»»›5kÖPUU•Û.¨!ÅÚÛÛ©®®Î VWWG]]]Yædq]˲X³æý¼á Gr]0ãñ¡'Óò}Õ½1•ÊgïuwM€Å&œeæïJõ· 3•R‰ÓÂ̶¿2ƒûïÑ$ðz\IÏS¯Ý¬±2 ƒx<žë=¢çSN4-iìA=ïLGGÇ€aœ¢Ñ(mmm„B!êëësÉ¥Ói‰žç‘J¥ð}ŸX,–›«E /÷{¤9[ÊÅB ýÕÅÀy"¦ƒáb˜ÐøôÇ=!‡iš¸®‹aí¡åë•4`Ð23M“ >÷9ÎùÊWFµžŠQ½ƒßTb1xÙ¨óc±U¨ÏÕk“p© ½6,·à3>%ÓÉ¢E'Ôº¶»“L›.c¦Nf| !F'(u[!D1¹v \“Ÿzt‰a—ÉÎ9’H¨v}s{<®~ #ßþ³Ò†5ÑÑßü^ØÃB÷`ŽaiU =…Äh×j¾‘d’AGˆFUO“ÁžjÔ= ×h´¶Ž~ú[ýš¶=ø1·mõ~5ªLÿ÷YoC6]UªnûôOáñ'²hÑAõÀ ÀMMÅ“…Ã|áÞ{síI¦ij>^1}•”PrݸR©—]v¶msÙe—qÙe—±yóf6lØÀu×]7ì6®»î:Ö¯_Ÿ›¼¾¹¹™ºº:èìì0ö^uu5ÝÝÝÃns÷îÝ477j§ÇaÏž`åÊ÷ñÉOÎÇ÷Õ‡£þ@ŒÓ2ùjf+¾¯Ö‰DòŽE"*îkkÕÿz,GË‚={ŽS[Û˜›0,‘P]c1Ýø¬¶?‘Ýuâc¸¹YFóFssÓ¾†n(‡ÃÄãñÜ$äŽãN§I&“¸®K}}=†a‹ÅðFàDAb{‡)~df `Ã]Øtz°sç|ªªÞ’MÌå?»»»innfÿþý“vlË¥ñ¹ÿ~𛛥áh¬ôçK~LÈá>kš|̼“T{{;étšTº(㔺­Eê¶£¯Û 1tÝv÷îÝ•.ʸMVÝÖeäïozŽ P ëmm÷÷¼o’¾¸e*ÈÑ&z†J4Œôú£m«Öóh–[8\| ô> õÚ–¥ÚÝF“‰ÇóC²’ºmiuÛá–{ùØËœ8~‚ÓfÏUÜÈà ¾¯Þ¸‚ñç,Ëʵ1Ú¶=íæRãÓÒÒR–ºmIs¨hëׯ'ÓÞÞÎÖ­[5}CCCî?R/P•7ÒÝÝK 6GK)“-X° wá-ÅoÛKss ^Îÿ·ú Ôc9Þ}П‹q4q©3êétþÂÜØ¨.Ô…ã-F£ð…/Ì££c1O?ý¢QÕ(¨o®ŽDÔ²‘ˆZO{Yø!®.zœNÝf°‹‡çåÇÓi’û±Ò )ü@3 #—pI¥RD£Ñ\ÏÓ4sYe='‹eY¤R©\bG'X ·‹Åð}Ÿd2™{¾c´·uŒ‚N­¼ê*¼it{Â`± cÏåË—³jÕª¢Ç< 5ª'ys1M“T*•{¯,¬çÒp²ÿ'FvsHï‘@Í:èdô¶jQ­ü£Ì´…˜Ü¤GÝHÏîCzòëÇ T¥£•ýkË®ï1¶YÇÉdð›J†;–p‹¯ Áöìcº‡X$¦î ûÐ’P=WNý»\ÒU=`;úΙ‘zàM%ŸóæÍ£¡¡A&àÕý¤(®°û¨Ï‘xö¹þ]ÉbÙÿÓä'Ör ÖÓ Àtv»êóÊÈþ=Úî^ÓLMM uuuìÙ³§ÒE™0•¬Û 1‘رcG¥‹1a&£n+ÄdÐuÛ_ÿúו.Ê„)gÝÖGUφj¾‰Åò#Ž”:ï-L¯¹TMsô½@Æú:•hß¶¬üõƒí§iæÛ×J‰¨e-k`o©ÛO×m«««‡\æ”—Oaé9ßá¦ê›Ø<Ò- |Ÿ—¿üezÃa\×Ŷmé™"µjÕ*~õ«_MøvKî¡¢UUUå2–ëׯÏ}áÓÁVŠºº:6mÚÄ<ÀæÍ›iii4°FÊr,\¸pT_:?úÑöîý4wÝuÊ ™õ¡²úzè­±èèÈo·­Meµ£ÙeýsãËxÍknåöÛN4ª’)ºËb[›úß÷ó½%Kò=_"õ“H¨ä ä{¸èIÀjkÕúzB°¡ºvÕö¨‡,µ‘Ú(u/Çqô:°m;7tW<ÏMj …r ê¡Pˆ®®.’É$–e‘H$…B$“IºººhmmÍõ`ÑC„éÞ.–eåÖÑËiét:—ÌÑëä÷½´†W‹|-|é¥üñ¦›ÆvbÐ`± Œ9>—/_N]]]î]©Õ‹ {/%St‚ …j„t²ÿëß :Ó/æ‘‚õ}òcHéÇBä,Cq´¦u—¹Þ^5Ë¡~íDÁsCÑûÔŸ^_¿nŒ|ãlaãk$»¾W°žÞ7‡üðfÁ2ºa—ìºÙIÏí;·¸‡O#ùäM,û?ÿ´onÁñ#Ýfý^¾ËÇz‘È7Ž«c­Ë¬z•´¶¶æ&šïÑ#gáyápT÷ÒËÿþt¦01£“&z^•¶¶6lÛ&‰ …ˆF£¹,µNœxžW”|I¥RD"‘\"f¤!Ä4}êxLîÜå4\lŸ꘩¡™ÔÉ8`˜¯ª1_/Bt•XðP=/ ùÙe{È •KŒXä“(!ò½;"¨žoUûŽd·é¢’&±‚çt¥Lßµ®YuíîUSp^çèÞ"úïúìz:IbO&éf”'N>)äd×׸VvýÿßÞûÇÉQVùþÀ„„™Ô€$!Œ‰5À TqP©"«hÖêaý±&»›îõú#úÚ¹v_¯ ‹ëw»evÝì޻ؽè.»Kº÷²².o—"(êTDÈSšÈ3ùýêûÇÓ§ªº§{¦§§TÏœ÷ë5Iwuýxê©çÔó<ç<ç;¿y¤q‰öËŸ{ñÉÅÞ÷âÖ¯žHé\lo´Ph`¢û˜€!ˆ÷ÊB_•ÐoÙà3E[x,ï °|ùrHð¼çõ ]¯mxÄfÒ(ù¬;–ïÿ© ›Õ@mðFå¥äŒ"T’3’]’‰<Ùà…”ྃ¬ßÖSb{æÝ€ý_Þõõ»Ä¾æ—€Þ¿Œ¥@ü. ¾0þ…á ˇÞ0odգ𠰡:Ô#3-š5¶efrfMßÉ0³FȧÏ BÑ;(šG"!t²ˆÑ´ÊC¥©je)ZfŒmubËÛcù+ËÅÆÅ“H൮.<÷Üse¹¢ÜÐ SkjP„pRRûññq7_OO›äq3s¹Ö­[7ãk’Òý¦›vaÙ²eˆDÊ'Ì’åÒ.yh]™N‡®(¢œ”¯…^êäùB±‡†¼„^Ù¬è0È oÀOÜ Ãðò¹ y”XLl—$ï|²,ÎGe¥œ†Q¸ ‘H`tt4ÿryc<¯`×®¾¼‹g ±mq½b£Š¢(¸è¢Ç]å¨ÎLNR©dYF,ÃO~²Ã™‰¤¡ª ×` … Ë2 ÀmÛP‘HÄõr!o•p8\ð2¶Êø€¶èÂಔ“M5“O Bo©(žw ­"pC¸Ñr" ¥#A(c˜˜‡3& k*“߇§<£[ȳÂò‹ÂòPà]2œø?ûã€I Â$£°‘Dõ]ƒã4±á‚É÷?u×.¬zÿûljD0::ÚìjcæÓÊ¡2Súúú°}ûv¬_¿عs'Ö­[‡¾¾>"GËæÍ›±fÍìܹýýýe]¦ƒmÛ°, óæ=öööI;ÍɼW‚F$2Ñø3Ù½[Ò# ·7Û¶Qœn$˜‘ïœþP_EN'0MqŒÈ‹áÅ"5Mq|,&þ§sŒŽ.ÁÒ¥×Â0„Dz„1%ûhš·Â\’$\r‰0¾¤RžM"¡¹^3šضìžCQÄ IQ€‘‘˜&ËGíííu•ùš¦!‰  AUUX–Ó4ÝßMÓDoo/Òéô„|3¤Ã´½Ø¿¿ÙÍaFL%›@íäsO¾ÍZ–å…û‚Y’=#„ ¡\¥6;Ræd´ª\Aá—¶“§…¡hMÀ[iNÞ/…×¢\%ô€cùÏdh 0>ix^*q׊p~h1ÚnúÊIŠ_ Du@ ž÷ 1ÂùÿÉû† "†ï\t>Ê5ã[¦µ<»;vìÆªäÏKÆR0“‡ß@bA(±ð”Ù´¢Ÿ×Rþ{Ð 2ÓŨ*ðý|B”ŸôðGàU;_’0ôÎ)Ÿ3F‡hÔÞLˆv5ѶIοw˜¿í…†>òŠCé<~ãíCÛ-ß±Ixy†@ì€ù5aøÀy@Ìgœ %X7 °^ð댫ë9 õ÷€p+ ˆ(@èr ¾ÐnõåM»ÐòåL$| Юä€[ùw@&Xi ‘¯«GT§ Ò„/RŸ¤e€þ€ùÀH06Ö(˜' ;Ö€ü> ”"Ÿì3D¿H±Â+{.Ѭ±-Ã0“ÓR}'ÃÌ1š!Ÿ´ u&ø£*3Á‡þ뮪%‘(ŒÎ2[iÖØöÔ5Gqîø¹ÀêƒÊ‡6ŒÇãÐ4 öë¯Ãúð‡¡­Xá¦`˜FR‘Aeppе@–ƒ¬—SqÇw`xxØu ó»†õõõ¹ î‹› –eáÈ‘åxõÕ£¸í¶“î«ë¥“sÑ´ɽdYžà‰”OÚ% Sañ{¬øÃ§Œx(šœ~úNŒŽ^޾>ï>¢QÑI%“b°£ëb_Ó†Êÿ¢ª¢ †!¶'“˜‰x.›É¤Xqbš^þ˜¡!á-ó¡ý1î¼s::ˆÇY–022‚/~ñ/ñøã¹£J<Ÿ˜(žÞNðÀ,ÉÑ0™lµ‘O@¼ç'I`ß=í»bU:…ëÊ{L )RÉ@ƒ%bhúŒ† xJY  @Fò$¡ü,d´ Ô”DóýFÆ ž mH¡ z³$}ç‹øŽ¡ÐeÅMΆЬ’h¨h{ žâYòÛo`Ñ!™Àž…{DüeòØ ç뛼zèÞz11¼à)¦ýå$cyðPùèõâ.ƒç%P†|޹‚ÃËlXªûòÆ´',àê|Ûçm<æìrÇn„|ÎzæÔæÉ éOÄNíðò‘ÁƒÚ*H-ÊI¢-fàIó¡ßÜkúe€Œ(š¸Žý( EòÇ¥!Br ˜‹y!`Ïô§€ä1aD‰œ HËHQ;-˜åeÃ?I‹ü¹h»É0óMÞéÝ@þ”(—”ψûô½«ÄvýV@¿SsFFòž¢Ò-@LÔ]€t }Xo´¼l' _õ–X `/Ú)úBZð`Ûâ|ª*Êæ_+@ž¯ÌôhÆØ–a˜© |ßÉ0s˜zʧÈIL7W 3{ˆÇÅbáZœg®Ðȱ-M;£Çðùë®/ü¦wbgë|R$âFÀ¹S˜¦P‘A%—ËaxxxÊý*M 9Y"¿z f-ËÂøøZœ<¹ ª:yÖdŠhâöé$ªj%¦ûâ™Ìð«(BIcYbÀBŠ á%I^hžåËàÈ‘%Š›¡!OÉC^*~ãM$â%#O—HD\«x€”N{eŠDD¹u]t‚7ÞØ‡Ý»—#›½²,Œ/ŠìØÆOºK—>]¿wÜqÎ9ç‹PU Î+¼×f?¸:1U’ÍZÈç1ØkûB©…K·_êȘW‰Ì©âx¨(ôP!ÿwBÎïOçÏúö¡åàþ¼+´ž”Īï| cÇMgßä6¢¾s…á…Ë•Ãôƒ ^ä©C^Aþz"E¹ßøB!Æ&Áï}W,k™ p†,—}yÃÊC:ðy£Ô%¯Ë7f—AhŒ|V…ªóÓH¾¢ð<¤ü!ï,xmߟ[… )ÅáèÌ¢ßósP’€åÆ@ĬËèó€<(·É¼GSöÿRÐÓ€qø VÔF´ßÑu@D”IŒ~å(^p0©7ˆ/ ‘­? Ö£@â“¢üÔM›ÂyïQõ.ßyÈ»Þa1xÿ r ȬÆ–DVüF9Õ¨ŸÖuaä¦%ÔŸ3•Óè±-Ã0•ؾ“a˜ºÉ' {{Å—Z¥VxöÙg D"]×aY4MƒeYÈd2H¥RÐó1ÐcEƒBÛ¶‘Éd rÁÒw:Ÿ$In~Qt Šž‘Éd`Û6"ìnÌ4€FmÿäLH6`_^¸½`­a`éÒ¥î"hUUY˜¦Q‘A¥¯¯¯Àý²ÕX²äc°¬oâ’KþeÊ}‹¤ØO&ëŸC%è‡ÊdJJÊéxûù÷—eñÝ0î…eÅ Ün©î CÔy©ú&ÉmO/?‚$yJ¢M›V££ã?ÝU ¶-”J¹Ü…صëm¸âŠŸáÊ+߇ï~·¦Ù MÅŠ?Cg'ðos Š2ÆEFX–ëjÿÛçžÃX>O6{¦0ͤ"ƒÊøø8r¹Ü”+‚ˆeYØ·ïjȲ‰}haEÇPRW’ÙZÅ\luE9fòÎR/l—e•îàeYìã8åÏ#IÓ/y¿ŒŠlöËÛøýïOE4ª¾ì® ‘e`ÆG022 Y C¡C:ž², ÃGßñŒýþ÷8ðôÓ {­ÎÅ).‹CHU y“Ô¢/õ+#ýrÇDE%Q.¿ )…ý+ñ§‚üYK‰F9o¤èø©ÆÍ °÷Œ½8¶øXé\+å £K :2¼ò€ðHÈÂËC4…f¢Ï“<óâ[¶,!¯W@œ…,.¿\†ó§=jK’€¬Šv¶o_…uÏTyi‘ “QÈ·³Py ˆ}n;ˆïby¯ÃÌÿ´n@ºPÿ0m@ùù"`¾HÌB¿ì—€ôÇ€Ä* ²Àj@ùýGˆ6Rº3ñú¯ŠútÊÓ`²YV~Á@Ñ¢/Y® \E±ÐhÆ.2¼æCùEþÀ8`÷Égô'M”}y»íUÂEïkÛÆ(ÃÊl¶yÍEè½Jcªâ¯x?†a&ˆ˜^xÓt¡¤MÓ„,ËÈd2H&“îöT*I’„Q%Á_=ú(dYv=P4Ÿ¶ž¶†x<î]z{{¡( R©âñ8B¡EA¢Ì T×u„Ãa$ ¤ó…'/*S1ápñxÜ5ÆD£"2 …x'ãM$*ɶm÷<ñxÜUL+ŠâzÁX–åF•˜O6oè¡:óCe•$© oªišn~cÊ_«ªª[¹Æ«whN0ÓÜ9D<^hœ±, º®»u“ãŶÕc‹-$@>Wl*hqñ¸˜0 á,ÃÀYù¶Rë6Ã0Ó¡"ƒŠ®ëÆwÜán@___à]¤ ÃÀ¼yïG6{*$ijaS/Îx,&ÂPõöÖ&æbP©ô%$Ë3÷Ò!ÏI’°lÙnÄb+&ìC«ÐëÅèhùߊ'² ,_¾?ûÙ›ñ¥/íÅ¡CËðë_ïÚ^:€ùóˆöïcñ‹ëWàYE Ràõ_½>1™|5H(Ì/2Ê)PCA©ü&å øÓ1ôDà%y/¦VcØÙ~|ñ©/ŠïÓ5dE¦Ø?ñº·¸8^UK¯$²,á-Hô÷¤„.ð9ïhÀx›V»Á33äÙ%Á ©GùȨÏèèÈ{ŠÜàç€r1 ÿÐïŒ_ˆ‰®²°ï ˆ>hï’ß"ïð,Ú Än´'ékâz– ÿØ+€ÈÚ©=(+‚^TMÀ05dþ)ïURDUíä}Gy‘b€|¹P¢€v5 †ÄoÖ@_¤O‘ïò5â´ÐÄﵫ랑%ãa­‚m‹1.-’éíõB©Ú¶gx¤UU]%;yšñ$‘Hü^ŠH$âz­Ê«EA2™D6›…¢(†2Œñ#‹Á4Mèº^pŸ’$!“WÄd2™‚f†a@Ó4×€L&ݺ¡sضí†<<=…2K&“î¶d2 EQ ëºëDבeCCC˜)޾V!ßD½Pxj ¡PÈ­Ó4‘ËåpÍ5×Ôîbs,`á PKÌÙÈ…>¯¬í …\.÷Å4“Š *¥Øºu+zzzZ òo\Y¾¸¢ýiõª±åö˜­Tê&'Ižâd&ˆ„ä2~ýë#nN?´2(¬^}¯¼r~ðƒ¸è¢_bÉ’ocçïàä“ÇpÑM‡ðøsíÀ¼¡TE\$D;¢µ14B6i<:à ¡ÄœŽREé$ðµÄ>wèsXµj•¨» Vl0•ü“GŽß …ŒKQƒL<Ÿ6„òšÆAù¼5–%”µÅ‹¶ü+¤eÙKaãO¿Uo©âTf/pÞyu®Ï¹LD{(2²™¦'ç’$>“!;‘Ï—<cÿC(deÀ_Š?€–÷~ pSšX瓹û$Àz °/®ájyÍ ùß„¯2‡Úʈ@„ !sŠç™‰!ß+à‹€z“€µP> ×k.~о(G£â¹K’7çÍfKå(ôJÆytoA+Ã0 S=ñ¸èãÊéåmÛv=&t]ÇÐÐt]G$)0¤T‹ßûdd¤0¤A%¡¸RSº%¢ª*t]/ix‘e²,»ù&dY†mÛ…Be©TÊ5t‚:™Lºu]]]®±Å²,¤R©‚kY–…®®.Äb17G „ººº`YÒéô„żñxªªºçE4…®ëÐ4ÍõžQUÕ}^’$Á0 ·ldÊf³0MñxŠ¢àôÓoÀ½÷~+V<ÃØí͉„û܉2™Œjå>”׈BÛqž ¦™Ìj-p&“Á’%ßáÏ“@15›Áµ×¾µävI Ö WEQðÆQ=ÚïNòßñŽ_bäÖ,z4 ƒãñô¢E¸®ÙmÆM`¥üóßÿ3n캱vÞ%*ã©2]òác뽨ƒ’“Ó5{!VÊËaÁHɆûEáÑ,û¥Äó$¡ßs… *ôš§i„ànXΕÚb@xÅ Ú¶ÏøL …$å+„²µ|Ç×Ü+bª°v­†O0Ҙܨ¢#¯¡Ðs @l)9"R¿ Ïxj‘_¸ȾÝ‚|Î1O1M¹W8']}‰ÇE=¯Æ%OÿxXQ„Q£®SÑy Ó7òt‘eaTñÏieÙ æ÷6#2ŽÐùÈÛ%“ñÎCe…¼Ï½½â¸DÂ[|z¹~2Ï`KMóŽ7 q\*%Ϋ(Þ{ʶÅ~ÑhùІa˜@bèö/&ñaÂá°ëY˜e“©Â‚SÊø1~¯•bÊÕ'åm™ Ê­U6›…mÛ%ïÉæ‰Ôìb ÀI[ô…«~° «c«kwò .&šyè×úQo”ò× å¼—¤?G’lw5Qæ-¡Ø5¼ò–ò^ó›„5ßÿÿ=¬ç_µÅ„xf6\¹£0@ª:1|#(g´©š&ô).sݺȩÿÏV<‡ÉÒ@½07ª/Eš_A e÷‡?܈„B¢Í”2¦¥#¢m:hZ¡ñRU=ãGñÁHDÌc1/ߊÞ‹ ¯òš¡óF"Âcð¼gèž(Y±|ÄbÞ1”ûжÅçdRcÛ^ø²bÃ’¿žR)±8\hf†aZ À^³´·{2™tCcÔ|ÙzȲ2„ÒÖÌ—ƒbvQ®•kìБ/k^¹¦ªù…ó>eE +5_ `Ï96àFçq#yù^‡5É9ɈåꙌ8Ÿrа*”Ã0<£iJ)VOñq]]ÞgÚ—kG"BóßÕå%R0Mo%ToïÄkS"ˆpx¢æWÓ<7‚ÜwЇåÖm\œ'Ž)í5É”×2×Ò-ÍG¥Ë5SÙ)Èf%˳Åèd þ ÈüPޱ¿ÝþæúßÏ,…<5z{EӊżÐVA÷¨°bÒéÒ†“ÉðÛRe¢]U’&n+ÈáT´¯ßÎJ¯¦x¼Ð«'m½·W|¦?]::¼<5?èùQn›xÜ;]ÇûŸò¼ôöŠ¿PHœŸ^Cɤ—7§Ôk©˜dÒÛ"i†ØÖÕ5}Ï%†a˜ áØþõ.†›äœB\ÕByÏÔžVx.RɰÔì¥R-€ç àåÿS˜Bs$_¥[–˲ؘ‚ŠTg¡÷¥ë’(ô@‰D<412âidy%zzj_Ÿ Ã0õæQx. |ÛgPÑuŠ¢px #Ër]¼†h¨_ "¯Oõ—{ªü0Lyt7x´£ÌEF66^1AbÖæP±, ¬n¨A…m¤³—rnªªâ‚ ÂK/-ivàš°ô'/b7 ËÜ`²í)xÆ”x~ß!¥mÀåþ_þ;…>²€ÈU¨X±û•ðûfm7×\{„QïùUÓ´ÊšÂëL€´„äyáOì@K¢ÉXáÉCvqÒÊ&-ËÞ’|ÿ[’ʳBž~ôüõ|J­ÿì7¯>ØìŠh]z{…òV¢\7¾úM$J$»¦„ Ôùú '„¦•6tøµ€@¡¡#ñ–_«jåÚÓâ,Ú@uÉ#TUÜÛt—Û“³˜Tªð^óçÕãâRʲ݅±©nÈ bÛžwJq™üîñäíCφ4ºufdij%“¥«íæ‹aëYcu/Ël¢”8ÍF‚"“" 6`] d’â·’IÓ‹½7üÉÙ M›þrrY. ~*Ê-ë®fÒã8Ó?¦ÜuªY…ç¯p ;æ??-¿³,¯ÎýZÒTJa‰Ò.ôÀk4ë$…p9ÆÈ—G°à©5¹VhÄØ¶š|$Ló rR{`¢-{¶Ñ输a˜Ê©‡|¾žL™œ› Vt·µ4zù!OéZ1—tùÛÀ $îybâïÃ781MÑh´ní„aª¡¢¤ôÃÃÃØ¶m¾ÿýïcÓ¦M¿uvv¢¿¿}}}¸ùæ›§<×ÀÀÖ¯_­[·â–[nÁúõë1>>ضm›ûÛúõë±mÛ¶ªoì?þãÎ;ïx3ë–™ÅÌF«ød² Ì\>-« ýÖ4ö_¶¿Ù·Ë43 dæÿ"ùs%}ßã(\"&AT|ÄbÀY¡ß7»jB½å³Šâ³aXb@æ)_Ô)Û^þØ0ÅÆ”RÞ$æBlÛF†bß”Òúõö CA âñø´ r¨4blK«VIUf.Ь¾“a˜©©—|/g±,«¦*ìëÒšÔʦ‰”_—4›h¤Þö  ¼ýÞ×p¦”WML"U ahh’$±‡ (*òP)E__úûû ¶uvvbl¬|<ì\.7Á0sýõ×cll ƒƒƒhoow]ɺ»»ÑÝÝÁÁÁIËqðàÁ’ûœ8qgžÉ!¿˜ú!Ë2±{÷îfeÆL&›ª–ÏÝ»wcxxpÂÎëò–Œ6ôÞt]/P‚ZùžÉdÉd ë:¾ö¦i¢··]]]0M™L¦iBÓ4Ȳ ]×Ç VЇÃad2†á®§Ï¦iº èè4G¥Vé'“ÉiÕi2™¬nµ¿/Ša@!O” g5r~Ÿ$ Ç/~1Œ}ûΫÙskõÏ£GbppÐuã.…ý > è? }º›úƒ2+'‡ÏÇ]ƒE8†aÈd2e=7Âá0ººº‡!Ë2ºººˆ÷,!âñ8Âá0z{{ÑÛÛ ]×ÑÑÑçoº ¿Z¿Þ5>š¦‰ÑÑQ ahh¦iºm6 z{{!IR©”»zѶm¤ÓiŒŒŒ ‘H ›ÍºíœdR–ewb®iEA6›E$A4…®ëH¥R$ †a ™L"ºòjÛ6’É$:::L&Ý{ñË);ö”{LGGÂá0Âá0LÓD(Boo/Âá°kzúé§±ûðáÊU~²âa"ïáú`¡ðþ1 /|X V†år9<½èi,~eñŒÏÕl1¶5M!jµ„i<¶­|lË0d||ƒƒƒ8xð`³‹2cê5¶ý§áaüÕëeoÁ 3·ÑõòyO¦K¹!°$IÇ“O>‰ãÇ[?JN=Ƕ~/4x.œµæy¼pî bC&XŠÍ&á2Ѧ†‡‡ë2¶­ÈC¥½½}‚¡¤Øú8>>>åಧ§§ öÞøø8¶oߎM›6axxxÂ9ÛÛÛ'UöÀ¡C‡0888!¦ßÉ“¯LîÞi¡pås£kSRe3í÷õ¤ài™í "•Jáî»ïž“ÎÉd@Õò¹{÷nìܹÝÝÝx̾ÚìY¸§n÷a Ã@·Œ—”±º®#™Lº«hò6ŠÇãÇUƒÅ9%L£•ïÉd’$A–eW±ì7Äò+¿MÓ„išH¥R„Ñ%N»Š]z¯ Á¶m„B!$ Äb1H’]×ÝùTdI$PUÕ]åF‘J¥‡ÝÕõ´ê#CÓ4„ÃahšæÖ ¹Û’˜&*~];›ÍºÆªÞ< ÙâHßÍÿ HA¼Wc,`lÞöîÄøøÚºµ·FQù$ƒJ¹ÕD–h¯ò@äy±Fb1Lé}BîØº®CUUD£Q¼ºr%þòða|ñÓŸv÷£ö ˆ6F‘N§aÛ¶Û¶ÈÃdŒ,Š¢@×uÜnYÀóÏãŸû”G'Ô|›*([À_ú´D:€T: …)xU… ?—ñΧý´ü½[ô]–q÷cáÙÿ†ªBVU(þå_âž{îAߎÐòûZÒÝ¿U>~ê·?üá<Œ‰ ×4Í­ƒP(„t:í(é÷Üo üö·xç±c®¬Mú>£Õ]S­òÊf'Æ6‡E,¸()r¹9þ:ßÒ‰wãÝUŸ'4bl‰°1…i³Å Òˆ±-Ã4Rf:t¨ÙE™1õÛ>ùä“Xûßß ]ÿÛ‚ù3wQ””‚3a²„ôÀðð0ÚÚÚš}Ë3¦žcÛÎÎ΂::aïÞýs<¾èãbC>ò@13ÕÓ0s›;w6Ï rýõ×c``Û·oÇõ×__r]×ÑÖÖV2™X)¶oߎôôô ¯¯ö©ÄeléÒ¥ŒôáîCªþˆm»a·lUÅéË–á“Ë–á›n¢K.Aîê«ñ•7½ ™JaùÛÞ†¯œ}6¢É j-Y‚D:.cH,~€®(R7uNJQðúŸþ)^{ç;Å=}ó›X{ã¢ü]|$<àuÙ }ûÛC ¾{¡.›2Hùc xNRjþÞé¼Ê7¿ é›ßàZüêWqf<@D©#É¥:“ÌÿáÑ{â>¶d ¾Ñ~;`éîÝøÀF ©tÿãßÿöå—CVŒ¨*dYv :@Þ0œH¸ï5Q¥÷=DÆ[@ôÑ´]Ó4(y¿Â¡ÀøYʉˆ%z²ìÅP°,o¶Z.×+Nµš­Õ¨ÇØÖ²Dj›¢È S7xl;9þ±-Ã4Ê];Û<¤j9¶Õ4 ›zK1ß©eþ¦5‘¤Ú…üžO¥[³f ®ºê*Û–¡¼ÞxmÇk8ãÆ¡â,ñ°Š,W¤§œ+zF¦öôõõMiô«†Š *Ø´i6oÞŒM›6¡¯¯ÏJX¿mÛ6lÙ²eÊscóæÍÈår¸õÖ[ÝIu{ûÄ8Ú¹\®ªÕ?â%§ -H âÿ„Ö„V1§óßÉ;„âñJ9ŠŠ#ÃÓŒHùó%!4(2pâ_OàÈmGpó€øB@öÝ·Kí¥€˜Š‰î…ÝX^€'ÞýÎÿéùXxîB¤>–·¾þ-W‰qÓ÷n‚®ë“vü¤ì%E')tå|ìøT*Ã0\…,)+I¹JçÇã$ ±X ]]]n¬wÿêyZµŸL&‘H$ÜÕ±½½½PÅ]LÊWRªÆãqd§˜õûW«Û¶ízPÌz~Q6‡r² Ì\>mG,Ë€ùWôI3ŸˆR®RøûÛ …þQUÕ]ÍM |2’X–åþFFAò!£"!¸^.äéA†24D"¤ÓiD£Qضí6üžþ@q;'4 £@YJF‘rMÓ öJ{“Ññt 2‚Äb1·,þkðŒ6~£×%I’[þJÉ_ïäe@Æ# ¡ÔÛÛ‹‘‘7$’mÛPUuò8©”,= €^;¤ÝΈßÏ:k€·Í¸½5›zÊg)´=€™Æd^X÷ÃÐS‹0þ?oB|åJÄ ôBt—w>õ~~ñŸýöÛqè»ßÅo¼SO=+ÛÚð=ˆn÷OÂa|ÐqpOOÞ–Nã¢'žÀ§®º ·µáäM7a¨­ iˆ®8ñhÃZ“Еÿ®æ?§Ø§†{þó?qüøqh§† ÄãOÁ]»Z6`A dxF–ˆï\„aEÎ_? ”߃¤òe1óåËbrÓÄi§§&>û¶ëùû„-ÂÓùrüêÇašÀ9_x ?úÆßáµ={`ut`ùµ² 9\*.’S¿¬Ð¸€>'“Ipe1‰ ž7ôž“Œ¦”û(‘ëIU…A…ò®Â=_QÄ(ó¼—l{Ndï¬çØ6“©"À̽²i¡‘@{W3 Ðø¾“a˜Ê©—|î5¦»ØŒaj5UÕòÚ³M‡Õ½-±úÀjÌù žÄŸ‰9D‘A…£LP©È ˆÕJíííÐu[·n-ø­³³wÜqGEÞ)6lÀš5kpÇwlïîîÆ¶mÛ ¶U•ØèW¿z’d M ‡Ð‚¨áa B[’ðí'í“÷8yè–‡°H^¤¼æç}Ú³Æ:>ŒÝ?ÅSêSø«ßÿþÚúk _9Œç¤ç`«6’ÃIhWk8råÜ}÷Ý0~b¸ vMÓÄ¥¯_Šûÿâ~\øÙ ]/ ñCÊRš’±Ã¿J>‹¹ûS oD ZNÊÿjvÃ0‹Å ˜†a$¾VÅU@SYÈCÐ t®a†Â½P™)¹0í£( lÛ†_ÝœJ¥ <jLŽ)M9Ùf.Ÿ&€w¨@ìIà ¯×Æ ÖoœÈf³H&“®çE&“q=Pb±XA¥ß)¤ZH‘OÞ¡PÈ5Äãq×0/Žl6ëz•PH.ò ”âðcÚ$!’Eqó;Ô3ÙNÉ€S )býå&cÕA^ +æ_åN˜x<Ž¡¡¡‚wƒ,Ë^nôN##’~—òò*Î÷GßÉ@Q2>X·úlõ”Ï X€u0ú}ñU’€žy?„uï½xøÁ±5.pðÜ×Ñ7Þˆ…õWø¿mmÈÀKscBt»Ÿ72€Ï%Pee\±o®<óL\æsûÎÂ{”$©ET}ûÙçÂèáì@¿S«ñÏü6RâäÏEÀ3ÌÐ~þã¦K¤è3y¼¼W±aÿ¿vüüóOá1ã1\ññ+pUŠkLð‡Æ¢;nœø8ðŸùèÐÑÕÕ…t:í&É5M±XÌ5:H’Tó€ ¤p¤F¦i"» rÉx¢ªªkáLÁKÆŒbüÛJOŠe*mÛ®±†ÎKÊnZ9B!›(„X,s “QÇ>:?S&“ÍZÉç.üçc8ãcgT|L)¨­BIHÉ®S©TAÞRÈãüŠA?’$¹«¶#‘ˆ+7äÅAצÔÜíôàÊz*•švD"u5¦Ö¬8œ•ŸBŒù)ÎC à]Rü;®ükô¢ëøC{Ñs$¥ïèè( Ã@4u6ŠŒÞ‰¢ð4Þ) ¸‘[™Fȧã ¢úˆX èŠõá^£W\±SOEÀ‡þò/±¢« û::ðâ=÷¸ûû%Žkèðµ·Ï-]:áÚÅrø÷+Qw¦ÃnÒ ×¿ÄŸò»0~v§ËG õS/Œ™¡Ï¦peYx=´ŸšJáÜîn\y䈻¸¡ØŽÂ~Òb UU1::Šd2éz«W õËõ¿ÿ7þ¶qãñã¸ùæ›À5.û=Þ ËÞ 3Iz{ÅçTjVÍDë=¶­$ܥ囀åÛA¬Àø  m¤ S®EÎ\ôþ9 Y€ö ˆß (‰Â÷4À>X§vþâù ÖqÀXHKÍŒsl°ÀQ¯Ö#€´°ÏìùâøÔ\à€ôuÀú Àƒ€y œà—âx,ì3å`­ð(`_Ø?䀋D¹äU@äÇ¢ì4°^´óHHžDæñ‹é÷€z`läÀZ `_¾Ü×äí »€Ä6Qéºh[Dy2퀵_¤?¬€’ŒÓUÔ_Ìq@V€Ì[ìyžÔæ!@zc€q.€w±¯úŸò-ù½0?XçÚ€²“ðŒ2äþ–·´šÏÆE€y Ÿ(¿”ÀmÒ·ýËr.°P.Ö¼û>±¯nrÓÝw2 S9õ’O+ÿY..3ç0ÍY5ìlÒÛÀ¨\xz'œYvZ|É0AcZ¢Ò<)Åär9är9lܸ±`û¦M›Ðßßþþ~lÞ¼kÖ¬ÁÎ;Ñßß_UR§ÿõ¿ášsß ¬ÃÔK\‡&?ys¢–rPX I’ …°êÙgñÀóÀ0 ¤Ói×ÂVƒ“W×õ‚°9®Ò2¿Rì?úþþÃÞÞ^×`x^'´Bœ"äÕAIk)Œ€‚ûtŽéR¬Ü•eyÒän~+ ”¤ÅaÀèÞ‹ÏF]¥,y ÐêY2"Q¸1ºAÞ“ˆ˜òL%›f,ŸGmà™Ëž©Éê GjçþsSÂ÷b&ë)ŸP(/Ô†‹=4JÝ‹¢(ö«”FSÈQ¾ËO-’¾‘є€ß›$IïÊo£ëú„Ü/‘HÄ5¶p½ÜŠŸ9 išª¹Kõßö›Ö÷Õùôc¿(">Ç!÷×ãÂ;îÀwO=§?ó nˆÇñ‹ýš¦¡gçNàƒ­ï.zõUŒ8 ¯•p§÷£¡0ô¥‚#O—(¨* c‹”—õÈÐPÉ(MþwÉ«¿?§w…>L$ÐuÑ(Ò¾ülñx¼ _ÔßxçÛ6 i°3HU¾ƒL=Ƕ¦YÞ;ņ°$!ì%Ù=€ñ ŸÈ`ÚN ÙàR ³V¤¿ÉÐV¡4 ”Âx™ù þÈÎL0T/×9Hœî9`¸§Ær±yP7À UØà+€ôyÀ¾8oˆÙdþý€7Ò—5 ‡U”‹<§ e•8 ’LêG! 1k|°^ð €Ã ¡_H<(¿Ò[€ÐÏãsÂp¡ŸšŸ2¬ôêÀZ™/÷‹û_ó `wáÖr@6Ì €}~Þ¾ÿ,`tB`ëò!ÿPé@ÿKÜ @]!ê™T,Ö—y™¨¿®ŸŠsÛ]@æ qÞµ¥â=­^Dþ°®Ì|Y|6 ®¥VÑ|ýáÿä!@ù ~@<7â|mwîÃ_ìd³Ù™Ýüˆã8ZþoÔqœ¡ü6ÇqœTþoÄqœ¬ã8Çq±_*•rR©”÷{Ìqœ´ãü~Çï—>èÕÃïo´Äué·Xþ3¼éN§Å=T¸ïÈȈ‹Åœ‘‘gddÄÉf³N$i\}ÜvÛmÎÃ?Ü”k7šéÈçÃ?ìÜvÛmŽãˆ&uþUŽóWo¯ZN¨}$ WS©”£iZÅm§Zè½H$êzF‘J¥UUë~ÑÑÑií/˲û~-UfÇqœX,æ ü_|?¥úˆÙÊtä³\½d³Žû´ø<â¸ÝŒsÍG>âhšæp"‘ˆ#ËrÝån.ò±Ûïr>¾é×΂ {gt%ÿËÿÑw8b¨P õ£ÓúaUU ú_ê£Çq¾³d‰ã¤RÎÐÐ#I’»ïÈÈHA1Û©vl›J9Nñë0‘ÿ“ljýÞq²·:NìïGsœÔCŽû™ã¨‡'¶Gì£9Þ.åø†#Žã¤EûPïÿ†IuÄñƸ>Fò£ùûL×èr4|ξ”ÿ0ê8éƒâü#Ó¹ï|fÇ…LÃç©ËpœÔ“â¸éHÛHÑçÕæ¤üsÏ&ÙÏ–Ø?ëˆòfÇ‘NN¼ùQÇqþðÇ?æ±m æÒ{‹ .<¶-͆ œ¾¬ã| 2Z×yNýgPL-‰ÅÄü¦ 9N)uÍKçR1S½mÖ²tÞŸœpŒ:ÙìK%e‹t4·`˜j©‡Þ¶*•zBnžÕbÀ¢E@–ß œW}9t]¤¬%ïòRrW^’¥4‹‰Ur3õ%”!bZ[™yiY ? šÂzöööâÁ¥K1¸~}k?˜T+›–U¦"Ž|Nx Èþ $i­ð ‰\å;x¡®dKÌ»ŒÌܱJÊ8+ù[a-{)×CfyþÞ0(F¦$ùÊT1œ‰UVN €z&€‹«+{©Ï~4ÚÂÂïåðÏVFO›xó€+¨2"A«Q‹¾“a˜úP|?~ïb&iŠðŵ@QÄ_1¤oò‡ÇšíÔªï<ýì7H@Géß)$ëð˜ 8ƒJ-8tèE,:¾hÚÉ-)¤åð „É]]]nâdRÔUI -³˜8 VP8s3Ø1,]<˜ß–OLyƒuƒ0 Qf`}d Œ6d@¡d–DñÌÒF~Ÿ?Æ„—|3/A){â¾ÿ)É¥ /fžA%Ü(ß(®q_þ|”ÕŸtÓŸu7¤#iì{z–ªKݦ?N<½|É8FJ@2¾²‹¶'ÕfjËŸý!ðËû~‰¨­ø¿{'…}ª4É{-QÅÍ›4B2™œù‰j ”J ˜b±B¡FFF\ãhWW4MƒeYnxFúÌ9–ªÃþ p4 Ärô(Æÿýß‘Y¼Ø•5 Í6Û)¶m#“ÉLyŸn’š¦é¶EÊùãϱDá UUEoo¯û>£ßÏzõUدÎÇ'O…yYp…¸«Ä`X*­P¢ûAtÿ&¼õ”‹EÍÿ^éð‰Âò• ­ñ¡Í›‘ÉdI&]ƒ4…|ùÏÿ¼‘´eQñl¢‡û`äaˆ…,Y7å÷Pª‡â©'Ã0 3—Ø/§ùr³‹Á ΣLÆMàÕŸž†_ý㯀ÕkKîã×Á2LИuEº»’ÑŠ—›‘rNÓ4˜¦‰T*]×]ÁM$UIšŠnpF¼ºþU¬ÀŠ ÷å*]ŠßADýTz[’ï´Ü1a0¡Eû~[a6|¿ëð4:Ñ|bÆ+~=ÿ§Â3ÔÂÆ:AËû¼ôÅ¥@ÂÈC @tYän c ‹Å`t]‡a÷›¡¡!7î»i𮲇žÿ\]í^K,ÿûoÿv¦µº ™LºÏ‚wü,fŽ$I-—oHÓ4·Ì¤X®ë®ìÆb1·Â«åÀÍ.zKa=Œ|8åÅ‘zÿûñÚÆP¥ÀY*wÍl!“ɸÆ8JhªëºûÞ¢\!d Éd2nNµt: Ã0Ü6˜Éd Œ2]]]H$îþt<cdYÆÒ±1ÌÅ[?ˆh´‘H¤ '[$A(‚$I*Û?É–…P($ƒÄbŠu B…è‚íüçQÅ}o~êšÉñµ“å¥"¹¥+þíwnØ€e;w6û‘Y9T2”m€Q[×àï»MÓtsyQÿN†Fä¯8n6-š)ÞFûÒq~OrÛó{.ÓuJÅæö{4Ó<®Eç&c"Ué|´8‡æ²,Ã0Œ‚sÐg*3åg¤²Ê²\Ç‘<2éúT_~ù£ßhìKù©¾¨¼R>±2½cLÓÄ‘#GšÝl†a¦Í ¸à´xaô'mÀ ÃÚÿv7 u-pÁÄ}’Éä¬_ÈÇ´.³Î ò™ÏìÂ…‹®˜Ö²›û,æ}uö·ï‡¨*”¼‚0“ɸ vI¦ë:LÓD6›…,Ë…BÐ4­&‰ºç*6€+OzZÇ‘‘“žQ«‚ÌlXéA!ý gÃ0Ü¿H$•i¢ž-’üå÷`¨*zóмVh/™L@¡ç…£"…£eY®1„¢€çNNJËx<Ž¡¡!„B¡‚’ô?yJѪ)2lhšæQdY†¦iˆÇã°,Ëõr£mÔ¯øÃWf~óÌ?å:„w}á'Ò®×%y¦X–…t:í¾“ɤkÈ!Ei<G"‘@*•‚eYÈZ–ÐÌûð¯Û°óD—: aHIæïuË•Wâ= Bèn‹U±XlÊö‘NO\%²ä­oÅ®ßÿ¾ÙÍ&ÐÄã"‘¼1d @úvmÎKm‰”öÔ¶ÉÐAø÷<9)µO9üŠ?¤è'Ob22øC:—I–ew¡ÉmóŸ·¿Q”äŒ"þ÷ÃÄúC’¤Å\4-_G£Qw\Iôöö@Ç4]‡ÞAþëúô?…æô—Á¿Õ½³È;ŽŒÂ’$!“É ºŠEQL&aÛ¶;îííuß™¦i¢«« ’$all k×–^-Ê0 TvëÀÂáÀ4»$ ÃL-eo?˜Ÿ.(­k+5‡`˜ 0ë *§8 0ø)ೕ£iš«4±,Ë itC qÁg.˜ùIªaªwÛd†d ¥ƒz+Eÿ xo]­Ä¹üø\äsØÿþý8û¥³<´§ÛÝ0cÅá¾h’K ©T*…h4ŠX,†T*Û¶]%0µ™ˆö§@üöŸW´/Õo<‡,ËH$\ßLI,Ë*XqLJ-UU¡ª*yä‘f±¥È¼ÈoHÀÈ+ýK­Þn4•u¨ßŽÇãîwY–ÝUâÔN(„'…ÔuáÑF122I’ÜæétÚU(“1ƒð{2RŸBíÎO)c¼M,ËŸ~u¾÷½Ÿãº—ÿ ²ü}÷w@(i)‡•gdd¡PªªºJiÊED!Lãñ8R©”«¤VñxÜõÈÔ4mÂb]„%ËÈüýßc÷²eÀ§? <S+ÿ¿V媱SßùN,™%y©ê…ªæÃ²=H7Tžd2é*öÉŠŒ*dü£öá÷x £íCJûTJ¬È™©±Õ¶m$“É‚$¿“åÔš)ñx¼"C •É¿_±<“¡Ã?gH&“®gm¹óR—ƒ®CÆz&Å KüyÉXìß§ø‘!†ŒÁþ±-í/I¶nÝŠÅ‹×í0ÍÇ ¹¸Ÿ'Ï12pú½ýᔋÃPR¿CýíG}­ß[æÛ4æWÅ]ØFc2–Òbº\ý[j“~Ä¢ Û¶¡ªjÕ‹²h‘N"‘pç%$;$ãdè$OiÂï‘Gå&£rR˜qª:É)õ÷þû>~üx³›O ¢Ôo^óGÅÌtP” 늘@oêö±À×Jù¨O¨ç˜afÂ)Žã8Í.ÄLظq#î¸ã÷û·þ`.øýiøè/ÞQ& g!º®#“É㝆^ˆL 00q ìtIBtº Œ1ˆÑO^¨1jx9b4à[[¿…}ùcX’Z‚~öÆNÃ5÷]ƒp4ŒX,˲ oèééAÏIÞY)ƒƒƒD?Î3Oª€ê-Ý!Ú6Ɉ¥¸¡qFFFØpÅT)ä‰Ä„>‚”ªû5àÊk€5¿öòx<î®Än¦†á¾s 2¤QŸM«ÎI¹IÊR“Ò€ëyHÆ’JiÄûHQìØ±œy&®(ò®"ÅL±–V¥ûsƒF]ÅŒ?W)šÊ …Íf ÂYݦ /K¢ŽjÝßG0…lܸû·w`— |lÞ(+Êï_ʰAŠ;RÀE"‘–ð4c‚mKSï÷… #ã½·Éð`Û6b±¢Q‘PUU·¯‹D"ˆÅbnˆºh4ZöŽBR’!#»†2 RB ~ SIïòR#Ï`~/*¯¿L~c‚aî<ŠBÓù·t¯©TÊ=žú¨h4ꆤþŒr+’Á‡ ¥þó’·güÆúLž`@¡Gœªª®A§Ø›ŒŒ¢îr¦Ñ3¢gHQ0ü"î1ŠAÛÈàé74ù½ëÈ`tß}÷áñÇo¶8Ž7âÅ;î€ ¹yÛêÁ)ZZÆÔ Û–§xîð xÓ®ýøÙûÏ‚/E QÍ|aÊQ±í¬óPùíoÞŒ«ú^¬È˜â÷:˜,8Ó`jò”ôE£¾mÞ†ÈÀ«Bh…Tˆðd¶øþeõËâóàØçŽá"ó"Àúß×ï–³RVÜÂ΋9þ{%œaXàÛ`…™álÐuñ'IøæŸþ©› M+Ê8ÜS!ž¯:®7€ö5ÂþLò7™’¾^Ð*k(›X,憪ñÿ‘¢IÓ4¤Ói$“É‚U´~ü÷QÍD»c„L&ƒSN9¯¿ÿý~+§ 'eÒdÏ)•J¹«æiÕq:F8v÷1 £ ¼‘¢(®gK8F:J/x]¬1!ꂌjU÷3Ã4Ï@l  FI¯_’Szž´›xôç7¢1 Ó|H‰.I’ɤ¾‘ †a(üžŒápÙlÖõ.I¥R0MÉd]]]FŒl6ë†2q¯ÀíW5Ms½Î2–øó×¢Ÿð‡¬,†úk2bPHJòú÷Ÿ«x£ÿ½E‹×Òé´k¼ >î½8 ÕA©ÁT—‰D¢Àû#B×uhš†H$â†ÏÄX$‹ȸ“L&1::ZpŠ¢ ££Ã5lѪjEQÐÛÛ‹d2‰T*5¡/'ã?üx,C(‚išÂÝhš†Ÿÿ¼2ÿ9Içp… Ó <¬çý:ðþ‰ê[¿ž–a‚ʬ3¨üú”7püê©Ý`ý+ö2™ »‘Íh|­Ã "/AVhLLŸcÀru9ð)qಽ Ï^þ,bÅpdùìþ»±ÆXƒ>ó@³ï*ð,ðòû^^0¦ôöé´g$‘e •, ¿zõU躎µ×]'&k™ `YÂØâ—SÓÛI‰hš@½•F]]ÞgÛ5þ e<žÑbˆr—Ç4Åq'LdÄ3¿ìdÝF(¯`¨·1…Âm(á7ŠP²fÀ[-KyJ(_)(Š•B­Æî¯} ‡Æ¡çWxL¥ BÈPFÝz¢Ð-~¥)¥R©”«\šL!Ÿ€·V!á±bC¬0£RÑjd6vVŽe¯ˆ| ÀHáo”?‡òý‘’/•Jq®1† ¦iº!¢È˜âgE ÈPÑÛÛ Y–KÎOýJ|¿çy‘+àýû¿Ë“ÉdÉþ£\NºN©>¼cèšäQI^ÅÞ“yÌѾ~ñ=—:†<@Šñ ü¿Ó1äëÿÍ¿ðÂßÏ’×n©ñQ*•r eþ:"£R÷Lϧøÿا˜Õ«Wƒ)ƒ œ{îžò¿›ðÇ™n·<·ÛÄ2y ^~VÉ;7Ò«G¬üþ¤S …›“ ›­ü9tß¹Œüµ)5™œÿÍŸkÖ_N¥è¶o†i5L`ÞŸŸ7W#Á Þ™V`ÖTöîY7xqÊýh)k  d›’ä)k§Àhö3ÓCƒ7h„²‚$€Xrë×û$€y±yø>èÀŽèühøGøü~¿ù¿¿ÁªU«š}Gfô^ ó¡3qÎ' ™Ɣ⼠Š( .°m|÷ºëÜUê®Q"Çú'qº.Œ1¥ä4õdØ4Å~~eže‰?YžX5ï)Móö€‘LŠ$‰ë&Þ{ÄO2é˶…á…ÊdšâXMó 2þI±axÛ©îb±Â{×õÂëʲFͽgÓô®¡(Þñ™Œ0%¢œÙl¡±*Á½~"!ŽÄo’$ D¶]h("£W‹ä¤šË»ÀKÜ}ÁP¥!ÊoR0×à)lüJ!RÈÐ樂˜m+ï—õô`ÿ¶mx~åÊšŸ›ê̯$"C …Y¤ýh…4hµñd+Ò%.`ã¾}øáüù®‡ +ú§Ç xó%€?ÁmÛ…B$ÉU´úCÛðÄ“a‚EBðç¯J&“øíü"Q•oßp8ŒH$Rd:ø½8*¥TޯɠÜa¥®ãFç¦í‰DbZe#o’é,ê <)¥Ž)w O6w§?ŸL1åú9ÿs­”âÜLLeŒ£­í ø’ÏêbÃ[õ!Ã3Œz2Vhð"fŒN¼†º"¡œ ˜OÊB¬*ICè1(ŠÃ3„èb79ÅPõSHG¡çÏ/Á3žFÏOå¯A÷J±ÞüyRð”F!Æz~ÿDÔ¿hÆà)¶ü†#ËW? ¼ðêrþ3Õs$)ÿ9“ÿì¿Gÿô"î;·^T* •ltN3ÿ™¢ŒÈ˜¡`4M/ V^Y<áwÓô”þ$´"?呤BÅh±â4)T Û¶PŠÒù5­0d’iŠsÐÊ—HÄ;<.®iÛ^¹I±æ¿wBÓ&–®kš^Ý‘ÒU×Å1ÅÊm ðâqïúþíT7Š2ñžJ<ï…¸[fx¿º$„‰+=h –[Ë‘üã$.¹ä\î\ŽsÏ=Ì$8Àê `÷k¯‰gQbÂAîô¤Ä+^a‡XÌ{Æ€xΓy–¥RBÑ>‹'Œ$$_~ùSUáECm9›Ø®J‹Mî%S|O~HÎ C”½”Á ð !¥…ËJ©‰½ß £Ðh¢iâØpX|öKumYÞ{ÁO$"䕌eÞCç##L*%¾²\ø CÔw$2±ì¥ä˜©Ö°p¹˜&~•^k¢Ñ¨›ÇâŠ+ŠâÆÇM§Ó“žçŠbáù矯:Ÿ[µJÈ ˆÞÃþ¼4ÅmƒÂ”hš-ÿìLÓÄc+W➇Â%7Þ)›Å=ÔÄZm=vx[Bqï¾âñ¸N¦žt2L0 ÷'½/]K)Í[6cùŸ, ¹\å®dJHv$qÓ÷n,àCïùÖ=»N(Mˆ¹IRì‹<…¥–?G ¸}ÕíxË#o Ì8„‚’V¾“bׯ<4´–ö´Ißµ€B%«wÞ4”ûúWÏ'à)€Ux+üós«X$敉Æô=’?Ö,,s,ó®M×#e­oµ?OÒ±´WgðýFÊc¿âÜÆ‘D"!Ž¡r¤8úÎerLFBËã/Ýåé$¥¬ÈšŒ˜ó®cÀS€Sj+ÿYçÓ ‰ÏþûxÖï}æ½kÐ-ÆÉ“'…ñ΄ø£gJ]$E§€o{±Mq*ã  7?}Qd.ì‹%HÇó> 2OœÆÌâ™û]w‰RëTTˆvä7¤ã&ÒTŠîWÍÿNm2”?W^|VºÎ( ~ÈK†ä’ F¾| DÌ× ½jè;`üSV Bf(g.ýé†ò¿Ç|נИD1ÒåÊÎo” ßyt/1ß9TxÞJdô‘ Œ&ä…䯪gº}”ÂÏí¿nÇÛGÞfjÌâÀéÿ#àm~Ÿ+ó>¦µ™u•ù¯ÏtÝS8Ú¶»²Ü¶mlúë¿üËç?¶Oz¢rp*¥()i…{)HB+»K)‡'{IH’¸N(4Ñ`*N-K(2ý ‘pX(…é>Šï1™¿—ZmZÆÈo\*V€C+àUÕ[±Nhš¸Ÿl¶p»axÆÿ¹#±?•Ÿ~£óF£ÞjxYö HCC^ÝF£âüþg‹zIL¢ ÷wÞ%›€Œ¡¡!X–…ÿÛÇ»ñn0¥1œs#pÎP/¾õ­ee‹VòQœþ h)O’©˜LŽÉÈXꜲ,ÚEÕ¡«jù0`Ôî'[I8•ÑG–Å»(™2^|ïŠ2¹N¹ú§mº^X>ªÇÞ^Q׊â®üž6þý)$œm‹²*Š0‘çO$"~+÷LØðR?´z ˆD`äs§Ô _áO6KïRZ¹:וÂ\p_sMï[¼B¹ÔªeEQ‡Ý•Öd#Ï!2†“·ÑgR)ühùrüÅŽX—Ëá'¡6ìÝ‹Ÿ/[ À‡›VË­Áªpý¸“úL&Ã0\O"†a‚…mÛH&“Èd2H$"—ˆ!á?ø[T`ù,®„PàuÁS@&€­ùÚnh$àk¡¯yŠOR²ûà äÏaÂU>žþù@¼dV¤,¼0Ç;ºà­–§k±Ã¿_…ÊU¿¢—V©“‚Ò¯°<%/w’ð²´B<•÷´Â^öŸþR¾rQYˆxþÞé 0A·_¾nµ°æ-¨#C’¯_ÀSÀ  L`þq¨ªŠ3Í_0™‚—¶—Y?¥‚–ñ¸(ƒ?¯Yñ9lÛ[S¹Ãˇ±&¶FìHž%E‹·.–/ö¾”RÖwˤÑ%Ї`“u³Ô”üÊЈï¸RÓHÿp¹”«¿<þáW©®¬Ôp‘ö#Q(§'Ê¿^"“C+ÏýøÅm¨h_ª7­Äybð A¥î1ÏBû^ž ÿ9•¢ÿOÑ\ê>|õÈ•òÜpÃnŒ\2QA^CbðGÖwÊ'ç·û)†”Þüï1#L$ÿ[ž-’¢XY¾Ïd‹ôG¿"G/³òÙÛ€ßç<“M kht;¹ø$Ž.<Úì»m N¾´¬äo¶m— ­È0A¢i•ññqŒ‰²>r¹r¹:;;'ü6†ܵ¨ 4É>‘HÉd¦iN+fìTԭÚm ÁrƔɞ…$•6 ù'äS¼}§‰&…8*Vf2b’ì8Þ$—&¤D6뭴χXS<0»’Ò—“M`ò¹xßÃfisÙ](õ\_¡Î PaeY#©”OYžè%Hž2y¯½·½ôR³ï¦¦ÔE>~;põ²sÝ$ä3…°êºî†“’$©±ÆÒV„ÂùРx±ðeYF</ˆ¥_*¿ÊóçãÚùó!/YÓ4Ñþï`ð¹ç %¸ù ñÝ»›}K5¥–cÛqxÛâs2™D6›…Lž}þ1 )l»´×¥?¤k)¦ú‹[€B£ŒŸ©ò-‘Ac²ñ•²ø)å)Z\N´L¦0çšm{ŸiOñ¹(Xo¯¸ÿ³·W|O&½9þë«®Qa93ÏÈå÷ÑõÊ¡ë¢Îüá7‹ÃúF£žWgqý«ª8–¼@‹ 1™ŒØ'“uK^ßTÿ–ŒŽb6Q¾ÓßÄ ÃÀ;žyÖî_ë†à"Íêí—ÞI’Ї>ï`ê¶6“=¿bCP7/‰ÙB-åÓ4Mœ±ìŒB£Y) (Ôùms*„S™?rýfú¶Å!Œ$ ›a(ÙëÈû…Œ5œüSÔÛQô/¿}ѰôÐ!ܹhÌü¹Öår¸cÞ<\ë8øƒ `JlgãÅ'žÀÛ®¼Ò-»M×2 œõÎwâÿ}ç;ˆD"¸wï^,»øbìyøaœwÉ%øÕí·ãÜ÷¼ŸºòʣзzË—/Çò—^‹]„‘¡!\sæ™Ø³p!~ùË_â–n€$I°, ¦iB–e˜¦‰H$‚L&ã†Ç¥E\F^‡ã¼õ­èíê‚,Ë$ ÑhÔõ¼'ÏêL&˲°î³ŸÅÛ;;axèž{ðèï~‡·¼å-øñ³Ïâ¦ë®Ãïî¿§„BسgþlÕ*üÏ»ïÆöo~’$!™LâÜ÷¼¹\O<ñnøä'ñØóÏcYýš^S¨‡ÞÖÃÁñù§OØjÛvMuµ S7œ&qÛm·9·Ýv[Á¶»îºË …BΆ œP(äÜu×]SžgÆ îç/n8êÜøÖ;Ëî‹ÅUU‘‘‘šßÚÀºcÄȈã¤Râóè¨ø?qEqœXL|×4'‰8?üp³K[3JɦãL_>~øaç¶Ûns²Žã|ú»Çœ/¿lÒýeYnö­3³ YvœÑQç¿ÿá6»$5¥Vòéï;Çq®‰9ΟÝê8‰DÂI$U—oddÄI$N$qb±˜“N§›]e­G6ëõ1g”úÆ2hŽãßI*•r†ÇY|âDɶÜÊÔrl{ñ?:Ž3$Æ®ÿ÷ºëG’Äøƒeª¾ Õî\±˜ç 24Tö~o»í6Û–€Æ¶##ŽC³èo~ÐùÜÒÏ9#‰ÇI9^z±X̉Q[¨¦= yýB,Vú™ŽzsfÖS<†kuj9¶ÅbÎÁ¥›}K.###%uOÙï‚‘‘ghhÈÉf³Î§¿øEçk‡;ÙlÖqb±˜344ä(Šâ¨##Î¥Û·;£££Îúo~ÓIŒŒ8²,;v×]ÎÙccÎŽßÿÞ¹æ#q®zòIgÕe—9wüð‡Î²_t¾ùÊ+ŽªªÎúW^qälÖI¥RÎE?ü¡sÝo~ã,Ú»×YÿË_:pçºßüÆ‘GG‹zȹøÐ!ç¢þÐyw.ç,Ù¿ß¹|ÿ~gáK/9Ë^|ÑYúøãŽ<:ê\úË_:Ç;Ë^|ѹøÅ3ž|Ò‰9޳dÿ~Žã\ñ³Ÿ9‹ŽsNâ çÒ_þÒY±g³æèQGqÞË9¶í\½w¯sãSO9Ç;kŽuÖŽ9Ë^|ѹñÎ;«ž|Ò9óøqçƒ:Œ9Köïwn|ê)§í•Wœ{ö8êè¨ÓþúëŽä8NÔ¶•¯¼â¬8zÔ¹øÛßv®<|ع|ÿ~gÅѣΪ»îr:lÛi{å'12â¬Ïö®]΢cÇœå‡;m'O:²#^ãòè¨sùþýnyV½þºÇq>ùÐCÎÚÏ|Æé°mçݹœ³ôàA§Ã¶µcc΢½{yl[†â÷ÖÚŸ:ŽüåלžONØ7‹•”†™ õÛ6ÜCeÛ¶mÄöíÛ±iÓ¦‚ß°eËôôô`xxëׯGOOOÅÏÙ‹Çw–ýÝ0 H’Ä+à™Êð‡“ ‚Å+pc1\ý‘`äÓŸnvigÌd² ÌL>üÛ×ñÞÃ¥=t]/„žafB^V_Y¼¸Ù%© õ”O8–.x0úüôWÙ¶ Ó4Ý€XÖèÄêLã™*4œ?Œ=aYŒp¤(Ài§5ûjB=ƶ»ÒƧÓO!´8Agý©U8B]ŸÚs§ÙÌЋõê; ÃóN¹ï_îÃßÎÿ[ÌSæ•Í=ðÅ;ïžW’SUÝt$äEd= ãØ1ÈGŽ+WB>ã /¿òÓOC…âÏ©(nŽzìÚ<ø ägž½lì·¿ö5×xÑŽò¿Û¤×^–-ƒ}íµ°Î>ÛÍi/Ý{/¤ƒ¾8öïxì‹.rCa×.˜'OBrÚiÐÏ?Xµªà¥'ž€œ÷l2/» X¸ʼyÐ úð‘#ÀîÝ„}Úi°W¬€ÔÑÐ}äœ8 @æâ‹!ç·GGÑQHGŽˆc.„rÞyÀ‚"¼ÑÑ£ˆ;†øÑ£°¡ óç—|ǰr%”yó¼ýûöAno‡¹w/¤ _rIA>xåÁaÍŸù”S`ž}6ÐÑ¥£ÃM)C)_ôçŸGæÄ · ä`ŽCzùe€|⬶6È+V¸Ç[TG Â~áHÝÝ0ÛÚ¼gùÜsÀ‰XYT÷­J=äóü]çãµÐkX„Eu)³®ëÐ4Íÿضín‹ÇãH¥R$Éõ⥨(–e¹¡­). ¼+²Ù¬«§2Mš¦áóŸü$ÌþgdL±XÌõÊç¢Ô X»ŸY»ª,#62Û¶qþí·cU$‚ÿø?ÿ íØÛ¶q^>ÿÝW(äg~¼pɱcøàé§#MaX/½ëîÆ±ÛnÃ>õ)„Ï;=‡á‘ÎNô?ø ^îìĦ½{‘›7²v-FH+V àá+„‡NG‡H¡tÍ5Ø|ô(ŽžwþÚqð/<‚›s9ÜÓÛ ù¼óG>ÔÒ¥n$åôÓokƒù‰Oà–|Ýóæá^¯˜ÞŽüùw €Ÿ@¼«z—,ÁMùóE¿øEØ~±p! á¾>Œ@¼óô³Ï¼á tâþûñÞ÷¾Ý§ææ¹Q% :òiiN?ÝM½d\uþë=ïAô”SX²ÄõŠøÔxôí³#)}=õ¶ðäI@zôÂÿÚ¶ Û¶¡i‡‡fZ‚†TÖ¬YƒÎÎNär¹‚탃ƒhooGOO »»ÝÝÝD___Ùóí_C漢ðå»Íi'¤O&“n¸¾RÉÌ™i’WºÍʵ„Í›7ãî»ïÆñ³ÎjvkB=ƶ§p°çܽh_µ زeÖ´‰9C&3u(µ€288ˆÝ³$_½Æ¶¿ú•LF‡ºÆÇoļÜ<‘³|÷nØg,X"ÜNû‡>„ž¿ø t½ùÍî9läßcc°‡‡a®^ØÀ¼ðB`ùrègœáæ$Ç'>áæ(„â΀PÞipúé@OôOºdÎekÕ*Ø«VMØ.Á ¤ÜpƒØøì³âÿ3ÏtsAØpâÔgžý–· zþùH<ôäU«\à À>rÖüùFG{ï{aýË¿ sñňæ|÷»ˆ-[ã7ê¢E0óÆ€ü­o‰k¯Zëâ‹Ñ{é¥ÈÂËI!ïØ bh|`ä)ñ—^Bï¼yÐ~úSÄ–,tÉ%®AÅ :y×.Qÿóæ‰ã—/G|Þ< , æ]w!ÓÕ…ô£Âú£?‚ ¡X¥¼ö™•+!= @v×.X§Ÿ½£Ã­'ã‰'9qÒÞ½HŸ8iÑ"@UÏ—aèÕW…qª­ æ3Ï 12ók_sÛJêèQØ÷Þ‹$\s ì#G0ÔÖæ>³ÃO>‰ŸŽâ[³dqh=ƶËv.ÃKï~ +°bFe‹Çã®R×¶mÄãqD"˜yÄÃadó Ê3gY2™ŒktÑ4 ¶m#ÂÎPýcå¡¡!7¤U"‘(CûÊÅ ‚iÑ’ÊaWŒ$I“ŽÍï9ýô’Û“ˆ9Y–EʧE‹pc"È%—P¡è„FÌ¿<’¢ßÙþnÁ`ÁÀç>øA¼; (ŒÎVî3à½Û¦ò_3[f»ê;F…0¤üǬ[7áþU¾O¾íÊ)§¤ND¬· â¹ü;®Õ©—ÞvÍš5hkkÙ?-²Ñ±î-î>†aÀ4Md2Œçâc˜0<<\—±mà *ÝÝÝ€ööö 7XlÑloo/ÙÁú9tèkPyùØ~Œ¼í­¸´hÛ¶Ý$ª¼b–©%³iÒYN6êås÷îÝ86:Š3_;‰+'®X°m‰D‚W 05gll ƒƒƒ³Æ Rkù$ƒ ­&Úñí…øù»þ–eUµð€(5dš­V#‘H`pp?úÑðÞ÷¾·ÙÅ© õÛâx0÷ Î}Ï{æ„'Á¬ÄŸ¾…à±íÔcÛ«®„m߀_ú9Þ|Ãóø¶qæÅCûÅ/ ^}5¬åË]ã†yå•®÷aåÿÌU« ®Z%{\PÑ­â|èX¾@yödLð ¿à‚Ò;^pû›×]Wð³k×z9$n¸Ajò_“bŸÿü„rHÇ×¾V°}Bò€-s|B–ß·‰Qèìð”¿éNdÊW¾"öí뛿gÈEAF‘Ò—ÍE$|×€,‹ºY»vB}@’ mÞ\6ýÇþË.ÃÛ¶áôŸþøÔ§ÐêÔcl{öógãĪÿ è=UµC¡ëbš¦k4!‘T*…x<@CüF MÓ`Æ„Õõþ‚š6QÊeYF¢‰“™ç¨\nM–¨Ó©z¹T‰mÍœûKù2ÍD+Xê]Ëåðò£â<Ÿ´•©—Þ¶³³mmmXp8zôHá;]Q\¯-†©%;wrŒMØV‰ËØÒ¥KÑßß0€SOžŽ3K¸Ø†d2É!…˜šÓßßf£îT+Ÿk×®ÅÐî‹!½1‚£çž;áw ĦÖtvv¢¿¿ÃÃÃÍ.JÝ©F>—,Y‚þþ~ÀOîÁ‚=‹ðõÿóÕ)ض ˲&¬šS…=@™ŠéééÁ?üÃ?àg?ûY³‹RWªí;¯¾ó=<ÿ@Iå Ó(Š—¾Åà±íä¬]»÷w7à ëǽòE´}x£9Ègœ”X[j„+çÿ&3‚X–п—:–~·,ag°íÊØüN’$ÎAßéz†!š°™wUü™®gYÞy¨Lî}+ÞöÄ1$tM:ÙM_|-º/Óå’$ï÷¼]†áÚY H/]êã/G©søËGå¡{ÊGUsË[/‡ºÕ…ÿQ-Ë_ßxßûxl[Ž%K–ྮÿ…[ŸzøçoOyx<7MÓ5|ø½AÈÓÄ?>žÌøÁ ŒZƒz,±&ÁÁÁfß^]™©Þ{çh'Ý{ öÑuÝý¿™FFföÑ××7¥Ñ¯cP)µ2!—˹–Ñ©°,Xpã%VÖ˜y—B IÂ0Ìô˜‰|.‘Õo_ŠçJÄû•eyÚá…†)d¦ýç÷~`ãíoæ½U©hðÇ‘N§‡‰D`Y{2ÓæÀ8’…?[©V6ïYˆÞñ}Ø;85•Ó¢„Ãs60a&}§,ÿxðB¼ý±£HÿÑ`QåqãK{JtËÒiÑ|dY¤â ‡MóöÑ4 ™ÿ«ªøÝoH$Ä9iß|ºEѨXp®ªâ|€0RD"žÁ‚î—>‡ÃâØXL\ÓoÔðT’IQŽLFüe³@o¯W&ËÿÇãâ|‰„w ÛeK§Å6Ó,ü=“¿E£b{^‡HDœÏo‡–e±¿ež#¿Åbâ<¶-ÎIÛ©>b1ñ™ê–Œ,~£=@\#-¬ïXÌ»*•IÓ¼2Ò¹Å{f¶]ø†aªc¦ýçð. 9ëübÿÔû&“I7Ft,ƒªª¼‚ž©ŠsÏ=çw^³‹QWª•Í®3±õÅGñ×oïhö-0Õ‰LÔb3b&}ç»?<þèˆö¶O¹/ éÔH‰®ëžñ?CCž>ph¨P¯(B¿JCëlv¢nѾrküÝw)}­}.^w1Ùz ÛçÅĽ‡Ä·íÂûôŸ›îǯcöÎd¼z$Ï£%›¨cõÛ¥‹ÏAõ[ªÞüÇm ý6Ýy¿P=Ȳx¦~Iuí¿¿âzó{êHRézUUÑnþíßÞ‰ÙNµòyÁøøÄÆLÆ”‘À¶‘ÉeSŠÈ2®‰D€¶6Q¹þ‡dšâϲ< Zq#îíõ«iŠç?G&ã »ªzîO~÷(²À‘Å.•*lÄɤg±£óøµaˆ{ôϧ‰ÂÆNu@û(Já9üV]Â/ ¦éYiË]£««°ÜšVØÉºZîþº(w]ŸxŽtÚ»/²Ú–;Þ4…U(|ß'Õ3Y¨‰hÔ³[–¨C_{[yûí™%ùË1Óy' BWžzÒÁëKÞ\°=“ɰg ÓRÆ ÒÓÓãÆ¼ïééÁðð0r¹Ö•HUЇàJŒA’VOø-œ 33f"Ÿ»¼qø$>â“CÛ¶‘L&‹ÅX>f†Ì´ÿ<ôÑåXûð8ެšzõ,ËÈd2H&“œ,a¦ ZÙ\t|Žû –~âÓ^‰ “ˆ ,ÕÊç‹/.Åýû^ÄêÇÃ4å’‹Í ÃSøË²Ð’—5 ¿°ÔÂt¿n” ~Š›W›[©r—»Çb&»ŸHÄÓýú¯1ÝEé•®)¾†_?KÏΟÕ,ŽŸª®üõ²ÿªé¼©V>UP‘ÍŸséRÜhY‡Ã" š¢LnÔ´©ÉT¹¦:‡,{ç0 ÑŠÿT×PÕB«`) ñW.·×TJlE™º~ëh)"‘ÉëÛ_ÕžcªãE¼|)`¹û´maX)ޤá7B‘g‘ç?óì›å!¿f:ï„Ae¿u/(ôPa½ÓjÆ ˆ˜½›7oÆš5k°sçNô÷÷£­Ò¤N&ð;Ÿ°9 q,K†©ÕÊçî7€·,}zÂvUU¹Ód˜1“þóÀ/±å¿Æ'ßÏ0 †‡ b˜Š©F6ß|àÍ8íõç¹d˜:S|9²û–´áŠ ïm 5M±€œ¼O(rE ⨘µ%“ñò¼Ì5enT€êäsÙ÷¿_ðÝ4M¿új\}ã0M3ØQK¡³ª§Ð´JĉJê@’ '¥˜Ãc´ém!B~ßþN+ʱkùãF2L Ð4ƒÊwÜ1a[__zzzËåÐÙÙ9-·1˜ã¡ ÛR©'¼f˜iPJ6êåsá¼ÃH<øu´ýÃVw[2™„$Ilìd˜iRkù4œ6<ö¾Ç&í+3™ dYF"‘`%/Ô¡vc[¿”Nr8ÌV¦Ü*`¦)Ô²ït^9‰¶‡ñÎwâìEʉD&æî`ê…Þš‹†*IÎ:k€·5»(5£Öc[?™Lªªº9Sx Ë0Ó£z[ ÀgV<‹Ÿž]yÞ† "òPP•@Í?†óÏ:µ`»®ë°,‹ * S#ª‘ÏÑGNÅOæ¿ áÀF"V1L©v@»øuñy2™4 ‰D‚å–aª`º²¹ë¬³ðí‹.Âðøµu¡¬ßLà™®|>óÊ[ /ï¾öíÐ'æÆ`ꥫ(—“z¶£(lv1Bµ†@x§¨ªÊ ø¦ÌD6G àGÇÚqÙnŒ!ÖÛ2­È©3?E0˜ÿ¿ŽáÀâÅÛTUE¬8î!Ã0 åèüxþÔÂp|Ñh”³ ,W/¾¦i–\µgš&âñ8b±Ë,Ã4¼ÙE`¦Þ±ïx}!ì"7Ê\Tè7YöòB3L9Ìâ$ë §Là#ïÀGßòc§iš°‹rÒ0LÐ œ‡Jµœâ¼ŽÕï^Z°­··—“æ2L“^€Ñ7 “3h•fd¦®5_ƯŸ]±Ó­’•h4 EQ8DÃ4^¥Ç0Áä Î<½ŠrFG›]šòbJ’$X–èã À¢(°, ’$A–å ûI’Ó4¡(Šî“âÚÓXÀ0 D"èºMÓÜEþýè†a@Ó4ض Ã0 öSU’$!“ɸeÈd2î"]׋ÅÜßé:’$atôËø÷ÿ.t}È=g:†mÛH&“ˆD"0MÓ½/Û¶Ý…!t*“ÉÜ®ëPUµ \Tñ})Š‚h4ŠT*…d2‰X,†d2éîOõK«®mÛ†®ëH§ÓˆÇãˆD"Èd2Ð4 áp¸`»®ëH$n™ãñ8Òé4¢Ñ(b±žyæ™f7¯ÀCÏœ½S&x\¼XÓþ.k_ën³m‘¹Ç‘iif…AÅx 8ð»ÅÆÜmÉd’ç2LXxô zû÷»®ë¼ú€aÂÏŸXˆ ?‡•Ÿœhä$n¦±8p ÙEhiüŠSúN e ãÿ­ø8R†’"´8 )¥é:ί˜&E-)_KýOÊl*«mÛîõ/üE¥çð_ß_ŽÉÊE÷Z¼ýÙgŸEOOO³e yáðÏ`]`¡¨ù¹ý y鹆án£ð›Ñh‰Dñx‰Dáp𦹆ŽL&ãþNŠøT*å4¨íÄãq×p@ûÓ~\£€_ž2™ Eqs!J’ä~÷·=úó((rí—Éd`Y¾˜i±X ¦i"“ɸ ÄK˜S)ßùΗ ¶uuu!•J¹rA2EeñËÕ·eYî}¨ª Y–‹Å ËrÙ`Ñhš¦ahhÜòûž[–å“t]‡$IÈf³°m𦹯&Y–Ý ÙlÜòg2¤R)÷¸X,EQpÖYgÕ¼íÍ6¨n† 6€Ñÿ°ñ¯Ç>Š›°ÛÝ®ë:Ï9™–cVTðÊQœ}Þ!ì_µÊÝdš&‡ûb˜°ê³§aÞ½çðV‚ñ—aÂÑcXøÆî’Ê R’0 Óxj=©,62dH&“+ÍI)˲»Zš&»´Š›‘´jºx5{ñ5i%x,Coo/†††ÐÛÛ‹l6ë*ˆédð¯ð¦Õê´hªX©\j5½eYÐ4ÍÝ'™LB’¤‚át/Å+çé|t,ýOŠºp8ŒD"Q`œð_€[wtŒÿZµNc"˲`š¦kô¡gaTU-8–ŒDtœÿ™‘RŽ+.)é)¼†E=]ãÙgŸm¶–翈¥-­úøL&Sà5¢ëº;6&™"OY–¡ªª+Kd £)àGFF õôþ ßéRüÓïd0)Þ?1IRÿ¸ ÒÕÿå9–3XÈd„B§LØV™¢ø$kåæ!t?S…8-¾ŸRçó׫¿>Ép ¬®‚Êí¯_ÿ˜Œ *SëÝ&˜˜N<ú:޼ëmî6]×]5ô³Â bŸ±W½íIŒB .h0Ê0LsyqéR<{zÿXL4âñ8Eaùd˜€` /ÁªÓAQ W"ëºÓ4ÙÓ“ašÀâÅ‹« ™L&x¡{ü¡dÂá°š¦”q€”¶¤°õ{5Pøÿ*nÿjoZ5íW^’²¸Rp9ŽÍÇL¢‰t¹ñ)‹ýû+‹'SÀï[¼"¼S]gª2ÞŠuR¨ÿ?t¿Ó=–êx²r•;mÿàçFÂëjxñÅ+^ä7¶éºîzG¨ªê¶#¿W1•b©”¿šE­¼hbÑeæ8œ‹a‚Í¡=ó!_éõ£´„aZYaPú9°à¯ãŒüwÿª-†ašÇ‘ ÐÞqÔx’ =Ã0Á ´ñMØñ_ Yþ¤»”ªœëˆa‚q)d?×A*•rå— Ãý_l$ }+é›éXú2Å~­ûú©VŒ3L£X¸pá¤Æ* õDŸMÓtû©ªÊ}+ÃÔ˲X9Ë0Å:|ígvljYˆief…AåàËoàÀ‚Vâ0MÓ/Ë0LsY4>YñV©†Ãavçd˜€`øíæ7ðŽó CG'Y+¯\e˜ÙH&“qs·'…båÃ4†+®¸¢dÿHžš¦¹^_ Ã4žL&ÃòÇ0å§ÿuo=Å[üCžÒ<ïdZ‘YaPÙséIl> ±ˆ†i./æ:qúá7Ü’Ã1L°8þô)PþÔÀš¦‰H$ƒZ† –e¡«« £££n¸-‚=7¦¹˜¦é&s×4e’ašˆeYn˜J†a‚DzÞ¼zï ( Ʊì¹É´*§6»µ ã;£8±ìL ' $Ãýo,Çë#'!Iâñ¸¢„a˜æcZ£øCíwÆ]×9d&Èp8 Ã0à8$Ib%ÈL&Û¶‘H$ Ë2Ë'Ã4Ó4‘Édš] †aÊpÏ­ÀÉŸ\ìæûcyeZ™–÷P9¾hÆŸ8’fC\EP€  ÃZV3LiŽî>†“'^€‚œ Ã4Ÿßl·aCý¦‹L&Ù;…a„®ë®¢–a˜à¡ë:Òé4R& p¸=† 6£xO= @DJ§ÓÍ.ÃTMËT^]¹'Ó§CQ¼ñÜsøìßü @` ¨ÒÑü6 uQÒ·MÎïOÆÚfå·ûUL¶ïa˜ÒœùëCXsâ Ãàx¶ 0ž||VŽŸã*‚dYfÅ-ÃÊ È¹Q&xX–…d2‰l6Ûì¢0 ã#³‚–aŒÜ÷<–íLN˜Ë0 `ºò9~Xý¦€h4ÊᄦNLW6–•B Sª‘OÛ¶9Ä4Ã4€éÊg6›å±,Ã4€ªÆ¶bäÃoÆ{®è†aÈf³¼˜ii塲mÛ6 `Íš5عs'úûûÑ××7é1ÃqÍÁ7L&ÑŸSB](-a˜ÚQ|ªÎ^ëq$“÷²bˆaêH5òyä‰yè¾â-0Mš¦±ÃÔjdóÀœËˆa@5òùì³ÏâÙgŸE*•jvñfVS|2 Sª•Ͷ¿‚³–¿ —_~9z“½H¥RleZš@T°eËôôô`xxëׯGOO:;;ËóŽWNâ#+Ʊm(ŠÒœ)ÓaxxÝÝÝÍ.FYÆÇÇ1666i7› ×á\¡ùìèè@Û»Ú°æƒkš]ü’½mår9´··£­­­ÙE)I+¼?æ ÕÈç{Ÿ9ŒË¾¿ ûØÇ044Ôì[( Ú¿?˜J¨F6/^<+”µ³© ]Þ+e6=“ZP|.\¸ŸúÔ§š]ôÃm:xÌ–gR+ª‘ÏÙ@+Œ+e¶´éÙôLjA5²yðàA¤ï™ž#/â»ßýqàB}½/i…6ty?pà>\Ós&ä×àà ÚÛÛÑÓÓèîîFww7'=îà9ñ½Ó¾‡H$($š]„IÙ¹s'¶mÛÖìbLJÐëp.P­|>vöcø×Gÿ5°I®ƒÞ¶¶mÛ†;w6»ei…÷Ç\ Zù\ñ ¶mÛ†‘‘‘ÀõŸ­Ð¶øýÁLEµ²9[˜Mm0èò^)³é™Ì”jåó¼óÎ ì¸v:p›³å™Ô‚¹Ü¶Â¸RfK›žMÏd¦T+›/í9Š].EtñؽlwàæžAïKZ¡ ]ÞŸzê)ìÚµ«¦ç Œ‡Êðððk[{{û”1ù~¾ûç8xêAùÆ‘fßBIöíÛ‡76»e9zô(Ž=Šáááf¥,A®Ãááa?~«W¯nvQê~ŸÓ•Ï_þò—¸sï$)°Ï/Èm ^{í5˜¦‰­[·6»(% òûãàÁƒxþùçqÊ)§4»(u§ù|á…ð?Çÿ'Î{ô¼@Ê@ÛÁïêÙ·oöíÛ‡Ë/¿¼ÙE©+ÕŽmŸxâ ¬]»6Ы¼*!Èmpº]Þ+¥’gÂcÛòòùꫯâÎ;ïÄ}÷݇•+W6ûfÄ\jÓ­ÂTτƶo¼ñF³‹ZwªÛ®]»gŸ}6–.]Úì[¨šVWÊlyÏTòLxl;ùØö5ÛÆ;} 7ŸùcÈcràÚEÐû’Vx/YÞŸþy¼úê«X·n]MÏƒÊØØØ„m•¸3-L ÃÌFª‘Ï/}éKøÒ—¾Ôì¢3̬§ùüÉO~Òìb3̬‡Ç¶ \ª‘ÏøÃøð‡?Üì¢3̬‡Ç¶ LªÛÿ"ÿé+;†© ùÕÞÞ>aÛTVN†aË'ÖO† &,› \X>&¸°|2L0aÙdÀTº»»'bГî0Ì\å“a‚ Ë'ÖM† .,Ÿ \X>&˜°l2ŒG` *===s“ #—ËÕ<ÆÃ0Ó‡å“a‚ Ë'ÖM† .,Ÿ \X>&˜°l2ŒG`r¨@?6oÞŒ5kÖ`çÎèïïG[[[³‹Å0 X>&Ȱ|2L0aÙd˜àÂòÉ0Á…å“a‚ Ë&ÃNqÇiv!üär9är9tvv²Ûà –O† .,Ÿ LX6&¸°|2Lpaùd˜`²É04¨0 Ã0 Ã0 Ã0 Ã0 Ã0 ÃÀäPa†a†a†a†a†a† *lPa†a†a†a†a†a†™6¨0 Ã0 Ã0 Ã0 Ã0 Ã0 ÃLÁi_ÿú׿ÞìB´*¹\ÃÃÃn2¦r¿@{{û´¯%ÃÃÃX°`N?ýô@•o||¦ib||çœsδÊÐÈúcZ™Èg³e³’24[>ƒP>¦u™L>ƒÔ¶ª‘ÏfËfÐê™=ÔKn›Õë!ß¾—zõÓüŽh-ê9' ’|ÎTþy/õœã²|¶õœ“6£-Ôcs¦eeùœHêd||/¿ür`ûŽ Ï‡‡‡ñÜsÏ^oÛpÝšÃTÅm·Ýæ„B!gÆ ε×^ë|ô£uÆÆÆÜßïºë.÷÷P(äÜu×]ÇOõ{-yá…œP(ä<üðÃ*ßÎ; êðæ›o®¸ ¬?¦õ˜‰|6[6+)C³å3åcZ—Éä3Hm«ùl¶l­™ÙC½ä¶Yí±òÝè{©W?ÍïˆÖ¢žsÒ ÉçL寑÷RÏ9.ËgkQÏ9i3ÚB=æ®Aê;[ñ™ ÔÉm·ÝæÜvÛmÓ._#Êô¹ñÍ7ßì\{íµ×Û6C·Æ•*xᅜիW;;wît·]{íµŽ®ëîwÿƒÜ¹s§³zõjç…^¨ø÷ZB Ãß°‚P>9×^{­sÿý÷WT†FÖÓZÌT>›-›•”¡Ùò„ò1­ÉTò¤¶U|6[6ƒV‡Ìì žrÛ¬öXùnô½Ô«ŸæwDëPï9iäs¦ò×È{©ç—å³u¨÷œ´m¡s× õ­øL‚N³ëä®»îr¾ð…/8«W¯.iPiö3 úܘ dà)UÞ Èw3tkœC¥ r¹zzzÐÝÝín»þúë166D{{;zzzÝÝÝèîîÆàà`E¿×’twwcÍš5î¶ ”oppcccØ´i ­­ †aàú믟² ¬?¦õ˜‰|6[6§*_%¿×‚Éä3åcZ—Éä3Hm«ùl¶lVRG,ŸL5ÔKn›Õë!ß¾—zõÓüŽh-ê9' ’|ÎTþy/õœã²|¶õœ“6£-Ôc³ŸIÐ B¬Y³}}}rXiùQþ Ïs¹úúúÐÖÖn82Ö­ Ø R===¸ãŽ;ÜïãããØ¾}»Û¸†‡‡'ĽkooG.—«è÷Z1<<ŒíÛ·#‰LØÞìòår9¬Y³Û¶mÃÆ±yóæ‚F;YULk2ùl¶lNU¾J~¯“ÉgÊÇ´.“ÉgPÚVµòÙlÙ¬¤ŽX>™j¨—Ü6£=ÖK¾}/õê§ùÑZÔsN$ùœ©ü5ò^ê9Çeùl-ê9'mt[¨×Ü5H}çLËÊò9‘ ÔIww7zzzJæÅÂ3 úÜøúë¯G?ÆÇÇ188è.Èùn¦n *3dûöíX¿~=zzzÐ××À³Öùñ?¤©~¯ãããØ¼y3¶lÙâZ+½~#Ê—Ëå\«å¦M›ÐÙÙ‰7º w²24¢|Ìì`ºòÙlÙ¬¤ Í–Ï ”™ËgÚÖLä³Ù²YIX>™™RK¹mt{¬§|7ú^êÕOó;¢u©õœ4Hò9Sùkä½ÔsŽËòÙºÔzNÚȶPϹkúΙ–•ås"A¯“ =Ó Î‰\.‡­[·bûöí®1eª2}î^‹2²A¥JÆÇDZqãF àÖ[oÅ­·ÞêþVÊúé·pMõ{-ÐuÝÝÝ®«ØØØ†‡‡1<<ˆò¢¡nÙ²===èïïG__¶mÛ6eU>¦u©V>›-›•”¡Ùò”ò1­K9ù BÛš‰|6[6ƒR‡Ìì¤rÛèöXOùn†lÕ£ŸæwDëQ¯9iäs¦ò×è{©×—å³õ¨×œ´‘m¡žs× õ3-+ËçD‚^'Ay¦AžÝÝݸãŽ;p÷ÝwcûöíÑÛ6[·Æ•*Ù°a:;;aF…­ø!Œ¹–®©~¯ãããØºu+¶nÝŠ\.‡ûï¿÷ß Ê×ÓÓ3Á‚èÿ>YULëR­|6[6§*_%¿×‚Éä3åcZ›rò”¶U­|6[6ƒT‡Ìì£rÛŒöX/ùnô½Ô«ŸæwDëQ¯9iäs¦ò×È{©ç—å³õ¨×œ´Ñm¡^s× õ3-+ËçD‚^'Ay¦AžoÛ¶ [·nu¿·µµ\7òÝTÝZE©ë™îºë.çÚk¯u~øá‚¿^xÁÝ' 9?ü°ã8޳sçN' 9cccÿ^k6lØà^/åsB¡³sçN÷ûµ×^ëÜu×]•¡ÑõÇ´3•ÏfËf%eh¶|6»|Lë2•|­mMW>›-›A¬C¦õ©§Ü6³=ÖZ¾y/õì§ùÑ:Ô{N$ùœ©ü5ê^ê=Çeùlê='mV[¨õÜ5H}g«>“ ”:Ù°aƒsÛm·M»|õ.ÐçÆT>:gÐõ¶Ö­±A¥ n»í6gõêÕþüz×]w9¡PÈÙ°aƒ … \%¿×šâ†„òÝu×]ÎêÕ« 68×^{­sóÍ7W\†F×Ó:ÌT>›-›•”¡Ùò„ò1­ÉTò´¶5]ùl¶l±™Ö§žrÛÌöXkùnô½Ô«ŸæwDëPï9iäs¦ò×È{©ç—å³u¨÷œ´Ym¡Ös× õ­úL‚LPꤜA¥ÙÏ´æÆ$+t ëm­[;Åq§¦þ6ŒK.—C.—CgggI—¡©~Ÿ å£k´··£»»{Zehvý1­MÐÛVÐå3åcf'­Ð¶šýþ˜Iß”:df3isAk3)k£ï¥^ýtО 33fK[˜©ü5ò^ê9Ç Ò3afÎli ­ôžaùl,A¯“ ?Ó ”oxxØ …tùnd²A…a†a†a†a†a†af 8)=Ã0 Ã0 Ã0 Ã0 Ã0 Ã0̰A…a†a†a†a†a†af Ø Â0 Ã0 Ã0 Ã0 Ã0 Ã0 3lPa†a†a†a†a†a†™6¨Ì!†‡‡188ˆñññ¦–#—Ëa`` ÙÕÁ0Mc||ƒƒƒlvQ&ÀòÉ™FµO’Q†aZ“júÙFöüŽaæ:Ó—²|2­J«Í­‚¢3òä¹3ô2­ö~ lP™ŒcãÆØ°an¹å\{íµnZyr¹¶nÝÚìja˜¦°mÛ6\{íµ¸å–[°yóf¨ªÚTy,†å“ 2jŸº®cãÆÍ¾]†aª Ú~¶‘ý¿c˜¹JµóR–O¦Ui•¹UÐtFDÐçÎ ÓÊ´Êû)¨°Ae@ÇŸüä'0 ëÖ­ÃæÍ››],†™“ ‰À0 üú׿Fww7¯ `˜188ÈK†ia‚ÞÏò;†™Ë}^ÊòÉÌU‚*›AïÓ†™»°A¥I `||ظq#¶mÛغu+6nÜèþ>SÆÇDZmÛ6ô÷÷£­­ °iÓ&\ýõî>ƒƒƒ%;%*C­ËTªŒ¼Ò€ õlûãããèîîv¿¯[·Îu_.'‹þ2ÕûQª¼,ŸLP©uûÇæÍ›Ñßß?á· Èg£úf†)ÅtÛz3Ƙ“õ³Ó=O­û¿ÉÞ1 3¦’© ôa•ÌK§s.–O¦)Õv§ê+ƒ.›­Ð§3L­i´~¦s@ÖýL6¨4‰­[·bóæÍhooGww7n¹å¬_¿¹\ÝÝÝØ¶mn¾ùæ_gç΀îî“þb¹•8[·nÅÍ7ߌ±±1ôôô`pp°æ«ÆÇDZaÆ %Ã4“z¶ýÎÎNWÇÇÇqÿý÷»ƒÕÉVÅ5êá‡å“ 2õhŸ7ß|3úúúJž/(òÙˆ¾™aÊ1ݶތ1ædýl¥Ô«ÿ›ìÃ03a*™ BVɼ´X>™V¥\Û¬¯lÙ zŸÎ0õ Ñú™zÏY÷3}ÞÔìÌe®¿þzôõõ€k¼õÖ[ˆŽcûöí3¾Y,ׯ_ïnÆ­·Þê^»¿¿¿lgÙÙÙéþÖÙÙY]³f{ß êÕö·lÙ‚ 6¸ƒæÎÎNÜ}÷Ý&—E 1ï ‚å“ 2õhŸ[·nE.—Ö-[J®| ’|Ö³of˜©˜N[oÆs²~¶êÕÿMõŽa˜™2™L¡«d^ZÉ9X>™Vd²¶;™|¶ŠlµOg˜zÒÈù³rƺŸê`ƒJéìì,øî·ÿF –M’·iÓ¦ 1­6X·n6mÚ@ °nÝ:×¥³===îçrûN·LĆ 0<<ŒH$Rߊf˜*¨GÛÇÍ7ߌuëÖ¹+k°yófÜqÇS–©ï ‚å“ 2•´Ïé´ýááalÛ¶ [¶l©ºL”ÏJÞO S/ªië¥b? ÔþýÔæÃ0S1“¾¡æ¥Ë'ÓºT;·jÙ jŸÎ0õ¤Ú1q½æ€¬ûi,lPi1zzzð»ßýnZûoݺÕí!Hعsg@6ªLÄš5kÐÓÓƒôôô°Rˆi9¦Ûöï¿ÿ~är¹‚U5[¶lªª®‹k%Ë'3©¤}N§íßÿýhkkÃý÷ßûï¿ß]©Gç¯E_YŠjå“aæ Íègký~¡r5ãÃ0õ¤óR–O¦UiäÜ*ˆ:£jÊÕŒ¹3Ã4‚zÍY÷ÓXØ Òbär97ÙQ1¥|ííí„uŸ„¢Ö‰‹¦[&‚\ɶoß]×9 ÓrL·íçr¹ +èûØØX ÊH°|2A¦’ö9¶ß,eIµòÉ0s…fô³µ~¿Ð6†™m4c^ÊòÉ´*œ[QgTM¹š1wf˜FP¯9 ë~ '¥Ÿåtww£³³º®»Ût]G[[›+LƒƒƒhZo½õVlݺÕ9È0³•uëÖaxx¸ –æÖ­[ÑÖÖ†5kÖ4]KÁòÉ™ZµÏžž7~u¿V ¿¿?0}%ô"–›©úYضm[ÙɦŸZö•¼c¦ž¡›j^Z©l,ŸLëRªí6[>+ÑMG>kE%}:Ã0µƒu?Óƒ=TZ ¢J¡D^Ôáûßÿ¾ûûàà ¶nÝZµ²š2ùéééA__n¾ùfN0Æ´ÓmûÝÝݸõÖ[±yóftwwc||cccèïïG[[ÛŒe±e,†å“ 2“µÏ™¶ýb‚(Ÿ t=ÆœªŸàއ§J´ÛÈ÷ ÃÔ› ôa“ÍK+•M€å“i]JµÝZËg=tFÓ‘ÏZ•«’>aZ‘zõS¬ûi,§8Žã4»Lýw“­Y³fB400ÀO†i“É#Ë"ÖO†™>Í›©Æ½7nä„¶Ìœ#(}ØdòɲÉÌU‚ ŸAí;§*Ã0L3`•9‚ß]³˜ÁÁÁºÄÈd¦4åä‘e‘a‚ Ë'ÃLŸfÉÍdãÞ­[·Îh…-ô"AêÃÊÉ'Ë&3W Š|µïœ¬\ Ã0Í‚=T†a†a†a†a†a†a¦€“Ò3 Ã0 Ã0 Ã0 Ã0 Ã0 ÃLT†a†a†a†a†a†a¦€ * Ã0 Ã0 Ã0 Ã0 Ã0 Ã0SÀ†a†a†a†a†a†a˜)`ƒ Ã0 Ã0 Ã0 Ã0 Ã0 Ã0Ìüÿ–Å}ozå%tEXtdate:create2020-03-05T16:38:18-06:00n;×+%tEXtdate:modify2020-03-05T16:38:18-06:00fo—-tEXticc:copyrightCopyright Artifex Software 2011ºÅ´1tEXticc:descriptionArtifex Software sRGB ICC Profile †2tEXticc:manufacturerArtifex Software sRGB ICC Profile\~=Ÿ+tEXticc:modelArtifex Software sRGB ICC Profile1(‚¡!tEXtpdf:HiResBoundingBox1584x864+0+0û8²ùtEXtpdf:VersionPDF-1.7 7ji»IEND®B`‚blis-0.9.0/docs/graphs/sup/dgemm_rrr_kbl_nt4.pdf000066400000000000000000005134711422157504600216030ustar00rootroot00000000000000%PDF-1.7 %Çì¢ 5 0 obj <> stream xœì½K¯o9’Ý7¯Oq†Yƒ:"7¹Iî©[€`À¶²f‚ Aw¹u–Ýjüõ͈µV÷¹7_å‚á GåáåŸûÅ×/VDð¿}”ÏúQìÿðÿéoøwÿq~üõÿúCý°ÿóoýßj«åãO×S>êê³|Æ*ås¿ýáº×õùÜQòS”¬ZÊþó—~Ä*ª¿¸?þï?ì{ïÏS®oÿã?þûï´™%õþœv#?¾Î*«¬{¿¯qßë³¾Ú‰’£–©ý™í\åjŸÏë£$ÛQÛ‰?vúz>ç«(9Úa™ÚÑŸÙŽ½«õ\ããÛÿØÿ¿íWáƒÿóOûøþ¼»Èú¨×ÇŸ÷Ã?îÞ—´w:êç~wþÛþÓåºfß/²ÿpÛ~¶ÖJã?ëûúCý¹ gÝ{ÞŸcžu¶ÝkÚ÷ÿüçÿð‡ÿñÏøß¾× jÙUŽîøã7]ÔúßXŸ¥¿j©©Yjÿ¼{6¥‚³©¬¤¦ÎZÑÔu­Ï«M±àÕTTЦŽZÑTïõs­£)¼šŠJÑÔQ+š÷ýyïJ¯¦¢R4uÔŠ¦Öx>¯v4Å‚WSQ)š:jcr×>Þ• Φ²’š:kýÖ^ýŒ}ñY?ÆîweýìÕѹþ4?®úÙÆÜ?üçý¯_ûqT,¨·Píú•jª×~­¹Žzý7¶÷u¼ü\½ñ‹ƒé?}Ôaoè?ïÿ÷ϸ>þÃošî¿™e¿Lî?þÂ\U¾7D¿´ò _·}ú÷µoû'ûÈ«áÏÒwiøÀÿþWùì×5øŸþØ?Ÿ¶Úÿó¯=ó—OÄõó‰éíòÎÒ?/›¹jÝ_azߘûkxÉuíO¾WÄö9; žÏaUö+»PÒæ^ ÇÚ·Õñ›Þmú«=Ÿ½yÉ}}«Ó×g(yì¿ÆÚëÝDÉ6½Œ5Çç@ÉìŸmî’µÿåò’µçØ};†Ä.yìÞdz¿äu{Éžtæ^–ž=i%×~¾juöÕ‹?çU÷¿Y{ßú@ɳ×Ý]²{4î纆­2»«]˜×ëÕ|±Köúý\ûÝÖ¨¶ûyGÉú´*}ð÷ôùÙ¬Ê^¦/”Œö¹vÁ~–‚ßÌj÷>ËSìé¼d}Ú¨Ú#ò³ú;½ö;ØwºKüŠVò´ÏauÚ.ñçlûߊÕÙ÷0*JÖç}YIû¼/Ù[›gî’QìÝZÉÞu_0ççðçl{Ôí'ö_•’µ{Ù®SË'šé{»²«\Å_¶•ÜÍú%ûƒKó¼Q²7sVç.XIv×ÙãzŒÝq7ûý[ªÇý¹P²ßŠÜ»kâï‰Å|ÍOoµï­Óîx³í ³Û'VÒÙkûžtšÕiþá½dÚ‡žm¿¬†:í¶½À.éX}w?¾¬ ͆Ûïû¶÷ü1íáýöÝîýüÁð“a“×.Ù_§û«êóúì»N/u/Ù³í+ö(cËûY|ëQ—~õt­^‚op—ËFëÞ¬è»ä±ßï:ýñ®»“í‚¶ŸßÿÞ/`Xöð…ßûŸö3ö=Ø&ªìÚO»KÔ!î>m°ú†Æ_̽_}·*·žàÞ£öñfn»o/yìçóznGV²Çñ²›±O°ü+O»oÞïS­û̾ÿ…·³g©joku¼‰±»ØhlÇŸaìYª<¨ã ýåm¨ÞÕ–”,ª÷ÖÕ_ÖhÇjß7x£™Ý½Ü f…qWªÝÖC4¼éc±T>ÍÌÛÚG•Ù|¨Þ»‡-Üðò~¸5 ]¼Ääþ »gù;{’*^G³ÂžC|¨Þ»Ž¿õicÍÞÖî×…’e·/õðÝìQá#õÞïèñ/³{¸ÔÛ:ºßòîf>Tí³bDíô¡zï÷ˆ^1ïÛ‡ª]«áW{’²¡º1ÐxÇJ¦½í]0¬Ë{Áò¡joÓÖÜPd6ká¡n¼c|Ø®Ãkß뾸¯5ÃvõÕðËkßO‡ÙoíUÈkßóYñgX{޲Áºgü99Rwó‚=AùXÝÝ3ËÚkÕ+¾îÚ]ÞÆêµÇ# ¦Õk?*“5»Õk¿,Aka?¾ï‰Ÿe-_X÷”ú`BZ¯«»`ÙèÛ%OñuuîOø‰~ª­«ÓVS,´Oõuuîå”}ä¹l]Ý­T¾…§ùĴ׉ʎõt_WwßìO÷uu¬Vrûºº Å÷û ÿ·Yvïöç~¦/«»™›KÉ3ýµí*Ãz¥•,Ÿé÷ÊÖmdYÉãËê.ÙSŠ=æUŠÏ®~;u¢Ä×4üöAvÙâéË*fÛŸÍw_š¬¤qYÝᯖÕýÖžæËê]Ñù®rcYµéññ‚Áeu‰¬ªÅfC”L_U÷βa_r•…Uµì)6{Û6Tí6+~°ªÚcâ†Þm¬ûœ(ÙŸÑÆj±ÿª^XUËžMù« «jÙ#³ú3ìUÔǪ=. ºm°÷ îw=ñ£«j±]×B VÕbkœßòž·l¨›ÀýïiÁ‡jiD¸ÝŸ}U-v hwaYµ÷Çv¬«öþp{ûSùPµkw/¨XVí£6`Uµ/èÒu]XU­oÜ(iXU‹ï佤ca-{xãó^û•ܨ¾n,¬V‡í ,¬ÅFÎ@ V»ŠœXX­Þ¸Öò…u¿Ñá[™ëz|]Ý{Á=sâ1¬«¥rI¼ZñuµìçG+­baµ|ÞvùÂjÙñ·¯«û:\¶öîëªubTéXWËžú1€ÚuÕ®ìËÂ.ñuÕo—%ëj)7fÐË'=«³'¢-ï%hZ½Ï-¸øz°ÞÏæKäÕ¬«vǾ¿Ý_¡Û Ýu&v{{ë «—ôŽ,¬ö«âíØ~ÄëžÙÚ±}²Ý6h—m$öXõgJl]Ý ;­«ß¾®î’Æ>ч¯«Þóñuû¬¬káËõéËê.(Xä÷æÛ—UÿQÃý>¾¬ú¾Ïd«Óão´b7³K|]Ýun¾ã»úºêoÏt_¾®îu›Šën¾®›ñnnµ ¿Zh¹ûºêoÃá¾}]Ýu¸|l>°uÕoïÂí-7ª”ØÒˆ;ö­K0¼Ý±_éG3)”_ú¿À¶þ¦ÀËþåE;Q`lX“+Q 5˜O¸§%À› ÐÀê íÎ _|B`gç \ûUbû"\»=Ј p m¨k®@>@àŠÍ§ píåv‡-é`8lI¯(níXÑÖt,•„ÀaKºßp<Ú¨wÁÄê%tŒåÝ-.V¶?Ç•€{êâ¼$ÜÝ´鉀»Î#.Û`3BÜË 6 DÀ]r¡s ÷¯·šdÀ]2¹E$î_i/L¶ŸÀþ‰ ¸K† ÕÐG(`ó лÿD@@LŠ12 MKørbÀRdÚ䊞$LÄ[¾ýMˆ‹M|(!Z a mP@ ,›¿Ø )з6×ÇA¶Â~ThûŠ‚‡ Ú~¶Q -Á E ´Õ6R `( Ëþblh;X;„¶Ÿ‚}AXúÃÇZÉ$õq½ê²‰ËuñÄöœ( ÚÝT4L ´f`úÚíà{ íâàa ÕÁ˜¿"–Ε&8Ð6×ÉeÖBêúsöäÀ3Ž8°Èè›Âà@ks™8Ðú$^©8Ð6fD:r íÀÖÁ‚Û–0À‰­cƒÌÖýpA` BÚ6P/´½F¯ Ð6(¼8 °„]JXöÒÀXX¬vMï|d@_¶ÁK@@,œÏG" ÏcåDÀ]ÒEY@@Ÿµð ˆ€>·°PàþÕb?"31Ðï×z Vrྖ‰è%èÖäÀó~Àûꕆ è³qE‡AY9@pÜ´B‡³èÑAp¯ ‹3AЯôàGÁý#ú‚¾~øw î.âäÀaUÉŠ“öUÛŸáWAÿ“ x4üȼʑ)Ü%ƒhr ÿHBô%{u©¸n¸Ò5®¬{LÅÖ=“χ½{p0pW˜„»‘F°!î ­¿âÀÝNÙ‡½ûz3ķ•51 èO€­91ÐWzŸh…~qÂcãʺßMÁ¯Ä»Ï?(¹¹²îX%re5ò@Ë+«YMpƒ“K«½|bÖÖ=S€R—Ö -€½M8p—,‘ з;@qRà¾ÛÊ0)пÜvý‰Àë¤@¿Ö":úµ°1'î’‹Šèê>)o÷ Äö uHkqñM äMè= , ÜÏIïQ ¿½Û ÔÛ ÜÿNÀÝ“è»Çœú3Ц 0L„@ŸlY(K• п l/ö¥PôvpÏ‚Àõtþ* °N’,!лÆ.!Ðß Þ¹ PºLR ¶MAу 'ìî’ Íã î"©0Ðf[Àš0°òO2`ü$PÈ`@[ü+–C_"`½Ø«w Þg  Ù$€sDÀ0Rמb›$ÀýИCÅ}8Åv'½Ëÿÿó¿É~.y¾¤À=®î·8Ä0‚À'LË„@{Úm“ºÀ€ñ:‚ŸÝ…’d@kõ&r"5³‰¼TÀ£$TÀ.íP*àžœÞømC´ÍÌ MM„8T@kÐEÌk%6bD`js@Ûé€÷€öA)A’MÉ4 ÍŽ‚ w ¶!BÀµ? „B`üH¨®˜—Z+„%´7Ä" Ó€ÞãP‡¸ö"Áv€kßžJhÓÉE$Ä2e%/´‘5I€¶ëºñ@@«R_¸QÐëPUwCÜ%!‚˜Ó·Lz 6WD@¿ú}*^B• ˆ{>ЯQŠ èuðùÈ€^!â)N%ð¸2 _8<«€½Ÿ x\‰ xVº*@@ÐQ‰€þPÏ)úÚÊ:@Àã%“wÉ&ÐëPd” x¼ 2 ß6Ëd@t R!V+«xúSQctÄëƒZôîßôô@"àn¥-€»dqr#ú•Љ€n†Z¸a  ¿ ˜7ˆ€þ‰|X«¬OIF!÷)$)Ðë`:&î¹ý!ÐqH^ç>¥@‡¸ÿ~$LN.W€nàÚ».r$pípQôÚÝbÂî6øŒb@{Ud72à aM ¸R<$Z …?2 µŒ [ ¸¾a@+é§è%¼C2àñdÀµ‡:z‰p "€Vå”}¥m>WwÑèÆK@"МeÖ)î’‹KŽÐ.„iU¸Bëšô9¥@o‡øI\á’!´«Ã²!\{Òë/\ÖW>´*“â pIR ´ÛÀD9òŽ‹{n! •LB¡¯­y%! ­=hh?y)ùÜ€ñF­äE€Ö5€$@+ ç’í‘&¨Œh%ààÚóÇ]hW‚}_¸[þ8ðÏ~B#þÙÛ„*)ü[{¸ú”øçFp\øg½º ñÏ~4Nü[r8 þ[2P.Ó-_x”­ÂpÉnh¿§è_w! Ý2öÜBÀµ'äq ~­v ^ÕhA’hU@PA€7·zA€Þ‘p)"`>оC¾íGèDÀ|9¢@ɧèÅ:¤@k¦œR TŽ—¸d¢ ´g/)ÐJ:…?P ×!r]µYuHùÚƒe Ìk‰_‘—LL¢@»eêq¤@k:$)Ð~ALèU^Z ¹>”þ¸°îîñ ¹°šóÚ!.YƒƒóÉEùN‚yËÁ%£X‚à^Yˆ†$ÁãW$Á£„$hOŠ9G$¸db ú¥€"AÙè„‚ÖJG¡`çvž(ÿ7ñï‹'¨›:NúÓXH pté{”mí¸]¹JaG$ 0<C™­ãâBá*)$À,‘hWFJAw:z þí*Eæ:•Aôç%/ 0Ä»ÐmÿúqðŸu“ç­†|j€õÅO(ª¡îµkNh€¶`B—“h3(M`^K`ˆc¡šßÉ[´-)êHÜWÀ|àþU9AýWpÛ pFàƒeu áÔ+g»Ðé”`¸v‡¸K€i’Ã{ 4ÀÖ‰¹¡î×¶^h¿º_hu‰Òw;o °uúÃ…hz˜Kà~†ö@S¾°û °Uî¬B¼8S¥xÉ]´Ë»¦sO"à#O" ‘ªHÜ%€/úª"à âãÒ*e=UÀPtB Í,TÀ,‘ xM qRÍà*àR(Ð~ýEŒvBìd©€×- R*à~Ù$E©€Y °È}5”ÀŠi<•@9"¤xÑÒ’Jà®ÿÕP+í ©ÒQì -!š/<`MB Å½…À=˜à¡B`匜B`匜éI!°ñ¥”Àý03C eMJ ÜßB ¬\›R ´Åù…V§¼ÅÀò­aØ?B ÜíPt”SŠC>¢!Þ_=B+c8R ¬µI‡ÐÝ Ü£C ´`–ŸN)°SS ¼ˆÚ!¾ðÙ¥P¤ÈÅìÐ/¾ÍÐ+ÎÔ÷õ·;(ƒ”°R"O)†5$šFÜ %n%é Zd¹ )°Ò|”J`•{h(¼¿« AÍKç%î’Ÿðá÷GÐBË֯ˀå[=é‚4:$šÁ4Fð „“[>逓Ófꀶg?AÝCùô…G:ª .¨_Ý…žÞ¡ÁY¥· gµ•è”çÞ#IÂNC»r‚àÜ#GžŸA/1Ð"œ`V<`Ûÿ‚£âÛžg°¾2°Ý èóÈñ€šŸ#p?/ÉFñ€íVÜ£â[¼ÅÚë)Î.¯–ˆ4Ü¢>ÇxÀ./‡ˆ´qZOœMª£Â{xR*°KV8`¿·= ´X/t…ö¸c8 E§áÛ)жúØ£')°'œÑ´§^Ggл^ ö£3è}É UΠw—¸$gP«C\£3èm¸ \£3èÀ HœcÊ¥OÞ F/gPÛØS†¤3輤ÞÈtÌÂ,gб—5¹~Âtì_¿„À9=^ú#XpŽÎo'_Pcœrè€{[OCUø‚ÎØÊtÈGW® =ü]A÷ÄÀá!WÐûÑ^X® ·-=I‚»™§G“£ý@ç ŸKøŽd3úN‹ÎxÅûÕGRàÜNœtµ‘Öà:ÍÇŠÜ@÷S¿ÃçnpI/Ð}ÿ ¶“èžlèK(/Ð=RiÉè´}Jè:Ð('P{ßå”w3KîšôE‚ODî®CÏPEv©Ò (¥XŽ ½Ž·8»–®Œ¬Sq†pµMT"9‚6£µ3°Å  hÀ–øÆh@Û—ÁQUÑ€—Mì¯hÀ+Ä/E^%€NÑ€1g) poÕ0}+ ÐÂéú©N[10·( ÐÂô0ž¸¿»‰"«yâAâSDàn¯ž*à¬1¥GHà%Ù7B#`‚!¶* $°ìÓÏ@# ˜7"$0&¿ œE‘{ ÔJRb2"°+z7Bwݯ!·¢–Ç µ&Cµ¬ LçP…ö®è¾ ÄHK 4܃=@ þZAd‡+¨9+$¦ÃsÆÒ=¤q $âáÚŸ(Ë_ -lâÔ ü‹à¦À? q8%@wÙE*pwvz…‚þü³ÉãS±€÷ç;ð¦ãQÀßžaÞ‘€}`úŒHÀýÈý ¸;v™ þ¨ øH+;BEAÅ®¯±€aˆXÀF?†Œ¼Êç;ð¢ý3CkÑÅ xÍÐ]x¡€áÆì·ÿåÅ~~­ûÍ~ûPbc,ൄhŠ´‘|H€G )ÙÏáëD0`Dße4 çË#ð‘êÍè m‡Žh@Jñb?¯Ãûí;¾DJÒŠhÀÝWñ‰þlœð‡O|Ò_Ùd4 …î¢NCxÅö_ÐÂö^á€!Øü"b™Ò#éO1.I7“™$þ È|°p$þ­.¢Š`@ Í ¼…ˆÂ¿PŠÿ$+Á€ñ+ñßêróÊË(pÉD–Á€tý \…h (½âÇÌ=×lý{eûé¶{¹ëG¦RIä„ûù±Š*Ä/2ëÌý•lrß¶%™uíu¬rd]k¶gš¯v¢äh‡ejGf;{×ãÒÅñ¬Q’í¨ŒíÄŸG;¶Ål¯v¢äh‡ejGþ£³Éµj@pÿ½Ùäú÷²ÉÕûË~Í&·K‹4EW¤)ú^7ØÃýJ2ÝÕ×¾jѶÿ¯Jj*Å©©3QœšÊZlê¬ME¢¸hêHME-5uTЦ"Q\4u$Š‹¦¢–š:*ES‘(.š:ÅESQKM•¢©HM‰â¢©¨¥¦ŽJǘd¢85u&Š‹‰#j±©¿'›\3‹¡tÿ{6¹_É&÷[¦ýofÙ/“ü¿0WG•ïÐ/­üî¤l¶YÚ¼ôÿ«¤l{;›þ×,¶V?÷.ný°²03³]¿ž™m¿Ô½åøðü–ÃÛßû-¶ënp°£¹´]{£àþuJMÔ,ÇŽû×Ù>ul~vo"†·k5ú×Mì/ö».ð¯Û#Û÷†»Ä£ÅÒ}»5³§1VÁõÜýŒ•æ ÚêLŸ²ð.™Ø]¤»Ø¯î†°¢•݇/³µ #†?§™üºp¥Ýžo®%QÛðÍõ†b·§ì´/Ƴ*JµµU µ™ÈdÿéÖØ èÔŠZ{a–ÔÇSF-lÀÛ}{ô»—¸9¥Y~ßeFB›5PǼBÌfu_Øì7³¶ºÍÊÒ áê›h …mw<ÐŽÕ,ƒÕ`r‰ffGcá{0,¬âöài†IGê6jEÂÕB=h—,OaåØl[R¢V6ô”abµ|¹!ocë²ßÈß}—,gá!m¶ ©Ä{n÷Þ:Ý4éfQ³*ž †e9GïÕåvñ内nxJmmšAÍŒÏcDÉt¶ÇšfP³:ÊŽ·ÐEË2SMµ‰þâ-ãuÎævQ·ãELó~Ä¥pƒó¾`Z6Tq¬ÿ¯×,¥6VGtëiF0{…økï `W¦ÛÏ.y`W–×u›Gqú¾ÆÁ´y¢’Š»ußÄ{Á°|C§l6ON·–ÒO·™÷£Të诫uš–éCÓVwEuß_‡= ™“¥Ô«©•ÜîÐç·ƒëpþ¦4ÉZä T3ÂcJµØ‰vÊÞCDìãúWóp)ßòÑšÚ,¸lâ*nèk&ùÕq~×°ÙíðÌ  °º9Vø.q¿27ƒ6óóx¼kRÓhæ¼âyæôòÜmÐ-ùô$oæCÔ¬Š-ChÆŒi6HE«æNwžŠ®À\ÐÜ”°½ÜˆÞi¡ïPsóŸÍ° ºÙ<¿òE÷Án6ŠûHÙÍVä{íB¯çîf³4Ó¡µ»‰Ì¦=…öÒSBr#ÚÍjæ)!Ç×-CšÛ•:õ2¼ÓíÙœ90z™ †åÖu­åkªß`Ã3,_S§-ì7J_öZRa4êµ\L5wÃ)²×êkª'Ùt›L7EpyÚ»™˜Ý°¬(¤^Õ:Q¡ûŠZåϺ °¢V:åözû‚ZåÖ$ºU™IöÒ` j|QurA-p'íua=-öÚ^.§Jz¹K¸œ*·_Ëi±à7oæªXNË`¶Ù~A%Ý«=¬î,§eÒD×/¸%yŠ:Ë©€+êÀÓ~ÿŠZÎ.ÁrZöæÀåÒ~ ,§E¥ýšXNí±nÔY¾œ9pî,§e<|ÿ×ãËiQ”PoËi‰OÐ*–ÓÄ€Ýó€h±ê&*ß|¥¾«é­a9-r¤ì­W&™£]·l¦6Rí .”ܮ騉_Æ$sLƒ×ÛÄrjvYÖ1ksûùüÔÛaZöÞÙ ®N¾Ïê½`5 y¾[¾Æʃï>6Õb9µ/ãKDïnX÷ßöÞ°œ–ý¿.Pî,§E;¨½1ÁrZ”†s`95+?¯=°ž9Bí,©žlųO,©EKjï KjQðA÷L¤¬ƒ±ëÚsCò_dû]°¤Fò—nJób_Ⱥ%uÛ²mPçÂ’©höC¸¶âû߉:ýbêÆáöû.ŸLbˆžrßXSͯçg"¿½E»˜·‡æÓ]‚EÕî—÷²°¨šÍ³ìý`QõlDþŽGÁ¢Z4¡ï¬ªj›•T¬ªv3%&8_P€0%†UUYwÕ"Œ¾7A¯­óõÙJèãµUöQ[¦õ¼Áá†r7†c¦ÓWÕ‚Õß ÖUö¶ÚVÏ>‰ß¸7Пû³b»Kús'ÝyÒŸûw/–ørå /úC*3pèÏK°ƒ$ý¹Ò§’'¼Ö°èùp-Ò_¤. úó!Mär¥ ú³Ù‚$Eús=õþ8èÏf%þLÂ-h—ðW¤ŠüÙ¦ VÁ_‘·tÀ_Ñv&à¯È¥*à¯(ö9à¯(8;à¯(z7à¯(š<à¯*ǨàÏ$^éžrIÕlS€JÒ_•óeÐ_ £€è¯jî ú³ý:ð¯^\r´V9ƒVet ¬É@ƒÃ÷ Ð7xV­€ör„„X­jXœ€¦B×VÍÈÀª$E€¶-c9Vå> ´Ý&æ à¾ÎÇU ”ÿj€†ðÏꀖÄ•N¶Æu„æÇ¯$ü«ûoñ/o_øgê<Û!ÿ¹$i+•ò ÿÕ;pügŸ “íÚ 7`‰YXµ}´/Ò^X…+€UN€5Ì+@ë %$ÀãW$ÀªŒNA€UÁA€•N €%L€ÀZÒ=/°*—‹ÐÜUA\Àºk¶cF4n` ÐêÜĽBŒ‹à?ç7P#ù¯hþ+Êèügÿ‹]œøÏêº%,ø/¼‚ÿlÊ*€(ò_Q¬_ð_azÀ?ÛÝ£a៕€€á¶èî? €&ëƒ"€á4¸^X”l* °-B˜Ð^sÁ¯ˆ€¶[||B@Ãð”°]5!`Ðh  |Š•Ñ-ðª#dÌJ rU'*÷bàÅüA€±»´­àÇ€Êý™x ÷çÊ+>PYð+ÕåÓ’H¥ä¿]°Þü'‘ä?[{H„ä¿«ªŽø/zI ¹Œ€•V­@eXJŒ‹ •uRèÎ)è}€ äH CH òU%  û>€ò¨O¬±@å¹J,L¾ tw·I&ÚÖòãä¿ýJÈeâ¿BCaòŸe|…‰ÿä§ü'šä¿B[!ùOAɇä¿ü‰ø¯hšþ+Le!þ;>LðßþÁMüWþ3T!î‘ÿ M ÁöL¸”øOùÕ“ÿâõÿ)¡—øÏo¯øÏìûø‘ønÄÿe+â¿Â| É…aâ?¤J÷†ƒÿ”‰ëw$d lž€üd@G øÈ< èчÆ9GÁ€–Xz‹ЖïŽ2à#«M0 )wЕB´m+„:)€aýP)tS† Ð_ä@IH€\B¬8M#@ ƒ PÖÇ‹RQ ±*À›;²N~€X7Sÿ“ÿrêûzÀ éU¦ÇÐÿªAí[ÿ+¡Ðÿ*]ÍSÿ Ãx芴sšê‹¯Vi–^ʺ#¼&ÍA€—ŽÙÚÂv^JŒh‘)%X¯¬gE„€v¾ övBÀÆqha(0E€ ›Î$ laÇ6ù*¦6*´^IùŒh}°SëÃreÇDáÉ €¶Ðâã M?E&6Ù[hÖÀr°ÅÖXØb¬ ›vG€6" Ý ­þŠhJ¤F`>•Ðã” Ã-úœFܽUÒ°…iHhuð!€MqÁ€öT“¼ç«•U\&´‡"ŸNÿãmãÂû'¶DB2`S `@ûºÄŒ€„`@{€ûÖY’ØÂ@ØÍØ.&½´Ó†(ç­+¡G ›Ìî-L„@\ØÂFA t?@1ÐFC{a`Ó)"6Z1 mŒ——h‘e@3R » |h'¯áö¶ª´^“îÑ6á¸sPà¥,0AW_xé[^ ~P‰­Ûb`øgÚÜ‹õ_h^l†XåX%KVe|I0T q Ÿàôâ@3 4<•tÀ‹ÓñÁLkè‘—/¬:)uÀú¨Ž@Ðvk ‚Ö>%¹Á%Å‘$øH¢TÜIP½&Ip݉HpŒ¯$È‚ ‚ʯ~hwa‚«òsÎ"O ¨\z ‚SvùÁIßÌA‹ÚBË"Á)‹j⟠Á!ä -0nçС ‡4ÏÔ+;IjðìJdýC | %°¾90t¬à@û´+T&½AÛlâö‚ƒ‡%ê°C€œJàzƒ`ô|`×÷M%ðfÇ %+*Ú%ÊC#APQ› ‚Ü'*n&…À[x3Árr ‚’uÚJr ,†)*KÚ!Nš&ïúIeh͈û"<† HÃYÊ€×'ÿža³ÿÞãý§(ð& $vúg%vy%†*`goR ¡P؇ˆJ¸K £êu¼\"`¿%ø upH" 6I ° Ì„€a° ìœE€!îI€ÑH`gâàTN©I”ç߯¤aKè3èón©C÷ÓÉ|rQIè¸'ôÉÓ7¡OY·út4@B_¹%µ…Ûç úÌ«ƒˆGèN'ôɨ‘~Ÿ6Ç£„ÊߣP<)‘e;”?ûvKRþÊMgÂPþ”nœÊ_¹%'JùKÇP)Šº ì+Êܧ¿¥òVkq_Äa÷…E4¸¯èøÛà>³ö÷™MÂ@(û×0Ƈò×–Ê_Ó®+”¿ÆÀ¦PþÂÊ_ìÞ¥ü1*ýþ¾QýêËç³Ð5ëPý$¥êÇÔ¥‡ê§>ªß^¿¨~6Sà Tªß`Àqª~yÿRýv ¾¨~ÑŽ)ú)­S0ŸG¨‚©(úí»š/—ÏðQóåÀ æ+rA æ“e>¯0ýVŸ=å<_ Ägk?õFŸ­­Ø=‹øl¦Ä^^Äç!¿ .Ÿ­ãx¡"¾¢$g|á*ÈWthZ _lÿ„|åÖ°òÙ¦0DäóT\‰ÈW”€ È+b Ÿõ#½/Ž÷ ä‹É?/Îv ä+J!äóÓõ®òÙnß[È—DÈçu éu-OÒÑ„|öP0K ùr4„îGŸ© >kæ_lz‚ølqˆÄÇ£ñÅrÄ—~ó">[°^º_ wñ^¹{Àç¶Qp‰/Ž â³Ö!ñ•úÕñÓlzó­ûÙ¸c_‰¥DÄ—B€ˆ/-Ð$¾84ˆ¯È=›Äç&`PN¡AøüTÆz nÎm'ñe„¬ˆÏKÆ©ü!«Í‹øÂ²MàóOÂ%€Ï]DÖ |h j%ðáW,qàËsŸÇçWUå{'ñùqXĹÎU5œ A|û7U@ÇèÇÈÖéÄç>.¼•9# 䋸Ü{ú‰Þ3,‘?̈́ω9@Á\Uî4—$»‹î4“å">w§¡»e£;M²$ˆÏÍΕ|çÄç‰ñ"H|n¬Æ>ć,¸C_f$ñ¹íü¡ø NùæÁµ$>O—Hñåù‹">/),y˜°uIØóy„1®MæC W(r€¾Ì(èóLL „>O[OõÏuêéýéuÐÿ}~š‰Їk¡ ² З¹ }Þ0n‡ÐçÉIŠ}^ðœîŸÈ—H \®YÐçÊi ЇŒŽ } NÉPâ_ooñYx‚^"Ä+®W#Âú<-îéü‡y ùò°3!_&kóy+€2»B@Ÿ{®­CûËSBE}~¾, ÷àŸ×éûémHA}ž˜þê¤>o–ü êÛ%÷›ú¼åN5K«Ûü"+¤¸/3*Šûpêà àç%óôýt>°.ÁÏsŽánÀ}ž!°¿¥¿ôëtîóv1SûüGè5¿<óIà‡£·Né/,¦ôwQŠÈ8zëw$a ´”o÷O%p9¤?imšf#j­íÔþ°æ~$º®>N÷Oß±<§ôçv¸ç”þ<`€.¢ ”±£'ºA—‚!¥?—™Ào”þ®U¸§ô×ïÚ_C‚Ðþ\L{Eÿ]fD]šøwé(ñÿ®PZ$þ]¡™ˆ/%® 4m _A꟥,ySàÕƒ&ý×(êß‚Rÿ"n'Ô?ÛϽü?¯Ù‚ ©þiYNõO§eô_¨«Rÿ”R(£ÿä= ´eª½Ô¿TD‚ö]ú‹›ÎlÊF•êŸrPò“¢ò³Gúߤ aè¥IW”þWŠêHÿ+r| æÛ ^AñbÁKæn±`¤ø <~¼´/ ¼”‘.XÐ~ç>ÁàQB´’‡ì¼¹ÐŠC‘ Ú —W %®Y/ùï Z0xi0x-ä ¼æ¼t&z° Í"ë”ÿ\Bd’­J§Úç,hÒ¢C(XÐ6WOú^ʯ,hŠ5C‚–ãçy^ƒ™K/e¼2êߥ@AË,F=(xÉL(è³2®EÌßpÕ>PðÒa¡‚—–¹`Á+|cÉ‚W™XÐòJŒ“/ù– ^á?N ûÇŒ ”¨ùÕ,x!zø€>7L;ế’. ‹{£ÃT¾ãá:q¨\@¥1 ÖP|ÃôR0åjq‹)ù€Æ^M> rñMœŒ±•úWcû!¬J^šêŸrG§úÎf¡þ)F9Õ?ó7õÍEx>Û˜`Á‡Ç⦨ŽJK/Ð¥W¨6Ä_Q€e)¶(¼@wŸÂ)Ü@u\{ªZnÃ4âæBþ›Ì8òŸåךJþ›ì€”ÿæâ¦5ä¿tZ•ü¢Rȃ‰™Sÿ ýo2Š#õ¿°¸‡þ7$z¦þwË_SúŸŽ/:b騒úŸNfIýïfPlê!r…þ§SVBÿÓ)©ÿåÅ©ÿ)Ñ^êÊožúŸ<ÁS4PùøéuBy €¶ÓF‰ÀˆK ÐŽçùøé÷¨À„ŠV€:Ó爜o„Ý Œ+P~3)*| €]ä'°âBÔù¿)jct„2 (Àv‹:%f‰À ê“î¡vºÖ¤¨luG(ྡ4´pÁ‘2B—„7)€û›×w(`8Kg(à-dŒPÀ›v¢Ð£ï¡€÷‰ƒ^4èoøK$ ³b¦x1wXJ€6’ðDÈÃ7@@Š¡Ê%E@¦&<¹[8Âë—0ÀŒ8Œ0@ä=¢L%Ö[lH°Ui‚TÛ…J´¯ö lEqŒ’•{ïĉà‡ˆä]Gà…èHÄv[’ŽW¢Ÿ+óÈÈ£’H«öó?bUø;±}Ûv–d²×²Ê‘°ì^Ç4F;Qr´Ã2µ£?³aQ÷õõ¬Q’í¨ŒíÄŸG;SçGE;Qr´Ã2µ£?ÿщØn?Ù¢þL"¶úó Ó¾&bûNFµH"¶ïuƒÕ‘?3E}í«ÖM‡ygbS[™cMmIÖÔVÖR[g­h+’¬E[G–µh+jE[G­h+²¬E[Gšµh+jE[G­h+Ò¬E[Gžµh+jE[G­h+ò¬E[G¢µh+jE[G­cd2ÑšÚ:3­ÅôµÔÖß“ÍÒ`>{¿ôý|l×/åcû¦3~?ÛÏUûšíg›û’í×Úû:l~®ÞøÅ1õm>¶ß2û3Ù~™ëü…);ª|o ~iåwçc» öºüÝ|lû ü5ÿó/‘ í×’²½2§åÿüNÏvþËÏvÃ_ÎÔv·éÖOÕ6r"©Ä÷íÒm¹·L„Y Ô¸íÜ„æq÷»£ýF=¿CÆÝßÝŽÃi8Ö‘%—ûãû¹ƒnTÝ%”ˆü æc?Ý­·åì*<¯Þ7¤w¿=áyæj»íL†‡!ó¿ÃUýw÷Ù ÂHç¿û¦ ãŽ×bfdž~÷g`ã]á–¸·§ ûn¥Î¸ïêëuxhì‚…ÌÈÊÛqßHaÁþ§­ Ž­¾»­?>wLÓÎ.Y°?+ìá¾q,®Çײd4œ òTpàÞ+´d ß%Ë÷ÜŒñVbæôŽ“B:Jì8÷îtR`ÑRDÍ.YX|‡zzãP[ÝüÇuÁ¡]qùûæ Ú•žh—L8´Ë'âÝyf—0u÷mù®üX½M?ðÀ쩃öÔ]â¹ fÓ!·ÏÖVg.=ÁºàÏ®üлÄÃÛgÓ1ï÷x<žk—ÐîyÛ! ëÁ! ¸Á‰Ó5¦q\Aê4ê¹›põ¹Çm½­wãeLÓ¡ŽCJî‰ó&§¶á&™]ò '*3ËÝvŽ²Ï îi•Úoš±\D9ëXðàXùgìÏíéO¼™†wèšFŒx(KË1'2Áý­âIúvHÙ÷ªþóÙeθm¤W; En¾{ÃëÏ;ûbV›]ò ¯•¢‰îÕ][óXŒ(?‡§#`†u¬—!ÐÅU×Û*Eø Ê pæ‚äö{4²| xÿÃ7B>‘çÜm 6Üøl&*ŸÌ£¯V&±òwcç3ÙP½”Íí¶s¾Üúë8ÃÛNÝó´VJªv›n£õR°Ämºü¤¢ÔQb&·ÆPL«æ 1hv}ÐÎ~žŠ*¨±'Ê›UŸöèõØ,¸âsúë7„—Î’ óó¤¤:ŒÈ!1ßß0vóóuº‹'»„ÎáÃì'6Výxüê¾a~.p§fز±zùaOÃmj7·PaN˜ž ƒS†çÅZ@ó·2̃¾7—á:ÏÓóÅ Ãâæm šÑØmÃyröáÁ7lÄn\fFåí44÷ø™fà+h¦[Hùn…–—áÇz®÷8Œvžxë–ý±¡ÍûæB?æ‰!cfYÈ¿v\ÚyâÁ昈ÎëóPu<¦Û3&?­ßÌBVX/yN;«÷‡K±ú¿%WÛ€>ñ¿°Ê÷3V–•­"PG&&” %'6*8 €Ø‰þ"W[Пí¯ý-}?Ñß’|ô·ä<ôW.nƒþ u]ÑܶÀvÀ?wÁ"Nÿp0/ðü—Ç5‹ÿp4=° 莡ýD@w‡ F" §_@ °(Óm `œ°hVþ‡%ZªšîXt0¯Ð5(ÀÐ:¼¯Q¨ ºšXH„ä¿H4üWƒEÅ‘n+øÏöj%ä?„I–ÀÈXq˜á€ž§éãà?ÓèˆÄ¿ªt:URSà_UvàŸíõȃ ¿ŠÅþ ¿*?ÑŸmÞ®ý™'H„ôg‚0@ôw•¸4é2òA—Ò:þ]ñú„æ:¶^øwéÒÀ¿K)ÍÿÂ#øï kŽøÏ|Å€êâ¿Vþ»(þÙù[ïÂ? í9þUù^þÙ&sñÏþb ˆÿª’Ëÿ™¿Þóqà_•HøW•£>ð¯Ê50ð¯êtÁÀ??jõ…U'ÊþE:áÀ?sHX,þYr±‰«ÿÌÄÓQBü«:M0ð¯Ê\/ü«Zmƒÿ -°Gsþ3BÀ‚"ŒnX-§ ‹hOàÃ#°*ŸS`•èXÀèž¾PŠ«b=«ü˜+ÜNÔ9vöõ°Z· ôF¬S $ÆÖXX5 =ß ª'À|„@-[Æ9Øû ‹¢4u’XP`QLFR`ÑFhcXÚEæYÓ@f¤@›l±µãhô†­†(°(qJP`$§ ´˜/ò›(мqñ+RàÍ–¤À›¹Ž‚{ãs&NÝŸ(°3`R „ðÄ@9Ì$¶Nø T‚a g#%š uÄ}bà…\®IûÇãMJ`“X™2()P–ܤ@¥úK ,Œ–H ¬ ë)P ã“åÁš¨(Ϥ@«ž¨SÂÀŒòîz 3í“0ÐCuð­ˆb° Ó7[è¶s€51Яåo‚è £bÇyRàbúå¤@Ô¸4€+–¸„@fÓ9 ™G#ä*¬å Àò‰*‚@í“÷J‡„@½¬„@Y3’¹©=(ñ2EaRà~ß4&*6?1P§s'2ðåÀ@jÏ•¨TßI‚·lgI‚L†˜$ؘø Á* ”Ù+Hpt• âxÂàʼn*aPw0¨HÉ„ÁûဴOý)u0(þJTç! ÒSüƒ“%‚Aæ;`Àž,Ø0% 2"Q§V$ ÞŒ;OTB‰$Á›Qå¿#k[ ¢zN\ô= |b*|”k7`ð ó·`ð‘ccÀà3¸> š‡-~DŒäÓ)jrO1ðAð’h03ø…¨„.¢AG«òÒî[Dƒé`—Z 3D‡‹wj!)I tó,4:‰G¹§h®Æ?rà„”r L¯Á‚ÃaS ¼n¤ÔÀI¿±T5úB Ôa¡©NÆ m™Å–4Ô@Ó•j 9»}0h'“à…‡¨p°+ãKŠ!*K ´é’ÒpðñTb Î‚ 4¯JB |a8x+Óxàà­CÎoÅÒÞ¡= o% ôscQ‡8xk– ¼ƒÓ…ƒ:g*hЛ-/ÔA8)VÚC ”KQŠm‰M)Ú)RhEj`@[¨{HÀ!lJS8Ø” 'pÐá½pÐ|Ǥj Ml(!¶;TEâ`$e ´ñЩmkZÑq°1ûJÐ` ¡^4h7ö 6 jà›wƒ›M ?²`ƒÅW ؃ hÉ÷î—ØèåØä†Bà„I´i˳8°éÌëƒÄÅT”¨é)µ@Iý©j Z¨K¤,5!6N,A—rž‹/ÅkZ•ñ’/eH ÔyK‡H3XRà¾=ܤÀÁ¡“R ùê ©ÝS Tlí¡2åW*•ñA‡ؤŠæbH|*·D¡",6PQ2€atÜU© ¸ß4y*P*F"àóU ¼˜^.•@Ëæ d>´/ö‰`@›˜ÑN0à#¸–Ð!Å€ œIT’‡ƒ‘9Yˆ\ [À“Ô0" ïj ˜½„ 0ÏÚâ¤ï“£*’÷b1N!Ðë`“¸×M7p¯Í. "î5-=Á{mßÖ›÷ÂWQ¼gGÂ;•¼w<‰÷lc^PÞ³nƒ×)Þ»tWðÞB^xê4ÚôþÜ¥¿ä¿+¨6¼??Å{ÍàôþäÑLéý¹ŸNtGïOKsR“÷§Í¸w)Š¥ó§ ¾áü™¬òþ¬r¦ƒ÷§­ä;º2Pzš÷/°KÞŸ:”'½?Cã ïOõ¾—÷gCßı1éýÙ™"@»xNÈ×™‘3‘OÉ*“ùÄåÉ|¶Á|á—̧øÓd>ù±ôUú4'ôUù újWù®Æõ<ü?ÃY( OqB_øÊô]77ƒúèæœÐWC å)#SùSº½Tþ¦¤¬Pþä_Â_lçúúú*üÉŠÐw‘RúäFÐw}ãý¹»çõÖýÊ-íRÐg¹XbŒ’4‚W¡/“ ú\B÷KÝO’¡Ïë@É"ô9£ÄÀ|î@ˆ]™Ùâp)0_®úb>§ú•‚ùœ7Ð0Ï Öéüyø”ùì-—Ä|rlJæSº»d¾ÐZƒù·. /Üâúî}±+ è‹Ýd@ßÍÁÌGûS"Ÿb×ù¿‘ħÔÉI|ýí÷™z™x¯‹}Å{éW)Þë²Hˆ÷B ÞSÚÙä½]‚±¼' ä½p‰ Þk<¤$¯M©€b>Û¿’É|JÍ’Ì×Ôaƒùäǔ̧#’ùšœ°ƒù³È'óéÄÁ`>Ƙ'ò…orx~6áfx~F‰˜O9y“ùÂw"%?ïÌ'K2ŸÎtIæ³SóÛO‡ÝAÐßbÛÃï³|¥?|³þuÊ‹Jn•øÞ„Â?Le'ÿ…ñ;øU‰ÌÆ*üËÙ¿áݘ°Gü[ôZ8ð¯ðã%þ1\"ñOSXâŸy‰Á¿Au;ùƺä?ó6g¬Ÿø¯ŠöIJtþY¦¦Sò;iTü§Ó$Å£üwI.;øúãÉp€ þ“ÂÁôHþ ¥+ùkKòߨü“¤üw3çg Ò,$Ê®•xOa—Pžø wçx¼—°¨/ïကÀ[>±Ø3Ÿxóäí„À®‰ Ðg?¼>™øðú\ÂO ²›'f\Ÿ°3ÝþËë“ÞšáõÉü¶‡×§äøôúdô$À®ÀÈPýÊÇÉ+þÓAë/—Ïõæ?óêz.Ÿ˜üwÑ—üG :=>õzÿÌs@(ü“Õ >ëçþböIOž•’𧃒þ†ô×éH—ô— ú ·sâß#Jþ…‘ ø/¼Ùƒÿ¢Ù”ýäW²ß%j Ù¯|~QýèDô×Rsˆ~¼Ý#G›o‘_És–öp$éaAä[ûÙŸ°†þýïHÐ6m{³Î¦³$™©Œ9ƒâÏLd¶<õë£$ÛQÛ‰?vÇ›óIYp´‚"5¿þÑIÕ¦EiØ{8“ª}MñôK‰ÒKï¾ùÏji¯LÀ¶K¯ßð3ä‘KèÛâeËÀ‘ùéK?³Wg[öWµ”yÓÔÒ™7-e%¶tÖ‰–"kZ´tdMSKQI-u¢¥È™-9ÓÔRTRKGh)2¦EKGÆ4µ•ÔÒQ'ZŠ|iÑÒ‘/M-E%µtÔ‰ÁÙÒÔÒ™-M>*±¥¿'£šåØ^{1þïÕ~-£Úo˜«|Ͼ_§æ¿;6_Óõwæ»ßMÍ,mo+þ¿Ì¦¶§¦ß“MmWÿ^6µ]¼›Þ{g¾¦Ð©¿8þl65·-ÝN=ÞæÝ|»:–NqkÓZˆºðihÞÝìÕ¾Âhç¶$Û!/E'Í{¸­|Øðv8Ø%ÓgØEŸâi‹Cõóy@ø¼í$% ƒç®dÞ–•Ûã'öë»dú7…ù’ç(äJ焹ÙäÊDn»ÄÓốػê×Ä2wïÍX§JòÀü7‡Å6](a;ëø££-ö<8±GVâô9Fü¿2št﹎?l•‡jŽ5°A–…s3Šñ°)ÿÑ,{d¥)ß%Ï'ã×ps³æ‡ë°òÌéñƒɾŸ³UŠ™ÔÕvÉV+?§íäOÁsN€¸{•6Ôi+ã¤wÉ‚«Äà9ç ë„ýmN¤êÙ%U·üTæ²aÀä.Yð`•‰s®âçˆZÆdÿ³6&²¡Ec®«Â}Õ2L”¸™'.ÜWöì<•ïnõ†Æ›çsNKx¦ß‹ÇÓg/T7"u°â\³!‘’-M?JÔS1Ë.YHµ: û´åôD6³ííØy™…-» ~¿—‚D6¡nZg~x`³ãô'9.@âéç!y"%žj5m£îçäòL>^e>v–'2¯Ë»V¡ä²ÌzÎWI›0<)ßÖ2ìÁŒ n?X–_½2Ÿ‚÷áeŸÑ͉‚ËÇlˆ2wÊ_–ßHü]~(G¼Uw‰ÛTÜõ}áRÏ@†¥k_–ÙŠä¾ûZö"=C€N÷Z~Œ¸ýf@RunáòãšJJÌÆßþ­¢~ŠžÔkê¨ó å{b¬>›èåç5ÝÌç÷Üü`—ÉdËUä¹cÉôÁúð¬€å'6 \ÉoÆlàžÌC¢Öò›]5ýfìÀ&?†‡Éý–Ÿ×äìöa;¯éBÆ=,â^—]åZ9•¼<“Ÿ×´˜7ÄïÏd÷$«4Í/?¯iá}Æ\v^“»óUš\—Ÿ×ôîRËÏkrÓ<žÀ¤cÄÇøä¸ü°¦©ü0‘X\ÜuD-.?¬ià2èlvX“ûòU†Ž.?¬‰Ç]uüªcM½p´ü°&¯ÃÜŽËâÙ^ ÝÆkšG’•e‡5­ IM0Èü°&ª·è´70?ZëÁýâ%uº/¬—¢®×€‡5b™üCK"›ãäÀóÚåëª_z ëêÑ̺éÏǬ&kÐw¸=°z.;«‰—öU~,¸ûaBµsš:ü„1vìœ&Þ}C &ã'x'Hzö¡ Òäùæ½ÀöÆðôCÒMýÖeÇDè}ÏŽhê8=hÙ Mô‘Ä\±7 xn"^vG€:·¼ Îm>Õ êòpQA×yA§ÞEê†9h½Àt~ø)h‘L‡sLçG2?.E¦ó“Ga$!Ô¡ÄŠPcX P·\„PçW'ÃêÜà—CªË[‰ué»)¬ó§z¬sÿÉU€u~-á X瀬˓k…un´'Ö ¾ŸëpÔ.J€uyJ®°ÎýÉy}Téê"¬ƒh…ëü–I‡ÀºÌ*¬KEOX‡³€hŽuþT÷‰uUvX—‡ ë2ÎLX—G4 ëÒWX—f„uÈ'㯔X—IM„u™‘G\ç.¼:¸.µYq—qIHÒs¡d14±Û€v^‚N´CŒ 4úã}’ìeædWqÐÈÎ/ ¾%ÙùÍ5"ÈŽZ²°.O³Öå1Ôº³°Î~`3±Îï‹6±~¿Äº UÖ¥'»°Î•wX+ˆuéÉ.¬ƒœ|£db°f`]F\ë2­°.eIuz3D:xë‡ í¤†W€±B;©"ƒÄté× ¨C"”4ÚI³­†Þéé„@‹¸MwªxPrÓNªÜ²‚:d2žê¼¼OBB}y‹¦Ò; Pç± ØæƒëüR^r_ê:¸Î£—ñää:d@5ë2B\çuÈZà:N0%¹Îßi?¹.ó$‰ëMpÂ1@•àºã}‘ëܹœ\ç÷CŠ×!ƒ0©r]UÔ†¸Îýo°…%Øeò#\Ÿ½ ci¥?£°.BLDuéÜ"ªs7$rÞäÊ:˜§EX‡Ø´³¸²Žõº£`¿‘yC˜.Ó“é"BžHçãÝéÒ¡ŠH—É¡ˆtþ¬lsàœøø~@:¤dãM9W ÖÑ1D¢›éâ–èüñætfL¦;æz0Raûߎt™ÈŒH‡—v ]f•&ÒeH#]æª&ÓϦ;: ˜.cŸ u^ãP—Ò¡ÎÑ °b*ˆPçt ¨ËަËàig:ÿz¬ïL™Ìˆt™5œHw t ¯¶±@:Ô@<8 D~dÏÎèÇ”1c~ùiÎ’ê–GðœT÷\’àDuT¦ º‡þ[AuÜ΃êì­S¸#Õ=² ë™ ëžˆu¾Wa] 5R¥žI¤+ÌFŸ"]aÆúéÌHמPèÌüù"º‡fÊ:e‡9:¬”‰MNA§©Ñݷ¡ÑÉ‘15:å´O‘N©C¤95Dº¡ >N#75º`‹Ðè”4;5:R£S–™Ôè.f!NÎ6¬oN;ÍÔètæé¡ÑAihtq#4:”•22ĤL§”,)Ó)T†2ƤL·V¨ré8Þ¥J§PúTéì&!öI¥Ó¹ ‡J'±R*%Ë£D(•N§Ì‡JW »C¥«1V¤ÒYê ÔTéØES¥ãØHWËú"úcˆt¡õI¤SÞÖéBÉ•J—íJ¥«Ì ™*s²¥J§ÃÔR¥SR¦Té6›*ŽðN•®ò,Téäâž*JK•®Ò8UºJ/¡”é®KW—L·÷ã‹¢e:T’2¡ˆ:’éè*Òé§J§óáC¥ }¨t “N•.ÄÈPéL§nG•÷BS¢SR‹”èÌ«˜¢5:…^¤F§àÆÔè_˜2Ý&éŽ2]»ÄG’élVˆI¦k!„ùçÖ2]Xk%Ó)24e:¹†¦L‡‡N!±©Ñ™Ö:Òèz‘Ê(.@=4:…ß§F§“¯S£ëÌQ]´âC£«2p¦FÇ£ÃC¢«¡)„D§L¹!ÑUyK¢ó*¸JtUÞ¸!Ñõú(ÑY 9Œ] ùB]ÕéA¡ÑyðE:{„ë%ÒíP¤«âéÆÁs^M‡] ³ 5:;Ê€×€FWñôèj=(ÐU¥“@W™úÜñÏèì·€9މ¿&îXÊ4õ9?HŠÜõÉó@Ö)ÑUÅÀJ¢«ÊU"‰®*XU]¾Jtq€$ºªc¥ÑUÅiH£«J¬$®êØ#‰tUÊ$5ºæ.jtU: %ºªTû’è²OS¢ó#Ð$ºüX¦Yf)ÑÙPºžók0d€gv´Ò":[¼w<°#¦R tæø{ :[ÕarBW/y=ÿbæ²á\8~!Ü-h „{Bª£ù0˜(.P+ŽCþ@8º%ÂqÄÇ4,‰pŒh:Ž‘¥Ép¡ÃG@; 7sB±. ®ËÝ18Nw“×B«£±pP&È•o<- z‚œí­©Õät¦c‚\A ¼ä8º­$Æéh£À¸x¨À¸@Qaœ\sB— &–,wT‘,go—YNRYÊr4â‡,—>±’å²'I–KôOY.?ÊrÒŒ‡,g%ô›¤,g¿º m0ÚÐv0ZÉL]nÉ™(t¹¥¤ËYÁK—[:K/t¹άÒåŽV¨Ë¿¢.w”H—<æ”Y9…9ü¥0'ç»攳9…9s¥ GaŽ6ÒÔå” 4u¹Út¹½7Tá¨Ëí_A:–.§˜ÏÔåd ].üNC—šGC—Spkêr<–(e9G—²Ü¤h™²Ü¼¿Êr–u$Ë1epÊr+–,§C’R–›áÆ)Yn17KÊr‹Ã)Ë­Ë(Ë!ÓÀO‡,'Í/ ÆE£Æ™õ )Ž+J¯WäPWÂ6&޳_µÓÙÒª`3-Ž+abÇ•’9ΚYáh­!Âäì]ðW93J“yJcÜ IÎ^è YÎ_Þ8I.»,IÎ. ‘ —7FË·M³ˆ’q(s^€¿r~LÚÊ廟èq.–Ë~á,g cáŸ7=¸–æ¼ ˜sk=p0W´Ìe%ÌÙð™§¿e©oq.ÏÖÌù»ö¿ÀrEQb9_ám#5Àrö²a¶ ÌE2DÁ\ÑÆ]4W¯™4W”_4ç,Fq®O9mbVP— ÍÙäROšãDL”ËÉœ,Gãæ¬{¿ NÀ\.,Òæ‹~GJ²;s\ºN®‹óª‚ël;Ù^—‘ñ9¹nà&Ö :´'Ö15jPÝ­èž :årª{š®óp üÕù}ÅÏyÅ>–T—^Tç/•qo—V >¡ÎB¸PÒ¹í>½-ýðÀqŠsžú“×\dÓy3*y¦ð¸W1'"Ôy £Ø@u³Lù«‚ê<ñõuŠsž¿¢*#èªúNªs³H½ŽëÏ#¯C©sU«j¨s@%q®j qÎ~D©â\È,)ΙÛ$Ú¡8WXâœQ WT‰s¾ þ8´9ÓŽê+„Îô’ût¶tå€ú]£D®¢4WÃÒœåK›³’“é\Õ ìFi. ó!ÍU%ÝKiN®ã!ÍUyô¥4gaY$8Js6zè~IiNg§4§Ó;R›»…õ!ÎÝ<'8Å9w«JeNn.)ÍÉl–Ҝҙ†4§G)ÍE¢¤9{‹oinhÒœ.§4®O!Íéx¸”æ†6¡!Í…‹MHsJäšÒœŽ¢Ki.·˜ü,õ¹¬1tŠÜÉ:ùõ†>·Òúœ½´×U­–úœRþ¥>÷(ô"ô¹ÝÇú+†®é‡@·–$; tVíP Ëf$Ð=Uô§º¸¶º°2„@§sòR {xjS t¥@÷„ø&î‘2o§@—íH Û%Ý+)Х뤺G’ºGzWtòïO©´~JNVÌèâÚèt¦P t$ݳDmèdØYÁýèžGR ÂèdÎÍ0:³Ž¾ºGÐéMD]a^ÿŒ¢Û%è8!Ð=ÒC¡Ó[EWxVi*t2ߦB÷ðè꣋Ml„Ñ9\‡B·¨{„@§íB†Ñ•ðÉ”B÷<ÔãEÑ—Š¢ sŽºèkˆ¢‹¸¢èâµ(ŠN±Egi`ñ7‚èJeQ ‹>¦ º¸qitÏ#¸¤F§ *Štñ%E§dŽ颋*Š.ú„¢èdâ•N¥D ]àéŠüŒ¥ÒE(°T:Lt…)ê¨Òå¿3’N)‡J§ hDÒž¡t:2dºXUJgžLøûÑ`D›’é”™#"éJªré”þ‘‘tRB¦S*éìÔ.ÿ›t–,™nu.8 ¤³Õáp»ô6e9¸]Š´B§+œdcϰ€†#³ÌÞB4w’6*‰äa?ûÖà¿ÿÉÆj±~?›Ž’Lï¥2æÓ‰?3Á×~RÛO¼ÚQÉÙÊ¢þy´³wX¯»áßG^¢ðÇ?:јóÝ¿Ÿgìs‡yž±þÛóŒ•úÿ6ÏØ7]ã±»¾?ÎtH_{˜÷ŸË=·Zl)3ˆ±¥3ƒ˜ZÊJj鬥–"ƒ˜Z:2ˆEKQ)Z:j©¥È ¦–Ž bÑRTŠ–ŽZj)2ˆ©¥#ƒX´•¢¥£–ZŠ bjéÈ -E¥h騥aÄØÒ™A,FzTRKOž1dñý4cã—ÒŒ}Óû¾Ÿfìçª}M3ö³Í}I3ökíÝ¿±Þø•TU_ÓŒý†YúÇ×´ûÍœüã÷†æ9Mÿ̸|·ñ»ÓŒy¼Aû~–±ýðÍÿüKäôúµ,c¯`ù_ÿ˜,cã{9Rý½YÆžq{|Æ‚.vLŒ•bõ.ðÈrž%ð ?\ÓË}YßÐXʺð ÷÷K‡’ïÐX<üú™Å4–¼Äö×@:Gf´yæå;…¥ìÆ»yæ„ðÏlÃo{уõ™v5Ä\°Í»2¬ùÁŸËÃF䡲·+ˆ_”­u¿ÐæJô~pß×?Ó²Ø|xpÁ}/_ª#¾ö™ÏíF^¹Í>« ØÉü~ýÆ-²Ÿ'˜à'ËE`{~—ëò$¡sÞ›&†¾Ý¨ÞËg?b‹Åg</i§â""o{YÝ8–èñzêéhbÂ4mä›ðAž_øØ[d¦/VÅt¸ þÂ_ð5ÒQH{c‡ˆ'ÀcïŒÂ5ÿFÀ“œN‹ËmÐ3pf‘§ÌîRÁƒC/]Yhㆨ"UðçÔ"LO±nF4wÄß—¿ V¸þ÷ØÛJ݆ 3|bÏ'&ÙP‰Aý¿™,€Z!˻䂮"[ú.iB•xn—t߀&%¶‚Çoþ&ví’⊎=Ü%î@ƒìþsB^Q®•¬O´Å»[X”õl—˜›‚™Öy¶ÞÞ–žVÂCe­d}ÒÔ_ð,6À³ž1¬e—Ø‘x 7lÖf{£q•¬Ofa»Xâ²íîz7Û,³<ì™m†M4 c+Y~kF»f´’'îϾ]{²Kžâϰ–žÜh‡ÉÌ;~epâÀ1u­ ùí/Àðþû‚ jÞZ¬áá4£ýwƒG«D±]Ò!„š§ [¹¤Èãv­Z¨ìa»dšm‚`;jèsëû^ ØlgÊ],a”È‚]w—< áWi–h¬XÁSÿ Ú.©pqE¢i/¹ºÓ\ã9„»¤Ÿ+ÏÚ°?ã bMvI‡›kcÖŒ]rãE'ì’môarp+§k¯˜mvÉd\ÉÃV|]u€À.yªž¡ñþx»6FýmÄ)pwÕÙ»¤‚¤-/?®d§Nx6:ai%‘ÊíFËvÊ]ÏÙLïr0nü‘»tûƒþè>š÷ß84($Ž]2AÔrmÛ%85(ÂF¬P=;g ;6ÈŸ &;6hâfØ‘ìØ S_±pµ ´cÇQzàw±cƒnÔ™¸øc%ºnïv¿ú<Œb—Ü0DÓmŒSE¼N;­eáuv6ëðê?⸴3ƒ\Ñà¶KèV.Õ£–á~˜$Ä.à§…}ÿmÚ 쎃®å³j–°cƒ¯À™ÙŽ ¢Âq±wanÁíÙ©A V Nªvj?BQ®îâ\&˜ºûz¦±h„¾4v‡›°”Ðþž2º ÕIOóÉ¡]â„LÉf%ð5ï1!Ù‰A-M5»€f¬9õáìÈ ë0ÍZ ÝÍé»KîùIÂÎ xÃœ×æ¼`c½þýè°Ùå ªÛ™ØÈÓÑ‹G¸g®Rñ~i˳ M²À…sC•¥ñ¾¨íî+ª„Ù¡r*´œ·G@Ã.`‚(‹…Å+^È_8ÔÉy^LÔV°døj,¡úóhÄÙ®s½Ÿ‰9¢äof% a¨ë=~¢°÷vrϧ‚vÛZÖên% ¯¸èZO‡UmÿÝÞðÔÇ} î^”­`}RiÁ‹ñí#%gnÛüQ¤`Oó #ï…w‡Ó‚ìp¦qGzýäwû !¿]eÁTFHlslqôNnÿüQ»d?¿Ùl‡ ZYt¬a"f{}Pr#—[\™mJÀ#<ÑÎD679)Y ÅÝ †Ìjݘ_í`œ²[ÙcËBŽf­ Ñ0éÛGOˆi;Œ6 ¶d¹pÐ,!6 |’þ­‰Å’á<üç4n=Ø×’áä[ ''·`¸«`‡/„»:^\ ÜEõ.NÞÁp–€ðã`8Z gG_€žÈp µ †ëM?q†Sö1œqäu2ÜÒQÍb¸¥¬b¸¥81Ü’ˆ&†³‰P@†3ÿ %ní%ýN†[pH†KZu†3V á–N|Â-IËB8ËYF*Âyòí“á–41ܲùqM0Ü’”+†‹f`¸%ÑV·Sì ⬷Eˆ[ ßÄÙßxu€¸]@AÜÒÒIˆs^Õ!ÿ(pˆóŠ ¨éçø„ÏbV³A¦{"¥øG0œƒ=7p`8\yq…Ã)çA-œÜ@qž•kƒDº¦;Pœç4ë*yœ1Ì|‚5—‰Î€qÃf.à8:¥¡`áV åB ‹¬âç¹Ñ1[E¦9ÅùRqã‘ß± Î_.÷Þ€85/ˆËx@œ?·²€8å‹86_FYÈqÞ.w€¸óâ2BIçuÖâ ÌÄáªíõqqþQšJpeüÑcÆ…o¸AŒøV‹žøæ•˜|ó’›÷5‘f¦&ô-䙑s£ð-RÜÞü‘|Ê¥ÎÃVAoþ™¹…½ù¸ ½yÒ9’èÍêðÏ·vk«tó’ÉfݼnO€n~³ì@7¯Ã^Ø<ÜD&3¡›g²£Eèæ¿é¼ÒƒÄ3Êv'tsÃYèæ¶7ŽO ›çÑãëºyºE\rtó–¹9»yê?Þ!ØÍÏÒ­¼–Ÿë0ÙÍ£V&’Ð쌛B°›ß1÷Ï`·ñ(¥‡à-þ»åÙ¿b7Oó'ƪpwUš?±›—GÀnnvœ¬£~·XÖÎÖºn˜;Û¥‘xóô||逷W»'#©ŸàÍÛácÞOØ<ÙgoþɉÃÃSÌ„j+ñIp˜cËi/Z€p8&^À†åTáÚB8¯Ã!„ËôY@8?Few*–ÓNã½îh… ‡:% ºÓ™F —'t‹á¼Þ Îë,^k`YeÎ!Ü«F\*Ë;îxåD8¡KP÷h°>'á—àÒÀ8ÿÕCDƒ?€=ø ã3×¢ZÇ®ÿŽdbArÓ§¦$9ëz+IÎw6 r¶S¦ãE& äböÈ=•0œ»`ÜrŽÉÙ܇-8Iî‘‚HÎWY4Ú¹B‰FœäbH†§“dB«b,©q!­ISæÚPã´Æ…§Z©ÆaL‡·ïØ 1®¬ü!Æ)`ŒbœfÝã4U‡Z¨Ä¸ë ÉÅ|jœùÔ¡Õ¸x7RãtBR¨q‡jPÓÂrœæùã.˜‘C³è0å8Û«  Å"´€e”ã´™Éù‚ˆFïG+$ÞIî¸ œO‰!ÇaY#Ø=ZA)#åö]•€ržrYò[ÕOfÊéÎåZŸåÌ CÂ"Êå>K(—»(¡\+ñ«Á»‘ÐG”ËMŸX.·Šb9%”J˜»Š„ÁÜ5µIÌ]CL(š»:œ}~.b‚9™mæ®!ÌåÆK0'Q;aîZ’~s×4)˜Ó×O˜cÐL²œºm²\îßÄr­ ŸÁrÖs Hd¹Üú€år›#œSìKò¢€@Ç/"šË}¸h.wµ¢¹ýŽùÕDs¹õÍ)u¶p®]?žã‹ç²‹çl` yN£1yîj2Î é,…ëéZá^XD§a]hÁ"ºV º„ ]¾kþ†D×èóžD—»F]~È ºÄD¢“ûD]>ƒˆ.w±At=èñæ–Ä/¢Ë§ÑÉ/#‰NaVIt-¤]v@º¸V ]ŒÁ@ºD¯D:~ò@º*³>NAiÒ% éb‡HŸÎŽ‚äqÙŒ!H—íéb¯Hr0‘.&¾@ºÐÑHt)’ѵ€³ (?o]Ì–t1b„ti%Òå¬ ¤ÓâžH×R¿ëï)Ò ±ˆç´T<˜x.¤–À¹€#á\ µèÀ9Á›p®: ç¢c8Gª&΄pN!ÚÎÅà=pN•8§.¨]}ñh.^xÐ\L~¢9;˜4w=š'‚æÄ–Is|láœ'¶"œkZ†çb|ÎÅŒ$žËÙF<—}8x.Xâ·u…o'ùmî•Ø8* Oü–­â·£òÛ fñÛ ‡Kñ›\¼“ßÖÞV‚ám…ƒ°à-}o+ æ‚·³äÁíò'd·k±\ð²Ûâž'ÐmÏÅ×éI™yæÝVj[D7¥ƒKtËW%tS’ûD7óëbËŽnÈ¿néÐ,t;~Ct[K}Qè–þbB7­'º¥[±Ðí Y@èf¿’>·^O)tËvÅn NNt³z•LU‘·%ÑMÑñ‰nëQ¿ºÙêñF7eÓKt ¿H‘›N'¼"¼¥Ï¦àí)² Þ!’ðö„'²èM)“ÞžLEz;Ú!½™“8 oOè.‚7sŒK_Jÿ›¸àÍ%„·§jõùØ;·]]Ž%+ßóóÒFj“•çº ¢Hî7h5µ7½ ÏOEÄ#²æZË^¶¶-õ…eÏtþYǬÌ/Fowã Ex£ƒMÒÛ}ñe#½åȤ·›.΄7&YJx{N€x{úìSŠ»)ùÞΖ€·ç73À’‰&»1¿b²[º"’ÝòšÈn·\»Énw—vcÞ…d·»s›ìf§Ýìª)¼ÅŠÊRÔ‰n÷ůÑí|˜D·¼(¢k»'º1gj¢ÛÝéìÆ´’Én÷|ySú:ø èvŸ®”ÇÍ·é9ŠÛž– ·ÝHýžè¦y t»áž—èvk#ýäºÉYè¶iº1ie¢“ÈíFÖù$7$FHrã£þiÃDqϚԯŅg .‰ŒëlBÜ„È&ˆƒ÷² Ž…Òqk½ý)=ŠªV§áôqÇzè`8ÏI}lxš°A_I‡¸õ,þ ¥€¸Hkx@Ü*ÌkˆSŽ00œÇå܇÷\Ë_0œGË\GW8ö_ W‹lWT1q«d)&®¦±ÍcâÌ¿›Å™«5–ÅY\øAqUÊbâ<0)bâ*åfÅÄUV6PL\MOÄÄÙ«F‘.bâ*‹(&ΊXƒô¼nü·!BâÌ[¿’ÙŸuŽW»7„ÄUf:SHœÚéL%¸Ñ°ºŽZä ˆS1rÄÕgCx‘ØÂ¿kGäqæÈ>N†{scE<\ÇÁ­zÐÙX,jÞNnYº‡ûô§|ŽTy͇³“ #®2ráp•É¡W™kSñp­(ôñpvl Wý#  ×,ƒP+‚ájî  ×lmL„ó-‚á]C ×XûYÑpv¾`±†«¨#£X¸&÷_„ÂUæ%S(\–†ÂMiÈ g£B¹ŠH8{®$¨ˆ„³ÇÕ‘p6Ëèó‘píðyŒH¸ã=C(œ]5]0#ΓԽBáZú #®æX¸ÖZƾë!‡<ÄÂÙ¸^Áp6¿èóÁpvñø W™lRÁp­Vz:#®2Ø¢á“ë*î¸;ˆ†kŠ7b4\e>)DõôëG4\e¥…õŒßE8\eéy…õ2Éb çÉùÐÑpÍ †Ÿ÷ Óé­Áp65 ‘îŽH'Ùœ gü¢Á3›M½ä†ó$€hˆ¥”Ê‚‚ᬠ}6#®¦9‘Ápy§ Wñ: ®¦å‘p•b€"ájÚï W‡b=Î^ÎvÒÛªKN㈄keÈÙ2Bálµš§ðöŒÓÞôæß3¢Zá·~ð¶êÜ:T„ÂùzÂÛ±1Îæ1+bá*KY(®ñiˆ…³„hè±pöÑÀªˆ…«–0îô£|æÁ%¯Îˆ…«d~†Â5–T(œ'“K?J?áõ …³°#báÈX8û‚á„wWº”2ÎBª2‡p8Û‘ž~”ˆ©;Rƒ]×Úã¦Õ°ign0´(××·„.ìðG²ƒÕêò˜FÆßG6.oaœøãÈæU-•ñ~À–sŒhÓ(øó§]a(;®‘-Ç8hã8üó/ì² íõG³ƒíÿ—ÙÁ¾òr\öŸ×Ç+?ا·Ì_¡Y^ïÝÏëÌýc½2„a¬£ÆzçÃXGö/ŒuæãXÙ‹c½2‰a¬#ÿÆ:³„q¬ìű^¹Ä0Ö‘ cyÂ8VöâX¯lbëȆ±ÎLa+{q¬W>1Ìá# XŒõÊƉŸ½0ÖÉvYÈ¿å˜ÿçda¿‘,ì{¾Û?¿¿Ã_|¥þê\}}¹¿1Qߣüî„a—¥ÁûŸzưã£ú÷þiž{ /†ÈDq~! žcG±áÊ€½Oƒ<Øæ­[ƒ]Ýü»EO‹›· /yûÇþ§ÇpǾ`ÈÉÈbíÖr‡àΔ<— ëõp»yZèÎ0àe¡ÓWX`áy´áÒ°tí{EÈtl¯ LRõ´\®¥z©w¶„Gƒ±jÜ÷™úðªlØ"ÝŒ,®Ü¯YŒ¾†£Ü=äÔ²‘uà“ŽQh˜ñ™ ,­Ø€ ŠÃìILl/M9p×)¸y\µ…6n¶lúuÅ>°ú¢£ø×ÓRýÕãAÖgtyÏ?-›!ѵtx4Æ#¨e4zÜ_ø <â^>núò'K-[^°A…ÕS3½ûÜ[±\q ¯Äýá¡=Á›ÕÖþ ÉÜ`تW¸¢ß0WV«¸Œ0£…ŸÀÁŒ€qfdîñ«Ðùëw†ŽìÕ–”¢ÌW/x3t™‰k´°!Ä—ÎÔ!ÕóQ[Ë Z+Ü:…žú\vü&Œ;Õ¬/Þcãͬµ†ªÄ@µ¶R;rëYK©¬ð´ôRíbÑg„:P³ýi™!¤ZN´‰–RYoôiY¡¤š#ßA‰ÓjõŠm£k…7Ã@ýÇ«\ßñ\wƒ7Ãx”FJ¸„°>-1Yô÷ii!¤¦%©­ÇDŒž¯m„’züj„’ÊOË %5D²Ú–Ÿ-ýkÛÏ_-!£ž2êó+\c/¡£&¨î Ï1Ýú:ꈺôO¼F”¿zZ¨¨Ê W»;3(çÜó÷ÆÉóÉv83 ”@{ZfȨL²ñ´À™a0øÿiÙ¼üh‡Š:až¬ýuÒzZG uÐæú´ Ç›Žd5f´à Fõ\l°¹U«ø3âÀl@JÅŠwÁêýxÒE$¬~ “ÑòÕêýøÙ3áOeÁŸ‰2fOË U†»ÊŠ?Ì$ò´Ü…çùÆB®“öÊgoŠ¿1Kæ…ꑌ¯VñïÇ>uñØÒ:¯! ®ÕJþøaD}µš?,¶·ÂjþÔøU˜ê„'Ü|#¬æ]ƒ9½¢|ò©< ï‡ê'=‘aÒ’_­à kâÃÎ2®³!~€Pl¿b Ì@'l%^‡²Š?˜Æ˜;+ÎÚ½éè‚¯Ý œ Â.ÍÇ Hºvкx)×»ºz¹´l.Ä^.f¨ Á—“úuÃ5Xž辫à6ÜèÝi-±ŽÎÅï×pµ“ÁÔ߈¿\LÃPQÄõ–+c݈Áœ— ?†Å¤u# sU¾øa˜´<Ö0ÌÉÌFu#Sž•õF &ý5ëHÌ1ÚZöëu½‹©ônõ†'=oŸÄc2o޵ÄR*³\½‘)›`½áÉpŒƒ˜LÛ cÖper•z3G*7³•E\é^|µâq™R¹ZA`&_«V˜©C·‚ÐL X­ 6S™-[Ap愇ðÓ‚èLæ lљǹ <“ÚðÓ‚øLjóOËê¼{Ÿ¥bíï›î™ ƒ Ds2ÕHc×¼‚ !š¬äc-1­ÌN\Á…ÍÅ ížXŽªíBˆæBT±µÜtB!šÏƒ*h™ý¼¤ šÇ ˆÐ”j»¡)«f»¡Iïæ Ëõ~GZE„& =-W¬¦ú0·Šͼ9Õ+öjIkšò´mQîçø´ŠÍŸ Únz²[˦‹iÅ8€`&_ýÞtbëù2û²†maXO‘€½‹B°'-Y°‡Š‘Éz¨õž¨§ÐBÑžʈöžááUDÚËtk¤=… ÷Œ|Þ¸'É ¸§t2Â=Ë ÷D9Â=Åé ÷$¬÷¶ˆ{[üDÜÛŠ>&ïmño+¦Àg¿ºq>ëŽ#aØlÝŒ$ðmÅø¶¢Ú|gx°SÄ*ò½%eÁ…]Ç"ðmÅîð¥E€À· FàÛŠÁ"óm…Ô‘ù¶âDÉ|[qcd¾­ÐB2ßV„™o+]-™o3›™ïØ¡o+‹Ð·%núŽA‚ù¼ h-˜o'Çú¬K- Ï2êaÿèÛŠ#õy0iPŸµtðZÕ¥s3àÔ—§èÛJcBèÛXA|Þ$Ä·•`ˆÄw7ˆï8Ÿµl¶Ü<lK@|Ö‚wÄ·•S%ˆïìÄwÜßq$ßV"Ÿ÷ih¹y~d³@¾ãX@>§çù¬œ äózB9ïüÕêñ7Q2¨ÏGaËÆCøD}[)›H}–e±£®‹ç7ÈûÓ5ûŽ‘Á}6N?¸ï8pßy¤1x~èØ·•…ØwÌ`ßyzÁ}Ö‚÷Y6ƒà>îËcûŽqûü'ø;¸ÏZ°§ø—ò;nÐÏZI@¿ÍŒð$?ÿ2Èï8;ÈpÇ%øÙ~t/ž†qðóAbü”RSàwœ/Àï˜,¿ã ~[é{~~M€º¿|*ྭT`ä¾-w2rßy:{Å øüŽ‹ø'ðÛi‰£ª[î;ÎÜwàw¼4¿³ž¾90<}r½øù©ÄŸ¬~±HÈ‹å/ñ Üwž?¼}5 °ïøÑfúT=[pßñofPåÙ:ö÷Ø·Yà@ØwÜ`ßVþ)bß11€}çé!|³1É0¹ïìƒÎ<p—PßqÿúŽ!@}ÇËêËèÛ¬*è;n /ï7˜ï¸1`¾ã6€ùŽ×ÌwžïýióåùrB_>BßV¢.Bß–9šÐ·ik&ó ˆélK<‡ ÎãØˆêÔý$óåè;³ï÷ &ôù¡o¥óìb×Kè;î /§ ¡ï¸{€>¿` B;ó耾|R„¾³Ïìïc#¸3ï0¨ïìƒàÎãün-¦ äU.žß`ËæciƒúŽ;ê;ÎØ©o«d©ÏÏ|ÙßÜPß9îÔ$¬/êsA ¿õñMúÙÇü,Ë~Ÿ¹„Ș7˜‡ø¥Fð#gú,x °oßt•"÷!ÕpbŸüÌ„}÷%ö)ÄKا€.aßMAaß1N¨|TqRåc¸Yª|]E•¯1›€T¾Jg)bßM·baßÍ\v¤>–}Mê»Þ\QŸâÍD}òÒõ1þLÔg:%°ÔǪ´I}gËæ¼@}GÔg }@}7²x'õ)n Ô§;#ê³*êz…:*iÔÇx–¤¾»r÷Kê{Þž¨9ª“úöMS#©/ûú¬ T:`ŸÜž} ¢öé=ö8} ~ôÙ« `¾£ ˜Ï^Ò7ó= w³%*û®Ìw³ˆ˜OAž`>M9Aß–Iè;ú€û­)îË3&÷}À}Ç8à>}3Ä} 0öÙ£D`_>ÜÀ>MTaŸ…}¶¹DûŠ)ìÛ[ìË&öåã&ömíˆ}L žØ—·‚ØwŒ¼>1°/o ±/¯›Ø—7Ø·)M“ú6-µ¢¾£Ô·µw%õåEõm¡©±‚¾cXPßÖö‹Ôwôõ1·|Rkt'öåD%ö)ÖZØwô÷ÙÈÀ±Ú^Ç&÷í›(Kî³·â¸o¿¡/¡Ï7½Ñ€üÜ—’ùò }ù:úŽ“»5 Oµï˜•„¾<Bßs.z[Õ‚Úßз—49@_~5}[;iB_¾Ò¤¾}ÃH*êËiHêSè:¨/¿a¤¾ño;qªjU¥ªVµªü ø§'%þSªàñ«q¿ßt Þ Êõ õ€šS@½7@eÆò1ˆÿòPä?Mqñ_ÞòŸÖCñßfÎeðŸVUñ_ —ä?VÉþås!þå5ÿò„‰š½Â?m'„Ç8í:ÖPÑßNÖýi»&úËk"ýå!ý'CÍ/ ¿‘®,/܈Nà“c‘€oLFoðY„ ¯²=AÁ|ªR—n ºK·N^"ôÙ×}}G  ÏÆy{vGôg è;Zúª%è{ÆEÙ'BRølPˆO>@"¾< ‰ï8OÀB>}€|y‹‰|ÇÑ×ý>˜Eu“ù ·ˆùÜ-›×p½™OÕÅ|º5b>…ïˆù À€ùŽqÁ|cÈÌwôó1Z2ßѲUâ ßr2ßqÆ`>½b¾¼r2_zp‘ùŽ>õ}oÈ|yÝd>s÷‹PßÑÔ—NìË‹"ö' ì;úûE}j ôéµôå!ôåq}6SéÌYy„5@ŸG3{˜/OŽÌw æ{î ¶êd¾<_0ßq6`¾cໞSÇs!ò¥O ‘/Ÿ‘Ïn Ý=5 ÛùŽ–®Ù\ÞÈ—·†È§ïp÷tä{îC}ùwÚ×®¿ü;­D ßh’É€|9™ïèæ{Z@d¾ô8#ó©6-˜ÁŽB¾É(@1ßd$¾˜/É|éMFæ;ZÀ|ÇÉ€ù&ó»‹ùæ%hóé‰|y:|Ïß÷[ê³m†òÙ ƒñ€|Èé’Ð7™UÐ7/© ¾§¶ÔľÔ—þ¦€¾c@_ŽÐgß}G@_ŽBè3Ù—‹gž ™o2B@Ì—7œÌgw-`¾£ÌÇyÉ|v:`Çq))‚ù&J˜ ùòéùòGD¾|¯ˆ|,€žÈ—ωȧë&ñåu“øò ñåÄ—w†Äwœ0ˆo²6¤ˆï8_>(_ö!ñ¥k+‰/½‡I|ys‚øòšH|ùÞ“øòšH|Ç(S“p¼‰ÏæôËÉó<ˆïpeÝD]‰o2¡‹ÏúÍ.Ü:cù4[H|zm|yM¾¼{¾¼&Ÿ^ _¾Y¾üÒøò² |º5>*ði\Ÿf³€ÏFæàÓ‘|zP¾£€ïgS¼õ±ÌøtË|Ç9oŒòü47Ä{y2ä=}sÅ{)@¿Ï[SXàË›Cà;úøøÀÅ{yÝä½¼£Á{ú@‰÷Ò¯’¼§—DÀwœ €O/¬€O÷†¼§·O¼§wX¼—w"xOß _Þaß1îÐ’ŠÇDàÓüðãøøÿŽ4gIÎvПª`þn-2·Jþ2½$àoyæ(Œâðç¡Í÷)ø­¢ 3Àß²¹Â=‡¿çWMÑ‚9R)þ,KZ'êEÁùJÇgÀß*Lpïì·Jg)°ß*óz‡õ­b•fOü[E·À¿eKñS$—¿›žk 싼 )÷)d,¢ú ²ˆ(¨ïièoò»™ìAq}“RßMg=I}yª”úÞFìS¹ç”ún.ľ›©“Õg¯þéáÉT‚©ôÝÔEI}¬.êËsaP.ˆÈwŒ>Ûïð £BßÈç·òåÝyÜKBŸ¸æ1}åz{wƒ0¤/ľ§ŒŸ é³M„>ûD¾CúŠÂê}ÏÉl¶DÂÑ!}Ï8Ø80¤¯(à-Búô1¢O5~ѧ«d@_©‚5@_>iFôÙ{¹wž-½>΀¾’´†€¾§jAÄôƒ ¦¯Ò0cúž>ôYELŸÄ>ÛW½Ï.{¿d¾¬Å«˜¾’ˆ >eëR_ÌçE‰!ÀÕö:=†õ"`õ)ó¢úT×Xa}…¶Fõ•ú p1,»¾\;;Å >%RP_éÒÔ§ÅêËÓgP_‰A}ù‚0¨ïA}*c­ ¾|Ô—O€A}Ç8ê³ôQ á‹ ¾B{­‚úò% ¾¼ÃŒêËqÕgÕ¥_2ßq~Œê+ ÅeP_64ÇÃ]„A}ùæ1¨/φA}yMŒê;ÎfÞïë+2ù0¬ïø Âúì*ql„õÑ1}Ù1}º"Æô)Ü_1}ù$#¦…3¦ï1}EKÆô))¡búŠŒaŒé+4%+¦O©ÌÔwŒŒ ¾üƒúžâõÂ=ë3…ïxÖŒêS6FEõ©º¸¢úžq ãü–ÞŒƒ¨¾²ø9`Tß1¢úT“\Q}EÑŒê+S$¢ú”k Q}ºJEõ• ÇCXŸý†‚^å{4É€XOhSa}ún(¬O÷Xq}e1‚a}6ÌKáËòå ëS]@Äõ©„ºâúìö½ˆ/oâúl¡†!®ïlQŽŠ*D\_¡ÉYq}y6ŒëË[̸>»É胸>eÿC\ßÑ}š ì³›…öiR)°/û0°O¯›ûò‘3°ÏÆôæ³lj§½¯€}vÝïÀ¾| ìS¹{öi#¦À>½êd>;›.žßŸ“Ëí,ö{Hbóo~Tʘ¿Îì0ÿáG+’ú¼´?üœÿÿCÿë+¥Ì;Œû=ËÌßüõ¿ø›ùÿÛøJRœÿóã_YúÈç?̳ä‡ù·9̃q¾š“ç¼O·½N÷?ëþüõßò¿¾~]ÿ:[þñ¯. AÇé¾ïÊ:ÒôüÇO#}+!%ÛZ#)·}ŸGø'ß’xN´üŽ@OŽe9¹w?ÇBËïsæpÓ²8¾N -¿-HsÛ½Õ×hù}× —^ˆ–wbÁæyq>޼QUO2± Z2±à7ÄÄ‚èðG ögYó=·ÆVË‘Ðm̘Å?Ä€=Öç(ñ÷9†µhÿãøý(±óÙrŒ6ŽÂ?ÿâ‰ûå%:_™¿™öïjVø¦~;õàÓÁ@é‹tfßÎøåožñçã•ÇìÓ«c7ev^9c¬3`Œõʈ±Ž^ëScy1Ö™ce/ŽõÊ)ˆ±Ž<€ëÌȱ²ÇzåÄXG@ŒuæäXÙ‹c½r b¬# Æ:ór¬ìű^911<€1Ö+[ gsöÂX([`[nÑúçl¿™-ð;>Æ?¿?®_|zþú\=?Ç_Ÿ¨ŸFùýÙ{ñbµÿt²þùk9_¶À4m‹f6¾×¦•æi¿¬Pß,E窕nrOOÙÀ<2Í2© P= ãí¦í¡Í¥€a°´ÓìݬüŒ'ˆc:¸g70˜æFËå9 Ëµ1p/n'^¥o¨NO‹'. ¡éÅMÅë2 !Æé^ƒfß^F$bï­§e1Ásl1z™‘º0ÏX/+±+-W/;’@+áÓ;%¤ï厌¯¶ýŒó»Š'bïÊ#ׯËs­ŽçRJžOÅnæ²0hôg×ôü=À ýrcñ›áGݪ±<—0íqã@n,^ÓâÇñ«áŠÏxžn0Ôs¢ž‡}tfAìVÄ–…ÍX¢îVlIOèîE;ž–Þx:^'l-½HÝn÷°alßk±aU{©×ËŸi2dü¦VW|ž¹;ÏÓâŠÏº°w}Zš+>KuÙ{ukñZJ×Ý­ÚÆŠ>#»¹x-{âh™®ø¬Êtݽ.»¡VcGÚ^Qa^MGrsñs$V/Ä6o-®ÚWo%ÖYƒê–ÜÛ®áù´á<£½ bÅú˜~ ÏãŽ|zÝ8ËŸBÊØ[÷dìö\0aZ÷ª VtèÆÁÇŒaÄÔí]õ‡ÀÑÞ–'c·Ëމø´ì¸„‹oIss±ß¾ ãÜQUA¾Q½—ÈÆÞ)=-^WaJøéÝíÅÏí*úUõ ÓòTÅ ìn1~ÎQ}OËŽ[\ñ7?-¬ ð4x6öÙ)‚ô>K¼JôyZ<ûT$HïË++̛ѻû!G úÜ%®JOËŠk`Z¯>ŠWV°"aìÃÍÆkL&€yN°àWÜãf¦>ZW Ywúp›±SZEƒ×U°×&ŒU}¸ÉØ_t¼cöxÑ©ûöá&ãe¥pÿÆòº Ï'rP;æófó>¼ÜZšÏ³Ø ýž¿ïxÌúÖçåeì'ø6Ïêû½U™ ¬ÏæeºR<-®¼vK§7ûŒKÈ>n3~F†ѧ{-·l³Åž?K(=/¯ª°r1™n2ŽÓ‹'iÝí±2lñi8-p7Ɖ`Ï%4ÞO«æs¡óã%Àγ±Ù¿âÍÇ Š:`þæãvÙ‰ÌøÅ z!°!·Á¾<ârHì(¶ Ügúò„ZÏìRµÀ¦<›»U#þã@QÌT€¸H+æO—2NG=°iKé@‹¯ª³2qOGM°©€ÜîEÁ¦,:ª‚MóÛÀ(QlNlº; ÛùRë¨ 6U±ï‹ês2-QÝähÉÔçµÁ¬4 ¾>7’¡W&ë¨6Ÿ³Â“»/ûû™DõÁìû„ü]±ªÒßQ"lÒò÷´„Å|ž ¾¨f/.¦Â~S @:ê„ÍÆò„•ÂüªÐ~Sy_;ª…cs¤ÏŒeu X˜ý&¦Ø(áH1•v X˜¤)莳Ñ!c XجÈßS‚'V0lHv(6.V•¨f÷çWc›œ³u dؼè¤3êŒUUëã@É0;ö@ËŽUõyÿ*FŽ’aCQ£ºOŲêRxV(æ/Aôiñù Šy7P2l˜£~ãNÏÙtè%ÃìÞ0ŒæN~ ãFͰÖé]3š;U,û^lÔ *J;P3l(£øh±O¶zRl‰ªaÃJã ï£Tœ Ì+3ËŽî^k,Ê“}‡QÙßmZNtƒÂe# àü“z ü»`EûY¥ÈPFÈ~&Å„fEöS¦8Á_ç>•ð—‘4„¿­T™€?÷Â׺ÀIè¢çàÏ3{¥ ²?`¬'î‡ à¯£ü™3pðg|°ëüE÷þ.ÍÂߥ_„¿K± „¿jõy@`õ@§€¿šë€Ã_UT$鯪T0é¯å¢úkL|Jø³×<>„¿ž‹à¯[M¤¸LÀ_—¦OøëØöýžDçè×õùô³ øýB¿!g#¢ßð› ¾D=^Èï™TûH~V9®¾ÈoLñ7ÈϦS|àI~cPBùí¤E_cr’ß°—ägÛ`0À¯7ÑX€Ÿ­ðxƒ~¶¶¬‚üæb–G‘Ÿ}”À‚$?½W ?ûNÐÉïÙƒ&~,£ ðkÌrBðKâ ÷™wºÜ“X¿Üç Ò÷Yf\ô î³í5[È}7g7¹/ç“sß¼éâAî›¶@ ¸Ï<þð›à¾¥]‹¸o1֛ܷ¤æ’û– š&÷‰ À}ÆH` rŸjì‘ûÈy%ÈßqsN&÷M°~+·Ú$¿¡{!òcbn‘ŸíÊÑä·´æ“ü̪¾ù­|GE~ôúµ-Jú[£Ñoó úu‘4ÐÏÌ ‚AG¿5‘/Yä'×b‘ß`ÔÑÏPYG¿5¹ÝúuÔ¥ù›s ä·T2€ä·ÌUÜò›ÉV ?U‘%ùyYBðbŸq¬ $¿.L"ù ò—“Ÿáæ!ÈÏxw|"?ÙÁˆ~¶þ:ýVc* ¢ßñ¸‰~‰d¿Î´@d¿5tö{®Šö³ XÆœýÖ`ÙÏZnÒàâK²_ðg}Æ þŽð·´"ü­\L»éªÉTÉ~K;²Ÿ™pQÎ~Éã@?;Ö  ŸO:€^ Ÿ™qú ýì]Ázô[íæÀA~«Vq^ŸÙðm!ù…XMì;®Øw|šûìéà°ObŸ?!Ø÷̇8[b_ÚW‰}ö¤¼‹OxØg„ž2¦6 3a.¾Ø—7ŠØ·Jrj`Ÿ-Q‡ì[* Iî[2°“ûÌ*BŠ î3"Ù+¸ÏŠ—‚@À}îæˆ>Á}Ë–30\Ÿ§]”Ü·äEî[ò(&÷Ùƒšh îsqìðÉ}ö¼¸/×rŸî ¸o¹Gõ/öi‡Dì[ª Ø7—Ø·¾Ä¾Å¼ØÄ¾%łطTošØ—ï¨o=Ó Xê³ë úìekø†-µò‰ƒúŽ>N}¹Î‘úÒú+ê3ÿiŒê³ïXÔws'Nê3;ù2¨oÉ'ŽÔg~¸xÓA}vKZ Žl&°%õ¥‚ÔgØ…³õI!õÙ. ìsóß÷ùܤP’ŸûŸŸä'ÑÐoÑ(Mú;þ¬BЀV‹9jÊïçÆ飯˜®Ž€Þ‚å6p•Tq¨þ©ˆŒÔ?el”ú§Ò(RÿZåvÅÕ¿ªhöTÿæOø Ä¿ç)cIÿUÕi‘ø§tUÿrþk£êP7*À22Šü7žuû^Š¦Û‘}­ê*$ü×mw¶ þ›!rÄ¿¡âÉÄ?3ð”ÿY‰ïþâ¿y ñÏdøh€MCÉ?ˆ ÀAü³"ß/!þ-f®†øW§@ ø¼|Pl@€¶ÂŽh»r¼@@c,l‰€i% ø7ÙÿJ•h>ø¥ž$õÉé!©¾† ¾‹›cQŸDhQŸÍ©—˧•Ôå¯Pð·ƒåóiA`3ø|¦ d?+wÇ>ýkyIö»µ]¢ìg›ô ÙOTRŸ‚Ä}3…}fÆBŸÀ¾j–OœM`_Ua[b_UÕ7aŸ,oľfŸ> ]`_K³ °Ï~…Ý‘c_KñØ×ê’^Ù/wྮP?qŸR˜Èé3}¨ûå…ºŸÌÒýT ’à÷ì¶Àõ’þÒÔÒßžÂ3€ŸÙpþÒJMí/¡ à÷l:h‹øÍR‘ ðëªÐGð;û@ûëUççà§øOikËã4Àoúiz¥?~‘È}c3,ŸÜg¢"}1ƒûÆóY£gpŸy°¸¯²Üœ´?³2`äà¾q \œûÎc÷ £GpipŸy$vú†Êó”±÷Í&b©·h"¡ûYê œt¿¢—ŠÌ÷|XÛ›ùL>À¯ ü©â™ïp˜ó™4Ý áóÙMáÁãsrkFæ;|äÉ|åz3_Ebé~ª›,ÝÏl— R0Ÿ…ñPå æË'K—Ï!o]@Ÿ™¿IU}Sé±}¥óNP÷{æoÿäó©{>Ÿrp’ϧ­b 1ø|>ÿ"ãÁésʲ+§ÏŇ ê;\H}=‚ú´9õÙî §O» (8}.ù¶†ÓgÚ)èô9t'èôiÉ£ñ8}Þ2ŠÑéÓöâÑŸO+ûöùLï\ù|rï(å/¿ÌôùôÙ 7¥3ôpèô ôÉä-è«¢BŸDy|Þ¬!/O^’”?eâHé °Ï¯ØÑ‡Ç§œ?ÒãóðuKQ„ç<èå𙚠©Ï^Ø·òGcµ ïY!à ЧP9|Êu&…¿”ìÜásíŸÞÌWzzwB÷¢70ßÅà 1ŸŒIb¾Òä Ï[ΰô÷4A€ü=Ÿo<Á Âß!ÙúJäUð0Ð÷\ëýþìSFqÂ_úrúžqù«)oB)•?]©OŸ–TþŠ|V}¶MŸû,­ÒÁ}ö"7÷ÉD"åϲÿ€³È} í’ò§åˆÜgó…”îë˜s¾çVLØgµ? Ü“Jø»§ú8ö]%ÿ¾)´OØG«Ä¾Â(Ùï¶Ot#ö‰€´,Š%(y}ÞÜ7kgøpñ.TIw ò -¥Öô÷¼MÞ˜ý”¹²ßÕù+Ê~5½æ ûy.±WП?% [w ÚòàŒ·»[©éZ¢+þfÂ+ZîÀ¡šXÀÁÏùojÿìÃÿÙŽ.œÁŽR)†‹Ê5D„ÊÂxË~æNúrû4k)™,øÏ¬2XÁ+Å-ðßaG¤îg4胷ûÙ‡c鸞?í‹À¶Sêl áϬã 'þd&VÐ_úyFpBa1æOùó÷¼0ÂþŽe?­2’ý*Ëú(æ¯iÿâô—Ÿ@É~æ-J_P™(±ˆSö³›P ü[Šiì·X¶D²ßJ´ƒì·«  ø''sâßÊ}e¿ú£Pýn¤é#ü­Ü}KôÛ?Q„æÇí,%¿gþÓ[’Ÿ íýòÜ€~¦ÞÑ4ÐÏêÄS‰ ô;ôj~]¶{G¿Ý^Ñ~;ªÀ}[‰±$øu¦Ó’à—àçùºÐàgâ^_ ~†el Á/qà·3†–à—F(~¢:~*¸NðÛ²z’üLˆeP?ÿ~{?Ù´ ~Y¬ƒàg€^ªüròPð³á-øákj_ÆuQíÓÚ'‡O"õ™ÄÅ€;¨}CjTûäÒ-‡OúœŸ8[Rß!:ø¥Z.‡OyüæÀ ÷µ[^¢tø, ¿ƒ¿ç`"=I}ÑJe/"ýT±Hþž‡nGO–j÷Y6?‚„(êƒ?¡ÀoST÷ nvÓßSþÛô÷Ìk‚»§„i}V(õê·ä+%ì³ln/ì³Û’ ­/ï8žÆt¹r÷´¤‘owÏNyZ_—[ø¡õñô@}==BA}éLê³´owÏ&‹Ý=}«ã .õ™Be¯2b˜zÐúª\ü©õµþÓ‹ù–ŠÕ§·gKñï¦s9yîž©3Së³Í8Ÿ7ÏÐצΟýåð¹”á9©ObÐA}ëçg}@%rø¼ýÂ>Û¡ÔGT:|jS ‡Ï[J$Ä>Û/ƒ&!öU¹ÎQì«tJ‡Oí‰}æi^£ØÇµUܧò ô»«Géð)ù‡Ü'gˆ}-ô~¶ˆ0~Úo%ø¥¬H‡Ï[Ò#ÀO.þû”ñ!Õ¾M™KŸôËøÉÙ)=>¹5&øév¿çlà´*ð£ÍFàgYÄßjŸ¼ÇÒãsð: ~•{¥¿Ô~éà)ðëŸý–o ~‘Þ§éBî³ApC©÷¥§0¸Ï^Oz_ª°ä¾ç¦S7÷Õ-?Qx|ª&<>M×Fneâø-¾Èáñy3W¡<>YuXŸ–«1.AÜwÅîþÌŠVžù¹ŠnÛúeEÂ<ãíóñ`Ë/j™6óüú¯¿ò»ìÅ>çï~Gz´/Ž-q0?qŒ?-:†e®³c©å mÇXjɱpeù}oëÓés-öÚD—,ƒC.K µŸKà‡~>>Ë‹:D¥wb|°¨ì¤›{ºÏQ¹àrvàóÝd­.*?kNg‘ ßJ<¯9SNÕî®fÃì׬ëgPô@Ø„ÄUšu™J´o¥¦ž†AM³Zd¦wQ’å!ìÕÌ?Íâö ÖVÞw÷#–/œ5±=}è’ÒBÎ|PH‰Â›óÛ°j*Aí-Òm »H,hEŸuÇLÆð{®gú ÍK^pÙâÛè%ÕlOò4 $‚±Ä±ÅìÅÔ_¢c f­¦Vk:³ zÒ„a~V°C\žõoØYÜQ݇À[³ÃỘÂH8ì¬áß½Ö°s„><\hXþÛ›¾F¿OŸªäUîw7,+édX±‰k3P[^®È=Ã(YUL¾­¥Éá¹Û 5ð€g²ed¨¶K)›2«“½Ñ÷ß„Žj=Š€Ò¡Ó BÝicX›Álvæç(¡õ?ÿƒöóåêv·¶Ü&#|ü¸SQ›n fj†ûír;ƒ%”X›JË£ÖÆí‚ðsV…|·ûíø“ –ž‘ñÿ¡;¦Ç0oŸâ6îÌ›kô¸Šxæ–àÇfkW…3K5c³Õ¯ÝåÉìGÔÕÍw´ù-¥•eÚÖ@=Ï#ø(ü–˜ “ÍÖ®š&s_~O‘ôÅ4N›¬}2.ßDE›¬ÝŒüdLqµÉÚÿLh´Éê‰{´8ë«-‡rMxÇ…‡‚»ÂãËO'ÌQÇ¿¼O;Ãh7L= Ì٠'îE˜sVTdöÒÇ¡Ì+Ù~C߆Nu~~al6ïp¼‘äæ®™.÷¶DØ|µœ$a=ß‘ªÿìs˜¯75.«ˆæóu²zØn%æëónÆE™WlÌW¦ Ú}Ä|LCdÆvŸ¯1ß{–˜¯f6c*Ÿ¯&6úm·Šh>a íOVÍéc1¸ÀK“Û·mÒ€çe¬Ý~ÿ•×¥°O×ÅR –ü¦Æ'òŠ¿}e}¾ê¬Ps›-È>ü-fýaæÃÊc…-ÇÀ-ˆnœ÷’hÓû”øÓ­ŒÏ %œð½šÍU/K×¼¥be5A´{KÃÊÚ@ÈK¢Y— Gg«ˆ+k…_‚E³U~GáËjÅçªaäDÍ(/‰fTbÊ÷¿Y¾°vsG¾âWÛÖ§esÜÛÖnÊ÷ãܱ°ZÀ«þ¼*šÍUkñÇâUÑl®Z:ñ}j,¬v|ѱªh>W­~Õba5!Ý_µú¬L¶_ò£G—ëj)HDSmí¾l«bÛ;opídxu:¿¨kùºÚMÕ_ÑÅR¡ØOà™â…Ѻáéé…Ñú}üeôÂhÛïV‹½¡F³©ê7Ý·@^máŽîèS}iíV&îŸmž©ê{«¸6Iž©ê-NÀ^m¬9îMrß>òˆcM_ZýW+ÎpúÚÚÍu|GËZao¸1Á½6ší‚o.ÑVÍwÁVßçsûâÚmžÄ Øl§ ¾¾yy4Ûß\û«y_ÑÐão_[Ÿß4¼´­ùÚú´ €Ë‹£uïçY/Žvû0ÈšáÕÑll^¾uöêh¶¶I‹–åk«+Îwû:Ò½Î䊖;¶Á%½<šoƒ'´ j zÙq ¾òúh¾žÐ)½>šYÞü”£¥úÒêÇò¥Þë£ùn:$0«Žf¯¢+,1Ïl ó“lˆ˜nßøÑl1]'üÓžwâŠéOÉj£ù\Щ*ÜýÜ|CáµÑFoÖˆj~rþ¥óâh½Æc¹¢åòuõi3„G³¹êWG·òhËú\7Çi;æj…ó¦WH›v#jã¯F‹ÉÊmº—H³SnðaÃ‹Ý sa,e“;ìÍi!ã£üî,r'ÖùFÀŽUI¸˜ÖˆøÌ˜/„€›®!@@“1ë m^2D@óLÞ LL‰€rÚ‰MØŒa´–%6M¤ß/Üýf™9@ EE9+@ ›U_h[€vb +™¨FèJ&Êk9vÛ°|úŒ×¿¬¬,î¯ÿ¥Òo «Ue` ck„íýUAƫեêP«Õ`®&` ¿ï±¡æ×Zfô ì÷Fà(ð†\ Œƒß‚ýC. ôO+ÜÆ&V«lq ôUo,W«+},WüÐÏ‚¾~!râÂjepÂjuËÿ h‹i;AÐSÆ7ÚV†ñ¾¯´Efû¾ÒrÛ#ØX.æW%Z:ºÿsßW–VZhqo´È£Á£%@ЊŸ!… @мæ˜ÅA°tºÅ‚ÍØ a X†4ÁnÉ h[/Hwà@;tNp`AÎ@ mè M¨†n´p Ð.)ÞaB`é­ Ö'v°„@/:ü‚@m, æÄŠ4!ÐüãK´{„À¼„@Û¸ÖmàR ]y¼¡¤À¼rR =ËÀB@`i É!Z¥á B`éðÀ&–/ÐZÂB´Íw ÐŽ.2`©ð¥" %ЪNÇÚÝ{3 ÙÍ|€¥0¥ Ð÷ha…ƾòDÀnu²ãGA€¾Q¿À„+¶•´œ“}éŒ=Yü*°ß”õH€ÏÜ‹s üóïð<ñ¯[*0ÿºÁØ ÿº9ìÆzü3çŒøçŸóÿº•шqÿž•„wà?ß>¼øïiaEð_·ÏXm€Ï¡iåúæ%l:Àîµ%ãt}‘Š{ìV–}nØV/î‹€Ýë®~$úâûm àÓBʵ#Ï#ø¯[¥ÖÔèüç]b?þëö,î8NðŸ? à^,©ö(Ö ñpôŠí1 Ðú”àSঽ›è-±zË>з-˜+ÐÏ0.è}]€Þ'€ŠhDý&º<¶´$À½QÒ ø4Œˆ€Ú·÷Á„±¦Z—@_"঩Rh-ŽD@k d%î¡p/xL 7·”B@K\…€G  ]ùp Üx" ß8ÐÆ‰í=0ï ð¸×E\ ´† z"হšh ñ&“·‹ hEcã’÷A|Á€>p èÿ8ÐZ ´C÷‚ T¸'Ò í›W¡€€Ú -Ê)ðñÇzEë)0?;¤@ï³ètë•ÔUP ßPúDc½šÊ»pc½š Ë+X¯hÖ"ú8LfëÕT}‚ŠõÊ@îÐóÃDôbÇzeãÆ±Ö« iè"ÏM,Wö¾Ç±Ö+“pâ„7×+ž z äÉ Ö`d`·ºì`à ÁãW Á8VÐXÅ‚5X6$˜ ˜ß[‚ {j ú>ÕÀh‰. –½ Éǽ>-BäõjPNú¯ Ù]X¯h0%ú¯BúzŸ°ý ¯6HÐ^Ѳc¶ÚšT7°^u¦£ ºõ,^ö Ána;±^u: úOâñ‚ýdâa»…ÛžíGú@‚›ÆP‘ ŸÝ)vKö(èQE/´6¾µDA ˜/´>q( §ƒ;µ@¿Ìú‚A35Þh‰¥u³À²`Ð2÷l-ë>YÐâam”øÌsPÍî÷†0¸eß nYƒžVµO0h-Aä„Á- apSæ& ZÔ¨ ,è‡ 0èñTÁ[€AËG›#ò GO·mœ°ÀA/KŒFla 6¤MI¬ŸH|îk‰#“+Ì IƒæTþqÂ`Cf§„AºP$ 6ªY‚ÁF5K0؈M‚A;ÁS tŸ©òR=yc@a°!QFÂàÓgz oì¢Y°ÇÈ‚°ë$ ÖI ‘(¨[#´ok`Q° ½ˆ‚5[¡†H¬‚1¢`…i'Q0G& f QP×-4Ÿ…—¸irMÌ¢`…KQ¢ mÙ€‚¹*+“(øü¦BÄÒJkZ¢ ®A(èA[' RH´Rh' VdsL¬8K¬Hœœ(XQ—&QÐ'ÈŠ(X±—O¬SS(X‘´9Q°¢„P°V‚Y°";‰X°¶À¡`Å–6Q°’›…‚|¯E‚Ñ‘I‚î&I‚Ûö$A òº>N¬¨”$XQ/I°F@d‚ nŸ@°F±ˆäÀ …X(_b î8°"?¿8°‚2’-¹}x¢ÿzj9²ß~9ÏÇ;OKìǯ;ѯ3/‰Ð¯3ÿ ѯ1øLè×™&KègÂ\ CôëÌá‘n \ª…~9ѯ³¤‹Ð¯3ZJè§^è—² Ù¯Óô,ökÌä#ökLï(öÓ•Šý̸ø‚FÃKôô½‡/¨7Üoük }þÉwQø×XA" Ž› =S´å&úPl•ã)V¦ ‘˜}¨rß—" ‰€òR“h3È‚ûÆŽ"`v¡ØïŸNú³1I4@ûÍé êâg?½A½Ïuzƒ>-]­à²Bi?EÀ¡œuà?ëyüçã WðŸœÄv>/ÐûÜ/þ³c!wøÏú,ƪ†¼0zfy yA÷‹üçA¬,VáòÂhªï—{Bˆ™ —•Á@6àŸòðÏ]¥OЄÜ=à¿ãÐà?;=T@ÿÙeFðïÚÿ|´Ðe…Ï“øçw4¸ øç÷& øçoJÈsÀ¿|zÄ?ùŸÿòÊÉw:žø¬°:9ù/5qòßÑÌ'N´—¿¿Šéï¶ÔwÁh ?{ 7„Aø¬ÈWžôwëSAú3jœ:à«%èï‰þlœðû#ýÝúÜþn¡ñïnƒ'øw[TgtþÝÒ©‰þ™ à¢Èým*Ü{¥Xé/ )°2¡Ÿ¤@¬´©^´ßH ¬,G#%ðZŸ•À‹!©U¥xÑü 1ð¢áJb`¹0ÇS d!3Š–‚0øŠj`at?ÐÞxÖa—XXøSj`“½ÄÀÂï‚ÄÀÂWTüw3^üwÃc@øw3G¬øïF†Á俟ùä¿{RÈ#ÿÙ= æ"ÿÝ(Ö“ü·oyˆÆêÊ„@zÌ‹oð‡(­¸ñò'îý™mÝCI¤²—z òÁz |¡é ’(}K¸±þ¿õÀùÔ7‰€Ró¡ÒÁRzàÅ.ÒÁó©"çÐÃùøügS$ˆ§ ‰€ ù9®p“aE€˜C Œüp €©;J D¦Þ@Vüš¸‘ùÐ'vØ©"JjÂè© © ¹€«÷-0¶û©úŒJ ÄçîÐé -œ:0ûH ”XI\H’HVà¢G£pÁ=& P!´`ûÀ9àÍ‘ù8 €vä—?¨ /›p!ãô!"Gà!ÞdM‰Ò3%R½L1pÅ®â‘Eÿ'Þ7!àDÉâC ¸ÎÕ"1Uy“mõ¢@)£¢À‰,ù¢@i²Šë´\#G‚ñïÊ4'5ÐÌÞ@ÈÚŒ)²ˆ‰PyäD„ôµ&ÞtgšOI¡ù¯°…þ+‚Qá-mƒDxßÌ® "ôô&PÝ'+` @èñ ì –ã -„ž—ä>Ѓ2à‡@8.zi16Ð?ª§ShÄÃEŸˆ |¶AVÆâă£Â^ Ð@û·Ó'ôy™Ÿ¡vmóhQ%§hÉDÞ.¡ÏX%—‘viýø|°M`d`©32°ê-Qd ‰‚õ`?.¦ÿU`àbX-bØ: †#2Ѓ  "í3Ëdîì•°"6°òÁ)4P>À ¬*¾ÅÐÀç²™«¡…¦„ÈÐÀš…mØ•óš¡òOTl eð{Çš‹5J"6°)Á |B›€‘>¡Mq§ð mkzÒ'4O>¡ÖÈ„S¨µ0­ ‚‹ØÁ¢äêi]ÞÁÜ‚Ò'´e`"ÜB- §b§ø± ŠTl ÍÔr µ‡5N1pXª½qŠ;ÖO1Ð#Dáón¡Ís% ú(ñ`àÚ•qz…úûw …›}$ zÔìuJÏ T áÚóÚÑ#ôÚÔoèÚ2î.¡þž¿âíÆÜ/ŸP/H€(Àð µ}J<]ú„ZžŸøÐ'´Ò5I>¡vg:|@Ý'Ô†X§ÐzóŽÃ)Ô¶c§è=&\@Ã)´11‡â«Ü·è'¤…¸Àú|.SX\˸Àº„”ˆ ´ä}² µê)KM]Xå]̰À‡EàØŠ¨À« #$°Ü,ñÄ@ûžCUCH॓CH२ Å>çØp\r±UP ”8ÆÊFȘÀ«ò£« À‹"¹‚{¡˜@ºfL`lšÝ)¼Ÿ2 Ç¼3&Ð}ê!´1,p x†ò›z„v8’2*°Ó[’QýÅH­øtY<ÐD¼=ƒ!It·N¯ÐçW(ˆD ô?x—>-‘_˜[„À››\2à}CºZVC˜ ,¬Œ¤ZË}Ƚžð×(*pQ´2¢ãˆ \h@PàÓ>_¡rÌΠ@9·)(Ðöhï ÀÕIT ´´‡| ”û‚Íç ¢,¬‹¡R \Ç2&Œ <\Da`]f¸¨n*&ÐJù2&#+&pѹ“1¨e—1ñ‡˜@‘PÀe¢:ÆØŠ $ú((p¢dEf(á·ƒŒ$ œ¾§ D)ç HfçÐÎfú§‡…ö;3ƒ[ýí nÏ­µìO«åœò»ÒkưíŠÐ|ß´:½˜m·²λOˆé_šô4“³ÕäŠ_í' àI}Æu#mtëÃõ:O"T£eºû˨tÿyZ\&u…oZëË+:P~§õ¨:;Üî§s_nϲÑå¾ÃžÅýúsÃ-KýÈãrÒõŠLWVVኖ;,Z†³>î0+Å…d]~ÝÃŒmž µíÛWdº‚¡¶YRàíɰ°×}ÎjF¢«gò”hY-]ÍÉ–íaÉOD+>-;]-ä6oVzÑ]ݨ"×f7‡—’ñ‹°â–UÕl¦¾£Z,ëÿ6Ú4{±µX’Á¦™¼9FG1œfµV¶u©Lš%6‹–Ý’+Z†[²†Õ‹ð­B³ê+Õû ’L³jWÓútäÚk^­Ú¯€~Íj´Wí±Æ]f*3 ŠÔk­Ø}0UhG‹'÷V#>–kÄ&«½ ¾Éi–kÄ&«Ù ½Ë6‹›Ý*æwjV,Ãæê`lqs÷[병䭙o·ÍÕaÁÅ~Iù`·s#¹XóÐËþ[€±Y<ŒÍÕ©Œ€¢çW _Wíõ[‹Ç ÙÙO9^wXÀ[·+ö»³™¯‰ñâWá.þƒDÙ,kˆÍV³êÇ5Üá9;ã¼Õð>W…¼•ÍV›ýñ4¯$›­V%– wÏZ1abŽ{J¼-ۧ먈vofñézóe³„UÓ^?7ûÜÇt…ã§—¡²éÚï(KÔK—ñTzþúyªÙízt©Ø}˜=¼•«¨…é5¨öS¼ßÀî©ÜZ¿ÃzçU¨B,Â+Ú-[†‹EŒ™÷*TÓ5'ˆ¢½¬&ûsó†í «çé_q~ÛÖa¢áŒ>‘³äÆ‚— rã³B°†p$ò´þÎzªíi;n¨ÂþÌ5ÔkPÙL½×Ó/sŸµe áJ^‚Šöç]†¯ªV­ªÄ±ƒw#õhœÞ*ö'v^~*¬ÏH æå§bYEœ»—Ÿòe•Éå¼üÔ¾"…FÜ«÷ìæçZ0^ʦª-ènïï5 ³óú’é%¨"%¢Üz Ú£Xù^¿5fÖ·©Zè¯ã%¨nïë°T6Uíá ÏŒuÕ~uÇÈ+ÖUϼG÷„®àw¬«…J¯AåFuä¿ë­ÄÂj&e·¯y *·?ÓÖØ½µç„Eõ /A576®Óæ{ÆÝ©ÑÒcaÍ»lŠ–MÕ˜u«AåSµÌ†»le¨<}È‚Ûo‘yl˜í<î²Õ¡šÌBãìXY Cþ¼Õ¸ÃÈï¦ØÞK¬¬)`½Õˆd+ñd¬ •ç1O¿ëV†ªGƒ¯½ Õñ¢ÌhˆuU)q¼•'úÁ†¢[Qk›¨…‘)^ˆjÎÈÓÐ˪òÇx!ª±B‚ˆ›eE¬‹» §¢ê蓵G"(Ù¿b^ˆª!ÃoU¼Õnq‚=Zj¬«…Ñ!^‹juŒì7Ô6×9eâQ83¿~‚cøºZ˜eÙKQù˜A}øž/ÉC¬XW ×¼•ÏÖ k¯×¡jè3ãäîXW‹¾s³T¤ú‰¨-¯Eå“•ŽÝÀÍ'kþÈV ïs‡}¼[;Ÿ¬&¯Eå“õ‚hâŨ|²RóbTi&}%óbT>Y ?m3ŠõºŒrǯl…ýð$3ñõ¶ò©nÞ_+GµBh‰»çuÝN„¼9aÂðRØRv+9$‘ÖV6O¦ÚïKá– è«Ñ‹4ž ÈOL2 Å€¦ÍÆv… ¸îÈA ´MP’Xÿ ðÂÇ5™9“+âÊÅ€ŠÔZ„\ tÚ|! ~žè!¼hXá€ô|ybKØ÷ ›9 Ð]qE€áŽÿ?ГçƒÝQ8¶ª @‹¸‚¸‚=-O`Ð-üq@€éÕMtýcËz¢ÎØÒ‚]j „:øŽèèzVììH€…>KDÀçW"É@@?Ö>0S€ ½Šgàœ# Àôw=î°ÐoY Xè 4vK‚ ƒuÄ€…q•‚@ÿˆû“ F¶Y }V{ ´Ïa–Ù´Ï|{ ­€þMzï’  E€¶HƦÒfÏZK¼$ÀrÓhA´ ƒoE€f‚ˆ«"ZŠ_°%Ð6qÓI€¶[ 3 ðbþE`¹£ðωÓ#þYrá òŸWEE Ö©±bä?+íwüW°i'þ™ÛÈ øw1_wàßU"ŸŒèO;-ÑŸ©ìóE…Þæ¢¿¨¹óqàŸí¾rÀ?søÛñ+àßWLö3©|ö»˜‡Qìg'³”ìç^’Ñìw1ÎPìwDç‹ý.O’ýì â‘ý® î¢d?{j1É~WÁ§“èg§wèg›ø`ô»r^äg¬7˜äwä±ùYKŒ ð³g€q~9.¸¯è«Bî³~Ü=rŸM‹¸F`ŸÍœØØûr›ÇÁ}…yÎÉ}ÖeÄ(à>ÛÐ Á}eÜd:pŸ Lî+L« î³ZldÈ}…ñ¿Âô ¿ã~7Tègï@4°ŸíuÖ‹ýlëFû¹»Ê‹ý¼ˆ PÏÙ¯Ð>%ö+|É~Jb)ETù•ƒýìÃ^:Á~…Q5d?ß0ÅöHìWvl4’ýè›ì§»'ö³jF'ûÉ£…èçžGþäD~üNH~‘Þ;~Dò£‘&Éïù^Î`ÁÉå‘-$¿c3Iò+(ÃLòs§eÀáå†O’_&C%ù¹ÏP=Éχ±ùù–À¿X$?w_AùùùÅÝùÏäç[‚°p€ü\%ç]HH^ÃCòó=ò}’ŸoZÆI~þšÖøy†Ç€-?tZÁ}þ‹˜?Á}ÇæÜç<ð;öâ?wF  ðs!0h€_ú?%›$÷¥¹Ï[ÆÉ}N-N8¸/à!°)¸/ÎÏîËäÞä¾Ì|NîóÓ‰7 ÜçÇŠÇîóqbÆø§ ðK5?ïƒ÷…“Hð†ÛRû|Œ‡ îów&f ¸Ï·£a«ø…/Z@]€_fï$øù8˜W‘Œ\¨àçG¿Oðó‘ƒU~>rÌ€_&ù?ÀOœð³,Q10ÁÏ‹ÈÜgaÑî³ð¿(qßB–€ä>æ>K/s0 Ùó»“¶ ýn·0è§5B¿0ô³MAØP‰~æ},@ô»¯ðúÝôêúyÆÐègû„òB¿»Ed—ÈÏb>Û‹ü¬oˆ4Rÿ¨õHücÞÂÿ6ÍÉÿ(ý¬ãBüÛå$þ±RF¨ªo¤ø×`“”øw1‘®Ä¿Ü7¥ø‡ØÄÿ:â„SüCÔ|j3ê)Kú»'$éÏœFâÐPþ.ú1Ê&š¸Ï—Ïø¥¿RI‹þ,h#dÇPþ¬m}a_­ñͤðgÖhÈhPþÌE3n%©¯ÒØ'ê«R_I}¶œbPŸymîhõ™»vyI¦fΗôgÑ0aº ø™g<(‚Ÿ•hACp_ýûê-ö÷Ù²\êÀ}ö® €ûÌQ=t\rŸÕ„¦î37ú/¸Ï"q®÷Ù0a» ÷ÁÍôà¾Æ”ØgÓ¬ûZ‘\ì3"î±Ï¶/ÝO¾ö¢>»}ë~èzÁ¯ ë ~{)_Mý-À¯ÊþBð«B2_Ó Jòˇéä׸sú5éäD¿Æ tB?‹†Öýª”|¢ŸÝ«¸åD¿ÆÂVB?»ç/ø³Cíü¹ÿQüðg—Cþì~BüÙÇ8¼)õy„ñm!üyœDü*àÏ®á¥ûYX¼Ž`?õ úU ûd¿Ê$™b?Û?7 |Øèá+ø³bmó%ûUæ<üÙ”¿ÁzAЬýÕ I™„î7-À¿št ü«Ìþ#þ«TéÅ9ù¯Rÿ],üFþ»èá.þ3·Œ;FÿYFlÑÈ?[â¿‹‰ëÄf/ÝÏüùÑügJEðŸÿ*ˆü·‘ÉLxÉ-dáÁÿ.j/@ÆÃ'j³Lܨ&–¸ðbwå(“.50„uk€#¾?©ýÑ—#ùo B$ùÕ’ÿ&ñ RúcŪ”þRB$rqNé¡… €Ï8 7 %zK,l•ÒŸ1HÀ&PIL™$é¯U<8Im½Ðí %úPúk0#¦ô§³‘ôg©+-)ý ï%ý1ÓYJ èLéu;SúÃ&/•¿¹©Sø“æ$áO6 üäHù£¢-á¹Æ$ü=³:f¦„?¦)LåQƒ©üYz4à’þ.š…$ýÅ]î×(úH÷c†‘ÔýìÞö û!|7e?¦îJÙ¯$ûÑÊ™²ßÕÉ\”ýt¾’ýôìÇýºt?=·S÷‹ºk/¦îg[t´P÷»ñí‘îw‹$ûU$,HÙåÿ˜R?u?Þ«”ýbSšªŸ @Rý¨Ã¤êÇR¯©ú±¢Zª~Ù'àÏý :üù{Y2àï°YýùeÇÜý¹‘(œL@fZúHôóroagäWÁê7ò´÷vT""{*}´Þž(Ä™JßB~ÅTú ŸRŸ|•$õIÑ¢ÖÇl©õ-äó”Ö—¿Ö·éÂbŸý éo)ñ~}i}–Ët©OФ>¬¤>9½Jêƒ2•>è|Eª‰”>zŠˆøì/â3]}¤ôMŽL¥ÏØêE|EVz _IGS)}äO0_¡#“˜/$¥Ï"5?~9…¾MGN }ÈV™:SÊ:Êê¦ÎÇÒ™©óÙ›-’úÔ‡R'mJ},Ë”Rßµ?K}©Rê;ZbebâΔú$qSê{ÞmPWÏ¥é~K}L˜RŸt$I}¢¼¤¾tó)Ë’úèî’RßE®&ôi“R¢†Sì£ JŠ}¶y1Ÿvš)ö±Ð ™ÏŸðËÙ³°n˜ÏÌòð¥ã¶Ÿ=¤`i}¬q#à+ÝŸV@_aj‚Ôúè"àãº#Þ;†ð• ¶òž­Šý%öfàïÙ0AÂä½ÂJ9â=;öõrôÔJO޳㛠àsEľ á£"¾"v'ñÙ~á~©}¶¼Æe’øŒ¢\?wh7=0@|eLâsç}ê}ùíð¹[às+x¸øÜ {Á«ó‚„°è/Àçbj|‡}=€ï°pø<—®Ÿ¾¨š]7¶4¾Ã¤ àsCxì`|þ+Èr6T&ú#ðe5MŸ¯ÆŽÀçWÕ!ˆšRb_äW ‚*°¢šSfpÙ+ªY£¡ø"aô©0£ZVø<1b8ðe¥I_^D‹Ÿ³Æ-•â×FìÝŒ÷âüð ab‘üì# ×N,«¬MàóÇîÀ§ˆX_ͦÞ'] ~4/ø¼~œTüäßàó”‡@·>xGÅÉÖSñ£ýÀç×É(~ŒâWá$’Š_E®TüÄ0Rüµ)~ñï_ÅOr®¿ Ø©øÉ3WŠŸ KŠ=óSñ«œ Rü*ܲSñ³ùçLů¢>nJ~ŠùHó»&œ?©ù]tˆæ§T©ù‰k¥ù]œwÒü,,ìã—Có{@*ÍŽ_©ùÁ+!5?h")ù]^I~V>òtõô“ù\l»%$?Ë d Éñ)ùÉ~#ɯœ~žYUMz_™¤7ê}ÐûP˜MzŸepŸRïãªzó^¤ÞGO£Ôûä% à{žø>/ ¸Iï³ âä¾Rß~ž~‚ñrJ%¹OÉ"%÷m Ô’û^”û6*f§ÚÇ”û¬ÇxÉ}ªê*¹O0%÷mºKIî3ÄI7ÏïÌÊ–r_;#h‘º¼¢ý¸$÷]Èr_;jË€¥Ü'¼’Ü7Pf’üç…SísŸ Ý׈ø¤¿qI4ýy³ýy2²%àÊÃߨ¬·©P? J° ±ïb²‰}f ®êwÙÛcBí33‚ÿ öUuIí»µ=¨}ÖŽ•Pû, ÐýRû*] ¨öÙóŒCe¤ôV©}Öð’ûªb|$÷Y*§ƒýjgèšÔ¾»þôûXsPjŸå ŠßPí“hC¹™@SFª}‹þ®RûÄj3b¦Ú—}¤öÆJíCuöCí£\!µÕŠSícL@Ê}ÌB”rßDż”û ñ§Ú÷lq ÓúÙâÑOD?ûM(ÏTûX]èwèW™Å$Õ>ÖoúYŸ0¦ýRR%úUf1ú)tHèWY‰OèWz*½O7‡ìg¯R|È~¥(ûÕA!‘rßs¨þ’û†¤:Ê}Š<…Üg ã‹ ¹o ]rÐ_eyÑŸ}ý^jŸ%4¨Ríã¶5Õ¾¾qú„?KhøŽó«(Ë#ø«½RÉüYÆ@èÏÔªöVû*ík¤?Fg¥ØG£nŠ}Ïçc bŸœd)öÉ&#µ¯ôOj½Ùåèi‘CVôô¼\?éèyz‡ÒÑ“)zÓÓSa¨òô|¾Áq‘òôdb=‰}$]=Ÿ{¾^1~²¾Jì3/ØöŠñ³xj4„Öw±&sj}üzË×SÒú(,Kë+XFÒד0¾ž›‘CòõdœDúzî†ø=ºz.ÆÉÕ“òiºzr…JWOK¥õvõdÕ¯ôõdº­”úl9Ñ×s"­`J} ŒSê³¥5D8H}}(ðRƒ°%õ=³<,Ü’ú7q!õe ¥>CIë«…‘ÔúXA+µ>­:´>Ôòx‰}±g–ØW:£ú(öµJON‰} ¾£Ø'éLb_ä€üåû0çSìS(–Ä>%ö±®QŠ} ù}$ö±M²}ôSìcÉû®ý9ÎÖ¦d?ú޼ľþŽóKÒ£ØWnÈœûhyK±¯"ñØKíC!å¾ê‡´¾‹ïµ´¾kP‚ƒÖG{^Š}H¸)­ÏöØPö`P½»,µ>ÚáRëcxRj}¹ËRë»à‘rßõŽñ£;µ>óðùøåúð }We0…>¤RLO>Å©óüù,þÇ/‡Ì§Q}L¤(•/1‘*ŸÅc}üB‘O—/‘iSä+•1„ùXD ¡O©Rù mI©òª(òÔKL•®R }›³O2ŸNY2_ò%e¾² ÒÅ“ÅCåk¤@¨|å •OdN•¯ >Ê¡òv¥òÔ:I¡Ïåð¥'ÁðHÃæ©}_™p¦ç]Gî¶œéÔ¾ý»ìÅ>, Û—GÈ–LQöù:Z2EÙ°rƒí5–ZޱÐvŒ¥–kº×ÜëÊÕ’c±-ÇÊ–c¬…Lâ9–ZޱÐvŒ¥–¿t¶aô`÷ø«iØ®o§Kûœ†í+ùÔþ"iؾöZl7œžÉ¢>¿ÄözFÍÙKc1Çš†Ê$k‰}4Pöá8™b9Ö8RöâPg/¥këH²¦±ÔKc½4–’¬i¬#ËšÆR/uôÒXʲ¦±Ž4kK½4ÖÑ똢H³Æ±Î¬ž5,H²ÃŠm¸ØÎ8Aw…‹Ü:q~Ûé(]‚‡ kÑÏ-[í2´yØbÀ¡Ûiû™½-8Ï/{:º05´,°4£é®¾>QŒrúdKû·xº™kÆsqŸ%2²E€å-cÀ/ U¶¦yØOUƱVìe¹˜%¾å™¾fÚürõ®?ÅÀwª¯ e¼§ƒºÃöâ_Ši‘. ®ð’š^ êŽ{áãéÅ îÝwÖÓò UˆßÏéÅ ßÕýiÕ fÄFŒ2*Ò´/Ž2@ Hù?½êiöwÅÒzÓsz-($_Yñ«KëÍŒ_Ó‹Ay䫚nU¯a£qåaz1¨}Ü‚1­ÔåÙñy‹½”ûB„÷û¬-VV}^ ê/ ÓÝ$­b˜K«y~ù½ñbP#^Ÿ/Ó„4w[AÀ¬ K+R1N‚£?8¯å +¢­„ÎZ §tÍpò >­¶‹/¬nЛ^ Š>+~«å«*m€³…猯à+†íXU/d,›-r#DŸøÕ,Qñ•Swz)($ÆÇÈËWUïoׂB©V‡’éµ à7rÇÑéÎãÇé• ÐÁM¯Ó2”†OºL¯åÂ9ŠŒM«å3ÕªñDKóeÕ]@|Á™V Êgª)ºÞ0 <18=SfýPTìôJPë#‹tNƒ¤(Ï ŸÉ‰¥~63Ž´WLÔ†uuz%¨Æ»X!(Ÿ§ ‘øÓ AÝá—SÌ AÁkɲ9Ü7×ß/5½'Þ×áW×ñ·†¾b¢V@œ–2Ò'ê…š Ó AÍÃfŽðÂs?_릧´\™nizŠÍ 7•¸†ûŠ™ÊØ¯i• j=¼I¦W‚­ˆ·Ä*AùL-#ƒé• vœO|'f½cª–ûå• î8~Õ[LÕ‚:ÓjAõ8å >I3ÞjA5Ìæè²ê½¢Æß´jP÷+½wÌÕ²Bv˜V“à¢g“ÿÈ«AáAćmÅíŽ[Z£eÃ) öܹ¢–™O¡}ZCÅW8ú̬à—yGÃŽÙªO¼ƒZ¸ª¸/uÇ¡|C1½TÌÖøsÇT5çˆhÙS• çŠzº¡)O/¢ˆ™j… |¦R;^ þ]ñ:zf1ï‡öé4„—/¾–VÊgjÁ$¬+FöS±¸ Ÿ©tJc×ÂïMÓv  =_8°C®(Œ•¸á/(4Í{¾pÝ#¤‘$@Š I€¼ú$ÀZˆa$@º"&R K˜íNa` àf%"  ÌîÍ-.Ð6—±¯âýKd¼q ÍÍ 7`Gb×$@OdÔà¼CK\ÈOJÌ,!I€¥QÖ*ªn$@o‰[J¬* £@€ŒL|VÂOÈ\›I€L5–xcÇ“HÝ: •ŒE€–ÿ ð¼è`'t¥ÈxQ½^ô«*'• ÐDýxä„@T³: Ð ™•ø ЪYð/&ƒ ¾ —î !ðb>Aെ"4WŠ–€ÀkÃWèªöÇÁ€rš£Y\8!ðbv«„ÀK“ °ò›-¬bRB`eÄ™ 𢹠ðbµHBàÕ‰¤`@»Å+z^ ¤^̼(¼Â@¼X]x=×/Ð^ ?5òŸåÀ( Âà¿‹Ñ%â¿‹á°À‹±õ@‹.o¤Š.´Ü{@—¬ ¼H<¼èG¼‘ Vx±n¤ðºî&¼˜é˜¹€ °Ý3ìIÜ &ú8±è×ZÒÐu쯀nV‰ý0ò5Çu­` Z ô°nV‰€^D@ÏôV¢# 7Äêt+Jìhˆ€LäBt³ÊJ tô tðÑ èYŒcåúWü èÖ­+p30¬dÁXd@«é ˜™ÝÈ€î‚0`æ>&ºoLÜw@ û×Ä=ü+8; 0’êFC@`Zl‡è‘F$ @¹+Ý`]@nÎŒ Œx??=P ›âGäÀÉw ˜qEä@gèx—À¾nú­Ú &²˜sb Óm&ÚÅÅÍ,úwÅ¡näÚŠTh8¿3¢@K”ûqB Ó$ÚV6ÐŒHÇÖ„@v‰”¯mëP 4] YKWÈ ˜ïØy&Òy*1°!Í\b +€¼00>’Â@¦œN ¼ƒ•¨c%r2/Ô[<0ÊGbà…ÊŽ/ ìo |ZâÑí;Äy``4€ êH3„(³‰Ü9È·K(dO Äú–(£“0•Öu>Â@a“8ðBžšä@ÚNl ßlq`CʺDA=,¡ Ìž‚tßK´|£' Ò{/Q¡e‰‚9 Q6íDÁv£…‚Lç,X#þ=Q°JïÿîÌm¢AÛî— h±!“mC[Gâ …²„ÜBT¤pÐwSÁ_ÀA³…¬*âM8xKU"Þ,!¼QÝI4hµP<(>ÿ#HJ‚ 9sG‚{bõŠ%‚ƒî’²`p˜m;õ@_—_4ÂÎG o¢‚2ƒ37Ä¿‚ &uÀ ƒÀÊÇA‚zþ"A ¾*§è)c³D´$E Å2™@‚•; ’ E.­S ôH‚2ˆíC¼O1p\¬í#¼è//¼˜¨U$x1ë–HÐòzÆî„$(›–HÐ,X×›ïX¹R$2ãL‚ 1ÎÇ‹oR9ðYo¯C ô.8r`G¡!q ‹Õ¸~Š#ÛÀƒ6ÄßXÉP†h“H‘D h¯KÈvïE¤ h›×™‚àC0¡z% Jì# n|^„ó A¾"Aómÿ8Aù@‚r° N †"Á‰R‰‚Ò¢…‚Ò¸…‚T`E‚Lqš$8 ¬>- ‚±w>oÁ…P œ„‘K‰ÑàE ìˆyM ´(˜Ð般p. ìS71tN 쨩—ØÑžÈžiR¸ˆ Ä@y\er/{` ¶M‰T\Eú‘(9i’)ž s\B`C®kA ÀGXaQ „|œ È,kNŽJäž>Á׉€LåXoB'DÒ¬DÀJ/! 5‹D@–o;ʳù(’«ˆ”(? É @ÖºH¬ˆôMÌ>D@(Õ@šQ/|±„€Ìèw ef! +Õ Ž0¿‘Á-±ÏLã…}“fçÄ><“û>Næ+•ôFæc°d¾kSt#ó±èR2’ù´·ó5äÂOè“>@èë ð‚¾Ž$ª‚>ÆÝ¥¨‘N´Ð ”©X/PµP4°€*j€¶~b_a¶pa_aJýÄ>ú‡$öUälKìkHR‚xú,Ìõ}J»9}mò„¾ ÀDâcaL_)ØwŠø˜;SÄwü„Äg Tƒ A|•ÉE| £òl6^ _Ò"Á|•µÄ|¶‘ æ'óYPd¼"d¾j»è¸L0_c¨­˜Ï’ ÄNÌWiŽóYäú’ÿlCtª¶ÇnÑÈç¹ OõOE‰…|Ÿz!Ÿêv ùšl&D¾¦Hä³äoä³>ö€|%ª„|–¡¢¼|@’Wúš-Ë/ЦדÐg©0 ÛQý»‘~#¡ON—€¾Jß)A_åÚMècp½˜Ïë•Æ¡Á|•Ia“ùÚÄ׆ÌÇPz!ŸRJ ù´ãóÕ”ûÀ|U·ÌWéu)泑+|Bƒù,8~Dä{^¨p/&òÙ54¸{òUO×IÞ³~¨“à½ÊðgðžIbKä=9‘÷*=*Ä{U¦RñÞsj–¼gYÞ¼§ÕJÀG:Nâ»(ùèJ#â“ ÄgEbÛ›øÈ¹©ýYL|hk$¾B¿)ßE;‹ˆïÚ 'â»è®/⻢+I|Ö$ñ YD|uSe$ñ1Á}jôQ?´¿›Šá¡ý©ýMúJû{Îgð@|,Ù—ÈgåOíÏc¸ë[ûÓOÌÇèd¾‚$orõñD>÷ŸLÿÏÿËÞ»äüŽ+[~SÙÍ{•%Q$'`w ØÀ‚Qv£Žá‚áùÊX v¾/ 0P­Ì[¢‰â+bÅbÊ~ÅšªT†Š´«Pù¤V¨Öu+TF(Å|w§(äëÒõD|ÆXŸ!¥B@ŸŸC@åµ½…€²RaߥŠ_Ìâ°—OñÜ åY!Ÿœ+·ÐÃZßáÂŽxÉ|òx+ä‹:i€@1ŸŸQ3Ÿ£ }¡½|¡ïdõò⾓f8Å}'K_÷Y¼2÷ÉU­¸OŽÅ}µ¸/À¥(PxáöY ö)¨°ÏQwƾƒ¾„*ùÜØ§ØÃŠ]ŠõSñ¦Ž}8Øšú*€Ò1 ÄsSŸjI|B@ñ6ûÂbÛû¦2Œ}´R+ê‹•>´Hû£+TqŸ\9‹ûU[! Mb¥¸ïùW(Û üäB·…€^LÌ}êÐS#@9ŸØB@5H‰ûÒ8 ý8”ó’?™¿üÂ: ã‹ÁOAÉ}Ó+žÊ0´â>eî÷ÅBŸ¸ï`!Osß\Zl«(P¯¸Ï6nŸ0PHžâ¾8ÿ¨ý¿ÒþjÅíx3Æeƒ@V­2:\µ8ÐaWæ@)ôr2Q(þpàó ]òmÙ´¿ÅùR‰ØàÁ¥ÞGA -ÝÉ€UÁ¡”?9\•òj*Ìò‘Ö¨ü5§ÌIùsÑú’þnGbJúSü”0ç„`52à©¢ fÀ³bE ñ5þ@`”jŸDÀKET ®$Œ þøpàÕ'Œ¯!óêÈW,ñ8ðr˜8ðZ§SÁ·qàíÙ²80 U>‰€÷Ír5¥ýuæB˜Äîø$Þ2.ío°²xiV4­ýMÚg•öCÉÚß:âÀû 3’@°Ë—Ò ØÓ@0 H8Öþô95ö¶øä†®‡»,ìJ (íïêÊp”öw±”Ji*O–ô÷ÞöþáÀ®,¥RÿÎ)ÁÐêß#Ž ØïGÛHý;QAðrx5A0ì ;å@€à­õ/à]¬H¼K±›oÕ´1 fÇ -’à}pm¼åSêßbœ¢Qðn§cùoòSSò_ÄGàX’ÿŒJþ[SÑ¡dÁm/²à­OIÉá,ÿ9TÚòŸÜ§ƒñþöüçã”ü÷8®Rò_ÜÙ^Êi5^ãhH¼J•#^|6Mƒ—jy›·nˆƒ€oª@ Z¦Á“V‹¥ÿuŠÄ rîcùÏi\“r€ä¿Æ‘ƒAæ'‡Öc ƒ]ºÓ.ÿß@PÙÝ•ü×n¡Jþó¬À0¨˜ iâX0(—¼-TÁµ†Áμ‹Òÿœ€'¤„h”€éL@¥JüS¢F‰Qgm#ÁLOWj Ið=[ž‰H0Â9Ðb”Äi”»åF‚Läýàú’ â%6Ô’A± «[l,ÈQþ“u¢XŸßYf·Xð¦1ï–ØŽíš‚o¦¼ Š’ ç‰FÁw`â6 ~“¯ohø¢0…—ÞÊJT‚^a ô—Â@Ťš•kW©€4¾ßRY•¤(ÐäZ¹€\ãüƒ\@Í *' <鼸jm¥r©F:¯ÎÑ&?^?a +w ¬C UããJˆr èóË7T¥¶PE‹Wèñ.¹ãýQ& #I• øS¨^+ Pá•{àõ…À0VùªF [èøeÿ¾å*9¡@i1º€êFTèà¯P‰€œʾøw›ž+PI|ÐþÒZџׯ2­P™€ú°”öç~œ È• #`S¼J%öŸ£?e“·er^³™º÷Sò5Ô™‘Ý¿›_±a·fûݽj#mò¯9º˜éÌýÕRngj+g¡j)·³™–ÕŸ“uKõ¥¶ê«Z¶¾bݤ®› [OhÚ:Rô[äZ^qOv¶ŸM¡þÈUm²µ?ÞàWÿÛ²êh¹µ½­ç_Ø ŽC‡~ýÈŒÃÜüxEýôðŽ‹ çg÷$›5wT6kêG›¨›ÚB½”ÅšºÙ-ÖØOmÄŽömÜ“ ÖÜÓf°¦ž¼‘zÚ¶qO¶WsO›½šzòFêiÛÆ=Ù\Í=mæjêÉ©§m›ze­¦žvk5¿þÚˆ=ý+ökáÍ=þßí×þÌ~í/ŒÝÿøÕ8üCõ?~óåüyøþÍ—óW=ýmëµóŽwêýßÒzí¡þŽõÚ»ùoY¯½ÍïA"7g|FÒÿÒþp ü]ëµK9)ôm}FÈÅŒk01žÊå~[Rá»c•&gµ£ßYç“ø Û Ò=O¬Žþdp[:¯q§gdÕ‹þc#>-ètñþRQC!èVN0o,ÑdCàx–tÌ…˜ñ7¢ˆdÔ5ÌnÞ :oK.“TÑx\õßIÚ 7¹Éü­ñÀ„;LŽuã£>“9Þy9ERîxž›* Ã^ƃà˜EàècQEa}šñΠ8}Æ.±dÆ)cίßcãä¹noÃÂÜ™Vc´‡±sŒX~_¢; X…ã9®ÆÐ¹Ž9îÛ²:G£¶1î³gÕiﯫ¹Ž{>žÆ*V\œ{[&¨TŽ1šÞÐÉiÄC7OPnÒé«aö|qÕv„ 0¨ŠæÔr„»_› eË‘¥0) èw˜?Ëám™theØÆÈz7é»GC›ófÌ78Ç1·î¬—óð,°r›‹ÇÊ Ä ¾#näd9¹…žï³¸f.•,"–Î ú9cqàLyýÖÑŸ¬cžúzñÆÔÕªéˆ+L[uæ/¸ÀƒܸЈ]FþZX’+öŒÔØ›~Ñù¦Îð ›ÏO=³2·ÉÕ’yã˽z†OÙÉlÜ{¡âZzpå[8ÃZ-×£ä3#±9×£$’Îw8èUÞp†ãöšÔƒmfcp‚û‰3nÃc­‹RA©yÎa"q!¥8Ìfd#Ó ù3ª[Òñ̺ç¬&œÏ쌈ü¦šØænHÇÉ„ÊsЩ ýö‡å!iR?Ûs!1Yrû ¿ˆ‹uó·z[ÒN£\ég›ä|‚+3…s¯|?f¸/´ù£ª(Ï,@Ïz¡¹h:#’çXHìÎÁnÆ‚j¿á‚3VöŠ"e?¹Š:³ØÓÀùäoÅžnÖ_È!f±'Ùàç ^°ÊËmp#²ÚÓúQ%OgV{bý…üÜÍ,÷´Ÿ3ë=±¤è… »™U}ýýçw5ºÁŸã—ýÍYÖsesF¹§›ZñŽe¹§‰ýù]›!¨ŠkŽ¡3Ë=e± ~)fÔ{ÊwU¦.‚à Ê!sFÁ'TqEÕ«™õžX˜þDÇωWUΩ3 >í>3 >-Z jÞxUUPrfÅ'z`PŠ’Oì·³ãM¯R3J>8›\V›Yò‰u;rš:£äSSA[ts=xWï›c@¿o¼«ZöŠ'j„`¯>éúxcÜYò‰·táXãÂ˪¸ß™%Ÿb³N¶L¼¬**9³äSÞ/Ѝ3J>eY²Î¬ù´ÐîiÖ|º±W.oÍ,úÛ¼O&nO}by_Œ\Qõ‰Ý`¤È¢OýÓqïx_e1³èÓƒ3<üQô)ß×ü¤Ï¬øÄ»þ “Ùñ²Š ç#—Y®ˆÏ‘QÛaÆA‹Ü~äBX¥Í(õ´Ð#># ïäì ¦ÇØ¿«jü†ÍR^~zû…°ÎSž&úM [ä×Ï_piÚP6ïDöÀÇÈ%žnlÑ/*<ñ7ÁIF§ëG%V͘ºOì‚!!ê;ñÖa€št”í´'›Q݉f»øîNÊú´fÖéú2FžöÒ1B@æÝÆi{`M_XN”@ì¡êáySI_-uÍuàËÙÙ4céu`—TnfßáÒ0Ìgt_Eì’£Âû«àJsŠÊ§&¯4ŒºÄ´dÑ?VÑ{3ëîƒÄ¢}¬JiåãûÖÌ9ÙŒ Ä0ÌÅÕO­¸nd žë”„m®²ÿ5× %îšëâyÂä_\7~T`wL¼"»ã0 ì”yj°Ózv]£•ÉNs‡"»%é ìN²+°ÓçºÀNuº ì”G^`§”Œ»‹º»©ØƒÝTt«Á®øU`7U~Ü`7;<¦Œv(ˆh…Ñ@°d;C¯Ð.¸?Ñ.¶X´ ó\Ú7ÚMÅýí¦RŒv6¸éB»0¨ í²§C´›#¡wŒv"£ÝL~7ÚÕ±„vnV"ÚÍyòJ…vsrú´KÃ.D»i,"ÚM™Zí¼g'´‹ $Ù.øíf’í&«wí¦ZŒvSå!vSyF»û° É.†º”BMv“Ï»:’À.6; ì¦ Þ vS¦\»,ÝJŒ#ØD‚|+ ì"y|°‹«å‘ÀvÑo d;ø‰v•§%°Ë¨Uî°ÃUçI°C få;Ä…b€]žÌ…žvytLÇ vp›Á6»2ÌØ!¬ÇØå±0Èìj]†`‡*¼;ØåÁ°-ÉŽK;ºZûÖ•9¬°î^,’*ª+qRXW1Óº<7œ-±.-R'0XWǺÔò01 ÖU”¤°®„oa]I‹Âºo…uÙf®çÕ>ëJ&Ö•‰Œ°nßX—ë^„8`]U Ö• /¬+‘XX‡HõëÊJUX‡*ÝÙªƒê ÔÖá‡!è †œ³~°°®Bà…uÎ{Õ!zu§:äŒb'P]ùûê*KWTW1;¥ ì²ß¶ƒRDÁD»r#ØmÇ&ØÕð#°Ëż‰~¨fÕõ¼9»ì™{u.—2pD`·Ÿ À®V$vyå8Òäz©r5Åu™Ñð° ¦Ædr]åû’ë2M‡&×åS‚§\W¡áâ:©€Ðn.˜žŒ ×eϤ¸ÎSÅ­ˆëð˜àXƒ ¦$Ea]¦€óà“ë¥ZeÖU⸰.ò‰l­9Cä&èq½Tæ¢Âº¼¥‰u0…φ+¦¾(R]ý.„ºL‡Åéê*cVPCr4pÁÔhO¬CRý†u•AO¬Ã>@¦¬œ§:´äº¼¹–\‡{ †J®ËG$˜X‡ðqt‘X—‡ÀB$°.OüÄ.ªÌ« +±.RX—;àۮ˄ݓ wüÈ ¯…Í“ëb‡ø P—ÑFXdÔm? ÎÛ'Ñåéà7Ñåññ…Ñmψ.Ï€»t>’ø+–ÿ8`]Ï,€ hH ChÛtÈrŠ¿ÁsUj€<·ý”๼LÒZò\?&x.Õ|–×Å$)ü•8‡g@˜8— ˜€sÙÁ XKœ‹A1ÿô) É¦Å~¿db¹ãþ„´Ø“àoø¡™æfÏL—æÞ·R@%•N~“¥Ò)Q­T:…¹–J'Ã0§j÷†¹‡uC æT*Å07PÔ¡XîÝ`I”´!(”“gY±Ü0îY¤£ÅÀ&ÒòÄr&³Ü`ì\±Ü3ù \>öØIâ K£SoitŠX,.\·¾2Ý{ZóÃr±æéÒéd Y:Ët$ÄrvÊeæI¥[t:Ê¥NBÉP*Ýä’„P.U@-Q.õLí‰r(`´Ê¥š¹Š(—{õ]¥ËÅ|Â44×z@D9”UÆ^'û%Ýå`(ãå²ÏÚP.—”n0XçJ¢ât…r0·ÅNƒ+‰ON®$ÊSM,—¶z¸Èriž€G”,—F<–Ë:Bx’sY²Oa.[ð’æ²æš4—žÚ.Óe¥¨{§¹Ü‹Šh®jk‹æÒ¹¡ç•ÅP¡ä檼i.­Ïy6Rê0Iþç¦Ô--y[©“gA)u« Ö¤Ô--Û[©›ô;-¥NÆÈ¥ÔI ,¥N~I¥Ô-Ön)¥niaÚJ¬¯K©SD)uk£¹íß%Óet`t:»Q[§‹úó£Ó…µ"¾7Öé”]:Œ -Ô5¥Z¨k=ü,Ô5%•Z¨kÇ¥ uÖÄÖéš2­Ó5Ï¥ÓEjÖL¥Ó5OZ§‹–Ea–àøˆt6µ—H×öj‘në€"]³¼*‘®Yõ”H{Q0¤Hi ì‡"]SÔªE:;”Y¤kʶH×´*i•ÎåVéâVaž.•®ÉøÆ*]ø£¡ŠtÍè+‘®)È"]Sä°Dº¦€i‹tMõá‰syQ˜˜H§Ëâ@,êtÑB¾ƒL×XƒÉ*]\$t2ŠtydlB‘. ê´@¤k{%Ò5K²J~s u©tÑ3žN©tMZ«tÍŒ%•.^5L·¤Ò5¹#I¥kªôh•.¾«tÍ )•.v‚F‘®)ÌÞ"]ó¢”Dº<=ˆ}é“9­Ñ5ËÑÒèrlØY.¯"§4ºvžê˜]ø96©Ñ5¹%X£kòE·F—{ajt­ñ“h®ÉqØ]ìEí ]šþ̤ѩ¸5º¦@ukt-áéŸ%ÑÕ#*•.êäí’H'3!it±?jtͲ|jtMy!éb@;6˜Ë âR¤«çŽ"]l/EºhéP¤kòÎ’H×dO"‘®Éº"]SRTº&¨tqÚH •®Hªtí°Â•® ªtÍKT领Ź«tMµÑ¤Ò5Ù4H¥« K•®†ªtþ )ÒÅ/ð§HWEºx¾ð¡§H/,IŠt¦Òèò,AlÐèâ…&±A£Ë.€dÐèšR£k± F×äM ®n 5º¦¤Wkt‘Š‹rݺÔ)4ºúր몌5:-çÿ‰ËÙs+Nës7ãò æ,æX†gƒ9º°n0wIâÍÉ´Ô47•i˜»•D!˜»Ä{¦9w+œ»ù‰æh¥ô¡9Ħí4G.3Í™ï6šƒîQ4×`)šMšRæT…¢”9s®•¹ÚFÊœ\oJ™{åE)s‹ò•2÷Lñ’”9æn•4÷ŒÍMŠ^’å.`—,÷t c›,×~’å8Å(YÎQ®–åj/Ér^$(YN‘°%Ë1„¬d¹ù_¥ÊÅ¡€ORå¾¥Ê=œ—*÷0µˆªœì J•‹â{Àe4`MÀªœ/Àª\Gª\m#U®%Y®zVÄ¥ÊCVÄåiSÄ¥jTÄ¥><qy=Š‹TÄ¥— q©`«Š¸T½“Џ„ÈépKE[•*w± ŽU9­Š•*§˜#‡[ÆŒå£ÊÕº˜…9Yã–0'¹sêb‚’(ÌÅ6m縌Óýêr*”i]n9ÒÆºÜmü’.'WÃÒå"("$Ë©bhÉrï[9ʲ\W$'e¹¸Ï˜¨X–s؈d¹°žÝA.ãŠ? ·ï$eîÝf~¥¹‡Ø%Í=Ž”4÷Ð$¬¤¹çþ‚\V*Á⯥¹G‚”¥9eb—4÷ÐÛ°¤¹Ç:›¤9­ñ•4ç3„4dzRæTÌÊœ’RæTëµ”¹Gßx+s¾éVæT‰¨”¹Áœ¥Ì )enp6aaî¡…])s‰KÊœ!K™ÓeZ˜{˜[Âܸ¤ºI™È»-anÜŠ•”0§’jæ†&7梗OÄå ‡a sCübanЮ„¹1¬(an=$ÌÅ ½w˜C‘žæ²ò1~_ sZ‘*aîm¡x'eN%åK™›´ü-eN«V%Í)°¢¤9yT[š›Kš›ôº³47¹ÒZÒœ\Jš“¿xIsS ©¥¹I…ÊÊÜl¤X+s,”TÂÜdEžæâJ™›"+sïïpí0—w¿°•9ùf”2ç»ee.&05)sª_ÊÜü\n?§¥¹É¸¨Òæ|­Í½Ѿڜo Å¹9|³’ÚG›Ó-–4'»Js>5IsS•¹I^”0§H6+s°Lúg)s2ö³2§•R+sŒÜ±0'»u sª†eaNõ¥)ÌMêõÒå¦ÄCIs“Õ!,Í EÔKš‹ã£ÎÉÛÂêœ*WX›¿ÌRçÆPpdªsþI%ÏùNIž›§“òœ~©s2²:÷°Œ­å9ƒå9_ˆä9e’ç&cߥÎMº$PLB²<§€®’ç’dyNÞI–ç„P&¹‡öVè¥K tšR[ {X*ño¸–ÔahÞ„-›êBáG`• Î¥£ u®Ñj¨Ke‘Ñ•Š az„ Î~¦:ÍÆužÁêb&C)PçÂh¦ºÊeÕ­ÙÌy ù?è)$ªËô$c‘êªH‚¨.S1Æo™i!מH— ˜5“ê Díñ–Wþì‰tÏ/ªCä3޾óÿ°È™°Îe'Hu)={.]Ê:Çp™ Ð-ÒIJµH7ú/{¸e6_Κ¹Ë ;×¥ÿ÷’F'¤ÒèbnLEŽ´Òèâ :I£[Cn­ÑÍ¥,9it‹%J£[C{]¬,€´F§º¾ÖèÖPp%5ºM°%ºvXÆ£D×del‰.–b•[ǕĈÇûHtM†–èšœC-Ñ5ùÁ—Dç”D×d g‰.V^¡zK¢‹…3üT’èÚu*(“W©,Ñåz7¶¡D×”Í$‰Î•T-Ñ5=D×ç,‰.ŸO2]“§%ºZ”D×.̶DÛ{ÌeÔmÍ?©ÏÅ.l¡>×TœÍú\l³>ú\lÃCSŸkNm‘>¥gxÂÔ皬ñ­ÏEa\|Ú)Ñ5Ç“X¢sì†$: –D×i©Pó<$ѵ›>¦–èš\ÅK¢Sï’èbØþJtmIt]ËÕ–èºc@¥Ñ™4­ÑEJ4P¢ë´µ)‰.¬û@\’è µèœƒ`•®+3Q*ÝÃQ¶T:Ñ,•î½X,[¥{X¸T:Ù•J˜³A"‡ÝÒèžSÚš4:Vô,‰îù•D÷ð³ZÝ£kKtªñVÝcaOÝÛBÓ¬Ñ=‡Ž%NE ¬Ñ¥­Ñm-Ðè:ÝK£s¿ÖèôÁ)‘Nk¥Ò ÉvRéüKY¥‹Ë$êQ¥Žå”Jgu.]ãB\©t…;J¤S¸N‰tï¿à®[¤3*[¤¦K£óÄÐÝ£à]it2b+n°¨I‰t1€ ‰tÏ­HI‰tªù^"ª•J§UëRé<Ÿ¶J7Òg•nXÉ“J÷ <£éT·D:ÍJ¤„JktcR”·Fçc[£Ór¾5º8alB®¥5:?ÖèT ½DºaÉP"çK¥ó{&™.îßG¦ã ˆ*Ýóü¤Òþ“J§ {«tE¤Ò)ÕÄ*[¤Òyt•JÇØ3‹t~ ҩеEºIw8ŠtRU,Ò=Ї—Hçô2‰t2°H§•x‹tƒE‚,Òé‘‘F7o¥4:¯DA£{®o&]üðç ÒyAI"]Ì7öLºc$Òy ‰t*c•N?¨D:Ue¶H'wC‹tªÚI‘îaÞ—EºGQé”o)î¹% B£kÎe]óš§4:¯< í¼A®É¯ds#{‰ñù8̼Ӈ+AÜŽ6jÙ}Å~w·Úˆ›ükndíÈ)ì~·”ï—ÚÊi§ZÊù«áº|~úRËÞÚö¾Ô²õõN·>gÅ¿·~²eë…ÿG;‘Eõ¼Ààß2"ûCs±4"»ÿºÙÑþ¿‘ýêaYOPöÇ4éçÇ.Ÿ¨3׌¶­Ô“LÆÔQ™Œ¹mânjöRcìf·S?µ‘:Ú·RO¶SO›Å˜{òFîiÛJ=ÙbL=mcîɹ§m+õd‹1õ´YŒ¹'oäž¶­üËbŒ=ícõÞk#õô¯‘…ʋؿéCöü‘Ù¯ž¼ßö!û½Í~ö!û“î~~Ñ~Þìg²?;ìó'þU?ûý…Qû?À¿5Fÿã·ÞÍŸ†íßy7ÕÓßö!Ë ›×oÛ½7âÿ¨ÿýÏ6ýú3²CØÿóïç;Ëy‰þ?Ȇìù­ƒlÞdÿª Ùzz.™+)Ûø8™Fò6dÎ9UáõŒ¬ÿ3VGz' ¹BŽd9ýYÏÊú?áy:±ËÊ☛åÊÐG®Oy_­Ñ.ø‘Q²yŸœGL¥•¼ ¹DøÓ™Œ‰Ž+3@ £ [dÄk%¬­ˆí »nLnÄÚúÀ7—v •·Ò¶û‡“ÓVèL<Ë+ ]„7N g ÿ¿òœ¹„³Ò+ Ëô™ÑŽÈÄÈõÿÇöm‰[TKùѰÊ¢ÎÛrBp‘ÅÛrAÕêþÛrCsÑd?ZVž9W_Þ†Ù%:Z`«6}.²‹b¦¢e*àá6“‹»]×/›ÊþÎP”抈‡-3/@ò}Ìb¨3Œ«z[Î Àèñ·%kMæ±OµL‰èj¹¡»ãð[tÕÙòÒî‹-:üÄ߆X0€BÖØç¼$Ô \b–vÛ$Ùh™¼H-íˆÔR®ñlWIˆïŸ'eÑK7÷ÌhÊÎïŸuÑ©õ¼¡ŒŽ Ðy[:µQfF ÅQ.û¿-ÕQþÎQÔœbõƒ_$ªSÆùË!ZhïÆB¦oË¢ÿïõuœ’í–ZVžŸ’2Þ–¡TjÁÛ’UqQÊ Ç¾.ÎW÷hYy~‹‰BoËIîâ’îÛÒñâa<[žS×pp›/ïšÀÑ·Æq o÷û÷¼e|Å72Ê‚ä5ðTSY3¼tsÀ¡F••Þ–v«â@Çï¢é;¦]Üæ„IÍÁü¨·åÊië!»à&ØÔÈïmé˜îG) ½¯-[ëý[¥†,޽-V5,ëõ6°Þì>ÐD,ô·aÁ«æè-ú³¥=¼-­é zc BaåÕ÷¶Dh33Åpð¨5ÄòÜáø×t?£ÒÐåH>hQiháôø0F¥¡k¿¦žË=™Èv±Ûd×R ß– (H’#+ ÅÉðPQjèÁ½Y[rmôÆ:ÌûwH½è…oáCG(¹K¼-!õ~nMÔZŸ‹ŠZC´Ä/¥†x¨ÁBéÅý¼¶ \‚w ¥—Ú*ÏwÂÚM9,oKzC,7\AÓÝ¡èø6ä"B ö“-°‡zÏ…e†ò––:äòó¶„Ò‹Ókì™Qt²xbíGÚrìŒ:C¼‚×ôλqv|ÁF:¥äCÎkŒ*CixꙎ*C7ND‘¡‰nø,Nʼíѳ8ºp{xšÔyÏÒ(*f†ì6dÞe,ù¶Ð,Jµ³Þ–L›>€¬/t44#~x}3:TPám‰oÉrW|[äåñ!K®áîâ¾d=œ/¿i¥½ãì²"ÅÁ)æP'ȯȺxÕ¸s‘IMG¾é‹¯fÓÑ2ñŽzún«±Íí¥4|™â둾‚¬.t(¹àm @?¹ZÚZ–Š¿1浬þ‚{5ÕÂp`¸Å—×À%ÔÖÒ×ðp›ÞnÛ6÷Я€—=†']Ãä6ìݶ–7æÍG²0ýƒÇC‚]þdæÉuèhÁÇ4Œ£Ðk$2ðÁ:±WdÀåÙ-W5ÉÖÑ’å…zÔ‚Q,’ƹüU—1c¡wlk²Ä6­Ã Û†…ma632a[ Í$Ç%¶÷âsµÝØÞCh ¶é«cl‹8@±Mi†Æ6ç4¶)ئ,+c[dÕˆm*­bl;iókn‹ÛŒÓ"·©Ô¶¹M&·÷ì¾à&?‚›|1 nr½¹ž;¹M5‹Ü‚WÇŽnÙž'Et› ·¹ÅßçNná_†+'¹…Ù ”[4í&&¸Å_ ÐsỉÂnÑ€« ¸ÙÓ[à çn6Â]nÑÇ p›Êù¸Åõà7%¹9ID軌B7ç׈ޢáÜñ͹3Æ·©]ãÛŒEgn~›Šë5¿MÔËðÛT¯ù-TNLÈoñ¡è€³5.g¦p-.ÐxlÜT´¦.¶¹1J“à¶"œ—ŒpÑωcábR.s>—@J"ÁMA’à¦ÔVCÜþˆâº}òdqÛ­!ÅåÃKôÅm?)n»é¤¸íX¤8W%ÅM…tãâ¦sZ”7•þoŽËx&ü”ä¸í>ã¼ÈcŽ‹½È*丩 /sÜTì²9.~:77Ê\‹G¼yĸØâbÃÂ#Ò¢8{ã™â¦ÂÍLqSƒ¿)Nny†¸&yóqS憸íÙ#ÄM}DqŸCâìgˆ›’©Ìq±&öá¸ÜK´ÕèåÆÊ𿏩„Aq\:ê‰À’ãr/>Xาó3ÇÅÑ›Èna®í—ûðçÇå6:6@.¦œ¿ä²ò.gà 9œÙéÀ÷Rñ{"¹ÜëÚI.kpÑ$—¾vÇNri|U —ð¹Èåº!—¥r¹ ßB€\ZQ 4“ä\ÙRe¬6~@.;æÚbŽŠ|ÑBÛîùs° ]€\ÞO¾Ê¹ª¬,K+Á©|A×Òc Û~…äp6„0ÆìÖÒP.÷"2s ƒeDG/¤²G™˜ qB9˜’Á Ç«_Óu $€ry µ ö< >¨Kë 9œ ;îX •ñ…P.»á(W–ŠB¹ýÙÊá¹â> _ՌĈ O]uŽCƒ‚PN•B¹ýd&Ñ#Æ”Øu-ý÷NsxBÙO§+$W/'ƒÑUëL8‡c³†£³¨h«ìb7:FjAsû%çö“Îe?|/sÙqé΍ì>@s¹×ÿ€sU]8—ÛpJœÛ_àʘðHãòé±ebeôóìybe4’x +£^©Iœ+oNá\ÕÃÎå6ÜåÄâhc}Ñ\zfî0We÷s6¸MÇÚ¨dÁ\ž! 0—g³ˆ€rH½8‰JšËC/‰©˜GÓù’ææŠæÊ1L4—-">Jù1¸5¶`iÔ·S87Tпl3&œ›È‰-œ›ÊιU8ys[… i[P… ø@)\Ë8‘´ "✠µç"„õÇFs?½aNÉÈ¥ÁqU¯4¸Å?s!Êás/§Y®ó4Ëu.Zšå$˜åTîÖ,×ùE2Ëm ¼1¢\h8?Lr}PÒ#È¢r¾¹Î:˜r ì-’7‘Üà!rþr3Irt¿5Éù¢Er‹Ï&9Å5›ä”Rk’‹“¸‘äºø^$ç ÉÅ×f×à¶NIry$¹úw’œn¯@.6 \äúe,"Èõ¡)š@N§^ ×½Ü-ëÿrÛ6¹®Ålqœ~)q\¿$ˆˆã¶NÈqºKÅqÕ-1î}Äù†§4鸺¸îOŽ8®î8nÛ‹çƒãꊄqÛ¡‰qzš ãúÐg^·µãúõË—âêÖˆâªcQ\÷§W¿­(.JJ‘ÈN[d6R\]’(NÕŠâ¶mHq*UUWO‘(®~JQœ^£Â8¾»¢¸ºhQœï‹(®Ž,Š«û"Š«û"Š«;#ŠÛ¶!ÆÕU ãâI#CãT;¢0n;ŸñýÝ„qÝaœâ/ ã" EŒ«½„q$1\7„ˆád3X ÇoL!\ŸÂf!\Ý ܶ®:!ÁuM7LpªQW;à4ÒÀõb&\=18&Ze ®în{¦ApÝóXÜvM$¸:=œ? ¸mÈ#ÁÍŠX Áíµ.=â|ˆDp~‚àö p[ Îg'~뽈nè[ÿ|ù­wMèÅoÕ ñM–Æ·í„o[Ëü¬ƒŠÞô5-zëÕ1ÒÛûÕàb‘èÍç"zë·n¯è­Þ$Ñ[½¢7Ÿ‹è­_ÒÛv;EodÞ¶çEðÖÍ „·í.Þ|„·½aý4ÆÝ¶[%vS³Û6B‹Ýjü%»å½bKÿŽxd·ídž©çƒNtËÙá®ÄíÃ1Ùm»5d·8¾’d·º›D·úF’ܶ-ΩûËç.É-×ÞÉW÷¥yʗܶß^äÖ F9Ö’ÜB)`ôÉm{ÎHnÛ¯Br«'äæ+¸Õ"pså“[Løqê:õ©ºÙrß™€ÐÍs:£›” “[Š"·xáºZ†™ÎC;ßa‘[ !B·zm…n“[$¾N¶œ§ž¢®|HU©ÈM^Ùb%f`Cá¯ØhÇM`‹\·¯ÝÌ÷5¯)[Ú¼V[×T[̼v-áyMuÄÌk7WM+j’fí5)ÕOÄ.ã›ü&Óq›J°™Øn®ŸÙ, Ùn¬4²éfˆØn–n5±©x˜‰-NsWßUê[“˜õÍûK}«ªo,§Vê›ÏÐæ;#h»$ Új R[\9ú µÅQ)yì;ˆÚn4µYEµÝtû5µÝ _2µÝÌ 7µÜì“uñ¢¶Ú…Ô¦§ÝÔæÛj‹öèÉ)×vcÛí5|a›”Â6¹ö¶ÅÅP%#¶ÝŽÎ¶éT Ûnk¶­r›ÎXܦŸ¦¸M?FqÛÖ ¹m;‚[ ‚ŸÊyY¸]SQ7™û¸]VJn×4…Üß*pÛº%¸mÝ2ˆòv¬ ‚(ïöS¥äCFPnÄÊû(‚R+‚òvÄ!"(ë'Qe$ ’ë2„RæfCá¹Ü‡1”ª•X1”™V~¸´L¬Ê·EHÉJ¹¦UeXy| m? ¡¼'¤Ê{èN*‚RE“+‚²:"(UF¹"(UG²"(Yd¡(o+N  T‰À  |N•J”Û6ð“¶ øIÌ?y/$*„R©öf¶Šq&²-eÚWe—ÚDh‹YÚª$d ¨-¦Q|M@Ùµ€ j[ªzhj[ݱ{Ķ%ãúŠ ¬y±mmP n[²0·Å^ׇÛVោ·š6’ÛÖFeÞ<…·­Z‘ò¶•·B )o½:©¼õ.AGÒ›J@–ô¦5à’ÞjNªÊ:¤·w ¾í$·íØ$·¥•c£Ûvl¢[Fϳè–ýp/ ÛÞØ-Ά§GåMëÁF·UËWD·Uóùd·­ºåÔ\˜è¶=ÕD·Øæø(o«`è¶wCÓ'‰ä¶Ší‰nûNÞŠö‰n«ÈÂÛÆˆcé 8âJxëŽ%»mÛHy«›'å-¦h„!*oòœ0½-­Ç–ò¶ms9O)o}ê}†ò¶›Ê[/ýŽÊÌu³…Ê[¬Ýs/Jo½<RÖÙPz{ÏFq“”Þâ‡!!Qz«ž%½U?ÒÞêI‡öF1£¤·J²ôV—M€‹“áú¯¤·¸~ˆÒ[1©¤·§i¨“ôV§òö¿-³£•·nÂÛÆfTÞ6Ì¢òæÇÆÒ›ß'Ko~9,½J-½yÉÊÒ›×(,½iaƒÊÛsød¨¼)ÿx ¤Ôké­?ü Xzë%«Qz“ÀRÒ›t¤Š¤|_Ð믩oǯԷ;Õé æÎ)aN†LsÎN3͉6š[Ÿ8Âšæ ¤9WÜÍEeœk§9[‰‰æ–Õ3À\d7‚!æ–¢³sñì1 09+Ôã¢ûÍsà;¶XJÔŒÇAbûU4—Å¿\™4We¼“æ²> ¶?Ö/W£„¹ô»6˜ëéc´…R¦-N0ÿ/ìò  ;Á/»[Á\åso7ŽéÌõ&¥,—çz(ó Aüëâ:P.­ÑÚŽrYÃ…BÓc´©/P.]θK’\ZÅß»‡ª*{.\Ö“!~à<ËO^$—6g»—.gk¤Ìb7ÏI™¿öHÊ*‘’Ë^xAryèc¤D9±]ñÇp¨^åÒë_—4—ýHWLšË çN si§ÆÛ ˜Ë>+®¼ùsyh.Ržé‘å Š:ì0W‡s¹ÐÊì”Y˜F!š®2­ @sQÜÂU¦M+{«ã0 0<à+Ó.sO²\:¿)”± ]€"+“å²ê'ž`¹lqdåÂÉ9ñ0——$],ahöl8ôÌmÖp°ò5X£i) ¹Üâ“ —Gš;Íå6 ’DB\´Ü»·_'puu”"¯™s8t q­RA˜—µNv®Üý˜—EKø7ââcýì<¿=žßÄKxvÚ1#®É¡Ò)qñ¢qY†)qáLÃy$Sââü>:\Çë™ Èˆkª1ꌸt CÃÍk¤ŠÁ„¸¨Ç!RCB\nÃNgƒ@gÄ5}¸—ç‹$Ä…Ó0Q•W‰€¹|(œ"7±Ï¹Ã\v+¼Sõ•î4Â\ÔýÞ lsY.CB\XRgF\SÙYgÄÅ­àò3âZ­`1%.¶áƒÎ”¸¦2œL‰Ûn1Sââ7`¸Sâš,ú×.§Ö2'.k!râòŽr:=Éüß9qMIçΉ˂8Ô‘ç³v KoD~'2).þ^»‡G–Xˆ¤¸VëLгA¥³âb›cº¼ë\Nš´}ŠÙíteéĸ(~£½/O&Æ5-431n»JfÆ¥÷"e>dÆÅó»ÀÌ8;I:3®Åú·a•–ZCefÜöj25nÛ‹©qM‹íNÛž@¦ÆÅsËß!SãšDçÆ¹LsãÚíqæÆå ´KriZÉ焹q*ÃãÔ8f:5n»9L‹‡ Q­:øcž{,ey€:5.¾  ©qqÂsGºíF(5®n¨RãjœRj\ 'ý“ã!å5dÆ5ÕÐtj\Œ8™3?URÖ¹qñ(ßo-&L{Cj\|_DkHKÛRRßÉ/kãJªRãT¥È.AžslÆaï“>û׿:±Ì]ÎalÙ=À~¿ÚJÛü‹ÞaçÙÛÞ?ÿÞ<º²e3Æáß›Ï×–ÇóÓ‹Zö~ж÷¤–­¯«a9m»bµl}±mëË-ÿÑÞaïˆ 5ÿšwØüoéöK›ÇñKûº‡ýôèåCõŸ‡ñÕWyƒ±«Í?L=yu´{Œ¡ŸÝ }ÄØÓ¶»úúŒ±¯ÍŒ}íbê«¶R_§1öµùƒ±¯ÝEL}ÕVêëã5ƾ6‡0öµûˆ©¯ÚJ}}ÜÆô:—Gúú8‰yðVìë_qka±–ôÿÝJì­ÄþÊ8þ_È¿5jÿã7_ÖŸGòßyYÕ×ß¶k F'ÿ?÷ÛÆÖÿò_ÿ†‰Ø{§¿)Y–p(§&ñoKê6 mfí»\gÊ?OÄú´jŽÄú´®¤ŒX€U*8汜«ª<Þ–Ž`dˆû¨ê÷Ûò Ev@›lSñJk™•û#08g™ŠX²1˜‹QZ<¿¥ÈõÆ©+¯DË·EëNor"h6ê?áÂ×¥²uZ6ÏJchÁL·Å:73¤)¤ÂócKñmQ‘ƒYÖ¼¥Që)sÖX•'Z˜¾«^&V¶•Ú‚™¤œ½ž‡ò5a:Ófû`yÊ?3ì*2{ó ëœãœÚú¶ Xi*÷«^9½T6êp`5¯Ñh5Î÷¯ÑhÕÕÕh´ºõC£Õ“eÞ:­Jg¸ÚÇbòüè´ªPÑ‚ïê)'œ«ÑiµM÷K«U«@WT :?¿øI¯Õ:ã(Ô~”¿ïÛB¯Uë‰êÁ*Ü"þžz’.öËŠ°v½»NÚ­žráñJR=o'#…OV=1gnð_s#+þCy™ÿÉ‹Çü§"¡DÀPJ¸üLŒ•É&*ÌUšQs0`Œ–7[À€q lFÃE”ŽuF€»Ât"à°°/´!š0ê’@Wö«˜!àÐô^¸o¶:†Ñ× …€‡$&!`lÃÀ.!  =Œ€665²Ø[ -4H€µðP”© Ð F@íd”'x øÞhãàÁ$Cóßq™“ÿŠ3ÄáÊÉNÈ5•ÿm{‘ÿešÿ¶“!n{®ï±Ð1%@;¾·½ía´ˆ pÛ†Ÿ{‰ÉËö€Æ6û!:ÌD8 „H€{ 0Z" p³ Àm`¼ÑD`´5E€‡"{…€s5 àvÿˆ€S*&À­É,‡’¶€¹ ~_`l36ÜÏŽÉËu¯€± gIÀ©h óŸ-uÅÛÍ#ÿm—Mþ›¶ÐÿÍÁÛ %ÿMÙìÿÒXψðïDàŸÍÍÛȳ –ü7ý#þÛîùoë™ü·÷ss‹A”F ‰8eu,þÛ»e³]aÄûÀÓ5â¿í2ÅuÏÉû6à¿:Ä¿­[â_^±Ìu¯ˆÙBØcs ±’øg‡,áß´ù±ðo;f0× %ýí§Ã$fÛ¼ÿ¶n‰Ñr~ðo;=âßváÄ¿íØÄ¿©Z³Æ¿½ø·=¢Ä¿hY<à_ž1·as=&‰û51‹YfBÂ¿í¢ˆS%LÛ='þM¹‹þ¶gDôw éo;;âßö+ÿ¶;‘ø·H3ÜP3xEŒÞ®ˆáÂÞ„è·]â”ùªw"úm¿Ñ/ks áz>Éo{H~³ÂH~{·Lb>–©ŽI µTBòÛO˜i ¶ÃúmG'úÍZâ úmý$ûÕ!úÕ5’ü¶„ä—GV ¾§±Æ…+ ùm·“è·/Ñ/ßRnÃ$æ:8sBëù%ù•²ò«“ùÅÉ$-æ…nû01Ô7FäW?”ȯ.\ä·ïÅäÐFË&“ß~,¦‡úÂE~õ#€üâïù!¿}’ŸnÀoÚ^à· Áo»‚ßÖ çÆŽ·÷M¯žŠûêÁ÷Õ(îÛΗܷš ¢íÀŸÌÝÎŸÙ¡Õ ¡ozíTÐ7µ(+æÛî%™oû’ù¦mÅ|uˆ|õü ù¶›@äÓé“÷¶{"ÞÓø7ËŒ|áMòÍ ]šÊwòLƒê÷Žªóƒ|!ªjÁjk¡ì÷Κ¨Iös‚Ÿe¿Þ|lÊ~Û^”ýÊÿ@²Ÿ-û9)ѲŸÓ %ûùoË~ç—ù¶N$û©ìpÉ~QÀ™(¿ª¦.É~Õ1‘¯ŸŠÏò9ÓÈ×F¾í„ùœÝgæ ã/óõÂ!ùUi/CŸs }QùK}ÎÖ4õÑl­¨¯‹ÝÏ·[RŸÌÑŠú¶“!õuÃ$¡¯³†yAŸs }½Yp$ôù1ôÙÙÄÐ)Ž%è‹pÇ*³ ok‘cÕ¡5CA_?xgÄ|6È0óÅ“ÛȰJ‰·f>?Xf¾í¢–}ÃÙ˜ÏÒ5™Ï°™ÏNhf>=žF¾ºŸB¾^â!‘¯v"ñU‰¯+ÿÃÈçÇÞÈç\X#_u³Î}„0ñÕÏ&â«EÄ×—jä‹IÑdËÒéñyòɧ½¯.[Èç—ÛÈW¿Šo;Ÿ!GöBæëVkÅ|õè‰ùê©ó½Ûp#æ«»#æÛ¶‘i•ÏFÌç„ÌçLq3_Ýc1Ÿ>C_ýt‚>U„/èÛ¶!ôÕk(è«c úºÄ }¶ß1ôU? ¾ú¥D}õ‹úêNˆúü° úêÖúd‰c滵€gæÛv’m•†1_ýPb¾ø¡ÈTGÿÜ`1_=6b¾z@Å|õF‰ùê"Å|ñ “É|õ°‰ùêÄ|õzˆùêÄ|ïÓ27ÉÏf¦Å|õrújÈôÕ5úªA_ÝQ_—±¯©Ï•àL}õš‰újðõÕïê{¯[ìX­¼7â¾­E&­[Ëô€CQMæUçO¢ßvU"¿º;"¿º@¿:?¡Ÿ=Œ~¶N2úù)ùÕe‹ü¶ndÙª·CàW)_½v¿zU~5üœåoò‹×…°(û*Y;ýjHúÕó(ô«‹ú±4v‘ßv²¯òKµªÏoù£zIã;ößÖäçAÌäçó5ùyÈ2ùù‰0ùyè3ùmÛÈÌUϰÉÏψÉoÛk|¿«?] ~¾3¿®“Ÿ¿.&?O M~~L~1~~ð~(Œ~~Œ~ÛùÀhúoyºê±1úm½ÈÓU3"Ó_ÝtÑ_ýT¢??ZÆ?Ï(ŒÛ6×n\øç¡Îü§tò⿺⿺[BÀú„€‘ª‰ˆé?ô=Û°/Þ‡ú*õDÔw²¤¡ïýä8²ïE¤||¡okQ¬ç°@§XÏGê– ïÝKøFèsr¡ï\22ôzô9}ËÐw®_væ«NÄ|x*è{·¡6(èsa)1_GÌç"U¯é º‚?—®€V䂾ít}Ι4õÅé(ø“§Ç(XQßv¤>·˜úÜ‹©ï\?SŸ{6õù:M}NÌ2ö©Ü«°oû›Ø§¢²…}Û6Ä>ß sßv$rß© WsŸïº¹¯®\ܧ‡ØØWöí-óû7±Ï±±¯NFØW'#î«›.îÛ¶!÷ÕeŠûÞcñ#&îÛú!÷U?â>=£Ä¾mb_]”°Ï﹯~qßÖ¹¯NFàW— òsñ6“ßv,’ßv>$¿zN€~Û±‰~ՋЯžY¡_ЯÎFèWÇúm-·ßhžÐ¯®\èWg(ôÛ¶Iô;÷Kôs‘?£_Ķp›å²Úœ{ ý"©ÈFô;UËèwªî“ÑïR) £ßåÐl ŸU~‘8þE¿hù¢_Ü4+µU¿D¿·…À-ô»TE×èWÛýê|„~+™ü¶’üj‚ßõX!$øm»üj'‚_Ì¿¤íü"É“ Cù’ÿ~×°’Gðs‚³É¯î§È¯¶ù]ÊÚ7ùÅù’ÏH~oËý%¿kü¬öE¿¤1’Ÿ¯RàW?¥Ào;Á¯î„ÀooY:Ák¿w‹þ¿ºHßåøx_ÝߥÀ!ƒ_ýt?gRü.g)üêæüê~qÎ[´ç~$¹ù† ü¶k ømgLðsþ¿ÁO¶C~õ“ üö–©kh[´g9Oü¶-~uo~Nš1ù]SŠ™È¯î–ȯ~O¡_½òB¿:–Ð/Þ6Ew?ý@¿z…„~õ ýjÐú]úsø9'Ÿ‘û¶]È}ïE2ÔEàW?·ÀO¥" ü¶ ù¹g’Ÿ{1ùù±1ùmÛüüÓ™ül``òó«iòÛ¶!ùùüL~Û6$¿ìîŸøùé#ùm»ü¶-H~ÒU ü.ÕM7øùüªŸÆs_[Ü·íDîÛZÈ}ñÔ á©ÇÁÌ'Â0T2_Ýn1Ÿ3_m#æó{aæ«KóùL„|‘F/…ïóùâ?Ü‚ÈWÏ”ok!ò½{Ÿ(Ïz%|º™Ã)­ðL¾óߨ<>Ú£€/pÉ$U1ÿЬ<™• C$`l¹Y“ÉZ0â·¥ñuf%¸\•0ja~U¿%'à*|"–¡)pmÞá¬öB\BuE€Ábj†g×7Ôs½§0Ø0&xwˆ€ÉgŸPÏ¥ ¶Jöû¦gÇ?+×oÉ^]8l#ád¿Ãñ•Êö;ôýs¶ßiÀR¶_S Ì–í'äR¶ßé ReûÝ>²ý\Ù~·Vø€ñ9%î·LC  dV¶ßåøO`ì%$Äwjz†#œžRЧç<"@,“™®_8ýepº_W.pOd½Ñ/ýMùì˜þ¦¬¡M”6ýU*‹èo.GdªÞè¬ÈÎ[0ÀQø—¦.Ù@úÛÒ•êw:»ŽôWI™¢¿uhíVôg?¹ÊõÓ oú[‡[H‚A¢ŸþLî[M«â¾Õô}÷­S«Ìâ>Û–U–ŸÏUÜ÷>@ãË}ëÒ¼ZÜWwAÜ·.G‚’û¶rß»Zpߢçÿ–åçÌTqŸâÝ}o·ƒ€Dì« û\xÒØç1ÅØ÷nÙ™°ï݆)SLó;~JóÛ·èζåH}>_AŸë¢ú¶³#ôQýñ¹S'øù¶øÖm#ñ¹)‰ï} $¦ùœ`äsO#_Tõü2ßûÛ=Òö=D[}®¦kèÛÎF5F}¿}oKSÊß¿ÛÙz }ïÙXÜ;µ…€ŽÐ·šA‘ÐWЂ¾ºNAßv$Rß’¥»©Ï?ƒ oѯÝÌ—C –¾_@¾%kv#_$.3~’ȆJjòm-D>HÄ·ç呸–ìåM|KW&¾tD|õ‰øê¹ñ9wÄÄçʯ&¾÷l³"â{oÐR +Ë¿ÊÄ'h ð¹À­/(ŠðFàóoÞ«Û)Þ‹Ì4÷ìOiܳ¨qo놸·X"Ç´W×(ÚsÆŒi/†(Biïm_¡o=íÚüŒL¢½m Ò^¥ç‹ö<Ë4ð¹Ú²¯ÎXÀ÷n£pM_äý*}ëR|‚€o»*ßư¾EÓóž»5ïE69µ?òžÝÌ{¾Yæ½Uú yïÝëݱ^°rŽÌ{[?ä=§2ø¶K˜¼ó |~ |ïÙ<_©¯úñ¹ö¯‰/ΘXEâ{»ûf÷mW%äÛú!òmÛùd/Kä{7 )˜¨Ï•žM}Û6¤¾íôH}µ¨ïí‡A¼¢¾wŠ»¢¾ø.3ô“ØW?°o)ÂØ·TËÂØW…°O/¢©Ïe¦>?Ö¦>}lv;µ+³wSœÎ*e§Æ–Úïî·Ù©q›ÑNí>Wެu·löelÛ ‚ܲY¡Ýiâ½õ„¿÷~¢eïo}¤‡õø\±Z¶~ضõä–ÿp;µ;2òﯟÚïšµk†+ã﮽¼ãÊó+'§ß÷Hûõ3p­kn÷wäû<Åa)’“û*ÿ3vµùŸ©'o£Žv5ô³»Ÿ¡£û{Ú¶bW_'5öµ¹Ÿ±¯ÝýL}ÕVêëã¤Æ¾6÷3öµ»Ÿ©¯ÚJ}}œÔØ×æ~ƾv÷3õU[©¯“šÞÑr?C_4¿ÛÞŠ}ýKi×È´…ÿî‘ögiapþǯ†ÙߊÿñÛ/ëOÃóo¿¬¿îëï{¤ÝGÚ$ýÿÇ#í¿þÖAþë¿ê‘ö¾RMþtk}Ê[ ÅY*Zä}eñ!dÍÓ3`= ùï'ÿœÊ'†r-®€…9w™˜1¨¶àÛ°G/o § ,÷þ^X[6Ù¾£•fˆßƦÏ; CD±ùMßÇ…úC ÷û0­‡à|¹¶™ÞÞQu!\eÍ\wÔƒˆ±¹iuõ>FzTŸ.8s3q¯ƒ¹6wVkx7ñ‚Å}¬´–¼ÞY>æJw;Ò¢:jNÜáŒÿ^Â5ÅGwz+¿ÛØnú~Ñüý[5÷Þ¿s¬§)úÖ4ƽ=+{_¢´¨î6»¿[OgÜÛ–ÞwËU°kXh~[Ò·OŧÞ-WÁzw²ËÝfZT÷IÃâwV–óaõÝÙÍJêÇéŽ÷y üéý{qéPý¨”æ}žé8ÿ<ÒŸúñ{ŸWÎ?ïíŽÞg.„õ(‘‚ö>{Î?Sö¿÷™ a}„ý/ûyÒp> Äyƒ_4ÿ^*lpŸ3íæÇ}û|s!,·áÓˆYßÛ¢²t÷•+a= ¥€Ôî—>âÆÍë·ab“E»¯3í©Ãüb7WúÍdÌl¸Ó:^ÝG-i7?¦ïwŒˆ]&×îëI·ùñÎù¼æSø~‹x[Òp~¸,Ð}åJX,Uîk¥áüP•—÷µÉÕ°Få¼îûHÃù0NçƒuçjX¶ðM½Ï ¿‚,§î;×Ãú8åÒ÷¶ä­¹X÷«a=LÛùËÝÚ‡SàïûÉ·9nß౟´§¶þºï‘Žó× ï{¦=u,ãLîµ\½xÞ†´§ŽÓ×ÞýHÃù ™Ø©çrØ»“\#ßó;ðËq°é¹ö¶hYëîWÎS&ðwÏŰìE{e¼÷‡¹(rÜ=ÃzúγåIÃùqÈ«ìî¹öÞ@9¾- × —wæžoóèªüq÷•µ¿Kqï=qÆXC{ÿ^xL.®ßOKÃùuû9o\ÀC9è~Ò÷û=ð£ÑüÉÕ°|ÕIÖ(ì±pÆ[ƒÒH=ìöqnQ)k a I¹ ß•xóóìåw£:Ò»£È﨎tã­„†t£C #½Q!éýI£Óï8óOž:î Ï/Ÿ»¨’ÄGˆÃ+Ê$åSÏ÷ ê$Å{0‡·A¡¤§>Q)é¸Ǜ¥’ž!­øNË”ØF<™(úº )ËyŒå“ë7 &=¾³bRŸ «¹Y2éQeàv³fÒs+·ýΪëñÀÄ’I­íÒ84ºL<µäç´Û$*u¬p¶ÛæÍ²Iï¶•=¥­gÞ,U<8×X-ÿ~ô€³tR®û«%?§Ý.f7‹'u[úeyÏ-+‡7Ë'í{u|N»êËÜ, Ôß÷€ß0VPŠQ`q›Tˆ{Wy±hÉïi¼ó|ŽÞùaüÒ;‹(…\€¢©¿½< Áï,¢Ô­;ö#âœÜìU”ú­o!WÞž•yÕYF©G¥¥ -©¿-,ÜÕz–Qê.¿š¢:ZØ-Ê(õ°vå. Õo'Í'Œ2JqkØ-Ë(õ¦ ׬Ÿ4qCñsvÖQzŸ.Æð¥Ñ\‚cRX¨?'&®àâ7¬g¥ø»s‹TˆßN¤Ít–QŠÂ.'“ ñ{h}:Ë(ÅÉ,ž^*Ä=jÑè„QF©ÇCÇ~R!Î‹ÂØØYG)Þös¦BÜ»¢i; )½sT>¢= )õ®J@…”º ; )Ý•û‰éqwe¢ÎBJÝUfû™"ñÛóÔe²R>ú~ðáe ¢âò9ŒøÝ¡¹pèøe…ÂK(ˆÚ~ññe Àï°kžÀïpÍU_ÔˆãðLòËÊhDJ_³ È¯ªüšµ‘_„4ðC”äwvÏñH~±À>>äwÉE~W}bH~—o:ÁïÒ:²Áï*¨Ãs}Áe=[À}ñØ:~1ã>?à/‘"Áïv¶¿ÀïÞ ä«sœ-ýîâf¢_¨ìœÄýú!ÊãWJ&â¾ønñtÉ}ù%ÃÍKîëªÂhî{¢lȇûbˆâƒFîëÖ·Å}1éå­"÷=M¦±¿GqßSàBî{l*ð{\OWà÷8‡à÷xLø=\;~1¥å„‡à—3pà÷LIý?›~ ü› ü⌅Z¿˜Pò™&ø…âÏnÀ}Aß'Ùðšà|Þ+qß­Èq_ì#‚÷=–¦Å}3ÙÌ}& â¾@¾,ä¾ÇÓ_Ü@AÀ/¢ 8 ü✠"¿›‰y¿˜Góg øÅ,þþ€_\C#Pü‚UØ/À/Vx~?%Rü6¤øuýT¿C1†¿´~5ü\ÍÑà_"Ù/Fhâ"ÙïÝ”±Ø/ürɇ`¿x”Ö—ý®fì$ü¹jáïô3 ø«·Ìð'SÓ_X›³ðçbi¦¿"}Ñ_à ‹øçjZÆ¿¾Üñ/>v„=à_í³ãßé…'㟖HqMoHõ¤ Òß8<²‘þ†ÍhEÃÅE±WÆH±)Òßh·€›ø‹\âHü‹ÐÞâ_ôr–8”Ü"ü Ùª—(þ{<ßÿmdLþË™Dþ{7)þ{œu*þ‹A”ïKòßS‹žä¿xyä¿|VØ ø/øz~ø噳ø/&ú‹³kú‹UDNvDïøÃ-Òß3½ Cú‹ø'~T“þž%'(Ñ_ ²äÒ_Ü+² éïq„ŠèQSÿ,ø‹CMù}áoÉÛJð—_)Bäáï`/€¿¸Upp~tÑ_,i_‹þâÙØþbјàö«AVì©nÀ~ûg±_ ™ì÷<Ó»€ýjYì«+D ²_ª$A²þTQ:Ù/ηó À~±Íâ^`¿ÇuGÌ~‹ŸP¡ßS°Jö{†9)ÙïñR´Øïñ¬Uì¿Ó ×ýò`¿`¿Çãb¿xY.¶€ý⃹>ìO y›ì¿ o Ù/ŽÅ“ìW%² ö‹3&ë“ýJûÅs$ŠûåƒOŠûŲ—ìÛœö{f)ö‹Iˆò›úÙÈ}Ë ‹û¢¾éà6ëÄK)2¤´þv –øÅï„O¬È¯+Bûïø¤üåRò.!ø«¼²_ ÉLxIö« O±_ŒŠTô€~ëbF€Ðo½omˆ~϶$Â<~=2E¿Â°_ŽLüÀ~Y$^* 4¿çú…ÌFÉÏñGüÎsjNlÉOwYäw^ìkŽ%ö]ÝŠ•ô¾(z«–üB]µHì;ã+ìË # Ø÷Î¥ yünYòû.‡Ôûœ6+ìëªcoì‹¥Á"¿Çó#r_(uó(øÛÇÖ‚†,ß ~} ~&µà3½ûžCÆ`â¾X •$î‹ùu9)~†[)~5öÕÌ›äS‰ãC~óH¬ø…ȱ+~‡µ¥øù#&ò‹™Øø*~‘iBø"ù½'ÕÅyPüžYàÔTGtHô[ª(aôó¢–5?>ŽüjîsrJqŸOWÜç¤ ~›LHÁï4“û6p‘à7”|dÁï¦< ~o©°o°Äªå¾©¶”û¢&òGî ù¤±ï½‚&q/ßä°Nç+'¹/¡(Gû†ëçZî;ÌÑÄ>;^[îs™å¾Û¸+ê«øƒ¤¾êDjŸW\­öE!f¡o¡}Ëç+µï½yD1AŸÝ’ }áÚ¯–ü@¥==χÐ7”Ùoè‹Û(uÒí‡ùÒ÷Ë|^4óy9}×û8öùö~¨÷ÝÓš ™/òûØBækÖ–“ùâ’8ʉù¢@+ˆ|^/份™¯†F1_ #b¾[3]3ßûFß_æ;•6mæ{ßãË|Q›H—Ì×ü|Šùœ|fèËÐÚl óÝ ×6ó•Æ*æ[uÂd¾®ref¾Ë.æk2š0óy‚læ«¡$™/>®¬˜ùzµ€ùÞv~™¯ }?M}çOª_ôó|T¿Q(¤¾ü}ÈC ¾ák¢¾á ¨/]ò¨/™”J!¨/^)‘!¨oØoLÔ+ ¼aß©ìusß’9¹¸oÈØJØ·-ôûB`æ˜*ì[²ÂöeTY ØÜIÒjü¦žšg ûÞ»(:ö Ë‹â¾QZ ¹o”ªAî‹å¢‹ý€û¢Îý"²=76‘!¸/ZrЏÏÉWâ¾x n³¸ú²xÝ¿[ ¿0 !ü†“¥E~Õ7E~{ÏD?/Áý†í„~ñÐJ|¸žzKú­û'Ù/Ö‹Nnô‹é¢_ÜãƒÇ"úùÁúÅÑÇGö‹çäa Ù¯T4°Ÿ—3Ä~ñ•ïö¥«‘ýüúÅr‘Hè7´®#ôús2ˆFK6æ>'™‰ûâüÉ@ä>u’Ð7\ÊÏÐ÷žŽD8B_Ü-¶úJ¨#ô½Ï›DABßã,AŸ³µ }N 1õ•®.ÁϹ?¿HaK‚ßÒÒ¾Áo*ÏËàç*«~7Fø?sG+ØK_¡ öªîDÁžæ¦½±žù0Q—Ù0 òŒw”t§¢¦šš÷¢Ú·!ïY6ï] %qŒç©5IÅx¾ÏYH1ž·Ò~,õ=þ Kê †#ÎÝÌ|ç×RÀ÷xlWŒ§ëÜó)#Ò1žïñ°—ß§ÓåäƼ*1_3­ùbÎÞ>Až§Ó›,õ9µŠRŸ²ñ„|×!Kq+}­¹*}CEk|]–Žñ<§Y È÷NÈ´Lä $U?D¾˜ÌPg¤Öw«0µ¾óqdj}¡º»¨õ)PÈ×mXe©¯¾Ód¾H2á¢9™ï®XQ _3Á–ȱ)ö•¶ ±Ï ¢û Ä%öt¥õMÿ¶$¾Ð ¥þøzŸ ×𽯸&¾ˆl!ÙøºÒª,õÕ šÈ×½ ä»§>gB¾Ð3ù ùrU€½ù"|——-©Ïõ³Œ|l@"ò…Œû‰ñ|lj©ï’/€™Ï%û¬õ¹¬(µ¾ã0¬Qës CŸø$õ=­Ä?¬JF…ž ¥¾ÃVd¾î„\1_@:BßÖ"©ï’™„¡/fëŠé<0W¿QêËñ›”úJÑõ…ÇëGê‹8Î÷$õÙ{QÔ÷¼OÒüÄx>ªñ-è«ÅMAßcCDA_tÌ×;¡ï±èDè‹ç³} /ò½t€¾ç¹,ýú"¸‘„ƒåiÛGyÚ"ÇQž%â*гû*…|%Óù‚Pøi–ÐgmÀB_äK»(ôÕr‚„¾û±˜Bß¶…¾þü"å:ßÓ¬¬Qç{ÌÙÒù*j„Ä7çþ_| I›Túê òÅZáóA¾''"hñÍóæÂ95 }ïS#ÝŒB_E¤‰ø²o¡/f·Ÿ0ÏÇS(+}Z°ð¥´ÂCQè³öK¡ï‘%®…¾Èùÿ }wó¡)ôyñÐJ_WżRú, øÞ—ƒ¢€Ï“]K}Îp¶Ô7/ƒoœ¼ûó`Yë{Nƒ¤´¾K× à› µ/­OCµ€¯>@Öú’fàsT,y/­ER£ÖçÅ—â=-Š“÷æmP#ïyô¶ÖgÏk}BNޤÖw«Ú˜ï©XPj}C¥­õÕÓ&æ³òc­ošª­õRš¡õ½ï UØçr>ƾ[WƾZ1öIÒõ-•Kõ ‡’™ú™ˆ ø¨Zp•Ø÷~¨Jæ3F‘ù†…R1ŸS?Ì|“ÎlN¾½¸ÉßqGÛµ¾÷}´¾Ó(Gü;¹°húëªíDøk\.©ï4ØQë‹8|*ˆ„¿«‚C 1gã‘þúáÊ£¤¿wÈž/±¯ÙWb_{ß4~©ö5ðSî»*·,å¾øÍ†òùòÑŽŸõùzÞŽÔýÝÖæEÝED·ãåEóÏ3ýu0¢¿çl.Ð_w1 Ñßã"Ê ¿ø0IsþU€ðo›oÿ›y ÿâÕã:(ño¸¸µð/‚öØÀ‡; × ú‹)ŸEů@HŠ_wb%¿ZFÞRüD£¿êE’ßÒt‹ôS'þ Êñ{wâ ů”Xçø9_“ø·‰‹ãÆÇb~è/–Øoµ@ð«øKâ_­¯:Åï”;W¥øY½±àG²c‚_Ôn 2Á/¬“¾~yK‚_÷SŽ ¿Xºü)ïIa±à'Êðó[(Áox FžÝù1ÎðΩ£à·œ&ÁÏ®_Îð{OB²è/FaZÐß,°ä·ÅÉ ¿YTIÉï”·œð/Kɱàß|Oa}2ü²®ìWò«§†ø-ŠÑþ…’Òì˜âWWÍÏ¥×…UbQø7ã óý† y„ÓËÁýìé"ü‹èy%Rô« ¢"=4S¢Ÿ'êýbÞE¿î»®HÏåjSýÅIÕÏ¡6Vý*YXKKÀÛH<§·‘êwI!g¤§sNéib¥êçè›Rý"á4?9Zõ+Éç÷#=]x»T?…zU¤g$U¿ëvz`çÒI€ÎαêWa±õt(ƒC=‡ôc`ýTõt\¾d¿æ¥£ß—ý }êÙ”ú—ª_žp©þ¹U¿ºŽôTj‰U¿V‰€‰úUýÎÓ˜HÕï°”.\*Uª_1U¿Ê)†êwhZYªŸg!›ê'¾£êƒ{¡ê×4+ª`O•ͬhOIõCMLk~­’ø¨ùÅp#$ÄWµ2'A€®ÖiœÊ­PO±zàt& ðŽÉT¬§F+Ö³»çÛ4ßPÏm“‡O„òI€¥ ˆ•èïçýõ´Q© °BM€ÝÌÅ`Ï¥eà"Àf±NÁžÏ7Ño“b€Keá €«îmNX¨ÄS £8ìÓq4ÿ¶†©hÕöå?Û˜ÿ–j7šÿüéÿQ:p¨çRa¥ õ”¯×ŽM…zΟõ¾µÜÏpþÄü)Ôó1X*ÔS¶ÐÆ¿ålPãŸø×*aø7—‰KªŸ<Œöö4þ-•»­PÏ[r©T¿ø1¸ùÏ)À1}t ‚kvÕoL€]æKõ»• H´£Án•v¬zÏ6èΙ.žï SË?Ý „!øÿƒýj+m³ï÷7¬Ò~u„jy/?ߣüêÿçÖ,¨zÖ;ßúrËÖÛ¶¾ÜR}¥ôú\¹[ª/µU_Õ²õBËøôå–­/¶m}¹¥úú²_ËÌœ÷øñ‰}–²±ŠÙåmW¨«|Ôð¿iK~5›Zýjƒ}Û°Ž}ƾíïö ?¢»üÙ~ýX´ðBØž×üêާóIƒÄ}+wµzŠüÕ>]y#wµm¥®ÒŽq]Õ•ö®j#uµo宂¢ž­'üýéH›¸ŸÚÆÝô•‰žÕ>y#÷´må®fË­«+6|ºòFîjÛj{9S‹uWjØ»ªÔÕ¾Õ_}¢Óïõð…÷öË-?³Ý»1›¬Ï~~†½áo³ýÞf?³ýIw÷Ÿlö³1ÛŸöùÃ÷è7ŒÙþ§à·Ü_üÿøƒÁ{ßê·^Ó_÷õ?tÈûSÇÏüŸâ÷Ž\‹ü­cÖ÷NÊó·þŸþ=’îÎûù·ÿñßc™ühýßþç¬Å°?û_ü¯ÿë;0Ŭy>ÿöúßÿá½u‘ýoÿÛ¿ÿ§€¼÷ÿþ/ïüÿ{Ìë_˜ù·ÿünY¬£ûÿ}C¹X° ;ò8öû¥øÊ]e(w¥¡Üó§^rïvá ^oÏÞøwä®ïa¶g*{ý¯õw™ÇÝÁ<îXEyÆ’ÖÐ0p检ßÖÒèã ôs´ðŠ-×ǪOTÎ[(>oCÈGè%­çm™LÎl=sòÎX©Àü½õ”>ßYæ©¢…O挞³iÂÞÄ{ÎËÕ1fZ¤÷4p§Í2ÏùTÁû\Ï>=áØ ¸4–v†ÒÎMUúÊÄxg ¿Ä&+Åö\PJ£fvœ .Wð«¤ø4ãlÞùéûJ½-Íž¾¹b \…kÓ.ù:žª™šqR×Öø4hNüŠRXâo™¡z…Ù¦Œ€syð cý—+—“®<¼ï'.¨åвl¹³XÊÕ.åó\=s®®(DÁµÈŠÏó£°ÛëÉÀ©+‚µp~í}±(ŒŒ¤È-|oÅO8s”Š®¸Ó‡r”ò›—–ÆJú‰“¸ò>ruüŒ;pèp½üÌj$Wr­G¬ \ñþ,ÅáįxÓk±ï¿·éJ­$Æ{ÅÂô­Ð¸ÿWŒ\ñ{ÒÖáŠb®-Ž,£ý¾³[oL>®«+.lÌ@îǶCwœ| Æéôûºâ>°ã!¿âFÊb&¸èmh–íîx_¯¸‘"¥À¢·á6¶eÐëŽ(ôrçRîU!e=£¯X &þ=C|Ý—ìëú“!áï#%ûµ°z_Øw/Ù+Eäùn(ä^$í_÷mr_qƒ–|rž#ç Ù‚ç- ÞöíGI)ÌÜѢ̓ˆíX±Í£r¶jØ]톩ˆöX8œàƒBËÙ‚W88/Î&²-òÑI/ÃÜdð· 9^Øøéñ ?ð4Éóág®jçï€aòiûKãx–bÅ+Þ׌šËm2_£FúX^Í×* >å÷uPeÈ‚Où fÁµ¨÷¯kž`Ž]Yñ)„Ô§3„é3¶x¨hf½§œ±>L+9‘Ÿ×3tõ‰mf~^8/iåçõmሓõžzÜ®ÐçâÅËzO+n—^à¬÷tŸ8²ÞÓŒ\\€zOñP+…h¸òózÆ:2îh»sQ0wÊõí¬øôÄ­X i|[òóúêÒÁŸø¾æí;ÑñÈÑ;Ïxb§ß×,FÁ“™ì=/õ»òûz†ÁRþQñif¿œ,Eŧx]ón=lÉ×+[²ßÈq=nnhÔ|zâfu&Aœç_×ìøFCFpæ%-ìϤ3‚ÄoœÍ“×Ü M`çâ6 g3V†ÂfÕ§˜ GÅ\ùuÍú<ýóñ‹_1cŽ.®gå§§ãªrü;#¸áØí—…Ÿb6¼.Æ‘ž1 8Ž”ßÉ,ütçÝâG' ?­Ü†©bYøéØ Ï~~Ê×µS ‹ÂOx]/bgé§‘Û0›çmYx]û¡S^^×µþýn¼­7K.fé§|[oz^dé'̆>Ø0žoëMÏ‹,ý›\4mŽÊOx[/æ§dí§‰†ü¥rÀÏ-˜*˜¥Ÿòm½iDò>o+Ú¬ý”oëÅêÌgwäÛz3Ç4Ë?åÛz3(&ë?åÛz ­ºoë eäd˜9~¼*¦øBÁèg|Ppvº`çs“I‚ÑÍZ$ Æ‹ë FQÌNîÃÇ5Nì ¬g‰$G:l$Á©õx‘`lr ñu ±âø`ì”—I0§óC‚Ûô Î`C´£å˜’#n?°HpÛ‹$89{7æÍ Έ°F‘3n—-øºF7¸É"ÁawÌr¾®ñHâA! f9v›(8{øç}ò †"4?(XϺPpë‡(8½Œ$¬ Æ^¸r±`}‚É‚#Œ@,˜åRÁh„Á¨v?± a0Z°ª%œ^~" n›#2+,¤Áø®­ Ϋ+@å¯[Ì?Áù*t* œÁÔ?Šã6bÁS<?f¸Ö¼'N­£›Å~³ºòN¬ÆÂ=:–:xþñ›¥»X@x«V†P·±€PË!„·âÆ „· „½Jj »JTó›u»°;y0¾ÈhÞÊëÞÓe‚ùͲFk ¼™Gk¼eÁe¼UuK<è³ÆoI–"ÆíÆ£5Àˆƒ10ˆ88¯)ˆ$F ­)ˆƒSË,ÆÁlôLŒg³â`lB1“8èÇ[88µTdœ û' ƇÌðÁºn›¿ñƒuU9*~°j/²àô4U,8½à.œZë2 Nëc¢ÁØëØ…AôÌ~±®îª+übÕ^ÄÁÚK88/¦’ãthZ  1]¡ü`yÐ`þlà÷Ê[ëW ÆE2¢’4¿?íoHƒñÅ 1’£cFP’ÃФS Æ Óæ‡4GGÎh°n–hpr-Î0èk æƒõcCÁzÒˆ‚󤫱H°~[’`œ-¹”$$‚U¡àÛòcãÀ™õÄ7 œV‰…‘W‚"ƉˆE³(‹8Ïñ•³c¼Ù¢ÀØ?‰(0ú9>Ç ' œ§J÷ˆg“-"1p:NAQX/ Æ&k×Q„œÐ °£”& Œ²böˆy(´3"0°ieQ˜ëh!Æ^ø¡„±×AèF‚¥Fb`´àÑFϸÆÀ&·(q`ãAö7ÊÉ3:þBx(þØx(ƒHx¨d90Ò¢~ìØäÀc<˜“l ¬^„þâ®ïš…Ì›åL›Ól& >Bàˆ5И=ãèÄ¿h!j’ÿê§ÿÅ ýÁ¿ØäLÿâtðà ÿb¬ßÿ†BŽŒÙÁø©Šè„ô7´Bkú‹sa·¤¿¡µ_ÓßPðšé/,´þâºç‡þêNˆþâüŽýE?ó£FT#kÑ_fî¡gÒßXþHÑóÀ^¤¿º Ò_l‚UÑßXÎýef'ÎOq½‹æDæ3gâ{ÖÔç^é¶&>#„|M~QF>¯„|ǘ ùªEÈw(KÍÈ _äkÄöB¾ÖþÉïSSN—‘ïígþ¤œ”¨”C#ÇØ">?M|M [&¾CgF¾˜}ÿ؈ï)°‰ïPü ˆïk§‰ï:eâ«„|‡lÂKtŒ¦oÉmØÌ÷ŒŸ4À)½Ç̧·¥˜o*XË`£F)€*IX  "ï¬6Å~Jlª¡)°)õÒ`ä¤ÓÆ`³Íõ?ÏSü‹<ѯø×†¥>ŠaÏI;€a=A¹ýÿÎC*Ä¿÷ȪéCñïtµ©ž~Zþ;]£Xú_Sîõ?fKü³pañïtu?‰m)“ÚŸ–0-þµ¥ÒÔþNO¤ö×”,ní/òq‰ÍI$þÅ~l´—?6‘öw¨\¶µ¿¦|^kMõR¬ý5ºÃYúkJ ´ô×TÆÒ_;'*éok¡ô×Î)é¯)UÒ_m"éOsBKM©—–þüj[ûóaíÏs{k‡Ò­ýVè¤ýʵöwhÇÔ·´òfêÓÌ·´¿ƒ†¾¥Cß’-‘¡/&x_èÓÇÜÐWGô­ùô-¹2ú­Ì|KKTf>:˜ù–|²Ì|Kq¢B>…ÿòYÔ6ò yù¬¬ùæ²Hä[‡4E!ßÔ‘/rÃѳoj© ¤¿ƒÜ%â‹òAÀ9_(á1+¯ÁÊßEðI¸*âÊ"0ñE¢6¶ò Ïù½ÊL|!é|B@§Â ù†ªÁùž¡@M!ŸÅ-+㔎fåƒR1_Tz‰ùÞ}°—”¿&QÊßÓÅk„¾qchÞ”?ÖÊÛ”?*õ›òçó³òw¨+Ì,ì{–DæFöu–ÞØ”?~§6éô’þN£,ý=LäÞ¤?ÝÀMú#„Zú»xá¥ý©_kîZ%ýY#³ô÷pžµI¬w°Iy¢¤?| Jù‹PœÿüIøcÄ'±Oé1…} ¥üE½st,å¯s\-å/ ¶p!Õ"£”¿¾ÄcRþº"¥üu–ý(寞”?Å mÊŸ¢VKùc©Š?Tþh\ÿQþ ©•?im¥üqA¦”?+vRþ|+¬üuZ¤nÊm+?ÊžÚMùCÄq)MÁ¥Rþh/YÊ_XÖ¡_)uÝ•¿öa¿RÚ¬üI<ù*@+)Ê'*åOc›ò'N·òwk=ÅÊŸ/ËÊŸm­üùœ­üIG²ò×9}Ú”¿Å7ÄÊŸhßÊßI¦¿c8WضŒìsm+/ÅáÂÿcÃ@Ç9 cŽ‚ï10üåŽO(¨pz4Ø‚oVZ¬ …¸…g WX¬Bv^Gm ¼ÂŠŽ¨À@äËíÊßuhE˜im M¼ŽSQjäÀ+>)cçÀëøIù»xÁWجü”8åߦ´À!÷G§:âÕic‡À+¬êÚúnÀŸsã¤hæœ@…PRà v2†gRàá ]%rþæœ@…AWN “3xªÀ¡s=spN`LM¶8Ð+\Vð«()02mnê|H t˜–’›¢:œØ´†â¤Àx äcޤÀffVR`{ìÅΤÀ¶Ê¦ IáÐwÜ%†…Š®")ð0ò()0ªTÓÄI1/ZrÕÍ$£Ã…¶•x •xœÇbÁë°¶Ê”Àã”cºRÓ†¥H ŒTÿK.—È1:mFÊ”ÀÃï³R#o•n®L ŒIÛµÓàÅé`ÑྠSKY´J Œ[sRã|ÖŽƒÙB5)‡Y_)•G«”ÀÃr¯Rã¦ïò_60)1˜<Œ Í”ÀØ›RãÿÙ{“ßq$ºóUî²½)ˆ¤$RÏQÏ`xá2à…ß­ˆ3uófåУ x•ùñRÔð×ÀOĉ{×ÿFL{~"%ðЊ»sç‡)'ð0´‰Ÿ©B玂y…ÑÀtÀh`¦”_*T‹Žu¾§c@à }º”Ī Щš>Ò4µÙq> Zªpè­»^Ù€9oþ¤†s'3™¯:Ü J`<¼ä<²`….‹+ÞY,ÑÖç‡Yð)ÐS>à”‘™óã’|`0úPT>àÛ‡á›Êô„Øù€wã|®ò¹JTù€çã Oævf¸;ðš úT>`g,µóU \œ¬„ÀÔê+pÒÚ³²Ç# U6`x9~b@ã‚]+ðTÒž².æl@C:ð¢G¥zôW:àŲŕ¨d¥:†Lé€Q;úƒ‚‘öÀ3ð=\r§úGp: r¨+°2çZeX0ÊÒù€" JTv‹pTB`Tü±±`„™C…©„@FhWB §*!°)÷P Š«„Àã¡Rã„ÀqIÈTB ^ N|g|냱î%žRºœè(F'1 0T .•8–[¸Ò:…“*!Ðb•ø(EP Š ª„@'Ï9!pÜâ&ejYã’2È•ÖÁ´¤JTŽ›òÃÆðÂbo*ðT ¨e Q 8šèU ] 5NŒ¨ùE ùäǵO ƒÌ±P Ò–x(tÔ 7<'vV@eUF`ÓJ—3%:8%°Ÿ?æ';gJ "„*%Pi›ñÜ;­?¾Þ?éŠzµÍmH-»ÜïoW½ÔçïÏývÕR¦l?ïãl-eÊ6èY¸å–m,¶mc¹¥ÆJ›íësæn©±ÔVcUË6V–ùŒå–m,¶mc¹å?m<7‚!âÿ=ã¹óWÆsíúé6ž{[¯ßë /£n/£_Ýç…x“²Çúù&ŽÛ3ààÓÉCÙSÎCmžrʽ4ÔÖIC•§œ†Ú=å4TõâP{'%W9T®rH}4Nuñ0ö”ó8›§œr/´uòPö”óP›§œ‡r/ µuÚNzÊi¨ÝS®^%êÅ¡þŽñÜq>¾ôÿ×xîßÏý™OÁ¯^¸¿}ñÿóß¼¼÷^¿zJ;Ö_6p¹Œ0ÿeàö¾Ìö¡ÿg5Ǩÿxihý?«ËÅ­ÿ±‹Û{iá8Óôég*?"´qýˆÀ{)ãÂÇù>w³¨ðÛ²7›>àñž¾‘s¡ÏŒÀ;¬ïÌõ€ó>g'öõdzg_ò…J³,Ä´Óïâ=ÉN-fBñ|Ï4ÕÅÔ3oôéZÌC-æ½x£¸>öÞÑ l9ýεƒ·Ëé÷ Eöm˜Ìq>t8÷•¸õŸl˜ùiÆê×Ì–uî/m‚e#Š‹Üèr³^ÇydÑÐ4ZKP~[²Êæ8b!:79ÛÄ¢–ÖáÕ±\‹†‘¡®ïÕ™X‹z[¬?Ÿ¬âðb@J\#Ñ-/TJ]éDÄ\¹åcM+V¸qyÏ;3Lr?n86­ngy¥!Ãè.ÇîÏ?ò7^øIPQø×û:Ân{D½Ë akß"j+ÂGŒÌrú¶¤R–îg[!î„e3~‚ëLƒ—¼’K¨#*ƺÖÊcàîNá‘ïÏÒ¦,±üýù³€Gþb¸^Q㱇V¬b_+cÒç-¿Ã#j¾¦ÑÕÁ%¨õ½®ðÂꔯÇ0´÷7¢ùúÛ²ÒéêDhä¸û£+™ë;K¤Âb+&+þ]°ØÂ~Ο«È‹Ç¨×Ÿ+iô#¼©Óçj:º™‚êûÑ f„£u,lžLìje¡ƒ÷x±b?ÂWüHã0®†°Æu­ ˜\Ñ!æé¿‡Û$JŒìÃøý‘UË­¶3÷ed å- [,R8¢bÞa4;?Ouf8–ØFße¯‰h‚÷gæ:à˜±Zv‰ûF¼ªâI½üª™+W[óî¹±cÄßæ†§#"´ãaÍ{.‡IK<¬±#ü õXÞ}˜™ÐÖâiµùÞX(±0Ó’ÏFd`ÅÓzÔG&ðOË•Ö7#J‡ÜØêÎtä‹ð}f¦+ä™.óL~ÏóÂK(cNbÚæ…‚·ï-pä´p„÷Çݸ8±´k”9°±ëÅ忬™žtJQÍrT9il¬•žå¨âY½ûÎrTù¬ÖÓÍzTñ¬^²v¹Ò×ñ¸äº–¤JOº›Ë#ÖóY•ßW–¤º£O´/Ø÷¿ï…¥­ž,û¾5W}Ç kæ‹%,³$U¼É‚ðG6 x͈R@yѯb›²BÃÈëè2\ʉJºH.Æ÷fIªt‘Œ4lu-F‹rm–¤º³3™Îcæ‡5]߸ó•ÖÑs¤Þ–ü°¦0–,IuFŸ“Y’*]é¤TgIªx\CÂ]èÓòÿRiìhéÖ¡'Ó²(U<®©$bœ4@Š/FÔ¤JÍHFg»ða|‹ŠyKö|¿ñaUþs¤Ê«\#² U~XÃ/íÉ–‡ßVéßYjQÔİýà·u"A++Rå§5"¼rW½ãÛzÜ[ðm=nÞÇgGÑŒE*ò}%©®Cλ6KR= ]ø´F Ýø´‘^œçÐ'>­1̃–Õ îêŠÇ·'õ"eÎgM*žfø´ :È’T)Î xX¾R¯ÌªTWÃk×Y•*׸ƸE£*UJFÒE²*ÕJ_X®àFUª|\ E-²,Õ\p<1ÌÄ—õx߸³¢,U<­qqú,|YCuÇÑ<ø°±›]ÎÖƒy§Y”êâF†kÝ7áBzBpÍåå,Iµ²Ë·s”¤‚d¤ôË,J•’ÑI½ÿ Ï”Œ¸†™5©î¢Íƒ†Ei—rB–¤ºRѤ–qž+ßqï¼h O¾ ýra+TÊ=ቒTñ¤Š5È’Tù¤*/JRáI=©ÕgQª|R%¼§–éôˆóä—åmAåê3 IãjáW‰’Tù¤*uî¼nãÅõ¨ íÒ®1ëQ哊_:ŠQåczÐ ,‹QåcÚᵨð”6V°ÍjT“&@8»åG•êf–¢º;ôZܼQ7ŸQ-“f)ª|F;Ãô²Õ³‚0JQåC*¥-KQ­”3uµ£øå8¡½âщbTÔãsšzFq‘Î ‰Qžü¢n›<ø¢Æç%ù\º ê‹'=Ê庳’³jI)4Öµ­Ø¦mÅ~òÆ+ö{ŸÌ×Ì~ í*ö‹H³ü›ýäÒVìÇxD£_Ö²ÂÀD¿©·šÑ/LÚ0ŒÐOùCE~Óÿ‹ü¤öšü2}H~K>Â"¿HÉʼn‹ü–´’"ãr¢@òË@QL9ƒüÊCFä—Æ.<#_Æ-ß;üe Ø…ð—¡OÀ ðW©‚¿ˆòÇs+úKÕû"ýU ¿è/B$è/UŒfý¥Dv’ó•[a`À_rsCÀ_*v˜–þR}Ŭ”ð—n\¸X€¿|;À~òúÕ­.ôË€€Ž>@?Ø”ë€~iT†©"Ñ/îúÅK·}Ð/ƒOÐè—¡`¡_<Ñ@e¡ê‘näwÈAÑä—ojP\ÓJ¿&É/^¸)„~‡<¡ß!‹O£_¼Rñ#ˆý)zf¿C‹f¿c°V ÙÏßX³_ÌlNb¿C¢­áÏQk†¿cŠqqˆ[„¿ø4ß@=Â_Ì«0ÌÐ'êàÅûÅÌ76Ù/‚.pb¿Cæ4b¿ƒNzF¿CÆ=@¿CB‰Ñ/‡ø _Ì ŽúÅVg¡_\*¬_ ýEkýù®ý¹ ýÅ›ý"Úà$ òCuÒ:Ùèïù ßá,¡_Ü×x? ýŽÑ…«@¿˜y/lôÔ‡ ]È~G4üó¤À/k …äwtVÖ4ùå<DIò;”ó$ò+‡>‘_¶ I~1Cé‡äwذïÝDK+¾ŒXÂŽ€}ùÑ$ÍûN%ìË>7ð,±ïm¸8Ë&öåú ˆ Ø—oŸ¸ìKCÁœöU “°/Ãiˆ†À¾œ``ZBìËè[û`Œ}ûòÌó¢ ûÒÕs1b_†Óôû26k§>8g÷E}9Õ„žÔ—okL^H}aNùÃÈ—fÑãäZ*ßï$¾ŒôÁ”Bß’À—6†Ç|i#àƒWðUl€/ϰރƒ÷|0ÚÌa|P„«MàËÀ Lž |y8#ŸüœÆ¬ ˜àK[r\m_ŽŒÉ<‰/C§0Q'ñe¢äÂ÷4jıßS%-ø2°9¿"¾œàn ñÁ4ûGlÉAXTE ørO(yòƒ* 1_Æ¿ç |0ÖþQÀ—S8K_Fõï|å›*àƒ8ÀÄ·íœÄ—W×È—Ã\à. _Wù*IOÈWA=B>ø~c _öÁñù²ÇGæËéžeB_ögúòZ´/ô“új"&èËŸ¦ß}ˆyÊŸ†ÐWái‚¾í }ø%° ¯b°}ŽƒgÔ—Ãä”IÔ—Ã`9—“?}Ÿ–‡1G]‡ îC8v îË qìà‹Qp“ÀOæC~¾kÉ~yGâ1#ûå87Hì—{ç8b?-ýò©ÇKHèÉ <úU`Ñ/7b ÐóÌÁ~ðG°6Ê=þ*V®àONå± ÿ“6ó_Þð/l|žþ-®·˜þi.¶àKé†äAÒ_X{fh”é/ ¥1°òÿ…^Hü kT,èZù‹y×þb6‚µZãßCÛ±Mø£û[ ^Ÿ·ðçù¢„¿1…nþî!t£ð'7¸þä^Fá/¢=?Â_‹¬uì˜Â_󊹵¿ˆ‹† 'íÏéÒþ¸°hí¯¬QâßõµÒþT(ª´?YY—öçI¯µ?HZú;¼¨.é¯y†+é¯éã$é¯Íƒ7€¤¿¦ ’þšïIÍ×OÒ_—s¥¿¶ºÄ@JEŠ»OÒ_“Å´¥¿‡}Èý`n‰ù¯7 ¥¿.¿ ó_o45ÿµÙµÀXœ¿?zñÄ{Q²e!…FIÀ®"7ÀÞ‡D;`Wê™°#ßjÀn˜Æ8X€]‰yÀÞ™³kìò5FÔ-n/`f+±Ø¥ `×äÌØµôjŒ}ïH€]"À,< ¾#vÅ®Š»Â¿€]þô@À¸ÂXñFjK˜åÃ0*0æ”Ô舀]v_FÀ¸%×]˜ÌØ´Ækìac…جL ›Ò䌀Q¾§)l‹žzFÀÖ/!°!®¿02«H­DÀ&;9!`S2‘)0JpCà6¯\™½re |/ SàÃøe뇗“¤ÿ¥n€žô( œ·Ž‡úß¡iVàmÉ’úßA+òâÀÀ™üäݾ¨(WÉÇÙ…}ÿE"[þ‹Œ- Šä¿XÑÆEòŸ3¿,ÿzçXþ;äQcùïŽå¿Lx¢ ùÏ)F–ÿjÉ]òß¡'¤@0Œ ~ìøt){âÀ5%‰‹É¨þá†ùצþC¤GõÏ—Âê_m”êßAr1 †¹Ð‡-¯[ûk¬X((w±ÒþÓVŠeŸP,¨üÕbA% Æ,[‰õ…+ñO±CÅ‚JÛ,õ z¡`DÞ )þiT(øÎ¥05 ÊÙªPÐ3]£`\¤/ *ÛªXða™bÁ¸Ö_|ß2Ü—XP¶èÅ‚r/”ÉxÁà:$F £>ö.ôOcÔš{Á *ƒoú ÎCd%ä'§`PoÚ‚Áp5Ä åÀ^0x_RƒJ\)¼›HT0è+X à)•P0èka¼­Ó ㎪fœFÁ L)6d˜LÁà»wœ—a°óíkôÒLÁàÁå Ò ã>4xP$ *gëCƒøaLƒ²íÙhŽØEƒ4xØ`PÏ™a0rñ€_‚Áˆ1é ½*T08ñA)”×E ‡~NÓàM°¢AaœiPÅàŠ'Ý4x“>4ø…A/ŸŸÎ?ðl3Δòw<%gT v!`cñ³BÀ6Æ)”…W!`õqð§%AÆ~¶K‘”"@Ù¿Vì§üV •šÿQ¿±Ÿá¥Š.›î%*'·@e¾XlFB €²¢ÝWTBn €oLá$Úé`ùðX ç'4Xÿ;\)ý/4j¶Hÿ3…IÿS­ÊÒÿ:ƒaJÿ ó\ìkÓÿx€=Wµ} GRTjQ €*×bP]JTm–’åÉ] ÅK€–Ï,Êǹ$À÷†ßÀ2fj[ß 0Óß°FAÌü(ª„ ÀÈ•œ'þøh¹ù‰òå#ÿ!Ï;ŸüDÅ|ûZüD é®ä?\PÆzL“¤Q»ø/Æz6~¢Æ›ø/[°¶AþÃï°G" qS·C&ÿå®&ƒ=ñ…’ €ø//ºñ/ÿ‚àâê½ù8ÄâJ‰RÂ?Há;þU©ð/ï*n­–+w‰À-Ð_~ŽÎ]Ì> È<ùêÔ`D¥ÌþòCMeq6?ª÷¹«Mþ«„H±ò 7ù¯Ü Å~åD(ö+D±_Üãñ!ûå×üÞÀ|Õáeð¸Õ"0"¤Hz óIÙ}Šý²P"`ÌŠ°Ø/GæiIô׎ðWÉ—mgø£ûAi€Z¸”ë–˜7X<´â. 0Ã>@™Ô½pY  Mà¶ÕÔÊêäüCà’5³5@—ó³h[Nk€Q“M+«ã{àgá­¸´gô[*y.0–‚׎~Ùˆ2à²Ò)pY( 0r;È©D¿t¼Ûã>s™º“ôVSaªd?ÛíYÜZÈ~µ•Ø/ê'bò&ö ‹;œ£Ø/Žp|tÀõ3ûåµj0üá0瓸¤ÃŠýlŒ'0,ø:Ñ- ØÏ¾}f?/Ù›ý–§ïb¿:)±ß*$ûÅÈÉ~±‚kÅ~KËæf¿e±[ìn„XŠû¹–•Ù/Ž?ºØoÉÖÃì}ú‡ýT$Kèfzp±~¢Ào)ÔÅà·~~ÑÓlßRÕcƒ_ìÒ’Ào9`Xà·àP´ß*%ø­‚C‚Ÿ ~Ž:3ø-YQü–êÇüì¦gð[柽ý ~Yj‹ý¬"T¿,9U2àÖà·´kð³sžÁ/ÜS°Ø#𳳟Á/Fþ‚ß²(.ò‹Ì°ñ‘£…Iò‹­&…A|Xí‘fòsù&“ß2J[\øÙÚOà·¬³ ü¢ Ü×·¸ÏÞz澺6¿¼~{’}Ž{ÿEÃ6Càß„*-Ë(·‚@•ø3Ú®ØT %Kø8–Khc…ÒõæŠì± ãxß~{èÛ~ü(ÌÅjÌ{I€ï{ι~@ÀLµh[ hÚ€Í=t4‡ QlžKl²„ªÛWTÅñÒo®ÄZŒoåúäÿE*ß'ý¯I.. ðdñ‡’Ue»4@U*+ 0 Y~ük“i²¥ÿJ䓸(DÐéƒå*ýÏizJÿ‹úk̤¨¢NÿãÓ` °Ÿ,”Pày(ÿŽ`?.ª"’»ç¤v9‡”¨À+€›þ(ðÝ çm`§ðÏÁÅÚMþCÓGý£r&õ/BÐó'°ú× šÒ_ÓÚmIC§¥¿S,(é¯F-ý5 #éO›ô·$;Jú“³¥¿¦j¼%ý…ËÌOÒß¡€LIr—Ù¤?,鯩oI‡ã8)ý5Õ2°ôbóØÿ+”ZùkŠÖ—ò³DŠvTþš‚ ü5,XùçªÐ¯2˜JùÓGÂÊ_Ó:w)V©¤ü5Å·ZøSå Ñåþ ×RKø»¦ÄA Jå(á/|=wö᥉E" ã JIøkS:¤„¿° úñ¯ÒýÉÃŽþ”CREÊ¥zÓýX3¹t?Õ-Ýo)Ùº_o¼õ­û]Zç²î·˜ý¶é~CãH÷£ƒfÉ~~5Zös°té~7?ßÖý§Ì!íï€'â¿6ݯåëQ÷“³{±+°WøçͲèþ©*Ô…~ω'¼Â?æö¬¿”œ°¨íðOó‚Ã?«Â?שl=…Êo¸d¿ð*GŸ-þóFé~OçÄ´t?^R‡€®ó'ø+!H1 7ßæjÉ1c@l1 ¹¤b@i‡Š5ZYø³6â Péä[(K}”ð§ðŽþ¬ºXøSßþ"î¡”+t|…¿TØGÊŸ&]U{)»tèR¦ƒ@éæWÊŸŒK·(PåªZù3ÐT¨”,+÷%F“ò穵•?/åO9¥üݘ3•ðçÄT >óŠuL¥„?GÚ: TË'þÞ¹ž*ñŸÊ#mQ “¼þήt¨úx[°y ÍƒÍ#¹—‡Úzy,{°y¬Í„Íc¹—ÇÚzm(MØ4ÖîÂV/õÒXÇ«-\gžóù¯¶þï¼Ú~s#þÚ«í÷ºýìÕöÃÐíg¯¶?Úíýo§ßzµý™/¯޻¿}ÿÿóß¼Ã÷^¿zX;Ö_öj»rš4~íÕö^ÿVÿû_m”öG†moçÿõ_Ba}dóWÛþù?mݶ5þ÷ß½#ÿ½‹Û5Þ¹ÆsÃÆí¬g7?3¬rp'ÍÄÞ–•jÈÛñ%Y±1§ëWV͉Œ\×»âÚªàd®¦¼“Âiæ`VÔf:-ëA3ð:Ç iFóÀëDþ в %ŒjG€¦ ”àt…¯Õ^Oì:±²¹eK$NlзaÑT™K×ùÜ ËcÌÍu!î´BT¯ð0j™o9 B¾- % S¹¯ð£ÊZ\] ŠàI“×⽄q¨™hŒã¹binaá#'p×u]0æPáÖ+¢ |ò̯y`áKÆoKf&d¨wCŸ‘µ.Nìýô~0AìºAï O{[21c2¯»%’¾¼ÇB×Ý;‚Þ×*¿—Ë£kæm™zô‰e¹è3™ür@ÚO®%´ëŽ…¹ø ©ÆÇÛ2Ó c(”ìºßß>?za‡­V®¤Œ¨‚{é^éE‘öP¸—î0Ë>ô//_kÚ½å‚Å5£†_2E±‰–´¼ËE}\œÙ'ê”øzÍŒÈy?¹tU¸bšÔ¢‹Bˆ¯™yãÔjÝ>iz¥˜íkB³§Ê\_á“‹_çhxfÙ‹8í Û‹Xü:ß' óí¬à¦W5Ä+Š6Ïè«ÆZ²ÀWJ8óˆžKÓ«Aþ ß‹–&vƒGuä¯ìsó>]+ ê”Ò}Eq¢óÁêö‰½_|wº„!$Vôñ<„Ú™KÕZ$¸B¸á°ÉÊçë½súrE„A.T+-éÊò\ÑÇÓmO»¸"“󺱬›?/#QR¤ÀICé'7Z°–Ÿ+׉¸W,:dŠŠL® i[ZÍ•³Âñ—8Ö@¢ÒšWDç㺆ÆYW)êW.ƒ!› £DÓ…qó•ó>¾¹2L'“;"Ùóim'¦’wVrÉE}Jùw$åçBu¦aß!ša•ÚÎÔÝsM=×ïp0ÊGµ1ŠúŽÌ‹\¦‡ðDÄp\ºé–KwxMåL7þ3'Å$h{_6W˜òRÃÞ£*ñÀ)4lõLÿ¸£bÔ …YŒº~Túô£2⌅.î,Å@»<ͨÕVŽcY‹Ñ„\n¾£dAc,Þ Y/Š}rµêž­1šP¯¶,•á¡t¸¹£fÔÃ>7¶•&¦mÜQ4j)F®£e¡Öºï¨•ϪÂCï¬Eg\Š ×dÔIÆñDÙ¨çG%ÜY6êBŸ‰qV‡Æ)dѨ 'Ž{6ñf¿Z >n9>JQ3Jqú9y¸³fÔý£l¹î¨õ©âŒ%Ž geÍÍ;Ë]2œ¿ƒ¤TsëÏZºm ˜5;žü½6¤‰l‘ ì¥Š•œS$x/sH0ÒG€^Á©’ËÁÉg­8ðà‹¨8Põ©‹ ðš»°EË· ]Àë<É âÀ%•Æ1y˜þ‰#â3Zq`K> ,p`9‰‹+ÕBq×? +èZñ0yñSu1jX˜VÃV€À,wÚ%–F),µ‘˜_Åã‡-¶þ$ÆÌðtÊ H<Ìet•LCà¡Ùž!ð@ ¥ E!ÇŠ>fÓ‚ÀCÀC!̆ÀÀj\?A`S|·!ЙφÀÖ‡ ‹ØTÇè /A`䱓ÃŽ%,Llòö56¥ÌÛÅFC W† 1 ÅR… °)XÒØnÚÛÍž!Ж †À,• x#6Y;£ÏÅ@`L‚±T!´‹„!Ðs]Q`“í¦)°)QJØ| c lï/`Šf06h÷ƽƒk!ŒÒhC``£+«)°)êßw)G!FDËÂ#4046/¶#Äåþ@` Œ•BàÁRìë-|Â6lZ˜2ÏýYÛ0ð —‘mÈl<Öú2†õ/9‘ xÕÍ€‡Â@Í€q,˜3ŠÃTx|0ìK.ŒL¢Àqqnl œL3* TˆIQà #€‚À› rJ /T˜zA ì¿ å2U¨¥QB -± e¾U¨uù‚@EsZ 7F¸_þ.Æ@­n*Œ¸8²;ªœ`qà jq`F9P¦6ŪúWØG6ªØ]q`V‹ÜP¨˜s ’a‹ýö0j®n Lq7 ž×%¹Rr`ÌžÁ·’eGbŒ˜ÐfÏ/x/10dÐ^Öi­*Êxê%¸iBW‰Z£,1¡ð¢À!i¥Ä@%›G>Å‘„µMbà-æò5Ë‘B>-.ma ó'äk*CUÈwsÚJâkò4ñÙZ›Q  ÁðÅÌ÷br¡Å1 ‹@T h{þñQÿº^ãjEN¸×UEÏÄø †òE%–È×eÍfä ckî‹È—y”?6âë "3ñuÙ¾›øºœ4L|‘ZËKâëª6däë’„|1·â*ä hÁO äë*cäëŠØ¨ÐÆš#F¾Ñèãbä²Ð2ò YšùbÖÄøI2ßÐŒÏЗ³¯õ ?e¢¾a±Ôâߤ[·©/Rn)ä‘úkêk’ÅÚY¤¸Ä?z[ü{¦¤HqŸŠðm1 Â_q_—ÏV‰ûÞ;¢ƒ@Û!~$ø5-@šýÂwb©Ù/V°•ô?©2ªðÇ€*ŸÙ1 ò 3úÅYá{ P/&[ÿS± B¿ƒóZÇ€>(cQQ ,^A ’Ø‹û4Ï1ö鑯PýLj¬r ¨CžêP>ëÊn¯P™–U ¨.xÅ€ª´RÅ€ªª€c@%Ã÷©lƒ¹Oë*Å}]:§¹¯¶O èñ‰-áÓúŸWÞ­ÿÉ[¥¸Ï`PúÜ" û´:'ìKÁ¢¡°¯’àWRÃoáGQ_Ú)w #õo:âóÂgÕ±¹Vÿd$eõï}I“è¤þ9&ÙÔG¼ ït0§ ï=¨ã+þ™¬ }Qïó+þ5Æ—ôɱ OÞ(}½+˜SÔwËúC5 }²z-èk·ŽXÐç@.C_¸%lÚŸªLúlXÐw\Â@AßÁðŽ‚¾Ã¡š¤¾åxYQ_L/¿1 1ÕZäÀéÙ$QŸ‹e™ú*>QÔ—ïßø·T’ÍØç‰ž±/[>Ø—~‚à(bß’á‚°o­[±¤Ä¾åXr_¨؄ܷà+î³ùžÁ/4 Bî[Œ³/éÏÒsI¬(TÒŸ—.Ä}Ñr}B@—ª¿•ô%i!ÙIú‹ZÒ)ý9®ÂÒŸ<òÌ}1i‘Ò_$`ç’þ¢¸(ð‘ÒÃñJùÓœÝä—†}_éÏ üÞ†5øy#+ó$i‰ûÂ(\%îcˆ¨ o²²PQßd!’¢>­“õMV0-ê‹£C‹¨O.<…}“Vw…}a(Yª_úã|±/¦* %öI *ì›,Ý\Ø7›$=aŸìÕ ûhc컵Dbî›Z{)ÙXþ‚Ÿ[1à7O9NÐÅ€¬ëT¨åÐMõcRÉ~•6ÙF+r³d?Î+Jõ“{t1àXÊó:^R .s_\,¿DÌL¨Í€ªƒPªŸH×¢ß#ØèÁIßLÀ D6)ÕOÕ€19Y¿QýÀ{$À.9`WÚ¿ °ËаD¿±¢JŒ¯õÜp4~3†F¬¾@À¡i‘pȱ¿D?ÏUñaûäž5*!0î•ñÑü"ᦄÀSn$†ÀsÐûÖxž,|]ºŸŠ+O½ZK÷›X0-ÙOê¬U¿–ý?x›ègœ£è÷H!µê÷°¶ðjÈÒ0^*_b¼dll &"À0›ˆÓÁ[‘/M”JôëSù}$ÀK>_¥úBCj#^¸GÙo0DËxYÃ/Ù–XÀ¡à/`(ƒ†x*~@²ŸœŽÍãùD~žŠä0ü…ÄKü’èçעߢçœáïT†áo„qäþ†|é Cn´%üÅqào(À­„¿Éd3Ãßup 1[’þ†ßaþüÍNú ³J,‹þFåá‘þ†’Ãq•¨T8àP•`$¿~t¿hÀ¼S8”`òK2Ž1ùå´ð–c”ù€².„{À®ÙµÐj€Ê~ª„`©~Z_ÞvÄÀ7Jq@ݲ–ýd¹P²_¬P|“ß[l'ÕO!OÿqUÈ¢_D Y%ú,p[¢Ÿµ-«~ZáÛðoüœxè½eÕïŠ%þ=¬Xª_D!"“ø'ÇØâ?K:æ?­lÿôu)þórS¥ž. €”Z+ô§(ø‹\S€’ã>% Uþ‹Àmùô—+ø‹©éýæSû½áý û´àTaŸë'ö{´žRaŸ,mø{hN»Å}>ÚKö£­è'˜NTò¦ñϰoüóVÜç©q÷ §ÇÀÚHèh >ò€ò«(TEÀ÷!¾M;Àã^aŸ‹ÌhŒMìü'M¤øo1Õð·mmø“•uÁŸÃà Žà5ü­K1Ÿvs›1Wü8é¬È™Þ]¯Ø°{²ýîVÕI]þž•ÛÌîûª¥lÎÔV–BÕR6g+]«?ë–Km5VµlcåBÛç¼Ù°„¦m 5ü§­×f¼ãšìÖk?»Aý;;µÅÖëv‡ßüo‹YV/›¶·µÿ‰Í`5tÛj跷̼z:î&Q?Ý|qíb&ÿéã‘ì®æ‘6w5äNi룑Ê[M#íÞj©:q¤½G’·š*o5£.¦zxûªy˜ÍWM㸓Úúx$»ªy¤ÍUM#¹“FÚúÔs,O5´{ªùñW'Žôw|×¢{½oÑÿë»ö¾kâÝýÏß¼‡ñªþç/Ο_ß¿|83Ò_ö\ ó°õÎ þwz®½o¨¿â¹övÿ•çÚÛü±ôóó&ýïíß¾×sm^¨k•Iógÿ¼!oº“Í\€‰ŒxáüÛ’3ÿÌ‘ç—÷LÛÛ>öóØ!ž(Cg^wb]•|[fΞ•ï7ã‘âIg™Ÿ÷§ê9{–­îûÑKi²‡Á|þC^ÆkÍû81{¾Xªz¾LÙ³jv¿-鲕ÕerÝmÞ}¢>ˆŒïßiÚ‰éó:Ôòî4gвÌ}[ðY_ª}0ïkrÍôÃyß'Ãæˆ óžY$£øpIïù8l®£ R ^7FŽU³gßicëJL|[XÉQšåCPg.O}öÓ…çÐ(š¬Ë9ÿÛòPìd&Ç S¾‹^ÐøÉç•âJ~ÜúÄ¢™œ`.´,F¸.þ|á³0X(ö¯4åÏ>¶Š¥3f†ælømY ]­TÌ(îÙ²ô°™E/O(̹§pòKÖÕ¤t†õÂÅTцQ2ÁX–3¢ÉN†çBÆŒr:rf¶ˆr§×²÷ŸYŸ(½P×rÆ ”yÉ‚ì7Pæ%Çz6Z õBÍÀ¾Ÿ yÉ'oÆí’yÉŠ5ŸÉÅ-IU3ðÿ™[ ï ´?s¡e©<–39ÄÍMÆ`ŸÚèœÈKŽ…ú<ÀXé'6ÂoÀ˜ä쓪ùŒ¸e$&?"ši­º¬ŒŠÇhÜw¬6#hbׇÁÊéy󭏨X–BÀÉŠjãëÞÒºWygÕñça—þÀ=@UÛ×1&¥Tðeå•¥#Ã=]îŠíZ‘.î·ð{Ÿe¸D†Mä*é U'ˆ¤´¯HÞ~hÀ>±l–F‡LðX‘Kû€3òÕ² 8‚éò[kˆ ¢g÷BìFza‹ž~óoHÉ«¡’fÖØÁiGÉ‹Ôyc&V„¬ áw'†¹n” Q˜Õ7žbvkf™ö ZdE`Ý¢y~¨ˆ»ÉP?­®¨L4Ç*è³²˜KÎ8‡¨Lt³ÄGGKËÕQD³ ¥§ê™;Ç/ÕGûQ6i+Ë=]È"ã&gÈ9é·Ðå("9tE¹§\?Ž%$ô !îFzZGËÌ—ô•{páiÙ'^s«cÍÀ–w+«=eãíVÄŸ]a>ù ¬¬ö4±ZÌ>ýÀú1cOW|Zˆ’Ê×ÓŠ‚OƒqH‰ë+ >åµbà×Ê‚OŒU;Ñ0QÐç¡,¶r-26,?™+*>1ÄìÂFøI÷¼Å–øªfà~ÿ¬ùÄÐÈ”ÒVÔ|:iË7Ù’_ÕÜSbÁ Å E}h¾²èS„dù‹¢O½#Ó÷,18÷Åq"Ãa[¹®²²êÓBÈ(Îê¼;UDñ¬L[õ›xÞHð’·ÖÊ¢OÍó§Ê¢OéƒÈz(+ª> ”Ê¥Á•EŸ.tI_¡vuŒ’k"+«>í…+ª>e¨Ÿl.WV}ºaF‰S¸Îü¨¦.Š:Ë>ÝpeÄÀ×B¤Ÿ_-Yõ)R9[Qõiu1nþ Ò`ž­(üÏj?Y¥meå§…–Ü( ?ÝÙ…‹ë+ ?=hÉ/ÙÊÚO'"]ñãÝ8¿Ì‘—ş.è¿x€£úÓƒ›v¢Ë‰ïjWUµÅŸ4ÑåÆwÕ1µ+j?e¸Ÿ_7Yû)m^d¬¨ý„ØÜ¦­˜LzŸ˜­(ý”›OÐÌTR•J\Qõ)N0Ê% L‘q`ø¢æí@ñl'O¢+>…ƒ(ž”™î ™è†Û™Ÿ:õÅŸîÏyÃÉ8dÍ|û¤\žgõNpNx-D©§©lj³¢ÒÓƒþx+Ä4<še$WÌÂÓ3”ÙR+&ácr FËzjåCà7[P»ÜŸÖʲ[ªC¹²î!FÀ[&ÂNò¨XtkE`Ò‰Àц(îG—b¬wMˆ[,îÔ·µ2=…çŽÕĆm“öH+Bí˜˜ë¸ e³ü“_o‰û+&ÂŽb !$c¨ ¸C†Uu¥¸„SKn=Œ~X9C+ºþ WÈ<îÅw×JâmzciäÏ9¨mX—Ï׎uŠ*-¬»X’¸°îfrAab'u±bݱ±.ðpìX7UÎÕX7•'¬›žó ëbî’!Ö…ëæ’º°ñ>QĺI1¨¨î¸9kÕM))Eu¡?v¨kœê¦æŽuú>ê–žCÝj _CÝò,_PæãuKÅ\ uKE(uK †º¥ ’ .Vëóƒd¨‹øp€ .ú·uaqNÐ"Ô…’P—Ï:F&Ô-ðˆ.dpªˆ.Þü¢‹aq‰Et®Ÿj¢[òD0Ò-™yšéV|û[`ºÜWCaÅ=B¦ËM€Ú`º¬O«†…Å7­ÅtYM?¡.—w@¹…çdº\dÁ‘éªàª˜.KáNÜðUURÓU!T1]…ö‰é*OP—'qbd@]áƒ>€º ÒÔe&ÀtÚì?Ìt¹P‚¿tû®“épN8^0]Úâ“ÆÀt Ø@c€:„æëP—-˜•’ê28±£TWÕšEuÑŠO+©nïªËàY|"Hu¨ßŒãÕåòTWå®Eu©¹xHuˆ•Ä%ÕUp¯¨.¾7¬«_A\5r»<> ®KQŸ=r]îúF ¸®BÅu Æ®Àu?™¹1Ö;וV+®«0gq]nÕÙ²¨a²8¢À®’"vy¢À6ÕÇ… וŸ¹®´\q]ÊÞð \—ÃÁu0&ÂŽÁuÈÙC ¸®Äpq]žæç;¤y‚¶vån#°+»YÌvv²«ü@‘]¯Ùe(fÍ$;„Õ³%ßÜ•;+´CŠ+°rbÁÔ§N´«ÕG¢]å& íò¬ðƒíRÑï;ÚeŸ…>@»2Úå"&@„hWaöÖAÓ¹ ãí*HWhWAþB;ü6ÀH°]Fp°Ïä‚)MA„v™ä¼“bPpV–KAû/“,™²¡aµ4Ê¢¢Gçj©bkvyp@«ÁÅR_Or]fgÆ‹‹¥Ê(ØU(ŽÀ.û` N°C$ Ž`—wÒCÔãb©"vvå-²ËÓD’Ýö0’ìò˜¯ìœí+°ÃŽìBÒÃÇ5­Áq»ŒòŠ’ì*Vd—[lÁ×5[02È6k8>ºÆ6Ö Ùåñâu2³n^£ñ,Ñ.GÀ hWÖÛD;8·»í*Ûžh—Sxí*œhWæÎd»}“¼åÉvi—ŽŸ+àn?­„»ÜÎpWæ„»ì ºË{ Lº«”`Òì¥ó°AwÛÝ!ä ¨z®Ï5è.ã¹a®á°£D¸ËƒÀª à.GìÜ!½Œt ¸ü¢‡/á.£õñ%ÜÁ^è–p—Wwc»í°žÁP~œ8Ø.Ï‹D`»ŒíÇÊ ØVÛÊd»²# Û•Y²•ÿ˜ÓäßÉvÙWW±rŒþ ¦hÆ»ufLÙ†wKñ³Æ»ÅHXÓ]LÊúG´[J=,Ñnrm¤D;1¼E»ÉeÀí0ƒÚD»ê"Ñ®F¡h§j²%ÚÍ_»íb|0—ðN±Ç%Ú¡~òŽwW¾ðNù¾¥ÙÝ\À1Þ=Zˆ+ÍnP_²d§Ö’ìÆÒF’ìÛY’‚FK²³$É®6ÉŽ´$Éî‘øºKêÚéæ6;Ý¥G6Á t÷¶p¡Jt7բݥ25wÀË}ÕxéµCšk°î]< ¾Ë]¡…|7ŽI#kñ]Æû}ÈwåTš]„îa«ÔìLBÖìbà£Ù•î'ÍN†¥Ù)çD»G²²E;M-Ú5Y$Z´krÓ²h×ä;fѮɠ֢]S5‹v–¯,ÚE<1R횦ƒVí¢Ô5¥>ªvMŸV«vM–-VíšB|¥Ú5}­Ú5™×K¶ ?À¯l'Cj«vÑ…êe»§ò²[¶k²ã)Ý.þ‹êvÑr~t»ˆ”ÇҺݠ5tév¥·I·{÷NmOºžÎÒíä_´év‹_ëvZY±n7PºÝ)}RÂWÉ­ÜÈm.åNæô¥Ü)«”»FÊÝÛHjåNFï¥Ü]¬ñPÊÝɈ„M¹"E)w×àÌÊÊ6oÒAËÒ]—˜'éN±’îN©p’,.éN©J%Ý]\ ·r'Ó‹Rî¼Ò\ÊÝÁ…âRîÌŽRî.> %Ý]šÎYºS%ù’î.†t—twÑ6¡´;.•twlrѳØ•»,ö„q%ÝiMÉÒ]“%¤»8¼±ó]¶`ÎDé.RôÀ’îœcRÒjQYºËÃt×ä8m鮩0 ¥»æ…qIwM®Ô%Ýy]ÇÒÝ<4ޤ»ë+ÜݬŒfánk¡pí@Â]œxf×I¸‹ðæp×&¿âîì² wÍR>­¡s²…ÂÍh,Ü5™åX¸sȦ•»¦4_+wq!p‰¥Ü5¥A–rg%HÊ]dQ}¤r—Ž©à0JwÍŠ†¤»ú%Ý…üM±ŒÒ]޼^\°üº]cÊ­e»¦‚„–íbªt»¦´oëvmÚ u»&ÛtëvÛV´Rð½u;ëùSu!q+R¸³ÀNÝ®)^º]S^³t»òs—”íbH¼S(Û1Oê_–íâùÄ!@¶sŽd»àÙe»æuÇÔíš%êvMyêÒí²œÅ†vyÔØ ÜÅýe+ wq㦢p;mÔéR¸kRž¨Û1Cì_Ôíâ2<»nç’›Òíš*eJ·«÷1u»í  Û9Nº]“×®t»O+u;”n—Ç TƒnW·t;¥×J·Ë°]·k¥Ê±Î‡¦©Ûe ü›U>æípî8èvÍ+Њ޾É?àxV<×î̽Ÿ™õÑê–ª‘Í©^mÑœ ­‹æd›V4×yÇ›æ:«õm!˜|•˜æÞ†û£ÕeË æÜÃ0'K“‚9eÙÌu¾( æú¡­s½ ïDs5Žh®ö%±®Ó„¡ÄºÞŽë:m6±nüF¬kÿøI«JZ«ë§B'©Õŧ@e­Nq¥ÒêúaI«SqŒÒêúøY«ÓÁXª«ƒ‘T×Eï–ê:­&J­sü¢ÕºÞ—Rëê¥ÖùŠZ­“B©uqž?v±®Ó:¨Ä:9kR¬k‚w‹uáR £X'Û‚ëªEb]»¹ciu´>*­N™†¥Õ¹‹¤:ÕÌ*©NÆ(%Õ­ãÇ®Óé]^:Ýj ‘”Nî„6êtQ•l%Nq‰¥ÓiÕ«tº¥% uZY·P±ÉØ•”ºE +u5®”ºçz&¥n±ìu)uò³.¥NÙs¥Ô=šÝZ© _J””º·eîñ—›ºc¥.’³AB*µ”P'cÍê®”P÷n…o‹„:;I¨séÃêdj¡î¢?¸…ºÒ $ÔñnùW)u. a¥î‘£›•º8LE¤Ô¥Õ#öE¥Îõ?¬ÔeÑô¡R·õ¡Rš¡ B]|\¯Pˆ‹#¡îq¬„ºìCiŽÅI hH©‹gâØ"0«¨ˆ•ºZ×–R·mD¥®|¥Ô=ª e¥îQá-+u¡L|•:{é–Rço)u©ÁÚ¨ÔYƒ±RçEo)uOEFR©“Ko uªã\B¬·,ÔåK‡¡.–êÚCÍCB|3J¨c!Uët¥4‰tš¼X£“kNitÞ‹4ºZ¼¶F§YAit)Ð=úžZ {ô])NkF%ÐékT f1%ÑÅ ø‘èHUÒçTÏŠG—@§‰:§½—B×o.âX¡SöX)t²œ.…®¶’B§IC)tq€€3*t±ºH Sˆ~ tÊÔ/nЉÏÝ£šZ%ÐuM<%ÐÅÈ`N+t&\Vè|Vè¼Rf….–Ãw†Ë]á Z¡þ¤<×ôUòœ],Ͻ'p“×Üߌ£<×é\”ç¼(yΫ…’ç†HEòœ/’ä¹ÁZu–çÞ†‡jä¹x ¶ÐË<ûîÐËÜÃ=)Ï Å…@ž‹C5Rž{? xIžSq,ËscPT–<ç@`ÉsC+’ç€¶ÒæÞFüªÒæ|VÐæ1fmÎ'!m.ì(pçF“dHqNEµ,Î Tù“6—Õ»€gÔæ¢àŠÚ\àËp™ž„‡CâœOâœ<^-ΓWâœJ†Yœ‹Ÿ8Fq®¤6Šsﮣ#qο¸Ô9ß$Rçèhù¬Ë æì¼óÜâ•,ž{¸Ž[<÷<Šˆ$Ï=Ö ÄséBF-Ž<§À!ó\ 3õá±È·øáá‹Î<§V<ç_Þ<Õ&#-ùáq¬¨x.Š‡ßŸŒºç7âÜ£°YóÜó0ÁŽ_žßD^F^DKsOWÂ`.KQ@ˆËeÝÀ{—æRÖÂÔœ0—5¤ÀÜÛBËÂ\6œÀ'À\?ˆæÒ6ûÞa.k(‚,Í – +iîý¬îq—Yòâ`ꕹK?¶•¹›ú{)sªlZÊœ“´,ͽ[ó¤$Í-|•4‡¯Ù.ÍÉJ¯¤9Ù€”4÷(IÒœÁŒÒ\“ÔniN–%›4§‹eiŽÖúVæ\yÄÊ\S9†RæT‹¤”9ÙË–2ǹÑ&ÌÑÞ¬„9Ù÷”0×te,Ì©ìD sƒ!%̽ãñ$Ìu.‡•0§¤æ,BK˜;i‰æÆñ‰½Lñ¤ïD—ùU~”0§Q%̽·Ö  Ga΋…¹‹&i%ÌÉ ª„9í¼„9Ë=æbT”0w)ÍÂÜ¥ s^™µ0x€q$ÌyÑRœ³L,ÌÍ&\£07‡ OœJ™S¹ÕRæäôUÊœe+sï½y}•¹ûJ™S★9GyJ—s–˜u9ïÛºÜs¸…ºœ¾/¥ËáªýkÓå¦@ºÜs(ŠRºœW¤ËÅl£J—Sµûæô+aÎØoa.¢ã0Ž„9Õ.aÎá†æ”PÂ\$ø~…9_ sïV¥: sÒ*©n)SÒ\ñfƒsêÙXIu’5­Ì©¤º•¹ïôÊ©“3fåÔI-uN<.K˜óÚ»sêè=º¥Ôi©À)uÇÁÇκÜÓ­©”:%I–‹†þ‘åÒ½ |&YÎyŒRæ:-º¶Œ:zUWFLå+£îP†§2êÂb ¥Œ:/(£Î™@æÖâkËuº4N¨kM™pJ¨kÊrB]…P*£®ü¡œQçˆ/gÔ½ŸÌ&]ΗØuÊꯌ:UC¨”:ÜTJÝÁ•Rç@;§ÔyQÄ)uþ­$Í)Õu0©ŒºÚ·Rê|VN©SlJ¥ÔÅbË7¥.C³uñtFBRç%¥Ô±H3ê¼ ¤Œ:/Z)£.‚ уu½}Â.ß1´#i.’ƒÀ†L©û„]æXRJ]5dNíR§ˆeÔµSą́ã,Ôu‡r•Q×¥®*£.é†ö#«;á(žzËɉç‰çh`¦åÛÉ%J‚åõŽ SišÆšQïƒq¢Þ hŒp3§íI‹r¬?hˆ(4Ä>ÛqD’á¬ä;Ù¹€?Ò?-Ñ*Z .¦õ¿-²‹Jq¿-"©* ¿-'„EQDËóV5>¸ÕñEeÛÞ– ˜ô„zÿž_X®4VžÁû|vÝ(ºL׿·åy •ÞÙêª'òà‰–•§ 磘Ñ޹Ю,¸·%‚£âð˜Üü¶ÄÒ)ìÚžÁ–•~cg¦oK®ªo{ŠšÈHB99îUêÎ@ÙhYÿ §ÚàGaØÙçÊûÛ’A£È‰á8±”9?^¬95\‹†>A—7J§ñø:lò›Ž&‘jçÉ–ya²ÇHš>"Žœ=ÎäéP)ö†81®*GKuh-™âŸúBçV3™ú·ÏÛ’K•Yîllç#ß߆'—Âí=38¾©r^´W"{üÌé_ïoÊðsT}[re!%¨{°è*yð¶ÄkGÌç凚¢tÞ–ø²þ@î÷Å(ôƒRêÛâïw_7*ŸÈEñm™)J:§¨?t}në¨?”™7p}↉A˜ûüÞÞ1aFÆ_~›V€ßF£K¿ø¢ö;†Nj1ýôýþ; ¦“}“®²Uo Ì}iX}¨Õë0ò[ã"Ú‚õ‡bO¼ÛÒräGf^iß LïºM"¶qâÌù.‰¹Ûîêø¶„ö ­ãêd•3´ðc—!;E~àg0+‰ObN9!ŠòŠ>—sGx+ÅBÄøÜ¢17ÊsXšË„»~Þ&'”¶·eåg5ªìÜ<ÖŸí‡Ï*'$y[ä®êÏzؘ`(G*ÿ£ObÄ ¡#}äÖ]_%dª±hH,j!ƒ„†œÑ€ iÁ-ÞRy7×¶[¼t#5n5±T·»ZðU•>×â.ÁÁ<<*¿'KcFËó&ãáG‰að#0ºæmi'2\.¾]j)‡±HÑò(í‚ç  ½¥þ¬™‘îL÷­ é.~˜ˆt×ètÊâ3ÒÉŽÏHwOõ ÒX„ˆt²¥ÒM™ôéâU1Éx°—")¤›Š®ÒÍç 1$ÒGb :{“‰èÊПD'©ÏD§/½‰î S•‰N‘&:•}6Ñ©d<‰N.#&:¹—è?b"ºˆÀà5ââtÑaÆtåO:Ð9!C@·”(/ Ë”ÄÃŒªÜºøóÞî=Vq€nÑW<·-ÿÄs¡§¬çÂÙ HNž‹ cò\ôà&๼$<†d8ò\4ä{<¦fX\ ÏÅãç!ÏÅ_ ‹.ët«æÇ:º;d €. ÍÙ ‹­á[]ôi [WãTœ<·è¨IœË ¼‰s 1WhIž[² Ï¥Ë'nä¹èó ÜèšúøÊåÎ…³ã§jN|OoÃ1P®,Ärå5$–Ë><ÅœL¥ðŠåö£YLÊäJ@ÕÁÙaàkÊLoq\¯¸íbo¾ËÁqû ŽÛŸ/p\ÚWrõ·ß°à¸|VÎã`ŒIN:ð9UñwqJ´‹Úð=]‡ ¬¯ŸÎáA}¸¦5`p\߇ãÒá’/sp\Y7‰ãªÂ8.÷Í3p\úEµà‹ºíýÁuq­ W~–9ä8²OáúÁ©ã‹ªÔIqÎ` åÄUÒ¹ÔBØpჺ–qðî:gç¸ìs’þäžJ­—©ìÀ”ÌÉɯ0®’H…qÙgÑ>¨4*°´ŸÉªjÁ÷T5z,_Êë/8މã'Ú³qœg­à¸˜€ŸÈqš{ ã–üË…qñîä:|´< Œ[Z™°2§ÇØÊ\‘•¹É5x+s÷îZ™Ó›ŠÊœÞV榥<*sª»ãä½aŒ‹OÝâæÂ#^ºröJ–»¥‘â²@ÞCœ–µ q7³& q“yu†¸i¾:ý p#)n2,Ò'ïXSœÌ¹Lqúšâ4c3Åù8Aq¦†¸A`ÍŸŸAhëz=R„#ÅÍS).và"Å)NÝ7Yɧ,SÜdTŸ)NVy¤8}'MqX;©°H!ÜååN!Üô ž®>µB¸yëÃ*„ ƒ>¶œõÑa¾9ÒþÈoó´Šws¢-#ÀÍ!&ÀÕ·O7/Kt89ÀÕD'¿¸yjUwºV"8=-Ep³k~‚«©ƒîöJ»nž–ßÈp5¹ÃåÈ"Üuéƒ#„«©‚®NAW_ ܦ‰ádý#„+éE7o.ò‹à ˆDpz†‹àêWÁé‘,„£¥c\‰"¸É T\ýl&¸®¨nZ;ÁÕÁˆàê¬EpQ)§³åѤê"á|C‹àô¸nwþLp›<8çç‹àäÙ´Üi™Ww°®¸EW³Üe¹CÇ×{\±N/ôà–~:\Q‰nvM«Lp&ÜuëîÜŽÒ•î'9.ß»B-"\†?£aéÍ-^Áy’o‚»4çÁ%¤áÏ¥»œüc€3ƒ àæ¥W w/MÎÅpõR3Ãù,ÍpEDb¸aùíà•áÓn†+ÒÃ!{C¸Kª…Îl„3)á|­„p×¥Àg–5ÂéQ0Áùw"Á)öÃ7Y¸ú± p~ß àXÈ~ã·ÛšøÍ”ùmŠˆÅo÷Rì‚ÎÇ»œúÌþíA€{ï`¾= p·àÁç·NœøÍ«(Æ7ïÉøæÎ7õQÁÕ ©nj½ëw®öD„«+c„«>…p…pu4D¸ºi„pÕÇç7ªÎ×Fw3ì]W§d‚ëbf\Ý"8UX+‚Óô­®î>Üœæ5\LšyR$¸9E3 8Ÿ’ .Þ4l˜ú\N¶áüÙ0Âù;g„óKͧÌ×b8ÿ.f89ÃyÁË §¼B1œ§{qÂqCœ¿»†8¿ù qžšâd¿\ç;ÒSz„œþ[s1£ÛOqÐψ(? [;B7̆nÌš5·ñ_ m²Ž5´5º{ÚèÆ]Ñ” ât4åÕ‘Ù,R‰Ùt@6¥,Ù”cd“;Œ™ÍÙ”?lfkœË˜Ùäßbhk\ì-åM{¥ò&UÒÊÒ¤¼MIyRÞtVÞD2–ÞnE[Úb—é­ŽÐÖ„»‚¶vaÚfhóqÚÚ ‘ÚªÔæhLQ›rQ›/¨­Ñ˜ÓÔ¦L4S[mBjk\ò6µUR[cIR[x~}¨­NŒà¦ã,pÓa¸Å^G·viÉN঻©À­ÝdnÍ«ú"·md›ŽXðÖŠ€<éäöðÒˆÞ6™Þö>óÐ9¸…nn7Ï ô™>'ùîé:‡ƒœz‹–Nê:¦~†g¤Ìk|4¸èCõôG³>ôG³Iù'ÅJ„Kp#¹ƒ=ErkÏ+ŠÌõã'N3 L… tš¥è.ZŽšèTnÀD§]¸í*Ü£œ ]:Ø€tž, é¢GÛóã¹0™éÞ—áÚóãüÂÓU™.Ìئ‹ô[HÉtÏÍ鮘îAÐbÝs‘)•§hçÆ)‚À¹q7 Mœ§ª ÎS çÆ©^²sãÞCÂï¥Ü8U¤dn\¸ï*\˜#œŸÜ¸»U¸G«Γã¼sãdRïܸX|ù䯩¾¦sã±àÜ8Å;7ΩšOú–©* sãVûFdj\˜t¸§ÖG•W27î¶ÖÅܸçÐ×8÷îzh¥Û¹qCoXà\&‰qF œ‡ž-åÆ-€sY~‰sà\ž$£8•×¼£¤¹ÌWc\rã*+8—óC§Ü¸~ @œ7t¹”'còÊ«¤æÆ9ŒÃ¹q—0•ç5JåÆ ;7ÎZ‘x.\öpÊ4èã·F¹qJ¢­Ü¸ÚrãŽiAŒ¹qòUn\?¿@—™{ʧcnÜáuWåÆEvŸä¹©3à2¦rãú#áJ¹qíðVÌÛ2õ˜§RAJŽ« ¨²ãÞY¼Äì¸Ê,Tv\M—•W“5eǸ*;Nfœ•'ÒÊŽ‹6“Ùqõ0(;ŽO RãdÑZ©q•ç¡Ô8´Wjœ?ƒN“‹g¥Æ©nPåÆÅRÇM™}x +7ΩÎ;/],åÆÕ|¹q§Ÿn寇æÆm‰Êk›<·põDæÆUü/sãÂÖQáˆÌ+2`n\ö!½17Nu–œ#óöCnœJb99.¶áj‚²ã*nXÙq§ß¡ÊŽ‹)2(=QJŽ Û¬or+7N@Ê{E#7n»˜Ã2V@¹qÃYƒLŽÛû 9n»K˜é§Cá“Ç?övNŽ;*ÊšÉqGEY39–ßÜ4Çédàܸ¸À|å37.&ª‡",å ó¶anÜ¡B[Î;ÄÎÔ¸8ï¹]&­ÎèpG‘·]­L‹³æ)05îèV‚˜gý‰§ÜOйq[*î’-ªó™wT¬¶rãN_.æÆ•Ö Ü8™“;7î¨T‚ÌÛ².™wXŒQnÜö<37pæÆÅ9(¹qy[ï‚\þTÊiCnÜaÍ›©q‡ /È/S㎂ÅL;*¤€©qÑ2v¤Ëüg…a^üª>\%cf\$“‹úw\þ833.=7¹kdÆmÏ 3ã²Ï–wÈçÓ©qq0— Ï¡ü¼œWødË躓Ž]Ë=)ôñdÊù°D‡ä¸ÃyƒJŽ‹‘Éoø¬^,WPÉq²4frÜáø}%Ç2¤rrÜ!ï#'ÇÅúÉ‹Kq(®ë…Þw¢Ë•c‡Ü¸£ÑåH–b­Íu}íbFÇBwyбewûýíª—úüMW±Þ3wÍãóïͽ+[6Ëþ½9€õ™åVöQÔ²ƒ¶}$µlc¥èÇÇÇ-ÛXlÛÆrËÚU¬¥…ãßu[ÿ;]Å~q»´uÿh?>¾b?ÝzySÝÇçfügµy†q¬ÝYLcU/õñÃX»kÆúx‹q¬­Çú:q¬rãP›»˜Fr ´;qœÍ9Œíþb©zi¨ ÇÚ¼Ã8Öî0¦±ª—Æúøéq.÷0ŒõñókÀ½8Ößñk ÆAÿ×dìLÆþÌ{üŸ¿y#ÿê­ýÏ_>¬?¿ÉçaýÍXÙh¬s¿óòÿÃÆ¶wëÿŸÁ^ì½Ò¿)é꼿(#Y“…õ2{Œ½-Q=a:ü¯eŸ-Uœƒrªåq–)~™~NeqSßÙðù ïíývŠŽOaì #èñª¢–*zW »R{˜;4¹ÂØFÐÇq+¹w cWüé{RMqâ<ó¡0v…Bô1C«ÄÃ>ÎS)z¼ãB\Ó’<þ¶¼ÛT¶võ„æwœgYµ(Þ¸×.•½x[¨‡[(ç$ þìÜÕâ·…ß¾I¹X…–ÞêÅžÙôIÁø¡îÚRŽfáO¾@%ã8Œ¼ÆÎ2ŸÑ€*«þ´ŽÊ°µŸÅ `m]¥az¦¶œœh¹9 £Ø£Î ¬b$-_Kì·Þb4°j™¶üß<ù¸@‰F¬eQË#ó ðdDðÛƒo›‡!Á5îÃ(ö­…aÁu9F±Ç)àQx\øa{Ôfâ8 –Që*ëõkˆ±?²l*¿˜ª%¢!OtÀK"µ7vÀ+xŒvnÃa¼ S+Zû^ri4Ÿ-$8¼ ÊḚÜ1#„‰$#ê]hhX¸ü_R‰mé÷÷à8ðô Ö„­„£ôÃd ¾Å§Ñ l¯@øm¡ÙÑ ¬š3-ÛwÎ}1@¸NºÝ<àÅ=1@¸N¹1@XÕqcIìÖÅ…Âf,7ÓÑemtFÛ7qD !ø$‹1ÜèÓÙ’E€«¥ÅßK78¦ ƒEa³/÷Äa»jíh;‡ÎìÎ:±øÏôÅ—þ }ï=vÎ}^'ôÕª´ ooôÅÁ³…Ô—QÿÚ ï.|ôEË! ÌÔ”‹³¡oÞ·†ó’’†È|a6D°•ÁHÉ|ó~b¾©4hCßT>¶©oÊ´CÐq™ŸÐ-„KB_´ aàƒ>Ýøè›N¢ôM¥zú&Ý È|çsq“e·ïçC}1¿O¤¾i Qß,Ü õM§¿‰ú¦sE}Ó¦¢¾él\`ßt*‘°o:?JØ7íD"ì«åaß,p öíãûöãöÍbßtN—°oÈû¢¥s«¾ð7¿©Ä¾©ô2Q_XçµõíÂú¦ó_E}Óö?¢¾™MÙèË} 'ŽŽ•j }µ™oªH;™o:ÙMÌ-¤q2_nóa¾…Hx`¾èï%™o:#RÌ·曲Y0óMÙ*˜ùö>`¾h¹yÌGá4–Ì—ç@2ómçM曂ùæ¤bæÛÇó噳Ïyêi Ì÷iyô3<æÛÇ™'ü9“ óM[–ˆù¦|Y„|Ûùfá/‘oªú‘oD“ú¶ HêÛvžà7 ~ ~³à—à·ÝÄ¿i·sß§eáj€_´p‚IðÛúü¦œÅ}³˜žÜ7m»îÛN‰Ü·Ýä¾iÛwq_ú\²¸/OáÃ}öÂ4÷m‡ìÛ~)bß~NÀ¾©¨AsßÖ’Ü·ý ä¾Éò‡Æ¾¹Ñ$±o»œÄ¾½Ø-|aû¢e}°o;obß~8À¾ia߬•‹ä¾ív$÷m¿¹o…Ü7mum¥´ŽÜ7m$î›ö6÷åVîÛÎÜ·CÇÕmœûùþMÏÕíøªŽÏ›à·1mWסõ‚ßöž ømãü¶»mÉzU7A’ßvùH~Û%&ùm?8É/ pØÛÏ¡úÌá ôÛv òsý“ßv$¿½ä·ÝµI~³ÖÑH~Ûµ"ùm§Iò«§Žà· Á¯Ž—Ü·ý–ä¾}#pß´ñ–¸oû-É}5ÀoÚË^à—QÖä)€ŸFÜW»úÕ®…~ÙB¢\ÛP©ÆRýêrIõs1«~[ U?ç¤ZõÛŽp>Ÿ *Ù¯Î[ºŸûX÷³úiÝÏ?¯u¿·å"OQ÷sj«u¿~Zj£îçL[ ½‘Â_·$%áoۆŸsz-üõ¦ù«„?æ[øSµÓþÞ}µ®þUý|#YõÛ[þ~>ø··Põëòx±êç:7Vý¢ ýâ©ùŠ~½„ÁeÛp®ùKô£SDi~+–üTÀU’_—·™%¿0“ RòsÌ«%¿H.bã‹K¼–â׿nÍZŠ_]L)~]ëWVü¶=Íã§Ë+Åo‡Š_0¿:m ~µ+ ~ïÅäòŠ¿‚_’¿: ~]uf,øm[Qð  ?ÿNÒû\‹Æzßv Ôû"¬ý«÷Õ]/Á¯vÁ¯Ñ9×z_ +½ÏOr_5PíÛ¥ÚW?¿Ô>Ÿ‘ľºTûj\j}]e¥¬õÕM±¯=ZA”ØWµÄ¾ú$öÕ(ûêx%öÕý ±Ïg ­ÏÇ+©¯zÈßÇ×_Jß¶£ûù\I}õHê«Ë+©o;I™ýø!•Ôç_VJ_\Íðm7̪ò‰Üh|ï(I}ÕJ_ýRúêV•ÒW×[R_]I}ÎL²Ô·í\Î?ÞJR_L ¾R_]H}u%õÕO ©ok¡ÔWoqI}ñÙ!ªQêÛ¶¢ÔWG,©¯~:I}¾G¤ô© H)}êB¥Ïg`¥ok¡ÒçãµÒç=[ìÛ¶¢ØçßÅjß6ÎåO锸è 4ÎíO©Æ™çÏG¸úþËYòÛ¶yü-%RçO‡'ɯ3ü¸$¿Ú¨ÿô%µâç_Ί_m$G ==ül-CÁO÷½õ>?¦Öûô:°Ü·Šü€X±¥ä>ßö–ûj`É}>\©}>ˆ}õïc}_òÖú¶¹­‚»C'Íð^Ÿ©€¥>™Zý¿Y)|!ì~ãß]Î _¼Óö°NÇ—Xás4>LXà[öpX§¬ð)PÄŸC3,ð9xÄ _T…û*|Ž[±ÂW¡ ðÕ(Røê`¤ðE\ ©‹ ß;+XIâsOK|ë)žãRäc ¤ÄWG#‰ïm¡)‰o©¥%¾81á·Òøc¯Bm¤ñU”4¾Šò‘Æ·mEÏWÇߣœJk|ÛÈç½5¾m\j|qÞ܆ß6.5¾m+j|KvÖø|ý¬ñ-YYXãó}b¯ŽPßs8ಯÏÑHã‹yG¡È·µP䫳’ÈWÇ'‘o;Š|u¥òù^²Ê·¦˜*_#™¯Î2_+™ok¡ÌWWB2_]uÉ|u’ùê<%óm#SæÛơ̷e¾mÊ|ÛVOÿŽK™¯Z$óÕñIæ‹Ø9‰zMç0>¤—O0 Œ2_Ÿd¾:É|ªDi•oÛˆ*_T>¶Ê-<ª|[Ê|ËZ¡d¾ˆ——¨ÇÉ­…+’µe>‡‰Xæ{¦#DSæSôŽU¾mª|ò$•o„*ßÖ‡*ߣ¸v«|ŽÕ±ÊWãH嫽Kæ{¦Å7Ê|ALTÖRæs’e¾èñ ïŒq¹#ª|ÛŽ¨òmQåÛ*ßÖB™o‡2ßs,)óùKå«s‚ÊÄv]=$û=úx’Rùª E¾:‰|Û¸ù¶>ù¶c¡Èçø-‹|*}ZäÛgÍÏï/‘¯¶‘Èç–Æïlv¡Æç+%‰¯¶¡Â‡‰ ZuQ ¾:)|5.¾­Ëý|:Pß«Ë"}ÏÅ¿­ï9ÔÏú^]é{õHß«q¤ïí-Kg –q |у{¢À··,Ãüß>¾:O |õxIáÛF¦ÂWg%…¯~n)|5¾ºZRøüãJàsôž¾º_¥ðmÃRáÛúPâÛúPâÛúPâÛ‡_]I|>)J|„©)òcÍ _?Jâó¯`‰Ï×Óß—I‰oëC‰Ï'e‰o‹Î¤ÄçgÁŸ_J|ï)<ÀGǧ€UJ|[È$%¾=¤³ùN—ê÷|/±5¾-sœ?ƒD¾º:ùêÌ%ò=*H‘o ¥È·…“RäÛZ(ò½[Ÿ ÏmßRù*ºU*_§T¾º’ùü£ÌW×X2_Ä#á(óÕñIçó3eïY©óÕ5–ÎÇèã¿`V2_ø³õηº%1za½?7ýÀƒ€Ø¡Óî¶®|Þ·°"-@ëá6?&Xç'·/èùP`„‹«…:ŸbÕå$A`¾IØf ê¤)Ö’­£ 0-Á”íS¬¨8Ç>€ÀGÑ÷bÀÇ© bÀ°“övÂÇVÉdÀ|“Hu¤Ê÷¾ ÕB•o¸Ü0T>Un-•o(MÇ*Ÿ-­òKób©|[ª|c˜æ¨ò…Ã̇c¦RHå Ÿ 4¤Èg»‹|IQÙ@/̘¾Ÿ­—¬ñÙ×ÑßPík|áMÉq¨ñÛìFÏG'•o8?H*߸¿*_ØTà`¤òÙïÐ*ßP(·U¾½‹“ÁDBÊ|6ò´Ì'÷O«|cþœÚgË|C妭ó…eã®óÕ)Hç{[Ä[Ôù¶ê|öµÐWG#¡o<$ô #„¾½«“ÃT&¡Ïþ<úðBÊ–‡W‚C¡Ï“úìi¡ÏæŸú‘SqŸ.ñ'Ès˜:_¯t¾QÌHÏnVúâp8r }¶è´ÒgóOK}Û¸”úê Kë³{µ>[‘Zì{ûü$öÕ¾$ö g„Aì«3Ø7IrÔú†–¤¬õ†pi}§[Z_Ìÿ–]F-ö‡ÑŽbßxJþcÁ`/SIìÛ¶J±¯ŽFbßé|0‰}§9]bßÛÂHbßé…,‰}Ûž¨öÙ#ÖjßÖBµïÔ2ŸÕ¾í¨ö½ßÅlü›h’ûNg¹Iî«q¥÷Å9Ý(øÕ™Kð;c'ÁïméÜG¦â·µPò;•‚bÉoÛךß#¦äW×F’_|©˜QòÛúPò³×¬%¿8âæYI|܇ãPô«k*Õo룊ŒÕçþéø¨úÕõ“ê·í›ªß©…rqàÖ"Õok¡ì•Ò¿²ßÛò|3üTÝ›²_íZ²_u ì·5,Ÿ·¡êw:gQªßÛ·”T¿Ó™ŽRýêBHõ‹Ãýª~§Ò%%ú]¢Z[ûÁIò«§âWïK)~Õ…‚_¬?Û,Xð«¨÷Õ¥•Þw:±T‚ß6 ¿¸ Êå‹oª]Ó¬øÙ]ÑŠ_ìú›Ûg?1+~1ƒ ¦Qñ‹q¨ÃQñ oÞo‚ŸA+~ÛÈTü¶*~çøà~ÄTü¶£¡âWç ɯúHòóÕ²äW{’æ§ûÁ’_\@4Pñó}fÉo…’ßÛÂdHH~5*%¿S©²–üꇒæW§-ͯ†•æW§-ÍoëCͯ~‰~ÑgWýê'ìWG#Ùo…²ßÖçö#¨DÊ~§Ru­ûñRìNj#èã‡s±üC9©±åã¤ö»ÛmNjìó7ÔÎþ`mÍ{pËæ\ƶÍÈ-› Ú™îÝÛHø{'ZöQð÷6ÆuPª«3VË6Û¶‘ÜòwR;[æ}¬Ô~×ç¬wÂ1úï{­½ÂÒâ7&N¿oöÛ{`¤ü{ÓO÷S\!ù˜¨q¬ÍøŒcíÆg«zi¬‰ÆÚÏ0ÖÇøŒcm½8Ö×Dc•õ‡Ú¬Ï4’ûh ÝBãlÆgh7>ÓHÕKC}LÔ8Öf|Ʊvã3U½4ÖÇDMÏhŸa¬=šŸm÷âXËmÌL‹ý¿öhdö'^ÎÿüÍköW¯âþúaýéõüë‡õ·cýu{´óÈŠ¸ÿçØ£ýÏ_Ù£ýÏ¿k6²x®êº¾/Ê[³´XMgI{ÄÚcšª]ʳyîÌMgŠø{)§È8žŠ‡à2}Ö'ø‘Y·âjØi/çY²9Â:Ìy`5,Ö$1}>Þ»cå rX{T޽å7Ž6íì2`N}3â¨Å}ôþýhFsšùωžÏp£}Þ–÷ƒÃ;;-q{”>ãáÍ´¦îvô:•–¸Ý^oKZS‡ üdË«ËS¾!g;Òš:ŒØ±¸t¶÷Kþ~[bò>Þñ4òKæïßï$p¶\{[¦Gi‰{F]y\š–Ëaã´³ÈÙ®ôÄÓ?[.‡½Çש̿-é‰{yúl¹6.¯˜œm¥9õµÄ«ï¼ æïñxïOÚS_.töãÿeï]v~ɱm¯>O±šU'‰«í¢ $êÐÆÉ½9B¼¿ˆ1ÇÅŽ•Y•Y¥-DƒNU~^ñwܶsÌ ú­Ôûõgñœ ©ûy1ÇQ¹æï¤Gz[*7uÛ]äû:ÎÊ5ß.û>\GÙêåЯîÊ5ß’àmyxyÞ ^xï-´w,ø˜ŽE. êwT¦ùv¹ß–ÊMdçþMmüª_ “³ìa˜©eí¼Î½rÍ7Wñ@Ëà17aã:«|ÚÙ’èz'…º$WÇWå¦nIÐñ¶TªùÍåzŸ.ŽpÜßu¶J4_f]L¯ÜÔ0wt»Wªyd^÷¹ËööskO¥šGYBÖu•=ì7§{Æ`Å=$YÃu•=ìlòú]×qò-XHº®2ˆ½‡l˜·eð4&®2‡½ÝžŠ£{*7uK6‡ c¾nÁ©9Þ–ÊMÝŠò«¡Wªùv¸2ìuJM 㕆ÍUÞ3'2×ûTO¥¦ÆNH§º·J5Žõ=ße{¿'Æ~¯oÃ8Ï÷}—5ì„Á‹¦×ë>+×ü˜M¾…»¬aïð³õmy¸{³úyÝe ;Ë@È·p·‹ßê­ÉøºËv"Íÿ©ž{%›¿Sëâªï‹-:䩪÷åìóïʼn§2{ÿæ– ûyê¶W®yØE5)´ƒÉèE>šnhwµ2†½Ã¦åWWåš¿šS ^,Œt¢hEÔ •‘Z”„¬HéýÓÃ…ÒH˜o; _¬ô¶8þ… 3æ°ìp±:RµèM±Yt¦±ðé›T¥3nÐ÷^bñy¤Lù­ JGsž›{/±¸ §´[”N¤$rËà ºôÜUA錇Ž—ZüîÔ6Ù›nUPšCñÞK.®W·Îdî]ö½.§ÍnPÂåq>¸÷R‹kDëT@ Ìâ>J.>±¦ë‰ª„Ò™Ô-w•P:“ªöV ¥3ÛØ[%”ÐÒt 7Èg–§[%”°W ‘ò>jóRƒÄ=³„Ò™Ô¹÷Qzñ 1²¹¥Ôó¯õòŽÒ‹ë8ÎoQB Ó‰Þç {ïß®z«„1¿Óû,½¸~£3©„Rmlõ«Ò‹Ï3¥­n•P:R™ö>K/>ØŽo•P:#‹ß*¡„\:;7Èg’fݪ£t6Ç-¿›g< °Í©¿i¯‰¿Å]sVKc#Ï¡,_:OÚJËÛâñ4é/ÙÿLï·-33éïöZúK%ŽÐŸLíB¿ž<¹F?¬KF¿é›fô›wF?,)‚69B¼ÓŒ6Q$¿J·Ëç%ô›©‹üªl®þ¤Ä3³À¯–!žl,o‰ÄŠðÛR'×à7k1ü¶97 üŠí>à·Ï]ªÀoOõƒßnÓ›ÀïÀbÌ{øɦmð;ææGàwÎ¥Yà7›Àîð;ïÓü-ðÃt§mªÀo.¿ëò$ið;òŽÜ÷>Fw+ðÃJ7)ð»¢:üÀ·Ú üJš.ü®|v¿Ûåí~ï$¬É×à÷.Oò—ø¹‚µ¹ïnNWmîC·Ú/‰ûî¹ç÷Ý}°‘ûP”ëË}wÁ1ß{1Ú üî¤Ðø%4=à·;ñ Àoë9·Àë ÎMðkM‘Yá¾ýö–ÏÜ—ŠÀæ¾mXDDîkï~v˜É}Øñ‚Í}§Ì€*о~qbø¥ô[À/%ì~:“Àph$ø%1ä—âÙ!¿÷Ç÷Oäçp1“_KæŸÓ)üZê¢üp1zß¿ùýüÚ;NeØø5ämÜÕRëè¤À¯¹´iÀ¯¥F’Á¯-Iði$ üZkAS’FEHg‚J-l"ù5'22ø5¬ä<‘Àæ MI¿ªX+Ö"ø-f_{¹ÇpHðkILfðk 1#ùµa “ŒÚG‹ü’ÚòŠüpèù!¿÷i“_KbI£_½ѯ ×O6úõecC~°þh¾ùá¦dL)òkÙ7™üÚÝ4°~mZ~-Ž¿6ç>Œ^n!øáÙðÃ=ðƒqj¨¡¸¯jßéGä>\Ÿ»9OÞ£˜Sà‡¢{§Q°sܦY‰Hà×R»Õì×’ƒÅì‡SF±Jêáˆý0%µû5cÁ_.“«üZ ~°“é~M; Q_KI7Sßòõ ûðœ|bb_KM c¾[ Na_{§tÙ¼¤]-ľ†Ò†<™Q­Cû0Òt}¾c’±£Hd-ìÊë~ˆ}óÓ0öµD±ûjå^°o®Æ>º þ:©¯|Ek¤¾úNµ<þNŲ¢>¬Q2ŠˆúZS_Û\5ÑÔ‡=—>(Qß}Å”"êk‡w¤¾¹s3õ5—lõÁ7s_]_jλM}6AÚ¿Šñ[Á/ÙH ~HÍ¥äz?”úQÞ?TÒðŸÅ}ÏL¬ î{²5ú=ÉÌeô{.£~˜<-™Iõƒ3 xKªßs…ë¤úa5Ñ1Rýàá$&£ìw0ÙFKöƒç”<É~=[CÉ~Gí쪪ß>·p‚?Œ"-vQýZX•ðw B‡.˜ðwDj5ü].õø8ÝÆÁ¨~n9n*…"4²ßjÈf¿w*×Iôk#ÌFö{/ÁÛ*±ß=ý¦}_ìÜ2­’ý®Ìóý°Š3%ú=®ÄkÑ/2ªà…“·üa?q}U¿³çW„¿;Ù ïà×`Õo¨ñý²šýi%öÃL¯þ°ýÑBoÑ™Ì?ð‡½¬hÁð—ü†¿~¸6QD?ä’`?†¿;¨U¿Ís©á¯ŸŽ¤›ª_¶M„¿ÛE®Vøë_Õï9µéýuÙ°#ùE¬5úŽõ7úu,¹2¡ßÀ~ OZ5?m¬…~ð1e¾Ð¯cIù¢_²½ýæ£ú!ßýæ–Z¬ú™µÐžÜzäF?öÔõý*A¿a°«žºÚF¿þþŸ„U³_l¦d?d˜ö[„±¤WÙoDûõ”02ûõøD›ý@#²Á„ý.b¿ª ²_Ïö{­,]d¿‘Wì‡ ÂkÁ_7°áoù` ÃÛ)üHćd¿~D©ûuÌѯ%Ù£¡%öÃ- ‚Å~ÝÓ…ýâ0"ö+{ÑÙ¯Ÿ®MöÞV†ýPáÀ4Hö{û9?ð×§Ú%øÃ {;)ÓŠ#ᯉ’þPj\•è¯ÏYÁô7A^ô×§]Fô×w'Rýá³L™þžhx¿©ô ÿp»zÄ¿)âÿvùÿ¢¤ÿúTÛ…¥ëL¿=vãjc«â^XÎø7ð¯G#.ã­E€)ò¼óÑ û;£ Ëà7>wú.WC\ž…!ðùà¬"@ØxÕòÔz=9" æ¨í#þµ”\›h¿,#`Oz© `–» `oéG8ݵŀxÒíZ]Ì$;Ïazúˆçb ! ÞŠ$#`»ÂPFÀþ“ú‡‰Lý–tHÙ&ùh(pÒ)ðñ20)ð²È$ „fX$6+áÀçÌ‹c. ÂwÆ‚ —Öwœë †'¯‰W©Îd8xO ÄdýMøÑñ„Ãùƒ&Ú+0¸h‘ÂÀáˆÍ``œÄ&MÁÀá\,ÁÀìþ…ËÄÀZÅxâ@ø<è7âÀæàpsà itäÀ;áÀù ™c ¾ƒÔš!wʰAH…5vçñzý›Ö*Vo ¥rÇ DÌÞÝ%N ùAÚ¿äg»gÈ/òƒ›Ž)ò»\¼Kä7®–Ÿ(ú3݇üPCõ'ÏXµãï™rýFä‹~Óÿª_êjYõCü–(©~kKÉ~Iiò[Ÿˆ¬1IýÓ?ºß1…¡~Õ‡ÏãÚâ¨)Ýû@ýƺßtÔ´îwˆgíï ÙO-D?øE‰],û%‰\d?xX|e¿ä!0ú™$¦ìw}Ð/®‘ý’ï;²ß»xhkaÙoóØ2ùÉßcò[vÖ"?œÊXGô;SÏèw¥.±Ðo¿Ó¯t¿ÚŒî÷Ž${J÷Ûs“F¿íÔÞVäw¥  É4¢}—ÈïÞüÁDö;-nò»ï‚$ù½Ë¸¬È.‘ä¦1Æ‘üÞ}Ý/n¨ê‚‚û‘ýàý§×-ö»“Ã-²ßŸb¿{:ωýÀè&2²ßyÐìw·)êãcwûÝÙ˜ýî©Ñ[ö{?#“Ù¿²€Göƒ³†¬Øï¾œGÒìwOGp;|N!PìwÛÑ)èw(c„U¿Ýç±êwØ[Ѣ߻-‘±ÊÞžOŒþñöŒ°½=çôcoÏáH݀߹΢ßáâbñöœzÝ='¤Óݳ9ÍzÜ=aÈdƒ¼=ßÕSÃӢߞ'nî›^æ¾wðØ#Ô¢ßóøµ9ïüâ_#Ñž¢ßôä³è7•#ƒß¹ç&%úaÝúŠ~ÓPbð{?Ìñ?,ÕZ)~ËãøaŒè“·êwô´ø½7kX”ê7®ˆ|’ý°Q‘R(ÙoÚÁ ~G€HàwOgË~›å€ß;LÚüæ)ðƒ'‚!Nºß\Û üîTž4øÁv%°sœ8ŒÁÏF£ÂºßÅjÝ/B¯u¿#nð{·šã ~I dð»ŸÃo¯ÀïNžž€ßû´Œ¿Ýå¶£þ¡è‹à‡Qq~œ>ï¹âüðÍèy üîT¨7øá³ÖwX1Šý®øPþ‹!òß廜ò_4/³ßáQùoßâ *öƒOšÅ>²ß‘]³Ù/æ€èÉŸ-ýÏ•Â~û€ûÅ föÃÔäcÄ~ïüÊeʼnýÞE}ÿ²ßto4û]“ãÄ~—L#n9äÒÈÒŽÞèwxô›*’ÑïtÙð ßµ;‰~÷â *ôÛ{ú1úmv¿5úmGä<¡ß.i ä—ÔGSÜ?臅ÊZžÀ©Ü ý.â ß¿Ù(€ãgðÜ‚‡V/ûýsò›R³É/Â2Á/NôÑÿö+‚Á“‹ÎlðÃêd”xü~‹¢jðk=.§¿¦lbá¾8­…ûg$ ÷%¹ïvÎéÈïx½¿à7ÑÚà‡„. øý©ÄiSþ+Qi…ÀfÃjü>SLzBà“0ú‚ÀìÁ¢ÿaÎÖÖÿ\)úßæMMô¿Ãu£ÿµx2‘KɳOfQà¹Íè-RàûúÛäÂZ­Ž~Z¹£üw¤¸9å?l½5ÕnvjŽ"#¼æFCˆ8;„ °Rû| ðBaÓóç=ýý÷yk („/Ãý‘ÿîé–&¼S– ئ^`ý/nøfÀrüøø~b"è¼øÑÿÞ%Kž*ÖÿÆ–PA©Û¿ÑÿîÔŽþ‡‚A®U›õwB`ÅÐñOÉøúf’ÿެ'ùï]ižï'ü$¿ú{7êÏOAý'ßO,”×7è/ÞNÅ€-Þñ‘ÿ¶8Yþ ~ö˜æó·„æIþÛíÿmä³È€½Î¯ú÷ît¶oÌÌú×Oç‚"BsP䪰Ï!aõo‰ð“úw¸xž!âÙù@쬥¿Xœ£‚À>·8‚ÀÞ7þIì3²ÌêßXbqb8Þé4$@(ræ4`ŸoVÿ’>ê"¤?ŽŸ}F“Š«ê³.WêÄT]Ô¿¹/·ú7Z˜Ø4+õoÚ(Āخ̤þ%÷·!°')_Ô¿'Á¸Vÿ¦¯Õ¿÷-;‘ØõoúYý»³—CL›Fcÿ0 J­;¦Îâ_Ìsÿîéç¹s~1†À©Ïç˳ú…KÀ)ü†üõÉ4f@܆n@â_Œ›aÀᘇˆÈy%‰N 8†½/…€1ˆO¿Ïè[ñûÌ2fÇÏ%–P·3;~îÑ…€pöW/BÀék|ì(7µ¿¬lÖþfL¯pÄSÚ8#¶€¨Ì( ÖBY "ÀØô%ýM]ÊÒßÂ{’þæêmÏOðŠZD€ó‹²ôwOf¦hpÆ{˜çŠdlw¼2åü9­Gtþì[ÈM˜âàSú‹À¸œIþŸÝqA‘þ¾1X\ô¾ãü9âe*ݯǴaü›.Æ¿Íå’„É÷:ñ¯%^Oø·›àßåHæéýgJã_Bl‚qÚҟ͇ÓýS‰èÜðõþ|çsûz ÿÞcAïÏ- )üÃ-ä,ý…NƒÃq`Æ¿ûñ¹Œðhÿâß;²géïH(`ñ_³šiü{ç^c›ð/Ûêà_\T‚ïè:FÊ_RÀNЩC ÿî+ªžð/ã&ø·„õÙ´ûýFù³¦ø/¾ßá¿"gþkñ#Žô—Gcþk*%ükñz4þÅf*O€Pü׺Ùh‹K!ÿ!3’ØNü7‡D@Ÿéî)Ëj·’jþëwÂõÌñ{6ÿM;‚ù/ñ)íC5…¿ìÀÈ^þ’w`·«© {H1á”þœ ,ÉÓÆäÝÃsùQÿí¿©¬žïØ-¿¦å¨\Îøÿ÷ð»y”Y÷O$OûÍÒr*Fáo¿9Å¿--ÛæzÀ;4ýÓ•[–®Ô´t•–ÙU%‰~>÷í–Ù•›fW³eéêU?téÊ-KWjZºJËìê?(Èù}tï§ùnýgJ+l+¯dˆ:gN5þgå*?÷$¸úÍë±H"Ûúzìßí—¹‰®™«í·bV-#õo¿½—­b,Ö£Ü"9ßÿž]¹aíjä®Ö£ÜÕ¾_µIWnX»š¹«õ¨tubkKWjøt•ƒÒÕrTº\ï×Ò•>]å tµ•®°áËcwç«”®–£Ò¬6×ú¬Ôðé*¥«å¨?;¦_´>^œøNÇÛÿ&j»þQ¢¶ßŒÂßOÔö÷û9QÛtwýÁa?'jû£Ó¶ø-ýN¢¶?±üÞ|ûÛiÿoÿ`ê^ú½Oõ·}ýƒ Y§/,¿ «n¦/¥C;žýùË¿ÖòÜÛ_þ‡÷yÀl»—ÆöW1wÔùïÓ6ÿõßó¯¿íf¿–Æÿò6"¸¥+yÞþã?áúÆÉaøîQÚ†Š«ûŸþ sÉqµ¿ü}·ïÊ~üåΉþ—üëÿúΛø†FûËßæþw8Ó»£ûËÿö×ÿ„CïýŸùñÿõWÇ pùÏïaÛî ª—ÿÏç¾+¡eÿäeÛ¸¾¹ïΙûî¬ÜwíÓÞL{ÇÿYÿ™dwç÷4Ëpÿw\ÂÏaè?i>`úñÝOï¸k7û@ÄPNýV{ Pªz}¯ì¨ rßNNþK}P—Ÿ0Âe^Ö`èÑMQÿÓMëÜÊ6±o¼·j)o˜Ù­“„üúÓiµ8Ê·o§«ŸgY„öí²×ÿÉxÁjQ¬Òû_Ç4lj!‹d/cÚºýîÑàïh±¾\\pÌcÍïĆ 6C"s͆­ÄîoøU¡ ªÊuõ¸ Hß Àj·a)(õ˸*¥‚î(öa«gÌ¥=b†ðXÝØ”zÀ»#su³yĈR8 n(sÏ@Öö†™ëmÊÉà€)V¦Í á^@+óQý…Z"€W Ê{عs«æ( bÉl«ï¶Ž1Œ×P $zè…¯5-â# ZCÁ ûØ2ÔE#¤äÀUzÃ1—íí÷]% Q5ÂixZ9‹ R‡$ÈVv„òˆ”×^µÕ1ÏÄ”¨à;xÊ·W5þ詤ñ¨LÀ~áeÑpl"ÕMårÀƒ@€X½*èé7V·æÉõÁ1H¥R7U©x Ÿ:¢ ‰‡ÜŸ€ýü&“ú¨9ðÁÛþ½9}HêðšÍ*e“j¦ƒ¹´í¼8>qÄÛouÌ­—ë(¾Õ£;%T‡¤]ϪË&Ç󫎱˜Ò™Œ§Þ-ˆËÀÇzœ6ÙuF^Õ›ãd +õQÛsßWgjŽ öÓ*Wz,Z`2Ç%ŸþÂ$‰öú5w|ýøÍ-›ŒóOrèjàM‹õ0àUiªúZa±¬ëûͯõQšR§ªõq‹qnüX‡s¡ÊJ}¬™]J}¬\Üà…ËÕA£müXo£øð±2]= ×Ô!Ns·Ü¢¢Ûžƒ(N5<œ·Ê-·ÈÉqŽ(O…o5ÎAj’c^uÎ:T§Â·Ziú«c¬$€×áà.T§Â· ;¡Z®ZZw¤Óá'êTøVQW€6x¬-øV!üòó@u*|¬HÌ{xè—¿³bA5<õ±âG:Õ¨¥uß›Swú¾‘§B»ðòª<¾V¥ª§þ¶T8è¦ïø0y›¨Nõ^/ôP‰Á«8dìâõ§J†©¡Ó pðÕVmª÷Á>¥×`mz¿T¸M”{ JSáC}v|z[jYÅ!:&ƒc¯~õžPœêýRŸ÷ ©›«VUŒõúÀª4Õ;(QV„{Î9ôßÏ-ÜUiª÷‰àýsGY¥©ƒT˜lᢌ3qÐ ¥Óû>‘|Tð8pÈЮŠSuŒ¼¦ß;•bME¿ú2“5޽“#I‚ß›ÄV¹––*Mõ~§øÄ_ÜyÖšŠ3qS\µ©®VOOµ©žçnj©E=7>¾Ju¬ÉÞŽ^—Ãáˆ{ý¨SéS8Ym»&uóÔªŠSõ2¯¬qÉ4Uq*|§› ¸Wm*|¦(l CŽæït«ýwÕ¦ªCê«Ô'ö*L5êÒÊðÀŸ)„D^F«µ2[s€#g¾Qä¢sK­¨xúޝQ+êã­nU¥Â7:/.'øH1Ç;FU*|¤™dโo4N½'@áñ )‚Èdþè¬HššÍ{5\µšÖµph±Ÿè®0äªIÕªõÑj-…;®¤c)Å@Õ…È^‡:K=þTz»@ÇÔ }#HgêƒËH-ž¦¾Sæ‘Pßû‘ ò}ž }™}U¬å}=¹ú2+†úš}Ñ}^vIÉb¾Ú°["¶Mõψ|ýqh°‰Û¬ýƒ|åÿJ¤òÁ@Ã*aîª.Dâž%|¬YÃßøÆEÅ{¨ß$ˆïaLí)JŒ!? «èyoÔ¼½òÞ¨Äñ+ð'X+à{æM øª€SŠšâ1bˆïj!ñaú‘Šøê©b.‰/3ïÙ’Ÿ¼‡Üôò^ÕUìSñ¾ãM—GÞÃl ²¬…{˜íTr•´÷ <àpfŠZ–P{éqÖ?.KØø9‰^­Kµ±Zq/˨iï©JHr“á²tå¦E{XÕOÇíA­Þì:Ï…éŽ?aN{¿Ézåè\á\VxÝo™ÊxXg5ƒ ðžMã„w£Âyxñµ‡}Á仪=¬^Èwc4ÛÄw(žwñýˆïÊ͆d+¾5¥-|oc¨¡ÖÐѽoßa±à`ÞU=d>ráݨx#µÔ":`á§&¼ÃÝj.ÞUA^°ðǸòŽÑÚ%¾Ã1šÅw¨á,ì"Þ øÔ}ï°À ñn”yaÅ»qwñ®*tÈwUÙ»n^×½àXN xhÑ&[€W¸Ü* ð¿é}ð°fk(À«z¥+à±°ñˆ„Web ¯ÊŠrk+ÂÃæ`¿ÔÂ…4K“ ¯ªå xUúxˆçj%Uƒ€èHÂCܱ °ßÈ©Ë#àUiéÚƒ’ïÆ„ñ݈߀‡â”âFÞ€{¹˜Š„‡_‰ÔEx#+² -Ú°‹ð–;âáa¶oìš'x17l ááÍ Ex0ö‹çxè–ä#ÀC¯zÛ„Ýp¦&ïÁŠ& Žx¯Së¡GM‹b=„q_oÖCºT±1ôà{¸xb¥X¯\Aô#²^E‘*‰zXÒèì¡_áº`Ë0·W†=„…RîèÍ5&®’õʵo[YOGf5±^¯ ›D§b½^r$Iެ‡~JD½w¯‡-ÔCù yÅ ÆJzˆë"H’^e)Zu<4hlôpbYTzËÈyë™ÈyÕ ±‰œ‡¡€8¯Wm¹UÆCÞÄþá¼ q#ïôú¢¸èuK°æ¼\0¯Š¢9Iy8±Ñ”×»` y0Kñäa„kÇ.ÈÃÕJ7åUJÞ‘(¯®VR)¯×„°Rn@B!¯‡Ù y¦·±R®XBQ^ïv\2åUÀ91oºHóºí5¼µb^ï+âu;˜ðð È‰¼z”Û*á¡EZ–¯—ßì x¸2¾¯N’ÞÈwó‰ïzŒ¼åi ðjD­€·^ ¯NÄCxåRÂCx8DàEÀCt²X€‡ëßxDñ‹¤Cñ]eó|Vý×&ê"ßÕÃÿ1ñ7„w=–~ãÝr±Â;-а…w5tÉ„Ä;DPŠ~Äw•ÏUú¯bÏðpÌG¼Ã!’:ExÕ—EÄë16ñz‹FIÆCÃÖ‰…d<ô¢Á Æ[[Èxu&S—ÏW×[Ø]×?€·ô*À«@@ZxK¯"<´Xõ#á¡EC^„‡{Ò$%Ä[[Èx˳ã!@à#âÕ©8X yøæ»7Êeª3Úamèãƒv~A;BŠ•¨Þ '¬±x‡lSûªÞA_à¾ÎòÝÔ ,ßU$çG¾Cš½íÐÀ=†Å;$¹‘Ÿ§Ô;dG—Z'ùn¸|bä;; D¾‘ÙHvufù?’ìêL«z·4ëР­µ¸n¹#rÝr¹âº¹*“ë–^‰uÕ볪wµ²¯â´Á1ÕEÂ4Ô5+ôºöD?ÔeÝ Õu'¤4ÕaÉ>ÒЃ¿ÕqW³@ÊrüêžËŠ¡qüÇ uˆ¨›;=AÝcC]ýÈéê usÏl¨›n¶†:ìHç)¨{’ QP÷4[& uOtXC\ÆR㧨nîfuèÇG¬[N.¬›[mcòõ*V•T÷¤ê î¹ÂH‚º÷j6W¼Ó=3S ‘n@¢{NoÑLtO\2tOäu]”y›ïkUîð¼eW1ÐMº0ÐUdýªÜ ‰x#mÃ<7Å=,¯á®"‘U¸«w"ôÑM¦ Ñ­?Ñ¡²P‘D‡u’oÀH÷äFºá¢s"ºå;ѽýþXh6<pÑÜ¢&‰æ*+'ÑW8‡_™ˆsC:YŽæ"±Ü˜S›XnÌÙZ,7zDoÁZd% ÌÁ‡@ÆÑZ49ç HI[Îé„/¤+‰Š¯QH7²×0ÒA€’Ð,¤“}ä;$9µXG¤UÞrõ϶É&¦Ã1Ân xX­¶€‡àX\b³ùö-à݇oÔr÷è\ðpL[¡n\™U$àÝNlýîòG*ùîý…ÁPú]ü¦-ß]QÓ-ß]þH­Þ]™©¬Þá·ç u8æþ1‘r”æckwW Öî. çw—?£wv机Ý.Z°lw>>B²¶Â+Í÷¶åšeÙîÜŒoTíÎ+h&ÕÙS$Jµ›^ƒVíNCxT»ó4&Z´›ÝHµ;CxVíÞí6Ví°!z>ª*‰ºEªÝ­OªÂntŒd»ŠK`ÏS¶ná*j—)ËvGXزŽXe»ÃpÕî¶~²¨v’¼,ÚmiŽhg‡ž)ÚMö²hw£¬Ùv£Ù-ÍNºcD;ž#Úíq˜‹hеjÿ³U¶“{¢¨nªiVíŽ/Ô•ž¦«v ²j§p§Iuór#ÚÙ”>U»©Ï²Ý$´¿/ÛM§QËvÚ,Û¾ËvÖ ¦nwY¾Žp×üô"ÜY™ÊÝ0ÐDº»‚zÒîÌS»;õ±[»³sÖÔî.`Ñ§µ;{ |Ä;Ž‘ˆw‡¿åˆwR„¦v·…¥¬ÝmæNkwQ¦x×­¡I»Ûìf`énúYZºkö‘jb¬í?)w_×Ì/ú uÓ²þÏd¡‹vWTW¾ûÄãÁU~,l‡ïô+ÛaªTÄÞ™U‰z›d;dþàrhÙÙ¯5'Ù®y E¶›oÁíöng'­n‚;ø´[É#Ý•kÿ wïiœ Wt·o§«a‹îÊyLRñîý•‹ÓŠï*˜­¯Þ™o?M€J¾«ŽP!¾Û7»¢ðvÔ'fP¯B#œ#«c¸Ûâí[sâ#!^s|òºë& ïvFÕä!ÕÐ7"¯;N"ò•fv@r¼pÓ쀼½œQ~LÊ{G‡kØ% ïr².ä!®¯yˆ}áN$yØx|òÚíjgŒÇàs5gÅãÍ=äÝ©Ë〼ÛÕ§w¦´ãñÚždgŠÇ»’.^šÈÐæB=ôÐlQ]í¡Ù8ƒÊE3öð¸h: 6.š®7nMØfttЬBqrÙ¤ƒæÒBÍþ˜mì¡™€{höY'a(-ñ”‡^tùvÐìÞÔóž*°büG­ÀÙA3;i;hN>°ƒæôC¶ƒf¿#žÉA³ŸØä ùÞ•àKþ™¸&)q°éµäž9=áäŸù¾,‰ˆvÐŒo¢ü3—E´{æ5l^°{¦,²qÎÄû–ê(ïÌaÏ©¸gö#ú›Ü3#kÄ=G¾î™“ìŸ9‡¢4±•ÝVÔ{lÞž>šq÷‹æSMM«tå£iKûtÓôè•—&R,Iç“—æ‹N2ÍØKsÚŸ†w8·sÂðçÓKÞÃCžÏgå¼ZƘè'qxït%SÞö¸8Œãð¶òþ19¯¢Ïoè@¼ÍSãðv”÷ 0¼­))›£ðÐÐWÈ{¯åRúAGáNOç(¼ípH¯£ð #~LÌ«Ð=ÎM‰Â;Fâò…·¹G¢ðöã—›&|Ž-ôàO|YÏ{èG½EáZQo¹(% òR_õ» ZºWý®Ny¯ú]µl«~·9/¡nŠÃ«ÐG¢šñv¹ÄÃò)§LÆáÕÔ¾ xˆP³8ïˆä8¼Ów™8¼ƒ¤†wqiTÞÐqx‡fØ„áÍ9 ¯rª®ú"v9\* oær޾懇H¦¾èwO|0‡7·áŠÃÛlÍñ=ݾžŠÃCúD±‘âðàG¤`8âm*Ñ8¼ÝâÃðì^Þ{'xw¢0¼Ù‰Âð¦óžq/ÆÐ„áÁ3O¿Rvyþ„{OÜ{¶S& o;$(Ü{”RÌAxÛ•;á^âŒ{±æ÷¯ ÂÛT@6¸CfbðâòÜÃFVÇ÷âJÜ*›<<ðíÅÊڛƴ‡Uݘö`Á}VW¬!cÚËœaÚƒ­ó\e¼åI÷ò L{qzí9!°7ïÚ°‡ùk[E¼i# ìáɹ{x]Êa‰ýïUÇ[¹aFQ)r¢½çü‰ö#lÚƒá\U¦;Î5áœòÄõ?Ì7rà拏û¼u÷øŽÞÆo¹-¿rܾûÕÿOåw{§äµëÿ:›‘ßí——ÝÆûÓ8“¼œä­Ê"2ÇìïžÜÏ cUA„Óß!Øy€»j×vV>#ÄîŸFª$cCR·S⻋-d†¿MSïKÝèôgëÅÛR•oz‘~s–?÷â²]%¡%Râ½ÑÊ^4*×ûW§xkéø}n•+hÀ#÷fWUu+ÿ‰º¥ÄÊd;Ï‹L_waé©ß”!©_¸Ç|á öøÞxæ±-6’÷ÏÎÐh;«œ'öÂ;“®UÙŒªÆxû¤ö¶TÍð}CÌ_5À.Ø“ó{ñ•¶ªrïÔ ¢ÌÊŽCœãàmyh#w>«—\:óê”S}µÜ޽ïŽL:/V¥©¤CZ*)P%]ãã¿`,ðÒñŸ×¨Êk•ÔL=Ã5É•.úVÅÊ„UÊZn>ü(‘ ˆ¢ê>V"¬m«2FUT¥ò`9ÙÛò0§*´œ­–+HÜ÷ÞW¥Ê®ŒV¹wæÁº6Ó re!{5TpìRønQe­Ò`Ý–€* xœLæÅqÁ4X‡üeßÒ˜ëV@I¥ž¾q 4º-TPC×ù漢v[§SõZ*–}Þ*6~S)ªá‚+~¤J¬ ˆ­É.5¸”Ãþ†_•ù òˆÃþvVâv4ÐÕw/ôåzåôÚO;Tzÿ÷ºÞcvŸü©lû‰Ò3u}( óÛyª~T•y©uÑ‚Á|8«ÞuZXŸŠÃf?¨žÕ™w†üÔº Wf©Zç¨Cø™¢„Ö8ëmê-ÜG}æ3MÑÂwŠÝRíV/ÔÛ™8‡Và*¢Uú3õÑë†|^Ygh ­ ZØ¿û\=½»Ý3—MUÏ’ôLE ªg•ô¼s*¯âYg+!—¢LÏ{)£”™P=«$­wQ£Ë]ÕÏ‚µ2"/5>߯´ú©s£|V;JNêæ¬%õ‰)¶ÊgÝô5¡I©Êg=£Z8M£TÌE%ÿÔ!­VÔ‡³C•#¹–$9U”¨£?«¡¯Ç<Ðç‚>¸jùÌ„>8va`AßH>EC_y{rê+O[î$E}¶q"©o$ ÎÔ‡:\'ŠÐ7¸™ú†?&Cü³ùù™úF"VL}Á¨Ü›ú 2êL„¾'°!æ{âiæCJE>!ßÞ׉ˆ|Ïáa/äCž5 ½F¾g¾W"ßLÎfäK†P#2±ñS1òUbT2´.c:µ³æø fnqE|umB>Ì]²ùæleäÔ¨CH|˜)¯™øÆña-àüâ‹´/âê£1dâ«åv%>T#B‹ø° > |Ûnì1ðmöF ð-§ñañ¿Ä€Z˜å‰ñáW:¹ˆ/{ž6§Z¸24ø°”~¾|CxGàÂÛtv`|ƾ >dKßæLœ¾JKÇC|[9Ýþ0ð9“}x/Û‡ðnH )ÞÃ1Û‡÷àëÁ‰È¼‡”posn2ã^¥/æ§aÜæˆ½öðn7‘¥h/û¦Ð^ܶÒÞ2ÒL{[¦8ÓÞr9¤=¼[¡hèDØÃßüÀD{ãy {O²öfB?ÃÞ“ÈÈ,‹‚½YËÀ°WK2©¬7]ÓÌzXaùV„zhàÃé=‰1é=Ó(Ò›>0&=ä¯c¸ŸHW  H×ëCŠô´å= $1åͦ͜!ï©ù‡L'È;-ó¢¼™Ó”‡íhHyåŸ#@#å¡ß]¬øR.¶éÚHypáÓÞJ”7ókÊ{Ê¥–ZJQUR»jQŽÙHM„¼åây¸º´ÔRú80ÅWÃúÇd< |1ÞãJ f¼¹œòžÓn†<¬Šzt„©¿ÿéLoæ<m8÷•óœؘ·ˆiâ<ä»äÝ›óà†«=®8›z›óP}X[Z’xŠNDz#á÷ÞYq£IÜë›…9i{+ûQßk§2êÍñcÔ«tÿl ¾ÇÉè{呼è{µ[å=YßsÝ"½²9^?Y!{÷Ö÷n%¾žúžý’}o³8fïîT¾¢ï•Uäǯ«À÷Ðà9>Ä ð |ûvþ"³À×Or›>üËWà+‡ú_}ÏSóÔ÷•I޾wn?&éUí&Q‘Ä=x{ì$îíµÉù1Q¯,Ù—Z¨î½£EÒ‰Õ½½JwOÒ{dŒ¸·øÿ˜¨WI'O.uo/Ëà‰zõ«ý£îÁŸ–‘Õ=0決‡=Ç LIÝÛ; öNq3%7Š{;ò}PïxÇÕR¡ª;U,îA ’ûÈzðæ†Û¬·?ª„ÖÛ+9Õ…õ¦:jÖ«jSÖ;~£îAš¥ôdÖÃõÐ"cuo{në}‚=h¾ƒÀ%ØÛ³Q7ìíôß]`o¯îöŽªÓ»°Þ^ùÏLÖÛ‘cƒ,'ÖÛ¢¡X¾ÒäYÃÞÞO댂½½ ÃÞŽ8’º#Ãâ8‰ö7ÚÛ+ @”½=§Q¿}”½*ŒMë¡åü°^yŸób¤ìí%`?b½ÝÜÂz»ƒ^Ãzj”MÖsZˆÀÞ;Ú%®IÚC¥Cš",ímM˜‘ö¶ «ÿ1ioÌP‹´´‡p‹s¥½Âö²‡ñ‹·²·$VÚ«Éñ |JÙC|ß‚•=LÍ@ {›SÜFØ«ZDÄ% {U½¸Da¯J¾³A¸÷¨6‘iQN ðaaƒxÏNÆÁ½dæî9ÿKhïÙÂv¢½…DE{ÍÕ`B{͡ȡ=LíÈ%ÚÃú$Â2îyáîa rŸbÞƒ¡YLj÷ÚmŽï5gv ï%ù»y/‚ð^»¤Cî%Spýƒ{öÐí]M&ÄÐ^sìEhr»T3á¶:Ï÷’¹<¸·üJ¼·ô,âËŽ&Ä—0Ø ßíÂ+A¾&[UˆÏ^¾ÛÙ8|·¦óV½ ííÃ6Ó|"ñi/æ×à^Êl÷’Ò=¸‡ÏPB p/i.‚{÷£í`xoÚ | |)DâK@^ˆïì†*_ªA™øN‡*„ø.Õq ð]á0ªÈ²|Ø^|=«>Ø…wä=GI‡÷Nª‚{W‹ü(Ü;,}÷.ç× î»’y„÷`á[2ïÁ|ñQó’&~òž­ïá½sJsä=ÄHð„{É¢Ü;”Õ‘¸—ª(Á½í‰®(Ü+“é÷/Ü;ÉhF=…؇ôÎþ³”7‰×¤w:J$¨½ öÙ÷õœ-9¨7/7¨çpÙ‰zOÎÖÓôlÖ{©½f½KжQ/¯,¤ç7!=”âÒ³ðü¹Þwò´°]whxž?£á¥”H4¼¥E^Br¢áÁ¶û|7G¤«xóWVñ‚šVñó/1DQñF³©Ü*žó0™ìêG<¢Èní„d7s´ŠìÖCHv•éU:ß‹vëD»*u¬"Z$mFÄ»”jªxÖ´¨xÝæ³ÈxãÖ*·ÊxßMÄ7Y $Ú!ÈȺÑÇèe ífB5£¾ømE»á2W&»åˆ»ÒÏŠ·y‰ÛxCDÅÃ!rÓäb”|ÎQñœz#"ü0¸â¯ˆ·;áST¼Ý›Œ¨x˜DˆWVñ xª©xˆ'ÞVÇÍ)Í*–›{õÛ|’VÛh÷$oµU¼¤;7Ú͸D¡ÝÚ‹T¼¸ÜŠìž$@1Ù=±CìªV–¼J»¬^¦ v)Eg®{RÁ\÷8a¿±nÖöŠ„7!Õ=S"Õ=ɽbª{\ ÃPWÆ–mQðæM êð d?"Ôa ÉÛZP‡W"‰Oñþ™®R?ú QÎL·Èábº1…+1Ý BºåÕ%Ùž¡n¤Ò“¡nÆfê*0÷XÝ5Grê*—Þªß ;éf`£®:Ñ!Dº™~OH‡(!݈C‘nDÙÑ çò6й0膳lšç¿Ý»½9ÉslžÃ!¾\òÜH¦eóÜHr&Ô1ynd±3ÏÍHKñܨ}I‹w?~Ê­®æ»}¯Jþ¡%Ýõnô”t‡ôEŒ{²t‡ø‡‡²œ¤»}»tK‘î†eé®òÆ0ÌNÚݾ;šÆÚÖåMázÔîpy‚7kwøöcíî Å“v÷®ºÜQF»ƒ'1ÅE‰wX3)J»ƒ¼#×MjwÇ¡„qS¾k«vwÄtžÀ<ÿßȼÝþ«ÑÌȼÓò™#ó6‹‰Ìãsýuï¨Mín0ò(ÒÝóHPM`rñj,Ý•ÛÕ xu̱^iQû70²æAœšE»ÛåžíîÑûŸÚ]Ó}OíîHè¸<—ˆ‹t‡\‡Ô´"Ýq®ùu‘î\èaJw3pÐÒë-ÒÝÐÀJ`ÞaÅ4Ò]²"ÝD"Ý!êéǯ‹r›éꦹcŽ!~Eº»©géNu'é®YÌ늿¬”·J{Vîn¿í(wNì8•»‹Õ¢ánèãŽpWe(üºhw›ƒ£Ýaþñë"Ý퟈¼Ýa*ÓGY0Ù«u;EMÍ„ÇEÓÉu"ÛÝL*Ù×F¯H©v™ñ¬Úmµëÿñë¢ÚÝM>±Qíúaá̪6a?~]D»ûpDœ\4ã@5U;oö¦j—ݨvNó¸¨v—¼•£ÚÖ™#ÛmLó8U»q‡ñѬ¢M$8‹v¦Gã%E‹£ñôó|ü4ŸÍ®†ÖíbÐ äÍ;c w‹'åniX¹§vî’¡1ÂÝ L±p‡q@WT w©½2…;ÇD¸ëñÕ³pw¶8TJ¸Cä̱`´¦ýgÝn_Ý4ïÃKµ›¢½4'J¶kÊ È»]V>²8£Ú] ©²jw¯„‡·S¤»©pÄAs %ØÅM)‚ÝuÙ‡SzÝíBmÑëμxëuWBÂâ¢ùXlbç–é¡éÄþVì’^=Œ÷8ñÔìZ¨OšeÖxhöHm’ìöë7šNk7=4]äkzhi‘d·üÊ>šÓ÷S’ÝŠ%»lÿã£ÙŒÌqÒ´3¨;„$œÍótô1¯u[eâ¢éT¨ÓE3Šx|4÷Ÿ$»=Ÿ§5»©L'Í|WqÒ†Š8iÆ|bÙîè¡NÉvØý}ƒð&®X¶K˜c¼4ó,Ûí±ÅM3f-ƒž‹èÄK3®¨ñÒÜ܇/:elWÝŽÎoÓMs:eJ·³ÇÑôÒŒméN%§æ&_r w˜£ëÕ[·›).šÎŸ=]4›¦ËvÛm̶lç*¡<׈h—dߦ¼ùµÅAsjt¥Ùm*U>Ý3ã°`ÎKUˆv(¿ù¬œ7õ‘%¿ÛÀüO’V‰Kû’ÖÇ-kž¶¿ÿ»y”ù×ò»ýö i™éÏ~>Å¿--3ýÙ]>]¹eéJMKWi™]µ“)_—ûvËìÊM³«Ù²tÕUjjvå–¥+5-]¥å?:¿Û NxÝïåwÛÿ~¶Ÿó»ýN¢¶ÿün¿7 F¹A­¨~¾˜W™×£Ü×LÝæ¾ÖÜmîkå¾Ö£Ü×ÌÝæ¾Öämîkå¾Ö£ÒW’·¥¯%{[úÊQék9*}%{[úZÒ·¥¯•¾–£ÒWÒ·¥¯%[úÊQék9*}%[úZ¸¥¯•¾þ…4oHµ ÇšßOóvü£4o¿Œ¿Ÿæíïösš·?èîúƒÃ~NóöG§mÿð“úmš·?³üÞ´ûÛÙÿoÿ`_ú½ö·}ýù4o7rj¿ŸÓ’æí¿üõ?P)Î?Êζ'ÍÛös·÷_çqÿD·7Ô×¼ÿõ„o°Jïäw¾½oöÿ˜ÿùŸ“mí²¾½ÿß}ÿëýšžå¿–þÎÿ¶4þ—¿ûuýãTp÷YU+ ÏHàìýïfj[ôpØÛRþ³=Ç}mÅyý’¬}¿”É‚™‡&öwS[γÎïÛòÀד×â}1•º¿' ñýnúKBÚ][ì¾`Ad%"ïÛ2("¹ÞÊ}¡z&5^öû2:D¤H³÷…ò%IsKý6”Çïˆ×î}=>*uþîÂOÂ…ó<¼@YÛx—Ñ”þ¶Œ*Ï€$ýj9ʹ«ò_’ܵ1`NwšÒï÷ùÁ®½oåÔ–AS:bôù«·ËÊÄ£$q÷Ý*yÎÌ‘óRÁÆ8jWDx[ÊÖUÙ÷wþ þMCFvÞ2Gä5˜¶änÛ&Sú©ç×d²Ñ«ûn{Yó+¤¤ÌäwáÈq¾øø½¸&ºJ^À–N^wƒù°1|A=W-=ý^LÛ˜9 Ù¶Ù€•Y6ñ»õòÒ(ƒ÷Æ“²ñï°ðG£†BÕˆÑ?%ØU7¥¼ï¢!ÝI÷Þ»hc?,ã¾-•ÝçmáOŽÎwp“æÖ~Tɘ‹‡À?·Ò@¤Žî{0óºèË;—u渃ß1Ô.ZÒaJª·¢Â•5 Û¼¸^Y·g"²»Üß:{>ù«J%Ž~†ÆjÚ÷ÎÄU§Z<Çý¨:˜Õ²7fÍóTÏÛö“×Ñ_ò (¾,öóR“Ü=L£tーÊÞ.©çf¾%ìᆯÁÅè>r±¸pQ¯® !rWÇw0F)¢UO†ã^.›y“f]È7uß—¥–…»Ñd̳bÇÚÉOµ &Íâ )ÿÛÚˆ¶_ØÇuÒŽî’9wypŸ ·)œ¸‘¬åPôÇÄÃá£2ï¹dv`Õõ?U&~±Ïßeÿ¤ZtðDÏͯ² º}?Û“¡T%‘5$‰¨¯´B¶ZÍ$û¨Òqê!•JÕoVôáN®Ÿ¨Ë½-Ÿèì‡YÁbõœŠµz'¿Ñ†Gµ]?$ 4(s4¥+•Ý;É”N]SÓÖ§^V)k5~[Ãz8ÕÑPFäÔ„VSy«â#eo¿¨µµªˆu3rîá¯`qûÁ̘uÉUë¦v©øc3Œ¯ ’­jbUMùS·ŠaÚÙÒyLÕ¯f›WÓkAÝ·r˯–±ÓšãÉÉ–G)³šž{ÕĪŒ r†kŠŽ£XZåÛA÷»™ª¡(ÖÎ4P4v¶*Š5?êvœµ¢bÈ1$³UQ¬g ähUë*c¬[*ofíâmUQ,‰Õ1JÝ”ý“‡V 0ïÅÏ»ƒKª«¶ª‰Õ[œÉÈúÜ[•Äj …§ýäܹ¢¦:`«’XkZœ†’X«AtuŒ9§Ïâ %±Æâùت"Ö(sPÍ­ò.®n¤­ b±´ÂÃCz-§)ЪÖS¥giškU‹EŽËÜÕà¸0Ëö¶ª†u/%bªa=RñkѪV›^v Õ°à•1è¥Ñª _DC-¬*Î`—Vµ°X.Zoµ°à”êRÓj-žy µ°îc±Õ¶*†5Ê“LƒÕ°ªìô•[€-q,å]êaÁ+#…Í[ÕÃzªÆ}ßZÕúëW4Ö6Äêô}ã(«zXwuÃMXCE¬V›=o[ÄjŸݵžÂcK#¦ bµò0£º¡ ÖE/4¾Éª‡ÕË[Lƒ õ°à:U嵨ñSËé¸ïÜÔSËi9‡qò©zX£ŽÑcG=¬ý¬cèÝÛª ÖàÉÙs;j9·‹º´ªˆõ”Y Ñ­ b]åý¥w…ŠXWùq§Þª"Ö]‡PUi¨‰uÖÅÐ@Þª$Ö½ø5Å*ç)WlñÐh¡»¡VÃÎc8B«&}Qôù÷½VÓÁj)ÕP‹é0$4TÄzŽjÐGÚY†o$d¨¡"œ§ÿÕ:ëçU^>”ÄBe[,½úU«5^o­Jb]å¦ëeÞd4è­TQ,ú¢ÑBÞúCB‡[•ĺÏ®†’XU˜÷ðWW%±èЦÏþ:c_¼ÊZ•ÄjåyF‰§¡ËÎcôšÊ8Óë&éÜÊ»ðXJþšëá˜Èaôg“ÁM죕~Á>Ô¤àÖ'Øgí"اêJ¾ÓY)B}ç£ï7ÔgÄ@ßm[ ¯9°ÇÐ×›2m˜ùz2™ù$b.$ómu ô¡$éBÐç a>äi¼2œî„­‚>|«œÏ }óƒ1ôabå 5ô-|)èÜΙÂÐq…¡ï•n܆>D"Q¶6õ=ñ;3õAmn©U*õµ }ØÅ#ŠùJÄgƒ˜ï¹pPÌíy'@ ù6î­äs ϶5U©2Ä·Y ñAŸ¿I…">T #³šøàl@&0òA ¿ØoS:ïßöþƒÀQÈׇ ßæ<ÃA¾ªFòA çë6ò¥]¨/YL}ûþA¾ÝIR|؆"äƒ~ϱiäÛ¡5È·×÷õcA¾8¶ ßîtÁA¾ÝYŒ‚|µa' ùö*üÞÃ|)æ={Ó÷öòXý±à^훿¸·)l;¸WÎj<†¸·ø{p5’÷ÊbÁñÞæÃá=xËð9˜÷Ê=ãÃ{H(\?2îmAsãJ nÜ«v#âÛ\L1È·9¯EñêñMȇ„7[„|pÖ¡ÍÇÌ¿Á¦ os)=C8& }›£}èƒ{KCjãq)4÷mηîÛq'aîÛ\ï!Ü—B¹á>T èìGÜW„T»asßVuÖìKö¼`p¨ñGÂ>¶;öé× öÁiç"z û6ù)Oês€I}ð-h?ê;Çã¤>§4œÔ§ÊI}‡²®LêSJý }v œÐ‡é„->¥nœÐ·i,ÐwëW‚¾·¥ n}C^úìŸèsJÛ0_|Â|ï:À†0T*>?1_òà†ùRÖÌ׿köÈ ó%em ÏQ#a¾¹=7ô9©N˜ïr\—™¯Ø äCI7Ñš/†á0æ }§+ã†ú%mêƒÇ¶^Â>è–z â¾Ç™Ü}2Ì·€þŸÊ`AŒ"÷áþBØ÷ÄD"êCº+º†ûžÔž7ø=)oð{œÿÓÜ7«Lšûʽ‚‚¸o>MaßоãgìR ׄ}1ùòúirß3ö=eÉd ±/•E}Ïæ|¯¡¾ñä7¤>$G;Šú°ëã£1õÅ>Ô×í¢êƒ?ßøbŸ2Ÿ„ú8Å^ }r ôu'È ôµ.C™¯í~ža¾Ço×Ìgch¯ÅÒaæëŽ0ó¡:„™ïn9DÌ·‡ÞÄ|N°äKç ßmwš _>[#_ªîùš#PÃ|½yØúZüa }¨ÉÛ>Зzô¾f§@_WÚ¼0_?s9‚¾n[œ¡¯;)a ¯ÛыЗÃ@Ruð½úâè›3¥¡ÏyÂ|¨YÌ{4ó±¬í‚|K/B>—!ñ¹ó?‘.Ì_«Å݃ñíi3ßÌtm曌m²— Þ¯t¾3ôÁ•UðHè;]\+Üw•MéÇä¾kW pF²ú÷¡hïö‘újI ’û®SÑá>CiÊÜw] K ÷]ÈGn÷ák¼?RßåšCA¿ËÔa?\óùa¿Ë"GØÅBH±ßT\Å~‡ÃÂ~dä•ýà}ÍOÁì‡}µ>ŒÑÁ~Å~ˆ†Ûˆhb?øl?­oŠ®†¿£+,ð‡Ö4þ޽I6üAªg þÏÉ?ÇÖ1‚¿ãþî[X'ò;Õeò;”òÃhª/òËM‡ü Vsù0ùU•n¢–È/‚vÈñ‡d/ßáŠ9¿#’–Áï8•]1àw¸¬Rȯüúyr‘%^Á/!Z!¿Ãy#¦à?ô¯àçH¥ ßÞTÚ(è— #£Õ› B?X=¸ÝúÁrr~Ðo§—þŠ~²i‡ýTX~e¿w¶=ù+³ßsèe…ý¸W[ÙϹÒ&ûYDz»’Þ)[–Ù¯å_«à—ÂDf¿BQn4Â~®nö›¥kÌ~I†ö~Z–ûžˆB¿÷&w˜üú®`ðKöˆßÜ0šü¦bô;BqB¿óɯÄ~xÝç‡ý’w ìgoà‰~—@‘ ‹ÆäkëJ~Ò L~‰«ú¹Éoߌ&¿øý’ 9ìŸxÑ–$¿ÇiÙÂ~ÎÑÍïéÚ›Mö“ss$¿'ê‰%¿'º‡%?')‰â—"OQüR>*Šß-ÄŠß´:XñCäQJ‚_Õ-c ¿wà±,ÂD?e«4ù%íTȽöÞ瘬€Ÿ£'÷yN3öe|û’K$Ü—Ìaᾡ¼¾Á> y¾ksßDsª‰ÏÄ}]YØÂ}Ý"¸±oZ„}“«Œ}SËöõ+ž°/õ„&÷~tæ¾ Äæ¾¾Ï~ïo„øuÍ ø5• ÷a‡Àa_EG~°‡HCöe 1õQ3ò%#f[G>(3_bøÂ|Í™ÆÉ|S˜6ó%iL˜¯}x¶Ü/ïUèòøSàk— ÛÀ—””¾©š‡ønŽÓ?Èʃlü|(ï±€Ês“@žË„ñΩ®‰ñj+A®ãaófOBÞý[yeá~Îîœ.qoNG8Ç™3¤ ]¯{%Š®Óϳêzþ £ë½}øézr—ˆª‡©û^]9‘D2ÎTõ†jÐL¾sv€ðݶ=f.ó¬Å<ÆžœñÛ´#g%Þù±àÝVücÅ»¸ûï\wâ‚Ìxryrbk+¿Myrf‡MOÎRŒ,|W^š< žœ—µ¶xrʆ¿xrÞ:óôäT†æéÉÙmr§'çõˇ`zr:§Yøá£ZìÊyýò‘õ°Ñé¾;*Çð„æQ9³'çaŽˆ3'êëþ˜€w¼/™¨fWÎˤWNÅ¿OWμɸr¶[Ž{æ;Ä¡R Š+çP"ŠéÊù˜!¦+§™Æ|w8úâÊ9Ìnqå<­ÛŕӶӕ3ÔeWÎ÷¡S·¶gñgºrcãÇyÿòÑõvWõ‰§óM?Î÷¿åµ)?Îw`ïãÇÙSšý8vbúq¾#­ý8ÓOü8;…©éÉiªéʉègþÈ®œeèý± R»_WN—ž¾œñËΜÏ/+ÜáaÜíÓrå¼ãiWN´|Ø©!ŽÛ!¿ùOÞœ¾¶éÍùö³}T½ÝÚåôæœÇ؛όg·7çuȼoNÛ>¦7箤üÓ›Ó¹’¦¬‡ùÂݭºîì”;u=TÈ”ÒG¸Ë.wzsîîFºžspO]¯=â¢Õ›óþ {•ÓêÇ w.6áîðEp‡·,qài,‰SöæŒë“…=Ùg'ÜÕ€’º&a/i¢ìÝÏd9Ò]ɽ+ÝÁlªíšè. BwÎqfºCæ¨ã#ì¡Øîöuæ¼¼ÕŠ7çæ•ùnrù.)4Ãwhi_iï lL|ƒ»G›Ï…wÈÐ(?+ñݘ§oôÍ®˜òçÃ{ä8tÆ÷ÒCߦý9“Íïóá¶Îþœó%ÙŸ³»ªUü9çÞÜtו´'ˆ•O¥è®)‘r:ç>Ôt×î èsÍ—îÚå3ÙŸ3þ¿¦»DïLÎÝ€ÎO¦»²®Â^é8‹°1EÒªé.î`qç¤%6p—ÜzÓ™óô¸‹3g|%ãÌyÄKT|·coNUNœºÞŸU;s*5ÆôåtNÁéË©ºäSÖ³Ît—üÁ»«+ÞêÊi‘|‡vûGÖ»âÿ-¾ƒKDûºrvø¸r:mé?råÁ!ûr6S—ð.‰û¦/ç·L;sÆårúròáÅ•3·WÎüFx7.ãÉ«G\9eúrÚPWN•¼'çíM€wÝ–çìÈy™ƒGN¦ŸŽœñ#gB9óÚâÈyþ¬ê9Úôãô!ÿDâ¸)ëmõÑ­²ž«ÉMà³@ˆßš¨JÈ—,£«¬·_ä“Çü$¾æØ6#_·×CÏåG¦®w…Τëí÷‡ùàý!:³¬7ÏLUï9ò'U/Ê­™¯,¡òÊ´ªwœŽ˜³ªm#²ÞÓÒeìÛ+³Ëûv§ÍöÅa.ªÞí‹zã¶Ì'ê;6Ù€C}@›ö¡¾)‘˜ú§ÇŠªçÊQSÕ{â.YªÞ³éŽL}'¡JÔ‡ì3:AËH±³¨w+ËY ‹hÿªzNå7U=kØ¡¾ yGø+QÎöñæ¼`Såˆú°”nYïBÌ ¡I؇•s“ï¦t½8)û.ÓøÔõ¬ßûŸ?±¬‡Z]rð¤¬'/šž6çSÓîìÃ|È=£`=kz6-šÞåc¬éÁòe¾»™¬éÙV85½D^FÓ åGÓC‚:Q 4½qék‰¦çD½a¾“[̉}'ª¹Iä#÷·’Ï™ûNÜ#îƒBËWiî;ó„Í}óÜæ¾Ó©bÃ}¸šñÑôÎË‘ªæ¾“s¿óò÷mðƒ¨L{˜Áï<ÍÈ¿SÔGÓ;²ðÃîuˆó~'÷v“üSZ È¯étè<YôC¦¨ûƒ~8Oÿ8tžN7ô+þ£ëÁ gM¡_Ý7%ô;«BÅýN'Ú úag/¨´®÷l?¡2xõo _í­~,è‡bpRèŒ~öwžèçw¾èzr±˜èç-fÐoʃB?¤š“§ÐoÈGzÑõ.Ã`ЯÙ_3|¾ó ß»èYé“®wîÚÑý˜Gò×E×ÛGéÔõàê²êzäsžÑÏèbòs¶ ~‡¡ ~v­÷9­óŒâ³3Od½Ó‚L¢øFÜK ~1öü¶„8-àgMƒ_7ßüâð³MyÆñm×ÇwÚÑÒà线1â *ð{_O[]:§ªdî{²OK$_Ýä7®œ Ü”âÖ+úÉo-¡|.g4ÑO>6“ünCbù6oFËç3–ïñå&–oF÷ýFB …~ý´%Àì×]ÏuÆòµŸÙÏY‚~QzM~ÝubC~Sr$Ÿ–Ù_W-WƒßäÝxtFL3ú%«}ЯÅ!Öè7“ýƒ~SЉK§èýRe:è÷N€ÛO.--ö錳³áoòw|:wsDâøwqO™âÒ©òaA?„EŠ:‰~3rÒ臘La§Ð/…˃~ÍQA¿8œšüPù@’v飼þ—ÔAjX3ÂýÝ_̓|È¿–H®?åa½œ -3Ïš›fF£Ù2ó¬ÊŠý¹V·Ì®Ü4»š-KWUzès×lX:bËÒþ£3¿u^¼÷ºd~û9Õ?Êæ6Ôz·ð›ÿÜìÓg–¸·õø?cf –Ì@¿-ý ŽO~ªŸÆžöðŸcÜÓLîæžÖänêi¤žÖcÜÓLíæžÖÔnêi¤žÖcÒS»¥§%±›{ÊAîi9&=%­[zZÒº¹§äž–cÒS’º¥§%©›{ÊAîi9&=%¥[zZRº¹§äžþ…´oHø4^ªûÿÓ¾ýAÚ·?1uÿí7ÓðïÌÔûÝôçÙûw?ÐßôôçS¾u`ÍËê~3²¸Çèmé„~[åë7-ïØ¿qõîíJÞ\†°ÆcŒr3¦¿cA|¡;cX¿‘ùÇØ•Ñ猪\®LSob*Ä¿vƒï»­ÌLcW Vo{¹Ê"÷?÷ÅoK™éF §¾øÜ]bˆTôÞH…°—M¬î¹]¥!é>oCmJæn¯·»º¶Î½Á0H:wé½!:Ýþlï_½¡œa®¿DÆ{5Eo0 ® fÞ=ñ^x0\õmAɆY®cf((—Wë!Œ{ªËÇF©µYŠ´#‰Cüî3#tpðXéï{† >¹¿÷V‚{¥ÀÖ©[ÅGÀ6W{øÞ{E$wÇviK†ŸwHìLr`GÜŽ”€ ÊäH[å³\ä¤×P„ ÊóðDÓé(ÍsÓþ¡18àb‹rg|c¥¥±n0彎Ýü³>î¥n2ﯾ”Uº0¦Ÿå–Û”>¯Wd cóýÀ쀴·‰ëG‘™¶WúôΖâáb„dâà³EàÓ£2OÈ›„L‹»O™Ž¼ê¥ñŸì´ë702¸¶ÁÙ « @tûSL¶Äw¢Ê̶TEzÕ/¯rrw‡÷øvW23~ÎÚêú¾QV½ŒloÓ3¥`ü@‰Q±Õ{™ãbËQ[>wn4àkǰi™6G9ȳîø@ÐzëujŽ…È®òœ·ÍtT€|yÎ_Üö½C éxî“-°>ò·ïÕ‡’‹-µÅHpºîU'«F(sç¨:Y¡=  e=K>ƒQ…²nF£”–1P)«ŒßMïò¬cŒd¼yj/óŠu5ÏÅu(‡á@©¬úP6£JeµÅ-k TÖéâYuç3ÁÔÉë©£RVÃ]_Ëp_,Çl)q ø»¹/~ª6I¾ëòÁOõÝ´rÌ^ô1æ1õ!£Õ§úȉqT©¬‡ŸüÍs=; –aÁ_A*g0fÍæ£ªeUú—G—ƒrYØ4ªZV[Æ Še•×â®%`T±¬ÆÌ-êåªÅ´ú­EoT±¬Fqãâ¹ïAyW‘QÕ²:~Ož«×rZé[wþjTÙÉr³ã@F¹¬~JÁ®É¤Êe•»Þ wÑ@¹¬¦cj{2ª\Öã<7£je]º©ºï*–õÐ%™§®bY• ‡©.Še=Ž|OU+ëæiøVP,k(Í o©Še)ÎÆòUŽ]nLÿžÚ*zéG|R?v–+á@­¬ú8”ËåmÊÊSOu².^[™bG¥Ãâ¥qD£JÖÉsp”$ó';ûP‘,r(’Õ$Ãép‰,W¡(‘ÕèoÉëf…¬Ã\;ªá¡¼öî;6®z!å±.ž€ÃÕ±5ÔPK•æj;5F…‹Í”FûãrhP¤1”ãæ•:)Ü^vŠs:‹²ÍÓÞ].Ãõ6¿?*·hÉ£†}ª{üë©‹Þ´¡*‰µ—/M5<—3ÁÖM¨"<Õkk3ª²¯™wU]ø ¹1¨Ü?*ã)'^l(•¶³ÓSé’ëáY×Ü4É¡ÖÛàwüÈñ6|þ=~‘ßGíˆÇ#¿gìyÙ©îK·Í.Ñ£n íNvÿsiÝ&½1¢f¡·Ôó ½9`0ð–йÀ[ŠÞÞ‰XûLÃöUÏ o ¼¯¸6œ"È´†ÅÃWGZ›Ü¦µ‘*Ÿ¦5x/q£+XC7´,ÖÏýƒa ç®ÉÛ¸6º‹Ã×*²…ç®UÌ+©ªp ³¨ìfµlo\›¹ÙŒk0Q?j!®•‰z_qm”‰Ç×f,Žp­Fæ¶àfê ×àOªÓ×âå%ZÃuÅ ÖæÝ‘ÕÊÜNŽ*Tƒ'™F$Q­x‘dµz¨+«átEý^oЍ6· Õ†=%Ej£üëŸIje¹çŒCR+YRQZ%à=Ôf’Úˆû¿@m$݇@­.Šdv÷ê@×LPÃ)Ë.PÙ‹Õ†c;…jø_]S‘ÚH±]¡ 7èBµS¶PmØ-R+W»&0©ÍÊŒEjødÝA¡ά–¨†‹¤E]¨†#|ÅjIÒ&T+G¶ Z²ý Õ–Œ¨6:½þt26“Ú»ßPÔ†Im¤¸Im”ExEµ¹§©a7%-H¤†=˜v"µ¹+©Í´á&µ‘ÒµÖÙàYÝWR›#VÚªðÉGi»ü"µ!£º[¸Ø$šgJm·ö˜‹Ò¦}©¥¶¤r‰Öv*ˆAmÆÔªº©ÎDRC‹XX¤V…´…wDµ™Ó¨†R«ÚÄ Õð+ëoXqÍEw)TÃox$µY5j[×U å6L$ƒ?"©=ÙEnÃDÉëµÜ– ‘Û0d¬·…s­·Élõ„¶U]›‰ôÌló1 ÙzŠûÙ–+²-^ÈÖ]rÈĶ4ØêZ%È‘Ø>-µÆ,ýŠØp¨ðVÄÖãé'`ë)i`C‹PĆ?ÛG]ëÓ¹”ĆCÆê"¹4× ‘ž÷ê"¹B^Cƒ- lË!S`£Ç­õµŠ•¦v&}-Uý¢¯¥|WôµåWÒ×n—¨ˆ¾–Ø´l÷“c$°9O¶¶ÙõR ‚ÕäiI…­9G6»¿Ya›~ÓVÙ2™ZeK¹´¨lí¶Ô*[¼QbKõëhlY‹,±µF53„š¯ÄæÎ(lNèmšg-°%áo6¤ âI`ë®"g­;Ÿn¶ªk,wÉ2Btárk Î^\+-°¡~=¹Ø’"$[eÙ`‹¶>,¹I`[~$-N·ØRh$›“õE_C¸m[imÄwÏúZ¬ª–×°$ß«sä´Ü–¼_©\’×àiÈ•TòÚ¸–×â,y &„ñ‘ØÞ•íÒ'‰-–§HlÓ¢o‰ éæõ+ilo?}eµº£guŽ\̺–ØÆÐNÊ ›Ó÷G`‹µ* Û¼`+lïpÛ?®‘Þ¢°=*Šg-&h l^¼­¯¡œõJi3ÁXäµ$A޼öœ¾eËkOÓ…X]{\ô2êÚÓvלÑc&wÑ×§qŠÀö¸†d¶rwãK`C66H_Ct˜t:)l+{Zb{œú;Û£ÄyVؼˆÂöte+lÉè…-Ž£°åâhOŠ<ÐÐò\+ Õ£Ú?ÛãäZ‘ØœTÔ€VÖâUa{â&<«DoÈO ã bs6Ÿ=Ûª®Í³Íî@ãGhöl®³l4{âÁc4Ã꧉MhöÔNz ¶Í:ɬ"5ú"®U]&J]ÔÖˆLÀAýGd䑟cqY•ƒZ¹læ'—=[œ2Èe8Âj]qŒô:EÔ5®B¤²Êì0¤¶UHA W•á÷ӊʪڔ¸î¥²§‚ øû¢²Ç e©Œ%&{HÎä±ÇEW„cOœ „cËEcOƒ cuzþûÝ×wKÃÉ%ô’Åp¼$,ÂøD cuB¡` À¥/„0¶< ÂX¢xÄb8ÀªX±¦*]-±[Åb³èŽXl¾4¢Ø¼K’þæ+ ˆÍì^"±g Ë1â7ébSsqð¦\,ÿD:´kÝ:a-%"¬9‰kt5˜ý©¢XXC².ÚÕ-¬!Á±(L>§=Ƥ«¥ytµ'ñFä2d.²g%Á -ÏâYŨQ‘Ëj×ÚVUmÖL_U5Npæ²çö—a6Cì“üêg8F~‚³Ç%°#«3Ž•’Õœ7%ªÂѶÍê%M„gUÌþf°Ü#Çû´Ï*+ŽÂŠϪ`"ÿ&ž±H%±¨­BoÄ_§üîËßõÇD4Ö¨äÈhU‚öä¯Èh³ñTd´©Z ÑÞnäZ`F›Õ9 i•1hg7„´÷WŽ€¤1?Ð iÕ3obÊjªä³Èjã—ŸTµþK gmÑ©ªaD~Tµ¾Qº˜ªÒû­ªÙ•fªjŽA™²ZááEW+ gu„,Oî"”uµòWù±èjðy7ºQXƒh#ä²°öÈ>…µgX±“°V^ã’Ú(¬"®°†s=+©Õ1çGXÛÜÂZ""¬Fv¶P[+ÕæÇ"­¡…‹IZÛâ/ÒÚ à°´6#¬­M‡kkû¹ÒZu°…(k‡ÊŠMií<¬œYZ;”K{ªk®€2Õµw|R‰Š¼ &òZU¶¶VÆn±™´5ç ¶vzëm­|M«ÅÚ¦)±™´µKÁ¿S[s9Ü©­9¡ýÔÖÞ©ÁRšÄ5×ëâ3ÐüºˆkÈëJõÏâÚu(Œ+êšKÞOu-Ñ‘×n‡QD^s5Ék±žF^»½U³¼v;¾1òÚ{·*"¯5ëŽÑ×f õ5èÒ¼:ëk—CÁ¢¯5åèžúZS™³©¯¡LÅW_sEᩯUœ,[¤¯µaGëkõ§¼v©*Ҕ׬¿OyMåݦºÖüY]kª35Õµî€"«kM1HQ×ðկܶ(?‘×*WVµX^{Ox|åµqJ:³º†|ˆ«Wä¾WÁÎj±¼ÆÔž¿.òÚ<ÆòÚ,³¼ÖUWbÊkå‚Y-–׺ã¦"¯¹räµî§Èk•±µZ$¯]¼y-²BäµîȪÈk(Ÿòš µMyÍÅ>¦¼Ö½ðÈký‘V} ¦“j°¼Ö6ŸÜòZ¢#¯õ®·y æú¯¼–‡}mX@¾6–} w$Cékp=ùF´Áï°,¯ #䵡ÌS^à Í-¬.|6Õµ¡²kQ×`´Q]‹@DuÍåí£®=]"¨Õµç°þ&u­« }Ô5§èºf«wÔµñü²:IÖ7Ê·jumxº§ºöÿ´w69»ÜJrž{šzrPÿ$áUZƒáÐï®ÈˆÈÌ:’Zºòµáz$}<|Y,«È‡™é…=­kËqa\›ûE·Ñ¶6•ŠÚ¿þüýý½Oô¯¿÷~þôÕþƒ÷ó7-ýu‰3¨Ô¼\ÑÎþ§ÅþSŠŒ•ÜX—?ûe²çÿC³5"“Ãï꛽Ïû¿Öÿþ—Tû3}³·òÿú8²ØŽÕþoÖ&cé›5ѳ¿«o¶¤\þç†8Q¯¥Çñ¡x Ö/qhxqã_Æe7‹w'„ÍÒ¸w¯û¿·ÀÇúo6Kaçùö8À dl_cñÌHÛvDÁÍâÎéµð„œß”n÷BpþÞüŠÞ ?÷¹Ùca È"ç‘úBw®þî× »Àˆ¿Q÷Ë„Tý`ðôð“,ÀÖc:éó‚7ʈc]rnn®,Ø·ŒÿàIð[ÀÜ.¼íH/ÉЋÿ|R–7(b¡¡‹»"EMK)º)x¶dŸ+ÔŽ[®ÏA£ñZV˜í[lã‰>"jãáÂLû´Cþwç·Eå°ˆ­°iü¢tø{¿dK§ùiÅ)}˜véWñDpVf%Y *Qà+\ β‚ø‚\ûQ6æµ"IL×( ‡üùÀcÞ¡ ̽w#MØza9`×ê½WYú$ÁæÞ ßDIØ{–YTþ[|íÇ‹œ ­HíÀ6Î8Ž_Îô ëH­º=äõ8cUÔ<8!ÑPF-ÈgÅG`€f²0jñ»¥©0ÿBþF­³Çœ¿DÚ(MTäeš1Éü“ˣ¥:Xxí›C¬¼L°_>ì13=-3#JBpðäÑbÈiðJè6çÈEˆÛÆ{Ø~¸`°ÊóCŸTdfŠ[x~ðž˜iÒæ9õ#˜¯cô([€’wpè'8ä³}x‹Ï¤pœeW9·ýRÉñ7u㥲€½ñbß¶zÇGœŽà{À}Jgˆ)7(xýàX*'šÙõ#X¯ÙŒ&š²2m´ÊD Ì×4¶ªàa&˜CY ÐvðŽ65;–ÞÐSoÒ2-ÚpwŽL¸Ó\|±²=“Y‡Jh¼Þ©Ä£qn·ù®O™¯XÅžÜ!UÏ}ªdý°Ö% xx·Ù†‡èºPŸÜ~è%PJ&ôN¯vL‹³Á½ãñÝæD¬°Ìž¼ƒí‡Ö°©<®P29Å?¹HïÂ:ZÞõwy³ÇPh‡0=à¹ps|.ë”$奿a¿þ¥45¹§¨P;¡dþ6ç¦:a߉àR=]¬qÊÆ£Wk‹3ö¨7LÉî,Ò ÏG·GJ¦š°Ñó›†~¾Çüèí_,9⤽žeܤCà »Ç?žê° â¬}c†(¹oª€J¹oñÌÁ÷r²`l`÷OA¡Ç¦ï)f û¶ì=âAo~¿†jÀxMƒÅäcÒ‹ÊU$‚#åÎ0ÙŽÎY6^í»ò1alø…õéÌæÔUÎ,a-¢‹Õ-ÛD5¤øžÕ¬‚gRÃÜ! ͘Pi¨ã"¥ÍóÈ›¥•$Ÿ)- Äš,Ä4\{h[NNKq@cÚ´§Ÿ1 %_L›)soNûÔ PëͨáB~ÖµÔþ#§EÓzׂÒfmi3äe;¤… Ü× J›¡. J‹dÇÃLr8×– Z~‡JÒzÄ´wÑkuK4Ð' „´JtmH›^˜Íh°Ðû7hXŒ<;ˆh¥hD‹ä[zŠD´™0ç—çÈI<ë7L<‹#OÍ&âêxÏbã®ë’ÏPg3jŸážýÑ# aä|ÔA@ƒÖó#Ùž3¿>D4\ÊW’lÏá-ä‚„ðD{긄€6só(>Ãe|ä³ÖâY¿!òY›ÏfŽÏÐY?wâY*ÿÏÐ;¿ŠÀ³Jpn< =Iu%è mø)“Îf&°4E66ÍJÒÙTÎì(¡üT¯CuÕ«ˆg™ÏÜtq×¥(Bu=ùñž•$’ñl^3‰g1š:%ž¡Ž? ij)<"šE‡amþÔ}¢Yø°è:D³þâÍ¢ŽV¢Y‰:Í"}¼¨+È ï™OIf3¥Mf•…ÞdeË©¯É,3¶Ìf:£ÌÐŒ—R’t@Iâf­û3TÐ.F`?q³Hí'ò .›w¾Ââ²Ìõg.«QsöºzDâ²v³oI¬uKfóÞª†Vgµ`VYç fÓîµæ²ªò– .koޏ,î’H,›‰Gÿ€|™ÉL²’…fÓ:¯d3§í1šeœœÙlyҘ͖>èf3ü=6d³ŒÖ6œ!6lˆÅâ­Ø6í§Åf¨p6+¾m`2¢mŠJ–m×çßF´mOØ"›-Ol[Ñ6ç©· mˆ×bjhEK 2[ÑÐk™½hE³óMlVOIhÖ N¯‡¾é;ô_®ÜªŠÌÚ… fm¸Ef½‘@³Z5ÍjÚ‰ÌZA€Ùpü»Ù,Q„fÕw‘Y{Ê"³V…`ÖÞYÝŽ¸¬©°l³…ì{pi&«ÕÃLÖ^PæP?Ù>Pf*"U¿dÞ¶˜Çú«# «ñ#¡>εfƒÇâ5ÖlÕÝ‹ÇZ³ãøtd,}Oô¨IcíÓ «&Åb™æ"Y¬½b±6©Äb!qXu‹Ö–a˜ëßß.ÀÚË"kŸ[X[·H`}Y"…UǤ°ÒäI k·+ kUÖ>t¤°Ñl³ëää×âE CŸß.iðÔÓ$…Å h| «=uRX[ö…a5¶¤°aåLCXÛý…• URX.ñ‚0üä”áëð:é'—Éô®ƒµI.kÝ„¥¢“¬D„’Áꥃ• ‘¬ÆÀ Öz·¼Lº"úbf$ƒÕËîãËy#Œ`m ·Sëô™ÈŸHŽ™»°ÿx²ÃaZîš:ú3w9pÆØ5‡ý…])hmîJ-sWúà˜»¦…ýÓ{ч˜é½øh_d£XzàØ(–ý £Xûkª×{c™<"a Pdˆ¢•l΂(˜c9“Åò +Y¬üïd#ˉb+ ,"±æ¾(æ´i$kS(–I’ŪU¡Ø*{„Œd逜,†¶]ÆVÖ Æ0ÓÄk4’µ¾X¬vvÁbVÆJÙ²«wšÈj"k›e‘تù/[uÜ,Y:L'ŠE>ÎîÌñ¦4_Åšs¦ŒdÃJ† ñÅR*Ídk¤‘Ov²vº"kp¶(nSP!k02“­ÁZ>ÁZÌØ½[ÌPGsX´Öî\´¯ËÖ-f©àFXC‡uh.Xût†´b²†mCïé—ÖÚëb‹Y}‚…kk³NlšÌÖ¡ü„ÉŒn‹é] ݆]m„n»ö·ÉnŽŽhðÆB›üTÓfæ¬KÉnÞ©ˆÝÂõhkìþX· ¦üOî†n½ÝºÍìytª@›YfŠ³Í }b{Œ;ê#Ë@·Uö¢[Ìvší‚ÜB joä:|ÜÖ¾Ò¡0Ð-BœšéF8ƒÝV™Ô^t[Çž膗Ùhè¶ ôÑÈmE]An(8d r[ét r[NP$pC“m‚PŠÆHp¢¢ä܆+˜‚ÛI%ÃW`ÛÊÌOÂ6\QW ¶­p@fÁm(à0ÛÖ™¬OlCT•ãÙ{v®dÃÀ¶’Œcì†ëjØýÿ;£Ïš±m5—…Ÿáâ—I.Vû.7G†ŸÝµ¤(ü ñ»)-–÷ٜݩâ³Æè30»¢ÏÞµ(CÍbѦ±iÁg™8ƒÏBï¾Sê>|ö”‡"cÏ Ìâø4ŸAØGf-Æž5·ÇžŸ¨m9‰¢BÏÞ6¼â(ô,tÞ:¶-(þØÃ’¡g©\˜¡gãJÃ]Fž%v2ôllåBÉÐ38#¹{6¼ÓгL`•¡gïS(›ÚŒ˜zzv%Ö1òì퉉]‘g™Z²BÏ®‚?…ŸmÅŒ?Ël™†ïlǶšAê/âÏFsûcü™ódüÙÜ3ºÎñg[Î] möàÈ´£|–A&Ž@;€–É%3í‘ %£Ï¬O©à³Ù\!|†®òoÆžáÉ {–È*ö¬N |–#3øìØÞy*úl^¹7UøŽ)m b[í,AñgãþÑÂÏ"~pvb[í$„ÄÖ#û~†O€› b[y˜È¦CT”ÙV'füÙ°o3‰íSƒÑgíÚD¶>4}R`dKüD¶wú=¾ìI^Ëì«Ékµ¦š×ªFVËSP£ZZžÕj‡CV \ýMVsšX£ÚZŽÀJT'0©åcµ˜R&¹NP«7ÉL³ßÄÆ Yx•dÎ#v?MmL%]7ìWµ\çoêÌ`Õ>ÿnÊ^QÐÄtôw;ðóùiD%½õ†\Òš:wæj÷«’Ö”ŠZSYòÏÖ{ß¼ÏKolþ¿Ôû™²‡yù«8öÓ¬‹ùôlŸyøk¶ÕÕÄØÖGsLmµZjë«LƶºžÛú¨Ž©­VKm}µÉÔVSS[]wÌmU-·õQ'S[MSLmuå1·UµÜÖGŸLm5U1µÕµÇÜVÕr[…2µÕtÅÔVWs[UËmý õ±Ð¨}?Žÿ.?ö'òcå3þëo>È¿÷Ñþõw_ØŸ?äðÂþ¦­¿.Aö~Ï"…iÓ +u°ÿ«"d)uö'­Ì‚ôXÈ£¾cóo\{¬-ÿí_þÁ1¨ÇšyÜAm-°æ: ÂGãÚóÀz"›ßUÎPvÛâÎQ²B†¬Îö·†HòÓNV!Ä…Hr{$!øãŒàq1ÉŽs]F‹kÓ¿CL«K‘A ™žgƒG†‹8gvÃrÖpTÖ>óúÉcþÊ;BnôõñºZ dvP7ôké¸[gô‹qÌiÀÚ×µ+H[J ë¢ßnJ1í8kb¶€B=)·½O㾊ÄFÁŠÐ`›°e½@­QÁNžuxLulŒc®èíB$=l÷Øè/¯©%GœÇïÓ£pl dö =JâD¾‚} óÇôñűݧ…eY96Å2'kH{~}¯=âd>ßÞ’IM8)¾½¡ÇŒÐØ™%Ó!·1RǾQÎÒCï&-âY*œö@:ç'·5yß’Á´2JH§|G#¤çc§£ÆyÚ§ð€<þ±™‚‰c§§F¾F–Î3š4Qžyèþ–ÌM¡ä:®;vºjœéžr@ÄxïA¹ÇAo >ÞûŽ€Hqãûw¸ðž‰€Çq0®2¡ä8ÎðãÍ€+”D`e澿Šæ‘ð»Áw\¥Fæx·u÷ «FÅkø:1,”oÅqÐ[‘£¾ÐbÜ®‡÷ ³Æ•Þ'ǹ1°òôYÕqÒYã²È{?áË{æ¡Ø[²Õç9OÆUJKþ-¸VÙÚ½wE}оÞÆUæùÊq>î 5®ßöÒï®°[OùsN…†.õ—nóuׯ¨Ê's)¢9O'ÞGV 7K!Íér\§#+³…4 Üß¿W™áÉÇ¥æÓ:®‡¡•i_~gƒšCûL†z¨®yëfMB|£¿CwHëÏ´T¡$ÞÀ[éÌöwÎ8J†6év¬÷”IëóX‘2éŠÔ"2&±ïòË81éìa 2&臖º)“Žè«ŸëC/ú;Már&í=Lõx×|]þô>“±¤²Bé+Rô@¤u´RCQÍé%¬ŸwzL™„vdE8€ó#FJö¸ò§z Õ AÞ>_F˜³q Šd=Fسq›z+ aóéL´Û Ûög8#ëlKÖŠ Ô•']ê±óÑÇlÒª}Û ç˜ôÔ¸ícqLZµïôV:0)"sõ¹›´kW¬îÁŒI‘&VÞ?éSqÍi›:&#BïÜ´“!¡°áùÚ M Ù·„Q¡©}ú~=Z·°šaËoÁ¤‚žã¢¼*r‰h>,6§{ϱ¤±š ÇRd³w]Çbœh»°âš¯œ1‹*«©Jy(­m{HK2«é4r(±mÉ1œ‚EoçòÃß~ƒ¹TœõVñ¡ä;|n ÍÎe|n§|K0zgPÞ¹QɦÌCWfÐ(Ò~Ý.‰E4#¾Ïa£xÕʈ5ôÎÀìzJ迎YOdJº¢×ês£ ÏíÈ“S‰mïtÚ9wŽVÔû©Ì¶˜ üŸ;CGë¥8wîƒoI¼¾Œ-8wFŽÞúµ|î-ð°§—þR>5wÎA£·wÖçΘÑ^…1£HùÃV‹œ²óœCF‘åEçªû£aÕÔ?Jù”ë9mo'žÄßS#¯o쩤¶¥ìzTó¹§=Áôq<è¬üä¾_ø^;Ó¿ªLVT·Å/ÕA]GŽSÂ:,+†6`”Žvá±îÜ âˆuÈs&’"ÕuÌ.¬;ŸôÐ×ÏÏ\WTsÝ™®Ïæ:ä':>\i½ê. ê®Ý1])»ˆéÂ8vv¦µÔ…‘IŠþ÷W£Å ºQê¹Â:Ô9ÝN`ÝHíQÝHA A]´«øPÝç:ÓÚÞÚ;‰êFé3ëBnëX7b#¤úß_é:*®m‹H®™¡Ñ\7J*$¸n\3×r]” ëFÛ¤ëFÛëF HëP¢Á×}.\׎v£}ÓIv£íîHv£-ˆ »ÑÖ|’ÝhËÑîS'Ðn¤ÆˆÈn”®‡Ð% iŒ‡¾ÓGYh7Úv”hWò}F;üêN1"º5 ²µ%Øõëì†Óµ™ë>K3ÄO–\‡*º!rÝhÛ0‚]ïZpÝh[grÝçGŒˆnû€Ýh»2‚]ë¹n´$¹.í9ÍÈuŸ‚¥¾ùÂĺ~!rêè¥×P%qÉÒ $Å×’g ®ë—¬ûDMÿE`Ýh;nr]¿2¹%âhb]bª¶‚êpè¦×—Q;%2ÝÈ-‚n4L!Ò}J 2,BºOïéFí“ItíB:ø&ЂòÜh{kðÜhÈA ‹ŒŸºOžëœ%•#œëÝ'ϵî“çzßhFlWšû4»ÆOó8‡||„¹ÞW]{|ä¹ñ3ϵ6‚æFî7sí”U0I0×fYnöå>]›Ÿñ ÊõËåF#D¢JÌA´âÖ{@C Ÿ8äÚÔ"ÇÒä¸Þ ½’{+tKnÐŽûÔ cr=¥ÄÈèq\tßW¦oòí,ææ¸Ö 1®Æõi1%·š ×F‰7“âzßHqýM ÅÕÄ Ãµ'F„‹1I¨›ê|b)ãK«÷$¸~e"\ë=®.K€ë'ÀE‰¨A¦¢êš– ò[ûj‘ßzWÉoø¼úpŸK3д=v\·¸öܧ„Á¦w‹ˆàÚ̵{ÂÕcÁÕ8àz œÖÀµáÁõÍ>ÿÄohCÎK¸Þ ®†[‡]—üƒ{ë7 9E ù­ÿˆ§uÞ#~k%µz0ܧUœÖcÄ}ú€ÓÖ,ãMkq­od¸>,„¸œ¸B¸6( ¸öª‹àúC'ÁõçE‚ë÷#oˆv?$8”¨e‘õÉÏ? a–'Ÿá†p•Â7Ÿ²}íüûþÜô½.Ü7ÅY$¸ò«4Áõ\ä‚wI¬EN©Y†9{¦¥].ÝÍoSY–Ë.7S1!n¦Å7S:\ ×ZÃUЬ.#opéši‚k£ ‚«ûÀÍiG/®Ì¿ÉoåqøÖÜÚ„o3Õ-oÈÞj4SôtÞŽñ­‚°oÏk|+ïYãÛi;­q–»ëéá馷 ÷O|C÷Ì’Ä·ÔcH|ë·0¿Z‰o m|›e²¾•_®ñm6 ñ­µøöþm3é­7KzKÙƒ¤· Ý6¾µÛ¾U0·ñ­Âo½3Ä·ŒwJ|Cãù­ {ð[dŒàÚ³ÀµÞˆàRp"®-p3ÅaÍpýWd¸òP7Ä¥œFB\Í$1\À`¸”²H†k7%ˆk· ˆkC#ŠkC#ŒëíãÚàãÚÆY#)®Ý·(®Í“ ¸ÔÂHŒ+s\y¾›ã*^ß73W”9ÏŶ7‚\a\›è"9|¶‡ÙM*[·Ïõ{̵ù(˜ë%ê#ù+Ò\/!͵y#œkA<׿x®d tmè¦CÐèÚœѵ‘ѵÉ&¤k=ÒA£[è>Uˆt½™iÏZA].A]ͤ`ºö¼EumdDuiIªëUˆuík(°kWÙµ;Ùµi#²CVõ4Êžè¾Öøª’ˆíz»„»R1ܵ7Sp×®èn–k€ð®Ý•ð®NÌwpb¾k«’¯½á¼ö¤ðúß©”%zš­(öÔ"ã¼64¼vã3¥ƒ–ºþ\fÊùÙ‰óÚK&Îkóo)ņçÄJ1¡ä8¢^{Þ+…<b½ömìµ*Ú+aÓ^Ñ^)²˜öÚcí•–!i¯îÉ´WjÚëu¤-”?Ó^Ý•i/õ‡÷ê9˜÷ª¾ºs_©¯Þq_퉌|½•Ÿe†Œ|5~f¾ÖŽ ¯Ý• ¯‚Ì }½é åÌ1õÍ´íûj¾ûj)3öÕbfìC‰±U:CùÄÍ}33üj»eò«ÙoòËè £_â`¿ä!£_¡âK÷úõF¿‰Úßýz²ßtRÈ?ÑNKàÃŽìë•ÿÌ2¥qR¿+½ #xÛº¯'fE™øç×LGÌãg“ÝãÜ1 |Ïiúïµ “÷2‹lß[bipB“,uŸ ¸÷ž§Æ½Ö„x/!Ú{ÿÞ»fï‡h÷gÃq®§6÷ÊU¸×›!ïµAñõf€|o L…|N¦”Ä÷¤EŒÄW¡Ø&>ÜÒñ!¾§Ž'E|ÏQ|·kh I|92¾†Û.–¾çLë—€¯÷…À‡EÙu|õ |5¾Ö²€¯„€-wGÌ~ñà½Þ¯ž’¯F¼Wà Üë¿!îµVH{½+¤=tæ{­ÁÞ³§]À^N2³^µ!ÔÚ(£I¯ÞM“^‘^ë›H¯Í‘^Ý@ïÙ < zm\DzýŽÖÑßO“Z1Z‘ôÚ¥Ez½„¤×&ŒH¯M‘^/¹~zMzŸ’¥·@*ÒkãúÜ£@ïÙ ëz¥–`ÐCFZÖÈyÏ–$qHÄ„FÎk͈óèv}8oe¢c…tº$æ¡‚’˜7Ž|n¼ʟkÌCw†˜‡–·ÑÄÀ³}Q^»”(ïS2}vÕ$åô"!åAbácµ+éC^eó5äe’¸„¼v—‚¼Š0åÕà òž™ÛMAžd'ãUIJ¯Ý@@Þûw²!¯õE72µ˜)¯=ZQ^o‡”©íÍ}Œf8ídÊkccÊkW'åµ§+Êkó&(7&Úõž_”‡ïœ Ž”‡:f&R^/!åá)ØðGÊkýåõ–IyÃéÁ y¸ÍaßK‹ eN; òz !¯ – ¯¦„ ¯=)A^õEŒ×Zãµé(Æk“8¯õVŒ×KÈxmðÄxm`ÄxmˆñÚ´ä³èQ)ÏŸmyø­Îly­?‚¼›`¼6‹Äxm Äx­3b¼vSb¼öXÄx½2^ÿïS2<ÏÝ2^¿)2Þ8‹‡Àx5|f¼‘Ñ(f¼þ2Þ§dé’ÖÈx5«Íx9oŒx½"^=#^¯CÄë]žGb#^ Ÿ¯•ñZ+B¼zÞF¼šÅF¼Ö?!^o‡ˆWÓˆ×z(Ä«yLÄËo¾ ¯w†„ ‰ðÚЈðê%3áÕ,1ᵡ0áå÷Ûˆ×n!¯ „/…ŒŒxmÚñz#Ïö]’Œxmô„x¹bþzk‰{tGÃ=Ü´ùns:´´¡íwKw%Ü‹”qÓ%;%Þ›%Ľò„íÅ×ÉÜ›µÑï!:(ÛeúЊ ïÍzȾY_³@>(ÝÙÇ¢«ùRñ­­rd‘ù Ì—@з—&ÇTB>z¶ßó…*Y–„ì~jË€¾UA3ö®›øw'oWÇÝ¥G©âƌ»ó1¸ïVÚB*ðN‡Æ ¼³-OAwž®sçä¡r·y—ˈ»­"åq·¯‚¿Ì:Ô¨îr}p¼]mÿo·çY¢îŽÚ÷8ànÏm¯"îŽúŽ+ä®—0äî-IóÚÁvÕ¬"îŽÚÀ*äî¨5Y!wG-*{fÍ:Œ¹{·1éÍ© ¢Wn–s‡„ nG)D¯rðdÌÝq§efu3r×¢ r÷–|`á‹_»ÞçGŒ¸{ë8(w-.R!w•Õ1w5M{«Ô1æî¸òͬ¦Œ¹C®w¡(Cî«9â?«#îÞÇÌ6JŠ·ÛW¶Áp»Ö(ÃíÐwý„ÑvxK?câÈ9FÛŠØì¦E‘v‡%}hçꌲC¯÷nÆÃ¦Ï11 ³«[U”]냢ìz3Œ²«t¯Œ²«ï£ìZ_eW!­ ²sÒb‡Øá'tÇ´¿#=Ÿc×Kc‡ž<(Ä®õE!vu‹Š°Ë+G|Ýû—ã|`׆@vÇ,“ìŽ‘ÆøºJoëøºšvНC¼ñu­†×e _Gסs ü®Ù·:¢ë2¯ƒë2g³ãëêESx]»aÅ×å€(º®â%]WÙ¢]—z¥]ט]‡:î,£ëÚ(ExB¨Ý;†×µk+¼®…Y+¼®RÑu­3Š®kVt]»´¢ëò¶[‡§lxcl.äÈ>ÆÖA¡T®Ïêïк6S[×"À[‡/†Y“±uõÐZ÷V±W·BëÚX*¶.ÅR3¸®Ý@×½­x¡Sp](×õ: ®«ÑUl¾†DÆÖµïˆbëŽT¨sl]¯ÃØ:\êé0×ë(¸®MD×Õx+¸®7ÂàºÖ=×½uô]Tl]e¬vpݱ*FÑugjC:º®rM;¼Te+ßôr)Kº¢ëj ]÷ù{|ïÀáuäðºcUìãëz ãë0Tö«d|êØðÆøºê°ãë Fd c€] …#ì*8#ìú=0®‰;Ä®•(Æ.M‡ØÕ;Ä®]H!vÄ2=1Ä®ÿŠ1v½cì ‰¨ø>†ÙõÞ Î®â»h×îIv™ÑuMÁ‘v­…Úµç¢P»sÿÉMóS‡±víÆ#֮ݤbíp%Gß1Ö®õF±v½äñ"Z%±ˆö+ûó±ì’lç:ί²ÎMÑ&ɦ’$Ûþ®I²©Îß”d»ÞàZWpIASQÊ’¦§v…¾wk(þîÍ  7¿[÷FC[»_•´fTÔÊ’º$Û꺺&Û ¦í'Td?m{+@üö7JP¬³öÛÇ®s¶âx|§ƃB·_56¶ÕÔØÖGAMmµZjë«ÆÆ¶º‚Ûú(¨©­VKm}ÕØÔVSPS[]AÍmU-·õQcS[MAMmu5·UµÜÖGMm55µÕÔÜVÕr[56µÕÔÔV×Ys[UËmýµ÷³ô~šþ]gíOuÖþ·ù×ß|eïKüëï¿°?}ÿ…ým[ÿ€ÎÚû²&³ö©ýU©´ÿ5ÄÊ?ÿRi×»uÙ®CRiÿò{Riÿòw¥ÒN$7  Ôûç|(èá„R?¢ìwלH €H|ŸxœØ‚DÖŠü;N§¯L?{.¹\Øùæ„’6´Q?âö-Ý·ð‘9»ˆÎµñ n˜ð¯-¦^$–P8†Cy+¿%!ú{;AеÅA2¼€È’w3 ±ó<ö¸¶8†ƒ\÷Ã%8€¶òçd ü‘Þ…#Ž1X‚ƒõ_püƒ ¾×ýy¨Þymxúÿ‚3‘¬³(êQ²ã(ù-¹XaßCÿò€öÛ¡p`ø™ñÚ_(Ýq2ŠصÇ)Üjõª„ú«$Žáðh~htwè]¼%Pcw÷8†Ãí¿[e•à|à].Dríq ÷nÞþÝ,ABÇwízŸ çлg9B[1ýªƒ,`ï¯îË×:6´ ‘"öæØq>ðöëKœ¼[ÅÝwuôP‹KÎ'Ö[ˆB¨$ŽãÞ• QG,AL2ÖÖËý;âó÷òèñK˜­+èÞß`ºD‚ÞÞ‚óô-ÄÜ|K§:Ïà-̼4’u dy*]H„€Ÿ~W/dD‰5kÞ’Á!FÐf”ÜxWÐÊ·$êÞaöç†ýì9óî8¨{oêöðaÆ,Þæ¦:qT÷^i÷ëz_8(Øq>7T'Žê0Äüó¹8G|{ÝqN·ãèð*Y|†·ëžƒu¦¿÷ºâÀÄ_‰ßÎn“7€ÓSÞÀJ6þyÄFG”úÆíã#qe£qJ·ß©Ix=Ðsàà`F§·àò@!¥Ó·ÿ@¸~="$uŠÞÛÏóbV§¸½ÿHëtq\Ô—8§Û™ŽÌë£r± ;MÎ;="fvz§Ðû·JbOýàðAíDr§˜xSí@%ïŒä=!¿Ó;]v¿ÇHðt)ž¢Ïò®°ó¢äÑP1ÇS,—LÎ ‹H]Lóuô Bè%Ö¿»˜è)ævhgòçw‡ÉžøAàP ÝSè€oj%6„q“z˜ðé-y<ÍBÝ ¿:<Ùó‰aõopE‰Î.¨ï4 …óšR¶ŸV–„Y:¾¹ô~»–µ®½…¹˜üé­3³ÎŽ¿õÙfê§w¶bU`A¬§7Hö„¹Ÿâºª6é·‰é—ÙŸ¢#zcW¥ß’œ®Ìÿu4vLµãåÖè®Éåôýñ©:a”ÞaxP‡×àz˸™êý Ô7XFéX­† b1EÆ”C%Ó±º™ê­3´[ÑAÇ[rfÃ×ÊÅž7×ÒT¼‘ê½òÔúqoa•Ž[|\µÂ;jvr-…²‘ZY\K ë}<×ÒóÒª}ïa˜Æ_C~3>±z1îýàZz!˜%ažŽNÅ{û4F‹^o€Öš{ëô%5Öé·‰ÇÝÝ.¤ï€çí÷.yõóömïaŸŽy¶t¥ÈßÉS±ŽÞx ìS@½ÿu:ûó4êjÕ¼™êýïÍó”Ä>i÷¸0 ÔŽµˆ{´›i 0Îz÷Åwœœª„ë(¬ÚºÐÃuÆ\Þ%³@ñKÏ»<Â<½ËÌ|3^ÏÖ#lÓxsy’‚KÆ" » ÏZß§¾áïS»Ã›I b\ôΰNã¡/ëÍ$PøFÈŠxŸaÆŒRÜ̵cÛó¨$ÌÓoÉûl8VL;ÑM-‡yßj?ƒSûâ±it3TôÇí,ÌĉÕß±ŽÂ„ÊK_a ÞO‡hûDæÅÎ𿬟ÖPŽ7_Ô“¶Y¯D—“õvëö°SÙü÷”¢šÝ—{§úlÖËŒoB½æ¹-ÔƒMM ¡ô«uœ-Ö›µŽo©r,ea±^8ÜèuñܶOìE6Ë[­ÜLE˜>e‚=¤€[þMÀÐ(Pǰ¿ÿа·å47ìá‹_eÁU´Z ö"ŸÊ‡÷v<„ïíX„ˆà½c³p•yïØ—YI¼wIOâ½£¶¼â½#«XBÞ€èBĽóÝiÓ.Ü;áUÁÒÞ‰AÿÐÞC¦Ú%í¡à%A{‰[ô'ÚúˆD{»âdö +{ô?°wÝ ¬‚½kYðwE¿£€¬‡½¼¦Yd§ M­O›Ÿ­Xï]g“ÅzWîÉ’õÎ";­O¯dÖƒÀÆO¬wé+Q¬ç/I²žÐT —Á´@oÏôŠô.+ôÝô7JÊÃ>]OQ”÷œ‡7+¢Ž§J–Ïd† ‘¼¿RÇ'têÌÐÙéA‹dò^¶™÷žÃŸóê Áyç6âñ¦ª÷ð#ñiC7?´‡Ï»öå¢=•¸Ýëácóß÷é°«ŽEÖø°öªÓÈu|¸‘„€GK˜Hâ{«‘øpn;ÅP$>ôXà(âCóÜ1i“&¾8 T+$>üf3àñu>|:mäÃa%?RF¾Žôº‘Së:N-ªwA U¸û«dåÑé&"õa”Ít€šXe>ÔW›SžÕøP_3›úzRßýäõÕë!èƒ `ºd}ßTCŽu>"èÃ^LWZqÈy˜ÞméÏ•ÃЇ—÷à]Ú?àýôm4ÆþuÕµ?6ð+ÕhƒßHßo_%þ îC¶ËûfÅÌûfÅ7 üf%8ù!â~k³‚»¸oÕ6J&¾Êék_i±ÚÆW2iä{ïݦBùöÏåßœÙ;,:&ÁX¨ÀY²ÍÉÆg®¬Â¾s³¸oÚø23pÙø¦wNÂ>dSÜ>6¾«Îº…}˜ ÚuûÎP-eÉ!ˆÒÞJØwÎ!nì»20ÈØwåyLšù¦§ ±ïIY•ð\ò}­Œ˜6óå~[àw¥8Í|PzS‚Ðe43ÎøuDnð{§ÿc£WªðCW O&Wî2læË³Ê$?\PW"ù=ïfÃæ8’_ì)¾f¾ÜÇ‘üÒË3­|TI~Øoë&E~ø¾h™7ù §L~Ϻ}†/ò{‡«˜üÂè k¡È3R%"¿u¤íMV¾Ûë᯾½†?<–‘oGVûÍ-;#ö av–ÿÞ¹ÿ5ò=&—p©¹›1þÕpÙÈ›™èŽø7|Æ)üƒK¼L6>¨†ño$¤ÿp¥—Uø‡1×Èÿêx ñO¾Q‰po¸?F>º§£Àôw'E&ýù–ôN‚úðoåNÞü÷¾Q˸'ßüÉÆ7b×ä¿Q óß,s¢øï²‘Dü‡¦UòüëõJþ³ù‚ø—ÇúÆ¿8èL ÿpn"ûœðoø88ñï¤iøþÍ´Ç ÿ@-ÂHá>Q_;ß}éý!—¸;c3ßþãkå+Œ3üExŸJâDR ]Ùðù3¡“áïIü]Ž64ý!ÁuDÓ¤¿VÑßž5„ð ÿfú.ÿî<1þádc$þa¾~ } r‘r%¿ç܉ïÌÒûcü+Kšð/ïÁø‡(þ°9P‰èiT"úC>2"é{-7LúkßÓÄItS¢¿wí×GÁôWÖKÑß3œÄNô÷NP}DO  –¿5Z yÂböíٲwøiÿØúÂl.†û|tb¿:2úO~—-Ñd¿'w·‚¿'šþšÅÍðçã¤?lTGô‡ Mú»C9Z%Ëܱ}¬}¸©£ÓŒˆú[ô‡Ó>Y'Eµ7ýå‘UÒßå4éÏžØIðpóÿpPÇá_uÇø«ÖÇØ )»\àßû i²÷ ‹ë&þ½ßØñÁ¿FÜÆ¿Ü‘$þÁ9ɰ§#Õ]§‰;^’ÿÞè/òѰDôCâÇÞ÷d¤„éÏùIÛô 0ý]>yNú{oêV»¢¿·ëKX©Ô²èïÙ²èï<²Ç¢¿ô2IúƒŠþÎ¥ Á_ŒM~Ó¹{þ"x—%‚¿í±IØ&¿e´)øÓŸ$?°àÇÜWÞ+E~ù´M~Ü ~èÊmÒ;úæÓ䇌Æ&¿Ü¾›ü°ó‰mØŸI®™öªPtÚsNÃøm~aïÎL[A{øàÝÚøÜ‹ÛûàÞY²‚òéÌ\švé„+ƒ¾xréŒ0žø›V¾÷±>.XÒ@G3¢îŽ{sdOàÞ¬háôéœyJš>·—RóÞûœÝ®|:Ë¥Ïf¾PHPI¬L;U¨IÞüÈcC¼wDþ–È­b7¹unÏ!iæÛ³]›ùòx¦Ì|C»¶´ò=i=î=éf¯Nø‹ªŽÌ|ï¨ëÀØf>ø ~í|ïGÐ%Ľx]Ô²ì|È+;YØùÊ/и‡9o³í|gÚ»„{`3qït4DâÞ ½"ûpÆÚ„k%Üûº-}tÊ’qÑÏ@û¶ô…B˜JÒÒg"y&EÛìÈ{WíÁÅ{‹„Xä½+ B½w+æ3áÞu¦A¸×|â„{¸”Œ“{W9. ÷®Ç‡•æ½دYÇõÓ>ÝÀ·é*à+tïí˼‡-·÷0ñ»_g¿/ïcøkî»ód:Í}€¹¯±ˆøš¿ =; YD|wnîÒ³óÌåÄž#¿6$>\ðK|§ýœÊ³3¶šg§yrí±D|wü8 äÙ G"ÙòäÙ9òK"àÃfC—ðÝÓ[…ôìd¸a”„g'ö {_9ó¥g'0J­È³´þ±÷á3{Ú‘“ÄÙÌTB{ß{·ö•kgHÛ²D®õ™µkg¹òÛÞWk/];ό尽[ø½ª)šîS{Íòïô¼¶{gÐÚ½³Î¤ìÞ i™ eîCîÅóaþͯ{g$Õ`I0ÜîÄK6øù&Ó¿smú“g¨y4SÞÓæ{wBœJu|C~¥éÜiç™tîœ #tîL×Útî|lóLçλÌvî|¼Y¶sg~¯Ò¹s:fá^^Û¸·Û:žÎˇKéܹ¦‚Ò¹‡>b·ð.t,ïMqyºwæÀØØ—ïNzw¾½3iÊ»sXÇ%½;‡CwÒ½§B%¹w>:ÙJïN\ñëֺ݉wç¸Ó"'ÚƒïkëÛ†ñÊîØ¶ªÎ]aêŒÜ;ßp¹w†Ž:KäÞ¹6“Žh/ÔU>´w§q-˶½M_sA—p¯Ùèˆ{x‡ý9µ¤^&áĽ=u)LâI”­/OÞ ù¬ÐbäâhNò½ß K%6öÝù+Zûfý½ìúÀwAȇSuF|;§Ö?¢À–¶¾òþÎÒ!7þÝ)aüÛÓ”÷PÜÊâw¶õmú¦¦­ï±ƒØ¯ ´ÛÔ—rζõÕ…;ôÄFÇ¿RÚbÿ^\JkñÊf^{eí áÁÝtÙÚ"ü;Ƭ ¿X¦À36îÿ#÷qò¼êC,ú»Ò±ÚôwÕÖ@ô©µñÚbŠþ°ÿžkß]¶© ¿;2‰ñoYûª7¢¿»¢j„ØÌkßûµ7/ØÚ—›û0ÁU¢™]îvŽéÞÈ>|CR^Ëô‡c3›ò¶ñËÇGú»›5MÆ>[Ù åL`økn‚¿HÒ¯dëƒÓþž Kü5{KÀŽ©®¯±ïÖã¡x$ •±ofÿO( ²DÆ>$Xø¸y>3§¬è‡ôzÞ¢¿§¼YE[7µCú›÷øS–=ùyÎ<Ö·­oO¿>ÛúÞí¿ Hì7Þ‡ ›m}wºÀ¦­Ï8#ô‹lÕ, ùæIòƒ‡ùñ çƒt'?È/é´Gè‡ôφ8¢²zÛD'SÖ`ÿb¡wÆ6 ýF9Í ý"‘¨Œ2õÕ±‡M}-‘"?|-Gò‹là¢Ã0õåù»É/6÷ú Ñud1ú1¿¶Jhê{¬g¶¾k™ I~èïúFk}m}iKµ©¯Ž‘~1­ùÙõ“¶>8 È"Gòi*ô #2 D~còE!ééùøK˜žžŸSšúÎŒ ¤§ç‘fFÙúʼžÆ¾#¯$cßõ¤ Qè7¼i.OOû°¤±/”èY"c߃eWÏ‘‹‹}©ûŸÆ¾ã'ôsÒ‡rõÌye[ß“Ô\=w[ö6;¢f ]=GÉØÖ‡:_WÏbÛúÊý×¶¾ÛÖ€´õ•Ó0m}ï¤Ô'Ö¶>HÆ}ÐïÉ”ÚiìƒÉãkì«•Ä®ž8Öü¸z¡ѱ±/ωmë+µ­*a_[ßVnÚú2.m}÷S¾ŸËÑÃç'°Ñ,±µï*RYû.»l¥µ/-;iíË ¼´öÝ=lsŸÝÓÚWNâ$¿\´ÒÚ ,‘µ¯Ñ¡­}#¡lí+C‰­}Ç¢òõÄÌ××s¿²Ž¬}Øw¶Ø>OÓ¶'kß‚¿1l1J_Ï©óÄ¿iSnZû ™øÁ?ؾ±}O,¦¹¯ì`iî?¾Îže|¤µï<=Ävö<Elí M6•pU…PÉ×Ù³ÂòlíK{YûìnPÖ¾™Xfsß&—Ö´ö~âií;Œš²ö¥)ùo™pÒ×3Ç*­}§Ø$]=ÓÝ2]=ÛŒØÿêW6ö45ÚÕÓ‡w‰וá{¶öùâ4ö]›mpåèé@Ùú2˜&m}½dyMržàœñ…¿ôíNø;—ØðW6bÁ_s ¶Áï:Ó^¹dôÜü·Âä¯oxŸö“ün9ñþúþóøßí˜Aendstream endobj 6 0 obj 167103 endobj 4 0 obj <> /Contents 5 0 R >> endobj 3 0 obj << /Type /Pages /Kids [ 4 0 R ] /Count 1 >> endobj 1 0 obj <> endobj 7 0 obj <>endobj 9 0 obj <> endobj 10 0 obj <> endobj 8 0 obj <> endobj 11 0 obj <>stream 2020-03-05T13:49:10-06:00 2020-03-05T13:49:10-06:00 GL2PS 1.4.0, (C) 1999-2017 C. Geuzaine gl2ps_renderer figureOctave endstream endobj 2 0 obj <>endobj xref 0 12 0000000000 65535 f 0000167420 00000 n 0000169170 00000 n 0000167361 00000 n 0000167210 00000 n 0000000015 00000 n 0000167188 00000 n 0000167485 00000 n 0000167585 00000 n 0000167526 00000 n 0000167555 00000 n 0000167649 00000 n trailer << /Size 12 /Root 1 0 R /Info 2 0 R /ID [] >> startxref 169390 %%EOF blis-0.9.0/docs/graphs/sup/dgemm_rrr_kbl_nt4.png000066400000000000000000006717761422157504600216330ustar00rootroot00000000000000‰PNG  IHDRTjûF¦Â &iCCPiccH‰••gP“YÇïó<é…@B‡PC‘*%€”Z(Ò«¨@èPElˆ¸+Šˆ4EE\•"kE ‹‚tƒ,ʺqQAYpß÷?¼ÿ™{ÏoþsæÞsÏùp ˆƒeÁË{bRºÀÛÉŽÌß(ŒŸ–ÂñôtßÕ»­Ä{ºßÏù®‘iü常¼rù)‚t ìeÖÌJOYá£ËLÿÂgWX°\à2ßXáèyìKο,ú’ãëÍ]~ )úÿ†ÿsïŠT8‚ôبÈl¦OrTzV˜ ’™¶Ò —Ëô$GÅ&D~Sðÿ•ü¥Gf§¯DnrÊ&AltL:ó5204_gñÆëK!FÿÏgE_½äzØs û¾zá•tî@úÑWOm¹¯”|:îð3™ÿz¨• €è@(U  t0–À8à|AØø $ȹ`(E`8ª@-hM œà<¸®ƒÛà.L‚—@Þ‚°¢A2¤é@F²† 7È ‚B¡h( Ê€r¡PT UAuPô tºÝ„¡‡Ð84ý }„˜ÓaXÖ‡Ù0v…}áõp4œ çÀùð^¸®‡OÂðø6< á—ð"Â@”]„p$‰BÈV¤)Gê‘V¤éCî!Bdù€Â h(&Je‰rFù¡ø¨TÔVT1ª uÕêEÝC£D¨Ïh2Z­ƒ¶@óÐèhtº]ŽnD·£¯¡‡Ñ“èw †aaÌ0Θ Lf3¦sÓ†¹ŒÄL`æ°X¬ Vk…õÀ†aÓ±ØJìIì%ìvûGÄ)áŒpޏ`\.WŽkÆ]Ä á¦p xq¼:ÞïÀo—àðÝø;øIüA‚À"X| q„„ B+áaŒð†H$ª͉^ÄXâvbññqœøD%i“¸¤Ri/é8é2é!é ™LÖ Û’ƒÉéä½ä&òUòSò{1š˜žO,Bl›XµX‡ØØ+ ž¢NáP6Pr(å”3”;”Yq¼¸†8WJ)Hq¤"¥öHµJ IÍKËIÛJGJJ·IK”aÊ8ÈÄËì—é”y"‹’Õ–õ’Í’="{MvVŽ.g)Ç—+”;-÷H–×–÷–ß,L¾_~NAQÁI!E¡RáªÂ¬"CÑV1N±Lñ¢âŒMÉZ)V©Lé’Ò ¦$“ÃL`V0{™"eyegå å:åå–ŠŸJžJ›ÊU‚*[5JµLµGU¤¦¤æ®–«Ö¢öH¯ÎVQ?¤Þ§>¯ÁÒÐØ­Ñ©1Í’fñX9¬Ö˜&YÓF3U³^ó¾F‹­¯uXë®6¬m¢£]­}GÖ1Õ‰Õ9¬3¸ ½Ê|UÒªúU£º$]Žn¦n‹î¸CÏM/O¯Sš~°þ~ý>ýÏ&   ©†.†y†Ý†iñªî¯&¯v\½mu×êׯ:Æ‘ÆGŒ˜ÐLÜMv›ô˜|253˜¶šÎ˜©™…šÕ˜²élOv1û†9ÚÜÎ|›ùyó¦é§-þ²ÔµŒ·l¶œ^ÃZ¹¦aÍ„•ŠU˜U•Кij}ÔZh£lfSoóÌVÕ6¶ÑvУʼnãœä¼²3°صÛÍs-¸[¸—í{'ûBûªƒŸC•ÃSGÇhÇG‘“‰Óf§ËÎhgWçýΣ<Ÿ×Ĺ˜¹lqéu%¹ú¸V¹>sÓv¸u»Ãî.îÜÇÖª¯MZÛé—ˆÿ2Â6¢,b&Ò*²4r*Ê*ª4j:Ú*ú@ôLŒMLyÌl,7¶*öuœs\mÜ|¼Güñø¥„€„¶D\bhâ¹$jR|Ro²brvò`ŠNJAŠ0Õ"õ`ªHà*hLƒÒÖ§u¥Ó—?Åþ ÍŒ]ã™Ö™Õ™ï³ü³ÎdKd'e÷oÒÞ´gÓTŽcÎO›Q›ù›{r•swäŽoál©Û m ßÚ³Mu[þ¶ÉíNÛOì ìˆßñ[žA^iÞÛ;»óò·çOìrÚÕR V (Ým¹»öÔ±? ìY½§rÏçˆÂ[EEåE‹Åüâ[?þXñãÒÞ¨½%¦%Göaö%íÙo³ÿD©DiNéÄ÷e̲²·7¼Yn\^{ˆp(ã°Â­¢«R­r_åbULÕpµ]u[|ÍžšùÇ‡ŽØi­U¨-ªýx4öèƒ:§ºŽzúòc˜c™Çž7ø7ôýÄþ©©Q¶±¨ñÓñ¤ãÂÞ'z›Ìšššå›KZà–Œ–™“!'ïþlÿsW«nk]£­è8•qêÅ/¡¿Œœv=Ýs†}¦õ¬úÙšvZ{aÔ±©CÔÓ)ì ê<çr®§Û²»ýW½_ŸW>_}AòBÉEÂÅü‹K—r.Í]N¹<{%úÊDÏÆžÇW¯Þïõê¸æzíÆuÇëWû8}—nXÝ8Óâæ¹[ì[·Mowô›ô·ÿfò[û€é@dz;]wÍïv®¼8d3tåžý½ë÷y÷o¯ñy02*|ñ`úaÂÃ×2-<Þ>†+|"þ¤ü©üÓúßµ~oš /ŒÛ÷?óyöx‚?ñò´?'󟓟—O)M5MMŸŸqœ¹ûb݋ɗ)/f þ”ø³æ•櫳ÙþÕ/ M¾¼^ú»øÌ›ãoßöÌyÎ=}—øna¾ð½ÌûØú>|œZÈZÄ.V|ÒúÔýÙõóØRâÒÒ?B,¾“sMT cHRMz&€„ú€èu0ê`:˜pœºQ<bKGDÿÿÿ ½§“ oFFsF×j`` pHYsNNÆÊ/¥tIMEä&>(Ê vpAg´¨“ÁQè€IDATxÚì½{˜e™÷ÿ §$fR0ŽÄÎ3(R ºí ¢Õ’€‚æµz< $»¦Z÷• ø­Z}A§*™w•ew¥+î]\™.ÍŠÛ¥ lFÞÐ%2œ§$41q*3` œú÷ÇÓOuuOwO÷LÏôaîÏuõ5=uꧪû®ç®û¸$—Ëå@AAAAAATäf€ ‚ ‚ ‚ ‚ ‚ ¢Õ!‡ AAAAAAÄ C… ‚ ‚ ‚ ‚ ‚ bÈ¡BAAAAA1äP!‚ ‚ ‚ ‚ ‚ ‚˜r¨AAAAAAÌ9T‚ ‚ ‚ ‚ ‚ ‚ f`Q:T,Ë‚ã8Í‘Ç÷}8Ž×uç|,Ïó`YV³O‰˜%$›çyeešä³½ yìlj‘Gß÷áy^ÅýÇ©¸žX8HV;ƒ¹Î•ä•dµ¹|¶|îh.í4H^[‹ÙÊk¹ù”žCÛ’ËÎ¥ÝårQ:TlÛ&l\×E__LÓD<G"‘˜Óñ<σmÛÍ>-b–l¶?º®#‰”•i’Ïö‚ä±³©EMÓ,«äZ–Èy$ikE¸ Ym1w–“W’ÕæCòÙ:4ú¹ ¹´Ó ymf+¯•æSzm_H.;—v—ËEéP!Z‡x<MÓN§‘Édà8N[ A,f<σišÈd2L[–Õ°(@‚ ˲ÇašfÙõº®#•J!N#N#‘HPt-AÌ’¹ÎÕä•d• ,ôs'Í¥1{f#¯ô,JÄB²(*¶m£¯¯K–,A"‘€ïûÁ:îùîéé®ëÐu½è†ëº.âñ8–,Y‚H$ÜÄc±,ËBOOzzz`Yt]GOOúúúŠ<¨õl;üXá1W[^ëñzzz‚q”.+·M­Ç¬v¾ŽãÀ÷}hšãããP¥ê9¹®|Wü˜•"zøvõîG, Õdh/ù¬&ƒ’ÏZäµÖãU;×Zd¥Ü9ñïO„à¯(ŠÓ¾WNø;%Ùl>s‘ÇJ²,yœ¯¹r¶òX¯\…çKI’ ª*$Iš¶ã8²,ÛJ’D‘c ͵³Qsg­ç»Ðs'§’¼’¬6šKk;æBÏ¥3=wV:'šK;²Í|¼…žKÙÛ‰ê™OÉNÔº\Î|¼fØog’“Ei¿Íu8ããã99Ã0r¹\.§iZ@NÓ´ÜÄÄDN„\*•ÊMLLäTUÍÈ¥Óé\.— Öó}ÓétN„à˜š¦år¹\Î0ŒiŸ!Ër0†z¶ 9UUs¹L&“!—N§+.¯åx²,çÒétnbb¢ì²rÛÌtÌZÎ7™LædYþ*ŠR4æJçTz¾ü{áëøñUUÍI’Œ¹Ú~ÄÂSM6s¹\ÛÉg5l”|Ö"¯3¯–s­EV*“ªª9EQrÉd2§(JÑõ«$Ÿ$›Íg.òXMs¹úd¬åq¾æÊÙÊ£išU÷«6_rdYÆÈ1 cÚ÷Pn;b~ ¹sáçÎZÏw¡çÎRJådu᡹´uçÒ™ž;+Í¥ Ù‰f>^3æÒ\növ¢\.Wq>%;Q{@r9óñše¿IN£ý¶ã*š¦åTU-Z&ŠbNÓ´iŠ ÿññ/(™Læ$I*ÚWUÕ@¨9ü‹ÿ_*µn;Š„"üWny-ÇãŠz¥e嶙阵œ/¿Ž|‚äÿ‡Ê¤rß3?¾ªª9AŠö¯¶±ðT“Í\.×vòYM%ŸµÈëLÇ«å\k‘•Jç¤iZð=Š¢X´O%ù$Ùl>s‘Çj²˜ËÕ'cí,ó5WÎVMÓ¬º_µù2|œRãN¹‰ð÷MÌ/4w.üÜYëù.ôÜYJ©¼’¬.<4—¶î\:Ósg¥s¢¹´s!;ÑÌÇkÆ\Ê¿›Ù؉ø¾åæS²µ$—3¯YöÛ™äd1Úo;¾ä—ëºAÊGE,%0œ‚[ºçyp]K–, ^­bT:Ι–Ï¿Õ–•Û¦ˆ¢ˆT*Y–aTU-ºÆ•Ω4uZ„ æl8­­´^fµýˆ…¥šlí)ŸÕd°QòY‹¼6‚Zd¥ôœ~úӟ¶md2†ññq¸®[T;º’|’l6—¹Èc+ÊbéëYW™äq¾æÊÙÈc-ûU›/ë¹v$« ͵±XæÎj¬.<4—ÖF³æÒ™ž;+Í¥ Ù‰f¦Ys)?n½v"˲ªÎ§d'j}H.g¦™öÛ™äd±Ùo;Þ¡R®fi˜j_¯kšc™<ÁË0ŒfŸVG Ëò4«õ¦Rú½…ë*J’„d2 MÓ¦Õ\¬¶±°Ì$›Ég3™¬ìÝ»¢(ɱ,Ë5É'Éfs™‹<’,Î?³•™ö«6_VB’¤²Ç/Å(†æÎÖf¡çÎj¬.<4—¶.óõÜ |¶+d'j]f+¯žçUOÉNÔú\¶6óñLÚÎrÙñQaYVpá]× <`Š¢ ¯LkØ£( \× ¼d¾ï£¯¯¯¨A 1{¸"¾¾¶mפHzž|_|?ÞÔO š¦AÅ¢¿jû K5ÙH>›ÍldåÔSO…çyÁwÆ÷ +µ•ä“d³¹ÌEIçŸÙÊÇLûU›/+ÁLà =Ï+jìKÌ4w¶6 =wVƒdu᡹´u™¯çN€ä³]!;Që2[yåûUšOÉNÔú\¶6óñLÚÎryX³0ߨª ×uÑ××Ü`¹¢"IEA$(ŠÓ¼]¢(BÓ4Äb±`_Y–IÑi‚ À0 D"Ȳ\_UUgÜWE$ ˆ¢D"hš6í¦ÊÏ¿³Jû O5ÙH>›ÍldåüóÏǾ}ûоSI’*îÇåó¤“N"Ùl2s‘G’Åùg¶òQÏ~áùr¦è0Ã0Ç!I\×…a³N['êƒæÎÖf!çN’ÕÖƒæÒÖe>ž;ËAòÙ>¨u™­¼rƒ{¹ù”ìDíÉekÓègÒv—Ë%ùæ1ëºAÍ=®¨ø¾¤ù¾Y–±dÉLLLL«iëyA¨)•›¨z¯¯ã80MétŽãÌû~ÄüRN6’Ïf2WYY(™&Ï\ä‘dq~hÕ9ߢ(R‰’&@sgë±Ðsg½Ç%Y]8h.m]ZMG%ùl>d'j]f{}[MΉú!¹l=ú™´ä²ã3T8å.¼ïûˆÅbH¥R$ º®—­×¸ ŽçyU&ɲ\wjS£9cæv}g›îÕJib‹J7ÅN–Ïv÷ð~õÒ ™&Ã\äq¡Œ$õ3rEÆŸæBsçÜ7_ÇäûÕË|}'$« O«Ï¥í"KóqÌVÓQI>›Ù‰æ~ÌV³µšœõCr9÷cΗ\ò}Ûa¿ùfÑ8TÊ!Š"’ÉdP£ME¤R©¦Œ…7Pª6Öfs>Æ8fë™lE&Q™N–ÏV—÷…–’ÍÖ‡ä±yc¤9¨’Õæ‘dŽ˜‰V‘ÏV—¥ù<ælÆ@r½øhYÚC¶ZAVçÉy{@rÙ\¹\ègÒvËESò‹ ‚ ‚ ‚ ‚ ‚ b¶ÒìAAAAAA´:äP!‚ ‚ ‚ ‚ ‚ ‚˜r¨AAAAAAÌ9T‚ ‚ ‚ ‚ ‚ ‚ fàÐÏþóŸ_èšš‚뺘ššÂñÇ_´.›Íbll ÐÝÝÝìëC‹Šj² |D3!ù$ˆÖ…t[‚hMhî$ˆÖ…ä“ ZÒm ¢: îPúuëðÄO`dd>ú(.¼ðBÀÈÈ6mÚ„'žx7Üpº»»100ÐìkD‹‚j² |D3!ù$ˆÖ…t[‚hMhî$ˆÖ…ä“ ZÒm bf–är¹ÜB~ ,ËÄÆ155…uëÖahhkÖ¬Á¹çž‹ë¯¿Ñh4`ÇqÐÛÛ[ñxgŸ}6ÞøÆ76û:Ιýû÷cÙ²eX¶lY³‡2göíÛ‡•+W6{ v»wïÆÆñ| ÙCžÕd@Ýòù™Ï|¿øÅ/pê©§6ûÔæL§ü¦ã}fll ;wîlöpçL£åóMozÎ<óÌfŸÖœyþùçñüóÏcÅŠÍÊœé”ûL­ßÉää$zzzð­o}«ÙCž3ÖmÏ;ï<ô÷÷7û´æÌbœsZZ¿ÒmËËç÷¾÷=lÙ²'tR³OmÎ,¶ßt;@ºíÜäóío{GÈ&é¶­鶯۶ú\Ò÷…V—÷yÑms ÈŽ;r‘H¤âºw¼ãEËÞûÞ÷æn¹å–ªÇ<÷Üsòæë®».·cÇŽf£!¬_¿¾ÙCXÐóè„ﮚlòõõÊç–-[rŠ¢4ûÔB§ü¦;á·Ê©õ;é„ïn>ä³SæÎ;vä®»îºf£!tÂo5—«ý;é”ïn>tÛNù-,Æ9§Õ©õ;é„ïn>æÎN¹oår‹ï7Ýn[¼¾^ùì„ëÂÏî3­é¶Åë:Q·mõ¹¤~[‹ñ;>l!=BÙlÁöíÛÑÕÕ…ÁÁÁÀ³YêÑìîîF6›­zÌ¥K—bÆ غuëBžJÃì˜ÚƒCCCÍ‚dž °{÷nD£ÑfwNT“M³’ÏÕ«WãÉ'ŸÄððpÛÿ&Ú}üœÅtŸÃðð0öíÛ×ì¡Î™ùÏcŽ96lÀš5k088ØìSœ5U£¡Ú‰N¹ÏÔòŒŒŒ`dd¤#2çC·Ý½{7é¶-F§Èg-ß é¶Õåó¶ÛnÐþ¿‰v?g1Ýg¸n»{÷îfuÎ̇|îÛ·tÛ£Sî3¤Û6N·jÉL•VŸKÚá¾ÐÊò><<ŒÛn»­áºí‚;TFGGÑÕÕ…7btt6l€ã8˜œœœ¶}-?˜“O>¹í8k=×v¡oóu[·nÅððp³‡:gªÉfooï¬äóÈ#Ä¥—^ÚÒ7ÖZé”ßôbºÏô÷÷cë֭ذaC³‡:gæC>_ûÚ×vÄÜÙÕÕ…®®®f£!tÊ}¦–ïdpp½½½möpçÌ|è¶'tRGÈçbšsÚ…Z¾Òm«sñÅ“nÛB,¦û é¶Õ¿ë•+WvÄÜIºmëAºmçë¶­>—´Ã}¡•å}¾ô¶u¨ì‡zýõ×¢Ñ(¦¦¦022RÖ˜Íf[úK!ˆN¢’l ‘|D“!ù$ˆÖ…t[‚hMhî$ˆÖ…ä“ ZÒm bfYÈ‹F£Ó¼jüÿþþþiib“““-ï)$ˆN šl$ŸÑLH> ¢u!Ý– Zš; ¢u!ù$ˆÖ…t[‚¨u¨ ›Íbll 055…íÛ·£··Ñh“““AŠÜØØ²Ù,Ö®]ÛìkDO5Ù@òIM„ä“ ZÒm ¢5¡¹“ Z’O‚h]H·%ˆÚXÐ’_]]]ºuëF‘ÍfFƒ¦aCCCØ´i°k×. µ|8‚èf’M€ä“ šÉ'A´.¤ÛDkBs'A´.$ŸѺnKµ±à=T¡ìîî.ªµ^×ÛÛKic±€T“ÍÒõ$Ÿ±°|DëBº-A´&4wDëBòI­ é¶13 îPPUèH ¢yÌ$$ŸÑ ¢u!Ý– Zš; ¢u!ù$ˆÖ…t[‚¨Î‚öP!‚ ‚ ‚ ‚ ‚ ‚hGš’¡BAAAADû¡ëzÑÿ¢(BQ‚¬WU¢(–Ýß²,ˆ¢Y–®ë¶m€ PU58AD«A*AAAAAÔ„išp®ëÂu]X–…¾¾>xž¬çïËaÛ6Ç ¶ÅbÁ:ÇqŠŽEÑjP† AAAAA5cFa±X –eÁ0ŒºŽ£ë:Òétѱ‰LÓD2™löiALƒ2T‚ ‚ ‚ ‚ ‚˜5•Ê{ÍMÓ ªjÙuº®£¯¯K–,A<‡ïûXÙ°p¦ ßöæ›o†®ëÐu===èëëƒeY;\A´1”¡BAAAAD͸®¼wŽã N×}UUÇ¡( $I‚¢(3¼×J:† A&‹að}?(#Þ¾§§¦iBUUŒÃu]Äãñ¢.Aõ@‚ ‚ ‚ ‚ ‚h<ÏkzA IRÅõá>(ž-RÉd²,Ãq˜¦‰D"Y–aÆ´Ï_AJ¥j>^>L–e¨ª Û¶É¡BĬ ‡ AAAAA´žçMsV,4¢(Vu¨”öP±, ±X u–¢(P%8÷D"x<ŽñññiÛ¹®‹¾¾¾ ÃDÓ´Ë•ž‡ E6Aõ@‚ ‚ ‚ ‚ ‚hdYn»ì QëÎPqº®#“ÉGÓ´iýP8†aÀ0 8Ž˲H$*–ã-¥Ù>³É¤!‚àPSz‚ ‚ ‚ ‚ ‚ f…ïû³*¡%Š"\×Ö$Þqœ²ÇÒu=p´È² EQg‰ ÁXÖ?%ìPá?³+A‡2T‚ ‚ ‚ ‚ ‚¨™Ò Þ÷¤ÚúÒLQ‘L&¡ë:,Ë‚ ¤\UU‰D‰D‚²]ü3%I‚$IˆD"A 0^êKE$ ˆ¢Ïó‚,‚ ˆÙ°à•l6‹l6[´l``]]]Eë{{{ÑÛÛÛìëC‹†™d3¼ É'A,,$ŸѺnK­ ÍѺ|¶?¹\nNëÃŽUU¡ªjA"BÅÞ-¢(bbb"ØV’¤ 32™L°Žg 8ŽQ‘N§á8NÕã¤ÛD-,¸CexxÛ·o/Z¶uëVD£QŒŒŒ`xxصk†††088ØìkD‹‚j² €ä“ šÉ'A´.¤ÛDkBs'A´.$ŸD9ê)ÁUmÛÙ®#¤ÛÄÌ,¸Cejjªh¢ 3<<Œë¯¿ÑhcccX·n¢Ñ(y< b¨&›É'A4’O‚h]H·%ˆÖ„æN‚h]H>‰…„2Rêƒt[‚˜™oJ?::ZVÐFGGÑÝÝl?úûû1::ÚìkD‹‚J²Éב|Dó ù$ˆÖ…t[‚hMhî$ˆÖ…ä“XH$I*êíBT‡t[‚˜™u¨LMM®½öZœvÚi8÷Üs122›&°ÝÝÝÓêö•²{÷nlذa!Oƒ 6lØ€Ûn»­ÙØ3Õd˜½|ÞvÛmnö鋱±1lذûöíköPæÌ|Èç¾}û°aÆ¢ãÄBÁK<ýôÓÍÊœ!Ý–è4H·%Ý–hM¸n»{÷îfeÎnKt¤ÛÖ¦ÛŽ5ûôˆEÈððð¼è¶³.ù555…]»v¡»»ýýý5í“ÍfF±qãFlݺ£££Ø´iz{{1999mûZRÆN:é$lݺµá† jaëÖ­ñPUM6£Ñè¬åóâ‹/ÆÐÐP³OX„ô÷÷cëÖ­a”œù\¹r%ÍDÓDoooGD³‘nKt¤ÛV‡t[¢YnKº-Ѻn[Òm‰f2_zÛ¬*ÃÃÃØ²e ‚víµ×âú믯ê\áJ'bíÚµAÚX)Ùl¶fg A³§šlF£Q’O‚h"$ŸѺnK­ ÍѺ|vº®ý/Š"E ÁzUU!ŠbÙý-Ë‚(ŠA“x×uaÛ6ÖóDUÕàXÄÂAºmãq¾ øS€¢–%€,ŠÒìѳ¥î’_Û·oÇÈȶnÝY4Åàà Ö¯_¤‡•#›ÍNKñêêêÀ„¶4Mlrr’ÄPM6’O‚h&$ŸѺnK­ ÍѺ|v¦iÂq¸® ×uaYúúúày^°ž¿/‡mÛp'Ø6‹ëÇ):±pn[;žXàûìÿx0M ¼îÍùínÌoºÀEÖ‘È“Xpêv¨ŒŽŽbpp0hBÄÙ¸q#z{{±k×®ªûnÚ´)pºLMMaûöíE© ¢u!Ý– Zš; ¢u!ùì\*•÷š š¦Á÷Ë[—]×E"‘€ëºPš¦A’¤ië$I‚¦iP±X,pÒø¾UUat]‡(ŠPUàû>âñ8R©Ô¢,9FºítÜâY€ð:ö¿®‚à9@½°læ Q_”kÿH@ø, ½ DÀÍ™ €§}@ FÓ<¢ @ì €æ È`N/0@È/òëÂûØ`N5¿“_N4Œº*Ñh×\sÍ4äÈȲÙ,ªî¿yófŒiaáÔ0žù’Íf§­#b~©&›É'A4’O‚h]H·%ˆÖ„æN‚h]H>gÆqxžY–aYTUö×qˆ¢”Æâïµã8£¡®ë×q¤ÓéºÏUUUÄãq(ŠI’ (JEçŒçyˆÅbH&“Pº®#c||¾ï#‹AÓ4d2˜¦‰D"I’‚óÎd2Á1dY† Áù¬™ïû‹Ò™Â!ÝESäó5™_å°Þ'Îía uËL‘ž¤'Áœq {€;ߤoɯêA9@ü€,€·²ãêâ6v|y' <ˆr~,q\´|0‡‰ æLábhçÿçŽ%¿­– “s¸ôäßK%çÌÂ4LÇÏ›¨Û¡²fÍìÚµ+ðVNNNB–eLNNÖ왬ְ¨£’ Zœ™š‰‘|Dó ù$ˆÖ…t[‚hMhî$ˆÖ…ä³:¢(B‚þKÿJ’l xߨ}xÖG%Â}P8•²Jª‘L&!Ë2Ç œ ²,Ã0Œic°m²,CÉwó6 #XÇÝk³kšVÔìÞ0Œà¼øqUU…®ëð<¢(ÎèDZ,,zÝÖs8€ö@ü«B¯€õ?q~ ¤À²U,¾à-ù   rÀ;8€ú$˜SvPŽ’”cëŸÿ"Àÿ5 Ìoêƒ99ìüß4 ޹ðY0À' Y*bþ¥äÏÉ_* 1<•KŽÅdšý¥´u;TFFF‚&ô£££AVJ4íø4/‚ ‚ ‚ ‚ ‚˜O²,—ý[Íáш}fr¨†l 0‡F,ÃÄÄDÝç«(Jà$ñ<‰D"È< ãûþ´ìîTñ}¿h<ü:r'O¹¬A ( lÛ²r’ÉdÝã':AÖFÜ”¯âe@b'àïÄïê‡9Â2T´A@è IÌIq= Ù>` p'Ù@ÁY!pØŸô `þˆDU7Â€ÚøŸsŽ`Ù(<ÛÄCÁ!Â3XVòKC¡D˜Z'æ÷ñòÛp1ÑóÛsg ?>òÛó,ÌAÃK‹ÉùcòÒbÜQº†^f¬î¦ôÙlÃÃÃèííÅàà †††°fÍr¦AAAAÄ"$켨Çq‰D¦GÓ´ ,Y-ÇàŸ[ºO-ã‘e¶mò,(в¨Ë}-*¸ãaÍå]ðöâË@,HopmâýОdï‚9Ìü_žb‚9$@>ŽA¡ìVÉOZºH%#¨«m ¸Ïn,3„7—7Q(Ë¥€9CxoÌÁ¡¢àäÐòÿ‹l,Pò˕И ‰B1äÅ7V~ÌJ賡}­Ð~Vh¼Nþ}9N„Žvàxùsjêv¨¨ªŠ ctttÚ‹ ‚ ‚ ‚ ‚ ˆÅïûA9®zE®ë²¬¢åŽã”=ïõÂ%Žã ™&¼÷L=cR%( Ƴdˆö!Ôʧ¾ýnÌ/±÷þ}@€øe¬Jò €ô·€aÒ‘€v ËJ±~B¡§/·Å<£#ß^Úh»óÿ{ùýx™.î„ ç3DŒ¿ŒÃg€PÈ@᥻æÑò¥ür…,A¹2$ò¥üzî ‘òÛñ̇›§‘߯Eqo)´ Ïx eÇìÐõ ;i8Jh¹ æxáû‡ýŸv~ü¡m›LÝ%¿,ËÂÈÈ`Ë–-ÓÖ?ôÐCÍ>§ŽF×YL˜E¯/‚ ‚ ‚ ‚ ‚˜±X¬èÞ÷¤ÚúÒ¦õ¢("™LB×uX–A‡H*•šö™¼J__$I‚ëºÁgJ’UU‰D‚uŠ¢ÌèPáÎ×uëvÍ'J*ÃÕ„óà= ð¤&C¼.@QÄ7´™oDoø[" |Gw2„}ùr^ÈWΤãòëÂ?-©dÞE쇳zÿó?/àÀûrxø¢‡q6Άy¸ô¨ƒ8òÙƒxÙ¢#2¿óaÀ~'ä;‡çálálø> øÀÁÍñó-Èd2ÌáÃ1ܹÃ3uòN  “& æüCãÕÁŽ¡£Ð£ùñ»ùu¼K*,-ÿ×È×ʯãÎ1t\ÌÁÂo^~…Þ1Vþ gN¨Û¡244„¡¡¡æx‘àºÌiÂçËT• ù>k~DAAAA A.—›Óú°cEUÕ  € q|%’É$TU ú©„{ª†UUƒ&ó|]éxJ;åœ7D{ày€ã°àó™7FЀ]‘kK¾¬×kõY@:–Ùb± …,nwµgwpGñ > Ì.•%/ßò2v{»Ùï’+ü¯ýúkXa­€QÑõˆ[¦^ÆîâÀO@âMÛðÊnüéÁ ð¯ß;+z>«.À;}'n±ÎFv2‹Ûöž½·Žÿ¾ã.\þÈY¸íÇ/àÔå¸[¿ïظ®ëBR%ø¾ß÷qÜšãÐuRWqsz A³nôÐyš`N îdáY*bþ=¿˜„;œ¸³&’ΞI‚9Qx& w øùÏ2QèÝ—£åÒ$ê.ùfll £££kîYt ¾„ûl™fa¹ž¯)Wc9I‚ ‚ ‚ ‚ ‚hYdY†,ËU)I’ Ëò´õËz©´Žè<49T¸Ý´*ðû+ß÷‘ظÏÒé€û ½8âO¿Ç-ß}؇B -…Ò[Ü ÏBþ$E¥®Tà/Oüf~ ß:÷[°l ?üáqG×øó½ÆòåËñºs&ðÆÕ÷âCú=ÔO¿ãŸƒ^x ^:ì%ÜõÒaøÑO–áïüÎyß9øÄ5§áÎ;ƒ¯}óüªû"ÜzëxbÙ'z2‡±±ïà¾oDÏÀw¿»ñ¸«¯~‘H_ýê+ø¿Owàò²]FÞÎl€9,€â2c¼ÄY:ü_¯Ð£¡m¿VÜÉÂû³ˆ¡ýÃåËøg¨(ôeáÎî„ñóËx† w¾ÌäP‰‡Ž9ÌÊ¡222‚sÏ=ë֭Æ °nÝ:ȲLŽ•Y—¯÷ç8ÅË}¿Ð‰;[J{kÕtó ‚ ‚ ‚ ‚ ‚hC¸Ô¶Ù_˪tê¿ñ¹{àꑃؼyÞ~@;ÐÞd¾L>ùîøÝ-ˆõýÒ©À¯ßùk¼÷mïeû—Vâùl8¡m  2 Žxå½×uáû>ºÿW7$IÂý÷߯vïÿÖûñ‘|úŇý`Ÿÿü™8pànð󟟂ݻ?€çÒ®oãïÈáÆW㡇^ÄÙg«V=‰Oð±ÿ~(ç[xê¥áº1|á ïF4º_ÿúRȲŒ={Î@:=ŽŸÿüd¼Qø3œg˜]Ú÷Ý,¼÷}f—¾úêŸâ‡ü\—eòÄÜþøqÀbÁáüµgQ).0Ý=…uü:)¡}x/þ^]Ã4`ç«4%Åø±tÀ¹€}ÿÓ é¼4›¬|b%{¦î"]U©Û¡2::Šááa áÞ{ïÅC=ÇqF±~ýú†n1Pš‰†ÿ|Ÿ5?ò} ™d¥¿$ H$ Ù*®Ë~;AAAAAˆe±—ë2{©(V¶­Â~ó›ß ¯¯Nü o9îDüèG'@\Èàeg'–ܳ<ù._z9~ð»s!Ÿ<ÒõN}æT<ú裸ùæ›që_n-d<ðæë@Ðpþïþîï Ÿ)¾ïÃò,8²ƒ;Þþv8Ž9##•Já½ï}/î¾ûnH’„©©)~øá¸÷Þ{!Š"Vž¾žçaé!áU¯zžçÁ4M‚€ÿüV7lÆ¿øEÜÿ^}ôSPóý!N¹è"üª÷møìÛŸÁw·¿Qáû=øÌgŽƒ¢ìɦɮÙ7¼ŒŸíüÞ÷¾ ôõ±ä‰×¼æA|üãß‚çßÿþ~Üu׫pãƻ޵W^¹žðmüd~ô£=Á©8áÝw'sp™&ð£èôõ¹ð< ²ü twøüÄspÞÌlÙΫ;_…Iÿ àåûȸ.à|ˆ' I›6=‡x܇é™@’í“x°öþ€· ˆà¸H°Ña¥Ì|o÷ñì¿<‹ñ_ý¥¡¿ÁºÝ3Û·oÇàà ƒe½½½Ø¼y3FGG1::Šh4ÚXIisl› :/јH°2À~ĶÍ~Ôa¸Ó(x]Ö3EØ:Ëb7 ÇaËJ3V‚ ‚ ‚ ‚ ¢‘X–4ÃËmY–UÔ ž ‰e†Ál¥²Ì^ŽÃʱ PTŽjß'÷V>¼_øÂ*Ülôà8~yÄ/ñÏÖ?㊫®À艣8þ´ãqÒ·ŸÆ½ãKpÚñ‡ã¾“‡NâSŸú–?¿—Y—å-þà<Ø–M›6¡kY<σeYe9(íuÅÁƒ\o×»ð?ù ¾ño`çÎxó›ß €9^\×…(Š0 ûØÇpÍ_ýÞrð8äÞ˜Eöw=ð<’$a÷qÇáä+pÆ wãG»þ«Výžw¢,ã“OÆoº ÿóíoC,52—\»tx›øÆý\zqñøðýc¡(cpðcxë[wàÄ?I’pä‘oÅŽŸÀÁƒÄAÇÄ‹Ýïe?ý)pÆðÊ䣨q° ‘GÿŒ¹úhôõíÇþp^yåQ$Ì+ÅÿçE|û…›~dÙÇGQ< Ÿüî>ˆ¢×ÿ¾yøø·žÝEàÜ»pÄ99èê[ñ†ý[°téj<öØ›pûíàÆÅòåË{v?œÑ~$=Ö¿Û€>}ãïóoºÀÉ2Ë”ù¦Ž±#ã8E8¾¡¿Áº3T&''+®ëêêjèà:A(¤žù>ûñòô)Ó,Ÿ–VZ L’ ÿsĤÓìØŽSHw#‚ ‚ ‚ ‚ ˆù¶m8Ž×u‹^žçõ1_ˆ"³§ú>s¦F‰M4Q¼ýÏÆ–ଳÀq&`1Ç4à¶nÃ×Oø:>pÙl’!aÉ!û±÷佘xÝ$HøÕ ¿Âm·Ý†¾ý}ÌQ£ëøÖ}ßÀäÀ4MlüóF˜¦8>>õ©OáÉ'ŸÄS÷܃ Ÿ~¿;þx|æ¸ã <ˆ¯|å+póö<¢(Âq(ЂիWãÈK/ŷޏÿ÷ûpòÇ?Žw¤Óe®ëbê”Sðîþ~Àk_û'躎D"î7¾¯Ï{p硇Vì ÁO’<#üÝaá¡ÿüOضž—[ŸÆ»Þõ¤Ói¤R)ÜtÓ•¸ë®ÿß÷ñäªUèyç!¸ë®Wá»ßz ÿtM«ö=‰%KúðµÌ÷qíµßÆé§_‹+ |îsËpÙeâÑ[=ö8r߃øìº;pÌï.ÆQGmÀº§¿‚}G¿æç1¹ŸÙ7…N8ìZŠÏ¿êÿâÁ¿ˆ-ßÚ«ŸùwÜ÷óó°zõF<üðpÑEÛpùåw㕳nDJÀC>p”ˆ7>ý Üw_œâ²Òañ80å`õ5÷áÜs+û3fCÝ*Ñh[¶lÁÚµkÑŸÿ–”Íf100ÐX)ét½zæºì‡Ë ŠRÙâºl_ßgûÈ2s p$‰—Ê}AAAA …ae¹ìº\.×ìáŠç1[ªiWû —üŠ çr+r<ßZr.´¿:ÉW}:eê œ|ìÉxæMÏà5w¾8 €œüÜÉ8áþxÕÕ¯ÂwÿŸþí§ñ–O¿™<±ìrù?lÜïàŠ£¯€ëºPUO>ù$2™ <σ뺸ð qàÀ<óÐCxæÔSqËþýø·ßþ[Žã ™Lâ†nÀ2TdYfNxúŽ;ðìá‡ãðÓNƒ°s'^sÜqX*Šð<€cŽ9+Wþ‚àâüó•À9³gÏ\ùĸÄuaš&t]ÇKgŸCï»/¸6¼z’¢(8xõÕø¹$A‘$‚Ï+Ø ÅÐÕuÉd²ÏŒgRºíWXõÎ{0x‹€»Ö}oó¾ htËÂúõ—±ƒ{áÇpWv _š21õöÕxúË_ÆûÞö6|ïºë°ö«_ÅÔÿA°j•Ž•O½ßûÓŸ ¬Z…¯Þx#þáíoÄ EÁ¦¦ðÈ—C’> øÃåãÅÿ|‡ðp¼8rž?ôTtògxO¿ Ò_<¸> þÃ× ¼òg\wñáø—y¸¡¿Ãº3TF±nݺ )½,ËA_•z²TÆÆÆ055U´,›ÍbttÙl¶¡'ÚL¡PšËu BÎ=©üËKvñ^)’Äö±¬‚C…— [’Xš[ÅzQ'ådèLù$ˆvƒä“ Z—Å¢ÛD»As'A´.$Ÿ‡ëºˆÅbÓ–õõõ¡§§º®C×õÀìº.âñ8–,Y‚H$›×¼‹Å`YVѾÄÂÑŠº-·ŽWüáè¾ïCEÿzá¿Â4MüûúßâOþ=³Ÿ> <{ø³ìü–á‰O<ç—?÷lx ±JaÏ;†£^s&røÎ«¿I’pÈ!‡àПmâÿÕ¯Æÿù»ÿƒ;ï¼=ö~ñ‹_à”|_üâñØcaûöíÅÅ+Wâô‹/Ƴ‡Žý‘îøÊWXÏï?ï<ì{ýë0ç$_~ÒI'áê}ûðõÓODZ_ûÞµt)~tÉ%Áy>ºz5Žĉ'.Ã1ǼaZi½¾H{®¼¶mC“eLr\×ŶÏ~6ØÆó<üòÚk±4\Ó4ŠëBnèë ¶O§ÓA™?UU±rå_°kÏÜyúJà?ÀG|¼íýǰ/Á¶‹Ç”JAúøyp&Î];wBEÜõøã8ñÃÆúU«ðÔ‹/ž‡ /<÷—¯ã·§ž )ïäéþæ7T ]?\d?xÏOñÊKŸžÔqÏ«nÇÏßüNŒŽâ–[ž†}Öf$€ß½qSÂ+¯¼ÒðßaÝؼy3¶mÛd©lܸ?ûÙÏŠúªÌD6›Åúõë±k×®`ÙÈÈÖ­[‡-[¶`ݺuiø 7Ã`uüD±à8±í‚sE–ó uò)i ù$ˆÖe1é¶ÑNÐÜI­ Ég{ãº.œ|Ä=yžß÷á„ʨø¾X,Ã00>>ß÷aš&|ßÖI’„\.Ã0H$‚gl^V,“ÉF]‡J´,­ªÛ:³ÆbÅ’IVjÎu]$ì{å2|ûÛg`ó—ð×^ UŒ“ØÀ%{.ÁÔg¦ðçGïÅ›Ÿ}3Î?ë|¬ûò:€$xøÏ;¿Qqȹ‡à‰•OÀqôôôààªUxeõj\tÜqøîw¿‹3Ï<üàÑÓÓƒ—Ž9Ë÷îÅG?úQ|å+_(ŠXuð`ýîibY]Žƒ«Ï: Ûÿô'áRDÞôÌ3XÞßGºº ~>9 Ã0 Bà„€ë®;_ùÊGH'>÷&k’$aôàA\¹gÎ;ôPLr ÇÁÒo;hÐmÛ6žÞ¹e8Ž)ßgB\ $zXPÞ‹Å Š"$I d]Ó4\rë­Àn¸ÞJ2•‘Ñq} ûâJ²4MCïw¿ ˆ">¸ö4œ{ÙQ8båJH’Û¶Ùõ)“ApÔ¿ÝŒÃ'³ØsÇ·qÈ•ƒ¸ìÁËðAáx¼êU‡AÿýJìÞ=]ãÁ÷aõêñêW¿º¡¿ÃºK~qúûû‹J~Õ˵×^;mÙðð0®¿þzD£QŒaݺuˆF£èíímèI/žÇ„›;N\·eâºÌÑ"Š,¥¯¯¸,˜¦n <³¥’SE–\ŽýÎyI1‚˜-ådè<ùl¼v,ŸàJ'C‚h$$ŸѺ,Ý– Úš; ¢u!ù¬‚À.Y–À?Œüúp y €ÚÏPšÐ¡ðòû•n_ú9RþàÏÂE‡W”¢RAk`/IEaÃ2 X–CEhùaY–¡(JQS{þ¬-I3ü B«ê¶<ð(£ÀE‚Gµ¡ª®8â­ø'ûqäñ?ǪCâ¥7¼Ä~÷8úÅ£ñò¦;08ñŽ~ÏÑÀ{ Ç9î¢ãð‘'>×uáŸå㪮‘֑xè_þOr’{÷â¥7¼{~÷;\qŸôÒKqà 7à÷Ï>‹÷¾á A¼÷¼ç=øÈ_ÿ5Þ&Ëð‰ ¬—$I@$‚ãDï}íkqѪUEçwÊÔ3‡wùï@PfLÁ Æ‚€½ùí\×…,Ë0Mÿýüóøýä$~{Üqð}?Ú³—ä{O¼¼s'vž}6Ö) Ry¹„ã‰dàû3LG"€ªÂ0 ì^³P(ŠÏó ö¯ÿ—–„¾îíÒ4føæTÈà÷MÓ°úon¹‚®C–eVf¬÷Û¶ñöGÞŽ?žùÇ¢€YUUqØa‡á¼G¿ç=xÿÇ?UUñå/ûïØ»;ùä¢ñî]¾“çuÊ<pt]x!N¸ûî¢}ÞòÇ?ŠìSÑ÷ FgM ¶•e²,Ãs],ïïÇño~3?ì0ø¾çN<###è[²r‰#ÔÍGñ÷¬³pÀsY ¾ àîh7oÆ}×]Qó}V˜ÌÉ¥Ä_ùÞ¥MÀ«J¥‡*‡;Qå*åšEÁòþåS°òô•e‘Hl$ gžù–,‰4ü·X·Cell 6l(ZÖÛÛ‹ÑÑQ¬_¿¾¦ý·oß>í&;666Í£ÙÝÝ=cM¾Ý»wOO«À›ÅKûF¡‘|Éülœ"’Ä,)Jm•°³†X6lØ€Ûn»­ÙÃh•d“¯›|ÞvÛmnö©Í ÇqÐ××7ßÌ‹GßD"‘À!ÂS™EQ„ïûE}}}Á6¾ï#N”žžÄãqX–Û¶ƒz°T6¬ñð¹jß¾}ÍJÃΧ‘ò¹oß>lذÊ'Mâ<ýôÓÍJCXLº-ÑùnÛ¹º-ÑÞpÝv÷îÝÍJ÷tÛÅE¥ç]n4ÍårE¯Ò¾­ é¶µé¶cccs—ã0û¨e1Û'O†à¼á ÿï{ßëÅñX÷¶§¡ý#°ùS¯ÁЩ]èIô°’Ty»}Ïþ,â¯Ñ³?[blÛ†¢(0 #È–âüº§PU¬X±G}t!{ÂuqÑ¡‡â#ÄŠ÷½¯Ì¸âÌ*A2V®HQØË4ƒÕà ŠEå½8®ë2ç‰ïJ"Ér‘| ‚€kÏ8Ëÿú¯±ç’K°ç„ày>}ãˆõôà»\€ %DÄãqÄãqø¾¯?ñ¾¾ôslýè(n\½çärøÁ}÷Áq‚€={ö}ïv`×`ç¦iÓ2RJí^á÷åεÜ>¥×õŠW_QøŽòNY–±cÇòÀ>ÞÝý(80§ß^9êv¨Ü~ûíÄæÍ›ƒeÑh7Ýt¦¦¦ªz&§¦¦°iÓ&\ýõÓš×ONNNÛ¾–”±“N: [·nmø…iá>(aD±ðû ÃïU•–Ï9Tž­[·ââ‹/nö0æL5Ùf/Ÿ_|1†††š}z³Â4MȲŒx<-ïñw]7𜆼DQ„,ËA„¿¡»® Q‰Dàû>ÆÇǃTçD"d2 Ó4ašæ´(bnô÷÷cëÖ­X¹re³‡2gæC>W®\‰­[·ÖÕûŒ Åàà †††pÜqÇ5{(sf±é¶DçCºmuÚY·%Ú®ÛžtÒIÍÊœ!Ývñ¡( Ç ¢èÃeÂEëºAÕ÷}ôõõM«ôÐÊn[®ÛÎ¥mT·‚¦þ†í§zà Ø¾ý 8î˜ãðÖÓ„øcàC“+ñcß„® óç’·Íßõ¦»ðÒ1/ák–¹À›†aÌðZ´Î4ÓÄ1ǃ+®˜Ö«¡l‰:^¾HQX$½¦±Þ&ùß¼›7ìŠe"ëeYfc•eftÎ;uŸ#I®Ú±È—ßã²5pé¥è±,œ·{7޼âŠàŠO|âÁõxòà“Á±âº/tlÛvpm#‘âñ8Væ+‹å/¡‰X,8‹‰D0æ¾¾>˜ygS, ö_‹ã?‰Dû.Û8uxµ'xÿûÏCoïÑsúí•£n‡J6›-;éuuu•]Ʋ,ô÷÷crr£££˜œœÄØØÆÆÆÐÝÝ]ö³ÚÞË$™,Ÿ]›ї.›K:ïµBõRM6tœ|ΟX À$I0 žçÁó¼Àq"IA€ªªAZ%À&=®zžEQN§‘L&!’É$dY†¦iÁ¶¼qA”ƒä“ Z—ŤÛD;As'A´.$ŸC,+*ÕÅ_¥ð ÂH$”Îæðþ)±X ±X ‘HdZf±p´²nëûÌnZš¼dYà}¿à—¿\‰+ÞýVH‡ ¬?–¹°¾Dy³ËsËžÃÄë&ð»ÃP0ÜÇãqª ©ŠC¯¨WÞÛ—HLϸÓu¬zòÉ™OL€tšyPpŽ”s¨hšV,•Jb  IÁ1Âö¦CÎ=—\~yp®ëB’$˜¦ UUñܲe““Û¶þ°?~–—mA°|ùrœp °m›½`Y-žçÁqèº]׃àáðXLÓ J†ñÏq'¨æÂš%I lqìr;Áw çû¬ÜsÏ=p¿?ý÷Á9ªj¡¿¸çÇ;‰FSwSúŒŒŒ`pp°È¹}ûö²é_¥LMMaË–-˜àÝ~û혜œD4–ž999Ù¶MǸ×Úû`ÎHž¹59ThÞ!fC%Ùäu1;I>ËaÛ6$IB"‘€çyÓ$•b¹ŸžçÁ÷ý²M±J•=^Œ;`J£ÂÛó‰ƒ×¡¤&{D9»|D+³Xt[‚h7hî$ˆÖ…ä³ýI§ÓU×çr¹à=tWU¾ïC–e,Y²$xöåFbÞè:üL>N-ŸKÌVÕm+µCÐujZźç^Æë¾ü>~Þ)Ìq"· ñäý+&ðÔÿÜŽrÀ÷}¤ÓiX–ÅJÍ•ôáœ*“üF“IÀó –:6|°mL¼ûݵ\å†$I*|v‰íÈ©0nÏóŠ÷1 H¡Ïã*RÞ#ËrQ&Š"Òé4vìØ3FFÇÆ‹/¾UUaYÇ¢(|æüàË2_øÄb1†Û¶;›¦i3†;qø¹r§M¸ŸJ"‘€ã8H§ÓH$U°’ìÜYÛ×Pu;T6n܈l6 Y–ƒFDÜc¹yóæª‚Tš½aÃlܸ±è8£££ˆF£C6›ÅÚµkÖ Âó*;LL³Ð/¥Vøï»ž}J÷¯ ?Q•™d3¶|Öïu’L&!Š"R©Ô´Æw¢(–¨W«!I2™L¾È3X‚³Øå“ Z™NÓm ¢S ¹“ Z’ÏŇïûˆÅbH¥R$)ˆ,?+Ïæy›h<­¬Ûê:kŸ†—‰Ú{ÿ^¼Ðý>þñóYY/¬ü“‡À‰‚˜SÀ3à´›?…w_þþ ÔU<›H7Wg„>úhð¹ÁoW§qCÍâŸËgkÌ eú • ÐM¥RÅ%ôDBÉ>Š¢íËK~±ÍYÀðaùæö¾ïcåÊ•PŠ¢À÷}X–|ªªB×õ 89|þš¦eôyæ wžðF÷²,eÔH’˲J¥‚`dþ9µ\[Iòpá…;œÓÐË_·C6oÞŒÁÁAÜ~ûíXJæõ×_?g¯äÐÐ6mÚ„ìÚµ CCC3–k&–Åd«Z†U=¨j¡TA´í&Ÿõ`YA•s‚Ô #B]'¢(ÎßDKt<,ŸÑÎlDëBòI­ Égg!ŠbÐ?”ÿÏ­D{Ñ,Ùô¼26VØu÷.ÀÞ½{qÊT>3ÅËL1Àþ畸¸OAfFúûŽ8ßþö·±÷Š+pÌOäéJÿØvÁàëûx¤««6“¼,3î,ºß÷ç§‰ë² êá[Ž¢¬–2‚P”&Ë2‰D‘ƒSqÄøË_þ×uqî¹ç­“$)pv@&“)²qUêI¾6ãããEå½ —SΗãËÃ=ËaÛ6,ËÂE]ÔðË_“Cedd###X»v-Ö¬YƒÞÞÞ s.”6ÜD4E6›Eooo˧tVË@Åú#–ÅäµÞRaY¦¦ôDc(× ·Ýä³\× Ò EeY·|®„ûªÔB¸‘=e¨ÕX,òIíH»ë¶Ñ©ÐÜI­ Éçâ€G³íE«è¶ŽSÆÆj'ÜqdYÆáϲ^((m}Â+2XÖJÞVø³Ïâ…^ÀW\-¿þ5®YºX¿¾à È;C\ÏvXmA°¡Š¢”—Ÿ—‹âû@>»ÄŸmÿˆ2¨ªZäPñ}‚ e­„áÊ|yéúrî„ #Šb°-ÿ[Ú›†/ç×TUÕÀY 0' Ït±mÖÛ¥i•ÁÁA¬]»£££Ø²e ²Ù,úûû±víÚ9;UJi§ÉÒq˜¬•³¿:Ë8©EaN•¹8EL“‡²\ˆù ä³Ç jC&“IX–Õ°‰®^Ç w¢8ŽƒD"Q¶W AT£Óä“ :’M‚h]H> ¢u!ùl¸Á(”šO íf€-­2¡ëú4ƒp)ÜPi;| 0c±ªª3–ó^,,´lÆãÌoPjb™ºh /ÿóË.’pÌÃÇÀƒ‡ýY©/nÖ‘Bï%¿Žyøa¤_~¿ÿýïqÂÅšZKRÁ *IÌ©bA†Êê:Ç>¯eì|¿rɤ9RjÏ’$ Éd===e·çÙ#ÕηÔÖÆ«ºT (öƒX8D‘ž—ÚÝïÿÂýxóáoÜóú{påÊ+ƒ ” IÏLáËòïŸ9õTXÎ?ÿ|fÒ4æ¹ rUUùÖ·6ûRSò0<ŸrÇ©æ0I¥R0Êôu©Dµ`f~.•>¯œ,ò.’$AÓ4‚€t: QçÅ¡2«*°fͬY³066†Ûo¿×\s ¾øÅ/6þý™Çeß¿ §={Za… ÀÊÿ•ËÏ… ¸ñƔ؀æ¡</ƒW¯­©¦l“ú”̵ÈKé¹4ÊÑSés%IZ 0u9TFGG‘Íf188€e¦ `N•¡¡¡|³áѱå–Ïg™¼™ ,D‚(eYpétºé¥½*‘L&ƒ¬™…ž¢ð}–¢(¬d­ g[€ä¸ðŸÄãš=b‚ ‚ ‚XŒŒŒ@UUŒÃu]Äãqˆ¢TfˆÅbÐ4 ©T ŽãY/¢(Âqˆ¢ˆL&Ïó‹Å£lø9™÷BI×UlÛvÐ;E’¤iY*<ÀQÉ7ûVe~{añýòöUÓ4ñÉÞO6°ê•UØö†mxøÁ‡YÉ/ÅÎ]J8ŽÃ0‚ïx¾¡®2X@¡V=Y-Ì™ Þ—¤žs™ ¼¢L)¼JéùWb¾J~ÕÜCåÚk¯Å† ÍfÙlëׯÀœ)Û·oǦM›>ÀV&.DÍr,‹e§43Z¶·÷EyäÈ{N!x³w-ëL4»SU•*Ä¢‚ÿÜ]—Í¥Ó{“ šyEÚ°„ýö±m¼§(€ ‚ ‚ Zþ¼ÍËj ‚d„ðRF¶mCÅÀ‘!Ë2E)ê'jFà  fmÛz ðgæZí_¼÷ 7Ô–~&À‚yi/Ó4ÑÓÓƒX,FÏçM`Ú×j“÷M¶mD—F 8ì™ÃpNêœúÌ©¬ÔW¨W €BÃù¢eµL…’F iÚ´2uó$IuÙšgk{ãŸ1Si¯Z˜/ghM*¼GʶmÛ‚Ò^Û·oGww7®¿þztuuapp²,#›Í¢··w^Ûj„zo`ÓdÑ´ ]rË4Í`":å”møÕ¯ÎnhZA´;Žã@–å¶‹,)ç}'ˆNC×™#%™dA ét(É‹42Qh2èÂÀù5lþm3Ñ&‚ ‚ ˆÊX3‡)54q%š#I…ž[Wj¸R Tv«¦Ï)A„ªFMß÷qì±ÇN3††«0xž×u±dÉ’¢m™"•žƒK{¨X–…X,V¶Y)¶mC„ ;Á÷ý`,áñ†Ë4yž‡D"x<Žñññ™¿;¢aLë—é?ùÂO ( wçËGö¢oÍ~Ö3%ˆR\Dº®¾cÛ†6ËïÒ)¬oêµÿrçb½Ì&x¿ÞkV­ï Ï,«‡çž{®î1ÏDM*·ß~;¢ÑhQŸ”ÑÑQ¬Y³]]]€ÞÞ^ôöö,‹…ðwhš…`óiÿt]===ÁÒq躎H$‚x<Žûî»^ørË 9A4×u‹"MÚY–kkFFmŒç±g8Y.&eœ¸ù—Àk2hBp=ÀŠœ)AAD‡¡ªÌ±~•bÅëKK ñH¥ð+ìL©õsJP¥¢1–7|¿à‚ ¦• byÖJ.—+zÕ[ `ÖZ¼¼Ü—¦iÐ4 †ae¿f_‹D"ÓŽ¯iÚ‚•T"Š)²¯ À÷÷¿àx€Õï[•ø%Ôïå3,ÜV뺀$öÑÀOð}¿nçÈ\z•ÔÜ<ÛRa•ìàMs¨˜–u2::Š¢eܹ²Xßç=•ÿRÕBÓÜFáº.úúú‚ÿu]‡aH$°m¶mi”ü‡ýì³kñÍoFèë룛?±háQ'í–¢iZQ3?‚è4 có© °yÔóáÐü˜3EKÝVò/€ë,oöYAAÄâ;‰D‘Éó<Äãq¨ªŠSN9%p®ì™œ÷^¦;e|ßG___Ý…¥Ç­†ã8ð<š¦A–åà¥(Jð¹¢(ÂuÝieÀxÅ baÑõ’j].pÕèU,{‰ÛÜEàh¼ÈÞû~a9À'ª I’ KgN•NùpûX=Î ~î³±­Õ»O%öLÇ)·¾§§gn« 5•üêîîÆí·ßü¿}ûv@4 –MMMall ÝÝÝ d+Rš9Y®iîl‰D"EM³yã®D"Qáy^Ð@‹OÉdªªB×õ|úår\zé0’I%høeYÖ¬¼ýÑîØ¶Ý–õ1AÕT*ÕìáDÃÏŸ<ÓÚý,€.Àõéw€•ù€qêàú *àĘ.Ì‚ ‚ ‚˜ À®ëèëëƒ$Iò ¿yæ‡ëºÓìXáž)ü},ƒ$IA£ëZžÛc±XÑÿ²,O³u•ÛFE(Š2­”˜¢(Ðu=pš$“IèºË²Šš}Ó3ùÂây¬ŠA©½ÿÔÃNeoøó¡,{tpˆÈŒµ)¹P+ŠˆÇã¸ì…pú5×BeÕgåá6ª…V®t/˜©$~¥±=óÌ3 _M•5kÖÀ²,\{íµˆF£°, Ñh4ÈH™ššÂðð0z{{‹Ê‚u2¾Ï„ÚuÙûH¤`š ¶mÃuÝ ‘×qT%h¨ö–¦ZñÉÉ÷A8¹œŠx<MÓ¨±èð<º®ÃuݶU~TU…išs?A´®[p€„•cá.Ηûòó/¬oJX'òË9{ïç%Ë‚ ‚ ‚˜W Ü's8„¢("NÃqœ ¹|MÓ ( <Ï›¶>—Ëm›Î—"+]^ŽZ¶ #ŠbÑ>ªªBUÕÀ†VnìÄüS)hnïò½8Ñ?‘õJQˆÀŠÉ @ó=S€X_ ãããCïmßþ6òߦ,³1+ê Ô¯Ö¥ªªVͪ·Ïð±Ç‹|]tQîCM•ÞÞ^ÜtÓMØ´iFFFF144€•þÚ°az{{qýõ×7l`­L8ëH’€x¼q²èºnPæÇ²,ø¾d2 Y–!t]¼müoØ©ÂT¦ÉÆÄSy6 A,&lÛ†(ŠmëLá´[©2‚¨†m³~c¥'Âa€}3  à3`Íè%3̯ÂñÍ>#‚ ‚ ‚Xœð^(Õ¨¶^Å–}Þí”ÒNí ¯ÌþyLLL {|ç8çže/k€ÊŒµ¾ïÙ <ëé×[¶à×sïj¥P?³)a_-S-èŸSBµ2ÿ«V­jx›’š*Ðßß_Ö ?00€­[·•ÿš‰±±1LNN¢»»{ZFK6›E6› šÜ·žÇê½óò^ŠÂ„¼Â÷Y7\ðA€ªªE^7Y–¡ækÿÆSÙÓÇ圯çåÁ|ß'ï:Q–j² ´¾|–ây^[–ú*…;DI¡[ÜtŠ|r‡J)Âïw P‚9Rj˜¦$IÇÙ á7»köi‹œvÖm ¢“锹“ :’ÏΆ²:Ú›VÐm}zðú£}ýö!Vµ€'Jˆ.’…ýÞ¼|Å÷199 ( žûÆ7Ëb¯|¶ÓlX(‡ŠeYP;¤¦u£ï•²Sª9nÞüæ7ã´ÓNkè8jv¨d³YlÙ²Ùl]]]PUýýýèêêªË™ríµ×btt½½½Èf³ˆF£Ø¼y3`ddÃÃÃÀ®]»044„ÁÁÁ†žð\„B©=Qd*³mBÏ1ìA㩎•¾ïÍwz¾ ‹mÛxì/“øÔšo6û´ˆEL»ë¶Ñ©tÒÜIÉgç#IÙÚ”VÖmÏþÔÙØö‰mìùÑÀ}#%EI’É$DËÂËëÖÞòáþðtCi,¤]¦ôù·Ý™ïëÖŒ{MÍ• 6`ýTFGG±~ýzlÛ¶­.o䨨n¿ývüìg?CWW²Ù,dYÆàà úûû1<<Œë¯¿ÑhcccX·n¢ÑhKE#$ÌYQ)¶,Ë‚eYÈd2H$Á ž‚ eSš*9T(=(ÇL²  -ä“ãû>úúúZ6u¸^$I‚뺑mCÔO§È§ë²9´(ÁS„mö¯¼ . ïãÂu]˜¦‰t: ˲‚Àžö?ÿóGèti€eŽz5ª'æŸNÐm ¢锹“ :’O‚h]ZI·-i xù嗙ǭ¼ŸmÛ€mã§ŸÆ¡¥ý>æ`#’$iAZ)Ȳ Ó4;Ê!9ß¶èf8Ÿ©e£ÑÑQd³YlÛ¶ CCCضmº»»122Rׇe³Y u˸ÀMNNbttÝÝÝA¶K?úûû1::ºà¥®Ë 4–а%¶mCÓ4Äãqø¾?­Á|­”ûáHReC9UˆRªÉ&€¶‘O—-­Qµøš 9C7"Ÿº^(—YD¨é¼±>ÎÞ»®‹X,4ŒD"Eªª"™L"NÃ0 ,_¾x”:è:ëk‹±qÛ.|ö,§X‚¨J'è¶щtÊÜIÉ'A´.­¤Û–«Ìõ­Áo1‡JØ×àyì/¢(¸øC‚'Š•åÑî,Dõ˜ÙÚÕgCMˆF£E \Ö¬YS÷‡­Y³CCC˜ššÂèè(†‡‡Ñßßx6K=šÝÝÝÈf³U¹oß> ÏëE²¬Â{McME™›C…7ËQUžç!YÖÊ43Õú§pCR)T:¨q cçÎÍÆœ©&›f-Ÿ;wî¬ÛñÚlÛ†ªªUsr!'†N ›Íbxxû÷ïoöPæÌ|Èçþýû1<<¼ ¦†Áœý>˜3Å««Ò?±U–e!#Nc||©T ™Lªª–UÄ>süL“9QTÈåØ<­ë€i²mâñÊó"±°ŒŽŽÂ¶m<óÌ3ÍÊœiWÝ– *Aºmkê¶ÁuÛ}ûö5{(s¦St[‚àn[›n;Óva|¿ÈG°ökÙAP^iy]×ñÂùçãßÎ;¯­«–3hv”~ç###ó¢ÛÖìPi$¼ËöíÛƒI“G#„©%eì¨£Žª«‡K­Ø6+Â{…èVQR©ÙÛ÷}Äãñ é|:žu*W¥F_‚ÀÆOÌ/Ñh«V­jö0F9Ùf/Ÿ«V­ÂÀÀÀ‚ŸwXväT©9³lÙ²f¥a4R>—-[¶`e\wZÐPL–À A‰¯L&I’ æ#‹*É´$IØÿÁ?@ÓX ÷·ˆ"{oYÌɒɰe}}ì°qÑ\¹ðôöö¢¿¿K—.möPF;è¶Q ¤ÛV§Yº-ApÝö¨£ŽjöPF»ê¶C×uXáèã¦i­Óu}ZÅß÷¡ë:\×-»¾ ݶ:\·íîî®ùó]·|u®}ûö±; /HRòÛI&“Á3d;Âûj/DɯN´1•Ú æE·mŠC¥¿¿[·nŶmÛ°}ûvŒŒŒ”¬Z¼—G}ô¼aµ öÐYN6ÌZ>W­ZÔÁ](lÛîÈ^#¢(.H½ÎN¡«««ã*”Ï…zèô<–¢ë%Ù)ËNä{ªX–…X,†x<Žd2Y—|Á{ËÎyÉ$0>ÎæDA`cgŽÓd¥Ál»0ašl¬žWœJ4–ÞÞ^œyæ™8âˆ#š=”†Ñº-AÔé¶Õi†nK@A·=ú裛=”†ÑŽº-QÀ4Mèe"¦<σ®ë¬EhÛ°ýÉ÷}Äb1ø¾I’¦­o7H·­×mÃUfB§÷­ö<Ë—/gÿ(ÎPÉGÕyž”Œ6Jû§4€…p@H’4/coÖùhª-«¿¿¿¹•]»vaÆ ÁkûöíØ¾}{Ñ2Þ¸¾###زeKðWWúûû‘Ífƒ¿a&''›6!Š"3°ûë8ìïlK¾éºŽX,QaYVÅRDü1{3ñr'áϰm»b4±ø¨&›ZN>«áºnG5ï∢Håú)í,ŸžÇJ}ÉrÞÉïèkBŸÈo$°‡*Ó4‘L&‘L&ç½¾ª,³±3§ Ÿ%‰9X|ŸÍû==2k"O;é¶±˜h繓 :’ÏÎAÅ"Ç À«=sgŠ$I³.}OÌ­¢Û&왌ã8âñ8zzzÊï AÖÔ|ÿ®Ú5ó¥Ü©9ŸðvFM•îîîi©Í½½½³š‘‘LMM¦¦¦‚|Ñh4hr°º™Ùlk×®mÊ…á)É$sª$…èÖúŽã£¯¯Žã “ÉÀ0 d2™²¥K\×m¨`* 3…|²¢Ý‰"*É&€–“Ïjø¾ßQ‡ß3:1%“˜™v”OÓdŽ A`%·$ € æT1ÁÒ´ósj"‘€¦iEqVΔ‰‰‰º¶W”âˆ'ž‘bÛÌÉ"I¬´çÄD! ‚¦L¢í¢ÛÄb£çN‚X,|vŠ¢L³+U«AΔö Ùº­ç1›lØþê84MÃêÿµzúùf<u¾³:¥¼¹3eš8*¥¾t]‡ïû³ŽZ‘e˜Eàðt+IlÎ/wëÈd˜RŸH°÷¦t[‚XL´ëÜI‹’ÏÚàÁ>aÒiV…`vªpéZ€é²¢XØÏ0¦g[+ Óm]wúö¥Ÿ#Iì•PU}}}±Ôó¼ â½ÔÑ.óÕ‰ÆÕN¡tÛrÕlÛ†¡,8¯ì>L à [I,ÔuZ(ÔBW«©É¡&›Íbtt4HóêííÅÚµkk ­[·bll,H g¹ ""›ÍÎ:¦Q„ЇÿÖ‹mÛÈÔh™¯™ª÷~‘$©b3{bñRM6Ö’ÏRx&Rïä Ôó<¸®;ï%‘ˆÖ¢Ýä“+ÁEÏJ˜#EsªA„Z:®ýàÜ»¡(l‚°ç„=8Ù=9Èx™ žn¢XœrNaÚE·%ˆÅF»Í±˜ ùœU-¯›†ÕæJ&ð~µ¨Ù3}N%A€,ËAVJµìž‘ÎÖwb  N¡Ùº-wöqùæ#Ì~é½*ÐÎ艹³Ð%òër¨ cË–-èêê J€mÙ²ÃÃÃPU7n¬é8Õù-ôd©ë•=îš6ûž)¼|w^4Ï+.U"I$I‚ëºð}¾ïwLÊ17fj²ÙªÊ¬mÛÁͳÓKbyž×Ö ûˆÙÓNòiÛeð`E™=TÕÜp7Ëd˜w#•"‘`’~ä¤GppÁ¬Ç+I, °ÚT˜J5ûª­L+é¶Ah§¹“ $Ÿ,Ëp'p¨$“ɲ†MMÓ‚¿‰D²,“ª…i¦n«(¬Ò甿;—\yIù}ðýŽí¥KÔN¹Ì¸ù¤æ¦ôÃÃÃÁæÍ›qï½÷bë֭غu+î½÷^¨ª8[Ú Ç©\Ý0f—™â8t]Ÿ±×B!IÅ‘µŠ¢Ñí®ëRsz¢íq'p¶‚ÌÍ‚ Î"r¨­Ž(æ›Ð‡ñhÀ䱓A™¯šœ)óvhZA³ö¾†Á1ÿÑJ3!IìpÕæ|]/Îö$‚ ‚ ˆÅw¤„Ë}•ƒ/çö¨D"Ñì¡-Š®O.{Û1ocÕÖzÅN×Åþ¯}mÁl$Ô‹ºuaAjr¨ŒaË–-¸é¦›ŠêZ@WW6n܈¡¡¡¶3Ìó’$å (µÚxÊá8\×m™^’ÄR8ï¹ç‚üÿ…¬Û¶é†@´=¼ÖB§øÓëy–[6Kø½$ìX!ˆVÄóØkš.#H7þ÷ð}©zR>gzʨª¢¹Tîu0çJ"ÿÞ+5VÞ7­’D‚ ‚ ‚ÃË~%‰Šå¾JI&“ð<¦i6{øD‹QΤsK×-8é哘}E/i.äû¸õÖ[«:óˆÅÃBþjr¨ŒŽŽ"VMùÚ¸q#¦¦¦0::º`ƒŸ+Ü0›z…†]¥»j…;(A€çy-ÓçÀ¶}û^Vk…!ŠbÐ Úž*lYÖìÓ†M0#¬6Q»(fý*ûðíâù}cùÿcùenþoƒ$©¹Ž#‚˜Û.ãLàJ.<ÿAض MÓf>Ÿ›ød])úÁ²ðÓU?e²ªƒ9OL0yòï=`r€Ë‚jAAAÅ„Ë~Õ‚ H&“Ðu=°GÅb1,Y²$xņ:bÑàûÓ{ú¼zù«ƒç6¬,‰rs]zÊ) ’¡Ò -ˆê,dÁšz¨LNNÖt°h4º`o®Ëì3¼Ù¬ ¦Y¹)íLø¾]×!«7óc>=i†<ÿü6<øà[‚eüF Š"ÇiçAÔƒã8E²,C×õÙýŽ}0C¬‚Ö ¢à É ÐÍÎÿÀ&v-¿mXÃmy -,RÞÎ/÷òÛÎò\IN‰v èY*{×ÝxòÒ'¡^¬Î¬è¸.›S©BÏ”*\ò»¥LÎ0ù²ò=éürL-0ù”òcËË¥<Ž‚3UÉ/!åe‚ ‚ b±‘Ëå‚÷ªª5™—e¹è¹5¼mx¾¼Üzbqâ8Åqt{ÿc/Ž~ñh à ð *Ÿ|‚$!ýõ¯ÏûØA@&“iö%"*`Fëe¨tww×äTi§ì€9QD‘•ñà°²ÌÞϦ䗮ëPU©T ‚ ´\ƒ­e˞ÑGþ´h™çyA¦ A´#žçÎA×ukŽŠ‹B6Il‚vÁ'™üÿ2˜Ñ(8R,0§‰œßFÉ¿ÁÀÒùÿó·0Ã.ÏbñÀœ0³¬´Ç¶º®·]™E¢óñ¼ÂÜ €9&óúî û^€aE[l¿8m`=Sž‹jó©$ᙞaïÓ`ŽÌ 0¹SQìä4Àd6&“@ÁùA!«ÌA!C-¢Ì>à‚ ‚ ˆ…¥Üã-©ÎA­Mi½{÷â™SŸaÏlç¹ÀcNÑ þá×¾w/]º`ãE±ål½s¡“Z@,tÉ·š*kÖ¬ÁØØXU‡Éðð0z{{Û*KÅó =Tøoˆ;Xâu”èñ}?HGäeL$Ij¹ú}²,㤓N*¹E!‡ ѶðÒz²,#“ÉÔ&w܉¢ h” l’æÆWî(᎕Xé -ôâÑð-¿©Ñ•o¢äó̪NJ$IÔÿˆhI¦ý$cÀ+ÀQ¤ÏI—ßɲؤ˵gßgïëð^¬Zµ ¿xó/ÓcpÜü xJ)"€˜Lª`NL~œ«"ŠäÓ÷ÉCAóA¸7µë²9·´·m–¹nåÝ<¸£¯¯x¹ë²yÜ4ÙßD‚mŽéhv%lÒ3‚Xìp;-gïÞ½…>ì§ûEðG­_?=`¨ EQ iZËÙ®Û…š*½½½Ø¸q#6mÚ„-[¶`jj*X755…ááalÙ²CCCÍ>ŸšñC2(Ëu]¦\Õãpt’$!™LËE1—Îöóľ}çO[F*D;ãºn!À'þ æºÌN›ø3ôºæÌpQ0¢¦P0ºVY,k%òÚ™àF[ õ¢ Ð·Å®í0üüDQ„ïûÔÿˆh9\·¤$–œuÃYˆÅbÅŠši¬'–ÅJzñß³e•Ô ›UÅKç¼ÝóE®ëˆÇãÓz ÍsrþÖ½ä”ßt°R~1¦ÈADu*=Vz^aï3ÝܶÙËÉ›&ÓÝyò*ŸH°¿¾_|tœ¼~š›]ˆD q‰S+b1ö7¬j8;ži²åžWT9׸¥D¢¸\¥ëâ8l |¶Íþòç‚ ˆÅŒç{8þÍdzžpwHEœ–eQ é,‘$ †aP_˜YRS³Ä²¬ errSSSèííÅõ×_5kÖ4û|j†+_¥Ž8Yfëêù=¹®Û6½®®Gàûç@ ÆYY–ašf³‡F°,&“õˆ+ù%B×ÙƒŠ(²%x¿„3Ü8ÏöåJ@M2¯kÚà%ƒæ /.‰vòTBþÆ$IdY†ïûÔW…h)Å`ו» ÞÀz¥Fs+ç±nðaЦÕgAEôÿoàþãmhªß÷áû>LÓ ÇišH§Óµ(’{Á®ÏÏCA‹ nÏŠÅ€ñq¦ {¾æ™ ü[Ù2îÈPUöÀ·á=ˇe¢ðí8’Ä‚#ùs;v°íÂçñRÞžÇÖóºüá„Xž‹cumŸHZ¹9[¯ëµ—çãÕu6F®Úðså%RùçñóåŽ#Ibë)ðš ˆÅD©óùå§_Æ3oÊ—w.SÅ@Q”¶±ÇEÍ€9UTUÅèè(víÚ€5¢o§2_œ°3Åó J_VOªëºm“b¶jÕOáûƒÌ˜òQ† Ñ ðÀôzæCQaš…MË?è8(”ØúÐüBÄ—®³‡^æß$‰=ôx3 ó5¾­ï×çp-?èÐ{,K¦Æ,A IR©ÇA"‘@&“¡¨¢éx^‰ÃÁŽþÁÑAäK®Ë¬-@yKA¿gQƒ’›üo__TU…(Špgv‘Kü|d.à} ÓKúAdŒp‡iœº^(æË¹#Äq Ïé4{ïyl}&ôô°}}¿à$Øv\gçú9×ë¹þ®(ìó¸ŽÏ÷ÏdØ~–UpÌp{€m³sP”Bf PÈá* äâÙ'üY£(… ¾Ž™;Tø5áãäc—¤Â9ÙÐAÄ""•*þùŽå8ïŠóØ?|RÉ3ë 9‚hu9T «« kÖ¬™–’Íf122Ò6e¿Â¶®|…ùz”ÞØ}îcšÿa{ö\(‰@q ¡FAÌþ0Tì9ŽƒãŽ;¶]°ÍÂkÏ{ XšÃó(9  óüÁ¯ËbpªZü`®L$lÝœ}X¦J ÌÙâ‚•+sÜpô…,ËP®ëR– Ñtx„)VÎΞ¹øà…2/À|§ª*lÛ†¦iA&iÝ¥áû‘8·X‚B%š2 ‚ ˆEw"ðlîÀ;4­$Å‚ù (ÜY (…퇩ÜéÁ÷Q”‹;_8ü¹ÖqØzǙs†ÛÞx<ÿ<€DzŠË;f__aœ|ã°sâY$º^xF˜“&ìüàÁ[†Áž!Â×+ûQ,®ÁJ<ø‹gàóä]Ï–/_Ý쯟 bÞÐuvX…¤Õ«Wì"¡gH×uáû>9Sˆ¦QS•ZÈf³Ø²eK³Ï§fò=äG¨Õkœ–Òn†ÌåË÷ø€B–ŠªªˆÅbÔ“h ¼ €¢ÔÞŒÑqüÍß| ‡ú~d2|!˜Å+ÕSÁnˬøM)ª är,K…—ÈåØùƒ— °:ͼöóœê+`M±}0C­“?‡D’ä–h6ášçðÁäÐF޲y†{(yÙF†Zò.³@QquEQàçÃ\=σ,ËY)3Éû¾]×+Ë“çÈe©P¥L‚ ¢ƒ¨Uå½Axâg"Qp”d2…gkU-ô4ä:7_0Ýš—Ú —â* ²âÇØÏ÷Å‚^ÎÇnšÓ{¡rG…a>?gY.d¸násU•l%“l_M+èü‰D¡4wöôõ15'cãT”BOU-”³mv,M+8]ø5àf…H„}&/ Æû«ø>pì±5û§B1/”ÎC{ïß AÊ–^÷kA–ós¨ A†Øœ?@–d&ä<ä²ÑðM È’"ú> ÏÃë×C–e¨ªŠ«/» ƒçž‹îxbó–×uaÛ6N~ì1H·ÜÂÖñÂç!Ï«ï‚&£:fì}D,ZA·%b:­•^.xü¦`šøéUWáGwß I’ Š"þõé§ñ›¿û;<÷®w± ßgÞÐ|•<âœö»ßŽÉ‹Ÿçᬾæð¬±÷ÑÙ´ŠnKõbYâÁ œŒÙvçÜØZ}îlEJ›¿‡á½Hx“v^¶‹gssxÏA`º£€—½*}ÖæÙà3ÁË{ñ}øXù2È|<åÎ)Ü(>¼/_W®¤//<>ÎŽ®õo…Œþ¹ÜAÅ—IRñ>á²hܾÞ|ÿd²àdyöÙãóe7’O‚h]š¥ÛòÇ9€œôôI@Ì™R¢ŸXµ–6!ˆù"× vìØ‘;õÔS«nóøãçN=õÔÜ®]»‚eïxÇ;r–eår¹\.‰ävìØ‘Ëår¹]»våN=õÔÜã?^õ˜ëׯ¯{¬™L.§(ÅËd9—›˜ÈåÆÇs¹t:—Ó´jûgr²,çr¹\.™L6ê.(šÆÎ³~^Dí\wÝuÁï¶]™I6s¹úåsÇŽ¹ë®»®¦ÏO¥Øßñq&‹áå‚Pü[Ïå–-;ëéñ r:žµ™L.'Šì\Òiöÿœs¹\ºÊjYÎiš–o¡ ÑÌfŽh5æC>y]&&Br›Îår㹜¢(9UUs*Û{Åó{Òi&p’T,lyYP%711‘Ëår¹g·nÍݸbEîª+®È‰¢X|*•û§+®È8ñÄÜ{.¸ ¿ûxî®ÿú/vÜÐ!%—K®ÛžWæ÷Ô:™zæˆV¦Ut[¢3H¥R¹Lþ>611Ìé†aäÒét.Nç4Mˆ‘3 #—ÉdrŠ¢äÒét.•Jû ‚S%gFnbb"§iZ.N³û^.—Ó4-—J¥r’$å¤Ð=NÓ´œ$I¤ÛV Sî[Édaºœ˜`󚪲çCYfÓžaL^Ô4öE¶ŸË±ýÂÇäÈé4Óå¹Î®ª…íd¹Xïç¤Ó¹LãEÈráX™ '_žN³ã—¢i…íÂé/%TR§“Iv>ó,Oóø8ûü³Îúéü`žiuÝ– fC§ÌÍÔm[ìD.÷R×K¹¤”ŸLTµè†=11èKQ ó¡ÛÖTòktt£££U· GT"›Í"¢¿¿?X¶fÍLNNbttÝÝÝA*Y?úûû1::ŠÁÁÁ†9|EMÙÃðZ°¼^%lÛ2;Ú9ÅÌóX:u2YX&BýM{‰¶§šl˜wù´¬â&‘ÞôÝq M7o~‚ðiìØñO˜ØŽBÏ 8C¥‰pñ1ŒB3ÉTª8z¯. ñüù•¹å8ŽI’‚Tö«³h¶|ÎO> VòKe}}~ò…/`©eá„Ë/oøg•¸ã©a¥¡­y9H…BAZ¿=G…o'Ežïcå‡>„£ø¯ÿÂï ¿øìg°¹Þq\4i*d§x/vÃ]ÿUˆ_;þÇVCGÕžMDçÒ º-ѺxžAày\×…¢(°, ªªÙ Š¢¥;yv/çÉáÿK’)_¢Ðó<èºÃ0H$ |ß2Òy³VÞ#Ñ4Í ¼¯mÛp]š¦Á4M$ Ȳ Û¶ƒþŠíN«ÏÍ„Ïe™ ˦æåjyöÏæà½Rø>®[<åÚva=×yÓé‚þÞóäÑðsg¹ò]@¡üV¹u¼bé{^«ÒÏ·œ.ñUn åX¨rý¥™=|L¢â“|DëÒLÝ6¨í¿yÿoà ^¡vd(Wè »%ÑLj*ù•Íf166VõÅ…®Ñh[·n þŸššÂöíÛÑÛÛ‹±±±iµ÷º»»ƒš}•Ø·o†‡‡k>aÞ@®ÔaR-ÅØ)iêà8”F6ÔmšV^!E‘Ê~ÕÁðð0vîÜÙìaÌ™j² `Öò¹sçÎS@«=˜8{³mÖœQ×þßùÎGðº×­€´ ¬ÇˆÖ³¡…H§ÙCO:]xèÔuv–ÅέÖ~1ÀR]°C%׌—äF‚Í[ÃÃÃØ¿³‡2gæC>÷ïßáááƒ%jÁ²òsªÀ)·g\~9 z„Bð†ƒÜ€¨ë:ÇA,ƒnYu5-Re‘HŸøáqÃÁƒ¸îä“qÞÇ?I’àäK€y% ×ä?à¼óv#ùÛ7!²çVÄÿá%XûÁz79`%ψ…mÛxæ™gš=”9Ó º-Ñ\LÓ,ºWø¾ÜC"‘HPVË4ÍÀ¹ÇÇ!Š""‘<σ,ËH§ÓH§ÓPãããÁÿÉdét†a@Q†d2‰L&MÓ Ë2’ÉdX!Ë24Mƒae©T Š¢ •JÁó<†|Ž(а, º®C–e~øáøñÜìË:gš©Û¶*¼œoÒÎ"xÜ/çÅ%é4›ÂyÓyÞïƒ;KxD`Z%–^þ«œz*åKq…?£•ö©„¦UVEêíy8ßÕK9ÜÉ&›Íâ»ßý"–/ß1ÿ˜gZ]·%ˆz!ݶ6Ýv¦í|?¿öÝ»w3‡‰ãLó~‹¢Mk‘hZ¢å™»mM*k×®ÅÀÀ@‘‡r®lß¾ÃÃÈF£,ûàXKs££Ž:jFGNQ,ß”N× µIÃø¾_Ô'…?l´;®ËnV’TÜL÷chw‡ÑBF±gÏžf£¡”Ê&€ Z(L-ò¹jÕ* T݆G»qÂÞŒÑ0 ûú˜¡.˜ñ2æ`h±ˆ­Ò>MžÇÎ-•*œc"Qˆœ!®zþ|åòçì/Tè\‹Ã#g:ÍÁÔ(ù\¶l¢Ñ蜛z^¨þ·ìß²‰D?¹ôRÀ¶1ùë_£±Î‘Hét:È ”e‚ @UUÄãq8ŽS÷ÜÌ·÷}ŸËGe›`™§–eÁó<ˆ¢ß÷YĶmã‚;þñgŸÅ+¯<ŒLæ8$Þò<ün0Y¤ì”šéííE?žzê©f¥¡4K·%Çq‚,žý¡i<Ï+ ¼RU¦iBUUH’4Pu‚ '¢(e†ðLÓj§|HæÃþËõZ3òJ>S8kÏT‘e+V¬ÀÏþóf_↲кm«àû,Ç0˜=Š·+çàz6Àº^Ü߃¿çAª:½ÏH¥ìž‰^Ji“0¼©})ŠR¹·IØÁSú9¤ÑªeiOVI’ðýïï‡ ¬–9Žƒ/ùËp]+VÜØØ4™VÓm b6n[®ÛvwwWÝ.è±å‡î>'‰'…¼,,Ë‚,Ëa›%æŸÜsÏ= ?nM˲066V䥯àà`ÝÖÔÔ6mÚ„l6‹Í›7Œå+›ÍÎèÄ9úè£k~èäQ5•ðýé/<•Œ?8Ù¶L¨üG»"I¬o:]QÄ#s‰ÚˆF£SI6ÙËçªU«jrĆtxi¯ðÃÿ”£sÀ²RÆ›}Õjƒ?€–:Òiö [éá°üÁ$òCÍ3Ǧi°, ===ñf±:G»ººF±eË–f¥!4Z>ùCç\Ðu&§™ ˜sS ÉÀ?]z)ÎøÑ€+¯Äê9Ô¦àN ÏóL&aÛ6|ߌƒÃ0fU¢&¬„ ‚”ÚQŠ¢s>7” ²ŒÝ##H&“0Í5„2÷ ÷C”ÁJó¥êÊ¢£··gžyfGdÍÕm‰Æãû>,Ë œ¼t–(Š#Äó¼ÀbF°$IsƒÃËz…¥ÆÓFQΰÀ+e„W…Ÿ‰x„'×$IÂý×5ûkhÍÔm›išÆ{{Þ“¤BVŠï³9œv¨…ß‹,WÕÔõ‚^R¬4Ýó²Zå~æ²\Ù¡’ª0—VËbçYOö/¿W ¼|Ÿ xH&k—Y~o(IÍKìéºQ¡( lÛ†$I¸÷Þÿ…ÓN; ¶ýH°üMoz^õªWáç??£ö“laZQ·%ˆÙBºmct[ϲÎ.“.›¶ïûA†-AÔB?V­ZÕðãÖäP)Ç–-[f°~ýz 9gø –¦OONN64€?P”CQ˜ðVRê¸C%•JuDma^—V–™ÂÍ¡’A‹—J² ̯|–ÖO–¹¡(ÓŠøCL´L¿”Z1ÍéçÃK.ØvA&g´«È(ÎT˜1˜GÄÆãq(ŠRT¯hš%Ÿ•à޼´àùþçñÀÍ7ã˯zUhÅlïKAªF ñˆp£Þº!¸%Œ$IÁ±#‘AÀ™«Váóy£#wð<øàz§ç먈¬,‰Ý¢¢™º-Q?¼_ w„ƒ‰dY²Ñu]‡ 0 –eÁ²,¤ÓiضdyðòI®+@– #•Ç&É204´¦yJPr˜Yð’>’T0xóçMczC¸D/Ê3,«` W”Âöãã=ŠM…™J±õܨžL ù±)èë2ÍþšB«Í ‰ãiºÎ~áì>å•sŽT+~–물„X9J3Y8ÕÔ„zÕW^š¬ÖDmß÷‘H$‡ ÏJ-݆;P¹ÓƒË¿ãøA–˜ëºCµôxŽã@×u¨ª `Îþ\Ãu®WضsÎyvï^Ó4ƒàÎññqX–…»îºÀë»@-Èb–O‚huš¥Û¨0uèT…mXfp:ÔS… šÁ¬*³addSSSX³fMQToo/¢ÑhÐä(}YÖ®]۰ϯ֨Ž+‡¥ëÃÙš¦uTÓ£ñ|t?Xã:dQ‰bQPM6ç[>M³¸V2wl–:øÆýo½Ÿ•×i³ìÎJ·Mcç̯Cj¦èv!î2€µ¸$ˆ,ËA„}___³O›hÍ”ÏJðZêŠæØs›Ÿ¼;ùdºv휜)Üh &‡ Ÿ å¢Êùçsg‹iš¸?o áýW4MÃÿ÷Ÿñ¥ýÿûðÂßðuˆ/ÎÛe'Zfë¶D ‹5®ë”´,+pœöôDðÙÏÞ‰O<_ýê§ñ¥/} ¿ÿýJ¼ç=ÿŒ|àSqÞyŸÁ޽ˑHljàÃ^ Ï[ÏÓ‹æuÓ,£yÓhnÈö<àÎ;O 2QÃŽî‰Å ÞŒ›ghwذãË23]!œm3½^×ÙgXV!#ÁóØ:þy|ÏcûsG o6nšÀë_ÿz<ôÐCmíÝŠsg½ðÞ#Õ*šXVÁaÁ³N$©´Ã‡åéÂÇ?öñmËQ©‘|¹¥œF?(çü(<ÇoË3ÌÂAÜAÁ®1{æÅbA"îLååúx/ógÛvàüà}‹Â%w‰DþZIA†šmÛÁçʲd»q¢(ˆD"AÔµišÅ_C’ظ¹>$Š"N8á“þ¦±uéù$ˆN¥™º-×­vº'—-3D΢UXP‡J6›E6›Å† Š–oܸCCC¦M›000€]»vahh]]] C%£&À)·ž+TÚôÈ0ØÃ•¦1Å›GêQdûâa&Ù0¯òYš¡RNu]ǵW^‹¥,e  Û I*ÿ Éx…é ñxáÿª(`Î7ÿ7aA‰GÍu’#x1Òlù,ˆÀ2Æ|õÞ¯b||îuø¸ñ³žíc±ØœËqVsÊH¡¬þ¿aÐ4 wÞ9…ÏÝ’Ã5¯\íÀðÐv_bö´‚n»˜áú¹eYøä'…SNy?V­zwÞ¹¯ý{ð gaÿþ?àk_Û‚³Îº?ü÷øÈG–ÃuuëØ1®¹æø>ðÄÀ?þãÖÀ t…t’Ø´©à¤û_Ë%Ç…çûrïÃûû~qéÏr|—¤Â½7üžÿ5 ¥ŸL2_-‹}F"Á+¾_ÈXQVz”gÍh;Ç‹/¾§vZ³¿Þ9ÑŠsg=ð`?Ó,ün¸c-‘`å6y‰\îȳm– ~®Š ÜùÂrEó9 ÛUš“Éúc&­†òÌ’ð³*÷g”Æ& H’]בL&ƒÌS^ÖÏ¶í ¼(_Ç+Sbm¾VþKQ” ÿ Ïïéé 1xœaH$ð>AÐÓÓè<(Š;b\×f4EþóŸ{A›@»Ë'At2ÍÔmù|ñ«£~±'%P¢h‘mƒhr5pÝu×åÖ¯__´ìÔSOÍíØ±£–ÝëâñÇÏíØ±#÷øã×´}鸪!Ë¹Üøxùu@.—Lær™LñrEQr²,çj¼Tm‰¦år¢È®ÏÄD.—N§s²,ç&&&r™Ò BLãºë®›YhEê‘Ï;v䮻K§‹å²ôÿœšËýñ;̽qõs9µÙW`þ1 &‹5“Êå4M+{J¥R9I’rÍ>­¦QÏÑîÔ#Ÿs½.’þ'—ËMärr]?ÜéŒç$IÊWš¨«L&s†aä’Édn||<'Ëò¬Ž3’É\î£}$—„Ü£¿Ìåä\.§är9š>«RëÑ Ì§nÛILL0=<“aºéÄ›E‘é’Ä^ìïŠÎ-_þ?9 —;î¸Ïä>÷¹¹uë¶ç®¼ò¦àé4“Ñ0ã㹜¢ÌnŒ†ÁŽÛŽT÷Ä{qd™tÛJ,ä}K–ÙïTÙÿ¹œ är©û.ÇÇ™¬$“ì½,¾c¾M-ŸQ*óÁlÔЉ‰‰\248Qsš¦åTUÍ ‚S¥hýøx.·jÕó9I’r©T*711‘Ó4-§iZNÅ€œ 9I’r²,ëEÉI’¼“e9'IR.™Læ2™LNQ”œªª9Ã0›ëÖ™L&711‘Ï)Š’K§Ó¹\.ìÑ$)§(Ê´óJVø¸ ¢Ç{ìüi-ÂBê¶1WH·­L­òÉo{w½ù®Ü“o[?m2ÏiíªˆMe>tÛš3T²Ù,†‡‡‹–mß¾}ZCnQ0[xšç|ÀSéËÁS›K£Z|ßê¨w2†ÁGìù€IDAT¢œ|Ar<‡ïûÈd2eS«‰ÅÇ|ȧ㑜 xvë³xäÖGð¯§ÿkQ&F§¢i,C×ÙýhÆÄ8ºeŽä=U8¼—J$$IAÍw¢3™Ïù³"6€—}ìøÉOæEǯ>s ö}cºíÆ2kY[fÓ§)²Ù‚ð&Ù¼lU:]hŠ-I…~<[|™Ì ù(p•‹™ð}±+Õç86Dq$i9€‹‚Ï«ÀXSyÍ ” ”l*»ôÙÇ0€;ïlöhŽV–ÏTŠeðR^<ÃDQX©¸d²ÝäyÅßq-¼•²§M½U¤y¶ï=Âÿ·,+è«°>$›ãeYÆÒ¥*DQ„eYAi®L&ôäÛ{ž‡t: Ó4aÛ6Òé4DQD__ Ã2_XúÂ穪ZTJ]C)ø?¬góž)EQ‚ã…³p+e䊢X±¯é«_ýêùÿÒZ„V–O‚XÌ̇l†{`óð18òÂ#ËpÉ.I´ ‡Ô²–±±±àF‘Íf‹–5û|*âûÌ@Y žÖ[xS\žæÛ©ðRgšÆ”sß4Í(2<%‰¢~2ÑÂ[§¯öüh~ºê§øÕ¾_áäwž ´¡£ÒÃP5xýußg&ß/nZ„ ¼|ÒËøØäÇX£ú4MÃøøxð0JsÅ÷óÆH˜Ú6…þùb<úéOãœ+ê>o.¯1xSWI’0>>ôKÐu=(×ä‘j8º®Ãqœ ¤W9x)J2}Χ?Çÿ—Üt >¿ìó¬,Ÿ æ&ˆE€ë²9Ýu™ÎíyL¯ìéa:67ÜÚ63ófëÉ$sLrµóù矇$9¸çž{ðÈ#;‰D‚Ò9®ëBUUŒ#•Jewªü+[çNØ}ÀGáž`Hä×éùÿ]V~½_Î×Çó/+ÿŠ…Ö%Dòïù:7¿Ì»ôöÏ©„jÏKÄüë}ºÎd†÷Ú‹ÇÙrÞ;‡ Tµ S×T:L.[A5ô}º®e²b±X0ëº˲ iÒé4dY†(ŠH¥R$ ‰D†aÀ¶mœrÊP%(ȪªBUULLLõ]ã÷ ~Lví”àÙŸ;Døþ|ÛZ0dY.º/išVw9ÓJ÷5*wCD'4¤ ¬PpÌÉÇLs¨p} Zš2T188Øì±Î Þ´±†QˆŒD¬p¥ª“´‡uBIb¿¼&ï§Žô%ˆFaÛUøDÀm \5€“…“qœt\³‡[D<‡aE྾¾ Ê `ØD"t:ÜCxskÞ›o“L&å ™,Ô¿ŽÅ Y+™Lù(¿‰s&pÁo.`“ p³Ñ®¡µDËÀ#Ê5;q }Gí”8íw¿›y² áyb± À e›Â×J¹À‡d2 ß÷ƒºåét–eFˆD"q„Qð@ îèáÛÆãñ ùl¥Lé’¥øîwŒññÁ6ûpÿÀýXzùR 3[°‹n´•ev?0M6—sUÑ÷ ÍÐKû-”Þ¸Àû8Ž„±±ïàüóÏÇ/~ñvüÇt#eò&ŠbcúûñlNÞƒL-sP˜K5Ï«``Ž €š/æ÷õòÛ'QpóËÜüg((81Ôü¾svĤBÇQBãÓòûñMb~#ÿYÜNëå—‰ùq˜ù÷ñü~Nþ¯?žY²Ñ‰Bf–$1™âʼ7ÊÄ“·pîdáÔ›mÒL›oô hòÎ*¼Y;ï]æy^à@Ñ4­(;„;TY……¯@Œ`Nç÷‹ð}£ô¹>¬;Ôš%»vžeN±˜à·W{¿ (¹iÆ^‘€ ZmJßL$©z=]/DÆ,…˜G£ø¾_WDI;cÌ€ËSò2*\Á¥›ÑHxé²8À¿¹WÉW5{˜A„»ïûð}?ˆ2ãëì\ü|éf€M$Pétñx|šCƒ7ÄÔ4 ™Lº®øC.‡(ÀÄDA‰ˆDØ}ªô^öÔOá¾;îÃUÉ«¦•ý⨪ŠH$”Oèä¬;b~áÎ=¸À­Î­¸Æ÷qÔæÍlò¨Ã™ây^PR’Ϲ†—à0M@¡,Ÿ×ÃsšeYH¥RèëëC&“mÛS…7³åeC|ß/kP9ê¨ËpÄG ¯/EÙ3­3ñÏ·ÿ3Ö k O‚h#|Ÿ½ø”Á£ãv5EÆ{^ýªyD:/m#Ë2¶ný+¼ð‚ YüòÐ.˜#%˸#„¾—ߎ;5 0‡BÛpû*ßOs2pçw²ð,Z L†ýжf~;%´œ¾ˆÚ³jåü+Y²ŒSÎ!+†¶©ô9˜ƒ(8oL²ç´ü_§ 狨âWSñ<&S¢Èœ*É$Ó‹§9"… ŠÂœ(|y8FfƱeX(UÐ÷}D"d2™àì *2M©T*XÏ.xcy6æÂ Ãó¸ p]7œ”,ÅÌõw€e‘h¡ W‹Ã¶Ö •¹Òé2‚ Já6ÛÀ™\r_ Õƒˆö¢.‡Êðð0¦¦¦°yóf cË–-Eë{{{[¶,T"1³¢³‡Bß·‹,AÐú>»’Ä®ÙÚµkñ¥/ý¡C4—Jö×ý¿ÞÓWž¾àãá‘q’$A×u†ôQò<¾ïÃuÝ >³ªªAY–aYLÓ„¢(#†G³s‡ Ïl ?¸…ÎŽ?>‹U«^F"ñ• ³¦J@$졚۟_ÁëñÔžb†€ñòçÆ Ës)­D,n<•ûòY*®ëbßèh]Í\–ǦiA„é|Âçót: ×u‹ÅÉdŠäŽ¿O¥RAvUUÑ×ׇd2 Û¶á8TU…išPU5(?”H$J¥ð–·,òe€èûPóçvÃÕ7àŒëÎÀjuõB~U1gtwM“É~:](ÑUJé”6llþ³,+˜CÙ>"’É$<Ï §1 Àrfÿϼ…Ì…rY\ŸwÁœ <;„?‚HùW8‘¬Â¼Xäè,çô ;+Â6ÔJ¾c?4®V‚?üÚqG § V:Lô>²ae³G¼(6§Š"‹IåBj>= BñûFO—T=ÏcrœŸcy¹.îĈÅb5ð{,Ë¡(«Ä4Íàù³Zkiù.¾O%½¢´”Öb š$‚huL“ÏwÞrà-ÓÖϦ”:AÌ'5;T®½öZÜ~ûíEJG4ÅæÍ›122‚íÛ·ãúë¯oöù”…!g*ùÅ›@;Ž»h31$©ÐT€_¼¾ïC’$*ûE4Þ\³Ý÷Î9çœytÐu=hXÉ£ÐA˳O6‘ó,•ð¾GòÄ0¶m—}xã÷MÓpÓM·bjê7øð‡YcmÓ4aFð@-Ч'+©"%"gUˆDQ JÍ·›èLL3ïÈs€ýÖ~x–WpÎÍ är'ÏÌjVù9I’¦•ë+]ÏÓÉAÀÄÄ&£<»‹;O¹bϳVE€¢úŸ†õ¿î€ú™ã ýò&>^×g—ö,!‚ Ú ×eAžçcÏ {p2N.Z¿˜*íAM•±±1ŒŒŒ`Û¶mèïï/Z×ÛÛ‹¡¡!twwãšk®Á¶mÛš}NÓ°í™kÊòŒÌHé¥ÿ.Fx3C]>üá¿Gÿ«añÂùÑ ãl^xð¼éÆ7Íëçóˆsæ¬G 4 cš#‘—åªÅ\êLá™,3=ð­_€Ë`Û6,Ë‚(Š0Mo~óñÍo¾Œ~t5$‰];Þ¨4x(QˆÒåFÐ팂yïEQH1!jÂóX’¤ÀŒ¤QpÌqËk|߇(ŠA/“f3Óo¾œÃQ„"™÷RáŽWîXQ¿q&bo{Âo,¸ŠuŸ{}W÷!y0‰„™höéDà0Ñuf¸åíT•EÊû~±w&,ËÂs|*T\ýƒ«ñ_§ýnúäM8ç}çà O~‡½ê0jÊœü¯¸…òZ!»iÒË;vx– §’*-2@Ú‰ü÷àeÓ~wûëESzA1ͳ©ç•FÅ⬔f ë­¼—˜ªªp§¨ Ï>ãº4/•žûKKµ4:¸‡—#ˆ¹‰äKÛ± ( îv!¾3”®™Ÿ7*¦D³8¤–n¿ývD£ÑiΔ07nD6›ÅØØX³Ïi•”ÕrèyÏ •¸*ðüó›#A4’Ježu°ú«çõóA€,ËADïûALî0)5¢Š¢8ëÈzQ‹¢ñfBQ‚4¦üïÿ¾?üáñA"€$1¶ë²‡sËB!:Ö3èX`+¡sæå–¸£† jÁ²ò¥3óM÷üèGÐy瀮WöŽ‚•îà%ò:p)?€e–ñ{‰mÛÐÿåÿÕ_?‰§¿ ÛÎûøy0Þaà©{žÂ ëohöð‰EL$£‰›ƒÇÇ™ã„õÍc³|Ù4ß¿6§ø`Ù `B›Às¯~ýWõ#þµ8¾sýw°îo×á‚O^€­ŸØŠ+oºK¿‡Þw(067ñ†î¼\WËb¶…ë5mü!ËÀ//þ%žõóÍJGây…øÛ.¯ ó,±V€÷:rŽã5’çs{X_M§Ó0 ¹\®¨Ç‰$ITn–hyøÜXÇãA ‚Û8V=¹ Gyd‘ :ŽSµü#A4ƒY‡ bjjªhYoo/&''›}NÓ95«25µ ¾ï·Dôl« iìᛥ›“C…h¾_¹ÔÀÒ]Kuóýù~¡ÁLò‡Áù‚—:¨w^gþã?^ÄÝwŠr)DQ„ïûH¥xÓ9¼@<ż]' fã†1±¥b.þåÅxàæpÆågÌï'ÚÇ2‚fÆW~sVLL¯{[Yq?Š¢tt)žñÅ£qmÛ†$=€_ùÞÿþoÀqÁ ?½p]oÙ…„°ç’=‹¶¼(±ð8N¡G7…E²(1Û$ž%Â(+¿%æÿ—xÀ×ü¯ÁÜkâŸùNüÛ±ÄY‚+Ô+Øö³œNÛþVÁK”µ)’üàïÄᇊh´Ù£é>4œw’$Õ<·Óô—aýmëqõùWãóÀoû[ Îîßzÿ·0uçàÐ{Þv¶}v[ñ m~¡Œ¶=Ñ6òêð™1eéÒ¥… ¥¬Ce±f5 ‚×uY ”xÒ¾C{ß˲‰Dà L¾vì×à$Äãñ‚Ó’ æwžp|ŸÉoªž&éXPChŠ´, ñx¦i⎓îÀÃÇ< Y–y®(3ëíÄü"ÀÄÄŠf£ãð<ýÞL' ÏÔÖu=p¨Ø¶ ×u‹²M$I*Ê6 ;O$I¢À:¢£p]æLY„ê*A´ŠÂ‚k×ï[ÏäÓ8çÒÖ 據*044„¡¡!ŒŒŒ@–eœvÚi8í´Ó°nÝ:ŒŽŽbëÖ­X³fM³Ïg¼Nm5,ËÂêÕooJÍf×uƒæ~ÓÇîÁuÝ Y¶ïûp]¶m/¸"«ëÀÞðž|rþ ûö­ÇÕWÿgœq+nºé/emÊn•Ð×u‘H$‚m\—j•.6<¯|†ÊÞû÷bõêÕsÿ]âqL}àÐu‘Hydù#ÇaÛF¡;ox]8@¾¶Û.üã¯ô›çyä¼s|ƒÂžb%{y*¬ ¸êª+°zõ£˜˜ÇÛ?õv}MíÒõ‚ƒ#ÏçŸßþö·8â¯þ wþæ7¸ì曃¦™AG^U-îÿÉ”?>.%Y¦ß·bìø\6}Ÿ½‡ý¨ÃÇ‹Çë _ÃâýA€®ëA{Éñóû~]סù,Ë‚¢hØ»÷yHÒ$I­·k®a—ãï|'n½u%ÞýîB©˜tšùƒ¬1v –Hg¬ÄÄøpŸz™9ü›ôm8 ’ô> ­Û‰ñÏ®Àí'ÿ ÿ~ó]xú¹s‘8ìOPB÷m/ã _:ˆÍ›_ƒ~â‡8å”SðÊW°ÿ3K°y÷AŒý:<÷áç°üùå€ì>n7Nºã$@E!«E3øÉ4° l=ÿ×EÛ×±/ÇBÉ'‡Ï¡ž(ùëlš&dYƪK/-lÈÛyxZ¶¢Ì²+u8T4 "Édr¤(€¢$ñÉOîÃ9«7â ¿„Ïïóx샒VÇ!IRïÐÏ›  ¥Ûš& ¦—¾þRQ†´ëºPU•æ¢%©Ë¡ÂiDŸ944,Áðð0°k×. apppNŸSX^Š®ë0 £b‹„FÁJyf k ]\WžgŸÈ²<íÁµôÏóŠšRÏwÛd„3p×]à¼ó€dòôôüîº+ ×uñ‰Oüçwxà Tõˆbá|,ËÂï n¸á,ˆ¢]×ñÀƒô÷¼gAÀQG½€ü38ì°ƒ$õàÃ>€'Ÿ|?ûÙ±H&s8çœPr²Ì7ådh¬|òr$¥²éº.þñÿgïþãã¨ëü¿ -¥üH:m±…6¶L¡P’jeBÅ  2‘¼Þm¢‚Ò¢ÝUO­ÞåØ=ï©§·+ñ°òUÙ-^Qñ$Yå(î  tÌ BBù•±e©¨™&Púƒóýcö3;»Ùìn’Mvvóz>y$ÙŸócßûùÌçýùqÔÙ :Å>Ò¦i·I’ I$œÇŽ÷½«n¹°ÙSÀï/aE^—`°ô/‡pØn-É÷käg~ÆÐð,Ö§pi>{1̓ý·†}…"ˆF£H$dèz,Ýpn¤ÖöÁïÏ7±&K¿}øŸÐúò‘8æ´'øÉGà÷«0Œ(’ñݿĮCbÆñ3`ðᆇ¯EËÂßâ3—…Xì!ÌŸÿ ÎûÚ ÌœÙ‹cŽÙƒÓN›?O›†÷žx-^üÚxÛL —ÄŸÿü.|xÉCX}Ët'šxîÍ›pükÿžÓ»ñÙ“Wáÿ¾z4Î:á|úœzÖh¢~@Ҁػ5oûø¨«—MF|º‰Á[>Øuê.Äãq$ò­¤›hñYKxeµÝJKÇc8lÿ©Å Än<„‹._ÃøgÜ»çH\•@ô{QÜÒy 8à$­LÓt,¦iò‚Âã&«n›®gŠ{Ý;{Ë’úÜö.éxá /àÍÅo" ‘H@’¤I]+A–9åW¥IpÌ1‡ÆÿB2Ùegæ}íØ”¤1UóJ"ÊÜ`0èLãå÷û2¸µµ±XÌYTÞMQ”ËUU†¬|ï9úhj¨D|êº}=šHäOâOáþ@DY&«n+§;L>ºïQøÔLŠŽåDždM²Ûn»Íúâ¿h-[¶Ìºþúë³îknn¶¶oßnY–eõööZË–-³žþù‚¯·nݺïóù,KQ,«¿?ÿý‰DÂòù|–eYV0hYÝÝåßßîînËï÷[===VÿH’æ÷û-EQ¬’_? ZŠ¢X‰DÂyýD"1ª×«žžçïï}ïaköì“­%KÞeçØ°ü~¿uì±{¬óÎ;lù|>ë=ïù/kÕª?Z–eŸ›3ž·‚Á ø¬ÓO¿Ãºè¢Ï[Š¢X³f=dÉr5þƒÖŠ›¬•+¶–/Á í穪eE£–50`Y~¿}þ&âsýõ×;ŸÛjV(6-kôñ¹}ûö¼¯cYvlº>>Žp8lýù”?[VU\¿µçÆ­žžëÕ­[-k`Àòûý–ªªV4­ôá´wPU ?Æï·¿|‰ÌÿE¾'ÜòÅy0Ì{{¿%˲ÕÓÓc)Šb…Ãaçñ>ŸÏêééq¾¯Âá°•H$¬`0hõ÷÷[‰DÂzôÑ}ÖÚµ[‰DÂêîîvÞãÚk_³}tŸ•HïCOe…Ãv\&–õå/'­p8l-_~¹',V4µzzìÇXVæñ?úÑCÖ‘GþÑ LK–eKQKU¬cŽyÒZ²ä]–$õ[+VÜjsÌ—¬÷½ïI P­+nµfÎ|ÁºöÚo[Ý+,ë[×>`]vÙV8ÜoI’e}ðÌŸUú“PåŽÏBe§[w·ý1-ËRíÏK¡øŸ¯îJ|W‰hÔ²äÏ[=W|Çz¯2àÄ¢eYÖãW?níš¾ËúzÝ×­~ñ‚ÕÓÓc©ªjɲl…ÃaKQ+ ZápxRÊù‰T¨Œ¨6“Y·‰ª/>%»¹z,˰,«Û²¬ e>ï°uÇéwXŸ]õY«_é·ÞUÿ.Æð ZÖ©§îdÝ6Ñ|oõ÷[–,Û?éËͲëïï·‚Á ¥ªª¥ªjÞòWÔçÆÀ°çF£Q €Sï£É7–2‹&³në¾î±Yè#\ìŽ(ÖmGV(>ì¸|kö[–¢(™;T5«Í‘h<&¢ÝvL#TÆ£©© Y Û@2™D}}½3ú¥±±H&“³¯¾ú*’Éä°Q3bĉ®çïu æ’½»ýþò|ÓY‰Ñ/¥N×!—­p8ì쪪Ð4 ¦iNøT+îMŸýì* ðÁ~ïÿÓ°¬@–eô÷÷Ã4e<ýôßá¹ç> >ˆsÏý´ó¼ÖVà¼ó®D÷¹}8öØÍØ´é&HÒLH’ÝÉß™šÆgŸ÷PH£ìm7Mûñ"Ù=ÖΗÉd»wׯ”#ŦØÏ±ÄçîÝ»Ñ××7lZ@U>:eðƒxïuïÅÿ‚¬ažYÄHIB\ס=ñÌßüÆþÜðù|PÅÓã˜fññâîiÇûƒ‰Ø·•ÐE7ß~Ž´`›¦iÎñQUÕéYèîõ.FÎevÁ>ÞvÏG óæý€Ïé )FÈlØO͊"C’TH’Žÿú¯÷ ¿ü¥’$AU{ ( t]‡$Ùû.:9~âç`Ñ¢!œ~t½;ýZâq À¿Â4e2~ýëFœþrèzŠ¢`ݺCèì<§ŸÞ å¯ ^xa=î¸ãX,^üI¤ôøûŠ~Ê¡ÜñyðàA$“ɢôÅú xÌþ?£§§'3XÎç´­­#SŠˆD€îŸeÏLœø³ßA]õYç¾›Và¼;ÎCëŸ[qü×Çí»oÇæ“7ã++¾¿ß¿ßHzˆ_[[ Ãpb¶škL¥RxòÉ'qøðáJoJYLVÝ6W(d÷€§>·.ãžj5KìEçMÀì1€·Ù#å°ŒGñh¥©7˜föC Ü÷»Ëpqá!.>d9û~±¨M<ž)çÝuuðO¨ifæ Ï“ý‹ûtÝ>.î2#jÅm±˜ýúbÑ:I²ÿÖuû5Äÿ9œÝ»wãíoÀ¢JŸq›Ìºm.Ó´cÓ4Ë7¸¶ ÉG"H’„žž´¶¶Âï÷»þË7óÁxLæˆ5Ê644„ÞÞ^¼úê«•Þ”²˜¬ºm `ՅٯǑF¦ë¶¥Õm›ššPWW—uŸ¦úvà*ÙÌ*¯8€P(ÄkK·¾¾¾ i·ô„Ѝ|Ö××ÛÁÜFúúú¼¬Ûþýûó^tÆbvA91g¬¨t–£@uOÁ¥( ‚Áà¨*°c© æÎ‰ …œ©Ab±XºSu†‚O$ñú 6á±Ç.Ä¥—ž Iš‡ÖVà­·vaÿþð ëöùmɲl7®Þr˰`¸Í>’$á¿èÅ]wÃ0`—㡇šðÒKÿ„Ÿüä"<øà-¸ýöá¶ÛêpôÑðÐC³ŸûÜcxöÙÛpøð¥xç;ߎw¿ûxÌûG,[ö~ô£kÚZ‘ˆ}M™o9ŒRÔRBe¤ØÆŸ»wïFoo¯óÚ¢= _»ßßzožû&ŽþöÑÃï4M»6,IN#„$IðûýÎúCÝc\‡d”²(SnÂÅç³çhÉýòë²H’ýe5†XöûýÎbnî†×h¿ø~ÇV¬ñ$/bÚBú|ö´m¦i" AÓ4tww;kAèºî¼ŸXÕ4MgZ Y–±r¥ä¼‡x-1™,{÷îÅm·}‹éÉ®½vvïþß‹3Î8ÁàÛððÿÆîÝïÀöí¯LÞ9Ÿ@åŽOqÑÙÒÒR0¡§s&‹Þ–^(F:aišYŸqÃ0 i‰[ŠP ž\%ìG·j ¦ÕA9?sÿác㹿u·Ôá Æ°ÿ ûñùùŸÇ‹ë_Äw_ÿ.Ž]q, ‘H8 jº®;1ä÷û³Ö°ñâa©T }}}Ã.¨ªÕdÕmÝÄWýý™iKr)Jþ¼þk_x ·s+ Ã@¼ÙNŒWSBnÌ"¤ç¤µÿ ö ÍÍ™ÖoðËZwÒØð0Œì„`ß‹eÞ#Ï^#ML ê^_ÍM¼¶Ï7l]*H’=›è1–»Ð ¢ØÛ/3‰”¥K3óM‰yEb§»ÛÞF±V\ºb¾hÑÝH$ÎPýåçdÔmóÓ •³jj†“@‰ÇãεŸèÈ'Ö­¤Ú588ˆd2‰ýû÷WzSÊb2ê¶"ÇÚ—’"m·7Œ¼ml¿¥Ñbݶ´ºmCCðc¤ë€òÀ§>0ì:2:Ö†:"—ÞÞÞÚH¨ŒdpppØm¥,n4þüaómjZæZi$š¦¡¿¿¿,Û.’3áp8³ð50)ªªfõRĦi:˜â÷dùÎwŽA$²?øðƒØ×gñø˜3Çp®ýþÌu­,Ëαrï\.¹¤ ‡©yçëM&wà»ß=+V<…TêA„B?COO?Þzë6|ìcspôÑ¿Â~´¦)cÆŒÿÅÿ¸ûöíÃ7¾ñ –/Obß¾G1þ§ñÅ/þ EÏ[(‚ßï‡,Ëèèè@ggç¤ÛJk|®Zµ*«§‚X ~Øõžì¹kÚŒ¶ü/$ºÙjš“ýÒ4 Á`>ŸÏ#RrFþÅì ßç~»»í/5ѳUd$÷$ÝÅÊÑÐínts'>‘Ð#ÚÚڜ䋦iN¯úžž˜¦‰ÖÖVèé/lY–aFVŠÅ¹eYF[[¢Ñ(LÓçÌç*F>ýô=¸ì²MxñÅaš&þô§?AUUüèG?*ÿ¹õ˜±ÄçìÙ³‡•ÃÄ£Çþ°{ñn¨¦?Ó9É÷9¤ÂDÇp€,;‰}I$˜øä'?‰›o¾9}?pì­ÇB… Ä#7âõý¯ãoKþ†Pz¦,ËhnnÆO<O<¡P>ŸÏIlÚï©:£Ð¼ð})Éd²Ò›2¡ÊY·uKtuwþÚÏ]wÎ4M¬;wÖî] ã »ó¨ÏTÜ‘ºžYWM”¿îÖlQ†ºGäÆBOOæ±ùî÷ù O¬/Ë…[Ћ]¸OäHõ‡‘ΕXÎý"±â~_I²:"a#*4Í>~Ýݘ={êêv¡*…”«n›¦•gQkÑ&‹9õ#Ñ[W\oŠÆ¦‰˜™ Ðwƒ“õ“N|¯ÈrþD§kd½sœ{Ü #»–ø~Ĉ¶x Á :::Ð××Wé=Ÿpå¨Û†Ý‘O4ù¨ª›"o]Hk+“*4:¬Û6bÝVŒ»ßu@ì·÷Â'§ƒÓ0ðÜsÏáØJï0Õ„ööö¢I¿±ðLB%_Ï„T*Ut8u>îéò)×"A×u'‰R‰FŠ‘öCôÞÏ“b±˜3½ÏDn«Xp\¬n·ƒK¦°¯ã$)3:D–3Ç.ia¸üµžnXŽ;ï áÌ3âòËÏÁUW ë:b±nºÉ¾À8㌛6Ý‹/þ>ó™A´·ŸŽOúÞñŽK°ti+W~ ^¸7nÆþý/à+_ù,ü~?vî<G}7Üp9®»î;غõüà«ðÆ*6<òÈ#E§å¨våˆO1ËD¾¶†]?Ø… þ\†Ã€¦! ;£¼Ð8˜WîQ©Fº@·çkdÝ`λQ¨‚ d’$9øî^%b‘m÷ãzDV™)ýÎk‰ øÜ^˜¹‰51ÂeÙ²e;“¥œå'  „ßlàОCøÉ_~‚¯^ÿUû1®ÆÌÖÖVŽL…ÜN²l‡®¢ÆÿûäKv£­Í•\k¿ý3C›Ú„}a ìZµ œü,Ë‚,ËøñœÑi cÇŽx衇 iE™#<¢ì±‰Ì€ÍžžâSÕff‹²§õÒu[/ÛŠsŸ xùc Ýß)‘ˆÝ°(-%»²/:$ˆiºr;4\§Ð«6ùb;ß¾øýÿˆTÕiu4ãÀ;Þñ4€ã*½Gj"â°æã–KKgLUUÅÒ¥KQÁbf…É\ W–åae»¨k•­þ/ÞEFÊ=‡·»S¦e2ËBî翵5ó] I™QXB,–¹h£Òr;[67gÿŸ;¢uÞÝ“ÓÝ /†*‰}ß[î}!wè„®Ûª)6ú¨ñ el|>ût¸§þ"¢Ñ){ÙŒý€r9`üÐÈ”oºŽc¿üe^_’§y&¡ÒØØˆ®®®¬ÛKÊvº‰FÛB…¤hT+]×ÑûÛßâ„éÓ ®ëÎ싸Ü.¹½P€I© )Šâ4°d6ÍtÖU(ï{ٿ݇Å}¼Åx1Ó‚$e*ëcÙÃÃ4çà _H8ïånıªj¤·©+WùÈy€­[/Ãc‡pøB47óç?†¶¶wáì³À/~1G}O?Ý€;¯ÄsÏ}ïz×WðÇ?þ‡÷áöÛÿo½õ¹ :kÞQŽøÔ´‘—yê©§°¯u_Áçë†S’`†3êÁÓJX¥lD|åKN´¶Ú=Ps¿§Ä…*0¡É—Ü îñœ·BßÛù.ìEÁñÇ?aûæå*?tžÄÐ ˜7á÷x ø„ñ‰ìu¾Ò CÃ0˜L§hÔîñ£Û| üw~ñßý¾;.Ëz¬iPIT¢ÀâØb,–1&ð¡3>„#ö™Ñ™Ð yè/8ùä“qðàA§¡Ž&G9cSËb”Ú–‰DÇá÷ûíé5%ÌHYb1e–{’û`0ÿl‚8 ¹¿iÔdxä‘ÙÞ¨ô¦L¨‰ˆÏ9sìã7Ö¼u,sÖÉêééqFñ»GèOÊô'¦ ˜&Î@ã¬YYw)²Œ `'8EÏ9w\Š€;!’Û‚ e¾†O¯Ø£ñ1RCQF^¤FŒîV”üù‹¹ túq¶»U-~_lD0hë)Öb¼ñ‰ØÜSì÷gf9,¦ÔÇ‘7ˆv.Y–aš¦3 ?`·ÿ‰†z1E®˜>Q|Ï꺞µ6¡è8í&ÚÏEö>¦iâé§Ÿ®ôa˜pe+; @ÿ6 H@8]¬¹Û*5I‚fšžîÿC䙄JKK‹3/hKK úúúJ¥°fÍšQ½Ž{j⑈©‚J¡išó¥©ª*žX¾«††°tÖ,Ì>óLਣ²Kjwå0_Ï02=jDâEQ2~"á’[9MWl‹ÌQ&„EA[[›3XØÉ½¶`÷†oCu¾Žöú²3å´Øír¸ðÂÛqï½fÑ$™»ÁÏ=JbݺKŽNv¨•øÞ÷úÈøÉOìCþ‘<…_üâlƉ8ùä>š>-ßÃÆÿWžñ°rħ,ç©”š° `ágŽøÜÝwÞ‰x2 ŸÏ‡D"áL³G%PUûBÌý'zÉ€¹Ã†Ä<ñb8yZ9âÓ0ì‹OýN q7ÐvèN¯ ÈØø_Bq7f¦Ë½Ö¥K¹Pà8Åb™ïFߦÀ Ze¿‰XzÍ©x04Æî™ß}‚WeŸ @8]mø ½ ˜…YNrEiµ§ùÂpÝ“×á¾³îÃóŸÀ»ïįû1^²pÌÛÇ‹JÎúmî„b*¿©8=L9bSÌæèÎe–ZMëë¸G÷&ªÈÝS[Ó²MÓnDõX1dÕ½]¹Éÿ\UürŽ×u=«€”î,bšv]6‰  :1M‘H>ŸoX,å« ‰µåD‘èX$¦×@?ÿìgqöÇ?ަK.ÉÚÎ×^[PéÃ5)Êuí)ˆÆ×±®›¢ib±‰"‘ˆsÎ'}Ta àt<ó­·0çÑGO|"ë~ Èĺ1&ˆŒ’’/n‹íS±DD)‰ 1*E<¾ZIÒð‘3SÀxãÓ5Kt–Rû»ñ2sdîǫ̀mf¢mÉ]扙DÛšmg†³¦¦¦iYõIQŒÇãÎãDùæ÷ûõÅ âG”}@öÔÑb]a±€Ýö%:‰ÈbVÓ4áóùÇmS/Šõ¬Ä>‰òzîܹ٣ÌkP¹ÊNí íFÀ©ý¿,øÎ¡CNaê¾¾ ò*Ï$T ££7nDSSz{{ÑÑÑ1êEt½xA™/ÛœK|Ù‹ƒXàÝØ´ çúý8z¤'{óBÀx<{œxnB%ÈîQž;¤8}¡”ÕàåúJ$ÒƒahmmE4uÖ&‘$ º®#8ÃËÇ2œ[¬¹éVjk,::êðÈ#ãkô‡7ÓAJF0˜9|—]v:î»o),kFÖó$IL‹PÛS~ã‹Oq|ûûDøÀ¾Ö}عs'j ÿ“ ;?úQ„_{͹‰SÖŒ‚XèÞÝ —HØ­¸ùæŒÑ4»e],p›û]d.’É3Æ[~Æb€r/ ¿„nrS¦‰?ÿ9þðàœœafº®£§§Ç»ÓîU‰Ü¯3±xªªJYs}›³ üíWÐÂ=h;ïßáÿÈKð߸†‘á"¿•®¤O“ѓΧ*TàÒ#/ÅÏîûÞÞÿv¬ûâ:ÄÛâX·hfo˜îD7–÷.ÇŠsW&°÷Ù½¸~îõøÜêÏañ×:Ї ªªsñì÷ûÑÜÜì$Õ>üácúôéxå•Wðâ‹/bÉ’%hnnÆ÷¿ÿ}Ìš5 ’$áÒK/Å}÷݇?ÿùϸì²ËJ?PUj<±g¦G”u½´„ʃw<3fâ¿¿õß8.rœÝAÔÍ&¢ƒ»˜’k¤:®hÜS÷䫇{äÂÙÝXd†ÓÈ#…‘H~¿‘Hªª:×b$¦i‡Ãδ¢áF¼†h\ …BNޏ.q?F’$´µµ¡»»²,;B¢þ./¡P===hnnv¦Eq·D£•ئ¶¶6øý~|à¹çðBOš7mB0tÖçxä‘•8á„w˜5ÖCX5Êqí)¸ÛïGÃ=*Eœkq.*2ÛÕ }sk+‚_Œåîû»»[ºÁ‘êâ#%QˆFi¬ñišÅóóÅø|ž)’J"’¢Lr'D¦ªjö€tr" :eH˜¦é$*Ü#?܉ q»H~(Š‚@ >~>'é ( š››×ÄL/ÍÍ̓ƒÎ6ȲŒH$Ó4‘H$œíK$Î4¦býb1 ¢,ËN§ËîîngÄIww·óœ§ÍK”é¢#{E‹ÅœkQ¦ŠçˆNDÎ1­•é‹)GÙi>øÏ"¿‚§û¯¹ïÙ¿ß)HÅ9&ò²i–eY•Þ·T*…T*…†††’†­_¿[·n`žÍÍ…;qˆ/æBÁ©iæ<ú(Þþ½ïaÞ®]vÒd ¯ ‘R¾8rãtßîNº¸“žJá‘7ßļ#Ò…‹išPEouU…™>N€Ýû4 :Ž"1" ‘t2M³bdÃ0ÆÝKZ´Ï™cÿÎí8¹tiþÏVgg'ZZZj~`tñ™L&‘L&ÑÑÑጠ˰¸Va7øIöú âB>Ÿ¿þøÇ˜µ};fßtS¥w¿zE"Ňî$7y"þ pŠEmE¯c‘†%u+Á]FÔºÑÄgîq }þ'‰ìƒiÍvŠ<‘|‡ÃÃv𛛯š\æý!|__ MK‡ÙO~‚¸¡@{n ¤Ù¤ùG!ø•#‘o–/IŽ:ê üõ¯Ûqß}÷ácûnë¼ Çá8|ãsŸ{¾ô_8nàXóò?¢ã3+¿ýöo±lú2ÌÏ|¼xøE<ðüX¾{9N{ÛiøÝ—‡c6ƒÆY˜¾z:¬Ùî}ó^üÓÿû'|É÷ñ¾+Þ‡ÏÝÿ9¬¬[‰ÇŽ| gÍ= ûçïÇ¿|ã_*}8'ÜXë¶b¡$ÙuQ7)r†a`ÿÅûñü+ÏCQ,¸|ÁÄŒH1M»¾é†SwoØX,¿ßïLÅ!ê§bÝCÑ$EÜ ‘H$â$S$Ir!¢ƒ‘ht2½ZÅãDoY‘XNÁ`0kí0Ñ»ÕM$VÜß±…¾_ó­ …œºz81Ñu4gŽ]±Mï›Íòãÿ?üá¸ë®Y·Íá®Ûæ—`¥&UÄg2ÛÞ\çÌ4MÌ™3'kñùJp'³÷µ<ë‘ÒØ°n[ø¸ˆÁã™}9ßZH¥‰sQFÅb1'¹!¾EBÜ=ÚÃ]¾‰rG$5Äÿ"Ñ ’±X @öÔËâ5ErÃ=ªQ–e´µµAMp'MD’F´ ¹·Ot8È-ƒB¡t]U{(;«©ãÖªU«ÐÖÖ–ñõ3žv[0ÿh÷óÑŸäC;PõExæŸÿ}þóàÔçˆÊe"Úm=5B@É™a.8c±˜SiÍGL"‰0磌ì;ñ5H–j4Ø‘*±…ÂNï÷²Ï|o¼ýí˜ç~\‡X¬ÇŸ|%v÷4¦OïÇ {¦cçÎAXÖ?àäÓz`[q8´çœsÎ>ûXȇuðÔ¯.ÅQÇÄðÈé{ñë{gaþS[1ëÝÀü…ÀÂ/ Ï|¨Ò‡rRŒ%6c±ìÆY1ƒN¡6Ìx<ŽP(„{ߺw^|'.Ž^g¹ñèN”䣪ö—µXÌÔç³G¼ø|™äŒø"Ó ºßw¼cøi˜Øu@ðâÛDàëé/k@’>ìâH\ ’Ç›S^’üÇWÓ‹}§cíò |/+0ÍÅv9»¯ã÷8pàêÞq> ¼Üåùç~þóÿá‚w]‹nÇÖgÞÀÍ×)8öØÇ±ðƒçà‡¿8sçâÄOž}Úƒ3 µ ر‡þö-|è?gáÙgÓ=¸Ó×Õ—ðÒC¯Wú¨yVîÔ^Åú«„B!hš†¨?ŠSôS&~áê¿ ÃÈj0àô¢ …BNoÜH$â4Þˆ^ûœ)ic±º»»zgº—Kww·³Î!€¬)¯Ä¹Ävä~·Ur$Àx‰:÷¨ö!§ËÝx6kVíO÷UnÃ` Q¦jÀÞÅ{Ñ÷}Ø·oŸ=Å?hO…뇽&–@±Ÿó¿ßú_4È €ž¾Í„ý·šy½¬¿ÅcܤœßŸ‡ã‹÷CúµcéßJúv9ý£§_ßLß§¹ÞSËó3}» { `Ýõ^Áôq‹§«öc‚øíòßbÆ«3ðÄþ'pÉÂKðÃþþ䇱ã®xÇyïÀªÏ®Êl{úý焉%ïZ’9â~ûæìÃà̓˜¿>žûÀsXúèRüzð×hüd#ÞúÕ[8´ðzgöBÒ$Ìzï,œ2x Žºì(üî'¿Ã'ßû$NúåIøëÁ¿bðƒƒ¸é¦›ðÓ¯ÿŸüÑ'U£¸íû·Aö˸×ý8÷Ås±èð"lŸµW%p90ãÕ8é¯'áè·å3—£iaž}äY\ºâR\tÑE88ë ßÛˆïþÇwñ‰s>GyϼöÌä}°«P8<þKY.<»±».,Ê9ÑÆ$fúÈm³‹Ÿ‹Ûó}_»Ë%wÂýØBm!#ÝÇ$èäyá…*½ ÞgÆt×e‹ß["\þüz¡CQ)j*¡"æ™ÎGLM•/0ãñ¸³`^’4¥× Pž’‡1?ߊóöƒpág?‹ŸÜ}7þù™g°wáB§çMww7ŽüÁðÚ‡>„ïHÞö‡?àÕ·½ u? Ó4í¹ F<Žc-‚uæ™0% _ìíu¦YpÏ#,ÁÓŽå‡ …‰žŠîy5KQ‰éŠkþ¼6Ïí#¬g$’g±X ¾h8ñÄJ{‚qEÉ$PÄZ.î) a‰Þab±Ì˜|Y¶Ÿ+Ó‰˜c®ô^{šy? î‡ò§o [S'_[Ó4D".D_D3OL‰…5áóa†ß€ÝÝ:ýy¸æšk …ÐÕ­š‰+txé÷ö“­¥øÒ—dÇØÿ÷C]bϘž` ønXÅÊ•é7‹Å€H¯Þ1V¯ð Ðp#-¨›ÿ±öº===vƒá$ä;ÿÝïâ”~¹æw[ºt)Âá0B!{Ý`0è¬Ý!F9‡ÃaÄãqø|>'A"êwbúÀN’Œ4íC¾:„óyž‚¦ê~WTºqÞßH›a'Hdd’²}Û£Gñí;¿sŸ‹¼þ|ðÀíõ…fd’ q ÁhÈ<ÆŸ~íhú7`Ç{™ä†–~_q¿lo‚éljiwôm2줅HŠì•í×hC&Ù!ÁNˆˆ÷€섇X{9˜¾-‘~Œ‘~ž”Þ‘hé¶ŸófÝ›H–Â‚í °ç®=8úœ£ñZïk˜×9›ÏØŒ+_¾/?ö2Ž|ìH<¿ãy¼û¿ß—ßù2Þœþ&>øàqò'cñÚŸnÏu8°ý?¿u×Ôá±_<†:o\ù†~0„N8{öìÁ‘«ŽÄíÇÜŽ#w‰ó÷ž7Þx¿ú—_áÃ×}}÷_±{÷nXq‡×Æ!ß!÷§ãð§—ÿ„÷Ýõ>¼tÞK8õà©Xöü2Ä—ÇÑøµF<|ÿÃx}–Ý!àô[Nlj:‹žX„ãŸ9í¯´cÚiøåž_búmÓñ•~‡~z+—®Äéï9Ðó´ó€ °@_`«¸}¬ÐSwŠÍ›ñʯ`Ùôe˜yÝL¨QЀ<÷Ü´„Ó DÓìþXãíSàn6kˆ“îbŠH÷Ú%===L`LQ§v8PéÍð> ð_•ùWL)'þvw²!ò²šI¨˜&€×\mA®ž'@fÍ\¢¡>+`'cÒÌjãÎTå»XK¯ËÒ¼?ùÌg0;w¦iÀ׿nÿè: (¨s^JÊLk âÙ{ïŃ>ˆ5o¾™µèØon¸'n܈#N9o=÷žß¹¾ÛnC,C(ª#ÄGð¼xø0N>âü§,ã'›6aÁÅã´­[qL2‰ßlÛ†º•+ñÓ—_F›k‰«, ·ïÚ…óÎ;¯¼ò Îü‡€8=MDOGñ%¯Ðx@#3öÒùÃo)¡"ÖUqmY)­=îïXK…¦,ÌG¬Ñböw‹»·m0D"¸è‰'*½§ž¦=øÞþ„=U[ÎwšX$RˆÇãÎâT£ÜßÇ9 تªLÊŒô¼¼÷ûýx<™Ä‹Éd¥÷Ø“^yå„’¾ u]G$®ë™z¬ »‘´ ò-Úà÷ûqö¡C8úŒ3œï1 EÔĈp1R‰LÓtFžä«TóHšbâ° 2{Pj?2‰@xðmâ»=ß…òaŸ~Ú~®à;úa_³ºgyI v’Â×ôs€LbD0'ý·™‘+bI›ýú;Ûwà‡?Äšg×àô;ukëìD‡–~]NRb­e÷uõRû}tI‡Ò­à±]áͺ7qä¼#qÚ{OÃuŸ¼þ°ß™ÿ¾ócø^ä{øÚНátýt<û泸äºKpkòVø5?~­üK._˜;w.>¿äó˜¶oùA¾UÆ uð`ž<˱h–ËË/x0Sš‰ÙòlìýÆ^œpã xù^FÓ%MXxÅB@æav|yÎ}þ\ÌÛ1Ï>ðQßGqàðÈ7ËXþÄò¬‘+çá< Õ>·s‚sœ$õÒÀàÂØ…™ó–6ËœeŸƒnûøÍTg:I¥™þ™8½õtàŽôƒÅ¨#v"­;}Ü]ÇyI| ð;Ò×íÇ¡³þá¬Jò=K×ËsÙøË_Äc=†W_ý¼3»†$Ièîî± €eQiôÐôŸþ>_+žŠUÄišYF€h,j&¡¢oTv%O‚]™L}œ;ˆ·îÀ¿þß¿f†@êÕæì›3üb.g2eœ6üçBÓ´áóe:®²ŒÕYÓ²‰Š ¸ï>@–q„ibIz*1ßlÝùç£îë_G]z¼ý‹9Kò Â[oÌ1ßM?_UUñ³ŸaÍããØÙ³ñë®.<ûì³øãܹN€$IسbêN8Ý|³³fL À¯, —ìÝ‹½\ãcDƹ9ýX^×qøØc±£§'û3‹aÿ/~_65aAz.p¢‚Fºx‘$ FüÅqQ¥·ÑÃÌ^@ùÂÙÃ`ź¢W¸˜ë™‹S“ªª<÷“hæÌײ{ׯãöwhÄ1€Wú@tÃ?Ãkª,gF‹Þ䦙¹m ­Kb<±ø-€¬‘$ðùIBô#A<wæs ²‹z\n/ÝB ¦Uì„COúGŒå°€S¦š¦ MÖz)„þßå,ƨfž;LÙÓu‰¿}°á‘ý>º®Cî—Ç¡*B¡ü~?­ÜøåÑ»¯V̲ËñO«øô!˜¦‰Ý»wã¡cÂQúQØq×­¸ ؉ÀôA Š9o%zŸ_w>~ÿäïqÀ8]Öõ‰îZ~Nù×S §:=öeYƧ¾÷)@.3.³¿ÒÕúð%a@dSÎ$€ÙçÙ˜®ãẬœ÷ÙyÀ°ð’…Ãî[¾|9ð×sÒ÷ÍÚ8 ؈üS£ù]¯‘{»„áçM$¿òm³ØnAq=¦ÛõœÜ×ô¹¯dþÞ9w'Γ*ù˜æØ§î³#躎¾¾±xñ§ÐÝÝ=!£Mò­ÑbšÅ¦ËLE&–Ÿtû-–7—Ò@æ½Üï!ª î H$)3+³ßoÏ#ª¦iß&îwo‹˜`À½ ¢N,–™ðELÑ‹ |ÛÜÇÀçˬ[%fÎå÷Û˜¦Ýo,É~œßŸù_¼_î1SÕÌ{‡Ã™™¨Å~~z6„Ãö¶üö·_ÀÒ¥?+ûç¥Öh·iÎ<Ýù`Šú&`wxçRT-j&¡¢ý¯C¦w‡»² ¾3ŽÏœòÔ_Uïô>y¤îÜ»÷^\}ÔÕvÏ ì!Ï€½Ú»‚J¿^ÙóÖ™!Ó†Ïk`øðhAÜ/z¡ˆye‘óQÈVaç|I’ÐÖÖ6êJHÿH+¿»_õƂ˜‡ÛÉb»—õ¾®/å—tš¦eTUÌN߸é&˜¦‰¦_¦ 47c‡,ãßZZ€xÜù‚‡Ãø¦¦áàÁƒÎˆwNzðÏKÿ‹9ë`üò?ÀòÓOwgš&Κ…›_}ŸwXÖ”žjhRè€ï;97¥×/pDimmE"‘àD“ਣöC6uàÔðRºbùc¸K `GÓ¼»›§Ÿ„Yíé¹}Ž÷7+vOôn’‘½`×…\[~ÿþ÷ãälÿë_±fÆ <1>æýüçhkkC8Fw4šÝºeì´¤¤¹{æ.Èž‹Éª qdF‰¤™‹õ#™ÿu]G p¦·Ëk¤"u„þgš®A «N§1ž˜žSÌ à÷û¡(Šs]uúE§ç-¿ã7Äa|² ֮š .€râ‰Ðuº®Ãï÷;ë^:ÏâÂa¯õ…[쌅š¾XIxÑq1oý¡PÃwÏ·ô ÙI 7çŒd¤¯11Ûh¶MLÉ6šçøFÞ†»WÜ Øá,]/¼”c.Ã0ðæ½oâ®»îÂßÏ|æ3ø÷üwüþ™ã¹Àv õJ¯¾sÃô¾Ì¬Å>ŸÝèÞÖfîFwñ˜`Ðnlw'Ò};DDwwæyâ5D‘ ØÏ1ÍL²D Ð7ŒL²B’²_#É<_×3 1%šx¾HîÈr¦ˆw÷ÉÛè^WF¬óÛ÷‹Äˆø[,™)f{ï#ú†ˆÇËrfŸÄk‹}qÿíž9Zl§Øn÷¬Ñb[݃¦U53¹8¶"Y$Ë™¤ˆx¾ûØŠãØÝm?W×ídJ8œÙîX 8ûìvíÚ]ɨ Ú+óýïsœÿEy kd3‘×ÕLBÅŸäÛrn Û´ÿÙüŸö´Ré/;1Í×ÕÊÕÙõ’f3S‰KÀ™×ÔY\OP‘™wV$I$8så„ÝÃÈ=Ÿµ„LÏ¢xúyq×c$d5þôíºëµ}éljßfÎ}ºNíîîžðázâËv4 Õ‹uWFº¨Ïº=]ëùeA–å¬9¼EÝÎÎÎ ÝÇj¿ÞŸþÇ5µÞ7î½7kª½XºûÇç︃ .D“$¶ðç„›è$â0‹e$¢‰uìáÃÀ{Ú€µQàj¦!î;c±¢¿‰bV¾ºOéÆXH'E ðG×ÔôÔ @_ÿÔ§pÆ{Þƒµo¾ SQ0¤ë85=2X­ ¹ÝF‹­ÔKTã?»¸p"vãP[[¢Ñè˜G÷9k ¦'===ÎZ@δɀ3*>õÐHSY×iéÇœ˜ç>6nQµð_ H­éLØI6ÑA¶ö´l*ðúë¯ã•?½‚Lÿ/^ŒOZŸÄ—þñKvyû{@Ùø‡é@÷µ€ñÿ¥×õz¢øÕÈÀ€v›NH¤§ús:újé¿]#«ü:†MÑ™su ‘[¼Çí÷ж!?ìéÿÜmKrúyºýø„˜ºOŒpÒŸ›éí §ïû‘î?¡¤·1 ¬Ø¿ÇÄ 8!À/:%G\Û*Fߤ×mRsßéÛÒÛîw·ƒNGgéý ¥g¢ûš^OJqwvÖrr–éǨâï6@Ó(JéÓwÛ]7 »ÚöÄ>¨îb{[T  (q8íq ¸ûÅY¸ÿàIeþTט[LGÊ®QS&LÓ„,ËYë&UƒÚH¨@ëÞa…Àée'*ŸbŽç‚ ð¹Š"¦sëÃé9dóö†q¯¡T¬·Œž~Œ{¨¢Ø<ñž"q" IÑ1„Ì(™…LòÇçzž¦Iÿ-’Apm6*Ž’!ê¹Ù·Åb1g*NÏ7 D“è~8r1€yÎMZºñT4Æèé}£úÎ$¢qÙÔQÀ‹ýÃêf¡Pº®gFØæ£d/î I’³| Èžº+MB&î×]6‰Èqor%Œwf)ˆžä™Ú†3J¿Ô_bÚ<‘ …BH$P%k¤‰¸æÉ÷º¦ifÍCO4ù~»]Åݾᾼ´ìimc±|Ÿ³žWö‹dúª Š{-БšÜÅ¥èë˹ÍõNŽ»·X‹ÉM¬©$¥Ÿ;ƒJ.ÑQW¼–Ø1ñœndϬ’ûþ¢³on•#‘Þ?ñzbßu×k¹÷·Ù $±þT7ì/S÷Œ-bý)`ø‰·‹ÛŒœÛázžû5°PbªF÷:Wbæ˜@ξˆ}h†“ÐrŸ#ŸÏµÍé÷z훯᥿½*Ì÷iÎߢã`'ïGÓQš¨Òj"¡bòªÜM¬Z…»îº loÇÊóÓÝ $){U}%Ò vsë¹s†úrþ»çîAà.lØ 1âE0€•oK?V<_MÿL?'æú_L‹&†gŠçˆ¡¤¢g€HøˆíuO‘6±nìú_Æ„Œ¶Q¥`#å·¨ÿ0;êìœë@{(§œžvDÓ46ØU€öûyÐëÏqŠ…x<EQœÞ­î‰¨rÄÈ’|e¥˜ÎË4M§<I“àh&’'¢’Ôtò²éPÏ‚rÃ3Ë_¦“)‰DKò”")ªª*´]»~øaç¾9ùÞ(µ¯WçÌúû3ש¥Œ+V¯v/l ^—ƨ&€fdž%3*ÅçCÔ½Š¹øü»cÖ0²’Àð•îŪðîÅ;Ü=ëM3;ñ™oä˜XdŽ`IîãrÛ«†í®‘½ˆI.M³SqËYOÍIÒºS‰ædZ[³ÿ÷ù²(‰Å2 È}È~N ½Ð‰¢ k8ˆ®g1MûØäÛV±x­Ü5x[[³fi[Ý ¦„ÃÀ€’ýbÄ4áœmmmÍÞ6Ÿhjÿ×f>²º®;kuqt U›šH¨D~ô{È+Ô¬DsLÓÐ{ñŘ÷•¯@×uÜùÚk¯\™y/2‡gæ…|‰"÷m=È Ù£UÒsd"ˆÌú.ÍÈdüÝC.ÝS‘‰×CFÛ^*¶QJ¿¶H¾ˆU22s£¶¥+FÛ®×óvº62 %}»xÝ kÄ6‹ý×Ò»:uûȹx£åŠœB¯;Þ˜}fæƒ&z¼÷ôô Ã4M&Sˆ*Dß3Ê…³œÿc±˜3:¥­­ ªªrª/¢ 3M3ïôAb}I’œíL M¼ƒ³f¡ûÁùæ;·…B!gD˜»#‚a0MÓIˆŠõKž–+´ôÊݹÁ½Ê3Q-k¥“"¯¿þ:>ÚiÐu=3*%È^]=wt–{—XO̽j:y‘¬P”ìÆuñ"Q"V0w+ęĊ;.MÓ~}ñ¾‘Èð䀦e’&"!âžmEU‡o{®R’´Åfpñû³·+Ÿh´ðýŠRü}&k[‹½†¢ O@2Y|û¦8óéui`wæSUñxÜ©BTMj"¡b †ïŸßíü¯ëº3¥P(åŽû§Ò¹‡lŠº‡Ù£a$ä_ÔFÅðá—2ŠWÉñ¹×î÷RGx¾ FLj5b{Ud;2C>ż¢b^M‘„IˆÙ÷Ü>‡ã&ø W§ý yÎëÎÿb3]¹ä<ÏD•c<ê¥vƒX;E–eD"ƒAö"òQn*ŠÓ4‹Åœ2”žD•%’%îâÅèkI’ i¢Ñ¨³îѨG}J;†ª:I ]×ÑÖÖÿš5ÙmAÅÚ…\¯1¢bqéšæoDÅö%©<É}æ^3®b4DîsÜ·{M]×ó~Ÿ†?üá•>$Þv§eæSPÕËØù‚Á LÓd'>ªJžK¨¤R)¤R)444 ¡¡¡èãßþ·ãqë['C¹d¡s[(·¾õ-Äb1øý~NYR äþ ÷|—¹suŠÛÝmâýÜu"Wéñ¡ÇÑ‚–J¡I1Úø|tn¤3N`W2âñ¸3ÝAn/>"ŸÑƧù®sëÅP(„h4ê41™BT>£M!‹9ë¦èº#==)Då3Öø4M­­­Îè°x<Žx<î\{ú|>6ÓxÊÏH$2ltg!¢¡ÜÝ nš&LÓ„®ëðù|Np$ßïwÚ›Ä4¹bÝUÓ4)ŒÄpQ×Îÿ>Ÿ/k­VÃ0 Ë2âñ¸ó˜D"¥K—¢»»mmmY x†á‘X‰F£eÙ)Ãsç#¾[Äcĵs¡khÑÙb =•ø-ž#¬Å(W÷wUîûesJd‰mÉ}N¡©ÀÅû‰Ñ€åØÆ±<§Ð MMMHNi¿Æ›ÚoAQŽ`_¶¶¶âÌ3ÏdG>ª^–‡477[Û·o·,˲z{{­eË–YÏ?ÿ|ÁçœwÞz«»Û²¬+®¸ÂºâŠ+,EQ¬žžžJïΨlß¾½è¾V‹Ûn»­Ò›0©ûqýõ×;ŸÛZ6Úø¼ãŽ;¬/}éK–eY–ßï·.¾øb«»»ÛŠF£•Þ•Q«•ÏôTüžY·n]¥7uRŒ6>׬YcY–eE£QkùòåÖ 7ÜPuå¦eYÖóÏ?_3ß¿µò=Sê9Ù¾}»uýõ×Wzs'ÜXê¶ÿøÇ­%K–X<ð€¥(ŠÕßß_éÝ“©Xæx]©ç„uÛü¶oßnmÚ´É’eÙòûý–¢(ÖÀÀ@¥wcL¦Úgº°n›m´ñ¹nÝ:+ZŠ¢X×^{­ ­h4jƒA+‘HXápØð|̲në=¬ÛfKÝvݺu–ÿˆŸZ‰„Ý6$Úm½^/Kªá{Áëñ>u[ÏŒPI&“¨¯¯GK‹=uRcc#‘L& f;÷í{ßúÖÙøÂvâ­·Þ¿øEøý~:t¨ª²Ãñx8ãŒ3*½)ãÖÕÕ5ª!¹^UÊ~<ùä“xüñDZråÊJoî„K|>û쳸ÿþû1wî\œ}öÙ8xð .\ˆ… VUlµó™žJß3¯½övî܉—_~¹Ò›:áÆŸ{öìÁ¹çž‹§žz þð‡Q___uå&`÷õõUz3Ê¢V¾gJ9'/¿ü2zzzðÆoTzs'ÔXë¶ÄË/¿Œï|ç;سgöìÙSéݵ©TæT‹RÎ ë¶#Ççk¯½†;î¸CCC¸âŠ+pÅW`ÇŽ•Þ•1™JŸéjQjݶ˃ÑK| böìÙhjjÂI'À5ï{ßûª"^Y·õÖm3ÆZ·}óñٸ׺ýÛ»±sçN¬[·~¿ß31éõ²¤¾¼ï»v횺­g*}}}Ã~}}=R©TÁçÕÕÕá©§žÂÅ_ŒÆÆF¨º!±/½ôöíÛWéM·eË–Uå9Ë~<òÈ#øÛßþ†iÓ¦Uzs'ÔXâsΜ9˜6m,X€óÏ?@uÆ&P;Ÿé©ô=óÊ+¯`ÇŽxë­·*½©n,ñyâ‰'âÏþ3Î>ûl,_¾ûÛߪò3~øðaÔÕÕUå¶çª•ï™RÎÉîÝ»ñÜsÏaÅŠ•ÞÜ 5ÖºíáÇ¡ª*vî܉;wVz7Æl*•9Õ¢”sºíÈñ9mÚ4wÜqX½zuÕ¦ÒgºZ”Z·=|øp¥7uÂ%>§OŸŽ `Ù²eU]~²në=¬ÛfŒµn»{öã˜[¿Gq®¼òJÌ;×SŸ ¯—%Õð½àåxê©§°{÷î²×m=“Pv[)Ù­ßüæ7•Þt¢š7–ø¼òÊ+qå•WVzÓ‰jÞXâó®»îªôfÕ¼±Ömï»ï¾Jo:QÍK|^pÁ¸à‚ *½éD5o,ñùóŸÿ¼Ò›MTóX·%Ê8¢Ò Ô××»­X–“ˆ&ã“È»ŸDÞÄØ$ò.Æ'‘w1>‰¼‰±I”ᙄJccã°@ôìlDS ã“È»ŸDÞÄØ$ò.Æ'‘w1>‰¼‰±I”ᙄJKK 9×úúúJ¥°fÍšJoÑ”Çø$ò.Æ'‘716‰¼‹ñIä]ŒO"oblexf èèèÀÆÑÔÔ„ÞÞ^ttt ®®®Ò›ED`|yã“È››DÞÅø$ò.Æ'‘716‰lÓ,˲*½n©T ©T 6Fä1ŒO"ïb|yc“È»ŸDÞÅø$ò&Æ&‘*DDDDDDDDDDDD^ã™5Tˆˆˆˆˆˆˆˆˆˆˆˆ¼Š """""""""""¢"˜P!"""""""""""*âȯ~õ«_­ôFŒU*•B__ ¾¾¾Ò›SpÅ¢M©T õõõ˜9sfÉûQéýÂK/½4êmóâ~åÛ—ñž£JŸ/ª–cR ç~¤øoüMö¾ۑΑ×ö£TË1©ös?Ö²³ØýµRvVj_hüúúúpôÑG—í\Oöç@¼ßÐÐÞö¶·•u['c_J)/ó-[MçˆÆ&_lÕuî ŧ×ë¶¥”ûc‰ÏJï•ÇXâÓKç~Óã¿JìÛHß3…Α÷Ãëªé˜Tû¹KÙYìþZ);+¹/4>Ï?ÿ¼ÕÜÜ\¶s=ÙŸƒë¯¿Þy¿ .¸Àºúê«Ë¶­“µ/ùâ1w¿þîïþάÊsDc“/6-«ºÎ}¡ø¬†ºíHåþxâÓ ûEã7–øôÒ¹OÙ9Þý,ç>Œ6>«a¿¨°‰¬•[¹ëØåÒÛÛ;auçjWµ ÷­··×Z¶l™õüóÏWz³†Y·nݰ‚s4ûQÉý¼í¶Ûœ“|…O¡móÚ~Ú—ñœ£jùN¦j:&Õ|î }¦Ç“¹ožg #/íGµ¨¦cR­ç~½\·-TVŽ7>+ý½Cå1–øôʹoÙ9Þý¯ñħ—÷‹Š›èúQ¹•»Ž].îc688h]pÁÖ=÷ÜSÒ6ÔzTå*Édõõõhii466¢±±Éd²Ò›–w[ó ++e?*½ŸMMMhooGcc㨶݋ûUl_ÆrŽ*}~¼¨ÚŽI5Ÿû‘>Óã¿ÉÞ·B±Yèym?ªAµ“j=÷c-;‹Ý_+e§ÎMgg'ÑÔÔäÜVMŸé¡¡!™éêêêÐÐЀÁÁÁqoëdìËHñ˜J¥ÐÒÒ’uûêÕ«KÚ/¯#›|± T×¹/Ÿ^¯Û*+ÇŸ•Þ/*±Ä§—ÎýxÊÎñîg9Œ5>½¾_TÜDÖÊ­ÜuìrI&“Ć Øñ¯iV¯^]t¦BL¯ôŒE__ß°‹øúúz¤R©JoZQø\sÍ5H&“¨««CGGÚÛÛKÚJï§øâÉ7Ï]¡mòÜ~´/ã9GÅös*ªôgv4ªýÜô™ï÷ÊdŸÃBß3…Α×ö£TÓ1©æs?Ö²³Øý•øÞ™ˆ²³”ûÉ{úúú°mÛ6Ü~ûíØ¸qcÖíÕò™nllD{{;®¾új´´´8IAq¡çõºíHñØÒÒâì`Çç¶mÛœ‹ßj:G4z#Ŧ¸¯ZÎ}¡øÜ²e‹§ë¶…Êýñħ¾wh|ÆŸ^:÷ã);Ç»ŸåÚ~ñº¹ ŧ×÷‹Š›ÈúQ9MD»\R©šššÐÕÕ…mÛ¶¡®®íííe©;ׂª¡"2Šn#õ’¬$‘ݰaž~úilÞ¼NF®Ø~xy? m[5í×xΑ—öÃ+ªé˜Ôê¹oüyiß £jÚ¯¨¦cR«ç~<Ûî¥ýªåú 744„7bóæÍ¨««Ëº¯Ú>ÓuuuΤ¹µP·Ý¶mÖ®]‹––'ÁYmçˆJW(6ê;÷#Åg­ÔmGŸÕ²_”ßxâÓkç~¬eçx÷s2åÆg­ìÙÊ]?*—‰ªc—K*•rF›lذ X¿~½“™êqP• •|Ùe/f¹±uëV'{×ÒÒ‚5kÖ8 ÅöÃËûYhÛªi¿Æs޼´^QMǤVÏýxãÏKûVèUÓ~xE5“Z=÷ãÙv/íW-×oh¸X,†ÆÆFg ŒÁÁAôõõ¡¯¯¯ª>Ó¢wÝí·ßŽŽŽhš†ÞÞ^lÙ²eÜÛZéÏôÐÐÖ¯_ÎÎNlÚ´ ›6m*yÛ¼tŽht Å&P]ç¾P|V{Ýv¬ñéõý¢ÂÆŸ^:÷ã);Ç»Ÿ“a¤ø¬öý"ÛDÕÊe¢êØåÔÐЀ͛7£¥¥Å™‘ «««è6L…8¨Ê„Jccã°188è¹l—È໹³ŽÅöÃËûYhÛªi¿Æs޼´^QMǤVÏýxãÏKûVèUÓ~xE5“Z=÷ãÙv/íW-×o(¿¡¡!lÙ²[¶lA*•Â=÷܃{î¹§ª>Ó©T YŸÕ––§]5×m×­[‡††hš–5½E)Ûæ¥sD£7RlÕuî Ågµ×mÇŸ^ß/*n¬ñé¥s?ž²s¼û9FŠÏjß/²MTý¨œ&¢Ž].---ÃFÎÔB›YÙLÂÂ÷¢¹¹ÙÚ¾}»eY–ÕÛÛk577[ƒƒƒ•Þ¬,·Ýv›uÁ8Û588h]pÁÖm·ÝVò~xa?×­[g]ýõÃn/´m^ݯÜ}ï9òÂùñšj9&µrîóÅçxã¯û–o?Š#/î‡×UË1©…s?–²³ØýµRvVr_hüÖ­[çœ;˪žÏô=÷Ü“÷s‹Åʲ­“µ/#ÅãöíÛ³~žþùª;G4>¹±iYÕsî‹Åg5Ôm ÕeÇŸ^Ø/*ÑÆ§WÎýxËÎñîg9ÿhã³ö‹F6Ñõ£‰PÎ:v9 ZÍÍÍVoo¯ó5¶™M”ª\”:::°qãF455¡··y禬$±xîÚµkÑÐЀÞÞ^´··;sö•²^ÞÏBÛV-û5Þsä•ýð’j9&µ|îÇ^Ù·bç¨ZöÃKªå˜Ôò¹϶{e¿j½~C£S-ŸéÕ«W#™Lâ‚ .@SSR©ÅIÇ»­•úL§R)¤R)¬_¿>ëö 6 £££ªÎ•_µœûbñY­uÛñƧW÷‹Ê£ÎýxËÎñîçD*ŸÕº_d›èúÑd¨ôöÕÕÕ¡££ÃYF¬£Y mfå0Ͳ,«Ò1V"@<=l¨¯¯ÏÚ”o;‹í‡—÷³Ð¶UÓ~çyi?¼¢šŽI­žûñÆŸ—ö­Ð9ª¦ýðŠj:&µzîdzí^Ú¯Z®ßÐèTÓgZ¼_}}=˺­^þLWÓ9¢òª¦s_(>k©n;šm«æý¢âªåܧìï~VR­îex)μº}Yw®fUP!"""""""""""š U¹(=ÑdbB…ˆˆˆˆˆˆˆˆˆˆˆ¨&TˆˆˆˆˆˆˆˆˆˆˆˆŠ`B…ˆˆˆˆˆˆˆˆˆˆˆ¨&TˆˆˆˆˆˆˆˆˆˆˆˆŠ`B…ˆˆˆˆˆˆˆˆˆˆˆ¨&TˆˆˆˆˆˆˆˆˆˆˆˆŠ`B…ˆˆˆˆˆˆˆˆˆˆˆ¨&TˆˆˆˆˆˆˆˆˆˆˆˆŠ`B…ˆˆˆˆˆˆˆˆˆˆˆ¨&TˆˆˆˆˆˆˆˆˆˆˆˆŠ`B…ˆˆˆˆˆˆˆˆˆˆˆ¨&TˆˆˆˆˆˆˆˆˆˆˆˆŠ`B…ˆˆˆˆˆˆˆˆˆˆˆ¨&TˆˆˆˆˆˆˆˆˆˆˆˆŠ`B…ˆˆˆˆˆˆˆˆˆˆˆ¨&TˆˆˆˆˆˆˆˆˆˆˆˆŠ`B…ˆˆˆˆˆˆˆˆˆˆˆ¨&TˆˆˆˆˆˆˆˆˆˆˆˆŠ`B…ˆˆˆˆˆˆˆˆˆˆˆ¨&TˆˆˆˆˆˆˆˆˆˆˆˆŠ`B…ˆˆˆˆˆˆˆˆˆˆˆ¨&TˆˆˆˆˆˆˆˆˆˆˆˆŠ`B…ˆˆˆˆˆˆˆˆˆˆˆ¨&TˆˆˆˆˆˆˆˆˆˆˆˆŠ`B…ˆˆˆˆˆˆˆˆˆˆˆ¨&TˆˆˆˆˆˆˆˆˆˆˆˆŠ`B…ˆˆˆˆˆˆˆˆˆˆˆ¨&TˆˆˆˆˆˆˆˆˆˆˆˆŠ`B…ˆˆˆˆˆˆˆˆˆˆˆ¨&TˆˆˆˆˆˆˆˆˆˆˆˆŠ`B…ˆˆˆˆˆˆˆˆˆˆˆ¨&TˆˆˆˆˆˆˆˆˆˆˆˆŠ`B…ˆˆˆˆˆˆˆˆˆˆˆ¨&TˆˆˆˆˆˆˆˆˆˆˆˆŠ˜² •X,MÓ*½SšišÐ4 º®—åõ Ã@,«ônQ0>«—aÃâš±Yݵ¥Ôx4M†aä}¾¦iyï£Êb¬V¯ñ”#Ūûu¯•Çø¬¬J]w²,­>ŒÕÊk¼æ+KÅí¼­nŒËÚS q9e*ñx¼&²µµµlʼn¤ë:–.]ŠH$‚¶¶6q¿¦aˆÇã•Þ5*ƒZŒÏj‰Íñ…Bhnn׌ÍêÆx¬-¥Æc$VÉÅbNŒ777W}%¸ÖÔb¬µ¯ã-;óÅ*ÀxõšZŒÏj‰ÍJ^w²,­>µ«@íÇëHe)ÀkÑZÀ¸¬=µ—S6¡R«4Mƒiš•ÞŒ¢ÚÚÚ ‘H$ÐÓÓMÓª>˜ˆ ©–Ø+Ã0‰DÐÓÓãÄu,›²ò¶ZÇñˆÅbhkkC$v_(Bww7‰‰{×Ò„«åxOÙY(VÆ+M¼j‰ÍJ\w²,%¯©åxåu(U«j‰KÊoÊ$Tâñ8–.]ŠiÓ¦! ûЊLøœ9s … …²¾€u]G[[¦M›†ææfçK½µµ±X sæÌÁœ9s‹Å …0gÎ,]º4+‹:šÇ"^ǽ½²~—Rx¸·GÓ´¢ÿæõ íŸøÒƒI’ÐßߟÏWpu]wÎxÍB=zÜçq4Ï£É7žø)6ïÄçxc3ßmŸÅâe¤ïqÎ$Ir~˲œ·‚à>&ŒOï)c-+Ò?ƒåŠE÷k•3K‰ÏѼæDÄãhâÊ}L@Qøý~(Š’õ8MÓ ITUu§(JMö«µ^v£«ÛN¥²9VÆ«LDYZ‰Øt¿V5–¥c½îçeiícYšÿ5*Q–‹×r”¥â8°ÈÛØ~;òëLvûm)q2eÛo­) ¿¿ß`…Ãa˲,+ Z¬`0hY–e X’$YÝÝÝÖÀÀ€å÷û-V"‘Ⱥ_ Ŧe.æ&:>Ç›ùn›¨ø,/…¾‚Á sîdY.›¥¼M®Bñ8ž²Ò²Jÿ –+Åk•;K‰ÏR^³”}k<z^¡xtËmàÉwáà>¿4¹¦JÙ)î+µhª”nùc¯•5Qei%bS¼Vµ–¥c½îdY:5°,Íÿ•*K‹ÅëXÊR÷{°¨:°ýväשDûm)q2UÛo§Ä”_º®;ÃÿY–¿MÓÌŽ›ûXÃ0 ë:¦M›æüTzÈQî6Ž•û8”ò¹È²Œîîn¨ªŠp8 ¿ß?ì˜æÛÇÜaÓ’$eÍ9ëÚæ6WìyT9ã‰O/Æfî6ŽU¾Ø›¬ø,/ùö/‹!£§§ápýýýÐuÝ™;z¤Ø,åýhòŠÇj,+ómçX”{^ŠÇbÏ+#É÷>ŒÓÊaÙ™ßT*;G{,¯“‡ei~•*KÇzÝ °,­u,Kó«dYZ,^ÇR–l'ª&l¿Y¥ÚoK‰“©Ø~;%*ùæÎUèäˆyN-{Dó‡+½kUIUÕaÁVêLîyÊKQQD£QƒÁ¬¹‹=*g<ñÉØœc‰Ã0 ËrV,«ªêš››!Ëò°ì—,˃hmmuž¯ªª'+>²,# !–”Ù­I’‡ÑÜÜ UUãé÷ûKÚ¿@ Y–žÁ`0ïcÅ{,^¼xTÏ£É5žødlNܶŽ6^DÅÆ}EA0Vɱ)ÎãÓ; Å#ËÊÊmëXâc¤çŠÇbÇ"£­­ Š¢@×u„Ãá² a§Ñ™*e§ØÞjˆ×É,;K9Œ×ÊaYêã¹îûȲ´v±,õ–±Æk¡²4¶yÛo½§Ü×£ùTc\NK/ 3%èºîÌ·ç®´˜¦é )2MªªbÚ´i6O¦a$ɳv±¹ûèE£=žš¦!‰ ‘H@Ó´ M®ñÄ'c³|Æ/“×4±òÅ#ËÊÉçÅrO;Y–9E‰ÔzÙéÞN/Çëd—£}]Æke°,õޱO–¥SËRoë1åuhmaû­7Löõh5Å唡"ŒtLÓDkk+º»»¡( B¡PÞù'£ÂcFÁ“TU-8ÔIl_¡!ÇÅ^c"¶k¤mëñëp//#Ûxâ³ZbSdØËŸ›îçŽV%âšÊ/_<ÖZY9âq<Ï ¼¥ÖËN±@yë¶^‹Õ‰:Œ×Êš e)Pû×â=ˉ±é-^/KoÆëD•¥c=¦¼­-l¿-í5&b» =o,¼r[nS*¡2Y–F±,Ëèîî®È¶ˆ” mëd¼Æd¼æX¶a,™I/g4©8¯Äg¹b Ü±4¯7™ñÂø¬^‰E€ñ8QÏ£Úá•xe¬eóJl¼î,e;×Sãur_o²1Æ«ãrr¶ËýZ“y=ZMq9¥¦ü""""""""""""‹#*½DDDDDDDDDDDD^Ç„ QL¨Á„ QG~õ«_ýêd¿éÐÐt]ÇÐÐÞö¶·eÝ—J¥Ð×ר¯¯¯ôñ!šR Å&Àø$ª$Æ'‘w±nKäM,;‰¼‹ñIä]¬Û6é •¾¾>¬]»/¼ðºººðÜsÏáüóÏtuuaãÆxá…pã7¢¾¾MMM•>FDSB¡ØŸD•Äø$ò.Öm‰¼‰e'‘w1>‰¼‹u[¢â¦Y–eM檪ŠöövlذCCCX»v-:::°zõjœuÖYؼy3ZZZœÖ4 #¾ÞÿüÏÿ`É’%•>Ž4…½üòËP‹-ªô¦ŒK¡Ø0êø|òÉ'ñì³Ïâ„N¨ô®Ñ¶sçN|üã¯ôfŒ[¹ãóÎ;ïļyó*½[4…íß¿õõõXµjU¥7eÜX·¥Zúmþø|á… ë:ë¶TQ¬Û²nKÞĺ-ë¶ä]Q·>™;L&188ˆ 6êêê išs_}}=ZZZhllD2™D{{ûˆ¯‡ñÉO~r2wcB<òÈ#X¸p!.\XéM·»ï¾]tQ¥7cÒöã‘G€ª¾è,›âþÑÆçOúS<ðÀ¸ôÒK+½{ãV+Ÿé©ø=s÷ÝwWýEçDÄç5×\ƒË/¿¼Ò»6n»wïÆîÝ»kâÂ¥V¾gJ='»w?wQ·½ùæ›kâ³0˯+õœ°n›?>u]ÇO~ò“ªÿÞ¦Þgº°n;¾ø¼é¦›ð| Ò»6n¬Ûzë¶µ_·õzYR ß ^÷‰¨ÛNjB%•J¡©© ]]]ضmêêêÐÞÞîd6s3šõõõH¥R_sÆŒhiiqºZuvvÖÄ~öðÀŽŽŽJoƤìG2™ÄîÝ»«¾§Z¡ØÇb´ñ¹xñbüñX³f +½‹ãR+Ÿé©ô=344„ÞÞ^èº^éM·‰ˆÏéÓ§£¥¥ {y]2™D2™¬‰ø¬•ï™RÎI*•½÷Þ‹—^z©Ò›;nQ·;wnM|WO¥2§Z”rNX·9>O8á,\¸u[™Jß3¢nûðÃWzSÇm"âS4ò²nëµò=úmùê¶MMM¨«««ô.ãõ²¤¾¼ï}}}R·=b2w"•J9„ 6 ¡¡ëׯG*•Âààà°Ç—RΟ?Édr2wcBtttx6xGkëÖ­•Þ„IÛqÑYí Å&€1ÅçgœãŽ;½½½•Þ½q«•ÏôTúžD2™ÄÁƒ+½©ã6ñÙÐЀd2Y´òëu---ž­¸V­|Ï”rNÄB–‡ªôæŽÛDÔm÷ïßϺ­ÇÔJ|–rNX·-l÷îݬÛzÈTúžuÛýû÷WzSÇm"âóàÁƒ¬ÛzL­|ϰn[¾ºm¾ç{×Ë’jø^ðr¼÷ööNHÝvRG¨v°mÞ¼€ý¡BWWêëë‡=6•Jíý3þ|ϰ¨vutt ³³³Ò›Q#ÅfGGǘãsÕªU‡~M”††ttt ¯¯¯Ò›R¶ý)g|Ξ=›e'UŒ¸`©…¤Àº-ÕÖmY·%obÝ–u[ò.ÖmY·%ïjooŸdû¤ŽPiii6¼KüߨØ8l«z¸&Qµ(›ã“¨’ŸDÞź-‘7±ì$ò.Æ'‘w±nKTšIM¨4559Cá{ÐmÛ¶¡¡¡---Î0VÀžã,•JaÍš5•>FD5¯Pl`|Uã“È»X·%ò&–DÞÅø$ò.Öm‰J3©S~ÕÕÕ¡££k×®EKK R©ZZZœaÓظq#šššÐÛÛ‹ŽŽO.XDTkŠÅ&Àø$ªÆ'‘w±nKäM,;‰¼‹ñIä]¬Û•fÒ×Pioow‚²¾¾>k®=÷} 6F4‰ ÅfîýŒO¢ÉÅø$ò.Öm‰¼‰e'‘w1>‰¼‹u[¢â&=¡ `Ð1 ‰*§Xü1>‰*‡ñIä]¬ÛyËN"ïb|yë¶D…Mê*DDDDDDDDDDDDÕˆ """""""""""¢"˜P!"""""""""""*‚ """""""""""¢"˜P!"""""""""""*‚ """""""""""¢"˜P!"""""""""""*‚ """""""""""¢"˜P!"""""""""""*‚ """""""""""¢"˜P!"""""""""""*‚ """""""""""¢"¦Oö¦R)¤R©¬ÛšššPWW—uCC*}|ˆ¦Œb±é~ ã“hr1>‰¼‹u["obÙIä]ŒO"ïbÝ–¨¸IO¨tvvbÛ¶mY·mݺ---èêêBgg'šššÐÛÛ‹ŽŽ´··WúM …b㓨‚ŸDÞź-‘7±ì$ò.Æ'‘w±nKTܤ'T†††² J·ÎÎNlÞ¼---èëëÃÚµkÑÒÒÂŒ'Ñ$(›ã“¨’ŸDÞź-‘7±ì$ò.Æ'‘w±nKTܤ¯¡’L&óZ2™D}}½°hllD2™,øz¯¾újÑÇM”d2‰Ý»wWz3ʶ/#‚cÏÝ»w£¯¯¯Ò»FSÐÐÐ’É$ù$>\éM) Öm©–°n˺-y“¨Û¾úê«•Þ”²`Ý–j ë¶¥Õm‡††*½k4õõõMHÝvR*"x®¹æœvÚi8묳ÐÕÕåì`nÀÖ××-÷ïßÏ‹Nª˜Z¹è,›ÀØãs÷îÝèíí­ôîÑ488X3 •‰ˆO^tR%¥R)ôõõáСC•Þ”qcÝ–j 붬ے7‰ºíþýû+½)ãÆº-ÕÖmK«ÛVz÷h êííºí˜§üBoo/êëëÑØØXÒsR©ZZZ°aÃlݺÉd7nDCCCÞÀ*eÈØüùóÑÑÑQöCTŠŽŽtvvVz3Æ­Pl¶´´Œ9>W­ZÅù4©"ÐÑÑQ½H'">gϞͲ“*Fôj«…¤ë¶TkX·-Œu[ªÖmY·%ïbݶ°©R·mk¢QÀ4íÿMP@ÓìÿUµÒ[85µ··OH²}L#T:;;qÖYgaýúõèììD2™„ªªE ÷ÆÆÆ¬yøZZZ°fÍgØX.ö. š…b㓨‚ŸDÞź-‘7±ì$ò.Æ'‘w±n[:Ö.Íü­­@$bÿ€X̾=É$VÄc £Ò{@ã1ê„ʶmÛÐÕÕ…­[·bëÖ­ìkooǺuë Ή'†Á¹ÕÕÕ°ƒ67¹°Ñ$(›ã“¨’ŸDÞź-‘7±ì$ò.Æ'‘w±n;\,ƒ®ëÃn7ŒÌ¨M|>{DŠ,ª $¶Ø÷ùV²“+ºnÿ„BvRî¤J@zt rï#ÏuB%™L¢½½ÝÉV 6l@CCCÁ9eÅP1‘t¶mÛ²†vŠ^ }}}H¥RX³fM¥QÍ+›ŸDÄø$ò.Öm‰¼‰e'ïý·€IDAT‘w1>‰¼‹uÛáâñ84×ðÓ´“)ºnÿ ÙI¿=å—ß„_¤ô€žÈ7Äù@8œ¹²ÎN¼ø|ZsÞL¼ –þÛpýMž1æ5TÆ¢½½}}}X»v­“|ioowæ¡íèèÀÆÑÔÔ„ÞÞ^tttdõT ¢‰Q,6Æ'Q¥0>‰¼‹u["obÙIä]ŒO"ïbÝv8Ó4aŠ…Q`'Pt=3Å0ìÑ'¾Gh€¤˜ ¨>@º€i?6ñu@Žf:¹Òoñks Åÿíç@Týšˆð§ÿ×Ó÷¢§ü  2ê„JKK ®¾úêaÈ®®.¤R)455|þ¦M›Ð××ç s #_R©Ô°ûˆhbŠM€ñITIŒO"ïbÝ–È›Xvyã“È»X·vܺ×Þy-º»»±ôñö üÛ÷iHØIŸèA;ÉöÁNbˆÅçc€ä«á$G” t¹Ð¡[ål@™D€bR ™¤‰{*0€   @"ý·›Žô §ÿvO“+e6ê„ÊêÕ«ÑÛÛëd+¡ª*KÎL666Žx_-$‘׊M€ñITIŒO"ïbÝ–È›Xvyã“È»¦dÝÖ5òã•|G{4 Ã@bÚ™xç‹/#ã¡Û@™ÿIHÐÖX2—ìÑ*NÒ°“"!Gf„‰ ;éÂí@<M fr+ üɹÒ#!“˜€hú¹zúµ#éÛþ;{ 9}»ŒÌz,Zz|é÷Û@ã2ê5TºººÐÒÒMÓ°aô··£££÷Ýw_ÖM"""""""""""OkËüÙ9´ ï}ׇ‹Å°üÈ™xàµehkóáð£+ð¾ý; I@ÿöcã·ò‘°“)b vCCfÔŠ;±¡Ú÷+§á ÿ…€o1 íÂ7Ñk€È ÀÜ~-Óµ}fúµÓ£Mzïìµ*‚xÿ8²¹IXŠLâ§™õYbéçPIFPI¥RèììDCCƒ“LY½zuÍÏ™GDDDDDDDDDDUNGvAî¿‘ˆ†ßý~öh+nºéWøÏ· àK³᪫°}°Ûy‚ýðט€4ˆoö,ÜãL †¸}4Ø ”nû潈÷Üh'/LààÁƒ¸ë˜» îÞõìðÔÿ{ Ú¯'ÞÀ–Cûìć' ã$EÒÉ’ÿýÖÿÚ·k°§óÁ~mö¨-ýF&ñâGf„ŠâºÝ@&Ñbä›HÎßâq&2I›)fÔ ¿ß¦¦&tvv"™Lû!""""""""""ò¢_>ý$®ì~ `ÞüýCoâ²§ ih:x ^·ŽÃÉ'ß„?»7ôÎD$4û¼¡y™„‚æÛþð‡?´§Ú “Ñ×f¾†¯}äkØû/{ñôKOãç¿þ¹ý8¸w彸zëÕPvÖÛðG¾à©À§?‡®c4 üþ~HÀ½wâÐ]‡ðؼǰoé>1ç>û–(­°“("ù!’+HoOvBFN?é¿ÓÛ=ý¤ÿ¸ž/3B ýÛý˜)–XuB%‹¡«« [¶lÁúõë‡ýy†kDÅ]·B|—„æfàü ãÙ7ÞÄIÓOÆ;½}j:víZå1؉ˆôÈ›÷oÎâï½-½XhÂi'½ x0õ ˜ ÀÀ´†ßõñë#0ígÓP··;švàÅŸ¼ˆ—·½Œ¹gÍÅ] ïÂyç‡'æ?ÝÐñŽ÷âõ]ó`ÀÀÙž¥K—â¾i÷aÏž=øÂ5_ÀÕw\~ñþ8÷ø®uâbAz øQ[_fd‹ @¬7½=éiÍ5ÂÞoìµG¡¸×\ÑI…Óû¬!{}Óõ£ ³VL @32 ·xú>ÀNˆ¤{*2¸Þ£ ŒzQúŽŽtttTz»‰ˆˆˆˆˆˆˆˆˆh 3 ÂáÂÓ¿l(‘#ÀS,ÂioÍ€¼¸÷ñ¥¼ò(À8 Í{€eoN‡úc@’ùp7w™ö øqâÇhzåßð†¬ïžNYp ŽÜt$ܲ'ÿòKlùæ7±ãœ ƒËñÈ#àÜÞsÑõDººqÌ—Ážc÷À4M<¼ía¨Ç?Žã_Wð¹ûïÇ¿; ]ôyüß­7â”w¶ã£þ¯/yÇwØ[>œõÉA|wï<þä^ ~ñÜxc#N¿èYüÏ—þê—T4£ÿy`ÔKŽÀ[ ÃNóxr诘u[#Î IŠøÓñçø2#fÜ#YĨ±ÆL+ìx¬„̨™Xúo3ýw™©Ë*`Ô#TÜúúúL&Ñ××W¹= """""""""¢)Ç0]áN×âìñ§e³…ÖV{ý’¯ù$®z_?>¾â»qÞ¢Ÿ|«¼ð}öè vþF‹½ˆÄºººpÜqÇ¡óèÛqfÿ>sÖg` Ã@WW¦M›†o.ý&NžÖ%ûÞxçXxh!¬|ùÖ/cç;aÊ&LÓÄÌ™3ñ¿ú_lݺW½uÞÜw¼Y‡íG|¾×OÆ­·^wœw7¾øh æÏŸŸkŸÁwN˜…4¼ŽxÜ€o%ðÓÇcå’_á³ï¾ûŸÜc]O~þ œ¾c¦OmmÀš™ÿ‹®ç–@’ð=ã¸ø™ýø×mû ìÚ4Àøû˜ƒ€qœ)Ì´7ãFMš0É—02I‘HëÓ¸§ ¦ËéÇ¥GË `)ìäJ™$M$}ÞD²'àºMœ×\±|Ãc&Ƙ*]]]8묳°víZ¬_¿k×®…ªªL¬ѤÐ4@UG¸S`¦.‹ŸõG45í€2Ã@ݼ½xùÿžÁ‚÷í¶ùe@9.ä@ø‹ÀŽ; išÝ˜ÿhŸ1Ï-yk÷®ÅÕW_K¦7á”ÝsÑÜÚ MÓðä_ŸÄ?lø$ ÌüáL?ãe˜Š‚ó¾vž:ö)Üpà ¨««CËÌ|ë[ß‚®ëxté£8¼è0Î?ÿ|¼šJaɻޅåoÞ‹/·ýÝßüþ8®¼ò ¿¡··Ý¶þÏDp_ÏqÎ9Gã”SvâÓŸþvî<ߎ}°ìõé¸ûîcaþ ðÿ‘Ӻˆ¿´þ¸ÛÎ_,ÝG±€¶›Ó3sµ!3Ý—™Ø£H°äžÎK¬/#ÖqÓ’ùÓÏÉ=}ŸÔœedFµÓÏmƒÄÑrÎs<€9|1—^˜W^õ$]:¡’L&ÑÙÙ‰ŽŽüáÀÓO? MÓÐÒÒ‚uëÖ•u㈈ˆˆˆˆˆˆˆˆˆòQ”#TÄ®ÚÚ€“ŒƒH¼Ò îÄIõÛ±wå^Ìx|>tàCv£}Ôõ¤tãþK /AÓ4웳Æ<³ž|«>º 3^(Àyï}'ÏÀ™΄ªªØöÎmXxÝB¨ªŠÿ·oz»>ö1@fÿÃlhš†]»va_Û>¼ã¼w@×uXX¸ê¦«ì÷ÕuÌjlĉ—.‚Ú6êgH$€K.i¹c؉žÇÿ¿IhiY€õë?‚ÿèý-Î8pïk:„—^:J:Ù!I.¸ÀÂ_þò®»n|>@–{.xy;>ö±ÿF¤ËNJE£À|ãa ¶â曇pTýðåwÂyï ² ˜u»ñÈë+ iÀÁ> 40ÿÑÎiÄÞÌ~ tLú8ŒžO"âÅÎyhïŒÍ@\Nw €0–ÂNœ\ ¿Š>`ý9‡;h—Ɖâ¤æ-€öQûÜjOÌV©À×ìL‹¾0ßo?ôþûWá/9º¬Ÿ¹Q'T¶mÛ†ööv´··£®®ÐÐЀM›6¡¾¾Éd²¬HDDDDDDDDDDØ €xz„iÚÿ;š3€È€Ïtõ¾…/ûeÄb1Ót –}n4EÃÒiK3£#"°G?Èöïßõøý~l}|+êŽéÀsÿò/öˆŠtࢭáŒgà“ŸD0Ä’w-A(’žj®·N^‚·þðÄô^}ðU„ÃaX–…ù[çC’$„Ãa("ûØó—I:oÿνä}Ù;mdVm—e;± ÑÝÝ Y–ñÆûßÖ¬Á™gv£¾¾ áp²,ãŸ8—_þþýßgÀ—^“ä`Ï_±fñ«xù¹çpÿýCÓ4ñïßü8þ¶ì&Ü{ï7pé¥+pkï!üþ±†ªþËÆ+‡öã/ú®Þõž9þ|ìcC¸è¢"¿·“ZÆjbwßKÏšƒË¦qÕUÏáó¾Šæ;í$‘gøà®»aÙ²!¼ãØ º,½èxåB„³qé¶çqÔŽ£ðÜö¿aCׯ » Óß¿ ÿ××gß4Mƒ$IÐT s?8’$aÁ‚PUº®ãº~›>„c.Ä¥‡ã”?Ÿ’½¡< øýÙ;ã Š#Ë2|éÌÒÊŸþ>I‚O~ý믠µµ‘H­­­ˆÇãê„”^ÈýðŠÃX°ï·ˆþ¡ 'ͺÇÑßß`05=‡Z0¨á;ß¹º®ãòo/Ç ÿô?øŸÄÉ8ð¶züzîõxæ™7 ý9ë A’"øÍož@[Û7\9ˆ°u5þýmB{ûÍXSÿOãUøý¢ÿm@:7†™3¿ˆŽŽÛðîw?€`ð@· ôDC ÏÜ |-†¯ü©ìŸ¿QO ÖÒÒ‚-[¶`Íš5hlltnïêêB*•BSSSÙ7’ˆˆˆˆˆˆˆˆˆˆHÓì܃®‰Df´ ȳì\…$«÷=¤~~ø›bÇâ˜ñß3àû1_›ŸY$]ƒ=êD,žî ¯- óçχ¢(øÑC?B4B@,ÃÅ-#‰@’$ÌûÊ<´-ˆD"Ðuªª¢­­ >Ÿ×Ür Nìy©.» NFCìD)B!{Ž,Û¿c1{ç¬Q+$óË_⣲ŒUý(4MC €,ËH$\ï}øÜÃx¡ýó8éÈ÷⦟ü†a ‹Áï÷¦‰¯½IQà÷+$ »}ÿy÷ ¬]û œòÄQøÃcŸE¬{B¡¯!‘Hàµ3îÄßý.Ló'€}§¼ò7H+ZpqøãØýÚ±ð?Þ[9ó_~Æ¥—B–eÀÎ7C×çbÙïÀ óMü÷˾O×qàÿnÕÿñ˜õøI8þ§?E{×°þ¼{~u >}ÏpìKÇâgWµcû…ÅŽû¢õý¯Ã?½¾û·B“>‚çÿrRÙ?£¡ÒÞÞŽ––¬]»ÖY”^UUg]•ÑŒRéëëÃÐÐPÖm©T Éd©Tªì;KD¥É›ã“È ŸDÞź-‘7±ì$ò.Æ'‘wy¹n«ªv^A–3k¨èº£†ã àä“ðëGà›g}ý˜?> A3h/l.ÁN ˜é¿{tÝžþjÇûv`ïù{Ç Øk’˜¦‰_Úîîn´µµ!@Q˜¦‰îîn(Š‚D"‘™ÎKQžS+{'$);!RL4j?Lj‰Ç÷”aé…lðKúûûqý©§â¯Û·g%TÎÝt.V}và÷ãgžÁϾùMtwwÛÛÓÜŒ¦/Ù™ŠLQƒA¼ûü•xç;ß Ó4ñ×Aûk#BŸBww·="gÖ,Ô}ÿû§GØ<ûÌJôÍýf^<°âÖ[qcSþþ­·°ø{ßÃG/¼ç×ÕAUUç9o›¶;5!K¯r¯(˜õãã;;1ãùçQwþù˜={6¤“%(ˆ†×#‚#Î:ïþ0ü?üïîƒïŸ—£uðgø—i,Z4­ìŸ¿Q'T`Ó¦M¸ýöÛQ*6lÀ}÷݇ööö’_#•JaݺuèííunëêêÂÚµk±eˬ]»]]]eßa"*,_lŒO"/`|yë¶DÞIJ“È»ŸDÞå庭®Ãµèºý[I/vnšvnÄw2ðôÓ÷à}+aÆÙ3ìõQÄt^&€6Óë•À¾Oä$àæ›oFss3àÔ =õÕ_·oB!Hñ8ß}7B¡t]Gww7îÛ²²aÀ0 'i!F^8ü~'ÙáP”Ò*á°LÏqOû¥ëvv)W$HdYÆ¢cÅßûÀ0 ;åÒ³pûvüõàAèºnoc"‘ÉX¥Ÿ …0sænüýß/–NèHgœåü:D"˜¦‰@<ž^HÅÞ'¹Å‡Ë—_ŽO´W’O$˜ÙÒ‚Y=„ºóÏÇÊ•+±êöÛ!"‘z¿ým8û Üÿž]öH¡¿W|éKY‡M¿o'”U7:Ûˆnà¾GïÃÞ{÷"ܼJÏ*¼ïï~Š/ü?|¼þ´²Ç”PI&“èêê† ÐÑÑÀWÁH®¹æša·uvvbóæÍغu+n¹å\sÍ5ÏxM5ùb`|yã“È»X·%ò&–DÞÅø$ò./×mãq;q¢ª®Áûì_ú}öÌ]áwû÷ß‚¿ÿ»zûv"EMÿ½+’I*¤ó¡P]Kº°{Ánô÷÷;#4¢Ñ(ÎI'ÎÿÔ§ðÙ]» ª*TU…¦iøËÆ€i"‘Hdoh¾5R{„‰iÚÙ wr$±ŠÉMª¸G¨†á$Z|âh|òIüÛÇ>f'Š4-;¹#˸á–[à+Ö˲=¢F$N$ >Ÿ_ûÚqPUÀçóA–egtßiv¢%¨ªŠÜý‘œÃ²:‚Ȇ…B‡ÃØÐӃ׾ðÄãñìÇåPU@>çD˜Þg‡ôè!Ã0pÍ-×`çÏwBÓ5´´ÌÄõ?]…ƒ³Žçã–ר*}}}X¿~}Öm H&“X·n]I¯ÑÙÙ‰ÆÆÆ¬õV’É$êëëÑÒÒhllDcc#’ÉdÙwšˆòË›ã“È ŸDÞź-‘7±ì$ò.Æ'‘wUCÝVQì¶{Ÿö(÷ÚË”Äï¢ð·çþ†y÷ϳ3,ìi¾þ{Oæµâ~;±"Ë2¾òë¯àCŸøPÎ{)Nâßî¿/¿ýí§“Á`ËwïÎ?ÚĽ°‹`öâòö“d;É’/9’oçEB¥»{øý‘HúÀØÞqÞyøþâŸðþû¡ª*%“ÅßG–×¾dÏôû|x×»ê!Ip¦çòùì‡Åãq˜¦i'd|> …aøø¿pñ¼aÇC’‹Åðµ+°ð’KœiÓFbš@ì‡3«¯¶GÓ¸ÎÓ÷¶}Kž[‚æ¶føý~¼~ÜëøïWþ»”Ô¨Œ:¡rÏ=÷ ½½›6mrnkiiÁ-·Ü‚¡¡¡¢Ô×ׇmÛ¶eÝIßÞÐÐu[}}}ÑLç®]»†%xˆ&Ëúõëq÷ÝwWz3Êb¤Ø÷%>ï¾ûntvvVz×h Éÿ_|±Ò›R¶ý)g|¾øâ‹X¿~=§O ŠèêêBgg'öîÝ[éM) Öm©–°n˺-y“¨ÛîÚµ«Ò›R¶ýaÝ–jë¶¥ÕmûúúƽmºžY†$·½Ý¡}Û¥gƇqvÎ݉Ö9­ö¾ôÈw g‰˜ÂJ×uø|>H#,‘eø|>¼ôOÿdO5e™Åâu=3ý`ß—;Å—H¦ƒÙ‹Ó»w0÷9ùƒ™EéGºß•¨‘$ ¿8ê(üþõ×ñÁ#Ž€QÊ{¸Ú±ÇwÞ°Û}>û˜û|>{º°œãÇ?ìiÖÒÇwX¢D’I‚ßÞ.EQ²Ö{Ésœ§¿ÓþõÔSO~÷»ßáúÇ®Õþ–búhŸJ¥†ÔÕÕ]~hh7nÄæÍ›‡=vpppØãó½O®Å‹cëÖ­e?0D¥ØºukM\TŠM`ìñyÑE9ÓM¦ÆÆFlݺµ&%'">çϟϲ“*¦½½ÝÝ\íX·¥Zúma¬ÛR¥°n˺-yë¶…•³n ÙywÛ½ w‰àÑoöâ¿>?~òÇxÞaNwŽDp¬ŽC‹šð×?þ’$! AQ´µ¶b¶,çOˆ( |¢ÿï°ï×4;«»À¼a ÏúˆLn2$=JÃIΔCN¶Á4M$Î<ÿµl~ø‡?@ŽÅò&µó‘M?˜7—p¿iše9+ â$O\ƒR$I‚)2b‚߯ðÛ‹m“<ò ›ýíÇ;Z߸úê«ñûoþ¾<ÇÔeÔ#Tššš°mÛ¶aÈmÛ¶åÍVºÅb1466bppÉdƒƒƒèëëC__êëë‡=žsdMŽB± €ñ9Nº®#‹º€ ŸD^ƺ-‘7±ì$ò.Æ'‘wy½n+fŒ62Áõÿ3o<ƒçÀ²W–áÌÙgfîБI®ÈÀÀü«ðÀôéxý÷¿O¯"Ãï÷cvOµÉMl„ÃÙo,îWUû>Uµ3=b ”| Uzz†ïXGf ÀÏçC$$Iƒ0 #+âóùÐÚÚê slkkC8._¡ASã“È››DÞÅø$ò.Æ'‘7U26EBEÓ²Ö[ìüãNÌxe¦?0G‰%—/±ïˆÁ^€°G±¸f”’$ ×üâÎß™fy×7É•»þÊÈíÜ«âaFí!>­­­H$ˆÇãˆÇãÒ Ê‡B!øý~ȲŒ9sæ »»jÎHÓ4¡ëú°ÛíC •¼¦Ëh-hY€y§Î+ëk–”PéêêBWWÖ¬YƒÕ«W—m8Wî¢Díííhiiq¾çN¢ÊÈ·`ã3¿P(„X,EQ ª*¢Ñ¨³ W®p8 ]×ÑÖÖ3=g¥¦iVhPmb|yë¶DÞIJ“È»ŸDÞ嵺­¢Ø Ӌ䊰ûâÝØyp'^}ðUÔ]—™êIEfÊ/ìi @×!Å㈥“"Y¥µH$ì¿#;™2‘m78Ý?iä,_âsÅl,š¦Á4Mø|>g¤Š¦i0 áp’$! ¡'g½˜H$‚X,†îîng”Ëh;ù†Q‘NÊ%-JßÞÞŽ[n¹ زe Ö¯_ÎÎNgѰrjhh@KK L"š ñi†3ô±”!ñx===$ jz!­B_抢Àçó!‹!Žj˜%Q!S!>‰ªc“È»ŸDÞÅø$ò¦JŦ,Û?’4|ʯ…w-Äœ}spÖgáøwŸµø¼“D‘a'XEQJZ^×ugûx<î´c麎`0˜÷o_z_DGâ¥K—:ïåóùœÎÅ­­­ˆ¤§: Às»è8,~Ĩ“`0è´wù|>§ÍM–egÊ01ªEÜØmn±X,kT‹Ø–x<î$yLÓDss³3Âe2ŒjQúd2‰T*…ööv@__:;;Ø‹Ôß~ûí“¶áDDå‹Åœ¹}>dY†¢(e²,;ð\†aÍæã~MÓœù$‰(Ã0€À•€üg@‹Ú#@¼«Ò[EDDDDDDÅ糓*y—/I'TŽ}ñX,;wPdö§P(4òÌ ~v¶Æç³*ª:éÓqMEQŠ&T4MsÖ v·}‰„ €Ì”i°“%"1"Ë2B¡Ó¾fFÖ´_ñxÜ­"F®vggñÚ†a@Ó4D£QgÚ/ñZbƘX,†X,Ó4ÇÌIdš&þö·¿•ýø•bz}ñ>Š¢dz2 Ϋªš5ŠE$UÄh‘tûâ^E×u<üðÃe?v%%TúúúpÏ=÷àöÛoGGG{ •úúzlÞ¼غu+¶mÛæ$\ˆˆ¼NŒJì칦˜K CtÙñrÎ×èóù‡¡( *4¥†ÝIÓì9s»‚³° ²PæÆãÃ× $"""""¢ê§i@ 0Â5ŸÜ{ï½Xôâ"HÒ€ €8ì‘+9"‘B¡ÐèÞ<ÏÔïµD–åa‡MÓDkk+Z[[³Ö2 1˜ø;_û™ûýÅúÄ¢ƒ³{´Š¢(Îè“îîng¤‘¸_UU§ÝÎÝÖ§i8PöcWÒ”_÷ÜsZZZ²O&“X½z5êêê hhh@*•BCCCÙ7”ˆ¨œD²Âï÷—´Jî<GOOOY·I,l‡…¾ˆ¦]ÚÚìQÕNŽS`Da'V°‡tßkÄ&"""""¢Ú!Ëö@‘X,= ${¡ùôà’žüà±຅×áøÁgìëE €˜Õ+ì¾ürDn½uÄN´#šÄ59*A,Øm\¡PÈU"F‹Œ§±Ï5UZî´aîmiÛÜÓìjI÷º-n1åWÉk¨ä&I’ɤ³–Š ’+DD^H$J.$Ir†!c_¾Ô÷RU’$9 t6$Q-ùÃ`Hü —˜»—QvÅÙLR°“*\G…ˆˆˆˆˆ¨æhZf=xŸvBEƒ“PùÃ[À 3oÀ/w O=3ÀÝ>Ÿ^|åÈ={œŽ«%3Œæ«ªª"°×—‰F£hmmEOOOYgc)¦Ð(˜RÖ-Ï—eÙY9£µµuÂÖ'.iʯúúz$“IçÿmÛ¶ZZZœÛ†††Ð×ׇúúú ÙP"¢r‰ÅbPUuT„X8°‡@NFᢪ*B¡âñ8§ÿ¢š¦ivç!MôM@ì˰+Ë&ìÑ(ÁôO¾ºÐâJo=•›®g–/qš`\‹Óï8´N<€ÓñÔíÝk?¡'çd¯õöfæ5-Ó›¯˜ jŒ÷ŸÏ‡9sæÀçóAUUôôôLX"÷Ú*¹·—’so«{­•D"Ó4aš&ž}öÙ²owI •Õ«W#•Jášk®Á¶mÛ‹ÅÐÒÒâŒHBgg'²¦#"ò Ó4`š&b±Ø¨G{H’ä$5ʹ}!~¿š¦!²HT š›íº¬¦ÙëvwÚ·,€=÷möˆöÚ)yÈG×ìDDDDDDS–aØ9 ×úåv‡»´³vž…íÞŽÌ´ÞÌM4YÆ¡={23Œ”:_´,Û©5.c``áô¾Nf2y*0I’œiñ‹ísŠ¢8k°È²ìÌú²hÑ¢²owI •††ÜrË-H&“ظq#êëëÅé“É$Î:ë,$“IlÞ¼yÂ0å§iÚ°„ˆh8]×DZtéRøýþQ'DÜ…ÊDN÷å&IúûûÑ4&Š ÛÉpði@ì2{¹¥ ™¹q%ä™’æ;ž¬ôžQ9FžÎsé&PÓ41kÖ,¬X´oà¬é¹Ä4V‹Å ¥§T·Ÿ¯×üT^Õd´³Çä#έ$IY£ZDÇèY³fá/ùKY·»ä5TóN9ÓÔÔ„­[·fMÿEå7gÎ »=‹A’¤Ñ/¬D4Åhš†`0ŸÏ7¦/kñEÜÚÚ Ã0H$Fýc! EQ ëzIóGyi­­ö¢óÎ`1ÑaH¤ÙÈŒN)Ò)E?Ðô^Q¹ kþHh º©cIÝìEŒèºŽh4:æÌ·HhƒAtwwOÊ7‘ÐaBeꪕøÉ¿?="ÛLÿ€ÿ÷.¤ QpTJ–e¬ô^ÑTǺ-‘7ÕJÙIT‹ŸDÞå…º­iº:ß ­°;ÞE€¸Ç¿NÿW¨ªŠÔÍÀ¯ÓÙ÷™Ï`ÿwÀPÕüSFÉ2*5¤Øtþ’$áÝï~7N?ýô²¾oÉ •T*…-[¶ •J¡®®~¿Lë¥\sÍ5H&“hhh@*•BKK 6mÚèêêBgg'šššÐÛÛ‹ŽŽ´··—u‡«‘¦ieº®;£„ü~?âñ8E¢(Nc«XÛALOÇØ#Y¢Ñè¤Ï…GÕ£PlÕŸmmmì/Ññ#ôûýμ’“Íï÷£¹¹¹bïO•UKñ‰Ø=œ<¿{\0Nôþl鯧ž ¨»*½W4•±nKäMµTvÕÆ'‘wy¥n«iöì\YM :ØyóN†%Ï.Ì»ðBç!{öìÁu‡áÚnÀ¥_þòðv v8Ÿ2D›ùܹsqüñÇ—õµKN¨¬_¿€½@}2™Äºuëpûí·*Ù×ׇ{î¹÷ÝwêêêJ¥ ª*ÚÛÛÑØØˆÎÎNlÞ¼---èëëÃÚµkÑÒÒRs½ÚÚÚœ,i(‚Ïç+˜èÐ4 ~¿@ªªÂ4Mèº]ׇë~¿¡PÈi@VªªBÓ4(Š‚¶¶6ôg­äDd+›ª2>ňEQ²FnU%§Ö“$ɉgŽR™Zj-> Ãžê €=2E‡=µ—ÀZ@ûÜè^O{Ð~1%Ö $bÝ–È›j­ì$ª%ŒO"ïòRÝVׇ¯1/¦ƒ~úé§ñùŸ·G¬$5å‰Ë.Ñâ½O>ɶ“)n"g–)iQúd2‰T*…Ûo¿¸ýöÛQ__®®®Q½Y*•B{{;êêêÀ ¸ÁÁA$“IÔ××;Ó‡566¢±±ÉdrÂv¾ÄÂØº®#‰ ‹\TÞ0 ö"=’$¡»»Ñh±X ÝÝÝþÂá0úûûÑÝÝ EQ‡ÑÝÝí$^b±˜óšDB¡ØPµñ)’‰~¿Ò§èš"¡BSK­Äg<47ÝÝ€”žâ sÄaWŒý€òÑÑ¿®|! ¿dÿ‰¡ýâŽ&ë¶DÞT+e'Q-b|y——ê¶~?0¬_lº9dçθtÑ¥Îõn±X s?óüåÄ+}8©Â&²°ä*---N@öH•ÑZ½z5V¯^¡¡!ôöö"™L¢±±---زe˰Œf}}=R©TÁ×ܵkÖ¯_­[·NØA*'1M—¦iˆÇãˆF£*±X ~¿Š¢8£KdYFÁé‹Ä°&ñxÀnŒ Î"öÌÔŽßúõë±k×®Q¯#ä5…b°{)Œ%>ï¾ûn@GGǤïS €qOóå%Š¢ ‹Uz3ªB__:;;ñâ‹/VzSÆm"âóÅ_Äúõë±zõêI›>!±“)ñ1–`¯•’SIʳð`"ÄuÝþ[$RZ[í÷3Mûöx<ϼT]]]èêê²eË*½)ãÆº-ÕÖm½[·¥©MÔmwíªþyNk¥nK$°n[Zݶ££cTKGöÌî&纞ÃÏ¥Ÿcኅöµd7€X̾Lg_Âá0EÁ=¿ÿ}¥'U˜¢(¸ð q÷Ýw—½n[Ò•rë±lÛ¶ÍÙ!ÑÁ­”!c‹/®ª NMÓ‡‰D ª*TUuÖFimmöxÃ0òN6–FbŸÏ‡D£QgmŸ­[·â¢‹.ªôf”M¾ØÆŸ]tQÅ.8c±âñxM%eYæ³566bëÖ­˜?~¥7¥lÊŸóçÏÇÖ­['å‚Ó4ퟬʰ{š¯œ$ÇXfç3fÚ£R$ÉNšƒv2Å02#VD.²@š$íííèèèÀ¼yó*½)e3•ë¶T[X·-¬’u[šÚDÝvñâŕޔ²©Öº-Q.Öm uÛ±¬ÃÛô944„H$‚ýïÙoO­Á¾èKD0 ¡P¸þ,°;ÁLDݶä*å$*CCCX»v-P__?ìq©TjLç5mmmÎ4]b]“D"á$J Ã@$išÎˆÁ4Ͳ/$/Fª˜¦YÓ Qùä‹ÍöööªÏZü|‹¤J-¼¡ÒTk|67g’$Š{ª/@€ö—±¬~ ˆ˜Ù£[ÅþQU{ACI²G©„BvÂE$V…ëÒøMµº-Qµ¨Ö²“h*`|y—ê¶ùú’8pægÍ=Ëž:Ú@Öõ¤X*h¢•œPéííu¦à éêëëËz\¡u]]]† uuuhllD*•BKK˰5Y«vÑ1]×a†³€| €®ëèé逬$I8†¦iðù|ÃÖG˜¨Þè>Ÿº®×Tï}»B± Ø…i5ŧX¸½?ߊ¢0¡2ÅTs|ŠDF,¤g­šDaOûU¦õ­|‰ü÷‰Ñß’´µÙFf›ÚÚìlj¤J(d'[ĈšXÌNÊ0ä(Ÿ©T·%ª&Õ\vÕ:Æ'‘wy©n›{ý¥ë:ö.Þ u‘Š3/8H8w µf Þ¿t)|>dYÎê¨N4Jšò«¾¾MMMY·544Œ)hDpöP-1?fKK‹³È`'jR©Ö¬YSéc4j†a ­­ ¡P‘HÄ’H$òö˜÷ù|ˆF£y_k¢MeY†¦iÐuÓ€‘c@UƧ¢(Öè‚ :ç,šrª5>5ÍNTôô¤Ga°G¥˜°§û*WWÂhnUµ§ í¤ŠßoWÒÓýœÑ+>Ÿ=j¥¹93XzI&¢¼¦BÝ–¨UkÙI40>‰¼Ë+uÛÜ© _xâ¼¹øM$‰a³¼tÜq‡Ãðûýðei¢Q*i„Šê5^íííØ¶m›3\¬··kÖ¬qæ¹ìèèÀÆÑÔÔ„ÞÞ^ttt ®®®ÒÇhÔ"‘>úÑëqúéïÁ9ç€iÊд ³®a”ÖÓUÓ´ K¨¸§ý£chê*›@uħ®ëP¦iVzS&ŒªªÃF²Qm«öøtFwˆ¤„;©RN!dz(ÙÁÝÁ0ìu^t=³‹˜",·“/ñøØÖw¡Ú6Uê¶DÕ¦ÚËN¢ZÆø$ò.¯Ôm—.rûǾ¼íe|ø/ξQN@‹D Ë2gò I3ê5TR©’ɤ3³¡¡kÖ¬)9€¶nÝŠ¾¾>gX˜{”K{{;ZZZJ¥Æ<¦’B!`Ñ¢¡i$)н{O|ÂîÙ*føŠÅìÇõ÷;k&eq÷<kœ˜f¦A"ûoÑØŒ¾‘G–e'™¢ªê°µ[hê)›€÷ãSÓ4´¶¶:h­ŽN‘$ÉYw©–÷“²Uc|jš]öeÕic()ñ‘—XU~¤²JǰžJ¥RU µ°¬ÌmÁ ]ÆÊ²ý÷œ9L¨P~µ\·%ªfÕXvMŒO"ïªtÝÖ0€p8ÓŽŠœ œq óÀ€ … ªjÙן&*dT •ÎÎNlÙ²uuuÎ`[¶lAgg'ü~¿3Ç^1…,ª¦ÂRÌ ¯(™Å’n¹åX¹ò§˜7ÏnóÑuûq²l?&±nD/XÓµˆ®ªªN#©iš…B¸ù柣µÕ~œ,ÛÏK?$ý¸Ì—ŒifWŠD"á¬ÅÐÚÚ UU™ÍâŠ-&æåø4 Á`ªªf%Vj¢(ÎMµº”_5ŧ®Û º»a':t섇4Æõùìy¸LÓ.`Ýö4bc¤(v¥=—ߟ)ßY?§Bj¥nKTkª©ì$šjŸDÞUɺ­¦Ù×`Ng¶°ýàv¬~óÀØd_¶Úw+~¡PÈž Œh’”œPéììDWW6mÚ”5shh]]]èì쀒“*ÕÎ43 Ÿxê©§pÿýCX¸p9††Váæ›í…nÅnPŠÇíεŠb'PÄÔ"bæžÜµ³7mJâÔS¯ÇÊ•+³¦1 »§¬x_±ÈîÀ@fj’R¿C$Ir2¸~¿±X áp ÑyaPªªæ]«¨–ø|>g $"/ŠÇ]½Š qd)¥&&DA) HI²_´­-3J¥µ5]ÓÎ)»LØ œG”ˆi¾r‰dŠûæ1‰èÿ³÷îá‘”eÞÿN 5€€Cd¬È1ÁE+ðjPù±TµÝöuªuwudv¯.ˆ¸ºÝ’UGÝծѸKÒÊ.*0kJu¢b OBJ ™åà05 Ç¡TßUÕ>%ÝIWw¾ŸëÊ•¤»ÏSUw=÷óÜ'B!„²<8N‰3[an÷¢Ü‹pìó{¼9¢ªzóLÕ+» ªjǯ‘hQ—Aeff[·nÅu×]·ÀJÙÕÕåQLÓ\5É<’Éxk;ŠòÎ8Cƒã(Èd‚ÈùQϱ6“ñþǽśDbá‚ë[· ¯ïÀÀÃAŠ0M ֙䨖¤ÿ’σaèíí¥A…´-Žãøµ€ À^j¥ì ‰ Ãðë Qq QöC ž¬`qé¾’Io€´¬ |$ó¼Åû;™, Š…ó„Ó~™…óªôÂ÷(ü_'a#‹D£Ò B!„B!ËGч8éÀq…”?±vOgðåß»™›™¬0/¨g£©©) V ùÚ´iæçç155Õê>­’jK×éi»vu!•RJ‹-©T¢¦ª^I,¬Iê¯dÒ3† x5T††€ø¶më*JA"Q.rlYØI¥¼öÞ:“mûìãýoÛÞqÅØR ]ב­gCB"ˆD¨èxà¢(PUš¦ùi ‰A À‹N±±(Co›˜Xèu6–ŠÇÁ‹\OÉ6¬0Pø> `¸Ð†xá7Bß' Û—I¦(A? ƒi¿!„B!d9Yà$n°ßÿþ÷À%Xµ€ƒ¾vvwœï\KÈJQ—Aenn®®ƒ ¶º?+F"¬éd³Y躋d²¾‚µºx½jšgìÔ_ÝÝ_„¢8xë[g¡(Åž°‰Dññ%Xg ×R1Œ ½|6ëíSÏ" *dÕ’Eàñ€Âß¼Å×dÉçIx‹¶¥¸¡c¤á-àAýˆe •JQfI䔘EìÆ‚¬\5™žö:1š”CÓû~”X͈¬$¼ES1|Ì"XŒUáy·‡O3ð_ÂOqE $³…Ï“ð}‘¯‚”GÙÂ>ÉÂöM(}¢i\×mü@„4/ Ä7>HH •ŸwÓô~t½Äi¼žL‡£`U¶WáUÂQ¥bPE ßü¹D´HÚ¡ iÖˆ¢(°“oe²BÆÞ³í"ˆÖ 3P¨ïºÞ€dAa°ááÅ¥3 ¦UH©å ?"Ó `ýåk(B!„BiÓ,ñ«Ó€ï¯ÿ>t]Ça³³EÞ{wtþwæ[Ýd²J©+BE…a˜ššÂŽ;x…èWKš/ 0Pd2ÀÐPÓÓž{¹ªß5‚aPëLÔžÉxQ1bÁ-µÃ„Sz©j±°¦ÁOQVZ¿É0 A×õºÛBH«xßû¾ƒ{ï=a÷tM&3Òk½ žç¹î­ÕÆ@3ƒ$àE|% ²’ÚGÒãÞ~©Tƒu$Š%Ì0‚ôCÀ¢…5M£A…DË dvá§œ¼d³"¬(Ń•ãx’\˜õ BùÒe윌¯&‚´7âB!„Bà­«†×.aÇýÏqP?¤zsŵåÀÛÄ«O{u«›LV)uG¨]]]8ï¼ó0::ŠÑÑQߘ’Ëå066Öêþ,+ŽGr º®ûi±¤NI£,Æ€a¼dmÛ[ª%S®f àå»7Í ËŠªª0 ƒQ*dÅqÝà9¬…m{ò¸cÇ“8í´ãŠ#»x…䥞I þ‚èÄ„·V«ëÞ@­ëÞ"ðîÝ!ERæe³^$—izÿ§ÓÞy{{=‹8ÒM«FiŒ /JðŸMxý6U¸Þqôööbxx¸þi2Eõ‹bðžãrÑZ¶]¹‰`DùŠØwîvxFÚ2 !„B!dÙØ³g·Vª±à8î»ï¾¦Ô¥%d),Ú R‰\.‡­[·¶º?ËŠey F±Íf‹p›ÒhÛJS~Õ‹,€ LjÅbôz'+N:Ôª…ãxr÷§?Š/ùÜÐð )R#eeY©õPê(/빺î^&'½¿''ƒ¶MO{F]÷¢Ä¤íbl¨ß0AäJ žQEŒ+u ª*²Ù, À¢(HÖmÝ!¤y,°åÅá=×26ZV0PÚvu„é I„Ë2¡iÀð` ïÝBq#„B!„¦Pº¶úøãÃQ •!§;˲pá5V¯ÕIÈ2Ò4ƒÊbÈår˜ššÂÔÔTÅïr¹\«¯ €`Ôu½S¯Ðµ ˲ UJj•3­®ö`Þâ±D½¨ª ×uáÖ½*L:j²þ~¹äÓ¶k"dÛî»oGyBñÚìE“WUõ .’²SQ¼ß±˜å’JyŸÅãA9ˆáaOžâñ:Œ+¼‚õ x! îº*Õ‹ÅJ¥Ífaš,òЉ´Z>+‘N{Ï¿?$šð¢¯äð„@¢›bÛÁà¸lÖÀkE[ºnPT¬…cK:3¦ü"ÚI·%d5Õ±“Bù$$Ê´J·-*Hos_žÃ±§»`»l6ËŒ¤¥,ª†J3Ãøø8úûû‘ËåÐÕÕ…¯~õ«èêêÂøø8ÆÆÆÐßß;v`tt###-¹0R)›õ A†’Rc P"ô+„Ôï¼­EÔ²/‹¦§.’âôF¥\a¤£¨&›VD>§ö:ëð°'o¶ œuâMP_ ?±á'Q~¡Âå ÃkSøÀ“ͯͪZ!õž Ï"ýxÊA/¼”I*ª‡Âµ—¦§§ÑÛÛK¹í0¢ Ÿ•¨.žB‡ghHÁ3V8®·Q:íýŸJ-ù\eqÝ dÍuƒÙ¶½<.¤%÷®äÉ”vÉO<^(tóþåÓÛŒo$U h ¨†´?í¢Û²ÚˆòØIÈj‡òIHti¥nëÏ+emÒÔ·©Eó2ÇqÉdêÎêAȲoÛ·oÏŸp U·¹ÿþûó'œpB~ÇŽþgçœsNÞ4Í|>ŸÏ ä·oßžÏçóù;väO8á„üý÷ß_õ˜7nlJû #ŸÏd‚ÿS©|>‘Èç§§½ÿ3™à{Ã0ò“““ͺtKfrÒkc>ŸÏùüìls®ƒtmzz:¯ëz«»y®ºê*ÿ¹mWjÉf>¿xùܾ}{þª«®ZT;DîÂìÞü=;›ÏkZ>¯ªùüÛÞ6—ÇÉïÈï½po>¿;ŸÏ«ù|~2ŸÏO·új–gvÖkw"Qü®ñ:™ÏçKå7SøQóù¼RئN(·Í#ZÉrÈg³®Ëôt>‹…>˜Èçóz>ÃDÂì|ÞÞå;''½Fèúˆ´AsÃðQÌÝ»½v »w{ÇSUïsÃ>O$òÓÓyÿÇÇÈ{²JÅRƈ(eÝ–¥Bݶ<òÞ"íM'ŒQÖm Y*2F´R·õ¦tùé¼7§4òù'x"?üÿ)ZD™œœÌ' odë$dõ²ºm]*ÕÂ0…ùùùšÇÉårD__ŸÿÙy燹¹9LMM¡»»Û/rß×ׇ¾¾>LMM­ˆ'Bس\]uÝ‹TÉd¼ïâñ8LSƒmÛž5´ÅHm yT%軦iPÙlvADé,ªÉ&€‘OËZXú ÷žm/Õž'ºX–‰ãŽsðæÿû?°¿ç™ Ã‹òˆh`†ªzéÀÅû;™ þ‡ü„1B¿Ó…ŸE8öÛ¶ McBÑN òY‰l¶$:Ò…¢Áèt:¨‰21QíÑ4Ô‚ÇÒÄDùïÃ1Žã5XLÛ.Ι©(Þ÷³³Åµ^0Mh‰àºèR11QˆX9HQÔV-QÖm YÍDyì$dµCù$$º´R·]±ÄÚûpè¡E©>TUE"‘`AzÒRꪡ’Ëå033SõG„®ƒƒƒ¸úê«ýÿççç±mÛ6ôôô`ff===EÛwww×ÌÉwß}÷á’K.Yò°moÍgr2(.=<ìÉj:],Ì–e!™LF&•NØ b×Yo¡º^\ïÁ0 ØÍ:xrÉ%—àÆolu3¦šlX²|Þxã«« ÙlP“ðžC1° ŒÜ ÛŽCM«ø³?ý™gdÈÂ[ĆhVD²‰th¨vy Ð7 À0êʪiÚª¯433ƒK.¹?üp«›Ò0Ë!Ÿ?ü0.¹äŒ7Ô6‘Û"dÜÃ…%¤Ñ’ΊSÈu900Û¶±v` 8v­ã'Å]¯œ³³Ô ©i~¿ÄüG|#°û<ƒ§R'’*`×®]­nJÃDQ·%¤¨Û6O·%¤™ˆn{ß}÷µº) eÝ–¥@ݶ>Ývff¦êvšV˜ªjâZº…ß¿øÀ™Åõ Òé4×)IÝŒ-‹n[W„ÊùçŸþþþ" e£lÛ¶ cccÄÈÈHYÅ´TPËqÜqÇ ûbpÏxxÀ3Lˆ¡BÓƒ…ã8PUP–ÃöAšUßW׃õ(×î¼óT|ûÛ÷6=å}§põÕWwܤªT6øÞBaê‘Ï׿þõ­ë¼²®94äE… Þ-+øÞ4¿t<·Ž¿>x ™Ò†õ #ˆ¼‘+‰j®ð G¼:+ ‚…ë2È¢ój¥¯¯W_}uÇ-J6K>:ê¨%a|‰ ¯vÊ/]à?†ýDz4H2™„išPU®ë"NÃ0 ¤R)hš†ÉÉÉ…ÆJ4RlLU½0¹ÉI…ó%…zö1x‘r+ëbdd===5£ŸÛ(è¶„4 uÛê,F·%¤™P·]Ý–¥@ݶ:õê¶–å­É¦tÃÀ+{%žíùàý)Ú.‹Ao´ˆ4Y5,—ÞV—AÅ4MÌÌÌ ÀØØ˜ÿÒX óóóؼy3r¹®¼òJ?ª¥»»{Á¶¹\®©FœR²Yo}DÂÊ4-ø (ÎbY–Ÿ+ŠTÊt²’É b'›= k×¾²ÕÝ#+@%Ù–_>-Ë“CÀ@Ç{¦e´T?sôg°¶wmG„x*Š'oáÂõe‰ÁK£äÀ+Ðæ˜@Ùbõš¦!#NcrrÒ/XOÚ—VÊg%üúò¼g2À¶€Wi%•êC×u¤R)$“I¨ªêPBd³Yض½üÑ£âqPÒ¯T AqzTV%QÒmÉʲ 5EÉw޼2äo³P@5óÞ£®|^ïkÌu½€¹ZOáÌ…«‘(Ž„Ê'!Ñ¥Uº­8¸£lcÏ>{ðä?ÿ3Ž )[Ùl–eÑ BZN])¿Ê±uëÖša]娏q#zzz`YVÑ Ù××·àxsss‹6Ø,Çñ<áe±VÓ¼ J¹ìâUš9Y’…m×õRß¿ìe_nu÷È PI6å—OË "£4Íû¿Ò3mÛ6Öí]çEltHiEñ<Ýe‘¥"¼( @Þ"vÙã)p]±X f̓’v •òY‰l¶²Î‚' x…X¬8Üq‘¸® ˲044TÎJ¥ÊŽÃ†a¬L½ pNÂÉ<‹dp΀EFVQÒmIuÂÙ!²Ù@ç ë¾€§‡ÄãÞöÙ¬g¼IC:0àý=4ä9# x¿{{½ÏâñÀÓrxØ;ŽìkÛÞv-ŸN{ûÆãâÐ|.Ûôö¥©’IoIW,}èíõ¾K§½sÈ1¥ûìã}æ8ÀÚµA¿Ã×§“2†Fqì$„xP> ‰.­ÔmUÞzÇnàÚ®kÑÿ¦7}¯iRL¡C"@]*Íb||óóó8ï¼óŠBázzz088è9ô벜þùËÖžp]Zù?›]¸Ç¡ëúªñòGhð«_TõÀ#íO5Ù\ ùtÝúž/ÇqpåÁWz ¸™V_µæ‹y UÑáykh…¿Óð®E‰s†ªª0 †a ^m!mI«å³Rß@~.Ö¸•3™LúQ)j޽ªª"™L®ŒQ¥Ó„:w\÷ ¤hw†/z®"èHm¢¦Û®'ÐÕå·8bˆ±ÂKZœÆÖ0¾öãÀ-­¾bÍGQ‚ÅYØ(+j ‚4_j®¨ªŠLá‚:Žƒ}öÙ‰D‚žmJ«å³bdWUx†½&8%²ªmB¸ Æg/‚2³â/ü œë÷ƒq¼è¹6éiŒ(鶈YÊûfxØÅÀ!oMó~g³Þø©iÞOXŸÐ´ f"e³î¡(ñEö‘v)£>¦¢;"•«…&Q¨r¼RÂwáaZ^ƒb ‘4‹Ò&ÀÓä¥RÅY åœò;|ìðß©cY^[:¥[ÇNBˆå“èÒJÝVt8d'^ðc¼l¿x[Ñ6‰ª…g Y9VÔ "ÂW‰‘‘ "—ËùÞ ËE¥œÂÓ¡âÖÙl¶harµ ª§¼¦/zÑ-P” —Í_OÚŸZ² ,¯|†×N+9¸ÿò_~‰/ÞóE¼lëË:Öó;¼˜30°ÐËÕ»X¢txi¿TT,PŸH$‹Å0<<Ì\£mJ«å³Çñ¼˜3™Âói7|HA>\UU—ôœZ–×u¡( ,Ë*2 .g4mûç€t“ʧa?•ð¢Æl“èØw ˆ’nÛHÍqbRï’Ízº@:í}&Q›’=Ðq<Ã@&³Ð`&lܨ7SoXï(ÕAä\¶]Gé2!mP”ò'f$–k{×TUN¨Iµ±“,/b\ ×-*‡ëzÛ…×Ä+ßËw•"èå=&ß‹QRdQö1Mï&ÑròyiVÔx<0ˆ–kk¥ÿÛÊ'!Ñ¥•º­DÀcÏý]]»Š¾w]étšk$ÔmPÉår+Ñ®·mÛV æÀX‹•,+TDÑqš¦­ªÈ¡TQëêº×\óvíÚ†§žúx«›GZÈrȧmTаàÕ$H‡ûpùƒ#W´ú*,/²@亷håì»R&¥LŠÔœH$T>:œ•?MÓ{Nu^]ž ‹ÜÀl_×õ%=£’öKQd2躎d2‰T*˲L&áº.fgg+ò,d³ÙÅ;Qˆû¹m#ù5`R…¡2`zq‡"ÉjZrœâÉ0Ô[’Âë‘™-Ô’ˆ‰ö]¼œ¡ UÖå¼M«/bÁ‹6•×¥×,|ƒ÷~U ßÉßza›<‡Šp4œúN;XgBËò^eCC‘ò«^V“|¶bl•h3©¹(k’¾ÎuƒÌ¦ém/NR‡(›-NËgšÞñ2™ 6Q"áEŠ‹qWŒ%ò¾Ro_©C¤iAûdyŠÑFQg)× ö‘¶Ê{N È'çV” ’(oHîd(Ÿ„D“åZò£dmàáÿ½ùò ¶‹rmk²º¨Ë "Â233ã&ÉvEr%WÂ4ÍÖäcšä”öþ×Í€CµŒà“ŸÜ…øˆV7“t2)K€<û7Ïâºã¯ƒþŠè\×…ëºeë7ὃ²ðÞA©Ðù•Âg…z2Òž²Q±„„(Ò0–8JÙ…VyGHz:ÃŒ ¦è–Ultp]ï!Çc­i%ÞädòOŒ%ŽD~X–g¬µí VR&ãÍw‡‡‹ul1ÞÄãÞ¹ Ãû,•ò¶V¯¯Ò_Y_§G䉙M Ã;¿Ô6J§ƒúN2?J¥¼m人.ðÌ3·úQ „¦#Ê€ðБþö¢m²b]&$ÔePÁÈÈH«ÛÚ4ÇSª*­ûd³Yض½*£S€âb˜BOÏÏqÒIžAí _øs¼ímœt‘æQÉ 2ÿëyÜü×7ãÂô…8ùâ“[Ý̲¤Ói(Š‚D"Û¶‹ %ÉdŽãÀ¶mضí/ò–¦#’íÊT²Ù PmÙú2²è3`q§òN‹Çã ÚJH½øµSà{.0‘~ºø•8»°B"Eè—jLEQÔJ¥Rp]×W¼Eñ ,º®chhP†a ]ÈçãºîÏ'·°*œN§aYVEƒdêjÀ)x“«€¥’B°€JH‘Í…Ï¥˜¹®{:¶x¯(¡!II(F ž<¦áâ"7œÂwqx†ˆ<ƒFIJÍÄY…ã;…»p,ö•mµÂ1Ä’*ì7 Ïx2‰ÀcŽ‘~µˆewI•Â1ÔÂñÌÂÏtèü t¡mn¡oná|FáXq¡È T ¸ùæ¾w$2d³Þ‚¾"€@Oêø ÆÛöŒÃÃA=£d2˜k»®gÀÐõÀûXŒªê½+Ä!aã« † ]/®x:²É&Åii¬?ÂkrÎrÁªaHi›J÷ §ê+m‡´]Ó‚~*J°¿®;~Få’L¿ûÝëWö¡ „ (e£Ø®‹ŸsNÑ6ªª–ud%¤¬h •(`YžòV-£‡mÛ0 cÕ_EXÞSªªÂ¶?ÃóòÏ ñøû` Xÿ"À¢±>.ð‘3>‚g~ö þ8òG0xÀŠ·-›ÍúžïŠïµk×Â0 Äb1d³Y˜¦éJTUÅÐÐ2™LÑ>≯iüâÛš¦!“É ··ˆÇã8çœMX¿þÏá8ÇûNIG°àzÉŒ ÏãÔ…·€›EQŠ0y§y2Mƒ Y<ŽòrüÀ>”X”1Åu]ضíGe-g].1–“““Èf³Èf³¾¬Jª0UU}Ãh)ñ¸V+Š%û§‘Þ²†QÐ3&áU8V’@¼Âï] ‹~²ˆÖ­NK# ½ÌgÉÂçM¢·+ ³¢S¤Ýáë ‹DÒš…c–¾'$b%Œ:— )ÀÆ>sCý.‡¤#“$/Nú³3°~ýš¥ß?9††¼ßÞ¢¼¦y2<0àÉ®¤Z‘ôRÃÃA„™m{FIkeš$ìH:B¹¡=¬*Fñ¾aƒCé¶õŽ„‘èŽZÛ/&RNU‹)Í ÿM1VKʳ;þØÜFBHH<©ÑyÝGàáÁqœŽ©„´’ETÆÆÆ0??+¯¼cccغukÑ÷===°,k1‡\ql;ð©„eYH¬¶¥e¥T×uÄãqÄb1¨ªŠááa}ô=øÚ×RˆÅÖµº™¤±,溺aÎú§ú±µw+ 1ueV$% ã8Èf³þßaD:†a~Ô‰a0MÓ/þ®ªª¿XFUU(ŠâRÒé´Ÿ €ïõn¦¦öâ7¿ù ãxÄãqd2ض7Á•Eí†a Þ¢ˆo!ER€”¬ûJ ²úî‘WÌ[Ò%QYÝHš 8ð º ¼qy{$j¤žZ%étªªú2 H&Å`R¯§’¢(þ˜&ÏòÄÄ\×ÅÐÐR©LÓD6›õ &†aøŸÇãq$ d³Y†Ë²Š¢Ë´—=cÝH\Ç)\+I»C£ iäÙ•”:{"2™â¢Ë"v’¢§&6Š’ÊÊB`Ø(Š$ãHºð™D˜d¤ÐÒ±°¶XXÖʽž$2Xhh¨Ñ‰È©Èbä\Þ¥IxÆW­Ì÷õLG2¨\¥Ví©Á"©ÌÀÝ ¼è·'â±Ç^DgH”H&=c‚ãDO$û)üJ‡Þ¨8 Kú/Um]Ý¥å@Ö/N8áG.nus!¤©HZI¸÷ð{¡©ZÉ÷ëÁ’HQ·AåòË/ÇM7ÝTäé988ˆ+¯¼ãããØ¶m¶lÙÒêþTEBŒ«É ¤õX­Ñ)‚„AXªªÐuÓÓÓ…(ž‹òä²Xd²VŽ;¿y'>õ`àIoQÑ…¢ë@¼Âïµááa^M‰Ñu©TÊ/ê.^êá÷„¢(~¤‰,È–‹ã‰,ì–S ¼b`Ó¦{pÜq¶ž°-chÈ3FMh¥À­tÇ@ÙÂØš¦!™L¢ñxÜOM&^øbP‘ˆ1 ‘ÕILŒu‹,Ã344äóÊE¥HºM‰â’z%bÌ”ôzR·(ü÷bÞªª.H/¦(ŠŸ/“ÉøÓ4‘N§‹ÅJ¥|#Žã8~ª2MÓ`YÒé4¦§§ûÌû`Zø¹ÞíçD³ YÒdÂèRˆYêˆá^<¨+×E>HaÃHºðY ^ú,¾‹Á‹ŒÐàGEx(|§baê+I_þL޽Xê(Ð^Y mr,·Ê÷õœ¯‘c¹r.P]û(Î9ññ&v–,‰L.G<¤‚•Ú#R{CT41ŽšfP§#19éµ€ ,X9vïFä ˆ'„Òø:.pÛžÛ ýy±‚cšæª-Ë@¢I]•™™Œãºë®C___Ñw===Eww7.»ì2\wÝu­îSEDÙ¬†,œ¬vJ/,¢—ý‘G~¦ùï4¨%#Å!~øa¼dè%HœšXÖ<™Y"i€&&&ü: ŠjÅRÍP";uÌ⪽ktxÕ«^„ë¯ ^è"N#•òÞg…²0 ï=Àã5o¡%‹ Ï»ŒÃE¹Ï ,÷‰D¯A100à€†††‹Å–ÅÀE¢¤øQïùZÄPé8ŽŸOUU_¾Ä€gÛ¶_ÛdzzÚO&Æ 1žHtŠÔ;QeIÅ 29>DÂõXJ#²DöÍBe]1ˆjš†X,†d2‰”ªÂ0€SOÝ à8÷‰ÓáÕ) Øˆ`YAú.)˜,£a§ rÍA8¢ M×ñ’÷ƒo¡^l¨’âJ¢KÂÇ®¤OjhÌhÐ$4­¾ô<‹&*×Ð{ýÆÇÆ0ö´ºE«ñq‘:€'‡ÉäÂZ"Žã9Õ¸n`D‘Z&‰DPt]ê TK}UZç£ÚÁŸ&\ÔBH{à/ŸXÀ¾÷í‹ Ž>Ú·ø3:…D‘º *7ÝtSÂlÚ´ ¦ibff¦êv­DÎrÈ‚M6›Åt³“£v¥‹JŠ¢ «ëV¼ñâ;ßyozS«›HÚÛ®0Ù1Wìû äÿ=îWt/Ûùãñ8 ÃÀÀÀfggýEÖFÓZ5«XÚ3Ï<ƒ¾ð~?ÅP6›õ#cÂ6‡‡ƒ”,ÓÓðE€ bEÒ©Äá-–ðHa#—dq<÷UUõ M’MjMH4=F:›lPžƒ÷<Åà=x™LÍÕ•l6 ˲pþùçûù¡¡¡¢:$™LŠ¢¥Ù†ù?“ÉZ$¢ (6TVªuÒ(Õ¢æ×Å 7âñÇ‹ï~w;¾ùÍg³»¼h1 • YF¤p4àâ%Gõ¢2Üf¤èÒP\”]jšTúD å|m軤ëA*¥¦!u^¢€âµE;¸žý+†ÔÅ´[†áL¤¸:\€ %—Bc1ï§·×;V*|Fƒ!„vÁ_J°Ÿ=ó3\øyX·(d`ýW5–\”~ddóóóEŸõôô`nn®Õ}ªˆe•/Foš&LÓô Ò®t*›vM3¦ë:®¼òÜÿ‘xå+Å7¿Ù³¬‘¤³pÝÊyÈ÷öïEroÿþŠ_¶ó‡=棕vß}G`ýúq(Ê?µ‘mÛH§Ó˜˜˜ðߢ| y“n£ H?èRŸF/ü¸ðuá-:›C&n<øF|æúÏðÞE“““ ÞE¢¼†X,æ×›Eo1øÈ¢v,ƒã8€®ë4´t–å-ÂÎþ??‡·(:ìÖ4¦X–…n¸—_~9†††ð|š¦ùÅß+¥½«‡pÔ¤D¸@2™ÄÄÄ„ŸÒOj•®‹´XJSþ…ÛtÀå—ã==xÍfW¼ñ*|`Ó™øÿÞt.ý§cÑólÏòÝ$BÊà8ÞBm:í²`[ÿà¥ëÒ¤óŠ¡- "²,ï¼hÒf2”.Ѷm?Ú€ï¡ë:\׋~õHT`çŽPÿlÎ>îV¬“¸Ü„ ¼‡›©”÷y,æév†áÉp,æéy’v+<í# @C àÍ38-%„öÀuƒ:uó7Ï㉓žž? 1B…D‘º *ÝÝÝ %==Å‹óó󘙙iuÊ"¡Ó•”K˲üÅcQ³Ì¥#逆‡‡‘H$üÒr/Šr—ÒT=­À+ªÄºußÃÓOÿþðqÏ=*àCêÁ²‚t¥ÜúÜ­¸ò™+›z¾l6 Ó4}#J2™ô‹YGÕ˜iÛÀÅÊ÷·m»èÝẮ¿8­ª*>õ©9|ÿûÝÀ«íÞD=l+r\[õ­€ê¨Ð]»>² ÷NÔu »K’h»®ëן‘H)äŽ]HûN{ ®R(Z µshxòÉ'qýõ×ã;ßùŽo#F³žMÓÍfá8ŽAeš¦/+–e!›Íú‹†Š¢ø5OÊÕr1Mº®Wc+E±9ŽƒS“IìÞ½ë\ùѸöMlþz't Ûð ?#%Õq d1$“žeQu’"OÂé#¹8¹$lÛöÓŠ¡CRkîžÜGî|ï}â½0 ÃO»)õ¦ä=&ºŠÔqŠÇäÒÚgŽãøïXÑ$u§ëºEéÅ©ì[/û®ÿÁõøÜïÞˆÿøF\|ñm­¾tM:í £å¦ž±XPÃD†Z©wRiªÚÔÈ©6GU ip¹öF!mA8sÉó÷åç›rY|xÑ~ûá]ë×ã‡þ0†ï¹§|j?IH¬Ý2^ø¶ím³Ì†UŽ>úh(Jû511l6ë¿Eñ‹gOLL@u5ƒ€–ðäQŠ’J¡Rg0ù$0þ—bßÛĹ_S€u@úÞŸ·˜&……]/þÊw¡î{Ö4rŸÎáÙ³žÅÄä Ã(ò€µ, ÉBÞŠx<¾ ò%ÊiÑhÚ5Ò\üÔ!Yµ ªT$%Üøø86oÞŒ+®¸bÙÚ&㢠éé¤V‹ã8pLj‘ÈË >„²Ùì’Óö†Q<ÞàŒÞˆOO}_;ík¸ÿ¿îÇe¯¿ €WW‚s²L$“Þ;ѾBYxõ~‡ï`$ TŒ bÈ÷üîwp (Þ_ %á¿Eçg¨ð1Åø‹Å`Y,ËBbOO<ùŸOøµ¡Ä°"ie ¸†›8ZÈùÄI¤ÞþczzÚ?Φø&Œ6Ž«Ÿ¼û»o«oIÇbÛÞÜÔq¼qµ’o¨˜¥iù}RÑ !„DM ÞשW¦ÓcÞ‚P”‰€(Q—A¥§§›6mÂæÍ›±iÓ&ŒŒŒø*R°~||[¶liu*’N{Z:©4MsEŒò°, ªªbvvá UUU¤R)$“I?G|¸x´iš~ÍMÓ000€T*EQN§ý02)Ìd2H§Ó‹š`-™ìí·ß~8æ˜ÿÅÞ½_Ç5×ßüær¹W/ûu%í‹a”Ÿþúæ_ã­/}«çÛLÓ„¢(8øÆqÙOŠ‚w•3¦Ø¶W"\uÖ²¼œ aƒk2ém+³´JyËš€ªŠ…¤$/Ópí“ÞÞ^d2ÿñÊ·¾ÿïÄÿÃx öìY‹ÙÙb¯ËâS€aŒÀܤÿH](ôޕ懀‰³eàî }HÝ 7Ã[dKÃ3°Äà§€Ñ, Ó‰iü…ƒcC÷nàßøwøÜû?‡}Òû@UU|ýНãÌ3Ï\ÀQ¼«x<î¿ÃÄ+WäÅȽÚ1š_¼œ^*+ƒã„ŠÚRýT‰0I§ÓxÍk^ƒ{ï½ï|ç;—½º®û  š¦!NûχeY0 ÃOöúò·Ÿœœô9Å‹{±Q4%S„a@¹ýAüð[κà'ØÿõûcØÆ—¿üeìÿ¹ý±fÍš p7iÒDf- K‹VѶµ~,Ëò#9Dd|QUš¦EzÊ;abbÃÃþì‡Çš‡:ëÖuÁuVTƒÌqßÑA×õªï Ã-ËB<‡ž(\hEê¥Ç(7W‘1s)(ŠR¡§iò³y¬ýÖZ¨J?rÞŽ_þò—‘t”kgÄŽ/(!»>i2í¬"† ¼¥ŸqQ‘Ò‰øõýàŒ_Ÿáé=…Å[q!$jÔ]CettÝÝÝ0M[·n-ú®§§W_}õ¢”îùùyÌÍÍ-H–ËåËåÐÓӳ໥bÛÞ„²T±rétzÙ‹ÐKgMÓêòº.·[Ä`¢ªê‚”;bˆ‘\ɽ½½~ái×u—½>Ìk_»_ûÚû011‹/^ïGáD5)O%Ùš'ŸŽäÈ,å§3?Ź/?·±N¸.æÏ;Ï«ý‰Ox‘‰„çî70Pì²æ8^‚jÀ3œ„-tÝ«önš5VäÓq¼Ï%A½ÌŒÃ®„ŽãSò›Æ¢fxaO ¡ÜûARk¥R) !6õ¸¯Û{1þð‡›ÿ¸ w` È·=p ìöΕJÁ7CCÞ%™¼Ø³5©[뛀þ= ˜ßÜã"À}@F…s= Æû4@;8Ä9þò‡1ú…QüìáŸáÌcÎô길€ª«@ ¸áàp9.‡‘1 BÅ¥?»‰ yÞ‘Èß›ÇM7Ý„÷]ô>·ë8|oû÷pƯÏÀ[ÿå­Øòš-Ø}Înø` /‚"<ýþ§q×Mw-é*+!Ÿ¥8N!=_Þâ_q‘¼ü©T púûûWìÝ^š¢Ë0 $“I(ŠR”ÒSdD*‹®’fSøã”¤Ó«|‚”bˆØÿ¹鿽úGÀ¶½ Bìc6âø×úWô${pÌšcpà®È5#Íg%uÛ0’ÚÑu="Ëò<ýå/äÂ3ìÙX–BéÕô{²ˆ(‘daÂ5A\×Eoo¯ Ro$vx©•FÓ4ß R‰vöz¯‰Àzê!tuíÀ‰'žßê5VŒa¤V (ÍARÝÉ;#\ûL"Tm;Ï|æÇxæ™}g ˲`Û6‰„¯Çb1˜¦éëÎRûOÓ4?Eh2™ôSõ‰þŽÑ4Ío‹eYˆÅb~¬œ+cvvŽã`xxدšÍf199éŸOÚšL&ý~J¸L&Û¶qã7¶ú4•VË'!¤2+¥Û: +ÀÎÁøïßþ7.ÆÅþùÅ1ލ±(ƒŠÐHø÷øø8¦¦¦°mÛ6lÚ´©è»±±1lÙ²ƒƒƒ˜™™Á† 088ذų’13›Í6=:E#Àó÷êŒ4ÏšZm’Wjh ¿tÄ{7N/‹A%p¾W m~ùËCqÄ÷!›=ɯcóÚ×>„ŸüäL?Õ@6›Åðð0R©”ï´’u`H@5Ùš+Ÿ•¢Õ]×Å\à§‘ª‰ªâÖ]»ðÀG>‚ Û¶áÎcŽögøó+¯Ä_~à ë‹O&ŸHT/¾­ëÞ6åŽ †ž²3èd2˜aW‰\«f| .ƒê§ /,—æq—”&RïDþßgM/ ãCpœ,Òé¬ÍfjÁXA"¡ ö<+%¨G”ޒ˪îAÀä¼½ì5À„QðÌL® $®,¤aìó.ÁPÐNÜ Àþ >hÚQxuø«Ï ]?¿-ÔH~È>$n^‡ìKØ{ÎÀ­ŸßßïóøÅ @ý Ÿ \žß…7?õñÅÝ’òƶ½GÛ7¨T1ð¥Ói¼ño„®ë.[ð}%)µ$ñ.—qG¼HeQDþ–E–l6ë§“q4¼Àëø9ÑŠ §íÐ篃sîñpÍ›‘½õ4h`YÞbË!=‡`×'vaþ«óp~îà¹ÿûœ¿XÄ Dôi…n&›õŒ'R¬®E[A, A*G AZ¿&"úq¸@{x|ÒuÝOÃ+ikea1\˜½T2Àȹ+顆± ¥Ó4D&B8ºûh<þø³­nMShÕØYÊÐPußÕ€è¡"_ò÷ò,?³Bø ŽášAò' ˆH;ðÀíøñ?ƒ¿ú«óýÁT*å×P›˜˜ð£jgggýÈT©o:00€D"á×4cL*•Zà,iYLÓ„mÛþ»+<ÿO$¾c£¦iþ¾âÄ!„ß=¢§ˆaE Èš¦áßøF«ogSˆŠ|B²Òº­ø¯ÞûÎ{qâA'úŸ—M§LHDX’A¥úûûÑÓÓƒ\.WôùÔÔº»»}cM__úúú055Õµ³(÷{ÑçAjf Eo“É$‰t]_ñ¨‹Z /R—e`` é†¤X¬ØkO×;îx9^ò’mˆÅNò'÷dz 7ÝômÜ}÷i°,øáÐCCC~±`Ã0üz º®/‹ˆ,¤’lÍ—O©é¾àsÓ††ÖËò„ºPðü>ˆ¿;î8ÀÜtEÁºgŸõ š £(ÕWPj£ÒÊ–¤ÿª"³™L}Þ°aÙ§! ÿ-…»‡††H$|=™Àšæ0\W)òÔ § xè¡upœ÷ú)  ͼà{ñ…»›H6º^l[ ;û+Š×Ïx˜¾SúlgÛÞ‚¡Ó hû‰ßf À/¼ãþË¿¼oöA|ã/õnÕqÀ5ßžÂM¿ú)8èuøPãOAËYIù ã;‰[…I!äºþê­,~d³YtuuùÏV«)·(*uÇù[Ó4?E¥,îÈw¥Näº.Òé4vïÞí§)¡^€ëÂø÷ÓÐ;´ªêÉ·i† ?€÷Ç~òXÜþÞÛñÔ™OÁ<ÞÄi]§áŒ·AÃJ„YiÝ6Œë6}y´k¢ àÕ+˘„·°ß išE©jÂõŒdAÐq±1,3•Òâ6ûÙW¥bšHÑáË·£©ÍðˆhÄž=û´º M¡Uc§ ÙaW‹¯˜¤Ñà"$#„Œ¥26‡‹ ‡#C§§§á8†††0== EQücèº^”^«Èi¡àÌ!ï‘oû^ü×ý¿‚ƒPù›¦i~¶ŠÒ9gé\YŒ­ÒŽ0aG¥rï«Fç³¢cÞûððÃoÝMn"­–Ïr¸®§û2šŒ¬vVZ·M¥¤ïÎ|7xŒát¸&QeÅ *’¬»»»èó™™™Íîîî²l˜‡~ccc BD…r™zø…#E”Ãx<ŽÉÉÉe¯ÇÒ ÄˆÑÌS9=õ³Ÿ=ë×ÿÖŸà[–… .¸gŸýa|ò“ÞÄ4› #ÇÉ`bH§-$“Yœzê±Ø³çàZÂ9hOi7M-«Ÿ066†[o½µ#ŠvV’M`éòyë­·b|||Áàªëe& ïc}Ø5º m*¦éýBÞ‡‡‡±í£Å£ãã~zy"?ð–[pN§=M>²Y¨²¸äºõ…ªÔ •Jù‹¾ÉdÒŸtŠAF"SÂ^÷á¼Ñ{÷~¶ý\aR d³Ž¿ð,) d1Mö•És"¡¼á/ZË9š+›žFŒ6ºîígÿˆý•÷½ûÝ/ÀM7ý¶ýy¯Ö”›Å·ù8ÞúÖWã‘G~à¿Z}·¦Ùò¹gÏŒapp°êûËq “J ÅEªm]s Þ°co¡áôÓOÇ?øÁHË^5G‡p»3™ŒŸ«€oH‘´²ðÇ}ÛrÞS¶mûøòæý¤ÓI}oÄÐKÂä·æ|ù¾ôšKñ±K?5¦âÜÞsñÔ1Oá7ßÿ ~½æ×~äJxAº™ššò pÀJë¶aL³¶]q©û’ðŒ(‹4ˆÁݲ,hšæ/zŠÑDRãÈ‚h»P³Ö¡ë¡{¥ï:Ç &º¾ÐC¼¼J)LÓÛVö-­·&…çTuaDl6ë;™,8_:í½ÀE¨ç>¤€g/½ ‡ú$€W·úv4ÌJê¶•h§ÅÙpÔ¦¤  §¿’èM‰¶±1-"i©Òé4 ÃÀä䤟6SjŒHÊg1¾”Ö-Ò4­¨VhØI#<ç ë…áÈøâ××õÈ×ó~’4º²ÈWÎhR©K£È53 ¹\ããã8öØc›~žVÐ*ݶŽãEÔË븎ҷ„øP·­O·Y°¿¤­Ep¬ ²Y8m¤C’è2>>¾,ë¶+nP©ÄÜÜÜ‚Ïê ;øàƒ«^?UI ‹ñ M&“ BrÅ#&›Í"•J5­FÊJ aÑ¢/G4µ~꩟²÷C¸ãñ,âqÓÞo]÷惀ëêøë¿~?ûÙ…PÕ$Ló(|éKßÇ3Ï|ý¨‚_ýêp|ùË¿ÂSO}ÿüσcŽù,>ô¡3}O¥RÂyí—CÉÄÎ;—í^E…¥ÊçºuëÐßß_ô™¤+•Ë»ÿçn|ü•Çׯüzùƒõz¹¥öXŒBdE*•ÂWl©ýWsÝu8îŸhõ¥j Ãð!›-áH§ƒZ,™Ì’sŽ„ ’¥u%jص, wßý?øÏÿœF6›õS!ˆçŸaèííõÓ#AžzYh“I–e!‘H #“ÉÀ4M²(¹§%-ŒÔ†’H1°tÐApœ uÄ;ìNüøÇ```Ï=÷ÞûÞ÷âá‡Æ®]»Z}W—¥Èçš5kê ÍöíxI,H÷uýõ×#SXLýÆ7¾üà­¾MEø<ø ð’—܄׾öœrŠƒÙÙI<ûl.»ìwxê©5ø·{}}¯Á»ß½ï~÷Ž;î8\ý{15uÞð†¯áœsvcãÆ aYÞ¹m;ëçø•…âjéá155ÕêÛ¹ì,U>×­[W´M2é)«’¢ÄǺò ¼æc¯©|°B‚ø‰ÉI?"¯‘’Íâ¸NðQ¯Ÿå¢Q¦§½‹—N/|©ÅãÞg‹˜È-6Š@ò6ËßR@3,‰DbÁû$SXø‘çp½1D‡'Ôâé/ùpj‡pq È©Nû ‹Úù|?þ8üñ•¾‹+ÎRäS&µpï=V¡ÇëÖ/~ëׯ÷óšoÙ²¥-"4—B&“)2Fðáô”’ç\ò½KT¥D´ˆa_Ä7îyôQ¤&^¡×m†sóHÜ7†k8^xiЀ­£“Gǧ>|*{Õa~džä™=EjÁD•žžœrÊ)سgO«›²¬,—n+Äãž.µ¨5< ‹ŠF ×]¨4åÍŠ¤ø çð•<‘áŽ;Ž'Ta‡a¥bðÈfƒúgÒǯ Šq!||èn¹ +¶åd/™ô¾/÷xU¢Z=*™‡$“ÅÇH¥ÊŸKÚ)}+Ìi{×CÓpÞcá/þô§æÞ¿Ò,ݶÃÞ1­DꀉS‹¤±'‰JãHi½“0¥éd…vŽš¬‡ZcêrÕ ê“jèêêÂàà ¶nÝÚê˱ì,§n[Êðp`›Y„U(Q¨Û.Q·uå €ú,`#´FkY¸{×.ÖO!M¡¯¯ëÖ­kúq#cPéëëÃøøxÑgsss óó¿‡ãH-ÄØ099 Çq|Ï›ðÂb]TK×cÛÕÓøˆ—š¢‡&"9m{{{}ƒG³PàÝïÖÑÝ+R²+M.äÔ’ Á»w'ãýïÞô&j®ÈÖ¥ç(Ü|óƒÈd~ˆãŽûK¼ùÍÏbË–03s.»ì œ{îøÚ×^Óüžyægxñ‹usLÓÓ“øýïÿñ¸ŽÓO~øa<þø“xéKŸÀž=ïÅK^ò üÛ¿½ûí—óCÓËÝ÷ßþö·‘ò«Í’OËòìUàc?]óÓêžj…Å UU,¬Ãu›ëŠÖJÊ¥‘Ék颕xÌ–^ ÓôÞ‰DÓÞ¥År÷J"U*QÏûEÎ!ǯö®OQ øÛK;.¹ä’¦ô?Ê4}ü,¬Y&ÿ˜¾ÀŠê*¤Ói¬¿í6¼îÊ+x jLÊ{œf2?½‰xäʶ’êH©Äë7“ÉøyÖer éT¦C6{ †q–u^ýê2…Œ ?ûYgáÔÙS¡@ÁÓ›ŸÆoý1TEÅ S7ÐÛÛ‹‰‰ ?ý^¥Å1²|,—n ÁKzÅ×0ÀˆÇº<ŸM«IV¶èÆáçUê§Iº-`a1®Ò4[¥ÏûÄDZªS—žo)T»ËÉ^êhQ­-áïdÌÍSîY¿‡Þy'z—·Å-g9åÓq¼Çl%^¹á:"ü4ZÉd²¨x{*•ò#.¥xºDž”E—Ë8Ð4l»¦@iJ»Ò"ª2O(§/ËqJSí™f9às{÷bGé9²Y®¾@WH§ƒ÷•œ?¬#›fñûLUm‡‡½ú0y/¶Q4j#,§|†'¿ÒWf:½„èOBVM—Í4àîb_LÓ ¢S¾òtŽBë”5Ò‘DÆ 288ˆ¹¹9LMMapp333Èår8ÿüó—|L‰r/%™Lb²š·à{{Ê¢œä‹oëBEð·¢,Ôœ%¤^ŸXl¡"%‹¡²øþ>™ôŽ- a©·™x«ûmµ%%éÅbˆÅb¾§k³< ½¹Ýúàš-’ðnåtÌ0gŸ}Î>û4ÿÿ‹.’,\šuøÜç6ø–Žs4íB"¶ð¥/}##Qð°W 5>6௸^ø î½w7ÆñÞ÷^ÃðnËå—??üáÝèî¾§)×+Ê4C>ÅáSUËÕtà‹Ï}#jõ|Ô¶mûusŠOšV†á½&&‚ ÛÀ€÷дÀ}y•J¥ZVO©•4}üLÖNðŸLTLÓľúU<üüóØ’Lú^¯« UUDc‰—o¸·ªª°m–eù9ØÅ#)ñ¼ô›R‹Èð2õœõqXö!vÑds¯‚»ÏZ¤ÓYF§µÖZ@tĹ›ÏÒÀ{ß dYmOþäIdÊúùßWtaœ,‹n+kp¥Áu£aA„ŠD_KÚÅp탦"Q ý~ãñÀ‰HtÝpk­l)JmXQ‚ã¬2÷c1ð–ulðŠ›ùÿsÊ)¸þî»ñªV7z™Yù¼ÇxxxeÔ/˲|ÃI,ó ý2Ÿ‹ÅbE—Ò±ºêMtëj²"ò HaÌâímÛÓS½4 çÂɤw ×õ<®%˜ßzi ¼íJ ’YnGب(ÆŽRkøÿÞ^¯-º^~¡iE}¹áæ›±!üN’B†d³½ûṅû&ï$yß•¾°KŽ_ÖP’H¶Ï­[DЭƒÊrɧà8AG`¡Mz•\fBMÓeӬװ‹Ëüø‰5€IDAT2\{öÙž3@«;LH"cP€ÑÑQlÞ¼ýýýرcFGG*êTš‚€_0³–§tia¹˜i"iõ *¸µÁàà r¹zzzé,—(NWõ¸‹Çã0 ÃóäqÏcN”ÐRŧYšr#!aO¾Rdõß²/É|%¯®„…»® ˲ڶVL£HI ˆÇ?[H÷¦#‘°<0÷¿è Äådh\>ř̗É4<Ïw¸ýéÛñ?ñËïhYøÙ7¿‰Ë  e¡\Ð ¨õ^’¸v™ñË>Ùl`œ-õô-LÒ}k¢ª¶¥Á¥X.ù´,ÀºH¨@öïå™Â£TPdoÉåðÛ¿ÿ{Ü{ï½øôÕWûíK@ìtdÌ /l­]»Ö÷º2MÓO»’H$Š¢Zdû–[þŠr Ü'\¼PÓàþ¯—–䡇.D>ÿj\»åðwk¯ÂO»^0‚7üÅ·ñÃ_>ƒ¿ÿû£ðàƒßÀ®]ð§?Šg»î‚¾AÅ¡wü “gåqúé÷âoÙŠ¯<öÜö‡Û00<€Ã҇ᎋïÀÑ=Ú[x˧fÔèÀ½‡ß‹#î;‡¼ù Üòé[pÔQG᤿? Ѐ?ÙK?©o’w¶D1ÉgÙlgŸ}v«oSÓYÝVÊfI]òX¬ÿÞ$Õg\Qè…ß6Ã{ÇÁîТ¢xº/ɘ24äº^ìÌ#DP”htñÞòSó%“ÉBä˜˲|D8­ŸEÃ0 ª*’…vÙWŒU.ò/Qjáb×R›IÌå=+ç–:6²Ïää¤_ï+øz|"‘ðÓÖÅ©œt]÷k™­/\™uË5v–âºÞãßÌ¡Q j’‚Ïu]†X,V47%úÐ4C€¦ÕNUW«£õ>K±Xq¸@atçò±Rò)¸nP3¥Röu){EÚ“jõ’¥¦g¸gøóÒýÃ5¥J÷±, ªªúǻ뮻ZÝõ¦³œë¶îßɧ<\óÆ× ïé§ýµŒááa_G!$ªD*B@ÓËlv¡Óº…­"‹iñàVÕ Zz;*Q²È\iá3ö´þXÌ×þÞƒ#^UU?ç»LÄ"Ÿ[wO>™ÈʂٱÇ>ŒN2¨T£ù´í¼+ Ï#: áÉ]ÖÍbB]¸Ø’Íf1÷íoC?óLd>ùÉHYn ÂÛð;MQj¥$Å¡¦ç­£³XÌ*Ý]†P¤˜†ZPŸ’¸Ù}×cò…/ ïùÿ0MèŸù ®'«9"¨^ Ӓ‚EÒ‚)Š‚ééiÿ½600Ã0ü(ÑD"t:í§lã‹gxq±öŸ`ëãñªçwí§ãWSÄŸŠ/}é]pÝë±.¿Ö¼lÏÝÿð½ïÝŽ¿øiìÜy4ææ\ܰ} þñoÖâÏýúïtýŒ_²/|áO1þ™Wâšô:üþŸÀþûïÖþ|aÏËñÈmÏâ¾+ºÐõÞgðÛŸäpâ£/BÏ›{ðÇûþ„½×ìÅÏy§|ê(L¼pŠ®ÀH˜ÿÊ<ö½o_¬?p=^¦¾ [÷1<'Ÿ|2ž»ö9¸O¯ŽB“K•Íx<¨­n‹(¦Ãg-!'lÓ4‘vÒPãÞ¢|©³Ì’£ÍTuùk„Eò :¨éÂ}ÔuŠ¢ ûF©(Ó4ý1FÌÎÎ"™Lú†ÇqüZ22H§Ó ®›ã8pÇ‘óKŠw‰¼hÓ4k.¨ªê÷I"U¤¿bìã*ŠR±~™ìFþ/÷þ6MÓÓÓèííÅqLJÃ?¼ãkÍ›{žM >>®ëbhhÈ7 ¤R)d2™ªÅ⛂D‰¬4’ùš)Ÿ‚â‡ë·–òÚs h¹±NÖ¤^“8Þ%ëFb„´,ËLÓ„mÛþv€·æ$û‹ŽŒóâh>§èÈñxÜ?¿¤Ö'%i¯86Þ¸)k9²ž#Qäb( Gž:ŽãëÝ¥ûH¤§8YHÛo¿ýv\z饭¾U+B£²éþ°_(»”jâ·ÀWß÷>¤à«Õ¡›´‘3¨4)MR*ƒ¦iVœ,Ї˜„M+RìèÜE@©Ù"^…²ðSˆÌyúïÄOÆÇqñ7¾áâÉ'^Rb¤o©NF&Ÿ ¢“š¸naždÃóUà§—1M³¬—»(,¯¹à33Ó¹rØhZe7-qN¥ªG­HqO) ZšþAjQñ>¯8® Øÿ¤žy †Ÿÿ$bµð6„kˆÉÂaÓë+t8á4JâIK¦§§}ÇñvSUÕ_Ø•4œ21UÉä¥x{"mÎÉpœ Ÿ XÖÛ‹ÅðïÎâܵGàÙCçï¹ÿýpÕËÇõ×ÛX·îMxè —>÷EL+‡áë@ï¡…»\û·ý8à€“±k×Z<óÌ3øm~+¾½ÏZì÷§¿ÂÉê“xð?·#—û;ì»ï^tÐï±wï 8äK€ïk×~ ¹ÜÿÃÞ^]]Ïa_w¯|å4~ûÛÇÑ=úl~Q>÷ô¾xúׯÂßý"œtNç§Ë\*¥uRêf¶ ?€›p1Ð;P”–jIé¼Ê!ie±z,:#E—”…YØôU"a½SŒ‹’RÏ4M?’C[Òé´Ÿ +N#›ÍÂ4Mÿ]Nk+1—z¥Jä €²|‘UO&ƒwcxÑ[Ó4LLLø =õÒÈÂùbõr¹^² uâ‰'.ùÜ«©“¾_‰B Ï·t]G*•*òš^mˆvÃóhUUýèµjkdiHiÚL&¢*§ç‹¢˜•®Çˆñ_ b`C…Â5–²Ù¬ÿ>'I)û„ ¦iÂ-8ÒÉqÄ YLÉlÀ?¦Ôn’¨Oy‡ cbbŽã`xxØ““ɤï$000àë-2†ONN"Nchhȯ)‘•“““èíí…ªª˜œœô,â,Ç111]×ý»aljÙÙYd ‚Ò–x<ŽÙÙY_¯˜˜˜€ëº€®ëÈd2þ¸®iN:é¤V?&mƒu)`? ¤¶0ÉÃóŸM1°q¼#Q§ã *â=9Y\’¤4/§ƒËñ‘¡b(’c]]]xôQ: Õƒý@û@áÃÀO, ‰P-˜I;Ðq•xÜ[s+•¿J“É{X”Uâ;;Ȱ(Å[´ ÕQ(ZäÑu¬q\ÿä“Àµ×™Œ?øÍNLàÉï|º®ãào„¹ÿþþ$Ú0 Üqé¥8gÓ&üìÎ;q܆ þ±;ÉðBbÿwycJX\×õkù)½ÚÉ¥¾Çå›âñò…d4=í½Â«Šâ;І÷/¸¢Å8鬉5ö0û}øì7|Ç‹Å|9•…O¾³£LâÂãh¥È!ù^Æë³Þüf^í„õðîí;l¾âŠ`§dÒ“«nÀÿWH4¾q#¼pߎ¿÷=zè¡8÷C¤Aˆ…ÓÑÄã¸÷ø9¬_ÿ4 8CÇñ?8ªªâ#ùŸ£*H„ÊbÈf³Øûù½Ø/·”W+Åãh(ª¯bÛ¾ž,…ÎÅ8"5H$Äu]QRfÈÂR¸N_¸p{xA¤+UÏ œ–¯µ<ÊÛÅ)Ç0ŒUS”¾™T+kYJ6›õÓÕd2™¢AIAÓVPß]Å!†ƒð®üNç#‹£Á)©U&)Yè•ÅW1ªÈ{LÖÄqPþÂQ#bÔ‘4Dâm/Ž b4™˜˜(š7Ë¢¸¤ùà×®’E]ywÈÿr|y§Êâ­DÌýÃ?üCkž6"™ô¦ ŠÚK Ézê£ÈRH=ˆ£€¿$âBîŸ<_ò{``À_0|æ3?ÆwìÅ­·Þý×µ×^ ÃHàÿñ[xå+_ Uuà8¢ç%`:TÕ€®{㊮?üá_àw¿ûW)Ø60=ƒizÃõé§Ïá˜cÎD6{2%×õ®Ãk^sž|ò0MµÕ9áaÀ0<ãË‹^ôW…d&1X–·ÎöÐCÃé§¿® xÍ—÷†‚DbÙ¬ê³o*÷ÜsÿŽ#Žø*~›4 H¥d2»‘ÍzŸ«ªç—LŠâÉÅÚµžï^:-iPÄb³è-d\?=oÚ™ðïÛðpðNv]™Ì‚Ìr¼½{·crò(˜f|ëÝ–•ÂÀ@qr¯mÓPU/ÑK˜#<¿ÿýšV?þmñÞPþºßÿ_Þéa‘¨ÓQ•B„aÙ\—ÙlvPJÇé†B&W5! }Ñ$Q.p9×IEÁAwÜýškûío/|Á÷’8pûvÝÕ…µ?øμí6üé7¿Á ozoòüú¯~uN>úhìÙ³Gýõ_cÍÞ("Þ†LfÚ†XÛÄU ?¿ãšk ž\ì/“z%tRľšÌJ„K¥xûð;&üLÈw®ë£tÿ‰ ÀqýøÇñúV_‡㺀}ïaоõþßIؾ, y„“΢ì;7<ö—ï¹ha|IÑx&ƒõ¥ß~¿ãïÀÔÔT«»Y[vÊ4M˜¦‰/òœúÑSqðÆÆŒÉáÅC‰ÔT ‰D»3œþÿˆ‰B!{ xg¸®ëöä}®¢ªªÿ^ äŒÒø¿˜Èž(µ›¬<µJnÊ¢«¤é™œœ\±t&R[HŒCCCþ‚ѯÎ4S%RjÏq‰°h ‰¬Èd2~ªÙOt~‰Ðy¹¼'äQγ\¶“ÿÅPQŠC ¿’©4…_9£g-ChiÃr,%}WØð#H„Âúõë}¼Õ†®ÍÃré8õ9+8Ž÷‹©µn¸a/n»í6œ}v¾÷½1;›‡ª:8à€£ñàƒoÐ/~ñnèú/pöÙ.¾úÕ£ (]¸üòxÛÛîÅ Ø𖂦yÇ?ì°áÔSŸÁA ׎?^ÅM7Gýœ{.°{÷+ Ù5UK04”†izF離þçë±~ýçý~÷ý] |ÓTpœcÐߌïK,(Ób1ÿüÏÅÎʪ \pÁpœõ‚ïäÇuU;Á0€Ë/?7Þ8ZTgÊq<ƒ„ëz¾sá`ÒÉÉ `NÄ4|m»üëJú®ª@>¿ðûp€¸ï/ÿò¿pÑEgâÍo>«èÙe§Ò×´´­\Fì‹.úææ^Ф§¸ƒù¢…¡žŒÙ‚mØ)YͰ¦i:Ê ’Là½À4pËßß‚«Ž¿ Š«xy¥5ັëðº™×Áø´ám¯À+âiØázÿ˜ðê=pý¾<å&ªêîÙ,^pÀ0 ¿&Mañå(ÈfaFµd2‰}ÒiœýÃbîe/óûî‹oýàØ93„U;žüÉO ¨*,×Eÿ÷¾WH]2‰‡Ï: û샃ƒ8fÍ<ûæ7ã7¿ÙWê÷Ù³‡MN®*¥š”ei>/”ð¾ )ŸžZ³]ù<Þñ™ÏÛY.¸è"Ôßï¹³ÈóDÚ]¯/F#FRE©¼À…ÿš8`¼ñàMÅï>×uýŽ€·ToÚBHc<úèúbuIJŠkÝÀGL`Ö{¤Š-_ù:žxñøáÖ[Ðõ\W`µª“pþoït–ÿ[ê™H ?Fa¥a¢à=ÎÚdµS-ÁVÁ0"Ù†††|CI,C:ö¿O¥REÉú i2™ TUõ©~6ƒÂÿ¥ÆŒÒ¨œåŠèCE;@?üðV7!²¸®·H_¸.ÔcÛ²m·Ý¶þå_ÖãŠ+Þ§žú,;l7;l7N<ñ"lßþ%œ{î{pöÙÇA†C×ühÀ›ß|€#ðž÷È×aÇŽueß ©ÔZÿïâö®ð®ŠmÅ.[”™ZS,U-ÞFþ–hrAåŒB%±ºòÊSqå• Ïí8•kÄUS)*}·5äÛßþpÙÏ«- Uú|``×_ýâ±Êp>ýu¨G}Áÿ_Æ~jDBÚŽ1¨¸.€y@ý5LÀ½÷Þ‹_üâxßEïóŒ&ðÔOá”ùSp܆ã¼ítïs¸ð&¡OÈÂ/š8<ÃJ¬°Søí"0¸8…} ž&b¨Aa»ð}'Ï;c1¬«cÁi¾éMXÏàr| …øÜû«_aÝ—¾„‹S)@Q‚ÜŸþ4<â<ø±áÀ·¾ço܈oÝv›ï]‰Üùò—ã—÷܃×ö÷ãÚBMUUqëµ×¢ïsŸƒªixðöÛ¡˜þЇpÆ{Þ㇣Ͻç=XÿýïšJ%-,Ä2Sø[×ýê‹ y]ÚÜ~ûá?>ö1ÏûÌu#›Ë™Ô‰ª.¢’2iî5@ìÍ ?—ºj(¥½…Y?ü^\ýNx Üj‡êÀ¨$5O§ÌOÝr ~¿ó~ä¼ï}ÉÉ8üŒ—wwyNBÓðôÌÞÞ ž”¦yzWhÅå']„c~úS}àØyòɸþöÛqðç?ïçuOnûÖ·pöi§–€"«…ãpÒKˆG9ÿÛ¶ýº’òn)ˆADÆfI‡²víZLOOöm?=g¥0 ¨n‡èâ’f*‘Høµ$MU¸Žd¥ßb©'b£Õ´Kú=²xݹءÉ4M߉@äáâ‹_ŒÏ~öë…-Ö†¶®tðC*¿ÙþHËí¿°RË©Tg-©tuuáØcmu3"O6×ý¢®àÿlpÇ7ÆÒtŽAå{Àä_¸¢øó/¥¿õ_T¬1¼\†vÌFÜŠcú·!s{iÊ·RÅÆ@žÑD~„BÄ â…cÄàcÂhð 6r.Q&Vø>Yø;Vø[ 46€ €¡Â¾™ÂþbÌQáLQ6*Š 8ÄúW¼¢lÄ‚LN;ûlÀmÿ÷BýÉI¨š†W¶®çT,à§>ô\׎¶¨*®3Mì[(‹Å`?ú(|ç;qöþûã–ÿþo¼yÿýql!'ï·¿ým ¶úÒDó£€sOáQ,hâñZêöo7ÝLrJc´ !M'ýŸ@æìâϤp´D§HM#BÈ òæ8pv¸=ãéuP°O§Ói˜šHücšö^Y ¯ÎÎú5Òé4tEkš~ºíµ¯Åº} ë\ë²YXgœ]׃±Ù4ñÊéio%èæ›½Ï -„xó­Â<Ñù ½À€÷Ù}ó÷áé'žÆ…ï¾—t>Ø›ç9X8OSáÍU`çàN<ûÏbÏž=¸ï¾ûp‘'àSk?…-nÁÅ;/ÆÉúɘÍi ŸÈY cd Ðm=˜Š oýW>Óá;Æ´˜ï ¨š7ŸuuR…jªÞüWÚ(sT™ïÆ ßÉœV Ž‹X¨OÒ?§°¯‹À‘QG0ßÍ"˜×&CŸ‡?¼÷`Á\X8.‹#t=4óe³¤}Ò¹7jèX2w ç³B¿å³lè™ÐBm•k"¯N³ð]²°Ÿ¬Èu¶ ßÛ…}åþÉÜŸTIJŠ#(à¿¶mãß=€áã8÷øs‘H$Š#-åY•k.ò^kÂÏ«|/ŸÉ³îþ—é­lƒÂyD†Bm,m³ÿ|–~o‡ö¿_Âò>g¸-ò·´½ZZ4't=Âí¯¶]é>jÐþ¢{eU¹6¡¶¡ã¹¡ßJÉu ·E¾ ï_îÞ”^'%t µä\¥÷ÓN<ñD¥¯…ãÀzVGæ½%m¬ªªöÓ:ÒtŒA%ùa ñá…ïôpí©ÅQb¼€yÂQÙA˜D`ä(7°„÷Ÿ€÷òuà)M@Å¢…Ž~A‡s@Ê€b¶‘íD¹4CÇc‘OñMÁSŽQ8—(‹fxY@É=Õ4 š¦ù† ¸¤bäYo°÷}ô£xÝ•W"N#ÝÛ‹ïnÙ‚w1mUœÛî„~ñIEŸIº€0á‹„ ›…³ç¨oZ[ô±ä=‚<é„•ãàgÞ3]V÷L&“°,«¦·»Èyý&<ÆyikÚ ·†Q_²yBVNSO\­] Ø@—ÓU>uÈ ã:Ÿ ÓBx¾j‡þþ­ä)#X€L”œ#ìØ—B°˜)ßË­¼f$‹ƒÌyx'­°¶°OÅä<óÙ ‹˜NaŸ°“£dœvËb©,˜"Ô.³ð# ©Ò6+t<1’²K(…mÃ×ÚEñB«ËµU 8ÃÖTór1¹…k" Þr¹‡…¹ÿú¾õK~~;Etƒj8IAþæÃؽ{7ž{ì9ô¼°ߨò œüµ“½}RŒ[@`€Šï»UrâðÚŒN“¡ïÌÂç&¼{^z ‰ð1ì2ÛÄ ŸO"X×DÎÅ@#FÁ°A 쬫”iG¬`G#e ÁsŠÐ1äOþySà=ÏÒ~iGøÒ~9·ÈB:´O©q#làÙŸ#OÆ“I6tL3´Èu¬É{IΫ҄ίG½ò(àHj¨*´¡ jKRôKZY¦%íDÇTì¹½ÐÞs@è÷¼õ­øñÓOCöެ׬[‡£/¸ ˜L&“ ´ÔÔ•,╲¿^åÿ0a%U/9&BŸ…=“’ð™°’+Æù>‹…ÊiX1#MxnÝ¡‘0åâäe¦¢àØ;[ݸ£îºê[ƒÜ¤ŽãÀ²¬¢ôA’¡¦±“Ò4Üí·câœ}lð?Ëf³~ÚÓ4aÛ6S}²Â<±ÿe)"“Rÿ Œ¤ŠÅb°, š¦Áu]ß©ˆÒöþ² æÏ¶@9æбÃï¸jß<2Ù.¿VÊ7z'Ÿ|200àí¤ë€VpTpüð=ÆE?ý)yäuê©xÇSOáÐû7\ð/½ÐigŸ {yÄÇ[y ×Tá¥ÅM&ƒïǫެhÁ\0™ô\ö'p.“ˆSIgL>íBa†Â¾åœ„ëq2 SÎG*oN ÏÃÑbl(w Y¬-ý®ÔÐT-È]"lô’~VÚ§ôš„½êÃû§Ê+ü™ÌÅ•ÐqK§>± Ç“kf§_r:HyR@=$)Ö Ï‹eY0M8ÉKMWäTðŽÐA*eë¥'*wò„ïo¹óÔ³¦Ö+=³ò\:à˜€ªT¯jÀlh[#¤Ù–w®rfY@,dAR@M·?f)FÝ‚•1URáÝ5ƒÜˆÅ&CBœ° 5ãBç)Vp’Å×ÉÕÉÐEÈ8^{œCBçq m,˜ GÞ‹ÐàioÐTè<šíÕ{Eáû5R)<<õ00UÇ=\ÅØw½äÿBÊÊt:]äàLH;Ð÷;{0yÀ›üÈÿÌ0ü‚`úöÛḮ—k¶4eI,V_Áäv%\§%¬¬…•Õp„LX °J~«%Ÿ%‘ÄK)Š-)ÒÄD¼,Ä;Œ9áwf8L6ìÝS.ü²Ô3D½åï°—„#ì&סô”ù¿ôÒòe_G=ð¾»{¤H‡1M³(:EÒ‘pÑ–•Åþy7¬]¯ æ$®‹d2‰ÉÉI8ŽUU‹¢ø!­CjÃÆ‰ KŠH‡½ú¨£²< Þ…¿Ìo†ñ@Ëë’ådðÆVÛ¶áf³þ{Ïúõxò‹_DOµôyõdT¨•޳GAyWèúòfÃ@+‘(–•VqšñZÖ€¬–Åëñún|›àšÀ3`‰û;à&H&“°m‰D1ÛöÔeѼ´6ªUXØS*K¥Ž¹ªZÑé„ö%0R„eÞ,Yدv ¡Z[5maÊlù.l0)•ópÍR1Жö-|þÒk#}Ô4ïXåÞ#²æ&m+w ¹FåÚ>¿ì¯ë Û*Æc1ì¸îÂ4¥šV¼_¹õ@] Ú¥ÛË>r²(ìÿÐüoYR©Eat i;: ’½ô‡p{>Uä ’L&}owÇqÊ{¾S`+£—üŠ=&Ê9 !ðX ×Σ“„·BYýÃ3ŒP©À‹ï{î~AÜ«ëº~¾d2 EQàº.b±X¤‹WÒ‰X¿?ÊÙëýÿeQVUUôöö–õ‚'„¬<ñx¼¨®‘eYPñx“““H¥RE“PNH Y>œ×Ùȼál?÷¿ëºH§Ó°,«hÜ”¨1MÓ`Û6R©”ï¤ZjF„å`µ_#t HÉ€SXôWܱw/Þ00€D"8ï)J`8°íòYP¯¤—ÊMévaÆm{?¥û”.ÔW;F¸m•ÚZî<õ¤í¬õ>RÕâmʽ3ä…XÉKU‹£MÊC¢cªm6—£ž÷Y=:R­ã¬Ö÷fPúŸ@ì½€_S7Nûi'"gPÉårÈårèééAOOO]ûØ÷?ƒØçOñÿ· oMÓÇ¡i=õVŠr—¹š÷O •C_kÿz…ÏÊ…X‡1*ü-äKŽ'„kÜ„Øuãs_·6a±ò¹ó×/†zÔ üÿÓé´?™ŒÅbPU• ¶„4‰Åʧ»Ï‰!G/ Žã@×u$“IÌÎÎÖÜŸRKÑmq>˜žžö=ÝÅ›OÒyqJÈÒYŠ|Ê¥mÛˆÇãÐu½Èà)ÑØ±XlAÍFBHý,iü,Dz¤Ói˜¦‰‰‰‰âq2¼.TÏÂ~9j­-…!•¶ µÉ)Dª¸¶ MÓà8Eñ– FYÿóBtªÌ¡]E¢ªpZ"Û² ëºŸþÓ¶m¨ªZ¼OáoÇqümÂûˆ1ØëJ°ëº°, ‰D¢h1Ü0Œ¢ó¸®ëG»‹e¸-–eùiž ÀeYPUÕ¿ò·lkLÓ\ð[×u¹>ªª"›ÍúÛ¤R)$“ÉûH€rçI$~Í×jmTŠ¢ømºæškpÌ1Ç4Q¢Ë’dóföM»ûê¹<÷ï|'N9å겤-yAã‡hãããØ°a¶nÝŠ 6`||¼æ>G>ö¬ç΂þîCŠíÅ_Œd2™âü˜„,• ïøì*y¾–"Ÿ÷¼àPNy1ø‹@‰DñxÜW !³ùtþtô÷x¤x<Žú§Ž™„4‘¥È¦`šfѸ™N§áºn´¼Û ic‘OÛ¶1<<ŒL&ƒX,Ó41<< MÓü¨1.²t–*Ÿn!Ý»mÛ˜žž®(‡–eù×uý1WÒ÷Éß¶mchh¶mc P)ü2™Äðð0LÓ,ú[Ú044Çqü}†††`Y’ɤ¿iš~QYÏ’ÌŽãø¿mÛöÿ—}ä³pJûÞ®ž}$¥hé>ákl…Òv…ÿo'Ǒ߲ü_ЦiEëâ-é ÂßéºîG5HÝ8ùcGØ©ZQ¨ªêï#ÿkšUUýóÈ>b’ÿe»ð»]"†eßÇ{¬…³r,Y6?ÿ=XO_»ï~÷»eŸBÚ‚|„Èoß¾=ŸÏçó;vìÈŸp ùûï¿¿ê>›ÏÙ’××=™Ïçóùéé鼪ªùøÃùéééüôôt«»DVW]u•ÿÜv2‹•ÏíÛ·çßqÞóÓ?ÌçwïÞWU5ŸJ¥ò†aäwïÞÝêîUÂÆ[Ý„a±ò¹qãÆüä¤÷·®ëùL&“WU5?;;Ûê®UÂöíÛóW]uU«›±ì,E·Ý¸qc>“ÉäO;í´üÅ_œŸÍOLL´º+dAݶ<òÞš˜˜È«ªšÿ÷ÿw_·%d¥ n[ýºèºžO¥Rù|>ŸŸÍg2™üääd^×õüôôt^×õüììl>‹ågggó‰D"?;;›Ÿžžö‡ÿ&¤^¨ÛVfãÆùÌáŸÉ'^çæóù|^Ó´ü‡>ô!Î=ÉŠ±ºmd"T¦¦¦ÐÝÝÁÁA@__úúú055Uu¿ÛžùR×˲ðÆ7¾£££xî¹çÚ.ßøø8fffZÝŒ¦066Öê&°Mf)òyß}÷á€u_ƒrœƒ×½îu8þøã¡ëº_t¬è”gï™Îd©ò©ë^m†ùùy8ŽƒÙÙY?ü½]˜™™Y”Gq”é”gº“îI£,U·}æ™gpÅWàÓŸþ4.¸à¨ªÚ–)ƒ8æDNº'²Tù¼ûL&q饗â׿þuqm†6‚Ïtôè”{Ò –*ŸÉdGqÇA2™ôÓ9©ªŠL&MÓ099 UU111UU‘J¥Š"$¡UëI¤GuÊ3ÝI÷¤Q–*›?ó ²»OÇy£ûbãÆÀþð‡ÈÌ=£>–´Ã3Ø)ò¾"SCefffAî½îînär¹ªû=úè=8ë¬CpØa‡áðÃÇ]wÝ…c=_ùÊWZÝ¥Eqë­·âç?ÿ9Ö­[×ê¦4Ì7ÞØê&¬X?n½õV<øàƒ8þøã[ÝÜee)òyûí·crr_ûÚ×ðÖ·¾Ï>û,n¾ùfÜ|óÍ­î΢é”gz5½g{ì1ÜqÇعsg«›ºì,E>wíÚ…Ã?ûî»/Þò–·ààƒnK%hçÎØ¹sgM]¡è”÷L=÷dçθóÎ;ñ’—¼¤ÕÍ]V–ªÛÞsÏ=Øwß}qýõ×ãØcmKÙVטÓ.ÔsO¨ÛV–Ï?þñ¾ûôÓOãøão[ù\MÏt»P¯n{ß}÷µº©ËÎRäóø~ò“Ÿà˜cŽÁ…^øõ¯]ô» n=¨Û,U·ýßéƒpà>ÀÿêÅØo¿ýð†7¼gœqFdÆÐ¨%íð^ˆ²¼ßyç¸ë®»š®ÛFÆ 277·à³zŠýÍßü ~õ«_ᢋ.¡‡Úên,±ðvÒ—zúqØa‡aÏž=m µ–"ŸoûÛñÜsÏaß}÷ÅùçŸßê.4Äjz¦Û…Z}yòÉ'ÑÓÓƒ½{÷¶º©ËÎRäóÒK/ÅC=„—¼ä%xéK_Úê.t–|Öâü#z{{Ñßßßê¦,+KÕm‡‡‡ÑÝÝSN9¥Õ]hˆNz¦;¥/Ôm–"Ÿš¦Á0 ¬[·Çw\«»Ð«é™nêÕmË=»ÆRäóâ‹/ÆsÏ=‡#<Gyd«»@ÐYòY ê¶Õ9Ó8 ?ÿùgqÅ«®À«_ýêVwc«éY].¢| ×­[‡“N:©éºmd *ÝÝÝ >Ëårèë뫺ß>ðV7¬b¢üÒh&K‘ÏSN9Ÿüä'[ÝtB:ž¥Èç%—\ÒêfÒñP·%íuÛÊòyì±Çbtt´ÕM'¤ã¡nKH4¡nKÚ‘åÒm#SC¥¯¯oAøÒÜÜ\]ÖNBÈòBù$$ºP> ‰&”MB¢ å“èBù$$šP6 ˆŒAeppsss~1£™™är¹¶ODH'@ù$$ºP> ‰&”MB¢ å“èBù$$šP6 ˆLÊ/ÅæÍ›Ñßß;v`tt]]]­n!”OB¢ å“hBÙ$$ºP> ‰.”OB¢ e“}òù|¾Õ“ËåËåÐÓÓð1B"å“èBù$$šP6 ‰.”OB¢ å“hBÙ$$‚B!„B!„B!„¨™*„B!„B!„B!Q…B!„B!„B!„РB!„B!„B!„RT!„B!„B!„Bj°ïW\qE«±Tr¹fffÝÝÝ­nNÕ6ær9ÿ§»»p@Ýýhu?çççñÈ#,ºmQìW¹¾4zZ}¢H»\“N¸÷•ä³Qù[é¾ÕêG¥{µ~´írMÚýÞ/uì¬õ}§Œ­ê iœ™™¬Y³¦i÷z¥Ÿ9ßüü<^ô¢5µ­+Ñ—zÆËžžžE·-J÷ˆ,r² ´×½¯&ŸQ×më÷—"Ÿ­îiK‘Ï(ÝûFÆÎFûÙ –*ŸQï©ÍrêGͦÙ:v³˜ŸŸ‡mÛË¢;·5ù6åÚk¯Í ä7nܘÈ_{íµ­nRYÞ÷¾÷åO8á„¢ŸíÛ·×Ý(ô󪫮Ê_uÕU >¯Ö¶¨ö«\_¹GQ¸?Q£®I'ÜûrÏt£ò׊¾UzÏT»GQìGÔi§kÒî÷~)cg­ï;eìle_HcÜÿýù¦Ýë•~®ºê*ÿ|çœsNþ²Ë.kZ[Wª/åä±´_oyË[òsssmyÈÒ('›ù|{ÝûjòÙºm¥q¿ùŒB¿Hã,E>£tï;íg3û°Xùl‡~‘ê,§~Ôlš­c7‹;v,›îÜî´­A%ü íر# 'äï¿ÿþV7k7n\0p.¦­ìçµ×^ë/˜”|ªµ-jýªÖ—FîQ»<‡+I;]“v¾÷ÕžéFåo%ûVë=SíE©íB;]“v½÷Œµ¾ï”±³}!ÍA&Dá{ß.Ïôý÷ß_tü¹¹¹ü 'œß±cGSÚºÜ}©$Ò¯p?Î9眼išmwÈÒ)'›ù|ûÜûZòeݶÚXÙ¨|¶ú½CšÃRä3*÷¾Ñ±³Ñ~6J#òå~‘Ú,·~Ôlš­c7‹ð5›››ËŸsÎ9ù›nº©®6tº´e •©©)twwcppÐ×ׇ¾¾>LMMµºieÛZ.¬¬ž~´ºŸýýýA__ߢÚÅ~ÕêËRîQ«ïOi·kÒÎ÷¾Ò3ݨü­tߪÉfµ{µ~´ívMÚõÞ/uì¬õ}§ŒQ¸GdiŒ¡¯¯ýýýþgíôLÏÏÏÒ tuu¡§§sss ·u%úRIs¹‹>?ï¼óêêWÔîYådh¯{_M>£®ÛV+‘ÏV÷‹4‡¥Èg”î}#cg£ýlK•Ϩ÷‹Ôf9õ£fÓl»YLMMann›6màÉ¿eY8ï¼ój¶a5ÈÁ [Ý€¥033³`ßÝÝ\.×ê¦!ƒÏå—_Ž©©)tuuatt###uõ£Õý”O¹·mÛæO~Ûé‘ÅSI6å»v¹÷ÕäsëÖ­‘Öm«ûÈgÞ;¤1–*ŸQº÷Œö³Yí—ã–RM>£Þ/R›åÔšÉrèØÍ"—Ë¡¿¿ãããØ¶mººº022Òݹh˱(†©ä%ÙJÄ"ºiÓ&Üu×]زe ÆÆÆ|‹\­~D¹ŸÕÚÖNýjäE©Q¡®I§ÞûFå/J}«vÚ©Q¡®I§ÞûFÚ¥~u²~C2??Í›7cË–-èêê*ú®Ýžé®®.¿0ié$°tÛmÛ¶aÆ ô œívHýT“M ýî}%ùìÝv±òÙ.ý"åiD>£vï—:v6ÚÏ•¤T>;¥_Ä£ÙúQ³X.»Yär9?ÚdÓ¦MèééÁ%—\âEV»´¥A¥œu9ŠV®¾¾>\}õÕ¾õnpp矾¿àP«Qîgµ¶µS¿¹GQêGTh§kÒ©÷¾Qù‹RߪݣvêGTh§kÒ©÷¾‘¶G©_¬ß…˜¦‰¾¾>?ÆÜÜfff033ÓVÏ´x×]wÝu…eYرc¶nÝÚp[[ýLÏÏÏã’K.ÁØØ®¼òJ\yå•u·-J÷ˆ,Žj² ´×½¯&Ÿí®Û.U>£Þ/RFä3J÷¾‘±³Ñ~®•ä³ÝûE<–K?jË¥c7“žžlÙ²ƒƒƒ~F‚ñññšmX rЖ•¾¾¾7bnn.rÖ.±à‡ [kõ#Êý¬Ö¶vêW#÷(Jýˆ ítM:õÞ7*Qê[µ{ÔNýˆ ítM:õÞ7Òö(õ«“õRžùùylݺ[·nE.—ÃM7Ý„›nº©­žé\.‡žžž¢guppÐ÷ kgÝvãÆèééeYEé-êi[”îY<•dh¯{_M>Û]·]ª|F½_¤6K•Ï(ÝûFÆÎFû¹T’ÏvïñX.ý¨™,‡ŽÝ,DÎtšYÓXÂ÷ËÂÀÀ@~ûöíù|>Ÿß±cG~`` ?77×êfqíµ×æÏ9ç¿]sssùsÎ9'íµ×ÖÝ(ôsãÆù«®ºjÁçÕÚÕ~•ö¥Ñ{…û5Úåštʽ/'ŸÊ_+úV®µîQûuÚåšt½_ÊØYëûN;[ÙÒ87nôï]>ß>ÏôM7ÝTö¹5M³)m]©¾T’ÇíÛ·ýÜÿýmwHc”Êf>ß>÷¾–|¶ƒn[M—]ª|F¡_¤9,V>£rï;íg3¯ÿbå³úE*³ÜúÑrÐL»ÌÍÍåò;vìðÿoÇ5³å¢-‹ÒÀèè(6oÞŒþþ~ìØ±£££esS¶)ž»aÃôôô`ÇŽñsöÕÓ(÷³ZÛÚ¥_Þ£¨ô#J´Ë5éä{ߨüE¥oµîQ»ô#J´Ë5éä{ßHÛ£Ò¯N×oÈâh—gú¼óÎÃÔÔÎ9çô÷÷#—Ë¡¯¯Ï/NÚh[[õLçr9är9\rÉ%EŸoÚ´ £££muHói—{_K>ÛU·mT>£Ú/ÒÚáÞ7:v6ÚÏ外|¶k¿ˆÇrëG+A«Û×ÕÕ…ÑÑQ¿þŒÔÑì„5³f°O>ŸÏ·ºKE¤§§'ÒaC333~hS¹vÖêG”ûY­míÔ¯FîQ”úÚéštê½oTþ¢Ô·j÷¨úÚéštê½o¤íQêW'ë7dq´Ó3-çëîîF___SÛågºîi.ítï«Ég'é¶‹i[;÷‹Ô¦]î}#cg£ýl%Ú/%9‹jû–SwngÚÚ B!„B!„B!„²´eQzB!„B!„B!„•„B!„B!„B!„РB!„B!„B!„RT!„B!„B!„Bj@ƒ !„B!„B!„BH hP!„B!„B!„B© *„B!„B!„B!5 A…B!„B!„B!¤4¨B!„B!„B!„Ô€B!„B!„B!„РB!„B!„B!„RT!„B!„B!„Bj@ƒ !„B!„B!„BH hP!„B!„B!„B© *„B!„B!„B!5 A…B!„B!„B!¤4¨B!„B!„B!„Ô€B!„B!„B!„РB!„B!„B!„RT!„B!„B!„Bj@ƒ !„B!„B!„BH hP!„B!„B!„B© *„B!„B!„B!5 A…B!„B!„B!¤4¨B!„B!„B!„Ô€B!„B!„B!„РB!„B!„B!„RT!„B!„B!„Bj@ƒ !„B!„B!„BH hP!„B!„B!„B© *„B!„B!„B!5 A…B!„B!„B!¤4¨B!„B!„B!„Ô€B!„B!„B!„РB!„B!„B!„RƒUkP1M–eµº«×uaYlÛnÊñÇiš­îi”ÏöÅqœrMÙlo(E½òèº.Ç)»¿eYe¿#­…²Ú¾42vV’Õðq)¯­‡òÙZZ5ïäXÚ~PV[ÏRåµÜX*Ÿs.ÚÞP.;NËUkPÉf³m+CCCMS[…mÛèííE:Æðð0âñxÃÇtÙl¶Õ]#M€òÙž$“I ,kÊf{Cyì,ê•Çt:½@É5MÓ—ñ¶W‚; Êj{ÒèØYNVÊkÔ |¶ŽVÎ;9–¶”ÕÖ²Ty­4–œ‹v”ËΣärÕTÚ˲àºn«›ÑÃÃÃH$˜œœÄôô4,Ëj{a"è ù\ Žã NczzÚ—kÓ4©<–²Zå±LÓÄðð0Òéô‚ï’É$&&&099‰ÉÉIÄãqz×’¦°Zeµ‘±³š¬”WÒ<Ú]>[1ïäXJZA»Ë*°4yå<”D™NKRžUcPÉf³èííÅ>ûìƒx<¾àKøÚµk‘L&‘L&‹^À¶mcxxûì³ü—úÐÐLÓÄÚµk±víZ˜¦‰d2‰µk×¢···ÈŠº˜m+‘L&ýß¶mûÇ ·½^Âí±,«æÿ‹9^µþÉ %‘HEÁìì,b±Ø‚c…ûeÛ¶oä˜ÕŸß½{w^Q”üÄÄD~÷îÝyÃ0òò“““EßËþ“““yEQüãÊqR©Ô‚óèºî·c1ÛV#Ü6yÃ0ò»wïÎOOOçEñ¿«ç8º®ç'''ó»wï®ù=Ç«§™L&¯ëºÿ;‹-hs¹~¥Óé¢Ïå>Ⱦ“““þ9 ÃÈkšæoWm?ÒZ‘Ïj²™Ï/Næ¢$Ÿådo¥ä³–¼Të“aùX,–Ïd2ùX,VtÌr²YÏùÈÊRM+óùúŸÁfÉ¢«ÙòX|ÖsÌå”ÇjûU“Ç0º®ûm”v–^ûÒmÈÊÁ±³ü1VËØ¦œR^[Ër¥­M9V»Ž¥Kwr,]p,-ŒV¥µäu)c©Ü®µ¼~+ÿ/Ç8Ú*·RŸVÃúíª0¨$‰¼aEŸ©ªZôð„…AF¹a™L&¯iZÑþ†aø‚-Èÿ_*õn[Ò2,,"@õGüzþ¯çxõôO®› òé¹Kû•N§óŠ¢T¼·rÃ0òŠ¢-ØVÛ´–F䳚læó‹“¹(Ég9Ù[)ù¬%/Õú”H$ü{§ªjMÙ¬ç|de©&Œ•ù|ýÏ`³dQŽÕly¬G>ë9f=}\ª²<Ô’GŽ•+ÏRå£Ú~Õ䱚¦•=ær)î¤:;£ÇJÕ ¼¶Ž¥Ñ¡‘y'À±´ÓáX-–*¯µÆR€ëDí×o£ÇrÌGö—ËUaPQU¦iú7Á¶í"KX,ó `XPÀ'‹Á¶mßbæº.z{{‹ŠŽ‘úE2|=³Ùl]Фã8þý‘ý¤¨ ¸‰Dªªú^ µö#­£ù¤l.K‘‘k¹O²_¸8 °P6—z>²Ø½{÷‚<™Žã@Q”– ‚´£´íÆb¯§eYH§Ó˜œœ„eY˾YY‘ϨÈf¸-í*ŸÊËJÉ5Y^ÊÉc»•ᶬ6y\N¹’kªª*S”DŽÑ`¥ÇÎÅ—òÚ8–F‡¥\OŽ¥«Ž¥Ñb©×”óÐ΂ë·Ñ`¥ç£í$—«"BE¨t\×ÅÐÐ&&& i’ÉdÙü+¡ð8ŽSµ`’®ëÐu½j;ê=Ær´k14r=—îÅ01âш|FM6WR>—C6Ãû.–VÈ5i>åä±]ÇÊÕ,ìW .þD ŽÅÇiv»–ÂJ­8.©Õ0–®†y§œ³™P6£EÔÇR šëDË5–.õšrÚYpý¶øËÑ®ÅÒîóØf³ª *•PU™LÆÏצª*&&&ZÒ) T­­+qŒ•8æRÚ°Ëd”-š¤6Q‘ÏfÉ@³ei9Ž·’òBùl¢"‹åq¹ö#CT䕲JH1Q‘M€óÎzÚA¹^ÝP^Wöx+ e¼=¡\®L»ÂÇZÉùh;ÉåªJùE!„B!„B!„²^ÐêB!„B!„B!„DT!„B!„B!„Bj@ƒ !„B!„B!„BH hP!„B!„B!„B©Á¾W\qÅ+}Òùùyضùùy¼èE/*ú.—ËaffÐÝÝÝêëCȪ¢šl”OBZ å“èBÝ–h±“èBù$$ºP·%¤:+nP™™™Á† ðÀ`||÷ÜsÎ>ûlÀøø86oÞŒxŸÿüçÑÝÝþþþV_#BVÕd |ÒJ(Ÿ„Dê¶„DŽ„DÊ'!Ñ…º-!µÙ'ŸÏçWò„º®cdd›6mÂüü<6lØ€ÑÑQœwÞy8ýôÓ±eË úlYzzz*ïmo{Z}æ±ÇÀý÷ß¿ÕMi˜]»váˆ#Žhu3V¬;wîÄÛßþvœqÆ­nrCT“M‹–Ïk¯½?úÑð²—½¬Õ]k˜Ny¦Wã{æÎ;ïÄ—¿üåV7·aš-Ÿ›6m‰'žØên5Ì3Ï<ƒ½{÷âÐCmuS¦SÞ3õÞ“Ç{ ===x×»ÞÕê&7L³uÛw½ë]8餓ZÝ­†YcNÔ©÷žP·-/Ÿ·Þz+þó?ÿëÖ­ku×fµ=ÓíuÛÆäóƒü Ž:ê¨Vw«a¨ÛF궯ÛF},i‡÷BÔå}9tÛ®d¦¦¦077‡M›6ººº`Y–ÿ]ww7}}}èëëÃÔÔFFF*ó÷¿ÿ=Þ÷¾÷­d7–…l6‹¾¾>œrÊ)­nJÃŒáMozS«›±býÈf³˜ŸŸous¢šlÊ÷‹•Ïx÷ß?ÞùÎw¶º{ Ó)Ïôj|Ïlß¾½ÕMm˜åÏÛn» —\rI«»Ö0·ß~;fffpî¹ç¶º) Ó)ï™zïÉí·ßŽ\.×êæ6Ìrè¶>ú¨¿O;³Çœ¨Sï=¡n[^>åšt‚|®¶gº nÛ˜|Þ{ï½xË[ÞÒê®5 uÛèAݶóuÛ¨%íð^ˆº¼/‡n»¢•\.‡þþ~ŒcÛ¶mèêêÂÈȈoÙ,µhvww×|!í·ß~˜ššÂèèèJveÙ®M___«›Ò0ƒƒƒ‘~Y6³cccعs':è V7·!ªÉ&€%Éçºuë°wï^är¹ªƒk;Ð)ÏôjzÏär9Œ·º™Ma9äsÍš5˜ššjûg»»»‡zh[÷Ah÷{!ÔsO¦¦¦033ƒ®®®V7·a–C·Ý»w/uÛˆÑ)òYÏ=¡n[Y>:è ìܹ“ºm„XMïÑm÷îÝÛê¦6ÌrÈçŸþô'ê¶£Ýï…@ݶyºíÈÈHÕH–V÷9ªcI;¼¢,ïãããË¢Û®¸Aejj ]]]Ø´i¦¦¦pÉ%—À²,ÌÍÍ-ؾA{ÉK^Ù›¶Ú])Óî ‹éÇàà vîÜÙê¦6L5ÙìééY’|wÜqxùË_Þù4;å™^Mïñœ±m»ÕMm˜åO;£¨Ð.ñŠê:å=SÏ=éééA__yä‘V7·a–C·=øàƒ©ÛFŒN‘Ïzî uÛê¬[·Žºm„XMïÑmñ‹_´º© ³ò¹fÍê¶£SÞ3Ôm›§ÛFµ€}ÔÇ’vx/DYÞûûûñóŸÿ¼éÇ]Qƒ à Û–-[x ûüü<ÆÇÇË V.—«ùÐrÈ!1é$íÉàà ¦¦¦ZÝŒ¦PI6GGG—,ŸëÖ­‹ü‹Ÿt&]]]ÄÖ­[[Ý”¦Ðlù”I'!­ §§§œr öìÙÓê¦4­?ÔmI§@Ý–º-‰&Ôm©Û’èBÝ–º-‰.}}}ËRÿî+Ù‰ÁÁÁ!pò__ß‚0±¹¹¹¶÷0 ¤¨&›å“VBù$$ºP·%$špì$$ºP> ‰.Ôm ©5¨ô÷÷#—Ëaff€WØoÛ¶mèééÁàà æææ|¨™™är9œþù­¾F„t<Õdå“Bù$$ºP·%$špì$$ºP> ‰.Ôm ©MùÕÕÕ…ÑÑQlذƒƒƒÈårôóÕŽŽbóæÍèïïÇŽ;0::ÚE‰:µd |Ò*(Ÿ„Dê¶„DŽ„DÊ'!Ñ…º-!õ±â5TFFF|¡ìîî.ʵþ®§§‡ac„¬ Õd³ô{Ê'!+ å“èBÝ–h±“èBù$$ºP·%¤6+nPPUè(„´ŽZòGù$¤uP> ‰.Ôm ‰&; ‰.”OB¢ u[Bª³¢5T!„B!„B!„BÚT!„B!„B!„Bj@ƒ !„B!„B!„BH hP!„B!„B!„B© *„B!„B!„B!5 A…B!„B!„B!¤4¨B!„B!„B!„Ô€B!„B!„B!„РB!„B!„B!„RT!„B!„B!„Bj@ƒ !„B!„B!„BH ^¸Ò'ÌårÈårEŸõ÷÷£«««èûžžôôô´úú²j¨%›ám(Ÿ„¬,”OB¢ u[B¢ ÇNB¢ å“èBÝ–Ú¬¸Aell Û¶m+úìꫯÆàà ÆÇÇ166†þþ~ìØ±£££iõ5"dUPM6P> i!”OB¢ u[B¢ ÇNB¢ å“èBÝ–Ú¬¸Ae~~¾h  366†-[¶`pp333ذaiñ$d¨&›å“VBù$$ºP·%$špì$$ºP> ‰.Ôm ©ÍŠ×P™šš*+hSSSèîîö¶¯¯}}}˜ššjõ5"dUPI6å;Ê'!­ƒòIHt¡nKH4áØIHt¡|]¨ÛR›5¨ÌÏÏ.¿ürœxâ‰8ýôÓ1>>˜™™Y °ÝÝÝ òö•òðÃclll%»AˆÏØØn½õÖV7£aªÉ&°tù¼õÖ[‹ŽCÈJ‘Ëå066†={ö´º) ³ò¹gÏŒQù%-ajj Ùl=öX«›Ò0ÔmI§AÝ–º-‰&¢Û>üðínJÃP·%uÛútÛZÛ²Œ/‹n»dƒÊüü<¦¦¦033S÷>¹\ƒƒƒØ´iîºë.lÙ²Åôæææl_OÈØÁ\1L”åfppëÖ­ku3¦šlX²|®[·ýýý­îY…ˆçÌš5kZÝ”†Yù\³f C³IËèééA__8à€V7¥a¨Û’Nƒºmu¨Û’V!ºíÁÜê¦4 u[ÒiP·­Žè¶ÝÝÝ­îY…ô÷÷/‹n»$ƒÊØØN?ýt\rÉ%¾`éº^Ó¸Ò××W”‡opp矾6VJ=ÖËC9„“NÒ2:eÒYM6,Y>×­[‡¾¾¾Vw¬Bººº:Æ ²òÉI'i%===8å”S°ÿþû·º) CÝ–tÔm«CÝ–´ Ñm9äV7¥a¨Û’NƒºmuD·íêêju÷ZB6ëýÖÐ×× ƒÊ¶mÛ0>>Ž«¯¾W_}5OÀFFF°qãF?<¬¹\nÑEª¯¯o ÎÍÍq@$d¨&›å“VBù$$ºP·%$špì$$ºP> ‰.ÔmëÇud2øhpïǶxH§Ëò¾ö¾3ÍÚÇvïø$º,Ú 255…‘‘‘žs›6mBOOvìØQußÍ›7ûF—ùùylÛ¶ ===ÄÜÜœï•033ƒ\.‡óÏ?¿Õ×ˆŽ§šl |ÒB(Ÿ„Dê¶„DŽ„DÊ'!Ñ…ºmmÄhâ8^ä‰LlÛ3ª y†”XÌû^=°·{ß›Ÿò -µŒ%¦émO¢Ë Wòd###˜™™Á† |ãËÈÈFFF£££Ø¼y3úûû±cÇŒŽŽ®Ú0BV’Z² P> i”OB¢ u[B¢ ÇNB¢ å“èBݶ6ŽãE À0¼¿S)Àx`|ÚÛÆÍšæ}oȼÀÀž´}CLæn@ùUáÀµðó4€Ç ŸÛ²R­î9 ³hƒÊàà .»ì²Èññqär¹šEú®¼òJÌÌÌøaaáÐ0‰|Éår ¾#„,/Õd |ÒJ(Ÿ„Dê¶„DŽ„DÊ'!Ñ…ºmuLÓ‹>I§Ìž1Ųãz@ý4<ƒH!jÅHÎm@×ìWÔs€vz¡¶Êïí;€{ ›t€_Ö€þæÂIó° $$(­¾*«ETÎ;ï<ìØ±Ã·VÎÍÍA×uÌÍÍÕm™¬VÈoµ $!Q V‘MÊ'!­ƒòIHt¡nKH4áØIHt¡|]¨Û8ßð@=«ð¿ãEž¤Ó€ú)@ýgPqÏ"ÆŽ,€ žÀpŸb:€GÔ{ôÏÜà¡87Š Ä ýs ñªÐq4i <#J žÅñŽ ½ÕWiõ±¤”_£££ÁÔÔ”•288¸ê¼!„B!„B!„t6|#Für@;HýÈû_× ?gê­\/½—ú xÀ‹²T@Um<ã‡h  ÄîœWé<Ùàl”ýûùÐ14x‘)bX±àUäo@ºð½^8§ ¦ [FmP÷‹…s\B!„B!„B!mKHöÆûçaÀÙ˜kÙÙ`“ÉmâlÀˆ‚¦’*|.BzEb/A`I™« Û¾ Ð×Ù1@ù`¬ìßöwàIL“Þ~° ÇwBmvBÛªð ,ò¹¤Ó@šÄ »C.—ÃØØX«ÛM!„B!„B!„4F/Lz©¼ÀºÑ«—¢èç® ض÷€gÔ"òÑ¢Â3`¨ðRrÙ…mUï—!‰\x À v±×Úi@úk€¾HZØÎEF,]øß.œG)|çÎo…Úæ„¶ ‡P»JqB¿“ul/í[…,:BÅ0 ÌÏÏcll ƒƒƒ ¾/÷!„B!„B!„Òr †‰´í¥ðJ>¸ÉHÆ@Ñõ;€6 Àð É+öw Lj#( ? JEjœR~ùçÔ ŸK½04œÛiÚ¾Àڀ݅c¢°Ÿ]8—J2Þþ¾Ä[ó¶rç“øýÍ¿ÇiŸ8-è{^´‹ü*ìŽd± m°»pÎ0éBßÄà#ƤUÀ¢ *¦ib||°uëÖßßu×]­î!„B!„B!„²ç'€û û ÌÚ •â@ædO±0?65'¬Aâ‚ý‘þ< ï. ÏÈ1>háž!Ä,|.Ñ!’rKGqTI!¢DM¸À—]hëý é€eªàÀ¾0 o¿KÞõ3\ýÃW{† ž1$ ¸§ÎY€ÖÌß0ûޏ§%OóŒ(É’ !mãIATŒDÙ”I$"ÇEÕbÃ3¼Ì¢8jg©Hm¹®3Ô,:å×èè(îºë.Üu×]¸îºëpõÕWãºë®ó?#„B!„B!„B¢ˆy#0pkáï,`¼xú{Oã¹çžÃíg>ˆËôUÀ'»>‰Ÿ¿üç°w¦hï.<õBìùÇ=xü·{F Þâ¿dñ?‹À¨žZóLÓô¾O"¨…’ 5,àÒÐŽÞ‰¡€ôa^*²÷k;ÞúÈó¸âëO!ýÏÀO·<…¯Î¿ïÞºæñÀ°ëõ£÷Ó@úç@vÜ;Ç>ØÿæÇƒã &Žã©Á$•˜D¸ˆ# Ú%jã‚}íÐqÂv<ãJ¼Ü…G±&œŠL¢dP²oºäüiTNC¶B,Ú x…éO?ýtlذ—\r 6lØ]×133ÓÚÞB!„B!„B!a²ðî,8 Hü=à>¨ƒÀ×?€?û³ÇÓß~ù§¿„išxïOÞ‹›çoÆSÉÿ…¡ûã ¼cÇ;pçw⢋.®îòø%V&t¾BÚ-I‰õÔ–§`Ûž%à჆­ØÞ6 ;?˲¼ã챡_pÞö¶yüøáczÐδàþ xp÷ûñ³‡žÁýü…8§w?~ >9ö†žÝƒù—ç±wß½0'å¥@røÉOâïú ’ÓÀTMüÇŽgñ·ûk¯m…TbÙ“€¬OÄÀ#‘4)ÀõË-l#éË€ õ—]ø~å#‡þ—4cÝ2€ ½Y6´b#T Ö<µ¦éÒ¢ *SSSÃèè(~ùË_â®»î‚eYÄÆ›Þ@B!„B!„B!d©Üûí{qÅ¿>…¡!ÀX¤öbÇÛ.»×ÿøzøàøÝOO¿Î‰cŽ]ƒß]ÿ;ܱ÷|÷§ßÅÙ»ŸƒàG¿ùT¨è¾§'œpþí¦ÃS_ ç÷N" H}UHýõüŸ‡¦ip]ÿýwÿ Çqàº.0\¸ñB¤Ói˜® îB¿èœzêxÝû^‡t:‰SN9ÿ}Øï09ÃeßüNzÍ0?:€Æ»{~…çŸx==waïÓWây<øðNÖA <ðiŒ?ñ<>ÿª‡0ñÔ+ñ¡žÇ _x?†> ì샀ô¿zm~p»€ôOó!iÀþ`àq ûÕB¿ôPcð¢J´Â^ø_¢v€âh1¸Èu2àUä»Lá÷‹]/Z§ÉãNæy…í&gOpHËùÕ—Fpû7_ÜÔgiÑ•mÛ¶add###èêêôôôàÊ+¯Dww7¦¦¦šÚ@B!„B!„B!dQ$áGQ$nÎ#wÏãÐ4`øzxÆ øÌg>ƒ‡~ü0º¸w=^•Ø3ÿ;ƒ£Ž: ¶mã®gï‚æ?9à'xüUãä'CÕUœùÑ3ñÜsÏáíûöÂIàG¤\xÍ…¸ãµwà–[nÁÞu{ñ¾ò`YLÓÄöùlÛF6›…åZøÖ¾…ÉÉI˜¦‰ûî»¶mc~þ×H¥Ã0‹Åðÿíþ3躎l6‹CÿbÔ7ÉdÉïà¶ÿŸ½s£ªûÿ»-¥-—¤¶”N´L ¢³Ò"¢gƒ„ªÝU°¢Ñ]õ}úxÙÕø âm§hQð§ÙÁª(PØAE$xÉp‘F@Ȇ EÈ´¡¥7 ¿?ΞÙK.MÒ$»IÏûõÊ+ÉììîÌìž9ßóý|/=á›çÿšß}ÿóœ3w7gž¹æ¤9ìâî¹çí\÷Õx~k-ïÿðñ¼súŸX¿þýøÿÌ `ûpÚœøÎwþ„ÿXë_Áû;ïI"Ñÿ…T+?çm?!øÏ]BqÅù¦WŠ"éÙàoƒõë×cïï{€ É‹ òFðp¯§™0û%y E¢[Á¹Ü8D¾ûw‚¦M¸µy\”=‹ßÉC$ ± ÿo[ÄùñË„ýuÚËÌhêÓ¯Õˆ•Í›7ú˜X …B¡P( …B¡P( …B¡¨x?€h~·yŸØï Hœ°ëO»hYÝ«־ŠãçÍçM‡üã8øÂì/°}ûv,X€‡–°z¾öy\\" ˜ “é‡L矛þ)ÞÎ÷ð}ŸË¯¿œÛkngá3 ÙõÎ]är9R©©TŠT*E,öm‘©d³Y<Ã`Æç?OʲÐuMÓÂSJ¥R\ô¹‹@ƒÎÎNð]GÔ|ï{,ŠÀ/Ÿ‰a¤R)Ž8b1?^ËáWÏá‹Ís¸ôÒùʱ'3gÎÓXûaÀeozˆwÕþ™ÿþï-|æ£Ýl™¶…Ï~ö t=àÜæ>Ž;ùrÌ8@¦ãµÄ·Î#ý'ð‚çÃ×wmÆ{N\cïïpÛì]œzÑ!<ú]DWî }ðãœÔøÛwÜCôpéiüÄãðýÛ^¦eé&½¸ƒ[z¯%l<ðp®{ß•|èÆ—`?Èd óS¯9¼—Dþ´à<¼îaN8p›º6á¦=h0àzQ Ì~¼¯¿óøÊŒ—yík·Œé×jÄ‚Jss3ëÖ­ë×/¥½½žž-Z4®ã@¡P( …B¡P( …B¡P(Š~”•ògÀcíæ ³·R·©Žxçy$“Iâñ8¶mcÛ6Kù ^þ5O_ò4º®A‰8BD1 ѽ^×u;ç¾ñ¯ …¢äD|hjê¾®‹‹qôô¼›¿èåMÞõ®—XxæBQ’ ¨9§†×¾öoX¯Ïó¸÷ˆ{™õ|ÇᾫùTò`¾ÿý¯’L&¹}Ç›Y¼ø@âñ(Æk þÀ™8Ǹ… nÞÎêÕ_cÑ!·pùŽ­ìܹÃH³fÓ¸ùæ.jŽù Oÿ‰Óîçì£v±üÙgizÕ\òú‡ùõ%Ûyì¯`ÛpÎ!ÏñüçrÁü‡™?Ñ3¾Æ9oþ)ßÿó§8÷Ø_qêY¿½gÞã³ùõŸÃ4^9¶—·w \À¶Ý³ùë³õ4ܞž~=É‹À˜ÑÙ;ˆœ¿›ÄósÆü+¶ßHŸÐÒÒBWWË–-£±±‘ÚÚZzzzؼy3­­­#ÊRéêꢾ¾¾ä9===ôôôP__O}}ý˜Ÿ°B¡Ø3MPãS¡¨ÔøT(ªeÛ*Õ‰š;ŠêEO…¢z™ ¶­ç‰,‹bz^ê‚:ñø%Ð~åË<³ýFNå’úÇq'ìññë¿æŒŸ!ž¨ÁÙÏž>Ì‹/Nã3w|†ÃÞ{ëç¯çãÛ?NÏ=xþ¼ƒw´“"Ãäv›ùóçsçw’J¥ð}MÓ0M“—Ž8’-›¾Ä¼Æ`F(ž †¦i|â†À¶ÅO,_C̶~‚ëB.Ž#ê_%áCº×_? ÜY…ýMøÀŒ9Ìÿànt]4McÑ‹Ð:Ä1›&˜È¤ !9ŽÃ?[ïä·Ï5q§öQNZQC]úm¤Ó¯_ÛÌ_ðÿw%¶m“H$H&“d³Y¶ÿð=Ü·+ÎîoyXO§yné2޾õ,ž[ñÇpðÁÏ ï¯'Y'q’y ´£9?Ãÿx_ä ¯zMMi ÃàgÏ?Oßý÷3[ËðáO˜çwÁ£÷÷±ÅHò±}–ÏÜw&Ü©º«‰úWÀÌ£Ù>³ šÒ¬ZµŠµkײtéRY±bwÞy'---Ã~žž.½ôRÖ¯_nkoogÙ²e¬^½šeË–ÑÞÞ>æ'¬P(†f ± j|*Õ€Ÿ Eõ¢l[…¢:Qs§BQ½¨ñ©PT/“Ŷ-OâxrÓ Ü_ ýÁ¹š_x‘w¼c#Æá—ϺœÏœòžøù\wÝu̼k&š®ª›}‡x]õ»øé‡~ŠišLb:×.¾–7rË-·ð“U?AÓ4‚ À²,^÷º×‘Íf±m›ï|ç;ÜtÓMàûìwü±¼À±üeÙ÷†}N±XLˆ.‰„è âûâÇq„pRL¾Tš&êb•e¿„äÏ ùí!¸ïHcY±¼`“J¥0M3ÿrš¦…Y8–eqÇ3³xý¢éÜþšnjh ‘Hphß“\öê÷£ë:©T ˲Èår$“I^ªù·Ÿt;Ç¿ÜÌŒ£åõÏãîNb{i4MãúëçsU|–(§¦#ú ø>º©ëç3롇QÚ,šÏÎy饗ØZw½8ý8}öa˜¦É¡ÓúèÜÖ\ÐÞFf¾MâÀ¿b,tyôÑGÇô{7â Icc#£~ã«®ºªß¶¶¶6®¹æš››Ã,˜æææªP<Š}…Æ&¨ñ©PTj|*Õ‹²mŠêDÍ Eõ¢Æ§BQ½LÛVf§AAGð<& ²›„þ˜»çÝÉï>³0OåùÛžçûuß'{{–Ïû9æÿh>\…(•åÀѯ¡ùïæåc^fß7üu’¹ çÂ965kžã–[naý‘ë±,‹x<ަiü×ýþóŸÙ¸q#wÝuï}ï{…b¼ô§:Nÿßß—dŽâñ¼`’LB¾Ï º…“K¥ú &APx]]/d³ÈÇâqÈfû]»³Ï>›æÇ>ÎLý[ûخË4m!<÷`nýãAXùþ.xõïzõ¦)Ô­ü{E£Q²Ù,ZSÛfoã_þ‹Ã£ßà°›ÎãÍuð¯Yç‰Ògò|] ð çQ†¦i|æ«_åž3Îà;wÞIjNlðfƒ·r±?¹õ'œº`©Cæð«ÝÀ%›^à»ú/ùçÎ|ðÁcúÝU†JGGGÉÀjoo§­­¾¾¾a=¿­­ÆÆÆ’~+ÔÖÖÒÜÜ ›ŽŽŽ1=a…B18MPãS¡¨ÔøT(ªeÛ*Õ‰š;ŠêEO…¢z™,¶­ë }Áó Û‚ `.¯`ÿŸðÓ'÷‡Ÿlü ¦n Á$ÿ:í_®íØ|øgÙ)Ò‡oÀœísp]—ûßz?õ?©'•JQWW¿s¸jÃN9å ó;‰'žx"<òï{ßûÈf³¸®ËÝ?ú©-ݼ<½V(ÅÄã¥Û‚ ôd@ˆ š&~¤ˆQþø@Û¡¾Sþ¾̬Ù{²^Ê.¶Q¿ÿ8µïÔB™5“Í–F©TŠ ßüfèî&‘H@ûÒk¡³“»¯¾š›î»Odá8Nþ<(-oVD*•™2šÆ çŸÏû/¿œY'ÏŒwaî·€·Ïy;±¹1n9óê—/gÖ¹ïgãß›èÛÙÇá‡>¦ß½ *]]],_¾¼d[}}=\zé¥ÃzþºuëÂt¢âí劦ìÏ2[¶lQ«¢bttt°aÆJƘ0ØØ”f|nذ®®®JŸšb¤¯¯ŽŽ¶oß^éCÆz|nß¾ŽŽŽ=Ža…b<èééáïÿ;;wî¬ô¡Œ ʶUL%”m«l[Eu"mÛ-[¶TúPÆeÛ*¦ʶžm;Ü üáàû"±Áqú'lüñ]¸L#Z·‰w¿ûq^»«‡ k/ @ƒ÷üâ=hh…^&ž|]?ð9læa†ö ³1|ŸéÓ§Çñ<MÓˆÅb˜¦‰®ëtvvbY–eá8—vt€eq衇òøÌO÷ϼ0ŒRe †0C]€¡ˆFÅke³f|àºpjÑ{É׋DÄcì»â5˜3áÜÏ[ØžJŽ¹èØ·\vßݽ;Z'¿ùd!š• Ç–°Åû&åÑ´üçf!~^|ý“ Á†9OÏáõfáà ùä·¿ :',ØÆÎGòõ#Tn»í6ZZZXµjU¸­¹¹™ë¯¿>œä£¯¯•+WrÍ5×ôk8¶yóæ~û'elëÖ­jÑ©¨SeÑ9ÔØ„ÑÏ 6ô«‡«PL›7ož2‚ÊxŒOµèTT’žžºººØ±cG¥e¯Q¶­bª¡lÛ¡Q¶­¢RHÛvëÖ­•>”½FÙ¶Š©†²m‡FÚ¶=´8ŽÐde,‰mÃ]¿:oÏÞȯì`¿ý~Ïëþýö[²ø@^3Øo¿ý˜9sf!Ë"_+NsÅŽ+ØÞ¸Ã0ú‹¾ºÎ®ƒâœÝ»É•÷2‰Ç1Š2;2™ º®ãû>¾|a~—8‘HD'ŽÓ_PqÝÅrt]þ8¦iÒÙÙYtøzáúÉ£X º»‡ÿ%ð€ÿçcÖü- ¤aæ/fRû•Zî8ê~ÿ¯Á—c<_û}æÎÍ ÿu‡Éˆ•žžž'½ššš·cÛ6¡1°yófºººèêꢶ¶vÀ÷ÚóæÍ£µµuÌ/ŒB1Z[[9õÔS+}{ÍPcõø<õÔSiii©ôé)öAêëëimmeîܹ•>”½f<Æçܹsimm ÓµЉ¤¹¹˲ƼŽm%P¶­bª¡lÛ¡Q¶­¢RHÛvÞ¼y•>”½FÙ¶Š©†²m‡FÚ¶cÙgE×…VïŸölÇá÷œÆ+Çä¨y¬†…;ndÙQ5œrÊ)BPÉsÀ¢xÃôý!òúA,ãm—¿3/8³ß{žÒÛ ºÎ?>¸P¦JâyB(*­‹ÅÐ4 Çq¨©©áçÓN Çaí~ Ç)”ØÊ÷\²a½müø@™ɤ8Ö8ðp¢´§K*%Jw‹0–U8Wy±y»rþzá…<~ÔQ¡ c v^±Xÿ4£áò*ó´ç0ëÐà¤sN¢wn¯®€Å×..͈#FÜ”~Ñ¢E´··ÓÒÒR2Ö­[7`úW9}}}¬^½ï¶ÛncóæÍ477ÓÞÞ^²ïæÍ›UÓ1…b‚llʺ˜j|*•CO…¢zQ¶­BQ¨¹S¡¨^ÔøT(ª—É`Ûz^A/ˆÅ€Í ýA$8œ|Üs,?°žG”ÓþsG7 ?&ÌDA‡ý™'œý‰DX¾+NÊ{•q_]d2´G"|X×…¢iâw4*„ˆÒf.4ÕÕÑÌÙ>˰82s$Y]ßçÓ¾Oïcf³Aa€æñƒbšB|®B‰jj‚k³p\Ùc²OK1–%Dy® úÍ ã-5McÝë^Ç™{:>)ÔŒ ¸ÏÏ"O‘fâû>©¼0dš&<ðÀèÞcF,¨¬X±‚žžLÓ Õ©X®ZµjÈTm·|ùrV¬XQò:477ÓÕÕEOOK—.ó“V(¥ìil677«ñ9žçfÑ$àå'Qc$›B1j|*Õ‹²mŠêDÍ Eõ¢Æ§BQ½T»m ÿ{quß÷:ð~™8Y»ƒÚÚøé~ÊyûŸWp´§€(Cd¤z˜µâ8º®cšæ ‚ |=%™²ï‡®—f®xo}â N¾ývR¤X¸h!hðl}=x"¾<‰½ñeFXÊ*¹‹‰L™¹ ÊmíAÑu>ô¡ÑgŸì‰âS(«Ìfš&ŽãŒ«OnÄ‚ ÀªU«hiiá¶ÛnDJæ5×\³×ªdkk++W®dÑ¢E¬_¿žÖÖÖ=–S(ƒŸý ‚€h4Ša˜¦Ihš†mÛa£¬ºº:z{{Kžçûþ¸¤*ö]ÔøT(ª56ŠêEO…¢zQãS¡¨N*=6e«~I ó¡{û+üåg휼ô¯l}Ë‘Ü÷ûxϹï)8Û‹{¸kÐ÷@3øßÎg¥ ÇùõH ±íBcöâs]4à qÒIBÔÉë'[Ï;宋iš¸ùßÊHE†D¢TÁÒV]×Çßï5ˆžä8‰bÑk– ÒÞÞN{{;K—.eÉ’%Ô×ׇ©˜{Ú5kJþoii¡¹¹™žžêëëUJ§BQ!ÊÇ&¨ñYŽëºø¾eY8Žƒïû455‘H$p'œƒ À¶mLÓD×u\×%’Éd†Œ|P(CO…¢zQ¶­BQ¨¹S¡¨^ÔøT(ª—j²mƒ@øöÓé|bF>YD×ÁXoœ¾ƒ;¿ügßÞÈÂ[âãsâŸNå R”f4èÐ9#CÝ9ç iZ©ã?D3–²ò[ .åY&eMì<çR¦ ôsþÇb±BÆ pë·¿Íy—]6a×sD_ŸòkYIbo¶, m¼2cò KPiiiaéÒ¥ttt°zõjzzzhlldéÒ¥{-ª”£&K…¢zQãSày‘HMÓÈd2xžG2™$•Jáû>™L†dR„?È&d¶mcš¦‹Åp]W *Š1e_Ÿ¾/ì\UUO1ؗƦB1ÙPãS¡¨^ÔøT(ª“JM×Í—÷ró=Ü}À=‘kàsþÃQÛŽâŒgÀÓ€ÓcÓE‰*"@Q‹“¦Ý7qòcÏaù~©óÝuK„<ŸÉd¸¯<›D×ï{ây…Ò`>à&$‰°a½mÛ$“I|ß'ë8<ÜÝÍñW_=á×vDL‚5¸®ëÕ!¨ÔÔÔ°dÉ–,Yˆ&ôíííã*®( E5áû>¶mã8¹\.lXæyžç+ŠFH§Ó€ˆbÈårD"\×¥··—H$BSS™LFõZQ(†I2)Œh)¨È^€•>2…B¡P( …B¡PŒž'ê,+Xç $þÓðÊ ½\tÈEÌ›5mÇm#ñæ„ÈN‘zG™Ûå…$ñ­oz™”¿Qq#vß§wîÜl0Ç}*Ux,E(ìhš:û}ßßßÏÿ_é =˜ˆ2jÓGûÄ%K–°jÕ*Ö¬YÃÒ¥K¹í¶ÛX¶l]]]z‘ …b¼é—RijjB×ur¹¦i†B‰eY¤dƒ®<†a„Y*’\.G6›-™<â¦e …bPâqaÓÆbB@ÉfKmT…B¡P( …B¡PL-¤Þáy¢EIIBHþ1ó(˜ýª3gûæ¼qŽxÕ û ƒoøaFˆÌBéà*}4ù YyæÏDù÷aQüºƒ<¥»»›îîn²Ù,Ï-[ÆÝ³fUúr+†É¨•bimmeíÚµ*KE¡PL |ß'‰ày^8aÊr]åµ Ãè7 KѤ|»,óeš&©T Çq‚€d2ÙO€Q(öu’IñãºÂÍdÀÌ?ÃÃvUú( …B¡P( …B1D"â·ï—Ó%!ä> õ8\ñˆØ.]6eZIh𯵫VQWW‡aœ~Øa¥âI,&›EýMð<^G±Ã0 ýú×q]·¤¯Š¢z‘ ÒÑÑA{{{øWWË—/gùòå´µµUú\öy<Ï Ë oSƒQ¡9Rè(Ž>Ш£9ZR©±XŒX,FHضïûÄãñJŸ¾BQq"Âp+ê5!¢ŒìüÏ …¨%…B¡P( …B¡PLt]ØeÊšºãS(¥¥Ã¶ÙÛ8úº£E6ˆì›’¢DxI&“X–Åqóæ1gåJ àþÄÁ¶ J"!ÞÔó Ù*†ÁCÇ—ÿs”%ÛcC?¬ëzØŸWQý [P¹êª«X¾|9===ôôôp饗"Ceݺu¬\¹²Òç³Oã8N¿Ô3Ù [¡P Ÿ Â&òAŒkýÅD"ëºAöcv ©B1ñ<˜6Mذ¦)Êz…5rD´‘ÿÛëÂJ±B¡P( …B¡P(Æ߇h4߈¾pàÚÅׂ u›êè;¦Ol/Û7Ç +ŽÄÓiÑŒDô^6+jLÓÙYTL3ì¡2êfçÃpÍvwwù¸ š¯†%¨tuuqÛm·±víZZ[[Ñ”¾¶¶–k®¹†ÖÖVÖ¬YúuëBÁE1ñ¸®63jhhSÅ”sV¡>žç‰DH$†ŽŸÑŒ£áNtº®ãû>š¦áy^ÿ¦h ÅÇó ¡šš„ÁœHE y@! ¸²S,Àý?•>z…B¡P( …B¡PŒ5®[(óÕ/ÎÕL˜¿a~¸©÷”^Qæ«Lóð¸Æ0ÄOq[]/kز ³ØÉ@UQŠ}QÑh4<%¬T–a *·ÝvÍÍÍ%ýQ:::X²d 555Ô××S__¯• @öu(Fþ/SÄâñxõÉtG5ÁV( ¡¡x§ID4M#N—¨Žžç‘J¥J˜ÌB1 MÓhhh ›ÍbYV¾& ,]äº.¦i’L&÷¬Î*û¶m‡ â‹‘cj´È2^{"‹áû~¿±žÍfñ+…B¡P( …B¡PŒ5%º€‡¼v}j¾ïóríË|øñÇÅYhjjDEŸm_ü"‘H¤4Øu¢ý,#p+ $„X–Egggè'², ]×q§ŸÈã8NXÑH1~ KP©¯¯çú믧££ƒ•+WR[[6§ïèèàõ¯=\sÍ5•>ŸI‹,ååº.–e‘H$0M“l6‹¦i˜¦Iooo˜¹‘$‚’ƒXئf¾È2BJPQìëȉ&;H£1MÓ±UÍ0N†çy˜¦I"‘ǸB1•ð}a[VYcÁ8̹z¥dú¿†,}™L&é=´6Uú¬ …B¡P( …B1VÁ ºG'Ñï¾›¿Ï™Ó?€vÙ{l;Õ¹Êý¼©TŠD"ѯô—뺪|ü0¬’_¦6-Z´ˆ5kÖ””ÿRŒœd2:oetúžÐ4mDNÞW^y lP¯iZXL¡ØI§Óär¹AS! à ›Íâºîˆ'£ÑL¶²ïŠQab„…b"ðÏ ý×k?ö1.¿ürŒâ2ê®;*AeoÊÁîü‡Va¤Ï)©TІ††ðïx;Å4M|ß'ÚÐ Ê"Øv¡gŠi–•J>Ù~8þ'éG‚€d2‰a¤R)t]GÓ´°ÔY$ ¢ÑhØc{¸¾`Çq0MsÂ¥jgØ‚JOO«W¯¦§§‡ššb±Ø¨ú¥\uÕUtttP__OOOÍÍͬZµ €öövÚÚÚX´hëׯ§µµ•–––J_£q%™LH$F¿7=dszÕ¬HCM˜:ã3N£ëzIï¡jF×u•I¦˜ôãÓq„ͪieÙ) Ä9õy„¥¾|ß'‹]òó•çyd2,ËÂu]4MãK~‰Ôµ"%ܶÅûèºø_MmЉ@Ù¶ Eu2ÙçN…b*£Æ§BQ½T‹m+3TJH:úä¡Ôœ!úzkšF퓟áK/ô‘AåI?Šÿ†72 H&GÕ„¾RŒD¸Éd2A@CC‰D"ôïʾ۱XŒd2I$ ƒŠÇ “H_™•Ïæ‘þéh4J,#“É û˜ö†-¨,_¾ ê;::¸ôÒKY»víˆÔÈ®®.n»í6î¼óNjjjèééÁ4MZZZhll¤­­k®¹†ææfºººX¶lÍÍÍS6Áó¼g©ëº%µþ†Ãh„bç¬eY8Ž3)ËŠñcOc˜ãÓu]Ç '–‘ˆ‘•*½¥¢Sa|Ú6$%*RdÉOižçFKŒ¶t:M&“ ç/ù{ËÌ-Äß æGE])Þ8tw a%@ÈQ(ÆeÛ*ÕÉT˜;Š©ŠŸ EõRM¶í€®$ø‚/Ô0 ž=äûxÇ iÄb1lÛ.)¥ND•½ŒºUPû›Ò&ؾ³³³Ÿÿ(•/ !³X2™ ®ë’L&KüÀ¶m‡×L–LÓu]×Éd2ضݯ·|žì,ýÛ©’r¥A€ã8%ýÁ%Žã„¥É&ÃjJßÑÑAOOk×®¥µµ•µk×R[[K{{ûˆÞ¬§§‡––jj„Š(ÜæÍ›éèè ¶¶6,ÖØØHcc#C¾æ–-[ö¸O5"E±XŒ\.7ê?š¦XT1M3|?Ó4'4emªÑÑÑÁ† *}{ÍPcSžçhÆç† èêêªôéâFŸN§û©íÃe´ãd,2KÔ9}}}ttt°}ûöJÊ^3ãsûöíáÜ>ÞÈ¡6àPpÙ):¡˜Ñh”l6K,#‹aY¹\nÐñtò/“NC&#„“XL8uuÐÔ$læx\; liEåèééáïÿ;;wî¬ô¡ŒÉ¹(ÛV1•P¶íä±mûҶݲeK¥e¯™ì¶­BQ޲m‡gÛöõõèX\úy—óÛ·þ¶dsݦM¡ƒ>‡ÍÚC§}.'šh´26…¨Ì0 ¤¨1ÒàZYæk ‰Ù|„¡iš%™)¶mã8Nس4r¹Aày–eaYét:ôMÉ5»ã8D"âñ8Ñh4,ÙL&Ãÿ‹ýYét:쉶mãº.®ë’N§qgDç<_YWW׸ضÃTš››Ã"Se¤,Y²„ÖÖÖÐhkk£±±1T6ËÍÚÚÚ=Nˆ[·n”‹NÛ¶I¥RX–µW×T*U2FŠT£cª,:‡›À¨Çç† X¿~}¥OcN– ‚‰é‡2±s mª1ýÈ‘ßTTÆc|Nä¢3Éñ èsr?ñ=—+ÅctOÁg^òph#ëºø‰ÅD†ŠWb1H§Åm [Ú÷Åo)´(&†žžºººØ±cG¥e¯Q¶­bª¡lÛÉcÛ*ö-¤m»uëÖJÊ^3Ùm[…¢eÛ϶•¢épp]Qò«1áD?tÆ¡%Y½sç†ß°p!/^|1žçÖ”š&…•¾ÄÃf¬[3ûµ,Ë ƒŒÇ!“É ë:¹\ŽL&Š:²qØ“&%™LÒÔÔ„išär9R©X–E&“¡©© ß÷1M3k"‘HX!Éó<šššðHä[±o3ÐØlii™ÔãS6Û*®™L&'D@”Ù0#¥XP1 #aû6“u|ú~¾L­Pôüï4aT‘ïûaŠ4²FBÍc5ÃÚOÓ Â‰ì³’Ë‰r`®[ø‰Å„àâ8âø3™ARΊ<ûªm«PT;“uîT(öÔøT(ª—JÛ¶®;p«“¾ßõ‘þUš‹~{ì.l¿ãå—áëL¥RìêéaýOpz¥/d•R,– p,ƒï‹Žk }dc8éû~(ĤR©pý/Ë}G"‘ÐO-÷khh( ¾”=`"‘H¿÷K§Óø¾?`_™±bØ‚ÊúõëÃÆô@¨î”GH¬Y³fÐ×hoo§¯¯+VPSSCcc#===477÷ëɲyóæ)ÑtL¦EA@ww70p ¡Ñ4 †aôëÙ2‘bŽ¢újl‚˜L'ãøt'TÆåM]¦.îM©¼á2ï!ï2½q´"bò2™Ç§ë–eUûˆì”!¦$„ÇÃÈ“‰Â0DfÊ´i¢4˜çAùðÊåÄöhTü­’Çåì«¶­BQíLæ¹S¡˜ê¨ñ©PT/ÕdÛ–¯½|ßg¿ýöÃ4MN:礢ý ŽÙ7÷ w¾“ÓßùÎ1?¦‰*Ç.ÛDLƒUdÑ4mÌÄ)¨Ht]}ОhùžÒw^L.—4 ¼ê’,96žÉÃê¡R[[Ë¢E‹J¶Õ××jÐÈÁ ¢±š¬Á×ÜÜÖ!Ôôôô°téÒq9ñ‰Ä¶mt]ߣsu õo"¨Ôû*ª‹ÁÆ&0)ÇgCCétšX,V¢xK&[‰;ÏóT¿£}˜É:>ãñ¢œ¢HÀW\¦ûN¤˜"[%•™'A ŽUö^1 ‘âïlV•ýR ξhÛ*“É:w*ûj|*ÕK5ض–UT! ï®t‡ººº°yºD‰?ôÐC£ªv0&Â'#}´•.¿·=¿¡Ð\N&“qi}]× 06M3,ñ„×NÓ´qMZV†ŠLõÚ[ZZZX·n]˜.¶~ýz–.]Ö¡mmmeåÊ•,Z´ˆõë×ÓÚÚJMÍðÊxT+¾ïã8΀êÚ@Œ¶WÃH(W9MÓT%…öqö46arOÏóÐ4­_6Öd`(¡g"2ØÕÇdŸŽ#Œàð+m& 6!0~ÿAÐÛÛ;²ëˆ úŽé£Î«+iL8’I!ªaSûtº4”a@$"öQ(ŠÙm[…b20YçN…b_@O…¢z©Û6/ªtrÂQ>à{¹.:pÒgŒ{åâê'ã…*]Eh,|iƒ½ÆXž›a¸®‹eYxžG<Ç4Í~BËX3â*===ttt„é˜õõõ,]ºtØhÍš5tuu…iaÅY.---477ÓÓÓ3ê ˜j#™LNXšÖÞ "ßCM˜\ãSÞL‹x­Ò?ZgI}¤Âù†¡2Éöa&ãøtݲ¨¢,Ðd\Ç k¤Ž8c,i#ºÎ©<@×ñ]¥5âcô<Ñ+%“¢‰DÓĶb”ž©Œ}ͶU(& “qîT(öÔøT(ª—ª³mÀ…Gÿô(ûµ àÆÎ *ãLkš&¹\nB‚v§Z©÷ñô9[–E2™„èf±XŒ ð}Û¶¹õÖ[Y¼xñ˜¾ïˆ•¶¶6V¯^MMMMXlõêÕ´µµ‹ÅÂ{{b¨†ESm²ô' È–e6ÅÈG™q^Gàû"se øÏX„Q( …B¡P( ÅÞ#;„ë.6}m ,°ÄóO<ÁnØT>žj ‚ ©V$+®Œg¿ì;ãºnÉûd2t]gíÚµ|ðÁcúžÃTºººX½z5k×®í§RÖÔÔ„"ŠmÛJPÒé4žçMªþ ²QT“×uǽ Y¥‚Ó4ijjv_&…¢'‘oîN Ð Þ'—ËíyœÚ¶ø1ŒBˆ’e ¥Fέ–ņŸÿœ?Ïý3gg ñ&ȆBß!®€(;–’`%Àÿ;…Rdùcvœþ‰,ù5I¦u…B¡P( …B¡˜tx^Yu6ÿ|3‡ÿ×áðþû¿üøãa]Åð‘þê‰(•6Èl›âóÏ÷ž>œ:::hnn2åkÅŠôõõÑÑÑ1!ªZ‘Ù)¾ï8м’â‹êÏ ˜ìH3•J‹Å†ÜWÓ´O¶•žœe³l6ªïªI½¢Z)N,Ù¸s#®î‚&/†-zÆb"%DVФÌ(züÃæ´O¢ˆÌN‰BPIŠ9HÃ< ˜ü´[òEÂË-@_ÿÑ¥À …b2âyŽã ú¸ïû455©õ€B¡P(ŠŠý«ôÚÇó/?ÏÊí+ ArÅÏéì÷ ÅÞ1Þ¾+]×'¼7ø°2T6oÞ<¬knnžÐƒ¯FÒé4±X ×uCïH¨”¨bi™W§PL2Ç ³S†3‰Ž¦¯Q5d›Iu]Ó4¢Ñh( )ÕF&S(™õÈO!}P7p±m›NY®k$/6„à±#ãì?-„ <<ŒÀ+ˆmaé¯ b? ‚å`þø^~[´ƒ^æ½áD– ÂÀW(ŠÉ‚çyaÍêx<þ]Xâyñx< K§Ózè¡•>t…B¡P(û Ž#Šó‹Ó~§Á)ö)õ)nŠ)˾OÅ*%S Yqe¼Ðu=Ll˜(†%¨ÔÖÖKTéèèØ'K~ù¾O2™$“Éày¹\nÒEwÉ’_ ÅdĶm\×¥··wâÞ4@8`+€®ë¤Ói¡¨J§(ªÈƒ]îÂׄq3ª1ªi"[eOè$DØH$BoooaŒh„¢H1Ö• ]œßN÷á¢D˜ÃW 9…BQ!¤³@f©Æãq Ã{Çår9ÇÁqb±Ñh€X,†ïûaÐISSSØ;±··7ìi¥i¦i‰DX°` ”S( …B1áèzYAvݶ‹7ßþfX|5~&_[ºøªÚT7åooᦘa•üZ²d ]]]C–ójkk£¾¾~Ÿ4¾e‰/Ù;„ó"ÚGÂd;^…¢˜îîn4MÃ÷Ç8мHà^xËBði¦²lÛfõêÕ\sÍ5zðÕ‚ëºÄb±’_–eM:g§ÌRQŠb²!JìéØùzšAPèa="<„óÔÏÿ ¢Áu¾ÿûÑ× ³òùùwÄï2bÊÓW Ãèç0V(ªx\ô‘ %O>ù$žîa™Öà†®m‹FóÇ‘*jxßïÎrQïƒd‘Å0 |ß'‡ý”ÇÁ¶m¬òüñ~/ž+¡$)&DÀ¾,!´( Å(‘"‡®ëÄãñ°|§ïûxž‡ëº%÷+Y*1‰`Û6‰D¢äqP"²P,Ë /$A„ÿ—o/¿7kšÆóÏ?_éK¤P( …bÄ-÷¯èàëù(×C}XP걇Ã^ûZù6JÇwAÊ4ÍqÏ‘ömÕ•ühmm„ú'³Q6oÞL__õõõ\sÍ5,Y²d¼ZH&“A@,£©©)ü"ަéu¥QïŠÉÊ©§~”d²jš¢‡u*%ÝÃü( A”÷ ÑR\q`Á¶¼tðKÌtg çj:ÿ£!âRžcJù½D×uR©TX}²ÝkSÏ:ˆ/ƒ†<˜ýÇÙo0Ba£ÇbŠe¢Œ|_lAËìÙ³Y¸å.øá·Â€iPÉ Ïóð}XãE×E•±’Ý4 Þ¢üßuˆû@qo…B¡€ƒ“"‘š¦…Ñs¾ï£i†aÍfI&“X–…eY¡8"çúò×–%ņA4%“&)Mä{•3X$ŸalÛ¶­Ò—Q¡P( Å>H¹.rÏ=÷°`ÁñÏÌËïàºÜuå•,~åzç;+}Ø“ß÷^«OB&Ú76¬’_’ÖÖVî¼óÎPÑÞüèëFðÓ̆ØI Í†w6œ BŠQ@ôP‘=WtD¦ŠHÇr´èï½` ¨TÓ4I§ÓªTŸ¢âø~QÛ!6¦ 7Ù‹iäƒ ä@ ‚²%{‰a0¿xðËÚcºÎgž‰mÛ†AÌ4ùãŒmÛèºN2™ 3Lñ}¼ æ°Ï<ó0éôÍ%Á½½½ÜpÃÃ\|ñbC‘­¢Jö*“š H§Óa¶x,Ã÷ýPu]ÓŒ¡iâörá…·ó¹Ï鸮Ç=÷<;p>–eÑÔ”ÄóNaÍš_rÄïÀó,xàóœrÊëñ}q{ò}ñsÈ!-lÜøt(fhš¦·m;ÐI¥Þ‚ç‚B2xôÑO{I–'L§5Þð†+1ŒB–n4*›9ó¿xè¡:@¼¿Ljíí}Ó¦Ï1ÇÔ‘HˆýS)ñºO>ù;þú×m477Wú£Q( …B± FÊ™qêŒ~Ûdï8…B’U#åÑSA¥§§‡žž€~†º|¬¾¾žúúúJÞ°pÓ4Ã> ž“¹¡»ê¡¢jl?>ãS:dæHظq1Pp"·‚ßÍû 6 ´—À½¼KA‹ °¶€û˜ØO?ìgDÀ¤Ùø7}Xgƒç—ù‚M„â"„)°Èd¯q¬Æ%<Š}ƒJŽÏ=!3Àpe°tpeßM™•’N|…ô(Êù+¡Ø§-[ÆÇÚÚøÂÇ?‘«Ï<“ÒiLÓ,xD"¸‰WÍŸÏ«x€_¼×uK•ý÷ˆööû¹øâ3„økäÏyòNýŠ1b*ضû"® ž—&N³ÿþïcûö;x啹AÀ~ð$‡z ÷ÞgæÌrÀ/óÙÏNgÚ´û˜1ã\lÛÈ·šKd¸õÖ{yé¥ã¸à¸õÖw`š‹$“ϱ{÷…ÈrK¥Äýò#y7¯~õŸC›"¢ Ìáž{b\xáËsŒ8ÆLFÜBŸ}V|¤ð‰@w·x,½‚k¯kš°U|n¼ñ0þú×£ÂçÈ[ßÏ~öWÖ®=—³ÎºÓ<š\N<7à”Sþ—ãŽë®ôÇ3&TóÜ©Pìë¨ñ©PT/•²mÃebOÿæi¶>´#ѱ•N§+^åG±o3á‚J[[ííí,Z´ˆžžjjj¸þúë©©©¡½½¶¶6-ZÄúõëimm°ŒG5ày¦i‹E‘¸M¡iÐÔ2èU¡˜, 56qŸñ¸ðµz ·zÕÍ7¯gíÚ‡9÷Ü>`ºžŸ€}0ãsâo½¼¹´Ÿþyˆµ œ gƒq¢x=óCÀ‘âïB©Œü›mûApï.l—ýZBA%Pˆ’G2`Âg\Wëcé”VT5•Ÿ{Â÷óã6|‘ÉF ‚ ´],6¶Ù)’ žÅDBH2 ºÎ©]DðùÏÓøÆ7¿Ȭ†®onæŽÃ9'Ä}_û§d³Í¸.—z(ûÝ{/Æ¡Oòôßÿ.Êñä_ Ã`ûöíüãÿÀó„ó³;—?gÅ>ÍT±m§Ž#~R)Q^[× ¶…㈿ Î:kúÐn®¸âfÏžÍ;ÞqûÛaüæ7pâ‰ùÊWžäƒ<˜ ŽÇ4¯@×]¦Mkö?C}ýN,ë—$Fh#\{ízèJº»Ëõbd2Ë<ŒahaR]‡µk§3cÆá¡ÍS|«œ6-ÎEÍ _rÇsÃþNº.ÄùÜX¬`»Û0ÍÍÇsüñ…çÈãÓ´¬]›æ„Ì~Ïy饃9øàƒ+ýqî5Õ>w*û2j|*ÕKÅmÛˆÀs[Ÿã5§¼†ƒÎ>Hsž®%eIgÅÞQ@¨>ÃT:::èèèrŸ¾¾¾=¾Žì³²víZQ²¦½½+VÐÖÖÆ5×\Css3]]],[¶ŒæææªŒFøÓŸ¥¥å#躶ÍW mž×¿™Òd@–ýšÌ™6Š‘³§± Œëø”e+L³99¾ð… <ñÄþwÜ!€s†‹3 D¹­|é!ò>Q¿OhZþîW^&Lúz¥ÃCÓÀ°@¿šþ ¹; ý^¤“C×Xþ·Qbˆr@1 åÁìüÿ#d¨r|²,‰(G¢R^§"•ŸÃ!óå¾~¼þÇ$.IL&EòÆHkù™"#e>ªA§Ð?€D‚¦ÿMÓhyë[™þóŸã[ñtëê«Yñîw³yÓÁ,¼å‘µiYB¬Ñ4Þ¶õ <1çi~ýëmÁ¼Œ4â~S<Öû Sɶlä“ËÙý²=“®‹¬Ó·×…_ÜÀË/?ÎÕW7qÒI·óÄ7ð?ÿó4­ƒÎΕxüìgâuššîã®»^ËÕWëL~Ó‰ÇÓ˜ægظ±Ó4KJR¼ñOsË-ïB×Ñï8<ò+|üãJ×ßýn ¾¿x€ƒ®í@×Ï+Ù†‘·s1ÑûU9pÅ-Ù¶‡Z“$1ŒWúm½ðÂ;€†Š|®cÅd˜;Šá"KN[_O…¢z©¤m«ëù*# Á¦7qæÝgæ+8ázRµ*,ËÂ0Œ)3·L4Ó‡³SOO]]]Cþôôôì±Î®ÜGJ€%K–°yóf:::¨­­ _£±±‘ÆÆÆ= 9• ‡\ÂW¿zò{—Ɉ›l9Y[© Õ S1ujlã>>}¿P¢¢ØçZpd ÌO<Á¦M›xî¹# e‰- áàLF¡‘´çhïÎïf ž#lk¯èz0/T-’ªm EVÞ’½`‚ÞŒâò_vþÿ2TäE&“Qè§Òãs8è:bì%ÅÿsžžC"‘à5sçŠTŽ1.'éº.Éd’x<.æ¬tzÐÌ—l6[C±s¾øEº»»‰Äã\øÜsDó \×Å0 ¦rzS߯­Å²,Ü {g'/ošÆîsè¡¿#Ý„w÷‹â>“¢Rì{LÛ¶(îï!ÿ!”D"ÐÐ æ\ÛG£bhÊD²DBÌÛ©”,#ê‘JœuÖ­ìØq)'žx÷Þ[ÏcýŒßÿþ¿Ù´i5†á÷ËùÄ'@×m `—Hû8ƒ­[¯/wÓ°ô°™œ~úq/ˆ"î‡ùµþÏ~.¯é+þ‘6šF@áÞY‡(™…÷~žØ/Rôï¾v…}ÒE7ä÷qÀLÁ»9ÿv~Ÿ$Ô<&¢À±)ØN8Ž?þäüJöšÉ0w*ÃÅq¢Ñ(étš;wVúpö5>Šê¥’¶­mغðè®GÙuö.ñ¿tAØóN±w†QZMB1"†%¨´´´°fÍšaý EsssÉ>}}}¬[·Žúúzºººú)šµµµa;ÁxòÉ'Y¾|ù„^´[nÙÁ‚ÛÂh/×-”qñø„Ò˜¡ÓŒåË—së­·Vú0öš¡Æ&0êñyë­·ÒÖÖ6ìãðýRgJ:-œ(ùb“É$óçÏgÞ¼7ðª¯΀8¢ÜV!¨ ’¹¨Ÿúç_V¡4˜ç2Vf¥¹nAPiºü3 9áèðPìHWWË—/gãÆ•>”½f<ÆçÆY¾|9ííí{ulŽ# _Wör€ ZÁîð`ñ‹YõÈ*!jXùç$0\Cìçç÷/¾_æEhb@wþ¹öÏ!2_s@!x؈ô»˜8.ˆûOþþK.ÿüük¥ÞîÃù瘈ûU »ë0ºéÇ#?ÒpÙÒË8~Ó,îûC]¥¿{EµØ¶Š}ƒx<>æ} ‹{›AÀ²eËøÖ·¾Åßÿþ÷JŸî^SͶ­B1”m;<Û¶««købÂ?7ý“™ß˜)ª•šJ{Šñ§­­m\ü¶ÃTúúúFöÅëÖ­ SÃZZZÂh„b†“2vä‘GîQÈKî¿3/¼ð .¼$¬Í,t±X¡ÑädÅ4Mg»hO1Ö¬YÃyç·÷/TE”M`Ôãó¼óΣµµuXï+Šò©sß÷io?™ãêÏcÁ‚Ù¼vûLáTˆ!{òÝž úÙ#».{›ø[F¿B¡,˜ °mñXîNq.éÛ!èïb„ƒc”ÃkOAày^Éâk_¦±±‘5kÖ0oÞ¼Jʘ2VãsÞ¼y¬Y³f¯êÝʨpž³áè3aÃÅçsù†› Ç({¦ø¾O2™Äqt]'DZm›h4ŠeYa½W”¯®ëhš†eYatN6›eÓ¦ûÈd2Äb1Òé4uuu444ð¦:Ý»ÿ–³âs.áòX¯pú¦F})÷9ZZZhmmåÐC­ô¡Œ)“Õ¶(dÖ©ãˆ{‡Ì>q! ˜¦È&M§ÅܟɈÛH*%ì9÷šf€ëºá|'z5ùxžMǵlºoÍÇ7ÓmtsíÆk¹ãûwpþ5çDмqÅWð™Üg„¨‘D<Þ W-äìGÏc:ß—üÏÊÿaç½;9¹ödqBÂ8ÈÂk{-'žx¢°A,„¨‘Cˆ$>BèÐóÛRùŸlþ·•LC…,[Ä{‡vM*ÿZ~{oþ91 ýÚäûäo‹É1?¿ž-ŽúÙQ\{Àµâ8 ÂàoÿäÛœõö{9þ˜+ý•3*eÛ*¦6¶m‡»®þ?îy‘ÈÀ)¬Ñh×u©«« ïgMMMxž‡ã8¤ÓiÒù’¤žçñÑ~”‹/¾˜¹sçVúÔÇ”j²mŠÑ¢lÛ¡‘¶mqÖË@„qx:…Û¼]Ø(¡c(Jí@…bO´¶¶Ž‹ßvX=TlÛ¦«««dq×ÖÖFKKˈëäõõõ±råJzzzXµjU˜*V[[Ûoßžžž=¸‰Ä¶á«_]Ç9çœÄ•WjaMbé3*®k,KM6t]Ç4Mâñ8™~ŘS™ÁÆ&Œÿø ‚BɯTªàpñÿü_iÙÿõ¤:g2-8•sãÀgVãw]¯=R¯6 ¼ÇdO†ÂvÓÇkYb{<.ÎÁqÀ;V” K7—óhˆý}tìC•ý’™eR 5M“Øx4þVTŒJŽÏÁ‰!1ØMÞÁç²ë£ò7½‰ã5-ìe2"‘Ùl6Œ@’}‚4M+‰H’}„ö¦)¡¦iýšñÉŒYVOH§1€C9?ýéû}Á>þëÿ%yq+™E Ã>{uSŠÉlÛNÅYœÅÉj2ÍóÄÜ,túòÄüú“wÞÊþð>>ÿã|çàïà=æ±ûÈÝ<ôôC¬]°–o™Á%¹K`!̽v.—üõ欜#îQEÙ(Ÿÿ×çÙyéNø&Bö(d›Žüíæÿ:ïë䎣ïà,í,!Dä9ðÒáÒAŽ{0sZ+¼v?FÓ4Wôwñ=èøÁíŽõÍë Ç"³k€ÍÍ÷3gÁÐ¥œ'Õ8w*ªiOˆÇA„6†mÛX–E$“I4MÃó¼°dv4%R©®ëâ8®ë† ÃF¤CPÓ4’É$©T ÏóH&Eêš|m¹Ÿ|îT¨Žj|*ÕL¥lÛx<_ª= O7>]TšÑkét:¬V PT’ae¨ ÄêÕ«÷˜Ö5—^z)õõõ¸®[2i666ö{½Í›7KӱѴ±m›tÚåßÿ>ŸË.;Ñsƒá²ê$“ŠL&ª¾Š}‡ÁÆ&ŒÿøtݸL&Etj2YÈøò<±Mö¾ýöïqÅåB'hµ»‡a‰)0ê`y´… Ó»lœæûÂ>]Mûoù÷ü ÄLpžç %>†‰aC $r‘çû~¸(SL-*9>C–º MÙm›ïÕÔ°xÕªQ¿®t@Ȳ<–e…Y$Ò¨.OÆs¾’"N¨øŸþôQ¤R)>ü³ŸñôÁ?åéîÎÖ@D¸G()¤˜úTƒm[ȹ;/É]©ôöŠßòGöIX`™úФa׫wA“ø¿·³—yÿ73?q&Gýå(ö¿lf<9ƒÓ;÷ÏY`ÁÂÿYÈ»ç¾[RÉgˆL¿s:³¿9[lqv ¨@hšÆ7_ü&‡¿ñðJ_Úá­«)ù€¼¥N1ßD5ΊÊÁ‘ÍR‰D"8ŽC¼¨–w2™$NÇ ‚€t:mÛ$ lÛÆ4Mº»»Ã×ö‰ìûVWW‡mÛaÙQ×uCñE>_ (ÅBŽDÓ4vìØQéK8&¨ñ©PT/Õ`Û>ýôÓ¼±±±ŸW×u<ª¨ F-¨Œ†öövúúúX²d álz$›a£û¥K—Žé1¸îÈú›È}}ß§¦f7ǻ߰JzMv-Â0 ÕKeb¨± ŒûøÔ´‚8éy…¦ïRH¥D4¼Hšrùä‰ïdÞSóÀ‡Ô‰`oþ{É2##%÷w0/z™i…ÌÓ}`ŒC!“ûa°o‘¹ÃÕ=4Mvô}&“´'ûMHRéñ92+ ° Ð’žÇÓ¦:[D:4MvÔÑDG(ÉòC’G/æ×l$óç^ìsQâQD„»bÊS ¶m¥‘}”l»Ð@>-ô,S‘ ‘DÑü;ÎÚÁ퟾"°á„ |屯 ¿¢“éÍ!›Oz3Þ¿Íÿ^z ±XŒÎîNÎZu¶ióÔûžêwl5çÔ°ðé…øo“Õ6ö¼ÁíðÞi îYSè¾U­s§¢òÈr¢²œ@CCžç…eº¤¨!ÿ—幤#³f=Ï#›Í’J¥BD×õ0»V×u‰®ë–ô~“½Û¤ “J¥Ba&‹¾ï“ËåÈd2af®alÙ2‚…O•¢Æ§BQ½T…mƒ»_¼›Å<" Ì"ì²ÿŠJ1¬’_cEOO===ým®X±‚ÖÖVZ[[Y¹r%‹-býúõ´¶¶RSS3¦Ç0Òuãˆàÿøo<ð,g ëy“¹Š8~3l®—H$Tç)ΞÆ&0nãÓu }H@6•-d¦€pÜú¾Yl¾uè·Â:àNoÙ{Ž&KmOhZA *Þùcï4ë> AøcÖwA.ÎÄûjaéÅä§’ãs0\7ŸíÕ@¾!²Ïª+V1?#;Pã£=`Û6†aFÉår#däóБQü¾ïãy^8FÆ’X,Æ)§ôòµ¯5pß;ˆ³JJ)¦6Õ`ÛN4¾/~¤i(Åkš(ÓàºâoS÷‰àcˆì’¢¡zPôw ð`óôͼeþ[‚€Ÿ_÷s>øÁrôŒ£IÛi<Ïㇿÿ!®ë²8¹¸$*QŽóT*µÇ^c{Ë`rÕN&#Ö3{ÄcØÙ¾“jœ;‹@ey.i€° ¤Èá8N˜mâ8N(žÿ–ýÜ€ðïX, +Pà!Å’l6fžd2™0óEî—ÍfCFÚ(¦i‰DBñF×õ0›LÓ4^xá…J_Ú½FO…¢z©¤múkãð´ñ4±¿ý ¾ûÝðñ ÈNÖþ Š)Ç„ *rð FKK ÍÍÍôôôP__?.icš6¼’?²Wƒ¦ÁÍ7¿ˆïÃ>0gДùÉ„Œj=( ÈD"A:V‚ÊgOcÆo|ÊR ÅãR× uÕq¢ÈVÏó˜Ï|¸ Q’£7,ù=,r¹‘ «ÃAö€)*¹œ¸xaùó£`ä3WâäÏo/‡—iš¤R©p¡'Ë(¦•ŸƒCî‡ú8qîôQ~ýõ£z=ÉÙÝÝ=ªçg2lÛÆq‰Dè‘eÂlÛÎ7®ün!3cFŠhh?üÞOùàôÍx7¿cáB¯Z‘MyªÁ¶hâñBϰày°ZDð@"!¶[âÞ`ƒ¦ƒ–£à¬—ó]Þu]?ð±WØ¡Pò•ï}…CŽ>$\0ËqkYétº_¿#˜8‘C:I'¾ÏðÖ/ ¦” Rs§bdGÈyÝ÷}‚ ËqÊr·Åó·ã8hšF$)Éò–ÏqïÑuh4J,#›Í‰DJÊ‹š¦¾—çy¡Àáû>½½½hšVb·HaD>w ¿ à —+4<,öXü)çMozS¥?š½FO…¢z©¤m[ìz%—c×Ùg3§Èî’åSSÁ1«˜ô [Pééé¡­­­dÛºuëÂT/Éž&Æ=1QŽ á©º.\|ñ6’I]?eDbÊ8ÁŽž'W‰=4¼ìììÄ0 ÂȚɶˆTŒ-c=>ƒ@ˆ'ÅA–%Ä]ÝF8a, &0ÿ·ÿÿÁ;ýlþ{F"âw.7üçŒä|ŠË‰I‘¥ÜG+…ýx„Óuô}»CŠ#v ÃP}TöA&j±–å;eÞå<íóÚQ¦z—Á-Žãà8NèØˆÅbD£Qššš°, Ó41M³Ä+£NA4‘•e8z{{‡|`@aæ»?Ø[¢ŸãÛw3ï£3H¹ÊÐW&»#( \ÓGY´xºÀÄ|Cˆ) æ69ÿå}†A8ŽLÓ$™L†}Âä<–N§cåÎËJPî¸ xž°M2{xÃz¹)ÇdŸ“Ïóú5~ÇãaVˆaaÀD" žç‹ÅÂ’\ÙlMÓH§ÓaÃâD"aá=EÎÿò½,Ë ›ÁK2™ š¦FKž£iZ¬T|(¶]Š…’òLºâý†S¦t¨{Í!‡RémÂPãS¡¨NÆkl†·JžÞö45Òy“GÌ)ÕÀ°9XºººÂmR‘œl¤ÓCgfX,:<ûì.8àa^~ù(^yeîˆÞ§š«íXÖð"ô‹Ë§$“É0%Y¡+<¯´”e¹ˆ¾ ›ïßÌgȦn*Yô›Ÿ}[¥ÏD ëÄ3TVœŽ8Gg$ÞAiSÜQ"`¾ïcÛ"êw8cW.RUFšb0|_Ì©€B Ÿ¿ÙühÖ¬·²_J±°1Zb±X¿¨õl6‹ïû$“ÉðØŠkŸ;ŽC&“ +2h ¼\˜$’J¥µ, ë ³æÏÜþãïððôwpµµš7“ÏËõxopÛÀݱ|w# ´¼Æe·×uq]MÓBç©çy¡ÀYÞXT:4«‘L&3éÆtqYU…¢RgxÈLji\Ü/D6g—ó±| DyO)4ȬT]×Ñ4††²Ù,®ë’Ëåhjj"•J…™,rÜ–Û Å¶Kgggxï)/)cFIy¯ñf$ý …b* mÏX Ðà…úcû9Râñx( +•fX‚JKK ---•>Ö½Æ÷…³³Üò<‘âybÑ‘N‹ýfμ’ÿ{Ÿüä¶~‹½=!_³ý’ɤ¸Ã=%™=‘F¤bß@×÷)eå’°îŽuÌ=w.—|ë’’]ÌõŒ¸±ìx5 ”õ¢iƒ¿Ÿ¦¯ë{¸YÈÝ ˜…ž1£E–F‘‹ÏÄžRÒ ¬!­Æ¹b0B1ÞCD¡°íšs×±Çò‰a~o¤ˆ’N§Ccx8ßÏ¡̨.vFH'L]]]X"¯©©)t¶¤ÓéÐ ÓÙÙ:{R©T(ÊD£QLÓ #f"þžX÷üU¬xî9>õÁOñÙ–ÏrêGOÐÏI¡-²Üm<™O@Ó o‚ÄO ½²=ˆ9·|~bøËò; lÊD"AaY9Õ<MF§ò9(*ï2xAιR(‘sj4Å÷ý°ä´eYaI/™"3Z‰ñxÏóèîî&‡Ï1 £¤‘ûpï){ îká‰päÉsW(Š}… (§z†Ça¼¶ŸCd"zæ)ÃeB{¨T™ŒL$ ¥ ¯¥":kÖn¼ÑæÇ?]4šeU÷Ʋò‹åaÔw—µdƒâZF ÅL AeÀõK¾ïˆïûôÖÃìM³9÷ºsûï—”.†1ò 2Yr`O÷Yºh$“¼p;o÷ðo÷ð^ÞøŒX,F$!‘H„%û\×%‚°´çyD£Q4M#“É„g ÈÒa²’ŒøÅbUíôRŒžÆù:.yãù¯ض L\¤wq”©,ý%Çtqæ¥ub±XØœV–“Èñ-³k¢Ñ(Ùl– Â1c¦LÒ8]?šÿÖþ›íŸÚNpÑèú³(M$Rȶ46Ïy,ð7Hˆ†òö®ëFéîî#Ï‹©†ò]û e+ãÌD“½8e`‚iš¡ÐaÛ6®ë‹Å¦ñÙlÇqH&“¼òÊ+@A¼ô}ŸX,VRbKHÛ¡2®x.KŠ@&Âþ-/¦P(S°Ï³Ï>ú,æ•Þk‹+ (ÕÀˆ•¶¶6úúúXµjmmm¬^½ºäñúúúªl„,#jm»PîJnÓu‘I’Ë $•Q4‘È;ˆÅb%´#¡ÚÓëS)!¨44ÀžÖ³Ò‘F+}ØŠ)FqB?òð‘H]×ÉÞš¸VŒ5QÕõ‘ *²Ô€¼¤Óé’I\>æû~ØØRFÒ-d3K(~“Çbå3qÜ[Àø)¸˜ó y2¤îݵÕ4ÎÎÎðïh4.pc±Žãàû~I­hY^@FèC©˜äy^˜ñÇ1M³ŸA3X¹$ÅÔÀËA¬¸ 0Äxßñ=á8NXV«RµoeÉ`ÐcˆÅb444ËåJ¾Ë²ôH, £bå8w'ü?웤ƒö¤ÁuÏð·óþÆÙÏž]ÚSB¡¨’ÉBVu"Þ*°>8¸ŒäwÔòûëºn(ÂAfJª(ëÊ:(Š1DáȹÔ÷ýpÝœÍfCû 8 Eö@‘§‹¢¥à"‘ókÊ›÷È>iã%vìmiR…B¡P ŒaKð¯ÿEÜŠ—<¾·=7бfØ‚ÊUW]Åm·ÝVíÑÜÜ̪U«hoogݺu\sÍ5•>Ÿ‘MØ}_,]Wˆ ¦)~§TüÆX*•µa&¦Õ<Þ¥4/ˆIƒ!Æ ÅX2dpíÏ·è´/a„Ãs°D+ÇqJ¬2J£ää8H&“aôºLËïìì ËãÉE¢Œ¢ˆÇãý‹òOy‹1ÞÞ]àm‚Ô4ˆ>‹èS‘aÄeÍŠI$ajY¶HÖ±—×Vö›‘…ÒA,K&$“É0Ú°»»;WdCát:–Ì TûL1%Ðæƒ.†Éd’ †ýyˆ²¾ïW´™ aa?”Á¨g˜®ë¡ $Bòñx<W2º:ªÅ¯B1EH&“a¦§Ì>‘ö°çya戴,Ë"lÛ3GdÉMè_îs {Åžås†r´Aa­?PIÝÁÊìgw GŸQòš²\¸m 1ZÓÄv×-üíyŸƒôIÈ×Öu±=„?BZišx=é³0 ñ¿ìc÷ò˯ªôWA¡P(Æœ ÷ľ}l[°MÜ\‹šÔÊu–BQ- KPéêꢽ½µk×ÒØØXòX}}=­­­ÔÖÖrå•W²víÚJŸS?‚  ¨H|_”ÚÉåJûœA€ã8a‚©8`ËlR)± ŽF…!7˜IF·«ÅXÜw¶ýqßû×÷øÅƒ¿Ó÷HP‘Ž Ó4CD Ò)ä8Ðß+¬²Ì\hÊ{‰¬ŸH$\ZVa§i࿌G@?¬ý!ù$>Úï÷î¼å¸•%ÀÊ›k†îc á¹€ˆü“×Hî#Eg™/E•d2fªÈë”N§KJ6(&'ænÂ2{w¬hç¾ûîV:¦ã8%Í^+‰ŒžŠ=Ís•â0 ƒX,Šª±úYăè×`œµ‘‡x˜ùߘOÃÏH¥R•û.MMÍæç¿4K[¢ëˆÌÏ=ÄÑÈ2—ñx<Ì<+ÿ^«¬Åê@UíUì-R‘#ř׺®‡ó¦´¡eYOß÷KJgç~P\Š; ¢…iîUR¨p]ñ“ÉævYºÐ¶ =Cƒ Pòº»» &kšØ/Ľ°ø}âq±.véG0¸ùæãCÁÄq }›šÄ{ù~AH‘%Àe e4*¶Ù¶¸{žðGÈŒ}yÙ¬x=ÓÇê8â¹ ¶=ÿ|¥¿ …B1öxž¸>~Óãì>ÕÂx‹,'Æ[L^wÇ—1ß|æÛ²Âér9Üsí=|ö'ŸU‹ńẅÀ"é´s1tóÕ‹vÎÿN#æš22]Îw •ê{^yt]õPQŒt#í]ã8Žã„ý÷¤][L"‘+Zwëù’²…y7™,|/m[¬ÓeF‡iÊáJ#Û CˆA Ët‹û[g§ 4ˆDÄk{žØÇ÷ ™!™L¡:…\§Û¶R C12iFŠ1±˜Ø×²àæ›_¤£c! DX¬pŒ–UL2ñ·aˆÿ#±Ÿ,«(ÏSÓĵ(Rè–—SÞ§-«PºÏóàã¯._‹B¡PŒR@¿ë/Ðxz#pwøØh[1(ãɨ›Ò·´´Ð××W²­¾¾žÍ›7Wúœú! :éó1 aÔ”¯ûdI›òôãÑ #fÊñ}a`É÷Ö4aɲc†!þ–‡ {±44cq,î!²L9š6t‰2q¤PŒrœ÷éó¸Î¼nÌßWúë}ߪ®ë’H$Â’De“Äãq²Ùl?a(¤sIÞS,Ë EÙÄZŠ"â]‹©çA®;S)pöÏß³d„é(îőã5F†#07 •Y-‰D‚\.ö˜‘‹sÇqÂkÂP²,«¤_iša 2嘫2jRÛ èbÌœ¹cG!4sd©¹}¥ œŒÆÍd2<}ÃÓL; ›ïz—ߺÓ<Í€ùóçsú¯N§®®Ž\.WUB“bê!…”â22PpÐ ˆŽ¨l3€¾-Ò Èd2¡.³UÊ1 #¼Ç+*ƒŠSP σ_ÿúvíªç/ùoä™gòÆ7Î7.äúë/§¥å#üìg5<þøãÀ©€ÈÓu±¾Ç b…ÌÎH$:ijï‘J•ŠA ¾£²Ï©Rd¦ˆiŠç—Ò–B~ËŒ–lVì›L¾û ?€,½%Eâ~Ž©Táïx¼ðü‚Ï`a( ä_¯/·K“Õ0 ÷_ÈX¼]>GfÑÈó*ö%È÷ xî9U:T¡PL=äýtÓ¦Mœpì ðdAPÑu]­™Uǰ•ÚÚÚ~BI}}}Éÿ}}}tuuUú|EYÅ ÉrÇ!‚1¨åkJׯ›ë ã,/DÊȨ—x\§® C-Çlšã2Ûû¾,CE©éº|4M¼§¼ɤ¸v²—By/…b¤g•³ëK»è›Ñ7¦eBÇ!‡åüгPä˜—ÂÆ@Œ¦\Õ@c$‘H„%Äd™Ó4ijj"•JÑÙùnLsZÉs¬Uþà‚»´ïáÂá5}g01Æ'Ì8kŠûKÈsD"Äb1‰ŽãJ¥ÂšÜAN§Ã¬ù¹ÉZÝétšÎÎΰ¿‹çyd³Y‚ @×õ0;F[cã€~(¤^'þ÷<–éÓ÷ö\Éô•B~wœ±Nû:‘S\ØqAp>é´˜?Ï~äl¾ÿÚïó•O¾>~3Š}ß¶¥e•%’%ÁNö@üÈHqñüoÙW%ßp(é â;_žÕ)QY‡ Eu!Kpéz* üä'w¢ë>ÿùÏÁì·ß©Nc£Ëµ×^BMÍíÜ|ó_Yºô¿ò™GåËm B´ëE™­‘7¹q]=Ü.׳r=\,ôÊ[ˆ<.yß*¾d³¥e¼%ò9ÅâHñcÒ„7Mq ²Iñô[lÒH±£˜T*UòåÈó->ùwqù±bŠ•ò˜ÎÞÇ4aÖ¬Çï ¢P(À÷ Bú‚/à˜‹ŽÙÒš®ñ÷µ5¥¢ú– ²dÉÚÚÚX·nK–,pÛ¶©©©¡¹¹¹ÒçÔÙP.lül”(žç…½ƪœ•¬ÇšL ƒNf…Q¢Ô ’ÇUY#S™¥1'³j"!¤Ӆº¬•.Š¡|Ô2¢'“)DöÄb…››Œ°÷}Jö—QLÅ‘f%¸ÐÝÛõ¾±0}ß³P Ã…•b†Ê<nVÊž(nžYœq‘Ëå°mÛßMÞ¥øýU¾ÌÁW ¨Ü  á ‹çËë©QZªÅE8É|„øbä÷w†Ê^6½Œâ¾,@˜ljÅbaO&y/‘åÖ²ÙlØF×uÂÒl¾ïã8NXB"‡B¸mÛašáôÉP ÏN¯LDI«ºiÓöø¼h4:àX›Ê„½‰t u¤yu:ͧÌYü—-&ëã~yÇ¥ã?ÀEW\„}¼M,SŠbÌ‘ßÒî,}1ó5ù±óqEN¿aŸ„b±;“Éô[Ôª …¢úð}‘=’Ɉyüw¿[Ëœ9søË_æ0kV/‹odÇŽ…Ì›w2ÿøÇ8æ˜qÕU¿Ê÷ù.×_9Ç»„o~3Î׿.^³¡A¼^,&ÖŠÅB…m‹õ«® qAÓ %»dÉ*™¥…Lr c`Ñ Á‡=G®‹Ë)ΑΞç3!ËE˜áP¤XÎ`×@öcøú8Ày#;Ű©«+d:)ЉAöÎX¸c¡ðgäý/ï+;SQ• KP©¯¯gÅŠ¬\¹’+VÐÒÒf¨È†õííí\sÍ5•>Ÿ~Hci(_¨¬;ÖŽŒbCl8/HúJHãªx½šJÎCÓ Ñ5Ž#ö—Fd<>ÈñúŽ3xú¿®‹ÇLSÔ“mj*6"RȤ»»›†††1iP¯šÜï»Gž•óçÿüy¯#\× Ç´ïûaƒì—RiÊ#yu]«8S.’H$¸óÎihŸBj%Dn„ SXKÁ4qÜAá »Œ/ä·e´ ÂÙ›D+… –€B„²Ÿ1Ä4M,ËÂuÝðHQÉ0Œ°wKñý¸Xx*ÎLq]—H$‚–\)nznÛ6‘H„£Ž:jb?Ø)ˆ,‡xÀ‡Ä6×uùÂ{ß;äóŠ3Âö»·˜¦Éú/ÿ™ë?ñjvž êÐcÀéß=›¾ywÅî ³?-ËRM¼£F:à¤m8àW)…¸·ËJ|ÅHÙS%&ÆyqŸ”ÎÎ΂`¨P(ª‚b'”Äq`Æéè8 ìU²jÕÖ¯Žx˜™3Oãå—ßÍÝwÿ–¹s3ØvŠk¯ýuuQ,K¼f2 ÝÝ×0~á=^y¥ð>±XÁµ¬Òã(6\·°.îô6RóAÓAÊE–¡ÖÂãÁ`BÏžž£–È•A¯*AE¡˜8dÖ ïû|±é‹ü˜‡ VVV¡¨4Ãî¡ÒÚÚJmm-¶m³zõê’ÇêëëY³f͈²Súúúؼys¿Òa===ôôôP__ßï±Ñ ³S†"‰Ä„G†ú¾O4 #ßMÓ,™¸e?âhn¹¯aŒÆâ~-‰D¡y^<>pß•¡®GqöŽŒ*’¥É¢ÑÂõÌd2D£Q,Ë"‘H„ÎêböÔó N“L&I¥RAPÒ[AQ9›0¶ãS6Z,gã#öú»PÜ[ w†aTµ3H×uššš‚€îînêêê –ed\›UCSÓ±$“ù¬Œ¢Í6°qÀdž¨ ™ÏAìËÂ1n¿b3@“b‰I!ÃÅD-¥ÂŠ›ÿ-E‘Ñ2J»F×õ|¹‰á}Æò¾ç8NètqÏ”÷ß÷Kî5²DÛÿþïÿVúcS&j|#ïûÎoA?Ã'™´˜óÅ/úœòÏc_Ç0 ¦¸’7>rÇ^û9n¾y÷Ýw—]pÜ#Çabrçê;ùþßûyž7ªRƒŠÊ1Q¶í`8ޏÏç+s Ó`ÙW+âñ8†avÒèžN&“)YÄ*;M1©ÄÜ98ŽXïÉ5¡(Å%Äý÷Ï1mZ©”Fsók8ðÀI$,çfb±ùxÞ¡8N@KËf,+ŽaæíX¬t½8X{ÑâÛÁP™ùX™qg¸Óeq 0E婆ñ麅 +Û®ôQ(ª‡‰²me9Å­×oåC»?Tò˜êŧ¨V¦dç+Vð׿þ•5kÖ„?k×®ÅuÝ—ú²m›ööö’mííí,[¶ŒÕ«W³lÙ²~×:Æ÷}üqN!“Í:}ßß744Ùl]×q]Çqhjj K,Ȳ5²Q³ëº¡óP"›õÉtfY+Û²DZv<>úc·¬Bj¶ï Ã]ë&xžGSSSXW»˜t:žÓ@ضM.— ËóÈ×Qç¶²f*Â@cÆ~|–€òËž_2ûüÙ£zMÙ—DF1ÈïRaÔwµ—Ô}TDˆp.—#•J‘J¥0 =§óÀŒزå.î½w#·Ür-oxè«ÛÄ<Ì7¿¹çNøä·ï¥é›^ ½¿%Âdmk÷>ð“‘ÄW¢D˜‡U2ùÇ5„¨’@”ˆ±⋇Èn‘ñ’ÎoóòïÙïd¸ŽbYîK6ü.Î^J¥RaÖK9S±×ÓDÏb4-ßl6IØËfOãȶmƒy`öQãùgýÙ<÷³ç˜5ëxžzêJ,Ëb¿¶ýXÛ¶–ýNßó: °mß÷ijj"’N§Õœ8 ˜(Ûv0’I1·vw‹,ãq)*eȾ^2 G×õ)wUì›TbîÜ[¢Q1¦ËýH¾/~¢ÑB ètZüã;xó›ßL,æ³sç'¹à‚[¸ì²Ëؼù:²Ù,©TŠîînb±©TŠššÇX´h@˜‰#/'=Ù(Œ•¥’ã3™¾ <$],êû¡P&ʶõ<¾ÿô`žš÷T¸=N+{TQµ ;C¥˜½é“ÒÞÞNGGëÖ­cÅŠ%µµµqÍ5×ÐÜÜLWWË–-£¹¹y¯ÏâTä(®Í?xž‡ïû¸®‹eY˜¦‰®ëýÊ ¤R)ÐõB4`ùM#‘H`Û6®ëây™L]×ñ<¯Ä.ì/ŒaÇ)d¬ìM%™íÒÐ þN§5>ðsÇ㺗FÉd2aí p‡X,†ïÒ=Ï Ë1IaÆ0 H&“¸®K,+9O‰ëº¸®;hVŒbô 56alǧï¾PÛöëmœŸ:Tç`Û6–e…Ññ¶m‡ãd²Pì¨.¿ÈóXµj1·Þz ßøÆ |ä#?ç5¯¹—ý(à-oyG±o[§¾þ! ¼ƒ6æëV븮Nw7Ø'€¾ÒàÚ`¾ ´oˆÏƵ!‘c"3Å¡ ²XJ†ùùmÑ¢•âŒ,'…,^Èëñ=Ÿ·ÿ¶BÆ ˆŒ­è5Ën˦i‹Åú]—}¡AÝDŽÏrl2ùÒv¾ÜÚ`‚JCC#ÌöR©‘?nƒÍIe„“ÌuA;þE¿c1›>¶‰lä¦soâòm—óµ¿F"‘2<Ï E•\.§®o1Ѷí@ÈÈtùµrÚ+{LÚŸº®“J¥¦¤­Ø7©äÜ9dÏ“\N®™ Bi<.ædNYU Ëg Û°~ý÷xÛÛNŶ#†‘Ï^¿r)rí{à /rÁª‡¢2TÃøÔ4!FÊ ÇWqA…bB˜hÛÖ÷ÁØmM«9çC爑FQOY…¢Ú• ²7,Z´ˆúúzzzzJ¶wttP[[Š5466ÒÑÑAKK˨ÞK–¨¬«¬á?ÖT:s¥ `YÖ°šÝçr9"‘È5ç‹ë³§Ói‚ Àó¼°Ùvqi]$ý^¹\!•u4×Èuñÿ¼M[Àa‡ý ¸3Îøp#A`°ÚÚ7£ë .ºè\zè!~ýëOsè¡§rõÕWåkóáù{žö¸ˆÅbD£QlÛÏ;—dêÈý”ciïllÂØO 4Ovþ†ù,<`áˆ_3R©TØ)‘HTE¯”±FžÓþûÃg?;X,‘¿ÏhÚNV®üuu?ओ¾Å¥—ž ”§žú6l ™¼…›þ™Df.Ý›zijºŽtú3\tQùK ×]×Çßÿ¾?MM³™7o+ï|ç.N¿~&_¼k6×½wÞ|ðl°Îs6ÄçñpX—€ýUHE))"³%†]rPû–Z$xÝŸ_'s≌¨¶óÿ'(ôwÉߦ3‰¢{©iJ˜²çL&r|#ËIJáËu]1Ÿù~¿A,Íd2©²SÁxãÒé£HýLÌ¥þÇ¿‰³ß{Èým YÈuÚu|ïñï±íMÛ˜qÿŒPÖ4-̪D"%¢Vj´»bL˜HÛ¶ÛÑé©ÔàÍK(‹vO§Óa·JLQL*5w×Sh@$"¶Éª‘ˆpêf2B@‰FÅ:NöF*¶Ÿ#‘H˜½ûÌ3.¿ùMg¿àœÁÆô,šÀOC¡(e¢Ç§ã”—æ ‚H„×-ôš‚ËH…bØL´mëûPûòËܾåv¾l~Ylô<Ç–/U¡¨.¨466P[[[²½«««Ÿ¢Y[[;à[Ì“O>ÉòåËY³fMÉvß“âPkBYŸ|¬ŽÉdÃ0ÂÞ ®ë’´æBŠ…ƒá k¬KGJ&“ ß»8J_Š º>z1¥˜â×>3×=×=›õë7ðï|h4ÍÌgÖ¬Ë9î¸>6l¸Çy’õë›9óÌŸpã°q]Èd„¸¢¯þ뿾ÁEý–O~òV>üῆçDZ,+,&…¥Â1 ǺŒ’–¢ËX—w[¾|9O>ùä^emU ƒMýø¼õÖ[уI"ý°ý>|×gÎásFÕ›CŽ?)fNuŠo²`,ËÈd„!"Õ_þ²Î»ßýG•à×ÏBo‡ÝÆWXñå÷0þ6~øÃ ¸ôÒU|øÃ˱,‹Ë/?ž… rÛmqã¯aëÖYwÓK\ûì?üiçhZZžà™¶ñ?¾†ië§qõ=ÿ`ãÆÅüä©{9ãŒ|øäÇyögóÌÙ;øS×£d-lè]ÑËÅߺ˜{/Þɹo€ÏìàéíOsTä(!¢è°aý^uЫØÞþB4I!œúMù¿‹3d< ß™|fÌs5ÏñÏ;ÿÉÖ£·Vú£Æz|nܸ‘åË—³dÉ’!_ÿ/yÇíÿPáþéûoÜ×÷Þ?*’h`dYNsrº.NÐÙ“ÞŠ•×즦›øÔ½ŸbóG7ƒÙN6}m7üæNüö‰¬\¹’ÿûßaà†œó&KJ|{{;ííí{챕>”1a¢lÛrd¿”úå ŠO(6Çãq|ߟt™œŠñEÙ¶#·mGBqÉ.Ù¯Af—†ø[d‹ýåz¶¸Ï¥Dö£Ëår444”ô˜SL=ºººhkkãÉ'Ÿ¬ô¡Œ eÛ:Žð-È1&Ç– ŠÅ =h=O<®b5#Eٶóm[[[Ã×.FŸ ÿžõoÌ³Šæ¯q¬$¤Ø·hkkãÖ[osÛv•Áؼys¿mÃI;òÈ#û-8e¤Ï‰a4ÏX2Û¥¸–ÿH#tc±ØˆÁÅŽ™ÚMMMáy†1îN™ “J-Äó`Ö¬÷óêWÿ‡Å‹!«áÍoþ3gnââ‹aõêÂM1)9Ë’dº.>ú:ˆÅê¹çžKøÙÏžcݺ^žyæ £ÓìÆ÷á€þ‡¯~õ œtÒ‘ÌŸß§?}2_øÂݼã«xÛÛæ‡ç‰ˆÔ÷ Âk,³[Š‘uëE™2Àï†ã8˜¦‰ïû¬Y³†¶¶¶q»®ÕÂhÇçyçW²àL§ÅÏ@+·ß°š55Ì;y^¿ROƒ!£µ}ß'±§ƒ–ßk â8ùä£8õÈoóÝ­á=‰¶pþö·ƒh4J6›-¹WȨ­¿ý0O?~×]·‹½Š—_#'Ÿ¬áû—pà ðÎwž@6 G½€w¼c!ßøÛLÖl~†_öÆaókùøk6pÏ=sèëëcçÌüëªÓ8õÔqÙeWòÿ÷(Ÿ_ö |ô@Þüê—yIë¥û“Ý\™ù%ÖS Öô7¾yÉ ìwé¿ÐnÕ˜ñ»qà¼òÍW˜Ö49ÞˆÁ¯~õ+ÞÚõVnyå^÷º×1gÿ9•þxÆÑŒÏyóæ N×ðe°þ$ág§þlÐòjMMMa*•28åpý§çËB4ú"次}âfÏžÍ\ ®°`î»çryïåy‡6߇'Ÿ\ÄK/ucš×†¥¥êëOdýú?q晟À0àõ¯‚+¯ü%_ùÊW8é¤Ç˜=û fÏÞÆÝw“X,FSSS˜ #¯k.—#N‡Ÿ·üÌjjj¦DßPŒÕøtaÐF"eõÝ}øÕÖ_qøÂÃizSÓ¯aÛvX¾@ e~§m»`›æÀ僠í1ò+ R[V«º®®F¸§FMUHOíRžq<ô,ë,@|—Ëʼn“ÇsÜq=üäâù­…ò|ýërar>÷¼õ öÛn°"þ gœq4ùÈ}{ì ÔÔ,ÆýËQ$“ßå׿†'Ÿ\@âzxá¥øíßvpè²Åðœ׸êëû£íáþoçÚù·1sæ{Y°c6w>1÷_þ<§c¼ê!¾qÅ~lÙòv–.ÝÂ{ÞcrÒ™ I,œúÎý±œ?!¨˜ù²™Älxdñ#ü广ðe+Ÿ‚]V\:‘H(GÎ0(Ž0–Y£ú‹ÈÜÖ‡óÃ'óæý/‹Ý*² „°`ÂqöqàÃ)§œÂ[¯{+;öcR{W^y%§Ÿ~:‰D" èééáÙgŸÅ¶í0˜@öÇPL c>6‹™žC®3mD‰/ž9à}ôQÿÞÈu ¯#ñ­„Z¤NŠô˜¼—ž¾O¾¶®ø¿,«0´ º½1žãs0\Wfå‹ÿËÅ’rdõÙ3Ncš&½½½áúÆf9é‘v1®+¶Éq¢ë¥û”?Ç÷…ý/½ëšÖ¿ö“ìd…”‡â}’ÉÂëÊ”‡bŸƒm‹E‘|¾ï÷_kD"bŒAÁ`؇ÆèXŒÏd²ôhš…¬”d²4[ åÒu]<®â ŠþŒÇÜi_ úàîï&¡Öî¯yÍ>QyD1y©A¥±±‘ööö’m›7oqc#¹6Ø“N’L&÷**O )^¾AoµQì5M“d2‰ïûD£Ñ0‹Å²¬qq€™¦ðGK;R*3,7&mOßFã¶•Ûñ˜XtÈZá >ë­[×pê©â3÷}!²hÚµ45 ÃH|̧ã8§‡¯õýïÅ¢EŸàÌ3áºëžàå—kÙ½{7§Ÿþvà¨|95¸øâmüèG³xê©.Òé4¾ïÓÙÙ‰mÛx६[÷¿ÿý7*õ1Oc1>å\( Û’Ï׃ÙœÍ7ÀcèŒ]×ñ}Ÿ}}db1úúú8äõ¯/ý.GóÒM³°’Øv¡‰‹Ü§ØÁPüÅM¥ ûÓÛ[Xp54ˆ/Yñ"'_fé=-ÛÞó*z< àþW¦óñSN 7iš6d»¦Á·¿]?ècPº–L§aæ¶Wsá?Ÿç‚o.Ä÷áå—O&‘øï|g]¸¿\sZ–ÃÞ¥½é`>šº>äƒÙ±#Küž88ƒÓ^u«V@ôdH~y|1[îßÂÓ4òáOíàoœŽçÕpã5\q4ãs3'Tæ:Oc5†½g4pMÐÈåK°½¿éý¥s]‘"‰¨£DÞŒsj0Î9+€ý¨§ï8ø-“ùÕ|@ õ]MƒXþRÏ æðï|€õó×óÙû?ËY9‹íWo‡#À×ý°¨ÌRùÁ~@2™ ·)ÆŸ1›eÄãbjJ¥ÑóëåmÀ€›_äüÏçò÷_GÁ AҗfrS,T ˜!í)Rø~ÿÀQ pñxñâEv#/~¿îîÒ¼©Il·,ñÛ÷ËëŠã˜ôJ‚ à]” Ý>t/¯ñ9²±¼d %¤çyø¾çyaæ¼ëº˜¦Ù/ð¥*DQ9*äãRø+x” FiSXVéw4™ã# ßßÁ„‰â‹Zô>ÂÉ0œHYŸ<‹çqë½÷2ï o ÒÙÙ‰–N<‚Pj`Aá1¹ê•³´çœ¾²ÆU&Sê”È@%òÆÔÙÙI4-éõ"ë¯ÒY.ýÈ2A`0Š/×P‡!/E±Í+ׂÙœå”ü^8ŽøžtwË€¥£Â÷uœCE]û´|Í9¬\ K–ìæškp≟Ã÷k°í¦ ŸøÜw߇xá…§ÆìúU#c1>åšb@Ÿ½nàr­qí_'™L²fëVêŸ}–“Þòz»»ÙvÚi¥; Õ@IÉÌU^¤z°/¯\úÒÊŸ\L•cëj)î¤RÚù°þÌgÙÔÙÀ‰'> 4¬ç  7¦ ¿º¯ŽÔãpAþr½îuëx×»Îã•W^ /C.'>éïqçqbñ}ü(N>9qЙ,- {3ø¤Þ _Á9??‡Ý1]40xÛåocáà ‰­‹ññ3>Î¥g]Jóû›ûeÖzž‡¦i#Šr.ïÕ&_Ç0Œ°ìؾÌXÙ¶ÅHßýCBPÉ;‹®ˆ_iš\ò‰K*}IªƒâÌ Ï+Üì$2ZÎá–U:Ê49q•§ I§­Üo b±ÂÚ!‘MÃuÝ0›Ü4Müü‡¬ë:AN§Ã1~&C¡MŸÈ£tÆA€ ds¹p<A–‹ÐM“t:M.›…tšx<Ža<õÔÔ¶ka|Æg9Å_XL¬a†š.mÛûCjšFgg'ñxœD"1ñÙ…Éd!»Ä{ åãPøþÛÄRЃ¡×³¦Y(YP~q³³%R˜Š¡ž/ÅÌb†Ót´ø9ƒÛpì"M¼¬†š?÷j|J¬x©'†äWm e`‚C EÆlîôÀV™ßô¿åÉ^È E5S5‚ ˆºf+W®dÑ¢E¬_¿žÖÖVjjjFôé%=Á¶m4Mcíi§a¿ðúûÞG·lЋÒ*J—O¥„ã´©©4ŠÝ0J›¼G¾$“…T㜭ÑhÁ£R.à z] F¸llš¦Xå#Ÿ\×aeý¡m?Ðc°ïeåˬäoÚÅN yìå¶õ²e5<øà[øÐ‡jÐõÒ¼ƒžÚ%¿`ïÇgñ:©<ìáE³ó;÷øAH$X,3O ƒºvÜÓ"f¼#ú°óAŽÃ0Dí³ÁDS•*­ýò¨¿½ää“⤓þ‚®Ÿ:n—@×᯽/Ó7¿8€þðµø~ÿP±â#–/2Ð5Š×¯g‡}•¹{ÛzV4S<e(öv|:—ƒ{ø=àEA¢AÀÝ_øÿÓ×W(Dÿ^Ëò’ÊØc4 :;É Ì y ã$yé3øÿ9çÇÓÉþz`òÿž„?årNË,ÔB…÷Ïz?‡m9Œßüä7œùÊ™¬ÿæz½èPæ_5Ÿß½çwL«›Æ§¾ó)pàÖ#neÿ­ûc& Ïqœ°Ì"À>ðLÓä‹_ü" l¦U«V±aÃ,X@cc#‰D",=*ûéºÎ“O>¹O.caÛgxF£{è)ñYxžF¶O¹,2Ù].fȰäâ¨÷âÏ¥tdtø@ßAË í?üðÃÿþ÷—>‹áåûWÈ’£ñh4,#œN§CG€ àò}Ÿx$B.—#™L†Bt2™DË÷a”âµã8hšF2™$‘H„u]×±m;O²ÄŸïûA€mÛ8ŽÚü²W <y¼RÕu×uÉd2Äóv‡ì-Y__OT~MaÆb|…ÔŠ“(2 ‹3Rr¹\IiáŠõ9J$ ™…óGtØ“½]üšm#Küî©éª¢bŒv|Xk–ßÞeoÙÏs Š·ËÄ=…BQÊXÌî~¼]pÀ4½Âº ÆÏ÷§V(ª™Š *5$jii¡¹¹™žžêëëGUîkOÍèå¢cOÑ´žçFÉårèºÎS×_φ}Œ3ËUº¾ç†-ùȳ!gäb‡Ôž¢q²ÙBDL·(V1dz¿\(–•p‡D"ã8ض.åBM–3ëìì,1è«•ÑøFÚ39‘Ð1MoŸ0ªk¶·ã³$ÌC8}@‡šoÖ`~kà Ó÷}´xœ4àkšp M•Z߃+Ó,¤_•—'€Bæ[±è:‚1zÄyøá…ã~jÿ ƺèàp›tø e•W$ B¨=âÀ#xà…ãz>Õ¸ŒOÒl;_1òùÜ÷¾Çœ{îáøtº$ÒÚuÝP˜WŒ ¤.ßÑ(ÉÞÏÖ!hŠÍŠñ s@ÝË™‘|dë¢SÙ½û9î¹çQ^ŠÌ~°–‹gŸÁŠ¿}†™=3éë9† ðÐâ7ßú Íšy¼ýqŽþÚÑà†on`–> ý{ïÁò,ö{p?úÎî£æ/5üù»æüÙçóùßž/ý¿/ÑÐÐÀº­ãÑ]ÒpAùË_xøá‡©»¯Ž[ÿs+MMM#¼"ÕÍxض2<‘ŸëƒV+îÿ a×®]´>×Êw_÷ÝJ_Í a´cSVÛéì,ôM*XÝó<ùö#¼ôàKäþž«Lö˜EdàCñ$ ëIÁDÓúÕq}¦£ƒù™ŒXP§Ó<ð»ßQc…ÒrÝÝD"‘0SÊÈ;Odß Ó4CÃɧø¾O:.ÉöÙRÒ¶s]7Ìð}ŸH$Bww7žç…}¢,Ë"N£ëz˜ñS<§%“It]/52eµÙ¤0âºîÂHq&ØXÙ=ÅY0òXä1èº^•=!'‚±R `‚kÅEò»)|UsíqDNY&²¬Â—¶‘ëëá€î Œf|| íÛ=Mr(ì+AyбÌ~,ß§ø÷`¯#ç‰,;Psq)fÈ1 ç')ŒHñ_¿Gñ±Ï“C×uKJ`–ûŠÿ–U\$Å ò1$í‰SN9…8 ÂŸæÄ°·sgð ˜—ÌDß÷¹âþûaÛ6žøÚ×0\UAPT=U'¨ì {  ‘廫A+#× ÃÀÔ4‘î’Hˆy2¥_ˆòsÕ4޼ýv0MÜÿþo’É$E¼#_*á€T Ó41M“~8Ÿ~ó›A×ù×7Ò¹ÿþ4D"%J½Œ´L`(*@±oàû{!¤d¥›ò_…÷»ïÇüŸ¿32Zoz<¾Ïw{d¨zËP(‹‰põò†˜ù’‚÷x~¡™§l˜›H”6ê,^ýKï€dyð5ܯ¾z>¾?bÞlªáBz.èB¬ÞǺù è­W‡ÂéSìè‘ ˆt:](}©˜xòã´Üa``Ü{6øõày$ùôÞŽe- ÷I˜ 7 ¾Aìµ­›^ÍÏ7„/ù1Þð†™¼òÊ™üòÇ]ìÚ2cÉÑ8N’ûî»îÿÇ¡þÌ{ð¼Ûh:# õð®ÿû ¿½|+ÛúïúBû6  ‚  7ÄϼÀÙg_HCºPÉqfòÈKÿáÈÛŸãÊ++}1«ÙbKúã˃ÆË‘™Õ·,¾…ú¯Ös vàÄt$"æ“⌒â/©läžp]—Àq²S^¹ùfbóçsÖâÅœÚ×Çö9s¸0/ X–Š .4MÃ÷ýP¸(Îú(¶¤p`F¡H‘ãIJ¬p} ëzx3 ƒîîîpQ?T‹á”U+.Ç5œýÆeƒOÑhÿX:÷ˆ)¾£É|V”mÛôööЬmÂïJ1„£´šeëF]IAúuµ²m£¸ö²|¶}Óé4–e…åb'°ÜfFXŽq '³|-¹Î.îKæÖ—IR¼œ)gÈþcEŒa+Û½b C§ÊŸSœµY¼O±?Fþ-÷-w^‹Å gM.p¡ Ž´O_µ#ƒ,ŠçþŽŽ:::*}h“ç‡`½­0Î^ÉåÐêë!“áÛðÞ¨PTSJP‰FEß@ÈfŽì kLËh0³Ø8Éå@Ó0¡p=(]V¼”ûqW—ˆܹ“ųf‰Ã|™ƒ»~ùKNþÌg8ÿ°ÃØøÄ\qãÌš?ŸT*…ïûä ƒ³/æñžž}6Ÿ¹ãÞ~Í5ضM*•"N³ú³ŸåùÚÚ0¢¡8b Î}&CaŠá|´g€ƧçyƒFæÉÆ©Õ?6‰†]ùý.ö´Î\iÖA>8\iÈ›ü]>îG„LFQà ȉº²Á/ Þ rL• pÁç_ÐÙf#•°„˜"`Å÷Üt:iš•«é®yaU³¬þ÷Ï|†‹,îߦù´¥D‰$¼n>yÏ·Äßæ[­°øgä(æÎ‹¦5‹ç&/„Ý|þø´ž¼óù÷‰FVèàÿ¶\¬DúLJ¾Îµµ•¾RU‹,Û&Ñd; ð7ÿ[ƒçNzŽë﹞ÎÅhOi0Õ&d&J~ñ<=›EÓ´°‹ï8¤ŠÄ /Ý)ËdÉ´º®‡å¦z{{ÃÈØ;W¬àMŸúÝ—]=g|HÛ¡X|Ø“h0Qa*EH*Qe €4xÏÁð€8`‚±Ì^xæó;xaÓcüõè¿Rçבʦ áÈ·Y|¢Iœ$ ¯$ý±âùýbù¿ƒüßRHçŸãå÷3òÛ‚üv qÿ0òïäÿÞ¡A´h;¿Ÿ<ŽLѱùǬüqɯVÈæß[¾v6¿¯ßßË¿ŽNá^æçÏÁ ³6¤æ|>] ºØrúNúÞI<ðÑØòË-Ì>c6x`&·y;Ó{§óüËÏcä 6œ¿mglc×A»8úº£Ù½{7½ð¯<ºëQ–ß¶œ€€‡Îàç¯ÿ9ÑiQ6ÌßÀñß<ž wðƒÿÁâGÓ3³?ë³xùbî½ô^^ûË×Ò;·—§æ=…é™ó ½sæŽD†#wïæMÿøÿûÉOrìi§qß}÷ñφ†0B'‘H`¶msѹçò«_ýŠá ¤ÓieòÙð¥/}‰îÎn–®\ÊÖ÷må eqrÛÉÔÜSÃúìÿÓýÙïÁý˜uí,Ð`™¾ 4¨{OOœû¿ùqŽþÈÑöÖÃxâkO°õ¸­¼Ú}5¯úõ«è{¢?¯ú3ozÝ›¨=°– ×nàÕk_ÍÃ7<̬æYtý¬‹ƒ—ÌŒ¾œý¦³ynÙs¼íê·A³¸´‡‡²óÓ;ÙyàNÚxKY*®{Bœó2;Ÿ úK¨qj@ƒ3Í3! 'y'A·øÜ´@¦ûÓYY)®›ü|MñûÌ[Τçåæ¿>0ßœÔØ5\öíË*ýͯZòî†qx]‘…ä8N(xȹOöÏkVYªªüG‹ÅÂ×Hä–Ïß[1¿ü}ŠªÁ‡ÄÕ…‹}B²çêxdê*cÍ”T€håÂ0ÑʲS<„áéÁ¦ºMD£Q:;;K',×Î¥8â®o†‰DXÂÁó¼~‘̇–=}á™gÂo~Üë¯ç#_ûZ¨ôëº.œ«3fðé¹sÙ¾};-Ñ(^>[%‘Hðó~”?ù ï{ôQN¸ýv^=}zI 2Û¶ùp{;sæÌáñÚZžY´ˆ×ö³€ˆ¶þâßÈoþsÞ|á…,8ã »ýv~7cFhì„Çl¹ë.:ûìñ±Ö¦(þ\ÐÏî¿}°¦Ö²|Gh*GÊØ0ÖFu¹ …þ.–%œ©Å™~¦Y\@¼¿6‘(/ÏÉ—}<’Iñ*UV|?Œ¶/¹o'“\¢Ò®‡Ä­ã5ÂFÉgiÛvùV¼MõMQ” K „üî "Àm~ýëÙ¬Æç€¼ð«Ðû€„3S¢ýÖ„ #ûÜi9&ï-³„‹³·¥ãÄ{†ÁŽ[oeÚœ9a¯’X,Ö/“¸¼ ¬¼Ÿ ÷>¢ßçŠjB 2KÄà)hj‡Äy`9ŠÐáò­—×ò“Ÿ|Ã8Il7Žt9DŠ¿ê±¢ÿ¢¿cA#Ei)‰~àã¦%²ÀV6®dÚµÓ¸Y»9tR¹IÑÃgçëvò¾+߇¯ùⵉ¡ë°aÃê ñ=Ð b¾'¢Ý/Ûÿ2>úÇò÷¤½4 3A´.JÇYÜ•º‹MlÂqr¹Ñh”T*EÍC5Ìþòl¶ÿi;»ÿ¼›ÅÁbt]gÇ70íàiÜðå¸ï£÷‰ó€& ŽÔŽ„ŸÊÓÓàÒÿÏ޽Ƿq•yÿõ–¤7;“–ÞRÓ2éÝ.—Ž[Š Èx›´@!02ìrIx‰Dw¬ ––nwé+C7À»  ²\¶ö@ʶ õp)%Чj÷Bë¡©Ú”Ö»i“¶´zÿ8:#É–%Ù’­‘üû~>þØÖe4£Ñ£93Ï9ÏÛ‰)‡–¶¾6üyß¡§rwühC›øûÿ(žwÙu— þH³ßs¶ØUŸ*øÂ5€c#Çú‹]©—ÇZÇæ¿e³SŽú‰¡è9@ÁmS÷³L†E¦‰›O¼c½ƒ´ÜsO:Àc1‘œQs·UYo“9¨ª…¹ë#ׯǷ֯Ÿº À²ÜPÜ G£ØþÝïâe—\‚C®¸+ FÎËrcš¦AM$ÄDQ°ÒuqÃwøI]×qä±Çâ¢eËpä-·`g4Š#Ï=J_Ÿ_²â¼å˱zp§¼ð¾ÿüóÐ5 ¯xûÛ18<Œp8 ]× …ý––ûe@]>ývÏóüºé…’É$<ÏãÚf (å‹åî/ÕëDÎSêb›,_Vê;EÎ3µW}$‚oîÙƒ74ú} 0ãN@ùѹ€’·R%2å„ÎìéF4ÿTŸüŠ“)<ÏCOOt]ŸÞ)h–âñ8"‘ˆßž‘'µòBŸwD–âÒ4 Šmÿð@A[¯î%xQ‰‚JŽÒÐà_8wlÀè-n¦8ŽÓ6ËÃÞøÆW/g¦ÜâL·«£Ÿ´YÓ4¿Œ^<ÇððpÑ$Σ'ŽÂù°ƒX$æÇg,ƒçy°< Q3êÇ·¦iþw¢)p’bdªmÛ~oáûn¾›°É/•-KõÁÎòÎÔ|ÒÔïT7‘Û¬‹Åíò;kåW–ÞN%¿ÓÌtz gýà¬Ò÷Ít_îÂûL×ó"ež7ÓsÊ}••ÛÎRÕÇ`óßlÆ6lMWnBúr\×õÏýÅÿŽ;n-^õ*¥âq¶Ù ²ÿ[®ÿ(\7?噢WlÛ+n›ú·$—ãyùSÁ©Ó3>¯ðñ’¢ˆÛåct=_…ºÔëä'6Ïo“,† ‹&D"ÅëjÛâtTöå“Ó›¦Xž\V$"ªbËÓrÙr\W<Æ4Ý»OÁÉ'6z—žµýôå_¢ßR)¸®ëc¢Ñ(ç餦Ñ2 í@ý1¦Ÿ|À%«.Áð׆ýDKæ¶ ¶ß¿]ü¦ÿ<çx"¯AÔŒBôD*˜L‘Üm€?<.òuaåã¬ÜïÄÐhY—ÖB¾^ª|-7÷\91aaZYsVÖ¹ øu­p8<ï%›îxá\ñýïcèCšv_ÑëÊ†Žªâ]ºî÷ê”_Ömo|#àÄ\/ÌWNi4YÝݘPUtX©i~Ûwll ×¾ãxê©§ö>ò úûé·Ë2|… '“%ªš,-4õ»†ÿ+ŠÞ M9G”ªN&)'”$¢ù÷—£ÿåêÒ÷ÉdJ$™UòBvbÇY9’ŒëÁÁAQfËó`YÖ´ºì€hW.áw-BíO¶‹s°)IYÝP’sÈxs ÙÉÁ0Œ¢ÉìaÛ6EñËqÊvµì”$ãµÔhpß‘H¤¨Ý]ªÌмmêrŠÎµr#çj¡š} ñ:Ax?›aÌ®ùoÛ6lÛöçôʶÔ`Y€a\Œd®œž¼h.yžx=YÉXQÄ…ùx)•ÓNb ½e_Ø×4±Î–•L<^œ„ÉÛ«ªxÂDÂà xžãˆ>frP©×‘}ئ>F¾¶|/å¶ùê­òµå¶&:dr¡°â«¦•N†ÈÛt=_A¶ð~E)~ÌÔeÞVX¹¿\©KŽ“OÌÈõ-L˜Èç)J>áS˜ø™š(:é¤Õø+pö>‚ØW‹Î{²s€mÛ%ç¼& ª–I¨Xw©OY¶¤ð¤ð x†††J_èWì÷f¦¯¡ÂÓ³RM”j¾¾ SêñS—[éufzÍÂç•zL5•J Þƒtz¢òƒ3 p^åêMòÉ@Œš–Ç9¢fÐ pfˆ¹Â AŽãøsz”5Q.0µfëLC~Õþ/Ñ£©hå® ÊZ»S¶Qä’‘€I"?šÅÊý–“Ê‘3r¤L´DP—ž7 õEèNíP…Ùž€È“™R=¼~ôÞ÷"tÒI ²­ÍÈsýŠâÛ6n͵A5M@Óð‹»ïÆ¿ýêW¥/ÚÊ9˜P!ª¯¯8ˆ¼ À:ÿ¦ÂÑ)rTJ©D2ͳîîü…MMþ /DÏ¿ÿ{þ­ìf)¯æ&“°sLäü'ëﻇÝ?^8åìݵ —üãÅW dwX¹M+¾’`šÅDwTiÛuÆ=ØýpÜ÷ºPŸ¿æï_ õâÄbË¡ª¢\ÉٷߎŸ¾âh³¬|²ð*¦ëâÀ¿ˆ½{÷béîݸõÁѹe ¬›oF"‘€a8ûöÛ1¤i€e‰¾q–5mEÝå|×uÉ4§w¡žz$»†Ëï&K©™Å‘ïP*¯(ùŸ_\ÿ ÜvËmxôÀ£øØµÃé§ŸŽK´Kò×Ir×zT‰wŠEêòù[àï< `<÷—ª‡üõœ©—(råèˆë-ñ)÷Å ®É¸† ®ñÈDïH+ç–×w ÉŠ(NîoùxIV=‘¯=Q°‘r ¶E^SòÄûS´þƒbÛýuúÚ…ëZ¸=òµ]ˆNÇ…ëQxM*ž[F ùdYªàõå6ËŽÃrßVy™2§è91¿Or 3”ÛF ß™Z&ïäçÍ.øï ðäÛž•¡CF~VåÂùúähi¢fÑ Çô3öXž¿Ñu±÷üóñ‹%K°2Å‹>ˆ}'œíË_AZê$±{à*(]¯µÔ‡²},6r‡|¢ÆF¾Œ™<˜äzS¹ß‘‚çOM0ÉIeÒHÉý?µLY¿'âbŸ,•Q×Úà‹„1q#ÔoßîÏÐéy¾»};¾óå/?އ¾ÿ}¼˜>ùXOA«Šï;QÝ9ÿ» 8,ÿÿÔÑ)ÉÜx~ÎgDÔ©TÑ"‡aF¾¢ë~rÄq>Û¶ý(gÄî+K½F¥ØŽDŠ¿²îÑ"ö†nǦÿYO]ŽTì%üà@;ú­oåG|È„ D¬*Š‚úÀp套bø—¿D$‘@/hRo}+€\i­Â3ÀôØ›:2MN|PHŽ`sÝüß…§¸æ÷Ôì4”œgÇU\Äãqxž‡ÔJ”$/<Õœ©Ãll†¿¥jæÑ.¼ÜTª#­1ÃcgR깚ç UxüÔå&氌ٮk¶Âó<ˆ¤†±Ÿgz}Yb?2Ãýs}ŸJU¢š²ïxÿØõ“]U,xñ²ß Øëò‡Çq‹Å`š&ÔjGIDK$T¼ßìƒî|ð¶ø EOQн|9†‡‡áæêMßrK~ÔÄÔ“ÄVUª–l?”Úü„]ðX™\‰Ün#ŸT‘Ù{ ß«! ÑØ)ìéàBô(ì {…ÈõCu çªAÁmÑ‚urr?òùrÄŽ\¶|ÌÔ÷@n‹†â2hŠOЧ`05X<|˜*:åSÞu>Æ®{£[2™ÄÙïyŽzÛÛÿ7w6¢©œDMÄ9è<Ýÿ_–'QÑh‰D‚C®‰¥ ™bš&<Ï+ž¿b„®}-“¡ñÜÅÑR#jkÆï"ì9ùd ¥„¦ à\¢C‚œ~j'9Ùµš‹×D"ÏãPUç}â3¿P¥rÆ3•ú›ºŒrËÑ4¶·©ÅX€«Ô2MÉdÒŸ#eQÉ`-Ri$[A‡ ßÔÉV¦>ƶ§OP25A;õuJŒÜ›6ê®ðuÿhÛÅ#N¦¾Žjæ,_gê{RÍöÈ÷D&¿s5ÎÎyTʱŸÊ¿Õ²3ªªÐ4­ä^DAÖ ûVúûz‹Nôâñ¸À”e¾xah– £…çðòxTØ>B~HçÔe”zÛ½Ü2 ï“C& 䇓N%GË(¹×´P<úÅ-xœ‹|ÂDþ-9½Häí1ä“BnîµcÈ—NÓ‘ïíàA {Í­çÆÍ1zÓh#öPà-¿oêá{¥@qx9Yg*•bl5€÷ø$ôO @\ð±, cccp]ªª2.‰À¶m˜¦YTS&R’É$†‡‡a†—%úˆæ_aŽÂq„s#ÈdÊcªëº0 cÚ…"_‰æQ8W›ÉópÛqÇÁ|þy ‹¸›:* Ê ƒZίª¥ËaÅ•q1½ð¢}5%3å òÒÔשf] _GÞ>uò>Ç™¹c„Á&çU›JQò3ÒÓKªju ÞråœJ%‰§>~½ ¸³|J£ûJ=¦šíÑõüÈ@9ªð±Ç@åEÞw  _ þü¹…ÇK¢f¸„J&“A&“AGG:::ªz޳ÿPÄþù"ÿÿd2 Ïó‰DL&ý‰ühžMM¦”û>,u,×§Ü_¸Ë Û0Æ —R¸ÌR´ —;S-Ù6ša2²­‡lE¡¹¾kMe¶ñ¹çOOC;íiÿÿh4ê':åA“'•Dõ1Ûøt–¼±ÞˆN±X –eÁ²¬é%øˆhÎæÒ¶àw<tZ–…x<MÓ‰Düò|D4wsO ßó]Ö}·,Ë/Ìã(QífŸ†&~÷;¼ýÀ_ŒáÂC5£²‰üüdSG.He–áº. ëð4 ªªâ·Ý†Wžr ~ëºÐÅŸ„ûÉ'ŸÄ¡Ÿûž|ñEÿ|ØË•t]š¦ÁŽD`†ßN7MZnŽCEQàª*\ÃÀ§ŸŽáT —]v¶ä+Gž›ôÜcu]‡y¡ª*\×…®ë0MSç­o}+žþùF‡Î¼›kl:ßIC=é2âjî½÷Þù)SK´²ÒÝÝݹsg6›ÍfGFF²gœqFöá‡.ûœ¿ù›Ïe#ï?Íf³ÙÁÁÁ¬ªªÙ÷¿ÿýÙáááìøøx£7‰Í›7ûŸÛV6ÛøÜ¹sg6ÌŽe³ÃÃÃYUU³Ñh4‰D½)´ˆ¬_¿¾Ñ«° fŸò}Ϫªšýá˜ÅbÞ ZDvîܙݼys£WcÞÍ¥m»~ýúl$ÉF£Ñ¬®ëÙ¡¡¡ìððp£7…¶mK“ß[‘H$û®w½+»iÓ¦ìàà`6‘H4zShaÛvæ÷e||<«iZö³Ÿýlvxx8;44”ÅbÙT*•Õ4-;66–ÅbÙñññl"‘ÈŽg‡††²ãããÙñññìØØX£7›šÛ¶3[¿~}6±ô‹ÙDäÉìððpö•¯|eöâ‹/fû–Ì|´mntBGJ§ÓhooG($J'uvv¢³³étºìó<ÏBâºgÇñ‘|ûØÇpÙe—ùÙâfÑßß_q[›Å† ½ ÜŽ:›K|ÞsÏ=ð< ¶mâío;–.]Н~õ«MÙû½U> üžiMs‰ÏÑÑQ¸®‹7½éMP÷Þ{ï´‰t›A:F£W£.Zå3ÝJû¤VsmÛ>÷Üs¸ùæ›ñÎw¾‰Dº®û=J› 9ÁÓJû¤VsÏŸüä'¸õÖ[Ñ×ׇsÎ9†a4åˆk~¦ƒ§UöI=Ì5>ßûÞ÷âì³ÏÆää¤?Ùu$ñËdªªŠD"á8(é ”µjô¶·J;ªU>Ó­´Oj5ר|ÉSOÁ|n.x×øøâ‹‰DðéO:0íÛ Kšá3Ø*ñ>)ù5:::­ö^{{;2™LÙçíÛ·Çs N=õTœvÚiøÕ¯~…%K–à–[niô&ÍÊž={ð›ßü[·nmôªÔl×®]-LÕlÇèè(8€•+Wú•V4—ø¼÷Þ{qÛm·áÆoÄ¥—^Š%K–4íç¢U>Ó‹é{fß¾}صkž{î¹F¯ê¼›K|8pçž{.Ž>úh¬]»÷Ýw_S~Æ÷íÛ‡§Ÿ~£££^•šµÊ÷L5ûdÏž=xì±ÇpÆg4zuçÕ\Û¶wß}7ÚÛÛñï|§Ñ›P“ÅtÌiÕì¶mgŽÏ]»váOú–.]Š/ùË€_ýêWÞ”9YLŸéfQmÛöÀ^Õy7—ø¼çž{ðä“Oâ˜cŽÁ¡‡Š={ö4e|²m‰‚‹ñILŒM¢àb|ã“(˜›DyI¨tvvN ĉ‰‰ª²D4¿ŸDÁÅø$ &Æ&Qp1>‰‚‹ñILŒM¢¼À$TB¡&&&ü‰€FGG‘Éd°víÚF¯Ñ¢Çø$ .Æ'Q016‰‚‹ñI\ŒO¢`blåfèëëæM›ÐÕÕ…‘‘ôõõ¡­­­Ñ«ED`|ã“(˜›DÁÅø$ .Æ'Q016‰„ƒ²Ùl¶Ñ+Q(“É “É ££ƒÃƈ†ñI\ŒO¢`blã“(¸ŸDÁÄØ$ `B…ˆˆˆˆˆˆˆˆˆˆˆ(h3‡ QP1¡BDDDDDDDDDDDT*DDDDDDDDDDDDrõÕW_Ý蕘«L&ƒÑÑQ@{{{£W§ì:ÊI›2™ ÚÛÛ±téÒª·£ÑÛ999‰Ç|ÖëÄí*µ-µî£FïŸ j–÷¤öýLñYkü-ô¶UÚŽ™öQж£4Ë{Òìû~®ÇÎJ÷·Ê±³QÛBµŲeË궯ús _orrÇw\]×u!¶¥šãe© b›iÑÜ”ŠM ¹ö}¹ø zÛ¶šãþ\â³ÑÛEõ1—ø Ò¾¯åØYëvÖÃ\ã3èÛE•Ígû¨ÞêÝÆ®—ÉÉI8Ž3/m禖mR7ÜpC¶»»;»~ýúlwwwö†nhô*•ô‘|${Ægýìܹ³êíÂvnÞ¼9»yóæi·—[· nW©m©eaÿM3½'­°ïK}¦k¿FlÛLß3åöQ·#èšé=iö}?—cg¥û[åØÙÈm¡Ú<üðÃÙîîîºíë…þlÞ¼Ù½Õ«Wg¯¼òʺ­ëBmK©xœº]oûÛ³M¹hnJÅf6Û\û¾\|6CÛv¦ã~-ñ„í¢ÚÍ%>ƒ´ïk9vÖºõÜ†ÙÆg3l•7Ÿí£z«w»^FFFæ­íÜìš6¡RøAÉžqÆÙ‡~¸Ñ«5Íúõë§8g³ÜÎn¸Á¿`RêàSnÝ‚¶]å¶¥–}Ô,ŸÃ…ÔLïI3ïûrŸéZão!·­Ò÷L¹}¤íhÍôž4뾯åØYéþV9v6b[¨>ä Qá¾o–ÏôÃ?\´ü‰‰‰ìgœ‘©ËºÎ÷¶Ìr» ·cõêÕYÓ4›nÑÜ•ŠÍl¶yö}¥ø r۶ܱ²Öølô÷ÕÇ\â3(û¾Öcg­ÛY«Zâ3ÈÛE•Íwû¨ÞêÝÆ®—Â÷lbb"»zõêìöíÛ«Z‡Vƒ¦œC%N£½½¡PÐÙÙ‰ÎÎN¤ÓéF¯ZÉu-5¬¬šíhôvvuu¡··³Z÷ nW¥m™Ë>jôþ ¢f{OšyßÏô™®5þzÛÊÅf¹}´íhÍöž4뾟뱳Òý­rì Â>¢¹éïïGgg'ºººüÛšé3=99 _n ­­ ˜˜˜¨y]b[fŠÇL&ƒP(Ttûš5kªÚ® í#š›R± 4×¾/ŸAoÛ–;VÖŸÞ.ª¹Ägö}-ÇÎZ·³æŸAß.ªl>ÛGõVï6v½¤ÓiLLL`ãÆDüÛ¶5kÖT\‡Å‡6zæbtttÚI|{{;2™L£W­ˆ<ø\uÕUH§ÓhkkC__z{{«ÚŽFo§üâ)Uç®ÜºMNNn»fÚ–ZöQ¥í\Œý™fß÷3}¦ký^Yè}Xî{¦Ü> Úv4ƒfzOšyßÏõØYéþF|ïÌDZ³šû)xFGG±cÇÜxãØ´iSÑíÍò™îììDoo/®¼òJ„B!?)(Oô‚Þ¶)C¡¿ €ˆÏ;vø'¿Í´höfŠMy_³ìûrñ¹uëÖ@·mË÷k‰Ï |ïPmæŸAÚ÷µ;kÝÎz­¿\îTåâ3èÛE•Ígû¨žæ£]/™L]]]ÀŽ;ÐÖÖ†ÞÞÞº´[ASŽP‘ÅB3õ’l$™ݸq#î¿ÿ~lÙ²ýýý~F®Òvy;Ë­[3mW-û(HÛÍôž´ê¾¯5þ‚´måöQ3mGP4Ó{Òªû¾–uÒvµrû†¦›œœÄ¦M›°eË´µµÝ×lŸé¶¶6bÒ©'­Ð¶Ý±cÖ­[‡P(ä'8›mQõÊÅ&Ð|û~¦øl•¶ílã³Y¶‹J«%>ƒ¶ïçzì¬u;ÒÔøl•í"¡Þí£z™¯6v½d2´ÉÆÑÑÑ 6øI‘ÅM™P)•]b–«³³Û¶mó³w¡Pk×®õ/8TÚŽ og¹uk¦íªei;‚¢™Þ“VÝ÷µÆ_¶­Ü>j¦íŠfzOZußײîAÚ®VnßÐt¦i¢³³Ó/111ÑÑQŒŽŽ6ÕgZö®»ñÆÑ××Û¶122‚­[·Ö¼®þLONNbÆ èïïÇ5×\ƒk®¹¦êu Ò>¢Ù)›@síûrñÙìmÛ¹Ægз‹Ê«%>ƒ´ïk9vÖº a¦ølöí"a¾ÚGõ2_mìzêèèÀ–-[ …üŠ×a1ÄAS&T:;;§íˆ‰‰‰Àe»d¿PaÖ±Òvy;Ë­[3mW-û(HÛÍôž´ê¾¯5þ‚´måöQ3mGP4Ó{Òªû¾–uÒvµrû†J›œœÄÖ­[±uëVd2lß¾Û·ooªÏt&“AGGGÑg5 ù=èš¹m»~ýztttÀ¶í¢òÕ¬[öÍÞL± 4×¾/ŸÍÞ¶k|}»¨²¹Ægö}-ÇÎZ·s!̟;]$ÌWû¨žæ£]/¡PhÚÈ™V¸fV7 0ñý¼èîîÎîܹ3›Íf³###ÙîîîìÄÄD£W«È 7Ü]½zµ¿^ÙÕ«Wgo¸á†ª·#Û¹~ýúìæÍ›§Ý^nÝ‚º]S·¥Ö}„ý4Íòž´Ê¾/ŸµÆ_#¶­ÔvTÚGAÜŽ k–÷¤öý\Ž•îo•cg#·…j·~ýzße³Íó™Þ¾}{ÉÏ­išuY×…Ú–™âqçÎE??üpÓí#ªÍÔØÌf›gßWŠÏfhÛ–kËÎ5>ƒ°]T³Ï ìûZµng=ßÿÙÆg3lÍl¾ÛGó¡žmìz˜˜˜ÈvwwgGFFüÿ›ñšÙ|iÊIé ¯¯›6mBWWFFFÐ××W²6e#ÉÉs×­[‡ŽŽŒŒŒ ··×¯ÙWÍvy;Ë­[³lW­û((Û$Íòž´ò¾¯5þ‚²m•öQ³lG4Ë{ÒÊû¾–uÊvµzû†f§Y>ÓkÖ¬A:ÆêÕ«ÑÕÕ…L&ƒÎÎNrÒZ×µQŸéL&ƒL&ƒ 6ݾqãFôõõ5Õ>¢úk–}_)>›µm[k|u»¨>šaß×zì¬u;çS¥ølÖí"a¾ÛG ¡Ñë×ÖÖ†¾¾>þ9f+\3«‡ƒ²Ùl¶Ñ+1W2@:::=lhttÔÚTj=+mG·³Üº5ÓvÕ²‚´AÑLïI«îûZã/HÛVn5ÓvE3½'­ºïkY÷ mW+·ohvšé3-_¯½½u]× ¦›iQ}5Ó¾/Ÿ­Ô¶Íº5óvQeͲïk9vÖºÔªÛEyAг ®ß|¶›YS'TˆˆˆˆˆˆˆˆˆˆˆˆBSNJODDDDDDDDDDD´˜P!"""""""""""ª€ """""""""""¢ ˜P!"""""""""""ª€ """""""""""¢ ˜P!"""""""""""ª€ """""""""""¢ ˜P!"""""""""""ª€ """""""""""¢ ˜P!"""""""""""ª€ """""""""""¢ ˜P!"""""""""""ª€ """""""""""¢ ˜P!"""""""""""ª€ """""""""""¢ ˜P!"""""""""""ª€ """""""""""¢ ˜P!"""""""""""ª€ """""""""""¢ ˜P!"""""""""""ª€ """""""""""¢ ˜P!"""""""""""ª€ """""""""""¢ ˜P!"""""""""""ª€ """""""""""¢ ˜P!"""""""""""ª€ """""""""""¢ ˜P!"""""""""""ª€ """""""""""¢ ˜P!"""""""""""ª€ """""""""""¢ ˜P!"""""""""""ª€ """""""""""¢ ˜P!"""""""""""ª€ """""""""""¢ }BÅ4MضÝèÕXT<σmÛp§.Ës]¦i6z³h0>›‡ëº%ãšñÙ:ͯšxô<®ëÎø|Û¶g¼Ÿ‚±ÚËŦ¼¿T|Î&æš!>ç#6åûW)VJŧÜGŠ¢ø¿UU±P¸ï›ÁÖ ñX‹ò3Wø%͵/5MC$¦iÓgÛ6E®ëþc5MkÚb­¦bà±³šc'ÀXm&µœwÊûƒŸµK«9Ïœ¯ø¬tîY*6åû^í±´06Æg3›c)°¸¯Õ+V —ÅóÐÅ¥Ñ×ogûØ™).«Ý¦¹¶qå{?—ãhÓÅfvËÈ&‰l6›ÍÆb±,€l,Ëf³ÙìøøxVQ”ìàà`v||<‰D²²CCCþ}ò¹CCCYEQ²cccÙl6[´œD"1íut]ŸÕãª!×mêßÕËÅf6›-Ÿ³‰¹fˆÏùˆMùžUŠ•Rñ944”D"YÃ0²©T*kFÑû4S|26ƒ­•âqjüµr<Ör¼”t]÷×QJ$ÓÞïR£…×J±*—Åc'cµÔrÞYxPâs®ÇÒjÎ3ç+>+{Λå⺚ØÌfŸÍf¾Ž¥Ùìâ¾NT¯X•Ëâyèâ„ë·³}l9A‰Ëj·©–6î\£Í›‹*¡‹Å²‘H¤è6UU‹>H…Á ?¬CCCÙT*•Õ4­è¹‘HÄnanJ~ ÿ/›ÁÖJñXkB¥™â±–ãeár¦^Ü)u²PØ¢Æi¥X•Ëⱓ±Ú j9ïÌfƒŸµ$T*gÎW|V:÷œ)6ËÅu5±)—Åølóu,Íf÷u¢zŪ\ÏC— \¿ícË J\V»Mµ´qçzm¶Ø\T%¿Çñ‡Jªªú{žW4<·ð±®ëÂqtÐAþO ‡UP¸Ý¥þŸé¶z¼îàà t]G"‘@$™ö>NÝG¦ ›V¥¨Þlá°¶©Ãæ*=—‚¡\|–‹M`ñÅç|Ä&P]¬L}ïo¾ùfX–…ááa$ ŒÁqœ¢ÚÑ3Å'c3¸Ó·»Úÿëe.ñXÍóÊ/gRêu«ÁÀX¾ÝÕþ_/ }ì,‡±µœw­ŸÕœgÎW|V:÷,3@ù¸žKlÎôZŒÏ`à±túvÏôÿL·Õãug{ˆç¡­×oKow©ÿgº­Vs=­ôÜV¹~»¨*¥j™N5ÓŽ’õN³bTÿ“H$½YMC×õiÁ6SðM5u¿L­¨iR©b±Ø´ÚŠ•žKÁP)>Ë}‰2>ëc.±òè£BUÕ¢XÖu½è¹3Å'c3¸7×ø¨åx9MÓJ.w¾.€Qõ«·ÐÇÎr«ÁQËy'Àø¬‡ù:÷œKlÊç1>ƒ‰ÇÒÆšk¬ò<´µñúmãÕ's=Ž6Sl.ª„Šªª0MÓß!ŽãeÆ Ãð'Ä0í>Çqüì™çyXµjUÑÄFTžlD¾‡–eUÕˆt]×ßòyrB? ÀÅbPUµ¨WB¥çR0”‹Ïr±)ïg|Ön.±rÆgÀu]ßÈç6lgŠOÆfp1o®ñQËñr&òä´p"n×u‹& ¥Æ`¬6ÞB;Ëa¬G-çò~ÆgmæëÜs.± 0>ƒŒÇÒÆšk¬ò<´µñúmãÕ's=Ž6SlÚèXH‘HŽã`ÕªUþ—vaFÓ4†îîn¨ªZ” SU±X ===þsu]ohHUUÄãq¤R©¢¿«Éä6‚¢(H$èîëþ{‰DªÚÖh4 UUẮ¿?J‘¯!÷ÍlžKS.>ËÅ&Àø¬ç:Ï6V^ÿú×cÏž=EûMÓ´ŠñyÊ)§06¬•âqjüµr<Îöy…ÇËJïE"‘@8†¦ip‰D¢êž¾4Z)Vå:ñØ9cµùÔrÞ />›ñX:çžS/¦Ï&6åãŸÁÃcicÍ5VyÚÚxý¶ñj‰“¹Gk}Í…vPn"™EÅq¿Þ^aÆó<x‘çyÐutÆÇÇýǹ® ×u¡(JÃ?ør]4Mó×}ê6ÑlßCÛ¶‘L&144Û¶gõÞ×ò\jŒRñYMlŒÏZÔ+ ×´pZ! cQÖ`mÕxœï¸’着,Q0­«…ëÂcgm«ÁQËy'œølÆcéÔuç±”*á±´±æú-Æ©¾xý¶1q¶ÙbsQP‘fÚ!žç¡§§ƒƒƒÐ4 ñx|Z=Ç…hø¸®[vÂ$]סëzѺÈu,7äX>o>Öe6jykêÔabT¬T|V›ã³˔ϛ­FÅ5ͯVŠÇÂõZ;ky^9¼ø\­«ƒ‹ÇÒú¯ËlÌõ= ZŒS}ñúmý×e¶q¶bsQ&Tf¢ª*R©”ÿ¡VUƒƒƒ ¾r¥rëYÏçÍǺÔûý˜kV2èMªNPbhÝø\èXal6/Æc}×e¦eÍ%>WTˆ±Zßu™iYŒ9š Æçü/¯–÷ƒqMcµ¾ëŒñÖ”ØlÕ¸lÄuØf‹ÍEYò‹ˆˆˆˆˆˆˆˆˆˆˆh6nô *DDDDDDDDDDDD0¡BDDDDDDDDDDDT*DDDDDDDDDDDD0¡BDDDDDDDDDDDTÁ!W_}õÕ ý¢“““p“““8î¸ãŠîËd2´··7úý!ZTÊÅ&Àø$j$Æ'Qp±mKL¬Y³çŸ>¶lÙ‚P(ä°mÛèèè˜qy¯~õ«qÎ9ç4ú}¬ÙÞ½{±lÙ2,[¶¬Ñ«R³={öàøãoôj,ØvìÙ³úЇðÖ·¾µÑ«\“r± `Öñù¯ÿú¯øÙÏ~†—½ìeÞ´šµÊgz1~ÏìÚµ ?ýéO½º5«w|®^½/}éK½Y5;pà8€åË—7zUjÖ*ß3Õî“}ûöáÔSOÅæÍ›½Ê5«wÛöMozN9å”FoVÍã1'èªÝ'lÛ–ŽÏ›nº _ýêW[â³°Ø>ÓÍ€mÛÚâ3ãÈ#lôfÕŒmÛàaÛ¶õÛ¶A?–4Ã÷BÐã}^Ú¶Ù´sçÎlww÷Œ÷­^½ºè¶·¿ýíÙn¸¡ì2Ï?ÿü…Ü„y³yóæìÎ;½u±~ýúF¯Â‚nG+ì»r±)ïŸm|nݺ5kF£7­.Zå3Ý ŸU©Ú}Ò ûn>â³UŽ;wîÌnÞ¼¹Ñ«Q­ðYÍf«ß'­²ïæ£mÛ*Ÿ…ÅxÌ ºj÷I+ì»ù8v¶Ê÷V6»ø>ÓÍ€mÛâûgŸ­ð¾Èmç÷L°°m[|_+¶mƒ~,i†ÏÖbÜÇ :)}&“AWW°aÃlÚ´ ét€R65£ÙÞÞŽL&Sv™t6lذ›1/B¡PÙŒn3‘½Jš]5Û±aÃÜrË-^Õš•‹M`nñù’—¼»wïF£7¯f­ò™^Lß3£££Ø°aöìÙÓèU­Ù|Äç’%K°aà 4zójÒÑÑP(ÔèÕ¨‹Vùž©fŸ  ¿¿O<ñD£W·fóѶݵkÛ¶Ó*ñYÍ>aÛ¶||ÞrË-lÛÈbúž‘mÛ]»v5zUk6ñ¹g϶m¦U¾gض­_ÛVλ4A?–4Ã÷B㽿¿^Ú¶‡.äFd2¤Ói´µµaãÆH§ÓذalÛÆÄÄÄ´ÇWó>çœs°mÛ¶…ÜŒyôà˜ÞÞÞF¯Â‚mǶmÛZ⤪\lvttÌ)>_ò’—àío;úúú½y5k•ÏôbúžéììĶmÛZâ¢ä|Äçé§ŸÞÇÎŽŽŽ@7~g£U¾gªÙ'½½½èèè(ºxÒ¬æ£m{Ê)§´D|.¦cN³¨fŸ°m[Þ¥—^ʶm€,¦ï¶mËÇçñÇßÇN¶mƒ‡mÛÖoÛýXÒ ß AŽ÷ùj·-hB„-[¶ÚÉÉI  ½½}Úc3™ :;;z‰¥™b³¯¯ñIÔ`ŒO¢àbÛ–(˜xì$ .Æ'Qp±mKTÙ‚–ü …Bhkk+ºMþßÙÙ9m˜ØÄÄDà³pD­ \lŒO¢Fb|Û¶DÁÄc'Qp1>‰‚‹m[¢ê,hB¥«« ™LƯ›799‰;vøõà&&&Šjóe2¬]»¶ÑïQË+›ŸD Äø$ .¶m‰‚‰ÇN¢àb|Û¶DÕYÐ’_mmmèëëúuë …Éd …üZk}}}Ø´iººº022‚¾¾¾i™Q"ª¿J± 0>‰…ñI\lÛDÁÅø$ .¶m‰ª³às¨ôööúAÙÞÞ^Tk¯ð¾f˜t‡¨•”‹Í©÷3>‰ã“(¸Ø¶% &;‰‚‹ñI\lÛU¶à eƒŽIÔ8•âñIÔ8ŒO¢àbÛ–(˜xì$ .Æ'Qp±mKTނΡBDDDDDDDDDDDÔŒ˜P!"""""""""""ª€ """""""""""¢ ˜P!"""""""""""ª€ """""""""""¢ ˜P!"""""""""""ª€ """""""""""¢ ˜P!"""""""""""ª€ """""""""""¢ ˜P!"""""""""""ª€ """""""""""¢ ]èÌd2Èd2E·uuu¡­­­èþŽŽttt4úý!Z4*ÅfácŸD ‹ñI\lÛDÁÅø$ .¶m‰*[ð„J?vìØQtÛ¶mÛ …000€þþ~tuuadd}}}èíímô{D´(”‹MŒO¢b|Û¶DÁÄc'Qp1>‰‚‹m[¢Ê<¡299Yt ,Ôßß-[¶  attëÖ­C(bÆ“h”‹M€ñIÔHŒO¢àbÛ–(˜xì$ .Æ'Qp±mKTÙ‚Ï¡’N§KZ:F{{»°èììD:nô{D´(Ì›ò>Æ'Qã0>‰‚‹m[¢`ⱓ(¸ŸDÁŶ-Qe šP™œœ\uÕU8óÌ3qþùçc``0:::-`ÛÛÛ§Õí›j×®]ذaÃBn‘oÆ ¸å–[½5+›ÀÜãó–[nA£7¡ÑÑQlذ{öìiôªÔl>âsÏž=ذaCÑrˆŠ,ðÄO4zUjƶ-µ¶mÙ¶¥`’mÛ]»v5zUjƶ-µ¶m«kÛŽŽŽ6zóhêï¶íœK~MNNbddíííèìì¬ê9™L¡P7nĶmÛN§±iÓ&ttt`bbbÚã«2vÊ)§`Û¶mucˆª±mÛ¶–8©*›¡PhÎñy饗¢¯¯¯Ñ›G‹Pgg'¶mÛÖ%ç#>?þx;©az{{ÑÑÑѽÙض¥VömylÛR£°m˶-Û¶å-ƶ­ëŠ"~ær?ÕÏ|µÛæ4B¥¿¿çŸ>6lØ€þþ~¤Óièº^1Û(rxX(ÂÚµkýacSUÊrQ}”‹MŒO¢b|Û¶DÁÄc'Qp1>‰‚‹mÛÙI&‹ÿ·,q[Oà8@<˜¦¸-‰×Ûv£×žj1ë„ÊŽ;000€mÛ¶ùÆP(„ÞÞ^¬_¿ÞVJ&“™–tikk ‚vj NLLpb#¢P.6Æ'Q#1>‰‚‹m[¢`ⱓ(¸ŸDÁŶíìØ¶H˜"yФЦ‰Ëñ<@UÅc»»Å}žW~¹®Ûè­£rfPI§Óèííõ³•ÒÆÑÑÑ‘‘‘²ÏÝ´i“Ÿt™œœÄŽ;ІvÊ^ £££Èd2X»vm£ß#¢–W.60>‰ˆñI\lÛDÁÅø$ .¶m«#)š&Ž#$ÃÃ@"†(ç•HˆÇ&@$"ž‰ˆŸ©£[¦.Ÿ#X‚mÎs¨ÌEoo/FGG±nÝ:?ùÒÛÛ‹ÞÞ^¢®Ù¦M›ÐÕÕ…‘‘ôõõõT ¢ùQ)6Æ'Q£0>‰‚‹m[¢`ⱓ(¸ŸDÁŶmu¢Q1â$‰“pX$ITUüHª èzþïT 0š¸Ý¶ó÷RUŽP ºY'TB¡®¼òÊiÈd2tuu•}þ5×\ƒÑÑQXXáÐ09ò%“ÉL»ˆæW¹ØŸDÄø$ .¶m‰‚‰ÇN¢àb|Û¶åõôˆDJ<.’)š&n×~Wð €.#‰·p¨€¡È•Ó4À6=WúËy m“eÃ*òpbû†˜uBeÍš5ñ³•ÐuUg&;;;g¼o±$Q”‹M€ñIÔHŒO¢àbÛ–(˜xì$ .Æ'Qp±m›çÆe à’9"KvɤÇРöÈ> À” Œø€A%?4 °œ›í­@ø§€ñq@½T܉È`ÿÇ$r‡§/—ÆœJ~õõõ¡··étÚ• …å0/""""""""""j-ñŸê/ó~`|\ŒJ€ÔçtΕùr‘O¨ à7 "ÈÝŸ{¬`ÐV½ü) > x‡‹Ñ)‘ˆ(+64”{Naù/ ù„Š\f‰²a4¿fPð'#*¬qIDDDDDDDDDDÔl,+ÿ;¿ûY õ-1ù¼œ#E? "ÑQXvË)XXÀ0ù¤ˆ¼ß†H¬Ä€È÷Åh—ع€þ°Ê“×ûœÜkþ-7r™S*òõŒF¿£­ëàÙ>!“É ¿¿¿ÑëMDDDDDDDDDDT›1/ŠãÎOÄdñ® ¤NŒcErÅý ¯,xNù$Ç0ò‰-÷· Q¢KË=.1ºÄÌÝb?}…XÎà×ç·À[O6ŸH‘ËõO¨x¯5• 1’…æÍ¬*‘H]]]èïïG:žöCDDDDDDDDDDH‡E²dÅOã-"‘¢À §©Š‘)ÎÿúsÏ× F™Ø  ÅÉTî~@ŒQàÏ­99½1’%—üØÛ½ñN;xßy/¼éì¾i7àžçáéGž ],ç׿.NœD1=áâå^‹êjÖ%¿LÓÄÀÀ`ëÖ­Óî¿ÿþû½MDDDDDDDDDDDÓx·Éî1€r{= \¬‘ý@‹xP^â?"Ÿ€Hbä2E%·,ˆ$Š‘h‘%Á4qàÀøÉÍ?Áe—]†qcK¶-ÁQÞQ€üâ5¿À×¾ö5´/½O?s(ðJàÏÉ?ãàwŒØŸ³øÑEßÄg.:­èE¬È|#ƒ„ßœú,–Æ—1À¹]¼”uàDdr%‰ü¤ö«Œ•xC,ˆ¤ž[où¹Z ç†)zs¿äGϨXfPéëëC__`tthooGggg£·…ˆˆˆˆˆˆˆˆˆˆhÇlð~X‘=ï†u@sMt™ DÉ® =(Gê äçBÑ FŸÈÄ‚ŠüH9Q½¼Ïþ¬üwy'.»ì2zè¡xá”ðÄ=OàÑëŧ Ó`(÷w2÷;|âFÞ×âf]ò ÓŸþùX·n6lØ€uëÖA×uŒŽŽ6z{ˆˆˆˆˆˆˆˆˆˆˆ|N°¿*J|Ùƒ1þO@Ë,I¥í:äç-QDõ=@¢°ÌW.9°xÞ}÷Ý' ZÁ}ÄÈÇ àè¿ßüõ7°aã°}‡áòË/‡ çÞw.Ö½râñ8vMìÂÙ˞ƙª‚]+Eòa`Í+_‚ϼ{¶ßþýŠ¿à°7fðÝÝxÿÛŽÀm·]ˆä¿«¬;±ü/:VO.ÇðD±¿”çô Œ»—£ûràõw¸yÙ³øùÏŸB*5ïw@¸°¾ ÄïÌzzïÅ6CÛà‹‘l‘‰ù‘+:ò£`1ÆÃtqäR6f?׋‹|²«J

üö·¿Åý÷ßÛ¶ …°~ýúº®Ñ\xž™ÿ*` ½ ~àÚéð(ª (Á/]uïc÷Âvl¨"K‘/ïå»Gv*ðèIâ=?|H D!¹IéǬ!„Ãa<Úù(¾³ç;¸}äv8ŽƒÉ &ñéo|¼ëØt0€D"SÔ'0ñÌnÜqÉ×ñßž€¡4ÐöŸm0F€»9ï¼òeøäÿü ~ÒaxÏÛ–âñÇ¿‹/Ü»«_x6ÿt3Ôã<œrð?cÛ/ÿÉ{±ú ËñÏŸ¹·¿j?ÚŸxÛ~¶Ÿ¼í`¼ñ%7Àú ž à×€} žhGNÐ}Ðs2àþè90oï£×†ü\0DBĆH”ØÉ™0‘‰;÷¾Åó»Ø-EÎýÒS°,³`YeX–X_øõ¯_ާžšu‘®²fPÙ±cz{{ÑÛÛ‹¶¶6@GG®¹æ´··sbz""""""""""j8Û“Ï»{5+*î^ˆr]@þ¢~ ù‹ü¹yPöìÙƒ/|á _>Ž»ï¾Û•ñÂ?¿€O~è“€d¾¸ž‹»N¿ ·ýá6¸®‹Ûμ KþMüþóŸÇ®¯ïÂêñÕ˜œœ„eY8þ¶ãaYLÓÄ/ßüKDÍ(¾ýíoÃ;ÙAçÿ9Md€ J!(ÇcÏo“ú @¹xôÑ÷ã°å‡á¸ëƒ¦ix…ñRܰêŸqË/¿Œ“Ž:è¾}ó·ñ¹îÏaàô—á{ÛŽqqë/Þ8@â{€3 ÀŒ˜x âÿ$¾Ïæ£0·ñ5€õlî}’óǨ€}'òsÉ8Iù^ºbýMG<ßÝŸäK¢Yâoï €}U.bnpo¿œ/ѨX¾·8è ñY–Uã8â'‹ŽFÅeû÷/Ùgî«ëgjÖ •‰‰‰ï“ """"""""""¢…dš€ëŠDŠ“œ"1‘ÊM¼®ªÀP/D¹*SÜ"`çnW€G}k]‹¶¶6´â œ|äÉ0MHñv¾üޏ÷¼¼ãåøÞ÷¾‡§ÿñi ض/üá ØÄ(®øÔ§°ìÍËpîsç6oÞ Ð4 †a`ß¾}pøË_v ò©cÅH²ÔX"W> t »§Ž„Þ¸G½í(ÿ±Ç<EÁÒ.Åqg‡T*…ýËöãÈçŽÄû®~nxàtz8n½óEÄ­8þñŸžFâE±Lån ò4 ëÀÁ«¿†«&žAìõXÀþ=€3Ÿ@ÜÜ~ñÙï¸úÄVÅžÿþܶo6G`˜ÿ ô<Ø `ý蹈ßÄ_D tßt¯âïìå€õs ü`•xï^·þ~¿ÿaüëYÿ Ó,°B@ìr ™o“aˆÄ‰µu/4Mìÿ¡!±ŸØû—8´Ñ#TB¡vìØ1m¾”d2tuuÍO4Í âq‘P±®Ôý"A`o„(U8·‡‘¬?£Uv}}n[r~ùË_âûþ€ƒz‚ªªøÚ_ÃÊÇVâ5¯y >°ýxôðGqèKÅ_ÿúW¼ïê÷áþÇï‡ã8¸þîëñ׿þ¯ûèGñ™ÿø &ž€axá…àº.¶mۆ׼æ5øÈG>‚ÁÁAlÚ´ =$²šX,ËÂxv?¾ãLjF£èééA8†çy¹äŠÁ”'†f˜¦%"GÞ¨ÀÒ÷,I Kï^ŠM[6a]ß:œ°ì\tø~hš†#¿ùô sÏ.=ý˜¦‰O}CÙ!>Ú{€ÄJào~\ÇÃ;ý"ºÓ€² ø r+’_ûÚ]xÃyÅ𷲸õ§b÷9ÏÀ¼ ºÀ±pñŠûû+šŒ_/=÷¯¸ôwcÿáW#5’Å?Ò‡÷à/¿ý+®=þ!üó7_…Ÿ,9¯¿ôHÜ=ö4´c<Üù¹;ñ_ÿµçüòGpêá‚ë'ñÌ3ßÄy°aí!Dný¦H´üPLi£ªÀ«O{=ú¯uýŒÍ:¡ÒÛÛ‹P(„uëÖù“ÒëºîÏ«2›Q*£££˜œœ,º-“É N#“ÉÔuC‰¨z¥b`|ã“(¸Ø¶% &;‰‚‹ñI\ÍÚ¶Õuq!]×õÀø‰±S &Nw€}îÃÎGwŠäƒ%nC€Üxãøîw¿‹ o»yé_pØa‡á¸8ËÇ–ãOŸü$¾ö»¯n¹åœþ®Ó±äKpÔÅGáG?ú¾÷½ïÁó<¨ªŠU«Vá¨çŸGDUñ¦¾ ¿}ñ·PU®ë"㤓NÂ׿þuüþ÷¿‡ªªÐug<ü0`šØ›Lâ_wîD2™Äýè¿pÈ‡ÆÆÆ ª*¢Q1‘ˆã8"s¤ª"¡¢žáÁÍpq K–,¢ˆIbLÓD8ÆuÛOÀ)gÿ®ëâûþ€|àÁÃw.ÿt]G"‘ÀÉß>ÃÃÃØ½ûvܺ÷Aünÿ1øøóoGÛ)ï@÷›?‡Ÿ,û>úÝ.|óM?Âwüéþ,¾{üã8òÈçð/Ÿý »ÀsάúÓŸðiõ0´7€;÷Þ‰³.}«Æ‘GÞ‚Ýñ>x8—ìrü«z3ÞþŠÿÅŽËOÁY_Z‚cŽ<½½½¼CÁø;³Ça/=xmxí#‡ãÄÑe¸í{{qÒŠßC™x?††ý[bŸº?BŸP÷ÏØ¬*pÍ5×àÆoÄÚµkÑÙÙ‰7â'?ù z{{«^F&“Áúõë122âß600€uëÖaëÖ­X·nê¾ÁDT^©ØŸDAÀø$ .¶m‰‚‰ÇN¢àb|W³¶me (E£TÜûåÿŠû”Ï#7lxð«â–[nÉÏûøóyÄÆbØtõ&üá°?àu_|Ž9æœ:ðLtÝ{/žYú vþ×NŒÁ0 üÓ?ý^ÿú×㡇Â'>ñ xžÛ¶a¶¿üå€mョžŠÿwñÿƒ¦ip]+Ÿ}[zW_}µŸìÐ4 —{, i0"üyÿ~ ã£÷|zJG*•‚¢(ˆD"°, º®ÃóN;í4ürÙ/qæÿœ‰ýÍ߈×J†a`hh—ß{9– ü#–,Y¸ID®óªˆRn–-;ïÞújünå!8ìÓ‡á ç¿ÿöäF,?ã'€'rKÊiÞï rׇqæÓ‡Õýs6çbèììœó _uÕUÓnëïïÇ–-[ …0::ŠuëÖ! ¡£££îND¥•ŠM€ñIŒO¢àbÛ–(˜xì$ .Æ'Qp5kÛÖ¶ER%‘ÈÍë>Š|ÂÄ‚H ØÀÒ‘¥¸ãì;ò%¿ôÜc v~ ZJÃð%Ã8ý¶ÓÅí*ŹÏ=‡W¿úÕxíû^‹±±1D£QÄb1¼üå/Dzeˈ¤xž'®‹#- ÿóóÿçy‡ÃøþàÁ“O†qúéEëÂîÝ~r$•Joœë¦ 5ñG´˜¦‰+&'qõ}÷aü±Çðõ¯×|ö³xúøãaÛ6aš&,Ë*J’ÀÅ¿XÌÏà¬KÏÂØßÁ²,ÿ~É0 ôôôä¶KÁíÏ<ƒËLS¼É°ä‘%¸°û8ÀuqÉ%§ç¶]$6þYÿ1àØ8">ùf Þ†;–Ýo_ô1|õe/n¾Ù-U޶Ñu •3Ο}\· ‘ˆØ§§&Ƈ¨ûÄ€.y;Ï|7>þ|Ï,}øà ßõâpã-8þ0஋ûqÑSÕõs6§*étº(°Ðßß_r˜f)ýýýèìì,šo%N£½½¡P@>a“N§ëºÁD4³R± 0>‰‚€ñI\lÛDÁÅø$ ®fmÛº®¸o<Àe¾"§A$C\ˆÄŠ"~ßñÂ"Ù¡A$Z\{íµ¸ë»0–ë^õ*|`ûpøk‡®ëXµjàºøý¡‡â©§žÂÐÐTUõ“'ªªbëÖ­EIEQDC×ýL¢(Ð4 ¡Ý»qæ§?í—æ’Î8ôP@Uó“ÏKŽ#~’IÀq`t]ŒZÉ®^¼òJ\÷‹_àØï—^z) Ã@*•‚æ8øç_D2™D8F4…mÛùyV ÈÑ/2ñ"©ª*FµXâºì‘GD2¹÷ö$ðýÀuý\H,&Þ¹÷\×ó3ÅÀ{ÿã½xÿ¿ˆ#ï»Ol“—›ØÆ²DŶÅ0£T îw Ï‹H$€„nŽé'ÁNúà[pä³—ã¨ÇÂk÷¿øÁðÐ_†kYxìþÇðø?8úè£ëúY›uBett6l(º­££étëׯ¯êù;vì@$™vûÔŒf{{{Åš|{öìA]ߢjõ÷÷ãŽ;îhôjÔÅL±)ï›K|ÞqÇJ­/“É ¿¿{÷îmôªÔE½ãsïÞ½èïïTã—t: ˲ðÔSO5zUê‚m[j%lÛ²mKÁ$Û¶{öìiôªÔÛ¶ÔJض­®m;_s®Èëð¶ tw‹¤ŠúMÉÜ*'@$M\6´“xö±g±{én‘PðìûŸE2™Äµ×^‹ÉC&ñá«>,ªÐňEQUÅ mmøÚ»Þ]WóEñÿÖu}Z2—HˆÄ€-›6AQüöÉ'ýr_Ò¿{®xiM5Ë’I‘`èîÎM:¯ŽƒD"MÓ ë:N½áhš–OÞÈuˆFx§}ò“þœ(‰DÉdRŒÌÉ D¹ûì³ÑÝÝOø) * ž½æÿ=óE{€§\àÖañÚ‰U ;ZüX¹­J·þöV±±˜Øy¹d ††Ämr”Œ¦A¿áƒp]À¹îâ-¹åÜܼ1qñXyïJ÷ãpùå—ãÂ?\ˆ£_w4VÞ{/t¿wrWÝ?w³N¨lß¾½½½¸æšküÛB¡®¿þzLNN–=€MNNbÓ¦MزeË´Éë'&&¦=¾š!cGy¤Ÿ%Zh¡P+W®lôjÔ¬\lsÏ•+WNëqD´dÏ9ä¶™ÍG|.[¶,pC³iñèèè@gg'–.]ÚèU©Û¶Ôjض-m[jÙ¶=òÈ#½*5cÛ–Z Û¶åɶm{{{]×5™ù…žñ¿e‰kñž(:D†à'Th{¦ib÷îÝxÿï÷“ç¦Ï…ëºxç;߉×ßüzœÔyÒ´×»àCEÁug…£Þö6ÿv?‰çjŒMYIÉ0D +]t–^w.8äüíþPô”ÚÚÄ@$ =11Á"Ñ™)6e]LÆ'Qã0>‰‚‹m[¢`ⱓ(¸ŸDÁÕ,mÛ±1Q ÌëíÔ]àî»ïƹֹ€Ìg¨Àóß}ûOÜ/æ<‰ãçãí¿ù ~pÐAxÓ›ÞMÓĈ‰2œ™F\È > (‰ƒ™,ÙË€¾>‘s’LUXb«p’z™Œ°,‘h)¥p”‡®‹×Ñuìyýë±ýùçñáX ΪUâ>ÃÀgn¼׿&¥?+‘IÇñˈ©Ÿú¾þ³Ÿ!Ã4M(ŠÏópí+¯Å!=‡@UU(Š‚§~þsÜ}øá8×Ïn¶m‹ùc, {^ÿz„V­Âððð´’g3à©P~}/\÷Tq£a̸íg¿ç=Xõ™Ï`hj‰²:™uBeãÆÈd2ÐuÝï='3–×\sMÙ@êëë+úÆ ظqcÑrÒé4B¡FGG‘Éd°víÚyÙp"Ê«›¡PˆñIÔ ŒO¢àbÛ–(˜xì$ .Æ'Qp½mÛÓ“ŸrC×E~Á²÷. ö¸xŒã9ˆî‰bXó¦ärû2ûðæß,þÑì¶þvß>lúÙÏðï|ÉdRL¼>MÓày^¾—ãˆd‡e‰Ä‰aˆ9Kb1‘ȰíÊ£HÄ‚óó‡„Ãþ„ô‘HDÜ7e.“i’É™*…"ñ:¶ý'žˆÝ'œä"€X ϵµÁúû¿GJ&näoE£b Áq˜¦é?Îu](Š‚d2é—òêééÃ0 hš†h4 UUñüý÷cò·¿…vþùèîîF,+;RÅu]¨ª*6Ñѳâ@¬ºÏœ¢(3ÏiS£Y'Tàšk®Aoo/¶oß@ ÉܲeKÍYɾ¾>lÚ´ ]]]A___]‡„ÑÜ1>‰‚‹ñILŒM¢àb|ã“(˜›rZÇb—á~ ÒX{õðàW„C” ² F©D€«ž¾ Ÿ=å³bA*pÈñwáˆÇŸÅ.½o{ÛÛð¶‚yQ) ' ‡¢ˆl$’ÑáyÕ%Tt½h¾EQ`Û¶HV(Jé²Y’eåKzU#Ï,S/xþéïzð÷ŸOBŽ)ø[Ó´|ÒðŸ(e“J¥L&aY–ŸØ +™x€îînD"8ŽƒžžÄb1bD‹®ëH&“0 ‘HD”A+“ôšjxx¸ú÷f–ªJ¨ ```k׮Ś5kü —j­»mÛ¶¢ÿ{{{ …ÉdÐÑÑÁ!D 256Æ'QP0>‰‚‹m[¢`ⱓ(¸ŸDÁ´¶­aˆÜC"( .nw”xôÑG±lÙ2Ð˲^F[_.ù£ŽïÄ‹ç‡(5ÂÆ4§%T>‘JáÎÂ䅜ˤP.`Æ„LI‘ˆi¢iÐ4-?Ñ}%S’#åJwÁuK–/“‰}6IšˆQ%lÛ†ëº"â¿Mù÷I×uÄãqxž]×áyž¿ñxÜOÒD£Q¤R©¢å4RU •ÞÞ^¬]»ét[·nE&“Agg'Ö®][÷Iùx°$ .Æ'Qp1>‰‚‰±I\ŒO¢àb|S£bS^ÿ÷<1ßùÄŽ`äŠ8âïÛö݆Ë.¿ >ù NMœ xbî“õg¬÷m/¼€Ÿ¿ä%Ø]jÃÔ„‚ça|ùòéIˆz–“²m ‘€¦ªE£?ÊÊÍ}2+ªŠrk=66V¿mªB*•òçd÷çTqs¥ÎdòEUU„Ãá¢yWǦi°ró¾ÌWy¯Rª.ùÕÖÖ†5kÖ`Íš5Ä$ôóš\!"""""""""¢ÅKæ2%7×»—û¸¢Ä— ýÇ£±bÙ q‡ è<ëG>õµOwˆ›{zzpó«_W~á xc©IÑ]7?QKîÅ}õ«óóÔ›ç‰Ò4(@Õµˆ™……J<¨¹ù`*½^"‘€¦iEÛ­NI,†áÏÝ‹Åà8º»»166†h4ŠÁÁÁM¨<×'®Y³×\s ¶mÛ†µk×bûöíX·nFGGl剈ˆh‘™Ò)h¾Ú´DDDDDD ®›ŸnDQ (¹ëï± èÀóÛŸÇeK/Ãá#à3·±X molƒk¸èééaXòƒ@UÕÒÉ M%¸ _bDDÕÉŽÙPQǬÅÈÇÔ’_¥UŒ´‰Åb°, ÑhÔŸ[%û‰.9 ˜¦9¯Û6ç„J¡ÎÎNôõõáÆoä("""ª+™4q=¢³m‹víªU^;""""""šO®+*lYVn„Ššû‘`<;ŽN8/¾êE¸®‹›WÞŒCÏ8ÔŸ=B×uÿÿ"…=õÅ ÊÛ_|1€…ÝÑ*dé®z$¢EÁðð°?šepp‰D±X ®ëÂó<ض Ó4FKÎS/³J¨¤Ói øÿŽŽbÆ ذaúûûçm%‰ˆˆhq2M`Å þQ Gœ€èDBÅ4si""""""jYª*Îý #whå~l:øãKÿ8ñÄ7=sÞøÞè/Ã0Œ¢ Ñ‹ôôä늉‹ÉZ<0 Lž~:lÛnôÛÐtEñ“*õ‰Dür`º®CUUÿ5 Ã@</ºm>TP¹êª«°aÃd2@&“Áúõëˆ*;vìÀ¦M›æmE‰ˆˆhqð<‘0ñ®’ÿ  Ð†Ž”?êK€DHÄZrd4!_‘@ Ì•ürh¹ß.xñÁqÚ1§á¯Gÿ`Û6ôÜ<(®ëæ/°Ž>‘4M$U¤XL¼hî9º®#‹q„Ê,)ŠÏóüý0ä>ñ<ªªb||‰D¢ñ#TFGG±}ûvÜxãèëë &¥oooÇ–-[Ð×ׇmÛ¶aÇŽ~Â…ˆˆˆh.Âá\Y¯bçÚµ€ñà´îkÄ a«€ø&ñX""""""j-†!Ž”<çKAŒNqxÀoþø¼äЗภƒeYþ…vÛ¶‡óÉÓ,"_¨pTŠ¢ˆ¤JAI„D"Qº\X“šÏ„C¡ù)2u{ä>VUÉdÒŸS¥Þ­æAÛ·oG(*š%NcÍš5hkkttt ££™L òFQëí,ýT ¦Bô4*¨ë¾ð²€òû|Ý\ý8ˆˆˆˆˆˆZ’ëŠüGÉ!€( ¸÷±{1~Þ8–üp NýÇS‹J{iš†ÁÁÁ|B¥Ô~]?²ô×<ލ oê(y ëú¼ŽN™Jîc9ÏÊ|©*¡`Z’$N£···è6™\!"""ª–e‰6­ãˆŽ@‘ç!z¢&nA™[oàýÀˆôy^{""""""ª7×犑H®Ôs€ÑánH>HÜöÍ‘oB5Tqþ¨=7’$ÇÀEo~s>¡ây3'Læñ"|ÈdŠ6Ï“’Î8gM)ŠÇq¦mËøø8V¬XK.¹¤î¯YUɯööv¤Óiÿÿ;vB¡Ûää$FGGÑÞÞ>ïo5?ÓmÙx‰‚+Hm[ÓñŠæW!’)ޏ¾òõ¿ŽÞ‰g–.Ç Ç§(P¶mCŸiâyj9ªªú‰´Bš¦á /¬ûëUPÉd2غu+2™ ÚÚÚ‰Df=_Êèè(¶oߎŸüä'hkkC&“®ëèííEgg'úûû±eË„B!ŒŽŽbݺu…Bì@4Ï*Å&Ægض ˲àyLÓ„¢(ˆD"µ/˜ZV+ŧãˆQ&~/£xî·‘HÑ0c2Èj)ÅûRÀ9`S™m[¢`j¥c'Q«a|WÐÚ¶®;e„ŠìXç‰_¦i*ðäcâ/¯~5VxU…ªªØù¿ÿ‹7ïߟ®ç‰…Ù¶8¡TÕjWƒš€¢(ðËp§d9Ä©âñ8lÛ†ã8Ðu–eÁ4MX–U2‹`ÆÛiqi¥øŒFE»5%ëÝš½‹b¥¾*´ie ÝÂ’·ÊË{§hl;Nþ1D m[¢`j¥c'Q«a|WÚ¶ž':ÓUqR!zÒyÀóÏ?Û¶a^³xñMo’I|ë‹_„ëº8ë駱ꠃÄó‡în1™g‰ ïÔÜR©bþd;ó¯ª*ét™L¿ýíoý ÒuþäôÕX³f Ö¬YƒÉÉIŒŒŒø šP(„­[·NËh¶··WLÚìÙ³ýýý³Z¢zéïïÇwÜ1«²wAT.6ÑKa.ñyÇw``` å†g[–UUÇáy”ÜÒd2 Ïó ë:’É$†††ü‘(žçÁ¶mxž‡ÁÁA$“I¨ª Ã0L&‹Åü娶 MÓÐÝÝÁÁASƒL&ƒìÝ»·Ñ«R³ùˆÏ½{÷¢¿¿¡PhÁ¾¿’I1¤hþ¿a=È÷4ª‚iŠeȰP“bùŠ’®ªâq-:×^SK§Ó°,ËoS63¶m©Õ°m»8Û¶|²m»gÏžF¯JÍZ¥mK$±m[]Û¶··wV#YÌ\Yè¢Ë!qã’€‘Hªª"™L"»z5°z5Þ àÍžøà±üŠ+Äó4 ½ð<'‰9N õFTUµdõ—yiÛV=B% }9¬Y³fÎ/*Ë‡íØ±Ãß Ù¡P5vä‘Gò€I  …°råÊF¯FÝ”ŠM`îñ¹råJtuu5z³êÆu]„ÃaÄãqôôô@UU û·†×uáy4MƒçyˆF£ÐuCCC0 ©T š¦ùI“H$ÇqÐÝÝí'd’É$’ɤÿ8š=ÙsfÙ²e^•º©g|.[¶lAË&X–ø)ê0bH«}ùî_EÛ8‘ÆÇÅëhšˆûä„öÔxèììÄÒ¥K½*uö-µ ¶mËkµ¶-5Ù¶=òÈ#½*uÓÌm[¢BlÛ–'Û¶ííí³Z‡²yÊA×u(¹š`š¦š†x<×uñÒ¿üeJ6¢×“)>oŒÔéêêš—¶mÕ •zêììĶmÛpã7bÇŽ(XÕ”;ꨣxÒI Ój'¥bÀœãsåÊ•³žk)(<ÏC8.ºÍ4M¨ªŠD"MÓ`äºÚkšæÿ/æ²—„Lš@,óG›†5W³3•J!‘HÀ²¬¢†a´T…ÔÖÖÖr •zÆçBŸt* 08˜Mbü(³_Ö´aßbo-ù¢iâÿáa §GŒìvÝ|/§BŽ“O¼ÐÂèèèÀ9眃%K–4zUê†m[jlÛ–×Ìm[jn²m{ÔQG5zUꦙ۶D…ض-O¶mg;‚§Ôµþ¸×HxÀ¿S(‘HÀ0 œ½t)çI©‚Öâ ¦ÎÎÎæO¨ `ëÖ­þÿmmmþœ,òw¡‰‰ ‰@¹Ø°(ã3êh4ŠU«Vù“ÉÇb1†¡¡¡¢äˆL®(ŠÇqŠ+¥$ ?Ñ"“.rDŠ•¢ª*\×å(•E®ÙãÓóòóþÁ†˜;ÅŬJ}br®”B‘ÇD¢¥”¡!ñ‰ˆõH&ó÷ÉRº 1š+¶m‰‚©ÙD­ŒñI\AjÛºnñÏó Û:\×…«¸x´óQ€â8¸áÔSÀŸ«0V‡R-®ðÚÍNÕ •‘‘lذÁÿÙ±cvìØQtÛ† *.g``“““€ÉÉI¿>f(ò'9DÝÌL&ƒµk×6ú="ZfŠM‹.>ãñ8ø£F ç0)u°)L¨¢4˜a°m{ƃS©Û “/Žã@UU !Êîó‹^3ǧŸÀ° Ê|"±¢¢â$ô¥¸îìŸ#;݆H¢XVþ÷à (æyb¤J.üaÛbt‹üŸh&lÛS3;‰Zã“(¸‚Ò¶-š{ðç©q®ëæGV¸®?·™¢( :1y3c"¥6UMJßÞÞ>­Vì\2½½½Ø±cÖ­[‡ŽŽŒŒŒ`íÚµþ¿¯¯›6mBWWFFFÐ××ד:]¥ØG|º® ×uaY†‡‡¡( 4Mƒišp]wÆÑ&…TUõçGf?|²p4Š|=Y>LNbO‹K³Ç§œa C¥¾æ0²XŽP™«DB$NÂá|2@$V ËÅãâþXLÜnš3€¡Åm[¢`jöc'Q+c|WÚ¶¶]|æº.Þ´âMð<¯xd…ëÂU$£Qxž‡Ay’Ge©ªÊó5¨*¡"kç¢>^:ö‡yutt`íÚµUжmÛ0::ê +LÌôöö" !“ÉL»ˆæW¹ØZ7>åhÃ0ü9STUV²Ë­ò*na–_Q”ª’0’¦iHæºó¾ž–›XMλÒê5.iºfOË¿¢ÄW7€€Y$'<σeY~‰¼¶¶ðôõ܃ÈÐPþªJÒ(Š(6•m‹Ä, ŠQâª*Fª0¡B3aÛ–(˜šõØI´0>‰‚+(m[•‚ó¼+VÀu](ŠRTIäð“N‚Îk%´€ªJ¨Hýýýغu+ÚÚÚü+[·nE?"‘6nÜXÕrÊMäǃ%QãTšd³ãÓ²,(Š˲088Xr¾]×g5‰<°G"‘Y%Td2FÓ´i“ÓbôJww7ÆÇÇ9˜…ÈiΦְ“%€ÇA8.zŸÇñÂá0ëßUÉu]„ÃaÄb1$‰ŠÉjK~ÕÒ#B&IfJê$‰i£Wˆ‚JQ€„ 1}"‘â¡brÃgÛ˜øÝïà8þß+^ÛÏ>7}6vï^*î7 ,ùð‡ñžgž)~ž™{Íxîu㉕RqŸ›û™)Ÿª(CΉˆˆˆˆˆh^ض(í_‚1ôÞó(qÝÄ+89³, žç±Ü-¨ª*ét¡P¨ì¯7brrétºÑÛÔôÂá0,ËBOOâñ8ÇA,óçzp]+V¬@8.ú)œˆJ‹Çã0M–e!‹AÓ4èº^qÔ—çyU%KäDöµ(·.rD QÙvnÂw"i!)c•ŸÇáº.î]¿—_~9"‘ŽêèÀÇÒix;€¥×_ÚÚðБ?%¿\ˆŠ‘T‘íl;÷·—û[†P¢ŽÊ弯ªXw""""""š;ÇóWÍa©ç½ì<@¥Õ Ï Ã˜U‰vÊãµ¥¹«ªä×ÄÄDU …BÞž¦ç8<Ïó' V©T €©266†+V ‰øe€t]÷Ë€­ZµªÑ›@HÉd†a ™L"‹Á¶m ÎjÕ”Ú«µl˜œt~¦›®ë‡ÃPeÎ%ňæ“㈹Sb±‚r_)TUêK&SzzzðóÇÇqo{ À‹áÎ?û=ïÁÝŸý,¾ë!àÉ’İðDE…HšÈþ6¢t¢?o¦¼’¹í6\¶{7OÒæ¨ÚŽÃ4]U#TÚÛÛ«JªptÊì¹® Û¶aYQ+>‰Àu]Äb1¿½¦iþDÔº®Ã0 D"ÿ~y¡WNžÍòkDy¶m#£§§±XÌ/™5›ÇBõx«8ÊehhÈO¼‰m‹¹FÐäh@$/Êä#ÇÁªU«àyR©¾}ùåØwá…œ§SGŠŒ/_ŽŽxA¼V "Y‚Üëɧ‰™ÜIË•Ôå@äÂÜmVîqS°IDDDDD4¿Âá‚„J®âÀmà¢ý_.¬¸çý—¿°³éÄb1Œ1¡2GU%TÖ¬YƒÑÑѲ “þþ~tttp”J•äÅОžÿb¯ëºþäØÃÃÃ3ö†O¥R3NH-Ë~E£Qxž˲àºnQ}A¢Å&™L"•JAÓ4$ 2új-t-NMÓŠ†°–º_nQضH<øíY9oÊ dòß²,$ ¤R)(Š‚×<ý4ξꪒϙÚÞûÍ+^ŽnÉ“òI”B ÄÈ9Rf¢ü˜ž»=?ÈݯèA~î•‚õçôEDDDDDDó§èò¥ @F—â©—<Üo”tçX¾|y£W¹))ŠRU*­ª„JGG6n܈M›6aëÖ­˜œœôœD?¶nÝŠ¾¾¾FoOÓ‘†‡‡‘H$‹Å`š&\×­X2¨\öPŽnDúh4Šžž Ñb“L&¡ª*"‘ˆ_âKÓ´Yeáƒx‘£X8oÍà`nˆ‘ܘ¡³ëºˆF£þ\a=ÝÝ"#©TÕö_¶z5J$GÊIBLRÌ\~L…XÎÄF„!’+žXöM """""š?±XÁ? øÙ®Ÿá”¶S€3¢„ÊŸw^£W™¡ªæPà'KLÓôG£LLL`rrزe Ö¬YÓèí 4yaײ,8ŽS4 Å0 „âþH­oÇÆÆFý²Fò¢k<Çðð0‡sQËñ< š»PšJ‰¿_ÿú=¸ûî«`Û6†‡‡‹_õÄñ.ÄÜ =šH$ÐÝÝXQ‹ƒ¨1\WÌ™¢ªÉ"1Q*Ñaš¸ûºëH$üËu],dpPέ’¢(¸ç„{€7Wxàl}DüÇr¿“€ÊùSˆˆˆˆˆˆæÍ´Š.[tO©)`¹ ¸¢ÃøÈM7áå?eãÆF¯6-BU'T‘T‰D"H§Ó &¢g™¯ê˜¦ Ïó‰D ëzQâDQxž7ãDÔ³¥( Çñçaééé¦iˆÇ㳞ˆ›(è’Iq÷CváŸxªz,Ëľ}˱dÉ`Û t=_‡3•J'mˆ ¨Ss™.àÞŒÜÄÕS†C†!.¶.l5°"21dÛöŒe‰Ši”ã²!3ôHzŒ={p¹¢à„7§Ó¢N˜m‹ŸY$T`ÿ²ý•G¨ òj©È'a¬ÜÜö6“*DDDDDDó¡TUó½{÷Šë7D>O”GO?öÔT z+ŠPë›UBÚÚÚ°fÍši£Q2™ Xö«„p8 Ã0 ëºÿ3Ó(”zÏÕ —744~ù/c–«ˆ‚ÌqD§öPè.œ|ò¯pÚi yä5PUñ¸¸_Qı7™ C…iÆù€·p¿àt ú öYÀIæ7¡+èý€òfàD¼¹8>]ˆ‰«˜PÀgžWq!æ()Áu]˜¦‰+¾ÿ}àMoÂû‡‡ñþ~TÜYfî ™œýÌ3¹é¦‚‰[f aîñªΟŸ«…ˆ¨E8Žh#5’çMéÀ¦C¢©žë§é~‡ôÈΉꡪ9Tª‘Éd°uëÖFoOàȉáÃá0"‘ Ø1™RÏyE)9au*•‚išˆÇãèééA<GTÖJ"jR‰ày.þüçqÛmÿÓ4ñÞ÷^ä'QE\,ˆÇEE!Ë’ÿ„ßD·É{< ¨Oæ5@äÄàûK€q  g3ðNÚ܉pà|•{»O™Ìz¾ÌëD ÉuE2Å?Œ•Èóݵf øÊW`š&b±ÚÞøF`h¨æ«x+8'îߟ¿!W>³®4)@¹b.–yx "j]S {žh—¸îôû¤pXµJü+VäŸSXÃ4înq[w·xži==¢ þ¶¬âû¢QñÓ̵‹’ùÛˆˆˆˆÁq ª@8á¦DBÅ4ý†Šëºì\J U·„ “=pmÛF,ÃÐÐPÅÑ'ªªÖm„Š\ÎÔ$ªªPUžçAÓ4˜¦ ×uyA–N^\˜‹pXÌQ¤ëÀÑGÿš¦áµ¯=ž'ÆšxŒû€ÈÁ€{  NC»Ô2À8ÐhQÀ{оh ¹Ð7úÀ²¥ŸÁŸ†WÀ½°>À¼Ks¦|d³+/4GõÕF4¦YpQÐÁ´R_žçáó?Œg?ö1<}ýõùQ’uªŸõØc‰?âñ| ÜóĘñzÍ$¯úåÉT/·DÔÒ’Éé_!SÛ*²£ÆT²‚¡ç‰ÄH8,¢Í’ÿ‹ïPÓI“x\üÀؘxŽ®‹üs4*~l[üîé'ùdžX']_‡räÿž'FõÎ?‰ˆ×T”ük-4NÎߟø¾¸îá8þù£ëº,{N 5ë’_õÉdÉd`Úü+ò¾ŽŽttt4úý™3™Lq]©Tªª@¯ç©ÔÅÖT*~REUU„Ãa 1ûȕ‹ÍÂûç#>-+?©õ\ˆäe ®{G®´^þ¯ú(LÊi@ìRÀÞà›èÿ´WPý8À;€h‡Ú·ýdÀ~Xºl)~öÜ!0^è;ø>@}3\Ddè&Œ‹e-TI0EQê6÷[#ã³Çb¸CVßò< ™„©(XùÖ·â´ðÛ¶á:ïN8áñ‡eÃÃâoy¥ÐuÅ•ÈÂל©¾ç‰.Þ©TÉdeZÐb`B…Š,†¶m+’eA‡†Äßš&Ž#âݶÅm¦)nWU‘ÄPU‘”H&Åc=O<^Qò£b=Oü‹‰ÇÚvþk(‘È—#M¥Äk'“"â8"Ù’k®û£XdE UËô¼|»I¾^$"î—9k™Ì‰Dòë"×Ë0Äפ]88(þîéiô^©¯ ;‰;Æ'Qp5ªm럂yór8ñÄÅ®ë7¦8,5Ú‚'Túûû100€®®.d2´µµáúë¯G[[Ðßß®®.ŒŒŒ ¯¯½½½~Ê2Mq"cYÅåÛmÛÆÐТÑhÕ=Ⱥ§¹¢(~/áX,Ó4‘¨TƒžZV¹ØÈøô<ñóÖ·Þ‹gžÑ¡iÀú7Ÿ‹ˆqà@¨>¤ƒNœoÚ "€–Î/Oû ®«×åspá?dpaÛJ¼ñ–6t¯¼±§% ÄEbˆƒ¾q±uF¨0¡Òú‚Ÿ~ÛÖBñdîŽ$“ØÞÑoüüçX¦ªÀEÕ÷ÅË–-Ãïx^úº×áyÅÒ0àjN¸é&‹+¦®=õT|j×.ñÿÔFx<.n³,8Š2í¸¬i¹Þê.Ûð„ÖkÛ¶×Í'CÚ‘ˆH˜f>ñ!ó­2‰`šùD î[µ*?¢Ã²ò• åòS©üˆ‘±1ñ8ÓÌ%™!r´‰Dþqò+J×ó£_b½"""‘ü×Sî« °Ä¥€º@P4@SDÍô Õ…øν†¢ƒïÔ“8ââ1† ècùõ1rm—ÄÙÀϽë$èÇN¢ÅŒñI\lÛÊö’`rפ¸Ã¶‹ÎÝÊÍMM´ªJ¨¤Ói¤Óé²™œœ¬¸9ÏÊ7ÞˆÎÎN"°qãFô÷÷cË–-…Bźuë …Ù¡pX¼®‹kF¢€‰ññwâ¹çVBQ V½ÌzN?Û/—H$‚U«VÁóÄEdYöc횦!Ïêû†šGPâs&~ÛVæõ eªŠ_|2>yÌ1ùu<Ö4 ¿ºüròõ¯ã™Ë.ÃuÈ•ÝtXñ8"‘b¹+’™ÛnûváŽuëpmÃpÂ3ÏàÉ_ÄÅo{›¸ªª¸÷õ¯G8ÆØØØ´—óùNîÇ+‹X+µm›‰ëN/!KU™¦H^Ȥб¡ë"q¢(ùW²‘<|ʶ½ëŠe( 0>žp8_JTWáǾ®ç¾ "é: ç’º À"K/‘I‘DÂR1ñòß©6 {^/þ†›»Oÿ§œÜs4ä¿@ÿ)€Ÿ/~þE<þüã8áúÄE =—LÉõþ¼ûø»±ìGËðÆý/Ã7W¯¦wo*A?v-fŒO¢àjtÛÖoßYö†#ÂGÕs–eÕõ*ÑlU5‡J&“ÁèèhÙŸL&Sr˜æÔå„B!?(`Íš5˜˜˜@:F{{»¿ŒÎÎNtvvVLäìÛ·¯âcê­§Gœ(™f~È~_ß8昇𓟄qçwbéÒëtJ™mRdll †a ##Î"Ê¥ÓiìÞ½»Ñ«Q³r±)·s.ñ¹{÷nŒŽŽVµɤ8>V;ŠëÖ þøÇ£óÃ=]ˆ‹1ˆ‰£uJñ…—ȉ€—K¨Fu×wºg+rÐZ ½6wÇ2Àù‹XïaÀ;ˆ0û , 0yu*•‚çy0Mg“ ’üéthôªÔl>âóÀH§Óþ0îZx^®4M"öä¡'…ãyø—cÅ%ßÿþ¼¾GŠ¢à+/¼€›n¿¶mû±`¬ÜäŽãàŸþßÿCÔ0ðõc $“I|ýÝïÆ]ï~·x\®æ›sßëþè¯\¯ Ãb£'ß ë}{òÉ[š•L&ƒ{î¹Ï=÷\£W¥.ÛÒ mÛ ‘%¬€|%>9Áºœ„=?ñx~.ω ÃmôDBŒ*‘%¯††DòDŽ‘‡L9bŒ®âÿá@ÄzTŒ$ÑOÐ  '÷Ó-{\7€U¹¿“@B…h›„!¾#U  | P{ Ú+ã@d%šû ¢„¢`ù°CFôÜm¹Û¿tÄ—`©ÃAqô¸=xìua÷e»qÅß\sž9¦k"¬†‘ʦðâÿ}^òaüÛsÿ†ïüê;Øõý]8êØûqÖ/β?/kôÇ &AhÛÕ“lÛîÛ·¯Ñ«R³ ·m‰f‹mÛêÚ¶ÕtÄ÷ûˆª4`|ù8?p¸h˜å.ê(ŠÂê:TµÑÑÑy¹n[Õ•ÞÞÞº á …BEI—ÉÉIìØ±7nÄèèè´Œf{{{ÅâÓO?t:]1™SŽ“ïé&OÊ`ppÿò//ªªxßûvâøãÇpçï®:äרž˜{B‡iš°, ¦i""‹6Ó4­’P)›æŸ»wïÆÈÈHÑÁ¸ÙÓTÖ¯ÄqD/qu)¿Ø¿?Tõ¸®ëÏÛÄfð|­P™ø”'µô&’óx^¾TLÑÜ)ŽÏópÁ%—LïJ>Kžçù£.Ür cxxš¦A×u¨ªŠx<×u166EQ‡aš&’É$‰t]Gww7<σçy¸î‡?Ää׿ŽWÅãPUÕn<‡mÛˆÈ:?žml š¬ˆ‡à|ñYà0ÀˆaÆï*MvÔ‘e=šY³·mƒBÎ'bšù6eåç‘¥º\Wü=>.,º.Ú==â±SþhÅóÙ@ìÿúŸ Ú Qø¥ 5Hé£8ÜÜ&~ZnY L‹æ–¯@ŒnUó¯ƒ8D2$š[–üžŒ ¸4¨|.r¯Qøµ©Ñhžç!‹AõT(Š‚h4 Û¶ý 7Ù7As4˜¦ MÓ`>ã|î½¢m066†îîn¨ªŠÏ9ŸÃªï­Â‘ö‘8^=Þÿ]ºôA¬;l þ p^£?5htÛ–¨ÞdÛöé§ŸnôªÔ,¨m[¢¹bÛ¶º¶mGGGÙ÷ȶE{o°àä—Þú%|ðÉ'‹gš&TUåµJªÊÈÈHã*“““Èd2um8îØ±ýýý…BèííEÿ´ÇTs <þøãÑ××W÷7¦”x\¸ÌS¨*L&ñѾ££1D"¨ê ¢žÐQÖv–½õJ‰D"ÐuÑh”_Reôõõ•üì6³©± Àï-T¨šø¼à‚ ªJÆÊIU%ß#G£âbHáEÇQâ[÷By`9þöÈ—æ{ÊÇ©È_´˜j.•±Ž¼[\<¥”GÐŒü…eÇôT®·ì…@Ï0”w΀öSÌKREQxž×uYþ âóÙ×××r½HëŸË—/¯ùØ)o¤Rÿ4ˆ „€¤ŽãÔTÛV& ÇA$ñ$rxw*•B8F,+úÌ»®ë¿n$AOOýçiš†d2)F¶é:ÚÂa|ä#Aww·¿Ã0F±·»¯þô§qñöíâ੪JŠýC„w †q¡tó–0m5ò$­ÕFa4cÛv¡ÉÉÞå(ïdR|‡D£ùމ„ø[v<ŒÅò£IÃáü1Ø?Ëò\!?JDÎ!"²4Ÿœÿ(7B$";^È@~IDÄAqâdĈ’©McY¢+6åv]Üfš&.x×8ô©CÑ….ÿ9wýì.<`=à7ÉÑá±X ¶eûÇuùæº.âñ¸Ÿ6 ÃO›Ž ]׋¯DOO\×õ;ZÉßñx–eAQ”¢¶þi§†_üBÇI'5‡©m[¢zcÛvþÛ¶DsŶmy³iÛª²j*Ûq·ÝæÿÇ¡ë:;‘RÕz{{çeôbU Ó41::ŠmÛ¶ù·õ÷÷£··wÖÙÿÉÉIlÚ´ ™L×\sÿÅÓÞÞ>í±õNâÔÊó€áa ï®ù'5ò"ZcÜ…’LæË"”%×,ÛCõ1SlóŸrTŠ®'ùr×.ýÛä\Eª =À§nüÎð’X†eâ ;%4S»õÓo/, âyâbÏø¸¸¸cY€r+`Þ Ä@Ïû€¡k­°ú‘¼¸S#EQŠzîstYkid|–"{û!=低ƒýï{îyË[Äô"úìGlÚ¶¸hÛ6R)±àh4ê_<,”H$¦%m _º®û£X o‹F£ùeÅbØ‹aÓÕWûÑ4 CCCH&“ø§ÿw¼æøãñ‰¿ý[û/ÿí—¿b:Ð-æ@P?(•¨™Û¶ó)ߢí, ѨHŒÈ‘'‰Dñü#Er¬¹¹ETˆçªDbC?’C5 F” C|ÉD‰“»}¦åOÍ÷ÊXÊÝ75¶gJœª€óнª±XÌ/¡+“ÑUQÿ\a°kÑh±XÌ/IÇ¡išÿ]–L&aÛ¶?jDöÂìîî†ëºH$Ð4Íÿ®SUÉd²äqßuÝ¢ïÄÂç8Ž3-£i€m_Ž?ÿù{ ý‘©» ;‰(ñI\ oÛ:\¢:Á²sÎ ËÜÌp8ŒñÂIª9TJÙºuëœ2<ëׯGGGlÛ.:hvvvN[ÞÄÄD`†kº®Ñáy¶ßc6™LúåA¦^0 òÜH‘ˆ¸–«`â÷2.…ó1,3Å&0ÿñ)kù 0ò·ªŠ¿MS\ˆq]‘<|ËœüÜÉxå¡wà´7üT<9‚é½FëDÕQ1ñQt"Ɔ‡Åʼn¸D¢€ýsˆ A€¸˜S§Ñlªªúeý‹4ÔŸ¥øe¾Lˆ —IäçÑ4t~8â®ëÇž Y¾NUU?™ˆÑ(3%g¢ÑhÙeNíÁdR©T~Ýb±’Ï“et†‡‡qßsÏá øöÞygÁrrÇP ÅåhQiÖ¶m½$“ÓÛ’²C„®‹ûEŒÜÎ8‘sø<ˆÑ%fî·,Óµ þ÷KÌÊÝ>‘<ƒH~ÈRZ2 "—«¡t2ðGªÌx_)S’)¶mû#FLÓ„aH&“èééñÏ’É$b±†‡‡Er%…¦i~¹®T*…ÁÁAhš†T*Ã0üe% D"?Q¢iš_ÊkjâXÞ?mSríƒRJµóuxéKÿˆ£>º^‘† Ú±“ˆòŸDÁÕ¨¶­mO¿Íu],9ë¬\oUŠ¢Ìiz¢z«j„J½ `rrkÖ¬) ×ÑÑP(ä× …BþD÷k×®mô{@Ä®˜ßÁñ{Ù¶íŸô”z|P;‡ËJ‰„8áM&ÅߥÖWÓ4¿ü'}j]åbs!âSö\Õ4qÆ4E éz~¤‡m‹ ÊäõƒÝËžÄéß:ßþàY8òžÃæò*?D^³%ÀTUüÈ^¹Îj ü x¹’#j.${µ–ò ÖÐèø,Åór3 ùÏnî¦iæËάZµjV ÇqF1<<\õsTUõ(˜©%nª‹Å`Û62_ù :W¬Ààà Öµ=€+?z1n¸ýq·â÷⮸·¨4sÛ¶²tõ¬(ùc·ªŠãzáà1?L=ˆ¤‰Ñû I5w›‘@I@Ä’É)o/îóÐD•m~7—-šš”ßW†a CQtŠ|¼ã8~)A9ÊD~÷¸®ë*•‰ñ>é~9¯©fú>UU†a”,±X8’¥®ëùÒ‡lXºtiÓ'T‚xì$"ñI\lÛÊ6¤œÖqÑ>’eK¶mO]KÔ šPÉd2Èd2ذaCÑí7nD__úúú°iÓ&tuuadd}}}˜ÔÉuÅÞáaÀ²\Äb18Žã÷œ•#Uš‰®‹mrÑ£^öüŸ)gbš&b±XMµð)¸*Å&€yOÏË'" 1"eh(!fp°ø¢Ìç>ô9ìÿÐ~|Æø RïÎB{É_çÿMÊMH;…%LäöX`îôÝ@ø»€~Q]*~‰U,¸Ø#/ä°¶hókt|–bš@ì„Ü?ÝÆ93»œïDUÕiå¹fâyžѱpTJµäòX\ê³_k<èº]×1¹kìW½ F4 CU±lä`ôôœƒÈßöé@jbäÙ 8Qý"ЬmÛZÈùNä|fƒƒbôÉÐÐ óó%€fCôä¨.ÓG—ÊdŠ$’…“¶×‘ã8H&“þw%gšfQ»W&C\×õG™$ †á—âšú#“¥’¾†aøÉš©dfªrfš;m.¢N?}ø4±î‚xì$"ñI\lÛÚv®£wÀ…°ÝÄ»&'Ŧ ÏóØÑ›cA[Ê2øfÒÛÛ‹P(„L&ã÷N‚d2ßË®0‘ä‡ÊO=é ò5LÙáM®²¦ÉdÑôÇ*Šâ—*µ™›-yD•UŠM`þâsê\>š&r®ŸÂÄ ìüÖNœ7x.üÆ…€Ç„3W.À•Û2l"‘0rÀx `¿ˆÔá¢ëÔ 3²6:*ͯ‘ñ97 hWx+Ä„ì €xÏœpBÑç®Úã…œ0y®Ç]׋F‹Ú¶í_ts¥ÇlÛ.;òÅqœªz<µý÷ã<Æø8,ËÂÏŸþ0ODî¹i=ï\þ“ê£YÛ¶saÛùÑ(²l—,Íé •¥ïˆÄˆ‘ûYA>A…˜Ä}ê1°Nq#'r—IÏó°jÕ*Äb1xžMÓü$ˆëºèîîö'~—å$dXQtww#‰ÀÌÐùÑ¡º®ÏX&w¦Ä²Q¦>°±µƒgšÐ5‘úûïšýB$ˆÇN"ŸDÁÕȶ­e\ú£ƒ— âéXüïyþù¯qPTPÉd2èïï/ºmÇŽECÀT<0V”ƒ¥¼.Šx©”¥QªçY©QAÎ9Èm+5¸(k&Ö_Œ¬‹Å°bÅ ˜¦ÉÉŸ±ùˆÏx\|Ö¦ ÐôrX§]qžz÷S8êmG´£åe~gfgp0?Qòã@ä1ˆ„ƒò5ÝË(,ˆ %v®éŠ+ü HiÖºòø™Z‰üEOÙÇÀ²ðæ¶6D®¸¢êå„Ãaèº˲fì]] ™@ò'lŽÇã~rDÓ4¿gùLIEQ*–ó<žçAUUÄb1躎ǣQ³ù]ˆÅn€_iÏG§/(mÛ¹ò<‘H‘íÄT € ¨6 æ'š1s›ˆk¥'xŸý`´ŠäÜ#žç¡§GLR‰DL&ý9‘d©-9 Å0 †á_˜¦é>/ìD%¿«äeŽãø‰H$Ò”s—ÍeD`«iöø$jeŒO¢`š¯ØœÚŸÄþØÇÄ?ccP]wÖe›‰æKU ,£££þm2#Ùj ½Üð²R'3 Ë—e‚ƶK߉ˆí—I¤pÐ4Åßfù[–þ"šw*Ä›Üdðv>ŠïuQä*ˆ¡~“4‰€z`Ù€ñR@s J¦h¹íšc¨)Šâ—;Ò4 CCCþ<L¨Ðœy€ó@=nÊí¶ÿ>úhè¡ê³›2ɧª*,˪û…=yqSŽ:Ñ4ÍŸX^^@uÇu"ï/WvL&% «zzpg®gºiÏ=÷+üÝß-Û“„H85ówµ49™|)òÄ6u…Hœ #?âDVšô0¯‰“Âò]r„‰-‹ÅÇáyÞ´òZ²œW©Ñgº®û‰×Â㢢(%¿4MC8öçRœiþ""""šÓ,¸~jýîÏ ~ô£þýžçÁ0ŒŠˆÊÁ³yp?®ºê*ÿï3Ï<³è§Y?Ør„¾œ³AÓDR!‘'’Žã §§gVõŒ%_Z+hfÚM®›/ç ¿ÈÚÚÞX”– LÓôO^‰æJ–—›‘ qÁ& Üõî»ð¹}núEù :MH×Ô ÿ=p_Ì»˜È÷ü#Mӊ敉*•%áE"š‘¸7Ú»‹ož¼â üÇí·WÕÇÔT*å×ðŸÏ$_a‚ĶmÄãq¤¥L¨ app𦡻»Û_O ¶mcÅŠ‡ÃÓ.²×úß¿úÕ8óË𽯴á_þe—(gƒèÑOPѨè@Ã/Yç|X¥ñ÷‘$D)¯0D‚ÅåìTä'™¯™0Y±b…ƒ===ˆF£°, ÝÝÝ~,û#ÆJµÓUU±œ`*•òŸSMBWUU¿³GvQ%…íiÇq¦Í³ntøh!IDAT$GÇÞ_j.¦U«VùçÜñxO=õT£7ˆh^ÈÓ¬gžy–eub³mÛ/iNUÏ¡rÕUWaûöíEèP(„k®¹رc¶lÙÒèí©H^ÿ—9Ó‰9Om©ÑúòÂËl*A™"Ít(KÉ÷FU^8º®ÃuînQÎÄ0 ¿æt8öˬÍ–¢”)gCôˆM/¼ézï¡Øô«Mh?µ½øqÌû\åæ](ZeÛžsb9œ#÷Ë@|?à¾Ðþ qñÌE©žÿ‰D===ÐuÉd¦i"‘HøßíápØŸ‹¢p›Yê*`Ÿ¤>V|óµ?þ±?Ú¤™ÀhÔ(©X,æÏu0uÞ!I®[4õ>Š¢øs¦(Š‚x<ŽD"Ó4¡( žxâ œrÅøÒã_ÅM™oáâÛe†ìÙ_CÕ“¼¾gš¢ããˆ6°ëŠF¶ D#Ààg-1òÄ„˜eÛ¶…£Nä1WUUÄãq?Y";ôÄb±iß7©TjÖe $Õ’ßÕ¶ ˆ¨¹xžç—L­Náº.º»»‹æu]¦iúßY²Ó’ªªþ…¿ÂQ±²MQ˜<éîîö¿çäˆ9yŸ•'çJ&“ø›¿ù›F¿MDDu'«Ào˜výUž—EU •ÑÑQ àÆoDgggÑ}èëëC{{;®¼òJÜxãÞ¦²re•ýÉ×=/ŸL)EöPí¤A.£ÓMìÉ'X·Ú¹€iâ¢Võ9]ñÖ¨ê´Qdªªúe‹ÇÁàà ¢Ñ¨_ÅqD"„Ãa(Š‚¡¡!ض]”|iÖшT;ï‹@ªÓ’˜–ea¸ÜÁ4G/Ù–2f¢ë:V­Z…±±1ÿB‰ëºE½Üå2\×…aøâ¿ˆt:s.ºwìÙƒ¯ýr5’ÉQ8ޏh LªPÃY–hË9óäß²C¦‰DË  hïÉ=IÁ‚|n{zz ªª¬t]CCC0MÓOÂZ–…p8ŒÁÁÁiÇÒ¹&7E™qK)²Q3N@O´XȲӃ$“†aÀu]ضD"áÿ­ª*¢Ñ¨_RFv¬ßI2AÇaY– Ûÿ²¯ë:,ËòËÓÈù"‘ˆß®Ë•=°åë)Š‚hT”6–ë‰DüŽM±X ·ÜrK£ßb"¢y!OÇÇÇñʶ¶¢Ú´ápxÖ×e‰æSU •íÛ·# MK¦Ú¸q#LÓÄèèhÙÇ5š<ÿ‘É”Jyyat¶’IQÊ'ˆ×ER¤ô}…磪*kùQª ¸®âÑÅb1„ÃáFo5)Ëš9Á€.zuýÇíÿQÕÅÚ¹’=ÎdÒDö“'Z©TÊO twwC×õ¢Éi-ËòO d’Bö<Ó4Íïu+'³–„¦Òߘÿ Ä>)ÞÇÌko= .ŒÜˆjÉ‹SS ±XÌ/k¤ë:‰<Ïóç†0 ñxÜß^×u1<< Û¶ýžýò„S>ÖóYpƒã ™™5Ó>—s–ض˜å㊢øß7r¢é©ÃËe» pޱ®®.8Žƒ§Ÿ~}º‡·ëS0Í6DÈ—'d§vj€pXS††òm=Ûž>J$ À{fû •ÉÑÍò»Bwd -yì”eräÈ0É0 $‰º_æ’àeÇ¢ùS˜¬(E–³•m\×uýï ×uýsSù]¢ëºß‘ó&É‘fápØ¿]&=<ÏóGÈõDBÕ²,$“IŒ!¶müÿöÎ=>ŠòÞÿEQPLÁ‰E1ѪµnUT6 ÔRËq7ôb…VvÛžZÔ“v÷ç)ÚÒÚî–XKõسƒÚÚS’UzÔ*ôd¼µ/ÍX«‰7d*,x7ÃF¬\”ýý1ûÝì-{M¾ï׋ÙËÌ>Ï<óçû<ß[(2¡ºp8lêØ~¿Š¢˜‘ÞVGÄ1cƘEQÌ(ë9=©·(Š‚?þñÕ"†a˜’c>5àþcîÇ_yÅP^ã:W®Z— SiòNù•J[[“Þkhh@4­vŸ2¢(†,jšñ/¥neä]É¢G¹<ØKóùW’†^#—ËØ‡E©Ðf1‡à1ÃÁšbn*—‘v§(@ƒMQø|>H’”´¹ …ÐØØˆÞÞ^H’¿ßoÖY ¬i¾DQLò†#£ ýH#”šF€®Gèv@Zl\QŒ{ ¯‚ÿ°]Y¢zR …#õfMŸÀ\´ZSzц2-.éóÆÆFóQîgJeZkJŤkÀŒ˜aƒKí¡ª€t8à<#þ†¢`ÿ×¾yüøŒO2NR½”ZÁzfªÍ Íß~¿çÞp~ñ ÜúÒ­øúØ'átžQ‚±Q½5穦¤„ÃÆ|Bÿˆ´"9 =q8P$d0„Ëå‚Ïç3Ó{Q¤€Œ©øˆBœœÊu~c¦´x½^3Êš äÈ$ôkJ‡% …àv»Mg&ÒM(Õ-ÕN£ìáp^¯Ðu¦sИ1càóùLƒ0¾Òš½»»;IŸ·¦£¡I†äT¬íd4q¹\æyRÓ:N¼÷Þ{Õ"†a˜’c:~kÀa/†içO3?£yu/ÆNäeP©¯¯b(ihhHz=88ˆþþþj÷'+š–¨Ù+R_UUÓä<ž,Åf{Œ…%åT¥Í릦¦i¦ÒHI’ÌM\Ú ¦|¬¹ÅÌÑ)ùàr ð–ãoÒï(% y2L.T5‹a` €n@43â£x½^3ßçó™ ) a\èíí… æb̺ÑC!ýÖ‰îZüéº§Ó —Ë…ÆÆF3 †ÒÓy[¿l½$¹–Q`!sþ‰œ€4 <_­¦L^>Ÿ/kÚ#«ç}êùÂá0¶nÝjzÎQ.ép8lzñQêÊïóù išÙçP(d.†­í´æ®fì… ¡Ft»ƒøï‹.‚ÏáÈ8f”Ng´Œ© …BÐ4 ]=^ùè#ìéîBpâ)…â×®Fí§ÂÔ †^¯áPÔÛ›[/`¤—,oŒªªhmm5ÓFêºnF¨¹Ýn„ÃaȲŒ®®®šô6¤z Ãd‡ô¾`<ï¶um­i$I2£>(²ƒ )d¬ TX.Iz{{á÷ûM=´µµÕ\““!I’]nÕÙ­Æ A’j£Xu~«!W’¤¤hÛÔß!¬ëál†âtëfëwÓ=gN<ñÄj+Ã0LI¡;elÒ›ÂØ‘¼ *óæÍCGG6mÚ„yóæ¥ýŽ,˨««ƒÃá¨vŸ2ât‹IKÔXFŠÝÄUU$r§§ iZRò—$ ßùÎo°dɵp8f›5 H٤ܮÜÒÒ‚P(„`0hnŽRNØL–[U5ÖÅØ<Á¨£(†aj„“¡i›ÑÛÛ ·Û]Tanfô’A'€»Â%-„N)«Èë-UÆ·¦ [£`ZŒ¥~–­}'iQd]¨ÑŠRk¹Ýîø{®´†§Ó0@¹D@¾h•€@ àê‚QŸ!ƒÓn&ŃR” kÝÇ“t~ò´©ÈsòKoݺÐ4 ­­­I•@ ¯×‹®®.3§ôhÙˆ·;~¿!³¾óv€ýû÷ãý+¶®[—ñ8UUÍÔy£ Q!þü爞pŽùþ÷!¯[‡1cžÄ‘ƒGâÚ ¯Åu T˜²AõQt=¹6^â 0RÏé¼ñ¿ÂñE¬W)µ Õ=¡Ô;Ö(6Çcê²¼8f˜‘µÆ9ú)ŠbÖN£”W­$tì+®ø¾ò•[ðÀ+pß}ÿ‚¦õàÈ#Ûàñ\…p8ŒþðO˜>}/þüçõ¨«; ² ìÝ{%\.² ŒûM¨ê¯ÐÜüK„óãm2žƒ§v;^xápøý†3’®Ÿy<ˆG õ£B!Cß …€sÎYþþ3ã©8Ʊ²lè㺞H]¬iqÉgO5©4-Q›ŠÎ-I‰u4`/Ë0Ïߨh´ËçK<Ç5ÍX»S–™3O¯öp3 ÔA0ž“0¸m[궘õSTUE0,›“-ÃJ^•††,[¶ Ë—/DzeËÐÖÖfF¨PÁúÎÎN¬^½ºÚýÉŠ×kDgäÚCÔu½è^º=@#‚#„SN¹Ó¦ÝIšQ” Ë@8,A’€¿þõ+øä'¯„uVŒ§FËø|>{ìWqÕU?‡ ìD"ã jEc³\›‘Ô>I\®_ ¥¥ÍôB—eÙ4ª°a…É„®gEòŽ ao¸¤§ßï7Ãè‡+…lüä“/5¢åöÛOƒß§éGR'þÛ"àÙ ³µp)d õ~À³<¾@< ÀiT'ª´À³yܹ\.3"‡Þ§kf=Îår™õZ¬†%òFt»ÝæØA†¼É€ M/Æîîn3ÒÓ–QŒG•µ$ÞÛ÷ÄÜuWŽãÄ’Ek — õn}àì^ú#lßþE\~Ý~œí=[»·-zÁuU˜’ÓÚjlÆe=/Ì:e¦a¥†3ƒˆŒútƒA¨ªjÄ5MC HJ›yh}–3 co¬å”Qá[ßêÀ‡žŒÃ?>úkŒw6öìy'NÄÁŸ]_‡ýû00ð=Œ"î½÷n´´¸{ðÞ{õØ»÷2pÑEÿ‹§žú6o>)nà¸ðÌ3â7öbêÔ/BQIÚŠûî3Ö º~`Û6@fãCBPàÝwOƒªŠX´hÆŽ5žƒd˜hi™A0Œ~Â90LVºº Ã`;å|x<À¹çߣú«t=hãö\.ã7Nã|ô]ÊŒAQ4jZuI†úÛé¤6ïS-S·Ûø,.¸àäjß Ã0%…jP‹"ðÑ+á°óN6r‹q'†±y×PiooG}}=dYÆš5k’>khhÀÚµkmBžñÔý9¡BuŠІòDž)Á ‡ã\sÍBsÌ4„ÃÀäɆÂär%çÆúWŒ§Ó0h(бîí~÷»7ðÕ¯ú°x±AH¬­„!Ãé4¾Khšq<=¦TÕ8/íÐæ]'·Û8=g) …ÄB¡DýCëûÑB¯)c˜¦kþ@ ©Bj­‘|>rJžxbfµo-†a˜’¢ªÆóîÿÌýøp‡æÃ9 òz’±%Ã*J¿lÙ2,[¶ ===æ{õõõhjjö"©Å‰D‰DÐÐÐ0ä³B EÔs¡ë:‚Á`Æ»ù"ŠÆïýóŸÏàè£#øæ7?ÆM7-0€¡PE݇km§¦%?òŽ¡óÀ£Î·´ÝPÐD…êœxì±~õ«;pË-³°oßù(°,LF|>`ÇŽT•Ú˜ð§Ú/TW=íO&ÙJ+Ÿºž¡†ŠÀilÄZÃÈ ørºµTк»»;)?»Óé„®ëfZ0Q!zÄ‚]?„ËÉ @Â×ꛀúw  ^ȃ@è^-€z5 ýÒø Œzˆÿ­Çÿ)0Œ[¾ø?/k°#5LÁ”>-5ï´®ë¦ÑKEôööB’$ƒAóÙLÏÔÈUU±uëVȲlnàɲŒ›o¾¹ÚÃZR*%ŸVhãÀ%Á¬Ÿ¢(JNùTUuôF§¤pŠ®aêô»ð§?-ÇI'­Goo/¢bâ—&B4|ðÁ8Å{бÂÔ,•Ôm3¡ë9Œ)àÐägzÈÈO)z¨›*KQ¨ªQóä¸ãD,Y2tјÏOXÛìóÊ¡5l8õ|éÎ9gN.Š/€HRi°—]6n7pï½ÆëSOƒçŸ?'¾À¸T„[–eÓàb-ˆ …¸V‚MH'›@éå3“s÷s»qË-· ¼#s¤F?”ˆ+;pÂ0¬h0Œ+Áøû½–÷„øwº`D´¨HÔÉÑag4@ôÏÊlcžéÙåóùLƒJ*Ç{lµ‡´$TR>­(Šñ|w ©ï+iÓ»išf¦ù¢šZ£A@Ý¢EÀúõðù€×ŸîÇ5¬Â™óÿŽ«{Tyº®ãòÖ˱÷Ú½xì²Ç°ñÉÊŸn)žjè¶V(B˜ríç$ÕTQx½^ø|>hšV–aÊMµæÎBQÕDj.¿?‘šœ) …Rt¹\ñ9Ú•HEuCHòx€ÿø'á÷¯…¢(fJTA°~ýi„ \c¦K¥èÓo;±pa3.'>üp æÎjÍfh(d3¬õj)"Ûk‘bP©5ùd˜ÑD%u[3ºZvÿûnÜ|íÍxÆù Ï<Á{ƒŒ]©¸A¥¹¹ ˆD"Iï÷ôô ¾¾ÞŒ~ijjBSSzzz²Z;wïÞžžžŒQ3ªjä#ÍæžðŪ¢(I©zÊ™ÆÀíÎÞŸL‚€ÞÞ^hšVòE±ËôZ^ý;øä'oB$²=ökÓ!ÀÂ…/Àéœ6ÄD›Ä­­­PÅ,ÂMŠ=mÊ¥¦²===عsgµ›Q2É&õ³ùܹs'úûû‡¤4 L¦?æÿ^ý?ÜtÛMÕƒp¹\fÄÙp=fkò€^0Ð]]]ÐuÝ ‰¥kñÀÆSÑÐp8 ³ó¿!þó?/Äÿ¬Úƒï¶Çdì‚2û~ø'1þ<,^ü&B¡‡ÃxòÉ9ˆDŽÆºu'áûßß/\3ÿ~îxÈ1@5\|ñ‘8ýôz#b!n$Ùä{GõÌ2 —`T<ñσñ×¾øßVÊjü{ç¦wŒÂÈ¡Ä{pÁ0ÎЙöçõø{: h뎿ìŽìÆs»ŸÃž={ª=d%¡Ôò¹gÏôôôä Ó6‹Ñ*07aƒÁ þß™g»=–Í~MÓÌù…"…8åÌnǃ /< ò´Ù¸éš:x§4TÁ`¢þ‰$%Ö`VÛ;MápŠ¢`÷nŠ¢›)U»ºº iZZ>+¯4tÊ|k] ‚0ì9¨Î|£‘ÁÁAôõõa÷îÝÕnJI¨–nË0å€uÛütÛææfÔÕÕ%}fúÄjÀŸü1.n»Øxíõ¢UyaЦ¿¿¿,ºmÅ *¤|Ö××é`êÄW__Ÿv‚µòÁä4¨d³PJ lŠ!E¤óUUn·[·n5Óš”;'t1k[MÓÌ:¥^$“gÒ®]“±páÇxúéßbΜèîn@8 Èò4³˜Ÿ(&F-!)-ŒÿP–e´¶¶š‘,º®›…L)šÅZ¯…<®¬c@cLšR2’™d(\>wî܉¾¾¾!‹NZ¦¢iŽ:ê¨aSt]ÇäÉ“Í"å²,CÅiLIeòäÄuL]àú|¾¤ôV¯½ÿúÞŸ0ö°Kð©S^6S$ƒ‡A’î‚,«E>:ºƒ~,XàÁo~ö/à±ãqá‚-X·nydÛ¶mÃøñ'â‚ ŽÀ† S0mÚ£ø×¿ŽÃ‰õ{NÁâ1Gbù“‡â™»Ð雄›´? é°ÏáÉÖÃ{õD`ö'œyÚÅø¶´êj/àêðïÀɧ|ˆ·Ç¾žaD·hT@wê4Á0®A'n\ @Æýp¶J[GŒA¥ÔòI‹Î\ÞDª øöèà1ž³áp~ÿûÀ“O&}— ²%=´Yå9ïEµñÑO?†³ŸùþmL Œùë–ßÜ‚Áéƒ/ŒÇÂxí™×pÖê³ð—sþ‚½×îÅ;¯@(‚×ëR¼VˆD"èïï² ªU*­Û~þ5M\’òKUU³V½.‡žÈÔ¬Û¦ÛŠ×kxçvuÆ{”]Ò Pm ·SªªföëÚ§»»;IW4ä[…Y-O\.×?ªÑh===øàƒªÝ”’P-Ý6ºž0l2Ìp`Ý6?ݶ¡¡!­AÅéïDø*KÚwIBWžÆ~†ÉF__ßÈ0¨d"y/Ÿ‰pêÔ©CòmZÉå±—«H:)¢©𦡵µ]]]·˜“vZ’$x<x½^³_¥H'âr%ÿ9sŒMÚ3ÞÅ7~’ŠúýɯÃá„´$E>Ÿ‚ÜyçYxýõoãðÃïÄîÝç@’$,^üMlÙò´™ZÆçó™.—kÈBB³n ] 0×uÃcKÓ4³¥Š ‡Ãf,Ç“d€Óuíííèèè¨èøWƒBåó¬³Îâ©ÞuCÊ*´S¶MÁ¼cæåÕ&2°)ŠbO¨II ª“’44_ ue[E2¦rqçÅg£ëÀ§.ÿ>ï16ì ]%ùaixCχ3ÏÄß| ß½v$É ·˜3g&.¿|®¾ú^øýãñíoÇÿç~ˆå+ŽÁcñft/þØ?ßùÎNü®ë\ôî|ðO±aàzœíÇYgMÀëÑ×ñ­GžÅsÏÍGôý½xóßðGþxên<ü“3ñê©Ã禽€+ÃWbÃ%ð×ÍÆô±Øôñ;XÿàLÔï:€è¿E1ù¡ÉXàËGOŇ^Ç_7ߨö0•BäsÒ¤IYçN€hB¦‘3ìÃãñàðÃOú*Õ·©ÅÍýŠ“R‘wÓ„û¡m< ÷|ÝEqõÕWã”SN1#ÏüäÅ%¸pÝÎn@V]¿ÊŒî¬52 zzzªÝ”²R.ÝV–iÈåJÔOÈê0®ÂaF„ E¦Ýn7$Õ ƒlŰn›tºípðû yõû '32¦XI8ËÿçšZ)å­¢(-)RHŽ3e'$iØÆ‘|#Y˜ÒÓÐЀöövô÷÷W»)e§lºmh^ 5-%›arºmvré¶Â]À?>þ‡Y^}zLáÎØ¶¶¶œF¿B°A%gB$)ÚûÇëE¼øÞÐÏdYÍ`…6ÜEQD8F €(Šhii©Š!¥TȲŒP(d>˜‹®cUüÿð‡|ðxs`½þ¤‡Óg^¯ñ¹Åb(1n·aÛ²¥Çû[Œ\sÍï (".ºèlÝzü~`Ñ¢õðûýøáÿ‡cvü·tÓÐ’MÓàv»Íº9d Ñ4Í4 ¨ªj¦p£¢¬¢(Âï÷›œdTÑ4 ›7o®ö°–•RÉ'yá¥]‹uçnÄž ò:W86½á‡L²Fh…a©ã¥ûÁZkƒ DX5fU5 $kÔVùðz ­›UW Jù0\¾×÷*^;S_pF^Çœ3ïüáÁ:ó9aìßN¼øâ瓾ûõ¯/ÂO~|gÖë¸úÙcÑxë.|ùËÓñË_‹~]¿øÃDgYŽš øÔ”·ñÊ®‰¸á¦CðúៀvpÂü3qóƒGà&½†ÓO[„¿*ÀG‡ÝŽO4§>¿—胘ùð¼~vê{3°þMਉïã„KwàÀ;ÏVm|*EÉçÏ t¯CRÄ¥ÈD8l¾gMõÅä5Ç»(BøÁr¸s®Ÿ†áyȉwÞ¹§œò9Ì™ó#ìØ±iIC0ÆÇœ&HÆæV04Óeʲ —ËY–M£ M­§ «5Ê¡ÛR*[Ÿ/ÙÞŸT:@átî… å„‘n1þ¾¬Êp Nhš]ׇäJæ˜Àd‡7C7Ñ´d‚r>IR"é+´ûGïKR².C…6¬Å7¡JƒßŸ8G(d g‘JQ®µg&‚Aãr‹¢áT$ŠÆëBåÂá0A@86ubUUÓ¦±Î4?§sèzò!ZÐg©b¬²«iÆy¬aúŒÖÖñ +8?6dÏú*’CkŸ/ñ;ºŽ‰#$¥P6*!Ÿºn\RE1.9=EÑH©Ì0ÌPÊ!›âX@ºøáWNÚ“œ^ôûÃåZŒo„ù›€Yö!ND͸\Ægª 躈P(„[oí¢×3<ÑÜD HjS]Ýí¦Çfª×æhðâ+•|* Öv=´ «Ž\…¶oçöúkii1S@–‡ZÜnCVhsAJÚN$ v:‡.¤$)³–èî6n ¿ß¸}¾dÙôûÎ:‰“u£ƒÂ²Ä&Jž…ˆê™sÄÇïßû^~ƸâŠcðÛ߿ߦ@ˆvîÃc`×·§Z.oö~þñº£á½ðÅ‹Ô/ùwcˆ¿üå“ ëÆ¥6.å·—yí÷>Æ£/OÀ¼‹ÆÁã¤H·O!Ž›}HA×µ–(ùü©ò^ |è¾"ñ6Eú –ä픟ݎ5®j‰î‡‚¦µA×#ޏ·Ür0&LhÇòs.¸x›©„Ã<c£FEÀˆAcî:ðÓ8ásMŸÃu<Ý(ª1·{<øýþšMV«”C·Õ´äO§3‘BÕÄÈ"ˆYÞOSÁÆ ‚ñ »®bžG2¤£“.N,Âjˆ pQ«~¨ª†."Š =ÀåJþmªR^§T½ƒ6{Óå/–$ã½ÔÍZÏê#:3­º‡åº®ãÐþN>PDn¾û G¡xêÜÑ@9מ©„ÃÆm40l%{Y.(ê0ÖY^¯×tfðù|ÀäÉ“‡]¼·"òO÷8‘jœ“b‚le¢Ýn:VÓ†ÿZZVÓŒ#-0u=!c€¡TƒHòú³þ2i§0Ηn Ÿ dƒŠÛx¯¥%yñc5æ¨jb‘šJêÚ@QŒ¶ë:w\ùÇ­ÊTB>½ÞÄ>CWWòå6k:0 “D©eS½ P~ x€Ç[Çß1ŸªªBniAh”è$LmbƒŠÃá0ó‚:ô÷÷#‰`þüùŸ3[áë`08İ8N IJ¦¨iØš:ÓNžœXÑllÝT%Þt pÄ"MQЦÕKPÓ›¿tœõü”äÓÚ†T…/ ©›)‚ @’$sqít:ÍëCŸW «])uÃÀ éž4´ž¤õbooâ\ªšpÒóùH‡•àpHñ{!C¶-Ò½éüo¾ÙŒ—^º€ N§ñYK‹q¾‰'TìúT‹RÉgÆu› <ðæy§ùëë¯ãPr’¤¡7H¶ô7OîʽùÜó‚!Ô C‰,N=Z¨¢˜ù\Y(t_ÔyàýÕXÜ2Ì㆓UÈç¾ýø|üÜÇÊû8ùm@º4ù½lÃåtw݇ Ç<Ÿ/Ù¸éó¿ÿ}aר–(éü©ÿèJ¹%É€)s’ Àï÷›Ñ}LaX÷—ÚÚþŽ÷݇_Î:êÞO!(_ƒƒßù<†ñΘ§ÑÙ9ü+<úè¯!D3ÓA®ƒ€00A›`l¤«€3è„Sw‚‘*ì/Ž¿à°y‡aÚìiF†?^£”•Rë¶´Ÿf5ŠðMši½3-ér>ŸÏŒî±iR ©º1C¬Æ 묪‰ü´‚0Ô˜$;I¤Ë¹&IP»ºÌ~²,C XŸ•ñÉÍívÃwfT£Ž™ ÅLG+ÄŸµ¢¦cOiŒo¬“Î.Ë2TUE(«¢wc#º»»¡é:¯ ©ª*Úëê0åþûqüå—ク}Í\÷´¶¶Âçóá¹çžËYçÖ)ÇÚ3ë­˜NÍËfÏ 'EQà÷ûÍhzAàr¹†C<Oéça¿ßÚ C&R£¨è;$ÖvQĸUþRåÑåÊíMy¢iÝœÎø˜ÁAÒ„RVÐïe2b†¬çÒÉ­¹«ÓAŽWäad%Ý{©¤»>ŸÙîþÅ‹±#›Jȧª—5]º¨šµ 3’)µl†oœ[3Ð\Ç0vÆ6ÀÈÙ»|ùr477£¯¯íííEuÊdP!žtªª*EIÊÝÀPS•ª˜‰\ÊR.e,×ç´¡«i o—äÎJ.m8g9—(ŠfN\RÖ)5–S›eÊ)œn¼%)Y·„DPuor‘Ó9¬ö±3vâ[ßú*\.^¯1´Æm±zõ˜;wäç²-V>ãNUiÇ(ÚÅÍ‹nÆ3ÿûLÚcwÞw¦OŸHZZZ°î¿ÿÍÍÍöNMA›0™>Ëô|°.NS®iNSˆ½sß´‰Ð.ÿ%8uîá¸ìƒŸ÷1®+†ïöì˜Åøç»_Lzäz4T€ÒÌŸÞF ”€çüø½¥i€,ãÕÎNÌ~ã ,^¼Ø¼¸´ÉÃÅ«K‹$I˜=m„•+á -€ä„–ùÀ8zýLÏÞ€u^ Iº S¦ŒÅ«¯¾Š‰ßÂÔ©ßÆ~p,®ðcžK€7§@Ž»ö8¼>æuà@]©¢ñŸ8郓0ÀûóÞÇŒºƆ¼»~=^ýu|ãŸÿD €Ëå‚Ûí6#óׯ__í‘®¥^{ZÑõDZãᨫ‰âv»Íç«Ïç3ë¡S‡•Zœ¦R”J6ÕG€p?Ðû°ñÚtü‡ާ2f;S5ƒÊÚµk‡¼×ÖÖ‡ÃH$‚†††¢C:3kƒÁ´Æ]×á÷ûŒE¦® ÎŽ3«U¹LíyØ„ÃÆ?¯7C¾¥ÔS&R~mݺ­­­IÙNgM§ ¡`¡ÔË•Ú%ëóû’K¦@’Záñô&yËÀ”)kŒ/¾t² /Ÿo⇹Y·ÿ'ûqñâ‹Óç÷ûqUg'~rÆ{ÖYèêêªéû//(Ïykkrަïy<€¢ @Þv”+]’ŒÍ£tÞ´;l:Æþ ò­ŸR(b3 ô6¬c$iøÚ§¾Ž±}ªÃ2’)—|†o3‚S òK€Êâh^}ï=¬œ>¿ýÆ7Lc möööB–eƒANT"LýdútÀå2‚Hâ«~ <0¶Í¼†¡ú¶ßór>~zçýøÞ7Ú°lÙ{˜4éxLœø#.Ìž= ú„éð‡)S¦àøãÂßþ¶¿þõ©Øø£]xªi'š§LÇcÎ0;t(f\h³·n{³3ÏÁùgž¨ÀW``ÜêN¯$`âï'âé±Oã’o^„US±ûèÝ8äC€ïçì8Z‹Í¥aßû°ãù¸s˘qá ¼ýöÛ˜›TíË]RJ­ÛR„mwwÂvº¶¤h]󹩯ÝñÞûî{p»Ýp¹\ðù|fj2T…x”„™Ê†:”=BÖ#J™cÙ(Þ5f 6]x!>¯kH† -nd$ ^U5Bü‚ù½^Ó A—Ëo܈AÆAŸÏgFH’„@ UUÑØØI’àr¹‡!Š"œN§yœ& PÅÜÜEÑ4$0ÿ¦×ªªšFG:fþ‰'bà _À”¶6‚Wp:'7õsú-añb÷ûßc£(šÏŸÏg¿`ÁÈò/×Ü™`и}éVφßïOº—èÞ¦{P°ËZãÈïOGε™e5¢ÀU J/ÀØ’JȧÕù@Q`:Hfºey—a ʹo¾èúÉ¥`¤q:!ŒÖ_LMa«%Qf©¦´Ï7t“œ<»R”>©0§ äŽB±;”_9dd!mßåJϳÐÕÕe¦A#SUUÍTä=•ê¥jW(Òz8MEqHÑÖÑH1òiÚ$½0 )"ÌôB2äŒé¾œN'Ne|óŽ;’Š+X¬š}j ºyÝîä/yâR:†Ô±µŠ±¦AÚ=§Î>+±i¥ªÆFy‰å75¥|¹X¹ò¸¡5F!Åȧ@»pßûÔ—&š·¡&Џäᇠc‰åÞt¹\æmÔ2%Æjõϰâ÷xH'^/~àgWïÁ}Ž«që­—Å áQUlõ àÜq³ðò‡ãñÒŽVLQàrµRSXÒ¼”ú]šËéÙDiôN§y ÍËÆ5M™°¦¥ß¡š^ô›$¿Vc†©?Ä @BþÈé×jp±þ¾õꯢ(f:N<Õ¶µvA²Lí²¦î¤÷Ip¹\¸ë®»píµ×V{Øk‚ðƒ€xAâõÞ_„îñ N¡W3šša†Áˆ3¨XK†¤"Ç­œ©m¿ßŸœFˆ QŽt—„tš~íÿáU«P÷½ïºAÓÐ/òIŠž3ž‹âÉÿø|å†ÌüÐ4Áa…&5k:fä£üÀSn27ʲœ6UE“uuu‘TL‚á*ToÉBȘ‰öS!ÙLX³&O]è+J"â…ò»Y³µÕ8† 4Ö• -Ñf /5áo®^î’á{µÛ[Ú°LÈ›‹(5DJÜâÿÒFÅë±]Oe¤i}ãüà…0ñ¥—ðøáÿØxÈL›6 ÀGèï¿î5kp€¯8€]cÆàÎÿ‹_}ü1€x4“ªÂýÏ¢®®'¿ó ýÛ-øû)ŸÇôé“|®ÚWÈ–˜>Züí»{ÈÉï}ö¬Ø|Øk¸jêU8®í8L8|BE¢{®¹º$á˜+®0Þˆ?Œi£ÁÝØh¦$h£j÷‰¢ˆÞÞ^só6Oèþ´Fz{{‡l2çó,*åµ Ý•Ò§CjÔLõW³PV&TU…×ë57&ÓEÀWm#É&X”þŒž´)LÏÒMHɈAŸ[ +´ÑKÇ(ŠŸÏgehC×ï÷›5‹º»»!Ë2$I‚,Ë…Bf=*Y–‡ì%q„ ÃápÒF6mÞêºn:R;}>ŸYKÉ õO³žï7Þ¨öÙ¯×XФfN¦mž\·z¥Öåjä £ÝÖL!t_Z#ÅéØÔ:^t¬×²–¶ERëÝÑýMòG‘›ÖúGóe¡ôùV'j×ë…®ëfÍ.ªçE‘Ÿô´IÈéÙ=B²m58¦¾o8±’)b… +éŒØÖs'ß¾!Î’$ᥗ^–-ì,”âT@úJâõº;°â¦›ÌZaù¤;e˜j3¢ *T´3Ó M%0~²,'½Ç¤§î /L¼¡iɪñ"¡Ÿ–$`áB8; ¢(Âåt--˜zðÁ8âž{Ð:0€Ö®â )Mšû|‡ÌžãçÎ…¦iðù|IE?­ 4[«kåw€ó³bL±z ¤Bµ{4MƒÈéÖ*ÅÂ[å¼»;³Ç¬Ï—}õÑÝm¬bRÓ•éºal¡¿)Om2ɲáb&ŠÆß¡Ð°6š&îÛWí+io4@íÝ Ï!Ëß%{D“·$AÏ_6¦Œ`,aeÖz ˆo˜Ï‰mNêqƒÍd¶ó›â¯ƒÁ D— ÇÇ,Ο÷åÕ«188XíÛíU@hà„aD¡ý;!þ· ËØÈxÓïÇ1}]â‘J³Dj’uƒ†p»Ýæ¦J@QðåÇÃ'Üܤ A000`:ØX½´­D>Ï»E©Ú­=Œ=ÐõÌjеæX5Ö3´IKÿ[7+”$j‰œèèùA’¤S„Ãa8Nx½^3ºÄï÷# %¥Õ£çBj-"ÂjØÐuÝ4zÐf¬5zÖ’äðGžçTO‰ ¼ô}znÑZ$¯Û”-Å)µ7õ«!6µí™RY@SÏ–.]Z²{b$ Ñ(©ËKJ?Ï2‚JSæ£òZ£((:ƒŒ@"’Ãj0±FuXÇÚ:ïÒ½I¯é8Š'=Í9‡Ó:*Z ¹ ?7뼜-Å– ŸI2¤HÑÛëŠ÷/Gÿ»\Ó'O%3à4¿/€¦‰¦ÁZ\–tÏ¢ynAp™‰W¬Ù¸ @É<&9]ªhú *J¢¼›‘A4ŸŽ“e@Dx<ÆU×%3 ª©é\<ñă¹ošÑŽ`b°i5\Šï̈aDTüþÌ)R)²ÕŸêyk¢ªÀ%ñ÷Ïh–édÒUpSOšt»»±åÎ;ññi§Áåtb’ `:`* ‚Û œtÿþw²y3î3îø‚\—e4 ÏŸt„㎃@µxC4{,¦¿ù&®ºê*s൸á%ÕC‰©Êó@èiÞ·„Ѳ,CÓ´´ž¨L¡JÇ©ïC œBŒÎ™-/†Çc<_4Í8>Õ#X–ŸÉrò*Éëł矯ö•´7: `yÑF?S™ábõºµ>ïÏ<óLôôôT»y¶ä½÷fÂ5 ÀeèòYEÏß Q4x½ÞD”uµÖ !Y–Mo«Þ ƒš¦ag_þuß}x8G^#ëâHrˆI282 ŒÍ·–c6Õ.á÷ûMoïrê·´¾%éT£¥ç!Ã'9ÌôÌ–÷HþÉ0a HŸÏg>ƒ(u¥´¢4Ûd!CÉÎÖ­[Í`«¡"Õ‘/‚ $e?Èdø ¹M5häJ ÈÔiJšäëôNäÖÛð†þ‚çž[‹ >ƒ7ÞxÃŒD8ä>¼öÚ™˜9ó"45½÷ß‚p-^|1†½{÷âøã'¡«k¦Ybìê«wâ‡?<¢8´1Šb¨ãñä$cÓž=Ðõ# G’Œ¾NžŒ¸SƒÏÌêNµc 〔´„"cQ<ÛB¡¡ !\.c‰¥ª‰%‚¢$¬çèê2üæ²C5âèdÈÐ4cGNÒÖß¡ïÐØ¤fˤ¥"¥@ÅÄßôÚ(|žø¾õL׈Îe=‡>·‡¨sæ|  çn¥¨@PÙ IP,NÓÁ`£S˜šaÄT¨Î¥K¨CžÝð,ZÿÖ Ñ%Aaà_;ÿ…s£çb„ FÖ›ø„ƒ€ÇèñYC‚±ˆå”2¹Éé#ŠXtÓMiÞŽÏHqO†ºøû_°#„ÏçÃk_ Ô×㔸vá «ªi;ï0nÿ~ìùÓŸðñ–-x⥗ ÆÃ6u]Ç´;qÖ† 8~`ï8€I“&á»3fàë·ßn*ü¯<¦OŸŽ?üGqÖŽÑ!3øÈ#xÿ¨£på5×$ÏÒLÞ¸ÜHk” ‡ÃI  k¦E3)Dv¬)ÂR=¤<cÐÚ:Ô-4BxéR°^›=ø®;hˆ žµÞ˜®ëhii1Óî0 S^Ž<ò5^‡Yk,]×ÑÚÚ I’àóùJb¨Æw^H7"læÆ)mÊšúÛ•Wæ†×^kÃÔ©cpå•_Æm·MÄg>ãÄ9çÌÄ®]»pùå“̨ŠtH©Un»\€$MÇÂ…éÛ*.á°a¬ðx†úžQMë¡çÊç:XJ M1Üs¤³u¦¡Ó}ÇÚŸBƒé¬Ç¥;G>×Ìj¬K=GOÏ{`_¡Ü(«ß€sßcÆ Q„\8ú—©-FŒAËaD”H0R"øŒÿ¯’¯B×ߺ0Iœ]×±òÅ•X¾f9&œ>!q°õáy›+yÐcC8€„Á†,ÖWü»ÖÏ<TamtN5Þ>Õr¼?~~OüZ¼ýzü}J?-YÞ£v[ }È£uæé§Ç¯cb@5W·OcËùèwÄøç4nzÊûjšsÓo³:Z5TuøSÕí¤”Y5å÷ ñ=‰d׬äè—Iæ_¹–!Ãm—Ó™H_– /y˜Z&üH?œÿ6,6^»Ýðù|ðûýYÓ*2ŒÝ1¿ðìðBòûŠ¢$yÓišÇg˜yúÌÌ'KbWüÑd%P‚¡<åÉBÊ¡UO¥Â£”[…ad‘â¿íDB¡ [þö[>£Å7u$ËÿBüûVe>Õ8S£x<´´´˜E3zjZ¼$­¹Jéÿ/» p ]:Ï]wűâÑWÂØÌ ïÍŸ{,~\í‹`cÂw82Ùf©ë:¼^oÒ&­$ICoÕyã†ÉßÞ 8›¯© $mÔ†Ãa³Ø$Ã0•á#Þ\ 'B°NÀã1½É]ÖúS€±»’2‡¾ûoÿ†Á³ÎÂ·Þ 綾âàÙ³ÑO‹‡ñå;pÂêÕp{¬1×ê:„ÔWÖ!ÖTüÌeF)~8ÁÈÕ¯ÂXWy¸ì¤xM×0aËüò‹¿Ä¤3&ë: G8r¶‹ÿÌägpʃ§`Û¶mسz¢‹£h™Ü‚ÓÇŸŽ}G샾@‡OñÁ£yŒõžŒÄz€ ç>F扵ªcª ±ÙOëIúŽ ÀXؤ“FÛdËñbü¼îøë€åsBŠŸ3Õñß Ä?W‘pTX‹º,‘¼FõY~ÏÿœŒŒµ9¥J×6Oü=%ÞÅÒwjµ…ÚAç ‡G5þÏj³ö]Š·KˆŸÏÄš^Oi—/þ{2F!kÑò™õ|0Æò‚W.(äÖhZþå)Í48§š;v‰¬ÅüûÂ0µ„º¯¡»¦[jïÙÌÔ#Æ ¢lB}©o*Øð­oÁÕU€¢àgwߨñÇ'òy•«’¾Ÿ÷Ñ*çà 9tæxOŒ¿öeøN:{Õ È†¡ê04²‘2§ ¡Ðj–ó“N<ÂÇˆîîî²ææ&¯M‚Š(Š¢ˆœ(3+úLÀùé70UÛ¾øEüùÀˆ^/ xñÍ7¡:ÉÞ¶”µW#†ar£(>1¢˜(1Nµ|>Ÿ™ƒ) SZ[5¤â† ¿ßEQ g]7r‡•ZÍ”¤”ªGEÈÏ> ÿQGaÑ¢E˜´p! IpÆõ^ÇC•]3§3Õ´De^zíó±k,3ªyöá¼é1xN~ ØûWßpÒTHŸ¯ƒôMÀ¿Íºõëñ­/ÎäXÌ’‘ y.Ýõoà©OáÄ×NÄ;~{o¼¿ý6\ç¹Ð|_3ð†‚ú /¼H~ ¯CGê2Õ‘ ˜ àj<†0>û¥ <"‚n¬õ<Cî=ˆGcÄóÉa @À™ˆIÝ×êFÂ(“.@Îc9¦;Ãç™ÃX¯nÍpngÊß©mÛš£m® gjý†å˜tm¤ïS{È©ÑzJEëtrrìÅÐÈ—å|ñcg¼;#ÆŒNº(•»ãú»0hº€Mû¶ulCÝ»u8oÊy¸|êåðõú ¸…„q­%~2K«’² ñ HGFD†S‚ stœ€É:—å|àšèÃKÂj˜³f6±&É8Hí #9Ê«;ÞŽTc¢ŠÖ¢þøS>óÅÛOŸ‹HéšY³´X³¸‘®9§”ÉD ãpWüû´oe=Ž¢ü$$ié·ýH&½–öY÷¿ÈéØi¹¦tý|H”âmòY®+E² À‘‡‰úêÁdFÿ'º{šùš"/Ö´_ S+Œ ƒŠøNÛˆ‹ï©*^ºî:´y$Îèíų÷܃6§3¬fþp8¹*P»·VÅ‹°¾¶*µ© cƤ !1Q‰0” 𼀄wŒ©Ä#Q†”W ¯&%†”QRè} ¡0¦(I €ú¾õ7¨ÔY) é V¥¾Ü)…™Ì¸6Ü iÚNX-W½û.ºzE¬ÿÉOpìž=ð,Y’| É¢ÓÉ›7 SÔÿÚ q÷´¤÷dYFo¼yì1 SR¦{ãÕbI>­A]ŽG—)Š‚@ €@ü“2ýÍ­™¼%©ð¤ê 3B¹rÂ~,9pÂož…Њè]<ÀÇÐt --n8N\Ï=CŠ(¨ª Y–áñxà÷ûqû¢E8J1óŒ30D³^MŽIYÔ¤Ê*Uk&RÓ~ pi¼ú²ªhøžÀND¢ÑÚ†Ö[éȦ’ãXìÂÐôYÃýR. 9—ç9(#Eºcé1ó±¿qüà‚vvA{”a$~=u]‡Ûí6ÒMʼn@ €é˜ž8Î:Õe( kŽ™c³ßšâ¢¸€ÄXZ÷.(-}{ô7“Œq9t@8 C}ÏeùÛÚ&Š&ó¤ü6ìè{Ô«óîdK…ö“ YJœc²´Æ: À®xCH3æ)@ÓXî H~†ˆñ6h*p¡?ŽŒ·f›à™ø1gè‹×Ф½«OëÀ+*°XvèÀÐ&ï ‰~íÑŒ÷ÃÈÐåL\ó€‡â}ÿ퉀GLDÎ×7Tà}g8Ç`š&$Œaÿ¦çé€Oþ"S4`‘„ÿÞµ”`† þP¶R¼ŽP8FWW—9?2L-1" *ʲ¿¯lOzO|öƒÐûØcÐüÊïG(µ0ºÇ“¾âÕhÃ:™Ò¼oU0(LÚšÞŒ ‰Z0@rÈr ï…Ôœ¹" oR,‚H( äBžV2¾R*#1q»‘ð¢h› å7Ü–6‰ ”É¡ÖN$<ÈÛ!þùùžU{mÉ„'À½ûóØh0ßóûýfAKxdÛ6¡¹ŸkÕ¸É05‚öÊ8hõ'š¯ƒÁ Y|¶µµ@ ¬‘ Ãä‡?±™-¦ëº¹I …̹•>¦|¼uÚ›\r0\W‚ðI‰t™>Ÿ/ÉŠÇS"J+”W]2QÌlì$rÍÑT ;›Nm§çgzaŠeG˜¨¢/ž¶UÁ`>Ÿ/±a«i¹å+1åïÔÃ…,ßwZ¾ãLó>‘I¤yü-¦ù;4ˆ­ëìîîäã”VãZ±u@J–sÈ ñÿhÆßKRžaÇü{>ŸEK¨þ„áVß ¤tÞL|Öç›u¯îTxR~L¼NËE£¨=Û'\æLÎôŽo4mÕ šñ ÅÄuÓ5ãwTèŽÿV(ˆC´®¿ãVŒëÞîâ­ýoÉŒòxžêvRd5§ûbj‘aPyT‡4oaÒ{~¿?)-§,)”#ÖŠ5”9MÑ4;-šÕ$ÝPåã$mµ dh;ygPDŽÕ+DHù(LØêÑAJ”lûä¶dÆdÊ#û!¾Û|Myj{{{Í:*]é*í1 SvÔÈ8Hß8 €±$Ë2EA8fc ÃØ’Kš7 µµ>ŸÏL“`F­0 Sv¢GFÑ~Mâµ,˃p¹\p¹\Ð4 ªªšé÷{Ý2L¥¸Ëglª{½€(âÏï¾ yÛ6ôööÎ{ªšH+MÉÆIYNÎb¢ªÀ@Êæ‚µ†0´Ž™¢˜mÈø;~ÂØA5ÊR œ©¿ãr%¬m%£‡U'ðùrbÉeàͧˣ–s¨êPco>†Û\íÅÜçÉçwr}G’r«ù™^0žÓñ¦ï€•¢igE`jÛT"‘"‘ÐÐÐ×1Ê@#|?JLVäɧëºé Ä0i½Dry…P¸0aÕ'âóè¶ŽÑcP®|îza,¤cöš¯Ýn7ü~?$I≓aJÈpåSûèSpµMs3ˆ œ,› S: Ñmc¡)Ë2Âá0Ô¸‡­ËåB(â9”aJD¡ò À¬kÔÛÛ MÓàõzát:¡ë:Q¦$ŸQ4å±ûŽ;™òIeéñ@³dSÐuª¢@’$³ÎƒæóA’$3º[Ó4ˆŠù iDQ„ârÁãñ@–esýëx½^x<¨Ä¸±BQ8Eª×kþN €@WWWÒÚeù MÓI2ÿv¹\ðÇ£ÌÉÁ˜þ‡ÃEѬ‘(Š¢¹_æõz …ÌïRä+銢@‚`ÓÚÚŠÞÞÞ¤ÿC¡Ün÷矦ip:f´^kk+º»»‡´Q–eH’MÓÌ>’a:õ»Ö~¥¢i|>_Æc¬¿Cׂ~®=9~z½ÞĵÍéZ¤sÍ5×Àívc4PlÃpohC/ ¹ ‡Ã¸ùæ›p1z¦6±•A¥³³hnnF__ÚÛÛÑÖÖ–õ˜Ó·Àóãǯ½^/öîÝ‹ ॗ^be–aJD!ò¹é˜‹±ÀucÑyî¹çBH’IJÉ0%¤ùÔŽ; ’d„Y+Š‚ææfvB`˜Sˆl0 (wß}7º»»¡ë:B¡ÐÐô˜ ÃL¡ò $ê}ÿûß76J=ø|>Þb˜Q¨|’3BWW—©ÓZ7èÉ+>ÝF¹i¤@b“Ýãñ@Q”¤Ïè5ÑÁ”}Úl§4ºôzMÏ QÍ9RvRê#Z'SzÀÔÿ³‘é˜lú=EºÒw·Æk°QÛÓ­Ûc±` ½CÇ dü:}'µÙ²ÊÒ¯LÇdûjcê5Évíé˜_üâèééÉ9FµNÁºí½oB—ÔÂsÁîò^Ýö jtˆžžÔ××ÃápšššÐÔÔ”ÓÂûÖ‡B8>ˆ .¸]]]øìg?‹­[·ÖœwPgg'úúúªÝŒ’ÐÑÑQí&p?JL!òùÚk¯á¥—Ä7¿¹7nœé½WkŒ”{Ÿ3#“BäsÛ¶m¸í¶Ûð¹Ï}]tQ’7\-Ñ×ׇÎÎÎj7£$Œ”{z$I±ªÛÀë¯¿Ž½{÷¢»»»f£Rxα#iLŠ¥Pù|â‰'pß}÷¡«« ÝÝÝâévj ¾§íÇH“RP¨|þøÇ?ÆŒ30qâDH’ŸÏ‡P(ǃ@ 1b×¹u$éQ#åžIcR,…ÊæÔ·& üñ"¼ðÁqÕUWaÑ¢EèííµÍüi÷¹¤îÁ‘"ïÃÁ6)¿úûû‡äÞ«¯¯G$ÉzÜž={pã7âôÓOÇ‚ ðàƒâÁ¬vw†Í®]» ª*Ö¬YSí¦Í[o½…¥K—V»éG?öíÛ‡Y³fU»¹e¥ùܹs'^zé%¼ÿþû¸ì²Ë fï‹‘rO¦çÌîÝ»±mÛ6Œ3¦ÚM-;…ÈçA„+Vàè£Æ˜1cjvîܳgöìÙƒþþþj7¥hFÊs&Ÿ1yë­·ðÖ[oáŒ3ΨvsËJ¡ºíË/¿ŒiÓ¦Õ¬\£iΩòÖm3Ëç»ï¾‹W^y3gÎÄu×]Wí.Åhº§k…|uÛT»©e§ùܾ};t]ÇøñãkzîdÝÖ~°n› PÝöé7^Æ¡hÇúõ†ÃáÀ–-[l5Ú}.©…ç‚å}Û¶m(¹nkƒJ4ò^>Åž{î¹j7aF<…Èç7Þˆo¼±ÚMg˜O!òùä“OV»Ù 3â)T·¥¼Ý ÔBäsáÂ…X¸paµ›Î0#žBä󡇪v³fÄS¨nûðß®vÓ¦äØ&åW}}ý÷rY9†© ,Ÿ c_X>Æž°l2Œ}aùdûÂòÉ0ö„e“aØÆ ÒÔÔ4D£Ñh^ÖN†aÊ Ë'ÃØ–O†±',› c_X>ƾ°|2Œ=aÙd˜¶1¨8D£Q³˜Q?"‘æÏŸ_í¦1̨‡å“aì Ë'ÃØ–M†±/,Ÿ c_X>Æž°l2LÛÔP€ööv,_¾ÍÍÍèëëC{{;êêêªÝ,†aÀòÉ0v†å“aì Ë&ÃØ–O†±/,Ÿ cOX6Æ`L,‹U»V"‘"‘8lŒalË'ÃØ–O†±',› c_X>ƾ°|2Œ=aÙdT†a†a†a†a†a†aì†mj¨0 Ã0 Ã0 Ã0 Ã0 Ã0 ÃØ6¨0 Ã0 Ã0 Ã0 Ã0 Ã0 Ãä€ * Ã0 Ã0 Ã0 Ã0 Ã0 Ã09ûƒüàÕnD¡D"ô÷÷êëë«Ýœ¬m¤¢M‘Hõõõ8äCòîGµû988ˆ·ß~{Øm³c¿Òõ¥Ø1ªöøØ‘Z¹&#aì3Ég±òWé¾åêG¦1²[?jZ¹&µ>ö…ι>)sgµúÂO?&L˜P²±®ô}@¿788ˆ£>º¤m­D_ò™/Óˆ­¥1b #lµ5öÙäÓîºm>ó~!òYí~1¥¡ù´ÓØ3wÛÏRP¨|Ú½_LnÊ©•šRëØ¥bppªª–Ew®ib5Êúõëc---±%K–ÄZZZbëׯ¯v“Òòï|'6kÖ¬¤›7oλvèçªU«b«V­ò~¶¶Ùµ_éúRÌÙa|ìF-]“‘0öéîébå¯}ËôœÉ6Fvì‡Ý©¥kRëc_ÈÜ™ëó‘2wV³/Lqlß¾=ÖÒÒR²±®ô}°jÕ*ó÷æÎ[±bEÉÚZ©¾¤“ÇÔ~}á _ˆE£Ñš#¦0ÒÉf,V[cŸM>kA·Í4ï#ŸvèS<…ȧƾ˜¹³Ø~–²ÕÏZè“rêG¥¦Ô:v©èëë+›î\ëÔ¬AÅz£õõõÅfÍšÛ¾}{µ›5„%K– ™8‡Ójösýúõæ†IºÉ'[ÛìÖ¯l})fŒjå>¬$µtMjyì³ÝÓÅÊ_%û–ë9“mŒìÔZ¡–®I­Ž}1sg®ÏGÊÜY¾0¥DÖ±¯•{zûöíIçF£±Y³fÅúúúJÒÖr÷%“í¬Ûf›+‹•Ïj?w˜ÒPˆ|Úeì‹;‹íg±#Ÿvî“›rëG¥¦Ô:v©°^³h4›;wnlãÆyµa¤ËAMÖPéééA}}= ©© MMMèéé©vÓÒ¶5]XY>ý¨v?›››ÑÖÖ†¦¦¦aµÝŽýÊÕ—BƨÚãcGjíšÔòØgº§‹•¿J÷-›lf#»õ£¨µkR«c_èÜ™ëó‘2wÚaŒ˜Âèèè@SSš››Í÷jéžH7PWW‡††D£Ñ¢ÛZ‰¾d’ÇH$‡Ã‘ôþ¼yóòê—ÝÆˆ)Œt² ÔÖØg“O»ë¶ÙæÊbä³ÚýbJC!òi§±/fî,¶Ÿ¥ Pù´{¿˜Ü”S?*5¥Ö±KEOO¢Ñ(–-[ÀEQ0oÞ¼œm r0®Ú („þþþ!‹øúúzD"‘j7- š|n¸áôôô ®®íííhkkË«Õî'=xÒå¹ËÖ¶ÁÁAÛõ+S_Š£\ýTûžµ>ö™îébŸ+•ÃlÏ™lcd·~ÔµtMjyì ;s}^çN9æÎ|>gìG?6mÚ„ 6`ùòåIï×Ê=ÝÔÔ„¶¶6¬X±‡Ã4 ÒBÏîºm&yt8fC>7mÚd.~kiŒ˜á“I6é³Zûlò¹fÍ[ë¶ÙæýbäÓϦ8 •O;}1sg±ý,Uû鼩d“O»÷‹ÉM9õ£RR»TD"477£³³›6mB]]ÚÚÚJ¢;j2B…,ŠV2yIV²ˆ.[¶ /¿ü2V¯^ŽŽÓ"—«vîg¶¶ÕR¿Š#;õÃ.ÔÒ5©c_¬üÙ©oÙÆ¨–úaj隌Ա/¦ívê×HÖo˜¡ bùòåX½z5êêê’>«µ{º®®Î,Lšº ºí¦M›°hÑ"8ÓÀYkcÄäO6Ùjoì3ÉçHÑm‡+ŸµÒ/&=ÅÈ§ÝÆ¾Ð¹³Ø~V’Tù)ýb J­•Šr騥"‰˜Ñ&Ë–-CCC–.]jEF»Ô¤A%uÙŽV®¦¦&¬]»Ö´Þ9ÌŸ?ßÜpÈÕ;÷3[Ûj©_ÅŒ‘úaj隌Ա/VþìÔ·lcTKý° µtMFêØÓv;õk$ë7ÌPdYFSS“™#¢¿¿ýýý5uO“w݆ ÐÞÞEQÐ×ׇ5kÖÝÖjßÓƒƒƒXºt):::°råJ¬\¹2ï¶ÙiŒ˜á‘M6ÚûlòYëºm¡òi÷~1Ù)F>í4öÅÌÅö³d’ÏZïcP.ý¨T”KÇ.% X½z5‡™‘ ³³3gFƒÔ¤A¥©©iÈ@D£QÛY»È‚oÅjuÌÕ;÷3[Ûj©_ÅŒ‘úaj隌Ա/VþìÔ·lcTKý° µtMFêØÓv;õk$ë7Lz±fͬY³‘H7nÄÆkꞎD"hhhHºW‡éAW˺í’%KÐÐÐEQ’Ò[äÓ6;3|2É&P[cŸM>k]·-T>íÞ/&7…ʧƾ˜¹³Ø~V‚LòYëýb Ê¥•’rèØ¥Âáp ‰œ {f%£…ïËBKKKlóæÍ±X,ëë답´´Ä¢Ñhµ›•ÄúõëcsçÎ5ÛFcsçέ_¿>ï~Ø¡ŸK–,‰­ZµjÈûÙÚf×~¥ö¥Ø1²ÃøØZ¹&#eìÓÉg±òW¾¥ëG®1²c?ìN­\“‘0ö…̹>)sg5ûÂÏ’%Ḵ‹ÅjçžÞ¸qcÚûV–å’´µR}É$›7oNú·}ûöš#¦8Re3«±Ï%Ÿµ ÛfÓe •O;ô‹) ÕO»Œ}±sg±ý,åõ®|ÖB¿˜Ì”[?*¥Ô±KA4µ´´ÄúúúÌ×µ¸gV.j²(=´··cùòåhnnF__ÚÛÛÓæ¦¬&TôÐCPóçÏ7•D†a*KGG<EÁßþö7455±WÃT‰H$‚5kÖ`éÒ¥C>ëèè@SSEÁC=d¾Ç0Œ½°ë¼šíùBíæg 3Ò±ë:”ç†IÆ®²j×9ža† *U¢££ƒƒƒèèèÀÒ¥KÑÙÙ ¦bGŸËàà :;;ÑÞÞnzÕ,[¶ óæÍ3¿ÓÓÓ“vR¢6”ºMéÚØÑÑþþþr]n†å¼÷“@SSSRÞÉöövó;===X³fMÚ6®X±Ñh‡===%÷RÄ’%K†L” SMÊyï744˜r888ˆ7šÊj&Y¤6Uâ™a…哱å¸ÛÚÚ°víÚ¤906T$ýNCCÍϲ͕’ÕJÌÓÌèf¸÷s5tÊlój¾Tòùä÷Œa˜\d“+;è”ù¬CóÁnó?ÃJ¦{¹Ú:e±²j÷9žaÊA¥÷gʽî㽟á3®Ú ÍÌ›7mmm`ZW®\ À˜86mÚTôoÅrÑ¢Eæ{ýýýX¹r¥ùÛííí'ˆ†󳆆†²lss³Ùo†± åº÷W¯^%K–˜JsCC6lØ »,•yf,ŸŒ¨ôý˜nÓ„ËH$b>2Ék%eµœó4ÃûŸ«¡Sf›Wó¡ó]>φɇLre2Ÿuh>ç°ÛüÏ0…í^®¶NY YµëÏ0夒k>:g9äŒ÷~ ƒ#TªHªB–ê “Žžžœxâ‰iÿ¥ %oƒùóçcÆ ذaÚÛÛós8æß™ ñ ·MÄ’%KÐßߟô cÊqïbÅŠ˜?>Ö®]‹µk×¢®®.Ï ‚哱ùÜ…Þëå ’²šÏ³ŠaŠ¡û9vœWÚ{¾0Œ•Bç€ZX‡,ŸÌȡеU­Èª]çx†)'…êÈåZ÷ñÞOeá•Ãápàå—_Ö÷׬YƒeË–™ï-[¶ èëë+‰À ·MDss3:::àp8x#ˆ©9†{ïoܸ‘H$É«fõêÕp:èïï/Kh%Ë'3Èç~,ô^OG:˜¼ŽÊåZÊö3L­RyµÒÏ :φ)–j¬CGÃüÏŒ*¹¶²ãžQ!íªÆÚ™a*A¹Ö}¼÷SYØ RcD"³ØQ*‡cÈdW__À°î“P”ºpÑpÛDP(Ù¦M› Ëò°óé2Lµ.U½ŽF£¶h#ÁòÉØ‰|îÇBïõt\Ze6‰ ®®®l*¥l?ÃÔ*Õ˜W+ý|±¶±’φ)–j¬CGÃüÏŒ*¹¶²ãžQ!íªÆÚ™a*A¹Ö}¼÷SY8å×§©© eÙ|O–eÔÕÕ™ÂÔÓÓSÕpè•+WbÍš5¦÷ÃŒTæÏŸþþþ¤\škÖ¬A]]š››«.‹é`ùdìD¥îdž†8Ž$…´³³óçÏ7_ÛQ^¦ÚTZ.rÍ«€!»™—V*9ßåóŒa˜b°Ã•kš¯löšÿ¦ÒÝËÕ–×|öŒ†#¯¥"Ÿ9ža˜ÒÁ{?Ã#Tj k¢|¡B^4E£Q¬[·Îü¼§§kÖ¬)Ø YH›¬8´µµaÅŠ\`Œ©)†{ï755aåÊ•X¾|9ššš088ˆh4ŠöövÔÕÕ-‹¥hc*,ŸŒÈv?{¯§ÒÞÞŽ%K– §§ÇôØ[½zµùy©åµÔíg˜jPi2×¼ ÀÔsÖ­äóÈýŒa˜b°‹N™mš¯löšÿ¦ÒÝËvÐ)sí G^KÕ®|æx†©Eʵî㽟Ê2&‹ÅªÝ¦ü šÅÆš››‡L@¼‘Ã0"›<²,2Œ}°Êjºi–W†J5ä"—ž»téR¬]»¶Ú—&k»9­Sjì2Ge“O–M†1°ƒ¼Úu.ÍÕ.†a˜jÀ*£k¸f*ä}Ã0LeÈ$,‹ c/xîd˜áQ-¹È&«kÖ¬)Ê£¶Zíf˜b°Ó•é>gÙd»È«]çR–G†aìG¨0 Ã0 Ã0 Ã0 Ã0 Ã0 Ã䀋Ò3 Ã0 Ã0 Ã0 Ã0 Ã0 Ãä€ * Ã0 Ã0 Ã0 Ã0 Ã0 Ã09`ƒ Ã0 Ã0 Ã0 Ã0 Ã0 Ã0LØ Â0 Ã0 Ã0 Ã0 Ã0 Ã0 “6¨0 Ã0 Ã0 Ã0 Ã0 Ã0 ÃäàÿDí]j"%tEXtdate:create2020-03-05T16:38:18-06:00n;×+%tEXtdate:modify2020-03-05T16:38:18-06:00fo—-tEXticc:copyrightCopyright Artifex Software 2011ºÅ´1tEXticc:descriptionArtifex Software sRGB ICC Profile †2tEXticc:manufacturerArtifex Software sRGB ICC Profile\~=Ÿ+tEXticc:modelArtifex Software sRGB ICC Profile1(‚¡!tEXtpdf:HiResBoundingBox1584x864+0+0û8²ùtEXtpdf:VersionPDF-1.7 7ji»IEND®B`‚blis-0.9.0/docs/graphs/sup/dgemm_rrr_zen2_nt1.pdf000066400000000000000000005567151422157504600217160ustar00rootroot00000000000000%PDF-1.7 %Çì¢ %%Invocation: path/gs -dQUIET -dNOPAUSE -dBATCH -dSAFER -dAutoRotatePages=/None -sDEVICE=pdfwrite -dLanguageLevel=2 -dEmbedAllFonts=true -dOptimize=true -dDEVICEWIDTHPOINTS=1728 -dDEVICEHEIGHTPOINTS=900 -dNORANGEPAGESIZE -dFIXEDMEDIA -sOutputFile=? ? 5 0 obj <> stream xœä½K¯/;’Ý7¿Ÿbo j;Ì$sj@`­[³†Ðh«U ¥úúæb¬µ"òœ}U(À¤îÖÝÿ8|“IòÇÿûÇö¹løþ÷¿üé‡ýÿó¯ÿò~ïýÛdzmÛÇ¿þÓÿü¥ìêÛçqŽ{<ûg¿>þôÃüÕ?÷Ý’?:Ìhç9þówA2ƒ|ãúøŸ?Ìb¶çÙŽïÿøOÿþ‡};Úg»Kš–<Ûóù Ÿ,[ ÿ©üÜÛç8"Hëãóî5!IjB”)!ÿ, =çñ9žš$5!Ê”fB¨æxŽûãû?fOý÷Y‹Õ}üÏùÓÇÿþ‡þ·ÿÔ?ööñ‡þ!úvŸ}öÙÚ5kq÷Ïû¾?þð§þîÇãw¿ß¯ÏvŒöã¦?GüÙ®Ïëü±}#ý&ÀýãýóÆç1®ÿü‡ÿó‡÷‡þï/FÊ5ÆçÙŸ2R~úrhÜãóé¯PJ«ïýúÜzIK’šV†RZ5”Ój³ÀçSӢ䕖C9­Êiõ6ËZ“ Á+%…qBÆã;f9’$5¥ ¥¤j(§un3‰VӢ䕖C9­ê·Žµv|nç…ž=çWqÅXó˜¸1&~?>Ž™îy|üáç?î;÷7á¶W°ãW‚mO„;[rí·»~.ØØ÷±ß¨öžÿ÷¿iBüé=Á}7ýýôÕÇòž¿þR¾IåºkV†Îú=zmVwõX?¯™Mû÷³²ŸÇ±õÿß÷ç5ŽñãøÝïgØ6?ÿÿ£ÿùÿúÝ>'•ÖŸÒ_nžÈú—'ª³žkûwŸ“òu~ö1¢(ÿˆt¯s?þ‹ÿú'ÿõ§Y’óeÊ¿þÞÿúßøW/ý½ÿú×ßÍoeŽñ/þÈ@Jö¼æ„÷}jö_ÿõw¿?góÜûU„™Î÷ûñÙïçl®QÿñüNQ2à¿ù¯øBöÿÌN˜å9νŒÂ+åjɹ(^ýù<†gäœÛ6,ŠsŒµöéŸí9>ú6SŸKʸ·Ù׳ë½Ö¢)™ãe.ýÀT·‚Ìu³Ï…s—ûóY’óœëÕšFïOÌ÷œž9-ô{Û˜Ê5s¹æ:´#ßûÞ?·¹Âõ~Ÿ óÞ=‡ø~cöœ‹éZûîYþãšiŒ™ú±$˜»ff¬ù=@€âÏêcNWJÒQü ‘ŽY$$Ügñ1¶Ÿ9ro”¤Ïâcˆõñ E!™ôkæýÌB<;$³ü£5Ä:ç·ɵbÑíϜֶ•ê°ˆuÍ¢C2£oO›3p{°!€äùÜ×T>Û 3Çôlç9¾·~®tg!Ά ³œk%³ íD*÷öÙQÍ*ìˆ4ÇÊ*ß@æ?“é‘0i¶bk!³ }ÎàûÖQ„)˜5×…muÒ˜é?k¡™e(Ì@ŽsFšÕ¾WÖ¨À¬î,¬³û,ÃØÏç³­tgìcå„5SÜ3k€ùdæÝæ`Îi3ï¹u™!™5¸ÄÚ÷Y]HPƒýŒ¬R~fîé¬5’Y‡>öÈëFyž{Íà ö¹çþª!Ö¸çWɬĜàk_þ ’yZt݃Jl+ó=ºnßf-Ž•Ì,à¾$袕ÕŸ·û솕ξÍZÌA;Ã\Ñy³ f-roŸÛµ$¨rŸSMDBO#«óFK²Ú`¶àu˜Ý8ð±Í0#v/û6k±¡VGõ~GG®œõ+å•8"«s…ÙQ‰¨Ã‚Y‡“Y]!™uh¨çñ̹`IfÖÐÙG|Šûj' ÒcW:1\g‡n,ÎŽJ¬¡Ò 7*ŠïaµÅ>—­gD»?!™•Øî`}å~ÌJìhÓëBKB²c¥‚dŽ™ë@-ÖÀ¸b,Ï!ßhá>«ÐGL’kîŸ94,׫šñ5ôùÝÎ,ú3w¸k!ß±Lo˜ræžâiKÒÖМ ØITÃäŒJÍ HLâs݉ƚ°˜ÄýÝaDZ&qÏ}VaMâ[}æpsÜÄ'>P‡5á¬Df1…·ÕmkûÁ!ó„d~FkþÖ€zMßs'_Vè5}»å°D¯é› ×>òߪ³þ«a‚ÿV¥¢ ä¿Ò8ä¿5¼ÖŠ/þ+å!ÿ•zÿ•dȥɥêÀ¦G¬À5.bÀk˜€5«ÀšUàìëÜQ¸Zù^%&–Ö!–‹¸fÜ3b–Ö!®0q¨C,¸ªÞC¸ÂœWyâ“ ,°|5DÀÒ¡BÀóàîV8ÿÓ|€sm< ì綦ÙdÀdÄfQ ØñYQœ`ÀŽO7>>2`Ç1 Ÿ ¸R^K‹p.à™8ÜqÒ-ìФʼn I°”(¸ÂÄx' NÉÁ)—(8%{=X°f08%C™08%kNH\UN' ®0kK'¬aK:„Á†0¸ªµW\剡K¬a‚k^Aƒ5Ì¢Á•Ì™ fOˆW˜Àâ` D˜Í#$ÌV&fg W+ß‘L0aM& °&PXîtž€Í€ÂÕ¡g…Â’©°† *\aZ YPaQaM'¨0Ï¢Âù³Å]T¸-‘ k˜ Â5Ú_TX*N*,aˆ…++– s g:;™ŠX˜ß¬°°† ,¬a® g sÜ Kba©:±°÷In%.I+XØQ†èra?&ùÜ• g˜+ÎTÄ…S²Ç9±p¡ó,ìØœÄ‘ƒŒ°Q§rþï>Ú¿cýÿõïÂ}iW_ZAT·€aßâ•‚8BZ]–JAÌÍ ¥<Ÿ¨[*Û0c24º˜ ½í¸c9¼IŽ"CpË:÷1zá0Œ†^Ó†XÙÖ80zÍžƒ o8ôFÀpØ0tb ½¦±\‹‹áä@% àp\¡Ofi‡m¢àúngÍ×@0zk8œ• žÙðyâ´Ølˆ:ŒÊ†í¸¢m’ ±¬ŠÁµ^«¡Ùh±Îþ ̆@àG³áNE’Ù°mZɆÚO› 3ŒØðà¬0‚CÐâÚß$b?÷†ÃY‹{‘i…õòQ‹Åí†CÊ„C¬ÿc†CmÌ ‡*a¡ò2z`ÝΆCÄj‘—àP5M8ôÞNpèn7&í]/Ó!ÂÄy®èÐE®tKÓaFš½L‡ÞɉÛ¾qƒ#:ÏFƒ‰Ñ<ŒE:ô§n:L "Lì1L‡n Ña–™tèsB‡üLL‡h÷ƒ,tXÈt˜½•txñßtHóÓaè0‹#:Ìa:tO$ræI:Ì0¤Ã¦C#Ú/СÏD‡YuÓáœ-£ÝI‡üÖ’Ý I‡*žéÐY›µé0%¦ÃNf5“5ÚM‡S²E,Ó¡Ùtè®I:4²‘}‘th€º“•¹éÐДtØ„¦¤Ã ":ÔštèHI‡š­L‡Éy…)Îtâp+éÐT':CŠ=Ó¡)St8{ô Z-tH‚ºyD‡>)2z¨$ªM‡fÓaJH‡™¹è0A”t˜Çq¦ÃQÒa–Øth7z˜ÝʦCJÓáüJZÕÖ0¢C[¢Ã<`2fÒ¡;Ôtèa:ô‡$:ÌIt˜Y™ýa›S":œ’±D‡>Ø0úÃ6f,Ñ¡—UÓa† :Ì©ÉtøôX$’UÀ¤CõhÒ¡z=éPÍc:TÞI‡ê¬¤C!&ª‹“3–èP½•tètL‡ê¿¤Ã #:t M‡Ktèæ1j"$ê£I:ÔÇg:ôâ“t˜ÉŠ]<Ó¡FiÒ¡AÒ¡Çt¨o-éPßZÒ¡«i:̼D‡îOÑaf‘E‡Žd:ÛXtˆSÿP>Š=ÚE‡YbÑaÖ\tèµÆt˜m!<Ì =O'ª½ˆ‡þßDÂo Eg‘Î7îOL]i(ÚØÁ%6šŸ‰ 1Z˜ ÷‡ªf#!öq¡a¯<,$Ä@Yêj#á úËP4à (¬|„„œ/máüŒâ,ÑH8?£2Vî{&}!¾ûª.´ÑêÂý[CQ íPCZ]èX"B„Ù+B°NL„™Œˆܵ¼™µo/@èdL„ÎÛDè¼E„H%¸RDè¼M„s†‰¯ÛD˜aD„™°ˆ03"^mE‹DDˆXçK[è®2¢;×ÁD˜¡»ÜDˆañ¼Ô…(&B&aJD„˜ì£!FiÝ3y0ÄAÄ “"á ˜&¤A õ—¦‚8  f²à±í"H² >±°‚ "L0QðÀ"ZQ‚°q  QpÇbàGܱD2DÁv‹(ˆÒÄÁ±PðÀqe„! BÜGLAÐq çs *ºq "íUKˆ q„.,‘Èsƒ@'q`•–Xä@„¡9jp`ÉŠ˜q`6±80;SX$äÀ"!f7ˆKÊäÀ‹è&–Ñãq4/ Ìš·è–ƒ^a`a º0 Ë„Y^a`‰E ôÊa D%%1°„!f„3ÌGa@ý$fšÀlJ`_˜Ÿ“P©’þJÒ_66é¯!ý•¢þÐ(/ãÐR:Ñ_6è/Sý!å°Çý•0¤?Ö@è—½(ô+‰ýJ¢_I6Ð/Ë+ôËd„~ÌY܇)¥UÃÐ<6÷¡KªR¿ƒk„}UØ—#LØ—Í+ì+b_J„}²K2õ• ¤¾"!õ ©/OÔ·öÕp¤¾*YÔ—yú  ‘)¡¯Ä!ôeAŸ“óeñÄ|™Œ˜/ûEÌ—ÉùJ2D¾’ ‘’­š‡Öòò!'«ù¼Ìùœ°‘Ï ùœ°‘÷BBÙħøJ">_ÉšÀWbøJŸÛÆÀ—•ð¹â¾LGÀWÒ!ð•0¾¬ø¾,ž€¯$Bà+…!ð•d |h=B/ÃøÜ¢â½LX¼—µïe$â^ BÜ+â^‘î•â÷²â½,°pÏcÜÛqêõQh o! ÚƒàŒ8¤½„´W%A{;ø/HŽ´I†°—ÝræD÷ëšÀí Mಠ~Ý1–ÓFtþ±´èƾí ]¸°o›˜Ó^ª@l÷E‚æ>(> öÁfv®û¸Lчֻi#ªU6±¯ –ÄØwì„IcßyŲ𨇭ÿ‚1a_{Bé˜Ø‡.ZsßàM¹ä¾[—ÿÌ}½­Ý{bÆÒŠdìÃÑAHˆ}Ð'®œl%*bìÂÞØ‡a»v¶ÅnåÍ}»)¹o6à:(³•( ýê Á,qrŸ#ÙJt¿™°¹]ï–Xâ>ÄŠ wæ>¬ó/M ,6âF ­DÕÉ}ø–vÎ܇ïsœ¸Ï–;É}PV„D܇/tån3QV$÷;ÆNrßì¿ö?¥“à‡­Â›üR"ôÙMè…~ãe#Š(G½"¸2zÈ‚$¿qÄ™üF“ÆQä‡S§¸E(òÃQU€ ý œµÑÓÐýÆÍ#r¡Ÿóù°‹ $¿cÎa×K x@7@$ùa,(òÃù|H„~ÐyÔ ‚¥) cÈhTðçZþ°†D,Â_Fü žz%üe$ÁߣKH†?Ùð÷ÄlgöSkýféŽz=°ÔÉèçÂý - ÕÐ[®H‡è‡JKý2¡ŸMæŒ~nc³ß£û§b¿Kì‡u0 Dsø‰ýrø‰ý²xb¿‹ì—Y‹ý² f?·¹ØÏmnôsG ýJæB?×Éôç¡.„$W¨ÉĘÍgtV@MSÉ€F ˜2 f;3  3`F2zN2zä˜ݤb@_XHtÿš=“ ³‹…ù• !‰dDì¢@Ç¢VT Š=g aƒt¾€¸»A%¡ÌC¯M4$èMCš‡ÎíW`AЦ]i*,ƒ ì¶Bu&Ć Ö ´—uèq¼ <îöùRÿ!ÈýRÿ•HAH• ¼óx\]¥Á,°@ah˜JÌ0AÛ½™K’ ']$ˆJ…e‚H%æ?¢ Z=V¡ bóˆ‚%/¢`6)Q0ûJ(èæ2 :£ «nœÊ×mÁU¾0d$ ¢xÛË4´äDL£@± ·‰fA7…YÐ6€BA·ŸQ0 BB# –0DÁÌJ(¸V±³ íìÃ(+Æ( I0B$˜m%D>¯ë‚¥N"Á†(˜éK,¢ G€YÐ_ŒY0ë$Ô#Ì– fë 3ŒPÓK”Øv¡íbÞi*ƒNš…ºAmêò¦Y¨ú2ÍBmo*»P·DÚ…ZBt:?Ù3̶|»½¨ïš3ãK×7?†…ÖõaëvÔ›¹ôÁæòíé­…ÜÐwuî¨Ó+Ì)3R4UÇå­Etö ódõ Ó¨»H¯0]H˜úÆäØ5$L}}®eãE}ÏÌ.èμu}˜KÛ ú&…Z¼x…‘/{…Ù·°K¯0³[žê¦UFH‚úžå.é£Pßw.K)ê{Ðï ³D}O£Ydº…Ù¸;5õ=ƒÖæ>Ì®O¡¾é‹!S߃½À "êÝ•úƶŸ’ú0߆DÔ9q Qža0»†M¦<Ãl›¸KÔ÷ :°gÜ(í/ûÏçyhí)ê{æn èQžaàÉh¤™úîûf^¢¾»ó`ÂÔwßã›Ë÷M}º©ï¾ec%ê»» öD}H™ìEê[»ŸCê»»l E}w—É£ÀïÆÕ¶°%ø•X¿{ÐVØä‡ƒWI~Øj…NBäwã&[õ 3%/~üîq âH~Hæ|‘ÂÄ9Ûæ­>ÙÎF/ô»±MŒ0D?ìü¼Lèwc»ù²ÿì›Ö¡¾ð°"úÝÏ%3M¢_ Cô»qÔ6˜~}“¡_‡V2‚ýŠ„è×·G¦œD¿ƒÙÈœè‡ 'öçd?äÍÛ‹„¿Žðu;YQ_GøCVÑ^‚¿¾ïÜ þ¦½ì?æ|Ý„„÷ü–¸‘;áSâö²ÿì0F0„?Ŏ?„ .øC²ÏKñ‡¬×íÀß~0áÎi¥Iø+±Ù‚¿‹×íÀ¬‚è/« úë»\—ˆþPæ°êý!L«öŸ}“¢¿~ì(¢?„ «5Ñ_?8]™þ0ÑŽô×w^¤ý¡VÛëv $45%ýe梿, è¯ïœßM(NøéýeE%éy—ýg?6öŸèËi!üÍ ‘ô‡ ¡y&ýçB)(úËH¢?DŠ»wVžš_­ÄYoHHý —NÑ/óϹÙáG-üëçþùRöÓ~gHH÷yÑ’y^jÀ¬¦è¯\ÅLýäZlü[›—ÎC­&üƒ¤“ö‚ÿ²<ä¿l@ñ:/`øWÒ%þõSŽÊ„³¿®¢|4Ú$þ!ÖýRBAH™•è¯ŸÒ þ²ýÙ‚¿~JÏNø›KlA ì/ÓODºB¥Gø»/^22üÍݨì:InbÑŸ³2ýŦð£Ð_oTn›þàܵ½4¨8õ~¤¿’2ñaÞ¦Ÿ¨Äö2ýD^㥠ì'ÏÓØ;ÇÍ;á_oº'üC¬=ñÏÓ€ñOãÆø‡=ÊBüCK/ËÏÞtQø‡²Œ—"a^׳¢?4_\áýe‹þª$è¯dEúë ´ø—}'ü˶þõF+ãßíÈËðóz†<¿ÿÌ+â¿Y¾™àÏí öˉýdé³Ó±0oñþ”þ¼ŽÁ®â-¶Íp˜1Ò-­ÂØëö·A2ƒ|ã×ýtŸð;qU÷Ú–¯Ø’Ñ?nþL¯Øç¸× Q’¤&D™òÏL¨ÇV«¸~–$–€ñù÷ßÚ77n·ï?ç›»?ö¬­?áz{·÷⟠¾¹ŸîúTßí<öûÑqÀ£i{ûæþj8\ËÝá˃7Ó*^·™Võº­´2”ÒzyðVZéu[i¯ÛNË¡œVõà­´ìw[I¥ßm§¤0N¨øïÖ˜O¯ÛL¨zÝö‡âPJêåÁ[i¥×m¥U¼n;-‡rZ…oîNZÿßÜ×/øæÖàr¸¯}sÿ\°o}sÿJrßŽîŸ vý\°/|sÿ–Ið§÷¤öÝ”÷Ó—ËküúKù&•¿Ø-öÒsaêúÊ-v·[ìn·Ø/¯ÕåÏ¿ÿÂõßÂ1öŸ¿HmÄ_÷øÂ1öítæ_á{òðP¦ð;ÇØSöoþë¾Ù1öñËŽ±çÊŽ£4¾,žüð®eærqïñŒ¶,x6zf9žçŒc[™^Ÿ8A[6 '¨žÛŽ£´9óŒS’c1C¿iìÜÎuµªƒ¦Ö!Ë”<±t?á¹ùÜÚôzâÈýÄÑ,È Ýÿ,Á½œ©uÔ„…éKí”ÇŽ³«–õ:4‘ ª€#2¸þÃ$tî¨Bx„^ÛˆÞ˜1ζþÄ–ëÜ-Ï0#Ø‚ž!Ù÷ò‰“€á[†0’ð­Œâ,Š9Ï8¦žI7„çÙ·2N“z„¹Â·2ʳðã„¿.¸çÄiËÓ÷2Ò‰æÁ½&øç<ñµGÊÏò­¯#œ+Ÿð{}‡$¼+#åøæì·ütΫtZxW†ÁÇ:²:¯+¼+c<Äȸî;Ædïêá]ðÕ¼FxW†Ú¼E˜'¼+Co­~oá]þ —â÷¼÷ð® ›¥èàûïÊØ Äйð®œãÿ>û2å)·ð®Œ13Ù}…w壓\çX ïʰˆ¦À96u"L”ùË»2>žeNqÞOxW†}[ŒÒ·JkõðWWbáÈ©­o\òXeÀsJ̉Àe”ø¦ÑÞ9·>ËS'’ÙCn‹Ôs1;ô;Ü+C=1Vï§Eë<k„{eÄŠaMG¸X^Gß”„‹e4Øéœábf+ñ­=-\,ç$ü\ábùè4><Ÿ;\,ç{–meÄJ[¦\h„Ö\>è ª-M×UÆrÃ:½æòA–kX§×\>¨«l°o]AèU©áñÌåþlÚÖÂÕ2ÆéY]÷{.oÛ®–Ý^mëáj¹p„«e·NÛžpµìÁÓö¸`³òZsJÛÃíÑ–d}7{¤ó„Ãe%mÝz öp¸Œ·÷–ë­GÂ’p¹|À}xHÎp¹ìqÚŽ.—¡ù^W#ÌÚÒ2ñhË0ç)vCë^¬è’>—‘N´)ÌzyÌSóŠq€ÕtÍå7Ízã¤ÀŸZ[ëÛxE9Ãç2¾á5}5,Ök.ïkœ%®¹\+ø$ží³®}SðÄ\î9å>FÌ僧í†?Ä«ËõšË84,×k.ÏÌï‹s9_õhP2¯¹\›Ü†“‚5—ã;ˆXP¹ßµZÐÏÆ\N;„eÝšËOnÔHe›Ò ¬u|á<ærîBΩŸ»ŽîuöqEV#¾¯˜Ëý%‰¶=aüV¯ÙChBŽ7nrX`x/%GƒÞÐiÄÊJ0\×(zH†ð±Û ávr0ns ñGÁÓzì¸D†ð¾EVDCì)Ž u‹Ýdˆub z „Yî«—)Ép™åÿ —U}ìùI†éßDdر5ýÉ0]S —'±Ø¸ÎÞ?b ¦+ÑáT”‰—'¨HùнÖI¥¾ð°_¸ï»Â{»è"\x8SnŠxد3^hNªçÍrÑaB”ç‡à¦s-lÑ#™‡³0¦×€ÃŽ×Ý®Î0Ý@8ì˜÷#Ù°bGF6ìîÖ\Ɇ³aT*4ìWì gyéÁ\hØ1ûûnšV€)Bhد‹Ë¬Ð°C}4ì÷ÎW „†3¬…†ý õX¢a¿¡wŠ0†³žtú)4ì–€“a_ð8dØ¡7(†3 ¯Å g$¾Ó"0\aâ̆`¸^+‹3‚a‡–<(`¸Z”@`¸$kÁ…3ÒÅ•\Ø¡´ ÎÝ„tÁ…³8\XZœ\دëVé‚ ;h0êD.,½B.œÕ‹ —î*؃\8S¦Y\رÚE½É…6‚=$Á…¥3É…k\|“ ×HŠ6&Î0¿†àÂ5®™ypaÇ‚L.ì°a$ˆv,µKe-.œ±ø\ƒ¸°tgpaé;rá~{d\X#®VŽÙŽ\8c]âËà†oþˆ §„ïI‰ W¬€,rajÅ…ùzž¸pÆÒѹp†9I>äÂ%‰ž.œ#ýÅ…3ÈÃV&v˜x’ƒ g,zr®ozmÄ…«•c!ö»ñµ4qa‡©hT‹\8%#ö⋞ÜÅ…3Lv샢<äÂëdcÖ Á…S¢ƒráŒD¿âÂìuqa‡}Ìa‚ g,úþ f§‹ sJÎsÆÄ).œmÊUÄ…9¥ˆ Ó A\ØïØ´&.Ú³raÇGGX .,å!NÉÉí>¹pU=ögäÂ9w~Á…k`ľ˜\¸2ß‚ƒ ×p"”vWì›2.ÌiZ\˜6¹0× qá¹ÑìäÂ5šb»H.Ì‘".ìØ ‚’ sˆ ;Œ¢zbpáŒÕ”NpáÊ‹¹®¼¶È=¸på A.ì˜F) .\’ä¶âÂ5ÞZåÂÉâÂ{¬€]ra‚äÂÒåä‹ÎûÅ…k0²Á…kN b!®X$ÅàÂÒ{äÂ2 È…K£\˜fÞâÂ2þÉ…åÃ"–/‚\¸Ò¹+®XOáµÈV WwFiÈ…åÃ"®)nD¬øÄª$¸°|XäÂŽ50È…e g,z–þ#N }^ˆ W¬8d ®0ñõ®ù•A‚ g¤® Á…e€‘ Wæ1TÈ…¦{w¤\¸b=• K‘É…ú1ÀÈ…k掹‰\XÒ!®¼NRàs¹–1qaºÁ…5™àÂ2 È…+RÌ äÂ\HÄ…k䯤"ý>¾›C\øÝfá2çK4Ì{ïÖ†=TÕ‚>þXT†z†'U†r%l2lg§:`ØpO"¨`Øp£naÈt±ìÁL†íÈœdxaˆ0$C|¡~â0WhxquFdˆ/&0UdxÍÞv$^/ ±Ï•_``Š­¥ÀðºxŠ&0Ä.6@`ˆd}à χ}.D¤`RbáuwÆ1ÞÖö s7*,¼î›KcáÍ õæÂëæEis!bUk¸Ê;_!nÅì/0¼y º€a ¤¨0~ É„*¾™Ðw3¡ÊL8#ň1º¬fÂΧÌ„YX3¡ëœL¨£}2aFJ&Tc&ªÄbÂfbÂA5x"¡¶ÿdBÄ9¿aÂÎ-¹¡Ðí'(d›]k¡ '"D­«¦pÖõBD!ÆËáÍù!y¾’ý-6k'¦D<ØŽoyëzЖx°]œˆÌƒFQó ?Qó ?có öÛ%U¢p°ìá`5³8ÄÁ,1qÉ*[8ÜHl©D4˜­gô"Li°$#¼¨ÛHœ‘õ¢ÁlÓ`£O„¤A‡ ‰hÐå ¢¹âE4X‘W| ¢AÄ # Ò`¶ºh=N]Dƒø6ª’°|,‚ÁœOƒù½óƒ "xøxæ/Ä7í%Ì/F0˜‡I‚AH¶¢$œ#»ÁàuQËdÄQGœ² ¯µ2š1p:õA‚3!Š$ˆ íE‚%U’ "H˜$ˆ²0+’`‘]“ æƒ`Fj.1¢aÎBô4fôRhô¢&\{Ý :r ª`H dÛ‰³Òb@[A™=îÅ€øàƒÄ€öf@O fÀ† ˆI!€E ˆÏy]Ž7b‚Œö"Ј‹„ èOÌ è Ò ˜ Чef@|OÑbÀ+îÒÔgiÄ'׫j0?0# áŒ€¾k„$Tq$ÀLXèg § `ÖX$@o¨L€Ú‘=kµÊšÿ0^I–Á)ÿa¯|„øšJÿi{៷šÆ¿‹ø‡OnTµ`•ÿ|8küã·!ö+QÈ~×ÎaŒ~9õýræúáT8:[èIðÉÏÇ&?,b1¬D~^L~9¢E~9~E~^úL~Èk¼È/§‘_–GäÇ–!öyI3öa/TµKãCÔW"‘ú¼æšú4Ì~Åv‚ïÇ'çµö çíÑcÆ<{Ë3çùy$sÞqJý#γƒÔÌ/γÛ1sž}3çù :sÞ ¿n¡ð#çÁ:o{©Ï¸àûǪ|dz'ŽVBu'ày½Ck©O0§ P!‘ÞÙda( ±Ø*ÀÆã>“ÞÙx²hÔ+ºE²„Ê@¬‡ÌãèZ¬—ÅëMxÇ‘õr´ŽXïlƒ»c±^–P¬‡Z„Ù“X¯¤¬çG²ÌzY-á^YÄ·.¼‘øk¼´€h÷8ñ•0D>Ø7’‰|ÙB¾ùO<ò!vìž„|°É C6!R¾ª¶Ñ1" MC_!äCVaQ+äCÑ;ƒ|õ”NCÌ Ñ1˜ïÄñЋù`ý%æC˜Q-D×ãd1…}ë>N„!ö!ÖZ’û`!° îËOKà‡0ÁD?ØŒöj!ºãz‘_öÄ"?TŠêD’Šw¾È/[]ä‡Ó@‘„®Dä—ù!¯ýE~Ùê"¿ld¡_–Pè—%ú ÑÏ¯Ä ýJqˆ~r¾4™¹Ø/c‰ýNØ\T ÑÒêd?‰ïSìW‚ýJ2d?ç~±_±_)Ù/œØ/Óûe:b¿LGì—eûaxÝ/M` ì—-(ö+™“ý²¢‚¿’ á/G²à¯HKð—½%øË&øËŠ þ²„‚¿<‚¿lTÂ_Ž&Á_VKðç0†?WÂüW$ä?·²øÏmjþÃà¹^üçùÂüç¥ØüçÄü‡tâèZü‡XoM ,vb[.„ezl-E€0¦õ„°JøÂ޼ åyŠ…hv¨ °!f{‰³•Eî S`Æ"fQ`&# ,aHY@Q`v–(°¤C D¬ãE%)°Xò"fcˆ³„¢À˜‰KR`‘‹„èáo ,b`V\˜fq`æ%ÌJ‰³)Ä%Lp`I†˜™‹K‚`I˜ X³gH‚Ù¦"AO FÁüd…‚EB,±ˆ‚žšŒ‚YO¡`¶ P0+!,aHƒ% i0k!,’ÀÁLF8˜m*Ìö–0äÁ¬„x°„!–ÌɃ9[‰K^äÁ #ÌM<˜Í,4€ K"a‘ ‹„L˜_€˜0LLhÉ_à6;ñ,W‰ãò \Ò·SÏ‹·»Ó:F„¸=[¸Ç1!îxÉò¥ hJñ„¸T;¤‰¨Î^m# ô|i÷FÃ9â>Ñe¼qo· K ˆpÁ¼ ˆ{«jÀÌ—I‡ûEO¦C8ù¦b0àÐ^¿ ‡¸»Ë«‚„C¬1¤º€C\@dÖ„CDº_p?S¼’H8„d{Ù‡¦©¬àp¿wÑáax_pXbQó°·f͇% á°„!îÐM|$f‹Š ³¹Ä†ˆs×Ûƒ«¹¢»Å†nu¡ájÇP! ³…†ÙBCHÂäVhÉS/–Ž¢³"ɰ$dèÃLD`˜ K‚aŽ a‰`˜C@`X" ‹„`X$Ã’Á0à s !9i`˜ÃM`Xb K‚aÉ‹`ˆX¾9¸þ=¬“Å…ùïÄÂRbaf#,Ì0†XX Kb¡3"Hè‹D…%©°„!IPa~‡¢ÂLFT˜aD…™Œ¨a^æ¡%™€Â’ ¡Aâö­ aâ­ °„!–0„Â’¡0ófAa¦#(ÌZ ]+1aI˜L˜A K"DÂ’‘°¤B$Ì RH˜±„„;ÜÆe?"a¦#$,aˆ„.Ÿˆ°! ‰’X·D„™L!B„Å¿€°˜@èt „c ,a„%L¡ÛÆ@X‚K2‹@èJK,¡«e Ì0 # ̼„% °„!–0„jcó`–XE|v(hâC7Ç…;_‡¢7’!ñÍözù‹™¹Zðõ[zP_‡‹½Â{f‘‰¼‡ÁÄ{½ój„y¯ãnÚëB`ß*;.$ïÁùw4°x¯?»ÌPÉ{v $Üë/û÷à1<ô™â½þ !!y¯ÃéL`yol›è޼‡ám#Þ³ róÞs;/òÞÓµ]ð¥#"nÃF7ˆøàpœ;üq‹øà½Wg1:ªI|H'Ô%$¾’ ‰ïÇÛYÌr‘_Œˆ¯HH|Ï ?aÒ‰ñ¡Z1D|YQß3èÙ㼯‹ø×ö"¾gìrCâËò\á-þ¢2NÈ—ó=“™/ ,æ{úÍ‘-æ+2*>ª³˜tónæËŠ úž~~£ D¥ž×¥À‹Ð‡Z„Y;¡ƒày©³µ}Y@A’áÝ=B_f%êËž!õå˜õ•„I}ϰ *©^ãßÔ‡ÃÀíE}YsQ_&QßóÈøVÔg§ü¦>„éÕYLÇŸµ°Îôê,fI¨Õ î{ú¥[‚ä>´õ‡ä>dS“¸/«%îCµè†Ü—éˆûìÛßÜ—•÷e ü²Z?¸g óßr΂_N$¿ç‘W‘_¶²ÈÏɘüàZø~‘ç…³˜mÛ¥ç g1ÛœMéö…Îb ¡šäÅÏ‹üà -n±ÈY ‡ "¿R@’ªW÷ä,ï%¼ÈoJNiÚH~Ï#Ã4‘ßóÈXUÎbüœ„Å””ƒüüƒÅd[ÈY žŠØ# ÅøA;‹)±è,CD»ÓY O5-åúeqä,&{BÎby«—§DHä,΢[Hè,a^èWÚBÎbJ:tƒAôMýÐW½XR^ÎbP©“?ÃY $[…¿)‘Ó9‹$6·r“#g1¨ÁÐY̶ÓG°Å@BQ:‹äª&¡¥Àr“±ä,¾µ¯—³˜m·ß—p“m,g1Yu9‹Ùv9]’³˜õ¾Fhé,&CÎbJÃYLF’³˜,ŸœÅ䘔³$·vå,f}ï!¡³<2ò¼œÅ””é,&[GÎbJ:tƒÞ‰tãVì,’ødå,¹ßÔü-g1ÛÎm±ÅäÀ³˜l 9‹Ùvùñ‘³˜ Ýør“­,g1H‡Žiè,±¶Š€¥ÿä,&s—³„éõR`©–œÅd:t³Éù²Ådær»Ä;:‹ÙàU"$tï/óÐÕkWTüf_g˜|¦'×uZzžÅe¬ÂØ ö·A2ƒ|ã×ýf_k+_ýf[R|UKFßµù3=V߀Ôñ”„,) IÆ„ògI¨okÜ—„$© Q¦„üóoíCvæxëçKÚ_xÀÙí×üfÚß”‰ñ˾®:þjhÀ¥û;”ÒJïØJ«zÇVZJiÕPNËÞ±VñŽí´Êi•PNKþ±TúÇvJ ã„2ŒÇ¿½c+¡êÛC)©ÊiÙ;¶Ó*Þ±–C9­¿Â‡6Ö‰Ù,?ãC»ÿ‚íïÆÎ×>´.Ø·>´%¹oG÷Ï»~q`¿}hÿ– ñ§÷÷Ýô÷Ó—ËkJüúKù&•¿Ø‡6VóÓØ>´ï!Úó¯ò_¿èC{þûûâ¯ü×_÷¡ýÎâÏ_¤öç¯|h·ÿï}hÏò®Ãµ{=sêûqN ƒøµÎÅ¢¸u‡dÄáÚ:µl!‰Ã5œ?®mÏ5)-NrG^m£-Å ‡€ ®ÃÖû§Ÿ÷»æ~=tpuÍ ñ'íÆ×þåšÛÍõ”̩י9ÇÇáZÕ³%¸igÑ"•‡kx¨jÁ^Ë .ãß|0eJâp­Ýƒ«=q¸Ö.:¸àÐëáåÕe~]{®Í½jðýuq¸†ã¨µ'¼pð»nçá)¡%hq¶Öýë^¸Nƒ88ûŒœnެΜ:oVc¿Z ´Ö½ƒ{¼Mõâ¾ì‚/¢u?O—æ®{‹›ÕÇ`çÍj\NY­¯ë~Þ6ØSË-]¬­æ÷;ánë ÞkyÉY×É[Oïµ½\xºÖ±ôS\Æ\÷àíjÝá»ðŒ]\¯Ž ¯ûÑíj^w¼°ÿˆëÕdÞÙ6º^Í;EW?–“§°É¹ðÐëvÞ…—[öêSìêoWc ¬¦é7oWë-Ì o\¶£n/ÇP´µ›9Û¢‹.màÒßÕì8Þ®{XÓÌ?älk0Ö8x»Z×gSóvµL]£ùvu„¸x¹ZWö¯qÇf¾Á5»™·«åŸaÖŽ·«u³{Jx»ú&CÍ6‰ÛÕ']Î_ÏÆÛÕº†v=ñþZoñ†$G«µÁ©ä9y¹úä{¨³ƒx¹Ú]ù\¼\}ðûzn^®†gŸt^®ÆãEK0x·úäc¶ŽyÖ =èZBò ßÐ[êœи®èÁ»/Éw«ÎH76)á#^•¾·“W«3NãÝjøÞ.Þ­ÖÍó{»y·ú £ÿî!—Rˆvƒ÷6xµš:¦€7«ã©FHÞ¬Æô¸RÙ7Þ¬fCܰ1\÷óN¾v{ï/VËEཟñ€™ïÖÞØF:ÛÜË¾í®™ï7oVëÖî½w^®†“£ ^®v5×Û‘9œ}x¹‡þ«8Ç'j~má>ö8QkO‹Iê>^®vÇà^¸KláçÆs¾ërµ¦6ON[7¼‹® \žRn\ÒÛ8²·ˆ5x½&ù‘×àõêÌýáõj\X’s‹ëÕ²lóWV}é±îu`õ秨7Ö°5ãgDjñ„Ù…q¸Js^¼a}ðåóû¼ã†5Òd:oXãAË Þ°1!á kxz‹0oXïônz·7¬á6mÅj;oX»Víà ë=´_w;yÁú cÿ¹2ð‚5\쬞i/X‡F ’›¬åÃæn¬q|³ 8—èZK¬Ïk ?ãEæËóÞ‹©Öå9Œ)¨>¹}Íà8%]ù ÇÖ ~P9wcÎXSøNÞÏ`MáþÆ1Ë­)<ÃܼaíQ².h·úur¯’ÁÖpv¶jÉœƒ6¦ ,Ðûkˆb…>zêp}´æpgp“Õ^ ÇK׫¢pœuÇ<0ôÆk§WÒï4¯;ÖÇÎOÑ®;Ö°_Ç;ÍkϼÞ±v‰y@}Õw^±ÆS Kpð†õµßxe0¼©Í×Kj¬äZ–&¥ñ޵¿g<Ó^øTögš_#¯4Ç NGG74µ˜Â[ï’v>ð#HLáÅ[ 3̈¼:éØƒóT±c‘ÆŽifD¬ëˆMxÛ×1€…ßá-B̰˜ÁA%딸ã9u=ªÓ_ÇÍëzöP‘Ó³N¢g,Ú8w<°ƒ),ÓB²fÏŽãöu€ß÷xµ·¯Cw,Ò˜ÂÛÎסã¬Õ„KÔs-møJgòç v®ñ¿Íg¶Ap<­œæ,Üx¥9Ip§>Q$8‡:‹Ó±¶Hp›°Í ÞØ×qo(ƒvD‚P}m+Hp;¨j2 n,&At\à…Pp»Z|êFAt%DAt“(ˆnº^(ý1(h»$£à¾óUy£ ._¼H†1y$Á%I ì® ‚Кµî¼+<6Žvs ¶VAyA¼Î¹R!"ΘE„-(@xàT!¨;™=ˆŽˆ×+ZHÈë™í Cr 玄‰psé’ígÁˆ'½„xáÒ"ÊÏ‚)ã&b³¶®Hñ€Ãášá è#B-£SçþOdD <:-Ìx[)xXOùÁbâ@8}ˆ"ÄS@ÑVâ@(£Þâ@¼$-ômTq ÜôÇoràzê4r""ïé’³Äâ@X+ËŠ}ßKˆ‡¢»ÅxCu)àÌØG3 9¯5œ/<7al×^ ˆuL Aß3fE‚ö=`\¯¼†„$Ÿ ¤M‚ç¾K$è›Í&Aßø5 º8FA¼EuD¢àÙèqÖ(ˆv&PÐ'ZFA¿Hg„ ùŠd]´>c®3 â%Ú=X‹0è{‰†AûÚ0 ¢Ýc¡ Úk†aåÙ" aðÄ­¢U Á ïâíGC0h†ÁlÁ ZðzÁ ­0 ƒö¨`̪ íÖÃ0x6>€gÌÆ žñÅ\†v/Ä‚{(Áàyí1O ¡Ì‚ýƒöVb„zÑ`6h°¤C´ÿÑày‰ÙDƒvVb,Y‘í¿Ä4cÁN¢A¤;LÑ :=ÚK4˜m*<1o¿p}ã]8xÞtk,¹Q½#R®W–D‰ƒ¨nlµÅƒx&ˆ1½Æ˜¢Eg㙑xÝÃK<˜y‰Ñ=b‘Ox´ yÕ<#òà2é yåÙ#Vð ^ÑÁdäÁìñ Ì8£ÕŃç}²?Ń% yð¼è6W^Dˆ¼âÜ@Hˆ]f e1aæ.&¹ 1!Ú+¦\1á²ÑY±Ä„g§{g3aV]Lˆsœ˜U_ÛC!š$I(Dµ„€¼i µpäN(ÄGÍC(Ì6æøf{ sBfqD…97‘ ÏF¯í¦Â"!â#‰ÎÚc”©0ç/Q!z">Q¡W S¡‹c*,R¡7¦BI¦B{m2Ú7–°SåÚO 1÷z—X¸Ÿ*2±Ð3·±ð ÓÎÄBû2Úc”±odž/,ÄÖå ±–w«Ý…Xo]ø.³SE¸¯¹7ÉpÁYìÌH†³%Ns /\Ã?Q%ÃY,¾kanÐ¥$ÄÆ5ÔRÚ@* …ÜVÂ..4€Dõ†EÂR¼UœZBØŽöIK(À.ZBr¦–'(o-a£°ÑÐÚEKØ¥ð“–0ÈZ`ˆï-¢HGxoB8êoƒ¦ŽÐz:¡!ŒëÆ‹ }~’:ÂýRYȆ¨m«p؆ÁOJBà}FŸJB »HIx ‡íy¨²’p»¨§¦®ÉJB¬"”PI¸6Z…SGd%áÆû©$T¤Ð QŸ”„ÒÓZG¸ÝßÀ¡ÙRGˆ¯9ÀpˆÔ)¡ÎÂRG¸ÝEÖ:ë]~ëgÇñ‹u„ ºˆ%ávÅ·/6l¸ŒòR6ÌH‘Œ”„0šŽHR΄£¿‡%) 3LÀ!*¾…vOJBç%!ß-H%áÍGù ‡8Ï íž”„n.±!JC_lX2—’PÝ-4ÌLhØp9*"II¨§»Œ†(ñKI¸¦‚·’ÐÊ¡¡[ËhX$ÒâæOHˆ†˜8B;@4DùBùc-a–hˆZ/5afe5¡•+BC×ÜhˆV§rQzBWKhÃÜP’ ¡ómŠÕ„š^L†©Í6ÜøH0L—À÷u‚±¬$Œ1a,Ì8ÂBÌZÔ, ]\«}Ô.*lã¥ôðLý ¿…„ÐjS‡H$ÌOý 4?DÂ,œÃ( Â Bé D„%‰0;)õƒwñ$Â3"¬Tê‡$B?Ea"D'Å®9õƒ‚'a~"B7yêµ!æ˜Br†6ÐúAÐúÁ-ž‘L…Õƒ©u$â¿1ŃБOêÕ»Ö¦¦OúÁÔZ?/e¤zÐ:±TJÍ“êAU)ÕƒÒØX=˜a~V=¨¼S;(”ƒ2$HÝ BX5¨Œ¥ÔZ˜ªAkk¬”NϪA›¤jÐF©­‚JÕ ï-¥n0ÃH9hU›µƒËÚA5•µƒÖä§vб¨,êBjÕXÁ3£Ô ªš©äßÔ j“ºAÙ¾¤nP{–Tº Vz¤r¦.©Ô6ËÊA÷Œ•ƒX—‚ñ¤t˜Tê ÁÊÁ cí fky•4µƒ¶±vІÖª‘S9¨·r0ó–rPc tVÆ@Û€Ý}Æ@«ÓîPc`‰X‚­i6ڢˆ0/å M5LX/CÁI DõqšKR n¿(­6ZmôWÿ+.´üp|ü¶ }¨ÉLðk<ñNð»ÙKà·w^LðÃv:4€?,ÀZâ>«0Ì}Б†¹(¹ïÌÛÆ¡:1÷Ê3÷b:s_çö×Ü7÷­O¤lîS­Ì}›tV澓nb’ûŽGÌ&îkVø ýºõJô[·  ù5^­4ù5¼,ñQÁ¯ñÖd‚ßõK ~¸Eý¤À“ÌGá>oÅÅ}0fj›ûô„¯¹Ïªus_¦+ìë<‘0öábXÔIØv¥Õ)±¯Ý:öµ. š¸éPŠûnõìË„÷a'vDrDŸüZŸ/îƒAAˆûÐ2$Aqß,ÜPGðó‹Ã?H"rŸ7“æ>ïßÌ}6£öµÁ QÆ>›@ûæ)XÇØ%\±Éô—mhž\ûLH¾RbbŸ# û°-|©q ˆgËÐS&†>KH}E"ê³=© Ï})èCyJM}µ¤¾dPRŸqÃЗŒGè{.®ù‚>ït“ùn“ùD>b>³wa>˜˜ͽ,C šùT^#ŸÀŒÄ§.HàÓ[× |¸ÔEàs²É{b€>'CàËò&ð©­lŠkÔ‘U_áF_œš˜ølï^ÌBîÞŒ|®B"Ÿ’òéT*­B3aSŸ ,êC?ñ}³c‡ŸÐ×¹e1ô Qdªc•´ Õ‘I2_Jdš±dª#2CŸO2 }²½.Ð÷È’”Зc/¡µ´M¨!‹È—Mn“P¼i#ŸòóA²}Ã|*p2ŸšȮ®;_Ìçòóå¿‹ùÜ·b¾­T„‰ùð-F,1Ÿ¿!_Ž"!_!ñå°òeù…|.­ˆ/?_‚®ˆ¯$Ä—…ñå\$äCñÈod>Ÿ‡úJR_ŽrR_NX¢¾ìJQ_VS؇!ñVæ öåPöùÈGÔ—#BÔ‡¦”õeqD}%aR_‘ú²È¤¾Ž¢¾’°lB=‹Ù&Ô!îóÜ"ìs‹úòÈAÔ—Ÿ¡¨/ lꃗ }ú Å|Y^1_ÎGd¾lO1_v”™^^¡™°˜/‹'æËE€ÌW‚ˆùü!šùT!ŸOÈ—_6^šƒr*LsPÍiš™ƒ2á´ÕW—Ö "i ªÌmêTÄ{ZÃÌ{3æ=ï,ÒTŸaZƒrn±1¨ÆYƒjÞHcP}©i ª%A5¤1¨>ø¿À=vÑúíø0*ü],hÂ߯Ûy3Ðf›¾Ø´Wýù›Gl b«,üƒ¯±Ø2Šÿàh1”7â?9Z4þa8……‘ð_-S‰ØvE ?ĉ„?8_ú¾>t5Nô7nÎ5¦?øa»^ ¿"!þÞ¾ÑøõGÇÜÂ?|ß×ëRàè´2ÿÁõ"µ€}N}‚ô7:ßNþ9„èÎï—è@-ÒHk"xѾ¸íEkW)ýÙ/¤é3Œ|Aãâ]fÓæ* ‰ðJ9^*?Laª&þÛ þàç.t‹‚?ìPc@þÆÆ«¸†¿E2‘ðç!!öCcQ'øó¼cøÃxØ^ ?”e¥!öûÅá+öCçeÿÙ/ú20üa0R-GúÃìú]Ñߨ¤¨ýy6þ¡ÅÛKáçyÐø—ÍGü7_œ0þ!Òû>`ŽáH¢‡m'ñ/Ç´ðC"ƒø7.ÚÅÿÐQ‚ôÁó¢¿qï‚QÒ„Ð/£ý–À-²:s¼Ø‰üP´ &_6ÀoìÛ7—³l?Dº^ê¾"!øÆ—W ~sKÁFðó—,ð—® ˆü²uE~c£¾Tà‡é•ÈFðËNùe$’ßÀB ò³ËW‘&½ãupÀYoÉké´EòÃ4HÃK’ßh/“O4U†}™°5{iúrö!ÒxÝpZ‚ŠÀÏYüЪO°Á>u©#øõqKHòCCŒ—ªÏMnòCçž&ÈoÌÝ®{~ž)~½Ó/‰Ñ/F°¹Ï뺹þHŸz A£¸?¸Þ^à÷î?LçKÓ‡ÝÀxiú:œIHÓ÷?ì¢Ý˜‚ªYç.Ï<»™S³w é¥ÙÃÌéP³wò2ª{®’5{î«öö! œ.ûYoÕÞþЉ“U{É(/û=?/ëöîR·íI„Ñe?ŒéÚá3¥ÊMʽ¦é¾ì÷49c‘rO7´S»Ô¸!¨Ë~O“Õ§´{³êíuÙÎWÃI—ýpføºì‡€$)í^–O—ýÔ©ßÛOÞ¤°‚j­—‚ï„’-ÂHÁ‡ío„‘†oÛdªË~O#gYÃÓº# œv겟C>\J~_ö‹©µ@Þ9§’HÆ*>^¤Š ¥Ë~Ï­Kz„<ÏÄiÖ™é貟ûØ:¾=¦ò®ßsñâïúi4™òP­³Þõ˦ð]?w–0/›Ý–Ûö’å‹{9VòaÚ~ÝõÃ~t×Ï%¶’oß„‚Rò¹}×o~Ñ5VóÅ¥`òêï»~Ь¿L;sÄYÍçjù®ßò)#5ìÚCɨ»~PB¤ž¯D!ê!£ø®„z¸…À#ÖË»OÖóù3ò]?¾ë綦ÊÖ—¦ˆïúA!Ï›}¼ë÷è8Èwý  x±ž ¬êsV¾ë÷tqœîú¹€Võy"ò]?÷•ïúáè;$¼ëçšû®¦øè®ßí]ªúÜU¾ëçzú®ŸcYÕçú®Ÿòå]?m¯R×ç¼|×Ïíî»~žd¬ëów®»~K¾ëçf÷]?<>ðÒõa×x¿ïú9+ûüø®ŸÛÝwýÜÌÖö¹€¾ëç†÷]¿qñ©ïúù»¶¾ÏŸ€îú¹u¬ïÓšwý\@ßõó,c}@ꮟG®îú#Ámw#}×Ïs“ïú¹Öøaý„u×/Ã讟ö y×OEλ~ú&ò®ßÓ¿!?|ü#®í鮟J˜wýÔÇÖùiúÊ»~Ýé‹b$£»~}×µBÝõÓ •wý4}×Ïuð]?{’ñ]¿NuFÞõÓgcøÃÝÖðH#ø3}OØWJ¤?Ö®"[uüª0ökýmŒÄ ßÅøuOØãx–v%Ó´¤ø–ŒhógúãþƵ%5!Ê”fBO ÓèRKIJB’1¡üù·ö„=°¯CsüFOØù'Žý—œböücÿ¬Gáï‡Òzé¿\5tpÅàíN›)Ø‘Rõ€­”2Sz9ÓVJé›)ÿ×NÉ”Ru¥­”ì› ¥ÿk§£ J¦¸ÑÖ‡‘ί#™êûÚ“1¡—m¥”®¯™Rñ|í”H)ýî±×yøýü¯èû·Ì’?½g½ïæÄŸ¾ü@^óäןÇ7©üÅî±;ž ø[»Æžë|ùëïýׯºÆF ï\c¿Sþë;רïÌÂ5öÜÉž¬„ߺƆìßü×?|!“kìãùeרÐü®u½ß9™œå"ÃÒ-·Z¸P«ç½Ù|ma½.·Öõþ•×ùtøcÙc׳ÎË÷êTc©FÖº>¨îXÎ#âŠÇ8xÌf§qãä1[ãh}4³ñ(nJxÎÆ C#È' ã¨Ëã(§–K§&ôòž7âÊ.]e÷ñЄ^&ÊýÙxÐ&3öþì†ôîp¨#– ϖࡽ+µlìÏ(ð’—§[˜¸äûj¾õ?µµð¥lý•L£se}ôâÑÊ€ãùóÕ™00 ïøj XÈ-Çð_Õ‹°ãÞè\¹…øwùV¦ñßÀ‹±ëî´çûäÝi×án[¤C ¶nÛ(× ÷^' ÈqÕùñîº<ÍKîöf­úÿ°%»ªƒÞ1ÑüuyzÀškMßòÔ>ðÈìš¾5ûÍå”Ó7Ý XY=çKÒtwúP2ïN[p˵òɹ‹óÁ+›k%@¢5ïá¬r@+­ÛÓÑÀ°˜ CzM±Ó³² ç5{†Ÿ“@L༲9ò¬L]ù€×šÀuÏs`i~yV¹æiîÀڼ׃¼1×t®1ÆCGZ–<›×x2· ¼>Må“Xu{Zþœô­ÌEt x{Z—îgF¼>Íeun t}š‹óöª&Vçw`×Lò yV¦¿¢gór¤û,ßCý#]9NÝœVºðûzõÚð0«›ÓÌéâÕé#Œp<Ä<Ž2¼Äü¼â Þœvœ‡§u÷ûÁÚ¼ÓõÁjϹëæ4'±çx gMÞÚ÷=ËbÔ‹±1{Óuï üÑjpmáyµ(çØ~+fà5ŽöØ~?X›×ô­­ê:ÞXÓ÷I[¨‹ÈùúuLãmüou‰-¼¤Uøo®i‹÷sÇ²ß =uÜÛ ûÝx¤—G¥Á~7ôÔáÖ›ìwã¥Ú¸ÉAö»1ç­ëf?<º¹t²f?¼¼ºÆ‘ýp^ˆ#öÃK˜áºNì‡×<ÏüáÈyþ¶OÌšþ€?[HÆý @úÃ|§ä¢?¼üaDößmúCÅÁ¾è¯HHˆ#ü[úU)á_‰EüÛšt˜ÿ6¼?ùâ¿’p;ø”¨‘bg*t2@DŠýKÍâ} Â4J&¶¯Àíäó•&À-žK/ˆ XÄ€EBL‰0³n'ÍjÌ€ˆµ,xÌ€ôˆE„båŠ0d@„y"2`ÖB ˆ¼Z¤ X‚!!n’—ÉE0‹#̄ŀÛÉ“1`ÖS˜u–0„À’9!°„!–0„ÀRB $±'nsîAx¤À,(•Òf^¢À&(°!–¬HÙ:ÂÀ†ˆG¯c§+ D˜eÊo Üæ4½õ!‰=¿8°HÈYdq`I‡Xò"Br–„É%ar`VK ˜ b=AyÁlB‚`‰DD¤ &`¶©@¼#a‚`ÖJ$XR& –â³uD‚F$˜y ³„BÁ‹(˜¹/Ì*³Ñ…‚Y¡`I„(Xb³¯„‚F(˜#ÌXbÁÌK0˜å fSK:ƒÙ‚Á„0˜ƒI0XŠLD¬¥Ÿ6 f,Ò`ÖJ4˜å fÂÂÁì<á`‰E,±ˆƒùÉ K,â`¶ p0%ÂÁLY8X³ ɃÙâÁNâÁ,Ž€Eî†@˜* ,Å!–tH„. ‘Ð=j$,"¡Ó1º»Œ„(á)º€FB·»‘°$L$tó Kqˆ„[0\"a&,$Dµ÷3fùÄ„™• Ð­l(,é K:¤Â, ¨±b.*tߘ 3–¨p;©97fó ³È¬º°°„! ±°Ä"IpavŸ¸0k%0Ìò ³VÃlAaf%0,a†ÙÊì„À0‡À°Ä"–ò K:¯ùÂ`˜†™ˆÀ0ŠÀ0?,‘aVJd˜ÅfSˆ Kî$Ã’ɰ„!fg‰ ³³H†Yd‘aGdX"‘ 3+‘¡‹üxŶvp‡{øJ‡sÁjÔŠY;ˆK {¡¢ÁL—0XÒ% æ§+Ì•0èéÚ0˜ ,Ì„ƒ9bƒnò_ñŽæ¡Ï2®«æ¡o°÷g—ÁhàþÐóPà΋ÛI€ݶ%|_"ðå¤ðä2É€x)‚‚ÀS®Å x6‹JCB 6’‘Ž 0ÃM$¯£[—žQØäÝØx8)P¯Ëš!i/ѯFR òÚ^*Bx£\Q`I‡¸öø)ÚOˆ Ñ~‚@H¨Ú ÄuÓçe"êdSBô3µ†@¤Cº$WUúm^àüwjÍL€*® ð¸â= *mþs?™ÿÜ+æ?b„¹›ø¯HÈîóŸ>Ìx)8¶»â?Äj•ÿ0ж—èÑhìkþËÌÅ™ŒøÏcØüWb‘ÿø&qâ_† þùÑ4ãŸ;6þ!ÖK5ˆtýeÛˆþ²mLÃIí”I¦èϲë‰þTÃ_|þ\Á‚ʼný2ŽØÏûe¿˜ý3’ý”°ÑÏÝbôs‘Ÿ+iòs%M~Fäçò ýš ÊŒ~šŽýœ·ÈO³Z’Ÿs2ù9a‘ŸëdòË B?ådòsaL~™·ÈÏãÜäçñhòK‰ÐÏÉè缌~î;£Ÿó2ûi ú¹’F?—×è—¡_¦*ôs{ý<ÖŒ~ç#%œÐϱŒ~NÙèwÒ¿M¢_†û¹cÌ~7b?6³ßŽêýÜžF?u¯ÉOgðsû ü<'üÜ|&?P&¿¶‹(E~)ùy¢3ù¹N&?“_æ%òs£›üN¾3–äÿ/üÔâ>5„±ÏgìsQŸûßÔçž4õãe`&#è;m)èS2 }ê…„¾ #èÓÀJêSO™ú˜wBŸæØ„¾”ú²|‚>õSRŸsõ¹À¦¾”ˆúœ°©Ï™›úp $b‰ú4Bû2eaŸæ–Ä> ¤ä¾Ì]ܧ9*ÁÏÕ2øq ™ûœ·¹O'¹O­nìsOû´8'öiT›û²,â>·–¹+zbŸËÜÇžØçZûœ®±Ïu2öeÂÂ> c_ £ì¤>}»I}ÚÛ’úÜK¦>ÕÈЗA}ÎØÐç|L}Ú¿%õ¹}}þ¢Œ}î\cŸ&æä>MÉ}î(sŸK(îÓ(2öY êËDD}"ècÓü²“ÿŽ•…ÿ¶ö­p›;ý0Œ$ÿm÷FsKñ&pu'þÃ?îÒ‰ÿààuùÞ„ÂM‚MDûù­‰hoRðÉDæ¨¯ë„ ›ˆöK$'Ñ®m"Ú»ŒFe"Ú‡n.c–ü)QKl"Úy·!MDS"ÑÎ÷åÓD4%2í­em"Úi¯Ÿ&¢ððóÒ‰LDÇ&­¤LD3ŒLDÆ&¢C×Pl":v™vÊD4ÃÈD4ÃÈD´Hh":%GÕLDS"ÑLF&¢F&¢–ØD4%2{¸ÎIÑ”ÈD4%2-šˆ¦D&¢)‘‰hJh"š™ˆfe"ê06M‰LDS"Ñ) ~—‰h d"š‘d"š™ˆ¦D&¢)‘‰h¦,Ñ”ÈDÔ›ˆ:›ˆf™ˆ¦D&¢K&¢E&¢I&¢Üi"êÁmÑ”ÈDÔcÙ&¢cQB›ˆºÿl"êòØD4cÉD4cÉD4ÃÈD4ÃÐD´ó™õ4ÕŒ‘&¢)‘‰hÒèÉDÔéØDT³ŠMDÝ‚6ÍH2ÍH2ÍX2u›ÚDÔmjÑ #Ñ”ÈDÔ›ˆ¦D&¢NÙ&¢F&¢.s˜ˆºÀ6Í2ÕÌ&¢K&¢)‘‰hf-Q‡±‰hJd"ê*ØD4%2-’Çs9%2Í”i"êaaÑ”ÈD4#ÉDÔU·‰¨³²‰¨Ó‘‰¨Ö¬4õ´‰¨[Ù&¢ÎÊ&¢.ŽMD3+™ˆf,™ˆf,™ˆf,™ˆº„6u›ˆ:›ˆ¦„&¢E@QWÔ&¢®¨MD3ŒLD3s™ˆfÊ2Í02U˜4U˜4¾ÿ'QmUÒD´û LDSBÑÈD4–‰¨¦‡4Í02UÕÓDTÃÉ&¢êÐ4uæ6u=m"Z$4Õ"‘&¢F&¢™²LD5㦉¨†JšˆºÝm"j‰MD]u›ˆ:/™ˆº86Í 2Í„e"ªE"MD3ŒLD3ešˆfÂ2Ídd"ꎰ‰¨¶‰¨keQ÷–MD3ŒLDÝ‚6Í”e"š¹ËDÔ%´‰¨kaÑ”<¯âÙDÔl"궉hJd"êÛDÔ…±‰h†‘‰h¦#ÑŒ%Ñ”ÈDÔ·‰¨¿›ˆº¹d"êdl"êdl"Z$4õ—oQ¥ó…'í¢ \ïWMàvã(fßûÛQ i¿,Aáµõ¥Üqýl‰8r9p?éqÚ¸ã)ê‚{hÅ€ˆñÐì3°J‚á€. +,2 $Á­bÀý¼¥¥wäy1`JÄ€ˆ2^ ¸7ú/5î'_%1BrÓ'L0àŽ#ˆE,2`I‡ ˆòÜAŽdÀR2 Ò ô"~"ÈKˆ öí&Æ©]>#`I—X°dE,"`‰Et‰E€Y>`–F˜Éˆ‘ÕF«Ï @ü—ŠÁ@w§M|½î–¬!Õ!ùÏÝbþËtÅŽ$üËd…%Rà_V[øç ˆþJ*¤?7žàoÇQÙ þ²ÙT‚?Gßûe‹‹ý2Ñ/súeˆ~Y¡ßÚDÖD¿"!úAò¼Ð/« ôËò ýüeý\b‘_Ö[äW"‘ü²V"¿5"¿¬'ÉÏ@à—ø•¼ ~™·À/ÇšÀÏ “ûò7±/‹"ìËŒ„}ÙV¾’5±¯„!ö•0ľ†Øçõe½E}Y'QŸ§bSŸgï ¾…Ôç¥ÆÔW2"õ¹i}%UB_V@З%èËj ú²8‚¾LYЗÅôe-}. ™/Ç•˜¯¤Kæ+aÈ|™ ‘Ï_։ėñå¨ñ•0$¾l_6Ÿˆ¯Ä"ñeE|Ù4"¾’2‰/Èø<²|9ø\qò^Ö[¼W’%ïeâ^ H{%iO»Ã^–_°g‰aÏ-cØ+a{% aÏ­gØSùÄz.žY¯HÈzn³^ CÖ+aÈzY>²^Fëyؘõ\<¡^I…¨—AHzF&½‰¤—‘zþœ z¥0½,°@ÏɈó2'r^† æe§ó0ù„sa^I…˜W$ļl`b^I˜˜W"ó<ó2–0¯Hˆy9j„y% 1/‹#ÌËÖæ•܉yÙÆÂ¼ìaž[ð|^} ÊË¢¼†”çݰ)’pW#ÊË:‰ò²N¢¼’2)Ï¥äe£ ò²ùy9By™9!/Ë'ÈË„yYsA^–Ï®…ÕæÅcö¾íplS\´îû줹9L_° cÿ×ßÉH ò]Œ_÷˜=Qž4kš’ÿÔ’Ñ)mþLÿÔs¹ þ¬…£¤&D™òÏšÐÜQ¿’Y¿_‰@â$âÇßÚSö7î÷_ë)»ýž²[û«dJ85îOhK¦$ª€§’vJpó£<Þ6%ëÎl¼´~÷3o»ãXeJfŽòzÞ”DZã£À“¢ ÂRðÄ ¼F½Ï}Ä$}†§ç)9úz»­Ýñ>Ì”œëX­á‘†™5åÁ¼)a n^ל’õd ^fŸñÊà¡^:ÇÚƒáMÅFɳÕÚØ?¹ÙYÎJá/õP…Ëk®è”Æ È]ø”¬Çö¦¤Ç ‡)9ïU%œME;àqÃ^ÜŽOÉÕ¢J#Îø¦d¶ª„}=ÓYux3¯g¶p(Êœg P'Üo‹.¶Gœ­SÏ›eªð€'‡-±1Y5€ûQ¶Ö5¸¶;ŽÑ§ö•Å%í”àÑÛò´à”ÌT¤S2{ nAèQæk¹ÂÜøTúüu@œ3$÷¶…äP­îY‡£x朒Y‡3ê0(9ÂõòNëÂ)Á=|ŸÆ¸U…LxVá~ïÆC]Ñ-ðžU¯dF¸^–Ï×)yŠÑ}ëQ<ñɯ´³tY;û[¼ÏòŸÅƒî”œ÷g+^B§¤]ÑOι³ò=9%¬À±k4ö~|öâvJ`ÍÞpùÉáÅØ'ú%J<68^Þô㑃â>T|Uy°ô™ë˜¥?Ë SSÒ®˜ZŸNÉ,ýC™Ñ,üý*êø®ðƒ…?w~<Ûçxïy>Ÿ×X˜›ýàÙÃã²<ûN ¼&G¤S(UzÚ]Ô8»=ëÂÒ,Ê¡=÷¹jtò ô)éáry§åû”Œý³—¬SÀÀ*=¬<¥î;œc>µ8XUê`Þ—kÇ:^öå*êÃî©wÌ:Q'-Uø®cñ ÚŽï&$;ghŒÍè¦,ÌrñR>Z´ðª–Çv8b>Ϧ =’ÄþgëJõÙÆç»oyÆR&ˆ'kÀœtÄ7Bˆõ[]d‹ôÖ»’O=÷¹±Ì_±A Ô»Ÿkׯ¨wcMçî0Pï~º¾*¢Þ5»„`½õdäSY/Ýd›õ¶ÂÍz0Ñè ¬‡×Ü£õ–rˆ¬‡‡&ÅmÁz c)ÙŸ5YoÆÛf½í ³ÜG«ÄÁzöÎlÖƒ;äë¦ä É© +iÏ.GM{öýgÚ«’ =;e4ímm‹@¤½‰^bå3.´œj+⮸4ÆÜ[[ ¨qoÃE¬FIÔ ‚±¸êÏ0Kt¦°3Ò)qoÆDîĽíÒ<*܃DH¸êP~Ç•œ]ˆCÜÛâQÓ?&îá=ïKöóx,žP¸‡ÞÆX¬Ø!JG܃ä$6+Õ0{5LàÞü¯a3pAbÔá ]ªƒ&2á$+h ŽPâÌŠÎH‡¸W%{Ëôˆt§: !yo–Bㆼ‡{N„ò^ À‡07Óðá7‘µ«ΉÄWÃ3•œˆ|5L ßzÞ• ÈWò&òÕ0ªCJ‚š !šùðÎ;G?‘çb¾’ ±¯ÄªCJT‡L%¸©† ð+u ø! ç’_MGuÈt² àä[jF¿R‹…~%²_•ûU‰êp†™¦Ù¯´(ᯔ†ðWÓ ø«±þjÕ¡HXå.øóõ<Ââpý'üm€ëØŠþ²|¢¿üÒDù¥‰þþ_òÞeW—]ÇÒë×SìfV£"B¡¸¼€Ý1`ç ²a·vÙp½¿cc Rs¯}.é4PFµÖüµ’()úDŠÄ?Ò_üG~ÿI5ÛE¨{BÒ_+‡ô‡<Y.eð3Aø'™¢¿&éo»fj×Mý)I0¹b‹þúSIOH¹YrÒR^¶.鯕Cúkåÿ|'’ø×J üÃZržðÄÃR“ÿZ?ÿzÍÉ­½‡$ð~šüׯ’üW3Kü‡yÄ=7ù¯Íò_½A €õ® kV [k€½ÜÀÞšÀZ±€KÊ»® bÀV;!°ÍPR`ëwR`›³í#¶·ƒX_a`{ïˆ=%1O ¶Þ™’Á}:%ƒ¥"ö§’¡šœÄÀ6V­É{cÊà/°8°É@l½ClýGl-&¶wþ*ؾK2¸.r`k39°½÷Á­5äÀö†{M’Áï9°½¿äÀú~ˆ›TäÀÖr`›“·d°äwÉÀÚ ‚mý lRÛøÛ<¹%ƒ[óH¯9dÁVY°µ†,Øê" ¶•”,ؤz$C=u¯ëq°`"Y°·÷}µÞ±udÁ¶º½%Ûò–JS_Û'•òÿ°SìRüåu‰Š?n(©ù;¶]8“š?¹;+Íßi}GÓüIÑ—ª?˜Zë©D);Î.ÕŸÜ—êo7ÐHõ·DˆƒHy i)ÃÀ©KN`ý2%Q ë~žPPõ÷ÉM q&ÛÜBÇOª/q|JࢠC$Äׂrâà€…ó$Ö¡”ppÀSœ!=)œV4åߘ:’J„‰ù\pp‹íRÁß–*ÙK³$à¶ž8ˆšˆÁÄÁ17CdÂÔ˜ŒOg„=ûµààøÀhg9‰ƒnÚYNÈ HËÄA”A…,qp\›TÈÄA<³ c¹h5Ç|­3¤PW1…\V±ÑÞ‹)‰ƒŽ m «ýÑž›µ‡ °ûåoɰüm™òpy~ClüJ„Å!ñ8ˆ<â Êá|$¶Ú‰ƒœÇ ÄA”ÌÍ8q0n{íïž¿¥_“ .÷– æ qp\¯f qpÜ»ŽˆƒÈãâ`ÏC¾”“y(CKI”‚=&ˆƒ=Oâ ZÈw(p°™{ e¸‡fÅ#NHHˆO5ó$¶ñ$¢d Ñ>® dØt¤ò” Ê“(Õó$Jµ”ÀAÜáì'bwÊ÷Ž8Øú†8ˆþ»l#ClýGì)‰ƒmNÑcÑbî¼ Ö¼VŸ&Ö ö”ÄÁšÂAÈÀMÔ&4³…ƒ=%aª$ÖLÖ;#l)»dx \)ƒÛ8Xo¢p°Þqá ú›>â`¯GTŠ$°LÄÁšÂÁ)á`”p°õ1q°Ö®ÄÁVwà`ÿÿD©6ÄÁV3q°§$öJ€cJª %ÁÔF–8Øê"Ö7F8ØZL¬µ,q°Õ=$C¥$Jõš¥ê]¶Ñ$¶yN¬ï‡p[”±¨Û¼!¢ÅcÁA|)W¥`ëÀÁ6ÛNÉàž8%Ãü¡¬•B8ˆ§¸&ÖŠ-l3i– ìAâ`›‘ÄÁV2q°õ2q°½›ƒµB !§|”¡zkJ q°Ítâ`›ÉÄÁ6ÂÄÁÖƒWÉ ÉàÑ#ö”D©^òµ¾ÄÁž#q°Ì%¼Þ[9ÄÁú ÛB¬/Šp°?U2õ$ƒG†8ØF/p°?“8Øæq°Íœû2[â`+™8ØÖMâ`aâ`jíYS(ƒ÷¤‰ƒmæâ®ÈÁÿ¹3ò;D¬ïp;Ô¹à`kï{xw'ˆLD]3íªÿ¦[ìBÀ<ÝéUü‚€;œÂeBÜWÂÞ9&‚ú¤ëKÜïÇæ¡ €_‡þ°ý´³m ¼m_ îðûM ÍÀ/kþLúktJú;è‡)"Øë/LHpB·g¨ŒÂ ¡ $áïØn"¶ž"üá‹HÈ%ü!1Ñé€!T&$û°]£™g².^Qh²_ÏCvš§$úázfl«ù—…üìêfJ’ŸÃ_™üPæ³ß±—•§šï¶‘üª%?L³3‚ZCØ&ø!e[ô€ÕâSè‘𠩦&0¡a÷bò‰½Ç\L>[ã }˜Bç}Hᬜj½ÍX }½®„¾cmšÐ×ó$ôõ”.À”®˜Ä‡ŠiLâë)I|xгć¦H|MÈKTJÒR¯=i©×•ÄןJâØð‚øÚÝ’áù‹"hTÉ{ý™d%tÔž5“÷ÔU„½6²·šÏŸj»[JÒkò‘ôš|$½6=‚ôT(1¯ñ¨é•RMW‰HmÔ‰ym®ózžÄ¼6çž?ð”ÓD¤&1¯=˜×róКg±ølSê• õT"R«›˜×ŸJÌ«¡'åõÆ$åµq"åÇFË×W\Ö»% UÝ yýwBžkã•b¼ê`1^µEŒ×S’ª³Äx½äd¼Vy"^%ìà5UíË{•„×"á¡WdÜ™„×ÚOÂkÕTóiI´«ù^/8ñhIy×µM€×Ê!ൎ9Že`ðšÈ¼ž’€×ËHÀ+‘Èw-Aíßy )¼ë5*…x×z†xW“îÐ 4Ìc™»¢»ÖQ¤»þL’QOIºkó…tתN¸ëK÷á®5‡p×& á®õ'á®—.½| îZÏîjyÜÕ'¸ëO%ÜÕ.¸ó‹-¶kÃ2%‚_u²]k0Ù®UN¶kÝlwH7˜`×ZB°ksfªýÚŸìšD»V ÁÎ_2q]{Q.µß|©ý8r]u ±®‰X×F–X×:ŠXפ¼$GŸXפ$ÖµÉH¬kRëj_&¬S“éz!€L×z&˜® @¦s¡ï¦µÀˆ÷þxqµÞ2èêU"ϵÉKžkIžk­%Ïa‹Ná§ÚÏÎ|îõžë¿ßíÇ´#ϵ<ä9Éüªõ^Òßjþ³Øyºþ ×eêù„?±v0Ô>‚X)¿ÚIv ý.;Ë"* íÍ–)D;8k` Ñîyt"N´k[¢˜fÕí5¶Ý•®QtwØt·ãT+v°àp¦£;þNºÛß+ÝÕåEѼ½ÝÕ•GѪ¦JŽx¤ >…w§/áï._ŽÞÉ {á”HïÚ3G@pÖLÀÃSx8öÎå*•(€ßÁý!áˆä³FOðžñðîSæ¶<\ìl÷úP'á=Ã:E2¼³yp %]_. ¶\ŒÇHÊ…x¯ …x¾—*Âûž¡R„÷Žj=GH+ÂÃ$')*îè¶Xy:²]A^•+ÈSØ‚<…é,ÈSäÑ‚¼÷±‚N2¼Ažâ –Zo;ô òZ]„<… äùaÈ«¢¼×vÒRë)¶r©õ6[NK­·ÙrZj½ÍvÒRëµ<’ᔢJj½Í–ÓRëµ§{ b*µÞfm©õp&´ð^kÔzÛ«ïµr©ÖÛ.ƒÔzÛ-µ£ÔzÛ­WJj½ê/©õpoí,ÙÊY¼ÇÀŽÒêáhi1ò<›&K«‡ƒ-êÞ¨ÕS´êÒêµ<Ôˆm¬¤ÕK¯}¿ïAðc1òìåP«WöÒêyð¬Õó@P«çްVÏÃ`­ž|™”V§[ ñ¡žðK«g¬Õku‘ø‚³´zK©WBJ©W'¥^ K*õj„}ÕyRꕘRêm/ÍpŒ}^÷}^3­ÔÃ]Æåž_SJ=¿šVê}Rñ—”zû´ÊŽJ½/-`S©çÓJ=¯lVêÕË!¥^ËC…X §”zذ‰S©çÕÙJ½*)õ”½”z%•”zûõÃÆ³M‹¿CwΤӫaN¯f¬tz5ÀÒé)Lzéô÷¾tzÕ¡ÒéUçH§·=ÒÖH§çeß:½jtz^W ÞX§çωuz5œÒéU×H§W*^½†¿çÇU¿6µÞX§‡ËÀÌCv]J²N¯z'ù¯ÕD^­úÒéÕèI§ÿ ¤,ʰmÖÅQ#V}!^•,^µO:½Zå¥Ó«þ’N¯&{êô ?aMϾ,&Òéá¶"ë¡N¯J•N¯ž’N¯^<éôüÕ´NOóïN­­ÇÛ1¹ÎÕÑÔ.“)ç8}KoÎêeÊyh !SÎB™r6G/d¥kþ0å„ÿ>iˈ{0-ÈÒôÅËžO˜BÚ+ö.>E2¤„íR3ä„—ßs¡= Þ¹Òž@°;ØÅŽ³Ñˆ`ï¹d%Ø{†”ld½g=…P.Ðke¨ùjJr^íÙ“óž[$ÎSläâ¼q^a’@ïëÚÕ„Ó±¥ ôðm]5yoQ ôw»@¯ˆF ×ÚssQãœJÐ+Ï?p’@¯ñAѧ ô¼‘Þ²‹ôª¹B½ª\¨WìjÔ«rˆzŠæmÔó¶ÿo žÛgÔóS£žgˆQOŽB½J‘ U²PÏí“>¯pÕ¨Wµ õ2PŸg°P¯l´z–\½¯\]Í£ZÌûTkôÚ¼”z-¥dà„”^¯FOz½ÂUéõj¢õœ’z½‚S©öpÝ{¹Ð×Vª½ê-£^•KÕ^½œRíUû¤Ú«C©ö Ý¥Ú«¾êµ§~‰z­yB½š´ÒìU!Òìµ £r¯:*•{%±”{ß7Œê)÷Jj)÷ª¹Òî¥gëß‹óüm·v¯UU˜'j¢vÏË·µ{-Õ{>Ô¤z¯`Q¸-ÒîùKmí^K!æy`ÌÓ×ÜÚ=˜L³æ?H ížßk÷|}ÆÚ=_Ÿ±v¯†)µ{5g‰@ußµúã³nï€[VéöZ)Ôí}Ÿ€›m¡n3Hš½jˆ4{>·µf¯’f¯=EÍž7-¼ç´îÊ=õ ðv|hVÝ^{ˆš±Öêö´m³jI±çž{°]c6ô‹ÁfŠŠ±ê¹„»–Cš½!#EiöÚ3j¿%’f¯FMš=ïî w·ñx±ˆO{õ2•ÒýF3MNbý³9Ÿþ°&¼¿´‚˜²”i.H?[Aç»·.%SzALSAþùŸîÍ:Èñúy³Ærÿÿ½7ë?N¥^îÞÕÍï¯æÎðÖ\,«ù©fY‹Ÿj–Õr±¬%—Ê*?Õ*«û©VY•Keõ\*ËžªUTóT­’œGµ_Ÿ{æ‹×Y¿øÇDèìI_~IÏØ‡]pPÈ/åŒ}¶cy}Ì+öa÷©;_Jì##‚ß“)wl$³OyžØ‡Ý¹-;æ›0ì\òFñqm±C  ÜØ×û0Düac®\Ì@ïJˆ™ÇŠ/Dùx/¹Z;®»°û²7S®Ø†½ØÒíLÁ6ìÙ6]¿8.:ýRv)oŽ+šÿl±U‰„à À΂oœò÷,7ŽÈ‘E·Ò?бªÞºixÜãˆUõÖÍêãÆüß.¹!ý€ |ÃNè¾­ö)_ ÒîèKÁ6ìÙ@"á~B¤K—пýc„ø6ýô&öíC±ë)OJ€àÜ'=)‚?f_=Lj„CŠ®oóŠÓ´ÈÂIôÀzç·ˆÄ÷2ÏüÚûQYûÛb†H™¬šŒ[cðÀ6òìT—}„„“¨%å !¬/Þ-Üéï*9ùÛ•œ!Ó¥ úC§_’,ŽwIJ…k<ƒyÎ=„Ê0‘7lȳkª½ßªûU=¸ý~ÇΪ×Dî3 ²Ž—ܺé| îB¤èŽã€CÈtëf؈iø[̪|õQ¨ÉŠpëîÿØ(¢7L™[¤<º!4p×éÍ”y®ø-ˆ#"Š"åÉIý­ŒwÈôÈûØ(^ºLÙ%‚… ;:Žêc‰ybCòì_ìŠ"¼CBíá#ßɧÐì.µçŽ *ýJ!Ô«;BU@ªwçÀŒ¸5µÔtH·(gÎqÀùáo”>óÀÆð·ˆûx³øGO9ÓÌrÀx-¤ÚÈxã  ùbŽ#xeS9¾—•š8ÙŒ÷If|J³#ßÓ\WvXpŠÁ6ýžåŒl>âÁ&†qî1L‡4¡Ž- Ð8©L¸˜‹„Œ©F\?ÄS7gÇ‘##})a‡ ,å½–A:á…6k~3!Ül‡HÌFå:“E|ûÈ‹Ó8Ùü]jÆq²ùßÞ’½Î7Öíoг«Î+C¹¼²g=ðäÊÈÆ€’ÛŠ;N5?YyL5ÿ¦ ëÀ×x_ºÛàHê×Ïá£/cž{È´É*n̹¥L›:wR‚wr9Sð€hÌûŽ1ÂÄd–çÊu[–.ß0Î#ã÷MÎß,öJðÆs½¸(Â&%ܸÆ)5’dWˆÉ.¿à¥z¾”7„ú6CʃO òÈ$e\”¡µ'ðFS†ë9óZX{;SªW3íû.c¸‡–|•÷ìP®¦7eØ^.î㦠;ø})sË”]ïÜ _9µ6Ö„ ÈYr6ï†F•ßÜŒ["Ü´ø7EH#ÃHÉO–Á‰„}Ö:NßW}·©mø&ïýÍÀ'9fÚ©—ÿaó7w)¯EU_O¾O~ùŸûN2°â—ð\¹–èn–wð¥ß—2•iã¥OÈ”ãЖ ãXf >È{Ž+{äØl´¥øRÞ÷ÔKöSûÞmé½TÑ“» CV9q’¯\3òU9à oöCžšŸˆ”üä¤Êæ¹Iî”Î-$Ø´¿=¿ïq±ÏðüŠ2e=·™{ ¯‘'¶£oÈέگrB€o_­;ýg¬H9y(wbJ^H¹ÕÜìé¨+OŒX,qÖûKÜÆqò~ëïÞß¾s§Z¡O|‹÷\7>råè`àbèçÈ+ò¹g¤7Î÷ss ·I‰uÑúXÞrÿxæÛÈÃb$Ïz‡O„H~úâz"Fòò :¿OqU|¨õ'÷O|…÷–áέO5g¥#_™‹)ïÔÀZyŠÞ|˜ÂÖS.0ÅÍØ5ïJí¥¯ùšNÂÛ)îDx{.·Þ$<ÇŽ7áaMºƒè)0 _³4Aáa²Îò0úDB¢a’ú’ñ°8\d/ž£Í!Þ ÆƒÚï&‹E$ÇÛq2^]±ãá¤äe©WÆ’¾´‘ñî=Œ~7âÝØx>Äöû¦>ïÆÞ\›wcsƧòâ"¾ð, ïÆîw'Â…PùäOJõá,)ŠMÝ(×ýEQ y퀞7x(wBÞ Bâ0=á}ø¦ònì'ÒØ‘öö@Ê‹ ýòzUO„ÓŒÍíïf¼vÏ…Œ7V8²ÉxqóÓ5/RÈ¿ÉxM5DÈ»ëv>!¯×õR_¤"äõÚò¾9»'äݾÁŒ·ü|× hD¼vÓ‘Œ·Ôó¦±Á!GÙd¼6?Éx_žWŸ¡d¼ºÔEÄk÷ˆxaù)0œÛ*/ ßù)âÅE¢£#ÞØµƒ)OÚK´”aŸŠþEÆëu'ã…Á51벫äö!/Rr„w›¸—M»a~ÇÍØN >àX¯ËÂk—£HxKÕï%™Äs[ZK =©‹ P8A+)îGq;™„w〙›­$¼›;ž$¼Lî¶’ðúð”Q‹Øž¡ý~ÖžIȋ֑†ò¢-ñzS’ñzÅCXìd¼¨êaJ@R ‚ /Í%†"ñB‘Áy•ˆwÃRqâõâõŠñºÌÉx}¬òBF"GRÞ’"nóZ €”—åÌ´68ôÝ#åEûžNyKÊsqîåÏÀ›@Œ â·#M ªmÉxÑÝä®3m%*a¦­„­SIx߀ܚuS­¯ ¼>É. Póå’žðIxQõÃRÎ46h)3Ø`ÿ× ¯IÞ’"<Å“ðúÜLÂëu%áõ‚ðz—'áõa¹%ÃÃ=2 ¯·& ¯×„׈$¼¥5wMÔ,¹%ÃÅ /jçiHR^oORÞ’çX_„¤¼>ó–<’Á/å#ܚļHáá\bÞR÷“FƒAïÈy}¨^‰àax%‚æ_b^o 8/2ì,äÜŒTrÞÍ;A59/.‰òdà•¬æ¾—ŸIHõ–&áµ. á-){îâÜ)$¼ê‚ ¼6bAxm‰$áµ."á5ùIxM^Þ’Gí×|áµ<$¼êI^^›™D¼ê™@¼Þ˜]"¸’ñzO%ãõæ%ãE×Læy.½8ìŠ]"èU"æurãUó‡”׿%)¯70)¯  oyDXÊä¼ö"õRõz—'êµCzôÖåC¨1CPcõÏ8©¶>/QÈú¼¶YÚ+¢=°`¯®5ö y]XϽ.ÔÃU¨T„züg¢Þ1ZD‰õzJ²Þ1,)Y¯:0Y¯f¬X¯®ž‹õŽ©€ub=\§ˆ¬‡Ö D%ãĉõŽS‘œÄzp潯Jî*¡^µŸ¨‡º¯†zué]¬‡ö“Ézߨp%1ëµ’×+JŽë)¥²ãS{‰ ”Ä öA®çIë) rý)‰PêA‰PO%õ”{í¢\/7Q®:‚$×J–"•¸˜L–(ÔS’äZ1 r½˜¹–Eí·Ýãq/«Er\ÿÿ业à¹ö I®=5ÔþzJí¯”$¢^5vó‡Uæ’‡*»šh¤¹žç¹×ïµü&Íõ”ºV®çI¦ë)’@Ý{J I¤kY’ˆz)It=%‰®ó®ÅÎ’@)‰DmðIu=%©®ÕDªkr“ê–”÷‡PS2èk&¬ëyëzJb]+9°®ÿ– .÷’ žĺž'±¨§PoמJ¬ëu%×Õg\h×ËI.êå$µ¢]OÙ׺‰v­Üû2Ü’Á­!Ûõ<ó•T¹ëY6 "»^Š$¨”?H@²ë)ûL¬;ЮÿN¶kýI¶ë¥üA‚§$PžË» å¹ïëé®çyçqyÿ Ã[2(å8~H|W»C!^Ï1·R‘ñzž’¤˜ˆ²ƒ°ù\ëHñª!^”Ï ñªÓñªq‰x½Ð¹ýågÊû—Ï\Ï*¯U¬æWÛ’ŽZ1$¼ž²õ}áõ”±ÿiÿ!Â.\7 ¯ç¹žB‘ðJ^¨D`ÊQ",€×x¶C¾ë¥œÛºx'ßÕ4ßõg®g}¬»kyžkýÈŠïZɺ˜[í%Ë?døg¼P ö$¸ho6Ä Xú`œ#Ú;djÚƒÒt¹Œ»ù‡ ¹Pœ²U6îáh…)Ä¥SÆÔ…{›oÂ=C¢q¯ðø±Ø‰÷Œä=ïÞÍ{·®Ñ‰÷|ï˼W¶›â=Ý (Þ{}« ;Èaä%yÃ6ðUyKiuIÞCˆmæ  œFd˜9ˆKeY*Þk)ä½Ë—ÅÄ{eÕ*àƒckr™$ –¯L•@ÜCÀ-ša÷ZJà^û-Z ˜<°6ñµ“-ãÌ|nŒ añÞåKâ={7ïµ<䥖BÞ»|0¯å ðµjÿ­GÄ×ò˜œÇÌ×RÈ|-…Ì×R$C¥H†J‘•cKI`j)ÓšFÐ×R}-¥d A•Ì"æ«,D¾J ñ¹kL|­  N7ñU1¦VÌý,È{_ªºkõøª[D|U¬4©p#.ùE2î•M©xϯŸyA3AÍ×»OÞó›OÞóZaÞó{oÞ+;Jâ^µM¸W-îµÂRK‘¦#ÜócÜó{mÜkµ?÷š#`©êî•H½ªG¸W¥ ÷ÚS’Àí=K‚mQáµðµöø.ù~1ðiU'ïù§pÏ‹¼q¯V¸ç±íµ,¤½I´W͵‘¦Eš%€ž")µ’I{Õ¡¢=7'a¯ú÷* žöZ A©ªìUE6ÒtEd½zQÄz­IPÍ!)y7ë•Ù´XÏoB¢^¬P¯*ê•LB=…Œz–@¤WõZ Y¯Æ@¬×òHK)Ö«&‹õêõIÖkÏõZ²^+¥D`kÄz-…œT#ÖÃõ‹L 굇ˆz5ó…z5A…zÕ¡"ÕU¼> B½ªI¨×j"êy\Dzn¯H¯r”ZE$=e1è¹ý½–Âö»u$=¯$½ö›˜äŠMz­ ’^KQû7iÕ~u‚IÏ+„I¯¥ôZ IÏ;Y“Þ¥›Ž$½ö["Ô3¥V.I¯å!éµrˆzÕ9B½zJ¨WO‰õZ AÉ#ÖkYÈzÕÀd½V‘XO›üb½WŠE¡ÞÃ{S…zŒ"½‡7n‹ôTŠAï±²O —Y~åfZ<7 ÄŠçÎ[Þè\åTlñܼèlQ87_)ÐHsp¿¢ëz‰s¥&Î]c󿤡ëxe¼Fœ»NE ÎÁ7M‰s×'µ/q.tïæ]åºlN8¯÷by]ºñ,žÄéž]òÜu£eòR^Ò%¸usW<‡¬ÇÂs=%q¨§$ÑÁY It=å w6§ 2´ DKÊ›Npd ¢»Ý3ÑÁåÔ»d¸'ìV¾”KB¤GL7à“7öêœì-:<øÔ”é$ åÞü2 …½N¨ë5%¡¦m1ÉÄ>‘ku­Rݸ_‘6Á.v—ÌCàoœ†‘ E¾Þ˜'¡¨çI°ƒ3QÊ`‡ßÇrÿÎEIß;´†o Á®"A ì\†R–T4§k;Dª¦™Á®úB`‡öÌì*¾µÀu‹2y¶vå„I`×ËM°«h廊“-²«þÙõ”D»êQ±ÝÀBLM]²]EºÛ¡œka» Á]O¹£'쵆tWQ»Ew±^tW1ÏEw¹]tW1Åxã\€×KNÀ«(â÷j. ÷êmîÕlJÜÃo]Û;÷>K„{½žÄ=ä¡Ý#q¯×, Nb±xRî,'Y©=EÞP½ÐZ2yoÀŒêµä=ôÍÉ{=%d€m¸,57‹,5–²¸^ér’÷zû’÷jˆ÷‡Ö¦‡dج”K^ÂÜÚ–{yã”§Cß8ë]žêÆ›è™jJ†óð¡·ŽÅx³õ(‰yn>•ÈׯœÈ‡ö½ÝK”³/Ê=Ô_½î…ÞÿòvW§Â<Ý 5ó”êYê!y¡þùÄ?à…ú QÊâó¹üoígs=1‹óh¥ô‚˜¦‚ü³ôl?ÜY+e)(Ó\~¶‚®¸*´tSzALSAþÙ ú³~_ jcчæ?Ý/ö™ ·øÅÞàÂÎ~æ·?Tåø[>´3ÃO_Ã=<þ-ÏÚ?\dÿbz½û¾zþE÷^áfnu£%u××(iq|Í’Z–´:ÑfIÍñu”ÔÝ^«¤Ê£’Ú,©_GAÍíµÊqÓÝgómjN¯QÌâòZ³©ò° Õ}6Kj.¯£¤î[%U•ôq‹}Þg¼«ÿóyÅþVð?.œëzý׿±üV–¿·êÿG¼bŸß€}IÿÃzÅþ÷_”öïÿ©^±?ª¦lüõ¯¿H“Wìqý¯Ø'¾¥ßð„Œï\~÷äfú|ãBÆ…¸tôöâlõKù•ÛŽwÄA˜èþá=S#pÒ?éùμݳéDøÃÖÜãš Ï÷Ž=¥Lyb‡xâŒ!7ï;D§Š{ÂUõ ‡Û;wêsÛãöáŽln!Âx C)±Ëý¤ç®rn#vˆ$ enqä~n)Ø>°ç|¼pÞ™r¥wAœ2=™rÓ?ŸÂ‚Ì-dø8êàÉçÜÞŒðÕÅÚáyòI”É5Îû¾WéØå hîdžRž^}¿ÓEß· °}ûHƒvÿ;ó*̳?[þœvÑÇ® õa÷ã;áÀ7\ôQi0÷'<ôûAö{¶õ¤ÕÁ<ØþG§móØÃ91\Z${L¸ƒDˆš“£páDZ{à ¿;|ùîœF·™>‰pÕ2'ßn„â“ýwEÔ‡þ9»`0Œ±r"qÁboÑ÷ƒOÝ#?LôJtía—“©o…9ò[›¯ýõ}T³Ð<õ¾Ðr¤rYp…{Pä‘3+úÌ Þ˜8%‚ùîÅkDÌÍJ;¶!˜cœä0ì:C†!o×™2`¤^>s䮨&Í9rWô5œ/Ðyæ®hn.wæ®!:²÷°‰ž}Gy”áÐåïë¤ 5vÂ|/“A˜Ÿì‹[)Ü\"¯ïu§Fåš”áR$ÍkR†]Þ¬.Ðَܹ-òòûÞ嶨^Þï“cu9åÉvÊl e8eÔt! ó½´ðJ.-é¢0¿}}}“´;j¿ð‰ÞÓ£zÞ¿.ÊPKÉE¼c¼®+7F5OÂ$¾yד[»Cö:èh½sS†ÊC¶Æ[u'^ÿƒž³…a8Ö0ðye½' DŒÃ])‰ˆ´J6 ¼ÞØaþn ¼ÞSqCˆ× |Ë„ À f ôA ¢ñdžö¡+9R ÔÜF6„ X×\DåŠZX!EØRÝ âóÏYRàØéó$b÷}’/ƒown¬+e@XT~p“oDRM- )ðžCñH÷õêþGPàG¿Š³M ¼¿ZœxßðÍRR†vS̶JÜà%Þ0÷¹˜çÎ@xCìM¼Ÿ0–úÝ ø%04/9ð¾oºø#ÞÜ)8 „º1¸#Þ÷KO9¤À¡¶¦6¯þ¤À/ejxc'Æ ~RàGô–1)ð~Ê„)A7¦Ü$ÏÞï©/))ð†‚ñ!Þˆ©qûƳœ&$~5m‚b ¦Üµ` ‚fq,eø6eÜ@·S>V…âß·».1Žî}{?”ý½0pcEÁ€lÃÝi0à&€{-îDÉ€ŽA ˆh2Ü¿’C§˜ƒK¬°b@Äk᎛ ˆíÓMZÛfGÁÄ€ÒG ˆKdzêŒXC§)q.ñGÄ€ŠE [W²qŒ…&V|! <ˆpí¹$€.Ô ÷‹k¥ÚLN<àŽ¦$âÖ§t`;ú bUàô â™—¥$=!šÓú“Ñ3é«D¸‡=àï€pöÿ.ˆ(["Ä"æKL¬àW@¬Ë`,.L¹ærCÄ >)‚£€ ±º§žÚ °"|½3†ê—åbÙ; áîŸo;0ÖC¦$¢dNœ@ì8(%[w‡«ÿ€ØO0Ð_} £’‰ÿàžkâ?o¶ÄÐC“aŇœ¡šÿjv‰ÿùKþ;.Eh6ÿmZtÍÀ(BmÐÈÕñÊÉY+þÃV™ÛNò(ˆ[pò<jÈ5mÅ·à_%#þ‰ÿ ˆ#Wÿj¼ ÿä™Ùø×1é ÕH0¿]Žt8™f ñï•náŸ÷Îâ?‡Z#ÿg$ÿ¿ÿ`†x®ü׸Mü'Åæñ_ñ”øÏsÖüWS@üwó)ùol<~3ÿíòßMþƒ­7y0ØéÚL{d§âLñ_ŠøßO²ùoÈ´ÞüwÈEWñßc"$;}S–ìÔø .þrájþó«Iþ«qÿ݇&¾ùϤnþÓ^Âüw.Gü÷º&òßÿJó> dMÊ€EšDHvú¾+¢)òŸ<;ÿ±.òßÔx‹ÿ¾•WÌX2ð•ÿ5j$;!ðdŽŒøVøL!ÿ5%ÿµ<”’Ùé{˜2ÿpš@¾"ÿuj<že¾‘ÿŽ^ÌHªÿİI"$ÿÁh~å¿ïKÊÓñî#0…üw+x‘ùÏÇÿæ¿gË•ëŸñ§-ÄBÜûiæ¢"lDÞK~Â-~Z^Qˆ WŒôEE ŽlN+­ |ÂD 8†¢›Š?"✞‡.Ü‹qƒŸ§`À4dý½c­GR„ C'*ùŸ`ñ)´L|šÏ³*˸s$^§`DÀëÕ²"¼Æéæ%?݈ݲ dxæJü¯Ê•cc! ,GùÞ%ƒÁ/Ÿ$ïM×茀÷î"àéÓp" ö_”œ xÅ|>ø„eBÔ׃"oBàs¿S)! ü !}’A¨Ì’tP¤ÏXU{™õ$â:ÊË,É€0D• Š]øåy‹ C”£<ÁO7 [Ò~è›!Ä¥j‚“¿Rô… Þ¢—²аëð«IÑÜÈ€½ädÀ¯œÓʶ`À˜š ø•sðt” ãÂò2\ ÓxÃÀWøøÕ£`ŸÄÀ¥-_=¿ úX‘¿j†º70*"\$~…й#°“ø#ÏDÀ¯˜K³hFûaàÍgfô’¢G{5A€_Ãx?7¯b’[€o`Ô#0có«ç’c•'ø© øåñÒ“±Â©É¾B\„ëxRÄšÁO_k¬ M„Üù3øï+dXÃü×§Fà l¾²·ð‘ËM`zÁ§žú4L\ê ¼aÑÃAÞà#%˜¦Ú›ܺëJì-NŒéìàÀ÷Á¨” þ[²ÿõ¾z(‚¾wþks$ñ/ZLÆNü‹bH{7*~dNúû2\b½‡`7A˜¢8g":}åXôy„vG†›¿yß”ôãÔá¯E—'üEçuÝßWѦd¿h0Gì2 Vƒý¢ÑW°_’ìw£{ºêï†?54‰~±æp˜è÷IÄûò$¿6H$¿öü–<”àÑÑÑ/ª*Å_ô.±*À¯º’Ü/Á)Eà›Ñ\†Ø÷r¬Z¿6W‰}½%‰}ÍØˆØ÷¥ìFÌÀ¾šv¤¾˜U³Dû¡R.êûþÿ1eõõNIêk/©¯It°ýž¼„¾¯"¹!ôÝÏ»Y¡Èôåy…¤ }íe#ôźOUHB_‚ÜÓD÷í]o\ñà0'óE7-:¿6uÉ|QÊΔ`¾IºD pÉ&‹ÌwÃ8na¾{væ‹Ù{2Ï››Ÿ›Ž]ˆ|±|ºB‚jïI ‰>[—ÄÓƒt’Ä×ß’$¾¨gïÄN˜ àCsó'[ÿê^ i/æ 6i¯­u¤½¶¤“ö¢ïˆWû›ó½³Þ ”誾Žr¢^[;ˆzѵR^¹íyuAƒ¨×»%QïËsk¨§Pk’ôú;’¤×ö$½èÝ#Ž'—›§ƒ^§/IàG(@«ç:õQ=™rçÆç™®ùÉOÍCÚXc”rþÜ€vÙÏ Rý=×ÚB»ð#ÔÙî(º ÛÝvñ-¶›Z…mäùê¾§<ïÒþ©•çÐ<5Ûá²7Ë¡•çæ¸Ud»ºu+¶ûZ¡=V°Ý p“6/Ö¶9t²#¸;o“ î0…i=J¸CHê w‡nu îpÙ‘CÁÝ#ïð†»c³0ÁèBxÜîÝ]Ü=ßän.àî>¶ú½ûµÂÄú=›œžù{c»F{TÓŠD²v]$9ª÷üžší^]ô2Ûy/!¶Ã:´°v„Æ`;O„v/”äÝÌ3v€ÜIÁw‹Ra¬à;©Ì ¾ªŠú=ˆDõ{ˆ¨ÅH¿7åá@l‡×L#ýÞxWýÞ”M†Ì<·M§:b;è¹)´~Ïæ™Òï]E‘TÁü-N8zÏM:Jé÷Nƒ:Ù®Ù!K¿SÐ…ípiQ:Àñ¤¥²x¡âÃ)-Ÿ ŠïbÔ¡Ý c¦PÇ­›BÛ£QÇbøBIÃ÷-m²¬LÙ†ï¾ì>CÇݠì1©áÃîyR÷m:Æ£††;,74|—®O[÷W¦† U*s¥á;d†._“à’ŽÒTñµ)"ßn4¦ŽfdÀTñµ1 Š¯m¨øš•ôU"pã-_Sú¥~ 5ïŽxOì3;â}uˆu|ŸàOG¼'—»ßMxÏ~v¼ûÊ0ëK¿·¿šõÔïmp¹Áz ßÃnVh©öký’zï4ÔR½‡”}IõÔcUï¡Íâ½Pïa}$³R½×tÔTïÁ…Þ»¨÷p'mv¾{àGôî|åÈrô>»Éê=X6)¶¡‹zÈ`kÎС¾¶Rï—!0õ{ú.M]ê÷0pÒÃQ†G®@¤ßà .õ{ø48©ƒ©mIC¿gŒô{pAȽõ{M©Eý^@-5©ß³&Qú=¨t¹%§~¯TºÒïí§™Hú=_°~ï”S1ë÷¸Ã’vË‹ ÍX8nùý¿”rïÚm“IåžÒRîÕøK¹‡+ǪÜ˰äT•½”{˜9k¤ÜƒŽ€Cåî0KmHòGjöà¨d±ì,‹8iö˜]j½ê3ªõjÜ­Ö+M*Õz¥%¥Vo]J= sQ*õ` Üù®½êRêíùJ¤F]¿݅ŧ4~²èœD^)ôJ\*ôJn…žÌà¬ÐƒŠü^ :­Â—B¯$–>/íKSŸà iâ¨ÏÃUŽ¢»xÅY¬ôy0I&‡QVzaéóla }^{©¤Ïû^_±õyey+}Œbhó™2` R')}^Ù­JŸ‡Ob'¼vï%õyXLøúJŸçë)eÏY–™Ò…YC*}>×D:êóšöŽú¼ý1,RŸg{éóšö]ú¼ÒˆJŸWV½Òç•MtÚs¶R¨Ïr¹m}^ÍÛsVMÔçí‡q‘ú<(øTêóÚr!}^Õ%}^Ù*KŸ'íð?ãb[ÐN…ÞΕ²nöÝV©ýé;C×í }ˆd¿\íÛà‚@—ЇõòZ®öíC–U‚>,ÄïrµÆB<&ôMh¤˜è+tô•;+A<ñ˜Îo‚«Q§íúžÍ&u‚¡è›prÁ’ ®—'1ß„-1+ ûd²#™ïÒçS¡·]¾µG›N¬QD³ÁÎñ„|×)§]b¾©¼Û·a7Ì”d>8‰Ó5Cêób˜/äƒêðYÔyp0'\KbºN_äݾ ö®ùîËb¤Ï+SQªó èÊBëÃHiÖæš±ºØ‡ý ³øJ7&mžOhE|p7w/¥”2¯x™Àû7Ù "††b2èÜÇz¯/Îet‹Ê¼:Ò—2ï›gœÑ>|w¸/“2óH .3æÝùP¨›sÆ…VÚsI•Çy˜æœeÕz<\ó=;ëÝ0Ì–Rް·é[&=Þ;t ƪ<9Šõ![êÁÀ·›.ï%&í¾lF=œânÊÙI•z¼w³a€^Ùh¥ïÅáÁ/) ×…ØV*òàçí¦œßSC'4ÔäÁêáY¯óašÒäRìS‚^];’&ï}Ê45yïë‹oÔä½Sv]4æ´ÕŒH/0q›¤×A”¤·=: éa‡Mko*ó^|„Òƒe 7ö"½²&êm¬'¨Ëƒo"*é {áAø—º¼wÚŠ09±ñå3¡L¥I{`Öœ "àëHØÛ¦¯öZÕ²å¬þì] -UÞ}éK%UÞ=|Ǻ¼ϪR—ƒzNb*ó.kS™Ϙgg½û¾}é›Ê¼ßÄ~—ï†7/ÑV*Ú=ˆ”y¯¶ÈÒæ•‰½PöaËU¾ €˜ IIJ¢>Ioƒ}w'½º,Ò3q›ôêB IŸA^2"éáP¡r6{zr6óO^äƒ-Xb‘.ò…óÅßçm:¿4çá‹M‚LNÂi)‰z¯N8ÍzØ’Êl3Y&+ëùÔÆ¬çS%±*<Ö«û»f½¡nf½ËÚ ±žrÌz8Ü-•^ÀÐ-p¯îv÷¦õ$>Ëo+ñËJ>Òê© >&¾Mîk…|u·3ÌßY2%ó¥$óMk{û|N“ØW7u}×cÊKîÃÞðìJ½˜ö$rN8Nâ¾kyg”ÜW7äÍ}×X•zý$Bà7uŒ,ðÃSÜÐ'øQRߨõú‹úð™_­8ú‹úlç.êkMêÛÙþˆúÐgãõÑ"\ÐW}û-‚¾ý~b}§•É„>ô]®r‚>LZªc}›>悾ù„¾Öㄾ}H/æ{µÑ7óUOùÚmOÝá?4{ý…Oæ Çs¿7äíZ¦Ø*K%G ‡ð–ÈW·B„|èÏEµïܶ"_ÕEäk«‘o‡ò)¿ò¶ý§ú¼QZ7¢Ý;¬c£>ïÖy¡yÒíæ¦+=Öç=:æÚÅüYîëaŽ)ua÷aýb¢¼iK;h^QtC.üO]²{Ú½¸×DºJàé…ÖhöÚrØ uaeZèµ¥ùh¡×ß©±×–ïÝ VE^[ª'äµÅþìµå²^P^[6_'•לæ/ú¼ÖêóZíéµ¥ü_ÐkËmx”×{¤ >>P©ÏÃÆäè˜õJˆyðçäµå[›©Ð•×–š5òÚR2ÉkËô…M*ôj»KÌÃ6‰¿åµe“TòÚRžJäµ¥nZÙk‹ÅöÚ²—zmÙÕbb<²P(¯-ØÜ/J½ºè`¯-0bм¶ i·ÒkËf—VòÚ»b½¶à‚Ñz¸ 1Ѓö¨½¶¼+‚ÞØmr`¯-f+ym)OHº´[¾ÅkK/™—öZ9áµ¥•"¯-ÓìGÏ3ø ,^[Úì²×ŸÉkKÕÔ¼¶HcÇ[{5 äµe+j£ ÍG oí•w$ÝÚ{|A˜^[6ßâã­½ºžc¯-Ò¾ûÖ^]@‘VïÕbßÚ«k5‚½b0ÝÚ»7û_¡VÏ3Ù^[ê:“¼¶Ø’½¶€ºbÏRÚk 4{b»mo¾¶7e€ãk{={mÁÁ5„¤=¿Ã¾¶‡å“)¼¶÷Lkym¯.&éÚ^yËÉk{߈SsšÊ=ûa²Û–ï;°pö¶èÚž¿ÖïU[tmÏóÆ´çÛ×öê¢i~ޤ'äµ½º„¤k{ö#Äk{%S*ù¼–øÚÞ­£kù°af¼¶Wý+-_·®íÙ“TÑžŒÆ|m¯d’š¯PC×öü²š¯fh^Û{tI£€O+­Õ|Ïif¤Š Æ5^Û³w.«ù^ YÍWíðyOák{Pó1Õ|õnJÍW’KÍWuåµ½jŸ‰ÏF±RóÕŒ$ñaM’âoÚ›ÊIâÃ8H©—ÄW_!¾j1eÀÙÕhT‘}_ûmUóUJÍ÷ÊŒ‰×ö¼ŠùÊÿžÕ|5žd¾&•Ô|5žRóá<”4Ék{5'íŸÖ×RóÙË—Õ|oyÕ³íï›þ½ÃÏoç{áû/ßÐÑ3áwç¸à /Âþ¯Ÿ™ê©Êô«Çþ—Û°êúÞZì|·¯V¥©èk)MBà>ö›ˆ×ÝŠRB/Ši­(§´¢€ßL«¢”ЋbZ+Ê)UÔŽ›kþù•ˆ ÷sîé£V~ŸÓާŸÇ®«ç°§_¥þÈpýËõçpÅlÚ×ëf ®.Žû­Yó×_Í‘+¢Üµ<*gâHõ9ZAJé%U.Õs¹¬ð¦ö²˜²”å\.«årYßg!׺,¦,e9—Ëj¹\Ö»_X[YLYÊr.—Õrù¥Â=üíme)¥—U¹TVÏõÎ5œŸŒ‰¡=p¶·º±¾þ†ëçú‘ï×n¬ÿ,ÛO7Ö§¸óË6ÿ,Û/ÜXÿýµñ¯Xæ~µþõïËVÇ_¾0,éoŒ¾ë߸aÌþÆ÷¸‰µ>®1rÿë'ô_Žc»ÿåù¯Û_ôNýÜô|¿þï¯ñ^½ÇÑþûïºÔF¦æRûúEÁÿî¿þàR‰U]j¿ã´H÷]jiÿÝýë/ÒìR{ÿÛ.µ'. Û•7—µdž>‘“G×'·ßÎãD†ØÇ„íÇ…Ö9˜JWz¶šûÆ›E¸Žðaø—òÒKÜ΄¾‡/±MŽñû–‡ 4Žùo÷ý‚—´øœ|ëñò1-ϰÕo|{½8X‰]ô'Ï_1šåÜhÿ÷×·°ò¶Úýý&7vV±:ÂùæØ¼p´\¨_Ý0, o˜¦~4añglGˆoï„66Zs‡á«v#q®~‡×L¨FQðK”¾?ô&l@(ï'ˆRòïƒ~þÈbâp9ön$ØñÐ΀?¸iü!î—2¨#Á¥à¯¾”“†/¸IüÉ;ãª*jÂõÞç‹׉¢`£Â'È‘>T›.õàbßð ‚^?Rp‰ïÅè8ãÖêÂÑ~ Ìöµx J䃴o+ò¥œ© z "šd+\Ãø)´Øacø¢˜‹®éù~PùÅó1ü×s¡œ›~qŽð=ñÔÍóq*¿é÷x‹(ç¡™®j¿d‰¹má*qF4ÃLCø¨K'>ÜPFÉ©ôÚÒåâD,¥ÜWCµp¡äGA§¶çEäʸKð"E¡a,€}¿¡HVFDÂoPâH$ÏàÏl›ËSo\oºâFC´/î÷ŽD]©z‚W1dÙ6ÉøÈl©‚s°/¬y¦[í‰zv]N —bgæ ÀØó2Ä„Wއ)á{b¤ÓöʆzpØã¸<ö<òA ÕàvÕ<Ùqꎥäe°Ö ˜£ï)e< ÔtÊ.Š3‹eÒ/óÉxìÈ@]p>ô bqHÆP—W¸~œ1Ã3å·‰ñC©†éÓ„ê+epd“özûú-Þù^ûj¼Òï®køvhòæÈå#œ°GU ´žJ&.¥2úÛ'DLõMOa‹šÌ(mWXÂNØOåüÈ{rÑ=Š^®Ð£{øÔP:ÃÒ)5w1,ÛYÁ­°î…à9óϼi3¡(£µ%¦bÉyånî<Ã.lÆÅÙL™á3–œÔŸW¸x ¡~ን/D B0é«§æˆ]”#±q¥%f)Ä®ð-8;œ N¾"i‹zà+k¸,ÃÆ~Rap@±k¸ûar §)ø1"ts›å©E<¾‹ÇH»J¯óÇÈÛº±¥‰okž»p““íÃ7:Öð“öúuò£ýG½j›ïì…†‚ “PÍIlDÁ>‹‚¶’Oøf‰Y$xb?‡Þ"Á>¢"Áó=¹/ žèÑØZŠOØ#Ç\ †©Î–)DA˜ÔdÛ„‚0O»QÖ1±dÃÒ¨£ Þ›ø~wE™2 ®%, Í‚ØÇm„{ò›ÃÉwT%Äeœ»³ ³}bAFÄD1 âýz„gÄcÁ8X`jÁèAà ôoQ—`zÕØ"a1ßà t±£2 b§|,0ˆ1M ƒPÑesƒñ:k ÑÀ¹À lD’ÐDƒÐÎÅ&Õ4ˆ¨7 •¢Á0lj<¢A¸I?„e.4ˆh0ûBƒÐ Å7Í4A”£.Ñ ó˜G~ƒ…‚èŠsAÁ#ž0F„ò&7 BÁ1ÈàBÁê.¡à Mcâ"QpØ›!Qp"vjn©ˆ‚j«Ü|#OC¬C’`ØÅ† 8qg‰œ—,826÷ÙdÁèól Yp"ènjlƒál1±Ž0Øž" "Ov—`pr’&„ž7µs¢AÄOÊ-pZÈÜGÇPâ rƒ"¬qÂÄâ"ü%x8û­Ñ`u±hp YI“Áw¹‡ Ž¡«N¢Aäa¤hÒ >c¡Ah¤›4Q³Ò K1Ï“ãÈ~Iƒ5 ¢ADÔ%g’‡/Ò‰kÐEƒx‰rc48˜(X3_(XSB(ˆËÎ F¬æ!knQ…‚c& "O&#@öo ÇP\`DD—-fl"0*²lŒ=Dôþ­0pœ¾N ŒPð´ŽK Ä &§~‰èv¦1l®ÅÄ"îüéÞÉ_¢˜Kw†Èã’Ë-q Š‘­Jl!*‹0ƒFb`Õ$ ¬ŽËaAˆ±kù­Q ¬ ù)°FNˆ} °I<ËI —øC!É#‹(ÅðHµ&ˆ½¬ ±^¦Å.!Ð3B Xï °f„ 0¶o ©„À–‡Xy•GØòÃ*$ùÑ»3…èé' ¬×T8".zQ`}D5CEÎ;ók†Š#px’)sk¥ÀžO‘Ç¥3Q | Ö¢®$WQ`ÍQQ`-¤ÀˆÏù[ƒ@ç0"KnËnŸˆ"Ä4 >>S=E - !yÎ,˜èñ5â¥"o1O’»˜ê 6‚@Í3ฉÁ ˆÞò!2`5Y ˆª’†Ä€XúÉ|[–q-XÿOÔT3¢%Ç‚€È’\)DB!ã¿/8nÞf5z®ÇžÓŒ€­" йÄ´îØ*"bÂ^¿5 C¬, ²$  ‡"_½¬ ý"kê [ òÌ…5Ë €¨éÉ,2I¸xØûO¸ÕnÚÀøXuuàËë襼i¢dÄUË U©^‹6p»éóÇÚÀíÍž¶2pßèo1”¸Yz +±û f”20î(Ä"@Låh†·®R_(Œ›ýÁ`@=dþû–ÝØÓÿ3÷©ÿF øï¼èq¿kÕâMЇ„°Æ<2…øçáî–ÍE—, ñ/nY¥ ÿàØc¡?\Š+¦?\æ ôýùÁnW¤–Oð'FqŠkøƒsŸx= x*PTì‡,¡92ûÁÀ4&Ù÷‘â\×쇻qmöïga?”çºf?<G f?<Y„~n±Ñ͉ £_x Œ§„~x*N÷~ õ…üg©‚¿Ýn –Óðמ"üaÒæ]ðg© í)Â_+™ð‡Úóô\ð×J&ü¹3LÕfÒ*ÏϳðÏÝnüsÿ0m® œ¸×”&üƒåñdJâþÍSxáfSš: ÿ0ÙóÒŠðÏÓßøçÙnüCž…þPpêMIÕÑZL "鯤ýµ§ˆ%§ðÏï‘ð7 Ó~]øç·Üø§×ÈôW­ýUÂß~ɩ௚'øóɕᯄüU þª*²J¬ØíËMù™ƒÂ{ߢ¿jœè¯ªýy”®WìW‰ýj†ˆýªm‚¿V鯥þªE•GøW“†üg)…h}ÛÿZ¹Ä¿V ñ¯§$þUoÿ°ô.ZÀö é¯äþyé5þµ<Ä?¯éÆ?e¿5ƒ…ûíH5ä?7Pøç±ýÕ$ýÕœ ýÕ\ýá]I¦ýÕÛ#úÃ5Ùg¡?ìsè„xêì:@ÿÌÕçâ¿êcñ_½>â?‹)ü«‡„µ$ÿjÒ ÿj`„5ý„­dò_ ŒøÏ¯ù¯ÕDþ«EVüW½.þ«šÄõ”ø¯êÿùmþµ‡ˆÕá_+†øWóDø×Ê!þUUI-ñÏåÿÜÅÆ??eüÓhšþZ1IíÒŸßÓ_Oy¹zû)Ò_+˜ô×òþªÑŸWã_•#ükOÿJráŸ‡Üø×ò€ÿ<æ¿–BôÒal…K( — ÓX«*`+˜ØS’ÛS$@¿ãB@Ït# %3`=$ô2o¬¶”d@/fÀêR1`¦°FJ Øò[É„@/Çév߯ ü  Ÿ«èøçez2¦ÁïN—W~#sø=¼/nòƒ[ÖXŠƒü°7íº¿H8»îonïK»P©þ^žùméǾÀocЋ¿‘gM~"Цù;ã°¥Ào#êømthRà·1ŽAß&ëR“ßF#(“ŸL~[:Í*ðÛhXPà§š üå¸Èo£ê¹Èü$v‘ŸSä瓟d*òsŠÑÏ)F¿þ ý¶ÔùIÛZä§,?%˜û”`ìÛh(TÜÇ¡,ìS‚©o£í¢¾‡?E}šE…}]ø›ú4­ŠúœEзɲÎзÉ—¡Ï‰ù*ÈçߦР&¾ªHÄçߦ">·ÅÄç‚M|›Â¿šø*‰oin"L|•GÄ·í?‰/n_eð9ÅÀç&ø\•‰O øê_¥øüŒxoûiüÙïU yÏeÞsŸ›÷*…À‡îK½‡O­1ð¹5¾Jðù!ò^+W¼Wu‹÷ÜþJð¹ªsk nŸGÀÀç¹gàsÍ&>÷•‘¯R„|n‹‘¯òùÜ_5WÄçšøœÇÄW)$¾­yZäÊ­ØÃ">7ÆÄg1M|U·ˆo³ÿ$¾'#_5FÈ燌|•"äóSF>7ÐÈg©Œ|n²‘ÏÓÚÈg!Ì|•"è«§}UrB_ jès1†>cès1‚¾Zo }î A_,èk)„¾Jô¹¿ }î/SŸSL}š†>'ˆùê1Ÿ³ùœ âsëL|-åýËšEÈçÞ3òUÕB>?eäs#ŸË1òU1_¥ˆùê)1_¥ˆùªv1Ÿ$7òyÀÅ|U“˜o³M§˜¯RÄ|ÛO»OoA_å!ô©y}•EÐÇóU1_¥ˆù*EÌç3_¥ˆùôJó¹f¾zJÌW)b>-Èd¾*Ḑ..æÓ+UÌWÅŠù\Ž™¯RÄ|ê-1äVæó¸˜ù,·™Ï 4ó¹9f¾Ê“Ì¡²2–Ž=SÄ|Ü\ò©Á&>WdâsŸ0ðUŠ€Ï"øÜ\Ú»(ýŒ;u§Ykè?á{»)ý"p_Wú]iÜ[vŸ ªJçAX4ü„Ûß³~Îmg<“b¿ƒÖƒÅ~§U~ÅyN~¦­ÒùÁ.ª5ú=ÏèŠý¬Ò+¥ß“bö›4R-ö“¡àï!üIQTð÷dÌ”b¿—¦3Å~ïÞ˜ý^Zá—ÑçÆ8¿†?8£YQFŸN)£OÞ5(£ÏþÊèsã }ît‰RFŸØ8 Úè¬iâ)£ÏýùqðØé§Œ>eÜjúû^vjÑlô©rŒ‡\¸—ÑçA1æ¿ð%æ›6úĶQüU]6úÜï|kŒ€ˆ;3¥Œ>wÆð6â©4µÑç&Ͻb@¸‡Ký—í>7ÅçºãMǦ8ߢÀcÓ­"Q TæÖCˆ©1Õòäѱ@þòhJôd1â©´:5êÆ®Aª´Ø¾ €`|å/Ì øêÆœUšß‚ïõÃòuåÁºA°ê V‘à+v&A·G$gy¬/Dg¤éQ°úK(Ø" â¡k¹ØS’kfˆѬTË’k Ä‚U•X°T,ˆ<4ô$ Öä Ö” Ö´ Ö$ ›ú i$ôWÔHˆÚç¢DɼØG(¬ QN.ž„ÂAa – °5™PXM–è‚B_51V9‚Âj² °:LPX!(„;ï&– ¢ÂV{R¡w¦B7ÇTèªL…HÙSG*t“M…¨jKÂK*tûL…nŸ©°§$ºÅÆB±±°•L,¬a¡§Š±Ð7c!:#­……í)b¡§Š±Ð› ÄÂö±°„b—”(a¡÷VÆB¤œÉ|ÄBï­Œ…%‚¸Ðãi.lå ½‡5¶<ä–B.¬6“ «ÉâÂê qaåúÍ2ÖÔÖ„#VŸ ±Î;«BÃVѰä–Tbñ¡—Ê_8énú?lOõMwKý‡.͜Փ«ìæ _ñr àÀ31`9†bóÊ`ôÕÅCÆ@øzÌa î(=‹ÝVíÆ@SÇCÿåÆÀÍpWž¦åò߹ˌS¯4ûbüyž4š3Â?bláÌ'ÌV–ˈ÷{§k˜äÀó¥ÏWsà‰s<$œ‚åò_lV"E›•…çþüðƒíKl^ÅHH‡2âÀØÐ,öŸðª¯ƒ9p^Ú3ÂÏâ¾\þ›“aÌØÅ@˜#XÕrùyŽåòü5‹h‘Zð³|.—ÿæ|R.s ¼<>y8aõyÄðû8œˆ ´\þ›æ%œ° M~#Î[¯ÄHËý?lïxoˆÜÞ‹[r`5Gˆ5=ï­Šѧ¤>r`«8ß)z$¢ök1­ÚÏß$Öà‰[ 9‘ñÈU‘8>Véj†ˆ<«C˜V29°•CD9s¹ˆC"Vw‰«ÛÉó}åsœWí XxUd?ràÌ­QãÀ ~3˜’xmº„JlYÈ×&«:q`åâ_FÉ$¶r`U%D ïç‘ÛSä@¤\‹G˜–‡ØRÈÛ>ë"ƶ"S’ÑÐ}¹ ˆ‡ÆrðÂæ~Q Â!þ±p ºg,—‘'_Gy„ÙuoÖavݶµG˜]÷fÅßGH8I¼vÅF¢œõ6àµÙÔ“ØòQ2¯í‘Qò½x…©ºÄâY®"ÏÞíAáv8g¥8ÐÞñÌ×®»~â@²ÇþÿÂGö¿ÿ¢à'ÿºž_øÈ¾\Î÷WúȾ·ã‘P_â|diÿÝýë/Òì#ûøÛ>²ăþ>æ'ÎÚv¿ÌðPö\tv÷>ÝrF4£ø #–!¾å Jð"¸Ö SœŒÍHI÷ÙÁ¶b_6D0î÷ËyÐØÒßN¸]¸2Ïxãk~Ž™V1c;ãdwÆÛºGÊŒkès ç8°h†[lÑñذˆÌdDÖŽ€,Ø´œ¼=0p%#˜ìfৃ¨p‹ÉÛçcG ™'=pÆ‘é×öçyãìÊ”7½tæÁRÆ›^:qº Ä=y0‚£| BüµRª=ÝÏÌgÒCÓØóm‚—Ž,æÉóµçäañ€!˜ìÉíõ—Å:˜ áуFŽêÁd0xŠMÞ€ý ˜ìyH{áöÂyö;UÎÈó5»…ÉžOSÿ wÕƒqɶcÑ—·ÖPB#='ÞYÕs¦§Î‹J<Œ…§Î+½ 8» GwþLtœ˜˜{¦tµŒ˜gG¦ÐÕr„}AˆӋpÍ,'=-ÃUjÌZøÙ®æzÀ_ÉN§Î{>uÇÑÚ—2Ò¼ï+8ŽÖ.œvæ\à·¹•Ÿ[­µ,ÚÃÁkD6ç<âhí”Ï×áϼÑ5p BÌÉÓ‡1÷8Y»p„ûdž#NÖ.¼¤ažð¥ÄÉÚJŒƒÿãórNžØï]Nò3>椫ey'3}ÞŒB=pZ[¸ï‹igØ4ÏÃΊÃŘ5<Á8Œ /÷•ð:€ôçR*¼t΃l„—N¹\× «åÉÐiã:éjù|Ù9׼즓u]“n:9­¯›ž–Xõ[¨ÓÓ²‚ xí /ßÚ|3î-B%†+÷`ýqïô´q‘pÐѲ|t´¬ªï‘~–¯‡=V´7S¢¯°¡ºïÞç÷E?Ë_²Ø›~–ê‚>£Ÿe„ÌÆ¼ô³|Sk2à×?ü,{ìàa3ü,? ´:žƒ~–Ç)ŸJ/iñB™gä©Zïsæ©Ú oà™gÆ©Z+8ç{é7¾‰áüÍóä©>k9÷ŸŒ‘7¡É5 ž¸÷ð!³Ü<öæg~ÀµôAö'SâXí‚ò$øÆ‡Ë cÎLç)×óa~¯Xož¿ä×LOù^€å/"JfÂ'jNxò5„çÐp”¿3PÄÉ5:º3ָў:ñ…Gùû•}~"ÌïšeĉZHÈ'îG¦¯|?4égYÃr"Ìo¬àxEó©›~–5¹N„ùü¦Í3™¾é56>JgØXc4#žøBãD $CÝvâ Þòå}öÄ:ü,kä“yFž¨!%ØÏ=â-OèÏÌ2óD g“ñé?qß'jÏyª9wž¨!äÄ›)Oøižð{gÊ›'jH úyD¸åï“ÍíÚõ7RxÅõÄzëžùO| ÃÏòF#èèð³<ŸóD°ßð³,¿'‚ýž{{‰Îö/ãÌÍÀ‰8~“ŸÅ,æ¡›eìb¦ @Z,áH}`q±„;þ#Sö8TcÀÍHˆ3µ–pÄ‘Z¼zÙ¾3B. +}â ½?õþžøBw‡êwÌ ?13厵žç‰ÝQ½õçΤڋ‡H¿×›KRØYœs#µ%%ŽÔjÙ:Gð=S„'óŒ8Së)gFSBTÑœ$ø@ï¨ë Ï -ôñ,)‰ºÚtœÐ»ž3·Aw–ó†È_Êž…Nh.n¦²É¡·@}ƒž8¾£&F>?qÖ÷ćVÓ畞cÓ““ _èíÌMO¾ÑøBÇ>¨„<ñ…Ž%¼Rrñ¹`ÄŸŒh¿#Û?3Ä}ŒKظžõë·Ç¡~c ßF*O„úÍh'¼;.W€‘‘~c ßx}à„£ý vBÿºyè1û´¾ÓWGÏCÄÆG(päõ‘m„eÆ÷5¼ß7_b¡ $Ý•Ï0±Ha0bkåÎL0ˆõ;û†0ø¥Ð†`pž„¶Xpž“¡ÁÄ‚_ÊÁOœñš#Eü²<©- ~’çgE(8ç~PL¢àÌ…½‹Pð[ššœ,ø=t«¦dÁ ÞK@' ~)¯èð¦•űs{NŒpó'ì ¾6ÚXôs!üúóÉYC ó.f9hbq\l A0ºóX@ð<Ó-Ÿ9ð|v±b˜ˆÁçoLq ú;O7ÄgD–oxÂ$+²k„çÃOŠ1FmÇ‚5Ó„š%‘'"Â.6n¦Àø|gb †ÿÎ<‰5ØÂÀšEÂ@Î×R!ˆã)qà„‰É09ý™Y’cw2‰#q>Cly‚ß’ÎõR 8wFŽ6¶<A[üñTl… ‚-A°&‰@[™üVÏ—·ñ ‚çKwÿÁyLCÄ®)?0Atr *œ¸Â—)Á‰Oyw*fBx#OÖ¢—¢r3áIÃÆbBa„‘pêÐßHxžI!¡V¹"ÂókŠOú.$´ FÂ3g‹ÏSóÞD¨ª „æaÁqáÁ‡„•%ð„ž>IN@8™²€ðKÉ,äAÐRng̓†\¡{FDXCi",Tž´u5Ö  «!¡)ÜLèiœLxXy(&ÄR‘ˆ + †Ž¿u&ÄF:YNL8è~¹˜P—¡Š }j`&ô½[L8xš_PX% ýgšü ±ùù­1!räðš ½JL!!ÞˤO#á ‡M3á™Î„°ÁØW$´ØFB $<ý}ÖSBBçÖúc$é0µˆÐňÑÀw%ÂJÚ„DØH„xK ¬ò`½?âÁJâxg,<ˆb®…ã}ìŠÁ(‡;ò`lˆ‘_á`½«ÂÁzW‰ƒx¡r’‘’K8ˆ×9uz¤A¿©¦A¬|©+$ za ú£`ôÚhÔ:gl‘½|šë!¢ ÖS“ *z´DA ‚î)ƒ »ª@ð+†ºD‚ ºAت&bº^I†ä@5̘zqÖ/ ô;( tQ`%±<‹FðÌ-ºÐ š ËCv‚ÐÇ´&@/M&@/*&ÀV °žzÍ0zÙNÄ+0øóåQÞ$âˆñ*­ú@}® €>L5ú4"ÏÛÕñ©¼¬ û €:¦5ÿµ,ä¿jùÏwcÍAøW ¤?"þZ!„?,yÐBøójaø;§¥‚?¼‹60Rrl5åØpYá"áÏ{ß79†¿Z1­Â_•#ø«‚ðç=ƒáß«£«[U‚?}ÓÌ~ÞšýüÉ0ûùsoöó§Üì×òýê]ûyÕú¹5"?•E~þ šüü©4ùù;hòkyH~­1$?žþŽ³ì¢½3tÚô»R´wÑ;œ Bq{$5j¢=~’iÏ®ËL{û”ªI´g7ç¦=àM~óD{ð¸4ÖH{v$eÚ³oŸ"˜ùà”àZµ€rÆ%è;p>–ö–„¾'Ä«°4|ÒוЖ¦„¾c¼RßQ 8tøk- º=S}—{-¡ kè+¦ô¡œìARVèÃGä^ B«.AßqʲOÐ!ˆŠ„¾V2¡å¼]ˆbÈŽ„¾ö¡/¾i U„¾KÐw€e“³H}-©)¹ñõ!.p²‚°ã·b_¨°¯•Lìk)ľcðøW܇žL…±¸¯*ø!e,à×òüZ É LÅɯCòsüc“_Í\¡ßqÈVWè‡ùž6ÈB¿zJèßsï‚~H¹m }Øýp×-µÞB?L=j ‰~%–Ð[¡šG~$úA„g1 myˆ~5Àb?„Ìöd´ýAІ=A»42V]Á” A©|$ – "A»û4 ¶<$ÁVQ°Rˆ‚U·XÐÃg¬‚ƒxŠº½!Ç[jŽx°=El)—où©[Ž·èYÔ—ƒû£sfâþÈÔP€ˆÏ & âß{D;,6 ÂõÔN«Pè‘»äDù6 Úù]¢œëÑÞ ʹ®¦RIŒD}² åa³Q^ å{¸Q åC²QN õº÷‡'—D‡-3 :ZœÑÛˆPk@tX[¢Ã ±¹Èî :„®ÖËOD̦mDG6 î ˆ˜ryb#@DÊro0Îg>Dµ‹ÖŽø3—·ùȇHÉ=´ø0œ¬,ªAÌîmáÖ' qò!RÞE5¸?tío>D í<ɇûkMòaM[ñáž`Öø°¥a2~/ºÁ2"ÖË'>DJ¾ùâC»Ù¶‚Ňr¢m>ÄCχõV‹{ #õ¼¼A">DB¾3âC{!7¶ñ¡ß=óa5P|èS;ó¡¼Ê£xñ¡bÊ'uña=%>ô"c>”ûkóaeVŠøp{9 ̇^¬Ì‡òº\|è§Ì‡ ]P|(‡ÅŇòì[|(׫Ňòì[|(?¾Å‡rÉûÿw.ÉšãºvîßQä2$ñ=ŽwÒŽÓñü-k-€ÿÞõŒãðuÜêTþÜHÅAñad™™"nnâC¥ˆ1›&>Äl*>ÔšG|‰7ñ¡òˆ•2>3'>,ÇÕ¦Á‡AƒäC¶rð!û&ñ¡ˆQ|¨”zf>Œñ!¢²Ýƒƒ!ɇ‚Óćó8>˜ˆ1ñ!‰|¨E¾ø0Rć\Ò’ïŇ«äCî?F ùP)âCn¯FÊæCî%>,°¾b %ø0òˆ%G|¨‚ćØJ >äÎ^âC¦Â8ø’ŇÜP >4WOÏC>d•ƒUù0Ä#E|¨ò¡…Áu†ª~Á‡ØN|Èö >TŠøGë‚Yxð!['øPyȇQºøP’Ňl/ñ¡ÔªÁćTT|¨êˆÕéâÃC>Œ<äÃH!ªÿć–âCñ¡äˆUgñaJF ø0ÄUñ!· ÿ±·øJ|X;8ð…·ˆl+pЖ­pÂÉ5ÜŠZÀñ™ÃǼb*òg¢>ç@[“ú±Gr`z ¨Àä@sg-ÅÏš’íü.¢Ð€çxÈŠà@KO‚#ApÚÓ~Ž hÕqOg‚à^X†Â” ¥-@Âí,ßžØ 8çM‹$@Ð rK0A0U -J´P ˆ´§&Ì‚‚)@pÆž"FéÁ( hrü­!N{w]2@0š h­ÕŽ2«þ4F‹­‚>w# ApND&Z‚Çc!ZQ07¹C*@Ðzâ:bÈX ^ijÎɉœ O£ƒ ‚Ñ^A“ìïAÐêÓ21( ‚I²ƒ  öÙ ¨ˆÁxe ‚ÑéÁÁC´Fmš<·)£G ‚Ñ7Á¨3A0z” hÍìo @ÐÀ¥AK™‡¡PÕJŒ@ÐîOtÏC‚àœäKÔÀª(à¾SÁa h‚=Ap®›@ ´”çˆ#cq=Ap®‹ä´§æGfÎ…øÄGÆ…x ãÈD âÈ,ÜqdýG&ªÃ82QÆ‘Y¸¡D hñØV6Ú¨ò$Züê>¢Œ#ƒÛéR™Æ¨1Á¨2Ap®Ê5Œ#câGæB Þˆ#yH†Ñb‚Ö^.Ed.D F}6Fk) #ÓE ™ #Œè(ÌUx¼ *£¹‚ÖÝÒçÂòU O£>AËsåP2©†Ak?§!‚ Åü¹s,™4˜‚) ˜­Üw ¸®A?P€  DjÚå[A«Ž+#F• ‚ëÂV¥@p݈[ ´¶@$€àºŸC¡=å­L´PìOŽ%“ž"š^  E-‰¿±ÁuÃH!\÷øA{ª }CŒ*×…crÁT€à²8?n†‚`¨NLO9Zo݇iôApݸ]S ½E´§|¼Gßá/hНýòÙÆ x÷»ð-%âÉ2G”ý‘)žŠLß=öçñµ7¹ô_[ )ž5Ó"¾m¤DTëþ´=«J”’(¦…¨HI¢†ß\¢˜E!-‰RÊ¿;Ö¶Ýd—}kû›HÙJ»þY†¿kû˨iÅ®!>bm3F <”Q´)(GѦ¤ÈEQ9—d)жd¥(Ú’¥\’•rI–¢hKVŠ¢-YÊ%Y)—d)жd¥(Ú’¥\’•ré¥RmÊÊQ´õ2*eý“XÛöÍx§îïcm?ˆµýeè|kû÷²}ÆÚþqŸƒûw²µ?×g¬í?Ÿû2Í}7þöÝûò9;~ûÂ|•ô·cmï}3›Ï¾‰µÝ'cm¿ÿúïúׯÚ~ÿþ¿ô/ÆÚ¾KúóŸÇÚ>Ëø×7‚ÿõ]¬íúÿ>Öö[ß½f¬voNLXÝvPÍá¥ï/ߨ{nÕ6d¶9ó]RmÌ«¶šÜ»oÊÞs{WqXúïsêk_Pmòör}Û«_ ·Sî½çV-öí¦Œö®âý‚ Q¨÷i›+/D~Øçnì64‹U¸¹v02N3¤Û‹¬}$Ù8Íÿ•0|ËÍâêhú–›….xú–›…6öo~õû¦šÝ8³W“ñd‡wÃV§þ°)¿<¾³¹£Ü»¬á º»Á0Í‚ïµöŽFS޲ZÛ[nVÛê¾åvY„5Ï2|ËíªØïkmú–›‘jó<Ó·Ü,Ú±+º/Íz\Î^½í›™V Q·¯·1L»Þ¾òþÜ—ÃXQ-b׸ßr»"¶îQG›Añ.©7ßq31˳tßq³‡†ç¾ãf±—‡>}Ç-ÕoúŽ›é°Ç@_¾áeÛRd¯ß^i¿mãnWCT«6žîåøÅ÷ÛÒß«ï·Yu½ŸFóý6Ó¨ûSÝ÷Û,Oñ§†ï·¥ß*i¶‘_]Îôý¶P º-Ù‡ñ¼|¿ÍÜÈü1ßµY³œùø~[zªø~›=å#Òb¿Þ®Öò„æûmÑæ³ûMhIÌðý¶PÂvnjñ§àÛmV›ÛŬ½ÝƒÄ ¦jâÛ¾_ mͼí ÑâZ¥ÂŽ5^Õ·Û’œæÛm)¥ûv[4Î¾Ý ¸¦o·Y©,Þo=:Ô"»¶’p‡·ìwj „Cgþäūïb-¾ÛY*®ÃVBÃmØx9úÕ}« ü¾„û4k†âB§o´©›ÞßhK/ßhKwÀ^¾Ñ Ý·o´…œûñ6u]¿‹ß’mI5çy»¬ï´éu~§ ßiKe ßi‹Æ»}76Z¼˜ÎÚ,ßh‹²ÍŸ¥Ž,ÅœÝöÎÑ×ÍNÚk–cç¬ö Î&~ªï³¥‡~bÔ¼óšï³ÅC÷ÙL§½IÔí6–;wÝ3}—-eñÀ\qÝD·¨—GíÊí»lñPñø±1`ßUµï²©­J-˜½Ù4sBÉíÆÚKß›l©¤qaöVʼ0{Smû>ßùåíö}~òÌÖ-$ §ï=öê.‡Q¿úàæ ®ã'µÄ>mß<È> ;Àçž´óu4§}œ÷ôý¸]²Û·yÏÞ‚Üv &Wjzý»Å«Gsî E÷‘§ÌÞ˜FºEZâì<)1U° ³7F]ë“·²øvtz¡ìÛœ¿}ß)™‡§}šŸüáèvY9Zó6˜»Y’Y…Û“_æÞžŸ=,»ç™“7² ß_KE¹+f<'&o¶_÷xD)Û©ýìÛ|oüx&o–5JÅä ÍG-š»=¡=˜ºõL¿1u«¤qý¹Âv˳ÏÝJ™s7Ý®y^-«`çcö¶oóçû4?ùÕ˜Ü-Õnºi>‹¸^û‘ÒoÌÞl3àô’«gf–qyæÞZKE­É›ØÚ:>öm¾ZcßfNÞ>)Ø·ùÉ‹›¾L‰#¡=˜½±Žê ¹æµb·|öæ·mßn‘?úÝnÉðÙûò£ÖÝ®6ðõ÷ô ̱ƒS¯ôÔ°p^ á•÷Žï°óž¿Í1ß*Õço®o‡}}Çõ¿c×ì>ž2-ü!/i\Z~#ÇX˜¿±°—{µç¯}*µÙu({óeØýÎ{/kœa×;ïÕ7nÕv½óž¿í`sÛ)¥úü]ÃÝ7<@^û:ïù»xÜØUzàÀðWÃlΖvt í¾ ½ÓxÁ]C8o4ÎǹhŽ—óжˌÐìªà='ÀjCúNXmS½;º9¾)0E‘«Ýòd¬vаÚÍ{#™Xͤ8‘¼pOD  ÏmÀl½…€,ÙñŽø’Út.#r¸v÷…€Z”mçËW!`¼/lÅ S ÐV† >G@³:nd! 9÷x …Ë[Þï¨Ü& ¥øÎÐn3õÞ#Ú˜vŒ%ÞÞáä¿{_¸ø#ñßmk  ¼_ñ;ü§C-â?;syÊÓ“½ð¶áè)@;q°;’ügÖOää?¹†‰ÿtxFü'ÇmñŸŽZˆÿäÅ.þ3—~/‹ü§Ó*â?+}úSà?94“ÿ¬Ê»—ˆòÄþ™½¶»\àŸ¹¬7OþÙ±ï[òŸùÈ÷B€ñŸœ ÅvÅß:òŸ‰ÿÌXìC„üg zW“ü—ò€ÿtæEü'WnñŸÜŽÅæwy ÁVV;øïñkǃÿäc,4*Ù}.TëˆÍï¾z  £€àN¿{å¨h‚@ù› -@¨¶>7¯u”O¨¸‚ÀL´° ÕSQB ±ÕíyÑ„@!ZáxøØþÛ~ˆhlïŠm/s<>®¶š¯ 1Ю(†`àSûW¨ˆ(â@s,ð*“QC øØé;— Œ²‚ÖÙ ¨° ÁÇVðžTX‘`’´0%¾¢ šVã A…H > Q˜E‚)HМ,‡-`H& šßäžo…‚Š‘"´¼TÀ¡àÓ[(h¥{“ŸŠ]agAÅt >vË·g ÚȇaÐŽ©y£E ƒVÐãÀ´Áf ÚeÖ>L ƒÖåÝË > áÃÑ\¤ÁÇ>1»Î¤A®Ýó8 >±Eƒ6Þ¶´pÐÚxÏÓÂÁÇ_Ô„ƒÖçãÀÁèOààÓÇZ8C›8/qÐtð…>q0U8h×ï%±pð±  ;qÐzâöààã^“ ­Mȃ1¼„6t @øt„T$ÆX"Z‡ÿæÇ¹l¡üî„&Ç_PácŽ«Îr@˜eÈ„Ö`þŽ ­™›ƒ$˜0šLj‘ mÖº&ŒwLhnÌ€D0¡µà6äˆ £É„ñ ­·š§€ cœ‚ c¸“ c–!Ú×&´áŸ2a¼ÆdB˳¼p0¡òˆ ­¬Ç™ L¨j0‹ 5˜Å„ 0%&T»“ ·DPhßë}”NP¨ˆa‚Bû*¢:€B­B…)ũМtI…æ9T¨ãº¢BZj­',T £¿h[dhÃÿ}8›í@ð†ë}™Ïdx½ †ÛpX_"Xª u²h¨ƒì² Ú:ae۠ίÉ6¨WP¶Áíºïy`Täç ÃVìÈäaÜËgN¡¸³@†ãÛ‘‰dh7D»ƒdhÑÃ}…L24ß}·× íœ@q9N†¶p‡qЊ‚dX,˜ÝA†Åa‡qÐ|÷@‘a±…£Ã—“¡ôÝìC2,v¨ßi hXZû0–·-¡¡Žq{ ѰØ%Î^аØ‚‰ «Y‚‡ee ‡–284¯ÇzXu”è°ŒN²3$Š‚H‡6xëa,v ÇS€‡© ࡵâa1GqOn§Ì‰£AI‡vÃ“í¢¬é) ÃЛthE5O»óÈ-ˆN‡Å|®‡V”ã+ñÐRnÏ<Ü/²§£uˆ‡ÅÿxXƤñ x…£(â¡9+!‡QñІ$‹»›õ€‡)x¸½cƒŽ‡6*Êa,‡¨„‡Åœ·Ý<´‘œã¡5Ѐ‡ª ðÐòøÂx¨!)<, G„‡zCˆ‡êsáaõCE ËþIZÊa"´ÑîßtÒ¡)¤C›Î»çÚÝgë0Z‡ÞþèPŠè°š¿†§€5¸E‡zkH‡õZ´"‚5LE‡VAL:Ôål¢CiN8Ô+"8Ôým‚Ôph}å«QÂá#·#Ët FC £ ¡U–«³$¡Ï>é'ôE]}åi뤾¾ˆŠ¤>ч¨OˆÔ§<¤>»u×óú‚ A}ÒSÔGÒôÙáàúŽ¡ôÙYý™ù¸® æ£1߻Ь‡K¨µÍéj•¹—PkßCó©%‚ùg0µÁ|Ú-æŠù”‡ÌGrMÌWfPiÈ7`™äÓ6+a_#‰/ÄüñÙCnh$ð½¼rò©ZÀ·ÏŠžÀG¤à³ÃÍ?ï ¼ïa/#ñžÄ€÷,Å}â=i¼'9Î{AwÁ{\Ü‹÷"¼§ ™à½y˜CmÒ^Ô7hO`IÚã䢽$G´G-øª¯…È{V»'»„–‰¨Á{s‚±É{û;ù#ãÞºæâ=;`þ#á^*¸b‰{‘Ü îÙqw¯yï-†6ðžõÁ:í; úbÖõÅÀ'õÅTBêK…ƒúb:'õżKêKÕöñ#%êS?ˆúTQç(A_ÊèÓ;$èS }!̧žói*óiì‹ù´=+æã¸&ói”ˆùBI2_JôEI„¾Ð@ÔGÉ#¢v2ýmâ8Nb3œBgóèoMN¡ ñ€šN^4(Ñ|€uY,gOáÉ@³dœÖ¿ŽK´‰€÷‰2N¸’­êå8þhD@‹s”V·ÎÈôGë»øOÁwÅöuqÿ‰É¶(¹Ó_³Wǹ@ûÈ{ǿǫ”°-î&$Þ:¤ìÏM_S ný Ãߢ h¡&Üû”XÝið÷­~ö-qŠþÕÑè! ü3  þu›ð<ð¯.8 ÿ´U'þëë&…ÿtS¼øO· ;ÿõù`_ü×x9ºøO÷¿ŠÿúÄîP÷¹ u¦°OÚ” €º\Xû§S¨©{`«ƒÎ›Àjhy˜ý,rGÏf¿ÖüO €fe^¡¦–, "t7 °.¶öUO´ÅODÀvÁá@hq¿®Û|`§'*R¢°7š@‰€ö”ï%íšz?¬L|'ÑŸ°ñ9Z,µc‚N€ö®º pÜ…Æ9`¿§ŽhWµ·Ã)tØfüq*ÐB²­ãX`+îGdÀñàÖO1 …m[.ÙТbø øŽ^œ• örñ¬ (Ðfód bñõ<)°ßˆG& |;ŽjÄÀQ([h¯û80ð}ßáD uâÔ(°W6ö ÷ “G»}õFì ᤠÇ×K„@‹ýöF?‹Ó«ŸÍhýàÀÑŸöŽâÀ¶àº. cRØ;®hÚÌ 'Q€ EÃô%'@ð]„ðl‹fÈ£ Â@Ðì¹ß&8°|s‚£Mzr:v[ýv¿¶>ZGÁ, 샶M‚àžß£ÃûŸ¸ÿÚÐ¿ŽƒcìJí©ã\ >0¢@[ØßÇÁ@›³qšÐ(°ß¸ç]hÓ´{ËÑìga‹¼“hö{iË“8.,/ñô·™8îùó´üÙ,?_Ð^A^„Àá‹g 5, @‹ñTó©@ã·t“w°&ç9@ 5Ýy,pT²/!Ð:ÖA‚hñ ]ŒCà¨ôG'ÚˆÈç/2!0=ìó0ûõ²>|@íý›‡Ù/ZŽhuªÇ‘ÀÑ.]h1%A€ÑxDÀ¨•#ÿÙÊUÿ·ºþ½Œ‡Ã~ ?{÷çO{¤Ο}Êxú³x¼>¯“þF½Im ?Ôègýãs8Ñ/¦;¢Ÿ¯‹“ŸÆ6ÁoœÓøÙ²jÖ>EøY[;üú’·¨ƒŸÍc>æ~öÐ8Ì}ö©oÀ<? >=ü¬‡ü»Dð‹Á@ðë Ô)òôˆü¬%€_ ?  /O Ÿ=oQ Ÿ¦;¡Ÿ}v®lﳘfÓ³€ýl©ºÜYìg/Ù~£ÀÕOèg¼Ž³€òírïLg?ë«uØûlYVÁ~¦Ôyp¿Cûiµ±œnD³ü&Zv0Þ³¿-‡•·f“ñâjݰò½ z|þž™O7êýÿN[uº-Žþ:ÃG#/·Â{ú§'=¡“ç£Lòï|ƒâü;…}áß9~ÿì“ïgÎÄx²ÊÆ×ÅŠrï§ïYŒ_#3_>Ì|Âsü>㙪‘_JA Y1Þè)²òÑ,¬|Á]ó.3ì#aåcËÈÈçñnåi—-Œ|á{J#ŸÝeý#Až­cœ dä£T6>Õ6>9zÒÆWLh²ñ•FSœl|47ÉÈg×sÿHˆWìú‰ð V&>oeâ{DE&¾‹±Xhâ“ã®L|79‡‰O6Sšøâ!šø"…6>î%ÈÄ'½eâ{>¢¾˜?¦“$,|æ=îôD ŸzV¾‡qtdá3Ÿ Oá¡?ë}g.Zøn…Šá¡?ÛUñ<<ôgÀçpI ßå§©ãÌŸ±ïaà3³ÿuøÌ£ËIgþVÁ9žù³-Lg.Zø,«ÏüÑW ÎüÙÆ¢ ¦‰ïD@žù³½d gþlï=˜ø®N§Sžù³î8Ïüqb #Ÿù x Ïü-ÀЙ¿xŠgþ޹ƫ£3ëÂw^gþæMó!­|Wù<ó÷6F9¼:­1:ˆÏ­|ÂÜÇ™?Û×9ÎüÙ´ëÇ|tæO­¬3»qæovœy’¡Ï";òñÌGSœù 94ô]ííÓò8šéÌGnXú^x8,}òò3¶1zœù‹ êÌŸzKgþÔ‚:ógÛ6Ž8óÇodœù³àÃÖ§ÏIœù›XÅ™?Ûvj♿Åù›¸˜"ÎüÁƒw<ó'ÕuæOCNgþæC!ÏüièÌŸjègþÞFŽø/1ÞˆyvÄÈÛ†˜÷4ìƒÅ™¿õ`ɪ3fÎðžùÓ ª3‚à<ó§a¡3!‡gþ®‹ˆ3œ¾âÌŸšgþ^µ@W<ó·°$Œ3*JgþÔW:ó§ MgþFg Îü­‹gõxæO5Ö™?Mh:óÇ%NœùãŒgþô”ÎüYXÁÃâm¡3tÏŠ3 ÛáqæO¯¬ÎüMîéÌŸz‹gþÖ ŠÒ™?uŸÎü™_?Ä3YÁiŒgþT”Îü©1tæÏ_Nl<ó7q×HœùScèÌŸj¨3æ§â’yæOoŸÎüi0óÌ_TgþôbéÌŸ^PùSuæÏ¾“ž‡gþl•ÙÏÞüyžùÓô¥3Cà0úÅ„¦3¶!å§yæOzêÌ'Ï8ó7'ã·ðÌß|d<óg&½óÌ[9Îüñ³gþâ)œùãëgþ¸4ûÙH $àOçNãÌŸíÅð§ï¾Îüqæü¥‡vþ±gþtx<ùŒ9Ã3<¨›"dÔ–BR¯V÷};ŠË9ÔõG¦x*2}÷ØŸGÈž6‡•‚•bQ3-¢ÒFJÄ¢žû™ÖZ YÒ’(¥„¨eß5³ZJ]&$QL Q‘òïŽ=-¬ºµÊ_ŒÿÛ6ûGÁ²¿äýƒ¸Ù¿jøË°£ÚvZŠ-üÍ2ëÅdRRhl“#cSNd‚ #È6%E`lHJq±%I™()‡Ø¦¤‹ I)*¶$)%åÛ”A±!)ÅÄ–$e¢¤^›ïZ„ÄvI9"¶^Qe‚¤6ÛŒ ·]–ý_.löŸO˜¿}™û¾›ûîùœ2¿}K¾JúÛa³‡mlüûƒf׫+h6ÿji3Û2}‰™m‰!wê__bf[bÈñ˜Ùïò¶@'KüŒ™miÿ[ÿúoߤ1fö³þ8fö0Ëh7o•k{JðÝ3o•Ž BÃ^—i¡Å&Â}ŒaëJ5æ›ÌvÞûf·ôíåɘº|aÉþ®[tÙ6R¶˜y!èòƒEà˜~¾äMBŒù êr¹øTAÔå‚SçcVD].ØsxSuÙ"ìåÈl»\p—ݰOåŽÛYq2}Ø^ áíP†ûE†…¸ËUoÊö25-bÏ^9Ø¥!;r§Ù®·õ î22]¶Ø-;¡"æ2#jUs™¡‡ß¶CÌe‹‘áOuÄ\Ž”˜ËŠà·&b.3àZ¹Ì,óº<ä2w»§uÏŽÚYqúcZ÷ìË‘Rr™eO‹XË!¸"æ2£Nš‹êˆ¹lA*êNŒ¹,1“1—%f!æ2C"ÎûBÌeFŸ÷˜Ë‘ò æ²$ÛŠîe÷¼+c.#®Ý›Â˜ËJiŒ¹Œmçi·Ò{àN刹Œˆ‘ÓBˆyàNÉç½t™bv´ µhî+¤kŠô8-xÇý)E—‘Px1Ó§ÅC)gQ—‚|(¶³¨ÁÀË9Æ}¤,^Æfé´=µ9³är3ð2¬Óì o1{—·ä´jÝyoÓè4G®£Ñí‹GîTJgÜeª`Ûæ;r'ƒ±Os9Ü‘;s–ŸË(ÉN¢1p§.;¦7¢ìlwzBAÜe äZw™½Y+/k ׯÀË~nß©\»:ú6ÖɸËìÞíÏÔrÙíBàe•ÔîGaó]N{<ð²^`[Mí\õ~H|§–æ.t÷Ü4æ]µ'ðÓw9ʈ»õ›¼Ì€’ÓüÿæÕ½«0û…ÀËz]ÍKbOàz]·›Jq9ÍŸ*ˆ¼yê3í4»ÿu¼òÛÒ_On. l–<z™ʹusÝiG:Ëñ*î›ÚZ®³E_mG“®Á—Uú*|Y¯ƒ Ýsx®¾¼¿ëïÚ‘—5pì½'p^°1w¡çH™ˆ½Ì^X ±—·Ôu]¼L©kGfÍþu=¼y /Cê²%ÍÈþeÿÊ#dYæ™fµeº§n¾•Ë>ÏWžk–}žïµ]ˆ¹ÌþX÷å1—Yóp.ëÈñ är¤”K÷ž®Ö]rYß!—¥ÐÝrãnÙÍÍ3/£– Ê3÷²/󕇿²/3#.ï,öa~² ÏÍxËLxnÎÛ^]‹Oåó6¥ZÀ¿cÞ^N¯ça¹¶‘?¿ëéý¼îdYè§¼bZ{Ÿz¥IymcÓˆÏÊÚ†®¼„Zå~4o{S™½”ô¦/³’ÖUz™Ñ¹®<ÌìX.¯;AžW‡ž_¿eÕ>oKòh˜·•gVÍÛ[‡²rØ7ùš¹avÐŽ<›-aHB«»“¦n©îá”å˜wnàú*ÐÖ‘§ïS©£Ì|JÚÍ3º—ÝØ¼%í³Ìµ·'˜¹ì£|ÏüfÛWù‡”²0kÃo8vؽ5V¶àQ¯üÙŒínH„?3ÉoŸ݃ýø^©Ãß¾SiùC ›ðWÍH¿-i„¿jWÂú2௚™ÞŸümßÑüU»UÔ®þªÝ’ùx‡¿}Jë ø«ö)ð}fÀ_µk ‡?åðWÍ'ÀU7øÛ`ìôuÛ2üíhÞ^=À_µ›,Ÿ û©m ÿU»òÑ7î€;Ïv’$V»¯Ø+ Ì¥;FäpàûΧ·œ’ pçÙVàNØX$ÀœâX—¯W‚ë6·xŠà¾5kïî“ßÜÜ |pS* 0‹qÜyšî¸ól‡:àÎãË`Ê|Sp¸«³Ïò’óSN€Õn…Þ=JLunÉàF'Àœ² p' ã˜Ô¦¢@€û)_@€ß\qJ¬¶<ÙÎÕ ÀT6p?´Ý,I€»¨ÛrÌ…;¦öî<¾¶f9N€»,_SA€©,àγbDÀT0?µ0'8V{¡nOqÌÕqÌE9î§œ À€) 0§8¦Ò©Ê ÀœÇ)pËiàÂM©GA¹¬»‚Ý™Ô10å˜;¦ÆæÇÀô”cà›ð¸K10u00‹qÌO9¦6æçÀœâ˜ËrLî²¾Á9s`’ÌOYh˜hQ€`Ni˜R`Œ†§}0šöÁô”CQS „šAd Õi Œ¤0Ô‚0%À@ƒ‡ÂheZSQ°F›ÒB˜ ‡…0ZÂ$BÝ]& aä¡…0êC a¼Z´¦Â>ÞaØW"°/jHìcаjöQL`#Íö™oK6 f9Ä>ª.ì«æ>b_Eì+°/÷UDËî+ˆÜW<}`Ÿj#싇ˆ}vBìÄ>é)ì+…¼FìÃÀ êc?ˆúB ©OÕ#ô©D}‘BêcA‚>5 ¡#) ÏLú.…ÐÇ¢Å|öñô‡È|ñ™¯ú |êJ!ŸÊò©É…|,[ÄWp×@_™¤BŸn:ñ©l_¤øTOZ ø"…À§&ð©+|·ð±[Ä{"â=»°Ö=9É{‘‡¼gnìN’à=¶¹p¯àƤÀ=;¬åe÷x³uà^)¤)➺—¸§^î¿v!hOÝ"Ú‹ÒžEøqF$íéí©AE{j ÑìIŒ`O%Øc/ˆõ¨‚£žZA¨§¿“ôø‘ÒSÕDzzˆ §Á)ÐSI=VMœ§bž¤ó4Ì„y!—œWÊÏdÿK¿‰y!–˜§,¤<*$ÈÓä©*„<ÕD§ñ-È+×LxüXáñ³„§ÚŠðøÂ+ ‘$¼(š„§<"<žÊá±!xŽs<öšøNï£øN•ß™O‚‹!ßI ñN ¤;vAàf³ ;öIÐ/§º+Ztw¼¯>àŽ ÜñM º‹ê‘î$—tÇîà±½ðØKx\*àñý À㈋§ˆx¬ €Ç„%‘ðÔ"¸4—{‹ÒTØòM$íß·V‹f·N§Ï&eTäÅ„±/Çlj˜0vêŒ ó ð^Ä„10ú‘,€–Ð?B Òi `æA›? ƒ¨¸)$ÌÅê0$LÅÍ· c[5?’Ð&P·XþQD˜›Ž–Šóð ƒÂÄÚ=¢Â´ÃñS‡Ç#*ŒÖDTÏÀ0Q=…„ñŸ ÃÈ ƒ3Ó) ÏÆG@˜‹ Æ€0ÅC§x0zHñ`K@ñ` âÁÀМâÁ¨$ŃA¥x0<߯x0¸º9…ƒaÙÇî †Ã#¢Á¤ø0K‘< ƒÁDÑ £ cñÚ= ¦v¿¨›"ÁD #Á(´€"Á°* SÄQ ˜ì2Àå*L}Ü‘;‚Àè Æ€áÀ0Š£Ê*Œº^1`ª_Ž!`ÔÑŠ£ÐŠÃwDA`Ô’ £Ñ¡ 0‡†ZF V†!`lýàf6Å€A…€aL§†ïMÄ€A´¨ˆ#" UP ©  0脈#)Œ£, Ã^‰0¬p„€9ã¿°q#þ »$â¿ "þ ‡CÄa…‘\…a³DøT?GÉœ—:-‚¿PJ¹OÎËy<ø Šè/¬\DÁ\¢¿°)#ú‹bÓ0ú‹LDü…‚#ø «Á_ØõüEyüEyü…J(ø‹ü…/AÄ~A7Eè6UÄ~aJÄ~aeû…ݱ_ØOû…³sÄ~¡ûEE1ö +¡_T¶B¿PËý¡_ø¦Dè¡_Xx„~¡Z ý‚ÖRä~D#ò‹F@áCŒýÂxsû…ëˆýbüí—â¿ )RüåQüåQü¨™Àè)€a ‰ƒA›"À¸V)Œä*ŒÊV ¦( åF´y ƒÞŒ 0) *!`X…€Ñ3Š£,Š£‚†r†õ0JQ j  0,)‚À`8Fdžµ‰ 0ì–ÃöT‰Q‰a¶Daÿ+ ã(¦ 0,)‚ÀD ƒÀàOA`Ø8-1`”E1`XãˆÃ,+÷va‚bÀø¤›BÀ°]" {)BÀ0¦Q„€aÝ" ë¦0œRåQÖO`}("À°: ÃGvS„€a»ä0^c…€áâ5ÅȾ¯ûž¼øþÇ}¿ôþK!_™#»þÈOE¦ïûóÙ÷µoƒJ‚™¢Q3-BÐFJD£~g‘VÍÜuDB…´$J)YÔ|Aûç!ÆR²ÿýïŽ}ïèŠÿ46vý±±kýG±±¿§Ëmß)‚ðwƒçÑéÞÅ.'_SPŽ|MI)D¹(K¡¯%+ž–¬ÈEY9e)øµd¥è×’¹(+ç¢,…¿–¬ÿZ²"eå\|Û›²rl½¥‘ ²þIœìµ/yø¯'ûÏ'Íß¾ÌßÍ‘¿}û¾|L›ß¿0_$ýí8Ù·Ý õ®/¿‰”m1¢ÿ‡þõß¿ cý%RöÑúß)»#÷_ÿI#e¿Ýö ·ˆì»ÊÓÄ· .ð{SªÇ`è¸ZñMÙ+nRw¶eÛ¶xf”ÀÉ/¸Û)óÙÑ1ìZ+OX÷^@[T1ÿôÚÛl“à[õÆ”µ'Ê{á£þܾ½fѤbá¨Î̸ùÅëûT_[\/ö¦ØŸžâµyö*œ«ïo»×^»È{™å@H)P€ëKY\@_.ØîŒËëœ7å?AxÍë[ ¶×°}Sl?1- ßhÀݳ7…Á$Ñxe¤ïωeY³|{Ûz÷[q¿¦Q÷, PLeý=àß›ðV!ž½)ké?p­]ßÚã™VæÀoJ/?áy!e 8ró¨ ‰U-0À9~>ïÈÒ.DX–ÐvÏŸõP°¡úª[cõUrÛWFèë7å­?Â2wîekd7Î åýÀ¬ó©™£Z¿¿C”dWoï.b»…°ÏJöW­loÊãK‡”²7òw]äR‰yÿÖý¡á•뽸JÕíoŠ}!OÁÓ7Ø’àu*0>TžsoÊ=™‚,Ïp•Tò(ÝUŠ”Ú¨ÒåõÔ@uÔ Š§Hƒag7nvÐ!y^×Qö¼–ë$)óS…IÔ×óU¡üˆ˜áoÊ«ú ­þlg–^~ö3…¨¾34`ý^ NæZzjëÂïåϬÛ÷×¢Â#/¹}S¨‚ÞžµcD¼×7ÅîPÏoÏûMæëD1ãátàóÃz5ǨYÐ ÞÜE XöûÝŸ§NöI9sØ'àÌa¦³\’ÍQ»Ôw¦ž¼íòàuTæyÆù»ô£GìK|Å8·f¡½p±Üñü¬§T_óïý þz n»€ê,¼\óC#»áwæ}Ûºëèýò¡B r4·.J…ÒËǸ+ãa¬ÿé óþee]œâ A¡ª¯ÝÑü‘r†ôFƒÚ-Íù¶‚7¥´ŸÇëW¿ÿAÕ«¡Ú¡Ry¦ç,{Þ=U×E­(y­žjÔA-Ú ¬ãoÂÓ9C qì’æy>T+; EµVs Ûùè•FÔ0-€Úm]œÈÑTm­—©_“*¡.ýœð vj ²:5NvIó<ʲ[š×QŸÞÏÚØ7ù>ºÅ¾ÉçXë¡CAmÖúH×ü~ãÆ:Hi<ý££ì¦æ³_FèÀ<Ô!ÊêXq†F]¼?öQ¾sÿÛ7y_˜ƒûQ-e}ôˤìÞ‰-”¨Ü|úǼm×4çuÐm·4CJ+ì&4çìZÇaÏq¾sÞg¹ë:Gž}Ï>Z×<çnir/ÖëíQ¿;(ÏÖb3SÞ´#RÀ1§<» sb't»¢½Åß¾fåÍŽ“.¢¼9ŠÇ‚åÙYŠ…<›’Â¥‡˜g»ˆn\'æ½)Ýt‘ó""69oÇ¿¾ñH•±­Éy;þ5˜È9¯š·ÊDž[ñ®¬Ÿƒ^µØÕIo‡ ®•“^ÄŽ&éEh’^ÄB&éEða’^Dò%éEt]’^D<$éEô;'½ˆç¤W—_£þK¨WmW3ê½)æˆz›óïŒz;O÷úVh`;ù ¹MK;ê´÷¦Ül §½2ñÔÆ½#eãÞ›òp¡nìþOÔf‚¬ÅãÇ÷vÊt œ÷ªÝS^3ïí”áO9ï)Ô ±5èì¾²2ðírã¾7eˆ67ðíŒâæ:L®–u˜|ëøvý0bøòSŽ|u¹¯Ñ/!ß‘g#ß‘‡:,Žg¾#eS]6•yùŽ<Ó£)§<ë>~ê°0úªÝ@KZÛÄt¤ld:žÚÔ÷æ¹ýÄ ©o§è CÊCî“úŽ”ÍLGé›ú²£¾œÃ©o§`^˜_t˜Ð!¥lf:žÚØ·Û o«sßγ2÷OQ‡"椑²©é³©)ç1îÛ¿AùÎ}¹$羞\Ô¡ºŸÜ·S0{8÷y6øyÆC­P?'¿7¥qÎY_tXÔ¡â{òK’7ùíßË¿¯N~œä—4ù¥ƒüvžr68eop:ÊÚè—túOmôËOÝÔAOÝÔÏÜZ¦â6ú¥¾ú26ú)Ô a÷èwäÙðt¤lxJoà/×Çá/ëäôwäyÆÑÂO9[Êé/k Ûf–Ñ uªÿ¹Ôàâóú&ÿÒ{üÛZbMîø—f àß~ЏWúù u¹­òÂÒÍùïÈ3|÷;ZØð¼ðxê‹€¹~€YÀ#Oñu‘Þ² €¹ì ÄD%RÆÃ™‚RæÍ9Ü¿À£Æsë4ê Ò[è€ÖqÌï¦`š§@€Yó¶ãƒGý³:Ä3Ð!É]×—”õ1S8f9΀G uV:„œZ?SZa_¡ôÞ/ ðH™7g;Ì:DÙkQ+´Ž3`.É0÷•3àñTñÕ]J¡‘: †Î€yã9ôvÌ:8fuÐü1C”ä˜kã˜Ëv Ì¥;æÒ²¨ƒÚk޳Õç¼oŽƒàQòÂÊH)N‚y^]Ô@óÝ ˜§´c ñ7â_ <;ýìd/n˜ÌìŽÀÁwÉíìHƒû [œÛµd¿ƒÙªF›_l)Óæ7äÒä‡e ~ý&DÑà÷–v?s°ôT>eµÌ¸L·­eæÇ±0øYÈA¤Àâ7›Õ·ðu;¿KƒŸ}\üÆ<1p‹éx ¿÷)T˜?;‹…§Bô¶«P·÷YØáÓà—rÀà·æ§ÁoÝ´XÒà÷¦À#Š¿u“~iò³ ¯ EÍ,Ž®'Àä—Š‚Í/›Ÿ]„1;¤“q¤ÌêÂbfFd"ßE•`ö¤ÑÏ üú0úÙA˜ ]w@z0 YýRÙ°ú½½Nû¢ýrýBýÌî”á$=Cº‘6¿hpýBKZý¢+iõC|ú0úE]hô³Pè§Õ/¥Àf¶ª»s†ÕÏý×ýGXý,^z¶ú…Ž´úY$oÚ¡Â…õ„Ì~¡í~vüËK¢Ý/^Úý¢~´ûas„F¿$&³èý,Ú< ‚ÑÏN•Ád¶~æ®Éß‹*í €­=O«ß¼Ù´ú™Ç R`õÓ”A«Ÿ`Xýb: Õ/å¡ gZýR•a3{§Rôœ[ýæÃaD«_L*´úE…iõKy`3Kr`3‹Óìgq¾=V?s,zÂì—SõÍ~šreö³¸ÐÀ¶jgöKí «Ÿj'«_^*œ€§<<-êïû#Ç3ð°³|'…ÄwQJÞéÒ™H’|T>}:U´øN%‰ï¼žó‘ÒÏ?“Bð.¥ï`Ü©MwA‘¬¼pUp§>$Ü\îT[²]$”~T­DõQ²ØNÐ#¶ p#Û©v‚»H ¸CQT ~úsFkŠí"…lǽ ¡tÚ±œ À*÷…Mv¥;neØI.¹NÝÖ¾Ô¿Eý±ƒC®‹\MN®K)­Õ#×%h£ Ú²Øñ•×±!„uª ±.HX§ºënQ6 ±.º–\§ÊëX±N: ëÚ§+§Õ©Hu)…T°ª‹÷DX§¢ˆuRIT×?9£e@u¬¡.ÞPB]t¡N‹tAJ&ÓżE¦‹êë¢õˆu!XC‘Xµ™T€¢óxqHuêDR]4 ©î­!‰Õ<¨>‚Õ±n#¨u¸sz¼ìΔ<´ÇëÏyhWÇ¡½på㡽p⡽pö‚;çj\wÎõŠãÙ9wç\okÃÅŽîœN )pç…ãèÎi7áÂ:¼y: {p…´+šðÔv…4T8…ÂÓ®';Ý9ç­úAÛ·¥ó¦ë`,™ïMyä† gH› a`ƒ;§Í&òªÅ@i§;ç|èªGwN›ŒÃ÷þrÖÜ®ïßqx‡îœiî—0o?CŽ‚;§ (5èb+j0aF–;gÊgÈ”wN›ŠwNƒP&Ü9“d­ÏlWÈwJ¢³)\!#…îœö‡ÌyY*Ý9mjƒ‹%4°Õò@ƒ8xÂÒÖ£( ô‡¸s¦§àÎ:¸;§í{á7tˆgèε¡;gtçLOÀS³›Ü9SjÀƒõrçL%Á2¥ÀR_¹s†ºsFºsWÃ…Òut’rwN}äΩ¯Ü9õ¥’;gz ÐiîœINhÀ²á ©ï›Ü9C2Ý9-žãéΙžúÐîœ)®Ñžt猖¡;gÔîœ)Ü9 :RÖùe’;ç¬r—„+¤í«eþËeÑ3jèÝ9“”/:Ð3¥ÀR« ¹sƸ¡;gŒìFTÝ9clÑ3äÐ3z†îœ¡…»sÆ{HwÎT6uP[è@ÇQ¸Bæ­Œ0JéÎeÓ3Êê¡3©ƒjHwΘƒèÎ5twÎtçL9àΙä†rð\œ+0èÎõ£;gÈ¡;gôÝ9C2Ý9SJÓêŽrà ™RÆYcºsFûÑ3æ;ºsFmèÎyèÎs"Ý9S¸s¦µ'±/òûâ,%±/F(±/ÊÖ)¾‡0FìKr€Lѿľ”ØgÁEÏS|ñn:öEmˆ}Ñ6ľBì ):ŧV'öEmˆ}ñÎ/:ûRé@¦x‰}1šˆ}Fûbtû¢¯æˆ}Ñľ¨±/•ì‹qBìK’©CÈq—Ø—ž2E»;ö…Þľhb_Œ@b_ÊdŠñFì‹X_ľè=b_´)±Ïâ^ò¤Z‡Ø'ÉÂ>õ°/åöÙ‰‚ûÒ3Ôß*a_’hR ûÔÃÂ>µŽ°O£TØgʈ}je`_ÔÆ±O-,ìK9€}ê]a_Ôåþ¢±¯TÐ4½µ£gàØw¾H!ö¥`ŸúØ—r”S*±Oý/ìK2€}Zeû¢}‰}5qг€°/Z‹Ø}@ì‹§ˆ}¥ ÆJ?Ÿ¡ñ )•d²PÂÈì ͉}ÑSľèqbŸfa_ԇحLìÓü"ìÓ×ا™CØý@ì‹ûBOb_Œ-b_ª°/$ûB±/ž"ö¥§€Lñ†ûÒS­Zûâ 'öE‰}ÑľМØ5&öÅ8!öÅLAì‹Ò‰}QCb_¼ÁľŽ}1—ûR`_*鋾ÈC싲‰}Z÷û¢uˆ})%t ÂQÍ0ľ”g¿a¾Húû‘®÷>ØóÿW¤ëù]¤ëý'ˆtý´Ÿ÷µ4þþÕÍ€ÈWO³kBìÿÊ¿P³´j㱉§µí ÕîÇ–§õí ÕooxS¶‹Yo÷OˆÛÃÌ®zðS‚OÛ®|;ËÄCk;hõΰO¿¶ƒVïbú½ý³úšðy~ºÏEã¢a÷…®·.v)Óƒßv+ˆ-õœž+ñ6¡å'2ôížew4¡ú½o÷¬ñv|CÁc»gåòxýGc˜Ï§{ýG_8…ûŒ«y +ãÞîYó¢£Á „Û?˾f~òéeûg ‡…gìê/úê=ëokÌ¡}ûgÍ‹‡ž«‚=5¼ƒŸ1¶ƒ–­(}ÙÿŒ¹´ì‚Å)«{5öÈôúÛµŒîiôÒª+`·vyýæS¨´že{ÖÏ[ƒè]˜J¶2} Ç.f±û¢Pö„õ†§Ö›²u°{§|‰úÎtÓS*üï»4³xýj³¶o½•„ž[×v2³ÛªÐ:÷®{ žZÐÁnàò²,Μ¥t†ð{vÜ6h®Àîòfh Gqžõν¯ˆ‡e>\¦RcÔógAÆHÏ‚6ˆPÌÚžé³W¨]®k»ÖÛ’Ý÷ÞËuï/kNy¶k}NvoRõWÀT*ÈÓ®/)˵b ßÅ¡ýî¸ãÔ–²Û»ÞbúûU¶G¨½,ŽQ•‹:,ìÕ•›:0ž çÝÞ¯áí}¥Öy¿¦>Øp™«¥,ï\ k›9®CTÖøÈ1‡›Ž¿¯íao²¾só.J¶‹ý¬¸¸ìM¹«¿F- 4h7&ŠR\ƒTR©·§\°É[|v—ÜðT[|¥ÐÆ¥Oשá¥/el/{|w&,ÅuxÀÚ¥Øe6ýe©Wówj"Já[•ú¡S}ŠëT1!•w!â:idUhoG…ñ.Ô¶Õsž>]§KrÆö´é¦ÔÙ9ÕMÔpë¿tÐÄ[쫼'¿‚}Âb«b{§.:•VöÔ…<õö©î‚í±´¶}í-ž)z¡A‡$:¼´Öy?žrqä¼­àZL~ogno{{ ï]·Ëâ’Ü4©–î:¤Þ{W‚>wX¹@³Í61ð¾ôvùg ÷#[Êò œ1X‹­l¡0'=–ìÞ8ä™ÝµšÙï:ϵ”üÎ宕ê3îzô¯}wÏ4ŽÈ4Ï—ATãÑöz(Ëi˵’£ï‘åÁècx_ÝÔj@}Ë€eâ«SìVåéyÜN\ìZåuŒù”üq+öÆÇo‘ýóq=ñý˜Ð!úsB‡¨ñìÓSTã9†÷Uç÷c_†í£½BÎjÞ3¸NÚ6‹]}êËrRÏXP¶u>UöX*ØO.ö¾Ñoßès¼­¶v}i†YÔA#Ù¼¦k^fó&i‡žv¹rÏã¶ÚåÊ#‹j7¸Ì3…:p)R¯­ÃKxÞêõª[ƒŠ¾¬=ù]J-¼CÕ¾ÐÏt_Ú¥§ Á›rã)h`,äY¾,²%®k`w+Û[5è°^íråár|œT»\ùXÚU»]yy¶ï£R ƒM)¾2Ò"²ÚÚ´Òò´ÞÃWF¶{Ð=eúÒî¹1Ö:ÜæÖú¸ö”¯WªQ÷úøÛYß©˜ïy ¥øÊÈLîxªúêîÍãó]}¿Ñ‰êC †lµôíBnTf WªcˆÖgúÂÈvÜ!vùÂè.ØÐå¶É´]9—\ B(ŽÍ–±àÍõ—ƒ`ëÜ6Eò_µ•µ÷Þæ¿jw©òwõzy&€ÿÞ¯ZãÒØù/¹òÿ®«‹+íBÓŠ” §u±Ð¼hæx™Û°Ë Ð̤I ]RɽàÎ@Ë&@;²º€¯]í_A€¼àQ7d#49Ђ²ÝîËÎ=ÐL¯tç…C€Ä¿8¸Dü»ì$ ØmW¯ž~Úž2d8;EòŸNìÿâÌñ/âYÿâ03ñï­+Þ\â_œï#þéÀé/ή“þ"¸‡Ó_é"ýEü2ÒŸÝ/ ‚ýé á/Àþ"ÚáOqÆÈ~ìgÁÉ|éOö3faƒýrÇ¿¤ÃÆ?#Ÿ†’úúÐ øgñÖ0<€IKàß½'_A÷5ðNþlrö¢H"ŽôgEùGí¢ˆãFö³‚S67ÝWÿ‰‚úþ9¹dúÝ7wlˆ~V¹ Õúo*)ŽMö‡u _* èw¿³)@?+K Ÿ]9 ´úÝ7C–ý¢=7ù…Ž?+‹T€ß}óó@ð³’}‹‰àwc5ê³bAœ >Rê3Ý=“Ô—Šõå§PýPzSŸ žÃÂDvG¾ÝÀ^ Ÿ]LØXŽ|©"@¾T‘ÂêKc ŸµuE&KÈãÈg¥£~@>k0 Ÿix'âË­~üñY ËÏ´öøR¹>KÁ¹²þ¬Ieõ^à^.ÚQ)/à^jqàÞý.ˆR\úÜÆú³`À^êÀ^j[À»¤—Š饯o¬¾º¾±úš'@z©Y@z©vz÷£¥ø½4;ë¯Y ³þª@/Zœ—: œg ‡9 œwÛ®6¨Î9/uI§Èà€”Z—uÙŒ—ÚŒ—ºp°úl žµÊ‰x©]€x¬ø.WÄù.—Ìê«Ï«¯ |g­‚)ð]š%6ߥá¾Ë)Îw9… 4rì¤Ôx—³8ÞåÊ8Þ¥ñ¼KŠ/ª Î_T}ºK3覻Ô2 ;Ë='нH~n™t—†æ¢ *ÈÑ( v4JYœí¢.d»h²ÚŠh—Ú hÄ8ÚÅ;B´S¹$»\Š“]*…µçP%ØÅKC°ÓÄF®‹V!×EÑÀºT4°.•t×cÖ"ÖE‡ë¬.žq¬»·§æ¯ ºû¹"‡C]Œ B]L „ºÔ¶€ºT .µ/ .ÊÓEÙébv'ÓÅ J¦Ë)Ît¹.Ît¹.Ît)Lï ™.µ'˜ÎºbCÔß fM¬³¡+ß}•+.“r³žÝWTY/®’¢Yïjð³^Ä:Ö½)6;`Pª‘Š„/¤:FÄÔ‘ñ@tñwºPTŒ]ï²´9 ¼øtŒ-¢{óøF.àŒHLjÙAt;æAtKx& ™x@˜îM!l‘é"™î9¬z–ƒ;0Q*T7.ZAu© PÝ uFTE‘êBð [ ºL¬S;aªãT÷f >’K/ ©.çÕ%±ÀºPX§‚Huñ±.ë,eX—SŠÒ@"Ö Wë¢hP]B ¤å¢Q§¢K¬‹&Ö…ÞÂ:É!ÖEéäºØ` ØE}vYN_¹ùHv9ÅÉ.Þ’]ʲKµÙ¥²AvIsݵ½WØ¥êÝT!¥|ª°Ë…³!€v¶OR´K*í’”‡*°z€»¤à.ÞfÂ]ªà. v¸K|B>5æùÌ<|—Z|—j¾ËyB$@hà]R x—rºËrîrŠã]L$Žwi”o¼ÓäIºK€w9å)œ "ð.Õ¿FýùêUà…F໘Éw¹(ç»,x= ÀKÏ€ðrÊS>Þ&^jp@žµM#Ò]œºiß[Ü_„õ¢QÎîd¼,xâbˆìóžC^ÆKB:5P;€ñ’N€¼øNòR òR·òre¨‚”çå<«qêFéà¼Ô8ô’Ú½$w„;¨CHqPJ:€ô¢¹ÀzY°³^N Xaª  ‚õRQ`=-QõrG½œâ¨µ›T@%ÏO@z¹*c|L =ë]à9H/õ墼XÿÈò<co“^ÎQovÓziìô’J+4ÀCŽJ9ËÄJ(J^Z˵ƒôrÊ]ÎFÔSQNzÑÕNzÑ#$½,ÔQ/”&êEåÈz©˜Ù逤íBÔ“[±P/çqÖKµë¥ß®Áø`½(¨—œô² G½Ô.`½Sd½”òPÉ륖yèNÍÂz)ÁQ/é¸Y/Þj²^zÄQ/?2Æñ"‘ôb~#饺ɱ;RXµƒÜÁ/?ÚûgÁ¬åµi°Ø2Ý5â„ã©8ñ.¥ïìü$}4}^°s…°ÈïìáïÞ”L#Õîì¤7X t—Ìo¼Zp”Y„g—–"ù´f“]=ñÎ||<öº(•»HÝ¥U6šµo§Á.¥Ž\|§êï"Ák?ȯãSÂݶzšì" à.• ¸‹,`»J%±]Ø-Év)È(“í$˜hÕs¶KB¨@JQ4È(奰]«/°K) "5•À.Äôu>®‹ Àº7ÞBWÔ®Q}d!ÕE@ÚEPE“êâ!V?ä~VŸL OК¤‹ :%è"á³ò乨d¹ÈC–“Ü•g–¨|õs¼=‚uívœ¼À:!¨c]òCÖÝæþí NuwãÙ RÝm~ÑHp³~åáB=tų hóÀº{Ü<|¬»mE‰Ǻ{V”ª»-Ʋìú/fsª³a‚“b;J²Òí Âú6Hu²³…ÌU »çb(’h/‡áÎ =-s=:,wvø‘ΙNvé8$ÐΆ-Žym¶{n¹Ã‚í,Ç…g£\’³ÑcÖtûsº³¸38øºÛÑâð”ãÝ>Ú PƒÏ-ctx’s6²”Ót÷˜ƒøqÏRÎßß=¾ýà;KáY;è`ñ‰`Ís<Ê)ŽGÏû%Æ ß=ÏÔ‘7ç»§\:8ç|gyÚq/çq@Ê)H6[xür^N1ÂÛË{®sij8´ñìÒ&t( Ïé±°%°¨9#Y P€ñ “ƒc{Îx–2ëHçq;êÐ>ŽäY ŽÞò,¥§#y1û° <« ¡Î1/Z‚˜gyàtSÉ祲z©,€^~ÊAÏòðh_èPÒ{,Ð R–RëlÖ³ßí8’}EØKm ÚK%Ñ3sGÈú¸—³8/%€{IàÞ‘²\)ª ¥WAµy/5'x/ÉïY Nõ÷rj rÊ @|YŽ3Ó‘²\§ìÈ÷XHväË)®ÃÔ¹¾Õß`>Ky ^*Ì÷”0´9ôåh`§Ù ™DYNM¹,§¦œâÔg’áìËem¢¤F”à—Sœ’V ?˳?Íœâäg § A~V:ƒÔ!žrtÊ¥;úY Ïè9ú%Í7ûåßÔA# SPÐ_[ ¿ü”ã_Òø—êüKb§çY²³S’ üKOmüË9ÿ,¥ãluИ_tþe¹ÎNé þå²ÿÒ{6¨ƒ¦ A$ü—jþKÍùç?+é>Näå<ÔAzNê úÿòSÎ9Åù/—åü—ä,ê §uÐÛþKSöæ¿4ßÿÒÜ þ;R|y‚EÚlj¼œâø”F2ø/t ÿÅS´åEÉQç¿X28ÿEíÈÑ—ÀœÇ0—°vÔ ò,,Œø‰&Ú§ÿ€©t`~Ê0•u×cy@LZ‚sJÇÂ(äŽqö0ép‡t˜„Ñ @Àø°cö ¦~Æ›çh ÂÉß‹=C)}R+œh&­‚¹6 #¥“žå‹ A[nìyý»àÕ4äáЈÏ6lfÄô2>$>‹ÈÌG¾wðó°ãY¸Çr _i¼ª‹ÈgŸwÚ™ÞÙêçiÊ+“¾çd¾2é,Mæ{ß}º¿úÊ •²#È̦“sLõâÙYBßûŸ§ïª:¬yV Û9ó™˜ãô]µ“<òÕû°äY1 Þ³(“À\ðžqØ«vêÓ¼êC^›^õw˜Ë²çœd+œvòª9mÃ)ÓY¯îÂ~êYjP;Q¯1`ºPoD  ÞX ÏLš<*Ô³k%r@½®S–Žz}ð„'QÏ\š¨×yŠPoTl&õGµêÙ.p ¨eõB+¢žy¸~š–§ã€IQC¢^ç+@=›´NÔ{_% .Q/å¡<²+ÔS¡ž-‚NÔ3?²Ãœ÷‡çï,Ï<à™ž°õõ¤ƒP¯MõÛ¨§¾굇_B¢^ç%?B½H!ê™CÇaÒ{ßÅè+6qNŸ¨×yIƒP/=E¸£*Ôk¼~D¨—R6'¥’€z¡7QÏüNÔk¼º€¨÷ÔÅ( d½Æ+TÄz)¬×y‰ŽX/Ú‹¬×ºb©@‡:}ÃY¯6lY€õB'²^¿G¬×xY…X¯qòë™#b­PƒÈRŠ1@Ök¼¸C¬×º<<Ázöõ€d°^’ã:DIÎIÒ‘¬gFaRëÕõaß³F¥‘ ¬Ä#Öãí‡b½Ê‹ÍÅzW£ˆõÒS`={5ë¥<®ƒÆY¯ñº:±^å{b=Û¤ÆS`½”¬WåÎ+Ö ®¤j ²^ô/YϾó0êõb¬‘õ*ƒ§õªœPë‘㨃ޠÄzä/p’ùá)°^åU‚b½d½T:u˜ŠýN²mÐ8)Ú‹¬WåŸí¬¬LÖ«¼Q¬Wy±¡XÏŽ¶ÀFNŠÞ#ëEÉzÑd½Ð|¯öÖc“õB²X/Ü$Ÿj#ëi‡B¬'’ëE²^¤“Ä«b=Ñ©XOÔFÖ‹>ëio¬o,Y/Æ6X/h¬—ž!ë]ؾë=‹Q„Vè€6&ëÅ( 륃õ4–‚õXŸ`=j¬Ž™[.°ž4ëYTœ#úJ.™¬Ç~멾b=é¬÷éº3ŒXOm.ÖÓ#ÖÓø#ë­è+1Åz¡§X/\5ÁzšéƒõBuF£’,Ö9‘õ¢uÄzj ±žÊëq¯&X/:Éz]±`Àz©$²žF‰XO’ÅzâU±žô$ëq&Í«-ZrD~¯Û "3E¬FŽ#bõ™)žJ«¿yì/D¬þR&±¡OÑÿ3¥¤0ÓíýÞþÌa¦™E!-‰RJeäà×L8DyZÅ”$ªïµ]n9$dQHK¢”’EýN'œ¢ÎŽÉ]õo£]í^¸uÆÑ¾,ÖëË–³}‰Tœþiµ<sÛ3|'ÎÞ¯gû£HÜ!µ¿´ußG¨á¯ÍÛ×ÑÔóHl)T¶‰i9P6ä¤<t䢤({KÊa²))òPÒr’R˜ì-)ɦ¤ÈCIGÀmHJA²·¤"›’"%á¶ñ~¦Ù&é£Íqy é…Ñ®cßÏò_/ŠöŸNèßN _æïß~.>2ýù—àŸDÑ®sÛþÿÓFÑþ×7rÿõo¢ýÂ6"fÛ¿þÛ7iŒ¢]úŸDÑ®öq­±Y3Ôþ..-WÖ³/˰ xLØweØ’+#»Ô‘Ö°½ª;‰)úÙ¾_~ÇLS”A ºÖÝ¼Ý gxlŠÙTøÄ®`çñ}ktÞx ¹}§sÁu£]{r4n®þûñMÛ+HñM €gÊ^7Ú·¢"¥îucÝ÷8xJÛëÆ¶hà¥÷º±Ák×ðȃïzêFŠë`Å;R–ßU`!ͶV;¸•M¹£ïî(ùò]múzÝâoXÔ¾6|ïu£]ê‚ ®Â0ïdq"Šw»Û^6Ú†2šâîµO±þÚ=ö²qØv…7Å=x[€ív†…ùÝKºö¸ ÄÒá; Y”éΘ oЇ3V$jã'…ß‹ÙÛÿŒª?G垦xÌh‡Ç°‚>÷ÖnõXÆy¦Çc¾iŒhÏòxÌï<Î_+—ÇcVdÌV\Û †œÌÅË*ÏôÏ C‚½ï"³^ȱ׌mÙ‡ %5ÇÜh²•¾w×Å2[ï­xjîý´uó6µmS@ìl'ÎmS°Ïë¥ÑWoÇldÈsûGù¡“×ûê ¦´Ú«šv¯ Þ ZM†A’ëhË8Ó©’‡ß÷fïZÉ )û+ÛÖ«º¿BƒwqÉ’]ƒ}IK~_Þò0ÒS{_Ž­S¯ØÚáú‡Õ¯ñýiÏÞ\¶CŽ®O§Û[+O™ýý[ŽŽG?Ä?öB›ØgxOt4@vû ?^•‰gÊàdíÛj½Ô½|3}s®(ð~*žÚ ìÉíRö}goY]¥Ï}ÝÚ²nö‘/ߺ]ã¼\í)¯{‚ïø¹|Zã7 ÛWø>*SËðqÇ5`¯µ{'ÝøR÷Ú:‰•©ÝïªêÆ]õÛbVëu>ìÖnÝ®gÙn×8›NûžHOX>ì:î•?½mÒ ·­ÀžÜ1Rm}½ß6ú»÷÷C¼§}èÞ¯ZõiíÆüÒß/‰4õÜ;U»Nôeïmkð6 —xÝ.qÞ35#…õîøi…Qb—8¯3Ï3ó³ï•¼•=~"*¼=ç;×ïg*ôŸH°O<‹ÏÝ^ˆ{bÄ»c‹ÿv OlhXûbÖ[<Ë *€núËÁ²ÉyÎ:½É(AÏ®çA9’ÞÅØ4$½yó ^µèñnËéU[¹úz¤WíÚÅ‚<Ãïu|›Ý¿C ½tS6HogÅ’ ¤gn#‘ž™6ðÙéEÜg’žÍ¢X}ƒôlóž<昴ÍòÈã¤g†ï ÉNzÏddz’^±PÕþ=陓ÍBéŽI–l Ò3c39ÎI¯_ ç¤gFã°å¤÷6Y¨gnNÐ ¨×Ÿ‹+ ^ë·ä8)õ†X‰$=[bAÒvéÙÛž¡(–™ =»ÊŠè‡»weyöí(•‹ °ž]7Ž¢D„zº0@¨×´|$ê½kæqÔ³;I¨§ëy„zv».P ¨§PÿB=]Æ"Ôë4·õt‘Q/.<"êÙµÉÞx$½‡AEzï\“ô*rôl ˆ¢IzMÐ[ç©Äy÷C¹à<»6]iœ÷.¨*>ÅÎy65à}"çí:óæÂ®1oÒ•K˜·m¦¿Dyï¬Uø¦ò¸6䥱3^Z·‰ñô‘ã¥é|C^·ï¼yZòbbä½+INq€¼½ØÄsÈÛÕÇKLÈÓÂ÷~GNÂë¼E„·aÃÕ!àG8àm©€á xìoDGõmð \ÐQeŒÞ»Ê]˜lx³Ã6àu›815ð¦&ªA:Ç2Ï"¼ãÍ £Áô¼Fg^·ûÙQÃMxfíŰ$á™§rP‡¢²,ê(&Þ;{úOà½E)ï,(*S€w‹!P‰w{ñs<’XàÑDu¢MÚØ8Ølg+ù‚Rw“ÑèIw°¾€ÜPù®Hw©& ;û`@èî.¼×‰t—tÞÝïw´á)Wá~x‡ÏBÝ“-’nV”nˆg×ÖS®#ž¹ßÝ4§<‹AÛRСr&#åݵp‘гíyôì“æ{=“Ì'½ÛøÑWB0uÒR¤gw¥ùRî(½0Õgí/ìÖ‚õº}ÊÝG¬gWD3eù@ëXõvN¤€”WÉzöîvâf½n,pÜf½Ô1`½nÞ’©/Ú¬×-¢°ÿܨgí‚VpÔë×Bœe^° ½nÇj!¤g ãÝ ØÛCuƒ‘ÙÞÛ†g%kŸ …oØÛÝÎuÚÛM¶€ˆN{¦£oHnÚÛeƒó7í™g‡o-‚ö¶èF§½n~ž#§½·äJ-öÞ”‹+ù bXövg!ÅYé~†ä8íY÷aî´·%Ë6íå§êÖ!jܳÆëã¸÷>Ãëêˆ{ö" $ǽÝÌã¸gk»Š”{{*÷n»ílrFç½Û¶Ž½,ç½=”À°>›JÐF|ÝÎZ7ü†¯xì4ê@c ‰/ QßmëGÈqâ³ÚÜà»M|y*ñÙKƒqӠë'XÄgËZÿö‘øRA|iŒnâ3)ÅN|o>žÛ&òÙûÆ3Сñ9™/—íÐw¿Ì~pè{ŸªØq$ôYPë€ yBß=±,û;Ñ´Á}Ît‰ûl™M« |ÜÎ#÷- [[,|æ:ƒ…ïí2ÄŸ …¯Ýz ¾ÎÙ_>£<” ß;k_™û’g˜,|:T Ÿ ‹ÁÂwñîBr_©UtæÌdfæ…ïý.7ä…Ïyœûl!ŒUp_»o1&¸¯ß²:4µª ¹oqƒ“Üg.²XánîkfhEç¾d]$÷Ýì=rŸ¹ÕÂJî«Mlî³ó%Hqð³µ.6Õ~æj ÂøµÁO˜ÀÏüÒhÐÛØ´Û4þx%‰<" @B$¿þd“ü.ø³ñÉ&ù]0°g¿'» B›ÚIð{ÿ?#‡ü>EÜ´ºç%’¨5J„Wnzjæ&êE)[G½þš'êõñ£¸‡UŸ‡‰z1c„RilìI/†ï.Òëó”Ú^{Ñnv~è,–])3ÏûøZ2åÉ}›íì$ïÕü¦ásÍŠ{è×;ZK?¸"Nn÷K[šžGG»]ʇÑîæi‘ÉîÐòm²›òM4Ùù* “Ý:tË0É®y¨ìÆ^ú]Rѱò5ÙÝ—m#ÿ€ìN’ ì!¤Á‘Ë „¢M4»sÿIлöérv´í$ÕÍeKÎl?\*ŸÝæ»7°\–D„v›w¸ý³ îÞ,ÉnÓ_(A pSF¨ÃÎèþªy§#XÍ{¬eì2=•׿ ®–«yÏ’,d»M¦Ý¦ ›nbŸÅ uÏIsËy°qc±ìÂ4£[ÎÓé°å¼w5擲œgZ$Ó5 PÉy¾¯\L‡¡ R ƒ-'¡--7—¸^rTÖÖÁš ‚õ¼Ç¢ ,7}’/=Ö~ô<ÜO¥XzÞ¸Ld´ÜÄ7‘4EE¯,Ie¹é{ìi¹YfŽTôifRô.ù† ìæÔ!cIz»íAe{jf—åæÅàd;ly¹?–á¦-}l¸  ÌGQïòKF´›8´gJˆzã²È¢Þå,ËMÛþØtLÉš©êíÚü”éæÁK£ÅvͤQ¦›Vo¥ë½«œ”>ZnVsÈv½Zn€.ÂpózÄzê€l ¥ê5f›²ë¤¤wùŒL6›pëídÇ“ÙlÞŠM`›ÍÓÒ¸m6­üHÒÛƒm6m F£ÍÇçBOu@åRÒ³ ÐF=Ç×h³,m´yUJm–]$Ù®¬dl´é–Íæ¾K–®w"&ßáCxß}dNÛÎËló ¥­6K•ÕfÙäÊlÓJUYnšÌ¾¦›5_S×{¿Éç×tßGâ­7­¢Ûzó8Êž3»°nç¡ý#ŽÑY 8t”§wÖ²àœ‹{JÉz§‚YÖÃ÷+ë o*SÖÃ÷³Þ›W>„²ž´¶”õp\}²$MN«xÔõ€ ñºì(]ÏËÒõàÍÍ*u½ ›ý¯ çsXf +T˜«“˜BÛu4maïy„])ì5u“Â^{ö`ZÉ<ì€Í{%ìaT%Òòäm1ÒõšvI]Ï&Í6â´dŸ²‚s†¤¬·/s- k(%ëÙÀ@²öj݆³ÙDHÕCÅ[‡¼&RÔk}–¨ë’Îx7v½ÜÔSÔƒµ« Q“á«éÁf™z- ×ezXéÀÔô`¨ \¤¦g‹izmIÓ+Ùœš^/‡zØËˆ4=¼^‚:jz5ÇCÓÃ<äë/M+û'æ¡6Nã#M W§¼(„Ò—½Mgæôð]ùzÛ¼,ÅQ ò”± çâU¸ÖólA ι+å¼?%çÁ’õ+ç ]G`9on å¼Sø–ój0%ça ui„ºt™¯å<|Fç_‰³-ä ¹å#ç9ˆÃŸùëçhĹÔ#ß~‹Ó†»š‡Txó~±Òû’ø°d‰ï’˜ÚEÑ$¾ºÔćó[’ˆoLïˆ|és ©Bñ$„|ÇeµJ6œï„º‘ïÙÆO6œØÌί–‡XrÌC-çA™@èƒTB†’ §5BßD«(Âô?õwBÖ{b!© ô5á<>ȇà<Ò“—Ön‹S¹êa€>:Þ³äk"â{6B·ˆol3Iâk\âÒzL4þÄ&í,T®z‡fž€¯¹ó%ðÍ[Ö>2âÜ7AŒl8—5Dq–?’=õ6ë>Å1ð!2#óœO÷Ѐñºî/Ò ò´¿¢€¯Ls嫇qù_ÙÃÒŒ3vyÕd†j‡Y_í©í«g«Rßñ5å ïCªòiÊiã›r^ŠieèóÝз›™ÊWO>æ¾KQËÄ};ÆB)Ù‡‡Ÿcß<9;eÈ)†‚>“ ¯x9í8Aî´ÑTîŸí8ß·ýêÐ×|; }åñGA7–øÒ”³ÌeÊ Zc M9Ë:UÔW~k¢¾S±?¢¾ýö‘¨O»I[szknè«eEÐlðÏÆ|åò)cÎw…å &cNo9l̉…Œyäk¨0Nå¯'F)è³R™Ð÷ÈÙ¢Œ92æ„_M.Õ…e“ËÞfÄ“ÓÛõ“×¾TãkÌY)sBTgö–R™À.À‹ˆ'è»eH˜Ð·¶¯¬×÷Š„>DøÈz1!…Š‚¾Íîu„¾cÙMÆx]º®×76æôRÐg³kAö‹r÷ è»ëo[>±NC能w˜2ç,s5™sFº6èÛg· On1‚¾±ßöö“-¤íÿdÍy—{­9÷Ó6 ´æ„oÑ*°Ï¾¡‰}¸-„2—¬9ÏÇöŸÄ¾»üòhÍY´Ó¸o}¬9{MìÁ²Š+kβõøÝÛOàGƒï2åœ_êóB#ìÃÅ%^™r^Š8aìóËmSÎ2s5öÉr«°Ï§*Ä>Ôõ“)'úÊ<Ä>œ³t×½˜ÈOW÷ÂHt+u/óú`.@²@|¦›žrÕ#7Ù"ÝäWDòkÆÑ$¿UþJ¦œeN)3ÈÇŒFnº±Èè7Y ö¾]໡JÑySìw+ò‡Ù¯L0Å~‡ÜxÌ~‡±žÕþa?LõCÞzìƒC±ß;/¶ ÉôûÈÚb¼X~:ã’ßÈxîA*aOÆ]Ø{ˆgIycéœLÂötrLÌ;Y. óŽý2ø‘ ­¢<ìù™'åÁ K‘fªÍHyÏQ6“Iy°Þ£\@Êþ‚øMMÆOÂ^ÛO’òÀ_O=xÒŸŠ”w¯íc±¹vÛ~ó&vd«=O„ÎGlÊ[ØËti¯y^‹òPìúh{ð«²%%µýN‚^?&èeDÉšóâÛ±}@¯ƒ'èÅÞÕXò@è< [;W†!ÊèÅW[€väê¶•‹Ý™~Éuž ÷¾ Ι» cq,±.íÝpç¼»´K¢„¼-„|’KÎ+w b^;Yæá-; óºÏãø¡1܆&æÅ¹Ìļ;E³va”Û`b†"Ä“†¢‘óâóÆ3†ä¼Þžä¼·=CF`'û“}€[Wùêµc:qzýQöº¿P‚^'{C¶…=˜ZHz±â¬!éíðßëÒ^ÔÅmh’^û¬Ë_/6O$»èƼ‚²ô'é¡ ¾ïtØ«o›¤=|)ÆÇa¯\Lzk:…=¸æO¤‡+Þä8G‡7•ä´‡§ 8-é´×F"H—ªÉ,“}À Y0A ¯ç覛8\éHzˆ…ÅÕN{­&’®Š{zT–Ø ð°‡¨7¶árJøÈÑ*4a—Ý åÒi.³Á.“;>N{¨‰J=aùŽOXÀ©WN{a˜’ œተolŽao7H°W3G~{ïK ’é÷Vc!ß=\)Á’ö–Ï {åpcÚóÞß¾{v²ïž÷EöÝ{|Ä"Ü«™#Ü»íY Ü›ÏO¸×Ö)ùîÁÏ‘åÐwO{ ávAü›¸çhÜÃI; )ÙÏ@ûî¹&ûî•C‹poŽ®BÜ»— D‰{b[ ÷À0Üq‘÷P;]nÈ{بË@4xïÑQy¯\{Ä{^÷í»wU€õA£%Þæ\‘¯æ¤y¯v£â=èE‘"eñÞ£˜XtÞ+מùpþq©ž¦€Ïo§¯öå>¿Utß«Ýsê|S–">©ø¦Nâ |õ |°—c¹ìß)ß´u­€záøªO>¯f¾jsºïÕû"©–/ó½Ï…ÁNÄ|¦ùüe2óM™ˆÛ}oJ*°ÔçÕØÌ÷ÜŽñB^ª 1_õJÌ'·1¹ïµ¿Ù‡%Û%3ŸWu3_ÍQ1_½‰b>¯ÆVû¼‡(æÓ×ÁÌ×õr_Tî„b>¯‘f¾z7Ó}v$<ê}kwЏÕ+˜¯Ö-»ïyŒÅ|þ[ï«USz_B=å‚ÈÚí¾Ç[‹°}A{·uNLz—½SÊ?ç ¼óÿ.SýÌ™~ñ«¿aapÞ~T¹•²h€ù§±èÊtb¨‹/Àb2´¢œÒŠbZ¥„^.Ñy¿´­(§´¢˜VE)¡õßËû|' Ùí]#­¢ÿÎÓÑ¥çt|êëp<_¥þ”áþ·û3À“èr$×ßÏš+ÔÓÕfÍ?~9Iîfz.—…0‡×ÓËbʧ,çrY-—ÊŠ{iæje)¥—U¹TVÏå²®‘¡i]T&|JRTy\ÎÜ"ªF+ˆ)Ÿ’œËEµ\~§âøøle)¥—U¹TVÏõwç~ OöýÇø9Zõý'ѪçýS¾_G«þ£l?G«þ‹âο—íú£l¿ˆVýwÇü¼Ðýb)üǯ^˜Ÿ—Ç_¿/¿+éO>ìïƒÃCûŸxzqÑáû䎸n{æ“ûßßN¿Ì·=ÿö¿ýñ:Ïóßþÿñ?ã°ù:ÿíÿôÿþ¿þG(1ëú·è_¦9dö…Ó²w/Û‹öcöÙïöˆ!³ñ¯ÿå)žõÙþÅàÓóq˜ì1ã‰õ¿ÿ2b62µˆÙ·«´ÿð¿~1û[#f¯ãt—žßGÌ~ÓþÓÿú÷_¤9böþç³/E}w'±¬¼ œïþsÄe=ø]p€}÷ qÍ]Èiwܧ€eGg‘“ÖûGÜ·[kx6¿ þΗ‡qDnÿEßw]„gÖ ˆyþ.ÇÁ‹êß-Ü\m•Š×»9úíå¦wýÃSñ ŒI,£ *«þñ2ÖqÚÁ£÷8ÞŠ/ÜuyÐþñ–sã3®«×†_m zòìq‰Òñì¼ìé Ïì·Ü—ÇDpì|^ì:… {"ÜîÙu½8ñ~~øàÄ™·8•þiÛzuéòÆç‰ðŽb?'˜áÄ1@ìá pœ¨üb蔹á÷˜QOÂA_;~µ“åãÐøÝ SÁÍù¡7¾R 8¼›Ú>Ò5zâú­ëB¹Ü_F|ëøèÀÒ(ò„ÓÃñ¦ÈðÁ–÷w‘=Â"$Ê…ÑþKb.G[ƒ‰ãTTµä&‰Ðɱ¨ ÀxæÒðîF~àê#ü‰ˆz?A°!$ ýïrpàø((!öî…šÃmàðü™¨Y¾Œ WÊÝ(fg¨ ÜA¸Îh/}‡¼ë]áÞ”ƒqQÃí`ì½½èÁvDë¨Ñàp|°öÜ{C>>z]ÚP3òD%Œ¥OüJÆEñg‡)ïƒÚ1q²œ;fô±ÊÉxšáÉåêXvxÂut×Óû=Òkéõ,8=åŽå8ô¸prŽô´ÇèCV(¢1ƼÅ}Fy?Úw˜õ¼íBs<ÍS÷š03ˆ<1ž¸möùâ¥(w³ã¹éàù]A‹ÉîXúïʇIuÀddB´ÉËÂ2%#Aˆí—fÒØ@Ì#óð¦Ì÷ÆÃÌ”3ËE--M)Že‹¾sD¤Èx7y×צðïê’¼­Ç²nA©^qø|ÀÔ‰W4 õ{]Z¨á2„‹=äu[‰^Î.fÆ!ûõJ¡ap}O{å!ÀሩM£k÷¸xY F¿íù®Èk*\þ,µ[~Ñ8åÁ:ò#«‚ªâ;¯<ŒŸÐ6Œ&˜KÉ6xÃÚz Öý£à?¿ÅÊ]žß°ý:úì½SëU¡ÈòðXw9<³/ÂUÌÈ£#$úX±Îœœšø8o±Îè ç}ä<Ê'ùÄõÌ19sÕƒ[l¬Ý=¸¼¬*[ƒËï\ÞÙÜn|æk‘ën¹?¯nŽ¥Ûø3]Íb¦¥!#ôïXºÝ+Ü>˜K·"àÛK·òñuÎ¥[±áñuÎ¥{æŸ+Ömœ.æ/pÅ1jvøÜ|~Þ ¸^W®9Ó°’Ýg¾¸ñ£øÂpv¦ˆ‹; bÙÞd›É#Š˜Ó¹†ÄÌœQ^‘X!<2+[M8kÿ¼‚¸øØ³Óù›¸¥¹ âŸm9ˆ¿|õcÀ‡)Wí‘KÑØÒ¡ží@¼öϪ=¶¸£¹× “±jë! |•cÕVÌ‘¯²Ví+«zf®Ú dâãȽř¿JCŸšlN\ãICÁ¦J\OŸÌ3Ž\·µ„ hß±nktÈX·µ \=¸F{ÉPµÞÂor,ÜИöHÉ+”£¢l0¾ÊX¸á8·g!ëε[`@öʵ›ñTî¾ö¶L Ü |­¶e¸8ÖîÊsî¹v˯wàêÖyö¡À̓¹vsqø.ÇÚ-þAg·â31ðY޵[¯ØÀw9o®æ·Çâ½3(æÀíÀ¹xo9õÇ‘·ŒÇf-³ÄÍñÕXñ÷¹–î{Ì®|9׎”鎰ތ´ ‹8í„gæÂýðþŸôà-Š#å¿B»Àï‰À8 üàMêÌ}ð9ˆ„¹q{b½!÷á:ö$8b_ܬ~wìÏbÀCaß@”íÁ tyPù÷ ðÆ™”—Ü÷¦PE÷ <ìØˆûÆJ %ôõðÙ úfCr¡KC,‚¾‰q| V2YŒ F¿qJnèƒÁg¼q†>ëÆt5ôáÐ,pXÐoËX }xÉôA=ŒÁ4ôÁ4'~eè‹p‘"è‹×>ÀKÐ{Ø@bA”¹ä7Q¬Ï²Q–‚x3L}»âæ™ú ¬'+Šú`(SÔ“8=0õáÀ,Ô&Söõñ 5øbÇaò{û,Ùä=%ºÉ¯òˆüPΕ)$?\’š)òƒÎö&?Ø4„Öoòƒ2H>#ù¡®´ÂùíŽñ.òƒ½BîE~!¯ÆÞP䇃ýT‹E~PxšD~­’òŒù ßR&òƒ•›‘ò|ÉÊd2Éf»)½‰ü R%‰üp’“­ÈF5Ù‘NŠ—"?5ðW$?|[RRúAOSì‡Úsxû-ÿÁŸ§˜á|Šd‚?ˆŒ[‡?è™©Æ þPev]ð‡N¤ *øC1Iî‚¿¸ª7óþ y¦’Køƒ›²²à²Þþ"´’ár/¾&ü¡œ,XôßâeÑäót@ýí¶ýU·„˜*¼ržøç×ßø·;¸ŠðC˜cø=˜qTÈUˆøyt¯oò_+„X\X⑳d" êJ”†áBæ!â-æÍÃDÀ@! žç£”±¨rˆ€hý,ˆ€õª‰«ë‚ÀV !Ï\Q1½hd”X-bÍ] Ä.E˜Ž­D (°FYˆDV ‚­‚`ËC¬Ñ Æ‘:w’`+‡$ˆöЇ$XS$XM ¢ª4  BÐO  îî*ÄÆ8El‘ B¤{IaÐó°@$»øe‘ ¾×i#!l¿" ÂØ6"¡ v÷ik!„mz¤PÎû¹â 7é¿FÁmòTÛ(ˆ<¹T ὓýQ±3i°e! ¶bHƒÕ-Ñ ºžçG¢ÁÊ#Dד!…ƒñщzgbŒ M2…ª ?‘D7Ù€“­hŽðð¤N¸¾[ŠÄÅ4DG"–ü 2"6ë_UÐ{°D S¤Gl‹ E‡Ú0š±ñ,:„tyD‡°›ËšE‡°ÅŽ/:ÔŽ¬Ñ!ç@Ñá[àúÒ¡x¨èP»ðF‡"?Óáä “E‡¿¢CmÕM‡~2E‡S7¿êöRÓ¡ÉAtèQ/:\<[(:|ëJ‹JÓ¡·á¢Ãö«F‡¹oÖæÓt¸t@tX-4zGO:¬&ªë¢Ãâ Ó¡aµèPÛQÓ¡‰Ètˆk¶²rÑ!¾~™GthF2ËM‡X@ÐD‡ÞeªÍ¢CWn:Ôì):\ E‡š©E‡•":\Š}e:¼©B™µ ºÓ!®ObúIêi™_E‡zè¦ÃG±ÑM‡æÓ¡(ŠÝfÑá›’ÛQÒ¡Üt8o›èÐÅš? ¾@Ç?ÓáäF³èPŒd:,6¾åäî½èе›Mtèö˜_˜K:tU¦ÃÊ":ôÉGÑáæû±D‡—üïD‡îºéPSÇtXô*:44™ÝOÓaå1>¾”tø6aM‡:ï2âþ Z‹+…tèÁ0º£¦COAÑ¡ÍL‡Å‹¢C7PtØtذŽtXCH:ô·ÎtØ*'¢ç„LÒa-q¢ÃZƒE‡Õ+Ña•,:¬':¬¹,:lyH‡õò‰k‰Öé°¦è°C:¬5EtX¯±è°NßD‡uš$:¬ãÑ¡?½¦ÃzE‡õDE‡µê‰kˆ[ÉI‡õBŠýU5ºÉ¦C7Çtè¹l:ôѨèÐo±éÐ}0ö”ŵüøI0ôä1ú˜Åtèéd:¬&‹[Òau]tØ~E:ô<0V¿‚ýÒ˜½‚˜ýL‡ž·¦CŽL‡~V¦ÃcÑ¡ßÓa==Ñ¡WwÓa«‹tXÃ.:ôÞJtè×Ètèm¥é°~$:Ä Ü q¤Ã–B:¬Á ¶Òa è°z.:ôçÛtØRH‡õ8E‡~œœÛD÷Ÿá¼ètRD¸ß©qJ.„Ô›ì&½÷;ÇÓµ^ˆË¥Ã‚Åz!ÜÅÃd%ôÂ5ÂÜzáš´E±^qÀt¹ƒò• s…ëŠá¤‡E)†ØÄ7 „>øã'¹0 KIƒÁ“Òj”4ØRHƒV1íDƒ‘ÒÕÂø·ëo¢`%V¶°K FJ(—"Á–BXŒ# ز$ ÎÑíC#Kj‡dÁV7Y°å! ¶²à@œà´% FJ2Y°òˆc8cA ÖC Fž´% –®+l¿" òÙ ëÙ [!Á¸r{ÁøUÅǼ–Yò´W^I-%9pàZZŒ&ÆäL|K 0Ø:ÆÒ*Ž){ [1Iñ¤½)°¥Çš =• y-žHÕ>B`$¤5!°·/!0ò¤É !0ØÂz·Å€=%°œ ØÊ%Ö¢!ìÅ$¶A'¶Ö$¶±IŒró žØCŒUŽò["`•KlÅ{J`ü(%``Ï“Ø8 °çIìy’Û ¶yrê©äOH€mJ#…·´'Öê.Œ/Àê&¢=O`ä9:Ä¿º>ØëJìíIŒ’y¥C`{ ÀVy`}l€=%0RNþ·ãú¤$öª{J`/8°uŠØ†‚ت"úƒ)þëY’ÿZ7É=%ù¯5‡ü×ËIþkOüךLþkÏ!ù¯LþkYÈ­*òß@PÊè@tš¤´Ä¿z¾I­O¤¿OÊÊÜ= ýµçBúë)I-…ôWuþjk#øë?Jøk•þzž„¿È³ui°—ð×&ᯜ«\Ï“ð×Þ!Â_«ŠðךCøk•Ë㵕“ð×ó$üõ”„¿OÊâ"¿ö´þZ'õ#Á_u]ð L­0Ù¯%$úU¹D¿žèWc#ôëU'úõ<‰~½œD¿ž’è×Ê!úµrˆ~1ùc¯-ôkåýz9‰~ÕO’_/ø%¿zr"¿øˆ'Ÿ‘üzÍI~Oçîº`+–ä×ÚBò«×Wä×S’üz9I~­…$¿H)ñ%ùE9G×{ž ¿ž%¿}=%ɯu”äíàì’Ä¿6^ ~½”¿Ö)‚_=r_ r_k¹¯,Çg½ÿB´îbÀ- ?®‚ŒZX&£ïŽ8Î5ËdtWÁ;}lFaïŠA‰ç×ftååO‰€íÏ Ç# P8x!f1àÍðØÅ€oûcCR xÓ–¿P13àC«ØÂÀçúÙjtË›ŸŠµ7* „rñÑ·!Ú>˜­1’¢¬ "†n¼5e4º1¨ª5ÁM·$—Ñè`Ôk‚Ûž¶Æ–h9Ý÷( ÚÅÓª`•+UÁZGj€TQÓ‘lHUpÛ>£èõÞ1° l- ¢ØÐß- â*½c`û•$AÄâNÄ“$˜U[ÄOöô ¤èö[ĸ¾[Œ€BãWI©ÒÝ)ëënžõ@Ôu~¬EñtWçÀjõÀì”Å@\pCCUŠžWQõø8 ¢Q0)Vó$âq'e¥ˆß$™Q DEɱ’Ù6逘š K&À¥‹t¤¢ƒ;™0uÀmŸÜûIô|°ˆùNNÒ1t4Ô¤X¿’X –ˆÑkØC5­Ž€õ Zôì´ X#.°jJC% ?¸>¢õˆ$V5’õ[ÄØmï@Oq+€­*€Õ#)€U0ÀškâI¬‡ræÑÝ7«K«-ëU’èy'ý¯¦Œô¿zK¤ÿÅÆ.Yú_ „ô¿sé[N”¿É•ê_û Õ¿ªHê_Í©vE°úçEÅê_Õ?<&Æý¤úײPýsó$þÕc’ø‡1W¼­´&Úuw»´?OVI5œ’þª½’þêGTþк«“_/†Ê_ý(…¿š"þjVIøÃ$' ü|¢fðãi?ƒ˜üèd\àdz(s_•*î«qŸÎ'‹û–î2÷éì±ÀO›¿Åè¬Å}:Œ2÷¹*s_U%îÓé³¹Ïdžæ>º÷-–7÷ùXÓÜç_™ûÜs_Ò¸¡&iùA_ýDÐëÊù–nõ5óét·˜Ïã)æÃf1Ë󩦯|· ;Í|ù¼óñl¯ O#cèÓÑwAŸ¦ ÝA°§úêW‚¾ªJЧ³ù‚>÷ÊÐW0&èÓXôiÒôiH‹ú4“H}: /êÓaxQ_5OÔçnšú\‘©Ï¿2õq ôI(èsŸ }š}?C—€b¾Õ¤>ÿ%Ús3{îq‡½l†i¯ˆK´§Ó`ÓžGß´çþ™öª*ážûgÜsÿŒ{•G¸§óõ_ènÒ^<Ñ.íIÈÖ¸¤.pŒTwàr¶ ÍB[Ï=¶Ð?š­':Œ&SÏ»­à/ǹhŸ¦ž×ÅM=ÏÅ›ˆlêyâÈ;CÂ8 mÂ*Ì,U¦žˆ¸’œÀܼƒG¦žƒ2:Õ½)GÚV˜ÁïŒM=˜âþøÞS,(¬ÃMαpÛÔóÙiõ!SÏhh#¬‹k¤#Å`p‘Ã' îÌ 80Ö=“ŽˆÆ:DÀ½>¦ž(çè¾€x»}|QùøpBëó˜ëâ¶Û®ð¸F7fÑWTÇ"b´ƒ/èþ‰ã€9F»¸£=òíââßµgÜ þyB;<’çCwÏýLwçõ³µ'ö‹ócí‰<LJîΓ›5ÓÝyÉTKt‡{¶æÇð¼dª(ºCJz­‹îΛö±¦;„Ñœ]æ{Sʶ3¯§$àµ^+™€wÞ2‚àEÈε'öÊù&áÏ&ÛN"ÞùÈQˆ‡¥½eù*<µ­=/…ˆåÏÅp­¢¼ó¹eÛIÊCdþl²()Ç'Ìù<’ßHy§¯NåSWŠòι³ëÄ<$|­=OXH¤‰(1ÏK1/—~¬=â4}¡„y¨|5©/úp}PU¥AœP?Ú?¨wN¾ÇF½×TÿÈzˆxþµö¬&‹õÐÀóÃzçR ±Þ¹˜†°‡<çÇÚó|¹=;*Ø«rö@P[×úzÂòäPöêýùX{ÖíKW#‰öκ ‚´‡’µ'¼>ÖžHÉ¡í!@¸jÓA/yïÚtÿx?:þ>xïÚ‡“OÞC÷ÇÍaròò(yðž?‡æ½–BÞ»|O½€ïÚ†ââø"¤îÇÚ3ú˸ÂI|޽f䫿ù.\¸ññÄ`LÝ#̇º¶µ'.¸çåLd¾BB²¤µ  ¯ÆKЇ‚s¶ú"¦ng¾}É’“ÆžŽÂRÿKcÏ ±…²{VÇeìyíºÂMÆžHÙºÜ×Ë¡±'RrQ–±'~u}Œ=‘òÁ¾7åTœ{"%ß={¶{^û#„£±ç»¦±gºŒ=keìyíÜÏÚØ³~|Œ=¯± âhìY•ËØå|<k¼dëYc*[Ï–B[Ϛʲõ¬ '[OÜ×0úõÖÐÖÓ)¶õl)´õÄú“\"[Ïw‡Eï2Ùz^#Ïdêé‘°©']niê鵩煳\šzº 6õl¿¢©'žÃìè÷–c厦ž(ùú˜zb…Ê#2õį¶# ò0ô M=«…aê‰÷aÏŸÐÔÓǦž($­eêÙ ¡©'ªNñQ¦ž×Hó[zârÒñ±ôl?¢¥'F‹^´ôÔl³¡'~´>†ž(øÉªhèYÃGCÏV7 =ß­';.CÏ*F†žÇèn6ôÄ}¯ôÄ£¡g•LCO„õ}ºÞW#!;O$lŸà0Ð,–fžʈ4óÄ„<>fžžH-X÷XWž©±gÜL4Z+"u¾‹,SvYV”ÐãÝ–“áyƶþMaeΖσS„;¸ŠEùNxXVœë7…–Óòå2XÆ­[‘pf|eÅ£=p`Dê¼xÞqÞŒ¯Ì Œqú:*/qâ:F-‹c¦ Ôɰœq:qõPÔ}팯¬ Æ±¿zt×7%OÕæÎ+ÝŽwé ›Û“‡áï{Í˃Þ×ÅËsp¯ˆöù0fÙûœayîÉx!rD ÎEãòT )ù îA–'½õŽ{geÝqú. ²üPy ‰%u>)‰½ c,ãb¤ , §s¦áÛq_ ±üÐÀçÀ‚¦sñþÀ0Ât>)̽KtFXv/±åÞ±£ÙR:’2âÂ/¦¿ËC,/š>¼+Uœ¨½?âM³$®ˆÒ9Fì]ÞâD 5Å0¼{Ÿ Ó9µXb3q:'¾_Ö»>q:|·3N'M*B‰@“>ÎdzdY?šc,/z²¾3ƒA–ýàG=‚,ãš©‘) ²¬ÀçY=‚,{†Ì“A–ߪrMƒƒE#&¡N ÄÊÊYöŒ€5f.ݼô]ÓyZ|lFXþ²¼è³xàvßëb6F3Œ ©{Vhn™gÄZ<ÍÒˆây#åQÉ'Ã,{ØWŠ„ñº¬,çf˜å•†+ñÏþx×dåIã¡È»¢&Úü¼Äþý?tè<ãªyÎÐ#óŒ-÷Øøpdô qÆõ±«Í¶!CϧuêÄí¾WOÜî øJ[¦—û>QÓ•yné û¦ÐrðŒ(W«·—®x?V~LN|œ·»}xÏ=ƒò‡ŠçgÜÞ}ôâ~ßc¯÷ìÜÏŒ´Œë}ãï+Óâ'++ºi¹ó0Òò¢YÒ ÛwÍkƒq,F[9ε™12aÓ´6ø4o}Þœø4ïwŽMœ“œø4TµSX:q½o,àM4Îq1Òò¢pzÆõ¾ëSòÃHËkªœ¼å.êº3eÅiZ´0D÷ûNN‹X>NÜï»Fv=Nˆò`Û(pœGÊîm&áû¼?™­;2öl¼A#K½â0-&Û™¥Þq˜Öž%®÷½ö‰|0¸Þ÷ZíÝãšåÖ|ŸwΜ'pEñÓÛÕ'xw£”xžJª½wgújŸ8±ïüyÆ-Ë- t—;œøs³´h[Nžqdv÷zpŸÌ:û8àã¼E={~ƒN|œ÷½Ï|œs çGèÄ¿ÄÕY×·®G/ï,yÆ3;aá§' .ôýè.ø½÷>ÂwØïµñÄý¾Ïì+pæ“?Ú3n(¾²¹ÅŸ¯GìâO| ÷OGñŽ%KHV0ň*”çWDG'òeÀ ¿±ÿƧ ¦ üb ߈'nø½^2nø}öìE|:Ï'îY>a]$râ‚ß9{“a…k¸»'ÑQо'>ÒûÑWDŸ“`>Ëçýï„Ê6ÂÖäùPཞøÀb6ÔQàsh @ Ï»E] YI_þÜm’Ç7?¨¤À0ÆIxI7µçN’)º¤Àº ÉHa£a ­ŸÛÁ¹` „iÀÞ1p{nþHöÑ a ã ÷ÁÚP$®,‡èë¡„¹lt¸s Žò¶dPr È.ÇKˆc•1bàXü¢!$• Ð…8ÏÏ–0y›„ã¢ô` <*¢Æ@Ôžì˜ 8׃ ¤ùíC‚#,™~4¬_‰1qdA =Ä-n3SƒG,&A6“àH‚QaK|ŒûK‘ ¬’E‚còs.|ËùÑ0ðÀ’÷£Q ŠÈþˆÄ üPà±-V, DHЉÇňéÆ@J5 Ç⥦æÀøÐf1äÀj1ðØxã°1ð°Q ~32 )wç(ˆqÎJš$Ž‹²)ŠÔ“)¤@<•,&˘âOBà˜Üбý€÷£1 †aKV#´$ß 1à»"ˆÞÈ€Øéä›"Ä{ñ$1V12‚@ص0 !ð8ÒË ˆß°î„À–"Ú+¬ö 1à9Y ï®ß> ˆ×$çð€{I"!ðé|l‚À–‡Øj"âµÈ·VX¯…(0nQŒaà›”Ê³1ÐSOˆ—?C<â<óGƒ@t*§„ ðW\¸ !ðˆ¸b•x> xÀ0óÑï(Vˆ¡É A|kb¼e!`=m V¾p$ÀøQň[Á$ÀzÞ"À#Ì·Š1ís¾Š[Jàû“•Àè±2¢¦ØNc…¸ƺžÛ Ÿ›ø/*Ê­Ÿø;éIüçÇ/Œ…9wD@?'óŸÇAüw&„‘ÿöm+݈O¥ø/æÑL¼Kþ«U›ÝÄ`½î&@<¨¬‰xìwÊÎÀ÷GqOèõTèK³&·yÀzw€µæ ãW¹ŸzZýFs‡+ôç^X¯¼0¦_n2 €mt€ía£y‹<˜æU°Þf _ `MPò_KHü«Ï§ð/Z›ØCük)Â?sð/ ˜²¸v«×Ä¿·®I¶ úë9’þ"%Ù„ø×^Câ_¼R êÄ¿˜ ù’ÿÚÛ‘øwÀ¦‚䖸צ ð€9äΔ´¦h¿JŒ‚£&`˜¯g‹ €õŠÿ\CCþ«„øï-÷áYù¯ ù¯¾â¿(y&¸ÿÅ:ñü(ük}"þµr‰±Êæ4'þµA'þµA'þõ_%þõö%þyÝ5ýáÉ¥Dô‡­k¾ò¤¿¿\¤Hí­Kú‹/ï•8˜ô?J6&ýEÊ–U%ýÅÓ¼4“þÚ“‘âîýâa®1ÎóÌ7Gˆ  Â|YxàÔæùÈ€np‡my¦P;è-Ž“ñÐ,Ž1’Ç}èW”±øÍÂjùÊ<À0†ÊàxòOÒ_éȲ}è/̧(ù%ýÅ$ë‘þø˜œ©Õ þ¼ƒ%üÕÎSð‡ ìÊ þpsNÖ-ø3ñþ°0ÿüÐãH¡N(øÛyDSðwР²àï¤KDÁß[NnÔ "cÒ_á•éo㉑éï}ÌãHÇþE?3ŽÐ¯¶ˆF?kô3N‰þ€™…ð×(“ð‡O_ÎÁß@ôDÁŸ‚ð ¦8(5ÿÕóFg¹€UyàI*ÿ™FÄ88‹ªÅ­ò17µâ?÷[ø‡>å)‡øoLécâ?ŒÁ8&=S €=…¡”uÓ•!¬óÃ8éÏlDJò? p¨ ”w`Ë#Ô]hâUÍé(l„€cJN¢äë£ÿ‹«SbÀ–BÄ;•‡.„ÀzÉU¹(,‚Àj °ýˆ8ž#•ˆ¿·¤BB Ì@3 èUL8êõ"@$äÁ‚°P^XC.8QKà#"%¿F@Œ)ùʋх<¡b+›«!0¬¼~4ÄQË%Öá‚ &Ë%Ö*ĺ›´)¬\X‹¾(°&›(¿"­‘ý­rBà8iE/ DB~éD5DþJ™‘Æ ¦@·ÏˆçIu.1ÐÏèÒØRÈžùæ@=c &1ù’ØZL¬ÊÅþ>‹#èÍ¢êGêû'ðýÕøíƒ!XS¯K Ä"0?ØRˆ¨;÷¬â@¼Û‡ñ|òÄx¾£s`|3ˆ”D3b WCc ß*c`ýˆˆÁ S Í@MØj¥Œ ¬N‰[9¤Àª\ˆé–RQ ¶Z«(Ð˵)Ð;S ŠÏªE5…x[®Ö{gÔdÄrJˆµ´ÇIÁ/Ð..Ü48`KI¬-¬-¬Z €íGÀzu€-%Ðß9`= ß.ñ_ËBþ+€ê»bþƒk Å=`8 &5«&òŸ¿æ¿zùÅx—F×ÿÚ:Cþ«y(¬§(Ä%Ï€­ ?QÀ  fïÈ<ÀV;Я—ûšý€Øî€x©â `ôJè…ÚˆÇÀ‚ €úv›ÿZ¹ä¿z/l®¯Ï_D¼.ÓOœ#}o<_䛯:-ËOŶæçHnF>A1òÁ¹>÷áB>`Ýú ßìø¶Gǹ"¾íÙS‚,ÉO·Ú•ä7/’„%?lóW„>ߥ&èÛ7ºÆ7ÉoQe±ä·ñNñ’ütÜX’Äšü©¯¥Pòƒ`ò•üöMz#©o‡—ÕGòÛæ#ùùÂ[cªšì+MR؇’¦ð@寈};Îæ(‰}û`(cÊI®öùj_a_5YØW#(ìÛ·G|Fì«<"¿n*x$? ØÎÞ£ã'!òÛ7Y‘‰üðŒsÀ„~íWD¿ýEòûƒ~¨}ÿX€âW©Ðýª*¡f\žyýj: ý|ášÑ;œí£ýÕÌ%ûµbÈ~¾Íì×*'ûÕtüázµýx5rL¾FÎðç» ¾”Íð·MzhþpÃóúÀ_½m‚¿–…à$Bø«‡'ø+M^ðW¿üÕàþj¾\Ððç[÷ -áÏwØþjíW„¿–’ðWÏAðç› ¾ÏôWÏAôWÏAôWË ñÏJÿ|Ñ¢ùÏWÇ}   Ð7š[9$ÀÊ#¬rD€¾ÂÑX]¶_‘ë|Qè.E€È²>*`+†ØŠ™ºG‡®FÀA!`U%¬º„€Õ-!`ûÕ¡kV5`BÀª] Xm¶r’ÛÈ€øâ­úûhk=™²ë–ÕKrÐåˆÝO3`+øÔ-«N!¢˜¯-¨ÇÔØš3uËê-cUB Ê¡µå¦[VÕd‰¨!qCbà†X¨ù+B ßS Ÿ–(°e!úÕ2úј[1¤@_tj ô-¡¢@ß&k ¬‚…~ÄÆ@¿$ÆÀ–‡è ]Í­ä»nYÍ&‹kLÅ­dr`=?q`åÖ<ô«fôJdl)äÀV9°UDl¿"ú1úz,ƒ`•#¬ kº‹«=âÁö«äÁš·âÁ–…<ØŠ¹u˪«"¶r¦nYUG „õ¨„Õ+!^šMh«\DØ~E"¬V'„„5¦BÂÖ2a«‹LX/±˜°V1a•C&¬ÊÅ„íGdÂjŽ˜°å!n7¥O!aްýˆHØò «WbÂí‘Ñ„˜)³›„¶]LØR’ [™°"1a=Aa½Õ‚Âö+B¡õ/„Ãn¾á€ß}oJ,&Ä'&D|ªs!Blö² ŵz]|i¶<iºnÍV¡›®tü“Uèvpo«PlÆ“+<âVGÄ—“y;™qÀçdëºà€‘xúy%"8™¥ì–„ø&b¹R£,»ò ß!k‚˜B¤6j‚H¹è-È(ËUÌÁ(Ëîgâ`½óÂÁ'MƒÒ›Q–õ¾ {Á‰ƒm¼ˆƒ­œÄÁV q°:El¥kÚŠãGé°Gl­! Lh–“4X;+Ñ`oÎd”å*g1ʲSHƒ­vÒ`σCž‘¢ÁVi°ÿäd”å7Š{E7£,k´ƒ½ªÉ(ËÎ’,Øž7Yp  ‚LA3ÈrOaå÷F‹[‹“{–“±–U7Qp <ì™px3Örýèa¬å·O k{KlÅ#eOÅng¬e7(ØÆ†(Ø*' ¶!& Æzœg5DÁX ™‰‚(çGq`{ºäÀö,É­yäÀÖ…ä@•JŒm‚!°!p š_g@—‘ØkM¬GDlM%¶îÃJ2W`ÙM ÛØ[å €jé¯=é¯=gÒ_k éoÀ‘n„ Àƒ ‡#Ã$ý.:vQÞþÄ]\“áÎòâöŒ 'ËOàLnïdù9Ð¥/€¹y¯jY~ÊÍC*  ]­âÏUÉ€ñ²~dÀØ7'­QD¸UþŠ2à ½$CÊ€{œò€d@ – ˆH¬©·HtÀYË€ŽäiÐA-"0æþ1þt(;É€½G3NÊ€ˆÇª(^‡Žã%^pÈêw âÙüÈ€x[st$""ëè”ÛëããúwÝ2]’ x]óKyâ¸vÈ{nS¤^°³IÄLðº§ê¦ x=»„Bª€×ó|ƒÀ\Ï”WE@d¹?ž×sKà£x½‹Ñó ƒ²"E@ìtçG|NºçZtäm‹€ˆ¤šŒDÀ眊J“" ²Pc£ˆØAy¦ Þ±2Š€U•DÀçfa‹€N^La׳Åv=õY‰€ÏsI(¤øÜ§@”" ‚¿Òd•"`,—¥&)óãè¨èËOS"`ù‰ID9)ŒKD4s*z¾C°e XC!cü|ÁàWTC"` ŽD@ްXµK|[nRDlûû b|¼«Ía7ÛLçhIt¼z‹€ÏÜ¥ÃQ|æ½QD<Œôm“ˆÐ½©RRDÝõ("\}¾ŸÅ€¤Û¯(FLàˆ_åê*ÿ%½Q|–|Á%¶,ë­‘ˆw„¿¢ˆq§ÂG)[«9Qy>P‰€¾J Åƒa,`‹€ÏÔº-°:!y>ñ`¢ëD<Š€¸ãà+V %>K¶,ñŒ [])úº‹€íGŸÉÏ‘E@7Ç" RÒÀH" ;*YR-ˆ@Дê(âQø,áKly(¢ç_‡ÀV2E@ä¡SE@äY_p£}p‰€Û!?BŠ€Ïâm%[JŠ€H œG)g:Rœ›q’" ºEEŠ€È³uê{˱z—"àÜv9åQDÊ‚È" _-‹€È“ÛP‰€É}§xGÐ/¶EÀ–BpÂý 뢈N=&LkD@t^(Îv):ô§EÀ?‰€ˆšÇÐ-kÔ%Öd’ˆŠV¦PDÊѹ/V›­ƒ_Ô5>^ƒ˜NXïÅÛ—-V %¢äæÀ=%iÚ+p"ÚÌÇ-°ÆF" R2hˆDÀG‘v-Ö J°z.°z.•Ÿ”S¬'!pŽ"`5Y" &ÊÖÉ/ÖÕÃįžahuT" †çþ8"N|vK"`MeŠ€UŒDÀªJ" ME)¶<'B´g9TÑœí£Î]¶¬RëK¬á‘ xÃ/:M:©"e|T@ttïaZíTkòH¬ª¤F\ý ØòP¬T* >#U@GɾÞýd ¬£´>û»:ŽVyZ¼ëŸ3ÕÏœé¿úë(ÙW¬=Jv¥TTj¥9F­Zlê1JæjEUJ¥4å„^Ô“ [QNiE1­ŠRÂ{Äl núùeÄì_Ļ΀Øç_eøÛ³?k®w²ÇñZ %ü«IrqdÔr¹,ÇÂvY-¶Ër.—Õr©¬Š…­²z,l•U¹TVÏå² ÛEU4l—¤<.¨ò¸ÇÂvA-¶Kr.Õrùr,l•ÕcaûUt.•õ_‰˜oƉÃà_FÌ~þ$böïæÎ¯#fÿQ¶Ÿ#fÿEq?Ïî?ÈvýéÄþFÌþ;‹ã?~^è~±þã—/ÌOËã¯ß—ß•ô/GÌŽ?XÐ~1ûžŠ˜ýþëù_1ûýÿŠ˜½Šqý bý׳¿uT ì*í?~1ûüÿ>bö…H18àÅ-|cê Äï32ºëõÒyœïâ»v½ï–*í*pûMÀù›’v¶Š¹ŽE» -g×ËAyÆûl¹;º^ÌH ]k~ƒwVË)â:4¼—ú…CÐc¦{˜r¿«=£majDÂM»û{æ.ðÝòå‘tƒ‚.ÜÞ{oySòÈ ÞóG¦¬:lf#l‹kG˜éÛr“:¯9rK ^Þ`Ì­‡ªÄY¦‡¹æÅ˜[ïú¹¥=÷òGƒn18Í5'cn)~͛ [phÊ‚WÝRX¦ JÍÝa]ÐÆC4¹É:l³Òãš~©"¡¯ŽêZ'cn)ÂÉ…á¶E­AÀòŒ¹Å'×zsKQP.Üàzô1np¸- Vr!6lÆm!8ÜÏy÷xi7"R>?¹íÞƒn1XÒ½ º¥`÷v2èô­,äbЭžwo·Bn1nÓå-ÞÊ =uÃÁd0˜ÒÊz'#n)¾Þ ˜ˆ¸¥P7"V†%Ýð`ºþ«}0â–ÂÝû‘—˜!zV^ÀºŸŠ¹•±ˆÞ CnÁê(¸ß ¹åª†Übl‡Ñ##DmLÉ[îT€ÃjQ9nŒ¥û!ØÞ±5¸ÊSñƒ!·p #ni »Ã“|Ïr·L¹r«jºr‹Aîîñäùš/p¸ÃÃóì®™q‹ñ o„¥ˆˆ[;u™ž-*Ç0Z±tûÞ\ õÕßݘ¸¹v3®Èeò9"äÆ “‘GÙ}ÜoË}<ÆÛRð¯ßåíé]Âw9nÅ»Åx[ŠuŸãmíy}Ã}î ·¥Ç†ÛÒàÅ5k|-òîßód´-Åÿ»Ï‹Ñ¶ü páé)n¹Á×É€[ v_WÞ^†‡“Šb,Üù”®GÁ¶¨ݸž9Vm÷匔¨2VÛR´ŸäX´w^Fqã›Á¶vÞÄû~LlËõÎÛrÊÉ`[~Ø÷•Á¶¼ðàŠæ{µ=Ã+šŸ§Oq„ÍwJØæªíæ,FÛòbÄÃö¶?;Ãm¹9ØRÆ²íºžƒá¶<€ÏÉp[^ž‹á¶<¤PÈbÙæWä†Dõ|Zó0Üv™2ém}ŸªiÑÛú¦—àÏòvö—{î ·¥(w7>Ëco_ˆy0ÚÖÎ˪ïy2Ú–_Žy ®ÝzóÞçH³W4ß=xÚ+šŸ½?,\Ñ<ûØà†æÉ~F`Rñ]ºÃpñêƒ&ÓGï>˹vk)Á}G_ÌqûH®ÝÑ•êz[Iâê‰XÕ2xÓ[$>k7ûgˆ[1½q ÃìÑœàš=ðÈÁá{°…Ÿå tĨ"¾ËèˆA×|—3Бu F¹¥Çý³¡?*Nï;‹7.ÞŒUý¦¬Üxï¼Ê÷ w%Lœ‘÷¼4«¿w¥LÚÕczç¯&íê!ÌeMÄ?\_@ÚÛÒ°~R4þmMO„×iÁˆÛà• æ¿m0¾½ù6OÛÁFSô‡`eU¤?Ü$›sVôgBÓ Žg ø³«²áo{F®]†?„$ȪX±¢1b?ø_gÄ~ö 2ûÙGÛð¯l°à¯X0^;>ðÕ:1Sð‡8óy ø³c°á¦jù,Eб ‘—¼­©ôšþvÄrÎrHˆ +²éÏñ#L¡«gɤ¿ZZ¢éB€ýAhgâŸÃP˜ÿP"ŽwÌöq4ÿí¹Ål›¼3•¸çÕöñ¡Ù2àŽ×.Á’ ˆ0¹î0™‹_‰à XÍ"EܱäF'ha‚ p¿´s"&GvKˆr}I;bÖfU¤@˜*œ t\S`5YˆÎÄ;bÜÞyfl)ä@t/i]¸cåŠ ÷‹ö–A\vB XÃ,ܱ¦D Aö¹Ç¢ëñµ2Â#Ž7 ‚;"kg‚`+‡,XFÜÏSpHÜÞhf¬^‰1:#SȂձ`K! "äi| ƒ(çüÐ äBi°ê ¶rHƒû©¥hWZoY2h°ÞXÑ *JÒ# †Ñlô›0ø> ÞKnÄhåÙ…`†¬G#aÐ&À†A˜¶&” ‘'ß|Ñ ^ˆœ¥BôéÎ<Âx²da1‰°§ˆ°¥1sB_7¢òXóL„õÈE„Õuá~Ó[ÂD¸‡fú£aMRa«ŠD¸_W˜1ms"‹÷›>¯&BÌla²ˆ°!º•뫈°žŸˆ–L7 0YVþˆHˆæÄyª‘°–!a½BB,9m…„õ~ w„‰Ï_‘ ë‹ iMݘ7ºçDÖK#&Äó#¢’ .HL¸#Üp& «`A!VÁ캠ëE¢ ëÙ k &¢˜y …õˆ…˜`'0¡S%ÃD…gX0±pÇF8K&‚nbæ wìô“È…ȳg ±Ð#h,ô´4òذËÎy ñŸY ±•ï™…XèUÐXˆip':’ Q0¡\ˆÕ Æ]\ˆo|Œ©¹sp&á‘ wøµfr!f÷ýáBì’â`.ÄÄØÿÅÚ…†‹)Vu®É’ßE¤,HO “!®rKð"¾[õ·ø’ª`X2&ôIÄ"«’*¸íBN©‚iÊX`gKIL¬ **xS¥J,µñræõQ}ìQ² ®£±,Þ  SD$nò%¹g]Œ­Ð q’bŽTA4ú¼¢dA† iÒX舵¥ êØÍ\¨;—Ì…• UP‡‹æBǽ5ú¸‡² OîŒ…Ž¦k,t´ÊR«ž[A˜óÖX¨È“% êpÏXèÃc¡ãk ß\è›æÂVö LJ Ý1¡bv [%Â/«iBBÇ©5âWyl@$ô1”‘Б KTàÌÒOšù [9DB<Æí#:,­‘Ðas„>^3:î«‘ÐÁ+„žŠFBk˜BBWe$ô™œ‘pÜ´l2–¬%$Ä;˜GèBBT•˜Dˆn’ö¦"0§‡™°e!:>¨0'„i°Ú&Ä»žR+‚:‚5 : ªiÐѪK„}zê}â/g0UàC [Td|àc–$x/ér„AÔ”L)ôÃ5 ¶‰‚Û-̼™v†AÔNÅOª Ï܃~ ƒžØM´8·13TàµðR­c ØÙ,Xu—.H±Ž(èIm´€jUP·ç˜ÀÖ$˜I4IPBˆ0°FJXoF‰‚ÒØ„5RÂ@«m¢ D a CÈ&âa±X‰‚–#I^(5g¬ Z¨µ&¨»J´Wš åž’é¼×4A©O% ò!•*è,V­>RÔ%LMÔC(Yù3UPÏÀª ÏóWR¥¹Y´MC©‚Vü¬ Jí)UP*UÐúžTÁÒ÷¤ ºW]¼> X d©‚êD©‚?I‚ Á[𠆦k‚<â¿ÒÁÄõº$˜ŒhIÐ5•$¸ñ-íš`¶¯4A«„Ö3ƒA÷°AW$ApÿªìO‰<§mj »Ô@Í«%ìI t[¥Zš,5Ð)V£m–›8H-°~BêÓO¤²?&>—aâ³…†‰Ï=4ñyêšøQÞEÿÕ¢¼‹¾Ÿ¦¼qѯ(çXù+Q^UMÌ+ö6æÙ„ؘîò.úcå Æ yNäÝ ÐlÎKw©z—„]“Þ5s.ôdS çôª‚žn*+л>&ƒž-ž z÷Æ9lÐ#íç) Fq^ÙšóµisÞ-ÑÛœ§›:Šóªâ<¥çå˜ü)çUqž÷ÀÅyÎ#ÎË´!O|Û)/IÁ”[`Zƒþ1æ‰'yn¯IÏ{m“^áIÏg8ôÔž"=™H¯ä§Ûdêñæ,¡^¡‹QO×À4ëÏ´È´é§ÚbÎQót{ˆ1¯Á˜0g$Ey.…×*ä9 y•‡Wu òd’_gäÕ¸òªQ^¥\ºeGæU1ÂzDzõ.‹ô|±ŠQ¯Z'Ôã„çÕK(Ыó^Íz‚^‚@¯^ëæµ ļZW„y­ØÄ¼–@ÌóÉ€(OGІ¼zŠ‚¼–BÈó%5†¼A^={A^ Œ ¯!y:½4ãÕ¡Ž0¯úMÌk5óê©ÙôÓÃgÓO,Îó5Væ¼ZõÄy.a^U.Ì«§-Ì«,Ò«—[¤çJ Wk0Y¯¦`¯êìU¹‚½ ÁžkëÕ€’õjhÄzœŒ½V Y¯ÆW¬Wß~ºGÂ=CÊðSÍ-ÃO u²úÔ”)«Ofɧ-(Ëä“KŠM>«Z¢ž;T&Ÿj~™|j2”ͧŽQËæSÇ‹¶ùÔœ*›OWn›O=زù¬Û|ºÙ|*Ï¿»i{'«ƒß‘ C¹üM¹ÙêS±²Ëåo\ô²ËŸ"—ËãÖÙ껿”à¤í= ó&ìƒÕ`ºíû¶“>C–ö´võmŒ†PÔw z‰ú|eóW¢¾gÊUÔ ©Û|¾Ÿh[JÚÛæªi{Œpdì;a„’ øGåÎGî;#X™û|$T.vç÷9ÐZ¹üic¿“a‰Œ}×¥ºíñw=¿}°»Œ+í;‰}ˆÖv'åÙãoå–ÞsÊoØçjƾs£ºmì;q ž)Ä>„ {ûtlûØ|"ŒI>—À>YË)!ìkˆ}ˆsBW=bß•{½†}˜„{þŠØ‡ Ž´¼Ä>Dç"bûÎcql„}çÅàÃæ¾ëëï‡y5>&Ÿ'À0óû"TXÂXb¢þ±bêÙ>þ~.÷õ÷Ãö‹ÄIîÃö‹•“û®É³Fqßy-rb¯åL÷E˜² ûN„œú˜|ž·ŽHÄ}hßñ1ùDÄ—´[÷]㌙ûîí-’û®qÏÌ}ü®CÉ}ˆ¹’¬Eì»v^=*ì»Æ.£KbŸƒû.œáeb¢Í| >3Åàç÷Ràw eðCt¶ó£ï]¹õ]#é˜úî}ŠñH}×2¯$õ9Т©›FÒ©ï]Ò÷¼&˜únøŸ~¨ÏAM}ïjÆá#õÝ'o<3õ]MsM}(&¡Yàwã¾é”á~Xöµ'öÜÙ@‘ß}m²ä$ù½ïØOÖžXJïûawüñúÃ[¶>èçÅÄèw#lÛ"?¿d&?šò{1‚–c"¿÷åVPäwM¹È‰üîû`Ý$?dù˜zâ[;6†ï¤ä—àç•Ãä@9>nXµé°GòC£¤$‘ßµdž'ò{1€ö]"?ü*ëù]Ëæ $¿û¤5¶ÉïšÇ¿þg’ßËe¹Xäð>"ßVÉV$¿ öí‘ï‚GôÇÖ“öC~¥˜OS䇌ð»–¤"±_½b¿b±ß5e*HöÃÇ45i±Ÿ?Af? Åü¨|½ûƒˆz~ð¯¥$þ!Òc¾/¿kÊÂOüW½Ö›(Ä—áþ¨|ײ…&°&  îGDí×? `ÚpÿPnRñ¯æ‘ðï†7H÷üC6&$þa:æë,ü{ßÈß>VžÕ8ÑÞÌFžî“à¯,ø«§+úCž£Ó_ûé‚óC×sðG¢¿ ñå2鯞®ðyÒ~3éCž ’èï>§‘ˆØf_¿¿ñæ>&žíW@,%ÏGïCÊù@ÏY Æïù~ž}fÀû¸…xÄÀ [éçŸú) |×mºÑ‰=ÏMèg&QÑõÀëÚ’ þ² •u}ÿþ׈%}Ï<„@,ûGñ»°“Ê< Ö4)÷þ"v©|×¶Áÿ%õˆö°5[KN_zQ*ßdˆg«|0ŸeË lN #ï]>t’ùÆ#“Ì'·—¾ó‘KŸm9%_Ù„Ê–ó<¹…íÀ—H¾Ü4àû…-'\‰>À‡Ë“éŒ×Œ9³Í>¸¶%JèÛè!e¥OgbMé³ö'¥.ý_kÎ"G+}ó·æä×J±Ð§ÃŠRú†hÓJ¨#m,¥ôé̦”>lY³I}6†µÔgÇRŽ’7%õÉ<ÖJL°“©¤ô ¹¢ZéÛŠ“Tú¬ÇIéCH’¯ÒçÖYéó¤°Òw0Ìq)}cH ´Ò'>+}CΪVú°ãÿшÏ>%¥ôANOW@B_9·Yë»x‡¤µ>—+©Ï Vú¤:ZêƒÖù g€¦’ú4ä’úÆ-;KI}ˆ'ô•úC-”Ô|ÿÑÊùúJ}ˆ™?"òùöñòò›¼`¥¤>XÕ|¼ü>%ìå‡%0óHêS §òò[t^µ—ß$E—ÔÓ°I§hæCs_a©oç²Y^~‹÷DÙËO½*µ¯Ú'/¿ªJ^~®ÊjŸŒÙËËNºÉbòò›ÂI«}|4åä·N2¨ü`…œ®û`6™ÅÈÉ÷©¤Q©œüªûã™ '?x0°Ï&ú¥÷m #Á–}Ékrò[—`QN~wK~¸k$K–“ŸGÐN~ÕBI~2þ·“ŸGÐN~‹—Ž•ä'›rò„}ü&χJò“y‰üruoä·O^­T’߯sÆrò[=¾ìäçyaÍÏca'?ÏA;ù­!†““ßZ29ùÉj¦œüd5SN~²‘)'¿uÓ•2üdžSN~žo"?{ߘüà7–Äa/?ÿÊ^~c{ùii*ÑŽÌIzòòó¶—Ÿ‡Â^~0æþx¶Úåå7y}šu?Ï%{ùùYÙËoñ¨®¤¿Guåå·èz_^~g¼ØŸéíÛèÓG/?ŽÅ?tgUòòó#·—ßâ…z%þiQ./?×e/?»Å?wË^~‹–—Ÿ§—Õ?·P^~~óíåW ”—_Æœnü‡+Iæ‡ÿêÍ·—ßz(3Û˯Räå·ýôû“—Ÿg»½üÖ-Ö”—ŸßGËïÌÈs>{ùUÉôòó2hýO»ÒòòóKl/? õ?OB{ù¹dyùÁjä#ÖZn/¿uH|”—ŸÇÝ '†½üü’ØËO ,/?|Ç¿^~Z§ËËO_ýòòÓ›T^~šåå·x-¢½ü$ö”—Ÿ†½¼ü¼ü^Û2E^~sg“íåW)ôòÓºX^~Ï£È.òòÃùzš†ÊËOÛ‰òòË—·{ùi.·`ØÏsdÐ`]ÀÒ³Ç{UžÖúçLõ3gúůþ:ö„ïËq¶r+¥ÂN+ÍágÐÂNÏyÿÁºRZQL«¢”ЊZø®l«·N©¢”梜ðß ÝåoîÆMûŸÅÅþ]Þ? ‘ý‡A…?­žçDäÕEøW“è€9ã'¢¶Jª(Ø,©ÁvIΤ’zöÅ€Öçvóÿâ_™~‰UÚô¿~û[Y†Ç~÷·û„ÄŸÃc#í?ý¯ÿEšÂcõçá±ßW-ƒlÍ#NõòÅâÃ;ͼ/dkO=éÁugêI±ëÁM\ñ±ß©e=p±ˆ½|<¸ (>öp{Œ-ÂÌKùêœâÁ§áíà™ƒÇo¢õ-ã7Ñ=óÔñ[¶½ <};yÔû1¨ã·h>”qú–Ôó)#û<Ÿi&(Û§¹äJ­`v ‰nèY ®¬Ž£7GÉ[ƒGoöbYÞäžü¬S¾Ô[Jëo ,;D>qôæˆëf€e;ë ÁdpWæ™ °l?„[ÛšÒܶŒ¯,gй팯ìƒá•åé5·ƒá•åô>GÆWn)Œ¯Ìˆ»s»^Yߌ®Œ•,ž/ÎØ]ìe(/ïêÆØÊî&ìˆ"¶òÉË'.3=ìø„Ðê¨pÌ;÷´˜ï§#­äÜœëdxåªêbxe÷&,ÇñùÕÃøÊøÖgžÉøÊõ«E_êƒ ç½1Àò™ÆLóÞ_Y¡ò'Ì•ZÎç}0¾2Îy3Ϲõ¶ÀP'\©OÞÁ<ï+Ûª-÷M_êœW÷CGj7dÒÚcÓÒkoÿ%ô\³qd ;ݨ=Ï µ_Óç µÇà9èGíŸãmïS/¶¯½ùøï³?ȸóéÍ›ô£ökû~erÍvÝs£µ£ˆBš Žïü|—'ÇÄÏN½¯ÿOËö<èG­lžt£>ã¼èFý|gÊM7ê#¥è‰r†Äçr:'¨ÈM\žk6ƒ ¦ÏO'q|.ÛNt£Ôÿç:ÒÚOet£Ö ñPcá>xH2±9Ê…[ußt£v£Àʘ5éE}0ræ\‹^ÔjÞŠ›ŸÖ˵íô¢Ö·jmƒŽÔúž-\Ì 7‡|!Fi¬ÛUÌ™®ÔêÓµÌZ¶ãá.D˜Ëe;‡|á“«6Æ…/r,Úú¶.|‘cÑÆf,J‰X“m8B9üüÆ.d!Ì“â*¯ÌsЙZójí©õ•[ûIgj èÚ/úSëã¿p+s¬Ü¼TdáÔ(îAóŠ…ÏrFÅ¿s˳ðYÞÏÚŠ,|•ÇÑÔ;ièNí!#Ý©ð~A]…[×E¼)?ùS/¸‚¦u³jºèNí~s7Y´Œâ3tAü5éM­]ÅŠHÓñ¹«Xø"§75Íð¾È±h몈…‰E{Ђd¡·±hóΆ…Õ.ÖlEXXËrÍæGeÁž:ïvåo>w/Ü.‹ö ÉÚ $±hƼ¯ÜÙû|æu=%/çnOÿLûÕZVÖ‰:§™çX¹pûñŸçÌ…[‹Ü:¯'WîqëWwlc…bÁ"ø¹?Yæ™+·‡·1"`,|”s³6v+.ïSŸäX¸uMj †LÉÙyåXW4ý:äÁE›?þ~8l³[¯ÙYï9h"ÖÏye# {ï,ÌÿŸ¤÷þI@¤7pgrĈô"òuÚöôFˆaFDÒ¸‘2=]Hzåœ/Ò¸Çò"Øé |¼’•ˆzwŒf{‰z­Ø²®d½17îb…{& F¸7p#j‹÷"2wvœ¸7fnw ÷ÊÎH¸×•¸7pÞ•öˆ{ýW‰{wV÷âWwæIܸöóȔĽ«%§‰{½œÄ½ˆ&¾ï Œþ“–¼×Sø*¹€o@2Êí/~u%š%ð ܆™»’$¾»9sSBäëÅ$ó½)ôSóEJ"™¯å!óµXoôÁVõÁz0’[ 5šÛÒ«d‰„Õ`©„UŽTÂj°TÂZ0¤Öj%•°^ ª„Õ ©„Õu©„­rÊ„5ê’ k%’LXó–2aËB™°z.™°§ðÊÏ[é„­ê„Õ+é„­ …¾OÍJauTJa•#©°FYRaýJR!~•b3¥Âö#J…5‚’ «9’ kbH+Ä5q¤LŠ…µ–K,¬Tb¡ÇÝb¡óX,t',zݱXèglµÐoŸÔBÏ8«…w«…îºåB_½g½Ð‹°õBOKé…~%¬VUÒ ýV[/¬žK/¬žK/ôt²^轋õB?- †­. †þì[0ôÓ²bX]—bXãNŰ%P1ôü²bXƒ!Űš#ɰ¦$Ãj %Ãz4R ë™K5ô+aÕÐë½UCÏ\«†UŽTÃj²dÃj dC¿7– [ eÃj³dÖ‡²aÍŒc}l$ÖO$úScÙ°š'Ù°ýвau\²aM&Ɇ­vʆÕ<é†õI7¬7Bº!&å‡Û£¡pXÍ‘pXÝ’pX ”pXÓB¡‘ä/"h—qè·«u"ÜéwhÁp :åH0\Ðe4ÉpÁˆ5S(.ØJåo(Â5'EDI†ë̈4V ±Âæ]SR [ ÃùM0Ä]ê4ä¤`ŸŸ b'Ápáúµ¬›‚!¼xÓpR‚áJG} †øÉL‘‚á‚uÚZR0DJÆ<`ˆkܓɨ"aëæ¡uÓ»õB¤¤‘ôB|XR^•^ØòP/,#^é…ö)°^ˆ”ÙÍC‘òÃ8ÿ?5%¶Š…¨çìÖ¡Õ‹…íW [JŠ…Ï#?)†kVÂÅB?J‹…~p +Eb¡Ÿ”ÅBÍk…Õi…-…Z¡GÏZáº_ÀZ¡Ÿ‹µBä9³®Ô [1Ô [1Ô +´ÂuÓßZaK¡VXM¦Vˆ‚×G+„o[¼©Ö «ri…HÉr)¶Q*Dݹ™’Tè«›-Vk$V‹%¶J…ÕdI…È“¦c’ Û¯R*¬Ê%¶Q*DžÜ¸I*¬nI*\7ï·TX•TXÏSRaÕ.©þþ3óP*DÉÇG*l¿¢TX-”TØjO©0\ Ö³’Pت¦PXÝ”PXÅJ(t1Ô [ê„5M¤ö”Ô kÖJ'¬Ç ‘@I™°¦d–B™°º ™Ðë–eÂz.’ k*I&ôð…JØJ¥JèÆI$¬öK$äò(…°µƒ aM{)„µ>J!¬_I!¬—Bˆ™–˜Rkx¥¶*„­®TÙ^Ƀ­ʃÊ@m°š/m°Š”6XË;µÁ*UÚ ?…Öý5²6Xk¥´AOCIƒõˆ$ ²¹Òõ9µ,ØÚFY°[²`K¡,Xƒ-Y°f7eÁÉ‚5ú’«G’[U”ë-—,ØR( ¶’) zô, ú-±,èZly( úIYô¾A² ;aYÐcaYÐï…eA=«‚ž6Vý†J¬ª¥ z¸¬ VÝRÛ¯¨ ÖàHlåPlåPÔb`Q°FK¢ æ£5Ábi‚žoÖ[žÔk$¤ . yý¸-¶ ‚­ ‚5k$ÖˆKôc’X¥H¬aX}”XsDz`K¡Xã =Ћ‚õ@o~­Ös’X=?ÖÙ+’X]XUK¬±‘è‘X T«b©•…b`«ˆb`K¡ت¦X –X¿¢X?’Xý–èÙ)-°F³yÿø—âg—èŠàJ ûlèbì{·hÔÚˆ}óPlsqß»%¢£¸o•åÃ}ïfF†¡ä>pÚù1Øø§±&Áo^{zIü‚&ž$?“¢M'Éo^'iK䇔ëk*z]¼Y䇔¼•9ME1ÎY‘LE/ûøÉTT—©h¥ÈTóàk*z1"l™Š^ ]¦¢•"SQL–”þd*Zyd*Z)2½¡ÊTTyl*Šiß!›ŠVŠLE+E¦¢X¼¾¦¢•G¦¢•‡¦¢˜SÉq2­,2­<2­™Š:Ŧ¢/.SÑJ‘©h¥ÈT´Rd*z-iv2­™ŠVŠLE«=4­,2­™Š:Ŧ¢•"SÑJ‘©h¥ÐTôZ<‡¶©hK¡©h¥ÈT´Rd*z-±LE+LE«r™Š:ME+E¦¢•"SÑJ‘©h¥ÈT´¥¤©¨hSÑÊ"SÑJ‘©h¥ÈT´Ê‘©¨óØT´Rd*Z)2u96­™Š¶šŠVŠLE«dšŠV™ŠVŠLE+E¦¢N±©h¥ÈT´Rh*Z 2ukl*ÚRh*Z¿’©¨'†MEëW2­_ÉT´òÈTÔ)6ÅF%u<™ŠV™ŠVŠLE+%LE]µME+E¦¢õ™ŠVŠLE+E¦¢î¸MEǦ¢ÎcSÑÊ#SÑJ‘©hýJ¦¢n³ME+…¦¢^Ðl*Z)2­ÉT´òÈTTŸ2õ¯d*êÙTÔ« ME+LE½ÞÛT´Rd*ZåÈT´Ê‘©h¥ÈTÔŸ›Šzm*ê_ÙT´Rd*êÚe*êÚT´~$SQ?>›ŠV12­™ŠVÉ2­’e*ª'Q¦¢ÊS¦¢•"SÑJ‘©hK¡©¨ÚcSQu¢LEõÐËT´Š‘©h#SQ{™Šº2u16­™ŠjÃS¦¢zÄe*Z¿’©¨Æ´LEÝ@›Šº£6­ÊT´ê’©¨Ë±©¨¶Re*Zyh*êÚTÔ ´©¨«²©h¥ÈTôäie*ZUÑT´ –©h¥ÈTÔÛTÔyl*Zyd*êNØTÔãeSÑú•LEÝ@›ŠV92­rd*ê1µ©hýj}ZØTÔ…ØT´Rd*ênÚTÔ ¶©¨lSÑú•LE«v™ŠV™ŠzþÛT´ê’©¨Sl*Z)4uU6õØØT´~$SQ–ME_ Æ_×.pîØÏufÝ$4$ÁŒz"p0Æc)€ð$ýÑÀ¡àu-#Z¬)€ãŠI ÓW àX¿}8°ýH àP¼=+€cüÄ-E à`ØL*€ƒÁKSñ`¤VŠÀ¡ë–ÝKK€c)ÒŒ$ÀÊ# °òHŠ,o °j—ˆ=Ä®›¬M¥FB´X áÏý£Q ›Wà±ËºS ÖêÌ# ð82Ì 5@µ·4@5¯4ÀJ‘¨‘( Е[ô¯¬VŠDÀƒ—”ˆXÖ™"P=·èÁ±X)Ò5Q¬R/ Ñ7%ÂIùGC@=¹GÞÃPúŸ{-ýÏcýÏ]´þçb%ÿU)ÒÿÜ8ëþ‘ä?½Ì%ÿ †g-ùo0&nÉãoIþÑR•?üCž»{ V7-ÿih¬þ©ÁÿÞßø«^Züó„µøç9cñÏjñ¯~%ñO+T‰Z~Jü󤱸çÁ‘øç‘°úç&[þóØXþsG-ÿù]µüçnIÿó¼·þçÖXÿ«Iÿãº[òŸŒå¿Áȧ¥ÿim.ý¥JüŒL\âŸ'›Å?=^k?UŠîÅ¿*UꟛoõÏCgI_Ð]´èUÍ ÚkýÏ+„õ¿ÁÛ¥ÿ¼â¥ä?Œå¿:in¿å?·Íòß±ËFT  ¾"¥zd¬º)€• ÐÅXÔKi°²HÔ ²è5Ãà` ÞÒõ.P»Ý‹€~/,ê¡Xô”‘è§d Ыœ5À*W '5Àq+–Œ4@÷Ó`ýJ †«4@M¬Ò5:¥ê¾ÊÒ9JÔ¶Æ Þž’õ²—¨…¯$@ÍÒÕÏÒõÚYt¬j(JäÄ) PÏ¡$ÀJ‘èICº¡@½b%j1* P§4@·Ø Þ³ÒõVYtû¬jæ” ¨[t‚D@n>J¬b©zÄ­j>–èg`pðî¼=%,j¡+°¥,o¼i*Ð3É"`¥HÔL/P[ä+Ï:ûàYôä³è¡°è™eЯ”U@Že@ZJôXYÔ§»D@=8k€ž!Ö]5@í»¬úáZt·­j#Q" ÛgP£Ù¢gï.eé\÷ý}Dÿyo³³¹ŽléÝÊÖtBâŸ$žÚ6PWЃ¶.7Τïß\kE3÷®ÚU8ÚèQæË"$EñaüpoJ3¬ò”8Ø?gÊÇ"Óï<õ£gß×zs²”)§Ziš6Jœê½ŒLìœk•RŠbZ¥„£¨·ùïZ RJ!öó?-#fÃwÈù®nÑ‹í®PK w,±/E¸¨r§ .ˆGñT“᪊K .­ßõyG|Þ˜ïö€Ì×£UØÖŽîû$BûáÅ~´|' "<”ÆoC§lf‰»SÈ|u½O4s%”îNq ÊÄù\…ô¿÷×ÿõ„×#|ZjX¸}˜x]ïeñÃÒúƒ•çG¯­ÃË- >>µº§ðî€3Ô‡I=Ž`2•º¾Kã4•òý¨á`o)„Äý˜gƒqíëç3âaЇ‚½¹PßÍÂ]+4ìþ=¦Ó9 `-dïÅ2V×0ù2}Û'ÇŸú˜âä‡òn)ÀË’áçZ_žÛŠT`âýƒS~îõü;êíÞú¦³õz?o|‹ïCÀ¾º–¼Æ‡žæâ|¾oÚ»WĬëî»éó¬XMnÂEΫ~ n\äü”É;¥‘»º9> }©º‡…ÏN”`§¨\—3jò™§éMâ\ï­!,ç»|ˆ4Æ÷ý8«š.BÊ=)‚ï”æ7RàÎR/·8¿Ç4Ä-ÎŒñÜ™b±Åc9¾§9DÕ7ºqWÊN¡)·]í~ôç´pŵîu½.”ÇGÞ ÷ó£^5²S(B¾%‹"Ä—òÆ-Îo]~oÜâÌûS|}[«/>ÈÇöàÆù\ßVJÀÕl}¾ÊÙø\ïQgãsûh,?1Æj±Ž¯ÐKœŸ:pÚoÆ£öë[{ãçïxÈ.þFx,þ~m ´ SïZdåúÝ)ß¹á¹_µŸÍ`)ã¨yx,g-Ÿ2OŸ?ÖÑ3¸Á¹^O³Sfw¡šhØ).îðæJúZ8÷é}ïÚ•øßÇÊ‹/1·p| ¾ëÕWÕ·‚:)“ákÜÃ=úºé¤ç[:#ús´ô°7Ç©nŸ“9éáÐ'I¯=#vŒŽzˆ¨­í–£^{Öô0:b= ¡Í’³ÞNá½òb½ö¼]á¬×p#hcc= ¡ÝHmÆz0{’Ú(–I¯ËYÏb]_L1NÚ)Sû¢¶éš{)g=ƒ`î_œõ,tgŠË€˜ÕÜD:ëYLhÖí¬—‘›Åz‰X¬×"ô¯X/TÄz½O¬—õ2 ž³žý>X¯aGJ™œõ,¥{g½òi\%ho@%è·ävØÛ)Œ~#Ø;R öÌÅFøg°g)1Ò`¯á•$“¡üv7Åu´g)ìM§½ò]nS_RŒövÊ«‚) 2E¼nê Ú;òíYÉ„\§½F…ðß‚öŽ“6DøvÊ­=®Ÿåáh;ðYžé¥8ð)ÍMêO@E| ÷Üò}Y”¡¤.Y OœøŽ<†|–BpäkX*9s€|5Ç#¢”G2«;ò)†K–Bóž8 9¾Oß%¶ÅY°®nŸ$ˆ§>IyúÔH­2`vêýÀj§ÞðþavìøŽ>D;Sü]_èù¤ùûˆÊÒüEhÌTý­+žrµÙÞ(¥¢Ï Î¿¥ ´S#( ¥²sÕboß§êY i®úCíÔ‹Hõ§˜®¡úƒºº³dSýÝÍ}[Bõw7}~¤ú»ÛTPõw·WrªþðÔƒýî][1ªþPᔪ¿–£LqÕŸ ª?Xõ å(CoÂ4SýÝÀÖdAsa„Ï¿»êo¨_]õw#×CÕŸ%Ñ$Á£ž îþD0êþn\òHd¤ê ÖâDF×ýÝã‘LÔýÝø°d×ý¡=OÑý]süHÜ?oî¤û»ÇÒÀQ÷·¿.¡³sÝòP¿IÝ.w&mQ÷‡§¾JƒøôOÝ_*´©úƒ´TýÕWýÝî.ò7Âà®hj”¦Dø´}§ö¯4†Ú¿òµ÷Ô1¾´PsãMõv‡W…Á#Åug(‡oÕ¶§dí®ÿ»3‚)®ÿCÊ›0XsPÿ«¯«Â IÅ7ú¿"õ(§3Åõ¥ÿ¤ÿË?)Ãbí’!S\yVS\yVú”ú?´0àïò%6QÿWZóJ†Ì#º´šÔÿ•)Iý }‰ÁÔÿAòUað¨+e ‚ú• 1S¨`ÐÖÌA°kO]U¥ÄZÜù„+kŠ+‹”TÖ<” Öt)k]®CËÕYZ@<õÒ\ ˆ§&Ñε€©Å—AK­kÑ/½Âà‘õ€øR4¢Ÿk!ìKÐs-`}ŠÄ7]Z@HÐX—«ÒrfI XJ¦"0ç£t‰ªˆÞ×™C2D?PXf •5+¯y©ÅÔ"Ï{¨‘Ò ¢’!æÕù—:°ÔEu ù#xÉTÉM˜_u©k¹‹6]Ñbª±_¸* ÖÞ¡:ž•ë Du ®Pñï¸ô¼‹)®LÙŠ_ꋘÔbD1MX^)êQ.µæS"h£$}`é ê÷bå|Ü õx=¨¯¤B[4ÑaãÆnÒúB A¼ÙÜåS!X^`*K_˜F°¼¾ÔÖ׿fOA´X¼èµòBS#XòP%xPjR%X& u‚¹i”R)\Ž©ÄFX¤·¸5ŠWØ´‚×Ih±n3‡k1%ïÊ‚µ¦W2Ä V0·ÆÒ 9©¼FhÇ©,rR+x·¥%‘ZÁܨ»V°,ò¦,3€zÁ2g©¼ºÌƒ¤Ìͳô‚E‚Oļ¡^0úï„ÇNþsœ,ü÷BÙè_^~Òm‡Ú@D¾æÏÅ Ë]» *#$d(á:¶eà÷ íó© ü°0Á΋À];uð.“¾Ðu5…û>Âê?›ü öÛYÞ‰~ûïë4¶ aŠk?îR©ü .åyëa)VM>wJ—aÕ€xŠ2S XŸr5 ÜØ)4Õ€°Xå±ý°Róoÿ#N1- ~Ó¬Z@ì¡ì3OÛOövN¾·}4àž öGK¨DU2Å$4]—ö𤾠÷™Ç•€¶¥;,>ëSF}åÃ>XêñïÎLå b_6—:À"#u€xMzÕÚCœ?¢¾¬ZÔWªrìƒ#õšÔ~^ï ®DB¥>B[S×¢d‡I`ºnYòRXó8ô•Ž ô¡-ä0g¾ì‡¥öwùPŠŒ7—‡€D¾R®_­ú»ß">\ÇE K'¾"‰/ûÀ‡ÖøJë|)Ò“¨î€BRù‡Î#sQùWSœ÷J9Æ{¥1ä½Ò˜W¨1ï/÷jŠãzÜ«y÷Ê<#îÕÊ÷jƒ•Ê|¥î/碩þÊO×ü•n æ¯LVjþjŠkÍʪBÍ_)Øõ!Wü•,®÷C¤¾l?%"êe?Hï—ë—ëýò½Þ/e’Þ/éý²yB½ƒ@½èq¡^®Òû¡‹Fµ÷<Úãz¿Òâ[2Hr×û•ö™Þ¯H@Ô+m¡ÞÏœ—¨s½_.ÀÒûÕz\ïŸ ©ýð! ºÎ ÷¡õËoŠ´~¥&jýJ¶öÔzLé—µPçWó»Î¯ôu~¥õÔùÕǼœ1Òù¡*î©ó˶På‡®ãæŽ*¿ÒªürŠ»ÊÏ\ו_ÌgiüJë¨ñ+=G_­Ú5~Ù5TøÕb$@L2^y-¨ð+ÃF…_‘‰ ¿oc ÍêLáWºjH„˜TC"ÌŸ~õ©÷þée¢Â¯È@…ßgMø[0^jJ„˜UÔ÷å&Cú¾ÒêûÊûfú¾2pÔ÷aóu6Ÿå]Ÿ!kr]Ù‘ÂM\ÔD}_™Ô÷–dˆö¬›¸÷0ú,ÃI}_éRÓ÷•Þ¢¾/ç Õ}µ"‰ vUY)–ê¾2RT÷•ª¨î+s‹ê¾šg ʼnýH„“ê¾|cLÛW‹}ïŸVn^é™G"„˜ï/"PÛWÆŽÚ¾2o¨í+uQÛ—ë•}E¦WÄBý>­Jdº¾ú€ëúJ'P×WÖêúÊœ‘ßo´äSócÜ„wÜyü±Óð±ÎúAzø.‘Òh4‰û h ja ˆõ^cž¬§˜ÉzЦ–¬ÇÐ$‰z"âo…õpìŲž®FJÖÓ-$Éz3½óÈzÒ’”–Lv‰zº‘!Qoé8&PáÒ£Olfîêà·SdZ´‡’”FZ²`Y+°‡h)UÉWéU°/5²›`5 6àýVl>?xº*I{ïÐŽP´À+؃!õd Ûÿ…™å/´*Ú{—º›&ŸH9ýû*ɉöºŒiò™_Ñž˜À,>ëŸÅJ±÷ Ø‹±h/Þཤ§ ½¡³Z|ÆŠZaÛò€½Î| {­º÷"Ÿï±¯‘Š5jïi°D…é,}z‚ö¦”aA{“#´÷ê$"p/„¤¹gé>á\ø”p/Ìlƒ÷ùîÝḸGCJ5?2X/z®ÀÞáÜW"Ö»Ãù3`/lö²`’Ò}ý¨¬W­‚õŠb¯@9/ æÝa³+Î+)â¼1q©Iuâ¼hHp^Ô-ÌK8dëï¡¥.0/:Z½ëbrÞ-W@jõðŒ4v®ÕCÇÑÇð“áûG W‰Z½"¦H7—3kõÊ õJ‹‰ªÐTÔ«›{ÓêeßH«—-–V>|Ƶz˜DÒþ,C¢^>EÔ+O¹V/ß®D½„H×êá©u¢ 樻Äu­^Žn ^Ö¨—xèZ½ÍD½„LÁjµï´—7 +ÄŠ@Téåü”J¯4†*½ÒåNz؆ǾÂÈTéÅë$^©˜½\¥ÑËù¨ï)zúI€OÊ›–¤Äo°^ô 5zå)jô,ä˜'˜Yu—1¬RèeOQ¡—‹f(ôÊS®ÐËeQ ½2ñ¨ÐÄ8ýûòàL ½ÒTè]¶wÿ[a=]JI}^-D"ÄÛ$}^,·Òç•7…ú¼ëBéóbá Öƒ¦õTèåä£B/×°Pè]r5’B¯L>*ôŠà¦ÐËï›zšõ"½Z*óJ‡K™§ÃMéòÊ ¦.¯Œ6uy¹èI—‡o¢¨NÍïá…GÎËæS——òJ¯P•—Ÿ}©òjÕ’ F€ª¼\o¥Ê+# UÞ݃Ø\•Wú›ª¼ì›À¼xI»¬L×ä•ß®É+"ç…Dˆ>%B488/Îõ`¥Ï¥Éƒ¦'óB*òjU!«2â4ÛyeŠP‘WÖ4)òrBP‘WJ¥"¯LˆO\?9øÅ‚ð;¡­SyãÈqF˜šÚÄÉx³kºñflÒd¼Ù¦,á¶e¤ç7»|ÿe»9èø¦›ó #Lšn†.7L7ñ#j¹éæµnm,hº‰<ÑuÄp|ªú®Úå™é& -¾Ãt_øÃ“¯ïMêªÁÛYFhÕ( ·BZnî èŠt–…¸æv›Y,Í6÷¾6L;Ýlso§T ëˆ Më5³Ú¼àøZ¬6Qµ(´ÚÄöD¡bÜjA+oñ›¯O«K}—ÒjòÌêÄgOÉF“ê¯Y@÷„Ÿ$6Kƒ¥¾{f˜qº諾{KHÊ»,S<÷|\Qd³™ ¡É&¢­­p.LFBy—Šç²7ÅsëÓùm6-67Ëq›ÍR¹ y„sY³pî™r£Î=q¾"œËz„sQp®<$Vy(;B8—¦ÔÂ9„â9¶Ô&>öC0÷Ü?NœËν·[8—µˆçv-?ñ\J$ž+)lÎñ\ô¸xNÍ%Ì¥4Îsï%ßD]v6½öŠÞ+4wÉf¡ÀéÐܱXá\¸ˆν‚E<ÇGE§Ð0Ç RxE3Ì>³`e=ã„qQ¢ôu°Š©žzµY¸‚zĸR±gùã2%ZµK€ØÂÆeŠ#P|Lÿãb] Œ‹¹§&(®d! ‰p1d˜™³-.– fæ;F„‹ŽËm Ü’Ÿº 3ë3D¸ò”šÏ¥1v142P¬,që Å !.»N÷Ü2)Äá,4!.?Ld¸òg*»ÿ„¸øòÄ¥Ež .>;q¸µõ„8-6²ÊÌ5YV™H¡ašn?$"ÃÅÇ–k}@\|9âJM$ è1Üsi£'†ÛѶN Wòü"‚FO'Ãázk¢nu Ó(³”ì—"âbG[—€¸ÒBÐÎê9ßð”šÜ*£IƒK‰ Ò×ɨ)m2‡¼Ô„p»Ü§úçY1ò¬3„K©…pÚYÄÁÞÔþ˜E‚¸|1DqØŽÐ’œ ¸KQ\I¡ÑA\¥ ®TµÎîÅ!\:K‘¶® ü$Þ1\–º:™¢Ãå$Ãå«+†ÃíÀ‡9æ…ësª®®¶ïIM—TqO«£/†+…¸g^Q/‹ábï ‡ë–i3IÊù*†‹ª„pð6¨ WåÃÁçäÑ’³Æ.×dG¸œCB¸ØŒÂ!¾qD8\{DëLµ?ºWʺÐäÂéíªq«Û¼LÍ“!Q¢q=5n5óÔ¸Õ?eÊÇ2nõ¯Oý‰¸Õüü”r#¥D‰fZ„UB 6½QÆte¥(¥Ô¢<­Å„ZÔhw¡H«”RÓ²(%üÇǯ6d\ÿRüjØ7ÿ¿ú×iÕf3U[ ìû{³Èbø¹TVF¦VY52µÊÊ\*«æbY%25Ë:"S³¬’‹e¹TVĦVQ%6µJŠ<*¨äQ9™ZÕÈÔ*)s©¨šK/]F¦fYGüj½«™‹eý+ñ«oÄ–ÿcƯþ«ç_^ g­üëï¿0çúùïËÏ%ýóñ«íX«ýÿ+~õû{ñ«ÿý¿ƒøÕmÞ´ó˜Ø¹ø 8ÜWÑwMmv |7ù ß$c»³qH™v¦†+§Ü£µÍeÛ3ì^o¥Øs´çõ”Ç6˜ø~]Lym†íà7ù³ýÙºyJØÖeÛ3ûè-O¹m{VªZ¾­¯q˹Qk7æiûì¶Ænî3d¯ßÖ´ÝÙ3¥vlkÙ©ÚÓîSvŠíΞuQ¹§µí΃mò)ñÕ>>å¼×M#Ÿö˜B·» ™bA;PÜÕ®YS‘ÂÛHwJ·íYÍc2À”Š¿]œ²¸ «¡©HyD2;Åvhï†Ý—yÛ¡½h¸÷óú-_çFÚÃÅ!ÏG•…‚ƒ ûëÌz)Ôë¢_ûmÓž¢²Yx³-Õw+@BCð­ïLÙ»Ú‡™Ég\†#ÅdÀ='Ÿyìt ÷8¹áLƒ8)²3nïg§kHqšÙ í÷+¼}oRìt ×>9&ûÍm;e(r»_Âæ)å ;£Âùûô›vÂöu2Øo×…ß¾öo;aC _¡2Œ‹ª ³0ê^Óbû¾å)‹°b‡BjÏ[ïcÓ{L¤Èïª_ÍÙ>¼BÌCúËSœý1¥ ªË¼_¯k2ÁªPÕÍ‚~9ŠùÉåNH°¢×Û¾©ûø³7EȪÑ~ø0øùKߟlj(¼»ù„A¨)û:ó {Ž®¸)”AØNqpm ó¬÷¥xX΃gšLçúýÚa[-÷[>TrØëí²Ã6œ:ÜõF°X0¥uO‘ÝXov ä~êãÔ¶ÝÚòr–<íÀ «3{y/‰&ÕÒâÖeX+Úc2<äõ—œE¿„L¬°,¤*dZ4s³8¬Ý õwao8(À§Žè`É_¬÷açU¥ê>í¼ æ~ŸRìÀ )œ}Ù›]QÊ”ÇÜj]„ëMßÿGGÝlÏ=™öÙç ù×G³Ó¶oïDüܤcÿ0޶µþáYKl}ȘvVõÙ²d ëõy³l<æ]c1ïòwGv‘ûS¹¼·ý[اÚÿ’Çû4 ¬uÓÍ”Ö}ÞÅ\½ù u¾¤sܾ¬xh^>F1'% }²¿·îƒ}>/_ó._^ÿïAœ¾Æ½<èûËŒ rSì‹䂱(®ó„Þ<Á;ÁIÖÖ.•9/_â…]óó—¦kÔ–ÍÙ:‹ÍÙ[¢«ùÎ콞ɳQ€ê¹ì  wÂù‡°ïÏò±à£|Ÿ9Ø~¦²а÷^ì†gÚN×¹.&|ç—ho)l#ôí}<ߵ籓6TÅú‘úêõ‡"dÜšüb"¨R×¢³¿ÊçïÞ\¨GošÖná´“Ñ1 WÅÑÕ|­´:Y‰øÓ1¬{O³« {»™—ö耽½½WsžÅö—°gsîwöì¢ø¦7‰‡]ñïq“øûõ8ìí§t7a¯V¥=ߘ“än·¨Òµœ¢½â™l´g–üi÷:Î…N7‰ŸÚþöº˜8ã°×  ~+ìµoÞ"QoœÖ‰õ„Ò ÖÛ›{†!ëO²ÞÞî_" g½†êcЉuË¥áVAÖ³ $ g½âAÖÛ5iƒNÖ+¦Çd=ÓJˆÚ$ƒ6·d½ 7@Ô³‚…q†zÅÕ‚¨gŽäÿ×n×  ¢^K~¢^úôŠI¯8VôZÄ, èµ R@Ð+å~ |ŠÈyÅ4Vœ—¦Èä¼b6nœwTdœ—>7ìúùòóÒöT˜—Nó¼´&æeU¤¼â BÊ+æé¤¼b*-ÌKŸhǼp;奜(/+ye yÅÃŒ—®`d¼šÐÛiœ,ÄK\!^é†[í—Y,¯x9â¥D$¼Zì·ä§Î^Xv ðÊðÒ¸V€—f¥¼ÚxÅ(^€W:˜€—úxEj¼´¥ॳ‚/mQDxé$Â+õtI)ãþiâ‘ðJOðJ{HxiÃ"ÂKû'¼2éðr”Hx¥[Hxé$È+bòJS†y ¯t !/G›WÆ–WúWF{|ô½!CI/“€—¶@¼ô’à•ÙLÂ+B“ðòõ›j½¼x¥i$¼´Åá•^ â•â•Æ,‰ÃJÄËa#â•!!啿‘òÒÞJ”§®"╎Yj¶å¥=¼ºˆWçˆgßQ_ÁñJ½D¼"2/,ÎExiƒ,Â+"ñjÕëÕ )ůÌÃGȬKˆWšCÄ+ÃOÄK hG¼Ò½D¼šâˆWZüJ†ýW2Ä !â•Q ãi˜xé!À+¯ß'b*ðŠ¼ÒŠïb Þe·ˆïRjñ]Nñ]©ü‡7ø.ÇP|Wz|Wë~ø¿à•ι%‚ ’è.ç è.»—t à®äp¸+-1¸ ¯±]TºÞŸ¤#Ø•Î'Ø•>!Ø•<»lHWÛcòíÂ™êŸ Iª<ÄSkIwØ„Âz¯»^*òòí”"¯ìqÉv "Ø.‹!ÚÅ&—j¼ÜCJ—oéñr× =^.mÒã¥Ûˆëñríp=^Ž£ôx9 ÒãåÜ•/FAj¼py‘/祴xÈB=µxù²I‹W/ª3©Å+åP‹wÝŠàîZ<ü>È®8½H‹_5·ª’ïº?õ µxî.ôWâ]ˆÀÍb>zÊð&Xéð@ý×+ è'Já Q…W²¸ ObI$ðcûq_Ó¡Á«Å>\¢XRQ¶ÖõwxÆç2ÕwEBªï.DétÕ0Õw¥ë¨¾C©‰uá¡'õ]iž©ïj¹®¾r=‡ú®>C tÉs`<N¬‹‡ëpC2S\{‡Ê¹Ñ¹~AÚ»l ´wÙçÁuj±®TM®+‘ëp3 ¡Yì-¢1ÔÞÕ<­kæŠvÇSD»\h—BÝ)ÂuhïbRìJ±D»Zd—YDvM—ÞÚÅC"»¬Xd—Í¥ê.›BÍ]é]©;Û/ˆüI»RÁ.ŸØ•‚]>%°‹—2À® u%‡Ú¯/Yp]b¸.$Ö•„ïü®&ØÝ?éîJ ìr>ˆì²*ï²*»,D`Îå vúÐ&ÙµP±‘вkDv%É®ä!Ù•æ¥jOŠÀÚEv%å> v%Á® Á.«ØeÕ»ØË$ØÅ(ì´#N´Ë,D»È"²‹8Av™¥…Ÿð¬`—"ÛE=Îvvn|‰öbGÛ•ržðVcHG9„w1–w%Ex¼qý,Ãïã]¡?²QÒ†ð®TC¼+O=?¹:ÞöÞ…/yå;6W|bße9â»’güÜeSîà#‘f;òßþÊB¶+­ ¶SžÀ»¨JxWHë'DJÀ+ìõ„WjšgК€¼„@2^ŽRa³<ä¡þÓÑ®>ôÍS €]­x©ýúÌ쎔ޔrU°«ÅÎëÜ-ìj–õž[‚]Íò®Ÿr®«åJc—yvGŽÖ%’rH€GÊûGdʼ$’Ê™Üežõžû‚Ý‘'eP9’á¡åÁ®æq°;ò´³5Nvµ&'»#dÈRfìâ®JvGž‡»¸,ù]?IåhWëú$CäùîØÅõ weWipW[ãpw¤îJ¹ó“T•펇žç'¡œíŽ<Ÿïƒp(SUw%Ù.«"Ú™ íŽGÆ]+&Û•€½d»£âõj·­3nûÌÍ£êðvÊ6œ´Ï\7.ˆ÷Þ5ÂbS¼×(y/ ÀTÈMö™•iŸ©=Að^Á7ç=…½ðUW¼ãÏ¢½†–½LïM)õ„{K>k{‹W¶%î=?ª#ž%е,pï g=áÞ :oþGÜ{Cë'VúÔ·{ŸÌ÷2q¯_¼ý*p/S„{%…"”ÒÒ~‘ÈÿÂ=Ü+Y ÷2%Àº§iff!*õtå#*eÒ^fíEÁ^&üÒz±–6’A©”KÖ+yŒõêo_#zø ~)€,>%@ûq¢^¨WRÄz]v3ÁzŽÓƒõ–N9ƒõ8‹õ4õ4C„zYˆPOS3Qï‘Q¨H/Š ÒSν_½û¢og€N Y AOQÁyZ“ónA ΋Ã*r^ùMÎ+¥ópGŽ"ç] x˜— d¤L #áÜÎ+äe2Þ¥mÁx8DäCl)æaŽ–†™µãÄxQ/ âá|–$–Íç·/+ãe·ˆñjÊG‘ü'G•'à•”·>`|´;¤twÉw8认ï²w—¦ ð.:Et—}/¼ƒq™„t)ŽcÞÕT·;Ë"/@—@Dx07¢ & éjapIBÚ½'âá#M9"^v¯ä‘™" B&1Þ5e2JÄË"Þ•™¾ˆ’©ÔüLQóU‚ø®d!Á̆Åð¢£Äw°®š»£5>óŽ®¶Ÿ¤£Ì#‹ö9àÁPè¼Ì Ô¸'ÛÿT‹Ì3åûñS¹Ä»lœð.EÞeUÙþ÷¤»,Ft—ítîÊ#„»œï‚»|HÄtÛåË*¶Ë %¶Ë7@l—o¨ØaûˆS’ Ö±]Öål{h–B¶Ë¥Pl—}%¶+u§ ÷ w9‚»ìOÁ]Ôp%ÜÉÁNè %ÚÅJ´‹Ž ´ ‘íbòÚ•§Ô| hhãlãlCpÃp]E¸ËÖî¢ëîJ§;LAt—-&Þ½#Ta»ìÏ2øO‚Qv°Ø.»Ol§Gv%ƒ]ªÀNêôݪÓûP—¢ê²óuÙRA],uúJÿ^Pi›]gû&¼uDTîé\·¿ïWD7qÌŽp„37Àìh7Ï#©t8ˆTxÛ__¹Z+’Ê€ÂyÜ„Ñb$VxÛ)#ÜäÜOÑ`‘&˜d<Ì1B3ÁCÛ7ÁÄ[aRÜ€q Ù.Ësàvùª®Û)¢oÙ`ÖJ€(v|Š¬Ô¹ #òÐêŽF˜!«Ân§„B‰F˜c… ¡aŽ•ÔGV¡æ‘bJüãZÖäF˜HÔ¹f}Ê­0ol~HZ.¶áWE¸ò©i‡‰Eá=B©`¯N\¤!æ}ß3ÄDMç\Ô´”b2 ”»:Øí< "KLDuu7~™bÞø–Ò´Ñm1oà!Ím1oÓB’2¤T´ÅD Å !ç¬J»ýÔ#£`³Å<~.UÓÌù$Ã#OCÙb•ì0Æ„ ½’ÜNYaDéÆ˜èÑ3”Ê:¦P†ò1ááGóL·dLÉeŒ‰‘yæú¼5´Ï£5&> Œõ@kL”r±Tr¬d‰¾Pt·e¬)nYSh‰¯*ñέ11z<Ê•5fô ¬1k9nÍX¤rsLD|âo7ÇD‹ŸªµÛy^WÈu_‡=fÎ¥0ÈÄføpµ+ãIƒÌZ-2q“AÕÚU9›dÈr\†W¡IÌ"³¶…™x±ÉLn‘™32,2±†Ÿ™0¢gÈZd~w°Ms¶Ñ"³Ô.‹L87².šd–öÐ&3ÇÎm2•–žf҈裧Q¦‚E¦Qf¶WF™ˆÈzT)óQF™ä#  Fî>}í²52Ë„ËK ³Ì”Rf™%Ë剕Y&œqi@I³FX’‘ÀhÖˆ=­.i—‰‰ZÕwµ}²ÌŒ¼aš™óQ¦™¸`‚yhØga¦Ð4sçá-ÓÌ\;Ü43ç„L3ña9=î²}2ÍÄ5›G`HaTÜ6óSp®0ÎÜåÐÎNÆ™ù¾È8¦HU‰·KþBÏGËÆl³Œ3s$Ü:3g—¬3³nYg"8.Ÿ¡ 9e‰½RUâÕ^—ufi ­3³wd™}*ëÌ”JÖ™9Ûe‰˜w‰yµodž™­‘yfΙgæ)óL\8ÈšhÝø*¨\˜g–öÑ>³´†ö™Ù§2Ð̹-ÍìAYhf›ÝB3[# ÍwÊ®ZÞwÙ>Yhæè……f˜!ËB3ç¤,4ã*†°Ð„+¿Ç‘…fÈšïàî2,4#l=-4£×i¢‰Ø"»ë\ÂD3Z&šˆ^Κ%Á<Õxö”è&ŽX@ÓJš8Æ›&šY»L4ß‹+˜h" |5ÑŒw*¬4S*Yi¾ äVš1Þa¦3)Ì4c|ÃL3.¯3Íì™i¦T2ÓDpD/GfšÙ_2ÓÄäåSf¦™},3Í-ÕÇ´Ó|yÐvšˆQ©¯NÙiÆ ;͈Çvš)¦L5Õà‡1|5´éµoCÍ<5õO™ò±ŒCýëS"õ¯Í‰”ñù(:3Á£çþÜþ8‚GGJ)ŠiY”Ž¢öòi)µ(O+E1¡µÚ´‡ÒqJ)E1-‹RÂQÔÁYÔ1.e þã£c¼kßûB×]õ; ?\þ‹ VÚß‹¤í~Ž8\3àäíïÅ×þ)PöïL´ï¾ÏøÁ¿ÓÁë3õÊL›%•ØVR ­’2J:Bi{I5ü5J:‚_³¤’‡%´YR†¿¶‚Jðk•9TL ¢ÍRJèk+¦¾V9™GA´ù~–À×(鎭y™yXÒ¿{<¦}ú06öŸXÑo ýyýþëßYŒk¦ü%øWbc¸ôßmlìÿØØÿþ{Ã6ã`ãÿùwÒ»¯{àëºÈ¢;òݳïà«Èav.;÷{½J1-ÁóÜÚ™!¬ÌoîØ‡!ò\µVØé!ªüçò3ÁÑæ} 矌zn-·ÿ ï5wj¯(¸¸Çyršÿ^šžá[‹yÝv4»¸ž—53îGhÙ)¶ñ]c̫۞ñi2 š×°=ãÚ¯“ïÉ&. ±@Ø/OP'öUÓƒeû¾wâ‚%¬n¸ø‚å¸o§ŸíÄn ·ük&N:°H¾RMN;9ýÍXÁÑçÝ.ož#óþm[Æ÷Vð¦y»vaIóáÝCëÇNóž¶g|³Ð[s/Û3¢ß®ÎÛúÑxq°œ×öŒ°¬jLq2èl.´ >!f»=0q„ÆÜ)Ÿ-óMñÇgkø€sØÏî±#åÄÀ[|ÛArÜ ájdÀÙ\Ʋ+Úãq‰o˜íõÐÊv!¦%|Yyÿãœ=ûå‘• zv¶'‰JñÀÊkp={cPâ‡`±_½ý .ékümûÅŽ»~K™v¸^EÛ}Ùa Nü¸hv`-E¾œ{YʧPs³v”¶^ÆÝë„ÇU~ÏiŽ›a•Åw'0ªòMZ™ƒd?ŒŽ¯,æ ÙSÒ&ÞÇZ¦>˜[Þ¨ðîì†8ÙMÿ¼v\ÄÆo>Æ‘3¬ùnn3÷{kƒ´÷‰ÎÁs¤æâ¹ÆNñ°ÊŸ\çælVÙOçî=—éã©òÜ ‚Lè4ç\šöaËãG߉ÅÄæã´Íù2²²¢àÍùydå®;Ȧ¬;"+ó©u{\â’ØÏå‘•#"õ|îˆio×8p%øb-zL‚wx¾¸Pà©QúwÚ1 –ÁΔiÇ€P·ruz"Õ#¸5sP„ì½çõØÊïElŸÏçÁ‰?ùù«jûÞÛã+?{¦-¾È#_ûù¶÷|y^¡ þNüÑ™r¾Óc¿ <4Ñöï,ö˜¿C=þ¾]YÈç«öË_t~Ž…ð­t5ù„Q÷c1Ág,7ý™É”?Ý1-=FIDçÇöR>N,m¯÷&züššK1@æî!HôjžÙÒQ×”…ï±½; ·¸. ðI7º.JðÑu¡D[ß&_Úuu¿eCÅ”aÇv¿Ùë)ÓŽÿ0?VnØ”î¬üé5çuÜØ½ÕXnZI¡¾Èwé‡uÛÕ‚¼Jùl˜š®/^·‰0×§ٺË)êÆºíób3âcÊœ¶Æá=óæáÂe[¯®z .¿þæÖNðùÿ<ÅD@Di¯{½ußœ8^‚Õn¯ì[­ÕšÇVþÔb55_ÁRV\9¸óä!§âjË#¿wót“¸Ê,ܵÌõÍ7~«}[9¢›¯ý9þÍâòs÷×8›Šñí[ï |‡mØÕ;ïÆx9qWVù’Š|õÉ»1d%±¿ÛÞø«sÅÙK±Ç%.O½¾÷¹t´¾pÙ2Ö¶ñPÀa¢v˜«{Ý­Çjèjœ5(@>Ñ^ßÎ)>êÝv>X©ó Ûù˜Rœ)Ó7oˆ~Í‚×yùÔNqr»¹ÆË ¨‚¡-\·l{T™×/\· ‘né ®[þ¼…|Ï÷·¿_ÍÒIº¢­¬é2<è>3lóó^Š »öÇØ¤Š èþ´ ß’J+¼ö÷Ä–‚RÎÛüA'økº ¸]}—íj®A“—µü4†|–9jÙöŒoßžeSµð-Æþíý"ƒ‹ðàn?oðrp%ñdÕË7@¯n¸Ü;9ÛÁzBO½Í÷ÙÏou4‚+Ù9‹ýŽÃŽTžÝž×OþdTlaž…¥¯˜÷( ¼0û„ûÀ<컎˜m×80W=»¢Pœ÷ u!é5\sçú’^³{™Ç8ÉBpS?à¤×^·.FW¾¹+»ì(môÈÐ\9vi$½¼oZ¨wÃaпƒD½4LêáÔåêÙͺÄNG=»¼–u9ê$Û㜄Ã{2Y¯ïfq÷OÖËk¥œõú’ªS¬‡ëboæp ý½˜â2àtÂ)Y»sÕä 4qæÁzxЏJÖ[XÖ[Ø[x Y7°*ÅYiݺd™¬gÚKn©õ  f¹„½Õy< Ö{`õB<$ëcÈm.Œ­ˆ`d½§)î–`o}úH‰öpZÁÊI{¦nõ§ˆ{¨‹[Ë.n4÷pa•Êî=MáÞ…{ÏþqÛEÜÃú{¸‡“nt‰{0¶ºYŽón=e_÷°¾¹1ªxïµëêÿ–¼‡Ø=—|y/—€¯ˆà³[¥ØÅ|¸W¥:ðáºt6…À.ÇŸÀ=¯Gú÷ƒ{ûó .ñ®GgU“¸„O !ËyO½ïÕ§œ÷Þno†{¦%qîùÞüoI{¸ú‹lGØ‹+#‚öâ.Ñ¢ÿs÷,ÚÛKÎCLSóûÏ´W9íµ FÚ»f`q/nè2Ü3ü#_ ÷bW¸7M÷ÊeAÄ=»y¦‘ÜÈ{º‚¸g¹NÜq€ñXu‘‘p/îÍíåÝ`¢½ÜáíÙ¦2Šöâ¾® ½¸ÒéïÐÞ«h™A{I¢½WñVƒöâj"âžpî%—ân«à=®Û„½xõ{qOQÐ^LìÅ"-Øû3-`/O‚ö†¾*A{2PMÚ{¹JÚS¨¸ =ìɉ{\µ÷º®3 Ü ÜSƒI{f„³ÒÞ@¸ëÀ=ЙÌi/['ÚCÿ_,ØhÏ0È·GÀíæ|ˆ°W)ö¬&n¡ö®ÁšÅzqáaÏfG¯°gó®WØ+ï$a/Ñž¬gƒr°ž ¿Š!ë]º ’¬‡9ŬgD.6P¯Â4Qoò "Q¯‰P„zÛ{fVB(Øû‚Ù~ñ¡ë˜sªõì^L!ê 5Ö3f_Šõâ6Öûóî±á%ëåÔì wؘfW…½Êë]Í—Í4aÏæéKŒôûªK8ìíö\Q—ÁžÍå·Ò^y ÷ìÔÒ_"âÞ¸Flþ÷*Ñ;ï•C4ò^=pÞ³Öpè÷Â2ròÊ€Û¦ØÊ§¨ä½G–“÷ìd‘§.?¬ßCù%ïÕr'eÀ ,%ePƒ¥Úbç={ª“÷`®¤¾pÞ³“ö¨óÞÎ3‚%ƒÎ˜É{µäEqÖî¼WǼg §§ßÀ•ð±Œ2”g$C´Øo7°5|µwøv]¢ Ð`O]­JàÛOJJï'døgbe“ù`4Öæûd…#ÍÞ¥ŸÆ{¸•†RRëE¬3òžY14 ó^‡£_Ç HW©öÅ“åPµ÷DÌ;ªö8§_·®–rÝ^G ñ­uý•€ˆ¯ß:˜ñÁN·Ä×^V&àƒÿÄ{èö"“ò!>ä¡~‚À7°5f‡¥‹]•Ãȧ– Öïa1Òoç½ *;Ô{XÂ8šRï5žV ÷æ‡èÒî5…ÜíÞuÙO²^i a…,៟nµZ7¶„;WO_ìÍOhDÖCתPg=„¬qT([½¥„=°=µ\„½½ñøQu{ûÜ5ÈzX´Ù d=,ÀÒÔ9ëA"sì-\–î?AJ¥ {ûCêA§=³1g§=rº½"#i¯HDÚ+u‘öö‡[ûiÒÞºåz-ÚËöV“Í«Ã>1ä­%ZD°·ãGˆõðucG=3€':9ê­&kV±š²D.@—}«X¯æqPÂq Ìaouë•ù`š=4WP€&ƒa±4çâCg¥…h6$2g=ôØï’P×Áz\ôç¬Wtòd=äá7ƒ¬·šŽÈz{ï$"ë­~Is÷ æ)§2Ñží˜B †Ü¸ˆ{Ö^}Ò^i qÍ}+îY1ï{˜Ô‡r¯Ã-QJCJãMÜ«å8-•&÷v)Óˆ´‡ÉIµi/o¦—r/GNʽFæ¡v¯)€x/ï-îݨÚËw_´·ú#!›c ؃ˆ=aÏì(ÆA{9E{«Ý¡€sÚ[P¢x›¿t0.Ø[øj´²(iX$g´gCÅioÜ8hoÍ'h" ]¤k¸·Ëh]Ž{µ¡7oŠÙ å†mUåž•C¾£Z¡¥ÚƒƒŒJqõXi›_Y­¤ÜËõLÀ‡š®¢ÜÃRzåÞÂ%ÜóaùõU^Ìçî; ä³W€S¿‡¦ÈW>1Òï¥]ô{eQ¿·°U º~‹u‰TðaO†5 _™ÍÔð¡óxB–RMPÅWZCŽäNgwRÅ·&Ïì¤á+ã4$BŒ?5|eæQÇ<³ßêÒA‚iøb5‚:¤¯_ôTðá›Å M^ÁÜ¢u/‹–~ƒ°*ïÙ7ýìñÄr®K]@è÷bÁ ý^¦ë÷âó ¾|Ÿ¨àÃD’Ê"Ì {»š&©©Ýƒ$DWî•÷Ê=<ä Ôí¡iŸRÜè’¢þQÐlá]H\ðî¹´»¾›+m9ñšÖü@éô>©áñpˆç <¼rí$8(ïÛ3í=l8Ñâ^µzU(D&RêᘜuS%r;çA{ë˜J½ÐJ©ÕH§:êÔééž“ÐéÅd ¥^Z@J©·ù—‚ļ´‰”N¯¿?ëôÂ^›J=X {!®Ô»à4”zÅhRö›¸I&œ1S«º)iõà×BM8ñòœ÷U˜G6œwP(8±«:{¯®Ú¦'´L44}ÅÞ’ÍS·Wžn/ŒPeÈ‹JêöÂöµK‚KRÊóÕ¥šaÈ9;Ç_vœ¡V%敚ˆyhß'¬»|V]Â>×ìÝO@CR±•f/L„y0o­†œ¦Ž]‡!ç÷ðºQQ^z>ˆò>ËAy؉3)ïÃBÜ÷iæ;Œòjêõrƒ)Žy˜Ðœôļòòólµ90¯¨ôÉyEi.½^ZH“óbáµ^8;óÒ)H˜‡i#lf04Rëõ[-µ^ZŠK­—*X’V„ŸÔz° ªj½j µ^¾td½2Ñ¥Ök·ƒÿ™Ú2å|±k9Ôz3@ëÏ{ì! ˆ 7É}q‰’À»Ʀ -'ª”I(m9­²åÄçƒWmÑ–U´p#øõÑåî»pá?ûî½¹ägK¦œû+*åM9qÐHœL9ÜØW‰Ø‡ðÏ}z’Ô³!À÷iÊùézLaŸyYn{Ø;qK列8¥¦œ¢w˜r"T’ù\зp? ·ôá¶wEÉ~ã’%s€v/ÌCt½õ® üGZ;§¦ý†õ¤SÓ ëIjàL³w,„fo>:øfy²Ü¯2§"÷>+rÛ»¢)4{S‘à~ÕÃŽª½.›*rrã$Í^¶XŽ{8ƒ,ÜWtOrÜ+Ï=(.©ûx´¥S4q_ž1¸!'vÒųè¤ÜK7CbŸWb •{+F_ʽ¦€!¾Ølõáëu(÷ OJ¹7µe—nï ã>éöBän{a¢äÌ÷ }öÅ|¦*kqè{îÐôúž9BIÝ^jeúÌ)Gxl?Ô^òäûüÀáÒL$õAjâ ©ïé1£¥Ü{´©w¿½°6õÁuà=¨ïQü >‹Rƒú°–³ÁÄ>˜å‡›ž;î…ÅL`_ø^û`¤Ë7…ØW%ˆ}ÅRZê½·Úqb÷{èöÒ}CØwž7ûðÀÊ¡ 1 iJMì{ú›)Ÿ‹Vï⾄|rŸÑ¡Î©éY2£øÁÏ‚ ,ÁïéqFŽ{ãÐîYK>CtÍüZ“ØœšÊ`üžñ Òš3L¯‚üÂvšà#.+_Šð®{et ~8ûU7æ”mÀsê=\C~i¿.ðÃáËÇ<Ôa›ä Æ}öî^$6úî }ŒÂw/܆~/TR,˜ì kSOpn‚]üLJ̚óQ̼ ¿0§ò Îú½öB¿÷£bVä—GC¡àKíÉ]‡‚Qð„Ž~0Óé¤Ca®p¶2ô›Ø™&úUo"¡ŸŽ;‚ü‚e~qD"õÞÇ7©G5ôŽ’9ç^`¢¾ûS©®ÜÑÄw(÷,êÚé¹—$nÐ÷Î7¬;m7»Ò3¾oï :Bß%Aß ã9Opå^ÆUç½ÌBsÎ¥Y|·67Á|ý ¼¤ï^Nx9ï}<¨•óÞˆùí@ù`xC‡:S?ùâNš½2-å¼—}'cÎýQï‡ó^}ŠÀ'>á¼÷}éÎçÐwPÿ™óÞ£ }ï 4“ RZôÁ­ñ„>Õ& }Mš02’9½Å|Kñã’ùø™”j/½äÅ|8šãÚ@æK×g> §ˆ˜ïQ8C©öŠ­7U{@q¾Ãb>ùDH¹8:,9m Ïêº7Ëî©–œæ71+òÙ©Ê%õÞÏáµS¥÷›Ï=ö’h‡(|„4ªô^ÆÚá Øs«M¼j µN«M¬… TG^ÃgÆ\¥‡…AéÒð¶ª^z›)ÞˆœâdTî< íæ#ël±]ñµ"Ûåf6²<rT‡…†Ð®øW( Ö§íʱ:ÑûšçŒÈ2@†d• r²+g"Nv%Ü É.'Rd¡¸$ÙG#’vröc4“tV!Ùa¢«î·+¬µ Èr)ºwdÉ`% È’ÁJnÈE¥‡°j²YŽ·" Ë ‹\»r„C²³” v¶dr«¤€,ßËmM¾óÞ¸Ò4(¸óð³oêÃM7TÅׯÞÂÀHМÜ×Çàù–tðY8ý—OÁTUÍæfXPWÙªbåú8¬rÂMÏlhÞC£—ÜÝoY0)¡YŠYO*¤çEÕƒE~6@(æ%IàÊÃoXƒ»ŸV™mËžfи>ÌLu›•óù)‰Y^ydoq^w9ÏŽæ-.›ìÜÏ-í óãû«ÛiµÇ)'bËÄj®î?¨<¢Óã×v28œò„ï‡ æpç]ðÕ‡šúG*µ+‘¬Ge`×õZ0®^l6M†˜#†åXn½z73?´Ý‘‹=×x|αÜ8Ñ›˜ùºì÷žF3¸ˆŒŒu/‹ff9ÏÝB6Ù7ßM;Ü@D¦Â‡ßëy\™|o .“’!Á.?FwvÚu6DéE"sù²Þ¼ T ”÷rËhæ¼·¢{Ø >µumYl\ñDc¾†³9Ô†zˆ9‚ekÀIÕK†H*.<ü˜â×t]æïUdì[{™3e‹ÐFí™Þíšß-eKýÌMפâíàÓ"‰âò-]Y¶Ì¹æYv­aÞŽ¸)&§Nб½y»KÎ«ì „­lŠl0lPpG§«ünÓEZ Õ‚ÍÂ"Xg¹jMo³¬k{„Ì«pØnÏ‚í(yßfÅèºÃe³E•·);ÿå2»_6»#7 ñbàθábÊrÔ 0pY\Ž`wA”®˜ ŸlÅzçýཹü!™¨áV&.%VS˜œ- yˆ;Û¤¬ µ»p'ñúŽË×ï+B)]¦{*]X öŹÂÐæ)<‘ƒ · Î3ܬüù<‘*Ý<‡kÉË‚ÙÌQÔ¡¶€_ò+‚%ñ¤œ<`}ÍLǾ\<ЂH×¼üûÜÉ¡·¿O(¸ñp¯¸öé÷ó6|¢í³WÅá¯/ü2ýŒð1²‚ù®Vþ|.ùÈ R¦-à°v²„Çl¶qáÏžq+ñÞëMÛ«P¯Ç23©ü¼È¬Ö°ËˆÈ¯°ï²üRÜt`þ8Iý|_èkúS~ò‰o´­àñæám+xLÛ×î‡.Ék‰;ßïdè|‡uiç’k‰m;R`éd‹ø'ó» £yš…/ƒÅ3“2X¸òð{kgà+}-Ê8»JbÔi€¯të.ºžÁ' ß>®*øì‚èÒ_ÐúV‰—\7D•Ã:Þ_^ÚÐp/1Öñ¾h£Ò ‹Ã:^Rº™M¦Xí²û¡­îÛ¦ÉÚôêþвS"Ü8é›ÄfÆIËû«{Š«a,Åôi{÷r–çùÌÞÝÆÆ>FÍ.&¶ºx‹LÃÅĶ!}x5{ÃÅÄXȰjyžn°û‚nuábâ×êb؆k?ލ} `º4_i,äø4/ä±ie=z{EøÛ,ÃÙn÷ -Oá^âÑjWà^b,ä%Oë¾éqÚp/ñ²º†kT®³½ùÛü{Õp/ñ;<åör¦]PK^fdˆëK}zµf7DãÎS_ >Ô÷ë›ïõæ÷î–<¸š+9‚,›2¹°’÷N„{{[ɆæiÝnè©Å¸^×Háö,п>…n&~í)ÞRàÇA”óó”Çlnp!¬¯ÿqˆ„r?ûsQ¼ƒ¡ÀØ¢% Î!~1΢ADu2< âø|®ƒ«# ½e! ßlù Âüý~* >{Ï´LT° Â.Ûk%)=NœDAO{„‚ÐéN›ÆBA,»Ýæ’Py¯¥á®zÛ‹(Ó¨Ç6©BAdÝ«¢ LÊ^S_ 0Ϫ(Ç·Û6LBA»¡Ý©S(7!ë¢ t±Í9T(-¿s(QÞg6àA‚—ë‰?9ßbÁ²w:@+¡õ„@ {a‚¡¯5£¨ A(3l DÝ6Ù‚¡gµÍF ¬ÅmÒ ÚÝ«H „òÑÎ…í¦sÃ1±`œ Z Ë#„zצEÀ °Û´„¢î>`k¬í0/…& ¼ fƒ¡ô„H4åü „~È5e"A;ï;Húµ÷ Áû–S„P]êZ/¡ ®·ì Ú5´ö š ž?E´k|=YpKÆ}ƒXZBg Âà­›ÖƒP“ûžE0¸Ë Äaè}Ð ò^d?§Á”\4xc£ï­! Zö‹cÚÞ·âTˆíÂv§?ò`Žyï(%´kÉ„vã¼# D÷ûÔbö;h ïð„–<ÂOñ Æj<¸›NN–<äÁÝRÊ)„±Ä`\îxH¼G ZÈç8ò ÆÅ"˜ÂiU8˜ã"Ü W¼âà}Óä^4xwîéƒ9VM„e¥"„: æÛ!,yíºiùzÙâm„AìÎâ¦1ÛClér‚4ˆÑUà§Á{T: â-£³ioÑ”4¸§aØÖ8 ¢*9(8 ¦´+:—í!`AJh# "¬ÅKÒ l»´êFƒ»s30‘á Ý½Í³ŽƒÈ爃¶U­8ˆ}©Ï}á`f¢9>ý„ƒ¹xómæ 1I}-b̦8æ æ ‹ï![<ñàMˆ# "ƒƒÊ@¼0…xs„Ø¿“߈ñ&‹÷«Èv‘óE–RH˜Vó À,F˜ ¼(SÏûVˆ1²îbæy2 røI€sܧ´+‚/¨bÀ’‡ ˜ƒFÌy'D0æ]0 Vá)d@ä±…90Æ^ U–,d@hÒ/† h·‘úSdÀ{ò¢Ÿ`À’‡ ¸×_Aƒ12ó`@äñ" až?DÜ+“˜Æ$,y€€Ù! 2vO!b>‰€)“0#Ü‹âOxë¢@ÀlŒSɹVˆr^O!¢=dB'@dql$ ÏqÏùo/¬’#øÏBK{ ùÏοþÃèZáß -Fÿ­àºÏO ˆxÆ™[ø—=,üËrI% é/ç°è/¾|ÅL‚/ï?Ò;Õ{¹X³ª(˜%Ôa ¼¤€]U¯ ›¸"@¸ÝfU.Ä5/ÝlØ„€ˆŽÔœúvš¬ÿ T¶äˆá—ÐŒsÄ€ðb™®v$~v¥”=E,¨FDü€þu .ñ¼Fe@3¶µ­|2`³¾* ¸‹aŠoàªê@<ŪȀð_e@XÀšÅ»nó;pOï«ê@øÿÌ»ªaék&Ÿ‚À/‘“!0[CÄE*>Ü‚@85]†÷‚@+ÇMB jzìE"V̲wB¯’öUu`Ö%„çám â©×j–§hÏXU!ˆåˆ·œ'Ö‡Œ‘£»¹80Ÿ!æ›'Ä üŠ€å!'ÀR °t °ãX†ŽX v, €¥g€9ÜãZUBò_é'ò_$ò_H ºaQ³çXËq%ÖÁòõ#–‹‚¥ ‚ÙÁK XSñ7'‚`VE¬9fû‚õ!Á|e‚µÁšÇA0W`ö²@sûö§H‚Ù"ÁRI0_|‘`i3H0fŽ@°¶ÅAïï ,:Ö<‚e‚Y09°4…X²8–šˆµ\ÇÀòc`ér`ÉbXšK̨80¾mÂÀœùâÀXŠ…¥»Ë !–ÆóMÖ<ÎùÆ‹˨‘ó­ûñ¾Å~¸èTØïÃnUþÁ‰sØY»Øîø·£ÙÐzWíßk‡KÁ}kÑé"¹¤aÌ6›‘"Ÿ'÷¥ÎN܇˜pß8tк)©tï~CÖ¡ûƒç™S”tÐTÙi.¹wv»wÂëþÞw@$÷!Å¡SÜèiÖq_I!÷•§œûl!6R÷á!ßÝ‹û2Wå¾Ì#î{ßÏ((ÁÁ^§iQ~Hqr&ø•‚_yˆà‡”·Wí_ÉCð+)¿Ò‚_æø¥X?<å¿’‡à—=(ðË.ø½¯#žCþîªiA_y‚ÐWJ%ô!¥›ý° /óú2 )סüÃ\reº ¯¦8ôå|ôÕºúj‡¾Z»Cfòºª!(žzzUþ•’ûÊSÎ}9ÙÅ}õ!羚âÜWšLðËK䇔×}I~5“_Mqò+¢“üJ“I~EP’_©‹äWóù•$ùÕ'¿ú“ß‘bäWSýÊ;úÕÖ8ú©È~¥OÉ~¥`²_ÍãðWó8üÕ’þJsGŠÁ_Mqú«%;þÕ<Ž¥®aÍ#ÿ•BÈ5Åù¯ 'ù¯Œù¯–ìüWËqþ«)Î¥Áä¿2MÉeº“ÿÊ`‘ÿŠ˜Î¥*ò_Mqþ«9ÿÕ‚ÿêSÎEPç¿úó_é/`)†XSœKsH€¥wH€5Å °ÔN, $–>%Ö'ÀÒËDÀZ—1`i2°TE¬)dÀøÂÂ6€æžÎ€õ)ƒÀ2¿µr‡À"9!°æq¬å8–<„ÀšâXšC,åËhKk9¥—kåNõ!§ÀZ¹S`©ŠXú”XH ,%“KɤÀZ²S`i!)ðHù|-Ï’kŠQ`}È)0+Ö§ÀlŽ(°æq ̪HÙÉ¢ÀúS`-Ø)°æq ¬å8Ö§œËS¤À|µD5Å)°>åXSœs[$ ¬)›³G…µÇÀšâXãXúXSœËSäÀœ^ÁÒ‚`© XËq¬yœk톂õ!GÁ22DÁÜ2ŠKsÈ‚¾í–jKK‚5‹ƒ`i A°>å XŸrÌ•*|°£÷þ‰`à¡D4‚ñþ7UF‚Bã47•Ihšw:"ÐÐ4…¨ Ì3Üo`h!ÄÍ~#lB±•m†@}ûÒöÉ¡ 0„g÷‚aPC€aâ¦ÀpáÖ#1)ªÜõvÃõ3*ý;F¡°{µ„° í„ÒÐ^ç Õ&´-§@êa´â¶¥Ô¦Aªô:ŒHu`çqP¨aÅâ*¹PêL#ô°ert”>0´œWè'Ù¡D„¯º"ZŸ=¤>g¼¡ÔQlháSúU“Ð<Ám`gÀüPbä\eÊ@å„2–9weB¿¾Ê…å))Ç%bQR…(e`6PÊ@Û‡;™QX}T„ÃL¥ ,OQ˜Š))%zèa]GûSêó,VºÀЇ.°ß‘‡ÊÀ˜€¡ ìÏOXˆ§–Ç„£:&~ä,u`L‚PÂgêÀ8n—>0f`(aö´è4H… tÔ¡L±¤,uI!¸W]R!£¡S!ˆÕbT/ÁÒB*j:*s°¤°DwP¤B°0;] Á˜ÒÆkúÀI ÁM)a¶7*"()%B0;T Á0S`˜;„J°”L• ìÏFøbUâÈI'¦¡„?S¨¼ž…N0VÖР¹é`Âúu‚aÕ:AÄß<˜{Üvø¦!Jè1¡zeB\þ%Ps`V.àÕ…AÒ ^]³D:A¦Þ• Óæ%t‚¥*× ^¯†A:ÁR0•‚ BK…`>!`Ò„F0ËFá uŒk³¤L!¥,%S#ÏCÆü&¦¢N*ÁRŽë¯;8Ž<ø)NAè±É ý‘±³oÕC0=BB'XJv,ŠDòà‡oÖ¡Üßq¢‹”‚—.G~¸Í§â`yH:ÁxH4˜5I%˜Í“J0" #¤Œ]F(óGA[$ü¨„Mÿ‚xÆê³g¤̱”B0Ë Fó¤Ì~>0š'ü> “ ˜f\¡¼®ÐõsQ˜“XêÀh^€`<êÀ*Ô1³á$A^s””Áp=\‘²FÕæ ŒYXž"Â3€š>r`L›àÀÏýáƒá5ÙýR`–+ üõ ÀÊ Þ™Þw‚Àò!0Ÿ f7ˆîh)Œ‡„€Ù»BÀ¬[S8¦'ØhàI,O³Ç‰€¥r"`)†˜UJ¿_ºütÄÑÌ)°ä Bã&æs ü„[A—x¨1 þ Ìî „Ó¢œŠ*@²]ÒÞÓ®màçÛᢜt9 ìa%p-gƒ ídƒ¡[Æ‚¹ÀÕbÁ\×|D,°l®òc,„ð{ªñ§mi{Uš™+  &œT" Œù ¦ ®«Ú~¦Yx„‚ Kçƒxž£Ú~Þ¹m,¡`ö—ê‡zÒý³F‚¹M”ߊûßý2ÀpD‚¹ážû[qÿ»?^Ì`nxŒWÓÏq»û¦]ŒI"ÿ¿vñ‚ÂðÿÃûi5Éý¯ÝŒnîífäåpÿ˹ÿµ›ÑÖÃýoõ8"ÁdŠÜÿZãe¹áþ‡”»Z~îÆÖ÷?¤TÖ³„UYÏ6½ÍƒÃÐû±»]ã'ï¿>ô>¼ÿúäMZáØ»®a`Ÿ/ãTÈåø—X€¨Ý·rDž«²^Ö€ˆ%îÁJäØaQÎwìë¦3£Íá¸a™þ rĆ߿àrD9£èÓ3><&•ú=zbqg<˜Ì£x0Q¹<±€Ñª”€ÈãŽ0ò,åа? ð/À,G.€h3£²Ðåx¹F<'¹v\æ t,)tDårø»J@·{Éok†.€á¤-À’@@<ô1aÂ<\3¢Ž\ËSt,OÑ~ï>Är,yèÿôëðD(Ó0#üȰcýò<ôD =ñl`âù¢°ûð,y&Ä”`D1'@¸Æ·Ã åˆÝ ‚Ÿ1aú{sÈ 0b(„ â#Ýèˆ<ºWÏÝ#ƒÜ³¹FŒ‚pDå$@º"Ø?MIéX*WP…k`ŒÜ3F‡Ü3"‡Ü³`¹"ÐCéÒ 0#rÈ ¡ tG©»fô¹–§èXSÜ °´‡n€ ∠Àϊ Ãg%* ƒb”¨0ºR]n€\#Ü3ôHD…É’fq‰Ë¨0Šc#7À ð’aaä×™aaäµ—aa¸›OÀŒû“aa"KÈú–Ð1FnœF‘lä˜rÑ!°£°0J)ÃÂDž £Ê!0»G\)ÃÂ(œ‘<íɪ¬åÐ%0cÛdXu†\K̺–Ú&ª¢K`.)\£Ã%0F+\ËSîXèÖáXòÐ%0.¨üsb¤K`Äm —@¤|GX˜’B—Àˆï>)–|dkTKPKyŸ@D+>—+|')\tÈýÞäˆ2Æ&óÈ%á½Ü„“ÄFÞ¢G`„7 Àìby–‚é˜Ó# –E.ãJ>¥ú¢5£Ú‚fD°ð ŒHgá˜'§À:¦r ŒË'0BÒ…S B‚ÍÃ)!¸z¥¿ŒôTâÇ…À*¼A¹³ïal®ßØK†ËÕßjØïš#ógŽß{æ‡ ïl¬—¿Jhn¥eØÞH)¡¹÷×̾,G¿j9L+å(¥”3z»$¢ý·”` ù¸ÿüŽøB÷…¾î­ÿš+DDSþƒ ü{"ƒþ‹£‹'Æžó¢Ù]áüçY0ö"x8Ÿ-¿ù| ü­22—Ê9‚ˆ³¬ø›eÕÀß*+s©¬#ˆ¸ÊÊÀß*«þ޲"W”Uƒˆ«¬ ü­²Jàï(+rEY5ˆ¸ÊÊÀß*«þ޲"W”õ/„o¸Pi¯É¿|þ½ðàšN‘ñƒÿQ¾ŸÃƒÿaygxðmþQ¶ß þ÷V¼¿þ²~ýÞ÷×_ÞŽŸ×¼_ß_ËøóáÁqg ÎØŽðà>ª÷û÷Ãÿù8ãgxð-€7îbƒ,¿Àû‰ÞOð>¢k—ÿþ»ßõ¿ÿzïÿÞïß á½¢œý?áý\í•T;ñ—Þ;í¿Åÿþóï¤Eïö÷Cx7XYì.7Ä!<—޽ÓXpdvgæ¡¿={_ñ}vÕé iCÆŽûô "Ä­^Ÿ§xàÔ÷H=žÒ.Ûj “±h¿p§1Îíâ9K°£8;J±ã¿Žk”Œñðm)~!ÒÛzì“Ús¬sƒj'¬—ÀØñßËë”:â;1 ¨;®2bÜåÙ^­[|úßìHÁvs1´žºî7â¨1Þõò<ã¦æÙB€qq½Ý„ÔqôkQ¼çò#A#š‹¶-õ^'ýôOœûýøáßì—ý|zò$·ßƒ@´ŠÙ]tî8i,NÄ‘õ”æáTý¡æv ž§t?øÃS¶Þ‹³üÍ©îlÓþppaÝЖŸûͽÃ|ü¡ÇÎýp’aüÖW¬ˆ«òOùúãM?{}÷s¿‰8A–g‚±âÄ·Óó4?÷³›ì§§ø¹ß¼yYtïÝÏýf{ü8§ãx¬XÊ™~î‡<ÃËY~î7A£–ðø±n$²Ã¯Þ_?ö›×ruS7~Gk„¯ƒÉ€Švõ‘µ†;MÜ>ùó4?õCE¦—±[Kë.ÝëO RÄ0˜ò¤#ä6d2`Äo¿®׆rNŒå‡~{ àðŽÇýæýø‡£#Æzcƒ½uŸÝÕ˜c‰ÉLŒŠÐ¯ã«óh6?ñ›}xüóÂ(Ð ‹>;£@ã@džøá(³Úë˜P€DTÝ=ÏZ>FË3<~à7{szï¸l”c4??ïÃ%ÕÞ—ëòó¾hÝ~Ü7;oì«1ôÇ’vŠ÷MD†³ŽZÝûrV­áÇ}ÙÜ5ý¸o^R–÷¡‡| íܠÄ郎”׎ûR¨ýÅ1JÌQÂ} íñ™g°ÙŸÛûPùåyš÷aÎ|Lñã¾|½qE={Ô»äü;J™~Ú‡¡´Ãþ,?íÃ9¥¿–Ø~|Ã'°Üóúi_®ïÏç§}9ïå§}³Q7ÑßÛOûf絞{9öÓ>Üçå‹ Ì/±vã0ÓâÁtxbíŽ!ý¦vÜïʉõáã]ì‹¡ÌúÏaܨþ>ÞÇ>eq«â7ë"%èuÈif­ö1Œ„Ú1œˆcAüíã"˜ÕÕòUÖNpìÊæ9êBòùêšÓÖ®—½kD¨KêçwóÚ(t/äó“>ô°}½íª[[¼¡ ›–rûI_”c—€¶VfÅÀ¥ÇÝó±ßÝúðšÛQ©]‡;©º?3ý w®Úqœ]ôg‹7Æ´[Êã}Ñ{vž-Þ¦>AÂçç|˜þbEÚÚ=yWßÀ—ùbl[Û |™oÆ ¶3©/³-Þƒ7<ÄB²ÅJK°›§mœl¸óØÖîÎûM°“Óæõ<óÅ*0pçñÃgyžÏùâeÍnžŽq`Ïóñå°5iàÛl‹7Âú7OñS¾x]¾Í¶xgžá§|¥¦é§|1‰Gó»Fó³0pë±­ßZŠn=öµ—Si`«ý̲ê\{l 8nžµ„Ûù Õí)°Ç¦«½ù!žžâ±mJØ ?ðe¶ñï­uÝ÷I¹p \zl+xãÞq@û4ï:vÝ)ÖÖëéu}fl%ÛNa`‹hÇ|˜töÇì˜ïó¡óÛ®ÁÀ·Ùðûc÷ »{—q»ÊdàÓ|×q 7hȯÇÀž±óõð,Ÿò¥PvH«By³lœ<Áîù|14ûVØ®ŸWï×â” ,K¶xãb ýåÚ­)/³­Ý÷ë»ãWÍ×nß² \yÜÞ2±³•+¸?óv_¹ãýŸfœR×Üx¼¸2,Ë6ÿE\xü¼e0–mÙkà2Åø6_ãxj._ºµãËï-Ž+ýþ~x®<îg]¸¶Ù.Æ™œ所93;ËÁ•ǶvƒzOù¸xs0»x:¿ª7ÛêÓ7ûÖ›W;ûÍ,£‰³-ÞñÊé\ÇÇÿφëòƒÇDŸ…ü¦ÛU9õÁ>‡fA¤¾µg„ÛðŠúÖlf‘‘Ô·`ç@êƒ]ÌXpN}l—¯Š}Ð}³Cì{aÛ½Ç>ì܇BØ—Ö­Â>|ÅÝØVØõ’[® û L÷ºc¼|ë@ê3ù/2žSî}ê».ÞKÔ£æ)¤¾Ëû-©—“8I}¸Šõ>°17= Áº‡Ir"R;Eûð¨Ø÷áìò;¸-׈}0àéöEÄÝÀ¾q؇۱|$î»bÙ«rîÃ%ÃÎâ¾6´¹÷ÝpOsˆ"÷Ýïbåâ¾vó¨à¾ y¦8÷µ‹·»÷áx`Ì›Ú}÷ûý„}Í7i…ûеΓľۗìÄ>܃ì"û>©NZÄ>˜“8¡‹ûp¾á{Gq¶.¦¸¯<åÜ׿b~a³à‡Éá¥û ×rr÷……V€_öȯaÃák~8ÛôÎ!ø¡'Ö~x1ý›$ðÃè_  ´O!ø5_ðE}ÑA.9Ÿô…ÍaPêñR}ù úhNV /§§¨³ÈG…؇Ƙ½I`_ØDö¡>Ç3b_t^`l+}Ã&ìkþÂ&öa}w0$ö¡y¾1ö5G*1_tn0Nèo'P2fÃëyÈ|h )ІŸ}1Éú.˜Ðv¿}˜Á„GB_¼P¢>Øý‘ñH}vdîU‘úbYêÃËâûyQ_ŒBP_,Ý¢¾0y ìÃ[H¤#öÅ«؇§[„}ñ>öÅ÷'° ôºI}ø‚úœõaúЗB ú´†óá³6Å}xÈ÷º}mïXøË™O¯z _Ê#äË^òÅBÈ—XÈoF _ÌW_H(àËò><>õ|è''q_,•¾¨G¼§w=p¯…X%" {Ù²úÍŒUÅzÙ±^ì‚õÎ]+´ã%Ú ËçÀ½†ƒO!î¡\µ„{xý>/‡¼×p®í)>Tõ:øâBÕ¾hŸx/vŒâ½ìñŒrÌ–)x/Öðམd½†#ß íAnñE{9]D{¨É{F?ÊìÝ_^¬{Õ`½œªb=LUOpÔËžêåH õJ Q/gX¯ÔDÖ‹…óŸˆÏÄ÷¹7Dßs7Æh“®ïãqƒ Þ~îAª¾ðdNUl㲤ê×¢U}qKèúJ u}º½#T}p·p‚’ª7sôÊ|å!jú@-DPjú`ÈväKÛŽÐôEù`>|þ_òÞ&i“ÜXÖÛJO¯™Ô–ÿ?ëà îàš&´cg¢ý+îᨪî&)J:²3!û‹B$/ à  ùêfŽB¾±î¿ñ­×­É¼ˆoĺMû|¥ßćðs>$ä[¯]“Âb>Ä„ÿ–ÌÇ)g2Ÿ:n#ß­‹Z‹ùðÃEƒ‘Ïw¡4òùš˜B¾õY8qkâ;¼hâÛ51ñæ.BaߏQŸ.ï-àK¼û#à[9£àƒÛ+ÁÌÄWíYÄ÷½B‰N M|xj&>ßÍcâƒûf¾†_¿ípjlàkZ7ðõ‹ðÕ9ž>Ä ÿ–¼WñÚ“DóÚêÞCd<)L¼×O™÷º­Ì{h’®·d]ÓVߘ þ@|›|(â«.Kâ»j¿ÐÄW/ÎIJäâBÄ!¦Í>ä£ý6Ú|™vûP™gÚíëwgâëÒ ù:#_}˜F¾îHÅ|:VÈ·)꼘¯{I1Î’üÈ×㆑ñ«3ò!Z‰ŸªÑPÈç#cE|뽘ÝD|péšöúº±L|ýL|ýL|ȇcâ«e">_'SÄW‹]&>¸Àe_]aâCÓìñõ`âënmâëõ_¯/úê›2ôõ¢¡¯‹2ôõ7eêƒEü&êëV7õÕxnèÃ}XÉ|¸ùH›Œb>øÍ1Õ̇l²™˜¯Š.æ«A ˜¯º–™/ ‚>ùÅ|0¼ÓV_uǾÈFØWnöՉžzá…}î6¦¾: jè{FÖßúÐI˜ÄÌwê–Íb>wØb¾ÖŠùjD*情¬`æC “}Ì|Ï·Üé«/¡˜¯F¾b¾.ÜÌWÃO1_ 6Å|Õ4F>øOÀòÕMK…|5<óÕÐWÌW]« ÏR1*C¦Ã³>Œb>ô}ÚçÃ:0 6ô­ì &¾ú–Šøœ@¸W¿”…{õ]ïu&¾ºª‰Ï ÛE|ýÎL|]–ˆ/’ù"‰˜¯;ƒ±/žöÕúxqšŠK*â¾þŽÍ}· Mæ>¤YeÑý>õÒL~õ{Uä×_ É¯Æ•"¿°ˆüêåüúc7øuq_×ÏàW ƒúÝÄ}=ª˜ûº±Ì}=ªüê·È¯3øµÛ¿þ L~aùÕ-…~8H³jSoÑ´[_ É¯~~í¶Ñ¯kcôÃ/ìXe/ô ‹Ð=é™Ð¿÷'ƒÿT’Û¸wm<ò¸×‘œÄ½7ª0ÖS¡tÖä=ÍÞVBy¯e0Ì{-2fÞk#ó^«5™÷p‹šJ>ü.zJ›|ØM:øÞ¯ÜÚtÔ&4!Þ$>œ»^´¯ÆM>(°1äÊ»|XÏçªpíòaa{B>€í2!ß8ü5Åv"Í3íò- ;é]¾ÎXÌ·`oó-›ö Ì|HCø5ôuQ†¾ÎÇÔ‡IíЉúz«Ò؇§ÈôÆ>Ôy­ö-üŒƒûàúÆÒÉ}£ƒð!rß‹¥5%!÷E» ü^„|® ©$ø½Ø…âlMà‡3wÛ~xÅ"÷½ÀGíâ‘ûbÛV܇^pj{܇§Ž-wúF·gø¦À–u ð‹î%ò{±YÉú‰üƱÁC{Tñ'~kð‹²~ùпLBðCIç›ä‹>¡_|B?”­=w¡&‘¼Àè‡KïJè‡|ôf„~ññ ý0;}ïD¿?ü'ó!úáúè…uúá}ò¾•~±/ô‹6ú½P”¿3Î3^ƒÐ¯;…ÈÊî™üÐ÷‘ä-*òë7%ðC^Weð‹&øEoøE£“ü2’ÚŠ ™üÍ®M9¢Ò¼â<Šxáu¹Èwƒkè"ùá+c‡~ù É/:€È/ "ø!  ~‘„ÜWÂ+ƾN!ê‹r„}Ñ­„}Q;q”3ÔAÄ}‘ñÀ¾h:aê¢ß a_tEaòÕï’°/JöEÎâ>¤Ñð#î‹EÜ×õöeb_TGØU÷eš~ñÉ üðrõ9 ü`y…Q¿was,ð'›Gç3ø!͹iûo\ëSMaðë¢L~Õ³ ~È…«¿¿,‰à×w×ü2 Ái&î‹ê üZ=Ôä7Y(ãU]ÉèןªÐ/ D¿~UF¿LCôë÷`ôÃë8îD¿þ`„~Õ)L~ýÂM~ýÂM~ñÁ¯;¤Á/"ùeÆD¿¨°Ð/]è—9ý¢+ ý¢Wˆýº€ýò ²_ä*ö‹úŠý¢.Â?¤¹ŽÜð˧H€=t˜ûƒ6Fé"ÀèÅ"ÀðIØŸ¸ 0-ƒã›fÆ$ÀøD€á¨0-$À´ ŒlD€Ýæ@|/üÍ4Fý€ñj€á”0Ó£(ò_EÌ¢€ 3ÆG/Œ|H€ñ‰ 3 0Šf"`"À¨0kCD*ÕûgÔøÞ«dh€°cŒ€ñòÄ€i ]R Y oF ˜O‘ãƒö¯ë?¡ÆÝÛûˆ…Œ£~[IÓ)è#æh’ ú¼6O ô‰!W úÄ”Š?bâAè¥-‡èAŸR;rÿï^Bô F Ó@ Œl„Qa."œ,¯ã8ÞÂè"Âè'"´³6D¬ ‘0GLµF>¢ÂhQ!ÞEgM…i!ÆKF}ˆ…QaaZˆ…ù±PŸ¹°0CX˜bat[aa|çÂB”®¥ qaÔG\Ÿ¸0~ùÄ…ÑUÈ…i ÞÐÆ>rCcç5vuÌ…]s!~™Wâ·ûys?Maz#Â2a!ú³¦* á½KbaM,ì®c,¼îÍ^—tùŒ…˜“^Ú¸#r–ª-Â…‘±°Mÿˆ…×¹{‡Tƒá’T ô…8ïò¨hBafK(Œl…º£j½©–#¡°ÏÑ ÓB*ÄC\ð4^Щ’ ÑI¨íl*L ©0Ÿ"¦…T؆LÏ §?ÆdÂ0 ó"!,§@’H‘£D„i!FÆ"Bœeâ•&ÂÉ2ˆ0òf>ƒ»6Â03ò`fBÌ4äÁÈfà`<#L y°Ÿ†4˜ÏÓB¿“¤8Â`¦Á¨®h0³! ^Cg6ã@»6‚Áxˆ08^ŽÜm! ¦…0µ ¦…4eÃ@ÌgÈ‚i! bâÁ«Ì‚i! ÆSbÁ¨1Y°Ë †$˜™3’`ZH‚ýÔ/¹kP8;€çK¥ߊњʂ¾Ã#)GÀÑ’ø<^ê$W¼gˆ¬xÏSq¼'0ìžâ=Q¿‡¨€Ï°(à'&æ€ÏûتˆOüÂó!|>Ç«lðù,›Ã;ðyß>~ïí?œ'|ø†&—k½ý‡ÙË5mÿáÖíÛqûûë´ýGEìßøÖñ»Ïl´ý‡›LtÂPÛ¸kb>1à›ñö®¶?t¬Ûˆ×õ]0]˜·ÿÞÚÞþ{·Jصý‡­(yûï=_çÌí¿öÜaŸ˜‡\“À ¤;Bç¸OH€îI|+´ƒÒœâ>ßõ¶êŠâ>1áâ^¨ã>qÇÌ–Ä·^›ÞqŸ×î7ê¸Ï¡U;ôƒV­rVà'VE¸¾¡ÀO°Ã5)¼\»Ä²+òEÓQ¿ §†sð³ø´¢#?/Dæ3gF~" ‘:ò_ýtè'ƒipÅlmêØO,Û칸bÊvOgý ŽÏ\Ç~~Ó*}¡Žý¼É,TìçÆA¡‰¯ÏTìçu9äѱŸ¢øÈ’ÈäBÔÄû‰GÖIç£ù•Ä7œâ‰1Ç~"ŸmRzÁÏÀsÇ~bÉÅÇ~vYŽý¼npŽý¼n«:9ösÈOÇýºûÙŽ+ø3ª¬àÏ® ƒ?á+G^—$k+ú³ÌÑŸ¨Nî~†û‡èOÈ'¿Søgd¬ðÏ(\áŸÃ;£*üóº%}[áŸøå¸ãðO¤áâŠÃ?»,Çâ7‹AŽÿ¼ŽÝ'óЧÎD¾ðK (ŠŸ£@¯Û甊k8T:´Ã í„@‘†ß‘#@‘óª}?F€‚PîÜ L‹"@»;9´›Ù í–C@»áŠ$š+´ª\1 åhÅ€ŽÞ9ɽ çkŠEw_¸ñ§Ðúl*mªS| EuöÜ E‰@Šë5Uå Ðú´*ŽrÙÝA Õî ›_ž¯pÞ Ua õF+´ýRhõåŠE’'7³pÅ^ÏÆ¶â@áè¬øRÐq e›û¾lŒÚŽEÆ<¬å8Ð ‚í“ä ,'7öЧÞÜì_€Š……LìHP\kÂÝ+G‚ÂÂt$(¦ÃleG‚vYÅ‚ìÕ± `ßøˆbAQa¡:Ùr³Ã± Xô;r?0- Å»—#B1ˆR›Ã¡˜­/Ó À‹S¦¿!bÏVG„^Ô!oú[Ç /´("9ï´0"´‹rD(ª|O¡c”çΞ"BâˆP4¿#G„¢T}„ý3E„BXƒIzA…^[„ŒíÖqD(žšÏ"g®Ó8"ôâOt3àø±V<ª"B±FÄÁÀ!¡×ûøäŸBBÑ-ž)&eñp©cBÛ/Å„¦A¡è“Ú¸SP(Úýš‚Bdë$þGù:(ö[G…¶Ž ……½ÝQ¡‘¢BÑSPh VP(úÎ-5F…¢u*¬¨P<¬EE…FE…ö+vThרQ¡Ý:-¬ ¨Ðæ>÷cP5doÄØÃ•jýo©³):}§øÕ3­Í}Þï˜]1×ú+±mkÍܲ„.öµãg‚ùÔ_‘mOY2¬˜~=^ùø¯ÌG¶ÈÇ–»N÷W‹q¡Ð/uº¡²Mîã¯üÃ:Ýs9qãÍÙ:Ý?öˆc bþW?Û Ü~>¸G§r>™Êyµ·óJnçÕ©œW¦ª¼J»ò îÊ«RU^‘ªò*îÊ+¸+¯JUyEªÊ«¸+¯P஼*Uåõ/ètãGᛥÓ}ÿ™N÷O½åtºÿ(Ý:ݘ߬ÓýÉÎ?í˳N÷Ÿ~ûi,ûÕx÷·Ÿ¾ŽÇ¿Ÿ¿ŸóøÇuº1m˜§N7D³!ñ°œ©¯}ücBÝÇñ—9ýÇÿøßÇNÎrþëJÝ$„7¿Rê¾+uÿõ¿ê¿þT©ûûwËs¯{þgÿû_+uÏ…´÷Ôµ-”ºÿOÜÃ6–Ÿ§ÁËÏ8Î1Ö0O\†åçŠÖ9qÏ"@J~í³0äÀ©NÞ± øàÖìqˆåÄý%¸'5Çq®óXÇ‚`ß{¯õÆŽäCËÎk½í©|=M×zûÈljb@$t,LÇÅóKÿMH¹ ¸Œf–‡ ‚¸Úîeš‡ ‚Ë)ýÞÒøvp!Þ@Ïš¼€Èåѵw'Tþ†€Ì¶q½è„¼áÁ¹ÿkXv.B·|c>±\½3Í9—ã m}3f.ÖÝ‘çÕ»ãDô‰ˆÄ“‡,\ÄúõÎ òÒ¤aŒq^ËX\°0üDTÎ8L¸œü-8±P ˆÄ1¥±›}^»ƒ/ºYí¼_$³{bƒrü’¶åâ‚`éÕ d'd¶W—Gz…ŸE'Áß•€qb>;N‚¿Zi?1uzö| Øx·8iuÞ[ªœ÷ÎÕ@d»ò‘ƒ«Ë«ÛöÎûÔIðEwÎ÷ÅÕ@¤¹øÔÍÕÀáÿ£9ïG'ÁW­³_(ví©çŠ!|ÌÃOì=Œ#…–8ŸUÁ;ÍÆÅÀ®à³ÏÁÏçkË£õéo¸çZà‚;ˆáâoÐúc“ã{>vã=—Û'ÜÊ:‚®Xô;–ñžØ¸@øØ ŠkÌï!i(Î[Ï5Yv.ÆS‡N‚/º7ï|O..¯.F<ßK'Á}kê9â)qnÑ5ƒçi¼¢Ñ_j±EG¡SýsPÕµ,\ ¬þùáäX \p–ˆI6®bšÎ{^qì8ÔÕ–ƒ+Õ¤ôǑ…Šè×rq!p¹_"ú÷ŽÞÐcOæòpвŒ^ë8ÒU†÷ÑyB‰T¬ËUÀê ºü8ÑõêzÊkÝt|Yø.d½ÕAÇÈk( /oRà÷{Ãe@äs2çKGÁ-ráXè8Ñ¥ÞváÜå8ÐõêzÊ bsm^®ÖÛ½°Ê?ð[²¶¤hÎÑž»nÉ…ÏÀëEAh àÏÁU@øðòš_¢Ú¨ß˜¤}ãW»>ÛM0|w¼ç÷ÐŒÜ_Õgá*`}D×öê4ø²Ù¯}«€d_¹ 8–"iÙtÜöÚw®ŽkPGuöƒ×»u•qéê#™››O]c°»îþÄŽþ§Œ®¢_ðRäÞ¬èelq}Ý‘O”œï¯ó¶p/ËÆUÀú=¹Ž«€Õ Žƒ‹€5ž\ǹi×îÖõÍ4„»û73Ÿgá[8Xòój×¥ª~ q(¡2ãGüÂ4à'rì¯^µå¾ðWóïSAãÊ5}ú&c¯ßœëäªçh­1=¸¾ßÍ1†w Ï›‹€‘ÏÍE@X.>õp°Ç üBk Ë-~ Ç Ž—8q³w¾¼kã"`WðÚ¹ˆ|ÆÖ…=qi5–i97ŽâîJØhºÔs.~s°ßøXg¿ø5rüÐzïðŠ·eE»¿ã·ÊËÑîø^G¿}8ǹÓ¼é×Lƒ.×îWÌz.ìÉçd9¹Xsœ Y_*ëa>÷XD\YÔÍEÀþ¨oNVŒÌ«p“õÆ­É{ágzœÍ­÷¡Fr´;~¦·é…>Ü@³§±Žz=ëçóúf¼Êíúséh8vËXúÍUÀþÐqbú^³;á2ë'&jî²~rÞx!úàÚ¿Ôãln5~©×éË»à£óìz/œ€áR?}¹5A¶êÎOëý|àPnÏq>áÒðÊ_aœ¦½·leî}Öè–7äÇPa„kX¾ùÖʱ[óËvr.îî}ã§z=¢yî1+ߣÞc¾²î›?t÷2Ä·ºu¾®¼h..'n¼ÎÅ 7Zw ås`šwÕÁÄãÙb¸¿1i|Ù¦c»¡’õ¾ÑÊ7~¬—;z ×n®èq7~¬ÇPZ´âS^ý£"Þ…¸ÒôJ(Ćúýø…X]¸F_5ޱŒDAá…yi@P”ؘ Á <¥d(Äv7CE ……VYbQÛxG(ü^·N‹ ﯮ…]:˜„ÂûûÚׇ(I(Äøu …ؾNVPˆÑãÒZ†Âç£ßƒØ (¼ñËÏÒ…϶JÁPˆýêk'» ,· .bÖ>¤DBáó}þÏP#7",é a ŸqćÕ!>#ð …Ø¯¾F´ ðÁq1r£ ð…œ&ùSPøŒ`’$¡ÃÉC<"ÌæN&|¥ÁÆâ!žv0B.Ç”Œ…/ö9áâzÞMÔJ,„C;…ïø®Ñ:±Ÿ.ˆR‹ ±œp³“ K»ÝTøBkc9¤Â›,¤Âw\yIr|~8%n*Ä ù܉…uLÎT¸¡Æ„©°Ïk™ 3Åç¢ÂÒUö$ÈXØGôÌ…/Fw¥¹uJüÐ+sáË.l&„胪òòˆ¸¶™ qÂ^™Š [}ÃLˆæŸWL¸àð)ñÔ)qGû–†™°e Š ñã!|tNÜr… $R f‹Î‰ë ŸbB9S !JÁéO!áré—PHŸâa±&™°…"Š —›Z?Í„¼-=¡Ðº¦B8ÂÃM…D³`Q!~Wy4¶¨~ïL#*l?‹ ׃Š6M…îE…÷àÔ´¨ÐÚ…ë¡ÉޱQŸ,ÊX¸¾”L0v5¶ªGcá¢{} ¿‘–“òÂBŒ£¬ÂÂ.ËX¡}æ#,\ðq1ca§1(˜³°k‘#8±°—À“ÌŒ…«" Œd3â˜Ê¨`aáv‰v Ë c!2‰±pÕG…Ð6': ëÕbívd\XX9âÄ!QÌXUoâš±pW_s!½˜³¹p_ý”¹p;yˆ¢¹°>Pr!Dng.Ä:9-âÂñæIæÂCÑÎÍ…õ9â×b]\è¥åæÂý5;š ë•–SÅ…ÛÃPÎæB„{Òb.¬žb.ô:rs!t‰]æB\§Á4æÂ]¡ÌÍ…¯¥Å\ˆ@jZÄ…]”¹?ÿ¢@qá®[š 1É&Mš ;¹pStxs!nr ˆ™ «Ãb•æÂω•4i.<$aß\¸¯­Š ARî ‚› qÛ<“˜ kø*.¬Ñ½¸pWÈjsá!íåæÂªNqáWÖ9sauÝâÂCÒíÍ…¸ÚO(.DðÌ…Þ©(.k¯°F„¢Â•Ÿ}SᨠgUµWx*ä¶÷ ŸCS!úµèRTX’¥½Wø.šü› kÜ(*¬~m*Ä9µcÚ,,™ØÚ,¬A 6 ñ5¶ë¦Âú‹ ëò­¢ÂnBS¡/cè½Â~HPØma(¬o³÷ 餈°>Ã"Â~ µQè넊»aÉ\ÆS$BµýDXƒT!î®aÿ3v[™K6ºˆ°®Z+"´^v!²á´Ð@XWëú†„âÁÒü-Üx>.x°~Nȃ멈ùâAŸà§)ì;̃}UXñ îtavѸ Ž›yÂÁH"Ĺ n³û%Ãrû¾ GŸ‹qp%i†…8X§ä ÑžŒU0†E8ˆ ò2vuŒƒ°pËY88N›0á`¿:ã`ÝfU8ØoÊ8Ø~;ã ®~;¦mÂî‘ÆÁvË8ˆ§ØOŒƒñ”pÐ. Öý”¦A¸›f„…´*Œ‚ƒ¨Ìx/fÁn-³ îìZ'쇄‚ý6‚u^¡`7¨Q°.š*ìæ3 ÆSDÁ0Q?.;£`ÕØ$è; «­ÄHðñÄavsš‘†Ë'æÀºn­80Òˆ˃âÀºx°8°š¸8°Þwq`Ý;Vˆ4 sVû™£(q`<¤ýÁê²µ?XNvÆæÀÎGX-XØ^™ë›*ì škœ*¬§þBúÛì÷Mj~ØÄH@Y’?f¿‹”§¢GÍ~8«}r[Éì‡E-îV˜ýz·Â¡¢ã)ø3ü6üy…»á÷ ^jø»öàîÓüyg·áï›9?üU”XߣšþNG}:T?¬¹+ø øCß'þtP³ß²;LÕì·êHVÃBb§HQœ‚äS†¿õ5¸þ6]jöÃõìs èv;äÓüWSûâ¿ýtªùo×Éæ?¬ïM±¢ë~›ÍxŸ3ÿU>€¾9¶¡÷¿ÿáâÎßÿˆ³Å~8o;‡‰b‰e˜ýŽ×! f¿Ncöóu`Í~åB?Ä ÏèWk~:Cè§ P£ß¹9zSèW>ú¹ìB¿b¶B¿¶ýNXjô;u±ÑïÑ×Óè'È,ôûò½¦0Ñn¾f??dô‡N&ôsŠ"?#¦Áϳß¿Bâ¿Ãa¤¿š!7ùifkò3øé"“æ>߯ÔÜWÓ÷â>_fܧ¥€â¾šá÷ü4÷yjÞÜçlŠû¼žÑÜçûZšûšÅÌ}ÍkÅ}º&#¸¯ò1÷é ûÞi3°V û¼êÐØç+ÎûüPaŸ.¢jê+v(êó5M}E}m1õu>ƾ®Ž±Ï·©4öáÈþŒ}¾'©ÈO£Æ>ß¬ÔØW¹öùVœÆ>D ÍØ§lÅ|åO1Ÿ¯ýhæó%3Í|¾Ëª™¯Ê)æ«úóyi¥¡Ï·éôùÁf¾jÌ‚¾z·†¾º+ O×< ú|GOC_[}÷êm|1®*Y­Å|ÕÇ‹ùªä‚¾êõ†¾xÊÐç« úʧ‚¾úV ú:gC_çLèë‘ÄÐ×Ùúú!C_]DÓÐW,è«Â}^‘+æ‹gÄ|=H˜ùê~ f¾rÜÌW×PóõwYÌ瑹˜¯ëgæ‹|Ì|Õ•Ì|è&Ú&¼|gÐ;CŸ‹ù"A_·º¡¯×¡L}=J˜újè3ôuã˜úºz¦¾.ÜÔ×=½¨ïž¯Ç#_×WÈWë*&¾, |=(øTŠq¯G/ó^WLÀׂ¯?B_”#à‹4¾: |‘³€¯ò)à«NTÀW,à«ûµ øjX+à«æ,à«;B |‘±€¯.å*à«%оºû­€¯~¬ øª_øêó)à«å®¾êÒ|Õ øêóécÎn¯BçûO6þ ]@(òAÁ»bàÐÊ¥²~Å„–ª_íü!økÉ?h, æ$ýµJjoý±—ýAh!»8&@ÆuÓ_Ý’VIkÒòÙmô‘þ _väÖß{Y=Úô÷ ’ôèoǦ"C7MÆ1ýA¶Lá°¦¿ýú‘þâÌß ?(¤) Îô·?’áꃂužKø‡I³ˆÚøw`¹‰Oþ™íýá†*Ñý¶žñï”ÂJá 0kü;ŽÇ@hüó>N¬Ó¦¿c¿ë\ èSö ?|ëtRðØõýÕªZŸ¼_ó¸µ{'þ«{Ë㤠Õ™ R¸í§6N‹¿^;…„®˜Ëh;¸!Öƒ ÆÚßCã^ öHnæ?_"]üwÞÒÿmج(”[:(„O+áN¸]:CÔ(Ò)þ;î݆ä¿í¾ ]æ?倸֖ 7Õ#¼{×Nx`ëŒ!àö*Œ©ð½´¸dÓAÁm—Nbqà¹îú4îÇeÈ#xaqà¹Hi²8ú„wF…~OI\±8pÈüLûC(iâ@¨?-STè¹­¿O¸ß>Ei Ünû- ÄG’1B ñR(9&ÃÁ§˜Ðý•daàöT,§0]îï©(9sàö8œÒxî:Yi „Ô#ýŒÛãøXc ä¶i÷ä|Î8T*' <1&1À’¸¿—ÏŠwìL$ˆ¢)f/<·Í›…bÀn@3à~¼ÞÓžû¦µ-3à±),§óÈ™ëc7_6ôÁˆÑ‰±FÀöʈ_|)î§Oe!]–ˆg¦PKVÔfæl¬ q¯ïVëÍ>,aÌ‘ž’ w[]»ŠÁ¼Ù‡^Ä| ÷¬A#Ü{}#S렃ͺ0Ø\ÐÞžtaÀLSº0›g¬ smÚÿ³.ŒVï…tŒua°ú8E{v›š÷ê4oñZG[y>Gð…ì‹¥aªM ø‘ÝÒ0%’SÒ0>?ÛÀwl¶lÒ—a&% s»ßðÕ>±‰¯wK ˆóI¦´ú$`õÿ’‡ùÚ}ŽùD rr[ò0·d}ój&± X/½ÎÞžì·DŒ_qKÄìz5uÐc!³ý@€­IQg­F1õTiÄhÈè³€åVkÄ”@ÏV yÐC\Ÿ,­ 3 f½SìgÕª³€¥¢Qg«E[#ÆMÚ1ni ß´FL=å³€%‘Ô1¥,S1úmi‹1ÕYÀR/i˜’i)‹:ÕYÀ’¬i‹²”FL%)K§ÔYÀêþu°úmkÄÔS¡ø5bNE/ÔYÀêí­cÍš: ˆ(ìù,`IŠ´FL À”FŒ£4b<î´FŒ{r¬Ö1þd[#ÆãNjİ1Z#ÆÝ²5bJYÆg«;ÕYÀ’Щ³€Õðu°„±Z#Æ®—FLUÐgK)«Î–@SjÄÜ vë,`‹»ü¡FL‹Ïø,`©Ú´FŒÇ‚Öˆñ'Ñ1•Æg=î³€­ã³€ž8õYÀ{5–FŒÎm…FÌÅ6í³€¥¯R1%5ã³€þÑj¬N[‚8X¦¢|Ð3ž> èù`Ä®; > h¢> ˆE¦ñY@ì–“(}°$kê, Žý ô}ãŽÕÓÛ/–KÝúßR´;StúNñ«gþZèûÙ _v(×ú+„µmkÑݲ„°öó\!Ð]e>²E>¶D>ïX\yì¥ÿŠ|lë|Êòoú~Vh”ÿ°ÐwÿçÕ“õÏ4¿Jû'òߨž)¶cI€3‚‹òa¯ân\‚øÍQúDÿ}?cíðÅò¢,¯äÃ^iÆÝÏBù0ˆ90 ¿q;”µ “<æ1ÏFý°Še¹Ÿúaç­˜.H±A> ë\+ TÃ4žZÏIõ°ëÑQ•?÷P»7]ª{?7Õà }Nu¾ÊU%¢u?/ÕÃJäë~ª‡=>s¿+åÀ&œ¦¾Ük•¬{Üw¸ Uî÷ |šQiïAù0ÛãÄZ‹§.ê‡ásb€Ù{kåpÙu€Uƒ~ؘ$F‡F•õÃÒ<Ë•C+ <ÐM´‰0Z6ê‡Yëšäê~ÏPfr '#?žå°„˜B¾á ‡³z–K ‡‹v|ÌÂoik,ûÑ¡zÀÅ6í|?ß›°i1«]lBð–ÍbeÙ)!†¡kðÕƒã'”³8¥0`Ó*Ï8¾§#žožº¹p¸jûëÏ”äÕÂázrÓìGë$<3Å|Ãß;‚*•¾¯A ‡«Â(žm硵îŸíÐÂaŽ ÁšV}z4Xó{j0ų]Z8´ø×ƒøŽÁš–e{¶Ç"bЬxŒsOeí‹EÄüÔ¾nܺÆx ˦…ÃUÛT¶õש¬ý°ˆ˜ËÂôœä´ˆ˜AžýÒÂa[n-®ºoõÁV"/ØHeÏþjá°úé±XDÌ v¬»¸YþCÜñ{78XKË®…Ãê–Ç¡…CG>Ç¡…Ãz]Ç©…Ãê`ÇÅ…ÃNr[DÌ­|W‹ˆI‡íÁ.ôû[K=˜)RD¬²9´pXmqsÏS ‡Õʸ•hÀfµ×yká°Ÿz~{ÎW ‡eÁž$EÄ\eÜD>ë ¸6-VY×n1Å <׈wíl-VoGØêX8´n܃ËÇÂaU7ó…Ãõäz̃êÆÂa[^-VõîE ‡ÕáîU ‡Uú½iáðkÀiv-Vé÷®…Ã~êÐÂa½š1]ŸŠº´pØÙÜZ8ì4«{}??Ë«{a:0ÆòjãgåÂaµ)ÔN¯éu>»ësü¾5ŽåæÐÂa½`üV/Ó—/4×ùÜZ8lË£…Ãj‹çÕÂa9ŠÈßãœ,«Û²iá°êó‹ï;‡ÞÄNƒû¡C ‡ÕÊcv’{²~­—#+ˆ_kŽå•æÑÂa¹5Ô³ó¼ø¤"¤~I^üÛ¡Î3¦2/äÏ#>ýçdÇ`îÚšvwþ@¾X!âwíÅvÞËý«úb‡‚š¼ø½c¹uß±¹OO½Z8ô”ãÅQUÕfÄֽ명C„GãŒéË­=ù®»=¾¾Z¢ dåsháп¡/”9Moæsiáp¹¸úù"°ÿÍöÅïõ"GÇÒ‹ßëõH·ð{=ÆòjŒmÕ¡õ;_PŠ&d “ìZ8¬Â·] ‡‹l^ûޱ¼ ßN-z ~q›ö³Å<éÅmÚoüн#ÔòͶÀÏõ¢¢F‹Ÿëõʧðs½©Êcâþ:ˆö;ò7ë³¼ËëïÇñÜ:µ/¢U¯T}q›ö}f›â6í1–{2ú"„ôÞèþÙ~ø±^¦ÅõËâ;*ƒëíÌÖB8ÝË—“{²ŸååX^. ¢zŒåÏys,¯Êà2íëÉÄeÚ7çÊ»2.Ó~Ž©ôwçX^u>Ç©vå±göâ×zå»áG/~¬×'³Á¯õ6çþr^~ŠZj5¨Úø•7b3êëÞ†ø½}/.ó qiùÁø'¢áÅ‹M› q׸OdˆÛ4y–ßd8ÂDˆ6"Cì<™àH†¡ ³É×îRØdˆ[Pw.¸ q‰öFñ=±á…MF‘Øi¤d6ĵ±ò!b—‹zÔƒ qmëEv$^c÷qX„†˜ÜÂ5¢!.ù|„kDÃ|Šh±sy 4ÄS—- qòfcû GxŒÀ”hˆ;=å·ÐðÆøz&âöpF( 1aaÛ [iÝhxÃ>¨Œ†È†Äk6DQçbÃ|Šl˜iâýÒO³á!O²¡+š ÓB6„eG@̆­(o6¼—Wg]̆ء5 0"F[ ó!BaTPP˜i…ñú…™†PØe û)Ca¦!v ó)Ba—%(L¡·Æsd2f6„Â,œP˜i…‘3¡0ê'(ìÎm(ìWc(̧…ýn …=: ó)BaZ…Y:¡0Ó kh2ÆCbÂðœL>ˆ £¹Ä„™ ™0ÊæSdÂ,j0aÈ„ÑêbÂÈFL…‹ ÓB&Œ|Ä„Q–˜0s&f>dÂLC&Œ×'&Ì4dÂL3 fÂhc1ad"&̧Ȅý3l&̧Ȅ™3™0*#&̜ɄñöÄ„Ñb°ˆ #g2a´±˜0ª#&ìAÆL˜“ û©B¼¶ A-ß@[†ç%aá ’ÖæßÀBÜÌë~Í…ˆ 㩊Ú1¬mºsLjɉ¤Âñ6´·èÒ¡ªŸ÷ ¡X˲E…ñòˆ…}ÄÈXØ) [ ÂX˜Ù 3Í­K‡ª ûª"ca_Ld,ìXû…í¨¸0šK\ØææÂp\ØÙ\m*.Œw%.L ¹0Þž¸0ÜF/F>Þ/lGE†Qe‘aÔPd*2Ì|f’a÷&a¼ba´ŽÀ0^À0š`N`˜‚a8%0ŒÆfQÃ^¶4†WìÁ0,"ÃøôE†° †0¼FgÆ@ 0Œ—)0ÌG†Y2Á°G[ƒaM0Œ4Ã(]`/\`˜‚aÔP`5Æ H0Œ#0ìÆf.äÂHB,Œž$, §ˆ…‘‹°°söIQSa$!f.„´ Ã%Aaÿ. £õ…Zc(Œœ…ýkj(ŒA;…ý'(Œê ³(BaüÆ ãE »-Ä„ù™°û–™°_ƒ™°²1†D˜¹ë‡\@˜)„]]a÷F!^ïíaÂþ‚„Q”€°_‹°Â@Ø>‰!¼ô¹IØ—ô˜3ò`Ö†<د×<ž‹£‚Â~á® y0rF â šËùÆÁHB';Hz„Á,xÀ`³`ta±`ô ±`>õñ½›#X0Z\,ïV,M!Œw+Ì|È‚Y:Y°[ÝÛƒý)3¢`†FÁl„‚Ñ4BÁ¨±P0<÷ö`×O(سð¿P/üÓýN1 ¾d"ùg°ÖcŠE—ÜÄQ©õâC@ž^”dâ·á<¹çG„.ÁÍ|D€­T`ÄU»ÛšøMÊt#® Dz¨Lgì z€i!>8á£À™ æ<7ñÈM%C!`d"¼ñþ—Üü&rR}¢œ—ûª"@µ°%D€Q¸0Ó3 îóPKí ¾:jhì$@œ»XöÀ´ÓBD6÷™Û‚™1 0Ÿ˜‘û dàU:a‰ÓBDÆŒa6âÔݾdÈh<%„…]ÒØGNj_p|²I€™†X $@$aÏb2Å^aÌ\H€Ï)`4…ð›sKÐÐ8ÄÎÀÈ…ü—î ¶G¿HBú‹ú‹þÒBú‹w)úC]Ž=£E£ÉEÑä¢?Xî)Z4|ò® øa“åý}ªŽè/ª#úËŒIÑÛDi!ý…EôNˆþ¢tÑߘÃÊBú‹úˆþâ‹þ¢ÁDñÊIýE›þú«7þ¥…ø˵æ¾`´»ð/ªLü‹ÏUø‡~Á+Ë™†ø5þeáÄ¿ø:…Ñ:¿x[¿ÈYøi„¨ás¹Èi!ÿEéà¿éÏÁÑ6â¿´ÿ¢ˆÿÒBþÃë¼×Œ6ÿEÎ⿨ø/º—ø/šÂƒu•½ù/ŸüÝBü×ß¹ø/ëGþK 0²ñ¾ f"w`&!Ö/œ†ãQôè@X8C0F_†ß"ÀȘØ>‰ÿÂñ_TOü‡ßÛk'¦‘ÿ¢$ñ_ÿ&‹ÿ¢Ââ¿´ÿÂñ_¼^ñ_VG›‚=" ³:Àv˘`&ÀþÎŒ€= »ÎbÀ41gxfCl'Ì€Y2`;aì¡A 5f2`ÈfÀLCìîe ?™†­#̲YCB`¤V§4†ç„ÀHAŒlÝQ Ñ¢¢ÀȆ˜Ù Œw' ìNj Œw' —„Ñ4ÂÀ.[oA˜R`TGoA˜O‘³‚¤ÀhŠý^·(0Z\˜R`¦Àð[˜9“£ýD™†Õ† ÂÀpS# Œ:#a`]ÆÀþÅ3FQ>[]ùüzáF GaŽÜ¼öÍ;V)jÝuŠî§w¹)º{¦"E#ºT‘¢û%Æ­HÑÝ ïmƒâD÷»b7'ʼnâfÊ®;N4,Š ‹âDâ8Ѱ<ÌäQЪEÛâ@Ѱ(P4,  ‹Eâ@Ñ´0P4, ÅEë+· „i!¦…@˜a[D„i ¦…D˜aZH„“eaZ(aZH„i!¦…DІ…D˜aZH„èê<Öj"ìv7æS$´ ÓÂPÑ0 ÓB$ ‹CEÃB&L ™0-ƒ aÐFŠ 0¼æC¤Â´ ÓB,L ±0-İ ÓB,L ±0ZYX˜bád¦X˜baZˆ…ýU 3 ±°ÇcaTYXO ÓB,L ±p² ,L ±0- Ó@,L ±0ÜFaa¤†[ÄÂ|ˆX˜bády9’·…Xˆ[ÛÂÂÊM…ù©0ëG*Œ!*L ©0òö‹©0ª*ÌGH…i!FÓˆ 3[Ra>E*L ©0,¢Â´ ÓB*L ©p²¼óPn*Ì4ƒ ûG×T˜ £m„…ÑÆÂÂxJX˜–…Q¶°0-äÂ|ˆ\ؽBXe 1•Øt¨X˜Ù £ç 3 Á°§$ÃH#0L Á0œ f‚a&!f‚a¸%0Ì4ô 3g‚a§1¶ëÃLC0L Á0Ÿ"vYîrE‹F6Ã̆`˜i†i!FQÃêæÂxF\˜Ï 3 ¹0j,.L ¹0Ÿ"¦…\Õ!ö'b, Ç……‘¸0ªL.Ì$èŸÀ0Ó ÓB0L É0‹d˜õ#f’aXD†ý©™ £(‘aTYh˜ù ó)¢a¦!f¢a¯FÃ,‹h˜–wz BÃ(HhØpb4Œ¢…†=N £2BÃÌ™h˜ù ÓB4L Ñ0-Dð Ó2Ð0 DÃp]hN £ÊBöüBBÜ蛿/ãY#°QQ¡Îé ÐV+®ËöRÀØ%€ã.à[€dÀÏrñH­!ðËg—P» p„øh $¨]˜ai®<,øYÎß'!™q›‘Ž!Þ’ ¶„ø€À¾tØ8Dÿ–Œ ]‡!÷åVIP£¹¸I‚ÚzΆÀ(Zø¥Yu}˜ ph¾yZp+ÉøV‡V’96u¸R’ñïl+ÉàF6Z¬$ƒ0>e%™r«”d,ÞJ2_>ìÿ¥$c±ßV’ùêÃ﨔d,ÿ+ ̇¬$sì’+%ì*Òb%O ZI¦-V’©+%ßiÑJ2v¢•d\ŸV’qc´’ÌWSwZIƯ¢•dü{]J2n÷V’ñ;n%™~ÈJ2ý”•dÜ<­$ƒm'nÚIIˆN̲’Œ_D+Éøók%l’è¡”dܦ­$S­SJ2ä­æÀ1)bT^)ɰ{6 …FJIÆÓ¶V’q·l%™*ËJ2î•­$SE•’Œ'W­$SŽ–’Œ{e+ÉøºR’©w^J2î•­$S/«”dp©1ËJ2õT)É”ç¥$ãie+ÉTuJI¦ª\J2_éŠ8µ’ h‡õ±’L5O)Éxh”’LµM)ÉTA¥$S.”’LõäR’ÙwõÉR’é|¬$㱩•d¾4ܦ+%™ê(Á1”ë)%ÀXîFs•’L}Yµ_+ÉÔ‡UJ2 A0-%™/ÍÍ=‡tÒó»•n×õ:K-×ÿ–bà™¢ÓwŠ_=ó×âÐ?ÿšÊ¹ú¯ì¶­u{Ë‚ݸW²ºvú+ó‘-ò±eÊç›fW.ã¿§<`ÉÆßÿvápþªÿ«ÂáÇ?!~ÿ’pøç£FÜÓi©åŸº Vú_õl«‚ûù”w‘JùL©”Wë‚;¯w^‘JyM©œW)ƒW^! ^yu*ç•©œWiƒW^!^yu*ç•©œW©ƒW^!^yu*çõ/ˆˆã0ŽÞþ÷ÿ³año? r¿ÿöó×ñÃÀø‹/ä§<þqñ1ãÇÌ1eÄ['üW*â!2þWâß×)ñ¡‰öý’ýBJ"ÚÿGý×ÿú•Î÷ÿ Râ×/¤Äÿ󿨔8$*ïß[k­–K  ~9) ·èwzc*{ðïëø=#b?˽#`ýûßgÀ î,܈+\.YÞ–qšŒ%mߘwü,{÷C–ozüÛ õÈ‹eoë8^¾íZýþ,¸ó7 ÛˆRÂz1\ÀJë>Ö¨qÕý9I|–ï“ù,˜.?*Î0k;TÐËg‘âq.Ÿ [œÂ 7\Àz-… °ž=\ÀϵËòË^9ã>h›/’Qø,Ÿ ŸSXY[•f‡Ë3 áKójküth)¾JWe~sÉ›õÛ±šËßè".W]G¦<ã‡yë8YŽûã•é±àÞ \ø³^2ŒúUN%aý±¢r¯þçœ vT†T»^Êã4ãFN—{âŸbÀ¼z‡C·ÄÙ0ëßÇŸPþŸ:Û»¼SÇÂMk: eôm*è¥uìÜrÉ­‰Ñù<8G[Qº×˜Óäÿ> Zrú _yzPíIáìøaÉvÀ¸=|r‹ß‚¤×±Ö²Ç1ÌuL òëWK#^•°ŽKnÏ8Þ¹Ž›ÅR;f×ÀÝ٭ƽ²O~ºxì÷î{d³©¾¸ûMCÆ÷oŽV+¦#ý[»r  r Ûå¸Ç¨”›>Ë3&@™æ øf÷ýá=ò Fƒõ”ýVp÷=5.ã~B Ý~L€°wϱó›˜ãƘ• ƒ_ä5g*ëIp7¤ºÑI¢9Ï—S C1!°Œ9Ðm½ÜïûZ½'§¹Öû‡®vÑ…~—Wyà¡Wqÿ`9÷ÞÓuísÑ÷˜ÅÅ·_äí7î1ЩK.X'O„ôz¡;÷½{ó šú}C'q«Î™–³¸Î÷.Ü ·<èúá&îwzs7´â[Æò:õWü oS}‡Ä‹8c_z÷ŒõÌxÝiží’O¤q ÷5[Îäv©|–sÌä¢AŸr¡Êº·©ë=Ï:µ&~ש‡ày 3Œ·c—®pa8™ï;<€eSKh] ¿_Z–üÇÔÁ{ç÷có!_à6Z^dÜ»pç ½k;j KÚC˜¹ Ø»ÀRGÂ&œB'²6^ ¯(áRùÇ05X¯ÕÂÍz­òmÖkMoÃd½=Á'ìa+Ös Âô¸=Ýìá‹ð쉰ׂ؆½–¿6ìµ¶µa¯¨ {ø´LÏ„½–:6ìµ²¥a¯ {-hØÃí»Ïݰ‡iô²4ìÝæ:’öî ëˆÊuж›íiï›·«,ðãGqÚðà‚¶€ÞqïÞ,la܃åQÛ÷p70ϲš÷0¦uÈ{°ÜšøZ¦”À7À@àCâƒåšïÞžj_"ß•yIäƒEË §ø¾ EìFö¥^ ‰o² â›,ƒø`9$>ÜHÝF_‹Ã›øò_>CâƒÅ‚Ä7=5ˆ/Èwãש4òa¯Ò‰|¸ yÕk!òMiòÁâ®FäC}yŽî‚’Œ·|èúÝòa‘¹lÈ|Y6™íå²É|(‹º—f¾é©Ÿ| óÁ²l"¼LðüP×!ó¥Ÿ`>ü­ÞFæÃož±õ‘ ˆ’E.tƒ’ù ãÞ|„¾|1¤>8믕ԇ§ ù\¸L ¢>Ô§rÌ„4BQ_>êÃ3ΗÔ7Yöá™{Iì»uê4š¦§4MO î›,ƒû¦|÷ÁâQé•íÕ+ªÝÅ}7ôanYÖéqßdàe ü¢µ~ñD~á§È¯/T0ùM9ò ÏE~¨±ÆZ‘žâ²é¿t 䇿/Ó× ¿x•B?¤9Yú!:ˆw2ý¦4t 䔵%ùM•è—õ'ú¥×D¿,j.teÀ~ñ®Å~Óƒýð ï¸0û!:™Ò:f¿)<¨¯Nì³Ø¿é~Ûd¿|·d¿øÝûÅ>Ø/{È.º§‘ýâûüÅð#ø‹áGð7å3àý¦‹þ²6¤¿ôô—mAúƒWî8¤¿Ìó°ôê]¿£|p‹’ÿ¦’ΉºÉSýÿ¥gùàÚœåC¥ð”5$ÿ݈FV/ ÿe ‚ÿ¦¿æʇ(›>dIƒžòû æSÀü8 €éùõ“$Àø!NO ~ʯ8¥˜^‘§’ʇªß¨üöˆ€™†˜9“3g2`Öï–‘|è$N–{›Æ2àT¿Á€9âÜò¡Ûâ‘5¸‘Ó2`V˜ 8¥9ކ;2`:þ” e¹çÑ 8åú.?¸DŒê³í^9ÐUyË?´ŸÓkú'´À øŽ ‰{~1‡ñžŸÕ`H7ÓÐÇ=?.-Úäžœ]E}ÜóלÚ9äž&s©où=…SÌ-¶fœÒ ÄKÛ¯´)€ä28‹'Ë`¨ç«¹w.Á-=d|Ûì|"õÒÞ&9óµW~’aÙO1Þ ¨çND®Þ×$bøø‰Á€èbÔ»3>×Sµ#æ®*ðÁb¬S@ k…—ò øÜ‹Ä¨Ì€Ø‡uíÉ€v–d@מü‡\/µùo² |¹j%ò_ß7mþ›Jü7•Œúc†è Àg›öŒÉi!ÿ=#’)·üP—K{,ä?ÔÅmK|°J)D¤XЕKä¿)›Á¨ž»ù/+Lþ{ÆR¼pôaõVç"ÚBþ{°Ô©ŽJþË|É“eð_6'ùÝáÒ²Ë%ðAý½è/kGúK¿IÈ÷ÚÅ•ƒþ²‰1CÍv ýeG¼åÁ6‚pþ^ô—ù’þ¦§ýá)jœ˜þP¶?Òžò^þ->ïmèô`SåÈ?x¾{—rÐ_¶èoþû^u7äC¿âÊ~4`ÿ²µˆÑÙHùÂI°<¯öåB7Å#î  ýMUä„/ê\›þò+$ý!¯õMúË’^¹ðTèéoJ3ÈiÊyÐ_Ö†ô7Yýåë|Ë¿Ò_tIÑyñþärº~¢?<˦¿è¢?,›*rDôµýM9xŠú‰þâ‹þâí‰þþƉüò‰uÔßbŠxÁ× ¿E~HÃÛ9L~ÑëE~ÙL$¿)ŸNÑ_…~ñj…~YѯÆß”BèEðË< ~1Z üò•ü²™~S>ªu_ßly‡¥Ë"øÅ€À/Ë"øÅh4À/_ü.jäøÅ('ðË'øe[üâóøMùȇnQ‚_ŒŸ¿lA‚_æCðË® ð˶9äCi¿¬ÁoJ3 )ß Á/?[‚ß36Ñ_?ù@ð‹aDà—9üòÍüb0ÀïÁ}}vìøM)è®àTºÐ³%q_&y_ rÚD[8ê~DèÃ#ç®4U·ø¥ú×/¿xB_”tíSŸ&òaêç] "_¾ëKÕo‡ˆ|1ÐøÐ=75%‰/—Ä_vžÒ”E>ôäEkò¢†„¼ð|@^| †¼~ß‚¼èù†¼ÎW—Oò¢ç‹òbMD”—OɇFvQ^æ#Bê^Û”ç>@ÊëïC”èjÊ î“ÝÿDyñ ‰ò¢Wˆò¢Eyá•(/|0åõ7-Êë|Lyñ«<(/æ ¢ø7^Ì"êõ×P¨W=Ô¨—iˆzýÅõz¦jÒk·Ezx9šCŠô&Ë ½˜1šôºÂb½¨à`= OoòeuÅzíÑTP¬Í"ÖË4d½¬‹%º%Ð/EÐqˆ':³† èÄRŽ:ð茆P@g×pýÑ…ÍŒhÎnGsFUÍ™Ï0š3ŸªhÎ ÌT4gD|22ÜV8çdyõýì>–ÇpÎ ³¬pN—5Â93Å>7T‡s:fµÃ9ÕëΙA¡ çŒ@R…sÆSåA•­PÈ.ËᜳÂ9ã)‡svÃ9»$…sF›;œ3Ò02ÞÂ9£…ΙiÎÙqg çŒú)œ3- …L Ã9£>çì75Â9Ã…sFýΟ”Ã9#_†BÆv8g…ž9š³ÔÑœëhÎ~UŽæŒ4Š„lÍOs ³¢9£zçO.(š3:º£9»›8š³œR0g<ä`λ~rá**!â@Èv“Áœ‘BÁœí‚ƒ9Ûñ«\¨²ÿ0˜³Ýt0g„On×<}¨`ÎË<~˜ÓU0gX Á›÷šÏ“"sF½ƒ9»ÆOùà’ͯÜÑœÝ¢ŠæŒ/ï£93|ˆ²îi­hÎ(ç]~ÁÍÙ8œ3,ò óU8gZÏéºüB®ûµZ.‰Ôi8ÅmÆ9¶·¹´¬Q¯O± õ–³&*B½å®u¡œ»óüÞ˜ü‘!Óõ–ðê-¥ð!ÒË$rá­sM"½¯ÊEŒ×1§Ðñ½°èø^XÊ…:š'Òòþà”H®ù˜I/röñ=œ ûéø^Xt|/,ãø^ü=Žï-u°M¤—Iz+äm­Í2Æ…É2Ç(©|°W½µuJ„{ñ”p/Þ‚p/JîåSô!Þ‚p/ó!+åSĽðS¸—iÞ¹oÝåƒó½Ë·x/j#Þ‹’Ä{Q’x/󑑦|¨ú•¢•Å{Yy/Zpð^ä+Þ‹\Ä{ùLùPiK™y/ÊïåSä½Ì¹|xç|ùi)Ÿ"-ÅSøòo_<#à‹¿?ù â‹^*â‹Úˆø²,_–EâË4åC[Þ¹¿™ø:"_¦ òumŒ|¯‘/s)û#1e>$¦î]F¾Ì‡È—õ!òE>kùPøÐß™/ÿÌ—2_”,æË\Êû$æë_!3_¦!1M–wþ]2óEYb¾¨á¶ýðÌ~ÍÿN^Êd¾Ì•Ì—2_>E2MyPeé_§óEû‰ùÒBæ‹|ö}n™ý'Ä|Yy)-d¾´ùÒBæË²éCXÄ|Qº˜/òóe2_Z޹ýÄ|Y}ÈgLiѾî[b¾Ì‡Ð–³|p« ú"gA_ZHLQgA_¦9ç~"è‹ú?ù èKË»üdáÜ®¥jD}‘FÔõ»Ê{~ý䃨/ó9÷¼Ô—Ïú2_R_¦¡“åýÁ"ê‹ÖõEÙ¢¾(KÔ—ièCæLÒrm?x5¨/ÿ~~˜™ú2 }ËS>¸$Q_ZÈLiÙ˜™úzönêË4åƒk8¨/S<ó8 êËú’ú" ©/$2L}ñÔ[øM‰úÊ’ÚÜÛ¹œTþHïÀ¥)·µ¹õo“6w¤èô¡Íý‹gþmîý›Ï}¬\ýWêaËr¸¶¤¦öÇ:ø@þšò¡-ó‘%ó9¶1¡³—ú+ó‘-ò±å߯Ñ=ˆòú—4º¿Žúÿ‚F÷܉¶sÃ]JÆ?v™3ÚúW=êÛz~RßV‘JùL©”W¨o+¯I}[yE*å5¥r^­¾í¼R}Ûyu*ç•©œW«o;¯Tßv^Êye*çÕêÛÎ+5ºW§r^ÿ‚F÷75;ñÌCî?ÿöÓ`÷«ño?? ¿øB~ÊãŸÐèÞÞmÜd‘Ý¡ýÿ¬Hw‹ÿUFÏ¿C£{;Æ]Zÿ¿Òè~~¥ÑýŸÿ4º·sSd¨bðŽßpµ ¤«·s\ЂùË¿qÁR\×ôYNݧ[¨>Ë…É% xå,ï¸áë’·æ ÷3†_ùFËsÓ‚ùã0¼˜[‚Wxɇ~Ë9FñkÜ×3,ë1Fÿëå…}ŸE£?ns“.¬;|ø7.cYqümç߸ž –í÷E) gÞßO¥¹ÆqáE¹ÞÏpéÅÒÂ0°þ¸¼g×CríÀŒ±>,ïï}¯–ÛNú¼SY.ÄÙ¶]‘Û# é¦’äÃXç†û†1ÐÑòÜé(轆SßCzï2®²ø¾ŽßÙ«^T}*éµ·ä5·wßhyí÷‹QX^‘öYpýVO{¿ßä«?^:ôò²£Ï¢úG1®ÿ×Y\–1,«„G÷e9é‘›j_ÖƒÙÇ÷š^óSvààõGŸÅœ¼¾ç³œ‹-<¾k³=÷åz™Ë©|ï‡^uÙÏ=¿•ïGýš½ÚWûP%}Ÿ9-/Üú,Ûî÷ÄöúÆû^•ß”Ë^)c»ðüþØBp£‘Šº:5.m–ûÉ÷¶¯8Úo{ÿ~߯ ÷>< ³oË9÷´}“¸LL”0UfÛ7ú´ü¾(Ÿc¥OUø7[>Aqî’åN!’PiìBµÍFÜ“öí¹§·òu¿áÒøaøÞíô5}s¹ƒÕØYÿå½µ¥¶ïª?þåìØ>¥×,¸Ð?½¶ã¹ÜóÔ!úPµ9åC7~ñ[tö3ýmú”Ï}ó‹R·:•]o—2ù÷k¾ŒÓ±F]h7Oº€$Ü<ÙÏûþýžúÙù\vÊ¿'Zõ[³ãæŽéoºÐoî²~µw¼ÎoŠ@žíy }ªlÎ÷‡ñ຾ÁûeªÉq›×=y Ðg*jìa£%V‰xî÷:ßäurò¶ÕTw{ N~Ÿ‹‡ °¸úä˜Æ•ûzèÔ×Îzê¾éT ,·\ÐWy«þ=ãÆëgÐpãõøyÕ…xŸeۧߌ¡“Änuë™cõ€ 1ã±÷ï&Þ;P£Õˆ-Ÿœ§ªæú=—Ǹ]iÞ“.Õ8øÚÿï¯}8ô0-Õï+}x÷mzûøI^§1?ÉÛÔ˜¸ädÏéÕþʃõõwõè#UÆ¥““¸ízú):pÛõÍ=dYw¿¨;àö<zà–:–cÍÚøEž<:ð‹¼e;}þg~KÇâú»½ÅìV>–÷üÁòÍé9µ;ù qà¦ëÙ#ÜtýÌ–÷üâ"NYŽuªÌjôÖü O»?ÈÛäåzßžõܲ<×>­öÀ}ñØäA}f·×Tm«yÏHø†§‰Ü‹®_Z^Î…]ƙ؅.úzlY”ææ4¨ÞþöÔ,H|3F÷<Δ¼`³a!‰Oíö |Ò2¾í1üÿÃÝ¢½k¥Jiï‚vXä¬%’-Ø ¡eÁÞÙွÇY–„=¬ÎŸ»Ò ØÃ0¥óc‚=0ˆÎy‰öð”p„°*p‚=Ç%ö$ìḎÄìAj@Âìads¦•D;Á`=ìÔ¿»-ãäÀøm‹õÆébFýãZ*Á^È® öÀ1:J+؃Hœ´ND{q8H´‡Ý…ÃOÁ…óö™CávöBFN´§CK"½8Ú*Ò«cÝâ¼8l*Îëã†Â¼8¼'Ì‹#”¼8Ù(Ì‹“ÁóBœD˜ZJ¼¥çÅOq^œ ç…`8/$‹zxÖMKÐ:è=ïVEÐ Ý&^È÷ Ð ¹$±žÑÁF±òÕ¦ Q/ ƒ’àÇfú”„ßJ%éa“H§âEz!º$Ò‹öé=ØR0£ L /EzÏû}mNs½y%‚Hï ìbÁAzÈW7¨‰ô¢­DzH£î+Ò›,ƒôžqÁ¹¸n<¿œÏ =”®ÓØB=Xv§‘¯¯êÅû¨/wãá@½©ìzÏGzê³b½¬Í&nŸ]ëå›!ëeYd½ç7žÿ½P/_9Qo²È…vs.Dõž{.x ^6Yï…l¸^.a.éàº`/;a/¤1{é6aµ¹ˆö^Ä|éõöPº>zÁ^\Ï7`/´‡ßN”ž1Lý½P/‹%êÁiI õ²"D=X4Fõ²aˆzÙ0D½l¢^öE¢ÞTú{Meõ²l¢Ê–x—P/Ü&éeo éeÑ$½ì§\x­%Ô›,”¦Âê¡‚â’ÖtNu^¿r Ö;»Tý~)ä¼lr^69/Ê%çew!çEÉ£ò9‘òò# 奅”—.ƒò¾Ÿïo® ꘇׅyÙ?n9àJDyù}’ò²HyÙHySQÃ…hr^&!çeÉyc¤18/}‹ó²Èyù ÈyY=rÞ”fPR¾r^örÞT¿Áy9`órpzåCw‚^¾)^¾’^–DÒ‹÷BÐË1… º|½l’^~)$=d¬§DzñbDzQA¡Þ‹½aÆ2\Ø=¨% õ¢É…z¡Z!Ô›ÊL–Çs9ýìõâÕ õ¢mÄzÑgÅzY²^Løë¡»r>À²òN°/J° Á^¶ a/Æ4Á^tQÁÞd¨”oа7Yìe}{Y:h¯±^¶Yo² Ö‹+ØË6'ìeÉ„½,y/*œ V;ø¾§.# ©é+ÝD$àË4>Š0ª]Ä{QßdqccâM¡/r!󵞞©/¨VÔ÷¥)¬’]’°/òöeb_¦9©÷''cß—âÒŠ€°/ºŒ°/-d¦,‰Øa_”-싲„}ñ„}Ñ)„}ѵ„}Ñ:û¢~¾/…~îŒ}i‘·%· ~¯Á¯}0ø}e-Þ¾#øµ†¢Á¯[Ùà×~ü&Ë;w?‚_¦ øe¾?œDÓ^‡À¯ßƒÁ¯?ƒ_Š¿"q_.îËl䂇c_æKfÊÚÜO~¼Æ¾LAì 8#õE]D}ñ¨/Óš¢iL}ý¢„}ɯފcûɃA}ù÷3 ,¦¾ÈƒÔ—M'ê‹êîåÀÔ×=MÔ×ÕôåCú² }ñùúb¾8 /Zj@_¿WA_d!ìëËØ êÃO†&)¢¾L¢êG.$&üø-ôanÀ¹—¡/z™ ïKs, }¡a*è›,„¦h(A_4‹¨¯õL}i!õ…¢¾¨ÍY>”…à”–A}Sίµ¾¤ðDì‹×$ðÉRº ð‹Æø¥åàí¯e¸~SA'oçèw'òÃÀ&7¯rÁûeÎd¿¨2Ù/û… D¿¸`Dè7YäÂã©Ù/*,ö˧û¥›d¿)ÍO.Üráör«à/ª,öCüª|ì^‹ý¢Âd¿ÉB¢zÏO.ý¦Êˆýº2ýb hô Ÿ„~­"gô‹nBôË¢€~Y=¢RœÊd_ÖWè-#ô‹%ôËÊœÒ2Ð/ZKè×~‹ü¢p‘ßôÐðÀõ%øµC¿) ‚_¦àÍ"ðËš¨ú‘d0Sf#îƒzó#‚#÷u§÷E}…}‘1±ïö¾La_{@ì›,ľÌe`ß”±/šn• f“ 3±o²0p<Ê"öÅ»öeYûðëqyÓïÕ0§,ð›ò½ï¹ï ü¢ùÈ}é‚¢Ø{Ä÷eeû¾ŸZ?ø+an³Þst„8Ô!WÝ79HïÁ%GmÒƒô~æEz80#q‘Þ³Ü"½q”qÚÚË|HJ8î›qœHR;l$½Nâ½mÄ¡þ½A/’ÀVá'è夤LAЃΜ#? zˆ5úôZoÒ —iTÿªŠ81 q^d#Îëû©ÌyøàôÐð ȃN@H ´±—r^TW —‚^g,ÎÃlpŸÉ®8/6[Åy™†œ—p^æ+ÒBÂBFŠê‘2 1/,¼~H”uåEc‰òÒBBŠlyY oúûýÁ%A^-:[òQ?dÆK /-d<|Úú!ã¥EÄS¤ÉòÊ)½K2^WØŒW6â…á'ÖŸ<áEíDx/Šá¥EÔk2âeR~O±F¼LAÄëÊñ"ÉV¸ !^TFˆÙð2^F¼Ì¸Ê4ä£Ì™ŒÕ!âe’ÙóGxñ„/ª"À‹‡Èw™„|ITýHòSõ…wñé.ZJtÙ º‹L®r`™è.“2¢QZHw“å]ÜEí®ÛeÙ£N"´ Ã:w¡]ÔDh]áþ©þB»(Yh—¢]>E´Ë4ò Òȃ®¡Ð.-£´lsýÄvi!ÛõÜÌl—iÊ5–Ð."ÚåCd»¬ Ù.Ò¼åBY~rAl3Ø®ç…f»´î2Â]–T>”å¶®såC:Ê4„»ÎÙp×iLwÝ:¦»|jßæ¿uþ›p”yï²â]ZäAäST>„£xJ|O‰ïÒB¾‹|x™>,ßÖ¢|ˇJA8ê6àetŒ|¼|ª|pm¶ò¡,¤£xJ€e ð2 /Óð2_ù)x™ /ÚX€—ùð"/Òˆð¢,^ BÿŒ4·#91÷?:’Cᡜ÷úý8Ý¢2…rnóÎD(Þigo{ß÷0\V6·Õ©Í• älqjr¶ìŸp/./ïµJ¢p/ ¨?ÎR(̸½!†‘qœøÙ9綠É2ho²ŒêO–Q}Xž+·õ&Ë ¥É2po² ÜÕøì]¹`Ã¥ÉðN¯hp^þ90/ óÒP•?ò¨^"¥a0^ã¥a ^t?!^&ù±æ¼4ÜóïÒ0è.xI¶«N¸KÃ@£4 ¶KÃ@»Éðήl?Ö|›k¬Ë¶ ÖER]&!ÕMÕ¼†QÝdX4YMù ª›Ò ¬›,ë&ËÃg¶W(ø^ÓßäºÉ2À.ZÝ”f€Ýd)Ê"–ß—ÕÛy £ëø~ªäÁΑë¦$ì&Ë;gB²‹LHvS’AF“eÝdhw_›ÞÏÚÁ²¯>¬G_v!¶›,&Ë€»É2àî:îqaÇßwÓßòᆠ-òáöéBÂ]]ÇWšOø ¶›rl7YÜMy–ÁF“e°QZˆw“eË&ßE…ï=¸åAM†wxÔ>’í&Ë`;X¹x«þ—̈í2 Ùn² 0š,Û>åB¶ƒeÑ!U²Ý”F.¤Å>ÔSŒ&Ë€»É2ànÊgÀ]¦yˇ²”~Šp7¥ÙQãÓúÁ‚»)Å€;¤q„æ`»4ȃ¯¬Â¿FH²ê½í¦4íÂ"´ƒåÚOí&‹<8~_®Þ¸›þ>ÖùïE×ñį‚:ÚÁ²­‰vSy%— !ÚåSD»,h—eí2g¢ÒT°å1×xýɢ݅°4È. ì`XnaÜ;Œ÷«]Cy°ùb ,»< ØåS»Ì™`7å3ÀOIm€Ý”‹<Ë»©ìvÙz»l ‚]8N®Ëêír!,rÁÕû•Þ¶øíÅ9àï›ß&U•!Z‚ƒ–Ú‹£îÊz^ ‘îJHŸHweÅaïàñ¼.Ž+ uWB^Dº+CP[ø^>W­@ ¯ôÁO ¯Ôië®ô‰hê®lǦ3³Ô]ÁßšëKw¢Ÿ’Èî D?]0uW¾æ)µê®À²è)9ð5ôF$¼²A'F±ŽÒ-ÁYGmœI·d¢þ½Õô‰, ¯\§]¢òÊõøÜœ<¸nù/ᕯÚÖP‘j {“àP ÅXy%ž¢òÊ‚ ã<‘÷Y.«áHyc›„w¤¼Üx26ó³¼nc)¯,ØÕUÎP^A G^(N 7žy26szŠÒ% Z“å²~’^‰²ÉrCÓ7QîK²¹§IzeA,}¢0K#€¥Wð”Ã,!½‚æÓ>µÔW–e-¹–áÂø­PAö`ý}ÉÈÌ(Úâ+HãCp_Á?XeÜP.>22óEt½wÓä‚ýÊ¡6¯fŽÒ^i¨½‚¿omë š› 8‡jK¦R<‡—¹éw˜@÷¾um–ˆî}Þ"'"Ò\¶Át(kóNÞ€º’å›ò¡O]ì&ªK¯ˆu°H”pÝûî–NØÁ­K‰ìÞ·.hÙ½ã™,ôá­«ßÄvðJW« îPãKsÒZçÙR}%½"ß½ÏSıɇú@áM%}|”í@ÄË÷ˆ—yñÞ!™Ià ¼¬­ÎäEÕ™< €1Ö?Ó >ÊÖ#ὸ;Xá!‰n³á¡6÷Gòºv:‘÷½é#µWÆtR]“€‡$¯%Ràå+!àÁr^ƹE/É}Êvò”]_ȃ,™º´NäA–Ì9ÀCÇZC|oEêã¼ô€‡g<'á¡ìÍ’(<Ôö•½¨CëTZuµeË»ë6 !ê'Õw!^‹‡ "Þ{—n®u–ºæ¥óp,E¹è`Þí«=|.ñšÎäÂUTMÈCÑú•åá)¿NÌ 7u0/>Ì ÇïrÁƒNæá.ÎI%_ (/›†”|:™‡cø y(z¿½¥7\øÚ\S|Ì»K{Z—Né`^÷}2^|?¯è\^9ÐÖ±¼x/ãX^ÔEÇòpeöûw9’ñ²¿åÁn OµE“òÞ§´•}.¯ÇŸËëœ}.×­ t.-䧆Uãyѱ|.¯{§ /Ú×çòº«ù\^¦) 2:—×í)È‹Ö佸MúÒÏåáÞyxo3^ $b¼© jÃ}ãÒþ+ó‘-ò±eʱ¨%Óí¿¦|hË|dÉ|®{?«µôWæ#[äc˔ϯZ}Îg~ñnþýrßÇWð×Ñ'¹ï*®+Nbþ¤®ÿ‰µ²íϤÁ™àG=åL€Óº&þƒò÷=ë]×VGþ¡Uqôªà|2½ñô¤ç­"r™µÁ™Sêy#§IÍ[9Eå4+ƒ+§Pó9¥–·sê4ÎiÒWN¡å=rJ%oçÔiœÓ¤ ®œBÉ{ä”jßΩÓ8§Eíû¸Áÿ žÿd°þåùÓðü·?j§1ÄÿSbßç1Öé&±ïBÍû—놂øñÍÕÎõÿ†\7(ì3ý—•ëþÏ_Èuÿç¿U®ûûl$ÍÿúŸ¿°Y®{¿þB®ûÀ;ÈñzkT¿ÆK)Q¼ÛXÎGŒÅ4,2o¿á&7m7ïîûâÄmÇ{ŒE^H©rôž#Ú ·/)¦é½´þxüî²n®?^·VbA™ù~AtŒ¥Š8r õÄÒÆÛå¦๬’°çLï\† ˜úêÍgËç¶rÝõ\ö±úxî^Í=—c¬Ý‹Õ`?º«ˆZ®±úxŽ«‡á>8ô®R7?:p]—:Ïå«ØÒ•2¡ÂÇÙ0¬cññùúÙ¿Yâ×ù±>Ïs·ßßcññÚW­…Ÿ+= s™ó\é®ê‘ÛXë‡e»´yBö@…oþ~áb¤±ú8.êSÙÏ Ä…Ÿ¯ÒÐÄhqúznra½uzìÄ~,§ÃOˆÂ)T™NlßûYñC)sÛ‡äáýGÜA9¡Íkp·²¥ ÷×CWYä‚3¹‡h2‚ _ü Ùçû¾\“w¨>?ìQç¾ ÉgèÊ›]uÿPE½aWå·åw=´ ½ä×ǰ¹÷}4À"`MYÇÍDœv£Ã|†¦Â¥4×Ð|¾G›kÃK%yvúS=s7ú㇎eüLcõ^mòqßxA¸Ej—…Ó„9xèà<äÁçö% <øÆl-·ƒÿ;ü*×s(>ßxƒl¨ã’Ï÷y»£òwÿ{×ïŒÞû~]† Õ—ü_ß®ï8‘…ïû)¸ì3(ÿìÄ— Í 4 ÄÀ „¶ 1Ï?Y®o•í G}z®ºwN~‰Ëvl^UemW„òTÊÖS&+œ,U½]½§LV\sèWóYE<¦=峜+CÑ(oõEÛ D»òR ¥¨#ë¼Óè,¥ötÉ£*Ë}E‡«dÝ,å9£Ã5‚ÕKi=ãó]a·Ô(¾~EåÖ(þ©ZŠ2d®-T'Z(k¥žwt:oÖ)Û½….Í‹’fö³¤è •ò¿‹ýÂSîž+YÝÿäÊÓ“%Oߎ~:U“·+NÜ;ÙÍ)E¹·Ñ麻mCùÂí1ùGgO–,9êæÊÕÓ=«®ŒïÒÓ=ëð­ÂËk‰Woü&(«L´ü¨®xFë¹’GQëúCWö-zÝæÂ={Ïö¬ñâçèÙžõãØÐ-O Õ‹ÆVÊŒ{i¹§ôlÉOßìíjOö¬Ã:ý˜[•y]®^%‘Ü£0.ž-x;Wü¦aB?³_Ø»öªbÓ‹ÚÞ¢•.OíèÚëÓ…Æ~á¼£‘N÷߆'‡`”Fù§/(­^ñ!]î!Ú«èÃ]õ úNÄ2©²ßW4 Ï_NÕ,L#…Žõ~a€¥W0À#mÝŽ®½Ž9ªng×^%¸Æ¾\Ý®®½V3ò{¥tñXÇãùÉaÂðê&Üí¤êö𮸠#n¥ŽÇjÞçO½j">¢­c±QuàHo•êíaÂÓ·tú…óöˆÍs¯=ïfÀx×r%zžÇ»ª“®{Ï»è¯U']÷V±0Xwà^þ+G”%ÆãúNÃSSמ`XDŠþÇwÌ*‡º†·vÓöõˆâßmgáS(¿F™ƒ÷í]ÛÖñ¡W‰Üðâà ~å>cZ½™ÊªŽ¹~â];WÚ”ï:»›Ïyy8[´õ¯‰X&is‘;޾ð3[=Ï;lÊÒWµMt˜3,˜Zö ô7®ô³ávÓÛÿ|Žh"¯ÂªÎ¸^>œª3®Û<Ô«0Ýh8Žmƪ‰x_ ¸ÎXöHp #¯+–=£_%–=£2¯ç|ʼl€'z… ú*n~ÕXýx½TuÊuà6wWrÝ–w½“qü†/²„ ˆèÐÆ÷§}¡cnë;ÇQÝß9/¾l–wR «š;yyqñÁ›fêë{ùJ+Û$ÕÁ«¹n±váÂÑH[>䌜ŽA+ëÅ.?„¨«]\©WØt0l×z³‚ÛðQ¨õ‰Üsç»Ø³iOÌhõÞXÁå÷ÄöLZùÍYº¼»ŸÀ4Až\0ê yZü8}_@^!ÍCžÄÂD¾x:‚´áÛ€WuzÆ>^•Ô€4€7k àu9ÎW:àÝêÌFxSÊNxÏÑœ ›²7Cx½L•§œ]NŽñ$û°SoÄ´ ÞV›×Œ0ÞÞ½†>â Šüàà# £‚xYºÁx§2xMŒ§±v‡è‚ñy2À]aÂùlÈ#f¼kóé#f¼³<^\Ãx×åD f-ñ*PO‹h:ºQOÅð× ¥Ý§*.›°1’z¹~î¤W…»+éíö¤W½ `ÒSý®¤w6w+H¯!Ú/zÓ zÍÍycò3èéD_n Îs  §¡Xì ÷þàèåÜhÒ›X1@O+0@Ä gˆRsþOʘmÐÓá¾ñX@O£Õ½€žæ¸Æ@oq€Þ“] Ð £½Þ´çÕj¾1çUoOóRóÔ +W‚·»ÌyOŽpÞ£Íܸ˜71&˜÷”j#;æ)Ç©±úróc`Þóö (Éœ×5þ˜8¯7ÕÇÀ<nŽR‰yVÌÓÄÌc(¿f[®@IÏNo0åÕ‚ŒyÒ¬ù‘0¯é¸«ód3{BÆ<)ßQ `žr´î¦ºÀ$-W“äjo‚óºO¿ôô•@da‚~ÌÈeÒkwR¤''•(!¤§ ±þ•HO§=7J¤þ™ƒôTà¼Mzr稰V˜ÐÞfƒÇÀ¤w5# IO5ÒÒ{b‹ÿcžœ:o Í&¸aLzÙôn#WÄIM´ôéSæº =ù±Á_ž–Ê܃ òæP¯V^mÔ{¿\^mÔ“;\Ô¨7ÙmÔ{|:d¢Þ]óåõšÏ˜ ÔÓ1ÝÔ&¬§ É’ìå×cÖÓò¯.¬§ÁcdÖSQ¤¤nzq¤¤Y“—ëiyñ®`=ùçžü*XOÅ¡€õô%Ä^y°^;}”•Yo ƒf=UÝÍ•`=u=Þë5ÍÏÑÚ°žÞDé`½¦¡œ{•š†·*µÓg)÷¦_{SýuÜkÚ£Üù»ÛЊ5îÍ¿ Tš>pOqOߥ0p¯í‡[Ükï”¶ñ.l8|Ðqoªep¯>觤ƒvÜÓ|„àž<¯°Ü“ƒ¸' |àžÐò{ ` ÜÓsÞ¸'O°ºðžìäx¯½ß3õïiयÃ{:ëžöìÀ'gp†(€Omej´ —ß ð©Äô€OƒíÁ=|²Óå àk§OKKiýzkL|Ó'mA¾Üq®ÜIÕÐwGþÑYÙK' ˜O‰é‰` 擌‡W´…={øZ÷=. QO‹[’ýóM>ˆ0ŸL'¾E=1>Sˆz E¸fæÛ»ëö`¾]¾jeQõÞ•/)Võv†ÎÀt((g‘õtX/32Ì'\ˆÄ·f>ª×Pƒù¹óœ°a£úNñœ}¨‘ÐW7“B@Ÿ\ç±€¾óòƒ¡ïš-Ðwêü¥ú´· ¾0iàïdïé}§üŠy;6H›߀>=y¾ \>UƒøÎvæ?ñ]‡—¡ß)ïeD»(ÿuùThߥpEؓ붕¿`>9…› ƒùäðM}Â|ò$_ŽK§]Y”ÿô!Ðf¾îÎ=¦KhüÈw½Ÿæ½ˆ{—Úž æ»4‡—˜p«!0ßõì^ØÁ|"0ôI˜ïº½–2ó]—ã`Ì|zÝæ­£0tæ»Ú½È{z¬Ì'Gx£e0ŸŠ ùÂ|z 5ó] =ZÔ=M+ôE O›]pSÙØ—6óé)ôM˜OwÒ­€¾îØÆseÀÛ÷mr‡>½ƒ¾ù}z/è+G~@ßÕ¶æ¢øï§9(oón ¯†ûÞÏÎÝ î»$ðq%¸O!fÃà>ÕIP&”ÃйO^ìÀ}ï°àî øifßð“Ul~A~ªqò+Çc†Ã„wÅ›º¿ˆYøÜw=l™šûÔô¸oÚ6êÜ'“Ðî\þÝïâ«°~oPÓäz÷¹jÌëà75 àWŽa¿©t€Ÿî9}otEÀo¾%À¯Hv‰ â>•8‡û´lò›±`45ÜW6Ÿkî+0`À¦²{·ìS¤&>`ŸZÿX°oê3`ŸªÆfR¨ ö©¶Ià{G1£+ا}ºº(|ïRþ숆¾Òã?óMëpa0ŸzÝ;óÉhT˜Om¼™òg1ó•Ó2·¡¯HÔæŠˆI«PPè+ç6o ‹rÍ|zuEÄ„w¼/‹¼§²-Ð'ÇXV–@Ÿ^e¾ è›ï èS·úÞ:ŸÜMÐÂÛº¿ž¦ }å¼’Öútõ¼ >UŒ…ÙN@Ÿºt¬ia>9=ð\“ása¾Ò½ÿâJ0ßÔ0_,ž˜oªßÎ|ïØîgÀ|S#Á|²ñY˜o of¾aÈW.û†ùäìˆn´¤Ú~âSÑ9!>}8Ï"ðM5Ó‰O_ñ½ßÔñ ¾Q½_ÑR 0€oº¥xÃÛ=Þ›Ê ï½ó {Ðe Æ=ÁJ2»-¼§{NH-xo*Nç=µ,?Á€wÙº-êÞd$¸7U¸§Fá;÷ÎЃ{å$Ú´§²¬´^åý ´7YíMô÷®F¼WÓiojIho¾Ã&8¢×´§h;ØÚ› ‡öT9Ï"ïÉ̶ÐÞ»Lð7x6+~aƒg½JÐýÂ{‡ØO²žºø,/#^xˆ÷ÖQF<ëΩ\ßî»9Eî˜ò.oõ'åéHhÊSì"ÄÖ)o³›f žðÈB_ ž$„>ðHËB@,ðhUžˆ§Ð.€Îˆçã x&ØI6âi‹uE<ùa®ˆ÷¤+ˆw=2„§U½å¸ ¼þ9C…–õޤ@œO•/ÇBHšÂ×M‰oû*ë©ësÏsúk¢0¨zò][<7Ç4”ªÞ5ùr"ŠÕÄ£ÅGÀâ Æ«ZFqª^.a<õFÉ¢žjT´®Wìk]/¿ì¡ë%µÂxÒþXçÃxU»‚Èm{Žqö×D9A†]×ÓÀ¡ëÉ×tÑõÞ‰W¦ö&Ñ.ï—òê“ maoO‘ÂÂÞîqŧä+,þ,ìILûÂÑÕÞ!O"àèPöäÝÓÙ‡shtAyõöþZ*{é+aÊ“s±EF”½ó\•½*ÿ ;l†:V9¯Ü”7 “Vö4{"åM¥ ioó iO·ñ7ÒÞ°ÙNœZS8œ8ÓM#µ=í§ö öáþÂb”sJSžcÒÂóÌïÉnœõv7‡òTŒÄ3=¬íÆy{<Ü8Ó¡Ê“;1Èò^z™òî»X]µ¾7\HÁ¼É-ùþ…2ý8w;*[à³ï\ºq–dÃóml6)¬ïiŸÅox¢î éÉ›û^=9µ¥ø†Ÿ²%¾Ã³²Ioòn¶Äw¥?€%¾áHm/}îŒzª@F›påL%)5¾é7h|)†Ú“S’‡Ä7ÉnH|û³¢žü!´ ½ás•žœïB£.¤7´së{êÕ`Ýpƒd† ON)òh‹è{z†À—BlºrÚa =9‡ªe}OÃç¢ïM"›õ½ôØ6ëÉ·‡Ísë{g®5'}¯|òäl€påŠd |–bSà›5>}»«+gó´‘ßuÛ¹}¬V/s-ð¥7uúrj °úr¾sœc¯Kè{G]õ½I>CßS\ƪïÉ‹lA=•–…1¨§caƒ Q!.à yûØåÔ÷®Í·àʙҷQOŸ©¯ ïÉ1svåÌQyo»?¹r>÷‘`¨'ÁU.Hojz«{[ÍQþôòOOλ™ñƒõb_ÎV’ñ唓 ب§¤uWÎwÅ^WN)JÛBzS]‚zOúÇ =µãµJ{ò€G Ô’»9Ûé¢Pþz˜­,ìmç'ÐÓñºöÉ ÐSǤªÂS] éMg±V‘­ëÉ [pãz»u½Q3€ÞüjÜ8›óa¦çÛ’f+4±Íîd&=µí¶ž>Ú:‘Þp÷H]O›N𮨊(XHOo¢²ìÈ™`Yï8ëôFÝXÕÛ æ< ”uá<)œ[„ {šn\9å¾³ªzïúᴈיO`fW͈×;òÌw˜oNLómÞKù¦,Ü Ÿ¦F'qÇ›S™æÓ4ÌÑ&éÍyøŠ™O‰’¬·í{¤Äbåö)÷ &¼9…¤çìÍ)ç›ÊR'°OÝàaÆû´Tõ»ûDAÏ‚}Êyç'[|¼w öõ¹ †Û"ÙÖž~˜A}JsYÈöŽdüº7ç~§¼ö)HÖqM*Œ%º€&ÅG(öZÊ•ö${.žr\Ü‹°§ÜVñúp±+Ýñ‚}Zã•IÚ›”K{Ze­ÚÞ‘K¸ïPú…ûŽ—u [¸orè3÷ÉQ÷Ídsß©Œ"Ú¤*Ò Fj¼ŒÜ;öŒËëÜ·Y6÷‰{ ÷I!<–Ƚ³¥ŸÜ'ý×…„î½¥¡§›û®bÇ3¸¯(ñ$ˆ¸wg¤Å=y¢@qaÃY3r):kc9Ù±O=¢.GIAìÛ7Ÿ+gìÛ´½Lဩg9tÏ3t:tŽR°OÃç¶Dîi&±g%êž°!êžvyãÂuÏ©±/E[°O¾±÷‚}E+<Ðu/7ÃSÝÓЂÛd0NÌ}¦Â}0ñ|†ûоfˆ u¯.Ð'ùÏޘߜUÚÓÐè‡ø&ea‰ÝÓûírŠ´÷ 'I¤½! }ë&¡/ }S,'ЧD9öá èÓØ¸ÄîmOúM†S§öxÀBÇîÝ6ÁÁ{ZÏó¢¦wáé1ÍòžŠç`½÷”'‘°»€¾É(Cß“†}:ŸžÖúªÜ¢„@_Ýrd¶¾7Ô±pìÔÆ O!~ïHµè«â‹x®¾YÎÛBÿ\Åø.gÓLÇÎ+ݦ>n ˜Bå€}Óܧà 6,𕚰ø,¾WÉ}»½H2„ï>?qßž&èS¨3øM‘éØ9<¿?9GØÕ3Àï83èÉ!|Gú~µÙ¿ÃàW5vOà×*Š^ø]×ÏÖ¾)Ì/¸O±êî D!êk†ÆÈÚ“²_pS“3õ ~ooûÄ7"œ¿änðÓ·~MäW”ëÒëä§ÍÂ%Šo8™ü&X$Š/·¡2ŠOÉc€ýž-u “Ÿ=Æ“üÕ;ˆOrÌÄ·§[l'?…CXFëä§ÈÐÊßÄ·;/jŠ|£@¿t¹1ù îž%†oì¦_§è€+Ó½)!'9n-äwk“Ü"Šïr’ã@?Åj8ÖôköÒIô³y’ßõd A|uá¾[êþÂ}“†f—Ζ©É/;8à7¥~c0ø¤ZrEà§\Šâ¿Ö2Äo€ŸUA¨i >ä7ßÝW²üz’e0‡Î» S$øicÛî›Må@­…û4Ÿ:/¸Oc „}ê6vøûj~ÕÆ¾LÚ`ìÓ΀ŻÀ>ÅÌâ,÷MýîÓÎ ~c JðsÇsüžVÓ‘tê_Óx£é©±ë¬é-ÙW:ß½]q[Ý6ÇñHðvL}Bpð]Zk3àM©+­éíÕnp™E©H¹ÇnŽÞÿz>–ªp4:ž><Ö•Þ´RCדK …@gdÉY]ïºìšnÀ›âo¼º%/9%K±ßIÓõËÉÈ2r´ ëIKE…pJ–'#Î:à©QWÀÓ:eõÜTÆq‡ô… #) |7ið–)vå ¾S>RtQøn„EŒ,¹œƒï¦dÎÈ2²38%KN$x TgEàˆŒLÉ2–’Þ}à==‰V\ 8Òr-À{O¼)€Å™Y2F ¾{žDf'fñäh¼S‡7ðu4ñ@_MÌ2¥ »ó`º¦»&K åN”éN9KŠ·3,”¼gÇS}KÇLLðÓéNQ÷¤êil 2Á;}ÓF·À»Rb¼ñ Æ»±Kg¼kÕÉÌw#¢Á|§aõ^"öF|ù®){ËÂw«ø0ðžìø%ø(—÷žRàòUxÚœô=xÃï߀7¼úðrAeÀÓÂz7òµHt—ñŽÞÔa¼V.ëŒ0Þde0ž†5îÀ©×\ @R†ZJ ã)Æ€] O=‹ÑÆ‘ ÉxOû$ì©Ô%p/Ó÷%ãMŒ'‡}ú§ÈZ& ¯ÙiǧZw,6ܹ ä)jã\|8…*§¯Ãê÷øHCÞô. O V™*€<õQÚÈSEïò¦6ÈË•¢!¯io†wcƒºÝyS/òF$Œ!O­G{òžt×òšÄÜ…ò„mÔ2”§Þå'!é?ç¢îe„ˆ)ozSPÞø)O½´¬á{9Jeø^-vˆ4F»¤¼Û»R¦¼ù9„ïÕ‘Ì仵„ï5 /<'IP¦L-2vÍÔ2Ýæé»².˜'Œ7°aCö cÞTbcÞ3à00Omå+ðåhaÌ›âÀåÐâW¨d£4VúžáMJßèm>msF_·Ò7êÂ|ãÛtß"‚¯–ÄFoÔ#øÆHa¥/窌à[;–úÆØæ>©ÌüÊÈw -aÃèíÖú¼"øöº’âž«üDµ Àªžçô_åž<¾ÿõÈHû«/?•\z=×÷¿÷?ÿd\ûÇ?Ç­_’×j߯½«Û?üú»?üÇÿëÙüÛ­Þ5È÷?ú_%•§hO>ºË[þÓùË?åÏã§ZŸ7Šú¶Ïôߎ"üý«?Ž‹ÿΪŸûÚï¿ü´»Wךõñ®•yÉo^3â¶ÿ^žñµBýÀ›øŸÿúò.ߥÚ=jâ·_4b½3ѧ¤¸ÿóËïÞeÕ#G¤*×Ké‚ÍÃï‚ÏW¾= ŸUZO±?Å…^š{BœžöX-üÿå|D—Žæ'Ü$rýÂx>¬(+íR®üÛý–üÙÕ fúU\Ð~÷ÝÿÆkìœendstream endobj 6 0 obj 185215 endobj 4 0 obj <> /Contents 5 0 R >> endobj 3 0 obj << /Type /Pages /Kids [ 4 0 R ] /Count 1 >> endobj 1 0 obj <> endobj 8 0 obj <> endobj 7 0 obj <> endobj 9 0 obj <>stream 2020-10-09T14:31:12-05:00 2020-10-09T14:31:12-05:00 GL2PS 1.3.9, (C) 1999-2015 C. Geuzaine gl2ps_renderer figureOctave endstream endobj 2 0 obj <>endobj xref 0 10 0000000000 65535 f 0000185765 00000 n 0000187278 00000 n 0000185706 00000 n 0000185573 00000 n 0000000266 00000 n 0000185551 00000 n 0000185858 00000 n 0000185829 00000 n 0000185922 00000 n trailer << /Size 10 /Root 1 0 R /Info 2 0 R /ID [<6D023DF2E6B4EDEB4910F12FBB7C8B56><6D023DF2E6B4EDEB4910F12FBB7C8B56>] >> startxref 187498 %%EOF blis-0.9.0/docs/graphs/sup/dgemm_rrr_zen2_nt1.png000066400000000000000000012141271422157504600217160ustar00rootroot00000000000000‰PNG  IHDR¬táÂgAMA± üa cHRMz&€„ú€èu0ê`:˜pœºQ<bKGDÿÿÿ ½§“ pHYsNNÆÊ/¥tIMEä !0Ÿœy=zTXtRaw profile type xmpH‰ÍVK’Ü0ÝsŠA ìã¸-i—ª,sü<»Û=Ý=“©Ê"vù'!xÀ™~ÿüE?pd^É.ÃKšUô¢Õ 'e­jºj—ÆÖÇårl_µøH5©¥I*ÍRÈ.ºRYl3,¬b[éµ(žP(‚El2¤§ÍÁPÑá&¸Ù¢Ù7U¨Þ­À<“ ,Á–6æ"•Ë^”ùªÂÙ°¶µ9^Íœü[wí&>ç5ÓÕŽlsâ&ÎÜÕ`ìn-¥ÕÄþ=pî@¿z8H˜»¬¸27É"¼¡ÂÙ*MÞ/œ0ßEáìÄÉ ²~¤È9é@+8“lÀ5,î!î¡ØxÀèê'ÞÀ £M%xŠ!Wîš-& `Ú£¢k]žÍQ÷SN:h0´ñðn.%Ø£S¥Ìá{õ8´Ãæ!• ø¸gÇcŽÒk÷µÓ;3¨gtïÔˆ Pd„ Ýv]08¤Ž dרýò=˜ŒÂçÉß“ÉÖg,3&1û˜#z þzõFš?:ƒtyÙê½ÆpWqÅðlһú:)Ýô6úô/à3زÑþÉù¥íCEóìéç/HµùßF(éX^ »8³caNvPÏR¹7€IDATxÚì½y˜Wyïÿ‘¼HcÉ#ÕX ÙB¶\cyA61ªñ’1ÁªƒÌæà›nAXlÝØÕbHº.fñ…Û “€só#é–oÄzAÓ 1„EÐÅbÀƒíLÙk0^¦,dIÆž’Æ–%Y–ë÷GÕ©®îéÙ—î™y?ÏÓOw×rꜪê·Oïyßwïû>‚ ‚ ‚ ‚ ‚ ‚ ‚ “`a£+ ‚ ‚ ‚ ‚ ‚ ‚ ÂìG„GAAAAAAA&‚ ‚ ‚ ‚ ‚ ‚ ‚ LAAAAAAA˜4"< ‚ ‚ ‚ ‚ ‚ ‚ ‚0iDxAAAAAAaÒˆð(‚ ‚ ‚ ‚ ‚ ‚ ¤áQAAAAAA„I#£ ‚ ‚ ‚ ‚ ‚ ‚ “F„GAAAAAAA&Íœ=ÏöíFWCžçá8Δ–7×Þ¶m<Ïkȱ'K³×OÚ,LÇqp]·j™Ø‚ú4sݤÍÂT3‘k?ž>Élµ³¡~Òfa¢LUŸ`>Ø‚f®›´[€ÆL•˜È±g’f®›´Y€ÉÙ‚Ú~Œ O³×OÚ,L%b ¦ñ¼øsœr¹ìσfÎjüd2é>à†á÷ööNºÜé¾ö€_.—rìÉÒìõ“6 㥷·××u=²#¦iú¾ï‹-Žf®›´Y˜jÆ{í3™Œošæ˜·Ÿ­v`6ÔOÚ,Œ—©ìÌ[ÐÌu“vÏoša¬`*íÀx=Ó4sݤÍó›ÉØ‚áú2N0<Í^?i³0•ˆ-˜¾ó2ç=…æ'›Íâº.ø¾®ëäóùFWK„YD*•"™Lâû>@`[AÆ‹mÛÒ„YÌTõ ÄBãiôXØAh&c d¬@¡1ÌIá±X,’Íf‡ýRë‹Å"®ëR,£u¶m“ÍfÉf³CÜ÷³Ù,žç‘ÏçÉf³”J¥7ÞíGBý)Æë>žõc);ŸÏGí¯·ÍXÊKÛ=Ï£X,R(Ð4 €\.‡®ëcj›º~žçE×m¸ú©mÔuϾca¤ë?ù|~ÄÐ+õ®Â¶íªö«cÖ«ûhûÆÏÉdÛÞ¬ŒtMF²ê|Õ³´ª¼ÚúeÝxÊÎL—€±ýG³¦i i†a ¯¦ˆÛ‚©¶#]Ûé²ñcNÄÌg;_/}‚ê}Gê4ÒLWŸ ¾\ NL†Fô âÇî¼´ï|¶íÀü±ÍdFkÛDûµËg«->ÁÈÈóÁìéŒ6V0U}u¬Úë:Uv`¸ö©cHŸ`æ‘çƒÙ3f“³0ö~ŒŠ-¨·NúCËžmÏ“é̆1ÃxÛÍò|0ç„ÇŽŽŽè„Ù¶M*•ªZ¿°¥R‰T*ÝØù|>ÚÞó<:::ªN´Zïy^Ô M$‘Q7ÇD·‰|>O:ŽþÕëú±”]*•p]wÈ÷zÛŒ¥Ì±´]}7 Çq°mMÓÈårcj›2íííѱ‰Ä¶«åžçaƸöì}çyíííѳT*‘H$Æ|mâØ¶ݯ‰D¢j}*•r¿·¯b*ÚÞ¬ŒtMF²êÜ g iÔöÃý&câûg ¦ËÀØ~#µOÓ´ªÎžëºUµ¶`*íÀH÷ÝtÙ˜¼-˜¯v¤O0RÙ#õi ¦«O H§ÓX–U×~LÅ}×([ }‚ééÄ×Ïu[ÐLv`´¶M´Og¶Ú錌<Ì®>ÁhcSÑ'P׳ž-˜ ;0Ò}'}‚Æ Ï³kÌ&g `lý3[ }‚±—=Ûž&Ó'˜ c†ªíqšæù Ññb§’B¡àkšæ÷÷÷GËT pß÷ýþþ~¨Z¯ëºošf´.#\•§üB¡}7 ÷,+ú^û¼Ûàg2™ªºÕk¤õã)»öûpËF+s,mïîîŽb¬ëºîëºîkšVuFj›Š7œËåªÖþüÇø€?000äø£í«òÀŒÖÆr¹<ê}Wy`` ºçÆrŒ8ñ{¦¶ŒL&ã'“É1í;RÛÇR¯fg¤k2’ð}T[ÐH; Êî÷0;Poÿ±Ø†ÑÊkÛÇò{ÍhšÙ]ׇäsªg &kT½F³Óe|â¶`>Ûß—>ÁXË®·¬‘¶`ºúj[Ã0Æ}=TÙ'ðý‘mô ¦§O Îí|°ÍdFkÛDûñ²f«->ÁðÈóÁÐuã-·Þ²é´£L´OÏí6œ-˜ ; Êi¶çéÈóA½õã){&Ç }r¶À÷‡ïŒfdÌp~Ú錽ìÙò|0™>Ál3TLjÓ,ÏsÊãQ¹ÏÇg®X–}.•JCÖ«°¶m£ë:žçaÛvÕ÷øÌ˜ø¾š¦EnþÃ1ÞíGB…¨-w¬ëÇZv½ïÃ-›lÛã3—úûûéïïDz¬!ªþhmËd2ÑguÍyä€h¶Äp!Rêí[2c$F»ïÔòt:ÍÌ*—Ë“ž9©ÊP3lÛ—öpmˬ”fg¤k2’€±Ù‚FÚù÷0;P»ÿX¾ÆxÛ>Úï±^û”Û¿iš …(Kí,œ‘lÁdíŒ|ßM—€ÉÛ‚ùh@úc-{¸e´ÓÑ'P34 …¸ÚUK£ú ¶`8¦»OóÇ4“®m“íÌv[ v`xäù þºñ”;ܲé²c+˜HŸ nGêÙ‚©²ª,y>häù`öÂälÁXú2f8<óÑHŸ`ìeåûhÌÄóÁX÷•1ñŸó±Ú“']û&b¸0:Š‘NªëºQ,Ý8ãýÁãÃ4Mòù|UhÕL&Ńžèù*Ã00M“t:Mÿ¸ö £Ýwº®S.—#÷|Ïó°,kÒ2Êõ_­Éþ1M¤íÍÊH×d4ã*¶ ¹Ë=©â­wwwGËt]§£££êr<¶`"¿…‘î»é²0õ¶`>Ø>Álc2÷åXúÅbMÓ(•J”J¥(ŸC6›W˜µFõ @lÁpHŸ`î0}‚Ùn Ä Ø‚ÙÇhc¡öž®g ¦Ê€<4ò|0;™Œ-©_ðªW½ 1Ãñ0lô fS5N2f8Ñó6sJxÔu}ˆÚ7š¦ k@ ÈÔäø¾Žã Éù!L#ݬ㹑=Ï‹¶Wq‡…BÏó(•Jd³ÙªÎÊhûŽ…Ñî;×uÑ4-š]å8‰DÃ0ªf9‡R©D±X¤¿¿¿*¡öxg[L¶íÍÊH×d$;b ÍDîÉø> õ»ˆÏÂÉLÅoa¤ûn:ìL-˜v¤OÐìL澜HŸ`ªÑ'±#!}‚ÙK#ú³Ùˆ±³©+íž®g ¦rðXžš y>˜LÆŒÔ/Ø·o c†c=óÅHŸ ¹™®q1Ãé8çs*Ôj2™¬J€Y;!™LF‰ˆÕz•LÓ4ͪïPIJ*L†a ëzÕuÊf³èº>.ƒ]›LVÓ46lØ-S‰§óùüwàzûŽçac´û.>[÷ì‚øý?†¦iUa¥êÍôª·ïpmWç}.ÌÒ隌d@lA£™Èï±öšŽ´ïp¶`²v@Õc¸ûn:ì€ú>Y[0í€Z/}‚æe2¿É‰ô LÓ$—ËE/Õ?ÉårãòlhDŸ@}ÍHŸ@ú³Fô f³->ÁȈ-˜}LÅXÁXìH­-˜*;Íû| }y>˜MLÆŒÔ/1C±Ò'˜}Lõ8Á\3„æ|>˜S†aÉdH¥R†ëºX–Uc¹P(H$0M3êTª‹ËåÈf³‘ñp]·jƒ0=tww“H$¢óîy޸ϻ뺴··Gû×sEN&“$“IÒétUùcÙw$F»ï,Ë¢T*ÑÞÞŽaÑ,˜áâÇDZ,+*×ó¼è0™LR,iooG×õè^V3,Ëvßx½Ç©jû\¹ßGº&#Ù@lAƒ™ÈïÑ0Œèšªû}¤û9n TصÉÚUáî»é°ª-“±óÕ€ô šÉü&'Ó'˜,è¨öŒf ¤O }‚ÙÆL÷ f»->Áቨ‚æe²ccµ#°Ò'˜yäù`ö2Q[0R¿ ÖkGÆ ÅHŸ ù™îq˜}c†Ð¼Ï |ß÷'uÅ›×u#Õøìåú¬N´®ë‹E\×â}Ç“Á*÷iaú‰Ÿ÷ñ̰m›D"ïû‘:?Öë6™}ë1Ü}?0ìúápÏóÐu}È ËÚz«¤Æj»‘ö®Œ¹D½k2;ßn®ž›fc*~êzgß©¶ñzÔû­O‡ˆ—;Q[0ßìHŸ Yi¦ÿõÉЈ>A¼Üz¶@úÒ'˜-4ªO0ÌÆçƒ¹l@lÁld"cÍÔ'€æ{>><ÌF&:nÍ1V0ûõʘKHŸ`öШq‚Ù2fÍù|0'…ÇáPêtooo¤,' 2™Ì¤âåN–¸±މÜÔÓQîtÕu¢Ä ÀTí;ml¶ó8Ÿ˜ov`ºÊžê2'ó[ž #WlÁÜFlÁäËžŽºNÇÿúd[0w;05eÏ•>ÁL¶±QÇê#¶`òe7Ûý+}a"Ì7[0úDÆ ç'óÍLWÙÍô|0]ûŠ-9ju4âîÒ*T‚r)m$ÃÅ×3‘ÚÓQîtÕµ™˜‰6·óجÌ7;0]eχ{XlÁÜFlÁäËž/÷¯Ø‚¹‹Ø©){>Ü¿bæ6b &_ö|¹ÅÌmæ›->ÁÄ;0·™ov`ºÊž÷°Ø‚Ñ™W‚ ‚ ‚ ‚ ‚ ‚ ‚ L ]AAAAAAAf?"< ‚ ‚ ‚ ‚ ‚ ‚ ‚0iDxAAAAAAaÒˆð(‚ ‚ ‚ ‚ ‚ ‚ ¤áQAAAAAA„I#£ ‚ ‚ ‚ ‚ ‚ ‚ “F„GAAAAAAA&ÍÉ®ÀLð™Ï|†žž–.]ÚèªL˜°dÉ’Y݆gŸ}–dzråÊFWeRìÞ½›sÎ9§ÑÕ˜‡¦»»»ÑÕ˜qR©K–,it5&Å\¸ÿÄž5Ï>û,|àhtUf”¹Ð'˜ ÷Ì {6ÚpàÀ>ýéO³~ýúFWeF¹ñÆ9qâD£«1£ÌÛ1^æÂït¼LäZŸtÒIÜ~ûí®úŒÒ××ÇßüÍßÈob öolÈóÁì}>˜óÑÌ…±ˆ‰0Þk=_Ç ÿàþ€óÎ;¯ÑÕ˜sáw=~§s¡ßñ»ßýŽ3Ï<“­[·N¸Œy!<ž8q‚|àtvv6º*¦««‹ÎÎÎY݆žžzzzزeK£«2)6oÞ̶mÛ]I·a>²dÉ’9qíf{Äž5ª ó¹Ð'˜ ÷Ì {6ÚÐÕÕÅ¡C‡]çĉ³þÚ—¹b;ÆË\øŽ—‰\ëùø|pèÐ!^ûÚ×Êob öolÈóÁì}>˜óÑÌ…±ˆ‰0Þk=ûÇŽ›õ¿‰¹ð»ž ¿Ó¹Ðï¸ýöÛùþ÷¿?©2$Ôê,¡³³“5kÖ4º“bÍš5³Úh(6nÜØè*ó˜¹pÿ‰=„É1W`ÏæB„ùÃ\±ãe>þNçëµƆü&æóñZ cg>Þsa,b"ÌÇk=V¬XÑè*Lš¹p­çÂït.ô;^ò’—°zõêI•1/<ç³ýf…àG7Û À¦M›]a3î?±g‚09æÊý7ìÙ\hƒ0˜+¶c¼ÌÇßé|½ÖÂØßÄüa>^kaìÌÇûc.ŒEL„ùx­'Âl‹©˜ ×z.üNçB¿c*„GñxAAAAAAaÒˆð(‚ ‚ ‚ ‚ ‚ ‚ ¤áQAAAAAA„I#£ ‚ ‚ ‚ ‚ ‚ ÂÇqœFWA˜ˆð(‚ ‚ ‚ ‚ ‚ ‚0ÇÉçó®Â„ñ<¯ÑUÆÈÉ®€bÇŽlß¾}Èò-[¶°~ýúè{WWÛ·ogpp7²eËÖ¬YÓèê ‚0ˆ×uÑu}ÌËa6#¶@›-; sé‚b A;0•ض=®í=ÏCÓ´FW€l6‹eY†Ñ誣Ð4;wîdÏž=¬_¿¾êÕÚÚm£ Ç–-[ضm{öìáæ›ontÕA˜"ÄTS,£™<©T Çqð<öööès"‘Àu] ÒqPËe0[[ Œn ÄÂÜGú‚ €ØAÄLŽãà™æˆÛ”J¥ªïétz\Ç(‹#¼Â§ÂóŸ§P(L&#Q²X,’J¥°, Û¶Éçótww£iZTV"‘ht“aÌÌ'[ ÂðŒd ÄÂü@ú‚ €ØAÄÄ©õ(ÎPÉÙl6Zæ8„ã‡q<àŸÀ¶mì˜pX*•°ÃñÉb±HGGG4¦Yϯ±T*Uy*Þ÷oð™â±ø‘o~3Ë>ðå/GÜJa»â¾—Åb‘ÓÞÿþ@­)ß!1S©TUù·<ø`åAWWW£›) eÏž=tuuqï½÷6º*Ã2’-˜lŸààÁƒQ(&A˜Ïlß¾®®.<ØèªÔeºŸî½÷^ºººØ³gO£›* Ežäù@d̰yÆ ‡C K®ëV‰kùØ6ñÔKJÌÇR9ýô¹ç ND´oíÛǃ+Wc‡¹¥R ×u)¹.˜&žçñÏ'N iÙl›Š UŠÕK9V@ÅCà{'NðéþW×ùÑI'EÇýêé§Ó58È??õ6ày·}ñ‹‘ðøÞÝ»12Òé4žçѺe &pÔ¸?¼îWíÝËÇþññºüè¸õ’KøÍÁƒ‘SÆxÃÆŽ„ëB½¡ÖO~-x9T §¶ õ¢Ðæ]¸³NW´0]»‡._P‚;îzo\1¼«C¸á熊’ ß³5ËßñË_NIŸ i„ÇÁÁAÖ¬Y¨ê¶Í¦M›¸å–[¦äǾhÑ"Ö¯_ÏÅ_Üèf BCY³f ,Y²¤ÑU©ËtÚ€%K–ÐÙÙÙ°¤Ò¥R)ú¶m;u]'“ÉD¡ Êå2ÝÝÝ$“It]§»»;  ¼ 5M£\.£i¦iF¥¦iär¹ªãªmlÛŽÄGÏóê†>¨Eâ¦Ïâ×U Ú#ÑÙÙÉúõëY´hQ£«^—™èÔ>ŒÂ|cÙ²etvv²zõêFWeX¦Ó,^¼˜ÎÎNy>æ=_|1,^¼¸ÑU©Ët?¬^½šÎÎN–-[Öè¦ BC‘çy>3lì˜áXP£ëºUÎ^øRÂ_>Ÿ¼?uß}‘‡£çy²3)Õ:8Øß;AÕuÊ$áÛ««EÍ<ðh+¼óp ʦ€v‚ÏZØÞxU³ûç×ûþÿ^ñ þÑñâ$ûÇM“ãñᇮú¾eËzzzؾ}û¤ÿüO=õT^þò—³~ýúF7SÊš5kX³f [·nmtUê2v`éÒ¥ }˜Èf³¸®‹išèºN2™Œ<U.FC]½S›Ü0Œè¿¿¿ŸR©D:Ʋ, …B´ê¤X–E>ŸÇqº»»«Ö%ŽüdˆÇw“Ïç1 £Ê+4“ɉ±=Ó4)•JQXZŠv¶£BA†A*•BÓ´¨º®“Ïç«Bó:Ž]çáòzªßA³z7ÌDŸ@„ùNkk+M=£w$[ ò¶L%< Â|G=#Ï×ç%< Â|Gžäù@d̰±c†cA ŒŽãT98áëó‡GãDçüÙŸÁºuürÏÈd°³Y<Ïcùë^ÇAà‘ßýŽ5"øðÒ¥<÷¾÷Áš5Q¾ÅSþæo¸ý¼ó8õÒK1—,MãÛÇŽ±sÑ"þíàA¾÷ÔSpûí”J%Þsûí|ò{ßãþC‡Øþýïsh×.mm…¿û;Ži'­[?ý)yÏã®U«X¸?ÇÖ®×e×yç1pî¹ žt”JÇF—^}5o;tˆG[[Yzü8Ýx#k?ùIvw߸è"Nùó?ç8`ë:/äék¯¥õ©§Øñ{¿‡¿|9\}5Pá’áùT£œ÷ï‚ëÂ//¬9ï^àݨÁyV£´\.©¾6ð‹óÁ_²³áû¯?ÏìÄ@#\VŽœ ¶Ë- ._´=ðXTËl`Éwà+¯…ÛÃåvø¢ß±‚ú•Âug탲Á)C‹mé‰äCïÓÓþáškxÃ$'!4ðXÎÎÎ!®Ð}}}CDaî2Wì€ëº¸®Kwww”Q‰JXT^‹ÓišÑÌ£b±‰œñÙH†aaÂù|0—JÅ_Ïf³†A.—‹„¾áN<oÞ4MR©¹\.Õ±mÛF×õhæ”jKüXj[%œ*áq¼õ™J<Ï#‘H`Y–e‘N§Ñ4-òrUuSªjc2™Ä0Œ(?§u]Hµ}¹\ŽÂé–ËeR©‰D‚d2•¥ÄìÚ³…¹b A˜µ¶@ì€ Ì?¤O ˆ-aîÚ›Š¸燻vñ­E‹À4#á1 ¿ ÜÕÒ™&Žã°ý±Ç`Ý:þóÈÐ4¾ûðÃðøÉOr¸áB~áû8—]Foo/»Î;Ö§žb0t6Ø÷îwó…µk9vÞyœzø0G®º <âNúáÙzÈ–/礅 ÉçóhšÆ‰ë®ƒ§žâ==ì¿þzÎ8ï<þ㪫xõüvåJÜE‹8éò˱[[Yx艃ùù׾ƺÁA\ËB;é$ž¿í6^µow^y%¯8~[×!Ìïyó‰ÜvÊ),ܵ‹]ç‡A f€üÒ¥˜€mY<å8\xê©$=[_ýjV ’ËPÁV•×_oXÆ¿^X Qªâɽã—p×Yðúp»îp¿ï]‹ž Ê‹Da!±eh-aîÉðú,Z ­ƒ‡¨äå4€s> »ÿ.ø®ÄEàã°òàeK‚cè@?`üí î‘lXÆ÷Àkß³‹KÞº†î—œ ªÎ°ò'ðôðŠãÇÉžr I ëÇϱås§¡u‡ç.lïwÀ#¯‘üßÿˆc==ðêWOø>nŠP«;vì`óæÍC–ǓƪµÉ`{zzšÚZ„±1Wí@*•¢½½=í’É$™L¦JlT‚Ðt c¦iR.—Éd2äóyJ¥¹\.è àX,Fƒét:ªk:ŽÄ<Û¶I$QNÊxhµj·Š¿®Ö)A‚ð Ùl¶êÝq‰º®“N§éèè ­­ööv<Ï‹r\ª¼•ýýý$“Iúûûéïï'“É000y’jš…—Ǹ†„™‡ž. m<6½ íAüü ÐÑÑAGG , ½½|>mÛtttày^Ô&rWmDõ5 # ›ÏçI$d2úûû£<Ÿ…Bß÷ˆÚnš&™L&¯ …B4ËMÓ4Òétt.ÛÛÛI$M›¿e®ÚAÆÇh¶@ì€ Ì}¤O ˆ-aþÙ›ú!?÷.ZÄÏúú¢œ‹P åé»Î;¯=†að‹Ç`ðòËð4R&Ãñ5kXôÜsì^·Žƒ àç>öÿca i@[*űë¯g¹ï³¡·€ÕÇŽQN\z) wíâ”;ƒDƒ'Z[¹ù£ &¿-o~3=§†ÓM~ÃøËÅ‹ùðÊ•˜"׉ÖV<ÈÒ·¾•Ï]z)¦ëò±õïþÕ¯(Xoni¡ÔÖž€½Àµ¿þ5x‰ûî‹–ç—AŃ“l–o/Y«Ÿ5§~ã|5¼OÇá2â¢Gàí—"_Jø=®O?º¯ ®‹.sˆÿ+ØN‰…:зò'G¥#l(@Û}A5á° ìþèNPwuÝ*ðöíÖö¹6ü ü·ïçvíŠÚüø÷ñâ‹kyãg‹FÅ‹SÓ4gà+®@ ·?ôÃ^(õÒŠEŒl7æÌ›wñø/ò¯þç|ç;ß™Üì7?þ¸þùçûŸþô§£ewÝu—þùçûßýîw£eþð‡ý·¾õ­þ¡C‡|ß÷ýb±èwttD߇ãÓŸþ´×]w5º™‚Ð4Üpà ®Â¦Û4ªÝš¦ù–eùš¦ù™LÆ÷}ßðf¼.ŠB¡à›¦éû¾ï÷÷÷Gõêïï÷»»»‡loYV´½úÜÝÝí†á¾a~2™ô5Mó?—ËEË3™Œßßßᆭi¾®ë>àëºî[–åëºî뺷P(ø~ÿ¤ÚX.—}Ó4ýL&ãg2_Ó4ß0 ¿P(ø€ø™LÆ·,Ë/—˾a¾¦i~.—óMÓôß²¬è\©e@Õgµ_¿oš¦oY–ßßßïçr¹è|d2``À/—ËÑñ|Ã0ür¹n„ïû‹?ûYŸrÙ¿ü=ïñ}ß÷·=û¬ïûg>÷œïûŸ{äÿõ÷ßïS.ûKöï÷ ÷»úùç£ÏWþøÇÑçÿþï>½½þê·¼Å/û¾¯û¾Ÿ ×­úüçýŒïûV¹ìŸtÿý¾.ß´u«O&Ô¥¿ß_{℟ó}ÿÿÄŽ‡ïû­/¼àëaÝ ßçO|¿×÷ýK_xÁ_yçÑx¤jco¸­S£a¦ïûj”0“Éø«>ÿy¿¿¿ß7bÛøñm|?gßïí J¶|ßüë~÷; ,·Ö5ãûþšç}Ñg‚ïz¸Üô}ÿÒ{|-(ßìï÷ •Lú>fPF9,kÀ÷ýËßãûé|°¾|ß÷—.}ÞÇïóÂíUÝÁ÷¯zWÐîL¸¼¿¿ß_DÁÿƒ?ø•ïû¾¿ö•¯ôs¹œ_.Ûÿð‡‡|MÓ¢sõªW}ÔßÓ›vFã»Ád°ý¦M[}]×ýþË¿øþõ׿ßßÿâ曦éçr9?“ÉøW^ùc|ÿÖ[oõ?þñOê>n áÑ÷}ÿk_ûšßÑÑáwttø¯{Ýë†ß÷ýC‡ùo}ë[ý×½îuþ[ßúV¿££ÃÿÚ×¾6jÙÒ‰„jšéÏ4ÎtÚ™l·™º»»}5¿£··wÒbZ#Qu¯Müd2雦é÷ööúÉd²J´ÓuÝO&“~2™ô3™Œ_(FÛ¦’L&ã'“Iß0 ?—ËEBi.—‹þ€Õúd2‰…š¦ùÝÝÝUÂa¹\ö{{{ýr¹}éœ5#½½½þYgå¿á ohtUê"}A˜9šù71š-˜ }A˜-4ëob:ûÍ*²B£hæß„<ÂÌ1ûÍÖnÓ„©~ß÷MÓôËå²ß^.ç·<ñ„æ»Þåû~(" Db_Ư×>ôÐ-çûþÕßùN•@hÅŽmÅÊÈ;Žïû¾ÿÅŸýÌ¿tÇ?–•Ëå|]×ýk¿üeõ·¾å›±²–>ïûgÜwÀ_ôÛßú¹°,ß÷}ËòýPgô3a=Æê˜]3MÓÿûßïû~µèXo|ã·>øþ—¾ˆwjœ6>Ž—ÉdüBøù3Ÿ9ì£Âk!lk°MPÿB¡à_òñGçË4ƒåµtwû¾aŸ•(éû¸xñÞ!ÛŸ{îÓ¾iúþu×] ¦?üá¡P0üßßßï¿óïô¯½öZÿïÿþ>øþ† Oû™LÆ¿øâ‹ýîînõêëýå øëÖ}Ú7 ÷,ËÏd2þûßÿ-|ÿþèSþºuë"'ˆsÎù„¾æ™ïòóù¼oY–ÿ¹Ï}Î_¾ü_üdrjúM#<ú~`îºë.ÿ®»îòüña·SÛŒe¶‚ïK'Bji¦?ÓZ¦ËÌd»•øøÉdrFŽÙŒ DžŽáÊår$ö÷÷GÂèhuVuUBã\eÇŽM;°àûÒ'„™¢Ùc±ÍÜ'„ÙB3ÿ&¦«OÐÌ"‹ 4‚fÿMÈó Ì ó±OÐlí6ý@œËø¾¿üÜs}Ã0ü¼ãøaî¡à=“ñ|ßoýêWý–Ÿý,þtß÷5ß÷ðï;x0•(éû¡Ç¢ïGûbÇîõ}¿;,CÑßßïæóŸ÷ËaårÙÿàÿÅÿÊÏŸñ¯Û±ÃÏ„Û[~àøÒ}Âýý÷û~ETâO^rÉ~Ó¦ß =¦ïçrCϦi‘c=âã~7ÞøµÐ«ï‰hŒð?÷¹{|Ó Ú¥ëz´ý•WþØ_¸ð7þ}auTûûÑPEqSmR¦ïW‹¨Éd°}.—ó·Ýq‡ïû~Î÷ãñG¿õþ÷ûþÉ'ÿ_ÿ¤“~èþ•W^é øgžù.|ÿ_ùÏþŠ+üÖÖV¿¥¥ÅÃ?í´_ùPöøÃ`ŸE‹ùm-õ zý?»ð ~oo¯?00àzÛÛüåÇmiùh$º&“Iÿæ›øàû/ù_FÝÎ]¾ÜÿâŸðÁ÷ÿõ†/ûwNÒYáäÉjZâùZFb,Û‚0;™ vÀ¶mº»»±m]×'_à,EÓ4’É$º®7ä<˜¦I.—£T*EÇïîîµÎ*צa3ÒfÓO?½ÑU‘¹` A˜çy–eEË\×2ÞhÛ6Åb˲X·nO<чm{d2òùyÛ®´ Àu]~ùË;xñÅw2¸û$X»Íó@ÓxûÛ¿\åÕtÃã§R.°š/}é.þæoþKàMoz¥oý'Åb‘d2I¦§‡O}êS´´¼ ]/áy!‘HpS?ŸúÙÏxá…ÿ:øÌ¢Edï¿Û¶¹âŠ+¸ãè{`‹ÎZĽ÷ÞËÇ>ö1~ó›\}õïX·®…GíC×u.¹än¼è,þ3çð£‡ÿŠ¿-èzænÙ¹“ö“;p^€ŽŽv~úÓ`¬óÜþ~œv?Yþ ÿµ÷›d2r™ _8óLîýÂO-{ö°üðÀ¤îû…“Ú[A‚?6ÏópÏóH&“ 2™L£«ÖP,Ë"—Ë5ôøår¹Ñ§AAAAA˜‡Ã×X°m›½‹ñ“ßþ–fÉË^Æå·ß΃¿ý--ûöEÛµ¼êU¸šºÎ;V® sï^ ?ñg"ŸÕû†p]:-ªZNl;µÌq ›­¬Ó &í_uÕâhY2|¬Ú -¿já†%K†´-Ôíjpؽ{÷Ð¥¡P™N§±C•0ŸÏS*•Ð4 ×uioo'Nãy®ë’N§Ñu=*3“«¯þ.'N<9‡´´´ðØcÐÑÑÁêÕ«ùæ7¿I:fõêcœº {îùÅb‘öövR©÷ߟøÄ=˜¦‰mÛ|ö³Ÿåرc¼ûÝ¥¥¥…ß_¹’ãßýnÔ†Ë[ÖSÊç¹í¶ÛxÿûßÏçNÿ}}ŸÅÍf¹vÉÒìy`E¸u/o?ÿ|ÞrìùÈGønXÎ~_|1çž{.vâú+¸õÖWsËÿ¼‚ß¿å’É$wÜq?Û÷f¶Ÿò§<½x1Ïå+<õµ¯ñ/=Ƨ‘îœËç7žLØûÓŸ’?xöïçß&¸ì¹÷ã¶ù<© øÑOWðO¿ù _½zR÷½‚ S€mÛ$ J¥¦iN¾À9‚œ AAAAa>㌰îm·ßŽë~‘Nø¾ïèQ~ÕÒÂK6n䉫®Ëâ÷yDÁ#W]žÇå<ÀËÏ<“S¿8õÔh½òäË£VU!‡·„Þ‘õPn×aöŒÔ :˜fP–j§â…ÎfQ(€zžG6T9•H÷hL&“t›&žç¡iårÇq°m›T*…ã8d2R©étš|ÞæÎ;¯áÞ{O`š&–e±aÃ~õ«»€ÀYáûßÿ>×^{-Žã°æ%oçy9÷ÝwýèG9õÔSùÞ÷¾ÇßüÍZî¼óN~÷È#|üãçCú§œr ×\s [·nåŸþø9çĉ¨¾~ß¾óWÅÇ>ö1öï?ÍO~%8wÛîäo^ùJŽß}7ç½pÿóÚŸ°òðaþüÊ+y衇¸ð•=Ç3h|íŸÿ\—³Ï>›EƒP¹ëñ“yÙ$“Ièè€åËùã?}–#oæÞÖV2¦É—ŽåûÏþ)©¬Nþˈ¨‹àºèÿ˜³OÛÏó§¶ Å"G_õ*þðÅÿbÙ‚ƒ´,yYä1:QDxlR”ç” ³Çqp]7rçAAAA˜«xõÝ—(•J®š 4ßÜ»—½¡7¢òÞøã_ÿš"pÏé§³ù+_ ´€Ð[o`ùr޶´°jÕ*\¹4³ŽE£âØö›ßðÕÖV `õþý¼æÒKjF%6ÆG*u]‡b1HQ.³mX° ~ý‡ù©S/CÑpr†ò`,•J‘p]—ÁÁ“8th!žçÑÞÞN©TÂu]V­Ú˶mw†!MSd³Y:::ÐÂñWå Y(¢sZ.—Iz¹\Û¶Ùzˆ~ï{OE:ËÀÀ÷Ý÷Z[O`Y9òù<]týýý,ð¸ãŽ=<ýôÓ;vŒ³Ï>›»îú--wñèÿƒ¿Y»–?ýÓ?å«_ý*.]Ã_žÿ¯¼ì…{üЇX>0Àé§ŸN 6¯?û:n¼ø<û, ~óôÓ.®œÿãkØÿþ§<û,þÑßòÿ}ç2Wß žÇÕO>I¡Pà¯ÿú‘¼þ4ú<òyι÷^>H‘}‹Ï๋.Â(•Àq°^z«X´èA~ráè®ËßÿÇà]þúà\XÂòåËYýíoC¡+Vðûk¿ÏoÛÞ(Z¹Ìæ÷¬àSÿëÒ·¼‘3Î8cR÷½M†ëº¸®‹mÛÑp¸?rA˜(O<ñ„ÜWSŒã8 ‚Ù&‚ ‚ ‚ ‚ ³ Î0NqŠPÞJžçÑÖÖy'¹®K6›%•J‘J¥ÝAh*òå©„¿8ùd~¸k?ùÉOÈçólذ–£G\x¶í[¿€ ¿ñ ®xÉK0¨ä_|×Ë_y~ýŠ+€ äi½\’ñ‘J]×£2ŒhÔËå8õÅDÀ|~èò‡zˆßþöÁ!Ëûûhi9Šçy‘PèymG³xñ ð@, äóyÚů~‡år™d2Ioo/º¦q®ïcYV”ïÑqÊå2š¦mGÛÞrõR n¾ùæ( ÔK_úR>tóm¬[wÚ‚ƒ,ûßÿ› i?äšûÙÏâ¹.ŸùÌgøõ¯_ÆËÛð׿…w\x!çwøÀøð˾ÂCƒëX÷›v®;çp]ü xýò~N,üÞs¸ƒ+øàòå|â%¿Àg§-<Ä>àéod×yçñš /Ä8~7ί—à|þAH&±,‹¾¾3±mð}È~âtœb JÿãòòÙM÷p­WƽæÏ!™$ýë)•àØ±ÕüëÏÇuáê?þcŒ?»”BÊO®YÃÀ† `Y”½“ï=ñ&ž{®3pG-H}ûzìVð_ÿµlÒ÷½M†mÛ® •7•ŠY,L=Ãu¦ÆÊtÍèšjÐu]¾ÿýïOK]çÙl6šaãyž„AAA¡)°m»n4µb±H:&›ÍFë=Ï#ŸÏÓÑÑ­·m;ÊŸ¶`Á,Xå<ËçóèºN©T¢½½ŽŽ\× þA¢¸ BŒãÇsdqÑq²Ùl4Þë».dí7R*•xñµ¯å¢çž‹öÝ 7üú×üÉòåhTDÄ—/®äY|åÚµ@µÀXσD‚(¢Âuë ‰šV¿œá~â/k}Š'Ÿ<µ5•Jáº.|á Ï‘Ïç£c{žÇ®ã¯ ¯×§X,¢ë:š¦aÛ6GŽ\Åå—¿L&ƒa$‰À®Ø6?øÔ§¸÷Ÿÿ]×±,«J̤T‚0kþkçà`ÀÑ£A­÷ßÏ©;w‚jÿrÞòÐC\ñ’—6mÙ2þ¤åK\ùòŸ¡e³P,²ö¦›XxìÎÎNî¾çl°m,ËâŽw¼ƒâÞ7òó§_É]gàœ¸‡?ýÈg¹ã`(º&¥—¼J%ì/>AGë#\tá7è{û…k}” ßüf¸è"ì—þøjœd.8¹·Ý=Æ‚`ßÛŠÝòf0MoÚ«V‘¹òNÜg^Béî5b|àFûÁèš9f&º®î}i§Ÿ;N¹†RlìzÕª½=º>¸–ár× î‘'žXÌdá±äëýŠ©x;‹Å¨s ã¢ä\`,ádã¢[m‡Éó¼)åÒétôÙq:::Ƽ¯ºnãÁqœ!m(‹UmT¢óh‹Å…Ru/©×gœu…ñ¡Î!÷`±X$•JEŽ‚ ‚ ‚ ‚ 3?TÂa"‘ˆÆªlÛ¦½½ ÍfÑ4 Çq"ïÆöövŠaèÅÞÞ^èííÊèïï§¿¿×uÉçóX–Eoo/™L†îînº»») †!N‚PÃàºu¸À‘3ÏŒÆ,Y /¼šÆµ×^˪Ïž£gÅe CÉ&ü™Þ€º®G¢IuHUÅhÂc¨Ý9ZÛ¸‹U«öÖ]gš=C±üðOØ@*•Šœ¨ž|r ¶‘Éd(‹QÈÕ O„—Ÿ{n”·Ñ0Œª¼ŽŠîîî(µÕ‡?üa®?v,8?¡}ŠœA4­¢ŠîÞ‰Mî¶½³9ýtÖ ô¢1°|9§ìÙC±Xä¶Wü5ç¬?‹³_øï¤ÚÚÀuyٵײðhÚÔ;ð<ù…‹V*qɯ=°Ô?d°å,J§ÿ÷àüþh€Ü[ïÁ]¾V¯†džyíòuœsáJ®Le«®«W£-z.º6hÖѤðú¯7ªsÆaï[Ë—åÿüjºï8Ã€Ž´·hú†p]Ì¿»¼Rþòå¸èÜw_žŸxY´ÍK_zû÷¯¦££r_@%„3¡{]qò¤öÆE<Œj&“‰–)%_¹Ç¬¥R MÓª~põ~|ù|žd2YwÝHäóù¨.“A…mÛ£zåóù(<¥ßJ¥Räú¬:B¦i¢ëz4#BÍŠH¥R$C÷ã‰ÔQ}O¥Rär9Ç¡T*¡ëz3:¼.ª¥R)2ʶmGÆP­«'»®K©TŠÎ±º¾êÝ4M\×Ú¬f“†QuþjÏ¥š¢öW¡-,Ë"“É igGGº®Gçùe/{Ù¤¯ù|Æqœªk§fú ‚ ‚ ‚ ‚ Ìj¢z|œÌqœh¼(—ËEckjüÏ4M Ã@Ó4\×¥½½Û¶ÉårCÆ×Ô¸—ïRã…BŽŽ’É$š¦ ÙO×uÇ‘44‚òÌ3ÏîZ¿>Sý¶·UÆÂ #Pбt“4 &Hpõ“Oò×Ïš¸‡‚Í–/g£ïóþ~«äpæS»XxbØ6‹3ö=‹i4ïTJzÜ ò*^z/É ž$û³7a®Z½½_úåMî}¸ƒªdÊ9È'`pA^Ïÿú_ðä“`Y&išÍù“Ip<Òª[ààÕôöç9}Ãì›áy•¸¦ÏËy1º,ó¦gåryØ ØjLSæEÀr5ËBz†ÁÚµkqo¿=Xûmý¦­ ƒ GcKK W<ó »¨Ÿ³1ÇØˆipUxÞðaTã\qÅ/¸óÎ+òlòù<½½½üìgGpÝ–*{ã8­ ò™W…bñp´­®ë<õÔó<ðüþáÃüÞºu¼òÆpwõÓºø-¼GÿXPH*ÅÚC—±©°Ó„²– ”6à RÝTº³b<ë¾ö5xÍk‚†Fä)ÊÊ•Á1N¹¬«¡XäÛ«Wsúoëo½•#‹óòЋsÎaÓE;Yõ…ïáþøqô?<tòû¿½ã ä}-ÉWÔ!ŸGKŸ½ø8{ãä!—3pîm%õùv¬ÿˆˆ¥R(ÐÞüŸÐ·M šQ*£mWªkÐÞ6õè›I.~þ;Î"\—H\T”ËAY¥Rp=Cí–l¶"Jf2Á±vïþq”OÓqà¼óžáïÜËßþíyäóÁé õc~x)o}ë/€Ë'öc@B­Î*Ô¶âaTU'@ý)«ØÅñYHJ˜.<©š]0ZøÑD"mÛtttDâÙpžzjæ“ÏÚÚÚ¢Øîj¿ŽŽŽh½ŠQ­BÅÆë/«D?%”ÆÅ5µm"‘ˆÄÚ¶a‘×`6›%ŸÏS.—ñær92™LUüi#ßó¼h}Ü;RµAu$•[z6›¼D-˪ g‘J¥X°`A$RB0;IJ,Î:ë¬ÿ"f/ê7¨~†aËå$¿£ ‚ ‚ ‚ “F=Åq‡t:EÉ¢±5—Ëå†LÈ·,‹r¹<¬°¨Æ¿†C…d­e¤1ÚP«S™&Iš— gãÂߨîÁ ç3W\ÁÏk¢ÑÙÂd™À«qåoK{[&õ…Çø¯Ö¶+Þjc¥ögí8•(¥ñßìO~r!÷ß¿ MÓ"§œ+v•h*²a~Ý{ùÀOÞÙ$MÓxàËÉåà²3Πõ©§¢P̓G["oGt¶£GƒóéRÃu‘²fYDªœëFÛ9š4¢£óÜ~ Èý]Á6ŽÃ“W_Í3K–`¬Þþ“ÏsÏïý?¾â X°€Ü‡žá¹ÖsHÑM⿇¹M“Äg߈÷êkð:Nü| Ö"ÎUB€N=ñPÉãéx ‚ ‚ ‚ ‚ Œ†J¤Æì,Ë"“ÉÔÕÄþéò*.œêH¨1³R©„išQ¤.Û¶I§Óô÷÷G“ú'B>ŸSº©áP©ŸÔ£«/Êqb¤z:ŽC©TŠBનqõ¼SM6›•qÄi ö·ùÌùç3°t)è:-ûöqäÌ3Yµw/ûW¯®òb¼â¿Àøà1=—£òn«%—«ˆNŠÝ»Ö!Û‹^[[äÌð½ï}óÎ[βeÏFSÉd’·½í –,9ÀŠ'aYV¡;õ¶³ÿ;íÜ «VqíÏÎç>÷(ï}ï:ܾ#èo®T6«‚Æ*—KMƒ}ûHl¿_û` ¨%Ðß_ÝÐ\Ž(v©çmSZy9m è:ÅÏœ÷t¸­®G'ãŒõûПž[…놂a`WcxжƒóR.W¡B(>ftî5-8wÊóT‰‡ñjvtT¾kZP×­”«LPwwPF:]YF¬ jÿ8ê´Õ Ïžнá_ÇïÿþJ¾ÿý¥|ìc-«S¼©ˆ¶ºû÷á±™Q„¾ÔŸ¬òÊ"PQª.|\ Ò4b±X%jš RÊ+þ®¾C ÌÅÿDÔ~–eEù•À•L&‡º®G³®”ð•Ëå"®»»›|>uŽâ‰Åb‘L&3âŸrm¾ÉZo½ÑPâlܨ+QQ%î‡mUç¢ÞL#]×£8ÔªÍÊQ…ס˜ªsQ¿UE&“©ú®:jê:ǽ>Uýê•Y/7¤0u¨k¤f ‚ ‚ ‚ ‚ L†xD­R©y6ŽÅ3n:ÇTÙãÿP š¦Ec•*ÅP:ŽÚ¨ëz4Îišf4VOó62žÏ¢Sü¶ˆN†Q-Hýö·‡"<ºntô3Ï<“îîîÈ çúë¯çÎ;Ÿå®»îŠô‰ŽŽ{,Çë_¿‚5kŽGÅtww“JŸ_éûA¹Å"' òÞ÷® °ÿ÷8ï®:|fy¡{^©„qó«(ï¿Äöƒ¤R•ª®[iú­(õp, Nµi¢gm¼k_M©zþ½êÍÀl ÄÁã좪,M œ'M3ÿ'‡ªýyÔήR"¬ú£Ö4mÄÙ[ÊÓ±öZį³ÚN Ác!.H Súã{ ‚ ‚ ‚ ‚ Œ•ZIMr7 #ŽâËš‰Ž-)(LµÏ0 ŠÅ"º®“J¥0M3ëTä4åt¡ò¿)R¡¢¡¢¯%‰(¢›rÖPÛ©Ô8JÈëèèˆ"Xe2J¥R´¿º&JøT"¥a‘8¨Æâi¥t]ÄG•g3ž†I9w¨sa½½½Ñ¸¡ G«ÄGÓ4£TQJ¼T޵¢¨rHQBµò¢ˆw…B!—TiµT½â¨êº¨ñÇÏ|æ3¾íf5Jxt]Ó4ƒ¨t¦ ®Ë‚¶6üåËQn'­­­´µ´pæ‘#£¾ÀIO$¢´ƒfÁ‚ƒÀ¢i1_ÊbËÊ¡ëðïÿþw¼æ{_#»~=Éd’ß=ðgìz/ËùÃ{¾É$wœz*?þÒj>²ålþÇÿøë ž±1ÿ?øƒ‡øÃûpO©J&él½oàÙ@áJ$pÌ `â,êÄë\Œæ>š†ó¦PúìÞ`§rÚÚ‚†«8 µ'@¿ë:Z( ê¦A’4Ž‘¡XTáh?v–‡>Σ‚‘Ù»nôް •g±TšO1™ ÊÎfƒÍã&J™låÉXKwwµø¨ëA“â9ã wUùµ’Ãpõ†®ßúÖß±}ûµ¿‰ÆÈÂi?µþþþ(%P3Ql,(ñT uÊ)ò¬H€SÑÒr¹¹\Žr¹L&“¡¿¿ÏóÈf³@ êµµµáº.år9J§ÔÝÝ ˆJT³m;;K¥R$zžG?år˲"QS‰Ÿ*uTGG‰DÛ¶Éf³´··G)J¥ét:ëÊårÔ&%ö÷÷ãû>¾ïGã‚Éd’L&Iªhù|>òŠTuˆ¼B‹Åb$J*'“8ù|žŽŽŽÈñEóþþ~4M£££#Š@—J¥( QJ­¶¶6ÒétÑ­X,’L&ÉårüÉŸüI£o¹Y‹’ØÔo[}Vøá}×¥ZZZxÙ’%Àh¿²š,]c¢vxøñÇÁ’%×ò«_UUð_ýÕ¯I§¡³ó}\ýõ LÓdÍ•@ëþ7·´€¦ñ²Ÿÿœ¿ýógp,aé¾}G¢çA>OfÓ.Î8ýlÿçßG œ½!ðÞt¶á¡… m¼³Öë\B‰$ÞÝGŠš{luxþÂF(Õo¤É¦©"®m+ ‘zç×ÐÒ„ru]8räLn¿ý<OÇ\ù`T¼a)'•¼FcŲ*Âbh¢ªÎGE…o­Såºar‡ÖNÖN:¨5ÝýL†eML#+âñ8Ä=jæI±Xª=ùTîÀÚP›ãe8áR•« [¼î6\šWÛ®Ãî½÷R^ɳÏ>ŠçyüòÎ;¹ÚóXÕ¾ €B&Çû®z"Æ_uîc8lØûSN,X)_/;q‚m2W¾Þ[ .ÏÃÙþ\Þ†g˜›_: 7ÞïýÅÇðºË8zop¿žý™ë÷ã<¶ ç¡ÓП93,_ÕÙuÁÈå‚ã:NE ¬G&ÅØ¹X¹Ó ÊRáVçj.ºèþ¨¸8 ×]Éöí¹þ%Uç:t̬ U¤WÛ®ï•8^s™LÖ¿vÃ-WèXÿKQ%^ùÊeatÚéý¿Ç)@‰‹ »\­«ÞTyÍM&Tãp3ŽT(€Ú|ó Õöxçm¾ :jó­Ý3…–›ña@AAA„æ$NGNj,Q…mfÆ…«5f©"°©±I=†Ž÷B,—ËÃFqSå©TWq!N-ïîî®›úI­§¦ª …B–´6º[¼œîîîq;=d2™º×^…Z‡@µ, [¹q…ÄÛªö‹Ÿ£B¡@&“¡··wÈV.—«+žHý…á¹óškØšJáÿõôÓ¼ä™gÀqXûâ‹\|ìXÕ>IF§¾×c=‘J gµÛ?~ャ^¸‹+¯<…_}ë[üõ[ß ŽÃwÞ À«ÿð¯iÙ·/òB~×Ë~ŽÉCþMh*Ψ¦±äèQ÷å)ýÛ‚ à@ÕÃÆÄxMk „9è:ÆÛÂüާœ‚ý…½Øj ·íœÿ|‚ä»[‚ÝOÿCÐu\7hO$ø©{u4G]§Ê¤¬¼&•X§Îŝ޼"¾uëÑuÈaÕ"k=M3ð„N¯3\90|.ÇÉdWS6ò&nÛÇŠ“Äó¼ªY ŽãN§£Üj†Jœx¾¾É‚*Vx-ñ?U·ù”ï/ÞV~>‘L&£ÐÂÔ b³«NžšA&‚ ‚ ‚ ‚P23î1Ï»7[Ò·L´žjüs¤È`#‰]JøËØi2™ŒBÕÖ.©þJÐÉAÄ0 2™Ìˆ‘Å&rŽ”ð9QÆ"ªPªÂÌóÌ3ÏùÃëtÞí·C6Ëy b¯\¶Œµk×FÛǯR"Q?Œ'ÔÏèyÇࢼ£¿wÁ<÷â2¾øÅ#ŽCwèá»jñbV.[®…ööåÅE‹¸ûìß ó,þàÄk‚úüÃÁrMÇÁÄŽòÚFÊe\7ýŒ×.ÃþåKñZÎËÂûÍA¼SWR*…QT×,„GÛ^Uí5ŒjÛƒ¥aç/.Æšf.2Ÿ¿^8=&Þ•øë¿þݰš¦iV{ *A7.dÖn?^Æ3Ä‹µê›Uê–=°]ÇV³ôâ‹¡·7Póº»)—Áh}Ž­$*ô< J¥@øSuR`ò—â={ ÞW‚¦¡݇¹ö±¨m¥=Wâ¢W{;ÆQªß(¤Ó>šLVΙ¦ÕÌd608x`ÎŽ»8kQ¡ZÇr-Ó9t<›†ü›Rxä²Ë.£§§gȺ®®..»ì2.¸àn¾ùföìÙÓ°zf³ÙÈ*ŸÏS,£Û*T‚š1Ó”ð8ß„7ê‰*Ì>šÑH[A˜yšÑ‚0ó g ÄÂüAú‚ Àì°Ê»¨X,’Ëåèíí%“ÉD"Ü|U[gÃùé;8æãØîHÌ;€®óã_ütËO:)\¤£„T5ÈáNd¬7,YÏ”h\uÕV­zŽL&ƒçyxžGÏÏâêÓïa¥ï³bp0p°0 Nyáq: ûðïq«Ó–ç /¬¨^ºN>Þ²µØ™2d2¸Ë^Ižàw¤Â¥ªúŽ• ª½r-úYG£mœ_žB±XYŸËÕœ‡1*z™LЄl¶¾W"õ°¬À@׃íÇc¦FúIÎÓ>&šRx¼ù曲¼««‹íÛ·³e˶mÛÆž={¸ùæ›RGÏó(•J‘Wò|T 5K¦Q"Em¨Õù†j·ü1Ï^šÉ¨âår¹Ñ§EæÍd AhõlØA˜_HŸ@h~[`Û6Ùl6rNPãƒqQË0ŒYfUhNæëx¯¢YíÀñãÇ+_tÝ»wG"žaèºNÈP‡c¸K\*U×4xñÅítvî¬Z®ëpôè—Ø½ûG8ŽCGG¥R‰7½çw>sï¹€c==œò§ÊE±pWÿA Üe³ëà† äþþ”@ósÝH³mHvîEk9y6º›o Û~w«ëcÄ< Á=q¥]—Eûx^੨ÊËf‡¶w,ärË6 pÉ%·ÒÖv÷ß¿0:öTæfšNxܺu+‡ª»nÇŽlÚ´‰M›6ÑÙÙÉm·ÝF__;vì˜ñzÆ…FMÓ(Å~*Ù°¦i ËŸI4ßÄ7Õv×ugÅŒ*a(ÍhæÛïHšf´‚ Ì<ÃÙ±‚0> 0;lòvL§ÓX–5lˆÌùàí(L-v,–¦O^7Ïh;àõtÁG^x¡êû®3Έ>[–E&“A'adDZ⺰k×&¶aQÕòR ÇâþûÏ ™LFùR/ù“?áÜeOó:Íã`[½ë]àºt.}ëÒ{1ÍÐSѶÁ0ð¼ ¬b‘@DQ»p%¥—} "’¾ñUuP·¬ãT ˆaÝ—¾"Z–Lšf2DtU’J½œ–áëA½ â´Yo8÷Á?ÌwÜ~+FËÇ;ô+AñF¦©„Ǿ¾>ŠÅ"·ÞzkÝu{ö졳³3Z¶fÍÖ¯_ÏÎ;Çs˜)!nàÕ,¥L&…YUÔv$†3L¿Í§Žbq:Jmn”@äŽÇ2 MC3ÚÛ¶EÄ„¦m 3Ïp¶@ì€ Ì¤O Ì[àº.¶mGù G ÝÙÌa=¡Yi;`Ù:Ë÷µ´T}_»vmôy¼Æ*‚=ú裬 ¿wtt°wñb~þÕÀ£ñСC†mÛtttpþù?æÏM›£»~ÈS­­ªr¿Ûùæ<òo½;P M3 wêyC½0½£-8¶ñ.T¡K!ðZL¥‚ÏšVÜEÁé§cYÁ>ÊS±£#:ÇI\WuªÎ}õ«.?ÿùwøÑž!“©èãÅGedšFxäÃþ0–e±~ýú!ëÕL†¸ñX¶l}}}#–ýÔSOÑÕÕEWW×”Õ×qœHˆP£iš¼ï–[êo¾g˜\`žÃ#bžçÍëYTâ¥VÍöíÛÙ¼ysàêß„L§ؽ{7›7ofûöíã®›ÜKÂTáLBŽ<Á…¢X³}í” ÊÄ/Ü׉}ŽOmÀê_ýŠÁÿc32}‚Í›77º™‚ÐPúúúؼy3ßùÎw]•aÉL¶OpàÀ6oÞ<¥Ï‚0Qÿ‰htUê2ÝÏßùÎwؼy󘶄¹ŒúO”çƒÉ‘ÏçI&“X–Eww÷ˆãqóy¬N?õ&ÃOu¸^3û˜áXÝ:ï¼×g³õ6èju$³±ëþûñ<Ó49ræ™ì?p€u8{àC¬{ï{Éd2tww&Ÿëy ˜uP×)þþ6Š?¿„b× Î3ç³m‰`× "¯*òùJ}T ÊåÀ[±\®!X®i•P«œrJ$øYÖô’ã".Žêzýœûöµ6×_1W_½†\¬22ô t´Éö NntCÅb‘eË–qÓM7MyÙ+V¬à-oyËÃ3Y,˪öLÓ¬+ÚÉeäu‚`éñvÔ4d29oãÆçóy™AVƒ 7ЬîÓiÎ9ç¶mÛ6®}T( ñxœ;86WÅÔ¯‡÷ô:ß=*á0Üð¥Be(A¬~7ü®*ðv",#n“ ÷U«òá»J8niÀ¤ÚkÞŠKM^qÂý†ó÷6€à¾üå|éèQî=¹iºUÌÆ> Ì6Ö¯_϶mÛšZx›N[°råÊq÷ a.²eË€yû|ð†7¼!:‚0ŸÙ¶m===ôôô4º*u™ Ï*S¹\ )1ø„)d&&Ã˘áøÇ Gc´€¸ÃåqÌ燊vPíI¨Xºt)O>wQýïôÓO§íéCìà-çn§õ©?Ç!™L’½a?çmÝ ·ß^)lï^ì‡Vc\z"pÿ ËS‚^½¿š,wÝà•ÏW×1.¬ª¡UÇ ^ÊÓ1ŽºÕ £~u¬hZµx8ÜÏfÑ¢7ò¾÷5&=Þl`Ë–-SÒ'h Çžž¶oßÎÇ?þñFWę$¾¹\Ã0—e*^‹Á@1TæwlF;`·"Ô ”%HLŸ,®äL´k|äÈ’8í®~ý"áqßYgqõï>Eí¤“*;'8ÿñ8™+ïdÃ’0òM&3DÍÔVœ¨~ºNùÌw£iжqQÕ)™ ¼¡:£B ©vwW–y^à=ÙÞ^ ÃZ»¦§ÒöD%^Ïø±ã¼öµk9vl5óðg4ã4…«COOË–-ã–š0¥]]],[¶¬j¶A__ßwêzîÕÓëºUB–išUáV]*ƒÞj°Û 0D:Á ²C0`œ¢âÍæSE$²©Ã4MlÛÁhѬv ™ò;:TwV”§]£PÿÑê쨉:O@Â:מAµÞ¨Ù_µ'M`;3±åEBo=*ö5¶T}΄û·…ßsá:å9ØM :áwƒŠ˜$ê¼ðXªûU¤âØKÅc=ÞÞx’ðZ¬pÕæþšõ™:ÛÇç_ů}ÜCR1û¬Õl_ûଣGÙuôè®ôÌÒ¬¶@„™e4[ f:‹„¹‹ô A€æ·¶m£ë:¶m3000ùaÇ™·Âc3Û*l›S^úRX³˜ø¸]­7d¨)YÞÒòf~úâ»x~÷/¸”=\ìÜ}7ÿ—[(ba¾ðXeGÇÁAòw›\²ú_x7TÅ=5^qû¡Pì ;&öYtØhÕ£iV¼]7ýâÎÞºx5vtÛÄC¬*ѲžÏZæÎkøSO©êçl.÷£0õ4…ð¸iÓ¦!! zzz¸æšk"àÖïܹ³ÊXôôô°qãÆ©g±X$—Ë‘Íf±m; ãé$…Váñ”¯ÄF`Z‰I‚ÁäR¸<Ïô„Zï gÍjÇiŠ‹Á$…1N}7¨ˆn%*BšK`_’TD>‡¡Tç™ÍPÝŒØñíð»òÎ+R±i¥p{-¬“²}„u3ÂïÉX½—«z9±íµ°ÙðxÅp_åIÞMEx³©ˆƒÊ³<û7ãaäkσ bß•ˆªPÞ…C;Ž# Ž ±Fc£Ym 3Ëh¶@ì€ Ì}¤O 4·-ðŠŽÐÜv §ÿîw‘ðh2¼wäH&£vHÛ0*9³Ùl”›ðÇÅ"G~„g[ÆKÿá´:ÄÂË.ãAû8ÎØ--x׿mçOÁ00l÷Ì«XyÑEUåçr -Ô°¿û(Îà:l̰*„©¦âžaTDD%>Úv êÅÅÂá@3L/Y*Õä{ Qâàx‡ck…Êz²€ò É`úi áqÍš5¬ Œq⃠™íÛ·sÍ5×ÐÚÚÊÖ­[immåšk®™‘z–J%’É$ù0X±aQHÕnM‹éKÐJPß*ƒí*„žúlÄÖ “§P(H˜ÕYF³ÚÛ¶« Ï4JÌKP-øA%? FEä3©ˆ€jÎSÙ˜"Ï;'ö®<÷” Xj^•¡r¨†I[–¯ÂyÖQ‘÷-‡ÇUßñ0~7Â÷x?Ì¢"LÆëÿl³n*Ðê½)L-Íj A˜YÆb ÄÂÜFú‚ @sÛ‚|>çyäóy™ø.L;qa{¾y6³`Lj¤+5Üe¬'¸9N/±P€RÉ "3ïùã5¼jo†¾m\}÷ÝÁÆoy ÒÓÃÊ¢àZòŸ¾™œóY°,t\ô3-Uåwt@&³ gp™L(ÌÅî9Ó ÄŽp /‘߯®ópaQkóUf2Á¶ÙlðnÕ¤[Œ›Ó©ÖÚ•€*L?Ó"<îÙ³‡¾¾>Z[['œ9Ζ-[¸á†¸îºëhmmeÏž=lÙ²…ÖÖÖi?Qžçáº.Žã`;?ÿy4Mãây¤ÄFRÕ¤âÙ/$Âm'eÌ}æÛð|b¦ì€ã8‹E4M›ñˆ<•ÙP6Ï»2¯F›@øî¿RíW[s'¶Î¡ÊSuˆ<*e73îÑgǾ×F-¨g×j—ÅãÛ÷×Ù¾Öë0Ž<Ê ŠFö AhÄ‚b A˜i[àyÅb]×q]—d½˜~‚0…ÄǦdܳ>ì¨Éû¯~þy÷ö¢oØP•R¨î>NýåCBŒ:<{°4Ê£X*•Èx·~ù4üg_ÇkŽ—ƒ °Ä‚b A˜ [ ¼s¹\$8J¨Ua&pgÞæy3Ý'Ø·ow?ù$\t¦ibÛv•ÃÀö Þk‡ …úBÙ…§=Ä»Îþj VÖ¨d'öí ïÝïfÙgò»};7rüä“ùÚSOñ~Ï ¸,èg¿öpœJnFÏ Âœf³Ðß_ñf¬Í娄F5¯Âu+âžm ¡ÚhŠan*1ÇÍÁ‰ì488ÈÖ­[Ù²e ·Ýv[ôcÞ¾};@´lãÆÜzë­ôôôÐ×××è¶N˜l6x<–ËÁ/O×1¼TÈB•wL1©BÄJAh.™^‚f‚ ‚ ‚ Bó‘N§Ñu˲Ð4-z„éFDÇæB]Ÿõõñ›¶¶hùXC/§Ó±,Îê“àc÷¼5PúBáÑxéþüä¿çùC‡xçEѲo‹/½€;_øCÎØô·QâEÇV¬@_s< /ªò**ÏD¥kÚvEtÔ´Êú|¾R/å‰8¦9>ѯ¡iV禦 ;wî‚„­qúúúX¿~}U²×77älŶmö¯^üÊe~wöÙQrX‡ÀÛQgôЇ£!£ 4ÎTĘ"< ‚ ‚ ‚ BóQ*•( Ñ÷FDJ¡q¨1|5rxä°mLÓ¬ë=æ|ŽÀžy;§û~ŵpÿù{,}á>¹øfN{è!\àÔ¥OFžãT×Ý»ˆ"ÚKO©:ަUDÂx8S•wÑ4oÆñæVoÄéÑBÏf2C½DG;¾D½n&$<ª8ɵ1’{zz†uež­Â£K0›ä ßü&­O=ºÎ}mm˜Tr7ªßH“y ‚0I1cQæ® ‚ ‚ ‚ Bsb‡£ôqaA¼…™ ~ÏIh߯R;v·k×®·.§ ç ïõ÷ȱÕÑç#ùÞ½’'ÃÕ»ÈÀ† <ðwÇ+ÿôJ2Ø´évúúGûärÕ¡Ãlr¸nð^,B"QÙN ’¹\ –Ö §:’`8^Ç‘„BÇ <4ÇJÌATh&$<*qqpp0Z¶cÇ HÚG Žëׯot['Ä_îÝ|ÐuÎ[¸0òŽ{8Šg’ ÌMÑ‘k¬Ÿ¥ ÂÌÿ\/äL-òP!‚ ‚ Ì$ŽãDya¦ÉçóäóyôÑ\Å„!¼êÈ<8âvÃEÈ­ç©¶}âX}ñàÁƒ\ü±¡ãrÎ’¯ðoé4 \÷‰O°{÷:ŠEؾýƪªÙlåyY•é8ÁK t†Qqª¬7Â0ê×q¤ªãñ’œêaW›‹ J\,ÆF„T~GZµvy­ 9[øöêpv®³ôøqn>z@lÔ/GA˜«ØñX‚ ´7·q±q´×­ÞWAA¦ÏóÄÛLh¦iR(À²&›ðK˜*~{ø0K.¹dÔíê {–5TØSß7lT‡ƒ?øV.‡‡ÆË/>oÜÎóÏ_ì °};ÆI'b\äTÇÌå‘/‘<•§a.c•ââ gê”GäT0Ò<Žñ§éEG‡ú¹öÆ[ïñz­”ÓÜ ­­­ÜtÓMlݺ•ë®»Žë®»Žžžnºé¦h›¾¾>n¹å¶nÝÊM7Ý4$,ëlÀ ïV=ô)þý•+y×›ÞD9¶ÍT 2WJšF…K‘GAf3ñäó¥Xw8Æøòx‚ûøCC½ð*2›QAA˜iǑЪBC0M˲äþk2v¯XÁ¢U«hkkv»z—­ž7a{ûArdyøá[Á²øïO>‰mÛ\¿t3;¿‚/|¡“ŸýìH´½µôÿa½ã0¹\ :ª2•¨èûÁ±S©àÝq² …B þÅŸãrîvŸV{Ôø@è½…õjÖ×Á›Lþª‰„ s›¨W Ë/ÖÔß Û•Ú;fR =Ç.Ð^S~>dùlâï~øC^|å+i}Ík€ ôb\S/s—FÍb»"Âl#.Æ;ûñ©±x0ª}㟇{xð¼Ñ,â¡fÆÂX¶‹Ø9žc ‚ ‚ ³Ïó°m[<A¨¢µµ••>8ìzèÿ©ÂžÆÙñÉï‘%ÇáçB±Hׇ>D9“áô‹/æ”Sžåøñ5ìþõ’h¿âÎNŠß^M6[ýŒœÍVžK•ɲ¬à¹ö9z¸È½š6Ì:%RÖ{w¨ÑÜp;›úâ^­W ¿çoÇêšÊÊÞ î'©~¡h·`A°íúÖÖ±V€³Ã:¦ÂÏE*¢ž dÃc¥jÊÌVŽM1ü^ ¿§Âu©Ørõ*QgÓTÄÁ4о—ÂcÃïJ´TçV‹SÕ¥=v>²±õY‚|©p;|yaÙ Âå¥pßðܼüæ—3Y&,<lÚ´‰mÛ¶±mÛ¶!ââ–-[xøá‡g¥è¨îõoûÛ ¼îu¬¼ðBñJ„y‚ÓÀc«a¶@Š{6ÆÃŸÆ?—êÌ´íÊ6qÆøLM•‡¢ÞñÕö®[›zr#Q* ̓QÛÖzšµÛ—ÊDAA˜>Tn=Éñ(TÆð¶µqæ‘#Ãn7Ü„Ùz‚äº7¾€÷·ü#»ví¢œÉ°ëöÛ¹ûî»Y¾bOî]Tyn}ã;!ô¸´¬ÀK±öyTÓ‚«¶súsÕë­$ô÷3Ô{ÏýLñJ¡„:‡ŠY{R”°å…eªW1\æÖ”§Ä;µ¯¿¾+ñ-¥à —%¨ƒù%M3,_ pm±ve Ľ"§Þ³T„Àt¸¬Š¸˜¯;¶\µ‡ð{:VWuŽ”é„¼Ì…uPç´H fÂv+‘3–¥ÅêÖ.Wû婎P·Wç´?vL3Ü&Þ>è×§Ãrr@–>¼”É2)á §§‡žžúúúª–¯_¿~Ò•kê^|öÙgÑ\—ç—,áÑY*V„‰áMÊ7’ÇntãA˜·ŒwÎÅpbc¼œz¶ ÁçølDÏ«l3OIM«¬Ëfë‡c ˜c!.fÆCÍÄ?;Nõ,ÒzÛGÿ2âG ükAA€b±H&3UI—A˜í¨G´ƒmmèÀ)§œRw;×­Ÿ/Ñì8Hw7ÁCrø€ýëßþ„åË üÊ?—•^È_^uk×®åÒK/e`` (ï©ÖÊ$Üc«aÿb xFÎfƒ°ª¶ ì«+—£=?PS‘l¨õ©gZåõ—k-±Ä¥"jÕz0º±eJpSy*ž~qÁO… -u E œ¥òP=«O8v|-h·†Ëíp»d®„Òÿ…⧨xû婈yʃФâ)˜'ãJár—@xóÂýt @ èõÆêV’TrçåÃÏ×î×î“$3a“á6ªL7¬‡Z6;f.Ü^-WõéËóÂãÂúö†/õ=£~vÃý3á{2Üߤ’SЀ§_û4‹,f2LXxìëëÃ4M6oÞÌæÍ›¹îºë¸å–[&U™fA‰ò˜&žëòú¯<Œ‚0Ÿhä F µ*B#°Ç“S fûZQ¬6ôªÚV…~Q^ŒJ sœJþU–iV„Àøþês­w¢Z^,VDѱx<Ö ¥ñ<“qoÌz˜ñòU[T˜Xµ|,ÞÃm£ÄLÏ›:1SAA?¶mãy–e5º*‚ 4!|ü8ç†Â`-º^Bl¾°œTŠàÁ3|à;ûìßãŠ+®àûGßÌ7÷î塇Mã7¿ù[>øÁL³z.÷-¯:ÎgÃ÷ð;×>㺱—C%¡ò8Ì ‚Ú¯©ˆwéðs\€T”båX•ý#áL#W”ð¢¶ï&ÀraÙI"ÑϸÌËÃòB!/ÿ=(]I ®…ÞzŽÎoÀ}ÌBXÿ–£F4IESÇÍ„ËËÂ^&8N$úYaݵÊñ¢rÔçdìxFøR(!R •™p_…:Ft³ÄŽ/Ç—Åë“‹Õ¡m˜e…°¬\Í1»«7=Øq•¿]Éd˜°ðØÕÕÅ¡C‡¸é¦›Ø¶m7ndûöítuuMªBÍÂgT\fÏã§žZ{î§qŽù ‚0 42Ô*T" ‚ Ì$qñn8òùúù•_çâËTžˆZo¾|>XîºAˆ%,ÆÇvŠEH§«ëäºÁìÍø6q‘n4á1•ªx.Æg¢ÆÛ£rEÆ¿CåO‰*_F2¬SõQÔ‡ãÇN@u] ë*‚ ‚0ضM2™œ|A‚ ÌIÞôò—sΣÖ]§i5“uóùê‡ÀXøœÿ÷ÿ¾Ëœ@ç;ßIËm·Áš–áî;Ö`Ȩ&»&“`î‚r¦">š-AhUý>*!Bšçý"AèNÚÔ!°T˜På%P•¦Zl4 „¬QyîÅí¦Â÷døÞn›¤"Pª0 Jl³‚õÚçÁx X÷¹šŠHi‚÷a°€u!˜Ê‹P‰µ‚Ÿò Ô¨ˆ|Jø‹'ˆòLTuUÇQŸk©õt­ôM2¹àñ:áqîÌÒ‡—rΣçL¢b÷ìÙCOO[¶laË–-tvvrÛm·±~ýú!!Wgê÷ôÈé§\MÓ®… Ì<Ï“dñ‚ ÌkjÉ*ñ0þ9îù§¤âœç"ža‚¢Ê_¡D:Ç DE˪|7ŒJx¶M§aQ {ê™ tw۫ЭJ TT–U-J*²ÙŠ÷¥òfTû¨wÓ¬x]ªº(áTåÍP^‘µ‚ªãTDÚ¸‡f*¬+•`Á‚J›ê劬'|Bð|ªÎOí¾ŠxÈØ8ñg[ Ý*‚ ‚0:ùP°m[Æ AMÓXûØcu×ÅŸª¹òÛ+e³¼ùÀÎ 7{LJ÷ð…;ánåË—£=¢‘ÏWžEóùð¹ñ |žÆý¸ßÖPÉ9X ô- *y¡’¿P½;ªð¦yª=ìJ^–@4S9*Š㢟Eµ‡ û¬°¨!šö†>Ëj׆“—Ÿ[‰›q1¯Lµ¨(¡æFåèYG']Æ„…G€5kÖT-ïììlô9™4ÊÜyÊ)õƒ/ ‚0çqMkÌ¿Pc}-A˜ÏÄ…®l¶ÒÁ¯}HRæQågtÝ¡38•à¦<òŠÅJù¥REôK§ƒ}U²{~Õq \¾ðù+&Uù‰DPGUÏ\®Rÿr9øœJÛÕŠsžWñÌå*eçr•ã{^E L&ƒ—*'.ø)ARymª‡Àøù¨·}üÜÆE[Õžx8žøçR©²Míq¥R}OÈø±m{üáuAAæžç‘Ïç±mÇqÄãQ ’ZÇ¡õÄ €ñå€ ¬·o ¾‡”'zˆ…Ï> ÀáÃoàœs®R«ò—'‚œ{ÆêpBkwðüê=C”“Àx'”~ îKÂå!z *̦ ‰ª¼•*©r*¡Q ÊËϤ’WPå-Tb¼<‹Š¨ò%*Ô>fÍòÚï5¨gßÚI¶jpU9¤Øûνüä ?™T'7ºÍÆ£> 'Ä~]§õ¹ç”M‚0ïpGÆ ‚0/ˆ{êÅóDÄCŽÚv BÅ0ž§Qm¯<{{ƒeJ`Œ‹cê=— „¼D¢²Üu+ ÝݯI˪ˆdº¼”`¦9舉¦Ž–Ui—mW?Œ¨v‹•ã(/BÃÊQûx^Å«2™ ÊÈç+ítœ`YüܨÏqÏM× Î£aTê÷ TçL­Ëçƒí•H«¶WçI‰»µánÕùª×}Uû¨:40± ‚ BÓ“Ïç#ñQÓ4t]£‚¹+¸.—‡_Ã:19‚õ¶ã@kð=™Ó¤üõ÷’xôs<ûÿÁÒ·¾•õ~Í‹÷±€[ùùƒ¯Îö¾üOs-Áü[Hý-è Á  Ý Ü¨~OXÇÀ' B‹¦¨äTXBŸIàɘ ʈ<•ÉSaEu*¢£~Ï…Ÿm*áWÕi¨Íw¨‡)-—+Ï䆅ÂÐmâ“s…æaÂ9ç*>õ¸. wíbpÝ:Ö Θç“xù BsÐèP«2ÕA„é$î!χ¨„6¨jÛxŽÃ¸à¨&}ëz x‹@§<UY®[ ]ªöO§‡Šh…Bð0‘HuQÞƒÝÝÁòtº^‚c*K¶)—+![»»+B\{{¥­*üªX“É`m;X¦ê¥ÊWB(mL&+“¹\P–ãTÊPb©:¶´Á0*uWy9T¸×¸7d>,Ëfƒs£Äa%Hf2•k¢B°ÖŠÂµ×^µ%¶VAAJ©TB×uǧAª >Œå¡jï^;ö Î’U¢ã}mm|ã–[ÐqyÛѽü„süøÕ îZ.,µ—Â.0öCò $2À‹ /íƒD9 “ @mpÝ$‹ªŠq3fÅÞu*¹ •²€êP¨Z¸Ygy2ö>…Ä#Å£!Å‘4"͉!*åÍÏŸ€·ñ•Ï?ÿü«ƒta¡ñØ¡«ÉL†Zµ ¢!d ú2 A„z¸nuŽ>E6[ñ´íÊ6ÅbeÖ_6[ñ¾‹ço„joDåy¨¼ã|µ>n•X§DGåí•üŠª|•Qm÷~TûØvà­¨¼•ÐV,Ëu½"–*!3—«ÌzTãAº´·T êQ."ö‰JXÃÊB¡"RjZE`,ƒï…BPŽ »ªrWvtT¼K¥à8™LõqUŽK%f¦ÓV]/¦UÕA…xU!SUhZå­¨®©ú®ê™ÍÇUmÍç+Ç0Íú÷ ‚ ‚0×uÉd2 Ÿœ,Bóñ˜Êç˜ÍR&ú=›ÇÉmèÆyêœÊ¯ú™üÔmwò²%K<ýmؘd¹Že ^ 6Ý öÀQ`9䎆Ϣ- Ÿöp/& 3`<úŸ@î<Ð^CµWãT:m7È$z^ýgÚÚ”0Bã™T¨ÕÍ›7×]~Á YöðÃ7º­#¢æ&_9G¥RP® êDÅ|>ØÏ0ªà|¾"ܪ3ª½q1Réê ‚ ‚ Å ;¡Éd’t:-£ U9r`Lcˆ_ÿ;ŒU{ÕÁ¼ì»É\ÿ)œ½«øÄµ_åoòÿî‹ qîýÐÂM—÷ÓuÏ:Ü_€½?pš²^ü`‚ù(äî‚ÄeÀ>à]ƒ‹ùà=soM%r£V³éÑõàY\MΟè,4׬YÃM7Ý4¥äÃþ0;vì`ýúõÜzë­¬_¿¾j»®®.¶oßÎàà 7ndË–-¬Y³fÒÇWºdÕ¢Eìw]VíÝË;/ºhJÛ)Âð4Ü8º®SŽ:OA¨t;|W¹˜M‚ÿ}y|„jm m3#}¿âá§BxÆ…G%©0žÊ£0žk1âT¨   Æ0†æT^‡ºˆ\–tà5­"¢)3©ÊTž ©šÏWªº–ËÁK‰‹¦YêTÞ–Ž*UÔ1•H™!„K=qV y*¼kr !`êå¨Wîh¨s¡Îi½zªåÙlPG•£Ry?f2áWy{êzÅUÕU ²ù|uŽIumÕõQ碙…DZ؂¹dAÊ|ì‚0”FØÏóÐuMÓ0 C„GAh0ÍÖ'8ò³ŸÁUWy{à xè7Mø®‡÷;çG§b¼^õ»w°öéU öò‘ÅIËÍ-$þ¡-H©økpÚïFý‚P§I°òà|œÀ†Ø2Ô¥6KMXmÄ¥ø„d…z®á±¹˜°ð¸eË–)­È 7ÜÀ¶mÛØ¾};7Üp?øÁhm ¯*á FWW7ß|3_ÿú×'}|¸sÏö¯^ÍëW¬`?ðöLJի§´‚ O£í€ëºSbÕ%˜¤¼uoÆ^fí½ Ì¶3E\`„Š€åº0”Ë M¡¶‰ç„Ê縩¼ë 耫ã¨pªj%Äe2Á‚¾ùº»+˜:~üXªã÷®S!F•ç#TBªÖc¬æW‰nãE‰£Ê³p¦PbãXǪ”H¬¼ãi\䌟ƒz©Œ•ÐèyÁþJÄÖ´à¹÷K_z3kמ¹2F³sÁ‚02ó¥O ÂÈ4Âضv¾LÓŒ> ‚К±O°V…[QÏTÏÚ«)èáƒøy¼³>ˆýDv^¶ìoúÍËi{±ìQp¾ œɳA{²|è—åf4t`p{ÍÁêLÂͨÉËñó«Æ- …ʘƒaTÆ „æ`R¡VãôôôÐ××3:;;Ǽo__}}}|ýë_f)\|ñÅ\vÙeôôô°qãFvìØÁ¦M›Ø´i·Ýv¦i²cÇŽh›‰â_îé¡õÜs¹hÑ"¾¼áð̈(/ÌWšÁ“~˜ð¢ä¯FA˜Íb f‚¸ÀÕžŠ %)âbcã×úÑGÏáôÓ9³'d ŒÅÌ; Âð̧> ÃÓH[ ¼339kM„!4eŸ |€{CkÚÐÉÃ{ŽwÝÊCöIK£õ+=x.˜ÀNàÐ \¥G€çÀ~ ô` tìíßóæl£X Æ"Ô3¼JÑ¢RÑÄÍsn„“K,œÌ΃ƒƒtuuqÙe—±yófºººèêêbóæÍ\vÙetuu1888j9­­­ÜtÓMC\£ãôõõ±gÏž*AsÍš5¬_¿ž;wNÉÉøÖÑ£¼ô¥/åê†dq&_„ ÌJšÅLÔãÑ#ðpl'ðp,‡¯ ": Âxh[0Õ,XPy\0T„ñå¨>C°]ÜÛ­X¬Îí¨ò¸nuþC%l*á1‚ĶƒýÊåÊq‰êã+áJ•‘LVf*±,žï°ÑõJÎÉfe:„QU^½\•W^ùKN?ý…F7{£Ù‚ÙhAsµO Âøh”-pb3þ¦*2’ £)ûÅ"-ûXÕ¢ÚçlbƒÂ<'+MàL~rÊf~½ètœ·„J[ œ ¹ëƒà<u´æøÃ<ãÍEœÁ¤¿?ãдʤ虞\,ŒÎ„=¹á†èëëcÓ¦MtvvFn̓ƒƒôôô°uëVzzzøüç?­«GÁ²eË¢ÜÓM܃Ñq £|?øîyÕhM >˪äb´íà½6d‹iË ½½zãTÂk*ÒéÀÃM¡Ö©¬–UÉݨ<K¥`y.¼×ÎÉšma]êµa>É ½úúúèêêb÷îÝãJ‘ЦÃ8p€Í›7³~ýú)Ï]/³‰®®.úúú8pà@£«2j=§ãùà;ßù}}}lÙ²eD/ A˜ëÈóÁÐçÇ‘˜dÂübûöíìØ±ƒÝ»w7º*#Ò¨1CEm$ÕÚqÄ*áQyœ´¡½4m:ìÊ ½´…­Ç–^¶G.Ç^ ¦æj fŠ ŸL(µW& Ï'L3ˆÆ”Íãñçy× Æ*ŠÅOSaR¨ßØdû÷ìÙÃöí۹馛F¨èììdÓ¦Mlݺŭ@ýÉ÷ôô°yófZ[[Gü±…+Vð–·¼eôA]Ç p„™GÙm„õT]£"ƒoRò”x˜ªÙV•oPñô¨ð:Âý=aIOÕOý¸a5 ÑI ë:’P ¿÷Æö±©žì¢rÿyáþÉðøªný õéþtÃc˜áç25bØÊ•°r%›7o†pŸÓaÎ9çœQ…†±z:»×(Cµ—ª ̶mÛFOOOÔYoVÚ'˜‰ê†Q ây¨§òí)oF%0ªY{qTòtÓ ÄBÛ¶Qù=/ðbT¹m»:”«ò¬T¨žÙlµ§c<µ6çb±8T¤„ Ó\,‰‰DEŒÌç‘Py%æó•P#¶|‡ ¼b_\…f5Í #žÏWÂXVe¹ 4c±ÍjA˜f{Ÿ@„©¡¶Àó¼1§aaúiÆ>šœ·¥;Tå<Ø<89|õ“/à^ Wî¹’—à} ?Ï'Ÿƒm‚¢»ò·–Ùè3Þœ w^,k|å3Är<^|ñÅ@tv´|Û·o¯Ú§kÖ¬áãÿ8·Ür Åb‘eË–±gÏnºé¦ªp®[¶lá†nàºë®£µµ•={öLiÙŽü®¿~jÏð  Cõ®~ƒJIPWU>Á•<‡*L¨É á6ùpÝxÇ#5Q&·02&‹Þ‘ \ï5 ÝªÍ³Qxl;PoV£G Øg¨ü®2ÌÎó,ÍN³Ø‚ñ r9ƽ •X¨r-Be™®ÛÆEH¨ˆŠétõò¸Yò¼@TT‚£*K‰—j[Ó ¼UhÖd2(_å•TÛB³2[ÐLv@„©g6ö A˜za ¦ÓãÑ£â`Ѹ ë‚0›h¶>Á)Ï>[?s dÖØ¬ F¦­äŽ,`ãÑÓ9þäqŽ´¡m}¿{ØÇuCá1|¦·íJzalˆPÛœLHxTI[·nÝÊÅ_ÌÆën·cǶnÝʦM›FýoÚ´‰ÎÎÎÈCrÍš5CÜ [[[ùú׿…m½øâ‹§Ìp¬yòIïÛ7µgw Qc“A+KÐQ‰¯S&Ï%ðÌR6ªL%çàX:5çáDIˆ›êó|Ã¥1¢güÚÎF›Ûh;Ôí8¤ú›Ð0«‚0]4ƒ-ÊËQ¡iAÐq‚Ùw*Ü© ©Z* ÍÛP*e•J•‡Œr¹² ‚}J¥@HÔõʶJ´¬Ñõê°ª½½CsH B³2š-h&; Âô0Ûú‚ L°“Õ8Cuº!“ê Ì6Áx £Ó };|þÈ#ÀÐ1ÄäEþ:äVXeÀyËkå•ÚÓp>}óQÎ<ýLö=¸#GŽD)UÔsºÓˆeA˜&$ SÏLÚÛ¶Éd2cÚVE S^Œª«F¦R¹ág3Ü>1“'PæÍÐ'(ÞÀ› P\pï 7z8ªÃÝÎ’½<·ø9Øpo¿õíäóyîÜ@kk+…B°K"QG„¹À„…ÇÖÖV>ÿùÏS,Ù¾};;vì²þ¦›n²¬¦ŸmØl¿g ¿¢AÐ)ÉQí©¨¼adïEµM£Ú7Ÿ=Âò <¶Ê/)ŒzùodzWÈo¸®Å×Ïf³är“ñÝn†kG©T"™Lâyétšîîn "6Ö.¦%&F%ìi­¸§B®êzEhT¹³Ù`!êC•Õß*W¤iå&çchAAA˜ÔØ€9LœC‡`| MZ¨#\ž!sbŸA˜[xTÆÛMÓ¬LôÝšÁ0ZÚ‹.¬Òa¿†wx?k_ñ4öÝkx÷?ʆwmàŠûîãàÁ{€ë€`,!™áQ˜;LXx„@\ܲe [¶l‰\˜³m¶á¢çž›¶øícŤÒ9ItV’Ô<¤Ó¼¨»¨QBÕlÍñØ ÔÚ€<•ߥÐâ{¶mG©TŠîîîè¡P m©TŠÞÞ^Ç!ŸÏO›ð?îp8Žƒ®ëC¶ÉçóX–5dy"‘ P( i®ëFëóù<ÉPYRç@×uR©årÇqpÏó°m›t:M.—C×õa=y…É“JB¡2¶„ÊQÓ P<³ÙÊ~*d*Ëã·iË'ðrŒ Žä~,—ƒW|AAA¦Çq†}ΫõRT~l™Ì „¹K|„Å0ŒÊÀ@´QÓ2¯1a¹ÿeÂÓ_„Cà8%ü|þéŸñ®wÁÁƒm:tF¬¼àåyõ£ ÂlcáTÔÙÙYõšm¬Ú»·ÑU¨òjTb‡xYÍ>L‚Yo«f{ŽÇFR’Ò%è,Ì&¹¸È”+M„‹ YTq#k(•JÑv‘È—J¥ð<Çq(…êM©T¢­­ Û¶«=ÏÃ4Í)ÞêyËŨþù|>ú\{ ŠÅ"žç‘ÍfÉf³xžG>Ÿ„Bµ*âi±X¤££ƒt:çy”ËeJ¥ù|ž|>í“Ëåð<]×I&“$‰H¤Ô4b±H¡Pˆ„ÉD"1ä§Tªä`pÝ@`ô¼êeù| $z^°^y&ª<,Ëå*b¢ãTò;‹°¨ëAnFq^AA„éÅuÝºŽ %/Ç A^F•¯QÆ^a~¡«YÍU½ª²°èÀÛ‚±p< ö°ÜFÕÅüÕé_æì³ÿš‡:—¼äü¨¤çŸ¿$*B$“•qA˜ÍL™ð8]]]\pÁnçˆxÀ¾}û])E:>C¬ð5ÓÄ»Æâ;>jª<Ã{7o ½Ž|>m;œ¨7õ¥D7Ä;Û¶#OEÛ¶q]—l6 ‹†aDb£:–ÚÒé4¦i’Éd"ñÏ0 Òétt.FkÏ“:ÇÅb1:~±XŒÊŠ—W*•¢íU½\×¥££ƒ¶¶6Ç!“É`F$Rº®-O§ÓUíL$$“IR©š¦ÑÛÛK¡PˆÄBÏóÈd2 P.—q]˲¢s“Éd°,+ÚO×u àT*Q*•"ïK%@.X°€o|ã3rÌu'‹Åà½P„D×­¼,+³Ù`}2Y ‘êº.‰DÏAÓ/Êþþà³iß’›QAA¦—xôD„<"#ÈPÉÛXdâc¸Df'Iàšü/iÙ×,pît1BMÑ;8–‡_¥ðZ[¸ë™5Üwß}´¶ž`ÿþÕ$p×]ëY·npHù¹\0† ³igðì³Ï6ºSJíØä|êÐÔÎKkáh&‘àŠCÍjô ý?ãâWœl6‹ëºxž‰Xj_×u)•J,X°`J¼Üꉟ¥R Û¶"ñ­Þ~ñåñzÆÅ|>mÛQxÒl6‹®ëäóùHxK¥R$‰(–~{{;Éd’\.‡¦i$“It]<U¹ Û¶#Ñ0îµhÛ6ííí‘8˜Ïç#‘Sß¶¶6:::"OÂR©D:ˆ< {{{#!T…=õkó®w9¬]ûߨ´iÛ·¯Å028¸¢Ñ-„icÞ{<ºÀÊÇʵ Ìfôšwal(<›Ææv¬ 멼 ]×Ä¿¸§ž ·™Ï磰šJhЇU_ÜkQ‰™Ã¡<ÿÔ¶jûb±…UžvÊ»R‰‹–eE¹•(ª¼ã9}ßÄM%JjšFww7¹\Žd2I?ýýý‘€ª<ü`¨€W‹eYX–E&“¡X,bš&ýýý¸®y+–J¥Èó0™Lb…BL& ›JÌTbb¡Pˆ¼Õvñº¨v4ªþêz)Î:ë,Î8㌉;ï±í@hT¨Ÿ–òZT¹'wíú!*ò¯Êë°wï_ÒÛ;4Œêpa‚ë…QVùBAAA˜Žãв~=E‚\ŽÃ Œªû.Jaþà»ví¢H10Nør8ÉÁåŒ'¿ö­Ïá‘4 Mƒ÷¿5›6mbñâ#<ñÄ‘F7Cf„y-<–D†?ÿùˆyÀa6!ÂãÄ1 › ^ûtÏ^Œ €ñ0¤ŽãDßlj^@BT‰i*Ì©òzTaF³Ù,–eEÞyÊ3*¦ U]êÙ@%‘Àˆ©iŽãP*•¢üŒår™t:M"‘ˆ<Óé4år9*+—ËQ.—#¡o?Ó4#á*^zSEÜSS×u,ËŠÄLÞTm§>+‘Ñ4Í!žž MÓdÒÊ<%yX &2AÕR)ã·±çÙtwWöí訬« Q\"XŸ'žsTAA„‰ãy?hoÇdäq%8Nvº©ŒF ÂìÂA¨U@ƒg<ü«\Üc«qуA]ç®»öñÅ/áé§oâÒK¿ÆÂ…ça•hI‚0W™×¡Vó„âLÌ«h.áØ?a~ÑM ª7‡¯ÕìAyæÙÌLnÇxÕb±}V¡;•è¥iZ$n)ñ¤ÿ{7|û6¼nûƒ±è‹¢P¡*‡ ¦itttD9U¸ÓR©D.—‹¼'U]lێ˜‹EúûûI&“¤ÓiÇ¡££MÓ( twwãº.‰D‚Ç!•JaYV´NÙT%VÆC‰6J¨«W‡fñJfŽS!5-UˆÕ¸Çcð@q‚D"Éú“Ÿüx5‹áèÑê<2AùN$֫о*÷i=á1þ{AAab¨çØŸ®ZEf ÛkL~Ò²ŒÛ Âìâügž©|)ׄÁ, îÒ ù`p`´¶¶bYétš›núk‰6Â@b‚0g™ðØÓÓÃæÍ›]÷I£¼¡ s ÍEdæÔüCcf„³¹†ëºìkiÁaæB¥Ø¶iš‘W£ ç©Ä…t:yà)/¼Ä‚žÚÀW®ú ¯ßözV ® ûÙ,fÆŒr&ª<‚¾ïGÇR¡6•'¡®ëÑq-ËŠÄGÏó¢:%‰è³òüK§Ó‘(Úºo†Aÿc 3ß4d&ÀCÓ`ùò  Ãr=–JP("cèLŒabd Â`gç^®½öyÿû¿Ä#ìà;ßêñ¨ŸDÏX,F&“ bа8l1Ã.×ø*y¹NpËy6™ø2¬òŸQÎwT÷±ñ}ý‹+Íüû!ù]ʧS7Qò„}'0óÐÌúœ¼A‹E€M›šÉç!›õÿ ?æ£X8JÜÆPxtY¾¼›“NzMƒ/}éÑu]×Kg‰sjÛvàÎ8—Ë‘H$°m»"Nj"‘@Ó4ÒétF±XÄ4ÍÀ’7êâ8ЬäV¿ …B¡P( E%gÿ韲ˆÁ Ó&ú°U¡PŒ.b¡üák°Ý²Å³ƒ?ÏÓÝ Í>ô·¤Î߉1gž5kVæHŒŸÄ[Ò(GR(& #rµºfÍ–.]Zï2Œˆ7ïÚÅC*¾£B1¥ë"‡a Ê+šÈâ÷8¢døøNþÅÉþo6¾iþýû˜~îtÐàw/ÿޱ‚?~"ïï åX öN›MÓ6ñÖ½•ðßr˜Ï>øYþqÎ?2í鈴ÀXdáã_üxèÞÁÚ€\9o„•`ÖÛgqh¦ÄZÓ´À5k¡P\;êº^ïÐu]ººº‘qÄÖŒ¡`G¹Âe…XT|l.OŠsZù»ènùX½|¼üIºiB0YÞ?WþŒ32ÁÏ"4)7Ë鹑<åóFóš”Ó,ÿ_,çIÄW±ÔñEY)Qu¾QàäÇNæÒŸ^ ·ŽNzS×õc8ŠæµlŒÇ}òÀg0ͳhkó- ³YÊ.Um®ºêgØöÖà9²,+ˆÅ*13™L0‘à[+‹Er>Ÿ¬£MÓ HüÕR©„¦iq\å\à»wÖu½W,Õ|>aÊjY¡h \×pAÔ]³ ñ¡Õ…B¡P(BlÛæùë¯ç#ƒÜ¤zêu+…?åfÕøÕ\(íŸwÀöguÜóQqÅŠé¼÷½›øÂri©a·b²3,áqïÞ½´··³wïÞŠíçž{.7ÝtkÖ¬©w¹Í­­wžÄ¢’òù3„"˜ëçcÁ‘$ò æž8Ó3y÷íïF×ub‹c¼ñðyûá·³æÃk8ýøÓýü—ˤÙš©…‚ ø‚^œJKE‡J!/SÞO/ïFE Œî[ˆv¾hè RÇYBÑODVúD¸3Ëßs„¢¬ˆ—må}R‘2H}Vw£AsHû#*jü^(§+ç“:’sXå:¶ÅÓ¨GN,)×X_º‘ûS' h,bt¹Žk1_ùäW¸”KQ ‰Û(üô§=|á M¸®o ÙÑ·Ý–å ¿ŒeÁ¦M›€å¬^ý×|ãðòË—ã@˜¦¸[.‹…q2™Ä-»€ €ñxÇq0M³Bh¡0™L’Ïç1M“ææf‰DRDM‹Å"†aô³Ù,ñx¼—ð(ù,ÙlvÒº°W(êM6› b?ëºN¬FÜ.ÇãñÀBZž[YX$¿IÜh±ž6 #ˆm®ëñe£m‘,ÔËl±Ê«mù“óâòY,µ…hz …B¡PL~sÚiô,Y2n.TÕò…¢ñغu+/½\6…åw&Á2H-z[_M>ï{Eø÷‚ýè"¾ð…ÊtâñÊù…b²1"‹ÇÉÂP&Ó‘É]ºÚØøóî Å`p]—‹V­âAjpÙÁïCÛ>ønU%®£¡£ËÀÐ ßµkZk>*î‰)qET„p²Ù²,Z[[+¬’2™ ét×uƒ‰©l6ˆ—à·i¶mc:޵m;p÷*î_ ¹ÙlÖwÙìêÁs+b ëºd³Ù^ߎãÏçýíb]. Dx”UF)8pÏŽ{ê8f}vVhñ›ðË; ð(Û.8”'ä*¬ªºí!.í¹”™7Ϭ°îNu3ã‹38ù±“×ÉG¾}„}ÿ³Ù¯›ÍöéÛÑs:¸pø[‡¹sÏ|üàÇÃöÔ€½«÷òô{ŸæÂk/ÿà0{öìá¤Dw®›Ew-òóbÃö?ÛÎôuÓÙ¹s'_|±ŸŽAØ.ë„ÚÃZ¬M$–‹®ë÷¢,8’þeYÁó }Y<±\S©Tð¼È¢Ã0WéÒç…B*• ,‘3™LÐŽ¤R© AªšøAg+ì§R)/^L2™ô½L”EÑD"ˆ¥bÍ-‹€@Ä,•J}ž§–89´’‡Ñ^„ê8NpîZyˆ^ÓZõ)B.„êÑ}¥Î¥ÞdH<¯¸Ïä^Êf³är9’É$¹\MÓhkk#“ÉûärƒY¦PôM´=ª…,>Èd2Á"„êg Ãz8 w¡‘ëºAœlè?޽,ØÊyFSìLÛÖß±AßJÑ'ÛÏ=—ëïº ”ð¨P(ú`æ¡C¼²`îîWùL 낦a=ÜD.ç‡i)ý0->8%KîÞ_ï¬+ãÊ”mßQ¡˜ò<ÞÒ¼;(,ã&bãO.ñ…'‰CØÁ€¢ctLàÑ Ò2ð6M3ˆ£(ÑɦÑ&•JUZ+ö7^®v7:•VbéUŸ E¾Wà{ß{‚իÕŒûöíc K˜ÿæÏóÐC‘V¤ûÓÝäóynï¹k_ƒæh4шCZ›F&• ãÅŠÈV$t ¡ T¤¦{âê‰s±®Ž ˆ@ jš†ã8tuuûˆUR,ñÜòÉs¹ét:˜ØÖ4t:LrÇãq_,Mø“ì¯ñ^Ã_åÿ €G[eeóJÇaá_.ä=KÞ°QËY˜¡À‚NÂaîCsyù§/ÓD;îÝÁŒ{gpzæt¼õA¦mšÆ}î}¼áž7pò®“Ñ?¨³ûv3ëð,ŽGI%R´%}“fÇqxnãs4mmbñ?-æ¤#'ñè›eß¾}\ºùRvœ¿ƒï?ù}n9| ›ßÌüïÌgãÿÛÈÅ\Ì3‹žák3¿Æù_:ŸGð†ßÀGïÄýŽËµ]ËÓ'<Í_Çþš/4}»{îæ²_]ÆáÇùè¶ÒtE¿kú÷öÜËE+.âðáÃl߿囖ÓïÆvmNØw_¾ûËìÞº›9š¾ÑÄnvóÀ±xÓßÄÓîäŽÒÜrøæxs˜7oóæÍóº‹Ë¾@Ó¶ã7XøQýî*»°¾)s÷vÖû±š”¸®K, Ä$¹ÇeÒXÈd¹¦iÄãqR©®ë’L&1 ƒR©ì%êÒXž§„Âèù«ƒ|«mqÇjÛ6…B!h§Z[[ƒý¢õ#y‹ÅbALjÙ.ý«d2,~°m;33™LP¯ÕeÎf³±u¥ QV;9ÄÂWÙÑÅÒv‚ß~‰0QÝÞJ;-ûŠUj±X¬°Šöe¬*y* ª¦ië]ɯԛ,b“ü&“It]'™LVÔA4Nð 'LÙ©†¦Ú½y4®s‚Wõ‚¹/‰D𞎊ÞÅb1½¢€ÀÚZÓ´Àýrµ8žL&1M3ð’`š&mmmˆt:M>Ÿ¼)€ÿËs,Ïtô™okk£T*aÛvàvº£££Ïv©/ÑNYÉ>bÝW~—¶B,†å«•®œ¯­­D"¸Á—ríÒét»»/¢ý¹jáp Ëeɇ,ÆRôϱSNášóÏ×s:#OB¡PŒÒ·m›×¾ôˆ_\L8Î2 LÇÿññàÁy\pÁ×;û Ÿ£F“ÕyQ(Çž={XÒÓƒ!£ƒïZ4?i;D‹7ÐÉ€<«w‹Å"…B!¬¶¶¶VX!Œ%ÊM™B12DÛÛ¹s'0§ž:ÇãŽ{ŠRi7Üp”ÿûùüC«0 ƒ9…9ÌùÇ9üˇþ…ï‹ã:üñü?†¥øíLY\43´â³EH m|W¼¾å[‚A ã"f³ÙÀºººÍ &%m÷«k®á¡óââ_ŒžÕYù+YöŽeËÓßy#wM™²«ÙP€L*ƒ§{üÓžâ¶ßÆÜ/ÏåÊK¯äÑo?йÙäùŸ'ñg V‚¿8úìùñ½öQ²G³\{òµ¼}ãÛyçîwòÚ?¼–/òE–¿u9—™ ŸÏãÆËÖìš_™„oIT,1^6 „oa”Ëð–ä[K‚ë‹©LŠ?Îÿ1©5~î½÷^ýò£h ß2lû7°òš•$$ϹϱÑÙÈ—·|™Žÿð]rã•ï è._Ø,¾ f±-Æ}ÕÊ÷W ~õ–_q §Ôûñšˆ¥®Ä[—¤2/ÃÉd2pw,‹ŽjM”çr¹ Ñ Ñßã2™_-À …`[Tü¨.·kš¦"ƒˆzù|>[$Vn[›¿è T*õZœ‘N§!S^€ÖÖÖpñCùœQq8ŸÏ÷²H•¸¼Q«)Çq××PiA%_QÑEÒ, ¾»íò1º®eL§Óâª'厺€L§ÓAüNÇqX¼xq`í(‹á¤šËåÈçó<ñÄõ¾E`Ûv…µªxPO"þ‰Ð-qX…¨Ð%÷¹#ÇÉó$ÿ‹•µxDû]ÒQ+* B¸°Âqb±XËZžK¹—!|î;::ëo×åXeႤ­­­AžÀ_¤ÐÕÕÕ«½L&“ضœCÆe"ʳ&eK`ÙWDƨ'›¨ËyÙ_Ê/×Fò)â¿\ƒ¨—c% GTH”¶Ì², …B ®ãåúÙŠŸyÿïò÷x/4½àý÷•ÿ”Ý+DÊX(—¯ü}ï¥{=ÏûÁ‚wx‡µOxž÷¹7Îû÷9ÿîyxÞ«ïôöýÏ>Ï£ÛÛúÏxO®~ÒÛ»d¯÷à­úùÑ=ï…/¼àmû€wøÄž§yÞgßé¥R)¯»»;ø‹ÒÕÕÕk[”T*åuttD÷LÓô2™Œ—J¥<ÓA¬»ÛóJ%ÿ³|nMÓ¼\.7¸ãÍrýåïz¹î½á?ÎXô…LÓôðe`Ï0Œà~SŒ>©TÊ+ ^<÷R©TPçÝÝÝž®ë^©Tò2™Lð=Jww·GÛ…T*åår¹`[WW——Éd*žý®®./•Jyº®{]]]ý8ù>×=‘He­.Ó@ …šuÍçT4R_¨££#¸Ï¥) àéºî^*• ž MÓ¼x<ì«išgFÅöT*å%‰à~* žiš^<÷<ÏóJ¥’§iš§ëº§išçy^pŒçyž¦i}Þ‹…B!xR©Tð]×uÏ0Œ ÝÝÝžišÏX”D"äUÚUÀ‹Çãžiš^.— òëy~;lFðlÊûWÓ´Šãä–ïÑz”}åÜÑvðLÓô‰„§iZEºÑ¶_Ò’ò&‰àøR©¼/äºÈŸ¤“Éd<Ó4ƒòȵ“ë®išW(zÕçymR&“ñ4M ú š¦÷GGGGpœäçÌ3Ïô>÷¹ÏÕûvw¤/Tò<ŽŽ!·±#Aºö ÅDb*ö *w‡Ûÿ}ο{wœqÈÏ󖛞ž÷ ¿ÝÏËåŸiz^"áÿ¥Rþ…®¾ð©”çe2žûߣtuUþnš¾:]&•Jy_¼æ¯¤ë^ TG&HýkY>¶PӨ΃¦UÔ£U<ÏóUq]÷•Ï(?éðÓÉdüüFˉ,<¦-í>ÁPéêêòr¹\0, ã‹LÔ{^夻iš½&¥6RÆ{á˜ô%«ÃáR}ŸNÅñA=ûBÕ‹Y<Ï îUäš‹h%[.—ó4MóLÓôt]÷âñx/q9*‚—J¥àX¹wD“ç¦/D¼“ýDÈ«%^†R©T±X` º»»+„EÏ ÅÅZó8]]]ÐhFP?]]]H'âkôx åI£££#XŒqu]÷ …‚§ëz ÄÊ5‘O„Æè¸P„Ǩ°) DÌ”í"V¿gD8Œ —’¶”C®QT•cäxù?“É ,Î=÷\ïøÀ¨ßï£ÁxŒRž?70žcu%<*&"S±OÐW¹K^¸6ÏóŒç<¯›nï«ùƒ/<®*G …`Î@>§Oÿ™ÞôéO{#YƒªPÔƒÑè'ËÕjKK 7ÝtÓ¨Z^ÞrË-lÙ²…Ïþó455ÑÞÞÎ-·ÜÂwÜÁUW]ÀÚµkY¿~=kÖ¬¡¥¥…µk×rË-·p÷Ýwû¼Ã @®P(FŸz´–e®séé§ûnç`„^OŽ‘aär¹ &J.— Ü©vG¡è›zõ úCÓàâËÁ¶aÿþWÀœÃò®ŸúÔGñþí þúÿý gmä¾øøú÷¾Î‚o/ øeÈü¸ypºÁù蟅â"Èt£û0%¦ª˜å=6×ðݯ‚_ÖŠd(Uþ+ýLýƒ =9ß%«I¿Òp±Ï„Í;øŒþßašÇ\  ìq`Ž'éЪûn¦mà—6\lÀç“М†BW˜[ðñ,t8Ø¢Á{\?”Ïÿ~“ß^{¯½íÿðݹæ=GßéïÇE¸Ø©Ãÿá )8)ŸºÊåM& «Ãº<JÁ’r<ªb¹üZ ’œjÁ>æ;aÞ /ðŸô0¯IÀêÏ=ÅqÕ1Ì °,ÿ;Žÿ=êzLt8Ôj»%^’aøÇF\*êºÎåÿöoØÀ/>ùIÞð¶·…AA…xÜO?öÓˆ¸Å+'¥’ÿ›ÄøÓ4e÷pÅb‘ozšãð~Óô÷«>Ç]yÿ^ÑuÿÏqü²Opj Æ»¨&ŸÏ“L&7ƒâV]1þÄãñ .\uL;qe4âiULîþ‰£qŸ%  €‰Ù'.§Ï²¬À¯¸ÂL$A,Àb±ØËݰ¸m‚}$^r­ø~rJA4ʺ¶44¶}mš¿a»ã½lLÿ=S~]pųٿÿ\æÎ=À’%õ®=…¢Ô[=õ<ÅÂ9çœÓk•Âu×]çÝ|óÍÁÿo}ë[+”Ö§Ÿ~ºæqÕÔZÉ-†²’p²!^Ϧ¢Å£¸—•U)ŠÞLÄÕKcÝôUîR©äáùÏŒïyxù/EVFÊ*RY+®À+‹ì7†çuµÄ½»-ò<Ïóìæfïg+V úÚQ ‡±hÿÅ:‚²ÕƒX] …‰jñ8˜¶`´ûƒ¡««+péÇ{YÍ(êC_Ö)µ®¸9l4Ä]öX á§âø`¬ûBâº×óB+E"VsbE'n.£.S"j-7äœÃ±X§Ã}ŽäÝ8ܼÖåpµ¨ ×!z|Ô…lç•çP\ÏTÑŠEì;pt瓟$ýïøË&-«"o.@GtuU‚‘·ž\nø–r¹üªƒã^y’?¿çÏý¥æ§O&ã[¾}I -!å÷(Ïeà®ý¥ 0€ÑŒ¦i|ü‘W¶~{«ã¿¬K’§rzZù¯ú”Zd¿¨‘¯… Žü¦¦i’J¥‚wÂh“ËåÈd2 J¥Åb‘t:=®e+j Ƴˆ’Ífq‡Å‹S,Éd25­ãK_V[µž;«ª-m¤ŒS©/9ÑúaYV`Í¡UôâÅ‹I&“d2:::èîî¬ÝJ¥¦iR*•‚wÆ@ˆ%Üpç2 Ã,)‡SN±Þ’çá?ØãıVÙ£ùïYŠõcÔ r ú‹æ¡VúCyhš”½ú³:º®“H$Ðu½â·Áæ{¢1^mÁ¾}ûBO …bBQ¯>¼ÕòçŸxŽýÓ÷sÈ“ÀÊÚþxÚu1ÊÃo€ãŽ;›ë®;Móž„ÒƒB1 ÃrµeýúõÌž=›«®ºŠõë׳aÆšû­[·®Ï4–.]Úë÷žžî¿ÿ~V¯^ ÀÞ½{*€Ù³gÓÙÙÙo=Êïÿ{fϞݫŠ &+J|SÛ·ogûöíìß¿¿ÞYéÅX·û÷ï§½½––ZZZøù³Ïú?:ø® ‡9W5ŽãŸù|ž’ô:Š D{{;¿ÿýï9ZÞ'ãÕ'¨u|-ö3/>ÏÍâÀ¢ã±›\|à6›ðçºËú½~žv<0ç9ÿçÖÃhÿöoðæOb¿ð ô³ß€Ø[¶À߈æºßóž@C³.ĹóN¬ßþë”S‚õ¶·QrUm‰ïmT<¢ ƒŒa k(ÌòvùŽÄaš6­.×µ.åqØú—yî…Yu)³0Ö¢TÔ_&“!›Íêœ===lÙ²…{E‹ÕµŽj1P[0Ò>ÁáÇioo¯9>¨…ëºd³ÙàÝî8Έ&Þã‡ã8½¶5Ú¤{”Ѿç:;;Ù»w/‡®wÑz1ãƒ;vÐÞÞβeËhjjV>-ËÂ(»¿Öu=µÐÝÝM6›%WO†aàºn ~ɘa°ïŒ‘†mÐ4mDiŒ´ý‹ŠhCEމèjW‰K†a ˜GRwÕçj[$û¦îR©TŸó]µò¯Æ¿gÛÒ¥¡[{…b ¢æ {ÏV/EppX~ÂrþõXyÃÖ­°ü4Ð4lb1]ðÎßaÿþ×òæ7+ÑQÑxtvvŽJŸ`Ø===\ýõÜvÛmÁªíÛ·ÓÞÞÎÒ¥K_Ë{÷îr<È 6pýõ×ÓÒÒ2*±'Ž9Bggg¯Õ ôêp*“yF8Pï¬ Èh· ½½íÛ·Ûö47Ó¼i¤©ŒŸ6 d`' ¯C¡˜h´··ÓÙÙÉ‘#Gê•«>Á`ã×ìºð,~¸ó ›6mò7hðÞ9ÓøŠ¡ñü¢™Øï{½¿‹ý»ßa77£íßU À^µ gõj⮋}úé~GüÁŒS~¬SN©ÜH¨Æbù/VÞ.ÿƒž¶Ùž®±ðÈ©4èÑ çÏßÍ,`kS‡æÏ¯w®Æ”x<Žã8ƒêßîÝ»—ööv~þóŸ³cÇŽzg}@F»-áq°«ŸÓé4–e‘Éd0M“D"¡,„ZïJ0Ù²e íííRx¬f,Æ"<ÊdåpÈçóÄb1,Ë¢X,2mÚ4’É$¦i1`«…žh Áá0Ã9·œOb—áž_ŽÉ«–p8!Ô0ŒºyÍÊ}#"xõñ}ÕtòâìÙ,_¾¼ÞÅS(ꆚ3ì=gÅ^½áÕÌ?4ŸÔ#Eýøm¾²X û_W®œÁ 7œ¥DGEC²eË–Qé ÛâñÖ[oeûöí\…5kÖ¾:zà 7&ϱ}ûvn»í6ÚÛ۹馛H$Ã^uåÔSOåÊ+¯ìÓ²A <S…•+W²råÊA­ô©cÕÌ;7hŸ„½§ÆE/óg÷ãCKÏqœÀE‘mÛÁ§mÛ½y ÅDbÍš5´··Z|«õêTsì¢ÙìúÏgù~ñ|°¡È[8~ñË\ñâï)q!Ö ¢ö²eè¯}-‰3Èú‡PÚ¦O§t Èâ{]Œß‰•bT2²ñ-|Ò’ø‚¢üŸì[,§•ì“)§Aœa[u7*Ñɵ¯}6©k®áüzgjŒËÇ)‹½&%E|‘:iiiáòË/à’K.©wÖûd¬Ú‚9sæôêÔÂu]’É$Åb‘ŽŽŽ[)ÆÓ4{ ñj©*BÇh/j+©:>¸ôÒKÕT#îF¥ÍÕ4D"ˆétº_qJîÁá¶)ržábƈÜ[–5(—°ý•¸ù×4mDŸX›—Ѱnþeì9غ«µ__yWãƒ+ùpêþ0îåRæЉ‚š3œÛgŸÀÁë{Þ7uL»Á9ýlâ7•Ï­ëA$ð &ch7ÅÔ`õêÕ´´´Œ¸O0,‹ÇíÛ·³aÉD/Ñ1ÊÒ¥KY³f ·Þzë€ivvvrýõ×ÓÔÔ„eY¬Y³¦fÃQ«ñŒ{¤ZȪÎ1xfÇ&Ù¡àŒ< …bܨG;°sÁf<<,7«Q«qeãºîˆá …¢>mA]2‹?:òÿ ^~ß}:ùü},?í>âewjE|mÏ=é$¬3оø'¡ )Ï”ÿd»„˜üw¸Uþ]¬s„ÆÙq  _ð”ï.¾È)V¾•d È×hãÔDÇä#“ÍfÉf³ÁĪmÛ´¶¶öŠÿhYK–,©w–ûd0mÁX·–eaÛ¶˜jW«j£EÓ‘0ÑúB>ŸÇqŠÅb`YljÇ㘦IGGÇ€ƒ‰+8ÐñÃEÓ´YF’÷‘ž{¤ÂãHH$#}k¹JÞG’ÿ‘¾õf¬Û‚}'øvÓ' ‹I…BáSÏ> °Ö¼´†§V?€³»)ôÎ㺠M|£.tS(F“a ®Žì«¯¾šžžžÒ[n¹…«¯¾š;î¸#ð£E,ªÝ!‰ïå¡â;wî¬ýãPÇ¢Ñýe6°Hh‚àF¶;pà?qb¢ô·âÐ¶í –L­Á² |z7äšQ(êÇx·O}6×}ÿÕUþ‡mÛÁs‹ÅH$+6…B1|êÑDÉS~mËëö°ÇÏ\ ÀòÅ$/°Ñ€ž¥sp?ñ ôgŸ%¾k¾Ð— \™Àõò§F{Y¦Ü2åm&ÐÙ^Œüž‹¤ÝQÞf–·ð…G½ü/§¯Ú/ß/+L)«tW¢d#Å~ö+úê. u:m,[ÌYÏ=Ç’²ç©Ò6Çãqr¹ù|>èk¦Ói4M#ŸÏWX9ŽÃYgUï,÷ImÁX·Ùl6X­¬DÇÆ¥ÖI­@oêÝ'¨FÜ©‹EÇÁ²¬ Áq( &®à@Ç„á PrÞ‘X#Œ‰[½‘Š®õîF*<6êDøX·|r½‹¨P( ž}8ôè!þ¶çfæ-ØAüX}þ¡àwÇõc<Ú¶ß÷Tc…b˜®VED¬^U°zõê^®ËdŸÎÎÎ>Ýš‰ÿä•+Wö(gÏž¬JX½z5ëׯçꫯ¦©©‰;3¦¦&®¾úê!—ÁN£N[Pêã écÊŒ¢‹oFÐ?CØVþž/ïãÌêÝýÑ»¹ró•œ|ßÉü"󋊉ŸGÞÿsí¹ðhíüŠû×uÑ4Õ´šßþö·œuáY†A±X¬°´r]4ÍŸü{ ¸ ÖQ߉ÌÎlÖ*_¨б¢í€LC½ÿ»óà›CϳëºÁdV©T"ŸÏ“H$FÍ¿¼B1©G[PM‘ò+ó§Àõ°{ÙæþdĦåK¹Å>Â¥;^â¡'Pœ1ƒÔ»ÞEfî\Šø¯ÑqÁÿ(ÿV¨q>9BkHq“*S˜‰ÈwÐz2jEõ!|­ËqÒ%±ñžRùˆ®Ó¨¤-«KhEÛ‰D×u±Õ¶m …Åb1pÿgÛ6Åb‘|àcX‚á3˜¶`,ÛÛ¶ÁVÅrl\jõFbmTo¦Ú8l"ô ªI&“Á˜X¼ÄãCŒ×Pf¤Võò²2RW§z‰‡¦iöZ€>TF*ºÖ[8ãÕÌ~ÛÇ™±eïüå;ùå)¿ä}]ïÃÁavz6',8ØŽï¾ôÝh 5Þpà üïÿËÏNø·=rxžŸ¯ &¥ù^Æcš3ÍŸ%ÓÓA7u}ö³:g‘ΧÉèö^²—g¿ÈÚ«ÖòÕ?|µ²Î\ÿØŠ™Í:‰‡d´*³Ã®_÷˜Uù·ƒoIÂFÕ±¡K´üƒ™”¹ê}sì$¢í€¼ê±§™uøÕCŽï(˜¦I±X$ŸÏcFÊzS¯>AiêŸ8‰—µãxÓ«zxå‰íl9»…ÃÞ Þ°ÎÃ… Öòz(Q{"¡¯¢zŠC§·×‚¡¾ªÏŸÂïÊÈom‘òf ݹÊt–Ù'OøŠ+wspÊ¿Ç …J3²OªüéR)lÚ„¨¬á’õZ÷R¶‰Ø˜/×išP4•¶rþ|ùøð“U«èX²„¯oJ$øÕ´i¬*çÛ$ts+u+o—Ø›b5½7¢íbB‘U„X½œÏèý u˜.çK/—UÜíJDÄZq»[$ˆóåc¥îªï1)·”éÌ7¾»ìnÕuÝÀ=ÛâÅ‹±m›D"AGG?ýéO‡xgƒi Ʋˆ.úSïöÆEÆzÑÅ“,<Ǫ®‘™}‚(⺫« ˲H&“ÀðáF€&CÞ'õ²mT œñj æíØ1îe“é$…BÑ?¡Opôù£è/ë°é[Ø 3¸{Á²À4}áѲ`þüC‹Ee P0LáqÙ²e¬_¿~À@ìëׯèפyÍš5ƒ èÞÔÔÄÝwß46Ë–-QÃ1oË^”dvKüš‰$3^ÉòÿNd»Ì’@sù¸þløÛ?0÷ž¹`Âã?ä_?õ¯¬è\µÀ⯷ý5Ó»¦3í¸i,pðß—ý7/_ù2‡;Ä 3^àCÚ‡øâ7¾È]ÿs+ö¯àÜWÎ¥ëÚ.Ž>v”7Íy÷]x¯ýëÙùÝlyb Û{¶óÚÿ~-¿žýknuoåí—¾ëwz<9o|²¹,‰®Ùl–”™â†“o w$‡ûe—í xlácœ?bºH,ã¸cÇqô/2ÿ¾ùpf3›öUíüÓSÿÓà;~‡÷½í}<ø»yó/ÞÌ´=Ó8ò¡#ÌøÆ ¿n ~]öü´‡YÏÍâ¥^bÖ³ ¯¼ø ÷ßx?×Ì»†žÍ=þ54à¡gâ¬ûÎB7uH•¶hÚÝIJG—qÒ‚“xôCòªÿy§/9ðÃ/ÿsÎ9‡%Ç/ž[úó¿?^v¶¬çívöæDDÌú—“æüYÀ$a€¬èõ†Ð4DÌQ¢³Â©òñE*gMñuWŒ|OVÝ”¥ò¶hÀ.A+ÿž-çGLR¬ªsˆµ®ÜŸvùX1]ÉCܦÊ6†Ô£°Í…îåÝ4ñà±m›l6KGG©TjJM)cE½úQl@;Í·øAýÕ–ñò¾þeƒ\ÕqB!h4¦ãdÍËhaà¿>Äb2Yþ¡,újÑLD±L”áS6²]¾ -Å „IèâU^ÇR^™ B«JY%ßå5iâ {Zy»Ä³4ËßÅPÒ‘Wû]7ÞÈÅßÿ>Åãl2Í@´,Šš&á«R„Q"ŸåõY²~+°n•sŠ(‹l—²eÊ¿¥©|µ‹X™#heûâòwY7–/—:Ð ã{É·FßsÎÊ•ì){ÅhúîwIjð×­ã³ÎB3 4˜°Âã`Ú‚±lŠÅ"™L˲¦œ•ÙdC×u/^\aéÓ¨“ïSÍúv"ô „|>O:&—Ë¡ë:‰D"õ~.š¦©vq„Ô³þñ~¶àñSNáPÙ=½‘>zÊЉÐ'¸àW‡˜õÒRØjÙÇÈd¦C>ï Žgœñ0–eÈ#‚B1Y–ðØÔÔÄM7ÝÄwÞIKKKŸ±ׯ_ÏwÞÉêÕ«G5¾B_.[‡ƒaá2r&Lf”d&Mf”ø3>™òö4¾Xå.I×ýA‰®ë<|ða.ûõeüä¿~‚븼÷3ï VOÿÉB*•âüyçspÆAÎÜv&ÉÄw}uÄæÞ¦{É}5ÇÞ§ö²í ÛØ¼y3ßúÁ·0Sf°b÷”{NawënVülËåÜñÍ;xûß68|€cO?óÎCûƒ‹BbûèºÎ–[øÒ¼/…n>}³ŽnêäsyÌ›\ðÍ ¸åð-üð?䙟aýÖóü?=ÏÓ_š¯ƒ+·^ÉE÷_ij–·óíü}ëßó™ï}†½ìå¯ÞýW\³ãÖ/ZÏ’?YÂÍ_º™7ß÷f®ºâ*öíÛÇô»¦s¤çë^YÇœ9sÐÿWgÝ9ëø?ÿ}å1²"ýã4¯Ì~…ÛÜNkO+ëÿ}=|îƒÌxtÿ»õùØÿ|Œ3f°cÎÍáë_ù:m­mÜup7ð_x| x#þŒ¢X,š„3ˆ©òuËÅ.B‹E™]ŒöËe_-#ª}dVUöש´ª4"ù(š‡H:ñHúÝ‘íÅrZ2»)3·Q«H»|FgPHzøû8ñÀ¨=Cõb´Ú½¿ú ;®1-<ŠÛµT*E*•Â0 ÚÚÚêæêH¡˜êŒfŸ ‚çáØ©ÇÀ@×òã˜}ê,ZO­›Ô¨ø8ÚkÿeíËh§ÒU«ˆââTGù·¦)|QM,ýDŒ¾j¤Ë”(ÿ‰™-ÿåÊÇ[Tºt•ãd]ˆ§Ò&Œ›)ùÑËûð_{þ+AÔÞdÁŽ“xìÚÝœ·I‡çŸ'^€eaøõWgóŽwtø!Њ)ΰ„GðýÊwvvrÛm·±aÖ.]<Ôííí´··ÓÙÙÉÒ¥Kµ"a¼qî­[Y4mZ¸Ô*ƒ+¥}`‰ß*™Q“Þ€^þËåZ莬>ð†|Ïýû ÃÀ¶mR©º®Þ/û˘¦‰ëº$ Ç¡T*aYkíµüø?Œ¦ittt¾°©iG£œaœäû–ÏÞ|ŸïÌgæqÇð›ß} ð'Q:::Èf³d2ÚÚÚÈår•–ÄüÉf³¤R)bVŒv|k´kp]—¿ºó¯x÷Iïæ‘óáó^Ÿ}=…ŽÙl–ú¯"‹Q*•‚ýÜÀçòŸ£ÔQ"›Íòµ§¾†¦iÄÿ%Îüä|r¹–eÑN;sµ¹ì|ßÎ Q!^ N“¸9ÁßZK⃠,Ƕm´ã5ºŸè®ˆðã ¬ˆ¯àGñõ}ˆ@îÕûŠŽ£&%zmQŒþ¯u\40W4zäS¾W/d–ôev°ZßÒªöa2Sc_€Üwã}Ä'Ítãð±GVpÂ>oÐÇèºN>Ÿ÷Ÿ‘XŒx<Ž®ëÊÚQ¡˜dX `á;¶³œ=ìúÕiì9í,æí€S¾Ÿ{3èóÇöüc5aèã{¡íQa5êÚ3úª’×”Vµ=Ù׉¤¯±ô85%mI?úªLDÒË•ÓÇu)hZ òuël›O]v°_ÓøÌ±c|¿O¤ë:¥>&N;"ßEx5¨|Åç€Å¯{›~üc¶Ì˜Áæû7…ã8ØŽCÂ49éÑGùÛóÏÇ!5£kšÄíj&r®êrKÌËêí}Ù=Eë(ÿ¶·ñà=÷0çèÑ`­R ߢR\Ì^8s&ŠJŠÅ"ñx\M¬O"&CL:E}H§Ó‹E …B/ËÓ4'_;!+Zd1­Ì}@ަyO3ËÍåáþQÏPºQų)&¿"sCcüY1¦4mÝ:îÖ¨~_Ï |”dúQúâ9C›5.æ‹ÞrѲ80Aè©#SNǬ:¿YÞ7ê}#êá#ºM¡˜ÊÌ<6“3_<ÞÇx` ޾×õc;JHÇoÜŧ?ýmeœ P0ᱩ©‰uëÖqçw²~ýzÚÛÛ¹óÎ;ƒß[ZZ¸é¦›&¤èþKu9eßú²Ä>* „3:2³%KákͺÅ!ß–'ã8–eñð8q1…p'ûº»»ý<Øvs'tV\·‹Åš+$³òZ×uº7m‚E‹Øºu+m¦Ä ³,+ˆë]¡Y(øÓކa ë:Á@JÓ4 …¦i’H$p]7°¢´mÃ0H$Á€^eјB…B!%5M#“ÉljÇãA95M«Љug.— âì¤R© _™L¦×`¯uAkøOsùBO%r#Ob*ñûD^ý¶¹ƒÞ_î_€ŽŽŠEß?³r7¤P46bÕ}Ãn?´‹Çö\ÄAûdÒl—¿’ñc,:BØÕíiò¾ZªÁL$ v²AD›(…A; ÀÎçIÛ6¹\øÔ€W9ÌœIÞ0h²í`)j6›E×u2™L B:ŽC2™ Ükš¦‰eY¤âñ`Ñ—ô‘ÇÁ4M Ãà‰_ÿšÏ¦Óü¼ü>Ÿb(æóy<Ïócdº.Ùr_Ìu]tÝ_¬æ8ɲ%}­wIµó…¡ÔË)ÇŽ±?— \ÖJWV¬(³À>òÎÿýïÇð 5®ëR,ÕdB¡|ÏA©Tª¦»´1u9Zù€J/6"ðE_ÊE*}—Gͤ¢/q S ²(¶9ŸAÚ|•¢@è×<ÿÆÇ9‘På(àw¤Àw? fû¢pØTº$ ÆâÑ'AÀX\3X„~ÆÅ­‚b–€ÇR7ºZuÅ¢ÒLEV5¥#çÿìâH\.H(q !Š‹ø?·N$Íbä»xZ’€ÌIïZfÑ$NœU¿\ú¼—|ÈJ£h¾Ýry¤~;CÆ@8o%/ú\äzŠ Q›Ê æ+Ü'ˆ§ò}µðßÒþÚÈBî)ľüéÑñ׋GŒjª×¬Ëm%Q„Š„‹8pï%r»HhÊi‰Ue1’–Ä\—Nä\ µívä˜8a´ª8•^DÄ:SB-H uYÛP¤rJ5ªÝC¥c¯¨mÖjMäÒ^ÿY¡èS8…¦‡5ñŸÞC¼p%ù<¸®ÿ§ipöÙg“H¼¦ÞYU(&Ã…›nº‰›nº‰íÛ·³}ûvÀGÓµêXqöƒ{‰]_v[ýFêk†¬FDÄb±Ä|(‹.eÀ"¢#„ŸLd9ŽS!@FWåÇDû•w½‹kn¾™oe³Á YÄÁþ:S"FV zÑüˆ et²/º_t]m=ûZ)*“>}ý^kûɧœìÙŒnhIÃ~ô£@0žÊXÀ"÷לüæÕƒ>Fðb±H2™¤P((ÑQ¡˜D8ÏeaqgËLf:8˜÷…Çe `*j"ÂUSK`H&“ƒ¶)‹Ø¶Ä-“wS6›íµØ|ËûOöq‡X,ô½ŠÅ"d2 l›Öd’\.ä;ŸÏ“L&ƒ_¦i‹Å‚E`"F‚?­‹t:M*• <ÎwÕÄÄq/^Œ®ë*&‹B¡Íöe-«ëúàÇb–$fEÕIŠ$*‚ˆrñÈoÒ,‰¸(æLQ‹DÙ ó!Á–ÅÌ^fæmüB!’Ǩ>„j@ÄA̶Ƕq^×y¡K­ò÷ ·’n®*Í<¡Ðõ$%ù——•NŸçRQåÃì_Œ¤'ž€D8ÁÑ" ˆ,õ'¡v‘k#iI~D”ÍRym(׃¸GÈ ‚QU©¬åÈÁv`¡ šEaÌrJ¹­òÿb=‡¨:q*Ë.jU’P´ßûâD*sï™Ë¹ÓÎe*òìÌ™žÀý¡j²¿Å‰âeCš0vºhþ"Rº„z¹ÜÒ²N D8U*áâ„ú¶hçcú¼ùdÿQO&‚K£¨µ_”t:Ý«ï"Öƒ‚x.ˆbÛv 0:ŽXýÅãqÚÚÚH$Á¢.q¿nÅb]×q]7éd1H>Ÿ'‘HL&+DÀR©D,£JѱB‚þZWWW»W×õŠ…9…B!ð𠖊ѾI<Dz¬À-g´.âñ8Ùl–X,ˆ‘}y­p]—æææ@D•zÉår8Žƒ¦i¾ûùD˲‚úWýà÷G ù¶msÒ‘#d®¹&øßuÝÀÅ¿¦i$€£¥,Ÿjî!j#÷oWWW½³¢P(&²¸¥¯ñsÍߊ„Á!œ|l™¯öß éâ M:¡ ˆi2‹Ÿ¡rF½/J ŽZŽE?ï{ç ­"Å—£0„¾†©Qµ¥4Äc*óøÖ™R¾ŽûʹD¸¡6F%º_u©ñ{šóÍ”rU“ÒÕ–©ý•+Qcßè9jÝ"&[‘ßŧg$ð÷ïšÇãO=ÎÛy;SS_z‰ííþ˜½Á‰Þ.¹ߣ·VµhüÕ’4OR;b ,i‰¡±XMZUç‘PÖ>ˆ™! Ë`E~ëHY› ÍlãdEì,•ó&ôhcZ¦"yߘ;Gåš½œ¾Ä˜Ÿj².*EP›w1”Ž'Œ?5hŽ^ƒhŒwyœe‰œKÄ×¶ò>ÑWF:’×D_ZÕù¥nDä•(dðâ¢E(BD$~D{º-Ð*çù- Z[Áó|Ï|j¾U¡ð5᱑Rœ8‡f¶kJ×uƒ‰!]×Éf³$ à N®WÄ­è`Moª6tó—û¦*›Ü̱ó–Óë¥ …LøNudÙ›Ý Ü×qœ ·È¦iRH$ÈnÚä ‰âW¡£#Œ( ÐÖæ‹’šæ/ª^ñÔÜìgþ>†á/“ 2iùºî€FÚ>XVxAüA( Ÿ}Ðtägl}ŒGÌ 9åÈ>ÚÚÀ5¡ºx\Aãx¾É³Ù¬/FU‰cQ¡B/ ‰DMÓhnn&“ÉN§ƒ¸·bµ×ÖÖF<,‹Åb J*•Jn«»ºº¡³T*ÖˆâÚT,)£ äMD5É.—c˽÷’L×…|½T âlK».HzÕý§j‚ôíÄD-¢nèê—UÇ+L‰¡-B-°â26N–”b•/çÕ®¹†ÖÖÖ@ДkœH$Hk'ðêþñFyƒP(Qú²øzy²ñÍid=O83+ÿV t)®Ee¹¿õ‰Q-$ðW1tÄ„i°ëA¥[ÔJo7·F­Û9R‡Ï< OÕ;“õáó?ÎOòùI!<Ž”¾š—êš©^N'·—^ã·hºÒ„E›=YSQmQ½C§VÇ•¯E†P˜ëȾ_ñD\è£ìVäS ™£†Ð.¡æhúNù·$~|u1^cu1NïÉbY% "¿Ù„§Ñº‹¼‹ñ¼Fhå­{IC,0Å’RÄ×ßö6½ùêׯ÷¿è:žéth‡à8¡×TÈ…ÂgÊ :ÌbÖßÍ‚3©ýV%va&“!›Í’ÉdW«“.Ø| /ñ?Ÿ9ᦟypz½³4¡Ð43Ï<³ÞÙ˜\èå¹YÏ¡0ê<òå/³ø›ß䩲U‹ã8L‹ÅxðÖ[YõÎwú;ÙvokÆ®®Px¬Õtt„½˪Çñ+»úËø1r]_Ü £·À)‘®‹Eßò2•ª-+<®ûõUF:Ý[¼­.«ëömUê8~=FX/‰Dåþù|åþñxo¡¶Z¸×õÊ4ä±…¾Z¥j‹»á –в@JÄÀt:ˆiâFÕ²¬À5|±X¤­­-ðèH$X¼xq³YŽ“8‡º®ãyétšl6‹mÛ¤R©Š‰ZÃ0ˆÇãbg&“ ÄǾD½hH,éZœ¶w¯ïÁ̶ÉçNŸNË8 Kµ,EûÚ¯Úµ§l«eM)H½IŠ0)±·Åb4*€Šo”ð¨P(¢ˆåy_èè¡ëJqá)M¹ø¹®6-s’± ~¬èŸüTVãà_çQ2†—ÅDЉ‰šÃ?jwª ¤eÛHÓïkl%Þ†ôolý¬þÞ—5¨Ž†ê­þŒWß—´„¾­®Ÿèh"ê5Úè#­¨ðýýƯ~Ö­JuOnŽÓ¡{Fæ#€®3mš?µâºËùÓU0u€ŠZLIáÑ•…ÇáFv'pÕ•ÍæÑuߪñÄßÄ;,µ²¬p¾_1öÈËòM§¾‰#¿8áxÜP“>6 ¹ðÌÜgúØÁD¹×̚Šrò‹/óÅb±Ò’¹¯ÎE®U£‚U-1(*‰ÛÖZûˆhXëÚ&“¡Vm‘ ¾ V,†"[u~EÜ‘Ì0zïcYþù%íêߣâe_õâ8þñQ´Ö5‰þ&B«ÏG{{þ9ÄѾœ£Z$­®3Çé}þê:«.K<^)Öb«‘C_ç¨%pVçÕ²ük¥ú>J&GÇZv ¬®Ý;šf²àöÜr6o›ÃR³òÕ!–€À­ڋBÔht_˲üø‚‹AÙü¾ŒüÇÉd2AŒ;9>ŸÏǃ¸‰)± E+:­!廸F­ˆõG/1J>¾¯oݺÕœ7HXa°“_²ªVêW,ôc±¹\.¸dßÅ‹W\#…ˆã …B! `‚÷”¬õ²-ÛýÆŠNR ÑaȘáÍTƲ쇨SJ £÷«XT†yc… ¦âu¬§±¸«Û‹ï¯lzÕ§¢Ç€n`.0+ ïkT×Ãiª––cÁ_…Bá3%…G€‹¶ó¿äò@ÜTÅãqV¬¸]Oaši4-ÎÞ½ŒòM'†®®8Ù¬?¿œHøŸºîÏ Ë¸šßf?:›'Ïx2ø?gÊuÝÀef5"ÌÉdœ'ŸbmO5’‹¤'éˆTÉG4?Žãq®ÄâD\«ÅãñÀe]ùQ£ Ì{ò 8õ}ï¤ëÐÕÅ÷m›l6KA×)•JEϸRë|š6 } ` ,§Ö´þÃ8\Ik”.ÍC_£èÒH¥ü?Kŵ¬0k¿Ñ*Ë@¢É@ç1ŒÑ9Ow7Ša`Ã;/ÞÊÞ™oaŹþ@¢Ú¸t̳P,’ªzDH¬~O‹EŠÅ"ÝåëN§W¦š¦.TMÓ (yŸÉ„ªQ²MD)±œËçó®IEÄêèè¨)^EßCš¦Âc½xî¹ç$cuËÃxc¥R©×õKÔÖÖV%²EÈ–•ŒÆ„°B¡h|d|ø~ø²øc–Ð__œa‡m™èô¾X ×NÊ9Ãð×þézí¹ ×õ+ýß5Íß?— |D×8Ê?é çóþ_G9c[›¿Ÿ\žXÌïòʺ>Ãð×ÞI^'<¯¬—”r ázÁ¨Ûöó§ëàèa¼:9®­ÍO3÷óûçv?ÍX,\›‹ùC\ÎßW†ãѺõŸ2„‘H"ªF×qš¦_>™S’z…pYÓ)k$]ðÓ•ú§=òÛå—OÙ)BÅF\œ*µ°c0͘_1?&k¼M¾ó¶o·•ð¨PD˜’½ è>¶/ÿ]>a~bÈÇ‹›±b±È·¿}®"•Êá8ðÆ7Î <"Jç0Ÿïý=çÄežÜ²üŽ©ŸÅALõ*;aR‡w›Ó_5=Xq"nßdiÛv0©*¢_Ôµœ®ëAìÎT*|æóù î’išAü¿x<L¬Ê>âŽW,Fd8ê -º¯ÄÈÊår$“ÉÀÝœ¸‘aQ&ÅJ%*Rʤt˜X€Le\àÐqÏòÐ܇jï`ÁCh•'íÅ=]*•RV"™ Q“ÇŠa`_گ瞽ÄuZ894ž·“Äè«¶Ôu=èX–E&“A×õÀâ0ŸÏï °JŒÆû“xò”sHZÕBTÔ‚±ƒi Åej=ÛÍR©Äçêvöú‘N§q‡™­Ç1 ƒmÛ¶Õ;›‚t:Ýw¼ÎjÿSÕ¿I_”pðM–ËFøˆ{†0P$rD6ëÿÉ94ÍÏ“L"K}Åbåæ}:¸I¿l"Þ%“á<‹m‡¢ ë†-DˆL¥Â4eþ'Z'©Txí$O"6ÊÜP6æMÄ^q‚’ËùuT*ù鉈*ÃÚèý`~ž$m×õÓéé™;•ÖhUðì³ÏÖ; Š:¡f ýáNÃëlØÝ¼‘ßdm»ãÀe—Íçþ¡¤„G…"”]`ÎÓ¯ñ^3¤ãüUs¶íðá_O[[3¥Ò[qÿ7éTЏX*…ìL&\u&l “‹…"¤¬€“Ž¥–©TØ ŽÇýóiZèGZ×ýt³ÙÚL±˜îL&\}ûß;:Bo}ÒÍfÃÎi[[hœ“NW¥Rá±Òé—²IÇÝ0ÂtäXÛWJh3©·D"\µ'$©ù4ÍÊ{â±P]2Ày`ýÆâü‰Ö\.r2*“±" Ê®®ë†ŠÑíò™J¥«G*!ŒW%“¼¦iVLøš¦Yaå(“¾biÒÕÕU1‘–ïrŒ¤+e¦iÒÖÖ俎ã°ÿþº<{ §Œ­ Ê/O*•"™LV\…B1ùÐû XÍv‡“Aéô8¸ðŠ`ÛvàÕuÝ@ˆ”OðżŋWX»;ŽC.—#m–ëºÁ{.“ÉàºnÙ|¥åv|ŒýuÕÍŠÌ4™¬¨ÏÙëN&“Á¶k¯¼Õ4-¸Ï¦:âm¢æs ñÛd9¼xÉ6 …E©ÞþÌ¿Qþ¬¶üÑ#iX„b<ŠZ9M=òd’PÔsñFê$ IÛ.o×#ûèøÂ¥ ´Fò#~‹å<‰A¾¨Ñ´ÅÓx ˆU•-º-W.GÔɆY#lU¹Råú–ºl«ª PT$eEˆ•sE_‰¹'B¦XáÖ z¥ŽrÞò‘4Ò‘óÆËÛ’‘ãó„Â/„âo¶¼-UþnEÊŠäSò}ÏDÅa3ò]„^-’=’OƒPÄ!;]Uf9tå}´èÅE(|6ÿt3¸å6a1þ5F? Oåc½¬‰òÿ­„‡ÜÚÑËèRy o`Þxúà·ƒ™‡ {œ¿žx^¾flCå<Ÿ¿žx,€íWÂk ð«| þ­¿ÏƒÀ’ßÀ‰ÇCæì(7‡ÿ²]wtÁ^à–CpÞBàJ?—ËuåG¼+lfè‚K{àú¦pDÊóo½,`fBÑT§|güÛõ•×åÀùÀÎã¡ø øêõ`,xÞ³¾ù _7ì„ÃmY0æøÇýÏà?ž÷ðÀ.yd”¨aÇŽõ΂B¡˜¨ìÍ=T±©r½®Ã”¸ë®ä’U(&;SRxt€?ûå –^:øcÊ.@®¹æ º^àc»”óÏ_F&sŽŠƒñxo/QP¾Ë>²M¶Ëj> U&î1²ÙÐõ†¸ÊÕtÅbè¾D\“ÈŠ7MóW» ¡¨)e6®”¼‰(‚h&ã·í°lÉrg[DGéŒË CÃð;é™LØÎdBÐuCáP\„Øv(¬JYEÄÓuY… ÅMФ-«öÈ«à¼ç‘:÷Ú +‹èä§/«Ú…\”hܤê´d¢ªzŸêtªÅÀþ¬áZ†är¹À¢²/”Å£?àºxÓn6G×È’Ò*‹Ÿ¶¶¶À:U¹¥S(&Òb{Áš Øá„LàŒ7¶"?åE)ù|>°~×ÚòÞAI,]×%ŸÏÓÕå›bˆ5¿,–Ëz)ÇZhœhìÙ³‡˜iRyR EtñS5ÒÙ¼ys½³YwdA•ê@6\EÅœ¨Àm#j‰GÕôåÕDĬê8qÑýkµGÑ®I_ue–_èïáÁ.E¨†tDÒ’maƒõô-¦ˆ±ÑïROQqQòÚA¥xY­ÂDÅTjl‹ ¯R7ržhhGÎ[ÝÍ“¼ Å»¨X,iÅ#iQÞ׌ä_H9EÒ#ßk]3±ˆ5#Û„è½'n?£‚¶Ô{–P µ#¿ç"Ûpà×Pø8Y‡_5ý*¬Ï¯L1vµiå–“Kaµ‹—V¹,[_ýxÿ2=\{–ü5üêåryã`ÆÃuẒb9½DÊ?.W>¯|kÕEÄŸ|\ž3…B¡hôßC&}€Gßÿ&^[ÞfÛ•û¤Ó{êM…bÂ1å„GY¼ºkãwøÝ¹¯çlÎÔq²zlãÆ<ùäjN>ùFÞüæ/bÛ'®<†£UOhÊ< èUbÉ(ˆ{Ñ>Ä=«’G@\oDã.ˆ÷( -«·ë¸j‘´z²U¬&«ó+¿™f˜Ÿh>å÷(®ë¯Ðí­«ÊmXNV瑲8Ž¿0`ÅŠƒ¸Vë ,Ë ÜmGÛjÇqK´ŽŽ Ã\…†Q³1**EL±¢—v+›ÍbÛv LN5.\ÈË/¿\ïlL(Ä=ûé§Ÿ^ï¬ÔÀE½Xà™ø³°âZ1J´ï<ÚDkÇ C]L·Œiè}|ïk[Tì/o}å³/ѯֶÁ”µV>¢ÝÁ¨ð+ïƒ¾Òæ%Zn³ê³ú}…~.ÔH£¯|&]ø‚¯f+k®‹î{a•55è|¶“+N¸’ïò;nÔ›°ˆ‰ B­W´uo14ŠEØq |ò$8i è3üíVÃGgJ½ .MÀûLlœÉ€quÙâ­ÜdeÎÎ$>Çÿ[A_ïȆ?k¬¿¾ú ,ï³Ùß®1xwƒŸ8 >DxÀÌgaKy²Å0 ÇöÓû@y½kõ-ž/×ÏFWMð]Bá2h'—ݾº°L‡ÜêÚÞše}„S¾Ž`Ÿ¶ÂñKB!1ºÞÁÖüïy@Û …ÿç#¡ÐÜIW„hŨ9^þþÑ»à÷³àÈMá¹dý‡ˆ–à?¶b°¼ùJ?Ý,áºï×ðÎ| J††Ì3vÀÖ&øè×àG©´ M”¿KZ>K³!¯¿+^|‘³víÊU™TãéâD¡P4 ñ"Ì7FûG²O*ƨÅ@^φÚ犺xŒ'J±^ì‹>ÂI ˆ%‘ß#ȵ”2Kl±š”x b)V•b™uí*±$>ƒ®Q·²RwbñYmM½!u!b°ÄÜKV±æ”ëëP}½|w¾&…B¿ù›»yøácñâ>z„Y³Þ8\~ù‡¹çµ¢àŸÿë½ü!õ+ÿŸ¨Ïâ*’ÉdÍøX …brat=Bsêlþ/¦é/ØËñƒã8A¬`ùK§Ó$ âñx'|ë4Çq—ªƒ!ºX"•JMY‹íÙ³gsñÅî4>j1MˆmÛ|õá¯ú3»£c}ÈL-CdÅx &dŠAãº.§¾áS|õúƒœn„†Ïb…'Cè ¾€eP)ªÉ‚eMó‡ÑøOâÝG<ü|úÓ°i $rþx¯£Ã?޶ñ§„`©^ð }ëÕýñùðA`çN8w6Ð<¼zª~ƒÈ¸Zâ'J蔾æPß/?•š<„ñ«Ð=òYÂ4^3>:Çß.ݽh¹ª× ˜W„çz³†pMB´Ž=?Ê܇Á.×y-Có|¤nÄ21z]ðexôCpãÝ`^æ-öm°>{Zýý£i[„‚c9,g`|-k]äÕ×¾mí#¸6Τ뉙µB¡š ‹g,æQ ¶EçÔU8&…¢6SNx”ÕoMÛ®äŒçÎèw_ Xî8ðýïbïÞ§9ùäû0ÍjºâœhH,©ÖþÕ*o2q——ƒ¸²º³up—LúßÁD ¾KZ×õ¿Ë}!ís¹p€h¡à-%½ˆ‹ÕóŸÕÞ%æC4`½hc†áö‹%¾¥®Ãž=Oòõ¯ŒcÇ®ç™gáСïsÒI¯âŒ3žãÿñ[¼êUï©÷eª+Rõ»^yÌï XV8Ú¯B\NºAˆB¡¨À°{È\wÿöê·°bŃÆ*Z[ýöx´ß£²"RVEÆb1 ÃâúŠËÔ¨%¤aär¹ ưbðìÙ»7¥¦QäK7_ÊiÇ6xsŸ_<îweZ”tù®”Ž¢®ûAËŠÑ"GèîG1hì¼Íã&–y~5ŠXSÝDä(‡fM‡‹•ÅM{&†:‘Ç]Æ€¥R9”I ôr8(Yt,cÂZÞ‰F“§V꣗žŒuen<î“ÇcÚDÆßƒ}­Õ²îìo¤gD"• Ç&Î0üú9ñY‰'^›hu‰Õb´XïØ ¯] »¦öñ/¼ºw^)«EhÐ/¢TO`¸„±å"EUn—0ήø¶•¿bz ¡É¯Ämn£·)uô<â^|òFc‹Ù­˜àŠéu4°Ù?^>^â9wšËñN ŠohQèÅßpÔä7C¥›s«ü§Ò×rù¦Ûù¹Ì›7¯ìã¸|¼KèÎ\LƒãTš1‹ rq_^ý0ËC# wõÃ-yåêºÖ¶(Ræá2Òãõ! ò áÑ7ú®åmN¡PLQá §§‡SçŸZs±b“†$Ÿ˜Å—¿ã‘Gî៨çRè¡1=EÈ­è³߄üßUºt…Þq8! øîºáD³Ìišؽ¿ã£Ã|Þ?¾««ïóÖ„yž߉¸(ÇŠæ%yÑ´šº.Bå§YµÊÀêú…hš¸ \€mŸÁW¾òüžíÔÄ´°sçNNã4¿Bs¹šŒr— PL6æ>¦Él;möì äëh¼GmÛ&™L¢¢¦iøX(ÐuÃ0‚¸‹",V^äµbèœü‹_Pzè¡zgcB!.}ßýîw×;+uç ½_]ú+®æêÁ Áߣ«È …°Ãæ8~‡LVªišßQŒ>Ó´]LŸ …ʉ(ñ(®0Äl*š‡è_"Q™¾B‡p`Wî#+ædðSݶ8NåÀ¨– "n<äSÔ—h>$!êÖE~“n´ÌÕç‘`ñÕçqWŽ©Uù½¯r Ék­tDu‘µâLH}H£å¬~ñDݨT_s)Kt@!«*Å5ÊÿsÁ6BS&¹å³V§8–eñƒoþ+eóöýéfr¤mÿöL$ü!E6 ù¼_Ý]]áí ý߆r Çj³i«'ðýóF/M¹•äñ/=ã…4“ Ió;¯¶ˆ]³L„ºM4X >|yeys9XlÃ&£·ð(ˆV£Wý¯ðéåáHbàJ3¬Ä•u¡¼-Feã"¾è—Á튄q{£.»“TÆ)Ž^ü,BqΠ2ž¯?­/i¼|þ¨™kœðp"Çä …S ¸ÚFepСðØA(ZfÊi7ÆÄ‘3´–ë(Oèß׆;N óêZ_K~Ä]]+‘¸øæ¼R/v$Or,å¼§ÊûE¶xy[ÿÝØF¥é²ˆ±b-u "¥IèC9ƒ¯à›‘{D®©Ôk4RödùxñL¤Îs‘mf¹ÜN$BäZJ¾¤þä"ÿGý,›‘¼Êµ“à®Ñ:ìËl\A7M[?¦tá¥K«„G…¢6SNxttÎXÕÛâÑq,L3tÁùƒüÏO.×8ÂãTÆÑ`ÅÅðùCr…+sC0üš#YÙ3éë·¾0M_Ìf{ÏÉ*nñ8>|¸üÑ«²\×%ŸÏWÄOS(“w:0s.d2üþµŸâœs^]1ï;R4MÃ0Œ Vl¡P¾Û¶M>Ÿ§;ººE1êìß¿¿ÞY˜p˜¦I&“á›ßü&^xáÈlTl˜h>?zç*·KìgMó¼è„¤m‡~ýj5†á« ¶][DƒÐb_Èj5ìª],çó¡h)³üž×» ºÏ¨îÓD]|€?ð‰Š‚ù|(öI£m•ãÀâÅa™5-\='HÐùD"1«ó(n<¤¬¹\oAMʪëá*Áh>Å?¥P]±ª©øB¡rE`ss˜]÷‹ÖE6ëŸGêË0*ï × Óˆ^c)Gu]EW: ÅbèŸS×ýë­/Ë Åd1‡‹Ö“Ô¥äñÚX†?›‰”A•Løó²ÿ¯§‡E‰b>™³‡v¼èóšæ/h•ï"Hf¤:-¹ÔcÁ©/A£ï1“©lRÆkØ)aO&úœo>+ÞêQëúÈ=T]VË‚YKáµ51 Ó"iK¼RE ŠT®ÓŽSé;· _€Jã·¯â¯VÄG³|¼X–-£J²øýíë†èËŸrT ñ³VüäèÍÐßM'‚j$·Û÷g³YÒÉ4sœ9þyËiÚÃ0H§Ód:2a0Ò²Hêj~¬ùoüú—§r×uýã´ EŠdJ~A%þøŠý+¸g×=ÌuçÒkeÎ?ÎvÜÁýNÊáÈÎ#¼ô¾—xaà |ä®`Ûv0Þš{Þ\¾þ³¯£Bgþüù,_¾œ‡zˆ×œûÏ=ÎÊ-+Ù°yû¾¸?:íØ¿?M/7ñÈG8÷ÎåÀÇðÒÿ¾Dç¬ZµŠÃOf‘±ˆ_ìú‹¾¹ˆ­¹•ý÷íçÙÕÏrѱ‹8ï§çqüéÇóxóã<õѧ¸ óþá³ÿÀÿ}Ûÿ¥Çîaþ¡ù<üòì²Wñ7ó1“kZ¯á¿VÿógÎç—ÓÉÒ–òÌæg˜h>7odÖáY\vè2ÿÚlƒ7ì`Zó4Nøí ̹ië:Y9c%O¼òó/˜Ïo×ý=£óÜ¿=Ç‚# رp~ÿB?ýqNèt¦Ý;oèÛ¼ÿÞ÷óóC?g埭¤¥µ€Ý wsâ‰'âè3gÎäc?û¬½GªQ ^i4³‰K/½´Ï}•ð¨PôfJ ·lAg\Ôû7¯Š›Ëÿø),ëß™9%@4 «Vž×¬FAÓjÇU„8s¡“;Hé?¯¹O±X$›Íâºn`…¤P(&'öËÀI @‡ýû§sÉ%Çáy£¿¹X,"c4f#ø} 5HQÔ‹X,Æ’%KøÓ?ýÓzg¥~hð7§ÿ —/»<Ü&+Å/buÇ*¯íþ¢"]mdæ7­bËd*óUˇ¿ˆJ}‰K]]¡õœXòÕ:‡XòUS˽G5¥ý""í@û”J}×ç`:¾"DV~æ3j±X­˜ˆÛ‘D"¬³(šº.‘t¢u&u%ßk1P<ñD¢ÿû¢ú:[À=„ÊB.®LT–ó½°ŸÆ®ä„ãNà?úÚ§lÜ[}ûø^fz_rè?Îa_Èm:VžÕu`£oÔõ*=žk]Å€w"#÷ÆŠýðK'øE°)gu3¢ëðÊÀe}–åϨa–…«Ñ4-Th ø"ašÚ¦¡)B‹´ê £¾8 •Bcuס–ßß¡2@w¤ÚËu],Ë <°d2ˆC>²8%™LÒÑÑA6›õ½³¤ lÛÆ)ú‹'³Ùlð»¦iX¶EÂJÐÖÖFWJK,š€IDATW‹›S*•øä·?ÉÎ;±,‹xâoˆó̉ϰ™ÍÜíÜ €¹Üd·³›?|"gæÏä§K~Jr­_÷çïgUf¤á¼øydÜ OðDPÞ¿Oÿ=¹wçxøô‡Ñ4 ]×q]—?Éþ z“ޱÆUMÓĶmâñ8ÿºù_iÉ´psòf27ùi¤Ž¥p>êУ÷N§ƒú’45GãÈŽpœ}¿|þ—|*þ)2™ ÙlÓ4±, Ó4YÂzþ‹ÿý‡¬Ápª7ôñrËf³ ’M¡o¦¤ð8û‰¹¢é ~¢ÿ¤×o†ÆóK¥àÅŸÜ¢ÅãñʸJâ.G¨ˆK5¡¨PL(ÀÛéñAû£ú>&¬‰ÅbQ Ådg0‡òàÛeùò9£—Ȳ¬@t„p…o5Ê“ÂØ²©¹™%==õÎÆ„$—Ëñ¯ÿú¯õÎF}IÃÖÝ[¹^»>ܦë~ß ‘&†;Ëߟ« ¡?‘j<Æ9£ÙÓ´ÚjN´ü}¹‘û¡¿2÷·±@ŠQí§QQ8zêÉÌÛùñˆ R±<4MŽ –ñpk«¯+¨çŠrÙ—kã²¹ öd3°¼ò<–åÿE©ä#E¯vmœÏslå_1ýÌSáÿÚ¢y‰ZöBå½/éJ^丈«gÇñ+­C/úƒ®´^;¯±Xå³VíNºXôóݧ: ¢¹súœ÷Aþ¿*ó*n±¥î¡·¥±”W~Ç{§‘,┼T»¶–›DÒ¨.‹eA>OjÅŸ±´çàòJq°ü{` ].kp†M›ü²Çãè?~íÄ?N®Ìãç¿Ãü÷ü9O¡¡ÿÍßÀ‡?\‘GýÑGáüóÑÄMx.W™‡²¥õ‚Í›§ôü•®ë¡ëR¹ÝúZÛ"âäâ8Ùl–x<^aaYV0®Èçód2™@4Òu|>ëºd2’É$¶m“Éd‘OD-ä$„ˆ”SÞu]J¥Åb1½$D„¤!.j5MÃ4M:::Ðu¯¼à§»»;ÿ†A&“ <¿‹E‰D×Þ0 JåKâ©«T*á8†aÔv¢ã¨X,ü]ä eqÏ3"€FÓ”ïÕÇHYªóÖŸ719Væ’äÿLU;&ç’´«ËXËF¶ …ŠcKU‹½:úYУ£sÞ’ßûî»oÈ÷ëdæ™-qVù»¼ þ÷Ÿµ˜X¡èÍ„¯¿þzÖ¬YÃÊ•+{ý¶víZÖ¯_OOOW]ukÖ¬¡¥¥eHé/øáÖž°¶æog›’²þžCß?ÄŽ .àþSNñW‡HçZ\þD©vé#®…Ó¬\õkÛ•ƒð;”Õ.u¤E“8jÀ¨˜Œu;°ØžÆùìs¢MÓ´ ƒ«ÜÓ*õc¬Û~ »]à˜7ïý‹#”.¿ßÇÁ¶í~]©ª6flI-_ŽkY,onfy½33ÁÈçóœvÚiõÎÆ è«-q;P£z² ‘DG…¢¢*H¯IÀXö ?vŒk¿ç¡_ T Åb8L²<ß‹ó›½Àlô|d\_-Ö%“•nn¡rî êŠ0ЀîJý'*ÊC_ÖÈзյã°âÔó‡Ù±J Ýèy¢V½ÕnžEÌ“8£®ˆe§e§*@eµE6„¾i%¯µò/B\_e,Ç©5æí@ŸÓÝ[0Šß×þ~¯ŽµZ½ˆL®­Ô TÖ}Ùív†Å-ƒ÷T r¼,\/Xgï^æžx"±j Î~ªìcyœ‚_:އ‚mÛ‹Å`›X&Ú¶ã8(Âa<§­­ Û¶±mÓ -üÒé4™L&°.Ìd2½Æº®ã8N`q(¢–, ,‹5Ç1"njšF©TêWŒÓ4-0âH§Ó†r¾¾<Ì Öó\"‘Àq/^\!iUíG>ŸêI Eס—y‚2Çf?|—5Dßüæs8Î!Ç¡­­M…NQ(j0á„Ç;3ÎÎΚ¿IÃ! ÆÚµk¹å–[¸û¶twwlÙÁΦ,g¹ßÉK&±J†† 1¹ŸØÍ£ pÊ)§ð‘ø‡Êoµ{£Zttø­Q-w=P9 ‘Îxu§Z╈ $‰ç!ˆ+¨hL•è ;×õ1Òa7ŒÞ«øòùÞA$ªWFETÃè=˜²¬Pˆ•ßM³wÑCu2ˆ‰ž§zµ`t¦¸0ª•†\›§ž‚E‹z×iõuˆæ³Ú’Uò½6ò¦‰RÝ!Š^·Zç‰æ¹ÖE~ß12ì«s$éLaz,Ûá¤ãw±€#}Ö—Äwt'ºß…b3mÏìaæ¾£üà±Ìœy^ðúª':Çqhmm VÚʪÞÖÖÖzWå”Ç 7ݤ„Ç*LÓä‰'ž¨w6¤¯¶`Ä퀾éQ´ƒå‰Žª ÅdÀ`ÒˆŽcÝ'ØÄ4û¯ù^üö`›ëúÃäBÌß@ã‡XŸ:†sîÿ„öôšsW¥XW=^+[«õéæV×+„H `ZÕ>ƒY 1Ðü„®C¡ÀüMðê—¨ÝÞ ”†¸>®Aàax4òZ=P‹H> óì¡§1P^Å~ù¨IÄʺÚå)Ðç{'¸‹ªÊ¡µU﨣}éo1¾¯@Íüj«V¡wwWÄò­¸ËeèlogW{;™±j öíÛÇ’]KüXŽ£ì:‹UX£9ŽC, DAðç²Ùlà†41R0 #ÙPaQ¦–e[*•BÓ4š››éêêêSdKɨè¡÷§L÷.—«KT4†¡ D<íoQg*• ,8þõ÷ĸÍz<{Õ|Ì_êtN;wtÌàСïcš&]… P(¦(Fx\¿~=·Ýv[¿ûlذիW³zõjî¸ãLÓdÆ \uÕUžCäƒ_½öWì]´—Õ±¯mã|á»Äbþo¢ß‘Éðž|žÌG?ÊÕÚP±¯¯ßÄuP_.„9x¨)–É9 …ÊÀµÄã•Û«D2 +âg_iH>l»w¹£«"û›Í×ß~" ö×Q¹çøà+Ó—," ¦R•iØ6Á !TÇ•I§+ÌhÜ¡z¢9—«<Ï`¬f[[+Îx¼r`bY½óZ}ž¶6¿L"JNàU]ãÑ8àôÏóܬYÌïãK¥R ×ùR(& ãÕ¸”çæ>{g³sçæÍó͆»†#“Ïç1 #pUSPB†b‚’ÉdX»víÈ#j FÜ8ðèIòÅÝýåöX1Ù˜¸ÝþA3^}‚}ÓOàÏ_x[Å6ËýôâÉEÁØ]û·a ÜÇ=¥Å·"Ë$ûN|1_e-ïXðÖåð?ŽMÚõ>5ÒÚÛ¡hZµ ïúšþX¾^ì#pš›ƒù%?Æc#1ÖmÁ´'§±êw«F5Ïét×ukDMÓw ‰D"ˆ×—Ïçq'°HÌår0).L‡þ%*nögÙ'ÖŽš¦UXlY–ÕoÜ:JS©TŸâd-Ä=¬X(ŽÖBo]×1M“d2Ù¯dÛ6Éd²2ŒÖFÜù¦R©†14^}‚(úðÌCÏÏQôqŠº=VáSŠÞLáqåÊ•¬[·€o¼±×ïlß¾½Â„º¥¥…¥K—²eË–!5ŸÎ}šûßò)ø™ÝÝ8¶ ¦Rb¤æw dÅÌ„6Á—^v_/‰záƒé¥KÚ¦Y;.Jµõb-Fc5á ÓÐ<wÚ4X½º·x9ЊDÓì-V3P0pƒ±šíî…ÇZ™ä5ºÂ¶šTª·uæw¾3pþëÀxµîxõ®óùü…òÕ>ö‰Åbtww÷ZM¨P(Æžñj ²øa[lNç…£3øÝ÷;¹ä’eƒ:¶VüW‰âºnE¿aB÷!¦Ë»»±GžŒ¢ô׌J;`Á¢_¿ÈòîG}ѱ&\Š!1 néñèˆs¶wàÒi¨UøÜc°¤Œ™ €„ël‹ÅÚëGÊX x°âŒÑO·žªIxŠ!r­‘h_e½i9t 1­Fb¬Û‚óœG÷œnšµæ!çͲ¬ Ë¿l6[1“É‹ÅH¥R$ Ãö—1…ëºÁØB×ur¹ù|~Ø™išd2™…=‰«X½è:÷kÑ(ÂéPÇ9KP¾æboÇqÏLÓ$—Ë©ñYÓ4) ³è~<µ='îÛ·/¸g$Äñ±cÏÖ» …¢6Fxliié×ßòÞ½{zùnž={vŸæÕÂîÝ»Y»v-¯zÏ{0Þá¿„vÌÝR7M߈,ÚÎÊKß4Í!»PÔcÚ4,@Ÿ7oÄiÕÁ_ýuš"7öúõëÙ°aÛ¶m«w©j2–íÀ¶mÛ¸ñÆq?óYèaÇå—÷¹oGG‡“–o¼‘½{÷rÎ9çÔ;+5>ÁìÙ³™»n]y0qŒ#OL㢋ÞÉ׿¾bPy,‹˜¦´"6ÊJ[Õw˜8d7mâI`ÁÎõÎÊ„¢³³“µkײmÛ¶š±Q&ýµ#íìÚµ‹_ÿì×ü¾ûšW¯f‘š4PLF!<®]»–ÎÎNvíÚUïÜÖd¬Ç÷Ýw?<é$.½àý¼8ûE°mòß¿€|~–]]—ö:&ïß³êh0Ö݈/ž?úiªyüÁ3ØQæP$'­ŸtM¨X„UKb˜êãƒÏ-`ó¬Í\ÁCÊ—XŠx—Íf1 £B`s]7˜[¬žcתՂ™ÄBÉœD:”p‹ÅˆÇã½¼´d³Ù>…¼h¹‡"â†A:¦T*Q¬ù4B[WR/j¼æ“N§1VÍús†W]u«W¯ö='¶cÓ“w¢•çÅyÞÌ™ hmm¥P((1[1©X»v-ííí#îLáq,9ýôÓyÇ;ÞÁÁ•+qºá¹Yϱè# zómm‘@èe¢E㢚ýJÄÝ@­•AS… ²nÝ:bOÁÉÝOéµ÷³,‹t:]3VB5~Sú¸–åo3 ÿ»„s.²šºÚ{±x<–sË>àÿ/! ¢Û]÷ó(^£ûƒÿ=÷½ÎI¸Öl¶·Çf]óašþþ‚x’–m¦YÎTH$Â}R©ÞÞ‡£ÇEÏY+ × '‚¢ç©Î_&ã¯b^ÃèqR'²’MÊ“Éøï I#’VêZ×ù…B˜/Ù/zn9guñx¸O©ÔÛ›rô¸ês Ñã2™Þ«ñ cgœÑÅáÃ;†ËX }‚•+W’¬'À2Ïgî—ãèÑ I&ýzÈ ÝqlÛÆ4MŠÅ"Éd’D"A"‘ «Çâ‰E‹0žzŠ·oÜXï¬L(–.]ʺuë&´«Õ±dîܹ\rì¾öÔ×øÐ]wÕ;; EÝX³f À”¼ímoc÷Ç>FçbÞE3 #üSär³úìÛ¦ï]5‘ðû‹c1e  °'/c9ÃÔ_ÚÑ[J£·ø¸nÝ:ÚÛÛiŸà1Ç‚ÓO??Yô'4džfí˜L&q]7ìŠÅ"–e±bÅgˆÇO Æ­Ž£¡ë™`<C¿ë]³yê)\ÎC¼á¦Ópüñ?áÑGï%Ÿ×+Æqšæ·=mmþ÷Žh®Êv*%c?{ïÝôg‡ãEÕ«Ÿä™gæ2-[Ö45Þô¦oÑÚêß)žGÅï`rå•¿á¿þkÙl©z¬žÉøç‘(G÷Þ{>_¼lÖ`Ïž"é´x ç²ÙÊ… ©T8–—±põyR)8î¸bóæ=A >ç<¢ó ýèo˜1ãU$“ἈäUÎ-óѹÓôÿ/C§o2n—°]27!óÑy ygô7ͧ¼[¤¬2ï­çZó=Õó5+JtNH×õÀâñì³W³nÝjÞõ®OéY˜,Èœaãë6Æf í eÏåkpÓM;8í47p‘¬PL&Ö¬Y3*}‚)!Wtð!ÿGìbÐêóT'ƒ†jÝÈï”÷þ-Ot‹ëú×Ç0ÂmѰ¿Ñ}¥,†¸¤Nd›ÚÑ4ä%×4znYÜ*!x£¯3Mƒ'ŸÜË£î\¥MRl€ò@}×ÿî¢éô3yòÉÚÅ«a±X,¢i¹\.X¬â;Lë94-RpÏ=Pj‡i‹aú¹,<û8ô˲sgyìß´ýwßÃ(>¾õrØ úÕ·`Ûåqôãÿb+ÚÌC»[`7h©++¨ÜsîO ûðWIüüƒ8§üöˇbeÓnŠwî!ÞòKìÎ pÎ˜Ž³©…biN0þw‹ÎÃ/c?ý*X¿ýÜépñõ€??cY`Zi²ë?‡‘¹êggFhÆn,؉îX·ûž|ôU÷“}â#0kV°OæÒ»IÿçEXOMböŸ]þ#²O­~?óÌêýHN ŽðßG¯æ/#G¦ W^y:sæ˜X–¥Ü­*}ÐpÂcgg'K—.­ØVý_XÍð÷ÇþžTÙiEtb|KÇl6«ü4+˜‘´Âé_àú…¯¯ù[,cᯒÍúB™ëú¡Ÿ]÷E?E*!*X”Jþd„mW¶3þ¸j‰]µ¬®¢áCûZ ]¨ÕÜEë+èqµö̹£õÒ×B±h9k­L<ûè>ƒÙ óô· ^¨×¾úܵ҉Ök_yhQ]4µö=rä0O=uxàŠ˜ÀŒF[`5ƒv\wÆ•=\~ùÀukÛvàj5ŸÏÇw=ÊEóÄcáÂ…œ}î¹}¯nP44#”,ì¶ÉÔ%œP¶|,1…¢‘I[ð‡}/ñzæýô^¬¬ö»þ݆ʢB\ŸR¡ˆ¢|bŒ-#¸ÎVLäóPüÒA'G¿úUÞvÎ4>+›Àé:æ#I;»Á: ÜfL÷§þ¶KMþ˜Ÿ“L&¹ë®.pÎçÏ0Ý?̱–+™_ýÏþ lv1S)¿!ºx!ftø¡-ƒwøÂÞw¾ÒÃÒÃUã=™„¨H3[á­ÅøÂõ•‡To´‹bfýUÔÁ°Õh-2n·žë7À™døMy²£rœûØc8ï¼ó@_Œ©Ÿ=Ò®:=P,ñâ® v>œ¨|ˆ¬žòy ´D&i®©j›LÿÏ4ÁŒŒ—èy€Ì•åkÓ²}U¤<ùÍÁXÂ\ôDù_Yã̳g¬ õÑpQö7ÞTZþ5£1OÒ>Ì“Ì Òia&=v#çž;“ŠIDÃâŸyË–-E{{ûЂÃvÃûÙ¹ӧV@bA¡ë´0+ŠñgÔÚ`Mál2.èµýŸ8Ìë^÷—‹­üÕ_ùÞH Ÿû™ÔD…B1à$åM]¡˜xŒÊø µ5ð Z,ú^Ž|o4 0·Ò¡ûñðþ×¶i¯^ak~¬ÿ´u½æ CwœÐMcd%òé}MBtt„þCkiÀNt]vWïW£3,«ÒUä@ ⿳?LsÀ}ÎûÞ÷®³èŠêZ«®qž'^t}à}c˜RN£+ÉäÙ½Þö“ÍÄ3« ± €|3èÿ¹O< œ?äóŒVyf2yDŒö<ÀA÷N<× Cüó?]×ÉV»)S( #<‚Ÿnýúõ\}õÕ455qçwÒÔÔÄÕW_=øDž9Æ‡Ø «V‘~‹ß`Dã'‹¥£²Zhl2øFê N>FÚD'uæ¼ë]¿½êU=tw{\qÅoسgõ ÒS(õaTúeæýî 2==˜uGâA×u,Ë „GÅ%ê¯X1©i;ðÒW¿Ê›wí|1ÊÂklÂøWyBñJ"ª¶™„eëj‰mµ¨% r>‘ÐEXŠz†ÎP)öAmñ²¯sK­~ö«%湑íƒé{WçÇ)— ·8éD~¯õGã”IìªmnUÞúó¦-ç“ý%-©“Á–±«*¯ÑíÑòGëÉä]DD9¿Ù‰£õdÐ[\µÊå—z1 <ÿü0J61i[Ð3óxv=*l.·•ëT…¢QI[0÷ž{ü¾b¡€ãjdÛü¶ ‘pÈçóضãh˜¦9ª}]ׇ~s•†a z^SÍŽ¢CUë¡bø"Hx÷Óÿó>86ƒ§ £9O0s÷"¶wºîB‹X,F©T Â4)ŠÞ4”ð¸fÍn¸á®¿þzšššØ¾};kÖ¬¡©©iÐi\ôĶà{*ÆeÄÚQM"66Ê­Ôde¤í@tõ·tðmÛ7†ùèG·Ñܼ‰eËT‡O¡˜èŒFŸÀÂ_e|â¡ý€YÓÝq-d/ƒ E ÌS&%#mf>Ì£gŸ1&~ì­ƒ·ìmºS£zÈ`G+ƒ>s¿ÖÈi$é˜UŸ•e¸iŽ$Án¨^ÌÛSwý•ç±ßÿ~„¥¬#i ¶.\ÀãÇÿÛ¾ŽÖVèî®w‰ ÅpI[pÊãC"AkLC×}ÃB€X,‰S¶JL&“¤R©QË4Važ+h*ádtÑ4_PŒkЦX-<Úæsßý³õÎö¤a4æ 眻çÕì?ÜL>ïo“Ç%‘H(Á^¡€ )<>þøã5·755q÷ÝwÓÞÞÀ²eˆÜp=ù¨¿âÔöņê÷«išC_m¤P(F±lfï?ÆÝœÎõøí@,æ/Bдï°l™‰©Vš)†±l LË‚ÒÜü†±¼ß…¦ŽãP,I§Óttt¨>ƒB1ŽÔj FÚ4ïÙÃW¿ùMŽ](O ÅDg¬ú+7ä-§¾…|^Æõ.©B¡è±h º>ýiž™±'²®ÐqR©T : …J—¤£„OL. £·uc-°ºÆœ.˜¦©E’Ã`¬ç œ°{o3àÏÊ5u]Û¶Õ³«P À„B|6™pòÓ/0kÖ,\··Ç­X,†ã8är9%<(œa·@ë¯OÀZçzü ߦé»LH§•‹…¢ÑI[/ù·Ë?@sóv4­ÿ¸Nù|ÇqèêêBÓ4‰„l4ù¼?˜W}»IËpÛŸüѱyùrA‰Ž Åd`8mÁ’mÛøÒû6ñw—Æ0j‡S(Åpû–]]áâƒt:¦ùîUmÛVsŠAa +ÊZã©§ÂÙÊ_ÛX0ÒyaÿÞí@ ¦ö\×UíB1Rx.ö‰`°ŠÏ^v†U¹’QL&3&+˜ ÅÄÀ¦½Å5¿ù úßXï¬(Š:1ûÅÙÌ:öw<òì§ÁQÖŽ ÅTeß¾H§C«g×uI¥RA¿¿T*©‡ŠA¡iƒr˜&X+gÀ55‘ùÐ3cÇÅ·’N_Ša„Æ©Ê`I¡˜)%<ì;m_ð=ª/X–5êA¢ ÅÄCbÑãâqp?Ÿý'ŸÛöãYVèVJ×üje`©d³þ6ÓôÏã8á9$n®ÔU"áŸG¼ÎÈÄœ'û‹•âO4¯‰„ŸÞ`ÎS]÷r\ôZUï#ÇE¿»nå$¢gš}çUî ¹?\7̧¦…×CÎã”/Mó·e³þ1’ïh>¢÷’a„ûW§½æµòZ}ýþð‡·0™Ó=°xñ„¯)ÑQ¡˜Â<öØÉÁû üE‡®ëR(åU14¶Ó|×êY\ÑÒúÒ ŸaÁòlÞùͶ±«;× …¢SKxì“_<üí7¸®‹Á*ŠIËŒÃ;Xvö%´¶†ñ¢ƒ …B1ù ¼­ÿIŠ­wÜÁ4÷¹¯ã8›%…B1y¨ž0Ȳ|‘&*¤•J~LhMó¿‹`²€ip–R²ðQ×ý´£î¸lÛO#• Ó«¶Ä–ñ‹oQ¹¿lQ0š·¨hfš¡8*ûGó.ù‰~jZå¢MÛ®4%_®–«/jÕ“W—ZD‡l"ØÉ6ɦ’®ë†õ[}­ª÷­ž[AOêAÊ+B¡#ç‘c #Ÿê ¨¨?ðÇ’à»Þ“í¶m“H$H§Óär9²Ù,©T Çq0M“X,”;‘Hå/‹Áõs8ŽœKÓ´ ßr}ÒétÅg,#‘Hôº'$ýT*”µµµ•ŽŽÒé4Ë—/çU¯zU½oåºðøã§pÅþ÷b±H6›¥+“E¡PL-¶‚¹íA~åΞˆçž›,â*‹jŽ@¡SKxììá?úW~°ôki#¤s§VÁ)“÷h@ó²¤Þn7MSuŠ)†öèü~'—]ÖI_kd¢,W=c­hJ¥Þ¾( “É`ÛþíaÐÑŽ Tô…bjðÔi§aá?ÿõ˜ p]Û¶+„¸|>O<¯E(«šDH‹Åbd2™ ¸Ç 'Ó4±m×u1Q„2ù†aTX†‹)ß%O}Y…‰è)¿Ë¾2ç¢i¶mÛÅ •ˆ~2?S(Ðux<ìM_×u:::0 ƒîîn4M£«« ]×I$˜¦¤W*•0 ƒt:ŠÑüTÏ I}Ê9åwEØ4M3¸>Ñ:ŒNL‹8+â¨að*u$å1W„XAêKÊ#yN¥R†Ô‘Ä#Œ^³hØ9&Z'©TŠ—_~™Gydü„ À—¾ÔÉùç¯ü{_-HV(¦6ÖÑ=0 z0H&COŽãH$T¨6…bLó¼èÚÝÉÉÚµkY¹r%—­\É=|_?!Æ#¼Y¼ÔÜÜt¶Š©À7ÞȺuë꺔û™Ïþ3Æ]wòÿÖ~” š‚ ÆiÓ¦@…b*ÐÞÞN{{;kÖ¬©wVÆéüïÊ•XÖV§>Å¿¾ò\y好,FŠÅb°0)«öA1)‘gbåÊ•õÎʸ"}¡ÖV_lTk ÃEÄ™ä—w…뺈 ÿÇmŸr|µ˜3ZLÅñA{{;ßøÆ7Èç]L³0( Þ¡bÛv`¡×Ä¢¯P(‹ÅðVÎ/e«%96›Íör3M#›ÍVX¯É÷x<ÔouÌөļy× *FkÈ3-Öz­­­ … Q¬ß¢–|¦i"kÁK寍ÔO£$ÏXÔ*Q¡PŒ.Ê0A¡PØÏÀÒ_ŸÌ‰'ž‰eî[ —ê1xP(©'<î|‘âã ®¹Æw¡$®0 Åaß©ì{x9Ë—wÍ8ŽLB©Á…B1…Ø úc›±‡5_ÝM<Þ{Æ1ŸÏ{ …bòQ,B"Á°‡jK7q£çº.–eUÄ4“Ø^±XŒB¡@[[[ð¤ÄBNâˆU‹ ÑsضM±X Ü&ŠÛ¾¨KÀh¼6q(â‡üišôƒÄ¥¡”G¾ÁoâzZÜôe2™ %1Ðä"¶È¾¹\.öÄ] ønoÅ,êNQÃ0‚‰à\.WájPÊ õ$ÇÊ1¦i Ì2™LÉ£Ô‘Ô“\Óè±rL4ÍZ–f™²é¼Iò)nå|Ñk]}¬¸HìêêBÓ´Š4ª‘¼JÈ9V>åX¹¢« ×`*÷ƒ¯½vïz×ÐŽ‘çBžq}åùQ±?‹æE¡˜x$“É ]U(S›W~q„£G¯ þ·,+è³+Š™2Âã¯gÏàû^Œƒg }ÕÙW(¦ÎéәÙ\rÉqþÿŽ£V4*S‘?ìDs]lLܵKøèG+ŽºXU(“M^,G˲qQ„5ÓÄâMkˆ»æj!L>«'0jMhÈ$¨Ä’ÕÖÒNI_¦¿ÉɈ\ò)Û£bõ1Õ"hõ§ä£Öùû²ÒLÛ×ùú›N¥R5Ë5•X4¾[_ÇÇÒ¬:- OW©Q‘y°é¶nÔØ·7K–,áá‡çBJ,Ç!N¢´aÈ+¼ªk…¢1I¥R£îÊZ¡P4¶'h²hÑÀÙA ]…B18¦Œð ;ðƒË¹ôÒ4­ ×u)‹ÁÀT¡PL~œf¸ˆ=¼õ­ó_\ï …bêàÿ‹f¼Š9sÞEõã_,I§Ó5­K Åäa ¸Ž£/ŸÏ–eù|>p³)VsQDt“ñEuÿ¢Z´Rý…¢þˆõs_ˆu±¦i‹EJ¥‰DB!ŠI†eY´µµÑÝÝ]ï¬(Š:ã ï}‰·üéSˆð(žJÔâ"…bpLáqß ' ;ðàôyüéõM@è›Y­fR(¦³œÃ…ƒX (Š©…Ût[öÇÙ³çÔ áQ„,^¡˜Ú¤Ói€À‚|ÑPõŠÉÅ¡C3¨õX;ŽÄu]—L&£-+“qÉ­P(¦6NùóÛ^Eæä}€?OP(Ô8@¡ÇÕ;ãÅÖ›pgáu¯[O"á7±XL¹QP(¦ ¿r^|ÅbAŒ…B1up›á¤ßàÊ+ï&:‡X,Éf³ªo PLAd|Ïç)‹$‰À5êpÜk*ЉÏ3ÏÌEÓzÇz-‹ÁÁ4Í`‚B¡˜¼$“I5P(8À)î~<àÏÿ|.ù|^Í(CdÊX‹ƒÎÜùÏà8±XL-@P(¦ M<Áùö£¬2ÿ>ئiššhT(¦ ¶m“J¥Ô¸@¡˜â8ŽC[[›rµ¨PLQ~ò“Ÿ(QA¡Pàö÷^ܹo NcYV½³¥P4SÆâñ¦Xÿ<ôv`€L(Sߟy&673q]—R©¤„G…b ²õøfv¸ 9çä€0–“Šé¦PL-Ç¡µµ•ŽŽÕP(¦0®ëR,Uìw…b ³oß>\×­w6 ÅÀpáÍ«OÆu]‰„+(àá,×®]Ë%—\¹çžË-·ÜÂöíÛuÜóÞÎ쓦cÛ6étšT*Uï¢(Ša2Üv`ß¾W0í‚M´¶¶ªŽƒBÑà ·-xñØzÜ“0Ͱ Pý…¢1n;‹”РP4>#i ,Ë"ŸÏ«¶@¡˜ ·-øèG?ªÂ°(“„‘ô $Šãr;Åë^·ˆt:M6›UÞ‘ŠaÐPÂãÚµkY¿~=kÖ¬aݺulß¾[n¹ePÇîÞÿjæœt"®ë*÷ E3’v@›%à²Ë.S Eƒ3’¶`îONfVño{Ûy‹Eb±˜r³¨P4 #iÀíè8Π÷W(“‘¶¶mÓÑÑQïb(Š2Ò¶@¡P4>#m¬GåTg1²µc&“©w±І¤¡„Ç 6°zõjV¯^ÍÊ•+¹ãŽ;èììdÆ Ûzü.h~VY;* ÎHÚyÏÌÀb±˜šhT(œ‘´O>ðjÎþŸ=¸®‹¦iär¹zG¡P ƒ‘´¥RIY7(“€‘´Ï<ó –e)O( Å$`¤ý…BÑøŒ´hßucż¦µ‹l6ÄV(C§a„ÇÎÎN¶oßÎÊ•+ƒm---,]º”-[¶ x¼¾Ìbþµ˜¦ÙƒŠõë×ÓÙÙYïlŒˆÎÎNÖ¯__ïlŒ˜µk×Ö; S–‘¶Ïœ÷ v‡M¡Ph؉ÆÉpÿ©öL1RFÚÌõ÷Y~~‰l6‹eY ×L–ûo2´g“¡ ÊHÛ]×r\0\&KÛ1T¦âs:•®õHÛ‚³Î:kÊY;ªgbê0•®õhô ¦Séþ&Ã\Äp˜*×z¤íÀ¶mÛ¸gáN¶ðâuë1M“R©Tïb ‰Ép­'Ãs:úÛ¶mã±ÇQ #<îÝ» ¢ñ˜={ö nÆŸ.ù)y+ß°æÑÛ·oê QÙ»wïüjOT½ñkdFÚ€oíhÛvÃN4N†ûOµgŠ‘2Ò¶àüÌàü-©Tª!û“åþ› íÙd(C£2}‚©Ædi;†ÊT¼¦ÒµVmÁЙŠõ2•ž‰(SéZ«¶`èLÅz™ sÃaª\ë‘¶/¿ò {çœÊÙýwß}7®ë6œµãd¸Ö“á9 ýŽÐÓÓ3¢4N¨w!ƃiÓ¦±yóffΜÉ7ÞXïì ‹={ö`Û6wÞyg½³2l>ÌáǾܵkWÃÞG»víb÷îÝœzê©õÎJ]xúé§™?>ßûÞ÷øÅ/~Qïì ‹F¾ÿÕžÕŸÎÎN^yåÞóž÷Ô;+ãδiÓø—ùŽ=ÊW¾ò•zggX4úý'L†ö¬‘˰ÿ~¶mÛÆK/½ÄêÕ«ëqçÀ\z饜rÊ),\¸°ÞÙ&KÛ1Tù9.C¹ÖÛ¶mcÿþý,Z´¨ÞÙwZZZøÏÿüO … .ä”SN©w–ÆõLL†r­§úøàæ›oæ¸ãŽcéÒ¥õÎθ1Û‚É01{­§úœá‘Ç9aîÇÙµà‡¼å-oá¾ûîã¾ûî«w¶†Ädx®'ÃsÚèýŽmÛ¶±gÏÞò–·Œ()!<~êSŸâSŸúT½³¡P(êÌüãzgA¡PÔÕ'P(…B¡ÞYP(u¦¥¥…M›6Õ; …¢Î¨ñB¡øå/YþÖ˜ ”ЉFøZj)ÅSiE’B¡Pí€B¡ðQmB¡Pí€B¡Õ( Õ( Õ(ƒ†Å?su0ØöövZZZê=…B1¨v@¡P€j  …j …j  ¨¶@¡P¨v@¡˜h4Œð°zõjÖ¯_¶¼óÎ;ijjâꫯ®wÖ Å8¡Ú…Bª-P(ªP(>ª-P( Ú…B¡Ú…b"1Íó<¯Þ™,===Üpà ôôôÐÔÔÄöíÛY³f «W¯®wÖ Å8¡Ú…Bª-P(ªP(>ª-P( Ú…B¡Ú…b"ÑP£ÐÞÞÀ²eËhjjªwv EPí€B¡Õ( Õ( Õ( PmB¡Pí€B1hHáQ¡P( …B¡P( …B¡P( …B¡PL,*Æ£B¡P( …B¡P( …B¡P( …B¡˜˜(áQ¡P( …B¡P( …B¡P( …B¡PŒ%<* …B¡P( …B¡P( …B¡P(Š£„G…B¡P( …B¡P( …B¡P( …B1b”ð¨P( …B¡P( …B¡P( …B¡P(FŒëHOO·Ýv—\r çž{.¦i²aÆ^û­]»6Øç–[naûöíCú}<ËsÉ%—ÐÞÞ>ä2Ô»6lÀ4Í]‡z—AѸ ¦-h¤û¯¯¶ Ê0mA½Ë hLF«O0Ø}Æ£<Ú'€Û‚F(ƒbr2ž}†‰xuÛ2ÑÊ<^mÑD+·¢ƳÏ0Qï‘´öLŒ×\ÅD*³bpŒçœâD¼?TŸ`ê\뱦‘Ê|ýõ×7ä{2Ì{öôôpË-·pî¹çrî¹çrýõ×ÓÙÙ9ä·ß~»×ÚÚêÝu×]ÞÆ½ë®»Î»îºëýûx—çœsÎñ6nÜX±}0y¬g9î¿ÿ~ïœsÎñòù¼·qãFïÖ[oõÎ9çïé§Ÿn˜2(›Ú‚F»ÿjµP†Ñh ê]Eã2}‚Áî3^åiÄ>ç Ü4B“—ñê3LÔ{x,Û–‰Væñj‹&Z¹3^}†‰|o ·-h´gb¼æ*&R™ƒg¼æ'êý¡ú£?W1ÑÊ=4R™óù|ÃŽ±'ü§œoãÆÞƽ›o¾ÙkmmõöîÝ;è<Ö» Õ×d¬ï'%<Ö‰½{÷öêxžß|óÍÁÿo}ë[½Ûo¿=øÿé§Ÿ®8n ßÇ‹|>ï]wÝu5oØÁ䱞å¸îºë*ÎíyžwóÍ7{wÝuWÔAѸ ¦-h¤û¯¯¶ Ê0mA½Ë hLF«O0Ø}ÆšFîxÞÀmA#”A19Ï>ÃD¼‡Çºm™he¯¶h¢•[Ñ?ãÙg˜¨÷ÆHÚ‚F{&Æk®b"•Y18ÆsNq"ÞªO06s­ÜãA#”ù®»îòÎ9çœà¯ÑÆØ“aÞsË–-Þ9çœãmÙ²¥ßr5JÛ2^s6ÊÕjؾ};+W®déÒ¥Û—-[FOOÁ~BKK K—.eË–-þ>^tvv’Ïçùüç?_ó·òXÏrlß¾ÎÎΊsÜqǬ^½º!Ê hlj éþë«-h„2ŒF[Pï2(—Ñè vŸ±¦‘û0p[ÐePL^Æ«Ï0ïá±n[&Z™Ç«-šhåV Ìxõ&ê½1’¶ Ñž‰ñš«˜HeV žñšSœˆ÷‡êøŒö\ÅD+÷xÐ(e^¹r%ëÖ­cݺuÃ*C½Ë9æ=›šš¸é¦›z•!J£´-ã9gs¸•JQÁÒ¥K{5===ÜÿýÁ‹cïÞ½½^.³gÏ®xéôõûxÐÓÓí·ÞJ"‘¨ùð T†Áî3Vˆÿá––n»í6¶oßNKK «W¯Ê3ÑË hlj åþë¯-h„2ŒF[0ÚdEc2}‚Áî3–4zŸn ¡ ŠÉËxõ&Ú=<mËD{‡W[4Ñ®µb`Æ«Ï0Ñž )çHÚ‚Á”i"=ã5W1¯µb`ÆkNq"=RFÕ'›¹Š‰v­ÇƒF)sKK ---Ã.C½Ë9æ=[ZZX³f à o{÷îeýúõ,]º4ÈS#´-ã=g£,'6làú믧¥¥…D"Qïì š|>ÏìÙ³¹é¦›ê•qýõ×ÓÔÔÄÒ¥KÙ¾};7ÜpÄzÉ(¦ª-¨/ª-PLT;PT[ hµ­*“©m*ª-R ÄTi`궪P †©ÒLÕvT[ ˜<4z{µvíZn¼ñF6lØÀÕW_MSSS½³4hÆ» UufûöíüöÞ=NŽªÌÿÿLî2I Á€aL¬$\¤Ôñ‚ºÕ@@ÑêøÝU!_MõêŠq×ùÙ­û•ýŠën—›]aqu»ÂnÄÛ:]_Yo@´ËUAFÄ)DɺÇ@a*™$$!þýQýTîéžééÌó~½úÕÝu9uNUõÓ§Îç<Ïsã7bpp›6m‚®ë-sÃb``wÜqG£«R3º®üèTUÅÀÀnºé¦FW™%°-hØ0„í@óPά_¿¾ÑUc˜–¶S¥ÝlËTa[Ä”c6Ù`vÛ~>a&b6Ù‚Ùl¶LëÓ.öм7±qãFtvvžæÍL#l({<6ááá`ÆŠmÛèïï/ùƒ+5ƒEt‡lýt188ˆ¥K—âÆoÄÆ±qãF¡ò?•64²Æˆõë×á Z¥ LëR‰-hæû¯R[ÐÌm êa ݦ5©WŸ ÒmêM;õ €ÉmA+´iOf²ÏÐ ÷ðLÛ–fh³ÈLÙ¢fk7313Ùgh–{£ž¶ Õ~35VÑLmf*c&Ç›áþà>ÁÌŒU4[»g‚vhs³_ÛV÷¤\«"}}}èëëÃààà”êØìc·•Ö±’mXxl ›7oÆå—_Ž[n¹¥d¬fŠ•[œ˜sppÝÝÝ“®Ÿn6lØ€›nº ›6m ^pùå—Ÿ+©c#Û±nݺ’Çÿ¼›½ Lë3‘-h…ûo2[Ð m¨‡-ht˜Ö¦Ö>A¥ÛLíÐ'&·­Ð¦½™‰>C3ÝÃ3e[š©ÍÀÌÙ¢fk7S3Ñgh¶{£¶ Õ~35VÑLmf¦ÆLŒ)6ÓýÁ}‚é«h¶vÏíÐæV¹¶­>î¹}ûv\ýõnÓì¶¥c6,<6ˆÁÁAŒŒŒʸøã 6```ccc€­[·¢³³—_~yEë§úш/‰U+­c£ÚÑÙÙ‰¾¾>lÙ²%8öàà ¶oß^¨™ÛÀ´6•Ø‚f¿ÿ*±ÍÞ†zÙ¶L5Ô«OPé6ÓA;ô €ÊlA³·i_f²ÏÐ,÷ðLÚ–fi30³¶¨™ÚÍLÎLöšéÞ¨—-h¥ßÄLŽU4K›™Ê™É1Åf¹?¸O0ýcÍÔÚÜì×¶Æ=ׯ_±±1lݺµ ]ƒƒƒuï‡L³éÈår¹io3Ž-[¶ܬ"}}}A¼à±±1\ýõCgg'FFFÐß߸ØO¶~¦Y³f ¶mÛVpÃVRÇF¶cdd›7oÆðð0Ö®]‹ááalÚ´ ýýý-Ó¦u©Ä´âýWl Z¡ õ°nÓšÔ«OPé63E+ö €ÉmA+´iOf²ÏÐÌ÷ðtÙ–fkóLÙ¢fk7313Ùghö{£[Ðj¿‰™«h¦63•1“cŠÍ|pŸ ¾cÍÖî™ ÕÚÜŠÏØí2î900€o¼Xºt)FFFZ~Ìpºï'[мnݺ’1Û'[ß TRÇF¶ƒŽÝÝÝ]ÖŹÙÛÀ´7ípÿµBêa ݦ½i…ßQ;´a2[Ð m`f/õº?[í®G›š­Í3e‹š­ÝL}hÇßD=ÚÝj¿‰™«h¦63õ¥Ý~õhs½ÎK#Ú4ÝcÍÖî™ ÚÜ×¶ÙÛ022„9n÷1Ãz\ †a†a†a†a†a†a†©ÎñÈ0 Ã0 Ã0 Ã0 Ã0 Ã0 Ã0LͰðÈ0 Ã0 Ã0 Ã0 Ã0 Ã0 Ã0LͰðÈ0 Ã0 Ã0 Ã0 Ã0 Ã0 Ã0LͰðÈ0 Ã0 Ã0 Ã0 Ã0 Ã0 Ã0LͰðÈ0 Ã0 Ã0 Ã0 Ã0 Ã0 Ã0LͰðÈ0 Ã0 Ã0 Ã0 Ã0 Ã0 Ã0LͰðÈ0 Ã0 Ã0 Ã0 Ã0 Ã0 Ã0LͰðÈ0 Ã0 Ã0 Ã0 Ã0 Ã0 Ã0LͰðÈ0 Ã0 Ã0 Ã0 Ã0 Ã0 Ã0LͰðÈ0 Ã0 Ã0 Ã0 Ã0 Ã0 Ã0LͰðÈ0 Ã0 Ã0 Ã0 Ã0 Ã0 Ã0LͰðÈ0 Ã0 Ã0 Ã0 Ã0 Ã0 Ã0LͰðÈ0 Ã0 Ã0 Ã0 Ã0 Ã0 Ã0LÍÌáÑó<ضÝèj0eð<ŽãÔµ¼éºÞ¶mÃ󼆻™ÏK+0ÛÛßî8Ž×uƒïÓ}½'²Í~¯5{ý¸ýL=™êõžj¤UmA3×ÏS+õèLÅ´ªh…úqûg7Í0N0lA3×ÏÔf ŠûT¶VݸýL½á1ÃòÔ­~¹YB&“ɵ{sS©T.›Í6ºSbtt4§iZ@@NQ”ÜÐÐPÍåNçõËd2 9v3Ÿ—V`¶´¿mA- ådY숪ª¹ÑÑÑi¿ÞÙ‚f¿×š½~Üþú0ÛlA9¦r½ãñxNUÕ)•ߪ¶ ™ëÆç ~Ì6;P¯>ÁTmA«ÚV¨·¿>´š-h–q‚Ùb š¹n|êG«Ù\®6[P®OËñ˜a+ÖÛ_?ZÑLÓvÌ6;P>Û¦i5[Ð ãl ˜v£ÕìP›-àq†)M+Ú¦5ikáÑ4M$‰’J´Î4M¸® Ó4 ÖÛ¶D"D"QàΟH$ày Ã@"‘€eYkªÛOýIŠõ§ï®ë²¬Š]a©,Ã0‚}Š—•Úf²2+m¯çy0M©T ’$’É$dYž°­‚kæy^p&ªmG!¦²o%”»žâ¹0 cÂp ¥® aÛö¸{”ŽY\ÿJö­gÛ›É~kÙ‚rvh¬-˜è·Q[P‰m¨¤ÌJÚ[Éïq¢öRªª$I‚¢(%;Q¢¨ôØSa¢k9]¶ œ¨d_ñœ°-`[ –WÎLgŸ [PKŸ@\FƒµÒL}‚JöŸMv@˜ì÷<]}qy=lA#úâqùù`b¸OPyyèL6N0Q{ëÑ' å­j ¸OP9Ü'¨¬¬V3*ïбxÌpüù˜ ¶ –>0;mA+Nå÷Ìc†õ·m+<ööö'жmD£Ñ`x‘-ËB4 npÀÿ‘Ðöžç¡··78ñ´Îó¼ 3‰D‚›’n’â²*Ý~2 Ã@, þ,éâW•%Ît(^Vj›Éʬ´½´LQ8ŽÛ¶!I’Éä¤m¥OOOp¬H$Rò\Ð:Ïó‚ŽF¥ûÖr¯yž‡žžžà‡iY"‘HÅ×FĶí‚{4‰lF îщöP·¶7;Ù`b[0‘×7ÂÔÓˆåMô»Ÿ.[PÉïq²öJ’TÐÁs]·``‚®¡hh»zÙ‚‰îµé²ÙÉö%Øø°-(,¯œ-˜Î>A-¶ –>‹Å ëú8Û1Uš­OPÉþ³Åü|0•²õ|0ÙïyºúD=lA#ú?T ÷ *£‘}‚ÉÆ &jo=ú@ëÚîT÷ */«Ç Êút yÌûSí³×´Ò˜a¥¿g3œ&[Ð蘱ÓA*•ÊI’T¯˜b‚g³Ùàe9ˆÛOëŘáT^.çÇçM¥RÁ:EQrº®ß‹sLuûÉ‹Çãu£ýUU0Žøde•ZVj›Éʬ´½ét:ˆ³.ËrN–åœ$IÁ¹Ÿ¨­k8™L¬PÇettt\&Û·’6Òyžè^+އ<::šSUµ¢8ÚÅ?Íâû¤¸œx<žÓ4mÒ}'j{»Å÷žèÚär¹ mÁdv€Îs£lÁD¿\®v[P‰m¨¤ÌJÚ[Éïq²öf2™œ$I ‘eyR;@ûÕÃLv¯M—-˜ÈL¶/Û¶•”7“}‚ZlA-}ÚVQ”)Ÿ±“Ù‚Fõ &Ú6Ùj?L½¬RËi ¦«O@eUk Ý'Èåøù ¸OÐ}‚ÉÆ &jo­}Ú¾Um÷ *ƒûÕ•UjY³Žæråû´ŽÇ Çï;›lA-}qýl´­4f8ÑþÿýßÿÍc†eö­—-hKGr§g²èºÀW‹×‰á3lÛ†,Ëð<¶m|'Õ]ÜW’¤Àå¿SÝ~2(T@qÙµ–UnY©mêÑ^qöR6›E6›…®ëªþdmÇãÁgºÆâŒ&š-Q*DÊdûVÂD÷-‹ÅbÁ̬L&Só5”C³lÛ®Ø »\ÛÛ-¾÷DטØTb€ÆÚ‚zÚâòJ}/·¬^íì÷X®½äö¯ª*R©T†Eœ…3‘¨äØ“1Ù½6]¶ V;P®íl ØLåûdLµ­ÕÚ‚Jö-e hÆf*•ªùÜqŸ ¹áçƒêÊ*·¬‘¶`:úõ²êl *ûÕ—WÉ÷ɨç8Ádí­vœ ÕmÛÊà>Aue•[ÖŒc†•ô 3,Çl°µô ¶­2f8ÑþøÃð˜áDÔj æÕÔ‚&¥œû<€IO°ëºA\]‘©þx˜ÉQU†a„L‰Çãǃ.E±‘Rªª"‹!›ÍNißJ˜è^“e™L&pÇ÷<º®×ep“ÜýÉpÕúgTëþÍÈDטذh<•Þ“o=NËdYFoo/ÞøÆ7˜š˜Ê±‰Éîµé²õ¶Õ´½`[ÐÚÔrOVÒ'0M’$Á²,X–äuI$S±Æ}‚憟Z›JîËZúõ²êl *û­ÁdãÕœóJÇ Zݰ¨ î´µŒNÔ'Òy̰2ÚÑÔÒ' ýÙ4ŽzÞÓA= ¹OÐÜðóAkQÍ}YKŸ ^¶ }€mA¥pŸ 5hä8A+Û¶•Ã}‚Ö [0QŸ@ôÖá1ÃÉÏ_»Ú‚ZúÛ‚™¦Ö{r¢ýyÌpúÎ{[†ZÕ4­ !¦8AÓ´ )1­kªª:n%)mZéÏ@QȲ\0;$‘H@–åŠtq2YI’Æ=,PòiÃ0 :•ì;ÝkâLSž] Þ£brWúÑ“á ·þJö-Õv:çí6+g¢kCëËÙ‚V·ÔžV¢Úßcñu÷¿è¢‹‚eåì@-Çë0ѽ6¶ ;Pnßrmg[À¶ ¨å÷XMŸ@UU$“ÉàE}“d29åÐ&ÍÚ'˜hÿâóÖ®vàçƒV£[PKŸ ^¶ }úÎÏ“Ã}‚Ö°'he[À}‚Êá>AkP‹-˜¨OÀc†Ü'jël fšZ¥öç1Ãé·méñ¨( âñ8¢Ñ(EëºÐuŽã@–e¤R)D"¨ª :‰³›’É$‰D`<\×-˜ÁЬP¼rrÉmÒé4"‘Hp®=ϛҹv]===Á¾åÜ5Mƒ¦iˆÅbAX…J÷ˆ‰î5]×aYzzz (J0ë¥\Ìh]׃2=Ï þð¨-¦i¢§§²,÷0Íf˜h_ª³ã8mo…û»ž×À„¶ •íК¶ Úߣ¢(Áu¤{žîé⎔hÄkY«-˜ì^›[P‰`[PÙõa[Ð\Ôò{¬¦OPÏkÙ¬}‚‰öŸ-v`²ëÃÏÍG5¶ }‚ZiDŸ€ÚÃϵ_î4'hu[À}‚ú\î4ÕÚ‚‰ú¥à1CîL¥O°-˜ijý=V²?Ößtär¹\u—¼ùq]7pW¥Ù0äöL']–e˜¦ ×u b‹É`É}ºÙÛVdÄ3]o òÐ&¶m#‰ —Ëê|¥×©–}ËQê^ äº‰pžç•½žÅu§DÆäÂ=Ѿ¥öoWÊ]›JlA+Úâ¶5»-¨×ï‘®óTö¯·-˜ÈÐñ€úÚ‚‰ìÀdû–+£]a[о¶`:þ×k¡ÙúÕìßÎðóAsSßs5}‚zÓˆ>X.?L ÷ šßˆuffœ`:hÅçƒf8o3÷ ZƒjlÑ ãb=šåù€û!µô ÄíZé\µ’-¨õ÷ØLã ­Ø'(UÆThkᱤR *s$A<o¨Ê/ªrLå7{yµ"þøë¹ïL´³ÙÎåle6Ø‚é¸×ê]f-¿åZ)wl¶³ ¶S+kºÊœ®ÿõZ`[0{˜ v ÊÛ/˜ÉvÎdùLåÌ[Ð }‚Zà>S+³Á´By„Ç `vØ‚VèÔú¿>ã l*§-C­N„è*M!SȽ´‘”‹µ+2•™=Í^^³2íœ-ç²Ù™ ¶`:îµÙpÿ²˜]°-˜ZYÓYf³Á¶`ö0ì@+”׬Lw;gËylfƒ-à>AupŸ`ö0ì@+”׬°-˜=Ì[À}‚ê`;P9³Îã‘a†a†a†a†a†a†a˜ú3§Ñ`†a†a†a†a†a†a¦õaá‘a†a†a†a†a†a†a˜šaá‘a†a†a†a†a†a†a˜šaá‘a†a†a†a†a†a†a˜šaá‘a†a†a†a†a†a†a˜šaá‘a†a†a†a†a†a†a˜šaá‘a†a†a†a†a†a†a˜š™×è Ì<ð2™ .\ØèªTͰpáB,X° ÑU©š_|GÅ’%K]•šØ»w/–/_ÞèjÔÄܹsñ×ý׮ƌóÅ/~/¿ür£«Qípÿ±=kŽ=ŠH$‚K.¹¤ÑU™QÚ¡OÐ÷Ðö¬ÚpàÀ|âŸ@ggg£«2£|ë[ßÂÓO?ÝèjÌ(íb;¦J;üN§J5×ú•¯|%þüÏÿ¼ÑUŸQÆÆÆðÏÿüÏü›˜°ý« ~>hÝçƒj˜¶ Æ"ªaª×z¶Ž~úÓŸFWWW£«Qíð»n‡ßi;ô;<ˆÞÞ^¼ã墨ŒY!<Ú¶+VàÜsÏmtUªÆ²,¬]»¶¥ÛðûßÿÃÃøì²Ë]•šØ²e ®¾úêFW£&¾øÅ/ÎÊNÄàà`Ë·»î?¶gÍÁïÿ{ض=ëÚ¡OÐ÷Ðö¬Ú`YvìØ¾¾¾FWeFùÁ~€n¸¡ÑÕ˜QÚÅvL•vøN•j®õ­·Þ:ë„Ç;v`llŒ³¶•ÁÏ­û|P ³Ñ´ÃXD5LõZÏÖ1ÃýèG¸õÖ[]šh‡ßu;üNÛ¡ßq÷ÝwcÛ¶m,¬\¹rÖÝü›˜=Ts­ùù`ö0mA»ŒEL•©^ëÙÚ'˜;wnËßíð»n—ßi«÷;~ÿûßã±Ç«©ŒY!<¶ýýý®BÍôõõµôŽØ¶m[£«ÀÌbÚáþc{Æ0µÑ.÷_;سvh3{hÛ1Ufãït¶^k¦2ø71{˜×š©œÙx´ÃXD5ÌÆk] k×®mtj¦®u;üNÛ¡ßqî¹çÖ<iN£Á0 Ã0 Ã0 Ã0 Ã0 Ã0 Ã0LëÃÂ#Ã0 Ã0 Ã0 Ã0 Ã0 Ã0 Ã05ÃÂ#Ã0 Ã0 Ã0 Ã0 Ã0 Ã0 Ã05ÃÂ#Ã0 Ã0 Ã0 Ã0 Ã0 Ã0 Ã4ž×èÔ Ã0 Ã0 Ã0 Ã0 Ã0 Ã0 ÓØvéå†ÑèšUƼFW€Ø¾};Æ-ïïïÇÚµkƒï[¶lÁÀÀÆÆÆ°~ýzô÷÷£»»»ÑÕg¦°``[À0ŒO%¶€íô7Ü'``[À0 Ûföaš€¦_^/OH×dyürÇ©OùMãñ¸cÇŒŒŒ`íÚµ¯ÎÎÎ`2ýýýضmFFF°yóæFWa˜:Áv€a€mÃ0>“Ù¶ ÓþpŸ€a€mÃ0l˜ÙI)‘±^ i–.Û²êS~Óx<Ž¡¯¯ýýýe·Ù¾};6lØ€ 6n¹å¨ªŠíÛ·cýúõnÃ05Âv€a€mÃ0>“Ù¶ ÓþpŸ€a€mÃ0lZ7ÿRK,—ò/¯Ä²Ù†iº^zãª:~™ãŠRy9ÅxžïñXjy½<*›Æãqdd¤`†B1ÃÃÃA___°¬»»k׮Ŏ;]}†aêÛ†a¶ ÃøLd Ø0Ìì€û Ãl †a;ÐHÊ¥,åxgç_|±Q\nå—‰û™ùïÅZWœî‚m—ö4ÍÒyK €@y°”8èy@,V>/d1ŽSþ¸mjuppkÖ¬Áš5kpñÅÄmÞ¿?Xºt)†‡‡]}†aêÛ†a¶ ÃøLd Ø0Ìì€û Ãl †a;P f™å‰2ËKé\.|Ѱ¡8è-§u¢öfç—›EåÑvFÑr3¿<ñæT(£­á§cÕœÑÊΙm—cjYå…ÇRËɳ±ÅÛ;µp{¾ ùÎGËÔ½Då]· …DZ±1twwömض 6àÆoÄàà`ÍeïÝ»[¶lÁ–-[ÝL†i(ظq#žzê©FW¥$Óià©§žÂÆK&£f˜ÙÄÆ±eËìÝ»·ÑU)ÉLô 6nÜØèf2LCÆÆq×]w5º*e™N[°gÏžÀÎ&<Ï Î§[nŠ+3« ÿÄ={ö4º*%™îçƒ»îº 7nœµ’ Cðó?0 ¶î˜a91Ιâö$H ‰^™2œü»™ßǃ/ÚÂzÂ^®ð¢2,áÝÊ å„ñ^“b›Šõ¾H‰º{®}©öó³wÝ=~ù¾.`ïËá¹™Œgù‚_±ÈŠpÏŸŠêîŸü÷ñáWO¾@x¢#w#Þÿð½³ï9ýœ¸:ðõû Ï‘ªP€ÿóþ»æ>AÓäx|ì±Ç ¾÷÷÷cppãf*L•åË—ãꫯ®¹†iu(Îy³v¨§ÓÀªU«°mÛ¶F7“aζmÛ088X·z½á>ÃL?k׮ŶmÛšZx›ÈPÞ–jY±bEÓõ "‘ìS]UUE:†$IÁvÉdJ–“H$`r¹\°Ìó<$ ˜ESo‹Ëff”'i¶>\qÅæŠb˜Ù?ðóÃð˜aóÚŸ;ðŸRËM©¢ýDÑΠå?“Ø1ay)“¶W„ý,„"%-#1Mʯó†buÈBù¶P†„P´s…wÚÆÎïïÂÏ2ùã©ùýIä4òŸ‡òe›ðÅAUéÜ8ð·OÛ¯-lëû€íÏ>ÓÿNad7øõòñçæ7o–¿Ç?®,,üCÀC¿ó—ÉÂqþ pï!€þ=º.:ðô~ÝÕ|½¸- üê~à+{Û–ûuù›#–_{¿Í)Ÿæ+ý¿ü°Û/€í¸øø>`¡ÇéÐ2`ÎO€¥»ûñðžÇP MãñXо¾>Œú½–š‰¸víÚFW•a˜i‚íÃ0Û†a|ŠmA»ÙEQÉd‚W:†ã8ˆÅb5•k,ËB&“A.—C.—C&“ëº5—Í03 ÷ †Ø0 3ûì@9OEôœ¢e@ÞÂw*Ë(*ÛEè½HÛ:eÊ¡0ªB’3ÔH䳄åj¾|Ú_‡/^*…@@¡xæÀc±)œkLXŽÙ_„”„:&òËMóúûE…6}ãàÇo =7I$Ýø(°ù´ÐK“BÀ>þàå ¯ Ï›à7g¶Ф‰|ŸÜìý ð‰cÀÍ»Âú^XJxþÍ|½æ<Ї.ñ?_uØ/çÛ«üJýüràŽåÀ›½FÁÜx8|pÅ!¿îCþâaà„›€]ž«^ÿ9ÏwÉ|a¡ N|ñE\ð+ sçq|wÍ œœ_\-M!±0P.ï[ì/ÿãA`HN½Ý¯ÜŽ…þ9ºúV`áí»Ñù•Ãxú/ã¬?ÿKÈNÿ&ðŠŸ;_ÀœÛÂðê¡£˜ÅA,ùàKRÆ…?úî9õT¬ù®ƒƒ}ÿïtýä'5ÝÇM!<®]»ƒƒƒ¡ž±}ûv\~ùåÁ² 6``` ˜É°uëVtvvlÃ0LkÂv€a€mÃ0>•Ø‚ÙddY®iI’J ‡š¦• Ù øž’ˆD"èééAooo vttŒ +.³m0M===ˆD"èêêB"‘ÃT÷ †Ø0 3ûìÀDÓ)Ü(! ‡¢0I#‰pbþDq¹_,³QöTô|¤0Ÿ”³ÐC(0RÈPÅÏ$@Ê$xû“…¤ž‡¸°/-F€ ¿íoüñ2î8+üN‚bÀÜÿÎóL¾÷{0° ˆÛ£eÀ×îöþƒ¿íÙ÷܃|AñÐ`áíÀ#'øõ¡§‹Ç/¾øBxnU'>ú2–lõ{üWÀ?_{%pீÕûíϾ:i¾ˆ£×çìòÀ ü÷åw÷Üø^Ï!$|ø§{±òÎÝX|ÝH&ðö'añg?‹O}j6n܃ûÞäâì‡ÆŸqø9ZÏ:ëŽröìy‡îY‹X,†§žú[¼bþ;ëÿäIXúãû°ë?Ãj88ô½—ñàO΃îJÈd2xì±c¸zåKâä“Ϩé>n á±»»7ÝtpñÅCUUlܸ›6mÂúõëƒí(÷µ×^‹k¯½¦i¢¿¿?˜ÙÀ0LëÂv€a€mÃ0>•Ø‚v´äH/ÊËÇk*WÓ4X–…žž$‰@$ËR¸®‹D"T*…\.‡l6 Ïó`ÆT Ã0‚¯Éd†aŒË5É0¥à>Ã0Û†af§(V•„E»h½SîA1×¢Z5ŠP4|!.!”Kùåüöäu¨Û[ð…²$ =©LÛ}/\NO1‰ðŸô?«Å›nÚ­_x@¡—$Œ=n§upÖÏ^@<_O*ßó€+¾ÖWðØýC€çF!yÎüÈGà:N;ìïsê÷wá÷Ÿý,ßûòÝÿ½ 8ûa?$½>ò3ÿ­ô§Á-Üsë·cîGüütî>ðFàkÿØñ} —9=î6¼ý6œõŸû!ÙÀâ ëî8Àÿ~8ðŸ§ÆNH²éϣ煿êU;qÉ%áÞsÀ/~ð<ùä“xøá‡‰Dpøðpè«þ„ÏK/=†¿é}]”ÄŠ÷àÊ+oÀ‡áÑGߌ9sNÆÂ…·ãº«âkG–Â4MœÞ¹ ï’\¼â¯ÇÞpË—_Ïóð›ßÌÁ‡?| ¾öµ#X¼øHM÷ð¼šö®#6lÀå—_¸CwwwsƒîììÄwÜ$»^·n]K†aJÃv€a€mÃ0>“Ù‚™´ÓᥗL&Ç-s‘H¤`™,Ë$©æc©ª ˲`YV jš†x<EQÆíC’´N–e¤Óé)[,?Ãu]X–]×§\3ûà>Ã0Û†af—ð&XNž|M ‘ „!We„aE_H”z+ÚðE:É{ò1ùåBoHZN¥š_OÞ€/<Àõ׊ˆbÆMXþÝïÎÇk_»8(B9ô…DFèìü6θm.¤·hHç—Û¶_þÎõŸaþyþ| »W_½÷Ü3йs—ÃóFqáË/Ãu]H’_Ûýûçà½gž”ê.`Ùè(Îû\¢@aVíÒi¿>ªpn%ã8ž›s ~ù8ðë_ÇO„>~ŠŒÝŸôŸ‚o|ã |§žz;4í:|ëËÇгu>úÑï¶ߌǪ:'žxn¾ù·$Ëü ‹Þò_èzõ{pß}—à£ý9 ÃÆe—­Â…jÐõ÷â?þ£‘H±˜C·ÿÎþÀ<õÔZ8ò~‰/É߀¢ßüf7\w!¾úÕîº+äu÷A½ùïñ *#•Z Û4MEQÊÔšháÑ¿qÂ|-QÉ6 ô&l†Ø0 ãS‰-h'; ªê¸Ð§‰DÑhÙl¶¦«”7ðNÛ¶alÛF6›'nªª EQÐÛÛ MÓ ( 4M›rŠ=*eYfGfJpŸ€a€mÃ0³Ç¸=©'Mž‹Æçf”„ï¶°<_(TòûP>E%¿_hÔ {”ƒ»,,'ÑÐ4Ë Å9z’¤P|Ñ4Ÿb>ŒßþvürE(S˲06ö^¼áܽþ¹°mDMþðmX¸ðþã?~…hô+Ð4 —¦Óø‹¿ø<óÌ×ð ctôsÁsÈܹs1w®ŠüǬ\éÂs@Q°{÷nœ²èØöÕð<_Ì”àÁ²$Ø6‹íæMY¨ùI•®+0‘NÇÎ$Ép¿ÒžÃ[ß*á²gâûß߃?üaÀ9Ø´é"¼õ­áÛßþ$“Id³ ³sr9ÀÏ~öÜyç÷°lÙK8ïØùþ}#LéßñW5ŠçcΜ ðÚ×. &±îÜ CHä°ìÈ+‘JÅáüíèýÿ.ÐÞûä·®‚,˰màÑGÏÃÐÐï|Ê%—!“ù2¬/íAì†0>¶ ÀJHpôhí÷qS Ã0 Ã0 Ã0ÍF)ïÄ™<6…'­¦®ëŽÛWQ”@Hìéé)Îuhh–eÁqX–…D"x<>¥z šµzo2 Ã0 Ã0L»Câ#‰„¢°èåß鳂У‘¼)tª_XŒ!Â\Œâ´Â$ ñº.àÚ€®nGÂ\)(쨈e•^¾dɬ_X(׃$IPßÃ0BUU躎ùó_0 óæýÉdº®cΜýX¹ò1¸®ŠåËUÄã;aš&6nü~±mŸ0ºp :EeY¸õÖÛ±jÕX¾|N>yCð|²ã¡¹èxö$H«\.‡­[ƒOަ$¡(À׿¾Cp]?üá\tÑ͸êªWBÓ€N8ŠK/½ —]ö$€ÕpžçáèÑã_þåSxË[.€¢¼_úÒ¥xñEccÿY>ùÉ‹ðÞ÷nE*õixÿ÷tݱ Àu8rä8”Ž­ø¿›7ãé} ¦ ¨«Çϼ}}'ç+ö]û›ÏB»Ç\ Ê?¼©Ï?‡È?;@:‡äµùk®ú×Áþ¹°>ú†‹×…vC²?û#zÞÒ iñ(Ê"<ÿgŸÁK‹ùðÅÕÐ9†a†a†a˜ñxù'új;ÊËhYÖ¸u•I‘š¦!™Lbhhñx¼lŽG¯Ìȃ]4åÙuÝ’¡]†a†a† ½É»C¦ºÂvfþE"!%2ÐòŸæhã$á •¥¦Š¡S]¸é¦£‘€/:– „BaOKQ*Ó‚ëJ¸ùæsø¹á{{{ý¶™ÀOúöì97Ýt'àg?û6^=ˆ VàK_:Ÿÿü¯ ( þæo¾×U±sg'öîíÄßýݽˆÅb¸ë®GqÏ3kqÍ5+qà ‡HP/½ô¿áyIìØñ>üàïžW.žû·øÛSþïÿatw?‹­ñ4^|ôQ$“Àk^ó8r¹öí‹áÛßÞ‹/}i|ÐÀ‘#Ï ‘H —Â÷¾w6žxbN:é]B6›Å•WžŠC‡¶Á¶uH ë:û·Û.xÆßŽá´ÓnÇ/y:@úý}ÐÞ¼€\€E¿ødYF2 ¨«vbù¼PÕü…éé,)7 é çúEQ /¿Þ‚°_í_Àœˆ"“t`$s—ByÝü`{ùß>¹s/ô÷®‹}ûO>¹¦û˜…G†a†a†a˜&Àó<ض]ðŠF£$© 'b©íìR1à{7ªª„UËH$ãÊ&\×E"‘€S45Y µ*–W.¦a(é8LÓ~•a†a†a˜¡×c¡÷#a!ô‚$¯EêaËRùÏ¢ð(î/ ëßQL5O‚¤ë»v-,YÇóñä“O–ÜÖóücˆŽã@–­üq\üû¿ •JÏ?úÑ…8xð¯ð±ý,˽÷¾€mßïÃI'Ý‘‘ùxè¡§ Ë2.<ç·'žè‹vïyÏ&ŒŽŽâÒK/… 't O?ý8Ž?ñr÷îÝP¿N_ü› >÷ïíÇüçŸÇßxÎ^µ‘×_«ü!¼ñ‡qÛmßÁá÷`éÒãØ¼ùi<üð!~y®ëâæXR)àƒ¼o~ó7‚25 H¥€N8ÚÑo ©iøö»ß¾eYx;váÑGÏÊŋýíyH¿þ‹Èd|ïDù §œ0íƒÀáÃp´ÓWxóqm%džyï9pçž™¿¨*`ÛÐH%>xÐ/_–DêñC>k¤_VÒ² ½u/ ÄI¢§ŸÆî•+kº‡9Ô*Ã0 Ã0 Ã0Là8"â?|á0“Éx'–ÚðC•"N#ŽÛG–e¤Óé’žº®Ã²,ôööBQ¸ù$+©”?ŒAÞ¶mÃ󼂒Åõïêê‚¢(pº®74t-Ã0 Ã0 Ã4. ס‡#à{>RU¾#…A¥uj¾ ú z6Æ‹Þ'¢Ô<Æ‹/Þ`©Ÿï°D°”|zÄ€ã/¾ˆÕ«‡ëžÿ÷ÿÄ{Þ³ ²,ú™®Çñâ‹âᇿÏóðÒKo|à§á‚ >½<€ÈßÞ`ðàƒ]8å”?âbøèG¿ ï÷OãO»®Ä•WîÂå—¿ŠrÞüfŽüéOÀw¿ ¨ê‰NÄÇÞ¶¸%ç?³0ÿíg.TUÆ 7œƒÓ}'CŒŽž…{ï=EqptïQHçž‹5óçã]Û?ˆÌý Þ¼ø‡8²o1þïÿ÷6üÝ.†ë¯yÍqæ™s¡ªÀ5ßü&N}î9\wÝ퀢¡×T I'úª¦a@•e¸o€ç-î½p^ÀÂÛoG2ó>¸‘¿€ñÞß@úÙÖnÿD:Ô¤-Ô®>˜õOr4 Y×áןXíúÛ›&Ô¼¬ôÞËò7€ D£Ð†V"q+ ¾ó$à6Lº5b"ú@gxÑ4 °m¨×ŸÇÝXßÃKK–ÔìñÈÂ#Ã0 Ã0 Ã0LƒÉd2uÙ.™LŽö$IB&“뺀`RÏÃL&ä'|‘DÊd2 MÓ„<,¥Ã§¦R)èº>év Ã0 Ã0 3›pá{-zÅBòbt„ïôYBèÙH¹©×/†Y-b|“H(~¤(:Õ0<Ká8¾žEȲ/D‡U]xô(:rYØöø¯ÿz££i躎sÎYˆ®®.d³Ú5#~O>©âÔSwá¾ûVâšk¼óÙ_ããÿ,n¾ˆÇý«^x!.¼PÇгàO8áø¯±páxì±Ë ŽÉø^˜–å{Ú?‹—^‰h€ý×?†ç]™Ò⟵´¹›ßp~ýÂqÜz뙸úôoâðKÀàõ×cù ]öSHÝ+ðýûýáË€ùz˜w½sçží{O>ÿ8’O>Œ³é„D£p÷<½÷AÀü¹¯Æãþ@.dÀ0B¥véR˜ßîDüu«çN?­i¬oƒºv/ä÷˾ð˜†SÏþð¡FÄ¿ ŠI–¡|c7”_â—›¿PPlÛþþª HÔÎüÙQ]áÅÔuÈ矬8 Pì¿øâšïo†a†a†af²,„J­„‰„ÂJED†a†a¦¡ˆ(Á÷Zôà ‡®° †L•á‹‹  Œ¥¼Eh[Ç ó0{0R8T±ë~äÈ‘²õ—$`çΤ± ¿¿rÏùعä~ð¦7]×ýÄb1xÞûðÈ#Hbõêǃ”×\ó"žyæó8å”7à²ËÎÄ¢§áèOo¿¸ÿøuH&)Jh–ì¸ÙƧÎKáñÓ·çÛ‘€®'aY6E…ãøhÁúÉ›±âåUøˆã@ÚµƒÛ/Á•¿5`ŸsE» ½z>ðÌ¿âŽ}·ßÞ uåXÿÚ£¸ð¿ïIJܓˆ,¸÷úm}øàП œx"´¾%°ï]ìÙž,]b1(‹ üüÀëò'S’ÓD|Ñi¸XÇ|ñÉ]@yg7È«¥ž˜&”=+€;ŸÞÿ!{Iòs1zçùºbÄ5¡ª€ªB)Ϋ™JÑ.á1ó\úøuÐvm¯i‘Ÿûò¹6ks<2 Ã0 Ã0 Ã0 Ã0 Ã0 ÃÌ $0ŠžŽrÑz~¨T'eæt=K¥`'Å¢4îð¼ð%räÈ,[–‚ª®£üŽ÷Ý÷{|âŸ/ÃÃ)‹§¼® ™LB×uìÞ}.½ôX¹r7^|ñtÿkøkxúþ_ÚgãG?Ú‹}ûöÁ4M<»ãû¸!žÃ‘#›ñ¯Z€/Á…l󿆱nüÛÓÃW ãw£¯Æ®Ÿþžçaog'þ¹÷ÿafå^á«rš$“N|öâ«€ÑQÀu!ÿà(»ï„ãæO¢®ûª_>”©,xíkýu$0ær¾7c2é—$_hTU(Šà•(ËþY†zæS.=?<Ùùý‚à5EB" †Å•å‚àL’‰cJ°ðÈ0 Ó¢¸®›WN9"‘±§§‰D===ˆD"0ó1†a†afI’&Í!É0 Ã0 Ã0퉋ÅxE#a 4…£,,Sø{*–ƒ„ÇbñQ׃ ¬[·]]²€gŸ=Ã0`’I_¼ºõÖ•xä‘£ˆF£eoÿ'¼zÑ",[6Šûï¿0MlýøÚמ Ê´,?ı/|W]õF¸.ðËOÄ} —º÷Þ|3~ó›† ·Áq€Ïݼ 7CÆ“Ÿþ4àë#ŽPð–§~ŠÁ†ap¼xà»w_ï¤óáX¥ÉøðÓ0öÓŸB’|¡ô¼óÎÃÊ•+!åe×g¿õ ÀÇŸy#þíÀzÚÁ#wÞ‰!Çe©†°k×.œpÂn|íðaܱ|9®€…÷.¼ç.ÂÂe¯†êy8ûì³1„^¼ù¬?>ô¡! ™LâÓ0qzO^ï[¹ç=ú(n:zH¥àä.‚´x|>KmÓ2¨×v“$ßëQUý¬š eÓEᆲ è:Ôwž4¥{CQòš¢ª^R‚K^Ãҷܸo£ÆƒYxd†irHTŒÅbH$Ð4 ñx™LÙl²,#‰†††N§‘L&1::Šx<)ÿÇÅÂTkB¢aÛv @wtt §§¦i¢··ˆÅb|­†aZ²ëůH$Rð°HÊ‘H$ÐÑÑQ°Ìó<Äb1tuuL`*.›a†a†a˜úRÎãÑ-z÷dP(8R^ÇbJ‰‘ÅhÚøš;wî„ãøBc©í5­püðá‡`Õªk±k×B=ºÉd¶mãàÁùX½úy¬\y'yä†UUñÐÏÂß¼ôeüÅIwãm¯|÷8΃þ³ÉÓ·ÜË2qÉ%c¸ï¾gðÄï~\IÂ+øCH’á÷ã+#¯Ã(Pó[ïñcÅü,ðÑž ÀÞÏ7É lˆìƒ =ïx>=w..½ôRH>óšçW^y%Ôx²,™ ^y~7€Žõû·Á¹·mROäŽ'JœEšæÀ0Œ‚¥åB•åó'–½?J ‰ ¸.Dqš-G¤å‰|ÒÏÉ¢âÕëù…Ç6ÆqH`˜‡<és*•‚®ëPUªªB’$¤Óiär9¤Óiÿ´J ¸à¦iÂó<†üIaÇÇuÝOD©lÙMˆaH$°(÷xž7NXŒF£Á´eYPU™L¹\CCCÁ»çyèíí­è8 Ã0LsAyé•N§á8N͹š ÀeYÁÿF.—C&“ ¶3 Ã0 Ã0 3=ˆ¡TÝ¢evÑ»‚Âpªâ÷‰(§]/?é$ß#ïÈ‘#⣪úÞŽo~óQôöJ°mžçá¼ó^ÄK/ý ]4ŠG9O=5ؽ{%–.}}}·C–¾¾¾`òcò¢exý¡C°>Ÿúΰ¡âõ ïÅž={°â‹_Ä{wüî¾ûnÌûÝ6¤ÅÇááC‡pºçaîÜ1ƒŠ®“ŸDoGöuuáWˆáº9ßAnî{±7ûgPUš¦AÉfñìU›áBFÏà—_Ʋ÷¼/^s pÖYi÷#H&“A#¯¼òTÀ™þ0Ž®[UUáy®™騳cŒ®ëÂ0 8ŽS0>éy,Ë‚®ŠtžçÁuݲš¡ëº%EFr6°‹r–ØðLJEq˜¢ßY–×uFáºn!ϲ,X–ŒKÆb±²^“®ëÖmœu^]Jafº©%I‚çyÁ{$ >“ës&“i)Ñaÿ7FaÛv 6Ö‚$Ip§)s-‘ˆF’‰D"ø“ó<²,ˆº®Ã4Í`™ªª°mÛïp4‰£‰¢(ÁùŽÅbùN‰ŽX,†h4l¯iZp}IT%ûM­„mÛ^CEQN§a¢Ñ($IB*•‚ã8°, Z>™´,˸÷Þ{qúé§7út1 Ã0¥ò":ŽSvVk¥Pøu±lUUÇ+éÁ¶Ô-Mvœèÿ‰þ×d¹’a†a†a†i?¼üËDi1QìikÂçÉzÐ’4^`t]€!ÄnúO~ÒåËŸÂæÍK¡ª‹ï<×õ_/¼°0DŽãÀ}à‡øä‡?Œƒ'ÇØØ“èì¼0KºpŬxõ«±rå˜?ÿèèxð`GÎúãqÚ¢]øÙ//B÷¼¥8åø˜÷ÛßâšÃ‡Á­x7à_ |eþ6¾ø¼xÍ5¸â{.^sþÝøÚo6+V`Ùó9>çûío‘øà~ü`Ûœ²ëiüí7SAt7z¼8á A lÛùw¡~Άreáó‹¦Ù¬ @ÆÂ+¯„”‡ÛùÀxyáW‚±;Ã0 Ë2Ç ÞIƒ±,+ ]×E<î¾%á/:óÐ8¦mÛ$)Øž Ç*Ÿž¹è;š¦ŒŸ’CÕ‡ˆÅb"&?’hi$I‚aH¥RXJÇ4M–eáºë®«ù~gÇ$‘Ha’èsOOz{{øʪªbtt4¸©†i b±XFÓóFGG¡ë:²Ù,R©LÓD*•B6› <5E™ï>šDðä½H uJކʎ¾g2™ îÐÐPðNe“7Š,ËH¥RÈd2ãh+Žãñ8FGG¡i¢Ñ(Ǧi~§1?cë׿þ5vîÜ9óa†™2µ v’$•œÕªi2™LÙýÇ ž3迚DHÇq‚å‘H]]]a{:::`F°?…v%(7uññ:::8d8Ã0 Ã0 ÓVؽ]B¡‘FzÄð©´N”°"??b1ºiY~y’/̉]ë¾¾ïãàÁïâüóO,+¢³óG±ü4>=]1ÿ·¿Ç@JEOσxæ±û1’Îaõ©·cÝo¾ƒsO; ßÙ¶™L?øÁ ÂƦlÇǾ¹¾wä³sÇ0ïØ'pîáÀS:žÀü¹ËÈX²d ½| Þµr7àUo?à˜ùåpÞò <2v&”*x6RU!=¢ªú –$È—v##EÇ'³„ðl•ÁjY~úÐCX2çÉÀãÏ4M˜¦ ×uƒ1Gz'a¼ )%9xžW0kš& ÀišÑÜÄcÐqÄñMŠxFÏKQ@¤ç)E‘Òó<Äãññ2CUU¤Ói˜¦‰X,Vð¬Fƒ(tÿøÇñï|§¦{ž=[ r‹M§ÓH$°m™L&¸iu]ÀŸ•ÜŒbÃ0ã¡?*ÀL¥R¿çZ Oh‚¼¢ëí)zcÓÌjý ’×ý¹Ò ÑCPœýCŸu]&V¾—Ífašf  Õíœ$S[ÈëDUÕïF-È©IëdY.èÑöä¡8·£®ë%=T1888-Çf†i7:::Éd`E)ðtñx‘H™LfÜ{¹}J ~4¹… ¾Añ¬Ù©¢iZ jšV²}¢¾@4…ªªÁñ‰¢Ñ(²ÙlðKÿ}†a ‹AUÕà?Ï4M¤Óé Í½½½÷%MŽ¡‡aÀï+(ŠÒ4Q †a†a¦VŠs9Jð…G¡7#åuœÛ…6òl,~dÈkpH$zôøŸÿy;ŽY¬'Áëá‡7axxàË_~§öŸøèGÿ+¼ëŽîÆ?\ûV|âî‹ñ¹[žGç®+±¸³«Æ~…ŸþWkö¯ÃöíoÁñãã}¸_Ø·ÿÕÝC#¿‚Šç`uñØÂ÷a÷ÜGðbG6wÞŒ+;~û_8®:眣@Ó4tÚ6.}÷jà‡À•Wžƒ‹ÔsüJkTÉ+½zÙ¸ó<ÏC,æÏ$ÒuqJz\gèODQ”À ŽòBÒ±kiÍ"‘BȲ I’H$‚0kôÇǧ$–²u4˜JÇH¥Ru9_¶m#‹Áóˆø™a†a†aÚâ¸#4R/ær¬$Þ‡¢øy ÊÎ^jøßqÓ††rüü‹;î»2ŽÃ… ×>ýéÿÁã[8|ø}X¼x1^ÝíâŽÛÎÀikxöX·ÿþoÿ†•óþ ÿsøÐ`ÁS!°x)Ä𚣌áR˜8’lâç® uÉ|lnö>sO|\ü&\”ÍbÕ.ÆØŠ+p×zq©·ñx_Ð@éô¡(¡È ðZê|äKÿ®ü *~Ž(åZ=kQxÕÍùOÉd2×4 Éd2x–"-†¼ I $APL“AãŸt,ò~¤qÆH$MÓ‚ œ4vKcT·X,6NpŸÓdY†®ëp§àÙ.NÛˆËu]/x©4ö‡?ü!^÷º×U~“—€…Ç&Bt±%!ÀY‡*­€IDAT0Œ`0 â 5ä]Ä0LsB±·iF yõÕú£ŒF£e9ü£™3dc&‚fìˆÞˆº3‹ä$~ú³¥æµzl”‚r!Ú¶H$Çq‚¦µ`F0Hð-@.öfd†a˜jQUuœ'¤èeXËÿ =L¡W>ýg‹"A­ârY–‘Éd‚\Ì¥B‚‹Ï“‰®š¦Á¶íà!™¤†a†a¦Ý°á{;¿_|¤ž³ã„aREJdN€$ùz[ñ:ER)ßÛqß¾xž¿í¿êÀo´` ŽÅ‹`çθá†Â0F±ö¤Ç°¯ ¸—àèë yv> ÐÙÙ‰‹ŸÆÿàp àØPĘÐñrG’¹l¨òÏÿç?ÄâgŽcÙ“£8ë¬XõùÏã¸$áTÏÃBYûà]O?VZ–E)éÕ Ê%s“ŽU~Â+xvRU5ˆÆbYVžTŒ*IÏQ´-9]P>Fzw]7x΢ç¤L&8…‘p(Fs£(h$rRÔ´X,ˆƒ–JŠp&BcqT51j\%“Yi|ú駟ƱcS8×%`á± %œnÚT*MÓ7ÝZ¼wf*÷3óÐ}Cî×$V“‘bšú}[–…T*Uñ@-ȲŒx<äI”$))/ýÁP(Vz‰aßhL"‘’,ëº^àÝ@ПïLÜ“”Û¶««+ø#P­RÜ|réR± Ã0 3“$“ÉàY¡š <4¹QÜ—þ›5MCOOO‚§˜éþ¤IPžçÁ4ÍÀ ’a†a†aÚ/ÿŠÃåüËC(B&¾pXÜõŸÈ«±X¨³, +ÜNU¿ù—ßá­§¼¯œs§¯zßðxôS—áÑÝ+ñ­…»pû[ޅΉÑß…úBÎ8ã2¸ÛŸ÷Ë‘áÂ…ŒKaå¿ó:_Æ•‹þ‰g“ø^çÛðˆrdYÆùy¯ûÇÐÓÓE9/¨@^ü æÍä)M$ eyÅÕrô¢gÒbÄñѰ ¾vCãŽôLE¡YÉ¡LŒú"RœI7i|ß¿~V Bþ3! ’¥ÆX'wêsäÅ_\sz¦9õ»Dõcll¬lã¶lÙ‚‹/¾kÖ¬ÁæÍ›122ÒèêV G½½½p]™LCCCÁ }2™¬KÈÀbGW˜á–š*Á4-†aq é¾¡Ó‘H$È­Ó´³ Ê 5ƒlä¨ëzÉ<ˆ4k†S‚bš¥“J¥0:: Y–ÑÛÛÄE6›-ûV.¿àtABgq~¬©`š&zzz rT1£mÃ0•SÎÌ; æO®vÊGRÌDeʲ<î?ÔóÇx<Ž¡¡¡’ÞÓ rå ?Åt: Ó4á8²ÙlpÑŸ]*• &I‡ m(¼AÉž+Åu]Äãñq¡î˜ÆÐ®¶€a˜©QÊ´£ œâ+Ž{à-µ]¹>==üRXU± Ê¿\ꡘDAqRMœúð‡?äV&¨ÿ0UñP×õ ,<2Á}†a¶ Ã4¯0DŠ–Qï[ «JÈðÅFz¯„r ¿ó9H$BÁQ×L8á„£xÏ’/cÑ¢axž‡[nùöïßEq±jÕWð¿×Þ‡W½ô^~î9œà‘o|Àƪ#‹ñp>øë%ï;€³Þw%¸ðBœvÚa@çç?xÝ'Þ…~îoð¡Óï‚4o^AŠ8í´EX´hѸ:ËgÌ–-«üOƒvR SXYÍ3M±.TN'š©¨rõ éB­nݺû÷ï/¹nûöíØ°a6lظå–[ ª*¶oߎõë×7ºêSœDt:!Q€r´PîÊ)G3™§»ÕB$ªªÎ˜@3xžÏóÆ.Êñ)&~¥\Ÿ²,chh²,—õ.£\wÑh–eוrßÑÌ‹“O>¹Ñ§`BÚÕ˜¦üöší~ÿ5Mƒëº%EÅVøs£Øç¦iV•'ªšASfzhW[À0ÌÔ(g ÚÑ8ŽƒH¤p¸BQd2™‚ÿåRÛ@.—+Yn:F4·,ËýN ÉžH$ÁÒó¼ šÉd‰D`YVZ(™LNù¹BÓ4†Á¹™ á>Ã0Û†ašÛx“|WPR•–ËZåt.YöC¦ŠçÓP^Þ‰¯îòðµWœžUàAÂIˆ@Óâp]‹n¾—¸*üøÇû ê²ÿò?Ç %‚+* PjޤÔÓìÛ7í×¥h¥ñʦòx†išøÜç>WrÝÈÈúúú‚eÝÝÝX»v-vìØÑèªWL"‘@, rºÍ²,Ã4M$‰ >ðÐÐ2™ 4M+ëýæy¢ÑèŒ{ǹ®‹H$‚ŽŽ†EQÆyé9Ž3.´S+@᩺ºº‰D‚üyF‘H$ï2šÇϳJgXPB\×uƒA&*'NcõêÕ>eig;`F+¼=EZ9Ä(M²ˆÅb°m{Ê6̶í–XÛv¶ ÃTN9[ÐŽv “É —Ë{ ü/•ÛŽDÇd29N€”$ ™L&èSÒ+›ÍNøL¢ë:²Ù,R©R©²Ùl *Šô-i8±*—Ë+›")ˆ(Š‚\.WUþJfvÀ}†a¶ ôž08ðÅE,åõXŒç•UµT¨U"8yÉs$ÀqlôööâÑGÅӮŋŸÁ{_ú/À·¿ým,:r΋ÿ>x|÷ùwÃ@7¿ü+ü÷Â>H\}²óÎ,³uœ—¢gœqFø%¦¥ü,Ê ±©ïYõC«rmZ•V›Æãqll ŸùÌg ë:Ö®];n=Íd,]ºÃÃÖýâ‹/â÷¿ÿ=–.]Z²ì™"‘HÀ4ÍqƒÓ®ë°m®ë! 1ìRñÀ-'Ϲr³¡iPŸÚDûL”Ÿ’°RøOALdÊGB›,Ëð<½½½$© ÏM*•š– „ųË'ƒ<3™ \× Ä?ª3çÑÑQD"‘ Mº®Ã²,d³Ùº>š¦á|i–¼ªªÁÈÈH~6Ló1vðg ¢»»ÝÝÝ3Ú6úý5kxÒvBUU ¡··7ð.®”b{ÖLØ(ì¬ÚÜüK‚Ÿ˜¼ -ð;°N~½’ßÖptp_;|s»ºݬ’ÌDŸ Ôþ 3›ÃŽ;°k×®FWeÂ:–³µö Ž9‚ÁÁÁ†?Ì4Õä‘$©¬89Ñ:¦5ÆþýûqäÈ‘FW¥$Óý|°k×. bݺuèììlts¦a â÷¿ÿ=^|ñÅFW¥$ü|À0ÓÖgÌÐ@(8ÚðÇd4øã16B±Ñqü”…ÅÝsËòÅdž¦ ˆÃí–eaùòËðLG¯zÅ|,{ÕN$1ܳp¾qòaôp†çêa‹×_…ûï¯}aÖÁÁŠC‡p,XÐ0š¯Ñ¼eË€=À™gž‰·þY{öœ‡‡Z IBžàºå…ÑRHRéu’ä·“i.†‡‡ëÒ'háÑ4M,]º›6mª{ÙGÅðð0–,YÒ°Û¶ƒðª3= ÇÇáy^ D4P‰D ilÛF&“ Â{’ðFƒHâ`E, ò§išY–ƒ<„ñx<Ø–DÀ4]×E6›E"‘DHB×õq3žS©t]‡çyA®ºD"D"1-Âc, <¦(ÌT±XDõö<¦iÂó¼ÀC³§§'8¿Ô6 ‘Jç?“Éùy,Ëwnk%›Íž[T÷‘‘ âСCu?gõ`:í:tƒƒƒèëë›qá±øZ0Ó ýÎÈ>‘í( x·ýæ7¸ä÷ކßA,gm<áâö“ Hë$±|Z~½%¬7 ˆ^~’_.¢#ì¬RH+¿ŒP˜¤°ÿrþX"§÷ôà¹%KpÕóÏÏô¥©ˆ™èìÛ·˜YÍþýû188ØÔÂãtÚi4ÃÌVvìØ‘‘‘¦§ûù€„Çîîn™Y õ šõwÀÏ 3ýð˜aíc†N™e*Âñ$q|&‘ð½+ üA¡Jc±P´m+V¬À=¹‹ð›ì2Ìÿã‚ØCç@Á˜šª†¹$+¥”ð¨(S/‡™~vìØááášûM!<b``wÜqÇ´”¿dÉ\vÙe ë@xž‡X,†x<ÞÐÁ’$!N>GGGƒð¦Š¢ ÂuÝ‚p°ñx±X †a ™L!#`(ËÙ0ŒÀ£3‘HÀ0Œ ä§išèBžŽj4›ÍV$Æ×;!d5M«› +zl& ȲŒžžž’^Sñx<ð&xš¦x·Mt=ÈÛqºrÚßo}}}èëë«h¦ÏL3ÝvV¬Xþþþm—ëºe½Š™úC‚œÿþ÷<P|xÿ~¬ÎÛ÷H¬sòû->rGÞóä>ô!…A=øEš©æäEKÚN‚ŸP¼ØjHÂ>$ªùï4w,–_®åŸÌ—© û92“{Byvþ•Aèéˆü2•ö_±‘Ä“üc£/Ù8Ú½OÀ0ÍBww7úûû±eË–FW¥$Óm –-[6ã}‚ɈD"A.ÅRPøÔŽŽŽÉÏÌ(Òl}>¸ä’KšÎ0L#èïïÇàà ]•qðóÃÌ …aM1ÎÉÌZÍÐøÈ¿2q|,+íñ¸rånØö©Áw?Â^?ÿùå€GY ÛöÇ«wíúO<`é ßÀKû_¼cçc:Î ÿZë9Ñ4 ªª¢§§AHÖjéíí ¼0‹Û^ê\ñLóúÑ.v€ÂíRžMI’Éd¦åX¥DA1§[ôøâ˜_¤Å<ê)Å;ÈÒù2ÁcaXOK¨ý¢õüú˜ð=‰P¸#qÒ.ª‰fTn©ˆ ª°ŽDA% únøù¸_’€HoÊO zšð<B;Žƒt:x£ Ë©þjÑz(7‚®Ádf­'O×—v± ÃÔÆd¶ íM^š¬YJ˜t'ˆ,RJ}P®üJÊ`˜™„û Ãl ¦ Š&¦Hš¨à8E ¢ºQÊ fëdÚƒV³âX–†p¬Œ¿;%Ü"Ï8ã7øùÏ/Ç?ü÷qÙeï…çyxæ™Pœ3g?vìøàèþ‹Ñ‰ÓpäÈÍÖañè(ž€Š_—ð[8øõ>\ÀV,~Ÿ;œÆ9où¼E‡EÁ¥õyòÉgŒ«‡þç!ÿî»>>£çišBx,—´UT|#300€Ë/¿غu+:;;qùå—7º %!O¼V+¥^"J=ÏyTÆb±À±Hxm›ëÕJ´‹p]7¸£ÐÃõ _X³á‹j|ñŒÂp’7ͪ*†rRëÞ¢uB¡CŠzzŠŒ±ü»(ï“àGaCM¡¬d~Ya(PO¨ “äá(z ¡Ç`p®QÞ3 q÷ݸ?Ú¼MéX„a`\é`ký3Ë2D»Ø†aj£[0[í€jÕqœ MàOîs§ ÅE`¡”¿\×uttt ™LibÝtMšb˜©À}†a¶!F\š ”I–eضD-K&“p'×pªª"™L¢··7x^¦cŠÛxžUU˦™±, š>I'‰º8$0³ƒVµ6üIïâ8]%.,äÙxÏ= pî¹á8ººžÁܹ{Ð×·÷Þ»¿úÕùïÞ3pzÞ‰Ë1ˆ9°q †°.–ø(ÜCÀÙï~äÛ\¤ÏÛ‚Þ¾ŒSÎ?ñKýiññ8`YÀÎãóùÉW¯ƒ~ë_ƒ…G¦šBx¬”þþ~\ýõ¸öÚkÑÙÙ‰‘‘ô÷÷7eòkÏó‚?ÑV ¯ØjȲ̼ªêq§§¹iF;àºn³Ó¶mxž×u§ôûÁÙDÙ+_à’á‹v&Âü‚f~{øT†Ò¤»˜~ ó’h'ŠwBOFZV‚:KÉs: …I-únm©ôW|&'“éÜOæM9]9DrkÑŒ¶€a˜™¥Ýì€$Ip]·džG ÃZL, ?OdñD¼h4 ÏóÍf!Ë2 Ã@, MÓ òÀ;ŽƒÞÞ^˜¦Éÿ‹LËÐn¶€a˜ê˜m¶À²¬À QËr‰D@øLLã²,)–ìÒqù »‘H’$QÌdYF, ú $LÆãqtuu@p,Šà@é• ÃÆHi‰––e!™LÂuÝ ¾4®Bbf¹ ¦iBÓ4ÇcmJekWŽÍMFñd‚Ç;†?üáˆ<ø ö¿ê1œúò)¸÷^¿Ä;ß _ÁÇÙs~õ8pDàO Ü‹N_HkþüÏ‘º-†Ä® ÊíƒîµlÐÖ5˜*™áqddÃÃÃèìì¬:9óc=6nYgg'î¸ãŽ ±åºuëš¶adYæxç3å ¬±“Ã4­b,Ë =Ï+ÈZ úÓ…Ö´¾GË)li¡ç!…ìÔ])ÞN.z§mÕÛÉ%ö«•™°ŒbgÍ)»Â¶mض ×u f^2ÍG«Ø†a¦—b[0£v xLþ0)”¹ü‹èÂ2ãÃý9Óà_$wøR^ˆ4`—N§ƒÿ¼T*…ÞÞÞ‚mlÛDG ôŠ4M¿rbj¼¬%ŠÃL'Ü'`˜¶`¢Ð§®ë“aOÉ“‘DCšœošf0)Šyô=#‹A×õ‚±LZÇ¡iZðìL‘ —ËÁó¼À«ÑqÄb1D£Ñ`›x<Œ•†LÖ6M3ËÓu¦iâ m[œ‰Îëº0 cÒ±—D"UUÇyb&‰@ô¬&Ô÷¹ÏÕ5‰kµbæLAaûêb‘© Y–KŠ •H$`ÛvÙü–LóÑLvÀuÝ‚ÙxÉdrÜŒ;ÊG(Á»$/F „¢£¼2†0´ª(‹s×vrÈš<8šjÛ6âñx0 “iMšÉ0 ÓÚÉL%Ì)M|ÊŠ'Ñ‘€H"#!F áœåL»ÐN¶€a˜êi%[P*TªmÛˆÅbð‰Ž]Dæ,Ë‚¢(AßÀó¼ D;E@Ñu=ÈYªþyJ(2ãñxÐÀÖ Š ²,C×u¸® Ó4 Úìyzzz‚è ‚)ÔÇ1 #;ÅúÒ1<σa°,kœ€I!ëmÛÄZ˲ ¼;i<&ˆ‘àJí#ïL1_æd}+*‹¼=mÛŽ-IRAYLu4ÒÈÓ Ù“lëºþ‹n sÛÿsêûñ÷»¿ŽLÆ¿o|øOX‚·bÅñÇñz¸¸ ö;Wàë¸à„ƒÀA`Þ›N@÷ÿ<‘Ü«oX>7,[æ$•n[yΓåÕ•7ˆt˜*©Zxܲe ¶nÝŠõë×?æ‘‘ÜxãX»v-úûû166†Ï|æ3زe ¶mÛÖè¶Î¦iÂ0Œ’ÖÌô"Îæš Ô sá0ÌT ¯9òœ+~pðàç8¤¥6B±‘ (ä(uN¨€…ñaF™É¡02’$$ô€¥i†††ØN3 Ã0•Qn"½:É6•?¨šÉ&ΔëÓ ]©°® Ã0 ÃL?”¢)•J,'aPQÄb±@`#Ë4M(ŠV$ŽQxÔÉDê'ÈUîù8™L–\7‘§ yâ8[2™ ÆLzzzày^-ŽP±<3©Š¢ ⥽…Ihi,@àYÙÛÛ䣤ý]×…ªªA¸Y]×aÛ6z{{ƒòÅscFÁwÏó (JàÍIÓIL%' 1l> ¦iL£c“—g¹~^µšÌÌ Áw,BoGêr;ßu×<üð ÐÜJÝ7ï¹ðÔSsîíÄiP°€ â8tÄÅ=x%þ쓱øg¯ÃÒw¿#?y5âqàK_Ú,Y‚®}ûuS=xæÀ1ðíÃÌU cccغu+úûû±iÓ¦`ùÀÀà–[n)Høºyóf ×Õë±Y1 º®sؾ †‰˜Š˜@€JÃb2ŒuT©ƒYª£ƒ/$!ÌåHáS'Cƒï!ÉòXu¨ª EQN§ƒ™cš¦{¸c†a˜Vƒ¹Do‰â©bxUqðJ ¹Æ0 Ã0ÌÌcF :ŽŒ%X–…T*MÓ‚ð¥ôÿ>::üSêÀî­&ä'•;™ˆU®lËQjrñxµG EŠÇêHD¤º“X§( R©"‘âñ8t]/(“¼"©ïDc8©Tª  I’OK:6•Etttçž"Uˆõ¤k+Ë2LÓ „Uºf49Z–ehšˆ«4–‰DÐÛÛܶm¡ñIØ,uÝHœ¥k+¶Ÿ¾‹ Å°ÊÔŽ„pÜÏuÏ/<8p±ØB˜f:Ã]8+7„¡bu~Û«!a!ì€Rˆ!†Nœ3G%àð¹çâÍþ0Vá8dyr¹eÀ™+üóV.=©â|“ S+U ;vìlذ¡`9‰‹¢è¸~ýz¾7d» ê€ó:6òf*ž%5S*† ¼IÔYÂN³‡0¬ª _<œjf »Ê¾¸ÕA³)Ù›™a†iv$I‚ëºe½i0ŒPU’$xK$…É()‡“¸ å]âI8 Ã0 3óG <žç!‹@HøbV2™,ðâ+.«Úç]êwT‹$IXW SõÜ£Ô6¢èJã°’$•M{E¢œ®ëˆD"¡[©±m£££¶]Ü·˜x<Ô©¸¿eÛvÏ›BºŸ‡t: ˲‘”„Ëh4” à¾ï+)w7àO:SU5H3Ež³Ž„ÉD"·¼å-5]ÓÙ y9êðÇ-a™,ûÂc1§žº ûöÍ &Ê;ŽƒááÓ.\¿hKŽXˆ_t®|Ð… `2.|±£)¼jþËÿx¼ËÇnüå_Îç眳В*Ø IâgÀ5>]Ì, *á‘´'g,ð€it[§ ÓI³2™ Ïn º®á *€),ÃLÊXœ|¢ùw¾ØXËƾ¸ÕÃáG†a˜VòýÐ`T1Å9›$IB&“A$)È/TL:F4EWWWî‹<hÀŠa†a˜úS<ÑÇólݺcccø¸}ûvÀºuë ¶%Á±½]×Eooo0³$“ɰ€Õ`èw*ŸZ:jÌì…<(9¹ØáŒÁŸÕ$ßéT«Uà© Ã0 ÓþP¨®ÉÈårÁgEQÍfƒ& é%BÛÐ,ËÁ–XÖTëÁ0 Ã0LylÛ†išÐ4­ÀëŒD#MÓ`\×…¢(Ð4 ¦i–MTNä²m»¦ÈkµNÖ­eÿZ<&I´­¦íõp¡©Se*ç«8ü,å¤{h²»”Ó›PU5ˆÖgÛ6’ÉdpI^‘‘H„óHN‚ ßÑ`¢ÇâH³ãLRžp] x.zÅž9¸]}_„7øNyå+1òÜs8묳?úÑxè¡K€}û,ó÷Îß2ž—÷²,¾Ž<ÎÌsªÙ‰ÄEñ¡–ò;RhÕâåÅ‚d;@³F²Ù,FGGYtl(fy%†Á¡V™ª0 #˜¥(vÆðÃ)dò/öVd†™YĹG•ÌC*Õ²"8 ÓH<ÏCGGG0‰ŽR” ¹¦ªjz•a†a˜é…Æ¥‰z{{ÑÕÕŒ£ŠàÉ£M×õ²aBKQ¯ ôµö ªñj‡«Å[À¸‰ZS¥ÒqÇz_¼î“ÝÅ×–ú‹…ñ§þa2™„ªª¸êª«¸¿8 6ü±¿b*ýUŠ9ZÀuuxžø4H°¡â]K–à•GžÁ¾—;±`Á ØsÎÀ±—~Y–qÒI'!™¾óK ,Üéå½…õPý—,c¼›%_[f†¨JxìììĦM›°uëV\{íµ¸öÚkÇ…YÆ7Þˆ­[·bÓ¦Mã²¶¶m³§\RiçÅu]$ èºÎÂ#S1gß²¬‚pf€^ø4|/G ì­È0 3Ó8N(&ZÖäÛW"<–0ÅåâØCQ§ʧԫ|¦µ‘$ ©T ‘H‘H½½½0 ƒs72 Ã0Là8t]‡$IÐ4 š¦xèÑx"…Z­…VÓš,OâDÔ*@Mab©îµˆsµ†©­µî@yáòä“OnHÝZ ahUÀ"§"EÖàço8 Üqà–tvb'ä~w»æÏÇk^ó<òè£ÁµsÀ9ºÊ™c㎑Éä5Fg7ÿª• o°™ÂË×?QŸâª ¿¿7Ýt–.]Š¥K—bÓ¦MèïïÖoٲ㖷ÅÂÓˆI¦'‚F'*÷Ù²üzc@r‚xÜ®[¾>S©}Üem-(o†Á*GqØ÷v ŒiÏö1 Ã0í åÇóM8/²PßBJ5¿ò7I¡(¨ïJ~;/¿M:_¦–¯‡ß;1ž_ŸÌ×K<TÏd~{]¨+'ßFÊ¡¶çëq‘v^TÓmS•ð822‚ÁÁAô÷÷£¿¿}}}¸å–[°víZ ×T¡fÇ4M˜¦‰L&Ó’0³…T*ÏóJhвL&Ã3}˜)áºnð»§ÿÊ ÊG`†™-ttŒÝDáÐóBÁðCZOB¤(Ɖš8f#Ë…"¤iúûˆÏÍ¢—L–Ý £p{±;@ûwu…Û‰âaøõ%AT¬“¸]±@èy¡§x~Š…X¢X˜ÛUêÅÛŠe–Ú¦AQ½˜  Ò™L¦`¢“¦i‚ëºã8ßÛ¶í EIŠöQšy] I’ ªjðÒ4 º®—ìgO ÈjšVrÓ4¡ëú¸Ùüñx¼ªã1 Ã0ÌtAcNžçÁ0 ¸® ˲¦4Á½㊵”Q˾õO«Ö!@’¤ªëP«pXëþÍ þñxh}ðŠÞËñ«_½O=µ€ß–ŒBÆÑy¯ÅèØ™˜7oÞöè7ðò·Cç^Æi»wãžC‡F±xån¨ªÿ|Xª;ŸË…žS\=/’!yZw# y † ¥ebyBQ’¼ Iäsá{îEá‹eê“„I+ÿ]†/Šiùwä—gŠn„"^¾ —Ì¿»ùeZþ¶3òå8ùí†òë(¼j*¿ÏPþsZ8…vu È¯ÏæëCBßP~7¿.//.´‰Â˪EÇ&ñŽ! íR1>Äm¹Ÿr©år¾œâõ.VÍK^ZòVü©¶Ü¡U ‚üŽD___M•i Ã÷0Ì44»¬x%‘Hp˜\¦jÇ¢(!¾¹«Æ0ÌlÂ0BA, -YöÅ?ZGF„øYU}1‘¼õdÙÑ_³m‡žŒŽæH$ñŽ´ñݲB‘1ó1Æbþºb=FôŒÇÃúÉra¹â~¢x'z#š¦¿_&ã·m"’©}¶í¿"‘°ÑhxI*déAS-éx¦z}Š‚¤xî‰PL%ñ”iHóH‹H’]׃L¶m£££¦i¡H»ººÆ “žç„+íêê Êèèè€aèééAooo°M¥Lu°hI¼,5IP’¤’¨¦iÈd2¹8 Ã0 SmÛF"‘@OOE™OÇzQKeÍ݆jÛÝ uoôñ™Ú‰Â×Ö€‰S9²O>y{ì «« Ãñðá7àg?Œ÷íº`ï\6þ~ÕWpÏŠPU'œ°ŠR8yµ&HX,þNžŠônäGžô²á j$(RNÁ^øáN_X#/@ ¡7¡.¬#qQÊïŸA("Òöi„"\©X¶äùaœ/K/âÑv$*B¹$ìÉe¡\ѬS ¬/.‡Ž,±]1:B¯ÏR¤0³/yÉëÐÙ‡°jçªšŠª:Ôêl¤7ã*N£YLS#ËrAžG×uƒðM,3Õàº.θøâ`b[†aÚ QL‰DÂ<…–5Þ‹°,_(S_à’$_ˆó¼ÐÃѶCñËq|±QÓüÏb¨T"É›Ð4ýwÏ ËÔ4 E<چ±– ©­Ô&òœ¤2J…†¥2<ÏAÅòHäK$|¡S<QÐ$oDI* #KåPšL†Â# ª$Ú¦ÓყÒ•Ú$^:ŽxìâÏLã¡>ëDƒ•Ô= ÃÂ’&“I†‹Fáy²Ù,r¹âñ8b±XP†išH§ÓÈår‚mÛû¡G%½‰LÓœò3‘eYÁä@EQ Ëò8/Lò„ìéé Ò[¡×%Ã0 Ã4 ôIÿá’¼ªý«Õc2™LÖ41?sÈÎÐÈ0³Ìx(5a9Ùó¼ ÇãÈÈ|H’„ùóçcÎÊ•€¿ê}qˆ_·n6‡RøÔsŸ€¢(°m]]]дñi> (~®K”ÙŽ–“w!òïäÅ„áGéB|ÚðB) ¨Ž0· (@RRò2Ì ua_ ¡`aÎB×]@ Sóü(gRåë „µ”?4h~ÂÁ5±ôù¥5•ÁÂc…ض ×u144Ä3RZEQ „GÓ4¡ª*²Ù,{<2S†¾V¯Nša†ie"_0Bï@ PŒÆ‹côY–CÏ9ÑD/Èx¼Ðk0êJÙv($PRÒTÊÈÏbSeá²6Ä^©Wô½`»|NÇ%ÇŽËt]ÇŸÎ>ç¿ôRÁ¶?üÞŸà<}ZX®çAUÕ`2+=/–Ä(únÂÅn=…o£0ªfþeÁäbÃÒO›<ûRù…úŒ ßég@^~¢_aCòN”Pj´d– ÆñüÛžÇ.øCMeÌkt#ZÛ¶ó?öfø50•@¢‰DŠ¢À4M$“IÎÍÉT…ëºPU&¦>цa¦ÑX6™ƒ’(ÒC㔟])† %(é½iú: yê¡àF‚œ(Š9Ž¿­¦ù›mûeÅb¡g$ e–忨^‘H(f2¡(JÂ…1%ANéœx04ôöúïšæ×Ÿf—öö†'y’Ø'žWÃðEb!}&!’ ïQñ!R\‹ëFõ=“I?4«¦…e‹žŒºz^Š×—Ú¯‹!b˜‰)þñßø¤´O´¦•- ~«çyeŸ7J… -ä”e9iûRŒåö/…ªªã<8‰¢Ñ(²ÙlE}k×uá8dYÂÁR=,Ë‚.ÜŒâà-‰§†aÀ¶md³Y~c†afÃ0 ¼ü{zzày2™ ,Ë‚aU‹8µŽOé-Ü™«Uô¬Uè­5¿e<¯)L-M¶Å© iR.ý4=σ뺸`Îq<‹³pþõ?¨(xWÔÀ¯à?ô]¹ûzqÒœýxÓ‰¿Ä;ß´Ïæ'Lh^øb…5U…ÊPFÕh•_f!'ãùíSù}H ¤¼ˆ´¿‡ÒÞ~*ÂP¢¥ÖÿÔùöoz®9ˆÇž W᪪˨IxܸqcÉåkÖ¬·ì±Ç›áÓS_lÛf/¹$™L¶í`@£•;eLc±, '^=žÃ0L} ðœ$”ÑgòŽ+~ØhÄÏ¢ –HøŸS©‰sAˆëDÁða)<>‰ˆ´ë†Ú ÕSUÇ{KŠõ·,= ”¢HùIh£rE¯JÊ Ö…ò+šfx^âñð¼Äbþ1Óéðxäáé8þ±)*‰…–†0%/IU sN’w$ µÔnEñ?«j(¦R@¨QQ{Éû‘êHeS½IP5M_õ<¿¬žžPü¤²Ä0²ŽSxOF(tÒ¹_»¶¶„ñ³†É·È¥u"&5 ËbN„<þTU-AZXð»(0«T˜Ó© †u­ÄÛ¬zžWà¹(IlÛ†®ëp]w\yJLÓ4ôôôTâ•a†aj<)ì!…0§ÿ0 zK–åšÄ·V¯dY®Éc²Âc-eÔRwEQ¸?Ó†(vá³´ã8ð<ó.ǵˆaøÂ—¡ªª?Ù.Þÿ¶ê§ðw眃 ¼GðÛÎÁà‘µxû Gà8ÿ’HÀñŸƒŸ<‰Œ „y (#ÝÖ&|ÁÏÊ¿;½ E¯D*ÃAæTÅ[•ÄÈbÈ’aª»»»±iÓ¦F×}Æ ät:Ýèª0S$óŸ9S3®ëÂv],ý_ÿ ÙèÊ0 Ó6ˆa/E/·R‚äÐP(.e2ahOØè³(|iZan¿rš=¼— Aû’PEw@¨¯®¡(¾fY~U5\Fõ½í(T) ‰®ë mbIÊñH‚&ÕG¬£X'MóMu¢Ð¯žFµ¤}3™PT$ïKj#åœÅF1li<†§½é˜$“è(I¾·$Ãð—¥Rþ‹¾G£þ¾´O4ꋤ ’==þ¹¢kÉøûFXwÚž®ŒŽúïT>Õùw¿[ƒh´0Ì3óÐà—iš%…GÏóJ®+žIaߨLÀš¦iÖì5H¢f¥åP˜ÕTª0X}"‘€að<žç^#Å>ÙË‘a†i4hÛv <ŠÑÐj ¹©(JÕy![Y–êÐÈó^kÛ[YpžmP÷Ž—}µÎxüC²,HºŽ;»"øòÈ_áùÙ¡Ò#€ô‚ƒÓÏ=Ý8iáIA¨UX€" ~&|‘æ’ˆ…/.ºðE €^øB£…Â܉T “¢ìAù+…¼F ªÝÝÝèïïŸÒk2ÆÆÆ°yóf¬Y³kÖ¬Áµ×^‹áááqÛmÙ²_|1Ö¬YƒÍ›7cdddÚO’mÛe™ ;ÃL3ÍjLÓ„œJáísæL9ß0Ã0S§YmA½Ó•‰¢ (BŠÛ‰aIi»R@GáHKO„ÊI§ CoŠ x$r’·" ‡$„‰žTF4êo›J•*I¾F^ɤ/¦‘×&æF¤:Åbþ»¦ùÛÓgEñ_’z0Ò¹•å𸑈¿Ÿ‚Tà3W|&œ|çÀ{†U¥(C*|±1šÿlà =„âc¾Yê²Ó¼ÀbáMS#U ¥ÄÖ­[±uëV Nyÿ믿###ضm¶mÛ†îîn\ýõ ¶Ù²e ÐßßmÛ¶add›7ožö“D3š†™^šÕ|ëþûáª*x¨‹af†fµõBÐ j@a@Q€Å. P¤íDáKÌ”·*–‰ø"!à‹_T/Ñ[QôZ¤å¦éï+Šœ$Š‘žiú/ÈH̤2#‘P¸ŒF}A:7¢Ð'†`òß{{Ãp¢$dÒÃußH8$OFª# “´…qu]9g™¦ßòÒL&ýã‹ù+iI ½M)¿¢X>y1’¨I‚%‰‹Å×BÈŠˆm,¾/L³PdUÿüÇ%?:'ÍÌd¶ •í@)D¯‡žžttt ££‘H’$ahhhœçŸ¢(èêêBoo/z{{¡iZ8™N§aÛvÁ6ñx|Jžã8ˆD"/Êm%Ö§Ôv‘H$³Zj€ÌÏ[£y(Óé4$IB$ ÚßÕÕÛ¶ƒuÌì¢Ýû ÃTF£lå'¦I@Åÿgµz<2L5ˆù°«AÓ´–¼›­O@g°8Êhñ³›/“Ç…(|AËqÂ|…bÉ[RUýí‰p]/ ©J!P=/ôúÕŠ91)-‰x$̉uò<_¤¤6ð„åSÝDoLÃ/Ò¹®3™ðtLI*éX$Š×›Ú'Ë~ûI Ò´ðÚ¨jaH^ª‰ºô=EOÊCé8…aX3™ð|Ò5ýÕ¯.–û½*±­j&‚ÄGò¬&ž•žJ¥ ëºŸ'¦„ׄ¢(Èf³9¨¨¬\.7®¼â°c•†!›l»‰ž¥†h|ÏL&×u f‡ó$ÐÙI»÷ †©ŒFÚ˲NjŠ(ʸá€ÿßÅÂ#ÓJ´âw3ö h:œ_ÂgUqÒ‚O1ø}[.ÜUo…ûÔ™ø›wîÁóçãÝ«WãŽî³¡îœKù×ðÅFaèTò`ôæjTær$±±+¿}ñefo f†©ZxÃõ×_ááalذ}}}À866x@â«_ýê„âcgg'6mÚŽR cdd}}}Á²îîn¬]»;v옶 ˲ày?ì2Ì4Ó¬vàßN: xó›ËN b¦¾4«-¨©ò&$8ż„äí'~'ÇÃè³ØM)ŽUÓ ½èJy?f2~=KE`4ŒP¨"KQüí³ÙP(#̓ oñPû]ׂ-+IàþÓŸV …ÇÉlA+Ú©0•Yè•lÛjÏ2­Œ©/íÚ'`fj4Êxž„ §‰>¥à0à 3ý4sŸ@Eè4HÏ¥ñCä]'ݽò^nÇÛà8À³Ï>‹ô¢z^삼zÔE¾#£ú~ø!RôìîÂW9µü{o~/_ êîÓz†i0U [¶l Ü›Å4±~ýz¬_¿›7oÆ–-[pÓM7•-‹rF¾‘Ø¿?°víÚ ìýû÷À¸c-]º´dLýêÉkž¾Ó2[ØÎƒÿÿB_aŸøÐîöY_½ºÑÍÇtÛxê©§°qãF¬_¿>˜ý4žx".‚|é¥>E S76n܈ýû÷㬳ÎjtUÆ1S}‚¥K—bÛ¶m3Ö.ÊH`DŽ$Q¾D–¤¿Ÿ¸/û®/"‘øèº…"”øøÛŠ[iÛLÆ?‰z€/®‘HJÞq$Z&“¾× ~U ¹J^‰$T’'!å´¬ð3y$Ò¬PÓ ó@Ú¶,M+ ïJP(X¢”¦" ¡…Q-5ÉWÅs( …¢ )j"ÅÇT±<*_KåÞ=KÅòÄq-:¿´})1Y¬7 ¾ÄÞ½{ñÍoþ¶áÀš‚ L “Ù‚;v¨¾O°gÏlܸk×®Òóô[¶lÁðð0öìÙÓ誌c&žîºë. £¿¿ÂÁL†iwøù`üómÛÁD˜‰ÄE/dÚ…lß¾O=õT£«2Žf3$çC 壣QžuI’ày@ÇâÅè\>‰ç ¼ûè½°màŒ3–à¡×\‚¿|µ®uî zöÈ,?Äj¡ç"™žxÑÙs‚©‘-[¶`pp°æ>AU£ ###À¦M›JŠŽD__6lØ€­[·¢¿¿Ò«bÃT¼Ïd,_¾W_}õ„u-…‘Ÿ‚ÞŠ.èLõxðÅ:5ÿ™&”$ø©Â¶^Ñö²°ÒRà~ÐS(ôš—ŠêRì|¢ åÐHË$„ÿKÅȽ½4ß°B!Óa`ÕªUSž=ÿ|üM©Ñ\†ia¶mÛ†ÁÁÁªr2Ï$ÍÔ'¨–Š=EÁ‰Ä=ÏóÆ’‡†¥Ï®ë ZbXUò”Bo@1 ˜b^@1\( ‹™Œ¿Ü4ýeé´/öö†¢¡(r‘§"•IÞ{ŠâoOm¦p¬”’¼ø(«(ˆiZXŽªŽýèXDqhZ¢”˜¦ùž‡bˆRq{1ô*•Ib(-¯ÕMì*Šu¡1ªâú‘G£Ø¾jÎRžªt/‡µ•eàÌ3—#߆#xôÑqÙeÕ×cº™[°bÅŠ|PoÄ| S 4ˆ·qãÆFWeB¦ëùàŠ+®àÉ ~>(õ|à8NEQâñø¤Û0L+@!JgkŸ`*c†4n\l!úúváºë–ßE$I°m`îÊ•¸îªîüÜ2<€3Ç_<Û¶ñøªÇqI×%€ H áîFòï4$)*P<÷çB05Òßß_—>AÕÂ#€Š<†HxܱcGEƒ|ôÄÆƒ\‘À4M[·5æÐ•ÆØ6æÑuà{jùy¬[“CŒ×MPXmѱx » „^‰jþ³’ ýhùõ^Ñ14†á¦}i¹‹òy€m„'Õ 6ZpÅÓ~mª¥YìÀןy¹ÓNÃ'/º¨Ñ§„af%Íb ª¥£Ãå)ŠN$(RèTòl+§*Š$ˆyž/ÚQÎ>"™ ÅÊxÜIhBq‹ÄÂdÒé{4 d†ŠS$†’ç ë†á=Ç߇B³RhT*3=)©m¢a±· (’Çd1bØU:¥–—*CÓJ{–ó`,åyX®üârD¦3 W¹cÒu—$ÿº‹!^©þŸúÔm¸øâæþŸ+e º»»]­†"IRË…Oe˜Zhõ>Ã0õa&mã8ü_Ë0MH³ô h¬Y䳟] àvíòP»O: §/X 1ȱ†ú—'Ÿ–ÎÉaù²1üÙ¡QüÓOžÀÒ÷,õou@IêîÈ$pàW< ™¦¦*á‘ÔÎJøi›ÁÁÁ²ÂãÈÈÆÆÆ B›ôõõ¡¯¯ƒƒƒÆcxxx\”é‰bÛ6<ÏãXí \å½Åï@è¡çæßiüζÅ$ÇôPèAHaE=á³&Sïnˆ!ŒÃ=”'A…¢•ßO+:.m[ª^“ÙþJ¶)…¶{²óCÛµBhïf´_þà ׿ŽÂ0Ì”hF[P ”K ’†¿4ÍPpÊÒ~”§OÌe(B $…bc1ÖT–}/CÛV”Ä+ ÉI%à{ý‰ž…$’#}–e_t¤zçU,Îg)Š‘T1¥y„£ëå——¢\4¬bAt2Ä<Œ"å&½7"]x^‹Ã´‹™ùŠU@¥¶ ìÃ0ÕÑn}†aª£Q¶Àqöfd˜&¡û}®˜ìÊOxÕðö9spÑE!~×EÈœqR°Ísc¯Âá#óqTZ‰¥KÃ\Z‰üîÏó…Ç*œ xË<2L³0§šH@$Ïlj m&òvܾ};®¿þúŠŽIù\ˆÁÁÁi™ñÜŠ3›(T§Þ“<üùW¾àf0ó/¾W -¼E¯€žü¾ ºòŸ{òß#Â;mß+,ïÊOˆæ—Ñw'_v¾&Ã÷æÓÚÙ8ºô= ›e„÷!¹ü÷$üðÖÉüKÍÎ/#ÏtÑMžìº’ßF´çÅÛS‰ È“R i6;`š&~uÁ¸ráÂFŸ†™U4›-˜*Åâ˜(:’× ˜ßð¿“š¸/ p’ä¦P™$ézèeha8ÕdÒßnhÈQE× ·¡ãªª^•„I'PM&ýÏ‘ˆÿnš…!U%Éß„QÇ)Ì=(†'-ö…TQ-%– Eï½âå¥Ä>Ê+YŒ(ÒUB9ÇrÝÇFÍe+†¶‚Èa e2[ÐÌv Z"‘:::`Y¥cq$ tttùbhŸD‰¦i¢££f~–@$A„¹2L‹Ðê}†aêC£lçy1sŒa˜q´JŸ`ttË–â‘GN€¦iX|ä.… wÿýÝ€Ë/ÿ9=p"[€áçùƒôO’  ®F˜»Qñ—ƒçA0-FUÂãºuëøIg'ƒ¶¡}J±~ýzŒaëÖ­Á2Š#+ –6lÀÀÀÆÆÆ[·nEgg'.¿üòºŸ˜Jc¹7 ¡xG‚¡_Äë…/ø‰b ñ^…Qø¢£•ÿl åE„ía?Ê"c"òò^àH ÛÄ…×(|p(¿ }Ö‰báBP,‡¼ü(‡®*¼H¨d!¯µi6;p׉'bþüùøú›ÞÔèSÃ0³Šf³S% C‹C‚Ÿë†¡NI|¤˜¶]˜_°X„#áÊ¡œ‹$@êº/ š¦Ÿ—1‘EBò¢ŒÇ sF£aÞE $%É/DzƋiŠ Ÿ¢'c)!‘¼+默÷PœDN„ºî‡¨-&÷EÒZ!1t¦™Š¨9ÝLUdm•Ø‚fµµb—qû-'Hcš&b±R©GoaZšVï0 Sa ¼|gž…G†iš±OPî‘òÄ u×½¸ø;ßÁ_œ}6¼ÝGñŽÀ GO<ÿük°ú¤ã-'ùƒë”LÆøPw Ó¢Tj•b'oݺëÖ­ÃúõëKn·}ûvlݺ6l˜0Ñkww7nºé&Üxã0MK—.ÅÈÈ6mÚTà*Ýßß믿×^{-:;;122R×$²"Žã@Óã³ìï4¼@¡?iy¾-2„õ$’' †¥Æ•RUÖM-ÚWʘèl•’p‹ëÅݹÙM³Ù?¼êU8wx¸ä’FŸ†™U4›-¨–R!Q§ÐûLôÈ3ÍÐSPôšs1¦R¾H„ùɃ’Ê!O>©.â|*Y…PYöÅIUõÅ=ÊÇXì­I/1÷£®û¡[) Õ‰r6RûDÏF1•öLÎ÷jvÑ©Ì4»¨MÓ`YR©ÂÞºã8ðù1¸™¾öìièïØ ¸êªWbáí'âVœˆÅ sPã~!ô<]΋ˆaZŒª…ÇÎÎN|õ«_…išÀöíÛÇ­ß´it]¯ø^Ê`”b¢|‘õÀqH’©ÎÓá)ÿ"ÙažE)¿žÂ–Ò˜ÄdC< ‚i7šÁX^~ùeÎÓÌ´$¶mÉÅ×­D3Ø‚J‰D¼Š@¡ØGâ…=ül»Ð£½ -Ë“Éð3‰}€/0Še¥Ra®G*‘¡¡Â°Žã‹©T˜#‘>Åa^Åð¯$|aXVI óEaý¨Œâw†©„JlÁLØÃ(üN÷¿e…9R‹·I&ÃešæÿFEq²Üx&y= Éd2ÈÙX ‰Žº®³èÈ´­Ô'`fú˜I[À Óœ4sŸÀqìÙ cgGÜGùœýþóöœ¸ýöÓðüEÏã/Æ#¯zPÎñº2ÌLPµðøâb?úûûƒ™D+wú§#¿£?wbq×EƒŸßPF&•a˜Æb8>0™g86-¢¸FÞÅD£Q¤ÓéFWu®ëN)WH"‘@2™„çyˆD"ÈIî$I òÐçh4Š¡¡!xž‡X,Ö²Âc+!†FUÕ¢¦Y(D&þöé´/HˆBD<î ¦æ|L$Âã¸nèåHeR¹¶zMRŽH× Ã¢&þ1=Ï?.‰TåsL&ý}è8$(¡ Hß©$\Ò±‹Q —kôUb˜Ú(—_TÔøJmSM^RMÓÐÛÛ Ïó IRfUÓ´’£išëu]oÚ\õ Ã0 Ó xžÇù†)I©ø#®ëÂó<œðÒ ðRn¼€{ò"x×­nwþÅ×~EÏ/ÂYûyV.Ӿ̩WA}}}¯VÆó¼º=¬Ûzà{5ŽÈ ¯4|±‘rÇ2 ÓxŽl»m4& ËÖŠ æy<σišÁ ,aYìâ¸xu®ƒx>£ã83æÝfYVð€F‚!€@€P้D‚}ººº‹Å`Y¢Ñ(,Ë >“Gc"‘@$A,ƒ$Ièéé ÂÐõôô¯¦i'‰lT/×uK ±¶mË‹½ iðÖ¶í༊މ±X †a)š¦‚`"‘€ã8Ð4 Éd]]]Ð4 ±X ŽãaS5MC6›E&“A2™D:F2™„®ëPUº®#CUUd2™`Ùèè(dY†¦iÐu™L’$AUU¤Óé@€L$A>0¿÷½ïáù矟á;³=!GE …D1|©iúB …=B/GÊçøŸ“I¿,Ï ·õ<¿ :iù”k1 ÅÆD"ô¢T”0 *‰º†o…Îrš†¢ŒµZ Og˜úCyéÿ¨Ò°Ù²,#™Lü÷2 Ã0 3u8l9Ã0•Bѯ`¾4Œ¬ƒ±ãRxÆ`:1| ¶-À“žÄoÏú- +¯^‰óÞ|^£«Î0ÓFM9ÛŠÉ\MÄïå¨Á£ÚÚ²ÃÌN'îÙÓ2‘Hɼû J®ë"˜çyˆÇkŸú@¡E'dÇ &n˜¦ ~Z–짪j°Ž¼‡†† ë:dY†¢( <þ(T¨eYÁrÇq ë:<Ï Ú®( E)™ë‘²–e!Ë©Ž’$Á²,hš”¦iäQŒÇãèééÁÐÐP ŠªªŠd2‰X,VpßèºI’‚yžç!“É@Qd³Ù`;Ñ‹¥ø¾£k'ËrÁ9¬]×áº.$IB<‡mÛPªªÖ徘ÍÄb¾ˆG—L̹(^FòX$HTt]_p¤mISH$BïCòf”e?/£eùyIH”e_¨ó@bD±R<¦øsN&Y@d˜f‚þ; Ør®^]׃‰7Ùl6ˆäRΣ*ÿ+ Ã0 3°m›Ÿ—†)K¹GçÝX‰wŸrßyÎ÷õò çÈJœƒ]xçÆw"™Lâꧯö à.8Óæ°Çc4(;•P«€^ø¹‡àçmdÑ‘aZÀ‹wÝÕ°|“åct]‘H$ðd$Q‰DAú¬(J¶”¼Ü&¢Ô@¤8@)z](øb§è]IûišUUá3‹!‘HçUìzzz iE Ê…KI’‚õº®#•JA’¤@t&4¥«‰DÑh4ðshÙ¶t:œWù²ÙlàU(IdY@3™ R©TPT*]×ïFÀ÷P¡²H„œiÄ:«ªœ«k®¹'Ÿ|òŒ×§]0ÍP̰¨NÕ²üeô“–åгÑó|áPÜ—¶µm_l¤qÃBº}ò?Å`=ý$)܆ʤã‰eˆ^™âòwôf˜¶ƒ&ÂT# ÒDÑËßqD"‘q/†a†aÆÓ*“‘†™yŠ­ÃË{÷ËN^0)ø}psŸ e.ð¯< CCC$ ÷¼þžòÊ%ôìñX„ã8?Ü{ øžŽXpd˜VÇÿ»ÆÖ­PÒé†ÔÁ0Œ’^{€@T¤š–eßÉsOQ”ÀKBÓ´@ðCI“wŸã8%óGQ~BZNÂ"…Íf³IåȲŒD"„!%O=ÊS¨(J‚”<É @zthh(¨G=fš’çŸçyPU5ð¦,öà,'fêB;~eDJ͈ÅƇ%•¤0'#à‹‚âOݲÂ\‰‘ˆ/>Š¡YUµ0×"}V1ÿ#-'aT¸­†je¦y ÿ@"™Lü/•Ú¦ø;!IRÐo˜h;†a†a ¡É·šŒÌ0Lë1÷¡‡ðÿæÌÁ/^‡»ú`Aƒ¼ð0Ü£‹á¼ Ü2ºó | 赓aš‹°m{Ü~9 øy“`{Á0í€àÒcÇðó*Ã-×ìEAWWÒétFÔ0Œ d'= QT‚ÖÅãñ äi*•BOOFGG‘H$Édà8NA8V*ÏuÝÀ»‚ÄLAxSÇq‚ФÑh4ÿfFP>€`[='øfâ\Ó9¤úVjçf"(Ü©®û¯b’<u=ô†BáÏuý«CC@ooᾪZ詨i¾ I·®(0Ògñ¶?‹??]Cªªj¡ç%Ã0 Ã0 ÃÌvªM¿Ä0Lûã°Ë,_}ü8®?ªãx>ãIØÃóñíS^/ÎC*™ ¢1Ìl *áqpp7nltÝëŽçyGÎd8ð…Ç 8$3ô €Swí‚$I3:»‘<ƒzä…GEQ‚pª²,C×õÀ£ñÿgïïã个;üíÙ–-Tƒ°edaQcÙÉĨLj,†PÛð¦Gû ì î^6?0dºó€“ÀfÓ´ Nv“íön’ì®Õ•M°ÉTž3eœ Ù`{ ‰±°eì)i,Y¶…Ý¿?ªNUuOϓ桻§Ï[¯~M«êÖ­{ëáô½÷sϹ†ÐÌf³‹ElÛ&›Í’Ïçã0§@ƒÐ&aDùž-šÏçq]7öf ‚ öj¬V«qh×ÑÑÑØkQ¼å<Â|פR”nÂ0Ï÷Ãð§Ùl"B:Nâåè8IšJ%m;ÜnÛ¡‡£Ó!UÓaZlœ¯©j~-uLEQEQEQ<ÏSoGEQZâF>”¸\®ëâyÒ]¿÷å73Lû2_ºøÅ?Æ7¾.)4‡'EévNIx\·n;wîlwÙi\˜³Ä €<¡‘QÑQQV°á–}vczmY™üàºn¼¶¡¬ß888H¡PàÃ;?Ì»>ù.rFË·xç›ßÉûsïC¬¶š=Åb1[šÏç) q8T×u)—Ë”J¥Xl”ÐÓCCC …XHÁRKsÀ#ŒÝ¯!-WŽ“¬…hš¡˜(ë2B"‹¡À˜^×1‡”CCá6-+ÌOޱ¬p Gh\¿1—KÎiYóEQÒÈï>‡H_j$·EQ¥SPGEQZá®ï(£çyT‹E¾{Æ«á¥ïS ŒÉ…ð%úl8ÿýïÖpéºïÇc|ÚîUz…S·mÛÆwÞÙî²/:2ø? Ž _uLQ”N®r]Þ¶ Œb±H6›Å²¬Ø£Ð4MlÛ&ŸÏS*•0 ƒÁÁAr¹…BÃ0ùà ‡ ”r%ìª Üêß ÷%(eK-E.#HÑ5óù|ìMéºnì}Y­V‹O .Š'c1ºà>IË­˜ú^޾/ôtÒ2\lòQÙ¥Ùè¯C8+ÅŽê#Ø„nòÂØ5¹_&*Pv8Õj¸–¢¬ÕhÛ‰W#„‚a¹n¯VÃ4¾c‰Xhš^Ž•J˜Î0…Ì´)J‡E•ð®²]Q”•A&“iˆL ضM­V‹‡3‘™mÝÆ  †‡‡§LL’IIÕ´{õ4çkU.I;<<ú;LèÄ¢(ÊÊ@†¿½ë.~»V[´|'¿ù|ž\.× (ærÉʵ‹êÙè o…¶ ¬6aÜŠ,I ‹b”®ÕÉŠ>^tœ˜vôÝ‹Žw£ã‰ŽwÀÂÜÕƒ(_)¯ülH]*$?qü¨\~´­7m3¢ý…TD¼lÇÍE×!›ª×)ü mûè6žyí3 ¸½‡ï'‚£`áÿ}¿qíFË ?…B"*B¸ö¢i6 ‰"XFãò H³Ä²×mTeebYVÃïnäóyòù<µy¶Olj£&8Ž3eµ\.ã8Nƒ(éºî”óID…Ví gJ#xžG&“Á4͆s:ŽC±X$“É0<<¬â£¢(ŠÒV溓¢(½‰I8ÑØq`×+ždãúõð0™¥ŒMé¾w~4½\~€?ýÓ¯êM­ô§$<=z”‘‘Ž=Ú°ý²Ë.ã–[na÷îÝí®×)áyÞ´ž<áø°Œ¢¢£¢¬4<àªÉIîO­W8/\ñÈ'Œ† /è‹“$­BŒ¬#bšˆk¹¦óåSù$Â[6Ú&åo¿´0çG›óD”ƒD$t¢ãD+â¡(oƒÄsÐJSJååEû¨^6‰hG*9^Ê쓈º’.å7ÆÜQ®ƒÐÊYEž¡ i›”Í dÅ34}ŸrÑ~ñ¼ô ŸO9¿~_÷Íuü™ƒó¨„’£¨Å±‡b©”ˆCC¡G¢ç…ž¶nð áw× ÷¥l; ¯šÍ&k2¦C­*вr1 cJ;Äó<Êbæëºd³YLÓ¤Z­R©TöW«Ur¹\ÃùlÛ¦P(ÏçãmA´,Wš¹¤)‹†1E\”µ©(‹SÊ©(Š¢(ˉïû: FQ”i1ˆÆ=DZ³±sË^ù¯ßƒwOc$b¤x‡Ê³'õÍ¥®Ü§Tš±ñüêç—°"+i"A(Ž%b¤ç…Ç …ŦȅØ6äóIèÕb1ñrÁBoÈ‚ÆrI æéï­H& ˆt;…Zùmh&úù½••Þd¾ë.A€ã8T*,ËŠ½Ó“,eméfD¬\L|ßÇu]*•JËöaär9Êå² Š¢(JÛ0ˆKé•$M@‡°i¨AM¥ûØ4ù ÞÃWòN~— ŸÁé¯þð÷­Ûχâĉ,I:#<ÏÃ0Œ–@¢êµr4Reeà'Ÿx‚ËæÚpHf$äÅǘ2ÐìWÃ64¥#“Ëåp'K&ë5U*•†0§‹ÉÇÿÇǯA“ÆŸbÜÒxY’ôFô‘ñÊé.Sº×d²°¦K…x6N·~¤Ô! å=]RÑq>X©¿mnš´©ûqøÜÃ0ÒîJtžŠ‚"5Ÿÿ‰÷¢Ì]ð¼©Ц ÍFãú+*¤êt\š´W%|~Ó륦¿O‡„œ.Ð8¡b:qO&È„ƒô½òSùe£}›&yJQÞ7 ‘,ÒžÔFZ&nT£t9’Éiq5JZ&Lˆ°ZŽÊ?œJ'á¥å»L6P/ÙE#³ð,¦ÐÊé=‚†õ]×¥Z­Î;ì¹ã8†A6›û8â)d³YÊå2±×¡mÛS<E œnýÉÙÒ¤Ι։¶m›r¹ÜÐnREQ”åÄ“FùI§¤™*ÁsdE ¥›îÙ7FÇ€+ÙøüÙ¼êéqø§Rò‚7ñS?u †q ª9*½† žçµœÑŒ5- (J'àoÝËP‹mB£`6.$t'I¸1Fls]Ã0p?ò®,‹är9ÆÆæ·s¤="ç2¦gÌ1ÝJDÄVEIѼƣç5†A5ŒÐ“1ÆuC2›MªÚvè‰v¶ÅúŽsì–­Ò$V³Ð&ÛË$ÞÌéï’°ÄâM& ´¡5’u]s$^¼¬‘*ç÷£|Äs9½¾«t.Éh4âDôõ C5CòžHÂ:gSçovYcV&bI&c©¼ä÷ÁJ¥MçW!YÇVÎ)¿+Í×<íEîxŸODÿïþ/¡­ËÑ÷¡h¿xŒKl¹NôW¸W-Öƒ²²Y.GdY1išóŽ‚P­VcÑ‘±T*ÅÛJ¥¶mã8ŽãÄá\³Ù,…B!îAв\õÈx͔ƶí8¯™ê¡3ÀEQ”vœâÒ+é¹ny’ùféyt™è»4 +$Í;EQº‹‰c«8—€5'×pì’ŸcÝ/Ãð®©iüÜØîb+ʲ¢ÂcD-…GY¢lx~Ù)ŠÒEÈXôY_ý*V+oC\—õå»  Ë@w„ã8ضišd2LÓ$›Í2::ÊÐжm“ËåÈçóT*Õ¯(]J. ަ™x,BJt<££¡G¤uFhk, ÌÿÁn07Cð;`4;ù„£éÿËx|³wÞ© ‚˜¬s:›ž!B¢¬í*ž"š„¶Ñ&åD ôIÖU•|Üè{%Ú/×.½N®EãZ§i.-*:„Bœx¦ë(ƒJy0ÚW#YCV&WHš ‚o:lkú>ÍE…J§O‡>.M“f6ÒÞ–£M÷Q¼'å{)ºò¼ÈµqW~ËlxË]oáÌ-Ú%˜åú¥¶m›ááÆžG±Xdhhˆ±±±9‰s¾ïãy¦iR,†½‰¸à8NCdñr„Pôt]7ö:‹…ÂVåšKÙÇqârL'>¶ ûª(Š¢(ËÉ|<eþœ4C›W&©6-eNÝPô™ó¦¿zŠÒØ€ìL8Ä·¿–+7Ü>x; ³êw…éÊå2¾ïóG¤k©(½Ééí.€099Ém·ÝÆßøF.»ì2lÛæž{î™’nÏž=qš[o½•ñññE9¿tÎÓ¸$ uzQ”¥§]v@KÄ#±2á`µýµ¬ÓÇ2m1"j¬P(P«Õp‡b±ÈØØù|×uÉår*:*J ÚÝ&˜ Ó ?¹\(6V«aÈUñr´íлÑ4Á<nÏdàÞO†aVýÇ€»À2aø¿ByIhÎbaȯ½|´½J8Z!ö(`öÑ Ýšï8H¦d§ ¢s‰ðç¤ò‘5QEÄ’õ[eBF•D4´IâH¥•ãEDô£òd€í>|¦ ?Y…«‹ð¯~RO˜ôÂsþ¾ ^†ÀO®“ˆž"Ž~Ò…ƒnªu,úH¹²$jR–Ю7k:Ík®.Ÿ·X ?͸nøI~¥= }‚h¿á7®e‹FJ^X· áoW6º£ÑÿmŸ#ýGxþU¹Þë\lA;ìÀr#aV«Í‹ÇNƒ„Y/DÏóð}Ã0âö‰ïû±()X–E¡P`tt” æ|¾¹ Z…·4¦)—ËAÀÀÀ@»/¢´… 7ß|3—]vYü¸ãŽ;¶¥÷ÍÄ­·ÞÊÝwßͧ>õ)î¼óN®»î:n½õÖ²gÏöîÝËîÝ»¹óÎ;çÖ[o]” áºîá1O2Á_Q”¥§]vÀ®xñE E'Cþõ<øûB!Àþ"˜¯ ¿ßu](JG¡ú?€‚ÇÁù± ç¯#æÊb>¿L8’!!2‹„ß ‰`9ýÍ qÅ軋™h[:<©x Êzµ?îÁø˜w»ðoƒÄcN¼;ðgEøÙ l¨†ù:„ ¦;‹p{Va¨?æ&ŽUàå"ürF2pe>Ý–C¼}ö Àç8èÀã>üZª|Uà_3œå!xÙMN¸]<o/Bž„ÏdÀtCÇltËy(æC±o` T…Óx^¸mp0T•›qÝä¸L&¼ÙÍ3ã')Çi§MÍCò—ýáƒ)ˆ°)eœR†" ÀÀoù»ý]Y,f³í°í@¼çnU¬7|d}é ‚€r¹ÜRœoX×¹`š&¶mO+fŠÐ¹Të\+ÝK§¶ EY^–Ë´òxô ›Ñƒ$4Dx,T¢ïâ¸`ÎóšË/j0‡4Š¢tF› ÙBü%ÿÈÇÂgÊX×$¡V}ßgxx8Ž€¦K (½È)ÅUÚ¼y3·ÜrË¢brr’‘‘n¿ýv®»î:vîÜÉÈÈwß}w¼íž{îa×®]ìھŷß~{<»AÒœ Ò™O .á¿:Cw>ÖRÖé¬V« kÉ´›æõCÓ!¦dºPÒÈm.»ã8˜¦o/‹X–…eYñ—ïûäóyr¹\Ãön¡vÀ^ñƒMƒm#ežú ïûñzL–eQ*•Èçóõ\*J§Òî6ÁL¸nèÉhÛàF^©np[¸ÿØÕašjŽþ|0ã½P,À?P}”®ïuà¿ ü`€üÃ0|¸?ý(Þk^¹~ü«¡¼*¯î à.øÁë~£ø®p”þÀƒeø¹°Þ„üX㈟ôà7øï.2 RGDòÀ·2p2€£ ŸQL.M>1«xن˲ð+6¼•dÍÅ#>\À`ðófxîaBrwþ³ïûpz-<¯¬yµÁ‡Í°L¿W¼ËÀ»Æà•üO;œ "bêp”ÆË†B¨iÂCYØo4Úð´/’Å9Óû-+ü+®¬é5x- *•ð»ï·EX‘|šEË‚Z­q!ÐfÒç”/M©~‚ ,ƒi6žÇ²Â8¿ùiV’º›&Οÿ98w.¶ v`© ‚ öJÊå2†a4ˆr­ÒAØŽ‘u¤›Éår±Ø(Q$oIÅbqÊùfCÎÛªL@ÜÊd2d2*•JÜVu]—b±Hñ$-EÎn(в|,·-h¿!M’9Èò Û¼${óøá\Gdd‰pEQ¦§SÚ2Qàݧý»y—?£øÊoPú¡zDG¡V«Õj<þÛm㳊²Xœ²ð¸{÷îE+Äøø8;wîdÛ¶m Û·oß»Cïß¿?N—.ǶmÛØ·oß‚Œ‡ˆ=iÁÁ!§Ò«Ëç´a–™¡ É5Åb‘B¡Ïî–p™Ó ιÏ"§ØE™žv· š‘%õ|?üˆ¾³ñ×àÉ_·=ýf Ú>r5d. Ýû1Èß Å/„ÿÿÎé°Ã‚ÎǬâm{ ðZÜ?zãü ¸€_÷ö/à÷ߊÿÕã¾£ŒÃ¹T²@ààýáßcíÛ‡wíµ8ï}’Òo‚gG!žÜ*|Í )£‰hQE*ÀÆP1ý,¡èô_ ‰}ó_ ¿\l$B—Ä¢>Tß±à5©ßΉe®Öú"šÑEüU~µiHÆö•ˆ¾¡0)á[ë$å0€BäÚxG´=Ý$©§e%bb‘©a+f5L3IcÛ^„^ÓÙÂ@β^¯w®Ìt¾ÙÊ3Ýo¾a@4ééð—¿Ü‘Âãl¶`9íÀr"‘ÒX–ÅððpC»µU:Û†a´Œª mi3Öj5†††¦äcš&µZm^žÒÎmU&€áááx Èb±8%ä”mÛŒŽŽ.‰·¥Ò½tZ›@Q”ö°œ¶ yœ¨L²¼v3Ú»W”壓Úð‹çþüó³oÅæ8²°Â ¸2OÚÈŠÒ‹œ’ð¸ØlÛ¶;ï¼³aÛää$wß}w–eQ.—yä‘GÚóÀÎ@»ì€,aVm|nd²Sˆø%ïdzÍHõtT”¹Ñî6A3WýOøå—CmGB­œs\óîðÿsð‡wÂñçlÀûÙPSûÛ/þ#Xoàñó!óëðà¾ãlxá«Àkq¯ÞOtr&&ðÞõ.Ü3ÏÄ{î9‚sÏÅü\Žj.Ç0ÉR‰%Âóx@®PÀ)M—PŒå‡3k‘'\‹Š ìB5Ùªôï²§9n¦­ÖÓ»[cÚµg2­%à^?\0óTl°Úí¶2›-XN;°\ Ï&ZÏ1ÝL^ƒ££ÉËhÃÃÃø¾ï'‹Æ6{KÎ¥\s-»´uÓmziS+J3Ö&P¥=,§-hdE¥B[›Š27:©M`k~ªŒ&£¸gæð¯*Åhòù|¿ä-¢ÜX*ü—¤¯V«†{Ô‰PAv©R©P­VãuïDD“O"Ф…SÉß²,<Ï£T*5¤Šó—rÊú5r_¥l"Ɖð—Ífc¯Áô¬¶J¥‚ã8Ôjµ¸¼â Ä‚ª©£££ Ń<–eÅR±±±†:Š7£ˆrÍä^Ë~ á˜fdð&x‡–Ëå8ޏˆÐßüæ7ù¥_ú%^õªWµãqž‹m<ÈÍ7ßÌu×]7L$<ÊöïOž}Ÿp$Œ9OcLØ•ËeJ¥R쑪(ÆÍ7ßÌÑ£G¹ôÒKÛ]”YYª6ÁºuëæÔ6ùÑZð¿~?t9XFÙrâRx÷<ÿípß/?Ï»@6¾e’ÊçûÂcÞü[üÜ~¬÷}«°6Aöøqœ÷¿óÄ ²$NPíïÇïþÖoáöõazˆiò …FùëEûÂ9>ÄùÊwÞׯO»œ˜î®†7lŽ¢H/±ÿ~öìÙÃÁƒ§tÎ;‘f[°oß¾åwøðan¾ùf¶mÛ¶¨‘\º‘v:Ó9ìÙ³‡ýû÷søðáveV–¢ð…/|ýû÷³{÷î)^ŠÒKhÿ 중öö)@š3êç¯t2®ðàÁveV–kÌP{ ÜúÒjŽpˆ*9ìË¡z&”‹I0‰B¢(ÝÈž={Yp›à”…ÇÉÉInºé&öïßÏ-·ÜÂu×]Çøø8###ÜrË-ŒsÏ=÷Ì«3?>>Îm·Ýç‘Ëåèëë[ðÅÚ°a7ÜpÃŒƒ*Òùõ íFç–õ¢#{i!˜bDef²ˆW±ç išñLåjµJ©Tš6T(—Ë ‚–xûI(Ò¡¡!FGGñz6þý¹ðQ;\ro2 Ÿù¿°ëÕaºs¯<Áó#«øæ‘>°à§žÃÉþ4ÖA°Ö@uMh^Jç †çžKD@#\òP<ó}}az’ÈÏá)+ÝèC”FlZ™DŒt‰&SYôvL¨L&ôbÔ !@2kxÏž=í.ÊŒ,•-¸à‚ æ51RQV*ÒWïÕþÁOÿôO÷üäEíHÿàOÿôOÉ܄íh›¥ý…g¡(‹‚¬Ø«m‚Vc†B@Ø ÇÖó0›Â}§W÷&Asd\YQº‘Ý»w/J›à”…ÇO|âŒ7,êš.„3©oºé&&''gÍOÒîܹ×uÙ¼yó´éšg".tf¢xßA(:Ú´/Ü„!,íµ'!?%”¦”AËåbQBoº®9ñú³,+>^™Êú€"ž9އõQþoYù| ETËçóÔjµØ ˆ½#%œ­eY±Ç üM‹rò}®‚ké<,ËŠÅÈæ|†‡‡1M3ö@lFÂOM·ÆLs~­¼;…nœYÓ.;`eÏc놭á†!Âx*³‚tÈ]YkSBÏ5䘢(Sig› ™gŸ…UçGÿ1!S„ÂO$ÿæ@øõG?v’o:‹cÇÎà+€ïÀ[ž;—Çïâh CÂv†Ihbò„3¨mB¡Ð†I„€p ¢@"2€L”6åDÛËÑq9B3fDß3ÑöR64k²n¥¢t:s±ËaEiÔ&P¥},§-H Ë!¨ð¨(s£Ým‚ø] 6ü軼eÝQÞ[ÿ:y/G­A„Z•±iEéeNIxoÆÝ»wϸ0«x;~⟘u×[o½•믿žO~ò“-÷‹g¾}ûŒÅÈÈÈ‚‡ï=Xúøí­Î Äz&5ÞÓuÝïAÓ4q]—B¡o—µ}ß§^¯ãû>Åb‘ ¯Šh(£ˆsžç‘ÏçãéP®ë266Ö°æa.—‹Ë#¾4½ö¡ ^Ëy][yʶٌ¿þ8´‡vظüÐ!®¼ëJø ‰»Ñ,ˆ×±iš ¡­¢£¢,Œv¶ šÙ´ ~xð8œ½^°àÀ+Ã}o~¼âóÿ›ÿñyî{û3yìz¾h‘,ìx>¸% e=FY®P½4jH|‚´Ê¥þ/âd°ÝbEǧó(š²Jt\™°r¬I(zzÌ>Ùj.iº»é+se&[°œv@Q”öÑImEQÚÇr؇sHÚÊÃHQ:‡NhXÏ=ŽÃÙ˜<úâ«ÉŸÈaÛ âûÍq>EéeNYx¦Ä;nÅõ×_»@OÖldd„ññqvîÜ9Å…sݺu±±Øµk{÷îåú믧¯¯;¾¾>®¿þú]„xBÂAºåhXø¾‹†Žã`Û6†aÄâeY ÅbF­V‹×!OÃ|>O¡Pˆ½Ó¡Te@Ù'^ˆi/Åb±ˆa 2<<ÿß¶m*• ¹\Ã0Èd2±—`š´5 #ö`·.å•JE |—Ñ.;à™Ã‡yÛ•o ]‡js8&²2q ›ÍR©TbÇVaE™ín@(ÒÉ$¤¯€s¾ œ/l‡Âÿï;l«¿–»Ÿ‡û^ <óc\ŒrIýÙkxí øå3à­'!3oˆò‹å~ª¿’"\B(,:-Ò”HfdZ„¦mˆd Hƒ°½“öÀQÔ ôÆÌEÿ—ëaEÛKQš"‰7fš´P9wez{úzO—æ”Éå©§J×1[°”v@Q”öÓ mEQÚÏrÙ™<_%l/‡SЙܧ(KL»ÛaßÔxþyð<Àäà‰5@^Õ÷Ã$NFŠÒ뜒ð(/xs å]»vM%Íþýûg!œ¹ÐÌÎ;ãøÊ»wïæ¦›nâÆo¤¯¯ññqvïÞ½ XÎ2£É4Íxàk±|ÝZy݉g£ïû¸®K­V‹×o”u%´éèè(Ž':ŽÓà]˜^²ym@A¶W«Ur¹Åb‘ááaòù<¥R)+*¢¥ü¿ùøJ¥²HWdùPѧûh—ðßu¹á…’i3 뮊g¯ïûxž‡ã8 Ç^¿Š¢œíl 2•Omë5áˇ_˵ûOô¿Ûdò'/G%î~ ·üó 6œû0X;à_V¹.<¦Ô˜]Ëï§JZ„l¦Ùe ÅBéù$¢e.Ú'Þ“UÂÎUdÖ·m—®å(5¥ 5H(ˆÚÀ@”_Dt£ôÃQÞå¨l~TÙ.ß­hŸëDùK›[)Ò)4ß4ñ$ÿL3ŠhPæÚÉyˆÊØj¦{1ª¿I£ø*ƒT’¶é4ЬSë%¼®xÄV£úÉ3iDû}ÏØ•Ê\lÁRÚEQÚO'´ Ei?Ëi Ö¿æ5qXQ”Ρ]m韄}´WïßOàºdó6Õ¿uÈ\\²Ùåú§(Ê) ;wîäŽ;î`||¼!žòæÍ›§ÄWïÈ™b)ïÞ½{N º÷õõñ¹Ï}.66Û·o_pgB¬z„†dÑ猬‹X,Éår±×a¹\¦R©ÄÞ†¶mÇžŽŽãP«Õ0 #^Q„?Ók@Î%$èÄÄD\×VkÎ&,Ú–LYÚa$Ìáú‰ vž}#Ü0·ãd’€„ZM7*TtT”…ÑÎ6¬³pÁkáŽï«Y7œóÜéô&®†÷¾ýüôq(¸páêð˜N´6‰·£I(¬Aâá(m!ñ| óBÒÕ ÏÒ"â`ô—Pl3£üDØ+ÒèE) ä-^íËx;Êú”¡·hžD8uI„B9¶’J#ª•«üñDÛeÝž áo¥L6"§—:W5º²Æ¦¤ÏGLj)¢¤CÑ~Iã’ÖÁJ€IDAT8Ú—SÛ½Ô½’5>«Ñ'- §—"QYŽ¡r1'Ô-7s±KiEi?Ð&P¥ý,§-Ø|óÍô³¼myõR”ÙiW›À#ìlj^ð_nû ß.ÆØö áöÈoˆÿõ¿&)ñ~q4R”^唄ÇíÛ·°wïÞY_ú½{÷L»àë©0çä© 1—e€q±g\×=£d]F$ÄëPÖeÌår”J¥XTOC *,t¶D.—ò¬®ô`T”fÃÈŒ%ÏóxÃà¸*{լLj—´ a“Ei‹Ù&dF£ <|.»ï!V¿òuœ0áœW­â²óÏdãÝpûeðÜ!0wÀU{à¿Ýî+2=a[Ç$ì8eH<úä{Æ0«Bá­}Ä‹O9ÅKQ<ôˆò޶‰)§¤w Å´ÁèšFéÝè{‘ÄãRÒ GùAâm ‰‡¥™ª$"œ}ˆÒJèX‰êg“x&QñòL×O„Å2Éá"ŽvREàA±¹~ùTy²Ñö±(üFIþâejDe(§Ê=Dâ´_MSÖùÏV9¾ÄÊ íµv@Q”îCm¢(°0[0±cïXæòÊ:i„íÁæ4³W¦#d¤‘Ém+©í§(³±˜my·,à»ÿæfÎþÊßò»ü$¿c…ŽÅbèõX(ÀÞ½Oašf[—S”NᔄǾ¾>n¹åî¸ã6oÞ<íZ{÷îåŽ;î`×®]‹*<.&â=˜^h±0 #^‹±\.ÇÞŽëy6#dÛvƒð¸PÔsQQ‘ðs>—ößwÌ~ŒLû=U¥3¯<á©þ§¹â ¸ <øó\ð |ðÍð—7Á¥¿¦ùç?jw©gG&YY„^m“u(e;QºÑ诬é(Yº3Ñ”w.õñFt¢cÒ-‘\*í‰W¥„MÀ´Gåh´MDF ùšƒcÞÁƒä/¾8öX#±ýVÁÐjªQ¹>üÜs|ôÜsã«Deñ"xå™q]—œmÇáU%O©Ÿ b…ÆçMÊõkòÇ__sY»ÓL•Q«äÚŠ‡¥KZWDXñ†”0¶Š¢(Š¢(JˆëºœZVN&ÀI”,ɤ3i×B2i ’è#fô7KØÆ"isJ[×%™DWHí“ã¥ýÙüEQZóÈ#ð~‡Ÿe#¦®ï(ÁmÎ8c¿ð 5†¦(Àé§z`.—cçÎÜvÛmÜ|óÍìÙ³‡‘‘FFFسg7Þx#·ÝvÛ¶m›“+t»ð}Ÿ—_ŽÃ¬K»Í9¿b1œßîyýýý ‹Ê–J%J¥Ãó÷ˆ§¤¢(Kƒ¼™—ºœÓ_1s(ëµÂì Eé‚: ƒ >|ñ5‡¾ ×üu˜æœýa㹯Áš“í.ñÜI¯Y(â$ @d ;fk+•H­Ÿ:§Íôk–Ëå)bA@>Ÿó±¢2A€çyq¸X9§ˆy’Vê—{ôQ¬G¥ ˜'N`A(HV«qd 9Îü&¯vÍ‘›n ×îNm7€¡¡!pÝáÐ÷}2™ A4„ZÝuà@Ã43(ù>åbqÊy«Õ*÷ðƒLDõó}? ñ­+œ.‡M8™Î÷ýøþI¸ÖLt-&¢ºHxYñªTEQEQB&vìXÖ0«2I/GØN+¶‡HBí˺êÑG–(åò$Â¥M²Vz>ú+“ת©ã3Q¾å(Ý Ð}/GßO#‰¤!Ë1ÚÉ„6Y¶AÈ.вÉ‘e 2d/Umî¿ÿƒ ý=EéeNYxìëëãÎ;ïd÷îÝŒsÇwpóÍ7sóÍ7sÇw099É-·ÜÂç>÷¹Ž^_Áu]^uUÃ@Õ|I‡^t]—r¹L&“!›Í2<¶m388Ø DÖj5lj×à6M“jµ¯»í8–eašf\Ρ¡!²Ù,µZ ×uÉçó ëyËu©Õj†Áàà`,>ær9lÛÆó<2™L܆”:ɱòÛ#÷,ímïû>CCCX–†}MÝ_ ½Õü+•öÑÿ‹nà5?εí~0EQEQÚÈK.–?Üh©éœéúÑÜvÍI¸wU¸ý…`Û°~=ÜÕGO‡Ÿ†o®ƒñUÉ’²¼–ˆ›²ô‚CÝ%î¯Ч²>}–Dt’¥d H–kcÔöæ‘`Ùg¥ÒˆÐ*K`©cÓÛÓ÷ÒMå—^fBŽ‘k›#ñŒM/Ia4åe¶xV”Fäž_ûàuÀ0ß=Ù8¾']ß|>O­V›oöв"Y´éÍÝ"6¦ñ<Ã0pHb¥Ï™ÙnÛv<8%X£££ñÀÏB÷EY|`í÷_äªÉ«æÜ»Èd2T*þjÃ[–~Ò!W]††]¢ÆÆ•" ŸoT-r¹ÆÿG9qþ ÁuUüT”y°ññŽW½™ã_-ÿ ÖYð“vøêžs"LÓ} =×¶IµZÛ9é<2™ ¹\×u)•J¸®‹išd³YŠÅ"¶mÇk\ ,ËÂó¼pýÃHÔ"—ËÅb¡xf2™X+•JqûÊqr¹AP«Õâõ«eÍîjµÊèè(†aÉdø©;xÍ3Ï„,Õ*oû£?âËgœ×!—Ë‘‹bãH™D,â2H TÇÆÆ€Pük>Æ4MÆÆÆpÇq„Â\._/)¿mÛ± )é¤^iWö›¦kY•JlÖqœØëqbb¢å@T\Âô3ëÖ±)ª‹¢(Š¢(J¯rìØ16:›6-Û9çÛ;Ÿà ö¶²,pœpŸi&¯¿ ¾òÚ…4GöÏåB1ÊñÂ<O? U ®¾ÆÏ‡C_ƒ+ÃÅ×Âwþ>3þ'Ø´ß<€|j éôðò–ðû9'à¬Çar+œûZ÷÷?g]ÖåÌgÃk½c=ü·cpü‚¤<ž€?~cžÜ}/ÁäpÖqxñ<¸üPå'͆IXóTøýùÿ4uˆ^'-"?ò¡µðÇÉÿK%qn2¦ô›¥—éé¸Jžçñš[n‰g|Ì™©/³ìe¨P(ày^<óÜ0Œx_×Mô ß?ª (Êòòú»ŸâÑ¾ÓØjl6̓_þ2?ûY6îÜO(âà† üv½¾Ì­°m¨T—Ü4ÃV|sD”Řf ^¶»nÒ°í°Õ-x &ÆÂãSƒà”Ëa>"bŽŽ6Š˜™Lbˆ 7Â9çÄÇIÞ…Bxk|/À´ …°Ýþ0ÁK}¸Q }{«Õ°ø•ÊÔrØvryD¯vœäöØvx+ë·vðÎwšßõ뤯}Nð<_[óøÀø` Î3ØWF÷g1†>š…¨SªcÔFiÎwppl6‹`"Šçž´oD0<Ã00 #ÞgY¾ïãy^| „áè]×et4œî%"„3CElKo—N›ˆÒ¶J‹vép×iP<3år<ÁìÙgŸ%÷ñ·¼.Óug §mzšó‘WÚ„RÏæ¶a«¶â\ïµÜOÓ4ãk.9¦=†pÖ:À³ÿò/°cǜΥ(Š¢(вùîš5œsâD[Î-}D™+,C2”P,6v·GG“mµZ˜>Ý݆ð¸sN„ #fæ¥e…ó¤!Ôkká—ý5èxŒ‰ð¡sš¨þÅ"¸.WzGúûùö«_Í`>¯Õº[^Й.jz@ºi ßó ÌRÃHtA/ZT¡TŠ’7{P6B[VØë^Fs ^Žó¼0]s9DHE­P˜z|tb1Ðóݼ\7/ÓƒíµÚTq3­æ5 ¨ò’ZÞÇþ‚àÐsðÁbýî.|?ÜeøŸø{¿‰ŸR°¿ÜÿØ?ÁºâEŒç…×/*—낟q0)ãbãaábaaqeå02Q/Å ÀØt.…h PÇë±½d|O‚ö÷ÃŽ‰Ø÷й;ÌãêËŒk’Ûwï½åäð°°ððBüÎû>˜ö;øO¬Æ’ú>þZx×»Îc ì@‚åø;~ÓìO:{÷ø.Y ‚þgµüäO>3Ï7fe#!n„s½çxÀîgËSpI?¼ñ)0ûÂ{#¿ÑË=‘Q”–šÓ‰‘²N`:Ô‹L”*G ™<%t²^a±XŒ´áááX˜Q0“É0::Êàà £££X–‡ mÆu]‚ ˆ#M¤‘s4‡£i%†Ñà82ñKÎù@¹ÌŽ[nYÖ{–ÍfcÇå˜ù*uu]7n›Nw­¤4›~˜W½êUËz]EQEQ:­]Ëú‰‰…gÔD4våm;ÒŠ2n#û¥Ù(ßkµ©Ã£©ÐmÓEaIÓª):Mó½áØô<¶RiªgälcLMs}§íCÍ·©<×ôoXo¸F ÛX—™ò•‰ÃS/Lêû…ð¶+wÇ—kKãõI_§Àj`qÌÖæë˜JjUÖôþV“bmàWÓþÍÔ4?Ÿ›ö¢zÜx×ßÿqn¸‡°~áøÑÚ1üÑÆ!/ÏóZNðU”^¦§…GÏó8üÞ÷ò®yW.—ãÐ[Žã²oßFêõ1.ºèp@²Zmüц„âRZتV“mé±ýr9ñ¾]Â}I'”™ƒf"íü#ÿ!.-lÉŒñÄ)ˆÅÑ! #ü1 TJ©„t=šÿ/b›ˆhò}h¨Qì“FˆhÙlX.ÉOÎmYa>R9ä5<æ-õÏd’™\år¸¿\N®‡Ü+ADbÉW®a$Be¥Ò؈L?rŒ”Go"˜fR6"ä¼r½åÿig7àdŸ¬?&ÏIÀ#¼uþË $øAÀ‰sfH”Ëñ»<ÀèÄ•}Œá·¼%<Ÿ×‘ÎŽÓø<–Jɽð¯ë&ïVÓµèÓ=”VÌÔ›˜)3yôÌt¼œ7š~(Ï©ï‡ ]yí_ÿŠç]@pü¬¤Ø‘X†n1©ÕFcñÀ>¥Hõ}0³Ä—Vþúõá'}?àÿü/_‰ÿÀyÑ…«&×¼P¨ÀÆçðþï0¯ìc8;¥ àW¨õÀ8;ý8»€]´º*á¥Ú\Ãhæ0¼]×c”ÄXvÓ~ ôgÉÅlêñÄçù/£”dŸçÕ§)€â· ›#×¢ñû¡ddä JH‘dmŒ¾9É[åAþá'~’3ŸëRðÎßmtH^n¤33¥ìÑÌ ·)¡T«ÕjöÔó<†‡‡ãП²è½bÕj5^¯Ñ0Œx‚E&“Á0 ŠÅ"•J%±d¿„P ×uãNXišþB½8§Ã0ŒxÍE«P >·ãRÒŽ5>Ò÷B¯KY×R«òÃGaí+_¹ìeTEQEé$N®YÃeçŸJÇJ?ò¼°Ÿ[«%ã[Òõ“¹¾H¨Z ÓÍÔî¤Èé± eåa°eË7Û]ŒÎäØ1&ØÁ%».ak†ß‘ ÃeÛIQ:˜ž}ßçÄ%—Ì;ÌjµZ%—ËQ©T¸òÊ{xé¥ÿãÇo£Pƒ%ÁL³UÒÈ f:¢8é´ŠÌè8©ð|)M„³l6ÙžvdÑK-넱±FOÌfÁ¯TJ0ñÊIG;lÕH¡+-¬¤cÎCã~ÉCö‰&’®“ä#c—¾ŸÌô1GÒT«aºh,v éÉlé° Bó=l•OZ“™Ë€t«4éqØéž“tšVã¶ém³MÒ{ï{¿ |`öÂö§?ô-:k¸fêÎè¢þ¬ïóÏ£Z­âº.µZmÆArÊÄÑP& ȳ^«…Ûä}’H©r%ír"ç“27{âÊŒÌlJ¨K{ÔÆÔ5#FGÁÏ(lÆ|m¸]ÒË'=°Õ{ØðÞå¶´,òü¿™±ŸO®µØ¾F;z.¹Îp1Ò‰OU ™ëqsI7S/3½¯UÏOÝæç…G(>Nþp×îøI^ý=øê£à>Æ!°66þ>-Žã̹“’öô‰@çÓXŸD¤L‹ƒY¡,m¤#ßå:x$B-„"¬LŠÊ¥Î#ˆ¨Y®¯\s‡Pô”k4D"ÚV£`Dçð …ÞrSJ©ý7íXÔC>ŠrÊÄæûÛß Œ œ^£7½>ïbaFËP¥žçÅÞÕ"6¦½ Å£QÈf³X–Õ.›Í¶ Ú.Úæi žÅb‘Ñœ}*!ÒB³xÔA@6—còïþ.œ²¯4¶¿D˜‚¤Í[ ™0˜&­¯Ï°t2YZON¬“´ÿ¦›¼˜ž30Ûk]™e[Ž™½÷€– çfÙߪ¾ÍŒÎá¸RªŽÃÓä!ýIcÜùžžešþ¿x©ÿ{„ý(é«H_Ã$ŽE,DÛÓç”:I?BT1ßc©s‹'©< Rf‡FÏô=2SߥO)´éN­ôà ’¾¨ôý¬T9Œ¨ÌQ_è ·|·òÖ9ÜEQ”•Kfš(ž—,W4:ºò¼çƒ,%£(½@z˜wâð›Ø1±h|,Ëbtt.[Eé-zVx8ûïhE'=;ØuÃOmoß=ý;Joçg½—³?{6Ç.9Æÿ~ýÿg¯Š˜–dìFf±JGÐ&ì¤JV:µÒ1•N¡|Ï‘tB[…ü‘|ÍÔþ:IÜ%é”Ê,Ù¡èœ2+7-4–HÂB‰¸—ž)-bWz–o‘ÆAÏ2Qýó©ó "è‰'gµ)Ù⼂t¢Í¦´rß2à^îö”§c1:‡•:oF1/“ª‡Ì:6I<öD¤tRßÓáŒÒiZÝ3yNäžyÓì7RŸô5¡4}=DÜ”cË©ú¦…e9—YO=ö€—¿÷2B¯!2™ð¡i1;É0 Î8c®kc‰¸”™²Ùð<ÕjÂTÂ$϶†§¢(§Nùg^K~ã©ðÊØk8—[šÎµ¬Åhš&¾ïcš&¶m“Ífq‡L&Ãððp,&Ê$ˆV´ ƒjtÐH»ËbÛvã´Ôatt”r¹ÜpýkM.»{Ú]ÈN$í=Wazp)èœ×¶ó‘ɘÐZdµ§ùž>ÛÛÍ÷:mZ%]eš|­ßÍiòšN4nõ¬µr—É‹¥uKÿ_&BNW¦Ô5øáÚ¢(ŠÒ«|wÍÞ°e ŠŒ¥R²Üˆ,§"ÛzÏ ?ª³(½ÆÇþè _q˜ ¸ a{¹\&*‹í‘ (]NÏ Að‚m·öxŒD3χ  þyð?v‚Ì×Oã·®ùo|úŒO³gr¥·—ØlIÂè vÞlÃ¥ižUœž•ÛªcHj3lkÕleïÒ‚E«¥–Òå›n}“Ò4é…ôxÖ³“%ùDg+¿ At^’ðSÍuI7’¦rÒõkUÎæ‡VãÁö4é[íŸNÈ*Mó}ºãZ¥IÍÿôO}š;¹sÖ˹ҹ`ü8¶K¨*ŒM}`E ø·ÿöÊXø[®¶e-¾'¥¢(Óc=3‰÷Š>*õÊØSX<¯õºÆ§ŠÅpµm×uq]— ŠÑA¼F„„(µfoGe ” …$œvQ,cA[™e$KÒ®ëñÁE¥ƒ)Óºo¡(Š¢Ì›Ã/¾¯g"˪Èò$ù|cXÕ^G®ƒëêr+JoñòË/³zÛêx9!›ÍÆ}yEQzVxü«£GYuìV4«)ÿ˜  {þ`Ó“¬{y•Ëþ†;¾““לäþ£÷÷R¥&VÊo76ªL0WÀxrç°rèœ?¾Šõëׇ­åÑÑ)=‰ €_þå>xà ­v+вÂ0à-_?ÀW˯'SNÖ@ïTg7A@>Ÿ×X”5 È¡Z­†eY±ÙJ\ñQ…ÇyR*õl<(çO©£ÂìáG "®ÑBzQØr94"é˜l²ß÷“é÷ZF;=/4<Ùl£ ‚dq%‰¾Ï£=>¿Äo‡ðØV‹J‹1ݧ\/¿qa«f™.ƒivo#ªÕBÙí, „å‘0°‹X´ó^|±Ý5TEiß}ê)8r$þ=µ¬d½÷J¥{Æ–¹½îù©ô²RاOÒ÷èÅü—¦e´$Š‘¢(œÞî´‹ƒ[·2ð½ïMÙ¼Æ!óQŽBá÷áCG?Díã5ž¼áINã4Žýõ1®ºöªÆõ·sØÞ1~Öo¶»0J§â't’§6?nhT ‚€¡!xøásùøÇ_£ EYÁˆ$•½óëüéßÝÝr]ÔVk¹Ì9ÿÈ£Âõ‡††( †eYñz{@jUYdl»qñÛ!—Ë©ð8W¦ŠŽ¾ŠgÍ3˜3 ÿ¶Ý$.{("N‡Ü›fQ±\óvœð»ã4×ßnÏç[‹êŽ.].‡Ÿæ4²®õÐP˜W«0Ä®®ýyÚiaYšë!× ¿¿u=¥ ™L˜Oó:¢Žæ-Ç 0eúx&“|¦ž£ZmÌ#“™z9~h¨u††’{Ù¼_ö „ûeq¯tùúûÃ2œvZ(Ö6_CÙ'çh¾Öéë(׺Õ}L>‚,Ë!ÇÊ9šËQ,&åë‘Æó``€ŒŒ (ŠÒ«ŒŸ~ü=ŸÅFÏ ÿææ:!©Çè”y9вÔÈ£~pÝçðο§Ç t²§¢´¦g=¿×ßÏk®¸"ÜCà¸`n‚Ún¾ÆGá_ÿð_9ÿáó) T«U àT*-äôÊb¼¬¿÷ÿ‚w²‹OYY¬{ü1í{´å¾Ÿÿùçøú×Ï!Ÿÿ4>øàªùe®(Jב»{'Ô0Ø Ìµcí8Îáв, …Åb‘ ¨G˜x0Öj5í¨(K‚μ#>ášíq=BÑI»B¡Ñ#°P D­ÖÚ¢P˜96óLýÃhú½Ù⽕J3ŸÃ²’ÑÇiô†FG=#›ÅÕZ-<Ö¶“˜Ô3•¡y¿”ADÝ ˜Z§ækؼß4ÃrHÙD(–ÿ»n£ñn96ŒÄT»ì׬“‘+õOcûkÂæT¹œÌku]WûóŠÒ‚ž_q?óÐCá`°Áûd7†‚£qÈ3×uÉf³*8v–Ö£Àó`]ÓîÒ(Š|ÄûKú^š*<ú><ùä œuÖ;xÝëþ¹Üo´»¸Š¢,1æ ÀWÌÐ80uüz®¤…Gß÷ñežKøÕÙ®ñlûg[({¶û(å›.]sý›¯a4n›.™®Ý\ž3I3]ÚôöV}Ù¨ Ço¾yös)Š¢¬PžY·ŽsÎ9Hæ{Ìö3Ò-ø¾ßR¤šn»ìóE±ø7är¹8/š¬ä8¹\Žb±H.—‹Å?e|µ\.S(‚ ^Ž"›ÍÆÇe2™8z‡eYñÒår˲ð}Ÿ\.‡çy˜¦ rérzžŸCÄ@Ó4)‹ÔjµøÜ"Æ‹EJ¥CCCq-—ËQ­V)•Jd2J¥ƒƒƒ”J%‚ —ËQ.—ãtRÓ4±, Ó4ãè7ˆ‚é2Ëw)C¡P`hhˆR©„ã8”J¥x{&“¡R©4¤—2 “Éd( 8ŽÃðð0ù|žR©×±\.Ç×¢R©Äu’:{žÇáÇÛýØvæóÏÃ9ç€ þOB°·qÿLB¯¢ô2)<ÞxãìÞ½›;wNÙ·gÏöîÝËää$×]w»wïfóæÍóÊ_檾cãÆð‹Oª¦î@ÔóÍçiQÖòó0ú0®¸ÜS¯IzDÙ÷[×w¶k’ž>ײÎtÿæržV×4ã$ǧÓI]ºhÎRÛXýüC<~Á ÛËåðµ+\ªÕɸѫ(J{Xj[ ˜û ½ŒÄ¤ÆüC+9Žƒçy8QhÄr¹Œiš 300 ‹Î·ƒb1ü]Tᱫ™Î,ŠpI¼Ç gZµEiËÕ&èx|Âu#Ò&e!ÈxÁ¹ç¶»$sb)lA¬zöÙi´‹é ¨V«±¨&i‚ ÀqlÛfhhÓ4ñ<ááa Èû&ŽãÄb eYض‹cŽãP©Tb-ÊårœÆ¶m6oÞ‰eYñ9ä<¹\®ALs]Ïób¡0›ÍÆâŸmÛA@±X¤R©à8–eÅåÅuÝx¿iš†A6›ÅB/¢FŽ!4›ÍÆ× ñÔ¶mjµZ\¶R©—]Î/瓈5žçÅõý¶mS.—Î-Bk.—‹–ï Å<©¯xazž× ü¦EÊB¡€mÛŒŽŽ6ˆ¥²}bb×uã¼äœ£££˜¦ÉØØXƒ ,â°<#cccø¾_Ù/u6M“›»`2Ò²¶ ž|ë™gxõ^ÍýÑ8Ì'ÏV¥õ£Z­Ö/½ôÒú}÷Ý7eß§?ýéúàà`ý®»îªßwß}õ÷¼ç=õ÷¼ç=³æùéOº!¿áz½N½^®× õzý‚Zݶëõ\®^­×ëccõ:Ôë¶]tË–ú·®½¶þì_ÿuc¦ccõúðpã§™B¡qÿØØÔ¼pÎgÂ4Ó•5ýiu]!©‹mO9O¼O>¥ÒÔkŸ®eM=a„ÛåÓ¢>qrÝÒÏÛÄDxM3ÜoSŸG9Þ²êuèÿýWÔ;™¥°õz½~ÓM7Åß©×ëu¨×jµx›¼úµZ½^*•ê•æçFQV÷Ýw_ýÓŸþt»‹1#ËÑ&¨×ëõZ½^·¿R¯×£ŸkÛÍ9L5ɳaF}tt´nF½^¯×ÇÆÆâïòWYfäF¶jÿ(-߉Nc:[°(m‚‰zØ(ÓaвbI·“;‘¥h,I[h¬Ú•fjѾ±z½nÕÃqˆáèÿrœ¥ËÕC»$Ÿáz½ž­×ëf´Ÿè;õzÝŽ¶YѧåcG õоÕRßsQÚ‰Ôù¥ ÃõzýÖ‰ðóûa_s¥P‹>Ë…\ÏBÓy›‡ŽFëÉ3#ÏÅÄ y6ÛŠ‰h_)ÊSî}úy›ˆÎUª×뻆ëõkJuÏñz¶0”Ïׯy÷»ë0uj)mq²±±±z­V«W*•ºaõ\.W«×kµZݶíúèèhÝ4Íz¡P¨†Ñ°]þ–J¥ø8Ã0ê•J¥^*•êÃÃÃõ±±±úÄÄD}xx8þT*•úXó˜dD­VkØ—6 ³Ø‰Ñ张ʢЋm‚éêM½^~öÙúãçþiýŽ]wÄÃÉ2D,¬4£Ü1{÷îå¶Ûn›1Í=÷Üî]»Øµk·ß~;¶msÏ=÷pÝu×Íù\€ëòæ¯ÿÊýp¡ëfŽ&Ã&Ôë \r …Ý»¹²ÙSl.áf ËšÎc:O´¹„vM¯hÛŠ\nv—¡ß°í©­Ê:[ygË#›}zÙlõµ,FGÃÁì­P¸õÔÊ:‡ó̺Ï\®ýÄÄì瑲T«­×n‘sM·ž¬¡“ÏC.Çî½—Ÿ¦óX.; sâ9ãÕ ³’‚ \ŠÇ² Z54F»¢´‰ålxÏ?'¿–9¯ŸÊëŸÝ3ÙmÓ4ã0í••¯©[QÇ®c6[°hv 8E0rúœ(J‡±Üm‚)$‹;MǯypÐ…—|ø‚¦ÿ³CѱYþ°‡€ €we¡šƒrt|øÓ~8Ç„=ÜïÂ6ü^Ô4€ÀÉ"TM° C3”+0a‡ž5àíø°g®—ÛàK?˜ô <çZðœý(¥Ê2T„J9©ÛÇ€±z¸ß €EvZcÀ…&ü;¾5œ²ÀC.üž ç«LxS—çàSFdo=xMOÿøgÞg…œeàp¯ñàB`°x‡žSîËa\¶Øp‰ ßB;žŠÀTáp“ÿÅ„I+¼V^ôù† Ç¢s~†ð|e;Üç›xÉWøaÙ×-…ç—<ÎqáÀIî‹|ƒ–ÁÎsàxø5ð¡P ïI@øªð&¾gBÙ€ßÈÁCF ܫµ>|1€ÓøH >“n¬:áqÉ?ëÏX· Ÿ÷Ãò#7Öra޹ðüÂ^•¥f©mÁYÇóì÷/]’`­BšV«ULÓ$“É066{Á‰×¡çyñ:ðår™b±ˆã8LDãG–e1GÉz}âY'ýY_P¼àZydÍuÌ£yiˆtV³yzê:‡ŠÒLÛÚkÖ°é¹°ví^RN¶@èe¬Ë²)Jk:Fxܹs'wÞy'@K—îýû÷3>>ÞàB½yóf¶mÛÆ¾}ûæe<þñÈ. VÿÖàÃ%‚ß*0Ú´|‹ëºqLnu—î>ŠÅ0ZÈŠ³ý­DLØÛâ©XÇÿéŸÚ]“–,—@‡‡_zKü~û> &Z²„ùPeùYÎ6?þME,ñq>¤ëºñ&i"ášu-GE™3Ù‚E³eೃð‚?ý.EQÚÆ²· «À¼ÓKÂQ^›…+-ÈjFÿZ GV~Ê‚˹„¢£åQ2á ÞI(üT‹PKM&õ ðՇ‹ 0JS•š ^SŸÏ²EÑ¿,%K…Fø­cLð"!òð1áeÂt6äàã¹ðØ#À׃¤óäŠq4•íBž‹ö„‚[¿«MÀÓßµ¡ ‹á…ýЇ]øÖdáo+P"ʾäÁg2¡py¾ ÏúðÿJð±lXð3pv/pާà磺d‘ñ øœáÁç‡a» r6àf`‹ Ãf(:nÉ&u5¿-ÃS šð:`«?åÃËÑ…ÍŸ)×ð=¸À„7”B19'×#zv¾ d£µssQ= À çÁ[,¸"ÊçžDR¨;ðZ 6p бÃRàï<ø‚Vt³ü¡ÆÉåE?YGàÇ xÞË.MÓ|¾Ï󯺜Ú+³Ô,‡-8묟^ÔÕiljÇED”ð¥2Q±^¯“Ïç ‚ Ó"†„õLÓܧhîs´bQÆ5EÈV”6Ѷ6AÄEo¹ˆÒMúïüÎcô÷_ ÿ:~¨(SéáqóæÍ3Æ[>zô(À”ØÍëÖ­cÿþý3æýâ‹/òÐC±nÝ:¶mÛÆãÇóSß;”࣪Õp™½´ƒ›Ä·Îçó*õ FØN!j”ËK¬Ê抲ᡇâÅ_lwQZ²m‚†ã=Ïc\A1Zr×óB{0›ã{×uãu92™L<YéÄë¿yzj399ɾ}û8tèP»‹2-3Ù‚…¶ žþyFFFxÃÝ/³úI/Œ@¡m~¥Ù¿?Gåùç;ÓÝi©û‡bdd„íÛ·Ó××nt Ø Àan‚; è·`£ÿ=€_$€·gf2¹HL”4ͳcMà·%³i0ŒÙgCÍÖw™)9ÔHu  à5Q¡ÓºG}–Ù½¶ Ö e-5gØêšÙpW=¦®eY"ô朮ßr¡:áûIz©BašˆLRüR)¼w3]³\tŽ hý;2Ýlèl*#¯E£óm©ï…¥6`§Îá×\ÊàûaT%ßçÐÆ=Ý?xúé§yâ‰Õ¼ûÝÓ$òß “P –gSÖ‰v¢}&Lþ¯I}íƇ ~ù~™ßyÍï0ù¡I&ú&¸ë±»øw?ý&Â<øoßýoœ8q‚>'eƒ"Çb†£ï‘÷+áó áä)‹ð(7•w,:Î$|Þ›öÛÑG¼jyȹ!´‡â œÎ#K8 £9=MÇy©sI&wX„æ@ò²Ê>Rå¢<ŒèDÇU›®SúX©ûäGy”i´-9Ody?åšÈ¤‰\ªüérK9ÍTY³©ïiä83ÊÏ%™à!eMWjª¯ç¤Ê9;c’<«¹Tùåœrm乑߻lxìäç&yöÙg9ÿ‰óéD–kÌpÊy¾ ïYó~ñÂ_äýCáÏm?—\baY–N0VVû÷ï_”6AÇKÉ /¼ÀþýûY»v-Û¶mã‰Õ«9¶z׃¶ËšÛèÞ@ÙUºµûSgdd„ãÇ·»(máøñ㌌ŒàoÚÄKÇÖÇÛ¥¿%ÞŽ²€yA=”ÊÈȇJØzi9r$錆ӌ†ñ¨Ù!““òù<¾ïS©TZ¶$Ä’ïû¸®‹iš˜¦IS&9A/RïyA`š&žçMÙÄ^–¹\.ÞnY®ëÆÇʈӤóÒéÒe·,+ÎSH×#ëº-Ã6Év·y0¬©îé _Íùø¾—Ó¶m<Ï‹¯ËtضmY<¹iû¢s·*ƒeYø¾_3ÉÓ²¬†2‰ÈlFÃwI/¡²ä™ÁAœws=Ï›6ÔÕR…ý>zôhl z_}ÎA.z³­¢£Ò³ìÛ·ñññŽ—7oÞ¶‹|\3Äýý,lƒ}&l®ÞM8h=W–y8A~W üM’6D\œ¦ßni ´úkÛ6¾ïãû~ƒGGú÷ˆ÷LÓ\\(hoy]çyaOe\Ç ¡½5sÚù1Œù †”Ë`Y|~íZF£w¡×xá…x衇èïwÈå®Jv£¿éÉ>¡à‰n'¿q’UåUœ¼æ$«ÌU|õ«_åüçóÈÚGxëO½•uÆ:}éQþÏú?|Àú_r¾”ˆ}‘H´*ú ÞiÍܦA?b“‰ÈÔÜ\4Hô}]¹´h'^ÂéóKc4Ú0FÌ$™„A*½›Ê˧qADÀ%•ÎŽ¶·ª¯\ I+u—®LÚV¤bÙ–% ‘l¥ÒÐâ\Íåj•F2MûDàË6å!çµ[ÜÙ/ùX-¾Ë9íT9›ë!Ï–›^Sé¼äØèüÏ>û,Çþõ{ìcô"2f¸sçÎ[h½û·ø“cÍ<€ï‡“”÷í;išäóylÛV§%eE±oß>öïß¿à1Þ×®]˵×^0>´z5ÿéŸWÇÆÖó'þ Ń<º“²’عs';wîœÓLŸ•È\ÀîÝ»)ë}‘‰¡GRµöͤ/jY£££í.®¢,»wïfdd„‘‘‘veÙinøækáéuqhÕ&-®%².‹mÛäóyr¹W]u_üâ¹âŠ+âÐJ"`9Žƒa±(˜QÊó¼)û€8ðÑ,Öó<òùpÊ­œGI=GGGjeQò©V« ›ˆjé¼-ËŠó—µhDD•AÊr¹×M,E(l&}]¤,"f2™)Â[z@U®töÒkèø¾‹’v­ÆÏ:DP,NÛ)”{*õ$ô~ZMï÷æàIÙœ¾•G}: ia8=xlFüÜø¾ϲ•gC®YµZÅ0 …BHؼy3»wïfÏž=³?ð+õë׳ûm»Áñà7çðÒϹ‡éÉÃccœö½ïÅiŽô÷óæ7¿™ Oœàëû÷óóÎ`ã¡CœsâDœæùÕ«yë«_Í=?ü!¯=~œo?Îh7ÀÿùŸ9ÿØ1ÎyÝë8qá…¬}äVE‘-äyˆm„^LÙæ÷!ý.O÷n¦ŸáVëVµBÞSy/›ß±qRÞźéõ­ªÕp13y?Ä–¤Å”´=nFÞ7±bÓÄf¤',¤‘¼ÓbNÚ~KÝ›OÛÛ¶ãÞi åIÿ.ˆýH#eMo{wàÀlÛæ«_ýê¢\÷n㪫®b÷îÝádí…«JðÅ\2P;l&·§ ]É$üÒÿ—ßÈæw­éýÍhä·9-6ÿŽ,7Ùl6>ÚfÌT&yWÅ>5ÛŸÙüÓïTÚ¾H^érµ²ƒéwQBé§ë ï^+û'÷¯R©àºî» “–ÄŽHùd»LFJ·×š…Þt}åx‰¶Q­V)‹-¯W«|†Œçázà¡[o]ªG¢cY»v-\pßüæ§ñÿ¬[ŠGwðŒ®ÕY±À0ÂuÇ~vÇÏòºw_ÈO­~ŸúÔûùÍ?û3Þõó?ûØÊV~ãC¿>ú%Âdí”÷+áo´GÒ!q›<•ƒ ïeI4\ìÔ³Q­†ë¼Æy’x½Ê¹‹Åd¿xMkL¸îTÏÙ\¬Ôy¼*8Ñybï¼èXás{°ú~˜ÆŒ›Í'O2:1Áúõëyêî»ñM“U—]ÆÉ“'ÃÄ2(dš¬~þy~tõÕœùì³±0ð'ÇŽ±éïÿžC¿ð œ\³€³ŽçU÷wص‹¾Gå¯É­[Yuì'׬aG4¨üì™g¬^ÍøªU å\sò$×<õ_zÅ+8qÎ9\xâÏžy&NœàÑÔlÕ Oœ`óÉ“<´z5—>û,[''yæå—ù‡—_àâ§Ÿæk›7óä¦M¸Àßþ6/|üã<61Á9ï}/îW´¼V}>Jÿi§q"Qåº<¿z5ϧ_r ëûûy6:ïÚµkÃûû™Ø±€³÷íÃà…^`õOpÁãÇ×éÙW¾’ÉÉIÎ:~œ5ÑLtl_µjk×®eÕ±cýÖ·87“ṯ}—·láEßgõÏü ˜&ú補8ç& Þû^N{àž”A·|¾a°sÕÕW³éÉ'9´q#k``€¯zÅ `õ¶mÔGG97ú}èûÉŸäœ'8íÈŸw«Žã3ßû/oÙÂê‹/æäÉ“¬^½:Ì<“áùÕ«9óÌ3YýÄœ\³†Õÿæß°ö‘G8vþùl8ã Î9q‚£ßúpß}ôßp¾~=}oz¿71Áê+¯äÌ3Ï„èü¿w饬}äúúú8pÉ%¬Ÿ˜àôØû補xÓ›8m`€'7m¢ïÑGYûÈ#áõû‰Ÿ lxË[ú:¶•Ei‹ð>ŸKÆ­½‰"Ò"–뺱­–I9"L§Eíôï<0EÈ·m;(›E0™l"‘YZMX‚F]&¥óHO.šÍ\fº2qGʉà=]›Èqœ8zD³@(×£¹Ì²]òO“žô ÿ—ˆrošï‰L¢’²•J¥¸åyÙlvJ‰ô}±X,âû>éØý®ëR(â2;Ž ´¹\.®›¤k&=™+M>Ÿ§Z­’ËåbÁRêž>®P(4ÔÚÐÊЦeA&Þ‹.š×3Ñiœª-øÑÂß#ëÖ2\@®”Bý‰°ôáÛ¯}-Ù¿ø ²Ù,–eñüÇyóSOñÅuë8ýýï‡÷¿? ܾWŽ35ôó»TnŠwÚì½êya>išÅ|¹¿3MŽ“}Fj‘ûf$™¸Ôjÿt!†Óç!­ÕyDl³¬$¿V“dŸ”g¦:ÁôçiNŸîäóÉõ€d Øu§^óæõ4›ÅQËjÌÛ÷[ßÛt>Ž~l;ü+!¹ <6×nMç)k¸V*畲Ë~£…=8ž+uÍ^èt3‹5N ¼ôÊ+ù‡>lˆõø³Ï>D©Têʾ¥¢,]#<Šg¾}ûŒÅÈÈȼ‡•ù:·| Ûc»-vBf+´ ?¦(J{Y,;àÖS±zÕž™L¸´“Ðì¢(Jg±X¶¢ ¾€¿§[DëOÅb4‹Ö¶m|ðA6mÚĽ÷Þ˽÷Þ ýÜÏýܼí‡iš±àØÌ|:12€6£££ óE¼kº Û¶)ñ±Màì&Z]ÿùÞr¹L‹Å†6îÕW_ÍÓˆH̢؟xæ»Dß’!—"ðð /°ïì³Ã ×\Cߣ2òƒ`­_Ï‘þ~žøÍßäÏ<ÃŽ‰ v¼æ5|c;ó⋼þÛßæ¢+®ˆ#|kÖÄc—&à¬Yƒ·kW À9ï<¼]»â4Õ­[ŠkÖ„iûûã¢WI"u ÞªU nÚ„M]ÍkÕªx"|TW¯&X½šÝ€ÑßöúûÙB‰,¸ä®'Y6È»âŠ0"\T†?LWÊàîÖ­q½å|AìüÈó©-[¢˜ÉrLrLyûöd‰&Ó$Ý#“z¸©c%ڛ‰™†ï˜f˜g$K4?ª€cÛ K4µBêû—Gް~ýzxó›ãíé¨o1)AOêIêyó`ëÖøz—_Þpxùšk"ÐÉ1­®ƒ ¸;v$Kcõ÷ãö÷ãïØ/OeþÖ­øÑ3ðÂÃs—†]^´6 Î~~ 'y@–Î âˆi±Qì±üΈ¸%¤{çê% Ìyͨ™~Zýö-dâÉl¿=ésJ»!—„_Žv‡iš ×y¶s6ß“éÒ›¦I¹\&—Ë5¤‘ïòwº{<ߺg³YŠÅ"žçá8cccs¿ÇžG€ïsôo\‚«¼<,Ô|øÃïãŠÞgï‡k³SµÔ€Á¡¿ý[>pë­ÜAòÌ_|ã¼"—ãô™ÚÙ¥YÖG…Ù™·í©be7Ÿ'—›*âJšÙÊ2—<$ê•ë†z$Ϲ;›ãŠeÍíš‹¡Ølgê9æ’çLe÷ýä|Mö±,~šîc1Ç Ò<ÎóÜË'Èf‡c}yݺg€Î\ SQ:…®!tóÜ»w/×_=}}}ÜqÇôõõqýõ×Ï9ÿᇱâßý0îûBÁ!QQf‚ Ïf¼Ei ‹aN`Á_ˆã„mº0ò˜KµZÅqêõúÜóSeÙY [Úš ’‡L¡qŒÁ÷ýØË1›ÍR©Tâpžô+_ù ×\sM»/ÇœÈÍÖa^¡dúû©|ö³ì¾ñÆv¥­È ¸Ý†ö÷~ï÷Ú]´SfÁvÀìðO&Ú$¢ÑEÿôO<þùÏóÓÇ“Ïçyrûvr[·BJ¬`Ó¦ðC¸ìg³¹Y£ªµÚf“T­†ÒZ½Íá²Irl«!gƒ©KÓÍ6¼8³³¤›ÑÊD^‹³‘®ïte›©Ì-˘PËÎvC¨IÖ¯ŸW¹N5mŽé—¹³ç°mNç¹ürnþÝß…|`5è¥Pvàßäàa3Œ=EÛƒÐ^ Å¢a6›mXše>"ÞJð4WfÇ4Mr¹\K¯Å¥@¼8Åsr^ÏY©ÚÈb‘‰z—²[ðâÇø•ÉÃõæ gµZ¥Z­ò@*Œ:°l÷ZYl»q x¹‰®Û(2FK^ÌkíÖ¹`¡ 9¹‹X”6A„ô Æ/¾Œ'cgT€+¯¼ÃøùvWWQ:š®wïÞÍM7ÝÄ7ÞH__ãããìÞ½{^ ]ú/¼ÀYÏžäÄ…'ÈçWS(L §VZaFWQV‹aøÑ ¶ëÛ|í WÄ¢#$¡rÆÒ!-EéHà ½† _x’La#†Nü”vA±XĶí†ÉH²–¢mÛØ¶Í7¾ñ®{•-[¶ð+ýý\pøp»‹ÒQX–…eY>÷¹ÏÅ [nß¾}Þ†Ã?ã Ö>ö]ìÚBå—·§^Ʋ,¥Í,¥p_ÙχO71 ›ÁAçFÛ¶ÖìP¥ý,i›ÈU«d×\I™ära綾î'“ù5<Ï›!“ÉP(Èård2™9‡ASÚG?ý©•JwÒÊ,ØÜàS|ËÛ€ò‘#ä Çá}Ù,]çYQ:Ž¥l„îºFÇÖ÷}Êå2…BR©Ô•áÆe^Ø6ÏwI䯥°§½üZ¬-S'bÉzœ¦i244԰ƪ¢,:­<-³ÙÖë^.•ÊÒˆšËÀ’¶ šø§ŸäškNbYIâZ­¦mE™…ŽgCb6Ÿ ðžoÂýöqS& lPX–¥EébN{3]´¥aòx7© P”îa¡¶Àv]¬‡m†‡CÑ1Ÿ‡üµÚo7¤õ}Ÿ|>ßà©Ñº„Z ŠÅ©# JÏSý‰ŸÀ ÜbqÊÄEQzßÏÊN×u›w¿ BÑHƈ§QLaNæÂ É„ßK%ˆ–•Ž)´"DY”Ëá>GGa` Ü'yXVxŒiB.~wœDìñOþÚv8ñ*Þó12— •u­ä<"ÆÙv(^z^(jf³a^Íâ¤a„?Ç:Ù 6^Ÿæ:‡×'ÍðpXV߯Ô']–\.W[åQ($u”y&R7y¤éaùná¹$ß ëâûaRoñŠ‘ç¡Pë+XVx\¹LCè>©»¤±ídÛèhxÝ¥9cšI9]7—ŽDàQ.—§,Ë¢(J#=%Çt÷-}\«¥À¦[áCÒŠ 8S3]«V×iºÞ>44D6›Õ‰‹Š2 =%q‚üøãŒ¯[G­^Ç ÛÆH]› º>`ær8€=:J1úëÙ±1ŠÀÖ/}‰oÕjüþñã|lx˜j´Ï¬áa<ÂI¢n”¿•Ë'œHfGç®É1¶M0†‡ã.ùË¿ä¢Õ«yîG?âÅóÎãpÕÑ£x_ÌÎ÷½×}ík<ìûܸ{7ÿöƒäë›6ñÓÇŽ‘?ïÏY“'9qâ kqär9]·AQz ûþà¹aî¹çZÎ;ï]Sl@µZÅ÷}W¾º¯¨ð¨¤æN@ÂÜ¥C¦'B¸®ÛP^ñš±,‹jµJ6›¥X,6xù4{j‹—T¡Pˆ=žÄ[*ŸÏS(b í'2R†ô±â]”Ïç)•JäóùØ^¦ÃüIèôÇÓÐÐPüÿR©Ôà%vW¼¥Äó)íU*•bO¹féó‰ÇS«c …Õj5/(õt]7¾ŽµZ-þ+^Kâ5%ž0é°žç‘Ëåb#9_+¯%ñ´¯©b±§cpp0öš/©™<êõ:§vÚÏ* ¹˜ö€«T* kiï¨üàí~ ÚÂi/ðí×^ÉïòyËÃð5 Ö|Þ³*Ü/o¡™ú^޾§—ý“}CÑ߇qÛsÏq×]wqá…òè£2¹u+¿ûÁ²ñÄ ~glŒ?xè!®ß´‰s@fíZ.=ýtþüÊ+ù܆ ä¢óÆVjÓ&Ø´ p>úQ`ëUW±È^s ¹õV|BM„CwãF6’ˆ‡¶laðÒ•Wr6pî¦Ml¼y`ýzÆ¢ó$"b@$$oÚÄ_ˆYDûÍèÜiÑU®+¢­ÔÍ{é%Ü~ Oœ L"”É9]KBØ&X}ŠÑ9rM÷ŒÔ¹¼è8ë¼óxæ´Ó8úØc±°·ÇŽ0ñ%—`D×âk€¹e ¿å)õºkýzLà¬õë9tè7þÂ/°uê6Äõ`˶¤®ƒë×óK©çÉ"tEô¢´U1; øë×ÇBn>U7©»M*šGtÿäž©ôéû 8QxñÌ39÷…èuÄsWQ”ÞÅÌ#ðÚàoÈdÞ-s?°,K'&(Êé)á18^}`?ß:ø¦ØÛÑ÷}õrR”Â[ÝÏúú›xòÉMñ¶L&£¡V¥Çð&'àr‹çÜÇOüĹSÒ˜¦ÏWº˜BAì*-ág!ˆÐ%ß%$¢äí8NNOD-$Ôáèè(CCC± —ËåÖ5 ‚ 5Õj5Þd»mÛ˜¦ ZiAU„LHBË7 ®–eaš&¶m7d‚ìK+ …¦iR*•âóË5±,+Ú ÃhiF|¬¬¯›õä\•JÓ4Žï—”Ç4Í8¯ôq²½R©`YVñ2`”®‹aqýjµ–eÅõm¨_«õÒäÚ×jµ¸¬r^)G:½|—rZ–ŸGÎ?66_O9F®‘mÛØ¶Íðð0@|žÑÑÑ)ëìÉó ÷VÒNLL`õz ¸÷Þ{ÛýJ¶…Ã&Ÿsù§•¸ò~È[•ˆiU"ï²Ô1UAHÄk‰žRâ/ÿÚ¯±5—ãozSø||ðƒ@(òØ›6aÚº5Ì0½ìèï»×¬¡J£°™Æn*Ïlt|KÆ0øÈ¡CüVt]– 1³@ðŠWà=Ê‚¦žœwCŸûæƒR*•æuO»^‹uÝFÆÆyþù6Õ¤3p‡l6«“’¥Çñ€×ÿùßoØïy^ì…¢t9:©D™Y³l¾ˆÐP.—co; AlÏ= AñJÂ8§E þÛ ΤÍ"ö)-¨¥·Ï„¬gÛüW®ÇL}£æc¤ÞiQ°Ù&“9Òž›³Oòmþ;ÓÄæ25ÿé|ÍÇJÚ™DêÙÎ7Óä¶éÎ#Ç4—Už§¹Ö«9ßVe2 ƒ³Î:‹^å¡!Îûo'ùÕ VMqŒoõ”™®KµZÅÈåâu%zJ=Фô¡i&7ϵÇÑñbá"ó›6-<“Y±h9ãT‰íD[9‹KóÄEQz“à\öô1þ‘µ±ó’:,(Êüè-áñÕò?ä O`Y«t&“¢ô°Ê¯ÇaV‹Å"A¨W“¢ôûŸÄòñ?—¾¾?bdd+7Üîr£Å™EQºñ,›ñf”°Ë2T<›=àÒ2-›EŸæíŠ¢´‡Ç/¸€Î=—«ÿñ8öŸ¬Ÿ6ïû¸®OJ¯[i+èDæÞ¤y}p¥»‘ßs £¨(Šwè1^ûôãìØq7a nâ芢̞Ÿ=3¬êãÿüC·ž„‡ÁÁAFGGµ£ (=‚{ ì|ñ¯»ð@ÃZ=Š¢ôý¡þמµüèG¯¦yî¶ eå3“èçº.ŽãÄk÷‰È aOÓè ³²˜Áò:jû>ôô<\σ÷Ÿ«TZ^wß÷q‡r¹ÌØØXWÛ ¨ý_iÈû®Â£¢(ÞE¹ú xàr¼MúŠ¢ÌÓÛ]€åâ;çÀ‰U'xç;ψã2k§AQz‹Gƒ/ñþ÷‡^ÏÅbQ;ŒŠÒƒxçoäË羞§Ÿ~ÿ÷ÿ>º‹EpP”Ãq X×…7½é^,k‚LÆcÆ_åŒ3¾„ãä(—s ˜ärá´ÓÂôCCÉÀÀ@¸-“ ó:í´$|OoËdÂïÅbcúVǵʣX„|>9§ãLŸG?T«É9å“É4æ û’ãº6—u` Ômäÿå2ñõ‘¿s¹&éòåóó»&ríÓ×2“ óœ)bqökâûáõkuMZÕ-ýl¤ÏÓ\Ÿ|~êyÒ×p¶ú‹áý˜Ïý”ã 7%íÀ@øý‘GÞÚîW±-œ8qÃÈEFŽ‘õT±m›±±±E Ï©(Jgâû¾z3)Š@°n û¾y–6ªÕjÃZÝŠ¢ÌNÏx<¼ú£œ·ù0¶6(ªÕj¼6‰¢(½Ã½°eKøÝ²,±¤(=H°¶>:Æø…Ÿâ†þ,ÞnY–v&¥Gð¼P¼ ÈfáØ±c¬Ys7™ÌZ~ã7ÞÇöí›xÛÛ¦W*…i­ôÙ.Δ–££ávÃÏiYaA@j͘p¿l3 ¥mÆÆÂíž—¤‘rKÞÃÃÉù}¿1Ó ·KIcšÉqœÇu“ã²Ùð¼’·tŸÒeMʔ˅û9¯\Û†z=<¿”Ó²’trM …ÄûOþJ},+ÌCÊiYÉõ-’ºI^–•\ûô5 ‚äšHú ÓÈÿe Ú4“|¥¬ék"×CÎ×|ž´ƒmúžIÙGGCÙuô麦¯³Ü+¹Öés˜fxED“{ká6× Ï¡€*ç¸ðÂýíyÛÌÖ­[1 »á}–ÈHÃÃÃŒŽŽj_AQz„jµJ6›ÕeX¥Ç‰š—|íÉmüÒ‡_Â5}uœ@QæGÏûåØs¯æUç¿;ÃÒ›S¥'øÁë^Ày<‡aœ‹ViãAQz¯Ž~û®¹fs²Íó(‹Œµ»xŠ¢,år(ð”Jàºÿþßçc¯&¡•Þ¦‹ÖšÞž4Ò‚dšÙΓЦ#GZМÉ«Õyšk•Oº,ò].]szØZÇ´08]Ý$¿éòmþ¿äѪniás& cú{<“þÔ\þ¹,ßÙ\ÃŸË HÞtýçâl—¾ÖÍeaSö¥÷¯]ûÃÙ3_<óÌ:|?¹Õj€J¥¢ÞŠÒc ]{YQü‡fÇ¡<|ÚëøÕ_M¢&jT$E™=juõ÷Òç=Çßx †ã8í.–¢(ËȆƒù³ÌûyוÅx›ŠŽŠÒ{ȺÏým7Þx%ŽãhˆUEé1*•ðS.£ÿW´] ´Ó ½—jÜ[ö2†p„ëÀ+ŠÒ;|ó›ßdhh¨ÝÅP¥ð/¿œÓêk¸lëñ6Ã04‚¢Ì“ž÷]ô*ŒÓ~À 7lÂ÷}²Ù¬†YU”cÓ“O²ß݆ä߯ë¶hEé=Æb]p(dzše Qm‚¢ô"4ø¾iš*4(A³Çåb"xÚï×Ùºõ`žÖ§¿¿Ÿ\.§mEéA6mÚÄèèh»‹¡(J૸”+ú® \.k¨UE9zFxœxù¾7ö,ËÂqœ8„Š¢(½ÃsgŸÇ.6õK-£ Eé=~°z=¯ò&غõ †aÄ¢£NHR”Þc``€B¡ !•Ž!—KÂ¥ T ×ÇÔ&p#AP*•Ô(JòÇüÇ:N¨( >pÐ…‹^¶ÔÛQQæOϬñxíÏ`øé5P:Ã0t}GEéAŽŸu[øèµ? X,ªÈ (=Ê3GžçÉ36ðúWý z;ÊdEQz‡ Èf³*4(…Žk-?ŽãÏ癘˜hwQEiï{ßûx÷»ßÝîb(ŠÒøÀÿ~®ýõ ã EQæO×y<îÙ³‡7¾ñ\vÙeÜzë­ŒÏé¸ï~)õM⺮ÎbR”.çTíÀ™Ç^Iœo†éÕÛQQº›SµW}õ Au-×_¿ Ïóp]—J¥Òîê(Šr œªÈçó:{YQV ±¦iêÄdEY!œª-¸ì²Ët|@QV i¸O<ÁyÁq~ñ{WpÍ5› ‚@')*Ê)ÒUÂãž={Ø»w/»wïæÎ;ïd||œ[o½uNÇŽ9ŸëÎÆ÷}íT(J³;°.XG8pà[är9íX(J³[ðôè lp'Éå, ›¢(]ÌBì„bƒ­ Ý)J׳[ðøã388¨mEY,´] (J÷³P;àŽä<÷~å“8Žƒçyêí¨(§HW ÷Üs»víb×®]ìܹ“Ûo¿ýû÷sÏ=÷Ìzì/œÿE.ý±¯t­·ãøø8“““í.Æ‚˜œœœ×,“Neÿþýí.BO³;p`ý·ð E‚ èZÑq%<jÏ”Å`!¶`øôQÎëÿ'ŠÅ"®ëv]Øå•òü­{¶êÐÍ,Ä@¸®k/‰ +ÅvÌ—^|O{í^/Ä\tÑEŒŽŽvmßàTÐw¢wèµ{½ÐvA¯ÑkϬŒ±ˆS¡—îõBìÀ±cÇøÜº‹yÊëçò}  ë&)®„{½ÞÓ•Ðîxî¹çxöÙg”G×û÷ïg||œ;wÆÛ6oÞ̶mÛØ·o߬Ç?‘{ˆ¾îÆÆÆº²S±wïÞ9Õ³“Ù·o{÷îmw1Ìž={Ú]„že¡v`íÚµ¸®‹mÛ]*a%<jÏ”…²P[ðæwíçÚŸý¶mwåìÅ•òü­{¶êЭ,Ôô"+ÅvÌ—^|O{é^/†-èÖ~Á©¢ïDïÐK÷ZÛó§—ža%ŒEœ ½r¯jÆ&&xôŠ ¹üËÿÄüÁG ‚€\.×îjÍ‹•p¯WÂ{ºÚàá‡^Pg¶»såèÑ£ Æ`ݺu³ªùO<ñ_üâY¿~}×¾€÷ß?‡bdd¤ÝE9e:Ä¡C‡ºöìÚ:È=øÁ~Ð ±>ú(ÇçË_þ2lwuN‰n~þµgíçþûïçÙgŸåu¯{]»‹rJ,´Mð¥/}‰ƒÒßßÏÁƒùò—¿Üî*Í‹nþ„•`Ϻ¹Ï>û,?ü0O<ñÄ”w©Xh›àСC Ñ××Çk_ûÚvWgYX)¶c¾tó{zªÌç^ç;ßarr’#GŽ´»Ø§ÄBmÁç?ÿyî¿ÿ~.¿ürÖ®]Ûîê, úNôó¹×½Þ?øÔ§>ÅÚµk¹êª«Ú]•e£mÁJ‹8æz¯{}ÌpÕñã¼ú?|›çÿGÞÿþ÷399ÙuïÈJx¯WÂ{ÚííŽï|ç;Œ±zõêåÓ5ÂãBøØÇ>Æå—_ÎyçÇÅ_ÜîâœÝ8 ´Réæ{ñÃþþð‡œþùí.J[øøÇ?ÎSO=Å+_ùJ^ùÊW¶»8§D7?+©ÝÎúõë¸îºëÚ]”eGÚ@׬¬V‚-èæ:<÷ÜslÞ¼¹ëëqªüçÿüŸù×ý×®î(s£Ÿïù°iÓ&Ž?Îë_ÿúveÙÙ¹s'øÀزe çž{n»‹´lõVzƒùÜë^ïHÆ^êô¢-èÅ:ϧ޽>føk¿ú«|ó›56ÿê‡Ø¾}{»‹sJ¬„g|%Ô¡ÛÙ´iW_}õ‚Û=!<^tÑE|ðƒlw1Ei37ÜpC»‹ (A/7ä´M ( ÀUW]ÕS^ Š2½Ü&´M (½l ´ ( „c†:n¨(‹×&èš5…V®ÑÛ¶mkw±EYFÔ(Šj EQ; (JˆÚEQ@m¢(j¥SèáQ”ÖæÅEGFFâ0QŠ¢¬lÔ(Šj EQ; (JˆÚEQ@m¢(j¥Óèá`×®]ìÝ»—ÉÉIî¸ãúúú¸þúëÛ]4EQ– µŠ¢€ÚEQÔ(Š¢¶@QP[ (ŠÚEé$N«×ëõvb®LNNrÓM7199I__ãããìÞ½›]»vµ»hŠ¢,jEµŠ¢¨P%Dm¢( ¶@QµŠÒIt•ð(ŒŒŒ°}ûvúúúÚ]EQÚ€ÚEQ@m¢(jE Q[ ( ¨-PE퀢t])<*Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(ŠÒYtÕŠ¢(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢t&*<*Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(в`TxTEQEQEQEQEQEQeÁ¨ð¨(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(Ê‚Qá±LNNrÛm·ñÆ7¾‘Ë.» Û¶¹çž{¦¤Û³gOœæÖ[oe|||^û—³>o|ã™wÚ]{î¹Û¶tÚ]¥{™‹-è¦ço:[Ð uX [Ðî:(ÝÉbµ æšf9êÓ­m˜ÝtC”•Ér¶:ñ^jÛÒiu^.[ÔiõVff9Û úl,ÄtÛ;±\cTgen,ç˜b'>Ú&è{½ÔtSo¼ñÆ®ìc¯„qÏÉÉIn½õV.»ì2.»ì2n¼ñFöïß?ï2vÊó¶,c6u¥mÜtÓMõÁÁÁúÝwß]¿ï¾ûêŸþô§ë—^ziýî»ïŽÓ|úÓŸ®Öïºë®ú}÷ÝWÏ{ÞSÏ{Þ3çýË]ŸK/½´~ß}÷5lŸKÛY»ï¾»~饗֫Õjý¾ûî«âŸ¨_zé¥õïÿû]S¥»™ÍtÛó×ÊtCô»J÷²m‚¹¦Y®útc› ^ŸÝtC”•Ërµ:õ^JÛÒiu^.[ÔiõVfg¹Ú ülœª-è¶wb¹Æ*:©ÎÊÜY®1ÅN}>´M°øcVïå ›ê\­V»¶½Æ=å|÷Ýw_ý¾ûî«ä#©Ö=:ç2¶»Í÷d©Ÿ'ÛÄÑ£G§4êõð!þÈG>ÿÿío{ýÓŸþtüÿïÿû ÇͶ¹¨V«õ÷¼ç=-ع”±õxÏ{ÞÓpîz½^ÿÈG>R¿ë®»º¦J÷2[ÐMÏßt¶ ê°¶ ÝuPº“ÅjÌ5ÍRÓÍm‚z}v[Ð uPV&ËÙfèÄgx©mK§Õy¹lQ§Õ[™™ål3tê³±[ÐmïÄrUtR•¹±œcŠø|h›`iÆ*:­ÞËA7Ôù®»îª_zé¥ñ§ÛúØ+aÜsß¾}õK/½´¾oß¾ëÕ-¶e¹Æl4Ôj›gçÎlÛ¶­aûöíÛ™œœ`ÿþýq:aóæÍlÛ¶}ûöͺ¹Ø¿?Õj•O}êS-÷ÍVÆvÖc||œýû÷7œàöÛog×®]]Q¥»™ÍtÓó7-è†:,†-hw”îe1ÚsM³Ôts›f·ÝPeå²\m†N|†—Ú¶tZ—ËuZ½•ÙY®6C§> ±ÝöN,×XE'ÕY™;Ë5¦Ø‰Ï‡¶ B{¬¢Óê½tKwîÜÉwÞÉwÞyJuhw=W¸g__·ÜrË”:¤éÛ²œc6g.[­”¶mÛ6Å`LNNr÷ÝwÇ?G˜òã²nݺ†éö/“““|⟠—˵|ùf«Ã\Ó,xóæÍÜvÛmŒ³yófvíÚ×§Óë t7³Ù‚nyþf²ÝP‡Å°`“•îd1ÚsM³”t{›f·ÝPeå²\m†N{†—ötÚoørÙ¢N»×Êì,W›¡ÓÞ ©çBlÁ\êÔIïÄrUtâ½Vfg¹Æ;é:j›`iÆ*:í^/ÝRçÍ›7³yóæS®C»ë¹Æ=7oÞÌîÝ»Px;zô({÷îeÛ¶mq™ºÁ¶,÷˜zv;×2Î% mäÖ[oåúë¯çöÛoo«Ybå6/Ì922ÂæÍ›gÝ¿ÔìÚµ‹O~ò“ÜrË-ñàú믿ϥŒí¬ÇöíÛ[ž;ýãÝéuPºŸ™lA7<³Ù‚n¨ÃbØ‚v×AénÚ&˜kš¥b%´ `v[Ð uPV6ËÑfè¤gx¹lK'Õ–ÏuZ½•¹±m†N{6ÃtÛ;±\cTge~,ǘb'=Ú&XÚ±ŠN«÷r°êÜ-÷¶ÛÇ=ï¹çnºé¦Ótºmiǘ mbdd„ñññXOÒŠñ®]»Ø»w/“““ÜqÇôõõqýõ×ÏiÿR"/Mú4,¬:×2¶«}}}ìܹ“={öÄçáž{îiaÔÉuPº›¹Ø‚Nþæb :½‹e Ô(§Âbµ æšf)X m˜›-èô:(+—ål3tÊ3¼œ¶¥Sê Ëk‹:©ÞÊì,g›¡“žÅ²ÝôN,çXE§ÔY™;Ë9¦Ø)χ¶ –~¬¢“ê½\¬„:wú½] ãž×]w“““ÜqÇ õYôvÈRÑŽ1›Óêõz}Ék¦LaÏž= kš;wÆñ‚'''¹é¦›˜œœ¤¯¯ññqvïÞ»ØÏ¶¹¹ì²Ë¸óÎ;ع”±õçÖ[oeÿþýlÛ¶ýû÷sË-·°{÷ƒÒ½ÌÅtãó×l º¡‹a Ú]¥;Y¬6Á\Ó,ÝØ&€ÙmA7ÔAY™,g›¡“Ÿá¥²-Vçå²EVoef–³ÍÐéÏÆ©Ø‚n{'–k¬¢“ê¬ÌåSìäçCÛ‹;VÑiõ^º­ÎÝØÇ^)ãž{÷îå¶Ûn£¯¯uëÖ1>>Þõc†Ký<©ðØ%H¼àíÛ··ŒÙ>ÛþN`.elg=äÜ›7ožÖŹÓë ¬lVÂó× uX [Ðî:(+›nxVBf³ÝP¥wY¬ç³ÛžáŨS§Õy¹lQ§Õ[YVâ;±õî¶wb¹Æ*:©ÎÊâ²ÒމŨób]—vÔi©Ç*:­ÞËÁJ¨óJ¸·^‡ñññ8ÌñJ3\Œ{¡Â£¢(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢( F×xTEQEQEQEQEQEQeÁ¨ð¨(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(Ê‚QáQQEQEQEQEQEQEQ”£Â£¢(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢( F…GEQEQEQEQEQEQEQŒ Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢,EQEQEQEQEQEQEY0*<*Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(в`TxTEQEQEQEQEQEQeÁ¨ð¨(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(Ê‚QáQQEQEQEQEQEQEQ”£Â£¢(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢( F…GEQEQEQEQEQEQEQŒ Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢,˜žƒ ÀuÝvC™† ð<<Ü–swòuéVJýWšX(£££uÓ4c;bÛv}bbbÉï÷L¶ ÓŸµN/ŸÖn¨-˜ó¹ß…B¡nÛö¼òïV[ÐÉeÓk0?Ô$,V›`¾¶ [í@7”Oë?7Všè”q‚^±\6½óCmAÂtm‚z]Ç »±lZÿù±ÒlÁR c†Ó³XåëÇ•‚ã8Sfêt3Åbß÷™˜˜ ^¯cš&år¹ÝÅR”Žf¥Ù…244D6›¥^¯311„¶EQV:j ×uµ ¢t%j £M ¶@éFVšè„qµJ7¢¶ AÇ ”^f¥Ù¥;YÑÂcµZ¥X,¶üQ’}Õjß÷©V« û]×¥X,R,Üù‹Å"AP.—)‹8Ž3ã¹æ›~¶úø¾ã8±»«üh¦ë3WäØr¹<%?ÙÖ*Ílyε¾AP­V©T*†@©TÂ4ÍYë&÷,‚ø>ÍT>I'!æsì\ïM«û™¾åryÆp ­îàºî”{+çl.ÿ\Ž]̺w:³½k3Ù‚éì´Ï´²’s}æÊ\Þû¥²syg«›ïûض €aX–Õ²•¶s=÷|˜é^.•-˜ÎÌåØô5Q[°2lÁBì@úøélÁR¶ b Ò&Ho“Á‰…ÒIm‚¹ßKv }­´Кv÷f{Ÿ—ªMÞ¾¶ m‚ôyµ03½Ð&ü›ë3WÚÙ&˜mœ`¦º-F›@¶w«-Ð6ÁÜÑ6ÁÌ´»M°1C˜{›@Î¥c†S¯G/Ø‚…´  7mA7Îç}Ö1ÃÅ·+VxŒ/ ëº ÅûÒ7Ùq†††â—DÒAÀàà`|áe_qc4“ÉÄ¥<$ÍyÍ5ý|)—ËäóùøÇS†ù›žѼ­UšÙòœk}e›eYxž‡ëº†A©Tšµnòò ÄçÊd2-ë.û‚ ˆs=v!ÏZ Ä/¦ã8d2™9ß›4®ë6<£™L¦!ÍÐÐPÃ3:Ó±À¢Õ½Ó™ÉÀ̶`&;Þ¿mÁ\lÃ\òœK}çò>ÎV7Ã0x¾ï7 LÈ=LÛI·X¶`¦gm©lÁLv`¶cµ!+Å,ĤŸÎ,e›`!¶`!m!ŸÏ“Ë妨ŽùÒim‚¹ß+v´0ŸcÛÕ?˜í}þÿ³÷öqrÕåÝÿ;@€@Øä,hC$žBLPÌYF…jÏ–'«-u6ýÝj%-ÌÔ޵К:c{ßØÚ»vFÓ*µÕ΄–ZkïfÇ« Ý#ª+…=)Jƒa‰ËJBaO² $!@~|ç:çÌììóÃìÃõ~½&™=sÎ÷|ÏÃ\ó=×ç{]×T „ɰ€>Œ–ù2&í§êù ‘~‚áŽm2Æ0{mŽ FŽ F¿ílôÂèÆr Õg¨c‚±Ž `þÚ‚Ùä3í÷Y}†Sd 3v*(‹',˪Êe,9Á{zz¢ÿÛ¶£¼ýòy2g¸´wâ„ÉÏ[,£ÏÇ9‘N§£¿kkŒuý‘p]·*?0p"›ÍVõu´íÕn[oY½uFjs´ÇÛÑÑåY·mû„mÛ',ËŠÎýpÇ&¹†óù|Õç@U—þþþA}iÛÑ£\ƒáîµÚ|Èýýý'\×UŽíÚ¯fí}RÛN6›=‘J¥FÜv¸cŸk¹¿‡»6'NœÖŒdä<7ÊÔÚi²lÁhlÃhÚÍñŽæû8Ò±uvvž°,+²!¶mhd»É°#ÝkSe †³#m«¶`nÚ‚‰ØzÛOç˜`"¶`"cY×qœ1ŸÿäqŽd 5&nûùdäØôù`dý|0Ò÷yªÆÒÖxmA£Ç'NèóÁh˜Ociªžé'îØ&:&õg«-Ð1ÁèÐ1ÁìLÄgxâÄÐcùL}†ƒ·O¶`"c‚äçóÑÌ&ŸápÛãßPŸáÛN–-˜“NŸœÉ’N§£×~–LŸáy¶m†!žçUý-ª{r[˲¢ÿ¡ëúcERÔîk¬Ûµ¬Þ:“q¼ÉÙK===ôôôN§«Tý‘Ž-›ÍFïå'g4Él‰z)RFÚv4 w¯É²L&ÍÌêììœp4µ#³<ÏuöPÇ>×rwm`x[0;sÛŒÆ6ŒÄXŽw¤ïãPÇ&aÿ®ëR,£4,ÉY8ÃÙÑì{$Fº×¦ÊLÔ uìj f·-˜ˆ¨Ý~4ÄXu¼¶`4ÛÖ³2c³X,Žù\Õ¢c‚™>ŒoÛ¡–5ÒLŘ`²lA£Æ ¶`4Ì·1LíóA#ý#Ûxý³Ý¨:&ß¶C-›‰>ÃÑŒ @}†C1lÁDÆ ¶`¶ø ‡ÛþG?ú >Ãᘨ-8eBG0C*|ñAåÕM2Ö/22®ëR(ªR¦d³ÙQ烮G­‘r×uÉd2ôôôŒiÛÑ0ܽfÛ6Q8~†¤ÓéIqnJ¸¿®‰þMöÙL`¸kÃÛµg´÷¤ä[ïè舖ٶMkk+ï|ç;±Ù±ì[é^›*[0Ùv`<Ç>P[0»™È=9š1A©T²,Êå2år9ªë’ËåÆœbMÇ3}>˜ÝŒæ¾œÈ˜`²lA£Æ ¶`4è˜`v0’Ÿ`<ç|´~‚Ùn ÔŒÌ&â3nLt¤«ÏptÌE[0‘1l¯¶ qLæ=­>Ãñ·Ñ0'…GÛ¶ës‚†3ŽãDÊrr[ß÷åýW&Æp7ëhoä0 £u%çp’b±H†”Ëer¹\Õ€e¤mGÃp÷ZX–Í®ò}Ÿ¶¶6Ç©šÙ0VÊå2¥R‰žžžª¢Úc™m1Ç>ÓîÚÀð¶@íÀô3Þ{2¹ ß‹gŸ}ÞLdßÉý w¯M…-˜ ;0Ç>P[0»˜È=9ž1Ád>ê˜`f£Ï³‹ñÜ—L–-hĘÔŒÌé'˜Í¶@íÀèÑ1Áì`"¶`¸1A2ZG}†#Ÿ¿¹j &2&µÓÍDïÉá¶WŸáÔ÷9™j5•JUÄLÎ@H¥RQQbù,YXÓuÝAˤHéLa®|Çq°m»jvH.—öíQéÚb²–e zXâÓ…B¡j€1šmGb¸{-9Sóì‚ä=š,î*_z1Ö?šm뻜ó¹6+g¸k#Ÿe ÔL?ãý>Ö^Çäö6lˆ– e&²ïd†»×¦ÂŒÆ µíPÇ®¶@mÁL`"ßÇñŒ \×%ŸÏG/›äóù1§6™©c‚ᶯ=osÕ€>Ì6Æc &2&˜,[Ј1ü­Ï#£c‚ÙA#ý³Ùè˜`ôè˜`v0[0ܘ@}†:&€‰ @mÁt3Ñïc½íÕg8õ¶`NF<:ŽC6›¥½½Çq‚€t:ïûضM±X¤­­ ×u#§SrvS>Ÿ'—ËEÆ#‚ª Dr’KØíl§££ƒ¶¶¶è\‡a8¦s---ѶC…!§R)R©™L&J«0Úm‡c¸{-NS.—iiiÁqœhÖËP9£“¤Óé¨Í0 £<9–R©DKK ¶mG÷°Ìfn[é³ïûUÇ>SîïÉd¸k k ÔL?ãý>:Ž]G¹çåž®d%í@òZNÔŒt¯M…-P[0ºë£¶`f1‘ïãxÆ“y-gê˜`¸íç‹éúèóÁÌc<¶`2Æ¥c9}>˜øõÑ1ÁÌ¡~‚Ùn tL09×GÇ3‹ñÚ‚áÆõPŸ¡Ž Æ2&µÓÍD¿£Ù^}†“o œ8qâÄø.ùÌ'‚(\UfÃHسœ?$a€IDATtÛ¶)•JAP•û;Y V§gÉþOFÁá™@ò\V5÷<¶¶6Nœ8©ó£½NÙv(êÝkÉýu?ß÷ ÃpÈk]Ûw)d,!ÜÃm[oû¹ÊP×f4¶@íÀÔ3YßG¹ÎcÙ~²mÁpv@ö“k †³#m;Tsµ3›™ö»>fÚ˜`<ÛÏeôù`f3ßçñŒ &›FŒ ’íêóÁðè˜`v0Ý~‚©`6>Ì„ó6]è˜`v0[ Ì?A²3åù@Ç1$×›içj®Ø‚‰~g’Ÿa6Ž êµ1æ´ðXQ©»»»#•¹­­l6ÛÐIC5c¹À3½½‰’üòOæ¶Óqœ3í\ÎWæƒ-˜Š{m²ÛœÈwy¢ µoµó µckkªÚœªßõ‰ ¶`þ0ìÀlh;.˜ÎãœÎö•Ñ3lÁlL(e>ØÙÐ^#QŸ¡óÃ̆1ÁD×§ÂÏ v`ôÌÉT«Ã‘ •–”)^ÚH†Êµ›d,3{fz{3•é8Îùr.g:óÁLŽ6î_µó µckk*Ûœi¨-˜?Ì;0Ú›©LõqΗó8˜¶@ÇãCÇó‡ù`fC{3µó‡ù` tL0>ÔŒžyñ¨(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(ÊäsR£; (Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(ÊìG…GEQEQEQEQEQEQEQ&Œ Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢LEQEQEQEQEQEQE™0*<*Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(Š2aTxTEQEQEQEQEQEQeœÒèLìܹ³ÑÝP”Ã’%KX·n]£»1íìÚµ‹ƒ6ºŠ2cX¿~=MMMîÆ´¢cEÌÆÝ…i§··—ÞÞÞFwCQf «V­bÕªUîÆ´ÓÕÕÕè.(ÊŒBŸEQŸ¡¢(0ñ1Á‚'NœhôAL5ŸúÔ§`åÊ•îʸyøá‡Y¹rå¬>†¾¾>úúú¸ì²ËÝ• q÷Ýwsíµ×6ºâ¾ûîãî»ïnt7¦k¯½–÷¼ç=îÆ„˜ ÷ŸÚ³™A__MMMüÑýQ£»2­Ì…1Á\¸ÿ`nس¹p ?ü0·Ür˼é—~‰w¼ãîÆ´2WlÇX™ ßÓ±2žký½ï}o|ãîú´ÒÕÕžðýNÌÔþ}>˜½Ïãa>Ú‚¹à‹c½ÖóÕgxÉ%—ð¡}¨Ñݘsá{=¾§saÜñƒü€C‡ñÏÿüÏãnc^D<žuÖY\uÕU³Ú¡²uëV6nÜ8«¡««‹®®.¶lÙÒè®Lˆ]»v͉c˜,[¶lN\»Ù~ jÏfr ó¹0&˜ ÷Ì {6ŽaëÖ­îBCXºt鬿vce®ØŽ±2¾§ce<×z¾>\vÙeóîþÐïÄüa¬×ZŸfïóÁx˜¶`.ø"ÆÃX¯õ|œzꩳþ;1¾×sá{:Æ·ß~;ÿöoÿ6¡6æ…ð8Ø´iK–,it7&ÄúõëçDúžÙl4”ÙÏ\¸ÿÔž)ÊĘ+÷ß\°gsá”ùÃ\±ce>~OçëµVF‡~'æóñZ+£g>ÞsÁ1æãµçw^£»0aæÂµž ßÓ¹0îX½z5k×®P*<ÎfûÍ ÐÔÔ4'jÌÇ<çÊÌa.ÜjÏebÌ•ûo.س¹p Êüa®ØŽ±2¿§óõZ+£C¿ó‡ùx­•Ñ3ï¹à‹óñZ‡Å‹7º f.\ë¹ð= ãŽ3Î8ƒ³Î:kBmœÔèƒPEQEQEQEQEQEQeö£Â£¢(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(F…GEQEQEQEQEQEQEQ&Œ Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢LEQEQEQEQEQEQE™0§4ºÂ=÷ÜÃöíÛ-ß²e ëÖ­‹þÞºu+Û·og``€«¯¾š-[¶°jÕªFw_Q”I@퀢( ¶@QÃhlÚE™Ûè˜@QP[ (ŠÚE™m̘ˆÇ;wÒÛÛ˺uëª^MMMÑ:b8¶lÙÂwÜAoo/7ß|s£»®(Ê$¡v@QP[ (Ša$[ v@Qæ>:&PÔ(Š¢v`2ñÝeJ˜i×uÆD< °qãF¶lÙ2ä:÷Üs›6mbÓ¦MÜvÛm¸®Ë=÷ÜÃÕW_ÝèCPe‚¨PÔ(ŠbɨP”¹Ž EµŠ¢¨ðwÖ/N£f’ «Ñhð1·=@ÀÄ®oX9 ý›1½½½U3jÙµk½½½lܸ1Z¶jÕ*Ö­[ÇÎ;Ý}EQ&µŠ¢€ÚEQ ÃÙµŠ2?Ð1¢( ¶@Qµ`„ıPby©Ñ2dƸ~#¢½qî·v¹®íñQ–…•ÿeyPù¬0D»²mXVr“t¼3Fxܹs']]]¬Y³†5kÖp饗Våm>xð @•ñX²d »ví¶í矞­[·²uëÖF¦¢4”íÛ·³yóföîÝÛè®Ôe*íÀÞ½{Ù¼ysÝœðŠ2ŸØ¼y3[·nåùçŸotWê2c‚Í›77ú0¥¡ìÚµ‹Í›7s÷Ýw7º+C2œ-˜è˜`ÿþý‘-T”ùŒü&îß¿¿Ñ]©ËT?Ü}÷ÝlÞ¼yTë*Ê\FŸôù@QÔg8ó}†!±X4ê Á0mL–à4T_Æ"œŽå8Epó,ÒõX‡Z¿4ĺõŽ©\Y¿özý¬ûª…ÂÁèaDU¿²¬€s•ÏJ•e¥Ä¶Aåÿ–Êz¹Ê2YGþn¯´ÑViÛOôåwºº&<&˜Q©VW­ZÅm·Ýcwë­·²jÕªAc¬œsÎ9¼ï}ï›p;Š2Û‘t3u@=•và¼óÎãŽ;îhôa*JùãŽ;èêꢫ««Ñ]©‹Ž eêY·nwÜqnjކ³eÙ²e:&PˆÒ•Í×çƒk¯½vØ”mŠ2_Ðç}>PõΟ¡OýT™Aå³Úô©e U³LD/¬ÜDÛò¹U³¾ˆh ;Š~€=Êcò*ûs]ZÔBå˜ä<È6²Ïd"°ú•ízˆ¿6 #¶å+ý¨'z•vÛ+ë×¶/ikýĹ‘Ï¡:½é'ž®œŸóÍÿVbr Ê+¬ôÍ­|æ ‰²®«¥Ä9,TÞ'ÔM{`ûjsò¹üßF,nаé%ÚoIœ37„ÿ¼åVÝwß(¯n}fŒðøÔSOUý½e˺ººØ¾}»þø+ʰçüøºÈ5 ûAQ®›8^é§\þ<þNpNŽÄà7> Þ'Lÿr@gå³–7ÁŠ— c´bÔR¥Ý Õ‚d XÞûVšv •vîzùSxÿŸîçÂý~þçGy…3cR­ÖcãÆ T-«½nݺFwUQ”)B퀢( ¶@QC­-P; (ó(Šj E™Ûv ^-À€úu%ŨD¿…T Œ"öµ2tAY^`tuEðaS¨ý[ú-b›D &ÛñkÖ-'Öjö'¢¢GœFÔLj’²_‰è+aDF©q()EE¨”þDQœ~Ä´/)LÛíʾrÄ‚©h£½òZù4ïˆ#CŒ¨7ð›pÑcFt±µX÷GpÕ£ÐK³˜÷}>ÎÍ›÷‹µÅ¬‰nLcÄE°*኷æ¢EÏòàƒÏ@¥}9ÆK.yÏ«¾.·Þú ž;w¾D†d2J¥‡àóŸ\.‡Yû^À·¿ý8¶mãº.---|æ3÷&µñ\0â½:3¢ÆãªU«øô§?ÍÖ­[Ù¾};K–,¡··—›nº‰«¯¾:ZoË–-Üpà \ýõ455ÑÛÛË–-[¢™ Š¢Ì^Ô(Šj E1ŒÆ¨P”¹Ž EµŠ¢Ì?; ÂbXH ŸÉ ªS‘&ÿ#xÛgs÷ïçcO=W^­'„RÃb‘/=ùäh]S5û+Uö××w­¬Þo'àm…#CÇáâcÇN;,°ûa¸ó2³½ˆ¡Y í7áœÿ—4Å¢h8þÐCt\~yU:QÛ¥0‚a Ë/¾‹ŸùTúq`{e›°’‡5M,ÂZÄ‚ßý?ü!ûÿò/éxÿû8ø_ÿÅß~îsüÕ?þã k(‘ƒÉÚ•ÇçèÑWÓ«Ö +·P(N§±,‹ hjz†+®x³Y§T"d³y}ôdÖ¬ÙC¡ÐNww7Žãð£ýˆ3¼…'Ÿ,Q(ôS, ÃÇÿ6‹]Éç?ÿy.|Û¶q‡ÏþfÐÏ]w=Ák¯ý„aH±¸€O|â¯Ù³ç¾ ÝÇ3Bx3#ášk®‰Â¡W­Z5( º©©‰;3®®.Ö¯_?ë ‡¢(C£v@™)A€m4÷húñ<×u'ÞÐ Gm¢(0²-P; (s(Šj E™_v ™jÕÈWÉšÉuD@“D?±¾fYŒhçáƒFJ—ˆ…"$¾¾·—÷/[FwO¬] @±³“Ý×__•UêæˆS¨z˜(ÄÜáßox•ð¢“#ÑÍ­|~Ñcà—˼þmoãçÏ?Ÿ<Ðö°t;,h6Çôx½ù›â~–€§·ogàÈx÷»£ãÈåàšÿ áâ¢eb;¿öµ¯Ñ×÷[„¾ŽSC,ËŠ¢&%ªàÉ'Ÿ„ð"\üÐÃ/ð²&¦²\.sò©§r¯ç™ógY|á·›C==q'DAŒbK«yè¡dÿþ¥Àû«–/\ø'Ÿ¼ß÷Éår‹E<Ïcÿþ4÷ߟ゠<ÏcósÏñOÿ´¸€ë®ëã÷~¯›r¹L©T⬳ÞÃi'N°hÑ/ày&NS((•|𛝿ë_ÿ ï¾÷3ä‚€ ظñ›4?ô_üç~‰»шÐy×ĉzCåã#3"Õª õZ6nÜ8lîeYg6EQ†Gí€2Y …qmçyÞ¸·-•JU©„r¹LPIgP(¢üø…Bß÷­#ËÂ0¤¹¹™¶¶6ZZZhkk£P(†!¹\Ž0 ñ<\.‡çy”J%,X@kkk´oß÷Éd2477“Ëå(•Jd2:Ô +3:Ô(Š£³jen£cEQ@m¢(³×HÊÑÑ ÒÕö§Ÿ”n5U³nF LÕ|îGÿ%—;Äþ&IÇ×Jü«Û÷yî¹ç¢èÃ]¼˜Ðq¢tª"„ ЙkÊ>ž|òINù÷ÒaO"6¿ûÝ#<ùäËxžÇò¾¾hýþþ~^ÿ×"PÄÄ €wÿ„¾ÕBl=p€¾oý!ög?0ç*ŒÏN¡¡˜÷¼ç=¸•å<òÿ÷?|cmmmÑ6æ8bÿßSO=ôõõ‘Éd‚€öövJ¥¥R‰»ÿò/±m›R©D.—c×w¿Ë†~STÑ÷}üüçÁó°m(•àÁ[oÅK´¿nÝ/ÐÔôîhý\ÎÜ=t%û·ÿŽeY¤Óé*ÿàÓOßH¸®ËϾò ü›¿ @:Ý €eYFL]¸‹þ·èèèÀ¶mŠÅ"ù|MMM¼újx©TŠ Xµp!;^{…MŸeí·¾eNx[=ŠeÁÒïŸ+&XãqÆD<*Š¢(c¤¿0 ÃÛ¶ñ}Ÿ H¥RcØÃð´··à8fO±X²?aÒÖÖF:m²¤Ëú`„¿t:‰qÙl6³Ù,AP*•èì쌜- ß÷ñ*?À™L¦j_`~È=ÏÃó<Ç! Ãè‡ßó¼ª6Â0Äu]R©étšöövÊå²™QeÛAP58’å2ø$½‚eY8ŽC:&‚ÊŒ¥aF$×u) X–E>Ÿ/žçÑÖÖF*•"ŸÏG3¡,Ë¢T*ñáxzn0EQEQEQEQ”yŠ?Žõ|à{GrìÇ?Æ[»¶*PêBœ"5[ùß!Ž1ORú•è?Ù¬xår™´eqÜqxrÙ2Ê]Äc]–ÕY”ö| š½8%©xðöîÝË+ÿy*îoX”+ç|ž¾¾>^}µ,ó«oxn%Õk?«¿w©Ÿ=jáñè³ÉdÈçó¸®Ë9÷ßÏIÁ[9õ­§ðæ7¿™»ï¾›·½ímüå_þ%>ú(×^{-ßÿþ÷ùÇüWàSœvÚNÊåï†!ù|ž €¿ø‹£üöoÿ”R©D6›Å÷}ž|òw9í´µ|êS¦NbOO¿ôÖ·R.—#ÁÎu]r¹ŽãV;ÿá÷¶nå ×^‹»)E©/üÛ¿qÿ£âf³är9vìÈ;¿õÿ­ßbóñã|íÉ'fñâ+±í}‘ yÞy—Í—¿Ü¸Å"d2\ÿóŸå¯þ .»ìWpœe8Ž9cÁW¿ÇI_.ðúµ}UþÔ0´Ù³¼Û÷àú>ŽmÓáºäî0ýÞñè9´‰Ö´m졼‹ð¥çh:mb÷¼ Š¢(  \.ã8NÃÒyŠ'¢W¡P »»{Ð:år™l6K¡P P(àº.A`YÖ á±T2™àevŽïû¸®[•T„¾Úí<ϋ҈(&Z>ŸÇ÷}Z[[q'Ú^" ƒ ˆf,ù¾_7ZÑ÷ýhÛ¶ikk‹r¦wvvFçr¹H,•J …H” ÃÇqªÎ›ïûQ;¶mG‚f.—‹f'…aHgg'A%¦Aà8N$X‹Å¨-0b¬É¯^Œ¶¢mÒéttŽkáŒ(ÙÑÑ]áŽ;îà…^hÈý§(Š¢(Š¢(Š¢(Š2¨Ql³oåJŽO¿ðw¯\Én }Çذe>ˆwÅ€‰*”úŒ6Õ¢#TR”V&éƒ&½0‚å·¿ý=À¥T*±ô¯ÿš{Ï;o8€?NYb±³âºŠÄHñn>ùä×8ñÄÜ?ÿ-á1 CØÀž=-@ÈéGŽDû?é¤=ýöBøƒeôþùŸsÚ¥—»ÞUiëI|ß„ÁGÿàxÇy衇(±oß>~çw~‡|àÀoñï|‡eË–±sçNÚÚÚ8õÔe¼ò üÓ?íæw÷-üáþ!—^zŒÛn»Ž8díÚµ477вò/èéû>ÚF±˜Ç C¾ðæ7³ùì³ùèG?ÊßüÍß°oß>>ÿùÏsË-·ðèÕWóü½÷òÕ¯~•b:ÍNœàÙo›öÿ+W~‘gœëÖ®%“Éàº.öò>޼ú:^ù“4¿½b×ïÞÍí§›zo{Ûj²•´®©T ß·hkƒ•+Ïâ=ÿöo&¤øÝ/ÿ«~ïaÜß¿¬ê:zOžK`»Ø·Tî®0„övX÷/Àépô(XxžÉK»ìÒ—IW­­­‘8'¢_[[[Ô×t:‰Žµ¢éPˆP)×:›ÍV‰~²ŽœŸ¤x(ËûûûëÖtL®?\½Ç ¢”®õX³fMT÷@QEQEQEQE™:FS:ïÛGÂOÊÑŠoè©ãÇyº©‰ P,â‹t?ñ\q.FX„8¥iº¦½,ÐV*Ñ]É¢•ÌÀ%µS@ú?^ÂT;\À[ßøFX´ˆ•wÝÅ‘—Ð_nfÅ›]´(5=Êñã' £öÊå2¯¾z Ç‹üy´··sà@Šææfúûᡇж¹|ùi¼å}+ ‚€{ï÷ø××^ãæ›o¾À7¿ùM-ZÄ~ðZ[[ùñ ÀË/_Á§?}3«W¯æÌïŸ?Û»—+Îcß¾|îsŸãÏÿüϹï¾ûøÙŸý8;î?ÀâÅ‹ù£?ú#8À?x!`|£»víâøñãüÏÿù?ya×ÛèéƒeË–pûïÿ>¿ðÓŸò³?÷s|ùË_ƶmÊå2/½ô]]]|¶§‡ï75ÑtûíüÂÑ£\µr%wíÛ@_ßÇXÀW°‚ݬ]¹’S¿ùMÒû|>}Ò'¹ä¿æ’T ~˜¿üenÚé_xX€U.Ã3W°¶¯“¬ƒæd9áÞJÿüz¼gèüÏ8•pðêy”ƒóËNc„DÏÃ:~?î;~–ÔÒNpð}CÜœBá‘‹)•*µ=Òiü/ŸGj󫬻ÿ9^yÑ„î÷Uãq¾ü‚+ÊpA0h&ÊxiooÇqœYQÛm>P.—‡…ƃïû”J¥(g-¥R‰æææ(õgGGd³Ylj?©(ý“HÁl6Kgg'ÝÝÝQJÒööv¼J:†|>E;æóùªˆHòäs‰$ ‚€|>Íê3³GPˆ£÷Lnò<ÝÝÝU‚­eY‹E:::°, ×u«ÚlÛÆuÝ(i±X¤X,’J¥¢ˆ@Û¶£õÂ0ŒÎl7DÄ”vÇÃpÂâh÷ߨ¨ZEQEQEQeþ†aU “Z‚ —Ë ò[Èäà¡2Õ¶¡(³…§Ÿ~“’4é lÃÔ~L*ûöí3¢‘l»z5`" ƒ  ¿¿ŸŸüd´L÷µÂ£¤Wõ}?ʾFx`ÄJIºcÇÓŽmó¿®¹€¾˜Otƒò"6ô÷›ò=•ï¶ãø,_þ .Ïäy§ŸþÀ‰J‰?­¹¹™TÊæ’K.á¹çžƒÊñü×ïòÙÏàÓŸþ4­­­¬]»–Ûn» ¶qÆûhmmå‹_ü"¯¾ú*›6m`á /pÆgðÉO~’´eñÌ3ñ쳿Àu×}ˆøÃÜ~ûíÜ{ï½lÝú´žèæ§OÜÅ‚ ø»Ï øýß¿ 0×]wo~ó›M Ä|˜Zضélcc|Ÿe=ÆÚµk8¶o?ø³?#Nã8Kîçxäµ×Xöàƒ|hùrÖ¾ô÷¾ú*^ñVžt630ÀGÏ9‡«Î9‡yþúŒ8~å•&ú°âgt›¦íWWÄ­T‚;°=K¾é3FI C#<;^[ •s]ª\ˆå2d³¤>¿{Ï}ä<²Yór‚Ÿœ‹†˜eJál~ þ®ÓÙú–¿äàÙgOè¾Wá±H:BebÈ€d."©%]åhÎÅp‚¶D©uttà8=öX£q^S.—«®™ˆ…µär¹¯¿l'©HE8ª„MØK´agg'¶mã8N”+]¢ûûûÉçótttD"`­—Ïç£m;;;#Sþ–õ¥ÿAÐÑÑ ‡É£õ" “‚[GGÝÝÝcþjÏQ=\×êC&‘šŠãí$Ǻ\ãéÿdÿÀ¸Ï›¢(Š¢(Š¢(Š¢Ô£T*UeO’eííí …è½d>Êår´´´°`ÁZZZ"qQü¹\ŽææfZZZhmm­+×Àe¶000 ]籄C`wSÅ&ž ýýf{ßç¬ÿüO#B‹‘Cù“HÄúõÿKlèïÇÁ•â?t]¢ ‚ëúúpl°YØ{˜M{öày¥R‰L&×¾ô Û·ß@¡P ­­R©ÄÂ… 9í4Spùòå„aH:欳Îâĉ¥,Z´ˆ#‰T«Ë–¼†½t)_ùŠ1¿öµ¯±xñbNœ¸‰×¿þõüÉ–-œ|òÉ Dí.Î9çÒé4ï?óLþî‹_`ݺ›Íy«¼ÐÙƒÃpùsÏå#ë×Ó\uÕïÆß¸xñbž{î9Â0dÍš§…¶§0 ¹ñÞ{ÊeÒé4§õõ±ø—~ Ïóð}Ÿ¥ý×,ýÀp•ûöA:Íâ+¯ä«Ïþ”¥ sð×~GV¯fÁ׿Îé·ÝÀ¯þ ÿöoÍÉN§ ~s+öÀ£ñ…ò}ó‚#+h¸Ïƒ©”I…ú–_ÄYÞGÐW]€Ñ¶M@c`îJciû¼Co‡… Í>- \—òŽ<ϬŸœ'b¿ùt&Ë…©©V§™ÑF°IмÚÔ|BlÆ 3ÛtŽR­­­T*U7²i4$ó[×"ƒ™Úšw£Ý~4ÇC‹¹\Û¶£ºq#‡D’ •Z3™®1›ÍFlÊÔãû>aâº.mmm¸®‹ïûÑõªÒ„†aXÉåíGƒõÎÎÎ*!Iî »»»£T¤RѲ¬ªë.ߟz"‰lÒ†ÜÛµuÛ¶‡lKq1¹Ùv,bØP} žçk‚ÂDëo&ÓÑ69¿¾ïWÝ;Š¢(Š¢(Š¢(Êü@&<×{¶•’#Cù‘ÊårÝÌ?AÐÞÞe\J¥RQ–"ÙdA’(’Q(N“N§«žW[[[£H©ÎÎΨ߹\.*ç"ÛKIIw(Ç'“™¥œÍP¾Ò¤Mü2:QW™NBL„aò©ùècê-¾Oóޏ6àgýèGpùå„aÈÁÏ}€…½½8«VEß! 0´ÏDÐC†ÜwßçøÊW*bfs3yLæâÅ‹ñ<èìÌ·¬\‰ÓÙI¡§œrˆŸ~÷»”Ëå¨,ÒêÕ—¥,ÐO,âØ±'X¿Þ¡««‹®®.²Ù,_üâ>î½÷y.¿üQÊSÏó8~üö=ó «V­âK_ú«W¯æðáÃ?þ‹¬ø—?ç]Û¶Å>øÿøv?¹€Er¬AÀ²Š°[ÿœ[Á&| ‚¸ñÆyú>R®ËóÏ?Ï¢E‹¸ÿê«yîé/8°g^ø0Ø6ý6pñþý¸®kükÍÍü¯Ë/ç_+¾¶‹~ægØzî<ïÙäÓ«¸úÄ þùh=þ+6mâšÃÿ̃÷Þ‹õb"m©m›W*Eð+·SâÆèXhm…t{ÁËä¯üWr\cÄÂÊþlÀ¹ê¥¯œ&2¼—? … XhÖïéÛ&Àn>d2P,ù<`&0RN¥ïÒuáµ×Nç­oØý®ÓˆçyxžWwFNrvB† …ºk1 …B4Ë`¸õ'³ï0tšØZÇþH)äX¤¾›/õŽAÖÉd2Ñ`FêÓ%£GåÜ–J¥!Û‘þû¾O&“‰ÚNW´µµEÑXõl'ûîXs¹¥R‰ÖÖVZZZªÒNH¸»‡D;Ê ŠdßÂ0¤\.GïeW.—£´—É~ÊyMÖ“ûå_þåɺ5”¨½%Š1•JE×WÄFÏó¢ï² àljî‰ò•û§­­ Û¶£Y„É£ét:jONH³m»ê`2°,+J§ cÂ+'RKL72;j"Ç.ö¡QŸØ}REQEQE™?ˆH×ÜÜ\å«’åíííA•[IR(hmm¥½½¶¶¶È!–Z[[±m›žž,Ë"—ËE™zzzèîî&›Í’Íféèè ¿¿¿ªÌKòùT2 I).R©©T*ÊV("ßWwwwTfEúV*•( ÑKü,AD¾?0%`Ä''ÿOG&µ™™™<ÎäíÖÖÖ(øb&ôs¶S¤N­å•W^ Œ%íªx eY\uçØ_â©=ÕäÏ£÷ßã8ê)?ðÀ°×­­-öKJÀÊ«¯^À¦={ªÖ½ð £÷¦þ£I‘ºƒ#GVD>:™¬°gÏ–/ÿ …BT*Egg'ŸýìgxñÅâºnt‘Ëå8í´>öî=‡ßùO>ùdäÇÿÞÀeœuâ½½½Ñ‚O}êSüʯ pþùçsþž=•0¾Ê9~â]|niž/~ñ‹ñò *ÇX}üá+¸üôÓ9õÅÁó€—}”`ÿ™ø¿ó¼ï‹_äÒƒyÇ®]د½Æ›–¼À ¯{WíÝ žG³çqíÀ‚¦ö¢ë²ø©§¢ ‰T*Å«‹7¾åJ°mÚ*65½ì›°{7\u;åTŠ¿yûÕ•®VPY¿wc$üTò¥º.þÏ}‚𢟡6ÞÊó ü­ÓÌò04B¥ç~óAœå}TæoDjb±©_<Ž×¿¤t‘J™óeYæ½ïCRÎ9thâñŠñ8MˆpõÓþ‰è(‘޾ïW9½Ã0Œ~ГŽ|ÇD„jvƒäU®mo$döP{{;===´··WÍ@* ¤Ói2™L´¼T*E3 ’Ç/Ç#mf2|ßú!Ç”Íf£ô‹É¼ðÁDƒ4H}::ŠÅb•³_„K0†6—ËEçSŽ#‚h›t¥ànò:È9”A rDø‘YVADÆGÅB¡[©g'Û€©¿Dme³Ù(jM~ |ß§­­-:F‰P“ª---QDˆ, ‘H™œÅvÖYgMÿ—`ž"±ÌÐ+‹Ñ,‰h”c‰“‰U)wåØuÝèšÊý,÷}eÀÍf6€{Uk—’7q²˜nñMlI2Òs:©}˜SEQEQEQæâ3óœÕ«ik3ëåófíí`Ÿ³’ì•a]syt]s9s(==fJI˨ýÏ}zè-ú>¨ð8MHS2½bùc‘Ù Ž’’=Û¶«>±©µµ5ªã'íHûÉžÖÖÖèG¼™L†l6¥^ÙM""X–EJße¹ˆx‚DJÚR™$ƒ‘¤à*3’Dt”t¦’6A™ %i!%‚LDÍäþk£åztwwÓÚÚ^‰,+•JtttP*•ªú$éSòXóù<žçÑÚÚŠeYQ_$-„ô7™â¶íH¤1±µµ5š"â°ô#“ÉDí¦R©ªsD"•ô9—ËEB©ÔãS¦Ÿä@5y ñ= ×')hËL? JY Q‘ù|¾ªÚA½l'÷¸ì{º‘~Ô÷X˜ˆh—|p™î‹B£¢6åx=ÏÓEQEQEQ”9B¹\&—ËQ,#AQ‚¤|Jwwwäãjoo§½½Û¶£åIúûûÉår´··cYVU©—ŽŽŽ(Ú0N×è&ú¬-bf-2ñz(jŸsEÀ_©ø ‹ÅbtŽ$SH§ÓQæ0ñË$GÃÚcLf—JúÛ’Y¬Ä(¢K²|T’\.W•eN"=% ùƒd™ø#%}­ ¾DñMær¹ª Çq"ߢ»ÜG©Tж¶6ÚÚÚ8ûì³'x—*ƒ¨s/‹·(ÄD; Ï?ü0–e1°w/gWÔ¨åGâ?ýtEð3ko:xbÅç³}ûÛxöÙE£êŠÜλw7EBV<÷Ü••÷ñ:Ë—(zÆgËåøÀ† ìÞý*{÷šïÚŸÞt_ß±ƒ0 Y´èW8vìŽeqÛ¿ü Þ÷²œwÞóœ~ä6Dvàë¯üuð“‘òåݾ¸‘\:}ßtª\Æ~ýå¸kO"XÙ|J%p¬ïßýÚ©„Ϭ5Ë, òùH ³íwAhàP »c©Ÿùö«»ymß>Îïïgà¾ûpÞó]ÎøÙз`=¥½%í}&>ŽcÔÁt:3üb7¥R,<ú¾ô¤ÛâŽõ}øÖ·Öškžˆ ‘Hà 0»H§-\7¾…hYÕÛ æP»»óذ֪ZOê7¤~½ ×½œööHK­º5§:Ú1•‚ zðý½ºíUxœ&D“ÿ“‡’@4IWÐÜÜEæ‰h™¥ZZZ"ÁQÒ@2/ŸIäžDJjÑL&ƒã8Uƒ‰˜±K–É\²ýäLB“‚Ÿ."J{"´¤R©èÇ[¢¾D8“sS[·°¶Ö[GGÇ s]›&B„½b±°Îf³Ø¶ ‚B2¿½AÉzŒ"¢vvvFQGGGô.Ç-ƒÇq¢P-¢¸®K.—‹B2hœôËqœ(23ŸÏWå—™m²ŵ1Í2S¦™Õ#$ßË€We *šQþ–u¤ÂhIFÝͤs ×/©9›s9æFƒœ_Mµª(Š¢(Š¢(Š2{(—ËQd›ã8U¾ñiÕúêùdR¿LàJ$”m“¾-!NGÙÎfµÏ¹ÉH¬ÚÏòù|Ýó#ëZ–•S¡N|3)âŽLöNööíhb¹øu%âP‚D4¨øY“ëõ÷÷Gþ_3¥¬Žœ™èCÇ¡»»; ò ÙFŽ[üÏ‚ìïúë¯oôåS„Q(›!¨ù?‰‹ñ¡‹EÊž‡†,»è"N?óÌA÷§mÛ+þí={6ñì³;êîÿ U]g¯’©4ƒ àÈ‘·QÏD<ø÷¤›w¿ûÝ|áSŸbó{ÞÃmg¬àþ?ø>þ³? ÛÕß¿hÆó<ó½ÌåøõW_å«ÀG?zW|ÿ\|ßçĉ€ÏöŸø9®}æ™8sG¥fãñãæÿlZ[ -—`ÏÍt|Õ‚²m³ÎN‚÷~[pŸí‡cAt¥’i²Xó- ¼eÉ/ùçBù{üðª5 °á’K°ù'‚æ‚þ7‘nþrââ¸Õª¬ë‚ïG5ƒÀˆw•̸ØvœÆ4 Íç‹qøðáÃxÞCm®m›z‹ŽC$<Ú¶é¿e™ve_Žc^A ‰ù|¼¿r9îOÒ¤‡a|ý“.Ylj·•¹oxÃQöì98¡{_…Çi"ÅW›Â3ŘŒ á ˆf&A<ëGŒLRŒ’›døsR0”¿åÇMÄImÚÞÞõ%:;;£™?"è‰8(éD0”ÚŠQêG™mäºnºoÛö ™IIñLù{¬Ô0¤VžìW\:Å£|&ÑŠ2+(Y, §§§j}×u£õ†š –\?)מ“ä @f$­^š‰ - uEYeêÉ$É ò]Kô“wù^;ŽC±X¬ºÖck©Wcqº»Vo߬áØècŸ]cRQEQEQE="f2™(û—”)‚x‚nÒ—5Ü„s˲¢=#E&ÕŽdÚš-Ï•cxÛÝÝ ƒ’eÊqœÈ—˜Ì†&)m“‘£ÉLn¶mGçYRœŠ°P(D$¶mGµ'“&ÄÐÓÓµ#ia%› ÊH’ô+'ýŸBrÛzçʲ,V¯^ÝèË8«©Ídêû>¸.‹ž}–#+V6FxtëŸöÒK<¿s'–eEeͼÊ:ÔD®Êw:飮E„¥ý謪ïo¢EÏò ¢åÍÍ;øñ7UEÕ¼õ­oå¼îä‘%gðÿðü5kxèÿ‘O5:Á7ÞÈœ--¦¼”½‡¯ýþ7ø¦ç™û- ¹róf:ÿØÔœÌº/âHG€;NâÚ Í¢gŸ3*šÉ£'Ç}Ÿpñ*‚#+Œ@çºf} ¼« ¸úû¡³~©ûÞ‡ï/7‘“âF·,m¹ŠrÒ›>É럦oùr6Šdý³ÒvœÕqL_„Šò'"¡è’"‹f9¤04›{žÇ~ÔLgg¡r]ä{]Õ(¬m›¶ ³,Ÿ»‘Ë™e…Bä)z(™L,ˆVßfûZá1•2ë·´@Ež0*ÉÉüC1¢]2Eõt#…ˆ8LN\QEQEQEQf6Éh·T*ù¯ÄŸ¬U8–rµ™ÎÆÃL‹vœLäy]&÷˱J&*‰0”T®õH ŽB*•Š&¦g³ÙÈG+Hð†ø{’‘ˆµmäKM2[âùÈ™ßÿ>o¾þz|ªë@ڕ׎'ŸäÑûï']ã/N^ÓûîûyÎ8ãX´L40QtµÔ»ewïÞÍÑ£¯cÿþ—«ûwæÅ„!<üðn<ïN²Ù,Að½®.v¿ü;¼ó’ÝØö®[·ŽçðÎà N;íûüËþ!Ÿúð‡ã¬ˆÊ„¯½‡ÏýÊã lo‡l–J<’‰V~úӬݸ‘ í).£˜9ø>–â4íÆ?x©yX‰§rŒ¾d(g¨sí2:n{ëŸÇ¡€–…ûoŸÀßðŒŸÏ Ú,¬àÆÁËÑ·|9XVU”b¹ þ»n¡\0‚ÒGï+¾^‰L”,¯"â¥Ó±`(m/_ÞÇ7¾±‡²ð¼™LŽýûaYòÜs‹ùéOßӿРY(˜hÄRÉìVj8ÖsýID¤d‡“’4Õu&óys©&§’ù´E‡x².  3S†PHÄ\’z?0ò))Okç´¤ HFKÖÛ§DÖ.—”£ÒI !¡û"<Œä„ƒ™LG;^ä˜ÆÛNrP bÞH.\4й< œÉ$Ó†&Ó‹#‹€õ¾ÓEöY[ð}:Éf³ƒ¾rœÃõi´ëᘌ6ÆËPé\¦ƒzéEQEQEQ”™ˆßIÊ0Iž >™ðŒÉç$u•±!B¤D• hH¦:Äœô¥R©º×j"Êô"^w‰<µ,+ò>¿{7¿^Y'驲 èïìdÙ3ÏTÝÉëîû>ozS·Üòh™Ü›Ë–=ÈO~òàŠè³ €z.±Å‹sâÄRN®Z~üø*, žyæ1¾üåBäËÿèOò»ž´°xñèQÎ<{?®{ŽßáÓä‹Eòù<­Kvãs=ßü x5W•ßÓDÒõSZ°€?}ðA8í4 ÅCd¡3kBøëoÆ}1À}ònàf£à¹.\½vG'§’CJ«þ˜RÒ'ÞŠó'-Q~ÓàÙE¤6"ý'̓΃e Ž”(EË2])ï\[U£Ñ÷‰êFŠÂXÈU xI¡â€MÏ3ÿ[VÈÃ_É%—ü:çœÒÛû¿Ù»w…»w7ñ†7œK¡p1A`YL‚üïyñþäs‰`L ŒÝÝFHLJAÉȶ6èé‰Åi©õ8™œ4¹Í)µH¨¼™S[4«e8Ñêç-—岡¶@²l'IךN§ë¦ðlÛ®[X¹öGTö_›2r4$Û“HÞëÉ ^ŠØ¡ÐÁü#YãTò±K´¯0’ð7–Y‹cAÒÀ6×uëW2=t=T8›8–e kÏEQEQEQ”éÇ÷}ZZZhoo§¥¥%ŠdL¥RC>Ki–±N(NFD)ÓÏP×s(‘Q™$3Ÿí8p Zž¼\@¼ÞÍ@ðÿäOªî ñ‹‹_ïСSX±bÅ ý?¾˜ÓO?2ª¾}ç;_º~Â3Î8Æ™g¾Õ*-•JÜÿÃkø™Óþƒ#GvE¶¤éRvト»îZÉ"Ë®RÚü pð¹ä´ÓL8^gg–·`ÎÞ·~=Í;v@©Ä?¼á#Õp‚s¯À?ó ü£ëbõÔ¶±nýöªãƒjéR¼­”ý¸b€Mùáóhk«awìh& Éõ$“«¤<õ¼(³kU_“oóy³}r½|>®›°ÿ¼öÚjÎ;ïÝäóyî¾û\N9åjº»»ùèG/ãôÓj¢-kbÇŠÅXW³e™€Ð04§¸ö’Ö¦Z‰DÚ®ýi˜l¬ S@2òIÉAùÑIT«—^u4¸®K*•ŠŠ'÷Y[ó+™'~¸BÓIF#ŠHרQ‰8mG‹F*õÚ­’JÌ ²££#Ý™ö²^}Ééb¼Ç£‰ˆm0¶¡s5ÍŠ¢(Š¢(Š¢(ÊÌ )8¦R)úûûI¥RQÇÑdIë3²N晌&£š2{ùß ò¿.à@s%Ú. qÀÔ2„Hr€Ã½½¬~äÞÝÔ}gë}ßwïnª»¿þþ 8PÕç8F”úéOÿ¥jùæÍ¿È’%/TÙ†0 9xð }}§ñw÷ ®ë’ɘŽÏ½zûN¾€õëßeîÙ0ä·¿ææføãƒúó¶?¥åÒóÍ–5HÑj]°ÀÔ»|ó{ùR(é1¡{é4üʯÀ¢Ex¸U œ}ÝZ²ÿka]ÌuÁ]¾Ó•ý†ç\µ]›F46¯ÚìrÊ¥V£lﺉ”«5HÄTª:k²oé´Yoýú•¼ÿý/óÌ3§âyk×näÒK¾²o›G½ lj·$…kåVÔçD`iU¿’ÇF lo¯n;yN&3q› “@9!cKhA"î’_f‰l”¨ÀÑÔ~ É´†Rs.Ù¿zHm¹Éb¨(§±l?‡yQÁfE™*’Žr¯•ËåAiäïFÕúôû0˜Œ:Š¢(Š¢(Š¢(Êä!þCÛ¶£ÌcRžÃó¼Ÿá¦¢<‹Ò8ÔG3wÙsþùü謳ðÇEhô}lŒðØôðÃê©(ò•ÿüO.=ÿühûRɈ‰õüˆõ\û fß¾•ƒÖko‡={ίZþ¿±ƒƒÏ‚$˜âàÁƒ\wÝu¸®Õ7ý«?>Îk§½Ä½ÿï>Ó@°ôMoâü׿×ëm«cE È^õ(ÿïàÏ,Z×[t:7ÝŽM;vðà²e|õÿàÜ+è:òÀ}¡í€mã\¹˜|ÜæjQ³P0¯z_ÛV¯¦\Ž£ü‚¥¤ËQä"ÀÞ½{)•âÒ‘Û·ßÈ‚Õí‰L"‡V.G™`‘¼LC¹~eÿ¿õ[Ëøó??5JÝzÚiÙ²å’Ê1Ø,\øŽS?ÂRÒÃÖ ŒÒ×ÚŸ‡Úóä8&rRjRÖ;ŽÉü‰QáqHŠyõ$ƒ ©á˜$YPx²EÇÚ~Meû#1Q‘e¼ÛËùNŠAŠ2”J%Z[[)•J‘ÐSモ:¼YëPQEQEQEQæ;år™l6Kggg•ÏK|„£ç[6E™ì[¹’C‡ÿýÆ7²âÈl ¿¿ŸSN9…å}}QªÕC?øA•ϰ\6ÂcmÔ£ãÔ¯Ûxæ™/sìØuû²ÿ¹U_ý¶·áàóö‹^$~ù=ïáMýý\~ù±íRÉ«ìË1%ä½¡Íߟy&v¹lR§f³ðØc |à¦c™ŒQÒ.¹ëì“àÊ+£P¼pùZ ?nÇn>wÝTgŒ¼ñÆíA,ªŠÈç\xˆà¥åUý—¨½$½XxèʪKçºå‘ø–L;zôè¢hÛ Ø³çüA‚¡mÇŒµ)Y“d³ÕbÝPîWéG*eÞ§ÓFüÛ»÷ähÇq8~ü!r¹\rÉ«ƒD@˺}©MY»¬v{)—9Ü1M3RxàÒK/¥««kÐg[·nåÒK/eÍš5Ü|óÍôöö6º»ƒ"-Ë"W‘À‡š±T»l²#¡,Ë”VÕ¶í*!Òqœª/ùLb"M2­¬Î›½Ì;A]+u|ß²hx£hô$„zLWôg2í²2;™ ¶@Q”©g([ v@Qæ:&Pf¯-ð< ê¦×‹ ¨Â£¢Ì;p|ñbîÚ·}gœÁªãÇc¥' ¹ðÐ!öÝu6^~òÉA¾ðSN9eM|°¸† J³*Ø6¬X±‹ýû÷GÀžY‡EÈSwïDz,Þýê«ÜøôÓüË¿¬ ,.¼ðjÈåp‡L[[ÔÖwö_‡ÿårty'î;ŽÀáÃ&´²TË2¢àÂ…°x±ÉõšNã¯þe¼‡›H­{{íi‘n±kõj¾þõvJ¥Xx”SUxèJ‚3ÖG}Èç¡¿ðqz^uÝB‰æK}øtÒ鏯¢H8o}ëÒÝmD¸E‹žåÆ·WÕN”v²YÓÙ®^”`[[uªëÖO·Z+Q„áàš‹–e±ti‘TÊåÑGï'›Íò'÷ô εõ¤‘验7#…Ç›o¾™AË·nÝÊöíÛÙ²e wÜq½½½Ü|óÍ í« Àá8\AIkZ=car²dÔŸ8øë9úgjT*•šPªV0ÑhÊìe¦Ú¤ˆÅb‘îîîè{ÝÙÙ9HxL§Ó‹Å†¤Z©õÄF eû&«ßaÎX;§ŒŽ™j E™^êÙµŠ2¿Ð1¢(0;lA†´··S*•Èårø¾•bªG*•Ò‰óŠ2fƒÀqxê©§Àqhj2µ=σ\Ž+ž|’…‡ccj<ÖfIK¥Œ`$v!9¡¾Ö]&½õ­ÿY·aòØcE~ò3~~.}K~™B¡Àe'ŸÌ±cÇxãßÈG>rŒùø+&¤Ð÷ùDO9;Ä>ïU£¼Uжœö Þ÷ÁŽF¥s(•pßqdPŠOû-‹ˆw|þ¾•¤R)Êå2ßö=V®|‚ÖÖ•¾N%šs9£qvv>QzÕ z}ß7‚e*eÚzâ‰[xàkhm5ZéÞ½¿Â¡CoÒ›Ö2šØ¨ä:Ùl,t׎ÔlL¥ª¯i&ÓŽëºlÚt>Ï>ûì }c¨þŒe¹m-TN&3Nxܶm[”S¸–{M›6±iÓ&6nÜÈm·ÝÆ®]»¸çž{Ö_ùâ—Ëer¹ADF¡¶¾¢`YÖ  SÙ¿Ù8j¢é#D´HM—„¯L*3ÙH:e<0H§ÓCÞ·étzÂbúxH>¼Ì&[ ýžM}V&Ÿ™l E™>†²jeþ cEQ`öØß÷ñ|9ùÈG°mÏó¸óî»9óÌ'y6,J¥X³f ï:vŒMÿý%vî<¿ü«Åq'ÂHýÌ3¸WŸb–y8Á1SSÒë<+Y¾Oöܯ™úŒuÜyþËÓþÍâû),Ëâ‘Gþ|ä R©XlLÖh´,£&k:މ2¬]&û« *—ÓjY¦ë/¼ðžºç/™Š5I*§'­çÖíì»8)}–¶“óNòù<ù|ž_þåÕ\qÅ‘öÔÞÞNKKK•ÝÚÚÝé´ù»–:AöÃ.ŸLf”ð¸k×.J¥üÇ\÷³ÞÞ^6nÜ-[µjëÖ­cçÎ ë³D;Êì¥áf0 ÅTEãHVRx¨íŸçysÒ±ï8étZgŒÍBfºˆÇ¡"šg"35¥òT“´Í‡z¯!0—’ÊÎt[ (Êô0”-P; (ó(Š³Ëˆ¯­¿¿?ªçX(flF"E™-Ìt;P07pÎ9UK‰60z@.—‹‚jýV«+iHGâðáÜyæ™UËÃzzúùéOÊSO=•…»òÊ+yñÅ‹xÝ‹ä?>õ)?À¿Ÿþ)¸o_Ü€ïã<üeJ÷O‰4áºwÅ϶éüßÒ¹évÒ'ÿM,<Ú6mÛo$—3ц‚Ôe´/<%j:›Íò§º‡>OšÄ²L„¢ëš(Åá\®™ÌàEY_´¹ÎÎX”ÏŽ]Ä[ßúŸ¤Óf½#GVC ‹¾o„ÎZTŽ#‘vXjS°Šðg"[ë¯ÿÎw¾ß÷£I,ŽãP*•¢8ß÷)T ^Êß^ÍIJö™ŽX­S¦~£c``€ÿý¿ÿ7étšuëÖ ú\f2$À’%KصkWÃú-âCRm!o´uŦªþ˜eYƒ"¬Fša5Wp§!ÑeÊĘ-v@&ÌÑѲ,½ðC­&þ0é0¬šmƒDÉßöP¨lãV>—íýJ›^e™´Ÿ­|ž©ü_ª|žN¬#ø‰vR•öó•e¹Êò0qlðîSfÌ`³Å(Š2µ g Ô(Êü@ÇŠ¢Àì³µÙÇ\×¥\.ÏɉÿŠ2]Ì;à^‚e±tÃÔ|.þ)±åryÏ*Û>½º]×­‘÷–·<Ç™g~ŒŸþô5àç(•J >øÁæÀ‹9õÔWøäÁƒ¬ïî&“ÉpòÉŸàÜ_äm/¼À±O~’Òw²ðÈ\W¥„Ù¸úaéJJ»¯!kl›Â÷mü®·“~ýYäŶՈ^¾7å8`gR΋éªÕ§Z¬´,#f2Õ5…0¬Ž’t#ÊüI³šÍñÍqL}Èæføæ7? r'³b…I;Tà¹ì§öüUÒÊ\oNŠeÁ?ø3|ìc…BÎÎNÂ0$“ÉDéWÓé4¥R)ÊÎç8žçaÛ6…Bß÷£É/`ÆD<–J%–,YÂM7Ý4ém?ÿüólݺ•­[·NJ{I'¾¤Zô}Ÿl6[U$ºÑuÅ&š®t6“Ïçu&Y¶oßÎæÍ›Ù»wo£»R—©´{÷îeóæÍlß¾}ÜmˆèXo`0‘èßÙH6›ñ‡a-À{ÃY]#îy/Wy/Ë3@[åÿ@{e»Râ³ÖÊ«-ñ[eÿ­•6Ë•e…Êöí•åiŒðWN,ó*Ûe*md*û¡²\yy!Ò©l[ èºçBÎOˆ!e{øêãóËçÇóÏ?ßk;Ó1&ؼys£SQÊ®]»Ø¼y3wß}w£»2$Si öïßÏæÍ›'íù@Qf+ò›¸ÿþFw¥.Sý|p÷Ýw³yóf)•yü&êóÁÄ Ã0r ò~6ø”ù‹ú Gï3”IÞõ8räH¤HhnÌdrѤÀ·¾µœüÇçÙ†zÑuP?¥ç½÷¾Ê‹/ÞÁ¯¼ß÷Éd2‹E:…¥KûYüüó¼ï‰'ð<ÏóøµKžç⦇i9~œæXyÆ”¯¾J°h>ŽQ>‹EpʤHݲ’tš(½*T4Æ“N‚åË£eáå×qÊä1ˆ›>Ž>ljߋëÒ¶«k6Š´ÕQƒµµ%u©œ£B¡Z(´,ó:ýô#Ñ~ŽÙÅ…òZË>R©úуc‘Æ*UX–…ã8‹E\×JÊ‹ENœ8A±X$•J†!‘ÝRIå†aTk¸T*EËGBt´‰Ž fD¸CWWÛ·oçÎ;öÏ9çÞ÷¾÷ šñ0^Êå2Ùl6 ]u]7Vš‹Åh=_¾)ǯ…q—0Nà$–eác“EmÄ_­› ÑZÊä"yÎg¢Ã}ªíÀyçÇwÜ1¡6dâA¹\¦££cZÏÑx)‹S&ÄK¤ž…™ÕU&N÷)B[’2‰¨<Ûæ@ss”ŠBÁÆV¦óyìÊr·²¬%Ñv9чqT ìÓs]ìL\—5ý±‚tVâ±ÑÌ@²@¥(mç1"¡D¶`ìwwåsùLú×Au¤'KA°ö7A„Q‰pL~>RåŽÄy’cªeßüfÎ{åž~Ï{˜i̶1¢ÌVÖ­[ÇwÜ1c…·©¶Ë–-›ð˜@Qæ[¶l˜·Ï×^{mte>sÇwÐÕÕEWWW£»2ˆÙô|àû>mmmض=(âTxTf6ê3½ÏP&±×£¯¯0þ£€ØŸVj,Š˜°ÿ>| ˪nMÒÚ¯gôÀ$‹›šŒ‹½Îˆ›…k®»Ž¶—¯à²Ë>ÊŠàë¼p| ©TŠT*Eùÿ»ŸƒGÖpÚ‰9ýô(Jñ”—_&xeÁåÿRo‰•:ŒˆgXY¶—ý_ qþk7p¥é÷¡ £Ïr¹úé<-Ë|ÖÙi޳Pˆ3µ:Ž -+>~Y.B¢€®kº.Q“I·g¡`þ®!zÉ%³cG+Ž#©iC.¸``Èk-‡õ#§Z^éèè¨úíèèè¨ú})&nˆ0 ) ¤ÓiŠÅ"…B\.‡mÛ„a8ª ¹0 9ï¼óظqã„Ç3Fx\²d ·ÞzkÕò­[·²dÉ’ª/ý®]»…S× ¯ž $M©çyU¢ž8ô/ú™Ÿ¡‡Ç.ºˆ'r¦wG¯ä1Îèw|øÃ|ï«_Åq2²íQ;Àш@e&1›ì@*•Â÷ýh¦Él`¢…ê}â‰ñD Iß)éEETô+ëvO¨ð1Ñzvå³cñ¯»ŽNâÔ¥’T"û’HúÒ4±8(Ë$M©ˆ„ÅØ6Ð?Â1JšT‰.´0öºž0ÕöÚ§:íªUóY-N¥?CM8IdÇú»´ôC%Ùµ€õõ±÷ôÓGÑâô2[l¢(SËH¶@f:«P”¹‹Ž EÙe 2™ ®ëš¤ì8άò(ÊLc¦Ùá䛃—]aˆ}âD$<&×Oõ÷OÕp“j³–Jà8åȦ¼úêÃ\y*ÅÔ’]¾s'^~™/ø(·?|=ë–,&´2œ_Ñ‚§Ž³¢éyÎ{Áã·¿§·oÇŠoýöË-ŠU¼Ž²Û~Œ×oÄ<×¥Já³,Zâ"‡Î{Wйév¼àF‚ Ž\ CÙX.›6DÈ”T¥rˆ"8&S˜†!´´˜ÏÂ0Ž’Ñ’ê.E²~-K–¼ÀÉ'gVDË,ƒ«sVÓÙiöåyÕéX-kê…ÇÚ{c¸ì–®ëV•ÞK§Ó º»»±,‹  ¹­è^¹\Žr¹ÌM7ÝÄ#<2¡ z3BxÜ´iÓ ™E]]]\sÍ5‘aÏwîÜYe,ººº¸úê«§¥Ÿ¥R‰|>_•j5yñŸ[µ*qö_qGï¿8Už8ï½Êÿ{6m‚¯~•2C;ˆ§|Tf³ÁH=ÖT*5£Ò‹È'¿}"¾‘ø?$®ècÄA©'˜LË)b›UiOl“DZT aV¥dmC±Š’´“NÔÇüœg+¯|×»øËÇùÅÊì¬Z’bŸWi¯Xi¿ö‘Í­³ û6Úhré»´•®¼FC½öeœŽq;a2âi‡û]ùP_]? W\1 {šó®ërÆ“û ±Xwò7Y½}» rVX—œ÷*§žú5v]ø^ÞU.G…ƒ“Χ{ù‡8çÙùD¥ýrà`Ûq*Ôz‰Ódÿæ8*ǯÖÄ9ŽìR©XD)B0›­Ÿ5›5¢¦rŽä³B¡º£DD–Jõ…ÁE‹žÅuW`ÛÐÞÞŠeõ }¢£‹¼÷ý¸>åL V÷ÉÉd(—ËѤ×uÉår|éK_âòË/ŸP_NjôÉ Úyýõ×sýõ×S*•زe Mcp^—0 ‚€rE¢O½ýüó8ºh`ŒÉË_ aÈÞ .ÀÃ8ÜågXôì³ÍN«ð¨(³™é´µ¹¯=Ïöíi3ÄâQ€Û€fâ4§9ŒM‘è¸<¦Î`geYíïugå•­´oUÖÏW^EŒÐXÄ}ÄÑ‘cÅÁ ²Ú+mЏ9È,éFÒÎ6Rü“»w®N5iä˜@Q”™ÚEQ@m¢(†FÙÏó"a²,“¢(ÓO£ì€”ûI">1¨žŒ.>EÇqX¾¼¥K—‹l{p„Ý\a®Ó²¢|¤»wïÆ&àM‹¾ÍÓ«W³ ¥\—%GŽðè£'óôÓ7ræÅ•¬¹™ò‘÷ò“ïç¥×^ £»› êÔÂ0YÓ‘è31oRSQÖ)•ÌKú-뉈èyqzTA¢%]·Z°a²VœÌçàéyÕç%Q†rC¥ZýøÇDÿÊe#ŒŽ&T Ÿ:²q¦E<Gm¤£çy‘èèºnôy:æ=ïy‹*Z×x™’ˆÇÞÞ^víÚESSÓ¸‹3?õÔSƒ–555qçwF…-ׯ_?m~EV÷<,ˤ ú7lÀ[½šµúP”F°°aär}ÆË„"·nÝŠëºlݺ5Z¶}ûv\×åæ›ofóæÍ\ýõìÚµkROÐÆÙ¸qãô?Läó&âÑq®cÇ8²b}·ÞŠO,*P(ö¼ÈáîG%e1ŽøÖ8ý¶Û¦¥ûõn"E™­Lµ(gy†a”:eª)U^EŒ˜èTþïÀˆŒybai¸oñHétˆS)FNÓ:Io#ҬΧóݰ1¢(3µŠ¢€ÚEQ Óe ‚ “Éàºî IËŠ¢4–FŒ ¾Õטh1˲¢²EIj}ó‹-Š„¹Z.¸` zŸ^—Œž^½šl*…ïûüÙ?|‘µ¯û ‹O>™sLŸm“#µý“C¯3ÊœmÃÀwݵÈcÛ6Ë—/§££#ªc(]”m;;Ͳ 0QŽí함ËN#¼õô˜uËeóòý8ŠQR·Öâû¦-‰”¬Åu õâ@ÒiÓ~wwýý¸C8äš›wະbÅ犫ßßL,¨f“Ñž³?qÃA0¥YýÆ- w³±¶N£=[ë<*Š¢(Š¢(Š¢Ìd …®ëÒÑÑmÛZÃQQæ1ßêëãÙDZÊl6‹MìËËåàðáÿUµã8\w]õLDzeãøñ8¢Ó.<óIÎ?ÿvúúúø÷·¿m?þ1¥R‰?ýûá†-ÏóÈ«ïaA&C­’¹¡¿Ÿûþö“/ÔqàÐ!/>TjÏæóX–¥>•‹¢sJJU‰n C³ŽD=‚ã …A»Æuã4¥µú–D/Ö“%¤«IêÕ‡tG˜é?”äÑ߿ۆ+®Ø?¦ë< .á)¥V ÃpJu¡q lÛ¶-[¶pÛm·EÂãöíÛ¢eW_}5üÇLWWפG=N'…BÍÍñ^¹ {/¸€ãoy 6ðÅýû± zûí£nááÃÓž†0‰ ŠRŸ¤øhÛö´Î`ÔoåÜ ‘ÂŸŠŽŠ¢(Š¢(Š¢(SƒÔt´,‹îîî)Qef"~—ööí`–,YRÌÏç±,7ú’ìßÿE‚î7E/]º”W~z:‡½ðyzõj>xÇX–ÅŸÿùÉf7ôŸ8a½0$6œƒÏÎÿ~cå‡üñsÝuqtf©¡ØÝ‹lá'âa=AÖ­æ$=©¤]M®ï8&2r¨öê™Ôîî‘ÅÆ$õÚ8ë¬W(•r<òÈ_ª{8é´©3™ÙžB¡Àš5k¢m,75ì}ê?¿ÿ$!Ý»VTV°È-ü3V¯^Mss󠾊°˜ËÅõ³•&]7þ¼V`t#X¥áÕW]wèš’“…ô=‰D9–J%' ££cÄvǤT-—ëËl¢^Ç©b\£–¬Í“ÜÕÕE?Ö2[…G¹»ŸÞ,p¯Zņþ~V?ý4𛣔z½LÓuߪð¨(#†a$>Nõ ªý6úÀ•IÃbúìúp¨ÅWæ ¡PEQEQeðÔóêPnú—_~J%þõ×~ €G.:•7ÿ˜o|e-‹ÿÏÿÁC¿å>s]Ÿ¿î+€mÄŠ2èužà‘“«TšŒ³æf~ã7öDiT¡ºf£¬ŸË™÷IÁ±^ÊSÇ1Û æÿzÇXñ˜ÍN½ˆWÏ•{øðBÀ¤Ãíèè•¿7Y÷2yóùúÇ;“ '}FF<Џ809½çž{X¿~}Õº"8®[·nÊb*‰¢ž*wØéï}/ý6°âÈÖ}ûÛæ£ ´ŸÏçéì4±’pPg³Y"edâA†ÓRÛ¦.=æLÀæ;ï³<í¼2êa,ù@T ˜}iNEQEQ”Ù‰çy£Nϧ(ÊÜ#ùèûÎ8cØõ-«¾@†õjOÒ™gœå2/ïßϋ˖ñs\À¢þ~ÎÁæò… !—cí·¾EéÖgø»>Øæ™¸’õ…“Îæ…„v#zSªía?|}Õ¦f£<çó&"±\6Ïâ‰ÊsضyöNFŠðhÛ&2°–b±úøS)sÜ?tè”JF?yÄ÷ëGs–˳ktR’ûlÆE<ЏXJÜIRßQR«Ö.¯$g »›š¢‹ò‘cÇ¢èÆ âØ]wqù »ýLˆ‹Åª›,ŸÏ«ð¨(uIÉÈÇÙŠ‡ tü˜ÂŒŠ2f’òäÌÆ¤‰M>ø$S®Œ4˜‚©MÑ¢(Š¢(Š¢(ÂT§§Seöà _ÿúa×ñ¼êgݪík\Ža’¥Àožö^ÀÔw<ÐÜÌttóôÉÐC‹Qì¤ ãž=8Ëû€O?ýÿüô 477sèèQ–¾öÐF> ‡Á™†õ'ïÊ:å2´·ŽH”ºŒ–UýŒ>\ýÇáh„}ûÛ_ÇE}sÜzHÒïP9iŒ×‰;ÂvrÌa’Éd¦\—ðØÔÔÄM7ÝĶmÛ¸þúë¹þúëéêê⦛nŠÖÙµk·Þz+Û¶m㦛n”–u¶ðù‹.¶m,Çaùi§ñÓE‹8ÿöÛyè_ÿ€++ÿÏÒé´ Š2DtœÎ‡Š™5]aöÓHÑÕ¥q×sMºRæ É­¡Þ'ñò¾v0_/ËP)Z¦ìA@QEQE™×¨oMQy =묳hnnrÝzÏ¥õ\}}Ëù‡•áWöü˜cO<Á¾}û8íCÂ^´ˆû^}7 8ç=­4`/íöì9‰¿|ím8ŽÃ¡Ç²3Ï:)—ãçërçR,ˈ§T­­‡X/SÒ¬¦RõŸÁ“‘‘£¡³ÓDWN'W®ZÅïüÎþ¡W¨3¡9•2/Ç»©zyÝãõ¨vÊ䘬ý<‡Q´½!>¯7é:Ääýa_¾ïÓÖÖF†twwOÞ‰­Ã¸„G€-[¶ðéOš%K–°dÉnºé&¶lÙ}¾uëV¶oß>hùlcwSGV¬à‚Ë.‹êd­®DqÂä 4´ µ¢Ì,Dp”ÿµXüìe¾F{Êqë«Ì’&µ³åsy ‚x}™)ÔKÝ’\?‰ï-kRj»dß“}jëD¨'ÄÖ¾WEQEQ¦Ž°F-¦º(™¢(³± .dåO »n= ¡Þ³í“Oo9GÞû^ÎúøÇ9ç÷ŸWj•ËD±Åðè"dÚûüÝÇX¿þ/ØEÀÛ·•,ù¼,ÏÝòüêûæ}òù×¶+©EO qÜAý4©é4dƒ™íˆË™À¬ºx@fðâ(•ì1°ˆùBº€»‡h§=ñw¹ò 5ç(WYF¥íråó PŠI²½ò·¤¸+'ÚÌÔì+¬|V¹}Â0Ķm¼²‡UÚc¸ä‘%>Õã6mÚÄwÜÁwÜ1H\ܲe O=õÔ¬åkü@¥>åñ_üEžoj¢žÄ8”ð8Ö«š AQf‘!ö¼iÉ8»“º*3ý}Qf Ia®ö¡GÞ×[ž|J n¹\\ì> ã9ß×k Öd„äP‘˜Éz“C­#ýª%ù`™|n¬WÃ2 «£>å½çUïk4¾/õ)Š¢(Š¢ŒBb V*•TxTeû/¾˜õO<Áù·ß>á¶.ºh6ôS(ì ,ÿÔ§Ø}Ö/Å+åóQÎSwC?Ùmç#Ň¾„;×rò²ßâxÿ N4ãÅψ¥ÒàçfûõæÔYZÙ¶ÖYy´Fx¬q¶ö#±L(36g§˜X/ñ˜h#Cu4aíàÚgë¤èUÖkúbÄ?»²?±~&n³üðî­´‘ÂW ø$ÕBa£{Ä‚¡D/¶WöÔìß©ì£=Ñ_.íJ{9 ¹²žSY¯ hMì·#qŒòys¼íÆ9|Ça:Š,Í/5ë´Wú#ç rÜç~íÜ1\´úLHxèêꢫ«‹]»vU-_·nÝ„;×(ä~ýò½÷ð“·¿€8jDó¸+ÊÜFf4º®KÓ*˾•+±ìÈn–“eYC‡í*Š2£I¦WmDÑø©J9櫯]Æ*ŠÒr¹X´ki,ˆI­ˆd͉Xì쬎^„øaª4ËŠ—çrÕ‚ar‘D·\®ºÉv’Bèp5'“"ŸDkÖ ’CEb•6)Ö ¢B²/Éóœ¬á‘l§^d¥¢(Š¢(Š24Iá±\.ãû¾ Š¢ òÝ]ñòËC–iª,G{»y%ù€íb%—L¦þæy”ŽþjÝZŒñóhš÷½ï \×üJól'ýßü‚À< –J~?Ø™mIÏþ!8 Áêg9ƹ&â_ù½æÙŸ%Å5ˆ£çDdËGØå¨Ž<‘QÒ‡æ0BL #ŠxX¨œxâD”ËTÖk«ü/ûiÁ8CˉýÛ•öRÄ‚i+FÌKW–—Ç–®|¤2âb>ÀúsLJZ§²­ø Ò•ËhW¶·*ÛIô£UùL"ó!°»²,ÝæÿžÊ:Qd\åïîÊ~;kÚ+V–û–>uT¶“c“~¹•s<õÇO1QÆ-çäAÌóªÓ¹ •¢5)â¦Æc¡P5˜LñZ+ü‰(*£ëš¿¥Æ…¼gpªØäLÒdÔ¢‹¬/Be: Å¢YžNÇç.ªëqHûI‘µ6*2¹­©(Š¢(Š2:‚ CÂ0¤\€…cI§¡(Êœ¥6Da¬eׄZ“ò¯ÿú¯ÑûrK ǯ¼Ò¬´ÜÔ}ô}óü-Ï~¶ vŸyÿÀ—G™u2ðŸ=Ûô5ÑÙög‚Õ·!‘"Ú—Cêÿƒì}_Ó$òPCIó)©CmŒÐe%ÚZPY_=›j2SY_ÄG#¦ù•}¸Ä¢˜D扅3ìDœ“—DŠÐ&5S•¿­švÓÄB^ªò7Äbœcþ/¥Ë‰…Ã乕};Ä‘ˆòY®² D_:*ïk‘>+ëåÔµköU»}«rŒµëK¤d#¢öÀº[ÖqÞîó˜ã{{{éêêbË–-lÙ²…7rÛm·±nݺA)Wg+ÿ硇ÌßgÓÙgú|ªrºÏ×èE™Ix¯¬ã8äóù!g,)Š¢Ì¤æÄÂàP$Å@ÛŽE¹z)W“× „É¡µb"œ‰@'K¤çÅ‘}žgÒ×Ô’ËÅbŸãT –"&žtÚ<ŒÉ:aGŠX)Qœ…Bü¾6êP–9NÝYù(ÇžÉÑÕ÷¡µµ~›Ùlü˜Œx²65m­0«(Š¢(Š¢ dCò}?zïé,.EQ4ïØ½*z¸DjU±™ _y·’Çsi±Hïßþ-XiÒiȤúy€;ïÄ~p7—_¾0¬è‹6AèbåÀ¹Ü—Í&©‹À9?~†Nm„ìRb!/ûWÁzO¥ï"îI4` #bˆH'5 ­Ä2‰À“è;yu`„®re}X¬“ˆG ;*ÿ‹`)} ²LÒvTÚ’AiO¢þDp+G+¦¨3«òj!N_Jåÿ‹€5q¢¨OÙ®"PV¥Žµ¨ù$]ªœSÙßPLW€}M¯9ÌéGNŸP“ãV­ZUµ|ãÆÓt&¦™®>2Ãi²Ó+è¼)E™8Žƒëº¤R©‰76Ô¬LfŒ×9ц”9ÉP¾’d”\kk,Þ•J±&Ñ~`DH‰^tœXèr¢ô.GZ–iËuM$_r›dŸ$šPÞ'£ø’‚bƵ2,ˈƒµiH]×ìSf} "†aÜWÙVE‰Æ”´4™L,Š()íX–i§PˆSª–ËÕ‘‰r®<Ï´ÕÖ¯/ç©6EªeÅÇÚÙ¯ÛÝm>kmû•dåo9÷òS–Lo›LO«(Š¢(Š¢ ÆO –$â1Mµª(JDB}®ìÚPîÅøyׇR‰g+Bæ»|‡ÛØJ…O*tsP¾· ¯!P™Dû¼Ñª¬S€7šh»äWBþE(à¼nîZpn€üb¡O‚7%ZÐI|&¢ž¼DÌsˆC'±^2T„9I VÖ/b„8ù\ÞG'–8zq4±!ÉÉÇq¤¡ü|_÷bGE&S›,'Šhlk«³­]Ó®Dm ùš¿g(A6`ßÊ}jcÜ©Vç*_?p€§V­báÂ…àûÃF;é`CQæþß{E™éÈøhŒe”ŒzËåâÈÁäûdí@ßgBа(šDéI ù[Ä/ÛŽÅ?‰‚QLDD™çåûñ{Ì„înÓ¾¤:•þËs]>G*‹ÐSÉ‘ŸÍš6eÿɈLÏ‹EU9'®W²¯PMØÚ¯/QŽ"Dú~,‚JƒÀôEf³z^µ8ÛÑaúYÍ™N›öòyÓÏBÁ¬[.ÁQί´'çZñTÒÕŠ(*}ÖšŠ¢(Š¢(C#¾Ïó‚ Ô_ (ó›ÚÀ¡ ýý@üŒY‹ï›ç7³qh¾s9Òi³M.—£½µ€·^ßÄ¿.û.:éqÊZûÀ> ÎYæ90dïËp×/½ŒÛ á€Ñ ƒÀ•ÎæÁ=Þ»LvTR`? ´ƒs#êu fâPrˆEÂdD_2h¥½H¤sj–×\Ep̧`…Xô¬5±c­€U+×8cÜÞ"ŽÐ\`iõÄèº$£2“çr–qö}góöû„ÚPá±BmâÔ#+V€ã°øøqœšÈGenãûþ ïýtÒ¸=+Š2“ ‚ú1£!) ÕÖ_LF&ŠE=YOD²Úº…"PŠ%âš,Ï÷p˜Œà C#¨¹®ù¼£Ãl+ìÎN#še³F@ñLAi«Pˆ#s9Ó^2¢0Ÿ‡þ~ó™m’¢TúÕÙiÚ•>ZV,ð‰h(È{GElM§ãó'b ô_Äʤ˜*¢¢ˆ—ííq_‚Àl+¢¥D-&ÅWË2ËùH§Í¶©”Y¿£#Nû*×X"4“‘˜Š¢(Š¢(J}|ß'NG¤ ŽŠ¢@œ­L‚ææf Î|3$ÉÙ»å2þ·LqFÛ¶ù‹[náà)gó¹ûOæšã÷óåW?FˆežãC`/pJÿá³ùÕJ›M.4¯æÚ«OÅÝîjH]öB°ß ô¥Bµß[Ù& ©Ï›È_JœÎTpj^B²F`©ïX‹EýT¡²¾ÃàýÎ3[Û7 ÜD©Û®Iµš<¶9àØ}å¬WXòÂ’ µ¡Âc± »wïŽry_¼˜Ë׬´®mÛSRãQåLEi;N,PvvMJÛ6ŸÙv•™4åÉz“É4§"T–Jæ8Òé8 ©ˆ2£T„×ÎNsL©DméCOO,F3Q+È9GEX”ã/—ã¾ôô˜uÇìS–'û ©lÁœ›|Þô_„àžž8T"@S)³Þ­·þO=µ¸Ñ·º¢(Š¢(ÊŒ¢Ö7à8Ž Š¢T±êøq(•ªKÖ3O?Mþ²;㸕SßJ …MÏ?ÏËK.æ·ûúàÙì˧þ.<‹qî®2Ë#ÀcPðàtŒSÑΓ øn°CøÆÊþ+ÏÜî'b±ÌºIX¦¾(‘'®Ñ8Ùd™•BHð\µŸ£nªÕ9B߇ú(§Çà€ªÃ)ÙxóæÍu—¯©#Ö=õÔSÓxjÆŽLü?tè æx.ÇûÏ=—!>LEN÷Yø}S”9ÇTÎd F *ï“é\O2š ÌeL¸7j_•Ù„"æ%£ GŠP“”¢ù|Ü Žp”!L²}Ia*â\m È’}Éåâè»|>þ»¶b[[á'éOETL§ã:‰P!ÙÑŸ I%*‘‹é´Ò„¤À—ÏÇç@T¦rüù¼Y&B¨o>G5¦RÕ£vwÇg²?‰º"‚åX“}”÷•9Ly*ä¼ ·¼¥%>¦îî8º2“3Î8Æš5‡G·3EQEQ”y‚øÜÊ€ÊqœH„TRQ”¦‡ægÅAùÛ†2 öÒ~r_OÖÏ™•uÐvÈ‹¼ËuyúMOã¼pùãO°óŒ&¾ðêr‚mÆwh¯ž¬4¸È¤Tõ-È/뀘چ-àŸQ r8C:F”®´êÙ1M5£|.HÉA“bϸ"W­ZÅM7Ý4¦×H póÍ7³fÍÖ¬YÃõ×_Ï®]»­·uëV.½ôRÖ¬YÃÍ7ßLoo卵¹gö^pgu=ö©¡*¿BCS1*Ê\¤ÑvÀó¼èÁbRÚÈ~e #6æ*Ë‹À‰Ä«“xBÑd2ùñÙŠ2µÌ[0x,X`ÞKšPy/¢\m‚…0ÜN.Ï´K ‰µë&—× ‘RûOpó@"Qv"†Š ™J!+™zµµ5íŠEó¿˜ÓdmHEü³~¿Y&õÁl/õ¥­tÚ¬“ùFƒ«ÉÚ“ò`X,ŽLL¦Mîb4ÃÁäèH~*9÷%Ù†¤¢•{ £ÃœcÇŸýÙÿœøÎ¦ˆÑØ‚ÙnEžù2&Pexa <Ï«ŠrLúÕ¨(ÓÏLìùÿëúúª“jŸµûÂæAËl|òA;™¶ „г´‡ž“ÞI™ÜðÒJ=v2üJ+Á¾ìËÁZÖ;*¾ÆZŸ€àlŒ“QR›^höQõìY/E*T×1T†E²‰ÿF…ÇáWÄãªU«Ø²eˤvä†nàŽ;î`ûöíÜpà |ç;ß¡©© 0†cûöílÙ²…U«V±uëVn¾ùfî¼óÎ ï߯¼öíÛáq$ñAk=*ÊäÒh;†!¥R‰|>?á¶¶ Œ 7œùI§ãh8IZ[S )T&£S©x[ˆ…(ˆk.B\ŸQÒ†H}EYײÌrI q TÏ3Ÿuvšþ‰î“ý¦Ræïd GA–fh5ÞáWRD­õͤ!]R,¤½Úùté4ìÝûC`c£».#Ù‚¹fEÌ|(Š2˜FØ‚dšUÛ¶UlT”3ÓÆO?ò´µ Òê=Ëå:Îÿð}ØÔI°°™Â?l @–>Ñ>¼óÙwòÇ NÃ_z€Ô2àþ7”Îûtþ-X!¸üW+mn ŽbÈ‚såÐ}Ä zžéHY—¶6ãW˜Ä¸•9É„R­&éêêŠf¬[·ŽGïÀصk»víâÎ;ïdݺu¬_¿žK/½”®®.®¾újî¹ç6mÚĦM›¸í¶Ûp]—{î¹'Zg"È„„‹_~™F±þdFE)Ê|g&ØI¥’m~»ŒØ(Ò@úÞ(ÔBÏNf‚-˜ ,€'ê–Œ„j,ŽÿÎ媣ò’"£D+J¹Aêf2±Ð'"¤¤2mo7ûïì4h‰þ“ZŽRC°Pˆ»0Œë=Jd$Äu;;ãú‘ÉT¤ø¤ß3}7Ù~-lj¯y’T ¶nmôÑÖg4¶`¶ÙEQÆÆ\(Š26e ‚ ˆ² 9Ž£ÁŠÒ@fâ˜`àþûñ¯ºªj™m×xŒp#<®vaO¼ø…/o§yל¹ß~V€u ¤¼ß"Ü\ þqH/çCfwX+Á^Zóœª?¤'B«û\dR³24ãJµ* DáË›7ofëÖ­lݺ•Í›7s饗²uëVFl§©©‰›nº)2õصk½½½U‚æªU«X·n;w“áGeùòåd³Ù!õÒ,LÞÄ›P”YÉL°žçûa"Z1⣎ETtT”±2lÁd“,>.õJ”ËñŠ~A`Þg2qT¢ÔpLÖiL>ؤӱ8éºÕ5!e¿™LœvS„ÃB¡:"2•2B©ˆtmmf}Ùg*×X±±»ÛŽ’FUj ΤÉáRÃr&õi:ÈçM*ÛÙtÜ#Ù‚ÙfE;sqL (ÊØi”-Hú’þ¿ÎÎN~T”if¦Ž Â0¬ªùZ;Xèã/á.ë7˾o¢*<{æFÎþ™³á®6¸>€åÀpd¥EÀBHo€ô­ñv…=úU`e}±³XTáq*pãëð<=¿#1îˆÇn¸ávíÚŦM›Ø¸qcÖ<00@WWÛ¶m£««‹¿û»¿‹>«G2uë®]»8xð Û·o¯ŠœÜèÃÄTۀÇÓÕÕŪU«XµjÕ¤ô;Gáè`ê4*ÊL§««‹Çœ—_~¹Ñ]Ät êm?ÙxžíäÁCBD ”šƒ"†É6òYV ‡B ®ÑX+`f³&BRÄ¿lÖ‹²I© FDôýxМɘÏÛÚL»Å¢éO:GKJ”f.gþŸ-¾—ɪŸ8IÖ­3^ß¹s'}}}îZ]F²â<ï˜àèÑ£tuuø| (sù~=z´Ñ]Ät<ôõõÑÕÕÅúõë‡õY(Ê\GŸªŸüÊ@Y2eePf?Sæ.½ê3—ϰ¶Æc=šò Ò˸?€‹+6d·ùoÅ‹]ÜöøÃü6ÀUöÀ÷˜‡÷`!„?ï0PŠË³ˆ)*•g¶Q¦ÉU*Åþ›¹Æ®]»&eL0náqëÖ­ôöörÇwÔuÜ]}õÕ\}õÕÜ|óÍlݺ•OúÓ£n·«« €-[¶LÊàÿرcìÚµ‹³Î:kXǽ½,Z´ˆÕ«WئÎnš}øÄBžÅàèÒx‰ )31¯€î,Œ0èG²I-?¹#Düó€6bÑÏÇ…ne¯òw­|]º+ûaÑ­ô¯øÛ«ìSÄËt¢ne{«òwXé «VÁªUØ3ÔÉ(L…xñÅéêêbãÆC"ÆòÝÎ`ÄÝ4æ¾_‚Ö©%y4úx¤]]]ôõõÍxÛTŽ 80åÂc[›‰L𕤠†Cϳíø3×# óyÓ^*eB0m¥RqHY&”ËñßA`DE+S)3`¶¬X”“ÈF©iÛñàÚ²LT£ôÇóf×CN2uí|çàÁƒ‘-˜éL…-áQfA+Ê|eçÎôööÎHá1ÉT=ˆð¸jÕª?.R”©DŸªŸ‚ P¿Ÿ2ïèíí¥««‹_|±Ñ]–Fú k) U &â1 r —öÛÿºìàøß~÷Ô?ã°xÃRàÀû-À ðžspö™ç쓉p”hC) ±€™œå(Œ`ÖO a)ÛŠ˜èyæó|>N•Z.ÇéY’‰ ’7Éú³}0‹‘YÃ[gj‘ÇõlÁD3,]ºtÂcE™ Èïêh"ÉT=\vÙej }>¨}>ð}_k:*óŽ7²qãÆy;&¯Ï0™1™Í”®.XøVþÇ?pÚ‹;ùüÙñ»áÅ,½äØ Áð€ÿcà´å¤¯ן‡Ÿ‹ŸÙTÛX¤,Í\dÓ¦M¬ZµjÂc‚qÕxìíí:1šŽÃæRîíídÔÄØÕ`=ã7ÑYÊÉ(èïý¨¶™ŠÔ 3Ýo—Ìö&›Wù_^¥Är¡œø¼­òjN¼Z*ÿ·‹nm•õeiOΑGœ~Ôˆe‹†>FpëĈx'꼺+Ÿw&Öu+/YžÆˆ„ÅÄvÅJS@Gåó,Õ÷“›Ø6]ów½d¾Ve©JûõaœD[#Q»½×êG×=0•4Ú@œNe8Ú‰#Y»™ùß[E™mÌ[0’b¢<„aý”+"4°Š(Q žW-ZJHi×qâ÷2DÁSöU[\¾\6ûîì4¯TªzÖ¤ëŽÍ8›DGev1Z[0퀢(“Ãl(Š294¨ð¨(3‹™4&¨-áXœTé9Ô‹üÖëφýÐw^Ï?ÿ„ÿØ:‚—Vî}›Ï~ w®}ÙÌìÿûI¸ÎÁÿ)¸×šIÃét<1XÌQºN§|^…Gef2.áQ¾Èù8²Îp)Í®¾újضm[´LR<$·Û´iÛ·og``€mÛ¶ÑÔÔÄ5×\3ᱡ¿ÚÚ˜‹ßÓ¸a#–1"b+&z«µò™E,0¶cDñ›8µh#öGû‰hØ]Ùo¹²]šXh”¨@‰¼“Z‰âë”å’†t¼5óFŽ[›Z$-k£î§pâML;3ÁÀðÂc™‘iEQ&ÆL±ã%›,àù¾%òѶͫPˆëÞ¾}{Õ6õXµjŸþô§¹õÖ[)•J,Y²„ÞÞ^nºé¦ªt®[¶lá†nàú믧©©‰ÞÞÞI-"k[Ì®(±$%âH;#ÚÙQê ZÄQÞ" ÈL Y¿œXªÓI:Q°Ìð©>S•þøÁqº;ìa„ÎéDÎK¢~ð´"5 g3Á —jµŒ¹¯Æ‰ª4–F}•ñ1lÁXÉåâú ¥RuªS§:ÿ˜—ÔipœxFcRlÌf㇋tÚ¼÷}hoÛs]³o‰h´í8â²X4ˤß×ÙÊì`4¶`&ÙEQ&ŸÙ8&Peò™n[VßÎ$ÎÒ ‰ý4òÞ"ž¯(ÊðÌÄ1ã8qZæDݯôe‰•Ê€ž8ß/XÌ6Ï_ù†óûðwZQ†#ÊåxÖ0æ?•Ùĸ„G)ÚºmÛ6Ö¯_ÏÕW_]w½{mÛ¶±iÓ¦¿à›6mbãÆQ„äªU«…A755qçwFi[ׯ_?)†C¾û¶m7ü?ÀؤTÍ2“DßeH³qL (Êä3¶`4õELô1¥‹ ã ˆ}xyûhä€`xÒ¾©QFÈϼæóñ­â¢Ë–²íÃÛȶe9tÁ!^}úÕXLŠ¢(Š¢(Š2{ðGœŽ—ää3˜ÐIŠ¢Ô£­Í¤0•ÈÅBa° †f¹¤BÍçãèF©å躱 )"¥¤UMÖrìé‰EN1UN£hEQEQeŽA•o ŒÉj%“ÌEtTeþRZ¹ x¥â¾ª ºðD+~ÅC¼hÑ·9ýôè]üzÂÅððÃçE›¦®ØOùÁeÑ„f•¹ÀIS½ƒ­[·²fÍšFçˆ=z´Ñ]˜TÔÙ8—f#yÝuæÝØ‘‡ I’E\EQ†Çóbá0L¤cqÐuÍ{‰^ÌUžPÄ‘ÍB_ßFÄA²»Û¬“Ï›4ª0tÚÖ´f_QEQEQ”I# ÃÈ7àíľI«:¨¯AQfɬZUµ`  ©p–>Oøð¿Â%æa=¬|ÛßøÆ7òøãÏÒûüa‚#ÕíZoZŠsÉ«d³æ9¿ÁÕàeR˜ráq6 Fc4Å£g+s÷ÈS+ºÎ'N—ÆO²ŽC¡òÿ\¨Ûœ¼ÿõþP”É¥vbÆ‚£çÅéV!ŽN Ãø½ïáC‹m›J!k8 …BU› ί(Š¢(Š¢(s ‰xLNHÎcÇ&o¢¿ (ÊìCJk]ä¿;CLX4OP:pþñ³à„y¸w.y•ÜÆOñÔSoá±Ç–±dÉ’h²r>_)á²ü4¬sNŽ2#©ð¨Ì&-Õêlgß¾}pöÙî†2ÌGŸl -l>äᢄy°˜ ¿óÉû_leráO¢ÇD1Jj”d*ÔË.ÛËyçG&cÖI¥ µššö20Å¢i«³SêEƒjO{žW·­¢(Š¢(Š¢(“CP™]ØVù{.LHVeò°'÷$Xï7"žLùŒeðpøYX¸V»øk6‘ß~#+W>ÁÍ>¼ˆ0Œ³%¥Rñ„b)Å¢©V•¹€F<{öìaÁƒ|Š2[ ™¢ÙtcYe̹SáVQ”áp“>Õ÷Mt£ã˜‡LÆ,CóÐÏ›‰]»¾‹ça ½Ýü?0ð(Åb\ÒqLz'‰l Ãr¹ €ïûu…Ç0 Éår£ê·¢(Š¢(Š¢(Ãóíw¾“èD}+Š¢TsÒž=æMxÕŸ9K~Dþ²;qða kRþ•_ ©© €#GŽT ‹é´ñX–y¥RæoE™íÌkáQ¾ãO?ý4™ÖV•9Só¿2:Ä™ï©iØ_)™ƒQ™rÔº+“A.§B­ÕÿÂÐüŸL‰P(˜ÿ»»û)—MJUù¬¹ùbÛÕO+¾ïGbc¡P ½½R©„ïûAÍÂÊå2¡t@QEQEQ”q†!X·~:ETtTe\Œ¸àßÍÁ²6Ü×v’{øzüÎ~Ø–…_OsèЀû÷ïç´Ó^âÇ?n®[2ÅuÍDd"e¶3¯…ǤÛÅŠîΤã‹«ÊüÁÅg*´ŒÇqð˜Ñ6‚II™hþ…Q¡ße2ð}#0Ö~í‚ÀD9Bœ^5Ÿ7 å²ûú^ŠÖwóÙ¥—ÞWÙ¾ºAÏó¢¨ÇB¡@:&—ËE6£T*‘Ëå¢(G$EQEQE?¾ïC*…ñ­L:}PQfU^¼ñhïVØ´í¿±zƒœ{îÅ\vÙGùßØÃ¢E_¥£ÃdK²¬êò,ŽF(sŒq ]]]¬Y³fT¯mÛ¶5ú‡$rÑÙ66lhtw¦ö•yCè@…–±Gßð¦î#‘äû~Ý¥±Š‘’Žq6¢QZÊlÃK&Ê DùÊÖÎX”̧Ù,\vÙ’ƒåïÿþYZ[›6žþ3X–5H4;ËåH¥R‹EÀØ©T*E¡P J¥™LÏóð¼š/›3–ïX½hJEQEQE™O4½ûÝÓ’IÐ îŠ2ûèZßeÞx˜/ñ½Àšú1Ò<ò4O>¹ŸüÇ·pà@&Ê‚$’e®2.áqÉ’%lܸqL¯™ˆDC£)VeÞ.[†Ãä¦SI:ñ“"áP‚@kkkÅ4ššm¥RiÚÅ;ß÷ëŠc¥P(Díd2™è\æxf³à:V$å¦23ð¼8ê16³Óé8J:mÄF0Ë0„+~ ø,^|œƒÿ+}ßÇq|ß'—ËÑÖÖE6¦Ói,Ë"ŸÏN§±m›T*…ã8tttÐÙÙI©Tо;µÊåò˜Ò:'ÛRe~ ¿ÃòÝ‚€B¡0©c Ïóªl‹Ø¼L&C.—‹öUolT»­¢(Š¢L5GÞû^-]£(Ê\xèÿïa!Äü „Ó‡Xÿ ¹è¢e,_ÞÇêÕOÆgàyƒ³))Ê\bB©V·lÙÂwÜ1ª×LĶ8L_ EQf.{Î?Òg6ú¾_%È{×uëF7‹ER)Ó‹r¹O>Ÿ¾#étÇqp]—ÎÎNÀ¤‡–åŽãDQr¯  Y.—ë./•J“2©`¦¡ße.#cIÏ,¿ò;éyÍÍÍ´··Gi™ … ,`Á‚´µµÑÚÚJKK , ¥¥…R©DKKKÕ„ˆ\.G{{;žç‘Éd¢íåÕÜÜÙi«¹¹™ÖÖÖh2~hkk‹lM²---´¶¶Fé¤e[Ùo¡P —ËU¥›–qV†U¿¯CMȘ,äw9Ùþt ¤“% ÏE{¯(Š2Q¾¾cÇ/V¡¢(C†,>¾Ø¼·1õ®²Eø»Ê¤áëú°ÿðW£ÕÿéŸþ‰§Ÿ6‚css3Ùlœ9I…Ge.3.áñàÁƒtuuqðàÁªåkÖ¬aëÖ­>¦1qßI'Åßö9Ä|$©‹Q ¾ïƒeá1ùߤ$Î1ß÷) 8•îâ´J:ÔÂ0ÄuÝȉ%¢ŸˆO"Š(áû~UÊEqðéŒðyÒ¡&}Ã0Ú8¥¿µ¸ Èd2´´´D}moo§\.ŽãP*•H¥Rd2Â0¤­­ ¢u=Ï#—Ë‘N§£ý 2™ ¥R‰¶JΊR©¥§Íq—J¥¨ïâ\­Eö%ëHDj{{{ô^„Ƕ¶¶è¼„aˆmÛQd‡8UʼnšÉdÈd2´µµÑÜÜŒëºÑ¹°,‹b±9~åžð<ß÷)•JUÇßÞÞ^ÕŸd߃ ˆœÐ£‰¦UFÆ÷Ø(/߇gžy&úLü—\roåÿ‡ñ}Û¶#ÁP¾ÃÅb‘l6Kww7Ùl˲¢ûÀ¶íh¹eÅqÙÙl6ñåÚK$‘\ïr¹\uÍs¹\$P´··ÓÖÖ}çê9·rryÇùÃ."‹¢ÌtdR‰Øx Êfçr¹èw´P(ÐÚÚÙ|ùýßA'ˆp(šD`”ßÈÎÎNº»» Ãîînº»»9qâ===¤ÓiÊårô{/È+¯l6 ‹©TŠþþþh¿ò¾½½R©D:¦»»›b±í7 CR©©T*¤R)º»»£ý&EUþZ[[imm¥¹¹™–––¨²\^rŽä÷V~WE8•ßhi»P(DçRlkRhmii‰„ÕB¡@{{;­­­‘)bk­í Ã0ú "-°d¹Ÿ ãI˜‡²³aVMXjmm­ã%#\ÛÚÚ¦L˜UE™­hnæÌýû'5 ’¢(s‡øÑ~Äï6=IÛjŒð(Ãå\ŽÎß{Ž#aøÿã~áÞÀÞp”øôHlÌfM%E™«œÒè4šÝMMÆ;8‡+¸ÎGRêû*ÊhÃ0* ?Ù–@Pn%q»8Òòù|$² nýЭ¤R©(‚Ñó¼(j)•JE¦ °,+ŠpGU6›¥³³3ªÑfYaòüîÝpÁQ‚ ˆ„A0‰¢’HJûûûq]Ïó"'•ô©P(`Y¶mS,£(<*$-¤ω'ÈårÑ6âD“4’â”4”²Ž8Æ2™ ®ëF‘aÒ˲H¥R¸®KKK ©TŠË/¿|èë]é£ïûtttD¢ŽôÍu]ÚÚÚ"0‘ÖÖÖE«I >I‹Åb䤵,‹B¡@©T¢§§§JL’¨t:M*•Š„W¤%"¶¹¹¹Ê) Æq,ÎÚ\.‡mÛô÷÷GÎÌÎÎÎÈAéû~䑸X,†!_þò—9ãŒ3¦ýû6›I~uN:ië×ÖbÛf¦¢ã€çÝËïÿ¾Ãg>s^å{°w¯‡eY‘³YÒ§Êý’Íf«îù¼§ÎX¥öÞíéé‰Êò]oooDL¹Ä1.÷r©Tª‰-Nn±c¶mG¶GR$&äÉû8•JE÷ùpˆP˜tN] ‡?>À³ñ,k?¿Ö,÷€T,ÚØ¶m–…fy&“©{ÞľX5Ozår×u-»XK¡PˆÎa’ßÚÉú÷­´Ýç#`PqfùNGçF™“$£ö þ²m;š ¿û---ÑﻤiÎçó8Ž­Sû;Ÿ¼çä{^;èééÔ/‰º-ÙlvÐw!9¨X,9!Èqœh Rë!¿Óò–ÉC2!#›Íây^!.¿åbÛŠÅ"–eEç_[ÙVÚ,—ËUçZ®üÎÊ5ikk«úÎËD&¹.žçE×PÆV®ëF¢£eYtwwÓÖÖE¿Ëg2>k)6¶\.“ÍfI§ÓQd«ôOÄÇŽŽŽh‚IgggÔöövº»»u‚†2­ˆ³Æàm•I–u£3™ ÃnDÏõ~»Gêsr‚H½±ÂpÈøBlòX¶ ÄÖ(#³÷‚ XõÜs°lÙ´ìO ?)ÊÌÆJ€ŒbàRà‚®bÏÙÄéV}À h+_½´Ÿ”}VÔÆwÞÉÊ•+ùõ_¿Û>ƒ®.ã;ð}ÐG=e.3ï…G€ÕK–4º Š¢40 YöÁNIù¤Pc’þ,•JA Žuã =oàÎ;±>cE"Tggg$àåóyÊårä“Ùìò€-N2qD‹EÊå2uÓM8ÿþïøPåd“è·t:‰ò¹8ûE ¢³³3rzyžõ+NG"8¶:::"ÁK"&ÄùŸtdJ´_www•ãQÄÃb±H{{;¶mÓÑÑ9Þ€ºü–eEmläŽ?ÎŽÇÃyÓ›hoo |>_%ЈsÏu]ÒétQ(ïEГ}KÔ€IC"EäÑ} Â’ˆ6â,ªœ r>’‚Pµ,y.-ËŠîq2Jû===U‚–ëº|ýë_ç‰'ž˜º/ÖĶãâﯽö?ùÉOøÜçÖF‘Ë—¿x|æ3EV¯~šžþ7R©ó)—C ™Ù¢qb;%ŠÔ½Ž@•Ð6ˆ2Ô3V®ëF"¼ã8Ñý Õ5Òäž”ÈI¹?剔ÁNœìɹßmÛŽDFqîËdÙg9g&‹ÅHT” Ò7±KÏ>þ,¹ë#¼vïkQDf¡Pàìÿ:›k~x ûRûxðcÒ¼£™o-ÿ§~óTÞðìø/ÿ¿"V,yú¦§9pàß)Û³ini`ÏíaïÞ½œ}ÒÙÜö·qðìƒ|ä}áþGïçýàžHð±€ûϹŸŸ¼î'lèßÀ³‹žå¹+Ÿãÿ÷,ݰ”®ù!oü¿odÏI{X¾|9·?xôxÿ“ïçÍ»ÞÌíçßÎp]ßuìnÚÍë½¶9ØþÚvþöÞ=NŠêÎûÿp“û@Pœ€‚PBD'Qb¬YeMDÙí!»¹(»¡zÍ®Áì²V?ÉOŸÄÿÖ<¿†?#Šû¬$Á¯­{}a‚€@s·qÀg¢EÜí4÷SØ K ŒÔà°ãñ¸'Ño˜¢ÿH,¢~‚\ O}þ² ÐÝ×$€j„„yª7å¾¥ö0¸Mþ÷`ÛK˃ºêò'PIוD>Û¶=±”&‘Ñ„ êïÐ$3Šòp˜<'Þ' ¶8“Éx“@âñ¸×7£œ¿ä K^£4…DÅ––O¤%ïÙh4êyÏÚ¶Ï~ö³å¾‚’/DѵžÚ Ã0¼Éyr&F—2MlÈo‡h‚ž¦iÞ¸úÂAQúÝ$ÒÑd'ÊYMѨßÌK“¨|Áþ5E¡òÓäHš4À‹F‘_n‚~oÁ:;ŽÓÍÛ›Ú ê?¼‡ÃÐu‰DÂkb±˜Í„®[~lÛö&d2¯}êiBT!hì™?‰£?Ǩ%Þ8ë,\˜Í–ì|Bx*¹Â#œ~ûmŒí‘ þˆÝ÷_èºNHs?€Û º /½ô|ç;õÁ͈P«‚;vì`óçÏg;vìÈY>þ|vï½÷äÃʽ÷ÞÛ­¬Ì 4åÔ)¶ìÎ;Ë]Ä!'ÅSŸµ„¨û€ðàÖ[o-w*ªÞº®³qG²Ô@šfŒ%sÿÿéw~ʲÙ,ciÆÞÿ>»mùmŒ1Æ$HlÏU{Ø{w¾Ç^[ó;pÎÆÀØñ ÇÙ¶¥Ûc‡¾{ˆÅÕ8“e™E£QÇY(bº®{§pl‡m¿b;Û»j/;ðõL¬˜ÅÒé4cŒ1,“É0ÆK&“lçk¯1Õý.Ë2cŒ1MÓ˜$IÞ2]×Y4õ¾ëºÎB¡‹ÇãLQïx}‘J¥¼²f2Ç™$IEïOôwûB\±};ÓcËÞ{AU½ë˜Íf½ãG£QoÙH"“ɰL&Ãt]ïñZîØ±£"ßÙÃMO}‚b‹ÇÛ¹ót6gÎ~¦ëŒ­ÿ&c©cË–½Ç.Æm ` PXë_b™L†`ï-{`Ýþ9eo;tÆÛÆ‹3Ʋî'Üïiw[Z¯ô¯ÌÙl–%“I&IcŒ1EQX2™ìq{Y–¦ë:Ó4`¿[ñ;öÚÎ×øiæµ ¿ýÑoY<ç¿·‰ÒuÝ;Ÿ$Iì½éïùm’Ì×Kسnd’$12{â’'vßÂûØãß`ØEÓ/b÷\}/‹¬³£ãŽ2ìþ ÷³Œ”a’$±íWlgûçìgŠ¢°‡Æ?ÄšùÀöÌÚÃ2j†išÆ~0ýlûÛK1vì¬cì§u?eYd½‘GFaÿtË?±g¼ÈûñU?fžó(Û3k{ã†7ØïVüŽÝ4å&–’Sìþ ÷³ßÈž¿îyvhÉ!öÌŒgØó×=Ï$Hì‘9°Ÿ¯ø9ûÁ?`ÏÌx†=uÇSìž%÷0*Ûþøv¶çŽ=,‰${mÍk¬cLÛ~ÅvÖµ¾‹ý×Âÿb vßÂûØýîg?¸ólÏ{Øþ9ûÙ‹—¼ÈtUg+V0*{èö‡˜ •=»úY¶wÕ^vâ–ìÐwñkƘÆüNÎXÇç:XÇòÆ¢Œ1‰1rŸ¥¸û¿Âïç/þìþMT3ÃÙJ§Ó^ €`’$1EQ˜$IÞ;7•J ÉûNP9¤ÓiFûµªªLÓ4Æo³©eŒ÷«zê£$“É‚ë²Ù,“$‰Åãñœÿ3™ Ëf³LUU¯¯–J¥¦( ›?~¹/_É©¥¾P*•bªª²l6ë}gŒ÷…C¡“eÙ[F}‡d2éµQ²,{Ïõ©UUõÚ7UU½ö-{ÏY2™ôŽOÏ–L&½O]×™$I^¿#ÿøš¦yí%-£¾Ú[:‡Æ<étÚ;>•“ÊMÛ(Šâ_Q¦( “eÙk»%IòÎ¥ªª÷§iZNßG–eïzQyB¡W®x<î-£zëºîí§ªª7F …BLUÕœ²¥Ói&I’÷ÑuݦÓi–N§Y6›õ>©ÜétÚ¯[&ÃûLš¦ÕÔo"Hp|0ñÍ7Ùª‡.Ù¹Év%TÂfè“o[ã}·¯LîdÒÆÇ_)Æ¡Ó/y‚ÅãÜ>Àÿœ1ã¶|y‡w ]çv…àvA¥1}‚š©á˜÷ÚklÅM7•»ˆCNŠ1&3!< á±0¢‘‹³ Ç÷ï`Y÷OcüA 1."HŒ½1ó –Š¦SË"Ë2*7ôœ\u’¥b4öÌ]ϰmK·±gÝȶ_±­hXÁ½îQþKÜ@þÚš×Øýÿý~ …XŠz#Aƒ±Â<ƒó‘ÑGØ;ßy‡1±X8æ ¡PÈ3€Ñ€;{FQØ'“IÏØÀ®h°šDOH–eÏðÕoŠÑSÌmò¸bûvv¶âÔ)³|avÈÈ2_i6l£Lz…a¡¤R|,¡ªŒ­YóƒÌØÌ™o0UeìŠíŒIcçœÓÁ®ÕmÄÙÇæ|ŒéQÆX†±¯î댱kê®a]ë»x›A/+Œè»Îø <ÿ{’ñgÌ#I?$“±ÜÉ)þ=›Í2šk€‹ˆ…~_Y>ˆŠÇãÞúL&ÃÎÌ9ÃÛÆr­#ª[Žl Œ^Ÿ‡W=̺ï!Æ$Æt™!éøúÞŽe{ë–·“Ûóã=ü:(å`ìwþ€×Maìõí¯³´–f§Vœb¯o j:ŸŒqbÖ ÆÀxÝèšeÛ?g?;>á8c!Æ™óûæúo²÷î|ÿ.¨ìDš¼.ôêÉøß›pD×3æ´±AH`(tjƒ©ý"C)W%IbOl~‚½¾ýuoÒ dP,Xö,Ÿ€ÒqN;rö!<dÐ âɸ|ÿŒ´‰.‚Á“L&Õ×êé˜Azk§R©K¥RlΜ9å¾%§ÚúBù}Ùl6ˢѨ׿à‰V™LÆûdŒyâ‰iÔG§vŠD4ÐHp#ŽD:Ï4MóÎEíZP0Ô4Í;¦iž F"$ q}Õ±’$y‚\6›-8Ö s)Šâ“Þ©TþàÄÎl6ëÕ)•Jye¾[éýK"kþï6Ø_ kC÷€ö ¬ùÐý¤É týS©”wxëóIª_ðtœà=ÔuÝ›ˆFu"tÁ‚lýúõå~ÔK2Œw!7?ñDÉÎ-„GA%"l†>= :^c 1{šy³”Õ9û™ª2&ËŒ­Xñs¶jÕ^¶té¶œc&“BpT>CÑO®ùP«swîÄ™cÇÊ]ŒaÁ†iK ô̫ӦáÒ}û€¥K oà^vy<΂á.‚-BÀ}€…÷/Þ^üÓ1vûXØ–þÏÆ};ïƒüKK´%î‘p±}1$IÂßš‹:©Ž‡½s€ÑçÆœšƒõï­Ïxœx½(x˜<—Ž5¸vݵH/O1àNóN"/Àó }é³_Âំ6Mñ\E§~~ !)„P*ä…ë“!{çðÂ0Ùîu°‘› Óp? „Ô4-7¿åd³ÁëCÈnÜ|mÜ뙿&6ܘùî÷û³»<°ÌæÇ:tè,X€ìɓزe î,”¿ˆÊP|+›Êj(§?´a(p. qs· ¹ç—à‡D¤0н_Ðè^£¼m)Ï…ïë†,ÿëåÈüU‚âPžüÅfañbàЀGãªÃi¥ øÚeÿ€Û5 jßYú$fácaLøÌÄ®ô¿¿‡qa÷{ü7 ÿ&‚ÏRÌý_Gn¤¹ÛÄÜ}"îò¸» HÞ€Q®Ø9wÎáÛÆû…´OÞð$&©“€z~.Y“ÑòP¬¸e5L6€9*`H^ùyõóÀwyÙ–_¼“ÿe2@—uÌ~î]À™ $€™í3 ;Þ­“ ÄeÌÜÅŸÛðÜ0¿>ë4<± ?7N [ÝÜ0]|Ù~xs¶Ìá×1ÂË·uÅVüyòÏ1Q™ˆ¡LPP­G=ê ÜäÂ÷>&¹·õx¬œÀÿÁ<}JùÄóCE †µü¼{‰DÂËßvÓÚ›¼m?óÑ¢%ƒåæ½¥sSØEÊ-ðÐo7κÙ?Ïb.æägQóCåQÈqI’Íf‰D¼°ÞADX;A>ÑÇ5ÿ˜û.ÔÆ|êSŸ*÷¥¨)‚éÃ0¼6…Bwêºîõå)=åeµ, ‘HŠ¢x!8)Ç8¥a õ¸¥¥%'W¡¦iˆF£^xsÊŸN9Y)Ϲ$IÐu¶m{yGMÓôÎ øÏ…2-”×5™LzyS =—=½+ó·1MÓ _(<,…!|§RÞÖàº`yiß`y(=½óËì/Ê[K㲞êN×@·Ü…¢—e9ç^8Ú`ÈhÊÿžH$¼û+˲¢Ÿž ÑÇqî¹ç졘&íÝ‹ 'O.wQAbºŸ–eaÍ¢6`÷à:ˆðœÞP˜æALJ…'OÎA{û“t47ÔlKRn¸U`¤2(áqíڵݖmÚ´ ›6mê¶|ß¾}½«³³7nÄÖ­[ÑÙÙ‰††lذ×_}Îv7nÄ–-[ÐÙى믿6l@CCÀÊ/XúÜs°G°@‚j¢í´75ᦞ& $À{QäŠe$ Pó! @šøŽ9‚Ìð£~„ûÇßQÊ(<~ìq`Nn?tæˆâÀDL¾  ˜˜šˆóŽÇ‚làœ.Ó>6Žep¡‹r}ÙSZ^kA&“Á^þŸ˜óÀ@Ú¶-€žÔyÞp7¾Ûàç#]*âþOB‰!ø¢åKÀÔtU÷ù¯$w[~޲ü\d6¸¸¢ÀÏA6×ýŸÄÉ|Áð…]|lúÇ0aÂÔÏù˾Xøe"¡FrkÂa‚¶b\h´Ý{àŠÌˆ»ûËc*çFu¿«õ’»} ¾ÀjºŸpën¸ÇVŒ Ü“ ˜©¸eh†/ eøù&šä?_Ž{} øBW8¼ê0_x•H¹Ú‚Þ°, fé$Lþ“ÔÏàxl/ï9 —þùóxùñxAŒ¿[pÃÌð °–Ê7ã_€ÔçÖFÖ15~+£A{™øNÍ‚ ~eø¢Zþ³Fí‘ø†ßnͶlÙ‚ûÞÇŸ¾ØM¢¦ L²'Û `š$d~ŽÛà« K>¢¿0€÷u>Z²ì7Ó1ÀP_ËÀ- ðCÅ{ÎW^~ΩÃ룿Šë^x€ h)¿WD€8) 6ð°7ΟU¼ÂÄ€q20&|\âõ¦6ï«ðZ3ŸS€nŠ1·Û·ãÁyâËÒ—so¦,óó²ÌUfY‚†LÓä´?à‰¹sù3âû»9æÈ`¬Ë2HðýéÁ|K¦ ?FðA#lK ËÐ$‰o§(ˆ3–[;¸nØYÏVÛ¶aY®š4 ÿãƒàXyÅøýï?ƒÎßÃ\Ü>,¿›ÁRL[PÊv Ÿp8 Ã0<xÐhMù”Áà¨Ä>ÁP@ù %IòDÂX,MÓ¼u¦i"‘HxFt]÷ò¿ÓDUU½|‡$¤QžD:‰‰$V™¦‰–––nùLI NPU5Gø"ÑÊ0x§:_(¤Üñ½A¹jƒÇí$<t"åÚíM/$€RÞ÷––ïZô‡ ÐWlÝóóôÏ/¶RÎJÊåJ¢up_EQÐÜÜ Û¶½±gð8²,cÕªUhmmÐunJÑXŽÿìg¹}¯ z Aq”£O@b#ÍÙ‘±kº;Iã¶øãļ¶#›½sæüŸ¸`€¯? êðØÐЀuëÖ iAÖ¯_]»váÛßþ6êêêÐÚÚŠõë×ãðj8¨Áظq#Ö¯_Ç{l@çôìÎbš@P”£°œnhÀ—¨'`Ã÷8J€û>æ›]oÂø™»ï»XÔGêñ훾»pW7ѰOTà#o ûx£ÕÃþ9혯«ÕãW¿úb-1„ìæ¤ç 0 ³üí3ðbÓØÓõ$BÜøO‚•ß{/ _ £²ÉðHò>|A3_Ѓ»‹ƒëȃºö$tÅ<ªsž»÷|k>9€?ž7 ßüÊÅüÜ*|‘‘„L×Ë6¸hÂDHäƒ[v¾@/Pf*]?¾÷bOKwSðÅ£ 0$Î!ŽG^’ô—„çQ:Óš‰d& É‘|±5ã–Éàç:xè P™v…²´=‰ðñƒäŠé‘pìØ%¨û“spáªðÕ–nœ}VÔíÃ5gþHÿ“ÿj Ò-ÓÖ+€üÀœ8 €ý¤ë8èþÖ v¸¥Ç€/Tƒ?Rr¾g]ÜuŒÔÜŸ± .:½ë_ øÉÚŸà’—.Á9M¿®ŽLl?7£làåpÌEÅC°1|üy¿ÓöJÀY6p ™_U2ð0øïã…(pu˜çÖh¦ ¤obÁøSaô‡Ï£õüà#’f*¾w§à'ð_ °Ó¾¥1 8D7ÀzXs©Ã÷5°" |^ž69ÖH@x·þì¯û@û2î¸g/n0M âñ\aQ’€h”_WÇ)<Õ²xÝU5W´$âq¾œ¼«]Ï 2oZ³† ‹ŠÂÏ]Ȩ%I|?¿ŠÂËá8|›|O©xœÿYvþçâÑ{ïÅ2pcr<GHQ¸øér^[¾ÑÚŠn¯Lᱯ¶ Tí@>Žãx^@dÀ.äÙ#ÆÁ੤>Á`!o7B¡š››=Åx<ž3‰ÁqD"oûh4êy­©ª ˲ IEÉñ~ zæ ‡’ëOmWP`#Ѱ/¯Ã 7¾øGË‹õŠñnìîOeîïþ²,{õhûNû ´ì$ºæŸ_QD"Ox ŠŽTgzÈSµÚ(E[`€eA*±* „G 8ÊÙ'0àÎ9ïRH!öÚaÈßò7(à}¿rå‹èì\ÞMxj†rÇ‹eŒ±ŽŽ6þ|¶uëÖœå7ß|3ûêW¿êýíµ×æÄ–}ýõ× î—OO9UƼ˜ý# JE)¤j‰$óãäKå.L…R‰ñÚ‡»è©Þ_?p€!\=Êø”vÿâŒç£¼jE@9½t]gÑh”ퟳŸí¹c{oÙ{ý¿0æÇŒH>A•±‡nˆÅêc¬#̺((o››³­ßçϺ×3xœþgnCÍxÍþbL2¶¾«‹1öÓ¿z§ûS‚ ãùâ‚©’ŠÍÍèæ×cr?ËÎuN àºÑ¹éú÷ð¨Ô¼FåèôÆ’%‡˜®»9ãŒMŸþ!»âŠílB–1¨Œ]²hcì+F'›¢ÞÄß½?`,y«ûŽ2–zÊOeþwÊA·8ÝÑÁX<Î2GŽ°Ð¡CÝÊ’~ôQ¦ÿîwŒiÏ!áæðŠ3Æâï¿Ï˜®³ôw¾ÃR7ÝĘ$±ìk¯yÇ~î¦/3…1HŒ…ÝlöD6Ë3Üë:c×Åû•›ƒ.Êüg=ÄÜü‘I¾=e}·ô,K†ùù“/ÎØ¾‹nf¸yˬúzöÚš5¹åf(¿f9ºÜ”ÇŠ1žÛ³§’'NdÿöoÿVòòõE1mÁP÷ Šrb)ŠÂt]g™L¦ÇüA5Q‹ãƒRõ…²Ù,K§Ó^Î=Y–½<¼psó‹,Ë^nÁü<…ýr,Ò¹é}ååzîÚ6åŒïë—Édrò÷z¿ 4g.]÷R¨îÅB×y u§²Ê/IÇííØÁ|…¨õñÌC‰ßé4Ü*‰ZìôToùöu‰1vå¾cŒ±Ìì0Q>.øXšñ¯Œ1¦(o•$1&† ‚jc(ú£Ë-|@[[ššš°hÑ¢œå‹/Fgg'`÷îÝÞvDCC-Z„]»võûœüc¤†@ Ο¹d ¬oidC9ÚÈ0†ºwßåÿ8ð½ôšÝï¸GPE=PòÈ0 8ŽEQpÁú ð›ûƒÃ“Ö2î1h`ßpÓÚ›ðwwýꮩëß¾üЭ>µ?8àS øž|ý,»—ϲ¿9ÝIª‡q·©·.~«ûSèÔüüDoÞ‹AZܺd¬ ?¤lbûÓóÌOZ%”«-è‰wÞùÀÿGŽ4ŽÂ ¿'ÜßGçùKùv“¦"ö~³ìKë>~é­?ÌøîA'`ë÷¿‡yâß9¶eÌ †ùÍo˜1βe^ZT0'N„1{6÷šK¥¼-6óÐ!À²`|âˆ}ï{@<ŽÄœ9Þãsù_þ °<,N?ˆöö‹FmpûÐèðŸß$\¯åP®·…Eî Ws1Ðï¼yŠd?’õþÝ_W‡®óÏ/ì­8LH’ÆÇª%;'ôlzÎ!yÏ=÷`Á‚%/__ôÕ”²ø˜!#{!t5Mƒ,ËÝòˆ ‚¡¡Òúý¥¥¥‘HsçÎEcc#t]Ï Ãl†—·X‚m¹mÛ7JÞ{´?}Ê]ØW9I’¼wN1ûÔ믯ÜËÅ0Ð0¯´ï@=©Ì=?í—í¨<Å„¹ ~V ¥j F¦uP ”»O`Á <õ=p5qI1äê< ‰ãðaz$œ9ó.¦L9íÌáUµÈ r<À–-[0mÚ4\ýõزe ¶mÛVp»Í›7÷xŒE‹u[ßÙÙ‰­[·bÍš5€ŽŽÈi<`Ú´iؽ{w¯eúÑvsÇVà: 2©yØ(›»¡ã8b:…  hhhÀ¦M›Ê]”®v¦L™ÒMl84k>òÖ[ÀøŠÁ~:¡PÈ3LZ–…T*富ì˜C‚_eˆ€¥càÂ1Ûì šçGV`Ǭ8àäÉ“¦öÿ CÓ-}ýi?§ð1èwP‰Þ Äp÷ Š?øÈ¼¼ÿŒ{žÏžÜ’¾òé ùJwt,´QnTÜéü‘‘N‚¹d ô‡Fjÿ~4._ÎÆQ£xÄÒ%K–$! ¾ ðÛ–ÖkëÏaðŸsÔýnÃïÇPóoÆâyu»Ç ¹Ç¢sk²K ü?…Ò~à øÉk¯áûå.H™†ͧ®®MMMhmm-w1{e¸Úû"‘Hx¢ã` á±XÇÉn ÃðR,8ŽƒT*å­ïI+â´XÈvAž‰°Èc2ÿØ}yÌ壷ÿûªÇ`Ä¿Á™‡Âãq0Âã` ä=ÝŸb®gOž®€L_¶Ì»FA­"l†Sú쨆ŠeÙeØ8õ4ÌÄ8„B~UEá¡Vwí:Ž;î8ˆñã‚ ˆ¦EPM,Z´ƒî Èã±­­ Û¶mƒ¦iÝDÇüBnذwÝuWŸÇܽ{7V¯^ºº:˜¦‰ 6l8 ¹Fç Še…Ž„`Μ9€Ä…˜o~é›øÞ·¿‡?þíqÕâ«rÂUš¦‰Ç¾ñ¾ÿì÷aÛ¶Và×Ñ6mX²åÝ Ã0`Û¶Ò*ߣŒDU:å¡$‰ß‹ó€w'žÆŒéû! ‹Œ\ë¡ ßÊGÏY!ÉíÄ üOñò ­Àú 2Yiäæ%· ²lR|>*//ˆì‡¬”d™TỀT¨÷S9Ú@Ýþý˜ñþeE ëAáQUU(ŠÇq*w­‚?¯4 †˜~h:&Ž= 8úôQ`é¤r©t¨àï³*Œ®X®>A™ÚþãœuÑœ’Fá„:çgºpàcñ‹eÀÌ“ H}±Ák¦Ò‹8f೘Ÿ· þhPøÖfðW½ÒBîºw9uiHÌ£fD†?_ËÉR௭ø£G^yÉÀrþ«- _¨£ï1÷˜ô*L»ç1Àç}‘gfÚ-‹ìž—D:)oy3Ì™ƒynt§ªb¿¢à»n]©›F×.â.¹çŒÃ÷¤kGeTÝã'ÝcÐrzõgÝe÷ÿ¨{-i—¸f†»œê‘/®’XKâ" ‘Qw?.cmÌÀ±4·ä¹ ìOõ=gèÉ!¥˜¶`¸ÚÇq`âñ¸0@ e¤úAHð ¦8)u®?I’¼P«åWZˆŠ•åOµ1Â(E[ðæ„ ce©_ÅæD¹ú9fWÛÆcËŸ†ª¨ÀéÓP—e!ËܩDzøßܹõøñSU9ÉC j$<.^¼°eËlذ¡×m·lÙ½º4oذ¡ÏãÜ{ò±Çó›Å‹j0ñöÖ­¸IQ|Ë H`Ôà 7$$R|/Íý®€[‹È¢¦ºû’÷¤;=ÿ?BÿcžÐÛ!|ïð÷°$¾߈}¾ð n;î9ë|ë‚oa2&#zgRLÂ5{®Á/çüu]uø·þ ¿Zþ+\ÿìõ˜]? 5åËû‹žúéS8µê¾üÞ—ñhãøÂg¿Û¶1åèi›:¸hüßÐt ’$A–eìø›¸¦îÜñã;°bÅ Üÿû½—–em@ôÁ(B¡͸qüØüÄfüɱ?W±Ó؉¿=ö·xù—¡Ø þqÆ?¢ýgíhooǓ˞Ä!鮞|5Î{.Ôƒ*–M_»Ù†dJxqÜ‹Øzz+–Ö-Åç:?2¾;é»húbêGÕãÔu§0áðäCOâ²Ë.ÃÂ'"¾,Ž‹Ï\Œºçêðð¬‡qiÃ¥˜1c.š~&ÿçd3 ,8oVl]­_ÚŠ~¸’wÞöø ¸e-¸OAk-Üedi&š;¾ñžDDŠ)Gb$YÉ¢Jv°™†»Î³ˆ e’ûüÛà»Gw*•'è]Kîôü‘+ ¹hÐ3n ")G;@ˆóÆW´b ¯J!–4M«lÃ$µM5ÆS>ÀÉ“'LŲ§—»8¥§ ½òõ ñþFY'e"ÞRÞƒô‡,&ž³] cA1Êe^£ù%ýE‡ÿê À’ûD,j2H¿VáwuBÈ !+?jAQ“=z}Ró…ïÕG^yF`›Bó#âðó^’ˆI!hIô F­¡®ÕcûÁƒxVUáØ¯(xìßÿ7ÿùŸçlOÐ+Ÿ< òž¤.Ýs ÆÊ[NDÝu-ê‘.Wœ“ºŒ:|Ñ•ÊE¯m¹õtÑÀ`–ÊÞðâ §%Í¡£P®Ÿ¾ôRŽIR^Ši †«ˆÅb$©"úA-QI}‚p8 Ã0rÚš;P*ÒÑXd¨sÏ…h …F†øœÜ_h6R‰QU5'}ÏH¢mÁ›& «L¡VEÖ# o*¡OðÖ[oá‘ç¾X@ô–½Hà*Ð\$úßúÓKŸÎ4M<ýðÓ¸äÏ/Áß|úo …`Yt]÷Ä=Y–¡é:Ïé„sÐñrE„B!ض UU½|ÁM~ p½®dY†ýÌ3ðìŽïムŽgD±,‹Édš¦õ $ø.‚>1Lyù ,ÿÞrà¶âöI$0M™L²,# ˆ eÜØq?~<à“O}²&½>ÅÌáG8ˎᬳNãÔO$| ŽÅe—?Xáo[N‚á]ÍÁh”#³mÛH$EÍ •|ðæ›Xfšˆ…B<öÛ^ç—½[(xÀ §'I’7qÌ0 ¨ªê…ØnnnFÖOÇ´,Ë›ÌÕÜÜŒL&ƒø Ó‘HŽãÀ²,¯‹Å¼p{…r Û¶,{¡m ¾šðØŒ©Ãd¬¯F À¢(ÎÙ&F4y—Þ=ôn ÏR"Ë2t]÷S¾ ;¹ÎS oŠÿ ø³[(‚SнžRŽäk†4!¶§æ@«–SªŠ$•Ÿš$%×.÷¬®BeüÐ% »*IRÏb4…‰(w¶ÂwìXeG2eågŸÅ›ò[\ð••AQI ƒ5 ˜1£«W—»¤Ae0`á±®®›7oƦM›°eË´¶¶bÓ¦MÞú††¬[·®"EGÀUYåÃ`gY†ÛkD"¼7ÿ³ßü ãCãFaYâñ8"‘ˆg "ÈxEšEÙ_ò;HóæÍÃ^ãçŒGèªgjC ‰.$Læ‹0dØëé¼=Ö`¹RØ -(¶È1@N™2Åß°•5€TŠ|8íCŒÆè¢¶'d2 *—7ëw£ýèXTn3A%AÎñÁ7U[ÝaL}ÅÁ?ÝŒ»Žý3= àó•á@t–*HTË/[–UЇ‘L&»mŸH$ ªjŸ¢$åÌ¥Õ’$Á¶m(Š‚D"H$‚d2 Ó4½‰[†aÀ0 ï½oÛ¶Q²,¤Ói$ o2Ôw¾ÿ}\q2B,‘B!˜¦‰––oR…&‹F£PÅóxsÇ C¯ë:÷z”e†á ~Š¢`îܹP†a ™L"‹!™L¢±±1§Nôî(t]òÃ÷å_{ºþT>ºäu?jÔ(d³YH’„p8ì­ÿÄ¿ˆßþèGžÑðCó9ŽãÇxôt/Am‰D`FŽ'µ§CÚVxBîø5?bNˆoFýô ·gPÇ ?vx ütü8å´mÂÝ>éž'â~§ãRXZïÀO)B…ò—ém?z#ü¸â”Ä Ô’DÇÜãÒ\bŠšIˆ ý{º¦üï6|q–þ'a†utKó‡yô?u‡(Vð^QŠžà>ù¶&ƒ·OÅe¢·Ð ´Y`º6žãyÙA7dðf´í™g }b+W†rå yé¬.º( Iº¨A53`á‘X·nÖ­[‡¶¶6´µµà¢ãP†V6,‹·”œ(ÈEGÓ4=C,Ë0MÓ{š=Mb#Ù5†mñbD︃ç@ŠFGF¾…>3} ÿrÀŒr—FP©‡Ð‹Î3.Ntà’5Mò¼*‚¡å¯ž¹ í_;…wLp’A1Œ;ŒìýØ œÞ7‘Ÿþ3f^\zQ¹K– ¥î¯yIJ,/AÓä-c¾!5‹ìCX–å‰j„a‡ÃˆÇãÐ4̓ý˲`‰4MóD>I’H$xÔÛö"@ ?)3-§Ô5²{þæ@ÙCåIðá–{ I,„»/Õ³%°ÂÝ?(_,péawŸXàáØA÷0«wÛ|Q8?âmCׄDY€‹®ª»-EÖ²à'ÛN¸ËH”Ý2R‚iò%aÚqcÀ‘Iˆ¤å‰¶·á{ÅÒ³†¯ßàå™ðfíŽ™ŽŽ‹#GŽgŸ]ÒóÒOR T.4W…;h!àé,‰PU€†ÉŠ|øáÈò÷Ë]d "´ðHTØ¿™vR}Ï ë'$’1ÇqD£QD"‘¢Â6 ¥0xã¡CˆÞqǰ»’aWñ‘Òé¶Ó`§Æ³F•»H‚ eyg'VC÷ÆEÌéH†bAeÒÕÕ…£N*wQUMJ?#h¿r:¦?¾t¸ù²r—ЇŒdÃì†axbU·kà†|à‰k$0Ò$*ZÇa†þ”B‘R^iÂHkiiñBÓÑ-Û¶ÁÃܹs‘L&¡išÞ²,$ ¤Ói˜¦ ˲¼Oò>¡¨ä ¨(ŠW/Uåy©ëëëy À'?ùIO ¬²Ž<)ƒf*k:öŒÌAc3ö¡cX™H$¼ë"I"‘Òé´'–’ð‹Å¼°©ä¹˜N§ †´Í7vÓ¹)œ?½›¢Ñ(êëë½0øäjš&Ǫª¸å–[ðøã—çA®0LÓ,èõ+jŠpœøQxCø"y´Yð“íRŒvò¤¹‹j,š!ø"‰V)äzÌÕÃãBÈ0L\(qp°¼Ôé †…¶§õÁ2Ú6H”ï ܾ{tðÜzP'Ç€/‚Ö΂練·éØð…<ɽn ºO(ŠpÁ(WôÉ»_$S ž„»äžÛ ƒûhðÃÚÒµ ¼´ŒDPº6A¯Ë|ïOþ3Óèž7x, kKÛFá½H„%ÏS¯Éó4 _ìL³ÿ0X‰šåÈÎÀܹå.†@ ¨0ºYÓѾ‹ðÌE£@8 ¼úê—Ë]\ b2ᱚ >˜eÈbî[–…p8ì…ÔÒ4-g€BžQ¥L¶^Lþ£‘ȹÏì{fN7ÎpV¹‹$¨@l|ðoú€¼ƒ(œŸ¦ip‡ÿÆM“‡ªËµ”pãIÿ®ë€)KÊÔ¯MÅŒ §â%@äwô‰7¡þ] ý]à ëe©»g½tñ8DDZÊ]Ê\új½ÇišÝ<)Ÿ¡iš^Ûð¶ŽúÒ”rRSDeÈ“‘<ò($)yú566zbW8ö¼I|£mÉ›0“ñó3“ÈF¹¯xy ½ÙþT0¿up¹ªªž§eYÐì?v¬Ç‰X}-ˆ¥i4MË™€ J×»¥¥²,çx–¦ÓéœúõF(òÞMA$IòŽC×Þe™LsçÎÅ5×\ƒ©S§ö»n#fU ðB“š–ÙsÞ< «©€‹A€/:…Á ÈôR$ PIºÇ1Á…©L`]~¨ÍBy‹Î_Éa6É“’ÐÀ…¸B)qòÔ{Ó‰)Ü+y0º6ä­HBrÐs“ÊA‚±îy,ç¶'1‘îsp9yY¦Q˜žÆ/T‡àõ!!9…îá_IÀ¤åä!K¡Tn {´&M„€ûwïÆ'ܰü•ÆPD胣®ó$²ãŸDýèM€£"vðsÀ…ÜhÛ@$Â+ΙSWî¢ CÍö*¼w ÀÞ)dg› o¼D”ç‘ ªK‡ìFÙ7i&Î8"Þª 4aÖ¤Y}¶Aã=y2_üë_C¢ Òdðv ó¿‡B<æ‘HðýT•÷Pd¹çŽiòõ5â±<”½ï(¬~Pçø³Æ‚ {Œ}Œÿ?%r Sï&|ÖðÇW Aû—ƒÂyÉ1(¤×" ‹$Šéºî $Ø‘÷!Àû:4‰Š<æ(guÐ#Îا-"‹y¢›WYF2YÈíÁ_ŸïeÒßè ù^é9y KHp2X!aKÓ44778„w!OL"ß{“ÎG^œ?ÿùÏËrM*¢=›ÁÈÇ`–må¾Gà/`¾ £ …J`}0÷ß@ºð ø¢fþþÍåƒí—„P™“óâk@‡ÞPÌã†0-„.&PXñÉOÕC”$DÒ2À¥›„ÞóSö„îI äzŽÅÅàkL®)doðú‘¸Ma`5àày÷†àW1å°Ý‘lþ£t†¶à§h%gY üq£G~éšAцé‘7Çü¾4Ì*À¿}éIœµ€ ( ŒÃWC]Â×K7ÝÓ‰Ó§O—»¸AÅP“£ `ú1× 6ÈŽ¶ahiiñr577#N‹ÙÒeDv#þ^?áz¼ÿ‡÷ ËÉ%¨Þ~ /ì½—í8ØûðÃ8¸w/ŽŒâa{5Mƒ¤i¼g¡(ü3ˆ$™LÏÇ”e.<Æb¾’l3 ƒ»W¹çÀGw6ƒJHT‘H„o«(\ø ¥ALœ8gŸ}6^ÄHJP6àGÇÃÉ“_ÜD,6¯â–ÉÞ(ƒ{Ë™¦‰L&“#<‘Wb _J!I)Ôg8†ªªÞªL&ãyÆ)ŠÓ4½Ü@®Ö— ašÏ°wL @Ø0 8ÿŸÞó UUsB¹7tÏEÁ¯ýërW¿" è~&møž1AK À­ƒÍàÀ|‹!àOŒ¡}ÔÀ±äÀvÔÕç“ÝýÈ‚HÖÊûŽ/åíGá)< µoùI2ºÓ%Ñe£õNà<”·ŒÂöQ^5À÷,ŠʬÀ÷¢ãй‚–S:_3°½Ü F”ïŒ")pL:g0´!5¨ôÄ$²ð¯§8&íCžQNÞ1éTú£k¼_Á{îÀ÷d#o$ÊÙ'ŽI÷0x ä _N \T7ÊñF!'öüªe\á1a$r'#˜ðS4wY0¤éP7’Ÿ=…,¥~E…¯HT t÷H¤ð©CA¡ëJP[Ù[´Íà!ÊH¡róÛ~…'@R¸ØþÎuÉo+ƒå¶ ,—Às†Æ Ô™ž3 -àÒ¿º¿¼÷—ƒ»¾UN©Ã­Ó#×à ‘tËç¾SjÐ`zÔzøM{°+ åËÊ;/éæÁ×¥¥×„?CUþ1¨I$Ñ“Ã`úPzĨÜ6üæ’¶7á?¢Aq5HÖQŠÚžö¡t¨R/û÷ÇJ"“¸jÂQÉbM.6B@8€mñ1XHùϹ~ïéw6œ¯”`hÌBë(7à@³«PþÉJ ¢ {.ÈR¼Âƒ¿'Ào{ƒDGj«I5‘ÀÕ"©óëg£ÿáriòC~€zôÔ_ ߌ,à·]5Þ 9Z¦±‘ þJÊ­BðÓuÒœšC"_þ£C"u)Òà·•^|Ç×àüz-375/Ô ˆ‚¿®è±¥ÇˆæPóH¡( ¿©¡ýé¼T/'ðI] %PÆàÜ‹`ZTšs0Ix¥®Í‹ vÝdøó‚éoáÖY”‰ÄPJ닼ãQêØ{lºg4ÏÀ€ÿj&Q7ÞRP|¥¦…ÊEõ§ÿƒ]>š§¤ö§²Q·*ø3§{S¹#£ÊÁ àÀn°ÑøÒ|¡ª&7»Q–¥³ÎZ†§Ÿ> øýŸU"ŒLjRx€s¼ŽçýßÇ÷û½/å "ï j5§b¥2vìXL^4¶mcîܹž@LŸñxÜóÈØDB2…Ó †Ñ|á’@òvÅbˆÇãˆÅb°mÛ3æóhÑþ$Ê²ì Žô©i$IB(‚iš^¸; ÉCB¤QØ:ÊyEuˆÅbH$9!ö$IòöûÕ¯~UîÛSv,NL@ú¢tÏ\Q-áÞûðaÄï¹gø '˽‹™²Ì…Æ^+èzT’ÈûÚ7âç oÈ|hnöÿW”Üò’¨ ðc\üÌ7cyVÀl6Wüklì~Žày".÷‰Ç £ó#-‹—ŸêFÂkPYjiñÅSYƒ×Í4s¯;¿|äÕJž«ð“€Q£ük]¨ŽÔ“ Ö1ÍBÃa¾aä^ãüëœwf=ü0¸^¼c90ïµcx)è\sÌ™P.¨Mw‰D w„Cïšì …¼¼Ó–ey¹éD´-Q(Ä'½WlÛöÞ™Õʾ}ûpî9çàrDP±Pb¾ØCâ— ßz”?ÝžDÅ`ó[(èA° ! cð[ŒçRþÔý4r­J@®‘¾Ð°$ÿ…º¡^¶§²–àõa=lÍÛ†ŒøA²¯k¬_Ýê™ÀñRðï9í—ÎÛŸ ‘“,·½ûé™ nô@¤sIȵ(jn #xý²E\‡(|Ë«Xfø6„È–Œï®ú.¨)'` ¥ MJ {¯r"rrYÊ#ØL£MðÛ-/pn¬+øv½U+ÿç7ìhnaIä/5Íîyƒ JO¨àmo!Õ¢'ïDÖ÷·)ÁŸÄßu#ײ|‚ÞåùФò„0ãÚLUóòË/—õür/Ëeø·¶·G†šûüßs¹¢^þù‚?3…_™º¿šúòð ®§y/©¼ã$ÀÝ8r…¸üî—í–1èèôæl lO¯]êžÙîzò¥®]P F·¦Ÿ=‰Œ”Ò•DU:Í) nÐÁÅRÒùI€¤¹f*ø\ºÔ•#÷þhÈ+†Àúàw9Pv"iîQ0ÀÕ™æÅ™ãä‡ìM¹Ç±*aÖm%±X¸¯Gêê1ó/¿€›Y‚æ²S§&wK-"Ô:5)<:.xûüýÛ? ý#‘ˆçm@ÂN,бÃHxî‡ÏÁ|é$R©”gx u½AB²Ö‹ …r=Ú–þ/ ßCŸt 2Óg¡ã‘§JÐs“ŽU(ßñ“Ÿü¤¤·¢R¹°}2>ýÞ§{Þ@Q¸–Hð™e¦ÙïübeƒÂB™&¦,«xåDQzßVUyèמ„ɾBÍ\ä£}e™ sù¢‰t¶íç ¢iþ1L³{ÈØÎ-À¨O˜|?lÒýò³ž,.A¡–ΟÒéÜP»ù×"X¾ž ëHçÉß>X§žò}š&óïY$ÂEK*go» ûZ[ñY<ûÝiÀžLvñÓ¶–´½ÜÅT0ä!Œ| ‘nµ¢éêdU,Aѧ¿û©%»Æ`ëZhÿàõ¤×o1žGt¬`ˆÍžžCÊûÌÿž¿ýpQ¨kR%ÝÛ’áv >ÿäçùož¬ò=ää êÅä)D!É ™Hstp ‰¼}h΃óÀÒe?`7ä:CC”Õ€ú( }šŸƒ¿ûé§÷âñÇÏpNÕ›‚¡¤&…G<øfûÌvÌü~ïOù‘È«@Ó´n9”•ÁªU«  $Ä •xD/”üãU‚8%fÙôÍÜç k´܅áp7>Ã0F{¡+ ‡šBXèÏóÙÓ¹‚Ë |]Ga=ž¿z3ö ?~µ'q±˜kÔ×6}Õà"ssswoGòž¬€ö¨ÒñœOÚ{ðþC‡4‘^Ñ‘r2Ci¡Pá0w»¢6È4MOp¤íIl$a2òz¨xªö0;’„ûfÌÀõ—]†ööör—FP¡˜¦‰B˜øÖÄáÏÛ&* ø¯»þ }÷" ˆÍqs©I@‹«Ìå‡× zÞPŠ?2‚À|ˆº‡4T`€u€Jj$â@ÿk@Î }ÏzjÆH,‹>„œ„bÁ²Ú7áu8 Ð!8Û]°ݬþdHo>²'(çZ ~(A µðèÄ…ö¯œ·Ýë²Þ &ï¡`ž¼¹Ìz°¿ ¨Ëã;@¢êÄe@ò%À^â{eR²†¸[Mò6¢g…Ò»’W'‰Ñó-.rêG€Èô@]ÏŒU~Þ?Y5Æe@,ã_¿`¤Þø}@ìf q&¿6o^5çØçã®lĘ¿z¡<Õ†î^””ʵÔЉ(€Å¹(Ïïžu6ꮹ&g¹ãp³Ëòå3æârS ¨8jRx4<ü³ëqa×á~í‹ÅL&½ÑhN©ã¯ ‚!Á°²}%®ùð _`<4¥mçäú#A@„K¨BfO)w JGµ‹C€Ò „¾·Ê^?ĤR*ÂááÕoC¡ ÀišÐ4 ±X¬Û$'êwÛ Bù{)ÿcU{-’%K–`æÌ™xè‡?,wQŠmÛ˜¾lºŸ”G Ô,'¾u‡S“ñÆm3`^3à{‹PX;òzÌ+Ëyß{jVzº¬Áw¯Ë'_½(}Åö,P§á)l ?`®F §Ò͇B¯’×)Ô‹ÙQ*ÔR¿ôA’”pJø@?°N=e«|$7cÌ-K0Í+]ãü4¶$t’ˆm¨&UýŽŒ«é`MñVJ¡?À˃ïûi ½ó^¨w‰Ç¹lô©ÑøøïÇ× öŽ ¥…r;VBº’b•%ˆ‰`Ïé·s–¥Rü]!ËÀ¿þë#=šýpnjš)©îÂ?Ç[_:Ö¯}EA"‘ðBŸ… :øø3Gqœ~ŠÂÅ›<‘¼‘UȲÀ÷JêÍ *“WÚ¡Ýÿgø§?ûÔÕ-ƒiöœÆt°P"‹yžŒô§i$I‚¢(°,kHf^‹‰À¼Ê]As²õ$þñÕáUvÿÇn|ÿ[SñÇ/Ü„ÿ_ÿ"oÆ Ãj ÷²Néc}1ô³CáX‡‹n¢æ”¢^Té9{§ˆw‚ ð<>y‰çH¬9/³G,H2rs[Z³Ìðדg­%ñâÆà{ÜÒ÷ÿï6$²¸`IácßY0 ?ú<0€”DÕN~êAuAÞÜÕHµ–»¦H»wCÌHinã¦DEùküøÇ‹Ê]J â]&2ÿè|œþùEíã8‰„'@„B!¤R©œPg…0ŒžŽWî«Pƒ?„`„B2â²l@™’ež#ÏL`š& Àã8b‚Aµòt¹ ¨Lxÿ0pŽÖ±c1qâDXŸ‹0–ey¹‰‰ÂápNžhUU‘Íf¡ªª—ßq(¼«>GãðåW_ÅþýûË] A#›2Þ¸ärC ”8ý©ÓøŸÒ/°ý ó¡Â IŠ<±J¡ÄÁ.H°®é˜”Kr8à{ E?½A ©:U¤í‡òrzê8@™Ø}~ÎQý2¢R~~Ò£cÇb≃+´ |PWAUÐã„A呦áaáñãW766â‚ ö”»”AÅQ“£`Êé)è:¿«¨}ZZZ ˲g¸SòòhEÜØ–46ra1‘Âaÿ{c#ß&ã³"¾ž–G"þòDÂ?&à©çÜ”’0 ~>€{d˜iY……ÍHÄßÞ*#Åqø1ißXÌÿNçt¿\T/úÜ>xþ £}wœ¾¿[–ÿêí8ü/XGÛæ‰„_~*£ðQôDðÙ}yáfв,O  \®‚*cj໘F(è‹Ó3€Ïkxýõ£˜8q"B!>a( pÍáp‘HÑhº®{ÞÔ$@\(¤¼ŠC‘?º¯IRµÀáí(è ¸¡ý|øg–»$ œ˜À¸gÆaìW¾ Ü›1Uî2U$Nb°blôÞ]Å~®¾ò^$oc²EÜî@¶àöA{ Õe°A'¤ÀgOâD°~2‚Û_x¸)‰FC%„ìn&üÄøÉG[Üÿ›ÝO<ä{³û=ânÓì~šî÷føÉKi}8pÌzwߘ»®À(ð˜¼tŒQî÷à::nÄýŸÊGëçö•÷½1P¶ˆ{úß Ô!X×ü$¦–û™ÈûŸ¶üd­F`J¼j¸ß)Q*­/Ú'ÿ¾õ¶ý@Öõ€0ST p6`Ö¤IÞ¢T “N§±nÝEå.¥@PqÔ\¨U €þC êG‹ó Ñ! !NÃq€–ÞÈ$¼,˾øF¢¦ñe±ïp†Ã¼3ªi\3 ¾¼¥…ïoY|ÛH„/7Mâ¶øzUåë¢Q¾.âqÞ§²D£ÜÝ[–y©œ_¦i|_:/uÞ%‰;|‘§i¼Ü’äÇ®&aTQ|Ò¶ù2]çß-‹—‰êFâ(•Ù²€dÒO©§ª|•˶ù¶$jºÎënYü;mKeQÕÁzµ ÍHÍŽó‡'o¡( À¢(Âã±Z¹½ý@Æ,à3ÀÞ¯NBCÃThCäÚ@žÓ¡P¡Pº®C’$„B!D£Ñ¡‘ ÁÑ«W‹ŽAvÖ×çD`àØ3Çp§q‘051°¢@ò¯¦{‚c¥„ t믘¦?¬¡IºšÆÇÏ4¾7 gÐÖt@»sº7¹×0øܲüɾ²ìÛFµÿ:X·•Â`Á`Îà‡)`útþ7c°t)pè0;0éFà‡¿ŽVÒ_Í™\0Ñ÷Ø{þA þNߎ¡ªþŸl dÛÐußÎ q›…mû6ÃàöˆP8|À àg?̽þDl²™Ü†ãÙNúõ­„BÜ®¡(¾Ý"ؽ²f‘0¿Fñ8ßæü€Ç³õËø=Ñ4¾]o]çËc1߯!˾DUÇÍóù›û÷>`P¿¨W¹=Êq€¶¸¸ïvÀù™{îk¾J–yÙ"þ)I¼¾”Ï\Ó€q+ÓSÊýT—¯ßL.²}5$z“r’JL bÉe5î·<Þ.¹§’‡-=*|ÏER“-øIK)ÿ(å‘¢2*à®Ù$œ‘×™2h?ÝýSÑ=^4ÅöÕõÏ7›ªàIV%àÈ‘#°c6–- ô°% ctÞ>Ãóáýü?~ŽõêzßÓ:::pl×1L:[·lÅš³×ä ‡:ð»S¿ÃÒç–¢³³3B3x¹làÌ»gÐ1¯¿»úw˜òû)X>f9 §;ºGê¼b Á¯¾ñ+¬þÅjÀ±Çaâ-1¦sŒ·Í}WÞ‡¯ýîk€ëO`Âî n(Ϋs^…¥ZXóà~{ã ha-g}×'º0ûÌlÔ=R‡kàÈkG°è­E8ýöiŒ»b>üÇx÷§ïbÖªY€Ÿ¬ú ®sî~ãn\{ñÿ‚uë4ì}z/ê~Q‡Y{gáÄÄ8>þ8Ž/<Žíc·ãÆ“7âåS/cö_ÏÆßùç-8ÄìÙ³qïÙ÷âÿðxÿý÷Ññ7`I†qãÆ¡«« §OŸÆŸúsçâÍÞıÇpáÕb̯Çà½WßÃX7Êϯ?÷k|îŸÃyÐ~w;~vÿÏðµ%_ÃE¦èþÏéÈ‘#94LÓµjYÁ+wq‚Š£"…ÇÕ«WcÆ hjjê¶nãÆØ²e :;;qýõ×cÆ hhh(úØç9þÆË÷\,„mÛÐu'NLĤIWà]Óä6òˆeÞFyÇŽRÅÅb¼ã(ŸÜ çèXhÚÅP@ž†Ñ¨/´©*ß7‘àŸqWÑ4¿ÓOß½ãË~G—$ðé:Nû³ôèTÀ_Nb$‰¦šÆëB⤦ñÏd’oOƒeÙ/»iòΰaPÌk¾Ž"¾Q§š¶…üóÑqH|¥þŸ×´øúB¶YÃÈé+ô‰eùŽ¡†®¹,÷¼¼€æåmðuÁïµÂp·“Þ:‰(¢¾²ÏM”bš&E#b# ee8Û#€4îúo`YÍCRvÛ¶ÑÒÒâM^hllD<÷ú´<_h9‡ž;wb§ª ï•*¦§¶`°íÀ+¯¼‚ßLø ÖKëË]E@ÐÃÙ'°þˆÍ.l?uÖYC_xŠ BƒyYæáhðkY@4š3N4v×ù0Ú› =¸Àâ ]ãðÕ°~Ý uudh¾öCàøqÄWü?„ý9àÌHçŒA,Vçãck_†>ñŸ ŸHünÄâ¾éÙ'þñ9HgÞ…¼d2ðÒØÎ…H f|x¤¸ä£˜þOýää…Xþ¢>ý|üãÀÁƒÀÿ~þ-ø xw Þg,><˜ùÁ(˜ÐÞL?q Ÿ|í]Ž,š9“Ũ×ÎF<î ƒòƯ |æûÞÿ¦ D¾vúå¿‚ñ÷Óa¼q%^n+í]Ç¡ÎÈ@ú“©ßz>äwÿˆ—:—:ðô=îdèåÁy³ ÖÃË`Ü;˜>š6Ýk[[^…ó6 ]Ù…ð?-‚2i¢Ñ…^©P°_z‘Èd?ꂾöm¨êlD£þÄê+º^À3XŠ xù$É?Ñ…èÄoÁ:y š›"âõ …€äú'¼ çÇ{ ûÌä|éKõH˜2xýçÇ€S0×ã5-G‹:¨¯Çb8`ÉÑC8wo;,YAó¾—¡\z-ß^‚dÒ7’kWí…ñwo#ö{®ëá#ÐÿŸ—œÎìnô÷ÞÞò0¬ã¾ ï$pÏ;ÊÝDy¸ØG1qCîŸì.7ÜOêÚ“¨XHÐCÞ2×<á8¤{×neÛ6 q›E7ñDSˆD"…Bˆ(P I4Mó¶7 ²-{Nº®CQ$ „B!$ HŽäMÄV%g?˲¼T†a ~m’$¡¥¥ªªæ¤©zëÄ[ˆœˆÀ¶mȲŒX"†¤šDËÓ-Èd2øzó×1::†m@‹khnnFFËà Í_@<G8†né›aD£Q~=$ Š¢`ßÂ}øÖÿƒ½Ã†¢(Ø»x/¾óïàkßý¢ë¢xuÓ«xîûÏá_ù”ß+°:-|çûßÁ7ûîýú½è|²þù.Zv¢çGú*¯û¬C³ð‰~Y–ÅÙÊÙøö+߯GnþÇAD@’$´~·>¹{.؃#oÁï¿ÃôeÓñÖž·0C™§Ÿ~S§NÅ#Ö#¸¯á><¸æA|ù_¾ŒW¿õ*>ÿÀçqû·c×§>DûŒvd—ea:&>lùŸþðÓ{t,Î\soþüM¼pÞ xúé§ñÅ|Ïûñ¿Å³Ùgѱ xxó‹oâñÇÇE_„ú+ê1õ©˜9s&àþßÜkº®ÁŒ30~áxÜýäÝX3z f\6S¦OÁ[‡ÞÂÉI'±3¶£5ùÈG°.»g8‹&V~¾ÂRØ ÈxäÈÌéaY–‘J‰Q¦@PVa$ 6þ|¶cÇŽnëî½÷^ÖØØÈyä¶cÇvóÍ7³›o¾¹ÏcÞ{ï½ÞñÀ{æö6öÐø‡úÜïýûîcá™±íãÆ±sÓuÆ’IÆô[ÞbcÒ¸£¹;e2ü/™Ì]®ëŒñÉüOUs×§Ó|ýE£þºTН’Jù…I¥ø_Ù,cšÆXúÇ{ ®÷ö£¿üsd³þ~é4¯W>é4߮€û·t›_L]ç×#•â·@–SÆ$‰_nYæ—>™äŸ’Ä?C!¾¢ð?]÷÷ …ø6tLúN·G’ørZOϪòïšÆX<îŸ+•ò¿ÓöT¶à¾Ám…ƒÊO·1™äÇÏdüÇŠ®Ãg?ûÍrߢ^Žv€1Æn½õVÆc:c¬iÏû,…¿pù¿WƘ®ë,³L¡ç^PdÆRc)uЇ‘ìØ±ƒÝ{ï½å.F¯ wŸ€ÐŸgL„±T*Å€( …^æT*ŲÙ, …BLÓ4–Éd˜ªª,N{ë%`*Àt]/wI*’B¿‰J£§¶`(úÏ_÷<»sÙ客@Pvè7Q© GŸ ØR-Æ.þ¿²ÄCvï;Ñx?H<Î[4hSÆXÞ0™d’ÄRw<ÅÒiÆRËîd¡³ž`©‹ocúÒm9cÀxÜ=ÔÌ7˜†8Ë<ù‹ÎÛĤ ÇY&c©˜å6wÏ£ëü/çƒËL†E£¡~&ã X³og™ïü´{YS)>¥ce³,›åc¨8­Ç‹FYú–bÙõþØ2›uÇÅõÓy„­ÿÉ£ Œ±ÿö(K&ý1³º¼ƒéWlgú%O°äª‡½óä°Ì~ë½S)ÆRw<Ř®³ìúo2müC,µfSn¿Í¸g>ñE>~F”ÍÙÜŤ@õé~¥ 2 q¦“Ñ ÿ~,™e§_ÄãCÆtš±Ìw~ÊÒu×0uÜv¦#ʲ+nòv¥K¦OÿS::Xp”™ùÓ¿ó ’IJoïþŒÈ²odˆÇY†q»cŒ¥žzŠWÆ~í³Œ¥cŠ[÷è£üz3Ue©‹oc!Õ?A:Í<G¦aË@æ—cìㇳïÞsOŸ¿r2\ãƒU«Vñ¾¢ÄK3Æ¢Ì7,Åÿ¤cÆXÖý>Ýút:ÍâÞ˜“ÉdX4eÉd’`étše³YÇY:f’$±h4êÙ,dYfÉd’I’Ä’É$Ó4¥R)–N§Y&“aŠ¢°T*ÅEañxœÅãq–J¥X&“a™L†I’ÄR©”7f‰F£,°!Ò~t¼L&ÃÒû¡,Ë9ëó¡í{¥R©^ûéC5~JçÛ<hšÆTUe’$õãˆDcü¹JóǪ©Å>A¡z§¿UVÌb¿8Ñ{O‘—1Æ’É$ Æ€ T(Ca3¬áñ‘GaóçÏ÷þ 5×^{mN…_ýu6þ|¶uëÖ^/<î]µ—Ý·ð>ƒtš²2>6åR0öü_|ƒÍ›ð3¦~â¸'þ°”+Xt»¢u¨½‰|ñ¸ßS•$_À …Ü“ sPç´Ðù¾o!¡“1_Ár;®ÁN§WÖ XZH§ŽŽzT5—EQº‹<¤¼)Jïu¡NzÎÈ*p=h xýà ÷»bb4ôYO1}Î#Œ©*K/¿%µÓu~™ãqÆ¢«ŸeÙ7±ôòÛ˜6ë)–\rwKHƒ.”òn¸Å¯{”é×=Ï’I¾>æ‚tjÙL³Ÿ©sö³øu²ìÎ×¼E:ÍXæG¿e™O|‘¥—߯¤ Ç™¶ôY·ùÁÛYjÍ&–½ï!–]ÿM>¸qµßl–±TÌb©5›XjÍ&–¾åŸXú–bÉÍǼ1 ¦1&M:Áô+¶³ô-ÿÄâ×=ÊRw<ÅŒ:cgŸý«D†³`,Wx\ýÂ;ì»Ò*þÌèÈêº.DÇj‡z‰ó¦«,*Yx,UŸ€PíãLøyFÙœ9°êSétšÁ¸âñ8K&“,›Í–f+è‘;—-c’{¤’…Ǿڂ¡èŸpœÝwÃ}宪@Pv*ÕÈ8œ}‚`_H~±eê… Üé´?f.0nÎ>¾=Gì‹á¿cþÄWªê:cú%O0ib—7!VÓüÃ’°Õ­¡PŽý \s˜Š=­¦¹ccÆ5œ`W<ö'Ã’9£GTÕ³'ß‹¦ñkúÝCŒ å<ÄTŠ1yú{Þã úuÏû¦‘ãÇY·éßd<ètý²Ák™w ª_Š ¼®:clÕ¡C5;>¸üòËÙëf,Ømq±'›B2™dº®{Œq. ±x<ÎTUeÙl֛Ĩë:S…%“ÉnǤe©Bƒ(c-‘Éd ^Ûa!ÉsÍÉ•::©Å>A¡z“Ié©;žbjà MFCa3¬˜P«MMMؼy3`íÚµÝÖïÞ½mmm9.Ô X´hvíڅ믿¾Ïs‹ôkG^ÃÎúüJªHŽ`<ÔÅçϬƘ1/ œùs¼zb)y€¯W³{üL¢·Øjy%)è?A‰(AdþñŠÉÿ”Lò¦ñ8 &«êË\UlÖ¿ …B¿Ñ1zŠJIlÛ¯c~]T•—µ7òËší)öl·Üdwòòs¿}_¨èP(²Œìï¹0@ÇoܹÅTÍçøé§À!@~-å‡Uåîã@bT<èï8m©ZCQ8]À'/è·ÃéÝíÖÃügà=x˜_Wé3ŸÈÉø®.ËÙWýD¶ eI (˜;—/J]ÿ tþ˜©@™ÙîÆ¯¥°¸z P>JÑx·e߇øâ±ßúÉ5ò°,K„YÊD)ÛÀñv(/ÿ¬ÓïãºëF 8¿£$IH§ÓH$0MI÷ÝÏ å,(-;ëë³*wQý¤·¶µOwP€IDAT`¨Ú½“ö¢c^G¹«*z T}{°Ø~¹p¸óD‚äR)oÜ@Ã[hþ+à8+¼€‘§ð(?‰äŽÁ´UÐ%_Uí–ñ¡;ycårEd/ö´T<Í]päN¦Ãàצה'”»FU¡ªüš÷'uµ,ó†·üÀ Cwd°Ô礑!Ôéiİ ,(t«^^^ïb niNt쇀Î3ØÌÞS?ø`è.ÔSж }f;¯J¨}îÒ#ŽãÀqÌ;º®# AQÄb1/\¨,ËÐ4 ‰DsçÎõR2hšÍH’„d2 ÇqzÌOùâšÛ]ä„çPŠŒh1öÖÁ@¹:‘û¸ ú¦äv—“{Oæô$ X¸°--_Ë u,r¨ᱡ¡¡×xËÜ »yÚ´iؽ{wQç ¤°+ŸY‰Woy•÷B ƒwäÀ–àG?z ÿçÿ¬„㼌·ß¾ 6¸bËlÉOB˜%PlÒÀ`Öq€TúK(4 Žmù‚hoÛ tYî{¡ªý:åðž>øAê€kú¸†ªÚ÷yúê€ÈrßÛÎÓc‰úb{)k&Cß¾îþå"IÀ’%?‡Ÿ½r(E;¸¹â³ãðcùKø»÷Ëqo` ¨bdð™5Ø JM)Û€¹hnÄïC(”òÒ/õ†aÞ ŸH$0 ¶m#N{ËCƒ} `å3Ï”»‚~Ò[[0$í€ <:úQ\ó™kÊ]Õþ““ÎìÞŸ¦¤ï„ivŸlÌ9GVý`ãgÛ\p B¹éJJOÇÍŸ0išþñ Jü<%œ/Ô÷r? ZoЬ/U†ê•ߤ¤öTÆüñIPõ 5)¿¼C•˜T­bê2Xc×p&¼JÑ'p ˜)/¼«¤ÑœàPˆçËüG›ò#ÒÜ]º…Ãm¿® =¡”s²×yž^Î:ªê77ÅbšüøóÏÆe}Üb²+Ÿ»Ú–캥Šk{#xŒž~©Ôr˽lÓ*€Ç*Xxî¶à‚ .Àßüêo€uƒ/+ ŽÑhÔ›”‡ø¹ÝÕÀ{‘Æ ªªæ,'$I9à‡ÊÓ§öe*Jtš‘F©ìAÔWçÎ<—#.ò. C‡üœ£ ;#<'ï¾û.6n܈sÿâ/¼kûÌv®L¥R9-Ûæƒ…/}é|Œ= ~x=2™å~cü³§Dpêâ` 6\¥zùð¤húsÙ²e ¶mÛ†ƒ–»(eáàÁƒX»v-G£P:f`ÂÒÜβ,„Ãao–¡ J‘!¦öÀÚµkÑÑÑùóç—»(%‡úÓ¦MÌ͛=cÎ9ÿ;TU…m+Eµ Àªªž ‰  AÓ4466ŠY„¢(°H`xìÞ½7nÄÁƒ» ÎkÇÃh1pÍ»×ôϘ‰øß-‹-‚ýЦ$•ÊíË77û¢ÀûüÉ °m~ YæcÛæ‘û‚¸ž¼|u#XŽD‚—¥7!.Ë­K¾ÑIJr—[Vw•€,ûŽã —Á㸑9¼sY·Ö¯‡móåtÝT57Ú‰iò £--þ²¼‰£Þ5•$^]ϯÑõ a±ˆÙØÈÏM“?ó‰øcAª›?㟟Ԩžî}KKî1€î÷vÔ¨ÜshZî$T*‡$ù“Tó1w®¿ž"Ðä×%pÿß?ë,¾öZÔ"?ÿùÏñø¹çbþ¥×ðw7=‹î3|äc1_ïWU~Yi>rþϬÏn=‹ýé/Ðý¬‚žüBcrú™õ:Ÿ õžqšKÑ³Í ÿÜÅÜór( 8cæ.o˜!h7ŸÄP$C=|’ãU:ÀóÜ{ï½xÿý÷QwâÄ_­ÊçÝwßÅù]ç£n]¿ÝFi Ë2$IBÄ}—ÅãqOPŒÇã^D¥ž„Ea{(?%+a3ä6Ã믿kÖ¬á“ÎŽ݉+gþ)¿K9}ú"47+°m[‚ÇÆÑÚÚ:h›aMçœsn¼ñFoj‚åûëöóJà¥B‘Bi2m{ûqD£ÇðôÓ¡\ã!mÔòs¨l Du ÉJÇš5k°fÍš‚! jÙ³gcóæÍh šÀŽEí·“e™ !I alÞ¼­­­hmm-wQJõ šššoˆúMÝx¨ªÚÍÜ–eÁ²,¨ªŠD"áy;ÆãqD£Q1+¹‚XùÌ3˜7of͘Qî¢T‹-ÂæÍ›±qãÆr¥,̘1¡KCˆY1èŠ+êgiraÇqº :A yÅ…BÝ…·ümâq_tPU_< BHOq{+À ö}¹Zõ•v¡˜è)}Eé德髜Árе*”†‚„ÚB×\Uù²Þ„Øükôüô…<éŒù I¡r$“þX²§rÐÄXrË?—®ûÇîI´Êfò·‹Fý±°¢`²eaÆO~‚ZäOÿôOñîŠ[ùM‹Ožäâqà¹DøcG·]Qø-tuš\P¬K¤eqá:¯ªIÉ=õ†èﳻ䪼Ràßb¡Ÿ»$ }¬Ÿž2Ñ@Q M| 굃{겇ï=–m€çùÅ?þ#þ}çNøÕ¯†ôZUçœsÖ-]¼Š¢HŽãÀ¶m†Ë}7ѤDEQº‰XB˜TÂf8Û åJÈÿðì³µd6¿›7kÖa$ ñÛŒH6lØ0$6êwïÞE‹å,Ëÿ¿7¤÷€:_€”×›hnæ}xÃÎ>ûfÍZ‡ÖV¥{^&Eér(ÈP’ÉÁ‡ÏFƒmì“@ר.L8BÁõ‘H²,l@0(ÛX¬õW€1ÁAT–»Eì‰P(I’pûét---eYÌ–­0–ƒög…ÅAÕ3˜v ó×ppgJ$ü\nñxaq©˜°û}õÝÛX äå ˆ6¸ 4ßjo±À½Š‚ûÛí-pãw~‰h¥ãî/å­Sûç_:/}¨‘›d½~t‚‘j‚ûÒòžð¼û¼v=’óºåœ¿—suCU{¼¯´>¿®ÝÊÑ׋ª˜÷PpUª\xL[`O&½w-;wvûib2iÎC2¯ˆ¼Z‹U/-‹{äUgPÐóïLÓŠÈ ã^#}Ï·(x~Å/ÇPœ?’ü‰óó‡ø„%â‚'p Ü…$m &¼9¡_á/Ãá0$IB&“mÛH$°m{Hs»£ª"ˆ€„všÛRLäqÁÈe("±W3ƒµéМ.|ðužÊJU¹vpÕUî»/#& ½P5Â#…€ÚµkWNcÑÚÚZtrX ÎZЂü¾ݧ¥8}ú4ÚÚÖA–m$ ÍÎ¥pAù¹J† 1sB ðŠvìñÀá±·bÍ󣺭sš¦=k‰ìØ’Ä›EñÃîÓD¬Á´B«PÔ³`ij*ж$ CÕ€3À2À²T;6Îsˆé ˲¼\Ž”L^–åœ¼Ž‚Êaâĉü¦Š\›#Š¡h&î™+ØÖu$!-epqÉO,¯wYPÊ–ÜmíÀ~ |PrÂî%ÜåÅ©L´<8gO„ÜmpaÑqGe¦²BrëïêNË÷ü’»?‰iv`Õ=pû`Y5øBh(P&+píîOe‘ûäã¸uÖà |FÞµ—Ýò™ðs£Ùy÷& ?íO(èÝ9†Î·>fàú#°Žžª “J \ù×N ”—îŸ8=NÞùiÛ|AèÍNAPé E[àŒƶþ?Ìxé%à‰'¼þ½aðyÀC>$×õþåÖT?ªR•Y’{Ø1^£}@ªÃEO·¢ÊnшaHÆEšøb±þò/ÿ€â:§ËP>aˆ's˜¦RÜÙÁqøs‰äR£Ÿ7EÀN}?š¿rqÎ9©Ù Sdp{"›õ#~§R@ì›]p:FCiÛæsšb1?š8ÙBƒçó'GôœÔZ{4”v€úXGð ¦â¢é!‘ðívÿñoâ _ÈŠIÇA/Tðp—ï-[¶`åÊ•¨««Ã¦M›PWW‡•+Wµ¿¯Oà¨d d¼O¥€ŽŽv|øaÍÍÍp§ûÌYØT;@0$ ¶ >½ãmý»«º-Åb0 à µJùGh¶!À”¢(˜ÊG’x;bÛ|y:íGQ’$¾Ÿ¦ùƒ²mÒ€&Òë:Ÿá8þ9hÎÀ+.™äç ˜Ñ(ß7‘ð£ÄS'%“ØBî÷ §‰i$ø‘øØ6\q,Š\ÑÉF®l†ìÀùá®Ë¶!1Ιÿ¤“XGâ yA¯H¢È2H"p-”¼²“i£ç´Ê$ÖѵÓà‹$†Ñµ4ÜåÑÀúˆûGu¹e”ûï‰k’{¼`ÖEÕ=6µàt_¢òÑu%±±1°@¾ G÷…®]P¤ëÚX¦ºûÓs’/¸Jÿ%øBe¢@ÝóÏ­ä•“®=[/ KòÑs5ÕË`Û³¸Ú9Î;ï² #â÷£‡eÎÊ@¢ªô¹B!á¼”krfžs´ „ ¦-8xÛAÌjšå.ƒ¶ 7ýÚ‹ðÙ»`Ç>ø”¦3Dc¾€§˜1¨î[I€+®€ò÷+¼ÔÃxðAÈw" ŽÛâ+Ù”÷¬F£àƒÿ¯˜ð¬Ž…ò77fà½ÈIÌøÀ¿9ˆÃÙ(zŽã;ÌË_[k×xHnYìWÂ0®öŸ]Ó„Ùƒ –û+–ïüsȱ°_–¼|Á~Ô×ç&Ëí)spFƒ‚ŒAòÛÄüËŠ’ÛÖ "Áëü±RlmÀwqÏŸ!‘žü\ßtYöHùõ!Npöz°¬¶íih¿ü™íd 8†möׄ<çUÿ\²œkh±í܈~ú§Ê°¡´€j¦qâ܉^êsÊ7ü ó ªuå®®@PÑT•ð¸aÃÜzë­X½z5êêêÐÖÖ† 6 ®®øº”Váåœ^(5² D"?€msoG¹Ö¦†Œ ¢è>Œ ÛP—w†³lÙúœu‘H¶m#•Êx}° (¨iü„DE)<!™äýbtÒ@„RåGÐÊ·=ÐLHë¤Ó~Š µbÛ@&“ëñH‚ õ_“I_$ñ”ò‘P$êãàDýkŠ6—Nó>/õ™Ip ‡}q2â}g I8 Œ¼>< ¯±˜‰,òÏA×*‘pó±¸"Ps3?V$’kDˆFùñ¨ÞTOº.$‡Ã|[ª£¦ñm£Qœ¼W´?ŸŽMãÐ5üë@Ð$‘ðg•ÒðÏI3bƒç§2ò÷Rî³Aç¥ñ›,#gæ¥¦ç„ g4Yž®íÒ¥UÕèÆPô J;pzÌiÀo~3ãÇ÷±ãÀ0 ¨ªŠææfè…zAe!bMXÛ¼µgλi ä¯<\}ÇÞ¦'…Fµ‡õ½µ4ùÞ”…öï-Ë"‰R½•½§ã“Çao¨}¬ ®Ï?RDÝBŽü®£çp®ÁëZ¨¡^ö—Ðû}é뺷%xŒbÞ>½]»üs¯Ý³§ˆ#V&ƒi º&ðÔ Ÿ|áDŽa˜&è‰9+ƒ£ÜæërdÎÊǠDZÿ“$ÏÝÙq|ìcu˜wúcX˜ø ºº>@êGw@þÒ'!ÛéÜ>¦j†CU¨_ùrï}¾&P>áÞpóé\$LÒu¤A‡¦ùÞœ$¤QŒ}êd;Ž¿?à{a’PL«tNMóËNËèªê{\¯?Eº’åÜI‘Á0¸$RYiûàršIb#]W®óŸDþ$Ètº{ÓôÅUº64(£ý'L˜Œ7Þ˜Ñÿ´Ä gŸÀ §¶`avŠ¥¯ßw£›cI×uD£QáíX ˆ|½#‚BmÁ`ÛS;w"ñïÿŽ$Dßq$3ØQVÃÑ'xcÆ HàÈ|F9†$“Eí.èƒr å@ˆÕÃÏp´Óþðð„µ´´ ³SÆ]sþ€KÙ|´´| ê„ßò—C¡iU 9#Ò¸•"'åÛ#¬€XGãl`<Ô…¾-ƒ&nè:à8uÞxW Õ{Ñ›ø1¦À™6Å»”i6¿ 4!8›ÛžÇqÇÃãëG~8ÑP0̃ñ<•qâÿ 0Ã~½b?:À—a~ƒ/Óu@2Ûù®oSˆýðï9Š„Xš\n_ι^¡. ²Þ·)˜æãæï˜àÎP\§BÇq'_c×BnCùô ˜îøŸ;Ǥë–óè`ª+nñ0¹-e9$i9¤Ù€½ ±0à$rï—sñr˜Ör`  ¬Œ3K`$ü Ö›yÕtDK¸â†å€Áí sæüÏâ]†ÓNdÞOšðÖ‘ÜHhЬY3²<§Ü—A ¨hF16òã†nܸMMMøYS;€ÿöõ¹˜væŒ÷«¯÷Å…ÆÆF躞BM i¬]»›7o.w1ÊRïÏoÞŒuíâ§~W°íÞºD¸çž§qà ã¡iêˆ067禃)¥FbYÜÃÒÞ•úšŽÅPêà÷W&OAÓìt+ŠzBnsqÆb¾Gj~D”bëžNû"k¡òëzGŽìD<^[ï;ê455a€tc#Î4‡ññè:Äã½ç°,Ë Ã^lXA…@®ÅB(îFð7QK¬]»§>ýiXË–áå@ V©ÅñAkk+þówGðþ Ç#{}0‘¶YP‹´¶¶¢µµ6l(wQJÊÆñü#fÍš•3aÍ4Mìß?O=un~e)>ÑÕ……o¼‘ëÒ'¨*r&ì®Ê6‚|z4I”5 n èoôÔZìä×Û0€> ˆÛd ƒ_ßTÊDssŒœgG Èg(ú՜ʡßX®×ýÏ=÷biiñgâÔ××CÓ4‘V áÌ~ã RK®õþO$¸÷ØÇ?~.t]1¢#à‡ä¤Pž¥>7…IÍOÉP*‚ÞŽýEÓxçr )u$‰aLÓïÚßskš¾¶¿Ð}…z.ÿªU‡qñÅûð†bYxãÍÌ™³Å QÛ‘H–e ѱ N­\~³b®ùÏÿüAÕ2§í=|ó®«ð—/¾ÀO j‹ƒ·ÝÖ-J†aøÑÞÄäÉ“±sÔ(È4¨Ë7#¨rn[¾;ç€ì”WT×G\Kåí~í¼×ø©n4 Pñ¸è,}QSÂ#>€9øö’%üÜgd”UUš¦Ay€‚‹`Ìñ186în‡‡yÈŠÎÎoŒ¸0Ë 4?ç{©ˆFùµ-G<Ê“iYÝó®7”{Á²&øR~Ëdr`ybÈs/ÉÍ/ð±ß6j<>øà#½n‰D ëº­Z͈Q· '>ö1|tçÎrC ”‘Æ3ÖÂþÙ³½œìâU/,ËB(ÂŒWB–ï<û,Æ¿ô_™ŽUP¥˜æˆË/I¾í£±ÑOé"j'ðÿe7`éÒç< ÷(5aÛöàO Œp*2Çãp2ëõC°àÇ$'zÓ4…§£@P8FŸ£cðcé‡Bl{ä¥)ïa8\žI™åŒZM¹Ë1‘‘rGæÜù¹>ûÏ?á'¹tÇ&ÌÒpâÄD¼ûîÒ^··,KLNªVš›oY0âÑ—-ƒ2sæ°›<îƒ9“i2 û¤Ü\¾…¶¡\ÀÁÌùvÁž‡~.TÊÁüŸ¼êóÏCï=š®(üxŽÃß‹Æ<˜“šòÓ²žêcÛ¹ç$‡ª Õ+˜¹§ëFÞý¹n´•îmOÇ(tžüò©ªo ¤<Óô1ûÏGõüýòï5Aç ïÔ©ÉÅ=Ü#Œ ]]8¿« £} ÍÍü9YWA"‘€m+°,Ÿÿàî8^ûׯ`éÒ‹¬è¶M"‘ðDÇ‘æ-Ppâ! lAð£õê:o߃¤R~ˆmÒ¸ó£ d2Ü]’rA⥠óD£ÝúKèÝžE8¸_¡cP(ôÞΜ¼C³»óÏ£(…ÏÒÇß/(²‘1,õ#½Õ'xN‚솉„m#‘\q6õó^S}HÌ n‹ù¹‘››sûÁëM×0ãç¡tIâ߃ç!q5âÂT•ÿ57ûÏ@<Î×Q(jéô¬e2|ûà0V×}±[–ù_"ዯ²ìŸ7øì¾þúŸ£™ñÆ82j~¹û£P”òô۹ض Y–aY$I‚,ËÞ²Þ <Üß4MȲ I’à8WÅiÆbªW¡ÉqtÝlÛöÖ;ŽÛ¶¡(Š÷išæˆ».Åq€o}ë~ò“ïâ‰'Î*KÊA‰ Ž×#õû&bø:pR{'Þ5‡óÉYÔ‡2 CDBŠ ¦„Gk"pݨ—ø» ¢Ñj€CÀôΗ1ëÐ!„ù¢œðdYGF¹T`¬ùÉr—¦8Žã‰lôiÛ¶',I’I’`Û6TUE"‘@(B$A4E,ƒ®ëˆD"…B9âµ±X ©T ‘HÉdsçÎE*•Bss3âñ8 ÃÈ9¯¢(0 ñxÍÍÍÞ¶ÁO:~,ó¶Ëf³¨¯¯÷¶Óu='¯6};NÃqœœã§Ói466"•J¡¥¥º®{õ&‰DŽ ©( ‰t]GKK Òé4Âá0¢Ñh×F–e˜¦é_Ó4ïºÒgss34MëVP(„p8ŒT*…p8Œd2é•9‹AÓ4†á‰¯$žZ–UU‰D¼ú2Ær®[<G"‘€ªª°ÜtݨŒÉdÒ«gcc#Òé´wí®¿þzüÕ_ýU¹í²AbÍ/ù¦L‰BU¿[î" †U‘qHMÓŸÜ4uÕ’"ïÜýln¸¡³fÍò®+Ÿ$6òž`¨©)áÑ,ݳ ¦¢x9¯øÌO‰D², o`„c(vâ¹1˽Yñ¼£`ä I¾×B­ÍR•end¬µz÷ ÚÛwâƒ>…S§–tÛÆq¤Ói1¼Ú÷OÐdXwœ\ï¶b„Ѿ †IâQ „ «ôš4 ú''–%Bˆã80 Ã5MóD/Ÿ × ˜F]×=¡¨¥¥Å¬¢Ñ(‰„'¾W7ýOááEñ-MÓ (JŽçyªª EQF!Ë2R©TUE*•‚,ËÞä,ª O’$¤R)(Šâ}f³Y8ŽƒÆÆFÄãqÄãqo=0W g½¨÷‚·x<îõÕò÷Ϻ³ B¡Pއrs©ª Çq¼ë ( ’É$dYöΓmHt”eªªzâ®$IÐuÝۇ꼖ÁkD×$x EñŽAùÞšôºn™LÆ+W¾]+êÎ> ²å_+ú4 /QÃ$áŸßúV+TõžrG0ÜŒÐÎõ%DŸbpX]€2êö`9VÌ›ˆàLäM/ô ojJx€ìî¡jÇñfí‰A p< Éqàœ£"þu§¬¢Â÷ª éÖÜ\>ÏÃr!Ë"]_8Ðyûÿë¸à‚Ë n“H$`š¦gØT)¢'èx<Žÿ÷F$•ïN¢Ao}ò< nGÞ2ýO^>ô?Ãó…ò¸ zTAÞTt 2æÃûɲìy™¦‰P(Ô-"Õ‘¼tè“ö%†ú#c>íK^=t ‹ÅrÆzTî|o° w••ÎKÞCT¯ P”ÿô îC^R´-yGñ}n™ýëI÷€îÕ/_òp*ä•EV=í¼µÈo¼á}Êy*ô["!в,oÝWò&¤ûJëI( …B9‚ÞùâõUâùaÐo€D(úìíþÓ:Ú7ÿ³7 m+IÒétÎ9ûc‡ îGƒ¡P¨×Ibùõ+t¾ü²Ò5ÏvQè<ù×±˜ý¹®$lö´oþòÞîg_:S§Ní³ì#•£GÇ"‘ž|²«Vµ “É&AUBÑ9‚!çcñ%7á>ƒóÏ÷íù“AAÏÔŒðxt,¯j;{ªªz¡’ÑQ ¨%Î »ã_÷-÷:d‰D¢×Aº :¡” æÈLß)”}Oà•׊ѣÿ¢à LQ^u$ úx‚PU ápá°œƒ%?¯‰h$¸E…ò…*Â(ly6577#“Éx“'[ZZF=a#ß;*šÂìCF£Ñn""ÕA×u/#—BÆb1/aP 4M3§^Ñ@œOÓ4sB>R}é“ö•$É ÃhY,ËòŽE"b~Yi_UU‹Å<Á‘®MP4 Þ£ HHÇ!3xO‚¡yé;‰‘$‚뼞tìà>D¾ñ*ÿ|A¹/CW0AÂcOЬýßýîwCÿC¨.¾ø6ÄbÈôZ$oÅÆÆFD£ÑnaOÉËŽúäEø¢!¥€©†Jè¦É£¢¯& þð‡ie`ñⓞG¯@PPÞh²w †ý!0ùéSt¨*“O}Ma?Šcc#ßdãÆ·r%îX´æY—ã™È¿á{ß[‚lˆD"°mÉd²ÜÅJÆÚµk±yóær£,õþ¯ÿ³³fî4¯wC©ÙžQJÌhÔ­­­hmmņ Ê]”’²qãF455ágç.{Éhï|ð6|\Ž>eÛ6æÎ‹d2) Z‚ ý&šššÊ]”’²víZ\rÉfÆÀ…GÃ0r¼ÿHÄ"á+£¥¥ñxápØíÈë,{Þg´?õEòE«B“$ƒmÁ}‚P‹ãƒÖÖV$“I¼üòÕ8sf5Š p`Û¶÷»knnö„x¹ÉSQ0¼PŽK1‰|è¨åñÁoûE̘1ŽÓY–s&ÍÕ„msÑÑqnµûùõà»ÕÛ7Oó"hQß_´‚Z`(ú5ãñRÇ)üðôxŒ~}¾—¿ú 6°ëgpÎ?¿ ²<‰„)ŒA bîÀäQËðÚ‘#øÕ¯º°té8oå~¦\9`d’H–:èÑô\“$É ‰Ì«EžL’$!›Íz9Ï?"}ö6ù±¯°y´|¤zE ¥à /Ä¿¸º(ã,y:Gr2™D<‡ªªžø%~¥ƒ£Sfÿ©÷v¬¯¯ †xoÎÀƒXrt4 Cx%5ˆ3iºN¾ W|^ÐAíbÛ6FÃ0 it]ÏÁÈã½÷¦¹’ýeŽã ‰@’$(ŠUUEh5 hiiišƒ?@ ¨j,çdÞÂÛ8ßúÖ,~~g@P<5ãñ8É>…Y¿…ß¾ø¼$»ñx\ÌTjˆ³Þkþ÷cxzôõP”I°, ñx\Aqt,ïþ\øÜa̸ò,àƒ Ó4…Ð Ô ”Û5NC–eÑ7j„lvzNÈeÊåJyœDZ vˆF£âý/à9‚ñöIÌò$é"o¹èý£f„Ç í/£íÃEøøÇÿà Äb±rI ”˜©ï¼ƒÿ{ï—ñ?çÜà[0 ŽãˆP«AñòäÉ€ßu.Á¿ÞvÜ´ ÂÛQ ¨M ÃÀ!: µÅ…F2éÿßÒÒY–E¸E ÆØ·oþáþAäw°'M™Óg㼆6\x ‡ÃPUUŒ‚~P3Âã gcvÛ‹¸íŽ©DN7 ™|êbБžþ)<‡ƒ·,Ôg½÷æþºï _üâr874:Ž# A ‰DF…·³@PƒLœx ¹‹ÅFET$ ¹à‚ „7“@ 8g…éûfâ꥿p5LÓD&“ý ŸÔLŽÇ÷ŽÁ/ßû V¬¸‰D‘HDˆAqîÑ£xnÔ§Q7æ LÓD8.w‘A°&MÂÙ¾…%Ÿøž»Ä®ëH]AM‹ÅL&ÅD$ Æ¡pË’$ o yøá‡Ë]@P!Xþko=&Ÿ{5 ‘H ‘H”»XAÕQ3Âã¥É½¸èßÛ¼ñº®—»H Ä8ûl¼À.ǧÕi³I ¨aÎz›ÁÎ\Œ)SnÀÃ,¶´´C£@PcضX,&f/ 5Žã8ˆD"^ŽW@P{\pÁb, €c6pÃ3aš&4M:‚@0ªNxܸq#.¿ür,X°ëׯG[[[Qû½Ÿ¼ 3ùÆE1«Y ¨^Úœ:5€ñsv ‘A  ´-ø“'¶ã]c®¾ú@’$áí(T)mÀ4M¤R)ÑFƒi ,ËžŽÁa mÁªU«„P ! ªOà~~ûÁEM‡a0MSô‚PUÂãÆ±eËlذ›7oF[[Ö¯__Ô¾gCžȲ,f)UÌ`ÚñoÏ„àì³G‹øìA•3˜¶àÌ3¢Î<ŽÏ}n¹~]¡O jL;ð°I¶m—»` ¦-èêêB"‘¹Ý‚À`û úl;`¶·C²´º ¶mCUUÑGHU Û¶mÚ5k°fÍ455áÀîÝ»±mÛ¶>÷]†,fžó466ŠÜŽA3˜vàœ;qǬ½‡Ã°,«ˆ³ ‚Je0mÁǯÆÅãÁ4Ma—‚*e0í¤ÓiáÝ ŒÓ?~², O`0Ø~@ ¨~Ûüî8¦„潆D"Ã0Ê]% j©áq÷îÝhkkCSS“·¬¡¡‹-®]»úÜÿ‚{ŸÂUßš„d2Y•^N7nDkkk¹‹1(Z[[±qãÆrcЬ]»¶ÜE¨YÛ¼ó‘w°ë¾]H¥RUkh ÏŸhσe°m[Çù×=ày:U[¿`¤<#¡= u¨VÛÔ"#¥íè/µø;­¥{=ضàì³Ï®9Oñ›¨jé^‹~Aÿ©¥çƒ ¶ˆP+÷z°íÀîÝ»±mþ<\b¾Ž§.ýE©º”,#á^„ßéHèwìÙ³Ï=÷Ü Ž1¶Ü•(–ŽŽÈi<`Ú´iؽ{w¯û=z?ýéOá8~øáª|xÛÛÛ±gÏžrcPìÙ³íííUyýƒtttTmÞyçï¯L;@õ¿õÖ[¡ë:NžVûóGŒ„ö¬šëpüøq8p/¾øb·ßR50Ø>AGG|ðALž<³gÏ.wuJÂHi;úK5ÿNJîõÁƒñþûï{¿©jc°mÁ‹/¾ˆ|sæÌÁ¤I“Ê]’ ~µCîu­¶nÝŠ={öà£ýh¹«R2j±- ¶ˆPì½®u›aý˜18i…ó^ÿgœ™y£FªºßÈHø]„ßiµ÷;<ˆçž{§NÔqªFx —_~9žþy|ô£­Ú^WW‡·ß~GŽ)wQÌ©S§PWWWµ÷€˜?~ÕÖ¡½½ííí8ÿüóË]”²pþùçã†n€ã8U{«ùù#D{V~ž{î9œ9sfD̆ë/—_~9víÚ…+¯¼/½ôR¹‹3 ªýù#FB{VÍu8zô(öîÝ‹S§NañâÅå.NÉQ¿üå/QWW‡K.¹¤ÜÅ) #¥íè/Õü;(ý¹×/¿ü2:;;k2×ñâÅ‹ÑÙÙ‰_þò—X¸p!¦NZî"•ñ›¨ús¯k}|°yófìÛ·¯ªÇ¨ý¥Û‚‘`‹ÅÞëZ·Jsæàü/}ã>:—]v=8€”»Xýb$ü®GÂï´Úû/¿ü2Þ}÷]Ü|ó̓:NMŸùÌgð™Ï|¦ÜÅefÓ¦Må.‚@ (3¢O àßøF¹‹ ÊL]]žxâ‰rC ”1>ðÓŸþ´ÜEFUC¡kô¢E‹Ê],@PBD; ÑÑŽh  Ú@ Ú R¨á‘â3ç'ƒmmmECCC¹‹'J€h Ú@ Ú@Àm@ D[ D; TU#<Àš5k°eËtvvàaëêê°råÊrM ”Ñ@´@´€#Ú@ˆ¶@ ˆv@ ¨$F1ÆX¹ Q,¸õÖ[ÑÙÙ‰ºº:´µµaÆ X³fM¹‹&J„h Ú@ Ú@Àm@ D[ D; TU%<­­­€Å‹£®®®ÜÅe@´m@ í€@ àˆ¶@ ¢-¢*ª@ @ @ AeQU9@ @ @ Ae"„G@ @ @ @0h„ð(@ @ @ @ @ @ Á ÂcéììÄÝwßË/¿ ,€ªªØ¶m[·í6nÜèm³~ýz´µµõk})ësùå—£µµµßu(w=¶mÛUUuÊ]AõRL[PMÏ_OmA5Ôa(Ú‚r×AP UŸ ØmJQŸjí}·ÕPÁȤ”}†J|†‡»m©´:—ª-ª´z z§”}†J}6ÓTÛo¢T¶ŠJª³ 8JiS¬ÄçCô jç^7ÕTçÕ«WWå{$Ø=;;;±~ýz,X° ,ÀêÕ«±{÷î~—±Rž·’Øl˜ lÜzë­¬±±‘mݺ•íØ±ƒÝ{ï½lþüùlëÖ­Þ6÷Þ{/klld<òÛ±c»ùæ›ÙÍ7ß\ôúR×gþüùlÇŽ9Ë‹)c9ë±uëV6þ|–H$ØŽ;Ø]wÝÅæÏŸÏ^ýõª©ƒ ºé«-¨¶ç¯P[P uж ÜuT/CÑ'(v›RÕ§ûŒõÝTC#—Rõ*õζ¥Òê\ª¶¨Òê-è›Rõ*ùÙh[Pm¿‰RÙ**©Î‚â)•M±RŸÑ'z[E¥Õ»TS‰DÕŽ±G‚ݓηcǶcÇöÕ¯~•566²ŽŽŽ¢ËXî:äß“á~ž„ðX&:::ºuãñW¿úUïÿk¯½–Ý{ï½Þÿ¯¿þzÎ~}­/‰D‚Ý|óÍØbÊXÎzÜ|óÍ9çfŒ±¯~õ«ì‘G©š:ª—bÚ‚jzþzj ª¡CÑ”»‚êd¨úÅn3ÜTsŸ€±¾Û‚j¨ƒ`dRÊ>C%>ÃÃݶTZKÕUZ½½SÊ>C¥>ƒi ªí7Q*[E%ÕYP¥´)Vâó!úÃc«¨´z—‚j¨ó#<ÂæÏŸïýUÛ{$Ø=wíÚÅæÏŸÏvíÚÕk½ª¥m)•ÍF„Z-mmmhjj¢E‹r–/^¼€Ý»w{Û X´hvíÚÕçúR±{÷n$ |ûÛß.¸®¯2–³mmmؽ{wιàÀš5kª¢‚ꦯ¶ šž¿žÚ‚j¨ÃP´它 zŠ>A±Û 7ÕÜ'ún ª¡‚‘K©ú •ø wÛRiu.U[TiõôM©ú •úl ¦-¨¶ßD©l•TgAñ”ʦX‰Ï‡èp†ÚVQiõ.ÕR禦&lÞ¼›7oPÊ]Ï‘`÷¬««ÃºuëºÕ!Hµ´-¥´ÙŒ-Y­9,Z´¨[ƒÑÙÙ‰­[·z/ŽŽŽèör™6mZÎK§§õ¥ ³³wÝu4M+øãë«Ån3\PüᆆÜ}÷ÝhkkCCCÖ¬YãÕ§Òë ¨núj ªåùë­-¨†: E[P m² :Š>A±Û 'ÕÞ'ún ª¡‚‘K©ú •ö —¢m©´wx©Ú¢J»×‚¾)UŸ¡Ò~TÏÁ´ÅÔ©’~¥²UTâ½ôM©lŠ•ô› :Š>ÁðØ**í^—‚j©sCC\‡r×s$Ø=°aÃ\xëèèÀ–-[°hÑ"¯LÕж”Úf#<+„mÛ¶aõêÕhhh€¦iå.NÑ$ L›6 ëÖ­+wQÅêÕ«QWW‡E‹¡­­ ·ÞzkE½dµƒh Ê‹h •€hÊh Õ@µ¶ýe$µ-ýE´E‚¾¨•v¨Ý¶@´‚b¨•¶ VÛ@´‚‘Cµ·W7nÄÚµk±mÛ6¬\¹uuuå.RÑ”º e¦­­ wß}7Z[[±nÝ:hšV5lkk+¶lÙ‚Ç{¬ÜE4š¦åüèTUÅ–-[pÏ=÷”»h‚A´•h åD´•COmÁõ×__î¢ UÝVô—‘Ö¶ôÑ z¢–Ú ¶Û1>ôF-µµÜ¢-T?#¥½"ïÍÖÖV¬]»uuuž§y%SŽ6Tx<–‘Ý»w{3VLÓĆ  þà Í` ºÃöµ~¸hmmÅ´iÓp÷ÝwcíÚµX»v-_ùïOÊYÝˆë¯¿Þ gP-uT/Å´•üüÛTrˆ¡h Ê]Au2T}‚b·jFRŸè»-¨†:F&¥ì3TÂ3\ê¶¥ê¤TmQ¥Õ[Ð;¥ì3Tʳ1”mAµý&Je«¨¤: Š£”6ÅJx>DŸ 4¶ŠJ«w) u®ô{[ívOʵ¤©© MMMhmmíW+Ýv[l‹ÙFedýúõX¹r%xà‚±š)Vn~bÎÖÖV444ô¹~¸Y³f î¹ç¬[·Îû€•+Wzß‹)c9ë±xñâ‚ç¾¼+½‚ê§·¶ ž¿¾Ú‚j¨ÃP´它 ºlŸ Øm†‹‘Ð'ún ª¡‚‘M)ú •ô —ªm©¤:¥k‹*­Þ‚â(EŸ¡Òž¡h ªí7Q*[E%ÕYÐ?JaS¬¤çCô †×VQiõ.#¡ÎÕro«Ýî¹mÛ6Üzë­½nSémK9l6Bx,­­­hkkó”ñà_P1^³f ¶lÙ‚ÎÎNÀ¦M›PWW‡•+Wµ~8¡Mð@NbÕbËX®zÔÕÕ¡©© 7nôÎÝÚÚŠmÛ¶å„0ªä:ª›bÚ‚JþŠi *½CÕˆv@0†ªOPì6ÃÁHèŵ•^ÁÈ¥”}†Jy†KÙ¶TJÒ¶E•ToAß”²ÏPIÏÆPµÕô›(¥­¢Rê,(žRÚ+åù}‚á·UTR½KÅH¨s¥ßÛ‘`÷¼þúëÑÙÙ‰M›6åÔ«µµuÈû!ÃE9l6£clØk&èÆÆsÖ MMM^¼àÎÎNÜzë­èììD]]ÚÚÚ°aÃÏž¯õ¥fÁ‚øÿÙ{û8¹ÊòþÿH !°É ‚1&ž€€‰Šœí* öŒ€(´´³±V*Ì|¥ZøÚ´3­•þćÎðÝV°­v&ZÄú´;Š¥ ÎQ‹ÊÖÆ=…öºÄ„=dIHB€ýýqæ:çÌììãìîìÃõ~½æ53çá>÷y˜kîûþÜ×uÝzë­UìXêØÌóèëëãºë®cÇŽlذ;vpÍ5×°yóæYsÊìe,¶`6>µ¶`6œÃdØ‚fŸƒ2;™¬6ÁX·™.fc›F·³á”¹Ét¶fò3ö\÷ìììä†n ¥¥…eË–Ñ××7ëÇ §úyRáq– ñ‚7nÜX7fûhëgc©c3ÏC޽fÍša]œgú9(s›¹ðü͆s˜ [ÐìsPæ6³áw4Îa4[0ÎA™¿LÖó9ÛžáÉ8§™vÎÓe‹fÚy+“Ã\üMLÆy϶ßÄtṲsV&—¹ö›˜Œsž¬ëÒŒsšê±Š™vÞÓÁ\8ç¹pogú9ôõõ…aŽçú˜ádÜ EQEQEQEQEQEQEiÍñ¨(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(Jèð¨(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(Jèð¨(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(Jèð¨(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(Jèð¨(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(Jèð¨(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(Jèð¨(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(Jèð¨(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(Jèð¨(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(Jèð¨(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(Jèð¨(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(Jèð¨(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(Jèð¨(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(Jèð¨(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(JÃÌ+áÑ÷}Çiv5”¾ïãºî¤–7•÷Øq|ßoʱgòu™mèõ˜[¸®‹çyU˦òd¦úØ2“ëÖ ôzÌm&rÇÓ&™­m‚ÙP¿éD¯ÅÜb2Úãí›ÌV[0“ëÖ ôzÌ<&s¬@Û“{mæ*z-fØé'€Ùk frÝš^¹ŽNSÝçåryp®œr¡PìííöûL§¿¿0™LƒÀ eYƒ=== —;Õ÷,—ËM9öL¾.³¹r=f»h”žžžAÓ4C;bÛö`ÿàààÔÞã‘ìÀT»QfrÝšÁ\¹óÝ Çxïo&“´m{ÌÛÏÖ6Ál¨ßt2W®E½ßý|²“Õ&¯œ½¶`&×­Ì•ë1ÚS1V m‚É»6s™¹t-f»-hÄ4kœ`ppöÚ‚™\·f0W®Çl·S‰ŽNOÝæ•Çã\¢T*UÍÜ©ý>ÓÉf³xžG?ƒƒƒ˜¦I>ŸovµeV1Ûí@£´··“L&¤¿¿l‹¢Ì7æ»-˜ ÇÑvˆ2«©÷»ŸO¶`2Új”¹À\h4{¬@m2˜í¶ ; ãŠ0Ûí€2ûYØì L5ÅbÏó0 ˲†]oš&¶mã8©T*\ï8NèbšL&Ã2²Ù,™L†b±ˆïûX–E2™¬:^&“ Ëïöc9§R©€çyUßmÛµŒl6K.—#ŸÏcYŽãŒø}´2Çs~¾ïS,éééÁ0 r¹ÅbqHýâ÷'•JáyŽãL&ÃF‡mÛÃÖÏ÷}òù|xïÆ»#Ï—œ§ïû†A*• Ïw,÷&þ zž>—rÌzun_Ó4«®G£ç=iÄ g y¶`*ì€mۣچɴ£ý‡³‚çyá¶r_‡ ÷†aLªéùš*;?æp×m¤}ÕÔ·Ú&þw_Ï^ŒVæXÎq,ÿË#Ù‚ñü¯×¶ âËe€b¤(<[3©M ¶`î· lÛ®»l4šÙ?˜ [0‘6ܿɲ#=_ÍhŒ´¿ö¦¦Mã{ögz›`ºû£h›@û“ŽÖg¶ŽÊùN´M c†óÓįÛ\íÌÆ6A#c†è:f8y¶`N{<¶¶¶†³ZÇ¡½½½j}6› /b©T¢½½=üäóùpß÷imm ÿèdïûaã4‘H„fù|¾jFÍx·Ÿjòù<ét:œí0Ú÷±”7Öó“eòçï8†aT=ôr|9v6› g<‹EÖ¯_+‘HÔ½v²N 0®ýGc¤çË÷}Ö¯_þñ”J%‰Ä˜ïMÇqÂç2‘HT­ooo¯j|´/0)ç=iÄŒdâëg£-¨÷;ŸN[0Úïq8; †QÕˆ7˜ãÔÚ‚É´0üó5UvF¶£í j äºÄm¶ FþÝO•-Ëïq$[0Ößs½6N§I¥RuíÇX™m˜Ÿ¶@ÛÃÓÌþA£¶`¢ma2ì̼6ÁXöŸv¦®M_?–g¦ÛzËš9V m‚í4ŽŽÏl3„ÆÚ:f8ÿìhÿ`8šÝ&hd̰ý@Ç 'Ñ4;vìTQ( èŠ],ñÁ{{{ªõ¦i†qüe}<†¸”98Äë- á:˲S©Tø½6'Àx· Û¶«â×~ `0“ÉŒùûXÊëùuuu…qÖMÓ4MsÐ0Œªk]{üB¡ž#0˜ËåªÖƒýýýáúþþþ!uuÿ±œg¹\õùª‰Üßß?hÛö˜bi×þ,ã×®¶ŒL&3˜L&GÝw¤óžëñ½±£ÙÁÁæÚ‚ɶõ–M¥-í÷8œÊåò a¡ 1MsHî†z¶`²ì€ì7Üó5Uv@îõp¶`¤}ÕÔ¿WÚ&ýw?U¶`,¿Ç‘lÁHûë[ß±M ÛZ–5¡ë>[Û£]·¹l æS›`¸e#ÑÌþÁdØ‚‰´ ¤œ‰Ú©×h¶ Ym‚‘öŸ¯v@ÎsªÚƒƒã{ögz› Þ²fŽh› Bû¡c†#3[Ç kè˜áü²ržó¥0ÛÚŒ6¢è˜áäÙ‚9ëñ(®õñY-q—ÑR©4d}2™ ?;Žƒišø¾ºLËwQáãû†1ª+ìx·ŸjjÝdGû>c=¿øì¥ÞÞ^z{{I¥RCTýøñkg'ÅÝÊ徯g4Él‰ø=Ïþ£1Úó%ËÓét8;«\.7<‹ZÊÙŽãŒ+L½óžëñ½±c±0»mA½ßùtÙa¤ßãpvÀ÷}²Ù,¶mS(( †1dÎH¶ Q;#?_Se@mÁDé^i›`l¿û©´£ýGj ·ÿÃ? od†f¡PhèÚÍÖ6Áp×m.ÛmŒN³úÂDlA#m‚ɲR–¶ fSÝ&€ñ=û3ÝÔ[Ö̱mÔGmÁøÐ1ÃÑ™c†“1N:f¯ï\¶r~Ú?žÙ:f8–}AÇ ÇsÍ'b ælŽÇá\é…Ñ.¶çyUñl…ùßzª°m›|>_&!“ÉÏçqgB׸ÖHI\ét:Mooï¸÷Ñž/Ó4)—Ë¡ ¾ïû¤R©†;2âÞ/F«Ñ?Ÿf7d§ƒFlÚæ0–çRb wuu…ËLÓ¤µµµêr<¶`"¿‡‘ž¯©² ¶`"Œt¯´M0ó˜Ìgz8;P,1 ƒR©D©TÂu]<Ï#›ÍŽ+ÌÚ\iLÆuŸéh›`ö1Õm‚ɲ m‚Ù„¶ f.£L„ùÐ&µãEÇ g.ŒNÅ8è˜á\Fû³FžËFô3?sVx4Msˆ 7†aŒh<,Ë •æøþ®ëÖM2«Œ‘Ö±>È’tU>×ÞËB¡€ïû”J¥!ISDzÿhŒö|IÂX™aåº.‰D˲ªfÎŒ‡R©D±X¤··74ZÙlv\³-=ïÙH#¶@íÀô0‘ç2¾ ¿‹ø,œ‘lÁdüFz¾¦Â€Ú‚‰2Ò½Ò6Aóiô™iÿáìÀdugk›`2®ûlCÛ3ŸénLæÀ¶ fÚ&˜¹LõXÁ\l€Ú‚‰ c†3—FìÀdŒÔ–£c†síÌ|y.Ñt̰q[0gC­&“ɪ䘵3’Éd˜¤XÖÇ“¿Ú¶=d™$-)ÔÞôÙò‡`Y¦iVÝl6‹išc6̵‰w ÃÒYäÓù|~ˆ;ðXö‰Ñž¯øl`ܳ âÏeü†aT…¨7ë³Þ¾õÎ[®ù\Ÿ‰Óˆ-P;0=Lä÷X{ßFÚw8[Шz ÷|M…ï£Ù‚‘ì@í¹«-Ð6ÁL Ñßc½ýÏ>ûìpY=;`Û6¹\.|Iû$—ËËËi¶¶ j¯Û|°ó­M0ܲ™Ìt· &ËH=fb›`¤ýk¯ù|° m‚™ÌTÌå6|×þÁøÐ1ÙK#v`2Æ äx£í?Z=fcÿ`¾Ù˜ýƒÙbâ4ò{lD?Ð1ÃèóDmÁœõx´,‹L&C{{;–eáy©Tª*Öz¡P ‘H`ÛvØñŒÏtÌård³ÙЀxžW5‹¡™HŒrqíý>Óéêê"‘H„×Ö÷ýq][ÏóX¿~}¸ïpnÈÉd’d2I:®*¬ûÇhÏW*•¢T*±~ýz,Ë g» ?>N*• Ëõ}?ü“K&“‹EÖ¯_išá3+3R©Ô°ûJ]×­:ï™ò´ †[6SiV›`*˜im‚‰ì?_Ð6ÁÌ¥c“I3Úñrµ0vtÌpæ2; L´M c†óÓÀüèÌ6;ÐÈï±YûÇLëLW›`Î Ã!ªuOOO¨8' 2™LSUÿ¸±Ž‘nx£ûOW™%þãŸÌý§ãgÒuT"ÔŒ=WÊd?¿þž'ÊHÇU[0?Q;м6ÁTý¯7‚Úù‹Ú‚Ùk ¦µó“¹j&«Œ©,¯Q¦ÊŽLõyδë¨ÌU[0ÚÍDÇ •ZÔÌÎ1éÚWmÁø˜³¡VG#î*-îÑâvÞL†‹Ág¤™>î?]eÎ4¦ãçÃuœ¨-˜žúÌÔÌOÔL_fjæ/j ¦¯N³µó“¹j&«Œ©,o¦2Õç9_®ãlc®ÚmL mÌ_ÔLO}f j ÆÇ¼õxTEQEQEQEQEQEQeò8ªÙPEQEQEQEQEQEQeö£Â£¢(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢( £Â£¢(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢( £Â£¢(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢( £Â£¢(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢( £Â£¢(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢( £Â£¢(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢( ³°Ù˜¾öµ¯ñÿñ,^¼¸ÙU™0O?ý4‹/žÕçpèÐ!:ÄòåË›]•†xüñÇ9ùä“›]†8úè£ùüç?ßìjL;W_}5/¼ðB³«ÑsáùS{638tè—^z)ôGÔìªL+s¡M0ž?˜öl.œÃ¾}û¸å–[X³fM³«2­üÅ_üO>ùd³«1­ÌÛ1^æÂït¼Lä^¯\¹’ÿ÷ÿþ_³«>­ôõõqÝu×±lÙ²fWeZÑßÄüa¼÷Zû³·0æ£-˜ ca¼÷z¾Ž¾ãïà%/yI³«Ñsáw=~§s¡Ý±oß>Î>ûlþæoþfÂeÌ áq÷îÝ|èC¢­­­ÙU™0´µµÍêsèî»›Í›77»* qÕUWqë­·6» ŸÃ|ä…^˜÷n¶ŸƒÚ³™œÃ|c.´ æÂósÞͅsèèè ¯¯oÞ O>ù䬿wãe®ØŽñ2~§ãe"÷z>öúúúhkkÓßÄ<@íߨÐþÁìíL„ùh æÂXÄD~m€'žx‚oûÛÍ®FCÌ…ßõ\øÎ…vÇç?ÿy¾ûÝï6T††Z%¬Y³fÖÏÄ\¶lÙœÔÚ°aC³« ÌcæÂó§öLQc®<sÁžÍ…sPæsÅvŒ—ùø;¯÷Zú›˜?ÌÇ{­Œùø|Ì…±ˆ‰0ïõD8þøã›]…†™ ÷z.üNçB»céÒ¥´´´4TƼðxœ lÚ´©ÙUh˜ 6Ì 8›g+(³Ÿ¹ðü©=S”Ƙ+Ïß\°gsá”ùÃ\±ãe>þNçë½VƆþ&æóñ^+cg>>sa,b"ÌÇ{=Ö®]Ûì*4Ì\¸×sáw:Úk×®åŒ3Îh¨ õxTEQEQEQEQEQEQ¥aTxTEQEQEQEQEQEQ¥aTxTEQEQEQEQEQEQ¥aTxTEQEQEQEQEQEQ¥aTxTEQEQEQEQEQEQ¥a6»ÂÖ­[éìì²|óæÍlذ!üÞÑÑAgg'\tÑElÞ¼™5kÖ4»úŠ¢LjEµŠ¢ŒÅ¨P”¹¶ EµŠ¢¨P”ÙÆŒñx|àèëëcÆ U¯–––p1›7oæÖ[o¥¯¯ë®»®ÙUWe’˜Ov Øì (Ê f>ÙEQ†g4[ v@Qæ>Ú&PÔ(Š¢v@Qf3Æãq``€¶¶66oÞ<ì6[·neÓ¦MlÚ´ €[n¹Û¶Ùºu+]tQ³OAQ”™‹vÀÌÊçŒ-w«ÙT”È\´Š¢ŒŸÑlÚE™ûh›@QP[ (ŠÚfâFåñ1ÏÑð*eÔ–ãv³O°k0“ˆ;ÏfŒÇc___Õ …ZvìØA__mmmá²5kÖ°aÃxàfW_Q”I`®Ø/ö¹HðçÐèÆ¶ñÇS¨¢Ì#æŠ-P¥1F²je~ mEQ@m¢(jšI¾Î2—@è"ö>NååQ=n*ËkÉŒ›ÖŽ7–ê³Ü£q¼a®Áxq]ðêTÈa{ƒÇ¼~¶ Òc¼6SÍŒxົ»9ýôÓ9ýôÓ9çœsªâ6ïÛ· Êx,[¶Œ;vŒXösÏ=Ç/ùËQ·S”¹N__ÝÝÝìß¿¿ÙU©ËTÚ€ýû÷ÓÝÝM__ß”žG\l„è8þ§ìQÿUQ¦ƒîîn~ùË_òÜsÏ5»*u™Ž6Awww³OSQšÊÀÀÝÝÝìÞ½»ÙU–‘lA£m‚C‡ÑÝÝ­ýeÞ³cǺ»»9tèP³«R—©îìÞ½›îînš}ªŠÒT´ ýEÑ1Ãé3œNÆ;îèS†WqK"¹¹5ËãcŸ~Ír§²Î©³¼HµH8Üòlº´SÿöÎm<×Ñe¨ù³]ð凖ómð©¯Y¯ý|æß†–Ÿ]›x9ø|忇ÞÇ.üÛ½Q]dŒùÈñpý’àš¹•ºÖaÎ?¾œÿ~è¡IiÌáq``€5kÖà8Žã°iÓ&n¸á†Iùã?|ø0;vìÐ٠ʼGhvUê2•vàÀSÖˆ¨ýË‹q/Gg˜íe:‘ÁöÇ7»*u™Ž6,(ó}ûöÍxáq*mÚ?Pæ;2ˆ7S…Ç©îˆð(ƒ•Š2_ÑþöEÇ §nÌpªΫÏãz![ó.ûŠèVŒ-—ñÎÕcœNͺør'¶}žH\têùèÄʨç!™Ž-—ú•ˆ„FjŽÕ[î‰Øçøòlåq4~N×> × –ÇÉÎuðŸ§Ëã×ì‰Ã=W_søòaÈôÇÎÇÎ}×&øÊÒàœä¸Y+8F¶²yÄXð ÑŒ–A¯ý£¯7SHQ¦ùmÍÔε¶ eêY³f ›7o¦£££ÙU–‘läm™(Ë—/Ÿ²6¢Ì&ä·4_ûçž{®ÚEAûÚ?P3œÊ1ÃÉb¸<ƒE Wgy©²|¤õ’_QÄ5IUd¨g£ˆ}ÔYNMñer²¯Œ›‚˜œ£ˆŽ"X&cÇ”ú¦bå©3%¯d¶f½+3ôT¾y/ܶ*È[YÊT «ùX9pß¹phI$è¥*ÛþäX´ž¨loWÊÙ½ vloÇ®õ`?l?%*["é^PV¼îyÀpàÎÊKW¶õd£ d*Ûe€µ;áÚÛ!Ÿ‰îe\$7î¹x±ÁW?üaÞ²m0c<ëÑÖÖ6$äI=ã·aÆfWUQ”)b6Ùù£Œ‹òG'ßåÏKÖ)Š26f“-Peꨵjeþ¡mEQ@m¢(óÏ :u´ü†õr0ú5ËE¬õ<”²EøáϫٯDF5.þ‰×{Åôڱc9¢X:¶±òÓ±ºHÝZ+ß“T „â½—#‹MÆ–å+ËÚcuLß<ŽÝÇ­/[ù|f%PYY^V톥߉êßZ)sõÑ5ïJXûõ ©_ºR—“,/ˆ¢I‚Ï~–÷ŸÅã² øíc®R~X>8ÈŸ->Äõ(ïç÷€•cËâ><àŠÃ‡9|ø0eàúáäOÃÉðÚ­[G{$GdF[·n媫®²<ž4Vf.Ô†CêîîfÍš5Í>EQd6Ú—j×û¸g£Ì‚àO©DôG'Ÿ‰/®(s•Ùh E™|F³jeî£mEQ@m¢(j„áÒ7ÕzûîP?Ôjí˜f\`”ýã^ƒ~l}¶²Ü®¬¯BɳhR>UF›`\Ôª|6cŸS±zŠø&㨑WŸˆj‘g` x÷=ÁòLeûdå3Å"=•ï>ÐUYž‰•“¯¬?»_Õ³T©ËÊà‹U9–Ià%yÓÏàÀ§ƒ²dy?ðégaÃ/ƒ2’•u=ÀÕOÁ_Ž<, `@|ígƒír•WªrÖ^½ŸT¥¾½•k…oüÏ`™\»?,üŒÏ\¿˜ã¾ü(&ð·bø>¦ ˾û"oúå>žü‹¿À¯”õÁ;îÅÏ/ÃÚn»õ7Ý„éy|èXxô#ð;7ÜÀ÷¿ù͆ž×!);I |‰w¢Q³LÊë"Ç’±õòYÄÇ ‘°—V?çŽÒX‰pùä§`õá(tl²²ýï¿®~$3•å×_¿!¬W*¶½ˆy™J½ ÀGï.H™Hí,^ûÛhñLtÝHøËìgÅ"<þOѹäZ;ÁˌՂ°¬On‹Î'(;¸«žý.TÊñ\ß÷I¥à¬mÐÚÚJÎu1€ó—±Zþó…8ŽÃ½—^J:æÛßÞþ}Gñª[~JÆ0¸ì¹ç0þð1^ùøC|ìÁ¸õío§µµ•׿þ#¼jñ)¼ýíooèy9׬YÃ7ÞHGG,[¶Œ¾¾>®¹æ.ºè¢p»Í›7så•Wrùå—ÓÒÒB__›7og6(Š2{™-vÀ!øƒ0+ß]"¢?ÿ Á·ü™Š¿ÛWâyg‰þlòÈŠ2_™-¶@Q”©e,¶@퀢Ìm´M ( ¨-PEí@ñB”<‰~lypZèyHâc6ÛNOO}}§ðì³»Õø¾ïûxžI"ƒƒÏç)IÒó ›Ë „ÊøØn=Ž9æ‡xÞùçclã\Z[¡X,b©T*\wá…+ƒëžN“L&±mË‚¯~õŽÓN*•Â÷}‰¯>ö¶mÛˆ[ñtüÿÞ÷>v<@: û·&–e‘H$¸úêqÛÍ>þîÑõ­.,Ë"NóÕ¯>ÁÒ¥¼éM§ñ×X–E>Ÿç#ò'lÊß^q=ÿôÅK‚ûbÛ8Ü}7\{íµ,YÒÛÐó;c„G *_ËHŒeEQf'3݈@(I‹½ØKþlÍØËŠmÿ,ïòG Cgû(Ê|f¦ÛEQ¦‡±ØµŠ2·Ñ6¢( ¶@Q”ùg¢i?:Dž~B<ïcšÈ•å„O•å‚qI0ST{H¦j>;D!HÿÏ.pŸ D:…—=þ$+«êd°WK© }q‘UÀ\.ò†ô<£Ž:‘;|à´ªcB nBàéhYŸþô§ò¿ÿûsòù/“Ïçñ}Ÿry0Ü®T*…£S/÷•+>žÁG+vÐ-[~ ^žça¾ïóÞ÷ ¬æ–[vðÎw.Á÷}\×å¨£ÎæK_Úŧ? ¾ïã8Ùl–ü7ž}öL>sÅ´¥R¬_¿>+ ÷ò¦“?罄B¡À‘7¿™7ÝsâÜsÏ%•zUåÚ\ù»¯àÙ›Kt>öÇx^O 0f³úí]lß9È'?y9-éV¬®.²Ù,—¾ñÿôúØæÁ¡—’´òGg>Ëžûw6ôüΈŠ¢(³‰ÚÿI ¯*ÈñPªÄÖÅFyÉì ‚YG&*>*Š¢(Š¢(Š¢(Š¢(Ê|FDÆÚe04w£{—ýÄñÁ¢Ú3²‹ê1Ë$Õ¹E\4£–TÊ‘2;ÿ%e¹èq{÷îå—¿ÜDy!›Íòîýû1ÇqX±âi^ûÚ7G×#¦fÞwß}$“IœŠ‚xÉ%—T¶1H&“tuuÑÓÓÃÑG„ûĽ—üöX¶ð™H õ}(•0Íè+á*Ÿ—¿ü÷Ø¿?‰D"|¬x%~ô£Åó<òù<®ërÊ);hii!ŸÏ“J¥H¥RضͳϞÉÿñý|hÕ*,3ðbL&“äŸN󯿹»âN¹¨¯O¾ñ½ÁçE‹0 Ã0(—Ëœàûpì±ì|Édp—–§RÜüš#\rɱdSýày˜¦IoOmW½†ÔYÛ`Õªè¤ÚÛ1ü%Ü{ñµYÆé¿øEC÷N…GEQ”qŸ±c µ!Uã¼qïÇ8ñdÂõÊWEQEQEQEQe~wL±ÂRlYE÷cÝ#T…TdÒ&òpa±L$ Æs%ÊØ¦¬s]¸úê€ê¼ŽÃqì±pèÐ /¡¾·#Àý÷ßÏ=÷Ü3d¹x–J%ŽÿÉOÂåO>¹–»îúg\×eÅŠ¬_¿ž›o¾ €{î¹ß÷)‹‹E¾öµÍ¬^½—[oý­­­Ø¶M6›%®\kkk˜;`Å;xé ;úî¿çþøÇØ6d2ð…/|„D"A©T¢T*ñÈ#°ä¨]|ó›?£P(ÐÕÕE*•báÂ…\pÁ]Ü}÷§( ˜¦‰aœwÞy,:r„G¿ðZvîÄ4Mr¹¶ _ùÊ«q0¥]]]X•8³‡Ÿ?#ïжyך5¤RÀÀ´·‡×ÅÃÄ]uIåÁȆ®¤¥~‚|èïÜ5} Ü΢ô蹘g/â¦Ó`šØnûô>ŽÝ³‡½«W7ôüªð¨(Š2dæO0{(>k¢?hˆfDŽH¨TEQEQEQEQE‘ñGÍ'!Kº$Ч£EµH(ï&Á8¤_qÝ3*/«RD"mï»ïè1×ù¿XzüÕbÕñÈxüñïpàÀ@ 2®X±"ôbt]H&“¤ÓéJnÆ`ùÙg_ƒaär9zzzX¸ð%lÚ´‹sÏ —JÑÕÕÀÛßþA8™×¿þõär9 …mmg†ŸÿõôÓÃëñ?´a,>Ȇ {¸ýõ¯çÖ~íÛ·ó'ò¾ð…N8ø*Þ´a^ÅsðkÖðÞ¿ËÞŸ}“R©„éû¤oº‰ƒrÏ=óš×|Ó4ñ<¯"ˆÂÚÝ»ùÔSOqîÀ,XŽƒµô¡àžnÛ †áyø?¼ŸòñG¥ï¸hÛp×]pø0–áb¤ïCk+ÆË–b¿k%†Î«BáÑ{²ûÌÝ^uKp\7xíÜæÐIJ‚d›¶MqÕ x+ÏembžvZCϯ Š¢(£OÊ\›œ9>{(þ†÷rTEQEQEQEQeî“%òNnå%c‘qÇ/öÚ_ ‰)ßm‚kf좱ËR)ð›ŒGjóýê‡RuÿþýÃ×o˜m'œpÂeGŽ!Ÿ‡b±àÔS7±téCxžG{{;]I9r‘<“É$®ë†!T¿ÿ­o‘H$°, ×uùЇnÀuáw~ç£P,†¹>z%O?½€»ï¾; ?zà‹_äŽ;> @*™äŒÇÃq|ßç±;|ñEv|éǼåÉ'yç›ÞÄúövüqž|²…§~|¿ýÍoøÄŸü Ö‚_S$ÅÑO½ŽL&–Åòþ~>ô®£1Mxî¹WK¥ÈØ66W,ëdÙ‹/ÆoM$Èßq=— ’IH§q=ƒÄþoaÛà^ðá@HL&ñ^XKñ¶cqu| f³àº[¿F2 ==`œ·1ØÞ0°ÏëÒÕ¬ÿÎ?âmxg ^&“˜»¾mzc`Ó„T ¿í z½}'ž8Á'>`aC{+Š¢Ì\¢?jƒ(†z’ê?~›¡9 EQEQEQEQE™ŸL$­’x9æ‰<‚±ÇxîÇ'·mãìþ~X±`¬2îå(i¡d\ó¯þªIm˜Œ•c׉£úÙÏ> œ]¿~þÐeO=ÕÉ#|ò/·ºÝ»÷ëÈçóFs1ŸÏóè£oàùçWc]]]¬ü°-‹SOýýý]X–…eY´¶¶ÒÓÓÃúõðóä¨óRX–…iš¼ðÂ[¸öÚuê•Èôöâû>ö¹+yÙ_?ÊݽÖãÕÿ8ç­¾‚߬\—“ï¿Þþv\×åugÅÍ÷Ç‹÷ÜCîHP÷»Ž?žwŸôä‚çaüÙ{±·ãœÉ$ÅÛãn‡\Z³6ƒ•êy6x`­ÚM©÷ì ¤®eáÿãwðÛÒÁ=´íеðÍ•8\~ùɼò•‹zæÕãQQe|††S-Ö|nÄËQ=$EQEQEQEQen#ÞŒî0ë Jùä ˆñèkç?þx¨Êø¥lAhUˆFÇþþHH¬èXVµÇ£ðØcÕ­»5ÌæÂ… ?§ÓiÖ¯_O6›eݺá o¸‡¿ÿû¿ç†nÀ÷}’É$¯~õ«9th íííxžÇ†C‡Hš&<²Ž³ÏþK’É$¦ibWTÑEþ¡|6—ý÷Cå<Ï]}\¤y¸.¹\Ž—íÚEéS;ØåBĶy÷9ç"eå$Nݵ‹öövžzê)^~ü¼i°‡'Ÿ ®ËYï?wýÏ'øÙÞÕœ…–EË׿Î=Fvà¯Y{îJ6·ÿ:È‘èëówŸE±c€üG—ÂJØÓ¬ÜT*ØÖ4á°+p޽$¬c <«ûOó3š›/'“{Ñ=Á2ÃÊÛ»·ê¾8›¶Q4Öäõ«)}{ R¨{x#¾]]à¸F Xh§Ž'œðŠ3¡¬s‰DÇç*¢› ¼éÞ{اµi¡âˆÀ¸sçκu©¤Oäg?ÛG6†}â‰'wˆwc½0«®ëòàƒ†ßs¹år™T*ÅÀÀ_óÓŸ.ãúë¯'›ÍR,immeáÂ…ü]X–E2™dÑ¢Eœ60€iúUBhWW¦aP$ŋǿ†WþüçB–Íb|ç+àVßpï@ïÇ¿ÁÁ†Ý»#UÕ²XyäHðÙ0À¶9m`€T*Åÿ½ã²7í⫳tï^èéá”Å‹Yúâ‹8G. ¿óò`Ÿb1Tøöz*m_ûsüÕ!Ѳ°ÏÜõð×(ý®@9Ìd„Š™Lå„Dt¬,H^¿÷Ñ•Á}H&aϬ‡1ÍàpΩÿ, × 4NËϰ¢²V­ s6–Ë`ý݆×Î0¢ô޲½wêÛÂK•N…~­ð<Ê’%‡Æúˆ×E…GEQ”1Ÿi$àò®B£¢(Š¢(Š¢(Š¢(Š¢(ãÅ%ãË„ø:¸ÿ†€@ˆ|aÛ6þïÿ/,ˆÄ&Ã|øá‡ëÖÁ÷aåÊGùùÏÿ‹b±ˆïûø¾ÏSO=Xu…FÛÇqH§Óø¾a¼â¯àšk:±mÓ4immÅu]^xá,–.½ŒóÏ?Ó4I¥R\~ÿ§yä‘«ñ}Ó4Áqxã)§ð{¯è¥ü¥=UÇûÏÏü€Õ rÔ¾}ÁÉ9ÞOŸ"Ÿ‡üm«pL3PQ z{{9 —Ü‘?N°X Þ+×ÀóËâ‚ã'gšüÝß,äÛßÞÀ£þu ´ŠGáêÕ¨wê©€Yɇø¥“?„ÂVL“À[±ú4ó™Õd.{.¤d¤q±âÙ^ÇT*Œm[.‡še ÖY/~íxžè–quô ˜P|èüP,àõ¯µÃ|œžåU×β‚ã„\pA¸Ü«ÉfšðÖ·>Å[Þ²­¡çZ…GEQ”1àýÑ'^Õw‰Š¢(Š¢(Š¢(Š¢(Š¢Ìuüa–»uÖ_tß}|çñDZ¨ Ï8p Xæºwø0vå3q Ÿ¬õTìòá~ž=÷òÔSËø¯ÿú_|ß'›Íâ8ÇóCöïßçy¸®‹çy´µ=x”J%ÇÁqŠÅ"<ö-ù ÿçÿœJkk+­­­\}õÕ¬YóÏùå/YÔ×G±XÄ0 üƒAÁdE˜Ã²8óÓŸæ¾×Jâ}§°ý¦›BeìWÏ?ÌYYzà$“Üóïÿ΋O=?ÌÉ' ïyÜõ“Ÿ€çÑrß}<†‰}Ô÷…-ŸÛÆ*þŸÞßu`W‹ø¿~šî7qpíÚ@d}d?<æ˜`Ëb㑯ð£=x®x<‰¸†MòµãúÁ2QkÃÙ:NÞà=ïy6½×þ>·|ý<Ï SAƱZT‰Á©8ƒÁÁBô\Õņ;§x9ÖÐçÄœ$EQÆHü¿Á¦:Ôª=þâ†Åk¼EQEQEQEQEQšÌ#<æsŒùÉg—ê4Oÿµp!?<ùd AÒ$p‚øÆ–-$+žˆ†çažç±|ù¿pèÐâ0=T-ù˜âô£= dðk”¬ï}o;ƒƒƒÜvÛJ¥(‹äóyÎ8ã OooÅb‘D"A{{;Ÿýìó8ŽÉóÏ¿–÷¿ÿý”J%’É$«|ƒû¾ƒw¶fYõ£aš&ßøÆ7صëÿp5ð¦_þ’L&ƒmÛ¸•[ûQ*•ðËå0,)ÀÙ™ O¾îu”¾ûSî?ú\>ü§¸ó¸ãøÕO~Â?> û÷³âñ ü¬oY¼ýž{ؾb_?úBž?úhž~qY~ÓÄ}á,Ìåý˜w.º–Å›žÿ?üYR)øÉOŽõñ}Î}ão8ê¨ÏpɧïçéövÇ¡¿¿Ÿ={ö`šàî^z5Ø:“ä•K«D¼³ÏÎ0ŽãpóÍ7ÓÑq;ÿòÔ‹ìØzEÔ*XšfµXxã{¹é¦§q]·*ÿf2 _ÜW9F´<• Ó:Ï m¯Â£¢(Ê4!üÅØ2“ê«ÖØ‹¿ñ"EQEQEQEQEi2ä©[ô¨,U–Þ¸‘3î¿?ÌËh8<ìÙ³'ð*¤’{Ñóð<§ŸNsøðâ!㉋dÏž=¡÷"ÀC=Àž=Kª¶Ý¾ýiÄÅâ’K.!•Jáº.¿øÅI@†ßþöå$“IÊå2¹\ŽU«V±|y?ÿú¯ÿÊí·ßŽïû´¶¶òÄ‚ \ú²—ñÆÅ‹ùæ_ÿ5ßlV®|sñA>¿k¶mcVeÔÕ½s/_þ¿ÿ—D"A!òÜûÏ£ÎaåÀ¯x¿üå^xá,n;úBÞ{Ûm¼íÔS|Å+Ø<¿hïÿg) üèÙg¹áÍóÎËþ)¸Ö'½_Tµc…¾¾He³,î|={–ð ;¹çžE´··³~ýz¾úÕŸÐÙù/Àz ÃÇN&iooç˜c~‡={öLVD¼˜`Ši²Ÿîî ïäM7mgûö¡.‡û÷ßäI§Ó<úèÑ|ÿû'’Íf)ýè6V®ü^ÅÛ3 ™kÁW<ˆaÀç>·-ô\½ûî»Âûüßÿý8®ë’Jõóæ7•D"QyŠETžýýÑeð¼¡Þ•E…GEQ”:äDì»A”È&×ÃQQEQEQEQEQ”¹K­Ç#DžŽ^åýC‚¡—}å+áØ£xÅÙgÛ¶I¥R<÷ÜR|ðA®½v *|­ïû|üãÿÄ¿ýÛ!\×¥³³3ºçnà©êû>üà?pæ™m•ªo}ë2òù<Ç·‘Ë/¿Ïó°,صk¥R‰-[¶ó'ò®›``à#¡ê‚ßcÓ¦)‹|éKïã‡?¼ÖÖV¶oßκuëBAÒ©uÎ=w–U ›ÍÒÙù"_þò|îsŸã;ßùNCÏ» Š¢(uð©­š©,ÏÆZGEQEQEQEQEQæ'Yª„çŸ>ü\ϙ̽¾³t)8žçaÇ>û,‡÷î­¸¡™xžišüñ1ÇP*•°í@žüíÿ`gÅóíî»wðoÿö’É$žçÑÞÞÎgüÛ·oïº.‡Â0À², …kÖ¬áïx~õOXµðçxžÏ¦M›øýßÿ}’É$†a30ð.žxb ¶mó‰O|Çqxçš'¸ç¨søI^18Xå>wÓM+(’â©eËøõ–-¸¾ÏWž½„c޹Ÿ>*ÈQù÷ú§xžÇ%—ÜÌߟùgœñI}î¹´‹lzøaŒãAXWzz8å½ï¥5ïò‘Û?@ž Å{7°ôÊ+áŠ+X²d GõMî¸ã–]}5¾ïãûs¢ñ;gàû>ù|ž+ÿñY| \pÁ<Ïcÿþoår™ .8ž¿ø‹«¹ñÆó9pàr¹¹\ŽL6n<ŽmÛ¶±m[ ­­­d³YN;íZV¬XÁQGíã”SÒÚÚJoo™M›v L‰ëׯçÅ—±zõy¤R)Þ÷¾ œuÖY˜¦Ék^óaî»ï4\×¥»ûNz{—“ÍfÉd2,Y²Çñrè™ú¶·ÝÄk^ó{xžÇ¬áoÿöfzzz¸üòm|ï{›èíí2”˽@j5›ÍòØcwpÆgP,Ù½ûGÜ|óßòå/™×¼æ5 ýTxTEŸ`Ö‘ÅP¡15þâFe2C¶*Š¢(Š¢(Š¢(Š¢(ŠÒ<N; ¨ÎéXëùè¥zÂuCÀúSJù<Žã°hÑ¿†aÉù-ËbÕªÝa9÷ÝwÙl–‡~€¾¾‹±,+¨V¯ÞÀŠgep8—5kÖpÜq‡ |k"‘À0 Ö¾ôÿcïó¯åÀÜu×]¼ãU¯âÇ_ú‡™ žæŒeËøÆM7a¶m³é¡b÷ /ç7ëÞʱÞ•Ø6öê±q`Ó&~øì³løØÇ(•J´´´pßÀ»¸÷ÞCY³†5wÝÅå—’;>'Îýkyë_@¡À)o|#üð‡‹²jÕ*R©hTvpðìàZœù,nïòpy*úÐnž~ú&N=õmœºe Û¶íÄ4Áì¸ß÷±,‹r¹Ì’µk¹à‚ B1×uÁ0 Þýî7`ðŽwœ2$/â²eËøÇ¼’³Îº›r¹L©TbçÎÏR.—¹ãŽxÏ{ÎäÖ[ÿú§¯ðÔSë€2ï}ïÍø¾O*•âúë¯ —ËqÊ)o$Ÿ‡B¡ÀYgEKKà…zóÍïåºë§‡}è=|ìcéêÊT.mŽÞÞ^vï^ÅÀÀJr¹ïÿ'ùØÇ–`YM©f%–ê£ ÀM7=M{»C>Ÿ§XlåŸþé …'ž¸‹ÿú¯oññœ—½ìe =÷*<*Š¢Œ@¼1l¤ 1b4^„¢(Š¢(Š¢(Š¢(Š¢(3Jî?_,U^qDt<ãþû9noÐó<Ž9ÂêÇÉçó,YòRŽ?þxlÛÆ4M2™ ¶móÒ—.á¸Ãÿ À’C‡ÈçóUçž{.™LÓ49ï¼óX´èœpÂÃázÏóxéK¿Ío»•sI¥R”ËeÚÛÛÙ·o/_ðk–ùÅÖV®]¸gŸ}–“NZć[ZXÖÙI¹\¦P(ßÿ§œ¸ìE–~z ü™&XÖ©ûÈ‘%•1è;é$~¾p!F>Ï©§ž À©§¾E§Ÿ–Å{ßûgA½ž]…³ã”  ÓÄZÞKî²wï¡„9“)£J,áç?%`ðÈ#W‡ËŸyæ\ÜÞ帮Цœ|2§v¹\Žr9ȧP*¡k]Z[£ò^ö²ó1 ƒ .¸Ã°ùüçä°´,òyxÙË.cÕª3Ãýî¼óN …¹\޳Ï>»òˆTôÎPø”Ï…BŽ›o¾ß7ظñ öî=®’o3p(õb*vpŸ!VDx;wîÄ÷}î¸ã^|ñ)z{{yÕ«ÞH6 Éd’½{¯àÈ‘5¼õ­omø±WáQQ¥@l·ÄSWDEQEQEQEQEQFÃ÷«ƒ«ŠÀèŒ5T5¾äç?gãáÃÁ¶®ËÊ~ÿµ¯Åu]Nã o¸£"dær9 Ã`ûöìû~bô­Ë–aÛ6?üá§¹þú;Ù¸±›»ï¾Ã0( üêž{8rä5ìÙóÒ žÇO~ò ÅsÏ]Æ®]»0M“R©„a¬8ñD^9ØËÆgà]ïz‹wìà]GÍÊcßÃã/¥ÿض@™sÝP \öŠWpÖYgA&ª‚ù{Þ€³ä$.9†WüárÇ1Ç<½€óÎû2íí+…Ì0xÍkŽ'“‰tËðÚ™IŠw®r'¨‚qý´¶¡°|ùrlÛ˱¬¡#»²,— ª ‚¡¤C”÷¸˜'ßO:i©TŠÿx1¾k×¶PqF­”]»O–+®Ø„Š…JxÛ¡çÁ¹—ËA8UÃÜÑùÙvpÞÅb´½¼§RQ9q~øaÒé4—]v¦ibÁ¶"`Z“4ø­Â£¢(J¼šw“ !`O¬8EQEQEQEQEQæ09M´/7®‚årt‰Æ%ú™ {Ûm¬}òIÇÁu]^¶t)éD”9réÒóëŠg{+^’§vZ% «ÅÍ7_‚e(æóAù¶ýú×püÃãº.¼æ5ì¿ç~øaV®|”³žû ,XPÉãh°pÿ~l<2ä*JÖ‰ûöñ–“úH{ÉÃ_+ÏßÇÁæôÓ•2Mâ.ˆÉËžÃÛ³„Å‹óG_ø‡7n$wÎ79óÌ3¹ûîËEõÃ÷qÍ4a-ä´Óà„†œ{\Œƒª´’@àX(PÉíh°ÿþؾ‘»`:]]NÍ­«:Õ½þúóÈd2¡0(ud¹Ðßÿ—üÞï}¼ª®qASÄÃTŠ*SDÑZl{¨ð(u—å·¾µŸ?øƒu”J%.¼ðB/^î—JAå1݆QáQQe ††>˜áÑk¼EQEQEQEQEQ¦(Ùšå+b¡OãÂ$Àú§ŸF4#ÇqøÙÏnr¸®Ë†C‡0M3ô&<ãŒ3ê÷СA"Áû6lÀ¶í0„'@ŠH`ûó¹†/¾Ž—µìä#ùç>L¸æšA.¹džðÏX†Á§?ô!’Ÿ} ¿¿òv-X€áykœi’yëS¸Û^ Øw1¡Ë\{;89ÖR.ƒùµOçø†¿a㥗rì™g’è¼˲q.™ÃÀ÷ÃÃT{â½a¹¿DMo˜ÁSÛ®·Ì&›À„"žïû¡i\ ÉëOŽÏSñ40Œ@D”º ²<|V¬àøã¿;N$øôöF¢a\8´íê0¯á½MEâe¼ÎÉd Ú&“‘ ù‰OÏ{ÞóizzzxÏ{VU]+ñžœLf¤ð800À9çœCww÷uœsÎ9œ~úé\wÝuôõõ5»ºŠ¢L3Á¤hŽ¨Â£¢DÌ[ (JóΨP”ùƒ¶ EµŠ¢Ì.; ‚ß3ÏõlÚE™_h›@QP[ (Ê̵ñü‚GŽ CªŠ¦tøÁIxC.Z´ˆ{î¹;tCsñ}?‰‚¼'×=î÷Õ‚RoïrŠE¸çž>Þ²s'©T ×uùÔ§¾À©|h÷nÖ®]ËëžzŠMË—cá²äÈ‘@å*Cåíþ}§òçnÜ÷, N8Ôºïb¿î©`ûŠº–¸ö4\7øZ/Ti2÷l›Ì¦]áîñíå2ˆ3ep-ƒ÷Ú<ަ•Y‰Öî%Ôêã¿ × ÊØ¹s'Û·¯q4.ZŠP—HT‡W­'þe2Qku½D"+Úo•¨˜JAWWô]r>ŠDz‚c ÕËkÓøuÉç£úÆÃµ:Nu=L38÷XT߆™qÂã–-[Ø·o_Ýu[·neÓ¦MlÚ´‰¶¶6n¹åvìØÁÖ­[›]mEQ&‘fÚùßrB­ÚD±ÖE™^´M ( o Ô(ÊüAÛŠ¢€ÚEQf‡èíïçàÁƒZ²$XX“xÐŽ<ñ®ëâ8oiiaáýWL<”žÁ¨¤’õòïõ÷ŸÍ¬0+Ù,ìÙÃi§ pË-KhyáÒé4®ëÒÕñJV.ïåU‡ñ’—¼$ ñºêŒ30ðáþ@ĔĉÉ$¼ëÊ¥ô<ÿ’÷Dn„--øK^Š÷àáà{<¦'‘§_=BÑÐ4q½ß)Ãs”Ë÷Zl»úrÆ·‰3îu/ã裿P%ÔÝ{ïK‡ÔѶ«¯µl_*Õ÷Ì„H Œï'¢¨„1M&‡Ö1®.§PÊ©ÍÑ(ǯ]„|*>öôT ¨q¯Èz×µ67f£Ì(áqÇŽ‹E>þñ×]×××G[[[¸lÍš5lذx ÙUWe’h¦p€öšeÓ‘Ó1ŽŠœŠ mEQ`x[ v@QæÚ&PÔ(Š2{ìÀ®£Žâ±øÑ³Ï = B¡OÆŠŠµnÝ:.¹ä’˜ðh ‰™É =Ö—¿ü KÄIÏó ŸgçÈÎ/zßðí} Çqø÷ØÏ“O¯ç•ÀÞãŽcé7®u{÷b»›äÁ/U©†Þßu²ºå…À#nãÁ¶–'„·¢gñ;¢X¢¦I欻C‡Iñð‹ Zžó4Mœm-ø~µ &:¦œs­ ÷Ü ®a$:N}Á.•ŠÊܽû|ž}6x.,XÖ).Æe³A]ã×ݲ"!/–TÄRÏRµ«+xÉòZÉZ°6LmüØõÄAî_­‡i>?4÷£`ÛC…aÛêeÙ3Fxà£ý(©TŠ 6 Y/3âÆ`Ù²eìØ±cIJŸyæJ¥Í>MEi*ÝÝÝtttðøã7^Ø0•vàñǧ£££n x@Çm¿Åô ÖuæãW^c%KF£%Á»H$~çcÇåà›™€IDATX_)£TY_Š•ç­@¢æ%“¥¼Ê¾íÀŠÊòðÚ_ýŠ{ŒÿyùË›}9ë2m‚ŽŽŽfŸ¦¢4•¾¾>:::ضm[³«2,#Ù‚FÛO?ýtŠIQæ3tttðôÓO7»*u™êþÁ¶mÛèèèhzþ'Ei6”J%žyæ™fW¥.Ú?P”©GÇ G3ýË—óèÊ•UcŒd³ä€yöîÝK©â wÊâÅ|îþ ôl\·nÝá±^î¿Õ«“!O?%Úx€oÜtÏœv`pô1¿Ã‹ëÖqð7¿ÁqNyéKyÙâßp!—=÷\ X%“XGý ã”Å”¨¨s¹ âî:÷±“±¬êcçþ~Ö›–à8&ZhY¸O¯C§Æ‘®ž§ ™ëF¢e\À´í@<¬çõ'ÄËÏå"!Íó‚räúîÙsˆÏ~öaÖ­{ Û®­ì/ïþ5.è¥RÁrÇ–´«+ØOê+”JQ¸Õ*áu¬a‡M3AkÅÁ‘ÄÂÚë$çR,]'Âigg礴 fŒðX,Y¶l×\sͤ—}ì±Ç²aÃ6nÜØìÓT”¦²fÍÚÚÚXZIL<Ó˜J;°téRÚÚÚX³fMÝõµ±Ø !0Ùì £L+Õ´C ÞÉÿq‚@ì+ {"ø­T^ÒÎp+ëÖWÞe½ˆíÏZ¾²žÊg·òòDÈt¬í±zØD"y¦òYêêUêi9¢gú×ë×ó½övžyÉKš}¹ë2m‚ÚΈ¢Ì7–-[F[[«W¯nvU†e*mÁâÅ‹ikkÓþ2ïÙ¸q#mmm,^¼¸ÙU©ËT÷V¯^M[[Ë–-kö©*JSikkcÆ {ì±Í®J]´ (SŽާĽx9^¥9¿LåsºòÊÄê)´Sg´Py .8Y®sŸìÊ:Á¬S¾½p!÷ÔSØ® oyË„îãT1]mXPæ;---´µµMʌީ`ªmŠ2ß‘>ò|íˆð¨(óùÌDïgí(Êô c†c3?xôQÖ½ø"»*Ë<ÈÀÀ?¾åžúéy€‰išUcb® GŽ?Äㆆñܹs'p Ï=÷jVüú×|æßþÛ|?~þåøå‰|¹|&-ŸMa`ÎÞï²kà $ù×3Ž…;ïÓ¤´ÌÄ0 µiƹ§…W„GÈÄÃÚð¢UVM}E䊋wò.‘ñ\Šâ ãûÆÅÀ|>(#— êÓÞýýÕ×É4‡ qoxÃ8í´s«êG¼$ã¤RÁñjC°Ê1êÝ#9¿¸¥P/fÜë2N­×i¼üz!ikÏ© wX¤.6l`ß¾} · fŒð¸lÙ2n¸á†ªå,[¶Œ[o½5\¶cÇŽ!¢ ŠŠ2û™Iv vÒÇ|Ê»X$à  ·Î¹‹÷Uy/UÞ“D^{¥Êç$‘çÆ¶/yèÉgÙ¬Ê1ÄsO¼÷ò•òüØ>"úDÂam™¹Ê»x•íEÐKÄŽk=•÷Rå:b娕cšT‹Fë÷šôbåÇ)WŽSOà•ú›Ô¿k]£ÜK¹.õ°ã~õ+f¢Ü0“l¢(Íc4[ 3Õ(ÊÜEÛŠ¢€ÚEQf¯¸ý¾ûÀ²8õ¨£Øø¾Ïþ¾>V/\È/| ,^¼³F r]8ùäç1Í3‡”„ Í“©¨^§ˆ„kÖ<Áó÷ý–»¿þu.ýÌgøà›þ?öìI*ƒL´·c_ñoxÛçÀî·q#ÜxcUùöÕë(•*"–aÀÉQ(Õ¸è•LF¡ïõÒ³íêðªõòSB°Ü4ƒsÎçÑNBÊ–ËÁòD«E³¸xçyÕ¢[\p1MŽqá…çröÙež~.¸à‚p«qÑÐ0†Šw"`æóCE<ùžÍV ´µù(+ÑmÃïõÊ©—ƒ1•ª/ÂP±SޝÇhÞ–õŽÙ3BxÜ´iÓÝÝÝ\|ñÅ¡aõ<ð@•±èîîæ¢‹.jö)(ŠÒ 3Ɉ0ÕLÄso¼õΉw¹šòÒâ]‰Høo¾øÿV@èKÇÊ/HAD8ƒ@“ @&‘(9 Ë|" vU>Ç…Á®Ø5wcǦ²<;¾x!f*õL ƒ‘xZKOåXôuªHVÊÈÇê-beœáþ¯Eà†ËÝ9œ7­U¹¦õ¼ÇŠ;ÁýšÍL²Š¢4ÑlÚE™ûh›@QP[ (Ê̳.Á¸Ôhã5»víâØ?üÃh?×幘k?ùI:°Xµj†±§j¿d¾ûÝ CI°Ç!•JawÞy'p5­»w³ðõ¯ç=mm¹÷^®fa4þå8Á˶á’K°Ï„%KÞÖ«B%+•Š<K¥ŠeYä‡H|¿Z<q2B’Š` Óé ïa­(Ïq˜H@ooµ ×â¢]\DL3 6šp¶m[ ýèGùó?¯^žÉ ?*Ç®õ$L&ƒp§õDÉáÈdê×ÍfðÎ÷Ã(¸!’—13–Í:×Cî™m÷w ‘|bFâÊ]KmŒõM›6ÑÙÙÉÅ_LKK [¶l¡¥¥…‹/¾¸Ù§ (JƒÌ$;à2¼P4‰{Šà'ÿvÍ%h•„­gĶïEñ”ÿ83öYÖåbû‰'¤$Èk(!Iû©tå²6ä¸Ôy¤{ ûä†Ygy9+o<÷5;Ïñþ‹×¤3Îýâõ—5^Œ÷o&3É(ŠÒ<Æb Ô(ÊÜFÛŠ¢€ÚEQfžpÛdï#\À «W‡ßÇÏãÜ•+ñ}Ÿ%KÞĪUÏÉåX,¹çž4¤<Ë Ä(×uq]Û¶y÷»ßÀ¾_þ7ÿtÿ»¹lÿ9uÕ*Ö{.¸ÿ~×ÎÒêäÑÑuÁ¶qœÀ[/“y#¼—P™Êf#Q*. f³‘hÉ'ÇL3Ò4!ß^¡˜ÉÈ‚]íºxVÉm˜ËE^ŠõÄ>Ãê$Ûů_Çðø ¬lŃp8Q¨9m;[K¥¡ÛŽ$|ŠghÜst¸ð§…Býåâ 9âç'÷;7Qo‡10%Âc__;vìsÇL›7oæÊ+¯äòË/§¥¥…¾¾>6oÞLKKËÔ]!EQfSm$„çLÅ%ðLyŠg\’HD”ð¢y`°²¯Ià}HeÛzy­Øú‘r[Öþ/Õ›Ô#Þâ•8ñn&ˆe"ÀN´.òMtÿZ¡v<Ì„ë7Õh›@QµŠ¢€ÚEQÔ(Š2]vÀãòÎ:kÈ6¶mcW”£%K–pòÉÇÕÍåøþ÷­³oÿóÙOò³r¸ëÏ?Ï¡G?À©o{/ÿŸÿ×½Ž")Üí±)ù%Îtk<ÝjŽ=’×^ÜqR(ª×KXT¨/Ö ]²-D¹$ë^ۚ宕›LV×»\Ê*ƒurжäÌå°X –IÖbqhý …Às3îeèyÁ²z`½ð¬B½´Ã…?N®ì±P›ãrªiHxìèè`ëÖ­\tÑElÞ¼€ÎÎΪxË6làãÿø¸c)ÿêW¿²¬¥¥…Ûo¿îî +ÕÆµ¡(s˜fØ› $g³i')ê`’ë0[©£C è™aJkEB›@dŒ{ýÕþЖ˜4rT{JÎ&âÞ¢Ù¢¡Ñˆâá:DHm(ŠCmÚE™h›@QP[ (Jóí@=ýG&ø{u\ñLÓÄuÝлÑ4MŽ9¦#GlLó˜!eýkÇ£¤Rkƒ/ÙlE52ùÒ—ö0ð¾kaùrX°€·˜=±ŽÀu;vpÇ©§VÔ)Ö­£çä÷â¿áj £ŽƒýÏ޹únàØ ìQ„Ǹ×`½Ðœ’³0žK0¼ÞІÙl òÉö Dâc¹yôÅ÷Îû/î ¯›ï¨xp ¶-ï͘3h]êy5Žt=ê]C¹ŽBüZ•JcÏ­(!okÅß±÷­k§‚ lÙ²…‹.º(ôjìëëã†n`Æ lÞ¼™>úÑÒÑÑQ•äµQ&Ó‹RQ”ÙÉ\¶6Ac¥½ò½Hà1X$òÆ:Ae¦NÓ<¡˜¸`8Ù”/bÂÈd°fç+jæ²-Pel¨PÔ(Š ¶@Q”é°ÃEK[Þßž‡mšUéwLÓÄó<’•¸¦iòØc&Ï=·tH.G€}{ªT2ÄFµm çusëß_È÷3ßøF~ð~½íÎ:ådþkà\þèþ~ðƒ@][õ,¬XAöž«±ï\M&•Ë¢Øn߱ؗTT'Yb¹yçµ¶ßE´«Eòº'ÁÊs3pûí"¶.Èi}ø‚À;3“©xBº¤RCÃnÆ=‰Hl¬EB}–Ë`ÿÄÓP<ÅC/žKP„ÅzHÈÓZ$lª„P…à»aåÆë!”ËÕ¹… ¿eZUê#eÕ’LÖ÷zÁ²ö5œépù)GÛÇu''/ãH^ž“ÅQÙé‚„­qD\Œ‹Ž]txC*Š¢(£#v¿@ e€^šã9¨Lp.ebH{k&0)Š¢(Š¢(Š¢(Š¢(@?+V¬¿ÛÀªÝÑzÉçhšfÕvqŽ,ï >x^¤ÒmßÀÕ/û  «å,J¿}3§Í0À0H}ö,r9"‘Ñ0B¥«XŒ„3!›¼à†¤ …È;/‘ˆ¶·¬út–…2Ífƒe®[_ȃ@L¥†æ=L&ƒ:¥ÓQ½ãB£iK¥@dͳ¯X êfšõ=É©8q‘w<ø~pý\wüû Óáé(LHx”8ɵ1’»»»‡ueVáQQ%Âç?—z/Î>’DÞ«ÍÀE…GEQEQEQEQ”i#‘à옂•Öî„Óª6“ðªõ¨{/å²Ë ”&Qéöì Þ|Ÿ•+y梋‚ÉîçŸ+VðòU»Q©âŠXì\†ãBÓúõQÙîŠÄ°U—¡Jñ"¬¥V°”mR©Hø‹ €ò4îyhÕÂY\ìóý ®µÂc¼¬8"¢•JcÔê墉áò8ZÖØC¤Ö»ÎRß®®±—Sﺌ‡Tª¾¸:ULHxqq`` \¶uëV HÚGG ³ª(Êl`º¾R©„ÛÈeÆ“"Ûì|“Sœ+ZQEQEQEQE©ƒ ¬{-Ú|¯¸Ú¶Í«_½tXaëG?z ƒ{~ñ n¾ä’Px¼óÀùλþš–÷¿Ÿ³ÿò/¹ä’ YãG>¶zˆ€åû‘÷b(*¾ó^ …¡^Éd$je³· BU\ìÁ,.àF$.Æë`AÎGÓ>xEݤñïÃyÕ¥RA¸U¼øöù| ö%“Õû‹AˆT µZK­ÀhÛõ…8Ó¬Ž<›ÉDbf½áUcÏ’b1(K„Ήx.ærã÷žKÝFB®ÁD‘‘Rÿ‰zlŽ• ---\sÍ5lÙ²…Ë/¿œË/¿œîîn®¹æšp›;vpà 7°eË®¹æš!aYEQæâÝèTþQÇ™6Çé“7‡9¾ïO«È:R=æfUQEQEQEQejȵK“É$ÉŠú&ú’ç¡V­¥§^¾>Ã0ØN™×/º€O?M&“á›nbÅÚÏðÌ3Ï„ÛN–rÁÃ4«…Ça…Ä– ®Íb``€ööö&_‰éÃ@…GE™o8Îô…hQEQEQE™ï 7½½žÀØÒÒ‚QÇÕ­6çÞ/î Ç7ù ¯XOª¿ß÷ùáȶm-œ°ðN9å”`cà ›7H$—ñ†ó¼È›0.5™Þ«°¶Îl+Õ¶¬j¯¹8Éd RÖ®«Í+hÕB[­ˆù§VôýèXƒƒõÌáÎQ¶•ÜxÖe¸Ã¼êkP,Ö9ßÚúԜǰ÷.ÁˆÞ'# œ²ŸËP5}‚LXxØ´i·Þz+·ÞzëqqóæÍüêW¿RÑQQ”YC#þp®ëÖ×ÄËNÖ;ŽC¶_@„GÏóFÍùmg8ÁÒ›ô͉_—|>?íù,Ó2í xìÀzè!Ç™7^Ð$-HQf ŽSä~¾2OLœ¢(Š¢(Š¢(JÓ‰¼Éˆ ˆ‹)@ÒЏfÖ(?Éd%iÌÝð‚ã O†Ë­ü –ëòÞ÷¾‘M›vqßógñF†º&JÑõæýû~´|8¡-¾ŸiFu® m»þ1¤ÜZ!Ñó¢|‘ò=>”Y-ߎ_›ƒQ<ãu”º-XÎ ÕÛÆPQ satþ"¤V]ø0«OàÖê‰cñ«ÈWö«¥ƒû.çâ8•åñ:¤+Ç‘º´W¾KvVÖÉ~R?7v\¿RŽ´ë<J_ ¶Éý5Xß&rÛMë+Û:°ì§ËÆp¢#ÓðÐÝÝMww7;vì¨Z¾aƆ+§(Š24" NTD7ñvôÎw¼X@W³+¡(£àºÕ¹!âË%Düsœb1Z>ÝIÒg"S2SSQEQEQE–Ú‘<ñv4‰r<œzê©$Ab…°Ÿ›Í†3i;;;Ãõ÷ÿú×üä«_Ïã?ÿóÇœpÂóäÉP¼su¸Mª7C®¸­zùãaTexn¤<ƒ¶ ™µýukE= ‘ZÏó0¸.u®]aPã×ÃO,v]Ñ:ŸgˆG‰ä€ ñÁý~P¾iFÞ•¡\$ëˆ}/|í"]–Hì“—ˆ“¥š}„va¯"–J•{Ÿ­÷€T‹ŽéÊ~^¥Ì,dó+•}Ú ÄÂD¥…Êv+*e—*ë AñZ ?X—ý#po©lgVŽQ 8@ –÷,§Q&,<îØ±Û¶¹êª«¸êª«¸üò˹á†&Zܼ¢v\Q”æ!ÿ2\ÎF×uCGÏó°, Ó4±mÏóB@ß÷q]·J”B±RÄK ÑšN§C12ŸÏ“N§Éçó‹E‰®ëŽè ™H$ðŸÇóŸ§5>~¤nâ}*×&;\l¨’EJü磄îðýHH,•ꋊñ/ñ‰£Åb4k2Ÿ:ƒ²–x'¬XŒÊtÝÑ=³ÙhßÑ"JÇg™Ž—¸È:\hEQEQEQ¦žÚîØ<ðøüç‡ßÞ­/¼…ýÍXœÔ×_{-_û½¿ñ\¾vme‹íÛW`\ðÜÇNˈOÂNxŒ ‰ˆ†µÂa¹ÕÑóêOþH¾ ¬¥C—['ïùOP=ÐꃱLp‚cÔóDŒ2K‡_ϧ ½Ü+¡+öžší¼Ê+>PçøOD}lÓóa.Kચ®|/y&+ß]"Ñ/A ò+Û§+¯ Ð ,¨¬wˆê$X]À#DÞ‰À®ìWŒ½*Çë êN r]`þgeY?[m¡R¾ V¾§€r¥ÞåJ}Î Êw>Z9V lš•w襇h”…ݱ££ƒ}ûöqÍ5×ÐÖÖFgg'´´´hxÕñ 3Ò/,†çy8ŽCªÖ¿XQ”IAÆhÍ#ìû~ÝXí"èY–…ïûØ•©?†aT…\5 ×uI$$“IŠÅ"©TŠb±î#¢œmÛU^Š2™!›Í†Þ…¦i^ƒƒa]VïÝKë;Þzþµ··W ‚RñÀÌår8ŽzQÆÅU ‘Íf)‹aýåœ ÃÀ÷}ºººH&“´··ÓÚÚŠeY”J%lÛ½-Ë E>¹6"œŠ¯«iš$ LÓÄ0 lÛ¦½½=¬¿eYd2™pÂÑ¡C‡Â{ uM§Ó¡ ëû>¦i†âfí½ÁU®ÔÙqŠÅ"¦i’ÉdBûnÛ6¹šiU²¿ËuÝPtÎåraâñÚg§½½\.‡išahÞB¡^£b±H.— Ë–kŸÏç)—ËaY®ë†õëÿ¢L”l6èHF úårA‡*þY¸xçÇqARÌV\D“™$@—Ç;žX^ˆ pñœ#Õ7™ B¹HŽ˪^gÁ‚àø¶tV¤—H@P§D"ªc6œ·®1³<"޼r¹(M.‰£år°Þó¢:Êu’ó®m*«T*ú¬(Š¢(Š¢(Š¢ŒQÛô½ïqèºëFÜVúÃu‰ ÿÒÙÉ—zæ1÷ó™»îâìG9õÝïæ”§–qøð 2]oÒÿ•¡=éŸf2Õ"dmxT™Ü6 û°¶õ#½{*+ÂSÿ'àÜ îÕçcü´òa7Ø'ëŠ`Þ¶èš%0Ø¿8^y&X/‚½@l×Qzïó2BÐhÒmà.©¤’àoV¥ÌQHR3(ÃŒÞàp €ÓÜö›*ûÚ•ò­XYÄ>±ò<P–‰H(ýì~qÒŠÎ$X{¡üà¥Áî­ÔBoC "¡²¿òžªÔM†+“±} ­šuñú›ÀÕÀS•}òÀùÑ}¥fl`íçÖ²öÖÒûúúèîîæÆodÓ¦M´µµqùå— ¹ªT#ƒÖcEÂ*Š2uÄþ?1Æ»oEè©õzËf³† X–e…¢˜|Îf³¡çc2™$ŸÏ‡¢‘xçA`7d¹|áNÞ“É$¥R‰r¹Šaét<=K–À)§pÏ=÷°«"xÉ~år91¥|ßD4M¥R¡H×ÕÕn/ž•===¡0hš&ÉdÓ4ÃÏrþŽVÕd2I2™Ä¶mZ[[I¥R¡˜N§1 ƒ®®. ൵•B¡z‹æóyR©Txíe}>Ÿ§«+ 0ºeûvæ8á’Éd(Øåóy2™ ©T*WS©™L&3™ ¾ï“H$hmm %"_*•"—Ë…ž—¶mcšfèýiY©TŠ|>O6›Å²¬ÐëÕqœÐû5›Í†¢ªÍ"ʦR©ª0¸òˆ „âi¼n‚Ô?.0‹E<ÏãœsÎáu¯{]³~Ê,Àuƒ~ÐH¡Xâb\>_ÝYqœh߸§ž$ƒwœ¡ž…µž{ñdöµeÄë(ËâuK3JŽ'ù$¤Þ"X¶¶*9'9nm½¥rN"¸Æ…OFE„”P²ñNŸ?Þ9_“x]7ã‚«çõmo¶Ñ·öœW®ßó (Š¢(Š¢(Š¢DŽ}Ë—/g/°hÿ~¨äh+©Q‡Ñó8›Ý»Ïä;¼™Eó7,yö8ï<.9iÿüÏAŸ®µuø ­ñI»–U=y5œT{X4ò‰•¿î'*ßóDÂã=à>Y3ÉÕ È,w7pg hæpBeùîÊ>E°Î„òÕ•ò}BÍ;n샕m+"ŸiyZ` Ætç ¼ú•mÝÊ»x–ÅAë ðªèq{Xë*ûËñpÞ)ÉJ9^¥L‡Hä«›UžQ)×£JÀt߉۠÷/Á®î$c…ê}(02cðY ½MÇ0ø}àŒ¬ÝÙ$á`Íš5UËÛÚÚTxñrË6†aà8Ž Š2ÅÄÇ·­qî÷òqMÄ- Ã3«&¶‚ˆO"€‰7Z2™$›Í’L&CQNÄ2€\.ÇŠ+Èår´¶¶†^q¦i’ËåðŸÇ4ͰN¥R‰žžž°Ód{.-Ë ½îd}­÷§mÛ$“Ép}ü3@OO4ÕI„ÍT*Ö¯\.‡Ÿ*¯=Ó4éííÅ0Œ½Ã ÃÅN9ãu‹—÷LM&“¡È+u—{'ÇŸ{{{{(Ê}, ¡Øêº.…BT*…ïû¬_¿>´ù™L&ôJŒ? "V—J¥Pä, ¡·¨ˆ½–e…ák% ¬ïûôôôàºnèõ™L&¹ýöÛY¶¬ñdÑÊÜG<m»Z„ÌfƒŽK½fŠ$iê uñæPmÓ(.Æ¿{^õLMùœLB: ’2c´£ÅbPoIPÏwß×q‚mÄKSÌ„ëÇŒ×AŽkYCóMHh:ÎÍ#†`ÿeÄ;vÅbt®õÄ×ø±ã÷Ç0"QV„ß /DQEQEQE™ «V­b/pÂÃÃÙg×ݦJ¨«tH3»º/X,rÒwá WrÙ÷?Æ‘Ä'èí-€a„z¦ôÇãýS¡0Œ8%}y„Hc ø×ToS.ƒõm‚Ñ4¸åMaA] ækÀþÈôxVB¨b€»8œB Ìù€…Q(Ð;+,»;aPľÊ6–VxEP. Ï!¸µÁzŠO@Ò¨,·„>wXO <æ¢zæ‚Â…èYúw`]u™#"CÏÅ*‘ÑaŸa›%¤mÝMã ñ(L™ÌÈ“´õñ_ñ«»~Źœ;áãM8Ôª2~âD" Ä×A~Q¶/¦áÂ8*ŠÒ8nûŠ' †¾”IâÝX+L ¶m‡b™†qñKÂuÚ¶M&“!ŸÏW v"ú‰èïiš&…BM+‚Ó{÷îeÕªUahR *©µxá …Ð S<ø¤¼ÚºË ¨*4NmèQËþTľ¸¸hÛ#ÿûf[ZZª¾ÇÏ'~Mê!"àpǨݷ««+ “*bn*•ª+Ілñã W~2™ EËøñj¯­xgÊäy!ºïÇwÝÝÝ(J=²ÙÈk1þsM$ ««Ú³1nâBa\d4ͨakÑçxîF)'.ü¹nt,ɹX¯q/Ç0ª…·¸HßÞ²ªÏ#~Lê¥'“‰BœÆë#:ñjŒ¯‹{wFuxT¹ÆŽx(ö÷Gç"×RBèÔ–?×ZT¶‘òeûd²Ú£SQEQEQE™»Î9€E‹ê»ær59K%H&ÃþÙß­¾”£þìd€ »v±æè§xõ«_ǺuŸ Ç‹Ä{Q> ¦ æªàs±/—«Ž$ýÃ쟃u¸½CC­ö.c1Pó³à¾‰NLˆ~àuhî‡Ä.\,Ã<°þ xø—Êrñ@4ˆ¼÷7Wz °“@,$( —€y‘ÐgxôYÁzº‚÷L Üv0$”©ø4È~åØgñ>\¥À:rß>—娘 /6Ž‚=šÀ9CØw⾆öWáqšð}?Ì¿C…Ç|>O©T ½žz{{Ãõëׯ¯ò¶QRQ&ê¼Ç£Ï ÷P–ÉvUrìô›a†×$§_*•ªìj…¤ZlÛ†íÛÙ¹s'û–/gÕªU#Öò¬°â=9ætª¨ÓšÉDÎS®cmè×zŒ×«},9ã¡mGy%N"ufD̲íHÔÏ¿‘"ÆË~qL¸¸€æ8ø%"œaD^ˆB*ÔGŽïûÕ35k…Jé„ÅCÈd2‘çºÁqDüÍ+2Ÿ:b¦Õݶ#oOùnYÁwÉ©!õJ&£ð°rí':/Y/¢bmØÙxGY'ß}?8çÖÖh{¹Æµ9<äšÕzV:¼ë]Ó÷Œ)Š¢(Š¢(Š¢Ì5ž®Lú|)ÙìÐ\ŽÙl(7Žƒã¤°Víæm¿ù Ÿ¸ë.n?xßàó=¿ËÙgg8昅Pñ8sÝê>ªLÒ5MàóQ±® d!ëV‹•ž,sÄêRés›û“æÀþBl½E൑ ¶-JŸµ«²ÜÞS©˜Øiˆ„>QPL2[óÁ\™ø[.ØfÈ(VŽê¨±HDŽ ![Kí0kI¼µ)O¦Ë‚žžÆËÏñä|ëM$óü ÏshÉ¡†ŽwÔôÚüÅqÖ¯_çyaŽ2ñŒJ$8ŽzII(Åø@´„ÆK$$‰qåˆTel8cÝÎqÂW±X EGñ2áQ¼GGóäƒH˜N`é‹-â™gžáé§Ÿ1¬¦ä#+âÅ9ÓÙ¿?O?ýtSŽ-áPGó*\×2ÉEQjÉf£Y‘ÃQ+ЉˆeYQç©ÖsNö1ÍHt”öâS´ªÎ ‘Wc©u$âåJ^C$Ù›±Î\%emÕìÅø¹šfuØSÑçEL¤¼Ba¨¤ˆˆ’/£X*Ê–J‘‡gü\ã"¢ìW›QB¶ú~Pw'åX’Rr7ÆC®Æ…]¹^µtuÕ_®(Š¢(Š¢(Š¢ŒŸÅ‹±õ±*Z{ɽX«vcàóå‡âòmÛÂM.¹ä=üæ7V½ß‘àM&°Ré;wŸÃáŸ"AÈÓ]@%ÂNùK@rok)‘ééÊç ¡÷¢„‡K­¬,/ñaL 9šRÑ$ßÙ^¼+“ŽÝCÁr¸bÛ7Ì8ÌЩ ©ŽwØ+™ŒÆ‰¼ “ Æ ¦ó؆œ¯ˆÖS=¬ÛðxÕUWqú駇¯-[¶ÐÝÝ]µL^s™R©4d™çy”J¥P0L¥RaŽ2ñD"‘HA޳þþþ!! 3™L•ؘmƯAQæ8Å1n'9ó ðfƒ(ßpù ‡c:<Ñ–,YÀ®}ûFôx”p s‡~˜C‡›¡3QjC¢N'òlI>Oen "ÕX)£í§~ÁxNC =*ÇŽÚmDsœ Á7m"®Aµ·¡ä@,‘Pê)‚žl'ž“…Bµ÷¥4‹r¹¡aJâ3:ãž~"âÉ÷øµŒ{jÊ6â-)yÒé¡9&ãç?¦xqÊö"zÊ:¹Žòó”sp8RŽˆ´rý$,«\%]7Ø7²5Žö­D‹Å ¤«mÃc<ö‡JQEQEQE©ËÒ¥GQo¨/÷¡ÝÕ *4ëà)Þw.=ÇžÉ k×RX¾œÿ}õ«8ÿüWsÿý•¾Zebjn]ð5æI‡›:`žTYnˆŽ@;íx8§@ë?‚Û ,!ðFŒç Œ{A?Ü{ye,OǯꇗÇÐ ¶càì Êò_¨ß¿2aw¬ F“œ›ä'T=L'–w´“Á„„Ç5kÖpÍ5׌ë5\wÝu¡Pyùå—³cÇŽ!ÛuttpÎ9çpúé§sÝu×Ñ××7µWh Ô%¿W:¦P( Ç¡T*ÑÕÕEOOÏõq,Ë¢§§‡žž2™L˜óQ=•¹F3쀌­ÕéCr:J^ÇxžCÉXu8¦ËîÎ;ïÓQxœëˆ;4Û#ÔqœYju6· &›¸ð÷òޏØ&yaxá±öñˆ{0ÖsȖ܆R7 ùY›ÏQ:"Éd$¾‰àX›ÿ1Žˆƒù|$bšfð]¼%k.\ ]*?9 =êyA}Ëå¨qKå\Ëåèú¸nä (ßãb¥aD¡Q!8G ež„]›€ø=,£s™†R¿l6:çx¸Ú\®:|Œl/·2­ªnr~B¹¼¤n©,i0|ÊT2[0쀢Ìg´M ( ¨-PeæÛ‘4œl¬–Q?xp€<¬µOrhùrZÖ®eé«_ÍÂ'žÀZëkW&ìfÿpÀé¨ôg]H‚Ô² fØëÅÝ`® ¶Ç 4Cwi¥®k ¹‡ c° sY¥nB‘±Tg{ÍÉ$‡F/vEØœ”ënŽÏs¯µµ:Qm_{:i†´#˜dü`*™PŽÇ5kÖ°yóæI­È•W^ À­·Þ @gg'W^y%ßûÞ÷hiiÃÑÙÙÉæÍ›Y³f \wÝuÜ~ûíS¥†ÁuÝ*áÑ÷} ÃÀu]’Éd]/¢T*E©TÂ4Íp@x¬ÃÉd’t:ÍúõëI&“ …ÐRòCÆ=¯e6Ñ ; ÂãXm½„¯‘QÂ¥š¦Ú‚±„O.–,YÂþ7¼•xóó•×9Òì*L+¶m“ÏçG ÷;S™­m‚© žÇa,![Ä«®\ŽD>)GD¬l6øœJUçCa o¹¸ø(Š|>X.uMò?ÆÅÎb1è¨d2Õ¹!j`‹×Ÿ'. JY¥RµXY,F9%ô(D^€µ×¯TªÌÔô¢²Elô¼àzØv”¯1‘ˆ¶ #$M3:©Skkuùñ|¶…X-•"¡W¼<åºÅÏ1žRDH9†eŸe?ˆ¼A³Ùêð©]]QýÊå üD" ©bYA^xáµ¼óÏ7ûQ¯Ëh¶`¾ØE™Ïh›@QP[ (Ê̳’ö7H¦h¦ßþøã$ü'þçNǸ/P»’I(ñè}üéñxŸy:ïI¥ð-›ž«Áèú¸¶ œHÕó!ð–>oC.þýP˜Y ö°> ü‚TÌvàSAåý逸%††25€XùúâX&ôi'*ØÅe‹F‡¬Æ[9žLx†æx>Æ'4O÷qk¯ÅT1!á±ÝÝÝá,ƒ 6ÐÖÖ6æ}wìØÁŽ;¸ýöÛÙ°a7näœsΡ»»›‹.º€­[·²iÓ&6mÚÀ-·Ü‚mÛlݺ5Üfºq*#h~1NS.—)•JÃæö2M“žžžpßñ’L&Ã|²Õ4Í0tëhÞV¥R Ã00M“öövººº4ŸÒtši¤±Pkoe"Aí2¯òÏÐÕÕæxá&!ž~'Ÿ<Cé5+Çc³1 ƒr3³dOÙÜ& ¾+V„ë"³Ïd›xsA>‹Ñì< µY{»ãaTãj;B’Ðu«óÊv©TpŒÚ$öPÝPáM„4 #Ê7Xé“…9DX•}¥ó’ËEç(õO&ATŽ%9"“IX¿¾Z´‘NÄ?ñ^”õ"À‰xY(D³6EŒ›sË B“ŠX+ç”Ëey^4Ó2îjÛÑ9ú~õz)_¼*ã9kÃØÊ9Ëg%'¥Âº‚w);Ž:S"H‹øx×]Ë€§¦ô¹Ÿc±³Õ(Š26æz›@Q”±¡¶@Q”™hÂÑÂJG.Üv/<8ÌöÙƒ‹u臘î‚]]° øxË?ƒe°m\òÿås£CxÀcr ÞiÂáIÀZ ¬$8%àoÁÈ‚±è,0×BþAÞ^È÷Wúÿ`C>Q=n€1¼7¡ô9'J>?4rÐD¯ïG.+@õøÆt"RÌtK2Óy¼†r< „îËW]utttpÕUWqÎ9çÐÑÑÁÀÀÀ¨å´´´pÍ5ׄ†£;vì ¯¯¯JÐ\³f 6là˜¾+Vƒñð‹íííø¾?¢×“a³(¡[E0ìêê¢\.‡"Ép‚¦ã8äóyÚÛÛioogýúõU›Þ2»ëºäóyÖ¯_ß´k­Ìmši ‚ãµ’a>öOê8Žã„!V!˜ÿ'“Éåí(,^¼˜“N:©ñ‚f!û÷£„èžiBøX˜Ím‚‘ˆ‡±Æ|mxÌÑR8ך—¸§Ÿ BŸ”)d³Õå‹È÷Š¬Ì¥‘Ç'ž Q:†ÔG<}?ê8ˆYOÈR©:ß$DIÔ㞃îDê÷foÉx”xYèÎQ bŸ\oÙ'>[S„@Iêî8Á{OOt­EàËåªC›–JAùñœ“"œÊ5("³T –ů·„S•k%Ë¥®RÙFDLˆBØJøZPŃ´§'ºFr]L3“É(D¬mÃîÝ33 ÷h¶`6ÚEQÆÇ\m(Š2>Ô(Š2ì€\ºz!mûö!3¿´äR~~×'‚Žšô™>˜GWú÷AÎÆE@>pžÈn ÀOòoe nnJ‰ÂS‹ô/¥Ñ­¡TŠÒ4˜n¯GÙ&ìñ800À•W^ÉŽ;Ø´immm¡[óÀÀÝÝÝlÙ²…îîn¾øÅ/†ëêݺcÇöíÛGggg•çä¾}û†xR.[¶¬n<çéBD>y—Ћâ•8•ÔŠâ}ÕÚÚŠçy¡£çy´¶¶†9! …©T Ïó(‹aèÈõëדÉdH&“´¶¶bÛ6¾ï‡B‹ `‹Å!ác]×з;™L†^£³q \iœfÛ› ºÀpH^V~ õ„ú™è9| 'pÆg°hÑ¢fWeÚY÷È#ìÙ³'p/›gÌÖ«Ð|[0UÈœ × D5ƒd¹x­Õ¦|–›òY±ZMÌ`£÷Ê“òÛÛ«ÅMñH”ÏŽ…çkMòŠa­—a½yRÏ‹:µ‚j<„k<÷£ì'aPã9ã"g\ÐANʇ •ãŠ@+¡HÅkPê/¢«|ÃߨÕç’H Á™ÉëòùÈSÊ‘P<5åºKøWÛγ½=X'Âd¹ ·årP†Ÿóda>=B]–J%òù<Éd’\=Ë8Ì=‹0$Bk©TsÙSGà‰'õá}®YfĶw*등ånååk¯ü¯ÿbÁ«_Ý´ó Sa}ôQ®ºê*.ºè¢0ì‘ j…GÇqB±^ðò.Ö/þ1ÿîîåƒ.¸@(;À:ð ü3´€ñàfÀû\0ßC¨„º¯ ÄÊÔ‡†z%šf¥'›ú™i¤”0q$jQ#4º#‹A¿^&07cˆW„Ïéœ'Þ®#Ýoù5Ú&˜ðØ××Ggg'×\s͈¹ÛÚÚØ´i[¶l³!?ùîîn®ºê*ZZZFý±ÆÊ•+¹ôÒKÇ•wr$Ä;жíP\s]Çqš&:Æ)—ˤÓiÇÁ¶mÇ¡'>Å?†x5ŠphFèÑXOXoÈ ‚ Ô"ÌyžG¢/.."‹Åð³išäóù*OGÅ“,›Í’N§Ã:¤+A—}ß'•JQ*•B¡Ò¶í0f2™ÑSòšÎN¾ñWEº½\.‡K 2žÇׯ¾šw]x!  þß7¿É“ŸûÇ]z)Gß~;o¹üò°ŸJâ`¡O¾ž}–ûXµjh¸2¯²ŸU³Ì !½<"1ѧúOŒÊþ^Ír;V†E ,åt;â=_Šo~3=ûìd=nSÂTØ€µk×ÖíH•kWûŽE–gÙ›î))ÄV­Z5/…ÇN8¡ÙU˜±Üzë­tww‡õ™ÊlhŒDÜCªÁ‘ÙñpœqϽ8µ T•jÃwÊòl6ø<8åYâž–R¯¸·Ÿˆ`Ò)I$¢Ùqµ6DJÜDú~TV­×¦ìgYx—JËÒéàÝ÷ƒãIó*îÝ纑'&ÛHJê ûå󑢄W0‘禬·¬(çe\´•åétP¦œ‡"ŠÊ¶’W3޶]¿¾þLÓ¸PlÛÁ>½½Á~r>ñP­Ò‘ˆ‹Â’wSB±œ{îJR©[éèèÿÃ=ÍÔ³kÖ¬i¨Ì“O>YBáýª«®jvUFdªúoûÛuò¢ ýƒéê(ÊLFr#Î×6Ápc†ÃñÈ#°xõj`èxb-é/Ÿ|8û•`Ÿ?v+Î'¾æ«\zÞÛ z8X©ß€/à€³ ¼‡ õ±þ¼žK•ÇŠõ ÿëºA?´^T£Fƒ 6*Šàï³N'2á8‘úüÍ-+š°<ÝÄÇŠê±yóæIiL(Çc__À˜~Ô²ÍH±”ûúú†¸<·µµÑÖÖ6äë¹FO÷ÌDñÜ+—ˤR),Ë E‰™ßM¼%'a#Šr½½½ôöö†^\™LfXo.˲èíí¥\.ÓßßO&“!“ÉËå( ÒÛÛK*•"ŸÏ“Éd( a¾1ù,Ç”´©TŠT*EWWWèé˜)¸eǾõóŸÓÕÕÅãçŸO²«‹žÁAR½½…¯þò—)Ò꺜¸};¯Û¶ãî½—wíÚEH'>ý4Ÿß´‰C;v·, Ð lÙ¾¬apß÷¿O6“!söÙ<ÿçýýÐÛË1ý(ŸºürÀµdúûyßÁƒlÙ¾/Þ?÷ß?í@Âóø¿ÝÝÜöÀ|s×.À:ÄÝwßÍn»Kž}–C‡Qîïgç“OòÜCñ«Ÿü„ x ÁËGàCÏ>K>ùõ¯ó¥{ï¥×ó(û>ý@Ð[Y_®¼V–wUÖõV¾—þÊ{Ž@€ì¬Éð‡Ÿdf‚ˆOðÉâÁëû~øüŠ×ãl`vÔrjX´hÛ·oov5”q2lÁd‘H¹¸pU *Â]<4(T7Deè/JŠx'å '\Ö¤•¨b¤ýË 2Ï Ž'†PZÔ²±0r5^ =*ûºnä±çûQÒwÙ7‘ˆD4 C+ëâalÅ#3ž4Þ4ƒzŠ Ï ™JÞŠñp#"¾Š¢†ÅâÐÎt줹%9/$tŠiǰ¬è|ExÍf#¯K #kYA]åÜãágåØñºÅ1Œèù‰ ɵ÷o¦3V[0Ó퀢(g.µ E™8j E™‰v ¿¿ŸU»w³xñbƬ[<?ÿÉÏùƒuÀÕtòâ³À»^x–äíù§²6˜¯óLB•³¼ 0£È@‚äð«ç/aÛQÔžFH¥ê‡f+ Dc%?¦iC& ‹„“ÏO¸S©G<ýÊt’Ï’‹t’˜ð(?è±Ì4–mFRH·nÝÊ•W^9b92ó¨VÀìîînxÆóxq]·J`´,‹®®®¦†å¬Å¶íÐ s´œ‰ãPÄÛÐ0ŒÐûOÄC!“ÉÐÕÕE&“!•JQ.—ñ;•"Y.“% *!B‹€cÛ==˜]]´·œr o^³†b2ÉüÇ”l›V"/¿“ÿøùu>Ϲïz¯|æíÙÃ`OwW¼k»ãŽý³?ãû÷ÝÇ—–,áŠóÎã¯}”®R‰kººèõýP¸ü+B±Î[°€T:¹~=kÿàXð¶·ñ¦K/å/Ëe®üÊWxõÇ?N.Ÿ§ß0è5M žÇ‹¿û»l{Ýë(§Ür ×^ËêüGþïÒ¥|é¥/eû‰'rûK^ÂÛÚ¸çw~ŠE2¾OÎ÷1òy>¼f ÿwéRÚ,`Á‚t\{-ï{Ó›X¿~=+V¬ ‘Hoo§˜ÍR*•H$댋÷^%0xŠêLd&ØÚ†‚xK.TÓ4Éår³:ž¢Ìtf‚-h‘„ø_¬ˆF’#QáÑ÷£ªñý$\f<ôgmÇ"Žü- ×xŽ{ Æ›årý8ÿR¾wår ¨IžBÀ$k<øƒÌ"”Ï™LÐA‘&ƒxbÆÿÊä¥n™LuxSï$!|¼~µ×]@ k꺑èºÕתµ5 7#Ç”uòªl¥üzù!â×Áó"oHyl;Å+RÎŲªÃ­ÆÏ'27NüúÄŸ¹øþqat¦;îf f²Per˜ímEQ&µŠ¢ÌD;000ÀÚ^=ãýÈ8årÐó.üÏ®ZÅ ëÿ„¿xßçøîñÀú…ë9øì)Qþ§ãÀó€ öµú˨ÌDg4·¶/,iEjqœ(ºP#È„ÙÙˆ„›-ƒûÒ¬~ñp“ɧëØ#MFŸ,&$<ÊY<GB¶)dÁE]ÄÀÀ[¶l —‰;g|¿M›6ÑÙÙþ°·lÙBKK _|ñÔ_)ÖJ¥*áQ< gB˜UA¼‹Åâ¨Âc-‘(˜'˜YQª¼g ¼å½µò^"²Þ0p’IØÇ°¾òJW¶o­¼ÖWŽ#öÕ"ÊU(^|ò¹ŸÈÓ/GäÑ÷?--ü÷ðàe—ñÎ{ï%}ÓM€‡~ï÷øÒûÞÇ[Î:‹$ðÅU«¸ñÕ¯sCÖ]E¬3 ƒB¡zxöôôP.—COV%ôf*•¢··ß÷q‡R©Š®ò ½Bs¹étš+V°bÅ òù<¹\Žþþþðxýýý¡whOO©T Ó4q]—b±ˆa¤ÓiÚÛÛI$¤Óé0h>Ÿ'›Í†¯õëדN§I§Ó<üðÃÍ~D‡0Óì€ëºáK~ûò»·m{Fx7+cã /lv”q0ÓlÁx©-'^mµ‚QmH YoüI9qA2žKAšÅbýÙjÉd$lÅË{ÆC¬J8RÓ^„„`ñГãʹI^¼ ¥ "B§äŽˆ‹t"J™–Ô÷ƒ¢R÷¸çaü=ŸDE¹žqïJɇ÷,ŒçE„èʼn «‚ÜÃx85Å›1â´^®Mñä”ïñ{`ET•cˆ§küØñg(~=ãÏ•xOÊ5ˆ ˜3ýol,¶`¦ÚEQ&‡ÙÞ&PerP[ (ÊŒ´¥'~ÿûœµmâŠÔÞô%kI$à´Ó0Ï]É{÷2ðŠwqû?ÝÇÿî_Èï.[ÎoüÅÁÀºƳ`­" >?ðzÄ‚bwµPeYѤåÚáíáúòñíj£ý ·ÏT Bl3‰ÈÜ—\®yui–OËt Êñ¸qãF H:;Z>„ÎÎΪ}ê±fÍn¼ñFn¸áŠÅ"Ë–-£¯¯k®¹¦*œëæÍ›¹òÊ+¹üòËiii¡¯¯oR“ÈŽ„ïû´··cÛvèñ×l$O Kàáf †6,—¹ûî»ùâu×…ûˆ}‰4O$´É:“(4´œeèÙH º•÷\e¿te]’H8ô DCÙ?U)ϯli¢E’(éX¨§Û3-™L’Ïçq]—®®®P˜®­S&“!™L†90ãuo?˲H&«¯†„Ô…@7 ƒ\.G6›%“É„a€%Lhkk+/{Ù˦õšŒ…™l<ÏòWÐW¦Ÿ%K–ðÙÏ~–GO;­ÙUQÆÁL¶Ã!^rõf ÆC^JãV­xøMËÄÔˆÈ/³V””ƒz´ž€&9ã¹ýâ$AˆÑxHØb1xI¾A%¼i¼.ííÁþ†­O&£P§â=èûAâ¡AS©(¿£äEJñÖ¯¯?QÊá´T ʪõ”|”¥R$ÀIžIN‹Å œB!òF),~¹\ä9(÷T±ÆÔ‹ø÷`”ò%Ÿ¥„€•}â9qQ9Þœˆç~”k(eJùñ`"îÆ¯ÏLf,¶`&ÙEQ&ŸÙØ&PeòQ[ (ÊŒ´¥†Ìž1¤/YÉåø£=Ë[^ß‚iš¼¼ürÎ<ó(xÎ~b9Û_$dw€0W0F‡2™ ß˜ÏWG‚hŒ¢¶ß—LF‘¥¯,“fK¥é›œšÏ7ªu2~}6;ôúMÍê—OWö° ’´uË–-lܸ‘‹.º¨îv[·neË–-lÚ´iÔø¦M›hkk =$׬Y3Ä º¥¥…Ûo¿= ÛºqãÆik@¸®‹a8ŽCy¦¸T‹¢0• ÈØG Þ &!°’‹N„B œ‘­l—#»*åŽ÷wV¨¼â$Gøn ó>©×/6:;Ý‘â8“‘'°ÖûÎó¼ðüë…ÿíï‰¢›aDD¯EÄ\ñ U¡qö±dÉN;í4mvE”q3Ó۵ąDÚxE*.JNFªjçÊÔŠQòYÊsÝ(tjü³„PೈQò÷ÿ{hm „/ õ)ñ:%QÇ¥64Ô%W„ŒâÙ'ï².æU:;"$J>H™cÑ …h†§äi”å2«4•ŠÎ1“‰>Çó'æóÑuïL¹RF\4Œßƒb1³ÙjD¹G‰|Ò”P¹R¦4%ãaë=Cõ¨ ã+Œußy½ŠÑlÁL²Š¢L ³­M (ÊÔ ¶@Q”g*ïâs¹hÂiˆ¸íÞ½ ï'p*G±páBVö¯ÀzìuàgÁÈ@é>pw<#y"Šh&ŸãH¿·V|” Á0tìa:CŽJ„£xtŸé"— ÆJ¤¯ßÌ$Óéegº†¸'$„J•Шµ³!¥î]]A'JBšJ®Äööàs2yŠçd:=4Äk܃°VX« ¦6,i½<ñòëÍô”²e}<†©Éd”—ª;añzЍ(ÛS1×g,¿x3’µžhYï™PEQEQEQ&×­¤Ù÷yÌŸþ¼Ì‚C>wý¯<±è ¼ô ´}§]{Gæk}° JðŽ«"Ú~u™¾_ÝßâPãx^4‰v8$"’LŠžÎaÏx$§éÈ5X‹D2’ˆQózyA§‚£Ù¹¥¥…Í›7óÓŸþ”[o½µêõÓŸþtNÅRw]wZ<È,¯$ ƒ*ãIÕymt }$ÇÁ÷ýy'<š¦‰a”J¥ywïûC¼“Óíû?™çÓì (ÊGBŒB$t¹nuÞÆL&ªâ³ùŠÅ(±y6[ÝàA2™Œò-@u.Æx^IéŒ@$ Æ·éꊄGñD”ºf³‘£ B¨aDábÄRrJʹąAˆ:?²Ü0"QQ<3¥\¹f†…Q×Cö‘r¤ƒR(D³>ã9EÌ•ÏÒt‹7¬ã÷ ™Œ¶‰o/u‚àÚ5c.ÏXþvââáhûÚ,PEQEQE™\ê:~ìÜt<ëÃY)2Koæ—Ï,¡ð‹A^µãU@à$Pü¹I°`¬*ýâx¸ÖB!èËÉøA-2ñ·–Ñ„D³€êq†é¹fQ?¾™~32i{– œ0–Uß‹v²™°Çc-s)”ïû±‘œb±ˆçySîAVë•3{eŽæ"b‘ÛŒ)3Éë8›…²é&>ëyétšT*>C*âÎ^TtU¦Šb1òæ‹›ã93™ ?$×AC;ÞÀwœ@ko<%Üi|Ÿ\®~è "!T$Tk"Õ7ŸêT/,©aDéÜHî!úUÖÅEÒZL3ð~”Ù„’Óq¢GWW:¶ÖëÒq††Ž‘kS.W{Æë9Üß`<Ôjj.Çžá¼EQEQEQ”‰cÆ ƒ5=èÀk2übà$þ(=½€½WïåÔïŸ gw•‰ºþ£ÀYacHŸ8 ßö£þu\<‹¯öty“¾i³†[elDRÅÌ7âé_¦’†<ÇBGG§Ÿ~úÔŸÉ$RŠMð ÓÅ” ³‘¸ðX,±,‹Ô4M‰Wycò(M·åRæ ÒxPÁQQ”áˆÏ”!2Ñq"±1NTÄBah‡Áq/G4ãbc±¼r¹ Q.¤’/RˆÏړШñºJ2yßB®JžI¥1ïÄÈ9Hã\:?Ú5.¸ÆEKQ-+8FWW$>Ö†i… LéÃÅEÊøgÉ¡©(Š¢(Š¢(Š¢(ÓE|Nqí¸¡É¯)¿ö,¯tXÏJA¿âäËðŠÅƒüèŒgÁ÷xÈn ö3Œá'+[V©Ö3Q¢-ÕëeHs>{JnKçã5˜.Tx¬ƒëºø•_r±Xœ¶•ó0—é”aš&žNYP&@m˜„¹ä5;ÏB–+Ê´! UIÈÿûÉfƒÆl*u’¯¡V\Œw"|?ãÔ†jÁ0‘Þãù !ãh‰è8q±Tr=:N°,“‰HÛŽê%"+œxhY\ëÍÆ4ŒÈS¾ ¶KJEQEQEQE™©Ô ¥{O¦õ¿/Ç-yÐÓç`‘AžuüÏÿüÙÕßcû«¾5x¤_ C£ûÈ„]™à\»_¼>R©hì@&HO¹\ó&‹èÁø† S‡ uð}×uq*ñ¦ËÛêzT+À®ŒvÎ%ÑH™₵išá³4[Ñ_€¢L ñ¦4þEx¬5ÙlãPÌ‹~",JY"PÆÉåꇕN‡„6OH)OŽ)áEEÜK&£Y•ñ<•²o¼üT*ÊçG–É ËÚ»˜¶yYƱ¬h¹ižŠ¢(Š¢(Š¢(Š2ÓI¥RäD!”YÆÏõß·ÅÊë­A'|ݺuüÔx{_ré‡2|-ãqQúëõÄEÛ®-ÇC©Mn®7ñy*Éf§?ĪPžÖQO°)ca³+0Óp+¿l§[tP‘`r( ˜¦©¡2•Q©÷ß,¿û©œt0$õ¡“ej(«ÆTjl³ ÅsP:ÅbÔè•YŒÉdT–ä>0Œ`¹t@¤ƒx'åÁÁÈsQpÝ œd2šÑ'!R%«ï3ãž“ñ:‰È_'¡^}?òr”ЭR—øyCµØ8] ÍEQEQe¦à%‚ˆD&šrIQf+¶mGãz•™»¹—Ææ1¬ïäဠþ»Ø¹v'÷|ë)NxñÍuË+—«Çâtu“™ë1Ñ€–Õ\ÑM¢@MD4mÛnžè9ßPÇ$Ī뺸®;msnãE(5d2õxTF¥ö·çLÓ¿n>ŸŸ”rüéþ‡V%$îqŸè8Q®ÄÚíã!J%i¼£ ‚¡ÌhDË Ç2Û1>K/‘<#s9X° ÊïàûÁþ¥RTžx>æóÕž˜’¯QJè %cÜ IžÈáP±QQEQE™ë¸锲•W;° òj­¬OW–+Š2;âLàydÝNúù4ù_x:XÐò–v¯ÚÍï_ÿ[::?0˪ŽxT,}÷ziKJ¥ás@f2 ŸO3H*šéD®±eéØÄT3!Çîîn®ºêªf×}Jˆ‹ŽãD.ÓSŒJŠ2s˜.ÁÚqœ†½ªóùü´Ù)E™ïˆXOT„H˜“ÏÒa!RD<ñ–L&ƒeâÉ(b£x8ÆC BäyhH7ñP%Åb°^ê!ùÅKR¼.=/ا«+èdÔ&¥ARÖÅíÊìHm¨+Š¢(Š¢(óó..bJ‡D> òÓom¶—‹ÅbÔ11Í(z©¼çrÕáa‹ÅêNLÜ<ÉO->Ã2^¿xHUEQEQE™¸ = ЪŠ2Wùê‘#Q®A>”«ƒ`À3/{%Ÿ}îlrÆÃ¼æ5§ÒÙl!B£ ýqÇ ú鵩]\wèaa†>‡%™ŒÆš%­ÙÇŸËL(Ôê† ¸õÖ[Çõš-ÄÅ€éèõÑ\lŠÒl<ϛѯÊáŽ%Ë]×­Jµ½½=¬¯ïûU!¢ås<”k#ÕõŽ_*•(Õ ˆ^,Ãå®;zéb±нñ㶯ïû$‰ºuó&Ü~ ç=Õ‹Åð~&‰ðþ&‰ðšcñ<å\}ß';ݱ)æ)¹\$ÈÉ#"³%|<¼t$$O¢ül¤ ×­nìKU/%Ù{ÜQ„Ér9(_n½xSæóÁçB!(Çq ½=¥³"ž—µ‰Õ!òtŒ×¢_£™+Š¢(Š¢(ó‘AÈTñX,=@?cnŠŽ#õ‘ëõÃãÛÇÇ-êmç8ŽãT•ãy^UŸw¸¾¾çyCR渮;dûáönÜEQ†cgK °¤*Ý P„ÿŸ½w“£*óÿß äJn5‘PC€Иš (V‹€Ekâzv¡[ÝuÑïféV ®«Û­ìzÙý¢Ýð]ÄU×t++*v‰€2 8•EH¸…)BH‚0•ûÒ¿?N=UÕ==÷{¦>¼ÂT×åܪêÔ9çó<ŸÇÛÚøÃ0}ràöüÛ§×*$Ø?üÃ5Á%2ÿˆ²Q=ÈšÂ@"šw–ð¢ô$ÿ†Éd¸ƒ‡>y<®_¿ž›nº‰Õ«W³xñâá®Ã€Âó<,˶íAõv´#”DüœÇˆ1O©T úä\.G:F×uLÓ¬òü”ò& ÚÚÚ( <õÞ÷b,ZÔëz Z×±nîm©TBÓ´à^ÖóÆ”{½¿ÒI_H?•J¡iZ–Ô¯X,åÊd2躎¦i455U“<]×Ų¬ªçN&jqÜÛþ¡¹Y‘yòJD=ÅòÐ0Â8‡òø»nõ`6JôÉ-ÉfCùÓL¦šà©Ç %N EþÕJ³ø1íinVåÉçü¤»‰ZF!åŠ>&­­áöpÄ|ˆ#FŒ1bĈc¤ÀA‘Š`L÷#­zk€2§6 #˜kš†eY”J¥À U×õ`Þ™Íf)•JùfÉd2˜o꺎aÈ5Û¶ƒy£¤í8¦i¢ë:¥R)˜ß†A*•"ŸÏã8Nn6›ÅqR© 8¤ì¶måH&“$ t]æ³ù|ž\.G.— Êçº.¦ibšf`\+é 4M#N“N§Éd2Á:ÌŸ£Ñ‚Ú4 ÃèЦ­­­477kº®cYV0ïK=äžÉºHt}Gæô…B!XCkYˆ^kšVÕî2w—st]Öj5P–´¥|R©O‡gÚO[ê6PÆÜG+ä)š0a.¥RdŽlÿ^ÂäÌ9}×V%mèÀÒ¥>󙻀˫æÚ2×È\¿&Ö`dÃuËk ±‡ Ù,46†k8Ý,ýÅèúD<îܹ“––vîÜYµÿÌ3ÏäÚk¯eõêÕÃ]¯>Ãqòþ*Ý@yÊ þQ¢Mù’Y¶mä[&“ H,ô›¦ Ä{ ™d³ÙÀÚPÊ “±4M“t:M"‘ˆC±^”²&ƒÐ ÙšJ¥‚‰…®ë$‰ ìÅb1\Ëy2– Žiš466bYVišd³Ù` ¼å¿€2áimm ô2Y"0•Jaš&–e‘Éd( ´··m­K±X ü2qÈd2äóù@b¶P(“ €b±H&“Á4ͪ‰™ä—L&ikk£©© ˲bÖó<ÚÚÚp]7hÇR©LTd²*å’<æÏŸÏäÉ“ôy?ÚQ; /ÔDC† ÖAˆÃR)$ErÂØŽ‰HP¹&êihYJFUˆD‹¤®«sdb’LvŒ»(û;›LÈÄG¤bA Äc«¿1bĈ#FŒ1Ôš^µ–ç–ÿ¯/+†…BÛ¶Éçó¸þª·Ì™S©T@ ±hš&ŽãÉd0 #X§2¬P(¡¢dnœÉd"PÒ:= I'¨%!%,J&“ HKÏóH¥RáØÔÔ@>ŸŒl…4K&“8ެ³†¤²O ~¥l¶mùY–Ô?ŸÏó~iCiO˲‚ýBæ¥ÓéÀ€Z ·³ÙlF´MÛÛÛinnÖ'd./Æâ†aàºn@ÊO:”¦¤ B¢FÉDÉOæå’v6› ®—¶“{¦ëz•q±Ô5z_¥®B Š±³®ëT¤t]î!^Šº®&¹\HüÉd"VÇjq³Ù0~ctn(ûüye@&àßb ô‚t•–¢ÈãaÛÕñÄ2Ó4CÉèÀÄÌ3 (ˬÚíz / emêùÛ# =ÑÖÊ`ȶë_ë[ÍâPm±fÊiÔnGóô㌠¡ª#å^Lj#FŒ1bŒ@x„rªÊñ7„£Ì9Å;O¼ÝÕܾR¡¡¡ ˜ÿ· ¦i'b½µ ™kGIÅt:]åUõà«…ÛZ]°Bà%"V“2?•õI»vÕ²¬€\ƒ^!”ËåÈd2¤ÓéjCÑzHy2™L@hŠº•¬D½!»R)’µ !©e­@îo”lÃèÚ?BŠ1r:Öa„¼L§Ó|S²u1gï^v½>µzç½)ÀÄfìoúé˜:`ÁI?=©êÔ®æÛ†×"úd àºa™¡4>6Mª¥jc•ˆ‰Ç¢òªV¨~!mÂÀÒ"¿«“ň1²!ƒõŽñ(ƒÀhŸ"ÒB$Š5›X«‰tITf³\.žˆ2P6±Â‹Z? qxë­·Â5×tð¨v]—ÆÆFÚÚÚªú¾h¹ä<±xb¯X,Ä Ž=Ï ¤R„lÍçóA>Bz d[H)» ð[#úކaTo"Ú™ˆOù’+û÷ïçÖý÷È‘ Ì’ŸX^ÊdAdJu]§½½½ŠÐ‹Í(Ñ•¡J³†A¹\¦±±1h/‡fÆ ,7.°Hìl"œ‹ J´^µ–’ÝyÆ”dwo!±4b ,ÄÂÐqÔ@5Vs‘:OÅhŒÆ(l;Œ™(m /Þ‡™Œ" CíO$Àw–¥õ>yDõ¤CëRPcÔrQäZ$N¤œ#|6Kçä^‰úÞƒ)ÂU˜(ÁØŒ"ÇdµF®Í¡H¢=Ÿ%Ô®’×ÜFmB<Ê>;’†m9¿l­~šv$’¿-kºŸge¶nøå¶ýk…dÌúçáÿö¨&R5BrS÷ë¯GÊdù×D»BÓ¿oiB³è§%žšyBoDL:~›z~щfÔ™]ÊW‰lG N)³æJÿ^lÿn¼°#FŒ1bĈQ‹&ÔðI†mÝ¡¹¹9˜[777cšf@*Êœ^7k¦9jÖûºnU‚DãmáŸÓ™‡'T—Q?ùÝ—2ÖÆ€ì z£–UKv¯±7öêíÜ¿¯k,1B©ÕùÏü™g½9ꇈº‰ñêËX7„!Ça÷îÝÒéŒx´¬¡%Å C­!ÆÐ*EC¾ u˜Ûî£áuŒ^#&#y½Þ …ZŸ2QkOóÄ#FŒ¾ vh6PÞŽ2`µL‹½—ïåÀÉðÖz<~Ãã|÷'ßeÝ·ÖqåÁ+ù<Ÿgÿäýlœº‘³¿}v@HŠŸÈov6 Õ< ø›Kÿ†÷,~ÊÓ'÷ÿǨß~lñê“ ïÍÍÍd³Ù` ,q…8•¸ "óÒ[”ËåÎÉ9!„è ¢^H5ضmÛ¶mcÂÌ™,¿è"²—_> ÷·ªüÝÈ9æ;3ßn!(úRE*Ôyx>yY"$«d@SûL‹w HxŠ|§Cø füýBj y'ò"ïiÓÑ«/ççé¢HËö:åm!!ÅÛÐñÓOÒv#ÿ¢Þ’ÉHy»šk×;-K’Žï]¶æxWiF·£Ýc­tª¼ºÝõzmÍSA-*ý<¸éA–³œ1bĈ#FŒ "NÑJçC1×uƒÐ ÖZ[[ò+:îʳp´˜‹J¼ÂÞ×F½êjÛ¯ÞZäÓÕúƒŽòW<1åš¾¬]¸£0è›Ä†HCú]ÃvìØÁ¹ßžÊŸ'S=÷=É çêP‚ï}ïšÖÄøñ;¹üò«< ³ÙŽJFñ† ïÆzÐuµn5J*ˆ¶¨F ¢ò²1ãûŸÄÀ`×®]ÜxãüÅ_ügžy&¦irÏ=÷t8鍊n ιîºëؼyó€ä/²t=‰ëè¡ÖךPk_­Ä¤cŒ¡îj‡f=‘ÔèYÜöÕñË=åu$ÞK þ¾’¿?ƒ" dì/$_³ÜVu%§êI†ÐõÜ·›;w.“'OfË–-<øàƒÕ÷ŒH^M‘òÙ‘ãõîµ N2þµŽÿWê“ñ·Ç…å Ùߟ‰œW ”:”úˆ‡W©&ßB䘴ƒ´OŽPÿ'Rîl6ÈÈVµ})LóìëÎf¤b¸ÇQ$¡lªëª†Q"`šÕq¹_‘„Žú+aàvö¥V?|ŠW]ïבÄn…ò |9Ð…oûûµí´ªíh·å8À~µ?:6Íð¼r²'> òùiÏXÕÏ¢”òÞ–ê\#ï¢Gèx± È@s æd`›£žYÃ?þJê¢/dàÿø/¸z¾=à dÆÁMM0·þÐS á{¡$ iLj„åàaW¥/ý“‰"û²@Ò…t?f®«fGõf*¢Ÿ›ÉtÔÖu]u\Ω h!ÁBK%hn?ÖOÕÍ7Nýkl¬~0£kôœzA3¤ ¶Ý¹™íBOú‚¡èbĈ1|Ic‚1b †º/° #:óI®T*„$ñö—IUþ\$Ÿ|¤œÍT“,ùHû–"m“'Œ­ÖJ?-*Å(^ar?lÿ:#’ŸI?Eµw–áç‘öÏ—gAâԉĤH\6EÚWd"uÈ–³*=!‚ þù¾l汻忑‘ˆáD‘L†¤l;Žš˜¦,—ÿ´ù¡u¢ë‚û$8[ “Pòª^äfû!¹ÝÜÚ“ ñ-?ý¥ÀZHNý"(Ü ¹‡•—#Ïùj®s®º·f 7©C†¬`üMÁ'¡H;dw-†cL BSQLÙº•㦇»xÎ…í6¬rÀ2!§¦zïxG;6¼ Çù ïz×§•"PÇs9¨ç­iCgQÊ2\°á(ƒ¦uîucàÐ'âqþüù\{íµVˆ]»vÑÒÒRÕQ,_¾œ––î¾ûî`ß=÷ÜêU«Xµjßþö·ë9§¯°m»Ët4Ôšö0Ä>ó¨”De Ã¨Š«7ÜåŒ>KÑß®ëâ8N ³aÛv § žh¢÷•KˆêØçr¹@–Óu]2™LзO×õ`&2#™ ê~@ÖÝ=ÖÄÏø )$¤(ÒG‡/áË<½ýin=õV¶.ÞÊ…Î…üèë?âࡃÜ`ÞÐyÚ2¸hìsà²Í—)YUPʰ¢ãÌ´ÿ/¡Ž÷ßåÊyW*²K‹œ+ñ¾,T''™Ä“ÇÅôË¥z܉¼¡œçDÒ2=ú’„ž|iêËFVrÜexN5u¬ŒÉú¹/×8ٚ̎;Øúr;oÞ¿m ã±¹uÒKû¿…ðlDÅQÓ"Ç¢m_Û†D~K¹EÒª9F¤më)| ©Ý™ŽwtŸÄu“8poNÚB‰­çëµ]߯¦½›i c‚( …®ã8$Þ¯Ž›&8‚±LXöFÈ$ýGë0 ¾­Âg€4Ç€öEÈ®„Ò1 ßŽä™#µ›Y`Cò9pv+ÁùèF84ξ ¼$ΫÀW÷Ç”wßwsð˜K’°°µ0þâ”&õ }Ë_ ˜Ùž®ž1 ¸Û…“=ø”¯·úÍ6Øæ—ëÿ3áŽ<\fÀµ.ÌÔ`ƒ¡ÞE_F¹=ô`ü-ê½â=XÙ ¯B.òÏ‘÷.X~à‡¡«Ä””çÞðÓŠ¢8Õ ½G‘е7³µµÚܱv<eŸëÍu½#™Y‹r™.‘ÍVçSÝÍ@£2ê•E‚‡Žô¤/ª~ FŒÑ6&ˆ#Æð`¨ûY÷«y¹®K*•"Nã8Ùl¶ßë+£gd¢¯$]½ëê‘e=M ÉÂÑJ<޲Q0ÜcÝÒ€µkײLlñÿ:ª×Ðuرc-û÷Ÿ‡išÜw_uZ–¥ìRÅžµC-:\²£…BÎf(¥VeÚ«W¯°BlÞ¼™åË—³xñâªýçœsNà½~ýúà¼h9/^̺uëú=¡èJfÕ% *Ý]X ‘†¾Z# V~ŽãT‘…žçzä²?N£i¶mãy^p,zŽÈ2˜¦Yµ_H=‘†Œ¢;ÒMâ¡uEzžG.— Ê(¤Ÿ|º®Q±ÀÊd2X–Ô7“ÉP*• 9ÇqÈår†¦ihš†ã8d2™`Ûu],Ky½ ,ËÂq …¶mD¥¦i¤"^–e‘L& R©D[[Û=½ÁP÷Q9A§ƒ6‰O&Iœ2!-ØuÉ.f¼}3ì|è¯?„ëºÌ]>—G^{„óO<ŸóÚÏë}Ô`+`!iÖðËÿ’üãœÿùó9Õ:5<–ìxnÕ¶"Lÿo‘ÐcO¬/¬ÈßÚ“xþ¹þ±Þ…Ð Kñì)tO¨É“'£MË;4]‘ˆÑsjóŠ–[¼EW£¹¦'BR÷}ÓáTbXÖ¦Qû;Z+ÒnnÍñÙújË«ìlÙه .F˜ 3ˆ—c: ÚÈ~J÷ªcŽÉK|Û€ñÀ]`nΧ˜ æL°ž=æ°Û¥`,Ú‡q°mç¼s^ÃY·#öZÀn†É`.ü,{÷,ç 1÷ã?7^Êœ||à/!ù¡¼;6*ÁTà± ¼…N‡ï×Ö2œ¤Ãƒ%XªÁݺz^L ¤) Ø$ÐâÀ4VhÓl²ºzFWèjÿÛýCÑgT @‘œ‚hŸÐNh¼ fM:É:ÛцµHôàÆödÖÑé7“þÁ¯²…‰îú‚áêbĈ1tÉc‚1b †²/ˆõVMr¹ÉdR…(ƒõ’Þ’­‡°§k“õÖójašf§ÆãýYmäHu, Œ„1AÔo÷ x þ ìÃ`cÀsêy¬øö¦ŸøÄñÌœ9SO5™8ñ Î=7¼VÓ”Íiss}»Ødrh½%*H:Ýÿ´FDÅÊq†¶Ç"ú%µ:PX¼x1·Ýv[Õ¾]»vq÷Ýw ;wªÅÑhç0sæLÖ¯_ßeú‡âÉ'ŸdæÌ™:(;õC­Óvc«>"PÀ:—ËaYV¿¥zâ)'Ö_ù|ž\.G>ú…–J%4M Ê#Þ‰¶mWýÖ4¦¦0àZô˜çyA94M FPžƒB&‰ªÁ`ss3Ùl–L&C2™Äó¼€øI‚¨accc@ä ‘˜L&ƒ| ……B!ð(t'(›®ëX–E.— Ê&m/ÞŒù|žR©šår™\.WÕÆB†Ô#—Ë¡ëz¬\M‰ãõª”ãŽãÐØØXâsÌ1|ðƒäµ×^ÎÇ´.»سg---ÌŸ?o¾’9•§ºÓg\¼öDª°Žq øn3Ì€,öôlÿÃvöïØ³`/my 8¹ç׋ܬÈêö¥ -Q-©ÚÛ¶‹z•öÒÞõa ¥¥…'Ÿ|’C‡õ!ñÁÅP ê]_Yÿy‡!³ò%Ðr¾ñË Rò¨l–€ã‚•}>ðÿÀ= ¸¬ Ÿ O?ýk´ýgPØhb}<3ç_ƒ<‚.Éq`ÉßÀŸžƒ ëñÎ7”ü©ÙVújC·m_3E¾;À%~pÃ.| ¸ÃŸ VÚôw¾/RÉè»§wÒ ääD²èm_ÑÒþ}ˆQ»víbݺulÙ²¥ÿ‰ ºë ú;&8pà---]ÎbÄ X¿~=;wîäÀÃ]”ŠùÁ–-[hiiáœsÎaÆŒÃ]å1† ñü@Ͷ,_ÞAÐ ¿Gª!÷P` I.!#;Cw ¬ÏE÷–àì:%ÊóqóæÍlÞ¼™={ö w•:`¨× çÏŸ_u¬êiõ€yáÇ)-þ:ð“Ÿü„oÿô45žJ`Ì:;‡ÿÒ•\[›b6§É HºÕôè÷'@@:Ë‹kÀlª%”vhÀÅz(£ÚÜéÃÎ;ƒ¾`4 ¶/X·n]¿ÒâQ¬ cÄ«X·n›7o‘Äc-c~ ÄãüùóGŸ(FŒÁB}:—\rI§ ŒBøÔ~hD¿9Oß×{‹(•u§Jn@<îD†3j)”Ëå¹ÍZ²ª3477S,¯ÁææfÊårU\ÁL&¤/R¡R.!Ë„P“k’Éd@æÉ¢h&“ ~‹EJ¥R «*ùI¹å*ñì3M³JvUˆJ¹‡$“IlÛ¦X,ÒÜÜL:<£×HYÅK0ªÓ/D¨¤+åßÑgF×õª’xeFGÏ‹¬èo©ã@"Z†åË—s×]wqõÕWh‰ÁêæÌ™ôG¿@­¿G[[Ó´0ø£ZèoG—Á]£„½¼·ò.T |’0%7…XÐûBK¼>‰+Ù[d &Ÿ=¹o&í Ñ·Ž0"oûêÁTéãu€öÎV¬àÐÿ=oée&Õ«½ExúcL+ÒÀP—´]½z5---´´´ô³ƒ‡áÔÂ4ÑXe‰·Îç…ÀÞÆTÈÎûh»×Pžs9¥)ÓÐf©Ó ‡Æ³æ¹»1™ƒ7wÚ×?·«A6lå+_9LDÿÞõ˜¶ø«Ø½Åª€ç»ví"“ùÙlÛ¶Édìà{Ú©ñD¾ùö`Çûí­Ìû –g(ÍEG$tÂM7Ý4ÜEéƒÕÌš5k@CGĈ1Z!^=ñ. æü`Ù²eq_#ñü@æMTÛÌ& @­Ó¤iu|´µª^=…Ì ê­u ô`´z,ö¹†¸|ùr–/_>fÇÑ5ÃZDgÛ¦iŸvPØÄšq+æ…:üA=çbëúþ÷¿TÊfÕMo$EÁp‡©’6jÞ?™Tk.1:ǪU«˜?~¿Ç}&o¸á6oÞ\ÔU /éúõë¹êª«ØµkW·éɹ˗/Ƕí.ÍÑój­’ûk¥\o±NÂz¥é›£Nwùuöax‡µÄ£H•¦Óé@TÈÆèŸy’N"‘¨"΢ž‰z:Žã/b†ò¥R‰D"¦i‰’N§) †ã8t©išÁµ™L&ðŠÔu=° K§ÓU‰"%*±ë-Œ¤1AŒ1†CÕHÈqPó}ÇqhooÇ’ôà’9A­4ê@CœúCÄ ´#@ŒÅHL;<ìq·â|#Ì? .Óáÿ©g:—SDZkk+™Ì,:³ÖuE€ wXQ]ñWê²H70Ô± µÎ¿îƒ>â͸zõê.³Š·ã 7ÜÐm×ë®»ŽK/½”üǬ{\<Ö­[WÕY´´´ô;8¬gÁo "$:d´ã8‰( ‚ñú‹zPIì?!+ƒcÙl6n]ò"ÓétൗÏçq]×uill bÏIÜD‰ (ç+ï ½J¾Uˆ7Ã0H¥R”ËeÇ £ƒñ¬Óu½j±1º%Ak½ýrà1X–h1CÝÈèFÍ{’(O7ƒj9Â:§-†xÕº®K±Xìxr>àý鈤’T§6†¸ô{—ÜËŽçáôÓ9æ˜c†»8C ñÒ-0¬Äo_1œc‚Zär¡·cóÿ€yd? gMÝËÓûŽƒmÀt°·ƒñ®3yñùݰ²W>…fÍÃóà'?y| žÃ¶OgáÂ5lÞ|&¬gÊ—šá)›rùš Ïçž[†A[[‘c^HS.GRÓ˜²ø¦|íä.¼ÏÿìgÌX²„\SSßúVO©TâÄ3Ïäóç£ë:Wÿú׳i?ûüçUÂZ(Ë*Ú"EnY%ÏÃðå¹£¤ôo¦iòÝ X¸iS0.ˆÆg‘ØÉ"I%ßbÃ0ª¾ñ22M3g¯ÍR©ö¥å2ŽoH%c Û¶)•JJ¢ ZüïÎìxþyÞ¾dIÕý+ Á˜) °[—p¬:ðý½{¹è¸ãÐ »Í®F'Q‡n—°«ÏÑ;Î_®•×6['ͱˆ®ú ™Õ€IDAT‚¡ìbĈ1|Ic‚1b †¢/±¥¬JØš˜txÔÎ"=è¡iYÖ HéÆ a:RÆ—ϽœDë¥pJúû© Û[e¾ªæ¬‰Dè±k„u?"ˆÕWu°‚®£ÃñøwP—˜¦Z牻öÁGŸ‰GeYºÂ¥—^¸@w&kÖÒÒÂæÍ›Y¾|yΙ3gŪU«X³f —^z)3fÌà–[naÆŒ\zé¥ýjñZ4£úŒž‰”ö>/‰9(ƒ!m[I¦577q3™ ¦i’L&inn&›Í§…Bt:,À¹®[—ÔK$¤ÓéÀs±T*q %± *‹444Ïçƒ2ij«\.wù1+¼‹¡îÂÅä*â±%qÙƒPÔp \.÷;ù ÁEÍ¢F`Ñ—q•ë÷sß’/±&ÿõN®òŽÓdÖšß`Ÿ~:¹í6~ùîÿ¢¸p!;R)¸à~ðÒK¼tÒIä€ï<ô?~ùe?ñDRgŸÍ”/}‰# ðÛæNσK.¡¹¹™C+WrÃG>B©P`Þ¯~Å„={x4Ÿç?Ÿ|’yò‹/¦Á¶iûãÉ}îs|íÞ{yÿ›ÞĤ}û°Óið ¿[?÷9~÷;^÷c&‹’Á/>ýi¼»îÂÉåxë“OÒzùåär9lÓߣñ‹[¶ðË.RÍjš¬ùÍoعq#étšT*Å9ï}/3}”nnæµ7½‰=Æ›ß÷>Žyì±`qbå]w±Ï4¹ôøçW_åésÏåý7ß̽K–ðꂼ¯¹™M³g³hÑ"öýþ÷<œçe¾ö¥/ñ¿Ï?Ïâ¥KùÆ;ßÉô×^ã]÷ßÏOS)Κ8‘«~ýkþnùr.ºûn>óÖ·’š6”çñùßýŽW\ÁÿnÜÈs¿ù O_u—MœÈÙû÷óå)S¸â•WøÛ‰¹xÆ <÷§­ëÜõÔSÌûáù¯¯~€”msë_ü‰çŸgòäÉÜyÖYXœßyê)þe÷n[¶ŒnÛÆô?ÿ™Í'žÈæ9s(Ø6·¯[Ç{·mcî¢E<½};\º”ãO?# `ø÷BÆjQOVÈäGeôGòBZOú‚!ëbĈ1,qc‚1b †ª/¨uL’µ³ÁÄh[=‹†dêqýuÄîöõqŸêHH©£Ã=&°Qó¶C-OÓ´£‰5Gæáîçd©íËá{!Ïw.’z¶ÝÑÃNö wˆQÛî}…e ¿×gŒÁCŸˆGyÁk5”W­ZÕ\”sÖ¯_ß%ñÊr¡Ë—/ç¶Ûn”„ëUW]ÅW\ÁŒ3ؼy3«W¯î·–sT†Ìöÿõ'´– —ËÖþ"…&qÅëPâŠ,h&“ ,ýÅÑu]R©¦iÄ¥H;jšÖA4úÁJJ¬EÇqÂ2Nw¸^µƒ‰z¤fŒ…¡îjy¸.ú(4¡Hš~ô4MöíÀš©RéG@ÂÁ‚æW¶áߎF¼òÊ+pÒ<œw˜4ÜÅ:è¨Yìh Áp j±ô;v@?Vfá²› ð£ç(õRE‹ o»î€ï|ç[¾ 4ùŒÐÔø³wm‡äÌøîÙµ Ö,€Uï> öÂ)S8ðþóÀC+Wò_ëŠL9y;¸ä¾û8eÉvË ¯¼ÀN:)à“±hÓ-b °ê–[8rÍ5”€T.‡fYxºNÉ08NÓxh+™tà ì™2…w®ZÅQÉ <ÀWÎ=–.¥-•bùÞ½¬?ž™×_¦‰mLû«¿âÈ‚þÊWàî»9þ·¿E×44”ã'É$Éd’ ».jL5ïœs¸úG?âÁnàÔ?ÿ™oÌžM³_þ2ðÙƒ™üÅ/ÒxÌ1<8q"ã×®eñ®]<9e ~ùKÎüùÏ9gëVíÚÅqŸúN:‰÷?ü0SÞòÆ54ðßù—œ7ÃóæñûÁ4ytÞ<–œw»Ï<“>¨Úêíoç‘/}‰;6ndòþýì>öXnÿô§™xç8§œ‚sÙe<°gïÜÉÜŸýŒ¹‹ñµ+®`ž=Œà&“P(PÒ4°,&Ý~;w¾ÿýÜ1c³ï¸ƒÃ“&a_~9çþèGüþ¬³à«_å¤ÿùÞ|äÃ@î9îÛ³‡×O;9Ÿþ4&“”Î=—9>ÈÇ|RöН}–yóxvŠ޼ø"M'²iöl^ÿÌgؚϳã½ïM#ŸË1®©‰ °à¹çØX*1åä“ùÿ6là_^xöY³øô¤I|çÊ+Éd2_Éçó ’N§+@Õ¶eY•d2Y±,«’N§ƒÙl¶bšf°ÝŸÏç+mmm•ööönËbšf¥X,V,˪´µµU’IUÃÖÖÖ»'1F®ºêªá.B¿ÑÛ~ Zï¶J¥íüÒétåçgý\u½x-ÒétE×õJ{{{¥X,w“ÔG[¥R)ûî¾»8ªÎV*çmÜU¡R©|ÿ/wqFzè¡Ê7¾ñá.Æ€Ôc Ç•Jõ«B¹RYzm¥R¾Am¯Ð*•ôÄ»+SZwU–5ÿ¾’NW*s_¬TÐ*•iÓU¨T*§}omeÙ‡þ­B¥R™õ½­Lõ žóÐkÁöì• Yµ=mû®ÊÜïW*ZEýNW*Ãß¶üT*•“öí«dým½R©ÚÖ+ª “ë%­+·n­œ´o_…J¥2ãÏ®LüùÏ+T*•¼\«¨qÉO‹ì×ücs<8nV*•ù‡U´HžI?_Ù–ýf¥R™zà@…ööÊY?ÔKê¨EÒ¤¢º+9§5²ů]ið¼ •JåøCeÊþý*ª‹›uäHp­Ô©ÕOgêž=•ž§îe¥RùðOZùïÝ»+®¿¯5r¿Ó‘v™¼o_eíóÏWÚÛÛ+ÇüïÿV–^}¥­­­ÒZ ÇO7<þx¥½½½²òª«*}ðÁðù‰ŒÍ–ýìg•I{÷VŽÛ¶­¢GÆ]ííí•r¹\I&“ £’L&+÷¿ðB%_ó,^ù™ÏT(+SŸ|²R®T*×íß_ùüÆ•²ßÎ ~ò“ʬÓN«ŒóÛfî‹/V&ìÞ]¡R©ÌÛºµ¢•Ë•J¥RÑ4­R,+|ìct½bYVå£>XA×+@¥T*õöÕQèϘ FŒ GÃ;ÑÛ¾àh ň1P8ZÞ‰¾ÎÒ5ö¬T*•|>_1 cÐËšöÿň1’0ÇÕ[æ¸T*•O¿øbÅĬTÌJÅl¨T RIG^àÖÖJåôÓŸÖüóùJ%Ÿ¯TÊeõ·¦Y}ýpÁ4U]Æ ÚÚ*MîRŒ| Ę OçœskÖ¬aõêÕ]ž»fÍ€N¾öyNö"3Z@9 „ĪXG9Žx+J¼Ä|>ÄR”8‹Žãný×”w¡x0Ї¤®ë½Š‰¨ëzà©ëz^l]c4£?ý@­˜mÛ˜™ÊC¬›×B¤éäýK&“¤R©à=qðPÁÆòŒ:ÉÍþbÿŒýìÚµ ˜ÎLwæp'Æ a Ç âö%!ô²ë,àWß‚‹>ÜòÒBöÓÙø—è/öy@Þð‡'y’7±qÕÙl¼ï *מ¿…9{°nù1¬º¶†f¦RÃÍ8=oUÛÂW6ã—¥ŒŸ¸S¦`ùû¿ŒTŸÖJè´õ÷kÀ7çÎ¥˜´o»þò/¡\F÷¯•؆–¾é_Ûè—ò$ä¹çÒ蟣‰ HûçÈùš_v %Ûä×Ù4‰æI“¸KÓ‚8Úi?a<ÃL¤ ¿lY¿œÙK/Åñ·?vÁ¼ä·¤ÆÃõ¯•1œá·Û÷úSþÏ•WRò÷ÿ}[K§M îu´Ë–Ú2…7/XÀ=Žƒ™Ë…'úã§<÷\~î[× ¢ã³Õ¯¿ÎU_ø{?úQ~züñUçHÜë´ëÊ+jžÅoÞx#Ÿv]ŒE‹0'O†SOUÛ€÷Îwâ<[÷ïgÿ¬Y$çÍ#å_{a¥ÂÇýXÞ¦e‘ò¿SÊuÎm·qö—¾ÄÉ'ŸÜ××eD`0ú¾@brzDú‘NQE‰Ði½6mÍÿýiûçÊç>éÿvßmÂwש9.×é„ñJåÝ’k“5×Fë o†9Çôëáö ݵíÿg'1úƒ‘ÒĈcxÑŸ¾@¾CŽãÄÞŽ1bŒb Ƙ`V[†n€ Öì;ðN»¢ê¸¦ÁâÅøÚ׊Áú`&Óy,Á‘"3jYÃ+·:Ôð¼¡+9VÑ'âqÆŒ\{íµÜrË-ÌŸ?¿ÓXkÖ¬á–[naÕªUJ<4\×å˜Ù³É.„õ"… ¡Þ¶ãû-kšF.—ëTÏܲ,Çé+®¯¤†2h Úß1bt™PˆÀ[æ¼EuÝ P(àº.ÅbMÓ‚ø#2¶#„«})º^= ±ïŒ};M}æÚ'¶Óú—`Œ1µ ®ùÌÜî3Áßß÷}5Ù.FÒ.Fòmõ¯KRM HTÓOªíA¢ÛѺF·£Ýœ¬Ø¾E=FnÉÝ?¯MŸÞå½÷<KÓª>]-:yžWw\eÛv ­ï8¦çñæN ¾ºú~Ô“¡’ï–•IùlÛ¦äyä-KÝû“Nâê]»È¹.sŸx‚ÆÈ½°¹‹.âìl^{]#GÇa‚ƒ"ªÅPÀFµo3êý‹*^Ë;ì¢Þ%9G ä]Íøç‹q¨û%æ„l”2Ù©öQòPH~!E…] d¦f¿‹ÐîA_aG~ë(Cƒ(„$ÍDÊ-m!$j4ZâQê EÚ]ò”>OŒ'¿í²T÷)Qè‘}YP>=²-é×;&moö»= «Ýù<(Eê#FŒ1äûbû±Í;¾c4ß1bŒ|<ûì³¼ÿțᠻušYMº.ÜyçYüë¿N ö9är*Žc²fM.9BÖè,klqc©®Ã> È´õë×sã7rÏ=÷°xñâÀš ¥¥…––Ö¯_ÏâÅ‹»õŠNi°aÉ’ª‰m_áy^`Y^(µ`eÛ6Åb‘R©„išA¾õ ëú€’1Ñ#FGÈ[áº.ï=ç½÷ëãà‡Ý_]Îd2#3®c:¡»Ôñ{åо}üÕ%oîâÄE…fÓwõÙå™—«ƒ<œù"p?ãÆ½FÂÞלÞAöž5‡9ÏïçØc³uÕ¦€¹í°qéŽßK&ÀCõ?§µÃ£3Ô+ú–‰p'á‚~‰„” öák,‹Û’ Æ0¥È~·ÎùÉÈvtÞŠ¤]bÉRMö ¢Db4dMšõ¶£#œÎ–s4ªce׃9·32¡µ½ñ­­8K–À#°«µ‡L&Ã…ÿ8úÔ=îúÞ‰ò·©©‰r¹\5ns]—D"A[[[•҄훑Š1šaضÄÝÖ4B¡@6› â‚ …@)Cò´m›\.‡ahšÄ*w‡B¡€eYx®‹¦ë,yåœb‘yÀu[·rÎÔ©è3gÄ®Ü4glÙBŒÎQÀ÷„%ôòBNC‘nòþ&IuÙïú×–ÉAÏß—‹¤+dx5¦ ‰¬,¾ç³Ÿ¾uyB"9)“äõt,ùçÛ‘|ÄCQÂA×{ŸÄCú'Qˆ‘2B5AWë)„¦ô?ÿUÆb6¡§3„d¬îŸ#1aÈ?iSI¯Dèe)QïN!-MBP©—ì“ûfGò)ø×¥#é¤ý¿¡g8‘g#JNÊü2Z×`aÛß§öÝ–_ŽLäZi©—x‡KySTÆâ±.†&Žß¾ÉHs@;¡w¹ ¼töÙĈ#ÆX‡ 477cYV Z#FŒ{öìaîÜ…°î0–¥ÅZxfË²ÂØ#Ž£<3Óý%EF bšdèÐgâqÆŒÜvÛmÜrË-¬Y³†––n¹å–àøüùó¹öÚkG4é¡lbT¬·Èår$“IJ¥®ëR*•H&“ÁB‘çyX–üƒXæ4FŒ‘×u™7u^×Z`ˆA뺴¶¶wñ{Ž1ØåLÞ1™ñGö¨:g8bĨ0ý÷~}2Çÿ+Æï<‘¤z˜*­óêÌY¿ñ0§Ÿp ¤aÒ³“xËÄ)¬™ 'y ½鯩à/h/€5„Þ„"u( ËÔl‹‡¡l[‘sZä‹xŒžÓ™‡Kg]`g]‡Žêë-ȤR)òùþ ×Û¶M¡P¨K<ºiÒÚkj½±nës9*×\øL†ã×®Åó¿ÑòK¾åNŽ÷¤7‚NHĨԬ2–pQ÷²H(W-2¯ÉÈ5ÙH­„ž­–_!t…dRR`1ñü<›©ö>­%^½HÝs(ÂPˆáaÿo’¦¡—©x© 2Hc§#åfñFÍz‚jÀ¾OìAKLj#ÆÑ غuk0¦Š#FŒ¨q×Ö­[Ùúž¹°i6ƤW±mE*Jwa°jÕ­hÚÅÁ5¦ ¥Rïòj˜&ŒtŸŠDL<úL< ®½öZ®½öZ6oÞÌæÍ›E:ŽdiÕ(\×eá‡>Ä£ôx´m]×I¥R‹Å`±ÉóUãÉÄaŽ´ÁƒgàØ¦°ö¿&@z‹Úa»þ¬v8f§òl<óL8ð+µÿ/ÆÃfÁW€“öÃ{çÁ´Ã ù|xt9jSõXŒQ„ÈxÖŽQÇAÓ´*ã(Ïóhll$Nwð>4M3•˜·¦iB„ yjÜ$äd±X äåE¦^Ó´€tL§ÓAÌk‘Õ4b±HSS–eĤa‹E2™ Ùl]×ihhH>Çq0)`YÙlÇq¯Ât:x, qÚUlG]×)—ËU1½B"¶¶¶u°Öz^Ó´*Ó4ƒûÝ]Çú–Å1]׃mñ~IX!Z…(mjjâÔSO„§ltBŒ‘› å*S(²JÚ"ç÷\U<…àoY xgDæ©vUˆsy‡*R\Òòº\.ï iš˜¦‰ã8‰mš&žç佨ÀDÏ‹>£ ÞIÉBIª*ƒÿÜè5žçu¨x‹á‚x3GßÏó‚²F!Ï’·È;kFU_ÑzâÁÚYLخЗà{·v_´æ:ŠdMacĈ£“~ÿû!U(¸ K1bÄl¼ûþû™§ý#Tš(M¸’¤©¤T[·nNªºF¦ucEÆt´À‰->†F<ŽVxžÇ¶·¾•ÏöñzÓ4ÉçóU“éÚß1bÄYˆSLaÞ¶y=v?Ñ }ô£èªÈÄ–F†ö<%®.Pº Édlâ4Ä8ëñ9¼áì©üy¸ cT DH$ì: v1=_V¿O}v+/.ßÍ´í3Ùék­·æ<ñÛ9™óÎ€ËæÁJàmÓáéçÔ9{6ÃüÙ€óCþMÄ 7ºà«u²=‰Ï(‘% ŸP¤@%¾¨81'ã‘û”؃™L&X¨r@Ã0/Éd2I¡P P(P.—ijj b"ŠÇ¢È­ 1'‹þ¥R ˲ãt:”'Z§b±ÈÜ}û¸kåJJ¥e`ÏÛÞÆ´÷½ ƒ·¦‚fûêÎ¥¢cÀ(aÑ“teÙWDI ×uÉÕÖÖÖªòŠçc¡Pà”SNés~G AúñÈ£Pï¥ȹ–em¡\°Ä,åU-e ¤Ä#XÚ#•JUµQôÙ—¶–~°­­D"QGµ¶“üE>YÊ"$«¿Ñ°rž˜Ñ¶:Š×s´­å~ɹ" -RÏÒJÿ(éד –vòWî»ã8¯<è¶nÝÊ„ ¯ÕŽY†{=Æ›óÄãcÇÃŽ††^{Èb x9ŠTW±Xìej1bÄ.Œ¿o<í³Úiк>±P`Ó¦M¸®K±Xdë…rÒ—¾¤ÄÁ £:Z´,üz ÊÄ)º@íºÐØŽ: C™?Õ³‚w•Î@ŽP¹ð“Üœ¾™}ëöqÿ±÷sÙ‹—©´#£koYËÚµk¹ækרt£ÁfE÷SFaûk=›Í‚ ;Æí`VÛ¬ÎÝ kV^;%ïkò7nœ2¤@£­­- ïÄ3Q¼}ÑE\´};Úœ9½ºN,Wóù|°#Ò1bŒœ±û ^žÿ2 tB<¦RY³†ñ;w2ùßþ ýõ×8écƒ}¬ó„»òXÑuhmU&Ož§ÈEÛ®ÖhH¥Ô~ñ@H§ÃˆÕÍÍjô"âäšÖsíÇŸlÍV_ï8ªœR]¯.ß(ÀÔ§2gÎTž€Îg3c„„Ñ=dÝÚ🕭;ùß&; œYlù=$þŽ@oñÛ×AJjU9c¬0áò}`øÕ. óéÏœ£3K¼pj‰G!û’Éd ó) ݉D"Ø'^† ¼ Ç â677òƒÙl¶[¯½ZiDåCëÉ J]:[àéΫ°;,]ZM3.½þú~ܾa8e¹E>¶VâU`š¦/ 4¶Q \x‹Æì.xšÇ‹ß|‘ nÀölnxâž}íYš_kfýäõdrnžq3ËXÆö‹¶3ë´YLº]-lnÙ·…mÉm¿4àÛ@,Ç I¸ ÁSï|Šóî?k¶_ÃCŸyˆ¥?XÊR{©*¨lƒNú(³7Í`îsÕµQH`?`É)KXvÇ2ÌMÕÉêaÁOÏ‚ã¼ã8nÎqÐ ¥q%6g3㦌ƒ L5¦r™y™ ^+«™¾+ÆÒÜR–KCO0¸ ŒóË#nv¤Œ:ŠœlöÏ• šÀ,f©|²¨UWÛOWòŽÖSÎqü4‘cÑt5øê©_åó¹Ï“%  £C´’6Iƒ¼–W>¤– ™Ì¼©Ê|7¬X»‚¹puVÊ`@VϪÜŒLV‚[Qí/í!«ÁXJ¤Í´º7¶Žzf“Pmœ'¯ŽGW…ñË \ͶáŽÏßÁß½<°¿¬NÍ’N’ 36ðà¬ûþÅ2Dã‹'®Þ–eÆ&b\õ%ƒ¨·±ÄW–ïq©T ¼´åÚè77êñ,ºxT‹B‚|ïÅ«;Nו*–´Dé@<À£Ê@0N©å¨yÔsÔ8¦§<}‘?îõ¼cŒè€ñ¼ª<[©ï‘è¡>'2Š3#û]ÿñ†L’’ÆöPŸù”D‰Eß&)HKÆCòiMªÂD¯s†)U§š¹ù­¢ñ°?|¤^6¡‡gT…Bb"ùº‘vÑ#eIF~KYm:Æmî 9Âáô8:O›ž²I½{Lz½hÙ¢Þ¯.á0­'(ùeù±ú°PmtÒ~åÍBï€ò0Mµ<—N›ìØÑÀƒ–€ÏT]GiYˆ=O‡cžxÜuÉ%XâÓ È ·¹¹™l6K&“¡R© ©|Œ1úP=pâÌýÜ\Î⬎'Ù6”Jü~ùrî~æxñÅKðu Ãè:š±¦)¢¯X¬OŠY–"ÅÛ²ö1»Ò´PV«LÚÚª½4kËÒܦ«ë¿Ì¹œ"ìl[•Ã4!êMS*©4 L£X¬6õÊdª…Õ £š\-Ô?ÇQur5š†”C #?¨–Öß#Bz> UvA2Y=tœê6¯Ôh;Iù5M•¡¶ü®«Ê\-¨2D˽OÑvˆÌÒž!¯kŸ¯h;¥RÕ÷Û²àœsˆQ Wþ§ÃŠSfRœõ:lØÞ&ì!˜åÎyJO@Ã8XñF˜=æì…÷­P·ô®8yu»Efµêy0vZ>×Ŷí`QPßDò/*K(ò£étºJrQ¼°dPò–¾M¤9âý(’}E©T"ŸÏÛbÜ/~ñ ²ýOfÔAd0;#“É$ÿïÿý¿á.æ°BzÆaLU­“w}a3.™y„â¸"ç<‡S`~ÂdÇòœºõTf]3‹¥XʉsNdá% A‡9øFŽßJ0ÏǼä¼põKVì<ÂÕ#ŽŽð^ý?ØÛmÊ'•ëj¿þÎýŸ*} —¼ž§îÃîﻌËh¸±!ˆE “×ÛJXÁ¼gU~Uä@“£ömuŽWj½¶;bPÊSo%Vtæ¤è² %îÄÃôóôWe…×§ð4ïõýLÓt~ð¥„eRWþŠG¨¬ ¦©v‘ÕRYáujÊkEÊ&÷8ªã[ë "®-¦Ÿgpå×üv’Ueñ$YÚ¯B¸z›†+Œ+àíjŸ¹ÈÏÚoï…¥…üø¡cèQ*•‚ï«H ä#"DÚ7'Y¼a…  f‘ø•sBV6ûãv!+eLUKã$Ù£kÃ0Ãlé/D^Ù²,R©T Å ñ`…XŒÖGÊÞØØxóJýAcš››™å¨t¼\'ubTÒ•6ÔB– y)JB|ŠGq±X Æ_r ”Wr4¬Ü‹h=K¥Rð ©“išA›ÊskE¥º]×%—Ë‘Íf;ÁBBKb ßÄ»^¤šc¢Ta÷±ÇrÒþýj*0ÄÄcgÏM-"öDÔTÌ:çæ É¿hz²Ož(!Ÿ\ÿ_ 5|¨GÔ )*2®bó# )ÿº|$]ütÅ]C>—&Ê&H>ÓiÂÏ®I¨\"¤c´Q26*/ÛXÓR_ÛO#š–^s®üÎùça+õuýzæ"å/Òèù2œ³IWÙ'Ä  1¤MRt$…põ"ÿ$¬ß>N$=ñŒ%rïd$dum½åxÚ¿~ËÛÞFŒÒVÓ^;Œ¼uÙ¬Zvñ<µœ”Ëå¸òÊïpà@Ç™DÜÍŽ,Ô.ÁÅ<Œiâñ‡O=‹ñ·½¸FÔbE(Ö2èla§~Z±£MŒÃyín~ôfÖ>»¶þI†­­è$²1•J¥€Hë â¡(剿%¡„¸2®X,!f$ÏÚoŒœµß¨¬´¶¶ž™2>‘óÄ“z¯õÚbUê•C–|¥íÓé4¦iÒÜÜL.— ®7N¹k ‘(ž™BhJŒkI#ÚÖÉd’T*´ËR9fš&¹\.ˆ›%eMÓ Æy’oôžÉó iZP!†¥ŽrŽÔÉ«™—$“ÉaUh xfÚ4öïß?ÜŨB”`ì:ûÄÕ~ŽåÓbDþuõÉNÖ\%£ŸâÚ:Ôƒ<ÿüÎòÒ­»¶ˆ~£ã»¨½’GèÑ)y é&^‘ †yÂø›&Ê^¨ä_#Ä*(!…hZ¯Ï,¡J}!’w‘Pä@l†\ÿ¯Ü?-òOdqþõí„¢–Ÿƒ"tETBH×Z‰]ÉÒf?¿—Î>›!tà†/}‡Êø¥@ H4¨eÓTK=óæ½—iÓæ³eË´á.nŒ#cšxüé¸qh½ˆî*ƒÿhŒ¢B¡€®…ƒk÷!]ïy(e!™Z,K­õæ>é†BJ¿„Ö'8Oñ}µí>ú?Æ]ˆ¯~oýæcĈÑ>™Ð¾´=Ü'VÀBLù‹y@•´ÏˆGÔS±/1*„4ë ÝMLk‰­zíÖ¹%G;k÷®ÒøÎ]ð>Î[Kj®.ÎÖ#á4­ûoƒ,ªtFkZ÷u¬õ€¬‡r¹ëã†Ñý9õÊÑÒBŒjØ@úVà3а6®‚cÛÇa¦3«¦lU·õÐTøð¥0õ)È·7Ñ] €ÕséŽZÏA¡P •JÑÖÖxˆç,JdMسpäú#¼pÞ |î§ŸãÌä™LæÚË2º][2Ô“Cì ]õõÒ–…ú£ òn xÝÄ«Q\*z“Po®ÞÊjjUQܱNÏà!êeèy^@ØAø¼‰§[¹\®òì jc" ÙÕ“¸tb°Õræâ-)cÑqlw¦‚Йvm½ê][»¯7ýT½ü¢yve^/ŸÖÖÖª´Ä»¼(k%ºƒx" !˜N§Ã1iëh\Øb±ܧT*E6›­" Å RÆ…¶m’»ÍÍÍAœW‘ÕE Qňz‹ær¹ºãѱˆi‡žùþ`¨FÝ-mö¥]¦µ=‚Yg;zN¶ÎñLdº&¿d'×Ö"MµÇª¤ßÓ'0YçwtŸAµE-!\¯îrüê›o†ÛnëaIŽ~èÀÙwµsܡϪ5ì]wdÉ’×™?±bŒ!Æ4ñøÈôé¿qcÏÿΗ¿ÃÇþîc´¶¶òŽw\ËOjð± >†½¬õNRŸ‡ÖS ”ƒÔ½À&(½îs`ÿx“Ám Çá…Û ¹§!û2x¿ƒÜ(æÁ› ü’‹”Ò›ö@Ç}h%ÔO4 „fIQYŸ(¢æ<ÑRˆNz£þýQ-€¨Åm­6ƒ ªs «9²¢#Fä1÷P >*—¤-¦=Q“§¨uq½:‹up´\z$O½&oÙ¶#eºÖÊCÉ9"±$: ^¤¬ÕZ¢£ ’IQs¬4¡YTTÚ)Úžb %¦Nr¾Üs#’gÒF"Î~)¶^@‡&šh5ÃÉ%¶]íMMŒQ†¹Ká5?v™1ºâSÆzŸ¶½w3û™K9v·ú}ÖYùFy_8®ºŽ™ é åyŸsö5xj'¦Ù}y±°¯µ™³è—@@@f2™à: Pghmm ´jåÕÆ Þóž÷pûí·sN,/£$pÐ ¨1U0áŸÛ™Cû£†~¦^å)hƺ2þèI^ƒIÆá$z ™Ëôtø(¡hÍÕÓQãy›#û`–£ˆ‡xÖöB"Eå0£ïÔh™gÝ¡¶ï‹·=…ŸrŸ£÷;š¾®ëuIÒ(Ú]Ll!\eL5üª%€å‰¯=ý4‡»1F¢ojlâ76ð«wàìç–Ò ±¸Ó¡ {SÓóÀ ¨VŒ‘ ]ï›FŒÞc̰mÞ<®ì©”‚¾ý7|eã?ðÄ‹O0~çOijl`ÂÎ3yÿVh½ì3@kï&°Æ\Ÿ|Ê9È|¼ýPü7È| Ü­j¿Û¦HÇüW!õ?ŒY 2wÀý='@fxs¡ø9H|ô(¶ÞS4 ¥ö d]ð2à~ô›!³ôkÀºµÚµž"87þ($æBò50^ÄÈæ i‚= Ì»ÉL1Ø2²Œòï3¥)rBòMÿw†P¿AH²(±™‹\/iEc—D£I‹¨|3j-£™ ‹»xQÂ2ª¹@Íñèø[ˆ=IC¢¬¸•,©‡ŒNMš9Â(ÎQ 1uŠ^m÷h™å¸¬)QÚ’ž”ÑOãÄ='öì¹?ʱãs;HŠMXm¼ÂºóŠ1BñÖ“ðÎ:©ÿéÄb‚4Ç+›á˜;ž€›ÏåùçÏ ñIXðx`7,páðv`Žê6v<_?½îœP¡Z"+*«%òg®ëR.—ƒcâÙÖÖÑËJâôÈõ†ad¥ 7rðG&OžÌÊ•+¹å–[†»(1F D‚+»g(ñJ©·Ð;Ôã‚®º{CNöG3Ñ•6pD{P߬D3-IÏÉÌ1Fßáº.žç2›"ë½\=ñJŒ£?‚»7ß)§6^üÄK“'±¡MŒ1ª!Ë®o^óf¦˜¢Ö]Óa4!€K.ÙÅîÝ‹p])'^>ÙÐõîÅÉb Æ,ñhöìaù¤I=:çÆ|cÜñÜ?þËlš1›•L¥íC0íS³Ðo‚æ ÀA0ÿsJ…вaê¡.~ °þ̨mózõ7™„äçÙªóÊ~ ˜¬:¬tR6ègi@a=è§«t߆+¤Ô_PDfòCà> ú¹À"(ؾs¤ÖjHü(€ûŠÏ‘M…ŒÙQÕl«2˜KÁHøáÌ®„ô•PxÔW#Ô•¬¬µtE>F…È{ŠÚØ+µ@T¥­³N\¼5E÷ G‘»§ãÇr'Û¡Þܱµi,pé:t†l´¢ëÒ5Î^÷_}?WŽIÁ9áaüñž #<R©ð…õáºnÃ$Æ(ÃVp–ö?™cÆãë°Ïÿ ø#lßþïLxüs{ìñÁñ¹[ÔßLTßm·7‹Êu ’[ŽãTÅé5‰óÊJ½+¹ÅÚ…s×uI$T*•ánÖaÇi§Æß^v™’ÒŽûò5a R¨ñkYÅÐ* UÃà ñ”Ô“[ŒÑ„!2z ‡ÎÇýÑàY1†âÕ˜Ëåå‚|>)Æ1‰ìž£Äý»Âîce÷ŽÃ]Œ1bŒ0ˆYÆ´ÃÓØ~Êv,X¨õ~!ðƒýìÜy:§6Ü¥cdaÌ0þg?ëz0æ€{ èï€ÿùøq쨌ã ÿýž=×#{ÍT wƒs3˜–"à2ÈKÇœZ”ŒªYDuM Ýz£s”è¶ðµs×Uûä˜a¨ÎNÓÔ1] O×…DŠ7*2´PPer]poRû #$?k×4Z[ùX*©síuPø€*.§¸]×îReI§‡)nˆLò£’Gúã@§Ç.ý½Âôg§³iá&õCס½½Ã9š¦R†1F¶wbŒ6˜­mäÞ¨ä8'MZNÓÂSX¾í5ÞY†'ÂEÇ«ïg&Sý^¢+ŽO¤Õ¢äÄⲫ¾Fbôôš¦UIse¤ 5àÉåbâ1F¸€±5vôÅr¹ÉdrDŽÐ3i¿Q‡z„@ÚtÐ$s{›¬Žlx8[%Fg( A >‰Ç•_Žc¤¡·}›mÛL:u¸‹=lxû+¯ðÐÏ~†¶xñp%FŒ#;'|ƒqÆáÕÁ>z¿ï}‡ùÞ÷N¢¹¹ƒ€ZŒcc–x´ƒ--è²j(.P¥Èv šöBÛ˜´r gýigm>K—NåòwBé1—ÿ¾Z€bÎ0¦£é,¶|tü(ë!2ß‘c’¿a(âPö ‰iUjëLñEBF¸VgYªÞ†¡®“m ;åºêŸ¨Vš¦Zï“¶¢´·p]u]—×1·bÄè`ž l=¹>;%ñYJ¥¥R‰rOtcŒ\ă¿=€¹ùl¥níÀÁƒW2íxá…cÉ­ñ lŒêØò·ŽBsÇ¡¹¹9èG‰mmm$ Z[[q§CÜþBÓ42™LÜwAÿ]ScÕpíI \\Ç5Ô•4É,òÃ0ŒCÀ4•xiÔÞ «ŒHضëºd2™ üB¬„c$£·rÍXÇÊíÛY»u+ÆÇ?>ÜE‰#ÆÄ%[6ñç9ëáÈÛ;ËåšùêWïáSŸZ6ÜÅŒcDaüp`¸à8N8kB‘U)+Ù îÙà‚Õ'×Uû …lÍåˆ1Òq]ò(gžfÝÃBÄ£g wbŒHÜãö…LŸî°hÑl… Ô11¨‘½YŸq]˲ïÆr¹Œ¦i±áDÇ#ˆØû)FŒ®¼ûŸJÊ3Ù0 *•ÊàyÁõ=!ÿzâÙhšvT{t ZÝJTÇŠï $Þ}Œ…T*E*•Â0 Z[[cÒ1ƨAo¾ š¦ÅqQ†1†®ëvûÌ9ŽÓi¨ ‰mßYÚ]ÝËÎò–¸½Ñ¿Ñcžçeê¬ìrmwÇj¯æ)’ÞõΩ×Ñ}b,#iô¶^¥R Çq8tèP¯ïéÑŽãoä˜}Çò~Ñ©v±X䓟\F::ðĈcŒzÄîÝíäóŠ “&ªb6‚Ö'†–/9+Þ²H+å²"ê ô‘kt]ý–ol:­<53_ÂÕPDŸ¤ÝÜ*¨¹®:ǼHÅžLýœq*½bQÝ;É_¶"Eë8*R)t’OM!¥ÌQ’1V׋Ìn¡¦!ò¶étHV‹Š8•õÃP×årjŸÔYêëyê‘øK&UúŽzJB’êº*‡a„åM&a÷î†ûv˜† ¯o`Ùc©Q3:ÉWss3mmmGõ¢ÛQ‹“†»1F dJ§%`æ‘ ;wÏEÇŽ-°·:VK6J—Ð]EñId6› äÚ4M£\.¸·#/ŒÖ"^L‹QNt£…DaÄÆiën¢iÚ ‘¥G³'Ì ÝoÙî) bâq„¡P(àyíuÂ1Ĉ1RaF¯¿2V1º qf£p]·.Á$sñ†Íåra“hIWÊ,¤e:&“ÉL&ƒòDÛWˆÄl6K&“¡µµ5Pß‘p’GSSår90¾“ûöÊ+¯ ÷ã=¢Põ–ùŠ€¢ãH$¨ø ©”ZsŽ#Æ%¯¸â V¯^ÍòåË;»é¦›X³f »víâ]ïz«W¯fþüù½JßæìÝ˹2‰v Õ“˜Ð·‘C‡'sáÉb»s¸xÖst)…z)bÊêºÕú¥ãÆUÿ6ÍêHÜæ¢Èf«W7Å•®öœ($ Ñ0}ÓhÙ¢®}Šì,ŸÚ“®²…ÑúDó±m°miJ°AËfƒê˜&C˜êÃɰʮ‹î–a]ÀM’͆e͛¸AÞrÁÕI¶e)•|"ÐÓ(á,²+îÆ˜»cÏB*•4l¥ÕÁþÆÿbÌÝ‚6y?¸,&ñ4=lâB§å ÆòIàºxË¡¯¬ßörkʪM$ΦuÎS¸¼Œ1iú>Šyx|ð<4­dÒ÷Ò|ôQœÒ1ØmBÛ~ÎÁs°õyAüMý¤ýXÓ?¾ù<Ø Þo§£ëK1 ÿ¶>öüþ~2·½™ÜÃ+H/¹íC—à8* ÏsÁsh¿{œøLw¯É°c°û€E[qæËÁÛ;J%ضM2™$NǤãhEL<ô¾ Š$œ¸y;Y@>ׯnc(CøÙìÉzN¡P P(`Y¦i’ËåÐu=ðD¬ˆÇ$ÈX¥;–8ƈFg}Aûc AÁ. X# º®w;Lrp0Œ#Žzè„Ö®½ÁÑËñ†rLày^°@;¬sá ¤âH#SpÇ?VðÿZÔ/êDÒsPF×ê9¢¼ÉÇðóE!ÃßeŸl¤,º¿_Œ¹%Èøçšþo×ÿ—ôÿÚþ1'òψ—sSþ~#²¯äo›‘6°"åwêä­Oò¾üò[þ¹n¤-4ÿŸG}C§Î1ißèýìîq*øe¦&R¤~] /†(B"É3?Ò1˜}ÁHQ q'ˆ/ä†Bô¹®¨á¤i–e¤—mÛ444P,ÂJHÇT*…iš)'JBHJøñŒ“ö1MÓ42PúI˲‚mMÓïÃqãÆ‘ÍfñŸÇ0Œ`\’ÉdåÓ4«ò. h6› ˆÊèx©ä¯çš¦¬ûˆ"Hò>ÉoÉÛqœ ½MÓ$›Ísºr¹L¡PÀqœ ÌÉd]׃ôÛÚÚÈù^ ­­­èºÜãè9BLJMÓ¤©©)(¯·‚l6[eH`Yº®±„áÒZêUûÜ_}õÕÃý t‹¡ÈS³ð–Oû 5½”gúR,FŒ£#Žx¼å–[X¿~}ÝcÒqH‡qÓM7qÝu×qÇwô*˜²ukõŽÈØJסðõ¸kþˆŽKö ÿÅ{Çý7ï¹`p<Ø0Í®õÖ¢‹\®ë³Lˆ›šlwü0P±Þ±Î˜¶j’Fóî*Ÿ®Ž‰[bgºÖ+«¸çIõÊm«ÎÒèzp®ÄŸ PÀœséóP¿_>¬“Ó4ÌÏ…u GÕYû~¯Ü`Íêù>àdí-0ÉwYœ¬©ò¤Ï-Â냅QÒwSp0Ü­Px<ì|?hçR3˜pZ`¿ö6ìH¾éôYí¾¤:~gæVpNYø%àñ×e¨1ý'Á†öï²”íÕ»™pŤã(ƳÀÒá.DŒþ`Hú€­[Y´u"î“Çs܉O2{× ^agŸ“}9õ®>YQÈ"€XÉŠ%ªX½†ã8d2Òét0Á1ˆˆMNG=:ë úÛ¸€ö2`¼“#ñ}ì‰Ôê`’ƒG³Çã µ[_££·™C6&@-ȦR)`ƒÄVÕ,næk!Qµ4ÛýÀ©|Å„ëüAG(Ûð\ vù†À LØèßÊÀ:Z ñ­ªWÏeÕ³(ÏV.AÀf€³ÒðtV•I~’‚ý.Ö`¥{ •–æŸÿhJå?Yƒßð¨äUþøeüF ¦éð~n/À•mài0˜áÀ±~C|××tXžWóý’ß6Z´!íÁvæX ›Šp³?¸ðœßw@3à x&4ûu(z æ;ðœs x]ƒOa;d\ȹö™Ä+=ø…’’%à%¾Œ:^ôëïBÀfýóà:5ϧ6ÜJH¨$hõÿ6ùyq+vÝrŸ„œµýô“„D¤üÕü|…´u#é°ä•%|ç©ï¨¼%í¼_ÏO#9¦AÖÊ’u²¼úÜ«ÜÑз÷f¨0X}ÁK/½4äuI¥RA˜L&"+—Ë‘N§RQæQ2Q­¨‡cgabdašf@n j×CWãÃ0b2]µøT·@Ó´*’+º-×GÇbBÊv]õÏr®(ÎÔ#ã{2茈ÒV< kïk:îQ½² 9,‹õ m•Ïçñ<˲H$¤Ó骃u9Hy¬r˜š6‹ÿáJÞ÷¾»ñ®º‰÷ü´æõÕ‰Ôzûu‡z¿®wô^¬EO>=I£»tº;Þ“²ö¤Mz’Ow1õºÉÇqÀÍ—1 ]´MOÛ¾»òU›ô0Ÿ.sòÓ(]}5—1ò0¤ýÀIðF~Ìë®crEF,ޤO1zí50pâ…¼Q‡¡°u+Û½…xå/þÌ »§ð ¾§¸ß©&“¡\¸a(û˜ÚîAb8êºN±X ,oÅš6:™N§Ó±QŒÝ »¾ ¿ý€ 0zÏCx¥ú f#G3ñ7Ü´¶ï°Þ@§¾§ÚÇ Ç+we¸"ž†:jMaƒ ÀÐtøs«z„ì)ƒ):ät˜èÀ­Ü•Wi´ ix°ÇûK°Îƒ¢ß'Àš¼I‡ËÐhÀf>3º]‘t"Óð„vàéðá68,2fèõhàÇî,Á%ț՞•3’ð1 ¦¡òøkBnð ¸& {=ØáB: YžÕ Œ×๤¯_ŸV“vK‹xzДS.1Ê6 Ë 6üØ7¨žàÀoøç6HjŠ|h.©kçzàd`SÚŒ°­2( sìNB9™ |934øYQµ‹¼-ø×xi8ŧßF$•Ô±Odà>r,ñà/³òÓÈ7f`A ˜LÕ@+†žÒ«møTt(ø÷ê-Åp êd`©Q*/7j°R­¡ÌþÐlîný1‹&ÞoΆž›â±¹Õ;wf®oÍCÖàÀ·ppêÁ^¿3CÁî ¶lÙ2(åÎd2ÁØ_ÐÜÜ\5Èd2”J%lÛ¦­­-ðü1›Í’Ëå/Á(d½¢»ïÙ`yrŠGewùK|¡Rz9YiËÁ€HžÖ­‰´©Ä]µ]¾%þ¢¨èÔÊ"G¿UGûÖpŒ úÕCüJñØÖæâ8^Õ3fq¶1¢1Äãòå˹í¶Û€ú.ÝëׯgóæÍU.ÔóçÏgñâŬ[·®W‡Þô2ï¾ïÎÀg‹8±0PN¶ çœó{÷.âÁ¿Ég?û/|ï{×÷8ýà ‘u]u?c»Ñƒ¡ê\`÷­»y™,úâëž#žH1F/ŒeКCYÇ ‹£ CÕˆš—ûÔF8y!L†W×´òâþwa|]ÓTkPž§¾)É$ìÛ·8§*=]×Éçóåª,(ÈdP&Ú"4RIŽ1F ºê ª0~/¶¾8b¤Õº…m‡AÑcŒlôö‘Їu1”ë‚R©D>Ÿo=OM,Ö”àmIx0«ˆ"ø†Ïð½) ÏxJT<Óò@¶MMP7 ˆ¢÷™á@À‘Æ$ Åóµ$hádO UƒîšþCÊ DHºŽaT>zb'Ð4øY'cÃÏ÷Í‘¼kû]M뺦G«Þ³´“穵ý©X›årê¾K9ÿ%ë¼µßuU^µ†dí.¬N†éPWä²SØR^šÑz÷À„µWËmhZõ-× Ð|’Ùu}#äðð©ç¼ÿ^€ŸdÕ ¶­·ªAÁkè Á¦Onâ@ËF"†¢/H¦T*¡âÅ(D”ü“¹‚È4zž‡®ëuç#uÞ Þ–=!>Ũc(ˆ1MÓÉìÁj;16­…H¨ÔØR<]À36 Çq( äóù༣Ã1&8ýÖÓy‰Ð+Ú¶!‘ÐÑ´†à]–w ¶-Ž#Ĉ!çϟߥÞòÎ;:h7Ïœ9³S÷jÁîÝ»)•JlÞ¼™U«Váï|x'^û¬È ‰F»QÔA³ÙEœqÆ6m:DJ.Å親¯Æk2Õhii¡¥¥…íÛ·wQêb0û€íÛ·sÓM7á®^ Àãó.eE'ï·øŽ1Š• ŠQ…›nº‰-[¶0cÆŒá.J] Ř ¥¥…WV¯VÆåGއÊx6mÚÅþõ.Ë.GÊC0 ’IH¥þ÷¾·ÚB5—ËÕµæ­\ëº~ÔO GDïÆ¶ck¤6oÞÌš5kxôÑGëÆF èª/èï˜`ÇŽüéÉçxçŽÓyøðÃ=76’p²Ø›L†`K¥jmæh55U°Ñ¶Îå:jdGÓuœð^IºŠkM»öœÚc…BX_Põ¯õf¨ý¸Ôª£ØvXvÏSÛµmW›Fmåy}©c²ú÷ç±eË8õÐ!F"{~ðè£rÓM7±jÕ*æÏŸÏßÿ>o|}–á¯:@SÌÑá| Þ‡íV(}i/˜Š8(â1K„óŸ·è¸4&›‡¦òž˜fÇ~T_%ýG½oG=âS#Œ¡Ù“ï¦u­šÔÍÊöEŸý,|å+abšÝ¦=ÖçëÖ­ã˜cŽé[á$vª^ =*žŽüüÿùãè‹”ljÙM4p}‰Q›ê8ÁA¨ ÿ¯Ku añdÆkòR:¡DmlX¾IƒG`š&?þ§w;Ž’¸‘Ceè%Ò£ÃaX–L&ijj°µd‰á)õªM7Jzõ×x>^3Tk†Ë—/¯JcÊÖ)üò‚_bÕÚ•gºZ>x¸[)FŒþcÍš5<üðÃýŒâq01iÒ$/^Ì9çœ|ƒÝ»ïÍ­4Üߨ±ŸÆÃåUŠÝYËÅqp]µÑÖÖqž?Ö1þ|–/_Î#<2ÜEwÜqUƒ‡ç¼X÷<‘±ˆ1ÊaÆœ‰Q…åË—óä“OòòË/wQ†2&8ûì³ùj ˆ};˜1áë×bá1Ó˜±A‹·¬Ð˜%®]Óu±mÓ4q]7Xµ,«GV¼£=®Æ¨B&Óqñ03gÎdùòåƒ&-6Ò1yòd&Ì9.öø}é÷$—×!žjÉ!þ \t–ãÑkQ‹t!“ºZ2 õ¬ÖÆ|âȶ«½k’I•¦ã¨Nª¶ïqEjZÇcQožL¦š°”ú‰ŒH=H¾RîÎê%ñìë-¾É@]ê[[FÓ Ë ñê%Ÿl6$[kïU”àâ- iÏhÝê‘võÆ‚Ž£>ÙlH<Ö¶›¤-u¯Í[¼ :ƒÜë®Ú6Zöz䉤!éˆWSí9Žƒ—LÒø§?qÊ%óæÍcùòåÌœ9€ùÿ÷|ó”„ ¤Q±¯oƒßêð ¿ï‡þÅòˆÔ>ÞJZ4Æè†¼ß©TõÂBg^çâ[oŒ'„ÐP‘ÍÒ'HÿÙ¯±>?Ø·o³fÍêx°€’L6PÄv.|ê Ÿ÷Yn~ôf*³*¬¿}=ç¬<‡Ë']μ©óp…³‚ö _’ØO³ŒŠµ©ù¿Ó‘cQH¬Ðè¶FH.¦Qý•Kè,-ŸÛ?·X' ª•f?Í´½xdK}Ó(ƒ €v”´40ïœyÜ¿ù~õc\¤L5c€…˲ôÙ¥aýZýv•8¥nMÙ²~ûH==¿¬‡Õðó)¿š¿ï¥õ/1á ª";§jùiE!žìÒ†f{¹ªÆLõóØzòVVZÉYOœ–KÊ,’Φ_»æFó˜¯òÜDKä‚fjüýûÿž•§¬ä2ó²ÐÈÁŒ¤aù=Ÿ”½)“ 7-dž;?ú3c²f(ä¦<ÂÚßÊÂÉõe´lÛ±É1bôçœs»wïî÷˜`L'Näì³ÏfñâÅÁww²»ŸCWªÉ•ŒÅdž¨æíñ‚àh…ÌÍs95ÞŽBˆuÐ-·Ü2ÜEL›6- §o˜Þéy^W‹A1b÷`ÇŽÃ]”!‡Œ –/_Îñç‡Ó/áõÇÇ1kÖ]̘qýÐ6¢¢•ͪoŠ@•¥©ã8ضÈ'õ„x5²ŽGb劺˜1cË—/§¥¥e¸‹2,˜„îyL¾ö›jQY÷3zõ² öX<úá8ê»Ð‹f×U$e½÷Wˆ†¡|fL34>èÁ¸s¬ÏfÏžÍk¯½Vÿ„,¡· ßlY´…}WìcÎ3s¸õ´[ùÞsßÃYéðÂý/0ÿ°ï‘%D“|*B¢JŸ¬ž<6õµJ'ÛÑòu‡zix„}›ø\H¼áixM I¨ùi¸0©0‰¥›—²ÖX[‡œç˜3´˜ê°?V2Šq´bñâÅìܹ³ßc‚QG<®_¿žÅ‹whŒžÂÞxø0sÍBIÎ6?ìÂ?þãg¹ýöoÑÚ›)ŽV¤ÓjŒ¯ëèo?ppüÕLymCÝc1ñ#ÆèÀ@ô% ¹{2›÷À¶‡çóõ¯¿Î[ߪŽE•ö¢kËŽãàyžç‘J¥Ð4ÖÖÖÀ²'ˆ½ªcÄô§°çÁÇ_y]×ñ(„cww½Å¸qj¢Ñ׆Z?ôDBK$J»#§$ÝÑЉtªHÍÖÖCÈÀþÆçéΈ`ñ.ÌåzäAcèÐï1çqâÏÎ^ÈG9É'Q úU±õ†»¦1†ò]è ä¼z B^ ew;FåŸúÓt©B(ú9õ?5^„5Õ"û­,žçq±w1žç1ߨ‘ŒöQRM3Hjˆ‡`=˜œÊèêúwòÎŽçêÓùÒ¾T}}•uuûuÃÝV]ßÙûIcÒ÷'Õ?§»6¯×eÂ{X“Ölf3ûó³»N_< Hzõòè~Íc|§Îñè²vôñ.ùe>Ÿ‘z|ùê/s·õ #±N…7Ñ rÚiÁo]‡óÏ€d2ÙoyÛ1ŽfŒâQ,Ö­[WÕY´´´ô*8¬ ÌimejÔxØumn¿ý[¤Óé8¶ã(Ç@¬=ÄY¨~àòß¼Èø»@Ïó‚ÀÜ1bÄ™ȾÀ ×Âôÿ»…݇W0uê 2õý(Âue ©alR©„išÁd#öbÁèÍÂaŒQè²·ÂëOnßݾ¾ÃÒitFà‰¬J_‰Gñ²"Q¼j:#MSyIv‡d²åj8N祅‚ZìïŽlíBböäœÑ@ØŽ ؘ PàGŽÐМOJßÅBHc¶Ý;å]ïÜ:êù6¾}ŒH@õ·/ؽ{wøCî¡xÆEbÿ8p€{ï½—{V¯fá'•W˜¦ih¥RøíùðÎâ9CÑÓ ªX2Çé÷V-¡Pèø¯ýö57WËjc5×Ë'›­+÷$Ÿ„ÒEýÊáÃj»6Ÿš˜É:tŒ7\[ÊRÛnQÔzõׯf®—Om æÊGïC>¹\xJuò©×&ÝÕGba÷´>VóeÈu‚(v¿¶»Š`ô<عót4íàpW9FŒQC<¬ZµŠ5kÖp饗2cÆ n¹åf̘Á¥—^Úã4`Éÿ—¯rE`Ù! ,œŠÅbì‰0Ê!q¹â5Æ£Ñ(xl™{zÕžR©„mÛuvLjcda úíhaóÃÏóèL)%ú=±m˲‰Õ8^ã‡È*ÆýúQ‡þöéïÁ>ñ)Ì~±ñ<µˆ×ñØ)™¨H’^&Ó¹hOdŸD¦u´,0ÕÊ­F1PÆšÖq®2Ɉ'#1&xlÙ2þêðaÚ&^Æø%¯FŒAFoÞu]O»ŒAGú‚—^zI9Ð56ªoJ{»òhÓQß?¶îž3X¸pau"aÞäø2Š\ uL£–<ªýFGóé,³H±‡V“KœhI«6‰‘\/^qM}&ȸãhø.Jë7„,£­z1›eLXÓFUˆÆq–¸Óµetk[ΑãõÆrÑXܵrý’FmúGÁ|iàÖ C|õH†l ñ¸eË>Á<æUíÓ4-öxŒcŒÁ´m~ô¶P*U¯]'“áús©T"™LÆc„шBAÝ\MS3Å1|hŽÃËÑ—¾¯ä`w$à@H­ÖK³«<ÆñLWÜu}àâÅÞìc»Î;¹OaÁÅWwQbŒ4 ¤ÑH,¬5¢ñÚôéð)]É,û^ϧùÿd³ÙS;ш‰Ç1FàÄcþ—Å §ãygãyÐÔ®{*K—Nîâň1â1~¸ 0”ðó)(ã2þxÛͲDNÍ£µµ•ÖÖÖXj5FŒ1€mÛ¶uØ—Éd†»X1bÄj̱˜xø –-ûT‡µ¥l6\»U„xŒ0 Q*)™ËøÞŨÁ·>úQÖ64„ÒxýyFºŠµ#±”Ý¥w4’g]‘©Ÿûh$mct‰‰O<ÁþÙ'ÅqcÄØöÌ4%ê;­ lÛ<<ÄB,´#ƈ‡{ø0ÿêN8n7Ž£ì=.½ô6nÜ8ÜÅ‹cÄcìy<¶Ã]ïâÃÓÿ£Ê(¶P(¨ ѱ%|ŒG=Œ-àà`jáÂ’ÄÞL1bŒ ˆ ‡Š<<án}èfZ[C¯Ç(\×%›ÍÆÑ1behŸ5‹3Ï?_ý8‰º1bt‹Éû÷3yÿ~Þ·ÿ+Ê )FŒc3ÿ8L‚~@Ó4ŒÁ”èû›1F<Ü xÒ;›û;€|^¦9›n:}¸‹#ƈǘ"N9v;wb“}ã´*ÃX˲b/†1Æ<@{a-ó¸ à ̱\.wcĈ1D h=ÔÊܹo¤P˜‡ëV;»455áy†aÄÄcŒG\× Çÿ1ñ#ƘĜ_äà„©ì=®BCÓ%eM ì=OÅ‚²,µÏuÕv¡ ö‹:p2©âFyž (ÛÙ¬:§¹Y]ŸÍª4 ¥8,ai‹EH$TþÅ¢:Ôµ®†,Bµby‘sZ[Õuš¦òÉdT¤{4Mصk=t2gµ—k¯E&ííí{ì±¼þú þú¯7ðÕ¯¾={&ð¾÷½ÌŽ üö·ãسg³gïâŠ+fpÜqÿÃOÚÄæÍ¸óÎu¬\yNІóæä¼óþÄSOÍ£¡¡SNÙ΂ øÞ÷ŽpðàA˜Àý÷oæmo›ÏI'íçòËA¹ü¦N=À”)S8ᄸè¢S¸å–,]:‹]»nâ©§¾ÌôéÏ2cÆ©lÚô÷w/ñ»ß}PícÛðôÓ‡xíµ?³eË\N>ù+WG©‡æ¯ÿúQ~ýësƒ¸ß3fÌàÓŸÞÂ'>ÑÀ”)SH§U;*ã5ÆÆqLœ¸—E‹öñ«_Ì 'Ë7Nâÿq÷Ýw|˜/|a7<ò=t2]ô4‡ Àxä‘G¸ä’e>|7{÷^ÆþðýׯðýïŸÅi§µ³aà N8á>÷¹ãùîw_gÖ¬YlÛvû·Á¶3\rÉçù«¿z™ƒç1kV;¯½6}è1î½w »wïæ’KãÁßB{{;§žz*›6mbÕªÓ¹ÿþ§Y´hòp¿–ÂiÏLƒwªmÇqÈd2UqÝm;ôv2MõN%“± FŒG+ÄPyŸsÓ¦fÏž X–úV666sà ÿ ¬îbƈ1¢1¦ˆGçÏí÷߃aÁà_ÐÜÜL>ŸcÄ8Êáìmg"gUí7M³ÏâGMâ Õ¯$“á6„qâdQÀ4ÕÄŶÕDÔÑzܸpÛ0ª¥cĈ1°ÐŽÀ¾Ë÷ñø—oãk_»„cŽ™,èÉ{gš&®ë’Ï燻¸1úÓŒ;Óày^¨t+Ĉ1&±£¡—'¾½ó_¦¡ê±P¨ÞåØCõc!'@ísµÏ4ÕÜ@æ ×UݦÁøñ;?Þãðáy45MàòË·°lÙ#$ xíµg¹üò·òôÓÿÁ5×\ÃoûS®¾ú}|ñ‹Çþç×X¾|¶]`Õªñ|øÃçó/ÿòß¼÷½KÉåÞÍÍ7?‚ç}Ï}î§,]º”\®Ä·¾õ->ò‘kxöÙgùå/÷²zõe<ûì³üÓ?ÝÊé§_Κ5k¸øâïrë­?ãÓŸþ(+W^Ãg>ó¾õ­1eÊ—1ÍEضÍáÃó9å”C<òÈý\xábN:é$öï_Ï?ø6oþ>×\s ·Þz+o}ëU|ï{ßåsŸ»[o½×=›¥Kÿ“… mñÆ7NcúôGÐ4––»øð‡?ÅÆ³aî¹æxàæÏ¿˜Ë/ÿK—.¥¡á ¾À}÷çÀ­¼ùÍG˜:õ óçïeòäW8á„ÌŸ?ËšÄm·µó¦7Ígüø \p_øBŽ%K–ðàƒSزeLçàŸx'ßúÖÇH¥¾m–\.ÇÇ?þmÎ?ÿo8昵œxâ‰Ìšõ~ýëqäÈfR©«I¥,’É"ùÈDþã?^`ÏžiìÜù¿<ôÐV޹×=À׿þ Ï'œðÏ<3Ÿÿüq|Ë–}ˆíÛO!‘€ Þ̆ ‡8öØûùð‡ÜwßFN>y »výM{MÓ©TZ¹üò7ðøãó–·ŒçÖ[ïgùò)üüçk™;wlÆ-{æ+ϰ|ùòà·iæ±íêPᆾ¿ŽÐÖ“1bð}ó<ÞÀ>ð*ßÿþ\µßó(‹±óRŒ=À˜"ñöc8/àjZÒ1NÇFŒc;v`89Ö’ówyžGSS­­­þoõÏuÕB(kØRIm;ŽÚŽZ7g³Õ‹b%]lõײÂߎ©”J¿±*µ_¬feq"^càa<³ŸÝÿ÷OL™r!wܱŒZnÑö;€X†}”#ödÑUF-FŒ#“÷ŸÍŒý¶~ò™ºÇ35O&Ãq=¨ß†¡Æüår¸­iÕÞ‚ æ¶m£ë†QÀ4Í vœêƒl‰Éd¿ùM÷w_äå—¯eöì;xýõ-,]:×ÝÅ9çä-oÙËìgýú-ÌŸ˜óÏ?“uëngß>×uù‡°Ð´©¼å-{I&±|yËZÆ'?©¾…mme4Mã´ÓÞƒaœ‚ëÂó<š›Ï ­­ Çù0–eñÿðf ãtn¹E¹LV*êúo,S(Èå>F6›Å0N¤¹¹™r¹YO¹€~TͶ>ùÉœÿûU¿?ó™ÎïK¡°…û·Ïà8eÿ:ERþêWráE\=À’ªë?ö1Ùú¢¿Vø¿WøõI“Ëå(•J8ŽC:æ¿þ+¦i|úÓjA¹½½ˆ¦i\}1¸¶P(P(¼Ã0ض-ïçßF&“áé§]n¼Ñôc®ðËî`Û6®ëò?ÿs}‡z~þó²¥Úäío70ͳ 0’ýÿW-xw´“JýÍ¥±\wŸøüìg×øûOõÿ.‹œ+í¥¼,ÓiuïfÏþ0---Œu\|ñëÀÛÑu5Ïä(ÊåИ ^JŒã胜:~&[iÇZ>/Ø_*•ÈårUÑ1bĨ1E<:§4pøÐËègéU¡çyxž7ð¢cĈ12ñç¼6uZ•¡ëº´¶¶¢ëF@(¦RêX2J%¥RJÓ=™$Xˆ®WF»!0dqT:†Ñqb’Juܯ늌L$Bï«ææp.§&:ÑIP"¡Ê%„§È4úÉ„^”òÛ4UzµÇK¥Ð’;-=-+ôè,•”·¦¦©òØvØ6²H“N«4DÒIÊ“ÉTKÓD½Eu½ZrJd«bg¥Žϱ˻‰3ÎQ 3º®þÅøŽw¤{ŸŸ5‹7ýû¿³jî\rkÖ°cÜ8fEÚ¨žåçœÙË–ñà¦MÕåÊfÙüÀ|qãFÜè~ßENƒºõ0»j‡Yý»—˜q3ÌÚO­¤Çíf î L;þx*“ǦÔ*¨ùè׿¾ƒ·¾µ…ÿüÏeÝÿÊA…“bĈ1‚áí€SÖÃï¸Ë Ǻ®Ç†É1bôcŠxô¦Na⎠èºè²Ëd6FŒcδ9¼ñð²*âQÉR)ÏSdZ[[—ñ%¤coàº1ãÄà! !£1X:”ÙQ× ñ•i’Øâ)Çm[O$”5fÔƒÓ4C¯ÎL&$÷¢d‹¿&UµÏóT’ÉPFÊuÕ9¶­ÒˆzvF½=ÅT~ !›LªkK¥jVˆO‘©Õ4ƒFˆI‰S#F_`¼¶‹O†Y³Ncï^µ_žWÃp)•Jñ!FŒ£¡x"$“ã8hš†ëº˜¦x8yžG.—#ŸÏ…ljj"›ÍV‘{¶mÞÖB„†€ŽãäW©T MÓ‚ú¡&û$}!çLÓ ˆ²hù£í"šš¦áy^¶išÄ”·ù|>XˆÑuÃ0‚ô$ Ã0ªÎ)—Ëɪë:Ùl¶C½årÃ0êþ•òEëçy^PG9§­­ ]שøòBJ= ÃÀ²¬ªk$i“r¹L©T ÈY¹’¿lkš¤½V×uòù|—<3@U;Gëgšfð[î™ä½¦R©ày^p´y{{{p_kÛWÓ´ ž?úцðí9xõÕW° ƒ~X߀ðÔWÀž è°µP$àÁƒ¹pëV6mÚÄó *Þßþýû9ýÌ3™r l;ñDR©³fÍbÕªUÌ«<×f͚şþô'NÆO›„äà%—\Â#<©§žäW;äõPd‘X±‚Ç{ŒóÏ?¿n½:×5ÇyäN>p€ §Lé²½&OžÌùçŸÏŸþô'V®\É’%Kxæ™gXÐñØÛẠ,Y²„{ï½—†´Y´¢¿Bnº‘:K;ÉuÑóϽè"ß²…Ï<Ã’%K˜5kVÝ<\?mp'Ofí‘#üÅ©§„*~:öXþâ]ïêÐö®\‹lKz BâO—k£éK½ä\'’Ž\3g¼¸¶ÌÉÎÛÉñ¯-DÊ7~î\–ÏœÙË;vô •‚íÛ·ñ·;µGŠC–ÆadcÄ8ºà„“^„)S~¬É)ÿØÛ1FŒžbLS¨ðúª%d2²@1bŒLš‚öÊ©Á”뺼ókqÝ7ŸL2¢k‘ý™HDI¼zDY6«&,õÔ³YUé¦Ä°JÎmj Ëiš!1*%f¤xJ:NH†‹ør<ŠäTÊ,d`”L”Ø6ù¼:ÖÜ\MÒJ=š›«ÛLbÜ™•³u]u¾œ£ëŠÍçCÙ*É_®Êööð~år“·1btÀpp?mg1kŬ€x”w´v;FŒG²â†ßK¸®‹çy …*¯@ñH¯7ñx"N(˲‚Èu]2™ º®“L&)—Ëù˜Éd‚… ±¬â˶mJ¥Rà×ÚÚYÝÕMú5!åÜ( ØäÜÎþöåÚ®úÛ(éÙ“k„tëª^rÉܸ瞫ˆèœ›¹ûnÕgÙK.è[À.•øþ îKëÖ®ëö¸.ßx"¹dIÕþìôº AÜ™Ÿ@ñŠž_Óˆ" [§Ö¯§eûö.ÕèÀK/Mƶáúë@Óz|Äo#ÆÑo ¼a×föï?#ØgFìí#F/0fˆÇ?úV[ë˜ËS¼©Jâo$I,ňcpáí‡ãŸÞÉž3‰õ¼ÂSOÃC Ž÷œa„‘\.”²ÉVϪRâJv¶ŽM¿³uBÇ Ç|^‘vBÒ A)2©âI(éår!Éh¡hCƒÚ/y‹yssH*Šä«ÔÃ0ªcã©èº¡Ä¥‘R/¹BÙ[ñ|”|m[šâñÇØˆÑ#lÞî±üŠ'É.Ÿ<˦ ÿöow‘Ëý]lÉ#Ƈx® Égš&¥R Ã0(•J‹ÅÞ€Éd’††,Ë¢µµµ.TâA(! MÓ¤P(tJâY–…mÛç È©æó½„£úJXÇ™Ø5{6®»3§zpÏÏCåD"ÄeÚ¾B<[Sß!é7zš¾.ô½©‹xë6û]¯ä¨×rOL&‡¤þ}®÷Þ`6Mµ§åXÅ}÷Ï9çdÇŽµXVÏ¿§Q#á1b=p÷lçk‹\sÍB C©ˆœ}Œ1z†1C<,Ør„çÇí·Oò¥½ .ÇH8ƈc`á̃++ù­\^}õÍ‹/cS%?éZìn‚utµV ’¤­­iš"óºZkŒzBHмªm‡ž†b±™Nw$bMS+dh2©ähJ%åõ¨ëª›1ó´mEºJìFñÎ,T9$?‘‘Õõ°Ü–¥ê^*…$¥¬ D½S¥.–¥ÒmJbt¹ìñN`ÒÜoÄ7€¦y¬X1~4žPĈ1–!ÞŒ¥R)ÉÓt:]e¸X;Èçód2™Ï/$æ^TÚY$0;CTµ½½=Vp‰£04¯¢ä&­NÆã‰D‚d2I±Xp%„Î z»°9”„øP©Aôăz êÒ›õ þJt6zËA÷²>z°{÷±|ô£[zM"ŠBQŒ1Ž.¸'ÏᘶƒÜê¬â–[Ô>‘¾#FÏ0fˆÇÝÇ˼öƒ<>{ÖÛÅ3'Èňcì õÉ›¸DKcÛðê«×3uêåÀ¼AÉËóBïÂzÄaO R¨¶ÝQŽUb?&Šô«íÎ$~c”X‰J¾JÜÇhZB.ú!ªˆH!£ò®¹œÊ£\=+Am§R¡<¬ä©i¡‡g&£&dž¡~ ­G©Æ–bRbfJŒK]Iب§dk#Fgð^›ÌæcãyVÕ;P(( ±·cŒcQÓ´@¾4êÝ=SJ±,«Wña“¾Lc†at¹°Q›G<Ÿ‰£ïp|£ºz¯\¡P ›ÍyÌçØ0:FŒ¡Å'?¹‰uëÖõú]—0 }ëLjcäAìæ9Û‚}™LÇq(׋‘#FŒº?Ü*l˜8‘C‡_á•)KÈfC+áx’#ÆØÁ¡ãŽà"w¥’A>wÞyù ZÓʆã„q ûr}gê?†zÖëÎ$."Ô?.„ŸXÆjš"%ß\N¥H„¨¶¦•ͪ}ò[HRë†ò¨ ÈÉT*$2>Qb£7 ÑÎ$s4-ŒkXXÌåB‚®ž e…Ò« ò‰J¤FϲϲÂIˆŸÑë£y•Ëa!”N•ú‹¡”,("³6Nc:æçºêZ)W”2Íj"THS!Ce¿xMÊïB!œ<†òÆlj Ë/„q4>¥ä—NÿÿíÝal›ÇçñŸ›6I7UÍm·["9a×Ê–Úí^m{@Fn%°W°Õ{€x€”Ã1ïPä7p 6°kˆÞñpÊ‹bÆ·IØF:X@QtýôrkmsX3¸9¡7IÔVÄ:Èmº=Þ v¨‡´$>äC>ÏÌÃï0`‰äÃù‹3Î33Ï<»œõºtèPk¹Í®Wæ÷ ÁsåJã1ÿ1¯\iĵ±±ûw¿x±õ3½r¥q¬z½ñù–þð?­Ó§¥ 9sF·oߎ»x"¶±±¡'N4' sK¿­­-;wNW®\!'Cà—¿ü¥FGG»'4çÃçÎÝ}^æ??ôŸÇfñìÝçi»üçíÏã}ÌëâˆÇ,š6÷ÆÏ.ܽÈûôé»ÏûÍφ¿|.4$onÞ½c”yŸ……»ÇuÌ­jÌBp³˜ÚÏ_¾ùùÆãþÉY³ðÚŒY˜ÅÖíõls³u÷'ÿÂbsÿ¸†™7ã-æ5££»Gó¸ÿ}¸à^ÚøùÏõǯUuûs¿’ÞoüîØ±c,Pº44÷ýüCÝ·ý[zä‘74:ú{ÚètÃ5‰ó¹×^SýÐ!ýÉ?ÿÏš?!ýéŸ~V[[Ñ,@ð_õ× óš'žht÷º}Ëèèþ[ŠúÇI‚,ÖöoÇj´w®Ûãö‰Ì'“‹f¢±}µýXþILs2qæÌnìíñûãöOpþ“ýúˆ{Mê^»¶·éÜï÷z³%­ÿÿçÎížL:Ô8^§¿¿ÿ8þ“ÑQÉ?ÖþYïwKŸííÝc´ÿíêuÉó f¼ÚîÌn¦ïãßÁ¼ÙZݯˆ3ïÙþw5å3 ²üßÓæqiw'ó>þ¹öÁ?3ˆgb6å5÷³Þ«,,ì^ña3Í ¤‰Ñ,\2ÛÕ›ã™òú_gŽÙþ>Ï>Ûú>{Õ#ówØÞnüß?lS_ÛËê/ËØXã½/^”Þ~û ÛKݺ5¢­­ÖþÕ¹sç499©±±1¶<†ÄÛo¿­•••@[ª·3çY{—µŸãôúöçwz¿¤¿™$kìZ·û˜™83ïo¾ËüÆÆv¿ûÌ­bÌNþ²›×í.€nŸÔÚÿwºù®ÞÜÜ]Dmloï.þö÷ãL?È|M]¸Ð;kü¿½oyÐİé/˜‰Þ×^ûƒ ÚÛŸý¬ÞyåýÑcoét¦ñ»……"]š‰ÇWýœ>z÷–ææ®ik«±Ãl”7`¿GnÝÒ¶FõîýYý§÷3=þø‰HîãV¯÷¶ÍªÔèD^¼¸;8Ø-ÓI?s¦÷‰Oÿ={yýÊJãõÝîJ±¹.vs2Ñ˪=ÿ A3¸ÛùùÖƒnwè2«çç÷Ÿð<ˆ¹¯f˜Ï.É^»yS’ôлÿK££_”Ô¸²Aâ>iÀ01W'|úÓOëý÷Ы¯~BßúV°×vˆ2»˜¯ö…2íƒd{ ˜ùÊÌJvsœ½Ža&+Íäœÿ¸f@Í¿2¿y ípíeô?×Ã<ÿvïæ8fÀп(«ýç½´—Ï<ߔӿxÊLú'nM9Ì•æ³iÿÜüïc5µo‡Þþ^í ·L¬f2³ý=LyÍëÆÆv'BýÌ„f§¯&ó7Ýkë}SoÌsÌãæ*óûŸýLCéÃï×éÓ¦nkkkK[[[e¼">ø W3Yf¯EÑ{=.í= Úþ}¸×söÚáé çùZØë}ü¯Ûo7+ÿïƒTŽŽã_°¼ß¤o§‰áÉI)—»$iµs!jSÒ/ÿk}ïGÛza£± i{{›ÅH@—†fâñ¸w]ùדz/ó;ÚÜÜl0ï=ø .몶ªŸ×#ü“"é8œ8±»R¯[¦x½N ]¼Øºš¿[í« »eõzù3›{¯±_¸°»Z°—[óø·éåýÛÝúµ—ØÏœÙ½Ú³Ûc˜+(Ú\±ëÑ¿ÛÒCÿâï%}Q›››ÚØØÐ fÆÀPøò—ïèð᣿ýÛïjlìSÍßû¿¯û1Àäuû]5Ð)‡û_g v¿wÛÔ:cjÞç ] özÎ~ š:ý]Û·ˆïtŒýžÓMY÷û»ú_×¾k„´»è þcy¾ÿjHÿ1r¹×:¿8>ÿù›zæ™ÆÿÍÀ"ý`ø|ç;ßÑ×¾ö5Ц¤ì¦ôÞ?>ø›Ûe2ЃÅ]€¨ü«ÿú)ýìÊoë›ß<¬ÍÍMN&€!ôÁ½÷jS ¯}å–Ž;ɽ¥Öí=zqíZï‡fà±^ßPó ++ 4ÿ¶\Ý2[}DûåË»¯½¬59ztw‹¶^bÝÝî­—÷~öÙÝm^»e®¶4W· Õßÿãýú¿·Ð;ïüKI+8‘†ÏW¿ú+}÷»Ó‰kÿ,ƺ÷ÄOèôéÓz¶Û-:$Â3Ï<ä#™á§µÍÿ¢â3×¹sç´±±¡£¬èºæÜÄc±XÔñãÇ5>>®|>¯jµèuùöé‘OÜÒ¯~õº6{Å`…^ó€$]–ôè—?Ðüü|d‡ zÛ.Ók¼¾—âš×˜›³wËlõÙíV£þØ{¸MF_b÷ÿ z™|[Xh¼w¯ãOW®ìÞG¡[fk·^è­ìf‹>sˆ¤ê5üî/ÿI_®é+_¹_—/_ÖO<Á@à¨0}‚'Nh;Ìeý¬&lmmi{{[Ge5Àqar€d“6ÞzK_Úø;ýñ'Oýf!÷¤N÷:  9§&‹Å¢Êå² …‚VWWU­V•Ïç½öíûÔûº|ù2W; “>Uù’F%ýÕ_=éÔÕ æÆé½Žƒ„Ykaî…ÔëÄ_/Û„ö+vÿ½!{ù¸Í{÷ZUŽmL¼†é£özµâØXãs7÷×L¢0¹`ü¹Gô£•ß×7¿y˜{8 “$iaaAóAöÑ`µ0¹àÃ?Ô™3gtáÂ&Ç…íp_Ø<°yû¶~±ù»úÌý÷èܹs:wî\d»¥IãÔÄãúúºfff433£l6«ååeU*­¯¯w|í™/þ7ùúKÎÞ Öó<çWjU«Uyžw1B+—Ëqa¨…ÉïþþÿÐw_ú¾¾õ­o8»MB·õÏ\9æŠË~‹*Ÿ5¶I½x±ÿÛÎٞώmÄìà×]`arÁ‹ïÔô¿õ–þâ/þ­VVVœ[Áh{ý * ß§IˆÁeaò€$>}ÚÉó‚^%%wtkÛé°}ÖasÁää¤S‹âM aû¬Ãæ‚a3lõCJÆØj/†é³“nÞ¼©¿yðwôææo+=¿¦ÉÉIç)'á³NB;MB¿ã½÷ÞÓ[o½êÎL3“Žƒ`{>;z´1Ù|íZÜ%Œ°¹à±o¿ª/þIA NÞËÉöúT¾O“ƒ«Âæa””ÜÑ­al§ÃôY‡ÍŸüä'T ‹61<†é³¦_нaªFÆV{1,ŸuØ<ðþ=÷èG>£¯z?RqåÏ´½½íÜÕŽIø¬“ÐN“ÐïèÇÄãÇã"¨IjI’422¢J¥ràkoß¾­þð‡ºÿþû•Ëåâ¥'7oÞÔ+¯¼¢R©wQzvçÎ}ðÁ?/ÛݸqÃézô‹_üB÷Ýw_ÜEéI˜< Io¼ñ†:¤ïÿûúÉO~w8=q¹þQå³>z@_ÿúÃ’¤\îµ¾Ûõ|V©Tôë_ÿZßøÆ7â.JOÂö ^zé%ݺuKûØÇtï½÷ÆN×\¯Fò™Ë1ܹsG7nÜÐG}¤éé鸋ӵ°}‚wß}W=ö˜>¬‡~8îp"‘”ÜÑ-—Ûi¯ºù¬oܸ¡;wî衇Š»Ø= “ FFFô½ï}O/¼ð‚~øa>|8îp"A›Ý|ÖÃ~~ðä“Oêž{îQ&“‰;”È c.HÂØj/‚~ÖÃ>føá?üƒŽÞóŒþ÷CÏjzzZ/¿ü²^~ùå¸ÃêJÚuÚ©ëýŽ7nh{{[>úh¨ã83ñÆÓO?­§Ÿ~:îbˆÙü㸋 fô HÒ~ðƒ¸‹ f™LF¯¾újÜÅ3ÎHÒOúÓßüïßÇ] œÙj€½œ›xÜëÕaÚ y@¹y€D.Ð@.@ìàÌÄ£ÙŸ¹ýf°žç)NòÆXsIDATÇ]< ÈÈÈ$rò`g&%iffFårYµZM’T*•”J¥4==wÑD„<@" h ÈÈ€MÕëõzÜ…ªV«ivvVµZM©TJÕjU…BA333q @DÈ$rò€r‰\€<ØÄ©‰GÃóAÐçD«}©s.p!$S”}ëð s‹m1G•‹l‹‹²Ï`kÝ“ \kQUØ3‚‰rLÑÆúAŸ`x>ëAs)æS§N9yŽ„qÏZ­¦|>¯ññqëÔ©SªT*]—Ñ–úɘM±™­;v¬¾¶¶V¿zõjýÒ¥Kõ#GŽÔ×Ö֚ϹtéRýرcõ矾~õêÕúÉ“'ë'Ož üxÔñ9r¤~õêÕ–ß)cœq¬­­Õ9R_YY©_½zµ~þüùú‘#Gêo¾ù¦31Àmrkõo¯\àB ýÈqÇwõ£Oô9QÅãbŸ ^ïœ \ˆÉUŸÁÖ:<ÈÜb[ÌQå"ÛâFgQõl®½æ×ÚDTc6ÅŒà¢S´µ~Ð'èÿX…mqGÁ¥˜WVVœ=ÇN¸§y¿«W¯Ö¯^½Z?{ölýرcõÀeŒ;†öÏdÐõ‰‰Ç˜ìììÜÕ!¨×•øìٳ͟üñú¥K—š?¿ùæ›-¯ëôxTVVVê'OžÜ³Â)cœqœAC¿Ç*l‹; ®ÄœÍfµººªÕÕÕžbˆ;Î$Œ{¦R)ÍÍÍ݃Ÿ+¹%Ê1›GZd2™»F­VÓÚÚZó‹cggG’îúriùÒÙïñ(Ôj5?^óóó{6¾N1}Π˜ý‡Óé´U­V•N§533ÓŒÇöà¶N¹À•úwP.p!†~är2ÜÔ>AÐç ’ë}©s.p!$WT}Ûêp¹Å¶ïð¨r‘mŸ5:‹ªÏ`[›0q†ÉAb²©MD5Vaãg΢S´©M˜é f¬Â¶Ï: ®ÄœN§•N§{Ž!î8“0î™N§U($5&ÞvvvT.—•Édšer!·D=fÖX__שS§”N§5??wq[YYÑÈÈˆæææâ.J(§NR*•R&“QµZÕìì¬U_2ä‚x‘ `ò@üÈp«¹¢[IÊ-Ý"¡“aÉÒðæò‚–\0¬y@" 9\ÏWÅbQ¹\NëëëšžžV*•Š»HEC¹â1fÕjU‹‹‹òv´ŒAžÃÄcŒòù¼¦§§µ¼¼¼ç^Íf¯Üöszž§t:ÝññA›™™ÑÒÒ’æææšÿ$izzºùÿ eŒ3މ‰‰=ßÛÿåm{ pßA¹À…ú×)¸C?rAÜ1ÀmaûAŸ3(IèHs 1 Ù¢è3ØT‡£Ê-6Å,E—‹l‹ÁDÑg°­nô#¸Ö&¢«°)ft'Š1E›ê}‚ÁŽUØw’³+Ÿ­ëãžëëëš=ð9¶ç–8Æl˜xŒ‰çyªV«Í™qÿ?ÿŒñÌÌŒÊå²jµš$©T*)•Jizz:ÐãƒdÿŸ¤–«-c\q¤R)e³Y‹Åæ{{ž§õõõ–-ŒlŽn ’ l¯Arí1ô+Ћ~õ ‚>g’Ð'‚åÛc@rEÙg°¥G™[l‰YŠ6Ù7:‹²Ï`SÝèW.p©MD9VaKÌ.Ê1E[ê}‚ÁUØwT’³íŸmÆ=§¦¦T«ÕT*•Zâò<¯ïýA‰cÌæP½^¯<2Ü¥X,¶TV¿l6ÛÜ/¸V«ivvVµZM©TJÕjU…B¡y‰}§Ç£6>>®ÕÕÕ– ¤ŒqÆQ­V•ÏçU©T”ÉdT©T477§B¡àL pW\àbýkÏ.ÄÐ\w pS¿úAŸûRç\àB H¦(û 6×áAåÛbŽ*Ù7eŸÁöºÑK.p­MD5VaSÌ&Ê1E›ë}‚þŽUØw\‹ÙÅs줌{–Ëe-..*•JiddDÕjÕù1ÃA×'&aö ž˜˜ØsÏöNÛ HãŒÃ¼w:Þ÷gÛc@²%¡þ¹C?rAÜ1 Ù\hGIˆ¡S.p! ¯~ÕO×êp?b²-æ¨r‘mq£?’Ø&ú·km"ª± ›bF%­Mô#æ~ý]âˆiÐc¶Å…$Äœ„ÏÖöªÕjs›ã¤öã³`â@hÜã@hL<‰G¡1ñ 4&1Ô<ÏS­V‹»bD@ÒP§ òò†uzCþ,&Ñ7•JE¹\NãããW.—³¾ñær9]¿~=îbÎ*‹:~üx³Ý/..ZßîÛ‘4qÖéb±¨ñññ¸ÿѯ~yp[?ÆÈVI9ŸuqLQJƘ0¬’’?mÅÄ#ú¢Z­jvvV©TJ«««Z^^ÖõëוÏçã.€)‹*•Jš™™Ñêꪖ––´¶¶F»†”çy*•Jq€#’Ð ïá¹>–@Âs5$¡/ƒòñ¸ €d(•JÑSO=¥T*Õü}>ŸW¥RQ&“‰»ˆú¬\.kffF…B¡ù»Z­¦b±¨Z­Ö’ $[­VS>ŸW:VµZ»8àz?‚¼ô‡Ëc ä ?\Í®÷e`¸â1!ŠÅ¢ÊårË%þù|¾ù…g~7¨­ Ê岦¦¦Z¾T§¦¦ôú믷tÌÖ år¹c,¥RI“““שS§T©Tþw R>ÀVQ·½:ÒæçIݵù¸òW;ò’&Š:}þüyMLLhjjªç2Ä âìÝÓV:µÅ(ÛA~D¯lÈ{À i¯AÛ|œýð c Ý"`Xµ×}úáýÌIéËq‰;0/L<&D¥RQ±XTµZÕòò² …‚Ö××õøã·üÎó<‹Å¾¿·$e³YU«U•J%•J¥=WüíììÈó¼WV*•Ëeyž§¥¥%-//K’fggþ7œU:ÖÌÌÌ@ß „¨ÛÎÜÜ\óý¤Æö(årY™LFétZRð6WþÚ«,ä$IuºT*Éó¼fÎÙ‹ ¹ ®þЭ0m¥S[Œ²éGôú÷±!½ióq÷JÁƺ=.yÃh¯ºo{?¼ßy } N6ô ˜H¶ZMt:ÝlŒÙlVkkkªÕj-¿ëÔÙè…Yų¾¾®r¹¬t:­‹E---µ4Öl6«×_½ã1kµšž{î¹»¶Xðˆ<àr_°Á°—38L<&H{ÃÑÈÈHà×{ž×òe¹—ƒ:+kkkzñÅ›Û ,..jqqQÙl¶ë•>Ùl¶%¹Ô™[îJ¥¢••Õjµ–}ÙEÙvŠÅ¢<ÏÓÜÜœ²Ùl³-™„nËíuþ" iº©ÓaÚO>Ÿ×ôôtß¶‹;t“C8…m+ŽE_¢ŸýÉݼ„Ñï­~ä[ÆÈVý8Ÿ»îâ˜b¿û2€-âÎÌ $hš˜˜ÐêêjϯŸŸŸoÙ{½P(¨\.«\.wÝp»9a [îb±¨¹¹9•J%­¬¬dà´¨ÚN¥RQ©TR¡PÐÜÜœ¤FÇ “É(—Ë)“ÉDº5yhÕMîµý˜-æçç›Û ™{2ƒÐ¼ ¸°m®ŸýˆaÍ{€ lK `XÙp>kKˆªÜ†-c"€M¢w0\vvv”N§Ùë´y¹°…‹m±Z­jii)îbNr±Íï‡\ô†<ˆ[­+„ÆÄ#€Ð˜xBcâ@hL<‰G¡1ñ ´ÿ Qh{c=Ë%tEXtdate:create2020-10-09T19:33:37+00:00—ç\›%tEXtdate:modify2020-10-09T19:33:37+00:00æºä'!tEXtpdf:HiResBoundingBox1728x900+0+0×ì&ŒtEXtpdf:VersionPDF-1.7½8;í(tEXtxmp:CreateDate2020-10-09T14:31:12-05:00ìx6tEXtxmp:CreatorToolGL2PS 1.3.9, (C) 1999-2015 C. GeuzaineÛ©AJ(tEXtxmp:ModifyDate2020-10-09T14:31:12-05:00Xc!AIEND®B`‚blis-0.9.0/docs/graphs/sup/dgemm_rrr_zen2_nt32.pdf000066400000000000000000005060461422157504600217720ustar00rootroot00000000000000%PDF-1.7 %Çì¢ %%Invocation: path/gs -dQUIET -dNOPAUSE -dBATCH -dSAFER -dAutoRotatePages=/None -sDEVICE=pdfwrite -dLanguageLevel=2 -dEmbedAllFonts=true -dOptimize=true -dDEVICEWIDTHPOINTS=1728 -dDEVICEHEIGHTPOINTS=900 -dNORANGEPAGESIZE -dFIXEDMEDIA -sOutputFile=? ? 5 0 obj <> stream xœÜ½Í®-Ir9ϧØÃÌAmùÿÏT@·A@w+k&E9è*u‰ ¢_¿ÝÌÖ2óØ÷dæ­RRâ=–á;"<ü3[fþß^é_Iþÿ÷þôC~ÉÿüË?ÿ çYVzí”Òë_þðÃ?}ië3½K]¯±v~ÏþúÓç¯ùÎÙ-ô6«Õzþü§ošÄAhòÍýõÿýp.³íÊëÛüÇ÷Å…¸e§ýÞÒÏÏÏŽÿtý™Û{m’s]ït_œ[®ŽhCGñçÕÑLý=ï+rËÝlìÈÿŒŽJ™õÝûýsÑruD:Š?£#ù½Ö.ãõí?Î-ÿo?d}^ø?ÿð§×¿ýýÿæ?ÎWn¯ßÿÓöäW¯ï¤¿ë˜ï1Æë÷úá?ý˜~ú]Ùe½óý§ßåþne-1^ÿ,éüÚ»þ˜©ÁýϹú»do;·÷{þ™>þ¹ÞeõÿüûÿÃÿöûþ¯¯ž„µÞuîë‘üùËgp¬÷žVìk–QÞ¥]}Ñr÷­Ø×ÝÊûµ¼ç£/X}y+ïëjånJõüãê‹–»¯hžîVÞW=OÌ,w_°<úòVÞ×Õê{Ÿ¡VÞ©v¹#õ=ÎoÍgÈîå{ù»õªóÚ.¯ßÿãù¯þØŒ† 통+¿ÕýÕßh·–µk¿ÔN¶ÿôÊC†ôŸÏÿûÇïš ¿™„>澟e*ó&¿9ƒþê­8Ñ›!7âwrGÎ{«wcæõžuÚÝøwg°ïr^Úÿ÷ŸÊx÷UÖÿá¼ÅëÝro?þþŸÿÏŸò™Úyöý›ŸNW¥ïõã?œvûÝVê?þ??ÕÓOÞãÇùé<`eäþã~úÝ®ïÚS¼¿v¹¿>!ÕÇ„”ÞkÌñZgfšrÛäòÿQ®¥×U~ügÿ×ü_:WUß2Žø×ßùý¯ø×¼þõwþ¯ù©ôwMë‹D#v[ûã‹Þþìÿú¿úÝùt4ù-þüÅÉþøÓïÎ=»6Ñüñÿý‰‡DÃõýý¶ÿrn\–7>_O®=³K>­úKêWtŸÓì¹Z˜ Z0è×|Ï·¼DjÙûXF:·Õ>tå‡XÎ#6†dÂ¥™ †±ÄRëù*á˜-ýŽ3'쬧>ÄK/ö×Êò×Èï´ÔÒ΃'–óVä±Ì¢_Áq.¿tíã<ãzf™Êê0ËÖ~äú‹ö#Oõ±L¹þ¤GŸKŽšçúuv:†$§šgòˆ©eÈ©æÀìzrå `5ífÛÜ:ûù…ÎÇõ|¦“ü)#ÈEþ<¯ŽüNóŒ íf–¡œd]!œJ.÷<Чí0‹þPó\BmÚ¦½¥É:×ßj3ƒ6YrýYêï%÷hÉ’ž{ÙAçúÏc†!c\çúç¼Ö«Ë-—UFÎï¬M†|Áå |Æ*×»dg°Çr/³œ¤-–.C9–3„¼eý”‡,’Žå ¡è¹²Ü°cÙg úA6[Ž’Ã[“³—|#–3†^ä¨"S†Xd¹š¥h›3ˆ±¥ŸÓx˽ÜgsÉÙÏ,¶d\{è„!–ýNÚÏ8CnrT•µÏ΄(â‹»eE:©çMW‹ !É©ëY_ÉçtÆP¶µ[-g UNt¾(f8W%ïÁnòd¨å AžØÝª=±9ɪYÐF† 'oã=ÕpF ë™ÝÎÓmŸèÝl[®A,ó<—Ã,k¨å "ɨÎ<©‰s›Î7CNÕϤcÈ2yL:žêœe b˜vÇs>cÐg`t}’ÎÚ÷\ºŒò¬utó‚>8£Û­;œ\†9x}YÆ g:«ˆ^Ͳßz£æyõŠÏ2Pßc™ö(å|¾r{Y›ÜÕ"ïè@=W9c‰dŸÅE2˃>¤gU ‹ BεšM6¹È(Ä0ì•?Ã,o}ÍÖ¶·5—3ˆ.圕ËÄž¹pXÇgSN%s’u,ƒ(¯™Î;®óM.21T›@s9SÑVËYi“zÆÎš/e<ü¹Êë4¤Íy/ÌrÆpæê)O™Ý½zÆP‹U¬ "‹¥â)­gmÛQ]ZÏ Î…Íó³Ÿ3ˆ!ç:¯ž¾Ô¹žAœuƱtü^²Þ8¯Óég³ŒBÎ^¦}²|9fª2/êŸç”INt^i β ó|Ðl˜gù"3±œ@‹v†Pe˜-I[±ÈäDuËŒ%‚ Óß«v† KšÔšð”XÎÆ´6öxµ3„9¬g{Ï*R®U²³Ÿ•‰Ì†ç\¯QÏúPÓ;-…²M'ç³_åy=–„ö3ˆ¢§:Ÿ5œÆUÆÙ1ßå~ÆÐªYš¶Ü¡cXò‰E† †‰_¢Ÿ å¸áýŒ`Ê(ÏÄl“Ðo€u–éÉ,YçÆcòRŠåŒ É©ÎKTõ‚å-’V²·\¾ÏYNµ ›œ!å™Wlã áü·y&>¼g㌡um£N}Ùg:oýšCF ç‘×XÇ4dÒÇyôâ€ÄÚÄ^ )L+ƒE'{ާ$×%ã<Ÿ<tÆ SøyÞÕ [gðóäÉ-–3™ÁÏ&gUß ƒŒ@9º•§SæïóÈÛ‚¡œÏ­Îßòꇪœ™Îßç=°Yÿ,þõBá%»åÌÆ:ŸÇÃnyÑŸVFyÞ*ëø íùïçí¯­³·\¬Î#E>Ï2{Ÿ'ÞÖèE>Ï2{ŸùÎÖåÜ8½ua¡½N£s~)Yÿ¥G5í¹œ(nÌkÇPtö>~ˆr ³÷ÿ[ÇXº¾¥§ oÁ!P¼åIù<Ëä}fzüzòy×Mx äë,“·^ƒŽA>ÏeØ«©k RÏdö>¿´=±‡¬šÎÞgea¯æ¹àªÓ÷¹Ëö–F‘éû¼ü¶†,õ A¦ïsY¸¾*_Œi·n]¿n–}yÍïÒlT6ù:Ëôò—GJò“þ,®ŠôkÿKÆE€çJ>P®à‰€ŠsTx»°~Àúý}0 1^0`±Õ»3 òÇŀզߋᄺ°ê¢ûBÀ†n›­x.l2S߈'ùBÀ.Âb=s! ¸ËPæSmBƒÚ!P¨H‡@Tƒ"!PôÚF)‹(ã7R XtÚr hÕ•c XôrˆjÐŽ‰ÎµŽbé œÄ@±<)0%ûÒÊâ@;v LÙ®&(P>þòûˆƒE?AIõ7 "k§À„»(ß5%N§ÀsúV¦‰~Ïë8µÁÓæø2@0á' < û”; ÊâÝŽ$˜3¾¦N‚gz°ŽI‚âm‚e¤n'ÁÓfb’åÛ÷$A¹Ð' ‹}pI‚òX½n<ËûÞ: &ÈO, ´á$(X¯Wã$XÊÛND,,æ (6;ˆ XˆC‚¯y€ L¯F^ÁÂõ²ƒ`Í‚N¼4‚eáÆ8žƒ ÏŸž X /Ç@pÈóÚ­AuØT °Ï@P]:£µÑ@ð ~²ï'AÐü f1òjà ¥]‚j1vªçhh x,S¾w‚CWq”‚êz°ç_¿»«ªó¨=Ø=êyííªóÂkP ¹3¬Qà±lø*@êˆ0ƒAàØ[êñ°GxÚdüä€Àck’x, o‡Aà1 [ÜÕÁa® @ ¹<ì £ÀóAjXç‚¥àÎ¥Âax O(0P} FHÀ@õo˜Ox,ï<0POn°fxš$61 TÇɾ1pÈÔ˜& µ. ‰z9ö#µÍ²Ë1Ô~¦õl$¨þ{ Œõr A<~ºÓÛPË@ðxc‚C&j{ªÁ‚fy šÁx(˜è¸ ŽÍï­£ ´±w•((~s§âDÁÓÏÆcâ(˜à= ê(í# že^C :§Ìæ$˜è¿" &:ÓùTÙôG”Ϭ@‚b1ƒ“ |P^7æ…¯‡ƒàib·— ¨>¥ŠwÈ^E‚`:Tl>‚`’¨Ñëâ@ù6𧂍'7 5<¿hnƒ…·(Þ´ŠóJë¤ÀT6ÖÔ¤ÀT(®,ý鈀CúêÖ 0=ÂD@}Œ€‰`@¹·É (N1m §@uBŒå\¶â'ÊQh TÇ™Y@©&[P8Ê`ôAw çÚø%iPí=uÙ0¸ê!¿ža 9P-†bà@9*ySsêÊÀAgàÀt¾F¡äÀÔ -AY- #8€ \sµž‚ÒO¶£ ¥‰Ý‚ <6Ý (wÚ|ÁÔ¼‚â´‡‰ ˜ † ¨O!@0uLé‚2*cb‚ Ü 먎H;780 ¼Î:—›ò^Ñÿÿþ·`Ö ê38äê.”µ·>@Ž‚²²Õ¯œ£ ¬lõ"ˆ‚²ŒÕ©ÓQP–±úÀ8 ŠEÙÝQpóMQÔ0Óë"AíBI‘$(–üˆŠÅbŒDA=JOCÔµrQPN¥ÜN”&í‚b™”ƒô®; îü J' y ÌÕ&ˆÊÕi·Œf‹£F0Ð[x00#øÑ@^nD½G³-¹#ÈŸÁ£Þû+ˆî#¨+¿G40z4°Úm¼¢XÝ_ÑÀbò ¬ˆÐ9fxŽƒ¥ò›s «à@éYräÇ58Ðr<]ðf2§s ü`Ús`Æx,õ¤{çâÀbóâÅð-]èý\Ø>@è9Y°=8°àóXð%,Œå‘ြ@#ô6A>=‚‰.pA¹dã>’ ^€A¹šgDPšX€’ ÈÇ)@ÐOî èý8­ÉrŒ…ÿÈ~cœùbz/ÄÀ81sc ¥À@¹SbÄ@¿Ç@¿Ç@>N~ëœýjœ£ )P,íuS ç® Àè‡è''rFʽ}ÝÈ×.0Sz` ;u ”O‰YHÒ¯±&)ó_P ?ÔŽþ|:ú©Hþn8²‰C œÛ¢o€@¿'ç‚í q4¤q”@ïë@q ÁÄ ?w9ý‰Å ’ôw,¶òwú;Ÿi3þåNiÃåô—°® úÏ–EëHç-F?¤¿„KÐ_ZúKt©8ý%ê HçÉ7Hsñìú€¿´y#üI0ŸÜ;DÒ_‚Øôg>¾× Ç`ø³k¹áO-ýŽªÅ‡¿Dèü™ËÑ¢~¤¿Cm7ü™/Ó"ü U£ü©Å<.€¿c©ˆvþÔbO¸ÁŸ^Á~—ÁÐO É`ÕØÏœ¯†RÆ~j©FƒÆ~·ÅØOݺÕû™ÅøÐØO-àCƒ?³Æü©Å^m‡?P=á/Qñ`ðg>eƒS£?µØJøg½‚þÔY½o´ƒ^7ÿ‰?Ûš(ÿ©aÜ!@µô;hmŒäŒÿÔb1 ðŸZšÊøÏÚ˜ÅøÏÚÜü§p›ñßm1þSŸ¼Åë ÿÌ`BÃ?µ ‚gøw[þÙ!։៞ÇzÀ¿»[Ã?‹XÃ?ëÖÌðÏ,7þY ÁÚþY?wP-ŸÀ¿»gÃ?; @¨øw[ ÿ¬Ÿ—ÓŸým£?µT³ýY=èïº>ПÅJÌbôgýÈ)ý©¡Ýôgõ‚0ð…‘þÔ’ï0 ZÒº±p¢Ë„Gþùÿò}ê?»\ÊùÌçv¾¦A|gâÐÕ€ŸLPÊwN|2‰= bÑ5ˆïXº @å/}ùR3ê äKˆuò%(CùÄ¢aGG¾ÔìÉ äK`G>ÈçMùÄ¢tæÈçG…—si@b†¡mˆö¹”MB oîC:¿ê|‰@—ÍŸö%{.èFѹ/™ð¡ÕÛrq_6aÊÅ}Åû‹ûOîSMjpnèÅ}xp.î£.4¸oQ^*Ðd Ç‹ûÖûCŠô&ûÙûŽÅä¥}˜ýû ‚Ø}e`9ïØWƧT„ô¯›ú¤É3úWœúN}Çb‚+§¾bÞ€¾²A}“KPŸÀÀ3úW¦¤¾j:”€>Y{< ¯RkèÐ'ý>u •«‡¾:±€ŒèßÄ7=¢ø“±¿_|Äþ&–ywìo>E FKø› Ýü-Sâ:î&aFÜÏ÷ã9â~ A¨ˆû%xÇ︟us…ýÒƒ÷ªëS=ìWሰßÀôûÙ}tÞ« Q¾sÔž¾c™OàC'¤=ÑgÙ‰H{’cDHÚ;?„ ÑœöâÔÄ=y-Ôf1¿Ä ‡ý(žuÞk ±áû50—ß9Ž"ðÕåROŸôðIØÒÀ×  à;Gµgܯ­Ï¸_§@Ô‘OÉFg@¾V‰‰D>‰ÆZxŽÈç—ìÔ×6bGŽ}uì<¹äŸ¦ñ¶&$¿NõŸ“_ï ¢‘üZb$è×'vD¿n’ ¿^pûœü:#mN~*B'¿ÑEN~;¿¾ðê:øõEìøu,³‚üÆÀ™ý&'5G?ùÕì(¢ßL˜?ýf"¢ýc¢Î~"r ‚ýdÅød?ÑnÚÉÉ~ƒ ìì'§z²ßŒØ‘ýdÆ0Þ"üM¬‰þ&U·³ŸæW¾nø[|J ËE¡¤¿Å9ÔñO2 $þ͉‰ãŸ‘ Òˆ“Â~Ç¿IÚwü[•ZRâßNP8þI¤ùŽý©¶>·Ëø{Ä¿Å(2ñOäþiàÂLâ߯·,¢¢–³¨ùO´„À…·ÏPÖ†rÀ .”GH<£ê†@‰a¿nþÛäü'O•Aã$áà¿Ý؆ñ? ®åöÙ%{ü/²ãg½ŸA| 1ck@áèëÿ% €ø§?ù†ª†mŒþ‰ßȰѿœÎòè_‚>¢²\}FÿdimýËP±DôOôÎzÉý;–zË@%ãÁ~½ˆþÍ÷C*áÀô þ½Eì¯ N±¿s¢ñˆý$ŸŒýº <ö'YMˆ"öç!aþÉråuÇþdÿºCÓËo‡þÒ¡?勇 Ù9— ”Ï[:oT½¦²b¨@›ýŠ— î¥íö$@еò¥¶À¾T Àî ±˜¿@0(´{€àëæ@î/¤638pÚBâ ý!ð~Eÿ²ý0WôË+úWŸ2Ð-YœjˆðR’®ðßV² ,Œ·9„Ï“üŒþ¼ŒN>rOÛýÊÒR?žAÇò‘ (ñ{åB§ÀV>s$ŒA’ï¦øæØÆg.`ÏŸ(ù3O <ËýE{³+ ìö| ‚„fA3tPàèø;ÎÌÄ>RऊÇ1p"120pb‚ \˜ Ï,='9ðLÉÏtÀó}Ív9ÄÀµ°Øp Ü<ˆ¸!X'ê·`\h"#c1Ã@ümÉ Ô/„£†gÎK Ñ;—ÚÀ@*@º!!r…§‘à•¨TÅ­@‚ÇR°$ jòø U<`4Ô6í¢Ažì[ªr•zGÿT1Rn¨*n,6ÔÌhG™ØH¢Èa£‰Ù€BA†[Ììö–G2à vz2à(Lëc2ààZÍ“'Eªž èi™ž x– û™ 8áòˆdÀ³šD?LœPD2 |7 ¯ô¶ÌýÿiúÕ~ænfy.à†ç>r3Ó=0'ÜÏŒ6ÌÌžSÈ\À´y.æ–òÄAýR·-åÑŒ¹€Òó…ƒÚÄQÏ,žèÇ\À’˜RÈdÀL6ðdÀ UdfÊܘ Xó]Zx*fRZíÉ€§_Ë®ód@ÉÚ¼iÐÚXØÉ€…“‡gÊó4¨« Ëêb2 4I7 š Ê:f> 8žŒ!™(þ>»Ë”ÌIc?¦JpóênO¨§ž6&ß$ nS"!PÞ2‹àAZ%hÇ/ì*P™É¬ U µ’;©ípßzB hß>T 5SâÉ„Às”1’Ë@Ÿc&ÊdÒnÔÉd=e ç(´¡ ´#ÏÁe ¢ |Ê@+§õzî!u …S¶Ã Õ¡Môl¹Td³OhaÖ¨ë@+´_!m|aÃb ò}4g5y×úÔÝI®•ÄôGB Ìé ƒ¡U¾‘%}ÓRwç†A×aAB ¼"é‘(7ýªê¯/R :¡ 1è™P ­$ 6B†‹AF0ØÛP z¾–YH<'ÏO-è˜h¢(¸—-§.)(¶`ÁV©¤t¸\”0(_34 }co™›ƒç(#6²àð<=²à¹sŒ@9·ñ®£àTyÇ` àìÔ¥q@] Ø#s«@Á}LdÒ`é ×%$fQ?’`CÊ¥ƒ`« Å#ùA‘޾n”Ï‹Yœ¡1û9 ½ñÖ»¸X›S ¬DÉ"¶ñrlŸMâ 4ùæV›ùíBnß^[îjg÷ þtýÕÎj?¿t¾/Ò-WG´¡£ø3:jš­¾ïÑÒruD:Š?¯Žä“8ÆÝ-wG°±#ÿóo]È­ÈUÈïúU!·4¹âšUr+wu¶Ï’lçŸ{~UÉmG¿hpÿSŠkM/QôÕ£0M÷p•Óúêaìšðõ¨÷†¾®mèë®Ñƾ¢ûzÔ{c_Q£}]5Ú¼/oå}ÝõÞøäF6ôu×hó×Ë[±¯G½7ö5ÚØ×U£ÍûòVÞ×_QÉ­˜â6þ²’[ÿµJnß”ïû…Jn¿Øî£’Û/µû¬äöuÙÀg%·ï™¿™…>&ÁŸe.ó&¿9•þü—D+k«îË‚hÓ ¢M/ˆö¨Wvýóï¾(]ö·(‰öç/z[ö¯±¾(‰6¼Ÿó/+‰&ëGŽé¿)‰vlÿêÿúû/l^­üzI´¢}5J¢é;Õ™ýnßÇÕÞÈl×/»P† zL¶\ŽnzÈw«x¹W¿êŸUù^ïvùJ«k U³lèy¸^‘¿b‚¬–®Aoµ ³ õÝ«µÙÙeZèæAµŽÏz½’Çk’1@¥kš*Y(ó2ƒy3ÕǪoDͲæ@n¶.ÁeC’ ®©R-„>V;H†PÌɪkÆše/•RªO©J “dÂAY¥ˆ%™Ûú]p¦%ò¨‡5 ÉÜæ ®%…’^aµäKI¿ÕR¨¤G"ݱPJMÂYËQJõ@-RzóÇ×ÒáM;Ý;h@TQ ¤©eš¨B Iÿ–Д#ÕŽÙÐTPêPkbF5ônõÜã°ŠXÐYXBSQ‘õs,UÔf*´Z+dîÒZdç¿ØCZ;dâ±°ž” ‰õµN(+‚¾§cH+Â?µn“V´_´%H+:Ô©gé i³yk+Vt°í±@Z!=U«ÐV T¨­™¶bðæµmÅ@¦d=+* ʱ´Í8´3ùÔ¶ ­8ÿeÚ©vµ¨ÜDäYœC[±P’¦ö mÅpK¼bu[ä ä’™«×Ó+äú…ÚäªÚ;ä šäÚµ“ ßÀ¹SWˆsÙ,È+&ªSv€?Mjh›‘ ¯XÙœ udÈ+Rê(W,È4Ž…þ´É~*üiRýD êŠ Y~êŠ5Íy”àNKpÖ1áN«¨u&jSWä´7ol¸Óä™”•Õc§šî´ÊWd¸Ó˜™{,t§e󞵊ku6i(®%™|zdĤÄIš¸ ´ÄÖ¨65ñ_ŠGMªÿèõ5yfÄ£&Ÿ²dˬÎÞ“&nx-±%Nø¦–…[1V’æé¹&^-±5‘ƒÚäS­%¶¤M®UKliÉË&ßi­¯5©¨¯µá*>jõµæÄ–;êkmdÈ6)¥õµ6*S¶<Í&>u¢¶|F0u”ü%ò6wZa®M“ºEÛj;53ds§•!L“ï´¸ÓäÿêG®ÉwZÜi¥¢¸C“ï´øÓ$¾³í¨fþ4éGiº•nþ´Ò`ke +œŸ‡ÌŸVZ7—O+ËüiEœf±Z`ç(Têh5™C­TA[ÍæP+e™î«O5N=íOó¨‰skYƒjµR¡ýmò.z"¬?[íæQ+”еjÀ³ÐÝ×ê4Zéמo§yÔÊyF›]ž•çe"¢µ„"[âAÓ6-£ÊÖDàæXPeKÖÅÚ³|¨µÊÖFô¬É‡ZN.Â&븡Ê=éM>Ô2—e"ÙÖ†yÕò†¸ç¯ÚFÈ£µÅ"[æÄlm«S­$„[O¨±¥öÖ3 lñíÙ\j²Z´×§ØZoò…ÖúZ™(M¾ÐV_ká×”/´ÌàeBU~ÆÓu—Utþ“–GÜÈFm}é'áÜ”bxë[Óåôù´gx$•¤L<¹b‘1ØÃ¨ËÚcPõ¶>Gêcm£è¢iÊcjïØHæ9•ø*õjä-ó·<¯öKÈ'Z&pi¢º…&Ÿh™ÀKE8«©ÞÊsÅÕ>ãMÈ_&p}ÚͲÕÏ8ÏâÚ( Í¤Å~fmÈ*i3k‘cA-ŠcÑÛ<«8Qõ § ÂNe¯ü¬Zbižõ†}ºÎ¡OáùvcÅe¾ ç€Ø§É7Z&p±ØÝ£gF.GûùÞêhœßРå±8 2»ÿÆA£¢›‹âŃÍÚ8:3:"¶}ñ ²™/¬<—ó ÁƒÕœÈV›/ $·¢J_!ªH9jÑ4ƒ2¡À¨5ŠÁÖðäA¯Ðí@(¼jßi¡J€ +„b±•6Б–<¨*¡*ä^%?¦‚5‡Æ@<¨ÜkØFL JvØ“WP„¬ˆ@( nv€0e›µƒ„¸A„â÷3Þ"&Ôu"<C''BY¬A„ :Ò Â„àX¡,ú¬ ‰0¡Úra‚¢?ˆ© „ø±aÂÔD˜¡Í "ÌÊŠ ŒÈìjHa‚™]íDÈ„ÿ BVK "Ì+k'B‰È›…D˜Q6>ˆ0£iaF§ BÉ‘)÷ "”{dý3bEA„½A„%ïLÖÀK&g¥õº¡·—ÅÐëæÁ Mkð`Æ<<¨+ æMØm ZÙ5FÒ ˆ­[Ò`A^.i0$g¤AÍ­° 4XP÷™4h޵€-Áĸ.Ck_J$ Zév;ª@k_ù ªwdß4¨Þs/­º»ñá€Ö¾ZÆ%aÐÒ ¬É‚Ô¾!sž0¨µÚº^‚Ö¾¢1aPÓÌ­Ô~4JI4ÕÜ ƒ–â`ÀØ ¶oØ0ù „Akbè7!¶oHè& ê©¬ß yóƒ¦ØÓŽƒªØ³Ç0¨Yæv êoa_8À Õ›»aP5|Ù,b{–ù% ªК( Z‘·W  æ@س4‹‘V‚Ò¾'›i‰‚ÚÆ–L@A•ÚzÓPЊáß(¨bA[ÕM4n4?–u3 ®NJûi•(¨mÖ‚Vf_ jî„ñPPUB¶ Zú‚YÒ~"M™4¨ýÌ‹Õk…ƒ:”öÌ‚ ꩆ]ÎD¦õDªiÐ2Œ!7”ö•@ƒšp±o´n¬I¡Ò¾°MÒž•ôHƒš5bX× ´ŸW T‹-уV¢ï†A³XǃêjË7 ª·p‘ Úî7 ªÖ³; ê!öä-kÃÐÏ`PÛèÕ£ŒYPZF~Æ‚úàØÂ,hû3¼í¹Ñõø jc/#Aí·| ê²û Ô6æN1´;g#A»<%HÐ’/¬¡ %@ØÕ †X•(¨m@”Ê‚ªù2  ª;q£ έœœ‘pPs$ì(ð dVØË@Ô…½YÀƒÒf?xP š@(ê¨a¡—ès L¬JO ´Rtà?B‘馪*R;&JÇë„¢w²Ë!ŠÊ.™Dèª\'B)þg‰P{6M‚-è@¨Ï›±žñ Þ=ó¹€Uæ¼_&”å Š·8T‚]|é4˜Œ:.[yРdz´ J?ËB®ß]#íB]@¸Ž„ò4uPÓœBYfcÝEŒ%)yP Ö<¨q)ë<¨+º×…ƒb(Ô&†ŒÀAmceÉTñAÍö5l3”%“ùê=>X§MpìÙ#†ˆ6.=>8¸úñáàZ‡BùHZ7 ÊÉ­ „µðúVl¾3ŸÂæhÇ¡È( Ò DndÄ»íÆ8Ø*8ذ‡Eà •\ƒ *ƒ,mè8h2°>ƒR€Ð‚mÄÁŽºhƒûsöåzvìÐßv« 4Øb&Nƒ†6Ž‚,†(8èŸ l2(è±GÁé?P°åÏà`CÎw `# V5‚Ìs½‚ƒH©<ÿŒI” ãë&Aúäƒ»Õ ìpízèÈAP.Ó,ä¹&ÿÁÉ™¢s-b¿ƒ“à€[/Hð ÀÐ 8Qè'Hpbó Á¹q-N‚"¼5@# 2?4`pb{”€Á‰EtÀàÀ>"ƒ“”ä0رñ“à$ãX¬0Èì³€Á‰Äë€AYcZÂà„/0`pßí0¸ å ÜX î† Èap£>HÐàn ’×äÉIƒ‹žA§Áå|Hn! ¾Ï”…YHƒ®ü ²n‹‡³‡ýÌ»Dh0-¢(iPuírˆƒ›Ï cƒ²l°¨¨ãàFºÇSb0ÚqpMb%qp#Í%ppóËä8èqyÇÁ5 Dl°t8Ú<6HÁ{Ä™â±AÉ3HwlP± dÑåaË„c‰ç<¸6Z7¼FÔì^Dâà9C¨”Ð7¨ï$ô!ÜçćåÂE|“"߀3#o0 åÔ7lF¹ Ám‡>~.è#£ô¡š^@ßÀŠìR„òf‡"…žBÊQ‡"´3’çЇ¸.è›Ä@‡¾E¨S"Î}c1´ç‚PlöÔ'Ø× }[UôMìÐ7 ÂË}ÄiзȒ„¾…¯W@ßïgôoQaèз£r„¾íQBßn ú6#}»ã¹=( ú¬:ñ›ëAMFrPuói SºÔе ʓЂ²b~hA3ÌÐ‚Úæ¬.õ±KAKf|RЂœÐ‚ÈùB Z6µª”‚ÖÂè$¥ "C ZQõ&¤ µÒB)¨ì x¯aÓÑ‚6lÐ{IA'c†à½ž€ä½ŽèAð^‡„Î¥ ©SÉK)¨|_îèŸ.ì…r)h›7âž³RP‘‹Ž‡4Nq(¤ ’’jó¥ ²â²gߥ _ Òž¼ÔÖ‚´7‘´7ÂH{«0Þ%hò˜ˆÓžP‹µî-¸p\ *…E„T4º¶6qÞc‡+AÓê #B *U:ÚþÓrËS š¨úr%hžä¡èx]¸—¹Ë{hA3\ï.̓P)¨yâ]šáÀ h©Ô›õd™iç:Ђ™ÏQO–dýŠüM¹¢ñ`=ÙaÖp•:PÉgP†b£UVüp¨e(t ™c×jÏwèOwª5è¦T~õÐfʽ]šDÏ®•6ˆãAš‰*ͦW£T²¯çöÓ RD©•R3 4 ²B2pƒT*«X¤ÐÜ1G¸Tn ¨¸'ÂåþÀ=ÙüÖi—€ŽM¸î剭ºB:y»{ºûí뢽ì®Òž<Æ3.åž³!5€ ꩪÚ,›¬RTMÔÓ]jAvÆzb1Œ£t¡ò°£ž4±QOu¯vPOöÔµËuÔ[yG½…].(ÉÄQoc¯÷@½5H`D½LÆüä’ ÝõDjgLÖË4#ë­ýóu»¡;aONe.Â^殫N{b)¨ ÂhŠ´'wÓÂø¤=ÑÞpöärž¬·‡&ëQ]¬'¾kBÖÛƒÁD²Þ¢‚Àao!?`¯#§à/(ö¿Öž2P(»ï¤@+ô2ЊŸ«@+D¡¥€2T  l… ”>ãP2f*PÔ‹ ôK™¹„Ž~Ð=ú%†ÕýXÛ,Ð/!!!è9bAVÐ Œð—êrø3кá¯Ô§ TË–=T ZÿØ.æŠúá §?Ô6¹ðo}È@…Ü€\N€A>à²%ŽóŸ‡2ÿºÇÉ}cÑQ?hÿsȃìü7Q?3øoÂü7˜‹ø·˜{ãü·¬NcàßFÊpÁ‰(+ /vØJ‰ 9P`+‘§€ºp‡þt¡À–lf'ßV`ËŸ ­Ýï°Ÿ ööS/=`® ÀV¦kx­ÕuyGý¬ÍõÓv¾Pj~¼oþÓŠ`†Ëà?upAí™P`K¾Fn¶ãÀki Ôò2éûé"×ø)2:FÝ0%@“¤NTØ’:ºwF ®¦qyÌì(,JTjHwF VwF ®ƒë-=f{F`F~ PûAÀŽ8‘þXò3î§…Ãæ÷Ó»‰ $²†ý…p.B•càÀ&µçWö%±Ê:&&Tš \p˜N^ sà‚Ë90'Èà‚7Ê+nft’3÷¹v”~ììÎÜüJ $ë½8s ÍÁ¥}rà¤GÄ9ðü¦ýŽûé%Û“ì Xy*ÁŠmú"'PN· Tc6:Vlå9’Ümç".Æû ‚ù|1‹ Á†Œk‚`æ.ƒWJàfì)òž>@P8Ë–Öž˜™) ¯p¤VÛ‹82K£0”¹¿(àe>OÄVNò›ÛšØ)°¡RaP xÌ-~—YaËÙ‹ˆ ù& 3‰žÉÀ@ä\$XÉ›$Á3oæGF üV††ŒùUF6{g–@P< ^A‰×=AÐJÑÝ X*ãu‚É”h΃?Ÿsà˜O ¨¶Ol(Ø(©'f·‘¹åDpà »±R°`eºš³`™ˆû: ŽFñ¦³ óä¹—AÀ`åïç0Øéðp¬¨ð0Èdë€ÁÆ~¥âüåKi\…!;Â`…"Õ#;×D今 Ò_8X(±$6m¯‹ Áн[!ØÔƒ”Ð: VÛT*`°â[ÐJÕ£Ã`uð$ VÊëgÜO½bÆZ€vUhCµæü±n@;ÖƒòD= 2› öÀˆÐŸˆë­ a°£e„þR¦¥Íx†þXãïú3h°¢š`h@åqyDþo 2)=S‡y4+Ó\Ë$ z…´^ÉP¡G3—ku˽×;ûl¡É7G|…´o/È-W±Ç þtýeĺ2Û}‘n¹;‚ùŸÑÑh+]½ØŸWjÀñøwl•=çýSÑruAz‰?ÿÖUѺÄå·üªhßT/³ªhõ®töYÞìoRí«Û? öIóÒT_=€R`ûÙŠ}E½3öu×;c_ÑŠ}Ý­¼/¯wæ}]õμ/oå}]­üiõzgìë®w比·b_w+ïËëy_W½3ïË[y_EU4ù‚4 ó}YmþZU´onú/TEûÅvUÑ~©ÝgU´¯¶gU´ï™ ¿™y>&¾Ÿeþò&¿9}þUѤ2󔊌_TE‹UÑοþàÿúÕªhç¿ÿ×/þÿõ·«¢=Oñç/zûóWUѲÓÿøúhçÊ™Ue&Æë5póôóß#«NÂ. ûs_ÙíÇb5H…^·9Ô4O]û9´£5Ý=¢©%›C æý¬ÖQONïÞªúÓ´€±5i¶u™¦Š[/ÝüiâAµëkÃüi¾ãYß1©ÚjJ÷¶˜SIŽ…9ÕHþëm3§:ÉÞsª‘Xß{fN5–s½æTC³Ð{eNõâQ9Õ¨¢Û{džն=ëÏØ¯:[‹É”j“Aö¾˜Q]»Ž…Õ¨^ÝûfFõ0üí#!£ÚRJúÈL¨^¶ü2ªÕóÝÅEoÕ¼šŸù–ÂFWUä[Ûú™Ì¨æü#rqfTëy1£dØU¢@^áP]7ö3QçÕOô|EböAÈÄ©4J1ReF5Ò}‡8¤6N¥~âºáÖf©e0¥a€!’ä’o;÷BFuCvÞH‹Õ•'ß̨†ªfä }ÃVŽCüMÉlS ¡÷ Bµˆ4hC#ÞÄ)Ö@n²gý $UK`E¯G@Ü$qݤCª&‰ƒc}h¼ò¥Éä¶½êKYºÜ¬QTô ;&Ž’‘T},긥@Eߌ Š*©AŸ‹QDô YÖCjó薽Ă¬ã ½ÅÝIJS-IóË,È©–*í:ˆ²‘Sݰ-ñ¨i²P¢mlT3rª;öb8‹däT3lÔŠœê†Ü¨ »—£ì¬½x.”^q–RÍÌ·Q'Rª;ö.ò‰NHÖ³zå­“x‡kÈ'Z'ñŽ„ŸÑtô’lf–L=6 ­tO†²=y[…Ž^ú±6 :ú^iéÐÑwLžã,hlïpËŒ6!¥ïТE;ÊAùDëLÞ¡Ûò‰ÎØ2ÑùDëL.ÎýÑ{†–¾#yHpÉÅîo¯ÓwskŽÞ ¥wC·Í«=nôÁœê¤ùÜã|™ …²XC¶â²œjHÚ†|¢-§-†|¢aÐÀÅ/´åTCI1ä­©PRNÇ= rª™ð0ÎscÓ¸yÚÄÒS-1 =ùè–S=LD8d3.ÅVvC6ãÒY|¡Ô͸J^Úž_²×Fê¸Ý\ùF'nY¨¿ç´3j±GT¾Ñ{ÚõÍÒmG‰­1k³I|Y˜vÌVm×=›ÔÒ‹ÍáË÷ H¨^øÞÙŒKõ‹¶4²—Ná¬é4d/.Â7¬CöâÚH-Ӆ篴 éù˜ËWZ§p‰ïëõÉWÚÒ :æÕUvn¬†|êàéX Õ•mÇPÒ'ˆQÆšp§%$C5™R/Üí¸Ö+’vtI¼£nöNð§%¤/èBPj ¢`]{e$9©lÁò„±½ß¶£d9Ó¿z1U\®š&(æ–<úƒŠDÖ² PV³–T'ëW¶ngU,ÌhÖŸÛFÙ®išò¾Í¢?ºý É^úÂP´©QEÛº[¾Ñ™Ûÿ,µ´jQí !‘ÖÕ¨6—¹º_E{Å^~#µ¨¶4·Eµe%ÜÔbAÉØ¿FE~a@NÓ,ªéPƒ.Øq¤ZÛKÇ¢#_èªÞsi ‹|«æCݯÛÿ kä´ts{|_q´ jq´ ®t6 |=0aâ !ç»0É´¬Rƒ±Æ DöÎÅ(Ìzq \>AÈZíuqàb¢§s B©YÀZ”Û° ¸¸/©s ‚ªá8PÞJ8P,Óx(ëk[Fƒ…\“u‹QAÐky &¨ƒ¶Ä LH©wLÄGASÔÜ(è¼ë(˜P?%PPv§2€$ &¨fƒbËÁ‚sz³œ]Á‚,„0˜ ¾ $8; 2)8(r”×Mƒ¬14˜MZ0(Ò=Â`ÆG0`ðÜw‡ÁŒíìYô!`0£²gÀ`FY»€AÚƒ‰ìŽ‚Ø7ÒI0ÓÝá$˜!ò dåŒ A!v»’`0)H°ðí% J­è' z'Á-c l°d’`ácä$Xðu ”£uàN‚jˆ ADÔ t ‚’°§7ÜA° . XPa×A>†Á‚*Y‚ÜŽ-@°lvC,ø‚2¯ÀA±ÇàÀšì7”^ìr XùåwõëfÀZðáw¬•TH¬ÐlŠäÉ€âáÐßÁ°Z-é@ÀŠ/´#`…_*¾@ÀjÛUVÔ ¬¨ÔX¹Ù¬# KaÒãx,Æ=Ž€²ò1L$VT ¬\'9V(+¹Ñ°"u&AÙ Qö6°YžÑE€ ‘#`ÆÂΰaWÉ@@FÂW¹Ž€â7Ñûëذv `+ÄD"`ƒº3°Y‚f`ƒ®0°5\ `C~C`#6žêû lVÝ÷ÀdLüGÌuþv7F$ÿ52þk›»ªç^H0w”-ï¬g"`·ÏM`‡b*°£¸ƒ`§OÇ °c_Ö‹¡î½Ð0Íñr· ÿ»þõAB$ÿ‰6æuãß@¥‚À¿ÉÇ*ðºØÀ¿I_ƒãߤÿËñoòÑsü›ØV9ø;êNzŠ'2ôç5‚ÿ&€sâv;NÔ_”â'†{ÀemÁ‹þ0ç?9HQç¿eUêÿVµl€À¿…Ï#ñÏð°Ç‚ZÝýiþŸM†FjÀÅý°_ýiF á=èÏŠX£?µØúÓ£ÒEÖ±uchEC  ­‡ÞL ²±ùa€–XhýZý)€¶gÄ €jIÆWÀ„·.Pd)ŠS€)}`Â&¢€Þ±ž€©±c £;€ .ÿÀße | Ë€¨‡æü—Îäü—àbäz80'{ÜòZ•A=´‹õ;q1àÖÝá_nB»3মÛ1P·õˆÊ‚ÔÐÄ@-®ûº(P›<¢ˆÒ^»$†j1äëÜs‡êB .OžÁ@YGÛ™ ”Xеa4P<ªÏh`G1¤ˆ²VD鎌h w—ˆh`¶½0#Xðdz0°$£ÅÑÀâLJ,JVûX,|œ™ö X6™‹ X‘Ö è7ÓP¾BÇóx ƒ“D^ÔìN|`ÀŠíj‚eIe=“eÕõ VÈ̯€ ïb‚d §À‚¹<(P¾«†–Ä@nv{Åá¶¹b‚ ¢|ÒÄqÅ'"ÖD9Î+&8†œxü#&XmÞ‹˜`}[/DrÌ4õDIÙ+"ˆô¿+"ˆ­·""hRÜ ¡Q½0pãyŒ€ 5®€`µÕÑ# øv##Õ|0 Ü~³+¶¬Œr;ò1 ¬p“+êVc»e›‚ezë† Xùavr´s3ˆì¨+H×réd``ƒ³9‚Ðü>‚¶Úˆ` ?Þ LX£n¬ß7®0@³À‚樸@p’0 ‚“AFÁÕF€ *ƒ^±@|-¯X "ÝW0ÐÛx0°#ìÁ@¢k+#‘ „Fú ‰x±ÈX c DÅ‘Á†´›+HÈ»9Ð"ÖMž¼@°X€`çŠ.bH»½@þüÁõo€à¢NÆùù«N¢ƒàdˆÎIw8H«ú Á•êƒí\F‚ d [ˆ‚ ºŠg,Ð, ´JûW(„b-pÅ?"|5ƒ'¢RÁ ø{ƒ`†Qœ48û‡_‘@.΃Që ¬OìPH v†!‰‚碊5ñP`b²àDN²à¨¸·Î‚þÌ‹肨Dz¡ Òá.äA ¶lxBn´ "8(ˆ­É/D1¼ ©qœq>fFõ<ˆ²‰ â+tÅášd9X›¥\,ˆ¾‹±¡æ-0î0ØñS8 .$9 ² XÀàªä1 +€ ®ü€Á(èwEQÜóŠbö+ˆ"H ”mX ý ôç ƒ†Z΂۾ýdAmÒ,gKY=xÜÁ@«?ng,hÕ=ï` U-¿XP ÓNe,heCoTËxK!Az0Ù2W0UŠ#˜^7 0²^ó4†¸H˜ì$hu“ ô‚¿Qí‚?u1<à[Øü%ìPxÁŠ \ð‡êŒü-åðWàcúã¶Sú³5§ã¶<»ðøG‰¡ã_Û1ðOÒ#­â_„À¿[à_š"ðO.ÝøŠø'ø¡ý8þÉjþÔÝs^7þeTiºµ Ö‰kAá÷¾´ Ôª†Iw—”ÒσÂýƒn]jPc=Ò_ScwäÀýMÎÓ ?V• úË…ýþröӀнüe†k#Ø©å$üelaÃà@È*B€VüŠ.š‡šxp³¢ŸÔGøˆnR'ÑÕX¯ *ýúIªE݈~¬ØèWÌ­äW  tò+`@¿Bn (ãŠV#ÁÜ„¤ b€Xô]ð‡"|ü-F=È“G ïFÄ©§½c€Pz^1@ãâˆv*O=H…p†A@¤b^A@è+"h1·+ØŸRÐB9_Ð_z?€5QbzÁNà ÜZàxÂ_¥´ìŠ‚î  ñ˜Ç+ÖLw°[Nƒý äÁ~…á»;hg?—¡^QÀô‚VDo/øC%î þô{…‰½wÐV2L¸—D¡™+ WÃ, Fðu“_ÅÞÎW ÛÒ\1@”w‹`ÿD¿ÊåPÄA!Ž~•‘@?²ª£_eDèWøpò«“’T’ŸG:üjÿTVì äW‘þäç±X'?qa=C€ÕjXøI“'øÕI¨#øUêåüª‰À}ÛW÷U,A‚û(„î£.?¸O†#øU áüü‡pð«¶ûÉÜe=“ý*’uƒýü¹rö«•WHö« þÒ þš• ök¶.ôk(Üu¡ç–ýìÔD¿†dü@¿Žr~m0˜Hôc>t _+Ÿ*І}ºƒýÚ4×b°_7¯ ÷à öë„A¢_Ç~s·£__„A _¯*ÐYWŸð÷“ü:t*A~B¯ ¿N “_Gõù ¿Î0¶£_ïŸ*PaòëPy;øuÇ<‚_§à×Qâ)À¯/òÁ¯£ðC€_ŸŒùü:r@üŸ-Fû L”QÀ‘Ld°S‹ëQÀÎ)É£€8C€ÝÊŠôuh]‚úºË;I}#ÑBê…a9RßÈä@R7+ ê®;õ ¤Nõ xKƒúŠq‘úLrð èSGI¹¡O#íÕu }f°&Æ}&é¾¹OµòŒûl˜ÆŽÆ}* @”Ù—R‚J³Am´ •{*PÄéît@Ó°…´zH:Pξt )y®X±†”úÈÐBéFLè¦Â^ˆ€©"jHLÔ£E6 j9\é€ûfÔÌ™O'À ­aà7ÀŒÒSWûÖ^ÈP‰G3–´„ëŠ6{÷¯`ÿL,Øãç´ËñàB&ßDTαug0`M3¶!z*œ3`¥¯À[w^@>'¤²6"€Po\@Ë%àsÉ@+²u®¬@1\RA-1°H l™mˆ ›¬JÅÐ×M ®ß @î:Ø(¬t lLIt ”…Õë¦@†&œQù. °Ñ×áØúûÉ€ ;æ^0`¼^0`ÌíóŒ@äòFB …Ó®ð2Wø_Î+ü7ßÑ?d]@&BF:àø ¶Á´BOœ¸ÏToz6 ó„<pá£Ù€XãF2à`Ξ'²‰ç.|&#ÐjÚEô[\Ñ?l tEÿࢸ¢‹ æÑ?((®èö‚»¢Ld‹èßBœ'R'©€(#{¥2Û-R¡9¾R™ÛF”MYŸØÿ<Ë'Àž(×$Jéëgø¯Óyìè:@'@îPr…ÿ0±vìd(çz AeŠ„Àž> P †|W.àGøo}¦v†j#q‡ÀÎø…Çÿ\êBP{Ò¯ðßüFŠïßþÃúÿ}È@éùè£ÖýÃΩWôÛ.]Ñ?”»¿2³¯LÀ;ú×!?¸2  „ Œ:ÊKôýËH™Šð“#ü—’‰ðŠq^@d$_ÀWÁ,І2hÊ‹+HŒñà|?°O&èe1ü‚ŠÅ@Ì)ål/ ìÀÝEÞ‹A)] ¶ƒ2‹Ù)p`rs¼—wÐ^_§ÀýPPàÀ&_WiºìRGи²s!#€‹¡EràʸâK jRhAQÌÅ • ƒ¬ ºt°Í„jóŠÚ @“ ÜØP/@…[¥‰1¨ËA+ä#ä t…‹­K:¤”΃2¥:ä ›Ò]ÀAɨGÆéù€ ¥I#0 "›ËA] êrÐ ’Š|@q¿òM}jÐÜH‡Pƒ2_ñJ´ÓP š3ÿ<pPuÊð_¶hÏ#°<£+_©€ˆÝ^@§GϬÄÇ+Ð@5r!ºê¢ÍY™D†=gžZ(‹gŠm¼ÊÙg“8M¾9âû뢭lÛ²Gßn¹ ‰Ñ†êDñg[R„Ϙ‘Ñrw;ò?££­é­ý--WG´¡£øóêH¾ŠFÃ숖»#ØØ‘ÿù·®‘6·0á~ÖHû,8õÕ?…tê¬?ŽïmÛúû;Ú6©m[õÔ>ëd}Oiµoé9e]÷(oõÕ#,°=˯¡§«dšõtWLcOÑ==Н±§(˜†ž®ziÞ“7bOwé5¾ZQ.Ízº«¥ùëèÐÓ£ð{Šbiè骕æ=y#öôWT›ºQñþ_­ Ú÷Ì¡??çÄofÌŸ¿|l³è×íG/qAµ)®¿}9µ–Æõ¯¿óýf95iôM9µgoËÿõM951¦/NkåÔÎb·btbü,§&¶õýý6–S+û×Ë©Éüo ŠÊUW÷øI·ËÙÍã'.<Óüo I—g% ÿ[&®VàK(~p¾gð¿%8KWkð¿%ärËörŠv[‡ÿ%lVæ³Q¶ ç[Zx]dÍÙQ¤Ø~š¶á}ãÞ8«'xß,µ×žá}“6zæ^Ìû–‘9±d•´-6#ô÷›T±°nÜo ß«w¸ß°¯ÛêÞ7Iõ3Ë. ³G©/¸ß2äΫo¸ß2<ˆk$¸ßdÓ}(F†û-öFÉ^BÃÞºQá~“H—YZ²?íçm{ »M£Ãý–9M_˜„[QoÜo¨Õ±Æ‚÷-Úð¾A´ºf‚ó-#ÇnÍ ç[F!“5 œoò–X› ç[Fêû±Àù†"K¾Ì g²› ËTô¢c’/sf N³Lxß2T9k.xß2>Äknxß2”Pk%xß2J@®•ÍûvØÎ^çUà}ËØ¶y­ ïÛ± Xà}˼¯Õà}“£ôräˬówFAÍ%_f¿3’—|š3Î¥n©µÜo2À%ëŠ8¦=7ºÓ¦zrùU:„—öjÝœÊ-“Á©A} ™,W/mùîR6ª¸JVýýäÛœ ¢µZ¾ÍÏfgZð¾eÛe}í ç[Æjb U_ÙjÉp¾eHë·î]ƒh­~“¶ìØ¥Sx†_eËŽ]§Ò™bËFkÒá|ËÐel©h¿q*:¶|Ÿ-;Ölù>gœª¨aÃ÷æW#›–°…Aö>Ñ û:øA u‘_#.:ù5‚¨“êq\ä×à¤òC†y‚Zù¡Z®“Ÿ›3:tøCÔò‚?„Ëþ.‹ÑŸüŠö¹&ý)ëW”ô§z+;èÅÖþTë¥C ýi7úS®7jý‰Å3¤?µè8I  ôÓm0 ~ ÿÆu@?µèWè§ò0» ŸZŒ)~biöS‚qØOÓš´c²ŸXŒ_Á~Ú¤gìçÛt:û©ÅNü‹€ÚÄúþ-VuüS‰›µþ‰Åà ô§Môܤ?u_!‚þô 9Ðßb™§?mcGý-Ž\ô§ûž2‚þLÞsÁŸ 3Á~îqöÓ~·À~ ‰{Ž~b ý´ÔˆÐO-Ö ÐO2„úéÕX?@?=J/è§é˜HWÐŸÊ íAê¥1Hý©Åè ô'#;ƒ?ùÛª„?µµþÄbKb‡¿„:éa!ý%"‚þR²ÅbÐ_‚–&è{ü%D­þRÌþXE6à/ayÀ_ÂÞ®Év öKP+û%lëì'µiÍBøo”ÀáOÊøµ‘þ$—A zö ?qGYÒ_Bü>èO,z…Ž’‘úºè/áKô—lÅðçþ*‡?÷{9ü%|»þä² »Jü%|—þXì7à/Yn\°_BEÔ`¿„»‚ýTÑÁ~ µœ‚ýÁ~ )AÁ~ ÅëþòÏþV  zˆ€?±èå8ýq‡ ¿„òAÜê8èïÕ"Iú ¾é/Aô—ÀÊA ºž ¿„ŸAܵ3è/5bè/šþÄ—¨Ëz§¿dÒŸ€?¹³þj$ý%lÐèôG7fÐ_ÂþÃAr5`=Ð_îý%”à úƒ+3àe^þüÉ6¼ öKP‰û&ú û%hÆ‚ýÂöKæ#ôK(éè— zô“Ë3¬#ú±.m _‚–ÔÑ/a-èýdê~âŒ5#ú%”6 ôKƒØFúKã“þÒ„;ý%¨Iÿ’mÿ¢â_ÂÒ)ð/!“ ø—èæpü5Šþ6Žܵ&ðO¤Œvñ/a»æÀ?*mÿB6 UC‚ʃJ½`'À„ÕK`¢¿ÄP~.c7 `‚H6.ð@Àè†mˆ€éª¢ýEÔœUÛÑn ܶëéEê`5 ÈĶ@ŒC 6ì» P½‘†…›™Ø…A5@àÎ 8îŒ@ŒS ºØÍR#{<(P}·Fl©ØØNÅAŸ‚ õ\(àÎ…Ç…N¬t;A0,Á85Aг‹wA•lÁm›Æ^$¨°!“±‘ä0(mšÞ`26âwƒ» Ü¥Ã ¦CX›Íllñ%èð; ™…¸:¾ñ”$;‹ÆU*ñ‘ä0¨êwXB‰oKC†ÛdP¡@€#Ø&ÏÄH`ôÂHà€P2B•…"82co 6Ô/Pà@Œd®D(pÀy¡Àc™tª‡++ D¥ˆ¶÷P`ƒg)B Òš6TèðP ÷½‰P`eœÊC•11VL²lô³{8° F&”Íu"wìÌc1&ž£ÌÀh`£[Ý£í dé¦6á5ߕǠÝC=1ÉP`X DyÛˆöʈ"#ÒÄ ‘ÀŽ*< ì‹<Š6úƒÒf?pP·™AlJ|Æ©<Ø3ÖߌŠÒåƒ*ù¶Ž „0;bJ:é3ØQOÇc«¾ˆ6F(°có— ÁŽz^Aƒèä4؉hNƒ`ç4(9¼ÏX`':9ú/ê8Ø=°Gl(ÿ8Ø6ûQ´ãƒLêì„UçA‚ó`Û€Uâ`‡ÄÁiPi¸Eì ·Ûi°!“5hP’¬ i)Eƒþ ‡Á¶à! ¶ ÿÓ 7 lu$6TNl|&% JÛ¹£Wà`£'ÑqPrZ¬â`«Œ’›í¦8Ø:‘8(É`¯›™?4ØÏMl8 6‚»Ó`Ë;Ò Oª¤Á†TÛ A¸!$iû} "å=`Púµƒƒò0 a°"5)h°%ßHƒÍîƒ ò€Á†ä›€A¦ú 6°¹÷ZÀ ¿€Á–æ# Æ™ƒÁ‡Á–Hz€ÁfïK°`C¥Ù`Á–?Y°ÁS,ØPb.X°eF ƒ {e ¶Ìø!a°²)i°!*hP~-‹«‘"ìAƒÍƒ “~Ð`C2PÐ`Ãg h»Ø ¶D°# ú8Iƒ • A¿›Nƒ ꉠAîW4Øàê l D9 ¶Dª$ 6K lŒ9 6¬¦¹aÀ ³F[a¤rãêºÛƒÞ‰Ã`C %`Ðo”à '»€A…›9­‚6 ¬›D²`CýÊ`Áf•Ø[F€ÖQ…“`ÆA‚œÀƒ¥á#I°eKÔ d¾ïoTQ»èOK’Ýô—‰ ú#Ô;ý%ª#ÿ¶±üKˆZþ%¶ ü#ÉþQßuá¶% ü“£>ÿè?üK ŒÀ¿„š—„øÀ¿dŸ^ЕeA ›èýYâÛMb1Ž#ý¥IÖ#ý¥O ¨ZP¿‡¿89áχäð§"üÅQ„?þ ¼š€¿°¸Ô-„?^qÀïÂ%õ£¨Åõ]:Poâ:P·¸ ¡—”ý„¿Å%Ÿ„ ì9„ ¸}—”ƒ!(·Kêý¸”¿© Aý/!¨­œo!¨­B åò¥E)½K Ú¤t] Š÷õR‚vìbÐ΢«A±À«—‚2äRP<\—ÔÕ˜—t>á/}è@Qêè×t ‘‚ÐR›yë@-Î:Pê!Cº€ƒ— Ô"m®]_¨@­‰‹@7¡!…£ænJ>/¨Áuˆ@7¼'!…ÙÑEý2*‡ûeË ôËôz8úeÔçh¡R”èÇ¢Ž— 4#Œ2ÐLÊthÆc:Pûô]2P(¶oèzÆ3 Ô\*P^_¨@Q|ñRV†ã\ʈT ô®Ü*Ðñ¡­À­5×I¨@]ê2PT yÈ@A[—Ô .­Ϲ ´"Z*ÐúÌДf— ÔŠ']"Ðu©³ŸXŒÉ~Åq/(ö¢øµëëf¿Œº-Á~Û“ûeÔö±ëËÑ/c#´@?ÑSšQ–$Ð/Csè—7’è—!Ÿ ôË(åì'O€‹ì—±5r°_ÞŸq@×↔ŠX‡¿lr#‡?‘ÕZ W‚bÇ4#0H%hâQ®…lö/¨¤öHìó)eÎ~ˆAá 1($ƒ—q£K Šr——””bÐE‹«ACo®ÝâWº@^“ ᫺@Úš =êç ˆÄ.’`#_: rCä ÁN¦“`?À©CýéˆO„%8Ð*ZÍë‹ñž_ˆßÅ,S¸áf%Aî¨$X¨æu,|Çœe‡0£E’`Aå¹ ÁâÁF’`ÁnA‚§¥£`%; ìV,ÈÝÈ‚+¶6 ¬p÷; V( ¥7kA”^¬_¢`eÀÌQ°2Då(Xó Ã|ŠBýb¥xûYå@°¢(©ƒ`u‘(AÊžÁŠÚ‚µ3ìF¬ð;8V¨°+µ’‚•L+ʼnN‚ÜN2HÐ 'ÁŠoE`Eò Põðë`hŽ(è÷ÎQª§@ÁŠz‚ØE1H»r¯Ë+ˆ<”ÁŠzŠ‚R¼Å “ ˆíƒ+Vƒ‚§Å3#°¢>`p`%ž;ÖÅ^Èñå«ZNY·ˆ^›'g}ÜòGoãeÑ>›ÄAhòÍß_H-§® «oZ®jc´¡*QüÕÆr’š}õÑ,ŽÌæñÏ«£3½ŒwyŒ–»#ØØ‘ÿyw´Ê³›U>;Yåêb}”tûÛP;sîÒ/ß_S@-÷ﮟv©ß]?­Õþß[?í‹'ùðª€Ö¸ÊY}ùèfd\E+ôÅÑØ×]}]­Ð×£ûòòhÞ×UÍûŠVìënÅ÷Ê ¤±¯»Bš¿ŒÑ }=Z±//‘æ}]5Ò¼¯hžþŠJjRssÍÿå*©}Ï$úósRüfÊüùëøžFáé}öòWRËRÒô¬¾¨¥&µÃþÙÿõ‡¯ }SKíYóìoQKm|ÑÛŸÿ§¯¥vîÝÁËå¹óé"¤ciÉóºª9–N§+Z ¤e]}ìo¤ÅëçýXVyÃ/›`Ù™–bÝɘD û‚e¿‘žn—Œ¬lEöCv:Úp#(²ÏEŠ^_¹æÇ2ŽNfe¦ùÆ!«¼‘·ÍÀ`_…óÍâ!.–í3ˆÏùàÖo•âͲЦzVv²«©­¿YÇ­˜…æú?– ìn¿oHþÆú¨®òFVt²_·n¤dcÙ›SKX ¤ŠX0€É»Ô8‚ÉŸ®É>° ÙÃÊ,Ë®®éV–:ž¥ˆ¸YŠ]Oõæf×Ü&‘ñç‚w}دÛv~#ºØ‰»dêš¿?]Ož=a‘R•­ßÎl»sØ1Io–Ž6"B™'mF}Ó_Ðó,L_ÆÓÙò~ñˆwƒZ¬ÅŒd³à"É0 F>ÄÑj–e#B ”®:A•—Ep”Á3}匑»ž![ã ½íc–7R‘;úYæK¨ðq,›åë¬ßÉ1þ6“cÀ2Ç"Ñ:Xlœ³Ì7‹ÕÙ¹§ð ,hÓúéÀ¸¾É1 pã±p ÕÀëXfy#×wÙ™RxGášw²QUþîg)‚ ï7ÒoqÇÐÌ3u,CãKµtï8=jÚ™–¤,™¯üê ‡8jÔ7Â78‡Ð,8y,B³5αœ!À²aØL¾ÄK/åÚì;³íB:<åôXÊ|3%Öîîæ:®Å6 QCC7ga>ҬͲízeûgÈ·ðUêïxáçÛÁðˉ!h“,EÈ™>ºÍ’qHÁße¾)úÂ1uPofÏ‘Ì?(ÓgòúánÍòþÀbž‹GJ¨ÝE¹ùÔÚ=“—ÃY8¯T)°6öîÈao„ÆÔµu,¼z•Ÿ?™:iw(g¥üá…÷ŽEÒ ÐÆ ½½Y­Ï ~ñ˜ ræõƒÊå´™–3íônö~#jg´\±á2?– ]íâ€Já1vu¥¢SûMäkÌÜH û7dt:*„_²ÈþâÖ¿váõc'ØcáõÃk-–M z®ª‰3M›=-5Ï7´qöÙÉUÜö°ØoU+k ¢ǰqä{ŒÊ ÝŽÊAÙ;’ë,o¤¨»¼º ½Hæ¥"OÔÄ©0„Œ„s÷Óâ ÐFvõB¥Åe?©ìêÅ((,µ³Œb²ëi´Üy¨|xf†‡Ðfy#§vàbV~S¹go;qkeüæM·.¹;Ï+†‘ y,ÂÕ¦ Z†]võ‚èWØuãFµLÕqî…~Ge€Ø~‡Î!@§w,BÁ/Ñwâ˜6 ›C2ÃЧY x1FžŒÃÀËGÖ­¼“¸ü‚ù:Íž|,º—âp¹ß± *Ñï,,¡ˆ÷K>ÇéÁTÞë±7-öiÍ3­7…{Öfª¨JûÉhSk(â·’-½¨´³OŽûË ÇÀEz–-½`Ù°L†¼ÑËÊEà±ìô¾‹bñ1`RX1ü~Ëü$b±åÁ[e+[q µsPÓ‰Õl%—_ŸÕ+…¹qq ‹Ü¼8L„k!f¿ñ÷¶5K@ŠÅÖ@¹áYÔ9Ðê6¢ÍëïõæõwŽ|­¿%3ßS<í‰{í÷ôc{±>ÈÎzXÇ]¬—¿=¬zö sÁŠ«]°W°¸wÖCý‚½‚ß"`›$_°W¸”*1¬2ö|9ØsuÚ«”Ó^%q•àU@d ^Å ÷*×EÎ{•£rÞ«\N;ï9Ô:ïAT{ñ^%VŽa㘉Šf¶ØrÜk¤Ç=çbǽF~rÜsRvÜk\;î‘•ö|Qé´Ò^ã"Øi/i¯"u[¸³Ž{=à.‘É7¡ḇÝÍ/Ü GÀw,p¯óIîy=vÇ=Öc¿hº]О¢½Ý¤CXd»ôFM6<Œ =-õf÷´§µÝ`)pÜnÀÞâžB{^þÍaOÛä ”´(›ŒõÔmú[™ŽŒIYO[€Èb›ô·éXx²ž¶1ƒa’ÊéÌ`¤w9@zZ†m8€I§Æä¦ó¡aÒåžé©3ÂKÕô´–ýÄß›¾ iq\¶ô´®›Œ’ÔaüËÐG´ÀgFy^ÖÍ1O˺ yýØbÍ1ï>Ê I}#@«Ä¿QÆyê±cÀy÷1"i•·å©åAyêpA'Fy— ”§ôÌla/1<ÁÔ°÷eÒœ÷T«ÿP¨“hÖ:ÙüF>õ@ G#›#Þ7+Ñ|>ˆO“õá=­’¤Jð 5®~€|ÎÃ$>Ý#ÔU&Ñ+±Âtâfá<2× ˆ©”§@z„÷¤ñnúºæ#¾§(ŽGÐ9JŸgó9ðy<ú©ƒNtÓ:Ç„Ÿ¦ÆÈ„£=ÿ¶„ÙGpOÏa† ŸPgаç›@8ìiº,×ÅÛ•öÔ*«ƒÃÁµ‚öôçFöÆñÔíùö ½ks§ iO“ ´§NÜò¢Gçér\œöôyA(±¸E îù3ÏØóHöÔ¿ƒ6‹?9.&†0Èv‰÷ C`l/.±½ìñÆö2*·El/~òCàQˆ‹åN/ c{¹á)ah/{”›¡=ræ†GAeÆõråÏ;ãúó3®—-bX/7Ù!¬—±íS„õ²Fg\>B“ ë‰å{êíù‹1¬çNl„õ2¿sÖ‹bˆœ2ª¿.£z¹1¢È¨^Žø!¢zW?ˆêÅÝfX/fÅC˜8 A19 gGP,Äõ²»=×Ë\½y\Ïg[†õâ=`\/&8Æõr„×»N=}§¢%âz1LÆõ˜q=¦XG`ï²d ›A8ö8Ó{\Ï+'¾ìK‰C›1´—éÜóèÞu /ûÊ‹Ð'ýA}qÁùˆiíX´õɞѽpŸ“úü¶8õI¯Oê󇨩Ï?”N}*õÀ¾ìGìó‰Ú±O’n¾ö1óØçó°Ï?5Ž}ò£`_Œ€Ø7—ÜwõËT r+/rŸ/œûüÍtîóIÁ¹/~?Døü9"÷Å/ã!>¡ûüUˆ_ôËçGç¾ìP¯1€ÏR,„ÀgÙBó#ÄWñ2x„FøüõâkŽœŒùíö_ó ßö¥±”!¾ÂßC|Té×>B|œV#Ä׋c„1øüEõ_#Ô{„¯òÖy„ϧñqΊ…oäC ô+ÈGÉWDùœ£<Êç¯øˆY‡…2NúŒòu2‰Gùü.x”¯‘šGŒµGùüaó(ŸOcå£\æŽò‘óåóGÔ£|~7gŒÌ!²}“_¼Båã×äŽò!ˆ?c ˆ£q~¢A2tùÀMåëô^Q>Æýº¯é0ÌJN‡€ÙQ>Ÿñ=ÊçTwEù°‹0ŸúŠòá9º¢|¸sW”O'…ߨŠvÁžVþ¿a/ñ‹OÖK\éê¥ÎE7Q/ù➬2²^BVq°^òøYûdë¥Á¥a/ Êý{,Ö°—„=Wò8íI?f85–Æ„=VŽØsÉÃ+Ð쉆í`pI®Å @=¿ÔcÕ¹`½8w0²ø1c= i/~â«ÏîůÛâúÉ»®¡<À’ŸŠ´×BÚ»NÚsç‡Ó^òØSóÜ´ÇêþA{qÒÞmñŠZx³%à¾ñ… «½KÐÉð!} uß’N Ê%éDhê’tRä’Î@ßrZ I'˜å’t‚GBÒ Å&%a½ÐtÂÛí¾Å0À¯h:¢G—¤33¬GI'þüÿ¹{—dÝ‘$IoÞ«8ìA_Âߎ Š"±‚JqIæ {ÿ„™©ª9þsã•L6k÷x8€ðÏUÍìæp0 >üœ÷›ö.úû_~N´4(aÍ;üœ@§ÓЉ}ÒÐY?T¾›"Åaè$ÿ‘ö¤Kå“}:‡¡£’Ê—Ï4tRÕ£¡xu8:û7G'áÞEåB¸w‰4‰{N§£ÓNC'¸ì0t¾U¾R¸°q:ë7C'Þ2tB > d¹žÔë÷òÐi餒¸—ÆJâ^á•8L·PøÀ=<‡©?Kà^åp˜:ÛîÕo™eg^žN,?ˆöd=ho¼u>™9hŠOÒ¿»/O'z&*ñ³JÚk¼4‡§óìØk?¾9:ñ?Ķ„½þVùJçìw,.ŽÃÒ9_°×ù ö*úHKç¤ÉSËßxqö:­Á¢½Î¥®ûð¤bÒòýü…4h‡­³@|Dñ}:;Íg§Ü€rvvZÈäìäâA:;I»éìThšœ“ÖDY;×û©næaíÜ‚4Žá–m“c¸u,Ú"o @°vÞ·àï’ó”ðWHøãÏ&á¯~X;¸#Ñ_…§Mô§i¥èOÓJÑ_'‹þ²……ã D6¥6?·< õ#ý ™+“þÊ7úÃù‹þ9^ô·x„ŒIüÛ ö#þí¯8>±í-f4ˆ?7fÐU7‘XðwóŽHê»Øé!õÝoø+Š]“ÔwI ¤Nƨ‚”úè J­¯rŒÒúŠâ)WâJIëãºyj}UQrÔÊdV–Ö§H0i}\eN­¯ÑŠ*­¯qMFZŸš™b~»‡Ø×?Ä> s…ÎÞCîc@Þ•vP[ŠeoöKñçûp%$÷IÑ’Ü7¹ò$¹OË6’û–¢ ©•M*£’û¦t¹û8—M¹oŠÑ8„M˃ô>>¥Þ7é¥Ü§“‘Ü·¥,RîËn8„MÑXrŸ|¤”Êè…Lµ/Ýœ²|~ª}/k§çÈ{k}–ÿ|F¡l:¥õÝüiü,éì›üŽj}÷g _½ç‡XjPð¨É*؃ôXFž4ò³¤oò«¢p~µj ÁÄØ€M•¡;ä¾*C¹¯ÊHî«M„à¾Z¹jNî«…s¤ÂÜ'÷Yz®øØW5•%öYRAlì«•szb_mŠä¤Cûj—·ØTåÔ#÷Uîû˜ 0¹Ï²žÜW5_ î« ®!÷YšBìî«2„‘ûjà öU­~“ûljúúêÈ–À¦Ú)^ýj i@¿JÏ€Ð/èWÎ ô«]6L`s/&úUzÿ…~‘¶"¿*e€äWe„#ù=-÷[ç«|ljü*z?Û¸ð«)ö¸zñO_¡¬¤>»¼ I SÅʵ ¯.Ž™ÐWç7óY¿°NæÙ£_B_›ÐW—âú@L•Ñ‚¾º8eè«“?QB_]ŸÖÎ:)JŽüª¤¾ºu$PŸån|[;ëæ¯’Ô÷´À4Jê³Y;Z8­1ú*cg }GÇ'3ß‘|Ç}u sxˆH}•© D}¹©¯nŠR¤>KÅ €¾Ê9— ¯…WžÄWµLAâ;ZI¢OŸ]`#ˆÏ2B’ãôÛ¥=œ¾år|ñµ‹÷È×DÙD¾ ‘¯ÉOä³½p, ¡i$¯)L6¯é3DäkZ !ò5~Þ„|­°"_“ñýÎ\oäkH%{f<«ãGV¨麥žÍÄ;¿j›Ìxö±IîÄŒgŸ{ü…ŒgÕN|ž}³åL †6fÒŸG~±f¹õúÙ[ÎŽÐÆŽôçÙÑÚí:-¯Ž¢MñÏ££^í£ËV)dGhcGúó_žù¬.§¯ÿl™Ï¾?ÑuTDfú©Ÿ=Â×™j/³èëÈi†¾^9ÍÐ×±úzmž2§û:sš±¯ÜŠ}[ñ÷•9ÍÐ×+§”¹úzmž2§û:3Ÿ±¯ÜŠ}ý™ÏžÙÇ?þgË|ö'^¦¿¼_Žß^¿üü>_§¿ñô¾{ùë™ÏªUH®ÿÿÊ|¶–ùìÿä;«£tÅ·óÇŽ(ô6ëhˆSøÈöÊx÷@é:Fahx†y12<°éiQ8¿ÕKaÔZ¶Â¨ÑÍ­0ê@“:¯ £Žø,!Ç1¿~^e1Ǫnq…6F4û+š¸ÎQ¯[¢a^ ÎmètÞ\Ôå×fxî…ž?v뼕õ+­®k°%–*ë*á¹±ø÷À`Sxk\ˆÕ*ƒYÃüXWG *{Jü5±Ï¼Ô‚†ûÝú|WE͉s]{1øsà„ïÉh›ˆÞ¨ûRÞ¯ ‡U•÷ '¼kcKhhu·ÊxÐ8øî…á -ËÒxBö¼+ÙÐrs¡úÂÖfKÇ6{qé:Æä%KÐMt™“¼%f§5Ü•3#ë]e´À%·i)Z‚yj”‹™C«zÙ诙ù°ê=é´àßrZ°—•N l³?2fUKÁÉŒY~±ÚuÉiQÐR”1+¡]UN‹PÙÚÕä´háh‰m×Ó"QžÙb}¥]“¦9i)gÖ@/{Ƀm8&h…c o®•"›B,+´R›Œ>q6¥UÙz°MWÒ¬m†’f…öi¹i뉧 =lÉ–‰½ö¹Ñï–Õ¢` ff:ÀV/Y-°W-Jœ?Åç‹'£®zm2*`§^(ãÇÚY«ãR¦)l3nÊ è…#`|«‹©¨âzÖÍÌNøÿ÷”ªw¥]ƒ®„…–ÒÉ ¸ÛçO·@k<†„·ÖaTØX­~E¹§.ì5njø<ÖÜÔðq†mÁ[ÅŸBO÷¦-Àÿìמ~P½†Ú(“à!ë­R&‰ç°ãÜM‰ûÜqîRüŸ–û³en©$èg-‰÷1â¾' 7Znh-x~GPp¾£È¢€nm–‹Sèd´Jå;ÖùÚè…^íøµ1.J?=s(ô´pÌoôPå’òÜ“Ò~8ãV|d¸Û¼`Xø›c@Yî§¥*@2½šaZpƳ+@7sŽë–ò´ÈU¿°×Ü”~¸Ç@»Áó”)¼?”yËU§b]²ÕÇ VÁ¡ñ޳Ï2ãR°E!®ÌêŠ Àov 劯ÜÓr+Ò+ƴ榜uãPk)R{qL¶ÔVŽ ¬,m_r¤ÇZo³ú[”³¢ç]¢…¿[†IÆõÜ]®zü´÷Pœ$îæä‰m¦\õ±ðùüp—Âoâ ï­(ÃXÊo‘(f¦¾Ýƒ>G7ÇÀðÑæe„¢e£¥½‚ÓšÎþri Ï}˜k´ÄòÓÓrS¾Â“~çpµî%W:^î÷†ô¨ÏšUà‚L÷¼[.ÈtqÆÝJpA”‹§­_×÷ûÕp~[Dµ>:âº}–1¦^ÇÍ1Åž™ÿ–$×¢…# [°_×µûu¶Ä“Ô­׌œUà‚Jv¡^*ÄSz»Uັ׊Žg\8†ÅkeŸe´`“ åqáõ×Ë’òÈCïI¡1^ˆ½äâíÜë1´”Æ–X¬íµJ=½ÑÒ ŽúÅA5l3 žâWac–Õí»Œ––µ¨§6´ìùt‡|ºñŠäBK£±MË1à·*ù´ÄâÆŸL}–äç9k_äÇOòkßÈ,Hò«E¢]‰~•¼ ôkœ‘ ý˜ú:Ù¯þd?jmÉ~ w4Ù/[@t ;H5ž®d?:–þèJø£U;á¯#’8áù³þ˜j#ᯋ·ð$ûuâ–ØOÈ öcÌX²ã ’ýh/Høc|UÂÏ  ÕKøS‹à& Ÿo«-¸u€?o”õBH'· ¤k AŽ) Hž“,ÖfÙt/º±p@¾ Xêïdg¤¿ÌAFúóïöj•-@Æ^”ë ;‹cº‘ó ß~ wáÆr{Ý“-ø þ´`Aö;7©©Í^è—gGôóUŽh.ô2næ:‹ï¨ƒŸo€¿×æÒI<ä?ïÇáùó8å8}´”ÎR^mL߹ϷyqŸoã’#à69L“À}žô-¦Î}~z ý8¨ñâ¾L&GîËtóä>UH÷)™±ÏwöÂATÁ}ÇÀ}™pŽàwœ`å€ì~þÿ‚~Ç?ï5ÎàçÛÄ^-€óm9‚÷ùÂX\pŸoòâ>?º î;† îËôü~™Š?ÐÏûé9ùà¯`?ïÛÔÆ¤z€ ÀŸ÷"ãV¯HÇÙþ|›%èï8_Ð_fý#ýy?ÑpÏs}ð—«Š¤¿ã@ ?ïŒÖªõ¢¿¼+€?ï›pº+ƒ#XüþÎCíÉLýÞpëbNÂø“#È 8ÆrýŽý2m!ÙÏ·Å ™fzž[ƒB?Â"ýŽÇìçý€Û®Îô‡×YõðwŒjq K¬—cÀ½ýù‘6ZT=‚ÛLUÀ%ý7fåxÆ9†ò¢¿£ПosÐß¹ES nÑËǨvŽtµs Xìý©´èÏWµÁ¢;×±×=t¯Àd9œÏc˜Ø¦V ÜÖ˜‡¬×‹^  ¶q)Wå‹þŽçäÎ1`T ¿óüöä¨ØÏ­õ|`Ü•Ëù@°Ò4( \³ø‹Cè øó¬žñç¸8¢ŠN‡Š’çÖ³öb?%õ$úeþP¢_f%úå#KôËÑ/ÝëD¿ÌCèwî“CX8Ò¸?öóm€k½@d¿|°È~zýŽ[ô;^©K.|ëˆ~ù"úù6Øk +*8¹æ0( Ÿo€\KƒŠÛôËß!Ñ/Ÿ½Ôøu7[Ž!Þ™©­â"ÿ•Dh¤?W JÒŸ‚ÛVë÷‹þ2MéÏ×Ç_Â_Æ¢“þ2—ô—Êéïl¹3Dù¥üù?8­dõ‹þΖö ²úCò·_“þ\'NYÏ—ô—Á褿THÞò¢??ìR€2%º¢ kÐ3ð/u âß¹Ç0_Ò_†vÿÎ~§”×Kû;Îøç-Ñp+ÆvŒ–#À(¥üéü¤üéŠJúÓÙ@úÓõÜ9‚ÌÌõ–"¬hRþ4$Ij‘ô§CIúcHJ¼Rþt¤üéàRþô|Bù;þ¾uWv9:‡Àªf¼Â©üq›Tþ˜51•?AÄ•c`KŽa~(¹Mªfñ;¤ò—¸GåOdt(<ãìèîPþÐ’Ê_Ë¥ò‡äCùÃëPþØÏ·1ÊUÊß›Ï-㠇ðW?„¿)ù­*Æ€*áO—BÊŸ%åïh¹•{GÏ!T°¥†îõ>*:)ºRRþžÊŸ(¼åê‡ò—=Sù›œ\IùËm¨üe ”¿¼»c`/7{•A;Ëó¥úwMNV)ÿ奣üwô“#Àï9‚þ"ÀóXÏòPÿ;¶þ—÷¡k 1êqŒá…€y+©ÿ]t£Hÿ;v‚þ—ƒ¢þ—§7Ž!€-!¼ðÜf+á {¾?Î@ÿË-fáCÿ;Zš2Δ—ú_ž õ¿õ¿ãlŽ1DÞ ÷ø¸QTÿòüBþÓ.TÿòTV§²rí€Ç¦üwô35ÂsNùï8™coù/{¦ü—çCù/Q!ÿiPTÿòd¨þå]ÙÇÞêßqè© 6Yšq“­ùP{áßqðûA4ä¨ìÕúqŸBû;:éåcLÔþònSûËgæÎ€`©ýGÚš±åÖ„èEypI…GI:¤?½¡ ýé0’þŽ^‡fCl™šÏQÖ;€~? é/·¡ô§gFÒ_îEé/NéO ¤?]˜òmTþŽ]æ~¿#$ýé>IúSò-IJÐ%éÏz·A6³½¢¡j6t›|PARþòÎ…òwì£!ÄŸS&(À4e?Û4¸ÓlOÙï¢ ÙOIÈ$û] “’ìgÛÑñ¿™ -Õ>¯ qð^‘º×`›`0ò^†W÷ž¼W(Vˆ÷ Ê’÷*Ýlâ½l!-½¤¾,°WiÑ$ëU²'XO&åÿ&&]òkõ嘨‡’eIzoô$½ i’k;%éÉC+ÒË’^ýñzU^QsÙBL¢ë'Aaú z•Ú›@/O†¤§mö1´äê‡É3[ˆzÙBÔË~FyßÎ1p‹c h!(U¼Ü’õ˜›2Y¯~³yêÆ6ÏúÁzL3rÚ< ð/mžÆ{y,Ú<Ù a/[r x”îc Ð JU¦N‚R•šFØ“gK°Wù῎1|Ø<ù{HØËž JU¶Îy¿÷!ìe aW4a¯ÊÔ™c LGRâÝKØc.—„=–NØËmr åÃæ©óìåÑ×Ç>„½<ž®h¯’¯¾ A°w}ƒ=>8 {:¸`/û!ìÉpWs‡ÚwŒ°—]ötþ‚½l!ìéì©ß–€hHRÒù‹õr'²^ýÆz:A±^îµß,XOÇëi±žöëéç#ÖÓ¹ôc ²ch¸?†$Ôˈz…K%B=ݶÎ!­¾@¤§ŸŠP¯ Ȉz¹WWÝœòziãÌ!à„Gáƒô²’K&éñÒô´ËÌÔ—ØwY §Nº’Ëtº:¯'Oœ—-ä¼Ü+GÀƒ“ò‰Iº "= HO¿ ¡^n‘C@'‚ž4‘žNF¤§“éÉ+ÒËCå0ð•C pvi2¸*íãçÐË¿IzúFˆôtè}  ÷û“š §ˆô4J‘^¶Üãã¶Ü9<±÷1„ÔÓ õôúêåCS:iÜwê>Æ k}Ü(‘^v|k>Dtºúû¨Ç~õr›÷ˆz•ü84*¤Ç{¤—æxrǰ1é‚(Ðã±ÅyõçélÄy:véåý÷1¶ÜïIC‚žÎN —{íù¾) z:›šC ¡M…гH/[ÚÇT(I¯~Þñ÷ç{Ù²ÖǨ{Ùrk*t½„¾³%Çp½=žüNü•Thg€_ýðƒŸpÐ"Yu´y¶ñ}]îÌ©:©ðUÊå9ÎG—çÐ6ôHåòDVÜ4yÒD“&OÊÄiò\Œ.„É“Z.Mž[–ÎŒŽ££óR,(ŽOºxÓãÉbéñ¼Èó¿1IMçMŽ–Çó–öF“çÍžLíCø»„q‰¯–ÎK-Ôý𮸨J þ˜,áUÅþ2ÌŽðW°"™ðWÏGp*°]$üy/ …šÝÀ‚ÄÍ#Âï¦ëó~OêNö»>"üˆÎúó~ü:x,Ébðà:Lj‚ yß~É|ÇßzU°%G§­Èõ–Ï?R]RÓ {fQ*e||E~MœÇ14Ê"?ÅЈüšD=RSî5ù÷G€_£ASä×ò—c@D…Èé’’üX×0É/[H~4m'ù±Îy’‹þ%ù1q\’3g’ü£_D~Ø×/)ìcZÊä¾.:#61pHØ—;û˜Ñ0±ïh¹vIɎ節Np_•ns&É}]¡{ä¾l!÷)F©åú÷Ѻžàצ&=¹¯+J܇êZ‰}¹‰FðÂ>–OìëŒÕ#õ)¤IÔ—-¤>¦1Mêc6À¤>…a û²2«•%ö1¯Xb_öÃ!¬w„ßÅÒ0É}¬“–Ü×én÷qàÂ¾ì˜Ø§aŽŒ«#‡€g^Ü—§³UÆUqry‘ûrܧÍÂÅ}¹WW©Ñý2yú^l¹9(n3U.•fÑEjR̲Àó‘?–”!ø …ü°pÙéÈZ©”ün °8U+›,•J½¡øñüYö'©o|<³ibßí²¶÷Ä>="¾‘vN ¯q8’û²grŸ®¦¸oH:¼U.•&Ëc  ¼ÃËß™¹õ‰}ŒIìŠÁ#öi¾Á7ØCÀ[NÜ—G"6å^ä>+¹Yü“ûX'¹=“ûOîcá´?Ž2Áoüøà¾ž_Ž{9† A/²õ~=ßGpß±W€ß+4ǰ±Oª|÷Ëáyîu¨|àLjÙSåCχʷ‚©òùþLˆÖ= Î(‚©uæºî#ϯÚ&¢}l’;1!Úç!!Úx¾Žï¬al9³†¡I…ôç‘~l쫼ó˜±åÕQ´©#þyt4r=2eý=[ÎŽÐÆŽôç¿<Ù¨Ž¯Ž}bú]Êñ¼üòÓdÞgž»Hë=‰Ä¬§W1ôtlƒžÞ)ÉÐÓ‘FÌ{:“ˆ±§Ü†=½’áÉ=’ˆYO¯b|ØsôôNG†žŽbÞÓ™fŒ=å6ìéŸI3ÖWD^ýçÊ2ö'ÞP¿¼ß8ßÞG¿üô©}½£~þÐ~ôò׳Œõíéxþ‡Í2öŸôöi–±‡‘QÌþõï?ic–±6ÿ ËX·oDÜžÉß?ñíó¤ÖÑ_O$QõuÊ è~·ÍÐr„Þß}1´_Õ{L’cfuO]Äõ{u®1ÂÈso…¸,ý®\¢ Ô¸®"M–òZÍW½8ÙŽÙãÓr3¹Î@KÛLGWGzF{=¼¨ô1“׌¯Ve…—q­˜UƇŒ+Æ`‹XǺcöðü‚î3Ê3 ~co¬‘aëÓqh܀በÖí<-¶”µ,ÇvøöÆsomDc!f<×ÎG4¸">†`Ê1>ưNÒK?þ¯aªE4,[ÉZV&£¡OÅ»¦R"qÛJÖšKcÆÙÏE/ø˜qöÓº-··Ü NÓa­¥¼ÚÏÈ–ß¡}ó‚Ïn YË2˜ã–L€­‰àaž1‚éýau’œ«Ã¦0Ϙ¦¥øÇéYúk¹¹Í2áé¸1ÿÂX–xëé§r íiñ!ØŒ¯ÀCxž>¼ØÇóHú öÅGþ¹Í6¨ÕP``¬aëXk­›÷ñ¹”_ËrgwüCØ ÄX1«‰Á™töôr³F4Xcí¢+¼=ߨ²µüÚv±…¬eU2pzÛ’[?\¡~î·ᙦ€lÇîÓ[n&V{x6Þ=õë²Þ¶¾Æ^vlK‚^lòò´l®úŽc؛Ӹ1†ª/œ×M{ÎÏ~Îl¹ýVM½;=íú×òE´4[ÌzFÎ,îãÆžw{Ž1x*l3»·T~qŸß…çÞ‹õÇóUŽ+׫}“‹»ã'7í›\­eÇ{æùuøl¹*´Ó§Å‡` *v²_ ÙJçÕ–ß)K=£¥Oü0Îk ü¿UÏÝG`«^ñ¥œWŒà¶½Z´l‡›Ô-æóM~þ~®Uüê¦}‘mL+"ӾȶÍd²Å§åöA=ÅÛ~–‚W@À6myKãÄ,öxØÀáy~&vÃoÔMCÝ´úVþ°UÜðiõ­ì¶ ÖæœCX—Z|Ší|>ÉøßÑ©}‘­e"znÚÙö°.v©6‘[žŽ ;Åé[-˜Xf›§?™×\þßÉYí'aÝ0¿Ô´ÒVËN¿êPvÑìàÌ:­´• hë)j>‚ÆOÓ|>Èö÷ÍƾǶE¥Ê6›×4X>mDK[>$KCj~…VæH› 0M-=ó8öòM¬9O+nåcbôl>kÞ—2ÈM+neè«Tú³ûn$œCØ,3í‹ìtŒÌC³7›Çz÷IýTq ìãkcêH[9íƒmiºËƺõì>€m?»n0»èæö9¯¶F?VÝÊ†ÔøúœÃkcy?±þ=Ÿ²Ì…Wå>¿œûp,47ŸYƒ·ÔK½ŒÁA¡aúÈ´‚ŽmV'ÂÅ|^ݱH@#ÇÂ3“ŽïÆ´âVÖò¼Ýc©}N,6Ø w\t+nuG Nðy@íÝI¢™ö]öïQïgúžQÞ˜ÎΉØ9Åé=ýÀ«?¹|"ä¿ãhØ5nTÁ—K(6gïÓ\%2khñyœÊGù§“‹À7>o}#>¬vŠøø->‰YðâkØ‹ÄǬ–I|•ñ"¾FKˆ%ƒ’ø¿¼">ª•A|@sqŒ!î)ß i/ó6“öü«ö¦=KŒŒ½fÖÆ6 ½+Ïd¬Ù‹ö®%âíYÚÖ˜¥ö Ã5@{…©²E{¬½%Ø«tuö¬j:ìU&ìE‘öO ÀrÇrwc<4`oÚ«·€Ì¬,c à{•‰D|Ó^úÜ«úßÙK‹%û™[ôX²>R¸Ùc˜Lmâ›öÞ>ñ=˜‹Ü²¾iOïïÂÍw¾K¶ߥjÇ$¾K!a$¾K…è‚øì™‹°ßeˆŠ~ƒøL|*/â³2a8ˆÏ¦<¸è ¾k°è!‰Ï¦<˜_ù®¹Hê`¾(ök"ßµ˜Û—Ìw)å{0ßµ‘¼7ÏJaÖ ä+ÊhJæ+¥ª%˜¯XÑ=´àüoz*É|ÖÏX5UÞ%ó•ÊÜ™d¾ò¼yÁÔ`¾òL8È…}¶€ùºC_é(ôÌgŽ–ö‚¾çMÊ úlå« €>û}újÁ¬–ÐW/&- ô™Â†ôÙ‘pý}¶BG: 諪ÅLè«*&ÐçJÙ úª—~M諃…‡}u2ˆÐguÎð”úêJª è³ß^Ÿ€>Û ?8@Ÿý„ð&ôÕÍçÌg®,úZ.¨9ô™’7À‰1„¦Á„>+iŠ›è3' @Ðgs6,@ú̃; ¯MA Ï~›8 ¯-¤ñ&óÙ& R0_SîC2_Û·Ϙ¯YöFlÌ×µk2_çÈçeN_ÈgK7ø©ùúÅeW"Ÿfê¯Û(ä³R¨ÅB7Œß¯«ô‘¯?ïûŽž ù̈ƒ5 ŸÕwÃÄ È×K2’ù¬CXL·Näë7‹¤“ùúbª81Ÿ óÅ|}1½:™Ï^KÜ&†ð|ñ9"óõMkl0Ÿõ‹©7˜Ï–;p~`¾a$è-˜ïù,ýÀN1„¡qD¾Á—‰Ï¼D˜ìùž7:^D¾ç;…‘ÏüFÜ&Fð¼RH.Ž|¶&çÎ|nwóõÅê„>«6;€}¶¦Ö±0˜¥™Ðg‹fñ3$ôY•:ШÏ&éõE}Ã?¿&ô=/Þ\@ŸÍÈñ9ôÍ*Èv蛵LÉ|V cóÍ¢GÌgïÙòb¾§suço5õB5 óÙ^ñ–#óýlÔVb:c0ßÓÂJs`¾õàלù¦ir¯Ã\\ æón©}ÏNSàÐgÅrû úÌ U‚ ¾õÌ,Et‚ÝœL aYQ>g “í’ ê[«0æÔ·ž™ÏЩo)e=©Ïú'õ-«ðwBß³ +»ú¬ênCKPŸY¼ð ê{> Ì#ê[V‡÷Æ ÇVã ŠÔgÛ,V0ÓóôqA}ËkŒa/£>sbãòú֦ިgIMKû&}÷¾…J@I}ŸŽ¤>Í8H}6cÇ^ ¾§Â/±o2„FØ7iÕö=-,† ì›¶‚UOì RzÕ°|OF9öù°±UU}.ؾ Ï÷¡XˆŒN…q‡ã{ÐuæóMæÉ|± /<ëV"] Ïú »Ðç-ö¶è)ôyìu„g}pM Ô7ÍԉߨÏ&m˜°“úÓP‘ú®çá¼^Jßõ<ŠXÝõY•l<ä ¾k±bPŸMÉcA}.:ƒ\³qöÙ+€LÐt©v0¹ÏhmpŸiÝ8ÝÀ>{·´÷]e¦´(œD‘ûla¯¾¸ïºnI„Á})@Ÿ-“Bs軺Jè»,üè”úæýLÞÁA}®ðãÁ ê›¶J»Â³n'8°„gÝZ°M Ïú¸õE äÀ†ï=±Ì ì›ö6ÇO9°Ï[ð¤öÝM½€\÷–ÌrÒœ€}µ1K±Ï_IàªÀ¾r3L„ØgÂÿÄ6}6ËûÊó4âÁ}6³"ûJAœ±Ï–;ÀŽ}^{ÝöY}vŠ1ãÊo1‹á™/†›ÜgK#%,eû®qÅŸALö‹Ãr ïêU`¸ý·ÍÔ„¾«1€Ðw5¾5}ö›k/¡ïRIjRŸ¯‡½”>û‰Q³ ê3£¿¨¯5¡¨¯UÅ#õ5Õù!õÙÈuP_K,ÔWûÁxN}µò]Iê«—¦ÑÀ¾²YžØWì;A.¨É¾¼ =÷™%j%¸Ï© €ûl½«â c ¶&†¹¬sß3SÀLѱÏÜâ ± ¾¢8-Rߥ¼ó¤>›£à:€ú®ÍÚF¤>[:Ä&Mö¼bè»}0 ï²•–õ]Sj&¨ïšœpõù&æ]ö·Øgv"Š}WgÅtbŸ=9ý…}mÓûAìëŠç$öYÆìkµ‰}U_ØgîñrJ}nôÁåsìËå8bŸ½Â˜.˜ÉIyÁLvqÆà>{ )ƒûŠÝÐbpŸµÜ§ÚçOp_Œ·'÷•A[¹¯xPÖ¯‰}6Åoα¯Hb öÙ›‘¨C(¦w`Ÿ`&ká^ÁLEQ‹ä¾Ëãƒû®ç,1ppßõ|'úKí³g¸ïÚüNû®5EcÁ}Á°úÿfm8BŸ­èPü‹Ø‚–?}}Ò²Eèë‹`>[°ƒ æ³ç‹|Ì׌ãÜ}íâ"©ìÚ7Þ”Qì½ö½)Š«ŠPÞd?å­#û‘ôø$&éñw‘¤ÇÂ\"½BaM¤Wè3JÒc„òIzëeê¼+_@½*!êUQ¯2oªPO¦Îͯ²P¡°iêœXÛHÚë7dêÔçS¦Î-|¢FÆt^iꔦÎÂé iïÁ|ÛI{ÏÛs¾io1M´·ê'í™ê®ímÆ© ø&@| Ño‰1Ø - ¥g†‚)oɬÀ·$àÛEMŸY}Asáì¼ÈŒ€­/ž¸g“å[çUª$ǰuúÄp•¯pMG*_åwN*ßC(ýĽeOËHÜó¹õ:¨|¾©|ƒo0©|S7Š*ßdIY©|€õëI‘OŽ$òY¥_´@äÛBjª|7§fTùÊõvvÕ® ™Ï_ÓÀ;Ê|)&Bæ«ârßè?Þ¼W5ä½ü’÷êøPù̃ y¯1€W¼gkä DòÞÅAïõ%eÐy©ó[$Þ3›æ›÷Fý0wÚ}»ßÀgkÌ/w§ÝÉI¼‹Lfð=3Íò¾Ø€Ï2X`/0ßônú¶¬êD¾ýaî¼ä’§ÎWX™2_QXÊ|En;Ê|>³¥Û3”Ê2]1ÛÖÈ|Åÿǯâ½g¶*%2_éTî¼W†\Óà=kyË|eJ3‹½À{6ä÷¦XS¼Wù“÷–4PòÞÖJyo‘5Ä{·tiŸ}°à+7‹øüÍö¾Ú¦ Ì:º¼“ÁKÆ#÷ øê¨íÕçÁš!hÏâ©ÆÅê^RcU¾va~BÞ« ü+qÏÞ—õ¥ñY¦Êu{69Á”¸W7} ĽV†P.P©UúA{­jÊÚ3¾àNA{U±¤=c°·ÆWå’íùYý*سxI|õ9tyI|U+¥‚½ÂêႽÁ[KØ3D„I °g=SN س!”—¯³Ö+þ Ò«u`zÏç“°ZxþãøŒ $ç]!úKZêÕ± mAz&oSg5hC·8ùɪD=oA?Jöì’!õµ=—„v÷Úà ¾ô©öŒèÄwëyìÙGŠšaÀžÍip `½\V ß¼$÷!†oqú”1|{¶óõÅGca¯™«†0Yba|ƒK®ãëéE߀3Žo±Ìµâøö õúÔD¨÷<ë|`zCiCˆz¶3”ˆ#ˆš7ƒøìúFCž}Ú0—Ž ¾Â Ãˆáë4C3†o©ƒÀ¼¶»É>ûöƒ8ƒòƪ”7S5e _á—†”7¶¢AyskQ”gÛô—²7–œ£ÂwË݉¾½¤($Í{Éñ´Š~Áyö5ÁmçM[ͤyó CÖ ÀyÏ‘8Ï>t$?Æðé5Ã>Kžö â³IÇ+ˆÏ*§¿@Ͼm× ô̈• ñmºzë¹|…îÍ+ì3\Æð)¿Œá{f$÷ËÎiž v˜dñ‚o]oyÒº_óìŒñ¶Š>KJö²sZâÛÎi'I¨c"':Ä< :Ü/?羪x+HÏâßð‰`_/d6Ž€– ‚ޮ̅EгÈÉöRöÌç„w“£žo¾”½íïÆ_“ô¶œ?$= ÙD Hσd@ƒÁIO“¤¾@½[Ï„ìœÏÉÌêÍBã#ø¦fÐ =‹¥w3PÉúDo•¤ÔÛI@½=fú;õ|ÙÊ"øJÚ!ÎŒÌÀ´ %‹­/]Ï.äADðMÍÖÁ×Äv1„-g~О…‹F"„﹚ÔÍÂWY«¾ÊhgÅðµ†'˜¸gî œ.cø.¼?Â7¹²¦¾‹æ%Òž=ÿpL2†oHÐíeqè ½=˜#1|‹‹íÃWxOÃ×¥1)†oH.D ßÅù>Cø*ßr„= èÁsØóÀ&t¼d°çEÞAYA{äIO¥ Á_R/]ï.•Gðí~+0€i["X-˜ÏîþD?Á|¶ î%˜oç"˜Ï’¼íóY„æKÖógñ â‹—ô·@>‹:¾O;g“À äÛ³ˆÞ`çÜÙKÓîœ1ùì…µ^ºžåÈë/]o[R“—®÷ÜN ÆP†|—ALûZ · b²›‡ç„~ΛòeØ9M‘yAß®*2휛ù ÒÎ9¥õ!Šïj:Ø97S5ÊÎù\Ðù‚¾=h,’Ÿs1*ÐgçãçH#æù ž9\_>ïýûyþðÂÊhøU[LËáo¦ÿós£Ü+7úÙn>™Ø·ÓRƒ¿ycŸ‡øûÑboÚàÛb¸s窆£+¶eWÙrtµ¢ÜRvņ³+´]©%»ªöš{~lyÙptŶì*[²«Mv2û^ø6/Ôó^`ªjŸïò·ÄO{+ËXü³š‡ènÊHõmƒóŸöÅ®EÛ®[ý>ÿ¼>þisò¡ÄBߟË©òLbõ þò³ÇÒRè®sö3Jس#¶œ=åVìêÜJ}Y(Gõ…–W_ÚJ}[©/ 7}¦–G_hyõ¥­Ô×±•~¼ëè‹-g_¹û:·ú³ÏO·5Åa·Ã—³ß9Ìæ™ÃŒ¹ÄôÄÌ #çØxg0û­¾e0û­í>3˜}Ûî'Ìþøåø³—Ð÷wá/¿ý>;7úoÕß½öYîˆÝÿj·¥î¸%ôWKof÷äyý£>¿Ú¿ýÏÿfË‚Ðüí}~Æ&òŒþ·ÿMÿû·4_ÏDàþÛ/ú×ÿôof¸x¦õû?žíl!èû¿ÿÍ‚|Êm9ÌÌÉhÄþãßþ«EV?|®Kû—S°™t:ŸïÞ´„³)Øž R°Ù¿þCÿb~´~ü ÉÌöB¢4û׳÷Ú3‹ªõøß˜Í6:2°ÍŸtüýë[6kÌ~ín]CZß3°=mÿ]ÿú÷Ÿ´)[ùý lÃV‰Ÿ MkÅÞ¢<³×nk¾°Ÿ”»D‹¯¡{•?”IÖs|½£Å¿)fãêÝ^'}›¶®hqŽaåCÄÖ2ÑEaßÞ(ÅìLÏÔÝZ„ùr®h©Ñbñ²¶WEŽY•ž·¢µ@«ºmµD‹/}šË½^vôÊxÁ+®‚·Ä¬ú*žª¹ÛHÌéÍêc?…Ýèª0ò=µÖ+—W“wƒ¤X´³ÐƒeG~û±¤tMOåÕŸg.ÖclÍÝohg,Ņ̃eamÅ܊׈Bñ´üv~ )©DeUoñ̃á[ÐÙRªË%Ý×.|˜æî6ÌŽð( ‡÷GgÐF_ÂWÖm%,à«L¯@Ò-‘x¬ÐB‰n‚1ÝWj£4‹´ƒ•Uc¸w !°¾àÛ0'#„kTcíΡQÈ£x.ñ¾•!ÅÔòV0,?çjƒx6ƒšë3û¡yÎòØixáÓg'šÛë3ˆ9âZ°ÎŒ¿#žC1À¿.7Ðu›|áP6ˆh@ +eã-Œ8sñص.•¼ð îO‹ .T¯µããD‹æuÑ Yïm6Î{©Ž€ct·å$¨ŸÐmeL%ÑüîNDo°øÁa ÔàmÚ±›us1ó½ ¢Æ6 ÉÇí|M´C’îaëMÝV= Ò=#xîk÷¤ì±MóÔBÝâÒb]©‡g±[üÄ¿áåݺ­r L¬štsEÆ‚€'ó³Q6:LL°ß½ékHc+Ü6ÊNËn¿=;I ÓL<¸[l¢p6C{³tXCW(JóW¨ßJ ^R­gtÕp­ë–Œ•¹¬¿n^L¼àù»¥AôŒ Á¸f`Å’¦rmÅVx°z·6®rzxI·ÈÊ`Œ_®Ôù¯©›#óâB—O3-œ†Fw}÷¨Bë4ö¥{•‹®/u‹ÜaÚ!×¼cœŽé-N I6ˆã„ÉÅa;ñ¹&B[6þ¸ÆV0i¯8”ßËAxÛ‘çö‘¶»I£~Âö¶ï¯÷ýzѪnËš±Ö´"ð®[¶­XaµzIÍO†Ù!-–¶c”qilza¯psŠcßž†£ÛW"^áöÑ|^á㺘ÏWqmæ}Qþ³åögÀò¾„¸gµžÑxK¼kíýþül‡9MãªÛ›ºø“sÁEæ«Õ5np,Ím¯\5L™nG‚±a‹â¡XŤç%î-qLMv¨† QžI¨? B­M?7äiá앱mœ…jÏ6{ÇõЇÔÖSw¤ýš.gc·}§‹«Ònßéjƒ( $ºÃ?ÌQ‹cyå*ß)íií~I§\í_cÅN®TO’fã¬ñgõØ´ašÂ»4¿Ö¶AÜ—zù—Î¥W›ëI‡ï­èfúoÉo/º™.ÿ„… º±¼d~A! T«˜ÔìàxUóVv£-¾Ø5¯%ªSø]ð…Z"5ǰɅ;&ª¥—™wÊOÐ &­ý´Ø¦»Ú·YÑϸ⠾'÷zHw¸‰µÆŸîÊÁVKH´~¾~ ª}¡ëˆg-Î÷öÊìq!¼×u1ü×DZŠIþ¿½Y-³­s©‰R~±¬dÒ\q_ü;Z­dÒ²QÞ˜ÞW+™´íX†0±×ð,þãùxÇ›¶Úú²+ºP¢VO³2JCÔmµt±qv¨GÕ¾ÐÕ/(2Uó">÷~˜ãþ‚ê¡^v¨«fmáäz†q¸6¯[5ìJǃc‰a¦-,1§P5—Ò²q>‹+:Ê7Lrq aºjãZØú²C-„)çò3DüÙÌlo¬m°/ ¦;@ÐòÁö ½!9ez‚×"ãAý²%Až¼‘ÌëA¤áI içàÀ:}ràF€NràÆ»79pC›Ha Ÿ–h4äô“ §ú ‹Mvª n4’7ü×bACWÿĉ½ÅI,ètûbA×E^0è ‡œ0hxë3#Á ëêŽ~„ÁÅJ’‚AkqJ {?‚Aƒ`Bƒ¶M€a0j",èäì¼H\þì~,h-þr .Ž MA’ð& ^L½&´b‚ÁpdA©ìbA•Ð ^ô‰/J¾bAç ^Lý-”M0¨b<‚Á‹óBÁà…,)bAz˜É‚Ò³ /fà h€BÁB…Z(( “PPæ ¡ ²`  s²  Ó= •ÖK(XÄpDÁª"™DÁ ËDÁg§ð m-DÁª²”DA£²ýu¢`Ef7‘`eþ’ ²"Šë` 7’`EÀ·@°²d9PyÈȶ¦€Zqä@[e€Z¿¨<Üb&r ùÐ3@pÓÿBÜq€ƒíP¨Åt¡¸âÀÎôäÀ­¬!ä@;”xÚrFÜr ÉËÈ÷´Õ¸ä@ë9 ŠhÛÄê9p+û9Ð*{Ð hèOkc€ ïߢƒàî#søK|wí”óM8 š!†> WXCœM ¥¬VV‚¾æQäü Ü^ÝïÁ=3{Y€  j2ÿ³ƒ ½ºéš|^ï_ÚòHÚqàÚÝœLxähß%’u ´~@“À@ÛA¶À@$¢‚ÃuPàž,áF Ü2÷dpb o{m›°Ú€­ãøqݱóâ@#©À#r ×½‹ƒƒ÷Bâ`b y¶Â© ìæšwÆSˆèÝ„è-ñ¤ýtbõŒh§ü¢@CФS 7Ä«›|%ÆêUœL@ /2Õ“ýdü@€@SxoÝúûMÌq}5(Ø-Ðýá±E `÷â¬_I€}ïA¼ Œ§ÜÇèk/±Dì7+ý\® ® @R  °[„ñ Ÿmƒôe¨ÝvËOØ ŒÛ;úªbÐ Ð;Æ¡ãvGKP ¯N³€Ÿ–ïR`7WP,(°ËE ômügG ô[åSQ {œ?Œý@WlØÍ²³ƒ}¯ôÆ¢“ÀÀXõ XÚítƒ±0ÐÓ2ú±ü{H ìî‹ 6‹×kìõ•×8€.(ЯDCúÒ2ZœýÑ_ŽA¾j'غ@ìn_óA}˜õ„@_œ\vKo·Ø-5Xò]XÇC¾B /EÎ8T@ /y&»¥³*±äbO€ÿõ—Ò´èzÚ‰7f‰7B¡oÝ ïÈb”È”×I7roTi d¡šÄÀ‘‡‰w¤½J ¼ãö%ÞЦ­_Û&!ðFù#Aà ÙIÌÏ}¨Ü)Õ@DÞjàíséC òI ü„À;²žj Ö5:ä@DÓ¾ô@ÂÁ€`Ƀñ&b=á`@ÄÁ ¸ã¶ xÇÛí`ÀºÔÁ€ˆr>òÖÁ€7À,pûÇà@ÀÈéz ¨ú@@ö’ˆ|â¡8pOô¸¯¿þÓÄ~  9ðŸo¼þóm‚íÀz´Ä¾Mˆxà?o ’ÿéôÄÇ6à¿£ü§'Gü§çO¸T`˜‡"fÇDÀ£ È[%´ÇÜÔ/Qè;8½%öæU&ê!òG$ÌnH€y(àÑÔƒ#\J;K<öæù½óŠó± ú6A]`ÀÜ‹˜óa"{óñ"æ$-€À)ð8(0Õu_¾Ì1³WBàÑÌ{GÌC<¶æcLÌkLÄ@½Ã…üZˆýƒÝ€ýãÝzDKô ôèƒw¾ÄAú¾‰}¯880Ð$ ô– /` ·ô` ·„Œ ôIOhˆÀ@ßæëÀ@kÚú>/ ôM¾ ô†>ß ¡è-!âiDZt>` ·D7À@Ÿ ö}ê÷Á¥¨u’ ·÷íß' zCœHpÝ!¾—Ô#b ïòuP ÏKÖ@Þ4h #@‹•BEÖ2!ÞxC›úÙ8Å5)z?§uÀ(аcPàbR}Qàb•GQ ~¢À£Å(pÝ/\Rðˆ€œå‹cWE€Zm.* Ð~2ë@€¾M´€m›àOàº'™¸PgGh +6zKœNàbQD ÿ€OÐ[B`$®Ý€.WÄ6@@ß& 0p1šðØèŠZn¼»±N%ôm¢h-A‰4 ßPþ iÛ}ž¥î…}X±?°¯ÅÓz`rY%öaMàà>¤ >¸«Ý÷EIºÉËö¡þÝ ûûf|:îƒoæ?î•àëà~Ø&Á¯}¨÷ŒÍÁ}3ø,±)ˆìÃÊçÁ}8áƒû T%÷±áeõŽüF¬ïà‡ÌÅ?3yúWú0‚¢¦ÕaEMàÓ.Ï4‚ÆúÊaE°õa… pAuA‹ÈÓjYZò^5>éµ\a®¾ÉÊBHé½°ž>ÐkÇ»?} OK Ì£ô‚¨ž>Ы¡ieÌuÚ@ „¾”þ ³oIú+ýSú³*oƒ”þ “Jú+‹³’þ ³xIú+¬H$鯰䇤¿Â/£¤?ËhàIé¯27½¤¿Ê¤mÒþ*ëËPü³djÑ@õ¯24Nê_Åcšò³t¥úG•Dê_Ášä¡þu¬¬Ÿê_LÖRýcúÿTÿXlíTÿb/©…6ÔTÿð¤úG£–Ô?3ž¢Qý+Œ˜Lõ®ÊTÿ<šò¥PÉ,{yÊ!‚¤üG÷hê,Ž °"–ô?Óô¨ÿÕùý/ÓSÿc‘¡ÔÿXÅGú_cžM €ùR¤Ï ¯p €Œ´M‚¥ÀÎ ä)vVr§Øñºx €”)²ÄÕ)FÔ§ÀÞT5`§3P`W…_ €]Åé(*íÀ¡âT‹ŠMC4IðÅ~®–½¬ ¼Ìì?(Y¾Ø/…9)€ƒµÝ¥ÎŒC‡8«*åPd†v‰€³1Ú–" …€!qDÀ©èj‰€ª5CPéÃS¤Kò‘ p²½TÀŰx©€‹Z¥.ªÇRÍÉRÝT²¥ ˆTª€–Þ4Z¨šl-‡ ?É€‹!ø)Ò¨(Ђ7?d@fJ9eÀòâ?Û¦¼Ü ® }üçQã{é‘Kp3…¬tÀ çNꀖy%¼ŸÔ7£»%šèÛPÜÌí"!Ðb·C £¸[@€6eØ/´3Œ7Fj¬î -pK† Ü›«²$@gJðµÀOSj7>¢@Sœî0eR Ü0“íØ¡«I ÜXÿJ-Aÿ©šñ*¸Zà¢æ©Þ‘’"¥À{Ò•I)Ðfª§!44²Óê£j§!Ô[“€@+*z½¤@Ëàêhó´ fr %Ì -¥@dŽZ'ë%ÚÔߎРÕ0Òz‘l ‚&íBÕÚù„}– èçs:B»êk‹U\H$h-ëp„ž Þ4§øL[`ʤXàð ޜڈ7\ôÒíóòA‰x O}Cç£X“Z ˉ¤X)4K ¬ø„ý…Än/*ìãí …öyxBQéð„Â6“žÐñÍ ;îá EºÃºâ#Sè†4M¡(y`áÓà ]„L&lߘ{0!©KL¸‚`_b ¿þ…ž•ãe uèzQ¡QMŠThÞ»ò²„Ÿ„Ö*4ñ %*´™³_LQ¡}M\FnÔxO(,XªO($ $V@ °"!LBaÅòiRa…e5©°!ÑR¡ÕäySaChGba/ŽP›Ÿí—#Ô½V¾°p ö$±p¶&|,“ …GQá JB!³$Zž\GQ!ªH%..F 73¹ 'Ë, ëô ‚ñÄ„K&R2áBæV!¡J¾ =áÕI„›«÷"B³:¿Í 7«Ë‰UýšD()Dh±e1ó'Ú˸"´rð•Ю9쟄f«ˆkC$´wë[ ô I Hhql1$Z.žðè 7Â)„„–„H$ܬÃ$ôð²ÞªH$´˜›û%ZÇØ HèU»¿"´˜4ˆA„Y#ŽDh¡cÐì@„–2x™Dx——èÀ‚È8™îQÆnL•hÉ™çËjÅ 1ÚBéKgl W§ „Cl …[î·-t".&Qð4Šoä¬LÜ{(ˆò½J÷V½*è‘v¬[îÔZÙð«¶8ó¶}l”{åF?Ûíϧ{ûvZj8³¡}âïGKfCkV2½窆£+¶eWÙ’]u»Åû>†Í†£+¶eWÙrteÉ9®Øpv…¶£+µü«Ó½YÍeøgéÞ®õÛyÙ"ß[=s¸}&n{þy¯Ÿå{»³_lpþÓ2q-¥1úÉ#±à‡Pî­Ÿ<—c†w!s¡Ÿ#“::3¹±§ÜŠ]½²Â±¯Ì䯾ŽLnêK[©¯3+ûÊLnìëÈ䦾´•ú:³Âñw™ÜÐ×™ÉM?Zmžþ™|oÕLûî#úI¾·ñ{ùÞ¾å÷ûi¾·ßØê[¾·ßÚî3ßÛϳ ¾ó½ýñÛñgo¡ï/Ã_~û…vnô'^«¿üõ´iö˾,ÛäÏÒ¦-¥M[J›öJjvüó÷§µòÿ"qÚ?~ÒñŽÍý“ÄiSý<ÿŠÄië™ËsPOã·ÄiOÛ׿þý'mJœV?qZµiˆ~¶'ÞÄOk0:Þ?}6ßþÊØøzÇb}dI³ÛØ,Óû}6h§Y=¢Å§ÍRG܈l¿b¯v…ßgC%jV¥,2B>l–À¡0=¶‰òA¾ ZãX–döŒRo^lÄ¢ª#G³R`îÖÜÈÀЬŒC¸5¯€VÜ$âV¡;J]³Æì¨Y±Øàí8A«?vMˆùÍ2&ÐŽòT^1ÇÃæ5béÕe™VfšîýKجøCƒ‘±Ç6;M÷-NðfÐuØ>Ú3ÉGÌ5¢Z-Œ¹Æ´«ÕʘëŽ[¥¤0Ò`I¨YŠˆ¹ŽÜÖÏ/«lLšÝêÀ*ÃÕšU®pCÄsQW¬²T¶hVáªÁ cߌºFÌGkîÕR°ÊVa]y¦›0^T”hV¾x#ËYŒÓŠmD(_±W‡ñ¢b­½µã…ÅGËÄ*[,ÚXË‚ñ‚9‡žŽ±Êf f> «ˆã;Á¥Ý¬^©¯f7$<b/:BÆZ¯0^tX®ž/:Ì€­7/²¥‡ñb6 /d܆rÞâ«VÏÀa¼¿Zß0^Lä¤kýn!×M,L?3v8/&–ΛՖˆ%eD)?K8/&–Äž8/Ê3·ÑyRmt8/LDŽ–çÅŽ%ï6æ%üÜ(/öocÃx1;Ï÷†ñâFÍ¥6//n,7+BáÆ ª‰mV/h³Âxñ€Éˆ~Ú.C¶Ù±ÐV.¶ ,´±V}³r¾ÐV ž·¹°ÐfÿþäÌÆ‹µ,Û¼™‚ åÖÚŠÊõ.ECÁ:[…½­Šu¶Š¢Íªb8£Å©Xún„ÿù’_[ù·Ì9ÍfK ËÀ;všÈ¿e«±ÍBþ-Æ¿7Ìj¬S»:ÐL–r@W¬Ï6{ù2[G¤]ó’6ÈqÇݶŸ¶¯²YäøŒäßXÂmî±ANhëÍó ³ß{ÀWn\N{vW‚ýê™Áóoíg“ñh‰çÓn‡¯²mÂh¶ð]˜`Èå÷¹ÄÚ¦¯è5 ÿõ\V%%¶©HÁµPÏ¶Ý ëlæ¤ÍV}m 2®ÙŠ‚¯³]ÈfÐŒûRSùÚM³õ[1¯œÿ½±ÊV/žÍU6+ÚjÏu·ÏôÙ¢b}»[9›Z´T¬²-ìž)*%ý[Ú­F”'àbi³n©…<×@¯n«C¾ÊÖ‘ ¿[(_ekXÕíV#Ê3pUÄftË}Äe¶{ÝÌÀ`·z±Ê… ÛW:VÙÂÊÚí#‹l¨õÜí#]‘ÓÌ‚néÏ}‘mBDè¥Gþ­«°ßU6.Àw«å«lÕÒ»ÕˆòU6–¿éV$jy?H^Эf“¯²íˆ-èõŠ \¬¯Ô­ …gàºñqíööE¶J'½VdàÚ0bvûF{.¾:º‰ò \f#ô†‹l6³‰+ì(tGÇq7­F”/²m$¡ìV#Ê2pÙ¥öŸC¯72pípfw+e ¸Š©\¾“•ˆºkÜŸyôçýåõ»zìå‡ ñ/b·´%à²ûÏ‘} M))ô7t«e¸Ž~¢–â°%E¤yž,ŠwÅ*DY®Ò{ÌÛºUˆšvð61H«e ¸JÁ[· Qž€k¡äK·’‘€ ê^·´'à2G’½·Xd[p¡uû>'ª°vû@W»™´âw+å‹l+vYȾeªFôé«ü™™q.w¬°M¤Ðìã ÛÄäª[¨È¾U1$«åÙ·.¸±»¤ðì[æmöƒÛÇÙ³oAJéömöä[ÌíÓíÛ\üP0cw«å2‰9äc¯ð´ùÓ?(«å2‰U‰SŽjêÏ}¹ãÝ×­VÔ,‘e,ÞHÓëtùrµ¥[©(“I K…t+e2I)ññèVâÆ‘â’Û×ùêñ˜»DÓíëì* -|ݾÎÕsàöܭXTõ•àG·bQ&“ص¸âX·§ùóg"žs+5ì’.¸e»‹²÷wYð•v+eïoSlýàËku [1vå³[©¨í ôün¥¢ìý] ª/ÆzÆøòrqgì mïo{;ŒhÁŠŠ•«ñWñŸMöFÁö‰‚á¡:X0¦“‘îdÁ¯ŒIn‚ j ¯Ö‚ÂG É!ApÄ—êA”;@æ»ùõnˆ-A„}3O‰Ð¯ÅÔDëÔ±M¡ÇWìè'ˆÐÃñ«úªsÜ+¡íõ•8‘&΃î5Žß*xðl tg1z ôsñï&yÐWœA§aíP54ð?Fí@B(=‘ÐæÛ'ÚŒ7üBDB›P‚°.Æew|ÓH…61Ù©ÐZâûI*´©* =Xú¥nÖ£úLõ…>› $ZK{A¡‡É†6 (Üq ¡Mb ×U "´ûzIƒ›ùÑE„þ™‰m@„–f3& BÛ$–½I„ óÚéÆÜŒDèÎq:”mnö"BÛ&F%m°2µÁ¶¨R ßÚA„»¾•ÁŠø×T+ÿT骕2XQ¿$•A͇¥ VxâSl )ƒ ߦTªpÊ ’ø§2ØÑŽÊ åD<”AhŽRÉ´© â…{(ƒ“Ú%•A¼d{§VH l˜‰%VmC ¬ˆêM ¬:°…„ á „íÆc+ ìåGÀ(y°ÁêšQ`!በOE÷„¬œx!\:!ðBq ½BŠ#^T4ÄWÁDCx!¾û°ˆF~ïÃ!JÏc:D¿N|˜H¬áz9pÐdz Ì–D@[h Pë`Ò;(dý•$À†£°‘ÌÅ€ Ù,’cFNlðþ$öð¢'ÿuzÅÁÌÉ=ê,$þu¼ÿ:Åe៽¢…ø×‘S/ñ¯sÆ&üë((“ø×Q9ñ¯o¬>ÿ† MøÇåáß kLøg‹hþ ºì„(v›¾Ð š¾Ð §YúB ré LIcГJúýÇÛ:Õ6ÂßÀ³(ö”µÅ~ƒÒšØ/¢ÀNö¼4b?‹Ë‹ž'V½Ç›ýl­üëD¿y“(‰~K„Fô[H:“è·ë0…’¶Ä~‹¦_±“ýÖ¤ÌGö³ Î;²ß.ŸR ½€âX€¿eÂßFaÂßæ’•àÏÊ}Èþnjo‚¿›z&áï¦5WÆP{ Æ&4†^”÷e ½-C-IAP%¡W'gÒz!—pCYa+¡¢O:C 2è¦3´¢¢[:CŸ½ ÒZ„p†V:oå ­ÈšÆÐJ•[ÆP+¯ø6†Jª”1´uR¡­ã³!c¨MB Þš6Ä:ùÏZâŒe í¨S,þ³ù[*ùOñÍä?óìö—h3‹öí1× ÿ™Ùv¿øÏ ¥ÎÐQ)!ÿÙNó%Zˆ€4àŸŸx øg“èôçS¡ DПçˆ~Až !‘¾ÐF¢Ÿ[ƒÈ€~v9ÚK´b®1A–-”U\„~^ðõd?K„Ð^ìw[€ZHz`?›òH‘ý,Ž5fÞd¿›%dÒjùà e¼®ØÏv õìgvXjƒˆ¾¾±^’¾Ð >þô…^X¢•1Ô¶×ýn†¤¤1ôj‚h õŠ´/ö»™Ö[ÎÐKÒ†œ¡“p†šsyŸìçÖelÐXš5od õ§2\Ÿ0†>;}%÷¹—¸ŸÜç.à`P¸B-3M\)ºBmº t…z†8ºBY&]®P‹êï'ö¹ŽN¸Bµî@WèuÊ‹r…V‚ \¡åRÇ0†^7,æ2†–BŒ1Ô-žp4†2tCojV4†^Èwþö…ÆNð…^·§0†^Œ×NcèÆ}¢/Ôü’ëå -ŸOúB ³¤/ôB±¹ô…L¿è µn§ èW+Vä ­HØ“ÆPúöd 5Ûo€4¡v:û”ýàõ¤¾çX‹vRCo&Œ¡h2†ºï7T>C壦/Ô ch)ó-ºÛµÔç·dch±ßK˜Ga 5Kyüœi 5{³ßÏ¿Bí@@$Ö>õŸå E‰÷Wœ`˜áÒ:0K{(Æ{ØC‘Ä𰇂{Óz_Ÿq‚¦-G í¡6ÿ‹½h½©lÈzOöL{èÀ·d@F³ˆå81 ÃG’7CÉ€… -°4Â%µÀ´%ÚêÈ×ö dPebঠI 4±&ÈJ8>£ûõuB`‡Ñ&!°G"®dÀŽ…£„ÀAŸ’ p0ÆL(!ÎFÃ)9pRZ.š*‚k€‚‹B$¸ Ž$ˆÈA«ã;oŠ™A¢:9ÐæÇ!ˆ’m&¸_¾Ð[Fp -o’mÊ:_‚6e“}NQ¤áª<89Ð&¤óA_² äzÐV´-ÿT{úÌ-`q3u,’à=òF´¥® ¢ OÄ^,xëî‘-ÄÊ`c*®Aò ú’ÞËê‰S¾ˆ‚–œA†@A›ð!¤,¨ü@bA›kï—-Ôra Útùz± ¥:‹~È‚·2¶ÅÀ>nQ&9% æÔ(À‚>]/[¨g³ùJôÜW!\}§°¶}Zò:PЃ̮WŒ %T'QN¢à¸ÊÕ#ûTt¼Š«qM(8‘Á>Q±6‰‚U‰‚ÏÌ‹*½P0ãôˆ‚ë¦6x "ð]¡©b*OœPPwç±$8?PðéñUŠda’à¸&ê+FpÓ>©Áäa#¸dùdŒ Ó§fŒà$¨(Fp+‘1‚T½É‚>}m1H𾄇 ÁRê'.ê ÀÁç o:%ˆ0PE ®SE ZŠIÈ|Š&%¸ã%xGêKÑ Í냵-á¤8 ÚÌ0”- Zf$XªÌ¤€Á"ÓaÐ’kÅ%hšÙW²à(´'ˆmÚ7XA‚µÈ$h—‚¢‘ãK,Xè°g”`ÇQ‚å3J°\$;F ÖòãÍ‚öÙ ¤þ 3JЛS6‡BÄ"£/ÆW)J°S5%Ú ê÷ V{„ƒ›¦Fá`ÍE8Xö8h^¢@=âàÅÅÅ .õ¬˜õ ]îWœ Ý„°Z ‡Ü›äÁçM6OpØ/ØÆ@Á¯x°ÔI=@X¾aG|N ¶úV‡%\…“@Èô“g àÈAaçõN¤$–Æu!&¶Éƒ‹n BõÚ÷\IܨE“‚ý"Ú1P°Ãˆ–<Ø $V”°Ž‹º p 6B@èq‹§3tø+íëäAæ*ΔPÌ~äQ­3Â,R÷¬2KTôB¦ nq&DûØ(÷Ê~¶ÛŸÏ£öí´Ôp¤û<Äß–L36<Óùq®j8»BÛÑ•Z²«ùì’ýÄ_G'Þ=àÏÜ}Ù‡1 W G'lË~²å_;m˜£À.êäNû–ã,r§µ3Úg´Iî´Ÿ<³Frså±úɳØH¹ ûɬhìèÌŠÆžr+vun¥¾”M}YÑÔ—¶R_ÇVêKYÑÔבM}i+õul¥g_YÑØ×™M?Tmžþ™Üiö5é^\ì'¹ÓÖïåNûv¿š;í7¶ú–;í·¶ûÌöó§ì;í߈?{ó|þòÛ/±s£?ñ*ý'r§ ó XêÆŸäN››¹Óžý‡þõ»¹Óžÿÿé_ÌVÚñ¿ÿ8wÚûÿøIÇÿøYî´¢Æëÿû,jÏ™3üÚƒ™ñ#›¸>Çm!üz#Â3¡Bø5+L<-¿ÞH4Úðë ß÷x(¯(ý›Ú ¯±®5zEôõ†ùbôÑ×ë£wÔ¾ÞHM<ž ^„_oh‹£O†__?¢a1úVºÑ7ï1Ý|Z~Í÷›á×pmŒq1üÑkc” ¿ö%íaÏ* §Æ&-k_;hÑ}`¦1†¢¯ýZÉàëê.F^Cc3òzàJ=/OD^Oæfä5ûǼy wØ…‘×HKü˜‘×(¼6fƒÕ¢ «Ê˜^‹¶}&ËðZ”˜ŒŽ9áµ(˜h޹àµ(HÇ7æfàõÀe˜;ö#ú¹x !d¬‹×ÀÉçâÀlQ‡h¬Šbxc5˜-îòa¯³E­¸zkÀlaÕ7¼aÂkÁ𑱼6“÷“[^‹Ê_†=ƒîµ¨PЪGu9<,AÌqÍm(+>YËù1Åû±%ï»^AœÃ|A%Ö˯h »Þ1›^b kê±ÉbÔõó3ókGÜÂŒcoX-¬2Ìtøi‡óaq[Aþ`Ùb°ÏüÄûá®Ç-Î’Ã\7ÂPPÑ´gÐõŠŽŒö ¢Û°E=]T¼aеŸÜ½é²o!z Ëkվ举r ‰gÚâá¤},Z B®x7-µT„\Ã+2M\ÝØÆ kúºµb¯Ÿ}ƒ!a^“!× £iJ¢²ŽñuØìñhMKjÔp(Wf§+ž3¶qì™.êáPþûž¾Ä‚q:7ÎR?lö³4=k°•M›1Ñ'->ûY_¦è…„ØdÁfß βa³ox9>-a³o“g|ÃfßPÈ`Ö 6{FºO˱RˆDšµÂfßJpÖ›} ©vxì¢dgðØ7Ô^kðØÇ ¥µ,zìQi|ZîÜÂx´Àcß lÏzÃcß‘Zéá˜ÅŠ>w­Àd{´ ‡}=¶ƒ=C(fë¨vFÇàóÎ…Á¾a t¶{+š‡Y0Ø[ÀIì´a°ï5~ËÓ¾Ë ’ò›mßeww(³_0Øw( ³ìñ{æ]0Øw„ÏÞ`°÷OÂóE€»¾cAlöw}‡œ3Ÿ)L¼¹;žª¾`®·e€èÕ”)#gßµ¶•po¸iÝ‘â`Ú'9¤¢?GA¤uGxÌ´â …JÏç ‘ÖOKjtDZ¯z¾äñæHÉ7ŸÏe¼¹< s,„Zxâ¦íò7·Ùc›XëQy¬;b­·óB¬õ@é¿iæŠ\¾&ô|Pk= ©ÍÙkͨý9;b­¼ØsŽˆµvОV´ËßÛ ^²9­øiE»üŽðRžV·Ë_Ü 5ê¦}•ýÅÍ¢ˆÓ¾Êþâ¶j~±ì«ì/î…*!sU„Z›51¶iµ^ÈÁ0WG¨õZ¸Xk Ôz!¼hZᮈºC¹™V¸Ë-…(Â1­n×Bø‡Ÿ±M ýÕmy£ß‘Ö;&Ó§I6T'Ó«ÚÖh‰{éQŒ“GM³†@k› ûåòª§“[çFVF¼û,LÆ_Ý¹Í c½}}ã÷íçîAÝÈM8½6c4ô8øÆúík§VOí _½5ø”uÞ³è)Aã%l_æ¨2Å7·}™£ÊTÁ-w}56‰çÑCsßHp8­†‚¿¹ï…"ànró¨n¤8˜¦n¹EîB8è4;ZT™ºð¦³Ô†n‘»P»h]‘ôÇMšþÜ.«óá.¹ é2—}œÝ%w!3ç²sAÃÛôy–àe æŠúƒ²L éPÀ§7X|ÕÆÁãtÖòö…ÈŽåÉí¾^£›{…KîZ(Ig²Êfì‰÷\¼œ7ø¸lIø¾_›´òö…ì,±šØy–H¯!o_; !·GÓÇJÌŸËœöÆ¿ö‰1;ño}àæ&þqnŸø‡÷Áxüë„;ñª%&ÿ‘+“ÿðZ9ørHòßF¶¡ÀX¹@±'ùo£6gòß^ 9âŸÑhpñÏÞñfÄ¿ ?_òßF>ñŸ[b›à?ÏgöuðŸkÌö‰€‹¿l! KÒýë@@÷ Å^@@ki]€F°>  § Jª£Ðk~¸bBw ‚øÕ"ZK˜#^º!^%ÞíI€&9|x¡a ýf¿Nþ»„j,ô¸âOòk–&^(©x!¡là…QI€ò$^(%–xÁ¿h.jD€"j`Aðk`Á|$ 2¥°Àˆ›X¤"@“±‚ ‰€öÈDÀÒ¹ °À/,H›™X<°à%4ƒb°°ìX&Ò^”X6û%–›€G¬p·'2FB`E „À u"!°"¾Ihþ¥à0B …‚ÕÌù†À kfB ‰™A—„@ë'zÖÆn•s A ­&Äù™~"!°"d5!°bÙ*!°BfK¬Hžȼ ‰+“­¿8)°¢{R`ìX7æ¢ÀÊYŸ(^œ¤ÀŠj”IA6IA¡ ‚¹#¼x, ò  xq/àE|–XÆI´$AhAÔ4Ll… Gl,dª‹„Áåù€AD[D?% 6T¶H´¹]lCä²H²`CúÞdA-ˆ&QÉ‚ YF“-fÎÏX8ȴʼnƒLïš8ØÂ±š8Ø78ØàRJlÈwð V™D1ŒƒaÙ:x°àÁIä»Aaa­ ƒ6üP[dÇ ˆàޤA–&N´ä[d$Õ¡b6üÒã)O=°ÄÔK ”N=‹Ü‡ÈÔIí©"|òйÀ"=9 =°réCOA)(A‹ÜIƒf[} ‚,k•4Xñé|Ñ ˆQŠ VÖ^Š`Pø©Æ5ÁNPŠ f5‡"ˆ”2Ƀõþk„Ã8¸ÈzÂA,â%’›¡Ë88Øpp೘8ˆÀÖ;éš ìì‡&¨ƒK@½SŒsj‚³·Ô¥JDèõ¡ "wó¡ ^ÜFš rÁ8ˆwäƒûnî•8ˆSnL¹:ž¢ Ö’QpÚ$ ’ESœ˜X'ò¢&Âxàà/$öoº`ÿÔ™Ã;q°õ„ƒzá` zâ`ÅõJ,@)á`E\é Æ—Úà…‰kjƒ˜.ÚàEò”6ˆÈ©ƒ;rð r!<ßñ‹ïo<WðäÁu’:{á E"SÈ„ƒˆH ”Þ@ˆ¥ßg¼ˆ ä 'j!&5¢"Û„Sr °ã i4H ì” „ J „ZH"d¤c!Ó¶'v”zO"ì¨ñ#"œT×N0P ‰9ö“G!Xб4~!œQ"ÙÅ„HµñBÂ8åDB¾< iºH$l„D!!æè‰„T¹ +…E"!Rœ!׊R$Ä'þ ‘Wî ŸQŠ„%æ$ÞÜFDS¤ƪO!r»$.4pEÙ±äÁ5qhñ ^ñà‚è“<¸àºI\taÿЮyj„ Þñ k•&FèÄɃ–Ù;z&Þø>4BG¹h!nêkB½?4B#Í;Zˆ„̧.$Ü“¢!‘pp3P*5‚HÔÍ58wh„ÿwï’¬;Ž$iÎkwè9ÈSÄ“Àº'-Ò-â+HiI©‰—tLrÿE3SUÿsÓQ1ÈŽ˜Ä=p$øóÏTͧ#ç÷Òƒø°G‹4BžNj„ø¨a¤JýAé´—=G$à?Hpž%Þ¶P¶˜¯ -/é ‚^¼ä@ÔJto á…8@aÊ$Aa‰H°`Ê$Xž$Xˆ7"Á‚4©$A[7%H‹$hÖ ªE$xCÓŠ+*_(]ªi B /kh 󴆯•ÖÐ*­¡T)e E¦k‚`Á3— Xhé ^”6ƒW#>/„¼¯oÞÐ /©C¤›5•Á›¨*iPrœ¤Á›°'mðÆ@¡ b¡CD"î¡ ¢>ÇAƒ…®NÒ <Ñ`)äCÒ`‘rI,t@Š ì?´AX/m¾”C°À¦68#C;µAYJ¥ ªEÚ Ê\¼´AH•‡68À‡‡6 Imp~ÖÒ`èú ƒBjƒ0EÚ`¬uhƒXòбÜÄ¡ ~s‡X“m0[À‚¥iY a° ¦–`° JYÂ`¹ q„Á‚†ƒ%û¼A –M< –EA‘0X°Üà¡ ÂC0XȦ‚Á;} NY0È—Y !,°®Ú 1 b‘¶ã“s° b¢É‚=¦<‰‚(…p  ¼ŸR#Àwƒ´Ê¥0ˆr#‡0ØÉt$Á܆$X+F’ -”Gd­Ú$Áº>I°Ò„G¬ó“ë„N$X9Ù;…Áñ+^L‡0Hã–„AXµe0¬Ú‡0H%S Xá(:„Á‹A°FVCr`åM+D„åÀ@ž]b /qb`¥THE*1%å‰ Ÿˆ8Òª0ÂÄÀ†ŒíÄ@ q„s”XaEK ¬4o ™á›X;îa`½é.%Ö0%ê V8j’¢@û1ߺ ôÒn, d•/Q WãL dp3)P.Q ƒ~I¥Ã“Y±')°!ù?)°#&)PFfQ`§ÇB8x‹­Rø‡S4ôAà úG'“Í] H ãë ã&uG§0G‘hÅΜ Èåž“V O´[êÇÉ€õä“'|AbÀY¨6™OžhÄü6ŠNÔîLä[ “o2Bàäý'œ(”8Q£4!p ùu}'*ë$>'¸Þh•ꃱv¬7N¨+ öÅŠ~³ù“¶KBàÜäMBàŒå‡“í— Ü¤,8&©²àÜ4xR¼±V‚dAz´S´#þ8…Á9«RœˆY¦08á;Ha¢ý_¨£vðà}d R'H§(‚¢‡St@WK§(–U8œ¢XíýpŠB!K£(ÜúiÝîMøD7J|¦OtÇ(iÝðÖi‚7¦“™'¸?yЊo¼*í¦äÁ ë1'‚…^G4[`@yÐÈþljƒÑ×—2YURéÅ=•ÁñÎ,S¶P*ƒw< „eQa”2H“"°"‚|(ƒ(:öRû+–<ÔAªdÂJÖɽ$"^|ȃ߀‹x&Ö…™~ʃ7õ7a¥+5€°Át$ 2]S@Ø AŽ@È „J\¶JC)°¡œYaÃòR „ ‘ÌBKC Þ"6,;’@ØPâ;°Qx$¶AÏ)°1N ¤’@Ø”«H d”þÈ„t•ù‚lÈ|AFU2a…—y‡Jy+Šò ªxò §CÜŸHØ/ò¨r·Cæ ¢¢"açTZHh…Q‚÷€„\œ)‘ &$v¬™H˜{\¦õ-rÝVa/øðŠY.9‰Ðvz»EÕ""ì{“;üI„OËz§ všWE„RŠD„ÌršÉ.ø@¨Aˆ{¡"ìå3e°3ÃJHرrA"a§eMLئvz1Å„^L1!@Ž@ØaÂO ìœj •„' 4 `œ°R‘á" ìdˆLlä6e Ò⩬Am¢¬Á@öÆ$A*ƒ¤ÜTé;Neåêe„uf ö·2Ø1¯:²ÅeGÖ`[GÖ <ŸÊ¼@ÂI„šháŽ0Ái½O Üña:òi M£èõM¤ÿ/uÁ âØi… ”@Øö7£(³ÚR¤.žºàÍTB%^ˆ&eâà…Kœº ݇‡Q´¼;~Ó)ŠuÓ§h¥½TNQÊeéL%dâ L2‡St,•;ˆõ“ŽÜA^¯3wþRé‚ ¤.H ˆpPŦï¦.¸ãÉÔAÌÔALðï°³ªàüPé¤N£èdº¡Œ¢ÊœŒ¢Ì O£èý™;x3w5¢t5dî`£8s™œ¹ƒ´fdî A-uAêe­L\”Q”¬žFÑ›-2Š®ÏäÁ…^‡QT¾P ƒ…îR ƒL;MaQŠnÿ)¯§0Kqꂘ€ºàýMŒ•6›(æGê ºQê RÔÁÔÈÔÁþ! Z ‘©ƒ…`©ÔAÌÔAØ¿R´ú•w™:¸>RG<÷) x@YÑß”mN-” äÏ£–Ú}7¤œ¡”Ï~ØÅ´Ã È-΢hå^¹ÑÏvûóµÔ–—n; †£ìÛ²¢Q¶dÙ±eü"ß]±áì mGWjÉ®¶Õ° hŰÙptŶì*[Ž®ì#ÉlJ߈ gWh;ºRË?º®š¯reø¬«öY«êgÿ¼½HnûeþÙmûøeÿ‰m»Õ]m¯lŸ%¶þL9¶o7ø}wK?*cýänöuNÏ‚mèå(³ÝœUÖØOn„Ž^ÛØSYCOG5õ¤ØÓY®=e‰5ôtTXSOÚˆ=ÅÚø¬fµè鬯¦G\¡§¿§Û=¬zÍþ§*ÂöǯÒ_¿½öæüõg÷ìçËô§wí÷žþr¶ûùnýà °õkªÿ«µýaý5Ûè[ý5kÌ~—þõ­þš5^úWöõמÉoÃè¬ñ³þšµý‡þõo?icýµº¿þÚó,!‡Ûçõp!á=Ïö<¬zäÍß÷Œî…½û¾‘½ô…]Háæ¤ìöÔc‹I•Þ¶! +¶ŠLzŸœ¸Q¼ f[ìÅÑ=€[c¯‘9ki±WÈœµÌØfDdΗáð3ôì­v„}o_ ùa×Z qáîˆÌy†¾ïâs¯;ZbBã r!v2^âN&?òn˜óŸÉÙ:U£ÀìÝôºœ+æØÏå‹ÀœgúûUß3sžé-wæ<¬'¸"0ç‘ëØfG`î9÷çÏe+¡@ó¿Kå¼áö–A9/P¼%RE½ÅHÏ/A9ÖXVë} >^£›±bKõZV8=Ö¹D8wYóXç–eu¿öòë»lQ_ädƒçV¹"&g-þó/_¢¦D‹ÇÛ–- fþÜi‹œTŸ•/«6kœ@~Z6Ö8A¾À²—ì@”ÇÁg„äl×þW¹=$g 1†²"$ç-q6;Br& øO¹ê!9kñÐŲÇ7ºÄ:ÄÏ“P±Ò%²†Vmå 3zÄä¬ÅŸº§%br®BøùÕØH¨Š–19k©±×=eµ›qðx"½¥Å±¢Ç°ãùÕiWÄä¼lƒ¢•ˆÉ¹äá{µA9kñ{vµA9kY±M¿ ­ Òþ´ì/nâ¿^”3ö§lµyC]¹ãµ°Ú=¥®ôØk ¨+7îÛ¶;ª0Þ¸SúÕP…ÈþL8+ª0F ¨ÕkAFhs4aÄ‫÷KE}.ü´lTa Qiõ±P„®æÕçýñ'n‹~OTá€Z·læU8P3ìyÕuTáØ‹Zãj¨Â±1¨Q*ªp "áõ%ªp옲-›/m´xlyްÜ‹ÍÓ‚°ÜŒ^c,”á@†ÔóVŽxªÇ°Üêáó*ªÂãØˆÊ]X³dÍ a9m3 ÂrB;kV„åX¼c͆¸Ü§Áš5¥£Ž°Ü…úša9ÊkkN„å®°÷<ß Då.,´æBTŽŽÂ57¢rj¹/Då.¬ ²î‚¨ʆ¬»"(gkòø¡î† ×ÃyZ”{Z\×_ö¾`^ŒÛÚ'¬Ño û>{PîBÚ²t…I3~K”¯‰½¢ã œ]zßf]Ê]XRe¹ñ-âåæZÜ>»ñ²~(ü‰ˆÜÙ¯±RqÏìò¤rgÅq&"r¦ËWV‡ÆY¢e!"wAí]† …W¼e_ÉYDÄ "r–©[¶ P,S…ü¼ekVÞØ$vj[ËT¹_tÙ‚6 å[ÐÍ@HîâKÔ>Ï’»°À²Ï³‡ä.½X{!$wa)eK™T:Qí n[x¦áX¤ÛWAHîÙÆ ûªÉ]ÀmKyHîB6æ¶•gÂ-—ñ¶¥¿`qõ[tÛÊ_ -+>’»°Nö¶4óf{l³’³€¶7lDä.,¼mU;œŒ¿&¶¯&²c“8[“Â#r¢œÏL ¹ ¯ëm+yDNǶ•¿nTÄ™Ñ2’»°(ü¶Å¿¬ÅnïÙ¶pEÈã+Þ‡Û>Ò’Çc¯ —Æ…Av½àÒ¸Q}n¸4®7å3× —Æ…×þ® .+*Î< pi\±€à¶Õ¿Â.½y “Ƴ‰ßÛVÿ »4^û»ÞƒviÓíºº*é¶hÙpi\H}Ûö…¦]:®º}¡+LþÈìVáÒ(W<ô»µ /pxµŸ–78DˆÝúÂkËl[þkâXþào[ÿëÆ@Gô+ÈÄ6±WðB´ÄùlžžýeŸgº¥}f²íó¹³—?âÛ>Ï Æùïí †ª§eÃ+¥évï ^iXáw7¼Ò˜än[ûk"×ûŽCYñ$Ä&«Ã* ÁsÛÒ_a•Fîê¶Ï3Ë(yXtÛçÇvAbÛ×¹àH36±„cXß[tÓ6¬Òør ºýéø+eØ^øï…X_ëÀ@]K D6áÈ,{a hRyãÀ@Ìk ì:a òL ¤õ*1¯öQÍíÀÀØ ª‰4.C±9(Uý’a™?(0„‚1>(5C ÌR ¢ÆíAXÆô ÀBI°û&ZK@@p!s0I0[H‚\r2Ipaå˜$Á5 BÁ…°°PpMbQÐZ~œ$Èè’>DI‚ E“ àØH‚‹³y‘ !?IùV‰‚‹ä \ÈÏLÌž‰‚ÖH ̈‚f,‹$ .|AW|’-¢›CË9Hõ=“­— <’à‚™%Ip!ç IpAµKdµû$A‹LÄ6$Á…±$A³"øÑE‚ ß«$Á…¼—$Á…ÊïI‚ É "Á…õÓ’-ÜG¤Y/I0œs/¼ÂD”$hEü¼@ÅDµ‰@ðÂé >h";óAXWDôD ÷Í‚ñAX±„›÷A”I8@°àl‚å+ˆN÷»8Ð#7à@Ó+ŠKÌQ„l,¤eRxÇmDôs òZ¸%B Çƒ‚ÅÖ2¶Wœ¯CàÍôNQàÍdNQ m÷=)ðf ¨0Ðû èfP‰xo$ U5SèÇ 0ú6? ô Rùq`àÍ%¯…÷Ñzl*€xsuua wÛ=Æå—˜h-ñæ úÂZÞñ =ÆL ôó‹n@‚÷þ$Ao‰~@‚õ ~ zd,ö ú‰§‚}›h Þñz=Hðf&°PPÅJ…‚7—“$ ú¤%º zÌÍO(è1· ú6?¼7æ!"Á{î/ô•=^$è!·*Þ'ôaÁïú‚ׂ7§ ‚Ö0ò‚qó9@u˜ÄG/à@ A 葼=h˜¼·° è!B`ß…Hʧ ½fì }›ZC‹ŽÁ¾fulôn|˜ä@#þ80ÐC˜AtÀ@?c߉è‡ 0 ´^J0ÐwŠMÀ~m^ èAÍ 8€àÅ.ÅŠr’á:8P¡Qq o”T@U¨Ð¨8Ðû‰p ªâ@­=6-à@h þ’ÚéÄ ˆÞq ëæÙù°É¾A 8ÐGèäB8A?Nì´M¢_p 7=‚o8Ú6%èèCò_Ž èñßè ¨¬@ж©'›}¿2Á{ó=ª\Hé•¿ä_(¿&´i¹OôU†_ èùÁt©Û¨-ô/‡“Œ@pc – ¸QD_ èuÜ^z ÷(V3uÛ¿§AkfØ/E“ÑOgêvû ÂYÔ90ЏbÚwp G.ã#]n¦m7*Ó¶ Z¤@%© =c-öj,âuQSì,â…Àƒ0Ð/Gì5XÄ na ÷-7Ó¶7¤Sb —ûqP ß |»Pà Z!ÐMñ!Vzô P„@k‰‰!pqÍLA 9fcZ tß|ðܤG…«E+9?(ðØh6Å@5@à¨T#\ñ@€–*w…ˆ´]bI´– 7 íÙèÕèè¦Ñ8òò]QQEü·â!>øÏ×: šº¸¢`€üçI¡w• úP&ÿy t¿,ÞõÂ?eqÿ| þù:7ˆw®çÒ\¬Ý…ZAÂ?û±ãÒÿTZIøç¥t_øç·HìÕ¸ –Ìþ¹‰-pç#=Qø·–Þþù6±ÓMwþÅmÝù¼Ä?k‰™;ùϜͱùϳ|÷* ú UnIèæûثӠ /¶GŸ¨Ý…ìàjTìH€žÍo:ô+äB —áz ýG {¼C,lLبE¦R lÒýF–rŽçŒhwJ\R)\G)¥@ÕeO%…0S Œˆ“dÀ†ÙaÊ€,Û°a¹Ôí– Þ£«~èõ¢ã@ÂN!°Q –ØbÁ³ÔY8.uÀ+J Í-R;CRÿNÐÎ.*`£š,E©Úõª€1I€öP¾ØoE^]²Ÿe§Å=& °QC—Øh Ø¢*TŠ€vKý8ÈÏ?+~×Il$"i€Ì;K ¥ÊSlOŽ4@V{O°}’Ÿß½?üT><5À†\ƒÔ*þ¤hwüü¼ÛÐ)Zz݃û|L˜T k¦hÙuÑB•SlH—L°am÷TYÇ@ `n§ØP(%@^¬T9ðTÄÏ”|[’qmR4ï{hpTYE!À†uTRlQ˜<@ë7Z(6„eRdÝÃ-2E°5¢ @+óðãÔÿ¸Ž^êyøÒÿX0õ?üà©ÿqñ½ƒL°n2@ Š`Cv[ €¬˜™ Jo¤þ×2úŽÔÿZe õ?K$…"ý¯¡dVêöqßjX½,õ?.Žú_Ã46õ¿V¹×Æ…Øc™çš`C‘”TÛ%λ”;À‚[¥6Æ[Œ·×)Ú´*°Ž`CEÛ”5Li€ºÒÌp©6äÒIlRü¨6J‰Òãûpj€í›Xÿƒ:k)ým_íð”þ6tŒ”þ Š_ÒŸ‘õÛjf¦·ô·¡5¿ˆ¯¾¥?kyK\Å'¥?º™RúÛ1iHåooªƒTþ6.C*t<¥ò·7D*{7×|uKéO»HúÓÙIúÛûëÅ|Ù@åO þö&9RøÛ2rRøÓ…‘ðg-± …?ZÂߎÿÃý¹läÿܘ ¥tÓ¹)è&»ÉJ}'  ¨w|8@7ä99@#‹ò0€²AþOŠMéÿD=ÿÃÿ‰pÌáÿD!ÞÃÿ¹Ixò†GSæOv›îOªZéþDª÷áþ\ßÜŸ ¹?QCçpvb¢ÜŸÓÑÓý¹_Ìw˜4åþ˜|Êý‰2û‡ûîéÃý‰d¹Ãý9)&Êý9áJ÷'ÊÚîÏIë©ÜŸÒîÏ ¥#ÝŸœµ¦ûóþÔüdÀL÷'B2"Òw˜?ãÏÃù¹ïäüD€îÐû(~¦ó“-)ø!©÷p~Fñåü\ÎÏýÁ{‡‹S‚ŸÐM‚ÊžÖϸä§õs¾xÏZB3ï](;ž¼wQ‘ï™%òÇÁ{JL%ï](ðr~B›;œŸûÍ{ýÜâ½§Ç–ó“⢜Ÿ…^U9? ®M:?QFõåüŒ°ÄéüŒ°D:?+‰.œŸQH÷p~²AÆO$”ÆOT%?œŸ•>œŸë |飔ó³Qà“ó³Sˆ“õ“^Ë´~¢*ÕaýÄTü°~2%ë'ÖX:¬Ÿ”šÒúÙ)ÊúÙ‰Š²~R.Kë'PFÎO,•~8?ùÒJç'£!iþÄ3™?ú•÷s ö–ÞO¾ØÒû‰e¿ïgौŸã›ñsÒŽ)ç§Zäü É(Ÿ O¤ñ“ïÆ4~NÜiü¤£=Ÿ¨Žt?'ý4~"ûä0~ÞÔédü¼¡3¤ñÕãçM:“ñ“ L?áCIãç\¾Oõ{ø>C„Kßç"„Ê÷¹â–=ŒŸ+ÞæiüÄÂØ‡ñå÷ã'b]‡ñs}}ø>Q.èð}"Üqø>1y8|Ÿûë%÷¹I16‘ís¨Ãö‰IêaûD7éúDÄt}bZx¸>7ÁP¶Ïc:mŸI}k)%õ,¸+ê+ð­$õYKtCê“•QØWP&±Ï¬Œ¶O±¯„_ãåúìo×g¹ ‹ú´¡OVKA_Aݼ„>y$ú ê˜%ôÙ•ç¥\Ÿ•úšlŸDzAŸ½º^rŸµñäû¬P0Ó÷Yé•ïS-ò}"‰þ0~Âçq?k¼ûã'Ã/2~Â#q?‘„t?É»iü¬_/ÅÏ®¿XWí°~º‹þeýÄR›‡õ“eädýdî\Z?™—ÖO˜˜ëçfVžøñüƒÿÞ¾OÕ]Oøƒç ¿¦„@Ò_Ä\øƒsâ€?º:Å~plýPàø@¿ÉD:¡^½úq½¬d?øÁ_ðç>áï­ö]x¢Sí»Pj7Õ>ÎÙRí»B6J±ïªFª}ÝITû”'"¹ïj@2ª}Ê6‘Úw¡hsª}&©ö]ƒ{Aí»ˆRû®Amj“Rí³Ïæ+ûÏ«r¿è/÷’Üw1Ê-ÅïºIeTü®…¹´¿£’ßEó¡$¿ •½Rò»PF’ßE@šßµA—æW O§æg^îà+Š~…ö9‰~ô{Kô+…)yýø"HÕ¯0EJª_·$ùYÕð€QJ~…*—$¿‹¼§âWh|“âǺ€©øÙ*¿oů0ê.ů4¢¿Ò˜èÁÕSð+J2¤àg-± ¿BDZ¿‚ÅqRð+“ŽJ ~O?åŶW ­¿SQ ~…h ~–ŒÛPðã"Ã)øqQ0 ~…éMü Ö4MÁÏêbÇ6À§%.²° üL`¡”H,„X`!²Š “2E€…æ\ ¼«~!YÝqåi±lÏhq†(Wõ:;‘ŒŽ†ýÅ\ô- ؃‡ª>GÎÂkO ‡€^yþ3 ìi±¥f¢¥Å¹T—Ø–…|þ¾SÊÙòœ?É< Ï)9ÏG‹çÌZ6[ZœM³`F´ ´xÆÂ«¥)ûúFÏ}|!Ñ{ÇÑÇ€Ôê§e"ÿ9®K‹HøâÚŠ …’OËVêõŒÃô “’?qö¨äö´ðì#ü4~DC‹!w[Cú•?-¶ìo´à0£!ù½X5íh¸âvéÌþ­ø;\\XSëùÛSq#üãVì --°_\üFYÊNÆ^8ÿExžœ?r}mö6Ø€!ŽÑ¿VÌnfûbp\»qWf'oìÅôeÜ—ƒC(¼ºÓâæ!¶ì/äéÆu˜eq±–ç;+üˆ¤<-f Ž–§79„¼ó´ŒÎ–'XÍ/Áã¾ú»e¶/Ö®‹1í9×7¹Wù‚ü´Ð’#àép¨ø^ž9À¢sÓÙ¹ØG½¬øÛ³•:ëÔ{'~Ñý¹£…#@Bi±çû‹þ*ì5S`öºë\YÛ¬BG`Üv…韋{ÏÆðËUí´z>Û ±ÅÀ–š-½N˜/¢ðž]–úÕ߇‰¨ ÞÓðCW´ì/²â\Úµ¾P3W¦•û‹..lcQDl?[kè÷Yã&ZFgK“i³‘Ák ¡Ýõ‹ªf4,x/ø‰xüb8aÜhÁ£~ÿkqL¸|¶ÆŸbk|Ñ2'ØŠnUÞH½Ã1†²sð=-BåÙ¡¥Ä¥é«pP -ûú‚ó¬âlÜ-=G?ƒcбÇÐ8N[ä+ZâÏ6¾ ïÆq,¨‚á).´Ž-f£F<°Ï¿iž?§®elÄat 7kÇNqjóZ_LÁŸ`–û åûâV¦NŸOÜäzþŸ–ÞÙRÐÏhÌGƽ6'No£—»rPq-í› »Þ2“#@öŒµl¶à¸½†[—ïi)÷ªâv×I㮨-ð›÷â :<-Âà/i |¡÷Ñ}ãŒñ¢±2|s¸§}ê÷Þ†c€êù¼Á8†ÁQ­ˆ”hí8‹OMŽ ¯9O<Š~®¸¤–ñˆQÅog¹³ð”ÅG©;O+÷Õ¸ÀkA¶¿°ƒOm½¥áDܶî-=¶±•êéꋞ}nrœ}Œtí3EþÏJ{¡Þ¼?Q/Þ—‰z“# ^ûú =¨Üé5ÎsÒ»b6ræF"½Î ½P¯ã•¨×¿>H¯sš#ÒëœæÔ„Õ8?±^çœ ¬—“õ4#ë‰UëÁªà¯èo“^/ÐiiðJˆõø¸$ë ÎïÄzX½ó`½ÁI5X/ÿ¦íéö°âÊ{ƒ“eÁÞà¸{Ž€-9ÌÔ|“¿¥€IðÅ ‰{kŠÁ{Ö 7H?l§i«£G°Òâ£!Ü[“(BÜ[“hDÜKfyö˜ë<{ÜÑä½5 #ä½DòÞºyÈ{Ç6:á°ø_âÞºy3÷2€@Þ[x ÷¬T¸—ñâÞºy?÷Xà-qEà÷Vd/$í­ÅÛ7ho¡úIÒžm¼âw í­E® í­Å[ž´·oWÒÞZ¤ÒËÂ%í-Ì–{ •K’öèäKÚ[›À´§N{¿X9ðôÊ,lVâjO {,—°·8Áí=s›ÌEÜ[X¾>qïØ†°tñÞ Ü[›·¹xïbh¼·6Ù]¼wñ,Þ»âO ÒÚŒXöÖf`A°wñ-(ÚCéí¤=T£;`ïâ|U°wqB}±¶?q°‡Lƒö.N¹E{ð´W8ƒí >D{ÈyX.Ž[ï)Q¼çÇyr ƒA$ðžoƒ†˜©¸wŒ ¸w{r‘œ™#À ÜSI>ជwç²°Å]zŒ1÷”<)ÞóE0p6{«VÈíZ =F”˜¼çgª“±GGÀ{ª®'ÞÓbâ=ït7+ƒ'ïyâ&ˆpŽ Ñðž–í﹫XÆ10JÞó|T€Y3ðÞÍÅÅ{¾ ú£Âý·r ¸‚‹cø{•×õò©hŸÏ“Z½ħeÔSÚß“·ãæD…Mqoÿ þBQ´„¾x—žÐ·Å„¾-­«°d!‰ÔÇ‚¤¾}3"Nê³.z3í›{RßFå—¤>®S™ÔÇE(ûX¡.±oßœ¢û6²À’û,Ð |Ô*oîÛRÙÈ} ‹û²…Ü·5å%÷YÊî[ã³m Æû¶¦Îä>;ú›ûr -Ç@Pc@/¯rÉ}û&ÍûXÕ0¹/ÇDîÛ7ºcooK€$öåÉû¶ÐDBßM“Ò§Av Çf•HЂ”>ÝRú4H)}º˜Rúr¯à`äˆÔÉn¢·¤¾ûëCémIé»Å¦·È!àž‘Ò‡’A‡Ò§§ERŠ{R_’¥>]à™CoöËgLR_nC©/iR_ræ.¯}îC}ëlRßÍgCRßMJ—Ô—=S껈ǑÇÐB¥L?ž´¾›á!i}:gh}º6ÒúnLžRëË–C{ã_Š^Òút#KëË~(öe?9BcŽ¡¾ñ/e¹•Z°ìÚ¯ Dº RûdL8Ô¾ñAÙBz²¸/µ?áöÔ²sõ›Ü7>7SÊ} F¼?å>5äÚ‡Ú—²bª}ì—u‹É¹ù7mòŸ¶)9Ì| G¬÷y?$þñüEü’þøÛ&ýñÖKÌ”®ƒ·^à$«y6â?þjä?¾cɺ’â?uAþã™ü§ )þãM–üÇg ùO7‡ø7Yòß-"$ÿ銋ÿt¬Æ!à‚·Bi}~{€öfû•ø/½ÊÇÏ$þÓåjÇ ]ëcœâ?õ,þS?Àlé¯7O`ö’cÀ8€yì¥ÙP£´÷1£K¼9 9†ñ€º‰€¹MÓlˆØØ5êèyôw/S3:n‘c`/9ŒSx ž `¶MèÆKð;.úÌ!à'òó“¨'˜ßšÒágjPó™p¿?QI€¸ð…U͈ð‹õèÝ9 eÏúþÊõl uÿ –ýñ ­cóÈO:’Pï Ž.ä/.þÓ5^Ç¢á~ŸÝâR‹í¥ø—Nø§Bü§çpçù£ßçO°i6TÂgý»uÑèóEÍ_Ð7ô> Qå2ÞS.AßÍŒ‹d>ráÒ[Ž-ÉK<Ì·¾1}0·9˜˜Ì‡I¿˜~ óa–N¥ÌGÏ)™ïø´Ë |€®>nsð¶!ð-‰MõµŽ |ëðáô|ûú¶ ö>´l½¨¿%ð-JzÑæŠÞpÜ&y‰ý$/Õø¨&ðÑ1šÀòðá—ð‘F“–n9øÐ WÍ”É{$Àãü£á8ýo¸Çn÷ˆ–É{¸[Þƒæ!Þ¼‡}Þ#_%+ẼwX;u~ïq¯ 0Y ×ïà=žOò•¸‡GP¸‡C¸wÃ=Šk‰JûÃÙ™{÷:OF¸GïOâ^£%ÜËmˆJM !Q©‘i„{Œs÷š´=â^§ú°vBõîu ܽ܆¸×¿ážüªÂ=ùU…{ò« ÷:¯—p¯óvîuZ.À{CêyoHÉ#ï Æ:Ä{ãï ^-ñÞ _¼7h}ï I€ä½A³iº;¯ÜSHX¸'ó pOáTá^nAÞ›ß?F!ø¦, &zø&…ߤAí¾òaï&–oÈ*à#dU ÏñõoÈ©.‰›$ñA ;ˆZÝA|ãCò»upÔ‰|‹Ó)1ß’ÐF‡*‹Êâ“ýƒùžï„¾EµIзùó úõA³ú˜Áзhômþ2x^ñ'‰o‹ÃèO…+OÄ'¯¬ˆoÓV&âÛTêäî¼Û—½ó¢,#{§L¬²w^2KÒy}(~‡;Vö΋±ìi°w^•ìвw>a²wò“ì’¬eï,¼idï,ħ:ˆ‡½³ˆºè,¸Ïeð,TXäð,d,8< 59<¥QËáYy¿ŽÂx)~î»%n ²žU’ž•V9<« ‹C¨ð Êà ü£5²R®‚»³ò°4wV¾ÐäîÔ&Ù°dIîÎ- È'ãïÒ¡HLE¶Ñ Ïü@¾*Ñ‘ÈGGR_ý´wæ\RÔ§4HQ_‡ß%©o|£¾ÿž oòGôMÆüˆÃqLH_<˜o0ŸüsóQ‹Kj¥ “çÏOa2ߦ#QÌ—Ûú¶Øqt~Žð[úTõ Ð矧CåËÏ ¡Ïßí0f^ß|„³kóÕ÷ùTNЗ¯#RŸ¿èÐqÏ·ÄKäs×ýKå;·¹«œù Ç…'ž9€‚Á >ßæE}n5‡³àEAÓ©Ïø/‡§›¾£Cº &wŠãàALfb§XÐçÛ@\¨¨|+ápöGå%;6¸/ùØ¡\ú¬@ Ï»6Ðç5cf¯º%T䤚ßÂRÊ_“—Ã{åó¹Wêa@ŸŠ]×ëH€>.Í.æó §/æózyô‚—üdÐm0_ôö["Ÿ×¢}!ŸwóRø¼-p#°2¨Ø+xI+É ù|›CâÓbíB>k¡ ȧjxB>¯yúJè³mˆŽÁK¶Í~I|¾ Ð1O•÷„|¶ p0Ÿ—øC?_Õd>?CÈs,!ʺ`>ïR\0ŸŸ öÉ1Ì—Ègé®—Èçü°M “W­Ã±‚ù¬…4Ì÷jÙ_(ˆ¤¹‚¼¥`Ø4_²*ý›|Ö)Óìù|H/•O5 Å|Vuïz1Ÿò¥òù ©é]Òb’ßæÇSúʯ!¥¯4yA+.LJÎ|^ÙðÒW”¶Ä”¾Ò99fJ_‘û9}Eæ'æôyü˜ÓW”­Ãœ¾ÂIŠ’úÊÂùÊÄtŒ9}…EÓWÆgN_B3§¯ u b*2’úìôÞI}å&€úÊäå"õ×D}…É¢¾²¾^6O;ù’ùŽqôùî}e è8„)QÄT& žÐg/E"^@ŸO~;˜¯(iv䨽q[VKSá»OÐWn>—„¾¢€C@_a|SÐWdß#ôeÉúìWx§õE†}õ’µÔW< õÕ"ÆÃ*ýí¢>+¤†mNUfu’ŸUÊ‚=4ªÜ±Я,uˆ~Uöp²_ÙŸ‰}E¹¿„¿zñ—!üÕB*"üdûYqË—ÏÓºAnêC Ùœ¬åÌë«"m²ŸIïâ Ú›ýìǃ”†!”ýõ²yú^6ÏE;د^RèÀ~,]™ìÇ“É~µ¼lž^¼…ù.ÆÉ~E± ²/$¿ªÌ’_%Ãüªàgçi}Y ­Žkd¨íz«5ëðü¦-^ÅÐÞå^G1´ŸìöŠ¡U«=°á¬†¶£°Z޲cÍÊïõ£+6œ]¡íèJ-gWÖÇYW ¯®¢íìŠ-GW½2ˆW°rÞ˜]¡íèJ-ÿð¢hõöØó?[Q´o÷wµ1 U¥~r7_G)¾¸×¢Ÿ£Ü:z•;COÇVèêµûÊrgìë,wƾr+öunž²Üû:˱¯ÜŠ}[ñ‘ÍrgèëUzn…¾þž¢hÏdoÄŠ^ÿDEÑþðúë·×ãÏ^¡¿þôîýx«þüöýÖÓ_/ŠæÑ°úÿ¯¢hëgEÑþö_ Z¥ó¥Ã‡ùÝ1;¬£!¼áëÙ+óÆõê…yã1iªc*Ç:fcO‹r¬ú¹3ǺFËR–ò…ž·²”c.SçÅkÌë,J³¦©“ïQ¼C¤6¬‹9•hX7ÓDñk{:Lt“Ûº.Õ‹~WQY°ˆ•V›á!1Õ—úŒ–†–^˜U9Ñ2¯F·SUÁp¬©ª`1k}Þt‹Éz1‰®k©¤Ïw«¤VÐÍÃÖ2^§Ô]d¼@Ï›Cˆnw“ëWsw¹.bB\÷PA-\‡=¯ø›[LÔÂï¶ï,¨…}8úª•çDKLÆÛu© VÊÚU亸±MUE­ äv5•ÔŠGûù8&Eml3dYhZäP»æ™àÑA‡#ݪ©ÁççͨšZµiÇàÃn…@¬¿•"»ú(UûÐ…QÎ)ËHÄÚäè{î4™xÂ[µÐr_B8~‡» FT|š}_Rx»s ¡3¶»ËoÁ–¡ŠZ11yZ²¤V4ÌE)|¢å¾©Òáqçp#Ý9Ü&±èc !Š,1qj«B—¯Jóõº¸*†ëi_dˆt-Cµpz‹# ç®­©jT -·*já×\krPx6×VE­ˆÙ·}©¢Îxs Œ¥7[œ µðMØg¿œ}•1ª8´}”±IÇ&C¦‹mr ÛÜÒ"ñ‘ÛK%©ðøÚâ\ÃØÐmq. *~»n«sáw‰‰D¿r7ZZ=Ϧ_ÊãÀÒ"+RŠ,Ñ2!¦2-¹_ãÝýZS#dÚ¯­šZñÍí¶4o¾-RäÄtªÛÒ\c’Þmi.T ‹wñó*.Ø"ίänl1R¢Nßí«ŒQ-é¾y÷ÅóÓËJ9ÇÎ1`¯Ê1L¼›{-#JïµJN i¯ÛÊ\UœŽ­ÌEƒZÆ…›±ão !$°nŸe´à[誾º]“¿TEËSLâYbËÓç<}<ºÚ {w9i¯áHÚ+ßhtÐæÓ¢½^ì±ä_‹^'ìQÙKØã»%a¾öøŽJØãN؃»‡¬Ç—Q²ŸÒd=>ÿÉzÙ„=<…ÉzV¹d=VêKØ£Q7aO@+Ø£z%ÚS‰/ÐÞš$%ÒÞ‚_A°·ø( öä`ì­I\%í-Ö7íe?+‡À–’UÁ@jU5µ®7î­[\Ü[LÞîO•CÌ€¼·˜.Þ;Z€K‹Ïœx¥Ã„{ë•ï°ëGY0ŸÊ‹‰ø“|D|‹äâ;¶ñ©¤¹ˆoݼ ;‡Ð%ñÙ6 5“"¾%Ò!ñ-Á‰o1?GÄ·h6ñ=-…-›£Z'ñÙ Mßb–ˆÁWMæ[b(BŸŠ úŽm}Ö1úô-,ŸÐg'8вYÂm¼¡oÑÆè³àÍúìlÐ/˜a HÔ·’ñŽ1D?¤¾<©/φԗã$õÙù¼±oA|õ©Ì¨OuìA}ªGêóêl6PŸµÄ©€ú¼W°V€-ÇâÒüŽÓøù68V€ŸoƒcøeÄLäwœ!ÇÀ¿7+ŽÈÏ‚c¤º ¿Œº‘ü|¯8È/+ΑüüHhÉ`ê òó¢yèy.މçsß Ö½ÉÏ·Á^½á¾äçûDCm,SÇM¨Ùàwœ À/ §$?ß =s›¯Ÿ÷ó"¿c ?fÜN~þ÷‹üŽ~gŽ¡¼Ðï8 ß¹Í¸Xm/$ ß¹×”öÂÙÜ÷Ǩ€~gÏ{ð§Â6@?ÆÆ6Ž~Çô˺‰D?­Aò;-[ƒBËÔ’ýíÄàÏ<Pľ!ФV&Vb_™j_ö³UF×r§å¾’ûrÊ}º$÷1€r_ö’chzŸ®¸ô¾ñÉG õ>õ#½Pr_n’CÀ¡¤øéîTË XŽŠŸÅO·Ú¡øáÞǾ)~ª`*~˜lоòRü<?rZŽÛc ¾w±åzóŸÎ™Šßøä¿ãü–ò¬¯7ê!KÑoÓJÿ•T?õ#Õ/÷êʳfÏ9µp ñ'3 ’ßà”\’_¶PóœoKóÓ65À–æG¯tj~S{I~£$¿Ü‰šßýô†¥à—]¬û}@¿ÜB‚åh¡_îÕŽ³†ãäÑnÊS!ùéÏý1bßæ2)ø1´ ì;öÙøà€LG °O_a_þbÄ>œ™òÄ»@ ´”gJàã.·jÌì7íésÚË-Æqê/ï8QâÞ±p/Oޏ—&î=À6€.q//6qï8à^=p/4¿ac¦5Õ!Ʊ‰{G¿À½³eŒŠ¸—£šÇ°ÍR%bª`¥|ˆ{y¬À½ãïšµ”±Ç;ð’ùŽaöŽÀÞ~“^žë}œ=΄g¯’^Ž™¤—ýé·ú1’^žÜÓ7‘ÞÑ25ùÁ¯MÒ;úYš¾á×&êeË>Æ=ïoc ê-íøÈyyzǽ6A/O— —C"è=ôÔ@O{ ôttž† Ð;zéå<‘ÞÑHOç"Òã»Y wæs½Ü† —'CÐÑIyy.¤¼£Eç‚;Î7T`0FÊ3‹ÒKàó¯ú]Y$'—€tXs”óŠ ÌÜÐݪ Ìp¯¦3„Ã.»ÖÂ6ãz_Í1P\橈0ïhY*’Ö=>FEÌU ór¯–cp‰ôêŸ%ÛÙ„é`;Šîd;¹ÞÄv¬6l×D{d»&·'ÙE ídžÚÁçd×dŒ$Ù59.Iv2Ô‰ì¸É®Cv ÙqAÍ$»þ옾žd—{Ýz7p›¥—ûÙZuCO#I;ÛqM¨d;VLH¶Ëm:®øþ »<ÒÔÓU>èN.]Ñ]—EtéõÀÒÎfcø0sfKU *нèN#Ý5*‰ ;éÈëÃÝ15é®âÝzº9y6鿤5“t‡?‹^¸IÒÊÉC‹í²%ÝœûÃÍ™ ¶«€…vºk3'aï8HÄ"Ž(Ñ®ÉÞ™fNàŒÐŽe5ídIºú‡!5Ñ®¤½S%´hÌœü[í@dÇëdDzIvÜI`Çû!ÁŽwl‚ÎE`§n8€öÍÍÉwM¢]vs¯×„v¢ˆÐ®?„v]°—C’‘tŲ+o]/'¡º!Ùé|¸Ã¥ÜéúîhrN¸Óawº‰wLž¿6!e/C Îì·ªÇw{Ò.¯è.´ÒKhíXhÇÓH²‹?‰uºÂ:žC?N}$ÛÊ{[CÚ×'Þé†Þå^ûõÆL¼Ó½.¼Ëmj.3ƒ–¦•rp¤ïpcïr›lãC4Œ4(Ñ_×'ÝüAw:Ð<†ÿeáÜ{ùx· î´ÙN?”Ø®ý„íð‹íÚ‡‹óhÛ5j;`;Zh§³Úe'Iw“èN݈âϹ>~#Á]“b˜§M’í®¶Ómv°Þ `»Ü"Ù7ŒØN'#¶«|8¶»Þ*^ÞœÛq›¥ itk·Á>Æ ‚jN~€e­¾Æ$¸kßà.·!Üé|wŽw¸àN÷¯à.ûÙã=¦„»&P+í5¦d»&vãÖ©âåD#žI¢¥í•ÇùCO<Îÿƒít¶b»öíx:¢;5´œºÞÑGŽ€[Œ²e*gÀ®®àN‡>’; Ä"õ+´Ó±…vÚ©çÔ$w½s 48ßóž;5¬œö¼å;~†ëÔ§¿>¨ùI¥ÚÙißÜã¬Z£{™profÞÐz¨7˜îM™eßœ¢@Ú7oeÒþÈõLÒ¾)c›ì›‹=˾É2šißÜÔÐ4R&ó1ÓíC»»È¬"¼ 䜄W8j^Aå^ÑN¼Jnà±O^ýLÕ³ j¹z ö•<º9‡ÞqfM=a@u^Âåx8¿<ì´þ•T|Gg®ðŽ‘S¼+¹z)Í¥x7°Å;þâÝ¢SâÑx4¿%ëMü,¢»ÉEÑr9xLúJÀSN¨o2r À“ßT€‡Bïä;®ý”€G÷dÞ’o”# W.ÅáðX†:Ë>$à-œ^ÞÎqô$àmfªðè¶ß-x-’ï´ùnë|÷dØõâ;æî|x'Iw\â5éŽ&Ф;T#ÝyòtòŸº¬7…‰nL ¸óÔ°—n—ucîxäÊ 2Ó+î²¼+áîHdÜy²ÛË´é{½èîÈ rºó¿ºS ÖLÕcùW Œ†ÿ¤<ÿQ^ŽMï¨Æ\=¾D3Yµ%™¬×hfU²Þøz)y~±Ð-sõ†LLÖ£âª\=¾Ž2Wu¿3]Oi¡Gº^t½,rfÕ°ˆtNtÓ Íª®ÎoÚâUäì½Qîu9ûÉn¡ÈÙx>’¯`l8k€¡í(¤–£œØðïìÙ^]EÛÙ[Ž®æC¯YüêfÃÙÚŽ®Ôò¯L6ªO^•É~§˜ÕÍ­ß 6}Ûàw –}”ûv÷ô]JÞ;¿þìN™û(_U𢗳4˜uó* †~ŽmÐÑ»Èz: ƒyOgY0ö”Û°§W‰1ôt”óžÎ¢`ì)·aO¯cxŽ¢`ÖÓ«pŸÜ=ý]…ÃúÊË?Qݰ?|Mýúíó³·Ò¯?»e?_T?½k¿÷ô×ë†õåNŠÿ²uÃþö“~ÿö­ö€#j„Ù¿þí'm¬ÖæÔ ëö©ˆ¨ð¡Ò#¾@»^l™lAúŠB¨»-¦Ž#of÷›¹ãØiL&ŠÇaÏ̪Ž/쾕’ŒÙÇ^M)mØf#ªÅfÆuÚK" 3®‚(Ü…-ª¢ZJxZrqC´´Å)kLGÇÕUC=fPÚÓF‰l«æ£¬1‚]bX£ Ù­“î§ÅCF7Zªý= ŠzûtnO®ãø|L|:gá8öâCx~v–/þvZ*¡yÔ»{Kë/êï çG­êÇ VÏJec4Þ„aƒª“äžÿÞZýòÐF!T‰®£Ûl¦uc‹çëécÓµ©Ò3¤Ö˜ü5ú´)ù°PÔ.üû9¬ùÂÉÅš½bÑO ÀÂUöÃâeOËMðÃV °–;^Oƒ·žË1ø@=¿®È¢QÁsãÙÜFÔ;ëHa#°šãxœÆÃÏY_ ËçO{1=×€EƸ-¸5,€…Ó^f÷=óiÇØÝò9O ˘1Z0€Æ„ЧeûLɸ-uy)ÖÂ(ϘÍÂ[ÏÍÃ,×1»…·ž[…>Ëç”­—Ißߘ1†ñ\<<ºó¶ØÐsR¬Ì>æ²ØÐp™'~¨iÕü¢_ÜŸ·ÅŸmÛO—ÿ,šÔÓcèty;Æ0—®×Ýno‘ ò\Ò¿TÅt o ›§á.¹Ÿw̰7*„!ܬŠ3î‚I=xÂÎõ\×Ê^‚;ž³Ä¢#Ö„xÆdK‚உ ÝO‹®ÍªÝò¡EèïùÁc•1ž±ºE†žó^«Œ5¼@îóÕþBÇÓHóé†ëŽuÛ¡;³áÇZÜwÂ…Y1‚çlÐÉÆ¶žäm‹cü¹ØÓ²}Lƒ  {ÿZÑÝŠßc·ÛçÒöÖÀ6Áä ›cc&'ضÝd¶}¶cßQô×+«{ò“éz…Ù—¹Ä Ç.óòÕц›_ÑC¸ŸQÆ•yZbª3/û„X ëEÍ«ÝþC *&óêÛzn5æaÏk ”•¨†2®Öó øî箾q‚Ëéä¾§þüÊÏ¡+>²Ó>Ì6¨§³Ѧ}˜kì±Â§eû ì¥G*1_VcGK»cPpÛÎÒ§ÿPIÆ&cø5›vš6V÷½`¯»ùÏ2¹¬ä,1û œŽ a駜ϗÙþæjÓ¾ËÖr3`6í»lû FúŸÛ}ù­6èÕš5`s–PMfÅnêaôç®ÔÙÕi³¡ç^n_Øä¶ ð4Pož¶œÕŠn6nFG;寷ÅX8g>Ÿå8 ~5û0Ù¶PØ>Ê5ö‰èölíö!Ù-wHëÓ‡´Q¬a6œÿ«öÓ‚óæe7}·@Óªn–W¾¶ç Cj^ˆÕŸEÜåÝ’g›­  6{ aßs˜iek¹t×÷fs¡áªhœ_ï>²µr"L9û𹕩ï8Òô:ÜÖ‚ç©Çìl¶É1àžè^öyp 0mE+ÕàërÚŠV6ªç•S”ù|šø»?ÌÀ&œ™C[›tŸ í›êÅ|¾;>¨çÛ=Ðíô¹Ðž\Îa>ˆÔÆ÷}ŽåÓ9{ E4v a°Äâ´­¬åæ"bsFìÁ–û ÁmÚŠVÇ^« Ïçµ}ÐE»ãwÂÂ&sÆù/ù&Ÿpœÿ¥;íÙÈ[+|ÌyûTh/¦}6mDvb¯ˆ‚ØµŠ¨ô¼qþ›«1v²¹˜÷Ÿ®!v€ß7î‹xñÁ}ˆLܱVaŸ\Sö!’.îã*D ~,̘à‡oKrsWÅ}‹õtÅ}V§ 4VP< WU‰j²e³Ä æ>À>/?ðÂ>ÃIÌÄ}^ô8¾»À¾4ƒûÜ&Ÿ|`Ÿ›€¡»J9û|µ¾ßê³÷eŒ)¨Ï8o껸ö¹¨¯°n³°¯Ð¶/ìóõ`~;¨ï™× À#°¯òù!öÙb%˜]ûLÅ"ä\¹ž"±o5zˆ}ËÐ+åØgëö­Žõ¼I}.|1s9ŵªÂd¬Ô÷À-g ¾§…tA}î²ì¨Ï˜D‡!l–ðõõ­" ¾î˥ƚÑîEW Cí¶²¦Ž}}kq%`ßó`u^ŠÀ¾nïøŠ#95ù³†[+°¯ÛË”Ø×mf×Oìó§÷I`ßóôaéUP_7Ù 4Ó}ÏŒ©$õùÉö=O§H&°ïy:ù­&ö™[fŸØÛ `íRßÅub }&åár‚ú.»Kè»’»}6ÜCƒ¾«³âY@Ÿ=óí}6Ä/è³Ù#^€¾k Ä}¶Û¨Âù/úÐ}Åždb “ÙrÁô]yñ}—jvú|F‰žm & âô•:®€>›sâ‡ô•~}½˜ÏÖ]Å¥ó™úˆ÷˜ÏVjÃ-æ{ž"R5˜ÏQÅ6AL妭„ÌW&'2„¾’Á,‡¾òÌ©÷ úʽ? ¯Vi ôY 7 ÏV€Ãê3õý€úl›…½‚úl† œõÕA+ ©ÏÞB:úª½l^ØWΩ¯j1wR_4Çúš,Ä>[&ü ì³`ÌÅg¦ö¼ñ1(`_³E¼¢!¨¯j½wRŸéšˆ'€úZ§ÃÔ×ÊÔ^ÁL¶~qǾfqœp`ŸE7â:ûšYT y1„Êu¾ˆ}OxQŸÙ”à,¨Ï— }Q_k¬MêkO4±ÏÕ«èCØdÈd^« -†LMnR_»¯ø3¯ñóDâëZŠ”Äמ;¸Ã˜š–S ò5•Â'òµg’ÝÑÈ×+=D¾Þ¸˜"‘¯Dzó·÷û>¯÷#‘¯WVf"òõÊ»—È×+&òõÂ܈|Ös½2Ù+þÂ6L}r…u2_gQ<"ŸùÀæ ùC¢G¾>X3Ͼ?ý…|¶ä/ØÈ×í>ùzïÉ@>»T˜îƒùì[8°PÉ,@>û¢Ä€|]ë¬ùlÙÃø$ùâëý‰Ï~F\Ÿ‘ nßPP’Äg¶ò"¾ç… ?)‰ÏZ0ߨÔpH|ÆHäÄ‚yÄÉ€Köq«/â³ÏTLÜH|öqã6Åÿî°ƒ{Ò@‰ÃdÔ—È÷¼)¶&òMl òKq Ÿ}Fñ°ùÌ9ŽÈ÷Œ¯r"ßl,ˆFä{°Ž÷Z ß°5 ñÎpä›w®õÙ‘ÐI Á–\$IƦ;¼~K蛃/SBŸË‹ùžÛŸa0Ÿ}¯ëóÍ›_2ŸõýÕÊaľnð‹û8¿÷m*a⾪°ä>9Y‰}^Áý…}îŸNX·¨+ûlÁÄû¥÷Y êÃûÖ…rľU¹ØI`ŸËkÃÀò©Éo‰}†$˜ìPí3½¸FµO1åCíƒTv¨}˜”Jíã¢4Rû®Ôÿ¶ª”SÛ4•ÆY?¹O˃ûlñQ ¸OËt&÷ñæ÷UÚhÅ}µ«‚­n ~“apS@ü ƒç?®ƒ‘àÇ$_ëoð³õÀ±À¯ÁÒ-ðëšHü,P ZÄ:¿0¿~‘Á}M2'¹¯Ñt,îk|„Å}å|É}>DK@Ó·Î}«a¥9¬4m!öùŸ@ÅÀ¾•³(`Ÿµ€£}Þñ û¼@^`Ÿ‹‚Z`Ÿµ”SíóÜ¢C˜T0:‡À~û?Û~qŸmõÜgÛÌSîë– ‚¹#¸Ï"®ëÅ}¶)Ø ÀÏÍ#@  ¿§¥À¦òëÒ¦ºWÃÌn–\lÓÂ̾Âvôóc#fcè÷ü=xKúy Õ½;Ìì¬ òë6mÇ… òëhÆ“;1€{'çÅn&k€üº[t£Ÿ ¿§…&E_·õÕ¯“üž–&Òó!<ßQ<ÝC˜b… ?€´Sîëff¿;ÜìS©@?oAô Я›ÎPOô{ZXkè׃z~ùu00ð ¿nËÔ²e„›}Ò™Nò4küÖM…ìÊÁ¯Ør³/ð3nÆãð3j¯/ð3dÀ;à瞀hî³eÛñ\‚û®‚'°¯›òñ{tgØ×ͺÜO±¯[È/áÀ¾n1ïrª}Ý àØ×=|b_·%î_Øç_ßvr_7K6^|Á}þÉFtc^pŸ›7ðš îó|êŒûá*ao'E¾)š¢Èws&‘¯²‰|’u$ò%•…È'K«D>&U¥È·$'¦ÈG’ƒÈW‡äDŠ|Le–È×5¯”ÈÇw¥D>Åc%ò)c&Æ0tCåãŠRPù,ð# ÊwK ¢ÊgZÇ‹öl”ÀÒ^Ú®©ò™Ëñ4wºµ¸¾hoÛ'Ü´g-˜?ƒööóR¸N¡Ï_f K§=³##¨á´g¿ <¯ =û Ö)ôù4s}àžùN(îíN³qo§v ܳi>À=›ѧ¨´Møþ¸·õ ‚öì_©ó"œ:Ÿ· zÚs/ Z‚öÌVBf Ú3Ën|О}¹×I{®¾Ó U^z€ ôY d]}W‘v ¡ï*I–!ô]é†wÜ»ê"ÜíÙ›öÏÀ=‡2t¸gupiˆ{K¡÷zý¢ð´×"í ]âÞó³Ô—ÌwMæ$P泉‚ùìS€Žoƒ™´@™Ï`ã-óY 'd¾kKø‡ÌW®tn†FV ¨‚*Ÿá ±1d¾Òôu„ÌW2š™¯4Yw!óY ¾6ùŠEÇгÉ|nYþ…ÌgÐod>CwPF`f F°(œAåó4¥h‘¯¨LE¾ÂÄI¢žåßB?êÙ–ª€z—yÓp¤@½kàN Ò»j¡uޤ§¦H¯O¹?Az—$’^­”Az•Q™$=®‰)ÒkLAé‰"Hz‘1ª|¶榮òHé*ŸýM” •Ï[r¡ò91ÒBå»Zêu€~¨|v.D»@¥«ÓqO•Ïk™¼œWo¿ù완ñ2ŸmÓÒÙéøz°·™N#سÔ€=ÕûìmIY{Þ‚³ìÙ-JŒÄ´”.aï*U"#Q‰/OÒÞuÈfA{v£ rN{I"¤½~C<ì­¬KØ+—B'€½¢ žm|ì•kIÕ¯þ%í•2£A{Ån5ªzÈrÑ%íÙâQpï’Ñ:_Ñć:ßµ¹üu>{ ¨+•βUÔùŒ°Ñ2_1£×Kæ3ÿž]È|VÛáÈ|²44>§+v¡ñÕ¦ëé_Ãõ, q°žWrýÅù×çk0߬÷??XÏLoÖ3¿FyÉ|žˆÛ€õª>d½ŠÕëÿJ…±Ä¾r¿±oÒ¹™Ô×ÞæNJ;rúÐ@oçÀ3”ÞNVcJo'%cy;7KÚÈܹ»öbR§¤¾œŠõ]w2¨¯Ê^IêË|=SÕ¤ŸÔgq!( ¾.£©ï¡¨V¤¾±t6 ¾û§™Ð·¸Î° oñkHè³ù0åз¯þõb> —ΗÆwdÕù,d-Ì·Gãäзoél€>‹Í^vå­ñEÝI}þAœ´rÆ›¢µ·¹Ó§?8ºQßsõËõ=W¨(W°ÇÛ®Ô·Èçv´ÛDNŸ‡ÕÀHˆ³Iæéî|†«92rúÊóAyßsš…÷ rúì´(ÇÅÌ$µ9}fîÚ ~£j•u&õÕªt"$õY¿ |$õÕÁeF™ÔWWyƒŸ¿c€Hê³jQ¸qÔ×ò^GR_«,{Á¤>³XµSæ{ú‘“4’úî&|ô¤¾ÎY‰²ú–T^fõYPÛ„½Ó¾z4|Æú%W%²úz£‚þNsü\Lâs¤ùaˆhaðìÏkþ:e¾a)ø@W¦õ=÷:€7ÒúTÁ.žvc\'øù[l‡g”yúMÜçGc§aðl…¥•Õ7ùq£Á³WZV™Ôw³šŠ’úFz@‘ÔgÄqrß³‰~÷wÎ&× ’úDUðw6S£ qIQðwÎÆâXôwÎD¯ ¾içò¢¾g¦Á„B¦ôÍK‰€Hˆ4WúÜZô‚¾g¢Á5RúÊ–×)}šRú&NJéÛLm!õÍ%ç‡rúú‡»ó®2B3§oÐ@ê³M°òál΃~‘W¥&ú¬%½¦žÒg‰7@G¤ôuN‘H}s4ArúnR* ÏSÒ(ûE>\æ2ƒú¬”$ž8PŸ%âÉeJŸVWJߺtp$Ä5)¸ ¾ûùâûèÔgŸaXZA}s‹n@}–Á‡ésúŒÏN‘ÏÏx"ßÓR• àgãö?KÇ"¥o±4›rú´‚‰rú&k·+§¯ã ð3Ÿ ù,ÀÏëø@­cJoX‚ŸÇc_ŸeÄU 3â.Š›ÊéÓœäw?Œ<_ß’d«œ¾¢•Ò·p— £ÏèÅŒ¾›˜}v»"ï}E¿3újUâÎòQFŸÉ*§Ê7,[¢¼ìv·cŒ? ¿Ò͉”¾#…2úÆ|gôui3‘Ñ÷Ü /‘ϳažSFŸX–}[Ê1D>›íÞ/î33~ÚÆÜ”k˜Òwo%ù!®ð`Fµ9¤ó–~ æ[ZF[é| éÇd>7G¼²ùÜK‚‚ù,lg ÌgSÜuÌæ«TÙ˜ÌWi²Êd¾ÊëÂd¾N[ˆ’ùª$*&ó™@  +H,ÅÈå«]†d¾¢Œ_&ó)_IÉ|6?¾ÈŽŒäòÕ!p â3óýbvÓ—ñÙûò#—ϬYæú \æ™ËW$b2ï9oÜàÌçë¬KK資ú- Ï4Âd@ŸÉã}ëy{Í—Àg—Áì=ƒ9±pÆ€>Ï%Ž|>³ÔðgrùãOW¨þç{þr›[~Ó6Ý‹Dü°raŸånÚè'{ýù"cßO+[6ä­_?‘= $„g¨†;×yªÙ’]±M]©áìʪ>ßçYeËÑÚ²+6]U{Áq^@µdWlSWj8ºúÇÔ+³O__ËZzÞŽ¬MUí‘*¿ T„ZKuÇâŸõ2œi*TõmƒóŸFùµhÛ{«ßçŸ×Ç?mâë›}Ûî'õÍþÌò'¯¢oïÃ_ç¥vlô'Þ¬¿ûƒØ§ýùIìçøWû]êÂo²í[¹â7ù?ŸA??îuÿòü‹Ë3¹üåÿzže þËÿ­ÿüÿXñ¯çK?~ùUÿúïÿò|ë3«ÿåÿ}¶3‡ê5~ùÿþÅü×e[e3{3=ÔÿË¿ÿË¿šq\ùÿåÂl–8Ÿ©ÕËyÞÈga¶g>…Âlö¯׿X5­ÿB‰³u«[­¨¤fùŸÿ°.›mtÔe›jÌÞþ¦}«Ëö>ê²íÖ5¤û{]¶§í?ô¯ûI›ê²•߯Ëö Žý2¸µ6^ ý¡4oñ¸ý02~'oñøÂôäܵ>ŸÅÿá 6š6yëÞ€ Ï4c]]Ñâ1/¬Wz´8x=S?ûëŽøŽ ÈŠ?¬Yµ¦w±…y›a©GƒÇ°¦½ÐšRšs}­Ñ⓼ÛÎþ²½ž±Oú­€Ž¿£ž9”Ïdo›œÞ›ØE¸--n¬hqY÷6á¸{7¡ÑÙ: ö…­%qü¸mÅŽ½€j8{í-ñ3,Þ/Âp¾ü…_Ë7«Wë¾ |F³½õhñ•¹‰Fñ½FbN¡‡‡mòë‘U}{v°øâ,Uþ¾£ÁA׃ќqxHʰmÇ$ ÓI F?ókAî£M¹v´ø Ý¥<“ìzÓ^±lE;–µ8X…ùkèfIeóUôg8O \„ž°^}/XðÍ ù q´ØÏi¦‰¹­›‚CmK§]~pèöVÐcÍ;¶ñ#¹¹}Ç&>mÞ–ÜìØu¬·¡–hñ‹lvØzÙ± kѸsÁú©L1wc³CÕ+8Û¬¸ö(Ü•î kÛmk-¼v?u\™tENp´xÃté3Ûc|ÛÄAû9-®qK[­aÛ¡ÅFsª_#Z°ÍöÐWµøL@O ÷E½;qÅT¼ !Ë•êE’lm¼4/Qo©Ø¥{5£§*|n«÷`^¤‰m·ip½Ûü§¬^Pn_Á¢šDÒdýmW™°²]i‰½üXõò÷LµG.и¯Hý´ÄŸÕU _) —Ø¢K•>°Çì¾™°k‰ÙÃy3ÃÊÛÍÛ`!› «Ç^b›Ûm[ÕÊ;űmö7¥)‹Âû-»°˜ˆ']Û–V+.T_•&¶©^Ù¤Zá«дgÍdŠJlÓ½bF½·–ðºOÕ †`=‹±Ú(¥ŸZ|×^8™9öÌ­ÃêÎKT‹w'uµêXéÁÆP£%‚¢þÙˆÒô¿yp#ñjo&TÌv™°ZJ’÷žó¯v˜ÊŠ'Ý4|ãÍ’}øE«ö: y¡G¸ZÀ5ž åۋĶ ¡ïö÷PõÊ—q6Ë‹UËYcš  «¥£Ñð9,æZÍ>‰–â«6W¯(k¡¡Z~B¸Í0ß„1\©KÙã#îvß‹¼–Dµ,1˜î¦W8¬«3©ß†`3þe+(ÍGBXÕËGV/§e ¶~Ò²}ÆEyñÕÀ«…hðÄŠjñE¡¼\Fµ SнÒgµªç®#TËÜAàiº¤Ú«’µ—P©.UÂV¼ìw®½@Ôa¹œíÝ@ú¶1Ø&,ÊEx^faónìí»l›…â5²Þ~¤…Ëy‡Ë¤új±Sw·å±“¯cU-Û [L?Oo)Ñà¿E5C`m %{q{0(´\©0Šëé‹Ù 7«©y bý°^ê ïBÝL¯°R{q[ü0ë6žÖB#œýÌöâ¶Ø_ÈTöm¶·E•âI°o³½¸íG@ƒ¡ZD7n+¯¿ê£„ÓÜ‘ýŽß?ŽeBüÈñc[PÍ^Û&ÝDz#o¥Z ,^q¶„Ò*ÑM¼¤=)ÂYé•³Ü {m[¼-^§öa¶w„¥KÄÓmæâÇbí$û2ÛkÛ‹Å^·/rTÝê×fûJVÏ&þ£XÉV{m{¯ÖGµš0Ão«ïÅjÕ\ìµíKHD‹-eÇa‰èj({mCõòu¬ªäZlb%7lTª«}•/¿;ã9¨öQ¶÷¶OBš·ÜžÛT̓éo¹jþ¼fÇî(YZ­X‹½·íVsu«úJ~(xa«Y`ìÅm×ÁïájË(Ù‹{Ó~Rm%{qoÖ©¶ŒÒjøü mņ_Ó]-ÕØ¶Z9ž;v1etÅ {¨·Ú7Ù^ÝöSàÐËsmªM›jl³½Paµ4 ÿ2ÖÊGµ,!V[HÉ^ÝfPí±Mõª_Õœ¤þãV3ÛØ»{/x_ª-¤dïn³bõèÇ–‚òcafQmÁ{yïë›Tû._x}žS«¯eUMÕrÉ«Úw¹øŠÔÇjæêÏáÑ£¶Xß¡º3Ì·±Õ”ìå½WlP]ñµ³ó?}!«f~‡›[õ áÄ¿zíZ =ßÛ¸¾- k63®èfzé×§eq›Û?w>f‡€ F]cÿlQ¶7õÝL}Žc/è³MNèó;社ÈçA‘òy@È¥Ôâƒãò@>Ô²:˜ïŽëp0_ä³È³H"ßÄ2!ß ¤Jä»áAHä»ñJKä#]ÌkáÁ|W<+óÄ’ùJ\¸ƒùGó]ñãÌwÅMr02’ù¾sÉ|v,G32ßB*t2ß‚2™o!u3™o¡p2Ÿ)t/æ›TñÄ|Öâ˜Ïp×B1Ÿµøm#æ3ö/±˜o.øn}Öâ¿„ ÏZü9ô_ >¯çêÛú¬ÅÇ%ê3löW±¨ÏZâOê3nŽRß”¥”Øg-¡NûŒ­yÀ¾¹™@@ì³–ðeû¦_Ì÷ù”Ñ¸Ïø;Ô/rŸ)ê1}÷i>rŸõ  î³Â"î»X]HÜwÈÂ⾋S6ßÅú}?sPD?¿‹Õ ~?¹ø](0(î»8“÷ð·Èï"Sü¬àЛü @I~önmH~å"s’ü,3!ö"ù™³Î/ѯ0ßRèWXqLìWP¥Nè'Å_ègÿ`ÀÅxƒp•pö =ÆÌô‚ò@¿Ã6‚qºÞ/AÐã–'Vó§íýPqëâ'P ¸˜Ü"}ØW½üs9ªÔ–,håÞ à·:Yp#§1ap#GP0È|©„ÁMÙP<¸!~%nÔå ÜHiI ÜDNÜx@’÷ˆwtò ¿q’¹ØxÒàFö²hU&’}5Ö7¾ô ƒ1»„Aœm²àF ÍdÁ s±XpCJMÜ#dÑdA¶$ n”/Iôå _òŠiò´´”ÿ†zÈ3¬º/ù¯½QË¢ò^¢‰‚x¢ •(ˆåÜ“w,• h[8œ m¾“@pc¦” È»(A>¿Á=>ä¿I 䂸±Œ›âà@BLr ÕµäÀñYV,9 ñ‹ˆ_æÀ@J¨ÓÆ.`@Ý2K[ ȤA2àTÍy2`‰ È»Oho _  wÇæu ú _ÚŸ~p! Eô߉˜×Š ˜‡æ‘È€>ÌØ èÛß½Pa0àÑ<ú ÌëGôßéÇ€z+ˆñÃ}ƒß€9" îWౠз ”æoIÌõls›øbðþ%ú¡Ñõœ óW"ú#0 ˜gGÌ+A<úæ¸ €Çùó®!æóá›óàÀøÏZêK´–ø½Év(t þ›Z¬€ü7µš$ùoʸOþ³–pÿü"…Vþ³–¸\ä¿©úNä?›«…€þ³†cÿ|“€F …\c@•­%Nh-A\@kˆ¨#Ðâ½ë€Žºê€î’Šm€ÖˆOœZÌ8Q"ZK NN.*ôu´½cg µ\§h‘îPg€ûîzKp$ÐZFìœ\ûFh-퀊³ }›ÿM– ÿÉx&þóm‚öÀÇ6à?ï8¶1þó]^üçç€ÿ¤ ˆÿŽnÁÞ@þ;Z€Ö  è=‡2ô–æ±H€¾`ìtS^´½%Ø2Ð;JNêæb@?Á—˜§LôŒhúéjàq~„@i-‚À‰4,1`$vèû­¥¾p®ðgÿn¹¶CÿóWô‹ùZÉ“ùäæd¾…|o1«]%ó¡ªj"œNI| eK‚øÄç$>›sxŸB>àOâ[ÈfLâ[Qú"™oÝßLŸ]Óôyǽ|˜>ßÄ·`N9ŸXYáÿ`4:ä?î•ò–áMùïŽoð!ÿÁWxȨtÈ¡rÄW"Âp _‹Ž_ŽÏþv|bm·ù°pÖ ùüåq ÞwòA¹:/æ€ñEÉðyC²­»'|šéöDi”´{^ˆ´vOd §Ýó‚qëð{¶x›¤ßÓ$)‡Bù=/hoé÷¼¸¡üž×ü >úQÓï);üžZ,D~Ï‹ ïò{^\‡U†OÛ+DF> ^’iø´ ñhøTñx …žeø,HM§ß³p ]é~…ÓDé~öÖûq Ÿi] 3É~fÊ~‡”ýXi"e¿ûq÷.I²óÈ’æ¼WÃ…àýXG® %=¹-r'µÿ¦ÁTÕ@ÈÌógeIWßÙ $Üé$>¨šÙÙo#‰d¿Ì,…Òý2ó¡„î—a’ð—Q>àÒýÖ‡îW «I÷SùšÐý£Òý˜áÖý\úî'!Pº“_‡îG¼”ð—™#OŸ}ÈN^þ23&‡ðGÛ_!óQøc}¢þ8Ñþ°¸„?Šdþ ÒR»ðW:å9 Ey?)ü~!ü%¦ã¤ðW°­Â_á§%á¯0 WÂ_a$ hþþÊ‚n á¯R¥’ðW3“YB÷³ÄôN_Ôý”±º_…¹U²_å’Zº_•4Hݯ.•Z†î×r$(8ºŸaü¿ë~•Œ)û5¥ìײŠÇBö«/è;Á ÍOÉÎ¥ùµªH]h~MUƒ¨ùµ) „æ×è”æ×˜ƒNš_ Ó‡è׸ !ѯ1÷„T¿Î|Â’ý:–å!ûuú)$ûµÅ>ý üIöëtZKö댲–ì×™¢F²_gB É~Ê€)Ù¯3#»d¿îªPý:3æHõë¬Ðªó›JõIŒÕoPý§ê7øqIõ0Ä…ìG[_È~ƒõ…H}–ç¾NÊ~ƒ™ó¥û ¦Û’î7(“J÷›L.Ýo05±ÏÆ™/Ýo~[Òý, ÄWP߬ŒNê3‘Ïe¡¿/û™„ìRU¿Có™Ñ æÌw.Åó™È ˜ó!úÅ|Gˆö>`¾9Q#IÌ7áVòYÃvÂòYíg`˜O…¼Å|GšvPóY l›`>‹*p¨"ó¹Ó}¦Æ|SžB2ß©Óã$˜ÏI>,˜Ï´ôùÒüìgâG‘ù&SãŠù&w`Ä|“ûb>+“º\ãóMîoˆùì «ã˜ÏÆqå’Ìw†ùÙùlàüb>[i»ÒJ曬°+æ;ùÂ^ÞOûõ;‰ùNZk?È‘ïd&{é~6®C!ˆÏNíŽ[É~‰Ô/Ù/m°7™ÏÄu¿#CöCüÜ_HÝöBÀg—§|Y@Ï\.(¾Öð€b=|y@QØø²¢vøeÅ6Ð ž LýO! ö..D´Áŀ݌¿´›ß‚·ÿ¦/á6›Kø+ìBøÃcóRþP-óRþ< +„?hÞ¢@cò2²9@G <1s¯À¿™(Ðm_Öò2žx¸CkÄ@[øAWh-ûøg-QH ´õéY5Dà×¹øWM/´ü+ðë šoý@P°Àh(Èuc  ­1Ï8BÁŠÌ=‚ÕÃA‚õÁ‚™c-HÐÜsI¤À$ع° ÚBâ¥ýÙ*¦½´¿³Šñ>DÁÎì&BÁÁ2¡à`¹k¡à(‡(8éƒ *Å¥Pð|·_ >?h'J± ßFÁ‚“epƒª^"lÌ{.äƒ!`p±«`p³æ–`p * ƒ–@ó¥ž'¬ãa6€AkIƒ‰gƒç!죭ÅÍ^„Á“NÊûÍväë@ % óílÀ -}ñH´%£ï“W@`ÐZüÛ# ZÈZ¹@— ˆ0x"Ô^0xVšž€ÁEàQ`¥»O€µcYª@ËÅóbÁSØÌ©-Áº2^.ÐÅ„´Št†Wø_£ß.Âÿ˜ ”h ”—þ§÷vpàf)q c»„†ûÿ‹ÌãÄ@»e߸“ªÆ}Ãfƒ<èÄ@š‚7kÑ(ú/)å£ÿ´£è¿¬4ÝÿSæ'qàV>ÆÿeæÞS`VE#ÚS9²˜éÄV`f]Z~«¯ màÊ´Hÿ—›²Ø"))"þ/R1þ¯ÐTÈø?s1»âÆø¿ÂÒŠÿËt©+°°óÀ‚l"Ág…_Þ€•›{$A@ÙE‚vC$d`eŠI…*%&IðT´ €öš…+(xœ^.÷ÉJ€Pp‹ê€‚8š`÷¤”~r>]ú Ïgñެ Å% Úïá'³´ÏD]•c t rkŒ$hÆ87ºŠÍfëñ|t€FŠŠ%}’—¶=.(®†ÐŒˆîlXQ…Ôžª/´ø×ú ´;Ùa‹ÐRØ@h” ƒ%êкa(è f’ÍoõuÁà©ãDF¨¥hÿa}ù?íÞ̯8Àƒq> ýŸqð&Ô^ ÿgÄGú?+üáÿ¬…)ÿç+p11x¸?-[š«m´¤[ û'“[¿ìŸ¼G÷çHŠ „ýÓWý Ú?s÷Mûg¦¶+ÿgî—öÏMø?-3 SýŸ Å”ÿ³àþÏ •ÿ3A¶ ÿ'vSƒ3ªD>srU68°±90#5ɕ̭X=–z'kör-E-ÿ¡>WZ¶ÏNq˜:ýrÔŸ'sûyYÑrå:{Ÿ":ݹΪ•wÎ÷¥FK Å6 ¥†k¨fÙµ×¾g­–ŠmJ ÷Pö‚dp¤¥–k(´ÅPlø·'s³Ô˜Ó>ßß’¹¥ù÷³®y6·rghûLËöüsÏß²¹íîZŠ­©üD¿ÝÖ‡HªõÛé±Î¯œoëÊÓ†±îx´úi°_3‚Õ«·ŒáM M÷SùµGLùóe5÷h.$d¨Éƒ“Ý.u.'Û$°Õ:OCÎnÒ\X)Ö\’›4Ö…ÕJL“æ¸b«ù”²ì¬ÅžEÔò×´åÎè§Å&ñåL?Õ ÁÅkkž]&Mï²è¯GýjEžg}ö´ê³ÈWœõYrV«Ó@ƒ½ŸÊ*,Lä0;‹ó§…{x4«Õ\8ˆ–°•Y­òKBð³wé ³n~}e`‡Í¶•üj¦ï°%÷3Õb›0zTuÓl”äÕª+tØ:ŽVR­ÊËá3$\zÖ›Ø_ËÈ·RkÁþZ^øZjÅþñ§Z}‰ gÀ¡±Z;ö× Œ‹µì¯~½ub­,öYØ_«@ùZ·ï¯±Ô`m n Ÿd˰Z4ì“ÕV`µh(ð´ÀjѪï×VaµhðáÕÖÜjAɼZy‰³-Ü6nšgYåpÖž÷ÌV‹¶©mÁjÑûXNŸ³3ëJݳ\‡Ób¸o¦ö £…íËz—£ÅpÓÓŸÅD}ÝÚ+|Ò@í >‹SÿÅ:l É_j?c0ÉÄóÁg±P)«öŸÅBž—‡%à³0ï9ÏHØ^[`Ô:2ö×,#à¹ÞQ¸¿'pµj¾¿†¨­:*Òk%ä?¯£!½V F‡ÍÂpø\ •—8t–ÀëÕž“‡Î"ë±åZʪTû ;!“@=RÈÄVÏÆì<ϲ‡ôÕ7§ê Ø^+HãVmcÁ™~æÙ]«ÀhSí>p8ÛN“Õ¾°CgL£]Ï>es÷¯Á6* Ú¯ncw­-êJØ]ã¶g=IÕl–‘˜õlOØ©ºW§«vgw­!z¦Ú–ÔÙ^ks8@}’2!1Vµ= ›Âð€ªz2z-mô˜Ø]›0ÃV˸ïéµ°IQQjóiá{íä¶:‰§`_«'••{Uߨ–>ª {Òòì®-÷Ö]™_ Áu7æ×‚xT-‘‘ç×Â"ºîÁüZü1ìS!ñd½:;iÕ ?üZ¬ã^­¾„ç×Br¯f¯fæ×:?±f¯fϯU|?µÙ«ÙÝ'ͼ7œ­5Ë••ý˜ê[k–¿ê˜àšU~²G÷©W¿OKg†-$li ÃVÅæi³ÊO¹§¦_ßò­5ËÿÔý\@Qk9ÔÍ*Lœ [UHZḬ̂•ýyÙìÕ|2le¤{iöj.È>Õý¨Š [ÏQçeØrC†-ÿ«#ÃVC4Z³ÊOöì¶\Jç)ܬòÓÙX›ØÕiVùiÚ I šU~:¶ªgˆlå”ß*VCįÍ*Lœ[V<áŒk¯e{t{U‘Ó€[–œà4TäךØiiV÷éä×¢‹¥YÝ'{rÛ­²}ÜüZ Q³ºO'¿ 5+ïsòkùÚZ6òk%¯{Þ¬ìÓsCÕD7j³²O'½ÖŽس$Ož?Ê?M{+ŸôZ¶·é‡T¤×ZP[ZmH¯eïÐsuVõ©ž„P°a4«útÒkm¼§›U}ê'! ͪ>u£Þ kl³ªOÃ7Á:ÞZBz­ŽDŽÍª>ôZ4­4+3±mšËÖfoædç*HsÔÚ©¿Um?õ¼Î›½˜óò.gIÚìÍ\,óU…¼×¬ðÓõP³ÂOÍNUá³iÍãê)îâ—³=ÉŸ6«û4lž®ÈfuŸN’­†EU³ºO'ÉVC¥Ÿf•&N’­6ü1ÖìÝœìTEÖ›½›=ã{ṬºÈÆÌÏ%[í§bXÉ4«ýTí\ÝãšÕ~j6OWr­Å#Õ*˜Q¬ôÓ°3 h×mœlµgš~‹Zé§i'²ÌHç ¶2KËúdÔyiVibŸ3Á—ÛìålÏo{žh³·s¶iÒÞìí\²ç$ó¯ÜŠ?•së@Tm €zte¿À}"â«mcŸ9Ø2¸Û'Z‘y¯ÙvØ4i8oÓ“T£a´yêo=Òª4ÓÔ×™gõ·R3óà¶3±|´ocØ<¹jö~~àÕª»m˜<Ì?ÍöÀ“û€$r ‡üßè¯ä@®¦;QîÀì &¾™| žôÂx้'ôÀ À‰dRA€“Ëg `“8‘¸ pâÛ´³ p>D€sƒaD€–ÀÒaH+P §'¸ ÐÇ~p%,b„€âZ!àÓâ³.xç-¦~ÝÈ .!à Ðò à`©"1 ¢Ì'ÄÍû8ž(8g>Pà ¸srÂUO‡5Pàál1`à —ñ>À@#ïì4 <.§Z‹ßÄ@k9?eaàAo?j2Ð:céE <Že#кâæ!ÿº@𸧠ã¬áÀžDÞRg Å’ ¨| Á¡å$Apln¶û ‚fÌÊ®Áç%?œ¶H‚ %½P 2™y°`B•á`AæE L(Ô0h- >‡Ô7 &Xté L€FL¨F,˜ø´ f˜R‚-Q‹ó"Xð„føÈ`ÁÉR˜ƒ¶õ>€Akñ¯œ0hÛÕÙÏað˜Íü À mpøÇG4ûÙYÞÍ~Ö_4h-~ÉÄÁɨÄAÛ'ñ«!Ú®ˆ¿ÄÁ™7 4hA>MÒàÉÒæÃ€­Å4h ¾í@4W›ïÉ‘OmÁ3)Ò ½'$)<æ‡?à ’½ Oj7G;ÇÁ“ÇÍO<–:?•#áÙ÷õŸ8ð´œÕ‘ðìáú] &<6Jx€ ë° Ï0~5Ž„g?y{GB·ëú(ބ׹„gïÚŸ[@ÂFá ñÕö¥óŸÅL(UZ@¡%\/(´à‰c"2Ço@¡YßP¸±UPhù{Ô…›;¬‚£…{Q9$j×]Pø´øšIP¸‘÷2 p#RPx‚¼P¨€`Bá‰!vePx¢WË…æ½÷MuBá)Yã¤(´—2¡Ðã,¾ O?7 ÐÖtã…' Á‡Y,»S±Œ"ÚÚÆ‘+±êe!2¡]quºžâ8/&´•Vw¶¤,XÊ÷ íÜÎi’kÆK¬Øà•.x*_D¨"Ó¡ šÑÙŽº`EUäЬÂ`%ކ0ˆwuƒÕS2^º oé‚1 uÁÚ>uA‰~¡ zŽ÷ñbY°AÈ”0X¹p•0˜ÆÂ`AÆÒ3 % ZA:D ƒ)vB¬¨ ë…0ؼÆnà`CŽ‘ÀÁsqààó-㈃~_ îO´%éׂ¬(بZ: öÄÓ[§RHìÉŸP‚, ,ØPú;X°ã,ظï!lÄFìîc ìØC ìG- ÷\²P°Á.‹ DÁ‰Ô4‚ F à‚4/´Ä/o<•Œ/œHE ¸˜ 8é'HÖ ÁI’ ¸ 4J‚àDC€àìØ|ZÝ+ ‚2F€àâ.döÁ…´@pWÒ#Ap#­v€ 3¨>ïqè–Áð¦Áåf€àsràAù•7¶µ×¢‚G\Ôœ‚ O]qà³X÷›–Ê`ÂúS x-'‚Ç4ìX\¬ø,\%Q¯ ž¸Š›m`4€ý,FH‚‹etD‚`„A‚'q¯Ë~ Áèçl¸èºÿA‚¿¡ AKÍs®G$hžh‡¯ÂÄË ’Qð8¾‚Çš£  å¾F% *ÀH(h5†ê ªÙ ínõyaúFÁ%-“(hj_ŠOÔ Wß[ˆ‚Kp´Õ¥SQð˜¾}d àñ¤û倭4tF°àê¾  ÚïËÑ…(h~€—©„ÃkÂ6êd¢@+ú¦Àçqâ >Q`ú!(°Ób& |ú8  Æ‹×ó$ám…ìîDQàX:Ràì4‘’w{ ‚föµ®(peE–pÅ".J¬Â@sÇ¿1pnÀ 1pNø=I‹*¬(оg1R ÓN‹íþu«(pºOéÍJ—(÷ ‚Y 0(p#\'0e‚÷›h†¡6Q{Ó9ÓÑ&Z$÷Ñ&Z*UCÚDŸU šIøíMÈG%´ú¯Î“àÀmôèçnnq‡I4I”£I´a’ 9ËKTu_’ ÍÀçDÜò8’­Æ®7Í©;^$hÙº_ Hp÷Å'AKà„I´b¹·Côø^!ãí âÓ&šö ‚§S@ð|Ît Ass;7“­¥¿äÀÝø{! n‰Â$Ámí/<µ„¿­ î¸-¢çÓòûœ ¸Íz[D žÚQ> 8оçfr }~þã%n–¤n—Ú¤Æm}~ ›/äÀ]=Ÿ0p3m9Ð ÝÞx*(;)í†b <Îw·ƒÍîŸ01Ðnôê1ºœBíBÂe¿Ù²¾±<¢tYD¹ú‹(T©pˆ.(ká¥]OD¸’äÁÍàxŠ—ç ´§·(Dp‚"DpÑD*  ^@èk !âôă”;$¦LÅŽR`b›¤@f –˜>ý¡Æƒ¾Š )È<ˆb¨"¡ðŃÈ7vñàÄ*_.PðdwúºHp1þG$¸ø^ Úš•^QdàÊ  ÒR"4ð-’ ¥FužA ‰ŠO²!?HðäWòË Z d< ­|û+LÐÖËÐñ@‚ .P` -„}£K1‚Õ·o#D°¡˜Ž(ÐFÝïÁÆ@SÅ"ÑrHœÈÁŠ’lëÃjˆ…Ž1‚” lHö¦ A‡~EvÁ&#+Ý ìpÌD€à óU 86ðX 8°T œ´y‹}Â’Í·ìú¥ÀÉ ¶Dú›+Dö¦dØ® °q#Q8Pò9 °Ã +(Ž øœ»¼CL>Á€û‘bÀ†»F8a ´Ì‡Ž‰DÀ.±Ø 1˜éûŽÎ‰€ZSG§'„£%øoÒ’)œ(žØiŽþ)Nns ×pNð•p!²8p‘;€{`—#TœFl0#ŠÿÕÍK,opR›ÿUXöƒÿìÖzó_AØHðŸPòßBIÌ@SàÈò«ØH{Ë€Þ‡Ø!AŠÿ:²Û‡ Øa C(‹„ÿ%ZlÅQÕÁ4HÿwÁ„ ˜±— «†Ð™é:„@Ëtòr„+;ºKl :à3ÉòÂ?ûÖ[l¼8Ê€– Øu?Ê€–BÎý–T뢨G%° –s( ²—È4x¡6C ¤Þ)%pvL)pÂoR`E¡WIudB ì !“Ø‘8?¤@ûuÜ1‚þtvÛ&¥ÀBWR`G¨Ë ëNh‹°$-ÐÒ|8R œˆW -°á¥Z åð€Ôµ@{d¾¡&ÒúÏLZ ]¨·H ôÔc!nä^)Ðæé”H)pbùR ~!RL )Pñ~DÀ„ —Èø\IÐ $– —Ø‘:¤@Û{K Uþ.)0a’Kaž&¥Oëµ!´ŒÉzfÙkv17û\‰Ð>;ÅaêôËQž>íçeEKdû8Etº³‹õ³]s_j´\C¡-†bÃ5Ôh+]ãàÏä4hÿë:|Ú‹‘Á’þ¡©%a›ÆQÿ=eZ?&ÕñOS¦ýHmæ)Óêí3÷Ù¿%eÚo·Á(žÑ<2Wýv3ú÷îű"Ǻ“¡q¬èűî^KÉÐ4Ö• Mc©—ƺzi,%CÓXW24¥^ëê÷?“¡q¬;š~ªêűþ•”iý ‡m…ü–2mþ£”i?¾ô_S¦ý^?R¦ý½~Ÿ)Ó~¿ÕÞ)Óþä±øËóçÇCðoÿàIvuúƒÇé¿2­ÛÚÕÒ6þ’2m,¦L{þõ?ô¯˜2íù¦LË•IÎ^YÌþyÊ´÷9"ZŒöŸ¿¥LËjLÿß'O{®Á×Lžv~eßßÁþ ¹_SczVU¾žòž_OHñ½n_[®4ûM÷–|=‘Ô¡?”áÁ×^ñÞ ‚¯†ÔŸuò7¼<Ýj¨q½°¦ë­3øÙµ{ ¾FéÆgÙÇàkÁ{[ ¾ö¼OÃVÔìÃlÆ^#­÷ÄØkìõž#öúl“u»Y½l""{¯{íëÞ{ æé½+öz{—±×>‡>|åvï‹Á×Ów9Ÿ_#<¥÷Íàkd#ï#ù[B˜~;l ÒÄsn˜-˜§Š¶'Y f‹Ô|_îY73øºùâºÁàkÏû˜ ¾F¼s?_$*^4´Ðp?}׺Ût<øz;Õvû?¾F4EŸf †7÷YÛ|>a‹9=^ nîõ{9¿"´¹›u£ X÷l—u«Ñp¼”ûIÆäm~Ôbð5¢º»Å|¯£6ºmþxð5Œý$ÞÇ??ÛòðàkDu³zðõ:kÿ~=ûþ¸ßô½Ç·¾:c¯ùYÙŽÑù(¸…ÞMÄ=^ ZªúÙv8›êH-ó´ÀkQ«¸+¤7œ•¾SÄ^¸ë–oÉ+ˆdzÍBÄÍ™¥¥RòØkØÖºICŒ½>©I{íá¼ÝD4½n<Ñdèuð‹‘×üùî…]¶A«ï‘×çÙ1Rbä5Š?ІÈkD:g)€Èk|—#UF^#Úg¤ÆÈëÉ>†ûh0Ü$ýx~‡žç¾ ÁH ~û‚ÇËÓ¿}Á^ÍH~{s±ê99Áo_`Î9Ão_P‡5øíaê¹¢ÞYAɰ…“ûå–?iŸ¯ n¤ç9Qä—ËÞg"ðúY€ŸWÁÈ ‘×L=ÿ´xäuM,D´y]‘k”„ÈëŠÜÙã¬~Ö½OAäõÓr°£TD^W”¥!òÚ"×ý¨¿}Í<×€ßÞúø¹&üö59ºËžëáRØ¥zZz]aVe/¥Q<Û¦£&½®xœŒšz]‘‘hÔ‚ÐkK9~&Q+B¯ ~Ñ£6”<«Èëù<{{mõNÃðÐë OǨ¡×—G]½®þöŽÎ»ÎS~Ø;º (ì<1GKˆ¼®w¶­ï‚²÷)Øh«(Ö4ZEèu§!ôº"A×h¡×L74Ú@èµ…›Yµ‰ÐkÛñ8×|¸Ô6÷ý×j¯èó¯¬öŠÎˆ ;ÛTÃ^Ñ^³)TFψ½nØñ–Pü<¶ô¼¹|í¹÷­¥!øÚöÀÏÅôŽ’g Û›£_s—t<ï%„·Ê뙾öÀ^Ð1…ð…a/h6œ3Ûûù<À×6ì}¼r Q7Ï{‘×&œøQ‘× RÛ ‘×Ífct¼nÄ]w”V¼k"^¿ q×rÑ0½ù<¿kKŸÅ܇þ;´·óy€TRö–Ë*Ïûeœ',„Jÿ8O('„ÊsCاè: ì}ã¤5¨Þņf”›÷Ëz#´ÍgeêãDZòaâ®'LGÃÔÅó†+!îz..ˈ»žØ­« ðšñøÃ¶…Ï#|bku˜Juá4 Ó:ðµÁ@ªC¯Às.ÐŒ/§ âÏ´øÜV«çäÛÓªY×?âãaA„·ÿ­z×y€o> «Þuà B†Uï:p[ÑÚåLK7çSþ§OøBEgrÀiñŠnö~ÎØ´~Ô¿’Bí…'…Ú }Áuc`ûÀ@d­½0¹. „”|a ²#^ˆÒL¢"1kea }ÉpçNÄEÒåèu¨n œ.˜Îíï©‹ñܼ(õL. ÌøEË¥º€ÀE !.Äò.d dòà€@kqP$®Áq õȧœâ˜xò#8t­åœ‰ 8XóS hd›}0ài9ó&Vô¹Á¯ xâKœÁ€Ã3šQÉ[È€Öâ°A<•í»¼Ø#Êw ­ÅçM<‰^8öú„À„%c@`B]DAàIÍ€fàB"É€À„X €ÀÛG@`B¡×€ÀZ&Ng>@`@zA`‚÷1 0!]T@`òhù`À4x1dÀ´x0!`!0'€0!p.ÐìANodÀ ÷]0 ±¸LÌ•ENI¬ž˜á³ ̈ Ì…-ÄÀ\ÈoÄÀ܈YÀÀŒ`ÚÀÀìyžƒ3òGæF|#r—<(5êE¹ƒ Dö¢ðƒH¹“I™ëQ`Ææ~P`†É(0)ׂéK ¤/80O, Åð%æåv† Q‹UXˆ]ÂÀ‚ßG``A$N``áÚ]-ÄÀR}ÄÀÂÕ¼0°¬…¥`5" ,ð3$ ,ÈrÈXa ³™ÚJÅŽXÏêÂ@lV–ô”¯@h.2P0° Îzp Äeu ,\9ŠÍæÔG4ýשO˜üF˜K/ äB` ¾IùHyqa`‘…V‰Óû+µm„µ}b 3É{b`¤}¦ã9pÀR8°„ ´X¯–‘‘¥A‚“[\"Á‰ôÏA‚[ó"Á GàD zàÄþià$Å‹'B*‚'jÅ‹ç"Á‘'–"A‚‹³ .Ž 2¯H \À‚ì ¸,¸Pö:Xp¹©J(h˜ì”´É©$hê~»IðT6ø9 žj~j à±ø™€‚'Ñ/,87b¨Ä‚6²—  Zƒ×0' Z‹<`œóÀ‚‡µu’G](x*Úí÷r§ zþå›7²¸ Z$•·™âL4hëßæ-›Eyðö Z‹ÓVfQA Ú‚øƒgÍüu± 5ì—$xt§—$xÇzŸÉª<›GÏÒÂõÈÅøëýŠ4xÞ/MОq¾$& žàeï´9ô—&8i¬Nn•,X8¨òÂA[;8ÏòÛÁ8hë7gâàÑÆn´çuyá rú†&Ⱥח&ˆ´ ¡ JW Mpó(i‚›dGM0#Kh‚9=) f††$˜x’`A哨ALž»$Áä/£bf_’ úHœ¾Ø½$ÁÉk‘$Èë ²ÄBÐ`ñgSÀ`I÷.Ep:0JÄ&Ï% "ú:$AD9^’ 6Öƒ3,7Aƒ¶âö£ˆƒ–bæë¦A–­ 2ÃÃEƒÒÿ„ƒ†¹Aìñ]’ 'hy)‚î$ "”ô¥ ¶M+KÌPGCÌÐ¥ ¦OM0s W0¸È‹‚ÁåÏ—‹Q3í¢Aäp¾hév.D!Ñ E×rh‚ÈãýÒqÅ—&èKúÐ ž¡ ò…¢ è!DAnÙ†(èÑ:—&ˆ·Ñ¥ Vž‰0h.M _À 4K —-± d° 7¦_’ Ët—$è,ˆ§ÂK„”'D´ØÅ‚üŒƒ=·Ó…‚ƒ:¢PÉ&.¤z&DÊ· Ä€@An= J¨»PÐÙ>PÐåï[tT¸A`襲…’ 6â.I0ãó IP4&Iv–KD$Õ…‚›ˆF,ˆ¹Xpá šLý–áÆ ê# –Ié‘(¨o7PS.„?ÿBAS^(ˆ ¢žÙ…‚M»PpáG(7ô…‚‹W(T ƒ}à`A¤ü¿X?ß@A®ªÅ‚É„+#ˆ"KWŒ ÷"F©Ü¯AÊt#Ø(b*F†ˆt¥û D®þ+DÛeƒ©½¯AY„"V=Aî…"Èø›PQ#æRuÄ+Hð#F°Q¤“ ˆ-ôKlŸ‚`EZ¼ËJ&b+ÅG™C;í¢2‡¸a•uUæÐÉ@C™C…u„Á¯þ¥"(þR‘ïR­ —9´ý0‡:ª„"H%4ÁM„¼AH/w¨7PDÙ Kl?̡ԸB¤Ûöv‡Î7 ¶D7(í¡¼¯ƒ¬¢<Ø}¨R±S<ØCɃm1T<Øh°¾ý¡n¶E×&y°¡’Á¥ zîÉÀÁ8•$AÔD IPRùCˆò‡rß-ü¡‚-ùC)z…?a/è¤Ü'IÉŸgâ8—AtüÓ'’_\Q8Ë ʯ/ ¢œ ¢þKùC]‚¹ì¡‹šœì¡¾¸Ý¡Î¼¡Â>r #Žo9°½åÀ];¼¡”–ú>HpAš¿¼¡› â3¥„Á-é0Èõ~ÀàÄCºC•HÂà^ßosè ]q‚âE‰(Åp œI‘‚È-zE âÕ‘‚L»|E ¾¬¡8Ø_ÞP¤zB%Q›ö´ëwb¯ÝÛBêlÄž°Ï•í³S¦N¿õçIÔ–esªû?Z"ßÛ”ÄH W¾±e™û<¶C©å m1®¡vrOã5kµÄPlÓPj¸‡²×##'}(µ\C¡-†bÿ=¡šÝ–Ó>ß;¡Úg~ªßþyž:³þ·ñ§}[ÿoûú6K”Z_É×>ÓjýI¶Ÿ7ø´pøyÝßûõv6\yuâHW~5éN¯Æ‘¢FzejãH‘] #]ÉÕ4’:q¤;OGŠÜjéJ­¦‘Ô‰#ÝYÚøsÌj>ÒXM?ruÂHÿJö5Û\ËG5ü/”}íOž§û|6þòôüÛ¯7îÇõ÷÷ÇH9ûÚ³Dùßšy­¥ÿ¶ýÓÌkÖéGæ5kŒÑ–þõ#óš5¦_Në™×žµoÅô¬ñ3óšµýOýë¿ÿÒÆÌkeÿãÌkó)Ç»cèç…¯ÎóØ/b! Þ÷uûɪ7LX4& CMû ‹ÆtÃäDþ”?KšSKµyËYtOËà\‹·œíâU`И€¨iIbAc¢,Ô³„ƒAƒÙÛ¦%sØÍíÞÒaИˆ|. „×OËP{ü‚Õ³†_‘ðmZižcИ($1w‚AcbóïYÒÑ áuÁžõ  {Ï fãVxÇ É)pžº0Û·šÏòzZ•šÜrgƒõYÓÁ ±2.pO4˜ŠãY ±Pðy ±`D_)¹AcaÓæY ±ÀÏB…dAÏ’ …Ì÷Ïw ƒÆ3?-0h,쓬ÔÝ a®¢~  Ù:†Ac!òYP ± ¯´aÐX€¾• ¹€ŸU&,,\ò,CaÑXž¾ø¹×àÐX0¢¬Üàа¬é-ph,d\ÙË…§é,84˜f}åy¶å¬Kó†åÛr'í³}[Î:òÂ*É·å¬Ï±e?àSìr ×åž_ ¯µUN­„ð­Ò|[nÐ ù´ø¶Ü©1êÃtß–;ÙOØ0Ù¡‚Ü*s@XYþk]eù¶Ü Ú¬²áÐX® ¯š|WîxšÎåÕì»r§å S=Ì9ò®Z3tð ºJ´ìotñ½v84²—¬:|[Î,LÙšCŠ¢Õ³Üß}vƒ°’ðá´T!¬x9¬Õr®ÌjÅqô¿m›ïþz‹Õ|W.†i[Éý˜¾{¦ËÕÆü†ìãßB›¹3n?[~zîEõÙ ¹³›BWO¹‘‘eõ\{§ÑŸM¹“÷ñü`lÁ´Ùr¾Íç=âOðJºO‹oÊY‹7ô…´ÕwòVi7 >Ï>Ònø!«#ç̱«ï†œØÑ\#UåÜ8ÊÁ¹ çŸ.ÃCê½Ïi¨ )7PÌs–|Ôêc´”9×è )7D²Æ˜H¹Úë¼ãš· ?óêpØ¡<ý²ÿó”^Õc{Ïö.Ó[rÁ.Üëûà¼OM0Øu\à1úVoñ˱·s‚ìç_ÜY¯bàs}p\ПÍg3'_~ªÕa°ÃÎÀšžÞóô9›ŠË¸Ü v(Ñ´,Å}zÞP2 v|ÒYý7Ø!‚`Yó…Ü'Çö¶N¥æ-8U_pØa·wÙëÙ-vnÂ[özΰd²’)TNøé²ZƒuÜÃìTá°ƒýaYr¯M5q_ì’á°Cê‰e•å¦7ø··ëFm*hèë”4CœªO+ÆÂdÙÚ‹CT^ÛÕž–³X{ù†Ü‘h}äírç(;ûÃé¾!w”ÅqZ<…ÈÑqرSñ 9E½n«÷5à˜>­úL¢ñìÞâ›à§¥ú¹ú„ËUé·ÕûšpžYY¹¯³Áö.6‰â-ˇٸ:Ÿ¶½ŸÎs~Û^ÐTŸ½  Îs6æws™7¼£OˆÉE‡wk &;¼švë&;3N¹z÷xž¯ÊJ~1sRõ–Õ”9Éï%+ùµaB=oÅmïè„ kŸ¦½£ÑP¼¡d¸ì8Œ½£ ~Ù[6\vxƒ‰¼=“›?I¾ö"ÁV>QÐw³±Ö DÁç ñî»PÃÅ‚H s± Rv\,ˆZ« º6p±à @ŠñBºXKï‹ɪÁ‚(®vÁ J©¡î]08ÉZ‚Aäµ œ“G|ZÎ:,hÐøMƒus‚'œ¨AƒsúC/hpNò!ip"Ú>hp¢ryÐàDRÑà„ƒ5hpB´ œp0 N—Açú„Á¹ˆ€Á¹È„AÈ8Á‚̉,HŒœÛŸpÁ‚“¬ œÈ1,hGë NTd œÛí^ƒÓm&Á‚,²,8‘s],8‘õ/T‘kÑàÙÚt° êƒŠß Æõeþ ž]˯‹•íV,x]Œ³ m6&gU° Ôü °àéãœ<»¡Îp`A;j;‚OŸ¯ Oƒ<;±Ÿ–¯‹€*´Cœ­ ‚§Å¯ xYÏwP7.­:ÀÏyϧ@<‡¼@Pq­Ak)gAmŽ ­ÏzàÙa ¨È[ µønAðì ûQÁÁälÁsvoqùuË‚Vø™û>dAÿÂnY°P½“,Èœþ! ÚSêë–K¦–HYЪ8,R,iYÐ?ë[´YÝ$xž~.ÞQ,ˆ•Y°BeÁRÈp” õ! ˜4$ w …*X!R H©‚EŠUÁh¡*XŠï[‡*X°P U°P¤”*ÈwC¨‚Å@J‚ÅWˆ! 칆$¨»¦²n#¸’ ¾7I‚Æ™uCH´q^$x¦ø"ÁóM:uRd&׋IJ‚ä’ nYI‚Y’ Ó9H,Ý IïÃKB´%•÷¡$X`Wú'9×ÿÖÉ{ãßB¦ŽÀ?š«„ óþ¹ì~Ñ2s\ô‡WËEˆÔ½è%n.úsü½à¹Œ.øÃZâ‚?ú.þÒ§)ÔZ4PL‰)øõ_ð‡áu”„@ëãF!PiÛ%ndÄ !PŸŸ„@]°„@M\B >?  lC´>_ÚÝp'ŠqÔ¹:àæâLB Æ¥ÈôdÒ·@“: ,ywÂRQB 7‡.S(n¿åÛ“¨q$êr$r§'„@}é퓸áà !p#[­„ÀhH½M¡®ÊŠ=ÏËÊ¥j(\ª†Hk™”@.ýC D–¤K ”ÿTJ ½\¡L<”@lÄ\Jà Z(%έIµ!N2¢„@lX_BàÄr;„@ÚÆ$R¬!P-‘ óRQUëRù±‡èÉù.! /!pÑ8*!pAè!°7V~¡n²¦”@lG‡/”®ÕP7QSJ "”@Ä_J _h¢ ”¾P¤’»”ÀM(“/O¡ËÊ_lC‘qé2†¦ÆP¬­.o(²2]ÞÐL=NÞP¼Ç/o(-íá ¥HæÐLÏÍ¡BV˜C mž2‡"áée-!eEÅÌËZÝ#ÞP4„7´ú#1¬¡d“°†"êÿ²†R# k(²¹]ÖP,ÛÃJZ k(òz^ÖÐJ®”5”a E>•ËJ©UÖPH«á mÔïä m¤=9Ct9CýOÙB¶ÕÂÚåá íð‘„/´óâä í¸˜ð…¾Ðïdß à†%(L¡”(Ã:(-Ê [Óe ¥¦Ð9>L¡ƒ$*Sèüa 4sÊ:(èÉ:‰m2…"†ý2…"ç2…J_¤)Ôcp.O(ÂtBÜžÕ7DÀ4á—%5/CÜØq OèôçÈå EjöPÍTëQ¤a6dÀ½8eÀ-í2 åTq𤠸‘‘2`´P”ñV2 •ˆ7vCÜØU“¸Œ2à†'-dÀp‹õýJä#p·%ôÜ´.&RÜØÔ½d@XÐ.ãJDŸKÄFÍ¥bJ!òË £PÔ}2 â_2àú!R;vP7DȀذ¿dÀE±N2àúðƒž›-”M2 Æ‘ ¸|wÉ€‹²¤d@jÇ!RXpA•pû³0d@ŠÒ!"/Þ%b}qé€:J: úü…„k—%ôx/K(nËË @XB}Ÿïr„‘ ¸ EšÇÌ9‹ ¸°§ ¨ø6àzk€ q# ¹?ÍcóŽ \È€È”Ï ?5`àš¤Kb ×™ œ+8™¬®è@|ëWtàV,``à™‹/0Pq~#Ò7'…Hqra`Y60é÷ƒ+¨%8°Q¯â3¾8i/ìÔ낌IR dHJ€ Nž|_雫RäoöKdLJ€ %^ ˆd‹Ò ¸ÙG$ˆtÍ¡&î§‹‘,HÐb!œBw$pveŠüÍ®±HLØ× !0!ņ„@šôC´ƒ^ x‚¾.<ñ/Gèqÿ¿¡Ç¶ï}(Ú©¾. œ‰B逩҂™#}ó|qàÉÖìGÕÈßÜA}ÌßLÿ…ÀD)NB`ÂrT:`êÔ ©2St耖Jø…'3ï9J: ó熘¢%Ðú¼uÀä¬BL¤oÉ€¨* g <Å–¿.´†WlàÉíHJ0ù;84@ËÁë„E 0Q%§˜<`ÚÐ8¤&ªFÒ¥ui€VÿÍÁ‘ %Cv(¤øôqÙH`b°ª4ÀÄ_¦4ÀÌÝi€ñÒ¡fz¥FŸ#æLࣘùÛ˜‘F=D@«åðBÀS_á-æL*EÀŒWˆ€9“ð(fªDÀÌ™DÀ\(ÍQÌH¯"`fT)UÀ\¨RÌø­JÌT¥%fþz%2iqˆ€™QšY…-DÀ ø•˜©ºIÌo‰€Ì—* ªð…h&ïB0£žJˆ€¹BK¤ø4ŒŒc5Àì 3CÌü1S̈‰ 0SÈ–È2Ù!f†mJÌôKÌR)ZhïCiKC´¼ZT3bÖC´–· hóœé¨æA¯'TÀŒâ²¡Æ0T3Á@*`Fði¨€zh¨€:9UÀL«TÀÜÙBÅCÌà©€û•¡fú`¥²`^¨€6°·PÔ<%æÆ+¦ ˜i• ¨ ” ˜aa‘ ˜×OÉD8D¡fD΄ ˜±z • C4ïŽ0Ã@2`Fú¿3}º’óú~«€f?r@£ ˜·or† ˜bú(f<æC´ §oP–t@–{¿„@”¬!03^B ªî…˜± !0Z(æMOB`˜D)b³ò!«\B cHCÌ´ŸJÌßïÐ@kðƒ¤fü`Bä´.ÐåÄÐQ®÷ÒÕ‡:`^©æÁ$]J¸–SÎëJ?õÿü_9?ßÒwdûõ¹R§}vŠÃÔé—£þ<áZN–|ú5¾Z"Û”·H W>²œ,Å_} Å–{(o»†BÃ=Ôó¤ßå5k¶\C¡-†bÃk¨UÞ­ò9Ì*¯AÖGú·O¢µç¼ÎËð_I´–ûçY{–­œg­Õþ¿šgí—ûú!Øñ½®ûúo¿ßÆÙE—«ÆŠ$jë΢Ʊ®^ëÕ‹c)šÆºò¨i¬èűî^K‰Ô4Ö•IMcE/Žu÷â¯U©Ô8ÖKM?òè…±þ•ŒkÛö/籌kò@ýÛçÃñ—Ççß~¿…ßÔ¿sŽô—3®e[]>K©_²®Y’±ÿ[ÿú¿eDû‘uÍþŸY×ú¿%éÚø%éÚþŸtíùþÌüùÅÀú‡Ò1+<-­3²~¡¥s/k#Bþi™õaë },Âô+BÛŸSN½å¬dr*§&âiÙ-û‘ë-áÚØ1{ZÌŠê-gü´pÓ ÆO 瀸OKojYÞrÄ› 9çù{ÖoĤcØ5aàO §°xÁ•SÀ†ºµìo†£ÅVB×6ôÓRæ7B¼+úT…k£¡õo&}óË©œ‚³Ÿ–xéì3¨ÑÒø¤êò­ü“ÓÓ²«ÝýRZò¥ÈJü¶&° 0Æúi±Ú Þ’ýêÚ©ûyZð­4{ë ß­·oDfãhVªÔ[ºÏ»M„Xwœ{aç½àÿmó{ñ~-ýdW9-­£þ ì>-†KhÁQœAå]Ý9Øûl1×Ù‚†Þ¾‹ì—ÓŸ b_SŸ…1ͧbÐ3>àÎ) ÝGN㤫9Ú.fØ^•·àLãÀÛiiþõŽ2Y_˨ã1ÙSpúÓ`%‡\tÀ,ǨßÞ>…a‰²ßÃ,jwþâÇF¨oõ“Sè8Ñä ð´R+Êr÷´Û±„a,­½ëxX¥Z„³v¿àÉ)À¿ô´p ¿KËõXÕ‚£,*Þb3¸A[ñ‰¯”ðwÁßû;¿ŽYœÃä7µ8DÎ>-V‚àÝç™Âbñ$YÝa™ðž†Q¿Ç»KLÎâ&ïëeþ; ƒSÙ^þWQtíà Wï±3´ŸÛ¼òÞ‚_Ýæ¢¥u¶à‰º­ŒZü+ߣ~Ãá„çðžˆÓÖ3kÛß[| ›S@ihkÙ2tZóXlèÞ@G ?ìÙM×`F ,‚13ÛÓ‡©üüwi¿oÚ›*ZFeËÄ8Ïàññg·Ý߸²7ìDƒÝÆåX]M´øÀ3ÐA™3ðaÎ2ZÃVµoiýN¢Š–Þ¾á6ò;/g^? o?-qýþ0NœÕâ—›I²ÈÇd-žzž½$˜3`Ý~Zòä”pT¡¡'ùKeÎ>¿{)goÁ÷VN%3?Žðf~2e–oȇþkÏ…3@˜§…3¨êc"—·øó3?k¹o^Ÿ_o;ÚH&ÿ´XDÈk•sÀ+ç¯ÓÓÒC©ôs×Q‰ä¸Óê,äý‰q¬q”Yß¾ŽvÙZ40g+†–åãXq0˜›ð Zq0è¤ø”­:,Q<ªáLþbÎs@å§…sh¼KÚôÕÐîülÚòÕ© 8jûjˆö,kÙœÕòYuΡó{è1t)ƒ–'|1V “ZþqÙF '…>9 qãØ«–-||=¦€/¯s 0h=-[3#Z|=´;o®‘|=´;Ï=òä¤ðuÎaà=›çÀq¶ò`4rùGaåÁö»eðjð÷„=ƒ«è|–eèãŸßˆ9$ôÙ›-¸MLú‚7$ùlO”Æô)¾"2ƒŽ_ñ©Àã}ðÓ›1‡ígŸœÃäÃà „¡eਠ]Ü?,{7CÇ9·/ê(”[ ¦°x_¯˜‚/fŸGÛÔ¤üÔ«øŠÈNí_¹•£pï·ò`L»ˆqº¯êèŠzZ8x`ž:½ ÎDŸþܾÚ‹?{3ãî'Þiш†—76ÒÖ>-œÜÜÌù§‰ÖÞô÷cK ð×_ð× ‚¿.°#üu¾Á+)Á_çB@ð×]¹àbü ’“àÓC Ç9 <Íþø3"üEÂoì ¿ñƒþ†,v¹HZ1Šþ—×¢?Þ¥ApG^ø7 X5+ZÇ?Ã`ÿs"ÇV䤿àdÒŸ!üMÞ€‚¿99GÂßœœ#áoN,õÉ~s‚É~sòË%û“ýæ":û‘û×ïì7÷È~sé%"z~ýÚÉ~“¿D±ŸõA g€úSÁ~H ìOö›‹ t²ŸõAËbJ8\§°É7d?Ëåü9!Ý[ Ÿ¥„}ýæ™’ü˜F.Èoj]Mô›ˆœ ô››ß-Ñon2ÑÏJt¡ecS¡‚¬ˆ~Hs±"t.öKüôÄ~ ë`?DÉ\ì—HÁb¿Dæû%|ZB¿˜Ü”8)¡_æè¯Û…~ºÐÏç(îËÜ~÷e>eÄ}‰Ÿ¸!qøe~O?m‚üàѸÀ/ëòHMùûÅ}VÜ—ùc÷eÞõ;¦@‚#6ng‰û ¿q_á—"îÓ¾¸¯ˆK9…Âí÷v‚üŠ€,ã˜ñF¿U¸À$úYaó¦˜V‚D¿Uù:'úq¯Gä·ª˜ä·DD?Ö'ô[•KÃSÀådV97û-QÙéö‚ýÌ_ ~ûYJ9¿:²Ÿía\Π:N,Œè·*WD¿›e _œŠè§üìÌþgÅ–Ó@@ÓBô?&¥ ð[‚Ÿ™Qüƒ!ø­ÆŠàgéîаÙ@Ê÷ÅAä¾åYÓû´ßì‹ûìZÐÈ„äwA} åƒú̇3ƒú×N¢¾Õ¹ö$õ-®D}¶Ùæ© è‚ú´Û&êÓž¨ou]L_>©o |“„¾kÓâ"MÐÇ¿€>Ú˜úÖ¿q ƒ+]RŸµ€ALv9èêc?Rßâ"MÔ·?,RßRßB~Ü >ÛYø ¾˜©o‰tH}kò‡:bxÒú–@†ÔÇÄzA}kòšsæ‘&A}LmÔ÷´4ô‰9p “}ê>sRŸ¹ÅÑê‹‘I}KÈDê[SdÈ9,n‹‘ú³Ô·¸~õi‡SØ·¸âö­ÉÏØ·é{ÅP Ô´×@Mkó.%ö1l2°o‰¬ˆ}+ ŽsØäïÅøLßö]ƒû‹/°Á}1(±omÙçÀ"à>U+ ømì–“ûΕ egΈdåàwú7·N¨Íüöæ7GðÓ©~›{ê¿-e“à·7Wõ¿½‰_3Àš¸)¼ ƒšö YàgAS ­¤ý¡þ?ÆðÛ‹”OðÛ(“à·)‰äÇÈ ¿«ÏÔþÔ.'¿Ðs(oòÓÖŽÈ/Æ%úíªŸ6ÜÄ~6oˆ)àã"úEPÓ&“ü¶´m’ŸµÜ¢ßÞÔµH~{)fÌìj²Â6€#Îüâ·Mð‹SϘž3¦€ÁMö€-‚›®~[z½ƒ_|â?mÓ ü®cb õÍ~›/±Âý¶ö È~{SV%û]ãp‹8KöÛ’ÙÈ~;¤¸ÄpA?áO;£‚¿—ð·µ!Cø³+~‹~ŒL øÛ!þö¦"ÙOßÑi*ý¶ D?FdJõÃ-¢Ì!ú!ª#È!º—è·DÍåFjf‹ËNi~Kj"E?>mBô[€àýßó™3èÐâEIb£ê kˆ~ø9…æÇo-4?ʹ¡ùQCÍoI¤b¦†4¿…÷Jh~P¤ùñ‰Jͻޅqj˜ $¿%!‘’Ÿ.W’Ÿö¼%ù-É‚œ‚×/É/ÎE¹Œ#ÅOŠ¿Á%Ÿ?ͨ2b¿¿ÑoÃp)~ƒKo)~Ñgj!ÔÞì·)ćâwµìIIñã¤$øáÇzŸ®Fzß"HAï“ð ½O?”vÍG±lû¥÷éÔ[+9^.å¾Ái÷˜~¥=f?ô>ýP¤÷éq ½O_TgÝ©ò&¿MGWè}4t„Þ£P+Ó.½O?é}KZõ¾ès(z—·Þˆ£T&‘h°tÿ¦Ü‡òKî[!î%N ;’ûô³“ܧ‘/¹÷À-÷½ÁÏÆŽq | ϘÓó’ÊЇRF]±4xn¹,cë-òÅ"ƒç¦Š"‡§>P9<£ÏÔ¦û(#á›õâúäð ]-i_GÉá©3Éá-U‰9À«I‰ì‡ÌwœO}¤rxFŸ_—7¯)¯®)x%²èB•L,•¯ƒùhþ‘o•%òM îHÀŠT¾)ù*ßü0xÎï‘o’¥%òéY¹®@ sdþÐùÖç"·KçÓ3W:Ÿdhé|‚\é|›»=Òù¶¤µ´_Ïn }›{#ú6÷F$ôIR–Ð'Z¬§0±ž~­b=:/ö´í%ÚKÔ¦/‡ç[çc:ÎËâI ‹'9—Å]{ A^~æ°H/kT¢R¢hsÙ;+Á¨—¹êQ7½ýñòG<û‡Á³ðÝ/Ö+ÄÁµ×€½BìÅ8—=IVºZdðÄ F°W¸øì^3`¯PMÁs½u¾íñý/çþö*–Àb½*BäõWÒÀeïD—pFö·Ê·+eŒËÝ [ÜåÖk\Ö]îN:7ÃݹÐîN¬¤ÅzjœX¯É}JÖë”ÄÄz·•XO2äåîÄBT´×Ð^'íƒöú÷ìu,ÙÅz2^ÞÎò–ùv§@+Ø£Wÿ†½òÃÛ‰Û^°'ʸÌ·úc¤`oP¬ìéŠ{Ü)¹Y-KÊCý`½Éß“X[†ÁzR©Äz2 Šõ¥ôòvíJ“ò_$°|0%^ùðvʈxÃÞ[åÛ|ïݰ—~x;áìi;â‚=ÜHì•Ø›¼!/o'X颽z«|î½E>íƒÞÞN"§°éví1®*hoËÉIÚ£G+poÿÀ=rLàÞ–³tbË·€p/ áõ:ÑÞæ/ÚÛ?hO·cí­òÙpÌúÇIÓ^öÎõÜ7¸$’¿“’5ýÄäï” OþNíùÊ߉dS—¿“@ŸÂÈD~ ùeÈ"¿BìùцäW„qä&š>ˆ~ žú5Eÿ-9àGúÑ®è7huûÑ£ì7¥é¹ê[å[REÅ~’‹Ä~ZBŠýèç7½£ûv NìÇ„ÑÁ~LÓ}é| , /ÓÎI•,¢ß.ü¤óixÔù*}¸ÒùªØnâÝ¿_ìWiG¥DÖ$ÆQækœµd¾Îë—Ì×?ýŠ™¯ó;‘Ì-!óAO–̧Ÿd> ù*™oÊ«I‘L*ù%óå7ú…*™/Ž ™š­t>mÒ„Îç†DöÚg-€Cª|›·‘T>üÚgL ³E;LäwòÆÁbéܤÂö"?ë.úY ®èwŽzÉ|ÖR_:ß)øî ŽM*u/ò;Yá.™ïÔnÇŸ›"9,‹‹3(|î­˜>OŸ²Ø‰ü¬åeð´a^ÜwÒÚéxý\ò’ûÎA×™éäëÂÀÎL'õÝ¥ñTsà5ç¾Sý¥ñJî8†3ÐO Üwê¿C¿sp²$q/§*Ö ûÎ08•cß)ÿòwÞ—Ã)hî;“¸¸ï¤ËCç¾s è˹Sè/ö³q°4ûY pìw¦ù í³–ñb?ËlGGª³Ÿõ¡“sL–3ÓãÁey2ä¤)ÉÎÙïdÔ×9û,|àCg?kÙ/ƒ§µ€¿2g _ØO9ëÄ~gIørxžLw¯à>ka`ž³ß9;úpëRú&Vb?å ùÝ8ùÙ…`¹ ô;‰úЗŸHz¸|-AÁ~–“ â ØÏJyÁ~“P¿s"t¨øLˆœÀ’Ô©é<é à96Y „€ßÉOˆqülœwXŸ].C c ›sl²ÊqŽMÖÒ^a}v. sŸ5ÇÖ÷/ð³pÀÏλ2ÀÏZ@2¿suhØœ-–1 Ù/&€6¸ïd×{õ]¸ïä4¼‚úN–AœÉ¹ïú¨~ñ9t΀٠È}'Å!†qî³–WHŸ2 ûÎG»f4ä ´Aì;3€‚çÈtæp…ôl€/웹ðì»[8>L‰}Ö‡ÆMg¦“Y(æØwŽz™;­øÍ©OéE}ÓŒþGPŸõ¡ èÈtjˆ^}çD/‘ïLóÒg-P 9ƒÊŸåâ oYPŸµÖšNÂE8,úN QåÔg}ðcõYž‹SˆNñµêq¾D¾WËö)éõìS¾Eaß÷eî´>lqì;iþlœ;AZé©_i£¬kµ”+/Ï¨Ï í£S Ò~õ¤•]}£Tã«åÊ!†¶H3Ć;Yµ¬|íJ-×Ph‹¡Øðj®úε¦–{(o»†BÃ=T+âdË5Úb(6üû¥•yRÜþWK”öóþ.½T¡2_Õo·sº3ôùíæc])Ð0Ö+ƺza¬W/Ž)Ð8ÖcE/Žu÷âX‘cÝ)Ð8VôâXw/þj#Æz%Jã=za¬%QÚ³Øëžùý¿R¢´?x°þíó!ùËcôo¿ßÂïGëß¹ƒ?Gúë‰ÒÎfXùÿW¢´õ[¢´ÿü? =Zé¹)ú?y¼˜|UzE¸³Çƒ9…qã¾.+½gÅ㘑7îàö´(ÊMYwtY ²ÞÞ°dí+Ë2‚¬iK*#7F$;‡=¿XYûbîÁ0f0Ã1Ê~µ£+B #1ÙIôiÙÜìÝ8Í\Üìõ5·ËðÞÒq¹˜ÀbVmoÁsÖV¾!ì»g^ò-Í[ja ë@Ÿ†(V‡„2»r„9—9[|!ü´le ÃQs)JG-Ø/Ða†O:{”•” Ÿ÷ÊÊækIJJU‹7ÔÂm\ïjYû׸c·z Çˆae(A®vÍÅ\ðZJ¯UpÔ Å׿Sg¢oÊ••!Ì¥ìéµ¼¡ÅzCË ?Ä=²»’káŽØƒÉµ*þVr-'ìç±­äZ WÇ0V®ì­äZÞ§¦ô‘\«¦¬äZþÝÖT”]«¢O•ÄïÏçõ(ÿÈFŸždœc‹²k¹jVÓxíÚ×4•]« ÇRv-³e ñݳš9Æ2Õœ[ü»«¹T熷Te×jhi‘]ËÏ•» $ #w™/ü3­o¾nÕ£e«ö>÷‘˜Ê{Œ,n¿Q>uTÙð}Ž&û†éé§ò4lZxæ¡RF>ÀìèúA Ãlyðñ*8ؿ̙_‰–ê©Bî-¾ñQgLÀßurpÛÕÙe]à‰º¬öxÒÌ!ûî‰9e¿è8¦àÛçur zt[¯–,£:Ëõóü5WíÅL·ßköb†Î•p çÀŒ.OK„ xÃQŸÄšŠ›D—¥¨C_Ôµ7‰ûs'9íÝyTwVÜ$VÇ -¾ïZw…°È¿[¦S({1C©ËhØÒ1ìùß÷ža¾ð¯n¯Aé +â5ÒPÍŠxaR~ã7«â…èV¿ZúœBK•—‡cZ~Ñ¥»Á–-ñqyËXŒoõ´4'…º‚£8¦YiiKŽôwe³^”#}œœ!G¢4ÏÓR ÕGÿêš•ðÚÞâ ÅçIœ_×—9T̲ ’ø¬ì­\Þçž“³Â0kpRþâk™S Ñ°•˜²I\o)…«ßŽÍ xaN~«5«àùÑ·ïÛó^þº„ÚV8ƒŒ7h³÷2[pÌœY®fIRmè³!© wzÎûõÕkh‰9œOë³¢ÝÐ÷<ä_Їõ/ / 0 /¡% /㘀>ß‚èÃ= )ú( õ ž\ÔÇÄ}A}4±õMQ]er0ÀXc"0Aê€ û&Âòû¸Ðö)©—°oNÁbpëz%¥ÖJ-PÓDqÍÀ¾¹xÅľ ]ǾÉ6aßdL¸°oRaö!û&Å@aߤã[ä7O+ò›\‹ü˜0Làg þE‘ü”,\äxîä7éùÍ_ŒÈ/䧤b"¿«ÈonñÈ9Ä~sãG%ð»6MÊŒB¿É—…ÐÏZ€qý&wB¿É B¿‰¿"?Kh†. &eAùéD"¿¹qÓŠüty"¿©WbŠ)   i2øAà7)ü”ž]à7è"ð››’b XÅç˜Â{š”æ]à7ùø)o›ÀOYÚ~q…?JÑ~Éÿœ8K&bŸðƾ%4$öÍ-¤#¹&ÜþÅwº°oqB쳃@À>–j î[LZ!ð[Llð».oaŒ‚‹ø-ˆÙâ¾ÅqßÕ×…vëÇb’ܧ´xâ¾8°O9ð„}‹¹<Ä}JÐîÓ6¸ÏN쟹oÑ(îSkñ†˜3)ë  o%\í›ú¬}@}WKÌ_±Oé …}+ Ø€}ñE9öÅû ¢¾¸¼3ðõ±°oicˆØwµû¬ ìÓÞ°°/¾ÝSXoìc5çÀ¾•ù sì[\g û¬xÖT%c¾±/>¾sÀcšÜg-þYû×È?e¢øÅQ?L€Ô·˜^^Ô§tP_L‰Ôw ÚÓ•¼RÌW¶¯«:‚ùxÈüŠxÖ­í{â€Oƒø"K¦€ÏZ’®ðÖpíÿßW=|ñ¥øp±¤=ýÉkÏØj&êÅmJÔ;×øËÊ,ºAW¥p6¸ ^|Žzgÿ3.ÞŸ«$½ørHz×t@zñã$êE ¢Þ9•óa‰)øK”¬wÎJ+ÊŽŠ‰ƒõ®¯¬wZÈv çÆŸ›“Ê/Ô»>= ^¤X%êapy»sR@\Šú1r)àòê5ù¯¤Bí‡IÀÞbª$ÀžÒÄ ö˜›M¬·R"Ö[ÜëÙî=ŽšŠ°Æ2™°·h¼ì--· {kr{¬…!Ö[ "ëIë-dê-®…zÖ…ð§k,Ð¥ðEŸ¸~àÖˆëÇÂ_ Ÿf-…OGIáãŒ$ðéT“3 ÅpÈPl2U¡Ødœx*º„+y/.e+ºšzÞ5àWLZ]© UÁÕíCàÓ/zÄxæ˜HŸ®W£ƒCà£6>KŸn¼S ÕQã]#…O·•>Ý›Pø®¿·&õ¡ðÅåÅxê=Þ-¡ðmi~Tøö…O ZŠ)TuÍX'u¬¾Aïjû=ÊŒðj´,…W³O̚ϭðÇBácK(|À™Káù…À‡S]¥Ã˜‡ ÃÌWPy—éÑÿ,ÒÓ3-HO³éi‘"Ú.ÔcF¸@=m~ õöÔÛ$FN!C[\ó}’ãõ¢…¨Ç8–@½M  ÆÐ@RŠ.$%í  õâTD½-]¨§=õÊ)äêé¡^´õ˜’/PO£ˆõ¢OÌ }°ž„±Þ’0HNÒœÄzÜ­ Ö‹Í´u͸EP¢÷>Xô¢A/!èqk-@/NÍ hJ"=}q"=ÆGé©HOW#ÒÓ™„z:“P/ú”b²ÞÕÂ\9þ'A/:pº\Þ[Ü‹+åiPž†åiÆÂ¼ÆÓdÄxúøÅxqb2^œ˜Œ‡?—Â$I¤[)rP©}ÌG€}J}ÿ]ËÇ|x1 'rëZ¿ñ±>[Hw1éƒíÔAh(ã¥ëÚésÚ1€/Ðîƒëâ¢:ðº£Ùè%äÝW¹ûû§\-¹¾¿™à:ÞGä:¨m-ßWP÷’ðî£Itüpê^úÝÝD¤ËÔE ¡N'Ôi*‚:]mÖÕ¿ô»ø^‚ê¢ÏP*"æœSÕÅ™¶–kÔÕ~ÌATÇj%Au:‚ê¨- ŽÚ0¡Žùh‚êb!3Óø : »äeh!Ôé Aã¯ê ˜¹0ÿYš³à¸jòÈ1Œ‘ ׸|È5I®Ñm(’»Z6sB’ÊȱtA€Ã#䢅 ×°ù$-œÔ@\üMBuÏ ¹†Ýø ¹81I.Zblù1‘ËÉ5ù9‹Š¡RØ#Ê5‰œÂ§q Œ? –ã¤fX°’,§.D95ä¶yo¯fz+v1%¡\´åºŽ ³æz±\ü}M€-ûãk¹Ìš<A¨Éz™5\d9õËé\;总D,ר^ æô5æt=€9~ b¹$¦À–˜>t±]ªÁrM2YŽ,‡“Êñ—(‡a\œ‰Ô¸C ’‹AHrqf’\ãÆiŠP ‹Ì’ã×$ÇGBœ®F(#Ç>%;~¢rÑg®ûù,ã’åÔ"–ÓgQ®9 Š Ê`í!–ÓÕˆå,ÇÚ)ÁrÌÆ,çâ8Ê‚½˜b aNß®`NsÌ5¹*¯ਘV\¢9:¢ƒæÉ4×Ð\5U‡çú˜hNß¿hNçÍõ4§YŠæb΀¨ ¹èÓU¦DÑ\5çÇ÷$škÔWç@»æð¡Ü…©³|Æ  ÓÕèâ(]ŒÜU‡VСÒ>ìC‰Hs´ÄÍé§ šÓãhÄèßä>T;U(‡å¸ú”‹£HsšhNß›h.ú‰t.î¾GF™×0JÌðÕµZL}Æú˜•˜®ýÐí¢%æ@û#ÁH}„uýëôÙëtÏë4ÏuÍ §º>Ÿd×~èvz¦Šì¢áNçÚ1²Z®o ñ¾+ð]ôhùã%Ä‹>}<vÌa¿›WŸ¥%ûìXÓºR{¿“ôx=zÑRËû˜–ßÿßÓ÷gË~Ï)p/Z® %f°>ˆO3ñé(_û!ãEKÍsÊíõ â‹qûþþè3ÖûÄG­ñþ^‚øÔR~ÌAħëñEKÍß”/Æééãïý1«2ÖǬ„|1îúXó©EÌÇ…i0Æ}X+ü•lg·msÜJž*ÃF¬Ԓ˶¹?bõ¦ ‘¶ÍI“&]›²&ʶ)S¡l› ª“m“{ÄaÛ”¹N¶Mš¸“¬•ÿ³Ñí¯Kç§E3ѹ°½'¥?cLòýÊEü‡¤™¼"ü+xÜÝ¡zôW°÷ôWà0ü•:^ùtlZÁÇúË Œ@=ò ñ¯3#V¶É˜­–«÷ÿr÷v;»ìH¶Ö­ÌÃj‰½ÈL§ÿ„8…$ê ¶Ð>¢hZHûþñˆ1FØ9çªU«šF ú k~^ù:Óùcû‰aÙäŽÕ»â¿blòŸBuŒ;ÐC( {B± ñoÇšœ&âÄ¿ë«ØN7qâßý•lÕf<éïþ…þä>èÏA€¦¿úgðOÇlük?ëåVäÀ¿ñ“+/aoÓ_ÿÿ´³?ðÏÒJ³Sµo$ù/wíÉÚ½$ÿ9YÇæ¿šÞ?¡Z´—üWíE<øO‚±ä?g›ÚüW“ÓÌUþÒÍNîºùÏÕ)6ÿÕÿD?ߊ$?çŒÞä×3‚®<ŸA%ùeLe’_~`I~9ð$¿¼ÅI~!Ÿä×­hOòk²ÒmòsnìM~¾¥›ü|KM~=e•¯FP"¿þ›tš¿–N;ƒŸ_¬ ~N˜¸ÁO½Î¬Q>qzÑ"¢»³bDùÄéE·?ùùZjêsníM}=•™&¦.ÏUBŸ£p7ô9ÄvCß>ÑBýI¼ÙÓ‘vgÒòd΂Ÿ¯kS±‘o÷RUò¢KܹÐåÓ3òuGšøv'#³.´Ÿ¤›9€$>×ߨķ[6ñÅr&:CF¬#íÓ"º†¤~;¯Îßò˜3ÑÙOíŸíDg¿þêŸHtV×ÒøÍ–-G0µí4An8SŠÕqÝßìdÙrvŶ£+5œ]µÅ®Gö«ÿýh9ºRÛîÊ ÿñÙÉ*žìýÍNöùÀ6÷ù%_Ó/üAÒ²ŸÒˆýúö¼ó¾w篿ûªDÅŽïQêéL†ž>ÉÁÔÓqŒzú&SOGr°èéL æžö1îé“fL=©Á¢§31˜{ÚǸ§O’1} Gb0ôôIæh£žþ]ÉÃÞÎùÿŸr‡ý‰¹ê¯?Ï;¿33ýõwßÛŸf«ßqééŸÏöÒðÿÙÜaÿö;¹Ãþí?4wØ‚Få ÿþóï´9wXiÿ wØ‹õ‚¨ù«ò²¡ È|.·h2…òš–ßYÌ5u¾Ý1ãÚ×ÌÚ"® ÔlЬ ³¿¶5jmž£ØXç~æck©¡^W¶Ürß'5ÖëI‘:#VËt î>ëUT,Ù ›ëõfun 7*m2ÁÖ«)kù©^Y YW'çÒv¨›ÉÿçmÖûbÚ‚Ç1âõ¾™¶€[Ëz?ÈYPœÏiýÍœ¯CkëÍëïkêB×ßlu«weÎÔÅP¿9 †s€×»3gAZXê=˜³`:Ø¥ÞÀ@–ŠhxxýLE wX„Æ¢ÎýÜaÅÕ^Ö‹¿aLâyžÛ¹Ñêo:àíÜèލ02“Y}8´Týª‡Ah®gÒÔñ£ÖÌ´Ùõ™aÔBâyŸj¹Â¨5«3×Â!àMæw°Zb³YFPË¡‰lFl(ø rˆó>hÇ…$óC-f‰uº|Ô‹°1(Ø«NCXK²%oµÀL»Zš“Ô‚òV«åq2™5Qp!o®EV_äµþ¦@ÚW —ÿæ¢õ!¬Á^¾Éïú/aö›ê÷EX õ‹ +TAúx½ioƒQ«Ü·K9U®ë<¯"‚êËÜÅÞ˜úrHë®c*Òv¬–ÇõjE:ïÕ’±Ý«V­0ûÑZ×óŘð*Ó,\× Ä˜°ÆPß_+ÆðÄçVtúÚ·þÄ;WðÖuÚaÔ*HS©7¤FªÝu¹®8SkÔ [Ç8Á`mÀƒ´jážËéãVËŒ–7ßÏöŒ²²«¥iÖõÜ~÷ÚÛâ1Gâ¬KF/Yx®6!Óù×ÖßxP·³ÒWÌ‘kTÅ¢dÛ°tÒõTY¢<Í5²œ¯N† Ú®wH-À㪵 ^)Åñë~¤µZ¬,ª˜ªð”†SÕ¾­¬;ãy¦s£ík×õ?ÎU;²“ñ>è“#tKÔÔlô«¥5Y{W lZëc­yֺ̛ºâû94„ î®ãmѲnt×15Òã–WÀVGƒMkâì|utœz¸ÂCÅLuãòò‚#7bà ´•B±°­'ÿ#Üë5,Ê·$σEùáã÷oJç˜ìŠmøbñòUnkE#xòz‹F0žlé…)7jY9‹6_ô!WÿŽk¨e5ùêóTo áõ×Ý^ aÞù“gD˺~ï /f<Ûî[þ¾ïž…<í­5Tø}¢¡1£÷´·½ŠQé•y5=\þì®úÐjdíZ-¨kñëágáTÓÖ¢ŒÓÈ9Ñ*/>}€U—_¡­MtûòתBr96´Ø¡AßÒZWb@]EÅWËx8 &K[«Aµ  ¡Uçýíjˆ]~¤û‚:V1§jëåÄÇ?³“Òùž)ÛFk@÷·ÔxýÕµšÚ:„Êï³õØ-ØÐ´šÜ)Oþ6}Ô¬~Ò:/?îæ£^ÿúÕ?—3쀽ú3ì)»Ü{ÊwÀžÌÚ {59ͼWõÝnÞóvdó^Ó„¿y¯ÙînÞëv¡$ïÁ6-ÄïÁñ'š»•,«šî2÷TÕo4†Ì“¼‡Â7‚¹·[ž¡µP¼JÁ\ˬÃÚ³ø¶ÃÀ·ã, |QÍNLE`Šê±B@ßNJæ á=™§®}™ïRŠæD>Ô3bƒˆïÊM«‰ïvƒ$¾;÷Ï&¾ÛÕâL|ðȽäC]–úa¾^øñ^Ñ›†óóß6òõÕ~©["HWwFÈ×»ÕF>°¯öºB¾8F8§Œš$¦hG-Þ kßÀ7²T˜eÚ¦Žà{° ¥ÍÀ7îÇ[a߃Âm25øÖ0,†ð-`~¼í"ðAÇã³s‰CVß‚j§Öð-ªÖD¼·þ|µÊï=ðjwOÞ{Ffï­–ç7ÁM¥ùyÕ©®ª6u«ëŸÎD&Ü[ÝLĽPé ½»]Ñ'iï‰ê4'í=˜¸ŠÀ #˜Å÷TÓ7KÜ#ì‹*÷Ö1oöÊò+³yeî=3‹I ÷ÿŸ÷žØh Ë‚–ž¹n·Q.h)Z®î]¨o%2 Ü‹sñƒö.‚úÐÞõÈAiػ֖A߬`ÎOqºx/è_tGÞ»+wÌ{WubóÞ•–;óÞ•ÉßÌ{×t6Ló¦G}â=xIõJïÝWbx7°º8§ï¾ìÙ4ðá˜¬¾ ñÞZ;|yâ½;jøümã&ÐòÁ½Ÿ¯N¸·6¥rR÷ÀÂxï~]aм‡)õúðZt÷|pI\",!ÊÙñNø0¥rûoàƒ$JwKÄw7—*3ñÁl 9NÄ«Þ>ßSœŒ×ćv¦BâŠéé½â{¯Ó&¾Õ©o$¾µhxG-ä{ª-TF>lò¿ÈW°!àùžLgäô_xD>œK`sy ~äF>LûÚY ùS$¾'Sÿ'ñ¡ÒŸ(ŒÄ{_<Ä:‘ˆ/êéŠïL%ëÌ™ø`Úf‰øÖÿ%'’øÀ!ÚÛŠøJ&p5ñAÙ5ÕÆ€:½†5àt^Ú ‹øJ.܉|5JF¾µ·Í_iIF>,Kíƒ|@Ç©”h×ùPK°|‘oM«>FÈw¥e€Èw9až ™¼T²à­‘wJŒmäƒ2ù‹|Y&üD¾*˜òug[Oä+6˜&ò½Ö.$ò=-ÙLÈbÝš™D¾uôø|oi"_ùM|'â[S3íÏI|™4‘¯' ùÞ,<œÈ—}S„q·¨ÿ£ç”Ôg' ©¯Â®!Rö½ùNû¦·ê‰}9õ+l*6A™ûÖ^PöAo§eì»»‘S#Ø .êCiF]Ÿ±oMñæ1bd{ÕÀ¾µÉð³öÕmS÷ah¯úÕ —L~¬Æmòƒ¤M-F?¸Hô«Rc%ù­—OÔlò+*`ðϤ3üÅ—wÂè ™Ž*áoZמð—vpÃ_)V?5S”Kˆ#ø‹¢ºø‹â·BFyʲ2°á/ÊêÆº#öëi!ûTd­û¤"öëEߑѕ eäNWŸÕÝÛÕ7ÓkײÖáøÉ×7µ ¾Ž¨efÉç)ª7¡D¦¼rrõ]Ní,o_Uüí¿ÇHžà‰§PP#xÒ6mô{dkHò{Òéeò{fú E~åñÞÔäW¬YKò{^s“Ÿë‚'ù½.m)ô{­?ÑÏDiôËa&úy/°ÙïöÜìW]É$Ùo;îÌ~o7Ç›ý^)Âý ‚ùxû:ìÊ"0Ñß”pEÃ6ë‘þpkÞýõ2í>ý¡…Jð‡n|"ÂSüHàIxÂS°Ïð‡ct'ÇåþÐòÂ4„Òó!)>èÿ½~è->é¯ç£Hü{îô! ÿ0Ý©áßcpâß“>láß(NwiþÅÖhó~¥‡ þ0îü7¶{=øQ3ót÷¤k/þi5ÿ dê×™É}&3ˆÿ:l4vî±ìóLÿ[ô,Å}–<¦°ìóp8—ù-‡»– õÂ1t,„¢Èκɨ'&¬›ÜùJø@ñüÈ w±òsÿ‰Ÿ¾-]cèN‰)\-Nr-| ®ÖJ\-ÝM\-i[Œ‚æßUržbËï+&?&ôHŒ8“„€‹Þ»½ìD@ºóÅnÁ€jØ~\~ªÏë­%†˜@ß pF>s2àƒ*»fÉ’×a†¥ž ø@ÇmæâFs½x1àâ“´IŸQí;$>cO³DÀYÈBE|FÙ.> ¡¤©€øàŽhµ#ÆGep…´4ðDK\ Öç‹ÃÐ¥­Ò¥\3)1ðiµ´l | ¯×‘_žº!ÂtP?>¿;‹Õ¯9²Ò ãðù]¯ÿL€0¢<§ÏCsúüâeÓN“øÌêåE¸ZœoW¯Ÿ:Œ(·"ü »UÑ©Ã&?ð™éÀÿ=xwÚæ¿x9ÅNä?¼œúsÚr'"ü­w³f¼øÑdDûÅ«©ÑH²‹ˆAá?Ù/^VQ0Ùo½›^ÄÄ~«¥Ë/ö ›&w¼%.+¡½{þ¶\è·Z.#Ñ/V¹v‰~aL˜ ýîf‹±ÑïnN»hôƒp^Qè‡ç-pú…žFç"ú]ÝyÄ~W}ÀÀ~Wñƒú]¹³4úqoû·$¿õй‚Ð¸®–@¿5Ãy§&ô «¦ÆMô k$_1’_Rê)‘üøžþ¾ˆÇ´Gí¢îé¾’Ðîx Ê'ò[-Å&’ßzïJÒáK;8*¢ÉwWiGô&Íà},ò‹™“…àç¥ssx]»9Vðv{. ù=¤Ñ›Gò K¹|ð ?N¶rç‘üBŽ¢’¤Òˆüw %òƒ©LnM‘ß=öÕüÖ¾TÓ™ÀïÞF%‘ß•U'·p{rWó´×¿®¾™n¼gü~]}Óu'6íIò˜ž¾œbÒÓ733]ÂÞ“`iØ{CŸ°WÀž}k¢½ÛùìE{WvM{ÛblÚ»SqwàžÖðĽâÝ^âžãe6î9þ|ã^û ÷î™C»ÉZrÙv“I{”ÊÎîZâÎÄ•wÖ”{jonyÌ{RÕ1‚¥5!ȉ`àÖLÇø`% øÚ&Ia½:»¯:(8¯¦ÉÀc¹À,€¯ç~ÁÀ×okDÅ{Y^8yoÚH¼— †ä½i­‘yN8‰¸‡ „6½qÛfgÞÃÖD®ñ°ÁÇÈSVFúéÂUVF!o_qIÒôö½Ö¥·¯:qKzûÊ–€ —j*¾ìíkWJ7åík6zooß4³ÚÛדYíí[Kß8€/æFá\ÀRM×´Ý}55¶v÷#ÙÀ÷x¾žu*øî4Õø®„Kß=Óí&àƒñã”wÆÙ­ÄðÁv®cb Ås·€oíŠý ߦ{ßëÍj_Mi¬€o8v$o4³/?‹(˜öFÆBšöÆØÔHÚ3_#Ñ'ôíî‹¿-ÕF²²h ¬!íaó§ÙR´7¤›ö°¸_§¾ó7è›íÍWrÃÞ|óþ öÐÒ?°êõ=´Ìíî ·§–°·Zò !ìQ.­Ë#(aµÐ'쥞>a/]µ†½™ï•~וߥ~ÉÂH:˰¦è1öæ¼ûøûàv:…¿/šþ¾Hý ú¯¾Î©eUµ¶ÈßϬ¡¯ìjŽ·¿ïêÃôGwܰód=µ ’î¾kæê2MJo’I ù!d\w~cý)Ý}𱚮èîÛ’o»ûТͺÜ}÷Ó~r÷Aà­mÜ}÷ú–µ_’»ýH°·^“tFöâñjkØ[Ó¹<†=¼Þ‡»ïBì†\y{«ç)±»nvmçäîC/&0óùq÷á˜KÇÐYv­!èÜr÷¡Å®<ºûà·î¾k}0åãîÃ]³#1Æð¤Ø-Ü}°–È]!wÞÇûãî»Jnçåî»J>¹û®b…¯Ý}8F ¹ûÀ5åD¾Õ’ZM¹û¢E.AºûÉð|Ü}WLMòDF|OB7JÞ>¼Ó’¼}W¦,´·ïB"õB仦} F¾++]ù®Ì d䃅ÀÇùPÕG0)äkÎánä»!™Ñq ž}Ì|°NèÄ|Ý›]»ûâ1å•£¿ïÊxlûû®ÌDdîÎóñ÷&ÊI}YÞ²+ëר߇û~ŸÔWîköÅÏI}bðO྇}rä%l“ý òæBWRÊ̯ïÊh.ûú°¿ígßÝíÆÎ>ô#•³ïÎÜ;vöEšóDEI0#ò=°lœ}7ž¹pNC¨W:‰|ˆŒ×ãNä«é"ò–*æËœYf¾»_?éˆÊ,CU`ܰNÁ¡}wK¬Ph$c‚4Fö=)]qdßZŸ|rGö½i=‰È>´ y#²ïYCÔS‘}ës€£"ûâf5(#ûž×r'Gö=‘ éoI~¡’…£:.®z¯À¾g"*°¯T»d×÷`£‚cåÉ{#DËoyÄõEÞ+ýM•äÉN×wÏ+U¨Œë+YÊØq}÷ëhV…õ½Û3­°>\ì8ý|ñ¦×Aa}oN¯Öy–,Êå°>üê=„žï¾< =qÛëGéù"¢z¡l}DÞÒKé‰`¡Óͪªr‚ÃøNð‹ y’_ĘܟÀ¾:R¼êÀ¾™bAöUÇmÐ͇ÅßÁ€ì)ýÔ¥«!6½ØŒËõFlZ/œ_)=ßLWg¥gChLJü–awÇ€_9fÜ„ì—õÙ7µýÞb%ѯöí>$úáúÞÔ ¾tÅB?ìE2’/¸i½~„~U~Jq_ƒ“ä~µ ‘Ì}H>b)(¯¿m—¼¸¯NWaËÀ¾ÚÜ·64ép$÷!Ùõá>ì·´í÷µ ì5÷µjQ¹¯ŽŒo÷Euõ÷aº`8²o& z6ì˜û 9ÓS܇ý¬¡sÆO;"ää[;DþIèCÒ×>¿Égäz͆¾–+£¡¯¾ªLfæC7ç‰ùjOÕš˜à9=|‘ MÛn1_+¹“ æ«}Ë,L°B×Äs§4óµéà3_|ábrØ+Iò'æ[8#2ò!ËZÿ v¼"/!æ1½!B¾Ž¼:§—oãbd¾÷€Hjòþ¬ð„šÉšP2 a‹ù°v虯½Ê*käkñým_d›9’–"ç•ÎDZZ&݇$¾H{'i&‰¹q¯#¦o½ŽþD|»0°‰¯É\"ÜkÏL¸#îa¯-G–p¸#vî­hRîµí î­”°I^jV”™öÂmbþ‹P³ü3¤ÃòU‘ÞêÚ¦ Á^K¬ioÝcÏ ¢½׸×ÞTAZÚÙRÁ*Ü[¯£VªÔv¾®£™ÚΖ‚Záþ§Ë7'mç3?!}õþYÛÙ¶@ÝÚΧ&Ü9¨/íÕ—oƒµeGJÛ™6ÿÔvöÄQážñów"ž·SÜ™IÆÖú½v¯ãG”Ñë_ÒàÿöÄ—yÂÎ#öñûˆßûÍŸÏ-ö½šü aƒ‰Ÿ~îõ\Sv²5¼›Ù@ØOþuôã¶ÝO¶œýÀgØ}=ù×ÙÚŽ~Ürôó`6[Ó‹îšÿ:úqÛî'[Ž~þcR“UüÁŽÛ&ü'e z°!¸ÿR•÷iŒL1Æ>P#Ì’é¨~9àügÂylŸÙïúçõÓ?á5¬™Oè§·ŽõÚòüë/o`‹Jaþ¯þm¸Â@áß»åìcå~ΣÜò"cÊÞ}¹åìkå¾Î£²¯ÆÝõÑWó~ûè+Ê¾Ž£öÿÆÛ}¹åìkå¾Î£þì;³öˆ×Z/~D~øoʲv¦,s’±|GÚO:Yû&-û»Çý”´ìï÷sÒ²_Žû¤e4÷ýÞLóël÷׿3cGü£óŸ–é3Cö«ŸÈ@à/  Znùñ/Hþ³6Ûùïÿå?ASËÁÑÚÖ7<Ðüþå¿ËÆýŸÿõ_ Ö½ç?îè[§ ÉÀÍGpÿøO¸ÄÕy¼$‘Ú©íþÇuìÚ]ý/ÿÿ Îk¼ï_þ§}!ÿsþçÿ9ÆÖ–¢þå¯ù¯ÿ6Où¿®ãPøùªù?ò:ÿÏAÖÆ·"%Û‚ͧ^{ù§ó¿ÁÊ…Ðò‚®fü5cë×Bë€\$fÕµGZß-#¶¢Q˜¢¾ÑÒâr£ci<&¶~!VZ~|÷oÀ2¶­=]´Ì0/"üg‡A SK©¨EË “"HúB¹Ú¡¹FÇXÊìbŸXü™€u-v 89,8Ñ‘¿øÕz‰b±€BûFÇë‹ NGVÜOÀ@¬0 ã`Ø®ØBްq¼Ñ×70„?Z·"`w` ×-#¬þM¬ôœ;‘v¯ë¡øuÔŽdÍû‰p ãJLÝïèsÇ뀖5ˆõò¬e%VX´¬A4 ´ûö by½ Iš¼ Ã]O+`˜f„›æXØPu{à·[ï= #ýLHŶޯN:‘fmÍ'»FÓãA‰ž§j;bë\ï­ïè~0Šõ£uFUjyC°^ÖПaÍ 6’+R¤µ§Ò d6ó‡yàÖ@מ ¨,(Å\3Ì:èWoJ¹B± îlªA<HÝi\;ø(ûμO$Ã9)P]¿’‘¾á¨ÞVZsfºÀ"ðªÈp 5õªp‹¤/¸¼.—eR@ò|ŽP ‡k89 ,´ y¹\®¸·qˆešáD@9„û²‚ñ·ÕÐþ>"L㑉T?‚Ñv)âÒí瀿ÒÈQºé-q}Ýá?œßB& :ŒØXµù1‘Ñ|Æ­èŽ ÿxjmR µ D­Ó)Ã"<¦Mžé'ò(F‚U  v¾ÇMn €À÷²Oþ†Ü ŠËX }Á4Ôº7 0yÀ¼ÇCÑ1=B1,ÐJt5B ‘m“u6’HaÁÖ°„é=dqw"³ŸG¨dýÁÊEl)¡C6MUXª×K®Ù· á~:æP¿iMâ¸Wºå¨ß´æJ‹ãΠ~ÓšÄ#·+mmŸõƯ4i¢~Ó:a„w²ÔoZ“8Î¥Dý¦u.¤K䋹ãšÁzؼâI¡RÄij³zË4æpÔצu õS!Š-´kFX(W‡U´úsy~F§29^Þˆl<8D/d‡˜Âá»à×Jÿ5Lléµ@HJÇ™ìô¢p½™8JóB ÖE„Ȋ‰Q®×€SfÈ4vÌ3µ°¹GÄ"W*¬ÒO9Ï„Üq¯&?ùU´bÔ4´#•ê‹Ýz,Ê7Õ÷ªÇ¤õ |Óš¿#ö5Vöõ›:]¬4|kú†£ìmì&jháN†êDÌÉg#x°B_¸ŸM/Ƀún1ì+À+ôš¿{@Ó-, ÑcáaËŒ<¸¡->ç'ê7Íhá§ú ~SqoxÓÔoZÿ‚Oî ýƒD®kï‘Ü!z†Hfð\5‚'Ä,k kjã­~÷ZòX!Öy`ˆÝÞƒåyÝÞªæµËóz@ˆÕåÔò UÉš¿±ÿÕFnÒ5‡°×‹4®kþƹ¸×|P½iÝ·8{<oZÓ÷Úx¯§— OsÇ UòãAñ¦Á÷³†ïèAJÓ‰1"»‰Uî¢}5QE Càöy¨ÚíòÆ`y^—a¬|,¨ß´¦ïûµ›ÖÇØ‘ð·°—¿†¡ná/¢€r%syP»i½¸ˆ“«‡Ôð+­{ǿ…ŒËÐ= ƒÐûbuNí–å59S8Í>h°@dß²?›îC€Où™c†ý nçc.?7ïÀNj<0––ï˜Y €|Ã7b刖À¡½ì €Ü­x‡ÿ(Óa¼¯ €Ø´µ±w ÄŸAe €—6)•»qóßÔròŸDÍÿñKâߣÓÆ¿GsÚÆ¿õÕÆfmãß#Øü÷hYÛüW´éKþ±Æ´lþƒ#ïú ’Å š)ã t]ÄF ²ÕÄÞ1pµpMMÃÆãLŒ . Zˆ\@¤Œ%*  r|"I€¸Šð­&âõxJ ?D½Hâ§ 0è» 0ø8n˜8üÒ(DËà–DXCûx"`ÈM¸WÖ0Á³…X³ê˜‡ ú`E€ÁÐ\E€ÑÒOı\'ÖÐ’ZI€àl…3ˆÑÂY^†¾‰$ÀÈÐé* ò¦Û^ˆ_ :¶D€˜V&ƒƒD€`qmíE€`q.\&@lkÍ{$@´Ðöc¬ò ¬[ABÀ‘!a$âÜõ90úåÞňý Õx%ÂCaÁq!eÔ¯€¸Lî¤L€»Å¸¨ß• €8„= ¤«ª¹%„ÂÐuÑI€ {^5+Âs?“ ž\ÛµPøX%kþƒé@zOðßÝl0ÿÁþ Râ?˜LErâ?ì¾$#ÿ= šæ?6ßÿ=wR£øE õ+ñß3½µ7ÿ=]{«ä?Í—"M–ä‘ä¿ÅîÕùI‚ÿ`%p~Hò„wï‡ÿp¦öá?ìâFDþCF ©˜Ä¨’e5ø¯E}«ÿ° v Iðt8w¦ÆÆFb–‰È°‘h±µÒ?øõ:uVð_ñŒœü‡-äë„¿Áelvàb\MükÏ£•;ñ?’†ƒøYÁ#ñ«*§;á_#' ýÛÑ/ÂbÙ"ô«9ó ýBu@† þáÙN?Â?\t§^Jø×bâ¥ÿ`# =ØøLânŠþ`?ÑýASU„W¤¿(ŸÌ1ŠþZäÄ"¶‘þ°‘ѳ4þEACük™ [ô5Aù-þB1ÍyMôµ„unâ˜ü¦L"ñï¶±Pø‡ë»ù„-²"Ä8ÅQ€™·Tü×È×b?Ü`~ÝB?º(^ì×2g«Ð/ì¼~³ßõúS!û¡YcÍ~—mnf¿HaUÉhd¿(Iù°EìçÐÄd?Tv'û¥uv³ß«=¥Ù¯MÌ~±ÓD¹Ùï‘ý=Ùï¶ &Ù/’™‘·Ä~˜ùîû!áEÌjÉ~˜§ ¹Nì‡Yv²…ì‡×_öLö‹LÄdZÀ_Øû:‘’ðY®þZ$¹ä1„?|Èœ ˜(¸w6üá½r á§æÛhøƒ¡ð’þÂjùòW¤¿% “ ÿZ¾fá®FTã_ðã5ÿ`C匕øÝ.ø‡—úžd7â>ÌJ<5^ –K\³¥^`_Ó0mQ&ÀžFé$ÀÛßnR`Ô’‰ç" Ûm¢@p»ÞQ`ØnÆ‘&àÏ$ˆKD„öýqÂuU?®@ì0Ÿ+ɶƒL‚Ã>Š$ÁÈ .:“àð®"Ipx%DžRžI^©˜„’a×íi’ d_W ¶êåC‚PhÝW ^¨˜‰L‚0ÈÆ’Ñq¼OI‚£È²–$‘ªW`Ô{S‡?¶dAÓNÄÉcFKŒ‰490ÊÁÜ€ŽŽ$FYù`¸[Lf0VRà>yR`þ*)0•˜g?(—|R ïצ@hc[‘èž7ú-Ù˜ÄÀݳ10·Ë‰ûcà>—1Ðù’óTI~/L»_S`~ Iùá%âž2N$)n\1)o“úî{j ܪ1G÷?0|¼^ÒàÙ@Œ–ÓD%`$ ¢…Xg f£;S0ˆ½V4Ǫg—àäŒÛˆZ O wcÖØØõ¨7zÐÀôÅ$FžúÀ9à¦F î&QM÷Ähþëv¬nþ³@móß% HòßþUòß%jÜüç~’ÿ. zó2ÿár6ÿùTÛ8-MW`¶¤+pJj¶}yŒ}øvNÙc·+pþŒ€[æ™øJð°Ð. €6$6Ù¯66 ó6v=Ü€*3º °I&» °kuß84Wm:U"༴“ØRP›¶ôÑË÷Ñ‚Æw°µ `ÔŸ´ ?~Ò†Chë@húá?ããÒà·S ß­v‰ÈŒ(ÞþÍi«gê@/}Ú[zÙ$›:ÐËvrë@# ÏnèkŒu X°)ÿ²ôªÙ³t 8¦œ^À¦W*ù/>óròZ$k´4Ó$[z ïRzË©¼€Ž@M óæX ñ­œ‚^){³ôrÝk@¯'…™vË—ÒøÚ" (rR€e (² · ÐÀh`õîÈÐËŽ‘ôŽ<·<€SŠçôÞ¹³ðƽ"èɸZžþu>Ȧ °Äì½Ñ/ünú•\€˜¡ élvÛí›>Àj±}€[æ–NÀâ=€(ÉF´°ûÅJ'à´C(€)4K'àe¥^:»MþvÞ–½o'`·?ÞNÀ{hNÚNÀËûìt^¶G¤ð–,+½€È|èÄ–ôZ-¿½€Eæèí´õ-½€ØŸ9 ¼¼€Õn7{áô{/¼€Ó®ìôb¥=Ù?aØ ø8]„€å²TÏN@H«] GNÀÇŽ;S¶€k ÎK/ R8ñ½€èG-ö3®½€Ø¨ ½€HÃtŸ"P¸u*{Ë4Ùˆ|ƒ÷ÇøædaO`¹íW“'°¤ƒÞž@Œs|<ÅIÖí„§UT9£L‘'°äò`Oà;ͼöÖtÙXó«±'°¾fg{Qþ°œì‡»/cˆ]Hõ‡%W`s.y{[óݲ'°ÝrL¥'°m¿Ÿ<è÷d?¢‰ÔŽ@HÑ ƒòB}}}MQ=é lÎ j_`Ôt ÒˆÞ4( ýâRÎ@ÙÔ ÑÅCÉZrö®2Xó±Žè׆µóF¿zË©è×\íÌä‡÷½XöIg $\÷) ‘¹’ä‡cxuä¾(£úžÜy¼äY#÷Á·E£‡¹/ÂÐÛÉ}áªf¹Ýtùå Wúå „!Z NxÓW¼=öylOà”&"=à>!§<ÛhO ”P唯1òéÉ™{>ž@ì_Oh佸ٱioLGਠ‡#°ä‡~»&?¸q-'µ#ðU(S:cÕ;ÙÇpí2ûáéäûa»¤ü$ûÅÈëü¡…f8Ã_#Ù)á/nÅøx±$€§'ÐZ”"yÜ–„|¨'Þ2€ŠPΓ[:t“R:´ìmIèÔP6^²˜ltX9ÐS‹„ ‚Qµí# ¤)qæÁ®·yÇz>Þ xÿöå@› 7zû´9°iÓµý€Ý=s`rLr £Ä›_ø8ý€XGè•4Bªq}@pòqmÄn8Š90¶¨±šcGÊ@=q 6—\cÄ[¯elÑ]t#ĆГ­9;¡öAì{h¬6†ò†h(Än„ÔdŒ˜ayÁh99%¾Gæ@ìHe„$‰Ÿ¾90’|<§"4òšÄ Ì‚X¥iû5 ¶jWCÆ"jÞA¦#>ƒñíÖSŠP/Ë4ˆå›FQÃàk}lÂ`}½’±#¸$½¼H‘(a0* ðì‚A,Ô4‘‡và Ì?=± V¹zƦDÇ(¸×i£`w£à;¬¥4 fðpFb¦üèA¡¡Ê#a0’§ñä‚A¨­¸+4 ֔šgî™MƒˆrÏllÓ;*Ñ >F‚h°+°ÿ Áj•¾i0ô@ÜΙc³ñã ÁTA!9² º"óµa«ÑGùíÂE9Š,…‰nºXÅËd1 "ž„Ff³ >‰ÑÍ‚ˆh#ášg²ŒYpÚ”cì¯ÅSdAÄëŽSŠŠg "ÖF~8¢`:§W÷EÁ~à¢PK-%BAÄÈ(Ï(ØSh~uÄêe öØ+g  êë ‰‚½d ’Q0JÓ+9b `¿½˜£ØÛ}ºÑba©«ýO ̸#£`Ôƒs'¾·[FAìë]tˆý±ŒT,ˆª VrŠ‘“PIpw@ *=\Sˉ‚ȆêhDÇ^Šþ7 öðH}âGf• D0•ÌS,ÕÒv‡‚/ê© EZUCI·BáÎ&A(ÐÛ¥\‹ L¡Y†6ç¾uD òÅòùšaÃz?ÈtYO/`‡m–Wìˆ@ì"øº9"éB9Gb=jgH •}~ „´œ¢P â=E¡(Ã!¯¸C±‰×:&pxFAlýû7&PÙèM‚ø†¸:$«œ\s LM°C‘’WsèBuBA>¶SŠp4­€Ö…¢ÖÔsÆ"7!¯u¡ñm^ÀˆX#)$[;I0B÷N`…¬"\Í„)Yh,iôæ)$Ój=e¡Qزò“à­¯#e¡PoSÕhY(ŠÔÓÕy¨Rµ,4æAò—d¡ˆ¸O'`l¬ä8 ^Ì[€ ì²´3&°¨Dt†Öô69$o¬©dAÔûàÛh·Ã‘2$°¤ Õ!aVâ1bAH…EhŠ D2¹øX¦‰Š ìÅ2Ç>ÚÞYn’çÎÀ¡SKZ.«‰x)Õ¦I寸RoIè oGnÌ£&¦Ï÷$AL´ÿ¥&[ç£ ¼9Is—%üDbž¢ÝøÈ)늳½xp"÷SÿíÌw±ßGüÞoþ|N¹ïÕä_gúßG¹×"yßí«Ì¿Ž~ܶûÉ–£Ÿ©žÇôhý×ÑÛv?ÙröC³œûñ_g?j;úqËxN9¤â\kçïç”»úßOþƤrÏ™(îçìp럳ÿ^R¹¹ûÕç?‘ú«g’¢Ÿ_ƒN‘ƒ’}ýü Â:vÊ9ýöH§ßŸéâÜÇ>Êý|RÏ©¯#]œú:ÓŹ¯}”ûú¤žs_;]œû:ÒÅe_yTöu¦žËW>ÓÅ©¯3]\~œy”ûú÷$•{ ô€.èפrõ’Êý’6ðï$•û»Çý”Tîï÷sR¹ßOWøM*÷G“ßïM5¿Nwý;SÖyÄ?š2ÿ™¤rÈn ü$•ûó¹àÆ'•ûóÙé¾Iåþ})Ü¥cùÝn=S¸õLáöɯvüó×$nå>ÿùïOâöo¿“ÄmüA·–ý¬1‰[¿žáQ­Æ_’¸­¶ÿšÿúϿӖIÜž?N⥯ ;jLF¤I¡ÒäÍ.ë=¡þÃ!¥ÜÒ<ÚlGUc}e ~GK¡ÑïvV‘‚²“ùÎb‹[ Ë.G(ñÃS5ÚüîÆ¬2¥tšünkÖV·4ù¡…Ã,3L~·òG—÷Ê`ŒbŠJ°øa£Ïú>Ô ]tsV -~ÅYË[”̹¦Ö~Ÿ9À¬6*(»Kõ:’ô¿¦zÚüJ“…`š6?Ô#©¼ÀA–… Êò"µf K+?;ÔØ]õ£'ì}Í Î5±dï£æEM,Øûšgô5±j ë ߉5±í)ô'¿Wg0Ù²ãAƒÌ>ñäÌÃxÞ˜­_߀Á/¢£c,ÐÈ–B„ 4’€e.¹ 4,~CÞIàaðä]Ù¥¹Pó—ÆÆE±Ö`P8‹â·÷3í¼Ë\Xß;„ØCÛ⋪Xë»íÓ¦ÏU±ÖÝ+VLï•É¢°mL /*p¬ ó5¼XŸ× ª_¬Ïk?U ›X|Ñ/Êb­iÖ`.¾/Êb­Ë@¡Ý¡c#Áñvß¼œ&?ä“âšó¢,VkqvÞÞ'‚ß„ó7ÖÄuV`ò{íü¢^Ó`$»Šùä]+ô˜¹!{±<_#,]E-%l~c-€´ù½Xžaó+Οó¢*l~Q--l~Qÿx²Ÿ6?Tì¥YõEU,¤¨~óY¡*ÖºtÔðÕFU¬u›P»X¯-Êb œK5y^”áX§(Ó[²+4Œ~(²ÀWòòd8„Ä ôš…QN-ö/è5aDi`u±`ô [oÜ+hZS8æ*~¿/êb­¡<3—õ÷âdh  úE],¤‹úJñ£Ê3£9¨ùE]¬_5™ ßú0Xó®òÅt`ðsàX¡‘¬õüŠ{Íx2þRx^òà¯BT´ZŠÖªÕ5`–æÊô†Œz 9ÔCÏõ† ™ç¢U÷ü´?àXð!ØW­SawÏ·zÄõ¶Ža/ÿ ­ÜÄ=R¼á_EùÝ‹-5ª‹Äü_ø«ÈCú. DÞYª~PkÀË? çjŠ {±>¿|uéô±^=îŽ~°Ô®§_Ñeþ2}ày©NêKÒhh/~‘ípÝÊmÁd¿¨ðÕâvñ]CL'LÁËEú.¼`Îâ2à98ˆÿϤrûp`©?s £w CùÚX¨Urà&Cs`÷/9p$œ™s½5fðAdçöÓ Ø†vâæÀL žج„IlN½dlŽ&I …‡°O hYýAÏ(/yè7:!i‚ ãË3\‚`w¢ÓAÈç‘]<&ƒ$ÁÌù–$˜ùÆ“A¼÷‡3Y[¢ fY^²Q“–øQ(x#ìª"e\ÿŸŽê$A´«E$¹"÷¤"A4½&Á mb²H°æ‚o¬Ý9„M‚ào®{&ÁHE¡sw‘Q0c«Œ‚ÁèÜ] #²î&?΢B£Ö¥8ðËP±`DžÒ¢!Œ€Ú®–éBºÀÍ‚‘NX÷:|Œ“áà„‚5ŠÇ(…‚8„; £ Z8Sa1Ð{"Œ~éðVøð­ ¢áŒXvÿª( ¼KU` y‰B4ˆ•‚óvÐ`ÊDLÒ`èß:OMŒˆµãWq'ƒ8ÄXGÄ!z“ƒ‘ÊÏE0ˆ–&„$ nea0by.ba0cSÌ‚0qp ,x]Ù1aµÁx1bÁL Ÿ,ˆ ˜ñaÁØ‹üp%X‰#¢e’)ƒ‰" FA2BÄ1 ð6 bm¦Ð,Øb×Ä““#ªä:Y0ò²ñ9ˆ·:Ð,1 C2Ì‚0Áð… ¢þb£ Z ™DÁÈj÷²ã@AXiøD‚-J’ ž;å &AÅÒ"Áˆá“ Fä Y‹ í¢¾U‘ Z4J¡`X„òbA´ !&Y0D4ïÉ‚°Éô „â±èìƒ èfÁˆJàj&„’F#³àެ0 î° Ã Zhé âb´ bïÕEq„Aاx· ƒ‘Øž[5Á`D7ˆ2 ƒÈÌÆ°VÓ`”' BüIKi¿âäf„J’³±iÊÎ`tÃàÎÅoDÇÈ`AXÆ(þ0 âZÚÃCÈ‚Q·'& F;¡*Q0&nÝ„‚83·ABA¨E¹? † T¼F„Åö?“ 4SB‘ $ ‘0 âš3L‚‘~þæ1$Áø•($a*c&Á(!Ç‹Ѷø"AüŠ“`L‚H0ª&NRIY¹¨Ü2 Æ1q §”äC®9‰tÁ(À')Äl«“¡Iýr l‹Œä2B¬'^#F½¡"90 ’ýäÀ(¯Ë7€§>s 1 ·õÑ ×wr ׈C¦® „,TP/Ä!²ÚˆG¡Ï[Y×®“#E!ï–8°±gr`Ë|!æ@œ]6q (ÉdHŒ¸ŽÊr`T’[f·0†Öž7™©Ú8k‰ad¥J̈µ³©r`”ää¤ D‡†%Œœ~„80R&Òv" ÙùMÑU¼æ@üCœÌ-+Ò˜# Ü-2 „"R‚`H$i+½A°EýRI04δ5‰##!Œ¨’BçôŸNè–8Ø9½8Ø]3À88w<8ZºæÄƒÃ_{òàðD“<ˆ+²n{ºy0r£³E<§•@N<8-ªMÄ]jÄ?!~%W!Û9Y„±ýᯄñ޶ãG\w„±‰|O Œ–B®$Fرx‹¿ˆƒPÍj *ÄÆPÛKá .Fø%Œ¨ ] q0ïÊÍFlqóOŒ@yëjö8 Ñ3MUÆAìp­6Æ–nœ8¨žMƒïñ8ˆßȾ.Œ`ìT} åÚI¿`¦›M¿àãþô > ‡_;ât Îd6¹ "®³_Ð9¶_pz+fÇ`¬ÑäC9!k¥TŽÁ§¥PžAF¹ÇKÏ`5‡Ø3ˆs±Ÿ<ƒƒ~%ÏàíüÁö ¥í¼-áO¯ b{¹×µWpoí,—í)ö ¢”;7ðv ¢DOl·àS·nÁõ Þ Æ&QÊ+Xnï‡í,Κ~Aø{t úx·(ý‚¯ݧ_¶ày’`ì-ÛÇ/÷‰|uò ®žØÁ~ÁÕU¤_;[žÝ~Á÷Nª“_u“ø®Ù/ˆý')Î~ÁbÃ`² Ò<X»µ÷ãl–µ& 6×óHÄN/a0jЩ…0åîÈl„ÁæÂ ƒõó1«CɱB¨cÁ Òít âWšü ƒ5¥ †ÁZ´>% ¢ôFû),¼hIMDíêçt FÀ¿;Ó ö)tC‹»’L$ b‰vŠ¡‘ç÷lìMF,Ã`Æ7$ v(' âLýô ÆÆª~h6>~D¦AØ)‰‚Á¬:˜0تퟆÁzùí Â^ÁuÊžÁ˹’a$l‰±]äÖË®ÁËWœ®ÁkC]ƒ—gt ^IÄ“[&Óàt2ˆ¤ADÇMLƒ˜:¯ †ûç v;«“»Í9Iƒ­ÈŸc× Öò[ÎBÒ`wùǤÁˆÍ`ËË`§CMÌ(eó âr4*a¤äU7BDûÑr/ DPJÊ]Ìý4M„Ói/M„xžŒÝI"\ï›\m&Âi[C!bÆ&B¼ìÜßÚ7ø4¹I„ˆà½âVp»gÄœ!O¥x>zñŠx°ìöe"B’·ÌÀ< <«ˆ˜-§g0vÓò§ Dl®*"B(#øU™cç>éÒN£ áÇb ÷žDˆîE„pÀ3k‘‰q$e!º¥MÍ@ˆ^äîömÒ‚¸EÆÄMXF=²÷ô ,ª P\ŒÃ@È¢a„=aDD='"·¸L.Bxö¹‰4â=bÈ¡°g1 !!E×C „ô@Ö&!¢`âÁžÔFܵÜ̃PFpŠ4öæ¨!ó ¢è_1âÕ=ÆÝ‘‘<ˆx$ªü̃€7Ö>3âî ‘y+¨|âÁŽ PØFŒ€3:IɃˆÂiÇ ¡¹M<g¼dñ`|Š|Ńtȇ%D5,Z?þAN·“Áª'vgÃf]œÍ€éÒJLyJ2`±s*ðUº¦Í€fÞÍ€¯7Æf@ä_PÏbÀíÎ0Ç'%â:ìÄ1ÏGhE‚Cò€ô ¢ÚãíD ÷!ö âúäÞ“O®”6{¾ç`@Ü£¥ÐV—d@T—{Omh»Ô¹ÐåX6Z¤±pzç› èdòÉ€øåT‡Æ&ù‡ "ÀÇYP€¨¼W>ø8]ÿFÀ* ËfÀiš3vë5M€ÄKij#OXY Vl‘âP«´€/Âlih÷£4"\ì« MòIeèmIe¨—ý- u³dÀ7ß,3à›Òi3à:ÆšMA M"|›?C3 T¨|m‚1y¿m(äròŠ¡g‘”U ˆÍ'_ 3 ¶Ô|%Ì€·,\ûÇòqî¬É€Yé5pëÌ€ý2Ó˜Ñ"oŸ;\‚…°;GZ2`–-šG¾fÀÜš&¢·vŠC#]iŽoo¥÷O˜ÉR ?¯ÆÚÐËÉX¶6ÔÁ£© ½] è£ ¥w<µ¡®êÚÐçôv[ÌRúÚüdUèã,=© ÍBÎV…BÆK³*oùõQ…>®w“ªÐ·§–TªPh¤‰[…¾)m±(ÁÄ"0©B±í³w²ÐpJÑ«']("°åÅ“.´:%óÖ…Öô ZêŒß†V§´ÞÂÐîG`a(ô_Ün¤04¥S© }9MœÂÐ/g’Ò1…¡·Ý[†‚`yˆu¡6Go]¨ãÉ·.Ô!) ÅV„ ”ÂP¼oahÁÂÐéüNI‘«XÎÁ ?¼‚ÒÈŠþF†;›þ¦_ØT†®_ŽÒT†Z>”ÊP\·˜¢¿ˆ]æ¦8•¡Mó•¡HƒI|±29 Ä[R†ÂlJ NeèHˆ$ýáäÒ•Yú(¯O C#gÏéŒ[¡Ž- M>„¡âÞ†^Ê”ÂÐÛ‰D·0Ôõ½) }lêßÂP2Lah±1)…¡oñÍJahõ{ba(R@I*a(V™—°'ahI¯Ž…¡eêëLahDµ“¯, µL`+C‹ÝWV†"QÍuð_4ܧG³“¸MÊО>ÍT†*WQ Cß´²¤0ÔÇ, E\SÿC›k¤0´æ£Ka¨+yna¨¶[zSèºÐ×ÞtËB[²‹e¡u;ÿ$ ­6¥¦,´õ¼bÉBaö›§;=[™IY(´­üè- mcJYè[L<–…¶ÂíbªBïK!© Ýß”U¡Õ)"Rú¤îתÐÈÊÉž¥ }“Mˆ¸Ÿ§7S…ÞuÑä¸ò$KZ¦§)ËB/×|KúCbµ÷CÃUö’þ†óFlú›Ê“÷O$uÛâPj¡OÌšÍ[ªl ©ÞT§:4m¬&Á~ý8(‚W3)°çBh ì“‚®4µC›ã¤2DÐdwˆ k¼n ¼Ôh,æ„ÀûçAê¸ K ôb´)pzC’èˆ1Sàt‚)I©ˆ†ÎÝ‹#‡B6>’&'"µ3w1¦@Tò|?#1ÑÌøH>gDÆŸ/Â$¨d¡›~ÓØÍâ¦À+·Gv6™ˆ“qyòŠ×RÄ9)ðN”0‚èê7Bе[“‹÷ÉØdÎO„`ü¶ˆwäž9át¢>»GFŠ‘°•‡¯î7ÉFE"ž=ÏÏž@,n!>])ùßa(>)Í4"ˆß¡Aðòêž$XÓ+šÞÀaø6 6ç"Ü$ø:–Ï1‚u»þ‚÷OºPÌÍâëB±TÜ_o`ºÉÒèI$è´~ ‚Å9·Sž– ¸±:Ý@ÁÛ‰Og öÙÁ5Ëå™ÎÀž¼fg`R”Ap­ÂRž§3Ð¥‚·3ðMßß`y iâ5ÂèÀ[c|­ÁIDä™â‚oõ h, Û"AX4Åt"Á·:ÏÎÀ;CIí ¬®ø‘ÎÀšÆ;‘‘&ÓÈ LgàI¡OŽÉ¸]bÁˆc®' F±Ùúq¾©”—#°¦ÛžÀê¢xé L£{zKzöí ÜÁˆvÂJ§°<¹‘m‘=Û˜…#Ó¸f Ô®@dv®' F>HN’é ¼mõHahµ"V¾@äºOŒ”‘Š,”/ÁJý£ …‚þ+Co§WLehX‘ÔÊPìÉé¶°2´v ³ì ¼¦7¥ö®+æÃJ_ >¹&å ¬]wp+C›Í÷ö*·ëÆAµ¡X'7 b=á­²4Ɖz âÆØÃ(m( ¶~µ¡ :>9kC«ë¦6·\g–8i`Ï.qhÎ9é ¬ŽW0 bËUåÅ“:ôIÛˆÕ¡xxv©C‹÷`©…Sô&6UbˆÕ¡ë㬌/†ÝHzý%"^’ŸÄ¡ûÔ‡6W9KqèëMwŠC«ƒéSž,RœÄ¡¯öˆ†ÁmôCJš™êRŠmÑ{ºã ¹ÂÚÐ÷M §´¡0ª½GŒàÎ+‘ÚЖrHkCבÖtJŠt{üæ­ ­ŽÄIm(ì÷êYÚÐfQajC±*>' ï¾µ¡O³™M4YA¤•6´´ôüIZ›Ò=ŠöóIZ´ãJihMI…¥¡¯C>Rš …Sz99ˑۭ–—áe‘x¨ßH>Y”ÞÈÿíÌÓv±ßGüÞoþ|n·ïÕä_G´ŸûßG9Ð꼟ˆÞb?þëìGmG?n9úYŸõ¥NøÏ£‡hØ?çŸÇoû–bß)ÿuôà¶ÝI¶ü‡çs«0°­»ôò¹ý’wùÜÊ™£íçÄlÿ!ùÜ~~ôpâï|n?¿v0ÆíÿêßîLmþý™©Í}ì£ÜÏy”ûÚ™ÚÜ×™©Í}í£Ü×yTö•™Ú²¯#S[ö•Ge_ÇQû5w¦6÷ufjË2r_ÿž|nX,^ÄùýšÏ­ÿQ>·_žðßÉçöwû)ŸÛß;îç|n¿ÿf}ó¹ýÑ„÷{Ó˯SÜ_ÿÎ4uñ¦É&Ÿ›ë£ò¹!¹l{Wý‡yØîÐíús¹ÝÞ÷vú¯ÿòŸ"Jóªÿþän† dÁüänm8¹Ûú×Éýar·õßÑí.ç?÷ÿÇÉݾ'Ù9Ûþ5ÿµÛŽänw6^ÿï§y[WÎñ°º{ªhŒ÷§°–ÎñŒÝ_»>ˆ#*6”«…âs_Ëd€8bîYÞã½h Œz6qÌ{+@ü’{¤¾Ä/yÎë[!~Kз^9– ï."S×.’â.ßQߦñW»Ÿµ-U„xÕΫ¾##Ĺ^-Š·ù«¾3#Ä©u«õR©p­õî.2Të“•Â骵(Bü•y®ÖW↠Z+#Ä[öÛ!ÞeJ­µ+BÜõW*«£2DæR #Ä9°ŠøâÁ L«Pa‹`5Cnûj˜kg=_jù;­"‘\¬EÐ3ƒ*j˜÷ÞØnÓ Tc͈fRxO¼¬¿Ç x‚G,i›› YVdz‹Õ°Bb ª$­U¤…ï i¦ý¡FÙ‡4GÇ”ŸêÕXÖkÚ¦+20#/«Qjè2ÐL%hE~%`äeÓj…¼®ÐRNMq…_úe’9½ýp°#Uí%Zh ¼œl "ýO“m5pªÂŸÜ©Í¢£"ßL˜ûùíÁÿ ŒDjº ¾͛Åþx…HqsÇ©(Œ®pß#Á8Á•™A§}óG¦ÀÛErÖ[¥ qáW M8†oΘa ¼Pq½f4®¹F÷bÞ2ºzòzÏh „'vòµg*FÜåívô/‰[QnñðbNjå¡!ðqzýV ˾/ˆg±¸Ç³5÷Òˆœï¬B\Z3Ùd+†Àç‘B¯V•ŽÞv¬Ò0>¯jX¥a|T¡½ ÃIÚ{Óˆ‚0,…õ>´"ëå1…–ÀÇ¥9ÖÚ@Kàc)o{+-‘y?îñZdcÏ8¸övY­ßVŽ–þ“¦ÀL‚Ö°D«â§êrÕ‹¦ÀǦ¬VošÛβ³c\¹x-]4ÂJÇžë+S â°[­,—ÑiëÝ¥%°8´aç2,GCjc¡húOø9`¾˜­ËdÃâwG7´ˆ5Ìæ7í9tº´¨¦Ú7eãpx G…¾å(–ÙÂùÐÊ×8ŠN1žŽ7&¬Æ6ºˆQ?‹§é´ÂLƪlmÐ;'¬ÏCåb·Ð°a «Š m›0Î3vñ¦ò„©Ò Àjî{ h:æQ¢°ªÆˆõL‹ ò‘’lžˆ¾bÀàìÊCÈ€Áâ…Ǥ'Ñóó1^·;FÀË5ÿ6:ÉM2 ªt5v#¼ óô$^®Óšxmp^¯–„@Ôq¢­ÅK@e?‚ÀÕÂ[œx9ƒº!ðr¤@)ã~Ðx9R3)0“†$^¶;%^J%oÄ”Hì2†Þüà·?„À[9É€0ñ’Q7ª²TøŠøÈ€ @™1-IWˆafÀÛk‘Õ$–Ú„ÀۆЄÀÛ[„@˜@øÄíéßh·ù†@+¯6:Õ£ P _6:ú"i¦IÃÉ€–èntúf@¯@›‹‹ûüöaÀÇu3’QBx'ÌीN™è€Eàc-Wàã*vI€ˆ¸{b"ÀLtŸˆyˆ4l|]­1 БI€Y"8 -|×LÈzMSUR`Óê‘-Þ3s]R ´Ž÷‡înS KÔm ”áoCà훕xûõ4:bR`u"ÒMÍ“uRàk;ÚIƒ-¢Àê~IQ²LuR1¾!0_û„@ï&6ÞÆ®¤À'On ,Ú{%:¨mS`“ÂÿC…°f ìÚim tÁMiœ¢cH ¼ôì ÍQPo/\òÞ (dN|¥Ç=6”Í€v/ml sÛ Ø‘ˆhÉ›-‚Àn›lBà-¿Á†À;Ou@`ç©!ö/jï¿ðVŒI2 ¿Ì –"m¬š¿Oä{¼!°Ë²!ðѼûOdxKTÎ胻“‰'"\ˆ7²x…»‰Ã銧Ë$®¹.ÌÓy7’×–Yžq ‚0ÄxâÀélÉSQùÆÀðš<'æVÈزŠ)0 ¨BÐ9œn”7ÖÑÕ¼`Q`(Îe0=U¦@”o¡7Æ8fœ_&NÇ›ÛՉ’C Ân­þfÀØ rÎÀ®œÈé ¬ŠO2F"9RØ£¨€.aÛö¾2”ãþÒ“{øå¾L_àPijÁo1` ƒ<ˆdÀØ ÓMkgàíE$ˆüã@@ ÎØ8¦(pª¶ëvÞvÆ¥+ÐIÙ·+pø•NW cNOW œ¿é &¼tNógº‡Kº»?–tvÒØv6³]—Îé Œ ³d>y/çSÛžÀws¡ÒE¿²×ȈlÑ?Aàë·ü @z’14yãì tùí lZLOO §Àí LÇßöêëNW`ÉÙh÷Ívæž;]— üvîSàTÔǦÀiWLRàL£)px%O ìÞ† á¸j_ ¢}¸cI_àÔǺ}ÓÜzøué t†æí lF(sà­ê[•dû_Ùœ6ïŸÒèü›Ÿ¼Q ÷6:©ó¦@ךI Ä|}·œIó7!Ÿ!0Ý­ ]žÝdÀ©x× ÃNˆ„À.cÖ†@'ßèd—š²6Òз!P‹è†@Çs^ )=ò¥(pøŽ›«ŠF&¢ðk¬’:%"‚üù2àmž"ø„¬fOàÐýMÊ” ˆ(-ùðÄ€ˆ.˜Oàëˆ÷„@¤¯çÌ‘›Ï®ÀæQ_—›Jli 4"†‡4œ®@Û_·+p;õì T!¸'P-e)0V'ØxyÞ0fĶ!°*ÙQ2 u|V,óŸk-&þÕ*cqâ>_3áÖùu“œ}€]ÖíÓ¨y;ñïUZ¿Í hÉÆ—Ídd›ÿ.9ÐŒ™³4ñ/*Í’ä„íÒÄ“ø‡–—Çÿª#ÿª¦é¤¿úþ윯‚Š“þæ%·ÓÆ?'Oü»%ÏHüƒ_SÞ<áœA[„0â©ñ¯M™:ÿà þý½„n'òaky"ŸuHùš÷áÉ|ÃdfæC‘–tV[ùùª=L‰|]¹œ6ò9B"ß´ '‘o¦N”È¥RèsJæ»%¬ÙÌ·éRЇPÙª%†Na¡¡œÄ_CßUäñ0óA{((©/¹¾¾¿žxfßß°ëʾ¿i×Oúþ¦È&]Ó[üÔ€ZgÏßp¦Ê¤>X'>ž¿ñX~jÏß5|;þ^»ÄÒñçäÒéøKãIR_w.Á¤>8ËG:¼=·ü Ûóç$VÛóçìŸÛó÷È(´=Ît$ÏŸ#Ž·çϵ+¶çωfÓó—¶ ;þ`ƒyNì /äûqü •qKßÞ&q |Û bßß°Pnûþœ¹|ûþ\–tûþÊ®?o{¶ë¯øÆ¤ëï6¯¥ïoŸÉ¾?/FÛ÷—Êaûþ+h…}»Ú³±o—w2ö¡EÞ`a_dÿŸ§ó/œ«õľÈÑO3°.YÎÞæ¾Cì,î ÓJì Í}¸B½7â¾]¾ÉÜsÏ.î ûÁ}j@1KIŸ(î íu9¹/_c_“ª§ó/ÀÜáûbÊä‚/ì {íó¾]“ÊØ·åÙÆ¾ðËHì‹[Á°/ q_§-²ü‹ûÐB»ƒÁ/ÉÜÿ ü¢ŸtÛ[ ~±¡åFà/ÓuŠ@ÃB$°"øÅMæÍøÅ©¸ø…©ŒÛ3_, Ü@ˆüâ˜ë$¿x§÷‡Ð4fò;ž°È/BWÝ2i¹›I¦"¿Ked ~(áÅqü"Z•þ¿Ì5šèC—ŽúA½Î›lô»\4ÑoµhXF¿ˆ'Ç ý.çp&ú!ÕöûA¿Îrh¤ÔûÃD?T‹'0ýn+£’ý²VY²l4`þnWõLú»] <és†ôœ¦?gèÞôçÂß›þ’*L.Ù´éÏ%Ð7ý©‚݆¿¦…ò„?}‹ Í[wÁpõã|š°†?Ä|RÛløË(ý¤¿§ÛkúC¸–PNø×'ç%óßã2² €PÈrB6‚°9*à“N6`ºPÍÌ…³ñ¯¸0Hâ_Iߘño;1™ª5ñ¯8eFâ_ñ˜øWRÞjü×-Jÿ­sIúmþC²þá¿â’É¥n"$ÿ•n“…øÃŸ ѧgD¡ ‚˜°4ëR eÚÖ`D ? «ëÅð¤@$ÿq0`ÉEÐ ˆ4_`±"0‡ ˆO´ÄĀϫ‰?!ðiŠÂHDÖO”!°Ø ‘Xl¡2"WÒ`ƒ 0ߊ¤À×Åò’‹Š5&¾®Ùžønz#–|‚À⼑ HTù#A`±É9![ÁÊA`±pëŸÈë¶µ ¬€pañ6þЂr-ÜZÐáíXjASaf"ìÎ9˜D¸º£!g‡:éÅ ¬#sX`<ï°Àá`¥ œ)•4‹®¦txqI1èŽÌ³Õ«tɃ"ŵuƒ¢~”.b“~À¶e?`ˆ¥°xûf?à#wºwD–Ý€¸àODà!³ðhqLàk¤µð±´"ý€Xi‰§èjé|œÆ-ý€Ï›±…ôbµãŠo? âÌÆ‰ƒGÇéÌ_¥ðsgHàëèà |½©ÏÀbÇK†– tHà»øÊû‘.<±#]T"#SAj<qH  LïÀx†V3Q†Ö߯©Ý{élFŽtvÃL:{†0ÚØ²˜ŽÀܧ#0ŽéìJ¶µ°”Ž@'ßÞŽÀéØÖtvßõ#$ЉáìL‘ºý€Æ€tNk Ó èðûí´¶#Y›7ùëì´Q;/…i¥#ðM¤´#ÐÞØŒ¼SdjÜGÇÞÞx;ðñ}It Ò&ÁagKÆ^ŽaKÀýA<àcYìx+ˆ0ã“1wL \ë©­†ÿè¸ÛԃΠç – >3 VWÇÜ‚P‹rSzË¿¡U{­-­v3Yºûµ/°æõYúÊ,¹¡õ·/ ¾·­•àЃêÅI=h>³`–¬›k†D§ T»Ãí |GjX•ôµ%3õ N7½õ ÓNÛ#*ÐLëA‡¿ºÔƒ:+£UÓ!ø¦ôÔÁÇszz]¹c{3®Â48lS3 ¢RÐCu¥`Q?7±ÎACe *É•'UÖ§(wõ Ýû¤¾¤YØÇE} ö¥4—G=–‡þ‚¡Ö ô%ÍÚ > õ%-­ã㥾!ÿ´©—ú’µ—SrÔu‰b—„µ%d†²Ó1XhtêKÀtܶ º)²I} –?ŠÅæE}IwŒkŸ7õ%ÝI´ú|(0é¶×.ħÀ¤§sa¾˜@Ç­Þ|©0nŽ®ƒY©0é.JÜg£ÂV{jv*Lz‘à©ÏA…Iw™€µC Â¤ ûÆu…Âùõø÷MI&Ü×CI·\…“îÈìõ0)0é.˜°Z(0‰Äúl©!0éΡ<®F ,ÿ±w^FIwõq LºIn= Lº«¢û¢Àäh¹)0éVqû¡À¤».ëzÛnŒ!.û¥ÀއÊ~^ LðnÄK:îJIw…»Åˆ˜tÇ9Œ»‡À¤ókf y ˆgÜ“ò’î8Ãñ\”—ô!ðø€¡/AÚ“x÷×Ç@} BÞx»žú’îdãy©/I[-Ô—@´õ²¥R_ÑïÍÓ¨/éJާ7Ky³žAyIwïñLÊKvK¹(/Î:¶>VÊK@ì§<”—ÀÆg*…ê’̧²xšêØvy+Êê’L\1J¥ºÄd7J£¸™Q:OÝ).6$Œ2(.&3œH£LŠK"×\Bq ƒÇ{S\‚cBÚ2Þ‡êôó°¥ÜÎÉ©c¼/Õ%héj¡ºª<¾%oLéDãÅ(¢FññöÆ4‘¶Ll¨kÿ3_Ké õ¢¼-1-z?ÖR×Zò’a[õ¨å²Fþ‹Q_ÊK†]Z«…òT‰é<¦fÙ·Îô ¯¦þOåeÕæ¶÷bjÎÊ¿¦%‚´½ŽH%Õ©|-<&òßá&ÏÜ›5‚4á ¤Ôlyphã:P«½oiº¨£ÙxÚFDmG©Ñ‹ HÇ4P.r2ý =Þ«óEw%—¶rþæf/-¬‰haí‰õùá¹iôHÐù{8CÚzIÚ¿â ;®X!ÐÂËóµ„Íb º`£§”†Ž1z–‡‡”iy -,Õñ&«)èÁâEŸfŒÈrE™a\/Öæ›jdªSÇ•5ŸøeŒù²æóÐîaÌ«°XÌü ·{Tû2.À¾Yîk·”¨3¥¼ØM™,÷•W<ßñ-÷µ¦ãNuàÏk`u¾8NšÇŒç»¬Ï˜‘'™iB5æ c"Zh‚œ×UXðK3ñ¼¢JQ4P4¯‡e†å3Ô0}ã˜x•&*¨užŠÏwþèÔæª5Q@MA½ô=NP uà¥ÍÖ¼"+eš1÷M¬Ï7sÒ2ÛÄúêÀKŸå¼1Jaã5žwäîˆC¢´ÌMuàM‹ÈÚH]Ú¶>Q@-ÄÎM4QA­óLt—OXŒ…¥tpL”P q ÓïM”P w¾«=N,Ðrçs6œX oæ¢ebV\/“­7ç¡?ÿÖFx‚Nø#ú@æS.úóo…P­–Iy “LÔPk(è‰jýýÓåך¨¡Fi.§œù„–û`N,Ð!|´›™X oJ|éýžX Å/óe*3–ïžK¹Ú[´r­–É4¿Â×Þh0ϯã¶'j¨Ež_繜¨¡† “b½›¨¡6Ê==QCm>Ÿë™ï!”œX ¯q¨n'è›ÙŒ¹­œX žˆJûùÂÞñÆ1·[&Ó; ëç‹Üì†÷ï D „Ž!¡‚ZŸ~cLJÄ=ßXYÊ}ñG³Pãýj73±<_<g‰åù>)&Vç›áÜÈ‡Åæá(õ–TÈŠ*ÇÄÓ†((ˆ!üÙôp'¢¯/*u‚¼Ar÷¹AÐìh ìº]oc`—Ünc`æûK t¥CNèC;ÀÄÀtj$6דK ]xŒHýð{1 "™ö“ ®‡/H0Í©I‚P°ð2 â’…†Á=*ƒ`¶ü)â’a¾ÇÉ‚0:~YЖJ£ Lx<@$ˆ æô3 ŽîÜïfA Ó{f„½³Ðq'LÃ_²àp-ØdA¨ºø#¡àp•€DÁá2׉‚cü&¢ ‚Ç^‚£'tÚ£ßòÁ´&f¥ØÁ™Ð,ŒP JÙD‚ÅæL$ˆch3 îú¼&A„kpGjŒ–yú£¥$á L’!Ü-"ÁÌ<‚¡¿‰pJMï©„‚[KnÜ:q£`(j VDÁ©È(Q_íDÁ-Þ6 n¸Q0±Ü$Q³âúx·Õ(ÁXìY([4¢`ôC»®XQ^ò]ˆÑÂT½fÁ(³ÎŽ;3u¥ì1 Fba¢•P0âP„h—ª9ß´Q0RÓ5!ŒhÞ/ ‘cñUÑ¡fJ F|ɯ*ÏX×êjÜAfÁaD‹üNbAhÀO`ìÉw+¾àöNM,‚î‡tX_PMÀbÁzåkB„Nœå¶Ì‚ñÞ¨¥)¾ÀYoÌ‚M§Š-¨vDNÅ ÂÀTŸ›÷sú£F Ï" ÜZsS ŽÑNXêsÞa`¼åDb †(lj004÷‚0ðÿêîìV}É‘ì~?Oq.» ³Q~éãÒ_1¦æŒC]`ìç·–b­ʽOWÕéiC»ë¦{ÇÉTfä_©ÔO±"”ÉÀÂÀµÏÍÜU˜[иä+ „…SØÀÀåx¬e3ME¸2N±»™\AƇÉÚ'H¸êŽÅ#%®”‰)vãoK \‚~òZanÁ­¹;)p5/3)p¥í¡ÀUBìt(p¥âÄ )peÞÄkK \;(õ=¸Äzx„@Â¥ Bàú-c]‚¸z^üÞ„ÀUáîÙ!p==R×Éä%W ϹC ,QûG¸œ`;òÌ9€WJ,׎¥ B`æÕ×YöxàÊ;cTî8™I™¢Àµ]Ør“¸†šNËprX8E \i‘W*X …¤À•œAKc¢ù¡¯)p}“&WýÉÔ¸º¾W¡ó¬¸²öbð\•ÏÃMB`ÖT*±O¸*ªÇI\‰}±ž@Ü> DÀ¬Þ.\gaåÒŽqŒvwK0àjçÜpUKÜÃëKÁ@ÀÜN¸6m#®+Eˆ„¸|`ð/p?&p=☮š‹$µ@À•Myí˜åæ…€ùÛ WÃápý 1 'n~×÷°íñÀø†Æ ®òü¼zPàöHIëê~!®cÈ… ³+ aa臸ž`ijÈ+Ù´î¸JP¬7DX­×g?ˆ„ ¸yN\ïct‚ë™®žC\w³G×oœE \7Sw \{0b˜³aàn \í9·ÎD Ìr§ —×cÖÐÂ~K \N¶±ÀÀe È"®GS×…ˆ“ëZ%,ËÒ¸uIbà*pËÄÀuÌ÷¸ubàªá403?EW¯õ- „…aÅÀÀõ@ƒWmÝ'”ç¿Z)Îä‡u¡§½È¯p—ä§õ£ßc~¢ßAýI¢#I~*î•äç2ì&¿“?m’Ÿ¶qKòK‹Ð/ÏúiÆD¿“ú„d?ULKø;¸>Gø;¾3üqãŠd?_YìËõÒ‚Zñå( ŠšÅngŠîV;”¤(à*¿³ß:ëÅ~ë˜00ØÏHws GŒ] Š#b¥ `?£:ªc€¸—ãÄIo)(,”˜2¸1@==‡·#ì„)KL[įÅ ¹#€¾’€þÜNbÐKTŽf3 æÍ(è54óÅÿT1Éñ¿•|ø¦øßL*þ‡cbŠ¢àJ¡ KD±"T…»§Y bé4É`WV¾C€©™TЯ»C€©¢T05“‚j-Î1@¿…¦úÑJГÃr*AO=0±°U^A@,’%½,•ôè[ zYt*)è%Ö“ôb²e*A/ÉɬUÙìT‚rë¿‚z>n!è­ ¥… *êl!èm†”T» ¥Ô˜l!èÃþf¨ŠP¥ô@Hê0—u õs»—SJhµèS2P"h瀙*Ю%«@› R*P‹ú¬ÕÂ]Ê@;Ë|¦ Ô2?Ë@=Ù¨%}Ö¸u ¢°Ôé­’2X:L•Ò½ Ö‚v¬M #€Ãl¥ äyq0"€°Äh§à(ïE%¯—ê¼wÐz=G‡Ί¢º`¬ž)(yž"€PçÑÀà𸠠iŽB÷-ÑoóÖ‚¢ä$ƒ{  žtuK¡t 2eü†°(þ7´_²ã(¤„«øŸ·ôSüo¨¶ºãC•çÿƒ ÇøΊ…Åÿ c¨‘ñ? ÛÿÃYÑÓÿsI!Çÿ,7SøŸ‘úÒ‚"Aù'ãC%¯ÿÃ÷ÿ F£Tºÿöîð‡c–T ©}D!Ö‚ú,Æÿ`ˆI¾µ UÚFkAU=Å *‚–bP-v§´r)$Å Uø`1hÕÌßbPU“L1håZCŠAwTH1h¥zÐZÐÆ€³µ Ú,µ ªm™ZP†L-¨6S š×–T1­U:jAµ+ujA;gÊ©e2iJAUQ;¥ >DJPí ™JЮH˜• Ú„8• ªÿ”JЮ›• RÝ¥´›*GÜÝób¿u!Ò—” k¦©Õ~–©íøI :„í–‚jM:¥ i‘TµÝR :¬1•TÕÞR ªrÞ)å†Ö‚*óS ª2k©'[ :$E¶TÓ BÜ.…Fj—ƒvÇó$UôD é_€!A°©ø§AuÙ^ ˜inAèÉú++²ª¨!„´©¾ä ?b_‘–¨¿A°qkÎL l¦>%6vwR wë”°°L¡“çX™ÈuÈäÀbí§8Psñä@}q“F¹’O¾G;êâÉLª4^̨KdÍ•AŒ_Á›AûAÕ´H¼µotÒ‹Iðù ôS ¨e ƒ`Ó Ú$ØLyÍE§‰D&ANtÌ(Ø4 ªFw² '†fAmÕ˜,¨mF’‡X0ˆ9UD݃CÛÉ ½å°ip ƒÞ9Ì0ˆòÖñÃÇiÁ(ap¨â™`PuúÍ‚[»·kN“xÅ‚˜\ö—t8"%—B‹DÁœúñµ‰ø“PlÜG´Âß$87 æìH$è)‹HíŽWN , b:2^IC…ŒL‚¸qF$I‚ž¡õµ7 z’eÄ䣽r½-™QПr£àPm\£à¨Î ÄvS¢ ¾ÿ  º ¹QpH½oÄ×=º‰XŸîx:dA§Í‚CPš=0 ¢áë%ÕìGÄÔ'úºhŬßrСê¦A<ÁˆÏñÝc®〥(’¥8`)J&S °Žó!è#,Ör ñá&è1ˆª›Ñ)ƒ(yÚ÷¤Àui##¥0·ZÀlFÀy„Yp¨G*X¬˜W …ÉÛ\+† ±Ã“„Ÿç+1¥6ad —Š_JÀ¢¬1fN_ñ„cñN@”E§²“‘À¢äyG!„‰Z‘Àüi ÄCƒ"¸| Äå±¢H ®Î– ÄN LØc(л„;ˆûy‡-ÃQ(Ð;€;ˆCꞸ6?v\*œ÷*ˆ¿‚pôz‹*µ9ˆ³Êž¸Z~áÚÎñ Ä–€Œâ1XžO¹u š Ä!uçÁÜlÒÁ@lÎWb,°èµw,°H³ìX ö0ŒHcØc1YŠjæ DU-i?#X”¦ïP`Qr¿Cùh ļ øF¡@Te ¶R(°h3T‡ñ%Ìd$µâzÄÕ „›Az –Æ9=ã€Åª8 N¹w9èúá"Ò«8`© Î) ˆ:¿mGÁu»DÊÉŠ,f"…Ñe _ ®JŠ; ®-+û΂«Žp°Œ¨Ez¼Esaó +ˆÊ™l‡@TŽ´Sµ1£Þì>Åf]˜Ø@lZß"4È@` 2ˆ²^íÄY}Ï \×ÚÓqwÌÄs°H§«8 žÓœ–ñJ ÄYŒ;xèI0Xz|?2 h­´Ã€…šuÇ‹¶Jv Ã;йJÜQ£Y•è8ŠÓ³ö‘þm¯ø¶‘Ççß;ç÷W‰›à|ßÙºþÚª©É–Õ˜lÙª©MFiªö/ù׫°ííв·3–úqÚ[þµ·CÛÖŽ,¯vú™­ôósý|·Ð?U«ûËT‡›c-êŠÿyÕáŽçw‡›SÔß]mq¸O]x¢jýè.ßõ¥Ãk>­å¹YùMçï¥ßÔÆvÛyŶ²ö›ÚÚ‹¿©­í(¶õ:Jm¹ú›ÛÚÊ¿¹­r”Œiø‹Q`Lº¿ãÒç±VQPnĵNÔŒúÆcè ZwZèÂ`|Z°?hXÏZÉg*07ÿÆ‚õ²TºyB²,¡œ˜–ðǰ•+|h̃aȰ&¤Ó²4¥+çš.Dvz$ MËåLs5]ˆœv=Š+\Àç¹ÐR¹+èæj‘ë X˜,¬HrÆ{ü¶×P¢y¨ÁæøRÖÄ â§,áŠÒM =І/Ó‚jó‘¸}ǵoì’–‹gacße‘7JwG€Oâ®ó—cAcZ˜òñðù7žc¿@Œ‡Ç#Ñă%”eh<å)‘g®­‡§ÎÈ›~â·}èÀÃ*ôÓBžvˆgÞ?ËÖµðè™÷™Ô5nföä=D1-H‰tg>¼§G‚q¬Ì¿é@edï(X«¡…=¬g5>Ì%ÇH»Ìʈ<`>‰µËÓ:FïJ¥ J0ž–éBXb½rZP|Ëžt†°°Û ÷ˆ³øÆc1'KÝ¥ÑI˜a¬l*”iÁ×â[n4-ØH`Y"ÙpZ°áÕ–><-÷ú˜6a×´ÐåºN }èŒSM Ê"¬c.ž)Ó·ÜùtZP†(a¯î¥lq ü=>"ýôäÏÐé‚’j§….øBûfE¬èä!ؽú[Õ›–'¨¨Düf¦±Ÿjðû´„(¡Ç·½‡k»ž…Èò4ÆGhÆBv?­WãˆbcŃÄ@‚ÊŠR=ìÕƒ¨Ò´Ü-tr)Ócõ3 l¤½ ÆcQmìð'`@`ᯓÇЃƒk° ‰Q×Ï©@ç^¸±Rà㲩  Ý=Æ—#ãUgñn`ì¡ì,?¼ß,Õ‘Â/-Qªï@ý 22~9ô€ÈåÆ#þ±Z,À2>"á3J'8>pDšÿõ×9ÇmÄŠÔü™g›nZ¦”·ÅïtÌÙÖÇõ¾=¸>Âǃ÷}è<×вž‚Ò`ë~*§eÕæîÊ$™÷V: µØ´!V²Ö´œÜ¦7.t^uSÕÍ¿çÝï°Awœ2x™EƤ™ÃC9?X¶ïâYv TÆÓB}B¦eÐkâóa–5eG;ñ9®cM„ºvˆŸl—ª9þ×Åâ~ÿ¶k•pž›•û|J]¡®í§¥­‰Pצ®ÓÒ#µ¼r%Ë å#jùÅê,á‚‚¡ó×/ÎÊìÃÖ¶Àë´œk"äÀë´\ÅlçfÕÀøÊ·}EܴЇÆÙÝq·“NñÕ>î~Ð)ßÌ([áCÖT®kÓÙ[‹Å!6šz ¼’i9+-ü½±[¸ÄIÀ†‰Ê•÷÷´# àÛ–j|8‹ýˆÀ×´i­ÇœÕÈYôáñ¬zŽ87àóv>Xú øpμ|kK7ZèÁ£EK!ÚÑ•™–¸ƒXÈ¥§%d>,d±2މ>1t_Â3ú08•=¹õW}Я ú°&K@ßvw„¾¥ÎzAß~ez щ¡¯)ÃÚЇv.ÒY@_«¸`¾ív.º èAûàt˜È‡!bUKÈ—ëpB¾¦,h#ÖÏ*äCÃ$"ÖËØ=‰|8KðÀ„‚w…–@>¨› “D>\]@wÇ•Ôí‰|¹z'äóff>ȤÙAÉ|X½»h ækú&CŸKýúÐÁ‹.$Ìù¬È6ô¡üi†Ð×מ¸rå2™ë†j–̧ô+3*öJ}Ö†ú\ùÏÔ‹`+¸.Î ~X:dÇ!ùi“ ƒŸËüœ'*ð+Ôàüp{9ÁOÊtƒ „1‚_Bîs½>sßv»ä¾64 û<©2ö)‰ÕØ ]bšá‹ÚXÐO $¾SËšÆ>1öy÷c†b®Öû6È}¹`*îÃù(È}¸Öóâ>,¡²g‘ûðÆC;}Ðྸ/—jÅ}.ágîú+Ÿ'¹Ïy¹æ¾~øÃ2ìž9¹¯I²õUàÌ~XÆ¿Ÿý\GÒì—/I°_>±_ÏáÏ5 éœào[×%üá'¼H`Þ„ÅðçÄdÃ_þð‚?oÔbús‚³éÏ Iø›ÓkÒZ!Büm{PIhv ¿"}ÛŠ7Éo;$ÀÎÙI~N17ù¹Ø‚ÉÏ• H~{+íz·ä·]8Èo;…䇓l½}ÿzn·ï_8NòsÙF“ßvq’ŸkHšüòù©ÄÁÏ¥) ~x®W˜Ï. ~hôxÅùò øáÆ;`„³>ëÖ8ÁÅ3ßÖÅ ~]Â>“_?A~èƒVû ×‚ä·]›ä—‘‚ßf85N\î ÷mW®öÀÄ`&Xøº‘ûT­ÔØ·‚ú\M€Ô—4ß~á"Oóíëæ}[#„¾†}eøx }®ëjèsAC_×~o†>Õ‹5óu¯â‰ùpRL«ƒùÐìñ‚>W‡5ôíçÐ…¼™Œòi‘DЗQÉŒò™7æ³Å.4öš ó)D¿…ùøp2ÎÇy–ã|ïOÆù8Ouœ/ŸÍ°Q\Åùòþè˧£@_I¦c o»}Å<ìCµE>°Gúr 6"} o:ÐçÆ>ßž}%IÐ.裯@_~ôèÛ, ôùv o»}%Ãxé:è‚Z‰@_aBxú¶#èsgs o;Æø:é‚ •ÿ)Ûš!ö /Ë+Ô— ûrzÊ¡âU÷þêXŸû•c}îWŽõmg1Ö§ …2Öçèµc}ù3)Ö—-+Öç7ʱ>¿-Žõ¥}àûãX_Ñ¢Žƒ}îÁö‡NìÛÚe°ok™Á¾­û0Dl •£ìËç¥`Ÿß1ûòéD°/ïï¶ê°wúÀçw››| ¹i˜píÛîᾜñ>éƒ,éËü¶·Aá¾tAá¾|8îË1@á¾’Di4(Ü—Kñ¾ì&Š÷å•ðK§òËw³Ú½TÕ>HjPNºz5:©KŠý8Ô)æ—OO1¿«]ÐL59éñ)è——VÐ/o˜ð×½B½ÑŸrÒŸúRÒŸýŠâ¡‚?utÁ_:•ðÇ.‘ì§ëôô€‚Sþr‰~jWè—7—è§Žþ§Ñ/_V¡Ÿ[!ú¹ ¢ß64úé¡_þL#=à+–è§NôsþÒo‰{}){Þ¸ÇHè†{Ô4÷ô½OÜSˆ&q tî9„hX’Ô'qO3ÝÄ=ÍÍ÷|–qÏ!8ãžæïîq~”¸Ç‰hOº½¤=¢qOx‘¼§cøžÏÀ§»Kàã*ϱ?_•BÔÀ'—ø|mypo¡¾ýÂ>VŸ‘ÊħçÄ÷¼•—™—> ;·›IàS¬w>Þ`Ÿ¢U">KHûû؈Èeàã²Ê|‚0Ÿ-v€+ï;ð ïŒKÒª&ð @7à“ÅÀ§Ž÷¼ê(îÀ§sø´’À§N¿}Hä3&&òñ•KäãÂï†|ò<‘O¯\2Ÿ-†>ö1Ÿn&¡O—N軄f†>©-Í|2X×y¾‘oWz2Î×µŠñk²ÎÈÏ0ßptÓu¶ ùÚpð2uµ~ÖuRz¶é:[ÿŒ|’রSÎ_v*8Ä'ZÚˆïèÛpn¾OÂN±°€Ï°žºN=†ÔuêwÛt|KSØ©@y ; ´°ÓòÞa„xï4 §°Sëè©ìTTDÊN*£we§ˆÐÊN[¬ì”ÆjSv’jRÙ© B*;ó4ðŽ ø6ͨ•TòøR)e§$m·ú`”tSvJ˜ÊÎëðiO“]ÙÉÈù¦íÖ ø.Ohþ´¸3•§)îÖJÜ™gIÜyñ—“ºóS GHË™êN/SÝ© ŽˆO»J'ñ=Ò¼˜øn}76uçùEÝyHËiu§ÀBÄwð%î´ü“.<–smêN @SÝ©àï±m@½ë;ÇI}§tÁ|M _ý|MÊ_Æ`|Í!cŸJFï O*, |Mý¦ÚÁpŠ<Nï©äeò^j_%òô…|Mß$_“PÃÀ×ü>•QJàkŽ* øò,_†š|Mïy*,߬Sµ Ô"OuãF…$§6›ÈÓ2P‹<™1câKÙ§ˆo(ãÃÈ7üíH•gQü/UžÒkù†GœTy^ŸTžÅ ÍÎý¨õíèÜZƒ@ª<­&¥Ê³ø["•gÑäaSy*¦™*O T¤òÄ?PìmWy‚1v•g׫g•gwÜ&Tž)”Ê3çID?(âÊ+Ò׊¦h$¿MƒFòCw®ä³ ¿M­Eòk§§/$?(™8[!ù5–í0øy;LƒÒº8+Ф¾WŒ/³µ”Ï—¹YÊç«A*ŸO[;fB_3#+¡ObçóåTVù|&2Ÿ¯kÀù|Ci ¤¾b%æÅÊíš(ŠúŠÕhI}‚ó¤¾ËQŸ£z¦¾Où|˜üp'ì»ô0ö©xrbß%=’±ïfÙmaߨcª£˜©°ÏIæ¾ÛÓKqßí¼Aq_ý8_ù|.K—Ø÷Hacì{œ*ìóÌÁØç”c_5ÿöµŒ1Ò…–K2“Ó7Œ}[Þ±/sè„}Íy‹Â¾á]è™âG곪ßÔ—ü#êÛRüH}5\„}ƒ›m%öY¯bìÓž)ƾß‹û\„Îà‡µ¼ž.)R%øí–ðax Uä—³ÈC÷x‘ÐC9s ¿Û‹ür¸ùa PHŽ>\ÜvÊä‡"~|§H~ûYA~¸?è—éB¿ÙŽ-ôáô ÙŒuL€Ê^›Èç(¯.Øo8qMð7N¿‡„?—4ü¡:˜˜2Ài?+àÏE„ .rløC)ÂS¨'”MøÎ#ûåIÁ~¨.¥Ð^°ßxÌ@d?W+6û­¤/‘'*œPv°ð'4LÑo<¢*RMHôUoŒÐÏ%—‰~®œHôSí]“ßèN®!ùåÝüð´ãý·Lûãý߉yMø•š0oaÊØ;üpÿïPß´pCîÕJ§Å}¨DH÷¡l¡þhB©òâ>—p6÷ §bˆû\À×܇:ÙŠ)Ò¦I܇چoîCíÅç•Õ§zƒÆ>”$”*”.pyCÜçZÑæ>H4¹®²¹od’¹Åh!÷arø–x;x ¹åûúKâ9†{Q€ßªÈnCðÃÕÇ~®¬lðC%cÞ_€ß*&ÈWà·ý ?´£cø­ºr¯¼¾u7$8º02d·\À¥´2AîÎn!÷¡™G$¸¸oUZ¤\÷y¢dâ)µfpßævpßþh‚ûPaM©”ä>töâ¾1œ··°Íûà·º_pߪQxîÉ}«X¤ØpA΢}8¤ŽÄ¾UqWx.ËúÖï$R\À%áxPß*#Èc‚ú²f¦¨o÷k;õ­G~í"O´,Io£§1¥Ñ…Ç?T`ßþˆ[‹;V˜>°GH;Ø—<…}8Fob§——Œû–Ÿì}8K>ö­r—ÇŽ}«Ü¢¾eh;õ­ª†— ·ÒN{çýŸüç}«Ö¤rýÆÇùj3˜mhräí‹ yûÕ?w0ßz ƒåƒ\Øí|ÊÃ:X“énTÙm*ìÆ{vÛŽÈã·Ânß9ç »¨p]ÕºþÚ‹ Ñ¶ÕO’e/¤v¡€à­vô×Þm[;²¼ÚiýÊqúëÕNØövhÙ۹Ϙò©ñ¯½Ú¶vdùËx;WŽÀß\·wW>Ÿ3õ|ê¸E£[Ź[é6žÿ*ÝÆ6¶£ØÎë(¶µ•nc[¯Òmlk;Šm½ŽR[YºMmí¥ÛÔV¥¶ö£ôjfé6¶õ*ð¦W:b[N·9™{V5ú¿¥o¿2dþôeüÞ ùÓ×¾úiÐüNýÒÆx; ¾ ¼m…×þßVxËJr¿ÕPÿKTu;o,šüÿUÕ­¯ªÛ/µÜÎ縙·x ‘^S·ó¹"ÿž«ßÍN¦¼ÇÄè|žãñ>ꢌ÷ÁcªòÛ¹>w®L­È*t凓ϵ?O”[ ø=W)êµrÌØÙYç‡ó†k|šá'[µµ³Þ‘%Í5´³>Jg$hRsa&5×â¦ep…ºê¬Ö™IMkÜ?¾‹•‡ÄýgòÙÊC sSÎvÜL9æ vríÅ”c[®“ º'Oº_¹·g£—¦×g«…"ë´ &·rÖ8ï®ü\þ(­7¦²r‰ïl£2?—É—g§ ·–¨&v« ‰ÿì祌ÝX½?')¹•¿B¿&·2r1-Ú¹vsöêŠf:¢ª¢Ksï´0çýì½q5žÄ7›«\'៣]Wy$‚‰WûšO“‚¾þ×uJòoàu]®eƆ¯[z&¥OÌ*ÔÀP¼0-ƒqIýºj§GŒR\W“^„K#×Õ#PÄUÁë¡á +_wy¤‰WgÞÊM Ñ×}J/Bz¾æD‹®4]·=`Hêºésç¦eÐ']ªvºÄõŠënM²:y÷*YßM¥1bØêåðŽK|1ƒ@Ǫë¹$áâÎõÜ’‹ðCs=ä"|¸•T{=U‚Ž<×JÝ^.»^«\×·­|Ùµvщ€XŒpW-,¥ÃíUé‚Õ,W¥ „SW½$Ñ“™÷@§t¥úH.B]Ü´ †çð½jíZ?à˜QéíOÄìiU•è¯>†ç(V¹Z¹žÓý´#®­Ñ _å—æjôáQ±«¥hÚ£‚ózÚ3蕞E«^é¤Ö(ãaXèjÝŠºÐ†/|°aZøÄj 6L£Z$Ô!W?CåQxÊ%±µ6¾É,ÚVبîû#½‹›­ £2(=_\‰EŠŽé• .‡_Ø1-´I â^ƒ.4…¯AºßLl™Nq øW„5úà£Ì:g±á£LÁ¨ñ z¥á¨¼0¾pÖXèŒKÝ×èU~°cZ]áMv¤;¦µý~nl™ö’ñÜ…>tuì»Ðf:Ý…;äRépã«Ì0jcÏ †#ÇœõwŠxø‰½‹= jô.ö€¯ü]Æ£jt1¡¾±a ì5ZŽKåô¢ߨ0>Érú]xõƒ>ćï>¾¸€ÏrX˜õyã³NQ$|­½+ÒMOªd=Û¡ ƒášû, sNxƒ…XŽ>§ÁŒÞØ.-Á¬^qcôWù¹{~™ãï˜Sßç£@ðÅfk—T©°‘ÖTdw×ë'—Îñ0¸­»ãÚ4P{ÀZsZ=ˆ­ šÛN|Çñ"¾[DGäc޽‘ÏåÔÌ|.§¶1“‡7æcØÌ×¥ã0󹚙ÏuÏÄ|˜0Ä,æËÂgb>LŠh¸XÕL´v¿J˜‰ù6ü$óÁ¢Fƒùª6Ü4óe 3A_Õ6†>@k|(}ÆúPÂŒ\ÐWâ¯>ü;¡ ˆÏEÐL|E¯Š‰ÏeÏL| Ë">—=3ñyþlâ+Jï0ñm–Ã%͈j„¥¢ ¯¯¸ ø¶cžcS™÷Šblæ½ÍB\r¬Î¼çˆŸy¯¸sŠ÷)tÌ{‡Þ'óÞ¡ UŸeQ¾#I’À§Êíä½íB¾ÍBT|‡¦f>{7ð’œøOÖ|Û1ö€½ÜÀçk™ø-Öù´E›oû›ÈwHèeä;$è0òGùŽ<"ß!Y5â^0ßæ'™¯9=JÌ··lŒ—AL›Ÿ‹ùp±•Ì—åó}XÒáó#ôeÅ:Q_V¹õ5‡ZE}k­ˆtÔ‡û㜄Է_+¨g=´Ð‡SotPþ&Ç.êÛï%°o³ûpwÉ+°o»Î•TžENÏ¡È}{;AMð€O˜Ü‡³8·%÷yÕL؇føhöm.-ìCˆž&öm.û²D °o»]b®ÓxŒ ²B؇cDpAM›ä¾,>(†ô؇†‰H7]ÐÓ$÷mN‘ûšÃáâ¾íBä¾½à¾ÍrßÞ²]ÐÝÜ —%È|ØØä!y-á“Å|Í™bb¾¼ç`>ÜñÎ|¸ßX•óåóóå–*b¾¦òŸB>ÂV}ÿLñáJÏ‹øpLÌXE|鵈o»__þ¶A|ùùöv•Fåo äÛ囹4*W%„|ù; ùš ªŠù Ö?^ALh‡ÀIæË¾&æÃ1„³»¼»Z ßv3D¾í”@>œ2x/|ÍbÅ|àè~ƒùš¥ab>XbLóÁ'^ë²±ó#•ÜÄ}Œœ[¤•Ý~÷á%¾_ÜçÂqæ>Xú‹ûœÆ ìÛ A}¹éŒ¨ó`B©¯i¿ÕŒôõ/‘¾§3Ôו»ÌPßö7±©ïHßÖ(#}Þ_Æ‘>ïJãPßv–0Y‘šºã[ õmÇú¼ZäPßvŒ\`T¬Ù9%òË»ùu-Všü6 ɯ;¨HðË›évA w»`Ë©ìj6#ðs-QƒßvÒs¼|êé-òÀ±¿¦}t!ÇÉä’À/-¿nLøåãé/>'³åÖ¾?‡8à·³È/n‘ßvít&c}ú¹…~¶l±>­ù$ìËßIÜ—/B³¾»/ˆûº—7Ä}MY‰ä¾îõqŸoOØ·Bš²OŒ}yRÕ\È÷Ò4ò½úšXÁÔ——é,‡&sjYÜ—-÷mçÜǧ÷GÜ—OOÜçÌ[sßv%bÛèš•OÌçVÍ|›å¸Þ¿’™ÏíùÜeÈ|ÛOyýFF>?#Ÿ;Œ™ïâÛ/:ž÷dàk s‡æ@åðm–ëøäNŸNßvÄ£9\ðmwCàódàˇ{¤lGÀ—íøòê¾lGÀG ¼Ë»ƒ‘öšOL{.•oÜó‹fÜk”L™ö\;ß´—\´çZù¦½| ¢½Æ*š¿U¼Í„;;$áUÏZƒðªÂ &<ï¶`Âóf&¼ªÅ~#^ÕB¹¯*¼oÆ«Žã‰ñª„Nf¼ªå3^ž%Æ«ªhAÆË+ãÝú(˜ñª–¡ yNÇ7äUä0ãUé ÌxØÀœ;Àur3^ž%ƳZÇŒWUuÂŒ·Yî¸=i,[º ‹µŒ˜ñì‚o;¤ÚÜÕŒ—–nt3b¼¼¸/å’‚¼íBž6½ ãU%ÃmjN=«TsúfšÔœnÖjN_ÚjN“jNµ#Èóæ*†¼íR:.È«J£4äU©Byéƒ o³Ø)o‡}p»$$[ yU…Õ yÕ²%AÞv–}N­¤ñùãm'‘ªêØ“ñªtˆ<¿A†¼íöÒꬻÀ·Ì·YyÛY„¼ÍBÈË«ö!-ö¡¾${;­¿0/Ÿ„8/±@/9탮$ÐóˆdÐËûè¥ç½¼?^Í`}°¥½» ½í^Hz~Lzye‘^ý|Ù|ÿº7q^^Yœ÷8|"Îsá(s^ö,q^µö¢zvÁy³Ìyé£8/û§8ÏC³9/¯s§‡byÚíÇg=ÚíÇW¯ý“O½í¬®í~|Ì'û þ ÐówÍ ·EÐË+ ôòYôò÷~ìƒúðc| 1Ƀ‚8o»8A/-zù@«]àxiÐs³â¼ô@ —¿·@/Ÿž@o;‹ ·]<=  B ·µCLʧ.ÐËvôòɈô¶#ìƒ~©f|Ö£‘®-ÔÛŽ©šÑ)‘ž¿d&½<ÄÈK^^I —W Ðs#â¼í€ûxÿNÝ÷ïC|ÿ:¤j>¤_[œ—/”8o;f<ïoª9/ðøâ€8ÏÌËßQ˜—OA˜—}F˜·]Ú.ø¬ÖÞ^ŠôÒ0<:.+÷»Ÿôt’9Ï—&çmÜÇûߟòþ zÛ1UÓ9]&ï¾3 èÛw3CS!Ý­XïVÖŠYo³õœdÖó¶Úd½[Â'³Þn²Ü¤6²Þv Yo;†¬·YèCÞÍil!,åYb½í²ÞM ¼qo;iá^ÞÞ™.œoÜÛš%îm­÷n© Í{wª5É{·ÒhÌ{›Å.„®ÿGª·mªÎ»÷—ªÓ Í+ô™ OdŸfÄuzW‹:S‡(ô+Bæ-‘•à·D¾öïmzÇ-‘ïy£Ÿ7iÝùGp&Ÿ£nTE²Ù–ɧü0¡ŸËUý\3Äìç^Í~E“G³_Ñ‹eösÎÙ¯X&kU§v{6ûU%´²S?S*;©&Ø”iÑN¯j¤i£WÍ~‡º—Ùïp¶šØ/µ‰b¿LŽû¥PRìwhl0û© Ùo; j¯Úó~‡2ÄŒ~–<ý6 ÑOW›®óÃY×)oê:mIU$Å©ë´ÅºÎ«îäç:È›°ÓçØ[ì‚-VE^‚-«"•õÊN[¬ì¼ßà÷=a§-E²Ø&ì´¥~ú»IØiQ©…ºtê:¥Ç´÷'ðÛŽ±®ÓÇXשN]§± zZÇR×évÚÛíÔuÞoîË,îK‰kÊ:} ±ÉͤªSw—ªNŸdUgZ¤êT3_8é€Oéïß:E—ìH}.Á½‰:%!¾|ÿLŒ5÷ù-4÷¥„8E§ŽÜ·Y,ê<ߨ·BtÀx •SÓ©D}ÞÌÚÔçaÅÔçºG¦>h¦¾Ý2d¡XXÔ·YH}+M}OI}ù÷c8y0õm"S¶+êÛ,¤> ÑM}Û1öAÙœ} ,ÍÔ·Cì;4ó3öyãqb_Qíƒ-éƒÎ!39ÞÜWœ{,îóGÌÜ·µCîÛ΢›…дµCjJ‹¸ÏÛ§“û¶¿É}þìšûŠÝZú`Ê+²0ÁWÜ·EîÛŽ!øÕ2øy`òK‹Èo³š±è1É/Ûúåµ…~›%}8ßì·Yª&D,ú`øÛÚéšù˜¡)îo¤(7ø´Sû'¯D€›¥×wo3¦åLxu`¶#ÜÎ"ng7ËBÀýïÏ>·cˆ€›…¸]›˜!`¶|¥:&}`­)×qC0–»štWQG·«ŽÿíUÇm;"ßê¸}眨ãöÌOdÖ;Ó_{½3Ú¶2I²ìuÓž^ެ¿¦¿^í„mo‡–½InË}ýKþµ·CÛÖŽ,ùúk~Æã]íW*ž¡ ðù¥DÕ—~¥,Û§Biï¾rãÈòUŸúEªÇE©â̽Î~•?c Û1lå]J-ZÚËŸ¡¥Wñ3¶´Ã–Þ…ÔØÒVülµ´—>SKyŒZz•QcŸßJŸ¡¥Wy4½)y [ú³Ê£ÝmMÃÿ–ª£ýÊ@ôÓ—aå{CÏO_:èç¡èk7ýÚÆTG{æ7§Ò¯êh?Pþì÷×7Cɵ{ÎDžã_Qß ¤1MµõÍ~ùN}³_þ¢õÍ&¼²–þßýŽMõÍ®úõÍn|°° Mßwæ²KI4ÎB Óá¦e0»5ÍïIñ•ršÊ¸³Û¹Â;žÊTvQçÛªÉ$U£÷hZ^;uL©˜wmšŸXUÊ¢Vú)E•²¸.û”ã¥9xJ¸Ð†v™–ÁJ8L\|ʥ⠜¤>ån,Îû›[Y÷œ©§Ô(³ßbx ªz­ª·T5?eù€½ ŠŽ˜ÆÔù qO—ç(˜ŠUÜg ös˜Š­‚Èôó8Ëüûq»Ç‰©X½n~ŽåC½‰> >`ÝW^O]–¡ ésT ux¶ÿx[:¦b5wú™ïûòašä=çò¡áË òÌñ–C -X°>Õ0yÖ1çü ¤áöya6ÙNåxPÏ𜧠UµyÎåö3``â9— ­zÏÅ9î`}ª¡Æ»ÎÂßziʯP²~Ú.óYŸÙɦS}Þ6õÐϵ\è§Ó¸¦.`Ý—Üû\'V¨úíåûùÎs+í8³C‰d.ÍÏkl(‘Ì>;y:ÕñRÏÙûPîkÕǜXc›–“Âõg>?ÌŠÊhGXà^ˆƒçÌÞƒzÜFÅ – _~l:¿a+ÞÜ*m¼¶M¸x¶ˆø†íi>"ûéY¯aAaŒ°,æÍ¡x-cYdŠvêÙ—Kóåe'ªW[.aØŠß Þu¹´Ò!²\Àž ü{¹€M0äôz‹¿aÃFæ|…Sè„eœË«µs ­Àaì0¡þÚ¬±aÝp ޵‘Ì2„ó? gæ°Ý–O(÷7GåÞió<áe¨O¸Èß Ñ5Ɔ%¦6‚Ý4âÒñÕ"a3]oõü¡LÂiË¥{…åìË¥ë`Yžùs/°©o§ßuYNä/‡åYŠU4, l¨Ñÿqð˜†Ks´ê¨ö UÕõ3vÞ?¶ˆï£{<Þq”°ty4P¿ söåR}ôÀp龘 þ :PuÆA°A-õ^–%óK[E—µ sXúçðBã\N!p¸žBÅwNÕ“a¸ZèB-ü)§%\pÁÇ96÷eÁÞ,#,W[N -×r×èzóx‡åyVOÃ5,t£>-ta¨7ÖÒϰÜÌušiÜ1¸8îßex…Í.âJø.ãˆ'yÌ1–WuF»}ðFˆ5zJÞÐpc:t FRhy0š–+Þ§Š­Â¦O' ÙÓÒ°´vœk=mÂsE–÷Ø4tý=¿ÉßÖ®$Qÿ â‹|„ǃ†±ÜÁ†*áÎyöåŽkSÕS7ïwÆÝ«BXXÖZÁúÙbB5g.÷ú‘Ð/zXPnõÛÚ¥ð,8„ÏêU›…Á£Ù\|]+&~nêáß(ׄ¸Q¼ZßãUöø‘“øã1ÌQ›áºš~¢ÊVN^áÀ‰w6úœ(xOóBMY\ê øž–¾êŽÃ×›·ƒÑ·Ø~%.…ÍÂFXâ[Zïå‘ù`nº²‰Æ÷xÕ­.ºö}µåJ¢ÄµïÓ „†?Û}0 ZgÅop×U‹mƒ—¢ «údXè&Cnqõa„`’[Ʀp|6aà:Ï)€ª.`‰ö¦e¹pŽ1~w‰3AßgàcH³°6àcæ|Ìù6ðyzmâk®Ù@âËjÙ">,ƒ¿‰¡.*ŠH|u(à'âC±øûˆh¦Oš÷yïe5ñªôïaÊǹ4yúöÆv‚÷°H’›mX΄¼·Êòr.¼·Us%ï­¥œOïmû¤.ÞÛvì$ïaÿ&Vi#ï­­¢‘÷Ö@•Ô¼‡æ8c%ïׄï•&Õ’x3,zu˜YÊ#ïa&Kõ?yo~S<ÞÞ{ \/Þ{ý½€¯^ÞD“À7<¥øð®QÇBà›ƒŒêtø°QsÝ|P8Q´@àÃY¿g_uµvò^]e;hXdáPâ^Í2° ÷jnF܃…õ‰{xa™ÏDÞk‡+y‘÷°¹Ÿžgð¶òµ.µÓÛÏ“÷p–áã¦Þ”k÷f·’È‹¸‡x­X¸¢î‚Ɖ˜š‹*í5|²tÀ¢½Ö­%#îµæÔ(âŽa…HâÄW¬·BÜkݹÃĽÔ÷fŸ’¸×ÏÇïsà6d)’…{˜ã³£ö0×BHÐv?be"Ò^¿]ô’¸‡½Ž´L¸ ki÷@òⶸŒi,@¥Ž±NܶXi…–ù„ƒöÆü~²ö ilO‰Ê¢=п~Æ ½4ŽïiÏÊò¤=ŒéZ% Ú˜gòþˆ{Ø/–ïWàÀ€‰o½‚m¶âZÁ{@­ ïaÜ×[¼7šwÛ$ïá, ¾~Dº †K7’÷FuñyñFuAXðÂÑ\"ïm˜Kà+Wá§YÀÌñsò^ÁT .EÞ+«XfX—ÊÓ8»ïa+ ¼W&#°ùÖ>‰<‚.T¯$ùʸ†…¼´öäý9‰¯`ħ…ć5¶7ñaS¨¸=f™l˜Äwh]CÀ}P<>vd;ð­ÏpüM⛜¤0–kIj‚ÖâcH|õˆøVÙž°øîn$ñÝžë’øðyë¼–|¸Èê&>¼x1óñáw eÓu~"¾µÁrAâ;ç€Ä‰¸“ð>œU‹M&>ccÆ)ä;Û'ä;¼{¥™ï4ù å"€’ù° C \.ÛÈPALêX‚¾ó¼ÅL¤¾óö…I} ¨ò¢¾Ó¯‚¨7GŠ"õì8ý%õá䇬Hêôíú†êé‰ú0=o;õM€.D/Ì`AýE}ëû3fR,dRßuŽ ¢>ÆÄ|×Ú³ïçD>l5MŠ%ò]7f]a ^ùƒø®ë „øÖd^€‡»Ç:ÍÅ¿ãîÑ1ã¹ø 0Ì—°³'¡0€ïZúû°ðaž@Ò%ñ]]»Šø0á!t›,ðRä%o,à»—Ôöç÷šO ÞÃÖº/àƒküU |÷qê7"ð]ÝNâÃfÙíñݧŸ ‰ï.VH|óÛi °ig¨ù„|EY/ÝØºð…|A²‡,仯tùîÇüIäã‰aÚȇážgò݇_~"ß È·¦boæCÄ)Î"óÝ·ŠgŠù°•xôýÞgöµöb?” ½_ìMÀù öuKgÅ~¹©€ØoÎáXMPì‡Rå²ûaïƒ4ì—!‹ýrÓe±ëíËeØý]†Poí"y8gŸð,!¬ þ°×lgHîV%u&b9Øw*åÈÁ¾Ä-ÂßÐ`'öƒ—\ñ&ûåvÙb?o ,ôÃ^ÃO¢æ•ÌÙW¨¯œ*­¯P_qY=…ú°Y&×™…~J?ýŒíF¿®t¡_*U¼¡õpF?o"ô;Œ‰~‡÷CôÃç_ñ·@?àâMK ßy þ…~Ðfs²EôƒÚYAÅ@?¬Š !ýfË,Ð)ôC¿/Ñïôf9b¿³$¤_çðÀ áo¶£§¼à㈂t`.οþpLUTqÁŽ¡V›ð‡cøÂþÖöBÑO8Kˆð‡û{Áaáo¹ðìð·˜D‘»+8¾+¶w·×ý­ ß{¬o9@Ô[ð‡ä!ApÀ_Í´!ÂFBEWþê Ý“Á¬¸ŠÓ-úƒk\ù ýa&ÂÒz•B¤?|X¾ÀÁ}1BîkwqîC¯ø÷5,²ç‚ûÐKòr¨+$8+¡9b+Á}Çú‡%¸o  þ÷A~ÃDî+óÕRp2¸£eÝc}À!ÎÁ¥)¯J§þ­bgÉz÷ù‰õ´‹’Xïùû‰ôø0éÝJ‰4é9~cÒë.¸—¤§êèIzŽ’“îŒ ’ôî…Ú"È7šç.+̇ g óî‰*Ã|Ã[q‘ôÐ'˜÷gYg1?ˆômÙfÒóÖF–u^I•”uºÊ›e‡Û¡¬y,â6Ê:Oõ`Ê:OOfÈzø²SíFÖ;«v…ëAèY_¬wçl›¬wKe Ô»½ãŒPï’öC¤w¶ÔQ†¿ù$Hz—k‹ˆônçqéÝ9‰#éÝÞ÷U¤÷xA‘^MP!éar}° $ü:|z$½ÜD¤E‘›AzÍ{f‰ôz-Ioä3ÒÃì˜Û5,ÒÃôF“Õ =Lį óÞ­Åa¾ªÝ¹æ+Ù.Ã|ç‡ ó]Ý¡†ùn¿ óaPzEùV”Æ(Ÿ‹ÌE”a|ÎW”oÕÀx…ùÐ×uD„ù°3í+Êw<žYôzÂ,Aox«jÞð¶t½V.G åÃrÛ Ð[C_§Ds§0 ‡©¬–zø®±ƒ&FÁzHqéµùâYrºHw'¬‹0e©^ߨt »/èávE¡zíè²[ ‡_¼Dàjͽß"­Tºà:$=h¢õ`‚ô0;“,>H¯Ý—öŽ#é!“Ww¤‡/¬FÇ =äíòåЛœæ¥² ½ö4¿¨Az«“ðWÒkYŒg‘^«W²`¸°ªï²Î†MEéx^ëŠ7ôÚœZiñ/@3É$ôÚüh}½’O ×ý+èuL)¥É\”ÔÏcƒôy¬7H¯_—¢äzøµGùú,EúzH<–—z”S|œ×çåUÈy\…»ƒó:Ê$<{”uBšÚ °…xÙ9•Côm Î[t'çMrõ+@¯Ï3§eÁyˆKRV.Fi)ô+ lÉ91‡Ð'bÞ8NiŒ‰y8F̘7¿ŒZ|&æ5¨Ã…‚áÁ)+)oÍ‚X”‡Ébs‹òЯ.NG‰yø)Ç óнˆ2y­{›%aÞq*Ö"Ê»løë˜^¡R sŒò•¤±ßã`HaŒ¬[Zì‡hoì7(½‘b¿ tì7Á__d¿Ço¿Ø•7”z쇙IÛRú€×JÅ öëÞ8”ì‡î )a°_;[RfäÃáÈcg?LÑÆ+¥o1'd„¿lÝ%žXìVt)}Ȉ*tNõ4» ú›tã9è+Ç+è³'Ë7ý¡F gE˜v°OþúR:í)}è©Ç+̇AE ð‡AØ¡¶“)Pð·J¢H¿Y‰5Usk Ù4ž“x< ø[ijŒÎ=1`”ú!î¬’ÅØ“‚ýfϨ;ú¥JöAô;0Ï!ÁúeýÏÏF¿Ù›ªè$Øo µJè[ÀEL» Žz|/`¿•_¤°àb¿T‘ûsÄ’ä+à¯w.#ü-©xÀßJ:9wø[×2!®=Ê€RF”,¯Œ¾£9K}¨ȳ–§3ÃVF¦,e‡¿•!%ŒŒ¾sMj6û-y—<‚ý YTweFD@÷jÐðÒSU^œ}×Ó}èÈŠFF–…vpõ¾tN¸pIJÙpP•üPSЉ!NçCÍI‚Ô"¿¥㯯|¾®¤% pÍ(ôȼet`é;Â'õa)ºJñ¹ô(•ñÎêô†stê;1[fä„úΔWV” Êó …ä§ó }'ÔoÊ }'âü¼xÈ;ç·Ý*ä÷å<Å%ï¬Î†—¼³úõ’¼óÁ,ì%ïÄ$œÊ;ñ5dX‡ Ï9w•–ÏÚÎOỎ`”xÞ½±åÐxbd%ÀRä¹ ­Á‡áïWVß ÉB"Y¡î}eõáå!!†ÆsiLø g¥Ø—O !×+¥¯ÎÁJàÉûÇ<áÒ‡è+¥¯Îc¥Äsmð¾I<ï!Ù¸$žKDKÜ?e’o7áÍá;J‰'Väù[Râ¹J3øÏ9ᔘÏêô|¡ê?JŠÜôúˆýƒ¡ºœì7'êÂÁ~˜o¼$žÏ*,üs¢ßœ](ZIô{°øðB¿9,X9è·:ùK቟Šoªj.¡VŒâzáB93ω‰üÂÿþjJ¨WÜïgE æx¥qþݱªrŸø‡,bôþø÷PSÍý?響¥íýï<ô—W½£kó÷øöÿðwÿøoþ¬¶ÿÛÿüã"á>þð?ò¤ÿƒz5ˆ2®z5XOÛ®òïÕÌÿ£Zùç<õŸÞíå­Îßgkä?ç-üò'Oã÷¼ú·²ýôÇ¿»ôZý<žKùOÓ8ì?¾Úø\/*‰}kÛR%áwCRÄ=¡½ãƒÙO[~r§Û*÷Œ½-Z~H3¬æælçÂè˜ÍÉò›¡h7øÊ±ß‘,?´¼áæ @>_wD šû/÷•r,Cendstream endobj 6 0 obj 164312 endobj 4 0 obj <> /Contents 5 0 R >> endobj 3 0 obj << /Type /Pages /Kids [ 4 0 R ] /Count 1 >> endobj 1 0 obj <> endobj 8 0 obj <> endobj 7 0 obj <> endobj 9 0 obj <>stream 2020-10-09T14:32:30-05:00 2020-10-09T14:32:30-05:00 GL2PS 1.3.9, (C) 1999-2015 C. Geuzaine gl2ps_renderer figureOctave endstream endobj 2 0 obj <>endobj xref 0 10 0000000000 65535 f 0000164862 00000 n 0000166375 00000 n 0000164803 00000 n 0000164670 00000 n 0000000266 00000 n 0000164648 00000 n 0000164955 00000 n 0000164926 00000 n 0000165019 00000 n trailer << /Size 10 /Root 1 0 R /Info 2 0 R /ID [] >> startxref 166595 %%EOF blis-0.9.0/docs/graphs/sup/dgemm_rrr_zen2_nt32.png000066400000000000000000006342401422157504600220030ustar00rootroot00000000000000‰PNG  IHDR¬táÂgAMA± üa cHRMz&€„ú€èu0ê`:˜pœºQ<bKGDÿÿÿ ½§“ pHYsNNÆÊ/¥tIMEä !1µ˜¬ï‰kr¸›˜};¸²«Ÿ©gátïÔð Xd¸ ».2<¤ŽHÉ®±)úå{8…Í3O83[Ÿ¹LŸ|äìcÎè!ñÏÔ«7ÒüÑÔ ç—­Þ)ÐkwWÏp'Æ0”ÞÕ×Ii즷ѧŸÁ––ðOΤ(mÿ#(šÿcO?‘t‘¢6ÿÛèJ/Xfµè'¢caNvPÏR¹7€IDATxÚìÝ{œWyçÿmlÉ–=r ƒlÌÄ¢daÌÈ\cÃ-@u,ã].&=C–ö/VwÈn¢°¿ÙíÞ$8‰Ù$ÝdvAá·@—œÈ!d—™NLÌ. ˜Zˆ3eÖÆžÂÎ l9fJ|‘1F¿?NŸêî¹_z®ú¾_¯yiԗꪾ/'7¸ÁÁÁ“§Àa®kããã'³ÙìIà$pÒó¼“ÃÃÃKÞîr¿öÀÉÁÁÁUyì¥Zëû§c–…>éºnG|ß?9>>~òäIÅ‚™¬å}ÓqJ+Ì÷µöv£££'=ÏKãJ6›÷c¯×¸°öOÇ$Ó™i°×~ºX°”8pòäúkyßt\ÛjÏ hL°¾öOÇxêXJlhÅa1ôÙ__NÅcC±`ùž— _ñ(k_±X$ŽcÆÇÇ9yò$®ëR.—W{·Ddéîî&›ÍròäIÆÇÇ[DDfÇ1Õj•îîîi¯Ïç󸮛ƕ(ŠWDÖ¨¥Œf‹Š"+kµæ4&YÛ–4W "²:6dâ1ŠÅ⌄ìõAÇ1A¤×…aH±X¤X,N)ß/‹$IB¹\¦X,R­Vg}¼…Þ~6öbã¾/äúùl»\.§Çßøÿén3ŸmÎçØ“$!*• ŽãP*•p]w^Çf_¿$IÒ×m¦ý³·±¯ëBî;³½®ÏE¹\ž±Äz¦×Æ Ã°éøícN·ïsÝ·ñ9Y걯U³½&³Åû|M V3ØíMÞÿù\·mÏ –+Àü>sÅß÷pÏóflƒÔ Zf{m—+4>æbbÁFŒúì/~ 0Ýe«ùÙoզަû,5n; C …`âJ.—Ke¡4FXyú>°~¾ÀÒb½ÿ|Æ“ã€}½§{®Zf:v»_#, ÖÏ÷¥Ì hL°øXp*Œ &Óa}æŠ Ë5FМáÆûìO¦1Âú#,eÎp)c„õ0gØxìV+cÁRŽ}Ã%;;;Ó', Ã)g¬5¾°öŒ6ûÆ.—Ëéí“$¡³³³é‰¶×'IB’$tww“ÉdÒcß‹½ýlÊå2ù|>ýãh_ðù^?ŸmW«Uâ8žòÿén3ŸmÎçØíÿ=Ï#Š"Â0ÄqJ¥Ò¼ŽÍ€;w¦•Éd¦»½lô1Ád#¬¿1Â\±a¹Æš3ÜXŸýÉ4FX_c„¥Ì.eŒ°æ í±7je,XÒ±¯v¿ØVªT*'Ç99::š^f{€ŸÇ>00öXw]÷¤ëº'Çizf;6Ûo¸T*5]œüô§?}89>>>åñ纯]n®cœó}7¹'òøøxúž›Ïc4j|ÏLÞF¡PhZkb¶ûÎvìóÙ¯µn¶×d¶8pòäÉ9cÁjÆ»½™>K‰ÓÝ>±a®íÍ÷Øçóyœ+8Ž“Æ×u§¬ñ8],Xj°û5W,X®8pòäâcÁFŒúìO½n¡Ûî²Õüì/v иnËLãkºµ ìv¦»Æk›¾¬¿ï'O.-ØûO7˜oh܇É?Ým4FXû4&˜zÝb¶½’c‚¥Ì hL°øX°‘Ç“iŒ°>Çsņå#hÎpã|ö'Óaêu‹ÙöZš7˜íø–2FXs†ö1µ"´"l¨ŠG[>ßxæJ.—K¯V«S®Ïf³€É溮K’$„aØôÿÆ3cïë8NZæ?“…Þ~6¶5ÀäíÎ÷úùn{ºÿÏtÙR½ñÌ¥ÑÑQFGGÉårS²ús›m{õ×ü{ßû@z¶„}­çsßÉ-3f3×ûÎ^žÏçÓ3³üMf·aÏDÃpAeØ3ûbÏâ^Kf{Mf‹0¿X°šqfÿ<,%L¾ÿ|þ?—…û\ŸÇéŽÏ–ýû¾O¥RI[°L> g¶X°Ô8³¿ï–+ÀÒcÁFŠúìOÝB¶;Óe«ùÙ_Ì ñó;×8`:³}†òùÒaåéûÀúû>Ðh1±`>ã€ÕŒ 1ÂjИ`úëºíùü.ó=öVÌ hL0½S94Òa}Žæ–sŒ 9Ãæ}^ŸýÉ4F˜þº…n{>ÿŸËJÌÎ÷¾š3œÿs>ß8ð¬%ïý2Sk=k¶'5Žã´—n£…~`da|ß§\.7µ4) i?èÅ>ÿÊó<|ß'ŸÏ3::º ûÎÇ\ï;×uLËó“$!—ËQ©T–ôÜÙÒ´–ú‡i1ǾVÍöšÌ\ Ö–ù¼'m¿õô2×uéììlú¹X°˜ÏÂlï»åŠÐúX°žã€>ûÇRÞ‡“ï»Ðq€½ÏL2ø×aåéûÀƲÔqÀ«_ýj`uãhŒ°4&X–cn@cãTŽ4FXŸæŠ ³YŽ1‚æ ×?6ŽÕš7Мáül¨Ä£ëºS²ÍÃqœˆçyi6¹ñ¾QÍ:Д¥™íͺ7r’$éímßa«R©$ Õj•b±8e݆Ùî;s½ïâ8Æqœôìª(ŠÈd2xž×t–ÓBT«U‚ `tt´iAí…žm±Ôc_«f{Mf‹ X°Úóžl¼e?gáÌ ZñY˜í}·qZ 6RÐgýZÊûp®ûÎ5˜Nc ™î÷ùÒaåéûÀúÖêqÀC=¬n°ÛÒaeiL°þ´bn@c‚©NõXÐHc„õi)±¡cÍ®ÿÏþd#¬_«5o 9ÃÅû†jµšÍf›Àœ|B6›M"¶×ÛÅ4}ßoú?Ô%•åãy®ë6½NÅb×u°'/&ë8W^yez™]xº\.O)žî¾ 9Se®÷]ãÙ À‚Ï.h|¿6>†ã8M­&§;ÓkºûÎtìöyßgéÌöšÌ@±`µ-æó8ù5í¾3Å‚¥Æ»3½ï–#Øÿ/5l¤8 Ïþúµ”Ïà|î;Û8`:ösÐø~¨V« jÍ#¬}XßZ=˜ï÷é´*Ø}ÔaeiL°þ´bn@c‚ÅÅ‚:&˜Lc„õi)±¡cÍ6?çëñ³?™Æë×jͬõ9CX¾X°”8°¡*=Ï£P(ÐÝÝçyÄqL.—kê±\©TÈd2ø¾ŸöÖµ/B©T¢X,¦Á#Žã¦3dy ÉdÒç=I’?ïq³sçÎôþÓ•"g³Y²Ù,ù|¾iûó¹ïlæzßår9ªÕ*;wîÄó¼ô,˜ù|QÉårév“$Iÿf³Y‚ `çθ®›¾—í™ ¹\nÆû6îwEMǾQÞï³½&³Å@±`•-æóèy^úšÚ÷ûlïçÆX`[±.5Øý˜é}·qÀËRbÁF‹úì¯_Kù Î÷¾3fR*•Èd2éŽã4µožVž¾¬o­L>#w5â€ÝGV–ÆëÓRç4&X\,بc‚…¾#¬]‹ ­#hÎpýöòšhŒ°¶­ô¼Áz˜3„å‹K§7kM+>öõ^È}[÷cºÏúrÄÆí.6l´8 Ïþú±–þŽOg±ã“É4FXyú>°¾¬Ö8`>Z÷Qc„•£1Áú³˜ÏœÆK‹}L0™ÆëÓR>ƒka®@ßÖÖÕš7X/s†°¼±`±Ç¾!3±Ùéááá4³œÉd( Kê—»TÁj&‹yS/Çv—k_«1´ê¾+qŒkíy<•œjq`¹¶Ýêm.å³¼³=®bÁÆ¢ÏþÒ·½ûºÇ—“âÂúwªÅ‚õ0€Õ,–bÁúvªÅåÚöZz®V Q,ØXNµØ°ÑãÂRiÎðÔtªÅåÚöZš3\®û*ÌmCµZKc¹´m•`KJWÓLýu-挺åØîríëZ²Çx*ø —\rÉjïÆŠ:zô([¶láÜsÏ]í]YQ }­üqV{·WÜk^ó.½ôÒÕÞ¥ÏÄ©c¡¯õc=FWWï{ßûV{×W”ƧŽÇ{ŒÇœíÛ·¯ö®¬¨…¾ÖGåOþäOèèèXí]_Q7ÝtÏ<óÌjïÆ‚­×Ïòz¬×ý^Lü;ãŒ3¸õÖ[W{×WÔÈÈÿé?ý§uùwb½Æí÷ÚÞïSõûÁ‡>ô!†††Ö]¬?•þF­ëu¿As†óÕÝÝÍ–-[V{7–d½þ½j´^c[£õ/a©c‚S"ñxüøqÞúÖ·rÓM7­ö®¬¨o¼‘ƒ®ön¬¨¾¾>ºººèêêZí]YQ }­o¼ñÆÕÞåUñÔSOé3qŠPü›ÛÐÐCCC«½Û+Nc‚S‡}÷öö®ö®¬¨…¾Ö}}}?~|µw{Å=óÌ3ëò3±^?Ëëu<²^÷{1ñïTü~püøqÞð†7¬Ë¿ë5h¿×ö~ŸªßžyæÞ÷¾÷­»X*ýZ Öë~ƒæ çkË–-ë2Ö7Z¯¯­×ØÖh=Ç‹Éǰk²ÕêÄÄW]uÕ´×××ÇUW]Åe—]ƾ}û›s{_|ñ)WÙ°gÏžÕÞ…×ÕÕE{{ûjïÆŠÛˆ¯u«ãÀ\°Ú‡µâô™8ulÔ×Zc‚Ö8?íííëúËÊbmÔ×z¦X°Ø1Ázµ^_ßõú7j½î÷FËñý`½Z¯±@û­ýnÅC£´ßóµcâÀô6Âk½^c[£õ/ZiM&÷íÛÇÄÄÄ”Ëûúúèïï§··—ƒ266ƾ}ûæÜÞ©:ÉØÓÓ³Ú»°â6BpZŒøZ·:ëºÄ}±ô™8ulÔ×Zc‚Ö8?§ê`£¾ÖÓÅ‚¥Œ Ö«õúú®×¿Qëu¿7jü[ŽïëÕzÚoíw+(ú¥ýž¯ ¦·^ëõÛ­çxÑJk.ñxàÀÛ=:tˆžžzzzèêêbÿþýŒŒŒpèСÕÞmi!ÅÅ1fŠŠ"§ D DDq@d½XS‰Ç‘‘‚ àøÀ´×5e‹ÛÛÛéèèàðáë½ë"Ò"Š"Š"bÌ DNˆ(ˆˆâ€Èz²f¼ÿýï'—ËÑÑÑ1åz{&Ãä2Õ­[·2222ë¶üãS­Véïï_íÃYUCCCôõõqôèÑÕÞ•i-g8zô(}}}K^Wd½ëëë£Z­òãÿxµweZ+1&èëë[íÃYUcccôõõq×]w­ö®Ìh¶X°Ô1Á±cÇÒVL"§²þþ~úúú8vìØjïÊ´–ûûÁ]wÝE__ß)µþ“Ètôý@ßD4g¨9C0ßZ1&X3‰Ç غu+{÷îmù¶7mÚDGG»wï^íÃYU¶Çô–-[V{W¦µœq`Ë–-¢W¸ÈRuuuÑÑÑÁ¦M›V{W¦µcõÛ—SÝÖ­[éêêââ‹/^í]™ÑrƂ͛7ÓÕÕ¥ïrÊÛ½{7]]]lÞ¼yµweZËýýàâ‹/¦««‹­[·®ö¡Š¬*}?Ð÷ÍjÎPÌ÷ƒVŒ žµÚ挊þþ~n¿ýöeÙþYgÅ‹_üâiφ9•´··ÓÞÞÎV{W¦Xî8pî¹çêË„õ3×buÃJ  äT×ÖÖFWWך=£w¹cM<ŠœêìwäSõûM<Šœêôý@ßD4g¨9C0ߎ?¾ä1ÁšI¶nÝÊÁƒÓËFFF¦$•PYÿD DĘ+Ø3D6. D DDq@d=Z‰Çžžž)g qíµ×¦Á^øðá¦`144Äž={VûDd‰D DĘ+(ˆl|ˆ(ˆˆâ€Èz´&¶”{²É=Ö{zzèïïçÚk¯¥­­ÐÖÖÆµ×^»Ú‡ "K¤8 " X "Æ|bâ€ÈƦ1ˆ€bˆ(ˆ¬Gk"ñ8_½½½Üpà \ýõ´µµ166Foo/mmm«½k"²BD DDq@D ÅÅQYKÖlâñÞ{ïrY[[·ß~;CCCìÞ½[CdSP,cr,P9õhL " X "Š"kÝšM<ÎfrOg9õ(ˆ(ˆˆâ€ˆŠ"Š"¢8 ²œ¾Ú; """""""""""""ëŸ"""""""""""""²dJ<ŠˆˆˆˆˆˆˆˆˆˆˆˆÈ’)ñ("""""""""""""K¦Ä£ˆˆˆˆˆˆˆˆˆˆˆˆˆ,™"""""""""""""²dJ<ŠˆˆˆˆˆˆˆˆˆˆˆˆÈ’)ñ("""""""""""""K¦Ä£ˆˆˆˆˆˆˆˆˆˆˆˆˆ,™"""""""""""""²dJ<ŠˆˆˆˆˆˆˆˆˆˆˆˆÈ’)ñ("""""""""""""K¦Ä£ˆˆˆˆˆˆˆˆˆˆˆˆˆ,™"""""""""""""²dJ<ŠˆˆˆˆˆˆˆˆˆˆˆˆÈ’)ñ("""""""""""""K¦Ä£ˆˆˆˆˆˆˆˆˆˆˆˆˆ,Ù³Z¹±C‡qøðaz{{b÷îÝ´µµ­öqŠˆˆˆˆˆˆˆˆˆˆˆˆÈ2jIâqbb‚}ûö144”^ÖÛÛË8|ø0·Ýv«}¬"""""""""""""²LZÒj5>ÌÁƒ¹÷Þ{ÓËo¹åººº¸á†˜˜˜Xíc‘eÒ’Äc?¹\Ž®®®¦ËÛÛÛùÀ>ÀÄÄDÚ‚UDDDDDDDDDDDDD6ž–$'&&fl¥j×wYíc‘eÒ’ÄcGG‡šö:»îãäjHÙ8žÕŠär9öíÛÀž={“p£¯¯®®®+"EDDDDDDDDDDDDdýkIâqÏž=ÜrË-ôõõÑßßÀ7Þ@OO½½½«}œ"""""""""""""²ŒZ’x“`ìééI[«ìÞ½;]ãQDDDDDDDDDDDDD6®–$‡††hoo§½½]k9Šˆˆˆˆˆˆˆˆˆˆˆˆœ‚NoÅFöíÛ—¶X]¬‰‰ öíÛÇe—]Æe—]Æõ×_ÏÈÈÈ”ÛõõõqÕUWqÙe—±oß>ÆÆÆV癑–SP,c>±@q@dcÓ˜@D@±@DäÔ‘$IËn[,Wí8Z’xÌår:tˆ‰‰‰Eoã†n`llŒƒrðàAÚÛ۹ᆚ¶i×ìííåàÁƒŒ±oß¾U{òD¤µD DĘ+(ˆl|ˆ(ˆˆâ€œ:ŠÅ"aÎë¶S’q§¿A°jÇÑ’V«mmm´µµñÆ7¾‘k¯½vÚu{{{g¼ÿÈÈ###Ü~ûítttf}È«®ºŠ¡¡!öìÙÀ¡C‡Òµ$öïßïû:t(½ˆ¬OŠ"Š"bÌ'(ˆllˆ(ˆˆâ€œ:Â0$ÇÁ÷ý)×GQDÇø¾O’$ÄqLww7ƒƒƒémº»»& C’$!Š"<Ï›÷ãO÷¸‹Ñ’ŠÇ±±1¶nÝÊîÝ»KƒAãÏlÚÚÚØ»wo8¦322ÂØØXÓ’ííítttpøðá–<"²zD DĘ+(ˆl|ˆ(ˆˆâ€œ:l…bEÓ^ßÙÙIww7QE®ë†aZ!Ašœ´•Õj0•™L†L&3í¶Ã0LoÛ -©x´ÕŒccc:tˆãÇÐÕÕÕôaŸI{{{º‘‘Ž?N?éý·ÙhëÖ­s&6üãS­VKÏx9 144ÄÑ£GW{W¦Xî8pôèQúúúæ›D6ª¾¾>Ž92m‡‚Õ¶Rc‚¡¡¡Y»1ˆltcccô÷÷s×]w­É¿‰sÅ;y°Ø1Á±cÇèë룽½]ßä”ÖßßÏØØÇŽ[í]™b%¾Üu×]ôõõÑÓÓC{{ûj²ÈªÑ÷}?Ñœ¡æ ey…!ø>³V †aH¡PHÝÝÝ8ŽC¡PÀu]<ÏKžçáºnšd´k:Æqœ&/«Õ*¥R)MJδ.dÇAÀË_þrî¹çž% Z’x¸ùæ›éïïoºìÀ´··³ÿþYÏHhÔ××ÇÐÐ`š­ôlÚ´‰ŽŽvïÞݪÃY—ÚÛÛéêêâÿñW{Wfµq`Ë–-tuuiRANy]]]|ûÛßæ‘GYí]™ÕrŽ ^üâ¯öቬª­[·ÒÕÕÅ‘#GV{Wæ´±`óæÍtuu±uëÖÕ><‘Uµ{÷nÚÛÛg<«z­X®ï_|±bú~ ï"š3Ôœ¡,§$ICß7‰À$I¦´4M’„$I( ”Ëeòù ù¬³ÎâÅ/~ñ¼“Ÿ"U{{;ííí8p`µweVËÎ=÷\µ$Bý ÀµXÝÐh9ÇŠrªkkk£««+ýÒ¾–M –:!`"§:ûùTý~`"§:}?Ð÷ÍjÎPê’$Áqœi¯‹cp]óo’À\Ë'–ËåZ•a ›"³I¾FQá8ŽãËå‚€R©”®åh“¶â1Žc …Bú{Çd³YÇIïãû>®ë¦-T³Ùì¤c1IËl6›>þW¿úUþàþ`Éc‚–¬ñxèÐ!öîÝËÞ½{›Î2èêêbÿþýŒÍ:©a×…ldËš'ßoºÒh%EÖ?ÅÅ1æ D6. D DDq@VžmY:Y’Àg>óaò§z‚rÙ$ mbÏV3ZßøÆ ‰G“¬´k0éš‹Õjµ©k¥RáäÉ“ …4Ñhƒžç¥¿û¾ŸV=V«Ur¹®ë¦‰HÛŠµ\.7UXÚu!wîÜ™V@&IB.—# C>ùÉO¦í^«%‰ÇÉ ·6²g#ÏÖKùСCÜpà ³>†ÝþäÅ`‡††T-²(ˆ(ˆˆ1W,PÙø4&P,ÅY968]E"@Aÿ?Q.—ùÇüGn¿ý›d2™4Ig[šZ7Ýô1Î9ç5µÊÂzâѶFµ•‰víE»Žc#ÛZµ1‘P*•p‡(ŠÒ$¤ëºidc‹Öé¶Ý¸Ö¤Ý˜õŸýìg/é¹lIâ±½½}ÆŠF›pœíÌ‚={ö011ÑTÊm´mLhöôôÐßßÏÄÄ`ÚÁ´µµqíµ×¶â0Dd)ˆ(ˆˆ1ŸX 8 ²±iL " X "в2Â0¤\.§Õ…Óy衇øú×ï% C¾ûÝïòÌ3/%—Ë5%*?ò‘!ªU³½»ïÞÆu×ýFº a’Ô“POöÙdätí]í¶ªLÒѶMµÉÂB¡þßþ¸®›&íí“öñl²ÔÞæ“Ÿü$gŸ}ö’žÏ–¬ñ¸gÏžôƒíµ×ÒÑÑ‘¶Wíë룣£cÖÉíííÜrË-Ü|óÍAÀÖ­[cïÞ½M=š{{{¹á†¸þúëikkcll¬¥‹ÈŠÈêQP,c>±@q@dcÓ˜@D@±@DdùÙ A[íØØ.µÑG?ú=ÚÚ^ÊÕWû|å+'xÝëž&›ÍR.—“H—ÓOÿU~îçþ•¸”‰‰˜}û¶R­‚ç¹Ü{ïÛxì±39zt€Ë/ÿ0ÿø¹ì²kH“ü›œX¬Vë‰G0Õ““ƒó5ù˜mâÑó¼´ÊÓÞÆó<Â0d×®]KzMZ²Æ£ÕÖÖFWW{÷îeÏž= J:ŠˆˆˆˆˆˆˆˆˆˆˆˆÌW㚌ë4žvšiYÚxÝt÷M’„0 )•J …´Ýh’$8Ž“®¯øÈ#ç$NZMEpÖYgñö·œ‰‰wðÖ·> À®]ïå+_ÙL›V¨\ð7œ}ö>v츟Ë/¿œãÇÿšGùµÄ¤G.—kÚ¯$†ÂÄE'¡¹5ëäu$ív[±žwÞyK~MZ–xìïïçÆoddd$½ìª«®âæ›oNt™ËtÉÂÙnS.—q‡{îù® ò‘£8 æ'àïø;6m: D>|9ïyÏGxÃv`ó¡QäóÀ§ó‹¿ølÞúÖ{¹õÖk—¸” 0‰I»c£ÆÄãR4&íã4&k/÷<½èEK~Ì–$8ÀÍ7ß ÐÔ7¹§§‡ÏþóÜpà ­y†DDDDDDDDDDDDdà ð)98“(ŠÃ0ë:ô¯Ä1¼þõ¯'ŸÏ§U‹=öØ”ûÙ6£6ù¶eË À0ÿðבÍf‰ã¸–|ÌqóÍÛ©V!“1ÕŽ¹¼øÅÕ¶âypäȯð¥/ý® ¾oª xÿû_ć>tŽýè]|ô£÷E$^íXëûǤ‰ËƪÍV›®âñyÏ{Þ’·Û’Äc?===ý6›å‚ ®Lå¢ÍQÚ¦®ëâ8—_þ¹éëš“¤^½8Y©d*óys›0¬W;Ö[µÖ“­j¿j¹®ÛÔæ5Ià oxÃ’·Û’Äc{{ûŒccc@=)""""""""""""2“úºŒõ¤aR,Óëÿm¬x„æ*>ëe/ë:Å$m»U€C‡~«¯ÞU{‚iãjÛ®zž¹Ü&mr3ŠL¢p¦jÊé8öÎ “®­ZO²%‰ÇÞÞ^öîÝK__W]u—]v—]vûöí`ÿþý­Ù[ÙpÛ¨ÆqŒëºé‹Qáû>žç¥·ú‹…B!­Þû¥_úxm½E“x´??ü0`l?þñ³¿2ÝNµj’xŽo|ã (—MÅc’˜_c›ÕÉü™®º¸NËuëÉÉRÉüæ±ÃÐ\õ}ó}“ m̽f2SÛ°6&ã¸~ûÆ5¡± ²u­\•x¡¯¯¯iÝÆÞÞ^Â0ä–[naïÞ½ìÝ»—ƒrûí·«ÍªˆˆˆˆˆˆˆˆˆˆˆˆÌ(Êå2`dŽãËå‚€q::^ëºiòÌ& K¥…†2ć>‡jµÞõoÜË7¿y5'Nt¦—é _øcž~úÜ4!Ç&Qéûõ*À(2I½ÆJCߟZeèûþ´Õ„óe+ƒ ¾ÏÙ¬I†V«&)h«.}¿ÞÂÕ®%i“†Û¶ÕŒµ§0—e2ðÄÖž³éK0[Uñø¬ÅÜ©½½ööv‚ `dd„={ö°{÷nöìÙCOOOköLDDDDDDDDDDDD6$›8t'm©E1¹\Ž8Ž) ø¾_K>–yÎs¾É»ÞõLÓÚŽO?}.žW˜’„z.“ÉóÁ$€OÁ÷¾w^z߯WÚûf³õÖ§­Umâo²Âäþ« ·Ÿ«’°P¨?¾M ÐÝmö#ÌcÚ}0‰Ä ¨o; M3Ÿ‡áa³RÉ\gosÎ9»ñ}Ÿ0œ¾Bs!m[g³¨ŠÇ¶¶6zzzØ¿?·ß~;ííí áû>7ß|3‡jÍÞ‰ˆˆˆˆˆˆˆˆˆˆˆÈ†R­VéììL+«Õ*®ërá…"‚´Õ*@¥Rà_ÿõçj­A=^þò ¾ùÍ«û÷d2õV©¶-©m] µê”ýhlYÚ¸Î"˜ÄŸm…j õí·ç;Æ#4oßÞÇ®ëh“™L}_}Nž¬'L]·^±Y(˜¤£ãÔŽQdÛλßýûLWñ†S×®\¬%¯ñh“·Ür aÒÕÕÅÐÐW]uûöí£¿¿Ÿ‰‰‰Öì­ˆˆˆˆˆˆˆˆˆˆˆˆ¬k}}ÇE½ŠjÕ$íŽ^x9ÿøq'M<|úÓñýïoàì³÷s×]mÜ{ïKˆcß7‰³ÎNÓª´Xln“jx PßÞøøW_ýëib¯Xl®LŒãæÄßbÙõçÃÞ.—£aÊúÚ“·ãyõË£¨ž|c³8®WE&‰¹þ¢‹^L=¨(2 Ë}ì>÷¹×.阗œxœlÏž=ÜrË-üÓ?ý¹\ޱ±1®¿þú¦õ EDDDDDDDDDDDäÔa“ŒwÝu=\ðÛ$IBµZ¥Z­âû>ϱ¤cXRⱯ¯ß÷éëëK/ëïïÇ÷}öíÛÇ7Þ¨jG! C¢(â’KîÂ÷¡P(àº.ÙZ¦ìN§­íz\×%Žë 1Ï3•fÍE‡Í›ŸdÛ¶»yýëïK“×ct“ˆ³‰ÅóÏ? „œ{îÓéml¢.—kÞO{ß•68¸ð„§ÝO×5?Ù¬¹Ì&GGÍ¿6Ñh“ªah~OÈçqýõrÕUÇyùËÿyIǰèÄc__ ££ƒ®®.ÀT:Þ|óÍtttpðàAöïßÏØØXSbRDDDDDDDDDDDDN-_øÂëù‹¿ØDÇœqÆ5”Ë&‰èûÜsÏûÓ¶Ÿàãº.ŽSo;Ú˜P´k?^~ù‡ñjYÇJÅ\W(˜ßm2²T²÷£G·YzèlžûÜ1r9®ßβmKײ$1ÏçÁÉ“õd¡`~·Õ¶…ë ^0NÆ|ùËwÐÝm‘Ž;wÂ?ýÓÏøæ7û˜˜8ƒg?ûø’öëY‹¹ÓÄÄ ··—½{÷¦—÷÷÷°ÿ~ÚÛÛÓË÷íÛÇÈÈˆÚ­Šˆˆˆˆˆˆˆˆˆˆˆœ‚þå_žü”‡Ž8ýô_K/c8†£GM%Þw¿û(Žã7­½8¹ 0Žcz(Þ Ô+ãØ¬khoo[¯ærærë’Kîã’KVûY×5Ç5¹ZsrÒL‚ñG?ú8¿ð ç±{7üÃ?˜Äã{Þó²ÙßàK_šàYÏz%û·g-y¿Uñxøðazzzš.·ÉÅÆ¤ãž={S )""""""""""""§ž¶¶û8vìûDQ”®»&I˜Ë™ >߇w¾óET«æº(2ÉÄ8nÞV’$Ä“/¤žtk¬´IÈl®¾úv.ºèÉt}Èõ̶OµÏÕdÉÚb±Èöíÿ¿ø‹ßàž{~@oï}¼ï}_ã3Ÿù=§ÊË^ÖÏØØ·8qâ«üèG?ZÒ~-*ñ844@[[Û”ËmÛÕÉ”xÙx¦ÉNëá‡&IvìØA±X¿¯ë’®éE¦…h©dÚ†NÞ¶ïû$I¶Zmd«­Æv«÷ߟýìÅ=ú|Žöj?mKbŸ«éZÂÚ¤lÇ„aH†\~ù\tÑE<øàŸñƒ|ˆR©„ëº$I«_ÝÁ5×\À³Ÿ½´çeQ‰G›\œ˜˜H/;tè»wïnº­M8ªÍªˆˆˆˆˆˆˆˆˆˆˆÈÆ`’ƒ¶5êL&&vqâÄ>\×¥\®'íZƒ`þÍfëÉÈ$©ÿÞ(Š"ÇÁi,m¬™|[ûÿÆË7o~’­[—VÙ·†'Ù&'oÇtvv¦?år™ááa>ô¡ xó›Ï©­­éãyÅZøWõ¥\rIÛ¼öc6‹J<Úä¢}CA}}GÛZuòå“’""""""""""""²>ÅqLE¼ÿýwò•¯<9åúÆv¨mm÷ÍUжº`xØT'6¶Mó39¹6y;&¯i5®…¸uë8ÿüñÕ~ ¬1/gs®µâÏÚï Õj•ÁÁA …¥R‰J¥˜çÌëR­õgõ<ÏóÒDî[ÞrtÉûø¬ÅÜ©­­½{÷ràÀ´íêÈÈ{÷îMo322B?ýýýìÝ»wJ[VYŸªÕjSbñK_z€ßÿýËÓDX¹\ÆqJµ^§gŸý[¶ÜÈóžWïÙ˜4kÌ#ær&ÙèûP,šä¤ï›ëÜZr¦Ä£½ÝtÎ<ó1Nœ8‡ú§¼ð…ë¯Õj†µ52ͱçóǸçž;ñ¼·P,I’„0 Éf³d'e`=Ïüø¾OEøµ'ʶZu‡óÎûé’÷qQ½½½ÜrË-lݺ•­[·²wï^z{{ÓëûúúÒ¤cãå""""""""""""²¾ÙjG0„wÝe Ђ€Z+ÕæÅï¿ÿe<þøAž÷¼ ˜$Ø4R³¶£I’™ÿ7&mâÑ™áÎÓUGZ—^z+^ø.¹ä¾Õ~ $I\×Åqœ´=ê ^Pá?þÇÙ¹s'®ë’ÍfMŸ£FŽcžS[‰Ú˜Àç»Hç<,ªâÑêéé¡§§gÚëz{{µ®£ˆˆˆˆˆˆˆˆˆˆˆÈT­VÓª¹ãÇŸÍSO=Uk¿ê†ð’—œÛ”œ|úé§8ë¬18hZ& N­Rl\ó±±*²ÑL³¿’ø¹Õ~ê%Š"¢(¢\.§-W]×e||œb±H®±—ì \×ð<Èž={Ø·o_Séë룿¿ŸÞÞ^<ÈØØûöí[íçPDZDq@D@±@DŒ¹bâ€ÈƧ1ˆ€bˆ(¬5ŸýìgyéK{Éår<öØ™éå÷Üó~ÞúÖÓÿ'I„<úè3Ä1µ HH(Mò`ÒR‘ó¶ÔÄÛ¥—ÞÊE=¹šOå´‚ Žc<Ï#ŽcÂÚåº.ÙlÏóµ¶åJZt«ÕVš˜˜`hhˆýû÷³gÏÀ$1‡††øüç?Ÿ^vèÐ!zzzèéé`ÿþýéÙ ö6"²>)ˆ(ˆˆ1ŸX 8 ²±iL " X "ŠkMlÞüb.¸àJ¥kð¼qÀ´ü|òÉ‹8qâì)÷9vìÅ"œ~ú@?¹\Ç1•ŽPOH®´ññ+¹è¢ñÕyðDQ„çyi;U0 V»–c©TZÓ•ŽÖ¢*[mllŒ®®.:::š.ß½{7ŒŒŒ¤·³ÚÛÛéèèàðáë}"²DŠ"Š"bÌ D6> D DDq`­‰ã˜K/ýElîëíoÿYzÝŽýìØq?q-“EÅtMGðVûRããW®ö.4‰ã˜b±H†xžG†ø¾O©TJo³’ްFT‘UeÏ>räÈjïÊ´æŠKœ8q‚¡¡!}?SÞÈÈCCCœ8qbµweŠ•ø~päȆ††ÒIK‘S•¾èûˆæ 5g8_a²uëV¢ÈT*>øà@7I?ü0@šxL’„ /¼$Ѝµeõ‰cÓ^Õ÷ÍÏÀär+w /ùßóÜçþ÷Õ~*›‹E2™ ƒƒƒ”J%\×ÅuÝZ»Ú•322Ò’1Á’7Þx#—]vYúsàÀ†††š.³? qèÐ!®¿þzÚÛÛɵà÷ÔSO122¢³ä”g?þøjïÊœZüq "D lê©§V{Wæ´\cM,È©îøñãk:ñ8Y«cM<êûœê>¼f“-Ç÷›x´“•"§*}?Ð÷ÍjÎp:a¦ë ZQ‘$.q QdÛ¥V(—áĉúššvmŸÿùóÒËví2'{¹®ù)•ÀqLÒ[ÁBȇ¾˜o|ãƒ+öxAؾ²@&“!ŸÏEarÚi§‘ÍfmºŸçy-{Ï×áÇ[2&XÔíííìÝ»·å566ÆÍ7ßÌÐÐ{÷î%—ËÑÖÖ¶äížwÞy\sÍ5SÎx9ÕtuuÑÕÕµ¦Ïî_®8°}ûvz{{WûEV]oo/CCCkú˵Æ"Ë«½½ÞÞ^úúúV{Wfµ\±àüóÏט@Ò5NÕïW_}µbú~ ï"š3ÔœáÌl»Oû»ã8ü꯶ñÒ—B’˜ŠÅ0Œ8qâÕÀf¼Z1Çáÿø|á ¿„çùÜ~ûÅév£ŠE(Lâ1IV¶ê±vt+ò(I’†!I’àº.…B8ŽÉd2ø¾Ïàà n½mª±ÅêJéé顽½}Éc‚E'[ýAá†n ««‹0 ›J§'ßnr?çÉÿ‘õIq@D@±@DŒùÄÅ‘McÅQX-÷ÝׯÝØü—MBV«&I†õÿážFÒ$eÇxžÇÏ~¶ðùä'Ÿâøñ³Ù¶ín ¾¶¢ã˜äãJv½ðÂ#\zé­|ç;CÀòf;óù<®ë’ÍfI’„ ð}ŸB¡>Oö9ÛHZ¶ÆãÐÐHÛ­.Ô¾}û¸öÚkÙ¿ÿ´Ãžy4¹ÒÐÐÐŒFDÖÅÅ1f‹Š"§ D DDq`µüøÇÏb|üJÂ0¤X,²ÿE|îsŸ$ MkÔ °­V£Ú=Ç×yÈqäÈ&^ö²ûÙ±£σÁAóS»ùŠV;žvZ'ßùÎoÙ´B³UL+ÚzÕó<<ÏK“‹•J%mŸšËåV¥ªq%,ªâÑš˜˜ úûû§,ÆÞÖÖFOOϼJžmÿä®®®)IË­[·¦g%ôôôÐßßϵ×^K[[ ­­k¯½vµŸGY"ÅÅ1æ D66 D DDq`5D¸nÂßÿý„ÿçÿù¯Œ=Æùçï娱³ð<³Fc.&¿ÐÓ“áÀpmQCRÍdï¹g;ÇŽ•‰"ÈdL›ÖBÊe󘃃+s|]tQí·8M”¶Jww7Žã0<±@q@dcÓ˜@D@±@DVÃ_þå ~øÃ?é>æß|ªÕ•;Æ]»&8qâÛsÞ. CªÕ*q§IÃL&˜¶©Åb1]×qxx˜Riö5.mEäš°¶\ÙV>ÎÆÞF%Î""""""""""""kÓ¦MfÇŽû—øm^ýê‡ÈåÌu¶Úq>mQlW^Yà=ïùwÞy-gŸ}vzùê®ï¦¿ÙÊÅÉ¢(¢T*‘Ïç Ãb±H¥RI¯s]—r¹L¹\Æqœ9¯æ˜×È¢–ËÜñuQk<îÞ½€þþþ9víïïoºˆˆˆˆˆˆˆˆˆˆˆˆ¬-wÝÕË“O¾ŠÍ›¿É‰ßæ‚ .àæ›ÍšŒ®;}›U×u ‚ ©Íhc‚-Ž |ç;ßà=ï1-W³Ùú¶V6 éy¥R.M8–ËeJ¥Q‘Ïç)•J$IBšäd’$ø¾OµZeppÇqˆ¢(½ß|ÙµׄeN<.ªâ±­­žž8À¡C‡f¼Ý¡C‡8pà===´µµ-ˆˆˆˆˆˆˆˆˆˆˆÈ¼% ”Ëæ÷'Ÿ|’7½éq.¼ðBÀ塇ÎN“‚3µC\Å7¹è _ø,¶oߎïÇĵŸ¾_O<A½ëJp‡$IÒdcµv`Qm'òù>¾ ¤£ÝöB*$׌Óf5`ÙÖz\RÅã|ôõõqàÀî½÷Þå~(™¤\.S,kɲ§Ÿþ%¾ûݸ‚›o¾×Ã÷75´Sͦk/ærf]Æéø¾?ë:‡öªÆvªËÕ4“É000ДDÆuÝ´-ªmºsçN’$¡P(,*èû~Ú¦u]I~Š˜êÇkYÅ£ˆˆˆˆˆˆˆˆˆˆˆˆ¬-aR,yÇ;~›§Ÿ~oyË’¤›sÏý<ðŠW<—ÑÑÑ´íéM7õõÖ¨¶ÕêtEþ¥‹¾¿<Õ“ÅqÌàà QÑÝÝMÇ”ËeÊå2Žã088ØtûÁÁAÆÇÇ]µ˜Ífg\ÏrMs&á`* [L‰G‘ ª\.óŽwü6_øÂâ8\xáu8üùŸÿ;6mú •Š){³9¸[oía×®Û›¾?ýó/C‚Ë ‚€|>OEär9|ßgçθ®›&'']w9\Ël{Uð1ÉÇ[öV«""""""""""""²òî¼sŒ0 ùÄ'>Á§>p&üÇçóÆ7VÈf³8N8mÕß}÷}”(ªW+.5qèyÍíV[%Iòù<£££8Ž“V:ær9òù<ƒƒƒ§n’q:U ÂT=–¸­¨âQDDDDDDDDDDDdú½ß;‚çyü›s££0D\ëÀà lrMkÕ>Ä“mö}6ÿð‡l~òÉ%=Ì¢Voo/«ýT‰ˆˆˆˆˆˆˆˆˆˆˆHM†üìg;ð}“@Ìç!›ÿ:‹QT¯|tÝ–uá\°îîn<Ï#I<Ï#ŸÏ3>>Þ°ŸÑú[Ç12@XÉ]/—áŸø©﬽¨O%Pö™7ÊÎw¼ƒGîç–ô0‹Zãñøñã qüøñ¦Ë/»ì2úúúVðY‘ùJ’„jµºÚ»!""""""""Ë,Š"Þô¦Çñ<(Mq!ÉÃÆÎ›“[¯®”$Ip‡8މã˜(ŠÒõ­u—t(1&ù¸’Ïm©„p]Éd žˆÁ^\×åÄóžÇù ‰ÝÅXTâQDDDÖŸr¹L>Ÿ'^+½1DDDDDDDDdѦ›âISÝxÛmsûí¿ ˜$bÍ»¥Rs’2—3—-ï±4Œ=¾Z­R©T \K‹M.… `ÖV\‰bªUó¢îöàçBó»ç™7F¨½?N<ïylÿÁ–ôpJ<Šˆˆœ’$!Ç!“ÉðÁ~pµwIDDDDDDDD– ¦^V.Ãç?ÿ4G~—;~F¡¶Hp¾ÅårsâÑqæßÅ*—ËDQD’$‹E¶mÛFµZmZ¿ÑqœõYá8YŒI:úµß[!I`rb6Ÿ¯—»–Ë&S}®Y»ã€ï›ý¨9ò+¿Bu¡ ‚N¢Ä£ˆˆÈfŽQá8ÃÃÔJ%î¸ãî»ï¾ÕÞ=Y¤ÉUŒIb’‘×\s;ž—ðý& mgÍùpÝ©9¬åf+;;; ‚€B¡0eÙ J¥‚»Z‹M¶R„i±ê‘V.ÙÎɘ›‘Ž¢æÊFÇŸÏÁ[Ìõ¾o²Ò>&Ú¢$¨"""PEtvv’Éd(‹DQ„ëº8ŽC6›å-oy ßúÖ·V{7EDDDDDDDd‘¢¨¹ÝjµjrKßøÆŸÍfÓ˧^õ8¾?ÿÛ¶æ8¢4¡èû>£££”J%\×mªpÜIÇF>MÕ†óÖŒMà7/rXk£Z­ÖêÌfÍeŽçÏðF´¬í«"""PãÙ`I’LZü½ï}/oûÛW{7EDDDDDDDd‘§¹ê1Žáª« Š¢¦ÄãB­tµcÇiuc6›Å©•f ü•΂®$©W=‹Ó÷ÏmÐÝm^¤$1•Ž6ûlãôýzo\Ï3o”¹Þ¦ ³–”x¼ñƹì²ËÒ€4]Öxˆˆˆ,hRo0 ÉårM}ðÏ;ï¼óV{—EDDDDDDDd‰ì¹æ¶ÚqëÖ?&—Ë­«êÀ8Ž)•Jd³Ù¦ý^¶õc XûY sse}㸞q¶ë76&+ ó¯ëšDääËÁ$<'+Ípù"6/íðxìíí]Ú#‹ˆˆœ¢(j:;+‚YQ¶¥Ä|‹E*•JSÅc¹\Æ÷ýtðæ8ΔV«""""""""²þA½¸Íu?ëºKnOêºP./ÏþFQD±XÄóÁ&>×cO|Å™câ€È©CcÅQhdsS¶ã¦ï‡ >¡}&®»<q“ÉdÈf³är9º»»©V«³Î•-Z’Ài§A&S/ µÅ…¦µh³®árŸ¯Ef¢È”¦œëÔ“†¯òLBÖb,aÛ6ó/˜ûÙÛ9N½òq©<Ø~Çv6?¹´’Ç%'ûûû9tèPúû7Þ8íÏ|8p€‘‘‘i¯ëë룿¿ŸÞÞ^<ÈØØûöí[ú“)"kŠâ€l4q§‰Ç(Š”xœ­R±\;õÌnÛ¶Xõ D DDq Q›N¡ù¼é¶90`º‡>þømxžÇÉ“'›–üY,Ç©¶J¹\ÆuÝôߣ¯=Ê‹îy;úw´î‰™<‡fK7ƒƒðÚ†D§ÏòW<ÚNh®k~ú£úcÚ6°YjU“ö?›5ûœË-,Á8“"Ì|õ·þü[|ëßZÒC,:ñøþ÷¿Ÿ±±1öïß?e½ÇÞÞ^öïßÏí·ßÎØØsn¯««‹ƒrðàÁi¯allŒ®®®ô²ööv:::Òħˆ¬oвQØD£ýÝþØäccÛÕ™îÉdšÚ¨6²—yž×TM9]âÑ© µ^ª  DfŠ"§ D DDq QµjrlAÝÝfÆ\Ž–µXmµ0 Éçó”Ëe†‡‡©T*”J%\×e×ßíâ{?÷=“p[ª 0™Ò©UfñËæËâI¿s=ÀªÕzrq&6“ëû@ÖT86í'Ó?•Jë³À-ÞÜdÏZÌÆÆÆ8tè½½½ìÙ³gÆÛuttÐÛÛËûßÿþYo&´··ÏxýñãÇš‚ÀÖ­[g,¯‘õEq@6‚ (Öú­õDd†³¶Nµ×EQ„ïûiÛT˜:€ Ãß÷q]7M<ÚêÊB+Î~ZEŠ"³ÇÅ‘SƒÆ"Š"¢8ÐÈuMÇM›çÊf͉ëq¯©Äc¹\NO¾/ éÉòémžõ¬g1ñš È£˜¶§‹Ç&[›‡›VÃãšû4üîP;¥V­šß7/J®ÖË4L‹U¨'D}‚i^+·¶_EL;ÔåÔ‚å g³¨ŠG»(kOOÏœ·½öÚk™˜˜˜qÁוðè£Ò××7k)¶È©À®Ãúàƒ®ö®¬Š|o¼‘þþþÕÞÙ`’$IûÔçóùôÌ­jµšV&6V.Δ|œÜ2H[©ÚõoÛXÙèy^º~ää–“ÿã7Ò××Ç£>ºÚOÝŠ³c‚…¬?-²ŒŒpã7ò¹Ï}nµweU=z4…"§2û7ñèÑ£«½+«âsŸû7Þx㆛Y(}?Ð÷Í®9à ¨W8Úã–-Ÿ#Š"†‡‡×ÔR;v­Éááa …žçMÛöã˜$XuÐÝm}`²±ƒƒµJÂL~nrÔ×9̘„ßÜ«$MÏ®Õèy¦nc÷²(jNŠÎ– ö0Õ—ËÝúu6¶Ô1Á¢*m±­­­érÛ?¹‘½ÍÈÈÈ”ëVÊ\À›ßüæU{|‘•4[Y½ís~ª¨/¹ä’[2ˆLÖØ.Õ–ì®±Í)@ww7I’P(¨T*fìZ»T[éh·c·=ŸÇö}ÇqÒ­QQ,Ó$c¡PH÷Ñ÷ý´G¾3©¥„çyT*•ôÿdhhhUO Z-ˆËNïär& yðàär¹5•tÌçó …¦%¦ëÎÕÖÖÆ•W^ ;€z"p®'ÂV–ʺ¼ÐÛà]í=oNíñ ²°M5íƒï7·võ<“xœ¼3UVfi®Æ\%¦¶y­éíímɘ`Qö±­|´ÚÛÛ§ü¡¶·éèèhÉs2Ý™ˆ­Ú¶Èzg“‬„r¹L&“!“ÉP­VÙ¹s'ù|žjµJ>Ÿ§»»›0 ‚€0 hJNMÕŽf«x´Žö÷ÆVªÝÝÝéz‘Žã¤‰I¨¯ßؘ`´\×%—›Ïèm}Q,ÅÅ1 Dd#ÇjÕä²§w®»îwß}`MÍùØ9°ù$Bÿâqžóòç˜d[•ùUùÉÀN·nãBœåÀð¤5²Ibª.§Ó¸_¶Ê³qnp®Ä¢ t.þÐæTÇ>,Ñ¢»wï˜Wé±½Íl=˜çÃ&4'/;44´äm‹¬g6Á´mm%ÖF 8 ËÍ&«Õ*AËåÈår 388ˆã8iòÏþžÏç§=³Ìó¼4aõ—ëº3ž `«ÁTGN®°´ýúê Gß÷ÉårMg“mTŠ"¢8 " X "†bˆœ qÀ®çØè©§n!›õW´Úq¶yæb±HwwwÚ l.gw˜×ÇÃTÎg »P0ɼÂbc¬y•ÏoȾÅ1Ýðüª©¾4k.o¼M>™Œù™oP¡0i;˜õ$gâמ‹`i‡8£ˆeo庨Äc[[{÷îåÀ³&ûûû9pà===-ù€÷ôôÐßßÏÄÄ ­­k¯½vyŸ%‘U69 Û$„M6&IB¹\žÒŽH«³¬ÆDÈz¤8 Ë¡X,rÚi§Q,q]—îîn<Ï£T*Qªµmð}ŸR©D¥R¡R©0<<Ìøø8ãããémÙJÄÆ„#0m+dû™ã8­N´¶«M(NwÿÙª7*ÅQP,C±@D6z°<­(ŠÒ“æWR†é¼3Ôç­íÉôƒkÎaóþÍõÊ;»¶á| /­Ú`—ßn˜'/—MYé=Ý0›Ä\µ ÇŠë‚ã˜Äg6Û¼nãlJ¥æ¬±ƒI.ÎÄÁ$b—²æäl²ÌØjµUµÆ#@.—cdd„›o¾™C‡ÑÑÑ‘žY`{ÀŽŒŒÐÑÑѲ5z{{¹á†¸þúëikkcllŒÞÞÞ)kMŠl4år™B¡&2Êårºž[.—# Câ8nª¢Š¢ˆjmÝjµJwwwúÿéò]/¤Uìç!ŸÏ“$ ¸®›®‡8Ó:Œ“t“×Sœ|¹]ïÑó<’$I/¢Ïóˆã˜L&®™Íf ‚ é³êy^º“M[åX­š3¯¦IŠnŠ"¢8 " X "†bˆlä8`s_6×–$ ™LfÊ:Š+Áž°o»•Ëe‚  P(AÚ¡k^|L’ L"¬“psf¸}™Ä_+*<ŸôaKdŸPÓÂux¸¶˜¦ [c˜˜fn°ól.3¯ñh0IÙn`Oé¼,÷’,!ñØÖÖÆÁƒӪǡ¡!8^ßÞÞÎÞ½{•t¼÷Þ{g|ÌÛo¿=]Ør÷îÝ"pˆÌ‡­~“0±I“$IšZ2†aˆïûDQD¹\N«¶ªÕ*ƒƒƒÄqܲ“–“â€,—(ŠÒdc6›M?#“zKmS19i¤ŒvÝÆr¹LEø¾ïûäóy<ÏÃ÷M› ×uÓ3Ç<Ï›¶Ú˜þì¶04ƒ±©O@½¿ü: X "0},P9µhL " X "§^CSŒ×Øäª\.ã8δ¸–[±XL ar¹Ùl×uÉf³3Î[ͨ@½òÎr˜¤ØLÓVù¼©\j›U€ó]¸¦ö¤:Œ×çÑ®‹àw:Íc-GÛÈ'ç¸]³cS¥Ø*eLÒw«x´öîÝËÞ½{cll 0IÇåìl++E6’$IÒõmå•Ç1aEQšXŒã¸©µj6›M+´’$I¯³k¾5žýòÅ/~qµwÉd!’$!â8&²Ù,Õj5ý<-g°çyiu#˜äc6›¥X,âû>Ùl–\.‡ã8äóùôƒB¡Ð\×­÷’÷<3êô<ž¾ê²Z5£Ò86gmE‘ù=I`!gŸ­qŠ"¢8 " X "†bˆl¤8ɘÜ×ɆU”ËeVeŸ …I’ÏçÉårtwwS*•pgÆ®`3 0Þðÿ °­öoc¢Í¶AcÓs¶bšoûþ§|ø\ÿ}™’»ó=Œ“(leâq,9ñh-w²Qd=jl«8›(ŠèîîÆq\×%ŸÏS*•ˆã˜l6;%Áh«›â8¦\6+ÑzžGéãZÓ%TÎ;ï¼Õ~jDZÂt*•JÓgͶ¶ïÿ|>OµZÅq†‡‡ñ<;wEѲžfßu]Î<ó¹éežãðk==ìøøÇÁqB—\άßxÉ}÷KÓK£–|L?Ë®[?ÕÍV:F‘ù©ý?Øs»¹¿ï›AY×ûÏÃô•""""""""²&„¡ùi¬tŒã8[pua ØÇÅq¢(šR@³`“§¨r˜µíáÙê³Y3ïÕª ÄdŽë/ôÌmV»kX–úZ óOX®²–%E¤™MˆØ³OòùmZ(šª®l·Û˜\½eÙûO—8±„”x”,*• aÒÙÙ™Vû Ç¡X,R(Òu¹®›VW«¦`°±ø±X4ƒ¼l¶9og‹í/ý¿Û ›;‹Üàyƒƒƒär9J¥RÚs¾Z­N›€÷}Ÿ]»ÞAg'tw7 Ö &žšã³Ë,F» ’„04ÿ¯þGaçNŠ¿ðuÂ?{Ðd1Ož„áa®ÿÃ?ÌcP©PNrıH:Ný±£Èü^;ß`öA\GIš¥´K9Úg²ýŽ;xíç>·Ú/©ˆˆˆˆˆˆˆˆÔ‹¦YÖÀ@sµcµZÅuÝi燗›ïû ÍfÓ9¶ ‚`iE/“s¨Å¢™<ûëAøUÂe>°Ùòš¾¿å›$_SmØ*&ñ¹P>P¨Ý·ÈÜíbg’iá±Ì@‰G‘yŠ'Íà‹E¶mÛF>ŸOŽ®ë’Íféîînú#àû>®ëâºnZÁèº.q§íV§ãû~šx´Û˜Ì&íu6A¡JGÙÒD]Mggg:°‰¢(ýœ9ŽÃÀÀ¾ïS*U¨VÍ}}ßOýLÁ¡ÇÙgÿ[Àtl4ã0É@ß7¹¼8®'" Cü‰ÛÉžuÝû."ù‹ÏÔZ¤Bù˯„BäþQ¾ä£P(Çõcˆ¢æ¥í@²Z5I×5[­šýqÝzòq¶v°ñé—ÒyZD„—&-㸞¼L¾Éßb5`¤޾å-|ùMoZí—XDDDDDDDDj‚ÀÌM®'©V«+^db‹jòù“ÉP,I’$má¤ë*ÚÛÛä_6›M“‹k,6žñaö߯êG[õh×–ƒ™«íå¶’rºÛÙV«öqÌ6—øEÖ{&UÖÛ…þ஽ö߆!õW?á.%_;9*Iê‰;;{Þóþ-P I<2s›ê'Ÿ"yp‚äÃÁ׿þº´"Ñ$×ö)Šÿó%ø;îO3wžgÆ>ù<„¿qñWC6ËÀ@½=«­N >s!ÞöõM V»¤ã˜ Jß7IÅÆä¡ãÔ ¯TÌ3—«Ýæ)Hþ£ylïÿÖªÔîXKÊú¾—5JK¥z¥eõËà]Þë1ƒ£¿‚={®æG?ÚºÚ/µˆˆˆˆˆˆˆˆP?½qZ×ÎYçr¹Y;bµBÇ”Ëe²ÙlÚ¥¯P(Ïç[7לϛ3ìï†BC"uºcÀä&—+ù¸6ñØÍÒÚœRÛÎR«']`¸¶? }~V ÕªÊä”ÔÝÝM©TÂu]Â0L«m`õ~%`Æ4<ý4Ñ[K_~?>Lù¿l&~Ãã¸Wl1;ÍRÉ‚_ßß Nýó^(˜í…as«‹B¡žD,LÂÏq>ÒtÒ’ãØÖ®æ¾žW¯ätœz’tp°yŒ5< tBr‘ù¿;þH À•˜AÂI(¾¢KÍý¡^E µ„èw ÷‹Ðý!89 tCô‡ðÒ-Ïpåøù«ý²‹ˆˆˆˆˆˆˆõù#+Žc:;;ñŒþýáO^‹{ñSøƒ‚³÷‘½a “×䶉ËÉ*“Xlçù~=éºÓß϶vµÉÑâ õ*EoK=ñ89Äx‰9*ÜQK*Ž—ÖÆ%öy €ê÷µIÍ$1ûU(?ÿ9µ}‰ d†Ûv>Á%÷]²Úo‘S^g§™;jœêîîÆ÷}[WqX­òô/üþËá?¶·süß X,¦IG0óÌ¥R Çq¿¶d>o&Å,Ç!]ó(a~Uƒ9L[ÑN–¶6âd‹Ý–©4t1ós‹­\lUñj¯íW¾¶?­|žI‰GY·º»»›’…v F{vF±X¤X,†!ÝÝÝd³Yr¹\šlŒ¢ˆ(ŠðÝ}[£6¶[µ&'grF‰Md>õÔnvíºz_ÙHáQ4uÁFå²iwZ,š“]£0IÌuïíb±È 7 qÓM# Ëi§Å sôè~úÓÿ—M›þDZÛÉq饿ÏÖà \yåùé`Ì÷¡RJÈ>õIÜB–áŽ÷P©˜_¥¸.¥¯½ŽÑlÂuM’.ЦONÇ÷§ïú0ûövÕžÃ;!ü˜{•¶3ó%÷b³v©ØJr[©÷sÍÍ9TMÓó̿ժIþº?¿Ç<¾$PÜ}/™àËoúrëß0""""""""2/qlæÑ 3ße—Ò±KƒU*•Åo¼¹N; òy¾qü8Ãããܺk¿qÝulÛ¶J¥Òº5$㺻ÍäÔb“–r@ ÓV´U|ÌüÚb8˜ê„Å'D[¹JšS{~rµ}É0ósµÔ¯ó¤Ä£´D’˜™$õ`Ùx2C«Ù30ŠÅ";wî¤X,’Ífq]—|>϶mÛ‚€(ŠÒö¥R‰\.Çøø8¹\Ž$IÒJF{Ö†=‹Ã&/mâq)þ¤r*×u›Övœœœ´Ékºää\}TULÒ“áÕj= 6™maz¹œ0¼ð…rôèQ¾ô¥j·H’O<ñ!^ùÊÿ@µZ¥­í\·žèÌ÷ó8¹ºqr»ÔÆÛDQ=©gÇ2ahZ‘Úõáì³ÿ€G}”ûîkã+_!ŸÏóñßÏ•Wž¬=\âØabâê4a6¾ïpäÈå<þø—Éf|ßÇw"ضmj4—ýçŽôÌ0;®™éã,ßç$nøwÄP¼ ܳ!‡ÜùPúmšJUš(yþ»ÙO{ ® ÉyÔF.d/€Ü%æþñ·Ííík–}¢ÖÚݱ×Úëõe:n™—8®wmT­VÓåÁ­ZÅ®/”ïýÅ_äº;îÀu]vîÜinãyìØ±ƒ\.·¨¹ïôq |¿>9ت¤£e7׊¶«eZSýWÂ$úÊÀNjë&Íq› \..&Që`æwR_—ÒaEÖTâQ$ŠL•tšyÿÎN[\×Ä’lÖÄ[¾TAÉdعs'ÝÝÝÄqL6›exx8­b´UŠ–ã8颷Žã0000%HÛ³7â8N¯³ÉI{]¡P Žc‚ ˜wÅc>ßü\}íkÏŸr¦È]w½”‰ ÓuçÎΦë“ÄT‰5žÈ2ÛqÜœðq]— €[o½”p ôr–µ£1¡8(2Ÿg›H,—ÍÉJqÜœœ³ÉÈb±ÞFµ»ÛüØÏ?¶9øÊWþ7/}éâ ?Ñ#›¨V«Üzë¥<ç9/¯Ée>[/zÑ=iÅcñÆ£äÚ?OnËçxÏ{^“ö˜'Ÿ76< ö²6ñh+.gêè¶@]Ž?¶¶ÊÒÿ—Ì>¹.¸Ÿ‚ìf€(Ä ìgµ›ú ÷eæW\ü‹jÛ¯ ª› Ùa¶ån©“{>8CàWê÷µ'7\uÕñe8p™K˜¹5{â¾e磽®¢†àûiWÀ$IÒ%ÇlМ4\¨86Ó˜9u3)7“´[¨¦Í©ƒI@V± «•s‚˜db„iuÌrÛ`Žë[%‡©µyšjíq[X06%eN6~d2õÄZ×+šr93÷ïû&Æ8µÊ›”˜I†µuÝšEQD†tvvR.—ñ<ááaÆÇÇÓ*Çé’€3µKœ|[s&‰C†Äq<åz›äóDχê!¶m"Ì~3pj÷Íû:³öÜ ×…øûƵÛ9ç¯Ìíý‹Ìí²YpŸüæ±^˜˜1M¸ˆˆˆˆˆˆˆˆ¬€(ª¯ëØ8åœ$ ™L×u§íà7oµþ­Ç2Êå2I’000ïÏÚ/-&ûWÓÝm&­S-P?ù~¡²˜Ä¥©äÛÉÂÛ¯Ú9¸V*Õ¶;Œ™óÛ†)4˜\ ´Ò } Rûñ0ÕËìY+|ˆ²ØŠ&[].›9~[T(Ô'êg«²Õ53©V«A@ÇxžG¹\N[›šm›„ã|ûXÛ¤]ã>•ËS'Ø3¨TÌ,¾Y0×M†¾aènÚÂu¦„cí¤‘†ãi~lß7@.¼ðf‚Àü?Ìmxàt¢ÈìŸëÖÕª‰õžg¶fÿM5c½…âýÑ£¼ï}çqÏ=›Ò¸nᓟ|˜“'ÿžG1-cmKÙ÷¾÷Vþöo/clì³\pÁÄr½}d ‰ãæõ mÎ. Í}oÙÏx©d’‘`Š ‹ÅZåœk>ŽãÐÙY?Ñà‹_ìç]ﺊÓNûccï&ŠÎN?¯ö³l÷ùînŠÅ€íÛ߉ã8 öÜŠÿéß%úó?§›öœ—áÑG/!Ž¡üõ×™Ïmé-¸1¸™†ä ãÌ»œz®8emYؾîµÏ¥ë/2ÿïç¬Z;õíµÛÙ>ìfàÖ~?·¾V£å¾ºï„Ü.ˆ¿þÙà~ø6ÄO×ß{3f Vc«©m¥ô›ß¼LÇ.""""""""3*Í<öäÂ@{ÿ‚Öv´~ þàì³ù„ï× f0ÓÄX3qåPŸ`´“ßÝÇ*•eœ\›ƒƒIô•0ÉÇîÚïó«¤Ì'—ißì\äõ¤c“,µ‰¿å*„˜K–¦ùÂå¢Ä£õŠ bÑÄÇ1I {æ…ï7'Ùæ£½ýiúû$I¾AEi[Ó¸ö`AP(ˆ¢ˆ p]—ñññE/˜†f¿“ ahþo÷Ý®éfbxŽÏþÿkJÌ8މ•_üfM:vwÃøx=qcQd3SK–<üð9ém¶ºÊ& èéy€cÇŽñµ¯=Ÿ›o>‡rù*•,7Þø|ÚÛ·‘ËY«j ÉåB|ð |°Àsžóc‚à÷H’„óÏ¿’~0ÏÙgÿgœñÛüå_þÞö¶s8räBþîïnåŽ;Îàç~îþÍñ×2zþß®ÌKV\š“šH“Ûöó[.›Ï·MÐ õ%íçfp°~²’MPîÛw‚Ri€cÇî&I*<ôÐWWñï|èáäIÈå<þà~+Ý» õÉBãgœA[¡`ªõâך±ÊÃïÁ};.ñ6ø¹³^ÄËw]îGckÑ$™ý$†Åò¼æµ¯[ÿb`4´ÍˆÁ…øøÿ38ªR?ÛÈ%m¥jŸ8®ãJ½†ò̉J¹ÏVLúxE ²ï¡iãºõ1æj½+""""""""­EægòêAAP.—œÿüxÔ+ì$>/—q‡Ê,æn‹zÂÑΗ¿9€çͤÒtíS—²~Qs2~+T0 Ǹv 1õäÞ*åEó\ÚœJ\û±kKX\«ÙuB‰ÇS”MÀyžIR$‰ vIb*lÌH’ù·ä³mI«Õj-¹XáÎ;¾ô¥ß÷q]—jm¶Ûö”.5”r'IB’8颺v’}rÂarܵՀž7µ¥b6¯ïE&FF‘©DüwÿîL\·~›¨|Ë[Üôq'o#Žë‰›˜±m'ËeçC:ÂÉ“»ÉçOã¶Û¶EàûarÅWP*ý{>ð¯óÅ/Þ“žÍR*•ˆã˜$Iøñïçu¯{ùü-\vÙïò’—8µö¯U>úÑ6’ĬcEÛ¶ã~á¼ãõã¼õ­Û„ßù îºë=”Jðýï-÷¿oýߟç¿üìWû-(-d+”mÂÛ÷Í¿¶Â-ŠÌ HÕj½Ú­±‚¹ñ3n«oK%óoÂwü€K/=0 8ûìçñ¿ÿ÷ïz׫øêWÿøž¿ÿûû8qâ!À|–¯ôQ^}ÇüäØ1>åyäðº»Ù²å(a¸÷²3ÁqpjûP©¼ž_vë]T›Nt8¹¸qLãIÓiüì·œ­x¬=~ú81 ¼ª×ƒ· 3Ȳ; µÿ»õ6«Mq/„Ê(äÁý8¦-EP»_œÏÿmöç,›…¡¡e:v™Všù÷ƹžb±H¹\¦R©àÏ·úÇ®Óe'ñ0srù|>-˜s[v=B0Iº,f.«€™oòsð=>â¶>`æÎ•WûÉR_Ö¨\;3ga ædó¶¶*sµ*Wˆ§[m×lÌåÌÄt¥RŸŸ< ?S‹ç$I‚ ]+ѶJõõ©?âÀwpÆ÷ñò—߇ç]O¹¼…×½îóÄñµ¸®iáúg¶‹óÎ;Ûn»ß÷¬µŽô<¯Öþ¾ÿ}»Wƒ óÞ¤……Íï¾ïE~õYÇxÓoì¹t?ümÞ½÷¿óè£6±ôŸ‰^þëüw>Jþ©sVûí(-Eæ}m“¹\ýÄL¦þ9Š"šªníIPÓ1mxÛðx‡oÂ÷ Äñ«Ãýi+UwÇÏðÏüèþ”j§j%IÂiÇŽ±¥R¡xÛml© r\×åMo:—| 9Öd³E§¥‰²É'Py?'¦>8˜çfÇžÆT:LY0Ú㲤>€j”«ƒ:©Ÿñ”#]¯±þâ’&"§í,ë‚ûKS/ð^1õXÅqŒã8Ü{ï½Ëtð"²VDQÄs{.ßÿ¿ßçŸÿåŸùó~9'N¤ \À·«f=Âj ÙÀ3óR °Å5k(Ú„ä»"Îj¹’oIÈ*õëõbÕ´\ó‘kˆf60[±g×´'8$‰™È¶ql®6Ìv’º\.ãû>QQ­VkŠIZÉX©TÒ¤™ÝnP«Ì3I;[A58ù¼y`·mk®t Ãz’²P0É {&H.W_»np°°ƒ:;Ím}ß<®M¸&‰y|›ð˜k™¸BÁœ4ò–·|—RéNN;íû|ìc/å5¯ùyÂð7ùÈGþ”#G.N“³AðÌ3ד$.Ÿþôsyä‘ÿɉ±}û}\tÑW8ãŒç“ÏçÓ¾Úq …Âð¼^Ë)Õõö‰L’4;ìû \`JWã¿øöïÏ6ý!ó>ú«8øí þ ¿4¯G–µ ŠLûÓR©^qk?O…‚yÉíûº±’1Ÿ¯'$ƒ ž|ll¿†azöS†|êSgžùßpœv6o~’‘‘Í<ýô/9²Ù›‹ Äï~à :Áÿ7ÑD;¼®HÛO¸Tb ¤ƒ¦B¡@¹¼ÿrÈõÔÏ«Âà36<Ó§=‹9Si”yŸe忤vßda÷[’è¬Ïlgmå&ýÛtÐÌ<±ë@:&ÉûÅ}‘·î~+_î×iÛ‰¢€éz5Ødqgggíµ(sË-·¬À""­Ç1a¦'pù|ßÿxàã˜@a¾z\É ¸ŸWñË>Í öÎäjžµå ÜõøyìÛ~‚/mýç÷ÓÕ>,‘ ÏÙ¹Þ0 )‹är¹…'kgÔ‹Åt~Þ÷}&÷pMø¶ w‡õV­ûá`’u1f.*ƒ™ëÊcæ³l;ÓµZ½7y~ÍVA&˜¢Y6J?øÁãüîïžIµúwiÕu]:;;O'ñ<ÏKל<묗ñÅ/¾Œw¼#ÃÄ„Ë/ÿò]ìÚU /'Š®¾úAà¥T«U®¸â Þú’GØ™)ó®w=ÉK_ÚÎ%—<ƒç}—ç??›îÿœUóQÔœ‰“U­%šÊ71mZû—.?Lü;Oẛšž¸ñqè켋$I½ž¦,¿$©' m5oãïÙ¬ù\Ùßdöíãyõ5[Ëåúm}ß|níg Z­òÊW¾’¯}í^¢èŽ˜nz€:¯àîGr|ä#×’ú>ï¿óN>¶cîæóáuWBéÊi#—˱éð&HÀ‰J¶ ð³˜K–zóÆ–V¹—`31¦ÕC“Pœ%a ½ Ø]ûO\ߦy¨÷~· RO~|Ûú`! ËÚG¯öûtq·2u¿íg2Š"vvîä$'Ibs‚G¹\¦T*¿ûŠßåÜä\Þö oã¿û ¼óAzîëáÏ~ýÏx÷'ÞM$‰‰ÏIí ”$IÈd2”J¥ô º×¿þõÜsÏ= z_ŠÈò‰ã×uÓ¼ìÉ7Ý?ü0wâ›ÜÁ—¹ä’_åì³_ÉùçŸÏÃ_ ÜÄ[ßú4þðåœþIþèîçSŸjcçŧñÄ'xåŽ{8÷ÂAÞèy|ì¦_¥ïwúøç‡)üI™Ï}à=Àm«}ø""""""š-ˆ±Ó¹QÑÝÝM6›mZŽlÚ;ÚJ‚(J«iŠÅb:ïãºnÚQoAb`§åÁ9Ö+Â̛ٹ;{R|ŒIFºµël¢o­N9g™~žNZN‰Ç  Z­À•Jõd…ƒƒsW5Bsec¹¶m’$ ’$™’Øj4]ÒÑuMÛGÛútpÐ$Sì¾Ln§ØÛ …úZsóÙ÷ÆØl*¦Õdw÷1Î8#âSŸºž+¯üC¾ùÍïsûí&¡†!xžGww7žç†!®ëâ8…B\.! M Xû8ï}ïÕ€9–rÙáÑGßÎÄăüÍ­·òÌ_ óø9ãÐù. 2ÁŸ2<C>Ÿg|tjãÚ'Þ¼xvçíçóæºÆòÔJ¥žôZL~mÜ7ï&yßô­$M‚t­þr¹ž$´IvûrÍ÷¤%ß7Ÿ!{¿ÿó."Žññ÷yªÕjšpw]—0 yç;ßI’$<òÿþWn¾ó[\N–Üc_gø¼ë9íŽ{ð.iã#·¼™g6]Ç5ïù-þî«À˜v¦` ŸY×uÍYP·`þ°ç0•2õ~ëÔþ_¦>ˆ‰0‰ÁÜK¨ðå0‡z2ªý 3¥JÐýJí¶9Lbú‹émýÚ¾ÕNv ñ9¶ RÛÇŸOÒ«í‹]{’°öyªŽã¤‰†$IÒ“8îýî½¼"xÅb‘ÁÁAóÅ=gœÅ£ûxÇ &xý÷ÛÝt’GN{„W8çóÙ‡ÞǾ‡þ3;6ï‡}ðâO¼”ß~^ÌæïoæŠï^ÁÝ¿û4qìâû>Îß8¼À{û߸‹¼‹xýW^¿ÚOˆˆˆˆˆÈ†•Ï× nlâ1ŠÅ"Ùl–Je–vYÕªiƒf’o` -* „aH.—Kç̶SuæÙ?Õ>ŒG½Ë×(& bæö*˜913ß6S!g+[¶Êš£Äã:õ€e+s¹zûD¨·ݹNžl¾ãDWÇAP_³­v†Ä¼²ƒ{3UfÍv¿_ýÕGqœ lT Ã08· B{<¶*(I<ÏãŒ3ÞË·¾u+®x´–¼)ãºIšPu‡ÎÎNr¹ÕjÇqÌ™!aˆ_(@íDîŸY€IDAT±²Y/mi™>ùA€{Éõ¸gßÈ7¾ñ%‚ `ÇŽœÿÄÇÈî<o*pÑþý¼ãu¯K«E?}Ùe¦Ÿ,ÔËÕ,›Ù®µ^-ë ZFQ={¸À’ûRi••²&ØvªfðaÞoómÇ>ϳÀæ}|÷Ý—ãy$IÂo¾ê".ÿ‹¿`pwî$ñ}â8æ}ﻂ8þ2ïü«;9ÿüó‰â_þÐ;Ùý‘Ýl»¤ Šðño˜AIü ù!ð#êI½ÆAE‚Ää©8ÀT/æ1ƒ’ê—ÓSÞÁ´<ˆhnEêSO^†µ»Ht†zâ2}b©Ÿ5^ÛþLc1›Ôld«$;kûl“¥vQj»ðv£rí~3œAeã_{Îm"²P(¤U×–íÉoãñÀÀwðn¶üd »víªKÃImA­µM8Ú¨N6i {‚€=aêãª$IÒ¤bcBÑÅe˜a<î{á£ðdŽ?zÞóŸä‘Mç²?û×òçx™óEþîï^Ë™gŽñðÃwóö¼[·ç^û—ŸõøROÿ·OsÓ;ÞÁwÞÉu×]LJ^õQ`ß«÷Á¿¾ |‹ 4éìï6ÖìÚµkµŸR‘ ÉÎÏ—JõfAÏç§,[6-ßO[ž=ðìgsåßH¥RÁó¼´+á’d0s\¥%lÃæþ õB"fþÎÎ Úg›£“uO‰Çu ŽëEqžg’ŽSïíºÍ÷³k¹Ù¶]v¢ÌNL'I’)ÛÿyÑgH´P’$ìÚõ Ÿüäsèëëdtt4m éº.A¤ Ã\.G†DQ”V0†aÈõ×ßÅ«_}5¯zÕ[’žfâÝqnز…ï~7¯ò}r¹œ™”o<‹ÄuMfw|¼þü‹æI-ðâoâ]u:@ýÄÀ@z²ÆÙ…½µ Iàë_7Õ‹“ÿ 4–§6&s¹é_ؘok]Y=výÕÎÎúKžËͯÒw:A¤UŒ¯yÍÐÝý®4¿}ûAÞò–,g|ó žx×»8gb‚‰W¾ƒþ¯Ë…áu¸´'tøäkßB|Å(±gª _þ//'¾"f[q[½²1‹ycó:à­µËcê•…¶ui“ô›Ì&šÏr²Ûž\¡hUn×ø·Ï™]ÓÑ.sæMs›éØÇ 뿟̇¹îW®ãë§7Üÿ6ýÞ&îÙýðßáŠï^Á¶ü¶zÒÓeÆjGÏófXΧŸÿ•o¬µµm¼iÃc•J%¢(JOzh\[VD穞âãýçOOü) ·^s+ûÂǸ袋8mk'c?ü[\ßeóÓ/f󿋨¼Ùç ¯dçÎÓ8öÈ÷ùõç<‡‹‡Nð$Ðþ½~^|õ;ùéØ?òÃ]MçéwóìžÃ'ßòW\{çµlK~‘ßÎç‚]0±‹§ÛŸæÌ¹®¶'fÜÝo6=¤w½·!iØ8dÐZ""""""«Ê&‡‡ëS¾QQÎç¹íCâ=s%ÁLhg³$IÂýQD¡P ›Í’må¤ï—–œ—ÆCËROB&Ô—\*cNòWÑ̆¤ÄãÇõõÜ‚ ¾NÛèèìÕƒ¶mâ™gŽí9òtv¾6]× R©´6@Íëxâ)IM[à8Åbß÷Éçó sï½÷óŠW¸|õ«£‹Eâ8N{UÛõ%íYÙl6­r‹Erqlž xq©9ÙP.CµÊö(â÷\6o®'øÎ"™¶T0—kÊ •bfÕTadèN¡`^ðÆÿËúPOrÍSÕ;é‚i¥ÚX•pÅEtœÝÁë¿v=G®;³/}6¯{ñf“t«‚[pq‹.8°©´‰ËËÍçɯýÔöÑŸF\L‹[è2sïô¹Z-ØÁÇ| õ &ñÚó_zøæ¯“‹v1—r)AWc²µZãzµö„ [ }ÓŽ›ø›Ìßðú¾ž_þõ_f”Q.½ûRÊDAD6›åþ÷ó²ÿô²´éöÛ¶sÿóîç×>þk|õ_å´c§±ù77“/æ) å }¬$I–~r‡‡I*Ìð¼$IBww7I’0<<<{Ë™–­X<óÌ3ù›?ùþô³ÊCÎCœ}öÙþÂa®ÛtO=t1Ňà·Îíæ[ÿŒ_Jø‡ËðŸÃwN{Š7üë Ø5qú“1º¢èwñý6àuµG{yíß+ÒÇÿ#¶¦ëڞ霹|Çl~òÉÕ~ºEDDDDD6”rÙÔ¯d³õ¤c†ä²Yþî‚ ¸ä³Ÿ…ßú­úì\vmÞšÑQáÑ=Êcg>ƽ÷Þˉ'( µxÎ8bù×c´“§Å—Vo#kœk@’ÔrdµªÆ 090yªJ%]3˜>áhÛõÙ¶©¶õ×¶m›6=Áððð¼*i–K>Ÿ'I²Ù,Žã¤ж³T*áº.Ùl×uñ<žÏ$X™º¾¤[ËÜdm6ÖóêÇW*™]{(›Ÿ@Ï3× ˜Û5&`kg‘ÌhRÂ`ÞùƒÆ¸3]ßH-×¾“´ÉÀ9Ö^ ‚úz§Õªy–J ËuÚö.æ·UááÄT ¾5 ÿƒžØôü_`Çýÿ˜|äyœÁ‹¶áÏþCÚŽ·Á }ö÷ŒÞƒ³ÛÇûÁÓ¼ö‡7ð¯ÞæôŒ£÷‡ï7ûý‡p±qóÎÚ<•ƒi‡Ð œdþÉU; ØYÛÁÅæ½²¤É=»­MÚÙ>øT*‚ H[—Æq ¯ƒW¾è•üô_Šïû”Ëå4>ær¹´âÐÆ{Ħk7ñžƒïáÂ_¿Qgr0^2åšöD»àwsjß_ ~Ñ GùÌo~†;nÄ1Ÿcë<ÏÃuÝÖ´±žm½o×etttJÛVi¡SY›Ã$‡dÍ»sŒ‡¾ý»&ùÊ».ØÅèð(ßxàRž¸ð?úQ?»øéOÏ£ý_žæŒG/à]ü&ÉW9“—ðsäºËÉÑå—F_@uÓaÛº•G|þ¯Ó£|ø-»üÄCøÀávdáÜÚßs^ÄNókc Ãú‚¾–=-ÖóêBgR)|Öׇ¶»$D‘ÿ˜œzBÓi§¥ÛÿÀÐ߸Ú/‘4*ÓÜa ¦^Áo«ù ¨-‘ˆˆˆˆÈEæëÛèhýk\Eü·½/^p—<ûÙÍKpU«¦Bá$°Ó…wVHv&ÜÕvÛÏÚνÜËõ—\[1ó‡yêk,V©W°ËÙ‰ùL//°˜Bd¾”x\E6ÁhOfp]s …úÔtù'{¾`oLâ9ŽC¡PH'¸óy׿喅¬·kù¾O†d³YÂ0$IŠÅ"ÃÃÃi•˜Ö¤O>Ìî7¿9Ý– ·rþ·Âÿø,DgâLŒm¯ÙxRÙ¡ëÎ^1ؘTe¡,Tµágó½ñsj× ú> N-—Eà<4Îà ߉àº*ü$ïd}±'î"àÃf:\yþKˆÎý<Á¹=¿×ögÞÆùí<¿ë º®ë¢­t>m¶ei­2rëCwÑ$<ûÛpû/ÞÎõŸ­ícù%Kr˜ÉÎx·Žmµ:Mü±Õ×¶1 CÂ0d``€$Ièììd``€îînJ¥RZ1m“i6ö ¦'+4&&S7˜lÕßL•ÞM÷{ð!f¯Öœîéª%3m ÄRíÔ­ÁÁ•ïyè8Ž’ŽË%¬àc’k—®öϦëÖOˆ°'W6,KØ”÷jüݲ»=Ï3¹°ÆÛårf¼àoƒø,øÚGùɶŸðÌ™ÏpÝuGøìg/æÄ‰\xágøç~yÓãìÞý0玿„'†7ѹõ£»‡yî7_Á‘ãGøÇ þ‘ŽgÎfó³žäûOmã»Ï|—'¾ÍØØŸc‚bÄitò6ÎfWSÞxÎùìÿ©Ë¶Ÿ¼)-Îþës²üç'¶rÉéÏàù(ïþ å“pî±Ë“køÎY÷ò\~éÆÀþq7/xÁ¹ '0o*׃ÿ åj­O~mýæÉ mïÜÙùw"¦ø™Ó©žh#þÈ6²g|¿ú"²æù÷>÷†ðZþ[žpÌM%Ì á—¾üþƒ|á¾/p×£wEIo’® èö¸\ýëï€ÿü\m?ì$"¤„›ÃÍlݱÞ tÂõÿëúÅsæÉÅI¢† ƒm[†!¥R‰0ÓŠCß÷§=I¡\.S©TÒ“Ç¡T*áyããÍ‹Cæóy\×Mפ]6ö,1‘FUêU¼YLÅs«&¿&Øm'e›o²…m6IX*™?¡`~>á?ÔsYW^9ή]ô÷ïছú¹õÖž¦‡ûµŽopç£Ïå;G/æåÛÿ€<ú lÛv7;vôsÏ=ïç¼ó¾ÇKvüOþþî>ܳ.yº'žõm¿“7žöî.œ>Á+Ï¿‡ÿöÐs8ó§gò,žÅ“Of;"ØÛ7žØd[«ÛË챕.¬OÜð»}Žâ†ç(žt»=¿öÙûåj¯GØp{{¼61›«½nv»vr&¤Þ‚êª4l;˜æw&=N8ËmìþMNÌÚ}±ëi©Mó? îóÌö£KøÿÙ»÷ø8îúÞÿ/ùn'–¼r.¾Dج’8‰œ Y%A“³Å†ËJP µK¼:ôÜ•ÝÒ_|h8´»E-LJžR­é1P(‘ö4%@ˆ‚hQsÑ„@¬$Ž£ÅŽr±sñØk;¾[¿?F3ÚÕ]Ú•vWz?=líÎÌ~¿3;}g>óý~ñ/«X þÁþ1Ø'û·sÌéPè„k^º™€N»>Bÿ¨]εz(ä\ŽÙ¶M0$ ÑÓÓÃ’_ù Êç´ñÜðâκ/óýlûþ6¦«® Ã0Øæß6üçf^Î w{,ó~–ÍÀµ†û™noɺ÷%S¦äÍÍÍ´¶¶’N§Ù°aMMMTUUºXC$“÷›Üÿ»#]e&]Noƒ¦™òzþ¸= Ý9ÁB¡†a87äÝž~ýI>ïn¤+…xœ€Ñ‚ß?üDµéŸþ”ï´·Órìxåºë¼aù÷tšG}Ô»?ðÄÍ7ãÿÄ'ðûýÄb1Vå+¬ˆÇŠýÍß°)ƒÌÉmÝL«ÏçtåÜÓ¨«Ë‰È™Ý#2ÿüYç?'_ξa6Ú—2+Lkp{X ô8|?8ñÿÉCXü(Æå{ Üp!ÆÍi|'V‚ïªD–?ûf±eY˜fœT2Åßïú{>sæ3$ÿ1I("¼)ìõâËz°à †X«gøF†KŒ%Îÿ»˜tr$‘L8C"',¯w¢ßï÷b”Ïçò,ÂápÖ¿ñxÜ»>ìÔÁM,ºÃ@"ý=ŽÃÑëu¤Þzš¯P2M[,Hà4Σ8çž{úß.‡ãöŒŒéî_ìOCò‹ºZ¾ õ¿ÖÓ«}¶¢Ç×æÐ¼>–.}–E‹^âT×oråÙyº¨²âpôÒÿä·þ¾Zç^s5ó ð§¯'ùx’¬?Àïû}öÿç¯ø§UÝü®ýIþ×Õÿ‹wÇ/=Nð²_sÝžëX|ò Vp†\¾Çø24?ȉE+ùÂEsùÎÊ—8yþy¿\Íò…m|·î»ÜT~9]¼Š×νƚûm>ô¦µ¬NÝËŠSoðþ?ã-¯W0ÿÄ[ùùÛ‡/ÞÅåû.,~}áå|ï¢sXìàº7]ÇÃþ‚Ö½ŸOìO‰…cœI|†k/>Í»½ÂÚ“¯óÆÜ«ùþ§?MíΫyqÅcÜôÇÏóöì¯'ÞónhoÇ4M: ƒ}ÞÂÚÖVÎ]XÎÙ˯'tÁBøNø Ë×WÊn{¾Î>øg| Ï^Ì•Üéÿ8í+ËrÚ/†Ÿ ÷m{ Ù 9m ‘Ú$Å’Ü ‡sßF+ŠkƒÌ„› ÊìYè.ãþ)·p:†þ w“LnâËM´¹I±8ÙÉÆHÆ2îó<™ÛÏWupâs4þmºQ ^Ï ;ïFáTÏêþÏ øÁ2 åhúûý`†Á¾|÷ƒ9˜ûÁ÷6°(ƒðG ñU`†ÔŸBêeà$pp¸?Ç÷Kg™P5DŸß“`/Cø7ÁúXiÿ>Hîé/øcÀÏ¡íCPßêìßÈû ¾(N€]þ'!pÜùœÐa0C°5{7uÄ!Øœ"Àú>˜™Ï[Å¡£¡½8tý!Ô~#{‘`¿‰8?£¢ƒ’ :ðÙ‘°s_Æá? sðÈÁ[ø‹q|ŠUQÄ‘I°íCGRÏa‡ƒ}Ê™Âïw¶á.ïš9 E,60"»Ë0 £ãR.¼pQ¡wIN DdZâ@œ ûx©@í]ùCˆ•Eyue;‡žæÃ7|‚ ý“s=ðG8mâþQF~ö¾Ÿ±ôß—ò®ß{m¡6oD¯¼LÑãrÛâƒ7Y$—«2s•TâÑ nÀhnnfÛ¶mÜ}÷Ý-—e 4Ýù_Á¹åó9­gæ!R!‘Hpù¾}üòèQ~øÌ3ÞP‚ï½ê*¾¸f oK§)w[‰ƒŸŽ/+øg£Ùï‡Ã<^Yɇþ6Búâ¿âÅ?ø¾±p!à )¸æ«_å=O<áÒŸÑ̶@F’Ï @ §ÿëý"ø3oF§n:{«Jü¹§WæÉmmP_ïüðÍj÷'Õ¥£c W¶«£Ã¹N2MçAL÷ÙÃL]]ÎçØ¶séÓØ˜ý\e(Ô_¶4ÒÀ»ÀJ’õ0‚}!°¶ÿÿg€«!õ"ØÇ!ðÁþ‡=ýÀ²þÝû 'é–µË g¿…SÉAÓ®þ)DÖ÷Ïß‚È-ÙÛpËH $M;nÝ GÂÊ•°r%Ë—ï㟖¾À…ž¡æÝðß—^ϳÏ>ËÊ•'X¹òÇŽÍç›ï›ÇÊ•'°Ž?€Å/¿L ?K—žÅ‡Íóo¿˜Pÿ²~†S÷ÞËÃO-æ­×œàiÛ&Yá•í+N_µŠÇÜ{í±97qnþq {¨ëRQ4±@¼â;ƒ’_£ ãžù ‚i Œ48Vd ãn Ä,7޹·¢Qç÷Ì‘"Ü2…2†ÃsG‰Jåe¸Øç6ÜÏ'¶Áð±/3Þ…BÎçÄ w—¹ÞHÛp?Ç0êï–Ý-Ÿ»^KËÐ8îî_÷µÁï»ÉÌ¥KÏrüøÂéù²LÅ™’89…À]ÜŸ„vªR Ǩÿ= =U?Äÿ휘ÓÍÅç¿ÉÚ÷ÌãŸÊou$ìüDSQB± ~Ž?í ‹aF~Ž"VÖ××7Þçm Î0 ïI€ÞÞ^ Ã`ÇŽlذaÄõš››©««£®®“€áþß`èð6îÄî°:~°¾ÖHq†¨  jkÁ·Z¾ÖwO8±—PÕAyÅ'immåß|»?½›7dK{šµ—¾‹ý sYþïË™wñ<ž½þYÞ»à½Co|Œ5,PæpBîAîP?öÛp‡"r¹OA»Ë¸Oz0h™Ì§ÅhN—<Ú²e »ví*t1&e²q «Þ6Ck¹ó¹ÃXYd_Ý®º˜–Ót.ô‚·œ"õâBB·$påQŒË÷ˆ 4ÜyW3çaÍ,¿›ÜÏœ›p<Üù] ÃÈÖÔMÞðÇ@€xl`>]þ~’þ ûÇ -4xcÉÏxÓñ³¬¼ägΜáÈoÿ6—ÿv/ÿï—¹ðw/dÉmd¹ý ÎWTôù8ò—é=0°äé§¹¾½¾7¿™‡~˜††6µ·³óÇ?&‹Åø—¿ú+¶~ö³üè±Çxߊ<ñÓŸ²ð}ïË:Ï/Ú¿€ònЈ³Ðvr ɹMpÇ®ì6ª;7Kf;²ÛÙ×n»´§=ë¶{ÝöEFÒ13× £¢¤RÙ7ÑÁ¹9ì&ÝTÜÄ^æ2™7š‡Kæù|Î èúzg]]˻ɰ̛öîôánò'“9ùT ìÞcðì³Î¶V-ÆWw5=ô2ÇŽã­oÏS_«W }bO¿p)]µßõK½äØ›ž}„ÊÇçÈé 8räåóñÈõ×SY[ëµen~â –9â•ãõŠ ½áï÷Å'OòÑ{îñ~?sæ O¯_ÏWÏó¦„Xñ½ïqËÁƒYõùÚå—³·¼ÜûýöçžãŠtÚû}oy9Þ·Ïk£¥R)z=äg`ÄVúÿàé³kÉž.³ƒìËM²G¾5:¨Fæç>ÖÝͶ“'³– ºAõ͇bå‰ÞïWV¹ñFï÷"ÞŸt<6>Ï.]Ê×.¿œ_ΛÇC=D)šl,ðÚBŸhr® ÜÃ<ø> zÀÉÆ‰ƒ¯yCë¹=’o#‚s3‡Fî—:þmÎ:©— uSÿP¹ÿöÙþ…nóiˆœ„Ä‹`¿b/:½xY„“`_Æ“NoZk1*À?¬…à;æÜÛ`1Ä–Bô°ç@x!˜G!ùBÆ>®„@9Ä÷õWÿ}¼7»:-WCò„Ó£6òVà$˜ý øæCÛµ|üAÛ-}§§ð‚þé‰O8Ã'+!ð"„W;uK{ ð Ä.èYg½PÆþbp=ðKß ‰“À»¼ŸÐ¿?–ÁegNóðÑ3<3ç/9uûÖó§8tºã7¿Îuûûøà¼ ¾÷ŽY}ßj®_r–OâØÉý¤/IsäÌ®~ý<‹/ZËÃï8ÅêûVsëÒ3üüÕç9Uù:G®J³î¿–qýxqà ¿¼˜C»—±váy>ûsV½~û={¸&u óÓ—ðý·¿DY[ºÅoðÆâïQõÒ^­|•ygç±ô¥¤Þdðâ% ¹nÏu¼¸âE®Þû3æŸíåWWÿŠëž¾Ž3óªø‡·c㱬}á<åGïâØÇHÏI³ê•“¼±¨ŽoäÞöàÛ¸àà\tên.:ÿSžŸÿ<¾ÓNù·µ×ñÊï¾ÂßþíßNå);eòvÏP¦…{¿$–eys»ÿŸŠrúý~oš÷ákkpv?Ï^¾öÙx¬ZµŠ_|qÊ?g*äåž¡+\bÃmý×ÈÀæF8‘‚7ùI}⃤ÞXA¢ëF^xá~çõïsó³OÐÍ7yåÿË_ýÆ¿°äÀˆÁß}€ås–sËæ[èêêòúW¢QŠU>î–LÇîînz{{³UUUÔÔÔ°{÷îQƒÇ3Ï<ÃêÕ«©{ôj¸Ã‚c&Ü|26ð ­NK?u¶’Ô™Jìεð&ƒÄ}`½±ß}Æ».âÝ‹örÃÜçY ýA7¿¾üœ={–¶Ÿ¶ñßþ>UÇàRàü‚ŽUßÎê«9Qq‚ÿùGÿ“µÿô#N]úϼvz Ëߑ敇_aÎù9´ÞßÊû·mç±»7ríªky|‡Åµ×^Ëæ;ßÇ=oÜÉ'xžçYsx î¹9öªWSñzõµõ¬Þ³šOÞüIʯ)粋/cÍW×89Ëà²k€oÇáò›.˜üÖå&û2‡„üwÔM4ž°6Sæz&C?gð2)†NrÊxÝè?>ÃM„ë^­÷_éŸþÇÓ,8¾ÀùÅ ; š9§‹Ë/#¹ì%£ÝyfÜq°ÝïÉàyk2—u—±½?Blj|inn.ÙäÁDäöïß?µáw’0Ï‚Êì @Ä °’¤Ì(ççå‘¿¦>æã–[NóÐCñ¿æ4óÀ÷  Â7.$w†5uo仉ÅP(ÄÇ?þq–.]Ê­·ÞŠeY¯—a<÷€×ôûý$ b±Á`ŽŽï_÷u·œ™Ät{PÆb1Z[[ùÙÏ~FMM7´©»L("xežIfË9‘©µµ•õë×SSSSè¢L¹¼´ þÇ‹ðãF¨ðÁÍ!ïÉC‡û7Û¼›øöAXü¿OràÀ>Z[ײvísü¡ ì=|òÜwøâóÿ—8ÐtÎÿm~^º-â’Ë/¦ëòÛÙð‘°ç±Çøšað•;¿Â;êÞÁ™»ÿ†ÜÏsk×rè—iŽ^y%‰ðwÕÕÿWžOõpÇó Ç~Â]÷ßO8fŽeáϘãÙ aêSní/¹ÛÅõ‹ßùéÿ˜Õá0«?ð¡;e†>`ÐÝÝÍîÝ»ihhÈ}c%d¶Ä¿\Û|΄ÿHÀ… ;£#» B9˜}NâÆ÷àepå§H><áwÓøÆiøKœ ¶c1Á꫱m'!˜2S$-ç<ó/~ßüc´üä ¯wÍý÷?ÊÃÿÔÇ Kœq—<û"‡7ndùòJN:Ááÿü/Â=sôèQ.XÀ¹sçH}"‘˼¢ÿÇà«kdUñkV†áT(ÄK8ðcxð{—rïêÕÞKvÜdð¸ Áxö3‚™ 4÷Y®ÁSVv00ªëÀ÷.¤ëÆ™3g'Nœàý'O²±·—ùóç³ðÌÎÍ›ÇÏöïgßCqæÌæÏŸOåÌ9z”ã pæÌ^¯¨`ß²eœ?žžžªªªxËâÅ,\¸ôܹœ¾à^›?ŸÕ+VPVVÆÃ?Ì\w¯îÙÃkkÖðø¯Muu5¯9ÂòåËY¹r%+W®äÅK.áÐÉ“\qÅìÝ»—57Ü@Cw7·ß~;Û·oçöÛoç‹?ú×]w/¼ð•••,¾ì2þôðaV®\ÉÞ½{YuË-|øÞ{illäž{îá¶Ûnøï>Ú2ô2M¸zÅ H¥Xÿ‡ˆÒÒÒB4uÚ{Äb1’ɤó€H*匮ï÷“J¥xGK ÁþeÝuèÿ×]gG Àk¯½Æ«¯¾ÊÕW_íH-ûG_Á>ñ,‚ù… ²Äà„7Bü‘{I]ém"´ó8ÌýM’Ü ‘U{ ~÷ŠÏx:>²—àCWÀCY,y€øK·ò[óeÞžy.ÜKjCæ‹ÀsÀ;๟ÿ'kç¾HÙ¾2Î>w†tå*.úm.»ð,‹çž§ò`/ËžNqnÁ9®›ßGßÜ>Ε—såÜwQvåã¬zu9µ‡Û–dÁ™[ñ,+O÷ñêõ·Ï‹Ì{p'åÞ‹ïãÚù¿æPÅ!Ÿ\ÌIÞÁEëÖÒð‡¸nÏuô•õи軜,;Iï’_Q}¬š_>÷|öƳÜxèFž{þ÷±£òô¯9uê§ŽŸ¢ül9ÿyé_±’{y ïã±áÏ~‘³gÎòÂë/°bÁ žÙw-~."E ƒ[¹08ûì矟¹ƒ$ß&L˜ø>øo|µ<ûœ÷÷q9ßîïíà lwo|ßùçanåË÷&̳À­ÜÇFð¶ð¿ž_yüi¶-ÞÆ÷ÊË ú;–½xˆçž;ÏE§/bÿ‚7ÿŽë.¼Žò×ÊÙëóñ»ûÿ{yß:Ç¢sU<¹è*¾zìYþ}üçѳ\sèWã8ûçOÏáÜœ ùÑþ ÊW¯áÀëXptkßø>}œ`YÏr)œ=È=có΋ÞÉ+¯¼BÙ²s,}u'ûNòڹט»ø ž^TNï¯öqåëW²oÑ>üKæc¿^Ρ«8ýÂAV­\ÅS'Ÿâⲋ }ZOJ®± â± øKŽe¼Ø€¿é¿N<9(±•0î3Å€ð §w~ÏùB¨KaoïÅzc©·H åF¬þ¦›ÿ÷àÙï?ÈéÞŒ±;æ\ÀÛΓnqâƒïã“þçyœ8ñóæÍã왳œ¸âN,ºˆ³O_Ïþ¥iV^q¿þù»³ŠRõNR? qþüyæû`Az1'Þè¾l!'®º‹ù{þ;óª¿Ìœ½Ùíèò‹~Éó}UÌ;x%gç>Ë3 üüyÖ2]ü 5ìàßeË9ÕŸÃçóýË\Î~>ÅUüYÛHó §˜Ïò… ;õ+V]}?§{>–µÌñ«ÿÃ+ëÝßyˆ%‡¯âèÉ7»>sçÎeù›Ÿçõc§9wä,]þê°ûíš÷<ÎËÿü~Öœ;Ç’K:Yн„Cé¬ãœý:ÿ,¯¿cýøýÌŸ7ŸÖÿ€_Þå«_YÀ­4½'*xîÙ ®]sš‹¯HñssuÖçlþô«üßÿãì§wÞüW-µ™tOt.àúÅ'ùØÖ£Þ2ßùç½|tëEYÛxçMÇ)[ztÎ'p%\Xõ?¹÷"Μ9˺ ÏrèÌ\~÷OóÍ–k(++#ô^HYû°^x 뺅Ç9ð[ƒož–†¼´ ,0ßÙŠïX ?yôE¼ûÆö“-Þ”jÉOÁoþæÓ,\ä™g,n ‡ÁqÃüßç•W^á^î%qo‚ˆ¡þêéêꢥ¥¿ßOGGÇøÊ2A3áZp&ÜÛš­÷"+™Äã‘þ§]?TQQAww÷¨ë¦ÓiŽßq†úž¸aÁÓ¬Y}€¹g–ñüá¿ã‘òÛ8vì+þ÷Ïè²§ŽÜÀsŽ8ñoìyöë,ZúvÊøOþö®bØÎ!ÀâÅ‹ùÚWËydéWXYµ’3/ÁzÏ*î¾¾ùÍoòñœC~ÆŸUV²¾c=ƒ‰lˆðõß|©ÿ‰†Ý¤RßÃ0 Ì…&Uá*~‘ø ÚÀ™õg¨4*ñY>. \J]^}>ŧ²êWŽó"Пݚó$ñçßþyvµïxJ†>F;œŽ .oŒ±\>'6Âÿ¯×Ÿ4½Ç¾‡k®¹f 8ùxüØý¿ûô* å.Iêc éÃi0ZÛ õo;Þÿo Ù/Ã@òÒdäDjP–Q¯8Ùwy¯—‘xm¢ þbüŸó?*Í\r‰ÇŽ£ñ]ítÍy·]qŒs׫øÕWïç™g®¥¯¯‹K.¹èaùò}œ;÷(\ð4ø|Œ'^âž{àž{àÆodÁêu¬[·Žx€;wòæH„Ûo¿oûÛ|üã'™LzOÉg&ÛÚÚƒ:tȶÔí Î%Ã0²z†Û9Ýý×}*j¤¹]½½½ÞXönrqð0©3-éŒëû0Ódë™.×6ÁâØOmW—ÜÇÊìãÔ©õ\ñ…oó)Ç+Yµê)zzÞ̱cëX´¨›cÇÀ ®ëׯæìÙ³¸øVŽ^úuŽ^~9Ÿ<ÓÀŠ+-ZäÍuZ_ï\XD£Q~»¡Á를°n¡syÓ&›6aË€ý~/ièžçÿôÈ#ÜðÎwäÔy6žGŽ¡···ÐŘv³åXçÚ&øÑЧxâêëyöØ:ŽÎËüK.aù7¿É÷ž«ãÈ‘9üÖ?µótÀ@g8n:ÐÁ<¾ÎÞc7Pñês<óÔ}¼¾ä7X0GcÝÅ¿dó_>Â¥—^Çùó'‰Çÿ=sÊC8áüÔÖlÓ4÷»¼öšï*ÿú·Y¼x1úQÖö'äþæoþ†+Vðð•Wòï?sS)–ûýI¥Xxâ7Þx#‡âío;ÝÝݬY³†E‹ û÷Ø}ØkµßOjÉïA5ˆïîCd™•¹½ÜÝ×Ü¡ìÃá°÷»û°›;Ÿö¯~õ+ž}öY>ô¡áóù¼e:::¼y¶€· Û¶yî¹ç(Eùˆß^~œUËxòõsü|«~}Š#ç¿Ï“{¯â7ÞàãïÞÏûo˜»hO¼€ ÷yÚrŽß 7ÜÏ’óWðÆñ›({£ŒóçÏ3wî\~ðoÈk¯}‚“O<Å>ó GÏ×±pÑ‹Þù÷í.“—æüOÊ.­æø /;w‚úÊÇ9th`²Ïúï ”3~Ø™wÔ8ãüXÇ!þ; <e9ïÿÒ]é$|ïµËßùóçs˵×R¾d/ozÓ›xþùçY}éj>òìA®XÁ‰§Oð“Å‹ùôë/qíéÓÌ™3‡³ûϲpáB>ò³çýï?ß?çòË/çïÿ‚_\~9/½ô\p÷¿ÑÉC'³bÅ >ÀûkjXý‹{¹úê«yúé}œ¼z1ñôßpÓ ´=ÒÆŠ+xçѽ¼‰³”¯YÃë¯çÊ߸‚ßýa⟌óáȇ‰ÇãüAäIn¿ývxàV¯^Í#¯îáÅ…û¸âŠ+hÛÛ†/äŽøÜ~ûí|ík_ãöÛoç“_ûÑxœ| /¼§v/ä‚ nfí[Þ‘#GØÔÔä%ä½ÄÔÈJâ§R)B¼ŸßÇ?þã?bìÚ5$ño4J[¬x<Ža|%å<à宸À4ùPäCÄãñþ ~A8æÞþ¶a*•âúUS©oøÿ€4W‡½‡MG£|4ü~ïaûSŸðâ†ÿÞfš\¾‚Ÿ&~ÊÇb1¢Ñgxî¹ç¸üò·±Ø0x5•âƒþpÆ>ÃÊÀÇ0Í•Þh:¡PˆŸ½÷½ÜÖw[¡OëIÉ5¤ö-ÌûnÏο‘žù×rù?þ_î}ù=ã8«îzв_,`ÿñ7ÐGe”qæãÿ'ö|‰Sç–pÓ|ŽÇžù›¬í¾û™!µ°‹_Ûõ”›bp'wóƒ¬e.|×mã?Xöx «¹š 9ë½ÿÇÙßtóh øõo°ÿåÍ8O:@YÙ<ªžÞËîů‘>¾† N?ÃûO>„õÆ[œÄ乳̛;ŽŸþ'}óÞÃÉ“'©Zx”U§óÒ¹¥ÎTN}}\xÁ1N=ÆÑåóxÕ~•?¿þÍ$Ÿ>Æü 8wî,ôÁÕe‡¸à⼸´’KN-àO®©âG¦ÅâÅ‹9qâKç-åÒË.eÉeK8öÜ1®^OeëÏé={ž²ùpºï çË/¦l~•«+y<õ8_üT˜ÿwç,Yzgže΂2Ö®»˜½•>N½zŠKÎ\BýÚ ù=?gÎÒJN?Å¢E‹øõ¢W¸ü-‹I½œâ7o\Í¢ûĹ9G(+sâ0+x}Þ\|Ë~ùË_²kÛoñJÙ¢eœ8‹Ïañü%̽¢Žã½'I/‘·Í{‘žÓÿÅ /àSo°tÉR~µÿW¬®ú=öìßÃâåûyÓ3‡8vÞÏùyç8ö<¿^TÉ+/?Æõ7lä×ÏìeëÞħ¾ñ( /XÈúÓo°pþBæ>ÏÒåÖ¾ù,§ç½Èé^?³‚% —pìôQ*/ã»qíš¿æùÞç™W‘fÝÎKgý\7ïœ.ãÜÙ‹ùÖO¿Çº·ý-Ï?ö<+Wž¥æôXP±€cG²hÑ"Ž;Á'~“U]Ä‘£¨yõ^jN¯rñQ¸bɾÛÑÅÕ«Ïyõ4?ÿ#®=¿€óçϳbÉy:ž|²Ð§ô¤ä£MðwUß§ã…JL€þ¤ïAv¿óæÎË‘#¿ ·w¯½¶†sçî’8fùòå455±ÿ~âñ8¡PÓ4‰Åb„B! Ãðþ¶Oõ¨b3áZp&ÜÛš­÷"+™¡V;;;Ù²e {öìÉz}Ë–-£ùçþçü××ÍQÛ ›¸Íîùó?JY™“EZ¸ð{ýQ^þ(§OŸ¦¢¢‚×_7¿ùÍØ¶Íe—]ÆË/¿Ìõ×_Ï믿ÎòåË9}ú4§NbéÒ¥œ>}š¥K—òÚk¯qÑEyÿ.X°  ûìàÁƒ\zé¥ùìB9|ø0‹-bÑ¢Òž}¢<Èú%ëyué«\óÒ5¼±ð ö-ßÇ5/]“µ:ú:à«~µÐÅž°\âÀ[ßúVÎ<öVž:¿’“(++cÁ‚{8sf‹ýgÎ<ÌÊ•Ý:Ôã\08À›Þô&Nœ8Ï磼¼œÓ§Osá…òòË/så•Wòì³ÏxöÙgY»v-¯½öš,XÀÒ¥K)¤Ù|N(þ¬»»›óçÏó‘|„Ï|æ3….ú„åÚ&øÎwÚ9}àê'qþüù”•ý%bþü^.ü‹¿Ì¹sçX»v-{÷®Ž'Ÿ|Ò;߯¼òJ^~ùe.¼ðBöÏ¡ìþ½/ôy?œÙxNœÄñãORQñéôE,]ú,sæÌñÎq÷oü‘#G¼öºuëØ·oŸ×kîÒK/åĉ,^¼ÀkK8p€·½ím^ûÁ²,¯=±råJŽ;Æ…^è£ÁmŽË.»Œ^xaÔuV®\ÉË/¿ÌÚµkÙ³g×^{-/½ô’w}’ÙNɬÏÑ£G½eV­Z5®uÆïJµ=RªåžHüÛ¿?ÇŽcíÚµ^oùR’K,èííåƒü ¿øÅÿýG0wî\æÎ}‚¾¾ÊÊ‚œ9s†å˿Ƒ#—S^^N:fÉ’%œ<ù‹Ÿdþüù£Æ†7¿ùÍüú׿fݺuìÙ³‡ŠŠ NŸ>ÍÅ;½ÊÜ8áÞwØ»w/@€½{÷zç{ee¥·Ü’%K8wîgÏžåĉY×#'n›fåÊ•=zt\±að¿™ëœ>}Àû¿{odÕªUNoí… yñÅY½zuÁî‘LV©¶£&RîÙ|}ð÷ÿ÷Äb]¼öZsç¦óçQæÍûgÏžeÁ‚9s¦ ðsÁÏpîÜk\pÁ9ò**Þ…mÛ¬\ù¬fÍš5ضMeåãœèúzñâÅœ9s†+Vð /pÙe—ñúë¯sõÕW¹¶8vÌévéþåÊ•Þ2™ÿ®X±‚ÇãóùƽÎd>'ßë,\¸^xë®»nÔu,XÀ‚ ²>çÚk¯õÚ6ÃÅ<÷s\§OŸfùòå¼þúë¬]»–}ûöy1ÉUn˺uðÒK/qýõ×óÌ3ϰ~ýzïûº|¹Óõ÷JõïU¦Rmg*õ{û÷ï'NçÜ&(™¹ø‡øø‡ÌWܧ Üù>nþ¬ÐÅ™_ä‹….BÁ<üðÃüš9ŒÆ§Æ»))Qÿðÿà´ †è,tÑDdœ`ùt¡‹&"Ó¤ªªŠÇ½á‡3{ ¼“ìûŸ-tQEd }æ3Ÿaøûª™×ºg(2ÓýøÇ?ÎøíöBG¤äÍ)t&j¸.Ã¥<毈Lœâ€ˆ€bˆ(ˆˆC±@D@±@DDŠEÉ$Ýñ™wïÞõzgggÉ %"“£8 " X "Š"âP,P,Å‘bS2‰G€††Z[[I§Óìܹ“òòr6nÜX袉È4QP,Åq(ˆ(ˆˆâ€H1)ëëëë+t!Æ+N³yófÒé4åååôööÒÔÔDCCC¡‹&"ÓDq@D@±@DDÄ¡X " X "Š"Ť¤®ÎNg‚çõë×S^^^èâˆH(ˆ(ˆˆâ€ˆ8 D DDq@¤”dâQDDDDDDDDDDDDDŠKIÍñ("""""""""""""ÅI‰GÉ™"""""""""""""’3%EDDDDDDDDDDDD$gJ<ŠˆˆˆˆˆˆˆˆˆˆˆˆHÎftâ±¹¹™›nº‰uëÖ±mÛ6z{{ ]¤œ´··³eË–!?ÝÝÝ®w)ì›M›6ÑÙÙ9ì{ù¨c±îƒ‘ê=žã?SŽ}¾Í´:ç+”Ê~É%”ò91\½gÛß|›Iužß…‘bA¾êXŒûAm‚™'N³mÛ6Ö­[ǺuëØ´iÓóŠ·­ÛÞÞŽa¬[·Ã0hoo/úr§Ói¶oßžµÍ©Š•ù(ûHçýàz ·ÿóµ¦^¾bA!ŽçXq Ë=ž8¯rå«Ü¹Ä‚bŠi2ºñÄ‚b=žÓÑ&Èw¹K­MÃÇ‚|µ ƳŒâ@áMgÜŸ®úÜtÓMC¾×¥P‡éjÍ}3Ô—¾ô¥¾ÚÚÚ¾»îº«ï¡‡ê»í¶Ûún»í¶B+ç:½ûÝïîûÒ—¾”õóüóÏO¨Þ¥°o‰Dß•W^Ù÷ÐC »r­c±îƒ±ê=ÚñŸ)Ç>ßfbó Je¿ä Jùœ©Þ³éï@¾Í´:϶ïÂhçD>êXŒûAm‚™ÉÝÏ=ôPßC=Ô÷éOº¯¶¶¶ïÈ‘#Þ2ÅÚÖ½ï¾ûú®¼òʾD"Ñ÷ÐCõÝqÇ}W^ye^¿wSQnw÷ÝwŸ·Ïßýîwçuç«ì£÷›7oî«­­õêñ¥/}©ïÊ+¯ì»ï¾ûòº¦G>bA!ŽçXq XË=VÈW¹òUî\bA1Å4ÛX± Xçt´ ¦¢Ü¥Ô&èë9ä£M0žeŠÃtÅýé¬Ïàïu)ÔaºÚ@3ÉŒM<º7c\Ï?ÿü \jî¸ã޾;î¸#çzó¾¹ë®»ú®¼òJïg¸†v>êXlû`<õëø—ú±Ÿ*3±Îùˆž_ò Jñœ«Þ³áïÀT™iuž-ß…±Î‰|Õ±˜öƒÚ3×îÝ»û®¼òʾݻw{¯9rdJ¾³Sq|o»í¶¬möõõõ}úÓŸî»ë®»Š¶Ü=ôÐGŽñ.øóUî\Ë>Öy?Ü÷Ä=&Ÿþô§óº¦^¾bA!ŽçXq Ë=ž8¯råZî|Ä‚bˆi2>ã‰Åz<§£Mïr—J› ¯oôX¯6Áx–Q(¼éŒûÓ!‘HôÝvÛmC¾×¥P‡éjÍ$3r¨Õîînz{{©««ó^«ªª¢¦¦†Ý»wºx“ÖÛÛKyyyNõ.ö}SWWÇ®]»Øµk×”Õ±÷ÁXõ†ÑÿL8öSa¦Ö9×XP û%×XPªçÄXõž ¦ÂL¬ólù.ŒvN䫎ŶÔ&˜¹ÊËËÙºu+555#.S¬mÝÞÞ^º»»³¶ °cÇжÜîNUUUYÇaýúõ^Š!ŽŒçï]]ÝïÎúõëI§ÓyÛ¿Š Ó#± Çs¬8P¬å+Œ÷3§#†å Š%¦ÉøŒ ŠõxNG›`*Ê]*m=ä£M0žeŠÃtÅýéÐÝÝM"‘à _øÂ׋½ÓÕšiæºSáÈ‘#C¾ ÃŽã_*vïÞÍ‘#GX·nàüljjò¾àã©w±ï›ªªª¬FÀ`ù¨£ûz1íƒ±ê £ÿ™pì§ÂL­s®± ÏÁrã©c1~?ƪ÷lø;0fbgËwa´s"_u,¶ý 6ÁÌUUUESSà\˜9r„ÖÖVjjj¼cQ¬m]÷æ|UUÛ·o§··—ªª*¨©©)Úr¯_¿Þ+æyåÖ'_í…\Ï©±Îûššš!7Óé4÷Ýw_^ÛŠ Ó#± Çs¬8P¬å+Œ÷3§#†å fjÛh¦+¸7¢‹íxNG›`*Ê]*mwߎ òÑ&Ï2¥pßh6˜®¸?ÕÒé4wÜqápxHµê0]m ™fFöxœ©Òé4UUU˜¦‰iš444°}ûöa'—™GÇ_\ú.Ì^:öâÒwavÓñ/}ÍÍÍlÙ²…ööv6nÜ8jæb²iÓ&ÊËË©©©¡··—Í›7õ…r]]åååÞ ‚ÞÞ^ïÿ¥¬½½M›6QUUE8.tq$¥ ЇbÁÌ¡X0õfj,P˜]Jõx' ***غuk¡‹’“R‹{…6#{<ÎT{öìÉú½©©‰ÎÎNZ[[‡dËeæíø»O5Éì X0{騋Kß…ÙMm‚Òç>¹ÜÙÙÉ–-[(///‰c‡³n†Akk+6l(tцU^^Î׿þu¶mÛ†alذaÔ!.‹™{“´³³“­[·‡Kâæ´Œ¬cÁHqàÎ;ï,tц5Óâ(ÌDÃÅ‚±FÀ(4µ Kq`v)åãí^§Þ}÷Ý….JÎJ­ Th3ºÇãpçRýƒ2’ºº:o ï‰Ô»Ô÷M>êXêû†ÿÙpì'c6Ôy2±`&ì—|Ô±Ô÷Ãlý;03½Î³õ»¯:–ú~P› ø¹sƒdª««£®®nHoÕbmëNˆlذ!«§@1–»¦¦Ó4Ù³g{öìaÇŽTTTLI{a*Ï©îînï)kÓ4ijjö†“ÚFÅ/Ÿ± Çs¬8PŒåOÈW¹¦úüO,(…˜&ãÅz<§£Mïr«MP|1MÆ6q*tvvRQQÁöíÛÙ²e [¶lzz—B\ÓÕš)fdâÑ}ÒðÄœEÿÄÐHÚÛÛ³NFWoo¯lÆSïRß7ù¨c)Žÿl8ö“1ëœX0öK>êXjûA&o¦ÕYßòZÇRÛj”®ööv6oÞ<ê2ÅÚÖuçE¼ÍÁó"[¹Óé4ÍÍÍY7Òé4¬_¿¾¤âȶmÛØ¸q#;vìv›³±mTªò q<ÇŠÅZî±âÀx?³X®±F‹¥ÓdìXP¬Çs:ÚSQnµ Š3¦Éئ#îO¥††î¼óN¶nÝêýlܸ‘­[·–D¦« 4ÓÌÈÄ#8_êÖÖVïÉï;wR^^ÎÆ ]´I©©©¡³³“ææfïµÎÎNoü÷‰Ô»Ô÷M>êXjû`<Ç6ûɘiuÎW,˜ û%u,¥ý ¿¹™IuÖwa@¾êXJûAm‚ÒµaÃÒé4;wîô^ëì줳³3kˆäblëºIíææfo›î÷ÎR­XËÝÞÞžµÏ›››)//Ïk¹§¢ì™:;;éííõzÁdþd>5=ÛÚF¥*_±`ºçxâ@±–{¬8¯rMõù3žXP 1Mã‰Åx<§«M0åV› ¸bšŒm:ãþTq“n™?à\׿;ÖM•élÍ$e}}}}….ÄTH§ÓlÞ¼™t:Myy9½½½455ý| £immõn2UTTÐÛÛËÖ­[ijjšP½Ke߬[·Ž]»v ™«*u,æ}0R½Ç:þ3éØçÓL¬s>bA)í—ÉÆ‚R?'†«÷lû;O3­Î³ñ»0Ü9‘¯:ë~P›`æimmeûöí”——Oé¹;Ç···—mÛ¶ÑÝÝMMM ÝÝÝyÿÞME¹;;;Ù¶m9r„ŠŠ vìØá iTlqd¸ó¾¹¹9ëFi¦ºº:on°™Þ6šIò q<ÇŠÅZî±â@¾Ê•ÏrO6[L“Ñ ŠõxNG›`*Ê]jm òÕ&Ï2Š…7q: þ^—B¦« 4“ÌØÄ£Ë}ýúõ%3éêhÒé´×%·ªªjÄ®¸ã©w©ï›|Ô±ÔöÁxŽÿl8ö“1ÓꜯX0öK>êXJûAr3“ê¬ïBþëXJûAm‚ÒÕÛÛë Ë3ÕçîT_w›Sù½Ëw¹3Ï—Á‰ü|–{*Ê>³­mTªò q<ÇŠÅXîñÄ|•«Ο™ÓfºñÄ‚b=žÓÑ&Èw¹Õ&˜ø2ÅP[©|'K½ÓÕš f|âQDDDDDDDDDDDDD¦ÞŒãQDDDDDDDDDDDDD¦"""""""""""""’3%EDDDDDDDDDDDD$gJ<ŠˆˆˆˆˆˆˆˆˆˆˆˆHΔx‘œ)ñ("""""""""""""9SâQDDDDDDDDDDDDDr¦Ä£ˆˆˆˆˆˆˆˆˆˆˆˆˆäL‰GÉ™"""""""""""""’3%EDDDDDDDDDDDD$gJ<ŠˆˆˆˆˆˆˆˆˆˆˆˆHΔx‘œÍšÄ£mÛ˜¦YèbÈlÛÆ²¬¼noªŽ·išØ¶]Ï.æýR f{ýg:˲H¥RÞïS}¼G‹Åþ]+öò©¾’‹‰ï‘–SÆ»-µŠ×l¨ãl5Üù:‘ã=ÚrùŽÅþ=,öò©~3[¡ï ä³Màn¯cA1—Mužr‰ ¹¶&J×¥k¶×¶Ñ=Ñå­|}³DGGGßL¯nKKK_OOO¡‹1!‡ê …B}@ÐúºººrÞîTo ¯£££ Ÿ]Ìû¥Ì–ú—b,ÈEWWWŸßï÷âˆa}‡šòã=Z,(öïZ±—OõœÙvîd"Ç»§§gȲ===}@À‹)¡PhÜŸ­6Bq› uœmq`¤6@_ßø÷pqÀ}}*bA±‹½|ªßø”Z,(†ûùnôõ•n,(沩ΓWjq¡¯/·Ø6Âdèz tÍ–ú—b,˜ ºg8²|•oÖôxœ ’É䤞Â+¤h4J*•âСCôõõá÷û‰Çã….–HI+ÅX‹úúzB¡}}}:tpb‹Èl3ÛÎý\¤R)’É$õõõCÞkllÄï÷{1Ų,Å)³-äÒ-€b”¶R‹…¼/ 6Ì¥ ·Ø û"Ã+ÅX ¥iF'‰ÑhtØ?Jî{‰D‚T*E"‘Èzß4M¢Ñ(Ñh4«;4Ŷmâñ8Ñh”d29êgMtù±¸$3Ëïþî6˜ÇÛÖÝV<÷ÖüÚpËŒµÍñÖ×¶m‰---ø|>b±~¿ÔºÞ1³mÛ;N£•Ï]Îba"ëŽÇHÇ3s_ÄãñQ‡[îØ¸LÓòu?spùdzn>ë^ìÆ:×F‹#Å(l,íÜÈG,OlÏ6ÇSßñœ£Õ×݆aø|>À°¨Ì80ÞÏžˆÑŽåTÅ‚‘âÀxÖÍÜ'31èÜÿöF:÷§² ˹ŸK ó>Üm›¦I$œ˜‡½ºL†Ú…¥ëñm«P×cÏùjÀÐX0Rp·›ÏX 6BaåÒ&p÷Ïl‹Óy=0Ö}Ñê k¨M0±X0“âÀpÔFß¶Jñž!L¾ {†3ÿÜn?©0ö¶Jñža.mÝ3Ì=ÌØÄcmm­·MÓÌzz-ó »O¶e6ãñ¸·¼mÛÔÖÖz;Þ}϶mlÛ¦¾¾ž`0è})Ý/Éàmwù±Äãq½?–îÁŸ w[™O: ~m¸eÆÚæxëë¾°, Ó4ñù|Äb±1ëêžüÕÕÕÞgƒÁa÷…ûžmÛ^Cc¼ëæò]³m›êêjïÄL&“ƒÁq›L¦if}GƒÁ`Ö2õõõYßÑÑÖòV÷b7Z€ÑcÁhq óýBÄ‚|ÆÌívÞOU,Ïù8V}}>_V/•Jeݨpafp—ËW,í»6U±`´80Öº®™ tîÏXçþT¶r9÷si¸Âá0^›Ãå~V沣ݤ‹Ú…¥ëño«P×cÏùh¸Çpp,)¸Ûüĵ +—6»¯fc,˜Îë±î ŒU×ñ¶ Ô&˜x,˜)q`8j#Œ[¥xÏ&ßFÐ=Ù}îgRabÛ*Å{†¹´tÏ0± ÐcÆN…–––>ŸÏ—5^±;&¸;næ{~¿¿Ï0Œ¾¾¾qý3Ç w·××çŒÏÛÒÒâ½úÂá°÷{$ñ¶5™åÇôE"‘¬²¹ë†1ê8âcmk¸×†[f¬mŽ·¾mmmÞ8ë~¿¿Ïï÷÷ù|>oßVWw¬áX,–õ>5·Û¡C‡†”a¬uÇSGw?ö]<ò¡C‡ú Ã×8ÚƒOÍÁß“ÁÛ‰D"Þ|£­;ZÝgÚøÞ£›¾¾¾QcÁXqÀÝÏ…Š£}}¹Ç‚ñĆñls<õÏù8V};::ú|>ŸCü~ÿ˜qÀ]/±`¬ïÚTÅ‚ÑâÀXëÎäX s?çþT¶r9÷si 6øüt·3Ü2j#”]Ln[ýVÈX0Ù6@æ¶ÇŠÃÍa’¯X 6BaåÒ&È|6Æ‚é¼ë¾ÀXuí;ûÿñk¸å+ªM0Úú3) Gm„Émk¸×Šõža_ßäÛºg8sÏýLj#”F!×{†¹´tÏ0÷X0#{<ºÝé3Ÿd ‡Ã€“5ü^(òþoš&~¿Û¶1M3ëw7ëž¹®Ïçóºüd¢ËÅ*`ð¶sÝÖH¯ ·L>ê›ùôROO===„ÃᬬþXuu‡=cœùD“û´Dæ1ïºã1ÚwÍ}­±±Ñ{2«££#çcxÛqŸF0MsÜݰGªûLß{´c£Ç‚ñÄ(l,Èg¼½á~éµ|Õw¬óq¤úºÝþ ॥ņ%ó)œÑâÀx>{,c}צ*äFª{©Çû“ßÞx~ËDë:Ùs<ëŽuîg´sh¢ç—Ú…¥ëÉmk¤×  ri@acÚ…•K› ¦ëz`<÷ÆS×á¾³Ï>û, 6Álo ¦6Âä¶5ÒkÅxÏ0mÝ3Ì.ïL8÷3©0ùm ÷ûH¯å«¾¹Ü7iýñ¶tÏ0»Ì‰órªA‘©û<ŒÝ@L¥RÞ¸º™&zòÈØ à g i‰DÆ=ôp©@ €a466ÒÓÓ3¡uÇc´ïšßï§££ÃëŽoÛ6áp˜–––œ÷ÛÝß \¹þ1Êuýb4Ú±Ñcâ@á÷;鎷ÞÖÖæ½æ÷û©­­åïx0±80‘Ïvõ]›ªXï80™º#û¥-—ï`.m€ÌuF2ц¿Ú…¥ëÒ6žïÝhm€Ì‹äBƵ +—6»¾bÁÔë¾Àd÷wæwVm‚ÙÝ&Lm„ÒË=éh#èžáÌ¢6BiËçwZ÷ '·ßÆcF&ý~ÿ̳0|>ߨÁ#x™åÌu-˵á)7Ú—u¼_dÛ¶½eÝ1‡3µ´´`Û6Éd’h4šÕ`kÝñí»–J¥ðù|ÞÓU–e  YO6LT2™$‘HÐÓÓ“5©öDž¶ÈGÝ‹ÝhÇFŠÓo²ßÉÌõ\îyñòË/£Ç\>;óóFû®ME,ÈGÈGÝ‹‘ÎýÒ’Ëw0—6ÀHÜó)óâ`¬ …Ѷ¥6Báèz ´Læ{7Z óIÜBƵ +—6(L—|܀ѿ³jÌî6Á`j#”†\bC>Úºg8óÎýLj#”–\¿“¹´tÏpòuŸ‘C­†B¡¬ 13Ÿ@…BÞ¤Äî{™k†1ä5w’ÒRPJ ~¿?ëéh4Šßïw<™¬Ïçòt‰;ùt<Ïj`ŒgݱŒö]Ë|R˜ðÓ™ßÑÌÉ]Ý“Þ n·þñ¬;\ÝÝ}>ÓžÊíØ¸ï J=¸õ)%“=ÇÌõo¼ñFﵑâ@.ŸY†Ñ¾kS ÆFZw¤ºÏ”X svœûã]w´s8î9ùH&“šÍ¥6Baéz ´L&ŒÖ(–X 6BaåÒ&Å‚é’ûî:®‰^ g6´ F[ð>-Õ80µJC.±!mÝ3ÌÞç3áÜϤ6BéÄÈý|Ì¥ {†ÿŸh,˜‘=‘H„úúz©TŠp8ŒeYøý~ZZZƒ†á³›ùtS,#zÁ#•Je=ÁP¬ÜñÊÝ.¹¥ ­­`0èíkÛ¶'´¯S©ÕÕÕÞº#uC…B„B!½aÆ»îhFû®…Ãa’É$ÕÕÕï©—ñ\¨„Ãao›¶m{ðܺ$ ª««ñûýÞwØ}ša´uÝ2[–•U÷Rø~ç󨣯‚RŽPš±`²çc ðŽ£ûw¿ÓƒR™q óXæ Æú®ME,O˜­±@çþì8÷'²îHçþHb±Á`ЛÁçóe É4^j#–®J'ÀäbÁhm€á"¨PX¹´ @±`:åz_ÆGÔ&,˜)q`¢ÇCq¡¸L66äÒFÐ=Ù{î÷Ø€ÚÅ&×ó1—6‚îN>”õõõõMî¿T*åuWuŸ†q»=»;Ýï÷“H$H¥RYcgNëvŸ.v™uËÇdÄÓ]nÿXئi éëëó²óã=N¹¬;’á¾k™Ÿ ûÞh,˶íç಻»]¸G[w¸õgª‘ŽÍxbA)ÆÁu+öX¯óÑ=ÎY?ß±`´8à~ä7ŒÆZw¤mÌ:÷gî¹?Ç›LÛd$j#–®Š[>ÎçÉ´Æ+_±@m„ÂÊ¥M¹\)í‹R‹™e†‰oSÝ.˜Ém‚ɬ?“¨Pr9‹á>Af9ŠåÜŸMm€±¨Pܱ ×ó±˜î;ÌÆëxŽ›¥îêêò²ÌÁ`H$RÐ,f ÉDp±o/W™'>׎zÛ¾œ­fC,˜ŠïZ¾·™Ë¹œ«‘>[q`fÓ¹?±mMÕ6§êïøTRl˜9fC(…íAaÛ“¡80³Ì†XP m‚\"Ž(Ì\³!.”Âö I÷ fG,(…6B®ã§â¾ƒâÀøÍÈ¡VG“ÙUÚ*Ãí^ZH#µ›i"OöûöŠÕtÔs¶ìËb7bÁT|×fÃ÷Wq`fÓ¹?±mMå6KbÃÌ1â@)l¯)Ì,³!¨M05 f®ÙJa{ÅJçþì1bÚ“£80~³®Ç£ˆˆˆˆˆˆˆˆˆˆˆˆˆäßœB@DDDDDDDDDDDDDJŸ"""""""""""""’3%EDDDDDDDDDDDD$gJ<ŠˆˆˆˆˆˆˆˆˆˆˆˆHΔx‘œ)ñ("""""""""""""9SâQDDDDDDDDDDDDDr6¯Ð˜?øÁèêêâ /,tQ¦Õk¯½ÆE]TèbL«£G²páB,XPè¢L«‰ë¹sçògög….ö´ûÜç>Geee¡‹1­tNÌ=Ö§N" róÍ7ºèÓJm‚ÙãôéÓœ:uŠ¥K—º(Ój¢ÇúèÑ£|æ3Ÿ¡¼¼¼ÐEŸVÿöoÿÆK/½TèbLX©žË¥Ú)ÕrO&þ­ZµŠßÿýß/tѧU:æïÿþïKòïD©Æ•»¸Ë=[¯}ôQ:::X¸pa¡‹2!³éoT1(ÕrƒîŽ×—¿üeÎ;Wèbä¤Tÿ^e*ÕØ–©”ã…+m‚Y‘xܵk×\s uuu….Ê´jnnæø@¡‹1­’É$555\sÍ5….Ê´šè±þò—¿<+÷ß?_ùÊW ]Œi¥sbö˜è±~ê©§0MsÖÝXP›`öxê©§èîîæ=ïyO¡‹2­&z¬“É$»wïžuçÄ÷¿ÿ}>õ©OºVªçr©¶GJµÜ“‰_ùÊWf]âq÷îݤÓé’ü;Qª±@å.îrÏÖëÓ4¹ôÒKK.ÖϦ¿QÅ TË ºg8^%_ïRý{•©Tc[¦RŽ™uȵMP”‰Çt:Í»ßýnvìØ1ä&Hss3­­­¤Ói6lØ@SSUUU£noîܹ¬Y³fÖÝP©¨¨˜uuîì윕7”'z¬wîÜYè")ßqœX0Û¾:'fÉëǺØcR› ?fã9Îw|¶Õ{¢Çº³³³ÐE—‘bÁdÛ‹-*ÉïF©žË¥Ú)ÕrÃÄãßl½>X½zuIßR*wñ—{6^,X° $cýlúU,JµÜºg8¾6Á…^X’Ç7S©þ½ÊTʱ-S©Æ‹ÁuÈEQÎñ¸mÛ6Òéô×ÝÀÑÔÔÄ®]»èííeÛ¶mcnïæ›o.é,ùdíÚµ«ÐE˜vMMM%ROÆL<ÖùŽ555…®Ö´Ó91{ÌÔc­6A~ÌÆs¢®®Ž¦¦¦BcÚÍÔc=\,È¥MPªJõø–êߨR-÷LSq}PªJ5¨Ü*w>(8ô7J寙 †7Žu©Æ¶L¥/ò©è;wîäÈ‘#þ×ÞÞNCC ÔÕÕ±cǺ»»ioo/t±E$D DÄ1R,P™=Ô&P,Å‘RQT‰Çîîn‰_øÂ†}¯··7+ã]UUEMM »wï.tÑE$OD DÄ1R,P™=Ô&P,Å‘RR4‰Çt:ÍwÜA8v8D÷I†Á]m+**èîîuÛ§OŸö&õ™Íz{{éìì䨱c….ʰ¦2;vŒÎÎNz{{ ]U‘‚êììä©§žâôéÓ….ʰ¦£MP*óÚ‰L•t:Mgg'/¾øb¡‹2jGй¶ NžÑ=CÝ3çú m‚y…®8 œÖÖVî¾ûî)ÙþÒ¥KyÏ{ÞSò“Šäª®®Žººº¢|ºªãÀ¥—^ªÉ}Ep&ëîìì,Ê‹kµ D¦GUUMMM477º(ÚêX°lÙ2µ D€††€Y{}póÍ7+ˆ ë]ˆèž¡îŠ8¨ªªÊ¹MP4‰ÇŠŠ ¶oßžõzss3ìÚµË{­»»{HwêáºW‹HiQP,ÇX±À}ÒYq@dæR›@D@±@DDJQQ$†ŸÏ[ ££cØíD£Qâñ8}}}Þk¶mFI$£n[¤Í´X "“£X "Š"Å£h{öìòZyy9wß}·7±åúõë8Df0ÅÅq Ž31b±˜÷»mÛ466ÒØØH[[Û¤·ÇI&“ttt`¦iæeÛ"ÓImÅQ)vE›xÍà1EdöQP,‘™|>Ÿ—tY–E<Ïi»‰D‚p8œµmÃ0ˆD"466޹¾iš9 ÍêñÔ»R¦ÌLŠ"2yŠ"¢8 Rxs ]Y®s1ú|>R©Ô×C¡ÐˆC¶‚ÓS²¬¬Œ`0Huu5µµµØ¶ @YYÙ¡a3_3M“²²2‰ÕÕÕƒA*++‰F£…Þ""""""2…”x)¶mcš¦÷ãÎˉDrÚn("™LR]]M4õ’ƒÃõ°t¥R)¢Ñ(---ôõõÑÓÓƒmÛî}Çéèè ¯¯X,F<2פˆˆˆˆˆˆÌ%9ÔªˆˆˆˆˆÈLcYÁ`0ë5¿ßŸóð¤±X Ã0H&“$“I/y …ˆD"!ë¸=$Ý÷ü~ÿ¤æ‚ÌÜ~$!•J‘L& ‡ÃÓ¿ƒEDDDDDdʩǣˆˆˆˆˆÈ(ÊÊÊòþ3Ã0èëëËú …BÔ××;TêD†AKK ===tuu‹Å0M“`0è Ÿ:xù@ @mm-õõõÄãq|>ß°Iʱ>7“ßï2D«ˆˆˆˆˆˆÌJ<ŠˆˆˆˆˆŒbp20?ã‹Å&=<©;dj¦@ @$¡«« Û¶GÜvWWmmmøýþ¬¡Z'bpoÍ\{oŠˆˆˆˆˆHqSâQDDDDD¤H¹½'›°sçeL&“CÞm›¦iÇ …BÄb1ºººˆD"#Îñ8\¯Iw;™R©Ô„{MŠˆˆˆˆˆHéÐ""""""EÀ¶í!‰:wˆÓÌ9‡[†k NïFÃ0¼í¸ËضM4²m—ÛSÒrÕå÷û½ÿ›¦émo¤žñxÃ0ðù|X–E"‘ÐüŽ""""""3˜""""""EÀ²,‚Á`Ök@€ŽŽŽ¬Þ‰Ã-Œ8„k[[õõõCÖñûý´µµ Ûó1“L&©­­%xsL¶´´x½MÓĶm Ã1ñYYYI À²,Âá°7|¬ˆˆˆˆˆˆÌŸŽŽR©”—@„á{Hþ,˲¼aT€—¤ŒÅb„B!lÛÆçó8|jKK ápxÌåDDDDDDdfPâQDDDDDdðûýYC¥ŽÇh‰Âñ&•l™=æº"""""""""""""Rú”x‘¼r禑ÙE‰GÉ+ŸÏ7æ’""""""2ó(ñ("""""""""""""9›W興ˆˆˆˆÈÔ³m˲ðûýøýþBIDDDDDDfõx)°`0HYYÙŸ`0ˆmÛY˃Á·F)++ËzͶm©¬¬ôÖ¯®®²m‘\)ñ("""""RÞO[[–eÑØØ˜Óvãñ8Éd’ŽŽúúúèë룣£ƒT*•ó¶EDDDDDD2i¨U‘"àóù0 #ë5˲ˆÇã9m7‘H‡³¶m‘Hd\‰GwxÖ@ 0ì{¶m)÷àe|>Ÿ†v™òÚã±½½ææfš››èìì$NºŽ""""""“fš¦7?b*•²¬¬ÿÛ¶í-3øß‘Ö™ˆ\v>ŸT*5äõP(DGGLjëY–Euu5µµµÔÖÖR]]í•ݲ,ïõ`0Hee%‰DÂ[·¬¬Œx<î­ïíꪯ¯§¾¾~Èç•••MxÿˆˆˆˆˆˆHñÈKâ1N³e˶mÛÆÎ;Ù¹s';wîäÝï~7ÝÝÝ…®§ˆˆˆˆˆÈ¤ÄãqR©ÉdÓ4I&“YÿO¥RÞ2ƒÿiḠK÷'’H$ˆD"9•? ‘L&©®®&bš&0|ËLõõõ†Á¡C‡8tè†axÉB÷ßC‡Ñ××çõžÌLp& ÚÚÚèë룫« Ó4½ä¤[¦Ì9&“É$@`Øž•""""""21™×g¶myøsªäe¨ÕD"Áîݻٵkuuu¬[·€;3ææf6oÞÌücÊË˧¥R""""""ùâö -!æ.3øß‰$Ñ,ËÊêNoGŸÏ—Sùc±†axÉOwèÖP(D$¶ŒnB5‹yŸ‰DH¥Rüë¿þ+©TŠžžž¬÷’É$‰D‚X,æmßÝv À0 ïÂ7 áóùH&“„Ãaï3Ýÿ‹ˆˆˆˆˆHn¢Ñ(mmm€ó@­ûðçhטGåĉ9}n^z<¶¶¶‡©««Ëz½ªªŠ/|á ¤ÓivïÞ=ÕûPDDDDD¤d†A___ÖO(¢¾¾~Ø¡R'ºí––zzzèêê"‹aš&Á`0«×¡Ë²,@Ö©ßï§££ÃÑfð°†ad “:ZoJp’nïKwZ%EDDDDDrgÛ¶7ÚŽmÛÞè3ÃÀã^—¥R)B¡?üpNŸ·¡Vkjj†}Ïíå¨áVEDDDDD&Æí=˜9âD¤R)¢ÑhÖk@€H$BWWWÖè`¹ö´‹Û Ó-ƒÛ RDDDDDd63M3ë¡ÎÉp×·,‹ÆÆFü~?‘HdÈô–ey׌‰D‚«®ºŠw¾ó9}v^555´··û^gg'ÀÞ""""""2:·7âdr¶m{Cê 6Ú6ý~¿÷Ôkæ¶‚Á kÖ¬É*›Ë4Í!½ G“9Üj2™$ MÏN)bÃŽLãiDœÌ©;ÜÄc4Å4MÚÚÚ$“ɬ¹‰„7išÔÖÖæ\þ¼$Ãá0­­­lß¾ÝK4vvvÒÚÚʶmÛ¨««±G¤ˆˆˆˆˆˆ8‰<Ó4³~êëëñù|YC·Üà$¡Ë[1g-cÛ6Ñhtȶ]nR°±±Ñ{-cYŸüä'ñù|Y=)݋Չ&Ãá°W%EDDDDd¶‹Çã^p$µµµÞÈ5õõõ466R__Ÿué&.MÓ$ á÷û …Bttt×^îCªî5Ý»Þõ®œë0/;bÆ Üyç477ÓÚÚ À–-[hhh ©©i v¿ˆˆˆˆˆÈÌaYVÖªà$;::²z'·@__ß°Ûmkk£¾¾~È:~¿Ÿ¶¶¶a{>ú|>b±˜÷t,8ÉJwè׎Ž‚Á ÉdŸÏG*•"‹9¯ã`¡Pˆx<®¹EDDDDdÖsG¬¹è¢Ïç†]ÆM666bY–—XL&“øý~¢Ñ(–eáóù0 Ó4½ë´TŠþÿÛX–…mÛø|>"‘Ñh¿ßϪU«Ø·o_NõÈKâ±³³“ºº:{ì1¯Ç#Àúõë½9EDDDDDdxÎS§¹/‹Å¼ä ËçóÑÑÑA*•Ê’g¬$a8& yCô/IèééñÞóûýYì—®ì@`Ä„©ˆˆˆˆˆÈLfš&@À›†ÂçóqÉ%¿ÍÏþ/#®ãŽPljD"Äb1ZZZH$Þ¨5¶m‡½‘i ˆF¡£æÌùmlû1oº w{áp8+Ç7YyjuÛ¶m^OǺº:ïg"IÇt:ͶmÛX·nëÖ­cÓ¦MtwwY®¹¹™›nº‰uëÖ±mÛ6z{{óQ)Š"Š"âO,P˜¿ßaÞÏx¸OɆ1¤gdæ{™ÛQd¼Ô&P,Å™¹LÓIJ,êëë‰ÇãD£QÂá0§O_Ë+¯\H2™Ä¶mR©Éd’ÊÊJ › .ØL àŒ8‰D¼í¹×ymmm€3ÂŒ;ºL"¶ ¦ çÏWx¦ü~^G¡ÉÛííí¤ÓéIocóæÍôöö²k×.víÚEUU›7oÎÚ¦;”kSS»ví¢··—mÛ¶åmgˆHa)ˆ(ˆˆc¬X 8 2ó©M " X "ŠRœ2““mÛÞœ‹™’ɤ—|ŒF£"‘?^É޽稯¯§ººšêêjêë **Úxá…·ÑØ¡3-‡;«†Ïç'è!‘aNBÒ™Bb10 è´&+ñ˜oyjµ¼¼œòòrÞýîw³qãÆa{:Ž6Ïcww7ÝÝÝÜ}÷ÝÔÔÔÎ0­7Ýtlذ€öövhhh`ÇŽ†A{{»·Œˆ”&ÅÅqŒ'Ì´8 ½¹‡ãGZVVFGGÇ„çR)5jˆ(ˆˆâ€§T ’IÈèl@<÷†.îõÌ^…–ey=m>úÑ_Q[[í%Á™Î"‰°bÅûøà}Üt“ÿ÷ÿ €xÜéÁhÛN21…p?~?¼üòç±,ðùœeÃa… $Vöí»ËŠOÉè5yI<öööRQQAEEŤº/———³uëV/p §»»›ÞÞ^êêê¼×ªªª¨©©a÷îÝ "%Nq@D@±@DcÅ‚™|>@`ÈüŒƒE" k*³‚Ú"Š"¢8 Å)•r~ƒY–E<'•Jys&‚Ó³Ñ}xÔîÔ²œùS©K–<Å3Ï\Íè$;:àCj%‡I¥ §2/#²„ÃNrѲ ¥ÅY®¾~ɤ“¤ ‡×ÜÎo}ë´¶þ-@ñöx­7ãxTUUyÛèîîæÈ‘#´¶¶RSSã‹#GŽd€ŠŠŠaÇs‘Ò¢8 " X "ޱbÁîÝ»™lÛöæLÍp‰I˲ðù|£&$ÝatFÚþx¶!2Ô&P,Å)>¶móÕ¯îåÕW—Wg½çŽbÇ „Ãa¢Ñ(©Tˆ»ïž‹ßoòoÔñôÓK€mm-Ô××óÎwÞÏ¿þëÕ$NÏÅDæÎýáð›§—b à —šÉíù 9 ÇDÂéáΰªñ¸“˜t×óû×/¸àRÀO8<5#éä%ñèêíí¥½½=ëD|²¥¹¹™ÎÎNÀIh7lëD½öÚk477SWW—s’T¤”µ¶¶ÒÞÞÎþýû ]”QMEØ¿?[¶laÆ Þ° "³Ñ–-[8räW^ye¡‹2ª©lTTT°k×®BWQ¤`º»»innfÿþýn¯O·©ˆdË–-ÔÔÔ”ÜõAæP«–eQ__Oªr‘H$‚eYD"‘Œ§imêëë½ `ŸÏG,#SVVF,#‘HxÛ0 ƒŽŽŽBWS¦Iss3ÝÝݶ ïz×£<óÌ3œ;w™‰ÇT*…mÛôôô`Û6µµµƒA,ËbÙ²çxíµ2>ÿùorò¤Å’%xã/Àš5_dÏžßÅçsz1º3p<ùä:|¾ °,çµáÇqŸõû^#¹z‰GŸo`9ŸÏÙN8| ‹ý7~"k{î9–k› o‰ÇíÛ·ÓÚÚšõÚÎ;©ªªbÇŽãnÄ»ä;;;Ù²e ååå9Ÿì]tøÀŠþ¦ŠÈTsÇ9ß²eK¡‹2ª©ˆk֬х„Î9ÖÙÙé5Ö‹•Ú"S§¦¦†]»vÑÜÜ\袌i¸XPUU•Ó6/½ôÒ¢k¸Cì 7Ï£; ë`†áõ‚ ƒ^ÑU__ï]üúý~âñ8^ÏÆD"A[[@˲¨­­%‘HdÍ="3—›xŸ­×ï}ï{Kîá‘© ë]ˆèž¡îÊø|õ«¯ñÄsyßû>Ä}÷!™Lzó9š¦ÉEý;ÕÕ~B!ðûý˜¦IOOõõ•<ñDš²²z"‘Æû¨¯‡êjðûßCæåžÏçô`ôù. ¾ÞI vuÁp#¢º¯””ìé~ÀyónåþèBn½ÕéBGGS^Úsò±³›››imm¥©©‰Ç{Œ={ö°gÏvíÚEyy9Û¶muýÞÞÞ!]žÝÞ’ƒ+8\×h=™(RúD DÄ1ÞX0mq 8è'Ñÿ¢€5Ì2֠壃ÞĶm,Ë" ù‰F£C–·,ËëÝèóùðù|´´´`gL4bY¦iÒÖÖæ%#‘¡PˆD"@(ò’š@Ã0†$/E AmÅQâ`Û6¶mó•¯ÜË\Ëúõ«¹ä’ù$“Io™T*űcû{‚ß%‰~"¸öÚg¸ýöóÄb1 Ãð†G½âйüÞï­õ¶ 9‰Áúz§§£a Ÿt„ׇ›or4Á`%åå7x½"ÝÏÊ×¥`^ííílݺ•­[·fuo®««cÇŽôööŽš!moogóæÍ£~†ûä‘;Ÿ‹«³³3ç'žE¤ðD DÄ1V,˜ö8ôcôÿD€àfÿ åCƒÞ†aôõõ ùnèÓd29dNÆÁ½"Ýb"‘ z?îE³û™"ÅHmÅQÂK$Ô××󗹓7Þ¸šo}ëâqø­ßZJ2iz×]ßûÞ ÊÊʈDœ„à3Ï\Ë{Þó9,ËIî}îs7ó×½ÚÛnK‹“ lo¿þN“€ÛÛÑù8<0LêHÂáåÇË4deæÜùô&/‰ÇÞÞÞ‡$pOìÑ&qݰaétš;wz¯¹Ý93·ÛÐÐ@kk+étp†r-//gãÆùÛ#"RŠ"Š"âO,˜Ö8` úñ÷ÿ@𠳌oÐòAïçoŒ«K{„Ç^€7H±R›@D@±@D¤0,Ëéð·[iš´´ÜÈÍ7_ÁýÑ…ÜuW97Þ¸•`0ÈoüÆ<ýô>ÿù§¼ùï¿¿œÆÆÌáSÇ_Ãp¶1–É$ 飛|ìèp>+ÏÏþËËUUUCNt—›p­KsUUwÞy'Û·o'‘HPQQAoo/[·nÍ£¹©©‰Í›7³iÓ&ÊËËéííÍë$²"R8Š"Š"âO,˜íq DZmÛK@"5sxÕÌ$e"‘3i)Rhjˆ(ˆˆâ€LœmÛÔ××ã÷ûiii÷z‰Ä@϶!™„üǃìÛ·œ~ôWÜ}÷´µ-¢¾ÞéÑhY 6ÐÓs˜¯}m`òÙÏdc1gèÒDbä¡RG‹/Q9™mƒ³íÁsK&“°lÙ¥\|qnÇ /‰Ç 6xOlܸ‘ššoxÕææfjjjÆœ¤¹¡¡ºº:z{{'  î]^^ÎÝwßí Ûº~ýz‘Dq@D@±@DcÅ‚™|>©T Ó4‡}?d% ÃÀçóF½‹éÁsA†ßïÏZƲ,'t.R(jˆ(ˆˆâ€LŒišýóÝ[„û3‰1²s¦éü„ÃN¯?Ótz(Æb}¬^}ŠË.»–}l YgYÎP©p#~ ßúÖŸqÉ%Ï Ù®ßïô&œÌ܉c ±š ŸÏéõ8øµHöïŸW‰Ç¦¦&À龜ÙåæyáÆpÆJbŠHéRP,ÇxbÁL‰¶mcYÁ`pØ÷;::²æcôù|ttt 1MÛ¶‡>µ­­úúz*++ñûýX–E$!ÓØØXèj‹ŒImÅQñ3M“P(Ľ÷®'•J‘H$èèèu··Ÿm;?,Xð$É䵬XqCV’ÎïèÉhÛÎïkÖlbýú‡Ýv 0ù^‰S%>± ÁŸÿù¢œ“žyI<‚“| ‡ÃìÞ½›îîn/Œ6Īˆˆˆˆˆˆ0æ…°«¯¯Ïû  §§˲ðù|øý~‰DÖòî2nOJ¿ßï Áš¹­‰–CDDDDD¤X–E4¥­­ ŸÏG2™¤¥¥…\€iþpÄQe2%“ÿZ,_¾—^ú%‹_Ä«I$æ[ôû~¢Q'ùøÁ^ì]g•Š‘æ¼çžKyÇ;rÛöœ|²µµ•mÛ¶QQQÁÖ­[Ù°a›7ofûöíÞ„®""""""’;Û¶)++ò, à xs7ƒÇÌÁvÕzUDDDDD¤Ô%û³…µµµX–…eYÞƒ˜¡Pˆ}û~Û[f<ÉGg9'‘¸re7¿úÕ? n¹å ×œ!J}>gXÖC‡ ¯¾ûÝ«†¦˜ 7¤{¹øúë9m;/‰Ç;w²}ûv€¬q“¸ï¾ûؼyóôì)‘YÀçóÑÒÒB0$ R[[K<×Ü"""""2c¥R)ošŠÆÆFâñ8àŒôbš&ÉdÒ›×ñäÉÅØýÙB˲úÿwv Ûwö ÀXÌéñhpâD7GŽü‚'>Ïm·-õz8º†ë-8Ö<’¥béÒ³:´,§mäe¨ÕÖÖV¸óÎ;³^ojjbãÆlÚ´‰ÎÎN¯,"""""2†T*E*•œ‹Wßp¢ápÃ0Ƶl)qo$@öа"""""2»%“IõõõضíýøÆ7®æÀ--- tpô 9×L¦iò­o­Ç4W`Û;ó4ÆbNOǺºiiYÝßëq` ЧŸ^2$ñ8“]uÕñâèñØÛÛˆ †}Ïã±»»{šwˆˆˆˆˆHé°,‹`0Huuµ×“±²²’ÆÆFïIÝÁü~¿7Œj¾“ŽÁ`²²²!?Á`0«þñ·³xq7–ågÿþÏqòäËø|ðÇüK¾ñŸqÿýïàóŸsæì㢋~ \‹Ì¶Ä#À /\šÓúyI<655±uëV𛛹馛X·nëÖ­cÛ¶mìØ±£ÐûIDDDDD¤(¹‰ÁH$2ìp©>Ÿp8L"‘œ^YY‰DŠ´²²rHbÒ¶í¬áJ+++½m”••Ç©®®¦¶¶Ö[f¼&:ï¢;ÿŠ›¼t\Ïá ¡PˆŽŽŽñ~”ˆˆˆˆˆ”Ó4G|²ºÚ™w1‘Hàóù°,«ÿaÊ/¿¼€;VR^þNž\Å¡C‹…ù“?Y€a@ÿ”ñض3œj}}%‡AcãaÞxãw°,øæ7Oà÷[,\ø"áp˜¶¶6¾øÅ5À¹î  ϳZµ~ð ï}ïƒ9m#/‰Gp’¦irçw²uëV¶nÝÊ®]»¸ûî»5̪ˆˆˆˆˆÈ¬þ«âP(4â2n/ÀÌž‹ñxÜ–4‹ǽÄ"@}}=¶mÓÓÓC__‘H„ÆÆFo‰D‚¶¶6úúúèêêÂ4ͬõa G¥ûFI$D"‘ Õ1™Lâóù…Bü~ÿ^˜nOÈêêj¢Ñ¨÷¾ÛëRDDDDDfޝ}mß°‰GÓtæTŒÇñæp´,‹d2Éœ9Ç¿ü‹3êf éô‡Y°`€×;1‘pކáôTli¯}!>üó?/Â$pøðaB¡'O®§¯ÏùlÃ0†ŒÂâó9Ÿ5[¬Zu’Ë.;˜Ó6æMf¥îînî»ï>6nܘ•T¬ªª¢¡¡¡ÐûEDDDDD$S:x¬Ûx¤Ö5ø±XËr–se\Ⱥ‰Gß(Ñ×Ã0‰xOâF"oø¡p8ì=ÜÓÓã­‰D°,ËK.ºI@§¸ ÃráïÎ=9¸,¾ >ò›H$…BÞz¡Pˆx $©­­äùçä•WnÞ‰aÀ±có³—nG÷²ÁMBfª©yËú8'OÎ×ÃSdRC­–——ÓÐÐÀŽ;¸ûªª¢³³Ã0ؾ};ííí…®—ˆˆˆˆˆH~ttdÿd&ÁI0^fðl,–ý~Öêβƒç<ÌäöŠÌò'; —ù{f‚qðg…r|\×}úwpRs$î0«¶mcY–e‘J¥ðù|Þpª©TjÈ•@€H$BWW¶mûóDDDDD¤¸¥R)Nž¬á—¿èçNýpÅiî½÷ƒ|ÿû'€.œÅ‹ßσÞÁ¢E×pðà-,^¼ ~Ôp8»‡âàç-/»ìNž\ÌÚµ¯ëÁÆ)2©™Ü$¤«½½ÎÎNî¸ãêêꨫ«cãÆ”——º®""""""EÇï÷c‰D"«÷ŸËMº ~Ï4ͬ$b*•ò’˜™Ã«f^L'‰œ/®Ý¤æx·ã³ÚÒÒ’õz4%cÛ6¶mLJMŒêf€ˆˆˆˆÈÌâÁ`Ыee%¦izˆˆˆHi²,‹úúz~xeeÕ€D"eù0 ûxà;ðù|¤R)Ö­›ï ¥Àš5{9sæBNœX9ér\uÕ”xÊM çä‡ZmnnfçÎlذºº:z{{Ù¾};555455‘N§¹ãŽ;hnnf×®]…Þo""""""EËM>Z–åõJôûýÞ°©ƒµ´´‡±mŸÏç ³š¹½žž¯aæ¶úúú†l¯cÐÜ“ƒÉXËÅFy ¹««Ëû¿Ï磣£ƒT*•ÕëS7DDDDDJ_"‘ð®s޽’Ç+Õ@ˆ… ßàÔ©Jîºkà:%•Jõ?¬‘ˆ3oã¿þë‹€5îÏîR"°zu§l$•J‘H$øÀ>ó¶&•xL§Óìܹ“¦¦&¶nÝê½ÞÚÚ ÀŽ;¨ªªò^ß¶mÝÝÝêõ("""""2†Á Ä\—-µÄÝhÉV)N©Ôèó*f>\xâÄJ.»ì Ï=·–µk}û¾•µ¬; ƒË}–qçÎÅ@€Å‹6®2 w)äóùظñX¡w×´0MÓ»tGšI$´´´ ¹–4 ƒ¶¶6î¸ãn¾ùæœ>wRC­îÞ½€†††¬×ÝäbfÒqÆ €ÓRDDDDDDDDDDDDf–T 2¦k÷Ø6$“ðÜs·³xñÏÙ·ïrNœXɪU‹‰ÅR¼ýí×Ã>|889ö¡ÝÀÅW™FzsçΆq­_ÊlÛ¦¾¾Þëeê&~Gz0µ±±Ó4YµjK–,Éé³'Õã±³³€òòò!¯gö€Ì¤Ä£ˆˆˆˆˆHî2çƒ)=Á XÜxãã¤ÓW°ÿÌ›·—o<„i^Í¡C‡²£€ä-oyǸÊ3Ádf¤p8ì ¡‡ÃƒAÚÚÚ°m›`0HGGmmm<ýôÓ^p²&ÕãÑÓ1N{¯µ··°~ýú¬eÝ„£†YÉÏç+¹áSEDDDDdf3Í¡‰ÇTÊI:†BðÔS«(/ß˳Ï.eþücÜzë+ø|ð§zjȶFO<š,Zt¢ÐÕ-zîPµõõõ¤R©¬Þ£@Àëé÷ûI¥RTVVz½#s5©Ä£›\tÇ„…ùÝ¡U¿>8!)""""""""""""3Cfâ1‘€ÆF§×aK œ<ù×,]ú,Ï>ûG<ûìR"øØÇV›ë^Ææ÷û1 ÃëÍ8xÿš¦I$¡¥¥…ÆÆFB¡Ð ßñ›Tâ±¼¼œ­[·²sçN6mÚĦM›† ³ÚÝÝÍöíÛÙ¹s'[·n2,«ˆˆˆˆˆˆ8‚Á eee$“ÉaßF£”••F³ÖÉüÝ•H$(++ó ƒƒÁBWQDDDDDf ·÷£Ïç̳èóؼ÷½Ç¹üò¯qî\9+Wžð†Bõ9 d ée¶mFG¼~H&“ø|>ü~ÿýëóùˆÇ㘦‰ßï§­­–––¼•oRs<455QUUå ±ºuëVššš¼÷›››½ddæë""""""2<Ó4 …BC^í‚2S"‘ ±±‘––oþ‘©fYN‚Ѳ,~ðƒ-ZDÿ´žòòxôÑAV®Œx¯×Û±««kÈkùê‘WêLÓ$‘H`‰D‚ŽŽŽ!Ëøýþ{‘†B!R©”wí™ïÞ¦“N<444ÐÐÐ0ì{MMMš×QDDDDDdœB¡ÉdrÈ“¦–eaÛö˜Oû*é("""""… 9C«VVþ˜ï|çŸüäÍÞ{¦ipóÍõ¿æ.q67ñ8\ÉÙ$ÐÑÑmÛ˜¦Iee%mmmÞ5c*•u¥R)LÓÌk/ÇL“j5Sgg'twwg½®¤£ˆˆˆˆˆÈø¹Cà îݘL&‡í™IIG)¤þÜ"?ùÉ>Òé?¦¯oø¤ÖêÕ÷vN½gã|ض“¬­¯¯Ç², à ‹ÑÑÑ‘µOÜåFƼÆÌŤ{¡ê³:ÒÓ¨nÒ1 ‘H$°,«ÐU‘Y ™„x|à÷P¾ûÝ^–-û,óçÏçÈ‘_d-ïýyìØ±B½äÔÖÖ‰DH&“TVV’L&³¡PÈ›·ÑçóaYÖˆ®º¦r¸ÚIõxìíí¥³³“;ï¼Ó›ã±®®ŽM›6 ru¼Òé4ÍÍÍÜwß}¤ÓiªªªhjjbÆ YË577ÓÚÚJ:fÆ 455QUU5e;HD¦â€ˆ€bˆ8Æ ¦+ŒÔ;1sÊÅá–i½Ñü~?Éd’p8L"‘sœ®®.Á`úúzºººfýœ'23¨M " X "ŠÅÆ4FsI&ëžT *+sÏ=pÁ·°xñËë˜Þÿ0Éõ¸3 cÆ_ïÄãqlÛ&‰F1 ¿ßO8öþŸÉï÷S__OKK †a`FA‡£TGwxÕÁ'm]]ݤ ²mÛ6î»ï>¾ð…/x=(·mÛF{{»·Œ8šššØµk½½½lÛ¶­`;ODòKq@D@±@DcÅ‚™B¡wažL&1Œ‘‡ ‡ÃÞeKK ¶mÏ|ìX¤„©M " X "ŠÅÆ4„#8 ÇDÂù·¥eË–-ãòË/÷–M¥R¤2çœÀîÿ™œÁóÎDÉd’d2‰išØ¶M,Ãçóys3WÃ0¼Qpâñø˜=§Ò¤çx̧t:Mgg';vìðžR¨««£³³“ûî»Ï{­½½††¯—åŽ;0 ƒööö!O7ˆHiQP,ÇxbÁLŽ¡PˆÚÚZïBq¬.¿ßO,£±±Ñ{ÊU¤T©M " X "ŠÅ,væwL¥œ¹×®}ŽeË–1þ|þÛÛÇ}÷=›•üH–™€¦ˆM¬øœD"A8×:>ŸÏKNúýþ‚^NzŽÇ|êíí¥®®Žššš¬×ׯ_O: »»Û[ÎUUUEMM »wï.tD$GŠ"Š"â+Ìô8à^(Æãñq']áp˜P(D}}½7O$€mÛ˜¦9äG¤X©M " X "ŠÅ&•JqòäIL¢Q§÷£ßîTó×_ÿ¡´µÝȉ+‡ÌAï$•tK0ÄçóaÛö}8ŸÏG<Dz,êëëÕ㱦¦†]»ve½–N§¹ï¾û¼'Ž9 ε¢¢bÒóJŠHñPP,ÇX±`6ÄP(D<ŸÔSª---TWWÓØØH[[–e ‡,Û××W誊 KmÅQ(&–_úÒx‚pø­Yó<Îq9yr1©<þx%7Þ¸´='qfüÜŒù`Û6]]]:::ƽž;¯£;æDbͧœ[¶löõuëÖ ymÏž=ãÞn{{;ÍÍÍTUU»éh^{í5š››©««£©©)ç퉔ªÖÖVÚÛÛÙ¿¡‹2¦|Ç€ýû÷³eË6lØà5LDf£-[¶päÈ®¼òÊBeLSÕ&¨¨¨rá"2›twwÓÜÜÌþýûsš§}º ޹>µ|ðàA¶lÙBMMMÑ\ ¾ ŒÅbÞð:#-3ÒE¨ÏçãСCc.'ÒÜÜLww7,tQÆ4×?üáéî©iH/ ‘ÙD׺>Ñ=CÝ3I<‘ˆóËr~NŠòÀÿIW—ó{KË!ÂáJ~ø œ<ù>LöÑÞÞAeåòa·«i!Fæ>4:чD}>¦i‰D¼‡X'ºŸ›››éìì̹M0©ÄcUU[·nÍq÷ ÕÛÛËöíÛéììdëÖ­„ÃaÊËËsÞîE]Ä>𒸩"2•ÜqÎGzh LUX³f.$D€]»vÑÙÙIggg¡‹2"µ D¦–ûÔpsss¡‹2ª©Š—^z©Ú"à%ÞgëõÁ{ßûÞ¢yø@¤t} ëÝ3Ô=Ѹ½ãqghÕµkÏÒÛûû€óûòå_ö’HÄÙ¿ÿÃ\wÝI^ÝYçÈ‘}À@âQ½Çg¢=]>Ÿ¿ßïõzôûýÞFSSS^Ú“N<æ»qÞÝÝÍæÍ›©««Ã4MªªªF\nð“ˆz2QdfPP,Çxbâ€È̦6ˆ€bˆ(Šm$Ýéã꜄–3eüë@œêjçý›nºœ%K _ ØYÛsæwœlÛÆ¶íI%ÿ,Ëšô´™½€'óÙù2'_êììdçÎìܹsRÙÐmÛ¶±qãFvìØ1làpŸ<<¬RggçˆFDJ‹â€ˆ€bˆ8F‹Š"³ƒÚ"Š"¢8P(NbÑaC:}†aY6Õ«ï娱ùÄ㯻ó;Î$ÉdrÄ÷R©¶m“L&G]n4@€ˆ;¾í…Ãa|>_Á§ÛÈiŽÇt:M"‘ µµ•t:õ^yy9 ãêòÜÙÙIoo/uuuC’–ÞS ´¶¶²qãFÊËËÙ¹s'ååålܸ± ;QDr§8 " X "ŽñÄÅ‘™MmÅQ(¤Ìœa*N‡Å2ž{n/åå{I§¯àÚkOóä“ΰ«{öTqÅÙy"Û¶I¹Ý&g˲°,‹P(4ìûn²Ñ¶í‰lvÈ6R©Ô¤z<Ëp¶“N<¦Ói6oÞLww7 ÔÕÕy Æt:íõ€ìììäë_ÿú¨ÉG7`lÛ¶mÈ{uuuÞøÊMMMlÞ¼™M›6Q^^Noo/MMMyËYD Gq@D@±@D㉊"3›Ú"Š"¢8P–5t4MˆÇãØv„N}TVâС±bÅ.½ôAž|ÒYöµ×Þ9d{31ñ8Ó4 $“I"‘Á`¿ßOKK˸?£C¤æË¤ÍÍÍôöö²k×®a'`Þ°a6l`Û¶m477sçwޏ­¦¦¦qÍY^^ÎÝwßí›õë×+pˆÌŠ"Š"âO,P™ÙÔ&P,Åé–LB}=ø|Îðª_þòÜ{¯I áäÉ—µ¤Ó¦¼ü¿ú× ÙC{¶µ9ÛÎdzò ŸÏ7ê\•‘H„ÆÆÆþ}™$S__O$wBq&$j'•xìíí¥µµ•­[·›ttÕÕÕÑÐÐÀÎ;óútÁhŸ)"³ƒâ€ˆ€bˆ(ˆˆC±@D@±@DreYÎ\Ž¡ƒL.Á0À¶áðáÃÜxcpæ|á…·ñ¶·ù€ˆ7d  >阙°+–!A'¾,âñ8±XlÈ{¦iR__OKK @€xMYY%gþücý½ýËÚø|>¢Ñá·Ÿ™l,ÕáD-Ë¢­­Íû&¿ßOWW¡P¿ßïõŽôûý†1¡žž¥º\“J<ºÝ•«ªªÆ\Ö]fðį""""""""""""RXÉ$TW;=C!°í$/¼ð) ŽeYÔÔ¼ŒeÅ9p`u’ÑÇêÕ÷ö'Èâ¬_ pq~?L`JÃ’‘J¥‡Ã$ ÊÊʨ­­Íµ±±‘d2éýî$ldk(¢ººÛ¶‰ÇãDGÊÎöŽmÛS[™P;u›ŸTâÑí®ìö|»Œº8‹ˆˆˆˆˆˆˆˆˆˆˆËræt ‡!‘pþoš&×^û ååï||éKsX³æ€³ øÙ·oyÿR|ã ½í…BN"³”çrN2™$™L …hii¡££ÓcˆÅbYC©úý~oxY¿ßO,Ã¶í¬¤cf¢2s½)Ýw)œ±•ë†F6©ÄãúõëhmmsYww)¼DÂIÆbÐÑáôÔK$Äb1Òé›Geùò# äÃL2W¡¬íevÖ˜ױX%œLj–Ì„¢»ŒmÛ´µµaÛ6¦iâ÷û‰F£D£Q*++ ƒYÃɆ1d^ËÆÆF:::§‡dcc#‰D‚T*Ecc#¶m{ÿN™Îá‹Sô1“J<–——ÓÐÐÀÎ;iooq¹öövvîÜICCåååS·£DDDDDDDDDDDDdÜlÛI<†ús‡~¿Ó /³·À?ømª«M à$(ýþ$àôÜ+//ç­o}ÀKºeŒ>ê½–9g¡;ïa±¯Wä”K徉áL:ñX^^Î׿þu‰­­­Cz>–——³uëVÂá°z;Šˆˆˆˆˆˆˆˆˆˆˆm$- ¯c&Ó4ikkœyãqÛö?!9B¹Õ«ŸÎúÝý çÿ>Š•eY¤R)/H¥Røý~,Ë"™Lzêº=@s>v¸u#‘à$Aý~¿÷û”óá ¹:&x'¹ØÔÔDSSYïÕÕÕMÏΑQE£N¢1tz9î¨×ØØ ôî … µõ<ûö¼ÍÕ«ïå¹çÞåý8IÇ©œ¦0_|>>ŸÏî´««Ë{½¾¾Ã0…Bø|¾)Ÿ¯2xóGNég€ÎüŽñ©ùˆœ™”h)Nɤ“L´mÈìXgÛ6õõõX–•5Ìg4 K—ÞÀ[Þ²¿L3»ã™3×qâĉ¬Ïñùià eZ,lÛÆ²,lÛÎ*«›xD"466’H$‡ÃS^žÁskN 'áØ†“„œs¦¶ÐÜÜ̺uë¦úcDDDDDDDDDDDDd¦é$ý~hks’ƒ®úúzlÛ¦««kHâëèÑ+8€3†‘5ÿã”ò!¦džÇ)O<ŠˆˆˆˆˆˆˆˆˆˆˆHáø|ÎOuµ“„L$Ô×דL&±,‹¶¶6ü~Ö:pùå_#³kœ›·s”×_ÿ' ‰ÇX,F¬É)ïÅ7˜¦é%ãq§Ì–eNymÛÆ0Œ¬ò†ÃáiéíxûpJùqŽI ‘ÿÈÛP«""""""""""""R||>§·b<O?ý¾÷½ÿá / …†$êëá¹çn À†ÎݸlÙ!FLÎ2éFgÈÔ@ €Ïç#™LbñxÓ41 Ã{ÍZÕM˜ÎH&½dvVÍõx™Á‰¤á7¾ñiÚÚÚ¼aFGÞÓï‡E‹®̬eÏE8Z¢.³çãT²,‹úúzR©¶mFñûý˜¦Iuu5©TÊ›wÒ²,Âá°7„ªÏç#x?3Z gžG€½óH=EDDDDDDDDDDDf DÂúÔ4o¸á~n¾9ŒaضíÍi8’E‹Nàdª oUÃè݉DŠf.ÇT*E<Ç0 LÓ¤««Ëûfb±¶¶–p8Luu5áp˜T*åÕaF÷v²Ã€ ЗßÍ*ñ("""""""""""2ÃD£L:ë¦Rð‰Oìå‰'6ðµ¯uΜ‚ápxÔÄá«qºÆ9IÇÁ ™tL¥RX–E  ‘H‰DˆÇãøý~ººœ:úýþ¬a`Ý÷’É$±XlHý‡rvÆ Øð]àwów'•xìììdË–-…Þ%""""""""""""2H4ê$;:œÞŽñ8|ùË_&g 'ê7:Àûï‘W_}¸¡ÐU" bÛ6ápÛ¶½z4ߤË*¶±±‘H$2»z9Ϋ^ÚÿøÝ¶¼}ĤÔÕÕpψˆˆˆˆˆˆˆˆˆˆˆÈ`Ѩ3ÄjG‡“< `ß¾¯ñØc÷‹u{;©ضŸŠŠç ]¥ŒºE±, ¿ßO[[@€úúzB¡PVODZ̪ž™ `w ’–3‰çÁ$ün÷öòŸü„ŠãÇsúˆI%kjjصkW¡wˆˆˆˆˆˆˆˆˆˆˆÈ¬”HÀàÎ}¦ ¡óãvl´í­­[éèè˜ðШû÷_ÄÍ7/(tU½äb2™$‰ …¼ºX–5á^‹~¿Ô¹-g¬Ï™Ðt¾ ~?¼7[’°îÙʲ²œ>bÎdVêîîfË–-twwz‰ˆˆˆˆˆˆˆˆˆˆˆÌ:¦9ôµÆFg^ÇŒÑT‰Çã„B¡ 'ÚˆDà;ß)/h=mÛÆ²,‰---Cæeìèè˜TÆÌ!gg•µ´µeAu‚oíÿä'ÙsÝu9m~R‰Ç#GŽÐÙÙÉ‘#G²^_·nÍÍÍ…Þe""""""""""""3še9?™¿Û6dvþK¥R$‰1ç=N àl«£’Ö×דL&½¡TÍa²­“6u2û¤ä­5áòþÿÇbð×a°+—f›ÔP«""""""""""""R8©dŽœjYÐÓ“½Œ;Di)+jš&~¿ŸD"AÏà ÊÄ<á‡cýÿw{|¶wT“êñ(""""""""""""…ávüK&S)g˜UÛÎ\Æ$•JÑÒÒRèâN˜eYTWW{êF"‘Ù;4j>݆[‡™3‘¿PâQDDDDDDDDDDD¤DÄãÎð§áð@¢1ÃÈÕ4M ÃÈš±¸ ÓH$‚aX–…eY†1éaUe>òšxÔP«"""³ÐW¿úUÊÊÊ ] ™ Ó„DÂéåhο‰tt ,cYÉd’H$RèâNX2™Äçó러ÒM@–òp±“H8cð†BΗe8! 'ù¸>÷TG‘Y¦±±‘{ÊÊÊBEDDDDDDDD&À4Ÿ¿ßÏ ]4™€dÒÉeNÕgÛ™cL$E™tL$†‘•X´, €–––é,ˆ3Fm¡%€Î§S%³[,8™êÏÇa¤Ün –¿¸®Ïíc‹rŽÇM›6Ø £¹¹™›nº‰uëþöî=>ªúNüÿ‹;@1Š'\D@‘QÑjµ3*Úje;‰ÛZWZlý¶Åvig¶»ÚV·íL¥­¶ý¹;£-ön2­V[›Që…Xi¢1G0D@!K~œùÌ%÷d&™KÞOyH&3g>çöžÏ|ÞŸËV¬XACCC¦‹+DNñù|™.BH¹,³AD;³µ‰Dp:±)*tÕÃ)GH,B@ç±@ ‡Ô „ ±@!q £¦Ýªªxn)àɆÄZ†a …’›tÏ$l^ÐÿonYPV–¼æa¦E°Ùލipž»óÄcšF`¦œx¬¬¬dÍš5±/_¾¼ÃŸžzਫ«ëðo«V­¢²²’•+W²zõjX±bEzŽ„ƒD8æÀ™.F—$ˆ\ ٽϒiÆëKjAq 6'¾×ëýžK$! óX q@ˆÁCêBX „8`šöOÛœbbóp8œuIÇ@ €išx<t]¯ßhÁû[Þç¢ÑõoB!()±ìB!p8ìäc0„Mü)Fô}ÃØ#Ò‡n;éÙ‘è¥3ºetJoÑçÄcss3Ë–-ãÎ;ïdãÆ444PSSüyó(**¢¦¦†ýû÷÷h=ÈÊÊJæÌ™ÃªU«:}Κ5k(//§¼¼œ%K–pß}÷QWWK| !ºf¦i²wïÞL¥CD>nÄ£Ê#F"ɹ\ðÛßnÂårŦWµŸÉúÅAbÂÖ],8 Dþ“:$!$(á°dì¬iÇ0 Âá0n·;ÓEMbY>Ÿ—Ë…Ïç#mÈjr61eÇ&¾3±ÿÞ\pôx ¾Þ^ï0„r¯ôÓè< ×ŸÂØ£ =ýøþ–eï{[ÐEóà¤g'1ûµÙ)½uŸwÜq Üwß}íÖ{\¹r%÷Ýw<ò 477w»½%K–°zõjV¯^Ýáßëêêhhh`É’%±ÇŠ‹‹™7o^,ñ)Ä`eõ0Ë¡‚z¶&%ˆ\çóÙŸééÎíu4†iBi©ýoðß7€;wðôÓ{Ðu=6G¾Óé´œ˜jUbºŽ„¤N „‰B‰ŠeÙKôuÄ0ŒXôlkûq»Ý8N<Á`Ã0(--eýúõœ<çdŠÖõß›ëº=­ßoO3ªëöAü†ßNü騣3AÇN<úIÿ¨ËpØ™ÐÙìg]\"{/ßËÔÆ©)½ý𾼨¡¡5kÖ°råJ®ºêªNŸ7oÞù$uuu¬\¹’yóæezw…ȘåËåû|?ƒZNmûöí™.J‡¤Í0>Cht5v\.n·;Ö=›¸\.¼^/N§3ÖV=ëÊY,+€Rìä_äKŽŽ³µÀðËĈG7öhKàÃN‚zSÚb\ `ÿx<_0Xµj»wsÚœÓ8›³û\„>'Ý„K—.åÎ;臘¦&c“'OæÚk¯ÍÚF!ú*‰àt:1 ‡ÃÓé¤":|Úáp‡±,‹`0ˆiš˜¦IUUeee™.zFœ~úéòEBôŠJê9{°°r(gÕBSÓw¨«û6áðL³óžhq¹ º:þžª ¯¾ºð¸ù毱pá÷‡ÇàñØ3&h”–¾M]Ý.>üÐC ÅÜpƒ+[aá1š›'rÛmMÔÖ.æÈ‘šNcÏgR'Â6oÞ_ç9¤p8 UIÇÄ)_«ªªbíך¦aš&Û¶qú²Ó¡>ÍonYöO4ÁÙ!{ºÓþmØ>ìD£3ú¦w‰Ç®¦\³,{:ÙÎ%ýØIϬ\¹’š%©× ú4ÕªzÓ¢¢ä!°åååínPõœžô,BôN$!‰`šfÒc‡˲ðûý„B!LÓ$àt:q»Ý,X° é5Bˆ¸Ä[£¢Âî Ԛǖ‰×3jÔ'yì±70 {í¶:›å ¶¶¶•ü\M#:5H=ü£‹¯}m ?ùÉ!<{t¥ß&ÔrÒI˜:u*^¸ƒcÇÞ¢ªÊ^c9†ùó7Vì5B!„B!„"»™¦ý£ë'gÃËÃ0bË…Ãa***„ÃaÊÊÊðz½IeÔu-°“~a ãdÔô¢¥¥ÐÝÀ›'BÐbÆGYúºÝzÿqcøìMs}EErb"¿¿ë‘>ú}zÙ>%U/ 5òQ)..n×CH=']Ó–t”À”)QÄ`eFl$£‘ÉðûýTWWdž¯«……=`v­«YNâ€è©ž$Ø Ãî5CII<ÑØSœF"ößC!ûqU‰²,‹H$Âo~³“pØþ¼ë­B¼^/ÍÍϲ}{s´rhÆÖW{;¥¥‰Û‹jTOs8ìOœhW.Nxúi»#ÏÈ‘WS\üq¦O‚P¨‚ª*;1iš&Û¶•ÓÚºˆÖÖz޽žõëíŹu.¸ »’ 9ObBâ€$!l „ù,ËΣ••u=Ú1ãìÉt]ýH%ËÊÊ0 ƒ¦¦¦Ø ¿ßñàñx˜8Ñn·Š%ÞRI†E"öÒ4{´_t©¢N=†ÝцC ;ù9#«‰'=5ìQ=ü@$b7d&ŽlȲAF}J<Ο?°ç~îŽzNWs0÷„Jh¶] ¶¦¦&åm ‘«TâQõ(Q ‘¶IEõ÷L¥Jâ€è ˲†mµMF†Ãv°¬Ìî äpد›3ç Á ]± …ìÄâãoäòË·rî¹Ç9ë¬Çq¹|,_>–GiƲ`çο¢i ç£Ærê©/SW×K<ú|>~ÿû£¬_¿°ß×åJ^ïÙ4í2èºý¾¡Lþã3Œýn7,]:GEZ(„«ôðùX¼a&4±{÷6lØ€¦9p:íºˆÓ _ù!kÇØÓ¿–”dúì¤FbBâ€$!l „ùTçøÎƆÑáhÂLp»Ýøý~œNglðKUUUlZÕ¶G<ѧµ=¯9öÚEÁ`ÏÖLjŽE àÁNü dînɉ֪h9Êè>ª.ŒÄQ .W|EwÔú’ý¨O‰Ç¢¢"n½õVxà.“•••<ðÀ”——§å///§²²’ææfxàŠŠŠXºtiÿ%!²L$‰%CjØ$zTt]=îèlÞç"q`pHu*Ð@ÀÞFÛzM$’ŸÏnëÒ4 ¿ßO0ì°ýÙëõv8âHžnÔ½ö …„ë¾vⱪªo;ð<°«ma±§;ÍԤ쑑èq:^¯ÑéŒ7œZVüy.WçL¢öñîG}N<±zõêØ¨ÇššxàØß‹‹‹¹õÖ[û”tܲeK§ïùÈ#PSSØS¾æjà™Õ61—‹Ô¢Ááp8Ö{dãÆFZZ.Jzž ø¹6ÚQâÀদ*…:®d©uC!{½Â@À~Ø GÇþñùìQ†¦À²¼,ZÔÄ—¿ÜÀ=÷LÃï7¹î:{ÞQŸÏ‡ÛíÆ0 º®cš&¥¥¥Ñ÷´8xðϼóŽƒwÞ!Ö›Ìét¢ë°uëžØý¦ë ióùÙÏnfذû°,¡PˆÇFbÁxŸã&òöÛ!¾þõ³q6Ïã‹/áy>†£è8Vó0¦Lyƒªêjª€_Ùø÷×íà ¢%ë׳ äóC†`ìÚÅ/¹™ÿùŸKõÙÿ„¡ÏÂÿ¶ =¿Ï£]¥<žèƒ-o0éâý™>ÕÝ’X „€ŽcÄ!©!@b"ÿã€aØíJ>_|P[GÂá0º®·[rk ˜¦‰ÓéÄápPQÑõPÅNËèÂN>:±Gû©µ=]¾q|”_uußùÏ÷Âè6íå^ ;1çéÃ6{«£s«Õ9ÑdmW£YÃaûq»íÿ{<ÏË;ÀúœxTn½õVn½õVhhhì¤cάFV ÑWj4•¢FG Ô¨t5#j_!F"N§Ã0Ð4H$ÂŽ?¦©iARbU%óeÄ£"q ÿ¨…²uÝþQ C5C€eÙÏ©ªJž²ou=>½ê‚›yì1˜9óš›gðÈ#X¸ðaœN'ÕÕÕ„ÃáØZŒª'–®ë±¹é#‘¦iÆF'VšœN1bÇv@uD²ï¹%Kçµ×¾Èü/Lû8¼ 5GjXvÍ÷xáO<ñ(_ú«—6¾HÁ«;ñ|i†%%OÚ£•?5s••3xõÕ™özwf|!ïhœN'K–läÕo=ÂX,ö]€¦Á5×ÜÈîÝ—°gÏé<ÿüó˜¦É¤IÏ2cÆÛhš½Ïûö•ŶqÁŸœL:5éøéºÎ-EE±ŠæÔ©Sq8âõ.ý²¢hY^äp`Ã?&]Á´–÷2} !„B!„Bˆ(ðÉÔÖvœW3M³]âo ø|>BÑôÄv1MÓpöeäaâT«`'ã‚Øë*¡Pû†t¿?µ¤#ØÓ™vÔ>ï%>Ýiêè½+*ìNðï¼àïøyJ0Ø·‘TNz6m Ò–x"ÛF<©¡FR)j*ÇHŠíÝ•uëöðæ›‡c¿[–[«1ÒM!ŒhÁÕPz]×c‰“Ç =º…Ä&êC@"$ŽNTëWTÄ…}oVTØŸ›š¿W»^ ÅŽ‡}ÿªz–ú¬UuÄ:϶mçñoÿö³Ø(FÃ0:ì¥î'5åj"5Ò¸íb]‡«¯žbφ æV®­êt:Ñ"þ÷šFn¼q^/ÜrË-œrJ'Ÿü:%%%Üwß}lÚô1LÓÞG•dt:ÌŸ?†¢¢=|ò“£“ÞWÓ4¾ôàƒøý~O¼s”:ž1Mxqç<Ö_tB!„B!„";¨ÑŽápÇ…B8ÎXGù¢ÚÐ~¿?=³ë¹ÚüîÀN´•ïXPZjgaSÁÓáoF×rRëEª2˜@]'ýRaÐqbS5”º\àŒØ£.}ýðþ^âSºöI<мÐY NärÅGW™f<ÑQVŸ ¹'Ûb‰½ÄÑZOn¶…mGS¾ôR«W¿K6VTTàr¹°,‹H$ë9Ò˲ڌ´²*A2jÔ¨v T‡Ã!‰G1àÔ½–(±??C!˜81¾Vc$åvÂÐï··¡¶£ëvb1q¤i𔕕ašF,©ë`YvﯹsÅãžŠŠ¾Øý£za©©Š;Òö^S:ºŸÔ(ÅØKÓ„è\ûºn¯Ë8kË?xî¹É˜&\z鏨,õõõTWW£æwPÉÒ³ÎK\ê:ÜpÃä;s¹ÝnUUUI£¹!ÓÚv:SÅ?õÔÝ™¾L„B!„B!½P(Þ~œØÉ>‘a„B¡éhY¥¥¥3ÊÒ 8ÂvÒ ¾¾óžõ©0€§+ ¤$> ›½³`øìéN{’+…ìÄeü`Ñ®®# ­ªŠO! {h É£@Så¢ÿ’ªQ’xyA%':âóÙ ÂÚÚøºqGŸ/6Ê1$­!×ñ¾&'JT°?ë¬O2aB3f´‹m™\hXä¾®zYuEåà©Ñ|–eŽª5Uåªí½ìtÆ×mTeÕ=l'#‘.— Ó ÇFEš¦I(âW¿šË¦M¿áµ×΄B¡X’Þáp`šf‡÷†JLvô7MÓ:¾Ÿ,ËÞ µ˜s(„[št»±6íJªÃø|ñ©×N'Á`… GËfï·šÚ5ñ¸uF•91ɘÛ’÷ ¥ãòB!„B!„) ìÎú¦™Üé^1M“ŠŠ Ün÷€­í¨Ë‚Á`zF9v¤í(š/Zð/xkSŸRµ+çD&kkíéÕ Þ Äž¶«6ÑÄÑ’*! F[””Ø?'¶o u<Ål"¯×N@VUÙ¿kÑŸÎÓ}ÓO§R‘Ä£Èj U—+~/†ýoM#¶î™aÄwÛ˜ætªç¸\.¾ð…ÿá…¦0iR9‡ƒp8ÌwäС ‡]x<Á ý¾[·®#„¦¦øö¾ÿý=„ÃáXÙB¡@€íÛÓÚ:@ÀN„øý~Ün7†a`YVl®îŽ÷ÓŠ%NËÿë_ÿš@ ‚oŒ¯gšöVsó,I<Š>ë*±öç«Ëeÿ?ñs´£×™¦ý¹éñØ B§SP´ïK'>+Ä“fêï‰JKKÑ4úúz¼^/eeeø|>tÝ9¬ë:‹/àÿøGt;ñQŒª²äèe¦ÓD~ _àZ혢i8u+ú~í÷Àãñ0yò0œNûÙ#±Õ"ݱÍtS¶x=I=¿£º¨Ãgžùa¯ö[!„B!„B¤_$b·™y<íg­‚øˆC]×ñûýR&˲bË †‘þ‘Ž€5”ØÛþ[px 5AXúéÀåÎäÅ4Õè!˲5Ÿ0àßp{´Œm“ ‰mêo^¯½Í`Ðþ©ªj?|Õ¤g£)• öIéùØJ¿¯ñ8¼7/DÿP#–URQ%+*ìÿv ‡íû\5Ö«©#‘x?»¢’‹¦™\9R#˲“bm+P^¯0S/ùHž{®™sÏý?®»n>¥¥wbÁ`˲¨Šöþñz½èºNEEElÊ •XÜ´é 푎‰÷OÛd¢®zp9N9|89C ÙKõFJÜ1ÅíÆ±å(LjØCmGG«§wTÉlmíýùë,ñpÊ)‡{·1!„B!„B‘v¡Ý~Ó¦8¦¬¬ ]×Ûµ÷'—Ë[K²_40Ú->½Y"?ö:ˆè¿ÓM£ãéN½Þø€‚¥p¸ßÝ Íä×tvlz22´m{«j$ì¨!V=Â^ÿÒ=l_“‡C°“ýHF<ŠŒ3{¥W#÷µFœê ¢ÚÿMÓŽ ^o|êÆÄ{5²;'˜&¬ZÕŒeÙÔ”?ýéaÂaûwµ®Zuµ½í… òÑG¿cñâGX¶¬ˆªª*Ün7×]·€£G¿Î—¾ô'×\s/ï¾û.³fÝ@uu5Û¶m£²rË–}ªª*¼^“êjøïÿ^ûÀÐu=¶æ£×ë% n3¿¥eY„ÃáXÂD%í¿Å§UT1O%% .Îôi9(qêSÈO¹ª¦XW #¾öbâT¢m†aßmFüþŽDàŸx;:­¨ÅæÍ¿cݺu<ýôé|å+oàt:Ñ4-v&r:Ô××GËŠÝ'×Z,™Ø×‘ޱ÷1M.ºé¦öÓ$´€¿í¼n7ú#’êÏÙ"º"S­ !„B!„Bdž=¦óŽã¦i‰Dú-éhµY×Ççóáóùðz½±%€úÅ“a8Ómêl4¥;ñé͆{(LûуNg|Š6°쨅Ÿ×C±æ{úgmÄ@ yÇŽh@5ö˜`"é]÷1Í$ñ(úE Ðq‚¡­¶‰35Š9²ƒ®Z×M­ñjt¶Øºõx,(·ÝŽŠ íc–ꬬgݺuü×ÝF ࢤ¤„p8̇×hx ì÷ôûaÛ¶ršš±uë-±ÄE0¤ºº]‡£G‹Ùµ«†ªª*޹éÓoç7¦àt:¹è¢_&Ÿþôrÿõ_7‰Àõ×cšv“ ‡#6|½¢¢"–€ 8ŽØ<Þ‘ˆýcñeå >ÒÑí¶§_ýêèL_"…Ãö=étÚ×’½Ni|úruÿ©¤·Z÷â÷qâ´ŸêyI¬ãìÜy˜#G6QRRBCÃëÌ»„™3Ëñz½øý~4M‹Ý Q÷ަiI•6õ¸z®ëí’—„B|íÉ'ùß·ßn_HŸÏ.j±gÅãé~¡kMKJ:ÖÖ¶ÉÍ–¦ÉˆG!„B!„BˆLóùìö³ÎÚÌÔÌ^ý±Œ–iš”””`Y–eÅFV꺎Ûíîs§ývÂáäQEŸñÆn’©NìD[¦hš=ªÐTa'@]ô>á§Ft(Ꟗe¯Ø@Gí”myz ;yêëþ%™ S­Š´‹Dì€Ù*Ùöý¥FK©iÕh)¯×NjØ#}lØdÊ”G€e±C*ñ¢£¢ô¤€mžz™Í›u¾ýí)/Ëöíå,Zt:?<—ËÅyç=Ëg?{2—_nñ»ß]Ç™gƧn5ŒÑ,\xœ ¬¤iNg¬ ·Ür9N§“PÈ.J|®]ûk&OÞÎèÑÓbÉ•`PqÇá ]D­û‡)++Ãáp$õnñxìcRZj¿^­›§¶k³ŸS]OP öuátƧsH¤FWTÄïGµ6¡šÆ¸¢Âä§ÖPÕ´äÏP]·; TUÅ“þ%ÖœN˜?ÿ0 €#GvÑÒ²>:•j— ¦OöêºN$é´Âe߃!œN'ñAÃ&š¦áÕ4»PºÎü]»¸}Ó¦äGªl¹â ^ß·™‰S7vGs³÷ZkVŸe‘4Ãu×í¦¦f€Ë „B!„B!€øŒ~å].‘H$¶ÔP:™¦I8Æãñ`–e% †IÓ›Ømmj}°DìéB»ãJ¢Ïuc¯Í˜~ÚOwړרõݽx½Ïo8Õ4ðøím9ñÆÕÞ6êØm}Ñ2¥ÿI‰$EÚ©d†ßŸ¼Z"ÓL¥ÖkL|Íï”––Ž/Â鄃ò³Ÿ5‰„€ O?m¯[¨’œwÜñ;wžB Àï×)-݇Ïç­ýpìØ>ÿùkxðÁ™80c†ýz‡ÃÁúõû¨¨(bÈ“ÇÉ…ÚûÛ÷þÒ¥gqýõŽv ¯×ÞïÿüÏr ž˜IÜÏ… O%oÔ1QkNNœõõ´Û®J2š¦‰išèºëi¢ÖµT#ÍŒ„aÞµµöû;ößC!2$>õêÉ'Íôe"2Ì0ì{'´¯ÝÄÄ£iÚ£fÕçJ`ëºos:íkK%¼UÝG]¾j®ºþ #žàÜ·ošÖJ À0 t]Ç4M6n 2rä|ìc xñÅ©®¶‹ºMMö=¢ê'm×hl+±˜ão•@9N§=ÕêÆQ£ì‚F"Ìyûm6ÍŸß~ã½^¶¶Þ@Í㜕€pìPÕôûâÑB!„B!„¢{GçMMjŠÕúúú´v4 #ÖÞ ñù|„ÃáØFiašvã¡®ÛÕmÄ4z>šÑOòÔ¨éh[+‚t¼ÎcWÔÈÇì‘^ºO@FÛ"cË2…°§l­¦Ïƒ ZöZì¤*Þƒ}€Q¤2Õªè5ã`GTrÂåŠ'Ã"‘ä)ŠÛNÓ ŧ u»í¿½òÊ1¦Mû Á ý·ßÿþ Œó3ÊˈmgôèûøØÇ~ËÝw_ƒþ ˲ˆD"˜f§S' QVV†Ó餩©‰#GÆP^ncr»““MMµ,^¼ùóFuu|ºW•œ9z´¸Ã¹­MÓN(¨Ï€Äµ`MÓN0z<ösL39ΪuC!((8…#GæÓfjm4M‹Ž¬tÇe‰Ä?‰£±ËÊâ«ä¤Šñ8pR¦/!1@Ú®¡‰Ø÷¦º #>ÒXQk£VUÙ׌ºU2â×pEEr,P LÕÇíVÓï~ÕH0¤¤¤„P(¹èp8X´È^ÑøÅ?Ó™˜h·“Žê‡î`¯“Ši¢…x¯Ü€¦i8v]{­}CVW3ôwX·paò ý~ðûq8OÚ¢”7îãëtì„£+ú» _µ˜Ñ-2 ³B!„B!Ä@Sms%ÕR`éJ:ªéT ÃÀår%ͬç÷û©N\/)TVµ³yd z>M¨;áçJ±×8LU*ë#ª„Ÿ-Owë>ƒö¨#•$H'ñ$®»í¯Œøt®íw¬SÙ†$E%&à ÃN$t´Þ©ZNt ‡ãkªuRUrQ%2 ÆŽÝL  Ž ÁáÃ<öØçb£ª Ã`ëÖûY´h**Ýwß ^|q*—\r3ÕÕÕD"|>‡úúz¼^o,ª‚^¯4Q PMÓ°,‹Ë.{˜ /ÜA(dâU•µ£Ä£¦%8TÉ>M‹¯‰vB°mââ#$_}õßÙ·Ï[K¶¬Ì>fJ `—Y•G,UÓ_*N§ýáÄËf'= ÃÇ‘#c2}9‰~¤¦)ž8Ñ^Õ^Õ¾nTBP]ƒjÄqâõëvÛŸ‡O*:ö=“˜8s:ã×Vâk].ûzVŸ¥ÜqÇAvïË·¾5 MÓƒøý~jkk£Éȉ„Ãjkkc÷XbÅ*qô´J¶K &$@i)Úy“ð¯Y[ÕÓæÃ½«E²õlœ—XíbW :R†|ôG·c…ǘýÚìLï‘B!„B!Ä £âtÄ4ÍØ2Béâóù())¡¢¢‚êêjœšfO‘•R‚Ó0â ‚JWÃ9ûʉ=J1@×ɵ cXôô¡,ý±v¥hÅ^ÿ죯ƒr™Ø#6û™Lµ*ºdšñDEI‰/× t8ÚO§ª’]~¿ýx(EìóÙñF×íש‘‚ûØ&¾üåÏñØc¯F·Òý¿Å„ °¬}˜¦IqñQššÕ ÖŒa¡iP\<ŽçŸ‡«¯ž‚Ó9%6µJ*ø–SÓ?ª2$Ž¢ŠD‡~©‘Vêùݭɦ¶™HüTÇÏ4ãÇ¥-Ç~þwŽcذa±ªŒ‘H|ÔX0ØñìÄÇü~;ÎÏ›·˜–ô÷÷ޛƱc'gúÒý$²“Ój´kuµ}ïZVüúQIÅÄéPÕ5vÂ;qzq•8o;2Òã‰Oß›¨¶Vu4ða‡ƒ‘#ÇR]}—^ºŒï}oY»rÇ·“¼~*Ø×nÛÎ@±Š—Ú±p8žWóÇ'ô"RIĶ•¨´-’=,ìŠA;yèÁ®,t5#C»“]¡ G_ë…íã¶³{ÏîLï•B!„B!Ä ¢»tÔÆkš&¥¥¥8Îvèû²,¾¾|9?˜0ïÜw÷ÕÕ%w¶W ý}ašvC¢ÚF?ÌÖŽ;qW†XSÓ‹fŠ?úSýÝý½+©Œ¶ìŽF|:Ø0v’¶žx[¢ƒÞO/Û’xÄ:[â£êÔôÉÉ25šJªózÛ'4Í *±a'"\{í¸Ý_Ááp0vìG˜æ~ûÛ#„Bsq:¯Àï·§Q-+³ßósŸ{‹.šI$Rƒ¦ihÚB!;vÅÅÏáp\GU8PQßÇÓéH¦Ä¼ƒJÀ@<‘aš&'–èS‰™®:}¨$lâ{¨¤zÓìz$µ®Ã‚c ‡Ç’8¶š[uélÚçÄ÷w8à«_máË_þ--70r䅄ÿÃ4M.ülÚ$#ó±èóÅþšfÿÛé´¯e'ùT×xuµ}Ÿ—”Ø÷]â¨\Ç~,hŸxìèZt:¡¢¢Ó41 ¿ßO àË_vsé¥Å–¿mýÆétÆ*AUA Ñ¡~ÑûÚ©¬¨ˆÏÓ¬vNÓìé r)©ØìÊA;‰hbW²šè|ÝÆ@ôyv¥ÂýñÃÞš½ì®‘Ä£B!„B!Ä@Qýå;k'VK†UUU¥ü^û_}•æ?þ$ÂäY³vãø?ÿùøt½ãéùzª¢">ò¡·íp©ŒºÓ°G‚=µ¨{$domzIo² ;ѧc'!ÑwԖߟ‰GʼnpTÇÙÄ^2ÝûÝ ™juK\—M­¨¦\ …ìàWU蘒ÖZL%¥¦LøóŸRVfç4 Î<óCÖ¯ß‡Ó G„²²2^|ñq\.>Ÿ)S~Àðá¯àt:Ðu=:wµ]†)SF²wïÛ†ý›]Æ3ÏÜÁu×½ŒßŸœTÿ÷G×hëHWÉ?ǃiš8ŽØ¶TÜí®ÃFâßÛN}ªë.þvÔÓEåPÚ&7»sÓM;¹á{ZË’’gb#@¯¿¾#G¦÷úzÙÉ0ìYJKí{£º:~-ªk0Œ' ©kÛáˆ'ÆU+u­©û@Üm˲,B¡%%% 2„ŠŠ Âáp,ïñx¨­­MuÜ·n&Í÷ªë:ŽpØÞ¹‰í‚%Ì÷ìUYø`Ðbéõ¶Ï¾g {jÔî*Tª§Vgó¬«ÊŠý¿»B¥f±°ˆÏ¯S1=aÝõºB!„B!„ý²ìNþ5•UTT`YVlɰ¾2M“p8ÌÞO|‚±?ÿ9S¾üe†½újûÆÁ¶ë‡õVUÑQA½­‡ÔÚ¨TçúêèÿUû[OwÇ óŽü}¡ÖYLœFµ {P€Er²q Š“ø(È v›á¼¿ŒxÄ";Ù`ö¿ÕÛm'$Ô€A¿ßNJªéRÕ”¡jÇ»îÚÅ!Sqx½jD¤É×¾ædß>“üàmšš¾Ï—¾dB,))! qÍ5;X¼¸™‡ÞlHš³Zu¶˜7¯€W^y÷ßGG1ªäˆÙnŽëžvÌèêy~¿ŸH$ÛvbÌl—MÓLš¶±m°/ñ¶«ÑŒ½íäâr¹¨ªªB×u{¢Yå÷šLNó"¶b@©)].ûºHL6‚ý˜Ë¿Íè‡IÛëË톦¦äëK‚lËé„ßþv>ß½±Ç<@€H$‚ÛíFÓ4***p8Ô' Ûut7´ZÐ㉠öz½ñLª*@[GúdîóIÁ®D´/ñ^NVôw‹øÂÏÑÿëÄ?ôK±+mãAEôÿ‘ès‘ê½ÔÇ0ñŠŽŽ]±B!„B!„Ø?MMíÿ …‡ÃTWW§´4eY¢{zm-ÃG´Õ›©Q#‘ø:NªM<•Žÿ!춬ê¾oÂ.v;šj›+%>¥¨‡ÎGAöç:‡‰BØms.âmtaÒ¿ÆcOx¢?@ƒŒeÙ#£‚A»­?±Ûþ[[ãƒä)HÕó<{ÍÀpxZtX_4ˆiÜrË÷©ª â÷? €Ï¢´´„_Üȶmó oˆÍIíñx0 ƒùó§c0aB+ûö Iž[5]éB^zé>,ËŠ½ÞžÂTo÷|õ·T8ª«ãÑ.1§‘˜´1M3¶oüµ©ŸŸTËŸH%‚°¬ø"šÆ§,‹Õ"ØYä Õù(‰Vöx:®¨N‰£v;Ëϵ½níÊퟷuëVþøÇïsá…;Ðu=6ªQM§êŽÞ ¡P(~o&ölPs'n\ÍýÞÁ›:T¥(7Eº™Ø•°+3>âÉBøâÍj*Ôâ CƒxåLj>V}¾ê•˜xTIË vÅHw=ú|v…ÅK|ZÕñ„c&çºBd-ŸÖ­»„%KŽeº(B!„B‘÷B¡ø`ŸD†aPQQA0ì°Í»'îûÎw¸ôÿà ÿøϼóNÏ’—=íÐ_Q/|¶¶Õ%®m¨~œØíuí“°ÎaR¢¯‰øLgU¤w´e’Äã ‰Äã‚jÿW# #ž¸Pƒ‡Ôh'ãT,™9s?ŸùÌÅ|êSulÞüd¬FEEúÓ—hn¶b£C¡Á`±c_ãÉ'÷Æ’`d2M3aÖÄ!¼ýöø¤2«šÿø9ÌŸ?%)Xº;ØÝ:Œ=ÕÕ(FŲ, Èío$! ¥eîíØ|·mçVµ,ûä$. ÙödâDÐu>|ã \p}Ì,Ë>± IŸ·JK±,+¥Þ3bàvã°ÓiŸÆª*ûþèdSœÎöSûú{8u=CˆpÂá0–eá÷ûÙ°ÁàÒKÇñÄv²ÝãñPRR}¿ø'µÇ㱯+Ó´Þjxt8Ü~âl­ØWª²àÁNø¹±‘!âÓ=‰W$êÛ¼Þ¤ã^WÁè¶'bO9á#žLT=¦Ô6ÕïC¢¿G{Š=öÐc\ç¼®ÝöÕTÒ¡Pˆ“O>™–––LE!D?Ûöê6Z~ÝBó+ÃøùÞ˜Rð!Û‡Íbجfví: Ët1…B!„"oY–ݶWUÕ~6¾p8LEE^¯76ð¦76<÷Ã~ñ nþÃ3}:÷~õ«émó8ÑþmmßׂìˆZ1ݜēŠvÛ˜ý DW³ $ÕN8HHâ1φݾ¯FG©\“aØLÓp‘H|­ÆÄ\™×kÁÄ¢ò[o¿ý7LÓä½÷nbݺ~¿§Ó‰Ûí& i‘H3:m¢ÛíF×M¦L àp\ÛžÃa¯å¨Ê8þt† ;’´j I]‡ŸþôÚí{gIÂTtKn·Ã0p:±$^ ÀëõòÝÛoç;÷݇×ë%'M;Ù©PÈþ‰˜#cÆÐøÆI‰Ð؜Ѭí¦ßü†QK–Äžó—¿Ì£?úåçÇÒçŸÌ6Y§ HÒ1Ë©ûX­½ØÛÏö¾æô***0M·Û«ìø|>,ËJá«_š5‹óÀáóÙ “+HõõÙÛ *ÔˆÂÄQŽ~z>?}W‡ÆˆnG%ÕHI:Ù¾šªÕa'?½üÓöºšÑŽ$áp˜`0Hii)Á`p8ÌÁƒq8ÜqÇ™>’Bˆ ‡ÃD"‘XýãÿØÂöíÛÙ¶m?v ðDÿï  `'3fTrþ¦Ûx„f>QÐÄSyà#Z+lY„{™ÆÃÌ †šLïšB!„Bä%Õä í›ÉÔHG¯×k/;Ô«í†0 ƒTUqôèQÆ?ü0¸Ý\Ò—B†=òÁíŽbQ:š6bCñv4‹äÑÚ“¢K’xÌ–ÉèrÙñA%á{úÔúz;À™¦ýX8l'1ìQMàñÄG¿Í˜q‚@àJ{JS¿ßÇcBMÓ‡íõ§N ‡Ãx½^–eÅ¥¦i.†«šû÷Ïã©§þ‘ô7µ$¡=Ûbv%.Ô´¯š¦QZZŠÓéäPc#_Û½›¡'~ð¾½?3¯»Ž)N'†aØëA†B>|˜Ñï½j âóùì$­ÃaŸ¸ª*Ð4®<í4^/-&puÜn7Žêj\.^¯—é»vñ­䂯F¼^/–eñÑ%—0÷ÔS¹º¢‚W¿õ-&fú`‰^SÓ[V|]ÕŽ·v§»ºJ$A×u***‡Ãhš†×ëÅ0 êëë“ÓªCAÒºª‘ßß»—=EEñžm ™ÏIG5b; Ó2¨õb}>_lµÓk÷h,ËBÓ4ŒÑá4Ó–eñÜ•Ï1í×ÓxÜû¼z¯×‹Ûí¦´´4¶Ö«¦iÔÖÖ¢ë:‡§Ÿ~š7Þx#ÓGRˆAÍŠv$2¢Ž ÃÀ²,ž~z6lGÓàÓãîæÄÛçòѱÍ<}ÔE}«]ÉkÞÔÌ™g¿À¶mŸ`¥çaölßMó؇ٵkäS'NaäÐV¾ìûµk½üèGÿÍ#¥³ùö£rýõÇòûÑýUüŒŸeúP!„B!DÞQƒ¼^;——<¹EEEN§³×IG5ðG×u&z<©D|Õ„Ë]06š4¸Àkw–/ÃîÛê¦FDâ1QbúwG!‰Çl§¦m˲ìD¢¦AY™´ª«“…ÃvÒQ-“Øß4ÍÞîµ×næòê«RRòMª««Ñu‹.ú /¿lâõzñù|ÑFj7§] TÉE]×£S¨Z=–vYgpî¹3Úý-#òxÆ'1`«ùj#–eçZ[©¯¯' ±kÓ&®_»–Éßû†ç7o¾ À¯ÊÊbÉœ‘/¼ÀæÍ›qFæ{xÏ&GG-¨d®:náp˜=úhldƒiš„B!,ËB×ugE‰kë…Ãajkk1M“=Ë–qz¡è=˲+!‘ˆ}{<í+#é ®5§ÓIEEEl½Õúúz\.øýþxÒ1:„º²©‰Æ‘#“7æñÐät²ß²Ò;ÍB6Rë+ª»íß›ÿÔÌkXöHn•Ì5M3vÏz½ÞØÔÓ¡P·Ûë<àóù¨­­¥´´”êêj ÈÝÏ–eÅFS†KJD"‘vS:‡Ãaþ|!‹›³ùºÍüÜø9^¯MÓÚ%‘“–………™>²Bä%Õ™ ±¿ÅD"fn›É»ž`ZË4 ²i÷tÞi|†l<ÌcÖ¬çØ±ãBŽû8ÍÍ“Y´¨ž#Gžàǯ–¼Å”sNð‰ÝMÜ=ý}6¼üg/þ4?ùûwØ¿ø,ÓboÉl…Åʱçô=ûø1^9g ¾¸€… ?‹®ëÔÖÚõ½ÖÖV>úè£L2!„B!„È;–¥ü´_ɲ,\.@§ƒv:²ék_cZK ¥UUÑÁB).c\8Ówùá&hv¢1„Râë'–a·‹9‰OYš«bÇALY*±§<µ¬ø²hn·¬; i ÚÉF{d`ò6Ôïªù wàtžŠe™L:Š{ïý<3f½¦ò&J*Kðûý„B!LÓŒM¯\UU»W“}ê>u:hš–Ôø¯âhÛ‰kÚ†ÃaÊÊʃ±Ž‹¿´Âðæ¼71þ׈mK¦T"}¶þïVþ¸ý^Û6œ]»¦³pá:Fn‰ÅY»Ó½èëŒo³m[EE wøwüàøÞz:ntŶ䫼¥½Å‹Lå36ñ×®`ÔGuüÛ”ñœ>{-ŸüÄEüáoç3é“{iºp=³®œ…ÏWÇïç_u;0}».PD§s:|3ºq&[“Aƒë´ë€hÌ6 tËŠO+dúÐ !„B!D^1M{@PU•=é]"5½*@uuuÏÚnB!˜öÎ;l»âŠØ¢Ô 8PmKv'´õ©åT‡| ðFÿíÀNHZÑ«çjÑßIø¿”$ñ˜eÔȧÄÞö¨F5]ªÓiŠê.&9š¦3iÒ6`¦À²®Ãå*cÔ¨Ÿàvk„Ã_ŠMå©’_j*Q°§Q E'¡v:é h]î¿…Ïç‹%?Ô{—MœÈúàÆk®aô·¿¼ó8¢Ïk^¼˜®»Ží†Û+ÂüÕ¯¸î’Kxè…˜0aßxƒŸ?ù$`7Äݶ¿ŒÍCS¦0ç‚ 0yÏäɱÆÄ/¼ñ^/þo|MÓ’>‚Á .— ¿ßÛíŽ%Ô1;Yàóù¨¯¯'‰ iZR2A=O%Û~à¨ãÞ6v’Q”ʉD ŽO§êñØÓ-¤#WlYV,¦¦\P#nÜnwìš ‡Ãì5ŠéGŽÐÒÜ –ŧæÍcRyy|c^¯Ý³!¨ Žª¨E°+/„£Ä‘Fš¦©ˆðÅu_dØ—†AŽgXó0NŒ?Á+_x…q¿øú©_ÇívÇF„ú|>ª««ùõw~ÍMž›˜ªªª˜bNጡg°îºu,þÒbj¿Q‹¦ihš†ÓéÄápÄÿêmÛ1Cýîîôº®Çâ‰iF¬2·ì‹ËXw|]¦ÏØà *×"¯ðÔSG¹öü]üÏgQË,ù.cŽNç¡®Dg1{ò/ùøÄëùÇž÷™û±Ó™¸ö/¼¼mÓYË¢™8´õÇÏz‹ÂÑǸÝýÇïaþü#èºÎÇ6aÕ’"0‹øÆ0 vì…?¯†õ&<ÿþõ 7üipÕ~|Aoˆ÷NSLÓ®4ªj^¯ÝsMÕ+|>»× ØJ]‡É“3}˜…B!„"¯ø|ö×­¶IG˲øë¯çÆ³Ïæß~ó›ž%÷»TŽÏuõõ,<ãŒôÔ¤ûQ‹âmr‰,›h¿n¢‰=JÒýñ‘<²Ðý»#ú|u˜·$ñ˜A–e·Y–ݰešv;¿e%O™š8«^uuÇÛJœÚOMuêóù5ê1þþ÷áóe÷îŸSQa'ÛÞ|óß°¬—àtÚÓ¤ú|>LÓÄãñÄ‚ž¦i4¥qY5ŒÜ›0â0¶n\$Âá;cû …ˆø|,òzÙ7d§œÂÞ¿ýï½ü2÷¿ò >Ÿ‡ÃAÍO°êþûYµaƒ=eis3ftÔa$:¢Póz™¢i¸£ÇéHÿ%—ðx<Ìxøaf×µ)¯J ´M$$Rë/‚0ìèC%wäuòÚèËè¤ÞÎ.ÒÄÂþðÔIþÐ턚Å×é´+M³Ðó÷¶ìFe`×oËó#Fðê¤I„£ Ñw-XÀ7Þ~€é]ÄŽ7Þàüp0h¯h ýÎw¸üÇ?æÙ—^` m>ë“Øft£íÜèÑGôññÊ…Ÿxï&µAvâ°*ú3áõÝ]òªSF|š‡è€¡ãO°aØ n*àÑwåœÓÎáž?Ýß½ ¶&圃sؾx;wo¾›+fP÷^ /äëÿÈMoÝÄg^ÀŒ3ø©ã§L_5âSŠYª-Åô²¯d‹.¦È[„SK¸øÜÅI¿÷%‰Ø𦵛j¢Ç(6à[F<÷; »gŸYˆ<¨)•ƒ²aÃ~øÃ!´´|›ÓFý‘<ÿ¯|4öe^vš„vŸÊâí'ñã _gç‰SؾùBþsc מ>–ßw,–ïlÂëžååÂ+y°p<ŽËJXnšv2'¾èöÑX«¾SaÇß+4ûïž6A2¶ã¿šG¿#j½èhX㓪HF¼"ÚÜœéS ÚRkÄ{ëÄ;ûº_ (++ãèûïóß/¾ÈtËbB:“ŽJ*ß+G;¶•8Û˜T cÏ.f`·ñÉwš¼%‰Ç 0 û'ж)E× íøâìA¦_b ‡Ã±©<-ËŠzSsDÃÀËš¦%$ÁáÐbSª±„cªÖ†a ë:û_}•^qgúÓL›6Y³fñ¹ÿç•W¢ë:º®³ë®»ØW^΄hróoS§R½s'm<7MÏ<“š#Gp»ÝD"Š"&Nœ+«þÐCÌr: Bl]³¶©š¦ÅÖ²«ªªJy”`O™ŒFÌ3>ìDœúé S€iÚ?`¢ivÇ;DŸ˜˜ÐN쉯œN>|èCÜö Ÿ úqXcŽa#0mÊ\° ¾N¨aØoÍtn‡!:%°ÃáÀëõ2íóŸçž³ÎŠ¿¯jÜTIÅDìJÑý¬ ždôaW.ÔàH;I‰>挾>ý€ä‘‹j>x'˜n3–u8˜¦ÉÑÿ9Ê¥ï_Êç.ý«Ï\^ª¬¸Ùý4mh¢`Q_\ÿEFlÁÿý {nÍaW~~8àsæçp8|[ÿ67˜7$u˜jN…©°4²ÔÞ'` ˆÜ˜¯^·\(k>ˆ&yc w9îFß§‰NŒ•ºëW£iv8{æ™õœwÞLx—ýû'±3Z_8xð §žº™'ŸË™g¾‘P¦ø†.Ù} [‹¶òå7¾Lss3_bM|†Bޱ›±Œa"®Â?òFÁFîÉöc7Ñr\£ììg¸éDxgnw„Ï­¾&Uð_ÎóˆDйÉ7/Áåe+NÒàïõíTIIü÷êêxÅÏéŒ~@t¡»ú†娞ÛÙóOÖªU};q¢XØl<$¯1!ÞÙIMÞ$6¨ÿ°§T²è8Þ©8hE—ÑàB!„b²,PMòOò„}‘H„™W^ÉU|ôQÆ}úÓÉ/V Ÿ£ÅÅt:©¨¨Àãñt9ˆ%-úkóm×€TÉÉ,™`Mô/I<HÄnTS G§Óþñzí ÔÝ`Ã0âkFlAõãõzc#ßÔóœN'¡P·[#±×S#ü”ÄÅk»[ÈÖ4MG,±øúÕW3~üxžþy>uñÅ4ÆÃ böúbc6mâ?N;‡¦æÈF-XÀõçœÃW¢`~¿£¢‚·N:‰GfÍB×uŽXVò›jÓ5-—œNgl*S•DI~zÏZ=OZG(IRqña7þ@=ñ‘O Ó.†ÃZÕLd]`ßç±ÑÊ01l×FÀnüN± ØïÆhìÙº•´°iųœvh/åÛÊY6b¿ûÂ&š&LìkY³4ª]$4&/ét:ñ )ÁaÚkzt˜ —FŸSÝ/ñNÕ[I´ðŘØ.®æoOTmu¯cqÉbZ.j¡ÀS`Oçì¶cˆ¦i4^ÓȰG†Q:¶”ÝÞÍ¡§qrÍÉ ;wÕoUãÖܼY^øÿ?&8'Pukº®Ç*]³˜e¿ççÞÿJâk3Z@Sû‘ÆíîY5O}ââ0÷ØÊF 6å­ˆžO¦kd$ñ˜0è]wdRÉ;u¹‡ÃñM>8F#ÀúüËàßÿ¿}ÔÖM ¼|••3’Þ'X×»€ûï_Çm·-NúûÍßÍŽ¦‘D^w°hQ³f5·ÛFyùƒTVÞ€g¼ÅÆFQÓ2&ö÷»ùĸzîý`‰]v\<ÇŸ8Á †²ã,*˜À"Šù4M±qT2 ˜ÀÜa‡øÔ°é\MC”H}îxè<$>*²­ÄQ‘ïäã$ÞY‚ècª§1Ø7‰;é©a_çeÄŠîèß,⟕!’“ªC’ŸøL î„r9£ÛУÛŸUAÕ1Œècêujtg º]Uó&ü›èkÝÄ;Jy¢Û‰$ü]KØÄ;‘xïÌc\/Rû¡ÊëHx?õzB¹< ÏWÇuÿM<ò¥ýüäÅŸ0áê vZÕkuâu[õ]ÂOûïâuUõÝ#ñ;„© G3¹ Ñ[’xì'¦i7ø9ñd£×_Ë­«ö&5mªJ2ªßUù®ë£S&ÆÞ,aƒ‡ƒ5+W2kÃæ^sˆký?%‰ÄFCvµN£šæÔãñðÇþ§¦ñ /°hÑ"–ß}7ÁêjÊÊÊp:\;bç̘Á´–v†I|Ô¤aÀćàÒèö¿Òæýôh²s1½“˜<í ™žTôšúpV Râ Dˆ<‘õ Õü–ð{ÅèÇÿAZAtGÕ¸¸ÔKÝp@ƒ—4»â0¨‚]OìâÐFˆ á1 œ9ãmê¾]ÇóžçÜñçòͧÿ/>WºjÀôD\vyb yÕöó¾YûÍx¢$l¿Õĺlª‘Ì„Ö`+ûË÷3áÿ&Ä…ibY¦iÆÖU!Âáp,œÛù¼|éËÜñü¸CîX§õz]×a><yýs:n˹Ôd¡{! YŸþ&ÚMuÚ%5%«;ùØ×öýΦŠƒ“jD7±×1pŸf¸§½Íh]?:ͺJ²Ølçi>Ó~Üï‚Nþì;¸oO¯òõ?Å_¶žÅÑGhiiáÉ'ÿ̈1MáÃßå·¿ÝÈÆK(§œ×x¯q#ûøXÏz^­ü£˜J`ÜE¼rô^>ò2×p ozÿÁ"*Ø~ÛÖ3‡‡FßÉû‡ÇáëÆñw¸Œ…\{äfþ·òqBÚYyÎJ.ÛzÃÿv.7ú$ãþµ‹¸ŠxêÐ?¸½à»ìû`"CÏÊëÏo¤æ´g8öîÐG:vôÛ¼9ëMÎ}ëiú cŽŒá@É ëßâØÔÓøÆ¾/û:?Ú|€k®¹†!ï á³~Ÿ}}¯3:t»hþ/=l"㮇§â:¸é&˜?í·‚9ÃA³e@è!ûà܆ÝM5±_–a€®A Ÿ?GQ ÇîHÒqð2Iù¯‘<Ë€J¾©éÈ;£awzRÔ罚ðÄK<)¨’ym_¯aNªF¢ï[›P&•H¬Ž>Ö”ð\µmµ-•PS#&UÒ-±D'>C„ê씘pSû­ÞC•­,áõ‘„÷Uϱ ò àIÐÏãàtÐ~æÙÀNàÿ®Ç;àø0ÿxô €1tð;оÆÀü;8‡Ú¯7|`]€¯÷ÿß lõ"8'B¨¨Äîüô+;¬h§Cä[`틟fSÁ\î¥y ÌMÑêÆØŸ €ÿ~ðý7püG£“2,6Ûwø>„G€~ÔÞŽozôØ4Áÿ9ðý Ì¡à.²ËúÁhß™à= h”'!„BˆIìàVÖO òýu±¾>ú•Ï4yìÎ;Yþä“èºN}}}ò•Ô`Ãm˜»q.ÞF/'ÆŸà/½ÄôßN‡ÛK€›£¯Iœ­Ì"yS“亴zL=ÏLx_Õ1Nµ-J8Ñr.ñ¸jÕ**++inn檫®båÊ•gºXD"vbYY|Ê05¢Ñéì<ÙØQ‚ÑŒYp:ÜxÍ5̘1ƒâ³ÏN¡ãóÅßXMŘ0Ö¬aÃÀ4ù[¶0ÂáÀãñÄ’—@€›ÇŽåï?úçœsûöícêÔ©œQYIuu5Vt$Ö7ƒAZ¦M£hÔ( ß}—W¾÷=&;í%0¢MÄÊÞïÃÀÅ 5àqÀG¼P-±dµ\—sTÜúpŽIù¬É¬¹k3'z'~üèè”QÆIáÿ‡1ÑB;CÖâòé÷rÁžL²†òöŒ[h{ 3öÎ`Ìéc8±çoŒ>´s¶É¼ÆSøÓ·žäÀäõšÆžu{˜÷A!ï¼\Ïwgæ½??Á×.žÇ=oŸÉ—§,eݺI̘1ƒ)7²gêqƽÀ¿4™´.<ƒÿ8ú4~¿Ÿ‰eyå{ßãËw¿Á¨3/¢±±‘Ÿï<ÎÆç1ô”QŒÝ?–³?ÇEõßàzàðŠ/}ò“8NF²ààÉìy¸Ž!;Ö3ª €sö­y‡¦ÖV4S ÿÃ- Ý4Áí&”èûê$8¡ã$àŠO٠Éфa›úšÿ]×ÛWÞ»g$/Â-2&+¾$¬³‹ŸäÑyªç±Jþµ]:½¯Õe5"R56èÄgbP£;¡–÷Ô£Ÿ±†ˆ«fyW(p8£$LÓÎÅ[Ñ端!ºnßQÓÊ{¼ñü½âwƒ/ÚÜí3m7 Ç—°ñ® û÷ÖV2$¡ÐxñÙäÑï^_Âs¶BÓŸÁ5xÁ^Æ"c}ôvÞ ú… ½á줜BûßF˜b'óLŒÉö±Ô´hbsœý£_†B>`:è~°B ábñ„jE4‡œØãÐÆƒ¾¬«£ÇÝ æ¯ìä!S±g¿g{hs@û!èÐÏÇûÑí¸À<ô'Ày hŸï_±„¯ A» ¼ç;A›ÖApÏó‰èïcÀ1ÞûÉ{}¼³CVÄ‘6jÕ‰Î$Nñ‰Ø1(q6ˆŽ^¯–7†ä˜¥¦tO¬þ9ö=­V¯ðzãM0‡ýšÿ»ÛŸå*‘Çídý·Ša*^¨r¨}дx5C íIsÀŽY.WòŒén·]†PÈþw¬cñý ãSÿ©e ÕqVmWºÀV¬èfÚ÷,'±@1 qà. þfÀBŸª®‡ÚgöãWÒ¼jE[·2¹ ÿ½÷Úíaì荒]öÝÏ3¾gøèåõ…QÌýÊ\†jC™Ît¸¶ƒ÷m»<’³“+‰_Y;ëX_ý"§*p¨€±jÕ*V¬XÁ#<2 å0Íx¥Òã‰/Õ Ú=µ¬Ãa7ì·M*ª‘B˜&:pdþ|¦.Y‚®ë¸ÝnnzóMF×ÕÙoðµ¯ÙjJn¥hyé%0ú“Ÿ¤þÎ;92}:¡Š ¼^/¡P¯×KIEÓ¦1bâDÖ8ý~<áp˜ûØÇ8øpFO˜ÀóÏ?ÏøsÏ¥ºº:9aØÚJ¨tGŒCzê‹ ê—8 ¦¹R"mþÜ`E¿¼ú*â1Àé´zê?G4IvKÒ¦#ÞhÇ‚°I쿊hç‚™Nt]§D+Á¥¹ph®Ñ®á®‰o mÅÁA¼Ñ2Úë_ŰïOÓíÀ`Áäa“ùø„óŽþ>Ÿ¿ÃÏçÃãñPVVFUUTWWÇF/ªmY–ÅWÿØÞgŸ/Ö)"qj玴M0ÊTÄ¢?¤-X¼hÂ|=Þ(|¥o¥ÃX,rC½'6 ÉÜüá¿ÅÚV‡qú ŒƒªÆ‚ë è§Ãòë6ñ% ÆÕ›Þå†é£Ø:·Ž/=÷-8þ¿è:;~µƒbV3~L3E;ó”)h-—®»092ºŽaqèäfFLZÁËÓgá¹ÕÃs ‡ƒ¡¿ø Ÿ~šó?:b_é¥ÜP{Ý÷·\w @€Qw~ƒ)S¦0·q #|“’ðBž»á,Ë¢yr3k ×¼RɉÝ38ôéó9>õ8‹}‹9®Ç鈠ÀõZö¸ÀK@שNWÞÔԦɬíÛ˜­-j—´»"_ˆÍ;šxxSõ޶k\LˆþÄû#ô0CÓUÌq»»žß¾»NSªµNµŠŒÊ–ïˆÏ Fÿ¹°¿Ä«Q€^:ìIlñ%©ËK5Œ;ñ†bÅãŽ/ ívÇ—uPtÝ~¼´Ôþ½]2»1]5Æ«†vŸÏ~Õ€^Q¼!ܲâ-UwÛÉ #šØLx\5Ô«[G½_âß5-9Ÿ_]üwû»Uü¹jmGû=ÙÇÈi¶Ï|[Ç“°|Ä÷nù_†8ûó±ã…hÎYIå{àŒã¿lƒ¦gŦ¢¶,¨(YÏÄõë8|ø0»ŸßÍðÛnÃ霆a„B‹7l`Òþý±Ílxa<æÂ…ñó<n©´G™7NÊô]»Ø°oæ’…„ = 3sÛ6έ|…£G2bÄ>üq  ÐuH~mX¿žE ß×OœH`Ñ¢Øï‹ššD˪TΘÁG3f`÷nË=Y ²„ê­fXP÷‹JÖ%NÏñû9²Ÿçñ$'ÑÔ, *ÑÉ 5õÇŽ†aoO-U¥ª¦ißã*q¦’h‰«­x½ñÙ£âɰøßuÝnwQq­ªÊþ{bìSm2€ýÿĤ›*‹zz~Ûø©úv«Ø§öGÅëH$ùu*F%ÓŽ&¨ …’c¾:®ªÏSbχ{×ñêñ38{üÎyèd.zj Ö ­¬/[Ϙᓟÿ$?^ýc6ïÞlÏö½Ü=æBt&§kÖ¬¡¼¼œòòrî»ï>œN'k֬᪫®êôuàСCñT’AoóïFú>F;`‰ŽYÆŸÀÜú q}iº£mòhX:’¿|a'ó?<Â+ÿ|…3×>Ä9›ÖÄÞj;‹©`ßœðM–ž¹”]“Ky$¡ Û ®}ˆ­§Q¼¥˜]Ïî¢åT‹·OC;K£úX^v5ß¼ø&>=îÓÝr”õ×3kÖÍœôÚILxz›ïÛÌu×-fò‘ÉLüáD–¾¶”ƒKòÜU8Q>“§z¹ëçòî/oÀß–w¡xï¹¹j ˜®æ†ä»mzïÆ^ÉkÊtôœHúß§yU3£FbÔ¨Qñ9¯]¼šÏº«÷Qû&>VÛ²ªkI=?q=—Žž“øïÄ÷øÐx­ƒçtò>Û¶mcÆŒñç@|4œÙfû9®¯qààÁƒö?"@À€ˆ·k0ÊiW7°Ý€ßúìuÐNŒÃ`6Zãç)»k>†§ýõçùîø\ÿ6ûv¾ ‚ïÒK£ó_[‡Uq:±Žš×žî¸£¾a8Ìøˆª“‚®ëvÒÐo' ƒÁ %%%TWWpbӪʣšRÙ²,ŽÌ?BØÆåp¡ëzlMX§ÓImm-š¦á÷ûÑuêh Ÿúâ:¨Ý­›mêêê˜7o^¦‹1 ?~ °°qãÆ1þ|Þ,(`ìØ±>xú ¨omeß¾}”””°k×.¦}ø!op¸¤„c|ÀGgŤÂB>Ì®]»())aõ‡òtA‡¢¨¨ 6dgžy&¯¼ò ç|á |¯¨ˆ)S¦ðúë¯síµ×òÚ¶m4oÝÚý=“¥RŽ–Ï nó5(ÖâßË&ZnóÅÌ­C}´>¯5¼×æ à­NÌ¿‚¹t7ß·¾Fcúôf´ËO"òN1æë •€óŠý„¾߆ÑX„ÿGÃñ}Ǿ/ÜÿæË»ˆ¼:£Ñ~L›ØB𸮷_S¿>[ïg÷Aá"ÏÚ‰+÷u‡Ý £±ç,ûsžò!‘ªbãÀZf o€cœ=2–MÀÉÀ6{Ô,ûÁ¨¶ÿ¶gÏŠ Ž3|çZߟSã£:‹/ÚÏI{¦QTpœÂ‚c0þY½žïý‹ÿàŸMüðÊfFì?Ìh>p€ ¶£aÉ1|¥ X¿~=‡yòãÍìj™ÄÎÓà¼øƒ]|çfÍÛfa>ÚÀM ÞäîÂa±ý}Û<•C“vó@ùL<Èú?~Ä“ç¾ÌIÍ1r{†±ÿ‹ûwF³̦>o¾ÅmÞ™tÜ"o2mÂ4¦µLã®ÿ€‹x‹eÆ Ž¦qÌT 6æ­Ó,b1õAØY°“ÍLoÚÅ‘h¬úg ˆûÑÑ©A€„ øC P„††…ÅÇØÄçÍDìYµ À:Ž1ŒÅTÀÄäN±€˜ý«Œã(뙈“Vtt¶=h¿OS›‰‡FMáÑYçshã!,,>Owq8é9ßd<—¬¸¹ŸîÔþ—r,ÈR*y8"7>ø€±cÇ2f̘¤O–ƒýø3Ïì㢋êxâ {>îE‹šØ¹³€; bï3mZ ‹5ÅžsË-oóàƒ3ÙµkS§Nþ#ûöMdË–³™:µ‘™3‡òöÛ'8|¸€}û&pé¥OñüóK8ÿü¿³}û,víš{ŸÉ“·3vìn¶o·¿•Ìœù o¿} --- >œ––¦LyÐii™FAÁ_ؽû’¤ã2s惼ñÆ´´LcÑ"/›6ÝΈv›Osó,f̰;ó44Ìᤓ^cÿþm9r;'NŒ NaĈÏÑÜü'âëh¨†D(*ZGsósØþè㥴ŸV)L¼ÁM-ô¬¾©Ç_§z§AræZÄ:ñ9ñ†¼E‹¼¼ñÆ=:Žä^o¶#²`Áݬ_o7‚Ž¿ˆýû“;Mú+ví²ß·  €)Sv°m[òw´Å‹oã7>—þ y€¤-ìéœ;r7“¶Mâ?ÿý?™öÒ4ÆKùgËíÏ—è7æKÇ] ð=ÿ÷À—^z)Ã×0ö­±,Õ–Â ìéLÚ'³ yÞgƒøº2êù‰É4+á1hŸ‹ÎO”œKL¸ÑÁë:*—Õæß%ê [`E,&L˜À¨ñ£âeìî}œÉÛèðø¨µæÔÚmÖÛŠM«öç~Gï“øÛPõ…P´¬ÞèsÔ^ƒöë÷ÑrMöFO|N⿉¿î¬÷Î"¥¶oßNdæƒf#žÖûp,Öa®ÓïMê(8…»OÜ˶='ñîÁ“9eT#Ÿø6l]ôg|¾7Ñ ƒFà 9žsOœ iÑ"ª««),,äÈ‘#ÌŸ?ŸÛo¿E‹1mÚ´¤õý~?eeeøý~JKK©®®Æår  ‡Ã±$¢ê…ÄzË%þ¿ÝåN¬ZµŠ%—,‰%¤õb!õ5S³ÑªU«X½zu¦‹1 *++Y²dIÒý‘¯R­”š'ãû}=Úð"øà®¿Þ`ܸq0{6KFXœÃ‡SxÎ9<öØcœz꩟ê'žàw.ßøÆ7ðù|\~ùå˜&°¯µ•7²`Á4MãDôs¦®®Ž9\Àê?ÿÿ7¾A¥ÏÇÇtÀ膆LßÖ}’–X01ñNqÂ:æ9~Ìßã_@»p;¡ïnÃ:Q{–gx#¾:°Ž‚ûjØôÔ^ÞØ7‰õ'fcµÚÏûYãf¾òÓ3cÿþñ/§¢ ٠째ò¥×xüaj^ŸNƒc/Gþñ;޾tjì=ÎjîÝÁçoàçßàâºç¹¸ùCŽ 9Æ!CÒ<„‡þÓ¢Öñ5Ž;†ÿ–_°o؆ Ë̯}ú6.æÿö¹xóà›4üæÏ<³kCF áøÛÇimmeŧZðòSB/„YξI|$p!oqá½sìNÌ@Ù>jÛ|á}úï ÙÇb>‡ãïÍü/ÿÃö¤ç|}Ô>[ðK8À³?Ë¿[búÑM±¿yc:î1ïÐ<æ™Ë˳_æ?ÞXˉ¡ãí' WßÊs®äƦ²ñ­=³‰ Í&FŒAëG­,mÇ×ßýˆOÿ<‡âù“Ÿç´Ç(>|€!C†pFkGFÍç¡cpSëMìÛ·ç—>Ï̽o2zôhŽ=ÊСC± Æ0±`!Kv.á…_`ÂÙC˜x`ãÇg¬u€ &P¹ÿ]nñy}ÎëŒûp('?†Û¦Œ>­ù œõ [·n¥èþ"¸íïœ9ýCê[ç(攂Íܳà"æ¼>‡£6rdÑ&xd ³fÍbëÖ­,Z´ÖƒÊE•¬_¿žæ+›÷ƦŸN3°óЇœT8…JåLû9‹Ÿ]ÌúËÿ¢¢"š››™:e*û&6ñoÓOc®5—×G¼Î‘E›xåÉ ˜uÖb¶­™gžÇÐÍßÈô-Ýg©Æ‚é¿Ýµi<¹ßu›n7-U€õ‡Û°š·ãˆpFp–wkv#ÿUßyï}ç`PÀ9ám>˜ø1^3g£·˜}Òÿ²æíÅD>±o»àQîÿ‡Ý{àS…orààAþÞï*èàC.žþ þÒøUî˜r+?ßýC,NÂ…N gñ6¯±\À$¶Q[â.OÚWƒp÷c¯Tnab4fñøio±ï]Ÿ=ƒû?¿Á ³”ŒF3ƒÃŽŸD=§°pÿL†îÎì×þ‹é-g'lÃäÝSgS¾Íž;mÜ¡­œûþSX8ì¶TÀ±íZ~tÚn>ûîg1³§ÀÉÛ¾dCCÇÀ1î|;6KÞ›IáIW³“_p´i ÏöH³SÎç{ëìÎScOZ·ëo‚–„ýÙæâžCø—ãå8v-ä£þþLü -P¨Ý@ ;XPç`ìÌ›áÄó¡m¬k^ü¯|ü%û|í+ñ1¡>ù:Ñp±úŠ\ú7pàfÔåuìzÖ… ‹ÅÀA&œ÷Ÿlþÿúòlç>Dѱ (Üú :°˜WËq‹+eë²û™õÈØß-èë/æÇWDøúß>/Ö8þÂ`*»pðÖ¨ßóÖ%orÑ gq蔿P3ã¯íAç-„]:÷\ñ>—ÿ͉ÖrûÏ߯©§3üè»\†Å©èëJøä’okûó–íi©¼c¾òIB[OÅòßT¼­ÖNä—”ìã3Ÿ9ƒõë'2cÆÛ,ZäÅïáóí㢋.¢õ­üd×c8¾ð™/  Ç9ý‹§3ýcÓ©¯ïßé¬óá»`>´m Ö¶ˆ¶†´¶¶¶¦¾™þWSSÃòåËÙ²eKÒãË—/èò¦ºúê«9õyúCšie/‡[Ï`Ĉ‘=úQôY.¿ª²‡Ã¢©©šéÓ§ÓØØHii)6l`áÂ…ìß¿Ÿ©S§rôèQ¦O·{î455qöÙgóúë¯sþùçóÊ+¯pÙe—ñÜsÏqþùç³uëVfÍšEK‹ýI8iÒ$:ĤI“úå˜=ùä“\}õÕ:c™±nÝ:¦OŸ;'ƒEOÏucc#¼÷Þ{¼ôÒK™.v¯¥,XÀ¸º_²•©4QHk놽‡'fš¿”`âpXœ8q‚ñãí/»GeÊ”)lذÇC(âž{î! qõÕWóä“OröÙvÅ[ÝÛ{÷îeÒ¤Ilݺ•Ë.»Œ;vľHžzê©Ð_äžpà›6mbçΜûb—jàŠ+®à•W®§¹ùK šØ‹3û±cA{:ŒÄ)3:>×Õ÷‡ÃKº9r„±cÇòÁÄâ‰úž ~?í´Ó8pà………±stÊ)§PWWÇ5×\C$aîÜ¹ìØ±ƒóÏ?Ÿ 6 iZ»×œvÚilÚ´)V/Qõ•ÄzJSS£Éõï×_=é5ê¹*ÖAÇuõ½G½Vý~öÙg³cÇ&MšÄæÍ›1b%%%ìØ±ƒ³Ï>»ÃïJ“&M¢   –ø{„aSSSRLmûÿ½{÷Æâ¬J¶´´0iÒ¤._Óö÷––N=5žøùË_þ¢E‹r®Õ›ø·yófš››Ù·oûÛß2]ô^K%ÔÔÔàõzy}í/in{|èÐ?qâÄÛØ==#Øc`ÕèÕÓ6„ÝsÔý·ƒxï]˜8qMMµ±k¬«Ø0jÔ(,ËŠ=GÅ“®bÃñãÇinnî4ž,\¸>ø€“N: °{Þ±aÖ-[F$áúë¯'‰ÄîÙÄx2cï^¦ŒɈ#Ø¿?óæÍãÞc÷ùÕW_;?þ‘Å‹óÎ;ïPXXÈ߇îûÄØ÷žçž{ŽË.»,öš_ÿú×ÜtÓMIqˆÝ«*6¨2%þ_ň½{÷Æ^³wï^fÍšÕ«×ÄÞO•5±î¦â‰Š%‘H„k¯½¶Óx¢¶•·&MšDKKKÒs¿&Æ Äø•ƒRÕ›úߺuëhjjâœsÎtßþã?þƒ<Ò„¹ÝË®Ö3cÃÅÁØÈ´ó˜Äû”pœãLÞš©`Ô¨¯päȦLyŒ‚Ý×QPP€ãÈ>>†>ÈŽ!C9òLZ[›(=yûÞ>Á)§œÂ{ï½Ç)§œÂ_ßû %%eìÝû7¦LÉi|À¤¡C?~<û÷ïgÊ™grßK/ž‡”_q{ÿö7Î8ã ,ËbÒ¤I¼xèGÇ‹}Æ_vúéÔWWsî¹çòꫯ²xñâØ=¬î¿3¢ ÂÂB8@ÑÂ…üfíÚØ}þ™O|‚÷þò—¤ûÜ ûtÍÔ©¼ñ ,^¼˜uëÖõè}Žvxån¸á†~}ŸtïÏÚµkimmå²ãÇ»|ŸÏ_tõÕÕ½zŸ—\B°¶¶Ëýi=ã OˆÃ½Ïäa³8VxŒ†ƒ \3u*ž±;”m:¶‰kfßÈß}†k?v-¿ø8§/<3êë),,ÄqØ;áƒá…¬>ö< 9Ø!)Õï_|1£ÖÞëœÅÇGüš'‡1zôKìßÿöç¿‘#?ä£^fá¢Øç­Ãá`âĉIŸKéŽç=•ßûó¡3×Û"6oÞLcccÊm†ƒ"ñ¸cÇ~ûÛßFƒ·‹††ƒLž<™Ñ£_ŠUøæÏŸOkk+………œrÊ)™Þ]!úÅ|À|ÀÉ'ŸÌµ×^›úXª•ˆÇœÇœ‘#§pàÀl>Ìg4ñá‡ö—Á!C†pÉ%—ðÏþ“3Ï<“Í›73}út‰ "ï¼ùæ›\uÕU© §*uÃ0˜1ãrÞzë³g§µµž3Î8ƒ1cÆñ/xsæÌÉôî Ñ/:ĶmÛ¸å–[RÛX¤Z'X·n>ø, #8ï¼ýI À³gÏfïÞ½\tÑE±º@ÛFÿÂÂBcõ…óÎ;-[¶pÊ)§Äž'D.ؾ};~ø!gŸ}vN6ޤ |ðA~ó›L›6ãÇ3w®=ŠøÐ¡CŒ3&)6\vÙeI÷}OcÃ?ÿùÏØÿU#š|¿Ùf°?xà?ò÷¿`æÌ™ìÙ³‡Ù³‡sèÐFæÎËØ±ccß æÌ™Ã–-[ä{‚È;Òfø8ÏÜSÇÐÒ÷),,Lª Ì;—ãÇÇ>ÏÏ<óL©ó‹¼¥¾¤Z'È™©VSqê©§âóù:øË¿fºhBˆtíµ×ö¨ò¤F}\yå•™.²ý"×F6¥Sçu!Ä`²xñâ%YzRPÏ̱Uä®Á~ÝÞrË-ô¥ïE_bÃ`?Ö"» æëóÔSOå»ß½½W¯ÌÇKˆ|ÕÛ6C!òUº®ñ¡™Þ‘Þª««k÷X®/š*„è‰BX „8 „°I,B€Ä!„Ä!²EÎ$U¦uãÆI×ÔÔP\\œéâ !€Ä!H,BHBØ$!@bBâ€Ù&gåååTVVÒÜÜ À<@QQK—.ÍtÑ„Dâ€$!$!l „ ±@!q@ˆl2¤µµµ5Ó…è©ææfn¾ùfš››)**¢¡¡•+WR^^žé¢ !ˆÄ!H,BHBØ$!@bBâ€Ù$§JMM óçϧ¨¨(ÓÅBd€Ä!H,BHBØ$!@bBâ€Ù 'B!„B!„B!„Bˆì’Sk< !„B!„B!„B!²“$…B!„B!„B!„)“Ä£B!„B!„B!„"e’xB!„B!„B!„B¤,¯«V­â¼óÎcΜ9¬X±‚†††L)%kÖ¬aùòåí~êêêz½ß¹pl–-[FMMM‡KÇ>fë1èl¿{rþóåܧ[¾ísºbA®—TbA.ßí÷`ûH·|ÚçÁx-t ÒµÙx¤Nš››Y±bsæÌaΜ9,[¶¬Ý} Ù[×]³f N§“9sæàt:Y³fMÖ—»¹¹™;ï¼3i›ý+ÓQöÎîû¶ûÑÑñO×ñ•ØÐÿÒ 2q>»‹ÙXîžÄt•+]åN%dSL]ëI,ÈÖó9u‚t—;×êÐq,HW 'Ï‘8y÷jÎ;ï¼v×u.ìÃ@ÕòFkžºçž{ZKKK[~øáÖµk×¶^ýõ­×_}¦‹•ò>}âŸh½çž{’~Þ}÷Ý^íw.›P(Ô:{öìÖµk×vxRÝÇl=ÝíwWç?_Î}ºåã>§#äÊqI%äò=ÑÙ~¦ÏtË·}l×BW÷D:ö1ƒÔ ò“:Îk×®m]»vmëW¿úÕÖÒÒÒÖýû÷Çž“­uݧžzªuöìÙ­¡P¨uíÚµ­wÜqGëìÙ³ÓzÝõG¹Õ6žzê©Ø1ÿÄ'>‘Ö㮲wußß|óÍ­¥¥¥±ý¸çž{ZgÏžÝúÔSO¥õøJl鈙8ŸÝÅl-wwq ]åJW¹S‰ÙÓD÷º‹Ùz>¢NÐåÎ¥:Akkç± u‚žÉÛÄ£jŒQÞ}÷ÝvA8×ÜqÇ­wÜqGÊûÍÇæá‡n={vì§£Šv:ö1ÛŽAOö»»óŸë羿äã>§#dûqIG,ÈÅ{¢»ý Ÿý%ßöy°\ ÝÝéÚÇl:R'È_7nl={vëÆcíß¿¿_®Ùþ8¿×_}Ò6[[[[¿úÕ¯¶>üðÃY[îµk×¶kØ¿ì ºÊjÙ»»ï;ºNÔ9ùêW¿šÖã+±¡ÿ¥+dâ|v²±Ü=‰é*WªåNG,Ȇ˜&z¦'± [Ïç@Ô Ò]î\©´¶v ÒU'èÉs$dÞ@Æý …Z¯¿þúv×u.ìÃ@ÕòI^NµZWWGCCK–,‰=V\\̼yóظqc¦‹×g ¥´ßÙ~l–,YÂêÕ«Y½zu¿íc6ƒîöº>ÿùpîûC¾îsª± ŽKª± Wï‰îö{0|ô‡|ÜçÁr-tuO¤k³í8H që­·2oÞ¼NŸ“­u݆†êêê’¶ pß}÷Q^^žµåVS8'‡ùóçÇö)âHO>ÿ—,YÒîÚ™?>ÍÍÍi;¾F:bA&Îgwq [ËÝ]èé{D K5dKL=Ó],ÈÖó9u‚þ(w®Ô  ëXŽ:AOž#q ; TÜuuu„B!î¾ûîvgû> T(ß ÏtúÃþýûÚ] ãÇïpÿ\±qãFöïßÏœ9sûråÊ•± ¼'ûíǦ¸¸8©ÐV:öQ=žMÇ »ý†®Ï>œûþ¯ûœj,ÈÆ{ ­TcAOö1¯îö{0|ô‡|ÜçÁr-tuO¤k³í8H ³råJÀþbºÿ~*++™7o^ì\dk]W5ÎsçwÒÐÐ@qq1åååÌ›7/kË=þüXùï+µ?éª/¤zOuwßÏ›7¯]ãcss3O=õTZëF:bA&Îgwq [ËÝ]èé{D K5äkÝ(_u TCt¶Ï¨ôG¹s¥N Žmg± u‚ž<'ÚƒŠûý­¹¹™;î¸ÇÓ.‰š û0Pu |“—#óUss3ÅÅÅD""‘åååÜyç.8.òœ¡Èµ0xɹŠ\ ƒ›œÿÜ·jÕ*–/_Κ5kXºti—#˜³É²eË(**bÞ¼y444póÍ7gõå%K–PTTk hhhˆý;—­Y³†eË–Q\\ŒÇãÉtqD r1HÈ ò‡Ä‚þ—¯±@âÀà’«ç; 1~üxn½õÖL%%¹÷2-/G<æ«-[¶$ý¾råJjjj¨¬¬l—-ù§«ó¯z5‰ÁAbÁà%ç^(r- nR'È}ªçrMM Ë—/§¨¨('ÎÇãIj0p:TVVrÕUWeºh***⡇bÅŠ8N®ºêª.§¸Ìfª‘´¦¦†[o½Ç“Ó¢s¹ :‹wÝuW¦‹Ö¡|‹ ± u º›#Ó¤NY—\>ßê{ê#<’颤,×ê@™–×#;Ê8çêJg–,Y›Ã»7ûëÇ&û˜ëÇÚŸÿÁpîûb0ìs_bA>—tìc®‡Áú9Ðù¾ÏƒõZH×>æúq:AöSkƒ$Z²d K–,i7Z5[ëºm"W]uUÒHl,÷¼yóˆD"lÙ²…-[¶pß}÷1~üø~©/ôç=UWWëe‰DX¹re‡ NR7Ê~錙8ŸÝÅl,wOâ@ºÊÕß÷OObA.Ä4ÑóX­çs êé.·Ô ²/¦‰î dÜï555Œ?ž;3åË—³|ùr >Ò;öA¨:P¾ÈËÄ£êéßvaΚšš¬ï1Ô™5kÖ$ÝŒJCCC,Øôd¿sýؤcsñtwþùï‹|ÜçtÄ‚|8.éØÇ\;ò9Ðwù¶Ïr-Ö}̵ã u‚ܵfÍn¾ùæ.Ÿ“­u]µ.RÛm¶])ÛÊÝÜÜ̪U«’š››©©©aþüù9GV¬XÁÒ¥K¹ï¾û:Üæ`¬åªtÄ‚LœÏîâ@¶–»»8ÐÓ÷Ì–ïX]Å‚\Ši¢ûX­çs êýQn©dgL݈¸ßŸÊË˹뮻¸õÖ[c?K—.åÖ[o͉}¨:P¾ÉËÄ#Øueee¬ç÷<@QQK—.ÍtÑúdÞ¼yÔÔÔ°jÕªØc555±ùß{³ß¹~lÒ±¹v zrþùï‹|ÛçtÅ‚|8.éØÇ\:ò9š|Úg¹âÒµ¹t¤N»®ºê*š››yàbÕÔÔPSS“4Er6ÖuUR{ÕªU±mªëNM©–­å^³fMÒ1_µjEEEi-w”=QMM ±Q0‰?‰½¦[Ý(W¥+ ôùìIÈÖrwÒU®þ¾z r!¦ [ObA6žÏªôG¹¥N]1Mto ã~QI·Ä°¿×¦;Öõ—¬å“!­­­­™.Dhnnææ›o¦¹¹™¢¢"X¹reÖ¯—ЕÊÊÊX#ÓøñãihhàÖ[oeåÊ•½Úï\96sæÌaõêÕíÖªJÇ>fó1èl¿»;ÿùtîÓ)÷9± —ŽK_cA®ßí÷`ûH§|ÛçÁx-ttO¤k³õ8H ÿTVVrçwRTTÔ¯÷nœß††V¬XA]]óæÍ£®®.í×]”»¦¦†+V0~üxöïßÏøñã¹ï¾ûbSe[éè¾_µjURCi¢%K–ÄÖË÷ºQ>IG,ÈÄùì.dk¹»‹é*W:ËÝ×Xm1Mt­»X­çs êýQî\«@ûX®:AOž#q ó2×u.ìÃ@ÕòIÞ&5/úüùósfÑÕ®477džäw:·'ûëÇ&û˜kÇ 'ç0œû¾È·}NW,ȇ㒎}̥㠟©É§}–k!ýû˜KÇA깫¡¡!6-Oß»ýq~Õ6ûóºKw¹ï—¶‰üt–»?ÊÞƒ­n”«Ò 2q>»‹ÙXîžÄt•+îŸ|Šiù®'± [Ïç@Ô Ò]n©ôþ9Ù°¢{¹rMæú> T(ä}âQ!„B!„B!„BÑÿòvG!„B!„B!„B!ÄÀ‘Ä£B!„B!„B!„"e’xB!„B!„B!„B¤LB!„B!„B!„Bˆ”IâQ!„B!„B!„B‘2I< !„B!„B!„B!R&‰G!„B!„B!„B!DÊ$ñ(„B!„B!„B!„H™$…B!„B!„B!„)“Ä£B!„B!„B!„"e’xB!„B!„B!„B¤LB!„B!„B!„Bˆ”IâQ!„B!„B!„B‘2I< !„B!„B!„B!R6h–e‰D2] Ñ Ë²0 #­Ûë¯ó‰D°,+#ïÍÇ% öýÏw†a`šfì÷þ>ß]Å‚l¿Ö²½|²¿"½=ß=·mLé鶤޽Ã>Vݯ½9ß]=/ݱ Û¯Ãl/Ÿì_~Ët»@:ëj{¹ ²¹l²ÏƒS*±!Õ:BoÉ÷Ü5Ø÷°‘6ÃÎ¥­|­ƒDuuuk>ìn0l­¯¯Ït1Ò¦©©©Õív·­@«®ë­µµµ)o·?Ï7ÐZ]]‘÷Îæã’ òeÿó-¤ª¶¶¶UÓ´Xq:­MMMý~¾»ŠÙ~­e{ùd;&÷~Ïôæ|×××·{n}}}«®ë±˜âv»{üÞRGÈnù² â:«´¶öü|wÔãý ²ý:ÌöòÉþÅåS,Ȇvt× Z[s7dsÙdŸ»–Oq¡µ5µØŽ:B_È÷Ü•OûŸo± ?H›açÒU¾A3â1_„Ãá>õ´ËV>ŸÓ4ijj¢µµMÓ™.–Y-ßâ@ªÊÊÊp»Ý´¶¶ÒÔÔرEˆ|#÷~ú˜¦I8¦¬¬¬Ýß***Ð4-S Ø"²ŠÄ‚¸Tê]ÅX ²_>Å‚L¶ H@ä“|Š Zlv1˜å[,¹)¯¡PŸÏ×ᇒú[(Â4MB¡PÒß#‘>ŸŸÏ—4œßçóaY@ŸÏG8îò½zûüîöGUŠÕpWõ¡™¸?=¥^ÚmO=ÖÑsºÛfO÷ײ,B¡Á`‡Ã€ßïGÓ´n÷M3˲bç©«ò©ç©)zóÚžž›ŽÎgâ±]N·ÐѹQ"‘H»s«Þ³mù{òÚtî{¶ëî^ë*t s± £8 ¶ßvzª'÷}Å‚žÜÝí›iš8Nº®wXÁJŒ=}ïÞèê\öW,è,ô䵉Ç$cÜûÝëîÞïÏ:@*÷~*u€ÄsÜѱ2M“H$‚×ëì˜âñxbûÒRGÈ,ù>еLèî~NWÚÇ‚Îâ€Ún:cÔ2+•::>ƒ- ä÷îÚºÛ·ÞÔ ¤NлXOq #RGèZ¦ë©´BßëÒf˜ÿ÷~GÇIêËå6ÃTêÒf˜z,ÈÛÄciiiìF"‘¤Þk‰'YõlK¬<Øó-Ë¢´´4vàÕß,˲,ÊÊÊp¹\±‹R]$m·ÕÓç÷V  ¢¢"öá©.†Þ¼6±DÛÇ:zNwÛìéþªÇt]Ç0 "‘‡¿ßßí¾©›¿¤¤$ö^.—«Ã}W³,+VÑèékS¹Ö,Ë¢¤¤$vc†Ãa\.WÏM¢H$’tº\®¤ç”••%]£]½HÛ¾g»®ât ºŠ‰ÏÇXГØÐ“möd{r?v·o‡#©‚gšfRC…:‡‰q@=/]± «k­¿bAWq »×*ù äÞOϽߟu€TîýTêŠÇ㡺º:VçPÔ{%>·«FŠîH!³äû@Ï_›©ïÝÝÏ騨sØ6tÔv =±@ꙕJ@«Á òû@wíÝí[OëR'è},È—8Щ#ôüµ¹Øf}¯#H›a~ßû‰¤Žýu„TÛ S©#H›abA¦çŒíÁ`°Õáp$Íe¬æWóö'þMÓ´V§ÓÙÚÚŸ×?qÎpµ½ÖV{~Þ`0û›®ë­'ö»×ëm«/ÏïŽÓéLšhõz½IeíéöÚ¾¶£Ç:zNwÛìéþVUUÅæY×4­UÓ´V‡Ã;ö]훚kØï÷'ýHZÛ­©©©]º{mOöQƒ®®µ¶ó!755µ:ÎͱÝöÖl{´ÝŽ×ë­7ÑÕk»Ú÷|›û»«sÓÚÚÚe,è.¨ãœ©XÐ6¨í§+ô$6ôd›=ÙßžÜÝí[uuu«ÃáˆÅMÓºêuéˆÝ]ký ºŠݽ6ŸcÜûé»÷û³ʽŸJ ­¶÷§ÚNGÏ‘:Bn‘ï¹ñ} »û¹¯u€Ämw :ZÃ$]±@ꙕJ ñïƒ1 ä÷îÚºÛ·®®ÙG}4cuUîîbA¦ê]½>Ÿâ@G¤Žu„TÚ [[û^G6Ãü½÷I!7ê©¶¦RG6ÃÔcA^ŽxTÃé{²x<Àηý›ÛíŽý;‰ i–e‰D’~WY÷Ä×:ŽØÿÎôöù½¥¦hû^½}mguôœtìobï¥úúzêëëñxŸ/©ÂÒÝk{¢«kÍ4MG¬w•a¸\.t]OêÙÐ[áp˜P(D}}}Ò¢Ú½ém‘Ž}Ïv]è:Hx}½&_§¨ûbçÎ@×q •÷N|¿®®µþˆéˆéØ÷l$÷~nIåL¥Ðu?%~9èî‹BWÛ’:BæÈ÷Üҗ뮫:@bOÜLÆ©#dV*uX0PÒÑ.]_³R'Üu‚¶¤ŽR‰ é¨#H›aþÝû‰¤Ž[R½&S©#H›aß÷=/§Zu»ÝI b&ö@p»Ý±E‰ÕßÖt:íS‹”f‹| øº®£iZRïŸÏ‡¦i=Òm“u8íz—¨Å§@R£'¯íNW×ZbO ×½ ¯ÑÄÅ]ÕM¯‡Öß“×v´ïê˜ç[¯œ®Îú{g±@âÀÀëëýØö<&¾~Ñ¢E±Ç:‹©¼wbººÖú#ô$töÚÎö=_bÜû¹%•û/•:@gÔ=x „Ãá^MͦH!³äû@néK,èª-±@ꙕJ$ ”t´ ¨×(½ý>БÁP'èêõmi®ÆŽH!7¤ÒQG6Ãäcž÷~"©#ä–TïÇTêÒfÿwocA^ŽxÔu¯×KYYº®cš&Ã0Ð4`0ˆËåÂétÆæÙMìÝä÷ûñù|±àašfR†LRs’«a·¹®ªª —Ë;Ö–eõêX›¦IIIIìµ Cv»Ý¸Ýn***bÓ*ôôµ]éêZóx<„ÃaJJJÐu=Öë¥'_T<Ol›–eÅ>ðÔ¾„B!JJJÐ4-v «Þ ]½V•Ù0Œ¤}Ï–ë;º:7@—±@âÀÀëëý¨ëzì<ªk^]Óm+Y‰q ñ\¦ º»Öú#ô$ ÖX ÷~nIåþëK 'çÒï÷ãr¹bk 8ޤ)™zJê™%ßrK_bAWu€Žd"H!³R©€Ä‚”j»ô,ŽH ç± _â@oχąìÒרJAÚ ó÷Þï鹩#d›TïÇTêÒfØ÷X0¤µµµµo§<û™¦®ªzèaÏê kšF(Â4ͤ¹¿ƒUç³AbùÓ±àp6H<Ö=ÍšG"\.­­­±ì|OÏS*¯íLG×Zâûþ­+†a`YV§çºmÙÕBÆjwW¯íèõùª³sÓ“X q ÿ¥ë~Tç¹7¯Ow,è*¨÷ƒôÆ‚®â@w¯ílùBîýì–mŸãmõ¥nÒ©#d–|Èn鸟ûRè©tÅ©#dV*u‚Äçe۱ȧX¸?лû­¿ëù\'èËëó‰ÔrC*÷`6´$–#[îýÁTèŽÔ²[ª÷c6µ; ÆïyxìˆÊR×ÖÖÆ²Ì.— ¯×›Ñ‰ª3½9ÁÙ¾½T%Þüé|í@ìg¶ËÁj0Ä‚þ¸ÖÒ½ÍTîåTuöÞò›Üû½ÛVm³¿>Çû“Ćü1â@.l2[è ‰ùe0Ä‚\¨¤*qDbAþ q!¶—IÒf(`pÄ‚\¨#¤úßíz./§ZíJâPi5U†^šI͵›¨7={²}{Ùj ös°Ël7bA\kƒáú•8ßäÞïݶús›¹FbCþ q ¶—‹$ä—Á ¤NÐ?$ä¯Ára{ÙJîýÁc0Ä©#ôÄžt#…B!„B!„B!„é74ÓB!„B!„B!„Bä>I< !„B!„B!„B!R&‰G!„B!„B!„B!DÊ$ñ(„B!„B!„B!„H™$…B!„B!„B!„)“Ä£B!„B!„B!„"eÃ3]€ÐÜÜÌÆ3] !²Æøñã™7o^¦‹1àêêêØ¿¦‹!DÖ˜?>EEE™.Æ€’:í-Y²$ÓEp 444dºBdââbŠ‹‹3]ŒWSS“é"‘UäûBÚ …z`Hkkkk¦w¢¿}úÓŸ¦°°sÎ9'ÓEPO>ù$W_}u¦‹1 Ö­[ÇôéÓ™>}z¦‹2 z{®Ÿ}öYž|òÉL{À-\¸o¼1ÓÅPrO ½=×ñÝï~7ÓEPR'<illdñâÅ™.Ê€êí¹^·n·ß~û K>^ýõ\tÑE™.F¯å꽜«õ‘\-w_âßÚµkyôÑG3]ôUSSý÷Þ›“Ÿ¹ ¤ÜÙ]îÁúýàÛßþ6ÍÍÍ9ëÓgT6ÈÕrƒ´öÔÕW_Íå—_žéb¤$W?¯åjlK”Ëñ"qR­ Š#GŽäÒK/å–[nÉtQT]]+W®Ìt1ÔªU«X²dÉ k<ëí¹®««Ët‘3bäÈ‘rO ÿºWSS3({ùK`ðP×ø`ÛïÞžëU«VeºÈ1a„œ¼6rõ^ÎÕúH®–»/ño°~?X¼xqNÞS¹ ¤ÜÙ]îÁúý °°+¯¼2çbý`úŒÊ¹Zn6Þš2eJNžßD¹úy•(Wc[¢\Žm÷!Y¹Æcss3çw^‡;·jÕ*Î;ï<æÌ™ÃŠ+z4EÒܹs™1cF¦wkÀåòÅÝWåååÌŸ??ÓÅpùx®ÓN?ýôLïÖ€“{bðÈ×s-u‚ôŒ÷Äüùó)//Ït1\¾žëÎbA_ë¹*WÏo®~Fåj¹ó5þõÇ÷ƒ\•«±@Ê-åN‰6ùŒ’r÷T>Ɖˇs«±-Q.Ç‹tÊÊÄãŠ+hnnn÷øªU«¨¬¬dåÊ•¬^½š††V¬XÑíö 3fL¦wkÀ Æù¸‹‹‹ÝzŸç:Ýq`ܸq™Þ­'÷Äà‘¯çZêé1¢¢A¹^Y¾žëŽbA*u‚\•«ç7W?£rµÜùÿúãûA®ÊÕX å–r§ƒÄ›|FI¹{*cÄŽåùÎÕØ–(—ãE:e]âñèt!×5kÖP^^Nyy9K–,á¾û®Ž5kÖdºØBˆ4’8 „‰B[g±@ ‡Ô „ ±@!q@ˆ\‘U‰Çºº:B¡wß}w‡khhHšß·¸¸˜yóæ±qãÆL]‘&„ ±@aë,Hbð:$!$‘K²&ñØÜÜÌwÜÇãépX°êÉÐvaÑñãÇw»èíž={Xµj«V­Êôn ‘Q•••,_¾œíÛ·gº(êÏ8°}ûv–/_Neee¦wUˆŒZ¾|9«V­bÏž=™.J‡¢N°|ùòLï¦UWWÇòåËyòÉ'3]”Nu R­ìÞ½; …ÌÔgâîÝ»3]”õ÷÷ƒ'Ÿ|’åË—÷è¹Bä3ù~ ß„6Ci3ˆåÑR­ ÏôŽ(¡PˆñãÇsë­·¦}Û“'OæÚk¯mx„lÔtÙZ¡îÏ8púé§³zõêL醴zõjjjj:\ˆ=H@ˆþ7oÞEEE™ÞO!„B!„B!„B!D?JKâ±¹¹™+VPSS{låÊ•<ðÀlܸ‘‡zˆyóæez_…B!„B!„B!„ý$-S­†B!6nÜÈêÕ«Ù²eKìñ»îº‹%K–póÍ7ÓÜÜœé}B!„B!„B!„Bô“´$+++ñx<,Y²$éñââbî¾ûnš››cS° !„B!„B!„B!òOZÍÍÍN¥ªÖw¬««Ëô¾ !„B!„B!„B!úIZóæÍcÍš5þM­ûØv4¤B!„B!„B!„" OÇF<ÿ?{÷W]çüUhiKÛ´' J¤ž S{ ÁÑ3P`E­; ««Ð•ÎèþÔª›Ý™u—ª¸»Îh~«ýéª3u·xßÌYë(ÎYµ(!P.BÅPhrÚPz¥ô÷Çw¾çœI&mšKÓËçùxä‘dæÌ™3“™oΜ÷ù|¾Ë–-`Ñ¢E€ {zzhoo§¹¹yЊH!„B!„B!„B!Ä‘oT‚ÇE‹qË-·ÐÞÞNGGK–, µµ•¶¶¶ñ~œB!„B!„B!„Bˆ14*Ácgg'ÍÍÍÜÿýakU€ „s< !„B!„B!„B!Ž^£<.[¶,¬l”¹…B!„B!„B!„8ö7+I¥R¬Y³†¾¾¾a¯£¯¯eË–1þ|æÏŸÏâÅ‹éîî°\{{;^x!óçÏgÙ²eôôôŒß³'„U2!@Æ!„2”±@Æ!Žn²O „ „2q¤•à±®®Žºº:Þö¶·±|ùrÚÛÛ|È7ÞHOO«V­bÕªU444pã7V…™zɶ¶6V­ZEOOË–-ïçP1JdB€ŒBå@cŒBýdŸ@2!dâH3*­V{zz˜9s&3gÎÖYÝÝÝtww³zõj5?ä…^Hgg'‹-`Íš5´¶¶ÒÚÚ ÀŠ+°m›5kÖ„Ë!ŽL2!@Æ!„2”±@Æ!Žn²O „ „2q$•à±­­mD·¯««céÒ¥áÀQKww7===UsH644ÐØØÈºuëdðâ'ã€d,B( dâè'ûB±@!ã€G¢Q µžžÖ¬YÃÖ­[hnn®z³¦¡¡! /»»»Ùºu+466†·¯3næÌ™5û9ǽôÒK8ŽCOOOxƃÇ¢ÎÎN:;;Ù¼yóxoÊc=lÞ¼™ööö!MB­ÚÛÛÙ¸q#uuuã½)ª}‚ÎÎΟ8%Ä‘¬§§‡ŽŽî»ï¾ÃòâÆ‚uëÖÃß'زe ííí444ÈçqLëèè §§‡-[¶Œ÷¦ p(>Üwß}´··ÓÚÚJCCÃx?d!Æ|>ÏBÈ1C9f(¨Ï÷Þ{ïˆ÷ F-x\¾|9U—­\¹’††V¬X±ß3âÚÛÛéììT%åhìôLž<™ÆÆF,X0ZWˆ#RCCÍÍÍüö·¿ïMÙ¯±¦M›Fss³TǼææfyäžþùñÞ”ýË}‚7¼á ãýð„W3gΤ¹¹™7Ž÷¦ÐXŒS¦L¡¹¹™™3gŽ÷Ãb\-X°€††<ÏïMÙ¯±ú|0gÎ „@>Èç!䘡3BY°`/½ôÒˆ÷ F%xŒOÜÚÚÚ¾á;;;ioogÙ²e¸®;¤u­Zµ*¼í’%K¨««ñYÈ'œpoxÆ~ q´jhh ¡¡•+WŽ÷¦ì×XŒÓ§O—³–„ :ðp¬nˆË} ı®®®ŽæææðCûá¬ÖX0Ò:xâX§?#«Ÿtð(ıN>Èç!䘡3cË÷Á4Ç{+¬±±‘­[·ŽxŸà¸Ñؘ5kÖ°téR–.]Zu–Ass3+V¬ §§g¿5zzz”<ë²æþ·«U-¢G>„ cBêX ã€G/Ù'B€ŒBÄÑ¡X„ ï­8tF%xì?qkœ>y½”׬YÃ7Þ¸ßûÐë×ó¹hR-ÄQ@Æ!ÈX „P4È8 ÄÑOö „ cBÆqär]Ð3 £<644 ZѨÇýY°hÑ"úúúªJ¹õ„¶ñ@³µµ•ŽŽúúúÕ¦®®Ž«¯¾z¼ŸG!ÄÉ8 „ „ÊPÆ„8ºÉ>d,BÈ8 /¾¯¾V½èºêK/£—ó}pœñÞúCgTæx\´hQøÆ¿úê«ill Û«¶··ÓØØ¸ßÉ ÜrË-,_¾œb±ÈÌ™3éééaéÒ¥U=šÛÚÚ¸ñÆY¼x1uuuôôôŒê$²Bˆñ#ã€d,B(C dâè&ûB±@!ã€8|ª`4MõÝ0À²ª—q2Úv´ŒmC2 é´º¬ÿmŽF£<¶µµê,‚þÐêy¤µµ•ææfzzz€hBÛ¸ºº:V¯^VW.X°@!Ž"2!@Æ!„r ±@Æ!Ž~²O „ „2ˆÃƒç©¯dRU5êàQ·PM¥¢ŠH-^ñ˜ÉD­WöðqT‚GPác*•bݺutww‡oþƒ™¼µÖ€QËþª'…G6„ cBÊX ã€G7Ù'B€ŒBÄáÇuU˜èºªÒÑ0Ôå¶­¾Ç« õÝóÔÏûÑúŽD£2Ç£VWWGss3K—.eÑ¢E: !„B!„B!„Bq¸Ñšn¹ê8ËEËd³êgËŠ–7ͨíjÿ¹}`¥d>_}}-‰DõöhƒÍ?y(ZðØÑÑÁ’%Kèîî/»ð Y¾|y8¡«B!„B!„B!„GèõŠEõ•JEs:êë=OUBêÐвÔW2 ¥Ru˜¨ç…Œ ‚h]º•k\ÿõÇÅCËñ2*ÁãÊ•+Y¾|9@UßäÖÖVî¸ãn¼ñÆñ~œB!„B!„B!„B´ ˆ* õ÷ PmSƒ@~岪nÔËê`0:Nu˜X+xôýè>jUD†úªUñxÔ´¶¶²jÕªª>ËmmmÜzë­tww‡“º !„B!„B!„Bq(ù~Ô õ`ÅÃÆ\NU.f2ê2]јH¨à1,ºnõzâa<`ì¿ñêÉZÁ¤i¾µÖy(JðØÓÓâE‹j^§çyŒ·`B!„B!„B!„b,ôüòyب"p°9MSµU ^† !úÙ4U(iÛêwÝ‚5ζ£ûpuVêËm;j·Z+d¬ÍªçEóIާQ ­hìéé¢R!„B!„B!„Bˆ±’HTW)f³*¬,”s]˜0AÝNsœ¨BR‡ñjÄ8ßWs8¤Ójyý{ü>-K-[,F×åóê6:PÔ“û«`L&£mÒËëm«5/d|;‡[õ9T£<.Z´ˆ•+W²råJúúúÂË׬YòeËhhh ¹¹yl‰B!„B!„B!„8¦ù¾ªì_)x àQ‡‚šç©ðT0X,ªåj­»ÿýÚvTuY.GˆjÑšN«ð0—‹*ãmU'º}ÿàQ/§«7u¨šJ©uëm®@¥ês¤&ŽÆJÚÚÚhoo§½½½êºÆÆFV¬X1¶B!„B!„B!„Bõ@zž ûÏûæô|‹Ùl´~ËŠ‚HP뀨:2Î0¢@/“Q×g2Ñmâô\úv‰DPêÀÒ÷Õåz¾H}nãZ(¨0SWKf³ê¾t Öþ•ñǤçª+êxlhh ¡¡b±Hww7‹-bÁ‚,Z´ˆÖÖÖ±ÛZ!„B!„B!„BqÌÒ!œ=Otù¼ Õâ\W…q:|Œ‡q®-_,VW!‚ ó\7ªz ‚ÁÛ”ZVlFTõX,F!£ÖÿwËŠ¶_W^&êþôü” ¶#•RëL&¡¥%jí¯¨tÝUº]k>_}?caXuuu´¶¶²bÅ V¯^MCCضÍòåËY³fÍØl­B!„B!„B!„8fÅ[¦FT}Ø¿ ªçEmYM3 u ×?¸ŒWê°O‡‚ûöE•„µÄ·C3Í¡µ55 u]]jû C‰…BÔ:VWo‚ºNoo [ #Z¾m­ùÇʈçxÔ!¤¶fÍ:;;¹ùæ›inn¦¹¹™«¯¾šºººC÷¨„B!„B!„B!Ä%›UZ­¥ Â7=§¡ž“QW%f2jËR¡žÿж£Š?=o¢%!ªP„(,,aýz๮ -uUaÿ€q°Ë@Ý÷Úšê`4Žæì_˜JEÕ›ú¾,kðù&uȪŸƒøö˜æàÛ;†Uñ¸?‹-â–[náþûï'•JÑÓÓÃâÅ‹«æƒB!„B!„B!„"Îq¢@°XŒ* uµŸu ˜É¨å]WÝ6ŽÚ‰ú¾ Øt°êz½~ýÝqÔ—–ɨõ×׫ 4ŸnoÛƒ‡¢µÂ<}»ý1 µ\©¤ÂÎZëI&£¹#ã÷çûû¯ªŒúyŠÏc7Zó>ŽzðÐÓÓÚ5kغu+mmm¸®KccãXÜ•B!„B!„B!„8‚éÐ÷«CB<ƃ2¾e³êK·Õœï«€Ðq¢eu»TÍ4£³àòR)úév¦ñ¹‡b(ó(êJÍÁDœöo©ª+Cû‡›¹œZg¡U…f2ê»çÕ~Ìúù # ÛÛÛ±m›ööö𲎎lÛfÙ²e,Y²Dª…B!„B!„B!Žq‰ÄàáV¼â0>¢ùŸâÁ—úþL³º:Óó`Ïž=5·¿X„ÎÎ]#ÛЊ‰Ã¹Q__+W®¤­­¥K—†—wtt°bÅ ÂË—-[Fww·´[B!„B!„B!„8í/€óýêvªñys9õ•ÍV·ÜŸƒ *kéßbu(÷Ÿ×²« ¾óG©«{ ¿þõ$^}õë\tÑõÀ™€ ']N>ùàÚ‘m,ìx\·n­­­U—ëp1:.Z´PÕB!„B!„B!„âè¯^Œsœ(P¬ÕvÕ0Tèy*4‹~ù|uX*©ßõ¼…--Q;V}û“ͪ°Í¶£V¤q:`Ôm[ã— &MZÎcyÏ=·³iÓw¸ë®»ø§ú‹_Á‹/Î$òù<ž×\ó2/¼ð¯£rßà ;;;¨««p¹n»ÚŸB!„B!„B!„G7Ï«þÕ #=/º\·Rí_©[¯&“QŸ³0™T¥½©ï«´Ö¶ê€Q‡›qºRòpàû>‹-Â=¹¾ïscaüùŸ?Ê¿ø>ðeïÞÅ|ö³—qÑE'óýïÿ|>O6ëðÔS[¸ûî9üë¿~•_|qDÛ4¬àQ‡‹}}}áekÖ¬`Á‚UËêÀQÚ¬ !„B!„B!„BÝ\whU‡¦©*‹Åhy]aX,FëÑmP …è¶z®E êùm; "£o£[˜¦R—·*ìö‡Ïóp]Ïóð< &à8årÏóøâ·S*•€h¾Ç‹.:™7½éUÇ¡µõøùÏ_ä5¯y ŸþôÝLœ8‘»ï¾{DÛ4¬àQ‡‹ÅXÃ]=¿£n­Úÿòþ¤B!„B!„B!„8ú 6Ç¢¡z^ÅdRýžË©9õezùZ!`2U6êJHFærÕ×­_µvÛß:Æ‹ã8.›Ÿ'S£Ÿk6›Å0 ìØ[²d ¿ùÍoØ»w/¾ïÓÕÕ…a|ýë_gíÚµ˜¦I6›%—Ë‘Hèû†öö>.¸àL~õ«üùŸÛ¸î£|ä#K8õÔ‡Gô¸†<´µµÑÐжX]ºt)mmmáõííítvv¸\!„B!„B!„B=tØg*ÈÓᢦCFò™¦ºÌ4£ÐQgpë׫¹uKSÛ¼âq8‚@m‡iî.ȱ®xt‡d29 |ô}Ïó°b—Ífñ}Ÿx l­šL&9ýôÓéíí¥¡¡d2ɾðòù<–e±aÃLÓ$ŸÏ“Ïç ‚€TJõ«=眻øìg/«<Îã(•J\tÑV6mš4~Á#@kk+­­­5¯kkk“y…B!„B!„B!Žr¾ù|4÷b"]]Q°çû*\Ôd±-« øt{VÇQËê¹õ\zNÆýÑ^­jGP­V-‹°ò/•|Ùýé ÇwÜeY˜¦‰ëºa%£ïûýJF¿þõ¯ðýïŸë¯¿˲øÔ§>Å–-[H&“üà?à¾ûîãÙgŸå„NÃLÇq Ê|>Oo¯ 7oþ.çž»’§žj¢T*aoz“lÑc‚aÎñ×ÙÙIgg'ÝÝÝU—Kè(„B!„B!„Bqtr] ‚ óòyZ–úŠÏó¨ç^ÔŸæ8j–U êÀѲ¢JÉ¡f|¦ 5º”†²Yõ¥·Ñ4£ÊÊ¡*‹õ§Ÿ~šÛn»­ò\ºaب+õï_ûÚרºu+7ÜpW]u©TŠ عs'·ß~;¦iòÖ·¾•iÓ¦qÁJ¥ð< ¬~ÌU&ËÔÕq>ó™ëرcY ¦RÐÔ´eÄkØÁcww7¶m³dÉ–,YÂâÅ‹Y¾|ùˆ7H!„B!„B!„BÞ\W‡ -]‘˜LF-T5ÃPÕ†Z¡„º2f2Qe*5´jG-~?ƒ‰·YJKU×uÉf³A@>ŸÇ§ª [§ö·yóf|ðA@UPzžG>Ÿ Òé4O=õwÞy'sçÎeÊ”)xžG"‘Àu]\×åŠ+®À4M^xázè!Þüæ7“ªd,BÈ8p¸ñý¨½jÿ`0^DgšÑrAý¬çoUiX.«Ÿ c`ð7غ5iµ@½5ŠýÂå]×%N‡?;Žƒã8$“I …¥R)leÚ?LÔmLÝXª©[¨öû¶nÝ À+¯¼Âûßÿ~~ò“ŸðÓŸþ”‹/¾˜={öpÚi§Ñ×׆ˆ:8ì_9iš&†aðío»ßsfaYVUH©·Íªñ„Z|èCO3RÞãq4õõõÑÙÙÉg?ûY-ZDss3mmm466rÇw„Ë­Y³†ÖÖVZ[[Ã*Ëîîîšg7!Ž,2!@Æ!„2”±@Æ!Žn²O „ „2Žâ†Ž£æjŒÎß|_Ž–U ¦ÓH¨Ÿõ¼ý•Ëêöñ6¬qù|¾fÕc1^–óÜsÏ ¨Òt' ätؘÏçñ™L†D"®£¥¥Ã0_úÒ—˜:u*Û·oçôÓO`Û¶môöö†Áæ›ßüf2™ =få~kÏÍØU3L,Äþ@:€¬âq´ÁcOOÍÍÍ466V]¾`Áúúúèîî—Óhlldݺuãý„#$ã€d,B( dâè'ûB±@!ãÀá(ªÛ”¦Óê÷Lf`Å£m«ÐÐóÔïÉduÛUFõüq‰„ºÝ` ‚øb±ý—K¥Jø¾ 4 Ã#N‡­NA…r–e…Á£¾¬ÿœˆ–eUž®ë†s+f2ŠÅ"Žã`Yþð‡lÏ9çœÃ•W^ À 'œÀÔ©Séé顾¾>¼/½¾xÅb*• [¨Æ™ƒ”ŠÆÃH½Ì`s<Ž–Ã"xllldÕªUU­[ûúú¸ãŽ;ÂE—öoç:sæÌÎ+ùÒK/á8ãýP…W´··³yóæñÞ”Æzؼy3ííítvvŽ÷Ãb\µ··ã8/½ôÒxoʇjŸ ½½}¼ª㪧§‡öövî»ï¾ñÞ”š4ŒtŸ`Ë–-a+&!Že´··³eË–ñÞ”Åçƒûî»ööv™ÿIóäó|>BŽÊ1ÃáÒaa¨€°ÿ¼‰º0ϲ¢PÒ²Ôò:+—÷*êö«µ*u•bÿ >}¹ú²Ù,žçÑÒÒÂÎ`šj{‰Åb1¬ŽÔmRu• ëº¤R),˪ìÅï·X,†ažž ÒóúÑpÉ%—T·U3ÔÕÃÿ›yƒVÁˆ‚Ç%K–0þüðkåÊ•tvvV]¦¿Æš5kX¼x1 #~&OžLcc# ,ñº„8’544ÐÜÜÌ´iÓÆ{Sh´Ç€iÓ¦ÑÜÜ<`~Z!Ž5úLÁÉ“'÷¦ÐXíŒd^j!Ž3gΤ¹¹™9sæŒ÷¦ ÉhS¦L¡¹¹Y>ˆcÞ‚ hnnfÊ”)ã½)4ŸæÌ™Css33gÎï‡'ĸ’Ïòù@9f(Ç ‡ÃuU€¨[¨ÂÀÑqÔW<8L&Õít'ÔDB­c°<ËR××¢+uÅ£Ç «}ß'ŸÏS,+-J]yd'P]QhÛ6ù|Ã0°,+lgšÉdj€º’Ð÷}Òé4žç…-Qã‹Aà8³fÍÂ÷}î¸ãN;í4öìÙõ×^ËâÅ‹Éd2aÀyÝuׄÛÑß`•CaFøœÕzL ,•}‚‰Ã¹QCCK—.Ñ×ÒÓÓÃòåËéììdéÒ¥¤R)êêêF¼ÞN87¼á ʱ…8Ö444ÐÐÐÀÊ•+Ç{S5VãÀôéÓåÄDgŽÕ ÚXïÈX Žuuuu477ögôŽÕX ƒG!Žuú3ò±úù@Bëäó|>BŽÊ1ÃËeUõ躺uéÀeƒòy(•ÔïÙlt}*¥nŸ²0‚ªÖ¢¹ÜÀËóù<™L&lêyóæÍÃ÷ýªÊC×uÃÛ‹Er¹ŽcQ*íãâ‹×2}º†…AÏçÃ@Û¶m|ßÃÉþ,Ë¢¥¥…b±ˆeY”Ëå0t‡k®¹†§žz ÇqH&“lذE‹±|ùr:::رcçŸ>ï|ç;cÏ—YU5i 6±å0Y–E6þèGwé>Á°ƒÇ¶¶¶Q}ÀÝÝÝÜxã477ãºî gtww%Pâè ã€d,B(C dâè&ûB±@!ãÀáÆ¶Õ—a@S“šÛÑqT€¸o_õ²:7‹M…—¹œªz쟭åóù~á[ty2™Ä²¬°*¨0-—Ë‘H$( äóy …BØ>Õó‰D"ܦ—_~™×¾öµØ¶VSÞ~ûíüñlذ¡ò\TW/Æço­ŠÞZt+Ù±2jsGÓŒæz¬E_§DÃP—e³Q»U-ŠÅ"žç‘Ïç«æjÌçóa›P=¢çyaKÒõëדJ¥èêê Ã;ß÷q‡\.‡eYX–ŬY³Ø¶mÏ?¿§ê¾-˪ þ !ãëŠK¥Rá2®ëAX9wî\ÞøÆ7†!ª^îï|';wî¬ÙF5Þþt´«õ:u[×±4¬ŠG­¯¯b±HGG}}}U×ÕÕÕÑÚÚ:¤’çÎÎNzzzj¶{š9sfxVBkk+\}õÕÔÕÕ±råJêêê¸úê«ÇôIBŒ=„ cBÊX ã€G7Ù'B€ŒBÆ“ï«`Pϱè8QPèº*pÌd¢ykM=˜J© ±¾¾zþGÏS¿Ûvõå:\ô}×uñ}Ÿ®®.òù|åv^l¾ï‡žêâßõ\Éd2¼|êÔçÂuÄÃ?<Æu]²Ùl8÷c¦iR.—™7o©TŠŸüä'5çcÔó‹E°x :|kÃûúú¸ñÆéîµ•æææ0`ìëë + ;;;¹õÖ[÷>êcÙ²e®knnfÕªU´µµqã7²xñbêêêèéé¡­­mÔz9 !ÆŒB±@¡ e,q@ˆ£›ì!@Æ!„ŒãIwuÝh.FPs9f³êrZÖÀ–©zù|u VFºnõÜŽê¾\’É$Åb±j>G=ocUU¾ïàé€M…ºšðì³ÇäÉ÷ñÐCafÍÛôAX9éyÞ€êF€t:M¡P •JáºnUåeôØU°išæ! Ç˰ƒÇöövzzzXµjU͉W-ZÄ¢E‹X¶líííÜrË-ƒ®«­­mHsFÖÕÕ±zõêp°Y°` B%dB€ŒBe(cŒBÝdŸ@2!d8Ô|? m[Íè[ªj‰DT­¨ÃHÛŽ‚Êþ\&LˆÂG×UÁ¥m«¶­¶­î/<Ï#—Ëá8N87b:ƶm,Ë + ÃÃÉxý¯Ÿ2åR{ì<à?±¬$C¦ib‰DÃ0ªÚ¢‚š7Ѷí0<­Uí¨ocYVÍëÚ㱧§‡ŽŽŽ°Òq0ÍÍÍa‰sÿV¬#ÑÜÜ\Ua)„8öÈ8 „ „2! „ cBƑҡ ¨¶ªÙl(ÚvBZVõüŒAP»âQ·cÖï2uêsX\{ívöìQs-êùmÛ+õœ‹Éd²ªâQÏ—Ø?ü‹Ó×Õjºwï €;äv§Ùl–L&C2™¤T*Q*• T·`M$±ç#Øïú$x¬¡§§P}“D/ÓbW!„B!„B!„Bqxð}"êJFË‚BAý¬çu2ƺŒýJZišêv岺<ŸÏóþ÷¿ðùÑ~À¬Y¥pNG]hYVf2R©†aày¦i†-KTíhÛö€pqÖ¬^öìÙÃYg]Uó6ýCCˆêõxžG6› ƒÃt: @¹ò ãÛ¾¿í:š[­+xÔåÊ \V/ÓâW!„B!„B!„B1¾t•#Dá"¨ Ròy^õu©T4G£mW‡ÅX9¤çU·k­«;“'ž¨ãÉ'grî¹yüñ鸮‹ïûaæú‡ŒÉd2 ðéÛÆ½ñoL.\8à:×uà Àq‰¹\. uõ¥mÛäóyÊå2¾ï‡y(¡¢eYC®¶u.ñZökXÁ£n¯ª+÷G/³¿–¬B!„B!„B!„âЊW8ú¾ uÑ_ÿÜÎuUبH}}­œÍ¥zýïz×éë;™—_¾‹™3ŸdÓ¦MaËÒþacºí* -à«Õfõ¥—&pÓMs\§çliiÁuU+ÖR©Tš¦I&“!‚°ej.— CÐxuäa«$F¼–A +x\°`\V/£o#„B!„B!„B!ÆŸïG‰™LÔ5™T•ŒºMªæºQ0©ÆÀv«:Ä‹WIzžÇ¹çÎ`Ë–ÿá‘G¦²eËÇ!‚šAa\­JÈ¡ ‚€–––ªuU?.·òd0MÇqÈf³ƒVU&“Ép®Éxû×#‚‰ª|ôFº¢Ú†<ÖÕÕÑÚÚÊÊ•+Y³fÍ Ë­Y³†•+WÒÚÚ*“¹ !„B!„B!„BFtˆèºN« ÒóÔ—nµêy*ˆ,Àq §gÛ€õT2¸žçѲ ···r_AN™òôõõ1kÖ¬!…Žê>¢;,Œ·yí¿=ŽãpÆ»9眇ۣG=·£eYär9 …B8oãQÇ2Àf+xhkk£±±‘eË–±lÙ2:::èì줳³“ŽŽŽðòÆÆFÚÚÚÆçÉB!„B!„B!„5¹®ªl´,0ê¯¾@…“¾¯‚É .ØË~´*¼½®lÔ‚ÑzU gðê«O†¿ëÀpîܹ€Ãùç?eYl› ª²ð@òùü€Ë<Ï£©©‰®®.æÏŸÄÇ?¾ß÷q]7l«êºnU°©¶ý0o™:6àŒÍª'÷†uuuÜzë­‹E:::T>ÖÕÕ±téRR©”T; !„B!„B!„BŒ£ PA õe¾--ª­j¨ªFÛ†M›Å0Î@Θñž|ò~ ª"´, ÏóÂÒó<|ß'|ß`Ê”Us>žsÎ9õÔS9ã Ë2{Рƃ{|AXigš&]]]ø¾O:¦··—D"eYôöö†Û}L°€ªÍªƒª|eÃA…‹mmm´µµÑÙÙYu]ssó!{ž„B!„B!„B!Äà²YÕµ¥*ÝOñ}ÕF5ŸWdo/”JªúñöÛÿ˺P•® ¿þõ¹œ{î>@µ5‡vA¿É=Ï#“±ùÒ—¬ wîldöì‰ÌkaÛ6¦i©šñ@‚ À¶m|ßÇ4M‚ çv´m›\.‡aäóyR©TXeiY…Ba¼ÿ<‡†S^s<ÖÒÜÜ\õ¥µ··3þü±}¢„B!„B!„B!Ä ŠEõQ£ç©êÆLFUCz45ÁþgüãÙ$“`š0mÚcáz}ô;€j¯ªÃÆxÅ#¨6¥étÏ˳k×mxž}sæÌaîܹ˜¦‰eY£:‚jïêy^rf³YæÍ›@*•Tõc±XÕû=âø¨ÊG“ðqDB!„B!„B!„âðæû*XÌçUèº*€,—ÕïºÓ©Îâ^zé%vîÜ Àw>Á|¹œK6«t]·f[S-•J…a¤'õœ‰+VLÅ0À4S£þ8S©¶mÉd2œ·Q‡Œ¦i²~ýúñþsŒHV~¶PÁã§×<(£Vñ(„B!„B!„B!Ù¬ú®3Â\Ö¯WíT‹EUÝXÉÉåTð˜ËA__›6݆ã@GÇ‹üèG“Âõæóy’ÉdeÝQéºnØò4™LÁ€9-+ 8GKá}g³YŠÅ"ù|~ÔÚ¸5\à?Óêç0ò©5àQ!„B!„B!„â(/J´,ÕRUëê‚T¿¢CàAoo/`Y°yófžzªž‹/^‹mÛ¸®¶+õ}¿j~G4š¦YõóX€úþ3™ …BÛ¶yÆ/\xÐQ?ôèß…B!„B!„B!„G!§’1U¦=¬bP(¨¹µ|>ëÂŽß\Z[·òÇ?þ €­[Á½÷^.«ƒG=·"PUÝhšfš¦¶ZmÅb‘D"A©TÂ÷}êëëijjÇgý0·'P‰´šïq”Ið(„B!„B!„Bq”ÑÕŽ: ,÷+‹•å<Ü0¡,6ÿø£lß>›… 3᜖¥&´m;üY­ß¨ u…£aUË7–¤Ú¶M.— .—ËtuuI‹ÕZæÚPg©$ÚBµ[ FºÒj‡s£ÎÎN–,Y2ÞOB!„B!„B!„„a@ l©ªÅ[¤:ŽSU±xÚi§UÚ¬fؼùQ`#veN@ÛŽ&Ô·IÅî¤è¯~)ß÷iii¡T*aYóæÍcß¾}áõñm5̰T*m-èŒyÔ +xœ9s&ÍÍÍãýÔ!„B!„B!„BˆßÓ„bQ…Ž®]V) Å«u€8yò7yË[f°sçK<ý´ªrœ:u*s羈ïC&¥Tz¾Çøúât¥ãhUú¾ÙlÃ0ÂjG1) 9×Uþà2þÁccc#«V­ï§G!„B!„B!„BÄ´´@¹¬~6MõÕ/ ù~4ɟ뺕v©·qç%.ºÈeÆ_0{ö›ù‹¿ØÁ¯~5‹ãWËÆ[§ê°Ñ²,òù|Õú ÃÀ4MlÛ®º¯¡ÒU’z~HÃ0(W\UóSŠôsžÍªïf 0áºÊõ&à¡^4£àkŽÇîîn–,YBww÷¸>_B!„B!„B!„Bqœ(kJ&£2™T_ýé0PWªv©ªeê”)§o{[/_üâ¹L™2ÃPUŽºi¼­©QcÉx¥ãÁV=ú¾OSSS8e±X$›Í†¿§R)‚ Öªƒ (zžúêßo×ó ÑWÁ#@SÓ|Äw;¬àqëÖ­tvv²uëÖªËçÏŸO{{û¸<B!„B!„B!„Ç ]ħCÇtZeNÅ¢úù@¾ïcYVUxxÚi*x¼ñÆÍ•u6…×õmÛƒÅxÀ¨+‡£X,†Õ’Ùl6¬ÈÔsIú¾ã85ÏÃ^ PãûÈçÕÞqÀ²À¶U¦¬óÇt¦xê÷B ’IÎþçfÊŽ#ºÛaB!„B!„B!„büTº†|_]ÖÕU>êb@=ßãÀu¨ ]×Ų,,ËâÒK¿ÀܹOQUãcM«¹úúZÁ£eYà =Ïò,R©MMMxžG©TÂó¼0hL&“Gfµc€üHWtÅ"d2ÑŸ ÂÎ"*µö<Hš•m*xeÆ ÎþÝïFt·< !„Ç gŸ}v¼7A!„B!„BŒ@ÿ*FÇ×USW—Êœl[ý °}ûºëp]Ó4 ‚Ã0°m› þÓTÕŠC©&Üß2SèÅã8aøhÛ6¹Aæ,•JUóM*tô*_Z6•¨UDs6z ƒ/kV¾ :  úmÇLÉ—,Y2ಕ+W²råÊ—Ke…B1z\×öäÙžçÉB!„B!„G08zäóÕ]5ã|ßÇ4M¦OÿðwÇqÈçód2™0\Œg²,U gYVØât¨’C©¶CµyÍçó¤R)Ç¡\.ZÍ8¬ÐQÝZZÔÏå²z`aOÚœ Û‡®­E@g…A ¶y°9‘PœøóœH¨BDs7îO­"V«²×üá +xlhh`éÒ¥£ðl !„b8&xÔqÇxâ‰'Æûa!„B!„BˆƒH¨êFÝbößY3ŸÏS(Â6«Åb1<6¤/Y–Uîél®Pà O|êò¾ï‡Ûäy™LfäOŽëF•¥’zbj%²ù<ä+`v1¶á£ï«ö§¥RÆ+ “TÏó˜Ë©êLljZ¡Æ™¦z|ɤZ&>W#€~ õsÿ¿‡Sy¼ýÿL6†)ÏNñCvðØÖÖ6ò'\!„Ãâ8¹\Ž =ëË÷}‰A°~ýz Ã'ã>ýôÓyæ™gÆûa!„B!„Bˆ! •­‹QÞäyµó)µ|@±XĶm‚ “ÉÏçI&“ø¾çya…b¼ÍjDëvµa Žã`–eqû’Ûéú}×è=9¾…m©ÔÀÀM‹·“íB…~zÎÅÑæº*t4Íê*ÄØó‹]ÙB† ]W=߯ÞfËR/Pë.ÔW±¨–M&Õ‹Âu£2n°ÕR0í±i0Âìñ°œãqñâÅtvvÖ¼®½½ /¼ùóç³lÙ2zzzÆ{s…c@Æ!§ÃCPg­¹®Ë„ Ÿëëëq]7l—‘ÏçI§Ó8Žƒiš¼õ­oeÇŽãýPHÆ! >È8 ıCö „ cBÆ=E¡ëªŸ ººÏØÇÃG.Z–Uõ3PUqhÛÕY×èl»‡çyd³Y‚ à-¯¼¥:€'ǶUÅ`*uàv£y*„s€üè>ÖP>¯¶©TR¿·´¨°0•®®8|Ìÿˆ=zòNPaj"¡‚E×ÒæþË¥Rê±C”×j]› ªÉŒNÅ㈃ǎŽÖ¬Yþ¼dÉ’š_CµråJº»»k^×ÞÞNGGmmm¬ZµŠžž–-[6â'Aqx‘q@ˆH:p™n‡áy^Ø’Bÿ®'‚Ïó0M“T*E>ŸÇq²Ù,Éd’3föÁ£ŒB|,q@ˆc‡ì!@Æ!„Œ 2&ËŠ ÙL³v¶”Íf+ËG-Uãac2™ Öý+G<ú¾_5?d:«.‰S«[Œ÷ ÑÁ[2©æEª+á\ 8¸i,nû’I‚æó*8ô}(Ñcoi·ÀÚzø ú»aÛ°~½ú¹\VAb:­n«çpÔ?»5žDD× _³¨¹qæ×ÎdÊŽ‘…ÃûúúX¼x1Ë—/gݺuôôôÐÙÙIcc#uuutvv²uëÖ!ÍÙÑÑÁüùóioot™5kÖÐÚÚJkk+ÍÍͬX±‚îîî0øBÙdb b±öÞw]—l6î4ê–z'N‡ ÚcèêÆT*E©T"U黑Édøë¿þkÞýîw÷ëIÆ!x,q@ˆ£Ÿì!@Æ!„Œq†Q]äV«“¦ïûäóùpE=碞ËÑ4MLÓ /·j$—¶}p^-®ëâº.¾ïS__O©T¢P(L&Éår̘1£z®Ãƒ¿ÚUª:J¾ •ÇBUŽEøØÛ…€¾¯þ`å2‹Z»ærj¹Il¨‘öš¦ºeE)s*¥.×mUƒ¥£û›øs?íVwž¾“™/ÎÑÃvðxóÍ7ÓÓÓÊ+Ì÷ØÖÖÆŠ+X½z5===ôõõp}ÍÍͬZµŠU«VÕ¼¾»»›žžš››ÃËhll ƒO!Ä‘MÆ!Tx˜H$ª&ØÎf³455‘ÍfÃÖª BIˆÎ^ *;z'2‚prðd2I&“¡P(Œjoþ± cö?È8 ıAö „ cBÆ-6êºbÊ5}¼Èq|ß'Wi¿?Fê¤õ±i¨–«#ÐêS©8­’ÉDÛZ& ÿôü+Ê0wž¹†…µT5ÍóG[ï`öógdÅ##®xœ8œõôô°fÍÚÚÚX´hÑ Ë566ÒÖÖÆÍ7ß¼ßå@  ƒ^¿uëV€ªÁ`æÌ™ƒ–Wk»wïæ‘GaæÌ™466Žè âHÖÓÓCOOÛ¶mïM©i,Ç€mÛ¶ÑÙÙyÀûâP ‚ l7¡ÛP¤ÓilÛûï§R),Ë¢¥¥%œˆ[ºâQ÷Ê·, ˲p]·j§Nï\vvvòÈ#°{÷îñ~è5Š}‚Z·âXÒ××ǺuëØ¸qãxoÊ ö7ŒtŸ`çÎtvvÊçqÌëîîfëÖ­ìܹs¼7¥¦±þ|°qãF:;;Y°`uuuãýp…7òù@>!Ç ÿc†¾MMªx.^øV+[*‹˜¦I±X ¥R©0dÔs9ƫǂ®¬ljj¢¤ç8¬zP¨¹  €š{p(Ò騚Op½qýîÏfdÕ—ñmóýÚÕ†ñ?Vžê9>d©ð3]y>ú,$N 2aã0Ùîîn7àŒÇÎÑÓ0¬ŠG=)kkkë—½úê«éëëtÂ×Ca×®]twwUg71ºòË/¿<Þ›2.^~ùe:;;ʉ¥Å‘C‡„ñö¨ºÂѲ,’É$]]]xž‡ã8X–E¡PÛ^ôÿQÅ£¦[gô_Nëì줻»›]»v÷ÓqÈé}‚ñÜ/âp°uëV:;;ëàq,éàQ>ˆcݺuëèììÏBÈ1ÃÃÿ˜¡ã¨)ÿúwÜìŸzžG¤R)|߃ÅL,„ŠW9Ö:n4ôIõ‰D¢j>Éê­|PAÜP‹êËu¡Pâjp©n­jU. ös› ˆæSô¼-^³YuyW×ÑÁæ¶4QÕ—‚0Tæ´ÕêºuëøÙÔŸ±æ-#kQ<¬ŠGýϸÿºrœ^¦»»{ÜΚ1cW]u•œ¹$ŽyÍÍÍ477éLŸ£Ñ©§ž: 5´c-›ÍVí`µ´´J¥Èçó†A†A¹\®ÚñK&“‹Å°ý…ï˯+õ:ô<º}Å`;mmmtvv“®eŸ@¥¡¡¶¶¶ýΑr4›5k–ìAt2ñ±úùࢋ.’±@äó|>BŽîÇ ‹EÕ½3ž/雾ҹ®N»?~¤–¯Ýv33œ6¥ûáTÂ8˲èêê Û¾ÚÒUWæQ¡ß:¿‹*u ‚Á+ý†buþä*ëHYTÅa õÄ:Nõ“®ç”L¥Ôu¶]]Ùhš*pIûZ‹ÚÕŽ£) dXq‰ú|ÐÐÐ0â}‚aU<êÆýÏhhhðZ/3Z-Œj ~ÒIˆÚœáL¬{q@I\×¥©©‰úúzêëëñ<|>OádÚýCGˆvüú‡‡zþF}¹&S±-ÝFÃÜ_/÷£€ŒB„ cB‘±@q4ŽA ²¶Z›eUwïÌf³xžWuÜh,[©j¾ïªTPO”Íf)‹žC2‰ªÀ+ñÎt5áHç¦Üêÿú²®ØÏzžF?¶L2©JNAýAú·M¥††ú¸ÞB…ƒG°a , ££ã€ËêeFÚYšýÛ!éÞËBˆ²Ù,®ëR,Éf³d³Y‚ àÙgŸïMÄx+‹áŽTœçyáNVSSétºêºL&CWW¥R‰r¹Œïû$“I2™ Éd²æN˜î³_k1“ÉÔO>Ÿï·P(„S ~Dó,ºÔn·šÍª¯8ÛþÜŽq{*íRëëU%ã–@~ßö£ÊÊZ÷](ŒìþjV†ÌÊóámu-Y¹14¬à±®®Ž¥K—²råÊý†¬\¹2,Ï©ÖÖV:::èëë`åÊ•ÔÕÕqõÕWí³$ÄD—¯‹ÅðŽAÇ!›ÍòóŸÿ¼fxr$q@Œ'ß÷ÃjEý ‚€––ZZZH$†ã88Žν˜ËåÂùõü‹C9ãl°v:PŒ“ºÊ±«+:=ëPœÕ6^d,BÈ8 „ „ŠŒBˆ£uÐ…uµšZe2ªð¨šŽGW;ŽvÕ¡Ð÷­OŠ×ÇÂj?8¢L‡mêÁD˘f4¯ãh:Ý€‰¤ÓêIö}H&T(÷SSM¨Y*E“iŽ&ƒAçX ¯Ï-ŒMøè°ÿ¹,GÁ°æxuг»»›åË—³fÍÃ3 t_øîînG­?r[[7Þx#‹/¦®®ŽžžÚÚÚÌ5)ÄÑF‡¦i†A¢eYjL ë8®ëâº.†a„Ad.—Ã0 ²Ù,sçÎ=p™ûaJÆ1^tÐX,ɺ …BØ6Â÷}LÓ¤T*‘ÏçÃбÖ<‹©TjÀܵ(8Œ¯#™LiG  „2!@Æ!„"câh‚ .v×0Ôqªd2‰çy¤R)Ç©y,j4é‚]Qéû>¾ïcÆÁ… T‹UÄy•Ë[ZTè§çPL§Õ2šn°á®ˆµGÕ÷á˜* ‹ðÖGUwî¯hR_×ôŽòý»¾Ác]]«V­ «;;;Y¹rex}CCK—.VèøøãzŸ«W¯'¶\°`Á;pq zÀÖóÁ%“I,Ë"N“L&qÓ4 æúì–T*…mÛ´´´„áE2™ ƒÇÃŒâp wš²Ù,†a„£çyX–ESS–eQ*•‚Ã0Â/ý^¬5Ïâhµ@=Z[©ÆÉX „€ÚcŒB[dŸ@2!Žq@wøÜß9éú8•.BÑA`­cQ£%NcFÕ}‹Å°èeX|,SUúå=ên*|í®^œYPU—šÞþ"j[ ÃXïhÊ¡*0¢–´GˆaÚÒ¥KYºt)===ôôô*tËÞɺ²Rˆ#…$†BWMµ´´ª,]ŽãP(³WZZZj¶lìêê²,üÊä·ú,Ó4I¥RìÞ½{¼Ÿ’“q@Œ=_£Þyµ¥ßg¶m‡‹úúþïo˲°ò€;{Ž£vlF°5Ög²Îd,BÈ8 „ „ŠŒBˆ£a•µårƒW;‚ê|§¿û¾mÛcÞ K«Îf³a¥e¹\Þ±©²«Úª:ŽjmšuÔƒ³í±iy:˜ª3‡ G›t qÙUõ¸ž1Ÿ—q48xÔÆ:lâHV,Éd2xž‡ëº5KÎu8Y,Ãö¨ëׯ Çq0 #¬pÒý±]× ]a èø …K–,ï§Dˆq§ƒyÓ4)‹áÎZO&“!ŸÏãº.žçaš&¹\×u)—ËìT*5 TÔóÈé°R¯'.™LŽi_o!'zíøkÞ÷}Òé4år9|/ <Ï£X,†UÈú=¬Y–Îëïkù5ªMÓ¼½…iB±¨BG=Iv:­‚FÓT¡dSÓÀ@2D‹á^hÎ4¡¾^mC*U}J\6«î'•ªª œøÒKãýçB!„B!„1ž]]ƒw ‚ <9>“É`šæþA‚D"Žñãg©Tjè¡£ï«åuYÓrÕ¡#À÷s*dïÀ/…jsš@µ[jkÔ±’\¢°#)M½c»¹< 1AN§«Z0AVIéŠGß÷ùu[GP!I&“Á²,šššÂËk صÂ˲(‹d³YR©A ScQŠ.Äa¨©©)|ß Ýuðïº.ét:lYœN§Ã÷J5ÛCTýW³mE¥ÕD¾eYQ÷¯jö15PÕxM’ʼADã;D‹®ëVUR¥R)\×=¨¶¨z]úl]Í%ÄÑÊuݰ¢±¥¥… hjj «~ã}æõ™_žç‘ËåX¿~}U }¦Ö`Վᜈ•¹MÓT·õû˶íªP^W ï÷ý’ÍBK‹úê¹iV·:5 ôc{CétTÙ˜ÉÀúõj9íP´AÖ'TèaÈCíÍš&ÛæÏûûB!„B!„ûÕÒ¢7¥RQA`Åb1œkq,çsÔ…7úü…ŽZ­B™Õ¾t2CXf¸|¢ãeCz ¨04? Ûä3òJN³²=ne]# 2Ç€â˜---áo®ë’H¨h¿\.ÓÕÕEo¯šQUW(ê³:tTÃ0ð[Äu]òù|Pêܲ¬Ρ¨ƒÅxÀ¨ÔaËÆQ0Ög¹q¨è¶ÇzÞF×uñŸÇ4Í0pÔïËB¡V)êêäZáºëªõë·d:­öi’I•÷yžÊüÂmÈçñž>Ï[\¹¾Oð•{(þú\ì}v6ÆY^¥ÒÐN¥Â©ú-­ûïÇ +=Ló´A{Åû~ížýiC€IDATŽÓ¯ÑQ',ežûë`»w!ç]@¤ç€»QÍÏ],ÆÎŒ³,õD¸¨!‡áO\-„B!„B!F•ç©à1“©}Žx>Ÿ§X,âû~tbýù¾O6› uA??¨)ÀG_.G¹t÷/ßW¸öÛi u¬j(w©ç{ÌV~§Â`xÁ£–! ÓDaäPèŽf£>¦*_zÝÙÊïý?•mc<Š#’ã8áYúL Çq°m×u±,‹b¥”[Ïÿ7XPgÛvøåyÅb1 㕃Ñ÷:x0ÞØñû´,kXaa„Ó³áûjì>Ø9!…KºúO÷¥ïÿvÑgTµ´´àUÒIÓ4Éd2á|Œ•Φ•ÜLU:z^ªêNÒŽã@¡ ÞŽ£î»PˆN¨ Õ¢bß¾ÊíR)üÏþo÷•äõx•ÊEïñ‡q{â-nÃjiQs1Öx\ r<ÍqÔýxžzÌñ·¢n“1@¼9ø¨ÚîR)Ú7ÓÕŠU;›6þœ•ÿä¦;ÀõÁý+H¾ÅÊý8ßTۓɨuÍדÏCÎDíÐÙ¨³±ºÆû•"„B!„Bqì uL)“©Ï¹®K6› [žŽ¸%xîg?cÞûßO¹\Æ÷}ºººÂUIª@qc5 X¢5U~Ï0²à0:N6’z äy¨ŠÌ£ÓBu$ìÊöèm*W¶Qo×Á¶—& Å%‰žç…m!ªLt‡d2I¡P ‘HÉdzP.•J€:£ª[2lµj¾¯B‰LÆ Û¬zýz@§,>›Ucy&£ÂË’©ÚÄáÃqTp¦»‹ößÏð<Ë.ûÛ·¯Ã²þ÷Ÿ¢£cfÕ>Šç©°¢.—Ë1a‚Zg"A`cÌÚGÙ€óídß÷"¥»çLª÷„“8¸ýœ+Ô%•Â{p+FùêÝmØ;ÞAê2àúÙ׫iƒJhZD)tx/ÆŒÚV£Òµ´’§†­ìu$.ª]ê`®W¿'Cò\pŸWÏ™mG'èÇ`à6©“¦öå ñÈïR÷Sœ;Áþäž÷‹à–!Ø­nïy•ªÏâ8“!—RÛ\F^ý<ýñéãý’B!„B!„8æ:Æ•J >N>Ÿ'“ÉT?è;0ÕÌ65‘ó}zmCwÉ‚áuÒkiQ²õT>êdú4êàX‰Ñ­#¶MMD­XÇ“žÓG›L£‚[´æÇ~%x‡5Çqð<Ïó‚€ 0 ƒÞÞÞšÁ]:«¦ºº\ÒÓÒ¢*¤ôªti;ÎÁ¨ßýU<êÛéQÏ—ËEó/¥2QµÆ{×Ua£~XºšªVð¨«Å„MúL,P¯SËR¯I]}kYª‚/™T—Í›×\óÞñŽó8å”ù´´À)§¤˜={6žgÐÑ¡‚· PïÃDB½öup™Íª×}Ær[U4ÞxÆÊÏc{ÿòyÌŸßË·€9ÑkÞqÔ›2HøëémÚ¢N€2 ¼ ¬·Á“ïýw,7[õøZnªcýú:ŠYusÛ†ÌI`àõ{êL¡ÐÁ\0gCâà°.QÛ««-ÕJZ 0^…Àþ¿<Šu|Ë£À0÷zȯPÏsÎÎs/ªòñsàÆ6`°Òÿ¥‚[çvHÝŸ¶f#àZ`Ø•1¯¬_Cç?.`~òéñ~Y !„B!„BS*‡­-(ñ<×u) ûƒ Pæ’IÜdRSO¥Øzå•K—ªjÅdrx-ºÝÙ޽ï—7ÌÛéðQÏ­˜eøÕ£9{Yîù•mò+Û5žÇèMÔqL6f+ÛsÂÚãÆña‹£Œç©à ¾^?ºjiðåU+SýTE£.#O§Óa;FÝŠ1—ËQ.—­, a`¯FŠo¯ãè *uYe3Èf£€Q'taÍûõ¼¨ #P©²ŒÏq7ôÑE–µè ÇlVýìºÑ}T?Ö€–u½nkÙÔÔD6›Åó<ç0˜]V–\WS ^[Åb,@Cí‹ê{"¡–Õó*ê&Óô˜7oóæM`òäuìÝ{étšw½ë^N:éõüøÇçâû¶­NŠêêRŸ~Í:Žº<™T×ϼLqÕ$ C½öƒ®õØï9E%”–…±áAºþ_guЮSÃÊSžE6«¶UŸˆU,†  Û è°Ôªõ~]þ) ¥5`_ ¾ ´€ÿeHÅÇÀœÉSÐõUuÛL¦²¾@-ëÊBösàN,õ?Þ8zc ˜`yàþê? ~¥Â ‚­ØÎlhÚæà÷¨ 3ùîJkúލ3¸¿‹*@õ ‰(þ²¯Âäí“Çûe'„B!„BqÌÐó:Æ‹aúËçó$“ÉáU#‹0o{Î?Ÿ¢eáû~Ø=pæ›Þ¤îXÏÑ3ýç²m5MÑ0ºùUie ®ñqˆÚ¯¬Ñ AìK¡HPa_ž($Õr#|ìÃyœTd®ò}ŒIÅ£8(ºaüËqÔ€©ç*+ÔrÞ~ÎZÐs4ê FéÉrmÛÆ4̓žÔ¶ÿ˜©C“¦&uÀÝq¢ùnÃV„±ùäôvWº¬2eÊöp]ŸûÜL,Ë"Ôø­+#uuQèàÄ+¸ÂyÖ*ßõ²ú!éj1†èç*!K×_ßÇìÅq r9uùƹùÈG&Wnà8–eÑÔT ,_þ ÷Üó –-k ÿQe³Y|ß絯}íx¿”ÄaB‡}UN˜…WÅ¢zŸ˜fô~‡¨½h©·Ý¶‹R©—|þíø¾¶;V¼ €õü÷×qÕU'‡­Põ U†½gËeõúÖ J—®Àñ-Ì‹Ôe)÷Sð‘Ê&•RÔŒˆq¥ßwŽ£ÞãMM¹œðý¹Ütä·Ar”T–-•ÔãvÏ<¨O¨÷¼7U=ÅgÀ›vÌã Ó†ì«K=>»š–ƒýLÔY·VÅã^µßÑõk0ÒP~3ÐÖ=Xmñ U¹`™`<¹MjŸ%ó _©½ŒÿûÓ| Ü€ÀÝ¡Z¶&ê¹( ð¼ZÏ¿MÜÇwNÜÅ•ãý"B!„B!„8F‹µ§(ÒæÍ›0´jGß|—+iReNŸ‡¯¹†b±8°ˆ'¾l*Èó3x¦R™P(Œþ|_YTÕãHB0¨LmD¶ò=I4äþŒeøf¡ÚÀBTi˜®lo¡ò³Å¡oÉz«/%xCÖÔ¤B¹T* ñôÓTçá8*üzðÁ |îsÿV-A€mÛäóùpðô<Ã0(‹Ø¶M&“9¨ùup¢«õ|qºŠ*—Sc°S'ª,—Õíu…¢¾ÛLFMíÄ÷§†Ë²eoÆuÕý$“aѦuwÔ'AÜìÛUŒY–~ººf‘ÉLÀó\::æræ™gò¥/}bñ,+ Pø?ÞÀõ×_‚iÞÉâÅW°zõêëßOSÓ·¸é¦®¼ò¸ð9½øâ÷pï½Eî¹'E]Ý÷yàï_üâ¹”JIŠÅÙ¨;=ßeÌzðüX÷ƒ$döŸžC}ÒB8/å›Áÿ¯B°‚ iGûdµV„«šûxæ™SÇû¥*„B!„BqLÐ…0ƒexÅb‘ X¿~ýÐŽçóƒDÓdÉ´i\2kÖ§" PDz\Ôq©ê,ùG›`¢s’ð×™ÑG›ž»Ð¨<Ž,ªòP{µžÊ°ïl[¦ò壦d*V~>ʧI“àQ ªX¬ho‰æn‹W'õ/2Òm<‹Åb80~õ«¿ K¹uÀè8¥R) 'úÓ-S)u_ú÷\.ª¢ÔAH*¥¶/YÉ"2™¨bʶÕí]Wý¬øëñ¹Øô™&º"*™Ô­ª ð†n £#ÚljÖñ÷¿—ã?žB>÷¹W±íãÈçášk^æöÛ§aY6lheÖ¬¹|êS;xñÅ'™0áöìy7Ýô4×_°qãÅlØ0‰ÎιœtÒF\÷ >ùÉÐÑqüãç¹óγgÿ˜w¼ãÏ8õÔ©<÷œÇ÷¾w>==»ÈdÖóþ÷¿ŸóÏÿå²ÉI'màç?ŸK>ÿ×€z\†?üá{¤ÝêQNOP­æU?÷öª÷O:­.‚èú8]‘hê} [ú66îä7¿ù¾ðå/›tvª²`Û¶Éår5[ [–º?PëÑ÷î7Õ×G í+ßÍøÀbØß¹ÞævÔ9µ3á¡þIëVúì¦j§©rÉ$¸˜]`7Aò°¾ –ÁpþR‰ÀDðN‚ÔÞÊݯW«ô_Tã#|‚R´Ù€Ú1óQg1¥ìó µ˜[ãd©m´÷VöÝÌÊc ÀÊ@¡üFȯÝ&§öSø|uè©ŸÓ PóHZ?€õÌ»üWÕ²Us}êëÒ–gyä‘§‹ý‹T1î|p+åòz¶l9Ÿ´„B!„BäóÑ1·þZZZpgèE9Å¢úêwR~±Xä½?úQÍéÈð€D®É@ÆTǧº€b .LÂ× ø2p"£_—Bx-&Õ!_åÄ{²¨c‰‡ ½è·OçÀ©Ê6Å$x@ äóÕ-H]·ÆAë ÏóÈWz’ê KW,¦R)êëÓ<úè’ÉdU»ÔT*ºÍi*žµF,•¢ö£¾¯BÆ ˆZ?ú¾ T´L& uèèûÕø¯Û«Æçj4ͨ‹c±--ŸçÍoþ(ŸûÜÜðºx;ÙÅ‹ïä·¿ý*wÝõc‚ÀcÖ¬8þø—¹è"˜6í¿¹ä’K8ûìÝ\{í$žzª›ï|çÏ9ñÄ“¹õÖËÙ¸q;ŸùÌëih¸ƒ={’XÁå `Ûê`à/~±–™3_ÏâÅ9òù]|øÃ'`Û‚ ú›ù>œp¿3{ö l[µ`;W]gš4\üÏ~—fnàHðx4ѯÝÊS¿o‹EÕr½¾>z•J>IÉ÷=<Ï#•J±nÝ7 ‚øÑþÃp¹ùæìÚ5‡|þ+q¬|è"Æ—`>±7c¹•TZÖÀ™ `ƨ‰A…„yT€V&š´Ù]·^]ï?æo õ.0¾9Ÿ°Õ‚®, ¬À=2ë*ëô!5§zÞUÛŽæßŽŸˆ¶oð*ÛU‚Œ¼i?Ï‘[-¢V† ?ÝV(þ¾ÆíjtŸÖã^( v;ïSÛìû>–UIfMØ|ÆfæÌy”¾¾Ç†ýºB~‚ À«ìœxžGA€ïûìØqÝÝ—ÒÐðùVvì¸XÈqÇMÀ²‚‘ݱB!„Bˆrݪ‚b—»8ŽCWWWÍ“ûkÒsêØ6®ëÒÒÒBWWÙlöÀ•ŽquLË‚‹ŽÛécùÔ±ª4êx[/£W­7š¡c&Ññ3]À ç[¬{#3¼UÚööü’‡ A¾¯Æ%]ô¯(Ô¯uµ`6[]Y£h¹®K±XIJ, Ã`ýúõ&»­¯ŸÇÝw¯çío·ÉfÕú2™h®16êíI§ÕX©+›šÔeñq22&ž]èjF}µè–©ºêQÏi§¯+n½õ½¼îuOðØcçqî¹yôÑ9áíO<ñQN8á.~üãåÌ›7r¹ÌÓOÿgž™cñâ€L¦¶Xuv‚aL®@'²`Á‰Á§xöÙX+Ƙï~· ÞÈë^7+l# Õ­Éç N½ŠÔÆÿ†´ª3l;Z_Þÿä¾å¾‘¯ÕÝü`^}b´è×k|~Q>&“꽯\L§Õ‡×ËúýmétÓ4™2e O?ýI¾ô¥òÎwNªü J÷ã“•B8ˆØ݈·ï-ØõUÎ@íXبÁ&@õÕ^µ w`ÿÇãüŸIÿ‡eË–1þ|n¾ùæQ}m !FŸ;"þ3®«Ï¬ð™5ë˜<ùêë'ðÜs47ÿ×½‘… {9ûìÿ˾}[øÊWzxðÁ_ÐÞ~2Ó§¿f¼¢B!„BÕtqbÿcSñc<5CGÏ‹NÜ ®Tèψ¹\Ó4éÊtÍ>™T!€ž‡©?U©ï2¨c`NåzƒƒÒUÅŸEtüͬ<Žbe›õ‹Ç :H§UN ç6Ô]3™ê9×@ z†‘§X4Èf³†AP9Ú®Û+¦Kó€×¾öôöÎâ?þãr.¾X]¦Û &“ÑÏ]]*³è_‰5”ùsDWPfjœÁÏçI¥Rxžƒç¥ð¼¨úé¹çþí”J%\7Ïôé·ó¹ÏÍä†örÙeÓøÓŸVc6ø@_þ²ÉÞ½O`Y¹\Žb±H*•Âu]J•Ô/™ŒJéA…ÕÏue>Ê÷> Å{¢‰"+ÿHLŒº®šïÍ1ú¥Ž€iRxáÝp%¹ñ;ÊdHf =c?LÌã½£ùc*ÔûEÏëçºêϯnìêŠÂHMïÈè f}]¼"FŸQåû>¶mcF¸ƒ¢ªä,>ö±¬Xï|çt ò:.£IMu 2DmN l›ÔgÀ»mþ¨‘4êŸ|õO_‡|©ÊåyÔ?ÿáI™EeV8j§!QyÞ¬|Ânˆžëc`<_YOQÝ¿ïƒ[u׊ªJÇþæŒ/³zy]•¤þhÐóûmøþå¬^ÝΗ¿¼PÕå®ë’J¥0 Ã0hjj¢P(0cÆÓ¸n]]]˜¦I6›6bY¶m³~ýz‚ à髞æ‚;/à¿®ø/~øáa¼"…£)>&›¦I±XPµײœ-—>À+¯¼Â´ig0cÆyày¼úê œyæÀÇøá×òñoâÏþìµ<ýôÓ\:m¼ý<þùŠÍ4ÿr6ù|™l6Ë_û oZ@Îx’3†>·¶B!„Bˆ¡Ëf£‚”xÁ‰ëºAvÌÕj9¨çSÒñcþŠÅb8å™îBxЊÀÓI0‹ƒWí€:VfW¾’¨ðNß>[¹>…:ÎçU–;éncÔ1H1f$x<Êè“tÐLFñy uec­ñAP,ÉçóaçyánºÂq(Lz(Å)§¨Ñ0Ôvé3•RÛkšÏô€~m‚çy˜¦‰aœtÒ`.w“Íþ”T*E:Ʋ,ŠÅ"¶mã8¿ùÍûhmý.ù|Pæ o˜B¡PÀ¶mn¾ùT>ûÙI\~ù$®º ÊåY´µ-OqœÉaÀ8{òdöÜq×¾óxëÖU=úoëF½m+z2 ™Ëï%¸íwðØJõõRÔÕ~²ôJâÉm®ö)å_Mâ+_ùÓ_iâPpœ¨Í°®†è½mšÕûƒí¤Rê+ŸÏ“ͺá|«ú}’Éd°m»ºjÙq°<‡îß¼^íHè §o°à­ø´ ;LµC¡'IVªs³ïƒ’n! EÝ*UŸ5•G…p…ÊzDó6e,ˆK±ušÛÕŽCOìwêÇN„ê±j(Þ õIù|>|žõXcFxöšç{ÅÇq°m; “É$ù|>Üá\²ä44ì ׫CGý÷Ú·o_Í¿­VÃ00®0àL˜±iÆ^‡Bˆ‘ñ}Ÿ“Ÿ>™»óßÂËt u[TËJrÒIWr çðÆ7žÂ‚0cËŸø\Ï\¸Vú2K6O«¬)ÏÅ_ÌYg=Í_ýÕí|ñ‹áüóË´¶ÞA2ùz²Ùáó~‰}ÿð:êWÖãå=&ÒE—Ï“ð§×Ê>B!„BŒßWçíW:¢†‡u}ß§¥¥%&x8…‘Rí8æ$x< T áFèªkÝ~±XŒ·ê6¤*dô}?< îû~Dè*UùxðgÂèCÇóÄŸ¥\¾9Z9££3™º82dáås^ÆM»|b÷'È! `Ûümܽót-šÇUg]ÅæÍ›ùÃkÿÀí·ßC"á3qbϾò8‡mìÙw*Kæ}šïýþiüמ¼‘YSg±å¸&Ú^>…mÛ&±÷í§rõÜóà^àDàîVuöD*\vËe˜Ón Ô¼Î_õáéÊÜñ3Íô‡½økU^·B!„B1¦ŠÅhÚÄx{Õ È751çĹU_¡[&“QË3=™˜„Ç­Ö¯_iša÷«Ë26•úsg¼˜ÀU—(tLäzÅC‚Ç#€®Zt]5P%*ãÒíK-«ºÃ&¨Aìž{îá#¹†Ù³¿YUqcš&–e…U£VASÃþ怌œ×ü°z(NÓÕÕU4ær9’Édø,Ëb}¹ ¾¥{™º.Tª5¬“6`ç—V÷mާµÀô¿û;nö}v¿ãX¸`@8˜üÑ{÷bvÈå°+Áoøôå0JK©áÑI·8Èvz?BW$ëŠÆxÛ…¡ð<ÏóªÂÆ[Î;œu“·oçõ L zbiØj€ÀöL7០Â==I´Ee®F0]ÔŽBÿ¡B¿¤sƒ\Wé—žÔó:,µr€·ŽKôÉñ±åœÏŸÊǼ_ẓà %]­hšfUð¨+„ôxT*•Â0Q/¯…ãK÷õhŽ©)Ù;|%P;É£0±8üÄ[¡¾ùô7siþRþrâ_ò驟fõ+±mâ$n=åe.{rÿ²w o¹½“ÛzÏâ¡'såÕ2ã_TÃà+`ó->zîûøö#ß&NÁøÞ)•{ÑÕÌñ¶Ç•ëR¨*ÅzÔX껯”Äëù›-à>45ÁÇ 8ÛRg=Åw ñaršŒh²ßø$ھϕ?øÛš¥âñ°Çêb¤Ó*©Ôsþa÷'v³nò:L<È_‰©ŽEŒÖaæJDzCB;M!ã1@‚ÇÃPT¥¨~×s –J*”èêªaé¶©º…*À”)ÛinžÍ'?Y>`eÍX0 #¬Š·(tß÷¹èä“yÍï~Ç®nà=_Ì‹gÅW\ØÿÙœ9œëyt%“ÏcWÊÀÂù˲YUªõ;Rož?Ž·£'M÷ÆŽ[¿>ÜÎÑ™¤Ç8¨gyŠÚÁ£C8a6Më™H¨÷¹u¤Î‡¤ÉLeÙ¯¹Ðç©×´e©×j¡>ì½i/¿9msý2}}}œúòËX»vQZ¸÷n_NI÷+­ÏªïÇW¶%‹ “¨;r Q¨géÊ2åÊ2zÇCwÜ_ëƒÁÞ69 Sɇ{€TŸàUiehF8ÿ¡>¡©©‰r¹Åb˲Èf³d2fÏß7Ôü††ž¼0XéZãÀ°{å}8õ¿]‰+þ[úƒçž›ÊOìeþ©ÛxfÛÃLxjõ[ê¸{çݼúø›Ø°w+[7neÂöxˆãQ|ÀI'}㎻۷‡?a7§œßÀÇ&4r¯7·5tá½hò½SÈd`¶Ù̯Èg X\ˆ™„÷¼g-ïl¸ø¶ýmà ª˜MÔxì¿,B"­þô?ÉɲÔ\+€Ïð • IÔëó4ÞfÁ4ÔmklÀΩSÇûÏ%ú+uµ‘¡ze}¹B!„â°긟mW|{è—¿dÒ5×ðoÇ…Ón¼1ºRwÑ»8' lºqS¿=•çÞþ“¦Oâ¦oR˶u`Ò… >¤ˆª -¢53öÝý.µ2b HðxЭS=O‘N«ËL3šãMŸœ¦ Å¢S5ǘ®äÑU€årÛ¶iiLæª1/¶‹·xuÞu]Î:þxúúúxpÆ îºë.®½öZ¾±aC8§Ùö_ÿš9wÞ©R™Š†B®¸":ÐßܬÂB8Q%¨Q|?Õ†©OžLÕ„rƒÉj0»¿V—â%j P@ý“vú-ãAÐÅBð*ØN¥ºñ+À­OcŸº‡Â•ÿ‹Ùñ¼LÊ©u˜@›3\85s`ˆy̪‡o´~ƒ½ö’~h ¿:µÄ”óÎäW³fqí¿H¾ô:µ³ÑE% É©ßTð˜ªlo™è eÿ6‘]±ËŒ~×ù ›¨–¦F„&ÇÁ¶í°er>Ÿ[Ú¦ž¼`Û6®ëR(Èd2˜¦ˆº½²>Y¡P0ãsµÖ2–ÕÞ£åØÄcS–èì¼"‡Õ™zº{²aD'0YVt¹^Fw]ÖóËšfô¯VK¥TU¶žCºx 0˜¥®×·ûÎw6ñðÃ'ð±=Ê—¾tnÕ:nºéIþû¿ÏdÛ¶I¼õ´Yçoç/Ï`ò®Éá2qáopÖ©÷êå—ßÁÚµW°eK=[¶ÔsÁw²ç…=t?óœ7u3K¦<Ï'‚óh<á9^Þý2™Èù|Ÿò>Îã+<Ì5쉥2W·•¿<~6wLŸÎYÛŽ§oâÉüä•·Ñ»çuØÀŸ¡Î¯HT–ïÞÒ·‡+Œ8áÕSyÃ~Ç¿¹y"Z+åqþqí?òþ‘g.ù"·¿x;É|<ƒ·ø÷B .öPGÇ-ÔEü½^©6ÄQëÆ¢ºg{ÿq¡R™YÓ~ŠýŠÅbXIQ•‘®LL¥Rø¾†‚étšr¹L"‘ \.‡Õ‰Z*• CDÓ4ñöÕ2UÞâ(æ£Þÿ½ßt°3ÔàÑa@õpÄBÁ»À|¼·©Ëôù7Nüä†=P¸_P'6”~ÿò/{X»vR¸ÈÂ…½œuVs™={#W]µšµk¯æ…gÎäÄÉ»0÷ÀK“zÙ¸w2í;žãfÿ‚3^™ÆïúÎfúÌÇynûé¼òÊÈçÿ)|pÅN®åÇÜÉÌg>s™Þß&6ñ"·Ãû/ç,úè ƒ·Ïx;L€mË{ØÎK°ïUšÖ-äø Ç³Ýø.êýí9€ÌÏZ©Ÿ×Å®w±ø¶wqÒî‡9þŒã9cÓn^™ø æúÓ8ÿ¥óù§³ÿ“7½8“9u¯ráÔ¯²l§y|㦞r:? ‹ßr»¶³p[žm§÷0÷¼‡¸àÎ øýkç“óN`Û+¯£÷¬§¹öÚãy݉zÞ4sf¥¥Ç>ÃÀ L¬^²&sZålÑ7Q½›b±]ljþ:‰Œó<µŒÞù³íª¹tñi)[ù¹ÀÀ“²ô¼Íúñe©>±IÏ­Œ˜•mŽ·™-£ÎˆÏ­ŸƒøÁ}»ReyBê@×!šSÆ­Ç$£õß©+ö؃Ø}ëç@‡Èú±Äÿ®ÅÊw“¨R>^Ūo§ƒçJêï"Ø=gn#ØÝàoQ_ÖlNã àÿ‚`~‚{!ØD4¿õµ`yP|‚ÙªÓ†ÿ{u•¿ü­`ÿ­Z÷Üç"„B!†@ïcƒ:æVÙÏLT:””06¬]»–¿ù»¿Ã0 J½½y#<†î?XðÂ/ðgù?£ð_žñŸá’¿¸„Kßwéþ·Ã$ªµÑŸ!âŸ/Êû¿yUÕ££ìˆ ÛÛÛéèè ¯¯E‹ÑÖÖFCCÃÈW<Ê‚@[Ò•‹zŽÆBA¯çfÌdÀ4r9? ô\ׯjGjÛ6†aÉdÈårÑÁt=IœëªXñƒ\Ž•ùΪªýb¸míÚð×M·ÝÆkþöoé¸ÿ~’É$MMMüï…2·£ƒY³f‘ܲ…S§òé~´ª éƒgžÉ–-[8oñb°,æ˜&çÆCT n½•Éûy®Â‰í„¢C>èvgºmA,À à:pþ²Ïî#µça¬sÿ@׌/cÕ=ïHÁ3Iuû•çÀƒ‡ú≞ÀËfy¶ûYVlYÁ»_}7Ç7eYü£õáûÿã|\ݡ̣ºÕk¼’1Î :ˆwYº’Ú0 ŠÅ"©Tªª­i©T"N“¬Ì#¦B mÛ¯/‹d³YºººL‚ÝÕÕHx(†çŒÑh¨µ²ïÙ>l«úpå³· üÿo6p'°’/@öËj±Ü'¡IéaLëU¸ö’ítmìeß ûxöŸfòìÌXÿ&þ쩳yÃÄ|÷ußeç-×’Þõ Yˆ•€I\þÊ'Špßxá•XÞ+œôàËüyïõÀõáCúÙ›Ƥmwb~èi|ÿ—Ìøí N>÷\Ê¿ý-·ÜônþöoWóç­ïáÙŽr´rÿÂûyÛ·±aÃNÞsê©üöµ¿å…Å?À®áúŒÕA@2™äÿý¿oóî·¾›Ÿ|óçœüÎ%Ìýß'¹bñîL&ÏžL`ìšñ(˜}&¾ï“H&©÷ê±íSQ“œÔï×@4‡"œÏt~Æ‚Êo¯¯|_-kÛne2Q¢;}_ úº\4ê¿¿ûÍ%îü¥RQ©hœ¾Nï z^´Î‘¶z>Ê?HŸ â'&賎3T‡^ B«ÞÊõºSAÜPw‡u0—@…|M•Ë3TW½êËô¸¥C<‹êy"çÅ.7b÷¡™•ÛǃN®Åæ„o£+;uU¢~Ž\ðwçÀ?‰èm8ì ¸ó€`]^åùðñÝC}Å–‹±@Q‚ :^s å Ú 0Œè+>EŽþ÷ï4¡wâ·óûu“±í¨ë„¾­çôn¨e,K}9N´]u©ÐëÓ'ºk†¡Ž=éÛe2Ñá$-™„ŸüäLN:i=G2 „‡døDO™3q¾¤ÁZ¹%¨;ï_àåÿä¡)SøXëçùȵ‰ŠbûÜ~ÆÇH455‘KåÈd2U½ÆœÉaÕÁI]ލàQzÀhoogÙ²e¬^½z\·ËuÕ›ÞÔÓ š¦Úy‹ÏÑh©”‡_ÙÃ+gÊüÃúõ<¸uk¸¾÷v8óL>2y2§\~9“@Ý8n„ê½ÐØÞ²çyÌŸ4‰Mo}+æç>Gï׾Ʈ ¸íºëÂû}ö[ßbÅÔ©x¾ÏE]ĆûîcêÛßN6›Å4M …ÆI'ÁM7Q`L rŠqvÈÇ}ƾ>p˜Sïwlj>¬e–y2¤Œ ä~‘ªÙÓu]¼¼šƒÐuÝAÝéo>…Ï/¬_ì{LÔAKƒêö 1ú}îû>g^p&§Ÿp:Ó’Ó(‹$“ɰ±X,bšfØîTW+&“I\×%“Ʉ۩« K¥–eÑÕÕuÀV¥ú6¹\n`k!FhÔÇ‚xÅÊs.¼?Q}}¡¹Ø¹ëÂj÷®é°í&ܯ%õFHw‚÷¤ö‚øO¹ Nϯü ëQâ ïz÷ý÷sÑY—¨M3áûÎ^7‘yÜΊo-cî³\wÚ&æ¾i.s÷Í >˜AÀââ}êFñž¤Ÿš²nû2 ú|èîã#mƒ½®Sןì>®Ë¹ë*7Èç±û)--ÕGà,«ºc‚ç©AÛq¢ý§ø¾U2©¾ššÔÏñÒéXÂZG¼EŽnj[\·úqößë¯)û[CrØ|6èßú4_ù½ÿ¹3ú÷$ûŸ;y(J¨ê¸ãÀÿ˜3ÕnJp&QÏàJ€§§7·­Øì±Y ü€ßT*­~sÁä|ÈV–Oº•¼½h=úÂ|^í•Ëp© @s–úÕ½2`.¬TsÇÏÂ> Zr•·ïEÕS¸Cu¸eE¡A­c³Rhlš`é9¯O³ ,½m׃ѧÅ·#ù÷`Ç ³_P`ÚPˆ¥FáÂÔ©Ï¡ÿ¡|uÛ$.¾øæÎËÜx’Ó÷°pa/Ï=7öR¾)Zçm¯™Ã‡g¼Âe—m®º/õùÎ7 Ê• zxž‹»{¥’êzÞloÀKˉ½ôÀj­~i@ý;ëÙôÈ#À­#|aŽÃf,8Béó˜uÑ}<,Óú‡fñpMd¶] úýèߘ¿ôù:ñ€Lÿ?—G‡p:À³¬ê¿ þ½ë±,™T·zN­tZ]·~=Ì›Wýx …¨îÕÌÙ·Ov5®åóÕa^ÿÛ•ËQ{=-“‰žWýœèôc6 µë w]ôút°©ÿ&ž§¾R©íñãú–ñ¿aüo Ï¡:ýôLŸ¾•#•ŒâhŸZëPzñÅÇû¡Û¨ºªî|ñ7yxÚ… • “IšŠ%ü§ážÜÇ×ö$9î›?à>ê˜1çÛ¤nz7SÿßTø&`ƒŸTÿH³Ù,Éd’–t %³D¡P¨ÙÉPˆ#Ù<®Y³†ÖÖVZ[[X±b¶m³fÍ-Z4´•è³€õY¹:TH©¬ÙT͵l÷¿À›¦$º[ ô3hy»jwcü˜w=M¹is÷íbvïVžÿþ½üø®s¸ºk!÷æïåNþ›ÕÇMdâĉLß}¯ºë¦¿dÞÛœ¨åÏcüÒƒS ˜mñÊ3¿åwžÇ¼•óذa]ö /ùÛ¶BýIóèèèàú‹®âc3ÞÅ×Þý5ÜoºìüÖ›ÙûÓ÷\a3ó÷÷s¶K8c÷T.{ì2ö4°ãÃm}'«ã#>Øg_†Þ®Þê3¶;yõDµºu€õít™¹nao%DårÝr(‡ªÜÒ×y¨³³õàÞÞb÷ßÖ€êy^ä˜ÝQiTÆÝ2ÕE½þt»Ä °3€±»Ó ¸»‰|až£œ%ÞºóÔ—I½õyR¹›}Ï=ÂS…lÃÀõTkâþ#V/Ú¶M.—ÒLºm©çy˜¦V óŪðЮªçD,‹”Ëeºv1Ý›Žã8a¡š/VµkÖ¡`ÿ–§åJ+@½Œ9ÒÊ!FɈǂø ?,Âñ|s}ô?åó\[V­ê¶úŸU9§ç6î^˧]ÎÎi7sÜÒ?Û¹“ÿÙ¹“ °éøãI¿”æÙgŸåÆwÜH¦-Ã_µÿï¾éÝ”J%>ÚôQ …7eo"•JñË_þÛ¶iÚ²…çêî£iïÙ¼d¤‹·ÑØ×Èìkg“˜à”y/ÖBG–eÀž©—“Ëý*zôÒG MÂ÷{&“D‚…® _51}r9.ˆÏ5èºðíosiåöçöŸ‡°XTGõ¶Áª˜ã•~ýÇÝ£¿½m×®@Ôôc,•¢£xqñõÖjmšJ©£† ìq”ÔÏFŒ–ºå¦æ£öòDgÿ¦©ž_PïÛêê?=×óz¢}Ù2ø+Á·£9Ûõ—W9X^ëà;D/uƒë¬<•x@»\†D¥bPÜõ¶Ôo¹ÜEѺ{ùú}ê»~‹êá@ïZô?×qöìÔ×oæÅçrÒI˜:uéôTN;m°ƒ¯~µŽ—^šÈÙg¿À–-[˜3ç¤Ó;°í…L}î9šÏñÀQ ŸëÎ ózÇëælbêÎÌÙ´‰«§pßT¶Ñguûñ¼õÞ{™={6[¶laçÎÊõP_®cao/ Ÿ¬>S+ÿúׇ?§ÓpíÆœÕ×ǬÞ^vìØ—‡blߪ·z*/‹øGÇT奡GUHZõ÷"ê¨zZå¥ïz{Ýœ9|jÇøè²o¼þõ·ÔדY¸°ò÷3¹pëVnê¨þ—Y¸½S¦p¤ñXà¢ÞÇzwZ¿Ïãs¢÷ ¥XOÔòX·ŽëßÚ¸Ö2%ð[Ô]7€¹¼JS"à"H~Šï¯¬² ~"ÚL¯Ì×BêÈÞœ ¥ë¡éËà¿ v=x½j¿C=D{!XT†¹ÉàïRëÚ—& åÁùWð÷;ÔeÆe`ßU6§@é^ f¥B—zàÿ€ÿÙÊGø]`|¨äè&ê„,~Ü ÞÜJ[àoö+Ì·ÁÎsÁ¼¬`ݽNvƒ1çêWm#Ó{<æûáO«zižó('nœÊ®“w±óäêþÖâŸúN!¸"`Ÿ=[§ÿ‘ƒWØ>gÓ±²û^zöò@æê?ÖÄeÆ÷X¸o#³x™ç¬üþ g³O°úªÕLºù$~öÀ6ŽŸøKvLVOŠ¿ÑçîÃä­ßàÒ·¿—}|›íS¿Éñ{ÏbûÔulûö|žý.godõ¦Õ\½öj–O½žƒWŸy•çg?Oý[ÓôöýßÝü]^¾¶[wü/õ;þ—^9í·Ó×ÙÇœí߯2 ÚÏjgÞoâ;ۿ̬Ýë™üêdž˜ñû.x=-“>ÏuOðÜÔçhþÓlR/üUÕËmÛÿý?,›ôO|ö¼Ï2éß?OnÏ¿T¿°ó0븯³¶u׈ߓãeTŽˆƒâºnÕIÌ#1ëÐë *ûú†a„ÇK‚þûÿ#äy–eÚv}ÜGo³îXeFx H?í‘GïͶQÔÙw‹ È꟯>—t¶…Á(ÎW‚>|ÍË<ôP;ÿ³â§4Ÿx¿¹n1}èC\dÛ…ïßIž<ó®¿aÞ¼ytuu…U½½½6Š£Öf³‘ç'40ñÄ©l7_Ëéo?+·]É{>ùv/ùûfœÂ³³?É}ul»x?ýÉ—¸þ¢ëÉ<ÏüEò_ôimm¥££ƒ‹/~3w8×o¸ž•ß“¯hf»0{ölZ[[9óÌ3¹ùæ›™õì,u ðR¸ý”Û¹ì÷­ê´Væ^<£ê´‹¦ ‡3ΙP³…—5ȲšnÉD¿mˆß¶Ö>AüàPû½òaqëƒ[™ùâÌèþ DðzQˆâÛ“¡úC¥žC&þ\Äçµé?Kü9Ðë°úm§^F£ú±÷ß/‰ݺ5Uü9è»Øý|á _àïÿþï‡~?G¨‘Œúö|)€Ìà ô¹°2™œ:bd‚ïnÄ{Ã=xÛÏÆë; ÷¹…Üþ£»¸çžùLú_øB?|Ã2ã`ÇwwàíØ¡}þóêÏTÙy›3go{ÛÛøÀ>Àœ9sX°`AX]¤ÃÂl¥r:&“ÉàºnX*ô'¤v^ùê=tñ;¬ØNæêö«Èd.¨œ ïsíÆœ¶c7Í^…ç6N%›.ŸÍBþàرc¯¼ò ?ÿÏ™ä_x!\Fh= -ùh×6ŸWùÉ?ÄžF—ê<傺:ìë«zª¿>s&÷Ï™ƒaÜ÷§?ñžž'OfÓ‰'ò½º:N\°€“O>™]»vÑü»ßÑðüóLœ8‘;wÒûº×±víZ.¿ürzzz¸àôÓ1ƒ€);vP÷Ê+Lœ8‘÷îåwÇÏE]ÄþðÎ:é$vÿú×466òØc1sæLN=áοürxàN;í4έ«c×£²ó´Óx¦§‡‹ßö6J=ÆW¿úUþõ_ÿ•«ßùNVÿüç´¾þõlÞ½›½gžIÝ–-dÎ:+ŸÇÍd(—Ë´´´J¥È,\ˆa¼øâ‹wÜqœqÞy¸ßüfx?…Þ^äóy>ûÙÏríµ×ò‡M›x©·: =RŒt,˜²c \Û¯ `°Á…sspC&ú\ºS½Ê}LüÊ;Ãúý?ãe/Ç}¤òñÜ/á?ª“À5È]VGö¢‹ rFÔYË|~-¤/'_{#äZï#¿6öÞ¹ÎñúØü.?ðÀF¦œòsx^•áY½@/liO°øüì=q/¿=g+…WÿYݾò' ©gÒ•Å¿MÚņº­\^÷8É_­%ØeT‘Ï·žø(+[ÏcÇ”Üýl/K_ókf>ÿ$ÌPëØþðv¾·p Ó¦>Gù‰Óp'ÿ€W¦¼ÀÞWörÿwg²oáµ,œuÐZw¹Í±û1ø[Îâ Î$Øв!Àa ãm\ÀÆÜ`’ÿ7—"]x°»rýF(üÇ,ž"‡‡÷~s7sOPÇK/Lä¥ÿ~‰N>Èwx”IÇMâ«?Ïßó"¯=nS¦Lawïnö®ÙKêuk9q׉<¸äA®|--ÛVòÊñyvßnvß³›{N¼Ÿ¯íæOÏü‰žžþúŒs9{óï8eÒ)lݽ•­[·òÍ“?Á«§Îå™?=Ã#g=Âï£qωìžñϼp꬧øÂÌ2oÞÖIâä÷O™ÄÄj|ÿÓ¬}4ÔŸÏ£Ájνö\þðí?¸8Áÿ{ðí¼úê«wÜqœôÁ+Ùò³§8nÎøã¦?²âÒÌ<žGÿ’×]ù—|ïÇGoxk×ldÏ™{8t,8å¶Iðvø°9€^ ~hÁ»*û¶àvŽp  œ‰þ –Q%ÿ§[<ØaÀ; 8'‰—.‚Ý—¬áåÏ`°ƒØÆ´e3yyÅ"vÕïbÆ%â8ï.vn:˜Î®ïeööÙÜý®—yÃßÇ õ/°û-_áôÕggãó>'q†ù,°˜»y&›ØÅŽYßfÒÆw›±8»ïcß‚{˜ú»O³yÊf¦žr7¯Ý|<[vÍNe/Ù͉x|7ó-v²“ßs ñC` °˜ÌNÖñ¯á ÞÁ.å9Vã¢çšŸÌä7ü;oæ[la {N½ƒÙÛöÒ·KíÏLzuƾ-üæ´_pzï§™öÊ4æÿÏ<þà Žßw&_=ƒé¯ù_=¾‘ƒLšÖäÌ«›ÿ‚ɶðꫯ²û¢‡ùÿìÝ{|W7þOnÍ¥‰œIJÓ¦)cÚ´8”¶ã0,léhI¸´]Ù°[ Þ‡HÛÝ¥†]ƒôÀ¯y–vá‘Àû@`w»–Y\زԞݲåÒ<Xˆ–¶žRÚ¸Mh=$¨I“’fb'͵©~i$K¶lIÖÅŸ÷ëåWbiftfFúúh¾ó='¹kà⡱`ïAX£¯ÁÑä2\6ÿ0^¿èÝp ?ÿÊ{±á¼ÓÐßÃÏ¿ón¬NîÇ‚óa¹ïSÅîóÿOî^ƒÆ Žâµ—ïÁÏ~q νr æ/|äoÎâëÿtÎ;‡+.ù5–KbבU¸À+ÿ ¼oÉ(Þ^†¯ÿÓ¸fÙ9´ÿÕƒø›Ï5A|‰þøÍ§±'ùZüúW Ѽ~Ö½á ¾sÏÌÇ9À¼Etk ‚íbùÈ_Æ·‡õû‹sÇ€+ ­HB¿ý"DÇC|äÿÛðö…âyX¸ þ_í\ëI@»P¯; ã›çpvß‹X´ì"h»WÁ÷GãÛ¸^¼N¯þg< eñRüÑÍÙ‚׆’|?à|þ(¬Ïüü ´“~ñ9gþ!ü뿎áÞ{=xík÷Âã¹ Ñè ª*þá;ÿ€ó½^\ï8©)ÔZ£­Â/¿À‡nûPjú¡r]«‡ï‚õpm+ãZÄV3‰ÇÑñ¡H³ßt "™0‰3gÎ`÷ÿw¾cV/¾c‡cÉO¬/¾xΜ9õGœ]ïÆÞ³,›wÊÂ_GÅþ!d†çCÝ&v-\Œ§_~‹/ǾÇ`øâÝXå]…C‡áÀ^üøÇOãË_þ2>þñcçv"ºiÖîX‹»îº 7¬t=[ˆ}ë÷aõÏWcùžå©çï?ŽS#§pÁO.þØwë>¬»k]Æë¾á0–X‚å{–ãøúã8µv|yçï> -D|g×}ä:œ¾ätj Šö_ç<çp|ýq\rø‚1üåa4}¼ Ç×Ç'÷|ø°ÿ–ýX¾g9mÀèÆÑŒå¥¯õ| ßï@-*&ÀÙ³g¡b?Fï8ÿk8ºº gãÏãÅï}££³g_€×ûïøÝï>ˆóÎ{/½Ô €wý¸ÜvÙe—!™LbïEaÿ²ehkoÇ÷¾÷=ñGý-oI}î/ºè"<õÔS8wîŽ;†x<Ž;wâ'?ù n½õV<ôÐC¸é¦›°ÿ~<öØc¸è¢‹0<<Œõë×cÅŠøÓ?ýSÀúõëqÓMâMÿ•¯|§OŸÆg?ûYœ>}7Ýt<ˆ ćdÙ²e8}ú4âñxÆ>ïß¿¿¦ïV›©ÑÑÑ Ç¢ÞMç\?õÔSØ·oæÏŸ_éfÏH±}‚§¾ú$Vü4æ-îÀü`ù¯_ÄòÏlÅÈÈÿÅÉ“£¡á_°`Á9’„¼;%‘°°{÷i\vÙeøÍoâ-oy –.}ÞoÄŽÁÆ… ñš×¼&¸öÔ)<¾`.\ˆùóçcèȼç=ïÁáÇ‹Åpí£b¥ªâÔڵČƒ‹.¹—\r <ˆ›nº ¿¹øbàýïOïóÆ€û=½l°sçÄÌ~ß/[<ˆ_/\ˆøéÓŸÿìøÒ§Ÿžü ÿÁäÞ¾tÉ%ù·±aCþõÊè©§žÂþýûç\,(4þ8q{÷îÅOy)žó<‡U«VáôéÓ¸|ÁŒÎŸ¾û/^ŒÓ§OãIEAäb+V\cÇŽá6lÀ?ކ£Gñ»ßý«V­Âèè(aÉ’%8|ø0V57Ã4ÍTÿdëÖ­4M¬[·ǬX±gW­Â«VÁëõâÇ?þ1.ºåDï¹'µÎ_þå_ÂþçÆ-·Ü‚={ö`ýúõøï#Gð_##ð¾ýíøÁ=÷ ³³|_þò—ñ–·¼[ï¸×ë[¸á†Òßu, ¯^´W_}5~ò“Ÿàôg?‹ëïº+õ:·Þz+Žßu665áÀxõ«_¯~uj}Ù‡:w×]¸é¦›°{÷n\ñÁâ+Ë–¡¹¹9µ¼áÀ¬^½‹-ÂÊ›oÆý‹¡ñÖ[ñà]wáæ›oƼûïÇâÅ‹±nÝ:¬]»»/» ^ûZ¬]»{öìÁòw¼¯»ÿ~¼á oÀÅ_Œe—\‚½o|#on†ÇãÁŠ+péþý8pàNž< ¯×‹ý‹cí‡? [USÿÞvÛmX·n-Z„+Và¿ø œðìŠ8vìÖ®]‹/77ãܹsøò—¿ŒSK—â²Ï{®¼¿ùÍXyÉ%¸éØ1¬X!2?ëׯÇñ /Ä{¾üeüþÊ+4 œZ»;wîıcÇðÿðX¿~=pÓMxê©§phx85ßöÎñ›3vî܉øÓOã³;wâ€Oþð‡Ø·oÞýÒKxà*ý±ž‘bcÁ#Ï<‚MóZpòlŽŸ:‡Wü=V}÷1ý~££„ãÇ/Ä\ûSüØ}€÷Ï[ñâéEH&“¸{à‡˜æR(ç/Ä‚ ðÛW^ÀÒ¥Çðîú"V®¼¿{òwhnþ®ƒ†¥°±tüÎPc°Ççz5M‘¯È¾ Ù¾Ãu/êO?\±Ï/:Ϲs¸xɼêU¯Â–;>õë×cÏž=¸ôÒKqÁùûEÁ3çΡyÞ<¼øûWðÛÃ?ÇâÅ‹ñüóÏãg—]/öàúë¯Ç?=õTõjôÞ÷\víµ8xð V­Z…—ý%O`É’%p+_ó|á±/à]ïzxàÜxãÁ•W^‰_|çŸ>ž}ùÿ/x½^$~—Àž·­ƒïàOþäOðÿñh¹åÜ{Ï=øà_ú`š&^ã} þ׋/â•W.ÅÕW_‡zï{ßû0üïà=¡÷ öñ¾üå/cÞÇ-|êSŸÂ=÷܃›o¾ÇŽÃ¢¹¹¸—¾ã¸þ®“¸õÖ[q×]weüûÐCáõ7¿ß?pß°víZ8pïxÇ;ðøø2ñ»âxÕ­¯Bë]Jj¹ÜÚµàêµWãßøNnyþuèn¹åÜÿý¸ùæ›ñûûïÇÍ7¿÷ß?ÖÝ´ÃaØõ:k×®…34„Kn¾kî_ƒ·nÄÿ[9„›o¾>ú(Ö®]‹`íÚ‹p.ÂðìÚW0z#~lšÐõqÁ•—ãÌ%çcÅŠøãcb>×Å+V`é~V^¹ïØðI Ï›‡?Ó‡·¾òÖJ¬g¤˜XpìØ1|ã¡{ñûÇ/Íùs+°`ñ^üØ—ðØÊ¯âôéÓðüë±~lοǰï\-bAëŸ#¯V¿çx÷ŠQSÆïø~óý_ÁÓ÷wã(‚ð<òÞôÈ?áGø^Æë¿ñ_Úð06GÃûßÿëNŽáÐ<óŽ'7àôÂóðüÿó—h8;z¾]ûaÏ{æÍ›àU˜7o¼¿ÿ ~µø$Nâ-8Ñnl^p?›÷,XˆŸ;‹ó–ãùOañ…ûá™÷ –5œÁÁCÇppþ*Ì_ð"’¯,Ʋ¥gñäñç0_}ÃöIl¿ùõøþý¿ÆåË^Àã§®Äü¯ ±á0~µx >¹‹çà­5žŒ?åËÏDZñ¿Y»ŽíÂ…×þûöíƒúÚ1,ýõAœ™w ,À™WÎá|å,>ð0Þqí(~ú«Ÿ¢ëWc÷ð3X±bNœ:‹öálò)üfÁ"4¬9§Ï<ÖWŸ'¿Ä¢ñ¿¡+V¬À½;ïÅ;®}ŸxÅ6Öœ:ˆ ñ{\¼pÎ;‡«æ!öýÞqíµøÑ¯~…?Z5Š…§~ŒWÆ_窅¿ÅoÇðð‰—ÐpáµxæÌÓ¸öô!¼úÌR¬p½Îm‘Ä;®½###Øýò/qíñùhL^ˆ Äë¬l˜‡Û"1¼ãÚ{qÿ¯~…?8ôk¼úôï°bÅ œ:u ,Àž§Ã/~V]‹ûŸÆ%‹aÝi×뜷Í7wâ¯ý%öíÛ‡»}K~¯9=þ:§Ïá|eÞÿ—?„ïÚ(žýUþÕR\z|Qúu’ 0¼ó1<²ðX¼â*ülßÓðΗ¿‹‡³ÇÎÀãiÀªæ¿™ð:êËbþüXvî0Ö­:Œ;¿ÿýJ¤g=Àïÿ{„Ïû6bg7£ažæ·ââï>€—¾ý¯8sæmxùå‡ñò˿Ǚ3çcÕªÿÀ /<ŒÕ«¯Âë^÷:\wÝu¸ûî»qàÀTø–[nÁ׿þõÔµ¼ƒã7”ÉËu jýûo=\ǬõkûöíÃSO=Uô5ÃyÉd2YÔfI<G{{;öìÙ“ñx{»¸d²lþ7¾ñ üÛç€m{ñû%×áäÉ‹qþù»qöì?¡¡á“H&G°zõ¯ðÒKç.¿| §OŸÆ%—\‚gŸ}¯}íkqâÄ 477ã¹çžÃ¥—^Š_|K—.ÅêÕâBË/¾ˆ“'OâÒK/­ô¡J9|ø0.¸à‚J7cV;v ‹/ÆyçWé¦ÌªBÏõþýû±ÿ~444 §§§ÒÍž¶bâ|ðƒÄã?8ˆç’¯ÁÙ³ïüy¿ÅÒ¥Ïã•W~„5kÞŒÑÑ_áu¯[‚^x¯ýë±{÷n\yå•8{ölÆgýòË/Ç‘#Gp饗â¹çžÃå—_Žgžy—^z)–.]ZéÔŸ‰¹c:çú‘GÁ¹sçÐÞÞŽ÷¼ç=•nú´Û'øÊW¾‚'ž¸Ë–Ý„“'ObåÊ•X´¨ \޳g_ÀÚµÏãâ‹/ÆØØššš°gϼñoÄO<7½éM©¾À‰'R±¡ÚÍÅÏÄ™3gpúôéÔEû¹¢Ðs}ìØ1<ýôÓ8sæ ¾ùÍoÂãαÛ'øÜç>‡/}é%;ö*,\¸çÎúuÏà…Äk_ûGéGcc#FFF°víZ¼üòËhhhÀ«^õ*ŒÁãñ`ÿþý¸òÊ+±{÷n\ýõxä‘Gpå•WâÙgŸÅu×]‡_|1£ÿ°zõj<óÌ3xã߈‡~8uÿo|#Ž9‚U«VáäÉ“©¾„ü¿»Ï!çò“¿²Žì§\~ùå;_µÚ©ÕvO'þíÞ½cccxÃÞ€Ï|æ3•nú´ ÆÆÆðáßûÞmX¼x’É$æÏŸÅ‹÷céÒX°àr8Žƒ+¯|###¸æškðøã£±±/¼ðBêóWhlؽ{7.¹ä’Ôr°`Á\tÑE±á†nÀO~ò¼ñoÄ3Ï<“ÑׯyêÔ)$“ÉœßG¦äïîërK/½'OŠ¡EKÑï©ÕþÈ\h÷\þ~ðýï¡P?vïÞŠåË÷àôéÓPÉd7,¸gϾ€W½ê§xé¥óðÊ+ 8ï¼ó°lÙ2\pÁ8|ø‡¸à‚wÂqŒÔçüÊ+¯ÄÑ£G±téÒÔEÛÕ«W§®%È¿É?üpªàþüÉÏœüÿêÕ«SŸQ÷¿+W®ÄñãÇáñx ^g&¯SêuV¬X½{÷âŠ+®¨XÛdœ{î¹ç2ÎO®uNœ8eË–áàÁƒX°`AêœÊë¿'OžÌùýðäÉ“âæd׎Ÿ{î9¬^½zBÛ¦sÙ} ÜxͰ°ïÛ¶mÃï{uœZø~Õð5œ:Õ„E‹ŽãäÉ·àâ‹—àØ±Ÿâ}ï»O?ý4Þò–·àá‡ÆÕW‹›Ü9‚JªÕ¿WnµÚÿv«õk»wï†ã8E÷ j¦â±ùÈGð‘|$ëÑÜZé¦Ñ,úö·¿ç™i ÁGD5-wŸþ¼ÒM#¢Yô™Ï|“çXþeVÚ1ׇß!ª$ǃÿú¯ÿÿí•nN†Ûo¿½ÒM š3Þóž÷¸.¬ºcû;ÃßæYûÓYÿQ­êééz  Àç*Ý¢šWsc¬å*njjªt³ˆh1ÀX@DŒD$0ÀX@DŒDÕ¢fr|æ]»ve<Çáõz+Ý<"šŒD0ã ŒD0ãQµ©™Ä#´µµ¡¯¯cccD ´ÇãÁæÍ›+Ý4"š%ŒD0ã ŒD0ãQ5™—L&“•nD¡ÆÆÆ°uëÖÔdì‰Dhkk«tÓˆh–0ÀX@DŒD$0ÀX@DŒDÕ¤¦R<lذ§ÒÍ!¢ ` "€±€ˆˆH`, "€±€ˆˆªAM&‰ˆˆˆˆˆˆˆˆˆˆˆˆ¨ºÔÔDDDDDDDDDDDDDT˜x$""""""""""""¢¢1ñHDDDDDDDDDDDDDEc⑈ˆˆˆˆˆˆˆˆˆˆˆˆŠV׉Ǯ®.lܸëׯGGG‰D¥›T”´··Oøžö~×±ٲe âñxÎçJ±Õz òíw!ç¿^Î}©ÕÛ>—*ÔÊq)&Ôòg"×~ϵ¿¥VOû<ß ùbA©ö±ûõgll X¿~=Ö¯_-[¶LøÜÕÛ×€®ëX¿~=t]ÇÀÀ@Õ·{ll Û·oÏØf¹be)ÚžïsŸ½¹Ž©Ž/cCù•*Tâ|Nª±Ý…ÄRµ«Tí.&TSL£É ªõ|ÎFŸ Ôí®µ>;”ªOPÈ2Œ•7›q¶ögãÆÞ×µ°³ÕªÉ:õÅ/~1ÙÜÜœ¼÷Þ{“;wîL¾ÿýïO¾ÿýï¯t³ŠÞ§o¼1ùÅ/~1ãçw¿ûÝ´ö»ŽM,K^qÅÉ;wæ<Åîcµƒ©ö{²ó_/ç¾ÔêqŸK jå¸ jù3‘o¿çÒßR«·}žkï…É>¥ØÇj<ìÔ'yœwîܙܹsgò¶ÛnK677'GGGSËTk_÷ÁL^qÅÉX,–ܹsgòöÛoO^qÅ%}ß•£Ýr>ø`ê˜ßxã%=Þ¥jûdŸû­[·&›››SûñÅ/~1yÅW$|ðÁ’_ƆÙQŠXP‰ó9U¨ÖvOJÕ®Rµ»˜XPM1¦6U,¨Öó9}‚r´»–úÉdþXPŠ>A!Ë0T‡ÙŠû³¹?ÙïëZ؇ÙêÕ“ºM<Ê‹1Òï~÷» A¸ÖÜ~ûíÉÛo¿½èý®æcsï½÷&¯¸âŠÔO®Žv)ö±ÚŽA!û=Õù¯õs_.õ¸Ï¥ˆÕ~\J jñ31Õ~Ï…¿åRoû÷¹Þ'òœÜvÛm%=¾Œ åWªXP‰ó9U¨ÆvJÕ®bÛ]ŠXP 1 SH,¨Öó9}‚R·»VúÉää± T}‚B–a¨¼ÙŒû³!‹%ßÿþ÷Ox_×Â>ÌV¨žÔåP«ÃÃÃH$hiiI=æõzÑÔÔ„]»vUºy3–H$àñxŠÚïj?6---èííEoooÙö±ÁTû L~þëáÜ—C½îs±± ŽK±± V?Sí÷\ø;Põ¸Ïså½0Ùg¢TûXmÇ}‚úåñx°mÛ6455å]¦Zûº‰DÃÃÃÛ€;v ­­­jÛ-‡pòz½çaÆ ©}ª†8RÈßÿ––– ï 6`ll¬dÇ—±av”"Tâ|NªµÝSÅB_s6bX±± ZbfªXP­çs6úåhw­ô €ÉcA)ú…,Ã8Pf+îφááaÄb1Üyç¯ö}˜­>P½YXé”Ãèè(Lx3444äÇ¿VìÚµ £££X¿~=ñ²³³3õ/d¿«ýØx½ÞŒN@¶Rì£|¼šŽÁTû L~þëáÜ—C½îs±± ?ÙŠ…ìc5¾?¦Úï¹ðw êqŸçÊ{a²ÏD©ö±ÚŽûõËëõ¢³³€øb:::о¾>455¥ÎEµöuåÅy¯×‹íÛ·#‘HÀëõ¢­­ MMMUÛî 6¤Úïþ\Éý)U¡ØÏÔTŸû¦¦¦ ÇÆÆðàƒ–´ÿÇØ0;J *q>§ŠÕÚî©â@¡¯91¬ØXP¯}£z5U,¢«í|ÎFŸ í®•><¶ùbA)ú…,S ׿‚ÙŠûå666†Ûo¿@`Bµöa¶ú@õ¦.+ëÕØØ¼^/LÓ„išhkkÃöíÛsN8Nõ‡çŸ$¾æ.ž{’ø^˜Ûxþk_WWÚÛÛ100€Í›7OZÁ\M¶lÙǃ¦¦&$ lݺµª¿(·´´Àãñ¤.$‰ÔÿkÙÀÀ¶lٯ׋@ PéæPj10TÆ‚úÁXP~õ æ–Z=ß±X ضm[¥›R”Z‹{•V—õjÏž=¿wvv"£¯¯oB¶œêÏdç_ÞÕDscÁÜÅsOß sûµOÞ¹ÇÑÞÞÇSç.d\0Ðu}}}Ø´iS¥›–“ÇãÁÝwߎŽèºØ´iÓ¤C\V3y‘4cÛ¶m5qqšò«ÅX/ÜqÇ•nZNõÆ‚z”+L5F¥±OPYŒsK-Ÿoù=õ¾ûî«tSŠVk} J«ëŠÇ\çZýƒ’OKKKj ïéìw­›Rìc­`âùŸ ç~&æÂ>Ï$ÔÃq)Å>Öúq˜«f¢Þ÷y®¾Jµµ~Ø'¨~rn·––´´´L¨V­Ö¾nvBdÓ¦M•ÕØî¦¦&˜¦‰={ö`Ïž=رcÊÒ_(çgjxx8u—µišèììÌyÁ‰}£êWÊXP‰ó9U¨ÆvJÕ®r~ ‰µÓ¨ðXP­çs6ú¥n7ûÕÓhj³÷Ë!£¡¡Û·oG{{;ÚÛÛ¤+½ka¤ÙêÕ‹ºL<Ê;ý³'æŒÇãUÇP>F)‘H¤‚M!û]ëǦûX‹Ç`ªó?ÎýLÔã>—"ÔÃq)Å>ÖÚqàß™«·}æ{%ÝÇZ;ìÔ®lݺuÒeªµ¯+çEÊÞfö¼HÕÖî±±1tuue\C<dž j*Žttt`óæÍرcGÎmΞQ­*E,¨Äùœ*Tk»§Š…¾fµ|Çš,ÔRL£©cAµžÏÙ蔣ÝìTgL£©ÍFÜ/§¶¶6ÜqÇضm[ê6oÞŒmÛ¶ÕÄ>ÌV¨ÞÔeâoê¾¾¾Ôß===ðx<ؼys¥›6#MMMˆÇãèêêJ=ÇSã¿Og¿kýØ”bkírþ繟‰zÛçRÅ‚z8.¥ØÇZ:ü;PœzÚg¾ÒJµµtØ'¨]›6mÂØØzzzRÅãqÄãñŒ!’«±¯+“Ú]]]©mÊ÷R­ZÛ=00qÌ»ººàñxJÚîr´Ý-#‘H¤ª`Ü?çZߨV•*Ìöù,$Tk»§Š¥jW¹??…Ä‚Zˆi$ ªñ|ÎVŸ ífŸ ºbMm6ã~¹È¤›ûßkKëÊe6û@õd^2™LVºå066†­[·bll ‰DU?_ÂdúúúR™H$°mÛ6tvvNk¿k娬_¿½½½æª*Å>Vó1È·ßSÿz:÷¥Tû\ŠXPKÇe¦± Ö?¹ö{®ý(¥zÛç¹ø^Èõ™(Õ>Vëq`Ÿ þôõõaûöíðx?õÓê]!± ZÏçlô JÝnö ¦¿L5ìM­VÞ“µ¾³ÕªuŸx$""""""""""""¢ò«Û9‰ˆˆˆˆˆˆˆˆˆˆˆˆhö0ñHDDDDDDDDDDDDDEc⑈ˆˆˆˆˆˆˆˆˆˆˆˆŠÆÄ#‰G"""""""""""""*DDDDDDDDDDDDDT4&‰ˆˆˆˆˆˆˆˆˆˆˆˆ¨hL<Qјx$""""""""""""¢¢1ñHDDDDDDDDDDDDDEc⑈ˆˆˆˆˆˆˆˆˆˆˆˆŠÆÄ#‰G"""""""""""""*DDDDDDDDDDDDDT´9•xt¦iVºäâ8,Ë*éöÊyŽMÓ„ã8yíj>.µ†Ç£¾X–Û¶3+ç9ž,”ûµ‹UÍmãþS±¦{~'[6W\)d{ì#T¿¹¶¿õ®}€|Ë–:̤m³©šÛÆý*ym€}‚Úi÷}n)&.Ìöu v?ûÕܶJàñ¨¼f8KmKÎ!ƒƒƒÉzÙåîîîäÈÈHÞ߫ݑ#G’~¿? ©iZrhh¨èí–ûHV䵫ù¸Ôšz9µŠ544”TU5Gt]O9r$™L–÷OÊýÚŪæ¶qÿ 7×?ûùLçüŽŒŒä\vdd$©iZ*®øýþ‚_Ÿ}„ÚPOû;—cA©ú¹bA¹âÀtÛ6Ûª¹mÜßüê!TúÚûµÕ>î{aj=6*u ™¬ÝÏ~5·­êåxÔz('^3œ¶Í©ŠÇzbFÆ;Ù¿W»p8 Û¶qäÈ$“I¨ªŠh4ZéfÕ”ZÅjmm…ßïG2™Ä‘#GˆØBTïæúg¿¶mÃ0 ´¶¶æ|> BUÕT\±,‹q…ªÖ\ŽÅö&‹ŒTKê!TêÚûTÏj=6x€H¨õ8@µoa¥Pn±X ¶mCQhš–÷yUU¡ë:LÓD H=ošfªÄÔï÷§¶‡ …‹Åà84MƒßïÏx½P(”ÚÎt—/dŸ à :Ìîßu]Ÿráp‘HÑhš¦Á4ÍIŸj›ÓÙ?Çq‹Å044EQ‘H±XlBûÜç'À¶m˜¦ ¿ßŸêt躞·}Žã ¦ÎÝt×/æý%÷Óq(Š‚@ ÚßBÎû=hÛvê})_3WÛ󭫪jÆñ(v¿kQ1± _* Êt]Ÿ26”2LõyÌ$Û¶SËÊóšow,P¥¤q`²÷W¹â€û5ó·ÉÖK±`²ÏþLûÀôÞëÕÞ¨¥ÏþtþŽg÷ä9•Ç*›ÜöÐФ>³±X,ã3UŠ÷û³‹ßr«ä÷B>ËSÅ‚™ô¦Š¥Ž“½ÿØG˜}ü>0Q¥ûS](UŸ@¾–;°O0wcû¹Õê5C¹¿3í#ðšáÜøÜçÂ>ÂD•î#ÌÖu€× ËÕ¨ëŠÇæææÔ]-¦iN¸“-§¢¼ÓÍÝñŒF£©uÇAsssê|Îq8ŽƒÖÖVø|¾Ô³h4šqGÍt—/·h4Š`0˜ºÛaªß Ù^¡û'“üMÓ„¢(ozùúòµÃápꎧX,†ÆÆÆÔkù|¾œÇN>'€i­?•ÉÞ_Žã ±±1õ‡Ç0 ø|¾‚Ï›û ‘ÏçËx¾µµ5£ó5ÙºJ²ßµ¨˜X0Yp?_‹± ×ç|6cÁTŸÇ|q@R%ã „»Ãì– J€üï¯rÅ`òX0ÕºÀ܉“}ö‹é¸Ÿ/ä½^MŸ{ùzµúÙ/ôó›«@ƒƒƒ9/Ê×s//cÆt±P=ø} ¿J~(ä³ÁT×JÑ'ç-;°O{]©^cûùÕê5C ¸>¯Öÿç>ör«ta6®ÈóÆk†eêTzìØréîîN*Š’1v±<™Lãï~^UÕ¤®ëϻǗÛL&Åx½ÝÝÝ©ç4MKÔï¡P(µ­™,?]×3Æ Îþ}*’¡P¨àß Ù^¡û×ßߟg]UÕ¤ªªIEQ2Žuöëwww§ö@2‰d< yäÈ‘ÔóGŽ™Ð†d29åú…ìçààà”ï¯ì1‘9’Ôu½ ±´³?–îc—½P(”1×D¾u'Ûïzß»˜X0UH&+ Jr=VÎX0Õç1_“Š¢¤bˆªªænÈ JäzùÞ_åŠò\ç‹“­;—bÁdç¦Ø>€<Î…¾×«½ë±jýìO¶îw¾óIûn¹æ.Ûɵûµ‰ß&WÉï…ü-ž*̤-ûóXª8 ·Å>Buà÷ü*Ý'˜êÚÀLû…\Ø'˜;±À}„ÉÕê5Ãd²¸>¯Ö÷ç>öò«t¡\× ¦ê#ðšaébAÝV<ÊÒz÷]-î’QÃ0&<ï÷ûSÿ7MªªÂqœTÉ´ü]fáÝë*Š2e)ìt—/·ì2Ù©~ŸJ¡ûç¾{idd###²úî×Ͼ;É]V.Ï«ûŽ&y·„ûœNgý©Lõþ’ƒÁÔÝYƒƒƒ9ﲚ¹ y7‚išp§àõsíw½ï]L,($µ r}Îg+H“}óÅÇq‡¡ë:º»»ÑÝÝ EQ&Ü…3Y,(6“¿¿ÊÆ‚BLvnJѦ÷^¯¦Ï=P»ŸýÉÖýÍo~`ê>@>“}†¦óùb¡zðûÀÔ*õ}@šêoq®XPŠ>@>¥ŠûÕ„ß&WÉ>A!×fÒ'˜Îµ\æzŸ ßq­õXàÆ>ÂÔjñša©ú¼fXŸŸû\ØG˜\=^7(´Àk†™íI,¨Û9ó•ÒKSlÛ¶3Ƴ•æÒøÖå¢ë:¢ÑhÆ0 ¡PÑh¦iÎèg)9®t0ÄÈÈȴןÊTï/UU188˜*Áw@ÝÝÝE;YÞ/ƒV±|*Ý‘ ÅÄÆÊ(ä})Ç@ïïïO=¦ª*š››3þ@N'Ìäó0Ùû«\q`,(Ädç†}€êTÌûнîtûîõò™NçŸ}„êÁïµ§R}÷:ùL÷"ûՃߪ×T×f¢Økr|æbŸ ×q­uì#T¯b®–«Àk†õ‹}„ÚSªë¯Îô¸ªnªªNÈB»ƒ…¢(“MÓR™f÷ú–eMÚ ¥©Möf-ô,']•ÿÏ>—ÝÝÝp†aL˜4µõ§2ÕûKN+ï°², >Ÿš¦eÜ93†a ‹add$´Âáð´î¶(v¿kQ1±€q`vÌä}é^G’Ÿ ÷]8“Å‚R|&{•#Œ…šìܰPŠyN¶îT}€|Ü1$×ÿ Å>Bõà÷êW©>@>¥Šr[ì#T~¨^Õpm —¹Þ'(ä¸Ö:öªW1q¡T}^3¬ÏÏ}.ì#T¿r]7xͰÇÜ­n‡Zõûý“cfßà÷ûS“ËçÝ“¿êº>á19iiµÈ>éµòAÓ4¨ªšq>Âá0TU-80gO¼«(Ê„;JääÓÑhtB9p!ëOfª÷—ûnÓ¾»Àý¾t¿†¢(CHäº 4׺¹ö[óz¿§˜XÀ80;fòyÌ>o“­›/d;ò½¿ÊäïSÅ‚Éâ@ö¾×k,˜ìܰPŠù æZ÷ºë®K=6Y ù9pŸwÃ0¦=d+ûՃߪ_¥úù”*Èv²Pø} zUõ\æzŸ û¸ÖK,pc¡zJÕGà5ÃúüÜçÂ>Bõ+õu^3œ½>@ÝVPýf»Pȹ+Eíd¡:ðû@u«ôµ|æjŸ@¶»cÁtÎ û•5Ó¸Pª>¯Öçç>öª_¹¯¼fX®>À¼d2™œÑš5¶íTéªûÎYú,O€ªªˆÅb°m;c,p¹.¡®îö»'®•¿×÷±-4knš&|>’Éd*;?óRìúÙò½¿Ü¯ ïóùX–ÇqržÏìvËÉ‹år“­›ký¹¢˜XÀ8P¥ø<Êó:uKÜíÈõY/Gpo7W,˜jÝ\ë׫\ç†}€Ê*æ3XŽÏo¶™ôOra¡zðû@õ©T P¥Šîv²Pyü>P½*qm \íÊ¥û¹¶QØG¨^Å|þfÚGà5ùñ¹Ï…}„êS©ë¼f˜{ý™¨ûÄc>2k=44”Ê8û|>„B¡ŠfýÝÁ*ŸÉNx±ëÏÖ6gÊýá/åú³±Õt)± ð¹SJýþ-öóã@91.Ôæ5Ãbñš!ec,˜{× xͰtêv¨Õ©¸K¥ey´,;¯¤|cp»Mv§O±ëÏÖ6«Ílìã\8޵ˆ±`vÚS+ æ†zýÜ—jåÜ^-b\¨_õ ø} < êcÁì´§0ÌŒ ³×¦ZÀÏþÜÅX0;í©ŒÓ3g+‰ˆˆˆˆˆˆˆˆˆˆˆˆ¨tæWºDDDDDDDDDDDDDTû˜x$""""""""""""¢¢1ñHDDDDDDDDDDDDDEc⑈ˆˆˆˆˆˆˆˆˆˆˆˆŠÆÄ#‰G"""""""""""""*DDDDDDDDDDDDDT´…•nÀløû¿ÿ{<öØchhh¨tSfÕ¡C‡°fÍšJ7cV=zK–,Á’%K*Ý”Y5Ýs½`Á|ík_«t³gÝ{Þó¼êU¯ªt3f?sÇtÏõ©S§pÓM7áƒü`¥›>«Ø'˜;N:…S§NaåÊ••nʬšî¹ÅŽ;àõz+ÝôYõÉO~‡®t3¦­V?˵Ú©ÕvÏ$þ]pÁøâ¿Xé¦ÏªD"ŽŽŽšìÔj,`»«»ÝsõûÁ·¿ým|÷»ß­¹X?—þFUƒZm7Àk†…úèG?ŠsçÎUºE©Õ¿WnµÛÜj9^¸÷¡Ø>ÁœH<>ñÄx×»Þ…~ô£•nʬjooGooo¥›1«ºººÐÒÒ‚–––J7eVM÷\···WºÉñ /àûßÿ~¥›1«ø™˜;¦{®ãñ8âñx¥›=ëØ'˜;ä{¼³³³ÒM™UÓ=×]]]H$s.ñxøðášüLÔêg¹Vû#µÚî™Ä¿¹øý ‘H ¥¥¥&ÿNÔj,`»«»ÝsõûÁþýûñ±}¬æbý\úU jµÝ¯êܹs5ëÝjõï•[­Æ6·ZŽÙûPŒªjull 7n̹s]]]ظq#Ö¯_ŽŽ$‰)·çñxpþùçWz·f]SSS¥›0ë¼^oMÞ±Z¬z<ץް|ùòJïÖ¬ãgbî¨×sÍ>AiÌÅÏDCCÜK¦õ{®óÅ‚™ö jU­žßZýU«í®×øWŽïµªVcÛÍv—cÀ¿Qlw¡ê10äVçºVc›[-Ç‹RªÊÄcGGÆÆÆ&<ÞÕÕ…¾¾>tvv¢··754ÊT®¼òJ¬[·®Ò»5ëj9«>Smmmud§«Ïu©ã€9ø™˜;êõ\³OPsñ3ÑÔÔ„¶¶¶J7cÖÕë¹Î ŠéÔªZ=¿µú7ªVÛ]¯ñ¯ßjU­Æ¶›í.Æ£ØîBÕc,`È­Îu­Æ6·ZŽ¥Tu‰ÇžžŒŽŽæ|n``mmmhkkCKK vìØááa TºÙDTBŒD0‘/0ÍìÀX@DŒDµ¢ªÃÃÈÅb¸óÎ;s>'ç`¼^/ššš°k×®J7ˆJ„q€ˆÆ"òÅÆ¢¹ƒ}" ˆˆq€¨–TMâqll ·ß~;@ÎrZy'CöÄ¢ žtÛgΜÁSO=5årDõ.‘H ãøñã•nJNåŒpüøqÄãñ95¾;Q.ñxO=õΜ9Sé¦ä4}‚b'É&ªucccˆÇãØ¿¥›2ióÅ‚bû§NB<ç÷šó†‡‡ÇqêÔ©J7%§r?Ø¿?âñxÎáÚˆæ~?à÷"^3ä5C"@|?(EŸ j±X ضm[É·}úôi óîšód'⥗^ªtSr*g€—^z‰" u±ýôéÓ•nJN³Ñ'à…šëFGG«>ñXÎX ü~@sÝ®]»ª:ñXîï2ñ˜oÈ6¢¹‚ßøý€ˆ× yÍßJÑ'XXéD§¯¯÷Ýw_Y¶¿bÅ ¼óïœpÇÑ\ÓÒÒ‚–––ª¼»¿ÜqÖ¬YS-«³³ñx¼*¿\³O@4;¼^/:;;ÑÕÕUé¦äTîX°råJö ˆ´µµÀœý~pýõ×3ßøý€ˆ× yÍHhkkƒ×ë-ºOP5‰Ç††lß¾=ãñ®®.444 ··7õØððð„rê\åÕDT[ˆ`, "aªX ïtf ª_ìÀX@DŒDµ¨*mmmî,ŠÇãØ¼ys*0ÈçwíÚ•,âñ86mÚTé] ¢"1ÀX@DÂT±€q€¨þ±O@Dc1Õ¢ªHŒDÄ8@TkJ’x ÀØØØŒ·±uëV$ ôöö¢··^¯[·nÍØ¦œC²³³½½½H$èèè¨ô1$¢a "€±€ˆ„©bãQýcŸ€ˆÆ"b ª5%jÕãñÀãñàÆoÄæÍ›sÎëØÙÙ™wýááa ã¾ûîCSS1?äÆDZiÓ&ÀÀÀ@j.Iرct]ÇÀÀ@j"ªMŒD0‘PH,` ªoìÀX@DŒ47Y ª€¢Tº%3S’ŠÇD"††lذ‰D" Ü?“ñx<ضm[*pä2<<ŒD"‘1‡¤×ëESSvíÚUéãHDEb "€±€ˆ„©bãQýcŸ€ˆÆ"b ¹Ã²Çÿ‡ظŒi¦—©f%©x”ÕŒ‰D´´´d|Øóñz½©m ctt}}}hjjJ­ïÞ¦[CCÔ‰Í3gÎà©§žBCCäЍÞ% $ ?~¼ÒM™ ÜqŽ?Žx<¯× ¯×[é]&ª˜x<ާžz gΜ©tS&˜­>A®õ‰æ’±±1ìÚµ û÷ï¯tSrš*È‹3íœ:u ñxœßhΓŸ¯S§NUº)ÌÆ÷ƒýû÷#cÆ 9Gn"š+øý€ßˆxÍ× ©òÂa@×PH$!5mâ2>08(–+‡ááá’ô J’x€íÛ·£¯¯/㱞žx½^ìØ±£à/ô]]]ˆÇãDB³ÿÓ§Ocxx+V¬à…šÓ‰âñ8^zé¥J7eRåˆðÒK/!£¥¥…šÓâñ8öïß_õØÊÙ'8zô(/,М6::šŠÕ®±@&å]ÐDsÕ®]»H$ª2ñèV®ï2ñèõz«¾_DTNü~ÀïD¼fÈk†T~Ž#~T5ý˜aˆáTu°ít5c ?¹8Õð«299»víÂððpÑŸ­’$Ý·¶µµ¥ÇÑÕÕ…ŽŽ˜¦Yжz{{Së¶··Ããñ¤Æež©+Vàï|';4çÉ*äBîô©¤rÄX³fͤóÍ͈Çã©ÎzµbŸ€¨|ä]Ã]]]•nÊ”rÅ‚b/¬\¹’}" õwu®~?¸þúë ˆÀïü~@Äk†¼fH功@@$UU$c1ÀïËèz:ñh¢êQ&$%pœl¨UÇñšæÌª"ÛÚÚàõz‹î”dŽÇlÛ¶ Û¶mËÈ„¶´´`ÇŽ©;&ò‘óBºÉ`—½^®àÇ»”‰jãŒD$ ˆêûD0ãÕ–XLüd3M‘`ŒDDRÑ]§gYéum[üß¶Óû|bV ³Z2¹Ž¦µRóA–$ñ˜=q«›¼y²»%°uëÖI_Cn?{2X9, Õ6Æ" ˆH˜*0Õ?ö ˆ`, "ƪN¦™N0º“ˆ¶NÊÊC)K'%MK//Dµbz›²RUÓËdoËM& #ýX¾$d4ZúãS’Äãd¥—2á8Ù›6mÂØØzzzRÉ!Ü Í¶¶6ôõõall €˜CÒãñ`óæÍ¥?2D4«ˆ`, "¡XÀ8@Tߨ' "€±€ˆ¨:™& ¦ÿï®rt'ýdâQÓÄe‰™<ŒFÓË»iÐÚš^pP$ ݯåNXºÛåþ×½í\•˜@yª"}ŸH?€IDATK2Çã¦M›RüÍ›7£©©)5¼jWWššš&+ÝëõâŽ;îÀöíÛ‹ÅÐÐЀD"mÛ¶eŒÑÜÙÙ‰­[·bË–-ðx¤‡?2‡L•ÿÊ¡PÓ‰Ã\Õ…ÝÝâq]ÏšUQĶ伎Ž#“l;ýX0(Ú ëù“¹Œ–UÅ€H>ìÚµ ÃÃéÿt&oÍ0r™¬z’ˆjãŒD$ ˆêûD0ãU†ªæ®ŒÅÒó9úý"±˜kT™Ôsñ#+³‚†!‡¡P:ù¨ª"© ‰h®¹ÝÕ˜r(VUmr'1M3÷~éÇ-K,÷Püq+Yâw´´´ðÃMDDDDDDDDDDDDážKq¦t==„i,&sýýâ÷@ t”I>ÛC¥ºÛˆul[$c1±]@$弦)rVMKÏ)÷CUÓëb™Ü Ó•“†‘^ÎÈÌfÛé*Jï·sgñÇ~~ñ›úúúÐÞÞŽáááÔc7nÄöíÛSº•“¬@,„LúIòÿ2ÙhY"Iç®tœôpª2É'‘ÙÓÿWÕÌ„£ß/‹š–N,&“éßE<&‡juWTÊö(Jæú–5qÇ™Xõ˜ýx®ääL”$ñØÓÓƒíÛ·@ƸÉmmmxðÁ±uëÖÒ´–ˆˆˆˆˆˆˆˆˆˆˆˆ(Köð¢3Y7;AçR5{UYm˜]YišbyY)ézzTÇIªib®G@$;çÍK' t²2Ù‰ˆ×òûÓÛ“•˜2iê8™ÉU sþHÛά¦,FI}}}hkkCoooÆ8˸ûî»1<<œšÔ•ˆˆˆˆˆˆˆˆˆˆˆˆ¨”|¾ÌaOóÍk˜K,–N:Ê„b$"ª‘´ Äs€x\VÊJÃhT<®ªâõƒÁt{t]<.“rþFÓIBY)é8é„ L8ªjºRR>wäˆxNVvÊ¡RåЩn‘ˆøÉ•XÔ´Ì9(}´¡èóP’9‰6mڔ󹦦&Àðð0ç~$"""""""""""¢iñùDò¬Ðye°²rÐ0ÒICùšòy@$æüþtâвD›%s^EÇIÀl²â0ëÈ×’ÉE9ìª|M™”¯¤«V¥‡X•íëù|éd¥¢­­é„¤;ù(÷WQ&Vt£$^¯7oEc"‘N@JV N¦»[$Þdµc0(Ï5ï¢e¥‹¦)Ö1Œ‰C­š¦H8ÊDže¥——sCÊáS³çn”Š2 ªiâq9ì©aLL¤ÊÇe5M$eòÑ0ÒU”r]wÂR&#åð°Š’®hŒFÅãîã!«&å¾—BI›6mBOOzzz066–z|``ðz½¬v$"""""""""""¢™¬"Ï4ÓC›Ê¤ œß0Óó*º×ÒŒ@ºÊP’IC™È Ä¿²rД‰LYÁ(‡/uW+Ú¶HÊ×p*¦rùH$ð”¯/_«¿b£üWÓÒC»ƒb;2á)_Þ<±/ºž>.š ­,ú<•d¨ÕÎÎN@WWººº2žkjjÂŽ;Jñ2DDDDDDDDDDDDD9YVæp¢Ž#o2©çóÉdæ:~f¢ÈLPÊ*H9,ª{ûîdŸœïɽ\ÉIEÉܶ¦¥+5eÂQþ›=\¬LVÊdª¦‰×‰Å2‡¡Í¶µU$%ÙÆÖVñÚ¦)‹D€ßþööî-į̂âqxx]]]N=ÖÙÙ Ó4qÇw`Û¶mضmz{{qß}÷q˜U""""""""""""š‘P(]ñO¬~Ô4±Œ;)ˆ!DÝU‡’Lâ¹+#å¤@zXT9¼*NNÊáNeU¡ÜŽ®gV0ÊêIÙ&Yaè~Þ¶EU¢LZæNV×Ó‰EY¡ ¥ç‚”Û—ÇÊqÄöÓ˜’L2Êuä°†Üÿš¢ÏÕŒ*½^/¼^/b±†‡‡±iÓ&lذ›6mB[[[Ñ"""""""""""""DR̲D"MVº“i²ÑqDòOUÓsÊyeâËÈc®êÆh4]582"’ƒr¾DÉïËé¶éùåöÜÕ†2ñ MfUVeº——ÓÛrWFº‡‰u¹rY¿_lýŸR(”NºîÙ³oxCqçjFmmmرcî»ï>x½^Äãq躎íÛ·c`` ¸VÑœg&%™T”d•Ÿ$+å¤ýýâq÷¶ #ý9ä©»Âph(ýœœ'ÒqÄüîaTÝÛs?¦iâõeO×Åvܯ ˆ`0˜^.IW4ʤi.–%†GÄ2îÄ¥›{î KŸO¼†{îH¹|w·Xö†}g”xt“IÈ;i¢¥¥ñx7nDGGúúú066VtC‰ˆˆˆˆˆˆˆˆˆˆˆ¨~ÉêÄlî9s IêNJZ–Hê¹·%“l2a)+ erëÈÄ¥®gVUvw‹ªAY5©(“Ÿ29é8¢JR&ù²ù|™í•CǺž“Q”t5çààÄvévªjf¥<6Ù£r»,)úx̶iÓ&ÜqÇxôÑGH$°eË–Œù ‰ˆˆˆˆˆˆˆˆˆˆˆhnr'ÞÜÜ E™<´ítåžeå^7×܈rÞGYá—½œª¦çet'áET)jZzžÄÖÖt²2™8ª¬V”ÉIY%)«³ùýémȹÝíÊE&³+sU>ºÛ ‰ÝC­Ê×Í>'=´zf'Ô¥ä‰GH$Àèè(:;;aš&šššÊñRDDDDDDDDDDDDTCäˆÙÜIÅXLTÿÙ¶X>ÊœÃÑMUÓó5ÊJC] DÃÈL>º_Ë¶Ó HwU¤i¦Û(ÿ•s&Ê„h$’Næâww²Ñ=Ì©Ûà XFî«®‹D¤®‹çrÍñ(Û‹å¾5›{_åÿÝC­Ê6g«xÅcWWt]GWWWê±¾¾>èºŽŽŽ´··³Ú‘ˆˆˆˆˆˆˆˆˆˆˆˆRrU("&+ñ'3)+ôp¤óæ‰ÿ«j:hé¹"åròww²MÎ iâ9E?¹†‘HîáU%÷œ‰@:!988q¸ÕÖÖtUn[&;}>‘\ÌÅq¦†u*òØÈ6—ÃŒ]]]èééASSZZZˆJÇíÛ·£©© ½½½Ø±c‰DFb’ˆˆˆˆˆˆˆˆˆˆˆˆæYÁ(Éÿ»“¶™xsW!Ê E¹œ{nF™dôù&[*‰ªš~N׿îå4-=7bv‚1N'e¢0™L”ûàóå¯îÌUµ9¹í|sG¶“'Oæ|._…ætÍ(ñ866†žžtvvbÇŽ©Äc__¤Û´iî¼óNÄãqV=ÍQ¶;ñ§«ðÜÏ»…²ÚP½*uw§çÌEVvwgV š& ¦·!çJ”C˜æš7ѲÄ:r¨Õ\ÜÕš@æ®îer%eò3ùœ»jqºî¿ÿ~ìܹ3ïó_þrñ¹¼%wíÚhkkËx|xxMMMðz½©Ç6mÚ@TCÑÜãNÖiZfr/M'e5ŸªŠuä܇29(É¡WeR2Hq*_C׋åN:ÐÜœžR®‰¤+"³Û:•|s4ºå«.Ì—Ðt¯—/Éš‹ã80MÍÍ͸êªý¸ðÂ7áºë®Ë»üÇ?Þ„gžYWø ä0£Äc<x<ž ËêÇlL<ÕŸBçtuê®>ÒU|îêGY¥èóeÎÙˆ$e‰Ä`8,’‹>ŸXÇ=lªäNöi04„BéêD÷ŽrîG`êJÄéšl®HùzùÒg|‡V­Z…ÖÖV€ßïÇM7]‚7¿y Nœø9¢ãã¿Ú¶p8 Û¶ÖžNf3‡%erqll,õØÀÀ`Æ ËÊ„cSSSQ %"""""""""""¢êcY…%e’/ËË ?9Ü);¹¤“n€øqWHºrŠ’™Ø”Ü¿ËÄâx^n‚P(]y™‡“ûO,–NNœQQ&¯Zœlûùæ‹L/ 0 ÝÝÝ…BhmmE(J­»iÓÐǶã8°m;õóÞ÷~o{ÛùSŸÈIÌ(ñ(“‹1× Ÿr~G9´jöãÙ I""""""""""""ª}Ž3õ0¡ÀÄe,K$ùä<î$êÔﻇ;•U‘š–9Œª®OL‚ºçYŒDD[m[,'Ï®$tW%ÊŠG9«¢L>ôªß?õóù†ZªRz÷»OÕ‰ˆF£°m–e!‰ ‹Á²,hš†€kìWËâñK‡aš&‚Á úûûáóùÏ=÷gxî¹5Ÿ÷\Îd%ǃmÛ¶¡§§'5ìêðð0¶mÛ–Zfxx}}}èëëömÛ& ËJDDDDDDDDDDDDõaª:³«eåŸ.Õ”´, ‰>ÃÉÂP(óudÒÐ=|kö<’rÎF™è ‡3{##âu&Kʼ㈡\C¡É——sSNv&{­É¶=2lßþ$¢Ñ°aƒUUFSó9†B!ضÁñŒgsÅñß·X·Nƒ¢(©¤äÐК››qõÕƒ“'—|Îs™QÅ#tvvâŽ;î@CC°mÛ6tvv¦žïêêJ%ÝQý˜jøP@$½ÜI59cö\îyåÜŽ–%ÖUÕt$ ~×u±Ž¬L”C±Ê!W'ÓÚZøü”²íÑèäû*Û:ÙÃÆfóù€½{_‹7½éMp±X Š¢`hhš¦¡¿¿þìÉ-]ëª*ð¹Ï‰BÁ°,`š&t]ÇâÅ‹‹®xœqâÚÚÚÐÛÛ‹ÞÞÞ ÉÅÎÎNìÙ³‡IG"""""""""""¢:&‚“1ÍtR1ÉA™8DÂM&³çut'ãLST.ÊJHEË;ŽØ^,&~Üd¢ppPlK&)Uuê„©›¬º,äxÌ”™• 5 €˜ñ‚ ưsç¿á꫗öm(ŠEQ`š&Z[[a¸þþþ ÛUqÌä±Ñ4-5×£>U†vŠJ<@<G<ÇððpÆãMMM%k$U'94êTCŒF£b™pXü? KY¡(—ÝÝ™IGw¢Ò¶Å:Ž#’‘Ž#k¹*UU$ }¾ôÜŽ298êDËJ'/ó)dŽÆÉÈùåÿƒÁ |>¢Ñ(Nž<‰¶¶?Â5×xRó:úý~øý~9r$Uí¨åh„û!¿ßÛ¶¡ŽMÓ iþìÏžÃå—ï+ªý3N<C×u´··£½½[¶lÁöíÛ‹;šDDDDDDDDDDDDTSdÂq²Ä£¦ML"ÚvºrQV†BéêGYÙ(“„²JIIw¡ÞTó.ÊjJ@$' C¬?Ä£i¦“—ùÈ¡^gʶmضØxiâÐÐPjžÆgŸ}?úÑeØ·ïrD"‘T‚QV>N÷uÜäk¼øbÃÌ`áLWìêêÂèè(¶mÛ†––ôõõ¡¯¯‡Ã«Õ1Û Cw2ѶE²ÈLô¢’qhH,oÛ"駪™‰GM;Næ¶s ]êóÉd:ù¨("ÙÚZø>hcTÒ)M•äœ)Ã0 ë:ÇeYÐ4 ªªÂqD£Q|îsøÉOIJif7#q¬<˲ðÖ·¾áp†a`dd04´Ï<3ãÔ!€V<& Äãqtvv¢³³---رcššš& ¹Z¨±±1lß¾7nÄúõë¡ë:&,×ÕÕ•Z¦££‰D¢¨@DÕƒq€ˆÆ" ‰ŒDõ}" ˆˆq šÅbé$£dY"è®D ÓË…Ãé*FÓÏ"‘'‡?FŶeU¡i¦‡OõûÓ˺ ¦çwÔ´©+‘ˆS”™ Zìpªùض Çq ¡ªj*¹¨( 4MÃï~·pZsRº†h÷7Ž  âþûï‡iš© K8sf7V¯-jfœx¯×›ñxKKËŒÒÑÑ|wÞy'z{{±iÓ&tttd®®.ôõõ¡³³½½½H$èèè(êQõ` "€±€ˆ„©bãQýcŸ€ˆÆ"b¨6ÙÉF™‹DDµ¡ßŸNº—1 ñ™04ÍÌ9åªÙeWºs'݉NÓDÞä\(”NPf'M QL5c.Á`Îø„–2ØÝÝH$’šQêîîÆÊ•+ N<ò o۲ıyì±UP«W¯Æàà 4Mƒiš0 Ï<óy¬Zu´¨}šñ¥466†x<Ž;ï¼›6mBKK :;;ÑÔÔ„|0µÜÀÀÚÚÚÐÖÖ–ª²ÎywÕÆ" ˆH($0Õ7ö ˆ`, "Æjä8™óÊ$X8,ž“I¿ñ\€ÌêÀ\C”ÊêD™ŒÔ4±¾ªŠ„¢ßŸYÁhÛ"q˜/ 8ÓŠÀBtwÏlhÖl–e¥’}‡ÃhmmMÍÓ …à÷û3ÖîŠ6ˆù/Ó™SS–„º¶ßÚÚ Ã0`Yš››qýõû`ÛÀ/ù4MÃÐÐE®ë0 Á`¿úÕ^,[vº¨}«ŠÄc"‘@KK ššš2ß°aÆÆÆÃÃéå$¯×‹¦¦&ìÚµ«Ò»@DEb "€±€ˆ„©bãQýcŸ€ˆÆ"b¨FîÄaöp¦Ž#*³–%’‡ÉäÄí©jzU ýÓÛR¤*õÜëhšØf.îÊÉl–•nßL†KõùDEg±¢Ñ(,Ë‘#G … ë:t]G${bÌûñGFS‰KŸÏË•–‰È`0Ã0à8>ÿùÏCÓ€uëžÉ¨¦Ô4 ¶m':m¬Zõã¢ö­*MMMèííͺull >ø`* ŒŽŠ1e³‡smhh˜ñ¼’DT=ˆ`, "aªXÀ8@TÿØ' "€±€ˆª‘;©‹‰ä£ã¤«ÝCžºE£"i—=ÿ£;A(ÿ¤“šŠ"^3{¹|¯äOH¹‡o.wÅçt8ŽƒÖÖVø|>øý~„B!H%§J:éŠÒ_ÿú×Dbü~ÆÐª–e! AQD£Ññ×òãàÁÓãÇ5}ü~?FFFÐÝÝõë×ã¹çž+êø•xlooÇúõëS?===ˆÇãÉŸéÀ–-[àõzSgãðáÃèêêBWWWÑÛ"ªe}}}hooǾ}û*Ý”)•:À¾}ûÐÞÞŽ¾¾¾JïQEµ··£«« ‡®tS¦T®>A{{{¥w¨¢†‡‡ÑÞÞŽx ÒM)H©cÁ¡C‡R±h.“:Té¦L©ßxà´··ó‚$Íyü~ÀïD¼fÈk†Ó完ÅD"Î0DRÓ&&݉@lj³ÁA±\$’N2Ê„b,–ž#2_’0Í=¤ªãˆuó ·ê÷§_'_òr2##bžÈé ƒˆF£©ùÝI™ÿ§ŸþB¡ÇA(JÍÓˆ¤£aðûý©Ï‰¶õßXŒ‡^‘s»]]]8}ú4öïß?ã¶À™¬äõz±mÛ¶¢^8—D"íÛ·#cÛ¶mðxQyÉ»†«=ñV®X°fÍö ˆtvvÀœý~ð®w½+u ˆæ2~?à÷"^3ä5ÃéÐ4 µU$ %9ªjU×3‡a E²ÎïÏËÇ’ÉÌ$æà`z{òµÜÿæjK6ÇÉœ_2[8,Ú2Óy ƒÁüøºÅb1˜¦ Û¶¡ª*TU-¸ªQ®/“…†a £»»÷ÜsŽÀ‰ó‰D`Û6lÛF8ƼyóˆD£¦i©ŠGMÓ°jÕc8rD»‰¯³³¶mO˜/rºfœx,uç|xx[·nEKK LÓÌ(Î^.{<çì߉¨61ÀX@DB!±€q€¨¾±O@Dc1TÓ ·ÁÁ‰ÃŒêzfPUÓ‡2‘¤çETÕ©“~~¿¨t”ÉËîîÜɾ\Õ…$©Ûà8NÆp¤n±˜hÓÄãdŽŽã¤ N8@ss3,Ë‚mÛˆÅbP𦡵µ€àcxÛÛnô÷÷ï·ŠÁñ®»J9UUEwVc= EiÌùÚ·ÜrKÆü31£Äc.ñx<5ŒDÄ8Pi±˜H.*ŠH0Z–H܆x^ÓÒû|+e¢RQÒ‘SU2éd iN?ù(ó{yFE8œN’º™¦™Jøiš–wžÃÝ»wãsŸ{ € `Û6ÇIÍçØÚÚŠH$’2Õ0 ¨ª Ó4á8"‘´ñRLÃ0 …F¡ëzêµ®ÎU)©iâ˜äÎv2ŸøÄ!üÕ_½ˆ5k¦Ÿ´œŽ%‰úúú°mÛ¶IçrliiA[[zzzJzwÁtç$¢úÃ8@Dc1‘ÀX@Dc1”šm‹äßÐH.F:éˆáT-K$(ó1M±ŽzU×ÓsBòúÓ5“y-Ë‚a©ä_8†išÁ¾}ûàñx ( ¢Ñ(®»îY|æ3«ðéO>Ÿ€H app¦iBUUX–•šëQì·Žh4Šþþ~¢zR×uضwnÆ\Eo¿úûºk×UøÀ€H䟧¦aƉG@Œ›<™xܵk?ôDDDDDDDDDDDD5$•v2a(ódá°øÿà`f…¡ûÿ¶ù»¦‰ŠÃ<£™f,7SùæŽr'ìÇéʆF"8Žƒh4ŠX,†5kÖàüóÏÇ‘#Gpíµ¸¶m£»»ªªÂqƒÁTå#D£QTõc$AsssjHùx ˜Vâ±X2iYΗœQâQ–+{½Þ)—•ËÄãq&‰ˆˆˆˆˆˆˆˆˆˆˆªH,–HSw‚JUEÒ*M'5M ³ d&üÜÛ Ò‰DÓ KY™eåµX²Š3I?¦(J*ahÛ6š››¡ë:ž{î9,^¼‡›ßüfÌ›7Ïç°e‹‚h´ Žã ¿¿­­­€ÐxƒMÓ„a‚iš©íkšÃ0RéjEdW‹IÌ–ÛŒ---èééA"‘˜2ù(«#™t$"""""""""""ª.ùª L'u==o£ãd.›]E¨(b»¦)–L?gÛ"yéNþeSÕ™ÍcX辆Ãâ_1g¥Ó4F¡( º»»ý×÷¾÷½øþ÷¿ÿùŸÿA?>úÑuøéOáÅ»SÛÔu=#y  …RsEʹåЪÖTåžîGQU‹€2%/çÏd¥ 6úúú¦\V.#×!"""""""""""¢Ê3Íü‰ÇX,ý¼iŠÊFÃÕvî¤`$21ñæÞ¦ªŠJÆ©’fCCåÔ½Ï~¿·Ýv¾õ­o!‹¥*Ïž=‹çž{º®Ãï÷ãõ¯=Ž;†°Ì\ð—pÊĢ܆â:PªªÂ¶íÔüŽ3•LÎìØ¨* ,àÐ\¾c;£Ä£ÇãIÍÝ800w¹ôôô ­­ §|{ADDDDDDDDDDDDÓ–/ñ(ÏöT&#‘̹ÝT5½œ;)é8¢âqªaTsU;º“}S1 #k_,466âé§Ÿ ÚÞÒ² ­­­xó›ßŒýèGxî¹ç08^š¹{÷nÀ·¿ýmüèG?Bd¼<ó­o]Š+¯¼±X óæÍCss3,Ë‚ã8hmm…Ï烮ëP³3±C«š¦Y’ŠÇ™PU@»P`€Säó˜ÑP«ÐÙÙ‰]»v¡££›6mBKKKjØÕD"x<Ž455¡³³sö å%‡45͉Ut~zhUC¯Æbé¹e1;ÏÖÝÔDtQ5i™sBÂ0 øýþ¼s#ƒAèº˲ð³Ÿý,5* ’–ªªÂ4÷¸ ==Gñoÿö¯x÷»÷¾÷½x衇°jÕ*Äb1(Š‚/}éK¸æškr&׬Yƒ'ž8˲Fáóù ( EA$ɨrt“í¶,«¨ùgJ&ˆ• ‚º”¡ªtƉGǃ»ï¾±X }}}*=¶mÛ†@ ÀjG"""""""""""¢ ²,Q…è&“Q¹¶-–—‰ÇÆÆüC|fÏùèó‰ó-_èP¡áp‘H–e¥†1Õ4 Žã@Q˜¦ ]׋Å`b±4MƒeYƒˆD"°m¦iŽO FKËÝøìg×Âã¹~ Z[[188˜J$@$I Ÿš¯Ýš¦¡¿¿±X ¶m§ª"'#«‹jµæc€ýq@ÝÀDu%‘\ìììDgg'âñxÆs---³w¤ˆˆˆˆˆˆˆˆˆˆˆˆ(¯XLT":NºѶEµâø”„°,QÉØß/þD2‡R …ÒIFMK©škôPM›˜èœ.Ã0Rs#Hý+çblmmÅÐÐ Ã@ @ €¢(Xµj|ðA†¯×‹›o¾O>ù$.ü*þýß—cll çÎCkk+B¡t]O%mÛF(ÏX°¦91É*çs,„ªªðûýy·_N€kîÍnŒ¹ZzE%ݘh$"""""""""""ª>Ž#¡¨\ÄP§2qØÜ 9’Õ½ž;y(+-Kü8ÎÄaV‘Ô”?YÓ-æ\>w›ضp8 EQR•Œ`š&Çã8ƒ0MÝÝÝ©$¥¢(øÜç>‡p8ŒW^y?ûÙÏ`Y®¾úvíÚǹÀ+ˆD"IÀB‚²t&úûûKuJ§-´ËíW,QC¥’%óéêêBOOöìÙSî—""""""""""""¢,²"1ó3Êd ¢ˆD`vŸ¬rôû'& #ñx8,ÖËWð‹ä¦{Ûº.ÖÏ—|”C¨Š6[©9åÜŽ­­­€Gy¦i" !" ¥–µ, Š¢à'?ù ®¿þúÔs"iù8ï¼WØ„††§]y¨ª¹«;k…õ `]è*Dò± Êžx$"""""""""""¢ÊQU‘,ŒÅÄ0ª2Y‹‰ŠF™ËŽ™Ã¥†BâÿÑèÄDe¶@ ¼ÌžÎ°µU<68˜ùx0L ¡*‡T•ó(f/wæÌ™ÔŽ2é8NjŽFUU¡ilÛ†ÏçCww7>õ©Ë°xñ ¬\ù0ŽrFDzØác+îíä>”ažÇù•Þ?""""""""""""*/9'£ßŸ2HWñY ŠßʆӶEÒ°Š¿XLþƒ3U–@4…aèîî†a°m¦i¦ª¥H$Û¶ñš×¼×]wlÛFss3 Ã@,Clü…UUE,ƒßïÇàà ü~?ࢋNààÁƒp7þïiCÛ®íŠGP¿5þe©zd⑈ˆˆˆˆˆˆˆˆˆˆ¨ŽÙ¶¨@Ì5Å ÌíÙvzèTÃC¥foº»'V1æ¢(€mÛˆF£©ù`dD$?Å6mX–•.5àÈ‘#JU-º…B!D"\rÉ%P­­­ã8PU5U©( lÛ†ªªÐu=5|ëš5kGŽÁùçŸ_éÓ2«d•«ºTL¤+Kˆ‰G"""""""""""¢:&‡=uçñL3ý8®z ‡Å¿ã¹ºw²Ñ¶ÅP©ù~¿HPÚ¶X,ŸÏ—ªFll”IN>ŸÍÍÍðûýó-*Š‚H$2!ñˆõ4MƒeY…BèïëhmmM%7e…cvÅä’%K°wï^aÜzë‚iÇHdⱵ²í"× £ô¯Ã9‰ˆˆˆˆˆˆˆˆˆˆˆêŒãˆ¡QsU9Jɤø×€Ô4‘8ÌN*º+#1,«\ß¶íTBI®áá“XºÔã8°²Æ'µ,¤æcIU$ºÉäa6˲R?@~¿?5¤ßïǼyórn>ð ðØcûðÌ3œ=ë­ô)šUŠØG݈ˆŒÿ¿Df”xŒÇãhoo¯àá!"""""""""""¢|,+³ªÑ]< ‰Dâ¼y"y(†E‡B"aiÛ¢ÂO2ŒÌm¸ƒAX–…ÁÁAhš†ÇÃË/¿Œ¥K@ U‘¨âìÙ³ˆÅbèïïŸP•8]×á÷ûá8NF‚Q&*Eªª”ÒòåËñ‰O|û·/TúôÌ:UœS‰FP!æytPùÄcCCZZZ*|ˆˆˆˆˆˆˆˆˆˆˆˆˆh2–•žßO’‰F)¢Qñxk«HVæ*8”9BËCŽš¦™úñûý©9ÅÆ¡Cgà8ü~?t]‡¦i0 @ûöíKÍ¿8]áp~¿ì'¹†iIØËñúׯ©ôi©µá ý?ŸéâdûXIÈ™QⱩ© ½½½•>>DDDDDDDDDDDD”ƒm‹D¡ßŸN*Ê FÓÏÉù - ˆÅÄ~>›aˆ¹Àç¦i" ! aÕªU0M££‹°d ðË_¦‡XÕu–eá²ËžÅÞ½{ñ…/„Pˆp8 ]×SŽrxÕ|d¥c®eÒ‰SO¥OϬ³m/Ÿv{P”¯Ú?þ"7î2&+ £½½ÃÃÕ>NDDDDDDDDDDDDsŽaä~<V­ DU Bwu# rNŽ“Þ†LBæJÕÍïOWCZ–…P(„H$’J † þ«Vý¤†CÕu¦ibÿþýøÄ'Ο4yˆ9 }>LÓ„eYˆF£ˆÅbãõæ7ÙЭº.~üþ܉Õzg¿t>Ь§O´Ñ À(ÍK•xlooŸðXOOzzz&<¾gÏž%"""""""""""¢¹Ã4Ó‰GÇš›E…¢¢ˆ¡Uås2ç§ëçD…d,&—–e! B×uÄÆ'~túxfѶmøý~D£â5u]ƒa¤_+›¦ip'UñhÛv*¡˜ËÐÐlÛN½žh·*ƒ "јã¹å__^ôKÌ(ñèõz±mÛ¶Ê"""""""""""¢9IJÒUã9ÂÔœŒîA™Œò'›7'àóùà8,ËBww7æÍ›Ã0 ë:Eɨ>Ôu×\ób±ëá÷OÜ®¬t4 1\kkk+‘`D‚TU‘ª¬ŒÅbœ•ã§ëâµU÷UµX,½ÃSQøÕ­ÞPÜËÎ8ñØÙÙY¶c±eËtvv¢¥¥eÂs]]]èëëÃØØ6mÚ„ÎÎNx½Þ²µ…ˆ*ƒq€ˆÆ"òÅÆ¢¹ƒ}" ˆˆqÉD™xÔu‘Äóû3“Ž’»h0{ÔS]sBîÙ³ªªŽW4ŠáN1\ªmÛˆD"©D¢Ì_iš†7¼á4ö­ÝÝÝDÒ÷5cpðS8ï¼'ñ èïãgÛâg–òœ•%³«îÒÔD’1XýÙâó+½ßÙzzz0<<œó98:;;ÑÛÛ‹D"ŽŽŽJ7™ˆJŒq€ˆÆ"òÅÆ¢¹ƒ}" ˆˆqÜ:NzþÆPHä”òM…˜+ñFˆä›ãûöíƒßïG(B(JU6Ê¡QEIý?sCÀþý‹ j³išhmm…a0 ¦iâU¯ú)|¾y©Ä¤iš³v m[TΛ'ŽcEXšDØÓ\×q€pxâž¹˜æÄjÇ0€XžåÀÂc ±î™uEí^Qs<@__°iÓ&ôõõa`` çr½½½Sngûöí“.300€¶¶6´µµvìØ]×100€M›6»+DTaŒD0‘0U,` ªìÀX@DŒn–•ž¯Ñ0DÅb2™ywâÑï ¾p8Œ@ ÛVÆ™ÿ ]B¡PjyMÓ`šfªÚ1›*uê6kš†þþþÔP®¡P¦ùC:èzwÞí×µ0™ ˜Nõess:ûœ=¾®ä8ÀªUâÿÓœ+ó‰¯?}{÷µ{3®xÖ-[°}ûvìÚµ H$ÇÑÔÔǃx<ŽÑÑÑ‚æƒliiAoooÞåðð0‰DF µ×ëESSSêõ‰¨¶1ÀX@DÂd±€q€hn`Ÿ€ˆÆ"bpSQå88XØ´}îet=]íè®0¼øâ%“&ÿ”<唪ZXN+ÃqTò1 Ž­@H U$ù8´³þ²iúø  €âÅtÑ‘õ5ÍÜ“U* 044£ñdO­=Uô®Í¸âñöÛoG"‘ÀŽ;&Ü1 çÆÖ­[1666åö¼^ï¤ã-ŽŽÀ„±›ò–WQma "€±€ˆ„ÉbãÑÜÀ>ŒDÄ8 †È5iŠ I>"ÑhÛ6LÓ„®ë0MŠâ‡Çso{îc«ë:,ËÊ»MËJ÷:MÓR‰ÅÈø8­Š¢­,@ i"7K4 °hHLw¨i†fïõSTDµ£ƒüó.NXoü¤Ë1v[[ÓãÇ:N:Ù8Y2·ÌyÞU<& LZ¦ÜÔÔ„ÎÎNÜ~ûíåÝ‹)>|]]]èêêªh;ˆ*­¯¯íííØ·¯¸RéZµoß>´··£¯¯¯ÒM!ª¨öövtuuáðáÕnʬ“}‚öööJ7…¨¢†‡‡ÑÞÞŽx ÒM©ˆC‡¥b!Ñ\&ÿ&:t¨ÒM©ˆxíííuuA’h&øý€ßˆxͰú¯†Ã"¿‹ü’THâѲ,ø|>ƒAtww#À0 ìßÿs;¶×\sCÎõòU:NõÚ¶m#¶mض Ã0R‰GEQÒÛ A$ÝLLžÃ"è:ùèx¡áwPö$\J,–žT2âz] b¸ÕéŠDÆw&"Þò±©øóï³Ì£Û'˜QÅc"‘€Ôxɓټy3¶oߎx<>ᎃÙrÁছnªØëU 9Îù\íP¯[·nÊùf‰æ‚ÞÞ^ÄãqÄãñJ7eÖ±O@$455¡··wÎ&ÞÖ¬YÃ>Ò£ÍÕïïz×»RÇ€h.ã÷~? â5Ãê¿f‹‰“Ì[ùý¢ØÍïŸz]Ã0à÷û ¥‡4µ, }}H&ƒ¦å.7tW*æ“›t>ŸŽã C×õü Ì0DÌ`@$"geÑûÆY‘„ C$Ë%rêºø ï¯>~ Â6`©™ AËëFzŒÝ@`â¶åc¹ž›¦ÎÎÎ’ô fTñ(_Ôãñd<ÞÖÖ6á*—)Õ„¹¶ÓÔÔT’mQm` šžÉ†Å¨eŒDÄ8@Dc ŒDT¯q@Ž Ùߟ^UNï' ݲٶ Çq at]ÏH"F"ôô<†††W0Yaãt–eAÓ49rýýýPUÉb*DâÍÀìpà?~Öµb˜Þ<‹Óˆ!PMSŒ“+§Ø´,Àˆð'Y'3ííîÉÊÉÎÅt’ŽÊ^a:£Ä£¼ HV>J^¯wÂBr™b?àr»Ù“ÁÆãñIÇw&¢úÁ8@4}±X >Ÿ¶=‹cV”c1ÀX@DcÕ{0M‘wR‘‡’‰G#O²Îq466¢±±æx‰¤?OiäêÕó'Ígù')©ŒDDNÌ4M˜¦™Jrö÷÷§ÖíîO1£b¸Ñr_º2 `Õ*hw ‘gÞ }ÕxâÔ?þSÊÄ£i¦ËS%]U‹Ž#ªUˆÿ‡Ã@€Ãº8ÒÐÈ6ûýâ@k%VCáóIÎÐŒ6l€‚Æ<–Ë”âÞÖÖ†¾¾>Œzzzàñx°yóæò%"ªŒD…óÝÞ1œ†ã8hmmÍxüÑG­t³‹ÂX@DŒD0‘ÀX@DõhnIF™ÿ“ HUy¨\yAÓ4¡ª*"‘FFF022’s¸SMÛ.–eY0 ¡PÝÝÝÓ߀ €Ò%GT 66ffgý~`hVïŸø4´÷º*6uѽ>9Ÿ£[$"~,ˆD§®‹v}½øµ>; X?Ä1/£%=¶mÛ†žžžI“}}}èééA[[[Irî…-[¶`Ë–-ˆÅbèììœ0ä+Õ/Æ¢´X,˲Faš&|>|>_*iÛ6LÓÄÐÐPjl}@$#¿õ­oUºùEa, "Æ" ˆH`, ¢zŒÑñDX ISÓÒ…o¶;qhš&t]Ÿ|ˆSˆQ>KAÓ4D"¨ê4³Y¤ç4”s=ËqŸOì\($2´™–/^}¢ßp? b¸ÕR%ý,K$ó1‘®:ìï˪àÆJÔ†|ÂȬ¬,ƒ…3]1`xxÛ·oÇÀÀšššR%ÍròÉááa455M{²ö={öä|Üãñà¾ûîKÍ1¹aÆšD”ãÕ­hTôå-Ur¼ŒÉñùUUE4Åßut|>ü~?t]G0D €iš©‰À»»»S˘¦‰G}7Þxc¥Æ” ˆÈ ˆæö ˆ`, ¢¹G\. 2sg2—(Ë•<4M‘HdÊ×P”i]’šÀ¶mض ŸÏ‡¡¡¡)烜 ŒÌäc¢ò±±ñ¬Ýà &¼rþ*®ÑKå\“Q3(ÚÌà8"£9U"6×Ó”¶ò2b¨×2šqâÑãñ ··7UõÇÑÓÓ“zÞëõbÛ¶mÓN:"{I¢¹Ìq&¡õŠq€jÖxÈPUøš›±²µ5=V»‹ÏçCjpEQÐÜÜ hxñE££PUïØP(Ã0ÐÝÝ EQR–eá½o}+‹A …ÐÚÚ Çq°bÅ <üðÕ>Ec, "Æ" ˆH`, ¢z‰Ѩ¸W}h(÷óº.’Žîë¶m#Ãqœ©çU„Hº ά}rjŸp8<³¤# `r^EÙ\Å  eÞð?‰Áë² ð!=ÿâLÉ3Ý P@$?ˆÊGÿôW¯3jÕmÛ¶m©ÉC{{{ÑÛÛ›ú½IG"Ê+wé5Í–ã6X`Û8ýÕ¯¢µµŸÝ°ÏŸ:…³ÿþïøì²eƒhll„Ïçƒeš½þz¨Á Z ÑðÊ+xhl Žâ¹ûïÇWnº ˆÉº‡††Rãõûý~X–Ó4qƒÇ“›# ¥’˜ŸúÔ§°téÒJ""""""""r±,qÍw²‘Rc±ôuáh4 Ã0ÐÜÜ Çq2®•ƒaƒÐ4 @ 5µÏ´e'ø† ’‘ÓaÛb>G·)ö]UÿzÀ÷XÖúx›LŸ{Ì[]ÏŸ1v¿VÞmΰUbÆÙ¼^oIæq$¢éqj8Õ+Û¶F¡ëzên3UUqÓÁƒð>vž> ¿ß‹4 ùàƒ¸ìÑGñ'v8ü~?^ÓÝo.] {ÿ~ì¿è"´Þ|3BÝÝøŸ·¿ë-"\¢iXõ˜è!iŽ#z¥Á 02MÓp$@ìèQlœ?_t~ Šßîîn˜¦‰eË–aÉ’%•>TDDDDDDDD4Î畎îys‘†ßøÆ7°lY ¶m# »»ØqB'ç8LÓÄÈÈESìÅiwŽP&Ü4¤‡_Jt†ã’¾ü4€«&>Ð8þït*c1‘ð a:Yµ£ƒÉ‡:•í6ÿ?uœŠ5ˆÂï •,ñHD•aÛ™SÄÙ¶HFΤºˆf µc à‡[¶  be2‰Ö£Gñá¥Kñ÷܃oœ8îîn8ŽUUqž¢àš&:hqU$‚~×Láÿë¿â½?ü!·Ý†P(„{ï½oúÙÏÄãð¥÷w8ò½ïa•œM|üñw^p:…ûýXúÖ·ŠabHWº®§æ< """""""¢ê ŽS”ê÷ÿöoOãCºGŽ ¥®;•‹eYƒˆD"0M3UQ©ëú̆YDrÍ=¥‘d B$ǦJ¶Ù¶HøMs¼XÛ‚?¾*÷Šxc@0$ÚShÂϲR×ݦ^bH×ä$Ë ˆAT€ÊáWKÅq|‹˜ßs*L<Õ8ÇIW=†Ëò5)0Q½sgÆÃM˜¦™úwÁ¾}øÛW¿K¿÷=|ôÔ)ØÏ<ƒ@ :\Ñ(MÃ[¢Qt^t.™ä5EQ088˜ÙIóûáÑ48ÐÆ”?þíoÅ]\YðUÁ ¸‹Ê4SwSyî½8u ýýýb!UÍ=Û8UÖV1JçT—®LøÐ‡®Â•Wþ?(ŠR¶¡U ÀmÛÐu@š¦add$c™’¾v7Db,;) ÍÍâ¦û@@ü‹‰§y1\Q]Ù Ó¹,ý e‰ënˆÝ!‘ ,tÓ¦ D".\H#!ª"C˜ý({•b)1ñHTä ±X ÿó?7C×ÏK=Fá÷ûSw¼Ä8)$Ía¶m# b0ëN(˲`Þ|啸ùmoT±X –e¡;ÁÏo» ~ñ |`ï^¢C5|êæ<‰¿¿à¾÷½ÌI»ÇÿðàA4¼ï}S¶+×aªªBUÕÔvEÉÝ‘IÍ`Püß4EÇË=´†ªÎlBk""""""""𲏤Â;ï¼ÀíX·n]ÉÛaÛ6Çã8ˆF£©i„äðªe€vÕͲĪfÎ= MgËÄ&BöÊÀõÚô‘rûª*ª WAü+/±ÉDz¯³É›ý ­üÔ1yµc®å}Ž”èøfÏ­YL<U997o¾&4Müض ÓTœË1Ðï4Mƒªªhmm…a¸âŠ+*½[DñÕ;îL–e¥’}†aà©|[-Âåcc8½l¾{÷݃PŸüÑàýÝï°òŠ+022Û¶¡( .VU=z+Wæít]t÷ÝEµ7‰Þ¡óûE0p0&›€ˆˆˆˆˆˆˆˆªÎd£†Ê ã8xì±å€ÿû_Sò6D£Q˜¦ ÇqpäÈ8ŽƒX,VÖ¡\3ølµ€8À'q½KN!$G÷f\ahY€ï™ë /<&ˆrŠ¢¡!Qõ(ˆƒ ?"YŠþI—¥ºçv,„ QÑYè±ÝÕŽaˆù!‹ÆÓD3!o<¨u–%âØdyYnY144<гgŸ†¢\Û$ÇeY0M¦i¢¿¿üŽ¢¹åÉíÛqÑ7¾;-ÂZ[SC˜¾ðïÿŽO&±ôÓŸÆÏwíÂÍ÷Ü%F(‚ⵎƒ{?÷9|àÓŸ€ŒNÖÊ2ßåå/tlx ÝÙrwv C&!‰ˆˆˆˆˆˆˆªšÄ*×È¡Žã ¹¹º®Ãqüó?ÿ>üaàÑGpíµ¥y}9¬ªßïG(J]S¡TNÊÁ䉷ÿôÇà`ø©&’ŽîJÇ"ÈËyæËoCšF"éëj–•¾Žf„?ŽˆÄŸ]ÌçV­ŽSÕÒ³šKé¹!‘œétkfy› 0ñHuJèZšë°¹Y´×£|¾Â*´Å´sNŸÞ…S§>Ž¿€üÇSxòIš¦—Å[èïï†ßïÇ¢Ñ(,xgêØo~ó‡SáJTí,ËB¸¹÷Íobõþ'~±d þï£âm×]‡ŸÚ6z-ÂñD¯üË¿`ïüùèšð¦Ï56½ªª©ÇõJ—MgwDlˆŽN!÷( pÀÖñŽš ÀJ¾+Ö®Å>ñ‰ÊîÑ ‰k¶Í͹G¿3MŠ¢@Ëz²˜Äãî÷½WÞ?ZÇ U]“KfcÊ b¨ÕÖVq¡{p0½óîħbNàl\i^~ð:À÷ƒI¦KÔuÑ.y-14þc"=ïcb¨ÖéÒQü‹*DR66þSæÕébâ‘JF&ÌÂáÒi‹ ÄHD$eU¢ß/„28b9¿?ý»ãˆ„£¼Q!‰A@< Š8"ã©ãˆ,EÄ–éæb±tvö±Éæ8éø%‡ƒ–¿oØp úÐ/ ©¸îº•pœU9™DüÈG¾ŠþþëðêW¿pë­û n‚£øð‡—¶ ÎóÀq€¿ø‹/`ùòyL:RMzü'?ÁŸ¿ÿýø£¿ø <}Ï=b(ø»/Æ^y¿öùpGo/EÁŸATDZ–]×Eã4ÍÚ¤Ùù8‡‚ã¿AtЀñá&r6Hê¢#"ï 3 éÆSý°woe÷ˆˆˆˆˆˆˆhŽóùDÞ-Ê} Ù²¬œ#ÙéúÌ KÇÁØ;ß Ü?þá¯þ ˯¾zF×ͦÍ0Ò øxÎÕ7“]ƒ“ÉÆ Ä5°45zrŠòÍ)©C\_34Bd.§;È =þS, "áhAT>:ã훪=ƒ(;µJ%#«õä°¡á–ùÊê<9´¨®‹£a¤urhT¿_<ß:>´`4šND†hŸa¤s:éˆÇŽËgWNÕF˯ç¾5L·%{øV9œªiŠv]xáÏÆð¿ÿ÷Qœ9³†ÑŠÖÖV|á «ðýï?Ó4 ñùÏß ø—yßøÆU¸á†{qòä[`YÀ…þ)€$Îó Æø0 V¯þOƒÀ¿ýÛóxøá÷ÏÊ{‚¨–e‰a‚- /½ûÝÀ¼y¸ìÆñ…Õ«aÛ6®ºåŒ=ôÌÁAl8u ËÏœÁWðƒŒŽ’ªªðûý¥é<;µ…éu*lˆŽ”åú]Ž%ï¸Ë;Ü„ œ¯vÔ\Ë(b; ]uϬ+þ¸QQ4M\£Î®x4M±XlBµ#Y$8%ÃÀÑßþ–e¡µµÿúøã€¢À{öìì$ƒAñã󥫂–ª¢2¨ÿ 3¥võPËä«üŒ@ ®ËM7‰h£øëŒnD²16Þžà$Û—CÆ–+iÚ #ð—1I&eÒQ&àÜ•‡ÅÃ)K­­¢úQÓÄ먪ˆ[š&þÿÊD¥»¢Ð4E²q²v)Jþ;L²Û ¦·ŠÿŠã#+5ý~ñœišæŒ¿†Ç~þó8zt>üá£ø—ù,ø,ë.¸À€Ç#ƒ¾‰¿üËÂñãÿMÓ‹W]u®¹æ üêW¼ím_MUs._¾<Õ>qŽNž<‰—^:‰K/íÀ¹sÏxí¬¾oˆ&5>áê³üÇxø÷¿Ç¯YƒØø¤§ÿ}ÕU8øôÓøÞÅãßñÜüÕ¯Bwuˆfm0TÙ©™Î¤ÍD¢OŽGß Ñ¹Ð‘N:•ìxcޝ«»~ׯ—»oAtvb˜8Ô„ @ó‹eýHã0Þ·[sÿšÂ:YDDDDDDDDT2Ž“VUŽ(/u)ЍHT¶m£µµ@`æÃŸÊêÃÀ?ßp_°‘HDŒò%/æ—sª!™DÍÝ×z4À?äq L&Ö¦s.‹v¤¸©ˆkr¤“¡VýXŽÖ4Iˆk…Aˆë¾ñö…¾–XÊ„ç$XñHÓb"ééÇeµŸL>š¦ˆ²Ò¯rÝñ\CjžEùœ;Qè8â±æfñ»Œ2)êžÑ<Ô4Ñ6™,œJvÕ¦mÛ…ºSÿÿÊW> ]mq‘¬ìîIÆÆFÑžÁÁtR2b±|>ÇmO?½ Ï?¿ý׆ 6àÈ‘OPÑÓóGèïïG?>ò‘àu¯û’É$†††pÕU·àÐ¡ÝøÙÏÞ„ÖÖߦö_&@%Yayé¥7cݺuX²ä›Ø¿?¥ ³ñM²,Üüú×ãpC0o^êΦp8Œp8Œ'ßüfüìMoÂk¿ö5\ýË_BQ bppo{úiX¡¾yàn¾çžÊMN*+ dÞ94Ù]Jò}+Äy}|ù¨k½Øø6ÃȼCJ>tý®!]ñ(“™:DB3šõÚ‚t§f|Bì5÷¯Á¯ßøëÊK"""""""¢9*M_C·³ªåÇÏçC4E0„¦iˆÌt^3ŸI¿'‡‡ñÕ›nÂï|'úûû¡iš(V‘ã»–cÅ5@Y$«ˆÌ £é’•Ä53ySÿ4©W‘•`_Õñ6ÉŠCyÏ™brÍî¤!=ESd¼=DR5ÌÂP«¬x¤‚9N:¹æþ]Ü…!“7/é*é\óF£éDœ¬@ô—øªjzF9g¤L"¶¶¦ã’®‹eäÍŠ"b—LPÊ!Oݯ­ª¢­…NÛf"؇Ãa(Š‚¯~õ4NœØŽßþ¶¦iÂqB¸æšâý¯k°fÍhà8ž{î9(ÊÍ©c°qã(Þö¶çÑÜ|%T5†ƒoªUA,^ü%—@UD"·B×uø|bß÷¾·§Ú±}û—ÐÜœž?óøñ7áÈ‘?ÐÛR1Ûx|ýëwãÉ'¯„ÏçÃèèßcùòƒxÃððÃÆéÓ—TúíDõβðµ/~¿þéOqèmoƒiš¸ùmoÃçl×\tÞ÷éO㯿ñ üààAøý~\=~ÇÁ¯ÞùN\óío#âJ.ö÷÷çÇ~V¸Ç\—s-Çÿm0‚tò/_p$ë÷~×ÿ5×ëXÉÃ!¤‡XÕ :€èÀÈŠE™”TÇ—1!:5Q¤«*e%e. pjí)º”%DDDDDDDD³Å4Åuëþ~qZÓDþOjmm͸=$/ŒOë5Lèºøýøbc#GF`ÿüçܾ½ü;¦/bË Ö¹8H_›.}|}âZXéêÃÙ @ô«@è+%Øgéë‚ÆøOâZžüq“¥–åÆ-à:&DòQ…¸n˜,ïK³â‘òŠFE2P& #,ŒDDÌsÊ jTVhÇbé ¬NÄ6ee¢ûD‚3J·C&eõ£üÝý¯ª¦«UU<ÖÝ~]¿_<.š››1oÞ<1DõUcc#‚Á TÕÆe—õ£Ý8'N| 'N´  Aר»w/>ö±ûÑÚ ƒaø|>ìÞý¸ôÒCÐuQéµmÛøõ¯ÿt¼ý*^ÿú;pÙewA× \pÁ>„BJjº¡¡‰7š¨ªxLV•&‹ÐÑÑ„Ë/KÝÓÝ^OÓl,ZÔ‹·¼å$ED¹í¶×á§?ýn¾ù­ôÛ‹êL4…ÏçÇßúVüàÒKæf膪¶møý~ôþ×ácO>‰§?ò_¿›®¸ƒƒƒèîîF2™D2™Ä5:$%M:ʪB…¿nB$[!:4ý“6÷Ct*š‘ž{1»bQ&§"‡!¤ïŽj__N˜u½–ܶ…tEo—{lùÉ^;ì¿eéŽ+M)×pýþôˆ~²(0², Áï÷£¿¿_ ‰: rxVÓ4ÑâO>õ)D"ŒŒŒL{[0MqA:›84àdä…ýÉF-sÎ52Ù7qM- q}­ÀþÔ_ñÚ“ñ·ié‚ìvYezíÉÈcåGfQD™°â‘¤oBs¦ç'TUøô0¦’¦¥Œ–•NF"b]EËËáV-×JV)Ê!ZM3]e=4\{í9üáþÀU€×½î$€¥©í¸o–°,  âÃþ0üþ·¤^C×EÂrþü½øã?~†a`ß¾ ðÈ#ÿŒ+¯¼Áà·à8ü~?¢Ñ(EA4Eww7b±D ŠÌæ_ÿõíãsJ.€ª~¡¼C%ˆNⳟÇD×Cxúéƒx?¶n½}}}xë[ߊÁÁ~¬ZƒH&ÇÞ½ç°wïÇqýõ÷áÿq lûK“–ÍkZ:¾ šöpà@:ÑÚÜÜŒP(¿ß^ðbóæVøýKaŸÂ™3»pñÅ/¸Ÿüä‹ho?Vé·ÕÃ0`Û6TUE4E ÀG_|«NžÄ#Ÿù .xç;q©ªÂ}_–ªªâ} áÏŠ2UVBÎh"=¤@+Deé1Α°ËîôŒŒo#{à÷îñÇüÈLôÉq¡wnÉd£L$ÇÛ08Þ¶DçIÎ iabâHw¸"ãÏÈßS€C7â3?DDDDDDDD4=ºž.‘£Š©-D£QD"(Š‚þþif‡lGü~üÇÆ‚¢(…BPeú G s4 ³ºH_Ô·,Q¾):t« qýj†SWf!5µÂã?ƒ׿ò\?TQø¨ˆ3¢!}]0 qí/6Þ3¯ö,†Šü#¶•s”e¥K¹%]©§‡HUU‘D”Ð43ã‹®§‡Y•C°Ê¡Me2L–ŠË„™e‰Ç|>±-¹\,–žH÷oÿö,|®¼òƒ‡`Y¿€a¬…®û?7½É `94ÍÆO$ðË_Æ`š&¤’‰'N,°}}}èë #@U=xä@Ql†‘Óº±±Ñh~¿@~¿†aàÿüŸ‹pð h¤¼%I?Ó.»¬ú§›qýõgaÛ6º»»±wï^|ï{ßÄž=I¼õ­o…ã8°, _ü–ñù×`çÎ¥øîwOâw¿;M{Žã¤&ÎE×űmmÿ—ž’¦iƒÐu££Œ|àÿáÜ9ylâ}ïû¡n>s¦ÒoAªQŽã  ¶mX–]ס›&Þþö·g$ίŸjCÓI:Z‰ÂAˆ?ri "Ù&«ó­E:ñ(o€^ ‘4TÖTö•ˆŽŠŠtÆMGºó¢A$ ˆÊD}|½Bûˆöøöå>eÏÉèî„É9»‘?±8ÅxíŽãàÑGYùL4×ÈQ,äwÃ@øå/¯FKK¥[FDDDDDTÿš›3 åµñ?û³—ÐÚÚŠ@ €@`™8ÇI 7xæþG¯¼'—,¢(P¥°m57‹j QQ“~<?"+š®Hr'$åEêj¡AŒ&‹Æ ¢ c§ Êœxt“×åHfòú_câqŽˆÅÒU†€¨^ŒÅDòÏ0ćLV,Ê*F9¶´Œ=2ñ%ùýb]ÃH'Á¢Q±ž¬nT”t¢L&05-sÞÇ@X·î0.¼pÀÛ‘Hü ‹-Â#Ü @T?~ Âá?G àG8|žþkxßû> Ûn†ªª©*EÃ0 ( ,Ë‚ã8¸æšÏák_ AÓÒ‘ùlûæÔÝ@±X ‘H†a¤þäÈý6àºë’xì±F(ŠDb¢Q/$¼Þ—±wï×pï½á‰'^‡k®Q‡aš&^|ñÅÔkÊÇFGàKxÝë.Æ/~45ÀG`Y@(ÁªU«rÎggÛ6Âá0t=ËÒ3æ¹çÌÂ;~ô#|ñòËáYµ ‡–.Å’g×@ ç=¾`4 ÄbXî8©J5¢l2Q.“á~¿¦i²¬ÔgL×uÑðÊ£bï׿^¾ÏÿŠ(DGÁ†èDD‘3]VÚÈLöÉÇLˆäÑéè‡øƒ/çD”"…èLw¼yÝõšÑñ×(äN"?ÒIÌì‘ee"rÜÞÕ{q™zN¾÷$–•à¶m#‹AUU„Ãa !fÄ ˜ b±úûûaÛ6ÇišPÏ>û,6oÞ\¾óFD#‡°×4 öQÀ> „zD7@ÞM+‡õ¹ô·—bÉS•n2Q]“ù;wžNUË.{_ÿúw`ÒÑðò9üÌ38¾z5¾°v-® 𦓸ÄfY•422ñyY¡ä^¾»;=ÚL•¢Ò1ï>ÿ+“&D ®Û)ã÷ìÎ`ÛÅP³þ­cL<Ö)Yy¨("q(«eœ0Ít…¢iŠjhwŸ\61IJÄðžn¶®JÓ dVTëºxÎç;Šÿ÷ÿ~XìíÒñêĉŸãöÛ½¸ì²?ÇÙ³<Ç'?ùq|þóâ€}èb=ºßü¦ƒûî{À]xñE>_¤&Ø•wpØ¶ÆÆÿ¿½sªºÿ7/’@2ÉðGˆÀ„§  †*¢ÑZmCl­µVj;ùõ^h«­MjZÅög›AXûÐdz­­3¾%¾!Ã#BB&™B`~œÙ3“ d’Ì$ëˇÏLΜÇÞûì½Î:{íµV F£‘7Þ˜×Fþ)¯BƒÁà€ C¯×ò,Úív 999<óÌ+Ü{ïh&Mz†k¯MbÛ¶gq8N`2é±ÛõLž|È“ëÑÄ]wmcá•8NN¿ûn‹kª‡†ÓiÇbñå¨ÔëU¾IÐ;|z÷ÝŒX¿ž3›7së­-V™Ü΢«ëX s´$™†üשž,àºoä;÷ßÏãwÝÅDµ¹¤Äó °Ù¼1uwïÞ-FG¡ ʰh±X¼cD½•233SëÏ99ÞÕMáfóÅ÷§öBš¶‡2ü™Ñÿ¼‡ùžßòüöSa ”òbÇ—4y)¾°¦&Ï9”g¢Š»ž‚fœÌćýbt(ÿdÒ¶‹8®(‹“ÉäõƶÛíÞÐûû¹}ðC|Ã’FNNùùùÞ\šJÞ8²³³ÉÏÏÇn·{-oæG}ÄŽ;.î¾ ‚8ÚÂ/-ä{ ï½×À;ïœbýú$*+cÑéö2yò[’8þ„Õú2v«ÿˆÿ¾ŒŸÓÍ ‚ ‚ ‚ ía±ør8ªè‚þœ9óvì8ƒÕZtQçu:äååáp¹0üçÃc¼ïÃÌL­]µÂ -=œ.¹a<Ÿ=úSE,ËÇçœ`AsDz 1<ö7Ý‚mì[,>ãŸÃ¡-V((ðy'ªü‹¾ï*ÜéÒ¥Ú„– ͬr6¶&*ª‚ììd²³•‡”½^»¨¿±/:úÄÇÿš­[ó˜1ãà @ÃáàÿØÊäɉ;ædéÒ¥üìgOòóŸcÓ&MP~å+šGOLL67`4(**%##£]wqƒÁ€Ùl&;;Û¶Ôétz“ó‚f¤4,]º“É„ÕjeÉ’%^¯®üü|–.]Ê=÷ŒæÞ{¡¸x%% ˜L¹8 0› Øí{½—…{?‚fkÎIz=TW·¼A úO“=í]Èx„Ì’R <÷#¼RR˜a4R`·Ãðƒ ˜L&RRRØ’Í«ï¿ÏmÏ?Ï3Ï<ƒa÷nvXò°X,F233}Ï=ü¿[om®ÕûÕdRÉ!aùò¾î²B£ ðV«Õ;.T_2›Í˜³³µÛ^z ‡ÑÈ¿ú•fàsK̰8ôXЉQ…3u¢æìøŒrêÁ¿ÍЧú|ÞƒÊp?šaÐß#Py@šñ•¼RáS3ñå_,B3JªqÑz¥‘Êטï9ÏEèkj!ƒú_`Óò^<'W‹œžX‡‡Ã{ŒF#‡Zy`FïoÊèPZZJÍoj¸"æI²³c0 ïïJÉì(€ú=>>>pJ„cÝ×ê)zÏÍõ'㉎=Í# ƒ‰‹hfx¸‹1ǸÎZË\ƒZ)YÇøñ &&†S§Âx¿®‚ݧ_"er a59|P}=碯åè=GIJJâPá!ªã«»[LAAA¡ |)Ëüu¬V+V«·{$ëÖý“)®ó“Y,`±à,-Åf³át:)í®ÛžÁk¶€Ó E³¡¥ïÉ@›/S!Jƒ(¢ê¥×mn0Ÿ~ê´¯Ãc£Œ‹&À¶lÑ †yy>ºœm‚^¯}æåùBo)O;ÿ0¨à[Ü HèõšW£ÓéÄb±`6›±X,äååa4 ³y=£¾ýítRR–y½jl6{ö$3|øãlÝz€áÃßdÇŽ?ÙäåÙ±ÙlÌž}7·ß>§SËÏøóŸ¯4ƒ›ö©•MyíFŒF#¥¥¥æClí–ž’’âÍç¨&÷­V+[¶lÁ`0`·Û5£€Ó©…Xv8¼BÛl†ŸÞüºM›Àng쫯rcE9*QhšœÍJÛ^lk«ìvô'&bo˜¿Ènñ°1ÌNЬÃ&g’Ãáà_§ÒÒRŒ&dg³ÆjŲcùùùõz¯§“2fè/äâL1·…€a³iÝÎãÐÚ&´rË}määäàt:½­ÌÌLœN§fpT2,Ìë6=ËhdÖþsš!렂 h›AS: ´ÌGØQ4z޵ÒÒÃO=ôíhÆÉ9~ûZ¯uÄ=-sšýι_®CÿDÒ™à| òÀY™I-Ur4Ù¨×CNŽqãöòæ›Ïb4[ÈIƒÁ€Åb!;;›œœÌf3V«“É„Óéô.\(((`ðà¿pë­1Þ…þ‹'üï3‚ç‡Â“OÒb5›ê­)(h›ÛûÇÌ™e]ìe‚ \2*_l6œZ}Š/ã¿dÓ¸ML|c"Ä}@yÜh6n>ËС5>\Gsó£-ßÊ Îrðì ¾Ÿø)3â\,a ·ÖÇ0T7”Q3|= ‹Ê"yO2oD€þÇÚÁ6Øý£ÝŒ}`lËÅZ˜ÈD°Âñlj”WAAA„€ãYÓO~~KG‡ÃÁÒ¥K1›Í|ï{w1n\'FGO¾³ó¯½Få½÷r{F&“©ÃEç]Ɔf`Ô´h`™hskF´98¦tmçòT4±P4à…b™C ™eBo*>ÜnÍ@Úijʟ¨Œ‡æh4jŸê8•›ÑkÜ2hßçÌñy3fgûòª}ümSÊSP»¶Íë±£å4áp8(**ÂétbµZY¿þv¯qÏ`0xÃZ­ÿÃO,aút6›‘›ožÄ}÷inIÏ<óŸèt`0˜[L²ûO¦+ô’’¯­3×qe¤(**Âh4zÏÀhµ2êßÿ&i×.ÎÍšå³ÜzÚHgÙämø‘·ÜBú A-/f0ø¼ ÛÃl³£ œ6 sÐ* ¶§’ʰ ÚÊ—¼¼<ìv;&“Éfqÿ~¯á×l6“’’rI1À…Ð@“”áIåHUqásr´îWP çœm¿üà=ô¾× šWcÞÒ¥\uø0ƒvì`ÖWk³i+üc=TWû:hÚ¤¹ MÐÊ¸èœ z؃¾Fû´¿æ§Á¶2­hÆ?E;aE°ØÀÍùµ`²‚ÑÓµ-_øx§SóÎßb %Fp:Àð+0=Û~›ª¶T²Õn×Îk4ÂUßtÑÔÔDDÄ6ö$7󇯕0uêHl6qqšA ¡a4G60uêš›¯äÓOGó·¿•z¼É3=cØÌéÓ§ÉÏ7`0˜Ø¿ßä wj·½‹>l6MΤ¤À’%Ó<žèÆ6a¢32´ºª> Ê®òôªgGvvË[éphû¨ðÚÊ3~Ïž8fÎìëÞ-!„íåÊ“Þ?_µÓ wÝõS† ËÄÁ¹s/òío§cÿ­‰1á©|Xò415·²ƒ©¨ä³¸žÇ‰àr`ä~žš}œ1_â@ÔVÎ/ϹòqÌ~m<¯íN$qB"p'?ï¨|ŽñÚ‚ åáíñPŸ:u*S³§¶Ü7Û÷ùQáG¤“Þ×­+‚ ‚ ‚ÐoP>*F£æÐÓžÑÑ?]αÙ8wß}œºåîINfÚàÁÞ¹în£"Ž©y;G½çoµÍ‰æL ¢˜Yð½*g³g›úûB>'bìLjá1PaNA›ÀRFƒÒRM8Í™£ +òT9ÔùýQ Ú•Â_°Úy”\ò—m£FÁ`ŒÿˆÏÈÈðzå˜L& ƒ7OÆ-[¶xέóìÙRÒ˜L¦6çW! A3Ê ¯¡Sy)ÏL»ÝŽÙlÆétb³Ù¼^˜Z;[ g»¤¯~•Š?þ‘ä Z\Ó`  ÑŒ¶ë²7áŤÂó}©k`ÿþýÞz«:ùU…þƒòRS7e`œ3GsÍÈ€-ÿ¬ÀáHöÊn8Áý6æM½ wóq >Xˤ‰Ñ-\€Ùlæ'# ð±R`2CÅP ~ŽAš ÉÈÐc4jrHïQ@œF­,F»ÏóÎbçµÀµ÷{ ô1öUóØ£´v»Vf³Y3„ù†Í£´(c Ù ÖgÁEfŸ·¶Å¢µ22ÚlÚ•ÏÖdòd?þø<¿øáïùŠý+¬]û:ÍöíÛ4h*ï¼3’©Sw6”¤¤õØlšà\°`'O^Ã=÷ü_&NœËæÍ_ÁéÍ¡CÌf#¯¿~ o¼Nee,W_]Ë•ŠN§cñbÍj·ƒÙldéR­L&Ó`~øCK—‚Éd ;Û€ÅâóF/*ÒÚDµC^ž}ç°0í7µÍß©ZKý®"äúË™‚Ÿ‘RåÐëaÉ’ú¾îâ¡òþú%ZymÑÍfãêú«‰Ë‰Ãœfæ¿"ÿ‹éHñì›C E$r+;$œ°°i|–ãÇ_á£Ç?àŠð)l ÿ€7c̘ãüîvͨ…¾TWJ{ Øaã4#ç `6£c'¨|µà[•ªrÙªÕ ù@AA¡ÇQ‹¾Íæ–s4N§–jÌ`0PTÔy’A»ÝŽÃéÄ2oÆqãxîé§;ìÀE¬3Z"Á3áçù¯Ò,9<ðE5SéTt3»ßù„~‰û‹Å¶OyßdfúBŸ*´Šš j/ŠgG˜L~aùü0›ñóòò¼9«ªìÌ™cÅápxCü9N¶lÙâh6› «Õê ÇèGvv¶×Óѽ^ï5:¶Þ~!A©×ë½!DýÏ™““ÃàÆFNGG{ó£ ­©áÔË/3èwp¾ÿ>¿øÎwµe )))dff²$=ÝgÙp:µÿþ!Ç<.SÉ=|Ï•Q¤«µi'Õþ÷@yC }€Óóÿ" Ê¡¢õZ­`µ“¼¼éX_…^? ðÞò«¡6‚’±?'¡ùG̹^ ÅðØc1—k¿Ômâ‰ó`¼ŽïVchúˆìÅó°l“ ì6°ÅfbÛ¥y&fº@ÿX!3Qó2,ÛI-ì¨þ!°?)šl2`èP­¬*O©Ñ¨9I:¾¤Ø ÿM E3ÊY­Ú°ËÎÖê²t©Ïk;'GóîöG3mÚuª«5¯ÀŸÿ¼-[ª))Ìm·ÅðË_¾EEÅÕÌšõóçïfçÎDÌæ$22L¼ô¦‹O–±qãÕL˜°ššvï~Žþp: åý„iÓfñ¯!!á&Àø¤Ü%‰`+ÓöWŽÎšáJJ>£b‹.k“lã´êª0¡à3®åä´u±Ûíèõzl6+÷Ý7žßýn#G†QPð*§OOã‰'¾Mc£“ŒŒÛ4èn`*ÇÇqÛmpï½÷PYY@F†…3vqÍ5«¸ì²c,Xð„g¬ÌðŒ­%L˜ó¸ë.håìŒÁà[b4úB»ªE ™™¾¯*—®Ñè kªn·Å¢K–aýú$Æ6N:Ell*ô̬9‹íSØÞÉü”÷xÊ9˜òê~Î+ÔÇ-ƒwðφ9œrÇr-8:8qñŸó³‡£¡aƒÝÏbm\œÈÁäÆÂOÆóàï›=újoæü—öBU lu°$ÚÄ’3~z‘JÊ­*ÕÞê0ÿÕI~aß½¨­„­¿ÐUçÉýÓ© ƒAS6UÌnh{£„¾ÁIÛ—p=ZŽšl1·úMéy´ cÞ•kYÐŒ™´IÙhž±JŽ9=×µà3ræø•Q﹦ZÁœíÙ×NK9˜ßêºjÕ³¢+Þâjµ´ÑïXµÐK]O•Ë?×´ ‚ ‚ ôN§6÷oµjógjJÝf³a³Ù½f ùcÆp£ÛMØÿw˃—.õNÞlZ¸CyyyTWW_|A.†´Õ=…ŠÂÓ‰ ÕïÃc¢ætÔd®ñãÙe0`0())Ád4òöÛoSqÛmØNîúéO…j[-¼ê(?ë­¿ÿŽòšÜñ»ß1Ò$M|r¥hGÿIC5£þ à ð„›]¯¥œÀý9X÷0Ž<Žåü÷pžÑa©óÍ÷1( óœƒìÑä'†0åÄY¬ÕÕ¼âŠÅÄ/°5æó£1/óòe‹Ù¼åz2®ƒÌ¹&r6ÃU?„ÒÕhÞ6­œ&²/ó·<‡­«dg-˜¾K‹‰C½ ²BÁÛZý‡Z¹¥ŒgCÛENœ¼ü ÿÃD²î'"b7Nç8l6›ß‚ƒ~ñ‹J,–® ¨¨«Õê üå—3q¹ÆQ\|‚ ò½À¢¢édf–òöÛQüò—q|ÿûŸÿ3@ó6›ÍX­l6MÞ.^…Ífk7v¾ÓÙþü¿ª§Å¢Í׫}üëª ‡f³o›º„ÊÉ«¬[¯ðϽ˜™ÙÖ¾ÐÚˆé¿Ýn׎Q†IƒÁgVá[ß±j•ÿ¹¤¤F¾øB</ ÿÉó|4ºõ„{€PÞ²þÆ<åè¦B¯ƒÖ¯ ZÚ‘TŸPÞ·f³Ö'Ló€ã`;?Y¾Ÿ·ŽçÍí,Yr·;‘W_Ò¢ ?üázž|r YYÏP\|_‹ßo»¬’‘ ƒxfï0RôHºl=þ: åAHK3³ukúANî÷9[§°­qx‹óä&n¢°æf¢¨'–¯r&ì†FàdÓI≧š"îû1uîÉ죘µd¡CÇ»ú,q¦ãæçy ž#|%f?ÿhÔV qÿ›¥á\ëN ÌmᶤÞÞÿ2×G¾F‘À|L:ó`X4‰‘nÜ£ÇòÓæ|nJ¼çeù#0™Ä±m¿ò ôkø˜ÿ{ZÉ›Í7Øöwµêùù¾0­Bêlkg¡x”ÑbñYuý]¨o± ÉåŘJ÷éÃìÙ®žíݲ||Ïz… ŸΆÏhç~O~Rrð­~eS¿+¹f ¥Ñæw¼WqÁ'•á2_8j£_}ûÏïùøÂ/)2=¿åx>3Ûi§RÏ6e U†Jÿº<õÒûµ™ÿð7¼ªvnµðÁk\õÿ®ÂBZçßþ´su?Õ5[ßw«g{>šaÙ¾Å.*׬µëXÚÙ_¡Êkñ»¦Ÿ;¢n‚ ‚ ÂEàDÓÛœ@‰öž®ÞûRêäQPP€ÉdâwãÇ3ãºëZ®0÷pfÌÞž±ËÓ~ɯÿç{lŠÿËã–kº›^EðéÈJôו¾kÆ7©tÃÖ‹U˜TYÄ'ôbx 0j!ºŠ„åïáÒÚ½úbq8Þÿ6› §ÓÉè†*7oÖ{ò0Üsë­üuìX¾ý¯y½Êà¨<õz½fàk%ð"ž}—ÍÆÙ³g‰ŒŒD÷ÑG<¹d _}ê)@ yš{âWú)×?ÀÁ‰™°o¥¥¥,]º”?ff2±²’ºë®cxe%S.dj+·¨ÚO>Ù³-•ÑpÚF¼ú*“Zm7›Ííz_ú“ŸŸ˜d»ÂÀDÔŠû<´‡w&¾‰ÿXæ÷¦à<0ž¥ƒþŒiר]zôÀÞÆY[°¦cžù;=˜æƒm³¦L­>ϲÚX "àÓ¨«q$Çñá¤T¾ôß<ð«\LŸù¡oñßï‚>J`÷ ã·ñM®)lý× ;eù{õµ&óPðg(]Ûv¾Zí_RÿøÇo°XµØóF£»Ýν÷þœªƒ©©©â†fSRRÒ"ìÕWWÐÐÌ{ïÅRZZŠÑhláÁkµj†Æ={’Y°@3¶UW+Yª'.NSêZ§œ5 dgûÂgd %/¯ý ýöŒ¦þ×WH™™š\WžŽª ¼¡eÛi×-[´ð°í‰)eÔì(,¶òk}nu=ƒÁç)©®§Ž+-Õ®«Âxƒ/¿€jÞ1cÎðé§ ]@y%å¡{ÕßÔÄG‹‰<ÄÊÉYÿ&`ë€ÿ¤çÅäpV€Ýæ°_¶·µ{—’Rƒý=N˜3Œóçùű?óùÛ‹ˆmŒå_ö­4Ô cxT3U ƒI¨ÝÇŽ/÷ð^ÜA""&Q__OFÆZÀÈ-{ÇàÚÁDó ±ëÂxœ•šÑú$j©åsXÍs즉—†2ño·òÈåï3=¦ŠáŸNaêèŸ5%ŠÇfð|ÌóÜwò>bÄpw$¤¹Òø8eºA_0·v.›c7sdÔæ—?ÈñaŸ0±v"i´3Öø*·mq3úÖѼùÒ›üøú³ý­Cœtˆ{O°ï¾²žMÓùaêy²üI ˆúÈzî›uÃSÂ8ýÍXj^}•w~ýkžúÅ/¸ÿޝ±å×fþÚ8šÈ¸H†Tîæ¾ÛÇóå„Ë©NœÈá¾MÊé÷ycd81åå0-{~¤Ÿ]ζ_2ÆOQûG››i¢Ó%™þ :Úõb=w‰„Ð÷(O?ðÅrð-ZrÐ6?JW1 ­JÎèàwe84z®§Œdz¿ãUmïúþ2ÍÔÎwÿE×í)jbCý–ßÎ>[ö U†*&:&2"s‹…ÕK–Pò÷lÒÒÒØüÙg [½šW,¯p[êmÚ±Ùï|ŒË0‰ŒkØ4éZoGüßà*[861ÎáÐÞ•Šj!;›'yR‹¾ÄÙí¼¨÷y\~õOàgOþ ¬V.?qŒã´A‘:Ÿ˜»'1Ü38æ_1æ|ßãÞél+/Å0d ŠwµÒقϋ̆&/ôh‹Lž¿ÙÕ:rí̘م2¨ÊFcËñþá“j¡ŒÕêYPåyþý<Õqv»/ĸÍÖr! »¬×ûÞ«üŸsÙÙ¾hj€Š.¬¢ ˜Lš¶åh¯FK—¶ŒlŸ¯åDFÝ*»'±Ç™X…RÏñxXnÉÔ wv;Pì;‡Zhš Æá`mÛzmã$Eí&cÍ<í6}ìÁòÑ9œE`J«&ÿ¾}Xl®ádç.ÈÛ ú¸fŒ×Á•. ëç#1¤Æbºìo‚!õŽò¨Ó‚ uWâœ|܃ÓdÛ¶Am-ú„“è§îè¿ fÍÂàY oœ ú6àÜ>ý{ÑW%‘c71v<ÀîÙÛ…,z%ƒÔ8V«g¹ÿo*¹ÒÙÕB=¥ ûË«ÕIÂ?Ì»ÿÂ?u>•±ÅÂéÔΧR,(9¨d—¿®äžš…œíïÒRßwu¬Zø¨Ê¡×·Ì÷®Îkµj¿«÷¹½e‹o›z÷±Z[o2©hi<þø}}Ë»…ÈAzE<ä€TܥDz×HÞý`þŠ6ÇÓøû‡Ø¿ä_ÜrìÃgÍâ©—Þ$Ѩ½/xnÛ¶Y›fÑÞȾÇö1sæLš¿ÖLÔ£ˆ"J»F‡Þ~ßýçƒÚ[ìוEŽù]ØG.2<*Á¡Faa!+W®ä¥—^ê•ë;¾—]õ¿´TûTÊíþýø4UmØ{'Ö®E·w/Õ[¶0´¦†7† Ãê êt:ÉÇgר7~<ñññ ËÏÇà ? pâ±ÇøB¯gø]wa·Û1 XòòÈÏÏ÷–:<~à 4mØ@Ôµ×2Çb4o °‚*++Ù»w/ÿ>r„7>ù„¯zŸjÞB>é´ä‰'¼ßg-\ضqZMØéõz1ø =B@倖Õ7AØ^˜-+ÚJ|5ÉæñRs8|“Uæ;Ï`;ƒ#Jÿ©óN¨:´ ëG›p~ÕÉ©]ƒîôüæ7“¼¡D³²nÂd2ùï«Û-j GáRÚ( ­‡*§«Á`à7Âq8ÆóÉ'ÏàpÜ %²ÎÏgΜ9”––’——‡ÉdòæVT‹ v»[n9Å[oÕIF ™™™Æ.%·V!Yõ¬Äh/ÌèÅüž%Éhôå7ìè÷ ­_hmÔk}žÎ˜´=ã¢ðŸxP¨IZ“éÂNM™™>ÃiffË Ð<ÇŽ=vé…ëc& þ`…ýNøv¶/4Éœð„† Ê  Ë,À3Yã´ƒ~ñ÷É)ý Ž]Í8æh!k_û‰›ÒyÕü9£Gxnã|õt%‰E¬­Y‹u—‰0ìÜ;l ñŸ_Ç-ºw¨ÓÕñé’#Ü6:–Ý_¾Ê¨ÚQ|ëão±ïü>®˜e»Ê0ÿÖL^^ž÷Ùz¤æ]ÆnÿñŸNT”ŽÄýÑ=ý4a÷‡Q]]Í®¥»¨š·Œ£¯¼Bò¨dÎ7ã;éKIûJ É ôQ£˜^VF^ÖM$½ú#ªqRŸXJ‰[séœÏ|_‚ ƒ‰!knf‹ŽW¤×Ãí·s@q1ižŽæ´—_Z‰ýF¾àéЭ-îÊ€ÛÎ@7 ¾2¨Ñ:?¢Še߃6ëÖ‘{²²Lø‡¤ôÏèÿ]ahõÝ–s4/>!A…:….½Ì·—ÛTMN«ÉbµB¡<çUøm¥›øŸC¯÷ ±ÒRmAŽšˆ-z¯ŠØ¢ò´ ZZê3æçkçðŸÐWáÆý_}T¾a‡ £(*¨¡àùÑÞrqú4†ðã0 ¨©Áp¤SÖ•Øíš'¾^ƈmPQ ž‚Ô|ˆ­ú'èõPS³‡#ø­¯óËi;34 géQêNŒgذÅ<ýôqêëxäI6°m—¶úJÿŸ/ñç¼ï3æÆD@k׵Þaä;ïÐÇ^›£ÍŽÃl¦ª* «õˆÁÀ^àé* y®¾újŒf-9´ÃYÃRª,“{ûamV'$PP 5öK&FÕ3vëqêWFqKJ ¯^wV«öûüù£ùåg›Ñ¬ƒÚ©FÉz’¼áµ§9Žãò<»_Ñœ^Ÿ99‘¥Ïïõ.Ë÷t½ØØXì›3›ZÞWo´ð|]ý3€[.fä }=OÐ×\hq€Ãá‹¢"}û‡qWÛ[‡qWœjÌ«EqEE>™¤®—Ÿï‹¢Ëêoµ°@ÁM˜3§eyÍfß;–ʉÞZ&•”øÎQRâËÃÞÞ9Ô{„’aê= |FBð]CéÙjáž*[ll%ï½—Hss3&TSW7‚ÝIIUTVîgÆyÜvÛ9ÎÚÆ±Ãwò žL£^ÏèÑ lÝÚ€mc23ôÆ—yä2íIDATo½4ŠIÇÿÂȘ;ÈÈidóæ† KbÂÍT|Ϩ‘#9÷ñAªw71vl8³fE9™»ï®àØöHRt{2è—ý³œ[ÃÆ±?úþò—7hnžÇìÑŸó­iš¾UùÝÝ̬¾÷åg©©‰bðàX²²bI:vŒ„ýû‰úìƒw×òÔXØxe2'O†®‘n Ë¡ë8Îç':Úð:„(Ôü‰šÏí*jÎÅáHN§Ó;Ó5¯Ó•òÚZ+”—ÈÉ“'rž¾ Gä€íÀ¬Êƒ>ž†† 'Nœ ))‰ÆÆFÜn7UUUÔ××3gζoßÎÌ™3Ù½{7S§NeûöíŒ7Žšš©©©!11‘C‡1sæLï1äî»ïæé§ŸfúôéÄÅÅ1z´Ög*++=z4[·neÉ’%Þ±þä“Orß}÷ñÌ3ÏpÝu×Q__€Ëå",,ŒÑ£GóÎ;ïx÷Yµj¿þõ¯ÉÏÏ'77×{Ìž={xçwº9*û†K•^]èü,xõžî0AšÉ÷^6Åy­^Ìò³aƒçÙgþl}ì§’pžÕÆœño÷a/ÐBêË·ÞnYî[âaR–u`™_?BÞà -ö1¯BƵ>`Îû;G°U&y7DWS´v(÷jWo…¡i`r}¤v®Ì›qDMÃö¶&Onš¿ŸW_höžcVÌaî»oø÷2nùêìx³‘Ê*_ØÍq1uDÝÇé×GÙ\ÇÉ+^£fýHÂχ“~ŠË#Ž=¹ž±³Ñ‡;¡šÚøÝ4~<’+£PëÂŒ¨¼n¨"Éõ ‘S·þÑq×Ô’A)MáCˆ;{œ‡Óf±äˆ–cz}Òzߺ €Z·ŽCî±Ô¬áÃá3I¬ºwÜ~FŸ{žÔ#zÆ…i ÛÙæ³¥N`hSu“øâ²wÈú”9aZ‚­C·’Væý½²²Ò»Ð뺱ױõÀV*c+™\7™Ïã?§>ª^‹ÒäpbôL\:p ÷üóÇŽÝ» ¦VaÔqj_ƒçŸÂ‰³Åv‡§s´ÞÇ£Åu¾÷5êëëqxþ}mÁ×Ý0šø³ñì>¶›w¼ëÝÿܬsÌ Ÿë­[Zu•±•mÚ­.²Ž½º½Œ.ÍÎè ›8Ìû»Ú_}ÖEÖQ[Iš;wO¿Ëìó³™4i'|ÌÜÚ¹Þ€g=ˉ'Eºý~°nöGþP·d™¾¼â9°8¥b*–M:¾ó*Fz’‚‚þrí_ȈL!þë—Sµ¸‘SÏbïG{ÑåêXš±”7Þxƒ7½ˆÙl¾(Ã÷Åp±ï‚ÁHë¹­P¤?ÌEbÎ0d<ËËËÛܰäädRSSÙ¹sç…Ç‘#G8_t„‚oüÓÙ QÕØc219MXwß×rÈ}üÅ6žgæsàܾոѧÿNDØ|uˆƒ¿À§aoÙÉÙsg9þ<ÿu5'ÐŒŠv›Ó£cžärÝYŽ5aÚ´i”±š7­àµ×^ciÎR>Ü4ŽQž—÷ªª*ÆLÃëŸý/×ͺŽ}îclòõ[ÁL4Å a\ ï\Hü‡ñŒ›5ަZÅ[¶¤qäÈ4âã?œœ;÷"§Oÿ€Q£¢Ù¼9…ææ3T͚ȯ¦gnÌXfÏžÍfãnç ¬ÇŽq˪U<úè£ä¥§s°´”ï~÷»”——“´~=3^¨)S8Ÿ@âUW‘õ§?ñO·lÙ¢ô¾÷=o¹‡êõdúw(£¾ýí 7”Ÿgâjÿ—(…Ápa—ahßòÝÁ5:¤¼ +**¼ãb ¡ä_§»:“íØRÝ0]Ë"¾~O2i•›YŸ•ÄÞ½:îÛ»¿}€NµMC æ5ï¢éØ&¶q3‰ÕÕܵýϼ_‘g"¹¨3gøÅ/þ±s Ù»÷••[™Û´›4˜Á¹-wºÙ¼“i(ÕÕÕ<üðy~7è3ššš¼E«¯¸ŒœœãÞ¿íV¿HI_j÷úÔÇâbMíûº:>*ŠS#Gòß«#™8q"ûöí#))‰Ìv‡ á”'‡û–ƒCxûð[$''óöÛÜrÍ5T6”c0™xë­·˜9s&{óMFM›Fmm- ¬›2…çjj2dÌœ9“}ŸÎÚµk1›ÍÜwß}ÄðK–,aïÞ½Lš4‰£GrüØ1¯œ,(( ÃlöêAO?ý4öûï'++‹°páBžX•©©<ÿüó”””@Fû÷ï'%%Å{lII‰7ô»ÁéÄäYXeµZ)ñì“YRÂo22(--åwžÏ‚‚oˆxÀ›Ž"33“O= ¼¾ùÍo’Íßÿþwï‚/µŸÿ1?ü0yyy¬X±¢Í§ÿ1þ*d½ú4›Í0þ|Ž=ê]æƒÁ@uu5óçϧ¼¼œ{òòrn¾ùf\.—÷˜††>ûì3ï¸èèhn¾ùf:Ä•W^ÉÂ… 7nK—.õF½8|ø0¡H@d9»îfœîxHŒÃðN,›öîåÓÍ—1jÌifÏÛÍ›{oà`ópjÎ à?_vð§F³ÓÍ¢·s¨|Ôµ|&f=ø8ûvÜÇÙ³g¹æü¿øôËy„……1=r?a„±qÓföm*ã|Í ì>~gŽþ•¥¼FðððpþòôNòF<Àùsç©Ýþ&?jÚÅ×#§r¶œÝLfn£»ï­ ß#!æ¤YxŸdð õþÏ—êØÊP21á¨r°~×òýÝ·OÁ÷ ü2ÆHDDo¼ð·~ùã›4·ÛÍ™¨3dÿe«O¯æÔ©S¬a#ÏÖ¦"ö2.?ý%aaa¼¹s8Ñ1õÜt&‘íÇwsÅV¾}æ4ç'¼.œˆ!üþӸć8}ú4ï‡;™sªœqgÏ>•ȳçi<š‡0 2°çøf¥Ï¢asCõC9Ù0•Ù±ü»&:n=7{íQb¾v/‘EuœššÈ»¿`JÒÞÛ^ȺIwPU[ʉ|UO\Ì×8Mcc#g§Å£·ÿž{S良¼œçŸž­÷V’””Ä×(tÃÆQû¿Üâž@ê™T6ØÄ˜¯}Û_IKKcëÖ­Ì›7Ï>º'ÓV°k×.&]7‰O÷4å7ÉrbÜ f7<ÏŠ±+غu+¯¼÷[‡meâĉ|ôÑGLœ8‘³)[¹ #`_Â>꯾’õÖ‡¸6éZ¶îÛGZZg\÷s+·²íÐ6Rf§P3üf.?~%§ˆ™RÏìs/r›ë6öíÛÇM¼‰£N¢OGÓÔÔÄØ©Ó¨ª.âúas‰;ÇdÃdêF\EÌ©dbÇÄÒpü8Ãtã8} ‹ØØØ¾Ö—DweÁø§öÁüùØ1âôLb%ÞóMjþòœ»a/º÷醃ÞcÜÄñöW¾Âõïý€m·>‹î?Âá7¾®Hh¢Bu¯¢iÈnÄ~ŸÝ'æz¯aÀAõè:¾øÒÂäó‘ìQÊ„ã;¨rGø—Ž÷XÏD~Ã(Fñ9K™Üj2/‰ã8¸h–ÐÈ. <Ì‘V^ì[FîgÎ1mBé¼þ5.«ý€ç£ýês9{†×Òpâg„'/g_E˼ŸãªÙ¿=N#CãÖ˜§x£2DC©¢‘ʉаOK‘0éò÷‰­,åD³ï:ƒ¸÷ˆ:ÎVÿ’¨sQÜçÓ|h«óþ>†¡\s®šæ°,¶lNc숸1î Î8@õØ0‘®ZÀâ¿ ¸}æn&ìúï6öžç†È¼sõ"®ïÇy”ßÿü]žûÞAŒs$ÀêG9>t {fÓ<á8ãŠø÷¶S±ãÀ€__ò0µë5ÝúÆ”-,8ZÄ©†ƒÞß' DõÂ1 [Ÿ…x´ðŸ¼œû9™ž½“©wßϹ/Æqý„ãüaÖãìÙ¶ Û¶›1bçÌÌ™Änÿ¹vÜMGþîÏ8Õ°Õ[Ÿæ˜¼›v7”=¬ÝsËFŽd¿‰“8ìh‘µn›t„p÷ÝœÚ7’†ä£$%þ‹’CIc2F>Ǿ5ž˜™£IØ~û€ùsö³ë ªN…aD3j6ÅcÄ1£½A tço·Q°ê–†yãAþGFá•Wˆ[¿‡/g÷îyh“³þügmaÿªU«ØÙ´“ì„ °fX)))aÓ±MäóÙ_½½^Ϭ…³z´ úû`ë¹­Pd ÎE´&d<ËÊÊX¾|9{öìi±}ùòåm'Óüøæ7¿IÃËsøâÌuØ™ë÷Ë|ëd =QQõ ´ƒ³g¿$..Žúúzt: Œ5Šªª*’““9{ö,:Žææfâââ¼û6Œƒ2yòd>ÿüs&OžL]]ÇçĉÄÇÇOopèÐ!Æ×{7)8vìC† !..®¯‹Ò«tõ^;vŒ'NÍ»ï¾Ûמhº#fÏžnûj>tϦ‘ñž­64wÛLÀΨQ¦ª*‰ÄÄjjj¶2bÄHHH &&†óçÏKMM7¤ÆM7ÝÄk¯½†ÑhäàÁƒŒ=šúúzâââˆ÷L$êil¬òÊ‚1cÆpôèQ†ΠAƒz¬Íú˜hjÂ[oÝÏM7=Þ×E (uu#ˆÿ²Å¶Ö÷úBu///çܹsÜ|óÍ!¹¢¹»:ÁîÒ/qŸü)ÛoYqODÄ6""^":ú4n÷~FŒAUU3gÎÄáppÕUWa·Û¹æšk¨¬¬lñü4h×+¦'Çõ¥0u‚úúzN:ÅÈ‘#ûº(½JWïu}}=‡¢©©‰¿ýío¤¦¦öuÑ/ŠîêK–,Áf3ÑÔô-Ýrð™ø,€ØØXΞ=Kt´¦;577åû'Ožô>×'L˜À4ïðÊ‚¦¦& Dmm-ƒ#GŽxõˆI“&±wï^FŽICCƒwÒW}÷×9¦L™Âž={ÚÕ9Ô}‹‹£²²Òû>¢ŽUwõ¥§=z”Aƒݦ>þï9þºzïQû8q‚ÈÈHÛSWWG||þsêêþIlìW8{ö,QQ„‡lW6̘1ƒ;v´ ÄÅÅÑB6¨ù†ôôôeCCƒæÅxöìYNŸ>íÝçæ›oÆf³1}útvïÞÍøñã½c  ±±‘èèh¯Q»3Ù ¼°Åu"¾Œ§öô4Â#"´¾çv£»œ½{÷öõ°îU9píµ×õ^ûÇ0 ØF>we#`eìØÝ|ñÅ;^]|Ê”)ÔÕÕy#TDGG·xîô6¡ú¼ò'TõoB}.âСCÔÖÖv['Çîð /pàÀjjj˜=Ûÿ—-~ß»‘„K„à“O>áí·ßfÁ‚ñ~[MøÆ¿ ¬ÞÿÈ˃üüuÝ?Q2ëÞ/¼ðB;94ôøtšágAè:- ,*t€RÑ ¡?“ššÊ6lj•[ÄŸö¼ûŸíëâ ‚ {ì1ÚΫú¿ÜØÁÑÍ+^ç÷ýZàíìóºß÷ù­~»ÆóiïàœŠy]¨i™çsæöÙЪ¼b6Ð^ÿøñ··s ­Ž»ºƒs·÷ÝŸý¾ÏíÂ>¸ÎU½t«/qÿ~ÐÑýéÊuBÏèÞ}÷]þú׿¢Óà«_}ª=Äv À0<L˜0¡¯‹ B°`Á‚¾.‚Ð˘ð¼ñ@®û…Ðëõ=–SAAAA„ÐãÛ¥3¡Ë„÷u.–òòò6ÛB-4” ÝCä€p1 dûR¯»ÈAD‚" AÐY ‚ÈABÆð¨’qîܹ³Åö²²²N6*B×9 ˆ,Aä€ " A‘‚ ˆ„`#d YYYãr¹X»v-:ŽÅ‹÷uÑAè%D‚" A9 ‚†ÈA@d "!˜s»Ýî¾.DWq¹\,[¶ —Ë…N§£¢¢‚ÜÜ\²²²úºh‚ ô"A‘‚ ˆACd  ²@‘‚L„”áQQVVÀôéÓÑét}]Aú‘‚ €ÈAD‚ !²@Y ‚ÈABÒð(‚ ‚ ‚ ‚ ‚ ‚ BpR9AAAAAAANÄð(‚ ‚ ‚ ‚ ‚ ‚ B·ã ‚ ‚ ‚ ‚ ‚ ‚ ÝF ‚ ‚ ‚ ‚ ‚ ‚ ‚ t›~mx,,,dîܹL™2…•+WRQQÑ×Eê7ndùòåmþ———_t½C¡mî¼óNÊÊÊÚý-u Ö6è¨Þ]¹ÿýåÞšþVç@É‚Pi—îÈ‚PíÕ{ =Mªó@ì É‚@Õ1ÛAt‚þ‡ËåbåÊ•L™2…)S¦pçw¶·¼ºîÆ1™LL™2“ÉÄÆƒ¾Ü.—‹Õ«W·8gOÉÊ@”½£qߺíµ ÚWdCÏ(YÐ÷³39ŒåîŠT¹UîîÈ‚`’iÂ…éŠ,ÖûÙ:A Ëj:´/ ¥te‘}OoÊýÞªÏܹsÛôëP¨Coé@ýw?åñÇwÏ™3Çýâ‹/º7oÞì¾ãŽ;ÜwÜqG_«ÛuºñÆÝ?þx‹ÿ‡¾¨z‡BÛX,÷äɓݛ7on·º[Ç`mƒÎê}¡ûß_î} éu„,•véŽ,å1ÑQ½Òs Ðô·:´¾p¡1ˆ:c;ˆNÐ?Qí¼yóf÷æÍ›Ý>ø {Μ9îÚÚZï>ÁªënذÁ=yòd·ÅbqoÞ¼Ù½jÕ*÷äÉ“Úïz¢Üê6lð¶ù7ÞÐöTÙ/4î—-[æž3gŽ·?þ¸{òäÉî 6´}E6ô}q?;“ÁZîÎä@ Ê¨rwG“L:§3Y¬÷³7t‚ž(w(énwDz :AWö9ô–ÜïÍú´îסP‡ÞÒúýÖð¨&c‡n#„CU«V¹W­ZÕízsÛ¼øâ‹îÉ“'{ÿ·§h¢ŽÁÖ]©wg÷?Ôï}OÑëYìíYŠc¢³z„ç@OÑßêÛ÷÷Ž;îhqN·Ûí~ðÁÝ/¾øbЖ{óæÍm&jkk½/ü*wwËÞÙ¸o¯Ÿ¨{òàƒ´}E6ô<’}q?;“ÁXî®È@•«»å„,™&t®È‚`½Ÿ½¡ºÜ¡¢¸Ý–Ò º²È¾§7å~o`±XÜwÜqG›~ uè-¨?Ñ/C­–——SQQAzzºw[rr2©©©ìܹ³¯‹wÉTTT ÓéºUï`o›ôôtÖ­[Ǻuëz¬ŽÁØÕ.|ÿûýï úk»+ B¡]º+ BuLtVïðè úcJ_¸Ð˜Tƒ­D'è¿èt:V¬XAjjj‡û«®[QQAyyy‹s¬Y³†¬¬¬ -· ᔜœÜâ>LŸ>Ý[§`#]yþ§§§·é;Ó§OÇår¬}E6ô}q?;“ÁZîÎä@W¯Ù2¬»² XdšÐ5:“Áz?{C'è‰r‡ŠN–Ð º²Èà ·ä~oP^^ŽÅbáÑGm³=ØëÐ[:P#²¯ ÐÔÖÖ´é íÆñvîÜImm-S¦L´dnn®·ƒw¥ÞÁÞ6ÉÉÉ-”€Ö¢Žj{0µAgõ† ßÿþpï{‚þZçîÊ‚`­é®,èJƒ±tVïðè úcJ_¸Ð˜Tƒ­D'è¿$''“›› h/¦µµµ“ššê½ÁªëªÉùäädV¯^MEEÉÉÉdee‘šš´åž>}º·üþãJÕ'PúBwÇTgã>55µÍä£ËåbÆ ÕÿD6ô}q?;“ÁZîÎä@W¯Ù2¬»² ¿êFý•Îdšˆ¶ûÙ:AO”;TtÕ¶É‚@è]Ù'æ½%÷{—ËŪU«ÈÎÎncD …:ô–Ôßè—ý—ËErr26› ›ÍFVV«W¯n7á¸Ðÿû/(¤/ \äÞ é ¹ÿ¡Oaa!Ë—/gãÆ,^¼ø‚ÌÁÄwÞ‰N§#55•ŠŠ –-[Ô/Êéééèt:ïAEE…÷{(³qãFî¼óN’““ÉÎÎîëâÝ eÈàAdAÿAdAÏÓ_eÈE¨Þo‹ÅBBB+V¬èë¢t‹P“{}M¿ôxì¯ìÙ³§Åß¹¹¹”••Q\\ÜÆZ.ô?.tÿÕª&a` ²`à"÷^PH_؈Nú¨•Ëeee,_¾N÷.;;»Å„Éd¢¸¸˜E‹õuÑÚE§ÓñÜsϱråJL&‹-º`ˆË`FM’–••±bÅ ²³³CbrZè˜P”ÉGy¤¯‹Ö.ýM€È‚þH{² ³}è}‹ÈE(ßoõžúÒK/õuQºM¨é@}M¿öxlÏ⪔ŽHOO÷Æð¾˜z‡zÛ¢Ž¡ÞÐöþ„{) „:_Š,èíˆ:†z; ÔçÀ¥Ðßëop!Y r@.P• ¡®ß‚ ô$‘}]¡°víZxôÑGÑétÞí+W®¤¼¼œÔÔÔ¾.¢ ¦¸¸˜¬¬,rss½Û\.………¸\®²@„Ч¼¼œÂÂBÊÊÊHOOow¿ââbRSSyä‘G¼û©‰:y!ÂÀ!Tu‘{‚XBuÞ +²@ä€ \:¡*BU¿Aè Ä㱟PXXHqqq ÿ•+Wzxj[O…*(..fÑ¢E-ª‹-bÏž=-:áB+†U]Ö®]ë SrçwR^^ÞãíØ•ò B°ÒÛc§=EZý][[ \ܘï+ùÕ‘B(Ó“ýW§Ó‘ššÊŠ+HNNîp¿7¶™[´h.—Ë;aו²ƒlèKD—:º:Æz£wEg¸TBIî Â¥Ò•ñ zwWç .–žÖß»" DÁBëñ0ÐdCÑo¡¯èky vþƒû j^EEkÖ¬!77—7rã7¶ØVVVðPjà§§§SQQÁÚµkY»v-mö­­­¥¬¬¬ÝßüÏW\\LYY<òkÖ¬`Ù²e=ކ˖-#99™¬¬¬½– ô½=vV¬Xá½háQÔJ_õBÞÕ1ßWò«½²ˆB•žî¿ÉÉÉäææ’››Ûá¤[GžjYЙ|ÙÐW:‰ øs©c¡+c¬·úwWt†Km›P’{‚p©te¼»Þ}1ó{ÞžÖß;“"„`¡½ñ0ÐdCÐo¡/éë÷p± ô$Ôj?"99Ù;ÓÓÓÙ°a.—«Å¶Î”KA­âÙ¸q#ÅÅÅ$''S[[Kaa!<òH‹ÁšžžÎž={:=§Ëåâ¹çžkb¡¬¬¬ÃGÝA —Å‹{C£B(Ò›c'77×»H‘œœÌK/½äý»«c¾¯ä—?"„P&Øûo{o]‘Á z['„ö¸”±Ð•1Ö[ý»+:ÃÅŠrOºCgã5Øõî‹™7è*"ÁGGãa ʆPÖo!èë÷p± ôÄðØh=ðHHHèòñeee-–íq!eeÆ ¼ôÒKÞ0«W¯ö&W¿Ø•>ééé-„Ë…â¢w·ÜåååX,\.—ä^BžÞ;*ÏÉŠ+HOO÷Ž%õ‚p±åö§·å—È!”¹˜þÛݱÒÛtW6¢Î#W¡§ÄXèè¼½¡7Rg€þ-÷¡#õ<êk½;Pó"ÁG Þgû‹lPu EýF‚…¾–bèˆáQð2}útÖ­[wÉÇggg·ˆ½ž››Kqqñ%%S¿˜—¨î–»°°+V°víZ,‹!¤é­±S^^ÎÚµkÉÍÍeÅŠ€¦¤¦¦²|ùrRSS{54Èa s1ý·»c¥»ÂPr±t·Îbhú3½¡7ô„Î rOˆËó(Xæ D‚`xŸ Ù¡«ßB¡7ßÁe>0xãàE§Ó]’»²R¢['|î­£K-·Â_IX»v­7L ôwº3vT8”Öã^¯·Ã ‰2Ó»;V:cúôé@[ òž´–½AO×Y —:–zBg¹'}G°ÌˆÁð>,²¡·Êls"‚Lôæ;¸Ì/bx¼\ªkrjj*:®MœeõíéÕ}Ýu©VJBvv67n¤°°Pâ± ‚@„r¹\ü;Tê"r@e.¦ÿöt¨1NGrr2ååå-¶«¿ÕÄ\o"áÕ!0tw,Rg¹'}G°ÌˆÁð>,²¡·Ê­–9A&zó\æƒ1< ^ºãšœ••Eqq±wU€ËåbåÊ•ètº¡ÊËË),,dÑ¢E 9¨°):ŽGy„åË—SXX(®ÕB¿§;cGåY°X,¤¦¦’œœŒËåbÕªU-Æ}OŒù@×Å‘B(Ó•þۡƲ²²(,,$++‹ÔÔT***°X,deeµX¹jòAB@±KK]ÕŠ‹‹Ù¸q#¹¹¹]ò 5¹'=I(Z‡,zºÜ]Õoa J¡Vý‘ùÀÀæv»Ý}]¡ÿP^^îUh¦OŸÞîʾ²²2ÊÊÊD„~BYY™÷ź½q/c^&þ:AG/"¡g ¶1Ö™ÎPXX²¹Uº"÷¡' ¶1ß]™7UY r@FD6ô,]ÑoAâñ(”ÔÔÔ ®¢r¹\”••ÉŠAèG\Hé—1/Ñ ¡o Æ1ÖÙDaEEåååA?1ÚÉ=AèI‚qÌwDgc%”eÈ!ØÙÐó›!T!ïë‹ÚÚZ’““%Ö¹ dÌ ‚Ð"¡g Å1VQQÁ#<Ò×Å„$Ç|Gˆ,„À!²AAè $Ôª ‚ ‚ ‚ ‚ ‚ ‚ ÝF<AAAAAAAè6bxAAAAAA¡ÛˆáQAAAAAA„n#†GAAAAAAAºAAAAAAAè6bxAAAAAA¡ÛˆáQAAAAAA„n#†GAAAAAAAºÍÿ_jÜ—ìM]%tEXtdate:create2020-10-09T19:33:38+00:00a¯,r%tEXtdate:modify2020-10-09T19:33:38+00:00ò”Î!tEXtpdf:HiResBoundingBox1728x900+0+0×ì&ŒtEXtpdf:VersionPDF-1.7½8;í(tEXtxmp:CreateDate2020-10-09T14:32:30-05:00Ò°/6tEXtxmp:CreatorToolGL2PS 1.3.9, (C) 1999-2015 C. GeuzaineÛ©AJ(tEXtxmp:ModifyDate2020-10-09T14:32:30-05:00fîŒIEND®B`‚blis-0.9.0/docs/graphs/sup/dgemm_rrr_zen_nt1.pdf000066400000000000000000005256431422157504600216300ustar00rootroot00000000000000%PDF-1.7 %Çì¢ 5 0 obj <> stream xœÜ½I.;’ž¹¿¿"–7í#é¾ Z7w‚ …ª:©R(U/úï7öÆ8çŽH ¡²2ÏgÁÙI'·ÿócûÜ?¶ø?üïýÛÿÇìý~Ø?âÿþå¯?üy?÷íãÏÇ»}ìÏÕ·÷8·ùÇþï_úÓ¾½Ççù~´gÛ>Ÿöñ·Žû9>ß[’’äÙ·müü¥LHÂÊqü¿?Œ¶_ï»ßþã?þÛö«ÝŸÛYÊ´d¿?{4ä'ÉfÁNòlÏ=Ff¦xÎþÙz-G’Rd,‡?]ÎqìÛç¹×>Jâr(C9úér¢Ï{´oÿ1ÚÿC5(þç¿þíã_ýe<Úçc?>þ2F:ÿø±Ÿís‹±hûçÛ¿üí‡ÿôãñ§?ýó<Ïöã¶üs?ÇÓhýÇë—\?¶ŸKpôø÷õŸÿòï~ø×ùáÿúÎß÷m$)³ä§ofNL‹ö|n×’ŠEõ­ïŸ÷î¢(¨E9‹ª©TÔyŸ{/EA°¥D*ª¤RQm?>Ÿ£ÁR”©¨’JE=Ïùy=¥(–¢”HE•T¿uz¼íó8û˜š},‡1Îsz¬qûwk÷È÷ã÷òÇ?÷ükË?î?7PÈhÝ×t÷÷Ò¡¸¯ótZÿécoÑ‹ÿ<þÿ~8>þÝoz'ý´¾c¾yýô½)»¾•¾?a¿”ò OàüœÏ ÆÿÏñ Æc›¡ïÏç}ùþퟎíó:Žþã¿ùÓõùžÏùãÿù§ãþloï?þ{ýñ?Œ5y}>ûÓ~üéO~·Ï»·CC”Uÿž×Řç~n¼Ÿï˜á³)ÿàÇðWÿóÿt·ÿö§?oóçý.ÿþ/N÷?"Ýü¯"ü—’öçþ]’×¢Û—¢ÿÙ¿ÿû?o–äüØb~|ü7 IìÛû~>ñŠ9ÏÏóâj;ƃGï¯xSìûÜo“íùÜŸ)9ŽñøúÞ‡àNÁûÙF’ãÉcCòOyË ×õy·!yžÏó˜’ûøÜFšûjŸ=Óܣ‘¦£ºsJZ`HÞ™;$ýú<ûGïǘ.Yó³Ç«£÷èr–ó¼ŸÇ3$Û›ï§}+|”Ø{ÛÆº ɱ]Ñ•!ÙÇ~2%ûþÙâ-3ö Þ±Y Á˜ÝûìÕq´15‡ä|¢é!£öFš˜´³[ǵ^ñbº[¬„)y>#ÉèoË$ãOg$é'úy´ós4æiœc¼¥HòŽnBò|Æêˆç´g¦§}îmÉ5R·=%s™ïç¶G‡ÇK17Ô!˜ ‚‘ä’±¿cDÇAâóÍLcl¯‰±ÞÛÑó ü‰4sjLɨt¤yÇRéYòuÇsìïH»Íž÷hü®wL–kÅ9Æ¿±x¯ÎÚGS÷Òñ„Ÿ9ìçx ·¥àñfØî¥òXá‘d<çüÝçfðîíóš)®í޹;ª~ð®Øa¢Ü1¹¶9)®c6FƒÇ<)éq2)]¸ÆßŽH3¦ïlÌuÅÑ ’œ¹aí×=¦Ç‘IÚ•’þyÇH{ÌÕÒ9käꬼ±K4œýW/›3›se9OŸá{Ž}6»•£4êº!¹ÇS;&çÒ=f},V·çÞ{,ÖñöÄb½Ç´™ä‰G’¨"’Œ¼¼s½¾cÖÎÃÚ~g¶Í!½cÚ…ä¾æzu¯î±šb½>ïkiJÞ¹^ߨ"¦ ·¹\£ãG6ï¹>žÏ*ï>WkI2^RûS»Ð¶6Wk<ª{ÖÝÆKj{ëãlcüc¹züZL‡9ÿö¬ªƒá5gÎXŠ™ä:cµzζ{Ÿ«õ&kºŸÏùèÎÏ{v²×Ô1“<1BK{VÇJÇÞ¹Z=ÿÚX‚m¯³­×ÔÖê¤èÛ9—«'E¯§ðÈ4£Ö Ï·Í>ôñˆæråéñr?³Wo&¹¶\­jÎx5çjÕhõûÎÕÊÓÇkj¿–ºûöÙê“êã55ë¹ã¥9^|s±ºØ7nîS¼a¯ù޺јg›ãVÞmA sµªÁÏqäjÕ?c$¤i{J:–+Çø‰¥s,iÆÏåÊwÅÓ6,Wvâi=—k”—’~a¹Ž )k,×1êY×óærifן·cµr¿[n­±ªf¯â½wÔy±-)Žþ¹L›(~®Uuà½roUÅïõb©ò5ñÞ¹µºýoË­Õ½~{n­.f¼£æRÕŠŸÜYcE½óa¾ï…µŠ~lÛŽµŠ•9$oœ ܇cÛÖ*¦Ö±¹µÆ[ôݧäÌ­UnHæÖ:v³Ä\¹µŽ½5ž{HîÜZ¹ß[ÃÖŠ-q¬Õàcë K5çý±=¹¯¾cÇx²¹ïŽ•jIn¬nî¾acG£¹+Æ™+Õil¬|— 6Vurì£XªhÎØ•b‚ùa㥟+µHr_u¦–Û*Ë1^ ¹RÕ…±êæJå4ì«\ÞãH„}u<Š6ÓŒç„}¯B|É5êÂ¾Š™uöU̬ã8±¯òÕwöUÍ£cì@w}õR¸¯¶<~÷UßѸ¯bEóp'²˜a³çÇ“ûê3º~ÌÑ9^쫯㞪1>·ÜW•d0C.U®©Ñ+ì«lñy`_½{æž'öU®©ã¼¾ì«Çy羪)zÞØV5\gã¾z1S羪ö=¨õ Ÿ6VN“óžª$×xCåZÅ£ºvn«œ׎mUIl«zv×™Ûªüua[U®+·Uïuc[Õº¶UncJp[U1Ûªs=ÜVqr9®Û*»}oÜU9Iî»*_Z÷ž»ê3xÏ‚ï#·Õg¬çž¹Nn«\T÷xEuë=î‹Û*Žcc_ÕŠ¹öU¾æ×åÝw÷ÜWäᾊÙ÷S|Ø~é? …fÀñÆC_0z–'D0`{âè”(6°=ÑæNÕž˜C™ib`‹ãê›@—8:ó;'pã'A1à6 O˜n£wOJ€€[Ÿ|V0Jß…‰€ñ6MÐ ŽíG\"à8@}¶„B àÍNvŽm„ FŠüä@Œ÷;ˆ ½½¼Æ´Û!ÉÍê:ò 0$ :„Àëæ¢&^cÚ½ ^ãls/»KK (ðÊS^¡Àxˆ9II×8ðfP`ìIyrÆ~“ßDH×x5$´€£¢¤M@àumÀ0B`<÷;%€ÀR °Ôô,!^£†|„@—Cœs,I x%™«HQNóåvUÒ€K] Àk<ûüøG ¼Æ²ÍY ¼âà.ÌíÊ]Æ&dÝÀÀ+Îg‰xÀÀk⓱@n0)0VÛ•Œ ¼F®…=÷Iî)°¤F§r¹’£ã= t¯Hn2 ÐÏ“èÁ!^[)ÐUÝbb j–B€× 0Ð}"ºßä@19ðŠÍ9ÉèN,u¯1FGJ‚zO 5I‚ì•8kS¨‰# ŒžŸYJb`ìg– <Ç;äJø4.Œ-,ϾÁs Ñì<Ç2És,Að p…›+w< 6/‘ šLŒ&ŸÉp7÷Ö ìŒrä>`iM’`i H0’¼Ù Ó£ãy€' FÇsÔI‚Ñð#HÐÏ(xöüH'ôHÝ)’à9ö‘3i$żYH00¨%?‚ÏkîÕ…Ï›¬@k) žãlÑÓ $(µ¹Hð¼¶‚1·ŠQÆ‘mF'óÝ <ÇÛ"—¡ôõ£IxMÜ;æ×§Ö³jç†ô.ÚÀ祚ÚÀ=~b´7AEÚÀÑ“ü…àyŠÐ  NÉcaPËJ0hR ÆÙ< ¤ÁP5¦z4xQË/›¤AÅIƒq¸L ÆÁ"—0èÊ ƒqZJâ% ÆÜ»³œ“Û•Òãd›M ^c{Iý*aÐmÀ —dÁÀpXÐÇw² TdÁëáwu² ÇdÁ+^) ^Y^aÁX…'È,ØæFVXе‹¹O‹ãŒÐ… OTdAdÉ‚n X0c‡0YÐyÀ‚®I,˜JE‚ !J 8Þ(‰käÀ8!¥ª¨‡+ÔYI( êp'Ôx ‹ ¨ )/äüX"£˜Gs‘ ë&AÖN4>’¯]Ú¿$AÖ…‚.—((P : QP(#Œ 5‚FA|g3 º¢ ê Ž£_ª=…‚£…'Ô@A§! ê<\Y0ƒ,¨ŽŠ]9X0*YŠ`PIƒB-Ãà/5‚Aç òé •Ë0(ú" ªŸ‚A}Á ª[†Á'_:bAS¦XC*$–U,QÐŒIT눂*V(xÒ®B,¨ˆ‹,¨ybäŠ jüÌ‚*‡,è\bA½XP½0 ²£‚AÍ%àZHTÉ‚Á“›'aÐIƒ|2¤Aç! j¼DƒSÑ vJÑ s‘]2i0Þ†IŒ¤ÁQN¾RDƒ®‹4ÈrLƒÌeÄ74Ó _ÆA%! rí‘ãûS_h0>Öõ¬(iP­ –¶€5ÂA ºpÐ êI‰5ÝDƒ.˜4è\¤Áx±w( ±½ª›¤A7‡4¨é&,¹€ƒ%Wâ`i p°4'q°ä–LÀA×Dt1ÄAM~á Ç‚8è>KÉ?µòñ‘õ ˆƒ¥rà f­p°Ôzê£pP…ƒÎt&â §p°$Æ·êÔ@¯˜áIàA÷<Ès¬xЂöåS«pðÛ>P8¨´ÂÁk´*±ˆ8Ǥ–ÀŒOʹ8‰ƒ% pß”…ƒñ5Ü–8ß®ÏE3ÈÞ¤A}Ý ^cS¥wF›."vW’‚p0Ú»â ë"ªÄAg"Æ€\)J= Ô—~áàµÑT8(L–r’¥›ês»ˆð½ ž$ÂçJ5ˆPÿ1~± mw1æžØÁÀ¶ m›L@“Æ,A 8ŽÀPàGíÅ,tL¯/f¡±^·E%xtiAG—¢Ú³3 ë55Q¤À ¢4í"Æ ^(0À¾/V¡g¼µ? Æ¿à9æ^nÆ„ÀXö+[åixމ–j'iÃè8.!ðk(ϦÒZiHàq|¡@sµ4‚aÏ›š2jU²4‚ª\A•,à8j¤ú…¨O Ög R`)‡ÁÑ‹E!X*§BPI’ç[sÕŽ©tW,õP¨bÉ€Ño@õb`I,p`É,p`É,iÀî9°¤–^€Kp %äÀsl°i‘MŒ CÑäÀHÈžcP’èÏÂ@§žc™<‹Qè9xì](ÐZkRàëï£@ !ЋŠXÒ½Z ±Zó@K<Ç€´EXrõ9O å®è>K’„ÀR p.·Ôö‹XrÃxàY4‚ñšz sK@ ë"–4€@*Ý-R`É ,¹@E’èNK’ÄÀ"jZ±•µ…pH-(ðŽJ (ÐU‘#M~Õ$ºr@`©X ú9ÝqB`© X$€@:!ÐiU€¬ @ ë&–L€@÷èÁ!–\€À’¦s{U9€À’XzT U’¨ù& ’ðW$€¿vsrþÚ ›C²_»ù ƒì×"ó¢ŒbÒ˜Œì×nZY‘ý"´A~™!ûEšÔ}’ýÚMÝ,دµ“¾|`¿Ö8Õ!ÈNþÚ8ô¦ðœ“d@øké‹_àïÞà€Jö»7‘)à¯düµFm7á¯u¼ú­óôKøkcWø ìz `ë„Â_ë<¶þ"@ü­ó‹°ÅÙ<)è×7~"ú Яäû دǗ…EX$`¿xBé,@ö«’d¿±—BÑOöë?«‘ýúÆMì‚ÅÔ¥ý¢|MýŠèW%Ø]7~²%úÅ”:ýŸé‰~U’è×ã³Ð‚~Eô“Dè×Ç.{.Ö }€Ð½˜ƒ ЯäúUÉúmÕö –$ú•r~}‡…’Яi¶'/ýBïB _YÐ/$ðIú9ѯH€~EôsÉd?—Löë;<ãÅ~Eö‹W™P ø‹'ñ&&üy0}‡ƒá/JÉc,é¯Óv臟?§'øUIn­®„à×㙺5€‹õ• ¾~ \€¨¯H@}!ÙÕ_‘€ú´8D}Z—¢¾ˆ=Ñê³ÔW >¬ õõpÐæÆ’gQý ¨¯H@}Tê‹·.:R_HÞÅ´Jrk-P_?ö´aõ…Ö¡ >ç"õõ£ÑÔ7„ ·¤¾"õõƒF ¾"õ ¨/$7¼sk­’Ü[KU ¾´Å/ÐR_•äÞ:@ðsQÿÅÆ”ÊpB_l^/¼sk-ÅúŠÐçúJš„¾*ȽµHúâxæÓ‹ä×íA·oìAŸ ²U8ß±FÁ±Ýï4ÉLŒ}Qp +¦£`Œ‹5èüß,,8ötrõ€‚¤ ·ØÌE=àE7ëùQTzÀ8ñ}<"ªW*𨔾Éz@øZ(â•"pœ‚é…Š@«ç¨/¶«ZƒÊÌÚŠÀó¡'ÓLØZ@˜X[ x½8ðK H‹j+›‰J@å’6ÕVÒ–¼¸Â^ÚJ@˜¤[H_ëoƵ¦ÙVÒÝJ@šÌK Ç+iš/% ‡F:@¨[ØÉA:@u[:@=éÕ^éå)àu ú tÉÔ^Œn#à8¢,>çȼúÊpÜ*À‹kN*@å’ ð¼é½Gà‰£€T€×C΢ p¬±Ô—:À“Áw¤t&*åN*% Z,%àñ~ñ ´ZZÀ“‘ˆ¤Ì™/à‰S’U€jžT€™Eú¿gëÿNq¥ÿÓ‚“þOæêÔÿ|?Iÿçš¡ÿÓÊ–þÏêÿ\õ'¯bÀ":—ô#Í“Ox- ôzÚd@—LôˆKÿç\`À’ è$zKÁ€@?;@ œDž#¤@]7)p¾‡> ZôÃ#z´È€6\ º}dÀ’‹ú?u“ èn’K0 ç…ô£] >0 :ôŒ$ºW`@gº½D@¿ˆ€î%°äÊ•Eè§@”е.ÈŠÕ ½f¤üãð‰Ïð+ÔàHù×``oå_ƒ†< ¹•´®±G`œÈ> ºt¤MŒ•‡þ€Oû2‰ÜUŠÜ¹ì¨^ËSÖî€*˜î€ÎDw@šÉð@Œ»: ܋۪«¦; ÒÈкª›rÔC; ÃØPNòT¯äxÜôþ£? sÑïûºvúºvújRÈÐåÐP£A@©üþ€NB@Kè¨ÖÈ!P½’C sÑ#Pc!@= yªçòäIÕey*<UŽ<Õyj¼äh \Õ@¹Ò¢I.4ƒ²K “Ð'&Nö ŒOÐbwå©Ý>;âAÉ%PÅÈ%PŸäH»'«þ:<¶‹êßáí¸= âBŸ@—CŸÀ síHÃ'¹6W #P¦Ø”Æ?9öõxÛÈõ ®¿÷1–ŤþùLHÂÊaUãû•hÖÎØ\¶%ŽMBØê§£Gã„ö­åHRÊŒåð§Ë¹â°ûԨؖ¸ÊPŽ~þ½£Y±=1ÏhÖ]!e÷[ øÏø·ãé~ûäǽã_5Àð×)ó#ÎæK"å@Õ,ªªfQN…¢j"¥@Õ*ªªVQJÅ¢J"¥@Õ*ªªVQJÅ¢J"¥@Õ*ªªVQJÅ¢þ@4ë0™ÜÆ»÷hÖ¿åÝôÓú®ùæMôÓw§ìòvúþ|ýRÊï${çÞÿGz,éZô?[¥~Ž#ùóãc¡ƒI¿LzŒiÄS›_ OÏõø8xƹ`éèqrž_IÆmivÂlà «’£~ÐǦ;>6 …±Ò9ZÆ»ã“å̸ßÅÀäŒo~ÛTìÁÄù Ãà© 8ñEæœGƒø¡$Î)Iï„þìpÖ9ãÔ6Þ€‡3*Ï…½ýœ_tf cœðÎù)fô ¸âÌð€ UwF¤‡û.Qç‡oŽûwF´†#g™¡o?9ÃYä„ÈÔêÓ¡$ÒŒÒç÷ÖóJ£ïi2¿^á 4c>;F8<‘öHó"þõyeÿgš|Rá—:ƒZrO}üXDâ}†¯ù; <àùw†øu¥d~Œ<Ãþ‰4;¼)ÇÞyE‡$͇Æ\_øñA‡àÞ<ÛÁ§roaw8’À¿lާ—ÑÀsí¼Cƒ±gEÓfH¦ï™+º#˜ä^kº¯iñyæ¹Ç±{ÌÞ!Áþ3$Øì¦M¦Ù>TŸ¢' EÎûÙó¨q¤Óù¡ðŸ&JO:?*;b–.Å^Ò4—šH3No}n24 :Ÿñ"mgœ ÷‰ï>1žãõ÷@òÆ2Uåʘëç2=Òié|Ú…ezdøž3Lãæ2uÉýÍeêžz–$ï•ëTÇ °×°ÓjûÂTn®SvjÆ5mK)gîÎ~S'Õj¦«å2Õ£Œ×ä\¦œ>ÏÐ[ÇÒšöä2k ¦€@ Á3ƒnÔ<ïž«TIâ³Ï|£m ËW4b.RKBá^ÞWãÍg’øÃd÷!y>K±×vÞ¹FÇ›mRù@ð3ר’Ü[®R{?¹J-iw®RÓÏ\¥|_Û³å*-’'W)^•c_¹#ûÌíýÚ·#×阦óýuíûÜNI#®!A˜ƒk?ævZ%çÜNŸ9"³ûµÍuZ=×éc½k=Ë’¤¹NçE!SÒ·%GŸû©çе?Ö)&ÈCOLÎ#‹}ç~êéz[Ç:ÅR¹ŽýÂ:UšTÔ—’ܹ¼^y4*Ûs\ÜO1…¯#>ù<9öÌuc?å6wŇÏ\¨p¬¾"^i.TLÙëx°¡r:†s.Ôô¢¾ÒŽ¿4&ÜŸr?eÕñá"×)»ßcr¡²¢8çBE¹ç‰ýT­ EÖ\¨š¡‚gîÂWhs¡*WÃ~êÊ;öSçŠ>Ï"y°¡j´"êéý–†3-—jöóÚr?Õz ßã\ª¾ëÈýTņv®U„‘¸ÂÕ<×*Ây\,"«ÒÜØRw„‘¸" @+'”+âðåZUk:vT½8⤜kUÅŒsܵ¬çëŦÊÃÐfš¹XÙÀ;žÈ¹HŽíËb½ž‹• ¼Ïi®] ¾°©ªŸ÷½q±æÒ¼ï®ÅšË÷ÎÍrÝýÈÅê,›ª³<ØT-y¯\¬’´ ›j‘`SµdǦªWEÜJÓfð®vbWušóÍÅê4WËÅzÀðü à\¬›øŽó¼«ä ][™\­·ÏeÍ·‡»*ß/aÒë‹"¬sWå g~TØk1ÓÜmy¹zµ£ÿÖ0Ò¢¿XøþžŸÈãüǃà¯Å©!Û€¿öæWbÃß A6]‘±ðÛ…pÀ‚¿ý€¶àoÓ4OŒ„?¢þ £„¿c,-PàO†(‚?}+'üÉ1Eð'ŸpÂ_øéɇ€¿$¬;àæ‚?…eüÉù_ð§¨e‚¿ëɳàOo ¹$ø ^:ÈŠu&ø»øÈþæNù¤=`­eÉ ýÝAâiÂ_¿ÛIIÂ_û„d礿ïÐàÜ«z¼“&ûõûÄW<²_•$ûõûá|ûöÂN†ð7$°á!üõà°imFø›Ÿòáþ†Ö5„¿¬†rþf/sþz¤ÍS/è¯Ïe¦„¿ÑM„n üõ(î¬ð72„þzXO´$üUÉ„¿Þ²ào$©ä7z@„¿‘%7I²_ìÂ~s¨î$Æd¿ÞNìBd¿š&Ùo–“|ü¹ðš"þõ°÷8¸€ñ2Ïéü¹°/ ÿÚû0á_‹ÃlOâ_oAø7ŸAÏ‚'þ Á™FPÄ¿‘ ‘ØÿbØsÖÿªäÍ›ÌèGBüã)þIâŸ]Bˆ=žh~öþùÖ4òŸÝFÈ~vÄ¿v`€öG!þõ˜*ùšþ ÎÄ?û£ÿj¦Ä¿2ÿì±Bü›~_WÒSâßt͸%ÿÙA…ügo1ò_•$Ú‹…ØÃ §÷& ¾Á€ÿì×BœIžlr`•$Ê=†ØãpVt& ]_H€sžÜ`Âg®Ô ŸBˆ€ö…!Ú݈ (w#"àtjÙø{¬kÔ8$øöDœ4W–óà“*8ÐUí?CŒ'þaþ›îHgå¿§œ= IþëaTu$˜Mþe Î7ùoºåÌEþS5 µšÓõ'S'ûÙ+ŠìW+Möóª ûÙEŒìçÙKö³ÙϳŽìW%É~¥½`¿ùž9’“ýj®d¿Ùæ§²ßL“‡P°_Í5Ù¯tìW“Lø+sðçuKø«iþÊœü\¸þôW¦8èoHý’ô7rÁ»•ôçW!鯖“ôÇ ô›É^ýª$ÑozÂõĤ Û)ßÔ`¿Y3’$û•‘Hö«I’ýÊ@€ýØ8€_i À¯ôàWž-ȯŒ8ÈOo/‚_y¶¿Ú–¿R9À¯L>€_€_©àW&:ȯ|üF~xøÍí>¿”üÊüæ±abžÕÙpñwŽû½oú þúvó{75û›ÞÊRü)ê-)þ!Pì§è¿b¿8ñ瑘ìæ5™†ì¦3©"ûÅÜ:Å_œËóø@ö»ßj²_÷;°Ÿ¯`?ýÉ~>R‚ýÚN&ûÅìímùLû¢ù+À_L Â'³ØÏ"²Ÿ?d?½ Ä~ZŽb?‘ˆ~>þýJ1@¿Ø;wh¹WåQAäçC'ÉO/’Ÿ^gB?gûé#öÓIFì§#’ØO籟ÏÍd?oÉ~îÙ¯¤!û¹.°Ÿ{EöÓ«Ýìw#¶àÏ]'ü9—àO‡iÀŸö[ÁŸÏÀ„?n®‚¿È”³šü§ã–ùÏ5µw K9@÷XúŒó6 Œx}Ñÿ•é% -!r_6: “GÈ}XÈý³ §à…|@î@®Mñw0óŸV«øO`$þs.òŸ%ä?­qñ_ÿ@õIèÚ €.™¨n ¨¡j„ €ªÛ(š"ê!-!2î‚Ðà ô@K€Z¯"@¾¨ €œ@½b€.†xïŸ+²n Ž(@³P(GþÓaÓü‡nþ³h¸ªn ^n@ã¨' Û#d¿€bD! áS¨SaEÀ<ý cD@'!"°…)PÇ¥¤@~ï1òSƒ1P§Da èÈ(^òä+ ´DÈá4JB t.a ¤Æ@å":0‡ja ”0³Dh 0Py„J" ÔÔjj 9D¹ÿ9Ì€Ý" –(ÐR %¤@µW¨Öˆ•„è$¤@NjQ ;)ÔêÉ–ˆ9Àâ@KȪJˆÁêå# Ô@Ùa r Y“)PtF ÔJjøDª‰¨rÛ2º†@K^}¯yV´DH°ªq‚@}Ô:—(KNX$ÜT‰Ì¢@¶(Ðø& TR h¼òýC ,nª|˜™F(Þ2(Ò¯‹ù=óuUÉoÇ5e&¿J Ù|î¸ÇGè.Óù•è7¨ë€~ñ—~a¹èúwZ¸÷Þ7>ñ÷Š"pïm' ›¸÷Fœ¤¬*qï™ab Ü ÏÅä{àÞÛ3f¸h/‚Ô´ÅÌ3*º«‹Ÿ\ ÷[¼7\ ï½—8 ¼§~÷Þqä8MŸG‚¸7ÏŸÀĽwÌ•mÑôYBÜ{oØ·’öޱΪèslj{E’¸÷Ž)Ø+O9qï³ :à^Œ ÔzÀ½w"®EѧÇ@Ú‹ó2Ì:{~tÄ=CÜ{#‚]*΀{.G~~Nܳóªüüä†*?¿‡Jxà^òøOÜSsâ^D.ÊDÜ+’¾þ¤ŸC“ ÷Þ—^ÈĽ7.cø(´§¨è¢½ ‰¤4Àžb ‹öìKÚ‹rÏÅÌS!΋›mƒI{EÚ{G;Arró£G!`Ï~”òò“k `Ï>€½* ?]íåGïÁ_róS¹ùÑxÙ~~´µŸŸrÉÏOièçgï@:úÉ1Ùž~ð°§_ñýƒ«Ÿü¤äê'_ ºúÉSI®~òf’« <Н {ìëG/;ûÉ‘OÎ~ôñ°³ŸJ–³­Šìì'ÏC9ûÑqÊÞ~LóKÞ~Utö£­”œýì”Gg?cg?$)Î~y*’³ ÀììwR=˜Î~þÙ¿øÉÙÏ…ÐÙoÌÃTÈÙï õœœýŽNþ£³«íìwTkOý¤›ŸË¤›Ÿ%tó;ªgü#ËÇ èàwH?ç ƒÝÄåáG?k{øYB?e’‡Ÿj’‡ŸFD.~NC?—L?Kèâw~1ò´ß·]üŠ.~–ÐÅNèvñ;¥0£ŸrÑÇO™äãw,~.âüâ0o?úÝÛÁï”Þ~a·m}æ-±Ïf’gŸü'åÙÇ÷÷ïˆ-5_›ÛÖÚå%›1´ËI„"õæ¡‹ÔÓŒ‘Ô>xPáúö8œÃž3©Ï¦£tî÷%²KqÓõEèæ}¡¾x]§vAÎ}yz—g_œ>Ö€|± dzöe[/¶…³êøŽØÚä‹x‡2Èwì!ÈÄ“ò°D¾3„Bä;z3ù¼Óð•Èwœ8Z’øŠ ‰/-æ·s_lb÷B|ÇÙðžÈó‚®~‰|!Éó4‘o½^4|qßo |±ÿõÖeH}|j0‘ï¸xþ#ò¹"_¤ÙϾˆ™ç6"_‘ùŽXÕ…øŽë]‰/vçcQð)丈ï¸7ªA|%ˆ/Ò@5âSU$>gñ¹\_$镸J_Éâ+i@|¥_I⛋|Qð÷AOD _‘ùÔ)Ÿ“øœÀçº |î/2m‹~Ï à+Ÿ§#€¯4ÀWjêëO_i€¯¤ð¹X_‘€øÔkŸŸ‰Ï“øJ_œH|.ÀW2øJ&¨÷JŸû õ^€øT€Ï¤vÏy¨ÝsÕÔî¹jj÷J.h÷Jh÷J]Pïy~R½Wê‚z¯”õ^Éõ^Iõ^IõžJ–zOi¨Þ Á»xö•$©ß+è÷J&è÷Šú½*åL<ËÎR2ô{%ô{UËK ßs?©ßÓ¢’~¯¤~ϵS¿W$Ðï¹.è÷ªÛª3¥~¯$~¯HB¿Wr@¿W$Ðï ô{>ê÷\,õ{NCý^‘@¿WrA¿W$Ðï•\Ðï•4Ðï•4Ðï͘ÆI—ÐïyЩß+å¤~¯ýž»ýžË¥~Ï¥P¿çb¨ß+¹ ß+¹ ß‹4w ðâ—™|¥d(øŠ¾RWçÞª’¡â+’‡{«$ÐñYB_•`s•`çæÊʡ㋠:'¿’çäÞª<÷VInî­,¦qkU’Æ­•I:wVÕŸ“@¿W’@¿çr©àsjøT 5|%ÓÁ•I á A~Ò¡†¯Hnì¬pge)_2tn¬ü{ç¾JÁÃm•‚—»ªÜð ÝS*÷,ع©²{ÔíÉÉMÕlªš™Ôí t{ÁEÇ¢Û+i ÛóøC·Wª‚n¯H^l«*åå¶ÊR¨Ûó ¤nÏëº=šKè;ÔrKìÓ z[/AV)Q8çŸÏ„$Lð@ß=ôÖ5^«%¸L¢¾ê§.·y;Q $m‰Ë¡ åèg)'n\¹j iKJ9±þü{€¾§ÃÕýýÐß„oÎøÎ—@ÿL‚ßúÛ'sg¼ßkLÞ¯S(æÇ5Íyj*–åØÎ,«wfYNŲj*•¥àÎ*«DwVYJ¥²J*•¥èÎ*«„wVYJ¥²J*•¥ðÎ*«ÄwVYJ¥²þ@èˆ>ÿ^ïÏD>~) ôñ Q ¿™?z¤»¿—îKèïϯo£@ÿ–ÔOë ç›×ÑOß·Ë+êû“öK)¿; ô=޶ÛXáß =Fà¯þç?*ó¯Å‚^6û_åÏï¨ÐEøß¯ßúT§ÁöÓ!€³?žC˜í÷¹UÄg ·Èáâ©!™¡S{h|æ—·1Œ-RÍûý= až÷†K¸ÆAdŸ§Á*yã›Ûüè7µ>÷_‚êùå§´< ò:óûŠ/AóöŒæ2,¾`^q_á®úáÛ0iñEûgðóÃãCðäU!´†¼¯·Á:F¨ãät¦ÁƒÝ÷>?„Ú°iHž¼,„–—÷=áÓàk›î”ħ jËßy‹ß´¯¿³œk+õžùMñŽVÓäëA|©ûN«ê!­Ì8ÊmóD×äÞñ-(̘^|½#ÈV‹áý{²öqßKd²»m[}„÷”Ìzëênck‹B‘¥†ànÇ€g=?|ß#j<ÛàIr‡/Ë x¶ã«èn¥ÇQ8ößáÍ4¯ yaõp‡£s æØ;ùÄÁPÁÕnÏ™ýÎç@ÇÁ0êz3×ó¦Ñ—ëz{^™§‘˜ûFP´-­'uÚ|9CòÆdvkêî¸Éò˜ƒ«‡{Ì‡Ïží› žÊÓìóÛL”éYJX˜ÌáB ­»·kîMñyibÂÌ\ÅDÌœ9\Oj™Çóž&µòñèÏ#KžJ¢ûÙæ'”Òœ'j]†4‚¬Çz½v˜eÜó-qÖö<ñAè)Ãqا¦šó\óŠÑ*É£pÉÔÂù£tê‹ý¹ó‰ç:{ÆD<ëˆ}·ßuÎ>a¡±çSx3Óûd„ å ›¬}Ïi;¿`ßï>\™8a“µõ9„MV,×k~·¿gø£>î7¾=u€Ãé9kŸÂÜêxjŸ¦íÏÔÜaákÕs6 iÚ|ï¿Ãže_ /£X«×³–±xgÍWÚg·07ȵz§> E|йV帜Ӧo/¿m×¼) Ç‹üHAŸKUÝn[|êYyŸ‚Œu0›û¤¤çQ*süì¹L7(‡Æ‹æšËTϱ…Žê:Ëеyùé«BâæÓóªYÀ ¥ióêÓ;ßOÈ5¶Ÿ^jÞ}Z§]‹KOÛ"ˆ»O[•¸ûô^ÆiÞ}ÚÊ›°íiV5Ó´¬ûÙ±HÙí¸û4)fC›—ŸöZ{h¶r‘b¶yùéSsÅå§ûYÁ¼ûô©Í‰šÛUg~wË4kóîÓ«Lò{òµ´¦å¦ªWX‹ûOÏúŽ´ «å> «”£>ï?mU!í˼š÷Ÿ¶²0Z\ø47Õ­¥†¨ÍûOçUP¸ì·…ƒ`.T>šiìÉ»ösÖNž8²¬•ðÖèçÒ˜ö`•²›óöÓk©(¾Í4P¸¶yÿé½Jž²ŽÛ¼þôVÛbÈæUúy÷é2÷âîÓ§¾òÚ¼ût™{W:TÉÍýôdÕ7÷Ó|#·yõi/ïÀwŸÞG°óîÓ''ã‘ L¨.“qÞ}ú” ¶Åݧs©rŸióîÓ·Nêy÷é]¶Œ—Ÿö,f6xF½ËÜâîÓ8G¸ïYLxO½2tÑ-ìÃçÇP*Û¼ü´ª§[\~ÚëGÕ6/?­á€Û¼ütZ<9Óçå§‘$ Bòä~Z*ŸŸj7GOþŒ…º¿0 Î¸Ê3~ÖŽñœWŸ¶,öÍ4Gî§²yhO^ÑiOë—Ÿö™Æù™ašWpúÅå§mÚW4ô’'öžÞi¿5*´éo›®É•þv¬Ñßsðøúkq°Ë诅!ý–ô7NÜ0"ýµwCD"Ò_{ã®ÕÃ_{oÌvÂ_›ºÀ -ÎEyf"ý…Ê.ÏU ?9¹‹þ¶¸£1‹Iú ýÜ]ým=§©à/Ž+WâàoßýZð'ï Á_¸Óï™ð·¸²Pð§$ Âß¼H’„¿¸ðóHhüíãužðBøÛ\ó²Îü…¶­¥ðw‹f1É~šÞb¿˜NÓï8Ù/f`N ²ßßaRö+…€ýh$ô“‰ŒÐ/–QÂ+ÑïØ$? ùvE‘ŸLzD~ZÀ"¿°@Bå ?ÝO/ò“}ŽÐO®2B?Y ýdÌBôK³%q_Xçl‰gÉ}2Å÷ ¸¯4ÜGe‰°¯´ ØGQŸ^¢¾iv|ê“ñ¨ïÈ{£ õ)/ΈùAƒØ§­°OÍ!õù©ûJMÀ¾°/Ê÷°OêaŸÔ«Â>2"öi?ö 6†Â¾hÞ¹`ßqã6aŸà»[¾~ÚÌ~G¬Å,à'å®ÀO»¤ÀÏcAðÓ=É?ín¿£Ã3ÁO!ð‹n'žûކFâ>}^÷7BÙ‹ût[ªÀÏÛ<Á/àÈ4 ¿(yKhùñjq8ز€¿Rà/†&÷VÂ_”vÿiÐÅŠG"þÓ ÿâè‰ÿJ’ä?Ý+þ‹1¿²&ð_© ü.÷lò_(þƒÈwò_ÔjÿùxEþ‹Ñƒÿty¶ø/L5{¦zt€®‹¨³ù/9à¿x šÀ¿ãA¬B⟟/ñïèˆÕ#ü+Åÿœ†øçrˆǃ8‰Â?©U…žKÄ?×Eü+ ç 0Z ÔªçÀÒd †üçÉEþ+5½¨&'ùÏË™èzˆ€î°¤zøˆ€îÐË•XÊz²‘#MjÉ€¥0àñd ÆŽüçÿbzî™üçWøÏ+Šèñêõ-<Úþ… $@½! €žWÀ0ãA17Ö‡äÿ ä?å i<+þÓö"þ s¥ü*GþÓ¾/þ“E0ùϨDþÓ1ŠüwÄÖž¤Iþˆÿ¸›ÿvB·pƒ¢]¨CPfÚ"À0ï:’Ü@€²îô!&Àó/“÷†ˆ"À"î7ˆ÷ÎéBÀý‚C¶°Hæ]4ìé…€:Py§P§z!à~âî!`œóŸ„9 ྟ€a!àŽëÁ…€a˜ÝnOJ~G€hc #D ß ˆ}k0Z‘Ð`C%àÞ© J@}¨Ô¦!% nU—Pѧ¤T€)gFhmµ€ Nc-à`r`\rŸ§wr #A+j‚ºìG ýyD&†]Z*#‚aÁ]@0z—ý$^NœRÞ'•wàÀèî¶(¯†÷½•€ Çq`سõ…ÃY †°½T»«$ªép±°óYJØàd š"`ÇÅA5…èIØñ1Ê*À¶‘©t.ª;4ÅäÀhM[4€nŸ4€¼:I? hTÞ¹mX8:•Ÿ%¨Ô€KÈ^R¨ñ”ð~©X¤ð†ó¢€£uP5‚=!¤t{©d`v+oœ­¼©h—ð¹°ž¥T¯¤Ô Ã{$UlDÁëÆÉÌÀ֩΃ pl¹¥Ôƒ¡ PÏN*À46,,XÒP¨)àX×ׂ1Ó~@*ÀŽHÝV¾7y‘ZÀ©;ލ"Á{ÛĆPº1Tv~“ ð…^Ã*ÀŽÀ¹Rº½TFo?‚ú»5€E «±°óD% WªHðN[óB‚zXh H°ä¢ãk5`" 10n"ËÝT:@N|ë9©…Ó+iÁÀxϧ¢Sj@• ¼7ÜDn5 ßRru ãÅŸèH-à³åaNJÀѺ<¨îw_ ðzn©¡´§ä<J ¨>I ø4êÔº¥ÍZÀWòX è\€À{Ç]yÖò - 3cǃÎ/÷T.e+ùF–æQ ¨4RêA‘ý¤H~R¤ÀÀTÅcØÛ¢Œr’RH÷x©F¯´~I‘&ϺÄÀ"NK픀Kp`•ÌŠ^ÌYr ‡Þu¤¾ÜV#M~> Æ! zçœ$gâüJBÄÆE Œ“M~4!ê¬# ÔQAèýè¶ãµÿ,šÀðåÍ>ÕÚ_‰mô»æÌ®èw5éû€~ÑìB~a;ŸÚ™>ø¨cóÏç"YÑüóÙ¡î“õ§w´þ<`|aëOjdüy¾°®$÷éû+¹Ï_ÎÉ}únEî+yÀ}Á¥°!}¿|©÷/攸O­mýÓ"IÜ—]ûÎ ÓWØWŠ÷;V»?iïbãOÚ»ˆû¥Òeüérhü¹á¦]‚ŸŒlüÛŽ€ºWàW$¿Ò • À/¢u¦Vܧ€ž¶ý

!š”Ó6çšç+¡€ë€e‘zä*rZh&ÝÖ­[Éf³œ{î_ý¡ð®šPV¹`ß¾ q ’N‹÷ÎX‰Œ ÒÒÒBcc#kÖ¬aݺu\zé¥eK–›ÉdˆÇã¼õ¾û0 ñn„á™hûôÂ#¬*©û¶m“Uýsèº{Î`SæK!ƘìÕ9mÛÄ\…eYxž‡çyDŸl6äRû©ÜD®ëÒ”›2>~&7ý»¹¹ÏóÈf³Á9Ô}Ù½{wþ$cT¼QNa°,kì÷~$tü0fÇÈŒ÷Á˜Ìús´„_•Á!ºŒ×>UªÆc™â~§ Le¯;­Üß=¿3rÎ96io÷s(ÿô§ƒÉná! Õ¯’¹ÝÃs,…a.%Oܶm[A´ÞÞ^€î^¥&Ñl»o¼‘îîn8@]]]Yf ¨AM£­Ç:7´ « eÃaŸJ2Èf³¾‡Š¤w‹7›Íbšæ yˆ”L&I¥Rtt nõ‰D‚¶¶6²Ù,®ë’O¯d»T*E<ÄŠ¶¶6\×EÓ´ <š¦ç´mMÓ0 ƒl6K{{;®ëây™L¦ /äÅ]×Éd2¤Ói²Ù,º®£ë:†aà8Np/5MC×õàÜJÀ 6ñxœÛ÷ÞÎþ£k1ŸœœËqœÀcÈu]t]Çó<4M#“ɋŠ *áFÓ4\×%ÓÜÜÜÛl6[pÿTˆÅbÄãñï5u®l6xªe#¢ŠuŒ4ÊiŸ‰ ¯6I5ƒ(쵢ĕ|]y[„}8Ì• §b”—D8y¼ãäň°Wˆà/rŠs»„Ãpy^¡'ÈòåùmUBú0MMy%d¨p`áó©$ðÊ´lÛÉ¥ú¿Ê E}VßUNšd²°ÜêÚÕýWÛ57ûÇU‚øâGx%ª„½UÔ}³,Uΰ¥îk[[ÞFÓòÏKyY–>öËóàÏžÅ)§Tô5p*Õ¶axª¥î„c‘rاCaÞÎ(ày–e¡iÚ }5¹NÓ4<Ï#DZ0M×uƒ¾šú¬ò¼Ú¶ôU¿ú“ªçy^Яs'Tpÿrß Ã³Võ“›šš0M3蓪uƒå¸UýÅâkT}áÁΡú·j›âëQ÷!|LMÓH§ÓX–E6›%‹¡iÚ }]Çq‚þsxcµ>¼?œ?“ÉËMÓdçÎÌ™3§Ò¯Ú„2™mÛý'î‡ØÿËõ€ ±÷Õ øÿÀ–³~};¿ú•?ÞP<×SõiD0¹?ã§$A¥¶¶–•+W,+Wƒ³¾¾~®‰ßùéOy~„!-¡tÆkŸJ.Èf³lýÎVh`B˲0 ƒT*5 ÿ‘1TÃ-Ü 7*ÕúpÃJ‰'jû°§E¸Q‹Åp‡¦¦&Òé4š¦ƒiš$‰ ?“jà*%•J‘L&Ã0hnnŽ©ë:Áþ±XŒææfÚÛÛijj ÇqH&“d2™à<žçÏÞH¥R´··ÓÜÜÌUó®bÞÜy¼¸ÿEþïù_s‘J¥H§Ó¸®K*• å¦iâyÍÍÍØ£î—*G<Öáû¥„õß4MÚÚÚp'dÂ8ê8êºÃâװŠžûKsÌSŽú³‰Òá¼(áÜ(*tT±Ã’ò„hkË ,–å{@„½FÔ ¼ò¾PÉÝÃ9RT:ì•¡B†)o Ëò½K”·E2鯋Åòž)JôPÇL$ ö©Ÿ€pcT݇âX´*?‰_”(1˜hç½>ž#Å3­Âš¯Ú®½Ýÿ¯„,UȇSÂøçR¢H1ám3™¼Ø¢¼zÔ}V¼Ôömmùgç8ùû§¼yN<ñÅŠ¼¯• R¶)ÂȈ} Bt«}Zøi9'š'žx‚#uu0kVA厅ü ~ñà|q~YÕÇS۪Ϫ?ªë:‰D]×ikk 'Ú¶ˆ$–eáºnÐç3M“žž`ä j*\öP•hS¼O"‘ ™L}i%\hšV 愯Mõ×U¤5ùP j¹êË«‰Ðj¤Z‹Å‚ëò‡#C¨ÿjŸàý²,t]§¿¿?(+ø“Í ¢ALaÊQw.8ºÀÿ,? ŠšL¦^Q×uY¸p!ïyÏͼñÿôgÂd³~_DÕ·ÆGI‚J}}}Éž'Q$›Í?Ö†aðÕeË&* c@×uj7×B’1g t˲H§ÓA#GÍH‚Æä…ÕˆSaÿÔoƒišAãOm§ ˲ ¼&b±™L¦@P ÚŽŽŽÀ¤½½D"A:Æê¼êøÊÓD×u’Éd $´çFEÃ7aG­7~Õ¶ªQÞWmßÞÞÎ}ÝÇŸæTf°¯_ è¨{ÚÑш3ªÜÊ[F5<]]]ÏDS Djv‘zj–“j4+ÁF ^–e‘J¥‚†}"WË«û~®ét:ß11¥¢(OtÚ÷ÞÈõáÌzQyG”øñaÑCO¹m75åãÝ*ˆ°GŠ ÷ö†{ ¨äîaï—xÜ?n*å—9“ɯW}%Û΋,Jä çGQÇR‡ ¡¥¶ 'žWâŽçå…‰°Ç‡ú¯îä…%„½IŠ;aoµMøÞ«c„jL- ÇV?+añH #*Æ®Œ”ècšù\3êÜñx^Dñ<ÿ™¥ÓyÏ–Ï~ ïÿä½§‚ ‚ L}ÔðÿxGñ5–Â`×RÊý.ÞG•e°2 U6õ}Μ9tvvŽúúŸG/ĺb:ÎO4nã [‹øàßMw÷àÉæGùú˜uFÐÞÞ^:;;ƒ_uuu\qÅÔÔÔTúZ†D ÀY–Å W]…ˆX)ÆÁŸ}0F D~˲¬ W&“¡½½=L ÃÀuÝ`Isss,‹‘L&ƒ™=†aa¶Ô ¿òàPá´T¸¯bÏ åm¡fº„cm¡‘Ð↘¦i444e.õWÖóè+fS3ã{—î%ö†X0sH5(U™U9kL„¬lÛИªá‹Å‚Fº®ë¤î¯·,Ë ÄÕ‰Qï<·Ñ–YaOŒ°·…ò$)~ ®ë¾«þ– ¥Âlµ·û c%Œ¤Rþ9Šããªó¨ðÏ]yÁD… S)j[%À„Ã\…Ð+”W‹zc±|þÛΗ7¼ò‰Êa¢i…¹`Â×0ÅBÉHÛÆXÍ |Îp®(ì¤(F… 3Œü²tÚ&ê+Ñ)†Ï~låAA —ѧ¾TîÔ$;Õ_TýD5á,óýûYßÐPêI1Ôàüp„ ~Ÿ~γoÁ9å8bE¬&Çé:ìÜ9ð'Ì>óÌyw\Ë žöâ2F%¨´¶¶²qãFjjj‚`7n¤µµ•x<Îúõë+}=Pƒyj†zç‡?Ì/*](A8† b´jŒiêrñu'8V:¼=]]]8Ž æ755ÑÑÑ ´+ï Ïó/††:::‚x¬Ês$ìê¬ÂW£Ðïêê*»ðßOý7ð1Žß}<ç<çç—í\–ej&ÖP1…Õ:5ã)|ÿ›šš‚s)š†††‚8½ByH$÷–€¼Gƒ UœsC‰0*V*•÷.±m_¹j«<#*é W‰Ñ!ÿ_åêTùCTîU•gE êºUÕþ(¹`Þ1 HàÏêPÿ½ÜßP¦o“mç’OF5’ 톎é1¡n¹á°aao#…2Qå•£<ˆÔ¾® ÿöoà±ÇfM\¡AAFA&“A×õ@8Qá”;::ôI ÃÀæÍ›7¬W‡ £ÇÒ4^Õý¼f&Ìwbü>FCtuùé(.¿¼; >þñ×ÑÔä÷3Їgd^å𨉄"<’•ÖÖV6oÞÌ7ÞHKKK°¼¯¯Í›7ÓÚÚ 9QÅ¶í ¼ÎÏW¬`ÍÌ™‘KP&ÇJ’ð<·/y;\3¶ã¨¯rÃv'HV§ëz xض$T×4-ˆ%«\¯j^ÅZU„ݪU|Üшca2<*®¾øjÔ©Å‹—õ\CÅãHÔ3QáßTè5“øÒK/-{Ž5ŠCZ©<$Cm«P+Ï…F $Ê¥£#ßÐS*¦DÈ—GÓòøj&“òB £ÂQ)GW…¬2 À·´R‚‰:?^F=d˜Ú>0,|ÃRÀ> ?4æoˆ(Vn;_\Iå¶KäÖÇrÛÛ¹Ïòa›rÛfrÛ&sç1rVî¿“;v&·Ÿ‘+‡@2¹}ÕÏ¢*»A^”Éæ>2¼žºoºžo°+AëŸ8™;΀7RAÁǦ´9$©T*èG¶··}=å¹/Âä‘5 ^í³€KÀïc³µ”I>úè.{ìžxÂï¶·æÛJC…ÐÆÇq¥lÔÝÝÍÆ¹í¶Û Ä€ššÖ¯_φ ÈFð‰¨¸ÿ§s/ÿË¿ Ζ‚P\òÛ ~{A^a%*>m8±»ò$)Î9N(^^Ûu¤X¯ÊKe*x<:tˆ ~s¾ûØsÚžJgÜ(ï!& ½…+]Ä)…m&° 'œ/Þ',¸(aÂó&VW¢H84W6ëC}WçQ¡º Ÿ@Þ0rỞË{QÄb{àyÐô¹„êÞ·reyÈ€öÐñ+ v7`ƒ^çÿOÇÁø'Ð éÃøbƒò0qüc’ ïY’ÂÿñóÈ{—(!Å"?Ë"/z¨ít|£ _ô؇/Ž´ø¢G:÷g†Ö›¹õÉܾê{{î³—+kCè| Àrÿº±sånÎý)!¨)÷y!(›+;äÅ¢*ÌWÞí-oy†Ó¦Ào ‚ Ñb(ÿÛ¶™?~–¸½½žžžÀãDåuaò9²gšß—ô¼ Ãî+:<8³Î:+èû«¤õb¶£CE}ÆGI‚Jgg'Ô××¹Íúõëéëë‹\&5}Þg?Ë5âR€Jš¦$ÕgÛ¶ƒÙÙl–l6$Š^¾|9žçɳ]× þ«ÐI‚0:þ{7ÿü1'£W‰ä-Ë < óìP¹SŠQùMFUî\¦©ÿöÄOdúôéÔªaáŸVº8ãFå²iVñšŠ8á„*]Ä)GØëD}çQâ‰Ò7U,•$Þ¶ó‰ìÃ¥ò2Ñçä—©œa/• >,ºF¨Á}ø\®Lw€s3$þhÊåi9 F ð4`ƒóKà àþ ’1pwqÐÿ´_øÛÅfùÇ KÞóÃÆ2ø¢ƒåïO_XPej#/ ˜¹ý’äÅ”8¾ÓžÛ®=÷WJD ½h;=wµ<ÜÁÐrë”Ó“û¬„›òârÚs×Ôž[ÖN^hqB×Ý@^HR^3ÃðŠWaÅŠczAAFƒëº$‰ ÑüXóVʤ ”‡—{އ}ûüØ^¹qžp_ÏóàÑG`Ú´?bUSB| • ¤_(é`Q› lÛv0 zÿ¢EÜ\é•%Ѝü*Ì™—íRɺUœP]×Éf³¤Óé`–¿ÊMNƦ¶Õ4-˜Å¡r¨eº®ÓÜÜŒçyA’oÏó p ‚âÈ®#ì¹q§sú˜öW•g2™ ÞçɘIVí¼üòËœòO±«ï0‹)oدr“Íf1MsR‹ …¨¬m瓎+±C…Üb/Ä—æÄCêkÀvà1Àãè59!æaЗÙÎ%në·þñ“ɼk²i擟˜Kz7t¼R÷y°þ Œ?€ñT¾ÌÆ  Y ¿ß›Cc6˜¯» 2:˜MÐs<…bHC.BV¾xÐF^Hˆã{v„×A^4Vº®:¦rÙ Ë¹å ø‚Æd†ç.å\Zh;%Â(Šò ¾à¢B–æ|±9‚ ‚ L ‰D‚t:išcš`'B™é ã¹ûwaÔD=%š¬YófæÌ9;ØEõUô¡tâ#åãF¤$•ÚÚÚ’D•¨y§8Žƒ®ëA_¾š¼À”ˆúÜÐÐx477cY–eáº.–eÑÜÜ„\K¥Rd³Y,Ë ÜV“É$–eDZ%‹³4”cšf ŒtttÐÑÑA<'™L„Vêêꢽ½Û¶‰Çã´··ÓÑÑX¦üš CpúöÓYr×’Qï§¼ŸÂv \='ã}+wþ”ÉâèÊ£üõW¾Ämß]Äùç—/!ýd¡Â±e2™ñL‘bí²¸ñšÉä¼VÈ~ ÌGÀ{ ¬w@*é¿f€÷„¿•~ ñ7ûs:Ùú(ý /ýŸs3”îû‹~H.-Éû;ÀN@g—ñ4pŸóüýß‚í˜'.¤ˆ/`¼Œ7à‹øQ×Û†ï™Ï­Ó)ÌCÒƒ/œ”:@g`£ÄÀ T¨®(3ÒD2w*‹ ‹¦òÆX°ô+K+}‚ ‚ L1”ó¬"“ɰ|ùr€ ·æX“Ê‹#O°@›‰Û;£`š£ýÄ·ãºð|n@„ ]56¦@4ûŠS’‡ÊêÕ«imm B Fkk+uuu‘òRqÇŸÅΘ£ •’,“É`šf†K‰Ês¤½½D"x~(ÁDÍÌWƒ½®ë3÷ÛÚÚ‚œ*y·çyA2oÓ4e8ÔzîHKÓ4ÚÛÛÂKét:ü.„V3Ê»E >áåÂÔD¥PX°c¯<8ª}=Ï A]×o‘T*x_É,£ÒXöÌ2.Û~ÜúG´ª’™ÇqlÛžRDQF…ï?|—šÙ“Ï£XßódÈÞ ÞÛÁ=¸Rë€Ã`¼ÜöNày°^¾™ÇÀü2¸ßjÀ¸ô½ ÿ=° ÌgÀ=æ@ë»`¶÷'ð Ðnö½PÜ@Ì÷J! ñ\þ4HÆ)èë¹YPƒ5¢æ-R-høâЉ/ª¤rÀ̺tç–¤ô‚ ‚ L,ª)åyÙl–d29f%Œô6aâyâ‰'¸ò‘:ö]0 ïö:_!ÉÙkSô÷Ãw¿û~ò“ed2º» ÷×4ñN-*„š0>JTêêêX¿~=×^{-ñxœ––jjjèëë#›Í²qãFn¹å–J_O®ëg õˆŽ âºnð§‰Õ`°?”ç‰ad³Yt]'•Já¸,ËÂqzzzp]7HÎd2'‰š}KkD”kf¿aA9•˜£< ”`ÞF‰0žç9Ôu©°bj™®ë8Ž„~J¥R´µµ &Ó4q]wÄDãÂäââ©Íê^ùÎWŽn_×%‹¡íJ¨Ññûßÿž–϶äCU1J|ÊK6›ox)AE…üÊ|²ÿ Ú¹¿–KÚ~¼Ÿ‹D_ä/Nÿ‹Ÿ_°«Ë?ŽJ@ïy¾8£×ƒþÐVsp¸IüðQi07ƒûfˆ-†æ;€$h÷ï†Ø3`ÍÂá¥\R/-×PÌiÿ…ñu‹zÅÐÏЉ}}ÿýg~Ïï:Çe\VéR ‚ ‚0±,‹X,&ã‚Qlà/¾È«Ÿ˜_Þth/ëUÿìŸÿy-٬þð=šš #Shšïm!CB¥Ò¬„qP’ °aÃÀW¯¼Q8@__uuuÜrË-¬^½ºÒ×3›ÊŒÚ¶ˆÊEÓ4Ç ”rP dÜŸJ"«1&WŸ‚Îå¹s¹óÙþ5kš60wJs¨âñ|£ÍuýÙ0ÊE‰*ƒ¡R&…=P”ÇJÎa­@t‘F¡ ‚ ‚þxô!š8øC‰ŠÆËŸ£ó_Oö#!a†?þêúýGñH?ž'“'‚)+¨xžÇÓOçoFÚÐ"?¨ï‘|×È'PÍ Ü¨vÂÆ0 <Ïãòë.Dz,lÛ«wuu _û©kaB)±#:o*÷_…Ûú:˜2öV_œ¯ CäXú ÇRØäÅ/·mHl î§™;Þ´Ü6íùûÐA¡x£›8¥{ÄãL …rçÌäþ+q(“;¯ëßWš55þ x3|ãÆoä/Ù¶™qý ¶¿z;gL?ƒ½«örêŒS™7û?¾Ÿ76½‘ît# z=þòÊ¿0sÖÌ’÷S³Š²ÙlAÈ;a|̘1ƒ%·.·Wº$BÔI¥r3€CìÏù-8û4hÙ¼h¢ª7ÓôÅŽ¦&ß{DÍ"J&ým]×ÏÇþgÏóŸJåÏY,Œ(ÑD‰4ê³ ‚ ‚ ã8–e‰‡Š T sºæÀió`{árËM³s¹“ýKé QaÊ *®ë²·®Ž‡`•èœwðÃFi…ÇRÉäÁk²Ùl 8ŽC:ÆqÚÛÛa5&¾wäE•Á¶©4Å‚ŒQô?FÞËFy±t q,BÅXÛ=C¹ýõäΥ§ªpf¡«éa|MÓdÿòý\Òq hpߦû¸óœ;ùú׿ÎÎÿçmän)ÃÍžz¼ôÐKì{í¾’··, MÓ†}>ÂPžk‚0Î/sVAögÀYÀÃþ"%’@^Ñ´¼£D%¤¨Æ¯ªÕÇÉÏ4J& ½]Tz,i< ‚ ‚ C¡¢™[–E6›¥££c\ÇayÍkH 0•*Úý®iþ„=×ßiñP?% *tvv»M___¥¯¥Ïó8þøã‡Þ …?¨¨Â\©d+EáGR©º®cÛ¾*ÚÖÖ†ã8Äãq<Ï ÜHMÓÄ4ÍÑ )a¦J¸ ?Wƒ Cå:‰Y¨:ï•¿z%æ†ÒGEÓé´¸j—ƒ"¨#ãûø½ÓÀkÁüXŸòW[–¾+ö?;N^XQ¡¿lÛK,ËVL³° yñ$Ï‹(¦)Š ‚ ‚0: ü ±]]]Ò„ˆsøða˜=ÞÁy?èKð' Ø…æcç<œR)_ù$¿þu{hV†s& ù5~Ž+e£l6KkkkÁ²ÖÖVz{{G}•+WÒÒÒ2@œéì줶¶6V__O}}ýˆ¹[ÃóA ~Z¸jš×¡BìÝ»·ÒE™&£m+“…´mKoÛ Âd¢Ú¶;vì¨tQ&„r´mï¾ûnž»ÿ~¿Y&Ž!a HÛ¶´¶mqnî—_~™þãöA‹I"áwqÂæ{øðµ•¾S’cÍ! µµµ,mÛ1 *Í,+ÅeléÒ¥lÚ´©`ÙöÓOgåÑ£ù.¾2Bí—J¥p‡d2I6 mmmض‰eå'ÇÛ¶?¾›Éøƒ@ííþX©iú㥆á‹$þø¨3Qûƒÿ_-‡üØKCÃÀñ\%À—âæ·9ÖŒ ŠlÚ´‰·¾õ­•.FÙ«}¾õ­oÍÇÛ´áñ=½qnñ‘?>¿<œ¬a,ÉÈ4-? ¾xy2é .==þ±Ãµ·ònQ5» ÖÑ10у}zz ¿¿0ìøÓ(::üÿ±˜¿]1]]þ9š›ý„âÖT*ïi3þ@ñŲüeÍÍþ_SÓЃ´:þï⦾¾žM›6±páÂJ¥ìŒÅ>.\ȦM›wë9³QBG6ë¿ºÊ”ŠÆómS}VÿÃ&õãÿ§¨ârg€‰ǽö÷¹ .¾`ãà;ôcSø³á1öŸ‘––6lØÀ‚ Æx„ê`"Û¶‚0YHÛvx Ú¶‚0‰¨¶íÒ¥K+]”²3Ö¶í[ßúVN=õÔ²–­XªqùîâÏOŽâý¼Ü>Ù!ÖOñ®[Õ#mÛáQmÛb—_|‘ôÏÃå…ã5ùn˜$Ø,ÇZØ´ 6”¥m[R•É`°™ cÍÛâWÍŸïI‘Ï0„ âº.®ëÒÛûÌŸÿ+Žë½€žm¯#û‰èOTíWl/ƒkùò¼GGþ\Åûf2…ên±­¹n¡M»®ÌðýTÉ5†³¯â7˜˜Èúðß #¯W¨ŸJÈ{c*±¤½=¯=ìÚõ†q1=ôc2™‡™5럘? 7Þø-~ø=üè›OÍCñ_;vpe}=¿üû¿ÇikÃu]Çaíܹ\uç<¹l{öìaÆŒ|bÕ*Ç!sÇêÕ¼éW¿búôéüæôÓ9óÌ3™yóÍhšFss3KŽ%‘Hpä›ßäìÆF¶Þ}7 uÃ0pÓ4ÉÄãÄãqž»ÿ~~ÕÚÊ^×Ŷmt]GÓ4Œt˲°²Yººº°2¾¼ ò9¹¦‰eY~®§ï|}ëVÒé4™LMӂ󘦉™Nãy‰ææàwÍu]LÓÄqǾw/Éÿ˜¯Ÿy&K b‚×½ðwîÙÃÕ‡sùŠ4 Ÿ}–ççÎÅÅwp oÃOµ“Â×k“¾½Ü>SÜ9®€ ·Í(¢T8=÷Y#?ê3Ö*SU?Ú0ë=†ô8/wc¨kP8Ètä)Ê1aŸ‚P¥ŒÇ>wíÚÅß”¹ßL~b‰F¾ÚRU“šÏ›Â¯BŠ«oýÀo#å"ïâà·§lòÕ^œ|à=w 3·ÎÊ}׊ֻ¹ýÔ9ŒÐvZn?3·*«ªþÌPÔ>êZÔ¶êFîsxî^q5ê•Å H†Ü¹Ô2µ*·jK†ï½záö©ÚOßí§S(Z©kSÇ1r۫㸹ïñP9UÓG]DZÀDÕê8á¥C̸ïYpý·JÍK¿/úä“OçêØÂÈÈèÄA¥¾¾~@葌)±ÑÞ—^âõ³gû5]šA;\ηCßûÚ]ߢ«s Ón{?~)¿ýít.¾øb¬¿þMÿñ~Ú.wèx`Ú2ð(ˆÿðù ”Ç­i‹©¼@l8gÓþž=ÀùàºÄÞñûëXÿþÌÙ Ÿ9Ãõêê*¼jPU©0áàøjyXtÉdüQ´ðlñLøÁB3…·Q‹J‚//žÞìy…ƒÄƒ ,‡×/|=Ù¬_FÇ) þìæâk {$(?Ächx¼öidጃg ±×Õ…çy89·¬ÈľÅò³Ü'#.ÑP¢ËHµ^±ˆ9]]þè·aø-FåjW|NÃÈ‹œ¦9ÐÖÂ?†áó_‡rËó<ÿÞ…÷Éf}±*,ªÛ¢©Ç/‡Llý LS?£†á?.¥½©W@…ùúéO·²yókÉf¯åïøõOnfÑîáÙ= þóßÃ7_C2gë·¾Åëöï'5s&݇³âòËy*E<§­­ Ó08qÓ&žº÷^¯¹Ïó0rbGCC†aðÐk_K6›Å¬«Ãݶ ššÐuÓ41 ƒ;msîΠnî=4 ƒ„ãøËrŽiš¸¶äJ³m˲Ðud2„Uâ‡ZË °]]]477ÓÜÜL[[àç~Êd2d2¹sÇb1¿Ì¹2¦R©@tñ<Ïó8ûê«9òè£`<:{6ïÿþ÷ÙúïøÛ|îsÜé8°äº.½7Ü@<ÇúèGQµ–çy8AÒF®›nBÏ}¾ëÿoïͣ㸮;ÿ¯DQ"E`Q )R°¨¢HÉ¥X,H¶¡qd……±hYvB»ùx91»“LbÚDÝJBN†þÙ§ÛDf NèØÎ„@Çò$vDZ(;±<‚™¥Å¬•¥¥E‘”HÑÜWüþ¨¾U¯ ÕèFoU ÜÏ98è®å-ÕïÖ{ïÞ÷î]º×:„ìÐ$ñÁA|÷èQÜüo੦&Ì:}—íۇ϶·CÓ4ܺu+¶ž;‡ÿ|õÕ¸rÛ6X;wbÏž=Øð‡ˆGUÇŸ²a`õ§>…g?ýi,¸â \ûƒàÀ‡>„žK.Á±Ù³ñ/âöeË9‚½  ÀªÓ§1ÜÞŽM~»õ¦U—ÍR ùÕàjT{æ­Ý‘ô"_C¢æ®§cÉܵbº¹c&l š)äAZ Q›"Á‹‹ Ç’¹ühˆIÚŒ\׃QØ[¯(=Àž\R.N¸š oÙ¸Úo9bB9¨^ô¼ÄûH‹“ÎÑóèô¤!•âpµ7¢V >y°c<¦<×ÄsÏ«ICîRÈC´jÂSÒ&Ñï#"þÖIû¹|îàç°·å“a˜`(W>MØ.Xjéò+ ÷U_©N’^Çâb v÷´öë?×k=YÄ®ÔìÛ{Ÿ [D#‚!£.5×°AF2(p×Pˆ†—t®L)ä¼éÐ3‹×èp‡ šP¯´ðLÒB>d°ŠÁíŠ-O=¨Ë¦áP ùݹ*Ô®…pL…ÛµSÙiB]¨äÉC‡Ý»í6ÜËcÛ’ v¸äÐ(€1Я/IöüS×®®1|êSãAW™a R²A%“ÉLð»{÷î Á‡ÊÝÝÞÞŽ±±1 ¡½½###Èd2X»ví”ÓºpûíPžÍ}ñÓ/¦RÐ4rË5P~ûÛH^†£ò§¸êª;ÐÙyΟÔä0ðI@U×ùëðrŠ“‚r3$"ºÉ!v¦r¯ `â¤Ø”pêCúýä?ÞèQîß™ç–,}ùƒþÐ’‘œ^3w%Ù0"É"Ûè|Ê9bisÕ$Ë•§Aeõû<•ºx•º^è †_ßûp.”kºR ù<ûäY쟻ß=àÙÁ ë:t]G4…6“yoïô0 Ñ{‰\˜E"þrE2R(â[©ï7¯ñV$-.Ónð©DÂÝ]ÃäQÍþÒŸdà 2O( ‰ضíÆœÝ*_¹û¿à=_ý&æ]ö8"_ø#èúsøèøjÌ?÷´4¿Š|þõ_b–…EÑ(( îÊ¥»NÈÛ¤ë×;Çh7 )ôº®;î:8ÆŽÈ$ c±’Éä„ÝpÞïήÓD[['¼Ÿ}úŒ¯Û?~eK¸gxßY²Ù«®BŠâ« ,~ïÍT*…H$2Á@H$èè@$Aòê«qæÅqéÿý¿0Mš¦app0ïcÝ:¤ÏŸG[[âñ8”›on¾ÙV¼ö}ò“¸#W/«¯–eáÉ»ïÆý.`Ëcáá#Gpü3ŸÁ6l€’ÉÀ4M<´q#®¸âŠ¢õkdª-›¾¤áj Ȉ‡­Ý eª€«Ù ¦GÚHîs¶–ˆ´ 2l¿—"C¤¼<ÀO¯°·Àµ"Ñ"׈iŒ–P&¿îf°ÀçB÷‘¡FÔ®ôÂÕ` "Y0ÝOÇ mÝŠzò“‘¯-‹#9±¨M£{¨\{…ûÄ¥É~uwãˆõ¾óÈwÐÛ2  åʧ`ÞO¹Åµ š³T¿îM‚m¯&:;R}®¯ñ+› WÿS(O2”b†R§x¼ÔÓðTº³ÙOä9VnžC¿ü%†¦IüÎBT³ï”ܸ÷E`ŵ€’¯z8räî¿ÿA¬Zõ fÎþ¦Ñ(É ÒÒÒ‚–––¼Bíííe¥ŸŒîînlÚ´ «V­Âðð0º»»ÑÔÔ4¥4LÓÄÙ–Ho£ð[=‡©Ñ$ðµ¯=…'æâ­·6£·×Äç>w—sY$,~)&S^ú(PèRÑ>Auik³õºî®8N§ÝxÞtŽåK’ý9¶?‹+”ÉË0=tÍ%ç)u_úÒ—°¼‚ä…JåóèÑ£˜Û6×=`yÏ‘Vm뺎½a[Ù18ù c¯g!#(¹£Ý+"3ЕX5úO€ƒ€uýÕÙ혴é§>ÕŒ‹/~ñ8ðÏšŽöW~„ǎ݇[:F0oøRtuuáÊ+í{×%?ÏXÀÙÅ1UE)hh¥Saªåe££¥hmËGpÕÉ“xúÈ`t¸öÚ’î“$©à³‰0@&“É<£Ô¥B=“>‹èù{Ï3~7:„TO>´u+>sé¥PþüÏ9ë֭ç?ýéš>Ó0P5Ù$È@ƒ»4ŽÂsÍB¢¡À6x¯i€n!PDc‡ßw¿ç7Ù3õj¯ü´eÊ$ç •CŽ—š7J¸gšQuùd¦j”+ŸÇßz«>3èµÏTjõ € Î÷¨yþ×8qâ8®¹æ¿àñÇ/rº S/J2¨tuuù®­¿`›]]]Ž¡†Œ8SåG‡áú¹sôµ®9š”nâjË\ȆÑÑgð‘Ì¢E«ðöÛ'«ZÇ0ÒÛëz»";äÁŠboG£îâu2¸¶þ2™tlºîn2½dE£nˆòµO¡KTÕÍŸŒ3”åkšö]OÇÈc®.žvцŠ?ãæ¥V¼îºieP)·Rùœ»®»ýš~TáGÒ4 ñxœÀµÆëÒ¯Q¡¸.~ñmÒiçE3ïÌ™ KZUj%Ÿ:€Ë\›yjÜ´é$ÆÆ.ÆéýûqÍ•sÑÛ;ŠÓo¼Ž[W]ŽWŸ›‹u»wã“Ù×Ò{x¦bšæ„!étªªæ¹ ÐuÝ«’;¶ü¿À·î¿7ÿâ°n¹Å¹ÖëºÂ0ŒÄa¯m™é]hŲ©Á„:^JÊ0U„µ ^Ê‘OÃ0¦t}Ø x}Åv¹¸€º®;®_ ÝgY ÃpÜk' Äãq$ ôöö:c`š‡Ó8•J!BÓ4ȲìŒ_£Ñ¨s£˜€z.6![)Z4~&¯Éd‰Dèììtê500€t:í”;‰8ÏÔ;fWŹÖÊM~t]Ïwwvv:yôöö:å´,Ë™гøÙÏ~†_ûµ_ º Õ…jô €þ÷ÌÆŸçvÙŠM÷­·>˜[¤½4èª2LA¦dPéééA6›ÅÖ­[ÑÓÓƒ¾¾¾¼ó---Žr (=s͇Û“MZ¹,øî2 [/púô ¸ë®ç0gމH•Ÿ!“¹£f@ñ®ÅP ¢O~úiD/"~ aE=õñ¢{6oX˲ó'@dÄQ[WD»m(¬„hp!¥"yhA<ÕÕ²€%KýØ‚±gÆ€ä¾ L°Öišæëj†a&EQ /¯H&‘>x ºŒBο²Æ~·|õUüìgïÅ_þåãh]ù]ÌBØ·¿ö‘Yxw–†Ï~6 ]þõ_¯Âÿ±kঠõa€&i¢±„ŒŠ¢8­ŽŽ$“Ig’&N"%IB*•r #€#%‹ÙqC„IÕÀÀb±œ@ö4q£|-ËrÒF£øéìÙø«áaÜ÷»¿‹_Üz+>yø0î8rÄÙybš&öìÙãidYv !”·XG*'¹üJ¥ìqŽªªˆÅbŽ1F¼&Râ$•ëý«„ŽÉÝzÕ¿ÝP~ײÁ/¾¥!*ND¦išŽÂ%êk‹Ò%å¡(НÐ0 Gæè1E•hd¥²ùíú"c©,ËŽq“Γ¼’+>I 0š?ÉÂ..ñ¸¨l¢4É(JϘ «ÉdÒyFÞºR½ ÃpvΉùú’†a…A!z‡‰ q -$c)û©¯¢x¢qC»Š¢8ãºt:í¤Cý$õÇ´SZ’$;ž¢ ··†a8Æ‚T*…d2éô7t}$$INb±˜Ó/Òu”]Ky æõÁb?#I’3N§þ^ìCMÓt dT~Y–#¹ð¥x†4&cÝC:¿1㩌ÔR\WrENÿ©ß¤ßMÔ_,\¸¯¿þzÐÍ®aPtþÞ `59_§·lY?d¹º^’¦Ú”lPÙ²e víÚ•÷jooÇÖ­[ÑßßÝ»wcûöíA×§OŸF×Ù[«Là•'•¦éÆyå•áĉ°m[iòiÅT… ¼ƒÔš[Ó¿ùl$âoÜ!ÈuénÅ]-ÿ÷cAW1ÔX0 Ì;8ÏUÀø tyW S6ÜvªC €`9øƒ!,ÄÅØ¶íÜrK .D$¶Ñè­H¥\w`í6¬¶1Ų,gUá§ L§Ó°,ËÙí&Ë2Òé4$IÊ[G;XÊÞo]w}k†&ØÜ4&7èy e€<å"‘pÚ‘Øž¼+E©½Åb±<ƒö(ModH$å ]KéI’äÈ+G^5MË3Ì‘Àon*•Ê3²PÙHYCeëD Ñ$*~¼ò'֗Ή»Ó(_јBÊ¥åË—;yˆJ32PyŸ)À ³³ªª:ÏŒž±¸Â–Iyå¢g&Ö—Þ%d°ó€l6‹öö锞aÆöŠ vÿkåŽEaÇ/£fî8u)Qàä·Oâ² øÚ¾†ß;ú{¸}ävàF`pÏ béŽ;†á¿ÆÿñFüáÿøClºn{é6Ürí-¸+sænŸ tPC×Âá‡ãüžó¸tÉ¥øƒ×þó?2ßOš°#§wæÊ±ûh5ªâÀÖX°`æÜ5Ç.Ÿ•ûÓUR PtP9"C†ŒˆÀ€b/JJIÀârH w»qèUzí2Äa/ú ˆö´›6-ä+’%!Ž8 I5 H@\‰& Êªû ©Ëµì{(P"Š}^Î=kT 0Ù’Ýñ‘È’ ˜@T’kü Ec@î·£ºè€¤H,É>&çÆÐ *ª[7Ÿ1˜Ÿqæë_ÿºÓ3ÅÙ¿?v[†½p™¦"ÿø7ÎhÒLcP’Aeddýýýxä‘GÐÚÚšw®¥¥ÝÝÝhnnÆæÍ›ñÈ#Z!ë*÷u/>5ˆÛÒHöR%“@"q†a:®4˜êB Þ&B®Ë`îÜSA/Ôp ðÊõ¯  …ƒ•Ñd†aBÐ è ÛXò¡—žCÇ ';çáðá…H&íE €_EUmƒ3AïEš‹J°õÁ4ßR„¬"p\æ:óUÀ'ô#|ï#w~fæ”±?=¯ï{X¶lF,p¶ü[–…Gž}™Lº®ãÅO|¿ñÃâƒñøO[¶à3ü ~pË-8}ùåøËÇÇ?ü!V<ð¬¦&Hš†·?÷9 ÄãÎܯWU‘0¸gÒ¹r«‘ˆS^úOsìH®ž*Üù·Šœ÷ÑÜš‰Ç(Ž´‘{FʃâÁ„ÔÖV³Ÿ9‰8Æq…¡èAt 6ú‘S)6¨Ôö’Û e¿è^@ž‘@ž« ZT488èk )5_q§„o5t½à’BDÊh_…vÅT“jìâ £–72¬xÓ*\ú-'[„RμƻCøá‡®Ùóc®!—šZ » S+¼;ØíY\ìiÀ˜‰†ö . {P–€£è…üô—?ÅÜus±"µR\²ƒ¹ÁîãÇÇ{ÆÞƒÿ>€Ïßÿy|òöOb隥vš:ðàÄçÿìóˆÅb8wù9̹e¾ýío»ƒÈ\ì ¨:pã7 0OšgŸÿÜä^¡N9ãÎâÏ.vÓ#ÃAÏ!š«3ýEàœëi`. yÐ ×Ì·Ü|®$ä¥À ç +NztL†óŒœ<;V\§ð9‘;§ ¡¼¦§qû:¿¥X§„ç„§sŸ©I¸ïÂ$€6¡H¹gH‹^ìÏ»ÞÝ…Ÿ¼ò“*´ä™Áþýû‘ùðn¬Ž®Î;nšfÎUÜà„| &J2¨ìÚµ íííŒ)"7n„¦i™ôºZcI.,?Äç;Ç(à:J'ߎ´=’© “yâaf2€÷ßñÇW>Pp ;ïPa˜€É‰¥,Æ÷^ÇÞL µªèüåN MÔœ Æ KöÁžóÄãÀE°u¿4?KÂïsMZà7`ÓÉ“HÏ öœ& `×ÝwãK§Ná™±1üröl,ÄÛû¾ýÍo¢ù _ÀÉûîCöoþs¾øE´~ç;˜sâV<ˆYŸø^kkC˱c¸´© 8¸éûßÇ(€QÖ_þ%¾ ±~LUŽFaøN®|âÍ»•ê!åÊkåê³ö1–».{ÞÐ׸ƒ;'‹À]À¡kh;dñJʡדO,sŒ+‘e{ÅD,æºVejƒ’‚Ð躞·ÃDQgWık®ÁÝ--ޱtdÈ# é Yvæ’áΉj*Ò­Z@^Ð9Ò‰ÐõN^¹ñ6¥aÁ_?+õ2“Ý#"#H¯âõ¦Oú%ËsŒ ÁÞ¹;=Ò5Y¹ôEñ!¤ëÍxuyV. ¿HÑyI¡¸GÂó«ÆhêÊ+¯¬B*ÌHùèý™é‡Ó„ÏÔ(ɪOà6¼¸p, ·ÃAîz²ìSGcµþÓ5Ô±ÑË@´öSãMäò2r׊/RÌ’Ò‘ÊCDá*{…•äy$á*3{sÏADEþ s¿šòVryRGNy‰« ¢B]!¤Iu–r×ëÂo…Ûq#÷U(Çíp9÷(žÿ9î¹ç8p è§ÐZS­¸Òz}Â)ŠÃ2Ä’ *ÍÍÍ %---yß³Ù,FFFJI®ff_8‡¦Ÿïîq{ÃtÚ^ìiÀ]wÄÿû2R©”Ó)2Õ',‰™pxóÀŸŸW',3}®3 ‚oS¸döl<½ô_ðÖÇ~YhŠ¿”Ûp©\mG4ß…;WªvÂu÷u¸¿·~øÃè¿újüǸᡇpö—¿DÓÁƒXòÁbÍø8¾zâ6-Yóõ×±èƒD\Q øÝ;ïÄ ¸ŠH@ôÎ;q\½ é/öÀžßˆS[š/‹Çè>q$ x®u@~Çè3éŸÄ®ÒßlŠÏ±°u—ŒÔ²,$ hšUUIãžÑ¸Þ0 (±PÈU3urn(hÇ|ãüyÌùe8}s¶mÃÍ‹9‹0{aË^T¸}®'±­Uk'C¥ðÎpÒó?þÀ1T*ƒ €ÝA&á ')×ä¯Â&c‡ßkÔ+°ÅôLŠÏ½Þ{dÏÿ 8LyñˆrSŠ ¸Ÿ)æa…O‘+ Buó¢´Š–ÑçÀïùˆêBÏ/Yà³_^h3§XoÝÒp_ʪ{Î4MÈ‘•ôìøÕ†_)­¤!¦¸N…Üf†áÄ×#(†{;a¼¼ýöÛ8räHÐÅh N—žÅ¹KÎ9‡h!6õ vJ2¨Ü{ï½èééÁîÝ»qï½÷ú^£iššš `hP‡Þ^žèhS¦ÓÙ2Õ'µŸ9‡Ä`ˆ;š/ö]uJ¥ Ë2Ë$É'ä>Wmzóÿçÿ‡9†­ó9'×ø7 øoIàkÞ CRrþbKÀÝéAz„8€š3ÏoÙ‚/þþïã:YFÛÃ#CÓ4 æ:‹1øèGóŠFú ñíA]‹¨Œ=˜0•¡ªªãÆbÏž=“{Ñu©T ƒ‘°|¹=PÞ¢Z)9w_)Ø":>:Š[¿ô%<­ixwÎg7ˆ¯ªç¿OS¦Ê˜°w› æþ§sŸý„SÜ!@»É!It]‡iÚq?霦iŽB—ÞÕ€«è%CÅ7"W×ÞÕ¾ˇÞñŠ¢8e ¸Hd8!7J¤èï&Æ÷¡ÕÅ–e9ñ¹Dׄ”/¥EŸÉCiycÑuT'*)À—¹ëè9Ògú/*à Ãp®óóÆãð–Ċ®/´¢šÒºâ+ðé=ŸÆk _C*•rž‘ø|©Lô;ÐsN§Ó$ gΜ©O›nP–XZQ'gš&:::088Xpç Ï[?–,Y•±®K?Ǭ9³œc”^|¿3L˜)É ÒÒÒ‚7bÓ¦Mظq#ºººœ*°¾¿¿Û·o´2&€K.>›?uI’Ä;Sê¹üâ÷ §ÇNc鉾DÏ0!AÐÙ‰c£ÿoþÞøÍOã xEÆ%`µ ¿ç”gl¢3Q )''¤Y(?Ã0œßó+_ùJÐ/´X–…_¿X;ùu${†a`ppÐyî±X Š¢`ïÞ½%äÆ0ù,]º¿úï +sp×¥³qü¦b^îy–ØÝ Ó ”C¥»»ÍÍÍÐ4 }}}yçZZZ°cÇŽ@w§öxö¾ÁÇ€?²m´¨$’[ÂjÒé4"‘oϬ1†aëRx§ï.ßºïƒøªOçhš&+T&hWZÀ§ œœŽÍÆÛ—·ä‚Î/–€•¹KUËÛ Bqb×C‰ µu+¤x©TÊQÅãq$“Ig‰°³Ÿ л°£#pƒ !IÑÙÙ‰H$â( ‰„cH¡ èÎo*D‘L$ø®.,;|Ø>Çã¯ÒÐã6{‘û‡ÀöûïÇ·¹¯d˜ðAAy(ȵä‡.I¥N§ d܈F£èíí-ÛPá?û­èw¯øåCÇŠ•aº¹_‘$i‚>€¾««w7‰ˆß½’$¹×RP¶¤šÅÊ:Ý~‡jc8ù€+ƒÔ5w”CÙ?ù¬yùeüÇo~¯^¸àÜK;©XOÄ0uà$Ðúâ‡qò#78‡Ä©U˜F`JAé7n܈7bhhÈ9ÖÜÜŒÖÖÖ ëÀ^ 4~‘Û)ÆrAþH0c±âñ8w’u@UíØ5 Wýâ*œ¿þzßs<1`˜ ø¿) Á¹•ocݯ]¡´í‚zW¸aX!l8øzÒž«RÌU/‘Hétªª"‰°k„©Ò´j9‰8‘ÉV Ëd€¡!{µE,fŽ–. ºJáÆÌÕ¶nö}û·<~e˜°bž„ê°Wȶ»]×!IR©"‘íhí“Æa¦?Ü•(LMXpÃ{ÅO*e+$,Ë^a›·üí¾}¸ãá‡q×í·ÃL§ñêåßý.Ôo}Ë?QËâ ±LQ–,Y‚+V]Œ†áÀrÏ}ÎwÚ¡Âé™FaJ"è(…Ø3:й—_çìð4Œ|÷ÝÉdº¨ÓY¶uBüdà’ãþ¯r!Ã0LÀX@ç_¿e.t-ÄñT`… d `TîŠËr: qo‰è·œüNÓN3¤ÆPcš¡Ÿ´Ë²Œgg A«hʼniš8‰¸2ðlP™ã œ6_v_ù›¿Á÷Øýēث{\«ë:Òé4¢Ñ( ÃÈsÉ€)3 |ÅÔŒ“מ´?¨ª½²–Æ)ƒƒÐu*Š#“¸æü‡¿þkœþÞ÷ þÆoä¿ÒiûÆeɤ«ÜÐ4wŒ¦ÙÇsFSvž¦éºLï¥ó€},™h°1 V¤0Ó›ùÀ¶‹·á>Õ5¨œ={¦™q\]2LØ)Ë VNž™ƒß~qó]–]w_€½Ýš)õ!±ŸÈuBL0n;ŒE™ KÂ0Ìd¤×ª8±o.™5 –@ŽIÀg€· û~£Ï}š¦€\u``–e±Ò¨d!Ë2"‘R©¢Ñ¨ãâ­³³Óñ?næbç8+ÍÅþv;31;¹8óí¿Ÿº{<]ŸèZÍ0\Å`ÐDeiº[‹iU æÄt½éxÝyv.AUóËBùPÞ†11ZQLÊ*YÎ÷aYn9H餪ùƒN¿8>Þg¢ënúT'?–eÙÅä’Ê,¦Aeä÷áô¥À é¶+D1&CMÑõ<‹L ÀvÇÔ„_¿ ÷/´¿Ð»XØA›J¥ÐÛÛëÈgËÿüŸøùïünÞ¼y¢A#•²ïõëÅ•»x|¢ÒƒÞùÔŸzû:ŸHøç“N»îV$Éî'Å~0‘Èï³%¿?N¥lCõo’”oðl÷²T˲ÿ‹y»4q¤7D"¿¿¦xz„¦Ùå”$W9$îZ7MûÀMÇÏøä×°¯Ëašî³¢û¼cïØ˜úø…M’ÆõßøF®»L ¼tŸ¸'ïÐ;#D"Ã0Ø54ÓL+ƒJvÎ,Œ.°#zçP˜©¼¨‚l/Òsc¸óÙg'žó æÈ0LX€:j@ÏæR4}€iïPyD>{Ÿû釒É$–/_ŽÞž])€¬AÆ+ôþ&w`’$9ëu]‡,ˈÇãÜ.ÊÀxPZ€´®»ãWRÊèz~1M[1"ö§^ƒ µ-‚0âõ¤t1 ÿU1²ìž+Ôw‹ÊÑð"bY®1C’&æCJJkâ Þ½Ÿê¦( *â5Þ²¶ÂI¬w$2ñ™‘‚…Œ*…=ÀÄ4LÓÎ'•ʿƫóîØȯÏÂ…ù¿‰7 RZ‰ø)¥4-? ±ÐÖ¨*6>ó FþùŸÁL‚g§aH¥Rù»Qh»× ˜NÛmS4úíÙ“ÿ{/_î¶M?ei:í*K)oÔ®HU5? ]·ßªêÊ€_›¡veYv=¼ïR†Š U¯"“dTÌG$‘p¿¤¨ß1^C,Õ'ï÷0ì:‰ U2nŠxßâ5ªê¿KÀûîò¾ é÷ úXÖIJDMÀŒ¸~GÉXFÏ„Ò.ô^e'çœÄèêQ,¢ çÒéôĘEø _BŠbËT!ŠkÄßܯ¿¤ó…òH&'ߥ’LN>VŒÇó ~^!ݾү_—$w—O±>_”o‘hÔþ£w^¡<üž›Xz†ÿØ„ŒfâB o9Šíš÷æíMƒdQ'y8µd æœ< ¦4>”ýïþ«ó}éÒ¥PU•]E3 ô2¨\öÎ>¼øë/ânÜ·À²,èºÎ¾ø& nú7ßã¦i²A…aÂ@x> œùúi\ùÊy—à½>ó¢œÞ<rñ•N§¹­q•_¢( Òé4dYvܽQ,Éb¬0>fßt †a@ &âªXB–b.Á¢E–Dû)9½Èr¾‚Æb;1d¹x>ÅÊZJÞ•¥~xWÚzñºpñ£X9ª‘ŒŽfÅž[1œ¢¹ü}==§ƒçNµžBgg'lc ­ WUÛhå·r ž…v±“çH$¸¥ÈÈø¸ÿŽ61ÉÒñ*Cý dü›¬oSWáKåñT¼†To™Éð£ë®aÄ«PöY½†c2|Z–ý™vTŠå £$ÕÇkÜ$µ¨Àö–5só¥ø^£ª ÃVº“q%•BäÅÁø3wè ,’01˜«¦iΆ šcêBiy ¾SÍß+ÿ¥\'â}‡º†Òž¬â¿óÅtÅÊQÌðàà'>ƒ¼»$N8ŠÑ+ Y8öꫯ"•JAUUž70 Á´1¨èÞ÷ü¯pÇ•wȇišÃ0-6Ñ`¦úœ9…wÞ9áùÛg&`R@Ö°?ÎÿLF$꺌ö.d'¬Ü*Éd2ɆQÆvS¤R)g5(ÇÒ)ƒ›€§_~Úvy ˶RžåŒaƒ@~úîD£QwAwe¸—Rˆõ¤’²”Rz.“½¿ŠˆJ1VÃÈZŠQ¹˜B¾Æ\ñyhZ¾K¤7lÀGÁøñ¾Ñ&,\½pÂqÔÅÃ0E¹øìqd¯È;¶}û\¼ðB”w¨0 ÃÅA š\ÿÆ~ç3-ìà¦irÊ0Ap8?ë<®¸âŠ §R¢ †a‚Áô[ŸÆ™wÏá¦cÇÍíbãpúy H$ˆÅbH$$‰ûØj1MÜyÄãqguYŒ|[3%c\¼óä“¶’–c$0L¸ÈÙˆÏ?÷GxÏ Ý¬üajG4Ê~´§À¼sÕ Z†að8•aBĹËÏáÔe§òŽýÞïeaÒét™©2L}™6ÎÏÁÜ%sä»+M§ÓH&“슄a‚`pôò£87~Þát:ÝXÛ®fº"¸òi̺ô8"+>‚Ë$7ÜB¡nS×uÄãq `°ØJK¦tüÜ9M"‘:::` Ã@GGÞ~ûí ‹nŸÅ`o/ïâd˜0bø†æü žJ}5èÒ0ÓMó_ÙÂLຎüq”aPU• * &.š—ä»ó555!™Lr@z¦a•˯L&ƒL&“wlÕªUhjj*z¯uä>ü“§ðÞ]Ÿï²V–ež2L…”-Ÿs€ço~?®[1Û9dY–³Rˆ]1LåTÒBp)pæp3$—á~Þ<‰LÓte3ÕC’ŠÇ¨h@¢Ñ(TU…eYèììD$Á7¾ñ ¬]»6è¢ÕœresôòƒX?o+€¦†”Ýw*À¹3ÿ€?¹Å?}éKAWƒ™î€=Ý)G>Ï_µ¸}¢A…ç› S=*šwæ8{83ûº¼cwÞùdù‚®ÔL¨ *===ؽ{wÞ±;v ½½xXDëâ‹ñÚ¼[ØcŽTÊuqʾ»¦rÊ–Ï#ÀÒƒK¼ã2r«¬ØÐÉ0Õ¡’þ&pÁz °Àw’ùqSD1Õ4Í êÉ“Sf*P{Ù› ¶¼cǼüòËA«æ”#›W½ÖüKðž8èâ3Ì´¦ì¾Ó¼s9Úÿ€?L0 `h.G>üà!ßã<çd˜êQѼ3ǯ®¹#gïrìÅ’<õÔº «Æ0S"T•l6;eA$̦&œ}ñ0 ˆÅòÇlPa˜Ê)[>£££y‡dYæÕí SE*é?a?Zw®é| †qtÝŽËê·0^UUÄãqèºÎ“S¦bNž<tjN9²yõÑ«qƒù –~üãAŸa¦5e÷iàûgîE$r_ÐU`f3ÔÝWYòéqUK®F†©Í;si6ž>´—¥ÝWÜL˜0Ó‹PÅPBKKKy7gõ‡~݉B+k5Mc¥ÃT²åóf०æÅ0Ò4­ªÁÆLÓŽ›¤ëv‡L1MÓÞ­f3v.ÂÌÊ•O@â À¾µ*Þ¸Á‘E±åÉK"‘@4eƒ(S17Ýt®»îºÊ 9åÈæW=‹S—…jˆÎ0Ó’²Ç¶* K:ïÔdêÃøxÐ%„ŠtC9 Ã@2Ù‹XÌžö<‘×Û2LùTC6[®9‚Õ«G x–œ={6èª1Ì”Íl-›Í¶lÙ‚›nº wÜqúûû‹ÞwìØ1 ž^øô„Î1‹A÷Ó 1L¾}û‚.FÍ)W>÷íÛ‡'ß>‹í;çžüéO˲w %@:mÿö±ÎN;fc*eÿ™f¾!¥³Ó¾™d³Y áÔ©SA¥.u¦&Ÿ§NÂÐÐ^~÷]h÷e¯Â¢÷îC4jïNñ#•JA–eŽéÀTL&“Á¯~õ+œ9s&è¢Ô”rûÎ̲e;~<èâ33ÛNξ}ûðãü1V­Zt˜m;tQêRW ¼±-Åv0Mà¿þ×ËNÛ»®eX¾Üžvvº†©<¶ÒÛÒýW>võWï…eÙ²98ˆ)Å`a˜©022R“±mh *™LíííØ¸q#^zé%lß¾===ޱ¤ÇÇÐÐ^:Å«7ü"OdYöîÝ‹ ¦Â0Uf¦L:Ë•Ï}ûöáì©,𬱼ã‰DbÒí×–eG  £X¸Ðþ3 {å¼$Ùÿ5;>™´;á1v’}=íXÛ³ÇþL+ð™éÍØØØŒ1¨”#Ÿ4é|6›Eä`µ\Õª+w€¿Ë¯H$tu™i@&“ÁÈÈNŸ>tQj^Ïrúί¼‚ã©ï°fǶÅǶ‹þéqÜvÅmAW™aÐØöø 0¸W2¶Íd20 àÃ>‹Õ«?ð犑°w¯=gœ!i˜ÃcÛÒô¶ccc°`Ü6<åu«çÁ„aD†‡‡§·A¥µµ5Ï_{{;Ö®][T0-Z„îînÌ:u÷XŒDÂuSb4Ò¸2L èîîÆwÞt1jN¹òyçwâòÙAzùݼã‘H¤ ¢(ÚÚlÇ¢ØÞÑQ{¬ª@4 ÄãöJ¢³sb:d¯¡ëH9Ì«‘f---èîîÆ‚ ‚.JÍ)G>,X€îîn\´|9”ïW>ùN½$Ï5ž¸S¥££ªªæ¹îc˜riooG$Áüùóƒ.JM)·ï¼nÞ<Üxqh†èÌ ƒÇ¶“Ëç¯ßz+n°±ø¾ÅAW™aÐØvÑ¢EA¥æT2¶moo‡e¿ñÿŸøÄßÃoèÊÃY¦Úðض4½mKK t7¾òq±«…þc2µ¡«««&cÛÐÌÖÈ¢+2•-_ò«oàÝ…ù//UUÙÏ;ÃTŠäóhg.Îßúêu×HØ©”½B¾·×6šD" "~xÏѽÞs²ìZ Ã]¯ë¢!Ö.‡eMŒ½B®Æ·¬€},‘°ï¡ûÃpýôŠé™¦›'Å¡…x?ûøeŠQqÿ©‹ÿb®Ï3¢D£âç(SfŠT"›DwzcN¡s·,k¸É0Œ¼4 ÀeY0M³ «c]×aY–s/k¦Ïb>o½õVШæ”+Ÿ-{ßÁøùÕ¸û7ïº 3m©¤ÿÔ4{.õÐŽh4š7ž©b8O†™1T:ïãÀ\bìÏ?Æ‹á™$4•¡¡!lÚ´Éñ©—Íf±{÷î’ƒ_À©,A$â®8H$?…aª@EòyÃBüîþgòQ ]·w£ñÃ4m%n©^NÈØâݶm¶C–óW ‰»Z::\º–åî\I§íriš} Kèé¸tÝ-§aØßÉ`B1\»~t?7}rMÖÑ‘ï…^]é´}pcÅÐý±˜}¿iºŸ™™G¥ý'n¸£##X¼x1b±‰§‰ÇMa˜2¨D6ÃnÀ$%‹÷€¦iÎs¡gHÏ”ž'=çt:íÜ+ÞC¿O:†®ë *†a8÷>úè£A7±šS®|^÷Ú<Œ\2RJ ÔI%ý'ÍÑ:ý\(Š;ßb¦4*žw0/Æoü&âqWW£( /†gŽK‚.ÑÕÕ…‘‘¬[·---FWWºººŠÞk¸xü8dYF:íº)‰F£¬b˜*P‰|âxdÁBbFžA%™´;ÒrtG´â(‘°ýáªêî )´*IQ\Cà®fì.ªjŸw’Ȳk”I&m#嫪ö9ÓtcÀ$“vZ”îà`þj(E±¯—e;Æ‹$¹;Z4ÍùB†ÓÌ?Fô,%ÉÎ3•²ëͯ¿™AEòùï¯ãÜØ\\{íµì6#ÊE"‘@$,Z#†)‰Šd³†˜¦éÈ´®ëPˆÇã0 ªªBÓ4(ŠÃ0 Ë2,Ë‚,ËÐu²,CUUG)¯ë:’ɤs€cXI&“°, ’$9F"EQ I’“IÌG–eH’„ÞÜJ‰h4êä'ËrÞdÛ4MH’Ó4ó PÑ\Ç?˜ë ÷îÝ Nz'qžÇóîÍû¾gÏž‚÷R¾Þü½ÿ©Þ¥Ä¤¢{($}§:ø¹O¥cÞ|éM¦° {£…OÓˆråóü¬§ðØŠÃxÐ`˜iL%ý§¢²l9ï¾BÄãŸ{ÿûñôÏtÑKÆÊuì†a8ÆLrGÌJ1M–eM1r1G﯑V’$çÝ"¾轤i¢ÑhÞUUëÄz†h4êXýòUÅ1ÄÒs¡Ï¢q6N;†e¿|©ÎôŸÞ¥Þ²F£Q¤Ói§nòÊ@e¦kc±’É$‰z{{'Íw&PŽ|Òü)•J9}Y!4Ížcåº,†aJ¤l½PÀC×>†¯›ÿÑÑSð>¦ •A°ƒ•ÃòWBþ¸å¬$7MÓ™È1 SÊ‘O}5 ªAžþ-|ç;÷ãû߯N@@ÓôO§Þ† …ã¶øÓu{—‰,Ûƒp˲]rE"®Ë/ŠÕB»[ ÃÞBsVÓ´Ó˜lq*- DÜ]-–e§AéÐ]§ÕXöqY¶]ƒ ÂqáÄúðéO9òi]Ú„9û›ÑvÿµŽÑÝõdw¨3a¥2ÃÔ’©Êæ™3gÊVþ‹n¶H!HY–±1íøð9HÞ½ù³1‚™®LU>÷ŒŽbö5×ÔµŒ^£É·¸ë›”¡··×QÊ“’žvuvv:†2"ˆ‘t:d2‰X,†<…2™œ`, rªª"•J¡··×ÉWü/ ¨ €=î ÷í(#c‹$IPUÕùNŠ7:GFz&º®C’$hš–W2èˆF *3]Cφò‹D"Žá…ò•$)ï][è¿×xEßÅkz{{!Ë2âñ¸s\¼Žòýyô*eªòiö|©O%ªÊ.¿¦\ÊÕÛ€|X}faÞ¢ÑÎÎN^ Ï4¡3¨”Ë™‹Îä3öw^QË0áàî§^ÈSÄ<üpâñ³P”Ù§=8Xx œLúN ÃÞ½á]D.²¼»^Ä8,äZŒb¢ˆ(Šë²‹ â"2ZùOFÃp 4â.Y¶ø¶0ÚÉbYv¹È ’HØu ¸ªºÇ$)?à=ëÙ‚œŸ‹·¥q<÷ÜJ¼õ–ÝŽÄvË[¯¦þ\yå•%û‘¶, Ë—/GooožÛ,2œ2ˆò*@†)ŸZÈ)øÉ‰DÐÙÙ‰ÁÁAÇAF QÑîUÔr9Gcqïü˜Œd°,Ë14PZäê®Pš~ÐØÞeÞÿ“ÝCF2øR9ŠGEÉs%LÜ)7Ù"o)?Jk²ßÝ»›Î{¯ˆh ¯-eg394'bO% ^¤‘ÃU?…,·9Ç8~ ÓˆL ƒŠ 3/Ó\ä(>Y &\rÜõùõÏÿ<Œ»ï¾_úÒåUI;‘pËûá7Ï#×^Þó÷Ä{œ\ryw“E–ó}ðÒýɤ{žÜ‰å¤ù,ah••MÜ}¸qa(† •AUÝ-ë´ƒEUó(dÀáÆÌ¿õ8¶}Öi;¹b&œ$ ȲŒÑÑQGË;I¦¶>|¸"7Yd° ´«ŒvHPÜ EQ…°×QMƒŽWiÏñG™F†ÎM+KdyPc˜Ð0~ñ|¼{úÃŽ„\ô1L£1- *ÆãÏâ–§G`.k‚Tó† ã˜å|îé™…-[^°¬jé[ÖÔ ªš^LðO‹¶“A²×R<Š•B±PTÕŽ—¢ªù jr'&I¶K.Úq‰¸2ªx¡¿¢¸yJ’ënLQÜ,²l_#Ëv™5Í>Néò\™qÈÙ;¿øÅ9yí‚VÉòà–a‡aŽ+‚]ó1L}-ËpIqŒ(>¥!.\ðÆ%bfjØ Òt'†Îd¨*ω¦ÞX08°Ô9¦( Ï9™†dZTpd ׺M³WŠ[–Å;T&¼µhÆÇÇs~žsçæW}ûúTw^ÐŽïÂ{ríåç&ŒŽ§ÓùîÀh7‰¸û„Ò¥#€} í\ËeÙ»N$É6ÈPl1?Y¶Ó¤ÝdX¡´,˾.µÓR÷y!…vå¤Óvý9¼C OcÙ¾ahZ¾0‹9>¼† š¦å¹µa¦¾¬X±bJ•DÎO,Å ™ÊÊyYÎ_C;˜ ÊŸÅñ¡øÝol+¦ëç¦Ö{_¡4è>Ú‘í½F¼Ï[*«xŸ_L ñ>oÝÊÍÇïz·O–X>¿gRʳ§è•<û£G¯.© ÍD’IÀ4KW̦ӼƒŸaê‰qìæ=Œùó¯tÇ¿f’éaPÉAƒÌtZw|¿2 Ÿ¹·?óðk‹ašÀ±c;l®Zú´£Ã¥Ô{ED×\^èUâ½Ço²¥ë¶qƒ‚ÉÓŽ]w•Õdä t) ÚöJnÄ(ؼiºÆ’Hľ.çÎÉd~LÑpCe$CŒa°û/&yï n¼rÂñx<Î}(Ĉtnk¥aN€d†aêÏŠ+ìàïLØ«mÅ¡àY øeï8fßø:Îþx!N¿û5\zãÅøF ¸9 |i¹}ݲ80ª's7Ÿ4k"@“¼žf¸1<ß ÌÏuÇse`©ìKç,`an\y0 œ“…’}Í\ÙN–ÊÀ>‘âšpÔö›€œKcÔ{¼ã“Æ‹áæ=ªÛù-”&æC÷ÏIÓ­/ÕG¼ïFxUNÁ¾‡ò¡û¼uóÙ›Ëç–)æsØæç~¿|Îæ 3³%û¾=¹ûõÉÇïÙÉ_{®G û>ñŠ×,•‘\­¹4²pA.3¥Gß_‹¦=mH§Ó%/àÓ4×óÃ0uàèQ,:0oÍžíè,8^Ó¨L ƒŠqÝ5¸gÆYuÍÛÅ&œ½ì,þuñ|lÖU0 `ÇŽV5ýHÄ6LEï«(î/šæŸí~óKKt9&îT¡‚¨ó¢­åÞW!(H=@Èèb®DQlƒMG‡‡EtFnÃè~2f`€··3.ÍÇÏMPÌjšÓ4Ù Â0!ƒw¦0Lðœœ3m§ÿ Ù p{AÌ(n¾ùy<úèÝÐöÊ'íûähnƒ'»g/ñø¨ÏùÞI®'Dý”ŸÂX™äz¿k )‹åSв:9ÅëÕ"iÔ+Ÿh ÷•ûì ”5à™mø£¥êƒØ˜Â0ufÿµ8yþ¾üåƒ"Nó"!¦a™•³ç€áW–"TÕ€¦i%o§f¦vH‡$,Ÿs5Ο/€êÇ6*Çv‰Lt÷E NÝØ VgtÔÝ-"æCÒO‹Aì)† 0Ñ=xÅ6„Ðýö»ÎþœLº“Y¶ÏÅãóN¥Ü8/´ F×í㲜¿Ó…â¼È²ûŒÉxD;\è¼×mÅnó&÷e”¥ošöŵQ×$IvÙ×(D rÓ@ÏEtÃÀã²Ò8?z .lË;¦ª*l&Dtvv"ó‚!† ¯\=TØ:nÓb¹±Ó‡>tO>ù»øÉO¾…Ûo¿@y;¨¦gæÍ º¡†â–Í7Ä5DµpwG‹ãDÄø›âg1±Û/äBn2wwµª76'¯ÁbJf>°ÿÒýø»¿kÃg? ö,Ä44Ó r¼åZ¼|õ ü'$‰Wï1LH8xÕ<à˜«dO&«gL©…úrÚyRÊnT¿•NÞàôâàXtJzUhøï/äb4µÿ7. A†2š1cïÞ‰×a‚üI“Ë2ÚA¸Æ2¢ˆeÔuÛ@²w¯»S†üJ†ë7Ú›¦Ùå³,;Vøœü|j“+´ÁA7:—JÙe˜7ûƒBX?ý)Æ^¹Ï=÷~|å+ôLMÄb±ª>†)˲ØĈÛ^z Ý÷ßXÌõö–e¯°•¤?Åí·7]Df£xtÙ² ‹1mPU{Πiî¼Cœ£ˆŸÅ{w~K.¨E¼ó#Zæç–ÙûYb>dh牟É5Ík {ŽJÏpçà¢aɯ>[´Úq—Ĺ*+kJ¼Ž™:Æ•Àè…Qˆ§yŒË4*Ó òJS–¼»ª hšÎÉ0!á5ù"<ówßÅ ó«hm}‰ÄlÀ½Õ4 5k¼Ãž^]A»õæ/~÷{½úý¤´“…vÓøÕIâz¬Bk³Ä^£‰hX"ã-È£ù¸hdò3¨ˆi’a¤˜ðß¹C¼"˲‘ñ‡bŸþä'­hoß ¦0ÖS¯ãן8†[r6³Ö †©!Ó rÛ/Ïb䤽õU–eÌ2LH¸nï1v îºëÚ ‹Tù±JjI=6ˆ;CjE2連ÑÊÓ+„7F 3²gObóæ×0>¾² Äb16¨0LH°, ‘H„ƒu2LȰ,¯YˆÅسgOÐEbf2€Ã¼C¥ ¦iB×uî7¯k3ïO§(Ýu—b ñk¥ÜççíÁ›.é¢QàãÁÐÐÁú>ÀFãÝ70ë¢7t¼`ˆi\.ºÕ suý±=Õu}L3LH¸üØQ¼vf’I[QkÕÃ"Q‰úù‡íè¨mú¢[°ZÖ'¶Wí –ë¦T¼+Ž˜Ò1ÿ;5†•+W:q}TUå>”aBB"‘hØ~“a¦3îJe‹·L]áÚäȲŒ8/bê„s”§O¥qöìœ:3'çÍÂ@š¶1LÒð•ÃË–Aúþ8}ôV¼eŒaÂÄÃ_Û‰=OÞÃ"‘HC¯@ ìµdppâvãjCÛ¤£ÑÚÖ‡‚Ø/\XÛúö–nÖ9Nó*@šÿ¸ûî+ØÊ[†aÂC<縀 R,ËD"‘`eêÎÑ«¯º¡EÓ4µžL1 S6Ïݰϼþ¨ªÿš=#0LÃTN_~9äWßÀµ×ž„išˆÖÒ· Ã0SâÌ™3xûÂJttièÁ-c¯‡½¶Ö.¿(Œ¦ÕÖx#Ëö6èZ¡(8=/-ƒgŸ…¥G·iªªrÊ0!Á4MÄb± ‹Á0Œ‡W^¹^ Ì}&S>ùÐCA!´°›L† 7‡¯¼ ¯½&!e(Óø4| •öŸý Kž9v¨Ðuã§0Lˆx§ù <°ø1Œ¬¡w§Ôsã[­û«õîZ;Gmó ú0åaÌš…Ë/º€í.3Nó$”aBÂE-Ä'>ñ]hšk4¦ «ä‚Òëò0uß»‘rîÜó䇜6£ Nt3)Þ§(ùAY 18kùx¯?W3Y¶Ÿm©õ¡ïayn´‚Æ2Þû(°®8Öim]ÆŸ·ÞZ„;î8‰X,†Áz¾c¦d‰Ë%Ęññ%X±â $i)"‘»šfš†7¨¼÷íÅø·ƒ«±Z²Wóñ–1† {Ï%xì±ââWÔÆôQÜ‹âk=~©Ç•hÔ®S*UÛ|¦#gOœÀ¢ÅG¬jhƒ'ÃLGÞ÷¾sX»ö$–-³ß¥²ìúê–$×8."I@ooñw»¨k*Eïä·¿”û8ŸÚäãíËå£i¶aÅÛ^Äû"‘|ð==,/^ØÈm·½„¼ ­­¼;…aÂë‚&¼˜`ÖËsñ±„aH¥RºX S6 oP1¯±_•9~ ÄgŸ½ Œ@C¯> ·RÓI²W¥¦Óµw/V˜šæ®Öf¦Æ‘¦&Ìs J¥Ø<Ĉo~ó_‹Ê¤_·:]ŒÿLa¦Úߕ╪׼Ô+¯C<EoooÐEaÆ/b˜ðbJ€õä+øÕá%xè¡Ålež†¡òÒâ³Øwɵ0Mƒ’aBÆñã—bÉ’¹°,«¡ÝñIR탸׳.Ó Eá*å²á«ÿ cc7°ƒò$”aÂÁ™3g {ýy1 Eièq-Ã0 ÃÔÝf?s1î»o1b±/ˆgž†7¨>|sçîG:æ€F 2Ž]‰%Kö7ü¤“âpŸ>È­ë§Î®C÷à¶ÛÎ"‹5´K>†™nœ>}še’aBÊ+¯¼ÒðãZ†a†©;¯?‹EçžG$D£Që2 Oè *™LCCCÈd2%]ÿî»óqë­‰DØ] ÃÔ˜©ÊçG?úÚÚ.jxÙ$wÓiÿt1@†íö‹™º|_†ûî» ªªò!S•Íùóç7|¿É0ÂTå`·B S/Ê‘O†ajO9²ù¤¼0ü~躎@e¦¡2¨ô÷÷cݺuèëëúuëÐßß_ôž›o>Ž?ýÓÙÐX£Æ05¥ù\¾ü"¼öÚƒ.zU ºÕ#¯O|“z (ö.•™®{,G>OŸ>“'˲‚.>ÃL[Ê‘M†aêC9ò¹bÅ 6¨0Làþ“aÂI¹²92üÜxS’$!>]”ÌŒ&T•žžlß¾;vìÀ·¾õ-lÙ²¥d‹gXŽŒŒ]„IÉf³¡_ñög8S(G>> UUC>ìm+“É ›ÍV=ÝDÂ?˜ñT ÃûC’€drzí*‡räóþ¡ ’$…r%|ÚV1fêûƒ™•ŒméÔÃ.ï¥2~“j0“å“Ûtø˜.¿Iµ˜©òÙcàR™.mz:ý&Õ Ùœwp.zl«V½€T*º… aïK¡ †]Þ=Š'NT5ÍÐT†††ÐÜÜŒööv@kk+Z[[144Tô¡„y»XOOOÐE˜”áááЯöû3œ ”+Ÿ¿üå/Cl,ìm«¿¿ÃÃÃUO···:ˆFxÌÊ•O]×ašf(}Á7BÛš©ï¦tÊ•ÍéÂtjƒa—÷R™N¿I¥Ìtùä6>¦ËoR f²|6¸T¦K›žN¿I¥”+›O;†ó/œ@W×H&“AWcaïK¡ †]Þ_xá¼þúëUMó’ +EŒŒŒ ¥¥%ïXsssQ+Üë¯¿Ž‹/¾6lº ¾¿üå/ãË_þrÐEg˜iO9òùãOØF fxlË0á¥ùüøÇ?ŽüãAa¦=<¶e˜pRîØ6̆†)—иüjnnžp,ì>âf¦ÀòÉ0á…å“a Ë&Ä–O† /,Ÿ NX6Æ%4•ÖÖÖ ‚866Êí` 3Ó`ùd˜ðÂòÉ0á„e“a Ë'Ä–O† ',› ãƒJ{{;ÆÆÆœ`F###Èd2U÷qÆ0ÌÔaùd˜ðÂòÉ0á„e“a Ë'Ä–O† ',› ãš*ÐÝÝM›6aÕªUFww7ššš‚.Ã0`ùd˜0ÃòÉ0á„e“a Ë'Ä–O† ',› csÑøøøxÐ…Éd2Èd2hiiámc 2X>&¼°|2L8aÙd˜ðÂòÉ0á…å“a Ë&ÄРÂ0 Ã0 Ã0 Ã0 Ã0 Ã0 6BC…a†a†a†a†a†a&¬°A…a†a†a†a†a†a¦lPa†a†a†a†a†a†)¬?û³?û³  Ѩd2ŒŒŒ8Á˜ €æææ)Ÿ¯&###˜3g.»ì²P•/›ÍÂ0 d³Y\sÍ5S*C=ŸÓxT"ŸAËf)eZ>ÃP>¦q™L>ÃԶʑϠe3lÏ™>ÔJnƒjµïz×¥Vý4¿#‹ZÎIÃ$Ÿ•Ê_=ëRË9.ËgcQË9im¡s×0õ•–•ås"ax&Ùlï¼óNhûްÏGFFðꫯ†^o[wÝÚ8SÛ¶mokk_¿~ýøš5kÆë·~k|llÌ9¿sçNç|[[ÛøÎ;óî/v¾š¼ùæ›ãmmmãO<ñD¨Ê7<<œ÷ 7oÞ\rêùü˜Æ£ù Z6K)CÐò†ò1Ëdò¦¶UŽ|-›a{†Ìô¡VrT{¬…|×».µê§ùÑXÔrN&ù¬TþêY—ZÎqY>‹ZÎIƒh µ˜»†©ïlÄß$ì„å™lÛ¶m|Û¶mS._=Êö¹ñæÍ›Ç׬Yz½mº56¨”Á›o¾9¾råÊñááaçØš5kÆ5Ms¾‹?äðððøÊ•+Çß|óÍ’ÏWjbà CùÄg6666¾fÍšñ]»v•T†z>?¦±¨T>ƒ–ÍRÊ´|†¡|LcRL>ÃԶʑϠe3lÏ™ÔRnƒjµïz×¥Vý4¿#‡ZÏIÃ$Ÿ•Ê_=ëRË9.ËgãPë9im¡s×0õø›„ ŸÉÎ;Ç¿øÅ/ޝ\¹Ò× ôoö¹1 ÉÀãWÞ°Èwº5Ž¡R™LíííhmmuŽÝ{ï½ ¡¹¹ííí€ÖÖV´¶¶bhh¨¤óÕ¤§§­­­Xµj•s, åÂØØ6nÜhjj‚®ë¸÷Þ{‹–¡žÏi<*‘Ï e³XùJ9_ &“Ï0”i\&“Ï0µ­rä3hÙ,å±|2åP+¹ ª=ÖB¾ë]—ZõÓüŽh,j9' “|V*õ¬K-ç¸,ŸE-ç¤A´…ZÌ]ÃÔw6âovÂðLV­Z…®®®<9,µ|õ(ØçÆ™L]]]hjjÇëÖlØ RíííØ±c‡ó=›Íb÷îÝNã™à÷®¹¹™L¦¤óÕbdd»wïF4p<èòe2¬Zµ ýýýذa6mÚ”×h'+C½žÓ˜T"ŸAËf±ò•r¾L&Ÿa(Ó¸L&Ÿai[åÊgвYÊ3bùdÊ¡VrD{¬•|×».µê§ùÑXÔrN&ù¬TþêY—ZÎqY>‹ZÎIëÝj5w SßYiYY>'†gÒÚÚŠööv߸aøMÃ>7¾÷Þ{ÑÝÝl6‹¡¡!ÇpAˆ0Èwº56¨TÈîÝ»±nÝ:´··£«« €k­¤bç«A6›Å¦M›°}ûvÇšXjþõ(_&“q¬–7nDKK 6lØà4ÜÉÊPò1Óƒ©ÊgвYJ‚–Ï0”™xå3 m«ù Z6K)Ë'S)Õ”Ûz·ÇZÊw½ëR«~šßKµç¤a’ÏJ寞u©å—å³q©öœ´žm¡–s×0õ•–•ås"a&aûMÃ87&2™ úúú°{÷nǘR¬ aŸ»W£ŒlP)“l6‹ 6 §§[·nÅÖ­[s~ÖOÑÂUì|5Ð4 ­­­ÎV±±±1ŒŒŒ`dd$å솺}ûv´··£»»]]]èïï/Z†z•i\ʕϠe³”2-Ÿa)Ó¸’Ï0´­Jä3hÙ Ë3d¦'µÛz·ÇZÊw²U‹~šßG­æ¤a’ÏJå¯Þu©Õ—å³ñ¨Õœ´žm¡–s×0õ•–•ås"a&aùMÃ<7&Z[[±cÇ<òÈ#ؽ{whô¶AëÖØ R&ëׯGKK t]ϳÐvcóþcccŽ¥«Øùj‘ÍfÑ×ׇ¾¾>d2ìÚµ »ví EùÚÛÛ'XÅï“•¡^Ïi\ʕϠe³XùJ9_ &“Ï0”il ÉgXÚV¹ò´l†é2ÓZÈmí±Vò]ïºÔªŸæwDãQ«9i˜ä³Rù«g]j9Çeùl‡ZÏIƒj Õž»†©ïlÔß$̄噬_¿~|Û¶mS._­Ëö¹1•Ò »Þ¶Þº56¨”Á¶mÛÆW®\9áOÐ;wŽ·µµ¯_¿~¼­­-¯Á•r¾ÚxVÊ·sçÎñ•+Wޝ_¿~|Íš5ã›7o.¹ õ~~LãP©|-›¥”!hù Cù˜Æ¤˜|†­mMU>ƒ–Í0>C¦ñ©¥ÜÙ«-ßõ®K­úi~G4µž“†I>+•¿zÖ¥–s\–ÏÆ¡ÖsÒ ÚBµç®aê;õ7 3ay&… *Aÿ¦07&Y¡<¬·­·ní¢ññññªî·a2™ 2™ ZZZ|· ;?ÊGy477£µµuJeúù1MØÛVØå3 åc¦'ж‚~TÒw†å2Ó‹JÚ\ØÚc%e­w]jÕO‡í7a*cº´…J寞u©å7L¿ S9Ó¥-4Ò{†å³¾„ý™„ý7 CùFFFWXa—ïz>C6¨0 Ã0 Ã0 Ã0 Ã0 Ã0 ÃÒ3 Ã0 Ã0 Ã0 Ã0 Ã0 à * Ã0 Ã0 Ã0 Ã0 Ã0 Ã0E`ƒ Ã0 Ã0 Ã0 Ã0 Ã0 Ã0LØ Â0 Ã0 Ã0 Ã0 Ã0 Ã0 S6¨Ì FFF044„l6h92™ zzz‚~ ÙlCCC º(`ùdÂL½Ú'É(Ã0I9ýl=û?~Ç03©ÎKY>™F¥ÑæVaщ„yîÌ0L£½ŸÂTfÙl6lÀúõë±eˬY³###•'“É ¯¯/èÇÂ0Ðßß5kÖ`Ë–-Ø´iTU T½°|2a¦^íSÓ4lذ!èê2 Såö³õìÿøÃÌTÊ—²|2J£Ì­Â¦3"Â>wf˜F¦QÞOa… *3²8þøÇ?†®ëX»v-6mÚt±fFÒÓÓƒh4 ]×ñ‹_ü­­­¼*€aBÄÐÐ,¦ {?Ëïf&öy)Ë'3S «l†½OgfæÂ•€èééA6›EOO6lØ€þþ~@__6lØàœ¯”l6‹þþ~tww£©© °qãFÜ{ï½Î5CCC¾•¡Úeò+cOO¯4`BC-Û~6›Ekk«ó}íÚµÎöåB²(–©Öï ¿ò²|2a¥Úí3›ÍbÓ¦Mèîîžp.,òY¯¾™aü˜j[bŒ9Y?;ÕtªÝÿMöŽa˜J(&SaèÃJ™—N%-–O¦ñk»ÅúʰËf#ôé Smê­Ÿ©Çu?Sƒ *Ñ×ׇM›6¡¹¹­­­Ø²e Ö­[‡L&ƒÖÖVô÷÷cóæÍç3<< hmmÍó;) ­ÄéëëÃæÍ›166†ööv U}•B6›Åúõë't” $µlû---Žf³YìڵˬN¶*®^ï –O&ÌÔ¢}nÞ¼]]]¾é…E>ëÑ73L!¦ÚÖƒcNÖÏ–J­ú¿ÉÞ1 S Åd* }X)óÒR`ùd•Bmw²¾²d3ì}:ÃÔ‚zëgj=dÝÏÔ¹$èÌdî½÷^tuu€cܺu+»ãؽ{wÅyÅrݺuα‘‘lݺÕÉ»»»»`gÙÒÒâœkii©‰À®ZµÊ©7Ä…ZµýíÛ·cýúõΠ¹¥¥<ò€Ée¨Ï;ƒ`ùdÂL-Úg__2™ ¶oßî»ò-LòY˾™aŠ1•¶Äs²~¶jÕÿ{Ç0L¥L&SaèÃJ™—–’Ë'ÓˆLÖv'“ÏF‘Ͱöé SKê9ÿ£4k!g¬û)6¨HKKKÞwÑ è=G  ’·qãÆ 1­6X»v-6nÜÀ0öôô`íڵΖÎB´··;Ÿ ];Õ2ëׯÇÈÈ¢Ñhm4ÔA-Ú~6›ÅæÍ›±víZgeMOO6mÚ„;v-S=ÞË'fJiŸSiû###èïïÇöíÛË.S=å³”÷ÃÔŠrÚºaìgê¿_€ê¼c¦•ô 0/X>™Æ¥Ü¹U£ÈfXût†©%厉k5dÝO}aƒJƒÑÞÞŽ—^ziJ×÷õõ9#` ROO†‡‡ó²^e"V­Z…öövôôô ½½•BLÃ1Õ¶¿k×.d2™¼U5Û·o‡ªª©ÉÖJ–Of:RJûœJÛßµkššš°k×.ìÚµËY©GéW£¯ô£\ùd˜™Býlµß/T® Þ1 SK‚˜—²|2J=çVaÔ•S® æÎ Sj5dÝO}aƒJƒ‘Édœ`G^ü|ÍÍÍlë> EµMµLm%Û½{74Mã€LÃ1Õ¶ŸÉd&¬T ïccc¡(#ÁòÉ„™RÚçTÚ~PÊ’rå“af Aô³Õ~¿Ð1†™n1/eùd•zέ¨3*§\A̦ÔjȺŸúÂAé§9­­­hii¦iÎ1MÓÐÔÔäÓÐÐzzz+ãÖ­[Ñ××çød˜éÊÚµk122’çK³¯¯MMMXµjUà²èË'fªÕ>ÛÛÛÿÕÝÝÝŽ[îîîÐô• ÓˆÔ[nŠõ³Ðßß_p²)RÍþ¯”w ÃÔ’0ôaÅæ¥¥Ê&ÀòÉ4.~m7hù,Eg4ù¬¥ôé ÃTÖýL Þ¡Ò`ˆAˆJ…yQG466†o}ë[Îù¡¡!ôõõ•m…,§L"íííèêêÂæÍ›9ÀÓPLµí·¶¶bëÖ­Ø´iZ[[‘Íf166†îîn455U,‹Õ(£–O&ÌLÖ>+mû^Â(Ÿ vê=Æ,ÖÏpÆÃÅíÖóýÂ0µ&,}ØdóÒRe`ùd¿¶[mù¬…Îh*òY­r•Ò§3L#R«~Šu?õå¢ññññ  ÁÔžl6ë[µjÕ„¨§§‡ž S'&“G–E† /,Ÿ 3u‚›bãÞ 6p@[fÆ–>l2ùdÙdf*aϰöÅÊÅ0 ¼Ce† n×ô244T™ ÃøSHY&¼°|2ÌÔ Jn&÷öõõU´Â–a‘0õa…ä“e“™©„E>ÃÚwNV.†a˜ à* Ã0 Ã0 Ã0 Ã0 Ã0 Ã0Eà ô Ã0 Ã0 Ã0 Ã0 Ã0 Ã0E`ƒ Ã0 Ã0 Ã0 Ã0 Ã0 Ã0LØ Â0 Ã0 Ã0 Ã0 Ã0 Ã0 S6¨0 Ã0 Ã0 Ã0 Ã0 Ã0 à * Ã0 Ã0 Ã0 Ã0 Ã0 Ã0Eøÿ»w @ ¬K%tEXtdate:create2020-03-05T16:38:18-06:00n;×+%tEXtdate:modify2020-03-05T16:38:18-06:00fo—-tEXticc:copyrightCopyright Artifex Software 2011ºÅ´1tEXticc:descriptionArtifex Software sRGB ICC Profile †2tEXticc:manufacturerArtifex Software sRGB ICC Profile\~=Ÿ+tEXticc:modelArtifex Software sRGB ICC Profile1(‚¡!tEXtpdf:HiResBoundingBox1584x864+0+0û8²ùtEXtpdf:VersionPDF-1.7 7ji»IEND®B`‚blis-0.9.0/docs/graphs/sup/dgemm_rrr_zen_nt32.pdf000066400000000000000000005100271422157504600217020ustar00rootroot00000000000000%PDF-1.7 %Çì¢ 5 0 obj <> stream xœÜ½M¯.;’7¯_ñ«µ•I&¿¦l‚Ûªž ‚­vRµÝjü÷͈µVsŸsoß* Ãè{ÞØLæ“ä+üoŸëëþ\ö?üïßÿÓïþÍ¿Ÿü¿~wìþå÷Ç»Þ×çe]Ÿ{>ãú¬R¯Ï¿üÃïþ÷_ûÓ}­òU×§ÏëúšýóO¿+m–¯ÕÂòç°ÌûºöÏ_;ˆET ŽhŸÿûwûÚŸµ®òùñÿþßþ¤Î´ÜíkØ…üé]q™×lûÉx‰Öæ×ýª',G=´©ýÌzÊUê×zÝcX²ÙXOü<êyæú¯zÂrÔC›êÑϬǞÕ\¥~üÇ~ùÿm? oüÏßÿÓçø»ÝDæç.Ÿ¿Ûo ÜÞ§´gÚï¯ýì>÷O¿û¿¿þðÇ2žý Ÿß7ûçW­µÃÿ¼gß?îßß¿Tà,ÛFûêã,û‹õ–aÿ~þãßý»ßý÷»ÿígÍà¾v‘£9þé‡&jí¯Ï¯ëy•RUã¾×W™Y• gUYHU¥¢ª§Ž¯qԄ߯ŠT$êÉ2QÍhýë¾zhxU…¢¦£T¶üñ|µšUÉpV•…TÕYê·¶Õ¿J÷§ï·{ígœm'^áõ©÷×|Ê>î?ï?¶×ÿ8ð×üÞ’¾WrÏʵ_;YùÕvõ>w·ÛøûÿþóïÊçßý¦žï‡ç[?÷§_é¶¢ÈÏZë·Z~åÔ/ öþhobV¼…q=ûEV¼…û‡r}í'1~ÿ?ýáùZuÖßÿÏ(û#\cüþ‰?þ¯ûÛ|¾æþ–ÿ§üç¿ÙOk¿ÑzÏßÿýþX¯¯zÕßÿŸqø¿ü¡¬¯5®û÷ÿ° ^÷×þºã±ârÿ’èîû²ï}ë»Ò{àòÿs¾ºÌþÃZÿý?ýá—ÿlëõïÿ”åþ+çÿï0þËQö—þ}?«îߪþçüý_ÿùg- mê²6õù/|$ÑÖnŸxﻯå'ZØX–u-÷½ßÂð¶qïîÜ-¥ìW"ûùwéÝ-»G¹ÍP¾öài†gÍ–:ÜÒößXfÒ²¾/S­yš¥÷ý`Y·[v¯°ß¯Ï,sc~9í —7½W܆ý"›[vÇ0*,ú”»ìÃo/3l3˽¯½ÂRiY{2Ë´ÿš¥ô¯öÀ2ü\¥jÞOÀŸEyî¯ÇžÅ}¡ûÚ–ùåcéþƒßÃî⾪ÙÏ ½~ÙÅìO©¡Úq/aß ,û”ö$vëþDËÜ]m‡O¢¬úÕ½ÌÀ¨}×ýB./³ìæÜ2¿š=­rÛÍ²Çø5`ñ×P÷ á±'±_3žMÝŸÜ´ Ü_ܘ°ÌÝÄÌ2í"Ìòøß`ñ›¨mwö´v'XPO¿ö Ël°xém)ÖÍb#³»_3ìþä²gQ;žV]ûÉÚïÁZ×@ïõÔ¯Û«}¬-Ø“Ø/OëÙÏzZ½»°»œêEßÜSü±mË~ ¨¦¶¯âeÛõ³'!ÝV»Ø Ÿý¯»ÀÒ,ã«Ù“h[ÒÓ­÷2Kçó{Fùz¼Ì²úܲìU÷Ùýé›eôÛ}_2®y=ø\w}h(m<þ¹î¹Oo°,|®» ¡ýµÝìG·›1Cyð¹î~/¯íÇo÷9÷]Ѱð¹nËZžÏunçÞ÷çŸë*|r·=góÏu[Ú‚eásÅpb–}þ¹îy#Ï5÷ýY™=*¡Ù¶uã{Ýß-šmÛ•}¯kwø‚ûåÛ–n÷k–ý±Ø÷j¿Ànmü1C±ÞÍ-Ó?×µ¿\Nß­Ê>×µ¿=Ô»‘•Ø_Õí/¦·Û¿V+quX¦}®kTÇìnÊ>×=ÕÝó·ŒêŸëÚºÁ²Ÿ›}®V†×;§®ËºS\Þ¾ßËË4v›c߯}®k·ÄË_ÞØýŠ}®{µ£Ý2÷à¹-ÏÅö6öñö½®}éh]c÷Sö½®§ó&Æ.mßëÚzñ±û)û^×þnqPkþ¹®ý¢ýŠÇn›öµ®î­×,㲯uífŒ~ì~ʾV+2Qd¿h3ØÌПÖX˜l,?vl¬±¯uíÎ`.X†­kðÌ"öµ.k=^­÷N,âgž»“²uÙx€"»‡°uí.…õîÝ>Öe Ô {²ouíÎôA5»²ouíÎtÐ2ü[]û{ÄûžÃ»åm™ìǬ}Û·ºYÝËœYÍ€›\Xí|—ëòu\6jºáöqÕ™øíÃê.ÐùtWñau-=îU}ÜsŸ› z=>¬îƒÔ>ÖãêWƒÁÄÞÅò2{æÕ}X×îo5|XÝ5ÛÜ –eßé.ビY¦§Ã˜òöÛ^ËÇÕÝl9¨¿;/3ÑCm˲¯d[ô{Êæãê¶,´EQê®§ãìeÏþìCÝ–éï»Ø?¬Än¿~Å{H÷aÕë}Po³quD-W÷+G8O÷au\»°–áê×ûàÌÓ‡Õmèó˵|XÝGí/®ÃâÃê¶4<‰b»ìi5S{‚Qí;—õ~ {bMÕköv´->®ŽËž¾ßÃFí;ÝõøWn–Ç&ØVÏ¢÷ãÆØ³-•Ïøn>®º¥á\ÝÆU¯Æïjw ö¡î3 Þçþê¾Ámîvî˜wí¶Üqêåãê06ÃÅ”ËÇÕ]s™²oܾT¿ƒVÇeÃ6,ŇÕ]¤a‚QJõaÕËø•ÇGÕm¨èº·eª^dø§»+ñAõ¸º‚ni÷•¯·tT÷A»Ûð{ò¹ñBZ¦ªÛân–åƒê°Wxãú–ªÛ²‡XÕæÉFàÕ¾ 3Ü>¨î"KEŠ ªÃxÂ;ümðAuØÛ?ß={ôAÕAWST·e`x,µù º- ó¼mñAu[&¦.¥vTQ¿†:|P{nÉOªNŸ mË@W·->¨zÍ>u)î.Ó0åÝïáñõ¶1ÔÏþÜ>ªŸôÃàƒª?@£ÊS|Põ°Ø<ÏÏ;¿ò<>ªúãš–éë~ÔŠ4U÷åÝüžŸî£ª[ðŸá£ê¾}óÏð~Ï_Þ@™écž¿+|­ÏòQïÊ_M»|T†68ª]þ½ù¹ÊÜ>ªúãBŸÔJÅ׺[kƒ¥ú¨: šp…m÷5Å=:œ•öøãÞç"ì–ì㪿t¼ˆf3e+Â!^‘ ¾sa5 ,ôÕ%n šWpàþ˜0+ ,šÆÚ,‰ÔGÜ÷M2$n î]hn³Ï‰û~ †ÄÀÂéHb MÞü‚wQðy``­¼©ÀÀ vîÄM1à¶¼°þ€€»ƒÐfõÄ%"àܯÎ! y€çb@ó´šdFt÷?_2 Ñ‚ˆ 8}SdÀiŸ5j!š÷`¡2 •¹H|`@;Þ¤н`I2 yÐBÅ€s_ÚµÐýŸíú…D@+Bà#ÎÖØ³ gã\#ÐÜíÅ€†E÷ Ý‚zs¿öñ‚@³¬çž¡áá͹”šsã"‚ Àðb„sŸñzaàÜ-TèE4ÈÒ‘ AÐ8Š 8‡@J 8§x‚îÌ@=A+ƒ§#œSmG(hþtDA¿øÉ‚sÒ]E„³È´= ±ÊáuÉ»Fìv 䳇ÃëÒå‘·¥ÑáAÜ–jBL²`_1‘ÝC^ º³Õ·á¶S& n ÝLBA/SAu@Á¾nºÓBÓ\»3ï8 (G->º.˜>‰‚»–A6 Âñƒ"`Á¾*G±`z_Ä‚ÛÂïU,¸->ð% nË…^T,èGÐXp_ÎH,Øí%‚“É‚ÛÂÁU,裂 zÌRÉ‚^¡ ,è£B W«§ã\΂»Hçì’0Ø×î Nî0¸‹,>/ !Ïý ‚xƒ»LEë ºß ¢ ×s(¸Ë kѿکl½_@¶›ÖÁùŒXЯ‡Yè`UÌVáaÝÏtMôKÆ™8Xw¯ QÐ+騤ÓÁje¬{^øé`z€DÁ]f|ázý«C ‰$¸º€$"A¿t7$A÷“CÜMt²å“÷©8í ú¹xÔCë~ÃG5zX•*’ {5Aÿ$A¯/$èM©ŸÑ0èKð>_ñÿþ› èÚç[v¹' Ô‚ìDƒ6*ÉHƒæüœ0¸í˜õ‹÷¬#Oà ÆÕß&Z7uO8¸ëÁ¤%pÐ,8¹p°hX,|‡‰ƒ…²aÐàn° Ü A;9-¤A›T¿ip[HŒ¢ÁÒ¾K‚v*Z@ƒYD4hówXHƒvSŸ³„`0žDÀà¶Ì·$G Úì ’àCxJ‚gt© †%4ÁÝ»ÙB|8eOMð‘ ),šö ÚQ€JÁ ]áç`Áï ‚~ÐuÊÍú¢@+0U—|¬ã‹È'+þ~Ë¿ª¹² Ðëø ˜7#<-`À¼21 •¹NEð¸2 .…w+Ìg&<*%úÕ‚§€fx Gb°€~!/ôzqð¨—xTCt Ž"FÐW ×J$æ;fKæãf™ @=N ^˜EÈñn‰ù›ô—‚ø—W+üËJI~Ì)OôwXHñ¶Eq-‚?“§ x4VÁ_\ŒØÏ hVb¿|ob¿¼±_ž›èg† Ðï8†è—Ç€ü²UE ¯Þ=É/þ7iï{èccí‹ö.zø“öHìA{7Cò‚önjËA{z©I{Ö¿@ocí©ÏOÚÛè#A{ÛÂËíÙˆó9a/BWöT$`Ï Ûö.Nlö¬”)9&aò°w/j>9&­—ôW“ñŸqr€jÌÌÐb Æ$ÝÂÌ! ²Àÿy‹ÿdIس‡ËÿÙ¿Á½²ì)z7aOÁ {šmýì5Nö:{Ð^—|´×Dˆ¢=…eíí ÁzKµ(t3poRÉ Ü3Öq ÷Ò"ÞÛ/úy‡€î¿ôwhí*#Þ«ð)ÞÛß¹Q¼·ŸäD=â=›†¿y¯ªï=šíï™Ó@%à{„Ý>ûÁe¾GŸ9j!Û øá|ß3$; øv‡?$€¯]|)ÿq:sÈì>‚÷v€‹îY úœ´·OHN´÷ õ,L BšP¯_ßQ¯ßü>õlnõì P›P¯+ü]¨· ¯èÏÙ%’é)B+I¯ÓsŸ¤·¿ôúVþÆE,ÒÛGÑ"Ò³þáýit&Azã¡ë-HÏ ‘Þ˜Â8¡Þn„”…zƒƒ{¢Þ.ƒv$Ú3µ‹Q“a)|Sч|û¿h|û»D@ßR`Aº½øæ›ö&§nI{‹qö{V+êì­Â7°gWùŠÿ4 Î$Ö[·ˆU¬'go²Þ"JêÙ[õLüB— ÐK®±žYžöLú¤‘õLv« ÷İjÇÈ‚aÕB*ØóKx‰~VFáž)úo¢ßÔÕHô“°u¨~ýëÅzK«(ѯÿ úY$úÙ ·èw3b>D¿ýSMë›®{±žÍ>'êm("PoD0ªP¯1ü#Q¯uÎ6õ¬ŸG=B=‹¯I õƒÂõ::QÏ® ¡œB=³@âêu*¿‰z½ª¡^§‡*Q¯?ŠÝ$ê… ¨×›ôE²žCÇÕÝÅi÷zgx§h¯7ñŸp/Šø:ãøö“(oâ³€ÏÏ |F!À;ß¶0,SÀ—ßRÔmßâ„'e?_²_(ÞI}Y³¨o14"d¿Ýyuv’ý.ºP‚úfãIö»8ÝIÙÏB±>ô­+ã=)ûÙ—ˆSKö³ B€¡d¿my€o’ýnµ›ýì( ”ýl†Ë‘ì·ß>EAŸ}ãp5„ìgƒÀPÔ·.| ûŒ/Àl”ý4£MÙ¯t vO,¬`-ÒýÌ!‰3I÷+RRC÷+ŠÝow÷[÷«qÅ+V|NðÛ­b¨~»BÝÕ¯®wü§·t'¡úÕëÿÙ­£®/ò3…¾½U¿Ý¨0Rõ{ §¥ègÓQ\1Ño7Ô •ý«õ¯‹~×OD¿f¯ý:šx‰×„ß PƒJ@ Ö£%²ß|A °0]“ßVÞŒ>$¿‹))ùE|jPàÐQACË÷'Ý—6½5?[ÿ0 ¬ß—Ú ¾oËë×Kò3†þ¼ ðá„5 ðQlç¹ *è1)áŠO’ô˜Øxò À[kM‚í/8J¨xñ#þSkó"ü“CåþÙ9-ËðOEeføgÿþ)¢Êðφ@ïŒÿŒz#þ“s†RQ‹ðÏ öÌðÏþ–ü~þÙ©FôgT,\ Ú«ëŠxP"`.P œ RŒÀ´@À1¿GÚš?¬»v.s´É,ŠÛR"`“k °EX¦p[ÐÛ­•‚‰€Ÿ“ÿ’FŘ¯¸-¼:`Ò§ðÑì8ðÑÃÊøOé2gügÿ!þ"U€r$ ¬¼ŽPé%¢À¼) ¬Š¦ ¬ã;Ú²¦·àgm §âªN 4,Â@[ÈPb`Õ‚ÃÀ@ <‰vûZh–õÆÀð¤VÂyP`-ï ¯IÊ~‹ý|È~Ýaª~ÂÂTýšÖï±@î„Àm)èEcà”¾Ë÷ïïe€¶Zës`  äÏ{à~æŠõä2@—ÞË÷G÷Ë#H=–¯%v>‰ÁÁ·šßî¹ £=ý©U‰þùP•êgãÞ¹Ðq½1Ø“cë G9e?­« Õ/¼¡úm ¢–CõÃ_´>ÛPý¶…Ð)Õ¯sÙFª~ò¤¤ê×#DTªßî”ÿªßþÞ® FØr¨~k’÷w áM$ø0F(Qð‰Å[µ 6Iðá2É$Á§rÎ$øhyOàS¾“ ­F“à•7A°JM ¬.@pAëN>'Ö&µN¸[®XÁŸK’M¬4¹øµðn)µpÏŽ0ŽàÏ¥ Çþº…þŒ þ\çw„RÄSøçÓ‚©ðOŸM h“lLÖ#ú3Be#ü3äÙÿ´¬"°m®iOñŸ{ÑŒÿ¼Øø3þóâˆòßâõ…ú·ªÖð‰9—NõovEˆJýÛ%ØQâßþV|â_<Ïÿº"¡CüSô{ŠøÿÚD4~Šmé\ÿ¬®IüÛGú8´6.ŒO l`#"XòßÃôÔÿ:öBÿ“o:õ¿øzC|èMKð¹xyÒÿª9ô¿ÚµæPà~øh‚6þ}´h½8ЖÉàõFôçjôMi ­Ñe®¼Ì³ `ã:À«É¥u€W‘†ëí»Ã§©u€—bôç”7#¢?w=@)R°íIýõÎô³ç ·MP3¥,‘í—bˆ#2ãÌùW’ªýXwZ2ùØëYäH>VmÚ4^õ„娇6Õ£ŸYϳç‡6ˆ÷–¬G6Ö?zlšY_õ„娇6Õ£Ÿë¤jÕäS{¦]RµçgIÕîöíŸß“ªmkû¥²HQT"EÑÏšÁÓÀj™êê{[µ†h ð*¤ª2_šª:󥩪,ŪÎBQ•2¦EM™1-*RÕ“E¢šÈ—õùÒ¢¢(¥šŽBÙò•/MUùÒâóŒR¬ê¯IªVoó±Ôÿ¿$Uû-=àηþîO¿ÒmE‘Ÿ5ÖoµüŹÉlÚ°§ÿŸÊM¶?è³êN³Õúµgýó÷3™ ¬üë ÊöCµlX˜þDk÷çNˆ¨{d…GkÈjÙƒ¦{p..HÜ– ÎÅÕ6µ b3Y-³Â…cΘÛ-ë‚àpq¶¿-.—z´Œ‹¶µ^ ‚ÃE0Û7Y๘àhßéeD‘«Á·eÄ Ÿ0ì‡×ènªçq¼vw«ÏÂw‘ îÖp¹ ƒ×}Ø^<®ŠŒ¼œOj×Ç=W¼¸9sèÅZדîV¯ä±‡ä.Ù§mq§Q¸Ïú˜‰a$®uìë0Í,”©êc‚ÄGÅuÅ ‹…ŠÍÁÄ4b>ù«Oó.Ë} >Û¯9˜¼-Ë@KŒqòá Î0mó7õÌÃoå2¸úØBI^ïž•pžIÝOÜ\~é…ÚSð'˜Ð/¯YØÌ mE‘²(rÅSm¶(톅õ>ŽýbÚžÜû<“«Óª%|3pÀÚ ®+@O«™‡i~R±«mO mIÖ Ë¤ŒOÿõ††NŸþ†ÚÍôÀ¸‰n¤÷Àw€£ºyB>îpðÙKí¥¡ ”ï¥v ’ùørS¼—¾'ãþµNFmnËÄ׺¸’k·Ø†¯Õ¸Ù ¶jî†áF5æ_ê”´q¦1Á„3fÔn&ŠÓ,³ü†=q—Æuâ5Œk ±j°ŽÛWËHúÏRÀƒ±íÏes.hKøžFu5Ái”µî>м:pP+wsw_u&C\B%{šeŸ©-z䉜1’üמӻ(ø0~d[DÁÆ`¯:6V‡kNªuJó 8ÄUæSðT[ÎcÕÃÇ Öðá½×Ü4'ðê΃ŠÅvhxæÜpQpÐßS­ý·ŠUr8Uëð'?UW§• Õ ÍѶPv«IRÅ7°øªÀm øY=¤By³¼CñTU7 Iœ,Îß§½aOâT胩¦)z'yC«¿ÓÉ«ðpl}éò2L¸Um!«'qª7»\_+:˜ªÊ TeŠ™kÉó¬¶rÐiÐã£fûD<ÏcSËéuyž'<õç2Ê~saÊc^wÝ ¦Xy,—2(œ<–k2”àõTæpšheºB§Žþþ±DRžÄi1ãÕs!²À3ï\8Ó¨ÌâÄÕ6Ï5}HõÌ;7N>}Hõ\AqõXÏ`6k['ªH]D½oR‡yÉ ÊÜžGÅ->j=–ÄÈÓ8é=<7<ÖÛr}Áð\žÅÉ–óá˜g ‹ÓC%ê¹-£—Â…Pb½aÊ¥k{ä»ìˆ 'ðþ9ÂÉòè¡Öù …SÑ{îå#ê¸;Wãl‹¨ãÖ*Χ\)œsL=2ý0ùõ”â#긕ôn[R8Í!KHáW´YR‡åÊÅ[(ÍWuo #o·Å‡Ôq››eº©»Lç/ÇÔ=­ílmŮà üʶÁ‡Ôá**,ÆÜÛ` eüñÕˇÔQ*}9O½}LÝe8õy `íc-Ò÷TÂÇÔ]æ†Ó÷©ÕÇÔa>EZÿH‡ ¶x^õñAuŸ‹î¼§škeöý²æîƒê(OåMÔáƒê.ƒäiÛà™·†ùÑDëô1uØCB«¨ËÇÔa3Mï4Ÿçò1u—Áêãm°!o—`®£çÖ:ì1údìyL……­ú©>¤z%µTRGY7ïày|H6]ÅÛ|š©{ôºÐ?O÷1u˜³màé>¦‡ý.ŸáCêðù«¦¨Ã%l­µ=ÎEï÷¶øˆêE||ÚåCê°—êSΧ™ ëezý§U‡ñ{$·ÅGÕažS?w«žŒmÔÊ€ã=/ôQuXKÀ4SaÍÀä[Ûàêäîå§ù•Yž6|\{BÆ~¤ W‡éÖh÷mú¸:|ú Ëòqu˜’íçé—«{*Àé¶ø°º‹ Àí_þ.0T«‡µ-Zª©Û²øåöêcê05üAË.ceCžÞ¼oÝÑcNûN÷ÈɆ×M‚µ2³ð{êÃÕ:ÕU÷‰Au1ü0úòAÕŠàÑõ…AÕ\Ã~yîS0ÏÇÅè¿gÜSÍWüœ¾Äm©²~kR²ú}'¿ëò» ¿úyÓÿ৉À ~¬8À¯p.™àǘÕü z›ü ~ Å<À¯Âs€Wa&ø] îSR²ä¾‹ë¼ƒûì¢ü‚û”“ŒÜw ´‚û®.”÷m ®-¸Oy_’ûl´3‰û®!Š÷]”N“ûöÑ…‚ßP'ð³‘gøÝ %Oð³P4Z~÷-¨ø)4.ÁOÉÅü”Ï Áï¦Vàw3F+Áϼÿ+‘_°tŸ…7Á"òS€Q’ŸV&ù)²5ÑOë,ýÊͶè§ ‰~…]¢ŸVß&ú)]A¢_Z„~…i—ý “¸$ú)Ö,Я°ïJô«Ì”ègÒúU†M%ûÕKLIöóF²Ÿ§±ßTt\°ŸK=ŸƒýLéA5b?_(#üY5°ŒügGŽÄ¾²ãsàŸ{ÀÀ?¢ðq ÿ"™ðÏ) CþóPÔ;(N“D €.xáÚ€¶`$´Õ¸~ YSä?ÄæüM%É ø³ˆˆ7ü™å~ÁŸ ósÀßLô$ýÙ‚ |¼¢?spð(ÒŸYˆƒ _*ÚÀŸû@йþTƒ7ØÏC#ÐðÈ~‡'…ð‡8;ào[Ô!þ<ÛîŠðçõÀûGøƒÿ×øÛ È„?/CLsúóȰÞ*tSÏëë€?/A¬V'·‹þ\‰.'ý¹Z ‚ ýÁ±ìW'W‹Šþ2¯»èÏÄ×Iž}ÌC,D¹FCô‡×Íqu1DJôçË-*Ю´³¹n•ãêbNüC°xù$þ!‚;þ!ÈõR ´€€‡¼w!„€þÜ€:~áð‡uõ“ð‡U $ÀÂÂý¦ îòš°þ°fÐø³ÈìO’Ÿâý¢È/ƒ¹E~Ì3üPçø¹#íä¾m`grŸG÷¹¯ %ûÜ“$!öyl7ž ±Çв˜\Mówb|x~&bŸÇOX€}ž€í:±#@:`Ÿ'NÃk$öyÖìó k´rŸÇ™€SÈ}HɆ£À}n“†Üç!àí?T|‚Ÿ;Á?w"ú“û<_?aÜç– ðîóükÊ€û¼ !´Ó—úÐó,îCî*Ðâ /õQ»!ùy ú¢ŸŸ‹dºèLm\‚ ôs Hšè·- <úÁóY>‰~‚ýܳI{èQµ‘e<ªÿýIôó†Âzq§»B?Ïþ†÷Môóã+$úy"7„~î@Å·Köóôjãd?¤EÈÝt©v¦uþ!Û ­Ò¥ªXáŸï_€JüÛ9Oˆîší'þaï”þùQ´8þy`Ö}â__Šú#þyB8ø3ˆž÷Î/˜øçlj~"ô.Ò@=÷Üo[”™È’—½„m>ês­@@¥£I,ÈBXjC€JŠ•h±§G!`á[M,|?‰€¶¥ÐMXúwÔræDÀý_8åŸP…€Ï#™Ž ¸@Œ'´`8XÈ€méLb@…N’ç-‰Q 8èÜL!›‰W}$Úº±Ï‰€jq‰€Z›h- &\‚¥@@Ã3 ¤ÐV€àäB@eLR8¥ À©)¹°wݦp°œú€¶w0M( úÛuƒöƒþé$ýMäKøŒ\Lø›ˆ@Kö›K"ŸØoLIƒb¿%õPègÊÊç ?_kjù-.½Iò³ Z@~ûcîäïQä×/z‚ü,™-YP¢ß%aPä7±F0ÁÏ"?'÷Í›² °oˆ×û† =°otÁ˜¸¯KÃÍïÒ‡èwIÓ ÝϼVÄ<S6{ŸÍ“ð$¤ûÝÜ~"u¿›~öÐý.¦kMáïjTú'—<@Ü·–îHÜ·(t$÷íÿÙ„}Úk&¹oÝRÑ„~“[c¤îgK²€Òý”½5u¿Æ©Uê~¦L~ò³^8ÏB÷kÌ}ºŸòiúÙtb@-úEÒ×@¿U+¹äçymH$?[5L8$ú-å’ ô³0`ø„~Ö qB¿Å¼R~6ß± ýlj€¯]èédýì/ˆ›úÙÈ;`!úùôásŸo²ô"?›4µùùÎLß@~5i±ÈÏ1¤¢Ÿ­)$èýúæý–b-ýì!¿Ñoî—Â_l'”Ÿ|µ!ü]!Iø³2˜ Jø3íwžèç‘è„8¢Ÿ= tD?Û‰ÑÏBbQ„äg9]û!üùk ª'òëM‚"ɯѻ—q _{ŸÅÚã¡_•?\Ÿ?z’„¿KiPCø»´³GöNÀþ|{¦—ðgz6æ†þL‡^GÝï’ 8éo?èjDSêeàŸ’æ&þ®£Ä>¯à?m@”üg;ƒ½°U€²d¿Ø )d¿¯%û]D]É~¡šŸÅPŸìç†F $?kÉJ~×S؆$ù]e¨ %¿KkECó³ÇIÒû-†`$û ÊÁ~‘~}ô„~Ê -Í϶GBÃ’ægKTÊÉ~þ¨^ìç8 ¤ùYDÀDšŸmñôÐÍÏ¢Ò´ýlO›þRý®4HÙÏ1 H²Ÿ\€*%ûÙ_^²ŸðÀ+±ßâN8É~{fÚNÝÏ?fTLÙÏ:ªìwß ; ÙÏ:‘²ŸEUà Ùïš\‡²Ÿmž3Nöó­È‡”ý.n\²ßÕn!e?k°Ôç¨üY4š”¿Ë–!©üùžm´pT]Sx(ô[Ü}-ÑϾ]X¨üÝöÌ_ÊŸYÐ¥Rù³¾hJáϺãu ¶Ñ:> WøÉ¤ü]“éxBù³ã“ü¼­M/ÿj&²¤=¿öíqyNÒÞͽ ’öBƒ ܳ ~oܳö¸î1—ÖA{— Úƒãô€=ÅI%ìIL؃â`½›·¬Wø$ë1ãg ž6H/ ½"x€^”pÎ+  ÎË#ÄyfAÀdÄx–¯wˆ§R!žôb!žšDfˆgÈã9ElGŒ'PP˜g“ì·Òg:-B<¹ÈôñäÖdGˆ'Ç· ñìÛ‚óêPp&9¯2SÝâÉWŸ!žcRõž*O¨÷TR} ^h8ÁzÏ£0P±Þ~"˜ïì=ý»Ð÷`\OÖ“¨¬×.¤òm€ƒõiÓÁzMb†X¯=";±ž’në…̬ר³ê)W¢žóoÖk\,Ÿ°¾‹ =-MÚÓbѤ½^EKA{jú¡òu½—Pù:£nRåë\‘*_¯b,É|½ î(óuæpO™O«bCæ3Ú‹öLS¢Š7ôó{}©á^S{ƒ+É’÷FVŠ÷09yƒW*}Ö¾`‘Ò7˜1&•¾Q¾+}ƒ©rRéÛ=ÿ|ñÞÔìTúl'Öï¥ëIRßÄJé³ …=ò]ïUÞeðž¹õaïæ¾KÞ+ ¾ï™Ÿsð^¸ÿ‚÷ì£øœ¸W/E ÷¬õ¼”>;%¨6p¯Ê¼gN.Þ“,ž¼W‘»>p*tÒ^U'aÏRì¡DÀ™`½:Äb=Ó©q^±ÞÃø!ó­§*z”2Ÿ73ì“2Ÿ•¡RI™/¶(™Ï¥ °e>/2ë=wÐY¯²ŸHÖ{¸ßpžVmì=LÄ•°÷ȹ-Ø{¤…̧­Y {»ùcf°÷tÆ’Jç{4 oD}Q:_«B2é|ûˆ[ÒùÃpRçkܘ%L­o*D.´¾YEˆÒú&#ŸRë›L/—Zߤ+µ¾E•>µ¾Å/Së[\ûqð¶ IÜ[]Tâž¹'(þyŒçe»Ë‚îãixTÄ{Sz&ï]M‚¡xï**#Þ»˜5yÏ>›SëóåÃøì‚÷n®MIÞ»å9 Þ»_“¼wKoÞ»§˜K¼Wnl ÷J@£< Û)õ9HZæK ƒ÷ì(ÖÞ»ê%eO¼g›†ÖçÀŠ*„{U1³{•kL÷ªÚuàÞäŽÉ{3æ¼§› Þ{˜ú5yO:É{íæç«HOë‚¡â1ÐÓÑz^™ƒö.cA{¶8Ÿ¸h¯R¹Ú£U2ŸM× +ö(„,Ïf“ã ó„`üÓZLJ1Aò±$?[ÃðŠô\ŒÕJðcVÑünzñ3Ô“£ÎêÉô{G¨§&°êÙXã7´Z/B=Çkü˜KøõÔ5ûa;ÙïV4Ó¹Æo½ÖøEZÐ_íŠ<%þU¦ŽHü«L%Fþ«Eѡ⿘ªÿUÉ]ÁUË ‘³çà?N*Þü‡jŽ%~ÀÈc‰—æþ5a,ñ“DüW^Ÿé"ý ‹'‡È§ºào´Xð—"p\ðׯ¯7û5=퀿€ \ßÇ}©øSœì óüNþä ø«{þjÄŠþªÖ} ÿÌ» ±*´>%ïþ³‰èCÚãHeÚÔ‹ÿÖ’@(þÓ†’¹À¯(3´¾¡…ƒ@k”Pò€kj»´À®©s`cxF`«²[,Æ>Skï.ŽTOË}>–B ¹o0‘SÊ}êé_ËüÆ €&$á’Cî»Ú׋ÿÖP$¨øoqè"ÿME²ÿ &ËNþÜu/ùÏr‹Ä=´<ñ_øIüëœÉ‹ÿƵŠb+ÁºpÔÃêN"TLÊ VšzŸ$¶Ðû”Ì(õ¾ÒC*½O›„Þw‰¸mIXŽ¡žKÄ¡ž\U§@ÏYÙ„#Ðsp£º ôBíÛo‚ ×øi‡û\â§%sÇ?naküv«êoøL œð®€?›ä|¾±&&Á~–dæ·|‚þ”˜9ðOkâ3ÌÓRÔ€Ûæ¹¾“až-–ý)ÌS‘t±È¯‹ü5Z_Ó:œÐúJ\øoiÚü7†–ë‰ÿ´±fòß#!$øÏ(ös⟂Õÿnvª‰w—)Ê“k‡(OFhÿ£<-Àüå9²›QžœÄQžZ°Qžíy/òsŸÖ|GyV¦ÒH©Ïf×ç"?ÏSp¿àÏ2£× ©Ï&°þî"'Ç©õ!ÈAZ_¿øVBë«Üâ&µ¾[!Ä¡õ]|så¹FÃ#ãØž¯wä”aùsX"Ø/Ä"*ðWdû±î´df®× ²È‘™«£ÕW=a9ê¡MõègÖÓ-=óýº×°d=²±žøyÔ3”&;ê ËQmªG?ÿÖÇš‘‚=ÓŸf»93Ø÷Œc?Iö7É8ö³f0 ZæúÞV­!ZÂÐwÊ1Õ•ÉÄT×™MLue)Õu–Šº”O,ªÊ„bQ“ÊDEY&ê‰tbQÑ‘O,jŠRQÕQ*[¿ò‰©®3¡X|¢QJuý5iÇ,§âÚ£óÏÓŽ•_K;V~%íØáÒŽ©)ýÒÉʯ6®ÓŽý–nð‡^ç[§÷§_黢ÈÏZì·Zþâ´cÍfÐûýý4íØ~ÿ˜ÿü‡Èùõ¯å{%Ëþ[g!;ŒÿõÛï'$ká‹=œ½—˜šÖ ¿ÎE×móEõ\=îq+ûz,[œRÚs?ðë\Ue›•áÏšâÎJŸÓ·§vèúJ6Ö›±2µëŸÊ•ÎÕ&“×q_©öø^-îMõÙM{FàŸM´Ç¦î_EÝqî9c[À çÞÓ¥ÂñƉ}O×*co:f­ÝÛ˜ùf[fì è³¼Ö°œÇÚà úpânE=Ak“‹;wÔcž'-µÀÙ[ê@7ôŠ=!*çH{þxqù.|¦ÏBgmºâé~Jä]ö§Õl¿x`ñÐûuÑ»€7Ûâ^(úŠZ¿óàr±[ë¥pù.Ik_ÛÅå»t`nËàò]®¶oÁ$ˆìðçÐmm½ó¨¸_\ÁËŒ Ûⲇ»0 ÊŒ†>¢qÙe붪+x+ î]ÂöE8h lÑèKÙÏî¶ÓƒÙvpBÖïO)ìeܸgäƒKxÓ†ËÚˆ¿hnØ“„›¡²,ì^ÄÅ{ä\ÂË¡³þp /"ÑÛ7;œoË·: He¿íμ 2Ûxðp/—À4O1ΣPó¨øZ;ƒ¬c¼3}3º½qÉøˆSvã ìþ|+®îÆÏûÂ×Ú)Nw F³tt(…ãšb·´a“‘:þ¦º©‚…KÈYÑøXBŽ2­áse€p·ä^þµæ2ìozq‹xÝ2u5nèw¡ 6p‹cz7¿îÃUæîÂèöbòz<ò©[ m¥Cß]‰ý†èë?ïþºoòC'õ…2¶ÖE&Š˜ÁõU¸OÛè‡nlÿºïóÃåáµ4Ne&£½»ïóãe¼„Ý]=\´pÅ“ƒëDð[·¬Vþ¹Næôé¾Í»‰©övƒäÂUæ>2tßæ‡û„U”¹9¶.¦'è¾ÍW™û·Ø-k”¯‹.¾îÛü,Ô¼Pæ™ø^SuÛéÇ ÜÜ®—αuÁÛÔm£n#Õhàкô6mŸ$EÄÎ Ý·ùá:s÷u'5Ú]Ò‘uu¨²½Þ=ÖÛó¨Â‘u\|6¶ÍÏâ²xà¹oóãþ<æDê¶Ï;x´ä£û>?Üï§êö¼ŠŠt ­¾ª Õ ­žoßoË÷ùYð%.Ô³.ºb™Ñr[&›µ_oóì¸'ÛæÇ¿ÖÉÝZºoóC Ò¶ùÁ)î¾Ø}›n QQóñ5Ë´‹Kî9²wÛçŸ+}Ý÷ùp¾£÷x …e2‡îûüLÔ¼`™]'‚Kúƒ¸/âÃd·m~ðµ"Ì·û.? mØwù¡Â‰GlÛü |áøz}—&òô±«Û6?ß3‹<['ëwÛå§1'îÀwùáQÊô+úßègÀâC`·~ðµrEoKƒkƒŸ²ÛF?þµj¡e÷~&ºŠ ËÍÁurav÷~&jö1o[8ºZ ?—oô³p=x^¾Ñσ'È£F×9áAì¾Ñ5;÷vÛé‡Û¢ÑúF?J ®frt]TÜ»oôÓÑ à#ï‹£«òtußè‡e&,7G×ÉÀ¹>nŽ®‹QÏ}Ž®Ê¼Ñ}£>wŸ"tÛègrWSŒ;¾ÑÏäûÃQ­aËÅKçèªmM»ïôóðaÀ0±ãÒzØ |§Ÿvv:CÙ;|¾ïèôPŠBëšG×èi :ªÅ™mæ?YŸÃ¬]'ÙizÎNÒýã|è¾qUÁƒ‡¼¬&k†²7 –ï,xýƒ˜% ’“¹ƒÃÁ‚ Ä8ÁÉE‰•j=8ÐØìÍóR-âÀyëúijˆJƒ)98p2úôà@~‰·‰ÌòÂ@AGÖ©^=1p°½n >¼À@‹“ µÓGràäÌ(9pr6OœÜS 9pR—:8ëV“ç+Š'ÓëHØHŒ‡ 8±¢@pi¨à±bý·ä*KDlÿÉ‚7ƒ “ ÷J,\.”0ë€Áʤj ƒ5ÐO0X€ÁÊÌ„A†ó' ¸R-sáç AC Ô!„n# Tz $AEl& ö*QN$8¹1v’ Âk“m–åN$ØnBR`[„¤ ÁÆ6I°1óC’à`ôW’`熣I‚J†—(B  ¶ô ÜÓ#ŸÆ+î>@LéîNÇå7TŽÜDAíÕ™(ØBk V  mÔ‹2BÁ1IQ‚r’ª B2ߢ ø1TAîds¨‚RoSì)‘ £$ÁÁ5 I‚ZŽ$(Õ#Ip^ßTÁ!-9Hp`=z‚ 68NÔÇÁ.™5XжÐ|³ bF“;À' vd°`ç^ãÉ‚¶Ò" ¬ÆÆdÁ¦v,¸¸%E²àî*©7’ww{Ñ ëù& zƒ1¢‰‚æ©&J¤ht  &UI‚ƒ©6_¢ É+DA.¹=DA^M€ É£°„&È`ó—Ä<àdöÒÁIOa‚àd}€ |ë ‚¦XAc»4¶¿Ap,NŽ!¤  œ(pTɈ¢À1Åo!ðC#`@`§à•j`‘zjà­‹.®ÀH\ôT%.¦ÅO \Ü),)paiÄ!r™[Š\„xˆ]°F ´¹Nb ¶”?´@É ©"+Ê!âÊ™êÀ%$ œœ M“/t ÊMâ©/ô$ЀÄ‘íæÐ¹gVòßäR…Ôñëa ûÙ,†0(ök²ˆý´¾å`?îøb?0n°_̈ƒý”bîPËì·ä>T@î#t¨€L÷R¡Æý-¦Ö:d@¦Z:è¯q&˜2 ¿ü¤¿5uÍháÌ´•ô§Øï¤¿Át0‰SÂ~Ê€úRÿ”£#øo)4ë™’3ùo1ÉÐ!^:Jüg`C"äpjws… øè Å‹‘%É‹™à“ÿL¨Nÿ-~ïÁô7øÞ’ (Ñ4éó²ýáiý-ÆýÙ^‹èoÝtý!ÎþĿŴC\l)NYBÔû4ÀNÉ*Ø/êI pà]û­ªjÄ~1¤ؤԉýBÈL ðùz+€Ö™ëý¸>å@?n¿w c‹„~råý\Ó²ýÌ‚›”×7 Ð:° ÉÏ·~ðó/EB¬BA‚Ÿw-Ÿƒû<’ÁÓ¿š©ìÐý|Ò‹õèIÖ»9Ÿ8Xïf\^°Þî|¿$ê•Ö„zZO¨WVq ž&«Éz•@°§Ù–h¯ð3HÚ³h/à»Ù¨ŽP®û?b@…½g ¨">3´‹å–< |Úý'O;ûÒ_á%§ôÇ„‡ôW9OéïцôÇu¸‡öǤ<‡ö5Kû 8 í¯+ÎòâyÆ7íï–ŽÚßxÇ!ʾz`¢€ïfîÞ>[pôÖþRUðÝRÉRû»d íÏ×ÔîÝ‹í1poBIQ¸WªèI¸WC–¸í:p¯0ì#qÏ^3¸Œ¸WèKܳí ^ÂߢžpoíÍ{(¼W8ýLÞÓ®®É{6™…E¼§”PÉ{…;&ïù6‚÷ÊTà¥x¯2sEò^H°Á{‘‹xϨ &ÞSÞÀà=æ0LÜ‹ iáž Š÷Š4Ðà½è‚÷ —µ%ÌðÙÎÎß|þÉä½radNÞ+Î)à+œi'ð†E%ðÎÏøJÑQ¾r¾‚äGÁ{åÞ³1èu1&}Á{…ù“÷ôºù”"1‘ÏþˆO"ŸÝ6pMÈWšÄAQ_ÑL?¨O®ÂľҤT ûÊ‘ û”|1±¯ Õ#ì+  õ$Kè+šxõ•Wü§EÕƒ …|UQgB¾z+ŠTÈWoÅžŠù”¬&™¯Þ"8A_-bTqŸvúNîSÈä¾JY<…¿ªùf•iRøSC õŠûê£XN—1'÷ٶŸûªô° ¿JOW _e: D¿Ê ý*Ó¿&úÅQ~–ú~ZïèW©¿'ú•ªz$ûF0¤îW¤S…îWë"u?eçKò‹o*t?ÍB’üâ+ ݯ(`1ÈO]:ɯ(®4ÈÏ>'ò+E—"¿BO\’¦…}EIJ_‘à²_¹é$ ì‹k Ù¯p—Ä>»àwôga^øÄ>íï—Ø·Ø·ا®0±ÏºË—ìW˜ø3¹ï°`X- ùð+¢›¿¢O*À¯T©‡’ýŠ<~J]‘àWÊwð+…½j€ŸÝÕ;þSÃB‚Ÿ¶óNð+L˜ì§!3ÙyrýŠ|…~EZz ŸY@‡D¿x1~%$=¡_ኑD¿Âà¼D¿Â¥‰~iú1)o’_áå‰~qò@¿8Hä—‰ü ÓŒ&ùUY _U¨F _e|O¢_eDR¢_åt›èW«Ô:©~Uñ¡úU)¿~QI¨~•‘w©úYÖZ8®VEÏüUædIÕ/‹Pý ]9A沃›5¾W¨½$A9Ѓ%‚oD½@ðþF‚·VÛ F¼§H0"ƒoz’o­fKÔò° A­'JÔ(D‚õVÔ¨HP{š% Ö!^ >üº’Ÿ›A—ÁGËw-ÿ1`Q hËâ¾)ñ6•?7$¶&uP Øôf;w‚9”?†ª$vl9Âߌ‰; äÀÁúþ¼8‚ñjFªŒ7N¦’<„?n¡tH8rè~‹1Œ©ûiF¨ÅI‚3–+е$ IpªM N¦%IœÌæ˜$˜‘àâx$¨ØùCø[Œ ®ëë­û-æ¼K\œ‚ËÇ÷Б¤Áª±QÇrÀñE%PžÊ‡Ì8V˜H÷kbààjÄ@£´·ì7cž0p2}HÊ~%–ÊWYµ*ÙO±ÃÁŠ/IœCr¢8p2ÑoràR@jp }ûïPéC ‚ò&*‚#AÐ"AÞ«÷«OœLD› ¸´>:@P‹µŽ HP©J’—f» Á¥™Nà.PßÊßšÜD‚öÔ@^"ÁE%5HP;ƒ&./ ½È }=Ô{5àêº@àz-4 æ-þ- S'®õm) 9`Ÿ—øç›U1à³0Ñ÷† úÖI`C¢ ï®õIôÜPŸÍPÞâ_¬2š·¼@pÉO– ¸šÖý ×ÐòA‚`¤<@½¹µà'@8‡È4ý‚VwA˧¨˜P`ä úN°¨˜(hZ )® ºÄ†"$AmØz¬ÔZ( _ ÑêíØÊU~A³ò‚yß¡Þ#* Pëù P 44@eÈ¥€·VÖ…¨„¹ðZ‡x+ì2–ÞÜ… $hƒ ¾HÐNýÖ}·ª—h§†z&ôz_„A/o °J¡ÞϷШ šÔƒ–Ûé~i€+D0h×|½b@íÆë+ÔSÖýƒvïëƒ~ï' æÃ zvü34À . ƒnyÁ å(¯Å€Êî,¸¤R ®XÐÇ \0YÐÇ0YÐŽ¢G´2Ï+ÔruTÄ‚~[/´sá! -s`=×Z‘FÆV¿ä3Ô¯æs° 'ž|-4 ®…(h8š„‚±Íq àÒl?PГ‚½Vfs .¥Ó´×ð¼V.JLÁ‚f€{B,hmk½X0ïJ,h«½"@—öG ´šñòœ—¤ƒ”% ¤ Xú7ôvñP2`©ïÉ‘5|¬!jgˆ`A; ÒÑí(¸]G³Ñ®ùN«3-Ugßeˆ”d¿xKèïE³a3yV–Ìõ%³ ÅÏÌõ5=;óëÃ’õÈÆzâçQÏ,^wJÃQ Lª„¿þÖydž…xÙs8óŽ=A.±IkëQà‡ÞÅ‚2GÙ¶–ßp² õÈ2ôcÍz€y4ª?}ogöèk¢å¬) ©¦£ŒjÚKA‚#Õ$ËQSbMg™¨©ZLÑyM²œ5E!Õt”‰šZ÷ð°£&ZΚ¢j:ÊDM‘î,j:Ò©¦(¤šŽ2Q“ï!òº&ZΚ¢j:Êüæ–mø¿Gª_IˆöG[ž¼gWcÖ³£‰ýÁzó5×·¼fß¹½Æû·×¸;ÕL•öË5–¿üëoɸözì?½ûàïôŸ~ú…¾:íŸ~žï:þâlkæË¨{øþ3ÛÚî þ’lk»øÏ²­mó®Ú¦ŸãÕ‘þ×ûWûÁ_̶6ÚÝ \>yu݇ÐzÁ u1¬x[t-íipB‰5öü¦À ¥ V÷‡íkƒ0Û¸a_ôÈâ÷hŒFXè—F³µB(ÜÓ Ëçë ±-ÃGAi¶c3?U.™¡©š GÙ6øžéðÄ£ˆ=;:¶;ª©Nº5F Nv,Û¼2YÒØsp*œÜagôþpò͇ձU¹§%£aÁe>á ƒS. aÅË#ià¢õ›×ÍuÈ ±Ø–õÅ•µx|cÓÖ!sýÞæ€þøòƒ‚cêÍeÈl¹- >¨¦·0žÎŒT.v/í#–$âj°e6oë°LŸ3$mŒÑ¡štné1l*1•µÊ ëæJ‘(bÑuîÕãïÃwáj=< &ÌsGîƒ2å†j2¸%è0í½qjžU—~—Ûdea®îu¸ð†/$æz+Ÿ£¾§S‡¯!䲆3Ï‹>(:§‡ÒÓ©×`1g(£ z†¹.ºhÑŒÍØV.û‹¹7æ†#G…Ó /ÏvA›L±„çÇÝ¿ã×atC1®eØ^YåܺbØ&W™…:ξù~(ä³–VžN¼Ëä|5øQp"KæÇåÚFô™xÝ]üˆÐVoÓ’"O: Ü…7¯R°­ší?JËÕÞ8¤ ­á,È›íÿâ§e«v¤½îg[¶tU»;¨‹^Ožeõá. 5Ï;–GM_5äLë}Éî';™v"˜g\3­-ó"÷}jú±é k?ž âÆ&ìžñ›Eê¨5QÊ ¶­\‡Á_ö´4Þö¥ÚKwÀî~;·Ð¦H3ï^Á´µÃ»µ{äLk{¢àTàoe Vó6'™{¸ZcwÛPûp­Ýo»RŒ­ãX& ¶¡ 쵃iÛ0ß]»‹”¾¼»²fñ·­ßÓ73²gÕ¸ßÈ´íŒ*ÅóõÝŒXÄ?ïi»a_8F#MßÍÈDcÐï´ÝŒi­õ£žY±«švÄœ¶›‘3mg,ÇôÝŒÊ8ÏŠMź!þ°|7#/ðÎi»¹Ê„À †Õ5¸’nVäãð'1QóƒaÕvpóï{únFjF;ñ팸™8ž†ogÔp=¨fø¸º´(iÖ‰qÕ2­£™Ø†FnÀà<};£~–xÇ7ÅñaaúvFVÍÓ63ò77¹hnúfFöLòƒ¥bPÝØŸQ—T±i[ùÞ‡ZÂ:}+#{NÚkn>#ªu/x·¾›ÑÄ©+.f`Hµ£N=1¤ÚFØî Ÿ¾›ÑãÃoÙ¶3òŠÕ |7#{.‹›®OÛÏÈo@±akì»"CªíbŽ^÷3ê8 wÕ ©V¦¡lyíN:,RíäGuR=O|AÍÇT?ÊÝ;Ó·3Ø´ŽõLŒ©˜F›aùWí›Ðø@2;òÐùÞâN›Ów3ZØAaGD²Ÿ _¦og´°¥;>ßΨa<ŸNÛÏhaŸ|u¾Qã¦znh [xh‡é»q—=<ÒŽ\¾õËŒ‰´ú, ËlØ®¨?ê®#ûåùØ^F ;á¡ÉlÅÓøxm£< …Ø6F 5¢?³]Œ*6ˆ»Pƒõθ=*'ö0Šíà¦ma4PÀ§v[yWeò1ê,(1Ú±»ù´Œv©ÃûÜ“…cW½i»qÇ?| –Uj¡¾CßïÛ œSM„¸ú>|îÝ›†P^%\1ö]ø *µ^õÝ4,¿ìGÍuj“{ÖàÙR|ßvtžkä¼1_Ic†ßêĆEçI}Õ„à…Í¢Nq΋0ÅÁKPO›. `@|¶_FG%êÂn1xú6ä5lÙ„NÁ¶0Y8 ÍG‚îÔ:ã‰1Ð3.ׇý¤8> +€áÉ·É„— ·ÆÕ8ØÿÖ”iйØÿºB”I¦«âµ`:F–%Ó]L”LwµïLwqÓá`º«‹Ïu· ¨»&pBÝÅ!, îbÌyBÝM4¡.3¨îfükR¶·Oª³(ŽTwkæTwsr–T'Í+©înâ´Iuêd@]á6D uêcê Ó 'Ô•Ê{ ¨3gÔ)H1¡NL uZePW:&IuŠôOªSuR]aÆ•¤º´ˆê Ó9&ÕU¦V%ÕàQ]%rꬷýœLg1ÒŸé, Ø'¤«d’D:Eb%ÒmËõFºÊ¹C"ÝÃE®‰tu ³„tu…t•ŒDºpDéf]‚3"ëÆÙ‰tfAsÒ™k -¤3 ¼)d:{ŒäI2]x/Èt)Ö^Pç¬E¨³!36AUAV„:8«°¬ÈGf#×ÍèŠÅu¾gxŒ\g–ÖÙ‹o¨˜Xg§"úë<±™#Â:;ŠPI¬ó4e>0ëÌ‚‘—X纗_±°Îó–­€u‘.#°î¨…X>™àºã(rÝÔ>wÁuj‡““ë¬LEr5z¼qï $×¹T‡2äºH9\7;1o2^=PP'©÷‡.ª —¨Î~V ©nj«lQðnEuád ª³¹ÉTçéÊqu¤:_ÞzHu–)œGª“#* ÎŠóuæˆZ/¨‹üøuž×Š˜7"µîJPg³„ Î“ßû% ê<Ï~‡Pgq<¡ÎÖ“c"CªóôN(Bª;Š€ê"p`Ջ鸰ΣñJÄ:r{‘')‚‘ììT˜Šì<§j–î©Ìwk¦$ÛE2¶`»9lgÕ€¦ÄvV†DH¶;,d»È….¶ÃÆ–v(°‹´ v‘¦=À.\„v‘ì)ÀÎæ²•Çauz`vsªó#ØaůGÕ0ë2Š–©¥ÅþsqDK0¨Cðžß¡.ýŽ‚:·Ü'ÔeîtA]fº ÔéÌ$º ñÒ¥ïRH‡;œyÈOʵ@B:?Š€ ¤KO%‘Î#Òpr0ÝËÀ4èÇÁtî!…ËL‡\ìD¸ ɧuV0²¦C”J8Ô¥s”Pç>V4u@\à:Ãü.€:w¦&ÔaÁ4þîPç1`èGu~®P×¹aëŸué%ÔeâwBÝÕê:g*Ô§m<`Pç¡}D6‡ºãÆuî„Ç.´ê|uHzá†›Ðæ! ºÃ) ªóíEOuv„ÿr¢ó°1|üËý<Úœ‡Dç®_<»¡Ÿƒè¹‡8Ñ!8 ‰ˆ_s³ ý7c‰tØCÜÈØ-ø ’ŸÕ-lÌyFTÉ¢:ÛøÐûò ºØc3¨Îv]Æ OTÇ-yª³2 õ€êÂùTg–êlÚI|$ÔùDEu¾±¬O%uKI{êÌ,ÔeÅ‚ºÃB¨³š+ÀPgeH‹Pw¨WgBAݶè6 uîSº‰yuîœ!dê† AuØ‚ÖËê¶åH9Õ¹vRÝ®˜Kbݰ¹)*Õ › õ“êÆ½®7ÕûŽSƒê†M*YT7lZ÷àÜ :ß!• ªÛ–›Œ ¨ó.Z„ºá u»L%ké†M L‡=5¡ÝéF1‚£nÅb“ Ôc[‡–¢÷D¦¶±ïEaÎ}Š6ëdPÝ®µHaÖm q„uÃv&_ëv™%¾Ö Û ø…uûå0LZXw”!Öm Óü ë¶…›¸ ëv=ô3 ëüì +PÝ6Ð&ªÛshŠêF™tÉê†Å,7êrNuÛB×=©nX3˜T·‹0‰&±nØÆÃõÄ:?÷K«Ûí’ñ’º]Û®ˆêF­]z¨nÔ‡{P‹ê†MŒ¯S­ÛÕ,\Ÿ¨nØtº“óëFmÌR/¬R©±nØŽÅ€LPݰ·8Ï©nØŒ#©nŸªHsªóscÎAªsË¡Õí땘Pç÷´N¨ó«Ué¶A‚ ™ÎŸ'n€L·Ë0MŽ˜nßÁ ‚s¦µqç1ݾ<.òÓ˜Lççòjˆt~Û7-Nu£v.ÕùÉ Ê€êv™[ê¿îÆŒ"¢ºa{(RÌsª¶t=©n¤Û&Õ ’¨Îê'Õ¹²0©nŸªPá!Õ ÛšçZ ˜›LI*¬óv„@¬;Ëë¶eqöJ¬ógC<ÖyP¤bßÑX7lëëJõαnXø>æ‰Äº]f ëü Js>´ú©$ßÙÐêm«žj7.P0±Î¿»÷úpiŒ¨n[PH·ë¸Åb¨Íßÿ ä-|©“¸éŽ6B¦öId:·Át~J0ªPÈt~®rêuûÝÕãL·+žÑ€u~—×uÞ#Ù€un8ê¼£¤ª¶Æ(Eªs ö’ëêÍxhQw x€’ëê=Ù‡J®³­ÙŸ—\W —Šëüzžíü\õ¥×Y—ŽF+½Îš<æŸÒë¬Éÿ¨×ÙÈPN´;®™z] ¡×ÙsŸt·-CS°;NNÁÎâzO¸e0wfèuÅÙéÏ!×ÙÇ?O½® 鳮וÑõwèu¶¢ õºÒªÔëlÐCÏõºÒ™’Bz]i\('Áκ)4h vV¢ž‚]±¹¥ÿ WµpNèu¶4éN½® ó’ëJ£üIµÎ~#ö‚j]y¤èR­³»"AA­³åP×v^(±®H¢Vg§ôÖ¼¸údju69¹(͹VW*W¢J«3Úµ:ëð™@­®tv8ÔêÊž¢¢µ:{ôõÔêìå`§VWº,µºÒ51p­Înë>ÈnÿX"©® dÁ”RWÚHB©³H!*u¥ià¦T— „R5ÂypWÚ%ÕýJr³Tèàï;:¹´R¡Ó~©ÐMªí©Ð)3e*tr{¥B7©M†B—)t¶®¸G…N®²Tè ‰qêPèl&É(K:£ÞPè¦Ô„Pè”66º)i2ºá‘Rè&†Tè¦äËP貌º<—ºIµ8ºY ’èâšC¢‹2’èâT!ÑÉ™]œ;4º¸«ÐèâÎC£›Ì¥š]–‘FwXäLŒ+–F—ç’F'¯jjtñ,B£‹£B£‹šC£‹+ î°Ð£˜õÔ~¶ÑŒ¼ÔÅDäe‰ÈKÝeF^F™ˆ¼ŒóH¦ËŠ#ò²~—éB= ™®¼5º9N;E¥F—e¤Ñ•†”Fòjht…««S£+Bity.it…>ºÔèBØ ŽëýS¤ÓÃ:E:rOˆtÙ-4:~чF×(ÿ<:LS ‹CB ãÒ©Ð¥åPè®·Bg(Ç0K*tl¦B÷0.=º'¢*©ÐÙP€¥Pè$†B§ˆ¥TèXp(tÒS¡+¾PèäHO…îá 1º‡wž ÝÃÙ_(t)!J¡kŠt …®që·Tè¶e¼"/M ¤x&‘Î’ ƒÖ$Ò5MÛ Ò)ìè÷÷J….ËH¡Ké/:ùÓC¡K Q Ý`C*tCRè†Â¸C¤ éO"ݘ¡é,B–²ÆU†B"'W‡H–é¸nãé %E:΂•NÑÁ)ÓI‰ ™NãÔ¡Ô1oc*ušÏ¤RgY«ßJÝ|ËtÚŠ&e:s»*q§PbuÚd)…: ¡ÓMFX¤L'b‘L©¦S¦ã!Ó)C‰d: †L§6d:…†L‡H¦«ÒÜ Óyâl ÓÈt)TR¦; C‰K–; &ÓE> Ét©jR¦Ku‘2'Y§a}½Êé’1•­‡)R¦SPÈt ŦL?%ÓÝÒ%ÓIŽ”Lgþƒ·L§àÙé¤ J¦; é.f ™.tRét—8$Õ…\H©N¬¤º‹éy$Õ¥f eÄû³Üc¿šOÌs=¿=÷Øuÿ÷æû¡i,»êö9“#}oaÞ~ DYJ5EV1Õtd‹š¢PÔt”bM™UŒ5YÅTSRMg)ÕYÅTÓ‘U,jŠBQÓQJ5EV1Õtd‹š¢PÔt”RM‘UL5YÅ¢¦(5¥TSdSMGV±¨) EMEî±Õà6øiê±þ«©ÇvóûúƒåØÜà–i½ú¯¦ûy÷o¯ñ‡Ôc?¯±üå×X–¾ê{ê±ßÐWÿéÕùþÐ3ÿégèÙYÿÂ×ù®ã/N=¶†OVšyl?¤ÌþCäùú×2½’‚å¿þ6™ÇúÏNòÏÿý™ÇVoî æªô³{dZðm8W›¯>°gÂE™xÏà ¾¨ ¯¾ÛYëÆ·¾à› °Ö¸à f6èý6à ÖZï5ÊCã‚®`zôרSÒûð ¯ñÔ/.Ù^8I‹Moö¿çw”qUfÏX ˜j3–ý8ë÷¡ðÉóóúâîe<ÁÄp]è_c5må̵|!ÿÛ†ø%LO¹„íiàVLÎ*ËÎÆ=Dð¤&Ös=ó²`n©tá[JñÉuÉË|×~Ó/_ëùÉÇËDL÷ƒÓÕ¼L¶óX®Ÿ[Óg„°LÌáÖ>‰Ü“¡ ?ñvlÑPûÄâÞµn¨+{¾Ë´ü¾ç²Ýå •>¹$wYú$fIC“°Å1PÜý—¥dø¸n^PcÃ>Jİ–í¯ ß½»X÷¸¤’¯…µtÊ.÷ \pS‡>®c»'jw&×ó…űøyß~ÑRŸÍ)´s•ý¶×VÌcê¾Óm©ÐB;—¸lËsClf¦³,¿øÁõòÛÒú‚‹õ —Z–PX´„Õ,ó‹ Vy¢‰Ï* ¶ ðãš°ƒÐž˜^ø6—±›e~qßŒŠ»4?eÅ›ñ¶Ø–YŸŒVÛÛzë“™ÝÌ2¿Îøµmy‰ÆŸ,ΤméTB»ÞÀmš=*©¸msºa›[¶Xï£6 içžkqóúÖî«\MiÜxå¦nÉŸ…+ÓÀ ‹‹¹I(*Þ8¯Å‚RUl<¦Q ¥nb–!]Ñ¿méí%,nË(RÂ5©ˆ.5"ÃÄ~Û²¨%â–mEHC¶[¸±!p[n._Œ&_]rełչ-±Vî}ÀŽo[j£yTÃî7c‚·¥.„§Ò,GµXo[°i“ ïß©ëmË‚B*o»Y–²-Ú¦BÌÏGc» 1«ÜÅ2…‹9%4 dRm¹-ó{mâeì¡´PÑÚ–†)Šn‹g™»õUrO!ÏÏc×52½Ä¶`S!ËVÇ÷`» MÅn» 1}ùÀ™lW!å¢QÛ®B–J7f‡Ú–Òq KmÔv:Óàm‹‹ˆ¶ÕOôøhi2 _Œí)´`é¸ÛSÈsçU¶?ÛRÈõÀª»$ßZ~–¶¥Úuž  &4ò¾mS¡Žå“|S¾©)<ü\lW¡†Zp×A g‘ê§UR&-e(WmËãCçz8'Ø–V¾˜'¯Åv*8ê–…‹0=aƒ…7~ñ\Z†ŸP÷eÄ-:óÎU˜íòŸƒ«ˆµàr[àc°t{|׃ëˆ[Óhd ¹$;ô|¹¡…ó؆B>pn(´ZÕ€eixï·¥ãcn\'¹-£àDìƒmC¡ö>õìHþ×ÕflC!O‰WtnÛPÈn¡Ç02©ìöè¹'ƒz|>“ÚnÏr2\¡Cb0ƒ§VÍÍ"ŒXè·njz6ÃŽí·öO®-îñyY0˜ ÑsÎmáêâcG}<Í_a=\_܇޾¯®7ùúQwdý¤'"¼ÕÈMŸ÷4~C݆õ 7dð°Läþ›ê —ï0šºskrJàQ-Dì®Ñ4r{úFáK°»™ï2£B<¿4èÚ?.¯ð°›Ið“³|@ÝSZt·ï&$þ¶‰….Ñ€/¾¨ÛÆF¿|ŸÐÝ6éï†ç‚ìÏ)¹Y®Y˜në™pí\{[o Tïõ d8Ê0Gê¢ ù¶æññ„xAöôýê'¼fÁhjk3qC¦${žBÍnÓ€'ŽBG”Î —fÁhº¨(.#ägý­9ÆNtóc‰n ´º1Z;Ñ- B7Ž:‰nœº]Œ>t»0­ t»èµ t»¸‰T [£ÐíbrŽ@· H ›MLùôv!ö-àíZb5ÂÛņ€·›I˜Þl/Ð!á- ‚·Z°›¶\'»ÝãG°Ûýˆ¼œÝ”À,ØMÙÊ‚ÝÒ@v»™&6ØÍ6U#ªÝnvÁni »ÝCIvS.3²›r'»ÝÌ=ðvsxÓîéoå⓼f xÓ²ÁoŠ»~Sž³à7Åá¿&ª&¿& ~Ë*Éo%ñŒüfI€ ZD¸29©ÁF 'Á•¤3\pDp…ñÃIp‡…§„e"¸cº®^Dpµh6)„S’³d¸MìyÅpò*$Ãí ç ] —5‹á˜a-®6´B¸S œüÉpõÑÃÃÕ¡¹Ž®N)Øá¦BL„㣿Õ@Pñ›-a‡Ë4ž ߦ¿ÕLE~«S³0ñ›\#Éo_ÉoG½à7[Kû¾åµÞ´þ"èÍ|.eÓµq²L|³%|©Ä·p»¾Í'è˜ø6Ÿ˜³ߎsß´¢$è-@Ao‘ã-è-ƒ½Y´ß™Ó[,µz‹½IƒÞÌ2_ôvEz3Ï¡ëfú¶ u›9‹G%ò·ñ¾ oæ1ªÞìTœ‘Þ"”ðvÖ a•4àÍÊ4¡>¿¶Ôœ ovnA!àm¶NO ÙM®%‚[¬ r‹ämAn±†"ÈíðX9¹¯„äfÙþùÝÜN È-ÖoºÙ¹…š”&u¹à6óNq"{Árn›=|Ø ¶G/Jn‹¼qn‘%.Àíð•ÜbáH€›Ž·Ùhù°¸-nƒÛ|—YV n;uä6;ªÜæ£ð‹ÛÌ¡Æ'Nt‹¥%nÇ™ˆn±œ$Ðí,Ãèò$Ù-–œ»ÅÒŒ`·ôøÝbŸ¢›y YÈ-VI¹ÅRÁ ·ã<$·XÎäf@ÞÉíp’Ü"Ó\[än t‹Õ%n±$…è6g¢œ¶‚=,Hg¸Ob/X¦° v‹¥±Án¾+YìfQØô–ÝÌÛHÇÙÍêá×Bv³êØÔÉn¾­0 Xlþ¢ÛQ@‹-c,"ºNW¢›ŽðZ}¡ZÑ-ÖŸºÅ¢×@·X0CvCÞ¸ ·tž Ýìi¨Ðz‰ÕXBö!¿YÄñÛyTãâuÒâ·Xûü‹ ‚ߦòßb]Kð[ºoÅo±r%øí(C~3·+>ÂÈ3‘ßbÙBÊ“jøAF11Ó°1…30œ9çæÉpæT‘ál#‰ €áÌ=vŸò› Ïáì¨c`8óŸuˆk`8s„á \l !„3CE \xÿ€p‘ñLg§ ×éQänb¸p¬‰áÖ“ŠÜ”3Ž%Àpá¯ÃY émt&>¢¶ûLÄ&ˆs OÕú*þÐ( !Ä™Ð×èDÔ}“áŽ#]ˆTˆÄp±pB ·êÐ!‹þÃ&±Ë.k Ãå“!ÃÙuWêmE×ÝNN™â„pG œÙÛ‰py™D¸¬wÁåÓ[ó]n)€\w8ˆIp‘/î´áteApè—Ý€‹·g2øMo–øÛ¼¾W |;ê½uÞ¬yHJ¼e²[<¦`·£ÐÍ®…ãÙí<ìm†ìvTt‹/0Ð-/Ÿäv<%¢›½ÒþRßìZtf ›•j‚ÞŽzHoÇõ:¾Ï…üvÔâü–×O|;ïÄ·è×ߎƒ@oÇõK}{˜Ç.ðÍGä—úvEõ-+^íu-Rߪ(Fâ[Ö!ñ-ŸÄ·£ Å·§Š6$¾å³”ø×"í퉲´·¼Joêø$½¥"éí°Pz{ªPIoyÛ’ÞòiJz{‚Z$½eë•ôvÔCéí¨‡ÒÛQ†Ò[Þ¤·ãJoÙ†$½¥~#é-¿kIoyç’Þ²fIoyW’Þ¹‹ÚÛqµ·xS’ÞòMQz›b&IoG JoyS’ÞKjoã­½e¨½—·Þ£ejoy=ÔÞR4£ö–M6Ä·¨7Ä·hÄ¿"¾¥Eâ[Z(¾å«:Ä7ÞUˆoy=ßR sñ-›±Ä·ü¤B‹{þ–µH ÕQò[^Œä7Ë©¿SËžOú[´Éoiï¯Eê[~QRßòáI}Ë3K}ËG%õ-_”Ô·£ Õ·¸‰où)H}Ë÷$õ- Ô·¬„ê[Þ“Ô·üR¥¾×Bõ-{P©oG=TßòÙH}Ë'!õ-€Ô·|~Rßò=A}Ë«‘ú–7)ù-?(Éoùh$¿åK~;jž×·ÞFò[~à’ßâ(êoq!ÀÅ™B‹gÜqTýö9‡ w”¡ í&d¸£ e¸Ã2®w2\ à”áŽc(ÃÅ“.ï[2\Œß!ÃE[ .ë‘ ÝBÈpºš%XÈoHMqÈo¶\ðˆœT ô@·K:ŠÐíE Ý.Ñ„Ðí’J"t»¤´ˆÝ´¸?ØíÒÌ^ð¦åoÜ12ØM ÉÉnWÄ9’Ý” ØMaDÁn©Hèv}G·4Ý.Ì=ƒÜ.6» ·¸ ÛXEr‹k¹]" ‘Û•(7^)ÑÝ®GjÑ-¥Ð-/Šè–%ˆnJîèv±éÝⲄnZ±èv j…nY‚è–uÝò²[4±ÛõM~3Ã8å·ã: oyÚY^'%¼ÅÓ¼]Ñ‘ Þ2ÞLðvÅ”MðvE7/x;ÊÞ®èF…o§eéú¥¶‘ߎëéÏñ ஘ àŽs“àŽ2D¸´áòÄpy}b¸ã(B\>A\ž]wõô÷™HqW%¸ràŠB%À•pÖK€ÓFT)À•”WBmW’”næRãüA*\‰q *\‰ Wä¼—Wü(ÂYªq…UÂoX()±«D¸¡¹RáJø ¤Â•d„ Wº<ßRáÊâ)® ùå¥Â¥„,NÙèS…Û]ïó ¢ô| ¤?Êp¡MK…KMY*·ÌN®„B.%e‰p…Û8¤W¯P)Âiãíáê!ŠTájkJ…K[*œ¶ëNî°P…K±Z*÷þ’§ øá E¸!já꣈/‰pŠ•O®2GVªpUjˆt¸T¸¥Ãêp©“K‡«M-:œí÷ûÂ8³T fÔáê"%®6H‡«¡|H‡Kñ_RÜÿÃÞ»ìê’$Ëys>Åv èÍ̸ÇDAÐ( øEì#6DJϯt73÷Èﺢ!ˆ‚FU+vddþy/ÌݼF䤸Tà%ÅÕò†—ÛHŠ«¡ðHŠ3 ¥¸ºC1£WWˆ~”âRe—g'mÐâRË—wŒL-.Ï—´¸vIäs)îøJœJ¼§×´è'!®…L$!.»P‡kEÀ+N¦©Ãɵ1u¸‘ìÒáŽ>âZÕ}!îèA%®….#%®E죔¸ÜJJ\FH‰K9_J\ UHJ\‹à|)q-Õ0*qo %®et¦+q­ëÝ"%® ÝRâÚg¥õáwDJ\F?H‰Ëp)qª—Jœ¼'S‰“d*qmKQ‰kKHqÇ6”┽’Z\KZ\2H‹;¶¢—áÒâú­xiqýþÔâúõÖâzJY”ãä„™r\Q„gìä$Êqý;9N98)ÇuEª†×éÚ•r\§mWÊq½*ð“j\W9Õ8l¦×Yñ*Õ8s»x«q]á­¡ÆETJ¨qñP… #¡ÆÝU©å¿Û4,—ð@:E锕 …SnµpJi…N¹÷ᔲýŠxJ¹œF<¥,D#žRn¥O9¯o§²;Ã)çV¸%Ã)%øGðœ[¨‰— J=ß5‚0+J()4V<ç¥Å‹:ûøXIoüÙQí¹$˜¹ÚµõÌy!¡Ã\–4ÌyK;a.+I ææU¯ !‡¹,ì-˜óºÜ<3€¹§Âà sYª[07ÍÇ‹'âv'9%{ æ²*¶`Î gó«˜óãcD"hÎǽNšó} ?æ²8¶hn^*õ*šóÒá"&¯Äeºê™çŽtWÒܼT&ç|rfÄ=-ã›P¼ý9¸~âÜ3©¿"·ÍqÎýãžó}Ož;ÍܶŽxªr¯>Îs>g–ÝýúŽ=9ÏM3¯{ñÜÓ °à9oá•Ïù8ƒäè<çõÛø&Ïya8'ëó ­œ6³›]ëu|à¹týϹŸ ²ÒœçÜõOdæ<÷luéMž‹ÚqÂ9·Œ¸ËB0p.­…sÞ‡/-àܼ•ÐL¬GQ¨¥;³Ý)Fèæm†Rlq¢{útaˆÎý•'çH÷ô™ú™@:77¼N¤›f"xŸ¡•>ò+-Îm %»9ÒùVW¦ÅùïÞ'Ò¹u /îiÙêHçˆRËéÜ5±*QnÃG±G8#ŒžîLyC]Bó?‹ÁéÉvEêÑ¥ÿ¡ˆÎv…?ݰŸ,÷ü9ßqîPÈ 4°ÜÓ²õ¤€åüÀ ¯§{ÌogBœÿ>Þ @9?·/IεJ€óê½â” ‹EœÛ)ò©É¹"#¾ArOŸ¸}ArY¬Q$ç¡t’KOH‘œ·¼¹‰±78ÈÍ;óÝÜcÓæ—Rß.xü¤²vOÝuêqé4)ŽK HqœÛ;.‘Oï¥Ç‚—Fâ8wX\gX¥o¥>0;µ‰Ád‹û{ÊR ÷´hNCóó)$»àÏfJ±ÍAÎû(ŽFFqÀà¸g#™¥ýѤ ãav?'¹¿ajáwx„±%<¿~y#vQ‡?ãV 2Ö42ÿ>\¹¼E8øãpõ*fi¼^#¨åm1 ÿ<Æ©7—Íò7ªå‡mGþ£]ž/˜¯Æü9—°õÿ¤KØnŽÛþ÷>¿»Ëü×ë¾û9Ç:<À8Ö馱²—Æzù‰a¬Ó c½¼Â8ÖÑ‹c½Å8ÖáƱN·0•½4ÖËSŒcN`ëô ÓXÙKc½\Å8ÖáƱNÇ0•½4ÖËWŒcn`ëô ÓXÙKcý ϰûF~øÿoöûLÃ~ÏÛûç÷Ûø»wõÏ?|b_ïï_x\ߣüaã°Û>»}ý·îv¼ZÿÓßÿ€]ØsŽ™_|U$,ïÉ®™ÅbŽq, =“8Ï9Ž5n/ÑõåÉÕ ØÛKfG3Š ¤žÚ\¸U°R•Ÿ–^$uc|[Zžë¬ÈoKð:3‰Ÿ¥K¾½šÌWZyY Ô™Ð?Ÿ9ÕOìz3Ù8Rao3¶Ù§ˆuof‡æ¬ZÄcóÒï_Gþ\1·q¤È«šÎ»ÉqÖcœÎ::7×ÒŠ¹eè&• XU¸èi™X·Ò{Ka Cdo•âu¡¶V™Ÿ¿æ :Cw©Ö°Õ*•aaØU¬^·K42õ*•a‘V¬H1Ka°Ô†§X僞–~+Gmp«Î˜%÷yZc–äuTž9þæ)®ëV4w]ëó70\=¢„J»³¤…ÚÒ®®È5k‰˜%µ0\ýh©U¡ƒØykgÝ û›Kб)áê˜UÚ`È•¡§…áêæçÁq&âdo™¶”¶0;C±Ò6âdo¹•~!NöŽG·_K¢®‹•b=ŒÛË{?VÈ-Çô°wƪߊ>)½!HVJÖÓÂXõ;w«ä+4¢°©A¼þ†5åÝÂXõ[ÅêÝèǾÂ:@æô ‘à™©òoh'eÜ’-·ŽÏÊÑqŒ§ÊÊ5ì‰w–•ZØŠ¿ÓêÕÉÞúZ«T¾/³2­®úBOËDöIQzi X/ŠÄ(Ï RŸºÁpõ¢°‹be€ÜYµà¬eËÏÙ¶ÂfQ! 0@+V h¾öm•€Ê!4>-tv.GÊd^fU¶h™JÌìºi§gfÛ0¾·è+\&| ëQ<-JÎÔ«n*9Skle1^½(:¢,ÆøÖ[_ŽÅxõc+FùVIjÅë»ZÅQæ[•F[XàÕÆå‹m1Ô·h½¿,Æ«ûžáü¦q¨W­—•Ey¸j*±(W>”M}8V€Ë¦@\ã¿]!® O([éšUŸ—Ípu¥‘>-’‰ã‡o†«×øRl Å2u(›áê_6¥â“Ÿ­põ¡¯êVæ&ëÐ=- X¯2v¨—ËÅ•FõRî¦TÊzQ/®J1®—²7™k-L>QÖ]½”À©Eíz)ƒ“ *õR'ëÏY “OäôU/ÊÆ•ºòÓ2›°pç.W:Ùß[æz‹=”È)sÊÊ ¯p_o%rjBWYâu7nR"÷*f½œ‡r+S³ûz+Sî{õî‘|‚uÖz.Nï=#ùD;š‘|‚ç´Þ™É¹xxJåÔW¶Z ?¼¡ W”Ë©¯uµB3~x ­¥|$ŸT¯îºC‹¨E©œ’+Ë»FæìÓ¢lN‰Ô±xÔdgQ‹Ò9—®¶x¸ÒÆá÷ZØçµq^Ø'«œÄ>½Ÿ‰}—¿û®¥U^aŸœ»ìÓK)±/B™„}>ûîðöÝM¤%ì³KÂ>Ä>Ùi%öÝ‘’ì“]Vr_B¨¸OÎÓÉ}G ¹O1Ù}oØw¶`âÑÓÁ}ªUè§@è ?ûžäÑA~G É/BšýJ‚ÑO±ÈA~•Eì‹ÐäÀ¾Eì+ò‘!öÙWGì;Zd0%ì«w`)±/Ü®ûªÜ’û"49ȯçüª¤¹ ¿°® ò‹ b’_Iȯ&ç‘ü"7ÈïèCò‹â ¿ˆò³Ï ûýäŠäwt!ùEàqŸÞ‚¿gøËÃüEhrÀŸl¾‚ýbi#Ø/â|ƒýjЬØ/âxþjP±àO&ç ÇÈMf¾ öË_-öË.D?«6÷F¿Sk¡_¯Ð¯Éi&Ð/î ­eܱÀÏx{:øe²ÀÏZxŸ ürÆ·çFä>›é‘ É}1)îKï5qŸõA˜ª¸ïÜJEéa¬-ýΗ~†,ð³QxüÎq~¶²ÅÁïü »*x™„AðË hßñH~Ç8Ž~±†&ò³AøTý2Zèg-¼»âÛBˆ~gŸûyÒ3Ž´¨àöþÁ}ç/b€»Pì¢_o^B_úÅ úbƒB³8ˆø2[Äwü`_Xÿñã(´=·šåv-â[nâËX^ßq4$>Û†oú©Ðv…—‡*öv"¾ &ñeÈ·ˆ/ºE|Çñø2à\ÄwÏàññÑ'ñeHºˆÏZÄŸŒ>öÍ `ûº—Ú¾¹JAâ;o)²=N(‰/}A|Ë Î]“ølÑ—$‰/cÔE|ö¸‚CâKG>ßqjH|¹À,ä³–N8¢Åj,J ùVÛ|§9ñÙŸ|-’øÎMØž‡Gâ;ÎçV`»ßqOøŽ“Câ;~ÂVd{¶¨V†®/ðå¯ñåñ-Ü â³âÆ¥Š:ç">»R…,IÛÕÈ òÙVƒ}T8CùB¾ÌSòûZå¸*"¾ó€i¾ "¾cX_ÞZ"¾³ÝWó'úÒ¶QЗWSÐwŽC÷Õ<í}ç6t_=Ž˜î«ÇñÑ}õ…î«¡’ˆúŽ>¤¾ã¤“úŽ“Nê³>S”wü½”æ¡=úòaõ- ?È3AêË„ >Ý8ÀŸ,Á&ng,ÃQAKIÍÊmøÙß6€_®Ô üŒ˜îAðËõ]ŸµPÖ"øÙ8S(È%Ê"F"øÙrízé}Ö§P\,NQ¸”#ðÛ7­óÁ}ù'±ÏF%¨û"!°Ï6œMØ—K¾â>k¹¹U»µP,iÜg-‚Npß9¸/KeüŽCžû=¸Ï0ªEîË÷kÔä¾cEšàgãŠÈ~ç8Ìm¾e%,ö;[Ú8O¨ØïܪâˆÅ~g Ø/~¶Ð/ÏŒÐïèw Ù/‡!úg‚èwnäUÇß@¿cZTå±üò²ˆüÎß¹=ªŽßyxô¨:Z€~y¯ ýò^úãýŽKIô;·ú}À~g Øï8çd¿óhÀ~çV*£Hô;wž5b4Ì.ož` ìwÜkUb´#²ßÙ!@~ç°íãYùQóË,Í/4¿cj~9Èïh â—cHñËQ¤ø}¨øå±HñËó"Å// $¿Øµ¿cG=@µPñ;™×çáIñ‹%øe ~1L~ñ Bð‹_y(~\ġ䗣Hò M0%?ž†CòÓ ’üb#)~zý§â]$øEƒô¾ø¡÷厤÷ÅÁPï =Rz_î9ô¾ì#½/G¡Þ—{’Þw¶ì÷/¹/»Pî;Z(÷-ûó×|ÞnçWr_ìZj_6PìˆÒ>îpi}Ù…R_‰¤¾<I}¹•¾ãàÆ~B¥/a)}9…¾c?Tú²EJ_,¥/†‘ЗÇ"¡/»Ô÷õÎwŒJïØ3u¾£…:ß±u¾£u¾c_ÔùîXf•З7ÞÎDP–2Aõöý>1ÒùŽM¨ó-ÔùŽQç;ơΗ‡'ïh¡ÎwŒL/‚$óeÃŽ'PHç*Ÿ~P¨|Gª|±›PùâpCåÓ~BäËj|w Ú¤ÈwŒB‘ïh¡Èw´Pä;ZÖÇ(ùŽ–Ñòùò7IäËß-‘ïèC/G–Îwô¡ÎwZè|Gê|ÇñŒvž,é|Gê|q$óÇK™/N2_#™ïès£“Ì»‚Êwü¹^¡ÐøŽ!¨ñe—q½ŸÑøŽc›ý¼‡~ÃÄ,ùn:‡Â^8‘‡°·¸[‘RªÞŠXC©z‘²ª^zŠKÕ[,K¢^䆨·>¢ÞâòKhz”šÞ1 5½S£¦·´Zš^„­…¦·fDnRÓ[cIM/Ç•¨wŒCQoiá6D½<>‰zaC¢ÞÒšk¨zÇ8s¿G¡ªwU=Ib”ôbˆôbÐôbõìAá8”õÓ°BÕ [zªz+Vd¥ê­X1¾²ô'¡¨wlDQïh¡¨—±„õŽ££¨KÔ ïýõâ솨—•õú“’Þ1%=E{RÏË#“ž·b!]z^8óg$gˆÊ™ã(”3ÇQ(§Ž."9ã÷0˜3NÊÌ©sÆ ŠåÌPÅrÆžXN C=/“ô¼¼ÔÒóŽ­¨ç#SÏËÃÙåý‹(ç剑ž—ƒHÏËIÐ[ús›Ô¼cXªyǰTóò*IÎ;Æ¡žwŒ3Û»õ¼cêy:8ªy¹‰Ô¼Tj^"5/ϔԼcªyGK»ß£PÍ;F¡šwlC5ï8ªyÇ8Tó>ºúyú¥ãå˜Òñr¿ÒñŽêxÇVåýwlC!ïèC!OášTñŽTñòÇHÅ;†¥Š§A¨âƒPÅ;Ùç§“*^þ©xgË>ï ©xGªxG U¼õŠ—‡.o}§â­ïT¼ü=RñŽ­Ö<Žÿ”~î3*ñîh)í<£Rîò˜¤Ü©e»£CÿøT†l—?²ÝÑ#\{b”õúTJ³‹?—Ž›#¬¨ ƒ?)×ÊýñJ®Ó&õü£Õó.‘Jwl,Ëž¬(Ñå©•D§M¨Ï¨ÏåAKŸ;Z¨Ï-ï3!.Ç•@wôi×yôRçŽT玖Q>ŽêÜÙ2Ï3*iîè°?>ŒÔæâ´…6GÚÜ’ÅgQC”}œ×PåŽ1©Ê›P•;[öû>UNÃR’;6Yåøçµ3jÿ”§?©ÃåXÒáÔ"ÜÑ¡¶W*pñç>UÚÛ±ùx}êB{;zÌõ:b oG‡]?ZÂÛÙÂß ÂâO­çŸõü7«ó/±í]õê_ñ•ùçù© mE–õïvKCÆÔÉ`“q]‰`Š®…Ål_¶¥f…em¥ 0ÅO…í–‚Z‘gÙ†EîM`˜lÌ’Ãv&ë‘Ã"&8lÄVîõÖØÜ/B”ø¤œ-[ ; †=-•}x÷FRO`ØÎ ÍI=ë…afÏMÕR–H‰íèâÛ¥@íÐØ.Å\‡Æö´0vJ[l –ÙCÒØ®L¢£Æv}¦Õ½ZhõùDÐØŽÔØŽ}Sc»d[f!Ic;Æ¥Èv´Pd;ơȖ-Ùr+©lG YlËÑ…*Û¥˜õPÙòWIf;F¡ÌW*d¶cÙs \o ˼.ÙVô{ٱ̅Áˆ$²¸%Id¹ˆìh!‘e–™,j’ãÉ2-Òër+¥×­Ïôºø™‘^§0çL¯ËavyÿH¥×Å6‘^—)o™^ÇŸéu¹U¦×©O¦×©%Óë"™îÖo¨â´­Ë 4=RY¼=HeG²©ì7Óë´o‚Yö˜Å —]Èe¹+qYÞ×â²=3î~ K,Ëã–;"–ÃËò ËŽqHfyugù œeÁYžÁYî p–G#8;[¦~CÃYŸøìØŠ|vùìèC>Û‘Ä#D;úÑâ#ˆ–ÇJÛ3ô,RZî[”—Jœvt!§ô¨%È]‹ÓŽ]“ÓŽrZþqÚ±¯¹?N28-O¨P-·­e[Ž"`Ë£°å)³íùÖÜŽB[ž AÛÑ¢Ú9îØïã%´íȾ´ÛÈo5Á^ïGUä– Þò™¼åá Þr˜:ιMÜÑBˆ³©¹Zqù¼‹ãŽƒ‘ójîšw¶,ýµå┋ärW"¹ÜH.oF‘\ž<‘\þ(‘\îH=sX²\XnOÉgD¹=S„ãGUE?ƒæŽ}«¤ç ÍiNÃÌeY.Hs1K š‹C  Û™jG ;úèŽC!Ð[莭ÈtGŸU>þÞ:>…’ì¶2 ît ïâÁ¼ËExùÃExq{äm¥RçãõŽÃí݃¨w Qo+R°— d½<:±Þ™l·!å{y¼"¾Ü7 /®¿°/´°/Ø&°/¢ÈïØŠð¿@ø§ãýîA6;ë_öæz^þð“ùï ÷–J£–ÿ)Lx~ÎÿŠÆÿò†»ËÛÑÅBåÖó½þ·ÿô/þí÷'ÿwÿùþ4ÿ×O­–_U«ïæùÒ»ùr˜ÿøì†ãüÐçn}cøû·Õÿýøwý«lýù§¿šu ÷}Vþ—Ã1çþé—¼q¤¡>³gwþô„M÷Äyf"n‰É–?h©±Ì+gµs,¶ü±ð] 7̺ëuhlùm…XCØ´­¼†`Ë[ìÐp <| ×DȧÓ_µ,ý—…SWe’púcK:ýýâFrúc‡?ãôמϙ¿bìh9öØ&ó*ýy8õ58Éç(øûÃZbÿãØ¾_\ÒÈߨ–c ¶iýùwúk·‚¾¬þ~чï®Ï¬¼–_ö|:˜·Ài]õö}ß_ñjyðóëe)öqëØ Q)œÓäc¹ÙoYÇXj9Ç:zq¬W/Õ¼ë1TciÖc¤è£Ž>ç0¿ã@§ùFÊ^êe¤Ç›ß§#õK-çXG/ŽuöúÝ÷GŽé¿b‘w}=±Úóýw'¹·ÏÜ_'þõ{¯»òLl?ûõ_ÛÙçú›v¿ã­ôóû-óÝ;èçß´ç{éÇwìÇ(ÜÁ®a]ï¿»¿ÿh'ÿ³vÕíN~éUÁô&óUpsƒ[®»cnyɸîÁKcri¦Kla‹Õ(ÄTr/L.Íb 3ÝÍ+®¸Ù‚Éå¥2`χxw+¾yu´ÀS©]\6pÈfÅ hn0ÑÀ(–‡n;»4OϾ¸¶Ù.¥¥s^ÛÜlÿ 9èÜÏèÊ«†ñD»fQ.àÅ­+Í4ž‰fòî Wy&š»Û/œ!=Ÿ«È´ 3üvß—B¹@…OË”éWåV…ZˆZiw¨Jä<-[.78ÚÍÜ„ªH¨vwGÛ´07aÜßx0±Ñß耙›ðLÝ'[ ÿͧëÞ0ü7‡"àvpóu†*ÓÊe.ü]æ9­Ü E&—Ùž ÿ§,wžÔÝXÒZq·áç° á6¡æ0Ý ÿíaQòiC¸Âà€‹»kÃU›-Ó>j&áÏåvÿ¾\Í=û’é,¶JÆ>>Ýq³iPU«¾dúl%;úVowü·zƒ îø_Fcþj{8Ë~AÙ20iÕ+·M_DÆÑUO‡Ÿµ)“ëiqÇë:¸U·¿­ ¯÷û¯^t¦ۄÛJïŃ™nøo•Ô²`‹»äÕÕž÷†ý«Á¿ù’© T‡§Å ÿ­†b[ó%ÓgäÉð„ÖŠþ7+1È­|Ñt6s¾_l±YÄó¤ñán¾d:mÕ&7Í:o´ðâ¶á†ÿ]þOƒû„Ûw4Ýï¿=¯.>©m¹Ox›ª-ÑÚvÃÿ~1ôip›ðn~óب{á×Ù-—GÓ}Étv[ªbËÃÓ*@Szþv›ð~}­W÷ûVã•-¾b:}…–[5÷ûE%*Z÷Óg+1¶>Üï¿›¦‰3Ñ}ÅtŽçQàÕìÓýþ‡ù4á.îËýþ‡ÅÀ]atk™:Çã²=…‡Õó·Ï®ÆóQâ«eÜî÷ÿÌÖ!ܶQ|J6¶ÊZ5ÛÞ~‚™r_1Ï;Aóhn÷o«Á¼«QšjÚøÚþjzZäïŒ0­$oû_ûî¿ï ¾b:­Æ¯‚…Íí(9¬¯˜Îi%«q®P£jú2.¶²¬ÏóÚ@hfC•ªg«N}ºY™*ŸŸVªt uª¦ý‡WÜ*U Û;ë‚7«TõÞ¤7³RUÝv$c©†ZUÏ ²jV¬ªá€y“ ZÕ3N‹q–»þÛ²=oPÔ«šs(è¶¹¥íÓ²”?×P±jÎ-Íf>@7No T­z~f­ª,³ÁÁ£n•ßjK-îûo·O¨ªÚo°·~JWMû)ÈYmæPj¯›%Ï·†âU³úUõi¹ü5T¯ò…pƶi­mçèf‹WÞ°kã–¶o{ûXq#nãë¦N|Cm-˜vCnãë¦~Oð„zetŒË{ U¬pCn¶¸ïÿØJèm(dõ< 3FöØ‚9Ã#ªm-xŽG@ Õ¬ž½«êÇCìvy·ü :ŠY=F%oûåÁÓÄ|g;«Yˆ˜è—ÌÊrg5«yË –PýŒ¬¯³š•ݶ\¢¸<¸ÀŸ†›}¬ Õ ³†~ylÁs¶jŒ‚‚VVšï›îUlùt´²3Û¯³ ÕódŒG¿=ºÀ_A¸2­&NU¿=´à¹m6ÞÎjVö|nâ¡OËâ{¬{5+{+wã¡Ï=,“˜ÎjVóy}kÇZð´ ¾š;«YÙü÷âVZ0g|::«YÙÑð²ÜZà-˜·tV³zÞú¼‰{ñЂçx”¦ÜYÏj.ýéX§ÜÑYÌjEçÎbVæ!†/R/>CöçI}PÌÊ„&þìâq>Îæ¡ ˜•M×y+xÆ‘seg1+Ù Áà ¦ñ€YÍÊçø8œúÀžo‚7Bg-«iõ9ÐàQÓ„÷KY¹a7ò¨‚¹â•ÚYʪ?'_Ù^;¾©Ï-Ùy0(eånoÜ ¥¬ì„ó6ªÏòºcd³š‘ÒÑæµQǤ siãåoVà·¯×9Vá÷çw/¯þüÙàÉ~ò’:ÙÑbÁ~Ô"‚ýÂÕ1Ø.͉~ÜWÈtÉ}ªõÜwé.SÄ}—`‚û®$Hð»â«ð3I…=~·L-‚üîøòŠünKùÝ1cù=¯¿É/Ìiƒü¬é‹äWHQľ²8=õ2«Šÿ­ì0QŸÅ·Õõ¹.û¢¾–‰¢¾4Žõ™y†èØgÎä<›Ä>ó!ç¹ö +—Ä´¡Ð?¯ÂzRŸ[}sîhÔ7<‘‰Dw·H€9©ï¦I}€Áï'¨oXœ§ …IéæІNÜã+BŸ;ÙVçòå”´xNzßÉxˆ|³gâ@äÒ Öi|ÛˎǬtóè&®úŒ/µ -v3ËMÔwʼn¨ÏÊ%ñ!õÙ­Îk@ê³Z…œá9õ]ñ õY½ÃÁÃö]£f‹Ÿìû=^ØwÙ%f`Š%YCcVz½ÄY€>‹v/è»M$#Dú<–Mˆ‡úPvÕè»yC“øL“}ßm¿üE|VWéR JC™ÈgÁoœ_ùìiÀù&ñY]ªúB>j¹+"ŸÝé× ùʽ ùì«Z ]@¾ò\Nmä+]ŸA!ŸEº5b¯F•?!Ÿ#ÜòÙÓðF> u#/ù¬å|öun/ä³ìʉ¯<ç“ $¾b™/â+ö™&eùŠUFã(@¾b°È]@>û<óúù,ªŽ¼Dä«Ï½£ _µ)÷eÈWkp‘Ïãå¸ ˜ÏcáDxÎ|Õ€‰£€ù¼^%~'™¯ZÔÁ ÌWs¾f¥2ÉX¾çý®µBŸÏÈw>{Y͈¯b‚#Ü«Vÿ‰pÜ{ÞwÀ½ºåœ$Ü3¹„k ĽçâO qÏ&¼eˆ{öšàÎq¯ù— 3ü¤½çE¬%?§½v1Â@°gO·@°g«;|Óöì$pƒ°×jœžUää aÏÆyÁ^qãöl£õ‚½f+~l˜øSX¯Æ'ëý-68êÙ~ø›‰zmÆ;‘¨÷P¯/ùêÙú©¨7äH.ÔÍ£Äy¶ÈY IÆy¶¨?¹vÚ8÷çY(…h œgƒàéçg¾ >#çÅR¤8oÜòÜçõ,8¸v*ë6qž}øø¨ó¬×Vœóì³·Å}X;mqo’óFÿä¼ñ¼‡ýdþ‘ЗD=_Ìy¡žÖ¿ƒõî"ø#êÝŠÛ&êÞ³AzEºU^ÑJb žy AÊ|úæ´!hÏê*ø[ì óiüIÒë*¤×õ® Ò³åg¶ôFíÐIo”ø›¤×Tš7H¯Ç‚ H/j:éÙËb"I¯Æ µHÏ»ߤwIïh!ìå—C´7´"DÚÓD½(Ψ÷ãõF½Ú‚PϦƒ; Þ Ê$é-i¾AzK†ñAzÏO•þHÔÛ!Í õ¶¾$‰zý;ÔãôD¨·š¤$¡ž¹pÛ€zV ŠÓ¢žÍ Ú‹õ,oŒBž¡('„=/oÅ‘=+âù,qq—°gs­ÄpÚ;ý”ø¼¥¿`/+mö¼…¿Š°g×–sDОóu;iϳᣠ=08ÅÃöQ?ÌioX¦Ï hï¨BFÚó–®Ö ¶¯Ì‹°RÅgÓû6 \¸g1÷¨ ‰N&ò‘—hBf­‰‰N;Ž§Ñ†ÌL%8N5ž1Qot!rÀ ò¹*Í[ÈçÊ5Ï ApIÈç52ÈÏ@>”;9™ÏK«Té~,wr…hvÁ©ÄÓÛUzH5 œùj7ãϨ;D˜ò «_´¥éч¬DŸF#¤¸TFdQRÈçŨøê4"»Bðòyx)ȇ„báΨl²ÙUbÐNæ–#¹OæóGœ] ƒ²ïÅʤÛXIòÙ<€Ãùì»ÞÈ×Ua+ïšÚ•_iŸ"ŸU.Íø²X½ˆÏòÄŸ >KìãcGâ³Åò"¾«)¹GÐg!ò|•ú¬n5¯&¡ÏbﯗÊw=;à§Ì ïy¶Ö‰À}Ã"ü Zà¾ó‘÷ùc'Z¤™Më%üÁ)ÒŽl¨„¹Ï×¶š0vd]•L~^“…¿èHfNßä±ÊGŠÄE?²ç?\›ùy!R5ÈÏ+ñÛòóBISœ_Áze Èï~sß3WgÈ}Õ2…q¬ë{pŸ½ûùRuî+#Ìsî»·\ö~ÑÏ«Mð³5¨ò¿»¨º„ÀÏ–ºxx?Ke¸^ßõ¼…øú&ùÙ÷fç°ôçµyë‰~~wR8úí—‰~öõXÜŠèW´/ô³¥ .ýl½ˆ˜£_3·<ýíèW§ ð ýìÀïúÙ4s† ¿˜¦¸gßÝíu¾Ö“ö.BhâÞT-âž—’÷ôZLÞ*&Þ+ÒÓ‚÷Šs_¼÷«Àg¯bX–’˜Fà«F¾Ê éÔc•ÊÞüé,1­î•q Ä=‹Ë‘ŒÜ3È÷î'‰{Q)pÏÞ*l!îµ·²ÅÐÈzmG (q¯Ëó0p¯+A+pÏ>E¸z‹poÜÁiä½ç ɉS({Z¡ aohnÊÞ­uäPö´bBÜ3¥ïŒçfˆÁó¸8Ê^Dø ÷ö§²—Ù¸!íYàØÐé¥U…Ôön=ŽÔöîP¤í­Ž…¶WV !µ=‹ ¢0FmÏÞû”à€{6âB‚´½GLܳE†÷lÚ pMàž¥òR÷Lk”$Øù·z÷l.ø¢½üÖŠöüûL®¤åôê1,hoïK±Ž‚½8{‚=Ë…'^ÉqZË={·Äý€½”à{vU8JZNKþ#ì=Å—öîÀ{Ážyä{y}{öaäV„½¢†€½"#¿„=Iab=»àÔÏœõl2+½ߦª:"{öÞ¢R§"³;°°÷ìZãö¢æhÀ^U~pÀ^Dìµ›&ìeJÁžÝ~#C:mêÏ?`zÛCõ"éÙ–ƒõv¾Hˆz;£îm§£`8Qïé“`GÛéÌÔ{öµ´œã9a6 Ù¬ç£ðº úNçòXÏo|ž˜Aãé­õZ²Þð)6íÆÓ¼”¼@Ö6éØÞ&ä‚õž–dëy ‘Ñô=›—KX„ÄgŽ7\I¢Äw]õÛIz>ûæŠ ŒsаFpÇáBà³=ñ¢ÀwÝñJ¥Àg³-.+Pá³ð|LBá3`´™Âg€+dƒÄw=wyyÅs^Q,QŸr9Aï™1Ý‹”øŽ0‚ž ƒ‹ò¡©‚õP˜˜ë±ÍÀ{¾–ÃWɾù‚çm½é={ {x.¹ ͧã°YŽ%•AzOgÉf5–b$ê¡Ôî)ò¡–-÷Íj,N¼YÅŠÅr+/ÇÒú72˱dHàÅr,-/–ci#håXž>×IzÞ‡*šPÏbÙO‘Ïß T„z]O&Q/âõõL·$›õzà@ žbÙõ*o›D=½õz(xôŠzv)H£WÔØÖh«µ$=ïBéçv«¨y…TH«¨)Ëf¢žÂÙÿM«(k9ã9ýð·¢UÔÐ;—¨ç#+h•VQSò¨:Áï­ò]ŠóKîÓ\†Üw+Z,¹/c>É}·¾\Ò¹#Ü Á}· §f6_h~:è§Ô ¿š$¿x»ý2fOè—)b¿ˆ^ö‹8ØïùµýÔ¹´Âìg³mþ¨LçÛ¯t>;õÅ~¶Ë#&þ™e ‰é|Ï×]tÅt¾¾"ÇNé|Š4ˆt¾œ)ÏjíÿüÁì ¬JšøChÄRÆeÖ/þó¥¢&òùl½éV¬'óùÖ)÷ùžÊ)÷ùJ¦òãÏgn*’òÏg+[Êðc>_g&ô]ÏüKÔˆ„¾kDRúìíWBßU7äù|×ýÊæ³8¯Sé›ö äER2ß¹›Jæ›ZÑQX§ ëÍgžw6Ÿ}2xøŒë´o\9Ñošù7b2ߥŒTê´3Z^Q«Ø”ºwi-I}ÕYJ$¸0ªÓ>;Ú Q¥EX™’ùfÄ3*™¯†æ©d> ‹çVˆë,–…ÅÄuQ×i>3/ïù MI„vÆRŠ’ù2©MÙ|=¤†vV[D8u¾ÙlòÛYKˆmŒí´pE%¾!¶Ó.a?Ùï9ƒŠ|AlgËL-Ævúª…5ÄvÚÅ!¶Ó.&wÆvZ¶á>…>ÏÍd#c;-ÈQLJØNû@íWlg76;…¾çxº^Œí|¦jz)xpgÝ™ú†àNû\®ÿžëûŽìÜ¡ˆ(²³)+rù8$$>û bCH|ýÊèPH|½ç»Æg‘‰\5QTçÔ*%>sl‚<u–‡‰ï™Eè$$¾nw Ù _kZË”ÄWw zøìóL‰Ï‚ò”"˜qÞºŸý+F÷YxÕzeòõÌ$'øYùL¡3Ó ÚYT¶5B;(½àgó "=ïÂ[¤‹‰ ~v1„l?s l©ðM»¯y{ü,JhÈØÎ.õ!c;#IB±ö]æÑ0‘ï Z ŸÁKä³ ¾$Üi±‘Áñò¡Ê×W<`®òõTÖÝÙû‡Ê×oÕÉ–Ê7,Ý…•ϲ”“ÇL¾«1jŸ"Ÿ SNò›fG9^‰|ͤ™—È×l*̆ÈgfžbWOä‹bÓù†É€/‘ϲ;/µ ‘/Š Jäë•”§àÎa™ î4YU¢‚;í%üÊâ³›XTgÁöÞ+"¸Óü+§ZܹJ¢;Ç5Lу9HÜi‘JëÃÓ·‚Âg©Ðo…o,fºKà³8AÆ`zhgùÌâë=I_;ˆŸù—*ØŸ's+|–J)L…Àç©Ñ/Ïü,+µ:wn¥+Dpgïܹ•d…¯ùÄåo }#ʽ úìvxçñÙ-tdpg!Î1¸3& â¾q+™[ÜwŽQ¦W*ºÓ2 ‰M ðl\Ia|§]¥WŸ]m¥Û1À3ê‹ü,–|Nò³p_ ð³µ àçiů<¾YÂN‹"Ÿ½E>òøìûÁ„È稇È×s½ƒàç°Ä<€_·Éö­øÎFUátþº,d=…bCþó¿p3×ç®PËߢeØSçÿ¿ýÊvÙK}Îíþ€Øw{È»öTýÜÇ?-ÏIÒϵçì~-ÇXl;ÆŠ–ËÂ÷ë—GKŽ¥¶+[ޱ,2~¾ÆŠ–c,¶cEKŽõ²3j¶sÜí­¹ )›T6<¹cPx…áݬ¾Þaõ]‡³¯9yöýÅqá8ÔÒƒìûÛâö ­¼_þî¶»Óð¼½zi¨n¨w·J çPÙIC½b(KËéýŠ ¯¡¢S uôŠ¡fñÏŠ ¯¡¢S uôÊG¡yJ çPÙIC½~ïýc¾¡õù*ZbÆóÿ° k¿fAÖ~Å‚ì»{á,Èêøïz W~õÖúÙïx;þèôý»ðç_yŸ½~tç~?Ö¯\ ›“?×îÅ_í¢¸sÄsAºÑÙ¸ ÿãOÅV›ËüË¿þɲçWýË?ýdËŸfùõoâÿ×çQ}&nÏ£í®žüßùœ9[¸×_þÝOµàû«þå?ÇæÿÇO6Ó×ý—ÿt|öú<ìqŠÿ¸š-]™]»)¯©¾lÔjÚ¨U·Q¿é VÝÜlüå¿þTÖÙøG|Óê{7ãcè¿çßi™Ö~‡eÚµ=š—~éi-¼e° pßž³e çã':Lin3DÁ¿sJ~W›Txjˆ4G×f˜·=S'“Ƽ… -jÓûÈÔÁ,]÷ cI×Ó´"t£’åÓ"Ë¥{yt·`™ì†#E3`P¹¼HóÓ¢9˜­XõÛ=ˆÃ1õfA†a(põŸië>ø+(±XÞ ƒ¶ØÜµ™¡¹lô=æ­™;-²‡!‚7Èþü¶Sð´ ÎÔŸÏâ7í5ž<@¢™ÖEÊö\çæžXù¾Ü⪙Ïú˜v;_F%XA·T;§á»V‹¯ý5sòÀb©­Ï,;Â-µu²ê}¶üïZ·¨yyì«û â-¸‘l)ò9ONñP\ëð›Í\°sûJÛß“¿Üp®n-K£ØïûøSð•é–Küí™Q<p³Åzå–ø¿5[šŸòf³é¶/h=ÕC@Û:,Ⱥˆ·ÈÐËV8}EA±ös›EOi™ËýE¶P¾tÚ³6T¯l§+…ÜßúØz®oeU±ìu -·\Í2Ëb(`n3>Ì.öq}ôa²0­ç™ë¦>úÏÜÍ?®ÝDl,MÛiÞEi³¬°­OQRƒ‚çõÞô¯ë3Ó+Òcî¬OUø¨å8M×Zùµ°¡çß|μ(Ö°.ôƒ,~\ÖãyÜü+é5±ºáMc˜Èµ›Òyc˜êßÖ~ ®zM,ïB-°8<°KAK·ok·ÿ`“áŸV_œØÑðOëÓ…!¾åšþi}FákÀKb-þp– î‘ݲlnü¨íŸÖn}ýã%±¶,ÓI}+3ìlÞ‡¹/^kÙ.ÈÁVËžÖn2Ÿ¿¡½&Ö´.›NŽå†w×Ó‡Á·^k8Uv¼‹‹‹Ï½MñSð†5ðQ,Ï›ÁžÖnŠçÆÎÍ€îË—9ÊòOk¦1ø>)+&¿Øãj“o…{Q,{\­¦³°ÇµÄ%·¢Xö¸–÷¯‰eO«íj`™²øÇÕ[|vâU±¦ÿêÅ(ìq5Ù£¥ùǵ{ÑlÕýõÙ­h î S ìˆmÙ°BbçbÒEÙ‹bÙíÖh 4~›À¦þwš§½0p|‡þ¦?0_•_%AÚ¯ kY$x“ E‚Š}Hl 0H”œ(¨è–DÁÎZ¢`§p(8T*Pp@X |XXQ$8™y (ã¨àÀ™ÕÜÀSñ/ÁSq+âÀˆkœúþ&*B5804ÜàÀpÛ\á‚. )#8жBqàRþvpà’ã[pàR@¯8p†Ø*4ÆKh-̼!ºù"F&% ­Eö ‚FÉŠÈÚ:¶Bž‚Ö‡(AÐHZá8AÛŠ2.Ap®0c#Z =‚V܇º.IpF•V‘ My¯ zUX™-ùÜršpJ0hˆáÄXÄKGh A»\HƒfÈ9_0èî•AV) AkQ†—ÓàŒüÝ ÁK—A“wàª|a‹=õ -äÀ6Òä@_š ‚WÕ»hkdGrà šÚFxÀÅ+,ÏÄÖÍXhñl!ìÖÈÖ‹^â@§?ÿÝâ@[é/´„5œq ?à8ä@Ka#O’mò$9ÐÖJÊ‹WDjˆ—GÒ$úß/``së À™c / A¾º‚÷1ë6å+1Ð×R®›ý¶63·›Åâ>&úê ~%1Ð×dê‰-|1Å>°… è-˜ä›™£øK:çšbr`³Z‰×Á~4X èk=hp læópãXÀÍka“ ñiµÕ ¶€›™¹`òIlæ:±I}ø´ÚN›¥ƒQˆå3AkÀ@߈ ôå Ð$1°ù½èÚrÐW2`³„±v2 ï°AôaAf`ÀæÙkØ3¿è+Ð{ÜdB|T} Ûe¦ °°Y¸–ؼ¦7 Ø,3 ‡Gl^åðl–)×…`Àæ©hÀ90 ÿð û>}¶öl‘®&ô%/b!(°É8p˰%8p«.Gp ƒ>äÀ­pùàÀ­\qàÖâ@p`MpàÎr`ì;8p‡…8pG`®80Ç l™^M «ÓÁ'@PÇ|‚ DB`l ¡Í‚Mñš‚Ù"lqJÔ0 ‚úY‚Ù°ùÌjò+Ìß)<öM¤ÁÜ;iðèBô“A>\ßÖy.DƒÇFÄA߈*àÍgVçT8˜çK8˜G,ôóEø»â™%nó^æ] ÌGK8xŒC<öȨX<˜KäÁ|üăù2'z —<˜ï ñ ÷J‘½(E´âyÐ[^ºà û+¡¿¿00¿$Boù:xð؈<˜ë2âAïóâAÿhápȃÇVäA¯hr#N9ç“¿õ­ßQðX4z º´üƾqÐZÐÐõ‰ål6h0?Þ¢A_îHƒÖÅT4è}¾´Lüƒs!=Zåë`A_?;EÁs£ª,Ý6ƒÖpcOMØ[ð×ù¥ekÐàT½¿ Ak!™N}`™£4848åÇ8˜;zË© zËõâAoìVô–ª¬”!¡µìZË:eAôÁ¾?°4c $<^üÀ2©;˜pª¶S0¡÷ñaÄ„GË­ìEÊFÈR0¡÷§U}`âLè-ØŠLh-ÐÐÄ„GËÐ6ö>ô½8»ú1c«¥ì…õ1¡oD©PßWÁ&™Ð§Ä§0ˆ2 ¿¯¡APè+Ì¥êûã ½ø®ëûz}Dxtú¸^¢F"¡õÈ&$ô­  }-DBß €E$œ – $ô­¾"ô.§*ˆ–“­Â!‰ÐZ:[ðm]¬Dè-Ø5‰PÕ‘½ˆÈOk¶}O†@è-_z ‘_Ö8!áчHhÃx!¡ïj#‘ÐZˆDBoA"á Æ&ZÃz!¡b# ¡oƒE÷ªËoù­%ªO”—erààwMºJp E(~xi“à@¥O'*{?9ðþ ݲ'KT©´äÀ›³¯ä@ºr'j£ÄÀ›¿Ä@)8‰Ê-O T­ØÄÀh ”Ix` &)P1‚Aê1óÅ=ÏüF­7.U,Kä—ø7ð»˜ÐòÊåÒWLèþˆ UŽm2 CK‹ê‚ -ò¨Rdhia·ÉÈPKå—ûä·—2Z`¸É…˜ç¤Ú|ôjѯ/´qîwdhÔ­ 9° åÚI,‘)A°Hî A°HV A°J× A°*(:ÁòŸÁZžIAк¼Á:¤FRdøRêMÕ‰CT”[ ‚¡g… Øz`k”4Clª2z`“!fèá~z`“Bz`W|dèV0€-Ô»ŒBlJÓA°Ë,J‚`×%A°Ë#G‚àPå‘»BÊC*U‚àކ ØeC‚`ß¡n" ¸“"8äЊàP‰¾Pk˜†"xóíŠ`£‚`“¡J‚MõCrFApÊþ#Á!A Bù:ÐòËÁ\ÔMwÂA€’"“å¸Ö›íàð¥ =pè™J=PI¡NÝ©ª:zê´þ;ô@*‡È€«gWÌç¡"h,õ@ANèŒEO=Å’BÔ;)õ@U€N=°Ò 'õÀÚD‰$@ Üg + ÐZ&™ŸW/iýL‚`eýä @Ûêb(>¯þÂa¤(AóiE ÐZ°Ð/XŽèáôDB~]+¯ í*€¸€^b#Ð./˜Zh-ýŒ Å-1h[ íjÞ/´»x¿DAë´Ú»c¼ÐЇhα÷ ]ü†¾G´WÔ1  ¼ý% ®@]à >š¸ÌX IÇ`B 5ìÚ[é¥ ®’D€ö Â-´àxɂւß)\òN \šu.…õ.¥.xq¢“ºà¥HËÐ5©J]P…Ý]g ?¯ñà‹íÎ8!ÐnAÜ‚Àxÿ íû õ.ˆâZ žQ VÙgh¨Kºó …v>’KU¼&1pÑl!(Ð«Åø®DG )Ц­ûE¨ð=P#“­/Q çHè@&½BÈ.=Ú ˆ+. ô,;£ĉí$Âýª‰|a¨‰'‡I„š” Å䉄Z9ðŽˆQ!a‘ìw !æ?‰„…³”D Uˆ=™ð’ìL¨/[0!cKŽLA¥5e¦ ¼72SP^™)ȈýÌT6Rf Š""SPV¾g¦ G‰Ñɘ¾„Bå~d„¨jd„¨j>e„(ãèQjÉÑè¢*ᔢJèÊQ¥ÎQ¹Re„èâÌÑ¥Ê[Š]¼Â!Êšb!ãF„hØVG„¨ò ÏQUuR„èR‚á!J÷­Œý:˜Ðs^Lh7™f íuJÞ#ÚË“¬b­ħ`Bûd¾âCý þN´9›LrðÑ·LfÄ„QELØÃ½1²•o+&ÌâìbÂv…å#?ZuȉULX%'ÊÀ7˜ð:š`Â%D &\ß>PŽV‰„ŠL$T­õ@¢T­@B}ŽQ½Þ2Ft)}P1¢"úŒeXÊ#еŒUre‰J=Ë ÑÊû/˜ðÖÒO‰¢H@á-cÄ€Â[Á~…V¬þ¥ ®(§Phe*@j‚B·P;™ðÒÝLxéá &¼Vä^Êìo&¼¹)&¼T+˜ðiæ ûðdÂ~….™°›s?ƒD»ùs¾™Ð On‘-ùƒÊltk‹dÁª@ÈH KöH¼«xOÉ‚—äÐ`Bû€ãpÄ„[FóÁ„K bÂgvŽ› ¡pðÕQ¢*w”a¢“+£&:8ŸÍ0ÑASî BM“ £œLPásŽêK´•‚whÛ …MYj…a¬ …ª“ ›æÎA…M"QP¡ð=¨°m$*¼›ÔDbaá{þ……û……Õ½ mqíLô·Ð;LÔnDæ’ -r `&*,\H*´¹*8LTø\g(_I…¼’ Uø$±Á†Á„÷Tf ˜ð¯8Q÷»N&ìV ˜¹‚ôw‹\A«žŽA˜*hçùz¥ ší±©‚–»º ‰Œ]Ì-Ï8ÑÙ”õ§8ÑÁ”æŒíå -]¹}ĉ6&*L´Ð6ÃDUb!ÃDïKÔ¨8Q{ãžÉ‚D{¿‰p‹kE„”ÚÝÏmBøÂÅJ^ „“¾e „Ô„“΀ „*š@˜¹Œ®ã#Z°;ä[ñ søK´…¿ýâA{zû;N´1Ö9p°U®u¶"¬$6>-ƒÏlp%t[´“[UèÈÅVˆ{‚ÁFgü€A{G ÑR0h 1‰ƒ¶XƒL=±`¥cZ ‚.«b”'xß]LÉ<ÁLÆTž ùôÝg”h¿ § ‘'h©¿x2™'ÅÔ"OЊû‘ý'h¯Mv‘¿ÔÅe„íz¹/Ï:£‡ö;Zþ-§ËÚ/o—½ÔçϹ³}¿‡lIç²Ï}üóÑ’ÎeÕfPó5V´c±í+Zr,w î¯_-9–Úr¬l9Ʋ™g}-ÇXl;ÆŠ–´;[}¾5ÝÎñŸsgk?rg»ûÇÿ~º³=­ý—úÂܨ„¹Ñn‹Öpi˜õyÛíihðꤡÒxMCÆk*{q¨³S Æk1Ôa¼CE/ utŠ¡Âx-†:Œ×b¨è¥¡ŽNù(ÈxMCÆkùઇú3îlÕkËÛ ÀÿÜÙ~ÏÛñGï ïß…?ÿÊûììõ£÷û±þ°ÉYõânóÿU&gÏó}ý÷l¶¡¿=h°þ²²1ÎÊo;U˵g†ûŠûÞO~õ/S¯Xã™T(k1ìhÁÇk,,ñLX-öÖ:}ͪY­{lšÖ©ŸIÜ…Ø4e¡W/¹Y°šêo‹jîÕmEĵXi#ÏBÇdúùž(âÉþUZ&eéºûœ¶Î0˜ ?·²{#=ÛTµœ£/äbc”>¹&KwñêþìX˜\ØfæÇÌçµ® «a»&dHW+b°¨é-æ]kêS×jo¸¥XÖ<ç÷£3£ô©XgŒS}’èQ&®8<-›A:,óü̉'#Ii¯Piãí1%Î<µÓЫàö´x4Y‹ª’µMOLó–…½¯†‰èÅP¹ GÞ…'Ÿ†Í%ªÕlé¹´åK!Õlr±ÂC¸vKŠ»±&…m,Æ‚ÀX°Qu¯!ÄHøïÍWîWýXz¿ Œ›çؼd×ÄB›#níc0 xh˜YŒ•NìÕŒ} UlÜ}-Šþ Á©îpî$æ]ÆåÅpåq²†-<5¬ÜècÆUÀÜ'£tŠþü®ÔQÍ(Þe;ü„Ñ<!µújžÂ•5Îùè2"gààTjþz8Æt3z_ÁåpvÎ Õj6Í.#.ÎÉŸéž«O í´ê¼.¬ÈZß–I‘æ|uÞ~|9Ç? Ï#T(#r½¤Îzq‡Å|ž_|w1Íáé²þ¹¤x|§yd1=³`#/ïŒûœ•Þ‘g‰I÷DÆ"a«;3 $áåbËtIÇ•jÏ’=­^¼Ú1õiÝHktl« &ÜÞ‚7’›ëd âGz!Ü^Èãô43ªy.!vDØV,©ÈÄ®û@b¡ªiU[ª²GÕVænŒ;ݳÏSq[›æ‡ÌB b5-L.^þ72š•úñ…êjü>‘çð_Múô´B©QÕ²N]?ܵê6k$ë³QLÍ«ùìðbÉ0¯Z´½KÑ0XïrÃ{×I¼lÑšhÁãã)†ãàf´ôAw‚z,œ<3 s'(9tyá¢a}ÇU7&¥¾ø‰ëd‡ÚÍ-ªÐ£Y÷‹}|/\dáÊøw¯[äSãÚqÛxá"÷ìâ‚Eã?¹g†Åë¶^ŽöO¾ë&íÞ°°Ûäãu‹Æ !ÆE›myPŠ×-2#(ûïÍÿ¨ú20†AêžÛöûMíe‹ÌÊlû}Üe=»yâºRîU‹–;kq™ËªÁJWÁëͯ-*ÛÝìÖõ&Œ ´ºÜÌ5Ê œ.F~‰ý¼‹/.?¿ËHŸU‚¼d‘»@ä|xÅ¢Í1xlÛ¿©î¼U°›íßTßÈÏB¹&<  ]q¼d‘›@Y9@Æ,šn7Þb*¹—,2¨(RÓJ02»$ohþEíöSý%ì‹ö«K÷j¿•Ñê‹Ö†cÑÀ¸Ó?¨¾ÒØ0Œé´fZUø –O»­@lcŽþujõòïi·3ä/ZäPCp›aì5`˜å/J/ZdÏém¢1úTÿ ö[¸½h‘;@]“ÒjÞØsê‹›~¡j÷Lÿ§Íüp‘[@] ÷muÞ°€ºXÏ ÙsZnN&[]P÷Ô¯ØþIí¦'ûRSk—R»iÎþYóÂEn…U./[´;¼¯°Vce‹l“Jß7¯Z´Ø¥¡Kõ/*ü¨ü€­nÑtû)¾ÜŸ?ÿÝVQ}ãu‹†o1¦åiñ/ªS¸pxÓ¿¨Ýd銖å_TØXaïPÛ}_þêóºEö¤š¼­¬n‘=ª6÷¯¥×-Z#ãtYq{TíŽñ™—W.²GÕJ6áÉìˆÔêÎ ~Ñ­rÑp£2~üZ7¥–àK÷Oj÷Zèâ[,®°{Õ"{Vmü+ï`«Éè-Ë?©Ý¤vÜiÝ–†}˜qùµ[®‰¿ˆ½Þ•ã®Ù³ZošÎyá¢QЂ+5µÚk¡a W.²‡µÚtË÷mÅ‹ìaµÜ£5¼x‘=­Æ x¥Zñ"{ZíÑÁã`>jÃÈǦÈOCÕÓ0–UŸa˜‰æå‹ìˆW¨Ÿÿª>-:[¾º`g¢M-0ÞþUõ#ÆõÖòF-|Ÿÿ^s³“üæx£½ÍNúûú@¿ûƒý*æÚ‰~´>ÐÖ9ù5äGáï ?æJäÇôÓýâu M›ýä­’ìg”ùu ßdeíD?¿†ùM:%ùM:ÿ’ü榊üT$%Éo.1œÈo2ˆ=ÉÏÂ7ùM7Oò3?2rÉoÝøœ$ù-º&ù=-ûE~>ëÑüŒo¶€ü¬¥cï$¿)£Î ?òÁÞA~ÒƒaH~aÛ-ò3p`ˆü"¶$ÈÏS6ز‹ƒª7A~žWõ"¿È ôó( Ð/2#ý<ôë ?ONE’Ÿyûk!ÈÏZ®ù9#|äçÞc /’ŸÛƒë@~ž÷ñ&? *ìSaªÄ¾‹¯£Ä>kÁŽ…}W, û.jʼn}û.†$ö]tIì“ëxbßÅ\¶Ä¾[«}æ I}7C““ú”Ôg}ðxú<Úû&õY`C±úܰìE}áXês÷ë€>kè@IBŸAÛõ‚>÷+ó£ôYË âÆà¾y}«±¡O&é}Keïú¬pFèóµŒõ¹0$õÙòΔ¨Ï¢9°Ð#ê[²Ä>_ÁÑû<´¤îà>a2‘ûL*ÄzŒ¸o©0–ÀÁÿ_÷™JIò÷ù:J9¹Éà5pŸ÷ÁÏ$÷ACÅÎÁ}-JÄŠû¼Ï8¹¶gèîC‹xÉ}¾DãϹσÀ@Üg4 –s=uà>oÙ :€_®ëü–a@~ÞÂ> ?;AÀÏ»LPÀ«AlÁ7uu°"°‰'öy| è ØçëG`bßÑÔç]¤>oõå “¨Ïc”±CŸ‡9) šZ³kÐçáÉ@1B‚šýç‘ú|‘ªŸÔ‡¸ú“ú¼˜Mìó­0¡"öù¾À ¬õùJæóh?4"Ò(Ð¥quQAóÁn|%ô!J @7¸Š*ÿOAŸ/¡©}°Ù'rusy–Ôç]€¤¤>Ì÷/»¨/‚,}Oà ¡ú|\ ¡hتquSpôyË:¡ÏC¸ˆoƒË¨ÏŸNè{úð])èó½Äôyb) #ƒ†}'JèËÈ|QŸ·\hqêóuA ©ÏÃÐHb >oH“ú¬´¤öêóüR_³÷˜Ôçñò¸4¤>£ýú°èˆ½ã²½Z&ƒo0±ôyÜé„>˜¶è}ÃÓЧpÕ*øáú|}scäÆuÔ™#¡Ïɗ먖äù|A´c7“˨*™ æóø"\2Ÿ/‘–“ùÜÅ !¡ÏíáÀ社æyþ#I}Þ‚—'©¯Ù'fÔç㬓ú`¿†PŸ/ÐbÁ‹ÔçvpĵÁ•ÔÖ5¨| ¸‰¥ÔÆ™¸¨Ï!ƒú}…_µ¹–Ú V*}ÇŽ}±ZÒ§Ý‘ºþ{ìÌû–ÇÌØ§ òÄ>Y%ùa.t’Ÿ­Ó¿T?‹E­€A¢ŸM_¹ÙÏ“˜!'’ýlúÚ^ìg-XˆûYË~±ŸMh¡ˆý":Øo•*iìg³Áë„¿u3â?àÏ]pOÝÏëÐãhHÅt§îgÁ?ùµjC‡Búó@Ù¯þ,è óNÁŸËM@+ŸÍÑ…ìgó¦ýRý< Iö[²Íö[«?ØÏçDh‘êW%´†ê×tœªŸ §ê'»ØPýŒÌ JõkŒ¨ Õ¯K/ Õ¯wj™¡ú ÍCö³D€·ìט©²_T„îׂ3¥û©Xmê~±n©ûeé~ƒÅ€S÷³èמûùÖýSPR÷«ÌÀ ݯñ£›ô×P²$ø¯2 1ù¯1¼þý˜Oü×·ZÄË4 ž$IýWŠþ+i%ýÅù ú«] 'ú›“¿)èÏB1! ÿ”Å–ø7÷'þ­ÂÇNø·X¼<ñoÑ<9ðožòÀ¿Éì⟟ÆÁ‰ÿfçŠAðŸ²F’ÿ&ýŒ’ÿ†Dòà?KRDñŸfä)úY†êgKÛoÕÏôí·ìW¸Ö™º_ÁŒ4e¿›.R)û½xCöS@tè~*_ÂßÅ+!ü]×·7ÿmš&ÿÉk#ùoIœ þ›tI›DHþ³ÊÜ—øç3„Sös§Zr%ñÏZpGÿì[÷ðo+_8ðÏF— ÿ|óuП]LtIž @$ýùTó+á/ôæ€?Of@ŸÛÊ[²ZÀß– "øÛZP úÛöˆa+ÒŸi¸õ”ýЂq€V‰i€Ög¿Ðö…Ù‰p¢" 9ð–SøóÙà hæº8["@;Ãøteýë @ 'ï8#À}QÄÕ‰Iü³*R<.âŸ]ßM Äu/–ñüÛ*"ø·×„ÿö hã¼p[.6ºÍC—I4¯`LŒE€„#üÛÿÂ?;oõÐü`™|Š~0pWÿlâAˆ£èçÕßÑBÑïÒ´!D¿ ‡?Ó½çKñ» ã‹Bñ³aqJñ»ìk ¤âg%¸8áoo΄þ&ómþ&m³þ†”䀿Nûí„¿Æ¥Þ€¿çÝØûÙ °ÅïjÒT¥øÙ™!¡Qñ»TÞ-¿‹þ%!øY/Pº?«õõB¿§K^¡÷]·Sé}— ä%ùm I~›9‰~“ щ~ö‚² ý†2ÐÏžâSï{N(gµ¡÷]’,¤÷]KÚ¼ô¾kh…Ëõ¾«k½HzŸu Bï»:Bï³–ýÒûìºÜ / ~vŠIhTü.ÕlÅïRš\²ŸÊœ$û™Š­Ä~S,ì7–Æû[û¢âgoU¬®Iñ³úd89TüìåŒ\Šß5õAÁï“Ï”?;x:$øY %@ ~—Ür2ʺðõ¾e©óyÿð5åøìÔ!„>ŸA{7]„ö´þ–°g9ÅY°wÏÏ Ï€û€½›ÅÃö”9˜°wKM Ø+E`)ÚSªtÒž}b¨ì‘ö,Ç–üÚ³#@˜h¯ˆj…{ö‘eL'q¯Ð1%q¯0 0h¯0á?iϪÃá`„{&îÄ{•!GÉ{11Þ«Kq–Á{”Æ÷Tô&q/7îÙûý{!îµ[ñ¤Ä½vsO¢=»òh!í5¾q“öZ„ Î÷¢=-­%í5]‚ ½¦WaОÊ'í©¤CÒ^›¼³Bí  ¹¯…–'¹/–,Bï³Üà·Þ×õP…Þ×é‹›z_/$BÉ}²' ¹/5Bîëâ\É}餉{]!Û{ ·‰{½)8T¸g©‡¯8Oÿ)gœg&N§Þ×—¢N¥÷uKJ½¯‡Ø(½¯3&)õ¾Îjq©÷u=С÷õ­¨Né}ãþÐûä–zßÐâ®ô¾Am>õ>ËŽÆ(Òû¿‡‰|öŒ¾‘oh>™z_g0¨ô>ó9ùÐûø O½oÀ‹çPü†¢8CñëŒ MÉvx‡ä'%áÔü°óÐü?©ù)D/4¿¡è+‰~CÊ[ˆ~ƒ.Sý ZSôüâ¢ßEõ&E?ú“¢kù¤ègå*Ù)껹"‘ÔgÕsý¹cmsÐÀ¾[ªE`_á›-±¯KûJU¤©È¯0+.ɯxD~¦ç`W"¿Âj²I~XÁ ÝoW˜Ä…ì·å¹–ºßň™Ðýb %u¿*îçu„Їºß–y_ê~íS÷3¾ý@¿¦XÅ@?Iñ‰~rZ<ЙC‰~ZBô³ƒ´‰ýúæ½%ݯ3¦0d?{ÀOôóaqÎCöŒvJÙO•DSö³gáëo‡ê7o¡ªT?ùÆ¥ê7Žèg òý&}ÚýCZƒüçI~øÎä·òA~‹Yï)ú™5>$Ol-Æ„èáPý¬Ã[õ[œ¥ê§™rª~ÏŠ'!T¿q“Rý¶ÞA~—V“’üºú0ÖÓZp?*ÖÓ^ìÐpëy]¯@Ïëyâ4(Ð󺯷äç-ø }7ƒÇûnEöÝúÝâ¾»+\TÜg“×W çuÓ)¹ï¦F¢ŸM,üúNeÉ€4*;ðVœf0`ßñ]„{¢øäîI™#Ü“wÓïJ¡p‘ø—Ýå›–¸´Æ¨‚©GªŸh'sý:Sܤù]ti~Ü5?™¥æwߊ>uÍœšLô¨7ðQp båBô»uAi~vß¾Rý¬ ,%ú]ŒÕ>8P+áɨv` mÔ J Ü´öL ÜUùÂÀ)EJ8Xs51pÐ=5?ÝG©ùÝÊ›6i72*94¿›¨ÄÀJ)ÿ•ë×>rý.Åw ÍDôEzaàaCh¯ÛñÂ@[hœÝZ¦¼xk‘wdJŠwFk’mMÛˆƒ9’Íñ»Ž\¿‹ $™ëñ§ÂÀÁ@¥CöëŠHöJ 2T¿E$ ´Y<£@‘˜àëVÍ€žâÔO ì—ʵÚ7޹üZ™›ÇIñŠùTyÂHô+ZqŠD¿K‘ÖHô» –¸¹˜œhƒ8Q ½ ©‰'ë•&Î ³Ðü¦Z@Ýf¿¸N¤À~_4²ökÒóHè9e`3R xîw®ßfe®+è¤èפèIô«L:HÑOrAˆ~÷üÀÀMQP©~×­<>1àC$,1àRÜz0àâ I©~Våþ>5¿~]8¥úY2ñN©~S+A‘êW§T©~·bþCóÛ5‚@©ùÙ¸$ѯo\…ýžÃ"Jô£­uˆ~™ (ѯh8D¿›ç&pÇMþÚ/Áo(-¿NÍ?¿Æ+™Šßó<$ýÞ0ÀSš_a…íHô³Œ¬Â+ÑÏý?߉~K§)2ýšä¥Èô»èÄ™~&u4¶ ÓÏS6Oú{î3EØ*ÕÏîÆxþö$žüÙ- ŽüÍʰ¶€¿•®`¿Îe«d?[¤Â6d¿1•TýlâÂ¥úmñ!E?Ë‘ÛPð”é7”™~U GÒýìÖ³Iö›]žd¿Nÿ÷Hô³sUHzw$ä¢ óülZO…Qè·™Çèg™-gžßqö„~±N“èÇhcª~ÕÌNôëf5V¨2ϯÁ4>Óü.‰T?;WLÏ£êg©©Œ6¥êw_—<É~“ßö”ýºJ¥ù™ñi~©¾*ÍÏH„ZœàOîüMIz‚?še$û Þýª=6§èW–I~ckX¤r!1D?Ï;}‰~fQ AO¢Ÿ+¼gBôÛŒÝOÑÏÎÕ[ôëÒŠýêV ¦Ð¯Pßã·ôy&ïWŽ_Þh¡øí?ŸÈ½¿&¥ süÜk8ɯl¸ø•ªU1‚Ÿ¥»ÖW†ŸÙbIàgî„x ünãݯ¿zßdPËaJöÍ~›à ·ÞœÑò·h9ÍÅ~y»ì¥>Δìû=dKv}î㟖4ìê&IÔ×XÑrŒÅ¶c¬hɱ†å™Þ¯_-9–Úr¬l9Æšò׎±¢å‹mÇXÑò6%ëFvŽhJvÿ²yا)ÙÜÅþ!¦d?º-žçÆSôÒ'êó&¶Û³udf/•~cë4ÓXÙKc½b¬0‹±DZ+zÅXG¯+Çb¬Ãr,ÆŠ^1ÖÑ+YŽi¬Ós,^õÒXÆ™Ì<w³E”9“•_s&+¿âLöÝ ñ Îdº¾ë÷v&ûñýõ½3ÙïyEþèEôý ñç_y©½~t÷~?Öv&{¾Eßæó%û¡3Ùs6þCþï¿[°ß²'{yˆý×ŸÜæd½þùmTv4þ§_¼5~ݳ¬W,c†iž ¦¡û ù™ÑÜHó oõ9NUº]õç™õõWO)wP|NqCžïd¸è3AòÐ$´xA1_òô]5ûào6``SAX1Þ'@½!o0S»»½¢aÑÉõšÞLr;Vd{{Žk´¬|қ̈́¹D»Ð°hÎÉôëÞ,Eù>mŸ]Åíâzaï·¾xÔ¯Ÿ–õ%ZPa,«¦vÿ¸(sãXF'Ãi|šü´,†é°€qïÝ9Á¥qvú¨¬/Á•”gŠy1N‡i O‹Ÿ9Ï%™è³|my"ø] d ~¼ãº°BûüZ_˜|ZI': K+´hÉ4 Û½9Kiòþ´Lfú2¦[‘¢ ý…>½„U½OSû€ÿ’G§àÚŽáó¬a×\ y‚ã]…¹¾„þ§e#ÐlûÑbÓýÓÚÿ9u K´…¦i}ÞÅó’Üî ®|£dZÊd®/ú´$_,’:`t›1ÜìRÑŧ<>·ð4†Q:0Æ ë>¸ösÞ\ž¥ãFw €ùÂ.Õu»O×™ÂÒýÞaè‡ßxž,4±6ìèÝYšÑ!>°—`ž/vn'íöP Ý^쎎éŽÝv꺿¼šº¯i2øBãp9ºùmo˧~~ÎÕM³F”NÔusSóËägnARñëˆ1÷¥Ù¢{Ñ*ùÒl¡3v·dÈ›a'8U•×ã»q™™.Ì8Á¶€ÒX ÐUœnk}»|eéÁ¾áA’AE}#kälñKæ[±et¨þeñ¦6 ÷‡´p•¯ïçe6Ø/(Š„›fïŽçTf|σ˵x?ÞaŒÛØáB‡{F©DW †¥Wž‰}jÁƒZø’1YØÇ…§eÒ£žÊÏ3ïÌŸ‚7ɰÈÕÁ§…&>æQ¹l8ˆU´tÎjxNíݼå ü¦élÙxNU#dX­ NÛ@èÌðZA¬!è<¼Vyü&îOõåñ6NƒÃk1êÉÆÜ©ž„ÃöB%…5u‡• BŒŽÎ¨— rE†–&ÃJµ3Žgx© Jøk3D‡Ñ’Ã+éð|çfíTXÿÀ÷T 5 ø FÄá…‚·@© ù—Æm7TÞÄà 5Ü&Õ1¬R¥v5*3ò›žþEµ¢†mæŠú/~›+T˜¼71ÌÆÕ†ñï^0¤\Ђ/ª›:ú×{0#Ÿi:à ùÙâ:Þ°BA›AO¸i+Þ”‰„›Öƒð°n¼Ø† R`”³ ò’y$à ±Ä–É/j¥ÓâðJALôÇwÔͯjŸ:fÜèL+^'HN•¾k«„§•a—Ãëñ3àÑau‚•¼…­*?«íò?¿© {^'ˆ1w¸×¬NÐ`:dǰƒßT³ˆ@Ë,´©g^ñð:Aë+‡Õ ³Z4În¬ Jã´au‚*íúq¼Nï?_i^'ˆñ†¾ü7zÁGµqýjx vÁ-j…‚·ACãGUŽýÃêuÅ(b߃ßÕÆØ÷au‚üaUjÞð:AÊõóeu‚ð]e¸ùè›V_ôó~Wí½à;÷:Aë|ð¬NÐÍEÿê¯Ä>øU£ìx\q‹z ý•Õ ‡× bbÀvq5!PÅÿ’Û…±ƒƒ@Å€Ê|!ö 91`c`n2à¨6p0 ï`@æ½$v®o%VÓ;06ɉ¹2’$1Ðà 8Óó¤ÀJ#ì¤À~‘ “G´ˆƒP I&FQ`eÖRR E†_¥@®¤@Ö}Q ñ2(>ÓIuóä¶Ée’ÀÀÆ”Ÿ… +㉠敊u~¹œ~RàfÃúx^ƒ»èRh°ƒ}2È'IP!h j¹#H0.ðI‚x^“)°$ÈʃWpŸHÉý nB|àð5Ä@zn¸yµ~•yŠ8X!1p0¨êÀÀõ „¨5 ÀA?äÀÁÒâIƒIAIJ[K ˜}xd²ÿ³„Àåñ'†ª¸éG•¸iYèsnP!ÐýÇ Õ­¥³…Ÿ««hB ÍŸ!©mÎ 5Ièswô!FÝ^A ]r"!Ð-j¿m¸H…üZ™½Ê‹—ꔑڽ^( òkU¿èJÁK´O£äw…¾UEèJ$?R ‡:ãxH>ýÆÞI*µ™ Ò˜S,ô Ðf@à7É€m ³`¨Ëû?e@[‚{A Åš l×R¬7/Ih€qêBÔòPj€–¥Ë}¨h¨• …Ø6C\’-E€U‹A€õ©‰++¼'j=0 °11•@ƒ[#» ù¨²Ä €ZMTÕÒC ¼;T@ ‡¡vÌï1é;°rš–hâ”8! Ô¥DÀªë}‚ue‚“i ¨„ådÀθó`À^¥Iе¾š Øu“6&¼•@• °uÁ› ðháwª1‹/!°1Ÿ-!ð¹XÛH%ðpŠ+ët%N¸7%¶Î»6 °1]5 °±†tB R`£t˜ØšT5Q`¬ï6ºa'Ê„3)°ÝÒâD!Q$n!Þ¡Þo%°QÕ?0pjïÂÀ¾úˆ]ó­À@¥Ÿ'vŠ¿‰CšD*úÒ‡¨yxp`L‚½IÔÚäû)°ð³R I%æ ‡È´¦ƒ·† ”l8%¢NÖ„JœŒªNœZgœÁkâÀ!1&8phQA8ø}N5°_VP;8pêøB d`ðÁã¡ïŽ5Ü'‰MJ[h,­8™ožhùà.a`gtsrः`r L“ '$ªTb Ÿè¤@eÚ'Φ6¯Üý¦À¡Õ‚ À è¤À·3(p 6@B Ì?•D‘øÌæÍ »µZͺ·عr–Ø—Y8øL DÀIƒ!"Iƒóº @•fO Œ[@hõÜÞZ`g½©¤ÀxèƒÍ%áMãÒ¾E怀‘E*ä‘hÈŽ‘EcQ› Œ|9(P‹QA“† N‰v¬Ÿp` –Ë“i=rP $¹ƒqžHºN®Ý'*=?)P‰“I*×”Hs„@óWDAà€#d2àÐrd0à`S2 qö x󓨤ÂÄÀ¡p“À@qUPà30`ˆ×'Æ œºÙ‚gèzâ@9&Æåœ]-â@©jÉó’ª(”‚÷®f‡èwû‹ÿ¸ÈsðÝ8þ£FŸ" Yq½øÏ §~øç‹l¡!Œ¡Z=€œ4ÀM?‰ÔUì25@e\‡¸‹ŽFধCˆ€›ËR©ªÎlª€[aWÊXÇ3´Ä€ªKh€U]Blœ§HSÓC Ô d ¾3‡¨¸»Ô—BI p½5@Åž`eˈ} pq•;5@»}¾ôùu ÿF0¢À…˜«WÛI\ - p ±¨@}Ç‚ÿ¼åŶÕú$ÿùÉÉ‘ÿ¼å¥ú‡vGþ³j‚ä?;W§h3(”è¢+ºóG sòŸè”üg-ãÅÞ‚£#ÿÙ¡j‰ÿò7‰ÿ¼/[ð…ò8Eþ³Ü|⿎Åg ¾Pö#ðæÿå *þsÓDÀðlXá«<&zà ­e¼D@¿•زø¨²þD ¿ÕÁW@oy`>d@¿s’À¼—€Q›+Я[Ö)A(ëÅ@•Ð þs»F øoªÖkðŸ»>ž.Z>’®Èa üç}° ùÏÝ_* ›R¾Aãüg÷Øýâ?/±ýе—5¾ â?k©¯HPécïä?_q|E‚zé°ÿEé°à?¾À?ßù ÿ"Ô^øg]ÊKŒ°áŸíˆLFü³ðýþ)N!èÏk? ËÿÍÞÛí|ci_ûų9³ñ‰'ö ÀH}è… 1Bœ¿ðZ×Çrîªî©FHH¨7ºîõ8Ž“ûçk}ÿÞ)îþe!q¡æÕ.:šWu”ð/&MØ©‰•ùwyÔ¯þò>ô—Ó3º¹5¯>Ø[0ý……¢_缪½tÑ_\~;Ò_4¡*¨iuH\šVé\cø‹6Xœ9špÊ›Uô÷N^1ý…?ƒèOs¯áÏÙV ù`£ã[¡LLoøK—˜K ´!ýåjmH›…ø—C3ÿr<Â?ÉR‡œk˜PËø—†¥É¹†®SÆ¿zïÄay>ü—8þË68{ý¶žp³ÿ‚×AüW¯ƒø/-_Ð<ꣾXdmüñ/ŸHÈnÀ¿\0þÚè/ c§¿zÚDay?`ª°þÒòõ=X ²èï`½aÓŸUÓ_¼‰ŽèÉÿ .øbø«“ þ¢ÍIËtÉCÜPÁ_öƒž aétüÄÔêјþ¤Ò˜þ<<ÁßÁ8ÿ‚¿ƒ)h þá/rò·‡Ü ë o_ú;¸ÙZôw0ECáß¡ (ãßѩ̉þ¦b+úS–¦¢¿ƒY‹þùW˜þŽKáß)÷iàß!/hãßÁ…\áŸ2™þòÇ5þr6þ¬Q\øw°JSáßaa°kneýº ™D^–¿”ÜlCÁ÷G8à8¹3 Ú[Ð$˜]Í$HGÜ BÀ3 Ú‡Ô$(W+“ òD ŽÁe—IpH‚(|$>ž±0é€ò‰[<˜¾tÀCK7뀇Ãú¤žÍ¡Ü®ŒÏ5ÑÛ•QÞ,fðOJ<§Cÿ¤r[ì£Ò"ð:~m˜AFŒû£xÑIySùµ-PEgJ”œUÀK4ðfÒÕM´L(ðæY 7÷ãJ ì,£[J`W§•@‹f¥^?£»Ô.+ÊrYJ`FÊ™¨”ÀN£”ÀGA¤V;R6—¨Ü»%>÷sé ø(SJà#ÕJàC³RµåYJàÃüË¥jƒ½”ÀGŒRñ€Ô%+¾;[8 Zœµ@kå®B_KÉ€ý–ÿèUQ ç7PŠJÉ€ýįtÀ玮çÓ: <°K¤è²é€_GÐu_Î:Õq‰€JØ\"`ì¢Ì$>ôn,°Kœ·Ø›lP®%ú‘°ø°ºJ©€ÊI\*`?‚_Æ—þ×(ýo0o•õ¿—ÅJÿ{§"¥ÿ dë*ùï•âkýO…SJÿ{¥ïZÿ¬õSúß@ÔvÉãæZÐòßè’%ÿE°?ÚXþSh˜å¿Á îÒÿ†Ö”Öÿ¸ŸYúŸv‡?ú# Qá–ÑÀ¥ÿ½tB)ýo^ô¶þ÷A¢ô¿Hóúkã¿(_;¾N S°õ¿)¡Ûú_%ýo0Ek鳑խÿÕ¥ÿÅþû¯ ÿ2“áWþ›Í@ÈuJw²üËÎü§Æ’ÿbŸœFùoÂJÉŠW)ùÏØmùoÊ{Ø8¥kþ3Q[ý›MqœQU¤ðoõ‚ë¶ø·€-þM¦É-ño¾Ž äœ:æoß@À¸î_ýåýÜé/ª¢Ío`¬> ñH|=@g“Eø7™ ¶ð¯ºþy“Àø76gúónéÏ;ƒ¦?ü&F¿)Ïu£ßT,µÙo>ÒðÄ~Þó3ûyÃÑì§¡b¿)ÿ{³_õ3Ùíõe¿I/ºb¿)O³ßÔG×ì7ÈSì7éWì¹>p”دÎ.éo*PÂÒŸvX¶go?Æ7—ÎˆÔ —aOSöªFjòËnöÆZgì'(Keþ’­’ •¥2ÌÞü¬-Õ—lÕWY¶¾æ5ûuÓ°õÓÖ‘ ÿÙÙÈ2-wÜ“=Ùý2Œ Zûã¿ûϳÅüX™Ë–µý‰Ãlèq²¡ß?2oo »ƒ•&êÇÃ÷.VòŸ6î)òð¾ïÞ-{On¤ž¶6꩟=cýª'Y¶žª{ÚÛ¸§\0ìc’eïÉÔÓÖÆ=u„,m=u1UOn¤ž¶6îÉ ÐÜÓ–M=¹‘zÚÚ¸§¬¬ú-{On¤ž¶6úÉŽ€#Þ«˜"í¿DÈòZˉ˶Gü7'Úúf:ûyÈùÏ{<ÿzí{\ÓÙÏäj¶ÇëÏ$aûŸñ¿ýî“ü_í¿ýá{úóKþ‡ïéïzúË ØÞX…¬•Äÿ› ØÖÇê¯$`[Íÿ(Û2¯“D@Áûù¨þoç?ý&þÃlïú¶@J‰ØõþýX¾š`‘¥(tr­²,/¤”X™¥õëþ¦%vÏø}  \–rK‡äey妀½R ÃîÖÕ~£àÛÐd­—J£'šïo”_rïä}ŽÛJJ®oÞ…×Ô=™wY‚6(Æ4\7ÃI(¨¿ q(¤Ð%aY0½çv|Þ™§¿XIŸ'>þïóÜXIc“',±¹‘m(z-ËÄRúd¶†÷ Ñþ†åÁc­›mVÁk y2Y‹-Ëüq¿ ˆï{>ÎW•aë=º³fF£ÛÂû^'óU tM¬¥Ër?ÎW…¿=…?ädÂhžÉø/&É]–ÅôE0z#ÝA®§/FS½tHÇkü|ùãçï ª—²Y%¼yã79¹ œÛ.oÜ]¸©ÓYöÍnæÿÊÅñ›uõô‡‡t\ ûÄOÅýa8CãÈW‚&xd3´Š¾î<óÓ¹•üÀ%ø¨¶çÞxcŸä¥#çMË`ÝŒ[ o.šU%-û™ÇeÇ×lÂšÊØ¼m°äܹ5Y“Ø»žºd†7J5–õÀ;%,.nc±Mì¡q×%ðH÷ÞäFŒÁ< µ_dã^ïÛÁ*Æ*½Y÷÷ÓíHÏÜ$`/œØ>Ápçät™E`oº§Œ<¢nÎ`“ÜÜYïlë*gœe™xW”‘EvOòS²Þëïê`JÀ5í7¼«ŽžË0 ½Dðq Z¡üȤÖm@-YV÷&žâTcâU|$Ö÷á!÷vˆî#ªF\à?\çyžä^fÚ_–™Éø Ÿ›q¢dslH–[O}zýfÉ‘–ˆÈ6/¶¨—%sRÝSRäB‡u3ø¨óÉTšy‡ƒ:lYYg32#Ëäþíú%gåù=‡gÎ…êkùI‘3û°àžF*öxUãÙÅUDåˆxUçIï¿…¨é¨˜åru´¬½  Õ#Ë ul˧o´,Zž•×Т_,ÅF…ÑP!lY0² Ò³ôæïƒ"ɸP3#±|ü¢ RV'¾(ެ‚÷J…iFTAêÙæ€{åÈ*Hl3`i˜V£Ÿüô¬‚4p®œzGTAº.TuËwjd¤‰:4¹4² RV¦yt®ØCc\z–Aê¨êöb„oάÑdâT3ëTMž•:ŠàÊ/¤xÏ^ð\G!¤x]Cgȭ‘…V*ÉŽ£ʱQ5Y éýUußFTBj,©:yË0PÀWEXÑ"%å5&êРË(tÁ€±DÆ(pãTiÒscD¤—Å Ð ÍW£zrBø^Eý£¬3{«í4PçkÉð9Cú½¯¿Ø#cÂÀEÒ@ºŸ,©ð¢Eæ«ÉCð„¢ßösŒ””óÜäŠCðÉÏȱ00gòY9ãÔ§0Ö&õÞqY!©:þž7ËK;ŠŠXÂŒÜøÅ ð‘A­£,Ä7ñ÷ÌaŸô 1ÿ¼(»„Ç6æ…“eùrXQü‡µüðÏ‹ušðŒïkGá\GÖu!—·c¦€œ5xj j’Ïç-ðÉçÎE$ÊkÏÇ! Ì3§ÍŽãºÄ».¹Ú†vy>hÇôxÚ1™Y¡Þøb»—±ÂÅvQH(׋f»‚F²]hHà4ÁÝ«õ­à.DDô+¸Zß î¨ÑÛ&(Û æÌ2ÛÙëÚl—¡è‡p—^þ°îÞÑ\·önû¸ φ àF¸+¦Üe$Ãýkƒ»°L á.œ†^Œ™p—ay»wrþ*¸KP°á.ܪÉr€»0öwéLˤW+×ñb»WêŠÙîÕæ¿Ù.}£hôjåV³Ù.SØ.øÔH¶K_É_ÚÕAF;:GÙȉT`wP4.°;X®™`§âv9i˜êÂņR\‹ê´`¨;>g†:oꦠîàÎdA2“Õœ«‹êô½+¬ó¶‚±îšë6 ±îd¸VqÝÉtÛÅu'“éØôz1ØécZ`w2ߊÁî¤÷~‘ò¤Ú1ýE‘]C¬jÒ¾Øt"(°Ó© ìš®»Æ°Ø"»Æt·Ev‹0Þ/Ùµ5Evªæ\d×Äd&»Æ¯„ÉŽ)Ñ ì=Ôv‘üâlìÂÒÑ„`–AŒ;™Óƒ…" vÊoQ\wñ›a®Ë 9i‰ëb›æËuNf®‹6XIˆë2«Ã‡ëÒw„F®Ëhé4ë2“x‹XWMòç¾ø`ª‹Ý  Õy{ÈXçLôƺqÑUÙX—I¶ÀläºÌ‡Œ~Èu™s''×ysÊ\çlàæ:oE™ëœ¢Í\—ÅM?\7ðêÂÉ ¿¤ ..á0¡†…|F¨ËÔR8ŠPç´ã‚:ç*7Ôe$  .ž( uéæ1·¸ÌtÎ"e¦‹¥HUL·E¦Ë¬V¦‹ïïõaºL8Œ³“é²rfÈtÞ_3Ó9Ïš™În˜f:å 1Óe}Ôé2ë/øŒL7:÷\Åt[B³.ê²+H‹T—u=Ñ ©.cÑAl¤ºÌó6¤ºŒ¤Ñê2ãSuÛ©uá Åê2ô¸H¨Ëq¡®ÚêbÖ. êâ"°±$¨ó>¢¡.,D8Ì«ëõ#’éÆC53]8…âK'¦Ëàt'ÖWŸ11]zýá(2]ôC6¤ë°»!Ó%\€žÒsøÕ^™.¢ºñ>‘é8ÓÿÝL—n „¼„ºØÅïH¨‹Cˆ€º0`=O¨K§² wIw¨Ë.ñJêÒIìœP7TžP—ÿNBK¨ËMVlËêÒHÔ•—¡Ý8„~ƒu” uyH® u9ün£ó¼Û€ºmœ€ºtMã°’êr×–G ÛÍ01sÖ\%Õe zˆ˜9W lnëÒ L ¬ƒ¯)îÄÀµ£7/ºÃáåÖå/).±.wޱ0˜ô VÕb¼ÄpÝ‚3,€ôïË¿“êÒ¿ê$æ ¹ˆåÏþ¦ìЦîn *6n°‹íÛë£ÙÅfí h#ØÅ=4:’Ýê„©­ wyÄICNByˆœp×Y‡¸èn™@¸ëQ¼ø"î ”üìød×Ã¥š$²Ë3ƒIvýÔ>¢È®Çzú€d·,'/‰d—må¹$»e¹ùà“ìzëLž*²ë±`N¨ÙeS¼º$»u·°Hv=ª;Ù-Ë«“'Ùõö ´»À.O„%Án·€ì²|ü‰v½­—+¢ÝúP‚+ ]?0²[M˜üPd׳l2N²Ëƒ0S‘ìzøs¯HvË‹Ùõ¨­ŒÍW’]âÊ È®7Œ#Ùåˆï]³ë4ä¶c{ã,²ëQ š¢È.-X“ìz”~ÆA»¬ø üØ­cô,°[ÇHf!ØåÍÂ6ÁnY&Ñ„`·:¦¹À.{&ì:Ûÿn°[–ÁŸd—#&–ìz Ö1v9˜›¤—h—wдëWì…À€vyB&Ю_k, íòºqÈ®_„8`]j׸fbݲèˆIºó겎ô±êÖ‰Ÿßˆp9Ÿ¦›„ºÿOŠ×-Ë ®[×õ(¾ýîbݺŸ\§KÔõ¨è•¡.‡Û7¥.C,Ö uËÒØ)©.žoü™si€,T‰tùtdºu3 ézܰ“ÂÝÄ+ºnÖBDºì?Dº,°LQsi{­äéò¥À’ŸH·ºa¶!]>b¸l2]8 @˜.¯ ™.GŒŽÁtiÀ·€L—_`4™.?_<?ûú êKD¦ë,úþw3]~/îéò:qsÈtùÀÍ!Ôe›‹º\~Ò!‚PÏüD§?‰s9¶AxÃ<êÙA8×ó…«çz”±ÇÝ$Îå—ŸðÜ2è×&ÏõˆÀÁÐÈs=Bp°OAž[m^S8—çÆ5çÖª•¯$inMU¬"Eš[Ôi Ì­#¤“ÌõøêŠ’åVóƒbX.Ço–ëM„Û–[]èã–[‡¼2$Ëõ[–˳ࣖËC0Ó¤@· ]kŒÙK–[ÍõØS kç4A ‹Ø©]Ÿ‹íà{ês­´5èsm}Ì®]Ÿk¨ÏÅ nRŸk'—6ÐçâO‚ô¹è’*!ô¹¸U}èZÒã е¦ù€]ü ˜_)е(ň‚B}à© B×®ç«ÐÅ•`‰ ]ýd©Ðµ›Iæ¥ÐÅïÓ6”Ëçìܺ8„¸…®eÄÎß-ÐÅsƒ9ŸÝvNtñTÀ/æ'ÝYÑ[ÏÐÁÞ¼'bzË\Š€,Ò›÷DLoÞ1½•G–èm·¼ÚŸ8¾ôö Io/·ƒ‹Þ6 èÍá[¦œûà›76Êç²,ò¹|%=Ùé²z–Óåfá.bYätY=Ëéò•ë¡.c½Ž£ätYc–Óe%§K÷l§K·‘ÓeätYÑéÒ×i§KŸÛN—Ÿ.«c9]V9]j¿©œ.ëärº¬³ËéRûXåtYã‘Ó¥üý,Ìù¶[™+‹¤¹ÍÂ}DŸÒœGgiÎW uÎ'–8ç±Yœ«ÓH«6RçÜÄ9¬Íõßv€KùBaIse‘4'ÐÒÜAOÃ’æbŠ£$ÍÜu*iîÄ*+s¯ ”9[¬Ì13O)s,”¹)s ¥Ì±ÔÓ¦Ì5ÊnæX$±”¹X+˜,ÍÉ;±¤9[,Íi‹ÝÒ܉t:¥ÌÉOÃÂÜIÇæN¦G.aNyòK˜;™‹fæ…9zG—0gƒ•9¹cX™kœ¥J™“pXÊ\ÑY™»$—Y™»?Wn×›2wÿöq¸ÜTA síáòÀÂ\cI’æ …”0'ïíæJ™+‹”¹¦ÝpJsôGؤ¹ƒëfKsÜaܤ9ÔÛ”9ú#”2§›2§-ôRæèñ²)s¥Ì]ü–2g…ÒÊœJ+sk‰±3Ü&/Z›»^qž´¹‹;Š¥ÍY‚´6wMqž´9U†±6WksR)­ÍY8´6'¿W‹s˜ÿ¾‹sò}.qNûèç"­ÌâÝ­ÍÅþÑr›àXÚ¾˜¥Í-î–µ9yÝ—6w¿_K‰¤)qîÖ6¾Ä9©€Öæ¢äPJÚ¿Ž›6Çtª¥Í™í‡¤èÆÚ\ãÖJisr+mŽb¢¥9$ÍuÖ8(iN¥HKšëöÛ”4g5ÑÒS—2×\Ê\ç'ÔÂ\§_…u¹˜8Ñ …9«攃¾„¹:ÈÂÜ!({+Œáù s3/lœDJ sÜJ·0÷0VˆÂ\ÄHƒŠ$Ìés*aN1 %ÌÉwCÂÜ#O s4%ÌENŒ æ*¯·…9+“æêß)Ì)58…¹íOsV %ÌYµ0‡( ërÖ9­Ëé+]® Ôåbo}P—{åª]N ~ër5¥ËY•.§Å”u9­;­ËÙ ]î•O¿t¹WžÒå^~i%˽rì,÷*²œUMÉrÊAaYN)=,˽òÉ–,÷êCmYNΖåô9•.§º§Öåä õ²—•Ã%ÂÌv²;αtY’ˆJç £q…l²S>°"»C2’Éî`)-“ÝÁÀ™";y8™ìÚÞ'²»Ú]îfÆ“"»[6Ùu¦”,²-íÂÜ¡Ð4 s‡D- s‡ ×Êœ"UJ™k×pºx >ÑtFq.ãƒÿŸÀ.ÎÃe¬ÃoºWìæMW)]æP[I˜“¿¾À.B.ÊpôúïL½l°‹ƒp»v3´tC° ËøDÓ…øC™;'eÎŽÔVæ!…¹` ‡ÊÜqÐsÇÊÜad2whËÈÊÜ¡*+s‡CS™;ý'eîhÜN”2w\ôl°2¾ÍPäÌER'vCeî¸øÞ[š;4%Zš;.f,³:wÈEÈêÜ¡Š3V碟‹zԹ㹥×Q;äàau.,Tù¨Î¦Œîú¡tëV率±4VçŽ!ú¤8wLV¸•8y¨®=ž.eVü çŽp² ê\¨¾˜ø¤Î“oƒÕ¹8S§uîˆÏõNwý<á©kqî<.Õ¹“ºŹó`¡‹s‘ÞêÜêÖAZÜKœ;›¼ý%ÎMçÎð©ÜÝ.ûé€&ŠsgJÛé.šÝ­&]œFu.Îýì~—« SZ;õí°ò•ºCÎ]©k§<³¬Ô5fä+¥Î↕ºp|Jƒ„:Ë8êúc¡.6ÖvÂË£ g[¨kÒ×-Ôɨ„:ë ÖêÖcwuËu—TnËu·ÞËu—dËu·]Ëu—¤DÉuò÷(¹. LCœ“\w³^CÉuëTçî~¹Ú¼æ>êu7²Œ•^wKû¶^'ñF‚]gLôºÎEz¦Å¿ozµ9Šu“¸Äº»}¢éÜžJÝ}Ií£RÕ©6¯Ëìñ­Pºø~áé“RÞ·t³ ¥®7¹‚R©»§PJ]—-©®3S±¥:÷!©.–A`7Ju·Þ6Iuv›‘T×åÿ©îéú“Ro»¤º‡¥¬-ÕÝ,yi©î–ƒ¤¤:ËÍ’êǤQªëÔï¥ÔùîI©óÏ)¥îEZ uŸ%ÔEÍ=”.ÄhìtJ¨[OçE„º‡©Î¬ÔÝšz¤Ô &dzR÷Hú—R÷r¹¹¥'›O¼[ž™µz¸Æ×F–=ÑØ?<¬±É,=Ùy„ݽŸÀ–J&[åÛ)K¥;ÈÀÜ>}ɲ÷ÛÞ—,[_kµõÿÞúIËÖ ÿþÏNM6QÊé3“ýÓlc™™ìþó™ÉŽóÿif²ß=,óYOyÿµ§NúùØåÕrÛhk¥žœsL=m9ÇÜ“¹§­{ªœcìiÏ9¦žª‘zÚ[©'çSO[Î1÷äFîik¥žœsL=m9ÇÜ“¹§­•zrÎ1õ´åsOnäž¶VêÉ9ÇÔÓ–sÌ=¹‘{úd&›¡›”˜ìù§‰ÉÖã÷Û¿Æ&Ï¢¸JúõüÓÄdÜãù×{lÜãÏÄd¡ÇëZýLLö'>àûù-þ£Ïõßþè5ýñÿ¯éïzúˉÉ"ñÂZËýa^²uÃþ×úÏÿê,`ÿ^^²OʰÿË·ü?'/ÙóG'ù·ÿçyÉæÓs¿øE1ÂýSIv_F ÷üëE¥ŠXË…Ü.ŽPò\’Ìg¢(Р´» ¹]{f¹¢˜ïá_¹œï‰”ƒšÁúyNL— gZd§Sh÷|¯ç7VÊIïÍù†Ûw–½Êm ©èXZðÄ¿?©ªfõœâ½~ci–‡¬K[TõÌPó_ }`‘e;ʹ£?sß{ùêŸáAÊ ¬Y–/Io"x5=^ôp±êÈæásõËÞ s¤smzÜh¿†=^y¦Úƒõ”…fVŒüU.3|Ãðb™Ãº"}g&þ•¾¹¢^«¤P`âãf$/JOn¢®õ©ùs¶\:ÅÕ%hÍÌ´ó«Ôý9C þeU~fÂü1ÄVojòÔÛgä„y~•$?#S #wñÔ̙ۣý×24…j&¹‹49îëÒeeTL àçÉ57›Ëúe hÿ•âvÞñ°@2U)öeianq-ËÑT¹Õ–冣ðÕ°Ìߨ01£Ëò06+ã#>z̬Ö9šHûex²Í`í¦ÒZ–LÍœšî‹¯ÿí²oÆo{Ti,lÅdN ïL/PT˜Å©Î€ÙMi Ëø•:‚ÆÛ±Ï¼þî×oªÜ[“Á5Z;‡· äÚ´Íe‰ïŽÒ%Dæ²_U§aY¢ ͯ*Ù–!I”·+v\Xøãµô“yy¾þnTM´–±)œëïË7û¸›È RÀ'%È·Ó˜F&ªY–‡ApãX†—A—e0ª‘dayå5xñä“ú]Ãð20aSÃ2¹xáG¹Nh¨*y½,ëÍ¿*ÐpY.¨¨JÊTO~bÃÙŸq‚.3Üë¿x³Ÿ‡!ޤëaŒ#%´eyß¹‡¶,rªùÂÂ8Ç¡w,ê1“?¾¨GÄÌsì9 1µ;€»ASpÓZ†t[AbtÜœ¨G”YºO 8êe\ÂÀí';A1¢¡¨°X™AX¨û¹ (GÚÝÍÁœ*Ãr±ÍdÚöñš(G”ÒÝ¥*Ê¥¼×õõ‰rD™šåè—¡åli½oY®œ.#ŸÝÅŽ3ðxõCF-¢ Hùá‹zD)|6Þò(GÔ`àÝ{›É¥Á²¼9‡FǼŸDàÙüa~2kT»õT=Ѐgúî½ðdˆ67.ûÅ&DXÞ‹–‰á=ú]ŸR˜õóÊrD±;ÄŸ!ê5Œ¦?´Ìߘo¯ÑÒsBµÀ»,™d­rò-Ë›½¼úÞg–!œûÁuç*îWfÒãÈòš¿2G?6©Ó‡ååô3(KY86D77¢|3übYàÛ0¥…eâ¸g¾,ðoˆ£øfŽL¢v³ÄÒúþ û™žœS£ ¿#¬Gä}Ë2rN ßï‡XÉtöœ¯z*ݼª|!u£›ˆNûÔë¹3‹Ÿ?ðù€üʼƒ¸¡óz>c‰Þè•Ä„ooüg…Ê/(èžó¨G”ûº’ȵߠտl3rJœ=YŒ(úÒ‰fÇø™‹ô<³Qüw,-rô]Óљ到;’K»3&Ǽ€GoXÌGÙæÅ¶vìj!ï›öµÂ‚ÌoƒuÏøB)5àÍ“?Èý¦ºïg¼cy 1÷ž´ ûÛÖOú'(ß¿ÀoÌAxñæÄ%0¹ÐÝüÆT†^”#Ê”™kWè¥#oX&†§i¸ö’è ÷g³í w|AŽ~q9ž¼HÎ’ÜË¥šIî…œAî}Äm¹Wœ Sv2ƒÜf`šqñ£@.<2rá/{érL’Sª2“Ü`Î!“Ü8Ć$¹(ƒ.Ir›Û±—è$çtg"¹hqƒš@ruH’\0l~»Er®ó ’ÛþÉeyqt”ËÑè(·€r¹Ù PÊÅèo²’¿MzÎåœðL(-ÎB9˜ËÅ¿rÉr[ °Ü«Âl…r‡9R(w¼?Q.ªTñ\7áÇ_(G/¨"¹ƒNÉErÇÔ}ÉC !’;½ZÉ^¶‹äNC­HNQ"9mÉZ£ä¶9Uö,ÓîIÜiÄÈ)ú¢@.Öj<Š$wƒEr1++Irç#ÆÉi×¥Hî¼Ím$¹“æEr§áY$w2#d‘Ü9uå"¹æŽH®FDrÚæ)’Ûú!Émý¼{lE‘\ë¾*’³Ñȵ&@ÈU·¹véÉÈ)Ò£@Ná!EríÑvŽH®‰XrmèÉ)‰\‘\ãfd‘Üuê PeYm=åÆÕøÂ‹äj,D¹8ˆkr¢Ü¶!E”s‡YN©ÝŒr0ò ݘíW@”Û-Ý1%|ª‰rq"Ò4YÎéêÌrÎg–‹sìʲ>Yαd¹á“F–Û[Ðý>õÔåÒÛ‘€–rX4Ëmûgd9§š3ÌEϼń9‡_æÂÂ/an?W:¥_EŸrèíüØåbÞç´A–‹í<â(YÎaf9G‡˜åb›¯3Y.z~>,ç  ³Üv d¹Xvð’å\¤Á,— –«mB¢\8Gå꺉rbBÄ&Êž!¹­}Ó½™ä²²,Ù $7žÒMÁ¤¸,ÉŠ?USVN‚¸ØÑ|ØåëQq( .Fv} NuÌpÑäø0ܶAHˆsø‹!Îéö q\!Åeå\üys_tøŨSâ¢ÍàQ€¸Øóä3Eˆ‹Å#' BœcGÌq.“aŽs:r\Ô=Èh'÷E»Q ëVò 9.z¹h¹¸3ªí*\íÛ ä²æ-±­wÝb|Éré‡Ã~^Ç•t""ƒ4}wr,q²c4½Û+s@‹AÎa4&¹¸[DO’ÜInï$縤¿yL0Ç»V0OðYª\>¾¹Ì'Ì91š`. ùQÌÅÞèØiÎÙÖDsYþs§9×äÍE ªjÍÙÕà 4oÑNAsÑâiõᅢæ\žS4ç n¢¹1¥p‘æ\<ĺ\uJ]n2A¯u9íèZ—›§…ºñ«öw­ËMël×µRºœG)aÎwBÂÜäòÔÂ\(Ì)!ž…¹2P˜Óîµ…9÷aN{âVæ|·¥Ì1_˜…¹:‚Â\õHaNÕ[¬Ì©œ«•¹1¿0W…”9Ö{±078=Q˜ós%a®NAanxßQÂ\möK˜Þ¿”0§nJ˜›úÈŠå†ç/±ÜÖ u¹í䄹1¿07^­ÿDs[ ÒÜ0æˆæÆæÆàÞ™aÎMÄruÙb¹aåŽ(§ÌŒ…rÃûÊB¹ºH Ü``h¡\]€Xn·Œ£#ÊÕÝÊmåê>åê(¡Üf9¯ÏU åê§ËÕyÄr¾/B¹áõŽP®šäêF‰ä†/"¹º½"¹í(’ÜvÔìŸëÉU ‘œ²_nšœöK“óUZ“ó#cMΣ±&ç»gM®Ô4irVʬÉU?ï»ÿØ›$÷Uä¶k’"§lAÎÏ9$Ž«!Žó™„qu?…q5Zq\ýNà¸ír\=‰â¸m0Ã/àùå¸Meœ~…d9Í­r5>\õ#«s‰ä¶žïóók‹ä¶$¹ºÅ"¹ºr‘ÜÖ†$WO–HÎ7] WÈÕ-ÈÕíÈU·¹Œ@në— ·E« ä¶6¹m49_‚8n;9nëY«9®Zä6 AÎ'ÇÕO)Ž«{#Ž«ŸNW×$Ž«áˆãêTÏý³Éû}Ò„q›…·šWßqÜØÈÎÓ)‡7* 0!Œ WW)«YC Wßa±\ 0WÝ*p<™žAnk2®ï©P®±\µËÕˆåê^‰åêΈåê΀åê‚s[ œ,–«—[,WW)–«GO,WK±ÜvQd9Š(W’ä|‰&9ß“\Dói r»Åó©ð ç{g«ŽÉq[rœ¯‘çÛkŽ«N¦gS"ŒóÍ4Æù+mŒóO`ŒÛ,×ûyŠþ´cF·ž9«7tÝ”>Ýè¦<åF7yÝ”8ÀèöÒ'ÍèöróÎèV-ˆnÊ$`tSús£ÛËm9£ÛûXyã¿Ý¥2¨ž†B7&~2¹)û¹É핦#r‹ÐE ‚ä¦ü&7ƒ¯ÈM Hn¾.‘›pó}¸iOÀàæA Ü<&›G-pÛ ïQÜ” Âà&¯-‚›\´ nõï7åÙ2¹m†©ì¤(’[õAr{KukÊ¢/”cR‹ë¹•èV‡ ö@:$ºÕ¿Ý”f¬Ð­¼Ú„nïÅu¢ÈMÑßEnïõÓ¥òõV³ÐmkCtÛ,D·í¨‡ƒá§Zè¶ è¦_¯ÐíÕf¾ÐM·¶Ð­N$vÓ½,vóu‹ÝêÜb·ºb·Í¢Lt:5ÙÍ£#º¹š³Ñí>3ÐÍ­ÑÍ «ÑM¬Ln® mrÛ-Y¸kz÷ŸäŠ{ •©øò˜ÜÂò|T¸Pn¿î”aiv ›Ý6ÈÍ«MnÑDzÈíU)@’[‰È·­‚[X(Üv Àm·ÜBV–”pÛ„f‚[X(ÊÜ2—Ý+n¡4s5Epse/‚ÛÞä9„ÝJÒº•Eì¦4Ånq*×I°Ûq øˆn‡¥ ±[ áb·ÍBv;ìW v;¬ÑˆÝ{ˆŠÝûS‹Ý{ò‰Ý¶~ÈnÕØ­4v±[éçb7å’)v;ì÷*v;ìÓ v+Í]ì¦à€b7ùWÜJܸVŒn›…àvØI\䦲kEn‡u&Û!—'“Ûv Ém;†äv”G#É­\Dn‘ë„‚É­\ Dn‡‚En›…è¶õLt;^=ç@·ã-IîU0[Ý"Ÿ°Dt+7±ÛQ@Ev+±ÛÖ†ìv˜ËˆnÇOwÊÝBv+g°[95ˆÝÊ©Aìv˜ÔÄnu”Øm·`B=­?‰ÝªgÁ›’\¼%ÞTÆ®àMi.ogÉl¤·­ñ­ÜB„oí6’ßJQ¿)C`ñÛåOøí²Gø­dWñÛvùíö§ üv?ùí>Lk‡i~JÄo%¡‹ßZ¹O’ßÂóõ«ÅíðÛÖùmµ9¨~”æ¥Í‘à”˱N ¦Šà”z²Nñ/…p»·Yˆp×eçG"ÜÅÅ„îb0V!œœHpuîÚ¤9œjÔÁ)­¤ Î¥:+dW†Mpö€«B¹òý…Tc¦9x¼l4§ß4wM©j¤¹ÛQé¤9‰þ¦9é›Ìiš“oškLägškvh$ÍÉËÆ4§$Óœ Hs·Å>Òœ‚{Ls½}Ý*¥XÍ9O4'D1ÍÎHsãP¤inèv‘æÌ^ ¹È”UíbÀb Isñ ÝÁ³Xq‚¹P¸Ð¿T¸›þŽ„¹påo» gO~Áœ¡‰å\<,þøx"ÈrQÀÈ5°\øÈãN’åäþ.”‹xFˆrÂ,9.üòwŒ ð¾Ñ€db\xXƒr‰qáÙÍ1eÕòΔæÂ¸HAî›ôâ-”ã¢xûõq§ŒêSÁrpãü¡'ÇÅHèDFŽ›ÝmÈqå^-Ž›ªadŽ ¿h:é'Ç…/õW‚+kq\|„`Ž ›€ã"Ø72. RÉ'þ×>ĸ8HÊ8nùÉqS•Ìqq§yPæ›Å‹‰q™B®$¸èvˆìàÅ?íÅOÛO ÛÛä"-ǹkpYKœ& ¹¬ô-ïÈóBmðãCr1;qÍÛ2åÝñ膃äòieIr™9ï·eÊ™˜¯xÇArËâA \?šoX. |‹“å²)‚iܚÓ‚å²ä7Cgsý¨`®ͱH€¹<·¶„¹~4ýp`¹J¸'–˼x’Ân”sß:N–ËÄ}|¦ÁrýPne±\Ö>+ .“ôé’îö{É}šLu¿ •TuWö?‘\×ì—9y³€rëT—nP.«£ ÓnÔvO4"W¢\ö¬°·ã{N÷’(—Ùå*ù¢¾ûmq(—Yüä_‰ï*Ú)’[ÿþ ¹ìXjÙ‰ïž ’ËûÇ& rëL‡b§rýxýúô›-xgr™Äoì ×M…b¹,ïvî"\öûî¡q«cÆÀr=WO» ×WC@¹ß¶G–TŠ.PnYì”ë‘ïP.-cŒË ‡”ËËœ»7e¦Eä (×ã3J ÊeÄs÷¦ÌŒÜ#ÊåÍ …;ð7%` \XòOp\æyäÇ ×c9w_ʬ„Çð+p\—M*¾èrÀLŒË çîJ¹ÚúŠ€ãzL œ°Àq•·zq8nYüä㲺?à¸ÊÐ(Ž[m¦î&8.Ûð—Çå¹ÇÎqûhÀq™0Òþ•3¯á_Žë±¤¦*—i ÏÇ 3Ô)Á-®Ÿ †ËÑ*f/.1ù!5”;I€Ë“òFà21$?õ¸ì¤)þíÄà§v8pû‰àz¤™T¸[\&Ääwh²^¡Jœ‰à2o%¿g ¸ÏQIpë(­@py”|0“àV»r&ÀUM\fxü;®ŸëÃÙä^™ïßÙ›£Îà2æM L€Ë¬•Š]K€ËL›Ø—·]&negEÜj#?~\fÚ¼'—³é™ùÜþN‚ˬŸs÷¥\V<;nˆµ»„p™n’ƒÂåQ×îK¹_®bV^¤›ùз„bçùŽþÍs5nn;£-{n°|\µR›ÿ`N±Ö2rÍýóï-wWZ¶,9ü{ËÿÕ"òøô"ËÞl{O²l}]'¶Ð¶+–eë‹¶­/[þ³sŠ‘<òüæÿoæûƒÇåÌ­ñoV±^>TÏñyÿV}mÃØ×žWL}U+õõÉ>†¾öœaèë“YŒ}m­Ø×7ÿûÚ²†±¯=·˜úªVê듌}myÃØ×ž]L}U+õõÉAƾ¶ÌaìkÏ/¦¾ª•úúd!c_[î0öµgS_ÕJ}ý2Œ‘¤7Öÿÿ)ÆþLб?óIÿÛï>ÎôÿÛ¾·??êÿà½ý]_9ÍØà½VçÿÏ3¶}fÿ·û ÉÅÖfô1bÌ?ßL¥E9#ƒçi9û¬½þnÐ`Š<…ìZRCË8C$¸·ü`ËrÿÜ+ÎÊ3ˆ[ž4Põ–s„»´]x>‡ÂYübYF“|ÉòAË—çPé2 Ô9éa½íŒzñeêœô°êtÆ–âØ¥ŸsÒÂÒÊ3RÖ¥Ÿ‘m‚ù¾xá±/˜²Ž‚QÏÈRÛÚ =£jB‡è±, Ò¼9¾Á0HÆÝ/ËÄÖ¶c2ÛA'¥ä 6·›¢†ÚA'ˆõHu¶iÜÞVö¤vÐ Â*I‹- û¹ù7–Ðt&z°[@XB*ô°/!µ«Ù2Y˜ŠM&ã 'o_ Ðk»~Ô¢<3€ñälç¯-wW;ã oüLöHzˆËxàa'¬tbWM§e錃ԃÓNz±;ê±Å|ÃzÞœ“^ì·ÌvÆAN˜^ìð\K˄렺ÖèÇ®ªSË JD¾a÷±EyÓŒsSz¯ÖÚ­01Ð~‹Â¬ uãø"svâ±RDzÜaû­»i‘_ô Ñ«E%ÞöÃ2† ”_+¦왎ì4…e˜Œ—Ó‰è Q‡Dqä½0Ò²ÐâQ™õµºåí»è ñ(ô¹EUkF‰án×7úÑo»:DØÇïÇÕ ©äv=aåD¸,ozº†k@„}¸á–!·B6™vjâS|—^ÔM_¹-ÃP¡$¾™7]!œ¢¬Ý×%¿,þ,7*”JÏ\Ó§©ktw·ï ‰û¡ ­_²›Þïôð^h°¬~´ ì+‡™vOH°ïÔÛH°uª~Ð…VÜ×¢Ä3”Ý<ª1/) u ¯ËB'ZI- 1ËÚÍ~åÆ^–‡‰âäÔT`hÈO¤î¤*S‰/‹üØîç´>éFË\ M†¢þNõd "7ˆúBýÓGÔš›<·,Í^´\”¢-ƒ(/´Œ…e~¢®ZTbÀ×`“Ça:èm߈ŽöÈ]¡Ðíì–ïöCOˆÉr‹zf‰kšJT5Öƒ!>Gæ6¾§ª«`Àe¹˜$N‘­-ª µ_[”J{of‰Sª©öR,žJàÐ^ªÅóá;÷¦Z<ý½z)OJƒË½xzÿ±½ÓiâNö¢ÐMß½A?ˆ©ìm(xS^ôƒ˜ ¡nH‚°Ÿ 5c§t­6½I¹¡©fìT¶‰6À©¤mÐ b²ªÇ²(„Ó_÷1˜'ÎË1˜'Ž[<Ë¢(Ni>mB>Žÿãl8¡G?Xþ, å],½Ú”‚ìO÷dj©CáÐmJFVHr›Ì-åD|mJI¦$Ñ&SK§V“Rò¡TcMec}Ë'µäÃK&–~ñ[^GÊÉïuPO>4]å¨dvÃBE9”ž“hÊËÎ/ ýƒ5˜ë ®|°4ײPYvžÀë ´|h»jˇÖxWTêèçåS]>4§]QW(‡§­âë ¾|Ú¢cÕØTÏÑïI}ùÐv±llœŸ€ë¤¾|háÔ—V\êË'‹…úòIý{Y¨/ûAºÎÔ—·Ô—– ô哹•b£ úòA©ð:©/Ÿý®v KÜ©„iW£À|J<º¢¬ÐùùÅæSSê•ec£—“ÇP^Ž‚z87ëÆF›—8 ‡?Ÿ m(J?w5*Ì‘.xß;Mè zÿ¹”dþeêáþu Æ?‹éÄ?Ëí…‡¡Lü§7¸øOwÌü»<Šü·, rÆ”HŽ$ndIŒ¿p¯)ÇaŽøª†0?Üèe*•ž`Ü¢÷€a¡ Ð^Ûâ¿0pžügmáߵĿ€Z¡ðÏ^΢¿rŒý•׳èÏɰMAÆ_ú+VýU^,ÓŸÝmMv·5ý™°Mv&ýÙ×ôgç_ÓŸ=eMvq0ýF2ÑŸ½^[âŸSwÿLüÆ¿ûˆˆÄ¿C!·Ä?ûÅÿŽ‚=âŸ*ŒGA#ñï( $þ >3þÙñÔø·µQ:ªƒ»Æ¿óàž€ñÏŽ¦Ä¿­ño³ÿìxjü«Ñÿâ»É6Ä?ïtÿ¶ž‰¬¯^ôg_TÓŸR€þìKú³ƒ«é¯:ý†\ÑßéEèÏé½L§×™¢?' 3ý9q˜éïô‚Pô·µ!ý9IéïôjUôwJÖ6ýù^‰þb™ø¥?U§/ú;Í࿺(á_]¸ðï4ïÿö¿‡òšqÇBø·›øç¼fÆ¿ºLáŸ=‡Ì'STÿL5kü;µ&ýU¿¢¿Ó aП3µ™þ–s‰é¯º%üÕþj¸‚¿­Âßf!üÚ15ümÃ#ümmHÕônŽ„2âß©‰Öø·,ü ÿ¶^Èu&ñ_ìqó(ò_,ÖjÀí¨ÇÉåÔ†xzSH¸µIÜÎDlÊøn¬^€íÀŸÄ?ç°3þ5%›7þmmˆªpPø·¨|…»h¹åxê„¿fTü9Ážà/®gðzè-Ü´N6ür…2ü5¢à¯i‹KìwÉc˜‰®È~uÉb¿æ]0Á_(`<3á¯)3’ᯞ!Á_ýF„?'ûUâ>³_Dö‹ñŠÚè;¼µIö«ßˆì~?ìgÇi³Ÿ~#‚ßvE¿-Á¯¶Æ~1~q)Á¯R ]àqbP_=¢¾:‹¨/—Ãb¼¦Û?Ä®³¡6*´¡ öÅ'æ …q¡‡v…}5 û*DGØç:xöŒ mJ®%ì %’"ƒCéQÔçÚÙ¦¾zD}¥<ˆú\NÄÔ· †ÔW9$E}ÑæaÏŒõãêÛ{at¨5Q_XD†ŒÝ®Šá¡­î8õˆL‚ÃCë§"ömç"ö…Exvß~ºY€}ÛUûêÅöUø°¯~*QŸüÒ—ü­oã¾Ø°ffg…±‚ûª<†¸ooÑæw“XÜ·¥x#÷U€¯¸ooîs ¹¹ÏÉÂ>G"”î§`†Òý^St?Ä—îW§–î§ úÒý^Ãe¿WÁ£–ýÞ·D>ÌPuU¿—ª•E¿íŠ~ [/ѯzIͯú äçÚ"–üÞ’Ë÷¬œ –ü^%‰7ô½ÊÂièóí5ômm}[Ï7ÿæ èÛ,„¾íÜ„¾ÍBèÛŽ"ôùy0ôm£!ôU?‚¾êGЧhæÛjßnÅ|['d¾×ª¥˜o;Jµdª_2_Zµdôûùê~ ù6 ‘¯ŽòÕp€|uj!ŸO-â«nE|~¤M|[ßÖ1‰o;ŠÄW?”O°‰ïU#_5™íó‹øê¢E|õ«ˆøÜ‰€Ïo“¯:ðùƒ`àÛ,> |u*ò^]Õ>}wÌ{þΔÚW'’Üç£,÷ùÔ–û6Ëøq ÖûÊ"½¯z¾ù¡áºÝz_õ+½¯Ž!ðmýJï«6Òûü»XðÓͲÞçSYïóÍñUÇ"¾ÍÒ®Ï-ñYjðmMH|›…ÄW×d¹Ï÷FÄ·EâÛŽ"ñmßv™Ó¯á±_]’ˆ¯Î$â{Òcâ«~E|JSÄç[!àsJWßv*ßf!ðm&ð•” àÛCà«‹ðùïU·B¾:µoks?žs!_Ý!ßvr"ŸïÄ[yZÉ€¾ío¥ûñ!J÷S£›çÏ+¨„?Â72_Ý1_õ#èÛ-NúCÃõ½ Q9®/ôÕ`}Û`}[?ïõãc#èÛ¬pÑjSñ¢‚¯Jÿ3¾Ôçß{*bôøBßv¡ÏW-æ«köÕè„}ÛXÈ}[%ªS½®Îö|¿í ø¹²Ÿ†gôÛ(Ðclí{ F¿­éÞý¶ž•¨úQN ÇPù¼ßÁè·YFûñ÷ü<æF?¿ÛF¿ŒÐÏ÷ÜèçnD~ÛAµ8–¸w~?–¿žÀoÍs[(-PHijtÃSêEœ?¦TƒŸ¯@Ü·59íACUSÜ·µ¹ÎO'×ø~gŒ}›Ei<^aßÖæù:Ðûtcþtg…zðjÛYÏ…#Íz]]d½õŠÝ„+²žË2šõ*q¸Xï)ýެ×Ë™”¬ç‘f½J7.ÖsQHÃ^·ó£`ï‘7‚aÏŒ„½êW°g6ÃÞSN”„½Ÿhï9-µñîÚB3ímý÷žÃ‚yo뇼×çOÞs²xßsFI|ÛøH|å™'âs™MŸï–‰Ïã3ñy4&¾­Ÿ¯“Äçñ™øº·„E|¨`ÜÛ:%îm÷LjÜójÜ«~„{Õp¯nx¯úïqp‚½­SÂ^÷¶ `¯'Øsˆªao³ö꾈ö¶¡ö4¢^u"Ô«ÁйÓC±s§;µsgYäÜé¡lÎêWÎu”œ;Ë"çÎ:»œ;½G-ØÛz&ìmýÌö i¯DÑ^I´Wý ÷vËÔøÔqo뇸·Yˆ{õÌ÷j„â½­ç÷þž›¼·µ ïÕ½ïU¿â½:J¼×½£/Þ«ñ‰÷¶£È{uU཭yo;7y¯Æ'ÞÛŽzýj4ä½m4ä½­g_Y|5>_õ,૞|[/>†M|[/$¾ÍBâ«ëñÕuŠø¶s“ø¶³“ø6 ‰o;júm½ß».â«Ñˆøj4"¾­ßv‰o·L]ƒŽ"òÕø„|ÛQD¾m„D¾m<ã{o„|uŒ¯úóÕo%æ«~Ä|›…Ì·õ|Í齃o;ªß?®Aз'¡o ¡o;fxZ•…Ô·‰Ô×§ôÕ]õõMØ;ŒOÔWãöm½ÜžVÏ/öm½(A)aßvÔ{ý¸aßÖ±o;;±¯ŽöÕQ¾­Íù½7â¾­ÅÕ~,]~õK üêÞü6ËÓ~<ë¿ÝòþxÖ~[?³}GHðÛÿ~¿ß“ŸÏdòÛ-?‚'L~Éo;ª·ïû`òó]7ùmãyïï7‡ä·õ2æ÷Y7úùÉ1úU/B¿Ý2ŒOìW£ûmmîóÇ5þ6K÷ü*¿Òç{G»eüø›…ðWãüUÑßf9Ÿãýmm®Ï—ßø·µ¸ûñ ÿ¶ÑÿvËø>ëæ?õó’¥m,³ÙGö+ÇH>áö£' N¥q ÎLùñ÷"Á*D.œ§66D‚åg+ÌÜÒQl·5{–‚#³yˆ$X¸E‚iMB re5çOŒœ Œcª¬V{ Á*-ŒÝdb’`|µxn’`ä Æ?(´$9f‚ç¥Ü#"Á°ð¦“£æ5³£' Æßº`XØ èšÝâÀ0¼ŒzÜ Ã]ˆa¡×1°Šx çUwóoùmÃ"‚cª¬Û± $Áé"Á°È#$˜Ó‚¸Ñ» ·á–$¸[@‚ÛQ$Á°pû0I0þ&÷€Á½_À`üêRƒa‘ï)`0,”ƒaùJ{?€Á(‹.<m¤È·£’÷àÁ*Û.ÜÆU)ˆ<¸[ÀƒÛU‘·»CÜîypoÜ®œ<×ÙäßÙ¾gnw‚<m(· '†E¼†·B2Dƒ{¿· Ø·ø· 0M¿FÜœ0¸0Xîƒû`æóãA' nmƒÛƒD¬á‘·““·«LÜ~²àÞ¢÷Ã# †e|´¿°|¤¿0Ð]š(¸[æ¥Ì;AÜLÜNNÜîy¢àvˆ‚5’à~Hp{H‚û`@‚Ûw$¸u ÜÏ Ün Ap{"‚ÛÉ·_› ¸=zÁíóH¬Á·7Žø±Ìßsràv äÀ8Š;MäÀ}ÀàÀí›÷êýpàv÷ÈÛ÷œ£¡¸]%1p›nˆÛôB ËWúÛ†G ¬¹Ž¸æá”z(0ºýú{†E.£ ö»·ð?Oª¼Ã¤ÀíL¤À­gR`} ìwi¡ÜÜœS¸MÜÞe2`œç+ým7˜ ×ý*´ÏsªtHû]Ä€Û¯«`¿ËÑ” ö«§/p»$ûÕ“¦`¿úìW€‚ýÖãÞ?âßv/íwÙI\Ñ~—D1`´éßp¿­ Ãý|å ÷ÓªÊÑ~>‘£ý|™ŽöózÎÑ~~H„€qáý#þÕÄá~[?@Àº]÷»Jàp¿ëq„b†û]§ðNá~¾l‡û]ÍúÃýüó:Üoµ9ä :ŒOá~5…ûÕu*ÜÏkm‡ûé³àh¿K±»Œö«[¬h¿«ýÿb0óC€q¢ûC€õ8ÜïbÁÍ ÷óòÜá~—â9îw áe¸ß¥‡ûyïp¿­ Ãýê*îw1ÿ­£ý¼†wÒ©ërú%§Z»"§ñ'KNgMˆJµFË'ÕÚ?¹Öþa"´óZ«Ž«ýãdl«Áú:?{¾ 'ÚïŸ ïã'§Óç)î+“|²¬¡/$½·¾dÙûÚZuåÆÝZ©¯{-zßû¢åÓWµR_{+õµe c_{2õU­Ô×'›™Þ‡;#«/Yö¾¶Vìkoõ§Ÿ‘k-®÷Ÿå);~Å~Ž>J™Îë›ì뿼ø×ß'ûÃNÖÜý³]ÿÃv¿Ë6öÏ×dû_«¿ýî»óGߦ¿ýñÓûã{õÇOïïûúëYÄî#}Ùÿ¿“Eìßþè$ÿöÍ"vÅ”Öþá—Ù¼åbĪîŠ\ö|~iω¿_ý=z~3âõšØ! cOæ¸ðõy¸t˜“éU¤éŠ´ê˜e7÷ ¢ˆFÇžÜ}œ(®åøôûÀQÄž?² ºÖ·ý}`‹(¶UR÷q³zÑÁ ~‰w$ÄÎáî3= D¬^Þæ(IÆ¡–›¯rr 4YDyÅîóðv/"ïó¤Fùpű,Øï]xñ¨Æ ù}Ò_` á–¥Š«/ ÷‡œ÷áδ•¿²È–˜÷Éý¡õÁKþŽ´³;Z¸?ÔµL^!°és1Úš'›2÷ë:'Ø4²úâìíx‘<[Âw;o¤îWÂåõ…d^vn,ÃDÊu%ǽۅ´ìQÃk¹A” Á;-iÙ‡hYÉ9“§áy/ùÕöh©|±Áq/<ÌL½‘‡ŠÇ $sîJ4ÆuP?#M|Hæ<•©÷¾ÎÌÊ~NÕˆZ–LË›~¼WWË|Î-ò´a4וiÙÛ#W»ûº3Ÿs{´è\–LËÞ"Ûôõ÷É`ðL\OfeDûƒã{3ŸóåŒõË’yÙ¯›ÁÞ÷5¨´qÝ_3³²Gâ}Þ}çQC±ª_–ÌÊgÂâ}çÑjsj4wˬì±BÑ}çÑêùæiYrUqï;wˆz$ã6-C¦s¾c}NË“iÙï‹á¹ŸLçÛl'ÏýfZöHÆñL#Ó9ǶÚàQ3Ó²G2~Dû.K¦sŽm5þâýÈ´ì‘YŒ»ZgFçü?ZÚ±þŽòðïÌ缊*÷ºÛq Ý•ˆîž{D½ßþ]ú™Ùcûk²ŸÜ#Zçf¡ð»?™™ýö§øî¹EÔcïæAoff_ϱÈ>23ûzÖõ°õ™õzÐ:nésDÚõ™Ä¶Âú;—ZëTúž Ù^ÇtýtOFÁõ¾Þ ^ÔseföÇ9ƒ–%Ë#<1¿ã‡yîÌÌ{z7Ï•{Dëb•óýŽòAq ëRø¡ tXÇ<ô»£€P\Á«ÔŒ7*­Ñ }£„Ðç>õ©C ¡uE„znêáLQE(Ú„ß6ŽB¡ur¥Þ¸ß|UÖ­PÚ›…„zÜ>üQI艳û%ŠRB=v uLÏôìQ@Qø7Š õ(2À™+æá¸†áÏ ê ¥eÈ’ ÚŸGyÓoTZ× Ü[KçÈžƒ«BM¡þFÚ —–dÁS¯ê õÇ…j"odœ{øïÜ&ZgÒrõ˜âªN[z¾ÒÑ g_”êñìçÍ íë Ñ•£ÀPw€è”ÄñÓó:Qchõ3õM%<¦,ŠDI1ä›{¨¡‡ÆßÈß(3´~ÌG§ž)¥öØå% ÒÐ:Q×âe¦”Úó©c?¹M´nèÁµUæ ªq¦+”ü‰ÇD©ãn”Zg×ÎGÖÔ‰6·*`Ü(;”=ó^KÅõ·çgT¨‰çáCÑ”RóQ‡fGÕ!<ü/,)¥öǸU‡ò!l“¤ÝóeϹM´î޲´f-‘¸†¡9êlD‹ƒëC”üÀƒƒWGÕ!<Æì%¥ÔeQý‚޲CùâñÜ(;Ôcóß^Txˆ‡âäËÙQw({ÆE)¦æsÓØ$ÅÔuCûo2 Ã<Ø LFúeösA™|}s@wäï ú[‹S˳ ¿lÁ…4é/ŠÓñf‘þŽCE]E©‘‡KÊŠÿ¢FŸò_(a$Xò_¼2\&“ÿB #Šÿ¢l¡ øÂI.è/°]dú;ýMôK>H¤¿P½¸!@ú Øg‚þÂMIcýªÈ‰þÎГ>ôUwDv ¿µxvÒ_T1zD{k’:‡‰þÚ!ß=Ñ_8q9Nú‹ywô®BdQÒß9ËüËUAø×®jü‹Õ¯Šø³?÷ˆ±ûÀ'2ñ/ÞG¡ð/„0"ñ/,ütÿ.gšþµ¡…–ð/ÞG2#è¯Ábx¤¿ÆçŠè×Ö£Ìû›èÎFD^¢_{MöD¿8ïóA¿V{0D¿˜ûÏú]‘òç&ú]q§`ù]Ý??É/ÞÎëC~qø­!ù…;T'/ùÅ[¯ ¿ë–¯¦È/—/ò»¦Ö$"¿Ø¸áãIò»º7€H~×-ïH‘ß™^Hu ¿ë–ÓˆÈ/\¤¸õEò‹=uµ ò ©!ÎË×0œ¨ÎùÅ"ˆWEò ™L£ù]¡¹’CA~ñ]"ÑüâkÆM,’ß5¥É‹ü¢>ø$¿øšñJô»c©LK _È74 _,íÁ`¢ß niúÝ—Šs ý®é;Jô»¥+úݧbH…~q¹ÅKô‹ñ¶„~w:¡Àä>|“übxâ3_þ 0üò«NøøÅ6ÜKøÅxð‹3“~Qñ² üR"%.üâ³NâIð»K ŠûîK/¸/*hjxà¾;βp_¸Ä Q^rßúy Rà¾ø@ßfLß=UäZàw{7@äw;Ù8ЯŸÚ™úåNaè×o9% ýºóK ýÂî$ÖýºsD ýîø4 sVž‚ЯßLÌ.ò O:ò"É/êmžùEµÍ—Ç€üz*–°€üú(ù=‡/“ä3 a›è»n¼¡D¿Øx¸?ì×ÃE†mÀ~Oþ†/ôëñ‹§ä÷ÜÚLùu—–úÅXøàýb¦zEzMû‘“¤öK'>rØ/Ýy&°__wÈ~=rl‰±§úø"û…KáK Øï‰¡X/w>»Ï ö‹ü]È~±;:>ìwâù«ùÄ ÿ²ÈéÿTèÃø7Tƒ×øç´ÌÄ¿HO´#þMe!2þ­ÇµÀQ™Ê§27Ršð/,D£Coâºð/2¬ñ‹GþKÕMÄ)6í&‰ÿF.šÓ ६CV]Õ àúFD;*€Mee­†ÃÁW<äªo ð0@I<½Ü“IN?¥{8c/}É€Š,0Þúšoo:‹ãEú2à]8ªˆáC«41`÷úI ª4Û G)¶˜š%Û¥6ίxW C`€¢,ŒR´Z&ìÚO4ÞÂa1àº~±$ð6‘óVð2`8j ²0nñ% šÂ£•D  <ª1`8,”÷ñ[QaéŒ  嘘MŒZMbÉ›õ.í'F%[.GÁ€Ë"O32`Z†,¬ït ~/Æ _Ö´À€Ù³t8:‰÷ÔuÀ?5ô3ÒÄ»‘ †^â]; w|—¸§rÓI<Üú`èíDÌ$n€ï¬;È6/¼S#G4û¬E1}Ôd-ŠKO>0W“\$‚sÃAüÄxáõ…¼JÌM .äº ÂXf’mWEkê`À,ŸÃ;Ü• ÊB¹½xn%ˆê–÷^æ¦1ƒïH÷Èo0cÎÎb@ÔSÚ%ÀeyLb'ë;u-ùÁ€H?BòºXßIY>Å€×PÕ%Aà}{|‚ÀÛ_r`|d^‘ajñüãe]æB>@àáÚ‚ÀÖGÄ“©‡}g±A"¦'7™ wLg¼F@àZȽڂbG‡m¢¬mJ>vùï—é×›aÅ ˜/¯ò•“¸•P0 ÜÆwD”ùé¸ä^Ë«twy92àz]ÅæA/ñx£oW¾OªMÌ÷é–‡r0Áb<õƒˆˆ\”Ô‡ˆ€Í/Ne¥†!¿ŽBÀð>ÿ `þ:[ÖõNC`xK/æú]–gîúH€Q™(Œâç|¢ €Q¼ý&ëýâ7–xtÝ`òß± ü±~‡,¨ÞTçxœÊ3)ÌM¿£¡´–ƒQ”SµAH€w¬Ú>x‡wþ±Kwxð Õè!.2$IFQ®«¥üv¤‹x°‡„>ì«Æä-(dÜ•\ˆ€÷ôLLD¨ÑHq”ªNÜ"A€w7ª·€/0öt.êv@ÀëTY `{ø{‹c—&¶ðm’% 0 O2k ? ›F£ÂÉ*éªc Œõá—sUI C¢Ž0ê“oxÜzÌ€Q]H<ì/<šª>“nUâ¿\ÇKéKþ;ùù‘ÿ¥8ÝD9´CÌçññEÀÇPˆ 0_šIÞcå£$ÀeÑ'Š˜Ë¾ ÀüÊòG †ÿÄ—oÙ›ßñCý‹>}$À;î#Û̆ͪÈ$À«[:'Æî! n쿟Y¬ /'Óô½Šì0ô©,ý} ¸ ô]üBô=ü®ìÐ'Ë?>þIâ³—ÄF|üú‹øÖàœ!âsõŸkg™øÖ7€ë=:}êKoÁo-)øMïÀIð›ö^‘à7[(øM…\ñ]–I|ªzfà;ì‡'à‹J-4°ô„=[Á{ç4røbÅn |M_vßÅ‚%æ=F™÷¢7 5?r…5?Á&úŽÄ{·J¡˜÷Öç–ÓxO4%ØSˆ›aïQaœ‚½©Á ö¢8R6àÓ iï-u‘´÷#"iox‡´7=i‹ö¼õgÚ ÑÇPñ‹M %¿Ãn„’ü\/Ì’_-•$ùµã§äW›’ü.¥íµäçr¾”ü">•çîEzq%p/ÄEv Ú‹|\Bö⣨ƒ@{Ó‰çM{kÇîñ™ÃE$i/>ød½ NëÅâ—>Àd½XÚqsäaHðã½°^>GüÖ< ŽÏGó0¾ß[qKØ3vÍoµèÒ¨Æ+L¸·ãÓØà ^ºrÔy~ç€{¹¤Ü!1È]óË5.F¸÷(¤±p¯”8àÞm $îÃìIÞsÝó^¼±RøÀ{CåÆÌ{ŸâÞ™qoØ—\¸eNåþ™’_,ÓøìSò;ëª)ùEþî„PòËd0H~Ñ‹dBH~ËÏ#%¿Hr2>Ξ,rO}á/'3â^~øR÷2¿Ík'"üûpLFŸ,Þœ¸—Ÿj¡úŸÚ6œLš³Þw*ß“Á«'I‚LšõæØ†ÁåÚ;™4ç¼¾žžùîÊg“IsN»:M%ÍqLÇTÒ;ÏN%͹w½/w¾ä³IÜk=4‰{®™bÜ‹¯û!îE1"q¯ÉoÁ¸×ä˜mÜ»û~""øømwô“qx ~y³L{—Wࢽû´GÚ»YQÛ°w÷ßvÖË™ï&p1iN—Y/ÛHrcÒœ.Üd½{–‡Þɤ9ýp¿LšÓÏÂ?L©O³¸Çxàõ’<=—å¶ezÈun&Íy|ƒ{ùôÜ»ÞwG*">€½´H© Ú;û02÷Z‰£Ä½X±É¸C8ظPÛiîE,¶¼AÁ{Ù³èn41­6¡÷5«áüÚÙLsPü"‚›w9¿Ö´-Å/–ƒ÷Î{=3åPaƒâÜ Š_„Ñ<Å/Ú´·'rçü½p/ùðTÀ½Ü}üà^Ü.²0q/ý|`Ú;‡| D{­ÄzÒÞYû0¤½ódÐÔ_I$¶£’Jú©Xy¡Å×"?In$¿Øº ’ü\E×ä§m {{Ú}ÛÞžá<É£ñ7´q.oÏiç3ÃŸÚ …z„¿Xfå¾ÓÑÔûn»iRﻪõ¾nÇ"é}·R\Xï«ýaé}]yeL÷ïô¾[Wá_¥'þ¥ÊñqùŒ™Caw­s¡ôñùÌ´`TÁñ¹U(¡RBu‚Bþ\~Ž˜S2ÙîÁÞ䆚Œø›£Œø{í þËítÞ.ð_î!q’fÄŸ‘[W jˆø‹˜:ž‰!gSò!…üeΊs.2ä¯ÃBþŽþ*–!‘ôcÓû0ƒ*ÀïD¸œö/ò×bEJJDÈ_;Ï/æ—©ïNŸ9 Ÿ¿³ ‡ê!ä/& "!"þòéÙ}>Ó9îÞõ¾ãä™mõþì¸f¤Ë8ʈ¿ÃJ}>cà‰àòyƒ]>ã÷ÚÕ¾übÝ;ÿ­›5D>Šøë* ψZ~vþ[vïî¤Ïg³£‘}>_%S‘ÏgüþŠ„Ïgw1 Gü­{õîzßúêjF±bü¸|^‘…Áå3œ †—Ï6íJ—Ïø½u.Ÿw†Ýó"ØKpº|^:Ê^èò9å1/—Ï?ähèòy…+.Ÿé¤ø‰ø ? ”Œøë~Öèò™ncì.Ÿá%¡îàÞ¤#±7Y>‰tùŒé²í˜×0w¹o=Zþ9ñ7TZrßsøuVÄß¡µ‘#þN_CÊ}wíkPñ‹™YPÅoÍEŽ$„âË‚W ÜÄšê½KñëÃ$øE\èWð»bƒ†˜ÅÃqyðúŒäjl§ÏûÔ NŸµÊÍ;…û9FNŸ=–ë<NŸ‘I·NŸñpp=NÊ.%§Ïp$$²Êéói?Âý–ï ðÉ´:i¦o Œ¨K~¼ €ážÖ>xÇ<-À\Ø|¢ýBî=?xÍjÁ/žO~(øeT( ÐûîÚ¢Þ‰$VEûEEgòÓ™±º‡dN ~ñA‘ó&]>‡¶¾í×ʹŠ_u¿ˆ¯Á‘̱TüòÍçQPüî>õ+Èåó¶”\>OGþSò‹Œ†üíwHQw´ßÛ¾>ŸOEƒ)Ø/`fWüò~J¤Ïçx¬ºÁç3]wÅo]ÂmõŽÁ~Qü“Ge°_ *þ„Ïg% 7Xˇú­Î3ZV:\>{T²UðÞå[[ õ[@úÏ)Ö/¦©{'´½ Òûâ³É;—ϦÒðvù ·z9x¸†öCð˰t¶a´ß¸ì:Êh¿Ëa…Ðû"2²}‚ý">•ÐJ½/Ý% …tùlYíò9|€1›ñg"Æ—ö!$#TW‘}x›çU> ðø¼ä˜!|Ö¸‰Fòøû’BI€111¬”O€õ=ø|>‡UA`?.“$pÍ“ºYŠ÷[K»þQüâ—"­‡~9Þ¯´Nû|jÛ ï˜ñänù|Nh8{*±cæÂy­sCúÿo2Ñåì¶üÝ–@ ¬bÿ—r\µR›ý¸¿Jìwg(K§;Èß~wŽÿ}³(eJ$ŠEü§/[¶¾hÛú²¥úÊÌÉóså¶T_²U_eÙúŠ/ÖûéË–­/Ú¶¾l©¾þ“Ò“Å£÷8æØõÕ­ÔS±¸¼‘*Ó 9Ïþ3sx_§“Hý®ÁÞ6VÙÏ»·ý‡ý"=Ñ]ùË~ÿXD,×µ=¯ûÝ3Oç“ëǽ•ºZ+–«úÉ¿öNøÏêÁÿîÃ3ïï¹õ@ç7r?[+wñàc Ÿ®ÜÈ]m­êñ_‹¯Ö«+ö®ª‘ºÚ[ýÙg&ôûkÍ…‘zÁte÷dëŸüéÊ~÷ûÿÈyöóéùÝɾéÊþøqúƒteâ‹øGßßÿþöO¾a{«?zZß×?ù5b%¾~ø-þKü(!HçܲV§ùƒü÷ÿš"ÀýüË÷¯kŽ[?tÿ—ÿá_[ì ¾ï¿üþ×ÿi½Ÿ,0žù[ýç»nÝâƒë_þçý/±¿þëÿðÁÿç¿Æºá=Îù¯«Y6½Ýwø¯§Y‹m«È]ç^ÌOšµ«Ò¬]™fíùw3¬­v‘W-2 =»ñ¯äU»¾§yÊœ½þ[ý])Õî?‘R툗_¥çÖËÚøÄä:ëD  ¢ùzÐäitÝ™5)-`ŽŒ\Œ›õJ„¿ž¼µíµWËõäæf O.&«©9 ®D2R3_ÁLI†aœöìzñý—Ý©R‚LË«½çx|Û[Žë‹seÇw†0øÀÒ€€œÙ¸‰³‘/>îÖtH÷z`΋÷«â;ŠŒÝŠ޵p +‰ð±¼jáX¦$GÉ>mŒ»c¤I·ù›µØéx•à&ßÖpº"gÐF ¯1!Z°A /¬S˜”okDï4úþ¤Aq\ù²Æþ yâN±¸Å %Øž[¸iÁAO ÙË ×¢þdÑî]8Ï›±µm”;2u^‹ ŠN35ÈHJ.ïÊ™©èÚ0‡>p›k •G«Å«ŽZວ¥ë,,éÌÞbC·†1}iÁ/—ñyËЙ9ò_Å›^Ø!z"%Q´Åþ<¹ÝM eª¨¸‘ÈÔ¯jDàl^ÜÙhò{¼®!éa3³Qhf7”c³:Ðwâê:÷“Së•yfó¢®7¿¸Wf½IÃÈîŽx£B…;ãfÝœ–²<ÐwK× ÖêæÈ)1«õ؆ˆe–œXs4ÙKTº;N㬥ـ‚NÔŠ>Áo©âÄW~ÄÚÝsZͱåÜœµÞcË/ßzrZÍ‚xÒ¢8ÐsâÞuŒeä´šGègæ´zÅÆ?žˆÈ-:ãV=ô¿Èâ@wþ¸7¦Õ,4~9|&:\Tñ1Ä>å•ÓjÞᇖœxòqÄý̬¹çÃõXëÈÀvEèÊ„%ÖɸÃ9bs$nF¿tª·ç«z10º6‹NÆôÿéœjl¿cÀœtvÌUÆÆ€Ä°a)–Ùµ# «ÏU„7*·L!àÃ…I! ¤ÉB@%66Fü4@MxK1ÞÃÓˆ€·–FÀxz€wBÀ»Jï*ŒLtÅ# |OÍ€—3Å€Ê`Q xªøŒ°+0× mA ™ËxbÀe!™‰»Ä ñtâ(A s¢™ÍØ\]ØÅ¦À.7kS`Wȯ(°+¡œ)0€˜¡9 À.Š1Æ ¾M¤À>$¨ŠEº GC ×Ç€>>‚ÀÇò‚Àpt”_= ð±,|ì_$ŒàBéð¹®L™œj8(0-ŠÅÞ£|2ÂÀàs ,ÄÀäó¾rˆ‘_gI±+—cr`»ÂÍ‚™8ñ‚‘ƒ2!A0 ¯šH0ÚС“$˜ÿ!Á×¢¿Hðu‚8‘`X¨k’ƒü±0 e\ŒH0I0öp»D‚a˜(Ì~vŒà*Ü?¡à«å’P0 ¹|PðuP¼P0Ò+ö ÆQ¸¥BÁØu …(˜{ €:¡à¡½¡`$1™„C `ì1à FZ"œPðw°Q0Ö] 6¡ R5š}¸M‚SX Oåà0žú cc„.Ì€6@A0v3„†ÁSÑÁa'sàp`e—Æ¿ 8²0ÜÆé4ž$ŽÜþµq`¤TÁ³.wB8œ¸AMpûÄ1N<9âÀØ9wŒ 0x9E‚Ã^I‚™N’`XpÓ…‚Y(PGÌý•_ çQ Æö ¾‰"ÁHò%ÁH5‚½ ¡`$ Á«Pp(”ß(8´°0 fA¹\ü‡—gBÁÑß(8 # ¿Ö fEcô ŒõB·DÁ° À"Q0Üy°¬ Ɔ ‡GÌm †(Û=Ø•(˜éf>,8¢Ì@Š,8äµaÌÒÃÀ/Â`¤¹ÀAdÁaˆÃߘGÌ„è—(8”I^(I󃂱ߒË9¢`ƒÓÒF‚‘(#Œ]%XH‚¹c”/™Q0ú%FkOK(˜;O€¢`Jt!lŽ  ¶x•°¬' f¹@\8Y°¥[-Ücœ«ƒiÇ #î®ý0»F”Mßa0wµ@R6Y']¯Å‚Q˜÷,˜ÛLج ææ ,ئj ˆÓÒvÌ0a°eèFÌ:‰hÄ©@€ÁÜs#A[ÖVùU,˜ux(È‚m*£¾`0+DÁ‚mʳL0˜V/ºIlü  ¢ -i0·ÎÒ=I8˜ã婃ÍQ€ÂÁÜ^ÓDÌíµ±ã`¶ÁË@Ì­'ü ÄÁSkîPæUsˆ&ŒmÍ_ƒØöúU,زà,`ÁÜíÃ%óÔØ 6§è æ“…‡,˜?î Æ¤žÓ•YðÏæX3ö ýÛqÐaÎÆÁG*âÁ,0¾ã`|j`ÄÁGëóà#ÿ#óà£YÐ<øXÜ>Jæk|IÀ<ø(ôÔ<ø(†Ç<øT¹qò`ÄÀ"Œ, _ôx̃ Q<çBñà£Èñࣰ-óà3\ <ø0™Šqð¡{½ið1­ZTÆXq kB™m1“¡8Ðý˜ª×8Y¨l¤â@·!úÂÍÕ>ràãT©âÀ:HXgÖQâÀGá¿æÀGN ‚þ,}åÁÍBôUÕ(2úž}Áj#¬ž ‚~ ‚z Äþ[XçV¯ÂÀêVè;a ôfà›00‚E É ýj« 10,ý£†;ÂÀ° >Fø:tS˜ýì ¸5!æf,Áüȃ ‚Õ‹@0,ä,‚`=9Á×¥{‚5}ëäÁÚ;FÏÏG¬‰I$ˆn"Á÷‘³¹H0, "¡`–ê@¢`ÌŠød kž æ.èëôÜúÒ ÉU^ÂDÁ×õ|„‚aé?M®Š½ 椣º&We³ fŒïÕ䪌‚bÁ|€C“«ÅÅ‚nc Ë,ø*³žY0,ø%W×§‰ë.M®LV#Œ&/šÜš\)‰ ÃÀcͮܭ3 æA øF0˜œjj~mÔǃ±W8u‡&Xµ ¦å£ ¦eþÚ`0-e0{ê‘Ã2@v]S,C²ƒÙæWÑ`þѼšb™š@4˜§þƒÑŠ™pÐ[¢ÆÁ´¶NM±<µhp;¨Õ^+t,Ñ`ZÀ‡·æXnšs‡c׫S=šbu™‚Á­›WS,Ë#ëÇ æQ¿6LØêà Ëä3†Áê—0èNÄ‚õSг ÚÜš`ubAoL›ó¨]Ä-e¾š`uÓƒ9>ô<4Áž_¬S ë2ƒy-š_uoDƒvQ Ö¯ ¬g‹4˜çþµÁàvêG¬®[0X÷O0èk nMæåwõJš_õÓ‰ëšÄ‚ÛQMó+ESÁ`Ý>Ñàf¹»_UÜ>Ñ`Ý Ò`]¸h0›àÜ/§W7‘woXàËûÏ®• Kù**ÒØ•]Sh÷Ä"ÀC"¢×· "­Š•|¨PÅ⊕L§PeaŠ•¶µðÒˆgMRÔ펚¤î¯S胸 vVh‹PÝ5Eõ/ÿÙ`þó`Ä—\V €»Š•¢PÔE€·Õ?MQNnT,o1à#7Ìý@@¬ åðT ¨„ã;â!(§ÐƒQN¡Ú·S¨ÜÁÊ)ôÖA¤À·;_;§¨Ê, |•-Gø*O‹!ÐU • X1yLÕÅ)j4ÇOsŠŠ^ÆBÇUUA1EßÉãf½(p¸ú(pHf7: …)pJ* tZ Q s ›g«ì“ùºÆîé—§j6›gÿ©NWSÎG!w¢Àé‚u¢Àá+¢@æ€NgË΃/ŒÐݧb.€óäCkœô¸3Îλ'œJÝ\R ÜÛ…€SUíz(¬Ð^¡K‡Ø)ôPaL;…J f§ÐC¾ö¥êíµSh€GåzУÛ>¡‡ˆ´„ÀiP ‘ÇÝH<•ýÂJà©´VOå¶°¨ú2%^Ôç$žJ d)ðTÙ’•6ÑR`S]ª’URµ¤@%´x*ÇwI.Ç%¾ò-µ8å[*-0çq”µ@y”¨rï%ÒCq•ñÞbàïœBõè&-pò·Ø$ìJ 0ÍZ j|”¨ÊT¥6‘¥ÄÀK…ï-^Šï´x± µ@—Ï+-P;?ÖåÖ]ZàÅg²´ÀkÊ7ÓZ Ëï”x3ÍCi¡2¢j°ƒÄÀþ¤%—¨ìÛ%*qm‰r•xÒÝ¥ÄÀó’Ì(1Pû%FA X$ž·HNb ÒE”¨¢¥žLQjàùšö(žSŠ¡äÀõ$³Ê!( Éñ°ƒî(*T½ôÀ&z·Ø¶k=°Ýr½”Ø~`hãÏîšûÊ×%r“ØôCXlS’!0žm\¦åÀ65@É—=A%Jd/9°uõCŒñ€YI€qÐ  ¢#ÿÈq»àõGª—nŒáÁóW8TóÝȯچ€Ñæ¡@Ȩ‹ë’dHJ#nôkn ËüèéL¸$f%Í \¹Á¸pä$fˆ,dÀøÿßì½K²î8²9•Ó¬jT $0ŽƒL ]™©¡ù[Ñ}=Ü‘7"•&«*«VÄö‚Ÿ|¾ü±vœª|nŒ!øÍÉ€“€MÈ€ù”Cþ#Nô4NUf7FÚJ‚À©jÙ†ÀPï?ñ¡ïâú”NGÌÖ0Ap¾/ øHqÙ!‹sZ@qZxW™Ÿþ“U–Êž7>Ÿ…€Ú ¾?ûø»5Øv¼æÕ±pPísƒj'n ñ“#8TÅÉ88T`Î8XTiT–ÂAs¦qP9…ƒÊ›)$ûo9‚‹kÙÊTÛ›ÊT¶ÊT)ÀÊŠõtŽà`>Få~ó ªnzŸAèŠ UÓ‹ }¸þ©QÖ ®øPµM¯øPmTñ¡Z4U|¨-ŽUéÙŠedóª¢ÆªÒ½ê|?LJ>\V|¨«°;>Ôó(>Ôýº¶øÐFþs|èúá˜*O´Å‡ªå‰ÐÓ˜Çt7áPk0a5}—õÍRÃa¼õÔÏEß,g-*MpëšÉo–»t;OðTVå ^?„Áy¨_‚ó«W¾Y‡kwšÝOD¨jÄÁÛµ…ƒfHãà¡úšÆAuj1NW1ª¤Záà`A á¼T€ÅÁ¡jYÁ¡r˜Tp(<‰[l¨^'ªðߊ =4†@øþ'ñ@Y«€;á£2‹‚Q¢àSIôY>ªªnQ0–ž#QðÌ3³(ø¨b©EÁçú) >×ÏØÐG±‚GJ|ÔòâàêµÖÕŸ*Mpñ'ß4A‰„¥ ®Ÿšàúaj–¿þã+ 2“@Tðqp’àkÁsè$Á¦~3NT(Tá” i |†°M@èìfá­HZ¡ÛÎ/õ]1Ff EBa”ªÂÌŽU+«=:t|£C;NE„¬‚* t;@á©Rû³ÿöåA7<6JÀ7*Þe<.~ „‡"® „‡ ´é)=p‰x¬.†ï—n«¯è(Dëï£sìCc¤JC(Að¹(º[|Dòß§¯ ‚ìgTzࣟ¦‚C¹ ªèЩØx‡‡>Švxè½¾©‚-йãýâðÐbC†‡Ê5¸‡‡Î 8§K-¹Û»¬?¾µ€²Vè8mù[öºj¾]Ò˜­Ûï÷P–ªUösÿ}³T­²«¨ç3—-Û\´msÙRseñéñ9s[j.Ùj®²lsÅê³æ²e›‹¶m.[þÝõØú«¸ñ¯Öc»þ¨Û9~üïÏzl¯uüÙXÔ6j®môG·Å5qU.ëçM·gƹïƒ4 ®i\Ó$üwÎàöæ.µæ¶RkžÄ£4Ï6ÈS¹Ôš§ÚJ­y*ÒTÛ ºýUjMSí¥ÖêaÕ(Nõ¯Ôc뙬Õÿ?Rí¯¼ÿè½óû÷ß?þÉ;lõG7ëïçúÛuÍzÔÖˆ^+ÿªkö>ÓûÔÿ£Ì1ëo/Ìÿc–±Š›µÿ¼¸Ù{i#Æyí·o|^ýô†õì«Á$õ\\ôvðî¨TÊk™ðî\LÒííÉê(f¶Ò2;ôþ‹ÍßÜ´‹Ò}jx³ÔóCÜû1 ÷_l¹ñždƒà¯ÌñuÑ;óÂey˜ ÁÒ-ïÅtÈRÞïQ;ýÉ1ô ¿C8dYD©Gáö›>ÈtÖÄOð=ƒ†Gß±©}ÏŸ¢ÄÐõÜsbÀºèmX~ô÷›î¡@ÁŸYÉÑ;y QP¼1Ä[´‹áh”×ûÕ3[,£Fp¬Wh„^lt=XÆ:/%*:Žu~Ûë>±þ”¤GUï‹øƒSºžÌÒ„s3Ï‹ P¤Øõ+ès[¾†eXÌÅÜ{±£ |ÒµÓ\q¡=Ê>çò3@˜–Å´_–Âï£ßx,ºoû¸R7†Ó [“i¿S[…ïéZߨû}Sígº÷ÇïVû“fûXßàÿµLj‡ºÑƺ©ö³nT¿ì_ ¯Bá}¦«%Ç Ã„vÈü¯~·Aíp`ÑÚïèÓßèIBð›<öZ&¤ÃÎTô÷n€EÕjïÙß”bvýd¬@‹ŽŽx,ïg‚cù’g™eü3“•nÎ÷ëÙóA §Oîû9²âÃ==ÇVlKߟ33Г0qÓF%èdEìö'|O  š¢×òäs…Á’Çz¼eMÓŒVŒ>ØÕ}üF$Æ´áËÌUïOòçd§ž¹ðqÔ¹¦G M²â¢±¥õDoxözáÌ!̙鑖,B¶xéñ§j¸¨ôL`~@:xÉQJÍôDܱqí‘Fˆ¤ž—¾ÃY€ë›ÚÛBFà…1¶~!qïÀ®žŒ’É­ðRˆ €iAûĬ•·Àu@ÛÉ]ݘøÆ75jcašŸÔ5Y'.; ÔJ`-ø¤FÍ­‡~§G Kt*ÊRm ³ËNE=‹‚±¨~v*š9æÁŠó;õÙªè‰*=j¡õ.£Ž¬ÿtPAÌNE™ó;—†„üÉ!80_GfÇŽžÕÈp©¢MÑÅRY7Ì ÕŸ¢f]ùE}-n¬lS4OTžJï`´)Bõ§“irÙ¨(Ë?Å‹*÷­È΃зìS”ÕŸuî+‚gõ§“_ÃìS4:&ÆÏ}ŠÖD­¤ cF~Uóq9£QÑ\(aõàŸ‹ ˜Ò­Š²Ë3¾†…PJ†ÍNEŠ\åy÷ãB¨¸~yGDŸ¢,¥Î¿Wl€ŠW9oô)JŒ»XK&­«pƒF£¢,NAòmáæ‹¦@½¡d/:eý§›ek®þœ¨ÿtÝx0³SÑ=1~¼Ž"ŒY}*Þ²UÑXƒÛ";lgÑ-æf¯¢¬EA"[%¼Fúd«¢Ø&Ö-Òó«úî‰ïÐèTÏ*Ž]µÚS_CG­¶h(‚yîü¬öhD…7Ç…T·wLždôrÉJmÑÔ(/Vô9ÚVö*;]AzUñìT”¥ÚãT²SQÏ Êt²ìTôþŠïV ΈNEYª-}æÓ<ª£Rß3È0„½3rÅ‘½Š¢VÛyêúhcbe´*ŠgõTÐÓ5²ºÛbbö)ÊguNÕÜdÀ2ó³Ú#bâx×…gUÍç¢OQ>«Ñ"/WpÙ©(žÕìì‘ûºÏü®æyÃвZ×»Ùạu„^¤!?«=[tå}ŠâQWWzû³OQ<ªçEÙ7ûáQe¬Dô)Ч"ÏgŠbšÁâ‚W4÷ˆGõì¬q’Šü–<§•ŸÕ~Ê‘C\­ ug¯ç¼ð¨ÆZ$/<ä‘ Ú_­jö¿öþèŽ4ü þ~ý ?|‹üPs?Š×ø±õØ~7ˆ7ð»¡slàwÿ?É~ãë ü.v#+ð»¨~ü.¾Ú ü..¿Ä}×—Šû.[Bßµ Iô©ZAßLúû÷©¾YqŸ9Öà7Úo_î”'ìm*ìSjJaŸšzö pö –9,ì f(ìS˜¹Ï|l5÷E£>0”¸/Öì_î{Ç`mîcQ²Â¾›ím ûn–--ì»)žû2Áóƒ}™Š™‰}‘×Á™‰}iù`Ÿ•vc_–+øµQ_–ž‘úBóÖûÂlö¡cuNì )%EÔ—Ú -“ù”XM}¡õàèD}©ì`+b_Œ!”ûr+Xˆ}Áù[û²ÞЋÜü„k#î ©v€­È}!ºæºÀÜçúäæ¾Áä¾xöåì‰Ø—•ÃuÀ¾gŽ/ö…w@b_xð菉`½/õ…ƒáƱ’ú²ÌYþJ¾tBä~…}Ï‚˜jêËl’_ô…a‚Ä}‘!ç_Зi˜†Ô® 2©/•GlEêË lEê ®·¨/ó(y ¾=Aý¢>—RõżÕD}á"Á[MÔ±xŠú2$FêË@rZ@}®sfê öMèËøïô…§åÆáú2~#OJÐçf¦¾ŒöÆ!“ú²†9ØÞ0©/DШ/µè\ˆúbÈ TõMã…¨/âk6"õÅFœ†Ô%Ì:àŒÔ÷ ŽÔÒøÂÌľ©ªÙƾŒÜ¡ÔðaW¤>„›ú"ê8S_LCô"õÍ®¥®¨/ä}±/sp¢À¾æ¾»Æ¾°pHb_:¦x4£nÞ8À¾ˆ+ÀjžØ—n)±/R~ó¡ä=€ùœGOæKo! Ì—! mg¾,‹e#¡/çÁêЗþ¯c}ð‘ý*æ«Èj1_zÄpÓù2Ö:ß÷b¾6aæË=á!ó¥%ï{2_úÕr×d¾× $%óE(Ö¯¾ô»¡ |ˆñ…ø²fÁ?VFtãR‘ør .0‰/ë*aiLâKÞyžÓÙp7ø²ŠÛNºQï.H]t£Ê-âËxrrØ1U’-ß"¾œ$âËYˆ]~Ô‡1"¾ Ÿ¹bý¨isÐúÐß)âkSi‡"¾´`â‡~ÔI8'òå`Z_Ö‡;1É¢5ü7ಃnÔˆ‹È­H|­pÀÒèFº‡I|i£…ćêt Â‹~ÔÅ"Ï$¾4ß©‹9#I|y»âBâË3˜€ÄGŽT¶‰ø²~YsÉ“ªŸ’ćc鿊øÒozƒ A|è¶€­€|Yb C@|é¢%&ùÒ‚›„È—»ÂSHäË“Àë‰È—db!/Ëýaß>©‹*”ˆ¡Z°,|Rc…]/~RsAD|yµðìùp%r‰Ÿqµ»ÿFñ2S_xî¿Ôw“¤‹úî‡Ë"SßÞ´~ÊI÷=M ü,/îSâFqßÃWJqßÃBøÅ}Q÷Ë}ï±â¾‡Ý‹Šû¢f"LÜ7àmìSáÙÂ>/õÈ}óx¡ä¾X‘ìý2Ãñ×F~±àÀ¢Däçu€É/V ªÉoƒTGðË€uX~q(ýC~9 „C¢_Ú}Ø/s–>’_¬š¨’ý2³r#Ù/,ÇGòËðZÌCöË,`¿©ö#f¿уfAöË2¯€A²ßT±³_fkÑÂU¿(} þRcûh~™ÿùkc¿B®“ä×X^§$?¥f•ägÙÍ’_§£¬$¿XafI~×%Ô“ä«—üåºø£ù)\±4¿“‹$¿h} ¦”äÇ.D¥øù‚Zñk,UŠß{ÞóJò;™DZ’_;tt’üNT7-ÅOyœ%ùT Jò‹î߀'I~ñŠ¢Iò³+Å’ŸVü_ýVüëF•âw-A&?…ý•äw J”©ø]V¥øuK‚RüÔܾ?å:–ä×YáÝì—Y+¿6ö‹ŸO¡à/> Ä/Âßd²†Ùoª¯–Ù/> ¸AÄ~1 è[ì—Œ!ûÅG;ûMV²7û=r*™ýžS2Ùï¦SÉèw’î„~*Z_è7XšºÐ¯O>rF?å5–àw°°N ~+¯•àw¿Jð;X±¿#Åï`Rü–B/ö[ZTþ´hûÅE#é‘ýæõUüæc®û…Šðe?Õ)ö‹ê6Åo*M¯¿÷îàI~ÛÍ”äûü°_h¨K~ûÍ”ä×¥±Xòëü`–ä§~Í%ùxTÍ~ñ[AGû-] ³ŸÊ›ý&ÃŒ‹ýžK;Jö»‰RF¿ow“_(Òp” þV¼å±áoEï ðáo ]_Á߬uaø[jÝbø‹ßàÜ¿¼âX þ–²ÁMÙÇ Fú‹k<ýE{.ü*¢¿uЫiúó ×ô§>F¦¿Éˆ ã_öP¢À‡j¶C•‘#”k^`æ¡@à#†|}0ç›" ¾ªñø.¶3Æzˆ—Q]¸:£L€Q>Óãrµ]òËç¹m’_\¿_;ýeûÛ_ÿQzßq ¥÷)ìÇô½™N"éoMú÷M)˜ÃBú‹öR \Ñ_ü ýƒ* ùoEq<â0^‚p,ã>Æ.ŒX Rp5úØ €qõ Ì‘ÿ²)¸Œü—õ¢1 ¿x}Þ©ø…šü`*~q½ðTAñÓ»º¿“auVüŽóIÅ/,” É ×Eða Çþ=+‚¿u³ØIÁß…êe†¿ø˜†ð™^€6²_\'\o±_ÔÇõû-Õ@*¹¯7'侈@ ›Rî‹0†{ƒ¿¼0í#÷EHÂñ‘ûb¼ïkIøü­ÉêR«¬d¾µ‡\3¬ñ‡Ì7 gà»ß¾¼§ªƒ|*"YÀùÔõH|w—~(â»Yö©ˆï–çÙÄ¢ ä6_X~íÀ§â|7kšðݨeà»/Å’ ønv¾²ÐwKï´Ðw_ŠM­OÁžëƒâRVt'KÂoÑü@ož·<µ*¶Ð§ _¥ô=çÞK1œæO~š¶ÏGªC<%Tˆ'ó ?!ž¸˜âéPQÅxêÚUŒç#2RŒ'‰»B<^Š ñ<¨Lí!ž„D‡xöß…xvíÉ!ž|™•ÖïOìË!ž‡`S¼â= #æ½£ ?Å{ÖAÌ{‡–üÅ{·7òÞI/ÎÆ{,eà;©>¾VŠøNº] |Jd/à;»àÓÀÇŠ;|§Öá|\ñ M|í'â‹P' šˆ¯9´RÄýD)í‘øÚá°O"_,¿03‘¯q™Sȧ•‘Oíæ ù3zÉ|tÅ|¥‹ùÔ³°˜¯QÉ5ò5V^+äë òõKH%ä;/Qù¢M,b¾Î|Àb¾ÎRÇÅ|©œÅ|ìb¾Ë‘ b¾þPMóu§(æ»-æ»ËSÐÇþÅÅ|MAýf¾÷tqRf¾X6ƒ±Ä|ÍJîkVå¤÷59¬÷õSÒ¢ô¾Æ˜ÄÒûºB(¬÷Éd¹¯³êi!_?¤î ùJ=#óuf$óõ.¡ŽÌׇQÈ×Yê¯KÔ0ò©SE!_„cc^É}‘Ëy$÷õKl¹5L6µÕJî‹wç'È3~ˆ%÷=¢(Ë}·èm“ûŽrß­­JÈ×µîòu*¾…|]a@¾Î;¢˜¯+ÐÉrßÁJq¥ø©úS)~]Ž{+~m »¤ø±Sq ~M«p ~'û–àwÞÒå$øÅ§{òÄK• ©R‰¬ø5º‚JñkMÄI拼B`¡˜/ªï}¿&IÅ’_“ jɯI´´ê§ºa¥ú™±$úµ©ðL‰~©%úE_ñÅEÿ¡ùu6a*ͯwîI’Ÿ^™%ù5F|•ä§.3%ù5úì-ùuC¡ Ï$)Éï|H–ü”(Q’_g»å’üâúµ1_:¦¿Š_w¬¨¿~ 8%ù…j â”æWóHô³ÈnÑï}² ð[ôSÄ}‰~MýT °D?µ)+ÑïB3¶Òü.¤YòSѰ’ü®Æß’_„Ï}%¿X•ѯj$•6%ù]t«Yñ»ÞVün6<6ô¥ÄdÚ?Ju„¾¹y)ÉoRS(ê;Xž¦°ï`Ö&ù±oDI~~¯•ä7?’_VgÀ,–üï#J~1~¿’üïØ’ü¤šúT·¥¨/ÊÑÅV£>Yàü)ù)}§°sÕf YßB=µ¨¨PO6íÙb=•¦dŒ))‡$4 \ùÆ¿¡üŽÊðk<¼Êðë\­T†ï¹-ÃOù0@*Þ¿ƒÞg VP;>|: €¥OŠߎYÅ€÷7D£î §Â+7ì_ŒX €š“ün:ÉÞªBÀ›I…€÷ø™åç|K~)iVüºÒŸJñcF¿R’,÷½·3®®ð/RŸ¾¡žKroñßɹùoʵoþ ±ªœøo6Gvž.#"$ÿ½¿äýÑû…I„Šõ|>ù}®ôRð" v$ø[t€üÝL/ø»ËüJIñ­¿¦Ì<ÁZÇâ aø;´˜5ý½(õ\Ï7Á/®ùóQû"q|Ô¾ ¡/ü%©ÿˆôÆA~¥Ô4Ç𷊦ïá|ÙÏOKÉ}LÕú],1Rè§r1…~\Ôú)A€è§j±…~`~ÇýSî;˜'Qìw¿6ðsë-ÐS~§÷ ëvJïŽ Uz_ÓsPj_WR È/úK;E~j \ä7øi.ò»˜ù(ðk—ØPà×䥸Å2˜ê?QêêZäw6©t"¿“uV·@OÂÚ=¯ß>àù~t‹}Ó'±ïb»†û´ö.𛃋ûÂEKeàg¿Áo\ ¤4øqgîs÷i¥è8O- ~çø©õ¬QWàw*ÝÆàw*¬¯´>-[¬õ=ÄíÒú«†•Öçd.k}B‹üBS@`¤ÈOòŠüÔʧÈïR£Éïz”ŠGòkÌ+ð{È¿Æœî¿ÆB•¿xÿŸä@EÐ )“?Gþ9½Oi×~*OVj_m"¶Rjßá ;©}‡ÖÇ&¿ÁòdE~ªJXä§Ê»[¬§4N“ß%’6ù]llUä_uì}ú›Ú¾ä×MLò;ùî.µïý½>j_¦1>_µ/"a‘Ú7èp+µ/–Ä@4¡ß`ôÃï¹”«'ö›ºÛÌ~úûÝZêþFT þT`þÇGî‹wÙù‰÷ Nµ þTï[ð—é£{†_>1ÏþB;†êbÅo(ˆÑô·”fú[KyŽ÷t¢èo°wÑßÅÎEƒŽ¸¢¿!”é¯)fÑôw0^¤è¯!ïªàÏÙ¬†¿S¡®¢¿HM¦pü ¿ƒðoñ%ú[—6ýýLñKYöÚ¿DHʄ¿XÓ}4¿dF†€Ê«Êz…ÝF ÿºâ„§Ôñ©ªæñŸþoħ–…­ýÀ¿Pbñ¦ÿ5±²ùï‘P!Ÿ“á-ų6ü©ì^Å{^к*ܳ1Ãg+Fö®×·Îe7[þÖ½¨ØŸoW£4æ_+Föû=”¥ uýÜÇß,U¨k¤_æ3—-Û\´msÙRsÝQÌùüœ¹-5—l5WY¶¹UÖö\¶lsѶÍeË¿»ÙŠˆkü‡ÅÈÎ?/ö³ÙTû·#û£Ûb^`·ªõó&ŽÛó`Ç¥¹XmL¹Ü˜fá¿k ÿ»·w¡1O±Uó,剶QžË•Æ<×VjÌsy”çÚFÕ# Rcšk¯5V¬Fi®¥"Ùȼïõ'ÉÚ?«HÖþIE²ßÝR‘L·Ðïvö­HöÇ÷Ôï+’ý•×â½|~ÿüÇ?y‘í£þèŽýý\»"وț÷ãõ‡ÉÞ«ñ_ëÿ‹ËýgeÉÞÁÿóÿ ü[smUĶþw(ÛŒÿíOo^«l¼Œ§O,èëÅÁfåkðù\\U¼–\©¦%WrãŠÕŽaÄÚ¸.˜–|ßUQ&"icZ¦+#Ç;?ŽW¿‘àä~¥%›óŒ/‘¿½`™¬ÇÉ•ïx—¿Ñ‘¹0eS3<çÂÄ‘&û+s¨±ë¨µòfò«“ë¸w×Ãv™cœüÊ©qàk™î€‹“¡ì6º±UÏFèO‡­®ŒãJGebék™ŒÎ!„Ž1RÏd|ØÆ¸;ºIDŠæy¸g•ûñZ2¤ ±*Ø*ÿ‚åÄyEãæÕ7ªQ ßø‚%ÝT¾¿ã>«]3}Ü­á=é|}îp’ï­úÃ$߆•ܸ¯Œ2,·Ù»n(¡»˜¾7îðK¥ƒ ]¯!I8=F,‘Æ’C&VsãFîtF¡œ0,.O7î•úz¡d$Û{ñ.,O£aS“À¨Œ8“Šr‘›Ðð®Ôzh­7žð¨ýªLÜË„“H5`X¿1W%=L#»b¤…Ib#c°p‚Kž!Jdxî³Ø¬lðÇŽŸc2Ã`â ÞËØ™³‘g“’¾öÁ~PðLåF9˜ñ&ø-)Þæ‡~Bfiú†Î8#¼ÜÃMR+Áéפ†Þ’um«î‘‘ÚÀÏNÃdŠ/Ó#ù’4˜1& Ÿ'±àaÎl0ù.i™ÌðEµ‰Š“IÀé.p}ó·Ì+Áªáù[>´L€äAÈÈ ^ ·DÆb¼ÔÕ’ûDܾÿxÁ^\Ñ(Aõ0˜ ï¨a=Ùå7ÁBöœOG(€YÖ ‹¶ãhÞ'·c7ù€Ý:~•ÆþZÖëfë˜s§^>wÄ`NyÒî´\)ó¥ó7¹ñŽ‚IÙ÷¨ùç Îa„û¸0²u¼ðïãÁç<~Û†‡É<ì÷5sá1mS'„ lð) ‹É€é;:uÞz¹t¼³3Ƥ¡5:}.0øx,¸TÙ(]GŒ¼£3Ð CRøyÇb:KlßÙˆ vÃ4>©é?ÆVßÔmž¹¨÷7¼5îl „1ñgtʧ´³ Èݵﲃw4:éCË«=&ð?uëW©(¹ãì ´à§Šs¼³!PÞ3º2ÑhœûifC ŽÁc .>Ê zw6z~•¬sGC Îo%Þ=Ùˆe"ð‰Ž@¹j)‰ÞÙˆ¡;¸‡£#P>ªÉw¶bˆ\è¾}PÞaÙˆñŽÈŽ@zña£qJJ91ïÐ÷”®Ù;Z±?Ná~ø=Uzè1dòsÚ™_tGIú“Ñ=x²!Çà,ŸótÝM ¿§!ßÁÒø=eÓý€8_¬è4çtÃÂÏ©º_ÜwÏ4InuósÚgØ·¢ì0Ï3ñ¬vª×wv˜âƒìK‚¹sý¨ » ?¨ýãîô+#/ ßÓ‹iöwÞd{¦äÍ0½Š…çáÁVx·ŸO«_H"ä°œðNüµJe_ô»~¢_ Kû…~LÂÝÐúqÑ\ä7¸À,òCäÒ~7×Y¿XDÂ"ð»(5ø],øhð“šVàwMq¸ïš:ßÅJ¢~—»¿qÈ"ðS—?Õæ-ðÃŽL}ñ#þÚ¡o°ÌiAŸŠˆôEî\‚Œ¡o Ú¬˜/Z‚ðÄ|ã§ŠùCžÍ|÷)ðóÝü6ùÞÇ—ùÔ+¾˜/²L€]b¾[?µ™ïf9žb¾›ßÐb¾û¾‰ùn#ô=|;ô=\ûú²aû¯ ú‡ásô9òÈÐŒõÅÛ¡}°/ Eê ¯úÜoÉЗ-Þˆù™r‡7S_N‚iI}Ùfý×}Yâûׯ|C‚[Ìç f¾@ñX#ô…" Rôe³vP¡ïQ¡C_À9ü*‚¾ØÔ÷(œÐÔ—°`!õ%¯ÿ*èK7¸Ð—}}pÄ€¾8w»7ôedæ!ôe]1lEè{ æôe·{2©/-©£ÿªH¦¾¸žX¸ˆúb?ç‡úeõ)ð©¨ï84¨ï`Î`_$›ÿÚ¹ï:qßÉ×gŸšÇø|1øIŽ-ò;Wß&¿²ˆüN6+ô;dô;Y›¦ÐïdHŠÑïdzm¡ßɨµB¿Sk"£ŸaÛèwm%ô;¾k…~§VF¿“|ÑßÉ´›¢¿ðÑ|ñïdåÈâ¿“-CÍéo#ívÒ`ˆðÏËi៖ÿ¢¿¸s°Fý5”,øS ’‚¿ÖqŸü©ÎmI†‹Z þÚ-Üü56Þ+ø;lü½7±Mðw°`wÁŸrT‹þÎ.‹ðï`¼É†,“]øw,…ø¯±~_ñßÁ¢Øâ?Mkþ;Y®¹ø-5wþë\^ÿ¬úYüÇD¶Â¿ˆ!ï‘›Gg<»ÐM¨d·"À“KŒBÀ“-‰ O¶ˆø `ÿ"à‰Tá"À“mY‹åæ46.2ŠO–º5žZê›ëTžŒ (4–›#ì[‰ÑoùC€Kû6ªÜÐT&l,K¼ #3 ýø^¼&@e›lxˆ E€ ]Ú¥ M€Šý¼ÒñYXX+lzA›\GF@5o/ô4Úma /௕£RØÖïP®¸BÀ“®#`Óí_xÐGVhÜ\äe¼æ õ|b‹å0ª¼Æ†€”2 UYªPå” ;µ­B@Uø•ËŠGF2ïxóî- |Ž_;>,»Z ªô61`Ý' Õʶ ðÑ‚ÓøÐÇUø0ñ¨(ði8QàÃ6Sàd¡Ó¢Àu /‰“‰ÆÀøDp^bà<iiÄÀü5¨öÑ_ÙØ–±00²i¾‘п6Ì@h›Hp- y"Á(b‡‰I‚©"üH‚¹Ð"ø O{Ćü`©–L‘ œ$Á=@M‡ü•$èE´HеŠw,œ‡4.`vç…åÒçÊ7ô½â‹Ü ˜Y˜ù–ÇÑØ›ø7ˆ;%þÑÙ¿©,»óQÿp¬þ)|¸ä?UŒ+ý/>„2é'3x¬ÿ)\²ô?%ZTÂâ&Þ¼%²‡Ì&ÊåP`ûƒ/Ž1û ΃¯ÿR¥{ZŒß C$ªÊK €,•xè·²ØYd¬Àή¾Võ¦Ü@ä—8¤=Z¼ø€—(-·Àƒc¬*?¿À“ÂF)€–T­žü”(Â(ð$‰Z)ýo"Þ½Hð}Õãs[à ‘³PPK¡à±uFAL"ìL.dfva`g.@a ’À ãS ÌúS* ìZc—xŠß¤ž\ïA2 .­Pµ ƒ0ƒ°ÑÕY’ÙPš Óv •(Xxé§.em7Pp^`ç*³@—(à%Fò9 ¨,Ýb@åÏvÖÙð‘”'°é¬ŠYÈlc@:¡‹éå-¼¨”üÇê›üÇ–l›þ'sqEM€—Xxñq*ðæÚϨì+ ½ßÅW“"(þëKx%þkèQ%ÿMÑ å?9’Jþ{øû–üÇ¢ÿIá²÷² ÂÎ{ƒõ˜‹÷‚Ÿ_;ò)·¹/Vã_ä»y± ùn )ä+‹ï~¨Šønމ/R¶AŽ"¾xQ}>oÖå(â i “øâ¤0‹„¿[kF ªÇ¶E|²^ÓñÉoá&üñžØ„?&×mÚßýSûãt øÄ]¾I‚!KñYúµñ^ÖWú»Om$à»}TÒ_†›ôפìYúûß3Xªº€/NèC|y}Ã=}gYú\i–ôí€)ôQú‹ÂÄâ+ÓÈ7XW³¤¿qK®”ö§KnéÏ;·ô7ndéO-WKú|§–ö§²¨ÿ‹¡”ø7˜/eñ/>¶0Hü¢‹ƒÊ@©¾È–ÿ†©Pò_dzB>óâÃ$ÿ Rýün•úçñú7Qê_LL=êßPÀ¤Õ¿1¤"JýÖ )ÿ ‰²–ÿ¿R–ÿ¿%ÿË€Gùo°¦déƒÙ©¥ÿ!MNúß`©‰ÒÿCRJÿt¨•þ§î„¥ÿ);µô¿1¤JÿCJžô?_ë¾Û­ÿù‰þWÓHÿS1êCB”õ?UÜ-ýo cJÿ‹›âC}9´FêÛÆúr 4BRŸÏÀÔ— d¼ÃÏë $øøyØŠàç›Ýà— -ËíÒ ŠüÂr}À:‘_ÉOσÁÏM×~›à—–_úåÓðkƒ??ô†¿|›`ŸßA†??І?¿l ~{þÒŒ#ü¥å93,RÿâEõ¿Ý2ù¸>Ò“)˜\^úßPhá/ 4XÙý¹¦Y ªCVÎ (þžÁM†¿´`Lë~\ož>®-À¿<+ÀÞ¥¯+«£ÿê—þÕ] üË;0ú(²æ&¯ˆÿòÄÞÉy“ÒÂ;}|0-`¹³¾¯Ò?®4ÔוÚ^ß¾®¿6üË_÷×FþR™þêfýåÅûµÑßfЗU—WðWSð–IÔ«OëüÀŸN†¿¼IÀ`ŸVfåþža¯óÓÊêBÆ?'î˜ÿÜÑü—c°oòŸªóÿbÈúhÙC§°ôeU,²0,x\€u óÎ'îéÓÊö^À­,že Ëó‰ÿÌ«ókã¿B5P_Ví\ü·YÈihwé˪Ö!|Ôqʪ“$ÀŒë¢tæ“ 0jmâ_üy}0¦Å®E€¹ ä@`†”åH€Ñò¢ÖÇOëlÒúH€1†}‘cfÈî"ÀÔÃ~mç¶þf ³-4‹+|`ðäZÃ08ر`0^"_ýïf ôƒ,*°Á ;¤o0xq‘ltÜb¥ÿѶѠò¸Šé1 >Šm3 –dI|¤·˜õK N¨ Z54 *`¯ä?¶1Þä¿!ÁM0¸œ¤gý¯+%4KwHO¥ÿé"S#Jÿ;Vþø9±rÿO©š%XÝc=ŒùÎ5æ­„”È6ï%¶KI…›AÓ ß§›HWø&^_ÐG € ÝûJÿk×]R·ä¿È‘ÖIþkJi´ü§Øž’ÿ:Cw,ÿuezYþSäŽå¿Î+cõO%ŠKýS,}©r–úÇr¹%þõ¥|@‰Ì*í/vý ͼ8›Ä¿ÎZ‚%þ… þª*E[öŸÒ Kû£sËþ»¤Jûë?A3g SüSRF‰áKü{¤V®ŠUA8®Å¿¨dò!Á°àñ¶øÇ(ŽÒþ:ûñ”ö×ÙF©´¿.šµø'_d‰ý’²'õ¯_ôYýëz€JýcޫĿκà%þ]'½žÿ4 Ä?e”øwÉ›nõïR|•Õ¿(dÃ\?¹+™·YêßÅ—w©Ê/õïRÔÕ¿‹{Jý»”údp°[p €×aJ¼ógPñø¥FÅX¤*'Ý `Tê{I¼ØrÖ à8œñGPyì%^7fÖ/6Û.°ÓÕT: j¾–ø~â°z³8ø€l: k»m:à©1Ò‡R›¬hîy€?d@@Ÿ4@e<”øú¤Ê?i pðÛ’:ê@V—. ÊJ¼eËIôÏdðµ<_p ¢%@VŽ* 0|?Ø—4@ù,KôZÓàDe p,!¨4@ù¬ª‘Ji€uy—ßtÜ—xk±gPêU€¯T@9¨KŒ3øFƧ”1Ÿü¨éûV ¶VïSYT³ßmI€Ñª³J¼…#–ßO6Só$Þ—hM`ô6‚Eà­Å²$À¥ K¼ÙÀÕàÍ´Òï[‰€O½I¼QŒ¿4ÀHDEࣤU‹€‘ó ½ç*ð–Å*à-§€U@+±Vo®IJ¼å8° ˆÊwæIÖ¨Þý­Þ†Pôõ³ x35Û"`‚DÀ[ª›EÀ›Ño%F' –DÀÛ’šDÀŠ~m ˜Å^AaÒïñÛ7PýõJŒ‹þÕc^ìI ~_k€7#K¼oY¤ÞŽj]}»0–oE X¼åK°¨ŽÍ%Þ÷Ï @?–o¦³•xsUU`\Ì# ðfÌíVÉìÇüЙQ±óþU{hØë‘ýéV5HCþµ2fO,v澃²T‰/Ùª’PYªÄ×ÌjÍŸƒµ¥æ’­æ*Ë6WTןó¦a› ¦m"þÝeÇž+Ëç[vìú¥Ä&­ãö€ßýïÙ¢º^•({­í/l† C·+ ýþ–yFkðVm¨7_\»XÌÆx¦Xjg‰1ÏDË>“i¦mŒfêg»QÜH3ɲÍTƒ8Ó>Æ3õ3ÝÇÛL´ì3yfÚÆx¦øïó9&Zö™£N«ÿ•Êká5þß½’ÿà­ý?|N¾Éÿð9ýÝL»êZº¿_ ûßYuí}Yýªkïð?ªºöšß©£úóy©þ·óŸ¾ÿ´êÚ3ÎE%¢ÎïËréÛJ*„¸×òPRaÉég\ƒ’ æ]5J*ØäÎàgˆ%',O¾pÕ—þ‰oÅÉØC¢À/´Öëiˆ$Üòü†½D©v8\s7÷ ¥éGŽåUÎqŸ ~ä‡~ä×’®úÌÒÈõä»ÃÕF&Œ½Ëµ ~äIØ~î«AM _×€…÷(ÛWêüÈá»ÆVh`ˆêd8ÂwÍŸùd¸ÒkYð#¯°úžÍÍ4eú½žI™6’•÷O&’ô\Q¾†…7ˆ÷áï9ßOîoÈÃy‚x:µ_ËÊÊû )Ì\Æ¥x˜4ÿÞ÷ÔyãÞçæÄƒ:Y ýµ,<¨“!)/ Þ,çÍbíó¼;žÔÉ'õ}¶N<©“Oók™xX'‹aÎsÞxXËš¿Ï_Çúè¡~Ÿ¶ë¤ ãµL<¬“rØû¬ÞxXÕã¥ÓއuQ}Ÿã8…Eñy6”»Ùwt|XáÃèl´ÍàÞýŽ&§ÁµÉ~G7ös`?OÔÏ>Rø¥Úì(¾¯´ëÙp¾Uü|f¿£=Òó»0;òöн>¯_¶ÝÅ–©qÂ:7VÖm›ë2a{Q@ÚNu´ˆ}Õe$ßNuu¤:>ÕMÕ Õ…o4‘P7/Àêæ'¨ËÚ˜‚Ârê²&€ PÁZm‡º0à(Átõ7;Öú˜@tS¹Š"º©ÄD]œ'®,‰n*ëUD—)$¸GÍœ/ Ýz§é¶Ó…7|šH7où£å'¤Ë l¤ ï5>"]„ÇüÅ WG3ÖEŸÒvíXg¬±.œ©aÝTyVc]tlε‚±.Ô,$»ðG/ªwÏoŒ“¼»ØæÚ¥º‰e³¨ŽG[T¾U¬àEuñscˆ¨.ÆPO#ÕÅlD¨‹›ëhQ]Þ5؈`—]_)Ýñëó<²ì½±v¡®–€v=[Ó’`×.Ž`דO"»‘ËXY‹ìb=½Ý;‚  vËt²ëG·–²ëçxDƒ »~Ès.²ëGd’ìd×ÉŚȮ÷mÖ˯O?ÔˆZd×£±0d—–…1 »Ñç.ÖõhbÜF »~^ã+ÖõhùË1 »~Ê]#²ëgÆý"Ù½¢À.ÿý¦4_ž~>¬* °{wsãvý”GQ`÷nŸ|]µ3w ²{-L&Ù嘹ËuyJШIv=WÜ`+]o'“ØDvï<—D>Ý;O÷Qd÷.,™ò)²ë±¾Æ1“ìzkôäŠìz,¨×®×¥…†ø½³"˜À.÷i`÷éð‚ ì^ËÍ Á®Gs䱃]̵Ëu=ºcD°ë±æ†ï’`×#fos‚Ýk‘CŽ`—[M̰{-¬—&°{·bè»À®G—å±ëuï4“Øõ\ÏcÀ®G9(¹®'l@x×åŽp)Àu=BÌ` \×#ªßrÝ{,Lä×õà‘ `×#2}Á°ËƒTìÞ«Þè%Øåõk;ØåÕìö#ؽûb§-Ýö[ì^ËÏŒÀ.ÌC°Ë3Å‚<À®Gäü"ç%ؽV…%Ù½—ü"Rìòx)èìö=ƒìò÷>w²{'f*½È®GHþØÉ®Gƒl\?’]ï{wï<¬],¸Ë1ø­wïÕb–¬à.çØá®÷ë”î2èŽóîz¤ w=€€»©»Z‘@t>îÞiXip—w×µ«uy§ß»Z—cˆN€»<+‚àn»swï îræ±Ãݾà.÷š"ÜõhŠNy_×øAH–`»Ü©l—Ý»`—7ò‡íò\Û½/.rÉvï¾¢Év¹'rØ.o¸{g»÷8¾ŠÝö& Üõ¸£ñèî^ ûwù“wï<§Pp÷nµ„{€»|GãÆ%ÜåÞÛ®ÙåV Â]Ï.÷À4À]¾È-ø¼¶H$KØî5 ˆ©Ðî—uIˆvï´¬3$´ë‘»ƒgh÷Žyø5 ÚõÈæ¡>‡ïk\­kWìò{¿ É.,ùgbÝûŠ’êòo’Ü  !R‚Ýûï8.ÁîÁ*Æ»÷Àõkìz¦%åßÉuù›\÷¾AôK€ëÒ€'\·ˆ»í\ÌX%ؽIýv¹âYüóÉ£>º¨,Á.?ÇpZì^ƒ”M€]4-RY’]î÷/Èî5èݲK½$»<,îeä:†%'Hv9%¾F »\é@bÚ唸rƒíÞ’Îw¹ð¡—p—œ<à®G2Ö €»wë½îz|ðúÜå ÷ÊW¡/à.÷gp—ö’î>†™w–Zì"£¹ 1Ž£ÀOºK®£’ÛÁÇæ?©VD×RÞ‹èÔ<®ˆî¢¯·ˆîjóDtÓ’‹èâý„0IÝÅ?sµ…xî’”$žS¤BºÍòÐÇ"†"Òe¹¹P—¸„+G_úh}Y[)ü²v¥ð˲(üò²ì§ÌÚ—"0kŒ"0=#0}<ŽÀô¯åÌÍB—¢gžªKˆ9€é›K˜¾•€éŸ×1˜¾qƒY[)³ …*³1b“ënÅWJ®{îß>!˜!úQ“Z'ª·X÷°Øv‰uŠ(±îQ°j‰uòy”Xð²RÇóM©cètÖ"­ÓéߥÓ]ŠÎ°NWètª›QB]S°%…ºKqê¢Ä5þ†Nw)t:Ý;Ÿ#ét{Œ[§»‚!¡®ôE*u$%ÕÙ ©n3, Œã#Õ]Š‘Tw1ÎCJÝÅÐn u,ŽWB ê"¥®FP©zZ©c[§ú>,ô-¥ÎajÎ:¼ù ýRf€93&{À\L©L-C*S±K€¹ú¥.–s胩Ŋc0¹*²;–ÒìHvzóÙ½Dû™ìXd×~¤ÕMUM-²Ó…/²S­î"»Û*›ÈnŠpK­ãXd7Y‹±Èn.T ìØÙ¨¸n)¿L\÷(X·:4Jª;)•êVë?rê6 ¨.Ò"žÕ-•3ÕŽ¿+u™w@ín(øŸÑÒ†ºx  êb ÁP·œ‡)¨[—6A]T~7 êÖžfºu£ §‘.FÀc ¤‹˜òùAºš7‘.Ðá bºõ0¬JL·œ(¦sh»™.¢¯!h‰é’X`¡Pw–å(ÔNQ”PwœÒ'%Ô~$Ôt/Z§;„ÿ[¦;ëèZ¦‹RUŸ´º~t¦/X¦;ÛÑX¦;-c™îè‡B)Ó I¦;Ô´Ä2ÝqÝÚ2ÝQ©‚”éºà%–Lw\rŸI¦;®aŒƒLw\òeI¦ ™Y ’éŽA¥Û2Ý1—&™.ªmL8×w°ëoÌû£Lw<úêK¦;Þg $.Dêc'»ÜêØÒêÞ‰åz—PÓ<»PwüL«{7H¨‹=Bî£N…¾öøË~L¹,%ÓŠ/°Lw**Á2Ýßv)ªß™î´%™.Æ|Tºòìá—¯EëB©ta_*]";Íuw­Ò%¦A¥‹! •JwžÒW¥ÒEé2NC•.Ê›!ÕH*ÝÙt¥ÒÅ¥‡\*ÝÙ†³ìX.£³¹”Uºø)yQ¥; fY¥ Ë éA¥«™¥ÒR¼UºÓÙgRéNgŽI¥‹1ˆþ‘Jwvvõ”Jw^"©tgI{Pé"raì\÷n¤ÇL*ÝyQHwªO‰Eºó’Ô"‘îÖÉ(ÒÑ[ã#Ò…åþˆtQ!?„Dºsüé"´â`žDº(4÷ìYuZçN"]L3÷¬ºÜ"]M#‘..@”"Ýɯ”5ºÓiOÒèÎHc‚…]DQ@l£D{ƬTèÎ…¨-зE< t§‚ƒ,Ð…8²>]Lƒ»OÝɨõ¹Ó)TÒçâ9'i 9(GÅ¿·yҲͿÿÝ•ÉÖÊÓ?,LöO‹ea²ë¯&;ÎÿÕÂd¿»Y^Ü:·o¸lßÛ.猪ޢm”frÉ1Í´•óLä™¶Qœ©JŽq¦½ä˜fªAši¥™\rL3m%Ç<“y¦m”frÉ1Í´•óLä™¶QšÉ%Ç4ÓVrÌ3ygÚFi&—ÓL[É1ÏäAžé_(L¶¼X—ìþ§uÉÞÛï·ÿ3Òa^Š«š_÷?­KvÿÓºdcÆöÏgl}ÆßÕ%»ÿI]²¿ðÿÇÏwñ½®ÿñGé7øŸ<¦¿›éo×% OÉûüaY²÷‚ý×úßÿâ"`ÿYY²wðÿô…®Úaÿž²d÷•%ûÿëeÉÖ=ÒKü pûþªdzúk@&:mÝ;QÕxW é'Ž•á…‹è)} é'v#­õlGÂÔËõœÝ_r“§ú^vŒhö÷ü;<1¿ª‚ÙzÂÿ+S¶F ùËìYÙ^æW&Z§gx=Y 6³³fx:ÚCð|¬ØsªWäã²Ç9rqž½ësé¹ByÍ”e濬,ï_Uïì5Ì-ºa¥|…X†\ƒ¿k«¾)¬l¿«…•¥»·T敹;0t·¨€“&páˆú­ß°‡( 'ú‚a¡rÀû3&Ü¿k¤ãñÛDýÇwùŠ’8ŒÀ€†…“ª4¬('37Y­hhí=—1+¼¨Ï–¼²Ô äo\—¨$ÂÌÛ›Ä/ CRÕŠ²76Y8ŽI}zòÏ•¾võ¢_ï¿QgŽ¿ÏãˆØ¸_•;ûZÎó7ÊÕ2@%=à º‹@àµt¨¤Óõ_ËéE¹§aYj¿‘Ÿõ×2 ¿H~-¨¶vá§~ÿ~ ¿H± ËÌØÆÌ[é–7-‘µ² ÈïŠõ8Õ ëíãÌÓKY"Ýw±ª½¥ô^Š.dÒçv`X–™ç —ík¹¨e^¸g”%ƒ´zÒrS%åÛ",B#õ™×¾ð_UÞíµD,?$Ðó D6u0,nÀ«ÓÒÝÜÜãöµœÜ¯yDÞŽïˆ67Mòý»3¥‘ï™×r1§‘)Œ¯e0©‘aùf5¾–›i”7^ËüÆÚ÷tbc»haf#œ¯a18®áâõƒš)£)² ãuý”±TÛn•mUœ!ù:„Si}aYJ`¼qtýz”-xsÌ`ß„¥sê7³»Î»ßKc:®_GU¹GOKô#ÊZÛ¾÷¢sŽYP£y)ö}ÐPUÁQÕòôµ4&<.ývÑ(3ogô#º¿3_Ro?SÑh`L£!ˉO^=ö"Úg} ¦>‡¶@/"WÁ óYÐáµ,<ÌÏ¥G3"f.\ˆhF”ÉŠ¾…£Ñýµ´üVƾ:çÉÉYõŽËH‰Qîúø;?—a99b þH¥ó^ËÝq|~À¢QŠ…¯¹7 åi£™ŸÌ¾:œ¸ZIs<èEtÃÒ/Z¨Ar›hF4~UI¾×Âx…9tù¢Ñ ŸžèF´0ïµèFÔaÁM͈&Ä̆sŠfDy ·®ÞÍ Þuë݈2Y²!ûµPû]·^}w/Ì[×ê¦ô»n½††/,VV{-pADžæä0ԼѨWææk`Ãztµ¢Qæiv½-ÕhqÙñZF~N·iîKCx÷½ëžÐôºÏàÊ_UéïµÌü¢F¿ ×3«|Î ?Ø¿²Š_$“Úïyè³;YIê` ü×BñW òka1©÷ñúÅ»?Ná¼ørœ¬'µMœBêÁ ïß,(u,Ý#Ù³“ðŽe7¢Ð,5fvœ‚ÃÉ¢Rg×W6®Êó«JžGÖ6„ZÍß%†ßÁ¹ ˆLýúЭµ²Õ~<+ÕߦG,Dê :9ïØEõ÷dŒbX&Ôuß}Qxm~¦y:ŽŽÂÁk™ª«_¿É0qpC/樻•“WóÌNDQÈ»……J¦`–|c·xnÏÔwc/zàÎLèÅ‘<Üê:äNs¡ö[c­Ô3ÞOp°6Û¯ÿã1ê¿u=¦qÿƒðã3î_Y“oå¸þð÷h‰'‡×YDîŒYp h<öÎüœÆ¬WB¡KÏÉ6DñëáÓ]n¤†µÿ_-D¶3ÜÑ> Çða1—nf8<˜áTƒÐ }Š®_Ã]¬Hd†»øäñ¶r1Kk˜áëöâºÍ˜á váŸp3\ÈpƒÚ©ntb"n0¿Þ7„"B8•33©“«ŽåÍHpƒ9ü&¸Á87œšýšàTëÌ7œaˆ+!N• qìo†SEoCœº·âWBˆcA33œñY w3ìÍg€Äݘާ´jÜÍlœë¡‰àò7à ¸ p’%ÎUÈApEè$¸ ôk'8%7Á¹3¦ îQH#Ü> ÷.p®·f€³kÀ·O€ ôçZüPmµ‹óà\ Ýwí ç–¦8û páSà § ó[¸øi&¿mC€oÙ”óß\Lø¶ÿ |‹§ê šß"ŠëDâ[XÑøæÄ ã[v=å<À·°pùF|sÞ„ñ-Ò$¸,lgÿ޾)‘‚ô«’ö¡7×^3½¹øšé-[±Ã@oN¾0½ÙGbz‹÷Ë!V;p‚9æŽLCav0ËhvS14£[Ä=@·pÆð"º……·ÙÍõÛÌnÛ±‘ÝœDav{TÓìæ” ³[¬éD…¨7Ìrd·ãТŒìc®AËÂ9\Z$’ݶ1d·°p±IvË:nÕ–Î{'»¹]±Ûaþ »Å<'ç¬I7¸'Ò[ä€ÒBzÛ,ķÄ/|;Þz¢7EʽŒÙ)z;¼.½L:,z;ø".z;´¬"½v.ˆÞ¶¤7û­oªdWðvü„·r‡ ÞŽKË}dM1‚·ÓÈxSÆGÁÛé7£à-TòámCx;X;³àí<ån½òcÞN¶/+x;=¹‚·“!¢o'šZ‹ÝN»(Äne»CïA²Û朻?ÙÍEß ÞÊñFx ·^Á›1Þ\®èM9¤·Ø†Ô%zk>À›³F oN 1¼¹žáÍ™%†·˜X¼Ä|Ì6t¹oÛáÞ6ß!é͵äHo® gzsE:Ó[vø…á±C”¯wÂ[dµ Y>ê=¦Å“Ztˆ^zà o®gxsÙ:Û»ÂÞb )«ßŸð¶oÂtLÌ3¼Å~Åo®îfzsˆém*XÖøæbsÆ·ìLBB@®®œ¸:œèšßbÈä‹©#~ᛓEŒoN£0¾9µÕøæŒã[¹xÁonÅa~sZ·ùÍõýÌoÛ\9“pNÀ0À9/ljX×–—þWªŽ‰á­QgO.Öý€ "œ»Táì°ÂÍ W±.nÿò9è^d,­Ξ.\ÀöJ‚‹~Ç.ÃÅ&„> \ÈxÙ~óÝàáŸø2Mz¬…pj> ²áÂù×v† ÃŽpö ábN`#.¼zÄ£“Eº Àp1ÃÚ.®€9ÎM8Äpr áêï1tÌç.ÃE8¹\m‚³KSgO©.¦8J†ó$¸íŸApq ‚«c Ám@\!.œ³Ø U8_©p> Šp“iHá&Wá˜=b ®’Üôê@"Ü<¥°QƒÓ6%©‘J©púÅK…Sk•RáÊ«,n›™*Ü6æþ E¸i⤧+PœnàÒàÔž¥48O# ®œà’à¦*’àæaû®$¸ùè[ n›—Ü|ŠØðÉÑCZ\”$¸mO”àæ©A\]ÃùgÂÕm%„Û,D¸:!\=ÛB¸i)_·Íó|?B¸ú™ÄpuW‰ájßb¸ÝÂï©/Ž®ö-†«™ÅpuqÄpõS‰á¶}ïÃÕY‰á¶£!ÄÕO%ˆÛŽoù)ÔB\ ®ÎAWÇ'ˆ«#Ä•t Š«#Åm³ RE_¤¸ú­DqÛV¤¸ÍBŠÛöEŠ«;Gç1¤8_ cÜ6‚ç£1Æm[‘ã|4æ¸m An‹rÛ˜ÛU邹Ýòè…3ˆió³0ÈmGC«= ä|çäü;äüäjfÜd¶ÿ¤À˜á Õó7zët*’Þ˜¦7• 3½©*“éM¥§Œoªin|SãÛ¥µµðí ßÊ@|S´ñíÒ‚ø¦šäÆ·!Fø¦²UÆ7U>7¾Õa‘ßjùíZ¯Èo,U`|óQßêOâÛÅû›øv …oÞ£øµÌo>Fñ[Èo¾t¸ËHI€«ƒ À],~C€Ó>pÞ…îú p>l\p¾r8ß%"¸Ë€F‚óaனhNœÌöùký8jÜUäE€»ü&Á]EU$¸ÍB‚ÓÕ*‚Û,$¸«xw}‘à6ËÍ£¹¿wù+ †ÛöD†ÓU)†«1b¸šGW[ â¶­qu<‚¸m !®® n›—·í›BÜ»âwABÜã¨S qÔâ‡2IˆSÀr q5FB3I‡{L$îµP/…§Šm%Ä•@)!®ÔF qC%Ä=à“WФ…8ûÂ-Ä¿}¢(óÍô‘âä —÷~®¹­TIq›…RÜt¢¤¸ÒB-ÅÙã/)ŽãJ‰+…8µ*!Î:'t¸9œà·Í@nÚ—.nÞ?U¸ùX=£ §®S¥Â©1U©pÓ¡ZRá¦ã‚ p»…*Ü\Ò¡ÂMûö p›ç²2F¸MR%Âíc˜·X™Ç7Åõ¸5lÓФ«iZ\$J_Á-Õ°1ÁŬ\+’à–:øšàVä}T¸5o%°àâ[y~D¸Uë|\aãýA‚‹ï)ï‡$8·Âe¡:R.Žeq.ª•0¹;:w‚ëQÜ­í÷ZJOK‚ë‡:+áÖ:™g•sÃ}¶ÊBpç©U*(îµL¼Ñ„qý8 Œ{g¹QN÷ŽéÎ#;Q¯MUò„q=Ÿ_*_ ÛÞŸ÷ŽQÒ1.«ø)5.1.·¶õ9b`\Ž`”0.Û¶Mju‰qYûïVxe– 9*" ÷Žéâ|`\6›’ÝNœÃirJŒëG«|¹Ä¸l>Ç« ŽË«#±.ËøÕÑ€ã²Ü±s\ÕÇeÀkÏ…ëYÎà™×cÝÕv-.+j_¨òtôîT·ä¸,4È™ƒãz¬çD[ÉqŸ(õ•Û®Åõcœzã>–ä¸×r(X—ca™—% w1îri¥ ŒëQ‘P)t‰q9fT2\*†J—KŒ{-] —u—RßNÁ/`Ü;æ²Ú•WM÷„q¯Å70®ÇäØáQ¼ÄŽËyæž÷ZÆo…qYàP’^b\ Ÿ2`\NÇå®…N r¯¥9¯M g±¡ÔñøÖšlZøz]ƒã²ýà¥Ë•gðøöÇõøLò— ŽË6‚kφˊ‘Òï’ã²jãØµ¸žŸVî;9®êLŠãúÁÎn¸~‡|#à¸w£G‘‘‰qY ’/c`Ükqþ&0.7…q9B i‰qý¨J\þPm'¹÷` ’Ë}3Å0÷Îã»0—õ!¯æ²’#×€¹¬Ey‘Ÿ²çbñ-Á\ÕÌmGCšëQTó suTn;X¼P4—çyîqïV¬:(šÛŽ˜4—c8äA‡¥“iÉ„¹~6¦õæòXæž—…''7i®G!¬Aý,i®Ÿ*Ý+š{E¯o6:XN8—¼¬]é`]‚­ŽØy†sóS¦7º·½$¤e/ öçÛÕ(ùK‰µ–YkžŸo%»Ò²Çáß[Ù¯åçgYöy`Ûg’e›+k4~*öزÍEÛ6—-ÿîRbgÔ<ÿÕRbóg)±?¸]Îpœ¿>ÅÄ~ÜzySÝÇçfüG͵ ã\{91ÍU£4×§èæÚK…a®OA1εâ\ß²cœk+ƹö’bš«Fi®Oá1ε• ã\{Q1ÍU£4×§ôçÚ †q®½¬˜æªQšëS|Œsm%Ã8×^XLsÕ(Íõ/;£ÐiÔ§ÿÿ+‹ý¥Êbå•þß½œÿèþ?|n¾Ôÿä¹ýÝ\»ºØÉ„ÿ///¶½fÿÛÿø5ÅÞ+Íäã‹}¶w¦ô¾s2y4:±g¶ÚJ„9Ãÿ˜–›É(Ù¾ïW&R3º'2A2G™9wgÔd²/K<½–Ñ”§ÌLTÉDe‡Eæû2j2Y‰Æ¯eBƒ}TìæœJF¶‹}. çX‚ŸKÉÈÒÅÏuR†•Z}.&#;7öŒºó×–~z.æ#;Ïõ\eX¥±žéŒ‚÷šK®5(Ãr’îí¥"0çz˜ yiU¹–ñ¢¯?¼4¤>Vÿjí`.²µ¿Í枨Ù&#«ÁkiÌ„ÔïÔAØ?òZ˜ yñZµãºw9«-RXОÉn!êµÀÝý®p;-3!¹ÑìJ#ìÜõ:¨ìðnm±„§¸ƒ•}‹;›7zZTpg*䢥1Ri‚¯…Ùsàvv¦BʃÚN†²;{®E!qzìnÅPö&/k‹OÍ'Í­ eW¥×2áþn*¡ÒN†²;׬EùèŒd“߃ٛtøÖBB‰¿á¾iÑvOrkYÐø×–+×ZoÊÃýÚ¢x0ߥ¹œgÀî,±Ön8»4íÖ˾YžG­¸s³wß´-{K9¬5ƲwIã-z]/Œá¯ÐË~Qü}O‰AMe`KÅT¶l$ O»_Œiº¼§qª&™¶ŒiR pë7cšð#õçÂ?óIé“MªWðZ¦¢ò ¹½—ûVuˆuM²”“5Éüt«‘Ðͦj¯eA…½ý–P'! hïÿŸm¢‘-üy£‘ÐÚ²×Ò Ãn³tè°·B˜Z4JmNŸ„Økˆo±h$Ô03ß57ã î[·mtÚ{…‘·b‰Ú=lƒÏp»qûõ§*«ñWƒXu>2:GÍvþ¼ê«’m-z =0ð=½„ôDîüA½Ú¨¬ÿB.WNL¼8†¢ñ£2 ±¬Àˆ“¬ÌM.|†!ü]êÆ.ü–_Ó‰iqñ&ã I"H¸ÇF¼4“q|ÁNFÿ>ª—ÐÐöQö/²o±œzÃ>*ŽÄõ¹“aÒLOeæ¦òžTU¤Büõ¯­v\›Ô qY¯ŒUéx3®Óy)¼eÖÉy¹²XÍ…áàÀÊzJë³§¥lN¿–—ÂØ},—ÔdN¢v‰>mILV½¹¶~ư§¾v~Ç(Š]©Æý@V§¶I¥éSš/õ–…}ã%Ü;ê>Æácu—ºCƹs€2;å’Kïû®†Ÿé±¿q¸Xäd7!ênõ\¼5f2;gñÏ¥c»9­R$wi >§‹ÍOMÃaI¥á¯V Ûˆ/ןâS™?Ÿˆ ¼w(dɼ§ Ì> ú¾I|*ÇUÄ7´˜3ñ)*¨ˆO’‹ø†Þ5&¾÷º‘çD|·“T@|·j&¾[µøL|ñA%©‘øn×Tñ±&pï¦ÄfÚ»d#ÚS1ë¢=øîi%ðݺ­ |ªžeÞ»•ìhàs™+ߣçÉÀ÷(˜ÎÀ÷4}L |ZDŠ8T~Ê I_Œ!cÿæÛ“ÀWí¾Šhð…å¡Àç¦ã&¾*²%âÛ·Z¬õ=ôi'ñÎs]NâsM-_ á‡ûlŒWçÅ"ðňç|1†—ÀÓ -÷^»ð•oAÀWñó¾˜ùæñ1ðý)Ü\¬þÃk |÷º2i/äÒž[­÷*”_¸·ÏÜ«ˆ{á^XnÀ=w[7î…¥p/,\ö÷*Ü_¼WÁûà½ì<ÄãSìûÅw·x/ÆÐ•Ðû.MXÀN‘šbßY}ÝÄ[q-GâÛçñ9x_ÀWy¾Â…y2Ÿãù…|ûùb?\bù¶1D¾mZ"_Xølù*æ_È·Ïä‹1dž|UgMÈWLâ«2k"¾ÝÂÈ÷ŠàÁ– {U¤N°Sðƒ@ØÛvLØÛ~é¤ÛÀ^¹>E{•&"ÚÛŽ†´·ï]µ/Z]…n÷'EE´Wé'½}OËi,‡ðG‹xo·0R¸öEÞÛŽf*VØpœÈ·`ÉU'Èù*FÌWÉ0b>õ0òm^ݶaåÕe'ñ……]ßv|$>7› ñÅß|a‘øömzÓˆ$YƒµÎ‰Ä·ï›UX]lQзaÖm  /œè|ú¶+Jè«y}êmæ«D!1Ÿ³„|ûjª¡b‡B>×ôm³°&«Z_›ùb›óÃ|URÌ·M3Ûg7“k Öe]tWˆø6˲ªå¶¯2¡|ÛF\{ÏĽú=„{a!=÷¶£KÜÛ·a]VŸi¯’©D{U/S´WÇBØs“Ó^¨íŬE{uŽ {ÛáöêàÈzÛu"ìUƘƒœ&ØÛŽÒ§®ËߨVfÞ‹¨ý÷"n¼n÷îUi;_”Ÿ›…¯<þ"¾rÕ‹øÊ¿/â+g½ˆoˆ{S- {NÇ7îÅìÏ÷bÌGßÛ‡¬§öBÔËã#LõªÊIo«WGÒÛ7¢ c³€ö¶ý’ö¼g ^  –JÔÛ-Ï©ƒ—×õþH{Û•&êm’QoNˆzµ#¡Þ¾µ½m µ½Òh¤ím[]ŸB„Öö¶}«QÌWØÛvCao›”ÊÞ¶c*{ÛŽ¨ìÕŽ¤ì}!o@Y¯¦…¬· ¬·Y(ë•–%YÏ7¥e½m+Êzº)­ê•¢Þv,õ¶=QÔ«=IÔÛ”µõ6¢Þf‘ª§][Ô+]M¢^M+QïþAyÛ4¥éÉ`IO‡+IÏúܦéiÌúNR’Å’ž†HÑ+½šT’Þ& RÒëò7YÒÛÆPÒ«‰©è•‚ž_QÔô¶Y©éí–©ã—…šžß¨ÖôÔ¦¾4½::izµoizÛ<Ôô¶1×ù—šÞf¡¦·mCM¯ŽXšÞ6†šÞ6†šÞf¡¦W[IÓ«1Òô"DŽ€DM¯ŽšÞ6‚šÞ6/5½m 5½ÍBQoÛŠ¢^]?‰zÛVõ¶­(êm[QÔÛ¶¢¨Wc êÕ‰z»eý8‰z›…¢Þf¡¨·íéògTŠzuõ¶1õvËúq•!êmSÔ«_S¢^‘¨·Y(êÕž$êmóPÕÛ¶êëçªzu-¤êm[©žO¹U½íh(ëmc(ëmc(ë•EºÞf¡®Wû–®·¡´·Yú÷œ$ím#¨íu-i­íÕKÛÛæ¡¶·Y¦ŸiÍCmoÛµ½²HÛ«ßAÚÞ6æü^i{›E¥†}ÄÒö¶1ª5ì#–¶·¡¼·Y(ïí–ççñQÞÛf^í{„”÷ö¿ýD$$ïyË{»e}ÏÁòÞ63¾ÍB…oÛŠ ßf¡Â·Y¨ðm–ùcJ|›…_Y$ñmJ|u|’øêZHâÛ¶Òú¸¶¢Ä·[ÖsÄ·Yîë»'J|ÛJ|Û˜yÿ<J|e‘ÄWG#osúûúCãÛ,ýÇj|›å?ŽO"ß¶§ûøy|j¦XÇ÷ŒÏ÷ë?)nV¬wžHŒ/ÖsÚŸa¯9D°ç¢õ†=w¦4ì59= {î(iØkÍ1Ÿ„½&'±y¯)²Ä¼ç¸6óž í›÷¶y|mˆ`§Uô&‘¯Ud&‘¯U&™ÏeìÍ|µ#1ŸÛmšùš\ìf¾mb_S¸Œ±o›‡Ø×. x‘­â¾m^rŸg1÷ys_“d!ìóÄÆ¾mõõF¤¾2\‹¨¯v%ð«i~[e›ßm~uxŽçôI9žSÍ*ž³,Šçôá)œ³æÏÃ9Ë¢pN[ÎéyÎé];œ³,$¿fÙHè·ÍBôkúmû&úm3“ýüXþ¶yÛ<„¿íxVû é¯ö$ú«pXáßf!ÿÕ<â¿m ùo³ÿ¶} 7·Ð<Àm+`'p›…ØJÐ#Ö­$¬YD€5Ðo-`Í#¬ãn–ëüp›…¸mCÜŽ†X¿¸pCÜΊXcD€u<"ÀÚJXÇÜþ&n³·YH€›…¸ÍCÜæ!ÖÕnó·³"n[­çÇ}Üþ>ÛÏ$À:à6†Ø~Ö¹[ÖwްÎü®>3më*]ú_‘þWû–þç#¶þWc¤ÿÕÑHÿ+‹ô¿Ú—ô?ÇøYÿó¾¨ÿù–°þçŸÁú_‘þç'ÌúŸØúŸ~<Ë5ä¿ÚHòŸïË~)Xþ;¿ðW¯=ËÞÆòßY8¸~¼H,ÿ•¥]?îtË5³ä¿ÚJòŸÓñ¤þÙ ñ¯²ïõùQ,þÕ‰u,ÿ¶,¿©3ø~uÞÿ¶ÎóÇnñ¯ÆôKüó£`ño³L­¶ž/úÕíhñ¯ÆL?КGâŸok‹žÇâ_hJüÛ?¹o®Zü«Y$þÕ‰5‹Ä?Å?ŸƒÅ¿šYâ_‘øWóHü«½¯ö½O$þ΄“øW–Ó©òÊÛ“ø§£)ñOû.ñ¯,ÿtÄ%þ) ¿Ä?ýV%þ•Eâ_í}¶ïž$þN”øwüÌïë h.ñ¯ÆHü«1ÿ|ÿ|4ÿ6ËÒïÀ\H‹e¹¯ï¾%þÕ‰¾Zÿêø$þ1ƹ´?°ÉOÅJûó4&?ÅmKûóÁXûóŽ$ýù ,ýyˆ”¿2Lÿ!ü¿¯¦Ö£ªï§ÎPóWS£åSMíO·Ûª©qÌ¿XMíj ôÞƒ-[õ2Ú¶¢@¶l•Ю¬à½Í„¿÷y²Ïòs÷?»ŸëX¶'ö*1̺ҒHŠ$ŒžvO°|£íÁÍ[¾0üþh®½ÖÚ¤""Ož, Û“ƒócH”¾Eò³×þÿ>Ú¥h¼ý‹Ýrô£¶£§lù/ϦV‘j©~Ó©ýÃ\gw‰¿ÿ8ßÚ:`MÎï™蟤Hûu ”YÆñŒøD¾ã OÄ%HÎDjì ©8Žâϳÿ{súÛLž¦ócï|Ÿ]¨åÓË>ÊG¹¯#±˜ú:‹¹¯}”ûú$)ó7ÀTð»/·œ}G©¯ó¨?=. ¢üú¥»~`²x€Yº¾9¼þ½ë_É#öÛNžç—ãÚo/öK±ßŒ©ß$û3Ôß~™k~7ýí÷#ö§9ê÷#ö×¾þõä`ì]ÿ(9Øÿø]r°ÿñŸM¶ÆýýS’·c¶ 5¨Ìú:Å"MŸÈ¾ñåM!3ó½ù§ôçË0 ¬”\E§Â~Qb@-ƒqHç¬ë(ì‹Z'ÑoT/…ýÂpÑØr3â°93v½÷Ûzžõ GÓ÷9ã”3ÑÃèG„77¡¸ß e]-ݱÁS×~›?/õÒG2q‡Q‘Ñ7b=œ$¾"c®òm1O½&y–¼Ø…Tä‰Uêìia]êãQKw2(ZÔêbÔ‘¼ˆQ}õ–UhýBÍj!ÆŽ%dZ÷Íp•º>,¦qèr½eBØ—[‚Gç"ÿªKÓ(„R ¯.>˜výQ2е2Ž‚ ¦Nš¬|°vÙŒªÏ…nפ¹¸>7 ¼®(´¦¶ÀQPýÂW  ŽG½f]_‡õS™¤ùrâ¬ú4f]/£«…Iš‘ш?s15Se»VQ]ã•9¤õ žq3…pËk&ièÚ“Y×g^©„]©tùç)×QÛ€na«%R®‡å’¬-$~ÀÝ«ª–)×ñrsQKÍ7‚6Õs”ëOd¡††?‹J«ÕòFºuÔ àÇ^K Í úQK$\džûÕÝ…Q¨ *AQKDL­Ž‹¶Íµ†Q¨àݰ&Àj‰„ëOsÞäZÃ(T ‹s½9üÐ+¨aZÇ8ÝjÁ–µ9×ßaZ-MÓÆjˆ ÍaøÓ•ÞH¸^/[VKdhÆT©g^{$\Gþð:"Asi¾••ëJŠªZ ‘ å4èÛéÖñ[õâZØ„ èöÚ³Vßz;­Òú;4c ªê¥DºõZTS¨¶0< wR#Ûzu½Ú T°aT·oäZ/mUK؃Êz‚þÖ[\ë3&GD‘k} ôP÷ö xæ—z‰SÁWÝtL؃֯r&÷:C)kkÎb¡õtnÏ»,$Ä祫‡RZPËBß‹ •HέkÍx½~Cc-¡õln ÛJ麿¦9µ±–Ð:¦éoW(¥1(^õö øåœóÕü>¦ZbIm(Å£k…RºZ®¼ú‹»)'í ´ †GU/aZç8µh»B)]wã­Xc-¡õ§„µ„âç8i÷Å/úÑm¬&TZ¦mwÈ¥q{·Ž ¹4^©v‡^‚bC5¡uÄ©Ý!˜®‡îÍPc9¡5°=-´;4Ó—®­ÔÙ´j Í4~¸Ë Åë:&4Ó³4a=¡u­éÇõ„f×⾪±¢PA±î/* ­k;«QcE¡ò¦PßXQ¨@ÒxtLì‘×YCÛÀÆŠB똮ª%í Õ좸±¤Ðú 5ï/TÓx‚E¿!dÓ‚ud¨çÐMËëâƒM5…^üZ²6Tëïõêšÿî¼½[éžZ ÝtÝLS¢Ó¦’B¸½l‰•YôTRèÍ‚…­„pZ ÷èöTR³¼FºJ Ee{äu‡7g㦚B¯†Ñâ^üáò3iºxµ#i5TÓuˆ­“iïX0¦–?$쟟l…›ühéLò«)£_µ[Ì~b8“_³17ɯ)¦:Éo]Nfl“ô Nu&?×`ßä‡ÒÖæ<’_»…ä‡l¬¢C‘j߉¾ª39ïr^³KGˆüPÃC-"¿öj+hðË”e ~HIªfšY[×/ ÷!OØüp_d ‘û jiá¿ôÉ3ä>d¨ªêÅ)Ÿœ ÉÜ%}ÙàŒO Dâ¾ÂÜEjÕÀT3(a¦–ž%VµØ û Œ™eÉ}Ø2TÝÍ”jâcp_˜ÔùdÄ}£ä•Ä}¨¤£-¼¸~H·Î*”![I“;ò»™ò2·¨Ap:m¨P›ØrZÑ¥ÂUuD`_HgÃ-¬wwçÓ“a|:j@Ô÷À/Ir‚_ðo?Á/JÊUÙ£Šw=,À/ÊïÍüÖ1»~‹’_}uA~‹‘ïD¶@¿¨Š&"ú=ð9’M„è…Üô„…~¨pf %úA)›ôCUœ×-¬µµßЬîXèkÞýA¿ÐÅve°“†¬Ðo×t2úAáz z¬µ•Õ~Ø1ðñ‰üð5úöˆ~øj4 Å~¨Å£=¦àï®®‰eø»¿äÅÅh ¿»¥@ä¨×·-òƒÑ4è±4Ïši„3B?lômˆýð1êÍ þÐìd‚¿kµ[bº`2áž Ø èZOZö O*S†¿OLÐFø{ê›8HøƒK’fÁ †4ÂߟCø{áWÇþ°‡ü=Óý }}u‚¿ã\(Jø{¦f³ßƒdÈÔ½¨vÎ{'Q’ûê}%{©š.þ¨%¸]úÙÁ}µ»–˜¹¶­â¾zå£÷Á¡KÖq_é¹µ÷dÞÓ‘û*L ê™Ü·uùä˜û`½2 ’û0¯j‹ûjM‹FpzáDbîÃìÌý¼°/üÍ„UÄ>¸Š׈}°D‰}øáSýû`¤ñ¥ˆ}øQ"a_÷ówSÜá†þ&õE K]šÔ‡K?º©o-nš°L}µ´D&R_½å{hèÃÂð~¨¯ÆîïúРmµ –².š$ô­IS ¡¯æteèƒÝIOÐ]ÑÝújw8C_ôó>øÙ½ú ‚¾ëÎkúj³•ÖÐ‡ê¢ AØ»à}M†€ ¾ö<É\$>,AC-$¾pð3ßш³~YS§$>8ë=:†Ä×<™’ø¦vI|°¬»%–S˜l¾ÄÓ€ˆŠÄö±ˆ/N©ú;ÔVó-‰øÚåô­&>üLÙD|M¯D¸V>¸¢©‰öਬ“H{aµÐI¤=\§¨…¸×°KÕY3­;‰uQ9UùZÖÙ1ò5Ôâüs;Uئ¾è¤>X¹¿Ô—(“Ø÷>Ég}Èol؇DÄ_ů{'–Ü×k’àNôÛ¾Šßj‘$`îë¶$÷eö´ä¾½¢‹ûPþþ(~cMˆ"«à>DG˜0­ø¥¡Û܇MZÄ}säýüP+Gû3ƒtBk€Ê1z§")òC–I)sWæµ:&Åïz~"?è„2}RñCÅH sRü°lÈoÀ·MW’äw»JqJ~÷û×ù‡5Í“ü¥¢Ý£É/ÝÕ’üJ R&¿õè»5ÀÌ?£eJä—†P“ß“ò‚Éom–Eì&¿'IÀä·)Ää· ÃäwÏÝ2­©š2…~¨òª«úÝi úáyêw ýFl÷£ä‡ VÌä~»î­Ño½(ýI÷Ó­‰û0‚§H°¨NS¾Å}ÃÚ–ˆûF®Îä>lìÌt¯ê4ånL܇–rJ~¬î¤c䎳Ĝ“î§—k‹û¢$½i,¸/¼Eu7ä¾ÕÒen÷E9E qôÇ1Í$8($KR!÷IË0Oî{¤¯Ü· ÝfÃ&?ð,%$ô ÓÉ…%\”t=´È¼–§m47$¿'"‰DlœO«ß7ÉïAœ‡‰MäWZ² ÉÏ -’üjšWL~k@ÉäßQÍ$"¿»ZÐø!‚¨  ~WìsØÀZçÏ÷ÁY¸žÜ÷ÌÙþzb߃šÄC0ØG¯``߃ݾÌľ‘›1/¼#’£‰}ñehLûžùh"ê‹ONfR¶=¥‘úhv_Ò|^I*¿°giYòŸ è¿Õ’Oo¸¼KNÕ ¿p:÷»¸‹Y1™_èî&ny¹¢î/ŽèG'õ#ô«)ÕýP…OÇý€ãâˆ~(L"Ñ®ÂZ«ý‹ŒÐ˨QëQ‰åtAú]óNaŽèE·u Ñ tYœ´“ºB¿ +’臺Ôú˜…~Wxí³N4؉ —xíxI~ú’2Bô{fšÖ„~«eóc#g³j)ô{°?4µÑÙ!’Ã089¿È~vžVßÊéÝ32OZ»^²_Œb_›±‘ó¶ýMìÁ ÒÉ~k«V‡Ø/†µ¡ì³‚HDð‡qó…¿5!i·fø{|N4©{ŠüÂý#÷a ›E~0þIUºw5`ñ­È/j[Ü£)um(.³ M©0ŠI`#ù¡œ¸Y䇠ƒfÔ£)µøK%üa—,6üa ]øƒËÔcÔ£)ù„¿ûø®k3H{}IŸ„¿EÜuÃŒ‘Äìè“$±‚WFIÎ,Í&ø{€"›ý"¤D§ýVËãßHö w2¾(¢_̨U'1JrfƒèïAd°yPbßãðÆ¿·Ø°“ø‡'ôÁ¿ÚóW ÿê•Rwà_±§úö{~TÞô÷ô$\Ñv·ÑÉ?K¶‰/¤üÎ7]Ã(‰¯üUðfàËJX>O‹ |oÏ#|°á±Á¼çš›÷2¿ùÁ{–Í6ï=_Ïž†Ló^wj²Ôùzn§¬ó¡’‹z®*q¢õÕ¼÷¦V`ÞCì¶Žï½o²œ„¾õ3ÅiÉ{÷Œæ=utŒx…ZÄOæ=g!H¥/'îTúJ|”»¾}<<Á£ÖÅ{Wî+Ì{ëÁjbÞ»j {佫¦»©€ïºÿúå=0ÁWé»Ó¡'•¾êUϼ‡t"¬à½õíÏiÞkÞ4¤Òw›ïÍ{ø|¿¼Wê×Ã3¢ë´šš÷jËc\ÌS•¹÷àÕr*}xëRñ„{=}ÇŒ{ÝqŒÉ{Ý%5“÷F œæ½‘Š‚‘o+°F¾,i‘ÈwHrB¾9³!ßL‰›È7]*‘{[ÝŸ¤¾+-Ó–úJ~.B¾™~F>ÌBG#ß{!ß. jäíMì"òt>^žqŒ>ª@¾±º…|¨aiyÈïÊ€ÇÝ&â}…¤B¾7MF¾ýöŒ|Yr#_IÉÐÈ÷¤x&æé$`æËò|b¾1$3ùj|ª}QЊ ‘/:Fȇúˆjò ûÏ$ò¡ÅéêÛw}!^¹DN!0@Ä$æÃ1þÁ|óz¿j_´hˆù0ôbÄ|¾Md¾™9 Å|±)ÔšÌ[>I7d¾uÖðP'ó=Èã¡¡1c33¹ˆùbs)Ë¡/Vx½pB_SìüÉ}b:¡ ûb ÙÎØ‡Íÿ—ûJ>Qsßž•Ì}ë#Òó2÷Õ¶å½à¾éùÏ܇ѬsÄ}͹Éü øëÚ?xº|ÁnÐ_ðki5ø¡öÞ©øÅµº½?cmÅŠ/=_à‡ܳ=¹£ãŸä¾¹&žâ–NâH%Tà‡}¡®Lî›ãþºz~[:mL-EÀÁ؉îT0â¾(VùžÜÓñã–îÕB\$ÅÁjlÇÎ,ëùá>|‰üÓ5=¯ä.eÄÉbñ‚¾øTËéçÉY_·¢¸_äÐ1ʈ3k*€Êˆ“rI}‡iPßå°¤>¨†§Ÿçñy'õ]6p'õ]õ+øE‹}—s%ô¥šÐw¥ÿ¡ïJ¡ÎÐw;Á†>×}Þз1ÐÐ75¡'ô=Û×RÔ÷\Éỏƒùç‘%ÓâL§—ôÅoiq0¹¼:©¾<ÅB"óâàÒ÷É}˜$ô'Õz§ŒØµ¨ÖìthQµŠ /Î2<2/¶éÏ }ñm|<ãÛ]úÂsèÞÐGÔéã_¶v}È©#àô!Îm¯ÏPünäNžxõRQÅ}ðŹġà¾;rÎü}c_tËG#î»[~»µ­Ò ÿ•4aÄ€Yš÷`@~ Í6uA`{“Þ Þ‚mô'6‡?ì8?ëOIï•1r¢À׆ÄÀ’¡v†À4&¦7¼!óÈ -ë‚@/– ‰Ü !p\i´è‡½‘OIG["©Âüî7Kæ¯á»'&Áûæ‡Y{~ÂüŽ[@`lq¾a~(Xø…Àžw,ĺ§ø›Œó+éJ œ¯â:3Ì5³Ô¢0¿íÉå0¿â‚Ò¢À5T3´Êq~#]„ç÷æO – NP'†ßÞ<ãü¦:OÏuŒÝ3ÎolšTœß•~oŽó{2LN8·G]``ì“ }áž¿2Ó%ãü§„âünmLä·§¡Œóƒ‡[(7ô+Å8Åù=WŠ|Œóƒ™¸˜øÂ@ù¬¡2ìJåú\ôv#Ðï®M¢H¿öS#ýÆ•a‰Šô[ó^‹Ü=ïG5uí퉹¬:¬/L”årØ ô{[³ýÞ·'¶³gLô¢98{"7ÚGô[¿`8¾ž×p}_ûzÂc¤|ÂüÂ-îÀ°±‰3ç—s¸=‘×ãúDúAmÛÑ×?Rr˜Ý=×ôqÙ½ó‚D12¶Žîž% ÁÙÝïÀPFwϧÚ1&#ýžrt÷Äj©÷/wOd°žGwO ¹la¬_³?ŠÝ=ËÈMÇú­oFŸa¸{®eûƒÝ={œäîY¢säîùŒÄ2º{Þ‡&E¿×¶Ù õ›ùê·>û ì»íää Â7=w·ÔüÊ•žúýàŽ8Nþ‹@TÁ(E?D4Zz£êWñ¦>ÞžXÝí;)oÏ'›#ýð ¸äí9sÛÛ³¥™ŠÞž3M…ŽôÃüwÊ~)³š¼=‘Áí:ñ/¢â„¹öölûWÉ۳廓Ã'æ?·Ðá󸮆ÁÀgáÛŸããðÙ¶ï‚Cý.ïÚÒãsnb”ËgKß¹|³ð¶ƒg¸|>m$ÛQ÷ÃÏ´[¨BýàÃÁÉ~3£Óã3ƒé÷¾'þ$Ú›ŸH?L–ôäñù¾)Î)ÒsÙGökRÒ•(û!Ð~¢òøDûGö‹±õ‘ý*²Wé,Ê~Hx8Ü29Ô튧H?ØÌKŠô›6›f¤zÌ„Œô6ë¦Ëç[“åò™ÉéòÙ3VI.Ÿ˜DË7Òïž©:F¤_uÊ…ôùœ©ØØçó逪H¿¹aS‘~÷-!È.Ÿ ”ýÀ"(Eú ûRe¤_V‡ß‘~ÎÌ—‘~·W;9}®ñx¤?8kŠ|ìô kûIáÜ,ÿXGúÁ±CýPú{×ìàB9}æþÇÒ’šç釽—¸Òßú°ù§<>kK—Nè~ð»Õ{K§Ï;Å89}Κx'§Ï;ß“^«õæƒÞ©û…¨cúèó™ÞJéó‰9±¥|>G>=;}:Î.bü@Ü’ÙäñùôÄ6â_xÂêy|®I£~büà²ì³ˆð%×w üC²CÇãIöËJ6)û!¸äã‡àé¯×gMã½>/‹|éôù¤‹'ñnÍå燘ɦ,F™.ìÂ÷3 cJ‘Ír=P·ü=[žëVF‰ÿûœ·ò1çyÿBº°_®-Eòß~¹Ä?ZÖ#Š)ùðÍ}ºrËÑ•šŽ®²ew)‘ççw»ewå¦ÝÕn9ºªŒ±=ºrËÑ•šŽ®²ewõ_”~ ؼœÝÛ‘d ›ÊÊP‘H(³ˆñ#+w¹3]Ô/œÇFhy?ý‡ý2QÝÙÉ~7fƒc¤þí—Ñ‹qù†âtå®n,NãÝ]¹áìjä®Î£²+lÊÖ^dw¥†OWyPvu•]½=Œî»+5|ºÊƒ²«ã¨ìjF"ÚÝÿþtäC²Ÿ}ÌŸ9ˆñ,k/Æ3þ&(«” ¬þA‚²_ÆÁ?HPVÞŸúû}‚²ß«ß$(ûsâ咽_gÀ¿ýÁ,võ»Qûk_ð6°?¿äµæöû¹ü’• Æï¿üø7üûÓß¿üÏëy¬MÍ{µ£ñý7X©×¾ò/ÿçlÛÿúù¯¿vs×£ñ¿­Æ`+医ü;îoíUb¬¬µú½0Œpwÿë¿!š÷©ï_þ—Þym ÿò¿å…þ/ù¯ÿ×5…¬OoM9ùÛþßÿ®ô׫üåÿöoÿŽ$™ëÿþŸyòÿëß°õî×ý—ÿ}„¾“›ýë9ßÖ†ôBþì{ÁúÍùVvη9ßÞšî­0Ýÿs4þ+IÞÊ÷2ïnþÜÂÿØïünõOäw»õgóòp(¿4ˆÂ Ô9lÏwø¾v8‚‘#î'ÂvÐRhf»Q¡ šJ?Àkõ–¡:é-ŠõH`ö°%¤?´ B,àÇ Ð„ÇÀa®GËÐÅG„ˆ¡eêŽGä;ëPj™Ql@~ÓÆü\áÁÓÃe<ŽyîHìÜa‚R)Œƒõ,àæÇ½&Ô€…RH]}S£@B+l °¥Ì ^°#vŒM] qØ«a}÷ª°€ W-Z”Âø±ôÇ ÏÃ(™ŽÄm·STD;Dêá„Ï `ì#îGi#W§3FÝ0ê¾£8‘ª€Á×ӂ˰Sò6I"¦òâ†é¡ËBˆÜ\wÞì<ܳí ±÷’k­+ôj}¬yëQUøvñdPä›Zÿm†&2¹Ôbn>¤žY?&"xÔ‚²%í"vtÇoäk{B{[¤züŠÞcÌ\ºâ('Ïg´.â4M½#"1 ¥Ïì¥'éQ¾ðÙ}ã,}Ò}ýÖ5#ÅOä½Ð«ÅG´¾O¸aùê-2B¡eðC@"’Ç ÿŠÞaü£é"E{âs çÄé_5 ­/B“>/8®7Óîot Ûâ‹—³>QÜËE[tT'ZÇ´\†"y6úiÙÏš±ÖgŠû휧àÚ·Þ\À:¥&DƬÏ4œ2øüÆRvç.üïz³07ªcù`[Ô7­õÂ'L ktã­(Y´Ž Î8þë;…«ÖË×0o¬¥ƒ“s¸-­ÆÞœC/<~ kÍ)ð Xß(|Æ8™Á›y=Ãàeáà³>ÑV*^¤ÅB32j­Oþ#z,¨=´:„ÿˆ¦‡¹ÞØz¥P;ª­o4ZÂ耈|¢‹+Eñ!|¢N@öÀ9ü?àƒ?Âjå‡ð‰âóŽ1dnÆÃáPŒ Dë‡ÓÙ€%4²‰Æì€Dñ…N¤eç9 k(.Ô:/ôÆ"—ž<éEt†m˜-ŒÎFä_lT!Z—ˆ4-ÏXDçšbHG¢õÎáçÁ)Š­Ï4â [î¨R×/ýÊ›å—ã}é˜'Ñ0ÓƒtžëæÃý<¦¦ݳŽ{˜Îj±Œâ˜ÒyV‹e=?…gAtú2®´ÏÝc)…«Š;†›óéŒsQ†h}§ˆ6 Ûz”!Zw—7~¸Q†h}¦q/|Ä ¶ùÍ•ˆ:iñ÷k)¼ðõ±>RÄ‘ 6ÔXJá©Âï8ê5rÑ¿÷lµ>Qøø:o,¥3?Ú(C4qŒì‹Q…h=²¹f(þ"T!Z_è„Ùñæ!3VÒé$(Q‡hýèX²`C¼ŽðN6Ê­)oBGy Z®_8±·œlˆu4Dq>¹RbÅ1î¶Æ:zÃ÷‚d¤k˜â7^ºCÿp¿œò¢ Ñzhð†à7ù„n‰cò 'zÇßšüŸÂÅúf^¼å+é É&z†¦‚ït>šÏ¢QƒäQèNT"š0¨Ürh‹JDÖ“K‘XQ‰(l.…–`"‡z㳟<©b9½/»O®ñV! öjKÙ¬·ð)d=ø>}Y>ãÃzõM@ë!Y¢Îì!smÿÀ^uBv³^uÒ+³J"3Y/þL±BEŠþr²Žcõz¿ õpÎ-$ê!­¿¦*¡^<‚ôú‘^Q$ì…CEL‚= Î ìE¤Ÿ`‡h öûæëöìÄ(EØ‹ô'× {1§†XšpˆX/âãˆWD½Hõ÷+Ò‹#>¤ò—aK¤!4 ˆô`@`DAGèQ ô¡D÷ ‡\(¾}’^ >¤·=Ø4q ô"Ëä8A/’¬Ä/ÎëCaƒ¢¼Žù€Ÿ‘(öÍ™¢<´ð±ò­&ÄÛaqF¼õµéS4âA†5ôqýœæD<ȱb-!ÜE‹¨.ï¶÷¾)/R}áHy—}l y×ôû1åÁ·êKyH9ûv]”€äPÐ!(PØ<„ü–ÄsìCcƒx3a¢7HáÙÂ^ˆs°ÖȨ"œƒµæCsDBÍ¡ß넹y+LÔ,‡nùB…rLÂsˆrqeQÖœv’\T×uHr°“ä*üº–Ñ™C‡$ÇB:äA’2ÓRþ¯dj3ÌÏç}Ò¦Ép¢¹òü¤ÝíRꂹL¿#–ÃÎv|X®¼- sÇ1‚9¸i©(º`®$Šåb.ÿwe¤$(š+i¿5ÍÁÍNP%œ+Éw¢¹’hš[-ÚÑ›çp)u# ÃYÒàtÇYºðÿ]‘]À<‡n›è<‡»»ExîfÊtîö…,Ü9o~êvÓe(-ÛMïR¶Ë+¥l7¼/:u»!À“n7¬0èÐÂÝ¡®¤)ØD·Ÿ‰®8òV@wô" ÃÝ~tû]¾íºü t9F’èò^’èòJ‰tù^év‹™.ã5ÌtÙ`¤Ö^é†1%‘n$_n¤s‹‘ΛèvÇ&:¼(9‰Ñ'D7Ñí]IñÜ@·G•n?MÝ~šº  :LtsЕ‘¤(¢+¶ÂèòÕšçJî"Ísûèöí™èö‹4Ñ•©M®n"ºýLt%å:ÝqŠ-íÃtÇ݉éJú"˜éòGéöIFºýŒty3F:<™þAº£EL—¿ÚL—óƒ‘.߀‰.oÎ@WŒËºý±èöÔ*¢;Ñí¯ÚD·ç#]I«‘—&À‰èö•Œtû7ê0 uŒ .Ÿ‚™®Ø×_L×3ÌÀP‡5¦ŸÂ],LÎñüô}šêŽK“êÐ"Ó‚¨.úÕEC•’§•4×@bݱâ‰ëzIÅW\F¢×E‹4À¦¥Ô©/v=³ÄŠëzzy ëÐ 5]\‡ùˆë¶ß‡¹-¾æº4|™ëxO²gln|ÄuÑq=¸.zù¨wØu,v=Øè;´ÐT`°Û®+»hé'Ø¡…;\q]wå"c.-¡CX-®‹ñÕ£•´êýìrãd®‹†ØÑ ëŽ)°‹CîSºë[†{¹ŽªVÁ ’X vÑÀË -£U‹’Á-_å®;/¶É ÷‡ìâ$égOFù,Evç!U‹¨¬OF»èWr_Ó*º¯ôj­²œî¢å£ÝÅ¥ˆÍ¢»8æ9Å»óZSËhM íâ:ZüÚxh±‚öp%-fx^B(,ZH‹¡°j-‰bMëèÑ¢u´¤pøj!Í~»ÖQ#1âÅ9qЇÆ$aÞq»â¼8IÒZÕ2ê-ÎC/šºÈyAT"ÌW먒öó A åø‹šûÀ¼˜’-Ñî [Ù‰v¯)Âh‡àÂùA»´''Û9ÙNIÜ’ìüÙm²«?ûdæä¸ÉÎ9g“ìZޛɮyEM²³ËT‚]ÓŽ7¹Îóý»fù!Á®YRI°sH[r]óÊ—\×l:5×í+™ëšu v¾Ýäºæ§\·{¹¹Å\w[5L°sÊÌ»â]C‚ý;6Ø5o+ìÞ”û vÍ»\ñìzzzìrÃt€Án™6Vm·ÌÛVp»eK¡F»šÊ§Ñ®fè¦ÈeZÛ‡ì9@¼%²Câ‰ëCv5wP&;øÃ)™€È.8@¬G´k·LLÙï‡ëà!Ú?R]kéE*®k™§XX‡(U¡“¸®m˜×µÜù ì b9í ¤—ñxĺ×&¢Ä: ËýÁº75cÝkï˜Äº7ýÆŒu1Òy'⺖ùR-ÔÕ¤C uÞÉm¡îUøjêtɲ‡PWMqRêä1“X÷^¿êôÄu™ðÃX÷Þ_¬{mFßJÃRS©ëþnR©ëšTêìŠmªÃó9m¡Îœ'ªR}±®»®Ø!Ô R©ë²n©®&pYªëÙ"°ë®Gx(uÏ+e.V$옮ÙÁù÷:µºíû›Zݳ}0¥ÕÙ; µºfgÄÔêRVN­îöÇ—bÝíÛ3Ù {Ë%ÙüôvH³^?l·U@±Ý_ŸÌž9MLvCþ^[®sfFsÝ´ì“\7oyqÝLysÝÌùX\7}ÚX7=¾MuYQÌPÙ¹N¨ƒw3WQ«uØì¼µï|ÔºËN…)×]›T%×]Ò«S­»¬“X¬»ìøjÝ5íá(±.ÈëΖëpÑPL÷*Y­‘î}ÓCSH‡ì‹º°î¾°ˆÎyÑè3–„' Cà¿JEtÝžÌItýCsøåf)šë~ÉIs=÷¿Æ¹®Œ`‰sØí|q®[NMœƒË¡º!Ï!éÄÇ'ùntýµª( ë[2Ðõa©K<‡ý>¥ºøæëƒçúL—Iñ²KŠ t=MºíJ5Ȳ`žÛ?É<7’QÍs˜Æk¹ñ&à‰ç_Q§¤º‘ïÖ@çª.ÉsNá›8‡¤I$1ñœ“y&ÎM%û0ÍÍÛ æ„@Þ“í.¹íæØDH˜ÃÔ¢N$ÙÝ—õ8ÂŽx?’\ÄÛÂ9$ü¥…@47ÚLŒ4¹[ƒE4….ÊIsP¼9Oç@¢q*ùçB7çʼns‘Ÿ„W²ÊäIÙ“l!üì—²Ýc˜U»G#á_I´–˜TmN²s%´»–ZÁ\÷8=·¹î¶£J’ÝΕ&»'ý:7ÙiÍM²3Do´³gþ‰v>Æh碥‰v· ÉvW²tÁ”+ÅöÀt-ätÁLÁôÁÞl¤æ°­Ô>˜v>KÌaGNy`nMo‡ÚIÌLÌiž$»+%F“³¹'Ø]Im&»+Ý MvW²•ÉÎ)nì.¿”»Ë»Ï;yÇo®»’!Íu>“\—A7Vì\ÿ3»3ìÒOépÁœ®EKc^9»Ë–ýìò$ëu;fÏzÝe‰)õºÝ ©.ÒF )IuØ_ ìEvø2%€‹ì¢…Ýìbóã’$ô#AaäÊ„Åg|Èn^Y·^ Sr¨Àn¸hMÆÛuçt!Úõ7Cô„v½XF3Ùy°&ØuÛQì잘\W“ÅuÈ„õ|À©/h°Û\j°âÙ¹Åd—>®‡æ'Ú. R¢žÉ.'û`¦OBú`ºž¥Ð®Ýye¡]Ë C³ÑïÛÕ4ˆ™ív¸¨á-ÏG²«—l¸Ûq¨†»¨$A–ÝÕ×r›àγ÷îªKší²Ú¢Ñ®¦¹Ù.Ë íêí/Åh‡PŸûD»ê:™©Ù9ý»Á®¦·»ÈQ/÷'Üù<í—I²CjíòÑìæ‘Ã·Cí…ä)Ü_Ý.m÷ºÖ€ý0³>¼cíRÛ´#消Ùó¹Ý‰BíÙG·+?ÌóÑ~˜~þrà §¤›ë‚ÀN¹n¶Œw3ו”â vöcJ²Ž´Z7ôkµÛ]ž"µn{ßZ®ë3¥CÉu=n,×uÅЦZ×SÙ’X·Åj]×*•bx‹ì$­îµ¿›¤ºW…D“êüm&Õ=?S]›é9)ªk¥”Xwå1â:Ì.×ìšm vx¢B%]³¯Ù.£B“íšÍ½Év-…9¡]«?EÙáÚÌvÈ“3?l×R† ÛÝ‘ –Ýí"¨bÝÕžœŠ²ëé7–avwªa ³{2ØÑavsN7ÌñZš³f>ªÃ SÑorÃl#UAùa6ÛsÒ)?l7J¢§1KŽ2;bBi!:ØtåD»‘!7éŠyϯV‡Ü·ÖºäŒ™f 9c^#E6±< †»iØl7Ó:l—Ø’l×e3I¶kÉvNâ°ÙîveÂ]Ž„;ÃÝH×OÓ]·Ç¢éiÂ$Å ïzŠîâ»n}%¯{3o¹®§nl¹®g˜¥åº^|w’ë°¶*zOzª”Õñ"´¡;˜uÞbׯ›ïÂR{ÔºÜ×ì;DЊæ`WÓ}î;oæv„Ý¥j¾é—ùæ£"àEtú’ïf=Økšè”lŸS'lrµHþÉß >Û}d rË™ ퟷò1ÿ¹,j¿^![v’±Ÿ/ñß–d¬`‡Ô?]¹åèJMGWÙ²»ŠdÑíó»Ý²»rÓîj·]a[Y>]¹åèJMGWÙò_E ©lÛztÿ©,jõwYÔîöÓÿþœEmµ¶t,Óý<™îçw¢F*à3¹ÕÏÃ{þÏAîj'HsWg‚4wµRWçAÙU&HË®ŽiÙU宎ƒ²«L–] Ò²«<Ê]eWN‘–=íiÙ‘q?ÿzµñ:åÿO²¨ý™9ñwSϯ3àßþ`;úÝ ýµ¯?ŸE­@-|Ê™EMÉÏú?M~6òÀßåPûM2¶6~ÓÑjüfQûÏ%-+á‘Òÿ¿*iٚήÿÇnFÒ²¿.‚ë!fãÎ\öüóÌekp in$.{ò³mG,{dg/÷‘¹¬<È(Á¸ô[Ǽ#LO·ãŠ¢¦ðËcÂÄR&ýDe“‡DäNXqit‰´ÿ“ÅV5ò‹WFsS¼~ášÈssg æËË/t«¥ÓïǪìzpÖa[Ÿc$¤…‚;SæÇfwì(#ÙùK2÷[xú [¤û¯w·#*ý(ÖýWú¸Y±Œ»·|¤«Zfl›±¼×&¾Ç¾fõÓ"Ñm·!¡T˜ÆfXi¸1e:ôJ» ÒöŸxuTÒ­mž¥B ¦9—™“tûÊ|I‚ûáðÙÜo& £G$fÍRUZWÃäžù¡¥/ò17zúJcb¹ÞkCÁîg³zA¦Úª¦öÙ‘\Á¿z–­ª–ÃWb¥˜nÝnpO ˆRËS‰‹½Ty¯¨HÑ#ÅI\û½£´iœB7[ð Ã6ÂùB°hÁb¼ô İ¢ÒR°¦ZذÃÒªQ÷Ö(/‹¨\~kÈŠ °Enlöú–[äºàwôö¨Ñ5R&o.äÖИh|+/Œb=Zt/3A¤º™~]´ ?2د–øâGæ’XíQgd&ƒŸf ] %¾À¯ ²%"žjðqÈ!aùO–êÉuîaÓ£ƒ]äŽ0RuŠÌQ¤ü…¤Üä*WBÊ|ƒÛýcFT 1L]Ψ Úç Œ²œ÷ÿ,ƒÉ• ©üðNã­ç?üî‘K¿? ΠaŽA¤&ƒ7A·-® íX+Ì 5Ø,83¢*5žA¬"V³{ƉLZETøraư²õ¡a¼gøú Aúªˆ3|ü}£(NpFÝïD"¸7ÂiA- Dœáå\mE¿"¿“h£Òú ”Aj‘)K%Ìj±ˆ®cd‹2HµóŽÙÍŒ5” Ñ‚2He0u‡ªD 'ÓŠKµ'ÑH¸‹fUµ†ûr±æõ"Qo'~( !½x®§TQ\=žE,ŸÑÿO‡¥½J4óqAŠ4lMƒ¢Ò¼yeÎ (‚T^¶ð£òňc&ö_«å½~­Õo÷å _=‹J×xŠÕ4nïæYЈý¶”‡Ÿ+ïÿe¾±ãÁ R|«4t¢¥ÅRºZ$,F¤õ±B1Òü¾QnæÆ\}±;a4¨âÅzÿ•ë뇇*H™Èž3'?ÖÞX¡‘f<ˆ¡üµµß•+œZüý° ½*Mùg³•€WÇ?<­” xÉàù6àiÇ’„§Ä;ðÝ·ÏwIx·õñ$¼ÛÓ‰xN`–„‡=&7þ&¼Û f"ZóþŒxÊ ³ ïJæáÉιOåÄwª—žx÷XXN¼{Tõ:éUŽDe¢»½‡6Ý=òzN¸ËüØ wÈýª…pçcÉvf•D»ÇþÁÉvôöD;ÔKãíŠì2÷A²ÝcµÈlߟK°G¸K¿ÃÝ£B<ÉvéË”pWìÚ˜tW$£$Ý9È)á.£î·’p—±— wÅ’^Âdwö"¸Ë0Ú„» vN¸³?@Â]±wKÂ]:"îªS¡'ÜÅÞ'‘îªs™î¢„¨[:šaAxŒ®ŽÉwpy,ˆïHí"¾X›"¥Ÿ–øîàvØŠ‹ïÐ ë„ø.ðë:ùÝHÅw8F!Àë.šeÀ ˜¿“„.¤^¤&ãçE +‚ºå4ú·.­@Q‰ /ŒC-“¾?—©Œ—¥TÍx°3ð^ÅxýµÃ»!—§JŒ"Æ?šñp’ž¯‡tÆnÈx;™¾Vb¼Þmðâ…Ù}“²¥r¶ŠñºKuñÒëA„]ˆŸHx°xPè4ámŸk^xT7ñ­ÈãJ¢"áÁMCoQ„×Ó2™ïvØ‚ùº±†³ø½hpˆ-`KÑj#¾ÛnÂæ»È¡^~l¼Ãçül¾Ûñ]ŸšdŒwhðwÛé×x·]\ÌwI¯º!àE®öë¼^P !/ãÌx;%›!/ZÞò`Ú‰òt^¤R#I‘ðp‚‘/oû›ð¶×²/œ”Ù„‡¿õ“…xãÖt-Âç¢Ý’Ö£š„72-©oä¶Ãˆ•¹3â¡Wñ¸/z%‘ðpR9oÜrÙ0àÅ7Kè"ßáîM…wpÒCÞÁÓ‚ ®ñ>ºá²Ósm7ß…4œøndrjñÝx†ñ“x‡†qÐݰG©á.\EDr±v¢AGí`Nã4b´ÅD.²ƒ¯Y;ÁnDÞžC°™bÇ`7м‰Íu£ØÝÈ\…(«H/¸v9­¸Ç<ïÉu#išëFu̹¸?þjaÝÈlÜâºáüÆ:Á¹ÞXG¼°.rÍ©…X‡Drœ uQJs¨…¦Ñæt¾ÆºpÌÓÝëà‘ÏÅÔX72Ð\7š-ÂæºÑœ®Ú\‡~è©l®‹<ú$wqÝH×0s2ôsÐ ë†ãEuáúÏïDTS¦&6P]TVÐuIuÈûÆ,¨^Ít¸*d3.£a%¦‹Ú|vbºñ:6ÀL‡+!Ýx½³6Òí›Ô×n©†ºè…0F¦ƒ»€^¤˜¡ ¾2ºÑ§O¦£C%O"Ó!ó÷@b:\ˆF3ÝȈH3ÌÀ4ušép–Ìf‚:dO¼ñA»ŒH´ÃêX>ÂÝ|Ý1ÑÛœÈÎéjMv‘#–½ì°Ñý“ëBâÆì¢>3iÐ`7œµÜ`7RF5Ø–‡ìÖò/Ó€Án­ÌuÓÃ%U»Ý­°nÚ/±•A zÄ:,6ïë¢þ [„uãÝ*¹®§þšºÝ­Ý³e»;gËvYŽ'u»çùI·{ª’ºæóêÐÀÐ=ËvS¬¦nw;w…»Ûu R¹CÚÈþQî¼_Má.jà’¤Ü]-Õ3Iw—£R»C®bÚÖîî¯v÷Þ†–î2¨.¥»ª­Ü½–{R¹s˜o wmü$ܵ4eH¹Ëm‰±7B],LÅà'¬Cƒ!‰X‡-ª¼°.^ÙG¸ÃPàW"ªÛÙ˜MuÐ+iÖ!'ìëŸÖG¬ýÍ+ëBåËÖ¡Å‚ ±n¯¤æ:¬ÙÚ ŠëbÛ!¸ ®KáÖ\‡À'mLÈu£9û€¹“&vaÝÈ$bƺȓlЋõs”HIw·ß[Jw·DjwQP GíîVPjwwjj’în'wOíîR‰$»™»“]¢u’ÝW…É®?_í.vQíÐîð(õ Lvu$Юz[h²C®ýr’’ÊJ¥ÝAÁmí.ƒJMvÓÍ”î™1RºCŒá-1ÒÝí¥Ül·3â&ÛM'^5ÛÅ×#yOlç L‰v} Lv(Íþ!»— Öì^oLvÍ"§ÈBªT`¡?âÙŸ—˜Xl‡í,w³¹$ énfX¯éý w³˜›-ÚåDl¸‹$¿$9²]Œ8]Hl—i‹“íÆ“Ì%¶ë‰šb»î¸Ê„;<;¾6ÂfŽè…}ÄÖ¢»i#œán¾Jüe¶Cì°Øn:[·Ñ“•(’d‡ NïUd7× p3h²›O~";<*Io;dY®'×aŒÑÔ›\7”&¹Î¬Ä:Ðsð¦\ã#×Ýul vs8Š+Ànì v8ÀJ²›#­7B»étÛ&»™ÕåLv(J¥™Bd?‡ò!;<©yŠux.CzÉn^&}‘Rt!Ýô*‘d7¯›êfsn”­Ô¹Œ¨bÞ{BÜê uðE6•ê¿€s¥ n8ê"\*¨›Í5…þ EYB\˜ž†{ÒjŸ ç-¬®xÞI„súÀD8ˆ’à2ïV"\i©ð‰áJZ°Íp™¥2®¤MØW<#$Åe¢ë¤¸’¤¦¸âȯCæ‡ââí™àœª3®Ø C€+~ ÛóÒsüö¼ÜøcÏËž~–ö¼œéÈ(„ƒåõA¸êdð‰p¶ËGœKKÔö¼|劳=/» !]/·Ôf×Ëé “!®`Ò÷ÒõðÒ÷rû“Úù²y÷içËä$û^:YêsÍi–RŸËÜR‰qmC›Ý//¹@šâPú@Òš(î}ò$)t ™÷:eOJtoIÌ”D÷Úa…îM‰ÔÝë0å$9T2 C#Aîí)¿ ä^omä®ímIëw"’ëwB¤ºã¡œá$Éu‡Å&Éu'¨K’ëN$˜$—el7É¥k­ºîb*t]“y tÝI—S ëòJ®ç· ®{ÑKn¸ú³º‘Çè†wVèð§:•@7’ r2ô%Êe¡´D¹íz`”»sœåî´ŒrwšŒrOŠƒf¹§¤«¦XîIéÚ0‡ oG,‡×âHÁÜó&5Šæž7o4÷¸Ú[ÒüË%¯‘æ¢Þ×ç@.ïç”?*i®(‰MÂ\yRÇÍ•'QM4WRÓ5ÎeU™Ä¹â„*‰s™­5q. o&ÎÁ÷£Ò '¤NšËŽ“æ\ÁÆ0—™Þ“æ0ÏžN˜Qâ s—¹Ì07·Ë%a®>?ith±GšƒqÕÍ‘æBv0»ÅZ:êû³HW¬žœ•¥lI§«¹5µPW•·"q®nÎáu½¡®¦u]<‡^¸Û3еtèÏygjœÛšHà\»ó"⹦=H uçœêÊ>IB]óü–J]JVêZIIMRݦtkuÍuS¬«.Ç@¹}J¬«S#È<×<'Ð5g@K¢K_]m Šb:DΟ¾˜˜ÆéЉ#,ÎѺÍþ–ë^O¹îIQÒë^מNÁ®_†1éu¯ðÔë^GN§`×ÓÏØ‚]w¬w v¹%Ô1…ÄÉtö¥N¦öû7Ó o(“éæ2»âP†T즇¢;„€ó^,Ø •TK½;ùúÑëfµ¹ÁzÝ´†j¹.£ÁS®C ±~B\çËêví™”ëfŠ›–ëæÜ'¬³±ÌXlÖÇa®ké™`½n¾æÅÀ:œsr0Iß\P–É~ÊupÀ—“¦ î¶pl¦ƒõûþÈuS™F’é¶­ÊL‡ÕF:‡!$ÓeF¦dºtÇO¹nLuXŸ„ø¢:œõqÁÄÒ ™I`IFÔB°‹8wö+²sb'ƒJ˜*°+ÆlsÝål¥Éu—yÑZÝ”yü_HW–.˜ôV<1Ï¡M¦¼Çb)ïɘ‡ôÀt¦‡í9½Û2ç=Ê“˜÷¸ø^b~NùHuÏmÎ!vvbÉu.)´/Ð2¹)¼Ä¡â:Ä ¼…®ØÑ)¹ÎU ëžž“R貪\r]&'Ý\w§Ð'°{•c-/ÓC6/íy+¬«ÓCÅX‡3ï”è0N ‚ºšÀn¿K×I¿Ë¬ý’Ž—ÅAïéy™IñÓó2 M¤ëeO¹Ó\‡öJ‘£ëå–DÓõ²;nOž—¯cíx™õhÓó²Ÿ=/[ÊÇr½Ô’ßåþÆäx™Ž—™ã=/,–~—e¦&¿Ë¬™”~—ûaÚï²æà0ÓÙe//§Ë朎—2 Úñ2Sh¥ãå;mp°ãåz`º9^º`pú]®‡.ï#ù]V{ަã%b4Út±8PŽ“ßeõ I¿Ëú˜úävY3âÍn—Õ¹µÓí²yšK¤Ëà†Dºëò–RH‡ä@@2]äè]rq1Á›éú;¿žŒöÀb:|lBY1]d—àLë¯÷%Zdâ'Ôáé)ÒOIbÒ™& ®§EÂP¾è§R· ¡ èpŽÞ¶€3¦~ƒˆnWß4ÑE½•O–±ÜãYÊÖÆw~ó㼑r³yÜrfûÇçí£|Ì.KÙ¯WÈ–ÄëçKü÷£e'ñjàêòéÊ-GWj:ºÊ–ÝÕ‹ÄÍ÷çw»ewå¦ÝÕn9ºR‘£+·]©éè*[þ«³”5PÂzt¿ËRvÿãlb?g)ûMº±ÿ’,e¿£ÆÂr$úyøb`Öð?r_;™û:3¹¯}”û:ʾ2Yöu¤ ˾ò¨ìë8*ûÊdÙבƒ,ûÊ£²¯ã¨ìËYȲ«†,{ò1ÙÑ¿žª 9±%ÿ}ª²çR•=ªì—ÁðR•y(ýr±oª²ß­_S•ý™‰ñwóϯÓàßþ`*;úÝÈýµ¯?Ÿª¬Áª½öAGª²ÿöoÿŽ\WùgÆîLUvýœ´lýë>î_HZö«ñBÎÿöŸOZÖby/¿OZ¶ÞìÿcÿïÿžÃþYæ²uðÿûßPG`ŽyüßñÏÿÕ9ÌŽÆÿö‡ù§3k¥Gš…ÈgVöD¡èöØŒ­ö;vÙ·¶V«!J@ !ÜZ½ÂA §xÜ*+o E‡À|6ÂøJ;ãj™HH g4Àz6ÙÐy i4›ú$fLèš$¢eÄFûiâ„¶6Iá$ôÒ½²Õ[`ڱ؟µŠì¹G9†Õ0˜môÒ.µÕð2£ý26œkKZè%älåk£¤%Û5PWË`Œ&{EkÏKC•CªZ¬L<0Ô,,9Lô\-ƒ¡–ý[}‚zg iã`˵E¾b«]•|5 î´m°kmm˜ßÈArlm±’ÕÇdÔÞëâNÛ€·Z-|x/|néAÃmj{Ÿˆ@‹†Ì‹ùØøwçNÛ)ÃÚáÙñ„¹µŸ˜¿Ûá_íÓ°zb«¥ÇV»9ÑB{™ˆû~ ˆ5xh2Рy™'"রe‰ö×öŠõìjlµ_%+hý~¸ÓÎ'ޱÛg´(ZlÞeç{ 2: ñoD·‰Ìþ‰Æ”ŒÀÂçÜÕÂ*¤ÇÀ›…-R^Bäé¡9÷¶»6D* °;»EŽçüÉ“À7š.A 3Ï#·¡¸[8‘¼4,ÐþÖàå~Ë‘ˆ 0¥ šªùZx&TžÄXÒW£ÁzVÖ¿S/ð0óÐë¸AÜô#*ê.;q]#Ú‘2,ÒÊóMC\ !‡ž´ÈÁõžgAÄ7Šj|1AïkLyò~›T•°&ú4x_â }»¬bmFË8FƒaÂÃdÒóþE!ílñ…vû 4¤-êŒM÷¥`º˜ôXÒ1pªÛ÷¨EZ¥°qè^fc0ÖÃ_´>ز˾È:WP‹ù‹P¾(¾ÎGëåå‹Þóî ½ð¥¨já ÚUDì-7ÐWe§Þ¨^Ô‚/ÊÍçüEQ¾ˆ%æô P¾h”ðþ \Rªzöò^,~¡,Mo/šôŒÇµ‹èÈ7Å‹x?¾¨]Ä"zw?Ç‘óòÊEq\\_T.šŠíã3‰ÊE ”¤aÿE颔tøò¥‹Þø"bµzQ¹¨kXòD墇è3Bå¢WƒN-/Ï®¢/ !©~#¼Q¹h°_gËàÚ‰yŠÃ0*±Þ=*áu¥ˆ7*ÍãJQ¸¨…rÂÇ‹ÒE¬†À=䥋Zt¢A†ÚEL–Á}Ûµ‹^ÖG¨li\>×ÒÀ¹ûâE4$óÍ£xQå!üì£vQ|k(]T$^ðöYô.â[ÙéäÚ9ì¥ôFá¢О÷¢p¾ÎéR\o.bÀ¥ÔûpñœŽëy£r«…^ê¹rùœ–”^”.bØÞ(]Ô⤮‹¿±|N¯+ïËI¸O›ßwpùœ¶ö¿QºˆY8ø–`ÿf¯~BT.’E:é÷ÍWlõÞ€>LÎIQRî‰ sûòÒ´„C½Ö‹96äWór‡Ê4®|±Ÿ\"ÚSŸEÔ-šqe-Z±ø<˜¨\4Ù±zƵÕé?¬ú½ÑÐ ]”ébuJÄV¾ç€Ð>Åë~J, 8FKü3;ûáÈ #I“8áJ‡/t6ÿj¡;î“ÝŸÍcö!»Ÿ¸î5Ɖëü´6ØÙéh“¦Í v]Û“»ž0%°C<êì2¯Y‚ÝíÔ8 v·täºÛ€¹î–ëîæºKÊSrƒ’ë2QIrÝcm0¹îqõëä:¼Ó¦®J™º$¹î)‰hâºG;±äºG:‰uÎ'–T÷¼I~¢ºGyGê2ŸXR]¹Œy‚ºLgb¨Ëð ué°L¨³¯D2]qm¢dºb¥>™.U’êJ×ú–TWFö#ª+NòTWUì)¡®ZœM¨«Š«O¦Ë$)ÉtUSU"]ŠÉ‰t™S!™®Y2Œtpjý"]»~lœk~Ô‰sN•k›è^yÝD7…o:'‘Ú@—ýèœÖÌDYtÆéƒc¸ü’˜%Ô=M…Üë²nmb]u%æÄ:x\•ÖUçIH®Ëä v6H®s²äºêœSÉuեѓëªs%ØÕv¯wIv[{Ù5{Ä'Ùõ7{Ùu{š%ÙÍ‘žÈÕŠÕÀõéU™ˆä:x1÷×uOª vÝ)“ì^§­L´›©Ví†2g$ÚMI´ón0Ñ{k‰|D»á¢Ú‰vö$Ù½E R¢Ý˜¦£Kü$ÙõC¿“űZY1Ù '%I²›¶Ã&ÙÍ­é íf>)£Ý»G±]ÿhu½H½5×õ’z˜¸.MðÉuÑ= v#ŸƒÁn(Äl7œB%á.—+ÃÝ`†šD»Ì”l7T‡'ñ. ƒ’îàxú|è®Ë¦–p×ÓVcºë=•9Ñ]÷^+é®ËŒ™t×½ &ß­7ÍRU‘ÆÅw1ïé໨–ÄNÄwNÄf¼ƒÕðýà]®Ù‰wÓ2Oâ]®üï\L&ñn¨CÒÝp HÒ]ZË“îúÈŽ…w= ]‰wF™wÍ?Û|—i‹“ïÖìaiNöÆ‘zù.S $àm“dÞ´wwÞì)àð¦ÃjðfK-N„7£ xó6‰ ð°J ðööÆ„—ymñ°]$ŽŠð†MaF«ZIï‚1ïV:LSÒ„Ò›”wËiCž}éòî;Õ=C^³oC‚žƒa6èU­hÉy¯!Ô˜wù£%æ9÷HbjÚt9ïî?sžSÙ'æÁ/1.cÌ»‰y÷Ì+‰ón*KÌ»m0åáù_åý£Ìf›ì()ždwyÇm²+Nx”d—7“ìü( ÏdgîH°s®þMvWBšÐ®LûoŠìÊ–ãDvÅþ4Iv%ÅB‚]ÑL\‡Ð”çäºRS´'¦J¡nGL°nGÌ',íˆùÈ6Ÿ~˜÷w©×m’²^'Óôöü}3ƺbç’' 쪷IvE2©®8©hb]­y†°®:Íhr]ñ\Wí·–\W­ë²Âpr]µç´±.K)¥nWf¶H·+imnWzB¦À®(©®Á.$Ø!ÅáìrP™ëö¸3וž %®+JR“\Wœ )¹.ã“ëj(³f:W¥J¤ÃЭ¤+V鲌h"]µ#^2]f94Ów"¦«¹‘¦C¬´41]æWL¨Ã›¿>ª]ñb¦«ò@N¦«×vÊìÓe5ÔÕ+;ué)žP—i¯“êjI8”p‡Ü^ŽÊ]uÍÝ”î² Ijwu»>J»Ë]©Ý• Nï²>WŠwµ' R¼«oJuÔîòHª³12¡.g‚„ºê⤺¦doIuUÚuBŽø@ZÚ u8gžL×î+e;ijò÷X¶CT¶Ž«'’gI"”l×6äQ¶kÛRº]ó®ÂÂ]óú“Â]SÒ‚D: µH·k¶8˜èÒºšH—Á¿‰t'²]º>¤fóz’º]úë§n—¥aÒ³åVÚž˜­çýH·k)¡X·kN-›Ê]ëyŒ¤»¶IPaúl-ß¡ª:Ǧ±.ŸÕ;œÄÇgoÌ–®i¦º6Sš“;fâHª{ÓAÙòÝ+?˜TïÞôp³zg'ïÞ¤]‹w¯CE’êÞ'!N‘ d"évoKÖ’n÷¦`"Ýîu‚¾d:œ±l÷ŽÔñu‘çuY)&…»ž8aå®ßéâ)å®§õËÊ]O¡ÜÊÝö#¶t·=Ú-ÝáZóĺÃÇÝÚÝö¶x÷º˜PŠw=õ\‹w]!¦ºÌ—Ú]QKº]/É—ÒíðñÛíd§ –펓¤Ûõ„f{bv[ÛS·ëöâJgL˜Ù Ýkœº]l˜¤¹éöÔjgÌêx&:Ìg_ÌH«ûº ºOå.B]¤é0…ø†#å€j•™è0÷N5pm‰µºHÝÄÛÑÅ1õTîÖ…lœÃ¥ùF8·³ó¤#&’Áè:o.¢õýs²Ýõ‹lw³÷wÊýn¶smÉd»LA²ÙN9Õ6Ú]ö´Ú•4ªíÊkús”ÝLáÌhçÅi£Ý“Çí6V’íê•ä)¸Ãâ#ÚÕ ÄÛa¡ã½ˆí°ŠÄvÛ=Îl—#+áI’ëî^«Ä wë­IIÜa ’'¸ƒêõ~è©ñ®ÛàoºËäÁ§dgOxg¨”ìœ7éα„;䲨_ÉÎþi¦»Q|BIŸÓ^· `¡Í‚]ÿëOzÝ•¾™[¯“|‘z%$³Ý´‘(án&öîŽn¦,W e¤»ðžºK‡¤;{%îBN?5»íÐc¸‹š4â¿JkcKh$Ümë“á.Œ˜êWp7•ó5ùn¾ÂxáÌ„?á]$s’ ¦îþÅ“£Ò«n_‚WD™ðúÌgì^*·/Íõú‹øêrÈ•ý…p¢bBË0Âßj™”igöŒÈ@F«PÒìoD@P”Ã<¾öÆ7ÃWš€wµÌH—cS~¤ Ôhèx]T°‚š{dž£XF‘«‡#Ã}¤JêaZä>?ïâ1d€Î\×LI£~¢À_¨‡îf@†$´tlœÆsTªëáY>vŒBïQ¯‡I_ød"xj„ù“ÈNÍLÃ~£tëTk:à¼UZ^y3£Ðˇ•Ä1Hºí¨@ŸCÒSG¥åBzªàoz(_¼,°éðM«agi¦#ண²ÑM7ÕW7s+c·¨±îªÐíÖ¶ÆŽÚ@€ø+ß#J)OV àÝ ürU¡x^|‚ˆè^¬ï1*À–0ûpD£HlŸGÉöŽj­O¥Ï2Õ„¶8ßM¿hi³#ÙjéÀøu X:ŠØ^ßC"Òr<®“´fpü£tqZŒ<FÞÚÝïz$OT¢zl[-á;Iß[(â¡Å‰ °Ò(BÏ õ¬‚¼ X¬–$_µž(”ø|ñ؉žô”DêaIY-ðíúœ…xcÖÄ£l1n8ŸÕâÖ+»æ«?äÕ2£Z\󓸟—ï$ѯ÷Sƒå›M¾cMó–½VÃÄG:šm8 s_VßB×êr|z7 =:Ži5DÅkXAÖ@xå‘ÏœÏážf+qÊXoÃékµŒ@ù¦Lë5GIÈú‘ÏSð‘⻢‘o|ÔmºïháK‹²Mo”3Ó€o5–Ñy;ŒoDÙ&Ԃˉ e›&+së~£nS³¸é¨Û4žhÑ[‰ºM=úá§‚ÒM•Ðm[Q»i°¦Š7½%NÒdÕ›ÖÃz¬°Ž¨Þ„Joö­QÀiFá9}OQÀ Eðdõ(àô=¢ÆZ:³ ë@'Ô1¿mÕQÂékëG½ññ}ÎêÃ%ã¸6 ÔpBÑ»Ç%?ƺ8C ¾9ÄP¾‡ö×Õ0XºŽ] ~ËÝiÚÄžwÝ~š76°%º¤Ü:‚”Ìê¼GƒÅ›pŠ®Ø"Fƒ3‹7ÍÂ2X#²–Æ¿sÈ¡pӬʳ: êão/•k‹ðµ…ô8#ÄìTL>Œzï\Cç‰×ºÌû¥?ÔÀò‰ ñžjCtXÛÑiÀ6zGÃä%Bÿ>.Ùp¸=±ÇˆT?Q5JP¤iÆùzd˜%kTh×ka‰&è¬D2M%úÐCe•&4h Ƨ´î:Ê<±ûÝÕ`³íÀ[¾?G`¿û%–ôb&&ƒvтӑ ÿ ÕLjCån6ªÁüÙE]d5ìP¹åªÁRyŸ ÛpJ-ƒ¬’ddƒl‡²èÔÆëEÕ¤6²<ˆP-^ý)± µ„i°?©F‘ÕÐr¢þÖR¨vžCTÛöZ£Zlùo«¡åÃjûBD5lGïÀvï'Ü j0.45©Í¬ScRƒ;¶pC¤v£(òs l76º×!°EC?6\IÝÕf¤™Åbs‡¿ò©°ÝwQ’0³Ú…’y%ÂÚ}E6ã›ÖÖYå¯x„k«åÆÞeãÚj‘SŒqmõ¬|´ÆµÕÂÈj7öËl¬­N°lV»áO}ÇK¬ÝwêÜÖÖIì£àNáÏÇ?Ij«‡(ûœ¤vßÜnR[]^¾¢Ú}‚6®7B\‹–—Ç×VËZglZ[—ŠJ£›ÖÎÒÚºãxÆ×Ö1ëÓú±im5ÀµöǦµûpþLáÚêÆ#Q¸v?\'Œ‘×nì¨Åäµû©ymƒ%*yí~E›×~DÅéäµÛnꤶuÒ­m€mu«Gl`»£Ô31‰Àv£Ž³%·¶ÕRÿ*N"°ÝªuDyíÆž«­x-NºÕ¼v?t§þ{òÚ:«rˆ›ÙâîÜDm7<Ø›4·À¶u̱ð÷Ķõ#.]‹à¶~¹…Á-~Wn‚[Ü_|ì·T"#¸Åý©’[ÜÍ<ÉíFIëÊŽInǯ¹­û›œ5Ln7ð¦°g’ÛjQõ;“Ûý¼ÅºÉí†_Ç8U¶8+F Ém=ÑBr‹k5¶ÜâyÕ”Ùâ¾§Îv¶„Án7`«ó:ünã‘áíFÜ@=ámu¬\ߦ·û‰ø±h!¾ÝQÝ;F…ð-ÎÏÑí­DZX´ˆÞâ⢷ÕòþUxDz ¿IIÑ[\jœôv#D¡²ÒÛ: !‰ÑBz;nYø¶®¥Ègã[ Ûzà[|–ÖbE½Ÿpäþ»ñm}óÐQ¢ø¶ÆÖ¥K‹ßÖ9òl6¿Åh‘ßÖ wŒÌ¿'¿­· £u´ßÖçàQ"~»;Rx .îOòn“=àbŠQCܺåñ¿'ÀŸ«îÖðø{ÜêxúâpÑï$*࢛qÜêåþ"\œÄ‡#†»Qéž½áVC”;ÿ{RÜjñ ‹âbªpãVËøë)·­Õ3ÉÅÄ+äbª'È­+!w|´ä¢ßÈÝøfç rq7Z¹5[MnALrqÖÍcHrq­;~Intû¤ªÅÁfÑ@[½¼zæ"¹Õ2é;h’‹5†‹ƒHîÆLtŸ$wßC±"¹µ(z%Éݘáh™Éݘ޸‘äVŸWüwôGŽ[ J™'[÷ùðK"ÇÅOãè&ÇÅ]ØvÅ-!"œ]Ç­eºéãÖŸÆ>9.zàâÛ;\œO¢!È­#Ëcr7‚ÉDIArG$¹h¨É݈H«<"PnõQõååÎ˶Î=an5(eˆ`îì!hîì!h.ú¸xÑ 9¼ ýtÒÜj@è+&où’¢!p.8LÈsç)ÁsÇ;ÏÅö yný»—:òÜ1fÈs7í8ªÈs«Áë%yn5øó’ß3Ú}ènñx81ÊU—ÙôŸ$OKˆ£Éç`¸Ëù˜“án›âîthÄ¥] )î~·Dqiï0ÅÝÎ.•— SœMIqGC@\þm†ÃüxI^#ÅÝé[iŠËõ·ê1‘ú[M±,ðm;Óß"÷¿áÛN>b~‹ üZÄo‘çDš=Xì“oz‹Tù§w4tŤ<œ2\N…)Ã¥ÛnÊpWjX–áä qªpüXR„ÛîŠVáREL.'P«pŠ9ß"œ}Sƒs­—á²–BŠpÇ1áe"ÜÖ©Á]Û’ÜVCƒ»ä!îrÁ+p[-”—»ckp>zkpéÄn ÎÎç–àÒ ÂÜv½ìLŽ¢Yœ-(ÁmWNIp9ÝJ‚»s&•w6„wËQ“Üy‰Ê©ÀíÑ# µ$¸+]`Bƒ‹ðµSƒ»ÒýEÜåLoá2å»E¸ãŠp9H¤Á]52Šp—fZ„sQX‹pNc n+Ñ¡Áe,‰5¸=Z¤Á]^|%Áy¸H€»†?) p)%+Æøÿhï]rµG’æÌy¯¢¦=Ð2¼´ŠF­¡¡ªÿ@û‡hnfîΓYU™¥ê†h’_¾~È`ðŒ'Ì/SL„kåyæhGû³ý‰Ìhé(9篟ä´ÿG:Jfì~:JºCé'Yžoö“L?7»IΑ!p p³'MúIf%;Jæh™ž’Ë•V“Ü6“‘Èmsù $·á$EnOƒÛÈx6qÛHÇ=sÛ\¥Ç‘Ûm'¾·]®£šà6ŸTúDnwº¶™ÜN×zKr»îôž¹•†htˤUf·’ÍnëÈ2²Û}ÿPààÏ/çUÃ[FaÞ(°Ï®À!Ú`sD›œóí³lz‹Äw§7ø¨»eÒ[y¤›Þ#òǽ­ì“+Jåþ¥à ®î<Òxeë|Ê•ð¶2a°á ¯îÞV¸Gö(7š,ln|ƒOô£x;âG.Äâ·u»`ŽnUü¢n]Êšd€[·«íšàÖã¸Mܺ•¢Î‡F¼.F§ÜZysp rwš\éäd~[Ë›ßÖ²C€ømeóÛZöL¿­( ù—&ÂED6U/ò[ fØ$Âmûúõ8ì¬Á×"²]l‡‡+ À*ܶKNnc~¸¿• · /µY…Ûr"cnä¼#ÜŽ¹Ä7äúÛ:½íûÐå´ö¶CG£¦Ä·=J1…EâÛŽg®óÛkxÒBõmß´²ŸêÆé]RßÐå³ÜkðµJõÍŽ:©¾íÐò¹Ô·ò`‹v Ÿó«¾aþF>;íÚrñÌ­¾a§CZ›Ô··Ç|US}Ã,ç`õ-¯…Õ·ìŒÕ·CŸ>©o‰DRßE°ùQ†ßKw¤|[¸ô¼H€C““Œ%î¼4(Z›w¬Àahâo p˜1ò¨ñ¼–¬-ÀRš©¿‡ÞCëoü^Y|³cNŠoðl pȰøvÎâÛåÏâÛ´ÓÅ·ó°gdˆoãøõÑÞÞSæàkíÍN©½rÐIímJh¶ô†(Bü¶òvZlµò†±™D$å 1 뤼yŽ•Ê[ž(•·Û3+o÷nMʆ¨†qo r4Jåí\¿>ÂV][ÀÛkPå¶ÞN -¼9ì®eA[×Û£žÓæ}¸ îÌ¡cKÏgöww«´É¿– “ª4·u[*ã˜M•Ú§,•s ®xO;¡ÿ§,½)šzS¶´¦05ùœtünÍ„¡5¢ßÿî h þùó÷ ýäf‘mþñhÛþ?ší7ÏÉK{K$Ç‹ö}ââaÂŒü³•ZªÔfj©§6sKµ‘[ê[©¥Jm¦–zj3·T¹¥¾•[ÊÔfn©¥6Ë–r£l©må–2µ™[j©Í²¥Ü([j[¹¥Lmæ–Zj³l)7Ê–ÚVn)S›¹¥–Ú,[ʲ¥!Ú:c¢óûùÏ®˜ÿì}ü~ýŸïh{É­r‹]ÿ0ÿÙõóŸý‰Ç?nqüñ“ÿìúùÏþÀØýןÃðïÔý½×ôÇàýw^Óß´ôÇóŸa½à}ÒZú³ÿ×éÆþsf «\d=7Ú?I[výO˜ýŒ«.¿Ÿüì}.þKýïÿ©ÆþYò³wãÿ–ÏSýß¿'ùÙõ{ÉÏZF´5ùÙºà¢ìùöAp|ük`(üâ,⎂ÃÎ;ÂŒ)ãÜ×µ¢…ƒØßߘ/!b=ÆÖuoQ¨ex!|Ý{,|;}!Èž“XË_ØôŠ˜r*y+’¡µJs+j×µië>{u½î‘1M¾B FÙ¿ÅnQùÒV§¹ôí#<1A™òYû×b³WHX¬‚ßµªNÄbSºy OüäúôBŒ#³¹TþN{¤óB®£Ù’­½†û½0´Kˆ©Ö(¹. ñ,ñÄÓ@\Ì÷ .µ/, ß-†y½³ø_t¦ /ÖBš«9J¼À-èÿ²ðá>›ÃÃ;·}ÀsA×2Òœ°ÌÑÅ߀Oøk,äø gU„i>Âq€÷+­£e[[‘L¢E¯ïpàúñÂÛ|}vy*¼k‡¨-ß U›øà™ù‹!¿'#Ç(ò\Ñ…%tÞ.^ 3´ômXý ¡÷Q®¨×A%yJ °¬_ òåBëkÁ j"8Bpf(´1E¸M”˜x–V ayÐÿTÒ_˯UêÝXôÇdÜ¥«¾–3ŠK /¿¿–‹¡—w^»ãZJ‹ç·ì¸ï¦øþ~¦"}‡P¡‰¡Œ~~P¡i²:‚®7*419ÿ©S@‰&V:ð=A&æ¼£„KHÀÇ‘7EšX•@ÝA¦žöüµ öV•P€¡˜Ú<Š3!ýGTgZ•B îQWâ¨×å™f@׈€úLGd_§²A b1g=ý¨Ï4"ÿݩߋyî~øQœio)ó°Úޝ"òìù@çdƼgù÷‰÷ï¼F¨Í´BɼuŽ(Ît|ÛÅâyÚ##É+DT_˃Ï#âå^ô®8¼¨ÏtE6»ùØ‚v§Çh:Ãðè…¾èbq^ù¢DS˪ÛÔK‚MGÇÃ+j4áH5ú£Fsüé ¾5š9J4!vS¿èkìL|¯~×Èå¢b‰†.ÀMO‹Ë©^K¬T²>XÂ×â:ò† 8S‹‰Å²¸[4–k#Höºdˆ·.µ]ˆø^b6àîá{ÍØTÝŒûîÉýð{EÀëé„´ézl£¸Òg§ðýi™ü` ¹ú^yBý.î;GÜGzuµüÐ÷"ó‚fæî{ t¿ÀÚÏñ«Ñ£rÖPPÂûâ9rØŽd†aÑ©*Óë†?üè;ãŸÏl`Á³5ŒxØäô Ž‚L×gdÚ#©`L`x"Ë ç?i˜?P§IÅ"-¡ß¦Eã5k<߯eËÑ7"n+ T›ø^öfžø`®üä¨Ór¨6ñÅ\®¥ äzMí¡Àž‘§õ'`¹Õ;Ý¿ÐIgëKh“È9è×+äË#ZѸRêžô¼ØCˆ‘t6^ÿè¿öÐñbÐ ` :Ýv<±Ü¤—7à³Lµ‡VµâÐzC£aÖDÖŒÙC&y¢ikÏÉœ#½¡;ãÕ/7óG›%“1‘nƒ2ÍÈd™ÔÌP¦üÕe»œ¤ e»ß¨¤2»'$–ÙÁÏX6\²Ù\6$ôšË†?[没4#Ʋ¡×…T†Ì ä!QÙp"$cY’£¨ ’‘JXÖ e™ ÍX6<Ã3– ;åˆܴHeJÐm&IÁdN¤f$K^=F²ÃN=F²tR1’e‰G3Ùa§h3Ù1 ÉdÍ@&;<$“¹ˆ“‘ S”›4D$;üÝ4’WB™ìpÆ#CÙáWËP–IÆMe‡?½¦²ÃŽÏ¦²9²HeÓSORÙÔ'ÕPæ,f²YìD$k2Y7’¡¢¸ˆD6ëC,"›gƒB2g^K"›öN"›·¹gS®6O;Ddø"Ëú®IdX¸›"KäO*ËE‚¤2|Ç؈X–IÝË2k[rÙ)Ö#“Êî-$;ëó/$ËÅ#,».¥ÌÑ$F²J×f$ûX‚É*É›¡,ŠÍ –ʺagim³ ™¬·1óÇ›®É*øÄHVËF2X<ñ “U˜ˆ™¬ÂD eµ>b*‹zÒW§2¬€,ÍÚ@e6b*ƒEŸHaY…Ë0âݪÀ²¨­|šÂBt¹î<+rY…’Ì*Á½Á¬ÂB f™óÞ\õ9}¨ˆŽÉ9 ±¬ÖhŒe诧mIJ 61•!ldhÖF*Ë•CYÔtM ư,ÏZˆdô"T#Ád½‘@² F!“U¸Š¹¬¢?Ìe¬?ÚÁ¬‚J fQ…Ö|¸XSzäÛI0«àƒÙ}'µÌŒâ7‰hVáF³¨~*ôšU¾9£Yo6È I6˜UyƒYß„²j[|"—Uš:sYÅ™˜Ë¢P®éhcˆŽ—!fØ'Y.À ?3ÄøF’ÌpÒï5Á¬ÂL fñ™7¼˜¡3bHfQýU·Ÿh‹žÒ & à& ~Þ‰geb<«’ Ƴ q1a¯‘Î*¤Äx†e8¿×ä³Ìg>ë+fä³ )1Ÿ},÷h ò hØÂ£$ ±+~êIhýH$´¶ G@Cà _;5·ä³¶6G<«ÔvƳ C1žõuÂ'ÊO<‰ò´ôéO@süˆ 'áUAZ<6¤exK2Z:ê'¤µÕFRZ8ë¤Ei[ Ù´¾×Asáâ´­> â´-‡DaZF2$¦¥ãzrZo˜œ¶ïµÍã•M_NZ攨í9(Ôö†Xµ ŠHPË “Z%×KT£Óãß’Ô*õœI­b%Õ2\Û¨†îØ‹…¨%bM’üu±„jèž¡Z˜Ôj]U † qË0ТˆsÖ?÷‚Óêîÿ‰ÌfB5œûûíLR«"jX&Õ°J*©‚¨†%ÐMdÆCMÞDj•N¤Ö ;3·1C˜8 ?MrãÑ2§Y/@­ÖOEj}—so«©Bµ\©UF:¡ZbÕ!Õ`0ªõ-Õ*ßœP-ª»Jð Tk»€ÕZ¯HkQÓ4”GÀZ-ïŠÖªÓ„µö;X­ýTk'ETk—‰¨õ]yïˆj¸n‰jQƒ·ä³({Kí+P­]g¢ZÞ:‚Zß=@­€ †X A “[€ZTÀ=þ’œVÅ_Äi}à4$n‚Ób¿¨µÔð[ÓE‚Z>²µªîkR«‡Ö¨ËÕz3AjÃR×}ä5láÑ~»¨ÜRû&H­+ $µ(qÊ/A­ µwýzÔwÏ iýÀ„´Ö(ícxÔùle^ŸkDNƒÅ t’ÎÜ`´Þ$e3ÿ™’™Q/k×J‚Y³H1kW+³Ö)fíê…bÖ· bÖ-T̆²ù¦`Ö ·.¸/Ÿ3õ]jYÿ;岦 I.ëÛ¬ó³…ä²±J “^Ö,ÔËÚM‘^Vµ^Ö–^ÖD+ fMê’`Ö,̪aée­™û{ÖÖËÚ¡S/ËmR/³ÅzY½ŽÒËÚ‘¤—•3xée­ÃÒËú^̺…‚Y»¢¡˜õÞP5ë©fõÄH6ëǦlÖUÀå·ÖO¯d3=3’ÌZ«ÍÚ‘¥šy*fýïsÿñ›BmOµ¬jY½Ëú&Ëz·)–µ¨•µãJ+ÓqC'óÿS$kHÖî‰D²vH©dÝB•¬·C•ÌÇ¡BÖ®¿$2ÿúX„$²Þ hdýÔÈÚ«&¬uBÙDz¾¯£$²¾ 5²ñÂZï$’©óÈzÈü÷{´ÿ_zH||*cýhk¶§DªX[¢˜ÿ¬lÀu$ˆùï‡?‚î›Ä°v@©aíç÷¢‰¶úAH[>ˆ²×òŸP+g©‡},æÖ¶ˆZMt— Öjåˆ"ÔÚkq&P« WB­#×"EZ½Y¢Vë I«íCÐjýhµŽ*Ðj;‘³²YbV 1+÷0eÕ'Ô”U6eõfHYÕcV·³º…˜Õ[&fåü01«.1«®¿1«ïCÌjqVë±@ëÈå“ÖDz¾NF-_®’rÌB‚+·æ®^¨I¼JÈ5^™MW™åÜxµ»rŒù*G™¯2¿—ùj· +‹;š°öe¥‹€5¼âgÀÖ>‚¯†=ÉÌWÎ{n¾Ú% ¯Ú‰W­KÄ«f ^•Axåñ¦«Ýn¤«ö“tU*ð*3n¯2·—ùÊ©½ÌWmVm@¾j¿™ãÍnš¢«LgºÚK¶]åU]%Ø›®ìéd¼ªS^5ñªˆW™^Íxµ»²™ùªmA¾j½$_µ]žñ9ùªÎƒ|•¹¿°öò{ae›IXÝBÂÊë—„Õ-D¬½9B’±œÄ?kOÏ‚@¬|£±z«D¬½Ö³…XÝBÆj{‰±òÂ%gõmÈYÕ;aVëŽ8+oH‚ÖnßÎÀ¬ÖaV? å°ãlYÈaG;õ°£‡zØÑÚ¡vä‘©†óq•+=,+[¥väõ9 Yøù¡“æ¼ ©†O "RÃìbXŠ·)†µ£P ;V©lÔÂ>–ÐÂŽr­ -¬ý–6›C"µ°t¾N-¬oC-l–«­´°YÊ€´°™.[’ÂìÄJØ,QBJØ,‡]IaÝ5¯w­Z { V?$…9éI*a³dIaY_0¥°yxz")l–°´°n¡Vò¶´°¦TK ›%³„ÖS ›¥²H ›3\‰a3ʤ…Í™O²´°yåC%-¬)ëÒš*.1,‹Š§Ö·¡6Sg -lz4µ0̇Ø;ia³¼Ÿ%†5]bX]p‰a³üï$†5íTbØuå}“VÚiha.¢•RØU“’º…Rصò—v­Rµ¨…]å1,-¬[¨…ÝåÀ)-ì.çdiaM•v—šbXúʧV «´°»¼ ¥…e©­Ã2•_Šawº—I K7ýÔÂ>–xÿš¸(1ìžåhH1¬´ÐÐÂúÔÂM©#S »Ó+TJXm!!¬éÌRÂîÎ¥„ÝõE•v×à,-ìc -ì.?n‰aw޾¡…½}¶pV) g]–Öv >ˤ‚©„e AãY& 4žõ)aO¢¤³.“Îú&¨Bøä(K6ë!l‡ 4ƒÁðI6kJ5Ù ¿xd3„I$á›U­1ÃY%7$a‹d±øt>võœUò;ÃYVX3›5áZlVÉÍf°hè›5Ñ\l†'1õ®ø|fÍ5£Y ×AfuUf¸¥z½fõˆËZ˜Š¸ ÷K_Sï~,ñíL)Þ¡„YGøO$3£1ê¨|/+°tVÌ |vV¼Ó“LΊwC²]Œ"¾ä­èGÊΊén`gE'…µ¯b:éØY"oF:+ægoEëÞôV\»¤³â*=‹ÎŠËÒŽœ—e;Ún$ UÐ2aYš}桱 šÝþ¬~þëÁ{"ÏæþõUŒÿ²uâÙtÞ¾Ô¿®ìù >BBÚé<«&´¬ádB;Юä\ZúÉ›Ðnå‹2¡=J8d@»CØ€v»±í.¹ËîðºÑâ³;CÜÄg÷n‰ä³Çä³ûÉN’ÏîhÏ“ž´UÑ ´HegQ,­ïE@[I!@óù'Ÿ=gŽÇâ³UßÒ‰Ù ‰ÒÒoZ|† ê^æ"Ÿ­­ŠÑ½«sFVf4˜aäei0ƒ‹_20íÓ6•Ì\™÷Îem’‚Ë"™¡fò§˜ðk¯HJxª‹É CÀ¯®šEÞBˆéŸ@bM’Y\ =D³OÃfýF‘Í*³¢Ù,ö:EIg{¤¾ìp×f/:‹<ºÂijȊ¸wí,.ßP¨X\Úȹd @‹‹åȰ ´àœK=BëgEB‹œŒz´Hhí¢¡EFÆ$²HÐVûˆÑð„19š-òd œ¾Ê®UgF‹M6E‹£E&Ç)K0ÚçPÁhq;/É{i‘]цHÕ†ŒŸ¦²Èó9Ïä:VĆ·”†1ˆU…Œiq<W`Zqæ3ºÏ„»À4 ¾z΂äÂ`-sªß|0Çàu¥“¥'ûûûÕVÞæ_L6XªÚçï–¦+ -%Ž~·L_»?ŸFdéÍÐÔ²¥5uì\kç+KkJ¦ÖTZþÝÉÃÞ™^ë)yØóÿgò°ßyRöðÅþ¦ûñÔÅótmŸçð¯ÙVO ƶ> ÄÔVÛJm}ÓŒ±­žŒm}Rˆ©­¶•Úú&S[-=˜ÚêIÄÜVmå¶>©ÆÔVK¦¶z1·U[¹­O²1µÕR„©­žHÌmÕVnë“nLmµ$aj«§s[µ•ÛúR‰EÖÆwRø¿s‰ý±\bd4ÿëoÆåß»ÿú»ïíÏñüï¼·¿iëç‹zŒïÄ %«T_ÿŸf˼eÿ¤•çßG,ŠL¾×æñDbí+ò_ÿãOdC5A~Lãò‹0ö\  ì8ð×€´ºˆ±ÎAÚ°¬O`5ŠÆB÷‘zÓþÌXè>*Æä¥Niô§~/IØbù‹™-õ­;Òÿy†4VûK= T6?ïÏb„®Èr_ TÎüL;ÅV ž} ¡.a.Ïy%j<«H–Å@å³Ò¼®q-ÁìXøYªEŽ… ®Ÿº¯+–ã3eê—îÊÙå˰n¦ìR6†H¢Ââ.ÊùŒíã”3Bô5< ö”f56†)wË`°¤›£”K®|-–”ŸÅØæßçñÑöÆF׌TӦdzÕäz-÷)Ac{+i/TyÝ$Ÿq>>0ø(PƒÉÈ#3›Ýw†Jføˆ$âMÀy O—Ž2gâ ÇN猬f…"猔Ì›±Ó;c¥ûÝÀ×óh8vºg<¹8ö'äáÅXü¾C˜í®SÞt|úÇ wF–^Aß­ ” >#TN dÅyWÕ z GhÃË%ú` mxe¥*Êè¿2Ôc‚ÿ­ôZ®¡ü^—Dwøn¹cé~¾÷ƒþð[¦Ncõ$aïO–²îƒ¢Å±xŸñlã /|Ömz-#Öî·\t-,”aqã8X?¨m3cí¾‚éÆqî Ò“ÏÐk¡sUæmÇå:BrÇÇ=[„Û8zWµ]zWÖSßëmï*hnô®ÊEË1é¿[¼…ÞUõ²MºÃ¿½æó°w•–Çœ{ ·{>/Á×B§ør¿ó:äݨøç÷iØä ¨…Í×ò|œ_Ëþ»v™D½ìC.Žòúçþ»ô[øï‹Ñ•®hEŸqŽ£45”»gb5*}4Rã~çàgl¡Á| ô-Z—(}´z³(}4+Æð5ŒiÉhçÒGÇg“¹Ô¿¡¨|Ä]ÜËNòùæ£ðÑÞ’Çu;xÌÙõÜÝIx\ò–y¡PöèãÝ=TöèðØF¬G$ž>„ã¶Ó|TÀù»ÓÁ²¾à#²sü¥Ò»›áœ•$nÜ×7Ükè¡ïoº#wŠîÈM§ãÊF7nuf–‹q+¬3ƒ¨Ç#çy'Æâ:3ÅÐxä;_ãõ£ØÎÓ∂µGæÆb;3IÝPÅÚÃÝãQxgè;<5¢øÎ•WîQ€gú"ÛÐß>³ž‰è`xÌLt·ÿXžïŠ‘ˆ£8‘®’~ñqHø7ŽŽtŸféoÿ6¢E2!,rÛÒ¡Y“áÍüq™dGD‡µ*?5Dº¶‰®¥NÑ…û¥¦\Dº–¤-®¥qÓÁ’èE‡û³æ„º¶p&¨ûXê`ÑÝþÌ™'‰îÓ•ç›?ßH÷é ýí¯=E ~sÎ"¢ëŠD‡E="‰®å·ÒUg tý”It÷U³b]Û‡žöéw%žk‹‰â9,&š-Ÿûs¾Ä¹Öiî.‡/Ñ\ß„Rn; q®o4×/i;ÉûL4×Rñ ç>{É;yøûœÃé\Iº'_9%ÎUÍã\yç°ÖIsÝ@åvHsýy)ב@sý8¤¹–}P4×DWå¾Ýí뜉s- p®ÝVÒöñÊi®š4×v"Ì¡]­ÙæZÒ@Ñ\ë a®_Ò\ïi®Ö«sØÉ¤F_ûʦ(˜û´Bgûna¢ÕÖ}úÛ_9k ˜«ãˆåªØ…Y –b¹ÖÁ,Jé)šû´Ã|«Ý„« Ó6æ’£x®®Œxî³Ó3¾Ý{V/Ïaœë½#εÛ&œk;‘æî+ù”0×Ïš4×Þ#áÜײoÅ_̺ê_H¹z»äò¯L·ÚÇt«þ;S­V$—®Â pýÌIpnƒøv_¹|øöÙž‰V1—3ò¾U¼˜è­Ÿˆœ!*¹¦è Íhj)6oÁŸÈH–·¸XS‡0y=B8ŒIÖ–€p=[®§y#Âõ„md8¬õ¦p7™~­ms­MwQ®Å)‹áZܯ ®…èŠâZL´(î³×º[Y Q\߀×½2hÚ¡=ĸތb¦Ë×óÇ‘âzçHqXÎÞ mq-ÆX×ʃã>[<—Î û»ŽžÀ×6ÆU„´(®õW—·D׎,Šë‹øÛüDY‹ãúa˜™ª7×î¢8îÓìÃÌMð[›úŸ{-‡Îˆ…¶SÝ÷2)®·KŠûZžïïãÔ ¤XÇ4U­/¹w/’û´sŸt¦¹Ößgûö_u]ZË™’ÂTÙ%c ‚åú>d¹j•$÷Ùâ?®?Iî³Í¼Õû<òùÍxÊ\SޤÌõ½¨ÌUo(̵+Â\߃Ê\;Ž”¹¶¤¹öØIšÛsÝÅÒ\߆Ò\»’溅Ò\»k–æÚÑ)ÍõmnæI©NÚ\ë´¹ºoÖæÊbm®+qû'8¬ks¹MjsَŶMˆsY/%Õ¹¶…Ô¹:©s}©síHRçJö£8× çÎ/ÉõK#m®Hâ\},$ε-¨Î},÷ ,y®‰ò\·Pž«|¤–çz;·K4å^”çÚIQžë;Qž«MBký•:×6 8×î’Ô¹v$ϵ®Hžë SŸëês}/ t­¿èú6èÚ¥ ®·K®Y$еV$е#I¢ë{ù£’èêâH¡k‘B×w¢D×v¢B×7¹Ö÷È™(·P^ ¶U³J T}‘Bך‘Dך‘DWÍH¡ë;ß·V ]ß‚ ]k„ ]{h$Ñõfîã{’èºáù¾¤èÚ‘%еû(®híßË"‰®š•B× ÊÔ ÷!F]ÛD)„Ûq•/¨[ø%ÍTVèzÃk|‡*ty tµ‹º¶‰µ6”9¨Y”:(o‘%º¾ÍùãKj®\郚…"]Ùéúéz»Ê!”wÉ"]kE"]ÛK"]· Ks¯cþÜF9„ª?Òéú^J"Ôús}{,¡®¾Ñêê6H§ëÍ®ãûY§«GÚ:]ÛKB]=6Vêz;Çþmåx~<%Rêz»çO©•ºÞÎõ|rKuvºù')Ñﺚ4n…T\¨@ô›¨k?[©Gës+ fî¶Í˜F´ÛråÌú¢ûÔå¹J£n}n­’ðÈv•±ÝÝÊ%~+t™ÃÝÝzʳsÝÍ{Ì]Uª´BWNhVèZï¤Ðµf¥Ðõv¨Ð•¿›%ºêºÞ %ºªpi‰nåú85ºÌ¡o‰®÷—ݪewItUJÓ]5k‰îmG«–èª3Öèú^éòñ J—½³H×ûB•®¹ôI¥ë½£J×|¥ÒÕõµJ×Û¡JW}‘H׺+‘®5#‘®œC¤k?)ÒµF)Ò­e$Ò­»9bÞêÛñÃí²z+¥®·#·Ë»9bÞêœü¤ìwY.“ò»¬²ß¥ûb¿Ëfù{~—Õ•ò»ÌäwÙ,êªsÒéªTƒuºÞ;êtí%ÔuËßÎP¨k­H¨kûH¨«ÎH§kÍH§[©ƒI¦ëíR¦ëíR¦ëÍP¦kO´dºÖð=¿P¥[]·{ôyŠt­/R麅*]kF*]ë‹Tºn¡J×-“[ØaO2]?eºêžTºf H×ûB•®‡*]·P¥kÉtíúJ¦«CI¥k†q|~R£ëMP£k“F×v¢D×{B‰®\š¥Ñµ}¨ÑõQ£k›P¢kP¡kû„BW{H¡ë†¥Î ®oA}®(ÐõƒP kW@]ßæšßÎK¢ë†¥¾¹+Ïç‚H kmJ¡«M$еŽH¡ë;ùã©DמHIt½JtÝ’)^ÓB‰®ëú>ÒèZ‡ŸãÇð.‰®mB…®.‹ºÖ¬$ºÖŠ$º¶ºj6º¾Ç<¾O†ô¹nxÔùÊ}¹×_ú\k…ú\k…ò\ÛGò\m"y®(ô¹þ›ú\·??œè>–ûǰ"…®osýüpJ¢«S’Bׯ8)t}§åÏÍ!ÑÕÖèúÔèºeüøtZ£ËÎX¢Ë‹g…®Îñ}7-ÐõQ ë*tÝòühåYŸ‡Û ]ÛE ]ÛI ÝÇòýpZ¢ëÍäô7wšû3D×·9¯ï3B©®ÿ¾÷_?-ÏÏSx®ïõ•bW v­ vݲ_?z'Ñ®)D»¾Åñüè¿D»¾Ïy|ÞQ‹v}“ëùq$Úå6"‰ZRÝ.× ê.{“šéÞ¡A>ˆÁte¦»gb].Ût¹¼“XÍtÓžÌtå{g¦ëÑe¶Œ¢»8]vcèî Å[÷ç·ƒèª.¯˜îcYê]ZÈt• ÔL×-dºeý܆P×-ò»lù]ffR9^¶ßr¼l9^¦%/»åÑ9¤EŽ—Í"ÇËf‘çålò¼,Ãüþ”çeäyÙÚLÏË´¤çeZäyÙ,éyY–ç{}Óó²YäyÙ,„ºåùþ&Öu ¹®[ÈuË­þe¹®ùŠŠëú6亾 ¹®[vÍ"²ËŸ`×Þ?þN¬«—É\÷±,€w"Ö5©®Hu½e:nR]·(ÙqyÞÕ}~3×ñõÓý²Êܚ꺅X×||…uÓÙ1u3³cë06sUBTW)ˆMuåŽ,¨kûêÚßÉtÝÀ²½g:ŠéšELל˜ÅtËóM†l¦ë2]·Ì½e]6ÒÍ,vi¤›ÎNj¤kå9®À3!]·é*´‘n¶à4"ÝÇH×-dºÖN@]úz‹éš¿¸˜á1_¦ëB]Öc6Ó•O¹˜®Ò^ê*™³¡®²g›êæQêß½£´¯íÇob]sŠ×eis]U˜6Øu É®yۋ캅d—YÄ v¯áL÷µð+:rµ/Ø®ÿ&ÜU³b»nXêœ »“•û0B»Ö¬ÐîcY?·!ÚM§¯5ÙeAð$»J¦N²ë¿o‡.¤…h×-D»™ù„ÍvÍ"¸ëÂ]fv7ÛuÃóÍO¸«Ü†»n!Ý},Î -ä» Ç0ßu ùîcyti!á5‹¯[ˆx•óžˆ×ñº…ˆ—‰óMxÝp_Qñ]3ïšt× ÷'™½á®–ß>G§íúÏûÇß vÍ@®ë~9sä0×Õ›h°ËB»nà§³ *u_R]éê>¿—Фe¹Þ}R±®[²â}r±®[Tó~ûÉuÝ¢š÷ÛO®ë½ß’È®ùÝ@Eï»åÑ)üÀºn!×5‹Àîcyt Æ-r]3ëªj±®·A¬ëb]·ëZ³ÄºnxÔuyàžqí@RÚOÆœSu*ãš,ŸŒkw¿–qMÛü‹׿X1ŽÖli9ÎdjɃÒÒÒ¥ÍHßÝŠß½z#üÝš87X;_YZ32µ†Òòoϸ6™µ²¥\û»ùÐöãAµú¿Ÿ“íÝÙ®{^’Fí··ÿXÇÓ.¯Ç÷QÂõP¡‘O²5¶Ù&Ÿ«µeKo«m¥¶>[¹­ZwoK–O[µ•Ûê[¹­–ˆLmõDdn«¶r[Ÿ¤fjkÅ„®5Eç¥ÜÆ Õ6øé8+üþG©Ê¶¿ ŸÁ;çgF¯o¾¯ÿt믿É9ö»Œñ›íÎß=ØoŽýγõ;‰ÄþÀ õ×ß 7¿7$ýõ÷ŸÜÃÔï?¹¿mëO$›1iyÄþD¦°?š ì¿"‘J*]ÿ¹ÀæûýÞæÿB¹Àþã÷rýÇ¿š ì}-÷)ëj\;ùQ›—ÒE*Æ)Ç™‹SAEþEô¹¿Ù‘À;,\hפv{d¼sßø¬š7-.Iá¥×väQ‰ïëܸ"…Êìœ,Î-ž< ‹WæÆ)¬UÚk°€×áyÈܸ&udú¦÷)àê‡<^æ¦pàá´ã¯…Xœ±y3ÒÔ2øô¢áv4¢Ü¡æölÊÁµ»ÃËÿ G8Ìm± ÉnfŸû6”¢êàŒfî»ëˆ_‹“<‘ÜæËÊA9 uw—#¹‚‘ßßÎ/#Äy_oÖ`½íl3÷s*ƒ…ôô¹Óü:¼ôZÂ…õ&ß‚nä8Ó[–ÇÅtaöÙâqZºÞû Ö—î•!iŽÖÁO\èœcVdŸæùÉâ7G\¾†Å ÇHÌqD®øXlâaF¬G!½¿.ä8#U|…þ¾–¥LöZÄšãŠTñHœæfîiÕ—„dîH¤ý>Ú"Ö¤°r,_yMËPfB© çkR-=ûÏ-ÒÅïãþ%C¼}ïÁ¦^}-P’°f®àŒ•©¯"Ó¸Ïóˆtñà¶MûÄÊÔ¾£”‚ ‘1o™†3¦Þ“Ü•{žWdŒÇ[ïCÅÊÔ¾GV'Y"cüŽ÷]–'2ƃ3™¼zžxZq,'ÿžˆù„¤,óïÅ":;|í‘2~¼x´Ïˆ‰¶‘ሌñ4|]±6EäïÊ5#c<2’úH±6µG™^,”- LÛ’Šœö¹/öÿP†þÉÊE‘ÀY# Já Æô›ÊÚEql‰Õ‹buå‹°M½ß,`÷EãҠܼSíD #H‡J<>cA}ž~ËPÅz—®UÄ®£Ù•D£=4úŽŒñ;ÖÁe‰Å©hæT;OdŒÇLG¯*ËaA]‡Â÷7á}õI`=#¨/~j ‡L±ãô“ŪFЋü˜£®´,¿©,l­ÍÃ+A™ò;‡ES{©Ý(nÅÆ¯ªétâ,o'®»ð(ô;ÐÊGqVúº/e‡ÆG~Èu°” §xíñ;Ÿ$–9‚šâ³Z¡ÕBMñèÍJGaÑЕc`¹ý°ØÖt=ήPk± é+ÊrGXÿT‰ÉzGXæõ¨µB®mô~°æV_}Mß¹!·àW÷dÉ#¬ë–Âz-–†µâ~²äÑ_NYB¯…pÀÇädÅ#,´ë‰õÇ)p°>Yò‹ºú œ[ȵXÜüÅU”<ŠŸ|jÎ-´Z¬#a‰Ò Çæ¬,çj-V¨´Îy²è UÈãdÕ#,ÍéÊœ{¨µX]b9Š“U°(øÎh ±KR¿B«Ý£^Δ%>ª*/°7¨z„¹­Š2œ{ȵ˜_ª(ÃɲG{|&OYâ«zàÁUû€ê¡½B¯Å¬B—ŠuÞCßz Î=äZLû|!X÷_vwx„\‹¥ó“åði×Od,G%5µ0Ôh²þÆ-=›g¼4Á“í«ÀHxjõvŸ#´Ú´IHµèµ®î¥Ó½Û'K ½û\Ùn(µ}AÂØ«Aí•n8òî}XiU‹7ö±öý÷ô­f $|§r›kqÁônŸ,„AÓwé¹6Nõ&j íPÇøñ>Y #޲œGLŽ£·z-Þ3}‘ÞÉ`ä›wN5¯‚œ$SXfèµï¿‡o¿–N&æ]håç û‡À7µŒ™Ä—l–È'w!ߥéz#¾]mø*훈oOÇl>(_â«”¢F¾ýq²D#% ÍF¾-AŒÄ7R2ña"%ñ½o»|L|Hvf&$ñ!%ç—øFRŠˆ³™Û|Dzͣ1`ÆLŽå¾÷“ 9ÕÀ‡T†*>õOÀ7‹@|Á£{G¾È$$ò%ôAÁ3"ú"YAòdš {ô!ôfT¼Öh%ôEµÖÎ|˜u˜ }ð‘ºÝE/×½@jcBaÓ¡ys5 õ¡œPrâ`Ôâæ¸[aßÓî-±5•½V܇4¢~ŒÈ}‘$Q›öÁuʧ ìû>î^`_T“2røöª† / ªUAß~xqDÐô- èËB~‚¾(äMú¢âž.¡/¦žE2¦ J¯Ì]PW…ȇنºOäC%!?òD>qËÃò-<çšGù2f¡P Þx?¾D> î0š ùpoµ—O÷Õ¼‡äâ²à=dÕûðÞVóó’9™îX ©“÷PêÒÅ{Óß•â½\'ï>õ”%ïf ñÞïSð&àƒ(ͽ|pHO ø€jEÀ÷Ä{˜ØBà» æ|#wïá{Å30ï]ÃçdÞCš<í%ÞCžJyT3ÅBÁ{`cqynT"ó^¤¦…¼‡9Š·!ðÁ+ê0øðéeoL|xø?Ä7VlI⃿ÕeŒ9øå+.âÃlßíŠøð´ëØ$¾cOðáBÁœ€³mCà;v}„ øpâàÃÌX“rŠÎŒ|1M×>$>Œ.zˆE|#ƒ£L|Gäó£…Ä÷¾” J[ñRˆø0ÕÔòÁ•ëEȇ¹¼!ðáTøök&äÃ4\¹>Ä#Û#K_Z4Gâ;IŠø0‘ŠøW4ñÁÓlS‡I|¦ª:‰ï@n>щÎgLJø`¹ñaL4©‘ø09Ô%⃼h.#ñÁÍÛøpctAE|˜Rj=DÄrи â;¢à]|3‚øP4S#¾€oN/ïEaK±yï¸sf.Þ;¦kì™÷Ú¼V¼7ÁÚ†Àw<ª$hÞÃLu¨aò^l¢fÈ{Z—¶ðY€¾¹'X’÷P½sÓ&ä= ÐÞI¼÷^†K¤FÞuñKgÞÃFÜ(àµ\B*ß<í›mâÇè’øð ÙñM”ZT+">¤çT+$¾~.Ú†Ä7‘—íC|3ÊÇÓ"âƒ+ƒȇÑ£m„|¸w"$!ßåW¾/AÜÈwJÏôáƒ.#ôHº$‹¡ï=#ÞF¬z Q‚>Ô)¶ú€^FERßû¸ç6ľ÷& lE}øpêú‰úÞnù±õ½DàûÔ‡ç.Ê2õ ¯%˜úàLÆ“õÖD릾Ëc‚©§)ZõáXZ“Hê{Ìø¢>ì5´ ©/*´ª‡¤¾¹\Ô⼿Ô7]×0©ëÉ쟨íþéc ~OD±7ðC ÑçC~˜¿¬ùUâe’ßÑ(ŽèWÎ~f¿òN4û•—©ÙÇ[¦ÁG.È–f¶t@—'˜ÙﺊÉ~•‡Íðw;Ç·ÙïÅq`¿§HÊj_†Ö›ý®;'òb¿;‹þî\>û™HÞìwfþEÃ_&É4û]YiÃì‡r–ê¯Øï~RF öÃašô‚ý0ízC±µÑï©«)ôC…‹{ ÊtÒ&?„ØJ÷Ü·•È)¹/½:ú¡ÐŠ2DZïÛ\qUä—¾ÀF¿-]…~á&zvô‹`oI€#g¶ª°â#˜à‡sœ&Áp¢{2Á»À“%ù¨øÝMz îCµ•>øáòƒ\µžÔª ~ð„5Áü¢8‘Tºà¾P~u™~1““á`=¦L6.îC$?Í?xáúŽüT¤þüÂMW“’_„iªMòÃ6F|’¶ñCFòk üžu$âüP*×,Nð[(º£s"ø¡’½D²ßƒÙDI}hVcŽÐïy¯”üã…~Ï}úb’üPì77 ò{2W¨ÀïAUuõ$¸/Òô»ÿ‹%–ó!ˆûtåëMîà ·Sßsd>‡ >¬>xƒÔ¥O8%$ô¡ò‰_úSµ\Î|,I}(æ²uèƒ ´ß3RßSN¢¾(¸swꋌrºÚ¤¾Èzã–³ÕŒ|ño€Àí߬ɴrR %yý‰Ô/n¿°¤¾ðë¾e ô!òWæÃUÖ6‚¾+WU }8bƒ¾ýÚR }XР/èÃÌUÏ eµ%B‘úPoÜ+‰¤¾¨’¬›Mê[mˆÔ‡ï¢2GŠúb¥EÂZ@|´ýú@§1ðýwEæÿÆgT¢§•ÌpñB™.åú®Šùà6á52ßód w1__“"óáÝqËd>À–`’ȇ¨A÷—ÈeD­G,—é‹CäÃÛå1…ȇðD¯¨ùPâÂ_%" pøñ$òÁ Åc«‘/+Fò92E> Õ"(‰|xYD¾’™˜ ȇx4# ‘oÇ›ðù¶¨o߆ì°4øà’naðTqö'1‘ÀGM–>Ìy¼ IâC=n-ÏøÁ¨‰•€»Ú‰ć<Ý%ßšOŠw|˜éé»*à[GFÝøÖHÕ‡¼‡ÈÍÑyoaúi0 ÞÃUb]ñœ|²3H…wì‹«_šÊÀô©Of†ï!8UÏx¯V]…{h5;IÞ{\b=å½ë§¼·Ÿ n„½Åh™ÅfÉ;‚=°Úõ‘÷ö™\$ØÃñ!#a ‡î/aÏÔó=Ärî}o;{Ûa©Û°·Áqá{˜&ßb9МÌdA{«®8aCž¾o‚=WïÈz®Õx!ÖCD‰Þl±‚N4ä‰õV¼\ö–å}¨€½ud¡<ÁžEÍàö°ðí‚°·*‡—`¡Ç~Ò{kËGÁ^¸ ©Ù`½UY®Ìz&nÖ»je!Y/o¾3 V¬‡§Ï¤¹b‰­ø¬‡Y¤Éެ7"hço…z˜zßþãc‰wwÌÝ;ÞeTSâ]âSâ]–ãހĻ#å¶Ä»½ðïâÝÙ,Ï79ñN2ÑK+¶dU>„v¨ô‘õÎTd‚ì°&êc쀯j‚`w\%óìŠ"^$×!B˾Ÿ;ŒðÆ8‚>pê,¹ë@çìÎ3'¤;¼MiarúQ”6˜ þ1€ì®,vc²»›3%É.ü>>¢Þ]Ϊõ2étŠz¥LYÔ³ª›¢^ºJIÓ{ò½²¦‡‘–“*€D?ŸÁ.òËY“¦7‹À¨ém+OIšÞÞÚQ>à§)x¡é çJ°¤7šXHMÕ}ð›UóÎtÜŒoR…ƒ[Ô›mªz˜lXÃc:àÓ¹&,ê½7îÃv˜@Y#Û=XmÒl“pªQp±àîY¥¢îÂÒà_LÏ—$ëmµê ]oËDuÖõ*©ëí…>Òõör‚Þ!k¡t2ÒêŒYµc:`Œ({§»'åÔŒgIgâ\‘jY¬Ó«$¢;x~|9[eHãÝá‰Æ»£qñ]UüJ¾ËåãÝ‘ðo¼»òࡾ›Ù €÷¾cžQ ðΙƒ—ç‘<„wÚŸÈ€§M+Š$<ÔÖ¹>„wy±Û€Ìýð&Íj–x÷Άüî ïÀö6Güör’ð³1‹fÄ; s*ÒÝzªÒÝ*° Þ!ÂÕ×›x÷T2;áÖ¼Ð@¼Ã#næÞáSmâÀǯ1ñÛx¸%Þ-Œ!fXâ¢uS„w£ÜÙ…w{® ‰îöZ{Ýíž]šîÞçYïºánK8¸;ÊApwÔ¥ÝÁÝdtºÃL'y/èíúÅ!Ýa›« zï¡âÁ~5 vëÈ ";Àª;K²‹‰šÁí%»(Ní.f„sëá+ òñì0›°O Á“ÆäÅ»p7ø€žÝ r]hë ×á•ÐÅ&ÖaèÝÓ›3’ß–‚êbä½-ÛE,ÄÄ#ªëc1±{‰€‰uhÕL¬ã‹eKCàéÔ0E¬l{¹€X‡ðG¨ë0¬zè%×=O¦®Ã ¯©)±×b7¢±.Æs;&Z\×ÖÄuðWQ„‡ÀÛ$^±2ÆÊ‘Vd×^G‘,ZÂÙåŸdwû”Dv«Vx…v¸Ùš9“ìàö¢uK‘ÝrЊÀ.^Ævx#L"»U9~EvØÉÜA²[¥1ì°Áf °C¾/Á»|D¼Ur±ÏÞnÕ1°§<Ìpá³¥¾D¨‹®éÒê\'¤´Óáù|¬™ÓÅô^Ø÷ÞpdLZúI¢CÉas‘.J/~@L—ËcF:@ÊÞå;,˜“èüŠèæ^'$¢ËÊì&:Dí=&¸—è°*Ô}6W•3СêU7Ý• ˆîZ~÷Lt¨ÉæCÑÁyIw]d\0‹Ñ­tÑÐÅòt×îð¸LŠkÄ£à‡<· }¤;ðÊú8ln¾Ó&ÑXc»™ÆÒgs•ë¤Ø®Ù.Pš Êëï";gr5Ø9KÌ(½|E3JïÉú¸;Lô‰Ø)Á`wæ"õ–I£<çØÁ¢MvUTdw¯Ÿzï½É@º@;(SºF»§BÜÄvxSÝÙ`»Hšm5l÷Ô’¤à.ƒ ¸Ã°yT;,ª–Žß%8§ 'ê‰` Ò»³†žÃô0?Õ‡IazX´%Ãô0Q0É ­çäí°r˜!y|¨ÇUÊU»²w±H¹ºj‡oÐÛŒ• ºÃƒóõØÜ‘rLK¨¤»}Û¼æ$ºÛ·÷‚jA_z«æŽÔ+µC‘z+=¨‡dXz("Po+uXzÑAwáЦçÓz+ÝÃHwäd S ÞÛáÙ}6CMдБzöèH½ýÊv©‡;(OOêá‚hÞzûH§ Ô›öKR¤.Ð'PŸ¹¡#+PïJç&ê!aÈÓÅ»ê­ã]ܑ׿Xée&¯ÍøÖ}7†7šãæ3¡ø)¿Í§¢ýä·ù~}ä†&¿MøC¶„ƒÉq;‚Un›ã|~„éeƒtÛDD“‘Un› ŽO˜Þ˾“öÚ\Š“¡×&âh$ÅÈkŸ ­3Éks êí7L“Á.àaþ¥èµ‰èìõ Ó[“%·Mduû†éÍc)ÈÁn›ÇH‡2¹mÂqÊÈ´E|ˬß\rÜs¡Æn›±VC‹Ãô*XŽn›[µ“%¼kø¶HÀ›È¨¡CQÀÃ+-\ÞDzF5|…š+~§×fÅ"JÀ;Ž”o§7SD‘Ûf¤ûø¸mF„ ûaw©Ì©ñ·D½÷ÞN䲉ϋ,rÙ<·tô¤Ï朞LŸÍéàhûl"4ÊjáŽuwÆõÉg«®§M„ÅY-¤Ó&ë–¶¡Ó挧ýoIz1º_ŽÚ£Ï&Úÿ¨x¸ü&¤ÏæcqËx'–—]òÙœWúMNEí9ÞÎ>›î@Fé½÷3ãöFJ>éAJ©øÔªx4…é²i/«xH@¸>*Þ¬—ЇÖÓš]6ï+"‡\^»ˆ‡ñï‡Ë&´}\61Ö|r}¡ì²yí%ÏtÙ´—vFêí»Î;]6¯<¸\6WÂ)Py 좹AH³›~ºlnéˆ,—Íw²­/]6ß½v[–]“ÌG—Md¦ÕÍ´Œ‡3‘ 'ïÈëioKX2Þ5®ÿ¨‡%rËv¸˜w«7rÙ,7cqßÓ‡ƒQzÿ×ÿñßšV¹endstream endobj 6 0 obj 165285 endobj 4 0 obj <> /Contents 5 0 R >> endobj 3 0 obj << /Type /Pages /Kids [ 4 0 R ] /Count 1 >> endobj 1 0 obj <> endobj 7 0 obj <>endobj 9 0 obj <> endobj 10 0 obj <> endobj 8 0 obj <> endobj 11 0 obj <>stream 2020-03-05T16:36:04-06:00 2020-03-05T16:36:04-06:00 GL2PS 1.4.0, (C) 1999-2017 C. Geuzaine gl2ps_renderer figureOctave endstream endobj 2 0 obj <>endobj xref 0 12 0000000000 65535 f 0000165602 00000 n 0000167352 00000 n 0000165543 00000 n 0000165392 00000 n 0000000015 00000 n 0000165370 00000 n 0000165667 00000 n 0000165767 00000 n 0000165708 00000 n 0000165737 00000 n 0000165831 00000 n trailer << /Size 12 /Root 1 0 R /Info 2 0 R /ID [(\257\016m&3|WG./\003[N\326{U)(\257\016m&3|WG./\003[N\326{U)] >> startxref 167572 %%EOF blis-0.9.0/docs/graphs/sup/dgemm_rrr_zen_nt32.png000066400000000000000000005453061422157504600217250ustar00rootroot00000000000000‰PNG  IHDRTjûF¦Â &iCCPiccH‰••gP“YÇïó<é…@B‡PC‘*%€”Z(Ò«¨@èPElˆ¸+Šˆ4EE\•"kE ‹‚tƒ,ʺqQAYpß÷?¼ÿ™{ÏoþsæÞsÏùp ˆƒeÁË{bRºÀÛÉŽÌß(ŒŸ–ÂñôtßÕ»­Ä{ºßÏù®‘iü常¼rù)‚t ìeÖÌJOYá£ËLÿÂgWX°\à2ßXáèyìKο,ú’ãëÍ]~ )úÿ†ÿsïŠT8‚ôبÈl¦OrTzV˜ ’™¶Ò —Ëô$GÅ&D~Sðÿ•ü¥Gf§¯DnrÊ&AltL:ó5204_gñÆëK!FÿÏgE_½äzØs û¾zá•tî@úÑWOm¹¯”|:îð3™ÿz¨• €è@(U  t0–À8à|AØø $ȹ`(E`8ª@-hM œà<¸®ƒÛà.L‚—@Þ‚°¢A2¤é@F²† 7È ‚B¡h( Ê€r¡PT UAuPô tºÝ„¡‡Ð84ý }„˜ÓaXÖ‡Ù0v…}áõp4œ çÀùð^¸®‡OÂðø6< á—ð"Â@”]„p$‰BÈV¤)Gê‘V¤éCî!Bdù€Â h(&Je‰rFù¡ø¨TÔVT1ª uÕêEÝC£D¨Ïh2Z­ƒ¶@óÐèhtº]ŽnD·£¯¡‡Ñ“èw †aaÌ0Θ Lf3¦sÓ†¹ŒÄL`æ°X¬ Vk…õÀ†aÓ±ØJìIì%ìvûGÄ)áŒpޏ`\.WŽkÆ]Ä á¦p xq¼:ÞïÀo—àðÝø;øIüA‚À"X| q„„ B+áaŒð†H$ª͉^ÄXâvbññqœøD%i“¸¤Ri/é8é2é!é ™LÖ Û’ƒÉéä½ä&òUòSò{1š˜žO,Bl›XµX‡ØØ+ ž¢NáP6Pr(å”3”;”Yq¼¸†8WJ)Hq¤"¥öHµJ IÍKËIÛJGJJ·IK”aÊ8ÈÄËì—é”y"‹’Õ–õ’Í’="{MvVŽ.g)Ç—+”;-÷H–×–÷–ß,L¾_~NAQÁI!E¡RáªÂ¬"CÑV1N±Lñ¢âŒMÉZ)V©Lé’Ò ¦$“ÃL`V0{™"eyegå å:åå–ŠŸJžJ›ÊU‚*[5JµLµGU¤¦¤æ®–«Ö¢öH¯ÎVQ?¤Þ§>¯ÁÒÐØ­Ñ©1Í’fñX9¬Ö˜&YÓF3U³^ó¾F‹­¯uXë®6¬m¢£]­}GÖ1Õ‰Õ9¬3¸ ½Ê|UÒªúU£º$]Žn¦n‹î¸CÏM/O¯Sš~°þ~ý>ýÏ&   ©†.†y†Ý†iñªî¯&¯v\½mu×êׯ:Æ‘ÆGŒ˜ÐLÜMv›ô˜|253˜¶šÎ˜©™…šÕ˜²élOv1û†9ÚÜÎ|›ùyó¦é§-þ²ÔµŒ·l¶œ^ÃZ¹¦aÍ„•ŠU˜U•Кij}ÔZh£lfSoóÌVÕ6¶ÑvУʼnãœä¼²3°صÛÍs-¸[¸—í{'ûBûªƒŸC•ÃSGÇhÇG‘“‰Óf§ËÎhgWçýΣ<Ÿ×Ĺ˜¹lqéu%¹ú¸V¹>sÓv¸u»Ãî.îÜÇÖª¯MZÛé—ˆÿ2Â6¢,b&Ò*²4r*Ê*ª4j:Ú*ú@ôLŒMLyÌl,7¶*öuœs\mÜ|¼Güñø¥„€„¶D\bhâ¹$jR|Ro²brvò`ŠNJAŠ0Õ"õ`ªHà*hLƒÒÖ§u¥Ó—?Åþ ÍŒ]ã™Ö™Õ™ï³ü³ÎdKd'e÷oÒÞ´gÓTŽcÎO›Q›ù›{r•swäŽoál©Û m ßÚ³Mu[þ¶ÉíNÛOì ìˆßñ[žA^iÞÛ;»óò·çOìrÚÕR V (Ým¹»öÔ±? ìY½§rÏçˆÂ[EEåE‹Åüâ[?þXñãÒÞ¨½%¦%Göaö%íÙo³ÿD©DiNéÄ÷e̲²·7¼Yn\^{ˆp(ã°Â­¢«R­r_åbULÕpµ]u[|ÍžšùÇ‡ŽØi­U¨-ªýx4öèƒ:§ºŽzúòc˜c™Çž7ø7ôýÄþ©©Q¶±¨ñÓñ¤ãÂÞ'z›Ìšššå›KZà–Œ–™“!'ïþlÿsW«nk]£­è8•qêÅ/¡¿Œœv=Ýs†}¦õ¬úÙšvZ{aÔ±©CÔÓ)ì ê<çr®§Û²»ýW½_ŸW>_}AòBÉEÂÅü‹K—r.Í]N¹<{%úÊDÏÆžÇW¯Þïõê¸æzíÆuÇëWû8}—nXÝ8Óâæ¹[ì[·Mowô›ô·ÿfò[û€é@dz;]wÍïv®¼8d3tåžý½ë÷y÷o¯ñy02*|ñ`úaÂÃ×2-<Þ>†+|"þ¤ü©üÓúßµ~oš /ŒÛ÷?óyöx‚?ñò´?'󟓟—O)M5MMŸŸqœ¹ûb݋ɗ)/f þ”ø³æ•櫳ÙþÕ/ M¾¼^ú»øÌ›ãoßöÌyÎ=}—øna¾ð½ÌûØú>|œZÈZÄ.V|ÒúÔýÙõóØRâÒÒ?B,¾“sMT cHRMz&€„ú€èu0ê`:˜pœºQ<bKGDÿÿÿ ½§“ oFFsF×j`` pHYsNNÆÊ/¥tIMEä&>(Ê vpAg´¨“ÁQè€IDATxÚìÝ{|g}/þ“'Ž#y””8qT‡¹Jˈ@Â¥Ì;”›Ë¬ <{ÚÂ19?ÁN¡„ƒ[`t()NwLë”KAšb ÄE4DšhB Ib'6$K ‰sC¿?ž}fgW»Ò®´Ò®¤ÏûõÒËò^gwõìÌ<ßçûý®™žžžUuL³7€ˆˆˆˆˆˆˆˆˆˆˆ¨Õ1 BDDDDDDDDDDD4TˆˆˆˆˆˆˆˆˆˆˆˆæÀ€ ÑP!"""""""""""š*DDDDDDDDDDDDs`@…ˆˆˆˆˆˆˆˆˆˆˆh«2 â8<ÏköfPA†ð<¾ï/ø±‚ €ã8Í~I4O›+CÇ4ÇçòÂñ¸²Õ2Ã0DUïïy^Õëiép¬® ÝwV¯«ÍÅñÙZyÞ p_ºÒp¼¶–ùŽ×JûSž‡._—+×r—«2 âº.d‹ð}]]]Èf³H¥RH§Ó z¼ àºn³_ÍÇæògYz{{+ŽiŽÏå…ãqe«eã•ç¢D´”VE@Åu]tuuaÍš5H§ÓÃ0ºNF¾;::`Y,Ë*ùÂõ}©T kÖ¬Aoooô%žL&á8:::ÐÑÑÇq`Y:::ÐÕÕUA­ç¶s‘ßæÙ.¯õñ:::¢í(¿¬Òmj}ÌÙ^¯çyÙL ( &&&`Ƭ¯É÷ýè³’YmE¼]½÷£¥1ÛØ–×øœm 6j|Ö2^k}¼Ù^k-c¥Òk’ŸŸ¢(Ñ¿ªªÎø\¥øgʱÙ| ÕÆ"°zÆãbí+ç;ëWñý¥¦i0Mš¦Í¸çyPº®G·Õ4+Ç–÷µ=f£öµ¾Þ¥ÞwJÕÆ+Çjsp_ZÛc.õ¾t®óÎj¯‰ûÒ•óDs?ÞRïKùÏÕ³?å‡J·£ÅÁ}çÒï;k}½K½ï,W>9V—÷¥­»/ë¼³Úkâ¾tåâ<ÑÜ׌}éôôü牦§§«îO9O´gùø¦iN+ŠRrÿÙîGKo¶±9==½ìÆçlc°Qã³–ñ:×ãÕòZk+Õ^S&“‰>GUUKîSm|rl6ßBÆãlcqzº¾1¶œÇãbí+ç;³Ùì¬÷›mœòÉJ'ñÏ›÷K¿ï¬õõ.õ¾³\ùxåX]zÜ—¶î¾t®óÎj¯‰ûÒ•‹óDs?^3ö¥ò³™Ï<‘¼o¥ý)牖ŽË¹¯Yó·s“Õ8»âK~ù¾¥üIªª)ñÜòÛAß÷±fÍšè§RŒÊ·s®Ëç"ßÙ.«t›FPUÃÃÃÐu¶mÃ4Í’÷¸Úk*OV%ª9Ok+¯—9ÛýhiÍ66å9>gƒŸµŒ×F¨e¬”¿¦o¼®ëbll ¶mcbb¾ï—ÔŽ®6>96›k!ã±Çbù6ÖsÝl拵¯œÏx¬å~³í/ëyï8V—÷µY-ûÎÙp¬.=îKkÓ¬}é\çÕ^÷¥+ç‰æÖ¬}©|Üzç‰Ç™uÊy¢ÖÇq9·fÎßÎ5NVÛü튨TªY7Û‡!ëšN‹LžèǶíf¿¬A×õ®Ö/•òÏ-^WQÓ4är9d2™5g»-­¹Æ&ÀñÙLó+=ôTU-Ǻ®×4>96›k!ã‘cqñÍw|Ìu¿Ùö—ÕhšVñqëÀJqßÙÚ–zß9ŽÕ¥Ç}iëZ¬óN€ãs¹â›m>cåœsÎAÑg&ï?¨­6>96›k!ã‘cqñÍw|Ìu¿Ùö—ÕÈÓxƒÂ JûÒâá¾³µ-õ¾s6«KûÒÖµXçÇçrÅy¢Ö5ßñ*ïWmÊy¢ÖÇqÙÚãœt9Ëãš½‹Í4Mø¾®®®è V¨hšÃ0ÐÛÛ UUgD»TUE&“A2™Œî«ë:tDQضÞÞ^躽¿¦iÎy_UU‘N§¡ªj´!“ÉÌøR•/?³j÷£¥7ÛØ8>›m>cåå/9:Tò™jšVõ~r|nÞ¼™c³É29ß|ÇG=÷‹ï/çZfÛ6R©4Mƒïû°m{ÞiëTî;[ÛRî;9V[÷¥­k1Î;+áø\>8OÔºæ;^å„{¥ý)牖ŽËÖÖèsÒå>.ךǬx¾ïG5÷äJ†Q Q†ÐukÖ¬ÁáÇgÔ´ ‚Š¢Ô”ÊMõ©÷ýõ<Ùl###ð›i¡ce©Æ45ÞBÆ#ÇââhÕ}žü¼UUe‰’&ླõ,õ¾³ÞÇåX]:Ü—¶®V;Fåøl>ε®ù¾¿­6Ω~—­g©ÏI—ø\ñ*R¥7> C$“I CÓ4X–U±^ãRàA0kÃ$]×ëNmjôc.Æ6 {ç›îÕJib«]µ/Å•<>—Ãx߯^ÍÓÔ K5ÀñX¿ÅWœüi.î;þx‹õ˜ò~õZ¬Ï„cuéµú¾t¹Œ¥ÅxÌV;Fåøl>Î-ü1[mž¨ÕÆ9Õãrá¹XãRÞw9Üo±­š€J%ªª"—ËE5ÚTUÅððpS¶E6Pšm[›ý˜‹±ó1ßÈd+F4©º•<>[}¼/õXáØl}ÍÛFîó¨«ÍÛFŽ9šK«ŒÏVK‹ù˜óÙŽëÕ§UÆ*°<ÆV+ŒÕ…à8_8.›;.—úœt9ŒËUSò‹ˆˆˆˆˆˆˆˆˆˆˆh¾Žiöµ:TˆˆˆˆˆˆˆˆˆˆˆˆæÀ€ Ñ"ÇÔÔT³7ƒˆ*àø$j]ŸDDÔjP!""""ZDù|W_}5öíÛ×ìM!¢2ŸD­‹ã“ˆˆZ*DDDDD‹èÚk¯mö&QŸD­‹ã“ˆˆZÑqÍÞ""""¢•jppÝÝÝÍÞ "ª€ã“¨uq|Q«Zö•‹.º_|q³7cÁŽ9‚N8'œpB³7eÁ:„ÓN;­Ù›±d¯cÿþýؾ};ÞúÖ·6{“[Ê>ðÜrË-8çœsš½) ¶Rþ¦Wã÷Ìøø8n¿ýöfonËyñ‹_Œ .¸ Ù›±`GÅÑ£G±aÆfoÊ‚­”ï™Z?“ÉÉItttàóŸÿ|³7yQcï޽سgvìØQÓ}^øÂâ„NXö“H«qŸÓêjùLÆÇÇqôèQüíßþíŠ?¶­w|~å+_ÁÇ?þqœzê©Ø¼ys³7AVÓßôr1×gòØcaÿþý8zô(~ö³Ÿ5{s]½ãóÅ/~1¦§§qê©§.ë¿mÛ¶žZ>“C‡áàÁƒ8çœsðÕ¯~µÙ›Ür.½ôÒ–>®mõ}Érø^hõñ¾ó¶Ë> rüñÇc÷îÝÍÞŒD"‘@"‘hö¦,XÿŠøLj}ƒƒƒËþ¤j1¨ªŠ_þò—«êo¡Õ­Æï™þþþfojKšžž^Ó£££ÅÀÀ@³7eÁVÊ÷L­Ÿ‰¼ÝJ655…;vàºë®C[[[Í÷Ó4mEü-¬Æ}N««õ3Y ǶóŸ›7oÆ;ÞñîsZÈjüžY ǶóŸ\pÁŠø›æ±mëá±íÂuww·ôßB«ïK–Ã÷B«÷Å8¶]ö••r°ß×ׇöööfoFC´ò _¯£YÎ:ë,œþùÍÞŒ†X) üž!i¥ì;{zzÐÙÙÙìÍhˆ•ò7½’>“…rÝÝݘœœÄèè(&''1>>Žööö–^¥×(Üç´ž•ô™,ÔjŸü›n=+å3i„Õ<>WÒqÔJù›^IŸ UÖêû’åð7¸RÆ{=–}@eýúõÍÞ„†hõÁQ•r³R^G³¬[·'Ÿ|r³7£!VÊß¿gHZ)ûζ¶¶ºVþ·²•ò7½’>“F˜ššÂ®]»ù|7ß|3&''WÌç=îsZÏJúLa5Ï•òWÒßôJùLeµŽÏ•tµR>«•ô™Pe­¾/Yƒ+e¼×cÙTˆˆˆˆˆZMùJ­þþ~lß¾½eË ­&ŸD­‹ã“ˆˆZÝ1ÍÞ"""""""""""¢VÇ """"¢EÖʉV;ŽO¢ÖÅñIDD­†*DDDDDDDDDDDDs`@…ˆˆˆˆˆˆˆˆˆˆˆh ¨Í"""""""""""¢9°)=ÕIJ¬’ÿ«ª Ã0 (Jt½išPUµâýǪªÐuàû>\×(ŠÓ4£Ç""j5ÌP!""""""""¢šd³Yxžß÷áû>ÇAWW‚ ˆ®—¿Wâº.<Ï‹n›L&£ë<Ï+y,"¢Và """""""""ª™mÛQ† $“I8ŽÛ¶ëz˲022RòXétÙl¹\®Ù/“ˆhf¨ѼU+ï5™L¦iV¼Î²,tuuaÍš5H¥RÀ(Ït‘·ýÒ—¾˲`Y:::ÐÕÕÇqšývÑ2Æ """""""""ª™ïûÑïžçÁó<ŒŒŒÔý8¦i"•JÁ0 hšÃ0ªgd¯•‘‘(Še²Ø¶0 £2bñÛwtt ›ÍÂ4MLLLÀ÷}¤R©’.DDõ`@…ˆˆˆˆˆˆˆˆ¨EAÐô"Š¢@Ó´ª×Çû H2[¤¹\º®ÃóL×u˜¦ ×uP!¢ya@…ˆˆˆˆˆˆˆˆ¨EA0#X±ÔTU5 RÞCÅq$“I>|¸îç2 †aD¯=N#•JabbbÆí|ßGWWW”a’Édæ,7Vþ:E)ɰ!"ª*DDDDDDDDD-B×õe—=¡ªjÝ*žçÁ²,Œ•Ÿoö{C´êÌ66ã×s|-=ŽO"""""jEaΫ„–ªªð}F“xÏó*>–eYQ E×u†KE‰¶ýSâ™ñ3ßm]M8oK4»%ÏPÄÐÐzzzÏçÑÖֆ믿mmmÂàà zzz°oß>  ¯¯¯ÙïѪ0ÛØÀñIÔDŸDDDDDÔJÊ3Hdߓٮ/Ï$QU¹\–eÁq(ŠA*õG1M½½½èííÊvÉçÔ4 𦡷·7*&K}©ªŠt: UUA”C3qÞ–hnKPÉçóصköìÙƒîînâ uhhÛ·oÇàà ®»î:$ ŒcÛ¶mH$èììlöûD´¢Í56p|5 Ç'µ’ééé]¬˜¦ Ó4£ EQªönQU‡Žn«iZ”™cccÑu2Åó<¨ªŠ‘‘xž7ëã¯vœ·%ªÍ’–üÊçóH$Ñ €-[¶`rr£££hooG"‘tww£»»»ji"jœÙÆ&ŽO¢&âø$""""¢•Nö©%Ø!o¦”_Wí~ ¦TÇy[¢Ú,i@%‘H`÷îÝÑÿ§¦¦°wï^tvvb|||FD³½½}Κ|‡ÂàààR¾ ¢Èàà n¿ýöfoÆ‚Í66Ì{|Þ~ûíjöË£U(ŸÏcppGŽiö¦,ØbŒÏ#GŽ`pp¿Ô£££p]>úh³7…ˆˆˆˆV8f¤Ôn1çmÙs…šahhhQæm›Ò”öîÝ¥†õõõE+mãjI;餓¢è(ÑRK$Ø´iS³7£¡ÊÇ&€yÏM›6¡§§§Ù/‰V!¹ræ„Nhö¦4T£Æç 'œÀÔljšÎÎNtwwcíÚµÍÞ""""Zá4M+éíBµiô¼m{{{³_­B===‹2o»äM駦¦°cÇäóyìܹ3 †TXù|¾$ͬ’õë×3 BM“H$VÌ ïjc˜ÿøÜ´iÓœ·!Z mmmH$صkW³7¥!=>e@…¨:;;qÁ¬ˆ 2""""¢•„ó¶´’tww/J@eÞ*SSSÅøøx]÷»úê«ÑÙÙ ÏóJTww÷Œô¯ÉÉI®ž%Z"ÕÆ&ÀñIÔlŸDDDDDD´Ø8oK4·ye¨ F«~‰¶oߎk¯½×]wݬ‘É¡¡!LMMaË–-%«ú;;;‘H$¢&G‰DãããÈçóغuk³ß#¢o¶±ÉñIÔ\ŸDDDDDÔJ,Ë*ù¿ªª0 #joYLÓ„ªªïï8TUšÇû¾×uˆž'¦iVl8O‹‹ó¶Dµ©; ²wï^ EMŠvíÚÕÓ»úê«ñÝï~mmmï›Ïç‘ÏçÑßß_rùöíÛ100€ìر===Ø·oª>5Î\cÇ'Q“p|Q+Éf³Ð4- zxž˲066UU‘Íf¡ëzÕ€ŠëºÐ4 º®#›Í"›ÍÂ4Íè±²ÙlôX´t8oKT›º*£££èëë›Ñ;bûöí¸ùæ›±oß¾ªµñäà«F>n>ŸVÞÑâ›klŸDÍÂñIDDDDD­Æ¶í(Ã’É$Ç©»¼eY)y¬t:l6‹\.×ì—¹ªpÞ–¨6óXd%Qëáø$j]ŸDDDDDÔ,Ì&Éd2QÆJ9ß÷ÑÛÛ‹5kÖ •JÁ÷ýŠ×õööFeÄd°§«« QÉ2˲à8Ntÿ0 ‘L&†a³ßΖÅóN¢yd¨$ |èCšQ#ohhù|===Í~MDDDDD-a||“““hooŸµ× -=ŽO¢ÖµÚǧçy‚º®Ãq˜¦9ã_Ïó ª*‚ €è÷FÝÇó¼ªA % ÏóàyFFFê~­¦i"•JÁ0 hšÃ0ªg‚ @2™D.—ƒa°, ©T Q0$“É`ll Ùlétš¦E¯{ll,z ]ס(JôzQŠ, Cöo!¢YÕPÙ²e öíÛ‡mÛ¶¡³³“““Ðu“““¬GDDDDTpíµ×bttÈçóH$عsg³7‹ˆÀñIÔÊ8>E CQ(ŠMü—ÿ+{˜ÈÉù{£î£iÚ¬Ûèº.<Ï+¹l>™¹\º®G½SÒé4t]‡mÛ3¶Áu]èºÃ0 ¤¼˜ltŸÉdˆ,—x³{Û¶£×%×4MX–…  ªêœA$""`•¡¡¡¨ ýèèh”•’H$L!""""‚XY{óÍ7ã»ßý.ÚÚÚÏç¡ë:úúúVåJ[¢VÂñIÔº8>…x††ì-RþïlFÜg®€JyÇqL&qøðáº_¯aQ$¤Óé(ó$. ÃÙ+2¨†aÉöÈ÷Qy*e(ŠÃ0àºn”•þ-D4—º*ù|CCCسgúúúš½ýDDDDD-'ŸÏ£¯¯/Zp$ëLONN6{ÓˆV=ŽO¢ÖÅñ¹|ѵò<–eall¬äq2™ ’ÉdÍ!ƒ?²”™TKù.Yî –û"¢¹ÔÝ”Þ4Môôô`pp£££3~ˆˆˆˆˆV»-[¶```SSSÅàà º»»‘H$f½ßþýûÑßßßìͧUª¿¿7ÝtS³7cÑÍw|ÞtÓMlöæÓ*4>>Žþþ~ìß¿¿Ù›²èæ3>:„þþ~ 5{óW­0 £r\õPU¾ï—4†D¤ÒcÉà‡ Üxž‡T*ešÈÞ3õl“aQi0™%S¡¡! âá‡^Ò÷œˆš§î Çq¢Ô®]»f\ß}÷5û5µ„|>]»v!ŸÏcË–-sÞ~óæÍؽ{w³7›V©Ý»w¯ª€A½ãóŠ+®ÀÀÀ@³7›V¡îînìÞ½{UÜ럧v÷MPžA"ûžÌv}yÓzUU‘Ëå`YÇ¢(Q@dxxxÆsÊþ)]]]Ð4 ¾ïGÏ©iLÓDoootasTd0Æ÷ýºBÐ×ׇÎÎN.2'ZEê¨ ð ’ˆˆˆˆ¨rljj Û¶mCgg'ËæµŽO¢ÖÅñÙÚ¦§§t}<°bšfÔ¿@Ô8¾š\.Ó4£~*ñž*¶mÃ4ͨɼ¼®|{Ê;•‚7DDÕÔP‰Çää$ÚÛÛWUs0""""¢Ù ajj Û·o´µµ¡»»ù|¾Ù›F´êq|µ.ŽÏÕ«žìÙ.åA"¢F«»‡ vp/zÑ‹°mÛ6ô÷÷cÛ¶mÐuãããÍ~=DDDDD-AN ÀÔÔÆÇÇ£æºDÔ\ŸD­‹ã“ˆˆZYÝ*²)ØÀÀ¶nÝŠ¶¶¶¨¶åÕW_;ٯ‰ˆˆˆˆ¨©úúú°wïÞ¨Lɾ}û°uëV–+!jŸD­‹ã“ˆˆZ]Ý•½{÷¢¯¯¯dgÖÙÙ‰;wbtt£££H$Í~]DDDDDMµ{÷î¨Dngg'W×µŽO¢ÖÅñÙúljšÇÇ©ª ]×á8NIƒz"¢•¤î€Êää$ÚÚÚ*^Wír""""¢Õˆ}‰ZÇ'Qëâølm®ë" C(Š2㺠ÍfP!¢«î€J"‘À®]»°uëÖ’ÜÐÐòù’ÉäŒËºººÐÑÑ˲`Y|ß®K¥RX³f z{{áºnt¿d2 ÇqJîKDÔlug¨ÀÎ;Ñ×ׇÑÑQLNNbË–-Qƒz"""""""""Z¹d@$NUU„aÏó¢ËÂ0D2™D.—ƒ®ë°, Žã@×õèºL&ƒááaxž‡T*MÓ ª*<σªªCH&“Ðu½jf ­>Ùl†a@UÕ%{ÎyTQÏ’5-‰ˆˆˆˆˆˆˆˆÈà–]6@&~Ø…ëã1 €»Ÿ  <¡ÃîW~ûòçÑ Q…ëº%'5Ǧi0 Cl–mÃqœè1TUE&“èºÃ0JšÚÛ¶ EQ i4MkòCD­Äó|>_r»žžf½-¡Jcàø$jŸDDDDD´œ†d2‰0 ¡(JI‹aÈf³ð}š¦! CôööÂ¶íª«ÎiipÞvec«Qlj²FæKŽsEQ†! Ã(ÉDó}“2™LDQU®ëÂ÷}˜¦Z‚ €ëº°m;ê«bÛ6þ¾ÖPÉçó3&r ­­­®$#PÑeƒƒƒØ»woÉívïÞ]S€†ˆ£ÒØ8>‰ZÇ'µ‚d2Yñò‘‘Òza²JoooÔ´^’ýS’É$4MCQj.ÎÛ.©T ®ëbzzºärÏó ªj4Óé4LÓ¬X¯\6›…ªª5ݶ×u£`‡eYð†!LÓŒV’뺎5kÖD«æ3™ Ã@QóùJSËóÒÂqÞveð¢æâø$j]ŸDDDDDÔ ®ëF“°²ùüb’+Ü%UUg¬j·, ¦iÎZBÌó¼¨$R¥Ûù¾×uˆÉgÓ4µÃrÀóÎæ“åòd€Ä¶í¨ñ¼lä.o ¤OQQð@ÅÌy½ïûð<Ùl6 €ø¾_h&&ž;c»lÛ†®ë‚ W†aDå¼t]ŸÑ÷$Ïr¹F–èÒþ5¨¹äW[[¶lÙ‚;wb÷îÝQsúþþ~ .8u+ŸÏÏxŒ¶¶¶%yˆhvŸD­‹ã“ˆˆˆˆˆ–R†èíí- pX–…ÞÞÞ=)›ÍÂó¼¨/„ã8èêê*™–­çzœl6MʯK&“Ñÿ=Ï›ñ«Ï;›K3™ E‰ú GA]×aFÅ¿kÙûDþ˲]2ø"†žçÁqœ(kD ‚ P 8|x$º\>—|Û¶£ eü1*.=¨P=lÞ6n<€gž9yI>yõPP\Ùºu+n¾ùflÛ¶mÞ™*&kòMMMaïÞ½s6¹'¢ÅÇñIÔº8>‰ˆˆˆˆh)¥R)hš†‰‰ ض Û¶111MÓ¢^ ‹Å¶mŒŒŒ`ddcccQSëZÉ•ú™L¦âijeYŽ^×ÈÈ ÈúA¬V<ï\:7Üp¿úÕ‘èÿa"N#—ËÍÈ”RUcccQ&‰a%™(’®ëQÿ•J åã}UdF‰ ¾Èñ.xâ;AÔ%—ËU|²Œ˜ïû³4”oÌ{väHÎ=÷gxè¡ ÔT2ï€J\ww7¢FõóÑ×ׇD"mÛ¶¡¿¿¯~õ«±eË–šÝÑââø$j]ŸDDDDD´Td9 x/É¶í¨¯ƒeY°, èêêšôð}©T kÖ¬AoooIp#™LFÙ'3J}Å©uÎȺ®•Š¯ØŸM&“™Q®hµáyçⓠݯºêÛøØÇþ3º\6l¯”P% ´ÈñP)¨"U{œ8™ñ’L&£L©½ýbxž‡d2eÊT#›ÝW+™ç8¢ÊìïËÜ’#G:ðìïÛ _Öô˜ USittù|>,ãããQCnT©U¥†D;wîÄøø8&''ÑÙÙÉ('QTkÆñIÔ|ŸDDDDDÔL2 Qi‚TQhš†Ÿüä'‚iš˜˜˜ˆ‚'ªªF+åådìðð0<Ï‹VÁ«ª Ïó¢•÷A ™LF«êãeˆd¤‘‘‘º¶_öxÐ4 ®ë"“ÉD×›¦‰T*M`ËÆÞ« çm—žì…rÖYÅØXéåcñ æP) E–üš+˜¢ëz4ÆlÛF:.pÚi§!~%lÛž3ÐX)«¦ôùDé¯Ù6+•2™âmELâO}ÿý÷ãU?»'<ôFÏo\æK55g¨\{íµèïïG>Ÿ jç]}õÕD0eï޽رcÇ‚7¨»»‰D‚ƒ’¨q|µ.ŽO"""""j69yª(J4™*3BdŠëºPU5š¨•½âY,¶mGšø$°ëºQ9ñÖXßG–2 f<' &€e £l6‹ŽŽ$“ÉEí ³œð¼sñxž‡\.‡Ë/¿Çó=³0«©¬%+E’Ù(Š¢`xx¸ä¹ xúéN˜¦9#ÐRm[Eç±ÖDD€$“Y*s%ŠÉ!îyâ¶ñÊ‚ªªâä“לòþéà‰æ~¼…ª)Ce||7ß|sII¯½{÷¢½½×]wÚÚÚÐ××]בÏç9¨ˆˆˆˆˆˆˆˆˆæÃq€òþåY–UZ×FÓ€x.ß·‰3ŒÒeݵalY\×…¦ið<–e•”W’™4ÉòåõD dYVI_¢óÎ;kÖ¬™³GI%åAOË*ýºÐuÙlv^Û©("KDUE@C9ÊŇdµH2 bš"¨„¡ˆ÷f2âùäõ}± ï~÷ÝP”n+žìÂðB¼íåë‘Êc…N6›Å‘#Gô)Õ\ò«¯ªªð}F0Ïójz¢ù‚aFcª ¬_ÿ LOO—Yj%û"0!³Cê)Vm‹Çsœêâ=¯ôºl¶ˆ)ÝNq¹Ø¶Ò,ß/Þ> E|8üò—¿Ä»ß}7þþ~õ~@:Æ“O>)žë¿MÛ'Çü7¿ù{<øà üÈj ¨´··ctt4úÿÞ½{‰D"ºljj ãããhoooèQke·ºººÐÛÛ‹d2‰®®.èºM«ªŠt:d2‰ÞÞÞ’ž)ñ¬y½ nÌ%™LbÍš5X³f :::ÁŒIçømÖ¬Yƒd2 ×uaÆŒIeÃ0¢àªªÈår°,«äu¹®;¯‰m¢j‚ @GGG”ÿÛo@Ü#†ÅÀ„ªªQS\W©¥OPˆŒQ–lö翞l¶rR|­¶=³‘¼Üœ ã»ß=Ïóðþ÷ÆË_~ét O>¹) D=õÔSø©òS|߇eY‰ÊÌ¥R)ض]Pq‘‘1_ªªFÙcñ GyP0@Ñ4­b¿™¯ATTµr_) ‹Ù1"»dfF‹ë_§ãË"$K€>|_ûÚsñ¼ç…Èf/…iZ˜œü>î½·Ž3 0=ý¶?ö<üHûüÑÓøË“ñˆ×û»ß½ Að —4쳬) ÒÙى믿;vìÀÐЉˆÒ_ýýýèììÄu×]×° #""""Zîòù<òù<€Òìn"j>ŽO¢ÖÅñ¹<È^(³™ízUUëî±TXâ‹É÷}¸® ß÷áyÇÁÈÈHÕ¿ÿÛUTžé%Š¢D îeÀEAËû®Èm¨”-£ª@.'"qñ‰xÍâ_P‘e¼âCKÞ^×KK‚9ŽÈZ‘Ïqæ™÷"0ôo<†½{Ÿa†¢(èî¾=wý×]xsÏŸáÔS‹uî¹áe/;£‘gmèîî.I ’zzz°{÷nîàˆˆˆˆˆb144„žžäóy´µµáúë¯gßA¢ÀñIÔº8>—?fuÐj#¬—s'êË£( FFFL&aFÕ`Šm‹&í…ØGM|¿Ø“$ž)¦i"(áy(#äöŠ€Jù6ˆL•bðÃ4K ñÇg¨N‹ÛÛv1ˆ£ªâþ†Ql(ˆ²|ÀHÉcÆã9¦)SÓ€M›v"€o; Û~)àÑGÅ·¿}'ÆÆ>Œ±±1<ôЉx Oá/ÒÏÅÙ·Ž[Ìv¹ä’ ] ý¼knJŸÏçqíµ×¢¿¿;vìÀøø8шžÁ""""¢¢|>]»váúë¯ÇîÝ»áy¦¦¦044ÔìM#Zõ8>‰ZÇçÊ i{ŽÐª’Jͼ,d³Y¨ªŠ±±1ŒŒŒ@Ó4är¹¨ŸP%–U ÔJMÊù¾¸.$0kfXʦDñí,¾V8ÑuÑ/Åu‹èEFdÀÇó¼Ù0š|ç;¿Ä+_y®¹æF<ùä=øêW?†¯}í<ÿùŸÀ«_½_øÂK‘ÍŠÛÿÙŸŽŽŽÞè{fÆøhݳ8öÌKá?ZÚäþK_z}c?lÔPéïïÇèè(º»»‘ÏçqõÕWGé—DDDDDT”Ïç‘H$Jú nÙ²“““ÍÞ4¢U㓨uq|ÑrT©A»ëº0M™Lš¦EY[³e§HµTÂsœâï2`R‰i3DŠ_ú"8"¢82Ö¡(¥Ï”6–'¡iš¸Î÷ÅýM³Ôçy"Тª*LÓÄ{Þs º¿¢^ø î¾ûx\ýoðÝïvào|ßüæ7qß}÷á™göÂóŠÏ©(Àï<ÜBM0U~yÆ0MÀ|VüßuKƒ>TS@ettù|{öìÁÀÀöìÙƒööv® """"ª ‘H`÷îÝÑÿ§¦¦°wï^tvvÎz¿C‡app°Ù›O«Ôàà n¿ýöfoÆ¢›ïø¼ýöÛyLM‘Ïç188ˆC‡5{SÝ|Æç‘#G088ˆÑÑÑfo>­B£££p]>úh³7…š¨R¯‘ æ]úÎuçî£ïaR­4—dYÀðð\ÍîÕ赌ŒT.9V-@!³R§Ø´ÞqÄcÉíÒu™ý"Ê Y–è-<ÏÑ#¿Â3Ï\ˆ?û³ ð‹_ìÅUW]…3ÎØ/ùøÊW>Šééb)10 †‘ƒçOþö2»ál(  ~½˜)ãû@GÇ‘y}³©9C%‘H”ԫܲeKÃ7†ˆˆˆˆh¥Ù»w/¶mÛ†D"¾¾¾Yo{ÒI'±œ.5M"‘À¦M›š½Kªžñ¹iÓ&ôôô4{“ijooG"‘ÀI'ÔìMYRµŽÏN8‰DbΠ(ÑbèììDww7Ö®]ÛìM¡& ‚™%·<σ>[”cªZ9ã$ŠY#ñ^²DW5ž'ú²”?æ7¿ù62è¡E·õ}|‰—«à‰?ž¦‰LÏ·-ï+#_Óþý@&“Á<Ïó¢þ2gu1N<ñGøáOÇ+_y!.¾ø,(Jià(NÓD€Çó€Î“;ñ’§^"®°Äë±íÊ™CPs@…ˆˆˆˆˆj755…þþ~ bçÎØ¹sçœ÷Y¿~=*Ô4«) 2Ÿñ¹iÓ¦’2DDKEö®]¿~}³7eIÔ;>PYz–eÁ)¯TÍfK®³,+j€-…a˲ «Ôg^¿œtvvâ‚ .ÀñÇßìM¡âyÞ¼³S CdvT.#Vz¹ÌŒ ÃÊ‘›Rt9xp°ôòxƒûtºôöñ’_¹\ñqu]ÜG–SUàU¯º;wÞÝ^T¾þõ_PñwwnÔKÆó<\yåF¼êUaròù¸è¢‹¢Ç­ö6ªªxÝa\xé…8îüã o Od³ˆíh|ö5*DDDDD‹àꫯFgg'<Ïc„¨Åp|µ.ŽÏÖ—ÍfaU¨ý,ËŠúÈÛÆ&a"™L" Chš6ãz¢•Àq˜õv–/Dð}‘U†Å¬E)Tl[3ʳHd³zUø&=öØspäHG¬ÿJ1¤RßGÔ^¼Æb &ŠAßÞñŽwàÛß>Ïþ$üXK&<ùd‚øþ÷O zÊd2è:𕯴!—+nl»z)3M&& ¦ ^[¸Â†L¶¦÷ß¿¹áŸïqµÞpß¾}èïïþ/Ò—Ü.^ë’ˆˆˆˆh5ÂÔÔ¶lÙRRÓ½³³“+h‰šŒã“¨uq|.ªªÂu]†]æºî¬«òe0EÓ4ä*5h Z¶üèo?A0g¹/Ë*ÍøˆÉY6+.^ L׋٠٬è{Rþ˜òþº^,&¯ÿÅ/N.yìK/ÐVRÆ«ÒóÇ÷<à ox‰ÄZ¨ª`d³Àç>÷nü¿ÿ÷)¼ño„ïÿ8zo~üã{qÞyOxAô<åß©”x-µVK `$@fÙ8Y*™Ê½m¡¦ •öööµb¹3#""""ª,ŸÏ#ŸÏ£¿¿¿ä‡ ­‰šã“¨uq|.†aÀ+«T`‰c0…V*1<\sÍA";¥Ú8ˆ‹g{Äiš8ÎÌž'2Dzô(|-|º.¶{ýú§±ÿ|ãoÃÎ/ Æ¿ëºøÔ§ŽÇ>pjô:abHfï¹a ™:†œ}öþÆ k×>Ž0·ÿå/‘#½°¬âóÊï Un½õV =Ãx>4MƒªÿñGpÑE¿Æ#\mû©§ ;ö‚\×…ªªð}Ùl¹ÜØŒ@PÜl}S*I&ðQ@9!vaX|/E@¥±=k.ù%åóyŒŽŽF%¿:;;±uëV´µµ5tȈˆˆˆˆˆˆˆVÓ,íu Å'W«M8ÆïWÜîœÏS¢(Ðu=ÊJ™-;%N#“ÉD ëçÛ[‚¨Õ¤Ói¸®‹ ÞÀCþ91>f†bìùþ̲T®+®“ÁM9eB39ŒdÀ(–‹7¡— ãu½RVŒÏ·ÿþ÷oÁùç¿kׯ•÷ C £ã6¼ñÝP%VÖ¬Šr2>÷¹§<ª =ú<äY&“çyÈd20MAPìÓª ¨gÚ)… 4Ù<` êjJ?88]×188ˆññqŒãÚk¯Å«_ýjìÚµ«®'žššŠ‚2qå"ZZÕÆ&ÀñIÔlŸDDDDDÔ*t]²Qf ¨d2d2är9X–Å&ôËçmç†!<ÏÃáÇqùåS8zôD¸®;gï Øà]Oʯ«ö™"{§Ø6¢Þ%€€”7¦‹1~ñ‹“qÅÇ# EVÜygGIï’ ÛLÏó²Ù,übíÚóñÖ·> ˲`Yºº:Jú¢hšÃ0 ( TU‚?ÕÞ¦\®¾Þ'™ < @¾ €¹+®-HÍ•ÁÁA açθãŽ;°{÷nìÞ½wÜqLÓÄàà`]AÇqfÔÀ¶mÛ°k×.lÛ¶52‰š ÒØ8>‰ZÇ'µ ™™/÷U‰¼Ü0 躎t:ÝìM§9pÞvnñ âøøéøÎwÎB6›­šåû¥eø4MSʇC‰ˆˆˆˆ¨ÕȲ_étº¦&ÜËå¢ÕíÔz8o[»xðdãÆµ8ÿüó122µ,"J 2ÛDö(ª4lÊ{žÈØ„ç‰LU-½My?¥Ùâ•–%n{ì±…ç?ÿóxÇ;ÞÇ)íá2>þ­èõuuuÁ4=œ|ò£««çœsEmÛQÆ lÞÜÛ¶£ì•’÷Àš¹þª (ëË.t,b"\M=TFGG‘H$ÐÝÝ]õ6Û·oÇàà`tÛjzzzÐÙÙ9cÀŽŽ¢½½=ºoww7º»»1:::#ˆCDWmlŸDÍÆñIDDDDD­HTìÙ:ØÇ(Š‚\.‡d2•FJÊeö±Ç¬¥©75çmkãû>t]‡ªªQ£÷5k: ª3n«ªÅ ˆŒ3ø¾ØöÌ]‡—Ï:QUq_@ddSùøõ²¯Ši–_t½|ùío_—¿ü0€ÍžøË¿ü ^÷º·A×u„aÃ0 ª*üq¼á Oazzz{³%ÔxìĶí™:>€^º5TF«ÙÈ—¬‹] #jL¿jÊP™œœ¬éÁf ¤HÝÝÝH$hoo/¹|||%—µ··ÏéÜ¿?úûûï"šE?nºé¦foFCT›ÀüÇçM7Ý„ÁÁÁf¿4Z…ÆÇÇÑßßC‡5{S¢ÑãóСCèïï_õ)ÚÔCCCÄÃ?ÜìM!"""¢y˜žžŽ~7MÓÓÓQIŸò`ÈôôôŒžº®G÷™žžžñÃ`Jó,Ö¼íøøx³_ZC9Žý]Ç[ɾ(qÙl1ÓDÞVD€™=SâñEÙ3Eþ.‡’ë'€¸\6ŠïîþHìþ¹’Ç·màÎ;ࡇ~„è½³'œð-¬[waâСâg<åÆ×!—ÛÇÁŒ,UâCV­T³«¬¨•®û¶4‚¶ ¥)&€PdU-ƼmM•öööš‚*£££óÞJ_>P+Ù¼y3vïÞÝð7†¨»wïÆW\ÑìÍXtóŸW\qš½ù´ uwwc÷îÝ8í´Óš½)‹n>ãó´ÓNÃîÝ»WåJ"j¾¾¾> àÔSOmö¦Q :o;[Õ£åÈó¼(KCQD°#—+ ”ˆÛ2+E’Á‘ò€J\yi¯0wì±SxÑ‹€¢©T Š¢ ­m²YôI$®Ä­·Þ ß÷á8R)¹ÜìßÿlØ0‚þ§û‘H¬ÅÆŸÆe—]†‹/¾xFTnk1°3K“–éºx¿&Di@Åà‹2o[S@eË–-Ÿ5`288ˆÎÎΚ²T*©´êv5×á#j%ŸD­‹ã“ˆˆˆˆˆˆÏ;‹|ߟÑdÝ4EÀÃóJ$ª*²BLSüT‹Eij\âÕód@%•­(â1ï¿¿ ŸûÜãüóàøãï ½½½¸é¦~ ÆÏþžÅÔÔ÷†!4MÃ'?ù¬]»Š¢À|\GÛÃm0U¶mãÿñ‘Éd*nŸaÌìÝR3@Y¯ù:ŽEí¡RS@¥³³Û·ošMMME×MMMapp»víZÐJôîîîqrr²¦h'-.ŽOZ.ü‘‹Xy‘Šþ¿’q|Ñbâyg‘ëº%Y¾_½|•ç‰`‰ãˆß?ñàJ¼¬—xüâïš&‚¾_ fA€ŽŽ;±~ýz\vÙ:\sÍ£r_†a “Éà ox ögÆÇ>Ö†OúÃð}AàU¯jÃCõˆm{JÁרé5{ž(]6¯ä”ˆ&ñ+hz¦¦€ Rdúúúà8^ô¢A×u¼èE/‹^ô"ìÝ»×]w¶lÙ2ï I$˜œœŒ²`ÆÇÇ‘Ïç±uëÖf¿GD«Ç'µ¢0 ‘L&aY‚ €çyèííE2™„çyÈd2 IEmuŸDD5 ±¢N䈈ˆˆ–Êj=ïL§ÓÑ æ!âå¾âLS”±Šg˜A1 ˆRWa(‚+2ˆRžùáû,Dž'î_/úË_>7îC:†ã8ð}™L¾ïÃ0 œþÆ’òb™L¦¤DÙÁƒ›ð[üÏœüŒÈ ™ƒªŠmŸ×K€ŠEm_‘Žš^Û|WÏ`š&FGG±oß>b@Í·ÌW¥Çß±czzz°oß>  ­­mq^9Õ…ã“ZA†Ã¾ïÃó¡¡¡šË~Uj$ß×ׇD"|>ÎÎÎU™6FÔl•Æ&ÀñI͆!Ò…#Ïó ª*TU…mÛ¢ö§<*®Y)8>‰ˆÊø'P€˜€ q•CqUœ<ïí*ü+W­ù+s`€…ˆˆˆœ·нRt]‡ªªð<`ÏžSqÖY ß/fkxžø‰g¦”³ Ç©Š"²' Ù¬xŒééÂ<[d½ø¾¸¢¦iBÓ4xž‡t:ééi„¡HÿU:f ¦À‘#)¼ðÔcpQÛYâXysšw";e‘²EćUxüøgBœ\Úø§«; RM>Ÿ_p«b@-WŸÔ,–eAUUA€Ã‡7{sZÇ'-;Aág¾A @ ÅÕgaáñ’(Öj–M0]OµÂe€^c'¬ÌX!"""šÕJ9ï ¤˜m=¦ã8Q¯EQððÃ÷ãá‡7cíÚÎR¾*^šKÞN` £ôz@\.΀օˆÏ|æÜvÛ'pÓM#¸õÖë1<< ]×£êñE¦@1XS-òœç<Ÿ<Å…I5ÈdæÙHÞ0Œâñú|ÛχhY„€JÍ=Tˆˆˆ–’çyèêêBGGÀ¶m 7{³ˆˆh!dF ‚Vá_³×U!‚Vì2"¢X•&Ï' LQ ?òÄYp8v™lÈžÓ-ükŠ ð·ìr""""Z‚%=FÊù¾ß÷£@…ÈP ðä“=% ä+‰1L³´÷ˆü½ü1LS,ÂPO ÷¿ó~$“I„aˆö!ŸÎ;ïø¨¬—¸Ÿ9ëvT €hàÈ~ô™ÚÞ³xVM݈c÷ì<ï? Ås€¸EšBb@…ˆˆZN°, ÃÃÃ8|øðªë‰BD´"%dùØ‹$Jƒ*AìÿVáö^ì²âÄÉ0Q¸L‹=nÜ\'ò~ÄÉž àÈþ+òäOn§V¸m"Kf1KÑ’éêêB*•* \(Š‚Ñу¸ôÒ» i3³LââY/ñR_¾/{ Ì Lär"˜ây€{€ pÆ·ÏÀÙSg#™Lbxx§žº€îÔÊqf¹rcáß,Jz¶,šÅlLŸ…X`UÎÎýÙ¹ º†•ü"""š¯T*EQàº.Lӄ뺰m;ªÿIDD+Ä0Š).D0D…X'(ü_–ì’Áâ$¬ "ÅD]e æ${©Ø…ç Û¡¢X2ÀB1ÛÅ,ÜN®¶+/&K5¬ÜÖ^DDDD+Šã8Ð4-êbY2«DÃÁƒ.r9—]VzU-mÔ>£Á>>çí‰Ä¾#DD´œ¤Ói„aMÓàû>,Ë‚çy0 ¹\J¡Ûl5@‰ˆ¨…ÉÉò*²ïIˆbð˜™Ñ!3U‘ñ!OêFP\Í&/Ó°ø«èâdi±j\ˆŠÌÀ ‚A!DðÈ-¼6¿°Ý28Ó"d£T"""¢Õ¢¼±|‚š¦Á²DÀ$DàŶ5œ}v1È ø~éÿ5MÜG–øÙ*ßúÖÔ”‹ó}Qì_Þw¿æ÷8묳€/¯¯–ÕRa©Tå@ŒªÚsåcqË×ÆÏ 4,^cúJ•Ð ÏsÜ£-ÒUÓ£mݺ===èîî^„WKDD+™ïûH¥R0 #:pð<ÉduÕÿ$"¢æ Ø(^ˆàÁJW½Íµ.¾ˆ¬Òn¢Õ&ÿeÀEfÒH D %Þ‡Ež°:±Ëd±EäyâäYUE=ít–U,?qÿý›ÁurDDD´’Ì<)r]†a ı’ ¨”/:©”ùŸÖ0 qÿò¬•o}ë(²eMÙ=σã8°mwÞyccãÊ3·à¤{¿‚¼ãÀS {U3Ìøb! 3:5’,ó+Ÿk1Jâê¨z,ýÓÿ§>zjCŸ®¦¦ôŽã`pp°ä²ÁÁAäóù¿z""Z Â0„eYp]étÃÃÃ%«0t]ÇØØƒ)DD+<á4Q ¬ CZ-ÒHñÌ›r²TÙpÙ H‘%̪ÍD]Wü„aaEe¡>w]]ÅzÝñZÙ¾ôöŠÕ‰Ùlé ÊÇŠŠ“mE•¯}í5x´Á«øˆˆˆˆZ‰ªÅK¾ïC×u8Ž8N*Ïhñ¼ÒÇ*Ïñ}´ˆ_žÍfá—55ñ<º®Ãu]<ïy8rd à]ïz—˜/ ° ³N¹ôÆ~_àóÔLö%\B?{ÉÏpôŒ£ }Ìy)ïÚµ ‰DKû.QKò<^á¨BX–UU+öCa"¢&<‘Z¨¬Uˈ¿?2ãÞ5€ò*@ëA1À2 dÿ¡xÂïy@˜²¿Œ§çIq²®ª"¨’É”®¨”µÁƒ X»;õç€Ñ (…ž5vaEŸ,qå•7àä“»šý.-ÏÇMª*~×u””ûJ&E&/P ºÄ*òxK>–®—/&&ÄqX™½3‰ˆˆhå2Mqœ&KwíÙs¶mó2³ ååm’I`¤p¬«iÅc»Zd³Yض ×uá8NÅ`Š<Å`ƒŽÅ+ÇßvâX°Ñªi<ûª4‚Tˆˆ¨õAPÒó$ èƨa4º£µ$âäËE1}?…Æžµ¨ø*D,qœbyBN‹Ûe2â:¹úqlLœxËŠ\‡`YÅ’’®Ðýû€öjÀøçØ•ÄIv¡4ÃÈ õ<ˆ“mÀÄçÓ Q‚Í)^í±‡Qº2°PÖbò”Éf¿ÕDDDD‹Êqı›ªû÷Oá–[òøÊW>  xL'3Tä±[œ®‹Kn–ò¶ŠÜ|óÓðýŸÁ÷}8Žƒ‘‘Aõ‰¦þbX¼R\åÇïY,Î1}y Ã@ãƒDÄ{´Dkzk¨äóùé÷îÝ‹ÑÑÑ’Ë–fˉˆhÉX–Çq011EQày\×…aUWU‘055…ÉÉÉåÕ{0 q²#Óò³îÙÂe²á¼‹b̼ž©%…a±Tƒì_’N‹“iÙ^ÓÄ*EÇAYÂ0ŠM+]¹Xi—9Ûnt¤<ã'~2¯ˆÿW¬–`¢XºACñ³Œc+3Ët|­ŸD´˜Ž}½½§hÃ{ßÛ]nÛÅã@ÏÇrŠRz̦ë"˜"ûÕ)²#4 سgŽã`xx¾ïG?ÕæQ4 Тxܦ`ñš¸—5dÃøF#–¬ÊÅYËx]nM•ÎÎNtvvb||<º,‘H ŸÏ7{û‰ˆh‘ø¾ ày|߇išH§ÓQVŠªªÈdVÐìÑ"q‘?¿lÉQDÄ/üÛ…b³Gµp½V¸NÁ’5l¹ê(6s—ÁÙ\Ô÷Å ²‚׿þùÐõ—ßÁ€XL#+ž'Žë]Ozÿý·ã´ÓæÑØc©Ž±Ë':D6z#›òchÅ2]Ë{¨Q$™LB×uôöö"—ËÁ,›9ª§WJŠÀzúÒû¾H™­§Š˜lüËÊcDÔjzzzÐÙÙÙºYÝ!Š'2ò„*(ûÿJ›b.3Ùl1h"ûd³bŸ11!n“É”öGJëa›« ?ÌjÔòã“VY>PUÅwÖÄD1¸«ª¢Vÿÿñ‹š½™K‚㓈Ûää×ðOÿôd³i\tÑ+à8Å9Û..² q¬˜ÍV^D£(ÅE9qa" Ãs*5± ŽÁ¥\ýQ“J¥¸]„$Då~):€táºF,N2±¤Mé©çƃƒƒ¸öÚk£ßÏ=÷Ü’½žY3""jÙl]]]QO”ééé;þzWÅù¾81¬‡ ÂÔC×g6ˆ#"jÝÝÝH$hoo¯ù>=öØŒ… •Fqå™q’“Š]ŸB±Ù<°¬ÊxÉ:×®+&-K\ÖÛ+ö-²IüÈÈÌý³L„ÑÑQ8p Ù›±$æ3>8PR›h.Ù¬ø>*çºâ{) E&Y2&“)–”‹†T¸ä’?à/8„?üá‘f¿¤%QïøõsÈÐÇ—øÍ#"Z¿ÿýï1::ŠD"±8O¯Uœ…XýVÞè¼…É2²÷‰i©T±q¼®‹U…†Qœ”,רsÛ•h5TæãÀØ·oº»»›½)Ô|_nãÇÇÙBÀZ–ìÊfÅ÷\ٜ͊Ëu]|wâ{LþâñdWNæuwÂüe|ýë¿köËnI2 ’H$ØÀž–\>ŸÇøø8ÚÚÚš½)T£l6‹ÎÎ{£ÿW+«†µ7Þ|óÓþ;¸nªªFs,óÊN©&ÄÒ§–¥È™0!²q빂ü÷+_‰îsÏmèC×PÇÐÐöìÙ3ãà±³³hooLJ>ô!ìÙ³gÞ“Ïçg¬(èééá—Q àø\Y4í0’ÉOÀó<ض=g†aÔŸ9¢(Åæ¾µN^É^(õÜGÞ¯¼\ËjÂñI´rœvÚi‹Û|7‡b†Š\×…ªªu•KŸÓR–Ÿ5 ²JÀ 0{óyY‚x¡¯QGÕÌúÉSNiøÛTS@åæ›oF"‘˜u%ÎöíÛá8ÆÇÇç½bgpp{÷î-¹l÷îÝ‹·BˆjÆñÙº\·¶’Wžç!xž‡;ï†ei0M³æóõ- ‹êê£"kÜëz}aòÄvµÖ¹çø$¢še!NŽ<O:4ƒ+M Lû¾˜˜”¥äe6+Vl»n±Žï—öÎbð„ˆj%³FäDš,˜Nccâ»FFTµØ«O~÷È,”\N<Žl\ìyÅÒ‚q2»Òqêj] DDËÓr<ï”Ç–€œ7ð iÚŒï_Ï+{ÖSiC×O<ŠK.¹ž÷e¢Ê‚*åýaem5.Ä9ÁR̯dP¹ôX½,é°y7¥ïëëÃÔÔTÉe˜œœœ÷ÆLMMµü@$Z­8>[—eU¨AEQ†!’…â͆aÀ0  ëF]Y 2s¤ñ,µÒõúïS-Ewµàø$¢šÈïp" ?)+oF¿„\·˜•hÛÅ`J.'¾Û‡‡K'#Ù7‹ˆê%ƒ$2@"KnÉlê\NS‚@Ü®R­üÙîØ6ˆˆV¼åxÞ)3O‚@|·A]ב͖~¯ËùÇû„Z„a˲pÁœsÎáÐ!Ñ“eÁʛ҇ýA}œ^mßeBôU\Š€ŠZøYh–J£šÛר¦¦ôííí3%%™(SSS nÐ7::Êz—´h<ÏCX˜ îۈèêÁñ¹4êmâO%Ïóàº.’É$’É$Òé44Mƒ®ë°mŠRÿL”ªŠwõTdíèz¦Y\íW϶­ö•ÉŸDTÅ“–xƒHâ$$À¢Õ0–ån ½!aYÅþ–%.“}ä>(–ú""ªÄ²D¤«Küë8¥“gɤøqœâ1£ Òjš8î)f¬È’‚DD4Ór<ï”Õ,DÀÜ2TÊÅç.æ:ö ÃŽãÀ÷}¨ªŠ±1W^y~c‚)•hl£xɪr¹Eã8Ðu¾ï—S‚ €išp]·b ^oooÔS"›ÍBQ躕E²b½|ðA=ztYEççc¾ãóöÛoÇÐÐkM×ÁqæW¶Jft8Žýí‹à‰‚l6‹ááá·wœÚj‚År_ÕüV"*õ¬$v@ß ¤?Lüº¶ûÈÉ6E)ö^Éçó‘#Gê3—™ùŒÏ#GŽ`pp‰DbÅQë…ëºËªÖòBíÞ½»Ù›P¤@œ”%Œ.S!V¼Y+ÕÀ%"ÃP”ZßÏ2ëDN±ß‹ï˜BK©¥Æ'E|_|WÄ¿|_M$y¬)˹¤ÓâûD.6*oÜÆ­öE:­†ã“¨u,tÞ¶¯¯¯)ÁÏÇŸ® \sÍ—p÷Ý#P*”ê0 ±OI&ç.uîyǪª3æZ¢üXX…64²1ý\"ȱЗ§aîs â$ÒÌœzTYü;44„Ûo¿½áó5T:;;±}ûvìØ±Û·o/²aýÐЮ»îºyoH>ŸG"‘ÀöíÛ±{÷nŒŽŽbÇŽèììœõEŸtÒIœ ¢hE¾ïûQ@EMTU…mÛÐ4 Žã ‚(Pâ8E‰îãº.EA:Ž[þddÉd2ê9¡i®ºê*¼á ohöË_tóŸ›6mBOOO³7Yñýú‚€8¼á†ð¼ÏÀó<ŒŒ” ”7œŸO¶‰¼m½Ù&ª ôöŠ 5»P­½1½|¿äêgÙ•‰D¾¿TK*šg>ãó„N@"‘Xv«‹heYοýío›½)«ÌJ)O‰—'m,8CÅu‹Y(rÅ·¦‰ïh¹@,¾PŒ+Á‰(–ãÒ4q<'KtÉcAÏ+f˜È&ïò;FF2™â#DDµÐyÛööö¦m»iÿþï·á¢‹^U1˜"Õ’íû>‚ ÀX]“ur1³ü•‰ÆTTÌ ÜÄÉýèBKy…ǘë˜ß€(û5[ûÙT™«êééÁm·Ý¶ð÷«LÍ=TÐÞÞÇq°k×®’ë:;;\C¯»»»dõA"‘ÀÖ­[1:::ëã®_¿ž•U$¸®‹0 £¬“0 ¡i4MC.—‹$•²OLÓD†‚ °¨ªW&&&¢ýòþªª"™LÂó©©©’ÇZM¥ ¨”뺂™L¾ïG™$²Ö¡çyÈårPUµâÙl_nŠ¢D)y™Xžw¼Öa¦,ÿ[Ó4ø¾?ãòL&ƒ³Ï>»Ùo×¢ãøœŸd²X£¹V²LA-R©.»ì½¸ä’WcÍ ™Lm;u¹ª/™¬Üp³Ú}â«ëÍ ©ù=8`#`< doÌâÀa–ûÛ/´+x@ö³>q ±ˆ FZ Ç'Õl¾+¾æ ÷)†QgF"­X2IXUÅÄ– Œˆµâ:Ûeºl»¸ˆFþ;W¹""ZZËé¼Ó²Ä<„ç‰ÀaèøÎwÚqÇâ˜5™¬|ÜZmQ§ ¤(вø•Ù:¹˜=³¤V!æîY"³Xòœõ”´× Ï%KÕT±dPz®#›4.‚º*ÒbDGGG±k×.ìÙ³mmm˜ššÂÞ½{±}ûöEyáÔº²ÙlTº+›ÍBUÕè‹kQSêæT˜åV¯|å+ñàƒ6ó-[tŸóWkÙª¸Ù²2|ß©éºÃxðýŽº·M6g«%8âyÅ&µ– 3ûå§@¨ŠÕ†#5ÔÂ4ß (=€r`n°@ bF•cë`äJ6àz€¡jb%Å ê~[–ŽO"ª™ŠÆ• @±—¦‰}×|z€Ñò&K®ú~ñ8ÑóÄd–¢3 £˜ñœÉ&Õ²NL!"j-Ëå¼SÎWxžøýÀw¸˜˜°ÑÛ[ÜÿÔS\6¡—ŒÅnøWíxÝ@m™%dC9æ[úË8©õ<Á€ôx¨?ˆS>·µˆ«3æPY }}}ǶmÛÐÙÙ‰}ûö¡¯¯Í¬W(ÙÛDö$‘å´âAÙPÛqŒŒŒDMå›Au¼ï}¯Â÷¾W:Aþ’—¼gœqF³ßÒEÅñ9?APÿ÷wˆ•z2ø ËÚÅKÝe2™¨—O¼žt½êÍ6‘5ðãÛ7'·Ú½@x¿(ë!vÂUœ/Æ•€fnuÀ°!V証²úé⯆!J…e2à•?xeýoÌ2ÃñID%<ˆ“" -ŸlË}ÕI–pL&KKF:ŽhòÉ^D+›< “ç@Ž#ŽY3q\(KtY–8¶4M±êW–ôªt,,/[¤…£DDÔ`Ëá¼Sî¯ä"Ÿýè(¾ûÝ]Ø»WT©ÑõbßÚZæ4$O¤¹Dó—Z³v^:D£øFe©ÔJ…8¯ÃügÕÓÈ ˜©Rk‰³%îËØ2عs'ÆÇÇ199‰ÎÎN6Ë]!ä„°˜üõà8|ßzŸÄƒ)¾ïcll aF´å¿sõ…XL"/Äå— Ë“« ÇgýELîÏg¢I”å ÐÛÛ MÓ ë:t]G&“) r¥Ÿ|®ZJÈûèºÈ©É ¨‰ãð'€òÌ^Žë(^ÀôïzÀ8 bÇXe ù÷öFñ»Ì 1 ¢Æh…å$š´!ÚAËÚÛ™ ø¯þÿÂU¸jAŸãrÀñID‘âûÒ„XI&K;¦ ÿ¯ãäË÷ÅþB®ð)6œ·íbŸ,Z^*Õþ–ÇæðÅ/~‘}¶¨D6+þ•+z}¿8)%3NL³d/0Ó„ˆhåhåóNì—ó'žxßùÎxõ«Ÿ@D?ñSëâÒt: @”ü—¿›‹–=[pÀ€¨Æ¡ca™ç7dc5ÔTXƒr$Q)®ù’¥Æ²…çž‹Uض¸ZëéÏCKT°õ á8t]‡ªªH§Óð<Š¢@Ó4˜¦ ]בJ¥Éd¢/¶EO™[UU±qãµQ3Äz{H¬«y|ÊœõöCñ¼Úo/c¦ üíß~##9är¹YÇF< â8µTt]ܯæã€#.p10üŸ…ËB½;­J'Ë÷Ø @´?/GrºPµÉ˜qbñò’fp:€Ï{€â§{À&Eœ­Ë3öÂídéˆÕXw{5O"Š‘iõ@éÉG€šV‡…¡Ыj1è.÷ò;v5µ:¹Z2[˜ùVÙlQ¦k6›…išp]€X´$Ñåÿà /löË¡EâxP׺niy.Ë*–óSqŒ:6V<¾Š/.“÷Q”b`""Z¹Zõ¼3 ÅþJÓÄ\ÂÑ£Y¬]û|õ«ï*¹ª¢P6}öÇ ‚¾ïCUÕh‘¸m/QD¥à@ô ‚ æß Þq€/f>57X4!æqÒ†—æm@"ˆbî ”'ÀñJ'¹äÉË]w5|ÓZ. BËÌ,1MŽãD%»<ÏC†PcccP¥de½l ¿¨ªŠ /œ*IsçdÂê_W+Yzj®>*²/Êÿû·££#k®ùwôô\…‰:ÆË•¶]{ðÆqJƒ)Ž3w`Å|- øˆš|¥? ‹ß£†aå¯ë  ¿Iün±Þ+Ã~ÕC(ΊO±áy…ô÷)ÀÉ ðÒàêâjŸŒârUÅð°M­J*ÄIVü{PGM5—“I±¯3 `bBL¬š&¿S›IÖí–l6 ]×£“ü ¢ìY4d2ôööFÇ಄®Ìvõ<¹\A”§6û%Ó"K¥Ä±£ï娶ï2óìðáâñ¯iŠÛ1#ˆˆZ•lqâûÀÑ£Gñ¹Ïý%>ðS+Þ¶–ù˲`š&2±ÕÉdš¦a¤žza‹Á†4Ì·ô—¢; ìvê»_ÅløZQ,¤‡£1×”…È´Ÿí±îI–_:¹µˆ0Th^d¤VNëºŽŽŽèºOººº¢^+Á³Ï^T²Jk5®€_íæóyË2)•2G<σëºð}™L7Üð7¸í¶ûðš×|ï{ÝÏ%ëW×r²«ÞÀ´Ë€ì§SÖÛ¯ò/ú1'Ÿ' E‡Ø‰WÈ8Ñ6Ú9Åÿ+Š8Qöi2]Tn¯eÁ} 3iDµ#Œ@Lîe2…'Þ¥‰IÂØó¹¿´0,ø7MXVmÙ:DD+N"¥¼æ°Z¸¼‚XL:*å=Ü*,sº|ßG0 aFÿ—ýÒLÓŒŽ³bƉ,ÿéû~t_Û¶£ JyMïÌ,)2#EåíŠä8ÅÒ©žW\Ü#3QDyYñ3<\,çåÅwÆ“‰ˆˆZ•¬"#+<ÝtÓÿÂûÞ§ãe/ÛVñö³Uñ}étccc3®›«‚HÃÔ†2ÌÕ,>DíNÛ. †è»xx+ňsŠdaæ –,$ "ŸÏ†˜wJ~× 0ñcØKF µ4P¡šÉÌYÆK×õ¨„—ªªÈ•qײº¾œç‰H±ç‰ûV:€gضXÙÕì 4-]û z&–l»X:%¾Ï•&ét¶mÃ4ÍB?! ;qñÅ…>%áÜ%Æâ™&†ø{ͬ;6[¦‡fÍÔõ…Û&Q½Éد(þWÖÉÎd &ìÒ+#bûcµPdIÕ €þ£/ÂÚý7È ½Ê?ofhËÐØ6p€Ÿ¿;TU|Ì(³—Et‘}°å„QÔ{I¼ïDD«ŠWøÉ`Æwr”¦/oê‰ïWÙh^–ëib˺IAä$EQÐÛÛ1|߯ËàÊŒ”±±1ø¾MÓ¢rÕ4­A*µ Ç)ÿÈ ™‰,I‡‡KçSâX²‹ˆˆ–#Yž_Q€7½é6¼àgâ£ÝVõö™Låö2ã7WeâÇ÷}d³ÙŠÁ–†š­ä—$Ùe ®J‡ˆ–U,R~¯£æj_3ä 2kd¶µ9^áyê]¿S>!:À; úÀ{ eZâÇÅéz40 ² ¹®8¸ž+óI–‚®ëBÓ´¨6³®ë‹R;P6ð6 1î[)`¹²|QXCé Zd¦I=äßp¡oYá2 ®ë" C˜¦Yuuƒaˆñ0W‚—ã8Ø? °z vTiˆ µ s+Ö'ý”Â>FTpÀ0Qµ¦~: ^Pº}Qæ &êRþ5~+êC¸? S;1ºòÒ `·=\sgqç²Ap`æs›¦x/£c–Lá~…sæ¬Ø _¹œxÿ~ñ‹WÖÿa-wr%W…ËeSù ߯å)T;y¬¬iEA†Ñq3 Nºef‰ ’xž‡ááa¨ª EQ¢,•ò`H<Ã[f’(ŒvQ²l‰\˜62R\´Y>´B ¬*ò{…S"¢ê\WÛöõMâ¶ÛÖ㡇þjÎûÄ÷‘A •JE‹È«ÍwVZLÞT:Ä1ÿÕiàµ:‰Í/%“â` Úbw¹k¾S»FáþIˆù F-Ê“ÖaXú!…!05€0'‚N÷žW"—6µ–p™TV¡x­\yPíyÒétÉä®ïûQtvdd$:ñ[LŠR\)•Í.M`1ŒÍ’Ë×çº.ÇÁððptÙ·¿}ªú`´2Ð4Þ^à o8aq7ZBÔ·j/ž>ÚÙù4>ö±¯á®»ö@Q”ªÙ[šVü{—•Zhw"Z½ü/À»ÐoƒŽÔ°pB×EÆ•1±Â ±sŒû½ÿÌKŠÿWU±Â1Z4¸Àº,ð~xU¡>„s\éT†!Æ,-=O bGx\åíŽeú(;lK¼FõDT¤ëÀ§?]ûgFD´ì³\U¤„¡8†áÜ\m,ËŠú•ø¾]×£^®ëÂ0Œh¡„ìC"{”È PÇqª–Àe¹-ª—œgPq,%„¡¦Ä›ÍÓòày4Mƒïûp§ä{Ahu]G8tèP³7—ˆ¨é°XÖǹš }_¼ŠÒS×ã%“Iär¹( 2ƒë……07ÿûÍøúK¾.Ž»ëèéÞp®[Œ$é:àŹ`iV¨ësNiˆÀJ¦Âûa¢ö’_–U¬C\>WþbîJ>¯{íò1’IÑn0 ² õõMbß¾}xï{»áº6Ä ªHi“%qЦ7qÉ¢m3VæKöz)ŽÈëâe—ä¿®ëBQ”h%a¸ï¾ßbÿþOâ‡?| lÛ†®ë°, gžy5¾ÿýKñêW?Ó´÷‰ê7Ÿ»†QˆÔÐÀ]Ú´éIxÞ09ù1üú×[`šæ¬cJÖ­¶íbŸ’9{õ]ù>ª*‚>²î7ø†Íаëª#0Âé_EÎ9ç¿\UûMD´œ¨œ™h³YÖ«x|¨ª*Â0Œ~ä t6›²K4M‹&8eé.MÓ ªjÔ7p.+¥Ÿ 5‡ç'Š€âq¬,o"ƒ(‹Øw•j${ É߃ ˆ¾g‚ €¢(%ùÝ£iZt}&“‰~W¦iBQxžÃ0ð¶·½­Ù/“ˆ¨é\WÌ_Ä ~<ç9Áu]LLÔ·C ‚ÃÃÃÕ3-+Zí­( þÇ)ÿC\n Xᣑ •ªUF ‚ÒUa(ìåv‡ U]ˆ’\µÌwÝ–\ua hû¹„˜YÞA}åÅr¹ÚNVâùJƒ6©Tm5ô€•UÄó¼B­¿7#þ^ùÊ[p×]ضe¦43€ˆ/Ey2 À'“¥µ~ËɆÃÃ¥uŠ,ËŠtš¦‰ÞÞÞ¨‰g.—‹VûÈÚ‡###QspùE*‚o¸a¾ÿý§q啹({Ŷmìß?…û·_ þb€ÔlõöC‘õ8k ¨8ŽƒÁÁ»ðè£/ÆÚµ£xË[>ÏÓç FÉR€ÿp¾Ø_cãN/þ*Ÿ#Êî²13Se3€——>„m‹Ì]TÍ<8¬ˆˆÀÑÀ‰^¦G³q Ä~Wö7 ‚)I`U¹ì§Ì¾Éfc‹ T±­V/0övù~„Q×÷}\}õSxÏ{:ñ†7|ªªÂu]ضà¡5ðýÃQ½y™M×ÛÛ‹?ÿó?ŸÇ_Ñ2UVŸ8™,î³æÑÚnÅÃÙlAD j€âqž œÈÆð¶mGÿŸ­ÑRÃâŠ\ ³¥!E”A4MƒëºÑu@1“UdÏ$‘ß%P% êÊ l<ˆR‰<_?þøã›ý¶5ëŠý¢ïc2Iã¾ZwÃø0 ‘L&gÌ'FdÙ¬Âê=íã±¾V¸^…"Ⱦ°ð³0b&3Q|_LbÉIŸòcRbÆ…¨æa.«SðlPKßÌ…Ç&Jáù+eÎ[–x> ¸2$þ:æ»:DEiéúÅîqTV4Ïó`YDl¶mãé§ßÛ~ñÝ i 8 R¾_®œÏfÓ JRïâ«mÛÆš5kË境QUU¡iZtâ+WzžÝ/~R\)µOþrrŸþôÿÆ?þãHt™X)äà׿þ*€hö[GuŠÿÔ$ÞÏ$ž5"W–Ég²éìÐÐûÑÞ~TUdGx7þÿ´ êÍ÷ü'¢Æ^æE"ž.S'ËÆˆ~: >1󱢞#ÄŽÅ*ünêÓ¢a|$ d³È{,Â?{èy²ÐàK]~Åšg²ái1 Ïãá¿U?s9ñýc€ï»Ñ à§žºAðûhœÉU|òDttôL¼ñ×`ëÖ§02">K.)‚TªãàóßûÂ?ÿsLOO£¿¿¿á;DD-Ë‚Ç ¿úÅRª8Gjeòx@Ô¼]þ¸®[rL(WËãÇÙ°g-5Ëç>–%Ž5e¹h¥å¥$Ï Ò±¼Ê¬™a Z°'¿Wd€E–ú«Uù÷ ËÿÍÍqÄ~Q–ûr±Ï<÷Ü[ðôÓÿŒ¯~µö‰t¹èzÖŒã\®d¢òØýÇâé>]¼^ƒ¤Pìg2…} , ¸ÍþÇUD,KL¶Ä³Qfc~â•JÇ:€hdE¬0<P|À €33ÀÝFñù £˜.ïyË:mž•&•JExÉd¢­\eç8ÅÛ›f %…šHœðú¸çžuxÛÛ^ˆ?ýÓ»ðÑn‹^‹išÑ„ëôôô¬%ßL©ï UÅå—@iCPÃ0ð«_ýªÙoÕÉ÷ %&ÝúOLev…Œ-¤ÓéhbÆ0 är¹ÂªVÑËÄÜ äˆLYß±Êóê&€Bÿ4€Ùµ@&@±¿‰‰(úü ¬½N;¯0„®iÐu–Uð{ðcøR8@pÇßAýä+ŠOZ˜qÓsºÈfU€Œ¶x>í/«¿'š¤ÓâaÌB¹/˜€Ÿ×;Ž•ÐÓ4-*… ëÀ_ÿõ[°aÃ$T5„aؼy?ÒébddÉd2Ê ‹{÷»ÿïÿ›¹è@Žéw½ë]ì°LDË_±ṙøÞ—ÇoZá²øÂ€BÀÜÿ˜ØÍàX±Š½•zf6ŠçyѦ\\#W‚ˆ(2_é$¹ÞÕ‹D5 Q:.h‘ |ˆã?9ve¹blk€s¾ èÇï´u@ø ÑwÄ÷@1A"ÉïyØãžS)ü^~ŸÂ1¬Âó+…û+(–‰ßGÖ$bסpù²ž³m ½ì=P —y±ß-WÐʲ…².º^¸\n¿ì½çOüð é:‚Ó_zzñu»âúü¹y<òñG°aÃüò]¿ÄÚ[‹ç䟃o íhÇÎøRkR8aÛ 8íøÓðœ=´?‚“„ÍØŒ‹Ì‹ÐñHrF®ø(±mVcÛ=Ná½+”â¶•¬VË^_Xø‰¿Ÿò9 ŸÁIO´¸ÇD«D<­9¯æÅ›£îWžeæû>6n܈ /¼°Ù/kÅ“Õk21—ÙÕ¬_ÿ4~þó309Y{0Åu]ŒŒŒ”#:ŽxÐø‚›²yÓÞpN½i%õ«TD%Ì£ïízçXe}sÃÌañ8€¸l¾iæ²ì–±Ï !öirÛÓJ}«}_LˆÉUå‹“R)1Adš•çdâ¡e>gÃ€Ê aYVÔðR–µ*/IPi•,×#ÓÇ›X‘’'žx©ÔUÐužçA×õн0 ~gžy?þå_ÒÑDk¦žNá…÷A6þ›eƒŠ=•Â鯻]tQémŠça×®]xÝë^ל7ŽæE~¿×*~ õš×L"› ‘J½?šÄ9\¡ÉUAÄŽUTCìì‡Mî¯T”ÔÚÔ7ê—T@ÙÜ/üÔÿŒƒ·wÀ6p½è@ð@}vøÜgг¦ ÛÖÑÛ[(Q¦iÀsU`P þ.ÝÁÇ“d2ÅÌ‘èû@ô¿«þþA€¿û»<þïÿ}Eaèˆ çºu›à8?ˆVùÉ,1Ó4¡ªj!ÐrÒé‹â9EÈF†ÈU™ Y-âýaÍp"Z,ˆ“9)'í€Ò‰X9ñV>¶Å×úrM®Ùè@ɤE¼ù»ìcB´ä²…å$º TxUn›A1H >¦Ïü{Ü(/ìêuãúõ€Ò(— XR$ Q]”Âm­Âåñ…‰âªÙ\ñy£ E¢$¬Žb°C-\oŶ9ˆ=/Š%5âßA2‰m›üÎêE1ĶÛ*»\>–¬¿.ƒ rÛL½u 6À£o}?ûòÏð«#¿BþÜ<^:þR¼í÷oÃ×Nù~ñÌ/?77®#ã06ýÃ&œvè4ÞpzÛ‡pÂé'Aÿ`ÀÙ…ç‘+ÏpJ=*Š“RòkGÞG)¼ÎØ¢§òu¢ì½ÉÅ^§|¾0v[ùü…¿+î¾¢!ÂDK­RM r`C.”“™aò÷øÿã÷—Áy}ùíä±C¥Eµr›ä1G|‚=ÞO-^–Oö;’Ûmš&.»ì2T–@2Y\X©ªÀG?ú0¾ô¥kÏÿk]#Ë…Ç.?s4r½ϽeïÌ+N$!¾çK‚%eNJ›£¥«Ecû½SPÌXq ö¯ò¼" k@XØ9ñ¥ª•'‡³Ùâ\iùöKs¼+ *Ëì"¿èåÎ!>©;[° <£*žmÕ²Ðrj‚BÓwÓ4£RHñív™LÙlº®ãe/l{¸°J4[x8x^,«gŸý½y÷’+f¬N”5 e´U~ø>Bãtàç;¥o’ãàÊ+¯Ä£>Ú€7Ž–ŠÜ?tuª×ðwÔÝ}éôø¾c½gž9€‰‰K«?Ç)€žGÉIU.¤­BùMâ÷O³À"Õ1øï”öc¼'º²¹ Ãü)’~-Ô8Úõ—3U@ý- Øï^ÿÞÛ02Rø“4‘‰ó\@û‹ŽªÛ­(â=qq_»01÷?ÿç|ñ‹£M˲¢ñYl¦Ù…¶¶ÿÆþçf|ò“*n½U…¦{ßKwÊ2è+‡Z*%þÍfÅ,…aU¿Ël[Ä€äv®¢ý6€™=ö‚ Ø‡ÉóŠ}ÈdF<öÍfKCË’¼ž'2ÎäùE&SÜ­›¦ø]>·¼¿¬c ˆûÉç×e2ˆ²cMSü~àÀfœyæx³ßÆ–­>.”/⊓e³âßå[p' ºA-x‘ àMÓŒ.‹—t%j*Y¼Å ‰J‡-ñq[’ô=´·ƒ Šàíe÷ŸŸU*Ë!·A’F…ûÈËÔ²ßË¿_ªl3ä:¶øíãUé>ÕÖbÒÓu]hºxãä䥺РÁM¹Ñ$©¢(@ 't`? ¼KÁ;w"‚hRì*\Uûç˜C1ÐTþ–¿Æx¯ÀJ¯±Ò{`Vy¬¸JŸM5…Çp¹¸ ªPsÈE¯¾ï—ô’¿ËëeV‡ëº0 #º=Pœ‘%óä–óDŠ¢””ë”ó]€èùšÈ~Eñ` P¹œûbˆOÈŸ|òÉÍþxV…°¬aû¿üË‹ ¥ÿŸ3ç}ljx¹\Nü]É“M‹ú¤ÌæÒ©Kó/®~ ÀH|@JÿÏø„ ;ÅÇŸ­|—\PÐhfá'¿TQ\¡êûâG¾ÉšVºzµÎÅì+*Ë„çyp]7ŠÊÛ¶]Ò䮞Ò•²ªLSLºôöŠ1RóÕÏèd³€ëâ<‚ÏŸr ÜBä^Ó´hg“J¥ ( r¹\4¡j<¯4 Òk’ßqŽÓÏc]„ªn_–DWOݳW:­|&JÎ@Œo_ˆ"û> ¼§ô‰œyùåÜy.3²Š,ß5[ Ñu]¼ÿýÇ<ÛËÆsM$?ø´TÜÙ#«Ûbt]W_Y©"¹Â;^@–aCì2Å’š6 u3Q,¯i ˜]&ƒ¦²LžÌ²!¾äíÒ2{ñòvZáöJÉÕâñç)Ïx‹—ÿ”·/=Zì¹3(fÓ<ö’Ç¿%:OœþXÛú’ÛÜüŠ›qúu§ã¬³Î¿÷¯è9؃®!Ž9‚ 6àƒ}Ïüñ3¸âø+ðƒßÁþ—ìÇëzžüƓ؊­À-ÀÅ=cÃá xïeïÅè]£xç¶wâìýgãàÁƒØ¸qãÌ÷!^&€mØÅ÷Î‹ÝÆ)}=QV™Wø.ˆß^šåyJÞÿÙž'þ~—oWA[[›ØGТŠåËEÛz¥£‚ @&“)i“]¯¿¤ÖæB &þ¼]]¥™É(<‡ `Ì4»˜É9Ûa­ñ÷µX•8´²%Lê€Ê"‘«1Æê- çû>ÒétTR( Cd2™’šÐóUmYN~¦RbûM#,6›²Ùh™éGŽ`Ó¦Møæ»ßÕ–Tž¢àCW\×ÿú×ÐÞóž'À# XJnš@øý»ÜÿÒý!³ã(üûÛÄë 1ƒ kƾ6 à¿þõ_Åmâ³F•Nä Kz;I(ÿùI@ÿZéõš†Ó~ó›¿š?9X×¹Ô,Àì‚Óg6™÷}?šÒ4 ;wÞˆñOGÆ@”¾™ûþ;\¨çBìŒdÿÞ÷}Ã̧–}‹|_<§r¥¼@¯è¯¼óôŠ›¬iÅÌ‘0,.pæ,¯]Q€ááŸþôZØ?ygüþ |ö³ÇÂu¯D.—C*•B.—ƒeY°mÙl¶m#|øÃOàíoïA*\wfðŠSU±­õÆ5l[Æhk_Qdšeßg­2£HË– p¸n1€ 3š=¯0‘½eéL9¡-ƒ‰¦ ¤»pR€IDATÞ›õ à+‡žAÇiGp×]§F¬øñŸÂ›ß|ÃÃá8ÀèŸÄŽ_ÆÛ­µøÐéwãÔ?LáK?½W>~6›`F´BUåÇÀ¶ðYüñºg°÷7{a›o(I¯¸HB–Ž9À«ª‡ÊÅ’¦Zùª©P+ç¨r"#tY§pîѱéI|ïé£Íþ¸—µ0,f5ëü'>Q*W”:…ãD¹ZTü½Ð00R]¼Avüd?¤Ói G“ÉdÃÃÃH§ÓxÏ•Wâç_ü"Þõ®wáÿñqÍ5×àýCCØúÇq`Û6¦qʆ 0yÓ‡ãüÓOÇ=ï}oTfSf躎»îº«ÙoEËÚx`£˜àñ%¬i¥çJŽ#.Š;”±1XY%úžÍ<û1(ߺj÷‰@2˜¹4ÄàŽ³íÒU*ñçäŸø]Þ,~>$£ß³=OYãÝJâ¥yd–²ßˆ .¹ðOÓ´’r:òû€Aú„aˆ0 ù¾ÍÅCi¹8ÅIoYBSžó=„Çá~ 씓%‚dìñ’€–ü½±ß÷Á«€àg€ÞàeB <{ý\Àû ü‰X´ÞhçAá¸K=}ñœ’r²¨nàß Ð_ x?»ÍÆöÇñã¯ß‹ãŸ8 ÇáQÿÓßãЯOÂäo&£J%ë~~~kÚkÃc¿û~1ò;œóäá„ãžÀ¡ÇÏģᯱÖ{gœò2¬}j-Î:á—øÙ#ÏÅ%=çàÈÿºuë v*ؼyÔ¨xüñDZsËg°æ@&:¯éZe=Чô þ x!€ç·÷÷=Z|=¯y à߬=ØÖ¹- >mÄÆè5ù>€Í€v6ŠÌ%e©QZò´ð{ø>*ÞËè³V+Ü>.þåÏ”fêUzŒZžç{À‘5Gó/|Õ‹Ï/A˲jž_´,KdBe³bqõBŽGu}fªÌlA™x¤è”%#e -; ¨,9é"WPÇ[rÌ& CX–Ïó0<<\hn=÷Jíš8øþå»€à˜Š̪ç`äe!ý÷¯>øm„—¿¦V\ik…!”Bù…ááaQz¡V"³P2™Lôå²±ŽÀ¦Õ7)®ü¿!s¶ ¸oEpU'ü—Þ€®lì·ýF&S}bUQpÏUW‰mŒºvÏB×á䦡:zùëQUœöË_.ü³¡útAìlñzž8,™4Œ7¯Œ ¯p€"jT‡9q¾ù‘܃g¾ßýÄwñP÷CÐu…¢çãÿ àc=Q ™›A¸oîoý>ëT…ç¨R̶Å9p*%Î}5 @P?(/©þ²å„m6+Îmxâ‰'àºßP,“ ±2å:ôô¨8çÀ[qíþãq÷Ýkñoˆ×ááa¨ªˆ NÆí¸Ð4qlPopd¾Ç( ˆÓ2&øÈŲD”L‚ÌdÄXWÕ*_íiƒš2ð!KÔÊý± ”¸ÿ MŸùñgðñ?|S§Naës¶âèGafMüÇ)ÿuÿÍþó[vä8‘ d–:Ž,Ë2ÊUæ2¨"KsÈýHyP`%“Ùñ¶ò^UUX–…L&-^°,+*Òµf ŽÿÍo°îÉ'ñò“N¡C‡àô÷G«ô-ËÂ'„¯MMaíË_Ž×>ü0Nœ˜ÀØØE=d|¿ÁIû÷ãcú§8á¾ûðõýW Ð· @ñ 1¶ƒÞy•‚L©tMÃ]ÌP©ê¾އ׹_œÐu¤þñOà&ÅþÃ00cP·äa¥•Òý—ùbD]ÓfüÈTÅÙ¤dÚ³äy3o32RšÊ[éyd4ÖóÄŽ7v^$Kò‰«½hB_.ì“߆a”ŒóZ²JVù>Ń ³}÷9Ž3ã˜]föÉ,2ù8òX^Ó4d³Y<òÈ#Í~¹­Ë0 „*à}ùpëz8¾(£i€eN>(”ë6Þ~°n‚ÀºPÀûùA@¸v#”'BÞoáëóÕ€'«•žx‡ýñ_ÿ)@=@'< àY…Ûj=€WÈxÐ/båÞÔ ÀÔ‘)üË­Ài§ß»×_Žý9xàœuÖðä“7â…/|#î»ï~tv>3Åx::;×X‡µk×âͯ9w|û ünêñçñ"¨ÇžZÒá,¥XzÕ÷ÿs½8Þ à?p6ð`¼Ø{ _O¿»¯4v ˆ¯ «‹5MÀÿÏÒžÖš¨Çîž™·— £tžL f>ÏÈH1.lÛ€›­ð¼|Àç>7óúLû?ñ t×ÿ Ñ\ˆIy´^NöRuÃû:Ü&t4ÅÜxšw¡¹¯ÿ@y¢†aû÷ìÁÚµ_‡i~ÿpÖÅÈ©)œˆ‹éÜ uj7f¬d‘°–¸*`›€’+<×….©òÚÂFà@}ËÙpÝmÑ¡ûydæ‚™x-ZQ?^NþôO7ã®».ÅŽâ{Â0Œ((ö(‰¿§·þUá­)xÔz» æÃ¨²Q¬l Z‹Â˜õ< üXý§< X>+ưÌäL¥Š_»á=€~àŒûCA±ži#Ÿœ¯æÏõK€û{ xÀ‰âÄÖÔ/( Ú„?† (p€ÃÃß9>0’CéwHaœ# @Ré#øÌÕŸÁgïιåüäù?ÁÛ~ó6<´ ozÎN»~=þ¿Á)œ‚ËÖ â˜_ß÷q1.ÆIÊIxÓî ¦'À]ï[‹ç÷ý3;î1~ÿaüèÛ?®ïî¯ý5®Ú+êÀï ðÃoý;>²°§‚§pðKñ“Û~‚®_uaÝÃëð­öoá{Ç|_¼ý‹Ø¼y3ÚïoÇõAÜ}ÞÝ8pæ|ö#ŸÅOúSì:² z ã['| oýõ[ñ‰ŽOà”矂§ï{™§3øÄW>wÿæÝ8çÑsб¦'wn8ÿü¯{ÿB5„«ºøØæáÈ‘#¸ãŽ;°é™MÃ]tî¾ûn\~êåxÇCïÀkG^‹ýس/9?<ÿ‡0úÄwÓMß» >ø r—äpþùçãu½®ÙÑ­KFÿäd¨L{B!¸øðí˜À[ Y?…/èòz2åX*_îûâÁâ “¸rúE·ßŽ#»váСC8ñÄŦ½ùÍP%*É3[_“åL)_¸$ƒD2H?F–e/eÀäK×\ƒÁ~Ÿÿüçñ?_úRÜày¸êG?в=ïùÒ—pÉÝw㟜ü¦7aä¹Ï|¿t5e¼æ­ªâ!#Ã]]hO¥@•½ð¶Û>s2R†¡ög€Ü—ÄpWB–Çv©¿ì¬\N9^ ®›ëó*[Õ«BcYÏó¢óP9ßþ‡?`ò˜c€Bv‰×2ki5d•ă –eEAbøPUuÆw@¶Þr þôàÁ’}«ù¼çAQ<ü0p n~f:žÛ¶ç·‰2 ÀÜV|^Çùté¶ü‰w¿û¢âÿ- y2 °K^Ïp˜,í§CœÔÆžÇDY6FFŠßQ†o¡ôA4À´KæuFPö¾Õò<~éóhîÜÏ3¦”=o@«óõèžU¹©åõø^üâ`ݺu Æqœâ.ÑuÅ®î†~€{î™)%û¥⸸X}ì/îOì«îzÞ{ÿe8Þ¸xƒ\ª-,XÑÈl’x﵉*—SËZ3===ÝìXˆþþ~ìÞ½»Ù›1Cy õ &''ñæ7ÿ6Øxâ‰ñú×o* FÔZ÷€˜Qª”bžÍœåê¦ßþú¯§ðÎw~5:¸“iñfŸñFaò÷oûexðÁ¢Ur2+^7½¢5kÄIÚ™ –5³´€âI¦eÕÕmÕ²J›j/ä RM|ipp‰D‰DbþO°ŽŽbtttþ«åñRÁWQ\Q­ÿï Ðnü·©q s*`>Px ¯ð8±ï¿t#>½ïÓü<÷‡øò½÷bݺ«ð‘\õç° ©÷¾ (J€GþG¸püdÜsã=øÁã?€é›@¸}óíØ³>ª¾âcãøá·~ˆG}:tõOá#¯ÿ<ËÃe=—áûSßÇSox**‹W›ˆV›ž~ÂéxÇŽwàØsŽÅíwà·ë‹Ÿnù)\×&V¦îšÂ;?úNìß¿Ÿ|Ë'ñ÷ëÿœú ®9óìß¿7½ü&>|'Ÿ|2Î8ã twwcppïyÏ{p˧nÁ›§ßŒÑžQd” Ýt'þðD¤R) ãío;Î9çœwÞy0M3j úäè“8±ûD<ò‡GðÜÇž‹gÛžÅ#x$jºò# ÞG¬`ýýýØ}÷ÝÅZ¬± QËc©‘óš2P ?Syl_½WœË1'#È}¨œ=æ{ßœðàƒèY·ÿuÜq8ØÓM‚þÕ±Çbê_þ›ÛÚÐvÿýøC{;~òÝï@1ˆä8¥«ÿu}a%$ZA6‹[o½Ç}ðƒ<¶-#¿·î¿ *.YVqq€Ìž–q³¥:ñ~%@1»0žIoþ,zXzQpt¹Š÷e’ç¯rœËÌQ ¨<(â8NÉ÷,U(÷Ññ}^ùïòùg[ÙèL=ÛVÖßß·ýîBXû®ÄÈ÷ƒ²azI_|ÜÉ1'/‹æå߈œ_–®q:-·¿ýíX³f ¾ð…/4{SZÎ|¾·d›cY= “î¸ã—øÿø.‚ %PĹ£ 0”S£ËeЕLF Ö#Vì¶ñž8@qÎ(ÄÌ®qIˆª%´¬,Ƽ-3T‰,Çn´ HUU\vÙëq÷Ý<ù¤(ˆYWo•l¶Xt]Óf.u*¤ÄÈÀH6›…Y¨+(W·oÚtN?½+*K0ã &&¾sžŠ×ÉÍUÄt½´tIߘéiÑ IÓfÖõrœb]—?| ZÇ@¦¬sšïÃÑu°íâvºniϨªecfùº”÷Cë]3£@·ü  ®ù<ÐõñÒ¿ßØ ÓL@x3Üã߆ì-Ï…zîÐ?QlJçû>]‡_Xé ^6ÍO~ÒÆÙgâõ¯·ñú׋Ǖ™jr%+ëÎ×À÷Åwez5Q™4Ds@/¢þã€2 Ý Xwágû<ÀéŒßæ{ ÷÷ãNDcúÔîÇÝ×NáÙÛŸÅõSßÇšÇ×à§þ·?{;” qâ©þ­8ÑüÛ_ƒSïú |îYàÀøÝž»ÐÞy0 øüó?_ÒËkbb—_~9ÞÑý¼áÉ7Àü’‰k7B7uœöžÓ°ïÈ>\ñÜ+pî¹çcK{†{Ç$&qÞyçáî»ïÆ+¶¼üߌ#/8‚5]k TU&fà²Ë.úO¯Ã¹Ú¹0Ÿkâ|ý|œåù€‹pÑœo«œœQø ðÊ÷½îy/ž~q”yæû>|ÅRÛ?ûãÏBUU|Ôÿ(4U|ÀÔgîÔÞû^ñæËýü_* 8g(~Çüüç?/¹ŸÌr“'gá¬è:ù»œ  ÅŽŒÁ÷ U ÇY¾_쿵®ëŠ¿©BÉ.¹ [îc Ã(™ lYÂRf‡ÈÉÑ ðìý÷ãœãŽÃ­·ÞŠ×¾öµ¸åSŸÂKþÏÿÁÕ;wF=Á¾¸iüÖ·pÖYg!ñÄèèè€Z˜à0äñsˆ»g¸H°â·ùèG£m: ®Ä¾]™ n?öX0”RÙ#´Ãóf–J÷Þ ‚ºÖ€ÕE6uc%·ñ ¹P®Ú1äR[VÊ“cZ¼jIà!>1-o_ž1¿Ÿ ‚È÷'D•ï  È^rß8<<\u@¦ ª€¿þkàä“¡;©’Unn¸ë;;ññ¡¡h©®ëÑ SÇq`Òé4FFF¢U6@±¬¬*0WÛù½Ų]Ž#Î15­°úøþÛ¡íßSi)_ÙµÊK»nTõ,š€*fÆ#™¬>?Ë •Êê^},w`rüܽÏÌül‚ ÀÇ?þìÝû;LO¡«ë.V÷ü;lZ·î½/€ßzØ×*N„È ewùkP/Û„Þ^qq¼d_¹ød\õ–J¥¢&ïòO®HšíÄ– «+ú2é¿é¦–ØG´šš÷ò3@iêq °òÎÜoŠzËæ§ÄUª±ÂGÐüèºá´[OƒŸàóÑÉçk¼‰µ Ü¿ù~œ÷¡ófròÄó<œxâ‰øìg?‹ÿÑ‹ñêç½Çwîh¿ßÿþ÷ñ¿ÿ÷ÿÆÇ>ö1är9±¨À4KÆd.—ÃÇÞ÷1|ãSßÀKþæ%øö·¿t: Ó4£Œ0¹ZW–Ú““T‹µ‚P®^mß ÌP©®¿¿·Þº;Z7£ªÅru2¹rb1^bV®N×u]-çûw-k0T«­#'FUUÅ;w¢ÿoÄÝ·ÞŠSÏ>7~æ3èù§‚ã8Èd2èííÅÁ—¿‡'&ÐÑÑc÷ïÇ‘T ß{Ñ‹¢mÝøøã8ó¦›pôèQlÜXhn+ËUQCðØ¶²ÑÑQüó??‚—½ìu3biA ŽIgkãX+¹º=‚¨á{|_!÷ªªF“EK½Ê]~§ÈÀ†Ü^¹PH.Y@i‰éxpDÞGUÕ("'«Ë_Ÿ¼~É^¯<ÁfžÄËõ‰,ýðƒ@¬Ê‹3ÍÒïMË*.¿–_~Ò™LK?ú>n:tWüìgKóú—‘FÍ É}fü(f–ÈùåHƒËóVY’NŽÉòþ_ñÅñcñL&e3Çǹ<î–)ËâÅà§,gšfÉ}2™Lt_ù}¯šï7$ïcÛ6’ÉdIo²x¦™ ”Êm¶, ¹\.Z ”Íf£×R)ÀkFIï³ø}ãÏ'oÿƒük×®Å÷ °TTÓø”ÍÚCÀÛ/,Ìsûà£'ú8Ú¿Ó.nûªt å*ÜpÞô¦7¡íU¯ZØÇzJŠ (f­Ì•ÁB-iUd¨äóyäÿöî>Ϋ¾ÿÇ!$vv=N‚“ÕaœÈ. 0›Š’fSšâF»½@‹·`©ô¶z·H¥ æ×"Á¶Ôm/Tcz7”ÙB‰³T“R"ˆ³hc%„°ƒÅIwâ<‘ýýqtfFZ=¯´’v?ï×k_öj¥Ñ™Í™ó=ç{r9v§,9"HÞ¨ÊÑ}ðW×^ ý—?GøE=°©”›ªKQ1#­?œ_ðÙÆáÏÿßÞ³ ϯÄ_‡í7>w¼ã øüç/ĺuX³æ ŒŒñýïÏ>Û‹»ï¾ ÷Ýw Òé‘ tS›6©H&gò é.m-÷§…¼e\ÄuéJXê•H% Ò4åGX&“…Zy/\(Ñ4/-˜?Ø’J‰€“,cµ›¢«÷íË+䆳eõ3ñ´0B¤rªLèéyw}ñvùÒ—pü¿ÿ°ýÜs1<þièú‹,[_~Wÿ÷q¨ç€vÙ ÿÓË€k|å—³§òÇ–oT¦Ó*n¹e?€³‘Jy7þÑÉd¦i"»i¦óCëJåGÍ!+°¦ûöµ»4K¦iõÓ†h4*Z9:$úR©|€1_?£Ÿñ§·´a8&세µ ú÷t(g‰Ž“äŸ%t‚\‰+`Á(tys¦ëº{Ã#oŒÞ÷¾÷¹£ÇÁÇ´ácûàÚ|:™Lü+gcè?uRÎÊ3ÀäÀYgËé+J ît¿üÈÙeÉ¿à²m{‹å¬@ÔÍâÑïÕÈö¨€¬#º®ìY¹ý_=åLÿíßâŒü@Ù!!g@;Žƒß<í4ûÙÏðê›nr½æÔSñâÔžÿïÿFॗ°í꫱6_TUÅüü<`šXïk´ àÂâ‚üæo¶ö¤ÑŠQoý¼ì²/\ÿIUë«·þ4Aþc ÞÄãñ¦uÞ_geç¤ì|Üðÿ€oƒ£2€áïˆõ¼—³,eªü»eYH$H&“P¥êL·½ì¿Vªª—™A¾Ÿ¢ˆ€®_qÄTjásüA ÇA  Ä·N€…izedÛ϶EÙävНçþôÛåÎa<^}¤c:-ÞÃ0MÃi_ÿzS>Ý Õ}C2“ˆ¿>ÊÀ‰¼§«µþd @^ÿR©”[×dÛOÖCù\9@VvâËÀƒaîk/8)gMË`A:ƦM›N§Kvø…³ÁäÌnùZÙ¯%¿V¶'dUXä ÿwƒ?ÈZHõ§ô†åŒ2¹f“f[qÚkù¹(¹ü®,ÊÊ5߯Í/ÿ ‡ÃAêRŠ_Sü¯ßøø8n˯g¶Üµ¤n~ÐþÌAìKgŸÅŽ_ý>ÿðOÎ?á®ù|ö§Ÿî²[>ltLº³®e¬þ÷ßœ²È„/•|¡Ãf¨LLL`ll ýýý8pàFGG1<<\ñ5 "&ć_NÙÒà寓TˆJ!ÛYqx£âe'R>­ÐÓ¹§ñƒ€û|N»ë<ûäcè?å9œrÊ)˜¾î øµ×üÞð†7ˆçÿưFÎPûùÿF<Þ¬ðØcaõo¬FfWçw{ì1ÀñsŽãGÿù#¼¹ÿ͘þaï½®7í>Œ~ì¯ðÝï~×\s θæ oí-°2€ó¨øÕz½0þÀã@øí€‘œ€-Þ¡«û`ýÐ^è×úÛŠŽ |ÇM£÷ñÈuId@£¨O»md`E„4Mt"–«)ûý×±úw—Œ´»è-Uoý,},oÉT]ò÷0ò ê˜,Çè ‰{Upâpâþ𢽸÷À3øiOþûØ1=:ƒ5k~ 7ŸûwèííÅ+¯¾g_y¥8i%¢1Žü×Ɔ » Àp8ìŽ8Y·nÒé´»˜¬lËÆŸl\LwÓ-:ec«Õ[?ÝãbAÔÁÿ4á¼ël(ϾÎåz?³aì;öÖÓú71›¯¸O\vâÊÎ ·1[â&Ôó&oZ ÃÀ½ûݸùÿŸýìgñ£þg\ñÖ·blná| Ë+_ö21ÊHFÀ“I¯ÓBN‰´íòyeçŒü[© Y´iq§IqÇJ‹{»ä´HÉqD™ýüé1§ôbEë•äTˆHûGÛú÷g±ßgÅA$Ãð.¤²sÜ·¿÷~õ«˜I§JÖ8±K5¥m[BqÚ.Ù! ;5ªêäõLv„Èà¥ádYg ÃpSi%“I†}}˜ýô§ñêo|¦o4è¦uë°Vö*'b¸þ ¤u³•2CeQmÛr—mOY?ý™äµ³ÚöäuT(°Š¾Ïý£ª£Ñ(†††N§144„ééi7P"ÿ•ku™¦‰“IÜ›H`î?ÿ×ŽŽº¢š¦A‘qî"fų1dC>·T"+lLwJ&…ƒJÍúH¥¼@†\­Ø½õßd.·ïÇÁýýý¸ôðáv—¤ånÛ–!Û«2£ˆl³ÊýÙÙY¼ôÒKn@Pè‘  £ÚŒy­ŒF£î  yõßCÏúïë/³Íêl+eöuSÚ¶moSEJiHÆÐ^$޾¡W߇«å+HÞõ-¼æ=ï3«àcxþäç1÷žßÁŸ:ä^;5ãšVŒV´m;* rÅW`÷î݃Èf³Øºu+LÓ¬ñܲe ö}bœw~Öó/À|æL¨¿{ì{7"õcÑ ýr/ŒÿÞ%¿ÚmôÔÿ í¯ÃÊ÷(×YH x)/œt:^qZ?8õ7ñÒ‹àìWÌaà§ppzV½ü4<·j V­V°ùŽãëÆ&À+_óc¼8û+øÉ/bݺu¸ãÇÇpûG^ÄMß½ ŸºðSøîw¿‹ ¿z!^öç/ÃÚµk±zõjÀ¹ï9°Ãÿu§õŸES¼ÎfIv:…‹'I¥DEý:Ð{?àüЂù×”z99 /(%Ét/þ÷ð• BÀ·=€×<óoáðTÑû¤!òÊm¤J¼ÿu¥ö'”/§…–½Ï‘#G°þÖW}Ÿ±·­Œ›Îzëç­·ÞŠýßÞ¿úÎV8/~ Ž3õœÇ€Ï%ò< €>œ 8k΀v÷ÿÅÜð'˜xýëÝ›ÄÓxyâ¾ñ‹õXsî¹8´á7qüÜ·ãW¯íÁ«_½χ΂µöjè׿Öì…°,Ñ¿ù­#PžxïQR¸Â1ñÒºUø‡ü¨pyCºí•¯Äe^½~=^67‡ ßúV$ò7”†aàW_ýj<øƒàèÚµØðøãxËÝwãÈ?üƒ{Ó J$":>äQgÇmÿÚa¾œG‡À±;î@ß³Ïzd²°cE\ü‹|wðÈN©8Qù¿17wÎ8ã šÃÅ_Œ žÃùç?[óþ§R)ôõõáÒK/m÷©X´±±±eq)Þ3<O_òtÁsî¿ÿ~Üyçø½ßû½eÚ©‘ú966ç“OãKÎïcÝÙž8—i6^ñŠïâÎ;·à—¿ü%úûÿwݵ'Ÿü0^|ñEœqÆ i&žzê)üÆoün½õV|èCÂç>÷9|àXôüóÏÇ£>Šn¸·Þz+n¸áüøÇ?ÆW\áþÛ Ëå3½’¾gžyæûÙÏâ±ÇÃ…^ˆï|ç;xá…pÒI'áÒK/ÅÑ£GqÑEž|òIœþùxðÁñ|ŸûÜçð‘|Ä­§·Þz+püøq¼úÕ¯ÆñãÇ—\rÉ’ìÿJúLw‹ZÛ¶_ûÚ×pûí··»¸-ÕHý¼á†ðÌ3Ïàg?ûžzê)œrÊ)ؼy3~ô£ᦛnrëÞáÇñêW¿gžyf»w³$¶m;Û¶žÅ´mßô_7`ü[°¶w«ûŽáºëÒøò—/ÃÓO¿/¾ø>lذ¿üå/ñîw¿_ÿú×Ýkç>ðÌÍÍaÆ -kÓvúµ¤¾:¹¾:t·ß~{ÓÛ¶³†J6›] ìííE.—«üB¸çäO`ÃVá ãBüX³f V¯^ .¸§Ÿ~:Þò–·à™gžÁ+_ <òÈ^ùÊ'°fÍïËolSþßÕø%žÀÈÈefð‘\à Þÿþ ܇͛O0à åà ^õ*à…fpð pð`íûßÓÓƒ'žxÇŽk÷©X´‹/¾™L¦ÝÅhÍ~ýºÿ~<õÔSXµjU»‹ÛRÔÏuëÖÁ8+…¹ù/â¼M¯Àš‡OÆO¼33ßÁ|§œò œ~zÞþöâe/{.ºè"œ8qgu5yä¼üå/ÇUW]…GyCCCxê©§pùå—/xŸsÎ9Äå—_ŽƒbõêÕ¸ï¾û iŸÃåò™^Iß3ÇÇ<€—^z©ÝEm¹Fêçyç‡{â±jÕÏ03s6Ž=ŠóÏ?ÇÇUW½>ø4Þò–Ü}÷,ÞøÆ7âĉX³f N;í´üuø6\{­ûïÔž·~çä“ñ¡¡Â7ob]zþùçÑÓÓ³,êçrùž©åœ>|?ýéOñÚ×¾¶ÝÅm©FÛ¶Ï?ÿ<}ôQ¼ùÍoÆUW]…uëÖNœ8sÎ9Ç ¸Èkãõ×__p€§žzÊý÷`= Ò&ZIלnQË9aÛ¶|ý\µj<ˆÇ—]v^õªWapp<òÖ­[—oÇžå^'àòË/wë«¿ž^~ùåxá…°zõê‚:ºTŸ³•ô™îµ¶mŸþùvµå©Ÿ'Ÿ|2Ž=Š7âþàÜÇ_ûÚ×.¸FÊvj'bÛ¶ó°mëYLÛö¿Oü/?÷á½Oá¥gÖàßþ èí½ —]¶ÇŽ]†k¯½ÖízÇ;ÞQÐÖ€ƒ¶¬MÛé×’nø^èäúþãÿ‡nzÛ¶c*³³³ «eºÕwÞÙî¢-{ÔÏßÿýßÇïÿþï·»èDË^#õs¥,˜HÔN¶mï¸ãŽvhÙk¤~^wÝu¸÷Þ{Û]t¢e¯‘úùµ¯}­ÝÅ&Zöß¶ýßíÞ¢¦9©Ýz{{Ô[?»a¿¨²V¶š­Ùmìf9pà@ËÚÎÝ®k*þÚæ/¾øâù‡~¸ÝÅZ`Û¶m .œõìG;÷ó–[nq;LJ]|*•­Óö«Ò¾,æuËçp)uÓ1éæs_é3½Øú·”ûVí{¦Ò9ê¤ýèÝtLºõÜ/æÚYíïËåÚÙŽ}¡æ7Dþsß-Ÿé‡~¸`û³³³ó_|ñüšRÖVïK¹ú(÷Ë¿×]wݼa]wލq¥êæü|÷œûjõ³“Û¶•®•‹­ŸíþÞ¡æh¤~vʹ_ìµs±û¹X‹©Ÿ¼_T]«ÛGÍÖì6v³øÙìììüu×]7ûí·×T†å^ºr •L&ƒÞÞ^ƒA@__úúúÉdÚ]´’e-5­¬–ýh÷~ö÷÷cxx}}}u•½÷«Ú¾4rŽÚ}~:Q·“n>÷å>Ó‹­K½o•êf¥sÔiûÑ ºí˜të¹oôÚYíïËåÚÙ çˆ366†¾¾>ô÷÷»uÓgznn€—n §§@³³³‹.ëRìK¹ú˜Ëå  ß¼ysMûÕiçˆSªnÝuî+ÕÏNoÛVºV.¦~¶{¿¨9©Ÿtîsí\ì~6C£õ³Ó÷‹ªkeû¨ÙšÝÆn–L&ƒÙÙYlß¾€¨ÿ¦ibóæÍU˰êÁÉí.@#²Ùì‚›øÞÞ^är¹v­€¼øìܹ™L===ÅððpMûÑîý”_<¥òÜU*ÛÜÜ\ÇíW¹}YÌ9ª¶Ÿ+Q»?³õèös_î3½Øï•¥>‡•¾g*£NÛnÐMǤ›Ï}£×ÎjoÇ÷N+®µü:O6›ÅÔÔöîÝ‹;v<Þ-Ÿé¾¾> 㦛nB0tƒ‚òF¯ÓÛ¶åêc0t÷õsjjʽùí¦sDõ+W7åߺåÜWªŸ{öìéè¶m¥ëþbêg'|ïÐâ4Z?;éÜ/æÚ¹ØýlVùåv‹UªŸ¾_T]+ÛGÍÔŠ6v³är9ô÷÷cbbSSSèééÁððpSÚÎËAWÎP‘E¿r£$ÛIFD·oߎ|»wïÆØØ˜‘«¶¼Ÿ•ÊÖMûµ˜sÔIûÑ)ºé˜,×s¿Øú×IûVéuÓ~tŠn:&ËõÜ/¦ì´_˹}C ÍÍÍaÇŽؽ{7zzz þÖmŸéžžwaÒâ›ÀåжššÂÖ­[ Ýg·#ª]¥º tß¹/W?—KÛ¶ÞúÙ-ûE¥-¦~vÚ¹oôÚ¹Øý\JÅõs¹ì Ín5K«ÚØÍ’ËåÜÙ&Û·oG ÀÈȈYéõ +*¥¢ËåêëëÃøø¸½ ƒ¸þúë݇jûÑÉûY©lÝ´_‹9G´¢›ŽÉr=÷‹­´o•ÎQ7íG§è¦c²\ÏýbÊÞIûµœÛ7´aèëësS`ÌÎÎ"›Í"›ÍvÕgZŽ®Û»w/FGGaš&8€={ö,º¬íþLÏÍÍaddcccصkvíÚUsÙ:éQ}*ÕM »Î}¥úÙímÛFëg§ïU¶˜úÙIç~1×ÎÅîçR(W?»}¿HhUû¨YZÕÆn¦@ €Ý»w# º &&&ª–a%Ôƒ® ¨ôõõ-8³³³í’|?Ô±Ú~tò~V*[7í×bÎQ'íG§è¦c²\Ïýbë_'í[¥sÔMûÑ)ºé˜,×s¿˜²wÒ~-çö •677‡={ö`Ïž=Èår¸ýöÛqûí·wÕg:—Ë!|VƒÁ ;‚®›Û¶Û¶mC €išé-j)['#ª_¹º t×¹¯T?»½mÛhýìôý¢ê­Ÿtîsí\ì~.…rõ³Û÷‹„Vµš©mìf ƒ fÎ,‡>³¦Y‚…ï[b```þ®»îšŸŸŸŸ?pàÀüÀÀÀüììl»‹Uà–[n™¿îºëÜrÍÎÎÎ_wÝuó·ÜrKÍûÑ û¹mÛ¶ùOúÓ ¯T¶Nݯâ}Yì9ê„óÓiºå˜,—s_ª~.¶þµcßJíGµsÔ‰ûÑéºå˜,‡sßȵ³Úߗ˵³ûB‹·mÛ6÷ÜÍÏwÏgúöÛo/ù¹5 £)e]ª})Wïºë®‚Ÿ‡~¸ëÎ-NqÝœŸïžs_­~vCÛ¶R[¶ÑúÙ ûEÍQoýì”s¿Økçb÷³™Ç¿ÞúÙ ûE嵺}Ô Ílc7ÃìììüÀÀÀüÜß»±Ï¬UºrQzÅŽ;Ðßß`tt´dnÊv’‹çnݺ@Àðð°›³¯–ýèäý¬T¶nٯŞ£NÙNÒ-Çd9ŸûÅÖ¿NÙ·jç¨[ö£“tË1YÎç~1eï”ýZîíªO·|¦7oÞŒL&ƒë®»ýýýÈårèëës']lYÛõ™ÎårÈår)x|ûöííªsDÍ×-ç¾ZýìÖ¶íbëg§î5G7œûÅ^;»Ÿ­T­~vë~‘ÐêöÑRhwùzzz0::ê®?#×Ñ\}fͰj~~~¾Ý…h”¬ @ £§ e³YwjS©rVÛNÞÏJeë¦ýZÌ9ê¤ýèÝtL–ë¹_lýë¤}«tŽºi?:E7“åzîSöNÚ¯åܾ¡útÓgZ¾_oo/úúúšZÖNþLwÓ9¢æê¦s_©~.§¶m=eëæý¢êºåÜ/æÚ¹Øýl§åº_äé¤zÖ©åkeÛ¹›uu@…ˆˆˆˆˆˆˆˆˆˆˆh)tå¢ôDDDDDDDDDDDDK‰"""""""""""¢*P!"""""""""""ª‚"""""""""""¢*P!"""""""""""ª‚"""""""""""¢*P!"""""""""""ª‚"""""""""""¢*P!"""""""""""ª‚"""""""""""¢*P!"""""""""""ª‚"""""""""""¢*P!"""""""""""ª‚"""""""""""¢*P!"""""""""""ª‚"""""""""""¢*P!"""""""""""ª‚"""""""""""¢*P!"""""""""""ª‚"""""""""""¢*P!"""""""""""ª‚"""""""""""¢*P!"""""""""""ª‚"""""""""""¢*P!"""""""""""ª‚"""""""""""¢*P!"""""""""""ª‚"""""""""""¢*P!"""""""""""ª‚"""""""""""¢*P!"""""""""""ª‚"""""""""""¢*P!"""""""""""ª‚"""""""""""¢*P!"""""""""""ªbÅT Àiší.ÆŠæ8LÓ„eYMÙžmÛ0 £Ý»EMÀúÙ½lÛ^P¯Y7»ëãòRk}t¶m—|½iš%ÿFíźڽsí,WWýÛe}m?ÖÏöj×}'¯¥Ý‡uµý­¯¥®¥òqÞ‹v7ÖËåg9ÔËPI¥R˲B6­¡ØJ–eaÓ¦MH$B$Yô6mÛF*•j÷®Q,ÇúÙ-us1b±ÔkÖÍîÆú¸¼ÔZ‰Ä‚F®anèúFðr³ë*°üëëb¯¥ê*ÀúÚi–cýì–ºÙÎûN^K»Ïr¬«Àò¯¯å®¥ïE—ÖËåg9ÔËPY®LÓ„ã8í.FUCCCˆF£H§Ó˜žž†iš]_™ˆ*é–ºÙ(Û¶‘H$0==íÖkÃ0Vl:Ûr¯‹a†††H$ü-‹arrétét‘H„£k©å–s}]̵³R]X_©õº¥n¶ã¾“×Rê4˹¾ò>”ºU·ÔK*mÅTR©6mÚ„U«V!‰,øÐÊHøºuë‹Å‹Å ¾€-ËÂÐÐV­Z…÷K}pp†a`ݺuX·n Ã@,úuë°iÓ¦‚(j=Ï­DnÇ_^ÿÖrñð—Ç4ͪ¿×³½Jû'¿4¢Ñ(@QÌÌÌ  UÜG˲Üs#·YiDÿ<Öó:Zz‹©Ÿåê&Ð9õs±u³Ôc­ªŸÕêK¹ïyÎEqÿUUµdÁLX?;O¥úØèµ¨ý3جºèßV3ëc-õ³žm¶¢>ÖS¯üÇ4MC8†¦iÏ3MŠ¢@×u÷yš¦-ËÑbÝb¹_;úÚ¶+éÚ ”¯«ëk'hŵ´uÓ¿­n¼–6zß)ϯ¥Ë¯¥¥·ÑŽkiµúÚŒk©<ì'êlì¿-¿¥î¿­¥ž¬ØþÛù`fffÀ|<ŸŸŸŸŸF£óæ£ÑèüüüüüÑ£GçE™Ÿœœœ?zôè|8ž0ŸN§ þ._ŸN§çEq·+·Ç¼®ën9êyn%æÃáðüÑ£Gç§§§çEqËê/w-ÛÑu}>NÏ=z´êïµl¯–ýK&“󺮻ÿ†B¡e.µ‰D¢àqyäkÓé´ûápx^Ó4÷y•^Gíµ˜úY©nÎÏ×WçZ]?S7K=ÖªúY­¾Túþ ‡Ãó¡Ph>™L·B¡‚m–ª›µ¼-­Jõq1×ÊùùÚ?ƒÍª‹r[Í®µÔÏZ¶ÙÊúXéu•꣟®ëne9‹}ñsh鬔k§ü[-õu%];ýJÕCÖ×öjÕµ´uSn«[¯¥ÞwòZº2ðZZzíº–V«¯\Kå¹a?Q÷`ÿmùí´£ÿ¶–z²RûoWD@%·Ãá‚ÇTU-øðø+ƒü0Ê–L&ç5M+x}8v+¶$O¼ÿ÷â Yës+PPAd¥‘«§BÊ ~-¿×²½ZöO7y”¿¿wñ>&‰yEQÊž[ùápx^Q”‚ÛJ¯£öZLý¬T7ççë«s­®Ÿ‹©›¥kUý¬V_*}ÿD£Q÷Ü©ªZµnÖò~´´*ÕÇÅ\+ççkÿ 6«.Êm5»>ÖR?kÙf-ûØh}¬ôºJõѯ¸ƒ§ÔƒÿüÒÒZ)×Nù·Z;VʵӯTg,ëk{µêZÚŽº)·Õ­×ÒFï;y-]x--½v]K«Õ×F®¥þ÷`?Qw`ÿmùí´£ÿ¶–z²RûoWDÊ/˲Üé’ªªîÿÇ)˜Ž[ü\Û¶aYV­Zåþ´{ÊQqå?µüÞ,ªªbrrº®##/8¦¥ö±xÚ´¢(9gýSÛüÓæª½ŽÚg1õ³ëfqUªî-Uý¬V_JíŸaH¥R˜žžF<ÇÌÌ ,ËrsG—«›µ¼-Jõ±¯•¥ÊÙˆZê^'ÕÇj¯«TË)õ>¬§íÃkgi+éÚYï±d}]:¼––Ö®ki£÷¯¥Ë¯¥¥µóZZ­¾6r-ØOÔMØ[^»úok©'+±ÿvETJå.VéäÈ<§óbFûÇÛ½k]I×õ•­Ö/˜âóTœKQÓ4$“ID£Ñ‚\‹Õ^Gí³˜úɺÙÔÛ¶¡ªjA]ÖuÝ}m¹ºÙèûQkT«¼V.½FëG¥×UªåhšVr›­j¸Se¼vvž¥¾vVÂúÚ^¼–vŽÅÜw¼–.w¼–v–Fëkµk)À~¢nÂþÛÎÓŠûQ ûë动¨ª Ã0Ü“`YVA$, ¹ `X°€O(‚eYnÄÌqlÚ´©`Ñ1ªlHúg*•ª©!iÛ¶{~äëä¢~€wÁF£PUÕ•PíuÔ>‹©Ÿ¬›­ÑH}‘õZž'ù:ÿâ€ÀºÙèûQkTª¼V¶G£õ£Òë*ÕÇrä©BÛ¶ ö¥¥ÃkgçYêkg%¬¯íÅkiçXÌ}'ÀkérÇkigi´¾V»–ì'ê&ì¿í<­¸º¿^žÜî,…p8 ˲°iÓ&÷ËÖßhÑ4 ¡PPUuAôKUUD£Q º¯×u½#>ªª"‹!™LÖÙmEQÇ100]×Ýã‡kÚ¿H$UUÝ‘Ñh´äså{lܸ±®×ÑÒZLýdÝl]Yë­/²aã?š¦!.häȺ)Ïëgç¨Ty­l_Y©å^W©>V;ñxCCCÐ4 –e!7m ;Õg¥\;ey»¡¾.åµ³–ãÀúÚ>¼–vŽÅÜwÊ}äµtùâµ´³4Z_+]KKa?Qgcÿmçiöýh)ÝX/WåY,Ëróíù-Žã¸SŠÇ®ëXµjŽ=º O¦mÛP¥c?첌Åû؉ê=ž¦i"‘H NÃ4Í–¿Ž–Öbê'ëfó,¶¾,U½¦Ö*Uy­\zxÝ“ÇNUU¦(éËýÚé/g'××¥¾vÖ»]Ö×ö൴s4rTJعs'Þóž÷´»‹vøða>|xYtÊ/—ï™ZÏÉáÇ`Yœ»J²Ù,¦¦¦°wï^ìØ±£¦×LNNbãÆ8vìX»‹¿(+ñšÓéj9'û÷ïÇc=†‹.ºhÙ·më­Ÿ–eáÖ[oÅ%—\‚W¿úÕí.þ¢¬¤Ït·¨vNŽ?Žx‡Z•zëç¾ð¼â¯èúÏÛ¶§–srøðaüøÇ?Æ}÷ÝÇ€J Ÿÿüç;ú³Ðé×’nø^èôúÞŠ~Û®¨¬^½£££í.Æ¢! " ¶»(‹–Íf—Å9©u?ÆÆÆ8 ¦„7â¼óÎ[QŸ…N·¿g²Ùl»‹Ú‘N9å”eñ™Îd2Èd2Ëb_–Ë÷L­çD>o9›››ÃŽ;°{÷nôôôÔüºK/½ãããí.þ¢­ÄkN§«õœ¬„¶m#õóœsÎÁ 7ܰ,> +í3Ý j='###í.jË5R?_õªW-‹k'Û¶‡mÛÅÛ¸qcG:ýZÒ ß ^ß[Ѷíú€J=):Y'ðêµ2Ëi?ÚåÒK/íúѵÒrù,ð{†¤åríìä†o½–Ëgz9“Å2 }}}˜E&“Áìì,²Ù,z{{—M¬„לγœÎÉb­ôúÉÏtçY.ç¤Vrý\Ní¨åò™^Nç„JëôkI7|—K}¯G×Tˆˆˆˆˆ:ÑÜÜöìÙÈår¸ýöÛ1;;»ì;„ˆºë'Qçbý$"¢NÆ€ Q“vÁöíÛ;~„ÑJÀúIÔ¹X?‰ˆ¨ÓÔîu:ÎP!""""j±•˜[˜¨[°~u.ÖO""ê4œ¡BDDDDDDDDDDDT*DDDDDDDDDDDDU0 BDDDDDDDDDDDT*DDDDDDDDDDDDU0 BDDDDDDDDDDDT*DDDDDDDDDDDDU0 BDDDDDDDDDDDT*DDDDDDDDDDDDU0 BDDDDDDDDDDDT*DDDDDDDDDDDDU0 BDDDDDDDDDDDT*DDDDDDDDDDDDUœÜŽ7ÍårÈår€`0Xòo@@ ÝLJhE©T7ýgý$Zz¬ŸDDDDDDÔjì·%ªlÉ*ccc˜˜˜@?r¹zzzpóÍ7£§§C?8€ÑÑQ ·û­•ê&ÖO¢6bý$"""""¢Vc¿-QuKPÉårسgöîÝ‹¾¾>€®ë˜˜˜ÀöíÛ166†Ý»w# "›ÍbëÖ­ƒŒxµXµº €õ“¨MX?‰ˆˆˆˆˆ¨ÕØoKT›%]C%—Ë! º•6oÞŒÙÙYd2ôööºSÉúúúÐ×ׇL&ÓîcD´ìUª›X?‰Úˆõ“ˆˆˆˆˆˆZý¶DµYÒ€J0Äøø¸ûûÜܦ¦¦ÍfD4{{{Ýœ}å:t###K¹D®‘‘ìÛ·¯ÝÅX´Ju@Ãõsß¾}k÷îÑ ”Íf122‚#GŽ´»(‹ÖŠúyäÈŒŒŒ`bb¢Ý»G+Lðä“O¶»(DDDDD”×Ê~Ûl6ÛîÝ£hll¬%ý¶KPñ›ššr§† »#mýj™2¶qãÆ‚ÊN´”ÆÇDZeË–v£©Šë&€†ëç–-[0::Úî]¢¨¯¯ãããX¿~}»‹ÒTͪŸë×¯Çøø8óÝR[ cttgŸ}v»‹BDDDDD%4»ßÖ?ë…h©ŒŽŽ¶¤ßvÉ¥Ÿ››ÃŽ;Ëå°k×.wªXooï‚çær9V8¢%R®n¬ŸDíÆúIDDDDDD­Æ~[¢êž¡277‡L&S÷”­mÛ¶!À4Í‚¡¾¾¾ÓÄfgg¹°Ñ)W7ÖO¢vcý$"""""¢Vc¿-Qu ÍPÞ={ˆüzÛ·oÇÎ;±{÷ɉ‰ ÌÍÍaóæÍ‹ƒAw‘£`0ˆl6‹\.‡ë¯¿¾ÝLjhÙ«T7Y?‰Ú‹õ“ˆˆˆˆˆˆZý¶Dµ©; 255…‰‰ wÝ’={ö¸ùô¶mÛ†;î¸===%_›ËåËå,"¿}ûvŒŽŽbtt;vì@?8€ÑÑѲÛ"¢æ©V7°~µ ë'µûm‰jSw@%“É`xxÁ`° Z¹}ûvÜ~ûí8pàÀ‚t$’¬|åÈíær9wä-µ^µº °~µ ë'µûm‰j³ä‹ÒWà IÔ¹X?‰:ë'µï;‰¨ƒAÜtÓM räMLL —Ë¡¿¿¿ÝûDDDDDÔ²Ù,fggÑÛÛ[q­A"Zz¬ŸD‹õ“ˆˆ:Uݕ͛7ãÀغu+fgg¡ë:fgg™;ˆˆˆˆ(oçÎÈd2ÈårƒØµkW»‹ED`ý$êd¬ŸDDÔÉê¨LLL¸‹Ðg2wVJ0d0…ˆˆˆˆbdíí·ßŽ;î¸===ÈårÐuÃÃÃiKÔf¬ŸD‹õ“ˆˆ:]Ý•\.‡‰‰ ìÝ»ÃÃÃí.?QÇÉårvÉ\Ó³³³í.ÑŠÇúIÔ¹X?‰ˆ¨ÓÕP ‡Ã˜››ÃØØ‚Áà‚¿—zŒˆˆˆˆh%Ù¼y36oÞŒ¹¹98p™L}}}UÛʇÂÈÈÆÇÇÛ½ ´ŒŒàСCËþž®Ñú¹oß>Àèèh»wV˜l6‹±±1:t¨ÝEi¹Fêç‘#G022‚Í›7sà/-¹‰‰ LLLàâ‹/nwQˆh‰ÔP1 €={ö,øûƒ>Øî}"""""ê¹\{öìA.—ÃæÍ›«>ãÆ ¦PÛŒcll¬ÝÅX2õÖÏ-[¶0˜BmÑ×ׇññqŒŒŒ´»(K¦žú¹~ýz^;©m†‡‡ÉdÚ]"Z"uTFGGÙˆ$""""ªì›››ÃÖ­[8z–¨C°~u.ÖO""êT'-æÅÙl™LÙl¶ÝûADDDDÔ1&&& fs÷ôô ¯¯¹\®ÝE#ZñX?‰:ë'uº†*¸âŠ+°uëVŒŒŒ`ëÖ­Ðu""""¢¼‰‰ ÌÍÍæææÍfÝÅu‰¨½X?‰:ë'u²ºS~e2Œatt×_=zzzÜÜ–Û¶mÃ=÷ÜÓî}"""""j«ááaLMM¹iJ8€ë¯¿žéJˆ:ë'Qçbý$"¢NWw@ejj ÃÃó@ €]»v!“É “É  ¶{¿ˆˆˆˆˆÚj||Ùl³³³]KÔAX?‰:ë'u²º*³³³èéé)ù·r­D}}}í.•ÁúIÔ¹X?‰ˆ¨SÕ½†J0ÄÔÔÔ‚õR&&&ËåÐßßßî}""""""""""""jªºg¨ #›ÍbëÖ­èëëCoo/r¹fgg1::ÊY*DDDDDDDDDDD´ìÔP€]»vaxx™L³³³Ø¼y³»@=ÑrSwÊ/Èd2˜˜˜ÀöíÛ1:: 0 sssíÞ"""""""""""Z!b±¥{¯º*Ùl###d2lÛ¶méJNDDDDDDDDDDD]ŶËjζH,]ÙëNùuûí·cxx»vír ƒ¸ùæ›±uëVd2ƒÁªÛ™››Ãìì,€ûX.—C.—+x^?S‰-¡Ru`ý$꬟DDDDDDÔjì·¥V³mÀ4M[Üv‰4MÃÿüÏÓ°í' ªjËË^w@%—Ë-èÈ€žžžº*aঠ€±±1LMMúÑÂò=òÈ#M?uTúûû111ááá‚ÀÊÔÔ²ÙlÉ`‹ßÄÄ2™ ¦¦¦°}ûö‚¿ÍÍͱ"µI¥º °~µë'µûm©’H$‚ÉÉI(ŠÒ”í™fù¿†T*…D"UU Þwhh¦iBUU¤Ói(Š‚ï~Wʼn{ñÑŠ×Û¶ Ã0ðŸÿùŸjêq¨; ²}ûvär9èºîV ÙÙYd³YìÚµ«j@¥¿¿@`Á1@,vïO%FDK§RÝX?‰Ú‰õ“ˆˆˆˆˆˆZý¶T‰iš°, º®/z[ºîÍRñO@q‰D¦ibrrªª"‹¹©½d effŽãw~úӟ¶m˜¦‰X,UUñ»¿û»M?u/J»víÂÞ½{Ñ×ׇ¾¾>\ýõ0MÃÃÃU_Û×ׇ`0ˆÞÞÞ‚Ççææ;wîÄ%—\‚+®¸U·wäÈŒ5ýÀÕbll û÷ïow1š¢\ݯŸû÷ï¯éyDÍ–Ëå066†cÇŽµ»(MÑìúyìØ1Œ!“É´{×hÊd2H¥R8~üx»‹BDDDDD>­ê·-78ZËq7}[3¶ÕÌríÅÕWÁ*2—¦inz±h4 n0%BQ”‚ôcÉ$ð†7Åàà R©Òé4þôOÿ´%ý¶uÏP‘d0¥Yr¹‚Á ¶oߎññqd2ìØ±@ âT²ÓO?Sͨm‚Á >Üîb´\£õsÆ èïïowñiêííE0„U-!ç2ÐHý\½z5‚Á`ÕY¥D­Ð×ׇ'žx¢ÝE!""""¢,¶ß¶Ôà@j=Ã0`š&ÂápÕçLNNVÜV³úWÇÁàà Î8ã19ùî¿ÿG˜šz[Û¶‘N§ ^£( âñ8 @UâŒc–%¹¿ï¾›ðá+nfõêÕøÁ~ÐôãZÓ •‰‰ lݺ{öìiYD±¯¯¯ _0Äõ×__uôìgœÁ€ µM0Ć Ú]Œ–k´~nذ¡©W¢Zõôô  bõêÕí.JË5R?P¡v ¸ôÒKqÊ)§´»(DDDDDTƒÅöÛöôô´{Vœ¡¡!$ ض]ñy2W5ò9VÇq_‹Å …pÕUWá7~ãM¸ûH$088ˆD"Q1°ã8â§ÔãðÚמ]º¿÷õõµ¤ß¶¦€Êðð0n¾ùfìÙ³###C6›mZAr¹Ü‚í±²uÖO¢ÎÅúIDDDDDD­ÄûÎîcYÒé4TU-›®K:üÏq©T ‘HëÖ­+xîÛÞö5<ðÀiu—%•Ja``¼^oxÃZ|âw\`¾’Jñ!M††ÄŒ•Vªy •žžlÞ¼»víÂøø8úûû111Ñ´àŠœ*&sòÍÍÍajjŠ£g‰:ë'Qçbý$"""""¢Vâ}gw°mÛ]”]×uw’H$‚T*@¤ÕŠÅbîÿÃá04MC,ƒmÛn0Ŷmèº^03åá‡ßˆƒ/,ù¾r!øX,†H$RðwÓ41==ééi$“I"u—¦<²““i„B¡‚5Q¤âI¥%aea:°}û®ÆƒžÑÔãÜð*›7oÆæÍ›Ùl·ß~;nºé&|âŸh(ÅÏðð0²Ù,¶nÝŠ@ €`xx¸¦…µX?‰:ë'µï;—Ž ”[öIJ,8Ž]×üm``Š¢¸Á@¬?’J¥`Û6B¡»°; ÉdÒ]¼^>/CÓ4¤R©‚™+kÖ¬ÁsÏ-œ¡’H$Ür…B!X–Û¶á8,(ÊÂ5Zt]?R)±ÏG–Þ_EñRz…B•]4*¶[ûe8å”ûp÷Ý/"‰,¦…ë¿(ŠrÈô]Òà`áïþ ’  8Ž˜½òö·ßç¾Æ4Müʯ¼X&LÓ€ðì…³{:Çoê9ª9åWñ¬“L&³`á!\!""""""""""¢Úéº7cÃ/•J!ºiºB¡óQ‰7Þ¸¶ê¶åke@E+•KËÇ¿¾ O&oÀÐ(g:-V’·íÂ5Q,K¬ƒ"×L™žÁÿ¬”Âr‰×ÈØL*%“Û=qbu¾<¢L¿øÅPÕ­îë ßâŠßeðÆq¼â9œþùM=G5ÍPéííE&“qŸššƒA÷±¹¹9d³Yôöö6µ€DDDDDDDDDDDËÝoÿö·K¦üJ¥R‡ÃîŒEQÜÅægfÖ–Ü–ã,œ xɶ½"¦Yø°pX=ŠgœØ¶øI¥¼ÿËuVü1›r©Ìü³JäsÂa@™››ƒªF`YEÌÔyßû^‡gžy©T CCCøñ e# €ìØq±X †aàÅ›» =Pc@eóæÍÈårعs'¦¦¦`‚Á ;#ennccc\œˆˆˆˆˆˆˆˆˆˆˆ¨±X Ù¬˜áOû‹Å …B¢Ñ¨»0}©eQdP鲄ˆa®;âoÿ{Ê$Ñhá,8‘YÄEü_Q¼Y*åR™Éçûß[Q€[nyÁà­€cÇ |ÿûGðÓŸþñx†a`÷îÕ0 °zõjh¯ p€{ï½==¯ƒªª8é¤+š~žj ¨Ü|óÍÈd2رcz{{1:: @¤þºâŠ+Éd°{÷ˆˆˆˆˆˆˆˆˆh¹2M¶mãûß?ozÓï¹ÇqÜt_õÒ4È(lI¥R%¯WUÐ(„‘AX‘‘³V4M¼ÞP)~+ÿÒ+²œþ2Ü|óN¼üåWanî6n|33óX½: Ó4 …pâDÉd“““8tèþׇ¸ínÃ7¿ù&|à¿Sr}—f¨y •¾¾>˜%Ž~?ÆÇÇ ÒËåËå€íe¢ÃúIÔ¹X?‰¨›XVaj«F˜¦ ]׋iÈfß„|d'ôPUÕMíÕH¹l[Tü±UUaÛ66mŠø“åÿ’rûzAUÏ3 HñÿˆõVd F’³Y¤DB¤ùÒu@Q,\uÕ0¾ÿýoàá‡Æ9çü!þéŸîÆ>p%Âá0"‘ ã3PQè³Îú!^õÈ8:/N½ˆàNQþrk¶,VÍ•rzzzxq#""""*266†‰‰ ô÷÷#—Ë¡§§7ß|³›6—ˆÚ‡õ“¨s±~Q·‰Åë¼wòÓ@EišH§ÓH¥€µk×âþç娏Ña˜žž®¸¹¨{)º.þæúÈàÌ'>ñZ|ä#â1ùzÛöf˜˜fù€Š ˆˆ…âE°DQÄóC!o=]/,‡Ü^qye@ç‹_| üà4'‚w¾óD£âµ¦y#N9eCþ½|ö³/â´ÓÄß>ô¡aãÇ€„Å.ÿ€;3&AKÔ”ò €»†ÊÈÈvìØl6Ûšu¹\.‡={öàæ›oÆøø8LÓÄÜÜ&&&Ú]4¢õ“¨s±~Q7*•R«˜a*xa„išPÅ tÜ|sŸýìV$“I¤Óé’³SŠƒ2pQJ8ìÍ‘,ËÂ¥—žpƒþ#º.f§Tʘ¥(Þ~›¦÷úDBKR)ñ¾^§° ÅšdRq¾ñÞûÞ÷üÑßþÖ?²€(¿i¿ýÛÿÞ´ó,ÕPA&“A__r¹¶mÛæN¿$"""""O.—C0D__ŸûØæÍ›1;;Ûx¬ŸD‹õ“ˆºQµåMÇA"‘pg¤Àà x\Q ¬‘rÆüº$Ê‚…è%ÛöÖ91Œ…k”ø…B"¸áýÂÿû_Ç/Ùã$䌹MEi³üä)òïÞþ‰ý ÓbæŽÜ®œÁ‹ÅJ¥Ÿ?ù“ãškŽà¹ç2øàW»¯‘3`î¿ÿÍn€GÓ47¥˜aägÈ|\ÀšÝk ^{÷Ý—7ý|×PÉd2ÈårØ»w/FGG±wï^ôöör„Q Á`ãããîïsss˜ššB ¨øºC‡add¤Ýŧjddûöíkw1Z®Ñú¹oß>Œµ»ø´e³YŒŒŒàСCí.JË5R?9‚‘‘öQQ[LLL`ll O>ùd»‹BmdY•g©Äb1„ÃaXEy®,ËÂää$æçç¡ç§˜È AQÌ€\øSmÉÍiZaðBRUo抜9"ž¯áŒ3®)XT^Îþ°íÂâ%Ûö¥÷?xkŸèºH}¦ibƉL&½ë]OãÎ;ÿŠ¢àæ›#?e%•Já±ÇîÇ}÷­Çi§}¨ @S&ž]¦§EÙõ5€úùü|A ­I_û •`0X¯róæÍ­)Ñ2255…­[·" bxx¸âs7nÜXБD´”ÆÇDZeË–vcIÕS?·lÙ‚ÑÑÑv™V ¾¾>ŒcãÆí.Ê’ªµ~®_¿ãããUë0Q+ cttgŸ}v»‹BmT)˜bš&lÛF4…æ‹.hÍž· WqÂopÐK›åO³‹ Æà`áó‹0¾ 2Ä,Ëùžñ¸ÄPïõÅ‹ÈË…æ/ÐbÛ¢ ¶-Ê©i…3Yn»íqüìg«pÛmÏáä“veYøÊW¶"$YNʰR4M”׸ °ŽçTä_ o|ã7ùl7aQz"""""Zhnn;vì@.—î]» Û]$"Êcý$ê\¬ŸDÔmB¡…)·lÛF*•B*•BÜ—+˲,(Š‚ûï ¯yÍy ¶å_~p°p±{™ÆJþ]9b1ñ<ËÁYË*œEâ/£œ•"Ÿ y³Pä{Ê^2íVñŒâu[dð£\äÏþì$¼ìe§#|;î¹çlû Ð4 Éd€H–HxÏ/7;Å/pЯÎ?àKm¦(ÀYg5?edÍ3Tˆˆˆˆˆ¨vÛ¶mC €išì "ê0¬ŸD‹õ“ˆº®/L·e†;3E¦óÒ4 Žãàƒü&N?ýµøüç?°`[2áŸ]" ¥^[*í ¶å­ãˆ ‹ bÈÞýï))þ÷÷‹DΊ‘ÏÁ1ûIJ,ضÁÁA|ä#k¡iÀš5k ª*b±LߟâY-Õ¨*`Þ¨çÈ`ÖþúFÔë¢èºŽP(EQ`YR©T>°R˜ZL+Šž„è‹®ö÷}(ìú¶Q¯š*r4"""""ªntt”?DŠõ“¨s±~Q7züñ .¹ä÷wÃ0099¹àyªª"bãÆkð£•N£UœrK>G7äãº.‚þEäGJüë®ø•J ‰À ÒwùgÚøg·Üyç8vì2k ¶¡iâõ‘HŠ¢ cÕªAwFŠxNá,”pØ{ÏÅÒ4ÀzÀ¯Êà.Jß*u/JŸËåÉdÜ”_@×_=zzzZ[R""""""""""¢aY^xáœzêaØös0MªªB-³¢z<‡ão{›˜u24Tøw@EQD¤x†ˆ\ë$ÿZ–ø¿ª.LËåçŸý!gÅøgÈÈ™*’?eؽ÷Þ‹§Ÿ>ÀUÛÔuÀ0UUʯZ?==]°.J1Ç©/­W%ЍˆT_K¤®EéÇÆÆ ë:ÆÆÆÍf‘Íf±sçN\wÝuسgO]o<77çeüŠ6D´´ÊÕM€õ“¨ÝX?‰ˆˆˆˆˆ¨ÕØo[;˲ÐÓó×8õÔˆD"H¥R—È[eY^ðIJD¢ÔâëŠ/e•XØÝû¿ šÈ™&rÝezºôÌÀ[Åq¼T]þÿOOÎJñ—u``þäOÎ(Y^‘vL,0oYàÈB”ˆ«8Nù26"à:…ÐÒY*5TÆÆÆ011]»váž{îÁøø8ÆÇÇqÏ=÷ cll¬® Ša˜˜˜(xlbb[·nÅž={°uëÖ'¢Ö+U7ÖO¢NÀúIDDDDDD­Æ~ÛÚÙ¶uë |ç;çà…Î@:†žŸRâ8Þ:)Šâü“7Šgj¤Ó"L/µ ‚b&ˆø‘kž8Ná –D ¸Äã…3M‘Ì¿îIqPÇq/‘ìïþî|ùËⓟ|ªä1…ضP(UU1==¸œö’À‚à† ì4‹öK†ÿ¤°ÜX j ¨d³YìÙ³7ß|3†‡‡ þÖÓÓã.fFÕmMLL`ÇŽ%ƒ/cccؽ{7ÆÇÇqóÍ7cçÎŒx-‘Ju`ý$j'ÖO""""""j5öÛÖï_ÿõlܸ_|ï{ßg þænÈÔ\€†”[|=ƒ(Þ @NTÕ À†·~‰?(£ªÞú$±Xað&e@¼ÖÿzÃ00äËC¦ªÀ‹/¾ˆ-[þ½½½Ee!•JÁ0 „ÃaضT*…Tñ)EM+\«¥é´? ’Éd Ñ××Wö9Û·oÇÜÜ2™LÅmõ÷÷cxxxÁ¶2™ z{{ }}}èë뫺="jŽru`ý¤ÎfY¢‘²œ±~Q«±ß¶>–eáòËïz×Ëñ¥/]ƒ7½é¼‚TVr†ˆ?(ˆ`ˆœ¡!”ü oWU1 ±]9[Å?ËDÎ\‘©½ü4M^ˆ)ü»ã®sbÝ ‘¾*ßÏaYb!yš°Pha?ˆã8Pò*Ž#^󃼀¡¡!$“I†H$Û¶:®{)3…ýŸÛÃ0L&‹Å`š&Âá0âñ¸»@ýoýÖ5PUàÌ3Ï„ã80 ©TÊ}?IbTá ˆQ«g©ká̘š*@Û·ow%š››sÿ677‡±±1ìÙ³gQ#ÑûúúTÄÙÙÙš¢DÔZ¬ŸÔËÊ/¦VU-?j£’R¹AW ÖO""""""j%Þwò'ßÇ/~q‰„»{ñZ!"}–÷»e‰£þ¸ƒì»)JQÖ ‹¸ÞßåBóòµrý?˲ÜUõ¶ÇÝ“É$‘H$phì^ßûzüò¡_" ¹ ʇB!w›ªªº¯…€3Î8ñxápÉäÂi'¦i²¬Â”_aˆàÐRTT¸iÓš­¦€ ¦È Ã0 \qÅÐuW\q®¸â LMMa÷îÝØ¼ysà ƒ˜ugÁd³Yär9\ýõ­Ùs"ªë'ÀÐP}Ïwœ…¹A«±¬ú#á°hHÔû^Ëë'µÒJ¿ï´mÄã?€/ù˜žžF4-ù\Œ%A–hTôuèº×‡!ÓvézQ?ÈQ¸ Òâùé´—Æ«UU‡ÝY#¶A&“Y0‹drrº®ãå/9Žm:†ýŸÛ]× …N§ g—îõþ…ìË ‡ÃîBõÞA€˜-Ò¢à†Øy,\„>œß8¹ž'ŽŽ"#“ÉàÀD…j4ÍW©íïØ±ýýý8pàFGGÑÓÓÓš='¢º°~®l¦¹p’Z_Wù¦Y¹¡àW<£Å0ŒüÖhmXX?‰ˆJ€¸‘Òá¦L(ƒwc7YëF‰ˆˆˆV¦•|ßiš&†‡gñÅ/^_¼ÀéîÌâ@ƒ?~aÛâ÷XÌ›U28(þõ/?bÛbAû™@ë…˜¡’'×XI¥€ü["–O"ˈ¾UUaÛ6,ËÂÖ­[qï½ i–ÜŸø…q\¸íBüèÉùÞ«|ÄÄ7q¥,Ã×Aã–-±†JÙHjæ`aÀF0àmÍ»º*ÐÓӃ͛7/˜’Ëå011QsÚ¯R É# "—Ë!¬¨icD¢TÝX?©±uJÂaqá¯umP©%xã8†††ðôÓ‘‘kpÛm·!ù t]‡¢(îBiË ë'Q lˆ”6Ä œ0‘3åHµ€ˆ- -ÁFDDDÔmØo+RhÉÔ^ªªâ ¿ E9žžc°íÓÝ>˃Beü •ÁEñ2iÈ”]Ñh龕hÔ·>Ê% ÿ.Ó‚mÚ´ “““°,kÁ R]סªª;ÈôÌ3ÿo}ë¹ ¶¥iš˜u2@^÷º×5í˜ù×]) BÌTi•r•ÍŠ©; RN.—[ô:*VD…$êV¬Ÿ+—\DͶk¬(ŠhTXVí³M„©ö|¹š®ëˆÇŒñqà§?}?ùÉ4Eã8ÀUW]ÕîC·dX?‰ˆò䢗aˆ=óÛù¿é7XÓùÇuˆsÉúÞ†ˆˆˆh¥Y.÷–%~ü³DŠ¥ò«ÇÇãqÄb1(Ê}?~ZÅA r]÷ÒzÅã…iÔ}Kˆr†øI}Hÿ̰>ˆÞ^¶m#N#‹¹ ÑË™!“““îÌÓ³a’åÚ¸q¤k†˜o!ÝxñNÚùŸëV¥”ÙnÀ\ÛªAÍk¨ÑòQïÂï²±QOÚ/E‡zÖD ‡ÅHŽ|»¥D¹ Äb1†P(„h4ŠË/¿Ï?¿¯{ÝV77¨¢(ˆÇã¸ï¾û–øÈQC,ˆÙ$õˆ½Æ°ÞL9h/ q—† ØðR)„˜ðF¶Õ[""""ê*2…V%rH8ÆÌÌ à½ï=Í ’Hš¶00#ûNd¶õP¨t?‰mçg´¬É?P”BýsŸë…®ë°òÓ^B¡ÛF19Y˜Ã¶ê`XÙæmâz´ápØý)©Î´ð5sP6P³ñ¡M;TˆˆV j ‡Rü£+j!g´Ô³X¼aˆ×ȵWLÓD$A$ÁÐÐLÓ„®ëH§Óîú/þâ*¤R‰ï …ÜÅÓˆˆ¨Ã_ ”¾Á²}ÏAF7Mzþo)x#Þf $òµò_%ÿ¸’]…7]Éü6Í|Y"k° ¡p­'ÿw'ÿ7Y""""ê*Õ¶m#•R`Yð Þ}#þ¬–U8hU×½à‰ÌD®(Þû•ËÊ¡iÀììA¤ÿ¢Íj‰2˜ù’X,UU}k·hîÌ”R}ª*R‰U?hZ Ã0 ¬¥9Q%„ÖÌNA¾ü¥öAiM@¥i)¿ˆˆ¨{Ô»À¼ªŠ ~*UyJl±Z×N)~/¹ØY"‘€¦iPUŽãT\hž±"¢. ×6‚p„!rIbf‰ê{~ Þ¬ùoâF3™ß–ŠÂ…å§}ÿ×ó?•hð5“ùí9¾ŸAˆÙ-f¾üƒù²«¾ÇZuƒHDDDDMåz”’H$ ëº»¨¼¦yýŽD"@:íý^¼m¹~Šì§Ðu/¸RÎÏ~v/&&^…ó|Ÿùô©€wy]×½µO|Šg¥+κUøÇü¿µ]j>®bÝ1ŠA´£e{»Ž”ð‹¦ëYÃ8ÜÔÍÖPÉd2Èd2Ÿ37ׂ„dDDÔrH­k›8NcA˜d²zÊ/Çq°iÓ&$“Ièz_ýê§05õ""‘?G8^˜w³ˆÜ*O#"¢v“³:ˆ@ˆ–ÿ= oæH"ˆ"¿Ó-ˆàˆ\4^êáÍ2™®íí+R fº„Qþ&O\¢¾òÁWî._ƒ¥ÞY¥DDDDÝÊ4EP¤Ô€QÛ¶ñÿÁ}÷Ýì®{ò-¨^<³¥Tû)}!þçV›-rãkñWÕy1ÿF¢,r‘ù¦gàb€PúTEqמ)™ö+…¦pªRµG×6= RSʯ\.‡l6[ñ'—Ë! .á!j/Û¶a×ÛÃLÔ| ëY$ E©ï½ä‚jþ…×,˦M›‰Dà8LÓÄàà Âá0"‘b1?ÿù‹8ë¬?Àüü<’Éê½SŠ"~R)/Uu bªÿ4DàBƒHÑ%¯I:Ä –œub ¢È…ä¥4š?#d2_¾RBð=¥îeýiÉóå—ë±l‚¸yl£âµÓb1qM÷?nYâæÿþç’ö–ˆˆˆ¨ÅD¯ÒÁO}ê«8qâ nš/Ùâo7U™R2Xµ~˜X,†?ú£Gð­§¿%Ú›)Ñ÷Ç …ʯK²X*š¶ŽŠ¢(Ð4­p†J¨ñíÕ¥Ìñ}ð²qƃg4õ­jš¡rýõ×£¿¿}}}Ktˆ:G"‘@(‚êû6´m›6mB(•W^Ùî"Ò 70=Zûóå´Óª ”•PÏó€xE"‘Âá0 Ã@<‡eY€®ëÐuñxñxŠ’Äüü,ÖÕ<ƒF×Åû¨j}³nˆˆ¨…lß /íV¥u*¼‘qu\ך¦Ú ¿âuWütˆ@Š o=ùxb‹\ËEÍÿBá f•÷O¥Ä }4Z˜B¢˜e‰”ɤø¿®{Á’hÔ ¤Ø¶¸®†¸VÇãb”æ—¾t%ÞýîCm8DDDDK#m©â4å‰Dÿò/¿†+¯<@aª/ÿs‡†DPE®©R¼ÉIñœZû'R©TUÅ“OnÄÛO[·\þ|þeŸ‡Ö µ8"¡Â[/° Çãï<òo[oš²]®•XÂ[îDð’æN©) b²Ù,ÆÇÇÝÇÆÆÆ0<<Œ@ Ðä#@Ô~rÔ¼¦iî?íì69ž:€ªVîX)æ8¢SƲ¼œŸõ¼W½ÏߺõIüó?›0MŠ¢ ™L" •LåµvíZ<öØcîH‘Z±˜èÒõú>DDÔD2€"‹7á¥Ò’k§tsZ¬J×Ù8¼8þ›9Õ÷÷üßÒ3sbùcË?oF<5‘€›¯;ò'$ÞuÎ4½xÃðnäe›@U½íض÷øà Ø¦ †|ÎÐhœ}öqæ™Ì<@DDDË—iz3Oü]†aàÒK£ø›¿¿«ªh#ÍÌ>OÓ û,J­«ªµ¯CkYÂá0R)àñ“VáÿÍÿÆù¿{>~ˆ¶î øg¥È Ê"g€;޳0›ÿ}tx³Ð›ÉðTس4ùÄjJùUÊž={Ëå–¤DKÅ4MÄb1Äb1¤ÓiLOOczz©T †aÀq†T*Õº©vDu²¬úrž+JõÜåԾ抃üà¸óÎ;±wï^üú¯ÿ5ÒétÅEåP9ï¼óêŽÈ7©6§T!"ZÑ ˆTW›à­“‡7m¹¯uUbdœ¼>[60ôjÀx‰‰ÇS°.Ä"@ì`Ó+EÀÃ4EÐÃúú `àr •7ãɉÓiode2é *°,q³ ‰€ŠüW×ÅHI·3ÀX&ztÀ Í^%"""ê6rðŠœ± ˆ †¦i°m/¥x,æµb1ïõþtaþàŒ_­™AǪªPUÑ(ð™¾S …pÚ†ÓZ;;ÅÔk.’Lù%Ó¥¡xzÍKÛë8b ¶ôÝ¥ëªi† Ñr&SzÉ@I<wÓâË`rr±XÌ}n:ö¾ˆ:@=ÁEvc U8²1Q.°"§uâÜsßËšÁ+_yN?ý¨êê‚Ôy¥¬^½Ï?_zÊl-R).NODÔ6aˆ5PäL ©›g¥ÔÀq¼ ˆœ ˆÿË!–åNTïº=9)ž3s/ÿ'Àùw@¹€ ¨6 ¾'ëû@øW!f³dè@È,<¶þk³ªñ?ô»€é›%qÓ,ojCçIΊÓ/zõ¶ûµœ¦‰>„1èÄ0Œ|¦/¥¸ Š'¨‘¯¼ÙÄ¥¶_®_#æëq§tcEêæo¯7iazÛ¶‘J¥*‚RA•ÅÌR1M1uH¦jÑÜWgú–E`@…V$ÇqJ¥`Y,ËB,C4E:.Ùá«iâñ¸p‘,ËÂÛÞö¶vï-#þŽ˜ZMO×ÿ²aP+¹øZ¥²Y–…H$Û¶‡¡ªrþA•¼ûÝ¿ÀOzoZm=ä´Û%¸~Q±ÄßÒÌ´o ‘÷¼†!®9‰„¸þ†Ø—³ELSÌ()wC=?1cD”dþ8Z€úuñ˜T™:mb­âÆ7‘)Ç4ñ¸¢Ñ ùíîË??œÿ1Šþ¯åßû^ñ¾kSkÛ}˜‰ˆˆˆ–Ô?þã>8Žƒh4ê¦QµmÑ–K¥bÕ4o‹LÑZL®õ*ÉtXš¦¹A‡p8ŒD"Q˜ÍCÆ" xë¶B ¢=4mazMÓL& ûV‹ÛÀrO£ý6–%:Œ¦§}#™œ“?i ¨5ßÐÐÂá0b±B¡¦§§aFÕ^š¦A+ª”{m©Éê]`p˪ÿuÌäˆFECB%å( 9 !BÓ4¨ªêÎfÑ´ÒÓ_K¹õÖ-ˆF·¨=8RœÇ´Þ`•!oªjýNmâb–Â4½AŽ#®9CCb¶‰Lï ª"`’J‰å€C¹NYMYbx7´Å3zäñ—÷Ù3E+ð‚,2H"ײÑK¼?à.ú›úÑ!lÀ†vz"""¢–‘³J’IÑÖûÞ÷ugUض—6Õ²D?ˆiGE´ Åïº^=“‡‘oTjš†ÉÉI·O1™,jüÉ6µ xhU@¥à€4ç},ËÂàà Òé´Èü£aᬗ(jÞØ¶8A2mŠ8€ ;Àl¿’ïDješ´¼š*¹\cccMMM!“É<6::ÚòB5ÂqÄb1¤R)躎p8ìÎ6©u=”FfÕC+êOwÕHA޲¨e]”p¸óÎ[ñ[¿õ?xÍkþÓÓƒn£@æÇ,N…çŸöZœ¥ñxmÏżN+]_8—ˆ¨Ýæææ0;;‹@ Ðî¢Ô&Ñ©/g†!F°Mbá3 Þ(³.š™’Jy×)yí•ÿ=m"á &ƒä=š®ŽH”ÍÉt«Ó3Hò\èçF^ϹÌ_]º®~­ ¬ŸDÔ*²¨ªÀk^ó >þñ_â–[BîštþY*r°g©®ÃZú,"ù”¡P¶m#‰¸k”$ƒ !ˆÙÆ­RèPàµí¤ë:fff¼¾! ¥S‰É™íåú¾ Cü8Ž×¯æê çêrËÂênhú¡«) ÍfÝÇ‚Á ¥§®‰DÜ‘ôápáp–eÕ½ŠiŠŸâQý'Nœh÷.Ò2“JÕ8šÞ"h““bªÍ‘¹€hÔû ¶'ÅÛ­7(EDÔ*ýýýF___»‹âñß”Ùðf¤äÓ]ÁÌ?–†7:M‡¸I Aܨ$ F¯uX0%ßÿƒƒ" ¿n·Ph:í]/£Qq-ó¯cI+OGÖO"ˆö¹\»IJZiX?‰¨Õ‚ÁÃøÞ÷vò,lÛvƒ;Ù¶½ÁÔ2Ý«ü)ráyù<9¸[®3+©úE£ÑÊ3Tüßû2µîRPáÝ4HQ Â’9ÄL”O„7K¥X#:ò~e‰ÔPÃÎ;Ýÿ_rÉ%?z-‰ø‰*ôå¤R) `Ó¦MÐ4 ñxîa˜žžF:Æôô´P‘t]_ðeV Ç7âÅ/ýÁ~€óÏ?¿Ý‡Ž–‰DÂ[Ô¬V2UIë‚`E*•‚aˆÅbîl®p8Œh4ŠÕ«W»Ï‹ÇkK-V\žFR¤ÈEækÝ ô4\"¢vèëëC0Doooͯ9räÈ‚u ›j(ÿo b!s ^¾d rÞähþGÎNYBÅßõ©”¸f:Ž˜i"¯ƒƒâz£ib$a(Ä‹õÃþýûÛ]Œ%ÑHýÜ¿?&&&Ú]têr–å p*Õ~7MÑ—$Ÿ“H_ùÊÏqãÿŽGùE»‹¿$ê­ŸÇŽÃØØØ‚5~‰–B&“A*•ÂñãÇÛ]*!)Ý?¿cÇ |íkÿáf¯‘süÂáêë›ëºø®vã–…T*åä‡Ã ‚'ªªÖ>È[Eí ¸7C"¨²ñx¼ò ÷‰(}ßQî¤Ub`ISÍ‹Òïܹ·ß~{Aš¤`0ˆ]»vabbSSSؽ{÷Ò•œ–­RuFæN•QÞÉÉIpsªªZw@¯¦Êí ‰Nd™NHºüòËÛ}ȨCù;uꡪµ¯‡"GOÄãâf«þ)¬2`¡(b±4MsëS,C2¿€‰LÝ%_‰ˆ4)ÕÊæg¢ÕSUC¡ÆErD2Q·9ýôÓ 6{Rº ïfCŽx“³OqUíúSåû¿Q–%%þ¼\ÃÎ0Ä5+÷…Ä,¹ö‰\0¾8ï5Õ. âðáÃí.FÇÚ°aúûûÛ] ZE›Ú²Äw˜%¿óñ}hÛb6Ý7ž…_ûµ>Ü}÷‡Û]ôŽ´zõjƒA.^OmÐ×ׇ'žx¢ÝE¡2J­çzäÈÜ{ïÍn`CfǨw]ZÿÚ±€XCDÓ4†ÉÉI -è]‹p”UjÐkbàÕ"×QÑu½z¿«’¯$Î.iâ4òÞ§žjÚ¶¤š*ÙlØ»wï‚)—@£££èííÅM7Ý„½{÷6\˜\.·`¡ûþþ~ôôô4}Ç©sÉtBŽcAUU$ wF‰¢(H—X´ž`Šü²¬7åW*%ÇòFÀ‡Ãa¬ZµªÝ‡lI°~6¦xA³jÒi/×{-kEñ®3µ^£ý£|UøÛ¿ý.|ð÷199é^ðÇ);jBUk[ø½¸ªÊ×UÚ¯â}PUQç’Éò ›R3XB¡••õ“hù8ãŒ3ZPD@E…¸Q² nÒùß—0á8^Ð\UÅÀËòRRjš\,T\Säõ4÷n^‹Ód2€²8Á`#¼+ذaSQYÅv2H¬ë¢}/ÓF"¢m+×5òHÙ¶7 HèÓ4àŽ;N‚¢lÀ{ßûy¿Úî]í82 BÔ@—^z)Ž;Ö\7ÞwÊàµüžÄ`ížžž‚þŽpß¿õf½mS@¤óŠÅb˜œœ„eY‹Ï椡u©vË-@o£ò¬õjEÎÔ­Iâ>$¹È}©å­_û¿ã‹|ƒB5Tn¿ývƒÁŠÇíÛ·Ã0 d³Ù†™ccc˜šš*xl||œÆ$Î?üýxè¡? ÓÓÓM{zg¦H²ÓVF­EXÅYgÕîö$X?ë'?'õ¬o ÿhˆZ^‹Å01ñzüå_þb±Oà_ÿõlØð^LOO4&E)¸ðû˜D£Ú,šÁÁÂ Š¦5äkõ¬-SËÚ+Ë ë'ÕL~o›ð¦ô;ðŒ\ìÍL2€â_ •× E#±å ¯?¨âÇ  µƒ˜Õíµ‡ /bš^ D×E;8ò‚Åòy2ÀâDTjÖwq;[¾çYgl÷a ¢¬ï;ezEUõ*†aà¯Øµà¹á°ø®®7]y8,fe¨ªŽ¡¡!·EUÕÆf§#_d€£¬r}&¡Å½ŸmÛ^ÿ’ 1˦ìÁƒ¸/±±¸5Pbù÷)ñ^³g…Þ{îšø9­9åW±ááaÌÍÍ<0;;Ûpaæææ:¾"RëØ¶ÃßǑ#ÌÌÌ ‘H¤™k–h‹,È—ÈI+ífžõ³~Ž#n ’5vNÉ€ˆ¼ˆ×Â?ÒBæc.þlÚ¶X,æ^ÐÖ®]‹¿þë?ŵ×þ›Íbh(ËZþw³ÔÏ#GŽ`dd¤¦zLÔlÓO>Ùî¢,™ññqŒŽŽ¶»bô— `^j/â&MÏ?Ö„q,†!‹·,ÑA‰ˆÊM›ÄïræLB&ª[ÇÔOªKµ¶²\¿dÓ&‘?‘í]ÃðÒn%“ÞìnÛ¿§Ó¢}›Lzpª*¾¯ŠÇùÉõM¨uX?‰:Çbûm;¿þ~EÓöí;@¬Ã\î:ÖöÝ‹Å`Âá0,Ë‚¢(H&“ /3P ]â±ZuT˜„!aÕ9Ù1—‚ÚRyÅáÍŠiD™ó966Ö’~ÛšR~lß¾;vìÀöíÛ1<<ìF$å‚õؽ{wÃÉårƒØ¾};ÆÇÇ‘Éd°cÇŠAš7b||¼éf¹«¶öA«$ $ èºÛ¶¡ë:fffܰåHs™V«Sn´‹;› C¿ñññ0h´~nÙ²eE7€c1/XQË5U¦>ÄëjYƒÅq€gŸ}±ØÇ`Yî½7…µk#H&“PUªª.˜é%GÙIÑhå åÈ…ßËÕÓR  ¦ÔwÐÐ;™Wˆ¢`úi8ì-æY,~!¼•ó©ùúúú09Ù‡+¯] šz%âgƒ‘?F¸@øÂ’'í´ƒ{ꉈº‹ÂÔ^¼¼ÇE) C\ßüW¢r“²Ò¤R)8ŽEQ`Y,_ãSNü3JB¡ÇA4…¢(îsäïµÐØû½¢Y–¨ÿ2å‰ãˆ«šæ-þ.ÛhŽS8h†ˆˆ¨“ÈrœÉ_ÀÞ½ÿà&)¦ªå¯kŽã ‘H Ãqœ‚™¼K¦– GbæF¥ƒ ŽS8ív¹è™ý@õÒQ¸¦Jµ¾*9k~1Tˆ{›Hþ§1 ²ùG9Na¨üâ0Mñx|IsšfùY ^½o‡N^Ç…ê74$n"ë™ù$ÕÖ'‘dàE¾N.²)StÅòw¯–eaff€7=Uüˆ‚©ª¨ÅŽOÃ[, (ªx?ÃXŒ±ïð=ˆ ›\ÌÌ„¸0åÉÐPÑñù)¼üÅò¶âÍŒQ^À‚Î;—æa Øn"¾Î‚¹q1ûý°æÿ®ë^ øDå[MVÐËÝà+ À€ ­41,œ(odò_¥¶-®¦)n&ÙÆi-Ó4¡i À¢(3GäßEq.¯OhYTU…“©Qj€“ÿõD¥8Ž·öI($Úzñ¸<¼ñ,ªZØ÷BDDÔÉR)o@öÀpÞyw ›M7‘í­M›6¹}5K.†Š©z]IˆuMtxíÛD”âNÖf,\¦CôõÄòÿVUãŽU)³qx3ï£ð‚5K“HÉÅ€Ê ‰xù°uxÏ{~EùG˜¦é¦H§ûâiEñŒje|Ƕm7 -ovS©”»xUOÏC0Œÿ n|åáÔ}§ñÏ’®×¶ŽŠ¢,L«•LüàáñÇwAQ˜¦Y0uÔ0ÊÏÔJ]ËÃa@¹À§ ‚#€¸` á¿ÿ×{ždMCŒ"ðZâ³UL@ÕE“©¸ªˆ`Ë |^¤ Ì¡|^Mù¤w(€: ý6)À:ßN—›–#o츜æZŠªâ™ûï¯aˆˆ– Þ´øbj~ˆï÷hTÌTîæ^דíH9[$•J!ömX–Çq‡ÝY(¶mCÏ_ðýÁ“RäL’Ni›Sg²,ÑÆUU¯ *¬É>=߯³,Qÿ‹ÉY)´täŒ4ù} ªª{_.ÿï8LÓ„®ëxôÑGÛ]d"¢Ž¤iâç â·ûüºÛM2mªišH&“Ýß'S¢¨*0i–*f©'á-" µvê¹`¢/(Â ŽŸü[l´X–•Ŭä÷Ó€&… ú¶j B5 *+e‰Ññò‹BQ°,ñx¼c§þ‡Ã¢À?›¦Uö‰ ! !ä»S£eiÛ¶100àF¢-ËÂ?ÿó^ìÚuTU…ªªî(C»žÊ©£Èõyjp SRiš·p{¥ë³œ‘" ¶m9’Á¿ýÛ§qíµ¯««¬º^úóŸH¡u€‚h€ø¿þÿZ °f g¸hý(}AÓ .†ƒ@xRÔ¹HD‚¬j÷nQ: ØâÝøèAà'€ÈßyÄ_øâyHj€õ£JÞ ›rÕ0ÆÁï¿æãLD´,”008(¾×''ÅW0;M«K¥R0 Ñhš¦!‰¸íJ$ñ‹F£nÀdzzÚm'êÍ H”gYÞìY ØcY¢Í*S¿Æã­œJ¥•ºõ§ì3 à ¶ ¹ÏM$PU–e! AQÄb1„Ãa(Š‚™™D"<Åõ‰h…s/+x1Ã0ðÒK „Ãõõ¬ËT«rVq9}ð.¨&¼T[;¦úÓp•JUbÛ¢a/¯32/gJA…¸R[Ç©à°ØzùEvk¡Á›5¢¡pÖH­¼ˆX­¾aˆ~¡J¦6n5TVÇq‰ˆ!ܶmãÜsouGÅÉÑñ›6-®þ,UõFXUê°m‘Hš¦ÁqèºîJdã5‹¹¹§eCÕ²,7ÅÙüü<¸³S¾ò­`´Äãq˜f# ©Ýâq/HQ1•Vž\]’ë“Tšår×]á®»Ö •Š»3šfffH=´×^»ð5z…ëX<.Þ³8¨bO8¯Ä ¢‘SKƒ!Q^MÔŸC\¤Kíwââ—ŸýaýŽh¬Lö—y¾œN*n[€šâïÿ)Œol•Õ¶«çHËËzBºFÊ€¢åSœX^ yÃZÜÑED´ì™7ùë„LíåOá#ÓýXhT¶5Mƒiš°,Ë®ë:B¡ Àã8…BîµFvrÊŸR˜‚‹šM®s"Û…r Ù—âÿ(²ž·ŽLÃgÛ¶ÛÞ”ß2 …ÜÑÎþ”}𦹔ÉÉI÷>XøQ<::™Lbdd¤Ý»ODÔV‰„—^]U½X‡¸&˜žž®{vJ$A2™\¸ìA"áuBÊ kÞÚ!1ˆ¾ŒfMwà¶Üt"ry@DäNË‘Áþ~'óå’)Àj™œò‚íå¥_ b¶Šœ5‡èW’Çåó1`Èe•é\ü׸ÉÉÆÊ x‡ª)iÅêÀ€Ê2•H$‡‹ÅÜQ.€h´ ¢ Í êd"Q{ °dw%;wÀ߃mÛ&ñö·ŸëΑR©¸³mLÓD*•‚¦inê<‘ùª§kÈi$;Ý‹ë·axÛÛÞÖ¾ƒF 1 \¨gö£?ûT4*nfK÷LÓÌO}Ö®]‹?ø¥ …^4*^Wn ò2ˆ‹PÁ›‹kƒ\KŽ‹¿P,Whˆ Ê Ì/*ªª@ê üÑ ;ë»j¿R÷‰C/a&õ5¯GN.D#+®,Pba4SGøÍô×ÔwrŠ×{Éß`Æb1D£Q·¡#—7²ò¸ÇãqD"Äãq†5kÖÔýù "êZÕ[ÇKŽXFWnj/Çq f!ËÇäà›D"á¶%UU…¢(núWð„¨ärrŠâ5»äÌÙ$“M±•ZÇ›Éÿ]a4Ms×=”WÚ>ÿ½h8vg£Y–…T*…d2é~ÈY*¥:ù|m/ÿBÖr ‘¿“ðd‡­$ƒšòÿ¢.Êñ\ápþ¾+µðù¥¶ ‰÷°,Q—å½bñûoCŽ]“}ªª*Êîÿ˜%“"ë€,—|I¾N–5™ôöGnG¾·ãxK]Êmض—¶Ú¿ˆ/-³m{éå6d¹åßåw™ÜF4ê ‘÷ܺî›x\ÚÛ¾ñ ‹yõ+ç!‘ý,‰†7 “““ ¿‹å—ƒÄ‚$qÞ€¦F›‹²B9ŽØ™ÝË>‹ÇÊ]è‹®ª•€ˆÀF¹~Ö€Çïß aº Üi1¹ 0€p¸%ßá,+VA¹›p\âÙ· ¨,3rÝT*åNU+” šÈF@-£õ[EÞ0”Û/øð‡o@:Æßÿý{ñøã&Þ÷>o¶‰mÛÐ4­ a«ëºÛ°õGšeglÅg²0e*¶¼áÞ¹s'‚Á`{5$•² ÙÉ)ÞÛɶm÷RIR©TAJ.9ÀÎìðÏ0I¥Rî@D9ËDV”Á—R4M[ð7~ß´— ŠÈË€ìˆO&E­ÿtɉ÷€¸Ý …J¯s™öeÊ'¸XÀO—È@”®!+‘ÿ9µ<¿ÔÿëÊÍ^ó¿îèÑÆÊZmeŸO¥nÿ G™%D”å­¨òo¦éuØÛ¶×Ç-ƒQ2 dÞs``à9Øp®8udÞ‘k1hZaeD¼©\7 Ѧ¢°ÿ©C—š¨*-bšâK·ŽºÜ0¹¦-£(JÅEåevžbrAM‹P7õXÉÊ«#“y¡Ð©nÇka¹Åñb}“£ÚŠ»îzɤ˲FkŽDËÙ;g§X–8X““báï2›>묳–ö€Ñ¢ù¯GšV8K²Vª ŒŽîG$ò#<þømÏu§íù4 Çl‚Ô@Jü«˜üxé  &à]<ïÂÔ8þ ¸-ÿºÃùçW „ªÒ€bÓ $~"H#?Ó–%¾°äÂfŠâ}y©fXGÅ…VÖ×n å̹æL«bY–›“~pp333nj¾ééi†áæ.× ªé¦Ô²ð–Ÿü¤¾KDÔ)äuÃø.N¡0O³™ÿ["ÿï `}°¢â:·×H×y}ñÏ8‘¦rV¶œmÒ©ë“)ѧ§E3LvÇû2“ùo*•róÌ뺎X,†t:íŽÞ“3wd.hyƒ{4?üÉ?ÃDN¹Ö““ˆZBÆXi‰% R ÈÅ5ˆïmÿÍU"=c(?(l°æ€ô•Ë#˜’H$x³OäµF×u(Šâ^WØ©IÝʿƑ±-ÓóÉïÝ•úñöÏ‘ÿ·,ËýWDdGg(rÛ¥Ö#‰WéAå÷Èò‹yä²Ô9ü3H%™FÏÏ?ÓLþ«ëº{Ï)XÈ6ìó§Ú“mË×&¿Oüiøüï_ê{D~OD"·Àý^ºõÖ[ñþ÷¿¿Ý‡vÙ+5™$‹áÖ[“5Ï”}ápXœW,…*/” ˆ¶ø¯”yÀÛmÀ°„.B… n¨dn8™F,*“¥ þEÝ+ÑÈYt€u¾íÇ5•2 ô‘Y~yºû¦V^çdF¡Pi9Mж½ÎÚÅ’ 9UYvRÊ™rñÌjª5&¢Qqc.ËÜhGŠœN‰DFÝW9ŠH–[Ž2Màã3Å©9·l2dÂ~l ãMH¥¼4H%)Š·*÷7¿‰Gw쨾ù9œŽSâËAŽæ§¶’7£õä‡O¥¼òób•G«;v †1é.`ëŸÝä_ðW~LOú=Eyy=Ò8b±øÍ[TM9PÞ^¥ðñüv, îú0júËN¹ân"eƒTF†·:„[zzÜz­(Š[ßUU…®ëîñ‘7°õ¤9H&“ªkº.Ñr!/+Õ¾ÏäÚŠ"þ/ÛéšV˜{Z¶‹å½B4ê嬖ãdh™â"‘ðJE"ÞhN9˜J¾F>fú¾Süù»eš/=¢úP‚Á*ùW¨sŽŸ#‚)Ó(\\Q‡˜¶? ‰¿Ë”K=Ãx±LÓtohý3Oü)zTUE4…ªªˆD"3A©9Üë{~ýEÇqpâĉv«û¸©9°pT© /çº 8çæ!@y˜ü(`R_B¯€¨ßÅà´üvåŒ5”xÍ÷:ÿÿe0V¦Ü0ᥗµ‹¶Sü:'ÿãÿ»$¿Ÿœü6äkßkýÏðÝï~ç?v>ÎÙ|’“I¬úÙ*ÀѵG±æÙ5¸÷«÷â™×<³`‰ö™¦jîzQnùäûØ€j«ÞñÑ‹Ž›íÛŠ]yÓ|“ÇÆ¿/Žï¸Éc$SûúËabáq·}Û•¿Ëv¹–ÿ›å+«šÿ_yu“í’n».v yßçPÈ¡†a¸ ÿ,REQÜ7úƒ¢rž?ŸLåY¼vQ,C8v3È`‰aPÅ]÷Ìß?&ìÉmJ©Tªäà ÇqÜ5x‹É™nÅ}V_üâÛ}jV„Rë—J³XŠüìÈ5W5™®$‘ðú «IèU ÓœÈ)¦röI(|HÏ[´°÷]_M³*~€£ðÚr—ÃáÂY3Å‘«0©†•‘9åBX†Q:—eõíˆñäl”P(äþSUµj§¥]ô1Móã’Ì¥â4þõ¤T*U0‚@–U®— /†ÅëÞú-º^c¯x,Ø6TEA<õ„‡b°•`hHûpPcC… Äó_x~ó7qᆠå· y=K¶hõêª DòÉ35M,¾¡ëÀ•WÖb©iüyMkI-Yj†V($~6m*LÁ%×ðxòÉ_âÅÏÄÚµ¯Á_½Üs¸ùÉ7ÖÃ!ÀVÄ54Êò¸¨BAd^KˆÚ@â ÀY hµ|œdžN½þ”–cA ©°-ÛM"GÕÈÜóþF†aˆÇãî(žx<Ž3ÞùNlš7¯´l¬6cáÞRk?5êœãÇ›²"C/w™õ§Œ•³ý9~K¥n‘ë3Ém:Ž +öíZ±=9[Rl’évC¯ô{À¹€öJ@yuá¬kÿûÈ<Ñ2½-Ô¨×FˆÇ½kòÑ£^¾hÀK%ìßÇRi1«åáþ»¿Ë"“9ÒîÓÚ‘~~æÏS¤¢ëœã‚é42P"¯/rÍÙÉ!;#E©º¶ÝäJY¦Fþ'ÙQ¥ëº;s]®ë&QrÍÁT*…÷¼ýíø×ÛnsÛèòÿãO|?ùÊW lÞ \w]»w±sÙÁM^Gº 1£ÌÁÂ+a¸ãæ³€:€Ú D_à!@Sí?pY‰mÈÎõâÀˆ¿Lqßc ¼´€²#_6Sð:Pbù¿ùòx7e­?¨`@ ì‘9ÙÓ†àá~úÔOq÷åwã¢CaÃãpøÜÃøÆÿ|a%ŒãÇãg¾‡N=„O|éØudzzzð³Ÿá…¼€‹_Œ3/</Ç˽òùòÄ}ï ßþØð:„,xW’1›ùm¤Šž/gÿ¥|Ïñ¿ /€Ré}4q Þ§8PUé}ŠË'Û ©…Ï YœjQ‰lG5em!°+Dúƒ`²~^]óäüÏ“9¹mVÖ1 µwºÖ»;ùkrq •ò>h2"ïý×Ã?0V¾N B¡PÁ,9pBfRñÏþÜ¥f¦øgïG½‹Žûg“ø…ÊŒÆõfŠ•k«l(׿DMS\·-ËB"‘¨i ¦fcÁó5­þ†ô %zaär‡wÝ5à¥ñò_“Ë5{m®ÃÛ þvA)  TŀʋWËYSµùü,ËB8.y‘i„mŽÎ/Gþ]Ž2•Õª*zTþþãÇ{W:„C{÷âÐÜ”PÎé§‹™'–…gÀi%.P%/Œ¦ ¼ø¼ 8½ §™ ˆžâUÁ¥dÒ½·Ð4Q桞þ+ÄÍÒ¡‚ á¦MÞÝPÈûòSÜð†€Ê"µüÔ¸±±EŸjœL ƒÕ89@;â&FÎØÈ›œ6ožÃoÿö?áÛß¾o}ëH&“0 ø.WÜ/ýàÞT«60ýy ññüÇõl@}K ;ÿlF O£pà"ض³ÂW¦¦°ip‰DÑh‰DŸÝº?ýÔ§°áškð™©)|8“q×4‘\rD°ìÀ*H•ðò—·ðŒ6‘¦aßk_‹+Ú]ê<²Ã+_å×»œ¹!ƒ2ÝU(ŸRI¦‹• ›ÞL ¤‹T€ò<`ÿÐ/¬{€ÐÀ¦ê…âï¡+ôxÛ1M`r+ Î‰ÇÂùÙlÐÄ6 D¾L‡çSâ9úF@0 љ㈔‚ø# êâßoöz<÷F^—‹¦U¾_Ð|Ï×üo)@‰Â *k€7꺔¼‘¸Ü`ðÆÿڈçn÷'¡s)9̶øg@*ëè }0øù…7ƒ¾5ˆ×Þ…º©M]ñxÉ÷)Pæ¦Ó²,·SÆŸšÇ¿Þ€mÛnà¤ÞÎåFvZÉc”H$Üô%ªªº3»e*9C6‹áޝ~CÛ·#º£nÏÞ»§e2¸æàAûÙÏð;bc4êv`}vëV\”H ·Ý†÷ :M¥ð«ë×cÿ·¿Û}€:Ôê«Å,1Ý? ë•å«WŽ„’ˆÙšXÇÒâë>ëþ· ªÆ€ÄŠ G:í}Ú6`E ߨ ÞÀ`ÕM5]tMÅ;±rØù¯¬ˆyÆÑ( é"HR‚ n¦Ä—¿mÛp‚à^4…ã8¸àýà vj;ÝϹªªx ^ÝwÑX‡uå¸ÿ–°–þ®R÷¸þ×i5¼®áu¥ÞÇW¾X,5¤.èÔMi)lÁ– ¹2%þ H_˜C´Wü£°ýƒëlˆö“¬²Ix8ðÅJµ4Ä÷P“ ¨ÙX8S-¿¦&`î£sxqÔû¦>zô(ž¾äiذqÙƒ—Á‚…™7Ì`ów6ã‚—.À}¿¸'Ÿ|2zo™z àŽuwàÜÃçâÃ? Õ€'6> ?z!¶«Û±ÎZçí€çN¿ƒsÏ=×KMšÊïŸ/à¤[rexxëÁå÷GM«î6ãáx¾¯¥ðx©Š*^§,<^Š¥ˆó&Ï­üžÁ`7•‘ïu¥Žy(ÿz¹iÈ÷ŒNû“çÅ(ÚßüëþåþÁžú¨uä2Çɤè3Åb˜œœ¬a`¹-Önõw-f hñk«õÕúŸnA|vð>¿ò’X¼x;u´Uóóóó‹ßLûŒŒŒ`||¼ÝÅX`pP´IeG¾ãx#Q‹ï‰åH=Ã0Üér ‘ZRxÕÃ43”D|èÞÂa´E_'~í×ðì¿ýàß?òÌ=ô:ü‰eâŒ3~ o|ãñúM÷bôµÏãôW¾Ò{‘?ß‘ì¨uÊ€a ö?ï‚>¸ úóû¾ÎqD/õL éAdãÀ þ1ì7¿×MƒÒ(Ë´T>ÇI4Z°cccƒƒM=WÝ.“É “É`tt´ù—#ëTQ×ÒiqŽä(]EŽ®3áݬäEæ?æ >7¥ŠyóÉ|Ÿ9÷3øÞù«qËO^‡Ï|æTèºø8éÿèV)— ØÀ|þjŸ¦oHY¢'TöæºÃÇåsl¯§ÖqpäûßÇO.¿Ͻ÷½nÚCþçxÓ£â‰'žÀ+.¹Ç~gÝ{/߈œXÌ«¯±XíÓ[qm»s‡CéÔkD»uÊq‘ëŒÉYœ²ïvrÒË}-g…èºøwÁÒ:€Ày3àlœ ^z+˯³,ñ‹ ¬y€‡ô{i³ /Ƕ?–Ûç; ¨€}LühÏÊßvP¯É¥8´\”0?ÒÐù8àLC3À{ßöÞÿï/aÍ¿¬)hû,žzé)œzî©øùÏŽõw®ÇÉŸŒýïÛ ^ˆsŽŸƒÇî 'ÝqþùŸÿ£££xç;߉í×mÇwþßw0wÑ&þ}¢ÝÃŽ322‚ñûîóò®Éïë7k2Þ²Tk¦ÈÁ>2í†l·Ê5üé\ý#—3jÃ0 fŒËÜ着â¤ÿø\|ñÅøÌg>ƒ¿øÎw‹ÅL&‰DðÅ ðì³ÏâÜsÏÅ#·ÞŠ—¿ë]xèÚkˆàÔïÌÍaãþýD‡×É'ŸŒ—ÿÍß^»ýSÉ€úWþõmçÁßÿ}<õ¹Ï±m[$“É`îïaó·ÿÒ½›º*ÁA™º¥é‡dz„bò&´Ôwˆ/Çä¡?ÿsÌÏÌàŸ.¸  ~ËT<2¥«¬Óþ@éJ ŽÊúìOOÀ ˆúS“‰Cì¸3ódpT¾VÎ WÅ]Âö¥“kBÈTÙ2Èú­o} ßüæ7Û}(:ÎÈȶ8ã0xÉ­·Ž ì̯)g‘øsZVa‡ €Å)=Šû%Š"ˆÞïþÁ’­ÊïóÀsÏáðÛß^°†Ç…Ÿÿ<|ðA<ûì³xöÙgqïºu¸w>Ú¶׮ŖSNÁã?.‚î¾ür¼áÆÝín¸í6¼j~Ĺ瞋µoxÃÂŽàÅì .kûŽ›LÒâãVÓûo£Þ÷‘í°âë©|Ÿ|Šx„ÃøÝ¿üKœvÚiHV[ƒcjÖ½§<}š–r×l-hgÊ@˜\^¾ýºocÝK_Å%«ŸFÏC•OÁS«u)³šIf?‘³]c÷s͘iGÐ’~[ÎPi™-J’£Vxç;_ÀÿÏÞ¿‡·QÞyãÿä±3 „ &Œ 'Ú2&PÑXÆm’¶Ð¦•M·§x‹¥v·m¶[ïJ_ž´M·}¤â}¶Yºm¥´5=.ö´ÙžHL­¶ -j`=”‚E 4C‚ db…œàߣ{4’eI¶$K²ß¯ëòe[‡Ñ=}4÷ÜŸûðÎwîÆ¬Y[08¶+§"³*æ2ž1÷‘˜gDÌ;æÜžÏ‡cs¾€ççÎÅÜæflŠÇ¡hšýºÿù¹Ïá‡çŸJMù]çÞ®Ãÿgž9„ÁÁ0ÍKð¥'<™¾^SutEIOÜ^Ì›[_o ¾}ìcDáÖÖ¿Ž!{ ÙL´Š%¦x*–ö©û¡œ¥§[ò8wåéHO+àj-z¹¤†ÿ,´ÉР]  ÿ~@=¯ÅsM@¹ÿ?@Ó5œuÖYø?ü,ºpEÁï/û=μüL\gW_ D:ßË€çf@~s¡ò¦2<€¬V'Å›y¾žÀ2I¢éJâãGŽàLÇB|þêWh=å¼üòËxþùçñæq–Ë…e©‹9Ó4ÑÐÝŪŠÅ©m,ÎUVç…ÁD¯îÅè,š™ X=Ê1¶÷Œ k„„#×&ÚqĨ ý€Ôf ô€ë1ª ¿ÌgR_ß»€à?rÐzqM#¦¦Ò=”ºoØOÎÅðÏgãÿ ŸÓ ´½ÅÝ1rÉöÎ:ÆþyöôTà9 (KY‘Z[Dôd ú‘9ÕBj®ö^xGÞð.<4?ůÿ!¾ûòwñzã |÷êïâÒ_\ iŽ„ÿzõ¿ðìágqÊÂSpç–;1wî\\yå•X°`^j| g¿ñ5øûÀÃ+Þ3>~TSÅ‹'_„)™8;y6:ý!\9ïJôlïAßÿöáÖ[oEØFÈ áßÀ}M÷៤ÂÛ׿¿“ö7X 7ƒùÍ#h¸¯÷~æ^\qÝ8|ø0ær>.‹_†Åòb <Üý0¢Ñ(ö¿}?.‘.ÁïVýOm oyö-Ø={7NÞv:ò!¬ì\‰'N`á) qýY×cÉï—àù矇ËåB"‘`MÙðì³Ïâ}ox´W5´EÛpäñ#8ãŒ3pÿË÷Cj“pâÄ <øàƒ8|ø0?ò8þ|Οᾌµã*2Ñ-Ö+7‘#NDb@UU{¤‰³Qµžœ ÚŠºp °§Íòz½Ø98ˆ«-·úSÜÐÝm7~žòÌ3xÇ®]¸d‹Apñb$ßùNÜóôÓöT·7ÅbX"†´ýñxû?ü (ötƒƒƒ;~æ3€,cyêÿìÎUsÇÛ‘r›#‹Uû°Ô¬“glBþŒFI”EŒ2k}ýë_¯öÛZ³¢ÙõÔïGM`‰”Ž ápº×Œªæ˜žG›PÉæ ô\‰LÑ È0ðôk¯áðáÃ8üØcxʱnXÃÓOãýk\wÝu8|ø0ŽœqŒ½{íÏž$I¸ ÀÒë¯Çe]É4ÑqË-€ó³,*ÙbIÂuÙ ÞTù.2×{È.o¾}ÎÞ?ѨØ#¨AºQ(;Y‘ý:¢So¡D¬,ÿ±ã­g›=ßn¾Ž¹’â’ã³#®ñÇû.ï]1sëÓ„išõ#µ¢n÷0>ûÙÉÖµhj6‘ηwâ«Þ‰¿^7.|Î8ë k¦˜²Ï¹&ÙDT¢_ij¿ë?ÕŽP©MK7Ø‹­ ð‡J«ªŠXìcH$.Æ'>qjÆ,Sy‰a.âäéñdÖÐÅ|%©“Â<€Ñ+¯Ä¶íÛ'N¼ Û·Ÿ…ÎΧì…íMÓ´/"ÕP(½ê¬3Û/†88Ïábj±®¢Þo] é™G2Ë/º#‹“›£B"ί•îä$ÖœEðû­¿5-³~$ŽŸ$¾ÿŠÁ«n³Þk1oZªâûØ[Þ‚—ÿíߨ‹/KI#TD2E,Æ%æN9:/¬“ h{ü-ÒC‰%@O­]$Ïô­€çŸåÝVãÐ׿¾=ô*>ö±¸`ôüÝC‡Ó§§‡ðŠ)ÚS=Œ‡èoÂûêFà¤çùÉž%Ȭ¨æê1ã¸ßÙkUL·ÕÞÞŽ`0ˆ@ €`0MÓ2áóL$ X)mmÖð:éX«çˆj›ôûÒŽôÏÙí§M€q0ÞÈ7Z'™mä0Syîè-®ÔY°â\lCT€Å\Òàù·>Ù_›cÏÃnþ.Üu!¶¼ð(:ò8°\0ˆùóÿ‚ËÏ<.— ýCýéµwRóÎÞ|×Íø×Wÿ—ŸyyúûDŒÎsÍ‹9ïÅ4 ©ïœ}gîÃÓ OãÈâ#hÙÑ‚E»áÂ…âo|#N9å\tÑExûÛߎP(„ýû÷£±±6lÀþð|á­_ÀôG¬ûø:ô::: …ðÖ·¾_ýêW1kÖ,<óÌ3ÖÛÖÔ_›ÿÒÿ/ØvÅ6|*ñ)ô÷÷cýúõÆ]wÝ…û·ÃÕW_mÛ¶áƒü †††°gϼ÷½ïÅÏ~ö3\~ùåøýïùóçãÀ8ÿüó±ÿ~,\¸+V¬À_ÿúW(Š‚íÛ·cÅŠصk®¿þz<÷ÜsX¾|9~ýë_cÓ¦Mxþùç1þ|ÜsÏ=öçù¨(lܸïz×»`šæ˜iHòÍw­¢£ë\1ñ)¦cÍ®N†YÀž/]_‘4ó¤ÛÇ6Iwv©ÝÑP¬(ŠÝ*zŠ‹ÿ_{úi\tÚiøåsÏáØœ9öóßvâ^þÙÏðÎw¾yè!\~æ™øâ[ßj7Ž*Š‚æÏŸcÇŽaÖÙgãÌË/Ï|ÃEeX˜ª¡BÆÑ×¹‰ï­¼>_zä£èÏ68hUÿ|¾ô³©ÊGˆz¥E&nsŽ$™#Kœ‰ = ™¸OŒD"ðx<…BƒöoQ·…BvÒCÔ½Å{b A1¥žHdämgš&f=ú(^{ÍŽÃ0 G£H~ç;hhh°¾+ÃáÉÕEc®c„ë¶¹uvvâ-Ï¿ÞÿºaJ®S²fŸEqu®3"8“”bÍ+‘d£ú÷‘|ÇŽÃO~ò“j¥æLø{+ hÆ™™9¼_üâ(~øÃ·ãÛw~oºïM™Ó8·èÀ¥ vú'<øÅ/bmooŽ¥R¿eX׃b=Öµ¡èw Ö>ËEt.¤ºR‰º-*`š&.¿ü>üá¯AÓ4Ȳ EQ ª*.>ýt¸Nž´¨ë0½~D"©Söb¼fæ}ÖýþùŸŸÆ£ÎB"q1ÅÀìÙ³±fÍ5é°ÀÔïESMà9#ãs øº$4 Í‘,)"jšéy¥5M³/ÆDãO$A8†®ëðx<¥N›*ííV¢¨N*þ[¯¸k{¬ÚŨ9“:wê°’šý°¦•òS=‡ ÀÛ ø¾ xμí*À³%5ÊD$,œ#[ÄÕà{ŸþþòÒ_pßÓ÷eT|EÐÅç^Œå÷,Ç9‡ÏÁ™Ož™®ô¬rE‚Üu×]¸ûî»aš&î½÷^Ìž=[·nÅ‹/¾ˆ'Nàæ›oFÛ¡6D£Q|à‚à»}¯½ö‰.\ˆƒbþüùxòÉ'qíµ×⯿þ+V¼¾ËoXŽ_Ɖ^ôAœ»æ\´´´Øq-ž‰Û@ `O¤ñô›~ìêØ…×_·Ïß_ÿú×ñ©O} ?ûÙÏpøða #”ý)zÊïgïzg#šÓx‹xV㻇 •ñŠO1ž=Åe‘Ĩ1Õ¬¨CÈè9]Ô]¢>Zæn÷Î^áâ³=ûèQœ˜7Ï>w†B!üðüóñÔSOáꫯÆý÷ß›o¾Ž³§ÅùèyçaAªãËÉ“'ñZCŽ~úÓXvÓMé3Œ±S‡LóéÉŠÅ„Jnâ{ëž{ºÇô=3Ít~-)į̈Îiö ÇÈe‘@ÈNšˆx®%ÎuVœ U‹óO(‚×ëE$±ëÈb ,g‚DÓ4{ô˜ØOçyPüÛÏN„ˆÑheÕÚ:v ñÓ뚦Ý€Uy=üıÊ5.†åʲõÁJ}¨j±ý£Tò}‰Jñ™r.ìîìp •5=W‡Æ«Û–ÂÙf ¨íW]×ñï|O>ù$~ûÛßVûíª9EÇgj9Í"?Âò¯˜@TÚ#‡½ð¦§òóÂîÜzph§vÞx#VÜsOñLÍFéí:§á£±¤Ôcú‹ß4Õ†1åW"‘@"‘€Ëå‚ËåªvqŠ"¦D½®p¹0òâ¯Ð¾p!üCC™½ùDw±$‡ßhwŸŽÐÿïFô/ù>¢³oDôÉóa¬_ÌZ[A– <÷ÜG±k×.üûÂ%ø€âǵ×^†Xì.{iç…q®ù+o.4}Q6gÄH$oBEôÆ:å”^øýVýR,¶Ò7 ÜŸ/5›Š˜©õæÇ±9²§g˾HBto:›ur|î\œvøpõ ?…*ŸQX½Óûa5ºfÏ)N`@VÂÄ‘o”C6X^QÑýÀ•WâßNßž0·?óÕùVÍð&ëy2€ˆÌ3Ó„ìJÒ§dXsej1ÊÄëõÚSˆÅcØTÙ½”ÄýÎ ášWgMš¢Ì˜e;+Ÿ©Êíde*ý] íƒN¤9@øßå&`ç'ÓÏóKH»N%HuC‡±Î•º¡ã’Ç/Á+ÞW /“qÃM7àËê—s#¢ñ›øzäëP7Z=úd]ƽ/Ü‹}òc€÷½ï}¸ùæ›ár¹pèÐ!x<¸\.œqÆøð‡?Œßÿþ÷º`C áÒ\Šý÷îGWWþð‡?à[ßúþñÿï{ßûðúë¯ãµ×^ƒ|§õY—eÿÿ(Ûq f5@˲l'WV`EÆ}ŸúÔ§ï}ï{ÇlÇù}‘ý2Þáx luñÝSÇÊ›ííV½*_Cœ›Dã³·ºÇã±\K:î¦q6‹ÖeYÆÿó?ñÕŽ<÷ýïcùòåx衇på¿ü þ~Ë»Wø7Þô&¬ÿÊWðòÅãÒcÇ0þ|ìÿ¯ÿ²?×Ðu\’ª8v|øÃ€$!œÚOøÈG¤§È’ríCÓ¨ü&ŸÛ·_Uͽ–­Ïg]&L6Ïèìá.:̰“÷¢áV$¦ºáV\gŠi°DØ9ZLtìsqŽk‰ïQOÓ Š:²H€ˆÿÅÈÈ¡q¦¬Í }Þ+{2%;×·õâékÆ\çüÓãMÅäÌÊeOŸápؾžß¢± ¶ïõzíçŠò455ahhÈžBŒ:‰W1¢O¼gÎý‹ýsÎ ‘=ªM¼Ÿ²,ãÀSò¹¨‰ÍT§Zó­€äú/¤Ž7ÇÓ÷=¨ŽŸ½‹õÅÖõ¥ã<ì3M(”`²,cÅD;ähkB}ô¥*ª©*}}}èééAKK †‡‡ÑÝÝŽŽŽ¼Ï™ê¦iâ™Í›ñÈ# ïÀûD¡ª*üb^ZY†¾ì&(w¼«¨ 5q²þÃâxá…¸à‚QûµdY¶[Ú¼ù7¸öÚà;ßy_üb þû¿ÏÁ®]§âÈ‘3¤ÛM­‰Àêü’*’ÝÁ¥ä…9¦ÿÊ%±ê‰…¾ËDr¼ºdMcùÅç±óØ[Þ‚Y·Ü‚æ ª]ÊŠšh|æí}, Sîõî´=@` _79®’I ¡~æ¼?¼O~ë×øø²»pÚŸÿ À_ÞøFœüÒ—ÒLÎé8 4žäª€Š *»*î ‡ÃvåL<§ÖzÎt3¥ßDãsÜ÷EGº‡`Ul=€¾ ßeu Ã×&!pEc¸Ø±#FmŠ¿ÅãDTq!§ªªÝcU&NÎç9Ö‚«Ùd 0¶»™ã$ùë÷¿î«®ªv +nÒñ)z¸G¬4€dkŠëóòí(ZûÔüó2ìüíQûÃ08<üÍobÕßÿ=[ñ78Ðù*f׌WçãÇ?~oxÃðž·ÎÇü7½òŒ\€¥9^ÞL5ÚJŒÔ…,€Œiúûûí ¨è$*ѹÖ.=äDosÎ}KÕ4éøÔ|Iƒ±ûok†¹ì]À>Àó)Àxl¡YóÝ´JóqÝ’=ó#9_;9g´¸òz½öÅ—xœè­.I’Ý›Ìyêì¡:˜Õ¸Q¶8sNÅá¼Í¹‚X§Ìù1=‡½V’hÄÑõôó¼ÞÜë-9åê¤àl0ʵ`¦˜_SìGvwigoV±f™ó1bÔ¬$YÛRUëÜæÜß¶¶Ìm*Jæ¹P,@ê,[öÅŒÇcÕ$)½àÚ 2ÙØlkË\UQ¬ÿ/¾8Hd›Ý#EĨ“`08nc…ˆY1½ŽM)zvеCD#J®)tD|6®Xé¿ÀRE·§8\—}ƒ,cÎ×¾† «}`ˆP¦kÏD¬9G‰‰ÆDg’³P¨¯f÷<Igƒ*n(ç\‘éïïÓ[ü/Ê#Iäï|o#+Å®ãÑ(Ð4«#o(„ ßŸùŸ}~Ë>gcÏ+Oæ¹)MÏÅ<^‡(±€§ýJÒØ$Löc¼Þt’d<…EeÊ“)3I9ãSÌ("FeȲŒ¦¦&\{íµp»Ýöt®¢+® ÛÛÛ188ˆÖÖV{-¿ßŸsª(1šÅY—בâ=^=6#Ö%þÏõ¼ìQ[býýýÿ‹ûs%9Ä>ˆÇˆ×ñæ‚çàœu!{tôx8ªÝéP”oÌBæetÞyçaåÊ•UÝÏ©Prl>c¼õznº$@ÌÛ€ÀÅŸÎv~kBÑ3Òö ø©OYçÊh¸¯ ž}6ŽüãG±é—¿„G×ÇŒü'šJ5“P‰Åbhll´³EÍÍÍhnnF,Ë›íܽ{7Ò¡}Q‡~rÑSþž΃¹o0ÈäÙ/!²c.ÌWÂ8²×ãxãàCøÉÿ4a÷‹³ðÖ}?ÀñV¼öÚkÀk'qÖ蟱øüa¼Ð ãèÑ7âüs÷áæO=‚Uÿ÷ìØ;0|ôK?À÷ÿÛšN`ÍÿÜý–ãùçŽã ox^ÃÀz=¢¿ŠBVdüá…? u~+®ýüµVoÏ3ñ×Ù½{7–w/O¿Ž=?cjGCÖ6¿g1¦»ÉÄçîÝ»1ú»ƒÐ7Þ À\ (ýðÞT{£h‡’رïLÿÌ ì4÷ãì_Æ= öE䇗,ÁCû=ó \¸záB¬[¶ @»Ý;fª"g ËmmmÅààà˜¡ÁÎ^»ÙÓˆJkvE°§§gZô¢îëëCKK š››«]”’M—cR“OóïïGèÛ» /\cîZ„;’0ž´Tlú¾-Ãwn/>»j'Ÿz ¯ßxoÿ~Ì›7‹-ÂíGŽ`íË/cå¬Y8tè–¾ûÝðìÜ ÇŸÏ‡U³fál]Ç© à¦ÔbÐ'/¾Øž¦rhhÔu ½ÝšX/€š=xvœ˜x<ŽááatœzêØ$…h,œ =b¨fvBE pÎiî$æ§t&LœD#ŽßŸ~­ì Ëq*þögZÌ«.µLÓzN®¤Œ˜c3WY²/¾³Ë1fnË Fͱ(y<Çp__ú³ç|ÝÖè4Ùº-~ëÅèMÓíÆÓ¦¦&\sÍ5v"EôJD"öTΞçΩ+Äm¢aCœó%E„1 $8yΩ=Ó阔ª”øtrN $’œbæèè(-Z„¯~õ«8pà€Ý{]Ä«¢(hoo·—@:)":ˆžæÎdˆ˜BGÔWs5(‰©ïDÝVô˜=ûì³Ç6Òvw§Ï]ÙçÀ\ɇìÇÓ°Uè¼R̹Éq¿ý™Î.W10ÊÑI£Œçµ¢¾g|>x²ë;ÓP©ñFñ«_ý >ú(üq\sÍ58|ø0>øÁÚÉÆP(„9sæà…^À‰'2ÖDõT‘œçH3ù:ø8/ö9NvÝvßCµªÖΓM¤L§cRªRcÓhÛ íwÃÐæ|þؘ€G¤‡ Œ¬8+V| MíÖ̃ƒƒöȪöhrª€¢(èOMëZ.µ^?ª‡Ï`­ÅûT¨™)¿6oÞŒX,–1 ¬³³ÍÍÍyÊ[.¹Ï?ÅÒùCxvþÿ`Ñ¢?á•Wö^~ùeœ8qóæÍÞ={pþùç㥗^Åüù×#™ü–-» ‡†,8~ü8æÏŸsÏ=ÄÕW_Ÿþô§xÿû߇zW_}µýûرc˜;w.Ž;8ÿüóKÞÿ‡~Ë–-òe˪}(J¶uëV¬][ÿ«³?ü0žþytwwãæ›o®v‘+f2ñyûí·cצWñç#ïÆ«®û‘8°sçÎÅñãâÕW߇×_?€ÓO¿¯¾úw8õÔ]X´h££C¸â †‡‡±zõjüô§?Ň?üaûX<öØcX¸p¡ý‹-±cǰråJìÙ³§b=B¦Ëgz&}Ï>|;vìÀÞ½{ñàƒV»¸5™ø¼âŠ+pÑS~ŽÏ‹rØ»w/öîÝ‹¶¦&,8x°b¯3¦Ë÷Œ8&«V­Êû˜'Ÿ|oxæõ´“­Û^}õÕxì±Ç0þ|œ~úéX¸p!æÌ™ƒÓN; Ë–-ÃÓO?µk×⡇ 7Ü`×qÅï¹5ò¹ŸIçœzQÌ1aÝvüøüùÏŽÛn» Ï>û,fÏžcÇŽ¡©© {öìAKK `þüùö5¢¨Ÿ^qÅדθ­V¼Î¤Ït½(¶n;÷‰'ð½ááj·¢&Ÿ×_=žxâ 9rK–,Á+¯¼‚w¿ûÝxöÙgqÍ5×T=æŠUL=ª^L—ïÖmÓJ©Ûžÿpú)+!-ìÅÑE;0oÞ<óL+Nœ˜‡yó~Y–ñì³ÏâSŸú~ðƒØí?W\qEYÚ\ó©õsI=|/Ôr¼?ùä“xê©§Ê^·­™*b ,§b†Œ} « Û·W^y%8 óæ]‡£G.¸àÌ›7_|qŽgþCÁm¿ç=ïÉù»¦ÓÅÓe_ŠÙ àСCÓ~AßÉÄç?øAüðµâµ]ÿ‰Ë/¿{ö<˜jð9†«®z£££˜?ÿvÀüù—`þüùnÍØÆÇ>f-6ÝÞÞžñ{ªÍ¤Ït½(´/G…Ëå‰'ª]ÔŠ›L|~ö³ŸÅO<гƹç^‡àüóÏǼyópÕUWáÿ÷qÉ%".ó»4õûÊ"Ë;UÕÔÚ¬o:Åg!/½ôšššìÈéj²uÛööv¼õ­oÅ[ÞòœwÞyã>®’õÒr˜NŸéé²/¬Û¦M&>EÁÍ7ߌ'Nàýï?>\Ôy˜šëɉ˜IŸézQlÝväê««]ÔŠ›L|~ìcà /¼€Ë.» çœsNµw0½â³ÖmókooÇS§k¸å­ xõÕW1oÞ….Ĺ瞋%K–`ï^W9¦Ñ¿ñÆíçM…™ôY­”Z~—-[†K.¹¤ìuÛšI¨466޹-‘Hrõ¹Ï}®ÚE§¬–¿4Êi2ñyÙe—á+_ùJµ‹N4íM&>;;;óns¦|·Uë¶TfÊ÷ÿdâóüóÏgÝ–h T¢nKD¥+©nËê-UI¥ê¶§V{Ç„ææf$‰ŒÛFFFJ^ˆJÇø$ª]ŒO¢ÚÄØ$ª]ŒO¢ÚÅø$ªMŒM¢´šI¨¸ÝnŒŒŒ ‹°ÝI$X³fMµ‹F4ã1>‰j㓨616‰j㓨v1>‰jc“(­f¦ü€îînlذ---Fww7ª],"㓨–1>‰jc“¨v1>‰j㓨616‰,§ŒŽŽŽV»N‰D‰D.—‹Ãƈj 㓨v1>‰jc“¨v1>‰j㓨616‰j0¡BDDDDDDDDDDDTkjf """""""""""¢ZÅ„ QL¨À„ Q³¾ð…/|¡Ú…˜¬D"x<hll¬vqò–1‘HØ?˜={vÑûQíýL&“xñÅ'\¶Zܯ\ûRê1ªöñ©EõòžL‡c?^|–S½o…öc¼cTkûQêå=©÷c?Ùsg¡û§Ë¹³ZûB¥‹Çã˜3gNÙŽõTÄë%“Iœ{î¹e-ëTìK1çK—Ë5á²ÕÒ1¢ÉÉ›@}û|ñYëuÛbÎû“‰Ïjï•Çdâ³–Ž})çÎR÷³&Ÿµ¾_TX%ëGåVî:v¹$“Ièº^‘ºs]­S÷ÜsÏhkkëèúõëG[[[Gï¹çžj)§Ï|æ3£]tQÆÏƒ>Xô~ÔÂ~Þyç£wÞyç˜Ûó•­V÷+×¾”rŒjáøÔšzzO¦Ã±Ïõ™.5þª±oã}Ïä;Fµ¸µ®žÞ“z?ö“9wººœ;«¹/TšgŸ}v´µµµlÇzª?wÞy§ýz7Þxãèí·ß^¶²NÕ¾äŠÇìýzßûÞ7:22R—Lj&'WlŽŽÖױϟõP·ï¼_J|ÖÂ~Qé&ŸµtìK9w–ºŸå܇‰Æg=ìåWÉúQ¹•»Ž].ÃÃë;×»ºM¨8?hÃÃã]tÑè³Ï>[íb±~ýú1'ΉìG5÷óž{î±Lr|ò•­Öö+ß¾”rŒêås8•êé=©çcŸï3]jüMå¾úžÉwŒji?êE=½'õzìK9wººœ;«±/Tâ‚Èyìëå3ýì³Ïfldddô¢‹..KY+½/ãÅ£Ø/ç~Üx㣑H¤îŽM^®Ø­Ÿc_(>k¹n›ï\Yj|Vû{‡Êc2ñY+ǾÔsg©ûYªRâ³–÷‹ «tý¨ÜÊ]Ç.ç{6222zã7ŽnÛ¶­¨2L÷8¨Ë5Tb±áv»ÍÍÍhnnF,«vÑr–5×°²bö£ÚûÙÒÒ‚ŽŽ477O¨ìµ¸_…öe2ǨÚǧÕÛ{RÏÇ~¼Ït©ñ7Õû–/6ó£ZÛzPoïI½ûÉž; Ý?]εpŒhrzzzÐÜÜŒ––û¶zúL'“Iééàr¹022RrY§b_Æ‹ÇD"·ÛqûêÕ«‹Ú¯Z;F49¹b¨¯cŸ/>k½n›ï\YJ|V{¿¨<&ŸµtìK9w–ºŸå0Ùø¬õý¢Â*Y?*·r×±Ë%‹add]]]¬øF£X½zuÁ2Ì„88­Ú˜Œx<>æ"¾±±‰D¢ÚEË N>wÜqb±ÐÝÝŽŽŽ¢ö£Úû)¾xrÍs—¯lÉd²æök¼})åÚÏ™¨ÚŸÙ‰¨÷c?ÞgºÔï•©>†ù¾gò£ZÛzPOïI=ûÉž; Ý_ïJœ;‹¹ŸjO<ÇÀÀ¶lÙ‚ 6dÜ^/ŸéææftttàöÛo‡Ûí¶“‚âB¯Öë¶ãÅ£Ûí¶÷°âs``À¾ø­§cD7^lŠûêåØç‹ÏÍ›7×tÝ6ßy¿”ø¬…ï*Ídã³–Ž})çÎR÷³\åÛÍ–/>k}¿¨°JÖÊ©uìrI$hiiA__ÐÐÐ€ŽŽŽ²Ô§ƒº¡"2ŠNãõ’¬&‘íêêÂSO=…M›6¡§§ÇÎÈÚZÞÏ|e«§ý*åÕÒ~ÔŠzzO¦ë±/5þjißò£zÚZQOïÉt=ö¥”½–ök:×oh¬d2‰ 6`Ó¦Mhhhȸ¯Þ>Ó ö¤ÙÓ¡n;00€uëÖÁívÛ Îz;FT¼|± Ôß±/>§KÝv¢ñY/ûE¹•Ÿµvì'{î,u?§Rv|N—ý"K¹ëGåR©:v¹$ {´IWW\.:;;í¤ÈLƒºL¨äÊ.×b–«¹¹½½½vöÎívcÍš5vƒC¡ý¨åýÌW¶zÚ¯RŽQ-íG­¨§÷dºûR㯖ö-ß1ª§ý¨õôžL×c_JÙki¿¦sý†ÆŠD"hnn¶§ÀA<G<¯«Ï´è]·eËtww#bxx›7o.¹¬ÕþL'“Itvv¢§§7nÄÆ‹.[-#š˜|± Ôױϟõ^·l|Öú~Q~¥Äg-ûRÎ¥îçT/>ë}¿ÈR©úQ¹TªŽ]N.— ›6m‚Ûí¶g$èëë+X†™u™Pinns FFFj.Û%2øNάc¡ý¨åýÌW¶zÚ¯RŽQ-íG­¨§÷dºûR㯖ö-ß1ª§ý¨õôžL×c_JÙki¿¦sý†rK&“ؼy36oÞŒD"mÛ¶aÛ¶muõ™N$p¹\ŸU·Ûm÷ «çºíúõëár¹F3¦·(¦lµtŒhâÆ‹M ¾Ž}¾ø¬÷ºídã³Ö÷‹ ›l|ÖÒ±/åÜYê~N…ñâ³Þ÷‹,•ª•S%êØåâv»ÇŒœ™mfe3 ßWDkkëèƒ>8:::::<<<ÚÚÚ::22Ríbe¸çž{Fo¼ñF»\###£7Þxãè=÷ÜSô~ÔÂ~®_¿~ôÎ;ïs{¾²Õê~eïK©Ç¨ŽO­©—÷dºû\ñYjüUcßríG¡cT‹ûQëêå=™Ç~2çÎB÷O—sg5÷…J·~ýzûØŽÖÏgzÛ¶m9?·‘H¤,eª}/|ðÁŒŸgŸ}¶îŽ•&;6GGëçØŠÏz¨Ûæ«ËN6>ka¿¨<&ŸµrìK=w–ºŸå|ÿ'Ÿõ°_4¾J×*¡œuìrmmm¶ÿ¯Ç6³J©ËEé »»6l@KK †‡‡ÑÝÝsnÊj‹ç®[·.— ÃÃÃèèè°çì+f?jy?ó•­^ö«ÔcT+ûQKêå=™ÎÇ¾Ôø«•}+tŒêe?jI½¼'ÓùØ—RöZÙ¯é^¿¡‰©—ÏôêÕ«‹Åpã7¢¥¥‰DÍÍÍö⤥–µZŸéD"D"ÎÎΌۻººÐÝÝ]WLjʯ^Ž}¡ø¬×ºm©ñY«ûEåQǾÔsg©ûYI…â³^÷‹,•®M…j—¯¡¡ÝÝÝöú3bÍéÐfV§ŒŽŽŽV»“%ÄårÕô°¡xë—acâš±YßÓK±ñhš& ÃÈùüh4šó>ª.Æjý*åÜ9^¬:·Ëx­>ÆguU뺓çÒúÃX­¾ÉÆk®s©¸×¢õq9ýL‡¸œ± MÓê6 ÛÚÚÊV¬]×ÑÔÔ„P(„öövø|¾’·i4M«ö®Q0>ëS @kk똸flÖ7ÆãôRl<†B¡1•ÜH$bÇxkkkÝW‚§Æj}*õÜ™+VÆk­a|VO5¯;y.­?ŒÕêšl¼Žw.x-:0.§Ÿé—36¡RÏ¢Ñ(LÓ¬v1JÒÞÞ¿ßÁÁA !Ö}0Ó#>'Ã0 „B! Ùq‰DXy ªš©ñXŠH$‚ööv„B¡1÷ô÷÷cppƒƒƒðù|ì]Ke1Scµ”sg¾X¯T>õŸÕ¸îä¹”ª¡Þc˜\¼ò:”jÙtˆKÊmÆ$T4MCSSN9åø|¾1h‘ _¸p!@ư®ëhooÇ)§œ‚ÖÖVûK½­­ ‘H .ÄÂ… ‰D°páB455edQ'òØñû·®ëö6e/–³<Ñh´àÿÙ^¾ý_(~¿ IvîÜ Ç3f[ÎýÒuÝ>6b›ùzô8ãDžGS¯”ø/6úÏ\±7UñY(^ÆÛ'qÌ$I²˲œ³ò ¶_ÌëÑÔË“=WÅË‹@åⱘøœÈ6+‰+g<€¢(ðz½P%ãqÑh’$AUUûqŠ¢Ômo±é€çÎL3éÜ Œ«ãµTâ\:Õ± Ôÿ¹t²×â8ð\:ýñ\š©šçÒBñZŽs©xØNTÛ¦kû­s»å>V«Ž;Þ>͈öÛÑ`çΣFƒÁàèèèè¨ßï0ê÷ûGGGGG<8*IÒhÿèÁƒG½^ï(€ÑÁÁÁŒûÅóG%I²·+¶ Ç¼Žªªv9&òØ|œe0êõzG<8:444*I’}_1ÛQUutpppôàÁƒÿ/f{Åì_8UUÕþíñxÆ”9×~…B¡ŒÛÅqÏ´_ÃëõŽ*Šb?.ßó¨ºJ‰Ï|±9::±˜«¥øÌ{SŸ…â%ß>y½ÞQÇ3‡G=OÆ6sÅf1¯GS+_<–r®-þ3X®XÛ*w<ŸÅl³’ñ˜ïyùâÑIUU»Œ¢œÙï}öchêðÜ™{3åÜé”+¯ÕU©si5bSl«^Ï¥“½îä¹tfà¹4÷6ªu.-¯“9—ŠcÃv¢ú1ÛoÅÿ•8V«Ž;Þ>Í„öÛ‘Pñûý£^¯7ã6Y–3><Î`FqÀÂáð¨¢(Ï÷z½v` âÀ;ÿÏÈb›Oö‰Ò,"€ŠÝŽ8áó1Û+fÿÄû&Nâÿì×ÎÞ¯P(4*IÒ¸ÇV¼†×ë•$)£Á6ßó¨ºJ‰Ï|±9::±˜«¥øÌ{SŸ…â%ß>ùý~ûØÉ²\06‹y=šZùâ±”såèhñŸÁrÅ¢ØV¹ã±˜ø,f›Åìãdã1ßóòÅ£SvO® çñ¥©ÅsgîmÌ”s§S®ÆXÆkuUê\ZØÛª×séd¯;y.x.ͽjK ÅëdÎ¥Î×`;Q}˜Îí·âÿJœG«UÇoŸfBû팘òK×u{øŸ ˲ý·išÃq³kt]Ç)§œbÿÔÒ£ìòN„ó}(æÿr‘eýýýPUÁ`^¯wÌ{šk¿²‡MK’”1ç¬sh›sÈ_¡çQõ”Ÿµ›Ùåˆ\±7UñY(^ríS$¦iB0ÄÎ;¡ëº=wôx±YÌëÑÔÉõ~®ÌUæb{µ…ž—/'òÞ1N«‡çÎÜfÒ¹s¢ïãuêð\š[µÎ¥“½îx.îx.Í­šçÒBñ:™s)Àv¢z2ÝÛos•¹XÕj¿-&NfbûíŒH¨äš[8[¾ƒ#æ9µFôØ?Á`°Ú»V—TUlÅ~¡d§ì¹EA8†ßïϘk±Ðó¨zJ‰OÆfeL&^ À,˱¬ªªýÜñbs²¯G•Q(y®œz“|ÏËãQ%ç6+Uq§üxî¬=S}î̇ñZ]<—ÖŽR®;žK§;žKkËdãµÐ¹`;Q=aûmí©Äõ(Pÿq9#*²,#‰ØA×õŒL˜Çã±À0fÇ]×팙išhjjÊXtŒŠ'*’Î÷SÓ´¢*’†aØÇGŒ×êâ¹´v”rÝ ð\:Ýñ\Z[&¯…Î¥Û‰ê ÛokO%®GúËÓª]€©àõz¡ë:šššì/[g¥EQx<´¶¶B–å1Ù/Y–á÷ûÑÖÖf?_UÕªU|dYF @8®êû:Y’$! ¢µµªªÚï§×ë-jß}>dY¶{"øýþœ¯±|ùò =¦V)ñYk±)ÊTÏñ)öa¢ñ"*6Îã¨( ü~ÿ˜JŽˆMqœŸµ#_<ÖÛ¹R”i&Æc¾çå‹ÇB=‚Á ÚÛÛ¡( t]G0,iÚQš<ž;kÏTž;‹é½Éx­žKkG)×bßy.¾x.­-“×|çÒ\ØNTÛ¦sûm1õ·ZTîëÑ\ê1.OI- 3#èºnϷ笴˜¦i)2Mªªâ”SNÁÁƒÇÌ“i$Iªj ˆrdïG½™èûF …088ˆh4ZñçÑÔ*%>k%6e©×ø,5^¦*®©²rÅc½+e™iñXɸï©,Ëœ¢¤ðÜY¦úÜ9Ñí2^«ƒçÒÚ1™÷“çÒ™ƒçÒÚ2Ù÷”×¡Ó ÛokÃT_ÖS\Έ*ÂxÁ4M´µµ¡¿¿Š¢ 䜿q**<†aä]0IUU¨ªš·Ån£嚈RÞÏÉ÷ªÅabd)%>k-6§2>+›ÎçNT5âšÊ/W<Öë¹r&Çc)Ïj Ï™Û)w¹&cªÏÕØ.g&œKgÂu§xÍrblÖ–Z?—µÙNT©sédßS^‡N/l¿ÍÜF%Ê5Qõ~[n3*¡2Y–‡íùÚdYFUÊ"PÊWÖ©ØÆTls2e˜Lf²–3šTX­Äg¹b Ü±T‰íMe¼0>ëG­Ä"Àx¬Ôóhú¨•xe¬eª•ØxÝYL9×3ãuj·7Õãõ‰q95årnk*¯Gë).gÔ”_DDDDDDDDDDDD“qjµ @DDDDDDDDDDDTë˜P!"""""""""""*€ """"¢ ‹ÇãH&“Õ.åÀø$ª]ŒO""ª5L¨UP"‘Àúõë1<<\í¢QÆ'Qíb|Q-bB…ˆˆˆˆ¨‚î¸ãŽjˆÆÁø$ª]ŒO""ªE§U»DDDDDÓUOOš››«] "ÊñIT»ŸDDT«ê>¡rË-· µµµÚÅ(ÙáÇ1{ölœqÆÕ.JÉöïß³Ï>»ÚŘ²ýØ»w/>øÁbÕªUÕ.rM¹çž{ð?ÿó?¸ð «]”’M—ÏôLüžyòÉ'ñío»ÚÅ­9]]]¸øâ‹«]Œ’½òÊ+8qâæÏŸ_í¢”lº|Ï{L> —Ë…[o½µÚE®¨x<ŽlÙ²6l(ê9ï~÷»1oÞ¼º¯WÌÄsN­+æ˜<üðÃ8|ø0¾øÅ/Öýg°‰ÆçÃ?ŒÏþóX¶l.¹ä’j¿$3é3]/ “ÇcÇŽ8zô(~õ«_U»¸7Ñø\¿~=Ž=ŠeË–aÙ²eÕ.þ¤±n[{Š9&{÷îÅ3Ï<ƒ·¾õ­èîî®v‘kέ·ÞZÓçÍZ?—ÔÃ÷B­Ç{%Úmë>¡ò—¿üŸùÌgª]Œ’iš†ææf\vÙeÕ.JÉzzzpÓM7U»S¶š¦q‘¼öìÙƒgŸ}ýèG«]”’M—ÏôLüžyðÁ«]ÔšôÈ# ³³³ÚÅ(ÙOMÓÄ{ÞóœsÎ98çœsª½ “ƺmí)昼ôÒK8묳pàÀj·&8pn·»ÚÅW­ŸKêá{¡Öã½í¶uŸPY°`AMf±‰ZZZ¦ÅV·Û=-ŽI±û‹Å0oÞ¼j·æ,[¶ çwÞŒú,Ôº™ø=³`Á‚jµ&566N‹Ïtcc#æÏŸ?-öeº|ÏLä˜:t¨ÚÅ­¨H$‚ææfŒŒŒ ‹addñxy¿‡—,Y2-FîÌÄsN­+昸Ýn:thÚ×m'ŸóæÍÃW\~ðƒÕ.~ÉfÒgº^{LfBg¡ÉÄçÂ… §Å¹“uÛÚSì19çœs‹Åª]ÜšTëí¶µ~.©‡ï…Z÷J´ÛÖ}B¥Þ{ Õ.BÙL—!ŽÓe?ªeùòå5=¬s"¦Ëgß3$L—sgsssÍV|'jº|¦§Ó1)‡d2‰Í›7°.Ö¶mÛ†‘‘‘ññœS{¦Ó1)‡™ŸüLמérLÊe¦ÆçtªGM—Ïôt:&”[­ŸKêá38]â}"ê>¡BDDDDTk²/,:;;ÑÕÕUÓ½·ˆf Æ'Qíb|Q­;µÚ """""""""""ªu¡BDDDDTa½½½Õ.ƒñIT»ŸDDTk8B…ˆˆˆˆˆˆˆˆˆˆˆ¨&Tˆˆˆˆˆˆˆˆˆˆˆˆ `B…ˆˆˆˆˆˆˆˆˆˆˆ¨&Tˆˆˆˆˆˆˆˆˆˆˆˆ `B…ˆˆˆˆˆˆˆˆˆˆˆ¨&Tˆˆˆˆˆˆˆˆˆˆˆˆ `B…ˆˆˆˆˆˆˆˆˆˆˆ¨&Tˆˆˆˆˆˆˆˆˆˆˆˆ `B…ˆˆˆˆˆˆˆˆˆˆˆ¨&Tˆˆˆˆˆˆˆˆˆˆˆˆ `B…ˆˆˆˆˆˆˆˆˆˆˆ¨&Tˆˆˆˆˆˆˆˆˆˆˆˆ `B…ˆˆˆˆˆˆˆˆˆˆˆ¨€Óªñ¢‰D‰Dàv»sÞçr¹àr¹ªýþÍ(ùbÓy?ã“hê1>‰ˆˆˆˆˆ¨ÒØnK”ß”'TzzzÐ×ׇ––$ 444àî»ïFCCúúúÐÓÓƒ–– £»»Õ~ˆf„|± €ñITEŒO""""""ª4¶Û6¥ •D"Í›7cË–-hnn¨ªŠ¾¾>tuu¡§§›6m‚ÛíF<Ǻuëàv»™ñ$ª°B± €ñIT%ŒO""""""ª4¶ÛgJ×PI$p»ÝvPÀêÕ«122‚X,†ÆÆF{(Yss3š››‹ÅªýM{ùb㓨ŠŸDDDDDDTil·%*Δ&TÜn7z{{íÿ“É$àr¹ÇÇd4í9ûƳ{÷ntvvNånÙ:;;±uëÖj£dùbÀ¤ãsëÖ­èéé©öîÑ ÇÑÙÙ‰}ûöU»(%«D|îÛ·èëë«öîÑ $¦ Ø¿µ‹BDDDDD)•l·ÇãÕÞ=šzzz*Òn;¥ §{hXGG‡ÝÓÖ©˜!cË—/Ïv¢©ÔÛÛ‹µk×V»e•›&Ÿk×®Ewwwµw‰f ææfôööbñâÅÕ.JY•+>/^ŒÞÞ^ÎwKUÑÑÑîînœ}öÙÕ. åPîv[稢©ÒÝÝ]‘vÛI¯¡’L&1<<ŒÆÆÆ E2™Ä† H$°qãF{¨Xccã˜Ç& Ñ/6Æ'Qµ1>‰ˆˆˆˆˆ¨ÒØnKTؤF¨ôôôફ®Bgg'zzz‹Å ªjQ÷֯_—Ë…h4šÑ ÔÜ܉j㓈ˆjÕ¤¦üêîîFGGb±˜=*Åív3™BDDDD”rÇw ‹Áår!‘HÀívcãÆÕ.ñITËŸDDTË&œPéëëƒËå‚ÛíFGGGµËODDDDTsâñ8¶mÛ†ßüæ7hhh@"‘€ªªèèè`O[¢*c|Õ.Æ'ÕºS'ú„D"žžžj—›ˆˆˆˆ¨f% tttØ#¸Å\Ó###yŸ÷òË/#‹U»ø4CÅb1ìÝ»·ÚŨ¸ÉÆçÞ½{Ç«]|š’É$b±^~ùåj¥â&ŸÇ·gP!šj‰DO<ñ^yå•j…ˆ¦È„G¨x½^$“IôôôÀív¹?×mDDDDD3ÉêÕ«±zõj$“I #‹¡¹¹¹`]ùÈ‘#ˆÅb¬SSUÌ”„ÊdãsïÞ½f/yšr###ˆÅb8räHµ‹Rq“‰O‘Pq»Ý\,›¦\"‘@<ç2D3È„*‘H}}}€Í›7¹ÿ©§žªö>Õ„D"Í›7#‘H`õêÕ¿xñbtwwW»Ø4CuwwϨÙ&Ÿ«V­â´×T.— ÝÝÝ3j„ÔDâsÁ‚‰j㓈ˆjÝ„¥ÅbèééAww7þ÷ÿO=õ¢Ñ(Ün7Ö¯__íý!""""ª ¢Q°ŽÇãœÛ¨F0>‰j㓈ˆjÙ„G¨  ££#c¨¥ËåÂÆ‹Å¸ˆ&Íx°§)Æš5k8] Q `|Õ.Æ'Õº 'TFFFÐÐÐó¾ñn'""""šiz{{í5].{×ÕÆ'Qíb|Q-›pBÅívcóæÍX³fMÆz)}}}H$hii©ö>Õ®/HT»ŸDµ‹ñIDDµj •ŽŽÄãq¬[·ÍÍÍhllD"‘ÀÈȺ»»9J…ˆˆˆˆˆˆˆˆˆˆˆ¦ 'T`ãÆèèè@,ÃÈÈV¯^5kÖ0™BDDDDDDDDDDDÓÒ¤*€5ü’C0‰ˆˆˆˆˆˆˆˆˆˆh&8u2OŠÅb¸ãŽ;ìÿûúúÐÓÓƒd2Yíý!"""""""""""*» 'Tâñ8:;;3ns¹\ˆÅbX¿~}µ÷‡ˆˆˆˆˆˆˆˆˆˆˆ¨ì&<å×¶mÛÐÑÑ7Ú·¹ÝnÜ}÷ÝX·nb±ÜnwÁí$“IŒŒŒÀårÙ·% $‰ŒÇµ´´pm¢)”+6Æ'Q-`|Q¥±Ý–h|N¨$‰1 9ÐÐÐ0¡ŠD"€îînû¶žž d<®û~­z€IDAT···¨ •G®ØŸDµ€ñIDDDDDD•Æv[¢ñM8¡ÒÒÒ‚¾¾>tttd$VÇs&[œúúú‹Å000€®®®Œû’É$‘¨JòÅ&Àø$ª&Æ'UÛm‰ ›pB¥«« ‰DªªÚ422‚x<Ž7L¨´´´Àår"X‹Ý;§#¢©“/6Æ'Q51>‰ˆˆˆˆˆ¨ÒØnKTØ„¥€7bË–-hnnFss3Ö¬Yƒh4ŠŽŽŽ‚Ïmnn†ÛíFcccÆíÉdpÇwàâ‹/ÆUW]…¾¾¾‚ÛÛ½{7:;;«ý>Ò ÕÙÙ‰­[·V»e1^l“Ï­[·¢§§§Ú»F3P<Ggg'öíÛWí¢”E¹ãsß¾}èìì,*Ž‰Ê­¯¯===Ø¿µ‹BDDDDD•j·ÇãÕÞ5šæÚÚÆÞÖÓÓS‘vÛ¢F¨ôõõ¡¯¯kÖ¬ÁêÕ«ár¹ìdJ¹$ ¸Ýntuu¡··±X 6l€ËåÊ;”lùòåèíí-ûCTŒÞÞÞ‘0˜l|®]»vÌZDS¡¹¹½½½3"á>™ø\¼x1ÏT5bÚØX,Ví¢QØnKµ.{[¥Ú$‹J¨ttt`Íš5ˆÅbؼy3‰„=2¥\IÑø%¸Ýnû597Qu1>‰j㓈ˆˆˆˆˆ*‰×Tëd0 ë·Óï~÷;¬X±¢¬¯Uô* X½z5V¯^ ÀZ„¾¯¯¯lÉ•D"d2™±†††²î,M㓨v1>‰ˆˆˆˆˆ¨’xÝIµN’Æ&T ÃÀC=„Ï|æ3e}­I­¡«W¯ÆÆÑÛÛ‹5kÖ`Û¶mX·nݤçÄCÅÄœ|Éd¹'¢Êc|Õ.Æ'U¯; "‘òmË0M+ü¸ööv躞ãùšššìíI’5õ×~ð |>Z[[±páBÌŸ?¿¬ïCÑ#Tò)Çz*ˆÇãX·n\.†‡‡ÑÑÑQÔB÷DTYŒO¢ÚÅø$"""""¢Jâu'VD–U-}[Ñ( ë€ÇSèqQx½ÞŒÛt]G4…Çã¦iðx‚e+¡òéOïÁþý?ÂÇ?.£¿¿Z1Y› šPB%‹!‘HØÁÇí¹›››'´ÐK®‰6n܈x<Ž‘‘¸\.f9‰ª`¼ÅŸDÕÇø$"""""¢Jc»mõV¢I‹JÈ^£d² ÃJ¨D"Vr¥¿ßºÝ4M„B!ƒA†Ó”±gÏ‘Œç¶µµA’$ô÷÷Ã4Müüç@×ߎ~ÏÓ81çÛèéù{ÜtS àÑG-û{Pô”_wÜq:;;‘H$Xsç­_¿€•LÀ† J.Pss3Ün7ƒ’¨1>‰j㓈ˆˆˆˆˆ*‰×•'Ë€i–g[†a RÆyºÅJ~”ÓO>‰óÏ‘Hzê/Ó4ÑÖÖ]×ÑÔÔ„ÖÖV44|/ÙÏÓu££ÿ¦iBQ¨ªŠGyêåÀ‘gã‘GBˆÅZʶϹ•P‰ÇãØ¶m¶lÙbB@cc#6mÚ„îînôööb``ÀN¸ÑÔ±FvXɉrOye¥=_¬‡bš,„$¥ï ðx<èïï‡×ë…ßïÇÂ… ‘HMMM¸ë®âĉappàñx°wï/p›¹ï>å¹)y‹J¨lÛ¶ n·;c”X,†Õ«W£¡¡ì¡^L¨MŒ˜ «>Ÿš¦A–eYh4ZÔ¨MÓÆ<·¯ï¯%•KÓ4´¶¶BÓ4<òÈ#x饿@–pøÙÏî‡aðûý$ ~¿~¿W^¹{ö<`Oö—¿¼ÇŽÍi*öv½Þ0¾¿¶ŸpAUË7ÂgØ UU¡ª¬_ÿÙ1ëˬ\¹¯¿ýu|`ñAøý¥¢)¤¨„Jcc#b±˜ýÿÀÀÀívÛ·%“IÄãq466V¶ÄDDDDDDDDDDDÓP¡¦i"‰ÀÌz ¦iÐ4 ^¯º®ãĉ$“+¡iB¡¢Ñ(¢Ñè˜çGL¦ëz*ÅÓO7@×ó'-œë¬ð‰O,ăεG ÀêÕá¯ý_<ùä—pÝu×! AQû9B(2TUE(H’µ–‹Ó׿މ÷Æ^Ä{aPñx*{|ŠJ¨¬^½‰DwÜq‰Dàv»í)Éd===p¹\Ó‚Qqò%+D2H¯GXSyÖÈÇÓ4ñÞ÷^¹sçÂçó!‰  bhhhÌ];͘aˆF£PýýýP ÿ…sÎyíí@®YÃLÓSö¶6À㉠™LB–eH’„ƒ⦛æáÍon„¦i¸þú7"_šQ‘ó¹öÚchhøfjú2@–¿ßú-Ì™s-¢³e@ÍÜ—­[ߎ§ž:«¬Ç§¨„ŠËåÂÝwßX,† 6 ±±Ñ^œ>‹áª«®B,æM›ÊZ8""""""""""¢™ÀãúûÇ¿_LÛåÉ1 CNeE¢(xùåsqÎ9‡;wªö(§üà8‰—íÿMÓ´“Š¢Økš\xá©8~üyð»ß%Ç$fÚÚÚ°qã]p¹¶Ù YöîýT5”ñÚ¡pøðEPo}ëÜŒíHR£` ü˿ĩ§þ€u›¢X¿EBG×u,]j%cî»ï>Dµ¨=B&bÁ‚~œwÞñ²£ÓŠ}`ss³érjiiAoooÆô_DDDDD$ $ `}™¨Æ0>‰j㓈fª@Àú=8˜y»išhoo‡iš8xð @FBCŒ&ÓyY‹»_Š×^{2gÅéç?ÿ9zh >÷¹¿ƒªª0 Éä'ÑÝý Ô¬K–,Ù U|7|¾‚ßï‡aX²ä]8qb¾÷½_„®[É… ,]: ç {;†a­}ò7ÓY¼^ë6I²î_¾üa\yå'0:ú-¬\¹ wÝõ%Ȳ]×ñòËcûöa×À4M,]º»¼zý«Øñô´µµ"é‡$Ixøáã=ï9YÖcTtBe< <¹eéééA__ZZZH$ÐÐЀ»ï¾Ûž6—ˆª‡ñIT»ŸDTo|> .ßö²—81 º®C’$x½^Ö(=kž.¯×k'@< hhXn?'›a©µQnÅ“O>‰¦& R*£‘L®ÄªU—g<~þüùøë_¿…w¿û~ø-ðx<öŒ· µ5„/y>n¹åy<ÿ<0k֙ؿÿ•ÔÈ™¹2;_ùÊß@’$˜&ðw·'NœÀ—¾t4 øÚז⡇¾þp8räzøýÖÛn»—\òtýthšYã × Ü»ï™ûü÷Ž»ðàƒC¸ôÒÙ˜7o.¾xoYwÑ •D"Í›7Û'3¯×ËõRˆˆˆˆˆruç-[¶ØufUUÑ×ׇ®®®jhFc|Õ.Æ'Õ#M+_B%»†ŠÏ烮ë‡ÃöT_"ñ`𿏠Í?>7çô`â¹ÖöÜ}÷§áñxàõúñ£íC"qzÆ:%ðoÿv:Z[u†Uí†×{+ ïzÐÒ¼ã?ÂÿûßÁK/½^x!Ö¬Qáñ¤GŸbŠ2I²¦ÿÚ±cþõ_·áá‡ß„[nù-nºécX»Öºÿ+_y7öí `pp­­­8pà\yåoS外ÙXsëÿ׿ºp_ó Xºtvì¸ k×> ©¬Ç»¨5T ³³±X ÍÍÍH$X¿~½=ü’ˆˆˆˆˆÒ‰ÜnwF¤Õ«Wcdd¤ÚE#šñŸDµ‹ñIDõ¨ÀŒZâóÎU7D²D–åŒÄH_ß èºMÓðÛß^…?üaΘ鹜Sh9‰‘-¿üåµðx{–,¹·Þúk\}õivbÉãfÍš…¯~õ€þþ~¼üò¹ˆD"P² ¨Ï®ë\€ ¼ûÝs`ÀÞ½ŸÆÖ­o/ûñ.*¡‹ÅH$°eËtwwcË–-hllD___Ù DDDDDTïÜn7z{{íÿ“É$àr¹ò>o÷îÝèìì¬vñi†êììÄÖ­[«]ŒŠ›l|nݺ===Õ.>Í@ñxؽ{wµ‹Rq“‰Ï}ûö¡³³“mTT}}}èééÁþýû«]ª¢¬<Æ„†ˆ#{!fòŠF£PUCCCÏÙµëBD£Qx<¬Xq+>úÑïçÜv4j%BššàX(Þrüøû1gŸ½ ²,CQ¬Q2"A’-×ôaŠøýéÇ«*pþùoǹç^ƒ¡¡ÁÔ÷Ö~‰)ÂÄZ1ÂyçÍÅßþíéX±by¤ L½žµ‹ß¼ùÍ+ìò_{íœ}ö·‰Xå7Ž¥6dZåÑ4ëß={—ýx=BÅívgÌW¹zõ겆ˆˆˆˆhºÀºuëàv»ÑÑÑ‘÷±Ë—/ÏhH"šJ½½½X»vmµ‹1¥&Ÿk×®Ewwwµ‹L3Pss3z{{±|ùòjeJŸ‹/FoooÁ&ª„ŽŽtwwãì³Ï®vQ¨ŠÌÑÅŠD"ðù|ˆD"v²¾öµï!@Q{dŠ®Ã5bÀªUŸ„ßï·ÿ×k%$1]XCÃÓ0Ít°¦î ŒìYÄœ3‡9ÿÖ4kÿûû­ÿ;:.ÄâÅo½#ËVÛÚt{?C¡ÚÛÛ¡ë:ž{î4ÍQ3wî\|øÃ—¦0Öóå€K.9÷Ý÷&kZ²ãn³¶ Z?矿¯ìÇ»äE鉈ˆˆˆh¬d2‰ 6 ‘H`ãÆp»ÝÕ.¥0>‰j㓈¦#Ó4í%‚XlÞ0 „ÃáÔ(ŠÜ~ûÏð쳃vòCдôè‘pø$`phmÿµ#+9¢(™Ó“‰j㓈êÍÎ…×QÑu=cZ/Á0 Ȳ UU¡ë:ZZv`Ö¬ÝX²ä]hoÏL¦D"é×ñzÓë£45Y#@œ ÀºMQ¬Û #3!òƒ<ˆ††ýöã–/8•ðIo7v–ìöMÓZóåÉ'ŸÄ½÷Þ ÀJ†( ìäˆÓ¡Càé§píµÁ?ÿó=PUŠ¢  áßÿýRøý™¯‘ÊÞ·p8•T¹Ð§îˆpìç¢Eå_ƒ«è*ÃÃÃó9‹éãñxÆã8EÍt}}}H&“X½z5b±˜}»Ëå*¸NU㓨v1>‰¨55Y£Dò­¥Í1'˜®ë$ J*k ª*¾öµ_àÚkã8ë¬O™rË9úÃyŸ$YÓm55YÉA$` Ú¢K×ÓSu=ýôkXºôTÕɱxñ(Ê S—‰× ñ[Ó4lßî‚,_ƒhhk»¯½¶ÐÞn½¦$££ÑÔtÂá0dYÆ»Þu)¥K—"™¼²lÜ1 ¯C–­D‘™âœVl<†(‹7Ȱ’*©ÄÎãB¹'é*jkhiiɸ'2""""¢Ü‰‰Ä˜滺º¸Q•1>‰j㓈êUvò#›a0CD.–,Y‚7¼á“ek¤ˆÇãÁ¯½>° ©µã3hšµ6ˆ¦¥G ˆD‡• HÿXIIÊ\4þò—¿àÑGoµ§ú¾ßüæ}Ðõ[2öÉ™Äå‘$ ££ƒˆD®i÷ÝwæÎýNž|üTõT¨* ëÏÀçD(‚¦iØ´é—¸à‚k¤GžH’„ÁÁÁ¬÷ 9÷=ûq+S¿=ÇâØ±9^-ë±.*¡"@#""""¢Âº»»ÙðCT£ŸDµ‹ñIDõÊ9ú#[4…aöz(mmm8묭8qb.¹d-¼Þ9¬*€¦0 +qâäL”äš +ûñb­I²~DòAQìÞý ÞùÎ-0ŒuÐu ±ñt<óLkÆv%ýœ§Ÿ~‡`4MÃ[Þ"!²¶{å•7båÊ?áСc=ÓœI’ÐÞÞŽ;w"#œš?LL=–µ4ŒMÓŠ™âÜGýA¢Ü&€A«ü?\þc=á5T‰úúúÐÓÓƒžž{8æD%“I{Ú°ìíÇb±œ÷Qå›ã“¨ÚŸDDDDDDTil·-Ó4ÑÞގŋ߂W^¹€•`yùåNœxæÌ™“ñxE±Fª|ùËû‘½äŠXßÄ0Ò£FÄt^€•Œp®[‰¤§ìÊNÀlß~¬ù±¬ûM³/½ôPÆcdÙÚ^{;ðÕ¯v`däÎÔã%x½^ttìÂ+¯tb`à%ȲŒ+¯\€W_]×ÑÚÚ:fä‰(oöÚ*Ùû_ìèëýä3å€(tæûµvíe?¦J¨ôôô@UUôôô #ãŽ;îÀ7ވ͛7Oè…#‘úúú2nëëëúuë°yóf¬[·nÌýDTy¹b`|ÕÆ'UÛm'&L¯ûá¤iÚÛÛá÷û±qã]Ø»÷]Ð4 «V}¦)cïÞwYè=‚Á n»íléEÚÅÂòbMñ¿sª1q_f`'f² , ™X½z zèz44ìG(|ík_ÃÖ­ûðâ‹'±qã½킦iöš/táÖ[¿‰£G/…™*È¥—ΆªªPU‘ìŒÒS”e¦™,Ã"`>é¼±üÇØ©èYÄh”7¢££Ã¾=™LÚ#Vk^Ë|úúú‹Å0000æ±===Ø´iÜn7âñ8Ö­[·ÛÍõZˆ¦@¾ØŸDÕÄø$"""""¢Jc»íäüò—Ç Is3’*>ŸÏ^pÞëõÂ4Ë/ß]×qÁWbÿþÌßg‚EQÒ ñ[,.od±nIk¤Iúù‡Â#ðx®´o3M`×® ñÒKó±pá!<úè¨êõX¹2Š•+¯Å¼ycÞ<«Pgu~ÿûÝ8ãŒãxàíØ½{ úûû!Ë2dYƱcqx½ ü~?€tbÉ›+Äôh™@È1€ª:±*^/ ý?à¸Q†5õ—Tüv&¢¨*ñx›7oÆÝwß‘L€††{q°\Y§l---èèè@sssÆí±X p»Ý¬u[š››‹Å*³çD”a¼ØŸDÕÆø$"""""¢Jc»íÄ™&ðàƒs3!Ñh‘Hº®ã’Kn‡iJ0 `÷î•ÐuK—.…,gN×UˆXEÓÒ ”@ smk!øôs^xá,\¸Ðžî+î¹çiÌûÌšu6ÞøÆ¿à¡‡^Âܹsñ•¯ÜŠßÿþRlß~†aÀ0 \wÝH&W¡¹ù<|õ«øÆ7Þ„ÁÁA{„Šßï‡ß¯ŒeÀN¸À Ç(œñ¤ò2E“$@~CÖÞ‰mc¢ŠJ¨Äb1¸Ýîœ 9BWW’ÉdÁ@jnn†ÛíFcccÆíñx|LF³±±±àœ|/¿ü2ƒ—ª&‹aïÞ½Õ.FYŒ›ÀäãsïÞ½ˆÇãÕÞ5šÄùèøñãÕ.JY”;>?Îyo©j‰žxâ ¼òÊ+Õ. 9TªÝv2ëo׋ßÿ~/-c]×!It]Çÿx¦I&φ®ëøèG›á÷[#5|¾Ì퉵Qkô…Ø®3q"ˆÞÏq&h.¸`üÕžê+¾ÿýçðóŸ?Ž;ï\÷ÞKxpá…ßF4j ”øæ7oµ÷aÖ¬Gû·§C×¾¾F+I’"Ë2Lsüæ­BÂ-’µÎ2—B¬)ƒhÖšõ¹­D»mQ •‘‘‘¢6&²”“‘ë5Š2väÈ&T¨j¦SB%ŸÉÆçÞ½{1<<\íâÓ 4222­*…ö5[¡ødB…ª)‘H ãĉÕ. ¡ÔvÛbÛ–ëÑÈÈ.Q=zÔ^×Ä0 x<(Š‚hª¡?\€;wâ׿^hÔ1’½æ‰smMKæ0 ØÏñx¬dK0h­"†a@–Ó£Txàn\qÅYööؾý:œþåxâ‰ã¸èß.ŠÅ¡Cmðx<èï·¶¥ª*¢Ñ(TUÅèh樘lR1ÓjeMj¥(°ß—r0g € W/¡ÒØØXÔ¿”ÄF®^·Å4ô,^¼ÝÝÝecˆŠÑÝÝU«VU»7Ùø\µjÕ˜i‰¦‚ËåBww·½ÀÚt6™ø\°`º»»KêA4Yn·óçϯvQˆˆˆˆˆ¨¥¶ÛNçuVî½w,¸·ß~º½¼®ëðûýøèG¿`'BI’`šéfn/Hÿ-F§h23­­é‡aˆQZ[[qï½/ؽüòÏbdäT44ìG{{;^yåhhØÃ‡㇛O`öÑÙ¸fééøùÏ÷@’${t‹¢(ðx<öhE» ½ Ë@8œç R`PqŒRQUÀ[Æi¹‚·fÝ Z¯ÛÑÑQ‘vÛ¢*«W¯F<Ï›0éééËåštãLssó˜@™ÖGT/ŸDµ‹ñID4 fé› """š)xÝ™›išxþùç±`Á\tÑaìÙó8î¿ÿ~H’Y–qÙe×Âï·’Á`z}çÂëmmão_–Óë¢èzúçýé)Á$øý~¬[·ßN° ü_|.ŽÙ¯×‹+¯\€w¾ól|éK'¡¼8ä;y‰Œk®9=ãu%I‚êx!çÔcã•s\©ä†³þ-IůS ï»rÜhLx3E+*¡âr¹ÐÕÕ… 6`óæÍóÞ%“Iôôô`óæÍ%q»Ýö-€5ÇY"‘Àš5k*·÷DTÆ'Qíb|MP€èa§Áº¸«àQ½ãuçX@mmmXºt)–,Y‚¥KáG?º‡‚?•9#QdÙybšéuOLG‚Á9–3Ñ ËÖˆ”H$ý¿ø½hÑdÙD¿u[(‚$IˆÅ~ˆ­[ŸÄ×¾6‘H®¼ò þüç?CUU|ï{Ÿß|þó—âýDZ`ç¨o0qÍ5/çÝWM³:“UÒ+©RÉM Æ.Dobìº*erZ±É’H$bFA2™„Ëå¦M›°zõê’ ÓÝÝ 6 ¥¥ÃÃÃèîîFCCCeöœˆ&„ñIT»ŸDDy°æQFê·óâÊÀŸzLµ JDDDT»xÝ™IÓ4 A×%Ü~ûýعsË–%±cÇÍöcÄÔ[†{m1˜39"îÍ|+ù¢(À¬YÂçû&%Œ}èS¸é¦eƒÐ4 Š¢@Qhš†9sþ€ßÿÞ…h´ÿññÅ/ZëW¦·û àõo6WàÍÿ¾"ï¾–´æ‰Mý] zjûŽõg §nŸUþ—+:¡Xãõz‹Åì…¦Ýn7Ün7‰zzzŠ¥ÒÛÛ;æ¶ŽŽ{[.—kÆ#ª†\± 0>‰j㓈¨éä‰ kL ÖH”(€QXÉñ8‘Lñ¦~Ë|="""¢iˆí¶ãs¹þˆÏ}î/PU’$AQ€¿ÿûÓðéO7ÞøÑÖv)y ¨ªµ°¼st‡HéEÝkZ0± ¼ ËÖO(\sÍ…e—^:ŒþðTUE(‚išPU²,Ãï÷#ÞóžM¸ú꿪.³á0êÀØQã gâ§hC°ÚŸW*@@–¾žPB°zõê1£Q‰DÉÓ~˜ÑITëŸDµ‹ñIDuÍÐë‚«”m´Ø™ú?€tÒ$„tòÄ0ˆtâE$X"ÈìÕFDDDDxÝ ìÛw>¢Ñ‡ÐÒbU&u¸÷Þeù>ùÉY…Æ>'´¦íòxÒ ‘HQUëïPÈz\6‘x‘eàÛßþ6vìˆ V‡ … ivîÜ™ñY.¸à8ýôÓ‘K(H§Ãª`Õó¤ük¨äÕ–Ú¾>ÉçCÁØŽQYë¶”SQk¨•Ä€•´¢HO½ÅÄ/² ¤{ºµ¦¶­¤~‹¿ÅEéNÇ}~X\Oê1J¯@æZ+"Ã5XˆˆˆˆêŠa¤×%)V4j"9yòEÜ{ïÆŒEÛEQr&EÚÛ­ÄK4j%3̬ÚÌÅæÓå4pôè÷ ËÀ½÷ž@só\ìܹ‘H†aÀï÷chhl$YþñÇŽLÉxÌ›0¡)¸Âá’*€Uï®Ðš&Бy!9Çæ”ýå˜P!""""¢Ês'¿}°F¦h°æ8ÉŽPê±­H÷¨ÒÉ/ÒjÙS¨©û²o—S?bôJ@SjÛ ‘ž:ÌÙãP$qÄ~Q]ë˜LD4j%5N?ýe ¤ÔY®»î$@’¤ŒDM0˜X Ó´’‚˜NkïÞ½Ðõ̤…išØ±ã‡8zô{xñÅ“hooô÷÷CQ¬2ˆrä*opœÑײ ¨ RÿxŠÛEIïǤˆNMSIïY\öÍ2¡BDDDDD•§Áº`kšøa-/ÃJr(©Û°í° ÒI-õÛ +A¢¦î‚jj›¹æƒ–J±`j[^X#Zĺ*C°)Rê6¬dŠ +¡b è Q""""ª>YÎ%2žÕ«Å~ð¼ýsóó8óÌËÈPR™ÓfÍZ Ǫ:•ok³~KRzÝ”HÄZhÞiÆãx晟à‰'ž‡$EñµË¾Ã0‰D Ë2^xa\®³ì×,F¾Q8’DDe§ãtdvN*§ñF‹K•I¨µ†J,C,Ëû˜d2Y¡w„ˆˆˆˆˆêžHŸõ¦‡Ãc'hÀs(0ÏYyPI$èééɸm``±X,ã¶îîˆˆ¨Ï=÷\µ‹@D„d2‰‘‘¸\®j¥°(Ò ðQX<Xk£ø^4]‡u$g=gÒõôú$~zzÓ´.À}>«wâÎÖEy `]<ZÉŸÊœòA’¬$ЏÍSd¯Cµ˜÷Ù¹^Ë4>.åRWñI4Ã0>‰¨R #=2%±êrÑh‘H—\òßP«î'F™#Q¼^ëG¬_—‹µM  A’$躎ÁÁÁœ‰çvÍ'N¨(HOûUnÙ Ö‹õMÊ9FÉñ:bzÚ‰hoO4qP²*+ÀßfUÀ3º)³¢¥w¹\p¹\ˆÇãöÛíF"‘ȸ-W¬ DDDù„B!˜¦ MÓàóùX=Aˆˆª-‰ ¯¯¯ÚŰ Ü/’(âBªVE†u1$¥î ¦n÷£2ÓL±Hsc‹)ºtg8Ÿ/}=‰­­Öc½^+9 ZÉ‘þ~ëÏëµ®çr]7‹Û‚ÁÂe£Ê©©ø$¢ ŒO"ªUµêb¢gužÑá÷û1kÖ*{ĉ¸Ïç³’#Ù²´ ÃÀ¢E#hk{~¿ßžÞ+_2Eæ sTÇT,X×å~-ÖÈöl¾.qêï·z(ƒéƒæäàQ¬Ç<˜N¦è:ïÙSö·®¨*èèè(û‹•"Ú•’H$3ÕF‰D0{öìj‘ˆf°¾¾>Äb1  «««ÚűhH,ÉÅ9­—ëbG ÇŸÆk¢X½­qñ¬ëV%L¯g"IéÑ)^oæ|Û‚³3\×ÌT%5ŸD€ñIDSGÌeš@(dÀï÷Û‹Í‹©¼Ū#æš’u¼ºžÏçƒaX«¼àƒ$ ýýE3‘‘™P#GÊ=ò8;y¢ÂšŠk*ˆ‘7ù:‰¡CÅŒ4‰P¤±Ã¾ ?ö^/ó5I\C…ˆˆê†®ëPR'SMÓ Ë2­ Цiðx&×Ô«ƒƒéõX °†]„Ãa˜¦ I’Š•’At€ÄÂô•žÊU‚u`¢|ë¨ÈyÊ-FÄŒ—/Ñ´"ç»Åø×7Z ¾¨)¿„žžÜqÇöß_|qÆZìNe1MÓ®|hšÓ4íÛt]G$A[[ Ã@ @ ÀÐÐk8­¨¨D£Q¨ªj÷!"ª–ææf¸Ýn466ýœÝ»w£³³³r…’¤É4˜)±µÕZ ¾©ÉºÀFÓ‹Æ75Y÷G£éĈªf.?““$غukµ‹1%&Ÿ[·n³®(Q¹‰)Çãqtvvb÷îÝÕ.Þ”˜h|îÛ·œŒª¢¯¯===Ø¿µ‹B=;øSO=…¿ýÛ€aXÉIJ¯™¢(ã×ôâôàõzaš¦ÝtÂÉ”\*¹0ý˜7å¥bÂJvä¢bì´cN…z9eokœ„JÕ¦ü€;î¸Û¶mƒ×1¾ÉívcãÆèëëÃÀÀ6mÚTöÑô&’&ªª" A–eƒA»"bš¦(imm…×ëÅÐФToÃ0ì‘+¡PíííxÇ;ÞQíÝ#"šåË—£···r/…u‘4Þðú:èeÖE®¸–$ëbÖïO÷$ôx¬ë/I²¦[v®aé$¦y Koo/y¬]»ÝÝÝÕ.M¢ß¦¥§ÒóóG"Ö}"ù;4ÔŒ}¨½½ŸªvÑkÒâÅ‹+{î$Ê£££.— ±X¬ÚE¡ ƒŽ†aHؾ}€ôÔ^ÎuÏ Ògoã[ßzkÖ…¢œ…¶¶6ìܹ³ÌE:1QÎŽ?¹:Yy´"ÿT\‘/¡âÅøë¨˜fyz9Uhaú¢*ñx}}}زe š››3îs¹\èîîFcc#n¿ývlÙ²eÒ…I$c†t¶´´ ¡¡¡";ODÅc|R¹555app‘HÑh†aÍW … ª*"‘dYF0´“(~¿‘HAÇ ¾º®Û£QdY¶GK*:qÖ"Æ'E ©Ï…@zZK¨ˆFFY¶’&5‡µ˜vA,& Z÷æÞÎLuBD•'f%É5³H$b}O‰=ëñýýV{Q[›õ8‘øõx¬ï21Š.J÷~ú@µw•ˆf°z¼îoÃÁƒ¡i_…$y±qãz\xá¯íN;‘ˆU·,¦ãÇ|á 'ð³Ÿõâ½ïýtñë¤LjgPÞ„JÎQÞi¿òñhK½fƾK†ˆ)ÑrìÓk×¢©ÌÅ.*¡²mÛ6¸Ýî1ɧ®®.D"Äãñ¼Ë§§§·õööÂív—y·‰h¢ŸTNzª[q °)>Ÿ~¿^¯’$!@Ó4ô÷÷ÃãñÀãñØ 'EQ`TU…$Iˆ¦ºöy½^üñ¬ö®N Æ'EàGf/1 ÖSé ‘IªD£V¤,gŽ>ï:u¼d Q%D"éÄ®Ïg%M$)ÝþÓÖ–^—)M'PD2E¬³«ëùÛŒœ zûö}ÀõÕÞu"š¡êñºÓç³’#¡PfòòË]×RÓt-„¦M|@ƒ$™8å”ã¸ãŽO£©© Á`°ôιê´2¬:{9e¯Õ"è°® ÂÛܤˆHö1Å.F_„}çŸ_„J.H&“·¹\.ŒŒŒLº0Éd²æ‘h¦b|ÒD†]×áñŒ]Õ8Âëõ"‰@’$x<ø|¾Œµ¸‚Á =Íd¡^b„Š¢(öcgRB…ñIDE1`]¬È°†ò‹^\LÝb—YB©9šÅÂð€ÕØ(Ié^Ú‘ˆõÄ Uš˜r˹<¬˜^Ðç³n7Ít’WôböxÒ#åÄ4^ÁàØï.IJO%#Ì AÕDTçêõº³µÕúNvúïÿ¾+W~RmÖw{vâ¥Ó4ñ㟠YFù¦úÊ5bCÅøSg•›ÖÁå¥"¡ð¨šrM/6…ŠZ”¾±±qL¢ÄåreŒDI&“ˆÇã%&‹ÁårUû=!ÊË0 ˜f¹Óµñ9³éºŽöövûÓ4Jµ‚‰5N²…B!´··ç\^¬yâñx ( $I‚?k<­$IE÷ìë«ÌTŒO"*Šø:öÀ©’j8„ ëbgO¨FzÑNÑ+[4VF£VOoÑ8)z~ƒc ‰ˆ&K×­ï¡hÔúio·ÐLÓJšø|VbÄçšš¬I(”"Öh ‡­5šœ=šƒAëvE±æúû­ÇrÚA"šêñºS¬¡'æ€ÕqÚi§ÙÖ÷»¦YuU£ÈÄ…¦i…B8ë¬í•ßÖˆòrÊ—ÈPQžÅée¾¾P-_'Š¡²zõj{X×êÕ«s>&‰ ¡¡aÒYJ1ÚåŽ;î@,CCCº»»ÑÑÑ‘÷y»wïFgg' £ 1M3cëñ»ÑWðù|Pªªâ[ßúÎàœ9UXÍÄ'UŒHäŠéØC¡tBW$o£Që1Á`zÄ\±#GÂy¦Dáè“Ò0>‰jG©í¶ÝÝÝ“^"¢ÖúSVT,2‰Dð‰O¬ÂÃKR‹_y<ÖO PÜv5M³Û<Ê.WÓH¹B4µ½ñF€ûah÷£´ë1}X¡æ?€öTy$À^ÐF*òÅ=È9¦§§Ëîº g-Z”±í¶¨„ŠËåBWW6lØ€®®.tttØI±`}__6mÚ4é‚$ ¸Ýntuu¡··±X 6l€ËåÊÛX½|ùržd©(¡Pº®C–eȲŒP(”1/‰À0 {QëP(MÓìµt]·#zäïÚµ ·ÜrKµw­â&Ÿk×®e2¥Îišf'G$IB[[›'^¯>Ÿ²,#Ø#J Àa‡ÃPmmmÐ4ÍN˜8™’”®À”BÎjyknnFoo/:;;«ýVÜdâsñâÅ +Y1YÅNS&ÃZÏE$UÄBeÅ^0`%e²ÞÝ݇·nŬ¬eKJUô*ÝÝÝhllD$ÁæÍ›3îs¹\%Ï¡'¿·Û5kÖ ‹MûÞÿT~‘H¡PÇN€H’„p8 MÓ Ë2Z[[!ILÓ´¿ EÏ{¯×‹ƒ¢µµ€5ª%B–e ¦&Âõù|xúé§§ýg”ñ9ó躎h4j*뜈EâÛÛÛ188ˆH$b'HdYΙœÈ¤÷¬ùBØд3%/úVÇŸD”“sÎcÖ˜‘¢iVc¥ªZ¢¡Pzý±–€s&Sˆ(ÃÈÜÐõôT,bðtSS:Q+Ö4J?^–ÓIÓML=]w.\<˜>V=ô®»î…ªª‡Ãhk³nÏnÃðûÇO®†¶¶6„Ãaø|¾ò­™’MÃø£T ”¯ST¡íȰÀä“*9ßza%p´2í_Êî•+Ñ´lYY·9¡E黺ºÐÕÕ•Ñ£°±±±,C¶‰’Édƶʺ³4ýˆ'MMMvOw1õO?LÓ´§DOv¿ßoOûå\AŒHÿK’„@jÌŸahǃÏ}îsøØÇ>Ví·¢¢ŸÓO €aðz½PUÕžO–eD"D"x<;N<LÓ´G¡ˆŠƒ·ÜW£&¼Øš×ëʼn»N¤{$˜©Ÿ’ca|ÑX߉ Òók°¾'°Èf±Äúªjý¶å´~‹FÎ2 F$¢iÂ0¬ï ±‰¸MŒ,‘e+Y"¦k”ˆ±p°Hˆd.`Ýî4ƒûÜ•U=]wŠitt÷îÝx·Ýöûœ“kÚññ:ý˜¦‰@ €;w" aHdî+a¼ö ¬ú|¹S?Â52Ù„JÀ±bôúnÙ5Á× bÜÑî•+±ì¼óJx£ÆšPBE¨Dæ1‹aóæÍزe L&100€®®®²¿Õ/]×íu4MC4…ßï‡×ëE0´,ùÖG‘$iÌÔCÙ‹Y;ÿƒðù|PU'#{­ª*öî݋ÇWû­©(Æçô …ì5Kž|rTu=B¡0ŸmEQ0444¦§†Ué¨p—bÖI=«0’úgžY–áÔcZSS1åëT 㓈2ˆ©ÂúNÔa}?Š!ôeún4ÍÌ…;Ç»¦äô9D${×u+á!IéÛ‚ÁÌùêƒA+ "»dÙš¢K’¬ÛÄ´NñFDTyõrÝé•X뺎ÿüÏ.?þK|á K fNY Ó4+7ÅW69ÏíM°¦Ä*µŽ]ÌbñâqC°#“[övB³Ø¯ù+¸nÏ `üõ`*`R •Jèèè@<Ǻuëàr¹0<<ŒŽŽ.–;™¦iOÁ%€×4Í^¸ZUUô÷÷CQèºn'F²—ƒ¢(öÈћߩ«« óçϯöÛVQŒÏú¥iš=Â$ Áëõ"bÆ_"_ŠÁÁµ0 ¦iŒ1OuÑuÖIM†5r¤Øç¨°EÏ‹B‹¥VŽAX †bš›v—Où[>åŸD”ACúK\ü„þžœ±€'`M¡ IV£¨®§H©þ9ëÔDá\/I×Ó‰I²FˆÅßÃa µÕúÎpv I'Ñæ¼ Z"¢ê©—ëÎTÓ!t=½f_$¢áŸx8†SOµî›HnÄ4Mø|>{:s¥+¿ùÊ„U·¹­qw š¬¯S1e¦`ƒ ,UÒÃjLÍ$T`ãÆˆÇãËå²¾§éGLË%I’Ýà«iÂá°Ý[ÞëõÚ‹[{½^(ŠbO×åõzí¿C¡PÅ¿ÌE÷u-ZTí·sJ0>kW$É9õ–’êüüF"H’„Ë.[Šïßzœ\äÕ©¹ 0OŸ@ÁDѸ'cü¹@/2{Jˆg;Æ?y;§°q8°¢üox b|QçE‡éÅ$'rÑ”bšVehÈJ¬ïÜiõg»{}0 ÃîFíߪªÚ–Äã«N°{÷îš› jaXSo‰ï1U—®[ YNß&~ë;$¿OˆˆêC-_wŠ bzH±æ–ßou4uÎÂ!:å#ÚSTU…®ëåŸî<Ÿ|M4Xu} ¥-?Ñ„JÖz·ÀÔ$U¾ìM¯±ÛšKªÔTB@YÖc¡ÚFíÑ&ìõJdYF{{»Ýƒ>‰ ¿¿?gc¯¸Mü–¦dbn>Ÿ‚þþ™Û;Šñ95œó@g3M‘HÄNî‰iðD#‰8Ù[Û±¦ÄóûýÐ4 ^¯¡P(5uÝç³ÞWíq>¤×9)´À±«‡´áx^¾!X•‚ìýcü“½n•oÌ6û]ÿ´«ìǧV1>‰€õ½ëü>4`]0ɘpB%±.Lý~«Wy8l;ØøY]â\n†ÝQBQ{Ê[1²[–eDŪݰ:‰µE§¥p8œQ׎F£v’…f&ÓL*ñù¬ßb4I4jýȲµ^’©&ÖKòzÓÓr@Öl""¢êªÕëNÓ´ÎIªš1i ´:’8Û ÛÛ­sW¾‰¹+êMS6Ý`%Kò%-$d®—8QºüNä dF$X£ÝÛR¯[ìõ€:É2"õ¼~Xlk,©Rs šD¤µµ²,C–e{Aëp8 I’r&JLÓ´³¾b=”|Äý•žžÀÚ~Šb}ñŠy|‰ÊMÓ¬Þ|¢÷ž¦iö‚ðÑh¡P€¢7iw÷7 I2¼Þ$|>ü~?dY¶‡£éÅãÅZ@Î…EQ¬|ˆ¹ð{‘ž’+‚q§ó2NŒkR¹é©f|HÏç?æI@ôe@6²—¬JEcTë®dcŒÑL”ý½¬¤þ/òPôæ Ò½ûúû­ÆR&R*Ç9Ý–¨‹ú´¨ „B!{šN±¦ ,ËöY–í”"™‡ííÓIUU<úè£Õ~;¨ DOÝh4Ý(åñ¤§ðRU«ž*Ö@QÕÜÌfjÇ3""ª.qÞŠD¬sT(|ñ‹;ì©Ï%=5X.¢ÓJªg@ŧøš( éÅâ‡&ð<]·Næš|! ,Äëö#ÝTÌú&Jk›QP\ReНS˜P¡²óù|ˆF£$ Á`Ðî)Whˆœø’òûý£XòÙ™kÜx™I’„9s>E±. "ÎN…†uQZìÈP]×ñ£]Ž×_ÿo45Ý–Ú†;w"‰ " ÚkɲŒ@ €_|/¾ó9ع³p<ˆ ö ô%ÇçX¬;2náìÌS‘ÙAøCMo‘çÉeÅ}„µPrŽ^ úÇ€À¿Z `öÔ`AX½0 döp(öDND4äjÌ,â<¤ëé…¡ýþtòd ªY3†¦ieÙE"F—V@’$H’4¦¬( ‚Á ,£Qòõn®‹B‚a¤“"‚ÏgÝ&¦å2M+‰š+ÿ6•s‰ˆˆŠ%䙣$ÿéŸ~‚}È3ft‰ªZçD'1ˆ¨?Mé_ÙŠYüݫƇôz*Î…k'ECŒaX=Ä=k._]²fú˜Ì‚ñ&Ò3*kvûM!†aeÃ<žôÁT`%ŽtX#d¼Û5Å:˜P¡  Æé¹–#‘€ôôB¢Ø™.vh\[›¨àKP”âR˜Å®ÿP Y–qÁÃö‚Šb1E¢|"뵘óp4E{{;Ló ÞùÎÓÑݽ¦©A×uhš6fÎO5ubéïïGk+ 5¤6$Ú` „=˜?¤Ã:1 bü“Pð\ (·Y•¯7u^V`õ'ĵU·Î‡v£œèÕÐëDèˆ%ý+€´L¼'9¦>I¿cu@w²É‘cD4Ã×Å&z¢G"Ö÷ºßï¸n)Ðs,¹rwN³eš¦ò ®ÁJnø|é €aXo†è©*Ëåë)%ƶÏd“QÜ•P(}qâõŽm ’ž>,€ô:½bÛ…¦I+3&Tf Ñ©Øë0±¨µ˜kYŒ> ºbJUUJ'IéÊ~­TîeYƪU+ašQ†„h´ ¡ÐAøýÓNãÓ!äJ ˆxÒ4ÍmÒßßÏ|æ#¸å–o!‚AEA[[›Ýø’Ó ¼V¦Þƒôt/yò˜¾ÿü·¾Í€÷³€*æÖ7‘{¨¤ ‡->7Ëâ¦h˜á—ò'Ïñô{ç Ø9Âe7 ~,}ñ?::΄^À>h}¯!–cT ÑL¢£èÞY¢§º¸Ö2ÍÌÞç^kkÐ4Í>‹¿E"‘0Ñu=µVYúÍóz½¦NP¹$"9’}žŸŠNC4}˜f:Aê÷[ÕÂáô‚¼‘Hf»ŠX…u§©3^’TtT …BötÙ¡PªªÚ#ÓÅ:¤K–,©önÕ1ÚDt€¾ùæN|èCkívËl²<¶½1Ø#ÃÅ4FNftG9ˆžP€u"÷(€&YíAƒýLë )¦Ñ÷…| ÜA$4Z1¦³ì˜Ç"Iã‘ÍÞ^?¬v$ѹ· ƒ‰˜P™tÝŠ9Iʬ@‡B!{fAÓ4¨ª ŸÏgWîĨ“섉¹RÊBMbÄ¡¡ô½JrVj#‘ˆý¿¦iPÑhCCÖ„„÷ß1fϾŠ¢àèÑaÜu×;ÙÐ0ûè½EBE×u{-ñSUÕ^ó–-S±~½uŽ`'ZòõD•æÚÛ@ ðË€†ubɳ@™ÙDþhÅ[4 ¨Adö.È®€þ'@¹ÁúÉøìaÄ4dœ‹#ëýTÀûë]Ï:§K©òù`5ù@NÍ{*ËyF©øRûèXä^Ó²Ž˜»†ˆh¦P‘óÂN¬‡ zîRÉñZé¸R LÓD(²;0ˆé¸t]‡ªªkû‰Q$‘H~¿’$app š‘ˆÕN fþíìiÛÔdÅ·X˜WÈþ[唩£‹Ei; …ìï çIb­QÑð§i‚Á t]·GÁ‰5“ÚÚÚª½kDDUgé5S1£Ìm·mÁ7¿ùs<ðÀÏíßùˆ:žHbc;¹d4‰iÏu¤§¼*wÛà> èV%>Ìl€Ñu+kdšéͼ©û †d%YŠq0‹Hbä㇕ÐÁêh›=ó‰H<ÑtæKôìrŽ˜™èkžÔv5¤;O!&Tf«R&Ãë•°aÃ1ŒŽ~§œòŒ]áSÅNœˆd‚ø"ñx<ãfwë §˜/«|œ›×´qz¶Ø?±b.j1µ‚ø_|AŠŠsO±`·ø2€¶¶6˜¦‰cÇîG0´ß·½MLJ?ü>þñ©=†T=¡cª«"(  (:~ûÛ?¡µõ[vC‹Çã±{>ä#’ y§õˆÁëtæ¨7jéÊ1öänX˜ibOé¢ZÛCcæÂŒ†œf=GI%/2Š%ÖCiÍ|Mq1/¦?³+RêñQ=¨†õ<‘øÍ) k4nýx<9Ž‹®çŸ_Ê!'"ª/ââÎñýmšÖ5—¸à”å±jfÑ©A,Ò.F^G£Qx<D"û>çZ€Î:  :F³Ø;Q)œÓ­jšUOjoOÏê‰d¶¹äŠo®R:1Ÿ¸N ¥²XªªÂ4M´µµA’¤Œ4M³§÷Û¹s§=ºMtÞ̘êÏ)×µ÷å—_^í·ˆ¨ê4-58#unSUëügš&î¹çŸÑßßo·ñ"–1Æé ®ëéDÀ/tà×&àU­6±Æk¹gb]¨ZÓƒ¨ªÕKâàÁô}Á`î(^Xm$X×aäOô¨:kÿJía!ÁºþðØmJXªÿL¿9²l½–H•c)õš^XmJSˆ •$‰ ‰à™g"øÊWÞ•+oÀ³ÏÇk¯PUÕ®è Î/ž¢†»•³ò Z ’”gbNCQéÿK’„öövx<ûBY$†DCq¡ì¼ÎuìÜ÷`0Ã0ðÁ> Iz“}»¢(xûÛMlß~Üî)y{¨ŠDÏÞb™×4 †a`Õª•hk»'N<ˆ={n-*éL%B$ˆîÔÛw¤Iô@3€pjŠ<»Óš'õœhê·ó\«8Èmés§=z$ë$¬Á:{ÒÏUnH'8[[ÇÙ/¬ÞC^Hß,Ëc}³I©×1\gÝ$Ö sžoÇ2—u ¨"°oh‰F­}å•<Q 3‘^è1•`v~ßëº5ªß_žk–z`†Ý8)Ö!uEÑF¬ùg<½þßxƛƶ”QÙDňFÓRZ[ÁA«®(ËéõODu¦Äx9‰u‹LÓ´×8£G4MN¢ˆëFI’àóù¤¿B¡IY–¡(ʘëhç÷I1 }DD”–úú…¢¤Ûçô–»3x¡ïX‘B4¿#«˜J~l/8¦Ñk˜ø»3k!¢ðb¹ßoÕïÿVÄÚ/Ùí±¢—k.¢ÃjVgWÆ_4>`»HH¨ˆ‘%Š2¶zjñ\]·*%sûפôH±•2ŧT&T¦¹@ `WE×ëÅç?ÿ8V­Z‰pøv´¶ZSÔÕÊ Öœ¿Ö·¢$Iøîw_Æ¿þ«+µ…i@‰D"ö—£‰DrN·àüÓ-‰9i º(øüç÷޹oÍšÓqË-âŸþiwµß:š1úi"½seÙêo*º@ Ó4íÏäϾ;wîD¨S‚¶ðºa}És’FÍ—Õ1 ¾ £H7˜å*ï|@º8ý¯è¬ ;“(b^Iñ|PÞhý©ªÖ9­©)kÑx/¬_{êy‡‹|£¼©} pLñ,@Õ´tï‘1$`û®“XþôŸðÕ¯^Œñ™ÏÅ‚a[­…{È~?B¡þtöÙ8vìÿæo`ìáù¿>†'ž¸Ñèðéáa[º»víšÄ'„ˆ¨ÊDb[Oý=8ë»Z¬CåG:žªÖø|éëÓ­ÍN$JDb¤½½@z„²¢(öt:bD¨˜Ò5×H¢Z!:¸ˆ%‘àý[@½P­Q)ªjÕEF±ëbÎDb†‚@ q(¦àDEŒNIYÃ0ìE‰‹íé 0ÙJTï¢Ñ¨]ÔœÓx;¿¶oߎÑq¥rñzÓ( #½†¹µ.`+TUµ×­+Ä0 ;É=î÷{ `”ERc <­g>Fth!£CjAb®N±˜¡(ƒ‘ú)…?õ£ÁJø˜©rfW—(€¡·Í@ ý拆1g%DQ¬$’-b_Ô ¼'u„ •iĹ6ƒè‰çñx044dW`É’½xÛÛn`}Ö+©Rí²@<>ÇžÖãñ@×uœqÆ%ˆFoNMM…×뵇ïI’d¯éRÌ” ’$! Ú½'Ò+è?X6æ¶÷¾÷:´¶þÏ=·¬èíPõE"o\ …¬$E(d­ñ#>j¢×Z$±‡ø‡ÃakTè½€ü‡ýJX'“V¤×ÉAz€ H* ß D=©²¶"=—„ô¨É³õ]éç‹Îö5£`'¬F¹Ò çÓÓmã$UÅÂñä»3{>:GkÊrÖóe~@qÜ.I@KË ¸çžgñïœüiô÷÷£½½ýýý8|¸»woA2iÍ#½l™„}ûÎÄÎ@ 4SCC½^/LÓÄ¿‡B¸íw¿Ã}§_‚»vváÄ9+ÑÐð!<ѼÿŠùûöMÕÇŠˆ¨|Ä:X¤'ÎïÙ¬ïg öâÆU€þ6 ðCÀóa1ídý6¶:,ÄhvVQ´¶¶B’$„ÃáŒuNÆ«zÙ…ŸÊ-šúñŠˬ6{Ý7V ‹6 öhbóÇV† øþgúËÖôçê…€úŸÖS/°SŒFkƒÿbîpéuåÌÔœ*—†ôºu!Xß-Ž×‡–úíIÝ/¾oDç‘À §þÖS÷°’½ÇöÄë‹éO‚Žçô;Ê-§çGº¡'èx}%ë9©}Ùû‹½ ó–ÍÑÇàg×ü çï;‹þ´Û]ÛqéÞK1wî\,>²ÉYIè—êÝ9Š;O»úJoÿúÛqòäI/ ¦“Õ¡Ôë{NR‹µý©ãT¯jÝuGÑÑVԱḩí¦Þ#ñ~:?'þÔkµ§þß kþyqŒDOã¶Ôsëÿr}¥?ÕD5E$4DçÚìKEA(²Û”Ä4ö†aØÉSQ/pŽHË^?È\c·½½ÝÞ–˜ÞϹ-EQì)ü`ïÞ½8ŸÓMW\ `Ö¬ö ÑèškîÇuןL‰D"Ðu==ŠPŒ®0 «ÁGÈžóý_dàýæØ Šs€Ö÷wÖ´#>ŸµmY¶*åÎò7ZÃDùˆ™@B©Ñ¦¦Ê<¢¯Ké7W¬ÿåñŒ½(æ½ÍnhKµ MGL¨L†a ‰Ør¯×;&Q༰¼ë®e¸ÉʧÀëµ`}¾±ë•›è1èäóùàñxpÇwãàÁ(úûû3.†£Ñ(þýßާžú¸øbÕþ.ËÞÖDÕ4Íž+»Ñhæ(?§_üæÏ¿«ro•8ø|[W–­óŠ5è+bt‹H:jLP^¶®…4 Ë€é‹"?2{<`yf9í)¬Ä9]ŒI5¤éß̱î‹ÌG£Yû¦ }rº¿–ùZ¡PŽ)#Rå‹\n­m"ÂL|ÅD£ÀñãÇqÙeß·÷¿½½²,ãþû× ³ó)»¢ºd °n݇ñÝïžÃ0ì5šÄ4+ÖÒ€$YóÕ‹ï‡HÄßüh:û`]:E‚ô ¢À÷ü÷ñ›Ÿ¾ ­­€¢,Àfórô÷÷uvNég‹¨VX±”û>ÑZ,Tž]ïµ§,°}ç"çš–¾NÛttþ­hýbº9çð9é†HÀj¼# tcŸxO%ë½nû ¸€þoXS4Ö1ªSœ'DE’$;9âñxàñxrNà :߈z¯R¯Ù#ª/¤{¡Š^—ŒIXñ+Ítƒ óg@ô$HHÊQÀ{'ÕOüVÖ¶D¢$;/èÅØ¤«`d=ÇÙ¨!’Î퉤ŒHd• ÆÎÉ>˜çõÅ6ÅsSÀCG:aàx죿{³1¿P~#b@J-´«k:<ðàÑùâ>ã>È—Ëð~È‹mú6|âŸÀ­·Â”¬ï”+Õ+± Ëp).µFË•åÀ—³Þ#ëõï?µ¿Þ¬2#DZ"ýÝœÝÞ¤§¶‘ëý ¥Þ7猃¢#”ó8ʸkÑ.Õ2q.wNµ)¦Ós÷‹ÎÎõoØÏu>OŒ£NkÊ=Ñ®#ê¢^ ííˆç‹2f4¦—A,C,«öÛ?í9s`²l]sìØqî¹gþøÇâ“)Š¢XŸð ¦i5ödw¾Éng 8’gãaXçþ6—x‹ÇêÁ.z£Ctj(±¾ Nê‹ ýŽi»‚ÁtB%_uÛ3k 0¡R§t]‡Ïç˘ :u!™=eÑà Õš¯ñe"DÏÑ›P’${Oç‰Ò4Mû¹¿¿¦)ã‹_l¯Î¹#‘ôBÕ¥Äuöz1ã¼ÉéùÒ—€ º1‡QÊ 7ÔI«ÙD¯†è­òx€DâÿÏ޽ǷQùãÿ„’@bg’@HƒHs 6l—1¡U ”"· ôšýʦÚx[Ë¥Ûnzñ®´û[è6ív¥Öí6ÝKk¥­ém[Ýl¡@B=m—ÄÍCÙb!d ˆ4„†L¬8Mÿþ8:3#Y¶dK²$ûó~½ÛºŒÎhôhfÎ3ç9÷@×?'Þ‹K/=”³Äœm?€ΟrN @Púá\áæ:ɵþ€1e²§f¶"G¦,¿óuuf;eB%Ëš€t@0›mIfsu]¼/ã]$qøðaŒŒœŒPèËðûýxä‘_âî»ÿÿû¿ßÇÛÞö—¸ûî7cÏž>üúÓCÞ4í«Æ,ëå—Ÿïœß7­­b]e'Y p†ô†ÿüWë˜ç,5 œTÿ§„asós¶UB’bd¦ˆ}Ótæ”É 9£Ï˜ÿ à*@ÀIr¸“¤­­Îd䢌¦S‚O×¹Ý÷Éû5M$ åk«ªHØÊçƒN9]YrPQÄk*Šx¬<Î^ýlØÀ“Î\þ¸ø™r>8lîDKšÜvápõN:-/þÄ1˜,‘);Nä¾T^¤`YVA²,+Î=G„ìÈŠÅböèmy±Âí·ß^é¦V¯œbÒx±7ÁˆhÓ1qì"¿× âX–dÍEàöñž3ÞíÆ/Í1ÞU¦ã¼¾aPýjF§<”÷ËP9Ò[^X§@±ã[Î]Žm´û9ÊØ 㽟uXMå½ñOá9ÁÉ?‡ *™q_+硜‘nîÛÜ£>Üÿt]·/Žp¿–¢(e´Üû|y¿išSJxäºh6ûXǵ+»ûÅï7ÑÒòM<þø§ó>WÎo%«ùØ}‚@á%L,O fÞ&Ka)JºÖ®&ŽÝuPü"¹¢i“©Q®iÜû79ÒõD Æ„JÐu=£œ—œà.Âï÷Oª„A®²ŽÁ 3ºm*#U䉲l›<1ÄÎJ^ˆ«×{zz2bg+N$&ê õ;;äñT’@¹l‘ˆÈÜÈ!nÔµóá[h¸nÌÃÏ;ï<,^¼xò Š‘‰¿?]›zœð±, ‘H±X Éä÷ññ?ïÃ|ì?°ý«ë€>@ý4DR$ǾW[ (®\‚¢ˆ8kiI •¥¢W÷ÊïßùYËÑD;C!׈y5¡ ¨Mc×opP¬›»ÓÖ´LÀX– Ÿëã/œUÕ­·¾†ûï gŸýV­º†aÀï÷ã…îÇêÕ_À‹/Š8~Ë[Þ‚þp9–`Ó¦å0Œ‹3ʶ´,Íù¾FæÕìî˜7\¥2dÇN èQÊš59^ÿön(u¯p°&3?Q!äçVî/ÅIvȆü'‹Ã@x üÀOúvï®Ã²eçâî»_CSS÷Þ»'Ÿ|2¢Ñ¥øÊWê`> (£@àïý6'€àßÑðŠ“öûßüæÓxøá·B]ØýÑ1çû4 Ì÷»ck¼}6Ý=Ç¢+Žr}OºïÏu²G&”tiQWû÷É}øÅK•Þª5&ÇyM$">ƒƒ9Î{äÐZ™™Ë®Ï({pUUüî®Ý÷È÷èb2‡­l ÑDä…æÁ`° y¡u]G8FØÝ‘(¯&›ª–±ÿ{Ÿ\l?œò–²Œ¥œ÷0×KË‹oË="C¬(L¨T)yBêž—AUU»4Ž4•Œ}K‹SsÐ-'å‘ÈØ2îvY–…Ýwß‘ßÿçŸ>žzê)¬\¹š×ë”>Ê® äÒ_ä„->Ÿ3ª¦¹Ù™lu2Çÿî«!l–%.§µ¬ÌI2è ß Ü}wQí¦òÐõsxäá»@8hù“}ž vÒR×u{„Äàà Þ¨.ƼvðN`Ý: ùã@ôn °™µ±Ó}™ûãµtÿ—a†€ªÂœ7ÆÏ€öáµâñ²?©À!@›³C0è\žq®«ÁU‹Û´;Äöìq÷ÐCñã/Æø>æ=3Ë’?Ãüµkñow_ ßytýv©ˊ᳟½·Ýöf44œŒ‡nÄO\aÄb¬YüùŸ‹^UMn¸–ØçóÙçþã #}ÕÀÒ•è ¬ß¿T<¹³ýË×-»Ã@ú‹Ê4Õ§ÇVæN€­\ õºÓ3·±O|?¬Ysza¢ª%?Úòs–óû~¢R#9 rt˜•Ùï”Y»ß):@ðÍ€u‡Óÿ,)ŠsQÒ·¿}'Nœ†­[âôGpC×\<÷Ç“ñgßúö^‚›~‡Ÿ~ïªÛ…Wí–-oE"ñs´¶®ƒ¦?Yýüzïr¼t»þ»ÚðìIÏâôÇNGÿ–Óp÷·ïF¿òN1ÒL5qÊÑç±ûîoãªÝáûÉ<1]ÖÊÿ1ÄÔÑô¿dvÈ˺ÿRºᘽ¶áz^8üÈa,¼c!æÿi¾¸­'½|ˆjQ»SWvð~æÇŸÁȼÜ÷îû°æá58~ü8,X€³Ÿ:Ê;Xl\²SV~±ƒÇT±÷ý‘_¯C`ÕõÝ tZcOädï­”}p'‡!¹e·¥çµ³¥k?[–e£ÊNSÙÉ";f²çðsš1»æ1‘¥Ë²'´ŽÅbÐ4;zW’W[–…†9spÊóÏã‹cõÕWÛñÕ2gö~àƺ5kpîà æ}ýë¸3}¿¢(Ðä°°¯|·­] „BöyÄàà ¸ï¼óE±ÇÞ”>ÈX¸pa¥ß¶ªµ÷¼½Àå:Ðs† º“ƒî$‡kÒÖPÈuáÚ¯SÀChÜèÇœ+L¤ìà ýs¿Nöcò%T&z92ø”óÉÏœüLÊϧüÌÊQ'~¿?ç|–“™¯2oõ€'/’ß²ä;9*«:È“eYéãtËþΠI0]?8s’¹Éùz@ô»qÝ}` x PWÖE€õˬE´Æéi.×ö:v ?IÎ-d»wïÆÞóö¢q#`ÿþý€‡_z'œÀk_à /¿€v=€ËO¿O=õ†Oƺ׉’w‡.Å¢E‹p¥ÿJœrô¼üÂËØü‘ÍÁŠ WàwÿCO°Ç™,ÚpµY†¬{®$ÍYŸŒ}ºœ/)û½µà;ÊuÎ~ù>È÷BÉúi¹ƒ·ÉùšÜ_1–kù²MÈqÿDò=¦ePÙX–³Ë5 þPdÜ} XŠèÛ‰D" D'A08þUµy‘õw®ÎÕl®91ñùM_k—攟g&9j*ebšâTöôŒ?b*{¢M9ÒCUU LëÁe ÚÑÞ~þðÌ´®ùÞ}Òwñðš5Øwæ™öÁß§O=§®Yƒã©Î_°gΟŸy)ìx…Ù‹•®c¤˜&Š‚àëOÍ¿Bg§èÔø‡{ üû—K‡³¿Üš›íûTÓF¶[ÖEÉqu–9z|§qj)ñªÊÊj†]Ã9´åNŸI߃èX”5åæ”õ®ø) †€ž¿~ÿû$vìøwü¢ïxÓ¼7¡nu|~_Fòïü—ÓËK/kàWé~¦u2o Ïø±‰ØQ Ê»®°Îé°Òu„ß§!tGŒ?¥'…WÒ±²J‡þøøþg7Ô·¼=³Ó+‚50 ýÐ¥è|îrø×íEøþ«‹Åpøp þðK¯|ùßpÿ“OââÓNÓ'Nà±›nÂy癸ñFZZnDݼܨ­Epô±ýè)xóü}h•—¢Ëš>>õ©Œ—µË÷Yaašv¯³ïå+ Ýõ|¾› ‰ÇÌbÿöY„•[2–/ä‹}PU þˇ`šï…²´J?ô¨ _VxÉ«è-k!ZZœ ­MSܧ^²¾Ec?&ðõ¯_[éOëÌ"GUeÏÿ32I(ûˆäŶ29áþìÉщò3(û˜°ž·Ñ9ÀÑËŽâ™áÃxÖƹý¦©aëÖ7à/þ¢ª*¾ºC!@9à1@¹ð½Ђ€z& Í´ëÇ®›a¸í]ÂÊ{Wâ¤;OFàoÖ­À+žWð5ßAÃWß‚×ëvãžy÷àmË®Ã3ÿD4ú¾ÿ^¾î Xàô`[µ…€åMD¯u&¢UÞ‚÷_ùG¤Þñ(ží{oؼ «šVÁø¢e'-Ã?òAܬ݌õ®GOOvÿÅnüçƒÿ‰ÑÑQ9rKÕ¥vM÷X,†‹r1.l½Pl«€Nàž3îÁ¹Ïž‹çŽ<‡ F.ÀO~ŠK]‚•oY‰Û?{;>vëÇð¢çEübÍ/pÎà9Øç݇÷Ä߃O®û$ÞöàÛðÀ¢pÁÈè«ïÃ’K–àØ±cøCû°lÙ2\n\Žú_ÔcË-8´õ欚ƒ‘çFðÕ}ß¾õÛè@þnïßᦛn­·ÞŠú·Ô㲋.«ô'º*vâ„ØÁƒâ_ŽãÀÈóBÿïUý €Ïä^P¾‹n¼'“V?b±XFY³¡–eÙ‰ŸÏ‡`0˜3y2Ó:Håñºœ ×=GvvF"ôôôàËŸÿ,â+WŒÉã*×ßr¾}ZâÛˆž€u¹_Dî°&’ý:¹d-Ã0ŒŒ¼ºaY0Ò÷Ï=Šá­[ñ£PÈŽc9/g(²« L&A2ÓÈÝ2 F 3Ê"â{/‹¥ËÖŠ„•¦iöãåäÙò>9j0´ËaÇb1;‘"¿zzz‹Åð‡?ü¡ÒoEõJÏod®Ì—vC}Ç=Zë9 ün ô›ppðê1€¿iðöSÛhgþÿ—Bä[¯B]ð:”ºEÀÑ îS ¿\üà[ ˜Çó? œ¼8yÔ•bT±± Pä[•Wœfù/Ì5Àƒw¼Š7žþÞðçÇÑ¿s»þ¸‹ç¾Š• Žáoø5þu÷*¬™·WÔÿ ¬™‡Y€‘×çáÅWWâüÓŽÀe ÿú«+pñ’øéúa|ð§ã¡£8ù”“1€z;€u€ñ ÕÏ?Äî‚8?>&Þ‡/?q¾ü4à_˜ïŒmN[µ:ÀÿA ôŸây@Ë ¸Ög`®ŒŸ‹Ç«ou½NZøÝ@è “yÛ'ÿ:=~ ówâu«ãÚ±¯ã~^øÝ@è¡Ü¯cé€2O<Þ¬ý€•ÞŽ@çnÀºŸ èb'¾¥ÀÏ>Ï­ÞWé(˜±ä$âüÑBkk+úûûÇ&šuˆs-xù‰—qÿáûñþµbãk¯‰~™¬‹§'­»Á첎rDŠœÛKÎÉEUmÎèh®"µ£½½½½½•nƱ˜ö@ÀéøÑu§D•<9å±Ü%Ê9¼±åòn¹üðûßÿþê¯pp÷nl_¾ÜÞéóù°ö¯ÿN:‘£ŸÂý©uø‡ì‡öáµ…—Ñ3MQ—+W¶V^ÖŠNÖôy(àÉ'>úéÌž´þ~ç Oö¸É˃] ŠÅí–O£å¡BøÆ½ðo¹8wÛܳè(JŸ· =1…못»^¯^¯·lÛ¬ÉIÙººº¦¶΄Yad^Õ£CtÆ€– ÿ  å;@xà;gÇ(œ«µ{`'W °,ˆ?Lüýƒ ß[Û^Z‹¹W¥€g¬PÄkZ€± ˆüõôkvµO‡uhÔŽoM”XT|®þ¤@ÿéPÚåœ8s¾bÛ#¸`+”‹V"úÄÐ,Ú¿|Hל•3[½]ÿñ¸úc]øÂÖâc{ ÷Üó3|úÓ7ãÉ'¿dÏ ¤( F~ö3¼xÉ%®«ÅG>•ß?À€?êÄ•lŒ;À# Chß§a¹±'/Æ¡c 3ïO×è3æ{¡^± €ÈYö÷æýýú ¯uÆ9h1Mg`˜Ï'þžè"9R¡µUüìïw¾rõ ½ç=_Äí·¡4êdÊûN "1 Œtsð'sÐ~¿Ø%X/áµ€ñ4`,´kÄ~Ä‚—Ê  p¸ó0÷ f\|ðÀWaï^q6Õð‡9X6º ­:ˆU«îÄ•ÏmvBÁ/Î|8bà祰±kcæÁ¯ñýàúX¬;ˆ“þû$œ|äd,¸h\ü ¶=³ 0eïX†¿|ð/q`Ó„b!û*SUU¡i6¼iθç ,=¼ÇŽÃüëæãÀOàøñãè½ ×î‘#7ZZZ000`wRÝöáÛðù·}0€›æÝ„=þ#»d’Ïç×¾ô%¼øâ‹xæ™g0wî\¬X±‡Æ…G/Ä'Oÿ$v½¸ ÛÏÛŽãÇ㥗^¼yó0þ|ŒŒŒàðáÃX²d >õü§`*&Fæà芣X¼x1Ž­<†‘‘ÜyçøøÇ?Ž_ýêW¸âŠ+pøðaµ Ö~a-~ö¦Ÿá²g/òw,×N| _þ÷/#Š«ä[Zìž²¼„ìd Ę̈†œÉ·¢÷3X{{;z¿ñq¿7Æ^_ ò hÙ9(“(òÊs)ç(ß*æ.O";BåÄ÷rkÑhŸhk÷?þq|æ3ŸÁG~øC„Ãa„B!ÌýÞ÷pé’%8|ø0êÄIçž‹_¼ýíö¼_>EAꓟD]]R©êÞøÆ±ûWw©¦"J,•ms‹ÇãØÓßn¸!c›†BcK˜š¦8T’×ae)7÷|%º®gŒ~pöe<Ë2\µZbGŽæßMîï(÷w@$ÉøË.MÀ.w+“Ù ”X,†p8l߉DÆ…fš¦]ò0{û¨²N¨{(®¦ûaÑu¡PHŒ2£ íííè½ðSèü§Ý0N4Á§ÞuÌ××8o§ J÷ûëÞ™†8a’e0åýîLJBcKå¹–aš&^¿æÀÂ… ‘J¥pw]î\µÊþ,^·oÞuì–.uÊ#øìg±öÃ.øuŒEš=¡v4:v$jö‰–ëuÌc+¡¾õ cß“P¨¤¯“s}²^Çzeð¾÷ý¨³›L¿Ž‘:ʼ€zï3º‡ÌÏþ+´}·Ã<¶汕P.> Ú-bn ]|Jæë˜ÇV×^ ë×;ÝK?øŒ=žÑ|Ÿ±ôišxë±çíû•‹ÏÂËǶã˜ê¹§L ÈùaàÉ'ŸÄ)§Ü UUEùX9Âĸ¨Ö˜Ó>_Y7wê^« AŒ‘Ī÷\e\QŒ?ÏU­rÛ2¡R&Ùeˆ~ö³{‰=´«Vm›Þt†]3¶ä'¦¡ŽÝ{/Ž;†Åü#~7<Œ½ßý.¢Ñ(6nü?ÿ"ö¾å1¼lî¹ç\~ùå8zÓMvçP.–å̳$eÞq»DogöˆÜÙÊYݾÃÏBYS_ÔÉ¥$ÛÕÓãt¸NõÁN¨h–3kvO:s+ª³Ì€½3´3÷é¿cp,@¿ðÝÿÐú çã€O^•bÁNÂn8ŒpO£xöÙeøÿoš^nÂÇŸþ8î_ˆÐß©B»p¿8@óû_ˆÆí€qÁA¾žó!’UYb1çc¡ªùK‘™¦‰áᓉ÷Þ»k×ÎÇܹ¿F0¨â+_ùû„M^ùæþžÇø²L!£L¥hTœKdU̱ D]ýÐßÍ:ºú‹Ñÿ³S&|Š<TUþá›ÿ„À{^Èx--âx:Û!1y΋‰uïB“jÝGTÚ”Þ"!JÔ Â©í`Ñ;ó2@]Ä~X ÿ…6ÁÖ5€õy@}³ë¹*úd GŽÁÓ¯?çOy·r^Ž¿ ÕRñrÓËøúᅫc Žá©?{ gžy&ö]· .Z :†bʸ“·¦~Âmü/üùš?ÇÒÃK±ïÌ}øÞÞïáSG?…o_ýmÚs:óOöã5MêVáùÇžGÃÒ4·4cù£Ë1h>,ÕÂóŸzÞî8‘W¡wvvÚÉ‘`0h¼Ë§ìà‰D"ö>_v°Èúñ¦iÚ<òj`÷óûÛßâä“O†×ëÅðð0æÏŸë®»ªªbÙIËð¾ïØ:v§Ï–-[ðá­­­øþ÷¿×_«W¯ÎØ×?óÌ3xì±Çðž÷¼€SnÈçóM¾”Ú$0¡2¾‰â3É=÷ÍTÈ‹{d‡«LžÈŽÕ KËÈÉì*pµº¼Ø@^-.ç”·ÿö _@ÓWˆÊ"éŽcUUqAo/^xá\âñ îàA¤ÞùNü`þ|Äb1|zþ|ÿѰxñb¼úê«XØØ8v‚ìøÆÎG1¤¯ÀèþÞ÷xl›ƒüÞÚ¸± ™vD"âxLQœó ¼!bbéó*÷$ïÙIyüèNî× ™’1.'`_(GzD";*!rÔ—ÜïÊ äs|>Ÿd•ÇÛÒÐí·cþ¾}xä‘GÐÖÖ†ô2(KëÎApv'qkkæ±pv}4:v>÷2do"( ÚŸ|’Ƕ9´··ãÂgZa.» =ÿ½¼¬¯%/òqOäÀ>æ“1&GnζR—³mÇ7©sÏtwaôVÀZ'¾fý~qüû¹Ïý=ö~øïÆ[î}‹3¢ãz¸ÐÎR°ûÉ‡ðø·¾…Óþõ_s÷µÊÒsQ×ß&œ$ ÎQs•ŽÓ .ú›Dÿ U&Tr¨ÆÎ2Ó4ÑÞ~/þ/¼üò0M~¿?=L:€'ù>ý¥‹¡ž~Ú§B{Ë‚ÂGÜË#v9FUñPWæ®[gtùæ 7à3?ú‘=ÔXN/B}0Íâîåq<¯” ç–rJ'›vÒ¢ÄÇøòÕ0œN[À™$¼Ð¶ÙsÔ74dôF3¡’Û”(äȜ̿çJ |ÍÍNÙøô4èé’É{ðÊ+/Â0 œvÿýÐ çŸ~:̹ïį^»á_^6¦£_×Ex™¦È÷ÉJUòf¢Ï¦LrtvŠŸ CW×kصëß3ʸ;Qå‰Ì»==‡ðÏÿ¼K–Œ–íê߆qÂ_M ºû¦&K޾ï¹Õ¸¨Sz_dRÓXobêÏØI€ñ2¸Ð_‚ï´ïæÍ€ú^85“€û¿÷þá^X–…sÿû\\·ï:|bé'ðî…ïÆÓñtÆEc:såPh¤—^ÿÅëxnýsxéo^²;CähË`0Ã0022‚E‹Á4M \ºæR¼£íƒP¢Šè’ûáô÷õc·Ý†ÓN; 7oÆJ1áëäÈ6ÈDJÖÀ«Œ |©¦”£ß¶êæPI&“H&“ðx<ðx<•nN^ò‹ZN`-¿Pÿô|/6ìØøO®£iÃZ ª*®½@ /4êþº~1TUtÄú^»¾“~ó¹“qºba~SNùäùö•§ܰßûùϱÙU*¤;ApÝ:ûJ¤oÝw_ÎÎ(±{ÌTäJ|ÈÎlŸOœ£F0œ!ÌòHÓtÌá>.–e…ñ+K”Ë©$d-ÿì¶ÙÉ”ìÎ2e‹O9üR^éFfy÷$^®mcYζÚÿ£aîO~‚[_Ú…ï¼×ƒïÿélÙrÎýë¿!NrN2“ƹêZ~®MÓ™Ë7þò/_Áßþí!ø|+\¯me\(ãÑ0:ñ?ÿóøÜçþ õõ°ÆŒËú꺲oÃj,—^ÌwûÃe‰O9*€¨è­€ÿÿæó€ù@zÒeÀìoǘ&îÙÄ-§Ü‚×.z ÷µÞgŸtú|>¬õ®ÅÊ+Vâ6å¶1/ë¾ÒWº¯JUb ,Õ‚ï§é‰rcVFéLù\™ÀhiiAz.ˆóÎ;Æ… Ã^¦ÜºËÈ« å\Ját'J©Ê¡ìÉ&Ö“¾>g2©@U2ïÎÌ"S‰Í†§Ï_Qœ¹­ó•ù’Ÿ{÷þ p’'þRí|>¿ãsMPí¾¼îàAœòɸïñDZöö“Ÿÿû±sãF<|Ûm¸àûßÇ}wÜÏÞu¼'ŸŒã ⼓O†åóAÙ¸Ñéµï·¿EÓ©§:¯ý7hÂéQU2Iyî7¿™ÑD-G›)Y~hyy¯î®&“ϸ>_îã©HDÄëdËñÉ„‰,µ—Q °÷ 2†Ë61y4 #Ý1œØtÏå!;eýzÙÑxßw`õîÝ÷»¸îºëpçwâÆï~×^¿ßÍ00ÒÛ‹•sçâŸÃâ]»ð³¿ú«Œ‘{Òÿýª*ÈÓ'böz›&°w/nzó›'Ä›ž½í4 kä¾FUqf®ýN¾²Y…\é7£ÔÜ `UÅÞ›n*ÿkV‰ÉÆçTKaʤ‰ìÓqW£6Ë{YÜÈN}™Hu*8£ÒdÉJÙá/ÿöÈiwé;ù»{T×ÀÀZZZì¿Ãá°=÷—û;I^,,ãþé©ýz²­áp­­­ÌHžÊäpöë†a'd³_/»ÙÏ•åùÜ#ZÝåúÜï³{ýä(6¹ yq†ûâ-ùS&»UUÅ®]»j¶lâd•å¼3]‰Íú.€×€žÔ½ÀmGoðówÿ«¬UÀRø[Q:GÆAsg'Âá0Ÿ¯¸§‚̹Kr…ü œLSWU#TúúúÐÝݦ¦& ¡««Ë^;ŽéºúØÝyjæþú׸{÷n¨®€Ý¼?üð‡€¦Á¨»Ú;—Ûù.ëR[®Ñ=˜?-~õ«ï¢±q3zè TUÃ#Æ{ß{N;í¾ò•ÕðùÄÁB pK—.µãdG°mìóMLçœêѨs^fYâXØ}A£œA&W4 %»¢drÛÖ™ÓÂçs†μ --ãsë:úÊWðê—¿<ã¯â›l|޹úXfú'Ó€3ùÝ猜ïïwJ@Ùç2òò¿t‡Íw¾ŒX„/íz?^>õTnnÆŠO}Êî•}w²,ƒ<¾ eºcPxÊ´hTŒ}öÙs±~ýé¸ë®Ÿ¸–mfŒ£ê4[F¨L6>3Þ™sŸÈQ`€VÀø"ý­ˆ›PȽå澨@î+åäµ¾ô~2›¼b^žìt¦†Ý'IîºîUŸ0˜í"ghŸÔÙ)¾Ì}>ñýÝÓø|³f„ÊTm¿ñÞ¼ÇC2Þd,e'O¦2’JŸº¯öt_M  …°í«_…ÒÜŒ?üàøÁÐÝrÙÿ7–>ó `îòå8øÆ7âµ},£È.„­i³ú"•ª”Þ6ÿvÖY¸ôškxl›¥˜ï­ì¤ àtjÊý[AåöòÈî”IY6KV4£"åþ¶³³·ýéOøãÙgíÚ…ï¶µÙ£~¿ ±pÿ~ì;óLœqÁ˜÷¦7ežTÊ:¸n@fÝ=¢ƒ#Ŧ„ǶŽ/r¿)ûugd—˜ƒO@™{ Ú)û€3ü[ØÎ€bÀ9âW_}¯¾ò*’kæaÎN¤R)¼ðò x¡îNÜpð^Ì{e¯,ö`Þ‘ €ͪø"Çî=†…÷-Äëk^ÇÛþø îx÷Ëøþ‘ïã3w~` КäÔy)Ť׽À‡MÀŒÂ8´–÷]еA9ÿˆ„C4¾¾ Lh+žG «΋ƒ¯½–‘@Yôâ‹xÇe—áŒyó°öºëpÑ»Þe—òYvÒIøÅÃÛWxÉ“M{rž ‰N䨌dÇV¡Z鹕röô[–Sƒ1×ýrØô}³å¤³¨cÛ,²#VÆŸìx¯HvÉ xä¤ó–––Œý€ŒÎ"ŸÏg?gª¥èr2 ‘€K£*aš@g'bªŠUý(m³ò½åe"KìÉØqÏi’}­|œ;^ÝÈÎUyñ<^u—œ‘¤ò¸×]L&R²÷·¥ÙuÙ‰Z•xl;Á±mÖû"ãÈ—^x!.»ì2¼þúë¸òÊ+3âÈ=rC&8úûûÑÚÚŠžžž1£/d »ç½›jiXª}<¶-àØÖ°E‡ùÝ_Céé€õk ¶Vвñ5øÞ9÷aëÖÍvÅ€ƒ_ù NÆ×Ÿ{¯­^mÏGÍdjF—üŠÇ㨯¯·W®±±ˆÇãf;Ÿû¿ç`œ÷è{@ŸïƒyÒ¥ÞþÌ7)À›u5°Â³?;z2ž?´O<¿gÍFýßÿ=ž|jFFFàyã¿ã…}Á1¨XrÊó˜¿`^y¨[õŽŸòn¼øâüà;†s>™Âš5kðÄO nM.ýÙ­øcÓû‘LÎÃêvãÏ/[ƒ»ÕaéÒ¥xí̇ðÚ\‚Uú*àÑV àJ_Õ¡ë°nìÆäXQwÚ+}1ߘÝôßÊ×q“+OëËZNw½_¹¾\ sûÅ;¾ˆ/¼å âo™Äгž#ÿVÅë(f:o“Hߦf=&«|mFâFà1Y¯“‘ çuäÍ'¼ ×~ãZÀzšÒÏó:>üþMbfŸnN->üq,øÑˈìú.¬ºyÀ‰5.Ûhé–¿ã>üjÉû122‚‘Ûâ…Ã'ðÉï}wG"ðx±˜S‹s¼õ‘¯#eטw¿N8ŒøOä>™œ… S=¶`_9+ÿ=ñÄX»v-V­Z…7¾ñöŲ솦iXºt)ì $w‰@ÄÝ@z;ËÒ!†½€IDATsuþÈ}ãd“)îs2†ŸV¿™²ÏÉ{ ªÀÀövwcU¥ÅÄ'û w«O?ý4Î8ã ,_¾§Ÿ~:EÁÕW_T*eÇ©»LNkk«àp×ò—¿ËQfî ®åßS˜ Eîwå²äg:㘷“(<¶™Š‰ÏX,†_þò—øÕ¯~…ùóçcddŸøÄ'°k×.|ÿûßG$Á»ßýîŒÑ)2:ge¼ÈX“?ÃyÊ|”¢ƒw&uÊÏ”ÏôLÚ&¥x/¦¼ïü™…è‡~ €~Úß#<ï4„~ ,Ñá²Ë¾‹?½| týÇxàE¸öÚkíÒ’~¿±GE ÀÇ\å™K©Ú÷%µðœ)ñ>U3BeÛ¶mˆÇã ½½~h.ºè"œþÄV<¹h'F^ÿN9åy¼úê«ö$´¯¼ò êêê022‚U«Vá…^Àg\€Tj/Ö®]‹—^z guFFF‹-ÂÈÈV®\‰#GŽ`ùòå8xð`ÆÏSN9¥äëàÀœvÚiX´hQ¥7EÑöî݋իWWºÓ²‰DÇÇßýÝßáø@K®=S‰ÏÏþóüÞ1œºÏÖÝ‹‘‘7ᤓ.Ãk¯} ü5Nœ8… „9sš1gÎa,Y²€K.ñØ'—»víÂÅ_Œ§žz çŸ>öïß•+Wâĉ€SN9‹/.ûúÏ”ÏôlúžÁÞ½{qâÄ <ú裕nnYM%>/¹äœ²ë}0G÷`ô´»J¥°xñb?~+V¬ÀsÏ=‡sÎ9©”¸àĉ±¶hÑ"ìß¿_|1<ˆ7¼á Y÷‘‘=zª¢`õÁƒ÷=^¡6MÕLùž‘ÛdÅŠã>æÀxá…pþùçãÖ[o­t“ËfªÇ¶—\r ‰–-[†… bùòåX°`ç8uÍš5½B̦}N­(d›ðØvüøü¯ÿú/tuuaÿþýX½z5<ˆ¦¦&˜¦‰sÏ=ì÷6û|òÈ‘#X¶lY¥WÛ6›>Óµ¢ÐcÛãÇã÷¿ÿ}¥›[VS‰ÏË/¿?þ8N:é$œsÎ9xå•WðÆ7¾±êb/ŸBŽ£jÅLùžá±­£˜cÛ¹ý'<'ýœ²¯,¸###8å” qÊ)§`dä÷¸òÊ+ñä“Oâïx ÃÀùçŸ'NLKüVû¾¤¾ª9Þ÷îÝ‹ƒ–üضjF¨ ¹­Éüñôo-yKDS3•øüú׿|]þõ×=»]¿¾Ò«FTó¦Ÿ3ýDœ¨LõØ–ñIT~S‰Ï|à3:ÉDT-¦Ÿ>ø`¥›M4ãlÛà“•^ ¢’8©Ò êëëÇÜ–L&+Ý,"㓨š1>‰ªc“¨z1>‰ª㓨:16‰U“PillˆÃÃÃe;‰¨¼ŸDÕ‹ñIT›DÕ‹ñIT½ŸDÕ‰±I䨚„Š×ëÅðð0âñ8Q¿7™LbÆ •nÑ¬Çø$ª^ŒO¢êÄØ$ª^ŒO¢êÅø$ªNŒM"GÕÌ¡]]]ؼy3ššš044„®®.ÔÕÕUºYDÆ'Q5c|U'Æ&Qõb|U/Æ'Qubl sFGGG+Ý·d2‰d2 ÇÃacDU†ñIT½ŸDÕ‰±IT½ŸDÕ‹ñIT›DU˜P!"""""""""""ª6U3‡ QµbB…ˆˆˆˆˆˆˆˆˆˆˆ(&Tˆˆˆˆˆˆˆˆˆˆˆˆò˜ûÿøÿXéFLU2™D"‘Ô××Wº9¶QNÚ”L&Q__ùó缕^ÏT*…_|qÒm«Æõʵ.Ån£JoŸjT+ïÉLØöãÅg±ñ7Ýë–o=ÆÛFÕ¶µ VÞ“ZßöSÝw滦ì;+µ.T¼D" ”l[O÷ç@¾^*•ÂgœQÒ¶NǺ²¿Ì5Al-m#šš\± ÔÖ¶Ÿ(>«ýضýþTâ³ÒëE¥1•ø¬¦m_̾³Øõ,…©Ægµ¯åWÎã£R+õ1v©¤R)†Q–cçš6Z£n½õÖÑæææÑM›6677Þzë­•nRNý×=zþùçgü»ï¾û ^jXϯ}ík£_ûÚׯÜ>QÛªu½r­K1Û¨¶Oµ©¥÷d&lû\Ÿébã¯ë6Þ÷ÌDۨףÚÕÒ{RëÛ~*ûÎ|÷Ï”}g%×…ŠóÜsÏ677—l[O÷çàk_ûšýz×\sÍèM7ÝT²¶N׺äŠÇìõzÿûß?:<<\“Ûˆ¦&WlŽŽÖÖ¶Ÿ(>káØv¼ý~1ñY ëEÅ›J|VÓ¶/fßYìz–r&Ÿµ°^4±r•Z©±Kehh¨lÇε®f*îÚÐÐÐèùçŸ?úÜsÏUºYclÚ´iÌŽs2ëQÉõ¼õÖ[í“\;Ÿ‰ÚVmë5Ѻ³jås8jé=©åm?ÑgºØø›ÎuË÷=3Ñ6ª¦õ¨µôžÔê¶/fß™ïþ™²ï¬ÄºPiÈ"÷¶¯•ÏôsÏ=—±üáááÑóÏ?thh¨$m-÷ºŒr½ÜëqÍ5׌F£ÑšÛF4u¹bst´v¶}¾ø¬æcÛ‰ö•ÅÆg¥¿w¨4¦ŸÕ²í‹Ýw»žÅ*&>«y½(¿r•Z©±KÅýž ^sÍ5£;vì(¨ 3=jr•x<Žúúzx½^@cc#Ç+Ý´œmÍ5¬¬õ¨ôz655¡­­ “j{5®W¾u™Ê6ªôö©FµöžÔò¶ï3]lüM÷ºM›m£j[ZPkïI­nû©î;óÝ?SöÕ°hjº»»ÑØØˆ¦¦&û¶ZúL§R)N¹ºº:x< ÝÖéX—ñâ1™LÂëõfܾ~ýú‚Ö«Ú¶MM®ØjkÛOŸÕ~l;Ѿ²˜ø¬ôzQiL%>«iÛ³ï,v=KaªñYíëEù•óø¨ÔJ}Œ]*ñxÃÃÃèèè â_×u¬_¿>ofCœ\éLE"‘s___d2Yé¦e;Ÿ›o¾ñxuuuèêêB[[[AëQéõ”_<¹êÜMÔ¶T*Uuë5Þº³ò­çlTéÏìdÔú¶ï3]ì÷Êtoɾg&ÚFÕ¶µ –Þ“ZÞöSÝw滿ß;åØwr?UŸD";wbûöíØ¼ysÆíµò™nllD[[nºé&x½^;)(OôªýØv¼xôz½ö:">wîÜiŸüÖÒ6¢É/6å}µ²í'ŠÏmÛ¶Uõ±íDûýbâ³¾w¨8SÏjÚöÅì;‹]ÏRµ_.7ÛDñYíëEù•󸍔ÊqŒ]*ÉdMMMèëëÃÎ;QWW‡¶¶¶’;Ï59BEfÝÆ»J²’dF´££»víÂÖ­[ÑÝÝmgäò­G5¯çDm«¥õ*fUÓzT‹ZzOfê¶/6þªiÝ&ÚFµ´Õ¢–Þ“™ºí‹i{5­×L>¾¡±R©6oÞŒ­[·¢®®.ã¾ZûL×ÕÕÙ“fŸ΄cÛ;wbãÆðz½v‚³Ö¶n¢ØjoÛŸ3åØv²ñY+ëE¹ŸÕ¶í§ºï,v=§Sv|Δõ"¡ÔÇG¥R®cìRI&“öh“ŽŽx<´··ÛI‘Ù5™PÉ•]®Æ,Wcc#z{{íì×ëņ ì‡|ëQÍë9QÛji½ŠÙFÕ´Õ¢–Þ“™ºí‹¿jZ·‰¶Q-­Gµ¨¥÷d¦nûbÚ^Më5“oh¬h4ŠÆÆF»Æðð0‰‰DM}¦åÕuÛ·oGWWt]ÇÐжmÛVt[+ý™N¥RhooGww7¶lÙ‚-[¶ܶjÚF49Å&P[Û~¢ø¬õcÛ©Ægµ¯M¬˜ø¬¦m_̾³ØõœãÅg­¯ å:>*•rc—’ÇãÁÖ­[áõzíŠ}}}yÛ0â &*c6ÄððpÕe»dßÍuÌ·Õ¼žµ­–Ö«˜mTMëQ-jé=™©Û¾Øø«¦u›hÕÒzT‹ZzOfê¶/¦íÕ´^3ùø†rK¥Rضm¶mÛ†d2‰;v`ÇŽ5õ™N&“ðx<ŸU¯×k_AWËǶ›6m‚Çã®ëå- i[5m#š¼ñb¨­m?Q|Öú±íTã³Ú׋ò›j|VÓ¶/fßYìzN‡ñâ³Ö׋„r•R9ޱKÅëõŽ93úÌJf&¾/‹æææÑûî»ottttthhh´¹¹ytxx¸ÒÍÊpë­·Ž^sÍ5v»†‡‡G¯¹æšÑ[o½µàõ¨†õÜ´iÓè×¾öµ1·OÔ¶j]¯ìu)vUÃö©6µòžÌ”mŸ+>‹¿J¬[®õÈ·ªq=ª]­¼'3aÛOeß™ïþ™²ï¬äºPñ6mÚdo»ÑÑÚùLïØ±#çç6–¤­Óµ.ãÅã}÷Ý—ñï¹çž«¹mDÅÉŽÍÑÑÚÙöùⳎm':–j|VÃzQiL6>«eÛ»ï,v=KùþO6>ka½h|å>>*‡Rc—ÂðððhssóèÐÐýw-ö™•KMNJ]]]ؼy3ššš044„®®®œµ)+INž»qãFx< ¡­­Í®ÙWÈzTózNÔ¶ZY¯b·Qµ¬G5©•÷d&oûbã¯ZÖ-ß6ª•õ¨&µòžÌäm_LÛ«e½fúñ MN­|¦×¯_x<Žk®¹MMMH&“hll´''-¶­•úL'“I$“I´··gÜÞÑÑ®®®šÚFTzµ²íóÅg­ÛŸÕº^Tµ°í‹Ýw»žå”/>ku½H(÷ñÑt¨tûêêêÐÕÕeÏ?#çÑœ }f¥0gttt´Ò˜* §ª‡ % {hS®væ[j^ωÚVKëUÌ6ª¦õ¨µôžÌÔm_lüUÓºM´ji=ªE-½'3uÛÓöjZ¯™||C“SKŸiùzõõõhll,i[«ù3]KÛˆJ«–¶ýDñ9“Žm'Ó¶Z^/ʯV¶}1ûÎb׳’fêz‘£šâ¬ZÛWÎcçZVÓ """""""""""¢éP““ÒM'&Tˆˆˆˆˆˆˆˆˆˆˆˆò`B…ˆˆˆˆˆˆˆˆˆˆˆ(&Tˆˆˆˆˆˆˆˆˆˆˆˆò`B…ˆˆˆˆˆˆˆˆˆˆˆ(&Tˆˆˆˆˆˆˆˆˆˆˆˆò`B…ˆˆˆˆˆˆˆˆˆˆˆ(&Tˆˆˆˆˆˆˆˆˆˆˆˆò`B…ˆˆˆˆˆˆˆˆˆˆˆ(&Tˆˆˆˆˆˆˆˆˆˆˆˆò`B…ˆˆˆˆˆˆˆˆˆˆˆ(&Tˆˆˆˆˆˆˆˆˆˆˆˆò`B…ˆˆˆˆˆˆˆˆˆˆˆ(&Tˆˆˆˆˆˆˆˆˆˆˆˆò`B…ˆˆˆˆˆˆˆˆˆˆˆ(&Tˆˆˆˆˆˆˆˆˆˆˆˆò`B…ˆˆˆˆˆˆˆˆˆˆˆ(&Tˆˆˆˆˆˆˆˆˆˆˆˆò`B…ˆˆˆˆˆˆˆˆˆˆˆ(&Tˆˆˆˆˆˆˆˆˆˆˆˆò`B…ˆˆˆˆˆˆˆˆˆˆˆ(&Tˆˆˆˆˆˆˆˆˆˆˆˆò`B…ˆˆˆˆˆˆˆˆˆˆˆ(&Tˆˆˆˆˆˆˆˆˆˆˆˆò`B…ˆˆˆˆˆˆˆˆˆˆˆ(&Tˆˆˆˆˆˆˆˆˆˆˆˆò`B…ˆˆˆˆˆˆˆˆˆˆˆ(&Tˆˆˆˆˆˆˆˆˆˆˆˆò`B…ˆˆˆˆˆˆˆˆˆˆˆ(&Tˆˆˆˆˆˆˆˆˆˆˆˆò`B…ˆˆˆˆˆˆˆˆˆˆˆ(&Tˆˆˆˆˆˆˆˆˆˆˆˆò`B…ˆˆˆˆˆˆˆˆˆˆˆ(&Tˆˆˆˆˆˆˆˆˆˆˆˆò`B…ˆˆˆˆˆˆˆˆˆˆˆ(YŸP‰F£Ðu½Ò͘U,Ë‚®ë0 £$Ë3MÑh´Ò«EeÀø¬¦iæŒkÆçÌÁx¬}…Ä£eY0MsÜçëº>îýT«µ£˜}'cµö06+£”çž…×2>kãuúM5Vy:{0.kßLŠËYŸP‰Åb5---öNÃý{53  ˆD"hmmEgggÑË4M±X¬Ò«FeÀø¬ ¡PÍÍÍ9ãšñ9sÔj§Â4MD" ÚqFgíUŸìø›ÉñXŒh4ŠÖÖVD"‘œ÷‡B!ô÷÷c``èììäÕµTrÜwæßw2V©ju_:Ý瞌Oªµ¸/J¬ò<”jI-Æ%MlÖ%Tb±0gÎtvvŽùËÌøÒ¥K … …ì/dÃ0ÐÚÚŠ9sæ ¹¹9ã ¾¥¥ÑhK—.ÅÒ¥KF …°téR444ØYÔB—O(²nÚ´Éþ½‡» º®ù;×c&³ÌñÖK~iƒA€¢(سgü~ÿ˜å¸·aö¶Ë›èjùX¹Í&ó\ª¬‰âs¢Ø”÷çŠÏÉÄ\-Äg9bS¾ùb%W|Êm¤(ŠýSUÕqÜÛŽ±YÝfB<ºcQ~æÜçSkñXÌþRÓ4hš6æqº®CQø|>û±š¦Õìb3ÍLˆU€ûÎBöcµ–sÞ)﯆ø,f_ZÈyf¹â3ß¹g®Ø”ï{¡ûRwlŒÏZVŽ})0»û‰J«îeñw```TQ”Ñ={öŒŽŽŽf,'yŸÏ7©ÇB¶-û÷BžçóùìõÊþ;×c Yf¾õêééÉøé÷ûÇ´Àh =tèÐèààਢ(£‘H$ãvùÞËç Øï[ Õ4ÍnóÀÀÀ„Ï¥ê1Q|N›£££Æçdb®â³±)ß³|±’+>FÀ¨ßïíééõûýïÓxñÉØ¬n3)³ão&Çc1ûKÉçóÙm”Âáð˜÷;×ãhúͤX•Ë⾓±:sÞ龿ZâsªûÒBÎ3ËŸùÎ=Ç‹Í‰âºØe|ÖšríKGGgw?Q©bU.‹ç¡³K5ôßNö±©–¸,tŠ9Æê~´ÖbsV%T‚Áàh ȸMUÕŒ’;ä‡u```´§§gTÓ´Œçû¹îÜ”ü¸ÿvï( y\!Š HùE’ëïñnË·Ì|ë%¿åRþÝ÷€ÏçD"£Š¢Œ»-åòÀ¨¢(Ï—8Þs©zLŸÅæèèè„ñ9™˜«…ø,GlÊßóÅJ®ø”±,·•ªªÏ/>›Õm&Åc± •ZŠÇbö—îådwîä:YpQå̤X•Ë⾓±:sÞ9:Z}ñYLB%ßyf¹â3ß¹çx±9Q\›rYŒÏÚQ®}éèèìî'*U¬Êeñv"Õ—…®S1ǸSÝÖZlΪ’_†aØÃ%UUíß-ËÊžë~¬iš0 sæÌ±ÿUõУ<Üëëïñn+Åëö÷÷Ãçó!#Œy³·€1æEɨ7ëÖ–=l.ßs©:LŸÅ&0ûâ³± +ÙïýwÞ‰X,†ÁÁA„ÃaìÙ³†adÔŽ/>›Õ‹ñ8v½ ý»T¦… 9Ï,W|æ;÷Ì3ÀÄq=•ØïµŸÕûÒ±ë=ÞßãÝVŠ×l?ÏCg6ößæ^ï\w[±¦z>šï¹3¥ÿvV%TrÕ2Í6Þ†’õNGŨû_8®ôjÕ ŸÏ7&ØÆ ¾lÙÛ%»v¢¦ièééA0S[1ßs©:ä‹Ï‰¾DŸ¥1•XÙ¿?TU͈eŸÏ—ñÜñ⓱Y½•7Õø(f9MÓr.·\`T8ÆjåM÷¾s"ŒÕêQÌy'Àø,…r{N%6åóŸÕ‰ûÒÊšj¬ò'ŠMy?ã³xS‰•óÏ?¦iÚÛF>Ï}`;^|26«ã±ò¦Åì/Ç#ONÝq›¦™1Y(Ucµò¦{ß9Æjõ(æ¼SÞÏø,N¹Î=§›ã³šq_ZYSUž‡Îlì¿­¼bâdªûÑZŠÍ“+Ý€é`ì/m÷Œ¦iðûýhnn†ªª™0UU ÑÒÒb?×çóUôHUU„B!ôôôdü^H&·EA8Fss3|>Ÿý‚Öµ³³ªªÂ4M{{ä"_Cn›É<—*g¢øœ(6Æg)Û<ÙX¹òÊ+qàÀŒí¦iZÞø\½z5c³ŠÍ¤xÌŽ¿™“}ž{™ï½‡Ãhmm…¦i0 áp¸à+}©|fR¬Ê6qß9cµösÞ T_|Öâ¾´çžÙ铉MùxÆgõá¾´²¦«<ÙØ[yÅÄÉTö£Å¾æt›“žHfV1 î·ç>€±,Ë^dY|>æÌ™ƒC‡Ù3M¦iBQ”Šðe[4M³Ûž½NÕh²ï¡®ëˆD"€®ë“zï‹y.UF®ø,$6Æg1Š•éŒkš>3!ݱ(k°ÎÔx,w\É÷NUU–(©23!VÝmá¾³8ŒÕêQÌy'P=ñY‹ûÒì¶s_Jùp_ZYS}«-Æ©´Ø[•臭µØœU#T¤ñ6ˆeYhiiA?4MC(SÏq:|LÓœpÂ$ŸÏŸÏ—ÑÙÆ‰†Ëç•£-“QÌ{XÌP¯j&F™rÅg!± 0>K±Lù¼ÉªT\Syͤxt· ˜ÙñXÌó&ÂΟê5“b•ûÎâ1V«G1ç@õŧ»]@iã³\±YmǨŒÏêÅ}iéÛ2S}«-Æ©´Ø[ú¶LV%úak!6geBe<ªª¢§§ÇþP«ªŠþþþio‡œ@i¢v–òyåhK©ß©f%«=£I…©–Øfn|Nw¬06kã±´moYS‰Æ¹1VKÛ–ñ–Ř£©`|–yżŒk’«¥mK5`ŒÏ Õ›35.+Ñ[k±9+K~MÆI•nQµcB…ˆˆˆˆˆˆˆˆˆˆˆ(&Tˆˆˆˆˆˆˆˆˆˆˆˆò`B…ˆˆˆˆ¨Ì‰R©T¥›AD90>‰ª㓈ˆª *DDDDDe”L&±iÓ& Uº)D”…ñIT½ŸDDT˜P!""""*£›o¾¹ÒM ¢q0>‰ª㓈ˆªÑÉ•nÑLÕÝÝÆÆÆJ7ƒˆr`|U/Æ'U«šO¨\~ùå¸è¢‹*ÝŒ¢>| ,À‚ *Ý”¢8p+V¬¨t3¦m=8€O|âxÏ{ÞSé&W•/~ñ‹øõ¯sÎ9§ÒM)ÚLùLÏÆï™½{÷âW¿úU¥›[u®¹æœ}öÙ•nFÑŽ?ŽãÇcÉ’%•nJÑfÊ÷L¡ÛdddkÖ¬Á×¾öµJ7¹¬‰vî܉íÛ·cóæÍ=§¹¹'tRÍw"ÍÆ}Nµ+d›$ œ8q[¶l™ñǶ“ÏÛo¿7ß|3–.]ŠÕ«WWºùE™MŸéZ‘o›ŒŒŒ`ïÞ½xýõ×188Xéæ–Ýdãóšk®Á‘#G°|ùòšþlóضú²M8€àÒK/ŶmÛ*Ýäªóö·¿½ª÷›Õ¾/©…ï…j÷rôÛÖ|Bett½½½•nFѺ»»áõzáõz+Ý”¢µ··ÏˆmRèztwwcùòå•nnÕYµjÎ8ãŒYõY¨v³ñ{¦½½½ÒM­JGŽ™Ÿéx<Žx<Ž®®®J7¥h3å{¦Ðm"7“¥R)lÞ¼[·nE]]]ÁÏ»øâ‹gÄga6îsª]¡Ûd6ÛN%>—/_ŽøÃÜçT‘Ùø=3Žm§ŸgŸ}öŒøLóضúðضx«W¯®êÏBµïKjá{¡Úã½Ƕ5?‡ÊL9Ø÷z½ðx<•nFI¬_¿¾ÒMàzTÓO?«V­ªt3Jb¦|ø=CÒLÙwz<žª=ð¬™ò™žIÛ¤XÑhF<Çðð0‰‰D¥›6-¸Ï©>3i›k¶Ç'?ÓÕg¦l“R˜Íñ9“Ž£fÊgz&mÊ­Ú÷%µðœ)ñ>5?B¥š‡MFµÇd´µµUº \*0“*3å³Àï’fʾÓãñTõÁïdÌ”ÏôLÚ&¥J¥ìÒÉd;vìÀððpÍ—ó*÷9Õg&m“R˜ÍñÉÏtõ™)Û¤Tfk|Τ㨙ò™žIÛ„r«ö}I-|gJ¼OFÍ'TˆˆˆˆˆªMö°üöövtttTýIÑlÀø$ª^ŒO""ªv5_ò‹ˆˆˆˆˆˆˆˆˆˆˆ¨Ü8B…ˆˆˆˆ¨Ìªy¢F¢ÙŽñIT½ŸDDTm8B…ˆˆˆˆˆˆˆˆˆˆˆ(&Tˆˆˆˆˆˆˆˆˆˆˆˆò`B…ˆˆˆˆˆˆˆˆˆˆˆ(&Tˆˆˆˆˆˆˆˆˆˆˆˆò`B…ˆˆˆˆˆˆˆˆˆˆˆ(&Tˆˆˆˆˆˆˆˆˆˆˆˆò`B…ˆˆˆˆˆˆˆˆˆˆˆ(&Tˆˆˆˆˆˆˆˆˆˆˆˆò`B…ˆˆˆˆˆˆˆˆˆˆˆ(&Tˆˆˆˆˆˆˆˆˆˆˆˆò`B…ˆˆˆˆˆˆˆˆˆˆˆ(&Tˆˆˆˆˆˆˆˆˆˆˆˆò`B…ˆˆˆˆˆˆˆˆˆˆˆ(“+ñ¢ÉdÉdàõzsÞçñxàñx*ýþÍ*Ŧû~Æ'Ñôc|Q¹±ß–hbÓžPéîîF__šššL&QWW‡[n¹uuuèëëCww7ššš044„®®.´µµUú="š&ŠMŒO¢ b|Q¹±ß–(¿iM¨$“IlÛ¶ Û·oGcc#Àç󡯯èîîÆÖ­[áõz‘H$°qãFx½^f<‰Ê,_l`|U㓈ˆˆˆˆˆÊý¶D…™Ö9T’É$¼^¯”°~ýz #£¾¾ÞJÖØØˆÆÆFÄãñ —922’÷1DåDZoß¾J7£hŦ\Ï©Äç¾}ûH$*½z4 ¥R)Äãq?~¼ÒM)Z9âóøñãˆÇãö0n¢é”L&ñøããĉ•n ¥•³ß6•JUzõhJ$eé·Ö„Š×ëEoo¯ýw*•ÂÎ;áñxH$Æd4ëëëóvö=z” ª˜™’P™(6L9>÷íÛ‡¡¡¡J¯ÍBò€o&$TÊŸL¨P%%“I$ ¼üòË•n ¥•³ßV^H4†††j?¡â¶sçN{hX[[[ÎÀ*dÈØŠ+ÐÕÕU©Õ Y®«« ëÖ­«t3J*;6L9>×­[ÇzšT]]]X²dI¥›RR¥ŠÏ%K– ««+çäöDåæõzá÷û±xñâJ7…ˆˆˆˆˆr(u¿-Ë‚Q%´µµ•¥ßvÊs¨¤R) ¡¾¾>c(X!ÏÛ¼y3’É$¶lÙbwæÔ××yl2™œÔ²‰hêÆ‹M€ñITiŒO""""""*7öÛå7¥*ÝÝݸì²ËÐÞÞŽîînÄãqø|¾‚æJØ´i<t]Ïèjll3Llxx˜L¢i2^lŒO¢Jc|Q¹±ß–(¿IPÙ¹s'úúúìšzÛ¶m³‡mÚ´ ¿üå/QWW—ó¹}}}H¥RX¿~}Ƽ'^¯×®yïõz‘H$L&±aÆJ¿GD3ÞD±Éø$ª,Æ'•ûm‰ 3é„J<G[[¼^oFputt`ÇŽ·&{2™D2™D{{{ÆíèêêBWW6oÞŒ¦¦& ¡««kÜä •N¾ØÀø$ªÆ'•ûm‰ 3å9T¦Bßxd¢&™LÚWÞQùå‹M€ñIT)ŒO""""""*7öÛfÒ ¯×‹›nºiÌ®¾¾>$“I455Õ $Qõb|U/Æ'QuJ$F}}='í$ª2ŒO¢êÅø$ªN<ï$šBBeýúõÂÆáñx0<< ŸÏ‡ááaõ"""""J»ùæ›ÇáñxL&áõz±eË–J7‹ˆÀø$ªfŒO""ªfS*ùÕÕÕ…¶¶6Äãq{TŠ×ëe2…ˆˆˆˆâÊÚ;và—¿ü%êêêL&áóùÐÖÖÆ+m‰*ŒñIT½ŸDDTí&PéëëƒÇã×ëE[[[¥ÛODDDDTu’É$ÚÚÚì Ždi„áááJ7hÖc|U/Æ'U»I'T’É$úúú°}ûöJ·ˆˆˆˆ¨*­_¿ëׯG*•ÂÐÐâñ8áõz'|ÞÐÝÝ=á„ DåÒÝ݇z(ïç´ÖM5>zè!ôõõñÂBšv²æÀ•nJÙM%>>Œîînx½ÞÿýEÕ'#‹±jÑ,2é„J @*•²wVÙ¸ó"""""’É$¶mÛ†d2‰õë×ç}üi§Æãiª¯×‹}ûöUºÓf²ñ¹jÕ*455UºÙ4 Õ××ÃëõâÁ¬tS¦ÍdâsÁ‚ðz½œ(›*Âãñ ±±/¾øb¥›BDÓdÒ •h4о¾>À¶mÛÆÜ¿k×®J¯QUhllDoo/R©6nÜÇ3áÕí‹-bB…*Æëõ"WºÓf²ñ¹jÕ*Îá@QWW¯×›³f¦šL|Ê„ Q%x<\tÑE8|øp¥›BDÓdÒ •®®.»A"‘Àðð0êëëy`IDDDD”Ö×ׇT*…ŽŽ¢3¬±±Éd²ÒM#šõŸDÕ‹ñIDDÕ<©¯¯—]v6n܈öövlܸ>Ÿ‰D¢ÒëCDDDDTd§¤R)$ –#!ªŒO¢êÅø$"¢j6é*ñxÜž(sÆ ¨««³k[nÚ´ ?üp¥×‰ˆˆˆˆ¨¢ÚÚÚ°sçN»LÉÐÐ6lØÀɬ‰ªã“¨z1>‰ˆ¨ÚM:¡²sçN´µµeìÌ<¶lÙ‚x<Žx<ÎÚ•DDDD4ëõööÚ%r=¯®%ª"ŒO¢êÅø$"¢j6é„Êðð0êêêrÞ7ÞíDDDDD³ç$ª^ŒO¢êÅø$"¢j5é9T¼^/vîÜ9f¾”¾¾>$“I455UzˆˆˆˆˆˆˆˆˆˆˆˆJjÒ#TÚÚÚH$°qãF466¢¾¾ÉdÃÃÃèêêâ("""""""""""šq&P€-[¶ ­­ ñxÃÃÃX¿~½=A=ÑL3¥„ êY²¦%Í“žCâñ8n¾ùfûï¾¾>tww#•JUz}ˆˆˆˆˆˆˆˆˆˆˆˆJnÒ •D"öööŒÛ<âñ86mÚTéõ!"""""""""""*¹I—üÚ±cÚÚÚ°eËû6¯×‹[n¹7nD<‡×ëÍ»œT*…ááax<û¶d2‰d2™ñ¸¦¦&ÎÍB4rÅ&Àø$ªŒO""""""*7öÛR¹™&`Y€¦Uº%“7é„J2™Ó‘uuu“  h4 èêê²oëîîÆÎ;3×ÛÛ[P‚†ˆJ#WlŒO¢jÀø$"""""¢rc¿-•›iº>K*MMMèëëC[[[FbeçÎH$9“-n}}}ˆÇãØ¹s':::2îK¥R D¢ ™(6Æ'Q%1>‰ˆˆˆˆˆ¨ÜØoKÓE×Å•Z4é„JGG’É$|>Ÿ@ÃÃÃH$زeKÞ„JSS<Ϙ!b€˜ìÞ]JŒˆ¦ÏD± 0>‰*‰ñIDDDDDDåÆ~[šNŠRéLͤ'¥€-[¶`ûöíhllDcc#6lØ]×ÑÖÖ–÷¹ðz½¨¯¯Ï¸=•Jn¾ùf\pÁ¸ì²ËÐ××—wy{÷îE{{{¥ßGš¥ÚÛÛq×]wUº%1^lSÏ»îº ÝÝÝ•^5š…‰ÚÛÛqàÀJ7¥$JŸ@{{{AqLTj}}}èîîÆÁƒ+Ý"""""r)W¿m"‘¨ôªQ2ŒÒ-«¡aìmÝÝÝeé·-h„J__úúú°aì_¿ÇN¦”J2™„×ëEGGz{{DZyófx<ž ‡’­^½½½½%cˆ ÑÛÛ;+SÏk¯½vÌ\DÓ¡±±½½½³"á>•ø\±b÷T1²ll<¯tSˆˆˆˆˆ¨ì·¥rÐõÒ-KQD 1÷¨—rõI4B¥­­ ·Ür <¶mÛ†öövtww—4»(;¿dz½^lذ'ÛDU€ñIT½ŸDDDDDDTN<ï$ˆÅJ·,U-mÉ/Ã(mû&Rð*uuuX¿~=Ö¯_@LBß×ׇd2i—ý*fÄJ2™D*•ÊXF]]Ýô¼ D4!Æ'Qõb|Q9ñ¼“ IŸ¯øeÉ„ŠiŠßK¡”%Ä&2¥9T`ýúõزe z{{±aÃìØ±7nœò¨9TLÖäK¥RعsgÞIüŸDÕ‹ñIDDDDDDåÄóN*5]ü~ñ{sóØûC¡É-o`Dҧ܉•‚G¨L¤ó©´µµ!‘H`ãÆðx<B[[[AÝQy1>‰ª㓈ˆˆˆˆˆÊ‰çÓ'4Mü«F¥l—e‰Ù ÷m­­@0˜ÿu#ñSUK7âe<“J¨Äãq$“I;X‰„=!wccã¤&zÉ5!Ñ–-[H$0<< ÇÃ,'QŒ7Y㓨òŸDDDDDDTnì·­Óÿª5¡‰ápñËq&É.!fšÎï–5ö½hmúû³ø€Å€ 1ú¥eÉÆSpBåæ›oF__:::ˆÚy›6mBSS±sçN$“Ilݺµ¨;Ò…ˆÊ‡ñIT½ŸDDDDDDTN<朗0M‘äœÛ¢Qñ3WÂÄ=BEÓœ‰®‹ÛrM>ï_„öÚšò¯OAs¨$ ìØ±Û·o·G¡ìܹõõõغu+ºººÐÛÛk'UˆˆˆˆˆˆˆˆˆˆˆhrJ9:¥¥¥tË ÅOÃpJlÂ4s'ATU$O²—¥ªNòÅ0œ+º.þÉ$KÆk¬´sÅ}îÄM9”PÙ±c¼^oF2cýúõ¨««{¨*DDDDDDDDDDD“£(¥›T=;éP¬ÖVÑ6ÉñÈÑ'Òx5Mg]ÝmÍNÀÈ„Š|¬e9󤘦‰ŸýlÆ0à;CÜ7Ù í'« „ €1uñâñ8ššš2n“É"""""""""""*œª–.¡¢ª€ß_º¶Y–XžiŠÄÏx²G£äqcb– d>F×$Š{>MÉ9™=tvvâÎ;ïÊ‹€Ÿ8ÙS %TêëëÇí¿wîÜ ðz½öm©T ‰Dõõõåm1Ñ SªdŠäNHk`@´OUÇýbY™÷E£NÄ-¥¹ Ãùâ&ËvY–3Á¼|í@@$m À¢(¸òÊ+qü”ãè}) åÔÌå;v¬´o( L¨¬_¿Éd7ß|3vî܉h4 ¯×kHI¥Rèîî†ÇãáäDDDDDDDDDDDDdš“›ë$9‡‰,·•Kvb$í‡ÇÞ.G¹äÁ’J¥‰è‡34á0ðØcGqÿý?ÁöíÛÑßß¿û»O`ñÒ8úêopáâÇì$Òy燒¿¯'ò ǃ[n¹›7oF__¼^¯=9}<G{{;<¶nÝZòÕªd2iÏ1èÝMD•Çø$ª^ŒO"ª%–5q ¬É‡K7JEQœÑ¥`¢äW,æLP/…B"Ñ’=)¼œoÅ4ÁÁÌÛ±÷ÄóR"q ££ÏâÁû°zõF˜æ<À»Þõ'\z©‰ßýîn¬Xq–eáç?ߊÑ–à3¯ý/>¶¾÷­­­8í´‹±k×Büá J÷& À„ 466BÏ1–§©© ½½½ÜÁ¹tww£¯¯MMMH&“¨««Ã-·ÜÂy‰ªã“¨z1>‰¨Ö´¶ŠrX¥ÐÒ"îäC>¦™{ÔˆªŠ„ÅT>rž”ì穪(áe¹$~¿HªÈ‰,õå^ŽišðûEƒc1g^é…þ]ôn<òÈ#8vìF<þøðûß·bhè¿qÅESÓÉØ¿ÿfXÖ…BhhèÄž‰äðÐ־ϼŸÂwÌÅ)§<†}ûæ—fã¤<)ýxêêê˜L!""""rI&“ضmn¹åôööB×u¤R)ôõõUºiD³㓨z1>‰¨•zÞ“É./Í=§‰aˆM® nîIà¥ÎÎÜí£T²çDñûû;;åƒâŸ»äWKK‹ý»ªŠçÊçÀÿüÏ娵kÖ­»ûXþøÇ§ðÔSOáòË/‡¦û÷߇… â±Ç.Äý÷Ÿ…Gy¯½þâVœuäî¼óT=ú<Î=÷W8é¤g±jÕË%Ý>'Tä*íííØ¼y3‰DIBDDDD4S$“Ix½ÞŒùׯ_áááJ7hÖc|U/Æ'Õ¢ìäB±²Ëiå:¿’€éìÛN¹ ]#Eä²:;ÅïÙIM#Mdy¯ìeÉ嫪x®e/½Ô‡XLN"X–EQðÊÉâ?úÑ'2ÖÁ4M,\¸çœs÷Ý÷xzéœ|òsèí½Š<ÿüo02r.|+vï®Ãë¯ÿ›OÛyÊ=ø°ò'ŒŽâÇ?~Éä_áÕWÏÆÞp¼¤Û§à„J{{;âñ8‘L&±iÓ&»ž%9¼^/z{{í¿S©vîÜ Ç3áóFFFÇ+Ý|š¥âñ8öíÛWéf”ÝTãsß¾}¼°*"•J!cdd¤ÒM)»©ÄçñãÇÇÙGE‘L&ñøããĉ•n U¦•v”ŠªæOÒȈ|}Ó̼ÍM¶-{™îÇËä‰,õ%Û‘Ý®‰È$Šß/‹'´ÌžÇŲ]סiN>YÌDòÛß~?¾ß~ýh4ŠÖÖG ë!,[6ŒÿüÏW˜xè¡7¦Gǘؿÿ>œq†˜SåœsFqï½ pã¢a|`ïàó™8õÔSqøðRœ8qeé6LZA ¹cÚ¾};ººº°}ûvÔ××sÈ%Q;wîÄÆáõzÑÖÖ6ác=Ê„ UÌlI¨¸M&>÷íÛ‡¡¡¡J7™f¡ááaÄãq=z´ÒM™V…Æ'*TIÉd‰D/¿\Ú’BT[äÄë¥à÷‹ååJЈ„Dî×7Mgd‰›ÏçL Ÿ=âÄý:2‰"oËU&,‰EÉ,Ñ%“0á0pç/ ¯ïi»ÿùŸÿŸÏÉÜhšEQðÐC! AUUŒŒ$1:z‘°ti+~úÓV¼òÊ%H¥®Ç’%{øƒÑF 18œy晘?ß‹+] 5©Âçóá¿Vÿ<ž/axXî7<üðÃ%ÝÞOJïõz3&[¿~}IBDDDD4“¤R)lÞ¼Éd[¶l)hÞÁ+V «««ÒM§Yª«« ÝÝÝ•nÆ´˜J|®[·.oÒ…¨<ºººfÍ©ÉÆç’%K¸ï¤Š‘ŸO^3»ù|°GaË=B$Êœ{Ä0Di-ŸO$V CŒN‘²“:š&ž¯(@$2öµrÍ…"“6@î¤N +¦é¼¾iŠŸ­­À÷¿ÿ žxâ0Œÿ|èCo<úè£Xºôuèz?|>úúV@Ó4X–Ãøî¾{5Þö¶¿Ä}÷=`-ÚÚÎÅ~P‡5kcÉ’Ã8õÔ4m-B!hi^xa•hÔ<àÕW_ Χþߟ==b½O=5…U«V•t{=)=µiÓ&x<èº^Pg-MÆ'Qõb|Q-Ê5rd*d#×(EÉL€Èßs%W‘|‰FÅÈ•þþÜóž"I"Û¯iÀ1(dÌ•pX~úÓsá÷û ( ^ýoðÈ#sp÷ÝÇ’%‡pæ™óññ?^x÷áÿþïr;Ѥ( 4 xöÙsñÞ÷ž…Å,ÆÓsŸw,m €SO=oxÃJº­™P!""""*±¾¾>¤R)¬_¿ñxÜþÇr$D•Çø$ª^ŒO"ªErîÉpO*ï&“"¹F‡Œ7GŠ!“ýˉӣG²_S>¯³ÓIžÄb™K×_ÿ]\ý³X¶l¦é$Pš›Åëhš2<<ŒÝ»wò€M›@Mg_þìÏþˆH$‚‡Ú]íq~O=õG¼õ­Ç0þ>ø|>ü÷Ÿ‹ãÇ¿…ãÇߊ^XeÏ¿ˆd‰ß\tѬ:åe,N=(^ËÔaÑ6Ÿ¸öÚß”|{\òkhhíííößrg–=äÔ=yÑl”L&‘L&3ŽŸ ££ƒeIˆ*ŒñIT½ŸDT‹dù+÷¼"ùÈÒ]ÙÏSUñ·LldË…"o …Äïºî”óùœQ-¹4ºî<ÏïÏ¥¢(™ ˜«®º ÷Þ{ /½ô4|ÐõÌ2>Ÿ(+ÖÐpŸ‚e £c|p.ü~?>÷¹»0gÎJû9¦)&¨WUš¦aáÂãX¸PÅÁƒ¯axø¿ (†¦ºÀ¹çžÃ@FBÅ0œ‰ïßtRæc…H¨¨€š^Ë~ÿû ÐÚújI·wA •úúz455eÜæñxJÚ""""¢™¢««‹?DUŠñIT½ŸD4[†HXVfBENüž«„W àÌ… ŠçÊ…ªŽ-é%ç6&žãÅ=_Š|¼¢ˆ2aº®#âÑG—ã]ïú |¾µöó²ËœÕÕ„a¨8ùäŸá±Ç>„%KRéejøÆ74D"bùª ±X >Ÿ±X oyË •: ‰Ä1ìßÿ[hÚ¿ØË}ë[߀Ûo¿¦i—^EqÚü†³ñ[¼”n8Ó¡ò䓸´¤Û® „Jcc£=ò$™Lf ·ôx<ذaCÆ„õDDDDDDDDDDD3ªN~RzŸé¹ïF3'¤2G¬¸'Ž7ÍÜÌËÒ\ògöýá°x^4*–eY¢]²„Y(D£Íú®ºê*>|¡PátÃLSüS±.øCO>yþùŸÏÁC ãxªz%q¿¦wßý¢Ñ¹édˆ Ã0`–C×Ó\ˆÏ|æ‹ösLÓÂ…ž‚Õ«B×uô÷÷pæm±,à‰}§bÒ5Ê408(þ\¸ðxÉ·÷¤æPéîî†ÏçCww7‰‰n¾ùf\sÍ5ضmÛ¤^8•J嬙°!¢é5^lŒO¢Jc|Q¹±ßvr,kìœ#¹#ç@Ñuñ/Í]ŠKÓœÑ(î„‹q"KŒE£ÎH 9úc¼’`îyVd)/ËrÚ‹‰ŠLÔƒÀÓO?ööûpÎ9£¸þúå€ù—OÛ#lB!àðáÃX´h`Ñ¢°ÿxꩳ3ÚñÍoîÃi§µãž{îq­“ UU‹9ëwÝu×Ùí^¾\Œryï{ï·çc‘÷õôˆ¤ÊË¯Š¥8‰ˆˆˆˆˆ¨ÜØo;9ÁàøÆK2yá‹åžwE–³Jç.l²¬—e9£WäH 9ù|®vøýN"Æü1 ñON*ˆíÜšž1~ëÖã¸òʳ°dÉ9P/¾¸éa2ï}ïůңU4~¬Y³e¾çŸÿ=ìÚõ R© Ã@,ƒ¦iðûE§¿ßíã÷uu»ˆej9²Eá0 ¬UpwÝkÎʦ ’_‰DÛ¶mÃöíÛÑØØ˜q_]]:::ˆ`“¿§¯¯ñx;wîóØîînlݺ^¯‰D7n„×ëå|-DÓ`¢ØŸD•Äø$"""""¢rc¿íÔèzî‘!ñùD"&ÉLœÈD‰aä.#&“"Šâ$rä|+>_îb²mr"w÷í2©"G·Ì{TU…išhkû%N9åZ+qÞygA׿ßh:3ˆv|ç;¯# Ú‰EQ0gNúE :0þ>|ðƒ«päȥػw/4M³'¦Ï5 ôôôØ#Sü9²O¡`ü¸bÑÎÄ\*“,ÃV¨‚F¨Äãqx½Þ1É·ŽŽ¤R)Äãñ —ÕÔÔ„¶¶¶1ËŠÇ㨯¯‡×ë æmillÌ»<"*ñb`|U㓈ˆˆˆˆˆÊý¶S—+ˆyOÄÜ ™·›¦H¦dßJèPçq’Ì'X–XfKKf’${.—@ w¢G&pü~ñü¶¶gqãßE$¬]»`®ºÊƒTê<;Q"æc1aY|>Ÿ=7˲e'e”ã’¯ ¦ÿˆŠÉí/^ U¢Ñ¥xùeñÙÑ4mÌs3ß×ñïs{ße®Äž‘T)“‚*ÃÃÃ-LÕDáõzQ__Ÿq{"‘“Ѭ¯¯Ï[“oïÞ½hoo/ß;D4öövÜu×]•nFIŒ›ÀÔãó®»îBwww¥Wf¡D"ööv8p ÒM)‰RÇçÐÞÞÎ!ÚT}}}èîîÆÁƒ+Ý"""""r)W¿m"‘¨ôª•U8,’#±ØØ"21¢(Τðªê$3Òs¬ÛäcERB&HÜs­XVfGU1špF±dÏÑâ÷‹ûdÒæSÁ܃yó’X³æi¬Zõ>üá3áóù`Ö®µk‹ë¯Ÿk¿ŽÏç³G•¸_ßýò6E(½eˆ„ÊG?ú4M¼~CÃhšŸÏŸoêCI@»PþÂ}#ŸUUŽ~Û‚*õõõ%UŠÉJæZ~!CÆV¯^ÞÞÞ’¿1D…èííŵ×^[éf”ÝTãóÚk¯EWWW¥›O³Pcc#z{{±bÅŠJ7¥ì¦Ÿ+V¬@oo/ÚÚÚ*Ý|š…ÚÚÚÐÕÕ…åË—Wº)DDDDDT€bûm'ªzTëtÝIPÆØ„ŠA¢(N²A–“É7™[s¥¸'wOJ?žHøû¿·Ýv°ÿ~û¾›o~ LJe_ýÄW±ð‰…xûÛ×à…®@8ƾ}kaY"É¡i.½ôR<ñÄöÜ,º.*²ôV8Œbè: ´ì)! «««,ý¶%TÖ¯_D"1a¤»»§ Q*¹äºê6_–“ˆ¦㓨z1>‰ˆˆˆˆˆ¨œxÞ919ÿG®º.’"Ѩ“<‘#Hrɉˆ²a²¼–ß/’¢ü–3á¼a8|ø íÃÀÀ!|å+ƒ³Îº ÿýßH$‚P(„Õ«_Ãîݯ!.ÿ¿Ë1wî\|ruÆëËäˆßïÇ 7¬àŒ²‘éšaò±æD4àÑO>ŠVÞ%½ @X³fMÑÉù^†¾ /¸nT˜S]b~%T<:::°yóflÛ¶ ©Tʾ/•J¡»»Û¶m+êJôÆÆÆ18<<̉ˆªã“¨z1>‰ˆˆˆˆˆ¨œxÞ91™pÈm’‹LŒ¨ª3©»{T‹;¡"§(Îó hmuž ÉûM¨ªŠSO= 6âÒKÿ·Þz5,xKúuM¬\¹wÝub1 ñî?+ež3rF¶Ç-·“˜“DNZßÒÒ‚Ô÷RøÞ£ßCû%Δ–å¼f±Æ­¦¢lI•‚*€"ÓÖÖ†h4ŠË.» >Ÿ—]v.»ì2ìܹ[·nÅúõë§Ü¯×‹ááa{L"‘@2™Ä† ʳæDT0Æ'Qõb|M’ QË™ˆˆˆˆ ÂóÎüdâÁ(È…ÒÓ##'x÷ûÇNfï.Ÿ%G¡è:p÷Ýe”üºë®ûaYÎk(Š’.Åe¢®îÛx晥xä‘GpÝuká÷ûÑßß /¼ðÀ¯àòžË~7 ,ÊyÉöe Åkf—2O4E(Bkk+ࡃáê]%‡–ØQç5KÁw) .ɺQCÙ*'OæÁ]]]ˆÇã jªe¾r-óæÍhjjÂÐкººPWWWž5'¢Ia|U/Æ'QNÒD‡8¡ç—@ ÄD•~ˆ+׈ˆˆˆ(/žwæ&K}Åbâg($&ˆ—úûE¹/MQUñ·¬våóMª À x0M`Þ¼•X¸p?€•xã­·~ùÈ›íL,C0ć>t ^|q’ɹX±bÞò–“ì äÃaà_ÿõe:tÏÍ?ÿqó™;ñÍo†à÷ûí$M4…išÐu@ýýýÄäõðÑ'>*湓3‰4E²íÖ‘w†¬+Íë¸M:¡2žd2Yô<*fu@U;Æ'Qõb|QÍè„Hz"y¡bü„Šiâ>Ñ A$Q ˆ“³V×ãÔôòýY¯Ù ‘8QÓ5á$XÜÌôrÍôrˆˆˆˆÀÌ9ï4 ‘\NáXOÎc"çî%¹|>‘qϳ®ëNE&SrÍEbšN2ÆÿNˆãd 8räLÓÄ“Ož†×^»úÐQôô\EQìGz¾x´¶o{ÛÙcÚ®ª 4MÁº{å4%3¹ã¼G:;;š¦èG__‚Á ¢Ñ(Âá0LÓD(‚ÏçÃÀÀ€=é|N²ì®â´¥LÐï‚geo¨ô{X†„JÁs¨•DÎD‘ÄÉNöI• ‘d‰@”0Ò?Cp’aˆNâ*¾=I™ìI. ’#ò5éçJ/«ÎI^+œÑ.H¿N´Òo•Še>'H¶ìçÉùPäïî‰é5M$8¢Q‘H‘ùwRE>_ÎÚ 1Â:âÜÿ÷¿ëÖ¥08F4…ªŠ­\ù,\¸0g .U–/_>æ69o‹uU:‰Ó*Êx…Ü ì¤I?4MÃÀHüÁ`±ô(îÇ(…ÔñšÄÄö“¶2Çmeº8Š """""*¿(€ˆD9$ ‘‰A$9Ò'uvE&24×cÉ“Céßµôßé:ÓÈq…Ôqn—˶ NZ£éåàœðE!’8H·-šnŸgä Õ”BFHÈ’]n–•9jDΡ¢(Ψ•l€Hdâßà sŸ¦‰‹&G£Ìƒ¸8HsžF±{w]FëŒ3n²ËfÉ)¹D£¹Û‹Ö±~¯x^ÁŽßÓ4íD Ê}ùý~hš–•"¯( 4MC,C,ƒßïGA|(K9]M‚€ruîûWï^]ò×dB…ˆˆˆˆˆJg¼+Ï|‰?€A8“Â+É sä‰1²$œ~®ŽÜÉw¾‚oJüévÉå‡Óm’'ÊD‚¥9}[ Ý9±¦Ž`!"""šäÈ7Ÿ/3ÉbΤó2¹!Ëwéºø]– “Ò§+ie¼N,&ó­+Ÿ@*•Âðß &pÇÇñÙÏ~6=‚Å„a¸é¦OpFœäâ9““˜Ž7½é&\½ñjøý~é•5 #]æ+“3ÿ‹†ÎÎÎÂF¦Èö©pJþ–aúm€ú«\oBy*Í¡ÇÇ'|L*•*ý;BDDDDDµ! ‘‰B$B4ˆd‡–þH\HÙçhJú1ZŽûüéeçRªÉã÷äxÍV8IWÍg»|€”H$b†‘ä(ñü @ae¾äq²gÄy ©*`¼ þÙ$>`õçVcϘýâ”PI&“H$yçõzKûŽQmÉ”0D2ÁJÿôÁ)¥5™H¯ÖñD·—#Y¡A\E'ÛýîöDÓ÷»'º¥o“ë߃ñK’Ñ´“³ç¾Ï²ÄhÀ"G˜¦Sžk<²—…¢i™ó®ƒc“1šÜÿ—°ví|œºì¯plÁ1\¹éJœýàÙ¸*|,ËBgg+ CÃþýûñ…/|aÂõÓuïyÏ·ðö·×!èD+sdYZZ |¸ûgwãõ&,<¾ 1‹®ëcJyMx.GøÈcå³·c®9TÒM<ùHA)‚´´¶¶6´µµ•~‰ˆˆˆˆhfð¹~Fá$ä\(‡ò<_…HDLV¹jºý…>6äzŽQÖ óÆÈÑ:²v´•^W"iSâ+õˆˆˆˆh|º>vnÉ02îßåÈ÷mÙËQ”t*ÝÕáNÞ(Š3rEºúêƒèéy'N| •xáå°äÿ-Áò1©|$±*Š‚o~ó›Ðu}Ì(ˆÅbðù|øô§¯Ã7¿)(‘HÄN–D£QÌ›÷W8ýös°hÑâÊÏÞfÏ ”á Ô}¬.Ëøæ»Ðj’|kßu¹ïÛuÉ.,ùÃ’’¾^As¨¤R©‚F¨Ñ,%ç>‘‰÷Dòƒ˜Ù%¯eÎd2ÅmOúýè‡H Xé÷EŽè‰¥ÿ§ãÏKCDDDD“&Kr9ޱ|>gЦM˜h eþíÎCX–3|8}±;¡¢ëNé,˲`š&~üã+qìXÿ÷'ã°yßñ8t]·GtÄb1ô÷÷ãСCðûýˆD"hii±ç<‘ Ã@4E0´_³§§†a ¹¹¡tÃ×­[‡¸ù2–-û»²±¹Gi(Ëq­ù ä¾ï¡«ÂÈ#“[`%T¢Ñ(º»»3nëîîF2™,ý;@DDDDDµ'{böœ9Ff{™+5ý @$Wä$÷a8óÍ´@$[þIÿT!®,æD·"1ˆ‘4îmeBœØ†ÀÄ Í ª*æHQÕ± “HD$Dä(–htâeE£™q@iMüðù€ÁAçw™ìøâ¿ˆO~ò“xå•Wðâ‹`ñâÅh>åÜtÓM0Mè;A| @(‚ªªˆÅbˆD"hhh€ahii¦iPÓ/ (¢4W?zzz000€þþ~,\¸çá<\xá…b¡A”‡¼Èn ‰òì‰JenUu&>5ßXk‚> ¡EÜ/¯Šôù¨%r\>C<ÇïTM\%©(€¼hQQÄëš!Q'|pPÜfÀ>p%Z[÷Uúí""""*+à ™‘¹ËÇ_ròxŸOÜ 9“ÌËã:ŸO<.;)ÓÓ#n3 17ùÅ_Œ7¿ùÍØ·o~ô£á™gžACCƒ=׉»M°«ÿ¶ão',Å%)0888nâ%›¦ÖÓY7ZpÊÀ–ІÜÉ“VˆÔ%b :*ÉdrÌÄô;wîD<ϸ­««kúZODDDDTåR©†‡‡áñx*Ý1ŠÄ€H’ÈòQ&Y qÒ#K¸«ȲRr¾) š€e9'ë†!þ–õ¬ÅU‹™%!"‘‘'ó‘ˆ8)×´Ì“uŸÏ¹"Ò4çËZà€¸Í²ÄóÜå*秦9IM0‹J~UU|QÆ'•“<ÎÊæ.‹DŠ, ‹9å¾"‘ôˆ’súýNBæ§?ý)úúú`Yü~?¾ýío£¡¡>Ÿ/g‰.㈫ò–g^¼< M¦âØÐ¼ óBâÜ Pðbò3 .ÖrŸ/(éõ2P²ùµ3KØæ”Pñx<ðx‰¨\ç8NΕ⮖%'¤…ıR4ê̹ˆc³hTü+¡bYB¡NìÝ{–,Yb—âŠD"¸ñÆaY±™ ¿0·—ýc1 p ¹1}(ÏÄô¹È×*QBeº”PikkC[[[¥ÛJDDDDT3úúúDZsçNttt¿ÀRÂ)Ý0€Ì¹Oäè€%¼²„ÒWú|âÚ²D‚D–yPqrjYâ_g§8)nm?Ý–ö÷;“•ʤŠ\~ö…Šq®T”Ì2^îÛÃ5”WUÆ'`|QùE£â8LK¹çGñûE’$ÇgÁ xœ{žEqŽÿàK_ú4íSö(‘X,†TêQ¨ê^üÓ?9kA÷áLÀpÖeš§Ðø¿¬|†@g‰_d¼’_ ç&5xÎ1©9Tº»»‘J¥°eËtwwcÛ¶m÷{<èº>™EÍHMMMðx<“Õ=22‚x<¯·L%—:áÔå dç»åºm–3MñOÖÏ6 '!“&~¿3i©Ï'n7M‘d‘£L,Kœ°çJpô÷gþ] Ix<Ž}ûfÇü)S‰Ï}ûö!‘H ±±±ÒͧY&•Jahh###•nÊ´˜l|?~ñxÜ®®B4’É$üqœ8q¢ÒM¡IpÏbY™£Sä0­­âxM×Å…2Ù#XÞúÖãèíý={ìGX¹2Hä(Âá0:;;Ñßßææf„ÃáŒIç òBÖߥ,Áåj¿‘Ç®£•ýç¥Áœ«ä—4~­ŒRéß`Méß§ñœP¹ùæ›±cÇŽŒáH^¯[¶lA__vî܉­[·N_ˉˆˆÆaƤꇕƒìt­¯¯/ø9G-oBEÎbBL$ˆáöÆÎ2ÉÑ#Ù“À«ªø)KsÉ He}lEW'ʹMä2Üeb±Ì æåO9_J-˜M •©Äç¾}û044Ä„ •U®ï©ááaÄãq=z´ÒÍ›“O™Pñz½L¨Ð´K&“H$¨«««tShäÜt²Û@–ü’ó¤ÈcºXÌI¤¸çSàØ±Íhm};víú$>÷9>ÿù?Ãèè(~ûÛßââ‹/†Ïç›|2€¶8û†Ò¯¿ªVˆó˜i:—)(¡’H$Ð×ׇíÛ·9xôx<èêêB}}=nºé&lß>õBoÉdrÌMMMüR"ªŒOª–e¡³³ªªâ´ÓN«ts¦ã“hæX±bEykŇ‘YYž É‘)5žP‘ó‡¸É%¡8!–êñ¯³S\}‹‰Ÿ2I¢iÎÄðrt ù»ûy` Òk_¼®®.twwWºUkݺu,…M%3æªà4y´»L ìwqÏkKŽ%K–pžªyL<¯tSÊ®Ï;eÉ.]Ïœ“Î4 fTUÌ{''Ÿ—Çw~¿ó]-“/rd‹®ë0 Á`~÷;`Ñ"Àçóá«_ý*®ºê*üÏÿüb±©MH’1)= ŽÝ”ô8=ÌÀ’+qBVÊDI¿Ne…SN%TvìØ¯×;á•8ˆF£E îîîÆÎ;3nëíí-ßzDE2ÍÙSƒñIµ@×uÄb1ø|>†1k®²e|QÁBIΉR"¡Ãôœ<•I4*N„Åɰa8µ¯MSüîó9sŽD£N9.Ms"î$‰¢äžh”ˆ¨±˜(%³gOfREÎψÎ=ÙÑ'çd""ª¤Z<ï4 gòx÷÷¨»œ+àïiš¸àÆ4MüìgI¼þz=,ë5}ôÿÃüùg";Àw¾Ó‡3Ï|+††tøý~<ôÐCøßÿý_È9é|>> ß“ucF‹„B€ñ; hd–2³7¦gÂø JSr8€i‹eRs¨¸µµµ!•JeÜæñx0<<<Å%Šº ÕˆD¡P~¿–e!bݺu•nÒ´`|Òt°, –eAUs1ÈR^¦i—Þë[–Ã0‹ÅìÛƒÁ ,ËÂÆ+½JÓ‚ñID‘ZÊ¡üò¤ÒJÿ­è™Âr§™…"K2Äb")ÒÙ)~Ê]€3!¼œLÔ-Ïœ DDö$Ź«² L!UfMS\­ëâ{J–“‘IÝPÈy\?ÐÜ,þŽDÄß2áÛÚzm¥ß"šÅjñ¼S7y&v—£PZZä-Q<ýt ©Ô\tvÞ––VŒŽ„aÜßþÖÂàà TUÅܹ¿ÄŽë±ÿãˆF›pã7Õ^U´÷eÝ„8^/µ§Ç¹½bÔH)* &N)uééõœª(ª¯äW}}ý˜DIv]ÊT*UôðÓx<Ž-[¶LÏšSUÊU¦¡B¡Âá0b±Œô·ngg££K ë:EeY0MsÖ$TŸT*º®CUÕŒ¤I$ªªˆD"°, ===P‘HápÑh¦iÚñçóùÐÙÙ PUŠ¢@Qô÷÷Ûs§(Š‚5kÖTzu§㓈 bAœɉ&å×°üYáIÑ£QÑÁˆäH+¹cšâ~U?å¢rQŸOÌU¢(@Cƒx®Ï—¹L"¢É’ÕZÜ¥^LÓùæ÷‹ûü~q›®‹ÇÉÛ4M,C~išHôŠeé:°t©x¬û;OÓÄmÙ£RÞð†Ç+ý–Ñ,V‹çá°Sîu"2éÝÓôöÞƒ_ŒappŠ¢ ‹!‹¡§§­­­Ð4 ªªÂ²,œsÎ(Ö¬Ó`XÖEW²QU@ÍN.˜ ƒ^øѾ ƒ8o(6©’/¡‚ôº6cÚG™£ „Êúõëía]ëׯÏù˜h4Šººº)g)åh—›o¾ñxuuuèêêÊ[£vdd¤¼wÒ´jmuÊ1LÓ4¡ªª<ñù|ˆD"0 –e!Ã0 ÜpÃ_ãøñÂ4M;ÉòÔSOÍŠ’BSÏ}ûöUjŸišö‡¢(Ðu–eAQ ‹!BUU˜¦‰`0h'V ÀßïGgg§=™[8,zûTU…aÐ4 ÍéKøúûûí×M¥RÂñãÇ+ý”ÝTâSNÜéñx8q'M»d2‰Ç'Nœ¨tSf/ ΄ô€8q©p2ŲĕزVu4êLᆰ[^ ®ªÎ•Ûöj¤OÀ®ua2…ˆŠ!')ŽFQq²àà ¸’YÎÑ40à\ :£åÅIòš¦3ÚEQr'M€Ìï6·eËž­ô[BD³T±ý¶•škÅq’ywöÈC™8ÿÇ<†åËc'SÀï÷ßþ²öÅ¡2y"¯D"(ŤzÙ£Qd¹^ %K8è:`^6Á‚¥‚‹]3Ýö‰úyå\*Lýœdœ<‰D¢,ý¶%T<:::°yófttt ­­ÍÖ÷õõaëÖ­SnH2™„×ëEGGz{{DZyófx<ž “%GeBe†‘­å&;u[ZZ F±X ýýýéÉ¥‚öÕð_ùÊCxãàâ‹? øŠ¢àœsÎÁÐÐýÅ:SM5>÷íÛ‡¡¡!&Tf‰h4j ‘ÉUU íR]AW}•††¨ªŠû@Eêï,ÒEKÉ2anÃÃÈÇã³"¡2•ø” ¯×Ë„ M»d2‰D"QÕ“W–Zooo¥› ¨¨ªIçåUÕ(JæUßrt‰ªŠÎE÷¡ÀøŽ3ü°ŒJ¬jâ“Jf¢R\†á$5¢Q§ LêÊ„ˆaˆ„ ¾‡Äcå÷Ž<_íéq¿rrcù½–ë;J–”¡Â0>‰ªG±ý¶gÚÿå÷±iŠïmÃ5_Höñ¢ªï~÷qD£à¦›®ÓG!¹ûÿäE ª \uÕ"¼ï}%H¦À`®Fq ‡,æ¯ßÐsúÒ¯—/’O¡¥ÊÂZ0õ¤Ñ8ƒ†††pöƒ–ü¡à9TºººP__h4ŠmÛ¶eÜçñxŠ®¡×ØØ˜±³ôz½Ø°aCÞdÉŠ+ÐÕÕUÒ7…*GÓÄ]¹È^Ã0ÐÙÙi— …BÐ4 =éqÖªªŽI’,]º@Ï=÷|â§À0 ¨ªŠ§Ÿ~z -©-SÏuëÖå½ZªŸœ/H&CB¡LÓD,C @kk+ü~¿=w‰®ë‰’\IÇœ‰H “Zªª*V[™±ãõx<èêê*ºe-˜J|.Y²„ûNªù¹ŒÇã•n M³ÖÖÌFwòD^ñ‰ˆIš1‡€¼ª›ˆ¨¡H¨hšèH“ó*ƒN¹-ŸÏ©ŒÐÒ"¾ƒä9À™^&fTÍýz²#Êý=U %¬‰ˆJ­–úmMÓI^÷÷‹R²Ù‰ƒÏþ|ÿûI{´É©§>|­­¿Çõ×zÂåË>EUUÓ#VJ¼sdïwdY¬%TÔ•@g k!æ`,æX|2eà FÅ¿LX6îç´µµáG÷ß_š7ÍeR“Òwtt ££#㸾¾¾$WŸ'“I¤R©Œeͦ+I(d¢¨Béé"‰>×7C$±¯j÷ûýhmmE8F €zKðè£áøñÍðù‚Å—è_þå_Vúm+;ÆçÌ …à÷û¡iB¡¢Ñ(‚Á t]‡aö¨9黪ªv|ùý~{þ“°«ÆŠoª½_:œÉÄ Üéjš†ën¿.s‚åY„ñIDcÈ9R Îw£<ÆšÖÒª¢ã› NEÞ&ËáÄbNG&à”Ï!"’¢Q'Y’=Åç#Eä¤îƒƒÎ\$¡ø~ ÄO9_‰iŠçû|c;ÛX2ˆÈQKçÍÍbn=9âPÓœ„ÒÞ½{ÑÚz=úûûaš&n¸¡ªªâ®»ó𦙳ÒFÉä:VW îãüb^âÒÛaAôÑLuŸMÿ,4¤èDñ¥Æ\œuJ·8“L¨Hå(¯DZmÛ6lß¾uuuH¥Rعs':::JþZT½tÝù’›Ì÷’,ù#;}u]‡®ëé¡w*ZZZ088Ó4퇃ƒƒöˆ”üËR©åv"9ŠFÓ4Üpà •~ÛÊŽñ9ó躎H$b2±, ªªbÏž=hmmE(²ËtÉ r4 1rÄÊÒ¥K3JyE^ýCÁ;\EQÄÃõ|Sßáׯ'eX q’5q£@|/ÊÄJ±KŽCÎsˆã¦hTü4 q…¸L–È ž-KthÊ29Š2¶óR+S[‰¨öÈd¬ü.‘e[TUtœÉRZ²Lמ=NrÖ=OIö5?ò1ü¾!"šX-wªªSZÖ}Ì©ëâû¾¹ù0N:éPÑ_(çs7I"ç_®Xéÿ{Jð­o,  ¥bdL1ÔOæy~ˆ$ÎdKÅ0­}@SJ¨”C[[‰6nÜǃ¡¡!´µµ±\PÈ«pªõŠ?MÃñ ˜B€H¦´´´Ø_zš¦ÙF…B!¨ª ˲ì+ñå—Þd2É2« ˆ/àX̹ªi6`|Ö>˲‹Å ª*|>t]G €ßï‡av™.EQì^2vd¬¸Gr¹G£hš6þˆ”ÉÖÛ”‹5!vÚ=u;ýwôI À’ð±ó4àLz6K0>‰(ƒû„E‡ø^U NJ|(ÙD–€8¦”s„BÎã==â6¹kPU§3SçÉ<<Ëy‘ü.‘_±˜øÎ0MqfY"Q‰ˆmv–‰âÆyJˆˆJ«VÎ;å=º.~º瑈øý±Ç~C‡ÆÀÀa(Šb_`:#Ý)hYVFÈ´’ó!3bĵ¬ž¯!ÿh@ý³.c2ýAI¬g®¤aˆƒŠåË‹\±ª&¡[¶lA"‘Àðð0<'Ê-“hÔ™0¯Ƀa9i6]×Fáóù …Á`0çò±X ‘H===öÕõÚ/?r×ÇM¿ì¬Âø¬-†«v^KK‹H‰F£‡ÃˆÅböA€Œ ™ñûý‡Ã0M3s²w9wRýýý¹>Lˆ¡š>ˆÄH!BéÇ˶‘H10nBE"v¶*œƒâ …Y‚ñID6?œ‘zœïÅ8%‹HbÈyTÕ9’}jZædŸã™M¥Ô YÒ“¨Tä÷ƒ»ÏI&Ld™g]wþ–å»,ËÍæ.˜½,7Ž.!"šÕ|Þ)ó€3=àìGEìGš›uëâðá¥PÕ¥éûò÷øG£Ñé;VšhðKNßbXw"÷14ˆ¾šIT)ÚÄ{3ÏkÊ šWM—CS3ï+“ªJ¨(É|,41™¨Ö„ N´³?÷òêúP(ŸÏÃ00˜Ó=Þ—š¬…˜k’ùb„Ù“\ÍŒÏÚ … ëº=Âd``ÀNšÄb1tvvæã$ Ú¥Àˆv+D¢CAÆU ãT˜È¬ÛŸ®¡0 ŸëD3äs¢Ñ.ÙWLø ’9WNÏ{^ ŸDdŸÅÒ?Ýß1ˆ„J‡CѨø'“*r4±,Ÿ (c¯§Ê², †a@Ó4(Šb_,!GªÊr¹­­­ö±ÁÊ•+ËRâ™f.y^$GšÈ‘%îÛe {Ms.ð œïŽ@ ³ŠG¯U§j=çêEŸªŠcVw®äóŸ«Vý€UÝXÐreÅ›`08} •‰ D߈‰>Õ7ë ó'1Ì%ÑÇÒ‰Â/˜Ä“©Œ—sÆ´`ü9º.†¾ûýÎ0Vwg·YhÆhòª.¡Bå‰dàVyÕ‘iøÀÎÃÎÑÜÜŒ„B!X–…@ 0©áuåøÂS1Áê@ 'I"šŠHzÌj °kúýþq'H“¥ð ™ó$# )GŠD!’#AˆR\>Œ¿×!v‚ò¥ö@´`ü²3rï(U×ëe“‡Ùíð—=xYYß"¢ª"ˆ!¾3ÝWmkéÛ'y%·iŠ qä¤ÍƒƒN™/‰ŸÕAÖô–Éĉ¦i…BvI EQ ( š››ˆªƒƒƒv¹‹÷¿ÿý8räH¥W‡ªiŠ>˜pXü”£LdB$sÊýõ÷‹ ärŠåJ¼VÛy)ÕUuöMrn?yÌjš&víú-¼ÞµØ»÷?&Üï„B!„ÃaûbTŸÏ7½#yó@ Bô«Ä0ù‹¥ CìÄ¿6ìžÄódé¯É&Ut7ÿJz¹’*>Ÿ˜4 ~í‚Y/"‡Ñ?úè_||L¨ÌRÁ`å*r¤‰‰D ëAìÙ£¢³³Ï=w :;?kO*ßÓÓS±IŸ4-ó½’' ‘HYJñeW—¢<—iš0 Ñhš¦Á0 ;‘RH¢dÏž"f0sï4ý¥¶Æ)&œõ·š~žŽñwü¹¾—äDõ¹vÜ&r'ZÂÀÃíO}]‰ˆjœ€^ÅØïÊIBÉrÊâó¸Ë°²¼ÎôûþH$UUíùP(d<µ, fúê;¿ßEQ‰D iš=Ç™L°È(}«ëzΫ7Üp/^\éÕ§ …ÄwßïŒ.‰DÄy¤¬Kï÷g–ðË.×\­svÑÌ$çé“ûŸHDì› Ã@kk+>úQ?Âᢹyâ ‚ Ã@gggQÓ%ßKÊäFkú±…ôí†xƒ±óVàµ)´M–ž¨ÈÍ,°}ã²+Ü¥> ßÉqUo]ŽÆ¨jÙF˜P™…ÂagòÐJ\Q(;‚-Ë²Ë ¨ªŠ}èSØ·o-š›/F ÀyçááÀÀÀ%Ðu½bÉÑfqâà À7V¬Y4CE£ÑŒ‘'±XÌîð·ËR^Š¢ " áСC…¿ˆÕ¡Á)Í5Ñ~f¼‘’aˆZš“­%Ÿc 稒qõ@$TBÿù|é^¾tÛ#¨âcÝ"š}²J2JNú¬ªb®a8Ç<}RZ†a@UÕ1£H£Ñ¨=ªD^,!G“hš–‘8‘%oåc ‘ëqùÊÒÌŠx×4'9‹ß£Q÷ª*§äcÌ„ ?>DDTMdYI¿_ü”%(1Š7 "Þ‘ù|ãWƒÒuÁ`¦iV&™v<¯BŒT±ÒÿˆŽ^y/çzÇœª*ÊìÈ¿eÙ°©ìÏý2}Aõ%É‹½ !ûtü~ç C×ÅÆ:š>X¹P¯çuÝ£ä2~ýë"6FnL¨ÌB¡ˆ!Ót®2*ÿkŠY MÓ„išðù|èÉš‘Ô²€Õ«S¸õVy•}𛝂e¡¢É˲°ÿq?®À0vç¶øìÞ½,3MŰ, ‘HÄî‰D"vgICCÂá°½ãÏå†?Ü€+¾u…“$‘£@&ƒØ±¥óˆBì„Ç+ß5ÞËû\Ï2whŒ¿ã Bì#pJ‚!Ýž‰Êx†Óëø[UìX}>àšðLºVf0(¾Lš›™P!¢ÙGÇø£ör0 q¾!ç3%½hêÜǺ–e!‹Ù‰yŸ»ì–¼OŽ&QÅ.Û5ѾŸ¨²lWk«ˆ}Uu.¶“;™0™D¥e*#]× š4™ˆh¶2 Qn2u.’ýê±XÌîcÄí±˜ó\ylÖÚÚ EQƇMg™ŸÆïimm ‡X€®QÍ™;±¡ÁfîÞoäڇܔ'b CôÉ>¥ /Ž Š“õÊ%®¿?³­~fߎànˆj)8ýIaˆ*'{,sg7*³XOøœÃ0 (ŠUUÑÜÜŒp8l> ‡Ãhii±Oý~ÿ„'‡bH]F¢e``ìäô¥fš&¢Ñ¨=@®—ßï·¯"¼ë®ûqæ™kîA0´K,õô¨øÈGàȆMŽišöD°Ñh4£$‡{þ“BF,¼c!Öö¯;2 bç«câš–&2wМѹö§!ˆº\tý‰3ë5åÕ ¹(éÇÊ× [âKÀÈñ--â¬Þ²ÄAƒ à{>àÔôpÕ}YFÅ©kHD4›È‘‡jm?8A¡²ËpÊò›º®CO’”GÈßåÕš¦t‘P%/$¢™Å4EuÓtJwƒÎ _Ž2©†aØWP›¦iŸ—°çAÀ¤ Ñ8b1qQ@$¼éM#¥çþŠÚ­H~fwAss3úûûÆŽà …ÄƒA窙HèÁÔ&\/”¼ˆÔ­¿_´GÖç hN‰ôpxrWB¼¦>Õ}KNŸNÌõ~¸“O:€&?ˆff±Ü“Rˉ٠™¨Zè³’óú¶@ôI…„í šS·¸LØ <‹Éx)4vd©.¿ßo'!ä d8†¢(vA˲ÐÙÙ‰þþ~»LÁT&p’¥'ÉÇA,³³Ìº®Ã²,ûjÁh4Š={ö؉÷ q4E?,˲OhM3`u›ö0çw‹/«ä¦¤!G¢¨ªjHñûýèïï·ãcJ(r$ˆ;AÒ‰ñkZê;rD&8š!v„“f%˜~Í\…‰•wjFÈuŒÅÄÁÉ)°Ò>ZL ¹5óéþ~q•…¼ÂÀ±›Mà+&rÎØÆ«z‰h¶ÊsL ‰¯by~0™2YvË0 ;Y"ç,€ÖÖV;yÒÓÓƒ@ 0½–¥†3ÒDöa47‹C¨p؉ÖÓ#~g"ez¸G©ÉyÜåü؉y^ÐÐÐ`'_åã ðÏ®¿þúJ¯QÅÈ}œe9•¡¤ÿ¿½wª¼öÿ?Ü’pK²# ¢¸¹¨”‰·p”Z& *ØR'±žz9Êäœ_m±§Ñ™—¼ÐÖΔ|[©m5“zÀª2J{´6c­ Q‘­“*£0rG6ÀpòûcÏÚ{ÏdnÉÜö$ëÍ+¯™=³Ÿg?Ïz.k­g-«UyoìØ“øö·GÂf³Áét¢ºÚ…–0E½ hv §N¹›C¨«S.Öç¡u@sb"e~*—äTîr)?dП¸?µ`y* W¢…à gŒYYDôta@ÉÕ-Ÿ‹€É tSj);bzÂãŠ&V¼7 ”)CÇíÙ Ât„20¸\.5DÓéT7”´¨s8p8hllŒ‹9O«UѻƓoJÔMF}H§Ó©žðz½hnn†Ãá€$Ip:!ƒô;¼Ìúý1å}©®®æE-’!}ÿliiIÒEŠòz#”‰Þ‹ÐZ€–´^ßü]ü2ÈX‘ÐÅC†ý‘KŸO™ õ­xdY)P€2G䌦¡GC­,›—Œ5+–׿f0 Ã0¡x½Z‚NGù[”!3<@@–eõGÕ駪ªªÛkäŒCkI 4‰“c!1ÀãÑòèq»•×$I¹F– •¬¼OyPˆL„yîkPî"’{;È)O†REQ ß@}_Eõ³²‹¢;Ðg›››Õ¨ZXim¡¾¿>ÿüó³ýX†a²9Šš¡«K™ÉAH–eŒS…+ZàñxPQQ¡¨Ã ? ¸cG˜WiðDrȉÊ9BC³ŠþC@ò'U|>ea.¿ÈnW&uÊ…’› è* èbÙ(Ì®7¨x<Ú¢ÃbQt4ú÷}ž’jhñ,É«"V9,PòŸøÜ*G\€¨ó” \.eÐØ¨e~û”Éù1rÌO ÄàAž!‹mÛ„×$ f@õnll„Ëå‚ÝnWà Òõÿb2¡ú£ð–Û­æ=¢ß~øa¦»Ã0LòHP Ùt ±Ê8n†2!~{¡nà<e/D UŠ´èriû±\ÖבrS?‡ÐIP³Ùâ9n³ÙT£Šþd¨Û­Ä 0µzt†É’¤yÙ ‚Æ‹üÚdY9m”boÓ¦Èá›û£O 9ÚúÓh$çÔPÐÔiÊ®1›ÍjnP;ía†1 ‡–ÿÄfÓÒˆ¼öÚ;öø|JˆÄxx½^ØívmÞ$åËÍæØ9H ཰Œñ6h†WðïD^¯¢_ѯC½YÛ÷ š.ÈüiѽG|Ý؃ÒkšÍÊ‚Dÿzãtd þXƒ *i‚6²™Ü°ê‹–Ëëõª›H2646Fuõå---Aï›±°X6elCIeõz½p¹\p:X¶ìeOdzÏ> «ÕŠÆÆFˆ¢¨æ4´1N/×údŸ‰BH‰`,'þ±à°2Àø|ŠòØbÕjUŸ5ÓÿÐË…™3›Í°X,Ø´iNþè$ÆTŽÑ&;”‰±ÊdÞýÂOšèÇh!¼,5¬DšœÂcZZ\ëf¹5`Õmƒž°X”Ïa„¾wh0Ð x¼Ý“„Y­ÚÎ_3xãàÆ”Bz<5‡ŒÍfƒ×ë ñÞ¿`ú,EQ„Óé„(аZ­ê˜(rOFâOžxÇÇŽíæY,Ë2¶oßžá^Á0 “ÃO ׌àz§8š7¢„m$§²ê åoÊBÎb¹‘BëèCf’2”ŒçŽËb±¨¹LâPÔÏ‚ °1…1^¯f4¡}¤~iC¡úôBÿ8‰By<%I‹uK¡œ)¬. t‚„öyb‹  X‹åDÈÆ†éŸÐú€zÒUR^Çã xï½÷0qâÄl½ÏC‡8(JUuµ2®_Ÿ“ikÂ'=²¤d,‡ªç‹É}"ð¹ûë´”ô@É«ByLdŸvºƒ¼œô÷hlDZ!'[Ò5‘ƒ–ˆî'Ûã“zK4¦lPI+uuŠ×P&¹²,‡Ä~¦PVV«µÛ&±ªªV«’ÿD¿‰œ0A€ÓiF*ö”4ѵºº‹^¯WMün±X`6›Õ8…‚`Å_þr¿þõ¼E¯~ÓÛܬŒuúÄ‹½Áf³¡Ž\¼á®»‚Î}ÝÞzýõ×QUU•üCcr†py9,Þnt?Qb…æ%>wF;Š ‚ Ø$` €7eà#ø¡!V™êjM£Fg`iB´8àW"PìW ʤîõ*?F?‘þ¥¹›°‘‘Ü.¬V«j(©««ÃówÞ‰mK–àK݆•Æ%2tÛ¨šÍh„âeèp8Ô1,|³«#&Mš\w]÷G&9rdÚûÃò ×Èš’{<Ú)o½—´Ù¬}—á 7v»j7…Å¢…Õ5›•QÔÂíÚíÊ~B–#ÎAWWA¶qiDw£Iœ5Ë¥<ç;”6Î%¤”5#Í14g‚‡Ã‹Å»Ý®*VÃ׸œÓ$5|ñÅÙ.B¿€ÆK}ŽJ éÔI_†Œ zƒ IH‰év»Õq‚N˜c>zAOàð° c<Èx¡7ŽêÇ ·G† }ÈgZOPž"+ôWrȈ7fPÈ?—Ëòw¸A…¾§´´@ Û¯ÏC¾œ¤p:íÛ·ãé§óátÚrj¯¨¨Ðô7’¤üP¨­xÔ8(Gß E¯ã‚bXí&cîz½‰)1#„ðMºí&(Nºã¾Ê¼ŽîlPIú~éǬOàñxT%f"±Ÿ­VDœ¡3LÂCq…Ï|ª$1ôNNô¼ißàp8àt:Õç"BÃòöä³ï^Е•ò"ŠÀ¹GÏä‹Ha5õ‹pAPõ>á'ÈdYVCqêÑÞ BÝçx:iFNº4oé÷¡‚  1¸¦¬äDœ Z[[ÑÚÚš‘{õgä0[†Å"á·¿ý1æÎ}!®JÀ ¢7¢ ‰É÷t: YÖ6g‡ÌjÕ +r³2~OМà?VžÜT`v‚†é5lPI#N§²©-)Q¼“Çõ!¼íX¡,˰X,j¨ƒDp8ºGí´\GuuJYÃK÷ëHÁJ9 \AÏôêêj466ªÉŸHî¹mLŠ™DÙ´IS@‘‚(Ý«RW1þóòù”‡ÑÒ¢zévÃãuõj쮬L¼àŒ!¨«Kìt¥ÃáPÃö ËÃ^D¡P¨lvÜP&!sðG’´^´h§S(V¹vÓO£ lR`.··Š‘iq&úpô¨×Á‡À¼I8ðË=øÀX­ÊLM!øhQ«÷þQn¯T²  4…J¸¢+ÄP©wéúp “IÈ3˜–(N/…¸4ƒƒÙ¬¥ ¢Sd˜Ï°poW¢ì¹\ÊwSRpòJ¶X´ùLZÈuKœwâ Àý NQ>C¡/-Í«™Æ3»0KP1Ví5"Ò<©ßSDYýkVÊxG ý°4ôýêwú‹jN'ˆ@É-ûñ·Ï:²ÝÔ¹YÈôãa°sJ­'áþèxwO…å¦üÐy¼dÈn|¦“‰zÂ=Ó($$YkhþŠ9м¢½£Ÿ7bEú{(.òžÕ'ƦçHÊ'Y–ñÉ«¯âØ–-˜qóÍx襗ÔübN§‡ª²Ëív«¡4)T…M‡ƒ‰9î¸ãŽlWߨTCÇJÀ•®0+Êr3”о0¹` Ê =/`½n%\â¸NØ/] ˆ"Dý@ü© ØÃ¬‚¨ ÀdÄñû€’0m‹`ÑÖ€ %à¨Nó4LD³vÍ(ÑÝgrPÎõ¡@è»Bîõ;ÞØòF–ŒÄÁw¢àl±GŽÁ+?}³Šgaïн}õh Ü;¥¥¥êϯ­¿Æ7†àô;§Qs_2ŸHМ‘|Pæ0*ÞxD?µgAôpˆú×ÄàßbŒk„ÜGö@IPÜÓ2Òiöð24Ÿ¼ú ¾\ÿ%˜ 7~Ý•””P:üÿzDÝç"]c¾O÷‘ѽ ãÝ'¼|Ñî#鮿|6ð3ŒÚ9 {÷îÅžÒ=8ïùØSºC÷ÅÁmÑÞÙ8\|%GJðöÇocäW#Q^^ŽÏ>ø ÇüǰaèÀ­Å·bÛÈmøæøo¢åÔ––âÔ¸S8\¬Ìc÷ÅG}„iwNô3Ó`±X0æË1„“cOâ¢â‹°yç¥]M>õIDATfÌ5ÍEéŒRˆC …$“ú¿ÃóFÐøãÓÞ·8ƒé9ÛÜ‹f¶è¾aÿ§5­ÞØL†ÍHÏ;üÙë^|”Õ«é†lzª««ñ§?5£ªjTÌÏú|>\3lîܸƒ’õ<Ò¯—«ª´Ðéá &÷i. Ü¶ä|Kc~ør7Ý&%°Ä§³YQ*¸\=?=¥ÏË@‚“BzõYŽÓ©(¾óCX°`8þþ÷Ûñýïß®Zr«ªªàt:!I®:ï<üûÉ“È5t|>eñHGtÈ#·'úW½¡ÃåÒ +ñž5yCF¤ºZ‹QÔBE3.Áé„gÔ(°9%øÑ=”V8´¨Õ·›üñž5€s? ü9ìcÁéV@E477ãË;¾Dñ‹1|Áðî÷r@9úùi50× LUO4X­æÈVLË×Àa|€| ¨®Š~y$¼^Êæ 1v’G*…ÜÓ{ú¹fž|b;€UÃ,…äŠuz+“öÆtÇe …›"éqõ§9ºá†æ½ÞØlVãôšÕª%ú¥y²¥E™W( Vuµr‹ NÀvàÙ Xn¼²fÔ “¤Ãö®Ä<Àz-`•s€Ó€¼p­6µG˜&ÎøÚbÚ 4Wê)_«”>·á™ °Z¿ÚqšÍÁçá…BUáÆ”*(cšç³ Úæ3\Þ+‚¯QbtWðZgðžÁïÚØŒi×MCÛKmùîH}Q„Cg¡tF)¶ØŠÁþÁù³‘=stFûVNáv+ )NgHç÷>»Þw.†ÿ%äÀ lºÕ ᱇B¿C¯¬oáÐQ(Šù Ú½Š" Kä.Ë2A£‹ÅbQóeQ}®þZ‡N‡‡.HèYÙív<û£aÆ×¾†U«Váî_þßþña³Ùàóù°ïÙgQöÁ8f Α$|õÕWØ´p!£F©ß}ÿÎ8zìÆ>ôþßÿþ/ÊfÎT=/)ïͧ–`¢÷…à3' {3êñ&ƒpñ–‹ƒ‰ì ƒÂ7 aÎ$AƒfE• Îg’päÂá°M~R›@ôtÉÝ `C¿÷pØ5zƒ ’€Ã:L±¨TTÅ­¬}‡$]à[öµ³Þ©OïeNF=òZ7›ÍoÐþþÓÏÿ¯z€ÁÿG ob‰ò=bœkÙ[¦à>’ yÄëR’$Ál1«ã¦OVœ–***”=µKRÃåêOëOƒÃ«=ów¶¾“@…ú)B••öàk>h{Çð“]zEºá}@S°G»†^“ýdW¤ûÐI$º•Oè~Ÿ'NàÏÿŒ+V_ü1ùØ1}m<„áû‡£  %Ÿ– ³³}wm¿ §GœÆêI«q×ö»0#QXXˆ”`Ìõc°sçN|ãà7˜À>ôŸøªþ+à=`äÈ‘br’NM(½ÀIA•zMaðY‡Ÿª ®9gzf*ï-Â5‘î#Å¸Æ eíéê~5t‘5ì}Ÿg¬û„Îá;ôŸ#ù;Xp{FÎkÛt¾\¥qSI% »dиáFá¡CõÔS˜ÑÙ‰A/¿œ\\ÜpCGssâzOZbx›d(º$ÚéÇÆÐ°A%MèOCÚíŠ"f„P%H$$I‚ËåRLV«UUt¦)‚Ç0©«« 9þÇ¥Á‰O£nÞ#¤KUÃ7õ+Œ]²VJÞ^6Z<+Þ´?kÒPìvŠÿi’´‘Ô•=Ú©&ÈÐÀ·pü(Á“SNå3’OKe-:m´Ün7l6~ó›·qúô·píµkðæ›7…ä7‘$IU¨èq8€šÀjµ'œÐÔãQônVkÏc{“G=“ãø È› Ý•íô~¼õ¤>¤“€oŸÒŸ(d…—ª®Ìå€å&m>¥0TÍÍZ8MIð <xßd?à=ø@ã ¥ßéä`ïvι€å$àûk€æ @œ¬[°ú“;lÊkÒ!@~°}LÐbäJ€Ó|>eŒ<’¡ ›%œwì<|ðÄ«8ü‡»ðþ ïãTk9ò>ÏÃG÷|„sw‹¼§òðêï^…ÏåSæf‡27[Eåè¸ ‚[¹oà¶&þ×DȱõôV\µå*¥]v@Ù8VÇn?†!wAþ÷ò±û­ÝûìXì]¶ÅÅØÿø~,+Ày `m<„a7ÃÛ§ÞÆ7‡`ÒS“prìI¸E7îß|?¶]¶ ­óZñÜsÏáTË)>|3fÌÀó·=[ÆÝ‚éïLǬßÌBgA'îÇý¸ýØíøÙП¡éH&Nœˆ‚w °k×. 0Æ Ãe[/Ã`Oøp†Ÿ:¥tØ(‰ø|>7Ýäf `·À%Ý¿(^ˆÅ£GQ&ª`8( ÑEN3tjB¹Ä©Æ2ß±cGŸ:YH§B( ­Ï=DQÄGÏ>‹_ûÞÿ}À¹ƒã¹S§ Š"¼^/š››Qxï½(>ãwï†÷¿€$I°Z­Esç¢zÐ GŽ@¼ür –åГÝdY€GDút·t¼Ün”ýö·ÀÌ™ÚtB6¬MCÈúÓ¤ÕÕlP‰ÃSÎü#z¢LÝó”eÀ'Þ5?V;<ù&¢Ñ”ˆZŒ¶¤SKrÐR2aÞþéOá÷xÔœt’‰~·´´ÀëõªN:}ÉHJáðô¡Ž(w92êß»Ýn5Bƒ-hd ‰$HÕ’š¯òAjÇŽêZ]:Íf³š7 PÖò6›-¤L~¿?Û˸¸ÔyâàØ)Z•0Ë„~<¤8«¢M[«ù|蓜DIÜÜÁ!ŠÊwè§Üðq×bQ¢Ð}¼^ìÛ÷,Nœ8}[•Px?q%: ÛäÃMOïÆÐ½{QPP€'Nà‹¢"n» ›-›%Ž`^Á>\¬ä£+¾¬ƒgÏÆ3ßzF»­€7,$´Ó sÐjZ‚¥>Uaõ1Û4¥/)W,мŽè™´hõ9¸ÐV¯Ñåñ‚G¾%mN ¿,syFxöú²Xta«icª¿Û ˜u÷ºßG’AYÂbQTúúX}Z<[IÒêÝ}¬ñþ:6lö±¿g}–‰ …¦°Ã¤·eÕÕÕEQuÞ(û0ªA"°3€ùoÏÇHág8ný9†Zª#‡eï áSkoçBŠr„ž¢"qL0ú“=Ø ’&ôk\AДñ«\}pGZHI’¤†ÍJ5‡%%Õ(>"ã“'¶á[·ââóÎCq‡r£±±‚ `‡Ó ¸\ŠüvV‚€ÁÖfx<e>mÑ6/ª³£/ÌåêIñ‡&5² è6…ÉãòÁá,†yR–ÛFÁûÎ5¬ŠðëG ¼üÍíØj Ý´p.càBhúF „(pœN§²ƒ6[ßùÎx”—…… ¯WKÊ+_‰Å¢xä“ór¼ô+€f°¬¨Pþ‹æ½^²Y†Å+Ç *†àBˆ¡@5rº (óEnÀ}ðm,ßSú›µòW€80ߤ̋N' -„MJh¬F2þ[ï“@µhyMy©¢BÑ;Á½Y! ^Èy8`X¾ø^PŒ$¸ç…é–ÝVö¶¨0n…²§0|ú8ðd(iÙ‡ªD,[¶7[ oóÅÛ|î?çâ£Ï>Â¥Ÿ\ŠÎ?w¶º·ª!ô\.±}üvx/¼’yÿ‘‡W^yìºÓ6NC^}žª”ñx‚Ç} λ8»ê,^¸áø¿ïWÂ÷U{a·Ûñâm/¢H(ÂËã_Fù‘rø¼>Ü6û6L¼k"ÞÊ ?¹ú'˜—í¦ñÀ 1½J(Êž>Œr¦Jh,¦|xú@ËU@ÝwÞzß}j΃hеF¿ÃEëô>½NO:񯯬†Ç#Ǫª*4ÇäðH¹@Éð!Š"6mÚ¤>Wzn‘’VGD’ Ê2œÁ˜¡VYî&ïáÏYäååÅÿîþŠèš=Úñæð¾l³…æ‘ ïǑ‡·¥>á,)ÓÃØk2áý÷ßDZcÇpôèQ¼ÿÀ8äv«'OoÝŠY]„ÒÒRŒœ4 “&MÂ7&OÆé#åL¯=¦˜²úñš×é=‚Ÿ×ž‡¨ËŽT_}d9Ô+XèYDŠ5Mº•hHRì÷õ¡Tè»ÂïCƒ«þ_,ÏÅHå”#œŒöÙXå¥k¨n¢”—Çÿ^&1‚§ô)¢åxôù€ /|uuOÁb±Àn³+ûºàÞ“N;úl>uMÛüY3àûòÉ^ê‚¢["ã‹9ìw"eK´÷dIN0 «««+Û…H†ÚÚZ,_¾<ÛÅèF¸U–eE!"Ëðz|ôÑXœ=» W_}7®¹æ#Ì›wzmR TŸ»øC 7{ñEœo2añ!ê18¿ÿÿj*.êBÞ‡¢dÂea~4=†Ë:)F½^e>r:µùÏjÕ}l„ž» û ä¾`ùì÷°Œß®MèVk¨wU]–ñ–âë7ð¶ø Djs¾÷Ú2õ+ɰBë ›M)Žþ±‡ï_«b„`jhh@ee%*9J””­¾¾¾çöB9]² ʤFafš¡L|´nr(¯Wµ–€}º+y%ås’$Áãñ@’$lØð0¾ùÍ÷°fÍ=°œ—¿·ÁdœúLѪÉ ¸V|iç(´L·Cº·{ÿ ƒÂØQ{ý¥RÌãñ¨ÇùeYÆ€pÕUcË–óðÇ?^ ·ûæÍóq‘C©Ù¬(›ã„{§Ë¥\KkÀxÆŽªªÐ¿[ZËÝRW§Ô=Ñ“0”àÚåRt;É ‰F#²M¯ž 97A‘ÉÐBRI€ïÿ÷HÀ:¨þ Ÿ¬%€í( ¼B+´²UP<Á|PeY=if »/%Èo9`™ -¾:-ŠƒûYò$—e£+GcðàÁÈŸš¯… ƒvâƒs>Àºmë0eÊ RÌx½^<öØcøùÏŽ•+W" ³³ÇGgg'ªªªðÄOà–KnÁˆ#ðê™W±gÏ :#FŒÀ±cÇTÅ—$I!¶‹çœsŠ‹‹qÑE©×tKÜ-wMú‘6ø ’ÔÑlj%ŸUUÝô}N> ÝEýÞn·«}!ªb•œfÒlD¡²éeC–eœøç?ñÞªU¨©©Áš5kPQW‡ïÜuár¹àEýõ¯())A @II ^­¯W ’ÁºßÚØˆÁ“'£ð •›…{üë•9½ˆHqg0åsŠph޹ú°|zÇ[Ž^“s¤cmË'TÒ€,ËX½z,–!“-)6ìv³rTúKáþÓ¹xüñ+°f¦ ;tBàõ×ñúSOaæˆ8òÚksÓMø—õëÑØØˆºº:üòÆ1@0jèPÌþy@‹n5/Ë€÷ꙸ9–—Tœ‡~¿)ËÚIÒâÍ `mnõH'wbºG˜ˆÍ[&#Æk7 §±1¶÷œÕÚM±#pÎ ½,<\í™éuR‚K’¢+ˆçœÀ¤}²wj#ýIý:´1hW£0>²ö¶ÏçÃ[ùoáµ=¯áŸÿĬ®.LŸ>ÿóýïã²MSñ—{:áº&(@<ó ˆž–`ø0Q3¨ˆÊýe/ ~0ÖïDÝÊF´´ íVt}¬t‡Ã·Þú|¾%¸ñÆ«qï½Óðúë2¦Lù?tÂjµªJNY–ÕS%0n°`ð¯ÿ x<Ã1vlh¾ î÷ÕÄ…Â'Ñ"Úg¼^Eæ(œb"8Ç©~&û&pbÝK_®x¹ê%I åN'úQJе”DœItRËÕÈ)_¸¿˜7îNåy»OÖo* Ñ7Ýȵ€ø (†Œ?B1~ü»î{(‹V+phÚ!l¾b3t?¡iGH…¡ÏlÀÒ5­øÁ@XŽZðËþûØ÷Þ{'NÄÎ;QZZŠööv\wáuèØýÛ÷cðmƒqÑá‹PönÞ<þ&Î|.®¼òJ¬Zµ {÷î…$IhkkÃÙ³gpÁ`ìØ±hooGuu5ö\»âN7ÝtÖ­›þð‡jÈ”»îº ‚ ??TxwБò&PØ +b±X°m›r:Äãñ¨!?Éóõ™gžÇãÁ…^¨zµ“BÈçó©ã‡,˸wbâÀ(úâ -äyh.¬$`@ˆÛ´™ UU!N Ý@RX¸†D’³1)#Š3lLh-ªÆïž˜¢>¨?ñ˜0G/¡2k Ô©ÿ»Ýn8­Vü~éR|óÑGU%©×ëÅm›7ãÔþý(9rD1ˆœ{.Üóç«å^— ?9}cÇŒ IJºŸâb´´´@Ee ¡‰ÀlFI°n4-¨ ­xŠ­Tháx2ê“PÎ-ʱHvgÚõ4'd4ô†ý‰1RÒ’Á€NõJ–S€>ç9P9õ!´¨ã©®®9}íõzÕ0{”ê(‚Qáða%)6­ZZZàóù0ü[ßÂèÑ£éfZ*B’´EŒ`ÆŒîÃxòŸÈɯxòo 2›£;'2‘D+ª-š“§ (Ëšhú¢¡uI¹ÁôaîAPC³ÅÌÍÚ‡Â!‡&êX ?ªwG9Äè3úµ1É?=W¯×«î›é³V«Um·Û†ÖÚô=´ÿ­ÿ Õ>kµZ#~†ÊAåÒÖb±àé§ŸÆe—]–í¦Ê]$¨¡“]Ó›@µÁmê—_â–qßÅm·NÇC?ü•¢/jjÚëµ`Ô °ñÞ{qõ”)°ìØ_èižÖÕáC»Î©OÔÀvQ&ˆá *~¿~¿eee(++ËvqBïåGk×±‡°ú0íÎ;ÑÒÒ¢L&äeL2*šÍp:p>fVBiÝ»®ÿo4 ð_ÅÍxsßXlsŽœlÅÌ™3±fÍãxáb?võ7܀Φß|36=ö„Æ\δPEmÍH ²Ý²²¬Ø?êêYv¢¹9R4¸¾ʆƒBs:3“öºL´ÜúN¤cøú÷9L‘BÚäÓÅC&3+Ž)I€üéœù|9iªÆÛ÷>†¯Ÿ~/Ï(€ÅbÁÃxX™gƒrç[· béå€(Â4œ9€ ÜY¾ZŸÖ‡2ä<ÜPw^x·@ÂìÙ磠 € wßý¯êÆ”¦sæÜŽóÕH Ç…°X¦©FÓHú|°MÅåÒ áë2hv»ÊKï™™EUÐúßbQ†'ý÷Ûí¡†2.#¨{T·[ù›N¬Ð÷Z˜/ 1F{[:1æói÷¡ú˜ÍÊwÚíÁ0¸Ág`±DW$:Êw‘®¸¹¹ÿé±Ò"Ÿ.¨Ç¡åfÍÙÒ{0ÜÓ‚ã¿3Td…àÏþÇ÷ãÃ)f¨IU¨‰m}’‚¤lÌÌ3Ö¯_ŸÏ‡aÆaýúõøÇ?þÓ§OãСCeyyy7n®¹æ¾ü0ÞÚý Ê PW}7CŒ~#÷ÄOà†nPîéóá)ËSÝ®¥ ’~S\UU…¹sçâ±àAOåów.Å9çt÷™á‡ bA'JHyK2Lóþ¤˜%8Þ›SÜ·iîóù|÷öÛøüê«CÖ¿ä`µZÕ°W.—K çt:µ9=Xvr¢Ó˜úÿ“A…ö­;‚rh >X’sú›ä?Öø%Š"°eKì 'O†žÊ'íôbBN]‘šU/ÜhI†¼dsƒéspÑzQohЇáÓ;ÄRâ“Ì ‚ #i/ZWW§þMQ¨>$£.— ÍÍͪ WWW£¥¥%âgIõ!¨ív{·q€ÊFŸÕSé=¯×«Žá¯ëëI÷Ó·]KíCŸ¡òÑúFoÐ¥1”ÆOºÖb±„œ ¢öÐÿ­ÿ ýÖߟœšô§â***púôé4K…1H˾3¨òÝ·¶³C0iÊq|øú(üíkÃñÇÑhiĘÕ_/Ô—É€¨ôaµ]ÌfØR­e= C…üZµjP^^޶¶6Ô××£¦¦&æg2ÎEï$ImÞŒwÀ9'ªõ‚?Æ”ãÇŸîüÀvÏ0uæ–e€7Þx§GŒ™Xi²ñx<øÝüùX³f jò¼÷Å0›-X¹ò”––âÀ%ˆ×«èMœN-ßEàhiÑÞ'e"9šÍ¡!¯Ò˼††&ô {E&|ê"Èív㥗Dgç˘9s&^zéKÔ×âÅ—â®»¾ƒAƒ6ão»¥¥í˜:u7DQD[Ûn|üñ-x÷Ý‘˜4i,–î'ýINÃq8Ìu¢HïI§9Âq»5ã‚^–i­©¿EÛ£qtSt:E8Jyiõ3´‹Š|uîÒ@ª„±¡aÍè¨÷œ Wšá6€{÷î̘1n·‹L&¼ùàƒ˜9s&>Z³‡ƒS¦`öìÙø‘#1rÛ6Œ_¹ûóŒüê+ »ç­"dቚÔK‡þT…²JFPôû|>œ·e F¼óNègô§?}IÂn”¨®Ö¬…TÞh1}G.*„õ¡Ih°Ò?SJb6cw~>^7 þól—:­ôvm{üørq_s>ñù”î§÷ž%Ù#å^ù½w(€oMýÿÉ+´±±Qõ,Ýrã({î9UÉqüóÏQvà¦OŸ®|y?4žå<>àõ¢éÓOaš;—×¶aô&œ‹^VÅ€AòªÁ¥Wð%Šþd)õôy9ÉÉþ[’$ÜÚØˆ‚§7èyl[,–È¡!C úwø@I§õPÒi‚Â`é½…Â (¿A ]ݼßúK8Û^¯mà½Ðo{GEgg'† ¹€×_ßaÆ¡­m*NŸV®{ÿýüîwñÜs—`÷îÝX¶l(-êDgg)Μ9ƒ .ø yy¢¨è ìØ1GÅw¿» ?~ Ìf`ûöí˜8q"¦N}wàùç¿Â¼yáàÁƒØµëJ ::t(&MZÏ?ÿWìÞ½/¼0µµûQRR‚ ¤¤'v`òäÁø¿ÿSòç<ðÀQ<òÈP”””¨õ¤ýœ^D’ rtEÍqM‰,‰2%×CáÒÉoЮ§¡Áj M&œZB|}hO „¦yÑ—E¯/Ò_OÓ]´²êËGÃEø}ÂSÌhº‚È×D++¼ür;×±xñݽéò9CJô¶têÃådŠð\ÿ¸q|_]€Ÿ_µoýãÿáÔ-·@üÏUWaÄŠ?;|ÀljvFrb˜x¤Cok(ƒÊå—_ŽeË–¡²²ííí˜<ÞËâiµZáq{§Xëgß8w^߯'Á›¯ æò†· m@p ÂÀ£°å¯^üðàëÌ¿¼×ÙqæÌt¡ _uàÔøp1Jw~ {ý§Çü ×~6ù_íÄ™¡08¿Âÿ»Ÿ½Ð9¥þ ùÀ9£ÎÁO?97¯ÎÇ¢ÎEøéW?ÅgŸ}†Ã÷ÆÔ§§bäÈ‘jù ï,œxæT @~e>Âr·jJg@qÆ«z¬$ýõuR'(oÉm@ã÷‚ßãèá}(1o]ðõÐb BûÜ¡‡0jç(%î Myžè}Ìaåkk?ì>êçô÷ÑëŸlО¥%x½~¦dOt¾\:„Q·Ò>G1Ãö Mš`škêó›ÎžÊ§×ëÅ[o½…G:îžó}ÀY X×¢(qiïD^×^/ª†ü-3 ¯½{÷îÅš5'!½>ÃdsóVàØ€OqäÜsqÚt>Æ}­ååóððåش $M)´~ý üýïÇõ×_ŽG=ƒ®®b\pÁ6Œý9¸\ð.æÏ?¤†Ü"o9R,ýèG'1mZ!|àºëaçÎQ°Û#ï×h‘æñh)(bX¼ù=|ßh³Eÿ Ò o²¬]›Èþ{ƽ¸ùæ1()AÐö§dÔ¤Ÿp=nxˆ—è©|Z­Vxøæüò‰ ðÎ…|¥¾AãÕMžŸ||,A{7åùmxî’KЖŸ¯*ˆn5 5.9u î¹ëo¾YU¾Þxü8àñ`è‰dyÀ›Íf¸\.5ñrKK‹š—€Â_èC HÊÞï÷£¨¨………Ùn†¤é+ò·M‚cîÎÕ«±{Å ^ۆˠ¢7œèó›è=ÝI^é¤Føo½3’ç9…Çr8Úª [C‘EïMNÄ>MÆ:>¬Ÿ i‘§'ÜÐáÛ\FÊK¤OtM©ÏÓ)©xèCÇÁwßEÁŒyÁéê&#Ñq潋.ÂåŸ~ší⦞Êg¸Â–N5s÷îݸþúë±yófÜyçX¿~}ÈœIrHFD»Ý®Ê %“M•ŽP_q×Q½€|‡â1tcŸ~iíñ(ÿ§kÉÑnåÊC¸ÿþQ½2ÜèI¯'hÏG{—h†½¯Rø}È‘êFC žÛo?†'Ÿ<‹Â˜†›§ŸÞqã^ÁϾ0emgDz»¶]¾|¹¢WûŽÞ¶=Àƒ‹!ŸžëÀëSöüÿû¿~¬]û[x<477«ëÐU â¢éÓñÔæÍ!'‡RujÓèkÖtŒ ©Æèkå>mPimmŃ>¨zïÀüùóQSSÓÚ9kú,\ßö]¸»n‚P<æ+Ï`Úeïb×Ù³èê*Æ€Gp啃ñì³'ÑÙÙ‰Ï?ÏC^ÞhìÙ³ _~ù Ž?Žñãbÿþ%6ì$Fމª¯;ƒgÞ9€™3k±qãJüà7á¿ÿûÔÔÔ`ëÖ­(**µ×~Œ7ßœ‚ââbLž¼ %%xç3f JK÷ÀnO|‚íK§Ræ5C† º1 BQÊS’(Šï¯Ç ÍP£¿ž ÈtMØ}–.]Š{Ÿ¸7î}~óöo0}Öô>ÑvÑè|þþ÷¿Ç¨ŸµcëÞRÈ—\ L¸M{QpÑaüéO“qìØ1ä彉/¾(Â_áðábœ={çŸ:„ &àÌ™3¸ì²Ëðé§%1â¿1räóÈÏŸŠ¿þu<þ;®ºêbœ>½÷Þûuu³IG¤Iy´eË1\zi$I3Dôä$¿,·Ý¶>zoÌŸvª%R»Þzë}xá…_¤ï¡€ÞÈçW\{w}Ž/ÿ\:Ë£¦æ3¬_߉ÿ†?ŽÃ‡ãàÁç1yòd ìèÀ¬âbøÏ;CÏ?S§N…$I¸Ô(¸Ýn,X²?yî9,Z¶Lõ†U7›”ô! ÇûRòǾâqšh›ô¥¶‹UÇÞ¬mkkkQVV†@ €·ß~{÷îÅøñãqî¹çbÊ”)8tèl6[7s’=}X !áƒ2 ¯mG¢mÒ—Ú.½‘ÏÖÖVüå/Aqq1>Œ¶¶6ìÞ½»víRetêÔ©˜>}:ÚÛÛÕP6ú$êár«7„’Ñ%üdH:èo}:H´M–Þpî%G’>Joä³¶¶W\qÞ}÷]üõ¯ÅÀa±X°nÝ:<ÿüóxâ‰'BæJ’³pƒd¶éK룾2ÎðÚ6´Ž½]ÛÞýé¿ÂõÖ)ÈÂdl>ÿõý-hl¼ùùmèì|yy£1hÐfØl6|öÙg¸ãŽ;TGªsB:0ú\’ }ËèòÞ§ *MMMhmm i€ÚÚZ˜L¦˜æÒK/ÅÙ¶Û±Wx§N}ŒÁƒ㫯¾B^^ŠŠŠpêÔ)Œ1‡FYYdYƸqãpàÀ”——ãÔ©SÈËËéS§yyÊ1Jý)’LpäÈs2ä6û÷ï×’æ0‰Ô£½½§NÂ’%K0oÞ¼l9môF>yäüñ‰W±çÐu4b+޼¼)Ü((¸gÎ|A1pà98yrÎ=÷\äå}ˆ²²ضm.¹äå”ШQêo’ÏLÓWútgŽ;†;wbÀ€x÷Ýw³]Ü´Òù¼êª«ðiÛTÎlDAÁœ:u £GÆÁƒqùå—ã“O>Ayy9vïÞÒÒR;v çœsŽúù¼¼<äççgM&‰'Nàĉ(..Îj9RA_gi“ýû÷cÿþý˜>}:ššš²]ä´ÑÛµmEEÚÚÚ0eÊäç磸¸#GŽT׬F½DèOsN®H›ðÚ6º|¾ôÒK¸çž{pðàA\z饨»w/¦OŸŽmÛ¶¡´´´›lfz?ÙúSŸÎ]Ûž={6+¹S3IoäsÖ¬YøðÃQPP€¯ýëèêê Y»æ ¼¶5¼¶ÕHfm{¾ô?Ø–¿»‡üƒÆ Aƒ0pà@œþù8qâÊË˱mÛ6˜ÍfìÙ³'£ú£Ï%¹0.YÞwî܉ǧ|mk˜¤ôÝ^Kä8Ó5ñœ#îµ ÃôŽÞÈçC=„‡z(Â;?Èvu¦OÑù|'<'Ã0)§·kÛ¾®(c#Ðùœ7o^Ÿ621ŒQè|¾öÚkÙ.6Ãôy’_Û~ @c¶«Á0)a`¶ @u{Íï÷g»X Àå“aŒ Ë'ÖM†1.,Ÿ c\X>Ƙ°l2Œ†a *&“©› =éÃôX>Ƹ°|2Œ1aÙdãÂòÉ0Æ…å“aŒ Ë&ÃhÆ RYY‰ŽŽ´¶¶Pâ÷úý~Ì™3'ÛEc˜~Ë'ÖO†1&,› c\X>Ƹ°|2Œ1aÙd ÃäP€úúz,Z´åååhkkC}}= ³],†aÀòÉ0F†å“aŒ Ë&ÖO†1.,Ÿ cLX6Fa@WWWW¶ ¡Çï÷Ãï÷£¬¬Œ1ŒÁ`ùdãÂòÉ0Æ„e“aŒ Ë'ÖO†1&,› c@ƒ Ã0 Ã0 Ã0 Ã0 Ã0 Ã0ŒÑ0L†a†a†a†a†a†a£Â†a†a†a†a†a†a˜8°A…a†a†a†a†a†a&ƒ~øá‡³]ˆÞâ÷ûÑÞÞ(**Êvqb–‘’6ùý~!???ázd»ž@èqÙŒX¯HuI¶²Ý>F$WžI_hûhò™¬üeºnñê­ŒV\ WžI®·}oçÎxï÷•¹3[ua’§½½)këL÷º_ Àyç—Ò²f¢.‰Ì—‘ÄæR1½#’l¹Õö±äÓèkÛDæýÞÈg¶ëŤ†Þȧ‘Ú>™¹3Ùz¦‚ÞʧÑëÅÄ'ë£T“ê5vª$)-k眦+GY¹reWEEEׂ º***ºV®\™í"Eä‡?üa×äÉ“C~6lØp=ŒPÏ¥K—v-]º´Ûë±ÊfÔzEªK2md„ö1¹ôLúBÛGêÓÉÊ_6êmœ‰ÕFF¬‡ÑÉ¥g’ëmß›¹3Þû}eîÌf]˜äصkWWEEEÊÚ:Óý`éÒ¥êýfÍšÕµxñ┕5Su‰$áõúö·¿ÝÕÑÑ‘“mÄôŽH²ÙÕ•[mK>sammÞOF>P/&yz#ŸFjûdæÎdë™Ê:ôT>s¡^LlÒ¹>J5©^c§Š¶¶¶´­sœ5¨è;Z[[[×äÉ“»víÚ•íbucÁ‚Ý&ΞÔ#›õ\¹r¥ª0‰4ùÄ*›Ñê«.É´Q®ôÃL’KÏ$—Û>VŸNVþ2Y·xãL¬62R=r…\z&¹ÚöÉÌñÞï+sg6ê¤ÚéÛ>Wúô®]»B¾¿£££kòäÉ]mmm))kºëM©^úzÌš5«Ëívç\1½'’lvuåNÛÇ“O#¯mcÍ•ÉÊg¶Ç&5ôF>ÒöÉÎÉÖ3Y’‘O#׋‰Oº×G©&ÕkìT¡f]³fÍêZ»vmBeèër“9TZ[[QTT„ÊÊJ€Éd‚ÉdBkkk¶‹±¬‘Ž•%Rl׳¼¼5550™L=*»ë¯.½i£l·ɵg’Ëm­O'+™®[,ÙŒÕFF«G.kÏ$WÛ¾·sg¼÷ûÊÜi„6bzGCCL&ÊËËÕ×r©OZ¸ÂÂB”••¡££#é²f¢.ÑäÑï÷£²²2äõÙ³g'T/£µÓ;"É&[mK>¾¶5W&#ŸÙ®“z#ŸFjûdæÎdë™ z+ŸF¯Ÿt®RMª×Ø©¢µµX¸p!Eþ½^/fÏž· ýAg»½¡½½½Û&¾¨¨~¿?ÛE &Ÿ|­­­(,,D}}=jjjªG¶ëIO¤8w±Ê W¯huI¦âÕ³?’í>Ûr½í£õédÇ•L·a¬q&V­¹@.=“\nûÞÎñÞÏÆ¸“޹3‘÷ãÑÞÞŽuëÖaõêÕX´hQÈë¹Ò§M&jjj°xñbTVVªFAÚè}mM+++Õ:Š|®[·NÝüæR1='šlÒ{¹Òö±ä³©©ÉÐkÛXó~2òi„q‡IŽÞʧ‘Ú>™¹3Ùz¦ªüô½áÄ’O£×‹‰O:×G©$kìTá÷ûQ^^ŽU«Vaݺu(,,DMMMJÖÎ}œ<¡BE=Ѽ$³ YD.\ˆ­[·bÙ²ehhhP-rñêaäzÆ*[.Õ+™62R=ŒB.=“¾ÚöÉÊŸ‘ê«r©F!—žI_mûdÊn¤zõåõ Ó@ €E‹aÙ²e(,, y/×útaa¡š˜4|ØÖ¶ëÖ­ÃüùóQYY©8s­˜Ä‰%›@îµ}4ùì+kÛžÊg®Ô‹‰L2òi´¶ïíÜ™l=3I¸|ö•z1 ©^¥Št­±S…ßïWO›,\¸eee¨­­U"ý]rÒ ɺlD+—ÉdÂòåËUë]ee%æÌ™£*âÕÃÈõŒU¶\ªW2md¤z…\z&}µí“•?#Õ-VåR=ŒB.=“¾ÚöÉ”ÝHõêËë¦;n·&“I ÑÑÑööv´··çTŸ&ïºÕ«W£¾¾^¯mmmhjjJº¬ÙîÓ@µµµhhhÀ’%K°dÉ’„Ëf¤6bzF,Ùr«ícÉg®¯m{+ŸF¯›däÓHmŸÌÜ™l=3A4ùÌõz1 éZ¥Št­±SIYY–-[†ÊÊJ5"ÁªU«â–¡?ÈANTL&S·†èèè0œµ‹,øzôVÇxõ0r=c•-—ê•L©F!—žI_mûdåÏHu‹ÕF¹T£KϤ¯¶}2e7R½úòú†‰L @SSšššà÷û±víZ¬]»6§ú´ßïGYYYH_­¬¬T=èrym»`Á”••Áëõ†„·H¤lFj#¦çD“M ·Ú>–|æúÚ¶·òiôz1ñé­|©í“™;“­g&ˆ&Ÿ¹^/F!]ë£T’Ž5vª¨¬¬ìvr¦/èÌRFß§…ŠŠŠ® 6tuuuuµµµuUTTtuttd»X!¬\¹²kÖ¬Yj¹:::ºfÍšÕµråÊ„ëa„z.X° kéÒ¥Ý^U6£Ö+¼.ɶ‘ÚÇhäÊ3é+mI>“•¿lÔ-R=ⵑëatrå™ô…¶ïÍÜïý¾2wf³.Lò,X°@m»®®ÜéÓk×®ØoÝnwJÊš©ºD“Ç 6„üìÚµ+çÚˆIŽpÙìêʶ'Ÿ¹°¶µ–í­|¡^Ljè©|¥í“;“­g*ŸOå3êÅD'Ýë£tÊ5v*èèè誨¨èjkkSÿÎEYºÈɤôP__E‹¡¼¼mmm¨¯¯›2›PòÜùó磬¬ mmm¨©©Qcö%R#×3VÙr¥^ɶ‘Qêa$rå™ôå¶OVþŒR·xm”+õ0¹òLúrÛ'Sv£Ô«¯¯o˜ž‘+}zöìÙhmmŬY³P^^¿ß“ɤ&'M¶¬ÙêÓ~¿~¿µµµ!¯/\¸õõõ9ÕFLêÉ•¶'Ÿ¹º¶MV>Z/&5äBÛ';w&[ÏtO>sµ^ŒBº×G™ Ûå+,,D}}½š†òhöY*ÐÕÕÕ•íBô²²2CjooW6E*g¼z¹ž±Ê–KõJ¦ŒT£KϤ¯¶}²òg¤ºÅj£\ª‡QÈ¥gÒWÛ>™²©^}y}ÃôŒ\êÓt¿¢¢"˜L¦”–ÕÈ}:—ÚˆI-¹Ôö±ä³/­m{R¶\®Ÿ\iûdæÎdë™Múj½ #É™Q˗εs.“Ó†a†a†a†a†a†a˜L“Ié†a†a†a†a†a†a2 T†a†a†a†a†a†aâÀ†a†a†a†a†a†a˜8°A…a†a†a†a†a†a&lPéG´··£µµ@ «åðûýhhhÈöã`˜¬ÐÚÚŠÖÖÖl¥,ŸŒ‘ÈdŒ&F•U†a4z3¯a|¡÷xŒaú:=݇A>Y6™Tk{+£èŒôyïÌ0¹L®OFc@WWWW¶ Á¤—@ €E‹¡­­ EEEèèèÀŠ+`2™²RžÖÖVÔÖÖbëÖ­Ù~4 “qV­Z…††U‹ŠŠ°lÙ²¬Éc8,ŸŒ‘ÈTôûý°X,!÷iooÇ¢E‹(++Ê+PXX˜íÇÂ0ŒŽÞΫÙ_c˜þAo÷¡<ÿ3}…\Ù[MgD}ïÌ0¹L®ŒOF…O¨ôÈâøÚk¯ÁëõbΜ9ê"‘a˜ÌÒÐЛͯ׋÷Þ{&“‰½&Køý~455¡¶¶¶Û{ 0™Lðz½xíµ×Ô׆1FWc/Tnc˜¾ŽQ÷¡<ÿ3L(F•U£Îñ Ã0lPÉ hhh@mm-V­ZêÂŽÞO–@ €U«V¡¾¾^õªY¸p!fÏž­^ÓÚÚqR¢2¤ºL‘ÊØÐЀöööt=n†ééìû@ Ä£fΜ9êñåh²¨/SºÇŒHåeùdŒBªû#…÷:õûýhmm…ÍfÂf³aíÚµ!Ÿ5wfBV35O3ý—žöçl¬)cÍ«=ýžLŒ/@bc ÃÄ#–\aM™È>´'ße”ùŸa’!R_Îöš2YYÍ…9žaRM¦õ3™Ø÷±î§g°A%K455aÑ¢E(**‚Édƒ>ˆùóçÃï÷Ãd2aÕªUX¼xqÒ÷ikk˜L¦¸“õõõê5­­­hjjŠXÆÅ‹£££•••hmmM¹—B À‚ ºM” “MÒÙ÷ËÊÊT9 X»v­ºX&‹T¦LŒzX>#‘ŽþXSSƒåË—‡Ì‰€¢PrŸ²²2õ½Xsg¦d5ó4Ó¿éiÎÆš2Ö¼š(™_€ÄƆ‰G,¹2š2‘}h"mþg˜Þ­/g{M™¬¬}Žg˜tiýLº÷}¬ûé9ƒ³]€þÌìÙ³QSSªpÉ’%”‰cݺuI߃,–óçÏW_kooÇ’%KÔ{×××G,ËÊÊÔ÷ÊÊÊÒ"°åååj½Æ(¤«ï/[¶ ,PÍeeeX½z5€Ø²dfÌ X>#‘éþIiB K¿ß¯ŽÑä5“²šÎyša€žõçl¬)cÍ«‰ù.‘1†a!š\aM™È>4‘ï0ÚüÏ0½!V_Îöš2²jÔ9žaÒI&÷|ôé3Öýô>¡’EÂdáž0‘hmmÅÅ_ñ'Ò1Qò6˜3gV¯^Õ«W£¾¾>áãa•••êÿ£%âëi™ˆ  ½½=ä cÒÑ÷/^Œ9sæ`ùòåX¾|9 ž31f,ŸŒ‘H¤?ö¶¯§ƒLÊj"cÃ$Coús$Œ8¯¹7¾0ŒžÞι°X>™¾Co÷V¹"«Fã&ôvœ®}ë~2 ŸPÉ1*++±uëÖ]ßÔÔ„… ª¯-\¸ hkkK‰Àô´LDyy9*++ÑÐЀÊÊJV19GOûþÚµká÷ûC¼j–-[‹Å‚ööö´­dùdú‰ôÇÞöõHDZ“×Qº¼SSY~†ÉU²1¯fz|²3Æ0L²dcÚæ¦ɽ•uF½)W6öÎ “ ÒµïcÝOfaƒJŽá÷ûÕdGáTVVv›ìŠŠŠ(Ö}ŠT'.êi™:J¶nÝ:¸ÝîÇÓe˜lÓÓ¾)TýÝÑÑaˆ2,ŸŒ‘H¤?ö¶¯G‚äR/³~¿………iS¨¤²ü “«dc^Íôø¢/c&džI–lìCûÃüÏô2¹·2¢Î¨7åÊÆÞ™a2Aºö}¬ûÉ,ò«c2™PVV·Û­¾æv»QXX¨ SkkkVC/Y²MMMª÷ÃôUæÌ™ƒöööXšMMM(,,DyyyÖe1,ŸŒ‘ÈT,++CeeeÈ‚tÕªU˜3gŽú·å•a²M¦å"Þ¼ (²ms©'“ó]"c Ã$ƒæ¨xûÐDe0ÖüÏ0É©/g[^ÑõD^SE"s<Ã0©ƒu?=ƒO¨äú$D‰B‰¼h"êèèÀŠ+Ô÷[[[ÑÔÔÔk+doʤ§²²555X¼x1'crŠžö}“É„%K–`Ñ¢E0™Lèèè@}}= “–ÅT”1–OÆHÄêÉöõpêëë±`Á´¶¶ª{Ë–-SßOµ¼¦ºü “ 2½¦Œ7¯P׿ñëfr|â1 “ FYSÆÚ‡&*›€±æ†I†H}ÙkÊx:£žÈkªÊ•ÈÏ0¹Hºö}¬ûÉ,ºººº²]&ý5ÙXyyy· ¨¡¡9 “!bÉ#Ë"ý¬F:"ÍòÊ0ÝɆ\Ä[çÖÖÖbùòåÙ~41ËÍaý˜Tc”9*–|²l2Œ‚äÕ¨si¼r1 Ãd>¡ÒOÐ× ‡¼o†É Ñä‘e‘aŒÏ Ó3²%±dµ©©))Úl•›a’ÁHsT´~βÉ0 F‘W£Î¥, Ã>¡Â0 Ã0 Ã0 Ã0 Ã0 Ã0 NJÏ0 Ã0 Ã0 Ã0 Ã0 Ã0 6¨0 Ã0 Ã0 Ã0 Ã0 Ã0 ÃÄ * Ã0 Ã0 Ã0 Ã0 Ã0 Ã0q`ƒ Ã0 Ã0 Ã0 Ã0 Ã0 Ã0LØ Â0 Ã0 Ã0 Ã0 Ã0 Ã0 ‡ÿÛ„A;5àå%tEXtdate:create2020-03-05T16:38:18-06:00n;×+%tEXtdate:modify2020-03-05T16:38:18-06:00fo—-tEXticc:copyrightCopyright Artifex Software 2011ºÅ´1tEXticc:descriptionArtifex Software sRGB ICC Profile †2tEXticc:manufacturerArtifex Software sRGB ICC Profile\~=Ÿ+tEXticc:modelArtifex Software sRGB ICC Profile1(‚¡!tEXtpdf:HiResBoundingBox1584x864+0+0û8²ùtEXtpdf:VersionPDF-1.7 7ji»IEND®B`‚blis-0.9.0/docs/graphs/sup/sgemm_ccc_zen2_nt1.pdf000066400000000000000000006510741422157504600216520ustar00rootroot00000000000000%PDF-1.7 %Çì¢ %%Invocation: path/gs -dQUIET -dNOPAUSE -dBATCH -dSAFER -dAutoRotatePages=/None -sDEVICE=pdfwrite -dLanguageLevel=2 -dEmbedAllFonts=true -dOptimize=true -dDEVICEWIDTHPOINTS=1728 -dDEVICEHEIGHTPOINTS=900 -dNORANGEPAGESIZE -dFIXEDMEDIA -sOutputFile=? ? 5 0 obj <> stream xœä½A¯/9’Ý·¯Oq—Õ‹¾Î$™™Ì­Y€!À¶ªw‚0Íh´P·Ð’0ð×7ãœä}¯^UÆð˜žîÿåc2“L&ÉO0⿟çÇÿãÿþÃ_~:?ðÿã¿ü„¿Ï§ôãã=ŽããüçŸþé»i×s|–Ú?îþžŸÏõñ—ŸÆ_Ïçy:åÏÎÓ[­ãÏú&K^Ä,ß\q}üß?Çlï{”oüûûÓy”öÙî¥L§¼Çûù¢œ_œ6 þËòçÙ>{‰,íéŸ÷³¤”µ ¦© ÿ¹ôÖòÙßµ ¥¬1MùÏ,Õìo¹?¾ý1ÞÔµ˜¯ÿóùø_ÿôÓÿò}üéŸ~Šw{ŽwöÙÚ5jq?Ÿ÷}üé/?ý‡ŸËþx^Ÿ­ôöó¡Ÿ=~¶ëóª?·/©_2Ü?ß¿ž¡–~ýÇ?ýï?ý›?ýô}§§\½Öç]zÊ/ßíwÿ|Ÿ-—ÊzÎçú<ž¥,¥¬ee.•µærYm<~ÿ«ùRÊ^ݨ^^ÜñËoï©×¸ÍoïߎÊ~–r;ÆŸë}>Û[Fʘ*Þ{¤ÜÇxãÏ׎³|¢?G“Èø»½c@˜HŸ1“>ç-Þ)µŽ côU>/Œ÷Þ1PŒÑ÷þ¼g1WùxJ;>ßùï÷ùyt¤Üu<$RFG?qŸk¦¼Ÿe”öÔ1ÂÅUÍê¸s­óàùË(§Ž>™<ÿ«Æ JOõ9»xÓ,*0ã=m¤ŒOz¦Œ <&†s´nõŒòúø5þ÷Ý)×ù‰yxæ‰rP‰sܼµ±"˜yF%ŽWÞ|Ì<£' nmT óž(fŒ¹Zæu¨ yîë?ÿÔGZE1£uÚLAN\Õ¯xs•8pó^xÕ¨Äh¡‘2(hœŽ6Á¬õÞ,eT¡v)|š~2gÄQî|šŽ*”úñ\xˆs¦Œ*ŒÑv¤Œ?SFÎ3ä{E÷Q‡‚{‡Œ¦xÇåsd¹Æh&`ði¢c½£WÁ5c:ñÀ/jpâÞ#/ø5¸_òÎ,£ ÏèÌ㢛)£ càÀEc×gÊÈÜpÕyŽVCʨÂçpÕ…¡r¤  åœo¼ñU8êRÎyŒ:”7îu΄ñ\õ‰‹ž2SbU™õ>Q ôÚ«±î8Ô—ŠY)¨Å¬Äè\QΨWck$¼Ÿx™W_ñ=SÆk}ï¥ãûëŸjU¹¯iL¸ÕXZhó<æg0¯ºêLA%¥Å—wž£uÞjtã¸hÔ¡=qQ‰”Q‡kÞêA“ eÔánñÄs8OÔ·:zŒ%#åýŒ—F úu´™2¦®·>ñáÌ”Qƒc6heó•Q %È3‡ñÞ0[E¯è³ä‚*œqÕ;+UP…¸èŠ„Q|e×ñÄu–QƒëY§ŒÜ×ÒqNŒFOÍ^|Ô¡ÄEó³; êݦF)ã{›vÜûžíPGŽ'¯Îö¬£ çyÊ|-c¨þ,xâãÂ+DJcãÈ3¾ãÙ!1Ê5Tó},RFfWÕ÷u¸XÏ ïÀñZæâõ¬£Ïü#è@ßš³¢%Úa~ßg›ïd<Ú|%c€ñcޣǿ§?Ÿ¥Æb]g#÷¼k_Ûò`íš½&ÌaølxvÖ/zYÃl°µ%ñk^uƽÇó?w\ÕfËaÄëmí‰xô—£Z\…1æ8·ÔakÆŒ_çàbîYñkÔ¡Üq󸔝Q‰9²ŒWûDʨD[Бò¢fû]¨C¼ØhÞkTá~·{*Ìu”Òg¥îquß®ºG—{[\UgwÀÜ|”õÅ`n>ϸêžÍ޹ù|·rFJ”øæîQ‡Êa­1eŒ“×ÚÍoL35:I 7j1ïÅ©m|ÿ£1žßóVš ¯ü€~9|Ç8ò`œ¼âqâcÆü|´uPÀü|–('^ æç­æÏ¨CyÝËÇÂ+Æî£+ÃÓcìßN‹<ý‰±{ô¤ߟ÷ޱÛWuÔ€ý¦Ì;÷ñäsì·¾gú¨AïëÕÇ€üÞ[9­ÄàíÞéù¬[ɨBYÇ„ŽZ¬ØŸùU/ ÑG%Ú³<*qñ[œË¦óÞ[ÏyQ‰²Ž/*q®Ÿ7,fž˜KÞÁ±süv_ÇcÅx­q¯ûˆñÛ_&èm‰1ýã÷ÈsÛ‹ZÄ¿ãVXÅÌ[hÛ?ÿTŽQ‰9~”ó™)£÷µ|že,e8~ó3S|á>Ö 3uX>½r\Çï3VI³óñ,ï³`z>ïå“)˜žK[§£ u¿÷{Çø­©¬Œ¥ÇoÝ}Lµ¿u¯1—ÅŽù=SFÎSsÕ[ÆÌ1ü§ŒÔbà xuþYŸøóõ …ùù\WRós¹–¯Œ—£¸¦ÈA‚W ãXàÍ<U8—A»”Q ãQñ2ªpsò=ç½ öDîe (eT¡·eV)o ㆎ٤˜ ç0>Ê™”]0CŸ[1àã¾Ý|T¢ÜËê ÔQ‰9Œ«û¼j1Œûæ•(k9•X_Uu¸×•g©£±0Ök«âÇ5RÅö +GÜ|Ôá(ËòÀ[I^¾ü‚ˆãGÿÑÎ1°¿#ø‚XµïˆÞ3‰Žx¿èa“Ï:Q3a x6‰ÂÀ‘Òc®Þc9“,0pL ‡„3eöAaໃsbàà˜w&Ž”3ú©1ð8ŽhcàQØß…àÚ@´Bð™Ày˜܇_ø•·Ä’RÜ·<-¹¥-ˆû0–ýP å>¢_é·@è‡b‚„~eÜ26¹…~å•.'ô+c ´HôsÈüPïX߈üP Yä‡ö ìùå­D~l`qŸïCìƒy¥=r:4 %÷!ϳqߤ½ûð™ã‘úð1••úPlÛÔ?Û1˜úJ´›˜ÞH!ô¡¡ÏŸ¡WQ$ôáó£Ð̇ï:¶ÞÅ|Èð%æÃ­¢RŸë,èC)TÓæËOº€ W„L!èÃðAð"õ¹TA_y*õXQ_6¥¨·Ú©ÅÄ‹õa°à$ô¡Â#¡O}WÐç–ó! .˜¥„Z)æ[²ùPJÙ s“ñúò½‰úüÀ„¾lOQŸÇ?cŸŸWÔ‡‡ ЇRÞ ú Ì^‚Å}y'Qò¼›ò‡‚ûð4S‚ûòµˆû–<ä>¼ÞxÀÀ>|/6¾ҹ—iìCJ ³°Ïƒ¸±CvØ3ûpïÀub*,&ìËW'ìC1¤Pb_6º°sWìß û²IHöùíŠú…HêÃóíÔ‡§ õå}ÈRWá/ŸNÔ‡,P¢>ŒV±q!êó×.è+÷Å,‚>|îeÓýÊ]td¾Ä|Y.™o qœ«Ä|™…ȇ,sR7òq\$ðáßcžóáa‰bd>¯\ }¸ÍZ©Ï÷1õáª'Ô» >¯¬L}h¾ >í¦>? ©o)‡Ôç±ÑÔ—yD}(çݨϣ©Ïs„©_a¡/YЇ,ñÈ“ú<ø›ú² B²œ‘BèóÀbèCžPAŸCòÜk„>>†¾¥BŸ 3.êT_ŽÜüÚÍ|±Ä|ú|^ÌùüÝù²šB>ŸF>Ï#B>{F¾|ÿ'1ï‹­ç9áxż›¸,Ì{ŽƒcHbިع{t)«Ê—1ïxØZNÌÃBg"Z 2·ÂŒyÞ+OÌÃ5Kæ¥Ãu’ò´ñaÊ˂ؼ3å¹9ê(Êë o¢ Eó" |å2 |˜¶7ÈCÓÄ"ÂߣMU |XLl¦ž¸ê 4”À‡qåcá<ÜêØ¾qQ¬E¬ð=Ú¶Â7®j页Ž]áÃ2<ØŠ"Ÿke‘ÏÏg‘ïѦ´E¾qÕ¹™z¢à{#=®I‘kË õ–Ç‘È÷Ü\ÄXä{´‰o‘ïÑ~¼E¾QN<³U>·»T¾G»ï–ùÔuRæ{úÜËn`™/¯’Ì—H™o\DKSÉ|neË|neë|˜ ³$ô=–õ$ô±û§Î7>SnJç{NYjJçs/°Î‡ýž¸¹t>¬ 6‹Ï|5–ú4èPêóÓYêÓW”R_^"­ï¡¼i©+…`÷«}Ã"ErŸ+n¹Ï­n¹ÏÕ´ÜÇ11Õ>¬)÷¹RÖû4¤àç^bÁÏoÆ‚Ÿo%½oôtÚ€Rïs)Öûtå>_c¹Ï-l¹ÏÝrŸ;ºä>¬'w¹ï©Ü†°Ü§OÊjŸz¨Å¾¼FbŸ»¾Õ>w«}™GjŸ+eµÏ}ßj_^%µÏ…Õ¾ÌC¹Ïóå>[–û\ Ë}3-÷=4ñJ¹Ï£ºå¾L‘ÜçÕrŸ‡ë}y/é}†Ôû ¦Öû\ ~ž^­ù©àÔü4ɤè§j¥ê§ÆHÕï~SRýÔùSõÓ皪{JŠ~ê¤)úésMÑÏIóÓÔžšŸ²XòÓ`’’Ÿk`ÉOƒGJ~ê)ùiâ¤æÇÏ.%?õДüô¥ä§/>%?õâ”ü´fLÉOãMJ~êÅ)ùùî–üôU¥ä—WIòË{IòË«(ùåE’üÔ‹Sòs1–üÜX–ü|•%?ßJ’Ÿß”%¿,X’ŸÛÔš_ÞJš_¦Hós+çyæ¹~[ò;¾•üŽ9G®,XÏØGMɯµP"Óâó =ÝŸaÉikO´Ï´ä´µ§-5míÙËÜõ cÏ^¾{â+Ù=ûõ^Œ=¹\N[O N"%Ž,…ŒG œ…n8jØ—‹ˆ#…»KÂÀyÕ¬0pæ ëOràHidPrà4O »ÒàÀ™¥¯Gþf–89Hœ_ë‘¿{ÂÉÊi÷*œy6[ϼ99pfy×3ysqà”{§j$œWaý8ól8ó„@Iœy¦ÀFÌçÎ,!Ôgž¾ú›yÞõÔ_VB$8R¨~ˆ³BÁ™§¬‚ßÌ3wìÄ‚3O[¿¬¨X0C,˜o"ýMdž`Á™'öQÉ‚Ù`bÁ|[‚Á5OÀàÌs­08ó„yapæyÖsÙò‚Á|í„ÁlxÁàR Â`×<ƒùrƒÙuƒùrƒKE ƒë½—J—rƒkž€Á|É„Á5KÀàš%`pi ÂàÒƒkž€Awx²àÒdÁÌA\jI\² ®Y‚ó« ®y×<‚Kc×<‚kž@Áåq‚—[ÅÔá2H‚K$Á5Oàš'P0¿r¡àòVˆ‚ù• —·b-YN àZN à’‡(¸ä! ®y& .·" ®Y×<‚Ë#³A‰‚9.—A‚kŽ ÁÌB\²—,Á9¶ —÷B\ó®y×<‚kžÁ5OàÒXA‚3˵Z~.mE\ó .·" ®y×r& ΄›vžÇpg \‹ \ó ®y—<„Á%apÍ0¸æ \^apyfÂàš'`p¦ô×,ƒë­×Ç \nE\ò—[—Wl—FYNÀàZNÀàZNÀàZNÀàLyW\óL\³ fEƒ™G0˜Í#\ó æ­ƒk–€Á5KÀ`ÖJ4¸>NÐàš'hp-'ppÉCÌ6®y‚×<ÁƒkžàÁåyȃK½Àƒk†ÂµØÂå „kžÂ%pÉC \ó.L \ó®ys0®y×r&®Y—ª—G&.y„K9Â5ÏÂ5Káš%€pÍ@¸æ \ó®yèöÇõüÅ^_ŽéÉm'¿i7¿{r?.ɯ_A¨‹ xÇf›UÀA;áœå._`–¹{R3 püZ£EÀþÒ›KÚzâAÙzŠåV Îeî¶ž•öli뉙bÁ¿§Ç—£~G½7[Ï £ÚM¬'ÝX¬M%VXôÆÁ>Ê€õzbS@2`mÜê² XïÆh–ëÕhÚ)°BšJœd@,âžM¬¯ô;É€õiÔæ(Ö÷úâò¥vK² Xß—§ %ÖNÃ\Ë€ çÌ7—/õåöœe@¬g/±X_éuÒÛI‡CVlN_à¯mgý¦©•ÿÆ;:HRœL’“ˆ<ï&6ºÿX¤ÀVššJ lð¨ô‘ô7³<ÛQ¿v¼2Þ¤ØpB(R¨6œBÞL>ú׿ôÅu°Øà*¸’R`›ö#éoÜýþÜ”À¥*­t£ØÎW8J`«WXãH„{£˜`%¶z‹Ð(6¬¢\ Yq nt @€àNê€Ù6Ò[Lc‰~³ÞïfòÙà¦æ#Éod)”K$≃;)6øºÙœ¾àN´¥ ˆÆ¢Ê€xàs3ûD5ßÍë nEëÑÑMÊ&¶jëKÊ€­ÒÐÀ2 *õlçýòq$âUÅfƒtÀVîÏÍéKã1=j€x܇)¡¢Œ€i€(ãÝ4ÀViT` )¡uN °ÕWŽV¨f§‘ˆv‰JKÌIÄãm–Ÿh—Øé—ˆ¶#.RÌž& Oש¢œPɥ⑩ïQÄgVrÒ[‹¤˜ïQ žeóù’}Hú_³=m8©ÿå+˜Ý ;´ô¿1@ê< õ?´á³~âE>›Ï—%õ¿6f©H þ‡‹¢³JÿËW)ý/ß¾ô¿Ö$4IÿÃðtnú^黹|Éw@m õ?Ü)ŒÂ%¢ÓĆ–Ài$âN¡öQÿÃà CÿCb<þ—ãô?x_ãQ> €ËUTq§kóù‚*Ð¥ @¸u ûL €x‚Àl €x/»Ë<å> €(‡øF¯¡’§è•þ‡R¢KÿÃÊføé–ü—õ–ü—ÝOòªP6ùyží´nun_p«º9|Á¦„ü·”Cù/[ò_k;’ä?÷}Ëþ¦,ÿá•?›ü‡Ç¹7ùÏ-*ùOCÍòŸ_žå?4òfýé®dùwz¶3~3ÖÿP«3ø‰úžæÞ¾ Ï'ü(âkä¡èÖ±¨¯ÞúŸÛ8ô?¯-,"C[yoV»nþ^–B(f½%¶ë €¨E9 €h›¶™ºA¥ÿ¡˜¾™ºÿYÿS7¶ü‡;Å5¡þ¡–¡RüË."ñÏ_³Å?HÿP,Ý­PüóÇ+ñG‰ŽâŸ†(kxI÷æê÷~WÔ› u¤ý-)ò?<{ë/“ï~ÛʳÅ̹Xy–¯|wÒÙ“ùŴд•g呵´òÄ`:qM|w`”™ ˆ‚«”3Þ1u1ÓÝQy Ít_*¡9Šî° J´#—±„{6º; ½ôÙ‘ V!›çQèñ$¹”8)•~\àb–b?.çד|ðC”“—“ž½ìÇÇ gÁöãrÒ±Wúq9å@Ó~\à>d²“ý¸œôæ“~\NºúJ?.'ÏÙËy9ɇaðÚý¸8Å~\Î8˜n\NÁJ7.p 1ŸFl‡”¾ÙxÓîÇêÆEå˜íŽ“ãÒ \Îûq)A„b;”Ó¶Ã|rAk´›p6aOh—#¶;N'1ÛÙãáÎ77Üá*‚áyÂUŠà)׿ÇWÅ1 K{˜dˆr”ö–J{™"i/S$íeФ=§XÚk",*{ºu*{™"e/S¤ìeŠ”½L‘²×´Ø´²—)Rö2EÊ^–#eÏ)Vö|••½Ì#e/óPÙË){y‘”=5Ž…½¼HÂ^¦HØóEöü·t=_ba/S$ìeŠ”=caÏ Òõòéz™"]oI¡®—)Òõ2Eºžo%]ÏYÚ±•a]OWXÖË,’õ2E²^¦HÖs1Rõ2‹T=g‘¨—Y$êeŠD=§XÔˉz™BQ/$êµ*G-õ2D½L‘¨§'¶¨—Y(êe‚T½L‘ªçËz™"Y/S¤ëeŠt½L‘®—)Òõ2EºÞ’B]/S¤ëeŠt½L¡®çëz™"]/S¤ëeŠt½L‘®—)Ôõ2AºÞ’B]/S¤ëù [×Ëéz¾Êº^¦H×Ëéz.Ǻ^æ‘®—)Òõ2EºÞ’ò~îY¤ëeŠt½¼¹t=ç±®—)Òõ2Eºžº²e=lY//’¬—y$ë-)¯ð¾Ëz™BY/$ë)%e=ÝÜøQêüAl€¿^|žã‘/súÏãûG‹ã.›¦óø¾|‚Õ¹û‰Fk‰ŠíÁPà¨yÖ#|À=×[â¨zÅ®èôÖ ç„m¦´>%¸»]±ÃZç{ SgìàW¸‚ÆnhYKÜê™n:žç¾ã‘ÇØ1õ镎Ç'Z§÷ÂM?VõD%Ƙu0.C…KZl÷ãŒÃ×NS!ÁD¦šVáØ bΓuúôõÄ}JFcéÔ§7–*u ½ôWuÇ…\qÑ3wØ:–Öñ4=6ØúÛtï76ØÞÆPcÆŽ 68/˜:D-çÜ`ëp©=eñ #!hpïÕcl)a=s 5RêÜ`gˆ¡ZÚÜ`ës)×Ü`ës+1®ºï˜j#Úå¢þ ßTc’êp`ùÄEïÜaëà—9FT]¸U¥«ŠZϹÃÖ±[8Åñ1"ζÀÓ0©b]ÑgEéÓ«Ö:wØF ¶è(µÍ ¶>u϶€õÑx#}òBÜêžl»õó‰ë3÷×úñ0.QE@¬Š;õKOƒ:D¥æÖg…•NÃ*ůê޹I;SÊÜ`ë ¥øZ8Kïèe‘PçþÚ¼h6 $ÔhÎg3ášl}:•ˆ,Ñç; (ºß˜AñXãFwš©­Ï ¶qUmôñ•Në]~nA×ÝãDÓÐv…+þ9õ×ð¶Q€êB-áí)s‡mîÕçÛ|“g”úÎ-¶wäS„¨÷1·Ø:œeÇ‹»Ï¹ÅÖáÂr :õ¯ü>ß§Î8Ræ[‡Ûõè²w¸¥ÇøîJä űO§–óyîkn²Í.cÇ}ÏM¶‡î1’ÝÏÜd[SP <m(êýÎM¶÷ís[¶Ž™Bùx/3ÃsζëÁ¨Á„ñÂ:Ƙhñ§Ì-¶Ž-ñ¹^ªj€÷`¥ú´¹Å6Š¡WÊŠEÖ3{MççýÜs‹mùà1•¿³×ÐeþÀ²¹ÅÖ'¶GÉïÜbëðnßn?fÓ¢›Ï?Ϲ¿ÖáÄ>^n/smiߤ;[ÇEun¯Í^>µ¬ñ Îq|v«hðެXø³<Ê3·×f?‹öì}n¯¡yY%D{8ÐkNúO­µÏÙkîÐÁ+|‚–yóƒ_7¢;”7ºl4Ä[æþÚRò;'q”C‡ùõmsmi‹÷šûkË×òF|‚y¯øäßé̬c$ºìÛ'j•0ĪoL¨óO¦n˜ ùyÐkÃáÕš½¯a‚.%n5•½űFÎ(¦ö¾3¥ÍíµYÌ]w ß/­`b,Ümé&íxZ ßô£œ>·×æ75 âª3‡o„˜yðmÏñ»Ò̵ámcüÆT1ßMÃØ9ÇïK%£Ä2kÁ@ mvòy¯›q¢HèÑyÚyÍ9>+žüoðs­§á(i~EqQŸ[sRš}§ïÜ^›#ΔOÇ íµÙ½æÔÊ9·×:œüD0AϼVô9»ï·î†ç‹ˆæ*퉼Ћl+×#xaX‡6Ý—½1Ý‘òÌÑ=ÇÚ“sô=éç·ÁáåÃA'úE˜ùI´zÎíµ¥cÌÝjÿ|c‡=›Ó3Æp<ÌŶ'ÆpWaL1†»WÔûâ^b½Õj¸«åÐИ5çöÚÒý+|vλŸ±àj£ÿs ?ÃÒ¢µs®éæp|EÂCøÙcžo˜ sY½´iãÏ×ã¢6w×úìQ‘åºcÇú7î}_1ŠWNã㢣xeøÖúÜ]ësßr¾ò†:D7ŽŠ#~ÓÅÙ³`„½™£øâm"âb¿£Rs:kˆVø¶x5Oä©=FñJ7N StŒâŒKÚ0EcÇãÄGtÝs5«5ÚõLóùúÞ(§×ÈayÞéàq4=µû8c$w»Q‹ø ¢½îó‘¼¾½{T¢?Q­9—¶ae®¨z”2ê0òZÂÞ½a’>ËÚ오ç@ÞžXF´û™“ÐK£M±wPùÝÇÞã¸FäöÓSÜò1‚Mæ8®§y¢xiÑUXûñÓ›ýøŠrÛÃ8‚.Ì„ëŽQÜfé9Š®í ÜXô`îßðÈ,Øßù+ ´u# Ž&PT&²àý6í ÞÓaÎ…dÁ#‰ãŽ‘1{üȂǀ¤²± ²sæ bº,qs² \’Ýqs² ý¡™Ï›&æfÁ³ß,'XðÁ&|¬Å‚å }»Y°Ô“‹(±`ÁG Ypî]m,ˆ¡8ãdA8Žç ŽGçÂ…,ø`¯5Luƒ3ìïüBƒÓ&·­08K<‘rÓ–þ |Â`Ú³ Ÿv½d{Â`žŸ NCãY Y0 ôÄ‚3~o,2É‚i-L=Áูouј¾óTž`pZ³'‘ç#“M;­éá%s¡ÁçÂ)š•q«DÁɘ´eK œŸbôRàl›‡)ŒZ¸øλ·`³±S!mÐ5ÆNmŒ™! œ•ª'Îí+æ'- œåDÎ:Ì_¸Üœ8. ?ø¢Àz+.ï8»h TkŒœÚNaa@à(†&¾‚Àyïøòãª#ðC8Rå@8Êa  AàÒ¢³˜7X- pM„Àù8QqBà¬DÀ7)pÜHO|$Žrh0. œï¡GJPàòé—¡Š8«Wç;/ràòÎ[ÅÖ9pV4ú-9p~GO 8‹™ÆÍÁYõ؉¾÷x gø£ÔÛ<Ü™,¸Ê€¡ :Úcê‚ ¢’º "ÒXÄÂ%æ¨Ôãà`Ê‚ˆÞ·É‚Xû~‘N(x]WŽBAXbÚ¯Wû­BÁ» ‰‚°9¥ (x÷CìE¼ £QÑ'bÙ'¼Ç(xwFg7 ÞgçŽ(ˆ%bLñBÁûfØE£ €ó«4 Â*õÜP·Šå®Pón(ˆNÛ~‚÷Å+£àsò`‘Qð~$» qJ%W(˜Ï#|:” ÞKâqˆ‚°n埱ÒU›Pð9xFÉ,x¿‡Ž,8AbcÁgθ >•AÀ‚þ⌂ϩ5¯Pð~…NBA˜è– óVA‚Xš×0’ Z"PJ0ˆÓ9¡R ï—® ƒ8°ó0³E ƒMâ› >'—™Ÿ“¾°ÍƒÏÁ-XóàSxfÃ<ˆE!‹Ÿ"[<ˆþŸ‘xFÏ7S‚ÑQ® A7}B\ôGDo¿­ Ž+hõg„-5UJòàò,äABâ"¢Þ¡šŠï°X\ð‰%‚„h‰èmBÂ{pÙF„æ£AE„Ï¡­!úMtc!!0¶\ˆ„Ù)„„6zâ…“¸ˆ„ùÂ…„èéÄF"áõJƒ"¢£«688PXHˆâ‚¹…„×cH$>åü܈=46SD„ùùŠÑ|±É!"D]b³DDˆaà$¢ß¢¹bhâqb‹…Tˆö‹ïCT˜Ÿ¯¨ x…H*ćwnTˆ[ÅÇ)*Ä+ã Qá3&Æè¢B´ É‘Tøœ<9i*ÄóÄw&*DƒÅÝE…ã«"O ȤÂ|Y¢Â|Å¢BÜêÙ¨ð Ûý… Ñʱæzì>'Í=L…¨y¬ÚD…OŽUœ5-\ˆ;…¸%.D1¤Vr!9VîâBô¥Ä…þŠÌ…÷Ë=s!zA1°ßt¬Ù„…ÏÉsÙÂB *œËØ I…ªL…øhÚ†…xd²°ð)«2˜c¦™)Á8bB4L«˜ëÙ˜p¹ ™py2!Þ Ù’Lˆç} 1!/p@L˜]Lˆâ™0ïE&œƒpC&ôHa&ô· $D­â q§ê!‘]"ˆHˆ*„&$ÌŽ%$D}Wep>MH´‚BtÐkU—&ú‰Å„žuÌ„FÍ„ÙbÂlu1¡‡?3aÖœL˜ELˆ[ÝAedBÜ*G1a/bB¼ª@%1!nâ!‘Ð+7#aBÂ3…„hÀsCB4`[•ÁåÕ =Ÿ ³“ ñ8Á$Âl?¡W&Âl?[|”[¾Ð~))°N¿O+–/£ s³=cÛ\xö.cQ"`)tcD,Øà'1 £™Ú‰%“qXåÚ ‡LcA!¬…!– µ]E¬M†Y‚@;0Ž©á,Öu‚ÀЏ˜›¸ÈvÒGµÂ PX8(nX™Y|ŠLL¥vzbH=Ø®öK†ŸÒS£#Öþ&­æUÒ_z©ÿ8Óò¤¾§Ð‘'g«qèH ['A`}»ìP ÈCV# [¨k‚@ínApÌò±úâ0o¬-b3Q J®» x02u ‚Y²AËœ³äÀÀvÐæ'ÁƒA°S<¸NJMÐÅq«XZÄ”ÔGMÞ"‹4ÁCölÂÀ±ÌâiYð`dô”3dA´1^âÊ. Œ+ž² Ë±,(uÆ@¶9ââun8? O² _ƒ0p®"EÊàA°±0è{[<´$ L]ˆ§‰e¹…A,aðQ&) DG ƒî%V¡d‰I<¤ú Ñ6)T™.HÌ‚‰Ya Š)»2L#Ä‹dB z,ŸŽ˜Ô² {µ 0ߥ 0Ë"OìAóc.y—,„À|dA`~Ï‚À%!0P˜ý\ˆ6™dÀ|1 ²Äf· ë1`~¾bÀ%0ß/0¿1`v1 _„з2"Ï»1 ¿p1àR P7úû6ºÍ€ÈZƒÐmlt­R K- ƒÎ`aÐkaPO'ôot‡z$6z 0âûŽu§Ðc³Ð¸0S€žƒ €ysàrpÉC´¯R †àR У‚pÉCôXgôÈfÌr€h³X1 çU3`6±0ÛF ˜.ôêÀ ¸ä!fk‰‘ò¬Ö¡K9bÀ¬¦0ŸP è9R ¸d!¢smæ¡KÕ¦ žº K9y+A`öcA`>Ÿ 0¿DA Ç}C`~D‚À¼¹(д)0»¿(pyR §*S`–# Dž¾*ƒÙ:¢@B@Ý1¿´í¤ þ¦-†,ˆ³ çvPÐ!'Í‚çEÿÃfA‡L4 ¿e»¢ˆ«B-± fÄgcÁáé7Au S’ñ¤´U tÈI³ \nÄ2G,è0bfA8BÖƒ‚ÖÎ,x¾ôzgtT³ ÞSÈ‚gçŒ`„ÞèhÛŒCQNßÁ³‹9È‚YŒXU/D,ˆ¬ „’XpŠQ žû# .å ¢H² ²ôõ°àã¬fAEä4 f5…‚ŽÞfD5 lgF\}×Â#ÏÆÖg„ö¹q Ãùšs3éŠBÔ âÀ³sH2"O|ˆAt›wA<ÿ³ º Ñ»‰(VqqŠW$È: Ï1FÅÀ! ´ßc ‡qlUè˜â@<]ß DåΈ,¤µS±Vé3׈;Ű tXHa`¶ž00?a`¾&a`¶°HßwHp)‡$ˆrâ ¢ÃQŠéwg!Aä9i2Êh«pܶÉÈÜ,D·y—Ó‚K“Šó…‹Ñe3Ež(… ˆ,m³E´†€3ràùP¹2fgf7æ»f# qós=+8ï{cA¼‡@ήp«29º æ@7±9pÉCDžkµÅÛÜ0µ,›¨_¸9yŽÍFÔ3«9U87Q¿LsàÙ7Ä;U@ˆæäù>r {–AÐ] ˆrêj êat(ƒ ;±A5ˆU£@ÐÔ ˜%=xõ.ÍùžÄKÌù4â@O½AlA5â£<6ËÐ%Ï£0«‰D€ÙCH€ÍM€^Řý4@O@F@< Í>›¢¬Ê8@è€ÐCpÉCt”x`~…@ÇŸzü4ž„U1àüÒB¿#jUoÌAèáÓ8WÔQ0Ðaì€ù‰ ½5f óe ós&"˽Qà’…ˆÐÞÎÆŠæðÁk£À‡IYÀ¿êe“þÞ®µ¼˜/3Þ|ÃLï ò¡û‹hŸ.Øãiˆ|øîêv(uÉ_̇” Ky‡9kó!ݺóå½Å|oשW1*Þ6 P¸ŒŠŽnï0OF™ùðqF?óåËó½·Þ¯˜¯¸oêÊÙ˜oÜëaÉb¾ 8 ò¡Z×*þ¡Vïz.p¾ò¶;ˆ9 t3£BÄÓù0YÌ7çvúÞ^e§I1øˆ¦ôácx“ƒ˜ô„%èË!Gb&’úfHôúf á0$%õͨˆAœtã~aêÃãÅè ÆÃ‡©/=V»t7a„<:ˆÁÅïŠ}C÷î æˆ`û‡qÅM}ˆßVõo¾ˆ0rõÑ£ò~3¨Çf ï÷&΃-«˜œCìÆžàä&o.ÿ0—Ò?ÌA_gö3ÃC„nH1ßîUÌ÷)1x3$-:ˆÁ¬GÒ¢ƒt&|ÒA Æ‹w%¿Yε9ˆ™‘2â*:ˆÉv—ƒ˜£0fºÄh¬²¼ó@8ù‡Áãðxýàë˜Swø‡9ŠjÉ?Ì\ ®V 9çÙ? ž÷^áÏšÝà €I]ÙoÎ;»§Úu;8㚆ÜGøÃ‡r®`Žö3má6ÿ0¨Ê„˜¬¶üÃÌ&môƒÁ¬¯V ëUôƒjpÉ? nxEÿ0í}ô]¦[?û‡É‚å&»‰üÃä,ÿ0è&ñÝË? –K¡Ò= ÖF÷ªÿÍb6+Ð\-Ù=Ì ~ÜF÷0éŠîa|'y‡ñ*ÌÞa¢f÷“@îaP…ïäÓ5 ÝÃ,)Ä¿È|wãOøçIÎþafø”âèÆ_•üÃäCÿ0sÌ @¤¼ªé&TþaàëÞŒ@ñÀuóƒ¸@O¸æu ¤„¾{û#ƒÏ‹ñû½ïЧӛ }`¼úú)¿u†>œâ0ôO7Êçþ:=;%ô]|³†¾{äÙÝÎÈÁ_ ±ä4:ún¹4ôF 4ô=±D}ãœ\þ™úЋÈ7½H]›Éç[tÔHÔWNùJ1õ™ßH}}ŠÚ¨¯wÉ0ò M4T S_¹%õul„´¤?Ъ«H}¥Š?,ó5z¯´ÊWŒœTùš«|MÎì¬òIÞ´È×è¯*E>„‹£¤G‘ï°GN‰|ÍRœD¾v Í$ò5u&‹| –íØßô¦´û[R$òe E>ØÐIäÃIùúfyÿ¤È·¤P从/Ÿ)íJ䋬>¸é ž“—)Rø ÉJâƒsþ?/ Ÿ³Xá»t>Î ŸÎ ŸŠ±ÆwÉ[®5¾,X 0ì4¥ñùՅƇ8o›­çr‰4>¿7k|À±]ãk —œF ñe‡°ÄçNc‰¯IÀµÊ—y¤ò·ýl^`òVùÜ!$òµW‡ %òù][ås“[ås{Zå[R¨ò!(L U>WÓ*ŸÏ"_{¾_6ºE¾&·²ù\Œ4¾ÆPשñ4V°Äw>”-ñ2/·Ä‡W`™$>Ä“‹I|E–’øÊ!íP_‘+MK|%b„¦ÂWdìn‰¯è¶%>¬ 6ÜC ùJ_‘{Rk|E#±5¾"ÿ´Öø°xi|¥îþ@—AU_‘‰¼E¾1+Å0k‘žÃS"_‘ßG‹|åQŠD>Ä\=qÏJå+·üxJå+XN*_‘¼a•/S¤ò»'•ÊWú—Óe°œ„¾*cD }E6‚úJ}ë|¥ëðžt¾j»Lê|E¶~Öùª ­óåEÒùà.¨Q:_•þbOvLÖùª¤@ë|UÚ…¾%…BœÆUúªÌX-ôåUúB#±ÊWeTh•¯Ê>Ð*_•=žU¾*~¶ÊWe»f•ÏW…ÊW­µIå«\¥ÐW­ÙI髲æµÒWå;ÕJ_•Pi¥¯^*YJ_¥Ýu*}U'-õ9¥¾*£eK}¾—¥¾L¡ÖWeÅl±odÙµ¾JAÓRœ@ïRŸ³Hé“C+}n_+}®¶•>WÀR\´Iêó½-õéÞVúªì»­ôe1Rú*•S }ø°BÖ“ÐW¹•Ðç<úª„\ }ìw¡/S$ôåEú2”¾*õ×J_•k¥qž£)}™GJßH º²ÒÇ%o }#˳÷C–ºÙzfÁú2‹„¾v¨ }í· }í JèË«$ôaÂ{OGIºj›ü±:¦eb­KPåqÌ£¯Yò"fùæŠßŽ’t=oD1t™NY")ÑIòÏŒOt—+"²¹ §,)åŸKAóÄý¹¤”µ ¦© ÿù¯1麟×õ»“¾ï("µßÊð»#&}ÛS®±0žÌ–ð1ßëAuk.••±TÖ Iee.•µærYŽ…ä²–XH.˹\Ö’Ëe)’‹ÊhH.Iy\Pæqÿw,$´ÆBòGã\*jÍå² Ée-±\–s¹¬AÄ$L ñö¾1éùAĤoúÎ÷#&ýZ¶¯“~£¸þkÙ~%bÒovò=bÒïÙ»o†Â_¾ûálÃã÷¿š/¥üÍ“¦ÿB i?Œ˜twEL¿~1iüûûίü×ß1i¿Ñ_¿Sæ_¿'©ý'i<ïÜZ¯izæ§xgä$L}bYÓSÒXM1–uÿ@ZÏH¨/=›\8댉1T&d]8O‹‰ñ;úL8¹±ÆõÕ5–î1­ß5héj56Öddzµ6Cœ<¥PØ¿àçx¥>éðþjwì¬æsÁÏîGJì®-W½ô°üÐý5}-á^=4ƒkzò(‹›¼‘e¼-v%®§ÒÁ²WŽÅ|l®Ùëz®Ø\³Èë¹cs ÅFó=,ÃB*Jî±»†¦ŽøôØ]Cžè\Õ=@Š©ŽwGË»`W?cw q¢£E{‰Ý5‘òÎÝ5¼¨É’×{ÐÉòxáSì¼p„j:èŒB¤”Ë:㓞_-nÝäm±½vãå¼â‡M¤ÓýæõÞ±¿‡ñÝ¿,gžN'Ëý+^0k¬h|可½ø„7tÅéQÏsCp{By™ïêÆÚeºè|•á†5]tâ¼F\Ôèhy<ènø÷Ÿ.:§®„„›~–ÇxoÔ!îTæß^–†AºB§>Ë‹¹g¼ÔòæfÕ IzY}’áXÓ?§>¡{îuÑìì¤7v Œo;F¥ûlt³ ÙpÑËrc\š1TÐËòÅPI7„—å|Ÿ^–Õ îihE£iΗ^–k-¯áOê»ËI/ËØuŸ5/…Ž–OšÜi¦WÄÂ÷{—&GËËK”.ŠÇà»kØÅŠ—'v× —nøkÑ(]t³Ü®Ððîz‡›e¿ÍúÈÍ2­nÌÑ››å{zC™_pùŒ[¿ô²,ï´7Îù‡—å‡] Q ÂI>éïn…^– UüáæÞh_9&zY.Tïv{É~‚ÉnŽáò±{·‡n–åñ÷Ó4fI{Þ˜£çqê›Ó9z§¾xXäÆ=Ýa`ò™·†Oëº:è¾ñmë7h‚9ˆ”©ãÞ˜yç îJaZ˜ƒx9cè¿Ç܃x¡D™)qWaŒý1ˆ#”SܽÓͲœdߘ:è%x¾ÌÑ'»hÔ“txY¦•á˜[åe™÷]åe™±ï»Ñ˲Cß÷^–Ç{ÇE7½,Ú•§—e¹•¿áÚrâòÁ{ß]~–;ß/æèpn«¦à¾Á=æÔtc’>ßõyŠü,wŽ'O¥Ÿey®¾ŸF?ËZ{ ~£Ÿe9˜¾Ÿ›~–ÑËf“>OøY–»ð‘@?Ën‹§ÓÏre\ŒQOùYV ¦é9ˆûëÄ4~–©{ߘ¦§ŸåJ㢙ô³£Rý,k¹t÷‹~–Ýý¦Ÿe¹ª¾ûC?ËrÚ=Règ¹„aÐxt³L3’±z’›åÂÏó=èf¹±úG˜+Û{*ýÞb˜Ä<]ø1>‘uˆJEß5EåûœªÄýFè™Y͉ óÈôÅ&:Ø ›Ò›žÈãÕL+ݲ6 Lç0®Çy`~ÙÙ¤sE÷ÀGÞmç*f½>ؤsDy0OÏq\áƒyºÔ¥‘ŸÄó\f°FÍÓ‚ãwþ Ff£kþ;²á._óÃs†§ì^ω:D¥Îùwx sü›ù[ôˆ<È|/ë9êåÌnâ¤Ô€úß,i‚n´a5•i𠬤ÁƒN9OžAŽ”‡k3âàèy rò`†\Þ H™@x#Æk B =Ç$ „è1ްO@8yõ"þÂ$G@k7'"úé¼¹xð€¸ý±à ,ðß w³G q15ƒÚHƒö@.T<(Ó EtÓ ‚nÎNkDXÐ+ ’41ùŒÒày1‚ŒhÐʘiÐê·iZè,E0¨ÃkfAú1 žãš—[“KåÔmV(9æQb ½;šË°JC„íÙPJDsÕ/r`-Œh,E˜!‰—¸Šˆxô±˜Öƒf¦Á‚# B5r‰em,XO­ìH¶4âαâeFƒŠ+Ö´‘B Ä­c5/ ÄÓßHè&Q0)ÐÎ1Mååa8S`=¸d Ä¿X÷Šk¡G}S lb‰F DÖQ ž/–@¢@øádR ̃Eèq)½-@‚ˆJ• GR Lbù% „/ѺQà¬Jä!Ö*ÒÖ“8x>’1°¼Œe ¬¦¦Æ@Gü3b'6 @Q'z¤0ï’Rd4l£ f^¥Pl4„MmðäÙ¡ÔåpÓ0X/§+ÀÙk{Ti°ö[¬4ßÚþˆƒ˜^¯ í3ÅÁ“a¬ƒx#±*¶ÂÙÂAsn8ØîJQ8ØpˆëcÁÁi6)äAÜ»nÚ ba…‚'Äé€ÐÑă‹2IlM´/lWS9äAô†hdñ 9hT<¹•)À œˆ÷+ Dz6qÐ!| „sM˜I DpÕ€'!”^IaÐÙ€5ΙÛc*#âæÑÝă­ŸRɃmt¥À4Iƒ'ƒâQî½Iƒˆ'IÚ#¢ ¡xŠ\µlÚ Ãúšq«{Õñxñå [§Ï C!¾ÀàH(t<[C!RÊ…0ûŒ¦¶7"™ D6pHƒSÂ&‘{sצ ¶‡~„×Aÿ_fB7º˜°½’ÕÄ„¸U,&Ä„xš{cBûMeFq+2¡+.&ÄXD’L¸ÜŠLˆ6-ILˆZÅFªµÁƒ§±Í„Þ¹4â•3™¶± "r,_Å„è^±áoqð o*lÏ#åXˆ»‡¢Tˆņ!¶Gœ(*„Iñ½kƒ‡¶ûE…ˆ•Í.*ÄÛ }DTˆ’c)#,l½Jæ#æËúƒ0:J´±õ õHXˆèÙ±ü"" 5l]ð?6ÆÁ¥\â lôY.q0¿ áà´ãrˆƒy©±ÂØ8ˆ·/ÂAô›øX„ƒÁƒsm¶á`‹ã) "(çMú 'Ë]J“pÐÁăù®„ƒ¸Õ. bŠý$á`ÞJ8ˆÆˆÒ C„³æÂA%š ó‘­ Í:!Ý,w:i潉ƒè\ñÍqï€yá Ú8† á ž8Ftá ÖN¢ÄÁöZÍ#¢àØŽ¢R¡1‹s:±*?ßæà! ĽÞÐ÷„ž‘S<èËÆ@ˆ<}Wny‘§lDènjU°_ºHªàK%xQ¹5”ªàK{!òÄ = Ý„þŒŒ„K1DB´r‰§t?´´æ¡Ø±Ø$AY ¥uh+"TY‡Þ j•Ö¡}¤uèýòõÚ<ô~¤†IdèMëP"¤LC;O1§iè#צ¡ƒ`¥i¨­ Ó4´Hˆ”ih>šLCi&˜–¡Ð™‚®dúYpÊ2x:ß’ñ~ú>’þДakÃP¶•å³ÍA)Ü6íÈlÚé2%ÍA{û`€‹eaæâ%±fœÇÆ}0“ŒOÐæ ¯Ô ›ƒ¾TS„}w¼G1láÏÝô•ˆ$æƒ;ŽøRl ŠVýX·96 £íPùnl×@É\±I€÷!eLȇ”kC>¤Ä&äCÉAŽA|wŒÕ òÝO-ùnìÜ,Aa>VÐB>äy6KP”C›N"ß /nfD>¸*96KÐ¹ÚøXˆ/PÄwŸRžD|÷ɘ‰'ªÕOLp$ñÝ'ÝH˜øð4×F|Y+‚¾çç|˜1h*;PéH;Pæ¶ÅfåF|KÙ¾C‹ˆ/_í@_[˜ñá´ù±‚‚–6Ї(ÒSxä‘!(b}|,ć;]«˜w²¨zºÍ@± º›¾Ò¶|˜Qã{·(üM†9)öÜÌ@ñ™õ`.ºúè&3P•càÃUGp™Ì@ßòø'n¼çXðæ=¤<Ôƒ÷0ï ÞPálÊÆI+PŽ66ÕY%ÓZø ¶“¨Žx˜öü%šöpUÝ@÷ý¿!,ÒB~'ÞÁJ~°=†ù¥$è“€“üb‰Ÿçµ¦ó¹Àð<²pŸc ¥úwÈžP'å¸ÄÜWe;¸'$÷aÉ+AqŸ¢˜ûì…Ý܇5J¬TÅ}'ÜÏ:ˆûÊÉpõæ¾Yqÿ°l ULÜWJ‘m(¹¯Tn׋û`öG„#ø•v ( ~in'ðÃb'h‘ÜWZØkûlÞ&ìÃ%±B÷•»Rè#öµË&ýµiÂIìË‹ˆ}6Bõ!DZ‚>ÜÖ1ö¡Ü7“؇…Øv&kµ +™vÕ#ô!²rMèƒVßd?ˆÁ›êgK²4•uœ¹ê0•AròðØ Ì@_.)Ó ´ÓymšÂn –Ì@e'–f ² K3P—l;ÐX~&ùÉp,í@߇g#múÞ‚:‚¬xøP† /«¿òjWG¶ .Fä#¿ýH Lñx¸O¶ ±V[ȯÄP¹lñvòC9uC¿¬¸mAݤB?<e>Ù‚æóÈÔ†‰6}«`0è/íêD¶1ýÁtl·…¯ßíD .Š sÛ‚¾:„g[Ð<üç7c„ÅB,ž€ù|¶=´Ü·-èk”#Ö³p=*D³ÓFÓ¶ Ät`Z aÎE{Q Ú‚hisPï[ÌAÏÍCÁŽ ˜·²9è)H¢¢adÀ% !0mmzê\ž 6¯Ç€¶Ñìùd z Pl zðÌ€0mñiikP`7¢˜íH 8–¾b@ —Uù³ÅÒb ú(‹¬AOE¢Z¢ÊÔ½"­Ae=(Äã›ö—f°¶Å:®’5詉¶Õ>lZƒž<kcP¿ª i|)„Y`ÙÎfGâ>×v&0ÔÆ 6/´1¨íùl jƒÃ4ÕÊ4}¾ˆ¶JcÐ4!µ1¨óÐôÔ®ŠAmejcP¼ŽÝÔŤ1hÕÙÔyh êLcPb\A¯MýCžcCÁ¥ƒúm ?‰Z6Õ½l zêp¡AÝOl ‡QŽAõ„6•‘¿lA3‡lAá-î$[P½ÚÔyl zú,ŸlAË×3Ù l šf2õóØô”asƒª½l j#\ƒf9²UãØôÔyu[ƒ–C*¬Ae,—Ö ®–­A©ÒÔVõ6õÃ¥-¨ŒÔm êµ-¨Mrm šåØ´Æ\Æ *'AK‘(cÐBׯi ª¯(A5}¥5¨&[ƒr+wTÒæÓVx"?XŸ›à7_þ&øÁÚõÜ?x–~·C€õá ¥4ú|éÙÝìg‹î4ú<é#ÐðWŸ.ƒN}*„µév´"!ùMçðdô©hßiôYOî;ÿRóµÑ'–GþåãYö;ÔulôyF„Í4úÄ‘çMöÇQ7úkUml£ÏÓbœd? $!êÑ계³ê4úlÚ£±ÑçñR‹·Ñg9uQFŸåä(ÙïÐqM}ú"Ó_•ß}bÒ›Œ>c ÄŸç-$úÁh!Äe[|"*Ãæ 2û&úµ³ê\ L>Ë-×/2ùÛ{6ºL{Ï*<Û{Öoì=±ÄÜì=aLBÊ“½gÐpiîyч®í=eööžUfo¶÷¬²Uö¥Ý›í=«-7eïyq8L{ÏZDy²÷¼ŠdFÙ{ú…§½'MÕÓÞ³1@wÚ{^ïñCÇ&þᢺÛ{¶F¨³¹'¡§Ågcðè4ù„óüÍLk2=“Ég£Wç´ù¬÷—c€¨”ÜÃÐæ³=z`ßý ¤dôY/.tmôñ*ðƒm}P‰>û£rdô);þ4ú¼dlm£ÏÑ^”eôé—VŸ€íÝê³éh­­>uð Í>OžœOò ÈO3E’ß[¿˜}âûI€ðº|ìfŸ'Ã]$ùu s&¿·Jñùa½wòÃWþîfŸG‘1¦Ì>Ý&¿Þ¥ç‰üÐ5ÐD~á::ÉÏß«ÁïÕpg³OøEøX¹ï•ÿ)s_^$î{-¨Éêó”E¹­>(›FŸØ4ÚŒ>³iŒ}/X$ö½ —™FŸ˜,ãT ¹ïm_|Á´ã’í¨¸¯_2 ÷½ôŸÜ÷^_|ÁàVQO}BÛ­>zrNîÃ%‹û^ ƾ—^õ}9íûòiôy:(ìë®}¯>{cL#¬>‹ŒÊmõyá#­>Š-I~ý‘‘LEéù…ä÷JUùáRÜIFŸê¶ù<è{<¹Ãfðš¸ïmb/qöÀ7îÃdJ©Nܧï#m>ºf7÷Ýtú•àÃ¼Íæszh<¿—Îúü^z’L›ÏƒÞÆ ~zU ~ïýüÔ~ióyv™ŽÊæóðáAÙ|žEèçÀH›}ç³#_m\òù„ö*+ò}Ͼ³Ó$í;;CJùê‡Ò‘ ôËIäƒüÅáËãi˜kâð²òƒ‘ }ËøR·S~sôúX€ï¾Ùí |ÏMûYHa?ä÷\t"eàÃ÷nö},¢ßÓx0ÂÀ× O øú)>‡{2ð=¯Š øz;T ¯:‰%àë77N|ý gß‹>ÈEàÃÀD.>¸… <ðõ1ýFøà;èÙľ~qÛÁÀ7£„ðL__MÂÀ‡³§÷vÊ/ŸPÀgAѾþÒÿ|ß[ s¾÷+àCðѾÙyö®ó˜> p<ÓGàƒç"j‚>ä¹é†!U ×§&>–ݼ¾¼MüNà›‘)Ãg®€ï­´U1ð9þ§€¢»‘øfܶé}s¬#|$>š«ˆ]â[ña ¿VKO4ή÷M $ñá½l†ž/<ôm†žŽ¿bæC¬—MíƒÏ¡íH|HØ¿Ì8f”ö`§è¬yâm ù%åÙÏAQ„|K‘ÏñNŒ|H¹6äCX’ÈBâsØ_f âsÐR.ª ¯S‹J!ò!…ŽUˆ|vâdä;é†ÀçØ&¾|8Ÿƒ™ø²9}ÁÅeã=Ç;1ð!esþ‰‡¬ð‡< ø™Žî­bQ"àC µ@RîÍíˉåÿvÀï<ä¶AÀ‡ˆ:ç&ôá*â&ï‡T3ê!åݬ=‘r­ÖžY I3]AÏÖ zŽËfÐójÐs3žÃ•ôpOôsÍ çHm=ä‰sÞ"=‡X3êùqŒz{fÔóoÔS 4“žc®™ôÎb3M’Þ’'HÏö„&½3‚†.¤çIߤ‡”x‚žÃžôËM ·d!èyyaÐsÔ3ƒBí¶Íß˹Ûzâ’‰ KH¤0“2Ç{µiåQ?”Ç޾fÉ‹˜å›+~;$R‡éXmK™NY)áGòÏ @Ôûý%’‘SÖ‚˜¦‚ügô¶ðð½ÔR)KAJcAùç¿vH¤ŽÖhŽß)ģѢ#}“÷’~5œÌ·]iP-Ì+Öø1ßë:ó Ùâ*±¤%R”´†BRI™‰%mQ•TRFBbIK $—äL*i©¤’ ‰e $—£,*f‰§¤#£ E1k$LÎÄ‚¶xJ*)c ±¤%’Kr&•ô/ˆ“ô\póþÿ=NÒï1ÙGÀoÆÇ_¾û±lcæ÷?•/¥üÍq’¸ ú3JR;nþ+~ýÎ(IÈúM”$$f™§ÝþõM¼¤ýæ/i,m+ã%!ñk¼$¤ý³ýýwÒ/©¼?Ž—4·ð0ãmÚÞ胤MJxÇ74mëOƯž;lë9 xž›¦™4}ž~1êy^šXT:¹yúA‹›–æ‹JE'½Ð¯ÖAHŸûS¡“6>· ¯¾lç™Xt¢é—üjÝJ¹ib'hñ<ýj]ázt·)&uúÐë¯ÜjÑWóór«E‘ûyOºÕ’Bü¼Enµ.¼ÞzÚ/K,±g6ý²ÜØGŠÜjuú:€ðð«Å£(s‹ì¡Ã©8œ3m–¦,O&BZ½«³”ç}/úeá¶õÜX› ô“1ÃÇOîáiŠ1ˆÓÆBŠz?*m,ÞkøŽ>ÔVïH~ÄÃÆâˆžÓ>kút oú~Ür¬EG(^ÂçÙjyèð,>ß¶àgÂË£ÕÜv¤ + =ÍíiIrF#wÀÅ<[-b‹ËB§sƒ 3¶ç´?iqUãÙjùfêjóÍaJÑÌBNC:ÜyO´!ëgçñêãÒ­^¯†ñ˼¨<^ ec6r9¿xÖê8[sÒØyjœ°>éT¢O÷ÒoÔaòõHáëãæ+/Xç­n±Å<¬±"âÎÉÏÂ-†ÞÔ 6¶¸Uê×EÇZ/í':×¹‚§cŠžç¬1£FÁCî(òQ7Mï£C¾QÌË;ÇÅ¡£ ¹sÐýw‡¤wGÁw$†Ü9ylª÷Ê;'C Œ†ÜQÿƒÊö²IçÌÙ1Cì¢Gs3âN¡ÎØ1CÏ!ü 7Þ;#îœHyÖ^‹ÐKs‡Wq?G šß)I(xÏ‘°-(8÷̃nˆ‚÷{‹wï±~‚ ï·‡ ”Hð~aûõ‘ 8Sôà,‚ öÇ‚ÇÉÕ»Að8ï/ x.… ‚Gá¨hıŒ¶àÁbI0ý — ¢@<Ì7ÂÌuTzÁ2’™ t˜$càÑx2Ñx´ë  ŒÇÉuº1P™LÇ%ï¢À#„Õ…!Ù‡Qàq]bGRàqÑq“( ÷F˜b ! DÁÓhƈM¾;Š!7ã7˜‘«R 4Š˜ûEGá”b „‘A¬EÇ_LHˆ¿()±rw)’‘‹ Q æËX_‰‘'0AˆÙ°ÄU¤@Ì ±^.w Díb( \RHGôÃ…›Ò§)qºt¤@äY!ßD¾€ÀÌAÄq¤)tš—‘—B Ô£¸ˆ ˆbbí.ô9'3 /Â%Æ\H D^D DJ‰<¤@¤ÄbŠ8íL6 Ä¿⢠VQ`V\È^·P ^o°)= š‘—R 'P\˜ýF˜¯WÏ‘eÃÀ£Þl b ÞwÛ0Yb) <*a3E¸¤ÊÃÚâ@_´8ÕÈBĸs ® T$â"9p¹ˆ˜±*–"åª"¢˜ *a ÃØ—«ˆ³óFÂ@¤Ä¿“ñpÄMRàQ5ʈRcI¸ä!f뉳!Dˆ·A`v$Aàñ4R 0» WÝ…œÃ}, ˆRÕÄ€ÈØ/\RÈ€9ˆ ¯d@\£¾·ª"% úùÄ€(7HM ˜O,$t, 8gˆYo1àò8d@ÌìbÀ^Ä€h¿øÄ€9vóÅ—‹K !)×H‰$A`Ž‚À忤@—l ôˆhôhtE;»9£R‹r‚—‚ÉÕ ‚èó33¢àH º½Ìyor`–"´+]s Ðè¾n\ &.yÈ~>aà’…¸Üœˆ¹ê‰›“ó‘ÅŽpiôç)ô½…¸†9ˆ¸&ª) \Ê%.W5zˆñwÝ(Q &%f½E.E˜Å‘ò†³—‘çx#â[Œ A Rjä!ú{5z°0f%j 1v˜ó>bÀ¬ 0_œ Ðã‹!0ï,\J&¢äØOf½Zo—,„@á†@¤“]M1 ‡?3 §3 ‡g3 *þêtüdIð<ç©ëUDD€€$ â}Æ*T4è >ÆAä }J8˜]P8è°>ÆAtÁЄƒ¶0fÇf[ÑwŽÈò(ÔŽzp0» pG7"ϱá`6!q0ë ÄÍ)ñbQ,ijé‚îîâA¿=á îÔ&ôÐ D–@'«‚O„ƒi˜ ô:ã`>ñÄAÖ6âFeS/Í<ˆÖ‹1R<¸+UP¡Å̃íŠãCÆAÇF0¢˜ ñ`Ö@<Ø.©HâÁl>ñ Æã ÉƒnOñ`>°x0ûšxQ®Ml1Ù,<˜OLÌÇâó ; ñ Ž›‹Ñ}B´q¼L!*B€0ß•€0‡ !–rÁ«Ò5-šçaËÐåȃh®HŃxÀw³WˆÝÆÂA¯Œƒ9Ú —{—‚¥ j²7:ΆqW‰ƒîÚÆA4Îyˆƒ¨Ue Ãí\<”%\Š!ÚoƒqП¢q°]]äItšíA<èňyÐ1̓¨yHMâAQЮZ‚ö„j\Jîò¾L´FA{©5 æ» ž'…7‘ Ýþš³V"A{ ÚA¨QÐÎ?‚p¸¹ ƒö`jÌ& æ ¢ž; Ê/«Ip¹ˆ$è¨ó&Á|ç"A¤Ä2V$˜Ÿ#I0{©HÐ^~M‚ù>E‚ù‹1ØH‚y+’`ö@‘ ýìš³‘E‚ËU—Ü/;Ï-÷Ëï Q¼¾WíçÔ,ˆŠÆ¾‚XÐÇ+Í‚v.kÌ»‹ó ' ÚŪYÐ>~Í‚ùÀbÁìÙbAtÛÀd±`ŽUbAyà6 "K˜òгŸˆíÖ,˜Ÿ§X7?6QœÇÙ™,˜_ˆ`p¹Õ#÷˪§`p¹ÕÛ<Yò¾¬¡,hŸ¿fA\Cy®¦÷å¶±`VS,h¿fÁ|½bÁOÄ‚þ…‚5z‚è7»}hö ±`6…X0'#²`ãbÁ¬§`ОРƒ˜C™ Úû½aðÿ!ï}vnÉq-¿ù}ŠVú Bÿõö¤6`ôÀå5jà~ÿɵHjï“Y™…2p;:góS(Ä…B¿X#)aÐó“; zsýë0èϴà]ƒž]ÞaPr·ZcAæ vL•ýR8 úÛÊQÐr €‚>¬; J›/}tsô¬æŽ‚þnrôgÚQ0Õ<˜~c«£ wmGA®Jwô—»“ ?2N‚ÞII‚¥Á •Ù—Y¤1ù2/19ÐÓ1;úSEôdîÎq»É| }†àÈäËNþ&p ”ƒT ô!Ò)°Þ÷„ý•èÏ3`\Þº[n P׊^±¡ñ`ã*ãÔdÀh?!Ðï 0ú+Ðbg@frô,£}DÀèU@ÀdúžŽ€Ñ£‰€Ñ>" C·…´z¥X*hyt22»‚ãà;‘fÂqðÐ8È-o>ö‡ úȃ3–àÁªÁƒc~è‚ò˜<([ðý’qpam…㠤ȹ"De«;³Ã DdƒAÑBm9"XP¶i×2AS‹)n΂†k‚Üf+@)Úƒ÷‡(Pº.”3×+8TàÖ®Ip q×90x’H‹sà3h †È c‚w‘Þ1Ð_…â¤c`Á×ÜÀÀJxt Dü„Ðï¤`™Œ u,ðŠX vÌ ”…#a$À²~| Gà9Vÿ9ðÿ„¬òŸS·ó_á*‹à?~Ctþ+ÔHþã'“à?^öà?>@Á¥3>“üW°ê#øËP[YÅ$@Þ½ À° 6- äõ ¤ëN€²ç&À²¸(+z®E‚~;ƒ 6¬×#’ –Í$ ,H<ã(¯£çZ%—ǰb½K `±Í½G@>ó€õ!ñ‘Ù‘ƒ£ µ3`AvÅ`Àsƒ­uD@¿~΀a!âqäÈ ÈN (yÊ.%0E ,‹‘ŸÄÀ‚”ÔÞ—ã¨ÝÒÀXl+Ì À²(Ø‘ã R w§@¿•NþP9JÚÓ+:Ô_ŽR¦]k£Û8úÍ ¬÷A©f^R 4§CøºÎܲ*8°bÏ€Ÿìž¼g1ôWjlòŸ¤üHëUÚ³(K罃O–üâ@ëdÜ%ã@;ó×Eè„2æq sQÊcè±`!ã@m.–ˆOR©cKevº?ˆ}B8-ôµ´Þ)5 –|Fh©Ø‘ÙÃ@™]?Â@öûŽ0PIR µq 2FdèïÆrOœú’é:÷9â@¢q µRîc¨í–Â@™a6f+:$›Â@;3Ìx¨íSìa 6èa ÿ# ´37‡ÆAÊ #õ˜Ôj¯àˆeÔ›Çz„SÄ2&0â@+yÍã@=ÁŒÇ"rõÂ@ÝÂ0Pfõ¹Â@ë¥ýE4®‡F`(Ã@q¿S(£ý" ”©< t0qM„z ª‡2χv¦gñ0гd¨Òz¨¤b·2¿:+&x:6øÈã@³q Ðq Ëff:&µI†ÊNçV¯‡òZDè@ÖåÞb) Ô“ºxh±Wp„Ê תÀèÊÚ7r01 tr!™‡ÆA õg•µÆgZlLa t”a ™ÒS(:²Gzl«GNÏüÂ(Љ:˜$‡Ž‹û䉰¼Çz0aÄ2öÜã@ýZxèx>¸/BbZÐ<epPÄzì­ÇzgÄ"ì芽µ¿.Œ@PûL F_ʧÜã@=„7â@é“ǶŽûëq lŸ‚ú0  µõ@P8=”¡qêÁû õHàåÉ#ÔöŽ‹8P?wÄrìŠ8P¶Æã@£bÆzà»Çú©<ñ~êE(£dshÏèÝ8â@9Þy (‡=}¹¤¿è³: ­êöÊPïˆåКâ@7Aq ÓÒ2Dè@ œå+ÎÃ@ÃÀ0P޵ʘû•gý"¿NÊ0ÐùPlCèxŠ{Q ø# ”Û–E(.zr$KA xî"”¯àu7=ó•ˆå“1 î“Ç€òÞy (ߥÊ©GÄ€úíõP>eÊ…)taic@®1 \‡1 ²Ò÷?{#Ô½òP® ‰P½õPÎa"Ëq"Ô;އ€b² vé! _ŠQ5B@ýêE(CV=”¡óêW8B@‰1 ˜~F ¨d{ (SðF (RE ¨_,õ¸iÅÛÖC@9±ŒÐDgÊùK„€r&! \ç•¶NŠpÏÞl·\ç½Ø‘˜¼wzÃ/{½BÂuØ/´0²ÞØÔAÖ›s(g½97ÈY>‘õÎ ŸkõÀz«½žôïÔçǵäïL;˜D¨·Æb‚ Þ™]O‰zçÈD3òvZ +0õäeò^¬' ׋õdCK“NÖÛ/¶qÖÛ’‘ŠöÝá.;ÎzrÔë¹%ÿŸ ¬·+óÌ“õNç=“õäœåb=)ƒ5tÆzûÅ–€{ÒdeìíQ˜;°' ûë{gú€=Iµo`Оlˆd:ÒÞy`ðr$îé›Õª{º¡pOœ”÷äú›¤Ú“ÝʵêOw…FÒO£=yós ÑžÜ"È~ =™ Üi@ek*›Ö÷â÷ääóZõwNÆM÷äTPÞ€{»s*KÜó;LÜ“sEzJ¯þìɾ û‚½-ìý’XO®ðç)û*ÙGn²žöy«¬'÷ÎD!²Þ~°G’³Þ<Ö“½ @v`=¹w@=yˆ²À'»)]Qž»aßC=ZÙ™Az2—¾7geø(HoŸ9Á{é{ÒÞqEyîî‹ù@zç…£@zòüÍkÁßnœ÷“ôöpbéÉ­³, =î9å 'Ǭ+ÊSv¡²™7AowÌuÉyò½WÐh8oO ÄwÌ—Àgà¼óJgÆpž\¬uÅxŠûÒ÷äò™nDΓ[qœ§s^k18oÛu!äÉ„w^)@}Ã.‡¼] ×àòä±,‘ûE/ûnCÈ“Å/Bž yr1± 'W³\âžäB»Å=Ù.ÄBÞøüè£)O®L¿R€Êžhä>£¼}ÞIíÊþ"CŸdçÛº9äöý’OzL»R¿Èã„°Qžlf·.qOö;AÂM#¼½ŠõMÞ¶k@º“Q¦À²±a âô²vå}‘—†ïdØFS€wš{îÂ;¼l߉K&æ“ïdD·|÷Êg§KÚ{+æä;1pá6Ý‘ ® ÌÀwÉÀ“Š­ð¤[áHÀ“MÈnmO,5àùžcx¾á™žïµæ€'Pd“yžï¾æ„—j6ÂóÝ\œðR5ƒ;ï¬èNßmÍ Ïcjðâ(ž±°Qw›qÂKE*7ÞÁö®Nx¾aŽ#žïo爗,ƒï,†{Nn¼Ó),2¸“Ûá8ãù–>Îxq/<ã‰3õÊü—‚Œ';å lŒ—Ê€ñ<¼Ýï-y]ŒñtÃCE0žÙ—¸'ˆ†d<ßD0r¿È>ÊWî—hÛ9âù.IŽxoéÌ Æ‹’ñ|*‡¼¸é„<©Ù²Ý×GúOo Ï7crÄóíñ¼Rž´Ö ¼è5¼¸¼èùà‰Å„ ;9ͼè.® é.𠼋{äi_$)Ç»è‹Ä;¹ ëÂ;ßx)í™ô>²ŸYÞ»ã}eR×Ó ,ã; }‰ƒPä눼gÒû YÁ—ë¤%íPD¶"‰Ÿ±CÑ>„T¯ÆÁ’+‚ùÏ\Ñ™N_Õè﫱xöã_½WÒ+µãŸÝ+©ý…½’Zû§öJúIzôÍvm"óÓ>#éw)Ô!±®¼ëJ¥P×UŠuùVH^WÚ ÉëŠR¬+—b]ÜÉ«Šý¼&/ÊR>¾+Êû!ùÓ¥PÕUŠuù†H^WÚÉëŠR¬ëŸØ7iKLñüO¿oÒŸ5½GÁ¯1òן?8yÜü§æ®å/ï›ô>nåð‡;'ÉnAÿ×Ï64úÚ9éÞÛè_·sÒøIÿº_Ò¹oòñ鼺~ÇICà¶ïšúNl–‘¯Bö<M^ذªôü–ky ÚúXäcÄ/‘’öXtB$¦;–ýªe!õýûIfv, ŲuÀ|X{þóê·6ÙÇ÷±š‹Ä‚ý¢î…¡÷E<б˜ÒM»Í äŹñmGÁæáغôü–ý¶”wáÓÒ’XâXÌßò@¹àóy±lÛºr[ôÔ±H+l¦Sq”L^¥ ‚Ž¥Ú.ׂ®fBÆ^v!*hØ=–óàÂTnªÓ>QßËæe Û ˶-®b>ÞGòÉiLTã$ª¡ýò2°¦4´?ÎÜÊ4 ö£?Éþ+|Ð9–ÖÕ£f1FÇ Ùâì ‘¬ n+, 5L<¿•Îï†Æí×\BÜÃéÇb– ƒíp¦êfV`ãÙ°Ž¶÷—ݹëߎå1Ð<UÎòiäc–°E×±HºB³4d­Ñzt¨!»n[™ç…eÿ€ÏÓjò©üjÌ(6‰úE=’YÙ\`™p¡Y§½Ñ‚çoHV¬_tïR$‘4VdÛÅËv·îøFq,û5•ÏÍ„ Qí„ ÇRìzN‰Ò¿š78íÔÛnõÔžn©¢žf³'oÞ p ˆzg1KãS0×k7 ÑûDzóÉ[¼žçºÿ¢Ó¼Wë=ð+³Â yK²PÛ™0p®ãA»nïÝìºuò¹N¡}‹>øõ[ð!k?fyM‚˶îgÎüßþ\Ì\Þ«?ègòÛâ4òUïî{ú%Òú0ÞòY·›ÛÍž=ˇK[HðºÄÓ²é{þ™¬û‰’×JnŒÚwç“Q‘ãN@_ẋ×>$¿ò|[WãÕ‘ȼÚöSrÚÚ…xQÉzéÒF™ýpDè´lÞëGï ¢ž÷½ú⺙/Ô«ñò÷Ê8Uòýê×ƢóÊBë‘uôXà€_ïW²Ÿö<@ŸÚcCv ‹íøêwò¼í›ŒåV¦¼Ó«”yÕ[tyºÌì"È»ø½.‹Alv© ûº&[â̳ÜÎ[èóÒ…q®½ÍâG =Ì<澚‰#˯D1oóáµz*}À­­ð!ÕÛÇòi-®*üçÞZgáÓƒÛ[×˧‡­ÙyÅçéXàƒw¬ö¬OË;?îT+6Šz$0qßeZ¿îeƒ>¸¿>t‹‘:–Yø>²9Úñïe÷cköƒ§Ç´l±lö¶ee:}ðkÚáƒ(>vvÙ]iZ¿°ï32Ãþ¸W½5Þ+k`×ÏÆñsTÞ)ô’ —tz°0{ûÆ4ˆS¥cÁ4ȯÖx0 âìäïdoÃô cªwMx€¥ÇÒ_²6¼¿£×gjŒzõy1¿÷¹×Ë;…>;èƒ_s [P ±ΰðøl×b¾óëY|*‡>0«OåðŒOøÊпs`>Tàä³\]ÞÌ×tè•7ó=0Lºà/…E/èÂ7•UW±éPÔ³jÿè~«aF5÷J§p]ðaiÍ’{ÛZïõ®‘×ò{ŸfoN¹Í°ŸÅÛ„‹ÉoBáÑfûýæòKR…Fùg÷E ä{4E|F¾gsŠiÈwfv¢ ù†ÌÀ'†|C€sŠ|C®–‘oh¸PRyiH¸Àe)/ ™{ذ äâòÌȧe0Å0ä;0@¾±ëc?á@ñ9ˆñžpÚ”¯“»ràS êTÞ"ÆbúSÐþú²’ŠöWŸ¥ï Q˜ßÌ{jº)îåŠ ÷rÅ=5ôÌ{jÙ8“9ÐLÒ7ÞÓ¿/P¥òž–`K”÷Ô‚ûh¼w[ÐþÆ~cûÏl¼wY”™†tKT£¸§V¬¼w¤¼§e Ñ\ˆct{.yVq„S>Âx/cÀ—2æ»ÊÐȺ„¾ë(}ª¯£ú®£”ú.‹Rßu”ù0ˆå>¸Å¨/×bÔ§´Æ¨ï*£ÔwY”ú®£èCX”™®³+4©²aßeQì»êÙïõ{~ù0ÃÔbØw¥Ð¤atŠ)õ]… ø¢2ÖQfÊ+2]+öåjûÒ!F}¹Öðp€…¦|"£¾«ŒR_>•B_¾z+`5á«Qfº¨Ì”ëîËÇ÷]å¾|¦. ^㾫^e¦ë(å¾Ë¢ÜwY”û®z–ùôܗڬܗÚîK½ÜwÕ>°–ðõ(9]e”œâVüRƒA~W5J~é 7<@kÞ÷òZÁ/Waà—[bàw•Qð»,Ñ~Z>Ûoà— JM×™”ûrëŒûÔ²3÷]z€Z„ûÒi û® o&‹bßeQìËÕDóY$Úï–}z ¾Ü:£¾!ARÅæjF}jy‚úr½•.D‰Þî!Ôw5ˇSF}×QJ}ÉÍJüT}¹ƒ¾t1_öɘ/ßIa¾«z'úòÀ˜/Ÿh½.ò]Õl›Ç…¥Óƒ°„¨Ç/_C¾ì”!_jŽ _þ9ê‡K=àyèA”ÙχO†|©b#¾lxç‡Gƒí Ûïµöáñ^>µðÞUÉ,ñÞeùrÀx/ŸÉx/×l¼—2Þ»ÊÔþáÔ h¡ßîÁ{W™y·Ø€ï*±1›‹Z”Yá¼2à»,e|xeÀ—k6à»jîõëõåÚåþ½îûbÄwµeï÷1†|¹-û˃Mâ¨Ú/ŸþÂ.HA}C3”gꛃ,Fê[ƒ“k£¾]< Ô—ÄAPßžÔÔ'™ P „>E¥ßþ-t¾ó>§Cç{žb¡æ®ó‰…‚œé|ÅÑþæÐ§–jó(è|r :_®Y7Z{ªë‡&ôI‰} }E‹þæà§\šJ¼5údÝ8ÊĂل>±Ì›ü$8SúòQô g õåZtç¹ÄhR_.aRßó`Ë\—ú. < =è®È™Z–Ú©OÊXߥÔ'¤I}¹ˆI}RÍ@ºÀߺ-\8©/•€Ô—Ê@ëKçÜ—Ë|9ÐÃçÒûrÓû²Å¿|.üò¹V¹KÐ?¿T‚_ºäüR½üÄB@SôË]`„<Êä²l1½,eŠ_n)~ÉsUüÒïI¼ÞI¼^(~ÙbzY®GÙï*cŠ_ºç“>Tr]¸@î4¹,WcrY:È¿ÔbUüÒy ø¥JVx@ £>@ñËG™â—(~i˜€âÍ[ôÀÇŸð ÓËòÉM/K£¡j~©h~©1ÐüdìÃ׊M|Ü…æ'1¹, ©üÒ° É/Wl’ŸXxrºðòƒÐ¦ ¬™’_ Î&ùEó(ùåŠ~©5”ü²%| ÅD³h1U¿l1Õ/eª_ܪ~ɇ7|@=/}àï2¯Z¡úe‹©~r­:Ä9Sýòyè¯'e¿\ÆD³\ÆD³äd¿¸S”ýR‹!û¥š }À]PÙ/ÿÝ$³tÈ~é^Bö‹JÙ/Ÿ9<°ïœ”ýÒÕ‚ì—<€ì—ÎÙ/Õ Ù/ùP?|¨ô!,&™å3™d–ë5Ù/yÙ/·Æd¿\sø¯ ûeË‹)‘ßMÈ~éìýÒ¹TöK-náÎÝ–™åã^AöËgÚ>%z(ú´®^²_:W§^d¿t û¥ö@öËez»LëüÚôðçؾý|@øKe üeË;?z „¿\¦ö¯fø€öÌð^AøËef¹ú ”¿\b?ým†åRþR=PþR=Pþ’WPþRÍPþòQ½~ŒáëˇõáƒJ¹ÖýÐ'\+HÉí/g‡¸ã;<€ßÐþü¨°óQÀßÒÕª) \Ö]Aß‹ ÏŽN ò¬/£ä)óƒ;ȳuÆ:2ȳU'F€Sk á#üµb mþ$žø³Õš¿%ø“5vYñS ÔEÂ_œð×[hð×,;|°_CÂõ`¿ÖXÂ…¬ùåX¢_›Œâ"ú5e%ú5d¯÷O)³® O)3¯(ÏÔC¿†ìûD¿Ö©Ÿý¢¹ ?‘íɯ b<É/NCòk“ÑŠ$¿Tà‚ä'z7è.ý¢É†~éŦ¶Øõˆ~q1‰~Ñ:¢_øDô‹›Bôk‹²1ѯ5†âýüò‘ü¢¹$¿¸$¿d1¢1áž’_4†ä×£‰I~­3à•ä­!ù¥šé‚Ÿäצ‡•›ÒQ ¿xH~©Ì~¯‹5éƒ÷`’_´äO%É/Y@~xü‰}1°û¢Û“ûZe€1¹¯!uxp_\>‚_ó¯-~ Y®üZE¨…ƒ_ a¿z~1Ðü¼‘û¢“ûâz®p­£Ñ^@S #侸œÆ}^ ±O^ÕC`_TKì‹KNì‹—Ü—Nî È}Ñ#È}é\áÏEØcûÚ@L£aŸßÇ>ožcŸw=Ç>wʱÏo‚cŸwrÇ>wÁ±Ï]pìK öùàØg7ìóÞìkƒRľt°Ïoc_:OxÀ£è{¬c_*h Ÿˆ}q.b_²û|¬öEk ûÒo SxMì“Ík†À¾T+°/în pçˆ}©u@¦¸sÄ>Zûâ~û¼ûÂbŸ¿mûö" ìKGû¢û¢ûÊC]˜ØׂØçï1Ç>Q8öE_"öÅU6ìKÇÐ>b¤¾p“Ô©/Uêó÷˜S_\PR_\ R‡G‡¾h/¡/î&¡Ï[lÌ—œÌÌ—œÌ݆̘ÌG‘ùâ“ùÚä• óŵ_.ù¢Íd> ”ÄQãšÑ9óI€íÍ|>ñræK-Þ>!Î=>znä ˆ|Íïñŵ!ñ% =ˆŠAKm1Óˆ/ZGâK%@|Ñ^:°Kà‹›@à‹KCà‹Š |Ñ­ | ;Yð¥£è›c¼çÆp/®q/µ¸=š¸G÷¢%ĽèÂÄ=¶í/ìrèg1Y÷;Ë ü†$õÁLÔt?y¢QºŸtƒë ûµM º_§ÊÇ`Ïî+ì+Ù_—ôë)!ßYöS Å8Äz& <èþ%™áž½¸ˆhÉdÑhIÙc’Â=“ñž²Ü%¯ïS ×åчdÙŸÄKvð™,ý’ŸÝ?ñ3â3ẎšWø]¿ñ™,ˆø #>{¥`ˆÏd¡aAÀd²T H„|& B>“!ŸÉBj,ñ»~#\2, ùÌ–ýã®…!ŸÉÔ jZÃÏT!Ÿ© B>“!Ÿé(úÀáu6„KfËþqÅÏdAÈg²ÔA¯.Ýï² ^òX n1ä3•AÈg*ƒÏdÙïõ{~ù0ÖAÄd² b2U½bÄ|&Ë—3| !“É‚ÉdAÐgX,è3ÿÞ?n?×—+| !“É‚¨ÏdAÔgxΰÏTæË‡õåÃ>S=™ ‹…}¦ßûŒ>ʰÏd xB&“!“1ž0ì³=\û˰ÏTaŸñÔïðá#쳇’† ÉdyWi=ì³héLö™jùôÁÃ>S=›Le÷™,ˆûìÚ_¶0ð3j~?|°ÀOY’s~ú[È?S­ü /ßð€õ~yÀÈÏT¡“©uýŒ2 ýŒ2 ýŒš-ô3SïZû>1ö3<`ìgª±Ÿé<ô ,ô êAädœÁŸqƒ?ã(öKûË­©_>0ø3Õ‚ÐÉTÁŸéÜþL¦s‡ÔÖ;G1ú3•)ããN1ü3YÚ}¦>°Þðe=™Ê,Ÿ± â?ãZ0þ3,ŒÿŒ£ÿ™Ê ~2ÎÅøÏdió"€úXâ éL_>04Y@™ŽÚ3#íÚ_>;c@£ž>°P¦z@™Ž÷3Î ÐTb½Oƒ@Ã+FF¦2e|xÅ Ðþ¡ý]e–Ae´Ù‚@Ó¹šJìùFûÖ— zš,õc~çA þ†ó ÐTóø˜ß!4¼´ ÐÔºý|ýa%»10[p²KÇ„ 8ÌÇqP`׆`ì¼br]*Rû=F;×Åå#×¥£F½|$×E7"×% ]ð|SäºÈuÉ®óy´s;E¬‹SÍpWk† ,$J§R$ŠæëÒ©u©ºàG­p¡ÝkûR@Q²ë’Xç"ÖE‹Wø€[eX—νÞû7°.¬óEtŽuq±.Yè×C¬[̸ëÍm¬sôf©LäÈðM™{ÎÍgt¢Ã7u!‚ÊÃ7×½tït£A9Îst6O‚àG¹²YÄ;eø¦ÌLîµ{²´0‹xÇâ)/¾¹ŸwôæÚdT‹ÞL¿¾¹±QQ„on¦WòðÍíi&¿¹=[%ã7·Ç11~SræÄ¿¹™&’á›ÛÓÛ0|s{nI†oʽËá›§Ã55öq{ˆÃ7ã4ßÜÌ4ÉèÍc`¼$›ñœlþâ]bôæ9ªÝëövÄY"z3•AôfœÁ›Û£-x3H#å‘S¶¨Ù ¼e¼¹7»"ƒ7÷ffðf*0‘©fDo†KLÔù<œ•2z3n[§è¾ŒÞŒÛÆèÍí£7·''eôæöL“ŒÞÜó3Q§T‡šéCÄ…"Íe*ƒàǸuŒÞŒ«Ãè͸3½Wt†OÖïòõcôæZÔr½¹O>¢7e¶|pî—Ï8·çŒeçŽND?Fú_p& 8—gµµÎýØ– À)SG¬¸ƒñ1€3ZÃÎãÕ¥ßéQ ´Dg<ðŒàŒö1‚SÞu°Ð‡h!â7SÉyg÷µÂíc gôQÆpÆõc çibäù#é(ÄpÆÕa gïwÚ–Üâ>ÜK÷8z{§÷ „pî‚\ù=+C8Y«GpöÂY8#8÷bT #8ý{çöL–Œàô›éœÛƒ–ÁécµGpúëœ;¢( ºðºîùH윛ÆÁ™ÎC<¶‘œ~Á=‚s ÿè¯1àô[éœq.FpnyOþöo àô·#87ÓÓ1~s-&`Aø¦?ÿ¾Ç zó™Y¸ÓvŒ;z³W—ûùèŽGoF=ŒÞ Ÿ½yNþäE{k{Žxàƒ‘GoFWdôf:¢7ß FoÊûçFôæZžÙ%|ˆÃDè£,½yŽ÷¢½d©>b=½¹˜DÜ£7Okƾ))÷j~Ü\Fãá›qó¾yŽÚ\Ægó¹xž¾)‘\°À‡¨™ñ›qM¿53~3¼²Î¸ê à Àéýµ‡ ̃ØÇ(‚ðÍð’á›qÃ7ãn2|³ÇrÑâ“Lò̓µ‡ù´0g-û±]å{»]­ýê—79 ÝzÃZxµ$¹Zlãìch¯¹´ÁaEÖõ컚3k%˜¥î¡ÞÄ‚ZáÀ1Øg˜²áAÅÎôÂüÃ,ØùL)ýîÖj÷Öú¼6H–Rͧ…Ž^zPñõµ>p¡VkN}úC‹týf%nÛz¬úŒßs™OaYÓœjøÂSºðâ D}éBÅw˜ú¾Í,^쎪NMt¬úê…ÓKa’CÕ=·Ä‚-Å…>p©Ö±À‡(3–Y*F›úÎuÿVŽ›²‰,³ï”õˆZžnNq÷³36Þ{Ï °Ò)û„VK-tʾõ×Ò^sª³yEwkÊw³ôM§ j¦ #P-æºV-k^W¡ìaM6·>.MXÞÆ®FK8`ŸãϸÜ¥Ú^{ ø¤ÖÚŸûTûæ…N\ǺŸŸZçäó3pvõ¡0¿g­{ØacymOÿñæ«Êh[ò@Se¸¨ö ~V½‡v +­ÄQð t¯¹o³lôˆ6lÒh^›“. T¼†¹´Àе© ûÅ¿µÓä¾­òV~¯ÖÉT¹X%ö%¡öZÌ'÷»·×|ÚæjïùÄM ŽesH`=áüîsš…^öeûª–õµìn.13kO·öÚWÀ:è6:¨ƒ¸K£Z:Ê(Ýæ¦ ]&™ÆécÙæÒÆ«Ž±Ì%n”Tà&U6žÖmì’ÝénÊ|}­œo»*‘×ò{ݸ b”›_.Ìþðu„k3ûfßCŸcÙóäcãœÓœŠzèBÔC˜U·®§ñkŸ|êz+;zþ*õºÿòZ~/¿åµ\®K¼àCx¾èÃD—Xc}Ü©5'(V¼Æ‡SkwÞ<Î;\ÀÅÙán•lž²ó$ ž7óõ(È‹ù½]y1ßÐîÛæ> Ë>#ËâÜÇæoU£¸­sA²þö«ïÝé”= MóeÞ–·òN™ _ ¬ò¥h] ߈å@¾\ó pvC¾ìƒ!_Š[òås ò]g¾ gæ± Ì—"}×™öG= /ŸË /ŸkÓ?—Aß±p{(PŸZpP>œè»N46BzÀu €¾Ë²„Î3úÔ‚ùœA_´Ì—Î æKN‚ù.KhY`ÇŽô8ùØ÷©'ÂèýÔ aô¯å‡ø‰^z@/Á|ùÔÆ|ùÔÆ|ùäÆ|éä/=h~ªð`Ç⢞jÂë L\“÷‰–=èNmÌ—ÏT肟ɘï*S ÂÅ1æË­1æ»-›^áRú@ÇË\×Ï5ï–ìÁ»„óò©eçÞFJF¾|Þíg™öÞ]ψ/;mÄw|,:DËœtˆÍYó>õ¾ï½_>ße)•.áBñå3·pgná[öGÏ3äKnñ]'_ã£ç5º€S÷p–aè&#¾«H-ô ÜØÞ^fÀw[Ü•/;iÀw•Yãã6ò¥ö ñå :–/ ù. 4ÏdéBó ùôÔ˜–ò寄<ù?î'Á/ŸÊ/ŸJï*Q*b ºà:&]K>FC¾«æ±>ÆC¾ë\ônNº@ƒ_>·ße)÷ƒ`À—ÏlÀwY´e…´ ¡{cæä}‚aû6îåÆl:à§Þt ,¥Ü]Oh/ÿlïýèëåk`¬wYØú8ÍœŸ–5>î‘Á^²öâä`½lˆæÛ¹õ®ßí½ëìÏO˾Çl°Þe‰öÓòÙ~Ð^>·Ñ^j®Á^ºG ½\±ÑÞeiïU =æ'ë¾I`½Ë²Æ}KÀz©âíÇA†z¹H)÷àÒËEÚóq„ôîß›÷—ÅHï²Ìùq—Œô®zvçS â âÔ»ÊÐXþʦFÔø^ɞؓÆ×Iâ¦ñIèä þ3O%Á0ÐøÞíò4> $Týô›Py_P$>¹!KSÈ$º²eÜÓj6Ä9“øÊÃ9%¾" ʘÄW^*1ªð› ʼn<&†ô…O,SøÊ»?¾"× iŸÔ ¡kаÀwý¸>1< ð¥"&ði)¨Ì>i ¸C>i .>éÌl÷˜O^­‰c¥¼Dè{R ÕFÓ÷ä ‚¦é{RÆú1õ=©gÊàA)TæL•9“÷dæ[!Ä™¼'Õ@Uy/5fуé²!]xœþL“+³//] |bÐáLà dL|¥pc |©=øÒÅ—|€Â—.Ž*|Éo(|byp |(LbA‰/[L %>iõPJ|ÑJ|b(ÜsJ|R¦î³?Êô1¿Á&ñÅí¥Ä'ÍÃçpH|¹ZºÀ=G(ñÅÅ¢Ä}”_.c_Ü`J|róð-ù *-Ä'7_—Uâ+o†=íYü³ |ÉOîA‡¦^×Ð ðùsH}/Fê{¹bÓ÷d ¡šgú^< Ô÷¤ „·‚ö» ·fŒ(ð‰efÚËu@à‹1˜_t{ |1 Ràï¡GBà˃zLàóQ™ú^>¹é{R¤CÏ3ÜiÕ÷ÒÐ÷RS ïÅXN}/[Lß‹}ñ£¾—.M£Q³©cé‚BàËí1/yO,PšùÀ×>±¬KáËeL ‹w>¹ÀLh _\`|RÍ̼wYèBTlú˜M”~sÜ;Wf¡ð‰¥AÑ{z>dЂ¥ Tø’“PøÄháPøRŸÂ'GUZ¶ùôâ#1>9׺£qv“Ç|òA…O ÔÔLá TàKçÀ'8=é_|1_¡Àw¦v?hÐyŒY,búž( }ï•ô²Pͱ°½æA: ú^*}/—)Ú˜Ç@Ó÷t½ô½|L¸Ð ÞÑ:}/dú^nŒé{é “÷ÒA›0œòž´ï–÷Äb«&LÞ“ßõ’÷r “÷¤^È÷rºðP~„¼—˘@–Ûgúž”iÐîLßËÓ÷Ä2€táÅ9ú0úÒ]¡¾—0O'Ý_y\'‚ÂW×Ð ñ‰…J¢écR•7ÓÇÄb~Sâ“n=a1/ŸX YªÆ—ë5äÜ,a™X6”BӸć~i|¹Œi|b©h }ð2%|À¹ ñ¥£ ñ‰¥ôLã“×úÊè—¯©Š|R‚Ú!}ð«‘/]uˆ|oÿùò¹MåKíƒÊ—ÊTúº}@‹ÿÑ6FÒ9JÄl늘‡è£¸'ýäÍò^Z±IÜ‹u”Ä=YšF–XNGÍu¯ü$ïÉŠLsÁ{±š‘¼«/É{±€¼ ô ør--¯þ&ïŲ^ò^¬$ïÉN*sqá1)Ä…ûc95/Õ àK.øb¹ ‰/]ÐÙ°¨,4ÃP-ˆ/µÈ—ËL,§^® ®y¯%òÅk"_jO®Î†êV*ׂâì`¾Ôf0_.#Ì÷ôÅ@Õ5|95uÃð÷ ÌËÑÉ|±b”Ì—Ê€ùbé6™/‰“ù²¥b)2s“ùbÑ:™/Ÿk™/yµ—/§.WXg\-2_\Q2_xEæ‹“ù¢Åd¾è¥d¾\¦o.}g™±ïsôEB_Ü=B_ôB_*è‹«Cè‹ä„¾¸3„>9;ü|éà |ð«è‹ënÐçC±/]t`_'ïR/_¥¾tqA}éPŸô| õñrùRc[4ÿe'š? û¦C¸Ü@>¯vÎ+·q/Ã=ùý^¸—np/\â^r¸—-†{±œ™¼—<êl¿_ìÎö{ûÀ{áx/Võ“÷ÒÅSÞK_.ŒpáŠèL†öÒ%ú爆ýá`/·„ÍË÷›ˆ´—œí¥› ¸——Jx `â^zn€{¹ž¾ït%ä½Ô%À{ù\ô!Î>à(ð^\.à^2”zÕ ÚË–æ‰qž+š3òö’—À½äp/×¼Æû©ï%˦L÷BÞK xO_$!ðåƒ÷ò1ý¡Wh1x/.Í`˜óð>¦A„½¸„½p‰°‚°çë=²" LÖ®´8d½81Y/|&ë壢ý,вû½¬š¬—š ֋牬}š¬—Zø¶7»ø† á!›ßÝ<¤ssÇ/éÜÜ ÏC:ZîÎÝ]¼_>÷’e~ÞKð^XÈ{ÇÂÈËðS²˜’È—,@¾lÙôŠ–ð–ùQbÝW†È%ˆ|ɨÎâªÞ—õË"_² (rs aG¾h‘/Y€|Éòáƒ!L'¾81ˆ/BâK@_²„´úRÍ€¦TÐÍö¥"à¾èç0Ö2\À1ä¾TД,à¾d÷¥zÀ}©Ì— =\x//—ø¥2¿°øù0ìþºñÀNIy`§Ph^ËwYØ™ŽB`§¿¤<°3•Adg:;¢"SÍ‹Œ£Ù™,oË/pì”Ù0.|Yë»,ˆ‹Ì–M¯hAd§O<²3• h ÚÛeÛ×Ëb;Ó1ˆíLÇ ¶3YÂ\›>°DG¦3!¸Ó' Ý™Ê ¼3jÞáCÏøwYJù´Ô»w1ÀÓ'[á-f„gø¹Ã5營ŒðLe¶OŠêñ‰Ýï!Ä“sHñôjâ)_@sˆ§w ñÜŒ"ñÏT!ž›»;{ˆçîM¶ß[‚øÈ¨…ž>ùöÏh#<\`A„§Ÿé¥˜Ö}ZÚîO¢<Ä3!žÉ‚ϸ ñ c<Ã)Æx: xg*ƒ O§òô«eAžéç&?”;ÆÓ/C<ÀϸtŒðt"òO'"ðŒ[[£ýz…¶cQDrN‘Ü]Ú+µRý±l-2ÊÛ$Ò^}¹M²gk©Ú³µ´M¹ÙZR&–ßÍÖ2„Ô“µÈTà#Y Óz²?ˆ¹ZH#WË¡OsµŒ‡YWL“,“<©Z¦gaª–Ùœa V…°We­ÍÈ)–v {U²fÈ›’}:¯ÛËÙg ëIö†\ª˃W']±Jï1K¥Oùè ŽÌ#]Oò\31‹ézr¦Œxz*$¸ƒ¬'Õ ²ž¤±Á=âUaq€—!žXðµˆ'épR¢–*.“…°<HFÔ¼jï”YTq ƒ= óêâ¸FÌ;“ANP€y1Šó$±í{¥k‰†˜—ÚÌK× ˜y©ˆyR3£€yâ928óy6”òärŽ+šSNŒ[Ê;srÞn{2¢"Þ”Wò ò¤mT茑äT0"Y2×=‚ñä ŠŠÆxgŽÎð`<ÉÜS²¹m>SÆ“©¿!ÅXMÈK— 'I¿p™yrÛíÈ;ä,dÑú•¬EjÆÃÈK×”—:ƒ9‡Ïs›ùÀL[¤¼ä(/u"P^º2 ¼\Æ(Oê¡Þg”'çBP`§~ë@yÒ2”—P^®Ç(ï´‚ÝS)OjÁyOî 9>Œá±š&Åž_¼®©ð‰çÎ}›<ºø¤5w!ñI§Ã‰/]wH|é Bâ ã5_ôüy¥lIC$¾Ô'}x=8Ó2ñ¼^_êûøRÏÄ—ë’å3Sž^‹ç é”; )ŸxŽ;¬"_º›ùäjá Èçó*j|¹\èÛ“¯˜@–†h|©[@ãKnBãK·ßéˆ|@ã«“év ñ¥gQ%>ñ e ñåjMâ“gŸm ñÕÎMU¨ñÉ©ˆÎD2é[¸ãPù’SPùγt¯âKnRåˠч‡ÉTê5›Ê'W³QÓ³9Ñx<æÓT>±Ü©R´„ìíç‰L";O‹f&‘ɘùdÈÓ~õfÈK×"ŸÔ§—î½D¾è3ù¢ÏPåË‚h*_ ~Tùb–O•OÜ„"•OºHZ™F&·©fÈË×2_<ò”ùÄ)™È|Òin™O.S´˜Ì'Ýq ŒÉ|úĹMæ“;ÅxSÓù¢{<§äèúÁïÖÔùtËK³›yìfy¯tœÏ3®¥zÏãK‹»é‡Ëx®^¹ŒG¬ ˆ2žËoIÆ[ðÔ‚Á$ãÑB¯;VQÆëAY/`¦ŒçKù(¹"^¬æ£ˆªx.CºŠeØ~·¸Š×07‹[<7K² 7K²ÿìÃÜšáÕó: ©MR¤6IeÆÇo$gIÇ ;K²|ùð†-Gn^dgIG!;K*ƒì,ÉòåÃ>´Ìx—e~ƒô,É‚ô,aaz–dùòéY’éM’éY’éY<ÂÓ³¤2áC”œW ÍnÒPÌË–ýáżd˜—,áÛóåżdG™˜—~CÌKˆyÉ>¸åÓŠy© ļd˜—Ž‚˜eö—ûËŠyÉRïû@1/Y æ¥c æ%KøÀ£ …¥2Ã’bžåbž—q1/Y>}€š—~·÷þ 1,[öc æ%˧.ç% ݰPÏKèyÉ=/Y ç%ˇï—ô’‚^²@ÐKzÉòåCùò‚^²@KzÉA/YTÑË¿?} ¤—,Ðô’¢^²@Ôk\Üì¢^²|ù@Qeò–F²µÎ÷ÊóÑéDli„2±¥ÑG‘8ˆ[}ñ'¶4ún-×B©âO?ÓNDý¼g\;Ñ’+‚ùÏ\Ñz>öF¢åªÈl^¦ŠFéÚõÒå‚%W+òŸ¹¢ß»îwEé^ä[ó/ßd©I }o²ôÈž’¦ ÿÑ>1²[gù£ ™¬@ýƒ"bÿÑ6Mû-ý¤{í÷½·žùÉå[§ßמLVSÞGIjºvQBM© jºwdBMi%­)ï¡Äš¢ kºöcBM±‹’V”öPb=^‚Õ佘ð4¥”¤škÿ$ö¦(ƒŠî½˜PSÚ?IkÊ{,±¦(Úþ™=–ÚT6ùO¾ÅÒŸÍ¿Ñ{ìþõ†â(òÞÿÌKmjXÜð-–þþ“:ÿþOo¬t˜úkc%±ýOÿßÿø‰+Õñ6VjòvróB{5R•o»Ø|ëô1ÄŒí‚9ã ™³íjsFÙ-Ò^ï»Ù º©)ìnk€äÛºMöèLŸ„’([Ó'-~[—³bÜ'÷ÌLh{úó¨<Ðeƒ£j–Wã¾eŸ¿¨>Ðý§Ê]>½³Tt³iTÑT›ƒÓtt×K”*{™&Üe-Õqi­Á/ý1æÆgôcÙúa]'[Væ}TXoAf½þ¾2a\šÄ å‘jñq~«6°;2‹÷W=XrÁqY^õ`É&Ì,]¥ýnh•ý…✧3¤¿S¥¹¹ö©¼¿K7…,²ùI1˶}ô&Î^ÔƒõŒê`—$xÇ"s~Sr»fF;…ë§Ês&ÙÛ¼.U¦¼K¾Œ™òÓK›êÕ™ù¾(£>¬Ò'ÔË^àƒ$LÙfSËäŽR½HfgñÓ;MÑ.¼ê¼¤õ‘÷Ü’KnT͇R™"ýXÌ%5È®ç…T;ÂÏã'nË}±ScÞ(N™4ÒE(:NQDPíèêTPzz… е4Þë”ñÐà®AR†ÔØeß-y=ž®eó.»u‰S›ötÙGBZ¸¸ Eoæƒf†³³7ñ¡xfûÞšÔQ+»gëC}:]« ùxj-A»½oÏ«šroð@¶Bó@ƒ¬æóèªE>XÚµé’MQê)Hßv,ò-p‘ú¹¿6Qh¬¹Ë¥”2qK½‹ò1ñ»»¸ý]tó w®Ë³oXoì«êmò•^½ËÞ·ršÂgc˜çÅÏ›2ÌÔÜ!­:e:ö©èC6›8E3®ô![Ik;ìhÃ&L”ØNƒ¥’мû€…›ô¡q3§ÈDXX—ét½ñûž­-¸•S6o³'Ìtü>ßGoŠop,êt‹ éÓ\ÛdZuŸuªS•IcÎõv›½Ó§díÛÀõ~}¹zž†£OóAi´>èîèjЭ„—@,Ī/ãKûzsjphY²+œ<+¬fÉÞ3wó@¾4£½«µz·Å-úÍnÔ‹˜Ÿ¾f“æ½ìœkUõ©>öí×YœZ¶µ_n†´ý>êQõVFqörúâR$sœêÔ~&yÂìjnk¿ WhÛfû7Çû-°•Ù8jêþ§²ë»E÷ôóZ–‡É_°òR¾ž!/e¹K‹€ó`˜ ’V¨Ã¢.ȶa)ËnSƒœ=é>rõ&†´ñ´Áûd=vHî—™‡½ñ˜…)ÈÇ.¼°,°ÏÜ0ž]ìêÙc:äµ,N5.þònÐ2ÁGDzõNîiv¼æ‚Ȧb·NuÊwoö@-Œ°gn×íê?PD:ìy*(2«úÔ™Ùr¼túXŠ]=[Ð;Î{Ùž‹:òV~íºÀÍ++uP:û2'Ž2äÎÙ;w80üBàc„ª;Öº"apR¦ñ’K÷ÐûÄTBgÜ+vŸÝ!ûuêêÈò:ªøð¼Lª>Î[Yf5\+4äü^ýA^Êx p äT{Jíµ õ©0xTó@¾ ÙûTó ^+£ÚÙr%ξl`Q'PÏ~Í'>?C¢peDx}jâƒLJÐÕšù º×F‰bs!ÙVeê´;Åd$£µaOSֻݩÁ§®fwŠCÉhðáx>Ñ>óA'R(³_'¼ŸôÇæB¾ÂüXöÇt^ÌrîÍz»ùPe+0k_‡2Ÿ3?å;M±2x8ΛÙÞ²\ÇwÞsíÇ5‚Žór±ˆ#ÒèËæsms¡H<±=@gL²Gª!£Û±è\H·+:^›Îû;a)+OY†¼˜õ™|.‡y W÷e˜Ò1ñÜBfYƬtiòl.äûÀøÇŽÊ`©Cн~ĺø'•|ÿÂÞJä¾WFð ü ?üD_Aú€ßÚäw-ذ™Vp$ 7î;Ó n° î;üè‹tŒûÆÖ1ï7ǾØ8 Ô—Ô|RŸ¼X„úžó°®Eê{$pâ…EÁO>?”1ð{õþü܉)É}E®=ª1î“I5&à>Yà‚¸OŸ{Ó‚ûäcfî“÷3&ÞÆ}SfÓ<&àWS4ü"8ä7›LdPKþ¬ÌCJòkS†Sjš½úôä§3p0¥’ß<¯JÎŒü9û´ÔÈïÔÃ$Z ¿)óixeä7ÏèÄɸ’Ÿ<}6‚üæqŽò›óanbß™âð;Õn?‘RÓ”Ù)7ð›"ßbzfà7ç™-Ú@ð›".bÞcŸB'æÖÆ}sN¦œøMù¬°ð›20ÏüÎ1ï‹ß™¿úLÐÀoŠ[qjsa ?˜A©é°ÿ¦Æ}S%ÕÌ}s××YK¹ï¸äÝĸïTìdjÜ7Eˆ ÷Í-ƒ~·i_Æ}S&£˜W÷MÙq óRã¾)sF¸ÝàÁæ¦Ðྐྵ›£¶qßÔp*0bÓñisòjÜ7%Èi€Ð”û¦È°À/㾩;¨Ù¹”ûd @Çî›"ÿ¢‡÷MÕ^Ñå>=ÏD[ü¦ \äT¿)R.° à÷‡C€Ÿ T@fØôHÐ9,ŠMSüšAÁO/߃jü¦®¸ƒEÀOF.\ß#Ã8ϨI¾ý€e@~’ìg6ð“,Ü}€ŸmâÓ ÀO¿âÏày€@~Ï™qàCÈ/ŸËÈOÊØ¬ÉÈ/ŸÉÈO“i‚͇÷-ÎVæC|ûû 4¼€6§gqmÙ/}nüi¸ þ$T"òiÁbàô¿y€?Í4ŒšþÞÅ,³„?Iÿ6.ø{}^@ø“ :hÙöÙî!¬þÞÊ×áOÞÎvË ò†Ã, ð÷.¾ž ’ÞSgПôõ¬4tztŠõáï-Œ9'ü‰ ;ƒ¿÷åןf–Â…óJ*8ÊØI‹¡Œ±“œ ð' gПn…‹ÑßÛ¸dô'ëKF¯–7ú{e¡žý4ø{~#ü¥Óþ¤LÐrLoâ6@ ð'sŠ2†NgÆ€oû„¿wa_P²ßÛ8¿$ûI ¸HÙ/ºž±ß+r2þnÜ$§Á=û½ƒ¯w²Ÿœ¸â(c?¹2¸`?æˆ~R fÚ@?¹µðèwþã˜iè'§.ýÞÉÌ݆~2³²9)ÑO¾¾D~r&–1l’@—õúÉ^8¨ÖÈONTAuF~¯oÞIò+Úµ ð“ a_™ ~ò±ÏÀïœèüNÃDÖÀONî ðÓÙ"Ž‹{Öüd¯+?ÕÂÌbà§ûÏàL~¯¼Æ.ð“[Œ# ?y>^r¾‚c–ïà'I÷QÄÈïõl ¿SƒÈO¦ªø½¾ó)Áïõ}$ ~š¼eŒüÞìþ~/—êüDqÁ%'ø½xÉ’ûJÅfLe£%²Ÿ´,¡Ÿ¼Bžͯâ™wÍÏó úM‰SCjqJ~ò€£H~‘`’Ÿ`/¶¸¢äéÛ!ùɤk‡ä'ÎâHÉOb¡à½oÞÙ%?™XlêÇ'z€¿ñú¼ô'Bó€ÅèOø/VÐß™SJýiD(Ñ|Õ*P@Cö¸èïpô7åC!xKèï<¦œþd2‡ïå ¿¾}Òú›‡ ¨é9ŠõS„? s]üw'ÝüÍÕ©0ƒÍȈ~ºÌ„ŸrÓyÚ9yú-y˃ÈýórN ô›ƒ‰è'Ë`nò“‰¿¬ýSn, ¿VÜà7¶7à'º@ à7°&ɹoóûŠƒ_õ ^IM\æhà'ôˆ92ÀïÌ q¹Á}³7'Aã>Yï‚oà>Ñ’Ñ~‡›\4lš•ÁOPýà'Sã—¿×çÖ¿9\CUðXÄÓdà÷ºäð[§û0 ütRnnüVó™,ÀoJºN»T¿%i> ïø Y7¨l~ë¼z÷~rµ QüdšNŒ3ð›Û%Ô®>$µOÁÇô­æª< O".æ[gj;æÓ€hèvÖøtYŒù´…¨K£×ä|2ߪ•òŸ1ßjËå?c¾%[þ„Ø7%zgµo –Ô¬ös½7˜o*Þdµï\[—r ú´ 59…¾Ó<ïw.¼ÎP.È÷0žÓi«FF}§=̼ êÓË…6 õé§ç¦ÁŽða„>©Ä45ÆܥĤ—h¦Ð—o¯Aß©˜Ò /7fÁ…øÞaЗ]0蛪ž¡OÏ…,ÐwjYìš}êF«ä™¿Á 1*1é%&Ñ)1i7ÁKΨOÛ‡aĨO¿ò }>¬ÆaoÇÎåñ ¾ÜB£¾ü0 õ©W( Ð7e­å3…>­dÍàB\©ƒ ç GXSbšÓ•¡ïÔCÒô¥§ЧNQo¤ /U«.œö€é úÒs¦ÔwXà“΋õÞù´caÞmÈ7¥¼€780;ÙÒOï ÄïÔ<ðJò¦Lj†|Sº.!ß”Ú?w­Ä§ÚŽß”™&ï†|çGaC¾såÈF|ÚÈwh¿lô‰2lu!QI›ÂS }òħÍÎòi¿ÇlØïX˜•F‘Oþ~%òIÄHpÊK:b¢nȧí…èeÈ—o½!ß)Ã:@>½ÛЇ*<8wòb>}×ã#€1_ú– æÓ>‚a̧pÑÔ‡Îä`¾xš€|ùÂòé}Ùòi'‚6ņÑfàac>}“³\ˆÕàBgªs@_²}ç¨Ç•»Ç&r@ðz·‰š|8µàL>LÿbЧ^ÕºM„$Õ ªö\^¶Yì»Ê(óió“ð`ðK ïTó8¿Y|³¬ü%á½ë£ó óåkeÌ7Eñ‚&G!Èj6ŠjÈ—mc¾|¿lZ7áÁ`, #´W™\’ÿÇ[,è·W&½gˆ|Bs„-žÏ} ^wŒêyü—£žoÖDÔ{±õ8O>j)¡½Ì„èœçûç‘óT¥‡E8O4ðu‰|µ³ òD'ŠA+ü>@È“|Fõ‚¼Ö‡y²{&Â6 ò{|@^“°(3@«Åc0 ‘Î%dûÁx£l×ï„ñú(NkÆxšÅÑ `¼3Å`D§ž‰ìÆ{ù‚&ã­ù!ðêa›d&úp‰Oßc¿èɨˆ©2@Oô»/…Ï~ª¼'‘5¨BI¥z‡¼×ýË(OFQÄèRÞ ®±õËIòÞlŸò^ñpV„u>/Ã\Þ“oç8 òž¤ˆ”AÞ«ÜXò^{\$TyOä>@´1‰á1Ô=¹uWX§ ¤E¨{Ó?úPÝ“ÏI@)è““{°†º1›T÷"ÜÒâ:E%Do¥¼7}Ð3yopx—÷$¾µPÞkŒ†I²9û“QïÔã‚4POd÷Œzê9n POFbô_ê{ƒ!ÏÔ÷]©ï¡‹ó4;÷i Žâž‡uSÜëLLmO63„–moy„)0OÄÓzi{ra²´7% é Í—eà™ò–$¯y3å‰C)í=˜¡ÒÞ3·—€´WÕBiïé v¢´ÁlÔö²’mO>ßÙ¥€¶—zµ½2œû(O^sh{¢ÝâÞBÛ“}³0âBÛ“ËE¢TmO`œ Ú^g\"¤=y÷•+®So0m¦´÷x”¤=Ùë*¥=ÉßzLÚ“ƒy)¥½× (íˆ*… ›¡¾.íu~£¶Ç-l©íÉÍÃAÚ{˜'”ÒÞ3ø9É¥½$BÚóéÒÞË„q”öäT‚¤´J(¤=ÑOÙ@H{l†]L¾$¢™.ö"`…Òžnʃ+{¸PPöä,Tÿ ìU§R({º_àÖ)sL]¡ìéž‘v›¨ì5'`J{ç:ãÆQÚ+ËÙJÃ:]†´'³iФ½wyð%¤= ^†iïñ”ö:¿v¸´çª·k{•{Ⱥ¶÷23œk{I탶W˜E˵½'MÛ“! *|Œ†smOžÜ+¬S–µ3\Ú^´˜âÞp˜¡¸Wü;Ä=Yÿ7nu¯To”1~NP÷ä:a1u/® ©{e8}Á‡Å銫{ÍUª{=ÚX®,Ó‰Ö@Ýk0tqorFââž/^wqoz…º'Zù¾â:E¢Lâ^’Ê!î%UŽ0…­‹{2«A÷b‘Nˆ{8­I{Ò«ŸŒyªâ ƒ´—î-´=_³óWvX"ò)*_È÷º*÷» ú„ó‰ÀÎÊp,ìN"°Ó%r"Ÿ¾ÄŽF}òjE.?PŸD&±=F}GË’úd°À2& 피^whçvÝà'ÜöÚy&hXKð‹= ~òkM_læé±ç±æ¹ÌI¡†MoG"I‚Ÿd@g §Ÿ,&KKúäˆMTî“õßåÒö$ºS8pŸ°c= šT‡Å IHn_à÷J ì%îIT8UCx Ÿ¤®ÈNÙôy^à'KÇÖÙY&4å¾rfª˜mû¤N î“e€\ög.hp>,pá8Õó’¾sêÎY¸OS}ä%}³”Ç×â÷I zG<˜ܧõÚY4¡ÞoÄ>ñ= Ø'(&úÀ>Aì+§PÏ£ |û^™(£ÁFN&ñ^ܧ±ÐÐ üÞ…oRä¾tEÁ}ÒÀ'VôM]_˜>½È+útwqJ€†~å±EJà¾"A?y9Ÿ>¨Ã/ѸPÀ¾Ø³œâžt‚KÛ³¼*¿ôɪàrI{CA>“Ö0ª_€aO.û¸xO’«ÕÌ{S¦6Œ55Þ“;Þ3ïMI·v-ã;e^Þ>({¥ûWð^)jÒ^©Xa@Ü“Uzx:UÙ+×lBÙ“,2ýRöJõ¸'ƒÉµŽoÊì àžDMLoª²'‹qnàž”i÷¦dŸÁ'!({rvÜ({¥y¿òÉÓž•=]BŠÖÀ‡wz½ðA>Ì¡“ÅÊËWTöÊyÛ‹ùä!gŒ¥I{rÑ)Éô•7P >´þ!íÉí$Mš,&OϤ=ä #Š´'µ #BÚ“Ö°ø ß÷òb¾Üq íÉlûÉЧwÒžôt[H{¥4®L€´WšÇlúÐ=8Ót1é€o†¾´ÈÞ¤½"É3ô©ßø m/"p¨íùëŒÒžuyeìKÏå=©ƒQŸ&ïi.LàšÉ{RVBBÞ“Q¸yO.8V›BÞ“Ž…8;È{Ròž´˜bÞƒ‰œß8•÷¤C\«ùrk ï‰W¸ýÐ÷¤‹pížé{r3W^Í7uÅ'ê1}O<‡ü}O:É“WóåN }¯è;þ7§>uªå˜Îôz7yOzDÏÔ§• :ò^¼`(ïÅI}OêLš¼'«ËY±É{âAMÞ“ªfêËô=IàËûöu .Ð÷ä=E °,srgìÓô"$8¸ ÏÈoŽ}z3A»ø¤yà||RÝ'è{Ò^x }Oîe¡šg4®§¾çsŸí­ôû€W]à•îùYxšRî·Äw2c†’ž$¿¢7åã S¸ a‹dº"zóõ=¤½ù.×ù°Å3¼“ïF÷©;¶¸è¾ÝŒÀg)[RŽoîX–gpÔ«ÇÐï$Qèwãåò*ÐNO.º;ˆJÆÝIü!ÞéÀ»­‡Œ-O_NfÂw"'Ý+÷"†|·dä0ƒy ͼd½¤9ïöãKå€w"c¯ŒwúE²Èˤ3¾ê)[^ZÞå„,Hw2,eK¬íBÊ–§z@S¶œIÙ­ã{ÖvÍ>,×/²E>"#Ò )[Àœ- K"eK$d1uOæ¸3©{’Ê€¸È”-‘ø.tÇNfmi3Öé=æÔö¸Jdm‰”RP÷äâàCÝ“sU\˜¾2“i[$Ä Èx2]ÄdÖ–‰©’¶xjOÚR} Ť-þ¡•â^$¢¸');°fŒI[êøX·§sÅkÝ^<‰÷$ ¾–3iËðé8³¶L†"{Ö¿ÈÚ):¤;ÙË¡)[ÎA%Cž&ƒ¡â¦)[|[aOÙr†9“§l7ä©O;q¦~ÆŒ-‘«†[<㕯Û[Û›RÅÈØò_*ÇŒ- i¯ºÃŒ- ¦ŠŒ-ÜúÒ3¶È‡w„cF¾h2cKF¼œ%‰éZâ!`ºVï|-‘ÛÄóµxª.Û[YÏ×ÂïŒXµ‘˜¯Å“ƒy¾–TÛï]œËö6ß4ž°EÞF÷º½éÙm¸no{~#®ÛÛÜHËîÉöžbÉÛ*Û­y³Ýâ~T¿¯éO’Çkv áNVªb7,Â]™žipç*ÌÀ]í~.†lzšÀÝ”9 KánzÒI.ÍëŸyYbsEÐ&0€p÷&j1¶“EUÏÅv²0‰lœYŒ|]Þû~¬Ë“Åœ˜ˆÙ”É´1°ÝêwÌææ†¢d;Yöƒé+c6S,¨åãL) ³)Û‡¢€Qå&¨ž•e»8¸«•;Çîžî_Û¡ÝIðÏdˆ¦ÂÝÓ]â€v÷41T¸“÷2âÝ㙵(Þ=·ÚÄ8ÝÚXff;í<‘iwbÁ¼ÚÿŒ+fÓ¶úÍÑN¿PPuƒ"_!›’“à«ÚüæÊ;Óî$‰Jiwbé9çÔйkužXÚµ:O,+£]JpKíN·®´,b™™íD·¶Ÿt?­õ µ1ÙN~3a‹ÉvâYÑd;Ab(:PîĤ-l»g³ilûôUx&€=žáÒXVNÄ©®¢3ñNö€ ñN,o€þF_UýN~÷+!‹XÖ%á=‘‡ž¦u¹²ˆ…YRèAXèÁ¦ /[Lÿzæã¹TLÂËÓðÄRÓê<ùMù>LÏ ï™ ‰¢†÷†@à Æhx© 4¼'øžX0®Lúð:o™þ%– vW“ðb±¶Ixò»f°S ØyÒ…(cò—Xˆ_&‰eãsÊ#­!áÅzJxÏŒœžt¡òìðòQ&å2&ቅkï&V. 1¦àåJèBAÒ…êKèLýº,ûÇU1¼\ x犤€'®ú X±©_ù(S¿ÄBò\Õ~c †€õRÀ‹2ðž˜Å?tÁg´PðâLTðäm ‚‚'©| @@Á“£îÅyùìô!Ž2õ+·g+J2/U O³e°ËÕ¾t¡x©â†4QÄô;±´ vWÓïÄÂ4.ôÀ“ ¾ô€ÊÛóÞ¿M¿ ¨ú]Ümêw¹ è«~ô`8 šüõøg x¹Œ xÙb^¶˜€«>wƒU¿“Þœó²˜~—.&ô»\Æô»ÇÓS¿{bv]é@ÔcÚW®Ç´/± °ú]ªú]r²ÑN†ÌiâWòú]ê®Ðïr=¦ßåzL¿K] Ñ4ZøD4ñ+ ï’ïÒ³¡ò]:„¸í÷ÐYˆwÙbÒד²ušz—˘z—- S9ÏÇ õN:##Mû’22…z'±ƒàW¨wÇVçI‰u­Î“©&†9¨w2Ë….tOØ õNŠ ðê].cò]L–)ß=ž&›òÝãßí(ß¹Si¥®ßSÖ/mêÌ÷ßÿíüÐõ'0üæ%†~PËÿýY(ŽŠB?;ìOì¥ôET¯Ø ‹$ý«ÛXõ¿'˃E/²ÈT]>ª¢!W[ªÊ-©*Ù(õLä£*rU°¥ªÜUýkö/’UOíÔ(³ìuæÅºá÷…YÍw^YË÷$êÕw„¡õ£Àð­`~R@’Ýuß²ã«×tY[;wôš_ÖGlšœÊ°ž® PRE´äš¢«Ê¥¼.I9û¶\,W]^ÊëJ¥¼.Y’زƒ´\uy)¯+•òº¶DÍ\,W]^ÊëJ¥ü¡qïÙ©.Zr]QŠuåR¶¯ÉwæÚåÖ½{¢ñû­ñQîçûý^±Ïý‰þAuë÷ŠýÎþD,÷³C~²?Ñ?'ýò~6,þú“gçk¤üéÃó]ÓÜAy½Ÿ{(÷ï¿Ê”år»Œ“²y‘ÜÅÿý8}pä™ûßþ‹¤Ußêª3Y:Ô.]eêsf#çO§ŽÉ͇„7èâ¬~™2¨*Ö"JCš_¤ʰò·?zdXIº¥]¼@iœE‰œjtßK-R%€éœ[÷Ò÷Æl\*Õð{™¬é–×q/üV4Ň÷œ\wµÔ“OFå¨íŸæÔXRû\¨‹ y.g—M-õs¾|ƒ­MÊ,\NYŒÝªT³K–¯ÏQ>áÊ¢óƒ»bÁZnIÏt®Xª}@Òd8ò{ñ-kiØb ò IŠ­oG·ˆ¥þ"Ûr™°!q:ï#ïKI*¦eŽï–·eÅ:kÉwRô\¶)7Kã}äºK^<9HÖïœÙ‰°xeÉ𥥵-.¼zn„ÞHüÏØznlX´emý’sË÷nµÈçÔ!Õ0ǽ,§ÞMîù²Íf¶|̯rî†ul²Fû-Z vÚâÂ#'— =Å]¤.+Ò•°z*e(Ì/»ì;`ß!Ÿª©õ:X´ƒ~¯®v"ã@ኩ§~ìÛ‹|Ö Iã’0ùÀ§÷Ò&øšôxXóí›ï³T[=M«ø.ùœöëµë ™‘Ä©òpDY )EEbÝ„JÎS˜CJÖy¶i3œökŸ©XÜ)Ë{F³Ëmi¾œ§1“—¬ÜÑ{Ô™¬æµ½Wº`²á‡¬+ÙËZgÈ/ BñrpYžšÈ(â;é¦D5Š.“8ÇØÒzù3¡Do+_™òÊëb$|`èµäÂR‰™õªgê×]m›^•2ÍC#BÙØF{ªîP| 2½fv§š2¥•Ék»4+cC²ª'â:}y:Úk½‰íÄÖ>¬Ëñ2€É¿ö½GÂuœéÌõ ÛßÌž/…L–ö‡êÖðc½¾ö­³ééÌás¦ò¹U »<¼Ón#2©Ø¾[é<­éT­ ö,:5µ® ÜU‹qnºâ]}²Ï`0½Äö£-‚ÊGÙÂj-CýN·I·ª‹ïUF¼SU†Z–ËtA»eÂL·ªw(º|èyœ%³^/~5×±Ôï5Ǧ›Ë?¦¼»´}üò:làîÌø2Íñ¤§B úÛäKxz–彬o„áˬk5¨ž³ÖöpÓ£PFR¯Ë24Oÿ±L Ö%îѵÇÔåh¹Kjé­k»µ^“z¦í(×u“#í)óÕ<Þ]Ÿ%½ì²áüù_ùÞz“¼›õ}¾)ïæ·ØÍ²h¸‰¢¦:©Öd{×IÖ ápB’µèA ˆ¦ÃÈ—´Hb‹Žî¥³ºò¼ÍFñeÈåLclØ&ü¼Þ FqH˜­ ãXè]t1üÈ>¼µØ0É«PÍs Ò+º8¿¤G¸´j}†Š¼ uçÝ,ò‚ÖqÜŒ…Ÿê”¹ynžã¼Z²I¤ãAÅE–-ö7uŠ¢‹wô¶"ášTûD‘e:Ї¥?6Š‹,lGõm£øÀN¯E^ÒϛޔE^Òo¾w2°è(.S«ø¸ £xGæµ"hÅù2=XÐ0Š7{©”j -Ssdß°aׯY‘öÚ(ÎN[t£™o‚ —ëòS?À4»êVÍ\Ä香âjè?»gRðŸìjžñORôêkÎñOF:ýŒíü'¹±tÖBþ[/¾†“ÿEêßM²Õê×gÂ_[ Ë‹þšflTü5OÆIøk’ƒZŒµ‹í &·È‚ruL ê6],Ød+7 $ F¿0ÔŠmQ `°E/Ò $3Ä ÊþE&’%sšE‘¥7Ùì—4~’ÅbÕ¥ÿÚ7 TlÁ2„A¹¡V XPÜY¬$Yðy¸í¸² Ôz¡ T¸M° ´ÄæódÁÇÓf‘£ `ô}¢ X:àÐPPiYœ!QпA: JsžÓHP<òô):‡{ÀµhF‚â#WŒ) Ê™“(ê". Iðñ@3@<ïŒ<ë:ð‹K ”~Ö˜'üÇÈ£)ЛOŒæŸÈ/Œ€øøN„@± ã 0®/!P,ž¥H!PjfVXƒ@8°N(¤‹JÄ,¢Œc´6]3hÜeïR –±ç¨–zQ ¸U2jž?;~’Ã+R ß*R`Q/!P—+ê© r;ÛqmÒcm #ŠÅ>ìå\Ê©À›Æ€ÞMˆ€rj[‰H”Ž(ŠÅ‚Á‰€Òg €€Ñoˆ€gÅ#J{m10"`²ãT @9•Ý Xl´Ê16È‘}°qÔ4¿Æe @y¼Á{ @¹|(”²V Ú8þÉ™õs«óŸ´n¦ÿâBÿ|¨sŒ ALGãÒ.§uô^BL ?ª€òÖ5G €bÑ · ¿@5ý«‘› ?d€þŽrô‘×PSw^÷†˜NÎ8‡‘Zaó$‡@áŠw^"`CÖǧq}ˆ€/¾ZºØvê(K,¬9Ð'Ù!òÕ©" ®–Îâ" DgÓü j†W#C¨€¾PÝUÀ‡¹ú\”°M¼\”+õ.S”`G½ò®>ÜÌU@‚Î ØåñÖ~é* ¬­Ð§ÂU@ ÙÕ£¨Jrq«* ¬æÐI¥«€2…·“Sô̪®>Ÿò\”4rz*Weï@}9¹ (¯:«¤ è‰U]”,Äï¥> G¸ ¨:µª€šiNËP”¤˜úeÀUÀ÷A€µ«€š75ƒ`±«›«€rP¿d@Ù`ðR¥ˆ^uÇ@ÝïPÏDP’¢ª†ë* n ¨e(j2P¥>Ê€Ò>#CÊ€â4=p [ì* ÆïàÀ®É' ÅÀÉ|}ã4 ’s^J Xìó-A0Õ|}38‚`: (ç²I5Aðü ³y€ TÓ.1P" T)Êcd‚•ƒ`gx<å@ ,—(·Ï‚ 6â—à@-b‘ï”yÏ] |l;€À@½{ 1È© 1pg=Pîœáõ@éIvл–ËÒ‘n9P·Aµjˆ€ìHÔSÛ ŠÅfKŽ€›É‰€ÒûŒkùL9¦2D@dûˆ€›«Vœã\dÀ(C´Î’!psŸ$‡@/c?IÕ:¶ÅH ŸMS€8úöŠN›’—Sà¦Þæ¸)88rQ§Àíé)HÜ]Ñ!ÐÏDôûíèÇ}ÿyÇ@ž(Ù9pmß²Ø80 ä@ßãÒAÐ[ã ÈŒ«‚xr©© Ap{Y‚à~?Ô@±@U$nßSˆ èŽ:úÅpôCôûK9Pæså’}†çr ¬ô¸@P-pä@¿yä@4ýItôæ9.&YvÜÔ{7Þ›A‚~ûœ™ûÄApS­tÜÜoÇAÐwvôj‚q@pS²vÜ®’½ç8 ºÅIps‰Ÿ£àæF·Ž‚ûS Œ~â(è=ÐQ0,DAo³³ ç/Á‚~³È‚qr² wÑ ü_ä½K²î8’¤¹•»‚¾ëˆ”Ô g)%9©ý7ÕôaÀñëîÙÙÒ-R#¿Ž$HÄGS¨ A4 žÚ¿Ö,è¿Í‚n90è«Ó0¨ç¾YЃ¿aÐ7¯a0?2 v»fAßÎfÁœLX°ës¨À ô¨m|S,|¥ùhô,Ð0ø& h|A4 ¾3 溄_Å›sè 37 jþntÃ9¹p ß½áÀ®bDk¬bÌ v‰9ð\~3«†ßS¨ìs » ôdÓèY¿1ð«óNÀM¸X“Ni@¿J#>¢ô)8• ßkø_°ßqòCd³ß-Û‚f?PB±c€ùŠOöóÇÃf¿o][£®ÙÏšýœï¡ÙoS6Óf¿]™$šýÅÂ~»„‘Í~;7k7úŠ4ú2˜kô;, úJÈÕèw(»ZÐïÐhhô;)oò;4;4ùyÜ5ùÚ½×äw(ÞÜäç)/äwJp9Ÿ¬ šüàu4“´=ùÕÖ¡ %†üN~Äøaz,i§¹o±-¸oqRð€_ívŸÀ¯¶-•(Óä‡_1–—à¥O1!¿ÚÔ_-›üp:5™6ùåX&?üêšÉ¯©9xùSªÑ¯}óŒ~îzG/gÕH0ùÐM~8u"¿J9Â:&'AB€É“`—8xz³]B€§Ó–:è3nðóvÁ?'Ç øåŒüìöaðë‹“`ÿJäWv“¿â*4è—^ýr†A? Á&¿4#øÃ$¥þú7Žÿ¥ †¿%)ù‘Ùï¼} ±ßéíËa¿Ü„°ßé¤ ÿÞŒöósÖ῜MØïpذ_ˆ<짦ÑÏo¿F?¿ëýºÄèw*®HòóìÒäwLGò#çü$ùå0!¿ô(äw.ÎË`òË—‰ßa'„_ÿÊè—SúåXa¿®#öë³_`5ð—ëøËÍ üõ¡ ݲàïô§‡ÀßïÃß™œ™†¿Ó9)Í~‡óÛ…ýr¤°_—˜ýúWf¿>”Ùï´!ì— û¶sûÉ]*öËå û%©PØo—æªÙoWŽŠ V\2³ŸG¨Ñï°GÐ/½ úeÔýºÄèw:Žô3<4úåWA¿Œ“°_®zدë˜ýrÕÃ~ì¿ mÃ_ž¢À_ÆRà¯eøË}üåæþò\þÒ‰À_N0ð—NþrÁC‰à¯eøëv»†?ßㆿãqÀÎðç®7üifjö;ôøù#Vƒß!ÕG“ß!éJ“ŸW“_ŸœÑïøúBÞF?/XýùÛ4úå ƒ~‡ÍÍ~’Í~áb²Ÿž—F?_ïF?O[~‡>ù5ú‡#z¦?/„›þrmB9»ÐßL3ýåÆÿr>á¿ã¶¦ÓüçüIá¿>óß!Qóß!ë¥æ¿CæKÍ‹4ÿ墛ÿrÆá¿ô3üw0ÛYóŸ~óŸgœæ¿üÈø§›÷odYvÞx–G\¥vë à®WXKA±ë¨m–‚žÚ!ÕRPôhÜ XÚÎcVƒ^ÊhK5èEs݃ÞúNÐbÐ[’úƒÂØ¥1è-Ex«A¹ñÎRPdÇ^ L3JPýÀ2P̤ÜJh(~qŒÑ¿#˜#ů6Ÿd ¨óXë¸ð@"ln´ uêà‘:ñyT øÙÍ*ÐäÜŽ 4Ƕ iæëo‹@sèˆ@+Ç5yO"ÐÚPo5ö«ä$ n% Pä4gÏ Ð4(ê\“uêÝg¬:ŒZÚ·ôy¶iàPÅ ÐnÆ PÔÑv?ò_]-¾C­Í]h'Š®CëÇ:’€u€c`ßM`ßq`ýjÚ8´#¬í´+¬¾x­ÅP—.SÐ ~àÑ)Õ­­ÔálGÐ>eàX" h§1·t(‘´<â' (´c$ÀªÃ  pè§$ øt™’€vÚr!àXGСŽ$ yhÌ€Ãe—t8aI@û>ˆ3‡c Ç"àÐo!àpµ„€={ûÚëlHbBÀñPDÀžËŒ€C¾4r.bÀše•T X£d£UG¡=B`ÕQÒB`]šw„ÀñЄÀªÃ°gœ[º!°Jžq?`•Øñ³ p,!78J8–Ǿ‡Óö;Å8¼ p8cAàX…8<‹‚Àáà¢ÀáYŽuHý&2ö8ƒ_8œŽ p<!°G¶p¬R 8XŠœáÔŠZZYÄí“% JÚDÀ±ÝbÀ>!àXƒ8\!à0ü„€c pø•p¨#Ž%ìÓÀ±à0 §’·fðÛz`UÙFèx2À¡ À±„8LÀ¡Øe< ‡£ Ç– €SÉ«<» €cÀᙸ žÇ`•ŒüWû(í#‰ûdÌ€c °ÏÆ ˜Ûi H€}ùL€Ã¡E€c °›'#Dì7´°gÚÀú“ûØD€UB£pl–8–‡>‰û|€=F €Ã¡€=¬ €C3ä¿áŠ‹ÿÆòßpiÈcùï€á&E•â¿*™ø¯J–‘ÿÆ:ä¿¡ãä¿>aá_? Æ¿¡ ñ¯^ãßp±„c3²þIÉo²- !¿%\ÿ²Øsêwk=µï£ _¶‡ïôÁðå˜÷ü•àˆÛO…Ö÷)Þ‡¬Ûµ h×㙠_VdÉ-ŒáËýÊÆá¾×îs*äö{Ñ^†ö{Yd˜×~/ÎêÛ~/ùUü^N¹Í·ßË!ÅJû½ÄÆ~/ö—N¸û×ÙïÅ?ü^´Ë'ñ¾íÖN•Äûàð_QœÄû°Ÿ~¶üÚ÷<­eïCIÝÊÄû6gn¿—•1ø¶{YävÝv/¶—o»—E–ƒß‹"=í÷²rè ~/òkk¿—u6{Ù‡j³—õær$Á>ÔaÐ0n/«´íö²)~Ôn/«ULq{ñ±Úíeõò-†/›·7ÄðeóGÕ¾ÀtêW³Þ Oí#´áË®hd¾lVZÆó%Ö,ñ|q×ÛóeAohĆ/Ž3üÃJnÃk3mø²úÃq_ù?ÄñeM·ãKÉŽ/ÉÍÇ—=¢T;¾”{rS^™åÈÆŽ/HžÈÍv¶|AFK–Èõ嫲M¾x%Ò‡‘¶JÔ)×»ðÄôe÷>®˜¾’Çõ¹Ù®]_à3Lвí‹ÇtÛ¾ £Klû‚DUÓF?t|yÂZˆ ñ¸¾|o˜mÚè‡.h[Ÿ]_ºÄ®/éU\_/³ãú²Ë¬K®/vaj×—ývÔζ/‡ÓqÅöÅ>Aq}9œ»*®/éS\_°žDž}AãúâKsØô¥ÏƦ/ñXŠéËþ&‚L_¾Ë—ìe›ӗܨ˜¾äP1}9’ûÁ¦/¶¨jÓ—c·ûµµTL_˜"}0ü_¦ý~0þQ曾È÷ÕŽ/Ü“Æg·Nq>4;oöÃ¥á¼8¾äfÆñe¿ìÇlË—zÑÿjÆ+«+YËò%ÞWŽó•ò¸Ù¯J®q³_q%Ð×'Ë—Ü[¾àë8dË—CÒ¦¶|ÉÓË—cµÀÔž/•ë¢)o¸€±|9ôÆlË—LR±|ADd ôá’¾³å ¬£)Ø´åKX¾ÄçË–/¹ê±|A¶­)Ð7Ü–/±|IÃñ|Ép‹çKnD<_§ÂŒç üÔgÏÄ2ز=_ò’ Œ<_Îb;ö|A0¼(Ï—c’x¢Ûy}ÚðÅ÷· _ÜË6|ñqbøÙiÌŽ/¾íø‚éJ±?9¾h˜´á‹¯p¾xüµáKêÄðÅt¾p( ¾¸}µá‹ÒÚðÅw¡ _dË%¿¤j4ž`‘cö{és±ß˹۠Æ~/¹ 1|ÁÊr ô႞S íHjÇ[é¶ã˹ÿôµ1K_ #˜6üõ9Ûñ.ÜÓw ¸ÂrÃ)ò¹¬³žtIç=ÚŸ‹ï‹4傱)• M¥¤›:ömúZ TA· ?ÿ»30!æ³þY¦ûMnÿ»×ä¼ù“ é½SÁÿDvš;‰@þ0R¾zœ|:ÍoÆ>ÆîëVÁùóþ:«JÞ Ðݬ÷Vb_'Ÿçø›å®¤ó~~QßWœÿWcçÿ¿(­À65zSZ–¨ˆí¾>”VÜoüRZñìR¯|ïlJ+Ê8|¯ºi2qù[®VtîApäa µèuÝÛ‰â#¬sP[nÙÙòImE}\«ä¢¼âåw3”Ü%¯€xQô-Î×e¦&fÃ/åÝ̾P_ï¢ Þ¿ÛPѹá¥êäª]5À6–P`ñ~ÃIuv ,ÐuÞ~Ä{ŽÕ÷úW>T»–Mþw%À8_(aê ÷› X‡×kök˜ <%Ö{ ˜«,nëPÇB…>÷ÖÙhqw¶¼bû±Q`³yYg«¯nÕL}xÝ Ôá­9ŽRX¼ÈÝ]‡ÆR ñ¹2¬Ëu\õÕíÂ7Ú…‡º©°ÀÝ;x¨‡ ˜Êòâoùó0¬.Bù–õÕ­rDó”Ï• ؼ××öýÜ(±€ùÇr=£8ÖA¢ý›+>÷¾ 9b?*,^d½`Ã'8êøYM¼šl¾ÛTßܾ.iÃß~>X¼·¶¹}TAœ²y*×RßÜ.¸+óÒ\k}s»ð±º>Zî×F…ÞeëlTXÀKwaÉN…EÎî:ê“Û׌,Ë÷ë¤Ââņ‡:e¤Œëz^ˆØ/î´ª³ÙX‚> •Ã/oå«ý nYtäŠ ï÷ZÜ®šlë@÷VÜ.0(±À ¨ƒ#ÄwóúqÂ1•ApÜXàFU oGÆxÌß©K‰ó7 òK'¼#„±j¾)`Ú+ V‡V~ƒýݨ°@;]߬Iü=]§ÞáhGIwÌiçÁ¹¤þžTXày¤‹ tª¾îxø«O²—Ùq_Ÿg}0~¯ü•½îQÞæ';U3ÇQÞàšnj~”×ØÆ¡ÿ² äÃuŸÖþ âƒUŽúÖVãæª‚“êŠ÷‘ÿ±\TW”«ýZ%÷Áù»›yêS[½V–¼TW¼ÛÅYà€MaÍßûÂO Gy<¢›»¢ˆÞÏ5#ý êK[Ç—%{}i»`¤ó²ô]Øù”+Ý7®ÚzËc_õ¥­ç’c½ëK[‰•Çþúp×k@ï—c}ëK[Muì ]àp,ç”ño½%£=ð‚®é{½¸H9ð‚^/ÎZ¬²×w¶ æ@õ´ÛQßÙú t WcÍÞÛÆ'üØ.ÖWÛ¹ë;[µóðPO}g»ðqç¿õ­Z®YêØ—úÎöµ#—Þ£”°UãŸò–?ðvæü½Q‘qàí¼¢—;¥^ÎÛÉ»RÅYÂjúÞd¬tT:™¯ë‡%w}i»°[|eÃO}i»Ê ›çû–!B]1äñ }Îß«äÙDZ֗¶ «Ñ’=õÆ:ÛË |SÞŒ¯g]b oçõá\¼ñPgeï¨k±°áëä ¾Ë#âûÑÁ|ÓýãxêKÛU›¤ëòåtw•Wrê\êK[MEŸs]8ƒ¯Z£}%õ¥í‚I6òÆ¿ê|`N>:5Dyuðz®oò9x=¯8Ö¡µÁ׫3x}á±îŠA~%JWr| SŒ³Z‡ptoÍ÷vÆó¹–r]«sf:Áó+ÑÒWðrßä+p\_ž›­ðÁ»(Þ¬:õ?ð†^^R>ÀxC¯êg-¼¡·;’ÎXµVW¯FÁ…UÕÍI·øz+*So<^÷é;êiÜI¸Ç½–B¿Î§Øè+©Ô•utަ½f†ûëÃóŒ#ù>*éÐpýnúåÔÐáÓ‰wtÍá›ì ÃÛ˜,^~aú×ò!oFO ¼_{œ ï¡XHX¹Œ¸Ï)}›1°÷_[Î` ¬D?¯JjM^¾jïˆÞ\¢;ËJ00v»ÁÀ¸¤cv „»4_ "A —¨FAh v¡PpÅ=å„‚ë)ÛÞ `öc„W$«S ®X7üh ýF4¸-ßq±alÖ6 "Š@b4 b“Wk¦A¼?²ŸhpûVYú•hðÆÛgŒÌ?4¸Ýæ Óàö®C„J^ìGìÔb¡Al¿àé˜÷U<4á¿i°óê…ñ8.LƒÐV×ãŒöÑ4xî·>\†#µ &Ÿgh/'.]IƒçþJMŒ¼08˜\lÁA¼Ñn•Pp  Yoï,«Dá ΊÒÕ ¯oЪDPx>4ü "ÐÌ[g&Ñ &‹Ð&Ä}"ÑšûPÆAŒbV  ‹³Z æUD™ûþš3‡Q‡cÖ4ˆÿ²Žh·—ãÑ8ˆ™öa Q8˜GÓ4ØÏ‹i­ícpø‘`0/ÅÀ`\Aœž0S4Ø3¤iíð›…i°Ÿ Ó`ßÑàÅ lĽdLÓ(ØÏ(ˆ!ÁÏ FÁt)âo¿¸þ&ORÓßV©tFúónùÈCñÊaå¡û©Ø€é¯¨‹Ô&ú[W¿úL؞˯é̸«„ô·^úœú[aÑÅ:¢?L¬jGô·­¯^Φ¿m}´Â0þ!„vNòÐmSrsãßv\z›ÿ0³£æ?8£íÿu$.qAˆ· üf"öˆÿ€LlÄaÁkó¹8,x¯ŽZ:,x…¼•¼Ã‚7Õ$|$Zè¨àýZÛé¨àsüЈBfÏõ£p{ä!ÕQA×|¬2nˆ¼NQAT¹ç¨à#—¡àö½¬¹D2âW›¡@¼˜&‰(ÎCÀü·½–ä™ÿúü €hæ$¢¸È×$E\•)þÃ(Uÿu4Ôü‡.Hì)Ü^eJŽ%@4¬`žph‡8üH¸=Qˆf8* €è8c2@´³N1AŠñ  ºuLØ=7¢Žd¤"À¡ŽPwz À>`îçÉ6ä!ì^{Ü{”˜Q‡`nÄ ƒ‰1F߉1”øuÉ8”ˆq,Ò“ p¨#Ä9ŸSL°öìýjì>q~,``?CÀ¡Ž°ÏOˆ*Ë€} €=p €C ÚÙ§ Jøœ™ñÄp†1¢[<# ŽEÁ€°Û1âWÄ2 ®(§c`÷Sˆ*˨†… u8‡›û’šûW&ÀœUx €ÝMàÐŒuf•h÷Ê8´#Äèâ(ö1ö¥0æ1 æ”C€CàXR˜aÌSÌÔ̘ b`»"ÀŒÉ`¦þ`zôTô ÿå! ÿåþ†ÿPG@ò_æŠð~tM!ÁÜÍàpzÀ À`yj€yW3½ñ#—¼šÄ5j€¨CÝ™°nꈻ&À¼¦C€ÃŠQ‡ëS êPIhÌ %ö¡M€C`_`æã`_  êPSiÌLÌ|ÄÅ!P‰û–=A‡ñ~ý0ö#$̪"˜•Gí -…€y~ƒ€=F€Ø"À>`&“àPGØO™ 0íšû„M€ÝK` ÖtÇD€Ý)`l`×1æ¾{ »`?›&À,PC€Ã‘D€C;BÀ¡Ž°!#`fã `ÞìAÀžNŒ€},#`ÏBÀ9¦À¾Ÿ¦À\C`nž°Ç!0óß¿‘.iØ/xcR÷ ž¯œÕ-=%è‰P»ÃF,O0Jj¬EUé2­=½¹É<™ñ2n<°?BPñ ÔûŠ*Š!Ñe¢—C‘‰®.-½ý­62Q¨¨Ã$b$ãÆAÈxI&º`F “’28˜,èáAèƒßqË ^š Cc2 DbPO „¸H×´k°Å¯BˆÖŸ)$¸\þþm"DI& ®l „I \îÝŠÏÓÙWÏL<¸Ü·u£äÁî‚yp¹_GÅƒÈ Kñ¤ypyä…ÄŠ‚aó 4¾›Jœ}õu‰€¶% 5 —Û)„ÁÃ<ˆµÊ:ñ`rŠ—[ÞãÂäz&qo€CsŽ¢çÚþ' ì¯*BÜ<ŽI!޽N"Ñ¡Š€p¨# Ä“ÂÇÊ@ˆ¡ƒ —+È% Ä!q§€0ŽÂå‘¿d€phG@ˆÊ/&ÂL¡N5r;Äe"ẳ°¯¨‰£b âJìSH°«ˆaw³(F¨¬Õ§æA\,©=Ѩ³OÁæA<,âÊœ£D´{iDâŒy]àØ2.—)×<Øžy7Št*ÌÉûdŒƒeüÃc ѧQ‡7ã ž©e’ˆbHœS@p¹â`ßnã †„ôŸÂÁå9FâÙ\¸EP8ˆ»© €ÄAt“¦q°g ã`÷Á8ˆ:Úž(ìÇÃ8Ø» ̃Ýsó`%ó ^;KæÁž<̃¨ÃoæÁÜ,ã`¿½„ƒ87u‡³f® æQ眶 ¢o$dþUÏÁAÜʃ™‚ƒ8Ԥőñ0bôS)fD3R qµ¤öæí¬ö& \Ä~¢Á¡Ñ ÈÐ…hWü™¢¨òŽ»뉙ô¡¸ ë¤Í­ ¢Ž$š„A\î!3 æé â\“>Íð^û>3&ƒ™fƒ¸ Û¤í›iìnÄbØÓ0ØwÓ0˜yŠ0؃Ï0˜§708Ô öÉûd ƒ¨óLá@Ô™¢y3„ó<ó® fýÄ«õ™ä¡}gDƒ™ÚBƒ8¿k¢ALØÚ$(ÌÓaD3S8°o`5´mO0ØÂ0ˆ:·„ʾšgÃ0˜µ^h0o¡Ð ÚfŠQg v¿ ƒ=H ƒx¸ÍÖ0ˆ:Üuiô’Ì0ˆatj!a5x% ƒy«Q‡Ÿ¬ ƒýPQ‡ßš ƒžf¸6×´e07Ê(˜×|PU¤û öm0 öÄ+D3‚8¡`ŸžQÍl“6´ŸyÃàÐŽmªn}ÎûM꤆>‡¾SÐ~É>R¦vôÉ$âd÷¢(à9rÖ€žZpý…GÌesxÄÜ^yú®Õ/vS ,‰ú.¤cdÒ1Çc¯Qßõ>Zfˆúà§Éƒ›úà…=ÅasO{cs¦IûÄ<·áQ>1›I'V1‡Œ×Û*ªIŠ=™Ç}•ì×À|Xiߟ˜›4—) ˆ>H›)èËü@_%/&®Ù)ÆÞq>ä"V|QÔ ík܈5,ê{÷K 7SÒn³S ÝGê«°Sð¥%ã@}°ç:2N1»7™úž×û¹Œ}05“+°¯œÁã³SÌêÍžqŠÙ¼MSØ3™gÂ>ܾu¾w}XÅ<0Dᯄ}0|_'!(>§\#öÁÉf¢¾Øú†C ú*m4iRЇÕ-£ †¾çõþ$CŒä9tÚ(fÓ@ŽQÌ® sm³y#[œbð݆‘BAÜÜßI ï{  úzÔúžW;p}´yÿ5@ñlÄÔW‰•I^¢¾6&2öõ±Œ}8=9¸ûPg›Â€ð¤]¦­ï²øèöŠÉ½3÷=ïni(¹õÚ+(îëÇÊ܇nɰEÜ÷<ÊÙîä}N[+qi‘܇¬†¿ÊŽ;Ø{¿Ê©@¨³[ f[\à××Ýà^¡–Àï¹¼‡Úà‡£/SGw‰ÜbÖÓ‘A‘Î眤 ÏûZçIòÃMׯ?‘__v“_Ïñ‹V‹,(ò˃eðë1hð{ûžü0}Ç~M3øõÍ2ø¡)J~åpL€ùõ»Gä‡*øalÓa-~1ÚÒ'êC¯ghu%¢¾Ì ¦>ôšÁS¼O;‘äá˜d Ï«šm³H¼ìˈ öaêÚ'ìÃ'èwÒ"-û9…ŸÝ«KcF‹¬_D~7÷´5çLñ›È¯RŒ~1õv`tÄä‡BŒ~C¡_n]ÐÝZÆ8`^îA¿J®Á¸›Ð/oÓ ß»œöuúáf)~'ôÃÓÀÅ£Ñ/SLЯ/ÙÕýðò|&ô{×mvŒé×JЯeôË+ƒè‡WÞ>Å+åÄèsâQ:'ôËô{—Ëx(ôë›gôƒ5›8Tì×Ðì×CÐ쓼°®7 ’ý²²û½b8‚z°Ž~1Ã6ø mü0aÈeFä‡õNa@,ÌÞq_ îÊäS !Þ„~~suŒB?Ì«Sg̯&¿¢&?87ñÊýúi0úUâ Я’ã0z(ô{wmS4ùeedô«6„8¡J&òÃåãÃjòÃÚéž„ XŠPiòà s4ùaá1í ĤÄï"&?Là×´-°gM£ßP"ôü ŠúÅ~Ñè—»`òCe"?¬öd#òƒYß:í ¬@,‰y¯ÅI©‰ï¨=“îóPZ*íú[—÷‡îÞê”YzÓÞX¤9²R±äÏ€×Fž->¼fà{n«5½çïö&ø˜‚v4ðõn7ž¸wÚô‡û9˜Á´aXó^µÂ;ßf>ßuùUmàÃ0#~øvYøâÞÃyT}^ËëÐexïô.¦ðÞ«Mç¾û´_]¬AÈ"„øšsÜ÷w!Lª€¾,7|ßzùÕWäDù6£nÂ|›¿Ô;Ì·É­Ã|þþxžËÄ{°U"p9È·Ý?výa­sæZ“1(ê°À1¾Í_îäÛm¶š _B¿ òí«ÝDäƒOÛäK7A¾TI/Béùö]Ã8A¾]&qäÛýíÀA>d}ŒAaßyL¼ã6.›äë:òí—–ß ò펉&È·?Ö:È·+¯sùúWòíòµë _ÿÊA¾={äËù0È×?qo·[R‚|»näÛý'Ê—ÓK”omûé0ßî]» óí2)ì0ʲ‡ùúXó%Ÿ0_×qœo×®\‡ù¾ve:ã0_ÆIÂ|»uæ óíÇÏ0°{Â=ôŠ”á0r™þhg7Gùv+åËhK”¯ë8Ê—“(_êöÅG¢|°ÀaÂÞãÊg„½úÕ2‡ùÙ÷ö¾:Ä脽¤sŒN0GÙs²Äa>¾¡؃צî0ßr›ÀæC*;ÆÞæƒ}Ç$û„ñ#AÎQ¾¯ÊÈzüN9W$È·x‚NoU"ôŽò-—F­£|]à(ߢ|õå[¶8Ê·J¨ßQ¾uÚó‡#·á[äÛ¾e·/Œ#|>pGøÖEK¼„øV&&ćýßM‡ørlGøY&·ȳ·#|虌@á[ä8™ßjÁÄøÖMhàߪ]îã~MŠÏ8to•’£ƒ|:Ž#|‹üÓá[mÔ˜ߢ}áó“ѾåVx,¾nؾU9¥;‡O%Ó†?œ/Ó¾…†Çßó-Hxo¯ñ–Õ2¹„÷V?ÝÃR“¿ptosÈ(ѽ•9²;¸·^ÞèàÞͦƒ{k´Ÿî­Öç%º·Úx2Ñ=pÂÝ[­Mtoµò4ѽÜëD÷ü¨'º‡å<äè …q9G÷V«iÝóµJtï;6 Ý[TtoåR±ƒ{«”©‰í­?…ž}ÉÛÛ¬ÊNl¯ë8¶·­v‡qlosð,Á½ÍZî÷úWîmò®îàÞfái‚{[BwŠîmž&º·ZfšèÞ¦Ph‚{9›÷º]÷6 JpoÛ4‹$º·9BèR/N›ý°*½§Í~ý«„÷¶Ý-ïå ÞËåJxo[†÷¶ÄÞÛÐMx¯îðž»5¤Nbê«óuÜØV·ïÄ5ÆH?*õ¯ºÒï~ö÷©“N8^Cê¤ ©Š\ÖéJº¤]ÛÉTmn*CS.릺dhêæVÔnÊcS*šJÉw¥óº™üõwi”~“‰Y’Ž¿«ð/§Qúè9w|cÒ(ýfŒ0güPÇít‚$74&HrK]ËMµÒV$¥­!ARÚJ­´5ÔJ[I”¶†Ii+µÒÖP+m%ARÚ$¥­ÔJ[C­2(.+[f2—‹kùˆ"aê{ÈQ½<$‘0õ½™Í¢,ëe¿/\}–+\½ìOùU•³´˜ÅSe×·csü¦P|¹›ÕÖ<,xß*¹ø©m…ÅÚQ%7¿µå;îy<Ú`}Éþþ+ñkQÁy¼Úa}h»Æy.²]ÆçÇ:ú¹z‡µ4‘ç¹ÉvùT´êT'V O/žã²êÄg;•ð;Û¹ ‘¢Ýh­Y*~G«Î¥¾HøUß‘‘ 甽Ö)‡Ù †•U'>;T'߃ÚÎ…ø~¾§ —±‹ŒU.Ùk-J.p¾7¿³¡›µêaFœ‹]ฯ¬C';Ά¯ià5<Ä5 Tê2H¼øçJ»åKÍ•ÁöˆõTº£òé|•¬¦R”Oçù¸Î)»eìÔÛ«ä’Ýò% ¼ V܆¡xÕ WcF¾Y_‰ì–ü•ÝòWR߆?º”Ýòµs_ë*»åuã uÕLY> oݵî%9kOÕ K,uJÎtaî,£ÎUa¼o’áò®ÜµÞ6\–<íZ.Û¢ô+¡á2"¥õ÷+¿eæDþJ¶Å~Ëne[å·lKÕkÛÚpyaÝ†Ë Ê^Ûц˪Cª~Öw¾oZã§6´S#ý‚ýÈ"CÒ%?µœ«D†ËøÜP¯ü–7Æi?H¢Ýòöp ¸öUvË9™}“Ýò®ç7ÿ²[¶ïµ»fï…/¸„rö–Wüµ_´[>ú–Ûò¦`ùUNÑ÷tìGnË_»õÊmyS:ª þÍ»Ž]ßU/\¤š¼7©Õ.¼è¶,ßß«|påðÊg øš&º-¿\ \ßbFnË>Ãã–Û²ýƒ¯oNfzƒ›‡æÒвrÜà R¦ù‡¾\'™Êµ"á×¹ÊmyS ºëÜä¶œ§áÜå¶ŒO)u{¿³àüm“ßë<7Îß«Lz®ój·åZñ\ÐîÒmÙOÕyËm¹Ûyä¶œQ‹×s Zé®rŽz8–êe|áõ¼M÷óÚä¶ìùÎàH1Wý:d¶lçë:i¶¼3¶}}írߤ0º®[^Ë›„,_‰¼–wI@¯ë‘Ùò~ªOx7/rg;út€~ן«œ–ÓȽÙiùкw;-{„Þ‡–ýðÞ§œ–sz÷e§eù _Ð0k.YØÌ-«åʇë~ä´¼_º•÷k§eŸß³Èi9—oçu®^%×l³ñG»–•òå‚ö€F˾¹Ïi§e9{_Ï%§ånç–Óò!eúõÜvZ–Jéz:-Ûhü‚úÇx­v.¨ˆjß% ¹ð‚¦Ó²Ç—ôà –ZEÏ!OðE'ÆÁ‡$»n'Ÿ»÷Z9ƒïÌ^/¶uœ¿ÚàúBV¢šÁs«º¯Ëü½5ƒËýûF ˆ3¸l»o|u®|¿¸ñ’æ þPMwã%]3¸ ®o¼£·}x½Ýؽ\3¸³ol)>†d$7¶!TÞ“[céÖ¦±JòòHØü~2ŸÅÊC½7ó7ɨï•–=±Þ+úÀ.ÔJï†cØ;¾¨n¼¢9‡çGø rqÙVóü-¼©õJ=Šùƒ›£ý+Ù“¬ðÌÀPó뛨8ð~_ Þ¯¢&Í EÁ@l¼ w‰KjB6#–?÷Jî"ƒžDÅÂÀo¹'­1ð€j„ëtaàçÆ‰²„aàÕÃÂÀJ½‹‡"~\!›1ð€æŽ+IaàWçÕ_x ïk½žŒ>ÑŒXüËSV^b.ªIRŠç.K.Ø7Vàw)ð€ìf‚@ Àx°rŽ‘¹V .”¥) ˆ¸ÄÍ:b@ìZI…bÀlÍ b#ýMâV:BÒœpÝ´Ö "Æz‘Å€E‰IÅ€ÙU„ÂIT(ÌVW2 –Ò<û‡8’Ì€qí " [CÂX+rùö®j©4B+L$& \—Ç%¢@¬ÚÉÐÆÀ)ɪ—ÆÀõÔŠ%ˆuü5aàºû ƒ8gL„6®×mÈ¢ásÁu3œq-t‚Árêb×}1z ÑÌ:‘ bÔ¼ &AÃF| ®‡¤¢!ÁõÔÌ\w)僂H7öN(ˆ–U"\ë ®Çéó n+ýJÇ\/þ)L†7sà Ë– ×[3o@p½7ƒ—@pÛ”Ò Õà: .–°O ˆ} yM ˆÛ½(‚+_à®oÐP ˆkÃU ApÛ”:9$ˆtwÄG¡ N°³ àúlZp·] ‚‚¸<ׄ‚è„ÀO(¸Â™Ž-ã\aàÌ*bAÜMJ,ØWÐ,¸a]H> â“*YK(i&—ÞFA\@~0 n»¤AAœ×Â(ˆ›ÿ°D(¸-Bi“ î9Á¥Hp½5—„û ›1”8¸L‚}“ „(×D‚8ò9‘ Η_/L‚Ûqš1E‚Û¢<¥!A”\<ºH£_¿ ⎋E‚xZëš añZo·€ 6›r¹nÜv‰E‚x,Ä}"Áz˜ø+‘ Jx{E‚оÖDÐàžP°»`ÜV%o ¢S£ F$oQc‹ßLƒ8uÓàvøë˜i!>¯¦A´ÌÁeìgÚ4¸!«Ç¯†Áá7‚A”pì›KŸD6 n‡T¡A\䕈&Ü6 낃t<,n%Á¡Ám—ü&4ˆ{®Ñ šyY"Ü΃2˜Ð`OŠ¢ÁáüDƒ¨Â!iÄÜÈakÜv%Ù nûjb ö B˜5Ó Ä[‚JÑ`ßrÓ ¦Í}¢A8«Žh—”o Óà¶);{hunò—hç#> bP®Lƒ˜—.Ön›²Ìáqü°eâàö!÷Æ*ÂÁMœ'Üå— âþžlC,ˆWTÍ'aA\âzôÌ‚C±`ŸŠYwJ? Âë™p(ÄH*º n¼?ÿVʤà Ô«Ç=…—·°Ã‚·’®8\f±$;‰Œ¯|¶¾õ$qk‘Íö5í\A¿¿“ÖŽ bîü¼nC›£‚—>Â'*ˆñÄ¥¬£‚˜OßO-<þcˆ ^Ô$*¸Ë¾¯£‚û刟£‚·™Ž n¯lpÜ.¥]é¨à¶ÌQÁØ7‡‘½sgÃŽ àþcˆ nJÚ DØrå Š‘–]wTpõí4"¥æCJî»LüC„X­0$i"D‚[ž€n iÂ}ß~a­;{Bè#W… •‹õ6ì÷Ãß „øˆCš7"®ªp]EÜX+@ˆ]„{!6M0l D#¼X&B$Û‰«4òLâ‚ë›%c}ä"ÜßUÌc"ÄãÅ«n"Üñac âèìfƒÎÎf"DN\B‰yKMö56î6€‡Q‡×ØD˜4ƒ&B<þ ´-Nƪϊ!B¤µ¤>ÀD˜¤½!Â|] &•cˆ°Þ&BL,ü´a"ìA`"DªU~]0âX×<û0îu̓¸ \–š‘•–AŸü4<˜4¾\´g<Œf¡„P˜<Ò†BüHñBA!nÃ6…3µ 1p^ÖQx |‚BL F quV• qu85 w~m0öÈ7F~"Dž)>˜—Cˆ0¯¼!N†Ó€‰uº&Âäê6&Ê$Ä¡øÙÇHØCßHˆCU+&B=M„µâý5aÏ.¼’C„¸ÂŒr›{:6ö4j"Ìš!D˜·™‰°¯„‰C”|j"ìkl"ÄÁœ6fÍ"ìâeÅ`"DÃKa¿LM„‰›…ûýj"ÄÁï‰sÙC„˜ŸE{"¼ëC„Xu‰ÿD„˜äj‡Qç„éz5J;@ØÁ¿•±„¯òÈ 10NFÿ…¸`ãx„Âܾ@aVTBœÎÂ8£ w‚üi*ÄÕ92´€üQXàoÒ'5 .ëÀàoHðõR.$¸É ¤I0¡® @}ˆööØVˆÚ­Y0!± ¾¦d¸° f©A!zkÝ\6Ü,ˆd¾3 žÚÿÜ,ˆ· Ò,ø(ml³àvY¤…èí¸Ÿ¢-wèkÕ¦QðZ÷ûSè"£´FÁS–Á‚ôX‚¡º  ŸÎˆêoèªeF D s#Ýúh誯Ñ-í:ˆZlÕ,½e¢ñ´@t·Ü8QDm mˆŠ ´@t~ ú¼ßQ¼ZO´@ô’fyÔ‡*Àh}¨£ðƒ>ôü¯Í1FKDweôj‰(— " ÷>¡ êH–i¨…‚@%›D¢]Å*ÑÉ× sù‚ÆCŠV‰ž§ÉÔ(¯Y%j0m•¨ÒµLôЇø–‰rËk™¨å²!Á[»–‰b>ÉDG„[&šË™èåOI‘‰æPÁËjµV‰Ê®1BÑÛŠÅE­©m¼õ}pŠêËd³à½qÆ„¢»Ö\ŠÞ–KF(Š™™‡²PÔÝl¡è7ÛraÑBÑÓ9 E¿Ì*Ö‰^‡2:QDd© µN6↓Eü¯ûbE%ú=Û¬ÅÃÏ_I%z"=^-5#µð±U¢Ò·Jô\´¤‰Jô¼LtV‰^+õ`‰^Ú×Ù"ÑSß[[$Š%€ O"ÑSﳉæ.D%z:Æh™¨'†–‰ž¯ÁÐ2Ñ‹²‘V‰žÊªÑ*ÑKB’V‰^Š5X$z9\•¨~«Dñx$«D}s#½ ŽH4 G$zëo‹DïóGdð¸õbo‘(¬p‰Þ«£z‰b+îD]3L8ÞnS ¤`OO8ˆ;E-¦‹Hô‘¶/Q˜Ëü 5ø F"ê -½f‹DôÕ.þ–ˆ>—‚~Vˆb+ñ¯1‰Ý“@ôu4%QX‘Ô,}µÝ¾¢¾·B´Û±B4]0b™ÍKD±ze3–ˆ¾Ê)ÙQoh‰(2Zòt,E¦=òœ(Û¾·‰ÑŸ1Sà¹(6Ò*Ñ×A"S ¶°£Q‰¾2nž‹2.E%ÚUDØbÀx±)'HE¼)ð\.I@­½ ŽJTùÄ[%zÓ¥E¢Ïã8¡E¢Þ Ò"ÑÇ ÕˆDs;#M"½%@ŠHôµX!"Ñ*"Q°$|‰> ýG#ª='-}$ŒDô¹tñ"íY"ú$’h‰è£x¢Ùl…è#ó”VˆzsH+DŸèA­õóÑ Qoi…è»Ë,õ)·DÔ×Ϙù<ˆYõbàPG˜bKDŸÛ>KD_G-ÍùE"êǬ%¢¯h¤%¢9ãHD5 €Ä'=ÓþåÔI­}+Ÿðƒ0`È/»w­Ë²[ð~½7Ð0¸èÓ\ïܽß,»OÍWщbœˆÐ¤•N¶ ®ºúAX Hn*\©%Í‚Ë·Ž TÎ,تF³`¬ÉÂIˆL…°àº–sŠ1ÎQ&ZÒ=í1 –Ž(cl `p]I! ƒë&‹øÀ DxbJÁ œÜ6Ö ¢Î=Áàz˜Tƒë±º@0¸žú"Ä¡2 bü]“R4ê¹À VŒÚ÷'„&ð` ”µÇP0ˆ’‰×[_~ÂØ}L,ˆð0oY%go„=…fÁ2È™â‚QÓµPô¦ÅcX \^O³àziÞk¡è-C Eoo€ŒPÔ§ŠÞFÓEÅbV‰æÐQ‰>ŽZZ%š#G% o“_¢@êS‹D¿é_¶HôYZ´H³2éQ"ÑçvxÍ"ÑW9¶[$ú.Z$Šs$C‹DY·HôÝÍŠ‰>þ²4ŠD· q‚ìDD¢_;J$Í57 ÂðhŸU¢¾Q‰¾úúÔ*QÌÄG«D£Û‹Jôñª?*Q¼Î'D;Ï,5ÓE&ú†K-ýšáª*2Qø|þ@°«D%šfL‚­ƒ‹L–Ê¿ÄÈgQ‰Â[qÚ0–;&Œš8(ØB½E}%Œ‚øVÇ%|„¢¯´Ñ‰.Þæ( ?¡àÐŒu¢9Tt¢QKš‡± Ú¡P/:Ñ—Ž›-…û:q12Q_Q¡à†WaË2QÁ˜5¢‹ì@‚h•Ñ*ƒ`+ ‚ƒÜSÑÅücì“kè6”Fôõ7hD‰³[#ºX˜fŒ$*(ˆNpobD¢‹?y´HTÞ”AAhjù”µH4¿²JÔ™8ˆ‚C#BÁV=qÂäI£ ꉢí:Q‰¦NT¢úvÜ*ÑEfƒJ4íD%šv¬ÍˆJ4—+*ÑÅÄk™èbÂm™¨…à‘‰.ÏÄÁUb™¨M&™¨êH&º("íƒG&ºüØ1ˆkÁ[d¢«6Ý´LtÑöŨD£6m•¨Ç@T¢‹ì+[%ºx×m«D£ µJ4c;*Qk›­Í ·JTîέýêÜSH­0\•(|ýs³J4g•è¢3­ÍEŽLÔç×*QŸNT¢oQ‰æ–G%Ú§#•(짘 ªp³BT¢ŠÉY"е鄘SfKD7"‰¨Ï? ÑUŸæ[! +gr¢ÑPG!šQ…èú“q6aË Qÿª¢ëÁ÷]+D×Í*R+D—¨?Eƒ˜W–X!Šh˯A Ú¿ â7ï´_“ïCô³F´%ì_E#ê—Y4¢‹>µFÔÂúÖˆzVo¨]¾Z$Ú%‰ú%ó›ÜIõUR°‘ú¶] ÉPß©ÜöM}¯¶»7õmŽ%xžZ–µGŒ]FÜ~P_Û*†ú¨í ò9Í^Çÿ(¶CÌêebN]Š0ßà4#æÃ&!éEÅ|0¾f„!ñ¿cµòSÌWF׿äƒ Y hä{”F"ÈÉô5IAWmm)(ü Ä-qˆ2Ô{Ú-ñ3í ,—ëqoà†…õ¯øðÆ?'!èvéP€o{M’>´KÔ5ð!:_9wôÏ;›|Û«¼u­EqŠþ!¸Ì`¬]-+Žt‘±¢ÞÜJÐõ°œÔJÐCy C|ÝÍ(AÁ_òAÅ;Äx£s A·Sàhht´ÑÂB“lf(v0Žg(žC²Yt JÓè.g÷Öž‹g¬]-DŽô£u ‘8'øgwˆè@wúŸ¶ 4FH‘î»ÆDd ¹Ä‘îÞ˘àv]MÁ?h»g´ 42ÞÈ@9Ý̇ÜT"è®Ü€ƒ ÔrÃ(A÷Ãñ@)AO¹o·{"'›ˆžß‰ù >?~(A·­õ F zjd+Aa_1ÙÄì‡l5[ zÖYF ºÿcr‰‰ÿT A‘Üšu,Ý;ÉXzhwm A±œdàÎñ¿Ei$Zz®’EzÝC A7Iv[º??lbrÏ!è©~FzÜÞçg!è¥$D-õØn!hnh„ 6ìj!¨eE-=nG(-½”t«… »^U‚â[ã„}¸:óîÀcQú¢‚ž‹ 9JÐKI|Z zø®w1ª øîã´¾“Àw/S€/Ùƒ{I3Ü»±œ%Ü ÷îU1õà¼yåãIÜCú•eR{ÞŠå ö@CËÝ{[Uöî›Âz>nN60÷iÅ£Y/Y§Âz0}—®S¬÷—ÏN¬÷lFw³’n2ÌjÖ{6N¡¼‚¶ õІ0N¨‡Ü»b4¡fÝmÚôW¼D‚ê%CiX/i$ÃzhgŸ¢{Ͻ;T'Øë34ìáãg Ãï™`‰u¹™Q°÷ìÌ-ÖK†¹°^²m…õ‰Õ;üÈzõkžÍã,«¡?²Þ#‡N‘ÞsÚâǤS'ªxMz% ˜¢{ÉYÒC‰by"=§–è!O/§A @ÎôŽÊ&Ã:“îlÆLžçE;`ÎCÁ¬òDî.ÍyIÎKúŽp^R5„ó’>ÁœWéæø#rÞñ^·’œw ±v¾Nº#nç!ÅßÒ½äÃèA±N;þ†_ ôP2ÉÀ?È…U›ôÍ1Ès—uÿh—Â_«à°ÀBŸè¿m²^´5æ9O ,^©dH­ðÜ+gŠç¼µËz‘¥õ7K`‘ŽŸ¯vYçª_‹içZµË:1‚TÏhñó\»vY#¶Ê_ »ðð'‡½¶®ð8§Æ×¥MÖ¶ù^XØ ë¹í²†Ž¾út½Úf^Þ‹¶Yç†#’uéX+K6m³Î{ïÚf‡±šÆ_énžû×V¦¡Zèr 䓇×ó*%'d¼Ÿ7ÝÎú$øœös:åW­óÜ?‹6Z/Rw>ÏJ‘EÎ!°KA½xžo&ø1W(åb¯V6|Èk ± þê”Ý–gm!n»Ê=xA¯ïxkžçÌ<ÎW"J5ãce òcp——àó®rÛ²•зŸkŸ×w§Æ"÷ë#ºm)ôIn[¹ï)·­ôïéetÀ|ð¢.‘Å+‰Ûó>YäÕ£xA=!µ~yñy—gR­¡_|ø,©Ü+kû_NÊoËÝz‘žòÒÓX3Á‹d6M¬Kø­b(²ÀN1þè”ß–ßÔ/õÕ»qgÉ-¿-¨V¯*y¤²°óã‹7u©,ü˜¿ëB•…ßÔ/4ÌôÛò¯›TvÎz‘­ó¸,ÿ^lå<.'Íw=¤²ÀÞ?ê”ÊÂNcˆÊo+ÅŽÉW²®+½xW—TΫŸïêuô¡zkŸÎþ«(ßmµßÖ¥v }ÖZ¬FÓ[þÇϯ6cüJä·•„§9 ”„éÝNûmÉ'îÝ®öÛZÙÎM¿­WÙ)^(Å9‘+-Â[š‘{ì9^Õë5,m^¼ªk·µ…Òï¾)!'Ïwg²Óa@|:™ß¾Ðð²oc•ó¦]†ô›/r÷9</íÊ-Ãñ[öMÛ°(ø¾chmÑ­Wå{PNSCàejnÛ›ì­ÌPÇx±àaTËq¿`_¨,8‘Ë*è…½Î)3áu®š(©nÃÖ£–ã~ð_ds|$‘=y¬wÏD^¯š/ê’Éç˜ÜÍ5›Rh°¾Ý] ÏÎ;j<cçv~Âàñ\zmLØTÿ‡/†Á㎑K„#ø" ï"…‚Yð+Ñ,m<ÞUo5ÃàW¢´†Árt[G¬¬H˃_‰d.†Á¯Ä< ÄŸ¿+g»,,W8ø•ÈïÒ8ø•hšqðÖ+Ä8ø•8Ÿ–pð+±žpð+YJG%¬ ÆddÁàW"7±à—×dÁ*x _dÁ'P„l¬V¶‘oäê=)<hÙzdÁ‚ˆ‡*¬"›X°,¸‚ V‰ê¿mt7 ~%^ «ä"lÇÒàñž&ÑàXrH†q*Õ¯ip,! ~%òy2 ŽÇ*¬*ä Ñàñ^zäMƒUç ´‘‡_‰ÇÒ`µÃu+i° rÝaÆú«Qr”«¤„.FÁ±Q°JHZBÁj.¹„‚ï„‚U‡ë=¡`]š{DÁ¯ŽBºFÁú×¾BÁ±ÎAÆen ŽU.É0.™•ËÁ‘$/¬.æ„‚UÂ¥¸Pp,Y%ø=6 »T)8$¸´Þ 8T9¥Áà}"~ÉàÎX%Ä_A`5Á« ¬:\Ñ ÇBàXR84#l«KS`Ÿ­ pl…8ÜAàp½ã¡ÕŽð’8\Xcz!à‡£ ‡»$® p8 p,!–@‰T- ¬³(p,!7F8´, KHUÂnЇ–EÃùˆ‡c‰‡gŒX?"àKˆ%À#Uø:Mì*BÀá|‰€Ã©‡»"îp¸BÀV…‡³q0t¨C:%¬~›ó°p¸XbÀ*áç1àX§p˜éÄ€c püp,!Ž¿"Ö#S 3à0i‰{64ÖPç¢W Øƒß Øí˜{2öG ØO°°Jˆ=bÀ±2àx:dÀ±„ Ø#C 8TödaìÁcÌ,d›!ö cì9Þ84Cì׉ °® ‘Ø¿ÿ ÿ "ÿå2þ =þõCdüëÄø7–ÿƒ¿±aâßX…ø×“‰ñ¯ê¼.âßð+á_ýêñ¯_óÆ¿±â_?¯æ¿*!O Çó!ŽÇ"Žu8Uè¡7ö%ÿ mˆÿ†³ÿ ­Šÿ†~‹ÿ††‰=ÿÿÆCÿŽ¬ÆŒÃ…þ }þUI éoø›ð÷<” þ†Á'ø’ã¯9ô¿‘>Éü÷ZiùÇhà£n‰v.+G™ƒ&˜4G‰vØ.ÑÀÛÎqc4P\¦p`vp%Ûêk bo6ÈÁ±s@0{X\ho˜xàÎ¥ÿ\Ïcqº¹OjP˜ÊJC*ôCË\ƒýâôÃË3úåŠý0‡ …~ñÊ ûÁË—o}³_÷Ó쇖¹ 1ûõÑÍ~ñûõå1û¡ì–Ù/.Ëf¿¡±_¬…]Çð‡:ÛñZ üu·}‘MC•Ã.ËÏ?&9(vW\ýáH×,ƒF.’Lñ˜ ýõ¡L±Ãýa qL±Äý í¶YN;Ä¿>eó_\&Ãq: ?öYV"—`ß :ÊØ– 0WЈ†Ï ûîã‹DÉ; FÁ2D«@ÒÛ>Ë—„@Š¡ zNÜ[ì´ì#û~ ãÉÄ¥ÀØWÔËß`\:C€ý|šãj~õÚiyw8N˜í–!Àø<‡ã†DÉ–H`5+q¨–WGO-Ëu"{æ0`ÏfÀø‡»f@Ø!sš4ö¨5öÈ6öÔ`Œwˈ€=Š€=O{:1öÓ`ÌH7Æ1Þ Ø¿1âHÇ 3`ÏýfÀ¡a1 ^*"G1 Óƒ€x7ñvqÂë„€1墙{ O«°OY˜ A@Ü~ 1®K *<“—\2Tàpd`O7&Àl« %"ÀXŒ‡}±€éR0‹`æÙ` Ø€ῌÆð_ž—ð_Þ›æ¿>ó–+÷¤Í&ü—×[ø/W48´,ôtþË¥1þeÁüËŽúà_Ò)ÿp%Þ ÿ2²Œ™×‚GÁ¿Ì@Á?tê!Û¶Y¾¬ùÿe ›ÿâÇì{gì³N &¥A0“]Kœ—è&ÌXö5æeìaaL~‡ `&D"`æ› `Ý –ûú{`cM„ 9E³FÀ¡!`ß+# JH±F@»>„»—&Àî¥ 0O•°mÌÚ ˜k°‡‰0Óþ¿‘0©að(¡øƒ±3 ^»7 ’——ß×ËègÜ$[otnŸ¦ÁSƒ·iØÀ:¡Á—¤iðz+ jÃÏ_Ñà¦.ü >‘”:× ÷Bƒž m™½þlôÚ­q°K„ƒa‰ƒëÍy°t&¯æA ©ƒæA¯òÃY6˜{IjÜ¥ý f#hx°“âÁ^w™‡făILfð`¯²Ìƒ˜ÏQÚ+dã`/»ŒƒC3ÂÁ^¶{]Ý8¸jß•q°OY8Ø«·ÆÁ¢pg|O±ÀŒ‚à`_@ã`z%´éÿƒÌƒܸ¬`pÀºÀ`òvʽªƒIìÕ¯a°/¨a0&ƒÉ0Ꮰ4 6—½ôn¼ºhTB“°`Y0)'‚y¥†“–%,ˆ3ž·ö 7 %†A§`P9:ƒN3bLrˆ°`™ŽMÁÀ¡]³ óf 0è_¥aPù8»J`ðU$²aðñžÃÀ ŸzÃàÐr`ЀÖ0¨ñƒJUÄC@\0 :qG³ nü) æfA' i¬ þ¿F„ÖĂé„•Ùe`A_š° ÓŠ4 ®‹·ô™s7Í‚=‚΄ŽEª»£†A á¡`0ÎÏÁ¾w¦ÁnY4Ø ›‡*»“î¤Îî¤;¾^¦Á~Lƒ}:¦Áäž öÕ1– .DB•wÚˆ–Ùuãà¶ž³.´óåÑ 'Eã`äNÁÁš¨§ J´ÅPD؃ÇD˜DA!ÂäΦå!ŽÎõbˆÐ¿ âœoþJHˆv¸j7&»Œ‘0×¢‘Ðéo‚„ÛÊ%„02e#aŸñëÌ;ºFBI«Sï\†»Í©wR"$ì. ó sk ×Ãx9õó¹† q¨uÚ¸mr¡ æ~† ·õ‘RÐL˜á&ì*bÂ\¿ a®Ÿ‘°oCp½MwFÂõvÈHˆ<›£0´ôŒÂÐaܘ“q(D8Ôf¶ö›‡_‰·U–M„¹1&Bœ!Å&‘!Âܼý†µ‰WXaB!JDi"BhÕ>ÀežÇ›3ÚL„=ŒC„¹\!ÂõöÑE„(Ù¦}„² uŽ1(ˆ*Ï´30ƒÖHØý46Õ 3~“5©Ñï,}çˆ~Çbß´ÓÉVõÉ.ÀC[ø›ý Ú˜ÛqùGÖ€n”[·ôؼYÏŽ0ÜÚýç½Kkýç}s~ný'öŠÉ}¶º÷!} ÓúÏíå’aÐ.’JRÿÅhü`n~Óhù'Ìñ¦ rápë`äŸ-É´ü3Nèרþ´–¥ÕŸûe2´ú³•¦V:Z?¨?é~ØâO÷!âOÇê[üéä=“%ÌìcýK«?µ‘õ¯ÔŸŠ±·úÓÑòVÊb§ÅŸÑµøs³j3êO›ƒ´úSò¦Jì2ˆ?%²hñç÷H³øó”„yZyíç®ug´ŸVù´ö32Óˆ?'3˜¾­ü\ÿ~£ü< „–~*ýÈ ü´-H¤ŸV ÒOé–Zù©Ê­ü<ìhÐÊOZ4ý•ðs¿µû§…ŸÖbµðÓ²´~®Óö¿áfGúW¤ŸEÑ~F´íg7líg4ÏÑ~æt"þŒ0-âÏ´ñgZnñç¡Ï*Z¥í§ŸÜ¿Ð~öÙDûyˆ¯Zû¹eÄŸöjñ§o¹ÅŸxùÁ,þÌ£ðWâOëøZýiurÔŸã´ú{ix:V:ëQ«?sÊQ§–VfFý™ù&êÏÜPª?åmoùgýç7Žå0cý§F-=6)B£ÿŒÊÔúO§ÖôŸn8úO ;-þtb§×ØC³¼x"1RâÏã±ÁŒÅŸy#þt.ª:Y«?yvÑ~Êí§_a­ýtF©Ö~æÒEû ?6cíçA¯ö–~b«;cz–~z“CK?o®¥ŸNüÓÒÏž­ü<øþoág¶'Dø™y#ÂÏeÞþW§·ŒÛÿZ8(?£µôÓ»DZúyÈAa~Ú_+ÒO€Aú¹ê,ýôoégÿÊÒOȱT"éçw¹ ”ôScº•ŸÞÜ1(?7Çù¬ü<ä9ÔÊÏo <³Ìw6³ŒÜV~ö®hå§–V~~càU,PÊOÝÎV~zçK+?Ó$håç!‹°V~zD¶ò&Ìãþ¿n­üŒÌ/ÊÏã§ÌA»ã~:yZ ?M×/ÂÏ>’•Ÿîf„ŸÑZøiËÂÖ~¦ß­ý\~þp6 µöÓÜh?•±¥Ÿ»|Û[úietK?»aK?]D‘~æŽGúénŽÊO’Öî%Þ;…ý2#µòóŸÔ ü\þ1 ?=ɶðÓ“@ ?óüDøé™­…Ÿ]ÇÂOçbláç©Ms-ü̳ÐÂÏ(6%üü5›¿xyѺOÏÕƒîÓBéè>ÝÏ!CRïï;êCËÀv@0Ž˜íÀ#÷èö‰lE÷Äv'¾ÕÅv竜3a»k»ÿ1y¼tN¢À^´L†e¾»—ýG\ïÞ»¾ˆï”h=^Nt†8Þ}+YAï>”ã=€—}î»+ÀûzG82àÝ—ÒQ™ïî—ùeƒwÈ”#ëáúúLx‡Œ>Ë„wHvsM"OÔÙ&¾û–í Lšï`ËÏ«g¾Ãëx™Tž0ëatÕ€÷ZÑ‹ï‡N"Ïg~†ïð~–a‹+ƒS¦.Ê´s/ xÏ> <Ÿmq0Qt—.†îr²Á;ä"X¦€^ R˜ðîÃoÊÞ}°¢–Íw¸0÷ÑÃe '˜ïp,K>Éw5¼&'’-à=§—˼$12àåÎð0J¹ò1ã¡ûhñr"ÅÂ=EôžÃ[FÄxÝ3Þsz«¡!/I’yIgÈ{@¿ÈûLà`ÈóǨ•!7kç.xþ¿™Ý>“l+Œ×ÝŒ‡<¶W‚çgÆÃòU;êÄxÈ.êã}k­Íxß’Ü2L1&¶!ï¹½ZäáPlWŒ÷ˆÃ‰b<”0$jÆCR i7ÅxÏe_3úùŒŒ‡¬[¼f<ŒH.´Íx¸ãâ71^73ÿ3:½Ô8'»ÏgWb‡0Þƒ hlYŒ‡çžvø}Hà ŸïY˜à(ˆ— Ç„‡¼öþ>¸-SHÏÂ9É;ŽŸð> âú(äáõù›ð0›á=·ÝMxý<òp[œ†<Œëg‚<Ì&dfCÞ7žÍt„<üž )ÔøÁȇì,“×'ÞrÿãáîžÓ?Ì7Š»ó^³Ÿ1'£a.Î"÷ÏWÉÒ~z}>ë­›kÎïEuâ< <θæ¥ãÆ<è·&£Ï$ æ%+K0ohW˜—ä.Á<4¼Ï$¬ æ¡aY ó’Â&˜—t>Á<$â!> óÐ N”—TB¡¼¤ å íZàéL8¡¼èËCyI%ÊKZ SÞP ÌKž¥`^ŸŽ1/šä`^²…ó’ÐÏœ—+aÌjó’]0˜×ǘ×gcÌKާp^d~ἤü çõ7çõE6çå”yÝqs^6‘óp.<_s^5s^Ÿ9¯oA/IŸz=Ø zÉÐêôz´¼Ó'lÐŽ%Ðë_ôœrʜ׋óúÖ™ó†FÄy8a8¡Œ“7 ù’Öaß!QǺ—òì”®1&>úQ©Õ•~÷³¿Ï—´.–„CÃ.2¹¬StIg&ú&D8ÆsTÁؔʆ¦R26õlSCõçÔ JÆFø÷wž¤é¼®ÿjž¤ãßÈ“tÿ¥® ÅÝ_”×(Áâ¾%+½–ø+Ùîš„•¾÷+Ð Q°š9¸Ü\$©ùJ FøU©I/5Ì¥¹,#¿¿ïÝ«šK%Ïö­“>~Õ"›•Ú«…k磒·J c_ At_ÁvW2Ø_ö¿‚]é®õð+©Ïg%¹fÎßÀ_Iÿ.y÷÷w)œöo˜ï´]ö;_ÉËT×ûÍâºÀ¹}g‰ê>}Š„¾‚:û£ÒxëGè,>Á3çÕW°_ÕŸã ×~%ˆÖ¡d÷…:ç5 ÓJ~É?x]j´ôáùû»¼"_i羿±gdPq} lHFÉK=JêãÛçp¶r~@¥ˆÆrEx}­N÷àõÕ=+˜S¿zyN|dc=8¡’ùJ¾7ñ£_!Wë\úճͻàöRð:¬‡J^÷JGº^GZ=@•8X²³åëëC=:¯ž®Ë]H7/¨&ø£S%ðŠBÉæatáÅÉ:/àõ0Ó5ŒBTò®ÓÉÜêB_ˆ»» cß³áôdÏþ•ÔQí¼j_U§ó».¥N/ûoua•äWâ.(3ÚWro?K¾.T§óÛÿx(^¾gYXAÆ 3¹xvOõ`<ßÇ=8øyó+Áç婸@uð ïjÖBó¯àv;Ë]ÐƯÄ]¸ø©ü+ùºPÓÞ¢ŽÜóz——R³ïÊ„×ßõa·‘`cÉÎV^uáX=û¿ˆs®Ñ ‡«ýÁ_éPÞ»×+ïÔ{ÓfùÕæ¯äYù)¿üW¢.?¢„}È®Kí!ž¼ZÆccê®·fç•%•ìÏÿT©³×uqºÖ-,):Z1@ÿ¡P£ü¬|¢ôMtÅv—\»§vÖîÀÁ_­î@EÛ¿?‹•sV¼’WNŸª€s@%[ÿJ*ø1\ïuu.Í#ëêäZ®Ïê»äSA‚ Ü[‹¢„É_uí ¾}xhNåké›9@•ü8ÿ­6­»o^Çë\£pv¼¶ÛµÏ÷ cÕƒíð°n>}½yÖMgß9Н©‡ûò¨?zϬ{}Ò¡Í;—° 9™Ý]¸µ^X)šœŽ;ì¹Î½¹Sº'• ‡%JþkêÃî>ÜZ«¬ÈÔrMwûX¹êcWA_ÁÎEPê¨OËP°òVîB7â.\~.RÛøzZ‡« áôÞůؔ¼î”.úé.HHü•t\²qýÏð[`³Séøyî•zqžóÅkyÛuvߪ³ûÀEÁz¾\ Añ :ïë[µññ¹–çÇu­÷¼ôY/÷Á˘ï¹L\r€º:×ùc1´^õ9< ¨ïe-nž1ÞËs¯.õ!ìWòz2çBx½-‡x9ïUk¡Œô{»8oç@÷~ú zô«î€Åíd(Ý×B»L¿’{˜“ñJ^ç¿‹ÇžõÙk/Ä7-YÌ­¼N>­ôAði{^ÓU@¬iz­H4ߥGèóyØþÍ3-GW¼‘×_Ã2rÅ+Y¿ÑÄý.\ÊeÉšCÝîû‡ø“’[þW"ø ùxŸ ø–5ðFà{JñÞ³JÁÞC‰VÃâ=`ž‰÷ÕBG¼Wq3ã]ßóqã!.#ð¡ŽC>ÔÙGà;½ÓŠdS¶u&¾z[%EL”|ÍñÕßþMßW²3 iâ; }·lêC×ÙՇͯ%!_ý꾚Pb,,æ[&ôU‰x‡Ð÷•œ^íŢ¾#\¬°Wn«ïÿkÕEê«’SpYÔ7þ†ÔW%œØD}ãq÷ ë5M%EMU"Ö"÷X¯b¶â¾éWÅ}ӯ؇þM¥çþ.fª_èìÈ}U‡S¼¸o*)î«’‰ûªDUº€²˜iúQa_•( û¦’¾éàî‚k¸ )!ö 'Cê«q/6+è›~SÐW%ú"èC‰Ì«{à’B¦©B¦©NQßÔrQßTç­óõ»YÔ7¶{« ÝŠ¨¯DS#õMíì×^‘ú¦_ut6·ûÐí3U‰î±oúUaßø+pßx$rߨÊã>¤•§ûà:MS;Å}Sâ¾*Ñ'(rßt6èÃã><þPEî›KÞ½ø­ü¦’¿±•·û ó#øM¿*nš~Uà7ýŠà7Ö)ð›Î¯ûà–»Z‘ü†v üêï‡oEßø›¿©¤ûpì7•:M¿*tšJŠý¦_ûÍ%¯{õŽì7¶³®Ó½+öÛ û #Éð7þ¦ào¼k÷ÀítþoòÞ&Ws]Iœ÷*î0k‰%qÝ“ª€»€DΣ7Éý7ÍÝÌÝù÷çáPE|~(’NQMftWCO›ÅàÓÖ;µ-â¿j9ŸûÒÚÇ5})Ç›…¤göÅñßf1ü·Õ›È’è*Oµ-€õ*€›ÅàvU¿÷é[rXGÏàvÕÓ>¼r¸µdp«'}.;ÞOËù|xåp³ôñq§€·ßéƒ[úpW¸]õžÏ”#À­Ìœûº@XÇb¤Baí–…³ßàvÕuÉ+YÆþô:ÜJ¤êMú 2óøb™^9¬õ8Ü,éƒ,éƒ,×õá•#ÀÍrïcìp³¼çǹӇ°Ì{å°–q¸YÚýᕃÀÚ¿'}à¸?é÷zžm‡@¸]3{õ¤,ó¦oÅõ*ÇWn$‰ëúì8p»jô}'DXý|Ÿ½ÀÛßçñãÓ2?î”ãÀÍ’Ч)¢%ò¬aù¹‘’ûƒJîÚ¹¿¬q”½É~þ_@ýÚЋú;oQ¢þNætJê¯âìHýµ ©¿vˆ‡õ×z”q$ á™;?h‚š t…-?ƒD‰‡×8,½sX ìÿɤ=Qä8?-äÎÚ¡¯ø„Õâ0–^¹¿êa`d& Ìî ¬•: Äè^ D—0ß¡[B—.9÷Dä_cD°@µQõ*Gv”dC…Q& „å&ât,[ì_;…牋…(p¶“\%A`i˜ °Éþ«–ì?ÇŠ °ô– °Z–[BXË|x0äA´DX:Lˆ Ý7Xê% ¬r¥æôáÜ``½Ê!T-ã00‡‹(EH¹ ,·í‘ qã¹SDÜ_N5¢À28DÙ4A`éÝ#NÖóÅ‚Àâ%A`©Ø1`tÀÛï©ÛrTî¯ö÷•Ñ41`­Ç1`µ8¬W9,#üÊ…®W¯\È«?•N XÊ,.1`é 1`ñj¦ì 1`-ãø©Ü_bÀZ3É¿AbÀÒã™>èªôá ¿æø©ZηzäŸn¯ `vO0ç `­ÆTmÈT:.Xš"œ]Ɖ³È)¢7§ÐoKˆ`é­Ø¿bqXúvªÿYoö_‡O¥sŽžj5ŽÿÊ0ˆÿ+Çeðš\`-†ÿêoÇNÙ0á_­Ôá_­Ôá_µdÿOÖ“ô þ•š ÿJ¿Rá_µô½Þž.p4 ÿê5êUÿjoþÕ2ÿj=ò!ÊþUËù|xEøWfá_î þåKð¯^#ùIøW¯zc3'ˌͮšsßúþ•ù ×‚à_½Ê¡Sé!á_½j\[oÿʈ þÍ.~—ð/7Y‚µm‡¹éüË­£à_ñüNd‘Ü® ýˆþrèè¯6äè–kC¥Zz>üŸþJCYÀ4ôñqŸž/<é/rÔT<0ä—»c!¿Ú¹ºsC~åæ¾Gìè8!ˆüÊ€ù•îù•Ö‰ü²Ã~µHºÀ!7àW¿› RÀ¯vÅÊ4’{üŽøÁ27à U~aù“dH ö‹¡\ÁÞ|¤À’г ·±oî…ör¿'´×O?p“h¯·°-õS- îõ.í”àDE¤ç÷ú!i—àDŽDjÄ{½Ii&¼×=Np½ì Ã½ÞF÷ú)µŸð^ïD½Â{é“ð^V#¼WÊ.eï„÷:c®'ÞëGèC‰÷z)§\h? 뇼MŽ÷ú%¦Ux/Sx/-Â{ÙÌ•Lb.9eˆ—zzˆ—€—â½Rñ^„ð^Ž¹ã½œŽ÷òæ ïå€ ïu†ÂNÀׇ ¼_¶,ÄWêIúŽøòV ñ- Ç\ˆ/ÇFˆ/}pÄ×/)ˆ…ørô„øò¾ñeKB|9í…ørô„øz™¦|È2ÄK½…j”x©¨™ˆ/ç– _zå/KòÅÓ"Ä—Ž ñ ñRN!¾œH‚|ycùrПtÕ.õC`!¾R1!_ï!Ë4È—> òåx òÅC(Ä—}âë§ä½B|ÅBÄ×O‰y…ørRñ¥ßB|ËËÆ-åTâË«ñåÍâ˵Fˆ/ïÂLúÆú•‡Aˆ/ŠB|«­W<àÜ'[ ¾˜nD|Ñã@|Ñv@¾õ€|áy@¾Î¨ôòÍàÇùâM&Ì—Y`¾l] /Æ” çåSñ¹Z~õ9@ß#Ý@_ŒU€¾ì@_)#Ž` šJ‚¦¡¾¬9PßÂJ¢¾¼Žú²%G}y'…úbù ØoÀ}9¾‚}9v‚}ý*P°/^ñû²Á¾¼O‚}ñˆì+eú½µ-ØÏ|¾Œ!“v úJµD}±Æê+‘ 1I„ú²q¡¾À@}¯dtB}9ìŽúòÆ õÅ£¨/§°P_Þ^¡¾R†¨/=Pß³Ë>k[ú^Ê)õe…úò õå:êËþ õåØ !×)ŠE¨¯Xˆ™JKD}9Ý„úrZõeëú⑾Ó΂€}Ï.û´z8¦û²‚}¥a_L7Á>½¨õeï„úâš}3¸;¡¾)¶L°/T°/Zz²ÿçûJÛû^‰hûÒ£€}1.OzÀ2û¢Á¾ì^À¾x4û²7‚}9g÷Ř ÷µ)±ã¾|2÷å’¸/ë îËEV¸/ö)ûòª™ðÙîÓKêoä@J Øn––°Ç‘~ˆÏR0 B’$Rû‰ó „åÙµŸøSRJÝ$¤Ò»ö’æ ÂB*QÚOHšI¼Qû‰Ãå E{Ò~ u“Ì™§ý.Ü|j ¥ý,j?‹E>\)IûY-óÓBåd±Pûy]òAÚÏb¡öÓ¦çÏĀŠøóaר™“ð³X(üL‹„ŸXKwág)“ÝWÊ&‹…ºÉb¡ð³X(üÌað³”y>zcªÉkH%&ágZ$üÌk$ü,e(ü,eäA–‘i¡n²X¨ü,*?‹…Êϼ‘C>´]ù™)?«ÅÕY¯´Ÿ¥ µŸÅBíg¹*}Pê&Kê&Kj?s¼¤ý,WÍý>Hû™×<_|ö³”¡n2Û–ö³X¨ý,õ|ñáI>´Ÿ¥-ê&ã‘ô3§ºK?ëï)§ˆÂÒ‘i¡j2/¢ð³¡ð3;'ág:ð¦ºêÓé>Kj&ÓâºÏ¬VºÏR‚ºÏbIØ=é>£iÉ>ËE”}–‹(û,e(û,e¾¸0Ó…YÏûm–s»&dŸÅBÙg¹&]%}…¢É®}–2”} I¿j™û²Ï¬ùË5}–2}K: K:–ùa‘è3Û’è3œ”æ3 ò€?ÓUAµdi†jÉR†ŠÏR†ŠÏR†ŠÏjùt@ŠÏ,#Åg±PñY®¢â³”¹ö–®ô¸î‹ |Ë{îË^>KÓ|¦e¤ ²¤ ;ö«–>>œ’à3[wÁg)q÷[5¾ø0¾ø Ágµ|l‡BðY,çóqcî/>ÜéƒÊ\×§eô¯\ðY~?[º|Ë$øŒ-I>ã–K:úØW„çKÿŸñ± ±g)ó´­j=Ó0c;'Ãüpç=>vs¡ô,ê$‹…JÏRÏu}<=RzK:Pp_-ðî÷CBÏj™»GÒy¦!»ÏkfvŸE¨òT‘o²%¸vŒ¯‚»ûÑ`»glûž)’EàîoÑwïˆÓwïýÈ¥„Œ¸{ŸÏƒ}¥ ÁÝ*óq°ï}âО©oõ£ ï#“ÀÝûü¨Øn]B%ž°ÝûJX$lWª• Q­°Ýû†f’à(ë¶+b»tAØ.û#lW®út¡ß 2*UÝ•Dwé’Ð]:p¥²¤[4“K¾Ilô¾!Í$ºK™°Ð]öGènYàÅ}˜Ñ¿·íµe_„î²/Bwy•Ð]±¤^ʃ©£žBwå*¢»œBw9êBw9ÆC><ÁW,Bwé•Ð]ŽŒÐ]Ö+tWê!ºËº‹I#pW."0*Ü¥Sw¥â¹wøùâ“.HyIh”N Üeoà.oƒÀÝ|ž/>Üå ¸Ë‰"t—m9ºK¿…î²Ç‚wùì ÞÅ Ýå,¼Ë¡¼Ë‹ˆîJÛò [’1ï²B£¼ÈÑ]V+t—•Ý‹<È«r8ïò¶Þ•zïJ=„wÅ"Šeî“-à]Ü(»R‚ðNè®\"ÞEgµÅ< tÝ tW®"º+WÝ¥åL¨ê;ÏíÙÿNtWJÝeËBwÅ’Ü$ü¾x xWÊ•2„wÙºð]¶%|W,m»¹Äwåï„Gq›ïÒ@tWê º‹)è.6îrô„îÒ"t—õÝeÿïâÑ%¾+%äAôO¯”!:*mà ^i‰/†¢qAø.]¾+⻬Xø®X®±_#Ò"ò‚£èžð]fl†ÎÑ¥ZFzÀzGzÀ"-öBt[è.ï·Ð]©x\[%÷Çv.À]Qÿ³qQ!´Ëq´Ë®ÚÅEBv±e dWª!2*eFÿXÙ•ßDvÙ]©öÓáº0Ö¥ÓÂuÙ€])Cd—Ãý¤4dÿuÑý±"²+¿ßóãY¶Ëá}Ò:)pM Û圶+õññäÛ•«FÿXÞ/.8¸Ë¦ßíŽÚ•ò„vÙ®°]:-p—íÎìÿ~„ï8¹‘Þ(AÝk4wu22T›×­h®Ú‚¨Iµ‰D!<µGÕ&¥C’l¾b436gj"œ³¥ˆÓÙý÷’FJ’Í7¢PJ²‰Ì¬‡` ·X-¸JbP ß;í™âñ½?轩RšÍeilI>¼Å2À¨b`Róø*¾¥4›ßRšMìvÍ&I‚Ej6g„¢”f³”1f„¨qÑæúýlŒ®à®K¢ÍÁø$ÚŒÐv!Ú\eZ“,ËEù%%%t&%¥fŠ6çGˆN³('E›«õ·0võ…è|wÑföE¢Í%ÚÌv$ÚLŸ$Úœ]³D›V¢ÍŠ¢Í!u$ÚœŠ‘¢ÍbyÙ?ÒÛmf ‰6g Ú9ŠšÍy)îŽ4›Ù½ˆÐ™‘>åB^EÁcŽ4›ÙAi6K=Ôl–«æÞai6¥½Ìþó‚ˆÏ™—Pï8#1›y/¥ØÌ®H±™sBŠÍÒõŽ¥êKë”lÎKA\²YϹö~ñAšÍì4›9äÒlƽ”d“c%½fiYý¯ßì?}”^sI¤×\Ó‹çú\¯™=‘^ê5³í™ýW Mj=#ÎÏÄse¤×,õ(©t|_½‘V3û/­fÞ7i5³Ç]\5DçV …ŽÙ=i5sì$ÖÌ9#±fÞ'‰5ãMbÍ i5³i5ÃKI5s<%ÕÌ»T3‡JRÍ실šØO²!ÊóÞJªY®¢T3CäJª™WIª9ÉM%Õ /¥ÔLEޱ« ¡æ;Š n¸Î Ï•¡’P3öN!Ô,e¨r¬–©ûtmˆ.»'fvF:Í|˜¥Ó\evDWK:Íœ®ÓÌÇ]:Íœ°Òif‡%Ô\ÿRç˜Ã'¥f¶$©fº:cêKª ´ŸÐ‹Mlh5KÍÔ9æ4q­fùM­æÚ‡ó¬š´škVsúI« XDÖ,}P`L*óá•V3û'­fÖLXWz,­f)#â^¹V3ï¦k5K;Ôj–Z©ÕÌÇNZÍ\†¥ÕÌGUZͼ Òjj׌Fm6Í"CÆ…ä’OÉhÄ[F£½P^U2}sÙ_ÈhÔ×^£ËPóÑV„„¥¤!Z0ÇžÕ¬Š†­*·Õªd)U]Í·té. µ*ÚJUaù—g62DyÿS™°Ñú_ŸÙèË´j£Ùc^ò¼|3‰Ûà–2¬§ä,bE[Î"ÖTJ±ª­”êÊœEª«æ,R]YJuÕRª+s©®š³Hue)ÕUK©®ÌY¤ºjÎ"Õ•¥TW-¥§.s±®-³‘žÖ,źþ™ÌFkÇ6°ýžÙèOÒß¿¬‰ß­›¿ûì|,¥ß?<_júû™’²´ÿ?f6:ã÷w9Žþñ¿AŽ£6Nß‚>XÆŸMØ~˜õuý¶œ‘óbLç…t,¸ú‰t;,1,¸úšzܬ·q[pu`¶Î7ïmâׄ'­Úx,@î’>†·wZžœRfÃ}ÒF}í\®§¦\`N©†s\fÐô6¯Ó}<¶Ý€áÓ-„ÒæZ­ÄÁZnK”Ón!ªµŽÓí§Û” 1VÈçÕ½mšúqX¢œ5×¹“ïHò3¼žé‹ûgÕø7Š~¤ “¹p3è|·´D~‹X…kJ¨Çkã8«ý°tÚ[_ÞÇ}“°Þ‹îÁM°ÙO:0nßÐ÷²Ý£¨w-üšzõæ. ÷ó²,9¨×Ÿå~ÒR=¸…Ôú‚›²8„îç³9½p‘n“ƒÏ~NK’ƒ†|‰ëíº)ÍF†×zûu·Põ֛枮²-V†÷i½Zý>åUc~8Õä‚@boîB M{Ÿ:ûš{þ8 Þ¯ÝÊpŸN½¾ÆÓ}Ò$êt`UÑêt`Ý탖ëÔÌS5ãK¬fL÷èå¢×ûýjž9ÜûóÈ#‡ˆ½»ʃÓ;ÒU—Þ^Çð»¤/‹«'—^cº%Æáº_Í<ïíõ<~ÂðÞšeêð¼·® :7 oãÓ'•›èØ)7w’†ÞtXí¸N¿IJ»ÐÇ8Ü%}h^–O†ˆ95žÇ-ú ÛÇ{kÞ©­9ä”è÷1¼Ã¼³·\ˆ;{Ë…¸+wo¾@Ä“â×,N€÷{~Ÿ²æ1Ý«lû~ìs⦹ô ¯0Ÿ&ÿÈÑ×voõç¸üem=çµù€WòYûþȽiú“>ЫgºWlûócExîW'Áóµ­ Y3ߺ۸ŽôÁŸ¼ëè­Žñu\gÙ{\x)sòù~êÂ[¹•)²öü¾•+u²ÿñ´\‡ú¯Ñ¼Ž9ôDùè]çqmsï:Ͼߦëlíá³s/§)±Öám»Ny Á¼ðV>ëžæÂ[¹Õ‡î:î„´-»Î÷ÖMQoèBÞ‚&ôˆ]€Bw$WkM^qÈ[çVˆÏÂÕ®CsOEÆQG¦¥“–ûÝž§kí°5óTä½uŸÔ•9ôôøŠ¥O(eøúÙ÷»ÒÕ>¨9Å‘ðó ïÙ!÷–xÏŽS8Þ³³“p¸ _ú*Þ»°ehpD¾‰u¸gµ;˼®ÀZï¤FËtXß@;à[–+@Öé ¬U·Ýøì(ÇLÀw9ZøI¼w½Ï¡ŸÃåW‚+î]XÈBÂÛåWYÇãê«[ñ ‰ö¬Þ‡¸’ÝÏŠí™…¨ìtõ•Ê?ëYè¹NÈÕ]|•õ>Þÿ“2Á^­õvýÕ£tM{f!Ðp°·5ôºþêéêËtùÕsý àR÷'—`Ï,„¦öjKö¬Þ‹e.—ÑGKÀzÖÎÉßràŠKäÀEn”`Ï*!nw°W«÷î‘C½Ú’C½âãTÿ/²¿„zµi‡zy4ˆHÏz…쎽{þØ}œêÿEž„HokhºýQV+"=³œÄ~§Kè—Å)wB½ô‰H¯øD¤W'ÒÛšS ÔÔ]Dé™nGzfyˆåA4t¦lȱ^ñ›X¯4åP¯.Ч×g:–p€½q¤·µô¼›‹õ6˼å½t¨·YäA´íPo³tןs÷à8¯vÅqÞVí˜Û<#ÌÛŠ<»Ï€yÕc‡yÕâ0/úá¯:ܳël¤«ëi¹ÎIç o+3æ½3ŽòÌò²õÇ¥óøèÇÖåAéÜ+u·YÎK÷‡]q·Yºkçéó•½èØ{sŸnï¶*ŸG¾¨#ïý1Ý.už×Œì<ýw€í:º«Ãáð®6ãðn«v7cdÿŸ ﶦœ?Ûmæø¸7Àvµ™[½O‹ˆ†ÛmRœÅ2Žz{ØåÏû彡"‹¨nk÷½?-sȶ⨮zT·ýn½ÞG]çOõ[Ðíø˜eæê½r0·uâytgÔhv]uÈè¸>‰…Ë ,®XÈÂa2>äÜÒ‡V¡™•™äÆœÄJÇIÂåœ w'7Ý#=pbàªåù(ñ>þT_dñœƒ…И ,dñÈÀÁBÞŽ\.Æ¢à0ÚdÆœÂB™CXìðõî ¶Ï98¬¾lÜ)¸\ŽEÁå²é\­vÞ[WHÁ•:HÁå¢/ Ý%=@ .lqpõ*9P,óÓâj&=@® Y¸jq¢7C>\¢ŒÈÂÁBŠƒ,\-ã4ê‘Åi8”!=@n³Ð‡KôïÙ–SXù† ‡2ÇFÕš†Ão*nùÐEíß郮q +ÞØbáj5Ε¦ÉÂU‹³p¨Æ¿¿Š…«õ8…U¯r «t‡,\qÜX¸r Y8Xn.¹µÈ‡Æ‰X¸t“$ wÅmfi·Õ‹äAä@§ºC\©—\^d\½Ä)¸Ò[rpÕ¢þ HËýÊâ‘8¸Zæå(ËLnâ´õWÊL¹篰õ#êëm/à,$KIÁånQ\½J.d§°Pæ`÷œÂBYœ‚Ë2¢à¢{bà`è´¤º¨·ý÷uî¿÷q'åk¢àðg&ÄÁ•†ÕÿƒÙ4DÁ•"N_¡È UæôU©—.º‰¹œ‚+ý#—t§àŽk’·Y|dø™ мnÎÀÁr“Ùs®–¡ —¢Òˆ+W‘CS>2pÕâ ®rQ›(8XºÝ±·DŠÅ9¸Ò?’pµ7NÂÁÒˆ,„Ë¡T; ô ‡OúnYþ,ËPÀ;Üë„w÷F¡ÞæÂ¯ÜÝ’z›Ïä^KÔ,èO.¼§£7·‡ç¶³Œ“Wó•®ÔŠ\áÙétª×H½ÍW™AD½¡L¥Þð›XÒ¸7l&÷–GÞŽÁÒXéÍC2W”qò õŠð¶zä@t…ä'µIöÍ6÷V6’‰zH¿áª#^9È/ú­¶äôUq›ü[mÛù·â'ù·<¸/eÈm¾éC'’’Q3¸  ®Ü:2pyèÉ)¸Z‹|Uä+²7Na•“‚ËÀâàJI•šI•֧|H©¤sXÅ+²p A4\-®¶ä4\ñ{ʇ˜S>äUNbÅ´ — —“@,\¹(=ÐEò /r –P`ÎÝ'gárÌEáÛÔä†ËY,®\uʪJÄ•†ÈÂå  —·W<\zyʃ¬&=à¾4\é±Ñpµ!§áj†+eHÃeÓMÄà‘…«9••¦ˆ¸Ò‰¸2|$ârJˆ‰+NµçÝkyŸ½egâJËdâp z\ÖZúº<ÛäâJwÉÅÕjœ‹«eœ‹+Õ8W&c—êï¼ë„!WºF*.×4QqµŒSq¥u?‹KÝ׃->®ô…„\qˆ„\½Ê ¹ÒÔ¼·K†<ˆKÈÇ•†HÉåJ$J®øDJ®Öã”\™ŠC.¨3C„áyd¸7N®Œ'9¹Ò’qr¥w·<èÜ/Š“+µ“«e®sÇŠ“Ëî‘•«Eîˆ`Ó*Ы9¹U sè.‘4;.yÄJŒ•+£@V®–Pÿ£’쾊ŒC–œ«Eî÷Ç>v$ç2$ȹRú¯s ¢çÊ-!=W\0z®þvz®t†ô\­EdKéBUZÖþ’ «M½÷ÇM"MWnäL£Ò… åYwîÂÔÕש™§ãø˜gäëjKéAòuÅqòuÅòu¹õ_—5‹²Ca´ôA­·½–ë¬}q‡ŠcþØö"â¢ïjËs쓼R† ^-ã ‚”HÙOÝ)öù¼Î½ù#C/ï”H¼ZËó|xE¯–‘1~M>DIäÕ2û ´ôSwŠ£L"¯´n\^éqKè'¹¼ZïóìóO\^™¤óJIç•¶º|‚©¼TÁÞ_J-šËµÃž³h.Ÿƒú=—\}’ËGîBrùLá5*.ìê »Z„ŠËŠËGIŸBq¹`Ÿ—ïL*.-¾ÁÏD}0´$öì·Dš¦XDœ^AÅâÛâ J.«…ïZ Kj.‹…¼Ç²$¹ ƒ—¯>{…äòUf¸Ð\ 5—Ú›šKLP‚@yÐ(R³X- zט$º,Š.‹…ªË7YÉ.ß¾Ÿ±ÛÊP¶XÊPvY,”]Ë8÷ßòá  (ÒBÝb±P·X,^¦EÊK,‰„fT^‹|H …‹ÅBáb±P{Y,¦½¬¿ç‡WÒ^"æQ=e§à?ôå¬ íe” íå_$¥½\¾%¾ŒYâËR†ÚÅjaðß´Ü¿©¾,ª/KoäCÈK؉/cª‡ø²”¡ú2¦È/ã‘ ùe6õÅ©/KSÏ[Ÿ˜P_ Õ—i‘ú²X¾¸ õe)C cº f)Cf)Cf)“>ô‚ûòù¥³ü¦3¯3k•3žçaf===˜»³”¡Œ±”¡3n‹4˜¥qj0Kß}\„™WH„™Ý•³”¡3»"f)#b¦I‡Ý•³¡’1Vôbæý—3]p)f^#)f4$%fÎh‰1³Z‰1ó"j1³i1ãuZL½.CŠ™©¤˜±…óUjÍPcF5.ÆÌcÆ[8ĘøÌKΊÆlHbÌrŘ¥fê1s%”$3]¸Ó]E]c±P׈ȩ»$3[wIf)AIf)!b„%Ì,Iµ±Im¦§6s2Th3W='ÉCi3¹‡ ifvPê̸/g¦ß.Î\—4’~g¾Ê‰âÌb¡Õ2?î‹Ä™y_¤Ï,Ý£D³Ô3cCwï*ÍbI)%¡Ò|(‘˜’ï¤d3¯ Éf´“<õ”ÝWáfhC‹psžI¸™J 7£é_ 7£»!ܤ†½J7ŸJðÙEãC½ùR»“ê͇œSª7_RC©Þä½Oõ¦ÐHª7êœR½72ԛќÙ\ÈZRÀéý-úÍ‹•¼qˆ†CN×I gŠ:傎©¤“õ|—YˆØn #’͵pˆý0Õ&BšpËMÕ&|WhWm"üxQ¶ÙÚŒ +.Ûlýú!5¨Ë6Ûj‰¼”§ !l=O7®’â=P‰3 @%P(€J†æð*àTî‡KkPwrx~æö¾¥ËS•ûúÐmæ Ué6Ø“¸—ºÍó=ì§¢§¬)Í(,Šžb ËÏw±5Êè-Ë%öÓ£§ 8Mw«•ñ£b»uÉ‚Pô”[¼rDOyÆÊçY†¢QôlfÈÞÑ7ô¬ ŸòD8…O¹EOGø”§7Çð)Ohg=| ÂdWhWÇAáS0ìì ƒGð*ArÖËø)Xù÷ø)98ŠŸ²,´³1od}.Y6F1 ð3]ÄÏ?ÇØˆÚ?%¦•â§àñggäÂ)m¬â§`­$Žcø‘5 ds?啸7¨¼ŠTžôQ»‰ˆñT—)€ ,l‹ñG°Ò&¡·Õ¢*·d—Š “""¨ÄðI½™ñ“"†Ê²ô íÊ£1Tr,"†Š¦mÆP¹SÐé>¬}¯, @ò¦ÄÓA%€D•Œº¢*îˆPÉà>  òhÿKõ¦íÐ@Ea¢3€JÌ… ’¤¸&·‚×—þ+€ÊH²NñGX€áSb˜"|Jxs ¡ð)×+ío„O ÚVáSâÍTã§p(~ ^ñSú~ÀÎn½›úŸe?Eq¤#~J„ÜŠø)CJÆO‰¸]?å ¥¤|ˆ[­ø)wßÏØY=C:ÍC¡{Î=~J©‡ñSr,?åz¥žVü”Œ²ñSÎÖÙÍã‡2ÆO‰ˆ ¿ŽŸ’OŸâ§dÌ¢ˆŸ\ÄO‰ø.?%܈Ÿ’e&¨nPÉñR Z}$"<1€JF5Q•ð‹T2ªNDP‰ÑŠ*Á’)‚JƱ)T¸VF*¶"€ foÅuõæ)€ 4u$Ò|$Ð0€JÒq@åŽc•ƒ»û ’KpPQ–” ’C¡*·ÂüÿAhóþ,€Êz†T¤RQM›Œ ""‚JÜ\¿’»ËkÄ{eñ^YFÜ]–w—eÄÝE™7}%} ð î.ê î.ˈ»Ëzƹ—øâÛ>¨Œx¯´ˆ÷Ê«ÄÝE™àîÒ"î.-éƒ,â½îàmqwiqî®üž?v?gú@l™.¨ˆh¯8Ô]ZDÝ¥EÔ]Z>]HêîŽx˜ÇîS2wQäÞŠ· ƒh»;ô›Ùb§ìþk×kEDÚ…Aœ]²ï›R³Ö*º+Š<ï^@Œ]aE‚°S‘ö¥óÁ×¥ElW\$ºî’ÚSl]þ ¶.®ÉÞ«Úî;YׯŒ’¬ëQ©Èº®vÅÕ¥Oûžò\¥Vò\ÕâD]öEL]VC¢. ê=νJÑtQ@,]HÒ•kHÒKv^Ø-ú^Á\5áJ_DÑe2t¥ÈÜêŸA—Ò[i =—Òsi ;—ÞϾ컊ÚÊ"$çJ’siqv..¹?;gçu¼V!­•2sÅ0?Ü1—E²ó*BN«XHjÅE¢åÒpîsB¬\öþÉÞ«Ìg÷EÊÔ?:¬GN®÷¼™E@QýÏ2ê”)—eÄÊ•2ÆÊ•d劅¬\¹F.dùeÈi Y¹"ÅÊ•zÈÊåU3}%}Ðñ<ÒZ¥Lo[K¢åÊ5äåªeêÆ(¥|ˆû+j®ÇáKQs¥ ©¹¨'¨¹b!5­55“š+¿¯³úÔ\)Aj®XHÍ˧AÍ ©­´ˆËÖÅÎ¥b犅ì\Œ Ù¹ò[>d½ä¶r¬Dϕޞ+eHÏ•zÒ‡¶ÓsÅBr+û#~®”!?W,äçŠÅø9=ÐAÏe‡EÏ•KÈÏe‡ÅÏ•2äçº+?×{¨4åµAÏu¦­„ ƒÍ’‰âFÇ·db‰-ƒÐ^(¯*„¾¹ì/dúÒ¶\={Õÿo±”´?£_¶‹ªd¨UÑVª K­ —ÔdD2lU¹­V%K©ê¶Ø´uäh¨UÑVª K­ê7a¯j¿1õVýËó]8G1÷¼Fòkœ çÿ(7 re¶?Êäú€Üâ2#}¤8ú:Ñæyné^¾ïmà¶$H^KM]„j¶ÄE¬§”aE{$ÖTYM5m‘jÊ2ªiKÄšJÚ"«©&-RMYF5m XSIZd5Õ”Eª)˨¦-ýŸÏ’²5mi4/³ kú§Ò]âóÿð¬Fº¸»˜~YËÿõº¼úó·Â?“Õè‚øªÿïžÕèßÔþ:—Ñ‚Ò_rÁö_ñ¿ÿüƦ\Fýþ“\F^·²ÉõX ìU‰$†¾­˜ÍwaÇC–zY¦¶'ÜhÌî;I„%óMͼüxO—¦îšÃ÷€=`Í·Ç¡˜„Tó1&ÛGêp–+ôM–ú '7Gã8ŒèPÐrž¿ñÊ8̇ ä{’e1.ãõŽ£€•Æûg!àúoc€µ¥epCQ0ÝrpC¢Ã2øz°Œûpƒçg¦}Dû!ÎÈ€Ç?^¯À6ò>ºdãlǪâU éõÛX€»oøtl‹M‹;ð^í«F<]ü×8o#&hæ–ÇH€çVÜžq¾–”ñhl™Ÿ/aìhÞyKIíe,÷ͪvurÊ2Í£&îR-ôM±Í’–{‰ËX ÌÀ‡-™7¦ o@£ˆ‘Ζõ(õƒi0`o^oŽ6›¹±ÖG?LÒ1o)¸F7î#‚).‹I:ÐodoøzvŸqžj=~ðdü§í![s°:xõU­e7Ã=̧+¦Y7†=1Þß…¼áïŸ&‰(ý½{Gb¼´œ¦èÀÓ9dñwôšxþèŽË<°¶œW‡×kOèò¸.Üí7¦*vu¸OG'¾¶\Ãï“há/ÝÏïÜåX”.¶lÜH˜íÀ|¬çÖ,!dë¹0Ÿ80kî-‡n‹LÅ o|È´ôÇ&8IïÌê ¶“üãzžqë/L\?‡9„—,ñà#àîIª{ È×ayuK²>ÃŇô¸½ûçE•ʸ½÷ø α½Ïiþ@Dåcw·×\³Ã«úcón*b߸¯ÛfY,Á«Ç¨ÁÀØ4]¸$ÅZ« ¾¦­™.ªYkG·y÷(®åZêšù„´^æ9NóéU„®ñœ‡ùt¾z¼w·#þ¸ ¸Îò­æ1§ fÍ×­ûÄ銕 ÷imÌ8Ï–ÞWÓêqð™â`-ôa*àxf³;u*Ù Ö¹^d®ïy˜W·â´,Ëô;uj@ßöšWxƒy[¯û€¬êœ}¯Å]·!Øw ¿UÕåò. õFÖ|¼\$½ö±ÁAˆÓ—]C.E”Ó}8À]ºá<Ì)|<´L_n ‘Ö||Í)¼Ùx„®èÌ£Æ']¸:)üõàÓ…´ à wG5?–zôà°ÞÉ~Ÿ8ï-i1^<žod¼Š†·¯GÃ$žAƒ):ÉÂ'ÍZ°Mñ6‰íÙx¯ ®®7´ÞhêæÌ÷µCÇKîƒý_·àf=Þ|•»Èè¯Ywù}œ²¶dÀ«…€Øã“>t%v\‹K«wr­yXðeÕGoeø„/ñ²Lói½+]x#Ç#|ê:q7zÐt&önî¾ úƒ ˜æþ^¹¡‡»½­Æ2Ðwâ:5~Í ™ßƒ=Æî –“ï¹»›ªù{½”ÑLãútã•l.)ÜìWr«Oܲ¯‡ÿ„pÂûá ÄÝÙû¦|w÷Þã9ñWÂZ”»¿]µÈÝýµD­èLg_çé3or×v_‡íã°Rû³t_æ@úw¹g¤7¿ñF>}Iã%ýñ›¤—Æ}]¶ ÊGô¾TÑ'դŵ²@Ü]¸c*^táTMÜRÅû Êßž÷Ú^ûÊ­ç}Y¦O¼A½î½ÞËþð þ¦ J }8™íæÆwšæE8ñÏî>Ï\µ^r¶“à æ]XoÛõý,° 7áøCÎXúПlG}cÚBü3@ßÀˆ‹Šƒ¾1MÞô31>[ðóˆc¾5ü6ĊOPÂ…˜¬®Žù†}ÇdS†ù 7©ñçòo>*a˜Ï6)t‰˜ï8t¤10_SäV¾£ëÄAŸm8œúV[ñÓAŸyÅ• ¯LN$¾ ú øã‹E ¯3î®Ã>(ó8ûû0|hûæû:£ w_ð*î³}wyŽûìkÆA‹á>›%Bp†ûÊgâ>Û÷q_ï¸Ïæ·¡Žû¬ ;h ŸÕ¼ ö™ Ükö?é õXÁX„`ä‰Ö 3 ÄœmêÃôã6ÚQŸí8…ßõ¡)!CG}˜7¯rÔwœ pFЗ1ÐÏ© ôÙ ¹e™îÑýƒ—8æ;Ö®•÷„˜ï8u !0_Wüda> çN„GÌ×cðˆùŽ5a 0ˆùÐáF ê˜Û2nv óaZ9胢¥ë·ƒ¾® «@ßqñ\¤0¾ö•‘!ì‹.Ô‡Xã¼GD}ù‘O¨Ï¢O»ÁA¾cùÞO 9 ô¡ >"R"¾£ëˆ® _~ ä;nmLù, >¯rÈ6Ù·Z‚|@êÄ÷„|رªfB¾CÉJùPÑña¿?ÙCöÆßñ*[zã.ñÅç@|‡öªøCüDI}v̵€>hþh]D¾›‘|#Ñ7Gt$ú¦6HAôEØ× ú^ž5;Ñ"€éD–ã—¦KñHôá;H« omg•ΔDߪžß.Iôõµ—<§N—‰úsÄt k¾¾À£ ¢ƒ><Û¼È1_k *(Ì7.æªâ6›˜O˜àÓº¹dˆù€Iø•Û0ߢúi˜ËØ0$Äü NÌ7^eíæC5çúÖÎ^Û ¾'ø,‚¾µ¨ pº_Ù‡'Œûjb¾5Ƴˆ˜°?­˜o*ƒˆ0D&î%1߸ƒw Ì^˜ï ĘO÷I˜oC Ì·®†"ækú¾˜ïV5„|cŠ=!â{ÖÃA˜íoèÜR@>œQ'ÂsÌw7}dæ»ß¸qÄ|Xi¸a'æC_„?2­ ƒn%1ßsÞ‚¾íè»G’rîfZ2}@ùÑÂ0ß=‚ æóåëgB>Ȱûù€2dQÿß Ùÿ÷ 6Ín­°š#&H¤ŸÊõZÂsÌlB‰˜ä£a˜ïAî¶äúIñ› 1ßÓôZ˜½#h%æ¾áü æ»mÇû3!ßFÁ Þ௷R}«ö`¯ˆù0‡ˆ7úðU`¶sÐwOÅásÐ÷˜’Î˃lÉÓÓ¹ŸæCï8,Ä|ЛÓBÌ'Á_™Q|å®ðA£~VžÏŠò# Ä|ÐË_ ø–ù ¨þ_úBÀ÷\ ¼-À‡†Ìñ¡3·H½Ã?Ÿ´$þìôöƒE†eò= kœ´Ð…; !†“NòaZ¬òÙɺùž'–IB¾çÒémB>JóÙ¤?+äPýsBòÁ._„|ÏÌ?!ß³^~ül1é¢ûxMùýqÈgS‹KC>k‹Ó˜oÕ2¤’ æ³™°Q}Ï%rUT¦’è@ú‚€(й¾´rÅ|«æ[H‡\fñI„ç\ß³–´“(>Äç0a>ŒàÉšóaÙ\ ÃÝ"A¦$w~úÖ¬ÐnÖAŸ}0#D:é„Aš¤mÛ­êè{ðî©TŸÕ#h Ïœ:i¡ CgÇ õùãGºí8ýsÝÜPn.¡¯£><|ÚO:ì³þnTß*[â&fX 5ÙM Åé°oõæÖ ö­þܺáû¬žÊôÙ˜“„3.Ì6ÐgKCüžòhè[½m;Óg놠¢¡>󨂾²nõ-ËCÊž¨Ïž•FDj¨É¾crÞ;ì3™1¨Ã>{æŽäúl º ¯€·¿#=âè 5­J ÷Ù|~+î8õÃo ŽûNèú×\â¾ágvì[Õè3aßꌴ4„}Ö›°Lw‰üƒ¡>ë 'ø  Ùké€x½Ë?}Ûñ¶ŸûlɽyÑí_¾AâÒ9ч·'+‰¾‡÷ˆ,_¾ÑÄò•ÉK–w–Ÿ>ÈòaÖqu0–(GÇ|æ2¿>ÜêÿµÐøªMÌg±˜À§ë.UÈgÝãSMyt¹è¡ #¾æPTg‹ý?Θ”8ïØv`#÷ðy]í»Bó)˜Çï×ònÅR ”÷àN¢6d-À9¾äOÅñ½µÇwi–ŸÔGÁñae£… ÙÂiÒM’ãÚ.Ç÷ïê_—,dGÈoEò%Í$_¶D†,yÊ`ùÎ’å Q|°|³²Ëwè“Æ-Šl~²|Ï,ß”à,_–ïBj"ùžhˆ.LD"ùlaÚH>ÈÎ9 DòElîdùB“ûˆ¨liq–ïd8ì¿“6IèÏ–³í8Ÿ> åq¾ñ!í´W&Ëþ!òÍÆò½ˆnG ¥P4ÑâÒÎ á7žÏAòmÿ츱ã?TÓeñ ˆèEæ.`Q…è;ûá?€œ `¸ëy¾wÕ³);mê:øÃñT÷gÀNï>Vãs£ùpœL‡ó>Y˜µæÃ9¢?Ü·é³çŒðÉПŽa‰ÁƒÄ;ÍWëpôwðvýáЙ?Gxtw]§Éò…õ_ ”³Aè§Mt|ÏÁ“…£#’sô‡c.¤yˆþð"y oÕšã[Ä)E¢?; ³Ñ|8“ÈÇèõPkMô‡Óp‡x=C¶ÜlÒNܸ¾@[]XÆ NfSLˆ£³žèvöÐË Ð…#ž6"@T+ ©£§c^Á¾9zÂÉ›8¾wH’ß«¸Óêy6¦jYèâ±fG€Ž ~&,^bzrÉ0¢•¸‹Äx?œUÚY‡œø>‰sð„jĽ9þ³³dnÎó¡3\yÑ–à=è!ƒ&Äô“°Ô92œuUÚimñKžñ|À5|º 1‚`ÎóÁ+ 9wJŸ DóÙ‘Óæ;8õç,ßiñ=&úK—DòÌóg€¿ý™ø;ö¿Q<-ì‡'A4 ø1Õã©0R|XšS|€wO=Îgó—‚aHgÈpö®ØÏž'rqäøòM$Ž«Í†ýlmHÖ”ª4²7Æña¥™Bz‡¯R‰ãÃt —äøÊà‘ã;ÇÜœ­Œå+íå³£šD‡Îò•'ˇZÎªí´ ÌѤùòIÍg‡,«¸s@a§«œ%ËA4_nDó•zŒæ+µæÃ6­b¿ÚÒ|r’Çäùì„?‘žó|vÈoãùЙ±ñ|yðHDnùM}ù@‘çÃˆŽ ýl¿ ýì ¹']¸â¨æ ‡ 3‰>;üF 7ÆÇE¦õHòéLf(q™><||êHö¡?‡€Þ¡'*ùÍ}™Ù‡þðë„‘}XÂX/É>œØçw’}Ч <ëœ Ù‡–„ôœì;-øäÏ€~6 B¦Nöaq$&'ÙWnÉ><š6±¿Ëžôkˆ—Ôœ„œCÉyñFžÌû¥sèÜ@P|ﻟ޳ ø±¥etçÇ,Å—É‘ñÖ‹(¢¦Xˆ«ó Ȉ-‡V²ŒØ2ãd#¶€¬ãU.hçÜàQOu0Ͼ߆ð Üë›óÆG,6åø ÷ ØÒBCˆ‡OïwrBø¤#uŒÙò$¡ç.„" B¶¬»É­b¶\Œ{/„÷Štx÷žŠ?.x‡=?@+dË ¼CjÊSÈ–GW)dËÛƒ´-ohÄï ÷¡-=2d B-oG÷0÷®Þ›øâK C¶ŒàG²¥ø.YDÈN¬g÷Š´>B¶ÄÑz†la-÷E§Ì´[(~pPЖõ´¼[Ж<¦@„gc¡ãp´%¥áDxöOWNJ× 8³c:h‡ -ÈkÄ/øy7б$ƒ¶¼W Iyë£W†ï>#âem‰’´Û— òʬ Úr*nË<~Ôã{vòŸ`†a[2‚‡më/¦…myⳠöà­*Ja[âü}„m¹ƒ=RØ–H%a[ŽVtàx?ã¶Œ¾‹9í$ÿ[ažx*̳\²,n ” ¢ôäC„ ‰¸-w‡ôûÌYI>Û1ꄜn9 ˜·¥gºa"n ¬-n Nò‹ÕcÜ–;žLÆm9Ÿ*PàC¼±YðÝgÄþRÜ–2ŠÛ2‚ TÜ–¹m)“(‚¶¦gÐãÇmÉAA[ `#VôÃoX7Ÿz€Ï¢vè*°|pIêNÚ‚½˜®¡8#SQžýßð¡%ERaÔ<¿ vâ><@:œG2`ðå\ˇûÍÍ,ðÁ©scùÎȨ[Flf¸åщóÜak9Á‡×5€dùâÞX>€°¾áCXŽ·ª9KT›ÜÒ•³#· =¹An—Î2nK¤Ð¸-ƒ¢ûÛò$ÈÛb´ ³:ß;ã0M„ly´Wı„ìz¤5½Dø1æÉMm¿Ø=L aÀÄ|`o°å9ƒdÀ–WÚ'lyÏÀf ÆàFÛ"¶à.Ûá½\Î"b˺Ëûé=%¯¨ -#vê Ú1õ Œxc¥˜-@uŒÙYz#f NŠeYÌ`ªã´u\ÌžUЖ7âÅ(hKÎ ²{y·³%ã~(fKdiŽ˜-‘ù6ðMjUÈ–·é #¶@ÔT#¶ÌGºNï[¦UgLS…kYû”{?¼—ëi=„Ò& tVËÉQEœ6=ZÕq–;X½ùêq%«‡uôÚX=„×µV§ÇžÕƒGœTŠÖYo#ZK¬«qv/ãˆÖkÇqa­åáÑ¥`õpXÌ;¬³{‘­&CÚžŠ¼i“ÒõëS³yí¬]×—Ó_C:„Ü| Å Ò-È3C‘inmÙ^å­úåÙ¼ x®Ý©³yñ“‡”ÄÒél? Òu}B Õæødí,"ÿ銔RA8/… Õf;A8{pg:œwè,!æß»Aº¾ö¿ŠÐ"H÷†ÞÒT›¯û Ò!y“"yRµy¾âñ.—*„ D›ší˜î<òx4*ÎJÚÕ÷·£º ŠnSDÚAÕ]P×ÜiW¢àÕ]Ðè :ªƒNF‚LCuŽª ‘x<þ:ª[3#z,Öîåå îBΫ‚:+"g î‚lLâÈÚÙöïg`º «·bºlHxÖ~}BYIή3)Îî(FÎ΂?°Z:p$œ$ëÕB@JÎîé9»£Ý¡¶$gwˆ‡ewƉNQvG€d£ìì)góÊ-k‡›Wµ;îÉ&Îõ ²ÿ¥:Ѓ/kwž!â$íÕ•Ž€îBü,JqÖîèŠ5+Òî œ‘v(@òÂI»Sš)‘v@ï›b>î¢Mø¼ÈðÜ…GTÔû߯ רÿóŽcvNyAøÅ5i;7m´]êÙEÛaš2m‡ :ÐGrž‘¶ÃŽX×8ç…Zøô“¶+ =i;,™LNÛùù3ðÜ*2"~&]È"Îx¡HEsVb?WŠÜÖÊTÿÉÙá© Ä”œÊœ[8T"E&¯ž:Içì ‘‘æœ]-Cή)_£8;|xLtÆ«ô‡¤]é³H»g‰´C-ì±X;©kgŸxÈ’Ñ>€¤ìP@ñœï*7›”ÝqŠÛIÆ®¥ø’ý¿â»c¹ 9Û¶œ¶N’»$cwP¯mtÝãt[(–Cü˜su9"AÖá!ÝâoÖ2Nve_ÅÖ¡ !èºç}H×å_—£/¾Î¢Ón„V”z&/N|é…Ù¿A-#³L-os;“‡2gEq6]šÅÙ.8ÅŠ‡ë–r¿ï(ÎÞAŠŠ+/7ÑuÇ'Í6cëò‰­Ã#-hçáè.óY‡%rjÚèŠRS÷ÏÉÕ!YgªFÖãd]¹$ërMY—2&'ëÊ-0²}ÑÉ9'ºìs& 4'ërv‹¬C™¬ËSA„r¶ѱ=óÀž€QÉ:Û‚\ËÙ]jËÙ{T,7àG§ô̇®"ëÊÈ­Ãú¬ˆœNuYB.gë06¼SdëP=gëð¬p‘­Ãò«zœ­+£C¶.Ÿ²uùb[‡jè”±uÅ)²ueö ¹Ðâèž3](³ 5·zœ­ËEQlÿ&€{¹…ÓvAl6"qÏw@ç¹ 5·2'·@!³5¶.·3bërç*¶eøx­3­s…tV†hÒÉºãŒØ+/÷p:\iYN…¿Y‡2g¿iÕ4?™¹”>¹­ý[C¢€†sxë—Ñ*²üŒ2—!Ôßé³P^…¾¹ê/äR¢Ê0ëM ä}Ý{O«ÎB—!ñæ…®ÇhøRUXJU´eU2Ôªüt-¥ª°”ªh˪d(Uýk²Ÿ]kÒ`…]Ë¢çQ:˜÷Š„+FD0²~¸#Ì7²eD†Ž¯³f ú3ˬùýÛIrÛaŠZ*êBüÚñÔºhÙêŠRQW)¥º,½è;K]²Ôº²”ꪥ¢® ´Z•¶šT&*Ê2QNÏ­"Z¶š¢TTUJÅ3…€®ïUê’¥Ö•¥TW-õWçš½«îìúOûÌKtÿA^¢÷þ(÷}^¢_ûÌKô'Õ½¿*ö‹¼D*÷Ý%ßä%ú+ åÞ7Ëâïß=<ŸKå÷ÏΗšþàâ ¿n"nà¿ãNÚq¾u‘goÍ¿‹ÿÏrzAÑãù·ÿû¿5„¹®ûïÿíß±3]K¿ýøóÿDºžõ¾ÿö»þÃô·“#»ŸµXc'Ñßï“#­“#áÊYt•ÿýGüU ‘Zc£5Rñçç¯æFBÑ’écÖùøß—ÜH{“Ì4û¥ÜHËø%7Ò²ýWüï?¿±En¤ós# èAÖö¹YÒ›ËÂu¬·&â ÙÇHX®µïoøÐhÐý¶\zk>“~Ü.Ãi’±u¸Azãåkqr±."jÓ¾°Pe9®Ö’ѦÄkO‡_‡¡ ‡Zê·gÐÖvdmL°à+r%ô,mmNû©¤i·¥Ö¸×UÊÂy›xsÕPd@ —µß[–“’žÓèv|úÇ5<„™ÖOÅÚöØ4xA("ÒËš÷«%|Ö7ËÀÁ\%Îí± Ûh»»jÊd1s]dgö­âÇâC­»@uèóâ@Ū¥ßL,„sÚýB™›|”ùê¨æ%} !Ô8qUc€[Ä>Xx÷·~5&X²ô°«_½K™†åëOÝŽècƒü.Þ…+:> Ú ¤“Ÿx ]7*¼ð¡õßgÚ?¿ðáÀ îôx ¯±rë¥tξ¼¡0ñz;y(r‚lÀ˜_‹àÄÚs­¶±k·íº…ømÖ¿nõN‹rÔQ„É'æ… ¨3Ø.BLè¯Ö‡y,þj [1©è/ÖH+‚¼Um7×I[|׆ZSˆ«h»‰-Å~{õ¢ß'ég|ìðò’ žûËnÚ¼L·£úþ재ù¿îŠbáTÛszoé6ÁEÇ·7G

$eŠõR×HœZÁÃqŸ:'‘â*‚D.&€\àn<¶{vû.Õ-È—ùdiÐÒÅèÅ úïåä=…%Œ]Çl|…ñÎÛÎîÛívw>v4§#µ¦#80oóõyî|ÞZŸú8$mub@oþF´yLP‹¿îešÉV%ŽipÂg¬Óí²°6m·akÝpÞX¼1I&›m·}c¶$åN=´ÇŽ)wÄøspÖàŠèÃ'rËcÆâS°ß$'=/ìʧ©±ûbªñ\·«6ջţ[õèPK¿LmÖ_Ã?xôaôZ‡ÐÝ\³óÅD&*´ásÜ;lÑñÜ;vo÷.;Ƴ?›? LkwåV$Ô $™m‚# Ά<>z.€ALý††ºÂñ]—}g\³:Ø [£W)ðX xùŠlÂÒ4è¥Ï$b1KÑî/®×t˜«Œ¨Ë?}YÒvÉ$.u’§‰°2]<Ñ›H÷¢óXÀïCÇ%.{ ÚÃËÏõ~Hu=d‘UÀÅZV†:´Ûôãö ê¬ ¾¯¦CkõÚ÷ޝÒ¿Ø\íø—mü;d]ß1ÚÝ^ãŠw…WOGÌW' B Ää£DXÀ:þå7dy©£\ˆw‚-’ÏË2Ñ„¹ÉÏ$ˆ?†õ†ªâׂG÷»)ÿÕ °¬]ü®‡mÇc‹„Uˆ‡ò¢Ì¥$–<`¯Ìm‘X/g¼wû£û†—sóÉçŒ âF5›4ƒßèpÄVïW)g?í²I#±Ò…ØêýJ]l·Mš›ÓçNmõ~¥Çz]‚Ú-¾©µŽs§¶|OÕüúg+{œýÝ·óQýÄÛÙÞ~to†Û„é‘/./|ðJü“÷û˜Ä ß‘õâ}íÜAGÿ¶†Hcø»Î^D½í%¥X¦¢Å¬9I4Îù(øSÇÏö(øç@ÜX¿Ç­Y×3V ô‡ÏÕckóMËôõ;Ä­ßR`ÙGRT#'ðÔÖïÛO±6ð•X¾†ÇžæÎÖoìšYš*µW¤i¹»U¦ÛO;QÐñ™ Ç(mõ~yʦáÝŒÕOîé-ßÓWï·Ë‚ç—×óxů¤ìØpŸfpÇšùœ¡Çëúxx$ Ù©{ =¨Qù˜›‹„½âjÏðõñ2×é‹·¦c³ó5Í»O €µ#¬ñV ¯æÃžB†ªkx5ŸO¹µíô°mAóþ"oÆåî£×DtSµÝnkðàô-“½e[k¬|•aŠ˜e°<ý¶ ~”r¡Ì¼µat¯§=ª 9ç±vkÅjx7guïf.êS^ͶtŸ`6¼›Ûí¶}Kë~ȬߧKa¦2fß:c¯¨Õ]ËŒ¹fÞéOîÚ[4[º_¦ðlý2‚Á–¿HbíK7çø²˜43Ÿÿøry>¼škJNҤIÙî_Í‘”Øøå¬Ø™b¬®À~€U¶ ìwOÞöÀ~¾ca¿‡‘ú!l©íÑú!,¨]äg.+ôkˆ`xmÐ/âò ú5¬Ñ¦>ôkˆåi@OЯεåPЯ½ú5,ãö–ö³"öÆökX´í– û5,ì6 Â~« cF û5¶²±ø[exVŒà¯™TøkHÆbo%?«fVð·,Ã=øk¯Îeü5¼2ì(ð×@%Û}"ø[¿D ü5¼Vl×$ð×À6Ûú"ð×ðÀ<økÈJc7Kè¯EŽÁ¿fïCS„ »ìIüËþþ5Thc*ü×6˦ð_C7Ìuá¿a±„ÿV=T˜ ¶ˆ_%ØÐU¯‡°Yþ«‡Ðúã"À6iu · —åä°!ljW‘NV°!f„ïƒ×Eÿ5{w;°tü×,i±Wâp]¢ä €-SÜšþ"uØf„Ò!l ï9l¸åˆ•°a›à/hB@sÒ7ž„€kø¤A'´îxG€6zŸˆ[ž¤!´;ÅHheÞŠm@}'Oئrœ8´k\„Eh×8æ"´kœ{#´¹å 9´ûä‹ÐüöIâÐî«#@»S®è&lØw½Ú|ôm%  –o¸‰›…5s¼çÐÊI:,3”ЮræЮr‘!`½Ê!಼/BÀr.¿-š%„€v ÁœC@+ãW8´‰ä°Ñ`ƒÅo !Òth#ì€ŸÐæ,ó:±Ã€:lXyÎ ²0QéÐÊ(iœÀ2Ä’±JÎgnþ–ðÏ®P؃öl0~‚¡¿ZÄÑ_]GvÍQÑŸÑYyCåñ&ü[W)RáŸç¨ð¯ŒáŸ]¥s¹ÿÊ] þ³± Å2ð_C» ÿj‡6V(;lQ`aЊ8ÀrØð:ðUŒÐ®Ù uØŸ"@³x€ÖWÑ9´ásDhË –)LX¯rh.xS€vc|Í"4‹'ñ_Î Â?r— þ•›@ügcsî¾zŸÒÇ:´»ëz@_kÅËšOXf •ñ/™€ÕBr$theü“ Y¼)ÇåŽÿÙÍó¶þ•‡Îá_C%ÿšCøgEO9üË›)øg3vz‡9KÿrÊÚEWE€y¿…͇BD€6g/ãкãHЮz¼f‡€vUwÀç0æµ nÇaÛl<Â"h]vŒEX¯rØ ºüªíÛù Ú;ºsØ"_ž yü"G€ù¨ –«ˆíªÛ1¡#@»Êñ`S,N!À22D€µ)G€ë"G{ŽÿÌÃÓÁá?3\4ÿYç¼R‡Väpxåð¯ÔBügùGâ¿x– ÿìÆvÇŒÿÊt ü³24L_º±°ÉIôgåpÐÁ_™f¡mPJ»¿‘.©p¦â®ÜXQ“â÷‡oE÷­ë[ñßÛÚþCàW3õ÷ÜþJêOíÔŸ^@¡%Ó'îïš¾öœ8Ödeí¼‡µ#ˆÐª†2BˆW©?¨žœ þ›Š6Ü„„džÿLÂo0RÜŸ)eí*qÇñˆê#ùÙ¨½åEþá"sùgZ=C¬"ÿ"›\‡²«ùgªJ\"ÿ¥Ïò/¯"ù‡¤öòpÄö%Aþƒ1Ý‚üCÅÃé@’4ÍP£Ø?(imŽý%­=FAÿáìˬø¯[N9Ôôß¡ôãÁÿaŵ÷qð¦Ñµ2âÿp†æt´GþÏ)²ˆ8dÞº@8³» ´¾þeÅAâpŽ“2b3—›@ hê°Œ àqó@D3ó ˜@ áèèŽ Êtr‚΢‚F2€(Ó6 ðˆ¢>Ò¿‹L'Hâ¸ûQ`·Hƒ¿%ìèQ#)@Dm{6e.2~ÎfDIq€PO_Z=}ãKr€`ÏFG ÚòÃëâÑeÇOâî,pMÁWì9@L¸DߊÄ„ë´8 hqO($ ˆ çÛ²€¥b²€¨ÆY, ž#Pbã© ðð±M hóÖGG, Úòq ˜Ý ˆz*¬‘Do›$`<çAÚŽÈ9>»-:*,0{+0žÄàѰxÄéYq€±˜M‘ÌÁhGéü"R€GјM‰;ˆh¼Þ¨_"öŒ_°O7a_sia¢>}ÖIÔרpIÔ×É$‰öË"û:u&AûY´oƒkûp^Ö,¢ý€C À‰õC\#ç‚õÃbh7V¬B™ßÁú!ص±~v,X?`câDú!™-AúEÛAú!âÝ]I?Ipí¦H?´m߃ôËŠEúM[_é‡õÜ=H?Ôl‹A~8gáÒL‘~s0ªy~¨y'ý µUѧ} °íI~Y³H¿©ÈùAú…§Aúá*#â‚ô›7¿{é—W‰ô›Ø.9Æéwó ¦8?\äÛq~¸ˆÌ›8¿[ÇàDúÁuW…‰ôCßY>’~yy¿¹‰>­/¾c ÒïÖ‰E‘~èÌY!ŸY^Šô»uv.H¿ð H¿èK~·¾|é§›¤®rºA¤®ò ˆX?\E•'Y?¸Å«ÄúE=býrüÄúå­ Öï'AÚsÀ÷j¢ýÐ¥¡¢ýnãíg{gùÈûÅÌIÞ/†¼zCV’¼_Lœ ýc#Šõã·!>›ü¾­ÖÉÝBÖOy|ùœ%釗®7EÒ//ç—m‹óŠóœŸ–r~Qkp~C¢Þàü†ÒÂé7t`9X¿¡TÁú©wAú…KAú Eú­2çNú¥E¤_Ô¤ŸÖÈ$ý¢f‘~Àü ¨èkxø¼ßˆ`âýbYâO^ï<Ì€Îû¥A¼_\#Ú/Ší72i¿¸OAûÅ­ Ú/:´_ŒVÐ~£ÇéSÒ~qƒƒ÷‹y¼ŸÑäý†B#ˆ÷‹ â/&[81RŸÅS¥ŸVÆ "þ¢%18AüÅÄßPæ¬ þ¢^ñ~Ù=ñ~z)&ïe‚÷ÓK1‰¿MõY/탴ßu´_8)Ú/¦ZÐ~±èí—‰ö ·ƒö‹å1h¿X‚öCJɪûÌ•Iû …¹Ú/Ûï/¡àý†ØÖ þôÊâ/–ø þt’ùÓEÉüéªdþ²Œ˜?Ͷ`þôÄ$ó§§*™?mM’ùÓÄNæS)‰?=ÀIüESAüEo‚ù‹ŠƒùÓMOæOb2Y³˜?Í/2Z“ùËKDýi$õ§µ#©¿¨6¨?­Iý…ãAý…SAýiv%÷§g(¹¿p<¸?Í·¤ÿ² é?í4“þÓ"ù¿(ü_t'ø¿,#þoPk`´ ¤ždÿô(&ý—íˆþÓC•üß`Ô‘z¶ù·¿•E©¶¦Tˆì¨½ü£H3Îý ¦ó í'S9§ôsòë}‚Àƒ‡6Fê3ˆ…оí„Ò^­6—ƒbÙ3°(ð½™Ï#P ô{ׯý½ïáß… ª˜!ÄŸ“Á@~0{—P4xb@)a6ó ¨Pω±;²"Ûó2m\‚@¡, è2A bt È9 /æ"/ «@‚Àëu(ž 𦸨€@е*íY\°ÞŒÂ^@ €Y€À‡’àÊñ˜ ñœ (¼ùm#Aàsû['AàÃð> mšýVAà£\L¡ƒuÌ'ù±ãB¡À·“ ø(l[ ÀW9ë>äܾÊ(ðehžÀ¯2Œ—#ÈvàÀh\8hw ®¶I F4þÀï뛥€S)9¾ }0Û(·ÎS§!Êõ2‚S‰N†à ŨÃ7¡À¨F(p2°I¢À©oà§r¢ów(D ÀˆØÌ_ä" œ ðÌ_„¾ CÌßÁïÒ‰ø§ª?­Œ3g§B_ó‡30¿U8G2˜?¼®½)1‡"KõwˆK Ų#6¿-Ê)@p*«HÁ) €àT^Œàþ~ŒJ 8# Ÿ¸¿C4C Á,#ò/S Ne òïh‘IÁ73’Љü‹Û µùwzÌjDþe5‚3’‘‹üCÔ!ƺsòï`0­àþŽÈ'ò/nT°Ç•±Àü#r–œ «ü_–ÿ“"ø?VÐ1'‚ 7ƒ<žš›Ô$A^U¿æïd:—?Ò{2‚IÑ{2—µ»à$þÄ$$ñwSJ±^0 ŽƒùÓ›,b½ åS1_\Ü!øìLfÁ^,f¡]‚Om6\Á^$ÆHÁçà J)ø K>'s6†à›s“wJð §Cði)$Z“àÓ2´Uî¯[&fy|ZêG£ß$øDúûš+Á§¥¢Û¢½X2y|"uá@é=qѵé=‘ndVÔ·,}?ï×-ÝÈîWÙbzO¤gð0Ò{ZŽÐߊÜyž-Ü bn¹¸SrO,W¶y ¹'ŽÛBrÏH²rO¤xyêq¿Ž¸ý•øëˆ‹úlñ^ÎÐ)¹'îû PrOƒ.ÎØQîiY@¶€/'rUæ¯#¬˜¯#EƒEÊ=±SYJ¹'0ÑÆýÕ¦(÷Ì2’{¢ƒ<èrO¬Ü³b¾žy¤÷×{ž ]zO¼8©÷D襳‚¾žy0¤÷D0xߊHï‰þUQï‰ÖÏÊýuŒw¨C½g6%½'šrSzOÜšwC}Ùé=ѧ@„ú,p½£R×{"€c¥þÌqJ0)÷DJ ¨#è³æ&÷D5ïú0w}µ Arnðx!åžÈÉC€Žú2¿‡Püì›à³•û³jï ùÒR÷·D|vO˜BjOdËðy$µg)Cć¡£(“jÏ;>‹ó_ŸÝZÂM>ôf;ïgen†€¯eZª=[Æ“'âCø4%n3¹g¸_)B¹g©˜ˆ¯)rjÈ=›‚) ðµL/à€¯ÔBÄgy§6Ä×"Ò+ƆéŒøíïVxåSR/‡Tƒso’Ï@A>4uWúÏÊœ$ûó¡-˜q̇Š7È·¶ÚŠñBȇkæùÒqA¾¼y‚|Y ŸEöÞ _öX–^Ù¿Þš~A>LSÊG ùJ[„|èó¨²Ï…öc9KõÅàê‹6P_T¨®w‡kŽúš"ßê+EˆúšÂhê Ïõ¡ÌQé?+ãZ„úÐÖù%«è+‚>X¦_EЇAÞeŸyEóY‚çíúr¬úÈü,ž@_ÖAÌ×å= _ܸ€|¨å©§þ¬–{}æ ò¡ž«R9µò¥‚|¥ê>K~æàIû‰Ùç´#_Ž„¤Ÿè¹G³â‹;¤ŸyˆøòÞJú£%ågöWÊÏ!¾ì°”ŸÅBħ×dɶT€^ÇTÝØ½öy´¯ñS"½ÆoºAïµ=®Kãs´v›Â™;ŽŒì‚%Æ®ˆÈ.'ßÓÙåd¾–ŒìÒøLgd—Æc|Ù¥}ìK‹"»„Aä^ZDî¡q{¿÷œÌ/üê»ëɾea4“à÷òFôÞsŠÌ½‹­¶Aïá–Ø4 z{3½‹G[½˱Ñ{i!½&wnOXF=Ø—loÐ{°4'üHï¥Eô^ZDï!u‹í ƒÞƒÅ ?Ñ{°Üè‹è½´ˆÞƒÅ–Û ÷Ò"z–¶i<Ó"z/-¢÷ÝÞÿ‰Þ KÐ{ÅBz¯XHïY”|Ç_¤÷Š…ô,¾½W,¤÷ªÅé½b!¿‹‹&Åï ù=X‰ßË2ä÷Jò{ÅB~çÄï ¾b!ÁW-NðÁB½( ¾b!ÁW,$øÒ"‚¯XÈð=ÇûÝ¥Xœá+2|¥2|¥ užÕâ ,Ô‚RçY,Î𕋨óÌ"bøŠ…JÏb!ÃW,Tz ¾b¡Ô–»‚½Í2¢+,Ôz µžÅBŠ/- ý*¤&)¾R€_±â+WQëY,¤øŠ…bÏjqНX(ö,R|ÅB±gZÄñ ÅžÅâ_1Pì ‹Hñ¥RÏ4à+Wz¦Á…žù›:Ï4PçÉ<Ó@•gHí¥Ï4Pâ™*<Ó@' ´$ð, <‹…Ïbqg$ð, <‹…Ïb¡À³X¨ð,WxžÕ2¹z‡… Ïb¡Ä³X(ñ„…ŽÏb¡Ä³X(ñ,ª<³f©Q@ÿ…þ‰$ _gŠ©¯=ýÒwcXä›-I“êÊÄJª«$VŠº¢TÔU“4±®’X‰uÕÄJª+K©®-I“êŠÔJª*S+EM*•Mª'+©¢’X)jŠRQUMÒ¤ç(+±®šX)¿(¥ºþ™ôKí]+vߦ_~I“+Ê}Ÿ~éWÅ>Ó/ýIu﯊ý"ýÒ7OÁžclO¿ôWÇß?ºo–Âß¿}x>–ÇïŸ/5ýíÌG–T Úg>z"óÑ–‘¨ü7)÷Q?ÿ…¹þñMî£Óÿw¿ÊŒ´þ÷5 Ò2þGüϳ =G{•i¿dAZ¶ÿŠÿýç7¶È‚Ôþ8 ÒÚÜö®ÇëÀ"aÛÓiïúÎh'Ͳ‹ÿf)œg€ ïúw0Dªio,ÈñÅ`K&gzMVßýñ5Šuc|ÁŽÔ®v¦ñÄO·L?Õñðƒ‚Åá09¦o\`Ë1/†¤¶€)`çΛ²ç~<Ãõ˜e{ÍïEvޤ‹)SŒkͿԛŸ§ªl,KÒcÂ2«ðáì“L ’_°-qȹ¾êµ/ãk?õ:9w9д,IHÑ€OIÞÐíòŠö2ÞÉ*ÀÍõ—QúNÆÍõ“io\n°Zº“çü4Ò]Ô­n¹ºùKíK«ŸŸµñÖ\^q½ÌÕÝ‘"Ü\G†¯çryÅ5ùu¿·áòŠ ü¼õÛåÈå⎷ÇäW#«¿ü³@6ö®ñmÓå×Åcwkuy2Faƒœ»Æx[cëò d¬1Þ¥wf°:ÈS©}õÞȹñ< ¤‰·” '“¢®A`J¥èýfJ|O°áA"Ö=ó€}S^3¥NgŒ˜Þ§É+n`x3\Sê,'¼÷xýî¯m\Ü:Ê̳,.¯¸‡ÇXîWgNçqiô'SWÜ7ÏàtdŠ÷¬ Smß.¯ÀÇ ŸL×ãò dž¸Üòº¼ÙÏÜ0M|mY%|¾ÃÕîÞ §‹+îÆ4Ak\\ï§_Ô\\aÉ\ÝÒ]\¯ÿ—_u¹¸âšÔRz‘Vre ‰&Ï¥[¶ªã-¹G,MŽ¥Ô9îÇÒXJ÷2ý–åë°Œ:ƒë[–˨³–ûdoi,£Ncv‚eaFWàŽYF“:º~_̨à ë†1¡Îš×Ó-7ê¼§0ÞŠÓ^úè!•¥/`Ä›ŽEÔÜXë¡ûô-$“ùtc-†'ó±»FÇòéàÀë—WDv©ŽµüöZn/r¹¼»h^4\^‘Säñ„Føn¯æQB†Y`Íõ‘¦?“ u”dm]_1Có­UEuxÒ¬#u@·¶>‡Hàu®éow}2?úy/&Õ9)Aëȹgy–†“¦‚C™Îc½—]_1œ§‚åu}ï°âéúŠvœy;-Çaç|ºE>},/Ò\_¦´ëˆ°ÒmL/çMútåš@<†×°d\ž€ÈŸpœq¼»gýñGBЇù<|,pÌëõuÂuzߺá åD»)ܸìp‚ùùøóp™ŠMÝþ³¹¸ù= ž\Èn¿?Ýi§ëèÌ©ãoX.WWàÃ(k®®¸»‡©¹,¼"||\%{3êà ÞÿGÞ»dkŽãØšS±ø’D=ÈqĪQ½hd§æ_± ŽE¸{¬¼·n­ì¸ÛCQ¤DQü´"ÛÖÓ·b&kÓ2Q§áóÁIãcú¾o¸2žñ~žug¼Ÿcú¾o¼NÎxAÏŒ:ö»<÷†Œ:›lû9}+f†ìÙ…ýBF‘û'áP9¢Å‹,ò¤kEܸ-ÏÔg6g19ÃM®Ïl3HiqN—,¦Ø9ÃucÌ;<"ÞÎ3Úƒ¸¹3ÞÎsî>°;öyäkÇyxÎãL¿Šø>_ï7ý*bÏ.÷…É;wÝ}"Ý*ôÞ8c©}ãL9 Ž‘n‘d)ÇPÛÒ­"ÆÐT„ÏHç8çîw¢›"öü€0ŸÉ¼IñfιûÆŒ7ǫ́sŒt>ãÍ<çn&ó9Û…Œ:Ì t¶;=+âžL ûŒL3£Îñ¤?ÁÉòfF¦j:߇0:ã§ò<7¤Ôar¤óÜ‘R'¾Ã´ ¥Žz¯æ™SçD‡3ÞÍ{^­9Gœñjž9uâsvZ®™¼~Þß¹²:Ï9u.L³ïAHªs`)ó®„Òµ"^*9Ï1]+¢È\“œñÖ›ùÐbÕ”–Ì*4¯é\Íž‘Ãn&D»Y㌼ñ1Çã’C)^Î3!Ú…ôg¼œçüÝt+æöKŽ9C3}_tô<ñÈ#™[›. Yso9G}ÙÂðm9 ̵ß•æüýö"‡ÎÌEr;é3.܃K:g¾3¨ÍœhtÏ9A\9ÑMÿ3Î9“¢uìS}Æ¥œÓ÷¬g¼Ÿ¹ºÙóÅÆIçü}Á3êŒãçüݱöá'&Õ¼Y϶çüݱù9uü¹’âl2ý;öœWsRz¢Nfu>íÉ雋ÃwTÜ9}ïHÀ‘D®¼êsqÆzNßL^§O2qÂðW3"™ŸéÛV8ðîŒf!nx;ˆ#J>WóäÀç¼Ò·BøÜ\Á’ŸŽÝÞÈ/ Fïü=kN|™“KDpàKbé¯O tˆ81pn¦žËF`àKƒe¼…10vNø:ìW¨È.qà¶s±IŒÊ€µu#A0v¨Ì…AP» Ã!/A08a› ¸oxØD‚%‘ @Œ£…÷öÏ@‚Ípe= ÁxC HI‹ ÁýFÞT‘`-G%Á(8³`œ`%Áð?ß’ª6:ÚcĉC‹ÙÁ}I‚ш¶ <|E‚r— †%»E|s¾ØD‚¡×dGI‚Çû'>£LÁ#ú0K÷‰zlCÁø6~- ø°tv ¹$ÂPÞs’`¼ûxI‚mãg’àû ƒþI‚ÇÝxr `ÜÅ\¶CÊ”,«ˆä—,_Oò Y0Êä²`|ÉÑMŒÐ8X°Xf%ÃÄ‚ï›ß£Ä‚1p"°à{Ã%[ÃÏ%# ¯1a0:žË~Âàqwâ!`°Xƒ-¾´€'Zƒ\¤Á¸69lAƒ±œ:œ^7³Å¤Á£c^Ñ`|ñ€¿ÄÁ¶#ŸpðèØÂŸ8xD®á„6à`±Ûί ÄÁøò•lEŒU⊃ÇÈ,¢Á÷Ö¤œ$|gé|ç‹ã~æû€43ÂKÒ`©4øNÊùäc…š#0÷7¯a0ŠäHÂ`‹0Ãm)'E -„ÁwÒÀ<@Œù)!0؃ôý% ¶†MâÅ‚mGò8±`Û‘NS,诀`ÁR X0î]– Ƙ¸“뀂Q¤¥(ØbžJj Æ Û* †a[h°øb*Œ öJ> ¶{ÑcÈ%y0no.´Èƒñ•²-<·!á8“[®éˆƒñ$暉8ru"q0¦², C¶4X  Á¸ÄÙ`â`Û¹’&¾ï×ùIH4}O h0¾Î&È% ÆuÈ…+y0,É[äÁ¸Â¹@'F&ûmáA=«âÁ8*+Ú ¯º$pò`ܧÙkâ`;°c¹pÐâ`‹ü¯BƒíÀ¤•4?·…£Ž\/“ß÷®%i0î, Á÷Öþ*(øv§ ¶Ø8)O Œó€A‚oÄ3`Xæw(‘`´…l˜$Ø6e ÆÓŸd  Cžœ$ÍÎûHŒjò‘ßUE®‘D‚Q&± ˆµ‰AP#ˆ×p¤c5OM ï‹|NȺ|ÄÀr0°5|ºFc’ü‰1s8ËQÀ@Vb`»ó˳(0д䮤À˜ŠòÖ£,ÀÀ–Fô´ClgË—“ð]å{F ÃéH–¶œ>€¥Z`T’ŸÈ€íÜã¦ÀügCâ_\ä¿váë ñ/ŠäÜ@ü‹Jž„Fà_Xrn þE5#õ÷¿œIÎþg¯Û•eÔ0d¾£" ·Üj·Z"àÄŸ\H[xŽå2žR éøN("5H^JS ŒÀå{‘c1‘‹&J!ÐåòGRàƒM$*l† è•¥ÀX£w_2`ÌR¹(–˜n~…§KÕª>Ò(âÅQ´@~ —xâã£0Ö·¹f"Æ\–ª¨ÄÀPQf‹‰€1éï>ˆ¨(Llé‘èF1ðØ s@@/9ˆ€ñ>&cFÆÙãUŸÇ‰€-¾.'IcN¼1°ÅG¬”쀀1Çì‹À˜Æ|‘ H"à»hýcÑc¦Oˆ&ƃœ DÔD$lO¦Ú†³[B°=ùj†ó[Bø/îoŽ-ñ߃¥ø¯]Œþ‹%.“ÿ4C›ÿîAüí…æþ‹zRÇ%ÿùT⿇ßÈÓ+?) üw*Áˆü×¾eòŸ®ù/.qŽ ò_¼;7óŸ&\ñ_»$C‚ÿb®o‹÷2ŸòŸ”æ¿Ø×"Ë€ÿbØä—ò_»ºPü¯àlžøïndMð_\œ¼¤ÀhϹ`ÜÈŒ@®€ÑuHrÀˆsx9ÐCGø6çX0†zÞs`܆œ €Ñó¤`8/z`œ*ç;à\Ž¥^ Ô:ÌÜXôÃIŒ9'¯; 0žR¨$@,€1ÞÆJ€74: ¦M JÿâëÂÊê“øï:H{ä¿«ƒøÅz¬€±e|EÔT!¼±GŠ PÎ"@=Œ"@¬¹€.A¼ ÕÈYÝÈ›¯‹‚! 0ÞyYÈŽ›9šq €•`dmɃ€®Fˆ1j<ðÉÄø.˜“PE€I z˜#*ë!^ÔNˆ€áI¾" ' #`¸©äɉ€|dÌ€| š#~/56@`|×þUð  EB@NFÀ y7€1óä‰È€œ7 Zº /lyc ¼‘MÑxQlæ*T ÈU(ð}¥È)¼à:d¼©Ò‰ÕZ1 ŸLc`l¬½rà½ÈqhJ&‚@=‚@Î#†@Šð¢p.Œ< U Œ"mQ=Ä€WÃprâ3^íÀº×d@ÝjAà…ŒÀ†@N#ùä ¯“õcçÙ,C Ô4ò’‹])o SàuB`­˜Ï“0P7œx#i­1P]7b²j ¹¬3^é6W8p’¯l.T‚ ˆMȉ91u¿I‚úP Ô“ Œ\N©9Å­BA^‘ Ïô'É‘L_éoÇpýõ $P 5-aAô 4«#èÜ .GôwÜtפ#èI¿,Ò_ÄAî£#hÇg ;‚.ªäš ŠB3øw¡¿ýÀîÎÅ9éI!Œµd=:‚6: ‘þ&ÏåA ¿°À«ô·ÇùiýÅ6_¹Dýí7|„Uœ ^)€ ®ðo¿á'(ðÆ6áolqbðÁfò¹…—@î´eð]úCýņ]p¥ø €ÀŽüèé“Hú‹¾d¯$ªb €Qv;öÔýiÇ.ÑßÞ‘+^ôe¶ÿü½ø§-²„{¿ÿXô?mü%ü‹ƒRïþ…áYø/jpþ Ë ÜKŒÖŒµ—špïG.[€QMºÛË©€î0Ê$fµµ›0Ê@ÊîN^@7è®㨱8ƒFȆ@·™Gå3rÝ÷r¢‡»mÁ-CX Kà ìK¾ºf Ç У‹XÊKÍ@ß`´9;NôeºßÀxŠàý ŒAuèaAôG1`±$ÆxKV'Æsu,  {Eô­"Æ“v-è‘LŒ2cq2 ‰@_/ ïP›÷‰}.`9W" §" »EôAôp"ÚBtsȀŬ–dÀ¸Çùf!†%Ÿ2`Xr€‘=ËK= ¥ 0NžZ;!0ÊäB‚¨T¨ýj !°¹‚@ùrˆ5ƒˆ‹Xš Ô|! ôÙIšwD>Ѝ)CeÎE Kzo&–ZQ 8o„¤#B`€^[„@má(Œÿ§Œjt @WC ÔöŒÂÀ8*]숾ÄÀ(“‹hb ^bÂÀ°dP )0ŠôÅ5ÔeHª†ENkÑ¥U tãȾ2ä@w’èKCôå#jŸJ¡ [Œ¥Ó¹ÈaÓ'H06„‰‚¢DA½b‰‚¾ DA>¢ ÇQÐד(èNôµ jÈ} QÐõ}µˆ‚¾QDA_?¢ ®IÐI°T ô­" z}ËI‚®$èÖ]1I°T, `±Ý²` ‚¼å„A?¿„AÒ ¶`º q°”zÀ‹8#p_”ÁR8Xʹƒ®pPï‹¿‘0Éh¸ÍaWcO8;Ê74æôµ¯ÁØgllŒ¡ohlܑ߆éÚ;vë’oh¤¸}ßÐH1t×Á— îÐ54öíx’ézí¬†¾¡×ÆàCú†Þ\JÉ7”©UA†o÷"xÌí·~ gž›«†NK~R:;ÁpfºŠkè4ä `8³à¦0¬–Î䫽PÒî0áÉЩI†ÎF2t $’¡óÈ‘ «ådþU."A†Î J2œƒ \ú ÿêCtM2œ—~©ƒùWÅfòî7CE!FûrÝHA0ö½wÐô¹¤¡ ø ¹[B|/Õ@·…jàsÓÛ—j`Û‰TcóÔ\ÜQ ŒÔ_ úTŸ;ãI|†¶¥ø<ˆ Ø‹$90.„=Èsœž£90¤øä”f¾wi½­Ãôã&B Œ"ˆE„ÏÆ@ |žãã ²#ðbà3èFL10ÜÂóë ÅÀ'd©”ì Æ6îû èkC1°o U£¡Á}ñí;BNR |"›U10F͹D>7)FµcÙæéœ(ºÁc(m‹7hß°–ÄÀhO2ÅÀ¾)Îb`PüL!Æþ¹ˆ„çZ6‡é·‚¡èSQ ŒGs[¼AŸÁ QŠ‘².›L1ðé ?…Ø7„‹Q Œ÷PhÑñ«bß¹œž©öؤ$[-0žU ì± \´À(»/Z`ô|ÇV0©Æè-0.`NJÔã ùr Øw[C ŒQ°ì ã±N)0nQ!zXP Œ$pþ„½zwÐH}p-R`Œõ«r_L”ã^¥«¥À¸ŸY ”À¸WØ?J`9 öÕ"P}÷¨êLR£WÏâªë'%ðؼ‹J . ”À¸€ØÆJ`<ÀWž9µöE Œ‹œª•ÀhNªsT§7R¿9„ÒÍŒJ` Á}QuC¥ƹ¨ ¦XÊ@ Œ2[Ý &:º/R`?vî)°Ç¶"ÙH}ç–!”5¶%ê]D)0<9!ÆÞÚÀ3H1˜nøˆ¦J:¹Q ŒyñX¤À¸mÙ$&nqŠY”ã}u/Z`ßw†$B ìÇA¤„èöP ô è{<ÅÀ~0v‰b /:ÅÀ™ø£‚ßÜ_< 1Pó›ÄÀ¾3Þ”b`¼¯*ùÍk|-n¡ïõûeì›Ï"ú ÆyRc¡¨7“”À˜2f J Ç•À¸—Ë1q â!0.ï¾qsÓM—B`o;ј¾ìN¦¦Ã’J`¬ò:P Œûö,;Ąޓr1•@O”ã\­bŸ§MI1²ì›×¢/R`oX±H Ä}è:¨F¿×ÀÀ¨õX\Bã‚Ö –ó@ô%¦×&?QŒ>‹èI€:`Ô³DjY&Ð*eÀ7L½¦ulËæ0ñdŒ%:°·“ÛÐ@Œ2ùiEûõrÝVò&Ø›:q…½HUü«h|Lããý_vîT¦ý_bߤÊz3aÐ^Ý?§¥/û¿D=­ÿU 4¾°äj–"Ÿ2òHä+g‡È§FùÂÒ– `lȆû7 Ë6 ‹%E¾ §±ˆ|ayª÷gµ¤ÈW ù”®H"Ÿ’øHä+–áä;Ù ò)’D¾°,ŸOEO™‘¤ñùSã ËVcÿœõHŸ2Qã ÃUcÿœÐHŸ-ÔøÜOj|ŃTŸ Í™wFõý¬–Ë™wzÝü¥ZfÞAb")|Å2y‡J|ÊB$‰¯”9˜yÇfÞÑQ™wÆâüY 3ï î/z3óŽ,3ï S‘D¾bÈg E>¥’ÈW,3ïŒu'ÐC¹$òËéÌ;£:V˧’Ç™w€ˆÝ™wzå½b¡ÈW,»3ï,»¿,gÞ¥9óNê_TùŠåræ»ò^µ<μKWæ{‘ùl¡Ì§ì<’ùŠåpòZœ}–¦ô;WÝþ¥Z.'à¹êö/Õò¬)x$óÙ0Ö<ùlØ×<’øŠÁxÒМ€§:}õ¦ß‘¼ç³ï¤¡’ïHݳ…ê^±@Þ+–ã“}Gò^±´OöÉ{År9û,·³ïÀ’ò^1t'ßYå=Y$ïËþI¾#y¯ZÖä;’÷Šåü$ß‘¼W,÷'ùŽô½béŸä;øl¡ÀW,û'ù޾jù$ß‘ÀW,çš|G_±ÜL¾£}IŸS©ÓP_)3>Éw(ðÃþI¾#¯Z˜|G–öI¾#¯X®Oò |Åò|’ïHà+–ñI¾#¯XöOòøêÏOò |År~’ïHá+–û“|G _±t'ߟ-”øŠeÿ$ߑħ4’øŠ¥­Éw$ñ•"ÐøŠåþ$ß‘ÆW,ý“|‡Ÿ ÔøŠewòUã+–ã“|G_±œŸä;ÒøŠ_±@ã+h|ÅÏj|Å’_5 Ìä²@ã+ˆ|Å‘¯X ò D¾bÈW,ùŠ"Ÿ-TùŠ*_µ Ì岤ÌW ÐùÂrWæ«e ó „¾bЧzJò¤kFûß%aÇah­•ü ,SÒ } ù0úÍQž<éšSMžd‹“Ѧt%2””EwìØG©ÊWE›ª’¡VW.žW%K© 6WEÃ{"¥Ø#f~ý]"¥ß¤AÊ¼éˆ ßÝÔ´ðriK#‹ØyÔ…›Áµ/Gu|wSÅXºšŸ»4e­³4U¢¶ÔðÕMEÎüèæ>º©uýF¾kŸèÁG7ÕñÑÍGu|tóQ#?ºé ±á£›-;>ºé qà£<¾¹Épâ›[Ãþ‹× ë© ¯¿½^ÍQ8úrLÇW7éøê&ÃÀW7sÇÖ÷w½m/¾åw7|wóA Þ\æÄ—7œéÞ.|xs‘Þx¥Þç/³^ÛÐñÝÍgêøî¦z>»©ÞØ-¢Çø½ïøìæ2>»±šØ„ãÕpâ«› >ºÉpã››k}ðÍÍ–Žon:¨ç'7—øäÆdž/nº suP¯åqàƒ› ßÛd8ñ¹Mç!(¹È¯m>σ¯m*Òñ±ÍE:>¶Ù2ð±M·hnÓ\j‰Í#9ag[b¯k.±ëã]¾;6ý{–3Ån[½v26ÁK-Ϧùm雿kZð©ÍG®ù:-çöh¾†e¿5_ÏsÏÜwõržíÔlcΦÙ–ëÐl­9o|hÓX=ŸMó5Žê[y)Ýñ:Î /œ;^ÇûS-ñ:>®Å²ãC›N dzN1÷ÕNÍØ°œM36,ס){öû}IjÆNóiÂÎDJ®Ñj‘>4a£Èè,†xïË/ãc¹•‘ó¨Õç"±œË˜¹Ï¦ –ëøc¹)÷½kÂF½Ï¦ ›|dÓÕ»{׌zF×”=ÏÄï .ïâ}±ÏqiΆ¥š³óäÏÙ4i£Ìu|fíçÆ765ðy¶uÖ~ž¡Y–Þ?³vøeåTñB^§í¾ßš¶óäñF>–qî 9o³9ýlš·Qæ:>w¿ñÍ–gÓÄ£ž¡‰ez~cs‘ñhæNËØnMÝ°ì·æîùj¿ã¼/c'^ÊDZ”‰N,†ëÐäŠï]³w¶/‚¯kµ Mß°ô®ù–èD™pžm»5Ï"϶_šÀaÉô›Õ»éž¥ÏL¯Ú–2ס–ÛPÎýváì‹ahOClrUC8Ö>>{zVKt ¶m¿—ÕÒNÍß8èlš¿Q&wa¬€¶,5_’Áï™ül¸%ð»Ó_£€_ÀáTÉ~÷@(¬Á/¦æ¤1‚_ 鱯m7ü8‰}osÜ×¢Yw•à×â»ú•–$¿·—Ø_ŸèýÎAKô«5'ú½õ`“v°ßÛÑ+g]²ß{òs:µ‘ýÞZàŽLökÑ—ùÜþ< Io5Ž"þM?Éže.ì¯>óäà¿·9ØMšü×ÂWcúÓóùe|ëÁÞ—Àéo9}l€ï[ŽHàÌ~7¿D’Û.¶¿ €3uDŽ-àìgÞà)W¢ÛûkmHÉNœ×øÈj’çþ¢àÈ$Ày;Ó0°½Ö¾eİÜ;à<÷è–øVóÌ)’8w ½²Hà[ Â&H€o5Ø‚”8Ó >•Ë-œ~±=O”èd‚$Àù4ŒJ€sÕ=kÇþZûÆ2I€óÎMÁ“8<'l`Ûöæ%Îç,ǰŚ/'0à,3ç?2à{q˜ˆø–ɨ50àû±dÀhß/`‹Ub.¿€o—3‚8GD> À™U1ð$À¶ŸHlKœc:ÛœmÛ²-v×Úç@ôö²$ÀÒ àL×8ßADÀy­r¶NOc”iØ^kG"àL™s1°MŸ©´ÜØ^ëÄn_@ÀrÀÓñyσ:¶×Ú‘<‰øÞp>d@À·Ì“ÅDÀé.tw`w­¤MKÃîZ {Á“½A/ pžYw6'!pN’-O•è›N œ'Ÿq<Ä@?ÅÀ@O›ÄÀÙšç3ræA‰¾îÄ@O›Òß#ÅjÝ,û¯¤M*`+n··Ò.$iqGÊ{ Am®-Œgf$‚û@W‘`ÀK®ŠI‚#ÂT’Ð@‚f`,œû"†ÃèSIp®:ï*¾+S„˜ç²3‹$ ÎÕâ•è—08— ¹x ¾/¥LÖ¢Á£asÑàq`3<Ñ O•4ø¡ÌIŒS]Uœñ2Ù)â`9pðØ<-ÄAå’%Æ"<¡ 4~Gû@ƒÑàVÀ· bÇEƒqî¼1ÄÁãiøÞBT¢4áàq¦„ƒGË} EƒQä^hð8±‰¯hðxöZ4x\ˆÈ! †{Ú^UÀy7÷…ãTm£a§daäRKJ#'¶w#FHÒ|= ãáÈW*0ÊdkÀƒâÁ¸SÙ>ò`œi‘ç}èUÔíÆ™îÃE;i†8Ƀï¬8ŸU œé¡ÑÀÄÁã1£›}áÁ`¾\÷‘ƒÕyȃ1*rJŒ›wåQàÁèy®«Èƒ¾ÁäÁ‰êäÁ#]dð`œ+WläÁ¨'×þäÁÿ{g‘;é<ÍÙŒFœUœW0¡Œ@¨‡F@¨dãBåà'6ýFbì\cÜæ˜$*û¸ˆ0zžKA¡"Fp$0®$H H-ÌÕ>‘ð¸v²&Ðw‹HÓvÒûDÂ-i Ø6©Š‚-žz 0†P/"aœ:Ç-‘0²'c =˜ˆ„ü—ƒ’Heòù$Fƒs˜ £ã½Ê‚Ît.$ÔÛ‰LS¢ð¸. ©0)>Paœ))‡T·êHùTèÑ*Œ¬Ü[Ò¨0š—Ý$F®q =…1ŽsB!º—„˜“§…1Ü. …QO~ FÏs¬ £9gÕgRõÄnBaÌL)&F-9w‘ }ýÈ„z©ˆ Ã_42aœ˜ðxrs1áŒM ˜0¢T’ƒÈ„Jm/&ŒSålF&<.|Î*ɺ˜0ŽÚ‹*8Ÿ‡d¸Æ[Jl`˜Žª NKŽQ2aŒõEœw –L°˜0ú™/02a,P€Ÿ`Âhq~{!–S ã($˜ð`Ây1¡Ö#bÂÈRÿ,L¨³‹ ¹Ò&<˜¿TL–Q™P£@L8ÃŽ~$Ô3#$Œ3G„ÑâùÆê  u„„1Žçº[Hà0†Å¾ ¡vg7ÿ$’1p´  ç5„{˜7LAÆÀ ù.…¡µÅ4ħ4#eD’bRàª#褷«êór®Iñãû\ª9¤ÀÈ`4}HÀI(îOƒÆF TN q`¬?·¤>pà±Ó¿•¨)QSN ŒA’" 0P00V800úЇ ¬r !±Ø6¼ÈQ$r`ĸéã löÕƺ¥'ä•V] ÅDC€ 2k •P  ‰S" *ÛHPYÖD‚ñž°µßkú¾$ÁÜÛ¥ô}‹'h‹á¼g™‹ Xñ5U$QzyH‚Q&µ9¢`‹ó`aÖF9,õ€êÀ‚±„»e0rÚB=<œ€5¥7²`ë$t° .Q°u~! †%E?` Î'»ú‚¶6Nz‡¤_•ÊT²F¡`dî‹0X,@Áèe~8! ¶Œ/(Ø:ò‹ [${Hò F'òÁ# ƵiðEúÕ±A„ Æ­ÊåQ0f¹d¯$Á˜Ñò(IP×F$[)Twй۞،¶ä1à@u›•¬Â`Œˆ2DòÕX‹æAA¦r¶|TîZq ’.‹ãÖep`äJΕ190Z“/~r`ô)>``\»{Q£È]óPs˜° j À(³H‚ñ˜ÝÀ­ã“§øÏ÷`ò_;¨r‘ÿâ±§ŠþSZ]ñß¼¨É[࿘Wú" Fô4¤<ð_‹¨½YÑŧº„ÎJ. R¯Žw–ð7WAiüµq%]ýÎ I-¶èKŸKÀ_´ø‹zó °ß¹QÔ&ûÅ&.­²ß¹ ê`¿rØ/Öhgõ m10ªKè¬&ç8²_4¯-‚à;-ìÑé‹Oh‹èôœ‚É~ç~лìw汰ߌrO†û•zþ¢ÅéžAø;w<¥d¿3¾d‹Á~Q˱è1j’Ù€~m /ºØO/|±_¿M°_ÌËcÑ[îÑQØ/ÆVV ô‹!úÅ£0Ñ/êMØ'úÙBô‹zï´ýü– úÅû>™@¿[l¦%Ñ/:žÏÑoîG ô‹Så™@~î7É/Æì^ýAçk9ïÉ/žŽsQù¼üâÚ@èøéùøÅƒ8Wt?uSàWêIðSÎsŸ6"¿–¡ê…üô&ùE‹çÂZä3Å^ÅÀ6 †‹üJŸnƒÈ¯”ùiœˆütò¿‘*©ˆwLç•c†Èè?RàNÉIñ€>Ó90:µP`ìp,b`8¦ a·PòÉ-”ÝB&'·ÐF‰Éñ€Œ]s< c•ÈX%Ç"½l‰Äǃx§ŸK‰”¥Ä"$Oñ€ íkŽÌõ}ÄQŽÌ&;PEJ< }A7¹'ïU¬–ˆ<Æ*ڮĦ¡„"h¯]«{r ¤åpÀûG8àý#n}´…á€7SြìŽdÊ’pO~ø,²("P…Ê¢@lÙXBeQH - ”E1ùÉ·„Ò ˆ@ùªDÊÂ@(‹BeQHàƒØ!¶0$P†ÒàÀ'?æ–@•QHà³*‚õ(Ê¢ @¥¨@•QX , ¤S¹ãUF°”À@Y(ƒeQ` , ”E‘²(2PF¢Å%2ÐFÊ¢Ð@Z(‹BeQhà³j‚Õ¢à@Y(‹ÂeQx , ´ñ2(>„YÆ‚*£AY"(‹beQŒ , ”EA‚²(JÐF Ê¢(AZ%HõÓa‚*¢0A•Q˜ , ”Ea‚²0NPŠʢ8A['(‹âiqœ ,Š”E‚²(RPE Ê¢HAY)Ø).*RPe2RP)(‹"yˆ#eQ¤ ,Š”E‘‚²(Rçr¤ , ÔQŠì+Ö2 T Òà`AY,Èj,¨2ŠTE öE¬E Ê¢hA[-(‹¢eQ´ -”EႲ(\P… "Ý[ T… ªŒÂea¸ R¸ , ÔA d‡ ²ŒÃUFá‚*£pAY.(‹ÂeQ¸ , Ô¹.¨2 T… ²ˆÃYÆá‚*£pAY.( ÃUÂUDá‚*£pÁNŸS… ê(… Ê¢pÁNfS¼ ê)ñ‚}åÃZFñ‚*£xA•Q¼`_ø°QÀ Š(bPe2¨2ФÅ1ƒ²0fÕ8fPE3ˆkZbUF1ƒªG1ƒ˜ ~“:éßq wÏ6 Äwˆ#Æ$wV£ShÇr;…¶Fý ØûÂ$ö§QëƒSèŽPv ÅOz„Þ']9㢟™P <â[á¢*VÄ.¡;åj±wøX´Àpï%Bp¤,*ŸÐز3‹Ð'”^õö =ϯO莽Þíz"y¸Bcsî_fÀézÖ˜R ¼á%'“Ò)ô¤$F)p¿\Rj{d#µ(Ç i!õîKŒà>5nóÑ/ôh,A‚s—÷ ³ß}u ݰ ûâšÕÐ+t»?A‚áýz-R uz¹…¾OÌV°í9™‹÷šÜBߣ`[è~ÒWb œíS÷âçJ ÝBå…D90š÷R¸…p0¢Èt.j üµíº!ŽÝBéb·Ð"˜ÜB÷Nen¡±Ww†Ò/ôÒÞ=0zµº…Æ 3-t …C*}BwxgA d~w{„ÒñÚ¡;¾äzp‰“Gè¾1Š¡ÇñÑc¨-‚á9¾-‚q]Fe¿é•v,R } åúNñOe¿9†ÛâºÓ…J¡ïAdŸBéÑ%‡P^,ùƒüJ Ðw4^ýæ“ïOúƒî’?èN·RúƒÝSéÚ2õ¢ÝA7xOØ”ÃSÞ >oÚTþ´òÝé -oІl—ö-Ô³fzƒü0ÕÀ˜±àdJoÐ;¶I ŒkÙ"f-xh2@ð¢.J50¢ZÝ"fZF¿YÏ–!cQ²‚1ç«A×ÃÁPn³=  Ÿ¯ôE…7èF7S*‚G±­A‚‰q$¨S)Hðwаä¤@wÐ )G$øPœR`ÇV ŒMõMp¨)HðÁÞyÈç M0bJð›1/y•$i´Sd ® ‚³¥?¿O$øà³¼ƒcrZBc>»Q0^ëpÿdà™Kþ |?;H0<ŽÖ Á~2²A‚úÂ!ƒŸ£‚ß+¸ˆ‚sëuxˆ"FÐ!F°3þO1‚ºåŠT§#xKªcŒà`À€b¹ÂQŒ`GºdǺÆfcß¼~Ož9,ÆâG¡ŒìO¾Å#øHòcŒàƒME#Üÿªî ÛN©Ž!‚\o9D0°--¼àjáÁk(h0UÁØnÿÉ2 ìAƒ d•C9"ÈgÏ!‚|B"ÈçÊþ ÛNQ†öœÆ!øì©£•ÔIöfbÕEôÓ–ŸEô;°ó 7Eò¤² (W³ý‰¨ls“Á¨ù1›’5¿½S¬ƒæ·sµ(ÍoçRPšŸZ#͉›¬ùíËPóÛåwJÍoïˤù©9ÒüÔOi~;cˤùíz4¿}p‡j~VÒüöAŸMj~;wûæ¹²j~\ñ­ùÙBͯ:~êÕ¾ãXI¯Z(÷ÙB¹ÏÊ}¶Pî{-¹‹ä>[(÷ ä>[(÷E$\òå>•‘Üç2ǽü¤Üg å>[(÷ÙB¹ÏÊ}Þ–ûŠrŸ-”ûd‘Þg ?[¨øÙBÅÏ(~6Pñ³…ŠŸ-Tül¡âW,PüíXÅOE¤ø©ˆ?[¨øÙBÅÏ*~¶Pñ³…ŠŸ-Tül¡âW,Pül¡âG‹?[ øÙ@ÅÏ*~¶Pñ³…ŠŸ-Tülâg¿ñÎVü\†ŠŸÊHñS)~.CÅÏe¨ø¹ ?[¨øÙBÅÏ*~¶Pñó¹ ø¹?Y¤øÙBÅÏ*~¶Pñ³…ŠŸ-Tül¡â§Jñs*~ÅÅÏ*~²Pñ³ŠŸ-Tül¡âg ?[¨øÙÅÏ*~¶Pñ+–¡¹¼¯ŠŸ,Rül¡âg ?[¨øÙBÅÏ*~¶Pñ³…ŠŸ-SñÓ­’âg ?Y¤øÙBÅÏ*~¶Pñ³…ŠŸ-Tül¡âg ¿bšËa¡âg ?¤øÙBÅÏ*~¶Pñ³…ŠŸ®(?¡âg ¿bë\nÅÏSñS)~¶Pñ³…ŠŸ-Tül¡âg ¿CÄFÅÏe øÃøÌåRül¡â'‹?[¨ø©ëRü\†ŠŸ-Tül¡âg ?[¨øËøLæTül â'‹?[¨øÙBÅÏ*~ê(?¡âç"Tü\†ŠŸËPñ³…ŠŸ-Tüh±âÇš­øÙBÅÏGQñ³…ŠŸ-Tülâg?ŸŠŠŸËPñ³…ŠŸ,Rülâg?JŠŸËPñ³…ŠŸ¢âGKÉ¡ô„¯åU“ëœâ¡Sƒ°LɆô-äÃTè7Gýy¥~Ä·¡³Ôk‹³ѦL%2”lE½ßŸÄG¶”ª`sU4”ªF¼×æ.§ê­,®Š6U%Ã{¥ØugÄEù‹9”üÏgî÷ïÒ)ý(ûo2+ýËü3?‡ÕÛ¶>K媧 ¢ð^1±&'OBM%w’jR!ÖTÓ0¡¦’:)kª™“X“ ¡¦% kRê$TäÌIª‡EXMIÀÄZœ6 Õ”¬IªG…XQMÀÄGÍI“²¦š3I¨ ¡¦ÿ$±Ò»?Æbávb¥¿2{þã;þf®üÇo˜ÏüùûæGM;±Ò»bú_šTéÜnü9þõ“*EÑI•Âè:wýëÖ¿~¤WZOžé•Þ¥oCz¥0~Ó+…íÿÑ¿þ¯ßؘ^éÿ>½ÒûâÓ\~äs9ßÅPNžx”zMyô<7Üñá•ò¼¸þìùñõy:ýñ÷ÔBß5-ýñ‘àèéýñ÷”5Ÿ¹Y¢)æ¹ûAw|~Kîîø²œtLJÆöZèŽ/ËEwüƒ§ºéŽßRˆ}úCwü–ßlßE÷½ütǧeltÇ—e§;>|xžqÐé—žÑ莥ç'ÝñuÔIw|Y.ºã«ž›þø²-ûF|YvzäËrÐ#_–F|ž+œ€Úr®ý¤G¾,=òe¹é‘/Ë|UÜ鑯"ƒù,3àåTñoçRæ G¾, ù2œôÈW5'=òUæ¢G¾,7=òeyè‘/K§G¾jôÈg™Ø½¡/×´íôÈ—å G¾,ùéLób)òUä„C¾ òe¹é/ËC‡|ÖÛé¯"ƒþø´D°ißËN|YŽ}ͳöb󮸪yªó¤;>¯ÖyÒ_]tÇçÓxÞpÇ—á¡;¾ªétÇW™Aw|–¹6ºã˲ÓŸG]ÜñehtÇ×A'ÝñUæ¤;¾Ê\tÇ—å¦;>ûy=tÇÇŹ:½ñUñ 7>-÷Fo|L‚ýÞé¯2Ç®yÖS÷K³xÖ;ÎÏ$Þ·¦I|éû±Îáï,¥9Sx¼£÷å9 7Ýu ïãÔž£flMSx–ûñ™ÂDZk G™¶q ù{|fðqöÏ >®G38,÷£G=÷g~ø*3Îu ÛÖ4…òë>¶c׎2m[§ðIž:á¼køáë ëÑ Ë}k‡å¹5ƒÃÒ/Íà°ŒsÂG8ï.Eb§èe ±çó¹ôsî}-eÚXçðŽÍÏzªëÑŽzî[s8,ϵÎá#ÞÒKlìØÇ©I<¯×t\®é±šÄa9ö?–»a.“øˆ}™®¥£scËåšÆiÏZÏ}k‡å¹þXzuôS“8Z3NMâY&^ÒË$>â%½Lâ£û:‰X®ikC³8ʼ¸–ŽÆÎ(÷z®ûÖ,Ž£"=Âz®~j‡eYñ¹#Äróâ%½Ìâ#^ÒË,>Îø¢p®–¡YUÓCP,Ø/l$ Ë”yÄ‚=}Ì‚îYÐ'' úädAuŠ(Xê NŸ¯ä< `T³/,X,`A[È‚qq¦W X°” ú>£ÌüÊ—,8í$?°`)t¿É‚aÁQ`A_P²`±€ò² FQÐÝ@¢`”4Ct/ ƒñpNj oa0,{ ºŸ„AÒ ë! Æíœ®¥ÄAw“8èËEt¯ÈƒQM¾sȃ¥ xÐ9y0ŽJÔºÅÄA]cÒ`LÆg²hÐW‹4ckn9%ÔüôdBŒ9Ù‘KР'2Ò`Õ’ý@ƒ¥ hÐç F‘ùå\0¨ [0ÈƒÄ‚å °à\ µ_…ãÝ0½ÍÉ‚š!Å‚šåÅ‚ê¦X°T Ô­ ºf° ¦^± " †eùm˜ÂñÌ‹KÅ`A7‡,¨gH,XÎ,°àûøU@P7J ‡ŒD/€ OÔô"¬–œ½$–Š‚nAP/A0ŠÌ(‚¾4ADôÉ ‚n A³¼8ka Ÿ:Q ¦Q`©X, @½`D¾ßmÔÉP¨Jè^“c;§YQ ¯)P“–(°œ ¨©NXÊ€ãÒ º›¤@w“¨)°@î)P“Ÿ(Ð $òÆü¼KâÀðÍžn‹ÇŽí$Åc`wh‚`ø9‹6¨| $Á™ýc’` ðH• $8s{æÞä Á¶ÅHM¦K|ëÁöÐ$Á™÷¢^’`Û"ì—Að-rQ†LlÛû†Øª68ãÜI‚3íeOXœ9DãeUµÁ™jqO¬ÚÊ5¶“MîKœù¯T “gfEðc’à<õ¼|ÁÙ4GœY[” 8ËdŒ@Љ;I‚35eJ´ ÁY&·• Î$“ùLœù ç è3‘çW²aC.Wl$@ô© ‚Ó’¯àA_>‚à̯šë€à¬·%÷u¤r}°΃rIœù7ŸD¯©\ŸN:;ÊõF&.’`9HpZn°!R¹bdg§’¢‚õ '3¹ÆÓ)vdrõ™3¹ž‘FôÎ~çê 8-I ‚óJä1'R¹>\Êë‰.¤råõΫ—µ>HäšK0 Œ’§e‘O” ø^ 8°!öÀ8ÇæâCWdhÎß= s¸>ÂKœw@šè1Oœ·d«z`y €€>7Ðy^‰€ó%Gg™QÐ÷èô¡DÀ2gƒó÷à ®x²I€åñz[à¼ÂG¢ÛŽ®7rR‚g‘|.@€3AOˉ®ï»“O¤p}Ÿ‚ü&,7X›ó ‡+'X" æ= ç=à<ù•t·#‡ëÍ[H€Õ’8-§ÔÀYÉŽŸÌáÊ~ƒë©oäp½‘“8ËT1°¶n …«.0,¿Œ¥±À¿™»xKfLü›o‘|Ô³-{Å¿ù^Éïu‰ó VµÀÙ–#Ožø7«É¯sÀ¿YMÖ’ôçȤ¿Ù¾Y$áϹ– Õ’ðW®àÏy1ó¨3©2á— äWNü {«..Èo¹)ýæ[:m ŸßÉD?§Å&ú•$ûÍë2_Òd¿rÁÁ~-â©%pvûªJ`­'ÙÏÃÉ~õä ^4þ¦eOM/áÏ—ôWJúó#ýyhþf5=+Nú«Õ$ýyô‘þœ™ô÷Z¡—ô7¯r®Ò“þJ5 ¿yÐY•À(óËèçËGô›Ø+úùÆýjµ‰~õ¨D??D¿yÚ›ôWúú›–-y+éÏèoŽ YÒ_9è¯ÜІ>ÑÏsÑož¹ô›—L™è7k}ò̉~³š§¢ß¬Œ–èçÑGô+# ì7û4ª¨g“ðWîàovû©`-“ð7-gž<áovB `2`¿Ò%°_¹¼`¿Z&Ù¯ŒW°ŸÏô+×è牃èW®0ÐoÞàa¢ß´$½ýÊ0ú•§9ѯÜ] ßìù™–D¿Ò@ ßAŠëE5¹ö$ìÍЪö”á™°Eެ´W*íEwSÜ$íí±yQž ¸W,à½r/,‰D¾8*I‚È·O?û_F¾wä #‡˜OÙíÅ|Øb>åŠ'ô…!õXB_T“µ€ùÊ1`>%(óåS'à‹‹•°Ià‹¦ì ñ)¡ºˆÏcŸÄçûBâ K "Ÿï&‘/F&ÄÃD>ßM2_ôéÈ"`>=òb¾8UEæÛöôóEG‹è7Ÿ—\ ù4g ùÜM"ß|pÒäÛì'$ä‹1qUÕ¯Œ"Ÿ/2™/Î~Uæ›3Nj*d>Mˆb>Q2_\‹üJ5™/š×ÍÀ|1$’QÉ|qêé“!æ+Gùb—‚­ª~¥ã„¾(“S¡Ï—‚Üçnjܖ"¶åR7É}±,†^î‹l‚ykÀ}ûÑ(òûbpõ…ûJpß¾ó»ÁOï;_lÙ0Šì7[“„ðÛw~Ë ø¹y¿bøE5ùÙ„àW,`¿hMJÓ„¿èUBá/"R“x©ûÅŒ“z"áÏ-$üE`k¯^ ó²'€þ”±Qð§W¿à/ªÉcÀ~Ñ`&Ø/ŠäWR²ŸïÙ¯T öÛ d¿¸©«ý4*„~º\B?]v¡_¬oŽâêq"ô‹ƒFŠz@¿(³8Î+º-è§>ý|Ð/:ª¨W[B?ÝÑ_4ç©Âß’³›„¿¸¢¹p&üÅ¥ÕtŽõ'ü¹Ôýbý–EÀ~±†Lz!ûÅA©’ý¢}GQþü ‰ýôœ‰ýæ¢da¿(“Wø·ïø¾.ü‹‹Óò¨Ä?wŠø'ߪ è¬æNØþi ÿ\1ñOÃô·oæÁ¤?·˜ø–cÁ?Wú‹ä¬Ò_£¤?w¼eXÿ\€øçûMüsëˆ1ÄÀdÀ?_ò_9 ü–-Ë€ÿ4ü¨üÅ~y{‰3n¾*sÜä"þiR"þyÜÿ8ÕŠþ<ÖHž(ˆl#É’=@#õY<@Ýäª8‘ªövžž¼yŽ TEòæ92e(Ëî<= ÅÃyz.\,cËKl êal ›ãØ@ŽmǪLwžž³ ‚¥Œƒ%÷íÊÓ³(‚¥5Ä+µ„ªb…ªÌå<=P øP5|œ§ç¬`XP‡²=äQT™Ãyz8€n,p| ªQ| Oîø@U£ø@,nJ| êQ| ;êø@4°Äb-SâÊy‡óôlŸø@¥ø@J Š|xâUâUÍã<=Û'>Pe†óôl ÝóHuÄñ:Hñ¬Øñ‚žây-(‹âs YÂU±Â±„,á,ãð@Vìð@YÈjˆs;:PªŸ¢YDÁ4(6PÕ26·Î±¼ÂŽ D- dÈ"Š TE²¹Ž Ćÿ%2—Á‘LÈ.82ð!q*2PeÆr1Y½D²G²yŽ T=Š ”E‘ؘ¼DªŒ"Ù)Gr;2—Ë‘l³#qÕÈ;0Ð* ycˆ£%0-þMz%«mîH]°$í±ïçƒØåûyŸPèìûÙòSÀ¿óý J^ÕÀ½ÓES¾Ÿ™îÕ®ŸçNr£ëçk!ïý+×Ï Akvý¤˜m×OøhÙó“R+=?áFQ´Ë÷“Ý´ïg§æ ßOîogçÏ|[ÿZlw˜_¿åüÉ»+þ½eT9ú(: œ?{†ŠÚù³ßôã¤óç[1BüàüÙOø'Êù3Š”éüù^öô|’ógïøÖ-ïÏ÷ZäWkyƳ™hïÏN-WîŸý„Æ%÷ÏŽhV»ö®…òÿÔhxsWú› ÌíöíÐ9åÚá—mÐYÔíúP‘h§¤%'ÐçmyÊV^ ê¨¼@»”Fz¾§Jß,yÆÐ5°%/Ð.Žn ;r}Ï~×HÀÙÑ  Ý@ù¬É”£In tÄ¥è{S>•èÛ…dJzÊ­Y^ ±[ý/“_8rÕAteKä*ï]ù€êîÊô­7‹Ðô©Ð7g¤dù¾—2Ÿ ùêrËT#D šäª¹D T;:€j̤è[펟pÕ©åÚ©åú"ÉÞ½:€>ñnP·Ž ººríˆ9·¨†|@cÖΣèy9Rù£¨ë¡(ï]@ù° hÞùêº>€FþŸê‘ü?߃FÁ½y@;œFäÿ©zåÿÉSËýSS¥Ü?™Ð ý¦&IP7. ¼'ò•¸<@u*y€jÞ‘¨Æ=@ß§Û<@5—ËT—F ºµòÕ­•h§o‚<@c3î<=@i±è7!{€rê¶(ç{€rþ²(;*ÐØV¾²Þ´Œ¬˜ ì–=@y#ìúVœŠž<@yyäÊgÌ ïA)ÄÑ´_”æè}VP] ù€r`PµO> ±ªá“vÝwH¤rÝÆGÜö“J]@u¹èš/˜"êÝlP.Çìú¶¦­^ ˜˜íÊYKN œìªcèª !PÝpù€ò ¹€r‘bPI. ÎdöÕ}‘¨,P¾ßíúÀqÈ> |Y ”Ï‹@ùøÚ ÔeèªÉ ”¯B;žw‚‰½@ù¢³(³ö=6÷Ñ ”/;{ªSòÝøõF^ ºôÕõ“h$ZJí^ %òÕ©äÊYò*•Ý?g^¦ªó½#:=¥óíÝ7¡ó1C’u>¦6²ÎYJ ©ó…ɯ*óí2IIæc>$Ë|¯¥UÊ«ê|Å/|†–­^Š…:Ÿ-Ôù˜{ :ŸRç“E:Ÿ-Ôùl¡Îg u>[¨ó t>[¨ó…ÿC² u>[¨óÙBÏê|´Hç³:Ÿ-Ôùl¡Îg u¾bÎg t>¨óÙBÏê|¶Pç“E:Ÿ-Ôùl¡Îg u>[¨ó t>[¨óÙBÏè|6Pç³…:Ÿ,Òù˜hÌ:Ÿ-Ôù|t>¨ó t>WCÏê|>Š:ŸËPçsê|*#Oe¤ó¹ u>[¨óÙB¯XRç³:Ÿ-Ôù|rê|{ã/Ôù|u>Y¤óÙBÏê|¶PçÓ¹¤ó¹ u>[¨óíHÿ+o¿¸Å u>Déå¬óíH¯kOGIçã¬"O-–Î烨ó t>WCÏe¨óÙBÏê|¶Pç“E:Ÿ-ÔùÔfé|.CÏ–©óñýdϨóÙBÏê||iXçsê|²HçÓQÒù"aѪóù(ê|ÅÏGQçS¿¨óù ê|¶Pç³…:Ÿ-ÔùôIçã»Y:Ÿ’Îg u¾bšËûªóÙB/të|zD¤ói´KçÓÕ‘ÎÞlIqÔù2£Ì?‹Îê'~Qçsè|®†:Ÿ(Ïe¨ó!¯¤e>=±’ù|e>®š,óí'wV¡ÌÇÙÁ2²ÌÇ›e™«/«|¼\Rù¸Ì³ÊçZ¨òñÚXåó¹©ò¹}Tùx¹¤ò½Eîeç·F*™Vù|U>J*o§U>[¨òí÷”¡ÌÇ[c™Ïí¡Ì§NHæS×%óñq”̧ë%™OWY:ŸN.O•Ч;!¥ÏÍÒÙßW¥Ï§¢Ò§Š%õqXHé㘴ԧnJêÓATúÔM)}ºêRút¯¤ô;WÐrg¤ô¹9£"ƒ•¾×­ôiàHéÓ…Ò§IéSó¤ôÙB¥ÏGQé³…JŸ:.¥Ïí¡Ò§ŽKé³RŸî”¤>]cI}Å©O§’ÔÇæ”¼Jû6Ý…KªŽ}3.Ä™AX¦dHúòa*ô›£þ<¯Ò¾Ý¡1Ôzeq#Ú”¨D†’ÁèM®3ÖÄ¥‰´”ª`sU4,Uõc­(×jÂR*™?ÿÛó)íÃ~ÿ§ù”ο‘Oé<ÿ£|J¿N[„ö%ÑÌoGÏþ”ûžwu)Y’ê*Ù’T—K±®Z u9]ëªù’XW)…º–R¬‹)“T•s&©&•aE¥ ëQÊ$UTr&©&—bUµ6%Mb]5k’žQ—B]ÿIn¥Øì©?ÿãs+ý•ôßÙð7óå?~ÿð¬sè¿xv¾5ýíÜJ{,(?ɯ)…þïße=ú‘_)þÎüJ×cz¥û7é•þëÿФJkÀ¾÷µ»MÔ*Ó—^įåD2Å=ńג©'ÏŒH|ßH›}å÷ò×ò´ÌÄü¤€óZB=IKG-ïó Ë•õÛ–"Gê5a\i™âÚkÙ‘7{¤œõZŽ'Ý‘ãéµ Å‚>ËÜ~àˆŒNóóñk¹‘ái®Þß±ÃWZZ®ŽÐ£ÖcÐæ…z}w¤ËHËÁ+Úö>{UŽzû€4Py)Zƒÿ½Š ÝÒÒ² ]@î¨×rãDOv¡¥û´ÿÞá˜åC)y¶ìä¹mà(4îtpÔɸLÜÅÕáúYsË q¾=xVËÛƒ¾žýn̰çí=Ísæ%?™T€;w¡G‰kÛØ§{‡E ypæëíÁ¹ZØ×ãÐr^_Kì³ZîÆ>ÑòìÏÕ?ís`¹ß>ìË1wì¿– ¯³µÌ±fäy-›”Ü»Û}`=± Èjyû𬖷k¯î¾¦äy-cíÃó£û@K„Þ­GÏ’yãµ´ûs¯žóúÜ«Ç} Å} %6”[-!ª­–±}îUß¶¥DìË¿Ž·î>ð÷eÂÇr-óöaíU¿ÎO¯zì^¶–q0þû>ôð„[ËŒñéÕØÖ{7öþéÕˆ¹{¹Ã}`™Ø-}­÷íùœ{Ä6ck™çøÜ«[¹¬G¹<Ê}ȹbQr™+â-S‰9œ½b‰·ÇZ‹û@‹û@ËÜÿo©çíõž+\.Ö2cãžsbt‚s8,;û`Ëþ)q,Wfô¾´nîÒ±Zfr‹2cïûììÏ*y½/ï²mcŸXóë¾[ÿôéØŸÏ}9Žgiͱd=zŸ×ú^"—¶wûܧw°>AûáðÌî,ãÓ§¶õÏ}jû³>A{;îÏ}jm­·¹ù¶Ýãý¼Ìï­ËeQ)óìëé;ß¶¤ÀRXÊ€÷‘ap¦Àr”û@‹ûÀ£@PÕ2Ø+œ+)°üúR`±¸}¥ÀRª ,P`±€}MÇ> ÷áw Â¯”5 ªüª^Q`±¸Ù+Q`9ª†*e@¥ (°Ô |[¸ƒÎÐדX~k¤Àbṳ́ÀR‹{@‹{ÀzÀP¥ ªÔ ´…è«N t=ûÀßí^ÎL ,u€KP`±€K½îË ¥f”-¤@÷‰èzHÅÒ>µ ¥ªX@På(P`±€‹XêAl!ú(R`±€cwª3- ÀRfR`ù>Ë>‹UÚ ôÈ'Úr¹@³] –ƒPÅ,–k½ „ÀRÂ] ](G Ü<2 "ú 2`±üèÂý£ dÀb@•zîõ “Õ<"`©Ä=e|,dÀbúÔdÀR XÊüèÂã.`ø‘ËQÏÚb2 :E,†oú}f ª!Úþ+µ€ÿ\Ä͇áÓú¤?ÿðW cí ÑÏ n:Џå8 ÉWñoäO² xná_VeÀË”rº2OÒ_, ñô÷<{fú{$è‘þºT,Ò_×·_Ò_Ït憿ðP‚ð×/Yýæâð×/®‚ ûàþJÍœJ½€¿ð(Ç1€¿~aLöë7×õd?7†ì×o®‘È~ýæŽìWÊ€ýJ=`?¦6ûõÜ|è×o.·ýÊo _¸Ü%úùÄD?_;¢Ÿ¯Ãéë€NÅtê7™Œè糓ýúÃ¥>Ù¯´‡}ÀeHösŸÈ~¶ý|¡È~®…ìç3þŠ…=àå%û•ŠÁ~îÙ¯ß_ö+÷OóØY®—ð§ÆýJ°Ÿ¯ÙÏý&ûù>‘ý< ¾¢„¿bü•£Æ^Ÿ ²_¿ø½€ìçŽì烀M{D??•D??É{€~ý\1¨©Tj*­ùyÀ&ù¹‹$?UÛÝ|Jéîn?ÁÏ'"ø•2?÷›àW,î ì‹€™JsÀL:(±Ï?A}n ©ÏWÔçë@êó'õùn“ú|*@_?ù¹ˆÐç w€Õ¸iô©É€>uZЧ+.è+v£HÐÇ‹ùʉ@L.äÓ°ò•öùܾÝ=@™=À‰ùôŒ ùtS„|ÅäÓ³.ä+gvx&S)`*gò¹—D>×CäÓ¥Iâ+‡´{=´äøJ_±€ø|éw'fû}`Éø4¤|ª†¼çöµOÈ{¾â=÷š¼WN ÞÓc Þ+õ€÷ʹÜÀÓÖ×ùA¸ç>÷J™v}F^➟âžmážGqÏÍ#î¹y ½r"О¯Íå.  q¯”+©bÒ^)Ús/“öÊï»-Ó¶`¯qÐ%žc} öT„¬çzo·õÞîË”JÅ%W|/‹L¡ž õ|#‰z¿D=DÒó¬HÒó½&éù €žïÚãöãÜÛÏŠAJY‡z~ z¥^žO=ƧK$=Ÿˆ¤çjHzå( ž*&êù.õ\„áYŸëD=÷‡¬WšØóm$í¹iÃÍÇQÄ=Ÿ‰¸ÇÖþIÒ$#Þ=cK*â ¤Ôâõ?€x}¿è Ä‹º¾ ^\àÇ$âÅ"ˆ± HaA ^X(ç%ãõ£Cmâõp*…Æ–ˆÁz î—Ù…Z ºà“ñêQ3 ÷1r !^Xк$¼z{À"TAx½!Ñ®/,¸| ¼Ø -ê^µ$áEÍp‹á…e€ùf"Ügšûݕ߉xõˆD¼ÞNùMñF§îIă=8Ù] vÛû§/n{xõ\‰xq%x®D¼¨C-¯œ»ëß“Šˆµ‹Ÿg”‹Ÿg¹¾@¼rÿx¥—`¼E´–ŒWz Æ+cŒWËLÆ]íCÞp–„–¶|Ñb\+@^= 7:G ¯œûf†jND*Ï /Ž‚›6 ¯Ö“W[8öåjòʘåÅ1×âçGáyæ•3óJ?y¥À¼2ÖöapçÕ&%…åFÍÉy¥ç“óJ½ä¼ñp,ôʨè샮(@/¦Ì2 z1AöÅϳ• eŽôêQèC9*A©¶'A),𤘨½Â÷7°^™]Àzý8s‡9±^¹¢`½rn²Þ{upÏÁzÑb’õæ5B5Éz1¥¼ƒ]¸sÃ(±žÞD=·8QÏ­#êùõBÔS[Hzî€HO ê¹-D½RM¢žïQϯ?¢žç¢ž/D¢žG~¢žï#QÏOQ/,7€,Q¯4wg\†à('êù9$êy¤õJ=@½r…zå®ìC+¬WúÖ+½ëUK²žßùd½rÅÁzq|îŽ=ì•~öÊ앃ö<ôZ[&PÂ^)pŸ‘Ö+£¬WÏœ¬×7ì)Ö«eÜŒÀ^¹¢€=ϲ„½rç{õ¨s=ÓÉ>höü¦%ìy=AØ«G%íùÝKÚ+Wøúч‹}ÐEí•‘Ü+׸çÕWâ^¼Pà^—t¤½Zz ·iÏkâ^¹›À½jIÞ+׿vÐ'ðžçaò^é%x¯ÜÍ |õL |µ–$>wóf\d vjqï,õøbµå•ð•{ â+cݰxwÖŠ“—j5ÏQ_²¾zê¾ra@|åñ¹O>¯é|QíðUËyò>ñ¨«ñ®à^ùʽœÌ×7ävóÕ¿m]{“ùÌd¾ÒI0_`>¯»È|º#QÒé·úÙ£’ ß¾K­Ë},á >{ORዽn‘PøbG¨Õ¿soò¨¤od±ä—¡â©IÿÎöÇ‚aøÄù »Ð¾q~?Ü;ý›î¶Ð½ÓwáYP›û÷N[èi Ý;m¡{§-tï´Å} åþœ‰[ám÷N[èÞ)‹Ü;‹=°…=°…î‘¶Ð=ÒºwÚBÿN[èßi˧ðïôozGÊ"ÿÎbŸ>É¿Ó÷€Xö£rð´…ž¶ÐÁÓ:xÚÂ>¬X,òð,–ñé•<<5úäái =<ù¸ÈÁSƒDžz8äáéjèáé2}ÿˆ>*B—NŸúžŠìßÖïûÒa:tªrèÔôçô!ôçT·íØÝxZè ÉQiwÎbë“¶çzäÎiËQï)½9Õ!j{.@gNŸ…Μ®“ΜjÛáö£7Ÿg¢¤*–/§-ôåÔQòådÅ­}*qÚ*íi®–´§Åޤ½R¤½b¡+g±ŒuˆQÚ³aÖ©ZÊž‹´Ïâž °ý2¸ù<âù,}ìÅÉùTº^)3ƧC—ÛO–úÑêz¥L»Ö.Q׳áZVªzåÄîÀÇWŠ@+-Ÿ¥›d=E]Oßn>‹¸ù´@ó©(ë˽6º^)a¯X~tž롲çNQÙ+e ì¹J{¥Œû@‹û@ ”±byÖSÚ+H{¥}?úÐÝEm¯”9îO¯¨í•£ îù\÷t;»»P£øJ} (îùÙ§¸§*¨íÙð£õãX×mRöx¢ß$=2͵) Wœ;õA–8w5O$ΗNà\lv¼†ëÝ¿ÙçîQ€@¡×@ý (›,­›·Ø 0wŸ„BÒÜí0;ôà>¿4wŸ¬ ô˜»/l›B–»/íâ–+vàú†êÝ—wqÉ áV€Y®XÀrå(°\±€åîûål`Ø–IA÷@½ØÁG€äl!É©ÒÓÍg7Ÿ`P±ƒŠ W,¹û¦ÿ.A®XØ3!È~ùû†/9ν&Çù r\ì°Š£Ø—qP T*Æ 0.wdþgÁ¸r*ö€û·|{@Šs[Hq.ˆs-„8Ÿ‡çÖÝ?z@ŠsÅ  RWZˆ+'k{Ÿ= ÄùB\) ò¹Iq¾ý¤85øqÚ q¥PP) ò£BŠó©ãüˆ’ãô`ã\mwPTjƹ(ÎPœ'RÜ}QÏîn?-  [î¤8דçùާ§¶âÞØ€Šçóâ\ (Î&Å•j@qîÀpVGM$ŠÓ”ŒS[Äqåpœî´@®ÔÂðF äJÀP)’S7…rì‚HÎ ÜÝ…³ÈwqS°–H–sÈråÀ\±ætâÝíg5l¿-€!_œ«Ëi‰åÜ^²œ+>>=H˜S¥d9_Â\±æÜEœïÈñ£ý‡ÛÏ2@!ß#Ò\±ìÏç&‘æ\OcXÂ}@'‰s¾TÄ9÷8ççJà\9û ÖçŠ\î-€¢Òp2±ÎP¯Öí ˆ;€jIu>5©®”™T§‰[TWŽÕ ;ÀÕ·¨ÎÏ.©Îg"Õ©Á„:WL¨+Õ¸ ¬Æ]À#Ô•£žµÁ„ºRP'ÈÔ¹Þî.€Å@E¥¨ÈÍ#Óù ])¤sv@†gA Ç!‘®”Ò© " n<Žn<õ>0-%µ‘Y.?°,{pjIsÚ{p2fÒ{p2hÐ{pn™V­ìÁ¹ë(îÁ¹g ¨²§ÊhÎ=ST—=8mÍ úËc3ï#J `¨Xnœû%‚çŠ­Ñ ˆÎÇèªE= Å= DT, ¢bÒ ®X€tøíù4¥ ²…@W-ãÓ!]±°ùkä])*à\±çX XŽ??M¿~4$W-ˆÏ…ŠŽ+Àq,ˆ+~´›W,@ bÅ (®X&Å«§ŸãsÈoÅúá!€7þ¹ñ'Ÿ?ZLhcO)b³%‰­þµýG‹ûÚbÒÕø ÆŸÀ4þds]9[LwÊmý9êXJ4óÁD³H|µ†Ññ€µ­Ä²R †e¥ ¬Xe¢Ût­mÕÖ#ü9jÓµëˆ×®#(Àæ®Xßܩ?¯ºÍð÷ÁOî0‚Ÿk+µ·ˆš¥½E@ ÜXD6Aî*²’K©pm«ö©ÌÂÜId¥ýµé}m¨öÁOnÁŸÜ:d¥þ¼êªÄ{†T,q‡°cþ8ê[Ý»…¨´¶ Yy¤X[ªB°þ¬©vŽk›£Â™ÎÈøÔT;(SSí| ù0§ÚùyÔ_Hµƒ´ò¥^YJbØœ·‚†šç]•χ©TEK­*m¥*jUç‘‹”Ò[ZJU°¹*þûSîLºÿ£”;ï(ýßrçç°:®c>´5ÿÈïFÑ6pµër2ÖU“é°.—b]µê*ÉtP×’Lu•R¨k)ź”N‡U•t:¬IeXQ)ÃzœL‡Õd:¬É¥XU-ŇÎÉtP×’r‡ÏªK¡®ÿ$åλä¹fö±ÿá)wþÂLúï¬ø›yó¿xÖ¹ô_<;ßšþ~Ê#2ÏÿL¹³ë_÷ï’ïü×ÿÉwŽkÏ(–ëå9Î÷Í="³z¾2g6ûHƒ:ò÷93­Ç§¾ ù:®+Ö^->È]8&>¿–ÞñIöµÄ:±µùAnžX)¶ÈYÈ7zætÖoÄÓ׈5Xkáê–§ºc 稆ñÂǽÇJ¬µëÆØ÷™ŸUd.ÎPjÞÆœ™“uþŽÌõgĸàˆ+díÜO,ƒûŽ5Yko#só‰×˲·Öï©ï(•Ù[ïW‘ãΜûŽO¦ï»xöà|Û›sê°Ä°<×Ü®ùµDÖu”9b¡ÖÎû`=s/íh3ýߎ'û°ár>èB\_roÓr>‘ä3-±j{OtýqÀòĪí=Ñ@ðÛ1w~ ËY+§eÜóF+·{::z99òúuö`CÄÜÑ6-7wÓž'}µœûìÓÃݪßA îO„ &ÿx-ÙƒØi* OŸ†w0æ:órÏìÒÃñÛÇ={¢³c›‰â·›u¾K—sv)†^v` ƒ[Ä£i¹uT¼x£n®ý¾Ö·ìýµŽñNÇ-poG½Ñÿ<ç@ú@€ËûìeÞ÷†t¤›–¯µmÛâS»"gÖ‘–=_âÛŽŒXm;ÚìÕÃïõmCÞ³ghÞûŠÍ> &ƒhÛµMËÛž S~-c.!ÞšŽºçï ê;=tÞ©Kf¯vnÂþ¾³]¶Úž}úÍ«Õöx—3½³ÿ¼WoÏÌÚy+–kñRû\ϼïżÊmÏ>\±Õ8 èBÇóóÎ_}ÞªÎä`í]\ÆïŽˆ©¶ÏQÖ"UøƒjÇ=;5:æ‰vloÌÈnìÂ4dï°¥eðÜG;f§zü6×ps’?ÛûzÍá¶Á5íµŒ¼U|Ú>̃i™}ˆX´¦?ë™G|°z/ÌÆÕâ.F™ —*fÛ¶Ü•–(#¢¡«Ø×rîiáÆqïŒ_‡êÉÛ5æ}z—u¸äíîÙ%l%÷N¸Ï쑇M‹ÄΙð‡î®©4ÏéwÏÁ˜3ìœÆÑ#\Ýóˆ¯ZsX8*6ÈXÆÃ™¸v:*ÎéìÎævuz76º{'žžwi nýmê3‡^9W¿ùøàÁ<ÇçÎyo6~_.U¼•÷:€cÅ|äðL÷ÆvE$_6O÷uîù<¡@LÇ9Ôší/î•í/·äzž|˜6xAµ«gÒÎíIˆ~oã•©>¶÷­œ×»g7ZïgàFóÑ´{æ™§½PÅ$ÜyQN”¹¶y‹"¨•\ãk¹±÷Ýç y›»µ;›öK§Žý㨆O{~Ù¡…»=Û™·BjïK9Û—‡Äy_*y~táa\æÚòir}®‘·èÂÎ;í¹ûgÚž[—æÍµG{Ø…¯éödâÁIYõ%®“w óEß[¾Œ˜D±½oåe†‹wòžgÂÓïäc9wg¸#ÑkA°3jëwg§:Nô<Ù©+ÂÖ{.„wxzRW>:܈©ìBLɸ¤]ðåÇÁ)£þ}//ƒ/ÞÊ{½wñR>–ék\s-SG†¿“Jváa&Š6žgíåè7Gì1r!4˜ åܶ\i^<·½q:¸P&{íË÷à»0=êÌy¾ïäúb:ãŒQn¼tÆù¨«“wÍŸ+¹ÁDAçÆ¸ÞìW0/Z_|Ù§÷I:¹fÈð.f±âkçœs)÷œ›E{Ë¥\)3û ·ö¹³°g¼’÷z=Ïx%˵Ú¬„øB;÷~¯йgâêä­{ÅÙ Ù3Xè.7ó<ð ħ:Úž7êÆ(y×Ú¹˜ëÄšó}'Ǩy0KŸGvá|˜KãŒ7ò¾žúy0óa…pà´úya !].~‘yŸøŒ‹>[v!†MFbóã‹.ú_N³CæC®1_|ò:8t}soæ£Bßk€ ïüä~ðÙó7@ß³à…Š{~x-–‘Þ_ ËW* oF/úf=à–„¾#ÀØì‹P€É{f¬g0˜ï[?oÖЀ–7œ†\ǧ!±Äö+‚È÷^˜“ ¯8 ùŠÃï2ˆ¯´ïÉöÓÉ ÄW¡@|Å ÄwØ9ÄWÏÓåÿ}‚>ÇM—ö4ç âîd½ |õL |åLÉ{õLÁ{ËyØŽGÀ7-À»G¾ÓO¾÷òŸ“øê‰’øê©’øfÅ ìÆØÒZrUâ›–2»6v ŒÄ·œéŸN öÁôAÝLà³¼7oèÂÚáÿ­¥qò^97x¯œ ¼·X®¬}’÷J/'ï-¿8€ûÜàƒoêÍ]Èë Þ«gJÞ›"Öp+y¯öZð^ï y/Jh…JÞë “÷ZÃĽÞðUýWÃWõ?%¯%ê qoiêy¬’»3‡U²ä½3wiÐa·$¹C) œYA´×ûBÚëíøzÅ¥€Õ žÇ)MÚ[$/½ª3à½~†¨® ) ‘øºàÚ­PâÝöã!øú!ðõÞÒÀmÏñSòÞ?¦_o À·ü>N뤖žRÁéPw†Ä×Û&ñ-’1×ÇDà[/,)Œa×@Õ8¯wÀ×"ïuÁµ[¥„»íÇc™¥€kó§äy~¼Mä½è'mâ^kûUÿKPÝWÓ„½Er®O€°×Gio•¼~J–”®÷y~<%âÞRæ½×±'Ü[$û釲 Õ¤C“œË«¸W·A´×íõ"c®I°·ô¤úoÉ{¯o“`¯÷…°×îƒ`¯·EØë5ï×¾þ.f‡½¥í1×)N°·HæX>¤b½Þ™C*d¢^o›¬×‹œû:Å õ–zïíÇïwâ„z½ÚçYA¯ ^.€ê.È uåü­ÿgõþ¹ˆ[•T'Í{˜7fÞûÐoŠ·ÀIïiC’Hï½.[wDzï}Û&Ô{±\—¥Ž¨÷~¨$ëŽPï…e†’Þ=™°Dzð…ØÅl$½Ö”H/ý%’ôÞÓf™÷¢¡Mæ<ºr,¨÷o›õ^œ!µä¥JOšÉz/HC-f¾ö&é¢(à›ó!øæóæ5>,Æw>”9»CgHT„¸4ç&e |s‰]¾.!ðá*9“ øp,rèB…ö´„߯2ÒjO ø zÔ|,þœŸ$½.‡58“±HKM$.CâƒDFàëÕP…3ñÎ*œ‰n¤¥EÂÞMBàC‡»;g±o)yî´Ù™Y¼ ïµzÄ{ý*ò^¯ùÞ×kJۭ•fCâR»ç¾~¯Õ,âƒdt—Î^Ïû›"¾V³ˆ¯_Eâë ~û"$¼ßtx­CILÕ¶‘¯Êùº„ÈW:˜ùJs3_¿ŠÄɳ˜øªÏd>ü6'úr(™ùz«à"ûoˆùÚEb¾v‘¯†€‘o"÷›l€¥€ÑÑ äòuÉ3ûÛaäk·JÈ×®òµ2‡UÈ%äëW˜šB¾RSÄ×+&ñõŠKK¬ÂÓˆ¯ÿ&ñµ+D|]Bâë+ãá,ì¬I`êÓ"aŽ–&!òu ‘¯=ºsþ¸æË}òµ+„|íö ùz"_Óò²%±gAàk‰Ë—º„È×Û"ò5®w,%îÒA=âR–Z;¾Ö;_ͱ¾Öòý›wiàzˆK]BâkÝ!ð5øªÀ°ùœÆoøê `àk- øúU¾^†À×%Ö õñõþ—ÚU"¾V&ˆ¯— ñµIâ)\¦tp-Ä¥^†¸Ôú'âëW‘øê–>¥‚nÅS*H"âk·TÄך âk*ˆøú5$¾^o© îM«PeÆü)yžJÄ×ëyok¥ÖßÒÁ hJräŠHZñµ–D|ýš{³V)y×/Ò[*¸3Ïóãòõ¦ß\ñ*#_—ìçú`Œ|]rëïk_ß?ÖCF¾RÉÈׯ* ,ù©‘¯VpF¾v•¯î„‘¯—9÷õ£JäkýÛÓAÌ×z#æë-=¹¦³dæšn[Œ}­7Gé Ö}­-A_—œû:/úzÍ÷öãwê`,Ó{>Ï­}í® ú ydÍÛ.kµuÏÎ~ÕùC‡ÿHŽ$ÀývbUv·°—áô¦¼2eò+ ,~— ¥ÅïöÉ—²øyã.-~¹M—&¿hó·fñ›ég‹ß{È’?¬˜ßN”¹$ ÞËgÔhñ{gðãi¸mÛʾNàÛvxñ¯}x³å%¨}Û–'¼t oÛNã‰ôm›Ýy} oÛö¤0‡kmÙ䇬$2ù!±cóïD¬AìcöKž‡C½öæ | dÒ‰>°Ä®«x¢oÛ”/Øú Ø–}ˆÌ£cjÓ*¼¾å:ÑɳœèÛv»ÞûDßö ½]WáD~«€4Ø}òÂ'ú ‘µVGú‚}T ÏÃA¢{¥3}Û~k`éHß¶ûÀôm{šu¤íèHß¶;ƒ©ô¡ž§;x~’·ó_\óÚøR©7¹Ò*”D*Þ-÷‘>H|ðŽÇá¶cO×LéƒDV,éƒdqñ ‰Ý7¥Ã‘ö'éƒdqñŒê|4p¼,!gMéëµðH_ïuÈ3S»u°¸ôA"7%éƒDñDO'ÀOòóDß"‘ ·»éH$³<<¿ßúÁó|²8v‹_Ða>ð!̉üñ,$²…ê0‚YùxóAâzx˜[9ÜûGûp<Ì·ÓçMâ0~O$óA2d_ãa¾.ái¾íð±[ŸæƒäèðÏÂAp/‡ù ™ÝÚ’·³_¯†‡ùz5óY¿k¥:Ì·!1hwî\$<̉Noé0$³£_HF·ö­’×’w9Ì·Ê2à³|MÀ£|ýšÐ ÜV`÷&äëž…kñ$_/“|]ÂÃ|‹Dýßóè^õ_÷A‡ùº„‡ùz=<Í×$qœóŠNŽRA'wG©0;ú-‡ƒäµeo³V)yÿò£-žèë½±>…á}Üˉ>HÎŽ~‹d¿–kt¤iõX‡*c²méƒD‡èt¤¯Kx¤o‹ïãß’ü–¦J) |8§áº„§á¶óLKÞq®¿y ’³{x†d,úúUÖ $<ÉÝÉ/$˜’'úzÍ<Ñ×$¯uÈ«^ëà>Ñ×Ëœê±m<чkŒl<Ò·H^kutô[Zâ‰8Htwt¦’N~­ˆôAbÃôu‰UP5<ÑW½ã‰>üèD_¯‚'úº„'úzWªÿ…ÍýwØ_Ÿèkè«Îé@Š,Ü×+Ö¾^ U¨ßVáNVäi¸^†úzK<Ð×Ëð@$¦ÅRaá¾EÂÓp]ÂÓp]Â}˜y¢¯õ'Nôµs”‹±/$¦GžèƒäíÜ·Hx¢¯]¥}]R:誳t àõ{Ö Øò‚%Ê£g k…i˜I—Î:Þ'Àû–ã¶ùN xéô—.éNhÀ{ödKÞ“9Lx¸Xf5Þæõ¼ ïÉ“‚$¼é/º/AÒ.³Ö£ýÿ{òl´Kçô¡*{tÎ<ÏeÎYçùL¨u2Oî³NÞɆÂÕ¥³˜Õ|‡‘¡Óy×±þ– ¯ÝÓ¥sÚÇ8]:±Ð[]:_ÖK—΢c»t¾ŽÂ.¯ãU§Kç{Ú…×.ŸDç.íÒù]¥2véüÚ:t@/\:_²HŸÎÖ’uxí}kŸNœØí„õ%åÓùýó »äÔùó\ï#dc–uÈÝ;u¾oE.‘onnØ©óu´qšøzÛòê|}2=½:ë9¼¥ƒª•K$޼‹ ä™*¤Sg*žNŸ s9Ä÷Æ”ò·¼¶wNÙ›têL½åÔùf¸{u¦–éÕ™w/½:nCŒe¼÷’n!‰Ü:ÛUr묚íÖY:Ø­ !Q uðXJ·ÎwO |梥Ý:[ÿäÖ‰x&=hK v딋¡}:lC—È#ÒsIºt¾×Êxí]H—ÎiéÒé1"ÎWáŒäÐYÆùN¦Cç7GÜðúUvèÌ™%:_Ç7J‡Îvè¬1d‡Îœ#Ò£³†«=:[™Ða.[ÚÎWzt¾Ž9›9ç¦Gçw»ŸÅ¼‡þšß¤A=${t~CÀ‡å 9ß ê"wÈœÓÒ£óu†‚ôèÌ]JytÖèµGçÌS´öè,½íљߖôè¬ñlÎzvöèD¤Õ\:(È]:A5˲Ɖ]:ߌƒb—Î9ìž¹-‰ôè,µíÑYMÛ¥sÞi&”?d~Ò¥³nŽ]:sÂO—ÎécÓéÒ‰¸®’?$BZè*9DNìNŸÎœºåÓYCß>¥ƒ}:gÈ“3WÚ§³†’}:k¸Ù§sÞi¾“O'ìÔ*#Z=Òáuø¼têÌIÁ>_Sý_û$ا³T°OgûtÖ{fŸÎºYöé¬ÛeŸÎvÕÌÑÞ#·ÄU«Kg%»tÖ4e—ÎïNlí,_ÄŠ_ |í5³Oçûó,–^GÜÝÓ>ª}:«{òˆ¬wÞ>y‡Ó§Ó¥Kg~HÒ¥3—préÌ–åÒ™ ±téâüÞõ›.óÍóêÿTr—ôè,¼!«^;tæš~ÝÓŸ3‡búsV‘è?<ÙVÎ éÏ™c>ý9óæ¦?g¾MéÏ™ËãôçœE^Ö`®A[¢ŒiMÎU³:s‚O‡N82ˆà¡sîéòY:H Îùdùsæ`MÎé¸éÏ9½O‘þœù%IÎ|OÓŸÓO¡'áɸ,LÌZqY2a¬â² =ÁbºC$[ê—Á¹–Óz¸JÁR˜åçMFEÿ[‘ÇBvMâ¸,0‰ž—¥I—e{ÜeÆei¿#®Iû­¸&ŸÄçû™¥Kx¤·I™¥I¬ÁヌŽÌRGfi6iEfi…fiëàߥƒ% m‚ j Ûu‰b³4‰‚³4‰‚³”d––”K8ÎE¢è,M¢ð,Mr¯=ž¿é0ÓÁñYšD±MšDñYJâø,M¢ø,Mò›ŽÏÒ$ŠnÒ$ŠÏ²e4þ˽Ü8KZU’UU,Uý½g°Vµ<—ö þÇç^B¸ëã]s/mHò5=ï”>©*”§‰ÎPà[¾Þÿ({Ó4L0ÐÞ}_3ÒüÁ o,Ç—TMª©¥WŠšzr%×Te\Ó’¨‰5õäJ¨iI­¤šZÕ´¦iRM•\)*j©•\O–p5=E“ji‰•¢šžVÉõTW´¤hÒûÙÒ*¡¦%õ’Çe•QMÿ©ÔKÈçqþÿ>óÒŸ˜Ýÿh:ý9—ÿõL̽Ð?ÿ*üg2/!Ë8ÿ¿žyéßþ óÒ¿ý§ó-}¬ý[¾%Èþ=ÿúo s¾¥sü“|K¾·ßcóëeŒãÜíõ?•Ž_öI¸–Ä67êß“kÉÓž×{q-y+aÄõÞ\J>6•_áW„Päxéàœ r'q »Ù!9å"s…ÕéWä‡âÞý ‹·[Âî³®ã™ßUxOo¨ßUÀŽÝ©2'}ÃpŠÿ¡ä’oØ«¶?—›¿ƒöÜÛ¸W‰{{ ä{ù¤Ã½…ç}]õÒ¯ –MÖ¼oô »Y]î}ß°Xc²žýؾZ¾IÙ%Žð Û‘ÜžZíÔëoYï: cüÐUwø†á5Ü)á¶ÃzSò„kT°d†k؉üò¼Jþç€[÷A °J¦Åç>öp‘Çj{Z.ò'R“²Ç¸_µœáÝvÜvý¼+¼ÛŽëôÓ<¨vÕBÀ—v˜ûxÂQ9 ‡jžáå|w˜Ö²ûx™¸ç›Di)¾Ï-ÜüOTÇ«NêpÂ'î–$t8"iw&½ö9û^@d#ØáBëȯÃ!q#;Òyí6%ßhóì¹›î“* Ç/}Iîs2ïÍWó©¶ßð”Ï,fßÂO÷æÀ47r‘<-ÿÔ'`Úžo¼*B NÄŧ `çHÏíºæ¢›À· G$÷:UÅGÿ3Rdž ¾ºçý½¦´8Ü—z?m˜»/öþº|¨çŽü¿bsNà y_ Ÿ’(kCÿm0kÏcÿ·û»yñL2%Ø}Cl6]*q£ÖÓÞ>ßÏp”Gò½’÷žþHå%µïžþÆ->‘ûeÚx2²wcSڟи5¸¦ÌéŸ åÇ×k°oü •;*ßãdÖžO=ƒq…«?Vèö ¨€‚z×UÀ­:Tïü7õÆ Gyìj|`^‡R0ÓQòláì?>HÔp}vfîž—? 3÷œvà¹ê0¾×@é Á¤¡«.fîA In¦îù†€úü|wà„­L³ÞC†¸$Ôal9Ã>/sßàä=&oãõ¡ä{îáì?.qø$áì?ð¨tÕÎþ‘sš÷tJ‡×†×{^ƒz^~Ýç®òãx²­ÎþmÐÎo¦Â.¡¿Y8J ­‡¡º'upÒæ5¯tˆI){xÊ#-†Þ»‡§<¾Öï¾þã›r,9ÃÙì‡Ux©’gèÁ¼Ráu ›~¾aád#7âV½¿b{öT&zsÛôƧyg-ô9ø4C©qèÁŒ:ŒS\ I耭NúÛ8bôI¾÷Œç±áí?¦#÷í o¼CmÝáíÆ«¶¨¿cc£ß§OæØ¦²ßŒlëE‘ž×àÓ¯Õ«3!Ÿæƒµp®ø¶ŸÌ Å%Èw·C‡Ö]ï~†·<ÿ­š/fðù^=ÎÄß /Üý1Å*3ÂÝ/ã¦23ø¼þšŒ]:|Í¡2o¼ä:Ð3¾o3gŠ‹?÷ÍÑaàÃŒ+¾/}Æq„·ÿ}ª;øMuþu mL|oO6;b)dw5O,…0¹ûf¾põ‡­øßì·O6ãD÷1Eø÷Ç ß“ßü<ðI†‚Û¡ieà› }àdÁv¾¯/¿G¯E¾mpBpБqJd–T=ÒnaªçaÚ›áü£ãœ±Bæx~ÆùÆR¿Úº¶XÌá™ÑMh\Ðéîù–ŽK:ToðUÞ9=MIÎX }o½<ø¾Ò±ú&MM#É4¥•ŠD–xmÕ’4øÞR=Ê‹´÷©¾·\ÌHhµ¼·H·ö²ºê¶¼3üv[ÔÛSƒïžiæøtÆû¶kZß§9tšŽÿõ}çb%4¾»ÅlàK³ÜÔ¢p óñQÝü¤nêO=Í9¿I÷ÔW nY|-Èóöû|MÎrÓ}þþD-¯G,Þ£s®f¹!`6 ƒ:à“ yß H¾ŸftZ}c‚‡°Æˆx\ñ)ÖÔJ4IÉ#ö¡%³·]àp#çO§]2úÝXMvö{¼¬Köûê–O‘Øëy"‰ý\ž(úm¢šì·ùl¦Ùï93=˜Øï¹µ®6úÁQÅÜIô{Š->8"¿ù­à_± Èoâl¯Ø‹ À*µ™I~è?u$¿B|Œ]äw¼‡¼~Í›6Á/Ï•ü`Йª˜à·7qQàwÏ$+ü$YÆàwĺ?L‹¿ï½ÒSàw¹À0øm§‰MÜwTÓ¢¦-‰WàwLÇQOðƒC°:C ÔRàwâ$´MÐôÍAZMü0ÉiÅàwÎ?H}W¬”ÿVÐW©Î }7N &Ù}¤2~ÔÊ£T§N™fè›é¾ú2›¨¡/¦Ivekµg™¡¯¾Ô¦>¼½·xд™0D}ø*빉úð]Ð`õaþ~E†ÒáÍ»)êÈHF± “‹Æ«¨ïÙwÓ¡ïûbÈUÑÔ‡ O¯Š¨oÐošÌ7¦E‘ùö]T™HÁO˜™›>Úwô!›F‹ /Є* ú°Ök"è ÿ8Á‘ Þp‡%}´ÿ­˜ï9œÎÌ÷\v'óÍëðs æÃRþY˜uh+æC†¸) ™,³/Ì—:ƒx^;†šù—M› ‚¾‰S¥Â5ÓóÍ¿›àŒÐ÷h@‰ø>Kuܱ™î¾çñšÆÀã¾›€ob]¡V|óž‰e¾ßÖ,àÃÄ*fð=o"ª€o"Xd¥ù}”µ$Þ›‡#\˜÷PF¤¼÷âs¦†¬ÂðHïÍÛ½Ø<•@kÚIîÍï­ÙnÄ=¸ÿ °„{‰FõPtGƒS¸7µª‡¬„mK=máΆ{óÕ’Ë´7/PM{óû ¼ íÁ_Ae„{ø ½–*¡=1¬p¾.Cܛߔr,¸‡îh×M¸‡¯»î½ßçBƒZ¸/Ç£á>x»J÷ºõL÷p‹µ€î½ß@Ò²V¸7ß7Á¨ôjm'Ö{¿õý!’õÞÃë³rj˜Ú¨ÔVöNìGJš˜£Ä ¤o¤C&=>ÚÒ›á0ð·=<%-özï7 žª†¬Ÿ­@o¾¹èM侕„ ‡ûò¨-‚Þû}X_!$Ux÷T;@Ïh`•^,àØ²PãLýêÅúGÀEÔ{¿Åƒ–΢=¬…+¢=´$¸í!/‹!’°„=u-…{èYHHÜC[+îµ¶÷P‚ï?q、…{5܃'z'Ü‹Pƪ…¸ïÚ[à& ñ ºÿ)tª’âŠõÞËÁ¢Íz­!±Þ{{Ú¬‡ÓOg½pý™ ë½áÈý·B=4t/¨É^tQÞJÚë¡©WWI¬D…vRáqfwÃÂU ìµ×K°÷^ob`/’Ú°%ÁŽHKMÁ<¥¹‚=œ}¸:ì][²‚`ïBÐ+Í*‚½÷û(k” öÙkJ"¾þ¼ ìE*‡K’XaÚÒÈìÅ á%ví— öÂKÛA‚½ˆNY£†´X/N^ê"²Þû}©µ‹#Ö‹#Jõ.̘œ¸ÅzWœ'¾%¡aüЉ©ÿHê%ã^ta1õ ISß©åOšú2Ójšú¦¿Aæ=,y¦“Gä½¥S/â=Œ¨§_DýÚÔÖ«ï~¯E|ç±'€øÂ|ëÄwîÓáD|çþ©«Ål}Ç›‹:ÙúàÏm*¤­¾¶3òû7¢L›D>Ì ®‡:À‡úU=â%Zl}ð ù®ož”1v2i)ä;‘xz±õý£Z¨'Š¿òÁïÚ®”ùÎo•,C™¯ÒAù0Ié&‹ù®á,É|o®oÅ|Ø%ž¡£ƒ+%õeúïľ²+û‡fHì»ÀØÃ’­ˆÂ¾oÁ U¦°¯Ù+Œ}Ûa¬õÉø¢>ØäÄï¢>ìšéN]£Ÿ‚¾o};èä+ô!%b¾ýI³#± 3¨m²•e†õ4õ½G©³¬ŒÔsª®’Ça‹apß~&±]±i¶%’ûîéwÙÜ÷•Ôƒµ­óêþ}XgQt^M}÷™OMÔ×t2õ=¹ÔöaëZkYaß…>®¡æß }7ÖY ôáó Ëš îZ‹ÛÐ÷Í"ú°²¾©ÿó¶]JЇMt£–-}^릥q±ô ðÎÂ}è–ë±¥OoΰOZñd%û†pÇ–¾ª¶ô!Þœìz?<8mHü¾ExZÛdé{H+-}è"›¬d›W‡&?ÄcUã¿q9 EÚùòõH;vc$¡ qls±óáöi5#ðC=†C²v¿\†ìkް–]ïÂ~°ÀðVþjÿËô‡KÔŸ°ól[ô=7¡éVYJ„MÛù°¡!‰Me{JOxœ²2ÿšµÂv¾²qÿ`r3ŸJ‡+ ðsÊhø‡åçnØÛ¨SÚÊ„°» ñ/PàXÊXƒ2ÿžZï„x_d…³µç}y'„5ùNÿê•!þáo ÿp_„¶ö]ž´Œ¨CvFát²ÄÖ¾*c ¼åa„«@C+î±à%¶¾ÚÚw)™ŠCB¢À6 lì«Ágc_Ý`3‰Qg±4ö}eD'¶öÞŠ2öšm°¼´r,sßt=6÷•6÷yšˆ§`”“ ˆ½E58ÒgCÙð4!cÌ•Âi컲eûޟƾÛó_y‰¤±ox‡-}X›É´'cŸtÕ%öÄ4ûžÜHcŸÍiìƒÁZ\)cŸ¿%iëw6m[_n¨ØÖWóšm}WÚ{mëóÖÿ?K¿dæ›?™ï=˜øð™W¼‡¿Ï|ï“f@1ßÇÛ&E1ßã WÛøÞS/F"ß™Q þ>ò}ó½xB¾}ÛäÄ~Ú™“Èwøu2òm0[©!ßö¤uNÈ7®„K#Ÿ£ÕùŽÝÏ$‘!¤WäŽ\Ô‘O^lF>Là‹•ïúêÑ’DÈwy#WÈwm~T‰|W2–‘ox ÈÌ×¼Í|Ó>f¾ëHçW1ß}¤s¤™¯ªp:àЩÐFÌwÝéhæKÛ=¡d#@ô5"1ô‰bE|ÍP%âû(½F LX]šI|q’U{5G¤ËÄ—nF>̄ς|à»XÚÐ7Œº|éOaäû­¥®í|›¿ŸF>¼ÐZ2‹ùê[cæÃáÒ±xwâËò,îXokýfKß7úìœIæ{ö;)P*ܹ¨è Wl˜ -/Ì÷\ ¾b¾rzH[ß“~Yï褭¯õ!‚ˆì=¶õ½éem[ßé Ðiì{œD2}{nRÐØ‡XêÂ@0Œt¦K˦c•¤±ïxÓå“܇ZôR¦±o¦‘ŽÄiÙÕØWŽpiìspð2ö•©ŽÜ‡¶4†ÓÞ—ûK4ø cµ°o~3‚!OÆ2ø ‰LÏÌm+ÛûFî ûæ¶%hÉÞw{I`ì›[Îs¶÷ဥ®’Á¯T°ÁφEYû¶cñî„}h_­}±áo…|ø°<«µo·Ï^Zû¦=ÒÚ÷½È<[û¶t°”µï[ïí ò¿ž…ùæeOhûæ®íÛúÎÜp äƒÅPˆocßðöˆm}ðE]l}qòAHe;ÙU ([ߙ߻¥'¬m}#ù]È›‘ŒÄB¾H§¸ NO?‹k'nºv%hëƒkÅâÚYöJ#ß þ´e/t€•Óe¨Cœ»XN‹n›ûNû ù0J´µ¹ïr*Í4÷½zP&>Øe0I{Ÿ?$²÷Ý;dâÃMßìÇÄ÷‚OÄ\$¾ùÚ¨¿ÛiEL|o=2ñ½×üaðƒU>b">D¯•ùÆ¿ýùËjï+“í}ßrÉö=ÚûÒ:!àÃÝ”ë¡í}·÷–ÓÞ·ÛE8í}Ïþøp; j²–=Í–ö¾ÃŸ•´÷!Þ2÷]ûOsßp`°2÷ÙÃ2¬eÓùLÒ܇@".™ûFÍ}ß×t[xö{eJ„R^-~#ŸZüäH“?øÔS {Â&ËãRö¾Òˆö¾Ãç6Œ{¶ŒÙʾ…“M„e+{TFö>„N—-Oö¾iŸ¹´÷]¹`{ß㨅iï»FšmïKP“¹ïöþsšû¾ÙSû'4÷!ü‰® º 3Í}¥æ¾ï  î½·Óq÷"|‘®’¹o¤_¤Í}ˆS©z¤Z¢'Ûʲ?6÷ ?Lsßk÷6™û¾AÄes_Æ +sŸ#¦¥½oN¿,¶÷•i–¼wEÆ!¡ì}õ`Ä{ñtñíŒF÷¾z”ƒã?’x©NöÍGûü”½ÏÉì“ý”ßÙàw8šjëóJçÎÛ¾ïy°ïôq¬<Ø·ÝÉy:ØD^¼;ç×'›òt°Þâ„wç“;½>×ïû7#œ¼;‡ ­éݹ'ÚØ½óöw*Ý;w›È}-–ž¸½TÍ{8ÄáÖ½;£Œ¶ÜÅ}ò1Šû"Ä—É܇1¨EÓ.žÜM|y¦§%±ïþ?°Jn–0O&®2öµ›؇EÙhØW9µÌ}ñZ‰àÈ}(ã³€øØÍßÜW ²Ì}ˆ.g#5¡Ì±p_¥ý1÷U–*s_%è1÷ᮨ3¸¯ò#ûв n(ޝ˜û*”¹WÉ"/î«ìbæ>dëÚ|Žoó@[Ì}•~ÊØ‡jDç¾íÚ|k„}•#…Ø·]åÃirwFÜ·]e|œÊ€óä¡Br^9ãÛ”Å'ë÷aF4²I‡:ô,îCH!×CnÚ®Ãã^܇¶m$?¹›Ÿçö}$ä_!òk÷S臑¥ñ(ô«|hF?Ì,æ<æð9|Wà‡¤["Æ•Þ_¥¿2ø!Ïš¦‘_%Ö2úU†4¢_ë ɯ½>B¿Ê×eô«þŠüÚ\)òÃy–C}Õ’À¯4_å;2øáF↲ß耖¹PfŸÎyöœ æ>ôe±ôU†$c_½Èƾ‹Æ¾Ê eì«רWûð÷©?i€`ƒË‰>TgwÒ™ÉodÇ îCËÕϳR³˜ûÐ’j÷mçH·Népù̶¹/‹±¯F½±o;âÃØ‡W×Çåïq|rs¦-Twªà r^ÛcᾚDÌ}hG¾lâ¾úÚ›ûòµ5ö5…}hê]°æ ûðr¯v¾š¦Í}•‹‰Ü‡qØ­S©oôß„¦z/Œ}•ËØWÉäŒ}­õ?_ZS_å’2õÕgÆØ×Fˆ¸+®}9ÓWY•È}•›ËÜׯÀ¯’üÚ{ ð«<[¿6ˆ~íq üЖÏ–®™Ô„at-f>̰"¿öÎù5dçkƒü¶ùŠüðΙóHMÛ©cC¿6Æ~5üДJ…óÍÃw„&Œóc?¨)Œø¡-Ù ü"²m¿æÚYøµa"ðë-üðºÜüâÒô(ðCùÛ üÚÛûX‡|íë õòe^úG€7Å]2îmÁ‘€w;©g2Þãç™Æ½SÏiÛcЧ¿5Û^Æ\IãÞfßÿ4îawJž/§…'ãȸwáì|Ån9÷+=_dÜ;nǯm³™+¡]ìÂ*Flæ°'¯YB¶½sÚÆ!Óü']„¦½û\ìz׎{²ë!€ª>̲ëµÐâ;P¬Ìa×Ã+"ƒ’ø.‹ïÚi`óÝ3OÇv=øÓìKÜí} v=8 i[Y€‡ÐÞv¥°Ò¡ux¦·àÅw8eOÍ]ÞßD¾CSqø;ýºâ;,ÝUÀVª.¢8.f3ù¹¢Å•óyêLùÕÈl#ÃvÿMjTG^ ^T«ºåßµe#öæ•N·â»:*aËÞ„£ŒCÞßNI`ËlB3!–~¾Š€„£3z.B<¼W׸/”¬r$<ìRÜ áa—ö¨S|׆ý@‘ãõp¿XækÞë ˆw8Jqv¼‹»r,x³ƒ#¹°÷uÀx‡=Ï<°·qw+—î»Ë´˜õ©I já]db“ä®ÜQ›;'ÎV¨ ¢Q¹Ñ›îÊ_twá›á 2¤»÷Þ„m‰” ²ØI}úÄï.xÒô|Wìv¼»°“·÷€-ÖNF7©ðä‡xwa­î£uw1dÎ~ˆ¯©)¼»@pvÛ” ×L“Tø&Ê­›õ.DJóU/zü¦áx½9lÄÛ¨ÕH. ¼»kzÀ–ï½ÜòÔ^ÐÑROàQ\å`,Áwˆ¿œçƒï.,&ÌnÁwÖrê TxrY»‡ Ãû2wñœÒˆ·…JßÒóu —7T} ¼‹sw?Î aæ´X>¤€­‡ %[CFpš#îbûª€»ö~ îBgÙwño²åS(þœ:w% ’î"*µ\kIw¡¢ËÝ} y;Mx7ÆÁ`¤Á8×c|1S:Æ—çãòßÓx* o$=é’©ëˆêfúUêΟ›é„Ò w¯0O†»ãúi¸Ã¬­2ŠÊrø\eFe9FFnQXÌ6bA…e9êL whù–;ü>–¸,¨÷¶D–Ç ð!ËÝsäÒZ–;Hl§£å’g ÌÒ%4ÝA"6٬ÞÁ[hºkedºkõí–20ݵþí–kJ_S:Üí¾§—ÇëˆvKÍ´Ýõ«æi­\¦t¸ú1½vÐdÚ›½Lj4|=Vñß¡ßÝc3„gG»œ=:K À½³ÝñäÁ±]¨yv¶‹Îh™K¶ ÉèN›½Ã§U¸2fŠTh$wÌŸ’3®9ÓÞÇð]BÛ$Ž 3˜¹gOËÌiN#Ù.$â%™ïÚUd»E²3sÏîãÊ‚»Eb2ªåuª„Ý+¯gý}3sÏž¦.ò]Hîî¶’£Ö[$Ö`ÏCvÛn‰ü/w¦½iEv&î©"óö´"'óöT‘KW ‘Ú=Ö߃)o>Éb» ÉÝ´„äèZºdT÷Ïn»[ÊìïOÉ1­Ñ åV½=*çR†:8Q¸èn¹æ¹,q™É”7{šóIw½ é®—!Ý­éPë° ˆwK™kX«»ŸÕ[$ã^—fÍÒÁ-½‡%ަÉT ­ ñn)³¿Öª›ïº 4à?÷mz„–€,஘JØSÔû’¼êý–'˜‰wK™]ÉnªÌ1ûÌ’S {J"Z=Ò ] …wËUÏi¥\fþèßû#£øn‘”ZÌm¥ƒîó§ä|¬•빆µr™û¶V.S:¸Lé`É<~J^õXkaò]/A¾[Ê쯵²¤t8;ß-’+ãÔ¹æû¶V.3.keÉsZ+KJK~èÀ;*'¦o•¼ÖÉ’cZ'KJKJKîû§d\ÖÉ’ç´N–ÌÃ:YòîÖɶ6ëàßûöã÷û—%ŽùC'2ÞRæÖÉ’ÒÀk03ÞËsZ'—™JuSe^¥ëI ¯_uQ‡*aJrÌŸ’SézJr)]OIn¥ë)ÉPºž’X‡tP¾~ÓŒ×%d¼~o)³¿k‰ÒÁ’ßt ä-eîÛZY2.keÉsZ+KæñC«»t„·J^kewÉ}þeÕ·ü>ŸZßt¥Ãè”·Hžó‡V¤¼¥Ì»ÿÐê)Tæù¡CK¶„óEߺú×·ø ïû+¬:wL“þ¿oJ˜|MþÏ¥D•¯t͟ȱ¨k¨Öü…èÜNÅ"™ë­Rè:¶e䙘âUõz$kõXÒëÁQÁTõz$kõXÒêù“Ä(’‡ß°÷}Lƒÿú¿[r˜yeú•931Ñ}fZK™æ ¶Ëù:Ö1‚çójŒüõ·1âÅõÿúÚÈÆ·v½%½Ž*åzz)×µï§Ò@».Kz]UÊuõRYWd¸{]’,ue©¬«•ʺfhu=Î ÐêÊRYW+•uawã~{]’,ue©¬«•ú³ã qÎïšÈ½¦%=ñògõ¼Dsü(èDBך˜èï•û™˜èïÖ·&&ú­ØßILärtÉ$&úG3á_›×þhîûëÏ7å·¹ð÷·å÷:þÁS×»g!ÂâñÓæ¤ÿÁ¦Ôø—_ÿа±ßRü_þçý/°Jbc¡I¿ÛŽ•è7üËÿ”Âúïÿþ¯ç·‚Ûß^Ñÿõ5Þó;Úþë¿ ‹á>ÿ +lR>ãd÷þׯìG÷Ûó/ÿË¿bËm^׿üoÕ‘ÿ=ÿûÿ@¡o•qÿË_ýW>¸ÿp¾&¸•çûV85zþq¾¦o¦|MøËi”®ö×Íÿu¶¦cùÓÿÿüÙ|M(Úò5þ÷üëßò¯ßò5AXõ(_Ó{^Î×ô Ë×ôÉþ=ÿúo Ë|Mû?Îׄ8äxÓ‘|÷šžŒ¯müHÿtq#ÌäÇ ÞŽ‰àBÏü[+abB(œ1~!+튈±ó|ßõb Œñ±÷/dcÚã-ÁAdŒxœG1£+É_8øôÆF4âY|øö 82A‡Åðé@>õ7$Xú_Ÿä‘_6¶Ïs@²ÑÀ€ã(×ñUsØ}ìAÿ·ïªã½ÂÕÛŠãçP¤0lc¨E-a?BhñçþÚ>œ­é¿ò…Zœe ^PX Ñ8÷Uáq³íhûUîŽ'¢§}WEv¡¨™±à‘™Æ™âã»›ÈÔÊÝ;DJ8/4þȧñl¯Õl:8Œàº÷ŽÆqW!^ÞÇÚ¿a˜»‰pÁúnЯ=Îü£Ëgü<,véÁ?î_H‡K«Nú¾ñ‘=Gf¶ï¡"é+ïNEî>»‡¢¯!é7Ÿ}gŒÃ•hëzt> 1·œ¢âèÍ·Jú…¾tˆÀÇöB-aû`ýyédG¢ñÆGÿän?\1ž¹³Ï±¢Æ˜f#Ãv´/¦ W=:ŸñÏW n‚Âã{âÐBã+ÎWmh}ØY>bK~õÜ8Œ«w8;œ±¼x¸5©U.r¼ÒY)ü/´ä…0üÔ‹x€¬—±Z¾¶O9À‚‹›Ûޤrmøzc«Ëö„w ?2ÿn3›2s!%ŒTø-bm<ð†wäʆ;tø…w™v­™íÆJìŠ[:äq³Ã‹M ;níwD:ŽžÜ·E°M=:¹ß³#0meûž*;¶só‘¿û[Ý—ö7 Qrs9¶ðK€qˆ»p³QŠîÜÚ€ö_KˆG£öÐ_Ç9à:Ùê}Üa$ù:sIïg ¡åk×Òc„ÏY ¥ïM ”Û‘ˆÆý*à¢!›«¢:ÂÒ¢ÆÏ-âz… ÜÝ=÷ˆtzÓÿè<ÂsfÝô“g:÷ˆhz"üâ…;úÁ¨REßá«ï-‹çˆ£gÑAîbŸŸ˜v°À}¥ó ëùwÕ.sÄÉLJ‘:‘ãä|ãÜ[<+½Û¢ÃwæG¾qb(Xç¥âþÑ8‡ÌZß78WrEdB˜ä0ÏÉ+r ;Ä)¹•V&G†ãÉ×”XØ+f–¼x‡í”ð3ÈfŒÏˆ ;^&@ˆóq×e[ÂŽ5¬6Q!@ŒPÇSº¯ˆWk›5?0¿ 0ŠÊ0¯ß.Ÿò‹4:°Ô¦3v¬£{ÃñÀá;ëÔLjYEärÝÁ9Éi}.Œ2X"+çþ‚]/ÃQ$‘xH;X¼:Æèf ?î,}š;" ×à[%›zœnwSfì'¢ÃÇ×áî69j]1”@Köß›ñŽ Påÿ¡„F¬°Hßœ‚¢|§·‹"_¡‡UÑ AO0RÜ úkDREK¸¸bÇÖ­õÏ39…#iGèý̇søkçççœÃ_GêÀÕgïsÐÜ/ÎáßÍaÍóˆzŒ6ögòK µ|UðÆ¡oX\®—1ŠõqðÕÛ%y9‡û$Å|⨀‹søë®OwŸ¨Þ-KÔÌq%jE§¾8µ¯ÇÉ—\)í¢kç¾Ù _iÏôê{yZ3”¢,¾Ò1‰ï>à‚³­1‰ïv€€›eL·N²Ã!1&q¿Ƕő„šY¸Ì›oHLЇŽ?ÅkFæcãê¡fÄžY/§“XpIã$.ŸÒé˜ÄýÚ# ô2Ÿ1‰Çz„KÕÉY~°/Ð`o³ü5/gp<öýÒ ~è*Ä-Ž…ãÔ¹³Îà¯|ÕŽýŠé3ÃΫx䏯Í¢ŽþÇrïÀz›ìLLv>л¦ÕÕ2gÜN~HbšEÙÇXWLáЊõœÇ©)\Ÿ˜o•]ëG±=Îk×îŸp‡}ø\N–¹#Æs¯†Ë”X¥ñ¢gr ÿª _€ÜS‚â±Øû³ù›q ÷¬ð-GþÂÌ(ˆ²#&J£à=“ꈂHäÓ¤IÑeŸ0˜‘¶mÚD‚Èí ß’?ĈBø†!Í ØT ˆÀU{L@AlÈò¤@p V}ôÞ ˆí÷7f ‘ ‚˜ïñ0M‚­ˆH0Lû1›ñ*Ö<AÔ?cuj„ýŠ‘n„ËŒYA W™ŽfAdV|É“ÁH’/ƒA°ÐÛ ˆ W<ƒ úz›a¼gSâ@XêgŒ>s ‚v1BÍœq¨Àˆ”2„>a bWñd¼ñÉ6>‘8·Ïˆ”¼ÅÆ@„…à΀17BSàƒ0‰¡·)’-\‚Lˆ^5b˜˜Bì ÿ7S`#_ŠñÁìŽ(ð{d¿Š±D¸:Âe£ÑkšàE€Œ9Öð§q¥"Dwù^126®‚…€†ã-I à[Æ#$Àqpé7*|«HX$À‹üÐ’Ië `SJˆ‡ÂWÛˆZþë‘ÿžçÔ1Bƒç숻EÿµÛ'¬gkD¤ƒÕˆ™‰ Ò peJÄ ôi¢Ã/WÅÀ'FËãŒ9q'Núê œžã£#¢©‹·\ÉÁµ—°=] nèAÅ€¨øàM2™!‘5OvPØF‰m³ ÚÚˆ@ “ÉsD@ìë ž>¶q|Åsyc’/„ÿŽž‚°)%lM ¡ÔÑùíÈ›”øÆ#Ià†ìÔ‘Eòº«P£Ä?ÔÂíMãß“ÙtDèïÝá×øìà1Ä1¦nÄdslÅ€?HžÙá!ð|L3ØuZ†ð×î%á`ñ:ñTÀ_xCù`FÐ_{$¢?øG9ÒtÀßK2ŸÍÆÿAëí¶óVÐj8òTÀ¦Í–¬DjS×ì‡Øzu¨x8QÀßÃnû!ð ,ú¡’{B¿H¾K²"ùáýbÃ?Ì"‡ä‡ƒ§¡Dä‡þd_{L"¿öêˆüp"ˆÈ¯=&‘_ E_»¿?<¦“þ”¿Šâ¾vïÄ}íIŠû ‚f#q_â¾zSˆ}hú½:ö=دâÔ#ìƒd#3 ûÚ€ö¡;ß/qW!¿ ûд¦=a_«X܇ŠON„â¾vÓÅ}hJ³“¸õÌ·s$šðÉ}Fúb‰ûòNûê)ûêöûp?bƾTSÔ‡×i†–¦>†¼ìÔÉu³mR_Ý>S_¾æ¾6澺æ¾V¸¯n±¹S ¿5æ¾ÖAq_-sFº@ðþiÆ>HΛWûŸcžgrcZ>ÅYÄ>¬T±±¯=a$üûz=ľš²Ì}5¥šûÐÖ˜”ûå”W÷ᢇ£DÜ×+&÷aL¼¬XÜÉMH÷áª[ ⾈k½±LpžÔ)‚#÷MÇ5ö¡Èí aÆìÜX/±7‡«@s_ï ¹ÐG‡@þt.§`œ\ý€\™iÄ–Ol¬Ù ˆS±é˜V@|ºc)mö{ÆÔêÅì—Ÿ[°_Áá/ßi³ß„T¼f?Ø~Èœb?¦Çìì‡ùt.ìWeÄ~ȹÅM5û!½äþvöC¨Õ“Ð&ö+³¦áÓr(döƒŒZûMdhbÅd?hnúE¾ÁØž2ú1:k˜á„~1ÝoÝXõýEuÆ~…Ù¨;F»ØžÒ|‹Ì~’VA±>Y|¯Ì~‘!‘P)øÃ¿Q­Ð¿½[g$Hë臸ºoLBF?xPs‹ÁèÇ<Šq•Øo•+Vdf?”´-Šýj÷‰Ûeö›Xï”ý>vŽndTâ°$ŠýPó\,€¨yã1ràÌ´xâ?TÌqoþCÄ[‚§ù·é¢iGü7qÐìé&@H·Åð3ÿAÂhþƒË9÷9 €½ eø¢'x@\ˆ"ÜÄ0âEãGΈˆÑ×"À‰´6\> áx¯U—°ž¨0üæyæSˆ»|Òú)¬Ñc¬ÁmDÚ- Å€óqàv! ólF@ŒA¾XfÀ;fÀÖ1`ë±AÙ6ïÈ}4ŒèÉ<‘$ÄE/ã!ˆ[wÄ€<2Þ‘!áæŒÝ“ˆQ†;Nf@†0fÍdÀ6”Å€x޳3 C_³u2`¿Š X¯z0`»D ˆQñî'Â{2à„a‰¶NA`½Ÿ¦@H´˜¢3ÏÚŠÛ ÎÈV¯3ŽX*ß[çÀé.:¢­Wa‚c}­C$ÁÖ¸HpFÒ{n Ħƒcò 2Öu7Br8:HÃV¯°H’C'œ¸²lÝ1 "Þ‰S 2¡o·¶‡'Ä ¼EhDÁ6LÅ‚½ŒXǶÇ& ¶{*ìm ›„4XÓ`.£›DñàŒÝÀn Ä£¹9üŃíIÛÖ<$DpÙøÄƒ8oGžv yp"ÇsâAij×{$¬”äÁö›8Èø'NRE‰ƒXei'*qð•U4èï½aoÇÍï…`°Ö†Aôà ê Ûý5 Ö ¶÷N0Øë! ÖË*Äzç¤6Ò $Ü2 v iÁ: VÍÆÁ|˳‰ƒ©Uâ`«†8Øë!ö«ÄƒH‹>"Ƀð4‰EŸys?÷Ƀù$’«-ñ`}̓õý \~v‰€0_—B ŠÄAÿ6 9h  ¶Zƒ‘ûg§eN0ˆã]DgÁ`}èë![[‚Áœ ƒ9Ö ƒXÑpQmdV Ùƒ­Œ`°Ä0Xs‹`0ï„Q0g#³`}ÕÍ‚9i›€$XK ôÂÇÑ™X&ý“¬NI8G3»á·;^‚¤?„&::ýwêõúû> i¢)ú»µÇ˜ô—ŽÀ?T_½Â?ïRÿyË!ùÞ¯ïÂøúÅàNþC'c;ÁüWßóBÈÝöˆ:Γÿ>Ÿæ?„7‹¦’ÿr½›˜£#Þu/%Àoñ#û  ðänˆÐaxLÌy ݽ`rn`_àµé[žˆÀ—o÷ÅiÙ7:˜˜Hˆµì ißnþAóî$"Fp·þ¡b.Zqk_¦ÑX$^'¿OI€8SM¶4bê£S¨È+ €8~{Æ €˜ôc '"þ#m €ð%” /$ié@T¬å¸ð‚˜&l ‘ƒ—_] ‚qs߈ª\`Bž£Àˆ"Ƕ€È§,râ`m0À¼ë €ˆùʦ €¹!’XŠs $æ=Mle€'üòÙA –qTÝXõÏ7uÀ)I€è("Àv‘°]$l‰¯MŸ©$Àk7x›2r %"ŽüKE€ðn }ÄxN/M€ˆ¤,‡Nà9lM2"DˆêæKœØê"“õ+ÇP`A¾ ðtJ2`N €x-EfmÂKÌÕXà®-›Àó°™"Ы±ÀVFXý5¶Ö€øóÁs"O, €p-kœ°êV €ø :À!0™ €ÕA`Ý `ä—r2«¿Œ¥)`Ý `é`¬»cD{n&V €±~ï¶@tÐöB`¬,»#h¯GØÊkÏK›yÀºHX#þB™öÈ#Y™Ä]"þ«íñâU^¢=ò_©iþC„rr®ùï+srÉü×ʈÿJó_]e¬î˜kx™kšk|™ë¡›kp ÛEbÀH<ÆŠÅ€­ƒbÀ_fÀ”†ÀRÂXª«ƒÆÀƒÆÀqÆÀÖ–0°µ% ,E…­qcàfãIb ŸzaàfÜ(1sx °ÕBl•sã3!U¯ ð¸EÕ ­bA`nŒ%æ‚2!ÑÌiŸ2"eö³S3 ²½²ƒfÀ|ÀÉ€yÿÈ€9ü’ó$ž /˜ˆ£-´åÏõê® ­bc`¾y‰Õ”1òßnìõ³;¦ÀºŸ¦À|Ü‚ÀVBˆÃo·Â$bÎÂ{ž¹†ÀD„ÀRJXÛXÏÀ˜/bb`êd ¬Çd¬›eܧ¶æÿÙž’ #¹éXÎzÿ1™p²:'"QKXÅ„L0{ƒâ´åÞÏ2u”±7(fRb¸ƒ:ó—î ‡ÌñéŠõŠvlÜÑŒÝAñùŒÕmºƒâû-éše슕úÓBÂu—‘°7V„M"$L­L„¸ ´ó‹q§ÈÂ&B’º:2»yøh Qä '!³ºw le„c×1<ñ`ýB@ÏOÑ`• F«A<$ ¶fƒM"¬« ƒUÆ4Ø$¢Áv•h°• 6‰p°]%leăM"„„o°yN9æÁ’˜»„@X5»„@X=4ö2ÂæÁ.ìm»„8Ø["6‰p°K»€8Gn9û»„8Ø%ÄÁ.!ÖM6v q°)!ìeˆƒãÚR 6a° È‚M(Ø* v Q³š\°„‚‹$P°ÕKl‚Áö›Xa *µÙØ%ÄÀ.!v 1p s\H‰˜ù‚{R`—k.7v 1°Iâ›Ñ~1oh@ !‘­UØ%ÄÀ.!¢fw„ÈOØË!‘;µ0°©) la`—»$0ÏN–%a $—ƒåv 1°Kˆõ`DMØ~“›€X`+`+Aþkêˆÿº„ü×%ä¿.!ÿ-’à¿.!ÿA"sø¯— þkEÄ7üz…r@DzÚ¯n„äÒù< $ò2¢f#a`ÉË™û¶Ó«°õXØ%À&6µ€­-`—!Ѧœ°õGØÛ".’÷/}`‰ÿš€ø×›&þ5‰ð¯5-üëeˆ­iá_S\ø×Ëÿzâ_¯™ø×%ĿޟÀ¿. þåBÅôׄ?ö—¼EúCPOûˆÿªiá_5dü«eü[$/çoëmüëâ_Ý ã_“ÿZw„]Büëò_—ÿZëâ¿ýWÐ_¿€ô×n„ð¯7Cük7Bø×ÊÿZÍ¿.!þu ñ¯Kˆ½fò_oü×Ëö"@Z` ›DØ%À.!¶¦€]@lwPØËÛö2$À^†ˆéÝùƒ´OEzßd¹ÍÅ÷shÊ÷óÖʯ¬·ì ¶þáŒNz°þÍÙI¯Žì˜ô`0‚–½caÒ+ëlÿÒhjÒC¤Ô}tã3ÌÄU"=`}øLzM•ôHz̆˜"=:gS&=æp‰2"½ÌbnЋæG·ý!å7×@fÛ”DN¤ÇÄ5ýàßž)[2 2 tÒÛ‘l-nx€AvÅ8þ R—½ýÜߎ¤3aÿvü—ÌA‘ñ_’uös;²+<Ý÷s4/Œ£ø/™!ã¿”Äñ_0 Žîý¹#ÉDt0ã¿ PpÆA vtüäNˆ“ñ_"÷Gœásü—-B-¶ð/È2@Žsø—Ìg‘á_Pq¼/þ%Bë:ü b¾ËÔ§ð/`*º½8üK${ o)þ ãÂê}G"qü—}S²x‡Ùæ­\:ÿ²!•o7ý¡š_zQà鎟Ñ7ZûeCü%ö Ê\ ôv$«!W)ôKuÅ¡_ª%‡~A‹ ÈîÐ/‘HÞ¢ ý‚àŠ—$Œý‚^ɧS±_Ð?úd9öKÞÇ~A‘w‰ý²oÝç38–È/;ŽvÿJÌ‹¢Óƒ üR)&øeßN€tà$~ 1Å_ê>8ð ‚ËrÈÀ/è>¦ü‚Ï8GŒ¿ qµqà—ßÅB½P®iü²ï2ygà•;:êE=óÂÀ/xŽž¢ ü‚Ô#Ýåó+"“|Æ}ÙwÅeʸ/hœö¼-ª˜ ¼¢¨/hEyõ=!Ÿ)è îæ±}A ½n틞q°:æ "2Û”1_ÐÖ«˜/È9¢³„ŠùãZy'óåN¢¦˜/(#’RÌHœ,.‚¾ baŸ‚¾`±¥ ú£Y‚¾ØkS_öˆb÷«/ 0ÜKfLq´—֪½T÷òG§ÌQ¸(è$¯ ÷‚ÈÕ.™16ë/‹›çw+@Ýá^PS’0Ü ®¢ÎŽ÷•fwóܱäThÅ{©;¥x/Hr!gLÅ{É1äp/Ðjï§þ¢7|sïeÇÖ Ïø)ÞKLQd1Æ{ùÞ›ïe?ßñ^öÓS¶ã½@ŽÇ{AZFñ^êV8ÞË÷6èt¼—=¿þ*Èû$ú¨d¼—ê²ã½ ž§Ÿûk}v¼$QÜÆ{iÕ(Þ ú÷óPæW1^è}vßWÀ_ G{A%£û‹†ž%Ü Â¢¯á^Z…{Á½éŽžñ1¡W§‚½ –³ø¾·æ~{ÉÇ›Á^pcNJì·œ'³ì--ŒJ Åìz ìe‡Q?öe:â…’W·ðÕíËp/è¼Nî½!ƒ:ÜK|Véž©p/ˆ*?º…/ÊLëî O—cÑOœ9Ü 2ÇÜî#m.á^v>¯‚¼Fîy»£g4$gK…{ACƒV?…{Áý›ýÜ_¨Àr÷ÉE«ŸÂ½ ž­C^ úÒ:Þ W0Å{A™Ñ\=wD9åGÇ{i+ÞKÝÇ{ÁUd`Ç{ÁÍà³r¼¨Õ­|QÍÙÏýEÿÈ«œñ^P†Ýq¼4ÎÇé€/¸j§)Ð’á†D3_f*¸»#¸Å? ï¹û0NÂ’í‡ÉŠWñZlÅûnCmTLYˆÒˆ·û Hñò¿mÄKmxÞ—I^îˤ o·55Mx¾(-x)ßGš xYIðJbâùÆÓJÞfîLÞ&XMÞfßbðr7 x›OH¤o³ósZð68?w—NX^y,,-x%ØÝN°-°k]“ì áñ¤´â!ð(IOF¼M3LÚð¶Ã‘clÃKIÚð6H^IlÃÛ|¾%mx%± yþÎŽuMbâzM:yʆWÛðò&Þü´á(f÷é„DBÛðÔáí\éÆbÃËšÓ†×ÊȆ×$²áµ«dÄËþ¤¯õGV¼ÖYñZYñJb+^“Њ×¤;L ·Èt×%¤;H|t×%²â!žÁ¾Xñpšýé§úºDV¼&‘¯öímÆkÙñjÿ߆<‘Ò’W[òšD–¼&‘%¯KhÉkMÉ”×$´åµ¶‰xÍbak^é`k^“Èš×$²æ5‰¬yÕ–­yMBÄë­ñºDæ¼RÂæ¼&‘9¯$—Œ’ò0ƒèx™(¯Kˆy]BÌë™óJ›óº„æ¼&‘9¯IzMM^“ô yŽz]Bs^Uls^“ôzŽ.!ëõŠÉz]¸×ä½.!ï5‰x¯KÈ{]BÞëò^—÷º„¼×%ä=Hn'0 Þëò^¿Š¼×%Á{M`«¢G=ݪ×%¾.!ðu ¯u‡À×¾EÀ×%¾.!ðu ¯I|]Bàë_—øº„À×%¾.!ð-_ø ÑÁs_—øÚUb¾VFÌ×ËùºD Uš„Ì×%dˆ.!óõ¶}½ ©¯K‚úº€Ô‡9„'M}]Bꃄ§L}]Bê«îˆúº€Ô×%¤¾EØ×%ľ겱¯Kˆ}í*a_—ûº„Ø×%ľ.!öu ±¯K>ì[~öu ±¯Kˆ}]Bìka_—ûº„Ø×%ľ.!öu ±o‘¼žË-!öuI`_ûjÙkì«¥±±¯Kˆ}]Bìk5ûº€Ø‰ ûzb_—ûúUľ^FH²LKuÀŠ…ÞGz’ ÁT0mpÓ@ÿ×S;õU¾JüÑ5ÿ<Ô§{,®Xkþjé—,«t,)ié—Î9ø`=þÕ둬ÕcI«ç:Í*ÆŸ­†Ôåüù?<Ô‰|¾/Ôóf¢ÿ‰ƒX{&àù;*Ôûdÿ‰T9O¦YÇÅWˆs’ãüw®ÏQº¶%wÒõ=¹“ë¨R®gI¥ºZr'ÕÕ“;¹®*庖DQ®«’;¹®–Ü)ëÊRYWOåº*¹“ëjɲ®,•uõDQ®«’;¹®–Ü)ëÊRY×"ÔøøÖÿžêþG) <œ²àßIõ÷ÊýLõwë[S@ýVì豈úƒ¿¦6[S@ý£ÙﯿÍe4ßýõ·7åçü÷ûÛò{>;–P>sÓ^™—þI6¨?ŸVjÍõŸË×tLñý'ùšžÌ×´¤QjVÖ#§i:÷þçÿÛŒMÿö›öüKùœÆüƒÜMŸð¿æ_ÌÝôlÇtî¦Oø[î¦Oöïù×ûYæn:þq’‚.ÏØiÕ ƒ]ÖûPôêãEÒ’_|X%á}O7Š:}n[ì¾ØS‹Iõ[O`«ðWìwÈž"¶‡aö¤mä ’ƒÛý,rFÖÓý@€¸#$6 ¹fXˆO¸yÀ–ˆI .E¦£Ía’üÚ>ÆÎÇs›WرֻØtØQÏCÃìÙÉ>‘D€$:’Iò óiäzhá;eÇ‹œE¼aº(‰–°¿+çÈËj CKBòM¦tÿ@’µ·øy)÷Ï1þÂ:núdÄý‰»"oöóXë£ä?÷ -ô«TÉGŽeÞðAø8`x"áÖ5[ޝGãs\}@2Â'¡ÒlÄy²ó:é’©ÎÈ…¶Oúnœñ˜CòÐz^CÉ+!ú‡D‘7bÐàD ¢H1äçt"mGdŽø^—ðc8‘#2GÌSjFª‚º¸k÷äÝãÛsJüsÞ4Ô°#âù¿¬ä¢ Ÿ$îl¤¸O_•ÜSÝ¿º€ÜÈß÷îžtAF>jL^‘6â‘gщ½ýH¢d§r p’@îKâNº_æ ásŠôq;oÚ5ÏqÑ äFè–¹é‚äļŸc(óÏ=ùŽG‰nù›|S43ÿ`[Œm¿Êüó(ÍÊù„ P$ ˆ´Ȥ: ̤˜Ln÷ è‚Å8$y>gx‚à±PoÌã‘5âÞôæbµY#`WdKC™`‘foeþ­$ôF\ðHq+ôë‰ðš»´âUˆ™Rœ¤>¤'?8û™R«ˆ_z¾Lq"¦oô‡³,‚PDêŸÓŸÏ\”¾Åƒá˨bzœñ¤é³÷}+[Ë9_º‚àÙñÍŒoZèé©å¤ ÐóÖxåþÁ}»(Qî*ùžtÁå€Kè}õ[üÞtÁ»Ëaü%þ¹7ZýÏpúìÝTÞŸKÞ'ÜFßþ]ø8Çìí÷ûÂÇ9fïøAp(íϸèÏõI˜ögÈÕñÚN¥ýZ^ð÷¼b„>ô¹¶›n èM8\ò¸ŒýïÓ©¼?ØšÜC2•÷çVxÖ u‘»íRîkßè ‚)/žË…¯s$os⸠_gLàøØÅþú…¯sLàã¡ýþ’;GH¨ìëìÎ~Ój” %þñs¸öG‰¾‹wJfÌÊ_™‹3⵿Jüs+X÷7ë3ñÏ}Óö:v%þrhºðyŽ |œôý¹ðyæ¾sì_ø>šÝbì_Ç¥Ü?ùlŽ[¹Róc±éæxè ‚þÅ‹w“¾ x‡vöø¥/JXk®sSêŸ[¨/$ª|¥g¬1bçãkùàÛ{áãsxjyžJý3XàRÞŸ1¹ôºÇòÔS‰mÎëÊû3&¿Î×ùÐ$?½ß“Ž øXðÆ|ï!Ô¯/äumÊûsË'òÂò)&ð[!ê?‰ÿ¤Fø<Ç Ë ßæo Ÿ>>Íû¬ÿÿºs7ò²Ê¡”?°f†àQÆO"×5é‚ÕÑËž½Ìø›Pt믘»¯IŸÊ «Œ˜»S¬æèÃùÇbîöGö§Ùs7ßÊÈ;GÙÎ2|ÓBë˜ ]¹Þø¬ù¹8wcéÄ2øÝ}޸߃s·¿×ÌÆ1w7<¾F ˆZˆ“â@+ŠS'ŸëéñŠpHÑ87”Œ‚¨'r‰‚5e›IÝ“1l¸9`ÄæÖ…P°”Q𸼠eÄCØX±X°”Yõp~4 ¼ú?”ÁÉ8ˆ“™V8ø ÊÒÝpK ¦xM[`f 1NpÀ¹Ú7en7âÓFR±)p;yMƒ)FœNS ì‡\VÛ¸]Þܶ-0—Õ6âðµðP¦@ Áè0˜ç¼m Ä¢ÿì,‡%·Î‚±8»e¤%0üèK Ö“\yÙ˜§íl ÄŠî".ʺ!áï: ÆŠýaÅ‚ÁZÒ±&fñ5]Xpÿ rAÁœø±Ä[I0Y&Á}jt' ÖjD$ˆ^rcÄ7šÅ(ˆo±QŸ3Þ¾DÁW‡é’á ¸Ë6HD=²(ŠñÞð›ó³,ˆuíYfÁb ³ î‘Ì,E©—X0çädÁªÆ,˜ßödA¬ ¸aaÌO\ò –…âAL3²ý‰q¿Þ•o˜±„‘qR<ˆzh@0†ÁbÌOXò`uÇ<ˆ;¸±ŒxedVLô²Þ@XO"ðHŠ˃1â[N3¨w”wÝD˜ê$Â\È&âK(Úâæð®›ëY™ëeL"ôº'‰õpn0âApê2ÜøøL„^ª%æê7‰JÈ("Ì%i!f"lpG"„V|‡M„XDóž¾ÜøO"¬·ÚDX£ÔDˆ¡Ã™3‰‹rÒžˆ0W©I„¹:K"¬&ʉqßn"BÔsv›`=¾"ÂÁ£¢I„¸§„©$ÂCF¬"ÂïfÿmfM D–1ÂÆÏ2Bž;ê@xÜ\–æxO ăý„ö1fÿ’íO’<˜‹æâA½ŒÅƒø8ÿZpPÔÝ„ÁýÕò;a®^¿4Ù' ꙿ2¿ã ëM½(䙗΂ÙßdÁ$ý„A¯î ¿o¬Ç0È' fgŒ‚yïý“=à æ}IôCJÌ»›$˜½MÌQ•$èÏO‘`NaI‚9¬ ÝÁDÁlË(è•A¡ °°£`v9Q07"¿2´Ö& ziüOR8þá>Ý\A‘?{vWPì?3Æñ3žLk¿‡ „Ä¿Oœ´'üûxçÓÍ/þè¾ /¶.øÝ¾È6vuÄálžŽ7â(ö{tsàŸ—–¼&À ŒV¸O-”…€Û¡í—DÀíÓE" >Ü©5n§ÍYFÀ rXF¸]—V×B@œ#݉·ðþÕp»Y…ðcy‹ÚxÛ-1m÷Ô~yÚÇõÃtçO[àІ\³*ŠSàö(öP³¦å϶ÀçÔº&mr/HD‘•¶mµÂiêWã?,&)Mü—Ù’ÿp‡–ùo{ü,͸êXø/ÃÁ%ÿAµ£ùo›é1*þCÍ´"‹ÿ6$}%L‰ÿPä^l¨†wÝü‡¦¸aþÎĶxƒ¢f.ýÅX&ÑcþCÅ/›ÿeœ¹ä¿Ö”øM‘ÉÌhJ&9ñ꡵Êü‡2öÿ$ÿáå¢UNø‡‹ÎÿP„ìdü«[jüË(qÄ?ôNΞÂ?TK;¨ñ}y ÿPæXðzS ú+%M(2ă¤?°ùxM8âJÑž¯(Rô‡(Û£èWÅ!ƒ¡¿&¦¿XÒD5ÚL¨x_B«Ë¦¿ë¢?8%™þò=3ü¡¥±À_©iøÃí:øC™¹˜ë2ü•O€á¯j6üU S1á¯î…ᯕ!üÕ]7ü•7„á¯5üÕD`øË¡cø«bøÛù¦%ü•ž†?HX±á¯zløkÁ_M†?H„v„?Œdn˜þªÇ‚¿¬7á/Ÿ^ÂêeÁ¢6Â_Î 9 $üåûšð‡2² þZ=‚¿œîþrvKøË6á¯Z7üå­HøCÍÏâ -‘†?oÿšýªm³_ΣÉ~9#&ûaâºöÃtw-ì WÊ‚¿œÌþP„MþÚE‚¿ôšIøC˜áeöþJ Ó_kKø U7þµ¶„9‹'þÕÍ0þUÿrROük•ÿª!ã_)nþkW‰ÿšDü×$â¿Àz2ÀRÜXý1Öè2Ö¸6]$¬áe„„ˆm¬qaleˆ€U±0?¸I¥¹)°ª1æè7–@ XJ™ën™[½bÀVF XJ™k˜ëÉkŒ[q`=*s` 8s`«G XÃË ˆ«Æâ ‰:(¬×Ü X5«a—/è¦i<Ë«f`Ul¬WØ ˆ˜À‚E ʰˆ8°Õ+DožwþÓ)œ’ ²¦1!bÇ1h™pÜÎên&|Žb02!Ö+Lbf&|¾‹<;‰„ˆº’HˆìáLø•¢‰ìû”[©Dß™Ô(ÑL ÚD©B:ˆÞðç¦D¢ˆæN®%ÎQÇãwrÍ̘&ˆ€¶u£ r2Ѷ‰‰¶aIDˆeÏ+Ö "D2O5M"¬œ`&ÂJ‰k(¬¬p†B´ÍôÀ†ÂJ}f(DæU¦‚7VBC!ßË+(Äùχ›ú‚ÂæO+(DbÓƒ‹}Aá„r£DÎYæ7"FÍÝDcqG'=Aá§òš Ñ?îR˜ ±Þòã$Îû°—°¨pâØÇÓ©pÞßèPͤBÈÑæ†¨:0øž©p>»·;D…óvâkQ!Òk·S!nûàx¢ñCçÿe†uŽcS!Ê0ž©°ÒäŠ {R!Šœ">Ra/C*DSzaE…“ߪ‚Bd Ö-Î{z Qæß {RaEr0F A2•¨ƒ‰IñL…xèCç£lt*ÄÛ9d³$B½3¢B”a,HS!žæ}u£àÄ-’„Xn™÷ˆ…(ÛÆB”aã¢B99LD…óš i*œ÷i—xQ!Ê0gŸ¨°m¥‰ ñ>0‘©7Tç¢ÂÌam(D,(9d ÑÒÅÑF(l  °=pQa»ë¢Â¦”¨JÉM]Tˆ«%B!Šì¬FPت¢Ì³øˆ"Ï5“ {B!ÊLá&¡]fØDA!nŹu(¬‘.&lÓ˜EÆÛ™e˜øÔPˆ¡4tPXµ …¸JSŽ °—!ΘO»Eß/Mì‚B蹫-Ba%ж[!(¬´à¦Â*c*¬¯©]fÖUcaMÚÂBTs sš KqSao‰TËF7 ÖÜo*Ä,>Õ6©°^S!êá! Sa/C*¬¯©°õPTX_4aa}fŒ…5O k"5ö«ˆ…½ ±°ÝAb!îñóv,ìEˆ…í kP Qæ +]¼±°’à kx +ñ»±wÃBTØn²¨0BÆêX ©°U*DŒ>e*DË›lw¤Â^ ©°i *¬—ÜTˆ«˜åÚTXó›©°~Q!&æé4¶».*¬ÙTXŸ`S!nó ‹ ¡7Óü𠛢BTÃe©°¾”¦Â^©°½ž¤ÂV¨°¾¦Âö¨D…íÝ¢©·{‰¢»ÆÂú@ ñ@¯«››ÂBÜäãí~¢Maa{¯„…­ƒÄÂ^„XXÓ¶±°>°ÆÂ6â„…¨çÕáDba/C,Äz‰f'ca»ƒÂÂ6â„…íö ÛT ,lÃ@XØn!±°MLÂÂö$„…½baSB\ˆ2C²å¦þ ±S…‡™-þðoÊÌh‹ Q§3¨ãug`d à~¾Aó(@†A(â©£€ôVŒŽ~qŽdëÖÀý„§=íz ?¢n üÖ§1SÖÀóññ'[¯©CJ6~Ÿ$º¢Êˆ%𽸃âÕa<ÙÇîsb¶"ྸƒbÀë*ÙÙälGãPð¾D†© 6œï§DöÀ<ÕšöÀHèJ¬“=0OŸ¦=‰,yŒÎöÀ|Nˆ“=pL—±=¡bŸÅ«WÖ,{`Äøíè÷õù•“ìq2Yìb–ÿ*ôÛ‘Hy.öÀ©Å 93ƒà€…¦£ß×¶ëlDìX.mDÐ#…~‘Ap¼›ÊÈ ˆ)C(*ƒ`ë ‚c\>½Hƒ ‚Òê´ ‚8Ë] ŸÍŽu6"Žîèè÷5¥ iDˆ{!$ ‚ÏþÓ!añÇâúlöU´Apà¤:›’AšËUAè%tØ µ¶å€ ê¹:û}m¥©,‚cØ+ÓÁˆÁ¿8„b‚Y ‚ ëà 8e0Iƒ ¼øl8"M‰ ‚ãÝëÙÙ"ˆQñÊû“Á‹?(G¶-‚Ðéîìm‰ôdœ¨mÄc¸ƒàx•IÁŒ˜AN>–1ã½4úmŒ‹ƒà?SÑ ‚6×_‰~ñœÆbÄgŽ&VÇkoU¢yvôÛqXàY ‚¢÷â ­ær>7`a?†zæ=kðÛ ˆ¶øÙ ÍÇ!wiöóx œðlDSr•Aj-Πõ¨lÌj{`)e{ ŠÌŽ~1ÐWgP¬ÞÅ‘„&{à€;%²b°óAØXZɈ"{G¿˜ÅÏÅ n6Û ˆ{<–1H‡±-Á1o‘“EÃB'ödŒÕ/’EZÉÕSA¼ ²íÉ"ˆ¹ÿ\ÜA‘®ƒñ4Ù´ìñZód„RÏâ ¥V{ ”zåJ{`>‡´b" ÙŽö@<ßÎ}_Cvг9©,;öE_Ô;YQä\>ÈíAˆ¢5:ò€­Ïþ8 ‹¬˜.Ùi ŒÍõŽ}í±Øˆ¦x#l Œd'‹5ðáBݦ@L ä_›#À:ËȘ#?M9†Óˆ¦QÞ†šÅÒXߦÀjȦ@tæ^ŽâðvÚˆ†dæ“)ðùeBE™qg®ÅŠ &K Š,l Ìñ`C æT™e|Ž]Å2¢È¹DˆÁçYõʈzÏ%H̳ÛËІÀœèÒˆ¦î†|q˯ň¹ŸwˆÀê± ¨F§e¬Õ–@ÔCßn›1ʨ'S î1#ÝØˆ¶ÄŽ2¢Ì%&2½²u™ŸÃçm ¬þȈîùÚ]¶)/Œ8L¦@Hîň,>ÛâŠÁDµ)Ãt_L¦sñ ų!ʘ_À´Bs¤!0W3iă )퀸Å2ʈ‘³wà‹†8øm„–«ChM rsà¯%ÇSq ±£ƒž¼AËΧÓ- Úì°,YŽƒeÂ-E‚Á“¿;ì Üü³Ÿýƒd {\ô7ìU>)Ã$ŽC؃äRdÂ^/CÚƒd¹÷¥éZ\?ëV÷ ‘•Q¸‡×Âï§å»Ž¿žø ëÑæl[z Ÿz·ûO³4]-ÝÓuýiMÿñßþ|<¸·û_Ï÷t-´ùu¾§§g¾§§ÿ:ßÓû÷Lò´Ÿþßù÷¿šïimj&oúúß?–åéú?Ÿåéío| Œ¼;w-¿±Á™Ù#^Ù~cð%Þù.rñMó•ð á[]|€»_Ò ¬„e6¼Ëîk‹„0jЧú¾h¼ KC|cº‘é@ìï[ŸÞ’ø@ˆ ]³ßéÖ ¤å=XËß‘`—Oïë‰ïƒíé ¾ýîPãû`ƒÁÅjz| l8²ñ~^I|!làá𛸯_qª„Žö÷½Å† a¸ï=¾â*ñ¾o†÷Ƹ‘Š>¤øßpnäö€)>‘p¼‚müäzG’„þ[GÈ®ƒ-5@j#Þ†»ÇÂ6†¾†ßÈŠƒØ‡Ñ冃\Hñ¥;>^Ýø=¢3[8ÜÏ΃uêå†× \H7¿Ÿ“çâcFhù\<°ëÌà[W4Bçphž‡çÛ/¾ßðÍ€)>¨EïàjÿQ•9Ùtç1€]GÊî0hßG‚.¹76RðÅ'ˆ0˜Ý0€ÀtjÐŽÇNÅܘPðkOÀ’N;w»y ñ•Tæá),¬Ë4ž€Y‰w»ñìT©ux«¡[enDу޿÷§0ÿÜw£8ÜGa»S™ƒ§`ÿøQê76EWÕ~À{ ÃðïQqãÜëOÄöêˆO¸³©ÆS¡¼òà>ºßr¡%<0G°8€œm¼—cã1X$ãLÇ»bðÀl|0˜ šº$9y ÀÊ\<0›7ϼWÑÝöÏ ý~#Ú=ÜGƒ£w–óÀ¿Ñy `N­1x ิ$=ÛÆS°°…µñA„üfcóΞ8°¤Ü!9y ¡[6–¹x  ¦èû4ò²ZÇêòlÏ‘g¹B…/»™ŽS/g¹„¦„ïhjùlƒgjоðË3"ûE™}çDŸ9)9x ¦Éƒ0ûãIöÛÃN5¹¸<´ßQ˜f£7ûÃ3Gš,„‡„ë(¾ÄžòA¨G¸ŽÂ8z³ƒ=ÎXÛƒg/­'¢ê5{Ìžˆv»‹ƒC³D†Å!€z†žãâ!€Ù¡ôäÁ”‰ÿúÈ>Gã!€#Íâ@ÍÚWÂC5#d<ýY|Î-̋·Ç*ê=žÀ»XyŸó䀽ɉý9¯“ ø#Wàwå倩ùùÄ€9GÏÆ3S)¼ ·µ©Î3°7«ÃƒgfÅH^xRÍ#Þ(æZ†ô:x¼c!x®“gæ _<ß1לçºyá›W=<0Çëj<+éó¾¢ãh|Hðz~—ðgÜ0S>x=¿Kx}ðv~Wð†`’ì<05ºž˜}‹DŠ»?Tp©½—Ç©Z_Ú$¿iË£ˆd)ý²æn<0—…È ¿ÛBûÜ‘½EX ^Î{··Çƒ·óÁ¦é@þ¾Véÿàg|Vá »,àÏsÑÿÑ帘ÀƒõYªyèÿoM5úÿÏzýYÊôž ¸;¼ ·ÃÞ­ù¥ÃæHx(,mÁ+øT _N)>íâ€ÙçF7\\EóúÓ˜Pkq\¦0°„Ã!ˆ«|£?9º¼qQÝíã½ñ忳ô~?¼)¼£Ýqù=†½tœuÂŽkYË}䮡èÝÿëMúàœ0Öðù@÷F÷ë_8Àá"Ô{7NtÿŸÝÿçã5> \XñŠÞO¿çxEÇ^M è0·zï âà^ÏžK¸&àxUÀ^û«±¸b /Åß×—ðÙ6ƒÏšÛ†lÃthÈ;úцW4VðÚý5¼¢÷Ë‹\'ðÌüóRHxÈ̶ÛlÞ¼³xãžó¦Ep¤Û`žÎm8™ðÜKÛ#NÓÏ)Ð|¦®Ô–"Ø“øóÑðŠÞšÝM~Áyì©jxE¾™ªïdUó_ÍøT fzk0T¨ ‚°´ó€Z‚`\¸È}Á™?"ÁXé2Ýöá*’$ø€íÉC"AXÚµá$ ¾oQ~¿JÄA±fqÍK §{A(AðA.î ‚på°@@O^ñ·@‹=O ›@q¶Ã“ A°!ÁiA ˆ•î AœoÓ‰‹0‚ ‘ÍâMS XÑ÷Á“ôØ)Dòa¢K‚`S¤€ÁÚvMÜéÏZ x#:)O XçŠ%w_HÐ$$A¬PÐ$Áó}Ân¥HžF*#¬Sw…‚øòNnNÄë9üx‰‚Á $C¡`yNp¤â½L„A–#œ(ø ›*DEá"Q‘ ¹Ù(ÄR­šÅ‚ïlãÙªbÁ±çÜ Â+ uYpÀÛJ²àˆrŽŠ{Ë/'bÁŒJœbÁ¸ÖdL¢ààD8æp¦  œ"ÄÀoK;¡Š8`Òå—a $Ç‚x<Ä]aà8öƒ¸F Äàu1p9i;Ž'£N&ÜÌ‹ðHÄàÝ['Žã”çW‚àÌ 8º«ÏG¢Y„ ˆž³©Ax]ðÈ}‚ †œ [‚ ¼7øù%A5Ó‘O$ˆ¦öá"A¨{¦$Hp`­ãW(8ΑØ"ãR8“DÁÐPGDèLé)8#K´ ÂP ­£PÐú#|ß ¹A ΠœÉ‚#¬é¬9Xû~œJXM¸m ¢Ëô/JÜ·éMgR¼DALS¾+Ñ?mÕ„‚Ø`p‰L„;ë~)‰‚£çž(ˆíÍ6Ç:ªœ(ˆÍŒ‰(ˆÆµý —VC*ܱ™¡bAÄ0^‹¡h"%Y0ým’`d¹XäEALÑÄI² æž3±à\ì1ñHŒp¯4²àÀbL* ξ _…1Q.Î|m& bÑ·¡  žX0î÷Åþ‘1!ùIU,i;é‹0ˆþñí–0¸ÃýŠM w¬`Ä:²à8ˆÆjÈ‚clù•‹,¸oÈCY󈓢¥sÐÅ‚(#v FpÜÆÞ …ÛtÐ6Y0fçˆXÃ¥ïbÁW+å÷J|kVâdA÷ðîûm²`Œ:ßbA»ŸdÁˆ0Ì…_0üÍ"„Áx|¹h cù" ¾J)%IÂ` )/" † ÑŠ,EnÒ!Yð½åŠÙ˜0ø–QΧ„ÁõX4“£;7%¤Á˜:á’/Ät+ö ŒnîFÒ &2C$ ¾c¡óÖIƒÖ¸h0VÁ_ÐàLΚ4hZ‰çsŸ4ÃyÒ`ÝÎrØNæõþŸ¦]Á?&â»ö²i|çeßÜ.N⺗8ØŽ3ýHƒfJ» ü!¹_ Ú>_4ˆpnŒi"Äæ/µÄA<‚Sñ Þ¨mcSäAl;ù0yp ÆÔÍ2äÁØ7 Î8áɃq6Æí‚èú$Æíнé|Vâà{;8qp®O‰ƒ;¶ºêfÜè|jgÆÝäÁÑ;yp†”MŒXâ¤ñ`„ $“wlPy‘xð}Å*ÆlòàŒ1›@iyeÓ»7º)¹•G ¯z2n´¾Ð$¾Ï©îxxIƒ;>Ãþ6.áGá!ijòn& ZS¢A4E¼IÄU|ð’çL îXùØ' âhÐAD Z=¢ÁJ_4ˆÑÙD6x.Iƒs.‰ëî% â^Ñ*™0ˆ ¤/± FýpÃ`Lu~$JÄÍãã+œCœ0ˆj¸â$ B§&;à¦U\/í‚ÁJ™Z0ˆšé$’4¸·- M4ˆYK0ˆ‹„~‚A¹y‘`÷Q"ÜyÓ`p”LQ08ç@Â`èp“M ƒ±AØÉ”‚Ášƒ³; ƒ³qÁ`í! 1ê± /Ì›W,Å/ÚÅ‚5Û¦×{ÎÈ?IúTˆC9çåˆÔR}!@lfhlI¬¼ÀE€X׸ÃMø™Å+ĨøtÏÐÈæÎ¯áÉÈZ¯L«ÛP XÏF1`eq,<.7FC4š$ÖÃ]X™¬ ñptâ§ðÀ—GñžÆ"ÒÉoÑ]n‰‘Œûp¿Ð™Ë°ðàŽÐ ËæÆÀù8ÖÃQˆ¿qõb ¸£Lœ·!·A>¨@ŒÎ0¿ÐWP†> $¼¿ €è €P”EiAÿA÷ }·6Îɸy‹-p>òŨw_øï¸ÒPü‡še€ÿÕíLüÃE±Mø‡"‹[¨Ý‡Ä?(ΡHüÃ#./OáÊŒ2Î4¾…È:Ë™_ø7ž‹102Žs¯üwÜzÿa™•§øïxNšžÿަ@r…X\¨Sâßñ0\iÑ–Y"E¨†S+éÉIú‹YHàýAB{aÒßÑÒ8“ôw<=¡Løge„(ó8þañÛ ÿ°= ÿ=í]ÉsÉLþ;xÚø¯ÞŲÒÜÄ€¸'%¤A«G4hÓM4èâ KˆƒóNt qÐ%ÄA—½?/Î51qÐ%ÄA»D88WíÄÁ¹Ö'zâ Kȃ~yp¾W’½ p‘ ®ãSB tI¡5. t Ð.zá|Ñ$z™B/B ô"B/C t Я"šD@hW m„vG„~Ð%B—½õB/B t Ð%B뎀ÐÊ]B ´ÆE„^†DèeH„މЯ"z¡— "t‰Ð$"Bk\DèeH„Ö”ˆÐËz¡!º„HèW ]B$t ‘pJ ]B&œ2¡—!º„LèB¡K‚ §É…s‹”`è ]B04‰ÈкL2ô"$C— ]B2ôjH†^†d8Ëü$ÕÓ$ÀqÌX¦‹ÌÂXø —Í @OaÂÖi<•Ó(^ñ*’® È̦‰€8À È<å z¤y3]Aw}¦›® ˆMc\º‚æ!‚é úN*ŽD¹‚i$KCà&ÏÐô-ãkùf:¯2nÏ™ÑhdÄ£#/TÙa²%Ö¦¹ÉJdÜZã÷69‚âóàbÜøî¸ïûùaĶ| óvæþ¡Ø32"(-}Ëtȱ® #åO|Ûjü^†À 9ýdà¾ã ˤ'(£'O|Û’ó]¹‚¦ÃÔtÅ$$Ëɸ!äowÍ%×–'è&_£i ÜÒ³2=Auð.Ý@¥>›n Û–Ž¡éŠXç¿Mø é¿™~ ½kŠ”(R,fÀý¬22bŠÈ½4ý@q@÷·‰~áÆ/åŠ'l1bÐ[Sn G:e•hÞ’ézœ?üT`Œœì‚å*/”éŠÃæ~áƒÜýTàÛÐõc¬^ ˆc@óbºJIsUâéº_r2*GP<¥«#(íP’Ž ‡2ÀMGм Ó´ovÀý8ä5[Ž §ÖÆò…Ÿ<›JOЪ¸ÿ—h5U~ ï2C`yÜO?Ðô¯Ÿ~ §ÒN?зÙÓYYþ6®Ž4”衬leD™cuÈÚüÞç$O,¦‡'–Sq¢a[ŽÖ‹¡ ˆMÎMC –øCah D[œ[u,°ç‘µ´Öé‰ò­AOK ^mä©ÀZêT`µ”†@´Äã|²bÊÛ’n µ’¥pëw!e¬×VÙ7Ø£œé¶>wbÈ‘^%†)Ò3éUΣ2öA½c SW¥±B‰@iì›õÈØW‰ˆÊØgÕÈØWy‘ÊØ‡½ÐîNŸ<Š*c‡ŒªŒAX¤2öáB#l}³â4öÍŠÓØ‡Í¼BrÊØ7+Ncލy˜™ÿ©¬}ø!+¢Ì}ïEŠt‘æ¾½p5Í}X#HSiî›™ûL swâtšû@½´’¤¹Ï$2÷ÙU2÷™Dæ>“ÈÜW¹°ÊÜgedî3‰Ì}óª´÷™D?“ÏòS?“Èàgü"S%2øYüL"ƒŸ]%ƒŸIdð›W¥Áo–IƒŸIdð3‰ ~&¡ÁÏ2ø™D?“Èàgü\BƒB½ˆGið›EÒàgüæEið³22øYüL"ƒŸIdð3‰ ~&‘ÁÏ%4ø™D¿’”ÁÏ$4ø™@?“ÈàgüL"ƒ2Ñeð³24ø™@?—Ðàgü¦$ ~³©4øYüL"ƒŸ]%ƒŸ•‘ÁÏ$2øÙU2øYü¬ ~&ÁoJÒà7«IƒŸ•‘ÁÏ$2ø™D?“ÈàgüL"ƒŸIdðs ~&‘ÁoJdñ3L~&‘ÍÏ$2ú™DF?“ÈègýL £ŸIdôs ~&‘ÑoJÒègýL"£ŸIdô3‰Œ~&‘ÑÏ$2ú™DF?“Àèç?iô3‰Œ~S’F?“ÈègýL"£ŸIdô3‰Œ~&‘ÑÏ$2ú¹„F?“Èègý@.ÃCÂX‘4ú™DF?“ÈègýLB£Ÿ dô3‰Œ~.¡ÑÏ:(£Ÿ•‘ÑoJÒè7¯J£ŸIdô³«dô³22ú™DF?“Èè7—ý¬ˆŒ~&‘ÑÏ$2úMIýL"£ŸIdô3‰Œ~&‘Ño*šF?+#£ŸIdôs ~&¡ÑÏ2úMIýL"£ŸIdô3‰Œ~&¡ÑÏ2ú™DF?“Èèç’‘kyJdô3‰Œ~%)£ŸIdô3‰Œ~&‘ÑÏ$2ú™DF¿º7iô³"2ú¹däZžýL"£ß”¤ÑÏ$4úͶÓègýjr—ÑϪ‘ÑÏ®’ѯÊX¾§wGTÁü#ã†Çdf9É¿yî&/1ËÏ?»æÏó=õ#âî¨Öúeù•R6ó­”Äò+uDg¬ÈïG从¿žªã3»'€²´MÊêôTª¦÷ÿñßNDü.SR§w_ÒLºÏôPÏüïÿIß9§þ°Òëß) Ÿhîÿ¿òD]ÛóWóD¡èWž(ÿ£þ·×ÿžúßWÆ(gÌõnßOeŒ‚ð3cdÿ_ýïüD–£ŽñëŒQï:ÃŒxù]s5<Ãg‡®ÿ ‹Å»™Aœk~‚mȼ4"#C™6D¯#œx´ui=>2âz/¾‹Œ0Èvë[|dDÆ#Fný ÏR4ä0‰´C;׸ÖOf‚‹Ãö‹Á¦Q¡:q#+½ß׃Mor]iØDÆŠ]a Zoñ‰™æåhß÷— ¥Ê$N !œ#íÒµ¥|[b6eªòˆW9+€¿‹I‡*7Ð+©¬C )?neÊü ñqÛc ?^¨aÖ¡Ì_Ðà4<ñ@ƒ'Ѷ[B’ñS-)Ã;ÐJ:”¹&z%|ÂjÀfGлó¶ô#á,¯s•0éPö¦# Ý³´ô(çPV‡=L9‡NIºrÍz‡re ¾3’Ÿ)–ˆ£ÃL¿d¬xGŸ9‡ì”ÝA´(e¬àhuDÙ¹nË7Ò#‡'Àéæix‡t3ëˆÒåÉEÞÂL:d’Á¤CS‚  ãöÆñün—%kyŸ„J:ÄYÝãÔ¶¥$é#^Í<,]ÑlqFö²T@Çé"ëP¦|é8âù0Ë.IWÖ¡LçÑqü¬qHù¨ösSÖ¡LSó>ª“\ŠÒσi‡*÷N?O¥ªžÓUF°W2äH¿ñ~ÞL;tlroí磴Cu¯Î¦´C‡œèûÉsv~Õ`Ú¡9¤×ö‘v¨_{¥Š#`ý:˜u(Cø¿Ì¯¤CÊìÔ¯‹9‡æˆ^sÍJîø°ˆÕP}¹žH94µ¾šRÕí½ºr rý.tÌ94¯º7æª HýæQjSò†ïú=–»c'9,•[ß"™r(Ì84Uºoeª‘BêÚó\jÌ8dWõ;“Æ¥dTÆ!ij)yM›gWÆ¡j É%úÒÖs2ãÐ|6Ÿkûm&VêƒfÙ#ÿÜñYqæ}êÏŸç}zsY‘ΜC•W¡?C9‡r¹yg)×¡ó4Wy3Uñ­ÕÛÉ”CÕv;™rh¶—ó»~#5Ä`‘;2ÍQÀ«y_”Ä»ùX›îL94'ÍûƉ廚ƫó>ü©Œ,3^â`¡Ù9ùçZgÿAã4¡¸¬3x3oËp Ù­©¦|C™oª÷~çê­{݇ŸÚô±¹zk-û‘«·¨q(ßP-tãŒ|C5ï’¿-ḘnhŽÞ¸™nh>rx9kñÖ2‡—ó’n¨®tCõ@°ÿÇt –ìÙL‡hÉ—éØ%RðÕWoæ²jÎøšˆl[|C¾|MÄ Àü¾¶½[Z›±=Ì7”·aàí¬µ›ƒ5½çô¦‡² å}ááÕî»Ò åÐ x!^ͶHÑR•n(W lCùüÄt[Æýn¹rk¬ö§² 1ëÎØòɆ/çÍך—ón™¿ÞÍÇiÓo 8ÅÉÄF ¹?À'~¿ŸhñV‰SÙ†êÆE@¢e<#l§…ƒ½7vÓñNÑ0l ÄQc©f(ÛPn&^ÍK¶¡Wóá¹ÔÆy(ÛPöø<##& ·ð¯ddº8NÙqâDs÷±9_Û^Œgn¿Sç«B÷WÔ8¡ƒg{»Ë±×òÆ4QÌÏ2ðZÞÛÜ_¼–ÛçÞunÜ{WËW$ذ—¸ ÀnÏ÷¸Ž)U9ï¯'b,Ù]¹"‹ 5¼k•?¹Š½[ø37ß¼™7On6ðfÞmÃ4ðbVÂ8nªâO¬Þùšx%#3~ê~ç´Ï¿š'*ñï†w¹} ÃçäWY‘ñ>"1É„ùKø\L8§d2ayh$$ÎÉžLÕ™Ü:™pN[1¡— ]¾e}$ÚœzB!†çZL‚¨y“ÕmSúÙjKPhƒ!(D=‡ ‰„B´u>…¸ŠY ¡(sî%Îç\PhwBPhSPP8befw…sn‹ m–Š gÖU1!æ$ý’ íÆ>בÐk!âV1=t"!ªá¢Hˆ‰ÂOЉ„Þ?"á\bD„¸ˆy’1—Ø=!²’ñ.HëݵÅßÏM?•{öJx0\ž©‘x•ðÛ‡pE´Þ­aÒ ŠÈ^.Ä*ÏTðIƒ¨WörÑà|$ VŒ„A¯˜0ˆ7Í'‚A‘¹L0ˆZ.ÒŒ`Ы‘Q‘a å‚ASS08œ48sù& ÎŒÏIƒxoê) ¢aap¾MÁ †Fn‚A”‘ýL0h“ß=[>ƒbÁ--’‚A>ÁàLC.DÚïÍ‚³!¡ zGKS¢ *a‚“dAr± 7D4-ƒh[»@Áàœ  ƒu[’Q„¾6É‚hŠÖ¡à|„‚V‚$èík2&bì¸5Λ8‹­Vaàœô‰³Q îãà5„À9¡­2 —[çtN´1ÖN´‘BÅsAÀ¹†çìMœs5p¾+磓ˆþÑŸ8ŸAà\Uçà‰çÈ1àÜ %νm" ]Dœ3< pfŸO´Þ‰gg€¨÷‰—Wà|爑ê‚;à|J1¾48$â¦Ð1Jò¥hã+´Îç@ˆÿlFˆÿ°¦p_–ügÿ0¯„¬@‘aœhÝÚX m ‘6I†gàœæ’ª olñ 7èC¸‘æÙZçÚÉ0‰|ˆ"Üùg!‘A÷ENôgðˆ|ï(ï‹°Œ'ñEßFš{S,s™'ñE¦ë]iËÙÌPH±ÌøÀù©Ý‚‡Lx(¢X¥¹ïE½›èŽÅPñ#› "ŠU^iñÞ+ÌÝ’¼·cµ7’÷BBªx/’±tÅ{¯DUÄ{‘”˜ÀÅ{3 xòÞô–Mà‹Š¹UðEx¸CÈb0NÀI“O¾ï'î1|3]vŸ—!ðE—¹=ðES$,ò^¨©"ä½hœä!à‹ wÍ}@£ ɼz\‰÷¢7ÜK‰÷æ}ïÍ´êÉ{Ñ~¸ð… »Ÿ)%à³ðEzÚØ|qÑpP»¿¾è1­¾È=®€/rÓ}JÀ·oj™´73”'íÅT—Í´góF´ÛD:w‰ö"÷¹\BI{Ö´h/´äÞŸ´¨Òž „h/Fâq`t‡$'Ú›OUÒ^ ±<5I{ó!OÚ ÷颽¨çpÚ‹Á8ö"<-¢½™ö=ioÇG½H{qÑb|פÁÈYI{ÑÓM€±  ǽXthfîYwˆ{¯`Óîí˜p9îEÆ=~FïEZ+Ä{‘ö|qÔõóÞŽ³$hñ^,¾œNâ½(CÐðaÑ9vwþ?E|sO䋪L|òÜ”%+‘/VyÞàD¾QnB¾™Ë=™/$´‰ù"‘<­Ð‚>“úâîu7FEÛ™;/™ÏŠ+ö^ÃK.…Cð Ò[ _hÉgHÈgà äsIW\±íâë"‘/&$— !Ÿõ—ÌM-ž ü6oþTH±jV¸¾:„{vK„{1p|š…{óõt'PSZ¼‡3ãtÛ_í÷¢)‘q/¦«˜‹¸÷^#bïÅ&wÎKÅàSÄ2·"ŠmqBø¢‡;æÐˆölòŠö惒´7ç]ÒÞÜÉ$îEÓ"5â^Ô¼» (8ÝT}IÚ‹û¼¹ÿgÔq;îyò^Œ]w»_LM1ÕÆhbU$o úp%ïÍÁLà›‹J_Ü~úʉøê©(â«ûVÈg’¦Xb›¾¼&òÍÓ7Å|£é+a2ßœŸÉ|.9K,WŒb¾ãÒwºd>¿èR01{‚Ä}Ñôé^ qUsTr_ ²Øà’în `–$J‚Ÿ »È/†”>Ÿ¿qès·Ào.¨ ~ÑÒéàgO•Ào..u>K&Ï:ÿå´Pu Þoo§Ì´r5•è+¹V?Ð'»¥h%>*?ÐLkT~ • ¨ü@+QùV®¡òÍ4Lå:WåÊ#WåÒ D1à ŠŸ X‰…g2¢@À™Ñ(pfFJœy]rTb!U+ô2×– )n?èÝ=óQPk! i-´"ýÎl·üf¨{`•Hþ›ã”ü7Ç2ùÏ%—r e_’ÿ\r3§Ð¼è©œBÙ™¦œB³L¯œB2+‰ÿ¬ŒøoÃO´Æ€VÐë¹”SÈ$Ê)4ë¹+§P¶õ´ÌE‘es ÕŠ½â¡œBUFhƒ!œI’ýª“9…Î4Ûˆ½ÈU9…Ôc KåšW5åš’®œBS2*§º,tÉ^9…ö+KN2 uG h7‹ h(ô‹¥ªþ‰½LWJ¡ýã õO heÄ€^æØ33\–9÷5E2 —¹F¦¢Èzn¥*½È€¦¹Ð/ê÷šŠ"Ðʈg¶d@/sdZ¡œJ+T3Y hSP hZ‰]ò´L·¬…)ЋŒÊ*$­„€VFh]ZãB@¿êÚÖŸ#³Ãé”ßÝs ¿ÜægwE8WIñß|o%ÿYCâ¿™ /ùo¶$ü›/»ä?¯æTF¡jJ8{C´AÎLà|™%zÛãÊE\W g‡Éó˜ügc%Dz½—ò UÛ¢@kéi¹„ë¤ pª-4ÁP2¡jZhµˆ­3b@¿êd2¡ÒR èÕ\J&4/º•L(5z‘¦\B[J$Îã4I³ñ¤@—ìÊ%4%Çž 8;˜XÝIœ3@8û—èõ>J%4%M©„f5]©„¶:•8”J¨$ä@kJ8»'4 Äs´’ç´IôŠï–‰=ד€ó9LĨˌ#œiEM K‚3)§@Ð:(|¸£žhýÎsr ʤQ‘ˆjd­$â"oZKÄ@É{Û™ûo–0ÐÚÖ¦=)ДÚ@ˆí"Bàœ× vvÐã²_"À™G5 °©&Ú0 m€3·j é#4€6A€^†h=&ÿMøÏ®!ÿ!,ñTø7ï¢èÏê üYoS럤~*KßÑÃ7Ô‚½ &swK_ÇQáa”‡µ˜'/˽Ïüã§ýÆ©|ìÓ»ó”[ÕôîlJÐT¦¾²¾—©§²Úbê{¹T‘fÒÔWŽVeêà X8¯ü!ʹ!`rîœöËpLÿ•έé{Y9w>·LŠéÛYnsåÛ‰°ô ÿ"ßζ‰ÓµÑ»$tíľ”ÝM×N$”ßü°<9õʵ³¬âåÚÙê”cºvî[žjkgÊuR®íÌ-WºvNgÊôíì­ŽáÉ·³½‹§êQ´dwØÍÔ‡‹2p‹|;Û¥MºvÂãH-ɵó½H‡íÓµI^E®È]Ï}CºvÎþ¥k'² (¸‹|;#J«<9éÛ‰Pú:º'ßÎøÛ=ȳQ§u´žxêŒFžÈFq-®ïÐèœWºv"”lirí¬–Ò³³ík䨉wÔ¹8vÖp¦_'ư;äÙmJ¿N„o¦I%ý:M"¿Nd[ؿξËÿ)Ý:ߊûêÖùÎ#Ý-·Îy‘¼:í"yu¶QNœôê|§°\Ó«³ïišI¯N¤¢¸œñP±|&Ó«ó•<‹Sçì^:u–ëA9u¶QŽŸr꜃žNs´Ò© ÎtŠONõ–S'ÒtœëÅnL:u–oD9u¶GVùôéD"ZçäÓ9Ÿ„ôéÄF_^”ôé´"òéœTútÎÞ¥S§•‘SgD›¦Ã¦œ:çÛNón¦Sç¼éÔ9Ç8½:gÍéՉˊã"·Î·žƒæ®ôëD”\±ü:[ù.¿Nìh¹L#â¹înä3Ò±s®}éØ9W’ôìDyWʳ9~7òA"„OÏNìþubOžu;Ó³s>éÙ‰”\´äÙ‰Cô4^¥gç;ýžÍùÙÍåaÈž•žsb§ggSú¼ôìœZ¦g'‚ú²ÃéÙYo»ò융ȳs>eéÙ9Ÿ ôìÄ™~äéÙi˳s*•®¡ÿbê{— ù¤kçœýéÚ9Õ’­¯ÉÍéÛ9W“tîÄ^õXœ;‘üæXœ;çHçÎ9ÕÓ¹i€dŒ”s'¶OòÓ”sgÍ·rîD:œÃ¾ÔêVÎ5ÝÊÚW#˜Þµj–{g=öåÞYs´ü;kõ-ÏZHËÁ³V®ôð¬Q/ƒ_MÛòðDnžÝ-~spÊÇsv9}<ë—ɯê2ùáIV0yyNµÒ˳΂”ÉQ܆Ÿôƒ÷šðK^ž5•Ó˳–˜²øÕ&£¼’•qÏ$²îÕ‹¥¬{&‘y¯^YeÞ›eÒ¼7ˤyÏÊȾgÙ÷\22\Ö#ûž•¡Ï2ð™D>“ÈÀgËÀ7%ià3 -|³š´ð™D¾yÒÂgÕÈÂgWÉÂg™øì*™øLÒ?’•‘oJÒÈg’½’¥DF>“œ™<¨•<(%W%JÉ]ɃRò´5\YùLÒ+yPJƵ.æeå3É^ɃRrTò ”œ•<¨$•<(%W&JÁÝÖµ¼Ì|&i•<(%½’¥d\k"¸4óÕÄ(3ŸIdç3‰ì|.Qò )‘Ï$²ó™Dv>“ÈÎgÙùL";ß”¤Ï$²ó™„v>ÈÎç%šúL"CŸIdè3 }&¡Ï$ã#yPYúL"KŸIdé3‰L}õˆ–©Ï$2õÙU²õYÙúL"[ŸIdì³z–õ¢Ì}&‘¹Ï$²÷™Dö>—Œ\ËS"{ŸIdï3‰ì}µ•½ÏÊÈÞgü¦$-~&¡ÅÏ2ù™D6?—Œ5©gýjü,õü­ûÌK²ï0ªÝÊm’ó4N^b–Ÿ%~vÍŸ§~Ú7óÌÔOõËR-¥lfY)‰¥Zz×DP©Þé—×#™Õ“’¥žw›]µÄÿ—: ñâ÷¿=åÓŽLdÏ¿šòéú)Ÿ®ë_Jùô1y^j|W¤JŒó5UplþU×Î|Ny½'tÊ:¬”êYJ©®™Ñ)ëò”NY—•R]K©¬«r:U]–ԩꚥ²./•uUV§ªËÒ:U]³TÖ奲®ÊëTuYb§ªk–ʺþ…ôO8]ÇíôO¿Z"ÿZð~¶(þþý¤|,’?yZ¾êøëéŸÞ…ãŠCžjæxúY(KõgÙšþså}≳ý×™ŸëèÿýY:¦¯ÌOø{¦{ºíÿ«yŸžŸä}úçÒlO8fÔÀÀžË—æ§´2ãˆ[ì5<>iãëA®[|¶Ç RÆŒÎJ8ôzF$bÀx(Á·l‹MŒcë{„Šc°%Â'< y÷˯dðÐ*NTGØhDgjºèÕ ½’S¼cÃO¤2¸bAI¨Ðà¨s±;Ø 0áÉÑU3bH6¤pPÓ¯ {$Ôú€¹4ŠÐ ‡#¡t½Yæ¤0Œtnpl¼C£¾ýÐà8ž%)}ž1Véx¾ýï–Lë•°ÿ0#IëýÉìjn\ø¬§pö'³È­ZG„‹î{ÝØkCþ@d…`ˆH¢ÿvÕ%.ùI½’Žz¿î•¼8Øäý ™ßÍ÷Ò°Üx¾’&(H"T4råªb±Gp I°÷bÿ»ŒJ¯DýèkƒUöµ„8"¡â­kÞÞ÷h:gÐ rÜ“® s+sù¼¿©"Y\”<¯{Œ P ±-š$8ç<Ôñ9"LtåQ{%xD^‰4Èìk¯äÕà‰ŠéÏöJS¬â~„Ë@(E;2¶â'zŽç3Øß®9Ô¤Á‡F Þ2Cóñð¡Ó)ÇWòª°Ü¦ˆÖ¾ÜD°¼×jJƒ®þ6i`’Wêݽ¯äÕ ¯5ã¯Qó­ Ü·mQ iâö¨÷Ðҥ¼u* P‰žþêp.7³_·&ŸÖ‡~_š{Ò»Ãyp¹s ÉpJ¨\ëô$tÔ¸LêŽÃ´Ë½ÛX¦ÑØ#B´õw¼æûùJJƒ|$ÔæŒ¶iØ}%¯ ×¢e„Ó[%íÐó#5ÃЂ[ÓqP…Þs½Ô`¶ÍSþ«ñP§N žaã‹eq}z°ð¬·)öPW”açÏT¢›ÒŽ TMÌ©Äþb€C¥šŸPáÇÚ¿Œ]Þ&¯dïö(¿ˆÚü6îxï~w¼ŽUr_ÒHSfßÙ/Sý¯†û¾Þ¤w'ºéqª28%7›áVßîm}]ÞjR)Gê™Æìý}>>}w¼÷etÉåszìÇs®óî—#nI“?î+‘Ö*0çÑlüÐ=9·.•6Ý·ÈËðïNfgçé³w?©/ÞÇûRä9u›ršíЗ ÷]ó.GîDq__ÉX—ƒýÚúºè½{¥¦gI_Ç£G)‡ü:o­ÚZóvøàúH]Ÿ \R`öîj‡TÒÃuõýã.]cÓª]-ØÁác÷à}»©À\m÷»ÈÞÝÇ£gI+0¶Öëëóq—îûò%eÇ+y_KP…¹?x:ÔKy¿Ç¶¼Š^ÁX_E/3v­Ú©æ³·‰öP…ùâÙ©0^ö@;N@ŽeÚ<ˆØ>÷u;^É»¿ìw¼’eˆ©P;=Òá,Š#±Íz«ÚÎ}СzX4¸ºånøJNîãjϸ7é£<ÛjÔÁúŒ”½#®Ò®}oˆÏ^›§¢RÚŽï±Fz¼C2Ö·éÞ¥Â%r¬iL˜ÑyŒßëb#T;¹½ŸÜÍyÔ¯Ks­ê½OÝ–â.f5ê5Œèòa¨Õƒ» ;hÇ ™SOøð.·±³ZøÇÇr¨ÿµÏ×ç‚9Íÿjj§d½»µŸ`ŸñÞöšð„°‡G ¹°‡¼VÉ"„=Xo“þ‚õ1jãëS¬wÌ»•¬‡Ímn}Éz‚®\`¡x¶½¶šd=ažd½g»jËBÖƒ¤ª‡¸ Gm|Èzð|bf²~ódB²<¡ÎDÑ€½gk5‡Txtt"aeJ0$ ·_Ò–‹#Ëî¡Ì­Æ‰{K™À=HNÃ)ºÂÙ÷€—ø¼^$ sÁ{Þo©&€Ï/’S°´4°‰ždÒÞR¤§ÏHÖ2ØYíOÚóKZu_µö `ÐÊ„½¥š =¿(`o¹¨ú_’êI•à5’_"{¦YÏ/ëy_Èz‹¤4(IiPµ)-e‚õ b'žw´·\%ìªR¡$JK=ÁJÞО_CÚ[$A{^ËG}8#í-W,-Wí-’Fw“î-õ|é0¤CIÄ{‹dç5û–ï-%ø‰t°«J‡’0Yÿ|K=|‹dlëtñA’]:Ìš÷}Ñ;ÏÆ\Èç½#ò-uò-e¤IJƒ’1-m1-½ äs ‘Ïë!òy=DZÜÝ@¾åЦEÈ·Hžs}b¾¥LiP’Ò`J†$Y™ÏËùü>‘ù–2:œ¥Ã³@ßR& i‘õ--õýC+bßÒã/ˆ}~±Ïk&÷-’óþ¸S×µ¶t•uMéP’ ¦¥í ¦¥ž ¿U2¤UÖs—%)ò*’ß" lZ® ò[ÊÜ눒ü–kJ‡’|é@ò[Êúy¢ŸÏ¢Ÿ_õ”U¦tÈý–«›–¶žµD?:E:ú-eJ‡)É==öý¼m¢Ÿ_Eô[Êœ÷Çi_:´Ò!5'ú-eÚzÈ~‹$Øo•Œ­zéP’½}JŽçc’þ¼¤¿åªûüЪ—u•t¨ß}Õ€ø·”ãC'⟗¥AIJƒœ7Ä¿YÏßÈæTÖ¾ãŒ0k2Ë Ydî« A$@¸ÌÞ²,‘±{ÌW7ðyž$Y! &ã##…pdÚ’BÀñè N1 PR&1àèJ-[ 8šXfàBÀ¡sùE€ãÉa$úo ×Jô–¥A×qê"À1tZ¯pd*¢2ø¡dÚ÷hñÛòÀ! 6MÖ» ">—–ìáñÙíñíïª%PñYoD|.!-½Z¥ß¸|<÷ gUÄgÓ8ˆo®$>[7|oC»¾a øì~ øÞÅï” ZÀ‡ÔP›®"ðí‘«€ÏžŸÝ;Ÿ »œ<íŽ øLñ¾=#ËñÙ€Šøl&‰øl¹ñíw¹æ‹øìvŠøæ øìÁðÙÄ–“§Ý;ßT3o2o*•À7ð¾ýÉh |^F*Ô“À«³Þß"¾ycù²oĽù`&îY˽¹°ÑÇs. Ľw:ì‰\Ľ9*É{sþ&ï¹D½ŸŠ÷\Bbš·-ï]Þ‚>Ó@À‡ïЉ€¾y' |óOâ³Z…|Ö_!ß~)Þk!ŸKÈ|6þb>-1ß{û~ŸÁL{F\,æKæ"ïYïÅ{¦sxxâÕ‘t§þÏ»(ÞCà¢Sîšä%oñÞÊzs)HÖ³û!Þ›+ròžxo> É{6Þâ½ùº'ïÙ˜ˆ÷lŠ÷’ãÈIÖ[±Þ܆¤çÜÎ$ëÕ2¨gÍõì6 õæj—¨g–Pφ*PÏJ¨g7M¨g¾K…œ†B½ùFNÔ3Å…z6a„z¶ õl€…z6„z0¦'’“¼Ìsú»!QÏn¿PϧtH¨êÙ¨ õlŠõ¬ÇB=[j…zv¯äßi=n¥ƒÞÉz¶€ëÙ}ë™b=›Ôb½¹AHÖ³ÞˆõìΈõ¼ Y©ÙäœIÔ³I Ô³‹õìyïR!• Öó:ÈzÖ QÏFJ¨gwW¬g‹ˆXϯ"ëÕkéoäm*î“+£q}ý£°ïA‹:>¾w0ä?œ>Ì—ÅÀ‡ w/><|òß“#˜çãhû}[ |ØÂJdàÛá¼. |؈å?iÐòHAZø¼ M|`E9É…‰ËE ¤‰ÏKÐÄg:ÈÄ·:k#ŸÕ#Þ?ná[.¢“'¶ò֤Ϯ¡‹§ ªÿ)xÖFÚ¹TH÷Nнs^ Ëž õU×5Wu<t£‹s§KäÜ9/¢o§7D³ž_„ÞûoøE­D!òí´òí´y!ßN»J¾~U)Pe¾o§KèÛéö\BßN—H‡úý¥ƒ|;­7²ìy:wz9wŽe9wz™Ò¡$tt Ý#]BÿNoþ^f¬=n_:´Ò¡$ô´zåáéeèáéºxºäK‡ö¥ƒ\<]BëžKèã >MIøxZ ùxº¤t8VOÓJ>ž^†>ž.¡§_EO—”%ùÒ!}žV‹|<½„|<ëa_*ÈÅÓ%´Œ¹„.žÞ]<½ ]<½ UX$c}ˆÒÅsÖCOÿMO—ÐÅÓkùÔ!­{^†’^†’.¡‹§Kèâ¹H†Vîä§/öÂÃÓÓÃÓ%ôðt =<]ò¥Àþ¥€<<]BÿÈE2Ö•ž.¡‡§]uלÏú›Þ‘.¡‡§KèáéµÊó3<§@þ&ëã”îV­Ü;½ŒÜ;«šó£ÿçWÿÓ»s¬Gúì=_Îc=Òç¹všà³ûòìt ½"]BÏN—œ÷ª;çOöÞ¯¨îg¹DNAÏÝOžÛ²ÕIŸN«5}:«’téœzCÚíIΪ6:§à^šMwÎY'»îý¨¾g9BŽõŸ•HWÎ*‘žœµC,OÎÚý¥'§µœžœ³^9AÎyBGÎÙNËÍ[èûÇÔz>»Ÿnœ%H/Îñq€ÏvÅåÅY{‰òâ´2Õÿª§ÈqH/Î9ôâ,Ó‰Ó*‘§]ò©A/ ²HúpV½éÂ9¯‘çl(=8g9pZµÕýº¨­ÃMNû-N— é“C™œ³QÝÏ«Fõÿ^ÎïÍz~’—i†e9âQ\e階šOÅ$Œ{vÅ ŸŽš·Ò\MGÍ^A7ÄqÏ(çqR^\y4/–KY5‘}h=¬×¶45ãL À2›Ò Å!›…Ì\¢¸W’‘‚âÞkÒX"Šk{ÅjŽ’Œ6 Šk{mb³¸$HÎA‘œKHrV¯PÎÊy½rr´«ˆr^3QÎë!ÊÙ¦£¦]U:ì›Ûílåü7Qί!Ê͵;Qn¶]Žš5ê‰r^†$ä5åæX$Êy¢ÜÔ*YÎ%ûr7ÉrV«XÎú"–ókÈr~•40‰4¨»,ç}! y²œIÄrv•XÎz,çלÏÒ_±Ü|ƒ%ËÍ÷p²œÝ]±œ×[”¤4¨¾‡L"œ³þçL'᜗9ŸµDém‹ç¬Ç:¿Š@Wy€‹èü*"ÍÙ³tÈñÓ™Vb:«GLç’3÷CÅl×½ÖKæÞ,©Îki¹ª«ú¾îìlüDvvÕ]:T ê€t*·ÇiYÊœ÷ú^J¸3­‚î¬ÇÂ;—”%)J2¶u——„gwFˆgZ‰ñ¬ž§tÈÑyJ‡Æózîóc¥Èóßíø˜¢<—P‡yp*1ÏZçYÅyV8ÏËœ÷Ç|k¥Cö°•9^â<—´c ž×BÐókJ‡l»—y•HÏôêY=b=—õü*žõ°—Õz[û°ç¿ {‹d|è$س–Gi- öl•ì•Ä22MSÝ«Ày8ä͈"b<‹(Œ‡Ra+Åxï&hkî¡ É¹Úê,úFÆc™1;2‹KÆG¤ È2#pd@–Å#²˜D:˜DÑLL¢Èþ[z‡ÊVgÙêL"[Ý”¤­Î%CZeKi¬›BÒXgWÉZged®3‰ìu&‘õû#žIšìL"›Å<‘ÑÎ%ãÇZïõ¥0Ï%_Mþ0&‹Kˆy.‘õûç1Y´šAYJ"»I”Å$_:dX“(¬‰I—Å$ŠËb’±ö¸}éоtÈÈ,&Q\“(2‹IšÅ$_:´/24‹I×Ä$ŠÍ2%ŒÍâ¿Ç‡VýK‡þ¥CÆf1‰b³˜D±YL¢Ø,&ùÒ¡év;—Œ­›Å~ïýC«´Û™äK‡ŒÍbÅ51‰b³˜¤Zel“|é0>u¨Ø,&Ùûú[±YL¢Ø,&ùÔ¡b³˜D‘ML¢È&&Ql“(6‹KƪUÅf1ɇû±Ö‘±YL¢Ø,&Ql“|i°i±YL"Ë—KƇN›Å$ŠÍb’›Å~+®‰I›Å$Ïù¡SZîLò¥Áñ¥AÆf™’ŒÍbÅf1‰Œw&ùÐáüÒ!­w&‘ýË$2ß™¤ïZ¥Ï%Ÿ:dl“ÈfÅf1ÉyhEžýþÒáúÒ!x&éû‡ViÆsÉøÐêþÒáþÒ!c³˜ä¼?´JSžIîeÿRÆ<+ñ¥Ãý¥Cšó\2>´JƒžIöö¡Õó¥Ãó¥CZôLrìŒdÒ³ßíøÐ*mz&ùÒaÆfIIZõL²ìʪg’ócwWV=“|éV=“´µÇiÖ3ÉøØß•YoJú—i×3Éñ¬{Ö²ìY™ëZ÷áeÚ³2¥C•ùС÷Uƒ4í¹äcgT¦=“”ÙÎ8>vweÚK‰g_:ně̤Òb¶Ì¾¤¿-Ù—¬Ä,oÙ—~rÍ_Ⱦt¾û¹wUkþòŒG’Y’“”xÖ¤cΪG¿–z(óz$ñz®#6t©¥~y=’Y=)ù÷ga ¢|þ¥,LÈLò¿? Ó:‰ŽûÀ]ùi>§ ŽÛÏ¿êZ˯¤ë—üJªÃJ©ž¥”ê²üJªkɯ¤º¬”êZJe]3¿RÖåù•²®Y*ëòRY×̯”uy~¥¬k–ʺ¼TÖ5ó+e]ž…)뚥²®! Ó»5»qÍñ,L¿X*ÿZø~¶8þþý¤|,–?yZ¾êøY˜$9Ö,L–éo¦™îéÏ*ÚgEÏ¿#!²YŽãÿÆ„L{ýïùYj¦þ'HÍtÜ;vÒý—øvÌõçB,äÙáà<¹–žÚ\؃Æ*Â/ÒÇKÉ Ppï¡äÁ4@‡vîW‚}ôŽ˜´Uwë±²öÌ}tÜ[þJ¶öƒ¾FÇ=°}äPvžµñl 5ë÷ò»‚Þgd” WÐûŽtö!q©®ÁsŸ˜©lq¯N±%g_ž;ÐTÃ6 qÑ)IÃ4ªÝt@X;íŸ*ð¶ŸJ">$Ï­c/Gîy%HÄm6 ±·gJ£Ø€îáÅš[¨ðôà&≂g Ao|sA‚èûþÉ_G õöèêÌxDÞóŒ'ÞZp­d=]*às dzSÔL¯«£gHpf™¸™¡t3È–6Õ{#ÇÄìK§íjŠàÿJ¨ÁƒOx!h=ÈmÍîöÞB¥ø¢„þƒ ãcc~D¤É•‡§^É}ÿàëc¨ÿÈ'«2'ßç7>ù„àÚC£+ÏfãÞB¥kÔEï+'˜HwiÀÕ"?%Òà}[Ií! Ú¡|d'†_¶þÍòv‡NH±S²soþ'%Ç:!‚¢$Òà‰¤Õ!‘ ˜*so!Av.Õ|P ‘¤$yKðÈä»uï¡TËçíÜù€½áóô¾ý¥2U„d—íÒãsî8éû[à oæù®2¡6á*s¡SB‡äÚC+$IâèìÒaܚï$tèˆÌ"ÉÓ?´zë¤V SîÈó[ìºoõx<¡&%Âý³7<(xÔ¡#â {|ç§äÄw¹=2 _”\;µê?ÕÓld*sjujRßë$ ¨v¨’ÞÖ¿#%J4…Þweø°¸Hâ‰áäòþî´BHxêó=-UyšTÀ* ɽQ©=—$š¼¨fÖütjuä“‹µôYÛ¢èŸnL£¶¨Å”Aë{.ĸGƒ=ÔÓü¾˜yc\êÄ{ygÿèÙ~âÅ|,-õÔa^E°ðq;wö§s9¯µ·Ø a§3ùÙûÃ'hÏÙGlç"1%¯Ô¡Áÿ‡ýÔé!5^ãˆÝʤäÄ3_Õrí|%坿ƒ/UM“q¾‘ö¼áC*ànðæÆÝ²ç¨žÎÝл,<ºjܹPPrE Y.S<Õ}mû™oUNÀk“ ¹ô][hÀoCñûÚýÅráÅ, ·1^ÌÇåV™‡Û9dÜR-©À]]IôsÜ©—¹k߸B^M–ywÿÜ7ÜÚ´\ûÁÍÜû~çÎìzߎ|ŸvqõS]«ÆµK\/¼”w6ÝUäé©ïëõVÈ›4´~¾¸ÉíÜÛPWө­Ûv©Bnb.ÐÐã¯÷ëÐç™W…K’“›¡ZS¯ãâ~‹8Gø}-sÊp]‡txûÇsïÞÊ!9µž_ï.›Zé%v½ÛXÞ¦Sûç뵟㫱¾ÁÜÅŠÏT¡†+¿0åíþËIšD}ð@@P‹¤>;ûÔ÷€ã…f}p5Pv2A_,ÙÚëúÂù Á0 ïA¢¬Sõô·Äsd¾çz2Ì·˜íb2ÞŠˆ'æ³jˆ|¯‘îÂ.ßónïåÝ+âù–›˜ˆ—¤ŠD>øNÈ÷Jȇz”öIÈIWרý·â'‘*péyiTÉ,E|ˆv¾uÁZ$Š-ⳃ7A|K½RÁê `‚D);…|¨7ï‘9{ ùðfU|\!$Š˜-äóš{éph‰|®™õl|ú Q ©€>üVÐdAn†•ÌüÊ}®¡oi(¨Ï•"õyS¤>kŠÐçMú yN§>€Ú¤©/v&údê[ êƒdèj€ævè[šb‚¤ÑÏOÔ‰üÌD}è̱P¦‰òíŠúlâˆúlî‹ú QRNQnø¡·#¨ïyDM6QJ<}. Ö™’žô¼„‹ûQÌç-“ùl¢‹ù ¹ùžëÌáò¡ˆ• ù\I ßÒP Ÿe%òyÓD>kú( R¼ä*ø°H ír|K™>ï oi[̦¤€¼ç?÷|ˆ{‹$pÏ›=«ûÙì©îW³¤=,YÓd=[/Äz^$XχàŒî_éQ°çý ìaåÖ~—¬7Wy¡ž5BÒ[*©¾gÏ.u¾Vc‘ÞrUp’iLÒsAž7=–¹ÕùY'9ÏÛ%ç-’óB9Hä²÷¥Ïš"â¹`¿–vHx‹DýŸ-7)`’ #»v<Â:kJX·”‘ Õxpí’‚ë–+î=›¸n·°n)R ”D XÃã–Jƒ!Øy‘ãøPˆ\7ŸèÀ:üëîêþüû=>Oך —Ÿ n‘ôGûê¬V/Á¡Îy‚\HçµéÉÉŽI®M›€]élÙÒyÓO_5"Ð-µöçC#KHt‹¤4X€nù;i—ÄtíÕïiO184Mpçé ±Åtñ¥/%ÁtXUž¤¼`ºXgé:ÂÕ:ÑÁõª‹BˆtýØòx›.>Š5ÁV ÕK¢C½§8Šn#ˆ` -2ˆ®G@ÎiÄÃo…*ÒuÄ<^ŒxiÜüG!$  ¤ÃUG–Qÿ÷ÜŠé Q 1êIX$Ó-e‚éPFQÄt‹:à­#ÀlÒ!?ý éP$o‘ÎÕ$Ò¹šDº~ÜéP±fC—³š. ®œ ":¯†D‡2 Ò$:QÝò[*̦¥ÁŒ"¢Cs:É(¢ó¡"ÑùU$:ï ‰ÎURaŽ ‘Ά˜D·\D·TüßÌ w}PRÁj B™B±"ëžn)Hgm éÐÒ¡-µÒ™VBº¥ægx…t6Äbº¥íÒ!ËìÒ¡FGPg7OP‡2:š'¨su‹¤tÐfQ©n¹ªõµ7AuödŠêì ÕÙÖyÉu>ä:”Ñ>qßr÷\‡ÖÂR\çãuH‡j»·XQ£^hçZí|dˆv(£œB;¿w§4Øó¨¯Øõ(ºŒàΞhÑÝRsÐÝ" ¼[zØÛ2VÀ;â×A¾ƒÞ |Áw\²Òß¡ošÂWu_ ³ð΋¹Î¤»Ex·H‚ï–Š£ÿ[¦áá-’à#¯…„ç÷ž„糓„糈gkµÏ{s—9§Éx=2¨L0ÞrU0žKÀxÞÒó¥Ã#¦Ý. ‚KVº`¤åš ¼¥ <-RÞR†XKIK÷“\BÊ[$ûåÛažß„& j ÌÃU½¨n“RUo’«Iг KÐó»Ò¤Â¼»íK’žWLÒ[Êkgˆz®YÏÕì¥Bε^*T™'÷CÚh‹öü¾ö\+âž××r¬uX$C’j)ÀÏûGð³1øatš@äç5¥CIœ ‘AHèç5ý|,ˆ~®ÐÏïÌQ:T½Á~®áo¹*ào)ðçõȽÝÚ>¥ÃÔ\Nñ8xÝÓœ÷«ìKI|çAæ‹ønx ʺä{i^¬+äÉ/òÁ´«Ô"B>HúÂ|´ôË èƒs\Úè}(’¹ ’;mp}±F¦±,¨D³Øñ h» uPÁ \GüTütA_0QO«]„|Çp&FÈw—ôA’#õ¨ÿVûß¶L{"èC™žøÈô–᯾åŠ>H ?úߪÿUgàRÕ¬T¿‚ôPŸ¢`‹ô iéÓ¤çeˆz]`—ýžðœ´” ÔƒäNS] ÞRæÞ—¶{öÝ$êÿ”(-m(-=Ö ;{“Å,XÏËõIé=&ë-õ(-Wìy{ð(UÚfÁÞrt°z¥Ãž{VF°‰"^ öÂõrûÕ#سÖ{ÖcÁž©`o‘n©”’!fÍ£TÐJ0·”9õ÷µ(E˜[ÊÜCZU™/sËUBK™‘{5IsÖcÁÜR¦t¨2Ò¡~_»·,˜[%C:i—+˜[j‘Ö²4°2B^3aÎËæ–2svïs‹äZî‚`n©7@h©7`n‘Ì-WÌ-5—Yæ(V˜óš s>‚„9¯™0çZæ––J‡’Ì-’€¹¥í€¹¥í€9—æIéPx'²Ç'½Rºg"ìY;§{&9%’…{f+4ùg"(QzlÒ?aÇ[^Öú;¸yn‚ùgº„Ž.¡‡ã+Ùu°Lš8–+*£¦¡ƒæÛøØUF*ÔïëX:'M/AMëŠ<4]BMo¹(É—rÑœ ÈCÓtÐôkè iE®cù©þO=]0~¬—Ð7ÓtÍ4=3§ ö¼WÏ“¥èÔhzeš€N™&¸÷ågu¼ÙñПÑtg4ý1§@î˜& 7¦ >;.gLБÑtÅ|é‚®˜Ëï±ê2ªëUä³ïòÄœEÒÓ%ôĬ‹ÒÓ‹T÷KRý/ ýÉXU¢#¦ÿ¦#¦Kè‰é’/ö/äŠéºbº„®˜.¡+¦K¾tØ¿t/¦KÚÇ5ôÅt }1M"_L—|é oL—ÐÑ%ôÆt ½1ÉøÐêøÒáøÐ!ü1ý72M"‡L—Ð!Ó%_œ_È#Ó%ôj\$ãC'ùdº„N™.ùÐ!œ2í·œ2]B¯Ì¹(§[æ\ÊÓ/s.÷é—éi`WѳÑk¦g£—¡cf-ˆé˜éEÆZ‰\3­„\3­3rÍô2tÍœ/ØtÍÄÑé2ÓmRêZ wö¢NçÌù2OçLÄ#Kî£s&âõ¥qΙ& çLÿ]:d½òÎDlªd3º7º„î.¡ƒ¦õFš^†šˆ%£ÑS:Tº8º„.Žv•<4­L¸húoºhºäK¹hšærÑô2ôrt 4½7ôÒtIécѾt›¦•‘›¦—9εÄy|Ü+9jz™/zéPeèéèºjúUtÕ|%é*/_M»j”ÙãQ:Tº:z™s½òÖôôÖ\$CZyæ®t8—Sx‹„ÞŽ¦ƒÜ5g™t×t Ý5]R:”D::&îš³t×\$C:Uô×tIiPW}jþšv•6]B‡M»J›ÖcylzéPµ”ºSé´é×ÐkÓ¯¢×¦Kèµéõ”Ù›£tÈšå·éº=ZÍòÛô2ôÛôšá·¹üNª:nº„ž›¯dsÛÝsÜ:™“~›³„Ü6M þ×%òÚ| —ý³\Ki«ƒŸéÝ é⤮ ébk>ÜV‡²y¦Iî™8ž"3¹g"^ã¾øgâŒlPrÐDƦ GGØüN³Ò!^þwrÐDm×⡉ý³‡Yéø`ŸW ‚Žº‡&>«ê–<4qNGºÞÎOMt:£ªÐC³ÁeWfC*ÐpLõP~e~ãôÐĉی¼BÿÆ~fvèôдþÈC³柉3­éŽI ªåqs]ï[«4ß«šŽ{ÉAsÖJ÷L¼^îÅ=³¿7[Iùg"‚N†]QÿŸÌ)žþ™oo€Dî™­¢©§{æ{Ñ~›{f¯ì 鞉“±ú¸ ÿLLùgâH°"êÈ?³ŸõIBþ™ï@ŒÝ*ŒMN’ôÏÄIØKΗRa¶%ÿLœÝÍè,tn´Á‘ƒ¦ E8hâ\ù“¿ÇÇ’ƒfG …ÅAó•´ÛIõìCn”tnì•ï,4çíMM@WJ¤Ã™VõtÐDäWk—ƒæ{U~³”ƒ¦_õPË3c±ÐA§¹yÇÓAÔår$Í~ëhvúgÎÁJÿÌ9gÓ?ó­f;ô\Mùg6;ª'ê–§fC@µN߯† ^j¾ó†§¦ ±ü3k^§{&Îj?ug÷7Ý3‘…àT:7Î¥$Ý3ý*ºgö+ýÒ=sÎÑtÏœË Ý3­{Ï¥>¦wf¯`ÿéieä9 ôÎÄóX¼3ç£Þ™¹’¤oæ[âJ¯Oúfâܽî€|3½múfvœjæ:{Pé›9ôÍœ‹DúfFœIùCÒ9s.>é‰Síy(®úŸ³Aî™6VòÏ´i/ÿLùgÚ,’æ|˜éŸ9WûôÏ´–äŸ9ßéŸi €ü3]BÿL¬éÃ…þ™sBÈ=Ó0¹g¾ÃuÊ1Xî™ö¨È=Ó›¢{¦)î™6rÏDü ñ¤Ü3m¶Ê?s¾nÒAÑ1®dºpÐlu^:4ívÊAÓžB9hº„î½"ئ‡¦ »<4竚6)ä¡i½i¥Ã©1–‡¦=ÝòÐôzéÞhÓVš¦¹\4½-êÐ*ÛIºh‚¥4Ýä¢ùÞògs£ž?xá¢i÷A.šõðÊAÓf‰4g õަÜ3ßþ÷l·}l†Ò=sÖBçL[ÜGõ>9gÚøÊ9ÓF*œ3­/rδñ–s¦_CçL,8šErÎlu$.3íÝ(çL›rΜw23ç›/3çb˜Î™óÞÒ9sn%éœéµÒ±ñ-ñd4:gÎÅ23瓛ΙSƒtΜ[ÇtΜ#œÎ™yŸÒ5sλtÍlc]3笧k¦×* j®¦kæ\°Ò5s®éšÙ>ÏäÙš®™sEH×̹¥k&âög@º5šrÍœ»µtÍ´þ„kæÜ¤kæ|E¥kæ|zÒ5³ÆSŽ™íJïªtÌ´Zä˜i-Ë1s®Wé˜YóÜó+U(ª7C©lùɶºí ðûÇ´Õm‡¥©n›G±dªÛæa2™ê^ɾpÝÁ²S]ăòƒwçåÓT±§<~fd£‘½C¶:—„ [îTì嶺;"ÍI`·J°@RÞŸv‹$4X$¡Kv‹$Àh‘Ø-’»ˆæŸ¾™Ò¡~—% 2Z%ãÇÇUv‹$àn‘ܹ¤—Úâî–2AFK™ »Et·Hî}ý]:LIêP’ £Ed´H‚î\Bº[$Aw‹äKÒÝ" 2Z$Aw‹ä¥»õ÷øÐj|é0¾t Ý™Dt·H‚îIÐÝ"ùÔAt·HVÉXµ º»#N¡ÇÑ\$Aw‹¤tHÉ^:”$Øh‘Þ-’À»Ex·HJ‡)IJl´HÚÇ5w‹$ðÎ%ä»Eò¥ùn‘-’à»E|·JƇVÇ—LJ¼åwžKx‹$o‘|ip~i@À[$H«d|èDÄ[$x‹äC žÿ&â-’@¼Eˆ·HñÉ—×—D¼E|´HñI Þ"ùÐáþÒˆ·H‚I Þ" Ä[$x«äS‡ûK2Þ" Æ[$Áx.ã-¿¿tx¾t ã-¦ËpI0Þ*Z‘ñÉ—d¼E|ä2Þ"Ù×¶Éx‹äK‡ö¥o•Œ­Èx‹$’üÖ¾th_:ñIPÒ"9ÖÞñIPÞ"ùÒ¡é@Î[$­}hEÎs­Hz^f|é0¾t é-’óXê%é-%îÜßU™;÷w%)JÒÚ§¤çÞ¨$ã^µé-’=÷w%)J²ê¤·ü¾sg4%ãÇÇ5O_ué-’O Dz.!é-’ýüЉ¬·HÎýC§ýC‡ýK²Þ"yú‡Vd½EÒŸ­ö/Ž/Èz‹ä8>´"ë-’kûÐ ¬·þþÔ¬·HZûЊ´·HÆý¡•²Õ¸äK‡óCϯ„l??F¦óxì²g~%ýmɯd%fy˯ô“kþB~¥µùkÉg´Ö;K-y‘î÷û£ò"å/¯G2«'%K=\yšò×Re^$^ÏK×1é4ZúåõHfõ¤d©çg£¾Ö³Þ »7ÿþ|ObøŽ5ßÓ†üû»¸•¿éC_å†bóðÿW£>R?}̬±ï3%ÎǨ>#¶Ú•ŠWzJ'\½$tR VFµ¬É¡X“'tBMK:'ÕdeTÓšJ5Y:§¨É“9eM³LÖ´$†RM–Ì)jòTNYÓ,“5-i¡T“¥rŠš<ÝSÖ4ËdMÿJº§«‡ü×Îöô‹…û§Ëå×Rýû,»K‰?YîÿV¶§™r%Ú–¿‘Îé¯çkB © Ÿ²÷ÿ…$M>¡ŸÿÙ“4ýó'IšþùoMÍô>HJÄÿýŸÈ25ÓùüIj¦ ¯ûaðï#× ¼ŸÛYöÇÛ¿È“’L2™ÅÇÎh3N÷5®8|„¸oŠs>î8|„ n2zŒçV#E^ºF s >8Ê@€Å.B=-Àï[Øqõtn½‘Gê]í¶#SºÜÿ³³³[Õ&7®ðù\ÅÎð¦õÛÒa1˜8˜`_ABíÄ`|ùÖªZ«$mã™Íl}ýv«ºõ÷h•ªž5Ú­;0¶a{Ìd/fÐõUbaí¤o˜^R,,|ÎÊÕžjaáòË$/i>¦[A·¨ðyÍëòZTø5„1/D{Ìl23 ]{¦…T_(O)·¥Ç¢Âcè±ZJû´2áÏêçÜÐ_[TøÜ+ù·D¦’É´ä&àÙ4<5 Ÿñnfê~uMÙ^ ŸÛ˨õ- ÝÕF6¬YÇŸžiCÌ Ñ¬²HÐõ~t^“,EÎZÂÓqºåµj±¤^ƒW‹l_±¨àÕ"Û/ƾ¦gÿPÎ19Û‡ªœ3;&g~(ÿt«w¸ÈÛÄk܀Э”â%yø‡š'úS^'Ó¢ô§zÞF8[/iž·±<̤ÓÚ_¾âþÐ†Ì 1ýÆJø.“7žÙÛ°Ï@³sò¯íµÃäŒK$^%–çƒV&·ø®÷T,M:벺©ÙÔ”år­ñ,ÏÞxM·!®ÑÅê‡ÖŽ?×܌ϔ™6§cfN>èÒÌÌÙGw\íX ™I«‘zå2 Èê==Ó€¤’Ü)±ì#RÇ¥û˜Eò[¼ñ©¯¡/Œëõ!õôQËgÙ^̆ªœW½ Û Lôi£c^ÆY9å:æåìÜ׎½”×mšœˆ{©¶¤k]i”z¡MI{¡ çr½ÄòˆÛ–yÍÈþ™^½­2“wŸG×ÔÇ×t]ù–Ö‚ùñúùʰWÚ€Ëkƒ‰9ù(âÓZ¯ÅÖC;iÇb‰6ÔÖüK5vÝŽåŠ}©ýlÙÐÔ+mX]Ì'Õ¾pÀ¿TãÈ×Ûãë!T"³dú—RN³¾&çïm[ˆ¹Ñd]ðÚ4Ú'§æŽË³¿cÅöLÜ&s‘ÜѼ«÷t»a ®Iú0mdöÿ“õ¯š:L®¯wßA;ç÷^ýÉ,‚^Â’<üMùŒÐ13Ã"¨‡,aý³²rö.Ž}]$“Øû[4r7Öoørh}9]ã»2@uŸwûKrc|líå¬%Ïè?9ISð6ýþÃV8ÑÈ«SUb(îaÎÍ2qòšêFÚ×ÿ>ä?“¦Áù `¢dxôø'Â)8ÿÁÑçaÿÁe‡54þƒÃÎq™ /0š p@¤êêœðE÷­I°)mðp„#‚O‹@Ò3y+|ºÙ0WÓnºÑÓ\ k^Àù*±ø3„ßÄð%+GüCIÄ¿¬ZpÿààAtrJ)ˆŒô‡D·qúKÈ÷Ã_9ýeÓh?7üÁâ!J9üA¾á‹!üåÕH…mNÀÓqÀd—Ì»8üËê ½ þ’Bç þJ~Ø„¿2F”8ü•*QDðWà¨Dº"ü­É«Â_E²S^#€ÂÓ€¿$¢1úÃÆ.Ÿ$ú[­úáoHH Ið$ý!K°CÒ诙;Ö熿Õ?^B›Ãt¥.ÔãX¡Ü 3Öú„?€yÚàs"[€ÁF2RÙ©°xSg?pÎàƒýÍëI²ÜìàWåf?8íùÛû­wÅ®AöÈKÈ~b‡×‡ì·¦åÎûÀ„ÙÙn¾†ûÁ ‚èBö³ÔR^àè×ARü‘³_Ëø›"ûõ7úÙ9‡È%d¿»ûaPµ9û­YZ]Œì×û~ï‚ß:øõ…6\›üúZy š^dUç5~pKF9øí$à?8[Ђ__«üL£3¶d~sYàÜ÷b‚a‰sŸEA<¸ØÆnñʄɽ¸5Põœ™`+Cî{qŽØ û2›½–؇Čl‹Ä¾"[؇´¦*qjz[`(±ÏœJø,Ç>$ì&5öáIœˆ}p)y.ìC‚Göbßx¢6Ä>$¯xUâéQ‘wTçÜ·¦ üV•0KòCÒRnå‘üð’8Z’üà¬ÂþMòƒkŠÀä‡C¡ìï$?¤!÷E‘Ÿ…i#j¹ È´=Éy´d8ç&$y~IlN~ˆY;.òCªX.xI~£-þI~H‚NJ"ù¡¡L>k0Åkáàèè·S› ýÞwš³ßN0-öCmÈ‹n°8^âädñéø£Ê ©ûQŽ~ø0\/ýÎkýlIâëE¢²sµmè‡õì7º²:‹ý)”¯ì·36‹ýp彨ÞJ¢A·`7H±–Püàd?lñ‹ôœýF×V¨Ø¾Ééb¿êÙÙç˜IEÆ~c­ØõïÎMÖ«I‡Î~ëq–8ûV‚Ùœýðn^C 0™TI Š’¦‹ýF–˜ ö%ð›ì7ãÈ ˆ~Ãrz‰™`9›ø·›°æ9¢ ÑÏ¢¸_臱zD¿Ñ*ÛÉo¬¹º]äwØMòÃhݘXÊL/qr«íMâ—“Å@òkÛ d ?<‰¤Bò;žDò–¸ÒKœœpÄ›$Oô[‹wj B?xžñKýð쇬çè‡ñ—»¤¿Ñ¤ªˆþ†eõd‰­†ìt ¯qú³“ë$¹lW<„A‡¿™ö4á¸-MÀa÷ þp”ˆ–ðvà^áøÒó)_ào¬1”¯TBþªwr§„ŸžÐÉùáPs½ô¿¡®¡ÿ•Ím®ÿaY{âŸYÈßPýË:“)õmˆžLTÿÞ´¯qõbš4CWÿæÔÑDÒ>)Ïû‡ú7bÉúKöýOWÿ;¢HGõ©Æ dd'„4à5b§¤$Õ¿TnJþ{jì™RþË];’ÿ"°Â¤'pyÊé)<¼À鯔Úž©5VJRÿÞ0AêßûÖÄ?PŒ¨RꟲX‹ÿÀvóâ¿làð¹ñï %‰`yÊmÿz°ùï}¶èì””P™â¶ y…ó_é6ÿ’Æ.á_™µýaóë¦?ì]Ò_y4P…ô—8n þ ”Šx‚¿Ê![ðg¾òD2Êf-VòëAT BúÓ#ø+o ‡àò91sKlÓ’þà-Ï;Sú[-@FéëÅz6X@;¥&úKYß›ôW¬å~ þ€xüwþŽëþjy´Þ&üá)ü°„¿Z£ÑKøC´+B¤×¿ÖÐu u-z%ÐQ7Ã@.œ.f†ŠKøƒ(JE›ðÃÆðÛÏüÕµìc9„¿[÷«!ÆI÷Ñká¯_ðw( þ°ó$tÑìyù~¥û­ö ܺ[ÙR%—Û®û¥èÇÒý°ÕC ¤f¶7ˆ¨ÞÝhç¿"þA.þÕwè;ÿ*aB#u¿žÄ¿Ãòö¸¹CþC{e×uÝ/§¨Í¶AX)írE:<%ä¿f§Ý>7ÿáÛ‰äœÿއìW¸È Ù/´£ý‰!ûIþÁîÉWýâ=ÿдÙ7¤ú…´%ü;öh¤ú!ÕÍ¥úA/fß–ì·¦5NYÄ¿-‘…ð‡éƒ×H¹ !_Â_hÂ?tÄ\þbs>„¿CæsüƒîóHæ{Ü*íÿUBÂ_|ªþpâ”°Gá/zLÈEØÛ6¨>þŠÈCÊßjý\CRù“îÊüUXBé/´êþ’¶îBúC(]þŠÊÙjµT&$ýmNÒßš;æÅØw#KúƒŸNòË–Béïi²Éµ¿ªy-´?Ä#·Qû+rr탷öí8´¿üp4 í/7Y)íï …KÚ_ ˜—öN"¡ýaP!…™ ðŽ¢hºÙ¡¾Iû›Ò¥ýí …ö·êÛÉmÔþBÎí§1/þÃ}ø&¤ý%¢(E³«x [“ð·Öw'ýÁd©„¿-‘IøÛR¥„¿­ˆ…ð÷èÙþVm÷þp¿¢[“ðg¾>¿;t¿­ØQ÷Ûj–t¿; ®ûí…î§mâÐýj¼t¿ujmþ°Ì¦¨GáCŸDá/§/ô”?¢ 83O–¢l¶Ö›â6Êfû;Hú+ÿiº–}¼u¿úªgK÷Ûj§t?œšác¨ûíÏ/Ý™†½€²ßnŠ!û5uÉ~»)Jö[ÿI’ýþ¯dNTû°Ir©}X›z`,!nÀ¼`o§o&ìaùš.ÚÛ‰8D{Ç x¤½Õ…l´‡¥ýCeÏioÑï«Ú8ííhPA{Oì"»¯çº5á^’{ qoƒUæ¬tÂq¯mí ÷rHF½©$³Â½´u^Þž83U¿àޫŇpK /pÜ˰ütö,áʸ7µßŸþÂ_U¸·]2…{táŽòòå÷JJá4JÞ[FqY&Þ+Û‘“¼w8eÒÙ³„ú(Þ[ä+¼8â²1œ=_-4|pyc õ¾¡}åpö„ÞG¾£V¶}åì‰ñæröÜ£^è}pýºçƒœ1Òç&¾S–£V¶ÖÇrÜtGÉ!’ÄÝ–rßÛ¿(£_ć®,’¤\&!‘RïÛ>y$¾þh-ô>sÌg‰#$Té}1R;òõ²7—ÞðÇ#óAá9óAÌ“®HÁ¯‰,üϸlÁ¯†Ã˜¿™7á¹^ön·L ~p%žQðÃ~%K(øa\ ã™à÷ÈÍ™6²‹Ið[ÍSN¥ürlkúé+¿ªñGŠßZKñÛ¥?| ÿNRüÚPC—â7÷¯¨øÕüq@ß¡5…æ[„>øÝK~t`ÂÎÞ"Í/‡/4?¨ñJ~[¡”䇸ATâÜ>´‰Ì×T‹ùÞ¢•›˜µ¢TkÌg™ùšbãHš_ H2_Ÿáy*ͯ Iôƒrùz"â Á‹šßZær£€Ìwê‚ÔË«˜×PókÑŤùá»_šß WTj~p2¼5¿.§Š)Õ2‹Îç–ËnOO܆ï<$¿ II~%ôGyX>V_ívPñ«3ˆPŠ}RBð+áHàÃM(OIð[/†>Äü:Fo½ïåB+ô¾G‡Bïk5ø“zŸóþÜÄ7p¾Ã ¬þÏÖàXÿ­2…ÜWD’û0ˆ)÷…KBè}MkÒÐû²¼‚Bïƒ/¯¡¨ÄE|ÉÊE|x¡ôz”ÞO‹ÃÓÓRȓݤ÷ DI–z’ûzŸMjeY0$µoÍÌìRûÖ<Âïj_ÒÞˆÔ¾ÕsªðÎ¥2LkÒÿ\í[³÷sùzâ;ЯØÕ¾Ò$±’ù „Ž[î«3Ä=šòKî[÷—¯§Å|c å>äÒåú#ªä>ì—¼,qàå§™zÒ' a^rýr÷ÄAèÆã~E®’BÀµÈ7MCÀ´Ö¯ÜÝs ¯®1|áøðpŸ»{ÂÙ´ž‚Ÿ­“˜b™îž˜Qt¸Ï}ir.5wÏ,,–·'7ù[º·'fª'ôöŒ3á"@$2žíòöD«¯'¾øò,}œpH8t>™°äˆ!…YµI€¨á(çy?„;cè=C@ oYÀ€ÂH¤.äˆ(›“ VG@Œ‚ýBÀ³ƒ ûÏ5Þ4 ƒ­ŸQW‰€h|Œ…NÄä¤oà8qþB¢äÌŒY*›çuØo`aOyÑñKõ.7Ñ쑚Ì™ô7q^š½ÉéïHŽ`ø‡Á¸ð¥8þabŠß;Z>5¿#-ño9kþБ™ã“ø‡N¯„9³àˆÜJü›%ö4œþ¤ætÒŸù¥œþÎFúÃt2tðõPÓǃ܂)/\g?ôôGøeä„©L¯×ÙïŒKö3"•üá>ó9>Ñ âšêAšw“qøC³{„vççüáå1À.áï´ÚáoÛäìgž@Aœý`“Æg¿#D0ÙoÀ¿wžì‡…Ó1“ýà«Ä0¸d?„õR»rö›OˆõŽ~çôC¿î”’ýŽÆIôCeúåíiž‡õD?"—Ìü%ëÉï£ÉI³zÚ¡á䇰ŸòíizF0±RÒ±?c¦°À°½:_žžø°¯d4i6r‚ß„ FLuð;êü°ì¡t`àwÄÿ6ðèâ?¼;ÕÅÉïX:‘üŽ”$¿c("ùá>›Ž~Þ'ùD¿#YÑϺ¢ŽúÁnæ"ûá>E\z®Vãðg+mévyÐ*v\ÂîÂÙ‹ðw,¸Xî1§8áïžN¦´G³ál7ÇGø;[…âïÖ±áïP è ežÇüðÑ] ІնœþÎ6êø‡¾ ïÏ×ó†tù’þÐ5§ìªKÕ{ð“Gõ¥ÊGêœ[Ð,¤àgžé|1ùàÊÄõE>¸õ>—O'z_»œ:ûˆ£@ùúó†\çXK¥çŽc¶Kä ©’M° ¹¼÷>!=PÞÃÁ!®=(ïa7X%^{kyä?ׯ°*åʇòzŒdB—÷°c\O¶;·Ü)ïaCð¹ô=ï Sõ=,˜¤ÕÛ)ß²¡ë{ãéáêúvEŒ„úž ×¼†6´aB}'*ú wÇñé{8fÓ¥æù~Pê¡Ä¹¾‡>WO¸³W „ »§îl'_Ac\ß¡òKßÛþõÒ÷0vëÜ -H§ƒúܳÙ>¨ïá>ô£¾g‘Ý ]®ï‡‰¨ïa•‡¦ë{˜µHa0a¾!`˜¼‡Õ¹ä?ׯ°Ó @—÷,õ ùÐå= u¬‰«{£¾á‹Éúc‡^ZÞsïÑIÝðLèri ó›Å= ¼rØtq¼P ÌuÛyâÕ—–êžMæ„9—ư^&&PÝ›-‡Ë¤«{`*¹kº¼‡ÇNÊ{X¾ ç܆Yct¢¼‡ N—÷pM¹ŽôaÑG$1yoâ(ÇåÒi˵ðÖo¦~Ê{¶¾Žôá{ëŸË{Ø@*1yoFV^é{¶‘ÀÚ(¹Îô; Ô÷Ð]¤º¾‡óÚ”æLßCXayº¾âx/§N¬8§QàÃT«“w.ŽÙ4J®rq Ë~9ZºÀgKÊn.ða¹v |büu¦x.bsq §Ðy‰kc³Ía¦ï!£å>—÷öÛ“¼7± H¬¢u;gÒ‚—Ǥîa¥CM€ê>8#.PÝæ„À¸ºgµ¾<:aÒEyëš.Í‚ê;Ô½9ŸÐò\ݳUªü77ª‡—¥«{¶my賌,qml¦÷‹º«¨ÄPÝC–ÅÕ=4?!œ«{ø½Å¨î!|TB³‘àyªî±Xžñ ª{Èzñœ˜·~SÃÓÕ½YJêÞp¤îaÇLOry ]áŽæ‚V£û¸¾g«7*~®ïáWê{³Ó¿Þå=¼†zÈ{É£.yoÚÒÒK\߃I\Sß;Œ¤¾‡0 üÔ÷Ð{(ŸPà›-…«¨Ëch4"J—Ç0ÚÆ)ðáWåÙ³†Nð=þ·$5Ú°%¾=KâÛ/† ^Ô;Wø0ذzTø00i‚­¾?ƒñÒ45ÃK\C Þ˜ºy’߇ɾ‰¸›üYq¸J[hÁú ãréÄ@î§Â7_®’Ä£(³QâC7ì—ćޠӆΔøæ—rJ|³—ð¤t‰×ôã@ß„û¸ÿÉ}ØU'®Ñœ¼¼:¹û,yŸ‰ðæêÞ|åQêF‘vžiï¥îá6P¨¼ÖwÎ4Pᾉ=«Ó}ó»B²+ëÙ=ˆ:vÖûKõ.í,gTïRdsS°¬þ:Ÿåê<Øù#Õ‚PoºÄÅ;lPM;üèïpÛ,¿K÷@…nSÎãzGõv‡$I²»JŒìPr…j¹.1°C‰Ä§‡&”ð.5*: 뺄'\Öõ´%@pþ– â\w•Ѐ£„%†F(Ñ®«ƒÝUb`‡©HvW MØ%™6DS‚Ý]2iU:¼7{Š|jÄ;”ˆ÷ŒîºÅà1;š‘bIw(áéN¹Í>ƒîP"}Íé%Üd#Ý¡D»ìNwk  $k¤;$#ëï©Ü¡D±y@wø;×ó¼ÞUbt‡’¤|Fwȶ6Ùl m8®16º®16:Kœî®£»†ì+TçUb64ó-ÛÑZ®¿ë{ÿmtwÝÃèî*ñÞg -X͉  Òù†îÎKîvÚ9².Qä%g;”HŒt¶ëæÃkê—ß´~ÿmhtýÂàî*1¸ë¶±pÒÝQÿÎúÕw´; ‹PЯ((¹•»þl¦·~Õ¤³þG‰aÑUbXtÝÅÐî¼ÆÑÎ̈Ð,™”´%L´;Òüí®_]×Ú]%†vWIo÷ßae ¢]7G¯ó´ÞYâhwÖØÑî.™_¬r´»î6Ä5†EW‰aÑYgG»ó]í®+ í®+ÂÍj3l÷†£Ý]¢äŠº³£ÝUbhwÝ9lˆ’°!JzýZòZOå¾Âàý]²€ÃÝUb64ÛÖ:áîº&{úm5îÎc;ü†š4Ùî¡ÈvXÌMá«ôCþžÆE¶àãlwþílw•ÛÝ%ó£Ü%fÁUbdt¤¯$Û]%ÆvGÒK²Ýu±ÝU6D mÐß`»#)&ÙîH·I¶»Jò MíòܼJÂÕ×Ùî*14º~elw•Û]54¶;KÊw÷ßóãËwW‰ÁÝUbpwÄ$Üo¯„²Éáî*14º~epw–8Ü]%´Aw©aC\ahtÖÏáî*1º»JŒî®£»«$lˆ’°!J¦+ryN¼;ß ãÝYgàÝuEØ%aC”Ôþµ¤µ/ßÊñîzÒ[îaÁéî, QàlwxRÅ]<§â.È÷¿Ï ¹ ¢îzo=ê%†vWÉ[¾|#g»«d¦/ßÈÙî.™ü"^ò3ò«<æYù=ÎN­ùÇS_ü÷¼æÛšøõNRò«o¿€Ì\Gýá·úçïwÙÿg_ú‡+Ÿ Ž@`Lÿݯ¿ûÝßý¿îýoÿý +„9æÿµô¿ÈD¸H–‰Âi?åu›ÿü¦»üÇþé¿ß÷ÛU]ßç¸ÉovþðWì…?fÕß«ì·ß~~½ÿÈûøçe†_öO×=þZ¥þÆ“ø?¿ü†x„oz÷›øÍ7l\¬7Å>ãÕì—ô¯û¦úã￱Ú?üþb®YìKŽì<ÈRWÂnÏÀîÁƒ°–#J~FÐXÞËRú­ÁfßK%?/‘n‡ó ý¬šJþöÁVÝbMØY;nÁ’Ÿç&­ÛÕiêÇíXòãÊ»~†™j\µ`ɽ£Ë3èâz Kpù¿|÷g†¬°)endstream endobj 6 0 obj 215022 endobj 4 0 obj <> /Contents 5 0 R >> endobj 3 0 obj << /Type /Pages /Kids [ 4 0 R ] /Count 1 >> endobj 1 0 obj <> endobj 8 0 obj <> endobj 7 0 obj <> endobj 9 0 obj <>stream 2020-10-09T14:32:02-05:00 2020-10-09T14:32:02-05:00 GL2PS 1.3.9, (C) 1999-2015 C. Geuzaine gl2ps_renderer figureOctave endstream endobj 2 0 obj <>endobj xref 0 10 0000000000 65535 f 0000215572 00000 n 0000217085 00000 n 0000215513 00000 n 0000215380 00000 n 0000000266 00000 n 0000215358 00000 n 0000215665 00000 n 0000215636 00000 n 0000215729 00000 n trailer << /Size 10 /Root 1 0 R /Info 2 0 R /ID [<83134DE97296D99FC270959E0ACCDA75><83134DE97296D99FC270959E0ACCDA75>] >> startxref 217305 %%EOF blis-0.9.0/docs/graphs/sup/sgemm_ccc_zen2_nt1.png000066400000000000000000011550351422157504600216620ustar00rootroot00000000000000‰PNG  IHDR¬táÂgAMA± üa cHRMz&€„ú€èu0ê`:˜pœºQ<bKGDÿÿÿ ½§“ pHYsNNÆÊ/¥tIMEä !1µ˜¬ï;zTXtRaw profile type xmpH‰ÍVK’œ0 Ýë9‚‘l ŽCc{—ª,sü<ÉÐMOÓ3™ª,ÅÏ–õž¾†~ÿüE?pL<'’MºÍ–tRћ˜”µ¨é¢M*[ë·Û­³a|Ñì#Ťä*)WKY ;ëBy¶Õ°°ˆ­¹•¬xB¡±I—–VPÖî\mÖÉWU¨Þ,žÉH€ÀÒÊœ¥pÞ²2*l– ­ÕùêÄÉ¿uÓfâsÎQ':pdwñ0æ¡c·0kε$öïŽsûÅÝAÂÜdÁ5q•I„70T;…JÓŽ÷'Ì7Q;x2¨¬àŸÁ€t"9&èlg’¼ºÅÁÍ Ä-w€.~â-L#<êP‚§bå¦Ù gÓöì]Êü G!ÜN1iHƒ®•»/pd˜”ÜcÏFåcÉÎHö¦ÝÅÛ5[4rȾRF¤20ÀD€r"ŒhyD üèþÄ8‚c¿g\dÕ·œ½“»=ÓCÑš«j ¸MΨ@€= îIéw˜T2Þ³¬áîÙâã%Þ“luWJg­C騰]Ä=PÆÌCâ –¾{©ô€¥"(€²—£4ør. AK{x]"Æ‹ îÇBÀ®‹ )=R²ilŠ~ùžNFaóÈßÎÈÖW.Ã'9û˜3zJü3õâtúh jÐsÈËVèšÃCÅÁáîĆһú:)Ýô>úò/à3زÑþÉù¥õcEãìåç/’.RÔÆýW×Xký&tdcaNvPÏR¹7€IDATxÚì½}œWuçý•%Y’%\ ¡Ø”,¿ Æ56fØê`CDÙžáÙ°²VwÈ ÏNèÞ$xXHw˜ xÙgI·Øˆ·ì¢éÄF¤+HŒ3e¶ÆžÂf"${JË–eÉêçªS]ÝÓÓóÒóÒ3s¾úè3ÝõrëÖË=}ëþî9gY¥R© (Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(ŠÒçÍwEQEQEQEQEQEQEYø¨ð¨(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(J˨ð¨(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(J˨ð¨(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(J˨ð¨(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(J˨ð¨(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(J˨ð¨(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(J˨ð¨(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(J˨ð¨(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(J˨ð¨(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(J˨ð¨´5¾ïãºîŒ–ç8άÔÕq|ߟ—c·óuQ”ù`¼ç¹‘M™íç¿™mhç¶×ÎuS”™`ªÏøTû#Úö¥=hö<×÷ ¦óüOÅ6,T»°ê§,-Úaœ`)´ýv®›²4iµíÏvŸ`ªuYˆva!ÔOQZAÛþøLµ~*<*m‰ïûtww³qãF:;;éì윑 ×uI$³RçD"Ñ´Ž³yìv¾.Š2×xž7æynfSfûùofÚ¹íµsÝe&˜Ê3žÍfÉf³S*_Û¾¢Ì?ú0~¿`ªÏÿTmÃBµ ¡~ÊÒ ]Æ –JÛoçº)K‹™hû³Ý'˜* Õ.,„ú)J+hÛŸ©ÖO…G¥-Éf³xžÇÈÈ•JÓ4Éçóó]-EQÚÏó(•JtwwY§6EQ”éâ8ŽÚ EY`4ëÀÌô Ô6(ÊÜÓ}zmûŠ2÷´Òöç¢O (Š¢ŒeÅ|W U|ß§X,âû>†aJ¥0 €b±ˆçy˜¦‰mÛ8ŽC*•Šöu'rM&“X–?:™L&*ײ,’ÉdTžad2™¨œ©n?Ùl–\.WS©w³u“EöH¥R˜¦9©u“Yßìœ&{äžF÷RÎy¢kàyŽãL&£Ž‚mÛØ¶=îó“ÏçI&“†1¥}§r­ Èž¯ø96zn'ólŽãày^Í3¿GñúOf_¹3qî³¶ý©µýVÛö\´ý‰ÚïD×ÀqJ¥Ò¸ÏÊx6¥Ñöb,Ëš²]™ì½¨· ñºÎ´mÏ.4ÛWîñR· ræË6LôÜϦmXv¡Ù5h¥O ÷_f@'“ɦáÔ§r­Û¡OÐlmû‹¿O¿.°0Ûþtûñçe2ý‚FvA–Ï„mX(}‚…ø¾0Ñõkf´O0õ¶ßãÍ®ÁLô dùRjûÚ'жß}‚VÚ¾Ü×Ùè,†q‚ú{¸XǵO°0úS¹F­ŒÀÔôƒÅØöçê}`A{<ú¾Ï¶mÛ"P*•"wÏl6]™Ùÿ¡ÉçóÑlß÷éììŒ~XdïûQÇ2î›ÏçkÂjLuû‰Èçó¤Óé與ñh¶n2¤ÓéèºxžGgggTV³u“Y?Ñ9MöÉ2˲p]Çq0 #zè›]Ïó(‹lÛ¶-:V"‘hxd²©ì;:;;£}Ç©yÞÆ{n'sãÔw ‰DÍ6ÝÝÝ5Ïu³};÷ÙFÛþÔÚ~«m{®ÚþDmp¢kJ¥(—Ë5?0±M©¶âva2õš ãÙ9öl؆fva¢}AíB|ý|؆‰žûÙ² Å.4»­ô âç9Õ—¥F´[Ÿ`2û/õ¶¿Xû°8Úþtû0ù~ÁxvA®C«¶a!ö `a؆‰®_3Û }‚©·ýv'hv f¢O çºÛþBh÷]?}hÌBè´Òöaöú }œ–Æ¢ö NŸ`*ר•q©ÛdÚïblûsú>PYÀ”ËåJüFFF*¶mW¾õ­oU€ÊÐÐP´Î4ÍŠmÛ•J¥Rª•ÁÁÁh}¡P¨†Q©T* R(¢u–eUR©Tô=“ÉDeMgû‰*™L¦¦n²³u1888æºØ¶]Éd2M×M´ïdÏi²×¨¿¿¿TlÛ®˜¦Y1M³bFt¿š]y&r¹\Íz 222­S‡‰öÌ9–Ëåh?Ã0j®W2™Œ¶iôÜÆ·mvŒ8õÏV}9™L¦’L&'Ü·Ù¹O¦^s¶ýÉ·ýVÛö\¶ý‰Úàd¯Aýó1‘Mif&S¯É\ƒr¹ÜÔ.4ª÷LÙ†fv¡Ù¾jŒšk4_¶a¢ç~6lÃB² Í®A+}ÙÖ²¬)ß³øyNÔöç«OÐlmû‹·OP©,ž¶?Ý>A¥Ò¼_0‘]cM×6,Ô>ÁD÷¤ÝlC³ë'm¿‘mÐ>ÁÔÛ~;4»­ö dû¥ÖöR»ovýô} 1 ¥OÐJÛoö|LTöb'{¶ØÇµOÐxýxÌgŸ`*ר•q‚øsÑhÿ/}éK‹ºíÏåûÀ‚öx”Yfét:š•R.—¹çž{°m»fZ2™Œ>;Žƒišø¾¹LËwQÐãû†1¡ëT·Ÿˆ¸‹jýlºfëšQ*•Æ\™õÓlÝDûNõ~Mtâ3ކ††"•JÕ¨ú]ƒ¸kº¸Ç·Êl‰øs1Ù}'ƒçyc®—”5ÞsÛª7•#³Ç™R˜Fç>•™)s…¶ýÉ·ýVÛö\¶}¡YœÎ5˜ŒMæva¢zM†fv!~>3mÔ.´nâåÃÜÛ†‰žû™¶ Í.Lt ¦Ó'ð<|>O¡P˜ô9‡ö fí,Î÷a¦ûñý›õ ÆëÌ”mX¨}X¶¡ÙõkôË}Ö>ÁÔÛ~»Lt ¦;N°ÔÛþBh÷Í®Ÿ¾4f¡ô f¢íG+}a¡ŽÀÒ° Ú'}#æ»O0ÕkÔÊ8Áxûÿô§?oÛŸË÷/<–Ëe p ]¶létz‹åy^‹6þ¿]cQ/5ä>Ä S&“‰Œýt¨7R–e‘ÉdH§ÓSÞw2Äó!Ô3Þs;d³Y–-[F>ŸŒR+´ºÿl¡mi1S·Ù”©Ø…éÔ«™]€Ù³ jÔ.,FZy'Ó'(‹†A©T"›Íâº.žçEa]¦‚ö fmûK‹™x›õ î»ï>`ü>ÁLÙ†ÅÒ'€ö´ Í®_3Û v¡½™Ïqmûͯ[» }‚ÅÉl´ýÉ”=QŸ`<Ê8, Û }‚¥ÅL>˵íÏåûÀ‚%ñf¡P`dd„ÁÁAJ¥=ôPSãaYV¤Ëÿþþ~2™Ì˜þ‹úëâ8NǷٺɬŸ)š=ð“m ñºJÌá8…B!RçÅon¶ïd0MsÌ,)g¼ç¶Õk)e Q.—) S~žgâÜçmûS£Õ¶=Wm¿Ññfâ9œ¬Miff¢^ÍìÌŽmP» v¡ ¡OÐèxS}§Ó'h%9|=Ú'˜]´íO¥ÒöÇ£Y¿`ýúõÀø}‚™² µOP_Ïvµ Í®ŸaãÖYíB•©´ý¥0N°ÔÛþBh÷Í®Ÿö Æg!ô f¢íOgÿ‰ú®ÃB'€¥c´O0uBŸ Q]¦ó 6Û1¶ý¹~XУ$}•“3MÃ0j’ˈßÛ¶Ç,“„£‹™T*5æºÈì¯fë&Úw¦±, Ó4k’™f³YLÓœtc¨O&kƘIÏçkf)Nf߉H&“5ÉWe– ŒÿÜN–ø=ˆ'wõ}Ã0¢Ùf·o£s—kÞŽ³y´íOžVÛö\¶}a&Ú`œ©Ø”ñìÂLÔ«™]€Ù± “± ãíÛè¼Õ.,JŸ@h¥ýM§O`Û6¹\.ú/v$—ËM9´I»ö ší_Ý´í/–RÛfý‚íÛ·GËõ fÊ6,Ô>Aý=iWÛÐìú%“ÉqmƒÚ…©·ý¥2N°ÔÛþBh÷Í®Ÿö ³Pú3Ñö§SöD}‚øöÂB'ïKa QûSc¡ô „VÛ_£ý¯¹æšhÙbkûsý>°bÒµmCR©¥R‰mÛ¶E ˲x÷»ßÍE]D"‘À¶íhIn”<4Ùl62 žçEî«‹Ó4) 5×Å0 R©T¤ 7Z7Ѿ³A?‰D¢fÆÄTîçylÛ¶-Úw¼\ Éd’d2I:Žf1Lvßfˆ;vww7–eáy^d€Ç{nÇ‹'•JEeú¾ýHʹ‹E¶mÛ†išÑs/³ší+uv]·æÜÛµMhÛŸ<µÝV×Ï3Ñ뙊M‰Û…ø6­Ö«™]fÅ6LÆ.4³ j/ ©O­µ¿éô fòþ·kŸ@Û¾¶ýÅÞö›1^¿ ~`d>ì´gŸ@ê½lC³ë×è9Û vaêm"»1ÓÌÇ8ÁRoû ¥Ý7»~Ú'hÌBê´Úö§Södû qœ@Îg)Œ!jŸ`j,¤>´Þþ&³ÿbjûsý>°¬R©Tfö–Ï=¢ÂÊL&ß½Ê4M“b±ˆçyô÷÷GûÉvrÑÚ1õlày^Í̽ɮ›Ìú™$~&{,ÇqH$T*•蹘ì½me߉®µ<›õÇ®k†ëºø¾iš gWÖ×] ‹ w³}íßÎhÛŸ<­¶í¹hû³ÑãLǦÌF½šÙ9̬mhf&Ú·ÑþíŒÚ…©Ñî}‚vû]o…vëLgÿvFÛþÔXÌm²L·_0“,Ä>A£2Ú•F×o2¶AíÂÔÛþb'˜ bÛo‡ë6Y´O05Ú½O Ìæïv;Ø•ù° ñrû¢ö ¦F»÷ Zmí4ΰûÊhÄ¢ëÅypp0RŒ‰™LfVUö‰ˆ«ñ˜îƒ:›e·ãqÇ#Þøgrß¹8Ïv»– mû3[ö\·•ö;›ŒW/µ µ 3[ö\{¶~×Ûéçë‹mû3[ö\·]ûsy æãK¥fSŸ ´O°´Yjí~¶ËnçcÏ%ó9†¸T®ñl£¶afËžËã¶ú»>ã Ú'Ë‚µ:q·_qWÑùd¼¸¹q¦;`6ËnÇãÎ5sqžKåZÎ&Úög¶ìvv»0Û×@¯ñÌ ¶afËnÇãÎ%Ú'Ë¢ôxTEQEQEQEQEQEQen9o¾+ (Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(ÊÂG…GEQEQEQEQEQEQEQZF…GEQEQEQEQEQEQEQZF…GEQEQEQEQEQEQEQZF…GEQEQEQEQEQEQEQZF…GEQEQEQEQEQEQEQZF…GEQEQEQEQEQEQEQZfÅ|W`.øøÇ?ÎÀÀëÖ­›ïªL›cÇŽ±víÚ}'Ožä©§žbÓ¦Mó]•–xôÑG¹ä’Kæ»-ñÔSOÑßß?ßÕ˜sº»»Y»ví|W£%Ãó§ö¬=8yò$]]]¼ÿýïŸïªÌ)‹¡O°ž?Xöl1œÃ±cÇøØÇ>ÆŽ;æ»*sÊm·ÝÆsÏ=7ßÕ˜S‹í˜*‹¡N•éÜëåË—óéOz¾«>§÷Üs¼ÿýï§««k¾«2múúúèêêZÐç000ÀÀÀ½½½ó]•–ؽ{7ûöí›ïj´|K‘µk×.Š{·ÐÏAíY{ ç°ÔX }‚ÅðüÁâ°g‹áúúú8qâÄ|WcÎyî¹çü½›*‹ÅvL•ÅÐN§ÊtîõR|?8qâoxôM,ÔþM}?X¸ïÓa)Ú‚Å01¦z¯—bŸàôéÓ ¾M,†v½Úébèw|úÓŸæïÿþï[*CC­.ºººØºuë|W£%¶nݺ †pÓM7Íw”%ÌbxþÔž)Jk,–ço1سÅpÊÒa±ØŽ©²ÛéR½×ÊäÐ6±tXŠ÷Z™[¶li©Œ%áñ¸Xè+n¡€žžžù®‚²„Y ÏŸÚ3EiÅòü-{¶ÎAY:,Û1U–b;]ª÷Z™Ú&–Kñ^+“g)>‹a,b:,Å{=rXLa1ÜëÅÐNC¿c&„GõxTEQEQEQEQEQEQ¥eTxTEQEQEQEQEQEQ”6Àó¼ù®BK¨ð¨(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢D¸®K6›ïjL ß÷Y¶lÙ„ç7›Ço…b±8ku› TxTEQEQEQEQEQEQ"<Ï›W,›Íâ8δöQ±Ùþ¥R©¥kÓÌ+ÑuÝ–…ÍVÅËù<¦ Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(J„ëºM…(ÇqÆ“ù|¾f}3á¯X,66óùü´„ÇxÆ;¯øßfç7žç5Ü_ÎÙqœ–Â¥N$\¶Šu¼ë>ѵ›,s.<îÚµ‹†ëúúú¸öÚk¹âŠ+¸ýöÛžÖ6Š¢´?ãÙµвtÐ>¢(К-P; (‹}?PEßEí,$Ç©ñ¬*'K¥RCm"OG9F}XÍ\×m*Ìåóù ·‘ókÆx ԯGÏóоr=[õDmT7ñâüæ7¿ÉÝwßÝRùs*<îÝ»—ƒ6\×××Çþýûéííeß¾} sûí·OyEQÚŸñlÚEY:hŸ@QhͨP”Ѿ(Š¢ïŠ¢€ö ¦ƒã8M½'Êsتç[\œ+•Jø¾ X¾ï7­ÛèöíÜÿÔS ë$åÆ2)KÄÎzaPÎ%.h6¥^ã â±ØL8Ï£Qö«Åêµ¢i³kãFÃã˹‹Åšý÷<üpTnüZW÷¯?øàØc†÷ìÁä‰'ž æDxÜ¿?W\q}}}ãnsàÀzzzèéé¡««‹;3ƒràÀ)m£(Jû2‘-P; (‹í(Š3c Ô(ÊÂGßEÑ÷EQ`i÷ $È’þþ‰Ä¸Y3ñ­~A«¸pU¿¿„X­ßÖq~¸|9Åb‘t:=®ø%Ǽ÷¹ç8zÁѾñò‰z¿qÏ=¸®‰o®ëFu±1îõˆiŽ)Cöiä•(‚¡ˆŠå;Z¿®â…)I¥xä²Ëªu‹];©›ìïùüçãS_oûÔ§ÖMÖÿ§ÿTS¿¯> ®O>ù$Ï{Þóh…9»ººØ·oûöík¸þàÁƒ ÓÕÕ-Ûºu+;vìà˜ô6Š¢´7ÍlÚEYhŸ@QhݨP”ž(Š¢ïŠ¢€ö f‹Éä¬-E/‡!TC¬JùbÕõ}F®¹¦&‡b\\ó}?Z&Âà‘#GH§ÓtvvŽK¥,ß÷¹ç±Ç>y2*G¶K§Ó‘¯™Ì˜º× ŽòÝó<ÞóïDçÝèüãÛÞÿÔS<>oÅbqL˜W0£ë È7Çq¸÷¡‡øZRØ÷ý(Ÿ¥ã8|þ«_…TŠºººÆ”¡(K‰¾¾>>LGGÇœ»]úôööÎùù+J»0<<Ìþýû¹÷Þ{çå7±U[ ˧Û'8~ü8}}}lݺUß”%Íþýûæøñãórüù~?¸÷Þ{éë룧§§©MR”ÅŽ¾èû¢è˜áÒ3¬÷ÊA¯>W£¬0 ,˲¢u¥R L““+W½,ãâ išðHÕÛÑ4MÒétT¦a5áUO[÷=õTÕëѲjðÿük¿Æá;›6qzçN°¬È òÉ›nª­{*ŹÛnãW¯Æ®T‚ó|ÛÆO¥À4yÑ 7J¥èäÞ«¯Ûfå—¾žÇ›¾óÀ£8ÿ÷~‹}4Èó˜ÉpâÏþŒMO=ÅÊ›oæ×þîï8ô¢ñº_þl›Êž=P*qåý÷óí“'I$ܹz5û®¿‡ögl»ï>VÝq¿{ÝuøÀ–C‡ —ƒ¡!(—ùY"ÑÒ³ÙVÂc#·çúÁ€Él£(ÊÂE퀢( ¶@Q”€‰Ú¹ÚEYühŸ@QP[ (ŠÚFŒ—ƒQ„ÁF9þ RNý~?ºâŠ(Ob©T"•Jñ½½¨æ8V(¾¬ºêªha\ÖÓÃæ®.òù<ét? êx"•nììÄ4MlÛæÉË/ÓŒ<×Þz+É0áe¿ó;UJÃàÔÅ“Ìd‚°­ˆwÀEo|c jut`F*††t%™äè[Þ‚ãûM“ÃáÏ4ƒ0«–Åé;)•JäóyíÜÉ3¿þëì»â Ž}ò“^³K>òÞ´o‡.¸, Ó4¹ô¯€d2½jY¬þÅ/ˆ²MærËÑñøãœ¼þzr¹EÀH¥X¹r%f6Ëo> |lùrÞü•¯pæÆYþÀ[ÿê¯8¶nû[¿…a¼9ŒZðñ 麼òùÏçxg'ßùۿ弞®üò—9sæ ¤ÓŒd2¼dõjNoÙB(;OŸÓäÆ{îÁÈfyý½÷¶ôl¶…ð(³Šê½ D³ &³¢( µŠ¢€ÚEQ&jçjeñ£}EQ@m¢(j¦C}8Qá'Nà xžG6›<]×%NGßåï3Ï<¢£iš$“IžºòÊËT*E*•¶íÀ#/ü,ËâÔųzõjÇ¡X,²ú½ïÅ v þgׯ'™Lp߯ŠÿúÊWòîOš‹þæoxêU¯ ê$Br¸Íe==Q]þð¢‹À¶ùè®]`Û\zî…BÈç3±mžY³†Žï2–/_NÇCiÒuÇœ–ÛñúדÉdXuË-`šŒ¾ýíÐÝ ÝÝ\32ÂÙÿüŸÙ½v-IÃà©}û8öµ¯±æÈlàê{ï¥çÓŸ& \4:Êʼ€W}üã¼ëk_ãø²e$€«OÂÖ=ö[﹇·>û,oÙ² p! ¼íÌÞ»z5–eaY¿óÈ#ä7n «mA>ÏG†—ìp¹a˜á²LX7˲Àó‚0´ÀöÑQ ±}kÓ&vÝ{/–eñ¾°åçtEË%̽½½Üzë­ìÚµ‹ŽŽ†‡‡éíí­Éµ0™mEY¸¨PÔ(Š0Q;W; (‹í(Šj EYÚv ›Í’L&£ð£Åb‘L&S³Íxbd½çãC=×\Ã?†â¬äYŒ„EÏk(h a.°råJ΋žaP"ð˜{( s UñË7M.}øa~5™$“ÉâàÓOG¢áõßþ6÷Üx#YÓ¬†^ݶ Ó÷¹ñÃæË•Ÿ¾vêXß|ÉK8ïÙgY÷Üs¸Ë—#ÙMÀ#ñ8|È¿êUdÃõ=<Âþd’¬eïÓOàm˜ ×ÿùáÃ+Üÿª§ŸækÖðÖ¿ú+ì]»pŽîÏêƒyù/I2™ ˆÇ‘ð#˜‰ƒzyÊ55‹E(°m;zâˆç(aìð?‘âI p$ôȌʾðÖ·,LáñÁl¸¼££ƒ»îº‹vîÜ9Æ(LfEQlÚEYZhŸ@Q˜¾-P; (‹ }?PEßEíÔ#¢¡MDF³Ùl$ZÅ— ?Z¹€¡‘ ©ºæöÛ9‘¸)ž¦iâ…áL1 ’É$Y`Åå—W…GËÂ!ûò"—løÔ§øÑæÍn{nÃÞW¨“I$Ьxý/½”ý—^Ê»NŸæŸ:;1††ÈÅöß¹e ÷„Û›W\•] K/~1ÇÁ²m|߯ö®»è"^ðÈ#X–UsŸä>\00À¥Ë–aÞv„uŠcÆ>{žå®¬Ð[³X,6ˆã÷^®GœL&ÕëïþîïxÇ;ÞÑð™»å–[¢v4]ÚÆãQxÌ­n£(ÊÂe1Ú³õÂe‰°m¢(Sg¢v®v@Q?Ú'PÔ(в4í€ã85Þm®ëâ8N”‘r™Ñ»îŠÂ§æóùZϷؾ?òI ô||ÀW¿¨z˸öZ(yí[Þ‚G’óânŽ œºøb ;®¾‡À»Î"Î:œc7ÜÀ#_Œéûx†zK¬=vŒ­=Æý×l¾ê*†o¾Ÿ@„3gíZö¯]‹AÕQþŠØöÎÿ˜§þíßH½õ­ä òŠ÷ EཇaDžˆ"Çɨì«V‘6ÇŽÑneÍ‘#X_ aD/¶Ÿz‡ŠÇ£]·ÿ;V¯Æ¸òJ¼û·†ÂàÆûîðm&C±X$•JÕˆr/ë=^Ç£¾¶mGù;K¥RÃ}Çáøñãœ:ujRǶÉñ¨(в˜É’¥Hq¾«¡(Š¢(Š¢(Š¢(Š¢(J›ððÃóÃþpÊû% ŠÅ"Ø6gׯJÃ0j¼íâØÑ£Gk E-1}àÁ—½ l›þ?ýSÖŸ=ËE×]åI4M3(ײðÃåñpãñ㜺øbv=þ8מ8^ˆYqð¥?ù /9uŠ+7mâß½øÅ˜‚¡ˆ‡}#ár$…UŸý,Ißç“7Ü-OQ'ãÛá:Yf–çaÆÎ9ο¿æ®øÑª—‡ªh)ç-b Ù@¸ñÕ²¬†ë†!RáºîU-Ë îý4°,‹;w’J¥ÆxÏ‹EÒé4_øÂ¸ûî»§U¾ Â£¢(Ê à„ÿEQEQEQEQEQQ?†8::ʉP ›Ôþ¡Çšã85Â‘ëº sÿnßyIJnEOD±ðû«íׂ2€c/})Ø6+W®dóáìX±‚c7ÜåQ¸ðßÿ{žY³†ÑíÛ1 >ñ4¼ì²ËøôEñ© ¢¼‹~¸Í¶ãÇ0I%O¢põsÏU=ëµwýßþmUø$‹ÚLÊ+Ô}ïÏ=î*˜À[ò“šïõò¤7•JEapi°“•Ñ0ßfH>Ÿ#LBŠ×ó<Òéô˜uŽã`>ø Åb×uñ}? ¯kY…B׿þõ¼îu¯›V½EQfEQEQEQEQEiÆtÆEà¡Q¾K)?_±¢&$«ˆ“Ýx#¾ïãº.7nàøñãÁÊPØzÍí·åGÖ¬aåúO¼{ùrþÇ–-¼¾£ƒï®Y…TÝ>:ÊÚ[oeð # ã✄]5¸pù`¸üÖµkyûö푨V/î]´|9c%Á*+Ož¬ñ&œ\ÐÑ*²çx‰^‹‰ð}Üp¥qš‰‡ã!ùåót]7ò†l´¾X,’H$ð<¯Fu‡îîn\×¥««‹§>þqLÓ¤T*‘Ïçköû³?û3ž÷¼çM¹ÞqTxTE™||<¼Ö REQEQEQEQeQÒhü0©†ØL$‘'Z|0ÆÓíñŽŽ(÷àã½½QU€ÇÞö6>s啜»ôR¶:„Â[7žÈXgÖ­‹r& 𒎸ê*ެY×/¼ëÎ'.$ŠG£–gÛ6†aDÞ™j½“4÷`¬÷ œº¬We2ÂáxŒçíØŒ¸ Ü É×YŸ}ß'‘Hàº.Éd²¦þG>ÿùèú”Ëå1¡T à •JÑÙÙI&•âѾ>ŠÅ"¶mÓßß@¹\&™LòÖ·¾µ…«°¢åEQ” EG‹é¹Ö+Š¢(Š¢(Š¢(Š¢(вðñë¥öÌ3ÏDŸ³ÙlCÏÅxοF!6 ÃÀ0M~hš`𨦉ã8<½j¯=? Ť GFXõž÷DRš QhÔú£vø¿›@ ÌQÍ÷4|FÞ€)šÓ(DêtqgÚå9Ž3-ñQèîî„×ÌXŸMß÷lèјJ¥Èçó$“ɨî¾ïówï|'Îßý®ë244倔gèªÏ~–Ü‘#X–Åͦ ‡GBäíï|'›?ûY¬ðx·½á „õtQGEQ”YÄÅÅ ÿ)Š¢(Š¢(Š¢(Š¢(Š¢Œ‡EqqÑó<²ÙìXǘg£eYÄe0Ã0ÀäÃßø?ÿ'Z¾ùðaH¥xäw~, ƒ@h,)Ù&DŽ`ó=¾L–7-gŠÉæLô}ŸeË–5ï rEœ›¾ï7 £šÍf#ÕzOGãçâû>Û¶m£X,’Íf£¨R×|>϶mÛ"ÁQDC £›ú Êå2™LÃ0Xû½ïqË^Ä-O? „ÂmxÜ?~Ík(—Ëü×O|‚ôñã>_—|êS\÷ÿØÒ}RáQQeÉ’¥ÈÔÄêC)(Š¢(Š¢(Š¢(Š¢(в¸¹f¤vA.ǯ»®&‡Ÿäë“Кã †Q“Ãð³›7³óôi `ÕÓOƒapjõj ] MàɘÞºvm´o}FY6ž'cýò$3+xÿý¼éüóY>:‹á1O½úÕü¿/{YõÙv°®Tâyßü&¾ìe-]EQÚñfãL–Vb”O¦n­ÌšoZ ƒ0ÓLÔIiõ9PEQEQEQEQÚ µêº.X'ž÷¼è»C¾ï/–Y¦iâľ‘Ç#À›W­¢¸!o8v,Êá(ûáÿ¿¸ðÂÚâcŸy46c¾OY–…acÆ]×%›ÍFc›͇mÛ Ç_Ç¡³³3Ož< ˆžÉd’õßÿ>k¿÷=<ÏÃó¼h‰¾ï“L&$• Ñz„!yÿç7òñ÷¼'¸ç¶ éttÝ¿}å•A8]¹® ‰¸.k^ó®~î9ÂÊÛy¸.g×¯çØ‹^ÔÒõWáQQ¥ ‰Çm‡‰ëD§ê19‘À/¿T*ÕÔÇ÷ý1ßçR0›Ê±$4Ål!…ñ¨O N§› ¡2a²Ltn“Mb­(Š¢(Š¢(Š¢(Š¢Ì.A˜O§9zô(ÐxŒKÂy¡ãŽ×¼ Æ£±Ñw¯® ClZ‚áºuëxùÙ³ôx:æÔÕ`¬Ð8Wbb+ÎÙl6ºfq<Ï‹DIÇqÆwk6†(âe¹\®Ùßó<º»»£{–N§yðÁÚº¦i²ùða:—-£sÛ¶(„ªmÛQˆT¢º®K.Þß„ÅÐsÑ2 þ×sϱåСÀûµT‚b1ð\t]^ú“Ÿ@&©”ËÁßd2Ø&• „Êlòù`×…TŠ×^Ûò½SáQQe–q™øG²þG®^Ì«÷0¬ß>¾^Â/4£^˜¬ÿ!ÏØq§æ{½(Z*•ÆlßìøõÂe6›­9Ÿ‰ê^_×t8“'~üñ(‹ g:ů]¼|Çqj¾{žWS~>Ÿ¯¹öétºæ{¼ãû>ù|>ºVŽãDÿÕ½X,ây^͵M$ãÞ§|>ßTpÎçó5×êSŸúó7ƒ¢(Š¢(Š¢(Š¢(Š2;Œ7I½T*Ãò}l›ãÇÙÞ²,2™ O¼á @(4š&f8îdÙ6ñ£†Á¦W½Š\l_WÞ»¶l ö ¿Ûâã˜ã26Ÿã\…N­CŒÓÝÝ=F8”|‡„-q1º¶coÉd’R©Ä¾ùÍ1¤ áXëë#㘃ƒƒ$‰(Wd±XÄ0 2™ år™\.G¹\ŽÊÏUWaý™ Vè…xÞ‰|óoäoþàÈÙ6†Œ):lÜÈï}ç;ÜöÄÁ÷mÛ‚¿¡¨ˆiBw7kžy†UW]ýýUa1ÖF°L¼!!ø[,ë3™êɉiš¾å––ï Š¢(3„CcÁËcb—ýzÁ¨™8Öhûz±«õâYý¸ëº5Ç«K¥RÍoý|½˜VO|F—”ÿžÍfÇÔGñNÖ‹0?~wwwÓcÇE]é0į«ˆy¾ï“N§Çñõ"öÉŒ¦úk•N§£{•Ïçñ}ŸR©D:ŽDÀxbðîîn²Ù,ÝÝÝäóùšÙl¶FŽÇx'¬/„„tŒdÿ/ùËlß¾EQEQEQEQevQj2È˜Ž„^cY©TŠáë¯àäýV*lÙ²…àƒ×ìÙÃW_ó^zà ‘H(ãú³gk¾ “›åwœiê↕ ætãÆdÃP¤†aàû~UÌó<’É$ýýý<øÛ¿Ýp6›Å4ÍÈó0^~>Ÿ'‘Hà8CCCQèÛ|>y.†…°rx8§|×¾\ól6þ|Ÿ7~ó›\ýÐCìzüñ Ìi±ˆ†¾†Á ÇŽqÙ~†x4ÚvUxô}(jr}’ËeYVàåXO(.F$“Á¶¦ˆÀÉ+®hùÞ©ð¨(Š2 ŠŒí$Ã>ã‡Ãl$Ói>xÿý|ðU¯Â4M.´,2–x-Êyýáb†÷Ô!±\B£Ú6 U…Àd2êyhÛÁ2Ç©~—}ÄK±©MÉÕeóŒ‡\!VÌx‰Š¢( Y²Xu?ÛG…ÍÁçúÙ:ñÐõBc<ùpý÷øÌŸxˆÔø¶„µm;òè³,+Ú>¾¿mÛQùây'?Èét˲"¯=ñ¤K¥R5ùãñÓã©aäóyr¹Ùl–t:M&“‰„¿ÎÎN<Ï#“ÉD3Šâ‚¢„&Íd2QÈS˲¢DË2ÃH®‘\9/-ËŠÎ\.‡mÛ”J¥(Q³ˆ£…B!º–â­˜J¥¢N”—©ûq–YhýýýÑñâñâËårM¨†B¡P ÃР¼‘‘‘šï™L¦&Ñt.ÖYˆ{sJ2k9©‹|````†žxEQEQEQEQ¥žñ"’5¢‘@ùÃë®cóÑ£Ñ8—\úÑòpñ©S\¹iˆ‡IªaPípÛF¢bý² dªYAƯdÌD»\Žt:ïûd2Ç!•JEÇd -•Jqèýïçp8Vç8ýýý5c¢Éd²f,tpp°:&ÿŽ[n|ž'ÿöo9yÏ=<µv-o>v J%Nå+¼aÕ*Ö­[žÇ[ … TªiužüË¿$÷ï@>-Ã0‚mÂ\‹†çñغu<°f v½È'Š‚¦Yõx¯Gñ^”ïrŒ™b=õxTEiÉäo$>{£q/AédÔ{@Ö “qE™µ“Ïç#a©>|©xÊI¨Éû'â_\8´m;ÅKO<øLÓŒ®r¹-1°Æ÷b%£Uâïg2ƒ‚âäO*¬ÄÄY#er¿ã8Õ±7ÏãÈùçS(¢ñ¼ÎÎN†††¢±Å¡¡¡¨ŒŽ‡âM¯zUä8qµx8v±9Hù¸nà‰X.3ü¯ÿÊk÷w9ïß`Å‘#pÉ%ÁúL&ðl¼ôR.=wÞüføÄ'áÏó"/ÄëÿèÍÉhYð*crÅ"X^>Ï`]D³)ÑÄ¢]QáQQeñð019sæ ÞÊZÏÆÓ§OÛÔy<Š@(3d¶ëº”J%<Ïãõ½½¸ÿøø¾‰ƒ".ö÷÷Gb˜üPÇ…6×u#ñ0nTrÊöù|>òB,•J¤R©¨Û¶kc®S+°I(Sù!phh(ª[|ÿzÁz¯Àz¯Âþþþ¡0^V#!1jÕ÷ý1‰¦'+:.4¤6‘8ª(Š¢(Š¢(Š¢(Š¢Ì>ßöð¤¶s‡íÛ·óPlÙ‹÷ìÁ‡Gƒ@x¬­ ¾Ï¾ï׎CÅ"ºù¾?fÌO¨²>ŸÏÓóƒ0ü“Ÿðok×c˜ù<###ÑØ^£ñ¼O¾ÿýÕP¤ÙlUüt]ðýÚ1Hm\Ó¶ù!pråJvž>x:N°Þ÷Ù²e £Û·ÓaÛ08ˆŠ†Qe|r<Á5™„0²œ?IOÐÅ‚†ZUE™$N4¯¨–x¸Uùüä“OŽÉÍwüøñ`›ºÐŸâÁèºn”?Pr-Š—â£o;ü›¦I2™Ä÷}’É$Éd2Ê+ã9! …BÇ¢”!õð©òclYVGb½ð(ž“ñïõâ^<—aüX“¡^˜´'˜)¯k}‡&‚a)°”ÎUQEQEQEQe¡³råJÇáâ‹/„cl·Ývâ éQçBxô}¿iŽJIÛá8‘ð˜ÍfÙ¶mÝÝÝ5û$‰(j[¿m³üÑGÃ].zôQ,Ó¬ŽóyŸ»óN¶mÛD„«ï,+8f:ü•eét :,[|O$‚ïâž×%ÿ÷ÿò÷ox”˘Š…”ˬyç;騵«Z®eë“Éj>F ¯šJUó1 KxŒ®m„ÇÑÑQî¸ã®½öZ®¸â vïÞÍÁƒÇl×××msûí·3<<<ßUWe†X¨v >Ï£‹Ë©S§xrÅ“5Ë%Ç£ïûl¾ãŽè‡Û÷ý(Ir1  â™x)>¸u+‡7oŽÖ‹Èë ÃÀó<‰†a`ÙvM¾¿ú¼†ò½^ˆs‚¤ÃS e:ÓÄ…7_'.•öb¡ÚEQf–ÉØµв¸Ñ>¢( ¶@Q”…mή]Ë‘S§šnsÙe—aFUx Ƕ.Ú¾½f;´¨“TC­Bm®ÇV˜ŒðXÙM„ÇT*E¡P¨q€` 2ŸÏ‚d:ÍÙŸþ×uñ}Ÿû7mâÇáø©”õ¯¾š¯¾ï}¼õ¥/ ÄÃÚª¡NK¥È“1Êã(ãÕ¶ñ1&<†Á®‚u¦ІQý¯¿aŒŸ£Ñœ8°íDã©‹‰¶ûúúàÃþ0ûöí£££ƒ[o½µÆ8ôõõ±ÿ~z{{Ù·oÃÃÃÜ~ûíó]uEQfˆv¶.sqùÙÆŸñPÇC5ëŽ=lãºT^übüP˜“P¨•?ýÓš§ÉdÏ08¹r%‡ÂP­©T Ã0q0&<Æ=%Ôé}‰ƒƒƒdë ÿnYÖ˜\† ™xþÌ¥ô£¾Xhg[ (ÊÜ1‘-P; (‹í(Šj EYØvàÉmÛ8ýºõM·Y³f ýýý¬þµ_‹–Y·®f42þÑ1>Å~"ïÇéâ8N­GcíJ¾ûÕ¯2úÿ-:ö¢qæ±Çð<îÎN,×å©7¿™#Ÿÿ|°ýç?ÏKò*• ƒƒƒäï»/ŠÖöoþç¼þÿþߚì»çÞ|ø0oÚ´):nõÄÍj˜ÓR)ø.m;ðD„ªÐhÛÁçf õ^Š3äµ8&$í"§m„Çýû÷³gÏnºé&ººº¸óÎ;e`` ÚæÀôôôÐÓÓmsðàA80ßÕWeXèv`ýC—àããáñÌšêìœí£Áì¤gžy†|>çylzÓ›À4£xæÉd˲Øð›¿YÐÕ²¬ê÷:q°¿¿?êt4$—cä hšY:Ä…Æb±¸¨Õ™Âi½ˆYe¡ÛEQf†‰lÚEYühŸ@QP[ (Ê"°+WP*•8|ø0gΜ³‰mÛlÞ¼9Oü—ÿ¢¢GnUÆ÷ê…Åú‘¯–<‹“Et]žùêWé\¶Œ?ü× ¼ ‹E‡†Xùíoó‚ýˆoÜv/|Íkضl?ý_ÿ‹{?õ)Ö9›ÿéŸÀq0c‚æ×ÿ¿ÿ×uǦjOE×­ މDËQò,–ËÕð§™L ò`ÜùÚ×òèEát&Ä 1*Ñ4kB†ú–…Kcé·o‡L†KÏ#.[¬?oõ©™MÓÄ÷}Òé4®ëŽ é0Æ»¾rf“úò} Ûà|º`¿ÍɆÿíl æoJw_Q6q[ v`áâ7ü%S”É¡}EQ@m¢(íeŠÉ6iyvùrX³„ÇC‡qÿý÷ÙNzÉ"»߸‘"µÂ£®¯éšÑdG±Ð©[âNž³Éý_þ2|ó›øéOÙrút”ÛñÍ›xð?ÿg?ðÿâl9z”ã÷ÝžÇú|„ GF‚íóy0 žÚ´‰¿¸æR„@Ӭ指N… oc6lÓß…Bðyp°êéÐhYÕP¨RF,•2ó¬h½ˆ™áCú}}}ŒŽŽ²uëVöïßÏŽ;¸ùæ›8qâ@ñذaCÃxÎqüqúúúèêꢷ·w¾OUQæýû÷sàÀ “ö¶³i}ôQvïÞÍM7ÝDOOOKu-RÄÅÅ©“¥\\¬ØÏ½…ŧž`Õ¯ü ¾ï³ýíoWZx–E*•º>þq>KЙHÝÝø¦‰C0Sé³W]EiçNl‚N†Ì r:™¨ðÑK.áµ_ø·Ür i‚NŠî7•À£^¸½Cm‡vÁÀ µ±ìeQ¹\n)ŒA1Á† Ø·oß|ŸjKøø”(‘‰½r)’š±lÊbæàÁƒôõõñ裎iKíB3[ ƒÓí;vŒÝ»w³cÇ}?˜c’h4‚v¡¯¯ƒrìØ±ù®JCfûýàî»ïæàÁƒôöö²cÇŽù>]E™7vïÞ͉'¸üòËç»* Ñ÷E™}tÌpúc†œ✺¨zM}ßgYç2ÎþôlÍ6£ãJ>Õq»G.» ¨Ç3˜‘ÑóÆÏG(ùCÖÝsëúÓÚm\—‘r™>ú(Ï…‚ê©;ïdÍš5¸†A±P`×G?ÊÚåËa° çÇ?æºgŸŒCC<ø¼ç±fd¶m ¼M³Z?Ó ê÷dô¼`ßR)ëo0•šÜv³ˆeͨD<+HXãVûm#<îܹŒ\GGdÏž=ttt´\öE]Ä[Þò–¶TQ”¹B ìÞ½{¾«ÒÙ´—\rÉì½Hœ¾€³Ë–á‡ÿƒ'…ÇW\J2y%…çs޵ײzËÓ¬é\8bÑkÞû^‚R(îÜI‰ ƒ!b£ÅXá©~.¼ùÍaY"X•€rƒê‹À§;†GU“ú¥”aP+ÂôO»L¬¼zñ³þ÷:g"¸†eY EG7Ü6î[¯‰\Ÿdì<œØçî°.ép™žwø7~Žqÿ3©[Š@T$Áäpqkì‹«ʤٱcûöí£¯¯o¾«2.³i 6mÚ¤ƒ‹ó€ƒƒ‹«Âc!ÂûR}?xÓ›Þ¤“Ø·o5! Û }?P”ÙGÇ gqÌ0†çyT.¬0º½Öcó,ÕèZññ6Éå(ž3Ò‹¯qƒ¦!6l`õk_‹çyAj£bÒi^±};££ü¯{ï`Íw¿ ¦ÉGÏãÏ}”Ô£ÂEpxóf¶=ÊKs9ÎýÅ_pÞe—¢_x¬g_úR®ùË¿ „Gñ„Œ×od$ø+ж¬oÇÉÒBD´V1Ã(v !TooïŒô ÚBxæÖ[o¥§§'êôr}Ä[T®¦rlbËËᾉ°žC±:Û±åýT…C7\–·)„çï…ë“á2ØFUx”{ ÷¦žS\>•ë[/çÂ2ºc륌úntZ_öàƒpà ´ ÅÌlŽƒƒy^Ñ2EY Ld ¶nÝ:ßUT¦ÁtmT}D ei }EQ@m¢(‹ËxÆÔ¼ß$b×°‘Úô:«O"³fM4&d26Äê´pœæ"œëâû>†ëòo| Xó›¿a^Ƭ_Ï5—^JÏ#päsŸãÙŸü„K>úQ.þã_ÿ5ßýñyõÅC:ͧý×yéO~Â.€Ë. DÓ F×åú/}©šsÑ0‚u’Ó1“ë™ §"<Î#†aPh么i‹`tt´f¦¡¸J×'mä­!QeáÓ®v@â´?üðÃ@5ŸÚ÷Ž}ÇW7\QÇqäÌcÑçÇóĆ œZµ*È™LR$·Vž<Éu££xÂP™ª¨”©û X$ÞŠª¡;­p»|ìs}XT‹ªÇ[ž@ $D¨xÑAmxP™qå‡ÿ% ¨ìÿ,”#^“EªÞw"–Âωðo)ü,ÇH†å, ×Ûa½‹ÔŠw)jEXF?,·n;ÛG„Ä¡ð{¸~ªX(â¯,ïA¹®åp¹ÖQŽ×ÖUî©•RT…M9®ÝàÞø¡Q×*n/^˜ý4ž g/|枆"i'ÚÕÌ%Jc–¹á?±G%Jêñ¨,*&k –‚˜iæÓN¸ÓÌœ'?&¼½²øÑ>¢( ¶@Q”Åc\·¶/\¥+ÞÛ]sä›&Iu‚¼¤ïi9@¨?Îd@ljD¾/¼ÿýϳçšk‚ñG×åøïüN4úºõë¹ù/ÿ€ÏýâÜvï½|çƒ êiY¼úïˆBºþ×O|‚]e[Vðß0OFƒ«¹“ÉÚ«µ®ºý3™L Ü.!ÚBxœŒK´„<¨O;00 3žeЮv`¼8í?òçQ.œK¾::`cà?÷Øêj'ç!àÅñ\œY±" š¶=JoGDy!èHˆ'_\4¡,G­8U¦ê9(rõØáþâéæQ%§€Ý"]¬è'Þ}âq˜·—p¢)ªaK]ªáR%äh‚ªXW¦æTöÏPâú© ~•p¹E5ßb½( ãwLDÓÁðÚHxÒ$µ¹!ëCVH8Õø÷Fy.Eü×E®Q±£fƒýg 9¦<f“íÞðÄ3x䙣]mÁ|Ñh ]ì’‡‡ƒ êñ¨,&&²KÉÌ4Å(¦ÀìîÇÃ#NKšŽøß¿qOð‰ÊQÚ'PÔ(вxì@©4vbñ–·l‚P¼ôÜ9®¹ðÂHhÑqF¨@}"‹E°,ά[Çù_þ2§äy÷ÝÇ×¶lቇæÂB-‡á›&œ>MÇsÏi’ÉdH¥Rüô§?åÔ«_]-XD!•ªz+6Â4QQ¼'òh¬ÏÙØÆóOr¾i ᱫ«‹ŽŽî¸ãŽhÙÀÀ_ÿú×kb¬÷ôô°ÿ~FGƒ¦¸wï^:::¢$²Š¢,\ÚÝÈñŽY£££Œ\3R·•Áš:©çìúõüðºëØ ¬¡*fÀ½øâ(i\ðOFñ¢«–sÔª ÙlîŒgñ¡À'?ÕÉp™ˆ|)ªBg‰Z¯LÕCo„ªàU˯Ä\¬œ¸˜'!"ÄÓO¶‰ €)j…¹Aªâcý¹±cÄ»P3ÜA›€$UÑt>º@ríš…ß0[â»mD»Û‚¹d<ïe€]ÄG ½§‘Ǥ¢,&c ªðñ›Šh³ÍxÂßx¢ÜD¢Ÿ”™ 1®@)vj²¢c½€(žÞã•ßI' ãÚ<97µ‰ í(Šj EY\vÀ²j§ŸoºrŒ«‘‡ã–-[ØæH„ªøØ2Ní8ƒïû¤ÓéÀ;1 {òç?çå/9ç^ñ Êå2–m³å‚ ¢}èêâø¶mÇa4(ŸÏó¯ßúË:;«…ÛöÔÄÁd2(SGÓ ¾Çó \hL+Çãðð0¤££cF’/oݺ•ÞÞ^úúúøú׿Ά ¦§§‡={öDÛõöörë­·²k×.:::¦··wÆ’È*Š2´»xòò'øð9 ²¼šÄñÈSOEŸÏT^ Ë<Î;·åO®€þ€o„3^wñŸÛ[×®ƆÂl2÷§)“‰ó.¡x<ŠGžGЉI26¯£›""Æiôó/"ŸÛ^B‹ŠðY®e¦ÆDk‰À³3ÅØ\ˆ³ÍB™oµþìÙù®BCÚÝÌ6ñœŽ>~M8UY."£“..&&FÍ ~<üj’dãü´ŠÒ¦LÆ,T;0_ÞÉ>~M>X#6%ÇÇ'A‚A10ðð(R$GŽ¥H4tqI‘ŠlP2ìň½‰¯¢<´b·&sÞR“…È®%I6G½ð_£õ66iÒ”)«Çãc©÷ E P[ (Ê¢°7ây^SÏ7™¬ïŒ—Õo9coô±:üý>À¿+—0ô„Ìf³¼óÞ{ùð©S7ÜÀ÷Þ˯:ÅèÆ|gÓ&]pA5_a( –ËåÖ½úd+S©±ù•CSᱯ¯pÓM7E1”÷ïß_3»`ÇŽ|øÃn9VrOO7ß|sä½uëÖ1nÐÜu×] °sçÎö0Š¢ÌíjXWýþ0YN¯Z}?K`LÏg—%€àÜyײîÈO0ŸÙJø3à1çÛ›k$¡OU84© fÄÄñÄ´ñ~þ%×`ýú™ +:Õ0°vµ®»2yÚÕÌyòdbÓ²dé'˜1§êà!Cž|ÍÀ½……‹ þËÀ¿,‡`?Mš¹HP”…ÀD¶`¡Úx>V“Óü¥Ê’%C¦FD¸½qq±Ãâ",ŠgcŠtFB¡Øœnºñð°°(Q"Ož92dððH‘Šr1Šp ÕÉ(QÂÀÀÆŽ®‰xWJ}d½‰‰ƒƒ‹Kš4I’øø˜˜ØØÑ1³dÉ‘‹G©“æ‰\x,¥>¢(㣶@Q”mÖ¬ïÂfyþâ©€1cÂc(zžÇËùK®<~œç~ÿ÷YÍòž7¿™Å"¿ç=¼%•♾µwßÍ…Ï>ËÛV®äP£ºÏ†@¨¢ã‚f\ᱯ¯½{÷rÓM7E^ÃÃÃÜqÇìØ±ƒÞÞ^FGGùà?H__ûöík¹2“õ œ /KEQÚ“v·?Æç(ðÌ™3Ѳ a胑GKS²l\±‚M›6a[˜»pŸQŸ#q"¦Ú¹‘¬óMàA)9,ë=8•…A»Û‚™BE¨Š†‚ ÔKG3 Œ%‹£ýd9N'5"§¢,&c ŠÏåzÏdi³>þ”'ÄEÃ$IJ”È‘‹DÅúm­º_Dnº"AÑÆÆÇgA$"aTöR&CˆØ— ÿÅêá?9¿ñê?È Y²‘+PˆlŸ……M–,ÝtcaáãGuO’Œ<%”­”-B¦ÔKYx,•>¢(ÍQ[ (Ê‚µ¡ðèy^M¨UÃ0 ƒ¬Jz¦ñ˜Ò›¼ãáJÇ#¬ƒã8¬úþ÷¹8ûË_òå7¾‘]Å"ÿ÷ÿoþèÕ¯æ]ò'°q#_üÈG}è!²®ËH¥BΟûè-Ê£¡ð8::ÊÞ½{éíí­qWÞ¿?wÞygÍŒ‚Ûo¿ƒ¶ìõ¨(ŠÒî<‰Ë3ë×ÇXµò α’ÕkÖðÜ·‡9s#l ·¿òÊ+ç»ÊóÂ|{JžL¹µª(Í(RŒ„…xNFŠÇs’Éà¹,K‘Š<e0ß ÿ‰•”)R:à®(sŒ´Ûx[í§¿ÆëN„Ǹ¤ˆ†õá‘ÅËOlˆì#‚f–,Ýt3È`´¿†"äɾâe(Û•)³1êÁ6%C&ò”ú‹Ð˜ ÿÉ>rŒ"E<<Ê”#I™X¹êãG$$pp¢I65K¹H4õñ)PˆÂÆJXV 9-^’rnrÎqL =­(Š¢(Š¢Ì$&Ù‹EÇ! j„çy5¦iòË·÷±f‚ò§4¡>.<ú~»Ñ²‚Pª¶x‹Ø¶Í¦/î¾›Ÿuvòû÷ßÏ.ßgó»ÞÅšÏ|²cÅE×]ÇGG)‡áUgÅ»QYtœ×h¡¸,÷ôôÔ,q1.:ÞtÓM@à ©(в¨ñaD /þE´ø‰‹¶s%&Æ¿ÞÄ™ ƒ ôêÕ«ç»ÖKƒ o78ßQª"b\üsq#P×a¬ÿ+žC6v$*Ö‡XÌ“¼€$¿Z’äO'EQf‡xÈÐø‚%Š£6+™‰‰…í¤“4i Öó¹H‘4éHH+Q"I’~úd~úb +ÙŠé¦;òú“}¥\ ‹!†j<Å^dÈ#å[40"Áˆ&6ÈydÈ`bFŠÉØ?YAØÖN:±°è§?*ˆÂΊ˜[mìèxò]¼eß<ù¨\Lh¢‡NÂPEQEQfšxTÁóx' ýô×ôŸ$G£xc‹=J’$E +ã,¤ìxþK㈠*ë‹kò?Ê9ˆøª(Š¢(Š¢(sA­PôKãÂã]÷²…ÃÑ÷ó#ŒÄN8rä¿|ÇÁÎç!—㯾÷=ÞxäNý×ÿÊÈ5×ðý?ú#nZ¹Ž¯ÖÑ0À41M“T*E29ßñÍ”…DCᱫ«‹½{÷2::‰‚¤¬qDpÔ0«Š¢,EÎ{fo¹ð¦pžý~p]^¾¬“•0åSÁŸ`]zvßPxìèè`Ïž=ìÝ»—]»v±k×®1aV<ÈwÜÁÞ½{Ù³gϘ°¬Š¢(‹ŽÊ…ÁŸJ%\`qnÕªhëò+è<~|¾k©(J›!ž@âÉ(¹Úê󨉨`b’ ÿ‰Ñl°>¾®~ÀÔÛQQf‹"E$°°d°¦Ý6Õ∘8ULÌÈ[ºYÛ–¦ÊÕÿÅ'+$IÖ„)¨ÌV‰ ¨³9!B¶ r,D¡(Š¢(Š¢Ì'ç]{mîtf˹æšêÓ ¼ ‹Eþúøq¾³i/]»6X|eð0ÝŽÃ᫮ϋBÂZ–E.Wq„Ô}hZ1Í¥¹àÕhÿfb^¶®¼‰Ä²ú 'mŸ}vìÇ¥¹0é7¸ùºï ­S¡¾®ñëèC˜Y£JwÝúbl¯Áö-rÞx+z{{ùЇ>Ć ذa{öì¡··7Zß××ÇþýûÇ,WEY 4ú-X·e §.òà®=}¨æÜ|øpMÈ„8:Ë^Q–&EŠ‘ð(bA‰>>%J‘·“MŽ6v$FˆH0•úzÑ`¶øe©"ùsäÆˆw“Ar´NÙg"a‚\‹Òÿ¥q/èñÄω¼)[!îÅ=×´RVQEQEQ1^Ä×u#±àš¸8<9=x˜UË¢R(0’Épùå—óįþ&Çï»/ üá+þT?/{ÛÛÀó°,‹ÁÁÁjñÓ1'Ïôê¶ŸHœ{ñj³úKéÕ•W¢vÀ¶^|«*ÆŠãÕÕe¬Gbý÷øöÝÀ²p™Ö«XWž±~¸ü—ºÆÏ=[w>ÝT¨ýpœ›_·¿‡ùp{ñ¶”úK¥Ny‚íbXNwlýT„ã&¬h¶²§§‡žžž†ëz{{5¯£¢(‹–cëÖ®[ÇÉØ÷óÎ;µÏ=Ë«Ë,Ëj8ˆ§Â£¢, $g› á (¿£>>6v´\ö«Ïi¦‹ŠÒ>xxøø¤IS 0m/:™t0UdŸÉìï{Ľ«eßñÄKwRÂf+h¿HQEQEY¬d³Y\×Å÷ýšP¥õ:Ë\–ϵp¬<ÂÈ ºÇ¾i²ñ¾ûðóyVíø#.>u 2Èf9÷“s$“o¶5 £vÿ“O8)ɺïòš$ƒ«VÝ>fìs\è*†ûZ±ýå¿ ØT=õrZ2\çÖ•áį-…ßÅ p$V¶›ÉX½²á_3,¿+W<pƒ@´3Ã2Ša¥ü$°-ÜNγ;¶­®³¨ŠŽÉpÛRø_nˆªñk™]o)ÃŒKè÷K†Ç1²LU8öÂíÒÁçuÿ}Ý$€ñY1Ñgφ j„FEYìÄÎ>çŸÞɳ«ÀX¾œ“çÕ:Ž[–¥"¢,aòäkìårtêâˆÔ qZõXŒ ›À´r·)ŠP¢Dš4)R$I¶º³áMÂ2O‡¸Çá|‰ñüµŠ¢(Š¢(вøñ|ð[ñ<>wŽ“þï².ô|$›×eãÆø¦IçÓOsÁó~mægééáÒýo¬–QŸÓQ¼Þñ ªÛFv«÷x¬*ŸeXC„¯rlû2U±P7+¶ŸpÉðXÌ•aƾÃz§bË;©Š£"´Ùá6Nxóá1Ä+%KUüÌQ Ï/_<Eì³Ãef¸«»ÖÇŽ‹.·¨z,Š jÇÊÏE{¥þrä5K®E:Ü7ÖÈ]Ÿø­OR+˜Îã†Z=xð ¶m³{÷nvïÞÍ®]»¸ãŽ;f樊¢(mÎq<<\~ù\µ 0zåïqö±—Eß_x޵ijۚ¦Y;CHQ”%‡‹Z7üâ^""ŠgôDð318¯üŠÒ:iÒøøc&Ì5FË¡JÇË/9!PMÌy½~Š¢(Š¢(Š2›¸®åM\·n"7–¹sZ$àºP,b׬áå·÷B±„^5 ~øaúGFØrô(ë~I2™Äu]þÝþŒæ©ÏëÍØ:ŸªhUÁŽºïV´L Ž¥ DIE|KQø *ÂzÂãv†ë‡ÂãCÕûPæƒ{À`ø½›jNÃR¸¿Ô}ˆjhÔUAÑ.IªŒ©pƒª˜ ?ÂÏ"¨Zárƒ@,„ßÃ2­Ø>~¸.ûÛn+ç×_·M|èÇÿ÷Sõ Ra9qäõ,3/ÿ£Ë'ñ 6g\ᱯ¯'N°gÏöíÛÇM7ÝÄþýûéëëkù Š¢(íÎwŸú8åñÓG£ek¹Œsÿ­êj¾ X³ê©‰.+в¨‘Œyò‘w¡‡ òË_ñ”šŒ(ØJ^²x>7EQ¦G)ügbFíq>…³™ðlÅ[s&ê?_èD EQEQe.ðCÄË/¯ 8Aj=gš%Æpœ ÷¢ëò“»ïfýÉõ¬øî· Tâô¾˜œ÷ÿ@"?W<}9Wm¾ŠR©Ä—¿üåÚðn¹ºLÒªž|Ò}ϼø)x_‚@À¯<öD8”²<áL¼î²bWlÿ$µBd.¶^ê&¡Q½°7<žxNЇ¦~.PU~½ðœÄkp„jhX;..ÝtcbF!VœyÏQتð9‘]˜ïó›-t"†¢(Š¢(Š2Û<|ÛÃP”¨]ÞrËR©Õ0ÀóxáW¿ <,³,V9<ÝÝÝ ØbÂa¸ð ɿ?Ï›oysÕ›O†5%´(TBÉ(ÚTÂÊ ‰€ÏU˜ª+ª¢T=ôTC‘BÕ#Pr#ÆC®ŠðçÄ»0^Çøk’ˆ¦U1Q< ó±ú®‹{šTÅ<É¿âT¨=“<ñòš‘blèÓfLõumНA'®=1{Â#ÀÖ­[k–wuu©ð¨(Ê’à©u뀯Gß—aðò³gy¸fä6nÜȯaÖü†(вôÈ’%EŠ¥(´ªäp,E±Ej»ÅÓh>=ŽE™ÒŽÅsÙĤ@a^ëÔŠôdY¬Â£¢(Š¢(Š¢ÌŽã`š&<òþ˜\­ó…z1+Š¢(Š¢(Jûáû>ŽLD^¹r%¦i²êâ‹k¶éa£KÕKÑ.IUxÜlŸS)V:/âEœ[·g¶uqá…ý¬|üfp¿Ÿ¯LÂW.ýÓK«âœ„&MÅŽYª;®KÕËQ^Ä»Q¦úT»ú<ƒñ×&ñŒ¯¯òêçWÖ{ýM4„R/æ˜ͽœÊk˜xh.Pßr˜{/¿—ßã÷¦]ÆyÓÞSQeáâFÂÀ¹sçÆl³ùðá`¶¢(J '_Cr8Š@!áãB¬Sñ@QÚ? •œ›ò[ëÂd>sW*Š¢(Š¢(ÊBäTè¨àº.ž¸¹­_¿êup¸&üÔt2c–ÀãPÏAÏË‚kúÁ÷«ÞÀ‰å=œø‡kÙu<8îÆmÓ£v ©æ84cMÁ®þw©z#Zá2É»èÆ¾7 W 6×`܃ю•?Yâ‚§2§œ]–gÖ<ÓR*<*Š¢„x1ø3gÏÆÖ¿r«O²ôOQ”±ò7G.òbRñçÛCJQ”©#¹µý*Š¢(Š¢(Š2‡àøÆã‹b¸fÍά[Ç–×¾6Ún]Luk:ùtNÇ~!ÿ³¦ φ®t†Ác«×ñ³gÃs·qñß¿„?Jý%ß]ó]ÞùÌ;«‹„ °@ ,öS ¡÷\4 D¿ú9‰6Õ¬…ðoÜK±ÞïÞëo¢¼…õÔ{P* Ц¡VwïÞÝpùW\1fÙƒ>8ßç¢(Š2m$ÔªP9ÿüèóúçžcÙrÈå‚_à,Ù(”¢¢(K±..&fMÞµ$IJ”°±U´P”Šx;.E4Ç£¢(Š¢(Š¢Lããû>«W¯¦££ƒÓï{_Íèá†(ƒüÜS‚'Eá;ð_Â’Lx|Õ%¬~Á à­ýœ|h-GN½-‡àª¯\Å–S[ðûÐM ö¥¼"¦š¯0K ›´¹¸Ôèá5œÌ쯉;8ä`˜ Gã•pvÓëXqì[`ÛÐÝ ¤ð±£7•Õ«Wsï®{9ï›çÁýpþoWx;æ©zJ.GÙÑ ÖÑbêBâÒš§©Lóš­Ü“wïÞM__}}}ìÞ½›k¯½–¾¾>FGG[®Äðð0#fÞyç‘¡8xð ÃÃÃ5Ûlݺ•;vðÀÌ÷uT¥EÚÙ0wþJAQ–(íl Ë\¢Dš4Þ’ è(³ÍD¶`6퀃3&o«¢(sO»÷ E™Ô(ŠÒîvàÌ™3œºø¯}ßk9ÿüóÅѦo '9úaWoô¡Ô Çlþmý>½ïÇ`p©É©?¾˜îÇzß!žëxŽUW­Â0 ¾vôkh„D­Ÿm˜C¦j*¤ŒÊŒ1®Çãèè(·Þz+¤§§‡®®.:::¢uìÝ»—>ó™ÏD릃ÄZÞºu+wÜqÃÃÃlݺ•žžvìØÀ‰'Ƙ 6Dž˜Š¢,\ÚÅxx ¼“fÜ_)OãÞ‡ÃØGíH|†”¢Ì íb ÆÃǧH“$I\\Íã¨(3ÌD¶`6퀃£mZQÚ€vï(Š27¨-P¥ÝíÀ©S§xø³æ¥k8»ò| ðt”ñDë! w»[³_èD.®Î_\¸ôáK9µÿ|Øhr¶ï,|ýóÄ¿<Á·6}‹{/¹—Cî!N®< ý5;ÆXïYQ/4¶G¦e0®Çc__ÃÃÃìÛ·}èCÜtÓMtuuÑÕÕÅM7Ýć>ô!öíÛÇðð0}}}3R™]»vÑÑÑÁŽ;Ž„ÏVyüñÇ#oMEYÊìß¿ŸÝ»wóè£ÎwUÆe¶ìÀ£>Êîݻٿÿ¸Ûxx|ñ¡‡fåÜj⸻Ð0âáLEAœhŠâé§Ê‚E¢<þøãó]•q™í>ÁîÝ»§]†äx7)¼¢,<ÈîÝ»¹ûî»ç»*M™-[pìØ±ÈÖS¢´är;.%4Ow-ò›xìØ±ù®Ê¸ÌæûÁÝwßÍîÝ»U˜P–<ú~ÐÚû¢,tÌpâ1ÉÏÇå«WGËDó3üIÎÞ?âYø© ×ÙpIžC[±æÈÎ]xžo±òŠ+Èd2<ïÚç±þ—ëùÕçý*–eaYu*¢„V3ÑkN{dŠQæÑÑZí4ôxfÿþýìÙ³§i.Ç®®.zzzØ»w/½½½-y=¤R©(N3€mÛìß¿Ÿ}èC-•{ÑEñ–·¼eÆóR*ÊBC✷s‡z¶ìÀ%—\¾}û&ÜîÉ'Ÿœzá.Á,¢&?Ð5"…G Ö;T”¨í¤µÓ¤ ˜ýT&“±uÅð{7Ah†VðÂó’úä©vX¦ãí(^’¥ð¼åüë˪¿rîE&7ój:Þ˜"¨NR­û.Û{á1Ç;n‰Ú¤Ýõ÷s²4zf&süºsÝ÷[û¸`€iTbnhÇ>>I’˜˜äCÞÆÖ«Ê‚cÇŽìÛ·¯í'æg ZÍѲiÓ¦†}CÛô"ÆÅUa9Foo/À’}?xÓ›Þ]EYÊìÛ·}?P”¥ŒŽNnÌp"Ö¯_ÏŠ $—±Ï+-uÛd'Ýá98aYÛbÛÉ9yá¶ñýåü¤nÅØ1ÜpûúsóceÖ_ËtXtìØNø7MÐ9”e‰ðx‰°œmáçlø9Ö±–íÅêÕ³3,7;v)\îÄÎE®o)\–ˆ3,kP¦E™y&c fèǣ¢´íÜ'PeîP[ (J»Ù‡D4ë?F8ö#ÎŒáQ¬¤ºÁ0ï;|¿fMðw‹ç™õï„Å3+·2úìrÏá‚w]ÀÆû6²þWÖWË2ƒ³år™B¡0öX:\¡Ì s<Ê,‚ýû÷O˜ï@®Ê>ÓåCú·ß~;×^{-;vìààÁƒìÙ³§Æ…º··—[o½5J$;<<<#¹%EiÚÁxxüüùW5^)"›ˆ’·OÖ9‚OPP ¹ÔŠ’fl»¸ UQIIY–Œ}†jÇø¬¥$UáË¢*"¦Ãõ’PZÄ( Ÿš¤ê­÷¤,PHeŠ–8€JxR3V9ÇUq4î‘G¬¨ïɹÆÙ^®sýÌ­Õ°C±z§bŸë±bõl%zæt;w™iî'ç×?åÌ3í` ê‘|ŽqOhñ~Tï(E™&²3md’¶iEiÚ±O (ÊÜ£¶@Q”v²Þ¸y‹‚-2˜ôEòQˆ®Ok€§Âï÷ã`dz0âÝmúìš±½g;?»ä_ÙýÊ”y$·5®ã’H$"RQÚ†ÂcGG===ìÝ»—;wÖ̈sàÀöîÝKOOOË xëÖ­Üu×]5a^ëÝ ;::j¶Ù¹s§v eÑv OžŸ[›0¾cà߯=ˆç_,ô!|ˤ®3AÐYp¨ŠWI`?ÐC­–Ší#a\Ýp]…@¼k$^‰w^=¹XÙ"@IÈ×Áºm“±²å¸âÕ'ý§fã®U¿øõÄ p>0 ¼ +±àh[Pƒƒ‰Y“ËÑÄTBQf‘‰lÁLÛÉãª(JûÐŽ}EQ浊¢´“h&<ºÑÀ^ݶ[b] Üüâh¸à¾àï>$ƒqß÷qýs\| Þ¶ûmŒŒŒÀF8»þlÍ1-Ë¢\.cú.£´+Æ[ÑÛÛË<Àí·ßÎM7ÝDWWWÔ˜‡‡‡#wæ;vLè9&²µ•°®Š¢´?ói<<¸ PÐúßÖ„§„@TáÑ ?‹WcžjèPñT¤šwÐ>M <:±mk\ë1¹ŒÀc¯QŸa²ý Ú=ÁvEªÞ’RßfHHPÉ(‚cܳs¾û:ª- Ú­OP¤H&æJšRU[Q愉ÚùLÙO'(J›Òn}EQ浊¢, ;ˆ÷Dƒ„y…û!YJb>õMò¿ó¬îFáM6”JðœxÀËþŸÿ—U=›Iù)º»»)S沞Ëjæy¤ÓiLÓTG¥mWxìèèà3Ÿù Åb‘ýû÷sàÀ1ë÷ìÙC*•ÒDŠ¢, Œ0$B¨¤‰ &‹JT½%¿¡~NQÍ»—%EêSÍã÷Gá~c=ðDˆá..X¶J½÷_#ì°Î“Miexif¨æªÌP «(‹ÉﵪžQв¸h6sYQEQEQE1‚Isªök*™‚„‰}ë~XJ4¦ ç™ áGl}·E©TâØÇøà+>H©T r8æ3^h©T ÛÖA9¥}XÑleGG½½½ôööF.ÊÂüÏPE™Y,¬ÚŽCŠjîF‹t ¶ÕP«™ð³A5G¢è>µbÜxyÿâ¡YgzÜs"mDr>NUèÌÇ®‘äÔ®ÌpÝ¥00j„Ç…È”_Že‰¡Š¢(Š¢(Š¢4ãètvê˵p­Ðë ¼ÉÖ€DNµ,èLòГpÆó°m# ê†ëº$“c}ßÇq ÃÀ²ô}FiVLvCEYr©†ïÅ$Hh‡ŸŒõ`,Äö¯ÿ½o$zá¶>w¢OmØÒ¹:Ïé8oI>IEYôÓßz!Š¢´-.® Š¢(Š¢(Š¢4åÁéìt%ÅÞ ànÞ ¬>Œß·øÓD–¤“Äu] à —Ë‘Ëå&MSè”öaÒÂãxôõõ±wï^|pZMNQ¥}±@ƒªW`‚@ô¨æs¬ÿ]—ï6“óüðx"tÎeê8›© µÞ›B^YÄøaÜe[c +Ê¢G…ÇÅÞ_EQEQe&ñ}?û“AÄÃ7𠿺áJ`KøyÛ)ø·,\ °†sËWËCaÑ0‚ÁÄT*}näéË00MÏÓÔJûpÞ|W@Q¥]`åé Á‚$UïC %jS+º5Ó!dÛ‰mDtŒ‡v ¦ãµhAŸ§³³3›áû¾ŠŽJۡ£¢( pèô!FGGxÁ/w %¤ªüv±¿’Ï17 Rö\ê&S³j0VTUg0E™2S}9¨¾ÔLŒã8S*ßqœ`¶¦2>¥ø>äóÁ_Áu¡X„Dº»!~ÝeÒöøø >«¢(Š¢(Š¢(mÀ¡êGã§1Ÿ8« x™ ×ÀòÓËkv-•J  …¤„G˲°m[C­*m… Š¢(ÀáU‡Yñd}zËaÓ ¬ó‚šü‹m“õh„æ™&UÓ¿Ïu$°Ì·¯×>4r™²È™­0«ãy$f³Ù1Ë|ß§T*MºlÇq.w]ß÷LjŒ¥RiÜ}1•º´Å"tvBƒkL©ˆ†ÅâX±0› DÅmÛ‚ÏñkU*A: †ü_ÛD"X7žhìûë2¾ÔÁqj…NÏ«­Ûe¼ìž{ææº·9^8ËH…GEQEQEQ&CÓ‰»+ã_NEŸŒ“¡ø¦$¼Ø€G`ãðÆš2ËårÃ1fLu{E™mZÎñ¨(вXxæÇÏÀK-~eøJ:ž|¦êÕgx=Š7â4h:éiñÏ&𴜪Ø*S=¯ÚÐõÓ¾.в³A#¡Ï󼆞ŽãLÙã±ÑìÈ/|ò“\xá…üÅ/0M“\.pÝ~Éç>ÇéC‡ ™$N“ó<ŒL&±’É(ß„P*•°m{R30ÛÏ D>Û„ÅL& ƒ „E–¥ê’í&“Á~ެ‹Ï&Íå‚}2 Œ÷ÈH <‹P(T—g³A}D4ôýj]‰à³eëm;8¾ÐÝÔÃ÷ƒzd2Õú¦ÓÁ2;&–çóÁù™fð?¼ç”J¼üûßçÑ'Ÿœï;3ïxxfUQEQEQ”IãºnðNoC0P{¿ßÛp°aWÃ0Áv Þç.sx̬¦Ìl6‹mÛØöä'@—Ëe,K½”öA=EQBV~{%0ȲKN„A¿AÆ–-f'œh¼L9ÖäŽæ‡Tø_ˆç½T”EÆlåxt]wŒX*•ª//žWˆ½Ôø>÷ßr ‰D‚b±X㽘ÍfI§Óø¾?®Hyõ¿Èê;ïÄqòù<|å+ÜË-¼ó™gxñà ŽãP,ùÜ?ÿ3ÏýæoB>…¢Äû²©:—9&|rÇ3Í@ìï>×{m–Ë08CCUqN°¬@ÌËåjEG!ÓdÆH2ñ±ž”cÁqãn&S­ŸëŽ=žÔ£R êIS©±ç•Ïu¨‰S)>ûíœ]¿~nîSããc©û¾¢(Š¢(Š¢(“Äó¼ñ#Š}^ö·V`Ù›F°\¢÷ËrG™W—_mjÛ6ýýý¤R©)…NM$Sš¨¬(³MCÇvïÞ=ßuSE™Sºür’KàþG–S {*ãÙ³5&Y|X0Þây)}W”EÆlxBIþEÏó0M“b±H6›å¯^ö2RÀ<Àe_ý*«»»Á0ø_ü"yàñÛnãßøÞ¦Mäóy6üË¿ðÌW¿Ê'·l©Ééh;Æ÷]§Oóíë¯'ó¶·áû>/zÛÛøåúõ”,‹´ëbe³d29zÿK_â¯V¯æ»Ÿú§ßû^~wÅ ^þò—󫯯J[<óâ¸nàµ78X+šù~ À‰ˆW¿<“© rˆ{BàÝçyÕ0¦õÇkF¡P»mrgOØvP·xÝûû›oßlvk½7fœd2¸.ŽS-£Phx~Ùl–»îº‹®®®Ù;÷ÂlM0PEQEQeqòÍó¾Yó^ÙØç-×`ÿö!زš|שà}-F©T Ò/¼£ù¾O!-gd2õxTÚŠ†ÂㆠtBQ”¥Çû>@²”$YJÂÕp«³Ê,AÔÉXøTÅYEY„L6ï[©T"9IËu] áÑ÷}Šé49àUßù¼ÿ“Ÿäâ /äs†Áÿ:{Âí/zê)¾óæ7ó¢O~’Žò‘ÞY©ðס€™4MRñ— ýû¡þ骫¸ñ{ßãÆpñoÜs+_ð‚àE%|Êd28ŽÃ+?ûY0M|Çá­7ÜÀ¿üeøáá‹_ ã¡‡‚|‰¶ˆ‰’µ»»šƒPD2×­zpz^ ‰PèûWžãÛ•ËA9¥R Hšf°Ü²i,2€IDATjÕŠèiYÕ0¢Á¶{-Æ…8+–Î6sy<ÛÎ_Îwœg²X,òªW½jn¯C£Š¢(Š¢(Š¢LÄÑg€ÕµË.õáv>gñÀòºIgÞU‹E0ý–šÕ…B J¥©f“L›àº.žç©ø¨´ Ms<ööö²cÇŽù®£¢(Êa°É{ X[bf_Œ{ Ú,<ïÁ¹ÎI©L ñ¤SZÃÇŸ´ÇãT„Ç﹇AÀñ<<Ïãkk×òغu”Ã3M¼0ÿãkl˲øD>O*•â•Å"_¼ôRz¾ö5LÓ䣞Ç^uï:túûI&“$“I†¿ým¶¾îu<òƒðĹsŸgãÆÑsÝÉ!u–öèº5Âc>ŸŸô$ß÷I$Q[’sr¤ýJÛ» ¶Åqœh}:&ŸÏÓÙÙY³¬»»ß÷q]—îîîš2d{ùÞÙÙIgg'¥R‰t:Ù ¹ò¹Ñ³ß¾T*ižάärUEQEQeñrø’‡‚› ãÙêÄNãØ3púÉàË1'H½aÛ°~=;ï–ù|>š4nš&®ëjä*eQ°¢õ"”™@«Œ&³ÓeðÛ²¬hFD2™$‘H`š&Éd’b±ˆeYd2:;;1M“þþ~5XŠ2Gð€`°úB.ä¯>ãü{öÏ|‘ù|~Z¢Ãxø¾Ù«Éد8Ùl6W °mñÁïR©„išX–…çy¤ÓilÛÆ4Íh`],J¥¶mGÇCö óá‰hÛv$.ø¾O¹\Æ÷ýHèÈår‘(˜H$Èår‘¸’ÍfÉårø¾O.—«QÊå2®ëFÇ1MÓ4éì쌋¨ȳmÛ¶¨üþþþHp,—˘¦‰†aJ¥Ø¶m¦i222‚ïû‘’J¥"Ñ&‘H088H.—£»»Û¶¹öÚkÙ¾}ûÌ?l‹ ‡$Il&ï&a6³Ù,®ëÒßßO1Ÿçæë¯çu¿ñ¼þê«yÇêÕô§Ó|áýïžq=Û¶I&“†A.NÔÀ¨±Q¶móxGŒñÕr€OÜ|3îw’ÊdH¥R¤i.ÌO•T*E&“‰ê^,ƒó-Éård³Yº»»1 Ã0"1ß¶mÒé4¥R)Ä¢s4 |ßDz¬Hì/ ÑörÇ¡¿?0˜"ÔÉ1‹Å"ߺþzn»äû ñÒ.D´Q/—ËEbœˆÇ¦iFa6›Å¶í@T E_ÇqjÏñT•‰õçfÛvôr)×F¶—cÈ9†išlܸÃ0¢Ù¯b»’ÉdTÓ4ñ<Û¶krƒÈ™=›Íf£þâÿþßÿ{FŸ‰…Œz<.mšyO&|r¼o/SÞÙEQEQ”ÅÅÓO?]ýò¬xÃ_Ï< ÏŒ`œX œ‰¢YßÞí"}Ìþþ~:éŒÞ3eQPiÀw¿ûÝÊå—_^ùîw¿[³üòË/¯|ìc«,4>ö±9—ùddd¤R©T*CCC•¡¡¡J¥R©d2™ŠeYÑçd2Y©¤R©ŠmÛ•ÁÁÁŠiš ’J¥*@Ų¬ P1M³’Éd¢e²mÛÛ¶+©TªÒßßw1"×Q™·Þzë|W¡mλ§R®þ»õG+O®|²R)W*•ÔÌŸ ­R.—'½íàà`Å0Œikdd¤Òßß_sì\.}/ 5߇††¢íGFF*Éd²R(¢õÉd²’Éd¢²€è{&“©†Q) •¡¡¡J¡P¨d2™J&“‰lY*•ª¤R©è¼Êår%“ÉTÊårTv#›Ðßß_Éd2•B¡P© …ŠeY‘ý•c …Ša•L&S‰ì¯œ“|—{Ðßßí+çÐßßmoÛv%—ËEu’óٰ׃ƒƒ5÷khh¨òÝï~wAþ¦·ÊTûT¨”+“koƒƒƒ R(¢Ïò, AåË—W^ô¢š}¤ LªMU*•Nù•JæHƒå?­T~«ø·Ã0¢gŠ •ÁÊÌÐè)mÔö¤I_EêÓßß_±,«244T)—Ë•‘‘‘J¹\®”ËåJ¡P¨”ËåŠmÛQ{I&“ úošfÅ0Œ¨ï#ÿ è$“ÉŠmÛñ›SùÐ 7DûJ_Ê4ÍŠeY•\.ÕͶíÈîÈÿ¡¡¡ŠaÓ4+ƒƒƒÑ}Ëår5íKî©l_oGâm[–W*A»ŒÛÂÁÁÁèóÈÈHtmš={RVí¹W*‘‹[h·~ò\ï”þÀBb6ú¾ÍÊŒ¯kö588XÓgïõûÄ7¥Li;‚ü&×SllÜ>ÔסþXQ™•L%YIFç$¿ÙÒ¦+–eEmVÖ†µý\.WÉårÑvRW±%ÒG‘ÏÒ¯‰÷•„þþþ†6Dl¢ô1äüåÅÛ{3&êOŒŒŒD}¨¥ø~°TûBŠ2KµM,Õ¾¢ŒÇRìLõ¼7Vì */¾ßŠÆ{¾‘©\õ ]±]»bß{i%ó·WVìo©Øe*¶»±ºs¹\©„ýÂÁÁÁhìŸ ‹~ü^Y8ÌDŸ@=ç˜b±H±X¤\.×Ìlo—îîîh¶½„ij,‹ÎÎN,Ë¢¿¿ŸR©D¡P •Já8N4¶í(÷“xýˆ„>“Ä´¦ibFÚÏ4Í(y­eYÑLxÛ¶ñÍ0n4;¹ÙòFˆGRÜ+EB¦Õ—™L&kÖù¾y?Qýã^M²,îá%×@®“Üñˆ A<8¦š×j±s”ê=ºòÈ&¾¶e?=fSpnš²Ù,ƒƒƒ ×yžÇ¶mÛŠÂ4L”Ç«Þë0Žx(I[ª%®Ç!‘HD^8òŒ‹ER©‰D"òâ’r …BNPBKÊ>¾ï“Éd"/=Ó4) Q˜AñòK§Ó$“IúûûÉf³5Ϲïû‘‡’´émÛ¶Q.—k¼@¥^@÷™eYQ¼ýFßëmLÜÀØߦiÖx"Õ3^ñ{+Ç>zôèt‹[rLÖ Ê÷}rTÛ„mÛ¼ùða>ÚóÜsÏñO¯{]mÙáoí˜6ê36䲸 üœ¶¹nsž]ûÒȃ6Zþeð_v½Ãk‘ ìsýâÇ!uQƒå‡!³¥v™iš8ÔšPiâiX.—#Ï=yÞãÞžqâߥO"Þ¼¹\.ò&²,+ šÉdp]·6ܨeñóÏúOPõÒÎd2Ñom2™×^Öü®Šçu=²L<«å>Çí†_Ú¦x"Æû/².n—Æ#ÞÆÅ¾Æ©·ñ“íß,%ÚÕÛQB-Õß³¸·>µ‹l6K*•"•JE^³ò~†ŠÅ"¥R‰þþ~ àX,’N§£6"ÏŒ„J–wñâ—ÏÒç”}¤.åÈ»Ø:é ‹—³Dˆ÷+R©Tw±xË»ô¡ãï2rñ\ÇPõ»|úONSz Ä²Ä²à¾‡ïÒ·–ÈrlY'ïcR¦Øx‰0#³Õóù|t}ãuH§ÓQ=¥Ÿ"ý$ß÷£5ÝÝÝ5ýþ¸—·”#Ñä»®;¦ï!÷[%Ñ"äø®ëF×¶X,’ÏçéêêšïÇ]QEQeað4p<³öÉhÑ¥?€'Î#Èç¸j=ÿ%œzÖ¬©Ý7öN)}ÏB¡D[Ò(Ê"B…Ç9Àqòù|ô²ìû>Û¶m‹ ‹¹\Ž|> žË‹f2™¬ ù7Bõr‚l#á´R©TôÒ./Ë"Ê u2™ŒêšÉd¢—ny‰–ð`2"B¡@4ðW_ÙO^¸å³¼lCu¬X,FÇó6 # Õ&gR–„”óñM„ TljõŠÅb´_B ÆÃÅÉçú8‰ŸG|@Hâ⇬¯ÏQ%ç”N§£)OÄe õ&aÒ$䣈#ñÜor.Rïøgá…/|á|7‹¶á4Õ{d¹°éÔK‚0†m<&+ÏžÜ_×u£pŸº3>€-¡HÇ%¦|ÖÛ ¹"òËñã!Ïåø2IBÂ@‹0¼mÛ¶èþÅC/ Eç%¿’OVÂ8Køgé÷É;¢ì#}5É+“´d£¼cÈ„V€Ï~ö³sÞöEQEQ"g—¼ø§cWžÎt`á~,ˤø®5°reu½iBl¬Œ¯+Ê¢cVéìì¬\~ùå•÷¾÷½•Ÿÿüç–7a†††¢ð‚îË0Œ …õ‰‡ÁšÍP¡“ ß6Ñ6Rg {&¡$L’„Íår•r¹…"’ˆrH>Ë:9®„ Ї<ªT—s¹6ƒƒƒÓr7·õ\.Ý‹B¡…U‰Â¼år¹†u”°ŒÉd²Òßßm'ë%Œ”„y“²Ç»Öõ!•*•JMhÆ¡¡¡i»Ö÷,ů߯ÿú¯O«ì¹d¦í@¥Ò8lÂõÏd¢°e»R™ÍHk­„q‹‡Ò’°Xõá½äÞ—Ëå(¬a¥R‰žI¹ÿrT( 5öHÂ!J@°„¹\.jó¦iF¡Os¹\ôìK19¾3Þ®å&{¾SEÚ°\‹ø¹*UJ(¥ùì”+åŠQ™|˜âL&Sñ—-«|àšk*¨T òƒ7¾1 ÉùÏŸû\ƒ÷MQæ[•Šy´Áò/V*ö?7Xþ™J%Ù_©‰‰J…JæAY•L¥R‰­Ï|¢RùL¬€T¥R¬TìoU*ƒŸ[¾uƒåC•Š9ìWÃ`PŸFñY“ Îu¤Ò8âõ`ãKV)?Y…VlW±k•JxÞ ²x¨ÜLÝy U*3ü› ÿJ%©TFè5bÛ–+•J®TÜh°}9v™ð{xÁÌp¿TlùŸªT>±úQ?äg—ý¬òÕ-_[—ðô§úDx±ñlÁLô 2Ό$“ÉD¡8-˪”Ëåè]0ì¯a•T*…üM&“Q˜`Y.ý»x8]é‡Çk%<¹Cúæò9Þß–wÛ¶§Ý•P¥¦iV*•jÈ`I Ѭ\yפ_,}ïz…+mTŸr¹\!Gåš'®w; m*ïl­§\©TjÞ+•Jt…\.WÓÿ‘¾–ì+÷Cî™<7 VBOÇûˆrã¡®ãaœ¥üJea„U›é>ÁBé )Ê\±PÚÄb3T”vf)ö ¦zÞ„¡VãÿÊ{Ë•ÂÇ •ä¡dÅþ¾]©F¥R.Wìð_=CCCQŠ´L&³àR?(‹›Y µºuëVöìÙ3obèí·ßÎèèè˜å}}}ìß¿ŸÞÞ^¶nÝJ__·ß~;wÝu×¼Õ5ŽxØÅC‚J(¡¡¡ÈëÈ4Í1³fgÓ»f¢‹“Ù&^çfÛ6 Ãß~¼Ùöñmâצ™GÒd‘ÐÍÙÆÍÎMf'7;Îd\âÇ;F|ßVž‡ñö_¿ç=ïyÓ.®˜3;ð ° ÀàÉíO‚³~¾O¨zÙʬõîînr¹™L&š1ÕgWÂn‘ç x ”ËåÈó@Ú—Ìvo Å+Þ¶…B!*¯¿¿?òŠ, är¹ÈÃXÂÖ·}ñÌz›7‘gO+á%Ä‹Bþ+ ›ùìøøS¿ø£¼€Îûîãø²e\ø§Êã–ßø×_q=¯~Û5Û:@"¨ q¼_7(ü8x›ã"è?ÞoV¸Þ÷w€³á,"û?ŽÕà þ»)ðÿ ø öÇÏïÁŒ_:Š)ÈeùI΃ûnpO›jOÕ}(Œ*ÛÀ+ÓxiÝö_pCPùͯ?ñ>2#ðL‡;Ї»xÚáõê&p·L†ßÍ ¾äÃí3áçdX–~',ÃË”k)ž”¹p™^wA®·S·.»¯¥ØòrX~)ü›¤êiÃíÅÛùaß!Ï?ÿù¼á¼7Të—ŠK~õ›¿Êƒ»¤Ýid fʸ¸Ø3cÝóe<2À˜ÔᲑ‘‘È“N~§%,{|_‰€Ð¬ß;–e188XªQ šõ¤Ÿ!Èçú¾„0™>ƒ\“·¾è­<µñ©q·“²ä­â‘Z .ZÊ­¿·õßãᨥ¯%Qâé3äü²Ù,™LfÌûS*•м7‰D´¯ô÷ uœ@Q”™Em¢(íhìs6ï´‡›p!—« «Ú‰ú¡(‹‘q…ÇÞÞÞy©ÐÞ½{9qâDÃu §§‡žžî¼óNlÛæÀÜtÓMóRß8’ÃDr{ˆØ(áo`ú♢,%æÔ¬†`Ù¢ktÕœc|à ¨Éµãyd2™h)žPœIX6 ½%aÁ†††¢‰ŽW(Tš|qNÂ;KÞQeàK„J˜Xˆoe°²UâaÅúûûǨTÚŸùî¸ *6ÙÞuy•a`;FfÏ ™L$e¼ò[¯„·Õípp cÂoz'ƒ¿þÁ¸:\èÊá>N°Ÿwx7ˆ[nø÷Ið¶ˆh6àgƒûàZ`‘¨åº`|l—ªÀVg(Emo$¸¼'€¸w€ýÆð¸&0ÞÁÌg‚¦o€_£¼gÁû øÆ©°ü8¯÷TE:3,ÿßóN!Ï·wÁ5À»<<Ÿ0Tª…EÅ®@|Ëgïe{ƒzî'‚£”EXßÁð|ÒÁùCxí¼êµÂŽ_–;±ºÚáçbx-sÁõ *Ë}’òJáúÐO$úÖ"¡šLS"ó„çñ…×~¯|ã+XXçyþ½ãßY¾9£¥Q<Ïãîuw‡¢bUp£T­×`õÿ0‘PJoõ‹ÈŠ0ú^¨þ!Q3ÄÊ…YmËþjºI•¥* ‘©+m<¶qÝ[Ϥ¾B`Ô¦¿íÓÛÈT2X‹?üþ†ýwºZ–±Ú4ê f³ðñgãQâJ|Cywœwÿ{èP·8“áw?ö1\×eà%/á¢ÿú/2™ ùÇàß–vbùÇ {/‡ìCÐý(øw‚ÿð>I(ÀÜ/†}A÷È~‚k ëó ðÞ©nHÙr(Ì—oÖAþQ°Î²£ŸOPÜåÇ]J è  ç¾ð˜ÔCa™z€®ƒP<þä×UÓÈÅaH…®£P~,Lc ᶦ]9u¢vïÞÍš5k¸òÊ+Ù½{7{öì©{ÜÍ7ß<£‚ŒŒŒðþ÷¿ŸL&ÃæÍ›Çì—• jç°fÍÆMûĉüøÇ?fÍš5uÓž Žãày¾ïAd…ÔLk¦CCC qøðáf¥.sÙ>|˜¾¾>:;;éììàØÓÍüÎÃs> ÀÀˆÜ€Z–‰"’•Ëe‚  §§§ÆUpÒ…VÒ–¸gƒ±+ßmÛŽHT*ljÜoA8àQÓkçA¸o›Èëb¦¯¯ÿøÇœ8q¢ÙE©Ë|Œ êŸÄÛPx|èûßgS±Èñ׿÷–[XsæMd ƒaEô¾|û[xÏ+À}lÅ…ª{ؾæ&B¡©¸¸ø:ð!B±Éž Á§€ˆÄ>wkµ¼ûyÄVOUŒÄ t4Ÿ‰ÿú€·©ú½*®¹KããËÈTÅHïB%›PÔÊÅ“ÙÁ+ ÿ(T…2¯ZowGUo³¡lÆãÎÈï…þw‡y{ÕŸ¯÷°eÖ> þÉj:ï…̯Z_¦c#¾â ý°\ÉŸÏ'¹…·ñ6pàSþ§b!Q¥ÑšŠÙ2–n‚³ Ó4ë/Q6ŒŒ°wï^öïß?ÿœ$ãõ3;vŒ¾¾>Ö¬Y›'¹È Šê6U\¿çíïá}oy¯úýWñ×÷wäz{±…¤÷ý¶MþëðMëwyèÝÅ3…_ã¾K·u—P>+üÚï†r/§ƒ{}h%l º/ƒà%JÞÌøà­‚ž÷†¿ËòRà 9îw®ôpÞ î›Á;+´FÎ^ …;€apÏ®ëË`=¹£PþUà$ôzàt‚sô»_ îK`ðNðÿìOCþÈ¿-,‹õ(¿¬¨dÃ:ÿŠçƒq zÿÊÁ’ª‘ï °w@ÏÇÀ_ éÏ@1¶‡ÿPèŠÙ:å­À1ð÷ƒý”7‚»2·Bæ—­¶Iú>ðÖ€¿° ó]žçÅa~®Õè>Æð7†Ý®u†÷@þè1ÃïîñêB‡e»/ìgòçCðXËÁºŠ'€ÐýL¸DŒ©s³Ö- Ëf\|qô´‰…Cã1à8ä~Eº—Åëò'Àz:,OÏÚØÚ¨žïÞq°†À}.¤O€wZÕàú8ä~æ%±È)ëGªóüþcá¬68ôõ&kæúý`ÿþýôõõ±eË:::š]]¦iè÷ƒÉ½h4 =g8vÎpÉqãý•9á´’–x^SÓõßå»ÁعOÙ/á·,å»ÌÖ;/I¹Z6ù 9r„Vd.û€#GŽÐ××ǶmÛ¢AÄÏÖy¬±Xú4±¥Ëà8N8ù^#eAuõ“ÄhÌf³‘XhYV$Š»UYä “‰\ˆªÓ4©T*51–TkÀd¬(ͦ¯¯ýû÷·ìÛ|Œ <8îÄB@€‡Gº‘:Çtšµ–Åðš5üŸ³Î²,þaû&®}Õ‡k½ôW…¡6vcÕ ÝÄ3Â>xÕ¡Š Q¹/CñUþxAOoÕðu%WV kíØ ¯„ •ß Zþ®2DÝvÕ{| `¬;=<ß<Å`Ž@î@r닽Àƒ@leP,…M;4.æKÂÿ¼?6Ö5MÂE28î ?Û}á‹ò;!õ)0@埀‘P0ì¾ ‚uY ÞµPÚþžëP~!Ø'!Ó ©·‡¿ùÜ×!wAØ~Ýë!} ·@~ äŽù3~œŸCpôÿ8Y(î€MO@æÁô~ŠgA¡';K€ý¯~@ði(Ÿ„Ün"‹L D&…æà Cï»À;ÌBpx?ÌßBú?«®h¿ Ù·…î¨+€ñ=(8Ä1W…ï‚ù\H:¼Ð⼜_Bî¡ØJ™Aþ È}¼WAé¿!ÿÈÜ™¡øYȯ­Þ#~&üž¹ ã w‹î;ÊÚß\ËgìËfýw6Ìõû-;.Òhæý~0ñûF³ÐÑs†cç ÇÃ6#á‘`èàÐ=c޽ð ±~ÏBKlø¤á’¹àÞ<5íÆÞ½{˜ñ˜ ¡ðøþ÷¿Ÿ¡¡!n¼ñÆ1>Ehàꫯ®Ìu*ôõõ±{÷î9 ôºzõj®¸âŠY@8ŽÅs ‚ ê$æStT…(yÏQLJ”œ0±Ke¢"ÇWq7¡{(¶mƒmÛ¸ »›Vc®û€õë×](±6>v’ë‹TgçæÏó¢ïû”ËåHdÌçó˜¦I©T¢»»›J¥‚eY¬[·®F,œ(®âD´‹«TÍܳsçNúúúèëëkvQÆÐ*c‚À8 è] …KkŸ ybãCy¶Eã+¶FÜ€Ç1ìP`$~îÊ3Ož/.qúòL“…/òüË™ñ³U¶¸kb!$£¤ÝC<>ÈyRÜ!ʧLäiˆÃ*:Õó{”m†’wxþÅ›9¥ãGמŽyruÍ€Ç% 9)ò„Êdi¡RbºïÚµ«ÙE©Ë\÷k×®eçθ5*  ?õ÷ÿÎW/¿Ó4yϾËW‹WðWûÿŒ£ùß#u!ôo‡Þq*,®O…§÷€žÕÏÀï\q!«ô W\ K—Ä.Ge¼¬IÔåõÆíV5Ýñ¤Id?ç´Ð /¡[_éê iŒ5Nxú;žªZ*}Q È ÿK°v…z7Æï5i}®“‹îuÆÛÁzì¥PxEÜy ³Ì÷Žý¦¥cüO0?»_ ç-…ÜUñ1%¹0Õƒ´ üNøÙ0«mõvâ©l2dà#`ûÀç«Mà£ÕÅÕ—šÂkƒ`äˆW„/;Ur’þωŸ …p[oX—u^æqè½Ø5óË!ý÷ÿ.ðÀÿ`ÞW0 ;Ô˜ð8ðéNþè&ð¾q'¼à´óñ~pùå—ÏÊBj¦ÝÑï³7gØ®A€çyX–EQ̹äeõù, ¥È«S½s5­Í¶mÛØ¶mÛ¤¬盦Í6Äå¿ Àù¿°B…ÅÎ3È|êAæ°±É},Çþ»÷“N§ÉçóQ¸¶dx -±5Ÿ_=¿¤|–ãd’Q,'Pò$&‰X÷É܃¡ü‘Qºb%%M;Ñ~ybUÄGiG©ŽZA´@<™* ’e.@ÚWU©—Xo@8—(åM·¢X7Ê5”öƒxÞGÒ“¼ åxÙ'®– ¥ ¶RW‹x…|\óä“S¸燦õ'aù3ÏpÏ=|jÎê§Æs4 ƒ\.Å‚Êd2‘Шº;µ,«F,œÈÂQ£Y´Ê˜ÀÇ'7ž´ë2|æ™tÃÃõû~œ_ýì/­¦ù#àŸˆÔþï„Û½"Øêªœý¡uÿZðέ]$ÏnÕÂjE@ˆŸ£/’c7Ç1ƒø!ÏyFËs4§œ«Z.æ”óT©µ¢äélâñ‡:žç¨ˆ§¹êÿ€xñ‘£ä/ã)S?µˆ‘höùËêZ§Q£ŒÈ8Fž•‚ª$Ól´X«Ö²ä©ïÁUÆ“AƈMðà:¯LÔÈJçÙè&|¹w èÃù_ý»ößÃø[üè3ß pßZ~Î žYóv>¾ X ©¯…×hø÷’^/Hå[ÿŸ®Y—\e1ӈē½7å¸fE@6;ÁüÿˆV HxÓqÏQ>—V½÷Ç);Á`Ô—šÕجõ2†ÚÕ¹ÄöäP¸ZC:¶ñ*-yŠ©ÒYRNµƒJ4†±)Ñ ˜·%òÈ(ùXaYM6ýŸïÑj´Ê˜@£Ñ4—ÅÔ¨1ß’ˆ˜'Ÿe>!—Ëáû~Íœ„sA`Û±Ç% UlÛ®»]0 #š›ð<¯áqõΓùR™;Íår5¢¤¤kšfMÔyV@å¯a¤Óé†åÏR†aŒ ? y{ž寶•eY‹Å1ÞíÊår䕪^¾õ„Vi·ä>õº¨u”6’8áRvß÷q]7Ú§n—2«m'B°š¯êG½¿D8®×~­F+õÒB§Ve•Õ£^X9Ìÿ(CI }„M1U$èÏô<Ó4qgŒð¨Ñ,$ ª›±}ûvn¸á†Èy:ìØ±c̹}}}lß¾=êdÿÞ½{k:‹¾¾¾‰žSAâ9:ŽÅ\›Ž‘ˆ{ñ;©K,þ‰ˆ'2®’o"¨‰…€«Š‹*b N@ªe{@8Y–'žø`Í‹š¿ØBhÁ(ô€wðvð |hVÁÚðÈ[ k ÜUÑî\µ<µø„ÏYôä™"‚œ¯ºR•mg‹nNuŸ<{!Cˆ¤ c…®DÚ½Ä  d!PšðyŸ"¶Æc*yfe¨ÆV#^¬$  ÖrKZ¹¬Ôê?;Ålþ(§WÏ3ârI{Š*^ 8“v®>õ…ÇÆŽ%D¸ÍQûìËÍc]¿ëÔEÕ¢UÜê¾Rír&C½<[‰‰ú‚Ùì âIÂ?å ¼åW=^üßɃÀ½ÿ»‘/½ìaÈ–âêoOMU¼sØA€åû0‰w­Ù¦Õº¹Âµ¨°Ó`¦å¶°&gå:Œ1 Äñ*³õƒ5'øÞB´Ê˜@£Ñ4—…Ôˆ ¡ÛÈ|>O:®ÀÊårÀeYVp$¢E©TÂó¼šùÙ'yX–E>šÞ‹÷$u¿çy‘¨eÛ6¦iFùË1®ëFÂV:¦R©DeIÖ+‚1E­C>Ÿ'ŸÏGóŽãDe“zÉü‡*~I9ä¯ïûd³ÙHLM†±‘¿"ðÕCF úÛ¶£¹9FBm©ù¨í#"¢/$çsÔò¤Óé¨mÕ6P±m»&ýä}ÌKm‹ñÄL&C©T"•JÕ´—pÎ9çÌìFŸZ©–:¹ä$ëž òZÀàà˜sŠÅbô*•J5ó…ÍB¥®ð(f”I?®õ~ärÌÀÀÀ´…ÇFA[ÕIÉ÷îÝlß¾ŽŽnºé&:::ؾ}ûœ7”çyôôôDýtW$”‰-Õd²O¼7%×Ì$]pš‰ÿNð‰PMŽ¿Ï«Â¢ˆq6±;P±ö«÷/‚¡L`É„¤,’Í$¶C,–˜Øk¥äÙ(¶âxÝorR-9)Wbòo VžD¦õOúáÓ1fÙ © šeõ`ww7Œ†ûdšJ¥¨T*Q¿¢Z;‚vK¢Yœ´Ò˜Àj4Åm|ýE/âï:;±”¾Ã—¸Û–=ˆ‚Ç«Û/%|hŠZ¥ÄIt2ñ\¼ú Ïj/¥ÆzäÙ/ ÄR_b‹¥áb¯ÝÄ yä¯,þÉ ‡6á³V<+È3^Æjo%B¢Œ]Äjb‘N“‰ÇêñY Ú#Œ@°>\ % ŸdÜñ‚%Y¼ä*ûEœ‰Bâ蕈Š9ŒuK/⥕5טÚ8Ͳ]Ä_3‘Ž,îR·»Ä‚¤‘8^Æ~õ\½Ê½%Ûå¾zæùϧ‹M¦/˜~ÀGËÏãî[‡o>‡]t_Ú‰yòïžÞ•ñ¢/u|œÄ$¯ª«ß›AÓý'ÈQ£™€Vh4šæÑn}ëºd³Y …B$år9²ÙlôüH,êlj,Øz{{£}‹w™LfŒP‘N§k<#Õ›«ÉzX–5Æâ-Þ¥ÞLKêœN׿ӦÌå˜@¬aŒFO(Ódû•Wrô3Ÿ¡¤^Ó»­ûeÏ,À6ñŸúi8ç⺵ó>Uzzzð}ŸÑÑQ*•ʬÞkM«RWxܲe »wïž0¨êîÝ»ê®:˜ ÷ßÿ˜m|îsŸ‹,2·lÙ2o/Sñ»,îɲ„v".ÊÄ•Äw¥2$Ý’LëËc3éæS¥Àäíj §Y¼ÌG?ptµÏ÷—}Ÿã¹³ZvÕ­…ã8\~Ï=¤¿ö5~íÀ%ñB†r9ÔT†‡c¡K„@E˜S…ÂÞÞp€S*Íl;ç\7§DS:"^ ÉA°djžI¤TE?)ƒiÆ¢_²œÉÁWò{:þ÷¼PtLî—žÔϯ3¡ì8ñ~i“¤xY,†ÛED-jË›ÏÇŸ%-Uð!V„Þ¤«¶©\ÏF®PDT„±Çˆø)û­•v¡µÍhƘ ‘µ£ŒŽ~à¼îAeålX~ô,H«ƒÕí@`‚Ñ·‰'²Œum*qeñè™"4Š• ü"!Á" ª{ò·(ûY>É]"¢äxc‘™µóôÏa®öÚ¸ÌB±bÕhS+4Š{Z+‰ëzi;±×óKªÛUOzqq[+Ž–Ä%®G(ÜŠð(½ˆ§/Žâ‚_\ÐÊ>?‘o¹š¯ô "X«=EžXô,+e‘k{Ìq8§«‹v ÙÌV?Po‘ÿp>\™þ'úÞzœåO<ÍÍo}6Öc9+æ§ËTWôk4šV›'Ðh4Í¡úß÷éé鉋5£x5Ñó<2½½TòùÐÒpm»&\x¢pM3 ,ž8d¡šx:ƒx Ÿ'^TµóŽò&¬†,p2Ž´©Ï485 Û}<Úì~`媕?ù|ŒË ¸{$œ_*atṯâRÙu]òù<ýýýÍn>fΩ+àÑ®ú²ñ½¯|…?ûÈG°<çßy'ßÞ¬ ZŠ|™L,@%E=Ólè®!B¹FHõ0Œ±VrõÎÓ¬µ^¬‡e5Æ$‰D1ï­ˆLZ Öc¢ºær×e¢4,+Ç£0³;Óœø˜ÉX.N”F›3c·¾µcð¥Ï~6tgS(ð¯¿.¾‹àËmó6àI™€ øâg{èUn_Õ3‚¸L—±ƒ*.ʯ[\tªñÕ’Öû©Ö{Æxœ,­þ*:^ù’½„Ih è[ а+"¡LÆ@,:ÊN†p’G\Øæ«ÇËÄN—²O,%íÄq6áxP/Jž2^”I Õ’N„Jµ ‚L6¥•}ÝÄîúj}Åí¾¸ä{×Ð&Âc#fÚ¨1#%çÃÓݯbï™ðW§…÷IïYµñB5Më0Ÿó¦u™ë¾À÷}ºªc§t:U(PL¥H§ÓËeJk׆‹ÈL3ÓYw[Vä‰DAY,&^ÐÒÄÞLzˆÇ•2(áÄ+Š,”“1¾ŒñÔøáªW5£º] ãàUe )ãM”r¦ ÇѽÄï²=v@ÓúˆKÜé†kæcLpÅÑçqïZe±»xºªƒÄo- Z»j4 …SíÈd2 pà 7°gÏžŸÉ}}}ôõõ100ÀæÍ›'´Šlg$ÐîDfÐ>áÀbw\bÙØÏØx>º‹ÑhZ‡Ç{|æ‰ôôÄî,M“?8óÌÈgþ]póOKèø“?­ï­ŸF›¯6Óhõ,‡ ÞÛmdÀ?YÝQð/¬~?»ú·˜tÆ1˜åå_œèÚÄž<—ù,µ±âÔ1ÃTW «µh?[×ñëåOñYV!no™‘˜—ª¥ Ä‹Vã\J޵“Iì:Uå c-KÅ25Ø&E„rÄ1'U$ݤ•«Il ©–UÜÁj#®t~à›?·'ý< Žuûi4F³x ‚€l6K:&“É`Ú6]ÀË~ücÌ‹/ŽÆaâmD<]Ș?CÂñšÌÊ£B,HÂØØÝyâ÷‡¤H8²ÔLÆ­=Ä !ËÄ2ÄCˆG¼ÈM<|ôV·õ(ÛƒjYÄÓ†Œ[Õ±®ÄG¯.TÓ‘±W£0 "ÖNV"O’‡x ™ì{”Ä{·êœ“elœõÉ–©Õ$¾\.§Ý}N“x·×>fsö†ª´¿~=Ø[z²±·ž;ef¡ÒPxìèèàæ›o榛nb÷îÝôõõqÓM7Eû;;;¹öÚk´è(އ‡‡ëú â*K¶ýÄ#™XÒB£FÓº<Îã“·x”Ø~¾_km&p†çûøŽCɲ0 ãw~':lëÖ­Í®®F£™¿Æ € `Õ'?ÉŸ¾[•„`4€o¯PΑ…e±kPÇòb-£‹ñKrRLšÀþv\&²†lg¦ZŸœrŽïûäª/|êdÚ^2ñQÕåqÔsËår´’µÑdPºÁñRFµ~êÚhÒÃ&žô™L:‹¯f¡XXw:ýâWŽÕ˃4F£Y|¼ñ³ŸeÓ›ßÌçN9…Ç>ñ V¦R¼ýíoÇ]·.н¾üâ‹#¯ªx–&û7ò—S¢vŒ cE²äøMÆyòy*”¨ÔÄ HP-§”EÄG‰ž¯þí©~ϲNbžK±e¥¤/bižØ[‡ˆ|]JyÔ‚±ÇŽ’’W@üޤÎÉŠˆjÎÍ„VœÒ¦"ÖJˆS)ÄÖ¢"¤ÔZ¥J»@,"›ÕsrÊ1j8 º_BeyÔ¿Ï'²ÕQÊR.¹'TKV9GÂ*HÛI[¨¡"ï'¦Y#j‹@›–~úï¬ÅÅ#ÇŽ>=Mš4yò°qc8GèºcŽ×b£f±rêD\{íµ\{íµ 144„¢ã|ºVm®ë’N§ŠŽ)⇞ÄÛ‘™ *t·¢Ñ´>ëÿçlŒâ$׬åóá@BböUb™bVÅ‹E‚ `pp°ÙUÔh4SÀÇ'\“šÍòã•+9ñêløÑÓáoþ ñ lš\úò²Y ~q•X0û↼(/$’Ö‰AÁ¸/têžr¹ÅÙ˜è))•JuÇ„õÈçóãºÐQ_>ÅíÎd]îøÕø°r¾ïûAPSq»:™Ò~ûÛßfÓ¦M“lù…‰¸Vö¾ \·Ýt„ïþæ þß±s§<¡§Ñh4fápÃ7¾Ám¿ó;\ô£qòî»9ú°¸›X°ªÐX´°ñ˜ê¼¡je8ÕŠÊi‹TÓUÓ–9Î~â¸ãjC?”‰…CqÁšUò”vAL¼sôë{ˆÅ>uafºúÙW¶u+m,†!²¸Ó'œ³•:Ë1â­NÒujÛˆ@(^OĽ­Gø¾& EbÑSê/Ÿ‹ÄZD<,+õÁZÄCmUËR5T‡¤+ÛTRÂ+¸ÄbqYÉ×Q¾K;H(‰¤DV©æ62š ~²zuø¡z!lìpá²eÕƒ Àó¼(Æ£Žï¨Y,L(< ‹ElTñ<»ofyèÈ*™¹BÓh4ÍãÂûOîÀr9´x”A‚2Á],ñ}ŸJ¥‚ïû¡Û½¢I£i;‚1P8à?V|€¿1¿Ã@ðz·= ¸ò 5ø¥Ó%#”_“Ó\öµo £_J®÷ŸóRê8N”~&“!—ËEVžétš\.íïéé!‰ëºÕg™eYQ s9g1(STþ²ðï×^q*—< j4F³H)»Ÿy†Ž/™;_ö2r¹•J¥Ft„æ¹a—|[}d?^ùÒŒuA+ÖÂW¬~â÷(1þJÔŠŠ(ÇŠ«Õzûû ¹~B¡¯Q'Ó¶±øg+Ÿ %äR@ü‰ç“sÔ†Û°é«®ì—9i™—V-P{©‚ ‰4û•ã%}ƒØòÒÒïãòÐÒªœ™ ±¥cƒ…§år¹º[ûSÑ,´ðX‡|>O¹\¦R©D+áeEˆ†7iòlõ‡½F£‹W¶>²ò‘±;ƒ ´nìétYVÝADd2òù<ù|žÞÞÞºÖŽ†žÂÔhZ·ÆÚñ#ÎÍx##üôñÇÃßµƲƿe#J'ÿµ/¢½‰ãçz aÒ±éÜ:ng±òòù<ëÖ­«9Fã¾÷•¯Ð_(4LÏqœHh«—WR˜,—Ë‘]]]tuuÕX"Ê~Çq"áÑu]|ß'NGB¥eY˜¦ €år9²Z\·n]$4º®K>Ÿ'—Ëaår™|>O:Æ4Mº»»q‡T*E©TÂóþÜÓþuœp[6þ÷ý0ùîºa¾²öÁqÂmŽ–)™®üGr¾¤].‡ûS©p*~—c{zÂÏëÖÅur]xè¡Ëš}{h4MK~æ–¾ï}—, C+ “v¹?ˆ`ÔîL¶EÅý* ¤Þ0»ï€S½3ëå-Ö­ðÞØÊxx ¯M¼‡Ê€«¦iFÞk´g4ÍbbÒ®VÅb‘J¥R³ A‚úЉ¼˜½k4šöeh¼¨gÅbøß4ÃÑãàyÙl–J¥R3qžÄÒ½†FÓòøø5¿Õ/§.âѯ|‡Óúÿ‡+κ|8ý™Ó•ãk_ÜÔØƒ±»ë^Uh×WÏó0MsR“0"~ÉøÊ÷}<Ï#Nãyµqň~år×u#w¢–eÕXë9Žƒiš|õ«÷pÞy—F¢›ãÄ!y³Ù,«V½žW½ê<‚  R©ðÕ¯ŽðÄ?£T*á8üÇÅŠGùÌg¾Åóž·‚b1à’KðÎw¾ŸÏ~ö.>ò‘»ùñåw÷c|æ3ÿC¥RaÆ ìßÿ*^óš#œqÆ—¸è¢Ÿóñ¾øÅF‰«¯þ+Î9ç9¼á 'ð¼[¶'“¹˜ÿ÷ÿîâÛß^Â7~‹·¾µD.¯~õGxè¡çòüç_ÊYg½…lö1Î>û6ŠÅ—qúéç²eËË€^n¼q_ü þpš3Îx®»œL…í_ÇûÉjì­Ãxt`½åü0=% ÇŒá€ã¬ÚHþ–‹)\ÿù£ “ ÷ç^ôuŠEȼà;ßϰñ/z ¬XA: 溃£k#¡Œ£GñY‰mC.ùwÁûÖQJÏý(ù‡¯ÃâYGN£tÕ—Éïy%Á“Ë)âߪeUËõÚý'NÇÿáaŒKÎÅuÃôøéOIw~ÿd'å{_†ùÜ¥xد8‰uÑŠ¥µ+ŽRxÅd¿|UTçb.~Ü}±O·Î¹n¸Ý²Â9#Ãÿ–ËaÓú~ؼ†n§"\Êëb¥äã«ðöŸ]>Ó„rižy†Òõ?Æ8þ,¼ýgã8P,ŒÂSOàßÞ—aqþrù+•ø»ë‚1:‰…ÎÁuá50ÃòØv\v˳ã1º»Ï¢P÷K‚ <ǶÃ6ȼí8å[–sÉ%›šwÏk4M QN8ÀoìßOæckvqê²c¸‡Œ‚´£Ê¹EÜÆjêPõqûÑg;,9·Ìè’ÄþqEYˆjY–¶xÔ,*´ð˜@VÓ';‰Ï$–ަýùÉ0°ŽÆ1¾J¥q‚išô÷÷“ÏçkÜëi4šö# ¨qGúÐsÖó¼_¬áHp…qXð¿¿:Œð c‹T¢sÃ5±£“ø%’Z£WŒÉG œ“]òJ¥H§Ó ]D¿ùÍËþçûpÝpR;•J‘Ëå°ípddY±µÒÒ¥ñG´½è0·ßþZl;À0©TÖ’ÍÂk_ûMnºé …Â0wß½Ž;žËgtrî¹_dùòײ|ùíÀ üÞï=É£lÛ¶œ'ŸÜÆoýÖÜ~û^V­*ÐÕåÑÙù|þê¯þ›ÿóžàu¯{¿ñ±{wÅÄ0ÂòT*P.‹%à'qÝ ÝÝR³-¼â‡¹ï¾ßáÀ—³|ù-lذž‡znT÷Ë/¿‡ŽŽ—ó7ó—_þ»lÛfðÉO¾ÓN{Œ{î9Ì‹_¼žßüÍ|ó›ãûÏá‰'ÖòÀgaši¾ÿýÕ,[¶Œßû½lÙò$ÿxÀ¶m𣽘ÓO?š5¡íºðÞ÷¾×…óχË/?‹ÿøƒ ¯Å²À0.Â4/bùòP@ÈdvT-¢–GVQ½½%þû¿‘Jå¹ë®>þå_ŽQ*màØ±Í8ضYk™fU)§Ù¶mÿß…­ > ><Êðu>¼}ûÔñ}üCgb>þ=Ï$¦v !&iáÅÃßþø‡ ¼çWàì³ ^þ|ŸP$úÝŸcÞ÷%Ò8dOùGü§Ï c¡øV¾ñ(飻çà¹þìnغ•B¡*ÜýÛI¬ò¿‘§€ÕñîÈå˜:Jú­á}fÛ±pV\ÿì çáý|=œw:=·Ä}(,n: ]Ÿ|æ©?#}áJò¿øüûÖbŸ· òxX§ÜCúá¯Ã' ̵kñÏÍ’N‡åáÞ{1Ýë0¯H °?ô \7l7Û¿²Y †é4Áý¿À¼*23à­KÁËS|Ñô)• ûÂïÒË.zü^Jç~÷üבû÷Kñ¼0/ïöýØßùøâ~¬‹Ÿ¤`øvæ ×P(þèd‘Z—ºHÓŒtâ\ñL ÌÏBÚ4à ˜ÍbTÄÿŸ‚ÿs9†þ`¼õukžÁxþyÝÿE%— +Ðu9ÃPLCs)ÄÚs>OÚðÀ 虯ÇÊÝF5d,9£ŒóóÓó¡K¨TÂâXΰX¾z/°¸- 5àßNžäè_þed¡ÔŠX,NNb'jfÕ}ï‰f¦ñÀû[ƒÿ£Kª²WW8ËdÆ;Ìd2Ñ‚Z=_¨YLhá1ïûcDˆ<¡ðØËXÿà¦}9|(€u ú¼dˆ{=q±*‚£Dh4íMðèûø¦É“ÿûK~ËI³qËÆpÒyÕÝ„/¿.¡Gu…¨I8f˜L0S[è ˆ-X±ñ}è[¯}møyä,øÇ^p çžû%6o~)çƪ9|ø/pœ;¢ôJ¥a>ð¬Zµ Û†;î¸ÃæàÁulÙrèpË-ãºð½ï=ÃsžÓÏ\Ê;ßyÿôOëxüñµ<óÌC”Ë_üMöîý¶ýIn¾ù·¹ì²Ý<øàý<÷¹|ç;¯äMoz/œÁÞ?¾;îáÑGsî¹'ø—yëÖÝÍ£îgãÆ<££å²Ë~Éý÷ßÏùçïãÿð}üÅ_|žB¡Ä¦M²}ûv›áá~\yäNÞö¶»¹à‚gqÏ=ß$—ÛO&SàС‡ZÆ–-/bß¾::àÇ?~.6<„a<—‘‘{èè¸Ó¼´j,Ou„ýgÑÝ}%_øBÃ0øÆ7ÖDûï÷ Œ óéOŸÍÅßB:m…" §—Ô“SV¸ÙöÚ1×[]§jÄ…B(*=üð î»ï_úÒGغÕdÇŽ¬X±¢áýsî¹Xô8ptà(¿~”M?Næ½ï­œø±´¬È QÜ]òÍý”ï5é¥L½TþúMÿüùȵ¨ëf°.þ] f™Tñ¡•­Oáu¾::0‰ç,Ì7\o¸„àEï ´æ‚§;­ ÷âoßs5œv™?‰—[;NÕ¢íð2Üt‰JòùË©äÀ÷WbY± (oÅâéd2—S.‡÷P¹|½™PSËåÀµ—“Éœœ?&S¹ ùòF*ºë±>ÒLƒ•©™L§ÏÞ@á:?veÕ%Ñ lxþ½ªPyßQÒ¿¤¯¯{ 2û?9 ñ5ŠÉ #Š{$¿)—Ø Vé?Ï?ÃàwoÅ9‚í½ŒJ”žm­÷U±¥h¹ŒùÌO‰zí\.Î\”üÆð †ÄýÅ?“ÁÊÕ_Êjšà%½ñÅþ‹wÔÆïïËš‹×&`Ûq™, +iݜ͒.Èå.‰ÛÍ*1Ë|íÿ|m ?F£Y˜xÀвe\úÀ-ýnߺ%›Û:kïss‡¡üÕoc –¸—»:©lW ¼É”Ëe,ËŠBmärÚ”I³¸ÐÂcq&„– 9šlnîöþ.q°&‰¬œ!œñ”hËâçM"›Êv¡Hl©­¼5‹ÿNŸmÍÒØùáø‹E‚ À²,r¹¦iâû~K¿œh4š‰Qã½É$ñ/—þ+°0¾iÀ»€óÀ> î²ðqëTÿgˆ_Øf3îŠÌYÛvøW¬qd[ÜÊ|~¡ŠË—?ɳ_´ŠGûàÖ¿…u\ý øó÷B„–-¶ ýý£<ØÉUWíŒÜ®Xñöìy_þò¥¬];JW×pöÙ#—[G±¸Ÿáá^~ô£÷ó‰OÀ-·ÜÉç?ÿ¿ñŸ!~![¶¬bÛ¶å”Ë·b_æ _àu¯ÛŒa\‚ey”Ëyn»­7гè8æw~§—‹.º Çù~ô£p¿išüàÿ@¥ò†AOÏÁ+¸õÖ~ç{”ËÈ×¾VÀ² EÓ4qÝA`Û®{”³ÏÞÏûÞ÷.|ÿr‚ ¨j›xá «×Ì XËz‰Òú—Nx}*•Ê”\—Îå g¬9¬¾F6›Å0ŒqWìßsÏ7€msV¦Vƥ곲~ú;?åÞ­—PÙZ¬°Än1MŠ7­Ã}âÙ¾ßêg¯•?{û÷zÉ塸­îjG¶:Q€U˜åGé?žÇèZ‡¹v vaý˜¬âËuFÍöHJ_í¹æĨR¥r9´öUf½X&`ÚÕrý•ÛS¾çm^„R˾ ¸Š ‘1Rb‘§| ÿ¾xü4r¹ñ½QŒW`Ë‚G”¸ÞU±Ð´Þ2öøªådDÒ5–øq¹Hj¹&ꈘQzɆS™Œû®\Ž1=B&Ã-wÝÅ+'>[£Ñh4pî]wqÅå—7»(ã"S}‹ 5sÃb»Ÿ¦Š·Ú#xaÀÁÊ](cAy9O !0 …„s…¾¶©'è5 -<&H á$â¬8XPAy„#“PL,U·¹Ô:j—þ,Mhz)ûr„â¡¡¤Eõ»¤)þaýê~ƒxT‚V M9çÚÏÛ|!ý¼ÅXÿ Iñµr\´(»€ñWúlø¹ÉÁŽeí 7F&# …ŽãDÖŽ¥R©±ËVFÓVÄ1ÇÀÑ_yß8í6Þðò7„Ï–‹ÂljÆÁƒë¸å–OrË-ûéïïÅ4| AðŸú”Ï?ýÓ)ÜyçR #çY¤Óžwrù~LÓÄóúøÄ'2tww“Ï›‘E¸eYxžÇõ׿Žt:M6›¥\.38Ø b">Z–-è¢8–eñàƒwGmU("×ø¦ibÛvtŽ:†ëéé¡··Û¶q]7r!;Û DZ9^b©¤}uL†b~ã¶Ðµn4ô+£à~AÅÙŒsÊCä2ó{÷0Ö«:VSÚˆp¸²~f…¬¬Ô¯w§Óa¿É„iÝË/Á óyq9æ=LÍLÆZ†Q+<.&R©™µF£Ñ,\àçŸþ4vºõ'ÉZw:wè'ÙÜ¡†ùl³ ÓŠÜ ÞùO,W¶I€rq§ŸÀ¶m<Ï#›ÍÒßß_³/jד¹.œ¼XÖìŠÎ=õê.M©YXhá1ïû¤•Æ”ÌøâàNB¡K|°A83™!ýba0Kì³M¢D÷*ÛÒù a,­|Ï)û!6â €±rj r®K,Rni3—¥C£Ñ´/~µC6ªŸ»ï¾ì­Œ0ÂK„ϧijQºõä£¢ÑØAÙâ­1• Å‚r9ò܈ï‡ÛªšG¸ú±jí88§¦D}تUÿZ];‘Á² XL‘¯š>&E Ó„µk‡¹ðÂgó½ï}Ó49ûìå VÕc¸°BbQ¤ÓiÞñŽßÆ0 ÃÀó<Òé4ÝÝÝär¹HØ ENŸ|>O&“‰Žïéé!NS*•Æx—ÈårøU·‚¶m×ÄÙ®g©gYV$4ªŸ“¨/w"Tj4IÌ£&ùÜzÅ.90ëׇfƒŽé4žoT5›dv®ˆ~›I7º­€aÄbc:=Ž(˜tϹX°,Xýx³KÑ<&c¡©Ñh4‹Àó°õâ­–c±ÆµœO£˜=‚3ž]o]댱ŠÅ"†aÔ}_õ¼Z'¾OÀẊNži022npœðÒ'Y½sƒ€ÞÞ^|ß§X,FV4¦½ñÕ5?;ãY\zG^úHôüT è3ăñÈfÃw’ª§ÆhP.ÝG.¸K¥Úյ݋K>ïR(ª‚¤‡ã¸‘ëNß÷#+A€T*U#â‹Eî|éܽòn‚ÁÇqèïïÜ™†ïûxž‡aôööF"£ü/ tuuUËœ£··˲"PòSûEÛ¶VÌÂê½xÍ…ež¼è¤Óií [Ss¥‰Üóª³øØc…?RÏÃÿô7“T*üfÅýÉüQ(4 7Ó<áQbdJÉù¶.àî4§îbª. ÜšÑYÖÄn^5f#S.zî»5±Ñî@ç±Ñux-x5zÖnp¬X+ŠÕª*îÉ5 ”í"bÊõoT‡z?æJƒÏ¨w?©ùHJ[Ü&vâÕIê%ÖŸjÛLå{RlS…CiKÉ;ÂïâIÊóâEâÎÛ¨ç»n¸MÚÂqÂúô÷Ç!rDcîî®õ¼ÛÓS+‹µçxÖ ¶Ýø]NBòÈþîî°,†–Gýîûaþò]ÚF—ç7`Ý/à9ãã+xTKŠ+WÖîS‡ë²˜y²b`RŒ›Êº7±`TÓ*—c1M+©^òx× _s¤ Åb|\ÄÖŽ==áU„.AÄ/yMTʟ͆ž¢ä{*–EÄ·|>v°âû±0jYa¹¥m-+ÜávuZXlS¤Ìâ´%›ó4Œ¸Þ==q~’§i޵"”¶‡O==µuËVië|¾V¨L ‡"šflI*í­ÖŲâèbrœ\ŸT*Ü^(„ÿ³Y©×Fòùc“»i …Ç*ŽãŒqóÕC¬+R&ŽK(1õäpqªßå4šöá(¬>ùJðþ9ü>ÁÓ;\×Ų,zzz¨T*ú…D£Y`a|Gσg|~Ùq.§>Á‘3N‹ŒûËŒuÃd”‹U÷âï'ü¿7†Êé.šש²ØA,­EL¥RQljÃ0"KÄžžž(Þ¢ˆ®ë†qm8ºá(étºÆP¥(§J7r¡­0Òh€³ ó¾_T+J­app Ò$áfZŸ5+ÖŸô!ÍŠ¹êû°òØÐ„¼¥½›Uwœ5FÓ8p×]˜zÌ«Y¤hû‰É±õÀ¹üôÜcã.êrÇqZPûþX—˜«F€á÷B!µD4T‡‘®[;œ¯ç.Tæ,c±«^Yº»C+@ÓDœ2ÍðÜb1ó' #l+õ>‘a¼eÅkXÅR3ÂÏ’±¶·úWÚ —‹-:¥Þ"ì¦Ó±pY©À·¿}?+VšÑoE ­ì—Î@BãIˆF B‹Fq­™!Ž(èe!M[áuzËOô$L>Ÿ§\.3<:Nø]\’Êû`>¶—ˆž†~KAËŠE?U•öREI±î ‚ø±^Íåâv‘ëÑÕÇ…QWÚ%“ …Ç ÏÏdÂãs¹XxµíØŠÔ0Âý½½ágIGÊ*VòØ3ÍðUÁ²`ÕªÇéë›ÙÏF MÎÉêþî`i _㭄¢êJU£Ñ´5ÁòБòk.ºhRÇ[–E¡P •JEÖÑÍ Ñ£Ñhæ þ×+rô_<йáôê¾ÐÚB/ܲz¬;UÝVˆØ?’'3ˆ°¨.fÈf³c=0ôôÐÛÛKOOO´Ïq\×¥··—t:Mwww´€J\¡zž‡mÛ5«,‹Q`jFpè 8ûÉŸqîÑ—PtãxsN³¬Ï’³óÍèh¼ì¶ Ø_y¦yÂc¥Òü‹ÚݪF£Ñ4䧞ʆ+Æî_2Äã{X¸“ýa(#‡ÐXAÈYb†@Ùo«=Åê÷^ _ÝnTͺeƒÐûZQÙïPuÕFl4‘©¦a»k©)åsOµ,Bºš¦ZŽ¡)¯ ñKQºš¶ˆ”~õ|S©Ÿ­o¡¬Þ¬cWÿʹ(Çzu>Ä‚¨œ§nómª"ÇêG¡f|ã…ß`ɨÙëâ]sƸǗËåÚ÷ðªð%â¡Xà‰XX(ÀG•Ʋb1/b±J¦ ÄòO²P-E¡M„CÙŸt7*¯ò]„A±ŒQ,› Ó”Pí"öYV¸Í²bÁLÄ,) Äa,T7°¢Ïf2±*‚i6þíïó Û5RËëD>~O¥ÂöKOQ!ü›JÅqm{켿?LO®¬ÓANÒ’W5ŒN:];ÄN¦-"¥l·¬ø¿´‡Z&ñš%i&#ÝôöÖæQ*ÅÇH¨µŒ"$ªÇ jÕòÎ-#<ŽŒŒ°k×.î¸ãFFFèììdçÎ\yå•5ÇíÚµ‹Ý»w322•W^ÉÎ;éììœQ޾ þúðyTzÌ•„ãAôÃI£™cæ«ð£Q°É~x¬‚:8Žƒïûtv>Ÿ¥KŸ­ÜY,‹!5šù¤Yc Ønq|éË8xðV¯^­ìß¹e-"ÅtæÐ%î¢,|r]·Æõ»ïûd2\×%‚Èò1›ÍR©TBשUz{{k,±ÓétÛÄbÔh1™¾`&ý€OÉeýß᎟þÁÜ[; òß H:¯™øžú7 ™µhÍeÖ§ WÌ5sž@£Ñ´óÑ^¶Œ 6(þ¸ó„™eBÁ.[Ý®ŠqªHè0ÖZPD=‰Ý#/%h¼­¤S ó”®îUÒAÏPò7«çAì­ê6çú«û,`X)Äb„“ çBÝêÿä#DÎñSEu!ç)Çø„©Wý48¿ÑzIù¬Ä«Z-bqWEZ¥½% S©§ˆ¼Âù_³z\ºº­UÒFÒn"üúÄῼjyåõ>‘sQ®KFI·úz¹éñMÍ®m]š9&xbÙ2ÀæÙ&“ý67ö 0 £Æê1ÏQbBlá¸éÍpø0Üïű÷DÈ“Ø{ªÕ¢*J:¶ }by—Ü/â6UD.qa*"X6[ëVÄ2Ï Ë!— ¯Õ¡®T½žˆUï¨T ÿ‹ S_ÄŠRuØ$V‹’¾m‡Â¡ ~W­JGG—™ ‘'z¥K¾c*o¢º©iL4“|¥˜êñóIË×_={÷îåCúôõõqýõ×sã7FˆtÒaìÚµ‹ë¯¿žÏ}îs3ÊÛ÷ýpÒ¯œ}1§@ú·Mı5Íœ2_ý€«çò}ûÆŽêpÖY—óÖ·~† 6ð•¯„ÛæÂX!é—]âs{¾ÐÖœšfÒŒ1‡G@@š4ðØÞý¬¸h/Z¶Œ!â÷ÏSîâ—c÷0ýßJ¹\¦X,R(Èår‘ûTß÷ñ<ß÷1MÛ¶I¥RxžÇèè(ƒUµ3§LÞk÷Ïš…ÈD}ÁLû€€gNžÂ>:x÷»OŸÕÕã2Ÿôz$—Hk>årìs«Íhæöïpä¶XP3ÍØí¨zNoo¼Í÷c«:qG*ñû2™ðÒuªˆzâ µT ÝŠ•e¡Zʉå£X쉛Óñ„´™PO”ï»ÌŸ&ßãZÉÉÇDS5­TÖÙ¦%„Ç‘‘úúúj:ŠmÛ¶Ñ××ÇwÜmÛ³g;vì`ÇŽÜxãØ¶Íž={Ƭn˜ ¾ïó²U/£˜ç; é•`ljvËh4‹‡ùîº~v)§þ|_ü”m@èóÛ§£ãU l`` ~¨O%ÉÅOüdB%…W©‹l—ïjÞâ?Þ²âïÓ¤ˆ8*¥.j¹$˜µì_ïSóUÝT¨uSË¢ÖUÜUHÞ:<ÞäiÖ˜ÀÁ EÇêJܽË÷röÙg±G {×ÿžb×'SÎÇq"KÄB¡@Fùd³Y\×¥X,F‚c:ŽâP—Jz%”fñ0™¾`6ú‘UüxÙf²Ùyt³ÚLò›íDH¦0€[H˜fÛ‰ÍÍž'Ðh4­Á|ô÷ŸºM4 #¶,Q+(ÎâäºfޱU jE]³Áçz.`›¸²md]—iðYPçu†ûz”z*ï¶½æ£ÜÌÍM®x-Í9ý–ê†å_w"+<ÏcéÒí5ÛÅrjçŽi©¯^wß ‡½xnKÜ•JC‰÷˜ÍÆ–2ÄKU-|ÅUªë†Ûäüb1ÌGb‹¡€)bex¾Ä4”y,™÷׈Ù5 ›–‡††Ø¶m›7o®Ù¾eˆ††ˆŽ:;;Ù¼y3{÷îQçÇ·o$ äBzS“¼ªª³Úê6¨=¯wÌt'$}UéXÌš¦1ßýÀÓ£k8ý™#±òø>Üu× î¿ÿ§Ÿ>ÌÅûx†’ò³!¯X„áÃ}'‚o„ß%@°üïé© À,b£ï‡vȼ™j )‚—|ÏçãE:~S„Eÿ ö¥nYá_Ï‹}ÉKDä“`Är®ˆ°RŽ|>nR Ê,~ä!ö9.>Û¥=e`ãy±+«´ä|ÛŽ]LÈ*­b1.“¬À’•]2(“|ÅuÄb¤8Û0âö7ÒMÊê1 ê],ÆiKpfÕ „|6Œð»ÔAj·+ú·\¹Ï¤Û—2Éõ”²«×Q¢2p”4Ć¡Iq¶ÕhÖ˜ ŠïX2ð9ïs¬}ÎïGû_tþþ¿á-çÿÿÍôêæû>=== bšfdÅhY•JÓ4éííÅ0 Ç¡X,’Ëå0M“B³-¤4šyf¢¾`¶úe'ŸË£§nàÿkͅݳO³WˆϨf,¤W³ÈçÃùD¾žæüµ™ðØìyFÓÌG_0rÊ)œ22ÂŽïï€7S+8j'"È5ûÑ).aç“Ú¡-L3Ç..ŸùCž·ÿéî?ƒç6VÞÒé4…BT*ž3ƒxFĆÃÂT*v ºìýðÖ·Ãí?Œç¯$† „ç¥RµsF2˜ËÅ1#%ª‚̉ËU™'Œ‡ãéôX‡f¿.h-!QUŸâ® ßùÎjÞõ®—ðçßæ2€P-ÝD4TÿŠpåyð£ÁûïóXògiz{ムdµ’KQ3wwÇb•k">‰ð$˜üì¤û±J‚-çrµÁ‘ep"·P.æ'âi©¯¨’| ,¿ˆ‹òó“ÀÊÒm ±_y¹ÕÒ"ºªB­t5r¬XˆªV„ YÚPBfÉ92°+GéRD˜”ºK·$çËu—uêª.Ï«ý¹©–étœ†¤+n)äç(÷…« [Õ¿UñX%Ù¯ü´£ºI]'€E(•®\Ú¶qÅ’|,6›ù¬Y³fL>Ö/./Å¡Ëþ'ïpö 70< ýjèyüÙï3m àR©D‚¢*&–Ëå8æ4a¼Ç\.ÅÔhf›víÚž}ûÆü–Z‰ú‚™Ž 8Àü'süêèwÉdž3•“‡P3â°ªáf!³!ÍÀ²ë‡lžPßÇZˆ]»v100Àš]”1ÌÇûÁ—¾ô%عsç˜ÉLf1qÍ5×pèÐ!.¸à‚fe óñ~ð-Çá´—¦Ø´û%ðžf×X£Q¨3t¶i×ê+çîݻٳgÏ¢Ÿ3¼òÊ+£4=<\\Nž6Âi'OÃn Dß~û^¾úÕS¸ýöJ¥…‚Mwwí1ýýáü,žWç³Lî{6¼ö8{o­Ý‘ÌOʼH ž/Pñ±Pˆ§­ez_¦ÚÅ¢QhÆ«ˆ¦=صk}}}3´„ð˜dÏž=ìÚµ‹ÎÎÎdÓ嬳Îâõ¯}ÝI7ïrâW/á›—®Ç> Œ'<ªj„ºML‰d¿L$ú~øk—_y*/+€X˜ ‚xƒú2*Ëd&<Ù#H4Ué¥`ìˬꄹže¤ÌìK&½ŠjîcMeDT¿1 ]-ŸÔ%ÙŽWÅW…GQ{ v²¦^~RÞ$"Ž÷¯úD³²d»õöŽõå˜LCÔ#u)JòÚÉÓ¢žFQ;¼ûئ‰±q#§~ .µ ´cêù‰E#„â¢çy†ïû¤R) …ù|žB¡‰ŽP¿Q£™ äå}×®]Í.ʤHö{÷îQzëׯç—Ïù%£+àîÿÞÁ®ŸÇÊÈJ”fX¾ÆØY‡ù¦™Âg¡@hÚÞ$š%Äs;b$°~}¼­"ˆ­‹ŽI¦¢¡6þ#´eˆoM“Ù¹s笌 ZJxâ†n ¯¯k¯½–L&CGGÇœæyäGxã½á/»¡³ ÍC\7œ(PM…ÄÜG¶«¿fy±——ëzÂßD®ÓDÔkDr¶=ÉTfÉ¥3Q5Þ,¾´ÃDªÂdzÁ‰VFOTÓœXI¦Q/½‰ÚT®ÙxêÅDõUŸ˜èÁ:™4Zfô*2(Ø»¾þõe ¬ÂÏâº@nÅr9\Y¤óж.Ö{ª‹Ë¿/8ÞU¨ÿ³›È°I žýê¿ÁAÓ„eÛ]ª!)B÷ÿ¹ðo¦WAn„n$§€”'*«àâabâ>&&FÓh1^WešpÙe‡håy…ùî ||ðî†g›”ËeþïÍ7ó'ÀÈÁ‹×ÃoLs5 ¸V ‚˲0M˲(‹d2r¹–eÕˆŽ&f®û‚Ç6À† ‡3æ·bͶ:\ŒˆûöÏqÇ1Ñ"Ì¥Ùï­†[µl4vøR¦iâ+ rå³ïûAÅœö< ºªÐ4MLÓ“‡ëº˜Õ{Ç0Œè\ß÷£ÿ–eEiIÚ·Ú0ŒšYõê#Ÿe‘–aX–…W}É2M3S5"‚¾ïãy^TæÉ"õÏû„ã8ÑØ®Þu²,kÊÞ+|ßÚZSË\ö‡æyÁV\§EGM0bÖ‰Õ”a.àHÚmÔå4cLàUヿø['·î\ñÚµkÙ¿©Ôó­±F„8V£êý^,#OiÕ´=İ@ ä¸äÔ¯~Íд -#< põÕW³mÛ6\×¥³³³áqI(3q‰òðé€ÄsḊd€(nBûûc%Aq§žÀ“tªÝ¥i4ã2ŸýÀÁÓžËáÓ×lפž›6à±Ç:¸ä’¬_¿~ÌÏ\Ü›:Nüз¬°;ø…ªW`ÿ¹p6ÀÙE\â—ò Ê”£ ­ªŠHŽmªƒ ㌰oQÓ³°jÒ’mF(RxÀ¯»bKÄM£&]A¶7r3‘!CZÆh)‚èšúø\q°ÙEjH³ÆöçÞ®Uð#¸ï oàÜðÀ­ðáɧ‘œd2 ×uÉf³Ø¶í3 #Z™©EG¦>“é fÒŒþÁ KþÁä¢Ó0ïÂãb}/áÍ¢XlžðØl!!Ÿ»¾ hÖ˜`º$E/ ÐdL ⚈|"܉8&±žƒ ¨ UQ/‚OÒS÷Ë6²DÌ’m©T*ö×u#aÏó<ŠÅbt®ˆžçÑúí4ijƒ*ªõHžã%úi'©¯ˆ¤¦iFÂ¥œ+õ•vM§Óø¾}–z:UI¶mG¢l²½ è¹É2©m’Ü.m(çªe•ñ‰qúé'øáëôÄp&Ô˜€ÒmH“‹à“"Uµ ­êð¢H‘¹HÌ+P¨±Rôð¦lµ(øø”)Gß­ê?£$OUlAÒ¬þ«—¦˜2³°(SÆÁi áQê/m‘këÕ9 ˆ®åDxx5b¯üMŠÄj6Ê×ÄÄ«ZœÕR‡i±ÞüØ›ç»É'Å| ¢¶ÿU‹ÿxä.2™ ß> §Ý6µ¸AJ¥(•Jd2™¨ÿ•¾Zž_†aÔÄwœO¦Û‡Læ÷áá¹ ‹Ò´¨õ‘þ+ àñ57»8 ¯/˜~ÀßÿÀ{yù¹ól9%x›EOÏä|¤ÏÍôÆ¡Œ³d£gi½±–<¯å³Œ×||2d0ª&pÕ¥‰ï‘žÐŽË\š1O0D¬êéé‰B±LŠU"š‰ vY˜$”çyd2™H„DÀ“IMo®5©àdW9U4U­*ëYÊ8Jmky·–wçR©½çr¹q·¿:A,Ö‰õÞ‡E4T]ݫ§zý䯔WÞÅ%6·Ú6’§ŒòŽA´Ï0Œ¨ÌžçÑÛÛ[3· çJŒpµõ©ºÇ­_ÿsúû×FkìÔõvŽ †™LELX¬k5 ›–ûúúbÛ¶mc|Ç®Y³&ê,vìØÁîݻپ};ÜtÓMttt°}ûöiå{ñÇ/æ¾Ï?ÎëDttœXptÝ–ûÕ«bœêÒ£\.G/*ù|Ó4Éd2d³Y,Ëšñäf#S}¨·’N^dp,Çäóy È„¶b±HoooävNîŽãP(¢»mÛôô„Azóù<étšl6Koo/årÓ4I¥Rd2ŠÅ"…Bb±H©TŠVMÊ L×uÉårQ“BfòEB^0¤üR¾t:‰yår¹F$”2ÉjM¹vÙl6jOu¥cò%AÚG¶ÉKA.—«Y¥)b¬l+šuëÖÕ¤-íïº.'Nœhöí<†ùì‚ãËž×ÿð‡ðº×EáE%Ä©ëªU¿äª«ò­omh˜Žjå^ß±ûU2d"ѱŸÚReÊãNÒOW0€P<œm@$UËGƒnº#n<Ô ;·NÚTÁ#)Àªû$=IDÜUEÒ‰HZy6^Õýr^µœª›l)gR„+ÕÉbcã⎱D­'Zù»_æ»?ù.¼zÒÉÏ ÍG øÛŸNuQ²m>vÎü”¦÷Í0 úûûǬP—çœ<¯›Ož|$¼«¿Uw’LÔ{S~oÉûU¶µÃ"µm&-"Ì0uàââã“&?æz¨¿ciw{Râ°JŽîµ.¯ë{Ýœ×yªL¦/˜i?ðÀÒ_ðÖ·®œÔñ³F:Ý\áÑqÂÁÎ"µ¶Ü{å-}5ý•ôƒâ1B~K.nôYåÉD⤺xK2å÷k``cGé¤I×ô»ÒˆÐ)ÈøGÆ1êb&Ÿù²¨LÒP÷C8¾ŒÆQ°Gþ«Z.音dqp87}n³/Íš5O0UR©Tô®¦ŠM" ©ï£Óq½ÙˆfzL˜êxF=¾Ñ¹ê“ÜnšfÝXت+ÕziMg 6Þ9"[–U“÷dêš,o²ÌõÜ–¦¹xa<³Évzýë_ß’1ç£/XòÄŽÿ9pQ³««i%’Q£2ãìk´-ÉhƒÏÍ¢M†ƒÍ„c>xápl¼ sˆá°ÞçÛß~>ï}ï0?øÁ¯’ÏÇ‘ÙÄ8AuR`YPL{a¹FÓ‚´ŒðáÊ…$Û¶m‹»îܹ“«¯¾š«®ºŠŽŽ†††Ø¹sçô|9{0|ÙsâW3Ë WÿZVS"«+äÄN„DÓ4) Ñä¥dêŠÊ Èf³5îEd%¥aäóùh5žˆRj¼q"1©ººº¢—&IO„ÄR©YxˆÐ'«õD„SWóI™Ã@»á9êJ>q=ÓÛÛ‰jžÃÕN^êÓßßiš âû>¥R)Z娺C)—ËÑˉmÛ‘`§®Ž7#"öööFb mÛ‹ElÛfppð§Ë¶íHä¡W]Õ©¶qn¢ú6²ZT·KÞõŽmÅ@ÑóÙøG|=ûž^¹’ ×@ìfÕ¶á®»ºH§;ظqcÃtÒé©­O°±I“# ÙØ)6t[Únˆu@ŠTd(“^“D©VIÑMç’ÛÔ <Ÿ^zŠSôæ›™5õî£z¢õê§V³òØ,RÁ¯%­%¼~J§%û(UTtpjúQ¥?õðpq£ß£,8rpjbp'¹U·üeÊäÈÕ,)SÆÆŽÒ•¼ŸzéÅø«OPüÀЍÏꡇ%J”ø¯/ý¼¦Ù¨–f &"ŸÏS.—£¨òž*ï|ª§UØieÏ3M+3}Áÿ.~úÌOá}ZxÔ,2Údh³Æ—bãã3¼u+›ªÛ't™*k;¸„|Ö®}ëÖ…ÐÆ“Í%zxmµpW£%£££­°¾bJHg³eË–Iu»víbÛ¶m‘É5tÞ{§\pß?묦L?‹è'«"]×¥T*‘͆“A¹\.!¶€Ëf³ R,)—Ë ãyù|>rÉ"®ëR,# ⸠Žb×­Æ$èíí­‰=‘Ëå°,+3U7’˜·rår9àÄbO/¡i.×\sMôPnW¦Ú¨õN §p×Y|j÷ 9ÿÌQlGù¹½ï}ûøØÇ~ΓO¾Ï›Ýu&×—°„¹ã–Pè·«ƒ4£ú&¶"ÔÌ=}}}ôõõ±sçÎfeÆõ€™ òåñ~ê‘#GOO×~x˜d§¾Uúȳ½\.Ó«¸3T]u/²dd°¦ßwÌPka™#\˜# ’‹ ÄYÅ¡U11É×j\ÜD×s‡œÕI 9^òLö9==áùAž—ÉÔ©OU šf˜F²L¾¯À–`t…BmýÊåZñ†šs©äóá1R—d>õÚ2ŸóQÅÞÉ´Q²<–U[çä~ÓŒƒë%ëÜèZ¹nø_%)J;NÜfÒ¶Éû¢\·IÛ$}lÖ+‹ä£îK¶Ádʧދ’†ëÖ¶M½z/fsLpÆÏ,Î=rZÝg¾ëÂ?þãC@x 'ö¦¦Ñ,vÚRxœ þså!` ¿ö±ÍÉË·ïûd³Y*• ùjg/VƒââT„»uëÖ‘Ëå( ‘;U %ø¹LVªÂÝdcCÈ9ɘê¨|Î(ãVˆC¥ÑÌ'—,Pbm†ãÔB! äóÊyçÍï$L=¢fžxø ‡;…ï>ý4§œò‡¼ûƒp×$EGÕ­¶<³Å%·úé§LyR}\ÒeêdYH‹6æ UÀ8ßù-éju>ðÏÙÀò'5»MC¤ßœ‹~NÄ$=þ¬ˆoùTø.?<µ±ÇˆÆÒvâÒù²3.ã\Ú_xœO<ñD8Çæº¡b  kù|¸Íuë›2y^(–J¡ ”:Ǩ~– o¹UrÝ0\.‰DŨŸYDG)Wrž0™O2ÆtŒSëÍ5ŠŠ2žÇ„ñ ººÂ63ͰùüX7™·ïׯKÖÁóÂôT—²_ÌÎ cleŹä%¢m2I¿^»IþÒ~ð/iÔ"éõÄF U±î—kœLW­C½4Ômr©Bvòšù~(TO3žìBÅÅåL?Ço}çÝpq¼=ŽÃ¦ÿà¿Êç?Û>Û«k4‹•E+<¬Å–‡ö,Ä܃Z±ÑuÝÈõ „…¾ïS(Èd2äóù(&Äàà`]qp¶‚Îk4šZ~rêϢϲ€,Ÿ‡ÁÁpüeš&™Ìüþþ2dZ:æ F³ñ6ÝÏò/çëC'xüËW±éÖÉŸÛÝÝM¡PÀ4Í1ž4!Ó5s‡¸–]쌜²–5GÚ.ꄦ…sPã¹·Çq.Ò…ªšïÏ0µ…ƒ[ý¡«Û¥ÿ³”—­z©e©HøQ-õ,¬«ÑV#žDµš‘¯@!¸òä#Á-G.ŠOš!y7wÀ"˜98ôÒ;ÆûI–l$ô2J‘b$”YXôÐ –9r5÷¾ˆƒI+IUˆÁTbU‹Å¨ˆ”YÄcI;Mš…è¸4éHŒmôÛS㺊¨*B¢ƒƒ‹K‘"%Jc,@MÌÈ:T„M?j›4éè©§jÁ)q§Ë”ÉÁÆŽ,C]Üèxq!Q¥ êbñ8Q¡ÂªUôêkömÙ>þñ³µ·7^’–c™L8aP©Ô7\H§C- ··VS™È PM/› ÍL0ŽžÈ5ìDû-kb¡)“™y9DÔ«;Ï '`’ÏeÓœy&S–ù¨³i†÷Ãtò ‚p²ª¿¿¾H=QÙ ¾g¿ñæ¿'Ì+“»îš8ýEÄϗ¯ùŸ®Š¶åóáOÕ÷á¾û.áškFyãÃ}ét}Í\³ðñ•ê<ˆ,:rqkžçꢴäB0¡ÞXC'¨ ÀѬÅÚ‹Sxôaÿ𧏸?šøA1<ÏÃó¼Èª1NÓÓÓC?¹\.rÏ]‘j4š9ƃG,y6Ä ×d±X±®`žïߥŽw¨Ñ4ÿìaN?úrßt.ÏþçQ†×.™”ýGô÷÷ãû>ÅbQ?Ï5mE½—šÅƑӖsÎ}‡›]Œi!a$ƒ,~PAø¾_³Ò4M\×%“ÉÔ„qøì™LÇqÈd2ÑIô‚ Àó<ŠÅâ˜P s‰ã8QÛÛÛK±X¤T*ÑÕÕE¥R!•J‘N§q‡ÞÞ^zzzeÉ’%ÑþR©…“w2i›r¹L©TŠâÓg³Yr¹\·^U/±ü¤íåœ|>O©T"›ÍFßÓétêû>™LÃ0(‹†aÑ1ŽãÔ¤%õ+‹lü—ô~¬£+¾ÞADñ„Ç¡T*‘J¥$›ÍÖ¤!¡<ä>‘===¬Ø¿‚ìë³úùU% àÚg®åøñãùùV}j7¼ë‚5ádQ/½ nÌ>Ñâ zq¦’Ö“’†‹KŠÐ­c½ ²èE&¿’n~-,ŠI“S.c̤Y²êþzÇ â ¾L¹®@:Ô¼‚(–²Ô#Y–ä÷€€"Elì†çLw+T&ÊC=¦Å):¬xøaVÜxc}¡g2’m‡“ Ó5lH¥Â|s¹ØP„º…€mÇÖ ¹\ئúÙ3>¥ÒìÇþiD„JšŽqZƒX‡ßù’Wqí_~r9þIŠ‘«–vw/©9·Ý~ºã‰VIDX1l*çç-`ªˆP'ž ’ÞÆCÆu2n™-Ò¤#¯Þœ.öUÝß«ßEœTËÑOS¼œ,Ná1€Ê+–rÁÀyÓNB^ØäÅÕ4Íèe3¨.kH§ÓضY.Ú:žŠFÓ|ªcÛÕ‡ãºá˜WÝm»^£ÑL|sóÁ‹Xö¢ç³ô¹Kp`R¯ÇÁq*•Ê¢‹ß¨Y,v‹O½`›6 7-å]¶í(Dƒˆ~ò!"•,nLŠJ™L†T*‰s¹\®F\T‘¸ïbAOA “’~OOO”Foo_ÏÈû•ÄÔ«rñ388µI:¦¿¿€ÑÑÑšãDlíêꪉw¯Z©‹ ˜DÆ…"øIÈ Ë²0 ˲¢²ÉwIWSJ»çr¹šë)盦I.—Ã4M*•J$|>Ùñ$ïêyWt¬:VáØ¶m†‡Ã{YÞ?ûûû±,+j»žžžšÅ¯ÃÃÃäÉS¨„Û®¹æšy½¶­Hž<ÃÃÃŒœ5çÃÝy7/\óÂf«m˜È5ðD.deû|ˆ»â.v.,$Í©¤=÷º“!C¦Æõªfòlü× '¦+ôXÖØX}S=_Ü«Ê÷…džN‡í#ÏÅvSeæØß62ŒðéëRƒ*ª=ùÝõìSºÏ uô³ÏÞÏÖ­Þð†OÎyy’â`=WïÄ=ÕZN,ç†âáD±’ÕöQݾÇdžï“Éw6ÈVÿ©^ÄÝúdòOºÇ÷ññðè¡§Æýûl ~I/ S‰U-‹’JŒµôKLÕsÅlŽÃ¥ðèÿ)<øµu¤¿öËiïº.©TŠÑÑQŠÅb´º¸R©Œq±¦Ý¥j4-†Øpæ7. üåp,_*Ih×u£ )F³ðqïuÁÿ9/a £<º1'‰õŒv­ªiGdB²ÜÎ Kà•ÅŽYOVÄ) µ`šfd—J¥èïïö‰å›ëº8މh^9–ËåȲÏó<†‡‡1 ƒÁÁAòù|îÁ²¬HœŠH(‹'ÄšQD,IS]º®YGÎ5AŒy¿*$Vâ‹'åOöɪðgÛ6™L¦¦$½FÇCòjtn²,²8UÞÕ²Éç䵋ڹÁ£FK5Ý\uÒZò—´D”Uï‹zÖl‹‡ÞÑ^èóÿë|ëx¬5EGßßJh¢ØqsˆLŽ',Ž7¡8—1Mëå%“m³Šïc™SÇÔ}¼ëìûáÿ:±ö,¬pb±…ï“Veßþ!ë/¿|ú ¤Ó]¬N±”kºÐâì‰ OMëR*5Žß¹ˆY?ülžõó{éþ ?ójûÛ†'Nå_ÿõƒ³Út=ô`cG®»Uê=GÅâjŽñž§"º¸ Ò£ÃDˆ÷ƒ¹Èu©´ËdH¶—¤!âålÇROæ7•tÓ¤I‘Šâ’7Šžü{ÎÖsxñáϨ܋Rxt^«î¹—TW«þ på%Û0 r¹\´jTV¬êÉG¦ pŒÓ–Õ|ÎçóÑ*F³xð·øØ'mÜe0úœ%0á4¬ïûôôô`…BA?ÿ5š¶e [·Nßm¨ïû‘x˜ÏçÉår‘›MÏó¢1…mÛ‘Eãèè(år×uÉår‘$–Žétº¦O±,‹|>OoooäVSµ„„Ph*‹äóùYsƒ*é'Å+±¸›ˆzÖƒj¹%ERŒSÏ“všM×®“ç ½ µµqp¸èñ‹}¿à÷ŸzÞ7n¥b!@b¸ år(ÞFìg-y¯¦÷]¾¦¡ÞƒÅbèÚÎ0â`PÃõ¿]]µVO¹\mår—KÊâûcÓXRuÿ&¢³eÕ¦áûaY}?<&º¨iäóá~Ù–Êe¬?~û‘‡`w5NžÚfù<ökNÃúÇᑪå“"®˜^€yÎJ¬?úk8†¿c#m¦.¬¨×îA›£$ëëyX_ú\ðücõ%Ë*í!®33™ðZ¨$¯E>–Ï4±?³ûö }Î’%ašfX¾j‘({Ë^ø`¶öš&b'Ë‘ÉÔ¶cÑ Ë¢’t*m$Øvýxp‹ˆ§V¯n®èbÛ±¦…ŠvãÙÚèqÊ||V;ŸSy‚¯ÚÂ?(ì:åѰdÉÝô÷ÿ †ñ±YÉO\’88T¨Ôc³Éd]r/DDxœ wëÉteaÓlº• 66*¸¸(àâ’#‡O^ä B„Sƒþýýœñ“3àÕÓÏ{ñ >ÜzõcœÜ÷Ûô\±¯æ&éVáåóy<ÏÃu]úûûkâsèIG¦=ð×…/q òêÜË)e±h&rU¥ÑhþŸ'ßlÀYpÆÉg°–-÷xÇq¢\ïK£iWÛÊÖ$âÖr²¨qõ|ßÇuÝ(桸·´,+rûYÏ¢ b+¶T*Y.ÊÇz}J¹\Ž\Ösë,qçÃcƒeYd³Y t*q Õ¸ˆŽãD®G=Ï‹,:mÛŽÚK¼Ç¬[·.réZ((‹5ñµ Í|ñ•g¾ÂÓš.ü3æ:FÖóÞ EêïÓ4cqȶcÑOíSr¹ÚmÉIݤ˜YïÕ꩎…¶]›g½w™þþXˆ ‚úVG¹\˜¾WoZÍ'ÙwZXöÁÓ±º ¬McÓ0MÒË~óœÓàêÆÑKz=Æ;ÞÞ¸=êµY½ºŒ×¦¦‰ýòb¬þ džSß:°Pˆx9Nø}p0Ü'l²™L˜·ã`ù%¬ç½rlÙTq/‘g† ÆË^¥-ñýU¯®I!2éŽS„R^ë1Ü<7㚘fãë¥Ñhš‚ÏèèrNÞ7ĉ¿e…„bN?ý¿ök_à[ߺ~ÖòQÈÆ& MzÑ ƒs…EŽÜ¬{>˜m!s¶PEæFq§“ZØÆé;6³ØÏ‹OxüaÀ=oü*\tJ5f°=ôDA?Õ‹&Íí¿WäÕüýÑÄB3WÌj4šéá/ù2ƒOœÏãÊ;µÄEÒh4‹‡€·ûVVÜÿ&Ø÷4/²N×a…ˆŽ2¡®-¤5íŒXW,f&;–w]·ÆuªX4BCb÷–¦iÒÕÕ¹µ/M‰õ'eñÄrŽ,!ñüæÃ0°m˲¢ò'ÿŠ…§êF,9¥Í%£ü•ö’~UÜÎj+AÍ|ààpâØ1^røe‘¸o¾â³ðŠqî?ÛžX$˜h¿¸Vœë4¤oh”–iÖŠ‘õŽ›¨¿4M(ÆŸnËdÂý¼v9ãïaÓ8í>mf¯xc8ã³u‚6KŠÍêßze«Ö3ƒqQãÆ)[˜“ȧQ¾‰:j« ÑïM˱ôäeœõÌ)@¸ž£X ×¥9r+Vå…/Ü4«ùU¨,úw´ùb.B,ö…½Iðø_?ü ¼ñ}¼èë/"óŠø¡na1H8qàãS¦ÌÁƒy衇øðæè¯å´‹Ncë²­°)N5tc,#+• ]]]‘§¢&h4í‡ûÔ~Ç…î\Oýüê Ò“|À¨~÷Ç[@"ó?%®<&`CÕÑRX:ŽªéšÕÿÉÐo™jºAõxµŒ’OºZ³z¼äcUÓ¶«up”|üêß@)KQùl(u§NXŒmI/¨/ÿÕãìêwˆyJPΑòIš^u{P=×Oä“\ÏmWÛÒTö«ùXÕï¾ò]­›ä/ç©÷Cò¯M’å«wŒ5ÿù¬8¸‚ÅJ÷Ánþxãc`„noõä¿F³è žx˜ƒk-V=Š÷ÓXxÌdàŸþé;ÁyÍ.¢FÓÒ,:áñë/ù¾—wUp±XŒ\õööâûfÁ4Mòe°,ƒtÚŽL¬ÁÇüuâAKHì q¬oõ³œûr‡ó¯ð9ÿs9Òét˜‡äešáöÞ^èé‰H‹µiÈ"nlj¯q>‡g¨zª‰òžn}åsàÀâ]EþË•+ñ,Nœ8½fÅ’F£Y„œ漟¾Žã¯^Á%k†©'¨±ÉT·ˆM»“©ÞñZx¬Åó¼èÿx.Øu|Wfaðóõ?Ç_wÇî\þ®B¡Í#»•ƒê6¿zŒ ä€,Ô¸Å-ÆÕ.佺žPç'¶{uÎuÇ9e›G(EjEÝäyåxA½¾™j½“ùTùÈ\Œ_'C)‹* «åËUÛ_ê/Âko"ŸdY'ªU­O5Ÿõ¿»^À¢ä²C—Q¢D‘"yòl9n±ê¸ÁSOÁ%',Žƒ}ûjÏyÁ àþÃ`Ùaƒ+Î7yäxàxÿùçÃ+^ÿøá÷bqlÒ—¿yî¾¶n… àß¿Ÿ>¬^ž—J…ßßýnøú×Ã|î¾;LcëÖpßîÝóÙ±#>'y¼ Îÿ‹á~ÉcÊù|ÄÆ¶Ã9(™4ÍpSæËÔ¹ÅL&<®X çhr¹¸,õÊ—Ë…ócɹõ˜þ~èî® ÉÚhŽLe¦sqžÖGæg#ÃÓtœxÞWΓùjÛ?«i¨õ­WVË ÓuÝ0]ÛÓúÑ^â'€G ÁE¯=; xKØ~ÃÃ>þçOè÷f•ðèãslÅQ–վAøÿãßÏ'?iñ¢æàÁ“ÍÆoét£[â­»îØ¸ßò=éR_ö«=Õõ~øàHcŸd⇇ü5 Xÿs‹G7zcê&y&è}`Øí5ŸMsì1j½ #~¨I~étX¶dÝD€3ÍÚmj]¥NòW"”ªˆ˜ªÖ/yŒi†å±íø¸d¨õ¼FiÈßFeQC`H›%Ãî˜&T½qaYÓÏG-« $Ô6™L}Ôë bê'>ñ=`q$~|áb%O>¹-ŠÅ¢Žï¨Ñ,B\ó§¬8–4\÷ÈX—Xžçáû>†aP.—u?¡Ñ,p<Ï£»»›þþþq-Mӌܮj4šöæ¢{ÓÛ?>? 29BáÇ"w*@½Pyª!t=g"ðä&q~¥Öد.õº¤Ê$*X™âñÓÍ'=Åãë9pU>7 O˜ipülçShp¼çøzç5r˜‘¸Æ,_½ë3ÚàóTêSÍg_ß>ècÑb8ÈgÀðxÑ{öží2ü(Ü6¬YÂÚµDsr§,‡§^ OßX§žJø¥Êƒ§Â£+‰î—"Œ¹w¾·Nž„¯ƒ>?_¼¸6üè_Ÿ<ÉÖÝËØ½Ž®óÙ|ü8§žú$ëžeð8`¿=<þK'áü|‚uëNåСQ·5k'>¿aÆè˜bÑç‚ .`hÈãóŸ·xä‘G8ãŒ38|ø0gŸ}œ5kÖpÕUǸè¢õ }Ÿw¼ÃªÉgéÒ.Þö¶‡]Ëš5³jÕ)lÞ¼–ÇGù¬[g’JÅù¼ãq>W]u˜'ÎgÝ:“«®ú%gœqFÃ|–.íâÌ3Î>ûlxà‡?þl{?>¸ŽcÇŽqÖYò­o]ÈúõG8ë¬Ó8~|?/yÉ&V­º—‡~÷Þû ×]·¾¾c\pÁ©ìßÿ(—_¾š VÐß?Ê}÷­ã“Ÿdtô9|ó›OrìØ*–,y£G¯õs„{­ŸqÆ#bgGsª¡îÒ×çòÇü¶f—R£ii•ðè>é²tÅVÖy E)lj­×r99…÷½ï|®ºê÷¼ÿ¾öÄ_²æ×ðÆ7þ1ÿøÅüú¯ßsã)+Q|îs¡9^:Æqr¹\Ô^ÿßÿ¦ŸË¥Øº5lÇt:ÍÀ€ʪZ¶\.ůÿz?•Jž_ÿõùü_S(¸ãŽr4ß³o_¸€lß>ŸË/Oóæ7¿‰ÞÞ^J¥,½½½üÝß…çîÝë`š&ŸùŒƒaض#ÇH>ÙìŸR*•øö·(mÉçsŸs( üí߆e‘såï¾}á9RµlrÌãçyÏ{ äóN¡PÀq¶n5q]—¿ÿ{xë[m|ß§£#ÍÞ½ùè>“¿ÃÃÎ>ÛᬳLúúÂ|N;Ídùrw¾3M>Ÿ§T*10çºëJôôü]]ç¯köϲ¹ `Á)½?žþw#oA^”¬ÑL‚%£££“Y'ÖÖìÚµ‹mÛ¶ñ·ëoá‹]…¢Q}`†‚c&–åáº.Åb‘þþ~ÌzŠU °ŽuŒNjyŸFSŸk®¹†›o¾¹ÙÅhJ½ÿ­ôŸœùÅÿÇ#W½•ÑÑ8~›ž@Ô,6úúúèëëcçÎÍ.ʼ"c‚åÛ–ÓM7˼Ÿò–KøÌæ±Ïý|>eY¤Ó‹×=µfá#¿‰mÛ¶5»(óJr,”Ïç1MSÇhÔ,ZãûŒ….}Ï¥ÜöÙóÙß>= ™(!U&Z‚$¡%Ü`» ^S ›(##Õcl=OþT¡¬žh'!“ù‹Åg£¥ j¸Ã¹n‹,±ÓÙZšê‡Û”Л⩷™ˆØ+#ÝF¾úUÞÿÎw6¹dóË®]»øå/ßDWWWäÝ*òù<™L†T*E¡P \.“Ëå¢í"ÊA(~Ùv(‰°˜N§ñ<Ó4£sÅ›JPu›%çû¾‰–À˜…Ѿï·ìO¿^]¤YØÌƜᢲxôžåÑùý7òýïï «+ôýº¢ X·.t«”N§[úa.®]\ì _}4M’§=ÁÉýçÕ |µµ£F³øî8óœMAÖk¢|6l€â#¡µc: ‘Žæ—ÉÌýu›L>[·®çYÏbÑ".Å*1ÏY{E˜&&ÎÌÒhšÈWŸã²Þ¿‚“'߈a@©öõúA£™<‹FxüÁS_ 6~ó2¾8‹ŽAP,Ûn…sžÐì"4…—öm¦—Q–žŠ »M£Ñ,>üŸæxzÛŘ÷ùð+[¢íÛ¤0™ÀȦíéêê¢T*iëff‘²ùØ1.ú§µ¤Š¡€dÛ¡øäûñœüµ¬Xø1ŒPÔ1ÍðÒ¢G=×0#ÛBOLaþãÓ®ù¸n,æærÓ/g>¦S*Õ??ÏI^»ÉÖÓ0âú×j>AÞÓmÏñŽ™ïëvðà!zˆEK±XÄó<*•J³‹ÒÖ˜˜¸¸¤H5»(ši²Xç …€€½›Œ›¯çOþ¤“-[ \Whè0,Íäi;áq×®]ìÞ½›‘‘®¼òJvîÜIggç„çýoǃ€ÅÁþçEƒ¯T*…išmgÑP¢Tã¶@£™*ŸøÞ'à5Í.Åô™n?0´î‡¼ôØ ²Ù,¶më‰F¦™n_ðì/.ãGÏîdäì—ó矨ٗËåô‚¦˜n?áÄB¡ '4šÀtû‚Ç_Coohõ¥3‰eŠçyXVøî¦Tã®Ù¸n™L&C±X$“ÉÏÉår¸®ƒiš8Nøþnš&¾ï“N§ééÉS(ÈçÿÝÝÝT*Êå2¦iâUUN˲ð›¼àÍþ9ψéö÷ß?–e‘Ó~AgŒM-Þ¶3‹uÎPposyê ¿ü‡ð/Œí¨ç4š©ÓV£tÒaìÚµ‹ë¯¿žÏ}îsž;pÎQxè2®½v؈ã8 …¶t±hVÿi4Óå³}¶ÙE˜63éî»ä^õªî½×j;KgF3“¾àÔƒ?àËïÿK¼€÷nÝmÏf³†¡$h4mÂLú!j·iMû3“¾àÌ3¡®C‚ÇqªÂ`O$ \×%NGq MÓÄu]lÛ&ÂP(2Ž!Oâ¶É„¥aUÑÒŒB>ÈßJ¥ rœŒIäI«R©`š&ýýýÑbjÃ0ªB¨c…B ˆþŽnFržiš|üãLªlÓ©Ïb?§¯¯¾¾>Ú•™ô·Ývëׯ׋‘f {RÑa5­Êb3À…[ù(`óÞ_/ÑËR,q]W[Ck4S¤­„Ç={ö°cÇvìØÀ7ÞˆmÛìÙ³‡+¯¼rÜs?zËïßÌ»ß} AÍféííÕ“‹M›1“~àä·]Cô¥ÿh¯í¦–™ôÿ±åvž>m)/üòøƒØ­R&“Ñ㦘I?¡…³^„¤Ñ´?3í \×¥§§‡R©D±XIJÂEŠª‡¤z–P²xAbÁ‰¸#Ç[Ü ýOòïxV«¾ß¨cšzã›ÙxJ.ØšL>ò]=v2}±~wÓLÄLú‚÷¾÷½lÛ¶­ÙUÐh43dÆc¾ðW÷Â]ïá5¯y'OºX–¥ç 4ši°´Ù˜, Õ :;;Ù¼y3{÷îðüŸOs‰»‘b±H6›epp°­&vïÞÍÀÀ@³‹1#ؽ{w³‹1cvíÚÕì",ZfÚœ}ö“ VNbYVÛ®d\÷ŸîÏ43e¦}ÁW‰k¹vô!²Ùl4¹hÛv[¸PY(÷ßBèÏBÚ•™öÆhYL“ ¥ï˜*‹ñwº˜®õLû‚£GÒÝÝ „âa:fpp°ÆòP,  ú7±xXL×z6Æ‹Åt a.b:,–k=Ó~`ß¾}üWð^N.?Ì‹n~¯xE'===AÐ6^Rµ^¿Ó…0îØ·o÷ÝwߌÒh‹ÇC‡ŒY´fÍšIÝŒÛ~ùAFGG±íßmK7jCCCSòGÝŠ:tˆ¡¡¡fcÆ´{ç×ÎÌ´"WIí .Ôc!ܺ?ÓÌ”™ö+ýg±ú/ οòYìÛ·/Û……rÿ-„þl!Ô¡]™1Ábc¡ôSe1Þ‹éZÏF_`YÖ¢²fп‰ÅÃbºÖz\0uc»,„¹ˆé°X®õLû%—ð›ŸèeÉ£ïåÅ?½‰löç‘Kóva!\ë…ð;]ãŽ#GŽ0222£4ÚFxœ K–,áÎ;ïäøñã,Y²¤ÙÅ™Äó̾}ûxê©§"WD‹‰#GŽpùå—sÆgpÞyç5»8óÂBé;¦J;ÿN§ËT®õ¾}û8|ø0›6mjv±çÎÎN>ÿùÏsê©§’Éd8ãŒ3š]¤yAÿ&S¹Ö‹ýýàºë®céÒ¥lÞ¼¹ÙÅ™7c_°æ"¦Ãd¯õbŸ3\ºt)k¿öVFÿü œ¹œÕ¯æCúP³‹5%Âïz!üNÛ}ܱoß><È+_ùÊ¥³(„Ç?ýÓ?åOÿôO›] FÓdþçþ§ÙEÐh4MF 4 @ooo³‹ ÑhšLgg'wß}w³‹¡ÑhšŒ~?Ðh4•þJøáŠf—D£Y´MŒG¡žR¼˜V$i4Ýh4šÝh4Ýh4Ð}F£ Ñ}F£Ñý€FÓ´ð(þ™“Á`ûúúÚÞï¯F£™ºÐh4 ûF£ûF¢ûFº/Ðh4ºÐhZ¶vìØÁîÝ»£À–7Ýtlß¾½ÙEÓh4ó„î4 è¾@£Ñè~@£Ñ„è¾@£Ñ€î 4î4šVbÉèèèh³ 1YFFF¸úê«¡££ƒ¡¡!vîÜÉŽ;š]4F3Oè~@£Ñ€î 4î4Mˆî 4 è¾@£Ñè~@£i%ÚJxúúúزe Í.ŽF£iºÐh4 ûF£ûF¢ûFº/Ðh4ºÐhZ¶5F£Ñh4F£Ñh4F£Ñh4MkÑV15F£Ñh4F£Ñh4F£Ñh4Mk¢…GF£Ñh4F£Ñh4F£Ñh4F3c´ð¨Ñh4F£Ñh4F£Ñh4F£ÑhfŒ5F£Ñh4F£Ñh4F£Ñh4͌ѣF£Ñh4F£Ñh4F£Ñh4F£™1Zxl"###Üpà \vÙe\xá…Ø¶Íž={Æ·k×®è˜ë¯¿ž¡¡¡)íŸÏú\vÙeôõõM¹ͮǞ={°m{FסÙuд/“é ÚéþkÔ´Cf£/hv4íÉl &{Ì|Ô§]Ç0q_ÐuÐ,LæsÌЊ÷ð\÷-­Vçùê‹Z­Þšñ™Ï1C«Þ3é Úí71_s­TgÍä˜Ï9ÅV¼?ô˜`ñ\빦ê|ÕUWµå;öB˜÷áúë¯ç /ä /䪫®b```Êel•ûm^ælF5Mãꫯíîî½ãŽ;Fï¼óÎÑ~ô££\pÁèwÜóÑ~t´»»{ôÖ[o½óÎ;Gßô¦7¾éMošôþù®Ï\0zçwÖlŸL›Y;î¸cô‚ .-—Ë£wÞyçèûßÿþÑ .¸`ôg?ûYÛÔAÓÞLÔ´ÛýW¯/h‡:ÌF_Ðì:hÚ—ÙLö˜ùªO;Ž FG'î Ú¡š…Ë|ZõžË¾¥Õê<_}Q«Õ[31ó5fhå{cº}A»ý&æk®¢•꬙<ó5§Øª÷‡Ìþ\E«Õ{>h§:—Ëå¶}Ç^óž’ßwÞ9zçwŽ^wÝu£ÝÝÝ£‡št›]‡ä5™ëûI MâСCc££áM|Ýu×Eßý×}ô£ýhôýg?ûYÍyíŸ/Êåòè›Þô¦º7ìdÊØÌz¼éMoªÉ{tttôºë®½õÖ[Û¦šöe2}A;Ýú‚v¨ÃlôÍ®ƒ¦=™­1Ád™kÚyL0::q_ÐuÐ,LæsÌЊ÷ð\÷-­Vçùê‹Z­Þšñ™Ï1C«Þ3é Úí71_s­TgÍä˜Ï9ÅV¼?ô˜`næ*Z­ÞóA;ÔùÖ[o½à‚ ¢ÿíö޽æ=÷îÝ;zÁŒîÝ»wÜzµKß2_s6ÚÕj“bÛ¶mlÞ¼¹fû–-[``` :NèììdóæÍìÝ»wÂýóÅÀÀår™}èCu÷MTÆfÖchhˆš¼n¼ñFvìØÑuд7õítÿ5ê Ú¡³Ñ4»šöe6Æ“=f®iç1LÜ´C4 —ù3´â=<×}K«Õy¾ú¢V«·fbækÌЪ÷ÆLú‚vûMÌ×\E+ÕY3yækN±ï=&™í¹ŠV«÷|Ð.uÞ¶m7ß|37ß|ó´êÐìz.„yÏŽŽ®½öÚ1uPi—¾e>çlN·Zijؼyó˜cdd„;î¸#zp:t`ÌÃeÍš55Fû烑‘Þÿþ÷“Édêþø&ªÃd™+Äÿpgg'7ÜpCCCtvv²cÇŽ¨>­^M{3Q_Ð.÷ßx}A;Ôa6ú‚Vè“5íÉlŒ &{Ì\Òîc˜¸/h‡:h.ó5fhµ{x>ú–V{†ÏW_Ôj×Z31ó5fhµß„Ôs&}ÁdêÔJ¿‰ùš«hÅk­™˜ùšSl¥ß„ÔQ æf®¢Õ®õ|Ð.uîì줳³sÚuhv=¼ggg';wîBáíСCìÞ½›Í›7Gej‡¾e¾çl´Åc‹°gÏ®ºê*:;;Éd2Í.Τ)—ˬY³†k¯½¶ÙE™W]ulÞ¼™¡¡!®¾úê–zÈhº/h.º/дºh>º/дíÚWL•…Ô·LÝi&b±ô°xûÝh&Ãbé k?º/Ð,Ú½¿Úµk×\s {öìaûöíttt4»H“f¾ûPmñØd†††¸á†èëëãÚk¯%“É´Í Û××ÇîÝ»ùÜç>×ì¢Ì˜L&Só£³m›Ý»wóÁ~°ÙEÓ,t_Ðè¾@ÓLt?Ð:4ê ®¼òÊfM£ië¾bª,´¾eªè¾HÓˆÅÔÀâî ôû‰f<S_°˜ûÐ}¦ýY(ý•XoöõõqÍ5×ÐÑÑYš·2ÍèCµÅcˆV¬¸®ËÎ;ëþàê­`QÍa'Ú?Wôõõ±fÍn¸á®¹æ®¹æ Vþ§R‡fÖÓA\yå•‘;ƒv©ƒ¦}™L_ÐÊ÷ßdû‚V®ƒ0}A³ë iOfkL0Ùcf›…4&€‰û‚v¨ƒfa2Ÿc†V¸‡ç»oi…:«ÌW_ÔjõÖŒÏ|ŽZåޘ; Ý~ó5WÑJuÖLŽùœSl…ûC æg®¢Õê=,„:·úµm÷yO‰µª²mÛ6¶mÛF__ß”ÊØês·“-ãdŽÑÂc¹þúëÙ¾};7Þxc]_Íâ+7˜³¯¯ÎÎÎ ÷Ï5;vìàƒü ×^{mô`ûöíÑçÉ”±™õزeKݼՇw«×AÓþŒ×´Ãý7Q_Ðu˜¾ Ùuд73Lö˜¹b!Œ `â¾ ê YØÌǘ¡•îáùê[Z©Î0}Q«Õ[39æcÌÐj÷Ælôíö›˜¯¹ŠVª³fjÌÇœb+ÝzL0·s­Vïù`!Ô¹]®m»Ï{îÙ³‡«¯¾zÜcZ½oiÆœ›D__CCC‘2®þWã;v°{÷nFFF¸é¦›èèè`ûöí“Ú?—ÈFýÔVl›UŽŽ¶mÛÆ®]»¢¼ûúúسgO £V®ƒ¦½™L_Ðê÷ßdú‚V¯ÃlõºÐL‡ÙLö˜¹`!Œ `r}A«×A³p™Ï1C«ÜÃóÙ·´Ja~û¢Vª·fbæsÌÐJ÷Ælõíô›˜Ï¹ŠV©³fòÌçœb«ÜzL0÷s­Tïùb!Ô¹Õ¯íB˜÷¼òÊ+ᦛnª©W__߬CæŠfÌÙ,óšiưk×®š›UeÛ¶m‘¿à‘‘®¾újFFFèèè`hhˆ;wF&öíŸo.¼ðBn¾ùæšv2elf=†††¸þúë`óæÍ píµ×²sç橃¦}™L_ÐŽ÷_²/h‡:ÌF_Ðì:hÚ“ÙLö˜ù¢Ç0q_ÐuÐ,LæsÌÐÊ÷ð\õ-­Vçùê‹Z­Þšñ™Ï1C«ßÓé Úí71_s­TgÍä˜Ï9ÅV¾?ô˜`vç*Z­ÞóA»Õ¹ß±ʼçîÝ»¹á†èèè`Íš5 µýœá\ßOZxlÄ_ð–-[êúlŸh+0™26³’wgggCçV¯ƒfa³î¿v¨ÃlôÍ®ƒfaÓ¿£…P‡‰ú‚v¨ƒfñ2[÷g»ÝóQ§V«ó|õE­VoÍì°³QïvûMÌ×\E+ÕY3»,´ßÄlÔy¶Ú¥ušë¹ŠV«÷|°ê¼®m«×ahh(rs¼Ðç gãZháQ£Ñh4F£Ñh4F£Ñh4F£ÑÌãQ£Ñh4F£Ñh4F£Ñh4F£ÑÌ-O>ŸŸôñú·¯™/ôo¿1SÀÔîÿÙ즚÷|ÓÊeÓŒe!÷ s1W Ç³×6šæ²Pû³õ»¯7.˜­1ÁTÑcÍ|²Pû†¹Bÿög·lZxlSÇYG>ŸÇ÷}†‡‡Å4MŠÅb³‹¥Ñ´ õ·?|ßÇqzzzêî×ýŠf¡óÿ³÷îñq\õÝÿÛw;Žecb;ޱ3Šq;Ád”¦³Í t·JHÃÝ1­Ã%-ÖÒP N4ˆAr±'Ž&6б­Ø‘/±õûcæÌήV7ë²+éûÖK¯Ý™9sæÌìÎwÏœÏù~¿bÆÛ¶Å^U‹Üû}>Ø¡š™Ìv¡Ò}z¹÷…jf²Þû#½ïêTÚ¦Âx0Ymƒ01˜Y錞çaYžç¡i‰DMÓÂíJÝ×uÓ4±m›D"øGå*Ç1 #Ü/N“J¥Âº à ‡õišF*•:ãò‘N§Éd2EmWmVëòù<¦i©Îè,‡D"®ëCÞ>ؾÇP¯‰úÛÚÚÂÏO]ƒÁ®‹ëºØ¶M<; ¦iö{m<Ï#›Í†Ÿùp÷êµÖ4­è;=Ïþ¾¯ƒ}'¶mãºnŸïE¹¶÷·¯úÕõéy7rïüÞ‰]ì<†zM†rÿ t]lÛ¯Iß‘ìJ´ìd³ ¥Ÿa´ýCÙw2چ삺ålC%íBôó*½&kŸ`¤va8÷oé½]ßÐÐ@<0$ÊP¯uµ÷ &ú½/}¹÷Õg9}U¾Ô6Œ–]ˆ^ÏRÛ }‚ÑEúƒ3Òçj+>Üû¥È½?8•è 續dŒ0úY–댤O iÚ¨ŽD¯g5ô Ú_Æåy¡úƒý®VŸ@}g¦Ê½?}‚ ïñèyuuuáÍŸÏç‹\?ÓétxAÔ,uÃe³ÙpÖ‹çyÔ××ýȨížç…ͨ[l6›- ³1Üò‘ÍfI&“áa¸!=JI&“áup]—úúú¢mlßÁÎc¨×D­3 Çq°mMÓŠ¾ôý]×u±,‹ºººðX±X¬ì5SÛ”!Sç5Ôý£¾¾>ÜÏ¶í¢™Uƒ}_»–Q¢¨X,V´½¡¡¡Ïw¹¿}Q9ïñFîý¡1’{{¼îý¡Ü]—D"AKKK‘­P Å®¨ïÁd³ 0°ml_˜|¶a » ®I¶¡’vA•-Û0ú#µ C½ËÝûÑë0Ü”R&bŸ&Þ½/}‚¡1îýÑè¨ïB9Û0vú· Ò']¤O08#}¨–±é{_îý¡P©>Áp®ËHÆýõ FÒ'Íq¨¾>ÁPöŸlväyA1ÆG£O >ë©tïIŸ w‚ÓÒÒÒ=®®®^Ó4{;::z;::zÞŽŽŽp»®ëáv ·­­-Ü–Ëåz5M —Þ\..†Ñ›H$ÂåT*Õkšæ— 7•Jµ-º¯iš½---Cª«­­­Ïu0M3¬ íƒí;”óê5innîzMÓìÕu½W×õ^MÓŠ>£þ®‹úd2™¢m@oWWW¸½«««O¢ß£þöÊy¶´´„ß¡èõŠÇãáwt ïëPŽ%zíJëH¥R½ñx|Ð}:ï¡´©’Ƚ?8#¹·ÇóÞÊý7Øu)÷èíØ®Lv» >³þlÃ@ûNFÛðßÿýßýÚ…ÞÞÞAmC%킪¯¿{`2ö FjÚÿ{ßûÞ€÷¾*kÆV±O0Øu«æ{_úƒ3Uîýþ¾½½ƒ?k Ö/ » êéÏ6HŸ`t‘>ÁÀŒôy šÆ ¤OP@î}¹÷£’}‚á\—‘ŒöIŸ`´Æ Ô~ÕÖ'hÿÉhäy¡ÀdC<Ó>Á`úÁd¿÷Ç¢O0á=ÕŒ³d2ÎPiiiA×uòù<¦iÍJ‹Ç〯Ú꺎çy¡»´ZŽ&úŒî«iÚ n­Ã-?QwՑ̬+w¢3~Ú>ؾÃùŒ»&ÑGtttH$ú¨ú]—¨+ºrŽ~žj¶„ú”2ØþƒáºnŸëuIèû:Tj6‚mÛà S=¸Üûƒ3’{{<ï}Å`÷ß™\—¡Ø•Éj@lCôz>üðÃýÚšm¨¤]€Ñ± ¥O ©](·ÿ³Ï> ôï»®K6›%—ËÑ5ŽÖ3ûý]·j¾÷¥O08SíÞ/ÇPŸ5ÊنѲ ª®þlƒô Fé ÌHŸªm¬@úå‘{_îýR*Ý'êu1ÂþIŸ@1Òq>Áx"Ï ƒ3™ÆϤO0Tý@îýâötïO á±¥¥ðÝC§M›F2™ð¹®Æ¥þO”¸Ô“uí£FIÅuWîÅÃ¥ÔH†A*• ¿#ÃÝ0¢1ÏË1Ð÷u$¤Ói¦M›F6› ÒHéþãÜû“ŸÑødW}ôQ`òÚÛ½žƒu¦Ä6L Fó;Üß½oYš¦‘ÏçÃ0O®ë†¡Ý‡Êdé”^·jDú“Ÿ±îDŸ5ÊنѲ 0°m>Áè"}‚ÉÃXLÖ>Ƚ/÷þÄe,îûáÖ=œ±‚3¹7¤O0~ÈóÂäg$ßÑèrï÷Ï„UÎ\.GWWmmmäóù°ƒØŸñ0 #TŒÕss3©TªO<ÿÉ@éu°m»(õ@ÛÛw´èË:Ô!ÚVs8J.— Õùþâ7´ÿ`èºÞg–C´Ž¾¯gŠÚ¿££ƒ––r¹Ü°¿Ã#=ïJ ÷þÐɽ=^÷~¹ãÖ÷p Û±`Á`rÚÛPz=wïÞ=`û§’m˜}‚rm9“ïà@û÷wï4A¼b¢ö »nÕˆô †ÆTº÷Ë1Ôgr¶a´ì l¤O0ºHŸ`pFú<0YÆ &cŸäÞ—{¿&BŸ`4îû‘Ö=ÐXÁhÜÒ'?äyahL•1Ä‘èrïýÜ'¼ð¨¾ªÕu=ü‘ˆÇãa’`uAÔ‡dšfÑ2’N†úÅN$}®Ct¶×@ÛÛw41 ]׋’™¦Óit]òPš¬WÓ´> *at6›í3Kq(ûD</J¾ªfÅ(ú¾…èç=†¦iáL‰þf•Û·Üy«k^í³wäÞœ‘ÜÛãyï+Fzÿ•c »²zõêpÝd³ jy0Û0](=÷‰n Ãè×.ÀÄ· “­O éýWnÿË/¿<\WîÞ7M“L&þ+;’Éd†Þd¢ö J¯ÛD¸÷¥O08SíÞ/Çpž5JmÃhÙØ6HŸ`t‘>ÁÀŒôy`2ŒLæ>Z–{_îýR&JŸ`4îûѨ»¿±‚Ñè«TkŸ` ýKÏ}¢ÛçÅTC‰~0™ïýÑîÌÖU©B‰ù|žººº°añx{d÷þ`÷ö`vc,éý×ýÙ•ÒÐd² ê|³ ýí«Ú=™lÃ'?ùI/^\Ö.Ú6LÖ>ŒüþÊþýÝû#e"ö T»'Ú½/}¹÷‡Êpž5*a¤O0ºHŸ`ììÂP¶6ã1V0™úê|äÞ—{¿”‰Ô'é}?ZuGmƒò‚¾Jµö d Qž&ûâ™èSáÞí>Á´ÞÞÞÞÑù¸+‹RdÕ,&uÇ /¦®ëX–…ëº477•Qp"Ä¥.=·¡Î´s]·hæÞp¶¶ïXœÛpŽeÛ6±XŒÞÞÞð»0œÏs¤û÷w-£ßÇÒãýnïÇqð<¯ìç^Ún•ðX•hßrûOäÞœ‘ÜÛãqïöý7ÐuÎyL»­·œmlßrûOJ¯çPìLLÛ0ûÕö»>&bŸ \é Îd¿÷‡sÝÆò<†Â@¶Aú£‹ô f¤Ï“}¬`4‘çñEîý©ö>Aé¹Å±ªÅ¦T[ŸàLöŸ(ÈóÂàLæ1ÄJí;ص®–{´û“Fx,‡R ÛÚÚBõ8‹‘J¥ÆTqŒ¨±ê¡~qG³®JžÇH‰Þü£¹ÿxœc5]ÇÉ‚Üûë«’ç#¿ÇŠÚ5Ö×_ìÂè3ìÂXÔW©ó«ßõj:ÇJcª1î}éT± ©`Æ¢¾JÇH+»"Ϲ÷Ϭ¾JGµRÉq‚ñ:ÆTc*؆ÉdFò»>Vûʽ_ž ju ¢n¾Ê=Z¹ŒW’þâgG꬀Ѭ«’çQ­ŒÇ9N…ë8ÞȽ?¼º*y•±¾rGŸ©`Æ¢¾j?îx"}‚‰ÉT¸÷¥OPYÄ6L<¦‚]‹úªý¸ã<L<äÞ?³úªý¸Õ„ô &&SÁ6ˆ][äÞ/ϤöxAAAAAAa|˜^é‚ ‚ ‚ ‚ ‚ ‚ ‚0ñáQAAAAAA„#£ ‚ ‚ ‚ ‚ ‚ ‚ #F„GAAAAAAAFŒ‚ ‚ ‚ ‚ ‚ ‚ ‚ ŒAAAAAAA1"< ‚ ‚ ‚ ‚ ‚ ‚ ‚0bfVºãÁ#å„Ç;wÒÝÝ-÷Ä@ìßÐ烉û|p&LE[0Æ"΄á~ÖSuÌð¾ûîãöÛo¯t3FÄd¸¯'Ã}:ú?úÑØ¶m›ƒ1{öl.¹ä’ = ÒÚÚ:áÏàСCþ.\8áÏaëÖ­•nBE8ûì³'üg7¾bϪ‡C‡Uº ãÎdèÀäøþM{6ΡµµµÒM¨sçÎðŸÝ™0lÇp™ ÷é™0ÜÏzª>,_¾|Ê}?䞘:œÉg-ÏS‡©h &ËXÄpîg=Uû3f̘ðßÉp_O–ût¢÷;žzê)žyæ™Õ1%„ÇÉ@ccc¥›0b6lØ0¡o8ŶmÛ*Ýa 3¾bÏadL–ïßd°g“á„©Ãd±Ãe*Þ§Sõ³††ÜS‡©øY Cg*~?&ÃXÄ™0?ë3aíÚµ•nˆ™ Ÿõd¸O'C¿ã’K.ñd¤é•> AAAAAAA&>"< ‚ ‚ ‚ ‚ ‚ ‚ ‚0bDxAAAAAAaĈð(‚ ‚ ‚ ‚ ‚ ‚ ˆáQAAAAAA„3îÂãõ×_OkkkÙmMMM\qŬY³†-[¶ÐÙÙyFeA¨~ú³baê }A`d¶@ì€ Läù@y>¤O ô[éCf\…Ç­[·ÒÞÞ^v[SSÛ·o§±±‘mÛ¶ÑÙÙÉ–-[†]F„ê§?[ v@¦Ò'Ff ÄÂäAžAçA@ú“ü0ÊÚÁÿP±*}rÂáqûöí¬Y³†¦¦¦~ËìØ±ƒ7²qãF6lØÀm·ÝF{{;;vìVAª—ÁlØA˜üHŸ@[ v@&>ò| ‚<‚Ò'˜,Ø€3ŒòÃ) ¾Ç£7ŒòÃ);Ö8gp¾Ã!;ÌòÉ1>ßq7lØÀ¶mÛØ¶m[Ùíííítvv²aÆpÝŠ+X»v-;wîrAª›lØA˜HŸ@¹-; “y>AžAéT3ÃñHn(T—b1n°ýKËÆpŸá–ÿò«¯¹l©(;˜ˆúG 0r[ Ö‹„‰<‚ Ï‚ ÀÔî88hhèè•nJß¶9Ÿ9uŠ__yåÊ»‹_žç¦¡õSÞâ‘å<`f¿×jx^ŒY môÛ7hOªd]ŸÊWäážXµjHmÉ—œ—,—;W¸÷ÒKù`äøÙà½ZvK¶©ë™ö¿nÖ,zJŽ—ˆ¼÷‚ëimËF¶¿2sä²á¸æx¬/½ôMMM†m„©ÀöíÛÙ´i{÷î­tS*ÂÞ½{Ù´iÛ·o¯tS¡¢lÚ´‰¦¦&^zé¥J7eÜQ}‚M›6Uº)‚PQÚÛÛÙ´i÷Þ{o¥›R<ÚBA˜Ê¨ßăVº)áÞ{ïeÓ¦MU? )c<Èó ȘaåÆ Ó¤±ª4{áÏv§gÈåK…ÁïìÞÍ-O?]¶¬G_¯¿RoF×uûlsJê Ÿýí2ëÒ´½Ô#Ñc`È<ðË×^+´•b/B+Òå©YÚ¾¨c6(gá‡A=6o÷8î_ZþݧO“û‘ë™ öw"ÇJǯÚ©EÚcEÚ˜ÌçùŸ¯½Æïx#a\<+ÍâÅ‹yßûÞ×gƃ L5Tœó©Ú¡^¹re¿á[a*±mÛ6Z[[imm­tSÆé‚ÏÚµkÙ¶mÛ”Þ–,Y"}A¦ìóÁu×]^A˜ÊÈó<‚Œʘa9>y’“'O­ÈkÐz»º`Ñ"]´¨_ï9%¢µEÊÛø^|Ê ð3»wóŸºï×W. ëß;Æ—çÎ —“@KÐ>U¿'•¨—‹ìŸ¦àiS,dæé+DZø‘ðà’%°dI¸]yÆKê‹Ö£Ú D?-Rw–‚¸hK|'×­#O±ˆªêÜ3}: AÙ…p«J,~ø0ÎÂ…á¹4ÇÌ”´M]÷$àÄý3øèÖ­0DO×rT•Çc¹Y†k×®vA&.bA±‚ ø vŸ‹„Éô A±‚ ˆèiÓ¦aÛCËÄè1¼œ–/½8Øè@¾™¾Ø¨øyO¯=uühÙYGŽðÛÀ£2êýèyþ;[×Éã bQñM iÛ_~9ÜÇ)ÙvWãP‰~ùH9µœ –c‘ívI}ÑóÎÿ1 ¶««¨œ¼zžÇó‡…‚¡º^qŠ=£ûf)ˆ¥ |ñôà_þ%.ZDC°O<ؾüØ1’@m.‡†/¤šÀ‡ã÷ìá{GŽpú_þ…<¾‡£9~*ø×)ˆ£-Áv¸ú®»øÂ3ÏpN¾øL© áQÍ**MôÚÚÚÆvJA&.bA±‚ ø vŸ‹„Éô A±‚ ˆM”È6<ÏãøYg ¥bÜ÷wüÞÇ>nSضëºì¹ðBö.^®WáG­àÑ£úâ&Å‚_6›ÅºW¯æ+†å/Þ·øâ©S8øÂh©°¨êß]Sù|(Lªín¤ø^€ÊûÐ ÞùÕWùΩSa¹¨w`?¬éû3yû÷Ó€/î)/ÆïìÞÍ碶« ÓuIm@öСðütà-?ý)^ðyd)‚Óþñ}áÕñÏ,tà{)ºÀ¼§ž"úÜçøÒ÷¿æyüìÿ1&ðÜÿ1g?ü0x^˜C3ì¯SðÈ4ñEÎf ¹&/ïêâÔ×¾Æ{öð /Œè»VÂ#øîÜÛ·o§;P¢·nÝJMM ×^{í°Ê‚0q; ˆ-Ág°û\ì€ L~¤O ˆ-AìÀh [ÚŸc6› EAEiÇË—³çŠ+Â:—ÞûçÍã¾—^âØ¼yE¡Z•(ø§O“^uUÑ6#R÷ׂ¼Ã.YŠksvîÄ›1#l÷·…Ádài˜Ž®Ë=Ç£ øE=A»›ñÅÁžž²ÀMgE÷ŒÔìÞÔû¬8yø³Ã‡yõg?cú¯‹/ìåðÅÇO_vÛW­â¢'Ÿ¤î»ß C¹¶47séÁƒ\ôä“ÜøôÓÌø×¥¶« è°,®KGK Ù¬0uÉ“O†‚¡ú?õ‰O@6 žÇ®_ü¿ö®‹mÛ¤lÇq|Ø@¸Lÿ:¾g£B§8ì¬ ¼í?Àq¾ýíosï½÷Žè;V59¹á†¸þúë©©©¡³³“ÆÆFjjj†UF„‰‹ØA@l >ƒÝçbaò#}A@l bF‹h®A=ò>ŠëºèºŽçytõöð­‡â£o{[(<*ƽkÖ°ïäI²øùõ}û`éRîyúiºW¯`ßŇu+/Ãù¯½†ùä“áúi¼ñTŽÂ½³gƒeA"A"8î·¿úU¸új  ˜>:muø¢å/¯¿ž–Ÿü„¯lÚ„¶d ¸.;çÌáU|aQ…?Íâ‹q*7¢Ê)ùòý÷ã½ÿý\ôýïS[[ËÃ/¾H~õjL`öÑ£¼tß}¼þÚkÙþÿ€çy}òIÌë®#ìo?èíeËßýí?ÿ9mž‡öÙÏúçnÛÌX¿žÙ=Æ>Ïã©þEû ‹á]pA(6ªk páÿý¿èßüfx¾ÞÝÍ»~ýkÜ@ìU!v£ûX–žÇ²žÌyóÂý‹ƒæ°, ×u9îyxžÇ¯~õ+Î?ÿü}ׯ]x|æ™gÊ®¯©©á®»î Y¯[·®QJA&ålØA˜ZHŸ@8s[ v@&ò| ‚<‚Ò'žçAo/>ø`(žyøžw Û¶1M3ÜVJB¯<ðE¨x<Žëº¡x¸?¯”· xÖ=ÿùσiòS§H͘“Ns(ð”üå•Wrñ—¿ÌÓ7Þè·8ëøqêbþ®]x'dÍîÝt¯^M[pü,ðÓÿý¿yëÑ£ìÎf9ÿÒK‰¿õ­àºdï¾€ù÷ÞËÑë®ÛæIÓô½÷\—º@s¾Ç\”JA+2…/Lªö'(xû5«ëÏóâóÏpôÖ[yÇš5<„™}çw¾ÃÞà7°¡¦×u}qÐqøðÑ£0>à {Kï¾›öŸÿ<,ãb^>Ÿç¢˜%?úö‘#xžÇ©/~‘ÜÞ½4k®ë†¢ëºhšÆS?ü! 躎aa[u]ÇqÒé4–e¡ëz¸¿Ê‘ùù'Ÿ„+¯ð;¤ö÷  ¶@±¥8ަɳÏ> ïxà ‰‰H™X,Foà¹X*<Ú{<º®Ëö7½ ÓóØ·tiPȆE‹ð(Îã&›1ƒÿêl›EÀ/ÿ÷Yø«_ñôM7Á7ò¦S§Ø;cKwîä’_ÿšWœì®]ôüö·$V¯.KO:Å[o½•]—•_ûú[ßJ>ºê¹çØó©OÁu×A>¦ÉñÛoÇÚ·Ï?ÿ¼ŸÍQyý}ò$ñY³€‚Ç_*r,u\Û¶ér]j?ñ :úSìÎNÐu4Ãà¯?ô!4MÃó<6,]Šã8¾ð躜ŸH`¹.ù|žýíß²ò;ß EGMÓB‘àü¯|%ôJÔ4 ï˜Ôkš&¶m‡Ç‰ÇãX–…eYázµ¯Ú®Öår¹P¸ŒÖ³:;<Ð÷'›ÍÒÜÜÌÿûô§ù©ã ë:®ë²¼$Ìîp©š‚ ‚ ‚ ‚ ‚ ‚ Âàì„ÑTØ‘÷JðR¯JdtJ^y×¥sÍî8z”§¿õ-æíßÀîšòDºK—âz=Ë–A>Ïêîn¼à]›7×ýÓ?ù…]—ÇfÌ`þ}tßu§ï¿Ÿ»v…áDO>óL‘Pj§·oÛüз¾Ut+~oCl›é{ö°ïoþ†l6‹¦i¡ð¨¼þ®zñŰÝ&…|‡Q<Ïó…J×eî~4ÛeáË/ãåó†¦ùµ¨°¤@(ò%“I¾ù·ËOÿë¿Âíñxœd2I6›%•J…Â!€a†A<§¹¹™\.‡¦i$ 4M ½Óé4‰D‚x<Žã8ázMÓÈd2´µµ‘H$ÂõJTËåÈçóL›6X,F&“!nšü] 4~ìÿ9sæðÄOŒè»)£ Â8#Fšt¥›!‚ ‚ ‚ ‚ Â$@ "ÞiQ¯FÏó ð ‹n+}u‚²twsjýz]Ë¢ç¼óøå‚$Ë~˜‹_}•ß¼ò $Ìêì„|žs~ýëÐÃ×¥f÷nvaQ D¸ö?üC^úâq]7Ìchš&XP__O]]'Ë ¼ïü*Ü0¼èοø ¿Þ|S×9ýÙÏb  寧Ÿ.ZŽz;Ú¶M}}=ÉdÒeªi¸å–Pdü³?ø°,ZZZÈåraÈZµEÅRaQ×ur¹¹\޶¶6R©T¸¯ ›jš&©T Ó4ÑuÓ4Ãÿ5çž‹®ëÄãq2™Lxlõzâĉ¢óRB£®ëüÅ_üÝx;Þ{çlù½ßC×uR‰8W>Ì®ºŠO<÷3w.»wè»)£ ‚ ‚ ‚ ‚ ‚ ÂäøYg…ïm|A1 BÂ\j óÈÒé4Ïyw]z©ïQà8<¹d ëy„'®»Žƒ»v±ë¦› ‘àä¿ÿ;†ëòÆ_þ’|>Šb3¿÷=ÀÙ4Ûæðž=hšz.á`E„ÆžüÏóÐu]×I&“xžG"‘ET²Y_lËçI¥R´µµÇ‚8WŽRoG%„677‡Â©išhš†iš¡¡iš†Іê߿ĉ"QR ‰à{ F=&•à¨ë:©T*,§Ž«Ž³ï/þ‚÷½ï}är~6JÓóºžúÖ· ×Âz Ã`íÚµ<òÈ#}¯up½ÿþõ¯çOžx‚¹==L‚ãpÖ¼ëå—™öã£óÏ?DßIAAAAAAªŒt:]$ e³Ùð}i¨Õ¨c6›õ=ðO;µW4§òÏ{ôÑG±,ËÏë¨Ä¬À{oiëñÔ}÷aš&]mmœ<ûl°,H§1 ƒæL†|>O&“Û¦+“ñe,|ùeæ=ô‰D"ôú ŶÈ9©p¡/ö³EÛ2™ ŽãÉdB¡/úªD?%¡9þüA¯¯atuu ‰Q‘1*bFǨ¨Î'ºßû–/½=j»a¬9÷Ü"ÏI,‹DÐ.<|=",bY|ü}ïcÅ‹/bÙiÓŠ„GêëÉ™&Ùl–|>Ï•W^Éþ T.Ù,44ð/™.Óä»[·²çœsØxø0äóÜsûí7u>ªýW=óL±0©òV---¼aæÌbñÒqøè%—pzófŽíßÏêînž¼ùæp÷§Ï:‹·ÎžM<çŸþ¿ÿù»vqúþûýÏÉuy¬»›î¦&>¸z5GfÍâú—^âÄüù¼gß>v¾ú*×ýô§`¼ïíoçð9ç ëÚ•"£ Â8à⎼AAAAA&-iÀŠ,Gó‚/Dª<†üP©P,÷;À¯^~€»—.Å2€”süУGް~ÇÐ4>²oØv(®Ü½›³ž~]…ùô_T>úÞó<Š®u,+ª/™L-$X{ž×çsAAAA*Gé¸a¹é饓èÕøQOOKï¾;\ÿ³}ûXºoðWF˜‹±TNS>ˆ^Év-©ÇinnæâW_- ½›6 #Û*'Z• —¥eLÓ,òXT¡Kj¿–––"A’’ö æ™H$øäŒ,]º´Ï¶l6˾ŸýŒËNžì#4FÍ"gÃð?×ËâðO~‚7¾Ñ¿¾ù¼/>Ú6¿ýæ7yúöÛ™·?ñTÊߌ»þìî»™¾g«¶oà‘S§X~à¯üÛ¿±îãçÄ·¿ÍâO~’«Î>›Ë?ûYš[Z8øþ÷cz^!7f<¹œ/ f2|þK_âò®.0MÈdüWà7ox[ëêXÿÎwúû€¿=rnCõ0=DxA¨¥Âc©ð7ØöR)*8 E`ŠŠo®ë•w§¨C“Ïç‹–Çéã¥7Q„H˲úˆ{Ñk[ºœÍf‹®eYE×:›Í†Ëžç‘L&‹ê/½.ét:¬Ï²,\×-º¶ áþÙl¶è³T¢ftÿèùd³ÙEÕt:M2™”0¾‚ ‚ ‚ ‚ UÂ@é™JÇplÛ†DÂK2 ÐuæÎËk pÇÑ£X¾œO?Í“³gûÞmX¶ê¹çBÇs|¡Ñu]|ðA  D*!NÓ´"ÏŨH¥Â–óTëÚ®ê€â¼j»ÚV.âZTÈÜû×Ýïµûãw¿›šS§èhk+Zï8ÙlÛ²ÐyÇŽ… ‹¡cyŽãðÂÅŸ/ÓétXF‰Ñú²Ùl¸ÝuÝP˜t‡†††>’Éd2•ÐhY d³Yt]Ë[–…çy¤Ói-Z„eY†¶QµÓ¶í°“¤iétš†††ð8Ñë§ê›6mù|MÓˆÅbÔ××ó§ú§Ü{ï½£ö¹ ‚ ‚ ‚ ‚ ŤÓé>ÅûKÙ¤P#_Žã@&C÷êÕ…t=JtjkÏcÞþýt¯^ͦùóYôÿÈò§Ÿös>*¯8ÇaÍO„uÿjûöPdt]—šS§0ðs=BApŒRš£|ÏÀLăN]?POÓ4©¯«ë³>‡Ç(“TÛ|ñ‹þ¸Zd,,›ÍbÛ6_øÀxˬY…©@Ý¢Eüãü¯ÿÝïp™?^‡\/×u±m› ººü}c1p]ޝ[Ç¡C‡À¶ùÑUW‘iiáèŸÿ¹_&‘ éy~­D‚Ÿû_¸óN¾ÿá“Ídx샤gÙ2ZÞýnÿüt?ùßÿ›Ç>øAÒ©þùÏ« 싎†©ÝpÇýY4Í£ŸY©ÐØOøXñxA¨0.î'î/ÔjtÖ’úA‹nRÞ4*†¹®‹ëºa}jßþ¼Òp ¥Ëå„ÉÒåhÛK…ÈR/¾Á(ç½YZ_”†††¢mÑp£Êë°ÜõVaJ ÃÛ§Ž¥< -ËÂq,Ë¢¾¾]×ñ€–––p–Y[[º®÷ñ”Íçó477ÓÕÕE*•Âó¼°÷Îw¾sÈŸ“ ‚ ‚ ‚ ‚0rJÇ {ì±`½Ï¾}ûH§Óþx]*Å“K–„ãCh¶Œêë™·?s{zxw[K^xÁ]êêÀó¨ùÎwÂcåóù¢°«WΘYÒ¾Ò§QáQCGo½µÏ¸_´îrQ×âñ8Žã°hÑ"Þ·|9Wœs“õ-Ë"N‹ÅØ¿?ûçÍã¹Ó§A ¿ŽC&‘àÛ·óÊãó“sÎá’ž_8´,ÿšŽ/<ø /^vY!¼ªãð9s¸þ?þ€7½ü2–eñ‹óϧsÖ,êëêÂбär ëüÞÇ>Æ®K/ Ú¾ù®»HF ‰©TŠL&S,ö¶´€aÉdÂ1Á) I„£Œ±gŽYÍ‚ “ ‡Zú-SN˜ôðʯÄ,õC^*B‚ÿãjšfèýèºn(„)Ï:Ó4CÑP• å~@ÔvÇq0 £¬Çc4w¡*¯Ú]~‡%z˲ŠfGyžW4Ã)N%–V³¾âñxèÕ‹ÅhkkCÓ´P´ËçóÄãñÐûP] %Fq]—X,ƦW^*ߢišÄb±0áµÕ ­d2I}}=𦅠mÛ¤R)‰Dèy¨bÀkšÆ´iÓH¥RØAÂíh'":{K…ž0M3¬3z=s¹\Ÿøòñx<,ÓÒRøN*JÕ¹°,‹D"~ωDXWkk+­­­gzK‚ ‚ ‚ ‚ C`° ú‡ƒð§J^êéé)Ú§gîÜÂøaøBS0~¸èÑGXøÜsèºÎÁùó˜ý䓜p] Ã(+³m姨ŽQšI±4çbt\/:9l<¯($¨ÏÓÝÝͧ”G_: ™ Ùl6+Ýêê ¹9œüê£%ŸÍò‰ûï‡xœ>ðZss(Žn:tˆ•§NmóÑK.áßÎ=—kÏ:‹“+V0óòËùÛÇçþ§ŸV†Ç®¼’õù<µx15<‚ܰkÝW_Í¢Ï~ã»ßÅÍçyúÛßfã…rXÓp]í¿À "E¯]"‘ ¾¾žx<^6_åPÈåreCÖQ&”ê@ŒfäºþáQa”(&¡?/I%*”XdšføƒZ*üE÷…‚@*•XÊ *F)C噍ޣ2ÇqÐuÇq°m»Èë϶mâñx(Ú•†„…‚Ø¥Èf³á¹©ã+Oyr*6 UÍ`RBc"‘Ûî8š¦…"g4\iôZ¨óRð;L¥‚œçy¡÷ ªC•WqéS©š¦õRS%?î¦i¢iZ¸©\†"—Ëõ™9%z-Ë/J´#¢OKKK˜×P[Kå),õˆÿ‡2ŸÏ‡^†aN§C/=˲Âëh¸RÕ.%@š¦–M$¡X¨–•(ªpƒÙ] Ã0H$a‡@yªN@é,¤R¡o°ÎB*•ê33l †ÔêsQ^›#éÜ‚ ‚ ‚ ‚ cË¡C‡ú¬s]—ž#GÂe]×yñ²ËPk–¼ð{ðDZlàÐŒ‹±4G\»?{(N9}Íf³}ư†Jj¨v®[KÁ[jšŒ%Î|üq^8pn¹… ayâ ®^¼˜×/^Ìâ+¯äºë®àÈýgãGN‹Ç㘦Éñ{îaÎ÷¾Ç¡iÓ˜ÿè£ÔÖÖR{ß}sçÎåÒƒiš1ƒ/YÂÑ×^ãÒùó}¯QÛfÖ¬Yܳ|9 Æææ|êSìÚ¿Ÿë>úQ¸ë.š{ŒógÍbÆÊ•¼rêÍAÆÅõW~{-‹T*5 7ã™\ßÑ¢œèN§Ëæñm$Ç£ ÂpqÉ“ïãíØ@iŠGïÙ³ ì=ôË…5--§ò1ª0£¶m‡¡7£õ8ŽC:Æqšƒ®ë’ÉdBO¾d2ICC‰D"üñQa> à ŸÏ“J¥BïE%ö)>Û¶Cá0zlšÔu]²ÙlR5‹aF˜ç0™L’ËåÈd2a]Vð®ò%ªÜ‡žç‘ËåBoAÏóH¥ReÃ(NEé,$MӊĹÒåáRÉ… wÑÐÐ^AAAA¡úq‚ñ´C‹°ÿ¼óü A4®7ýѱº»€5³f… ï*Ôª—º0ߥtÌÑŠx=‡!›¹®/6F‰,×ÔÔðîË/s+¼pÇtµµÑù¥/±¹­ž} €G}”ÎY³x×ý÷óþ;ïDÓ4f¾á ?ë,î[¹’G^z‰Ó«Vù^•õõNS[[ˇsáŸýËzz˜ÓMÌ{è!H$ $"Ù»jjØìIÛfõ'? ºN<çÁ%KX|õÕìxöÙ>c~*¥Q5OúWãÅuuu¡cIéXéX £ ÂP.ìª ›PêÑX2ÕuÝðKy^zË-E¡W•¸‹Åúäð+µíLD…C•Ó|±ÌuÝ0¡±Ú¦¼ñ”@ šÏçÉårá,£d2 ø¡DÕ¹D=UžÄL&z*áPÕ=U8T5ûJ_×uZZZ¶«ý£m‹Æ*W!d§ê³ïèè «««ª;>‚ ‚ ‚ ‚ t¯öÅÄ_O÷å%<ªš³fÍÂ0 .yï{Y_S®ËÅsæ*p®8çœ` \—es熛KÓ9•F_Õá8¼ôÈ#EËüñϺC‡°òyݺ ƒ jky[OpÎ9¬zî9®Z±‚c7ÞÈ[|³¯ºŠ{öpÞÚµàº,þà¹éíoçŠÿ˜š•+™ó©OùÇ1MÈfyÝãã»kj˜¾g¿Þ0üëj<ÿüó9r×uùàÿý¿d2™Ð¡#š71‘Hð¾þp|¾ £„Óé4±X,Œˆã3V*£ Â)NÕÅí·|鶃úë#Âbt9ú£¯„Äl6‹¦i¼ò¡ÍJRbžäTxÕ¨‡[©P©iZX¯ ¡ZŠÚnšf‘Ç‹rª¼‡QáRÓ4š››Ã®d2é'¬Îd0 Ó4iii ó-Fëknn.Znii¡££ƒL&ƒ¦i´µµý –†'mnnßGgì¨Õh‡3­V ÃsU ‚ ‚ ‚ ‚ •åù?9ÂórdÀ2]]]å7h«ž{Ž  ë:½µµè¶Í{æÌ ÇûˆIº®C>.GS•¦oRÛÄíìÇñÿËày¹L†çî¿¿hý3Ï<¦bú×~µû·`Û´57c{Ǿõ-–¿ýí ëÌêìd×®]ü ½|0nY³~=$“`YaÚ¨KŸ~šù7Üñ¸ÿÌZ³†¯¾þõþxg*勎‘°¨žç±ÿ~êêêÂuḢ®÷KH(ï×®®.ÚÚÚH¥RE騦ŒðØÝÝÍÍ7ßÌW\Áš5kØ´iííí}Ê555…e¶lÙBggg¥›.Â(Qív œcé:%6çNÜy'½|äÖ[¹ãŽ;À¶™³aÝ‹³ðôihn¦fåJßCXºt)﬩ñÇC•×¢mCàQ4¦F «¶–ÇßðÜP9X”8bd³Ù0¢[)†aŸN4”s‚:‰Æ^H­ᱩ©‰ÖÖV¾ð…/°mÛ6jjj¸á†ŠŒCSSÛ·o§±±‘mÛ¶ÑÙÙÉ–-[*ÝtAF‰j¶å¼Ë¡„Ç}ûö±»fwѶC‡aÛ6ù|žî«¯Æ ¼ã8á[Þqhii —=ÏC~à=t˲B¯Á¨w!P䡨B§Æb1Ðu¾³rå€?”z·|¨”z@–þX)ïËh8ÔñÄ”èªÂµ ‹j¶‚ ŒƒÙ±‚0ù‘>  ¶@„‰o^;ûì>ëb±Xú2ÊÒ¥Ký7™ è:+wï¦{õjlÓÄL ÏHWMñóo~³Ø?e’ŠX6Ô«Í™ v>_XQ*4Fr3þ¶`L.‹±êôiž9y²°½·—ëÖñG÷ßÏÿññ½ð…GÇqH$¾4`ü¿gž C ®ç;ñ‚ÙKÊ¿Ò0Œ‚¯¥®ó¦Ï|¦èر–ËÑuùåäjk!¨³?¿Íh˜ÕÑ Ò9mÛ&™Lö ·0L<lKÉù2ë­ %$ª×4åÅGµ½!²_2¨?ÝOýCÁ öŸhæD±ÕÀP'BÂD$j ÄÂÔDú‚ €ØAªË¸¸ƒFJ‹†<-˼y¸®Ë+3g†Âã©õëY~ü8«ž{.,ÖßÔúÁ¢}e2™>“óÕ8à@ãf>ú(ë–//^é8¸®K6›åÄÁƒô,[nêêêâ—¿ü%ß¼í6Òé4¿þîw1S)hh€l–#|ö‚ Øsá…üÁáÃx|~á¿`ÕªU\¸qcY±0CKK±Ðh¾GdD;Ê1T¯ÏÉÈx¤¥šYé“TÜrË-455ÑÝÝÍŠ+ؾ};k×®åÚk¯àðáÃEÆ`áÂ…eã9G9qâO=õ .díÚµ•>UA¨tvvräÈ‘‘W6Œ¥8rä­­­¬X±‚+VŒ¨­VŸþyûÏÃ[í‘'ÏéU§ýu˜Ì<Ò͉šG`î\4mž®ûb–®sDÓ0 òÀ©ÿù?yuÎ\|ñjÅUWñ|2‰ ¤€¬®“Ó›ø¾ eà ‰*ÌB”o¿ýíÌ:y’;ñ+#¨ÓÚ†qž. ã‹_g*ߥñ;Fã•iQå¯L•™Ùäâ‹tñຠ6¿'”k –µàZ$ƒëõéô‚òqŠ;‚JìS×?Ô©EöÑð?CõÙgƒ¶9Á±”˜™ Ú¯>“tð^y´:ø³ßJÏ79¾<ûÚk<7kO¯ÎùGãÑ'(·ÿDÄÂ"A'øó†%• S™îînvîÜɾ}û*Ý”~ȨÁƒ3í;vŒÖÖÖ)ù|`ccRÙ BBõÐÞÞÎáÇÃ\äÕÆX?ìÛ·ÖÖVÖ­[GMMM¥OW*Fkk+O=õ'Nœ¨tSÊ"Ï‚0öȘáè–râÄ NÏz­ì6•kqNm-÷,ZN÷âÅüßü†]Áö\|1ñxœ,þøO æJ¥0J„¸Ò4JåˆÕÕ±rûö ÛÏöm\×eùñãAÕŒ8®[·ðݦ-Ë¢µµ• 6ŒJçÿøñã´··Ë,'aÊÓÙÙIkk+G­tSÊ2–vàèÑ£´¶¶+±´UÆŸ¬Ül¦Sg…ƒS$Hö¯ÍôçxÔ®_išá^g­[Çü÷¿_\zòÃB8çsŸ#W[K3ež>$¾xdá V¥žŒ6ð9sø·ÎNâøB£”wèëÁ§Ä¯RÒA»ì’í6>³Â—€IDATå=ìT»K붺Gžª§'hOÔkPÕ+Yï1Ë£)_¬U^ƒõA}j+¨Ç_ €‹‚íéཀྵ'¼OöÓ~%:Ák6h¯/BzAÛÒA}¾©:•y|á°_èLe³@.XV딸=v¨£ `f€··¶òõkÙuþùÃødÆñèDñLT”½qp°±ñð†œV>LkkkU ci ”ð8Ÿ*’ÙÅ•ÐUÆÎ;imm­Záq¬Ÿ”ð¨+aªÒÚÚJ{{;ǯtSÊ"Ï‚0öȘáðÇ ‡Êéù»-3}ñb~8oX7¿ç=àyÔìÞM&ï`dÂc´Ì²À£RÓ4Ûä¤ï}ï{}Wzº®³ö¼óèÞ»—ýçnziǾ?{6gÝsën¿<|ìc8ÀƒGòû¯½ÆE×]W›ªid¥_ º><áq^{–5œ‘Ê©ÅÎ;G¥OPÜpà lܸ‘ÆÆFÀWVo¸áV¬XÁÆGTÿ‚ ¸úê«eæ’0åÙ°a6lÒLŸñf¬íÀ’%Kº‡Š]4ïà`D|÷¢Û^›>‡söœ« uôÌž @ï¹ç2ûÃ&/,Ù_ „¨¾Øì÷ØÕWcPì=gRðÔSïóøSWPO_ÐúHP¿NÁÛP ¶»¼õòøÂ›=sÁ²Ý”`¦P?͉Èþm0(›ñȹå#ëL ‚¡ò84ƒ¶E5/8F–‚W ª+Ky$6¯9|­4€…*¾÷¢ g ÎMy ÖQsU;Ô9©°¨-A{•à©ö׃m1|qRy>æŽàš+8Ô—Š\ïdPoKP¶.øŒ”Ç¢"E_OMuÍÝÈç–ÎEÕ^MÀ|Ç;hmm¥õ7¿¡Ú>AÿxxXX¤‚o€òr41COG µ* •+VÐØØHSSS¥›R–ÁlÁHg!×ÖÖ»O0Y¨ä5YB<.«õ»:UŸ®¼òÊ)k !Jcc£ÿ|P…â›<Âø c†Ã3C¡âNäP÷‹¢>ÿfÊÏ„›Ñë«ÝŒ5Ñy‡lp—YX¡°¨þ”àèá æ«°«yòeCE ÂD`0[0Qí@µ„I;¢"\\Ò¤‡´_©­*צh»ÊM¦PÇ,‡Ø»ÉÇTï‚à#¶@„ oæÍóÿ#¼ZÒ'>81üñå—‡ëVž:UTf´„Ç™¯¼ø¡Vñ¼‚§aÞïçŸüýßçù—à8躎mÛùüçÃí¶msñÏ~ÆÉ+øÒ‡?̪7½‰=^Ⱦ}ûxè[ßòD%úQ6}á árH @†©’L³xû(áöJÖuÝ‚ø*Œ:U!<ªxÌ7ß|s¸®µµ•ýèGE¡6nÜÈöíÛéîî`ëÖ­ÔÔÔ„IdA˜¸T³ˆíDzzzz8°àw…BóæAÐÚ·àY݉ùœ~öYÖ?Î* †b1kÃÒ¥¡ ÅTÈU%È)ÔOoªd]&².Aÿ‚UÔëQyä)ÑNy[f‚÷Í‘úÕ~.¾8¦ÄºÁ1Y§B…ªP¥PsAÝJ¼TœòT?÷mÁzÕ6E)¯•7¡W£] ‡á…£èOP.JPj]£uÌ3,«‰j¶ãÀWùUþFbÕÀ ’$Ãp‰6vQÞÙtðW*Z&C±ÍäÉW\xJ8feCJ×-bQhI’dÉ’'_´¾Üq-¬pâø¶K‰˜ 4„“-bݰȒ-²eY²eÏCMл7y˜ê}A|Ä‚0áí@á±&Źk'ˆèöÑ f÷nz{ƒ$EŽSøw]H§™õÓŸ2ã8ý«_±îøq6\|1ç>ñD訞‚Ž®óÔC1ë-oá¾—^¢÷‚ øøñã~®FM EÄwÜtË>úQÿhhS]÷ÿÇ;ððÌçó#¬IˆªÈñÍ1ó£ýˆ… ÒÙÙÉÆÙ¼ysX®±±‘n¸ë¯¿žšš:;;illµ$²‚ TŽj¶³–Î|áq6ÐõÚk[â'Ü^pø^Y¾¼eój4zÁÞÅœl?ÅRsG€c ʃ.N±0¦~rã hXÖÁ:!aÊ¡X¤Ò)xþ•¢Âºªv&(/ÐÅ#å)SWé9õ×½PõžÉ¼£h(Öf†/< •¥šmÁX¢<”·b’$zp‡$IââÒB Y²hÁ qâäɇïZ8yB›>¯‚à3[0Ñ쀚$ ÞežÃN)ã(::ŽCCC¦iúžžaeÄp¬8#á±³³“öövjjjF-ùòƹöÚkCwè+Vôqƒ®©©á®»î [®[·®º ‡ âšíÀɳOpx›3f6¾x6³ççDÏ!¨-d]œõÊ+œ³t)°8M±W.ãHÈ ±œúIm.Y?ÐÏýPÃè1T÷>O!7ejD5 ãM5Û‚±B‰‰..Y²ØØ$H ¡¡£‡ü:zè9ec‡ï:z(6¨þÐÑû¡ZÌL; = +Ά#;\zeÖ,jgÍâÄþC,ì58¬Âã¬Y,]º4œ±ôò·j¸?•cùÓZÉpŸ*„k _|t½8øÂø11lÁÈQ!U£ƒóÊ£H ÞGË•°„⣠Ôvµ^ ì+RyI¦DŠ&C±Õj”÷]3ͤI‡òäÃûÓÃ#N|@ä,Ù𷱉½š•½P!IU=qâaèÓ¨W²|1SµAµWG'K6$‘¡#¡`—bÄh !,§Òr9 -,tô"›!S䩘 zdF¯—n£áUS¤Âk Žíà„ÇWöTȉÇTé‚00b A˜”v _œGñØÕÛzzмñFm\Ë4!• ½ Ï:~œÇó–«m¶Í¾¥K¹¨¶–O=ÿ<·<È‚ÿñ?8ØÚÊOï»ÍçÇç¿ô¥0ßc&ãÆãq_x!lß^|¼ {ªkhÍÍÍÔ××ã8ñxœ|>/cH¿9›ššØºu+k×® oÖÎÎNn¾ùfÖ®]˶mÛ¸í¶Ûèì줩©©Òç!‚0.<„ü:qút¸næòå,ž>9‡ñZ›#}&t]Àeg_&CüÂÄÏ3©!£P½¨%(Ï(µn 1B Fð§ñ•Ç’°/ ‘(ÂØ¡<ó€Ð{Y…m¦9÷Thå$ÉP¬K’$F,Ì{¨È“ó.*OÇ<ù"ÑÑÀ ƒši_utR¤°°H“¦ŽºÐ¨ j"‚ò^Ì‘ …¿ lì>“¢¢(û¥¼%SÁŸÑÇ–eɆ“-ÊÕ­È í˜•7xŽ\è‰ÙA2hhák>øK 6²d‰«ôWDAA˜„ô—g܉xü¹®ËWî½·¸ÀÞÀ,ŠÇ®îøÔ§ˆÇG+FZ€Êi˜É€ãàÕÕñË7¾‘ï¬_ï·3ȹøßo~3—Ý{/·ßsmµµü|î\^÷æ73ý ûæj Xø¦7•]_I”Gc"áOšTB£òzDZ£¬Çcww7[·n¥±±±(Nòö@±¾í¶ÛŠ\™·lÙB{{û¨x= ‚ TEŽjÿÜòåÀÓœž1ƒåÀ‘—Wqàß@Ì‘pÕ® Ø„ñÇÄï´5´"AEJÅDå¨PaR$Âð€è/ØW¡YõàOr< ÂØ’'†6Î’ C&I’!NPáHÐK¯Ž: à©˜&Ú/£Ï*̪M‚Dx¯+¢!VœP¤41Coé <¼°Þ¨g£ ³Z*ª\Œ¥"a´myò¡`©ìš ³ªÂÍÇó0jÇ¢Bh©(ª&Z¨°Õ*?®A/½LcZŸ¼—‚ ‚ ‚0RÊMòµ,‹|>ï‡åÂóŽ×õÝÿ\›¸¶ ÐÕå¿Wb¦ãðêÅÓ{Ál>z”‹?úQ¾ó‘peK _ŽÅø”¦ùBdK ¦®“Ìç¹qÝ:BÝö+0V™ð¾È¨D\%<& ÿ³ÆŒ²Â£Š•¼qãÆ¢õJ\ŒŠŽ×\s à{CŠð(¤ÆL‡³O/äÈôŸ„«—÷ÌeÖü¼þ?§sàû°ÿ‡MÇDÉB1ÐÆØ†”„á¢ò®)ÀÁ Cÿ©P.n( †£ž’Q$¤  Œʃ0C¦(drž|(Þ©{U…Í‘ —[hAC+šL&‰Y$4Ózózf‚èiÒEa[Õ>ýå50H‘ê3i¡¿|‰Ñ0¦Ñö(qTs´üpPžÜ¡ÎEMÞ( W ˆð(‚ ‚ Œ ®ëFžê]öϛǑ#GÂ5š¦á-[ÀXe¢Ü¿?‡ŽçUÇÁ°,È}Ûæ‰³ÏÆ4Mî½óNÞþôÓü¯¿þkR3fÐÜܬ¦‰mY8ŽÃŹXV¥/ë°I¥ “£ful)jU%`-M¾ÚÚÚÚoŒäÎÎÎJŸ‹ ÂØ²oÓN*Z}ùüK10¨Ù½<àˆ·c ¢£PiT(UzQ…PL’ …BåÙ¨ÔUhÁ¡x(ª~D„Ê¢B§ªû8A" 3½G•'²òf60È EG !š"EœxYNí§B+Õ^D_ó¨Êæ„ÕÐÊ ¥eJËGCCŸÉ¤ˆr"h¨0³’ÓVAA¨Ñ0«JxÜuâD¸fn>Wvø8¶mãy‘‰Èù<¸~ô•Ó¿úµ½½\ Äĺ:H§Áqøé¬YÌèîæŸù ‰TŠ|>mO‚N$tuuùÎP¬‹ŽÏ†xešUè9™(+<*q±»»ðÅß±cëÖ­+*«Gñva2‘†¾Y€æ.+SÒà†`à_Ó4ùÑ„)Î4¦y*ªP‹yòØØxx$IöñüQ"P$> %j &‚0úxx¸¸¡gbé$úSQš“(*Y‘!3j÷v4jty$u ‡¨Ð9Ñs¤¨\‚ ‚ ‚P-¼ºtiøþàïígÞ៌ 6ŸX,V,r¦ÓàºäóyN¾ø"Ëzz8ø‹_ø¢¡ë²}ûvzkk¹öÈÖâ|롇x$â€õìÃhç¬jìvÒ9Œ¸•n@1e…G%.Z×Y•ßQ…V-]_*H ‚ Lt¼~ÖÏ>vÌ=¾œY=sù€ò8 Üô%´¡ LMÊ…:UŽJt„¾Þ@ÙÁñáz1ŽÇ@¾ ÅäÉSGyòe' ”N 01‰?†Zn¨Ä‰‡¡YÇÛSZû™z< ‚ ‚ B5T\Ž™¯¾ øaO£œž3‡™Ý#÷xÌWœsNa…®C>Ï›nâÑC‡Ø9g‹òC§÷?ÎÎ¥KùÑ‹/‚ëòÙùövwOΔQ龫Vþ(‡‡KÿƒË£ACÉr¬äx£y.g@Yᱦ¦†Í›7³uëV®¿þz®¿þzZ[[Ù¼ysX¦½½›o¾™­[·²yóæ>aYA&:}ìóܹ¼¼à—Ì{u)g"¤B ~ÄE„©‡z؈>txx¡Àha…£Žær±‚0QP¹ h K6 ¯ÚB˰„<åõ8Þ(›3X®Ä±b$¡VAAa"¢R6íß¿Ÿé7–Ý6À¯^~¹°"?µo:°÷“ŸdÞþýnË–-ãÿžsõõ¯~¨Ö¯ÕÔH$å*A©p7XŠÉlÉrž¡ã”Ù?êEèÑWØHÜËóø¥ÔíQmH–9~6xUeÒ‘vÆ©ß ö#OÉéýmhllä–[naáÂ…,\¸Í›7ÓØØnojjbûöí}Ö ‚ L&NFÞO¿üò¢m‹€sgÎ,Z×_bb õ%SåÙX*D:8$H„ÞF@Q¨EAª‡$ÉP|Ì’%Ož‰a i•ß”àXIáOrÒ ‚ ‚ “™t:Ý7ü)ðø›ßÌœ9sŠÖ)oÈ3eçÝw‘ñHÇñó;9OüâÜÓÚJÍK/iòØÕW£›&ßzè!^Z¹/ÇîÕ«‹ë‰2aÊfùÁ„¹RE‹b±Ï-S^‰sÃÖlн]Š…ÈRaÒŽÏŽüGËGÛj዇ý1 _,LõºÁk}°ÎŠ?hÁº¾÷£,7uÁrçžÇØNûÇ(£ä)9} 7ndóæÍlÞ¼™k¯½¶h[cc#Ï<󌈎‚ Lj^‰¼Ÿì÷ø½ÿ2\®¡¯ðØ_ŽGñf„ɉ ›ja…ù¥¤‡‡ŽNŽ\‘בØA˜¨ûÓýAAA˜xžç{t\pK|0\ž~òEf/™=’pÎáÃ<ð¡ù¢c>žÇK+WbãkSÿñ¤OÆG®¿žX2I"‘ðêšæÀ!V=÷2Œâ0°˜õà+WÞ.)ï–l×)ö$l X($ho>¨[c`áQy¦)…±àÕ*Ù× Ö©ã™A9%Øå)J½àøJÌR³Áq¬`›ÝHÙDð¶g‚óOû™@[PÆ ^;‚W/Ø®®S>8n>ÒžЂ«× Žcùç³äûK†ñ¡—gfÚÛÛÙ²e áº7rË-·°víÚ\¡ZQ¿+]‘uç<ºˆ^ÃσèdoÖŒ"¡A%%.—ãI„ɉóäCÁÁÁÅÅzÌ66Z(<¡(©¡«çÑ`¹'A( › “,!CAAA(Åq\7/ÔuN;€“gŸÍ_{=A¹Ó³žàÀò(›åÈÊ•\{ä¤Ó¾§£a°ð™g¸ð-oaÕöíX¶M6›%“ÉÍfÑu\.»T)£¢žŽyÓÔ׃±4¯¡CAƒ‚w`¢d»Ž/¼å)ˆ`e£šh>XÎâ qj‚Ш„µxp\½¤=Fä},XV*mŠ‚ØiûÚA=êÜÒ‘¶æ‚2õ<åmÚ™ ÊCA¬T«z5‚ý l]PV]77rMÒ‘k¨×AµQ Ž­†¦³%ÇQB§)£L‚ó·`ùß-‡›†ñ¹—¡_Ǧ¦&>ÌæÍ›Ù¶m×\s Û·o§©©idGA˜ìÄÒ¼Ðë[ÞYhÌÛ¿Ÿ|¾0ͦ44¢š¤‚ L~ÔäzQ‰É’ø*´ªÚ®¡…!STYAú%‹ŽN3ÍEÞŠ&YAA„R”ðX[[Ëé9ûÂõs{zFï ŽC÷•WòKþ”y=䋈ŽšÆ‡Ï=—Yµ ð%ÚÚÚp‡L&S­-“(ävTž¢t¹OèŽ4*–†uK–í l…P§Ñí) ÞzY|‘,E!¬¨F!©‡/ÆÙD?œh2rœh[ |á®9Øž Þ+ áQ-|ÁTÐ%A»¬`_Õ+Ø®<•‡aGP.üç(ˆšJ€Uû(Z‚e=Ø7Es`[ èÑTyJªóTפ_dŒ—ìOñ¾Ïþý³¬yb #¡¬Çcgg'­­­ÜrË-l žnذ믿žöööPa"ð[ÏÍåµi‡‚5óöïǶ‹}þE`„©ƒ†[U£üE=µÈŸB„ A˜ØØdÉÒF†LAAaHÔÖÖr(²üÁÕ‹Ù>ÜJ\·(dktý´ÿ˜%ç^ÿ­¨L($ÙlÇqÐ4x<Þÿ±¢ÞxjY£6´”<…° J<³ƒý”—`TàÒƒ2J¸#R¿ u 9 ÁÚ”§Âøbc ¾×"Áö F噦¢Uy3ƃ÷/Cõ …p¥©`6Õ¹(aS,§"ç–‰¬‹õfT× ú'˜ÒúÊ}6¾È©„`u<å]9söÍa¤”õxTáUW¬XQ´~Æ #>  ÂÄAýJœæíß@mW-::2VU¦8^RU…O- ÁôMÌð}é6Aª›4iR¤ÂÉrïN\$4® ‚ ‚0ÖØ¦í bexvÁ³Ã¯Ð*I²‹ù!U]—ßýò—ÌØµ8Üt|ùrH$ˆÅ5.s¹™L†æææ¥QìᨵhhÐhÎE%L&ñ…?‡â°©*_¡B½Oõ*O¾æ`›òÄS‚¦03‹sJ0ÔñE¸6 Âg<øW^†Zä<¢Þˆ*ä(‡'.ë¼ £ŠÅÁÅb`Š‚ÇáPPž“cF¿ßÇþxù]/óÌeÏŒè°3G´· ¤FýÒú¿BkçÍã!|/ÇE,ªtãA¨ìÈtÀ)llLÌÐãQ!b… L<,,\\ñrAAaÈÌš5‹ùœÏ¾÷¼§°Ò¶¹Ü¼|ø•¹®/4jšÿÞ¶ýe]çͯ{§ç_Êïæ¾žc×^˧³YtË"‘Hò6¦ÁKx444ÐÑÑ1𱔨¨B¤ªÐ©ÙÈ{ èŠ,§(ä=l¡àÇ‘Äï’Áöèˆ= ¢˜•X¨B«R²]£eÍrjøž‘ÍøÞ”Ñœ‹åö-E…|R:§Q+y?VBâaúÈ«A˜ø88¤I‡ËÇæÍ ßÏ8UÃ<@ .Ïœ)s6AðíøžŽñ’©l2EyML Í,,Y$$$² ‚ ‚ CcéRή­eñ_ýóOœ(¬÷¼3«ÏóüÜà à{A¶´Ðù_ÿÅ¢CÿH÷ùWröe—ad2Ìûçyè*ìªn@tO'•JÖDœ‚W ò T¹•øõpt)„MRð84ƒzÌ`ß¾PÇUÈÔèqãrªeEª¤|©°§¼K·«¶¨úZ(ˆ•C5*!£ç‚ ‡K8>wnøþõ//äð¹ÝárMMM¥›+B…qqÃЪàçktpÐÐ0110ˆï“×Q„‰ƒ‡'ÞŽ‚ ‚ ‚ Š‹‹k»0w.¯ÕKϲelœ>=ŒàùæŸü'Ä?ÀB43 !Òu!ö½ÁÏݘɰråJ8ÏÎÿSž½í›ØÙl]¾•Óæi¿œ ææA&¨mi ¹ £Ør ”Q^‡) ù•£*}\ІiU*—¢ªK­/ÍkXúØUv0‘p°lXª>u|a PxÜ´iSÙõkÖ¬é³î™gFóU¡Ò8E¿ŽVöö²;xoZ‘à ÂÔÁÅEGÇ þllŒÈŸ)Ô«„X„‰‰ ›,“AAAè}ûöÁr¼`f]ÓþŽže˸ ¶6,w²fwøþ Œ"ˆ±mPaS].5áIßçž{ŽEoücö-ÝǦg6±6µ–U±UÅû«\ˆPȹ¨@F5/&*DF|ï@‚w£ì«„Hå=X*$F½µ ŽRÇJ¯fF^…Ð?e…Ç+V°yóæJ·MaÜèÇþ§ÿ÷ó º¦éO‹éO¤arca‘!Sd”‡£ô Í`úœ ­*¢… LLœð~AAA(GOO_ÿú×Yø«…Ì¿q>§ç¾Bomm‘ÎöŽÞŠ“¢¼uÝÿ¿:å¯sù­-ðä4žÿÂwY³l 'ºWñòv—³g€ Ò¦†!œàߢ ‚/ 6ë²Áz噘 Þ;„DUŸÊ³˜ ÊX‘vÇK–K‡BJ=+Q²áŒ)ý ãÞ˜;vÐÔÔDggg؆k®¹¦¨LSSÛ·o§»»›k®¹†ÆÆFV¬XQ™«'¨S=v  *üåë>Ä 8-EsA ‚06T-(F ŽÑ‡ßº¿pŒ¦QΜÁlÁXÙ‚=#Ó`¡âTkŸ@„ñEl ÁX–łϾ›i55x5ÅÊÖÏ.þ;ÙYv¿"Ûöó:jÄã°>¤ýu® .ì›>‡ùnhw ã'`ýÊõ¾ –í§¾àçá{+Úø¡‹¿ŸüÇ#åf¤\é6‚õðI˜>Ô‚­­­lݺ•­[·ÒÚÚ:ê Ù±c[¶laãÆlÛ¶ 6°eË:;;Ã2Êp466²mÛ6:;;Ù²eK¥¯¡ £DµØrs¢Ñ$d RÆj±ýacãâ†!V'а¨Ët>a‚1˜-K;#VäÉ,Be¨ö> ãƒØA&ŠÐ4Ó5/Ñ,Gã§ =­(¥Ójp¿ë{8B#ðEÈD‚Þ_uqjÞJ´ßšœ:w=\é§„zrÉ“,î^¬æ‹q ¡S óó<øÂc_44ñ=ÕÐA¹à/QaѤ¯×¢ ;æxìîîÆ²¬p–@”šš6nÜH"‘ ¦¦†‘bY›7oC¼nذÇÓÚÚÊÆßÀlܸ1\¾í¶Û0M“;vô™Ý ÂÄ£ZìÀ`Adð^Æ–j±åP‚c”‰JUl—0ÑÌŒ•È“ÇÅ¥ƒŽJ_A˜òTsŸ@„ñCl Áìß¿ŸD"Á×´_Òßè¢=ø³ù‹y8åB`8àšåärkïaÖî·ðì‹¿cÅ9çQó? ÎÚyœEÓùb£•ç£òhTaPãÁz7øÏà‡WÍÿЍçc9ôA¶ Sš~…Çîînn¸áÚÛÛÙ¸q#6lÆîîîвµµ•;î¸cDâcgg'ííí}»ÞvÛmáûööv:;;Ù°aC¸nÅŠ¬]»–;wJ'B&8ÕbüFCD„ÉHµØ‚þpq%Ç« ŒƒÙ‚±´qâfR LVª½O Âø ¶@„‰b:.ïàÄÙ'˜9ólÀí7[ü ÂcwdÌá›yŽsœéƘ 'Ÿ9ɲ—þ†eèðòpág¯þŒ%Ÿ^Âò/,÷A_Ìã{)º@2xŸ‚pøS •PðŽŒ2XèT #ôC¿Â£Š—¬\—K¹æšk¸æškزe MMMÜrË-gÜå½bÅ n¾ùæ0NóÆY»v-‡èÓ–… ÒÞÞ>`ý/½ôMMMlذ¡"¹+¡Zؾ};;vì`ïÞ½•nJÆÚìÝ»—M›6qÍ5ׄ³ŸJñº» ™a’±iÓ&>ÌÞð†J7¥ãÕ'X¸p!Û¶m;£6ÚØhø¡LÄ‹P˜¨´··ÓÔÔÄÞ½{Ëöõ+Í`¶`¤}‚ƒ²iÓ&Ö®]Ûçù O~„P„‘ÒÔÔD{{;¬tSú0Ï÷Þ{o8©ê„©ˆ<Œìù@&2f8ø˜a¨H‘¯¼îŽ®< œÝ§ŒÑgs¹u8ÁòÛ:à¤ËòðƒVZO}€« ¨y©†že³˜·”Rxçü;¹uÓ­p'¾X˜‡0zk?´ªŽïõrøb¤ ý*¤Â”¤©©‰ÖÖÖ÷ Êæxìììdûöí¡§clذ7– Åz&\ýõÔÔÔ°víZ:;;CË‘²xñbEt¦<*úÊ•++Ý”~+;°råJ¶mÛ6hb÷îÝðÚk•¹éQªÇy}ðúy¦D;A¸²mÛ6Y¼xq¥›Ò/cÝ'8“A7*%tîEx&*k×®eÛ¶m\wÝu•nÊ€Œ•-X²dIh £88¸¸á=.L><é|¡~—,YRé¦ôËX>\wÝulÛ¶MDGaÊ#Ïgö| “ 3Ú˜a9^[à!vww3kÖ,z‚õQgÀrÑTú¬s€§‚¾êm:ûl¤ÝÙ`¿däü“på5WrÙ× íûZªÁ”à zè::†x< Â3˜-m;àà„÷¹ ÕAµö A_Ä‚P-vÀÅ%ßÇCÀgÞ¼yáû¢*{Ê. uÿkžÑÙ†Y]k ÷\ˆ3ÍaÏÕ{Ø÷å}xžç“¹»VFßëø¢c eÊcŽ0ž”UxÕÒ·ªÌHrì[·èë5=¾ª¿´LkkëRAª›j²»kj8µàw£SYé¤z_R"—B áO‰N±`½¸”gS“ A•’Ê  Dª×4Q¯Žbo<%t)¯=‡‚ÐþRø³¤2SG÷W+8Ï~؆Žà½‰ B…|è ¶{A™~ÏL%ÂNû©sÍǨÖ;A]ùà˜õø"›MqØZ%ª*Q7* ÖGÎ]]ûè¿êÄéAZ"mï ÚΣ-(ãEÚž öé öS ¼UH‹Ðì×´I§ J¦ƒòeà?”SŸ{"X¯ö©öQõj‘åØûɽ<ûÆg‡ÿcªÉ”¢¼d”ਡ‰ð(cÄ`¶`¬ì€òx¡òTsŸ@„ñCl Õf¾‹Í¾rŒbáÑ æ?êñØã/h/ž@ï\æ¯ßƒN·0~fdðôxPŸÁªçVqå•W¢ëÁX„Fq¬ÒTõ¥6¥áVaŒ(+<ª›y(®ÊªŒÚçL¨©©aÆ 455…¹"[[[Ù±c×\sMX®4ŸäÖ­[©©©áÚk¯­ôua„TÚ(AÁÅåÑEß=“ ŠEFf´œ]¿áPìÅèâ Kà d <×”¨ÔYVB ¯òD®f âU6Ò&ÕáPâò@l öÉQÉ:‚÷Jk¡>¬S‚œ1s‘òø‚œ*cRèà¨ölo¡8ôCsЦ–È9êA}ª‰È1”€iËQOˆ ŽŠ–’sÏDŽçRH¶þ•àvþRA=øoÚ”ˆ|vP£BaœBx Õ¾a³7XÎDöÉësÁ5Pa4T=ê³ËDêUmÏøí8øþƒ›wl˜_ô±§Ò¶` Ôƒü%¤Ç.cÆPlÁhÛ/øGA¨ª¹O Âø!¶@„j³{€ƒå6hþPŽ"Mš˜ =VÙðÂAðzлjПyCaÛ•‘§Àeò©¿}ªè0¿8ñ‹Â‚EY"J3FdJ–%•½0NÌ,·²¦¦†7²uëVÖ­[WtGÙ±c[·neãÆÔÔÔ0n¹å¶lÙÂW\ÁÚµkioogóæÍE.ÔÜpà a"ÙÎÎNG|lAªƒj°ÉÐíp˜(O:µk>x¯ÄÈxIY%n5åÚ(ämT‰‚ý¼àUu’Ár"²Î$ŒÄø—< ^rJìSá@sâ½—ë|¨ýúCµÁ¢à©£×‘éÏ™¬œÞ£çãPaGÎ;Úù*kcÎPðJ¬#q´‰Dä˜ÈŽxÕ` úCyB‰§£ Œ=ƒÙ‚Ѷj’äw„ꡚû‚ Œb A¨&;px­ÈͰÀ³E³þ#ùÅ+_| ŽõÀ%S>é¿ÌÓ!= ÌÞpâÿÉOŸdíCkù_«ÿ =ÁúûÖóÆ7¾±p@Ç‘J·ÉKaœ˜Ùß†ÆÆFvîÜÉ–-[¸æškذaCè–ÜÙÙÎ*X»v-#nÈŠ+¸ë®»ŠòK–ºA×ÔÔ•Y·nt aQ=vÀï$HB"¨þ„6à.}—Š +²^…­§àÅí¨¤¥Çl¦¼¨T®ó¢Ò šššX³fM¥ÏCaô±"ïƒ0ë8ø?øÉà_åŒNë[($vV¡tàìJŸÌ£<;a’âà™€îɶ-¡#a¨¨pÊ‚ ‚ ‚ ÃcÈ)^ÚŒàYãµÌñUN,‡š U\brÙÜËð<Û¶9çsç ë:¦iúe$H‹0±ð(‚0Ù˜qü,ÿMô‡ÜÆ|‘Q§×QE^LP!•ø8U:fä:Â$d¬<=Ïy%ýµÙu‡%<Že[a"àáI¨ÕIŽ|¾‚ ‚ ÂX0¯dY?TIåtìëñß/ºðàþ,̃u‹×;¤óÝžGÉf³xžÇŠ«Vø›t½PFæJ ANž< ÀY¿y¿"š»P½¦(ˆl9 ž¾?ø üO/@›BØA˜¤ŒE˜Õl¶ü“N§Ë®Ïç‡׸¿²®ë´R¡Ñ²,ñ-\ i;qpF^‰ ‚ ‚ Sõ ÝGxl/¦½ ½sÌîöWÔ‹8©A7¼zï«…ÿJg×'Èd2¤R…þ‰D»)^é3„¡!£ ¾7SWWµ3áÑÂ÷pLãÿ°ëÇTOR>‰³†Ì@„I„ÍØ‰qå„>Çqpœ¾ˆëºe×÷G>Ÿ/[Þ²,²Ù,Ùl˲ŠÖ‹ð8Dòy_\Ìf‹EFσtêêüס~^¼îø­o1÷·¿­Øñ«/ÈÇ2Ñó¸ ‚ ‚ ‚0>xžÇ‘Y³Êoì)^Ô‚¯ø ]Ài.Òayq9×uÑu|>Nд`QÆ… ‚‚ øÂãü]ó%¿‹ùœY ï½ÐUº<Õ‘k!Lbô²³ F†mÛ¡0èyétš††Ç– ™ÏçûxN$RÚ¶ j?Çqp]7|°±,‹t:çyEâ䄯u}/*f³¾ˆX*:Ž¿­¡’Éâm þ]_&úYÙ¶¿.‘è+J‚/L–’Nûõ•nó<èÚ{ÞÐ…MÏóÛ“NC}½ÿðÄ[ÞÂk TèC©Éï(‚ ‚  ^øÔSÜsàÀöXÇ¡îA;<z»à Þìƒêð<Ïó0M“x\Ü…‰‹‚ ½]ÍÌ=†#¡_|4ðC‰ª¼ †ªELz “!_ A˜h¸¸c"<*‘϶mlÛ&ŸÏ“ÏçCÑ1ŸÏ…\ ’ù|žiÓ¦Q__ã8d³YˆÅbäóùP,tË„üô‡«.», ÛR__O2™DÓ4lÛÆó<’É$–e…ÿà ñZµ¤Ó‹‹yù¼/úY–¿M‰®ë—w]]TL¥ « 𛡣Ãñ8ôöB.翪Å|Þ*-*ýÐuÐ4ÿøJHô<9™ô÷™6­ï¹ÔÕù"â´iÅuZ–NQ’I½çiµyïêÕ"<âßç’ÿOAA„¡Ò^ÛÅOúSÞ0à³Ä8~ýɃÎl8ú4¼SƒO˜Pçw^XÒó<âñ8©Tªàå(™åV¶¶¶²iÓ¦J·Ma\q®ù`°jÚ*<à‡Xõ Lùdâ{>Y–tP>©‘W!ÕŠËØäëS¢ ã8áŒFÇqB‘/™L²êôi2™LXN½æóyâñ8ù|>ÌÕhÛ6‰D‚†@tJ¥ResHÞ>>W>Ì ÑÒ†d½å†xϧ>E6›E×u‰–ew]Zï¹§ÏlKÇq0Œ1j\×åÊ¡Ä@Móÿ£ûX–/àÅãÅ¢ çù‚`t][›¿¦^Áß·¹ÙéJöÔ9gö©aøÇO¥üö%…sSï“ÉÂ:%wt”Ï©ëþ~©Tq»Õ±’Éâòê‘ë™ÍfÇöó›`ŒÕAAA&'¿üͳ{÷îòWEÞ_>‹Ìgðû±³¾‚ñè+áseæ… Ÿû›ÏÁûü¢¶mãº.¦9É„IOYáqáÂ…lذ¡ÒmAs\ Zâkóæñº¿¡ñÎF^{üµB(U›‚çctüYG¼üaŠ0TO(•¡?hnn|áNÓ4<Ï ECMÓp‡x<Ž—Ï“Âð0M“S÷9Þù™Ïçº~ØNÃà•÷¼‡•_ŒùÁ¢yÍÀž /Ä:}7ã?¯¾šëﻣ×]Ç®ƒ¹¨­ÍUAγŒh×ÇCÒó|1Ÿ÷…±\® ²)O¾Rï@Õ^]÷áyÅ"œºö8ZDKËÐÅб@×G¶}8˜¦mOÇ¡¥¥…ÿøÇ•»&U„‡'¡VAAA¦ جÆŸ´lcCW¤Ì+h&¼ ,®-ŠZ‹Å ×vWÏÍåÆa"Q6Çc{{;›6m¢½½½ÒíASÅêü…ûÅûî¤æT¿œÂ3øùa”)Í›—N§Ã°™¥xžGCCCÑv×uÃåhˆNµ­¾¾¾Ò§8áI“ÆÆ²'”Kihhó3&“I¦M›†æy|øºëp]—x<Ž®ëÄãq ÃàŠsÎáƒÝÝÜsãüõ]wñG_ü"õ†Áñ³ÎÂt]ßKQÓXtè_·Î?ˆeùâ_Cƒ/ι.?Ÿ7/<æ>ðN}ñ‹8ѥʯ¥…åÿüÏ\ùÉOú‚µ®óôòå̹ùf:::Èårè¶ÍÓ7ÞȦùóiîŸÇ²,,˶m²ÙlQy \ðío›‡~x?™‰‰‡GŠ&C˯ýÌ•Ðèº.®ë’ÍfI¥R$ ZZZøõëyÿ/~Áï{4kšï¡fÛär9þêW`šl¸ùfÚÚÚèíí¥­­£ïºŽ›—.%‘HøÂ\ÿyÛ¦£­Ão~úÚ" ƒ|Q®æ«_eÙG? @"‘à‹×_Ï%_þ2ù|Ó4‹¾_¶çAW¿wÛmxžçß‹š¦ÉÜÛn# ì Bù»®ë ˆmm¾Çb.W$ Ú¶í_?]Dz,-ZD]]]Ÿï´"N‡âçyƒ ÊË4z<õ9…íSßÏ£¾¾>ü<•PèyŽãÝŸê;PWWN P÷°ã8Ô×דÏçÉf³E÷²*Sj'TÑ| ÉdÒŸ`YVxÿ+[`÷“3j#$¿c_†zŸ ‚ ‚ ‚ Ìýƒ`"ç3Åëßœ~(òL¦žwkj`Õªputœ)N“L&%r•0)˜9ò*A&.ûK–-,R¤ ôVºugŽ åž—eùBE,ÜgiN¼t:M*•êwŸX,Fsss˜Ïó¼pÇq°,+œ-6\JÛ¢ÄⲬ0Œùð½¾·"@*…§ëÄ Z ?½¬ˆXqá`õŠÂM“9y¾`DLrwAçEo㪇ÿ›Ï¿õ­Eßm·LÛ] _DQ°É0c€ÊO ð•{ï厛oÆqb±žçÇyÈ0B‘PÓ4©7µ¶ò³}û µãøqÐ4––ò¤ëº†eY¡Ð–H$ÂðµÙl–X,†ã8躎axž‡ad³Ùpv¨ò.Íår$”™1ªDQÃ0hnnëTáoU[”ª)³Ùl(òogû›ˆ iZ(&ª}5MÃ0 ’É$º®‡ù5MC×u²Ùl(€ú­Þ¿Q‰Žã°hÑ¢ð+R]‹D"áçãTŸ­ã„vE]™E[ÀaèJAAA¿èûxç}É_8@qê†ßî… Îpõ¼§žù»ºº†=GªA˜Òˆ6z·Ï¿½ÒM:#ÒétQü÷l6 J˜/áQ娋Šq¦i†í)÷’É$©T*ôžRm7 #\VBb©—’òÞQ‚뺴´´ô+væóy ï 꺎¦iÄb14M£¹¹9ô<ÒuÇqÂa*•*òdr'¼ö*_"‘À¶íP ´,‹–––¢}u]G×u’É$®ëÒÕÕ¶!•J}žQ ­­ Ã0ŠDõÞ4M:::Â÷ÊóQí£®©ã8,_¾œ“'OŽËwb¢3TÑÑuÝP`T÷¦iX–ÅCgÅ%¯¾êVé4xNì|F û0·Lý/‚}UÉJMƒ•”íÑ9ç‰ٗò{?ÿyÑ÷ÆÆãôó@{L%<:»?–Ð}|1à{ðær¹Ð«÷…·¾•޶¶Ð+Q]‡¿~ª, Ó4Éd2¡PøÑ;ùÛ ¥º<`åõ×óÕõë‹îý•ÿó²wõjR_¶#•Jáyç¼pë­a[þÃ?@2ɼìò/ÿ÷èkÖJ¥Â{^Ù'åü±ßûoûèÛÊžoKKKÑul ÎQQzoööÜæMÓ,²I¥û(EU_"‘ècs£ ¥ÞŠÑºu]ïã)é8ÍÍÍaýåÚ2Õ™haV•àL£¼ìÕä œp¢~ëÈårþ®¡÷½®ë¡'¿Ð3%¹UÕ½”J¥Š"(á^ òjÚ_…VzéñÕooýuunC¤ÙubL ‡uÔ$õ™å|UÿQEdˆN`ˆÖŸH$8¡rö ‚ ‚ òJðúZTx| ¸èíwsaÁ\˜Ýƒþì+ - ‹e(ô¥Õ¸‘ˆÂdD„GA„€³ÏB Ä)‡°‚X–UäÁ˜N§I$á µLRÞUÑAAåE3TÏ5@¨êVaÕ¥ò^Rß±X Ó4ÃLÇqÂAíd2I"‘ ™L†*åéÔT¤ÊJyç¤R)ZZZÈf³E^QÊÃG×u2™LÑÀdtð>z À T8Vå „ªJˆ^«RaP nF¯e4üä`¡0q°Ëúöçy\ÃL~sè-á=dÓz{é6 §{ïYàrpºÁ¨‰TtX囡¢oòË×= ¶A±Pèóàè«gõ«»ÁYXÁ4ÿÕ›Þo($€´€8¤Ïó˜ï(®Æ9²ßqøìÆËÂЩõ€«ûrmTàú΂šPÿ^êèè F_‚óÜËš¦1CÓÊÅtÂEïù0ÿõáû×ܶùæñãl|w^LÎtšÿ/ÛÁ½ž–Ñwò‰ÝWXÔõ¡ ÒCeÈõ©ÏG+Yç®+¼É”0#bcÿ¸Uò£¯¼ð£ß5åY¯¼\ÕoPÔ_ýišæ UËårž*Ïà|>֡‚+QKå–‰æ†B>b%öåóù0r@]]]X‡ª7—Ë…O޶EÕ«SÕ÷PÇÔƒ¯ê|Ôo´ú.«Îê\U? “¢”hª®ãòo-çþŽûqæ:aI'&çD? %Þ•ö£Ô1”—û@÷˜š¦Ê”F‡(‡çyÄb±P8V‘ 2™LQžÝèyFQ©¢žÐJ VCÔ,{˲سgOå¾ü‚ ‚ ;ªHxؼÎìAq!ÌXÓû(Ìé.[O2™Ä4M…IÉôJ7 ÝÝÝ\qÅe½1ššš¸âŠ+X³f [¶l¡³³³ÒÍa ¨„¸üò˹¼ëòâÁÜ Qꡨ= O½d2 ¡ø¨þU޲þr‘)¯…Ê£…ÆÒ²jѶí0, Êg¦<-Ë íÔ` òTž‰Ê3C¯ ©ØÑÑAGG‰D]×ý\m åa¥ì¢âA6› ÅQðmãñx˜Ry[©ý•0¨Ó7T/at˜H}‚çüc2™ÏÒñÛßòò¯~EâE¾­ÈO~"ßU'½çJ*Ú뿸%Ih½‡‚71 dý×p?¬Ë¸§Á1è·Õ~xGðE6+¨+ Î:ðb@]q=ùsÁö‚uêX.x á‚+./Tœï*Á¬¹¹™¶¶6r¹ÍÍÍtttÐÖÖFss3]]]tttJ¥èèè ««+üíTÞ‰®ë†û)13NS__†oii 3‰D8¹F‰`mmmáoooø»ÝÕÕE.— û‰D"û-Ë óžªc[–…çy444Ïçikk ûñx<œP•N§©««£¾¾Ã0èíí¥···à-ˆ€J<¬¯¯ëøÆ7¾AOO±X ˲ˆÅb¤Óéðµ®®ŽiÓ¦‹Å¨¯¯'NÓÐÐ@CCuuud³YH&“ÔÕÕ‘L&ÃÏ­¾¾>Ü®êSǨ¯¯'A©óPËét:WÕò¢E‹¨««ûDÊ[Qå›V}·|>O}}}Ø_SylÕ@Vtòšò|V×Z‰–%üòDê‚0vˆ-¡Zì@WtÝÀŒ“$ö¾“Ì¿55PûJÙýUZœ‘D)„je@ÇM›6õY·uëV¶nÝÚgý3Ï<3jÚ²e ÝÝ}g455±}ûvY±bMMMlÙ²…»îº«×N„1¤vàݽ½ì¹p««üù Ík¨Õ€¹òáu‹Úù-ý½î§¼óUß!!ú¾T„Rý%^©<§¥JëQ¢a4¼§òPTÞwÊS:Úþ¨×g´¾hØvåqÝV.$k6› øëºÎ%w_Ây—ŸÇ£Þ£a_)›Í†Ÿ¢çßÐІR·mÓ4üնm‡"®®ëa¿I‰|º®…wWÑ-Z„¦iṫeÏóÂ<ÔÊ«1šƒZ]'×u©¯¯û^ꚪIcê:GEݺº:2™LŸÉZÑÏÏ0 î½÷Þ1¹F“J÷ A¨Ä‚Pv@wuxÊïœó(¼èÁö,||9ôôô)¯Ò ©±±,ÙaQª›²ÂãŠ+ؼysE´uëV>\vÛŽ;ظq#7nà¶ÛnÃ4MvìØÁ5×\S‘öN5†ªqªQš²¥yöÊåz+W^ÍnWâOi™Áµo4ŒÔË/¿\éK6 •²†npè݇üÞĈª1*·¡išá@V"‘ “ÉPWW†×J&“d2™0_¡äs‡l6:Eó.F᪼_P¡ÚÕÕz(Šl6‹išáà£ô‹FC(4@:”í#Ayi†Îö—ƒ“J÷ †ë5óñÇXój çÏgIpO¼gõ{ØÐ}vñ‡üï@åU´ÀY¬?6ÄG=W} øS|¡É(ä}t¾æÝ€ ^Ä]ÐÑÁP¢aäÖsÀù ç߃u㋈uàÍ/˜Wælð¥¼Ý°¼øö2´%JÝý¤ÑþTPÏWA? ú)½aο¶ ´\°þ§A=›Àø>¾]ÖÁý§à2= Þ~Èí°mÂù_ ÷€öa_Hzøõ/réÏÏÇu]n<ëF¿:¾hhûç‰IAäkÖ[ÁõMùõ§àu˜ >“dpîvðª¼|Q·ž‚@¨DÁ…°¨N佂}TY%.\ÿ¨®¢û@¡è pÿ›ï翞ø/¾b…%3–Ðý¡nÎÒÎ*œ—Ô•€¦î&6°aXßõñ¦?[PmÏÊ-ê}§r áï±×ÔoUWWWØ¿Ž†î.ÊULù€ }B2r&Âðr ÖžÒÐ䥓¨J(ïä™´/•Jõ9>þñãàO¢Òu= _®~%G>%p–냗«G…6…BßIÕ£B»«ÏYy}–æ“^; ·4JC&“ =•À­®ui>ÚrÄãñª+Ý'¡:[ BµÚD<YH7¦Ëaš¦ 5ûx­»»OÿÑ0Œ°ß'Âd¤_á±±±qÜÓÞÞŽeYÜqÇ\ýõ}¶uvv²aCa`dÅŠ¬]»–;wJ'"À², Ãð\…SyCš››û Ê«ÜiÊð©°>–e…¯j6°š¡Í«RJ4ì‘ ï£Â*©|'JËd2¡§Ê(JÛ£„•_F…wŠ^µjcÑ NЮ赉^5P¡ÎUåXQm)ýaˆz¢õWFµßuÝ¢5P fpGÛ¢>/%•æê`EÍ ÷<úúú¢¶D9ï¼óFç 7Œ·8ð%4!µN-ü ÃÉéŒP3âËÝ3Ñü;êsWƒIJ L$á }uªÁ150¥60œi]]---á}«<Õ`—4Ëd2E³ãK…ÂR¯ÂjBy (»0B‡ }©†>Á€Âcàóõ /@ãyö¯]Ë’ è›_ÿf_x|P‘Ià9`=8/@¼_U°€ŸEÎSmà‚Óå¯÷ÎÆÈ ¥tð½#ïöëpn&h xŠ«€ q¯sy'Ô9ûœù%ÈÇ@„Gïu`í€Ä‡üºÜ5 ÷zÿ_oÀÛ4_sâC¼t7(ûÁZqpÿ%4{dmi¿ûRÐOCþ ÿsÈl†ü7ÀÆȾ߯—k‚ü–øå“·ƒæ@ü?À¸µ…=ÏÏåà…à¹.Ÿíý¬ïɘ>>%ÆÁ…RŽUÁçSO±¨ÄG;rýË™¥ir«eJ޾ÀÝf—lWÛJuƒR}&b’×ÿÇzjÜìl.¾øb–~dißcMú³£iœ{<ª°šêwûÜYçòé¿ÿtb\õß¾sß}aŸ8—Ëù¢”¦…_{?hóý¼¯ÖÓ ÏsµM×Äÿj¤> a$^‰V¨×!ó4˜sü{ÊøhË ûVHÜÚ_øbøUR*ažâ˜Çy ç‡w¶>©ãàÜÙ7BnðȿͯÓk{ÄwAÚû%hiïŸÁmó °Žû r? êW},›bÏâ`[þRÐ_cyøÊÄý}Üýú 5™ zNªn‡Â GúvC‰|P*J*OÑ¡î_úLõÞ,Ç&e9ð±?üXA<Ž(½*l|ésÝdˆòP }A*ØAªÕhÝš?ÉÕ–¯l Ni° ›ž_Äþ™]4ÉNMþWËa²1säUŒÝÝÝ|þóŸ'‘H°víÚ>ÛÕL†¨ñX¸p!ííí•nþ˜‘ÍfñuË—‡K·ßsÜss—-cÞÚµÔ¼óüQËå‚®Ó³l™rha÷#°ýå—‰Ÿ{.Ë.¹„Ã{ö°råJf¾ò ß}ôQ¾ÒÜÌ/dYOnº‰96pÃM7ñ†7¼œ}6ßÚ¿ŸöeËЀ'þüÏ+ýÕ.K%ìÀÉSµÇÞEÏéŃSc<0«¾7jphÚ´iaþ$•ÃQ͆Rá¼0M3ô2TaTÁÿΪ0§j9:X¦¼.”8¯DG.­t m°NO5wŠÔ=í8Πƒ|BuRM}‚~Å 0) ÒÎ2NëÄëÞS˜à1ÿ —`¿72îç‘àýUøö'¨|QZHæ¡9ÄÁ ì’rÀƒÂºP;øsHÝ \Æ>ЖûÕºFa“‚óžê8ï³ìySãûƒ(žPê,õ×ë-þþj¬[¥'li.Ô§ÚàÜúu~>K°/ö×7´t°þöÞ=NŽªÌÿ'!WÂ$I‘PC€ 15ŒJD«å¦ð]üõÄË"° ÝêÊ¢»‘îÕ]¯ÝšÝ•e×µý²ºº_3½â‚¢¸S®‹è q*"$ S$†a*™$$!„üþ¨~ªN×tÏ5™žËùÌk^Ý]uîUuêœçó\nŽ{yð>|Oއü™À™àþ¼‰åöÏ,{25¡ø[(”aŽúj¬g$KO†GÞòׯϼƒóÂAp#§ð†qbÖ" e°Tb°7ÏÐF¬ÌÞ¦Kõ}“¡Â*u ×9q%šF:ö4ïyÀìÝ`Ìü°X,âæ]}Û6>߸†Rs‰äÌ%&s÷ÝüfÆ R–EXö¡òhÃd\Ëbó›ßÄ<öÁ›­ÿéÀŸ ¹‡!ýæ |ë0xG ?¼'Á™þ4(ú@zZùù7¡Ù€Ô· ˜ .ð‚ßf²9hù&¸¯ç$ð^ Þùù;Á»¼ƒýë@ÑÁÿ8—·/‚Ìw ;Š+Á;þÉr¡hÙ‰ÿo øKÁxüIA?’ßv‚-®…ðÿ Œoýó^V3dŸã´,®s=Ñ„QÿSÐô7úä|«âf‚gÍo˜ß!¸ÿm*c¨þ˜ ܤÀ} ¬»À»¼y`ÿ'¸?„ÄBhù°ÊÆŸ†X-—­´ýd`mž|!ê–ؾ æ/‚¶†.•Å:Y”Ê.°ý7ׂñ±rû$½ Þ‚7 ¼X ÖÜ Ûþ§0¤Œ"ø¿…â^°ÆýpÞ öÇË÷©È¶| Þ#`¾¼&0­ò±_§¼úš?¬'ÃiM ¡¡Q?è¹@CCc¸Í“Íàå)AÖúòÎÒ~ ¼ˆ|­ÁàùþØ-5Ï\N¿Â½hh gôJ<®[·Ž3fpÅW°nÝ:|ðÁªéî¹çžA5¤X,2cÆŒââõ…^`íÚµ¬\¹².–œ*\×¥X,R(¢˜.¶MI‰¹&nšLÓ¬ˆ“V*•BË»|>ˆ¢Ý*d™XB@6477“L&C‹½B¡ÀÝ|qæL(“yÛæ¬^À7 º-‚ÖV ”­ ˆÂ }|ëVÖ}6ó®¿ž––\×åÉÝ»ùðCqæ#„~¿xî9–LÊg¾ýmžþÍoXñÁrÝu×qï¶mຜuÝu†Á>ü;wrtýzž_°€–åËCOd"}†`?.ŠÍ©TJäìè!¶nÙÜOå4~.ÇÁë¯gêÔ©äËý‘ðLŠÒt($M–?­r$“< ôòF³r=mÀ—x0¦ o|#Ü|sxΡ>+ffþÕWÃÕO:Õ“DV3R§8+V`ÛËùY¼˜€;mÆ•WòʪU¸ÿû¿¼òº×1ùî»éš=›V"OmÞ¼y¼­£ƒŸ66²lêÔº>µp"ç€mÛ¶qÓM7qÅW„nŽ÷8os÷¼åÆÀŒàyõ<¯Bø,®N0þJ¶‹ëTQ 0M3 :-xE‚8¨þ«,Ѧ—9CЛ¥ôHƒ&{ÆM7ÝÄÞ½{9÷ÜsëÝ”ªŠ5ÁŒ3·vñƒÛq˜ºt)ÅO}Š%³–°è|Ý;™MÙT' Þeå ŒYÁ³Ö\Žçjù~ø§Cj”ç÷wS #¬S‰ÖéK‚ç°ƒÀ;qöæ²ñìR`G°Ì-Ý…Íå5¶ öÎ@I 8)Zï'¾”ow îE·uC¤¬®LfAã†à«¬‡}À^XNÓ……à•_ùv'x3ÁÉ»‚<`¥ÊsÖ7ݰá¸×‚? R'ƒ9 ¡4Ø-Wy(}ÜÛÁzœ×¯€ýYðÇCi)$K`œ ùÛ£{Îþ*´ü-d¿œùWÀ¾¼O‚ÓÆ^ð—–ûôN°Ÿî^ž«òÃ<òŽf@¬ž¿º>¡VzÉÞüèG?bÓ¦M¬Y³¦ªSCc¬@ïŽÃþ@Cc„CäþÛ¶m«wSª¢2ÃÚð9c×El]¨ì²-‚âžòo‰½ÇúWgTA`<¤eWÃk×®¥­­mÐk‚šÄcWW7Þx#›6mâ–[náŠ+®`ûöí´µµqË-·°}ûv|ðA–,Y2h2¯­­uëÖ°@¯³gÏæšk®©›PEFÏóBR1“ÉqÛ€É;vp8II/Ä„›W¡Åb‘Ë?øAZÛÛqÊ…žiblÞLñoÄ÷ýÐjÊ0 R…B¸ùv„í€mPŽ[ò!€ŽÖÒTz^*,\ˆyìe®l%u~«‰B*ç7®º ø`œuþYgA¹|ˆ y€yó0®½6 …ÔR>/‚Á¬Ò–Èk$Ü[wóÍ<]®ß0MÞ?uj¨ð›%\JØ&˜&‰Â5¹J…rzR¶P)°AH Iˆ2n9"kB.ztHúT’f•óêxuôipÕU”Ãi‘,÷¡âwc#MÀ©§ŸÞŸ[xHp¢ç€³Î:«ûFâ$8íÅWYüÒâê^µT*qÌÊîÜÄmn2™ -›!XHe³ÙÐQ '{‹Ñ¤Bµ”„HaAclâž{î¡­­¶¶¶z7¥†ËšÀÃëÑýbó÷üô$2À­ ü([äöìã³§ÏŽLÿòÀÊ™v¼päE±ìsÀŸ¸Í•¥ü2ß»€d¥Ä"Ñ»QBÊ;Ã!°„rdCôNö‰û³ñhÀ$Sn^–ˆpéOœÍªÞ½rÚ$ahÇàNdÖBdÔ#Ê@)BŽPþ]6æ ‡+[Î+ïjá\me8m¥.yÿJyÒNh<{œ}3^z•ËW\NÃ5(×·:¥>Ùr[òTzAÍÆ~«Ç“5ŽWK/DrêzDm»„•TQ+`-Z²„{µk×ö#×ÐáDÏsæÌ ×ãcdzÓ<’‹W‚O6MäùÜU?æo?z.üÓÜ7ý o€La6w^þlhxX²h´ƒØ¦öøéW›yü-Óhy¼=\xBÈ'g)÷É­å{à(Ä.²Ü§jøO{VDÀ«÷±x\öÀ‹pÈ,¬ìbµ{"E=ˆÂ™¦(Ï;e‹ÔD`qÔž²xxŸŠñ°O@ÜÑ­¹}‚}‰Ì†’O”*Â˰: kš&š[ ;+2r”«(eº7¡rXF·–7Ï ÊÈ—]ÑŠEŠò37 ²Bã…Ѻ>GຶðVE >PZÍ¿À;šÚbÙžT&hgEs¹{Ið™²7DÆÕ2'7·æ{‚ãí@vB@lš@Áƒdù% ïâ4ð×Μ×B~äv.l¥m¡'gnøÍ7àªO1œ0ûƒ«®ºªîÊÉÃzP?™¡†ÆpÄF¼é¦›êÝ”n¨›Ì°&\Žð–*Ç›1=而]ö&XdΜ9¡ /ŸÏ‡îU‡³71±‹5kÖ—5AMâñ“Ÿü$Û·oçÎ;ïìæYæ›6mâÆo¤««kPhkkcÆŒÜqÇÇ«imÚ´©›&âp×LÌçó‹ÅŠ8}W¬]ËËbÁM7±}âDVw¯Î˜Á÷~ùK^9åÞžLbÙ6°èÑGùÍSOqùÇ?Ž·l6ÑD°’ÉP°gÞâÅœüíoc¶´ðʯ~Å_Ø6+o½•¦X›Äº@„WË3NºøbÖá ´¶·‡Ö âŠM„ v¹®V¢ «Gd•‘àË%²f¢(ˆµ£¤—ŽÖýäbŸâÁÈŠO=Å«ëÖñù¯~ x衇ø³æfRe׬лõ„qÈk .ä«FÛØ=œTc«áŸ¨q¾/ˆ‡Žªöûå“OîciC‡ºÍ/ÃÄ—ŽòÀü¸Úºú„õO4›||Ç¡X,†¾Ý…PL§Ód2:::Â8B}Š÷ÓG טŒ*†Ëš M‡d7Gér“ënýîÚµ‹&<¼Æàm1yçdø‘d~Á‹m ‘ÉPK@#B0—‹Þ¥ê{U W¶1€¥äÒPˆ?Q¼ñ•²Žáab†D i‚µEŽ@P¯*ÃXåršËß… kÃÆò§¼—EÑIHJI_’…¢ÌSPÚ^ÍC©¼SÕ÷Y’Ê÷º:éy÷NÏwÝPA(ºT'kNy¬Ä®œÅ%õ½.eÇICY¯Å‰Ç‘å¨JlJ…*éem¦BÖ‚ñãµ xö–èm.Mçã5=­´\ÈO…ŒŸùqßûû•\{ë¥|þu¿Ç3ÏåѬ ” Æ¿©ü`¶Îòò}ºÜu`®®ó›f£aË’oXTQM¯×n¯ñLì{VjµbéÜ_‰ú,$k|‡êäg¼­âñ´¥‡¼ñsáêçPùvÔÈ'×C%7óD„eaÞ¤îû™jc% £’/G4?ÈœYQp’§Û˜M)¿’æWÍÀ©[· W'ÃeM ¡¡Q_è¹@CCc8ͲOî"p³jøLë„Ù.,ôIË+Ï `š¤Hñþx?é_¦éè车R)-§ÓÕ¨J<Š5ãš5kz ¼*ÖŽŸüä' uõêÕÝ4‹ÚÚÚ¸òÊ+ÉAÎoܸ±b²hkk«{èt:]K ’Aâ æóyZ[[±m›ûwìàÞ xzÿ~8çöS.^r GÒµ8Pþ#GBí^cÙ2X¶ŒõDdŸh{DÖ"lºëmocüÁƒìO§1€ æ:Ù¤KÌ@u³›Ø°6lÀ6Œ íiè.ìS…Tª•E\xÿm)y 2\Ò@¡ hLÓdK6‹ýÕ¯päùçûí:r¬L÷/.\Xï&tCÝæ£°è÷sÿÕ÷s5'ŽxT!.O}ß'ŸÏã8­­­a,TYxOÒQCc¤`¸¬ ||Zií1¾BÇŒ½<>g¦câÊ+gÁ E|w—ᦀ©„Œ™K¤‘»R¨|gæ!ô VCY㈵ (÷ˆ;S)Sñ–¯ZD ©(õŠ¢(I½²öPß½B$&©\kHÙ"0ÄÝÉØ¹8Y‡ÑCYqØà 2¥‰Ü· ‰+ý÷ë²F"XE !cÅý«êfÖ¤ÒÍ«|ªäAII¯*Y Q™§’˜t”ß¾Òߕĩ©”#m«6>bÝ·^´bž4l¾‡èm.8Þó@hÝ\ÅÌÔû)¯‡ù×~›_yßXÉuoþ*?¿|*ð‰¿žZß:D.JÃÙã†Êuñ_ýøÇÁ}¸hõÀ`:‰5`½0Е‘I@0^‹Éøªª½#®ìÐ_ôU) Úî%Óü=ÁHÃpYhhhÔz.ÐÐÐNó€¬$ç¼r*û˵`v'<ïÀ~/p±új”ÞÄäÓïÿ4¼?:–Éd4é¨1êQ“xúàÏ®¼òJî¸ãÚÚÚì–`Á‚,X° ÛqU¨ íY·nW^y% Ü}÷Ý444på•WÖmK¥Åb‘\.‡aa|Ål6N ¹\϶i¼ùóCÁ–X#ˆ‹ä„ 4¥Ó`š\™É„›Ã¸æ|ZR­þR“'cNžL‘@ÐfÓ»€Á²,ŠÅ∎ñfšfè®èæ;[#€ ì®w#ª ÞóÀñ~á;ŽƒaX–…ïû«Õ2äYËf³´´´„£öí®¡Qÿ¹@àö$˜v°mî9u§½õZ.,3@n9–£{9„{Ðî¸ò»{j@.evMyªYŠËÀ‰%qÅ¢]â)ªÖ1‚j‚j%lc7KÕ'KD<а?+SòJ—⫈vê§ÔcÎG¿…ø Å‘—¢à%$ :ÖªGˆˆEQSÉ_qYTÆ@uû裸@¤’–øB`Š×Š"KJ5æt»’Ï °>U­L… Eµ"rÕ¦®XÁ_>öX®Rmôe.8ó€Sý´üawvrÛÃs¨_Pˆ¶³•â°\—ŽÖV ™LŸ7—q¡bÜ-h_5sUÒn$Büb{ž~דxwŒt¡Åñž:§Á³<Ë‚å® Çq0M3¼ …é²cD‰¯˜J¥p§›ÅtU¸.Œ”ûÙóÀ0‚ „¡XÔŠïÈ×â±éå·qÕÖË#&hW,]†@BßÅÜÍ–gÃ:ˆ¸1”cê;=þDÅ”ä{ÞæýuñÝ_K§zÎ&ÀäÈËC¢üo‘¸B䥈â\ª.á‹D1ÚÄÂ4K@úI>q;/á;Å*TÈ qUï¹K´ÈN!*3D®OóDîuå8¤ãÙ±ã2Ö­åvFª.œ,ŸEä‚€ü€Sæ+þGŽ×<`ªt}™©õ·Aé"xê- ï\¼‘]7¼™ÿ¹è‹Þ€ûæ7‡1HûkIfÛ6Þ&54††£œ@CCcè1æÕ£ˆ††ÆñÇPÎ' ¾œì>  ä8)ØZ¬HÛÙÙz9+ Z^­1&P•x\¹r%wß}7Û·o¯Ð&¨¦] Ö‘ÇÛgúSO=ÕíXCC÷Þ{oHŒ.]º´n ˆl6K>ˆ”Þxýõ8Žƒçy¬úÑxèÊ+±îº‹'¨$kM/–eaxÞqÔõ×%ÏHŸø àX,bÛ6®ëŽøþœ( GW«Õ04ó€ÏsÓžcÕ¬óŽkÛUb>Ÿ~§àýï?ß›ýnÌ|ž«~þsãÆ…ÖS!²Y(¡P€dòùà˜ŠÎΈØó{žä5E~^¹›ž5kx:+‹tttô»> ‘†ªÄãÒ¥KX·nk֬鱀uëÖT5w>Q8Ñ–•½¡X,R,) Ì]¹’ÔÙgóø;ßI×?ÈŒË/Ç"X´Ó hÓ4ëâãy´t–e…îo}ß'•l4”чѲà<~ó€ ¬:îÀ/ÏžŸý ùÀEñj.G‰+,à ß½L“«æÌaâ%—T·d´¬€,‚0•ŠˆÁ¸5¡i‹ljHºx™©TDpºn@˜©pœ€ÐªÚ<”Éyq+iÛŽH-i« Ï‹ˆ:!ÀªAHG!RUâÑ4+IBÏëN QhY•í­zùÝ(O5"Vú™Ïd¯Š²òIا8áW*E„a­¾šfD°Êïøuinú\ËŠ4›­$€kYѨùG¸…»Š±&P‰ˆìS`_mæ?÷ןcöŸ¼€_ÿ*˜ã#µå9`L Ò‰õZ5ä‰ÜlÚ±!ap±ÄŽ'Fê{£Z¬i‹ˆä+R+QGõ)+Bu d&ð”´b…XPÒ ï¬Æs„HhÔ+·@$8—¯“QËøÛBbrJ{Ôò›©Œ 7Ü1˜y ›[å²Ï\osðó¿ß5ƒGš&ÐΛ1€·­[ÇÆûïçêÅ‹aÄ£††ÆñG½åÃÃe.pïâ)CÜã;Dq¹E)Nö¢X–'Zk é(îü%fy<Œ€¨ÚŠ’œ(¯å‰b©[JÞ¤R‡E¤œ'J(ÖÉzR]çjh w Å<ðÚ®×âoña&°b$Ç#×Vîæ[[[ñ<˲H&‡ËN_CãÄ¢*ñØÐÐÀ-·ÜÂÝwßÍ‚ jÆz\·nwß}7«W¯Râ±ÞÈçó¤R)¼T ^Þ”`ñ±c,?ž¢¸?ý…eYu‰M8ZÚær¹Dé1+OôˆtÇœö£pÁ3 £gÄý6Êé‹åróD„h‰Hq­UI#Ä£­œËjœr—ˆŒSÝ÷@¥¢žxéPׯ’^ÂSÕÂP[mÆû1š%¸§ôJvàØ¿?L‡“g0Üü ÆãK†A9ÊRx³;ŽC"‘ “Éà8†aô-ä’†ÆÇIµN¤R)6mÚÄwÜÁƒ>X¬µ­­¶¶66mÚÄ’%KzµŠ-p]—ææf¾ñœÿÉOr‘ziêT~Iô"è Ê¶íº’€öN«D£¶v¬ç.(Ë6:±çÓýîÄf6X˜µ·‡¤Ûánà‰·½iS¦°Û0(Þxc˜mÞ¼y}+ß¶»»ÔÔ›%Š!# Ý, vsá¾üGþ¿‰·c>—o4ùÞ4Á‹íÞJtå˜!r‹‰rLM3\0ÜÚs¼aC¯ê54°‰BŒjô ¯2ÆcȯÎ9ÂÒvñ Ϊº®×Ä£†††††ÆØƒ¸6wú²®÷§Bª>h„(o¢Ð$–‹²ë7½ü2ßzñE®¯"7ïyå(æó¼cÊþýýïçðáÃüóSO1ýÈNݺ•)b,^Ì©çœÃ¡¹sÙöòË|üx¶~ï{|þ-oárß§cæLþùÐ!ÜóϧáèQn~æ~qð ù /äò{ïÅY¿ž¿½òJ¾8c‹<ÇW¬ }Ú4vNÊÅGŽpî¾}<0> Ÿ~š­çœÃÔC‡xݯMãž=|çÚkY¶~=«~ücv͟Ϻ›oæ›;vpÚI'±mÂvŸ|2g<ñ‡§Mã‘ÿüOÖ¯YñcÇøÀ—¿ÌžY³Ø5>»Ï<“=³fqÞc±mÑ".þßÿåO/Æq¶”]h¶•Ã,\¸gfÍâÂGÁ*[—†A xä y[Ù‹ÑSÏ?OÖ-\qÚi|öÒKI?ó Ë;;Ù9u*§¼îuüÉôé,êêâ£O>Éô#G˜wð û'Nä©_ýŠd2‰çyü¬«‹3Ï<“Û7ãØ67?ý4«V­âS;vpÑÖ­Ì;x0¼vû'Nä]»X}ê©L<ï<žØ¹“‡N?UÏ?Ï×Ï9‡S§òÉÇçòÙ³ñ<×uyûêÕ¼~áB|ß§T*áy†a0yî\–ΟaX–ÅW^z‰Îöv.}ùe zž‡ót´qÇò7ÜÀÆ;øÈæÍxž‡išÝBU½øâ‹õ~Ô†5~ÿûßÃr°·Û0¥|pJ'œkV•ßX–E&“Á4MlÛÖû1ƒšÄcCC÷Üswß}7ëÖ­£­­»ï¾;<¿`Án¹å–1C:zžGSSé|ž–Ûoç;Dšò™òÿq‹©T+½‘N8jôšÂèŽ_x¿èý¹¢Qž•D"ŠË×ÒB¶XÄ4MR©_øÉOð}Çqð}ŸÎ¸‹Î¾B“çuƒX@9ËÁú àºüùO~‚Ygp„òz蜲K"%( º…(U”¹V­³q¸a$´q°1oD˜ÐW…)×uñ}?\»ILauÛSIÙlÛ¶ÃüÏ>ûlG ¾ðñ1: ˜8½Þðáûøí9Müð5wwÙkY8jì^ 1‡ÀªP\â[„úJäˆ\ÝË:ÌZ|Ã0ðË¡DÚ6o¦á 5a®ë’I&IçóázÎqîî,Ë'ürþ¸g4Û¶Ãõˆ(Q»óN^÷º×ñ×=J–e‘ýæ7q%\‰móÝ–~óÅ/²¢½G¾ó&|ýëÜ·e œ>³.ºˆ¯ÿö·$“I.ž?Ÿ7âyk0 Öß|s@€Í˜Á–Õ«Ù}Ùe,.•øÃ{ރͲcî\6Ür ¿:ùdæ?ðÞ¹ç²ëæ›YúÀLݹ“®Geç³ÏrdÁΟ=›GW¬`Á¥—2uçN¦>Ì·®¿žƒóæqhêT¦” ¼­çœÃüÍ›ùög|{ËŽ–½M~é%O›Àžƒ9ÿñÇyøOÿ”Å"ßxôQ^X³† &0ãé§¹Ó496s& ûöqäê«i™:•c3g’7Žc‘¼§Xä“'sÛ»ÞÅ‘éÓ£_µŠl6Ë̳ÏfO:0k›xÁ™>äFÓ¦ÁßÈÂuëØûÁrtÙ2¦~úÓì^½š{ºº8ÚÐÓ§ƒa°náBNþÑ8ðì³|(™Ça\"Á¤Å‹ÉN›Æ”;ïäÐ/ÉÌ·½ñÍÍ4lÙBçòå¼òÊ+¼ôðÃQxÛfâÙgó÷ÿð¼´cGxlòwpÊïÏô#GøÃÅ3qñb&<ú(,[ÆŸù ‹&Là¹GaÒûÞÚ® ŽÃ¹øC½·aýÿeö»llÃÆÙé`~:I·ª·)y¾=Ï#NÓÞÞÞ¯ú44F*Nê-Á-·ÜÂ-·ÜÂöíÛÙ¾};Žcɵ*@©TbÙe—qöí·ã,8ZõXihôÚú¡;.ò.ê=Q±XI<ær• Ç ÇÉdß÷) uq¬¡¡18t³€Ú üy3¯Á©ü~?ëÀi05 SŠ¿ $Qœ—@ð ñXÄÊq¬Ú2Ç5iëÞ3ÐHíK‹Ä%N_Úïº.Åb1Ôj…€ìË•…#¾ï“H$hmmÅ0 Ç!NcYVèr?ŸÏÓ¢¸¦Îf³$“É@x”Íâ8˜¦I¾,¬j-»Îf³¡"L5ˆbŒ[¶lá©§ž6ñêë_,ø$àB>ïþïõ¾ñÚ]P–0•ÈRi\à—•ÊÇsë}Q&L†ïS,!“áã_ÿ:?9z”ñ]ĬòúÎó<&lÝJÛáܶk Å+’ã8áº-—Ë…ëCÖžçQ(Ó÷C+6I«¢–%Uøñ‘#<4q"Gž>X;~ô£˜wÝExüÀ~\tÎ9Üý¥/õß8¡LJH‰SY¸új\7­7”ûØzõÕY…Ð]µj«ˆ"Y8VÞÔ©a,ËÔâÅËÙeËh)~Ú´0\1u*É+‚Ø”ùpåý×òå4¹+ð ÜÑfæLH&Im›7³²l•–%ÚÃIÌ¿þìgiœ81t3[œ>=ˆ§iš¡[]h^½cõj<`AŒO¿¡(FØÏÖ«®Ê®tËmðgÎäè /ð“w¿›Î|€É“'1A—/gQ¹-ÞâÅá>& ¤,ÀûÇdrùžñꫬ?wéRLàåv%çÏîéB€7ɶ}Û¦˜É0û›ßг3V°aÖ¬à‹ Ø`ϳƒ›##¡‡¨p­c¦iây™LfØì‰54N4z%c‰l"A– žåó<Ì#/‡Ñ öرcõn‚Æ¢V,‚±YLW5ØjÁ¶·ª¾¸Nˆ-ÄÇÁ²,ŠÅ"Åb1Ô`Ò ‘û'6\üödž“¸l“ÇVî¢xÎÕb€ˆV‹È•ª¬êIWØ=8ƒWÉ(s0Žþ‰q2m0Ë@ÉŸææf’Éd(é¶öËfI¥RáQbrTë¯çy”J%LÓ OÇÁ4M2™Lø^Èd2#ÇqH&“¸®K*• ë7Jò^Éf³”J¥øÌd2!‰éy^xÍš››) xžÆ#Wû#}‘rD1¦³³“óÎ;ï¸\—‘‡Ì–à)u¾[÷±1çÀÌ“Oî–^®“~¿khhhhhŒNËŸ²ž—˜ˆ9"kFU½Ë(+•yž–Å;wòºD‚í|­¥×uƒµ]Cβeܰl™k®¡±±1\³e2•QÁwè pÊVZ÷~â@%Iù£òšçx­ÕM"eKY1ùT—AÉîCöT•ñãyäœû­B Ez:nñtæâÅÝ꤀TyãiÔ´6QlÌÖ*u¨V±‚nÊ©³góñØ!¹Kªí€ºõyüøniԻ̦úõ0€¯–ÉPîððhó`ì`Ù¹²üþÌž=ä=é4“&M ;·´p a€÷~øÃcžt„(>¹çžÛ{bË étÕÓ"ˆ4 £Û¦ACCcdÁÅÅú½gyzÕ+9egŽ»,x鴗´^ùß¡2–‹Ì6Ñp¸Ï»Žã„n`)jÇ­V×KÕ nªÄh_Q,inn®™ßqœŠú³Ù,‰D¢Oeû¾O&“ „@À’C‡BÁZ~SSS((jmm >ÇqÂôÙl6´PL§Óø¾çyär¹P˜#±<ššš(‹$ R©®ë’ÍfC"0›Í†ÖŒ©TŠæææÐ­jkk+¾ïÓÔÔDss3¥R‰t:’šRO>ŸÇ²,:::ÂkÙØØöKÈÑb±–1uêÔãrÿŒd˜¿4ƒøv8åà+›9“ªŽ  GÁAËš4444†7$†cžÀÎ# „Z‰¸×u™5kÍÍÍÌš5‹¦¦¦pýµ|ùr®úä'¹ä’KHÚ6Éd’\.W!#°ä¶mW¸Ï?ÑPÅ«uÊÊæD·¢7Gõÿ²7ô¤)0ûxüDFÚ³¨N:=õ½¿õÔZÑf€y›6¡—,Õq¯ŒFÒG€IDATÿzðC=¶‡¦H`ª@öÆ:¾£ÆXBŸ-ÇJ¥R¨Inçr˱'&C$@ÔÓ„ÆHƤêÝ„a-ôà5Ÿ,S)(”uÏ’Éî ‚G2™Äq²Ù,õ†Æáà```ÝoÁ /´‹{Ö¾—Ë>öGf39ã­g: ÅÉAÊ}…hꦨïz! °7i¦n†r=¤w]·[zÙl–Byþë:Õ²0NWœW×_¦iR*•ÂòK¥¥R)°R,Ÿonn­ãnP›šš°m;,"bÕ4M²Ù,™L†ƒrèðar¹ét:lg&“ ‰;qeZ*•B0™L†D¨ïû´··cš&_ü!Ž]mÛ‹E<Ï ß Åb‘ŸüälÛ&•Jqß}?çÑG%›ÍÒÙÙ‰mÛüçîaÉ’ƒ¸®E¡ÐÉ7¾h¤[–EW×^zi1--oL¾ñm,Z4Û>σT*I©§Åb×uiii ^*¤¾ï3K\a˜ž x§ÃÜ­;H|ÿ;XÿxÕ´"(Ôày™ÖW>ÖuƒôeOLj¡±,¯Ê!°è‹LFBmöt9ÄQ…ïé'^ »@öƒeãDí÷ýh©—ÏKÀR)j¯içEGÁ4#"Q nYAR¦Ô!íM&ƒ´¹\P¾ëmL¥¢¾47WŽ«aùÄùF.|WÇݶƒ:¤ÒnÏ‹ê>ËyIŸÉÀË/ŸŒ†††ÆX‡X݉«Uõõ&$$^¶iš |ß-E ®š‡)«\¾G¶mS*•†d]!u†ñ)•ÈPxc±é™x”óZÖZÀÊo~ã-o©wS†%~‹Ç«ãü0 dzÒA€ÂÜš¦‰iš¡G›Z0õ 1Ê ‰Ç*ð<Çqøì…²cñb¾ú*[Ç'Éð·VÐÐÐè;ö•W¿?å÷ÝO–JFuq"¨\×Åu]r¹\‹¡,=ƒhh {¸¸á³ê?;tôh@XÍ6Yd-‚¹•ô<ѨÆr¬·í³‰}…¬ú*üð<¯Âª±X,V¸…’߆aašfèŽ:™ÌàûQD0C‹Æ_üâ9>ýéoá8Ÿÿüÿãߘ@C¬X±‚åËñìaæÌ™üèG?âÖ[ÿ+®ØÆYgL˜ÐÅäÉóùÓ?}œùóç3{öÇyòɃ¡þMoÚÉûߟgÊ”wpà M\sÍ|ó›ße´íîÿ-Y:ŸïwÜq€;Éã/âÌ3“¬]û ^}5ËË/ŸÌ·¾u'‰ÄMMMU­ð~Õ P(°víÚ:ß©õƒ¯Jà]Ï=³‰5³g×ÌcYVOs0ð¼à: qÁ5‚KÈ!ÛÂLË9•pJ&ƒe‰xvޤ1 ÀuñM‹R)ª·TŠÊwÝ`‰SÌub4Î ët݈ز¬Àéƒemhj ¾K(ëÜí¿s2Lž\¡§ešàÞ¿ƒÌiÿ—")J?ŸnyÒ/æaL9ˆ·gVHØ•JÀÁƒdÞùéb庩£Ä€·µ5"çr«çóA¿’ÉJG¦ k–Áã<Î/“q2~ÒÃÊM¥*ÉQ!ï„Lôý SËŠÆÛó‚kdÁXù»c̶/™„DòŸ}™Ìm‡0ÍJ¥èšCP¿–r½Äù€±;É䂊e©ôÙ4{ïÅxòIJ sæLùe™*×_Ê ®íªãò\ihhhŒda_ g³YŠÅbH2Šò\­2 wù¡mÛC¦Ì$m1Ó¶«†+*RCc$ãpü€ë 0UvãEN˜L&5ñ¨1¦ ‰Çœò.ýþ;ø¹mà 7ð7VÒš2ÐÐ8ï’Xl+‘.µ´TªÜ›f(ÕÊ–µšr¹\èVÏ0Œc1u즡¡Ñ„Ä£®¹˜N‰·!±¡›p@âÆK܈öõÞ6ÈGê²ÇÙ¿ü#àºÉ(D„eYe •V4bü-ð|®¼r?çŸÿ_|âÛ8zÔ¶ƒùpÛ¶ËY¿þ,–,9ÄâÅÏÒÒ2•»ï†9sðº×}ÇyÙ,œuÖYÀ1{l?7Þø*‹OdÑ¢ïñ“Ÿ,#‘€É“ï`Þ¼pÖYO°mÛþîï0gÎLž~'°“—^ú$ï|ç6<¯ÈÁƒó€)<øNœÂŽÏ0þÕ˜f‰3ÏÜïÏá—¿œÊêÕw3cÆBþïÿÝÎüù‡in~?‰Å³øçŸ.dÇŽILŸW]5Ï».œú¯¾ú\vî|•Db"¶=yóÀqÎ ÓœÃßÿýÿò¥/½Û†ÎN(•&”‰£–.…]»àoÿ6x…tt„N.ýÂÂI‹ŽŽˆÄ0k®‰^E¾?ÁóBSˆ0¹á†_òoL#Ž,±âr¿üå:ߨu„«z>p¡ãÏ:8ðøã$ûWÉó"«1Ï‹,ÊD麑•Ÿß¶9°†›¼8¼Òiyþ¢OY†8÷v‘¼ðIò?m"µl=ż׊ãË÷]ä¿97lKæüûpO};ö;§ây–œöÆŽø“7âžòÌ³Ž’)7”·þùÙX¸ØÙ49¼yo¦FóÀ}÷Á¡CX¿x€‚÷Ù÷aš×ÒÞ^¶¬Ûð%(0¾äccâc`eZC«ÁÒ·“Üñmس…ÌΫɽñÌä§!Ûˆuù÷à µç£,@*(‹gÿïÍ´¯˜µå»x¼ãßÂ0ÂÑø×/`9]t%(äpŒdd%é8dýïÕ…‡èØðnüWg„$b0+zH«TŠˆ¹÷}(z´¯X„•û<2¾¯<8I ¹ˆéµm‚Ï*O’¾ ©©”Ì™®Cò~a2íYloñöñc–ïƒgãY‘;{ó ä^þ+ì÷ŸÜ¶ v.²îlþkRžGJØÚT ìà-dY€ó]x·I*?2­`ÙXn1¸Ù}HB.¸×‹Exä‘©ÎhhhhŒM¸t φïûäóyZ[[»yÙˆCö.݉¼xøÓ4{,ǾÀ²¬Š>È«åD»íÉâQêÖĤƈƒãTZ;VA½žu zC1¸® íí<àºLÛ¼™cgŸ=eŠÞ‚ihŒBì&©Af2=úù2M“t:ºXÍõ²ÐÐÐÐðñMðá÷Àr¶ŸqF`ñhs‚ê:ɦ»+¥¡V1yyÙ ihå·{÷…üîwSH¡oƒëÿÞ{:¬_”Çw°yóü²å’I>oVXU‰ÛCäî^øY&Mú$Åât&Onäu¯›Î[ß'sç~Š—^z Ë‚Bá%úO¾ô¥rß}ÿÆ?üÃùœ~ú~ñ‹oÓÞ~+ÿßÿ÷Slû·üٟٻ7‰ëþ=ßøÆï8ùä/ðì³Ï2~üj~ô£Õ‹y c;6ìáöÛÿ?Þõ®›9pà|>ÿù¯òùÏžD"mÛd2 ËVž`Y“in¾Ÿ7¼a1þðfÍ \a%“ ÉdŽã1ÍÀŨmO Dz»Òù ¿l»{šgžY]ñ[ö”’NM/c[ë7t'ÕW‘SÕ`„dJ”w.†¹Y+9ÕBn ‚³dÍ·M Émç»SüŸ«(Üô+ “þ5h¬• î#¯‹Â¢µå»VÏ3ˆùÊFŒ'ËZK0?m‘4·´B–ãß_¼(σžžoi¼àšŒYÞvv’ ­->»9Ìð¹ø*¦ï‡«íæágkaBټ϶±ÕI·T \ãy¿Ú2î™è!7Ü<,¯qaËþN­¸¥¸°Ç®L„™L僛ËEq©´Ë0‚g̶#â‚ëJ…&¨ÉËß{T©rÛløÈj(ýedf©¢PˆÌ9 …èÈdPnK…ic&Ž •‚Gé÷“£¡¡¡1êàólRV<‘˜Ý½Á 6Áf*iF`(`¼«ûÚ—£ŸÇ54†<<ž9äÁ”òææà³Æ­T*‘.¯×4ñ¨1¡‰ÇÖ v|^ÙŸÐ]Ÿù æ”)ƒ,UCCcØÁ‡_Mr˜vðMÝÏU“ÇN§ÉåraÌ/ Ñsƒ Y8š ÖG¦OÇuÝn.+Mâ1Ïñ×ÎU­…4òýÈýa&ɰå`2 ¾ÊÖ­ãéèÈË.»œ¹s7ñ¥/ÊÌ;_W_ ¹wÁWÌáСvÚÛçsóÍGùä'ÏgÞ¼-¼ûÝ‹H$ «ë^V¯îä_ÿõfšš`ÕªsÉ%Èåà¿þk?[·ºÜu×gøîw;ذáKtv¶³cÇ l{¶}®û&`=v!ñ®¹f>ÍÍüô§­ÆÛÉçá‡ç}Žë¯ÏqÁSp‡bñÏ0Œ ÃÀó<¾öµhNþÞ÷¾^áÖ:“É„±U-ôd2I"‘ ¥¥¥L:Fñ!G# £v¬;õx_cñX/YàÃ×~I§¾·Õ ÝûwPüÔì-ÿJöÀ?šûMÌüµ;VNïuBþ'ÐáQx÷ARgLÇJštTL+ kc¹ŸƒóËê ˜f@>Ê$™Ä´íT²¨TrÈäg·FlhcÄ3%“³Éù`oÞн¾8G¦§Ñq«s^­\£"F5m ÙiZÄw}'쪡šFAµóâ›5¾FL¥*ÝkÅ!é]·ò¸2¶®¹ˆ…À²Ó²®†¼ºö˜Ä5 ª!~=óô> º†††ÆØCÜEªã8¡§£LoïÃX^è¾?0©o(yW#@ N,ù·ö¬½DÕÎðñqp8rLY[z^kÈb±ˆeY´ôeÍ6†¡*;kŒ.Œ¯w†~}Ê),|úipV=ÿ<ž3§ÞMÒÐÐ8ðžðøÕÉy.~øúÈ͈ïG¡{A.—ÃuÝPRCCctÀÃÃxÅ Ží|=“ü@àbIÕ ¶ˆ´†mG<ºn@J\°D" Óé žY"(S65Ó”Äþ*ÙsGG ¤^¾¼B¡ˆi¿7oþ(O=õ'$“œ9•ò8ç¸ùæ ßúõ¯çÚkÁu‹|ùË?ãG?ú+>ñ‰‹1 øò—å…ÞžðV >ýé_rå•…ÖÞ¿úÕçØµk3Éd’t:Íòå3à Uss3‰D‚R9øXSSS™Œ´Cw®†a`¹\.Œýë§L&–•J¥ºY”Ç]ÕÖŽÝÅ8†aÐÒÒB6› ‰I 8Œç páb×¢E‘Э|ÏÈóÙtí|üŽbÿóÿ¡³Ã'÷‘]gÏŒ 2Í€ôjmÅøÊ§°o_^y^MW r_« ûCÐÕ¨bE _H þ"NZnØ0ðº%Àå@JE¦äb†ƒèSxe/¬'äºie9 šð‰2ß÷I§Ód2,Ëê³e¢´…`PaÖ8>TýK5ä8±Î¶{ãl´Õ£Æð†‹‹‡Ç+ª —IJ¨Ù×£j1^ªÃ !%hãT¦—¨£*e¬B[<*p]—“'sÃôélM$ø[½1Óеp\f¿`qÁ–k0–?¼ ÒéàmØ‹PÉq|ß'™L’ÉdÆÄ"BCc,À'Ð^´VXÐ×dÁS/ÐqÉÙ,üîw+Òhƒþ“Ž®‰--ÙÁ1ß zÄ•a2Úˆ1ïÃ>°—3^Ä4WŽž÷(ù|žT*p£øOÿt¾MXo:fýç׳ÿ‚ýøG|Z[[q]×uI¥R J¥¾ï³lÙY´··ÓØØH*•Â÷}LÓ¬ºØ¶išd³Ù”miiÁu]|ßDz, ࣣ£ÂÊ0NVæXÇÁ,OÚÔÚÚŠß«'1 ܼ S¦B¯b?Åhm!ÑlcÛÁošŠÅ`-ºA ¶Y„ט'®L<õÚëˆ÷P«6×s½&}­¡à&÷œ áD6Ü[ÚäYCCC£&\"‚¬¹¹9T’ó}¿_{þÁ*%ž(ô$å8ÑN màX/i´TEc¸ÃÅ¥k¢rÀ0zÜ$ Z[[‹kãl¶w''ªS–8$Þ½ …ëRý†è·ãßey<Òˆ¹ž,4«õ†¯E§ãTÞSªç­ãM<*øëÏ}ŽÙ_ù +çÎen&S7Ÿç'î"— ˜ëºÖ‰BNš¦‰eY455ÑÞÞÐÍ"1Nöŵi!îñ8B¬+54âgþæ&H¥0^}ëãÇÏIœõ{’îì½zò<Ô"ÃOtü1¥«‡Z±h]˜f0¨Cë&™„sŸú~ÇQc>jl„ÎÎàûq߆ŠA5áXzž‡ã8t”5Bô:òÄäw«H ºb x†³ƒ½í,ìu]WÀí‰JgegBÇm(aÉƼ<¯çèžWIºneú8±(¿¥þM<ÆÉµÞ ’¬îFÆF¬3{"aE™\ÆBík¾ß³ndoçã}ë‰ ŽÃó*C=H8{‹ïÛw/¾8cPc¯]­–áº.}ÿûL=ã lº Ñ444F¼ç<¦4ù©ó7ÜuXÞFÅbQ+&hhŒRXXºó£E¶žõ2“'Oàé… )œê JôD8‹Á"Q\¤¦ÓÁæABªutÓÍ¢EkÃ…¤iön£Æ6ô}OY¥Ë÷|>ZeËfÇq‰^x!ýèGCQÊ÷¥ª;ÔL&C¡P(Fh5hYíííZ£1:Рפ–0áË_&õïÿŽCöºßÃìÙ¤RÇ™tTÑÚZ}W8äï×G]ZÕ¨‡Úo*—^:ôõÆÑÃõ»¢:®õs ªé·T*aYÖ¨ >¡GZc¸Ã?äã•IÇ[Àüsz\O;ŽCcccŸË/aÇŽè·j1(¿û³/‰…qOÿqÄžtãëÓb±Ò‰GܵªˆX†ÑÝõª:½Æ—¨ñ¶Æ Û—¶C@¦õŽSY~ü·ïWþÎ癜OU¾ü ÙSÛÔ¾g³•éã¿ãH§+ÏÇËSIc!Õq··B¨ªyŸ{nJß®4ñXÆÚ{ïà'ꞆƀÿªÏþqg³Ÿýð¼PèQó¾X,†ÖC†aèMˆ†Æ(„‹‹±9ˆ÷ÆOÒ¼tì^žþrxÞ! …n«E»e³Ñ¿l„cÃ>ÃŽmÚô‹~µ1™L†£çyضM6›%Nc™L†\.ÆWÌf³aüDQªºôÒK+ËÖÖVr¹¦ibÛ6Éd’d2YA,Æ…/Z£1Z0ÿÙà>>y÷n27Ü@>ÙNòƒ³ime±õì”Ô=]K°Ð Â¥Æ=;NeüP n°ˆGíÝhè1Ä~44úwQÄœ]ùà•p°çô¢¬[ ñ°ßŽ•2=/"¸d铨âd]\÷,N®©å•J•ËÖøÒÝó*ËW‰IßÈ-9&DœL©¢‡˜ÏGÿq‹Éjä_œøì‰¬Só ©&é'P WÓΚµAÒJ»¥nÇ ê•óÅbÐöR)øO§£~K¼v‰æU­=êØÅïƒøµþú~tßH{¥-ÙlÏ0¢±(*ÒÆR©ò¾“1mj ÈSéÛ¬YÒ?“-[Îb0ÐÄc?|â æ8Pïfhhh œs^˜©hõbjdÅb‘|>¯­54F)||Ìß™ðù`¶yüKœõ ˜qI  šBܦÊB³X ÜSHLÆ\.˜^âº âÆ©¯p]—l6’ŠŸQþ³Ù,†aP*•Âr…PL$áÜåâ’ÉdúG±¿é54F •U>øoà:ÑÆõ„òs5âü L³ÒÿÏP"îsh,AÜÛ¶¶ÖÔŽWµÁûRS||khhhhÔ„K°Þw]Wu€ViÔÖøuôuRä^“çóùP¸âV~ž]]Ñïd²;á¨Xq«¿8âçãVb‘ѾGê¢M%ì‚Ð/Ñy±üR±¥%¨#›Â¹77G2ñ•φ™âѶ+·q Êxz²BtœˆD“þ™fDæ ª’oª§*Ûú#Ä¡¸U•~H…h”m•…B0¶ä•­W©äojªÜ J_ÒéhìÔ¶¥RQŸT²¶©)Rr/ƒÿt:¨/› Ú/}«LùÍi #è[&”ã8A}¦äyê©é,Z´­×{½'è®Êö_r Ö¤Þ'ŽºC&%Sùmù„Ð2A ^á#‚Óë›æ·ëº …Ð%! `RCCcHáö1ÞbÀýA,¬]»vqñÅ3‘àõjRx-½l6XhJŒ.ù¬YŸï÷è®4ŸÏ“ÏçI¥Rär¹ ­IÑÄN•ÙÌR©Z1 <Ï çª¸£ßo íVUc4cÁ¦ç™2eÍÍÑÆë„"Ÿï{ðã ÛŽþëY=,¦]v=Wסß}èo2i"g2ÇùÉý6I_ >Â6lØ =ihhtÃÅëäÉ3&ôš>¾ßåFñ€ÝÝ“>Sþ.–l=…C—4µ¦*!ØT]Cù­Œ¶‘vâÞÕ²‚rK¥ÈÒNÈD!„XsœH¿Mˆ-‰‡($£eE v¢‡'¤f©”)yûÙÏÒÐÐ@[[·ÝvwÞy'W\qLëÖ­cÍš5,X°€µk×rÛm·qo9>ã@ñ¡+€ã`,èÖ(Äš Ì$„äƒÀ‡CŠ€è“ÀQùW*/3þ$•ó¢áH@MàXùX–È*R'ðg–ÏI[¤Ü¦òù\¹^§ü›ò§øun)—/ðÊí·Êùb!n9®â¯Î¥’Í(e¨BÛb9Ÿä1”¶yÊ1Êe±kP,§26;/cè—Ë’w‚¡\i_^o”|¥ò÷¸°Ù/×›T®§´=~¯˜åº’庅œŽ ó*ûI¹LõZ§¨”ˆ{T’ÐñóÃC9,ßb³aüÅöíkPžç±dÉ›8看hoï÷¯ì7âV”òb’æ4Æêµ&p:dÈ@ΦíŸÿãüóÃsê4, ãb1X´õfÙX ÅbÓ4C¦®ëâ8NH6¦ÓiR©®ë’Ïçimm c0Ƶ°S©T®\44F"z› ŽÇ<°·ãÎ|õæÎ 5m‡ Ú}ñØ‚ø‘ª×u¡‚ôzÊ 444†Nô\ðÜ”ÀœÉu]^@Cc˜¢nr›½…“;ß̲í»1ï(êa]•N§9óÌq3TLkBA.WéÊ´X„å_ ¾ ù%1Å¢N­RÈ+Y^ªÖ€âFÕu#ý"Nâ &–p¾‘h™L L&0™ŒHMÛòºnÐF!áTËI!.M3j«*K•ý—Jšf2Q» rmšLcR(m¹¬eEÞ§Òé€xK&ƒüþF,#¥\©£¹9È/ÄžjÙ) ˸þ^*U)£µíÊkœJEÖƒ¹\d¡(¤h:YsJ9*wT#×QHèTªû=!íUÓIY™ жêÞWÈTõ÷?¸¶žùõ^1,ˆÇ®®.ÚÚÚ*&Š•+WÒÖÖÆüãð؃>ÈêÕ«Y½z5wÞyg¨Ý iй;v`Οß{B!“RÖ…B> %7˜?¶D ­ÌI-ãPI«V"bÊ 6YTmŽÒJmoAIÛB@Ë´·½ ˆôZ x&åžm³Bu“šJ¥*¬ …Éd˲ð}?´ºnoo¯êúÉ0 2CΚhhœ8ôe.8óÀŒç8ýÑm´ÿѦ¥ËÇúå0¶ÐÚXº;6ø²‚H<9††Fý1sÁŽÉ“p‡\½Ü¡khhÔD½Ö>>GO:ÊŒ}MLØó`ÄàTA:¦T*qÞyßïf¬ Ú<$™%é6l€¯o…׿X)ãBO?!Є¼RÏó"’Pò‰|LêQ IÃÚ!¤“”#®:¥]ÒN± L§#žÄDY£ôSw¶_ŽJ?Å2ŽHKUnW(Du !šÉDqÛÛ+CÙ‹\³¥%²à“zb•©¢§é?NHJñ4µòˆ¸Fd¢qñM\.*£êoõ¼JVC\~ïÛPˆ†ñ¸}ûvV®\É’%K*Ž/]º44‡Þ´iS˜N°`Á–,YÂÆ¼¡n憻îªuw©ÄY3QLE±H"¨PþGdÝ%iú‚8yÖXd—Úv!³-=ä7úp¾ÚžUÚÛL¥Å¤’ñ¡­6Ô­UÎ ±HzUd«+C¹bõg”ëë­Lu,zy G¥%£„Õ®g5Á–j1SMÑû­Ž¡–Ò^¹îj9B|¶Â¦/oâ*®b8a(çý'… ™¼cGMALDÚ¹\tÑßðÜsS°í)äóÑ ­7ˆËyù|ýë0}iäŸ\Lîeá Gªo•<M™l6øL§#Ü,Dû§µ5ø-éÄÍ€¸Dð¼È5‚´‚·h8A´ˆàÖ¢e#šT©Täo\^èB2ŠßtY45E®TRζ£˜F²pRýÍË¢C4¾’Éh\ĹÔ#}”>‰‹•(nmÒK=¾•+}‘E™@ÚcšÑuPÇNòˆË…|¾r1#÷ƒWªÖ›øè­0!k… –{È0"M)ÑÖ’6ÉXV#œã ×áŠz­ Ü£.V— r­¦~à@4e«1 âÚe}ESS­­­¡E#DñLÓ¤££ƒ¦¦&1M“T*E*•Â÷}JÚ¿³ÆBosÁñš^>™ßN¼€ÉC9/vt@cãV¨À÷ƒÅm×'ΤL¤õ¨»Þ,õp­+¿Yq?]Ãõ”hhh  Õ\`xvYñOCCcx¡nr\<<޾|ówKáŒÇ{\ǦR)’É$®» B–¤’~aÙn$3Í@„¾n¬s¢è"Ëd‚íƒê~³ZC9ßÞÈ£e¿çEeˆ È°l;Ø¢ˆ›W!÷D®¤ˆqB *åM!´„ÀN7NàIÝqÒ®¥¥çº{“ÙÔSw;Þ¶ø˜öö{$`XK–,áž{î©8ÖÕÕÅüãPCaïÞ ˜¥:y̘1ƒM›6õXþË/¿ÌO<ÁŒ3ºMP>0õ—¿¬íÃÝ!r5ÚND"6•W³Ð—¦r.K@p ÅͬšeHû‡Ò½¦XDª.EbY4…Üjd^k¬ÿêCz¼•~…œV‰Ç¡2,´©´T­æö× ^ÔÛ§mg}Ãú!jXßq¢ç€ýû÷ÓÖÖÆ£Keÿ¬£4ì̦M›8å”Sº?ݳ‡ƒÏ=‡¥n¾%N¢Adµ–!xɪ®TåæŽûõ“x}Rä#%˜ì@*¥ûg1±§ÃÒߤåRdö”ÉT Ê–a™¢~P ì4%N7¡É©tZ,m(#s1]RŸZa4dVé-.‰E—Pâ:#ïX{Š"¯S¾–í.±ˆ»¡µ‡°ï•Ävº·oßN[[¢† Ç{8pàmmmì;k“ŽLbÎæ=ÝÞ ¾<<Îý÷ÏbëÖ#tuý7VZ Fðˆ ¡&>Ôs¹ˆ”G;ôÛž„Ùx¸ë+­ÕT â[]‚ Ëã(L¹\å#/Ö‘™LО––ˆ «G! ãÃ(¿å‘V?Õvˆ]Ü'½|i I{…øª¦©¤Ö% q‹ eÅ-ôdÌårÅë…ÊK©ú‚×+䟤ï‰DªvN­§švTÜÝçES¼ðÜÒ>Õ¢UþÕ1Pýö«.x«A,_U_úÒ~Ñ\²õ§?½›ßÿþfÏ>ÌpljZìÙ³§bCâ6ºX§B±xHÏå©Ôó"7Ľ‘ŽŽãÔTfr]Û¶CËÅæææ|Ìçótvvb”˜d2Ir¨|kŒIìÝ»—¶¶¶aK<ÆŸ 6nÜ8¨ò:Ä#¯y„s÷ü l:…Ô׆°3–U˳zîÒ륮+ šz¢žã.’­X6nÜÈöíÛ‡%ñljØñ¸`ÁM<Æ S†²˜÷<Ã00 ¯,E•OÓ41M³"ÆÈ¬ FÂsp"ö›楞\a‰¼i Iç‘y6°Tù_Âôˆ|,E.Ç!’Ý8D2$1VݘVår_)#CvH´#ãž¿ZceÄ,HÝù*uV+C­³Všv¢°FñzD)>Yî‡K#ÛRJ_E–(¡…dŒUBå˜ÈÕ±ÌëVʃS˜–2Õ+WV..L‚C3‘úV nîž÷_ÿõ(O<1‰k¯µ«†FioîEÁ_<{ !™ËÁÛ»àê«aWÌ;˜¸:C‘)‰1”ÙÑÈ—$n¡œây,Ÿ~‹¤xqj‰y>Ô\46nÜȦM›½&VÄãöíÛ¹ãŽ;hkkã–[n!•J—EÏ)§œÂå—_ÞMãà·[·2÷¥—‚Eq–ˆ`¤üY"p_iIóQÒd³‘y’ë–M!Êçššà(pÀƒ±Àb¢B lEq©¾żȶƒ·|+ žoHv÷ )u‹YTµjºЦpÅbäw`°´5Zü´ùtåFW"¼ÆËöIà,BÒªíPgBÇeaK†ðy,¾… VEÍ+æEÒÆ¸Ý¸0L2nq÷T® ÷ga²ovïL‚©”!f\2ññ޵aTŽƒH¾…¹ûÆ0¢ØžE"ÂüOÝn×uåý÷³8­¬4q¢æ€9sæ°fͲd™ùè|º&Ž«@‰Õ¡çÁîÝyê©étu=Tú@WÝY‹•Ä£XE‰EšÉ$üt,y§‡u´Ò7¹ŒÒyÔÕG^n‡8¡ŠrNnÍööÊßýJ‚Aÿåtý•)V›ÞTO¹…<âC…j²åjcÈïø}Ñjù®ý)϶o¡­­¶ÁFŠ>ê5ÁÓçÀÒmçƒù"Åb‘C›6‘"2’˜½¡T*Õö¢@ ”a]&“!•J…Ä£†ÆPbÁ‚¬Y³†µk×Ö»)=âDÍ3gÎ`kã$Ø~v½»9ô¨'6VÉ n]/Ô ÅJ /–õ‰Ü¬X±‚5kÖÔ»‹p]7tõ(Ö¦iâû~HÊ9Ïóµ…¬)J¥Rx<“ÉÍfÃ|®ëâû~¸V±mÃ0(•J¡‚”iš½®K„`T®å\Ç!•JQè-øP ÓZ`F8µ»d Tט¥R©ªò–ã8a™2–†a„ã-u«c,䩤•Ïžú ž/j™¦i†ž-lÛî&0W‰[õ^sÒ_i¯çy¤R©ðÚÊ8Ú¶mÛá½ ×À²¬ðšËµÌd2är9N:iX‰ +p"÷çŸ>íßþ6V*‹"c±d€Y‚7rN,…ÌQI¬…ZŒåïjH"¨´HëÃcDdW#}OÇzJ#ÞÆ$4•‡(ÇâQ#DvE9}‰JbÑ'’ËJ›EÞ©öÃ)ÿKˆ«øô'cãD«\§|iZ•ºUò¶/õYRòÉõÇÒGŸàÚzt'[sJ>õ»³rOÈ=*ÒÔû@Èq鹞•¬d¥¿’ÓöžÆpÅPÈ UxŠ©ðŒąna3qâyìÞý*®ûÏï5¤Q&É U¸È'~æ¿ÙãðÁ9Q—×€X*Š÷|1tpC¦Yù¯zŠ"U_”ñG<>FøY«ÞфիW³`Á‚AË ‡ÍŠbÓ¦MÜxã¬\¹Çq*4 âéâV‹ñßýÁ“/¿Ì.Œ¬åòÀíäË7LÀ‡¦Dä{Q%ƒ„ìK§#"Ì&˜À—à…"lm…ßVY%ô¦BЛd¼Vþe7&¼1W[ÓG, {ÚÈl$³[\H¡FÂõ<° ÿy¢…“«HÂk¨ÂrˆåeÜŠTT5ÄÄ+¾Ø7M¸Ê†;³t#¥ÎjlŽZ¾HúÕ`jUò¯FþU뿡ܶÎ2`E¬±.Íç£ûE½Æªv¼ÿj;%˜[ÜEè2žL±"'ûp— oŽ1Ue[úÓöíc8b(çíó÷±hïäŠc¢9äº0iÒtN?ý¿Ø±ã†ð¶SoU¨ ҬƄÊ8{B2^1–M‚Ü%•mé«ü­ÚbÀ+ÿ©ðñqq±{ñ',yML<¼ðEZ 2áKÖÁé±l³ü§¡1 ùšÀ‡­ vv]ÉSçžÒ¦LÁf%‚g»¯²³R©D.— …Sù|ž\.G¶¬#B D"çyär9,Ë¢%®p£¡¡Ñ§¹`0ó@æ›ò7,â‚sº€!°47½Œ §õðP@”çÆ*êEºÖR2¨—œàD¡X,†$¢ëº$“I²Ùlè^]%”ÚÛÛI§Óø¾GBB !¥þnll HÛ¶Éf³˜¦‰ëºÝH@ß÷q'T˜2MÛ¶ÉçóX–E.—#“ÉTUâ^È-±pÈf³xž‡ëºär9òù<®ëbÉd’R©„ã8´¶¶†1®kii¡©©©›5e–eaFXV"±†a`ÛvH¦I›„ô‹[púUæ"ÉTôUÖuê5P!c#ãmF86ù|¾‚ð”öÉx«ãÑÔ{Cí»aäóù ‚Ñ4MŠÅbØæ8Q,ý‘>JgœqïÿûOà0pœè¹@\K†F*ù'ÞÏ,yW-㪔r®§W|o¯`¹ÅzÓUéË«|¨œ ¨m­Ug­ðHýÉWÍaD\4ZmìÕø^+ŸÀª[[•86‰HO•@n' ­*m5ÊÿRŽY¥í¦Ò_!,%½XtЬU,p… ”1¬v_ôå>0”Ïaê¥kUÞöŽŸ„ïþ­³[ºmÛ¶áû«ÂwŒ„ù1· ñœ–ÉD †S§ÂÔE^(G±âL^}b“KzYîË@mûT*ÊÄIµ•;‹0n\p]|«¼èE˜¯¿Zù½µÑ0‚6öD&·+>_«m¤zs ªZãùAf'#_‹Õˆâ²y\馛¸Šá‡!›Á)Ná¬-[`Õ* r‡šJ‹€ùó÷±k× @åË^>-+2b…J+3±Š”Ë ç€)J3ä…ã”ÿTâÏÇïF(V#Š·¼è \Ü„”s’¨úB²P r¬D‰<Ý5ŸM̰.2䨃@UcT`È×å¸(»öË­WŸÏùo;'Y0÷ÇÕˆeY¡&ºju×Ôo­·›E €žæ‚ã1d~÷ò,äÂÝ[Rⱞֆ¦(Ö« ñ°CDZaŠ* Šlê«)oùøá&@¨÷u¡„o=ä…뺔J¥ä±m»©äû~Y(Öoííí$Qsssh‘¦ºbï„ÐL&“U­-Ë ÉJ±¼“<¹òžS%Ùzóè ñ­„ør3NcÛvH^zžGKKKH2¦ÓéÐ }gg$ÌUI:S!ÏT‹Á–––ÐÒRȶR©„ïû„«´_ÚÐ_×|½Y;ö5_ÜŠÑqœPU!ýRÚu]Z[[™5kÅbÛ¶immÅu]ŠÅb¨ø‡ô7™L†çe¼Å2Tî½Í›7[('z.xbêÔàKš€Pª&êÒáÖÇj‘uêëÜî!=€ü=åS¡ŠZjÝ—vô=+ãoú_nà†þ× Þk‚Ï=¯.˜<ù+À* …Bè "{âU]’©D aÀÏfÔ)ÝEíj:Õ‚QµX4­€•öðÈåÌ y£mØ!Ù&h¦9$¤„àj¥5$ï„È9 ‘Bº¸88XXá§7¨2ɸ¡‡‡ƒƒ‡G‘"%JŸ.nx^Öä>>%Jaû=<šÊ~Ÿ…ÄL“ÆÇ'K‡FññÃrâå%H``&¬@UYlž|X5™«ô5.g•~ËfǪßSÍ4ãâ’%Ê\ Œ°Ò¶,YJeÓp3l{¢lv=X‹ÏÁ`Xmmmlß¾•+Wv[ä̘1#œ,V¯^ͺuë¸òÊ+ihhàî»ï¦¡¡+¯¼r@õÞ:gs¿ùM®¿æ†àåòYè2"6Á²*ýÖZœªIèPÏ ÝXt1< jNö²·oh Èã’Dá=±mŽ»-±úê_R飦S©Tŵ+•JáfLÕ˜Œ#t%£ŽÊyÀ}ÉeÏÌ¥¬xì±Êãn´(¸øâ}œrÊ.zh?–uNÈçBeÜB±€ƒ\9Õ Wkx"à’—…j‰öŠr¾/VÇ B"Ê‹´'kÆ<ù^-"G*d±£.¨äÉ+×IÆË(ÿÅË‘ë(×ÔÅ [êÂD¾KÙ²H‘6¨é¤ ªUÈk7ð£Â»ö¿«ÞCÚ õX¸ Á8N|ã;p7l sùr®{¡ÒÃz_ „£oÄ¢QŠÙl¶G¡ÝP@U8ðñ+æ9•÷³Üg)RÏ~3ÍáFAÍ£¢ƒmýÜÔ ZOg\ÕD[·«›Ëþ`ý¥ëYùÊÊ~å ôe.ì<à^à7óîwÏúºîàË(ê9Õ;ÆbyÏ Ï‰<ê3˜'_ñ—wµ¼C« Taƒx}P‰LïòmøSŸÂRê¨ cU‡­¬ý_gÈqU LÖRw¸–°Á›ÿ@ÕÙÀ๠ž«ïµ©‚zÉ úQ.w¦j,g±tBH¬Þdϧnñ}¤iš”J¥ª„T_!¤U­µ‡ì/Ç!“É„íë×¾V)K,ýT©BhŠ¢ìqUW¨BZÆëBTM§Z~ª„x”Èd2466†{äj}èZl ×!ž/ÞÏZíQÝáÆ?ÅZVÊëÉ­mµòã®h‡» i(æ‚Ï?ς߃ÿ èøfÃÃaMðÒ¬3«j%{žÇ¶m_ÀuRljÉ £»3@y-4(¿7N³ëEŠdóIò±í ®U$E* 3…8L Õh¥‰¦è7­dɆÊs"7rp°±)RÄÅ%M'$¼TBPäH²9–ƒÓí8P!':!Z'«rM±*”ukŠ.nhå¨Z'–(‘#G‘bh(ç%=¶W”‹CEÃZH“­“$É’¥öŠú„hU Nu?îâ’"Ž‘¹².ù™9rݬGe}ßíž*½\Ã$ÉÐ2R¬e?#šr¾H1ü,Q Ƕ6Ä#š q¬\¹’{î¹€5kÖpã7rÝu×ÑÐÐÀöíÛY³fÍ |9¯Þº5 ,F‘YÕÅÙ0qv¬º9Q!1‰¹\î¸ 6Ur­±)š²Y©Ö¶|>Æ|X¹\.Œk%®`’É$¹\.ì«ëº¡{!ßD;QÈÆ|>O&“!ŸÏÓÑѹÅHBÖËbäPÛ´µµ5tÍ¢j\J\ Ų̀ñ%$„ã8 …0f…çy466R((‹ ~i·ô;›ÍÒÞÞj"JŸ‰D˜_ê–M[±X$•J…ñ5<Ï£P(„îpÒé4…Bt:Ž‘h¦Š–'š®­­­áöw9Têy`ÏÌÉÆäò5–{9"ï½wßúÖNn½õœÐ=‚ê "-£Z\y|ÿf•ÿ’$+H§b¨HG}!,¬Pó¦ŠCÒÎÇ'O>t±#‡jR©$œhÉØÉK[ÒFk©«D)´Î”¸”-‹Õ‚A4Š„˜·"ŒT5™ª ¥]ªR%ªå2Qªã-ý‘EŒ*`”tV…u$í°±±°øÅ¦_°kÛ®!¿‡zC=Öþv °|ypÐ üý±vTc5ŠàѶí²Ö£¾·ê|ù‚{¢@;$U2K4Eˆ](›qpÂgTÓ š›šhÂÁ©ê6äD ›_q'-m–>ÇÉ9õYV5Uës•XP¡’6vE=ÕÒ÷ê\ }ŠÆÕ”TE•PV •áL ÷e.ì<°Ëf»[ø?ÿgÑÐv.•±Ög#¶Í1¯Ð£õ¡ªD¡*Éo™òN–gP„7²î5‘yå<̃ó()ZËqô¤ˆ *©óŽª”&šçÒ,Ùp.0´ ø-.ß çuuŽºpÉ…õ¾:ÝPO9AOWêbegY©T*Ü‹Iš¦¦&’ÉdMË:ÙcVÛ» ñØ_«¼x@û¿89)1û É_­.µ²®Ö×d?ä.µòÈ~W\ŸŽFQ;ZûW C1X¥Ó3= ÇÎÐjhŒÔkM {/¸èP¤¬èy,1XÖûtu#—‹ÈF‰ÌѲ³/²…"E’f’(r¸,‡‰™ÁùL2X_Š,L”ÐÓ¤ñðh¦Ÿæ2á!–obõ'ëX±”5¬Z–ô]Ö™Bú ¹'ëHÉ›!Ž•ÈÔu¦|O’ìæµM¼¬‰|Päf&f…òs¦ü'Ç Œ°‘ñ…*Ÿ“5¾*+i§=3u®î¤¢¼(çdí.îZUÈ~Cä‘9rá8ˆ»W)GHW9/ò—©Pþ)}Y¨\;!ŸÅ ŸJO˜?Is& è¹ âqÍš5} èÞÐÐÀ½÷ÞN6K—.ðÄ!â¦÷ž~eà µµ|°P¨¿&®5¾€ã8äóyZ[[C7"*1%ÄŸhF‹E’Éd¸(¯¶‰Pµãî6äXsssX§š^b5ˆÆã8477ÓÑÑ WÓé4¡&h±X$Sži³Ùl¨©gFè&$‘H„dh‡ª.@|ß§X,†–$A´(s­ùf–Ì” 2–ª6¦¸p×,B>ÊF/™L†%i{©T¢½ì>µP(„q5$>EKK ©TªBÓRâUÙyìXà\^ÜÚäóyR©ét:<'}—@w#™L†„n6› ÇEîƒB¡@KKKEüŽl6Ë™gžYï[»†t8`rÙSÿ.Ä¿:ÀÕW¿ÄÚµ¸þúya–j{þþr¸cÅõ¨¼l$°±CMU`&¦ÿ²ø°°B22M:ØÅ‰>yqŠÐMõn`„ –,Ùð·,Ô€P0˜#.Ò$­¸]“pBHÜIûe¡_@©$²*€T$êâ*žþDi©‹›8ï=LÛÞáçJ©kÿ>Þ]ƒ¯n»î‚'þ½嘦IkkkhÉ.s4óÿpˆã˜"’ÏÍ4‡÷§‡G'U"$­,Ü…ˆ¬YÀö‡x,•ÿÔMD¤¢ÚžZͪI(í©•^Êò_æU‰AÎC%©¨>c²á‰“Ž*)8ÜȾµ?_ ÃÏà±OsÁ`ç{O{/øCL:B}]nŽuôÁ͵úþ¨¿¬L1µü¯ ®Ð_…´~­!&Ö>åáñÙÒgn±ê±&è ²ßw©Éd’L&S•8”÷~OäS196rIöþ½¹HU댒ªiš=æ¯E„ªûôþÔU«½ª5äh„Çq¬`(æ‚çž{Žww¾[»SÕЦ¨×šÀǧñY çL—g®Oðšòñb1"N>ùB²Ùà·Ž¢k(Æ }­OöÄ@¨H..7}ü¨RݠƉC•lS-à„\’‰â=£•VÒ¤Cw«.n˜_>!üll$Âr伬g«…%PæTÈ:6¾¾ŽïEžªZTªŸjìEU†(ƵÚ%èinb’!ZPªGÄ §²¥þZeÇ••ŬŒIo1…ü¬»Â+ª)õ‹LT 2Š11ybμcÊ; †ñØ_ˆÏæÁ`ÿþýLxêiVülEü×`ÈÜTŠF¡ïû!¹–ÏçCRNb*Hl±î¦J !&{™L†D"A>ŸÉ&ÕZ¯T*‘Ëå˜B*J=B!)¨Æ¡r³¹¹9Œ_%íBË:©§££# /ù{ƒh…ÖÒ! ©'(•J‹ÅT-.ãe‹`8•J…$d|£&§ ‹µ(›6˲ºÅáM|V>«åU뻜«J5eY!9,çÔ±·3Xä|ö³ŸÀ;¼0˜yààd“Îå{èô$ÑJ2Mxë[ÀÁƒ‹€åõîæˆE\#_D¢ÁT°—mM¡¦’ä[ÿa¹-´T='ÚH=½„Õº¥®ø¢ š€Q-/^vœ¨¨U†š^cà8k‚Ÿ.øYø}üÞ½lûÆ –î9"Œ”w¬%õv³ t{–Ä­ˆª-X BVŠ–cµÀêqˆBº°Ç¯­fY”!Ó-à|œ°Ïé§V΋e´ôGÕðê±Ö t84î¦ýa0³Þ]Уˆ Mú‹ãµ†-óÕñXTC©T"ŸÏ‡hz²Ì«¬Y•±Ô¢³qåFÈÁ¯Výªâ]i`ðLâÈÁoWÿ¶¦'‘ž,×}|ö~`/Sß9•4éð«†qxþ¦çÙ“Þº›pù&¿yrEL£žêPßé{J{xtü£õ©÷¶k¹ƒG/´Bȵ§iäàÉkŸìær,´ØU¼˜˜lýÀV0à‡oúaP¶â©äÅ׿p,§[l)YwˆPÕ5†hû‹2@<lÜÓ€Z¶Únõ˜'ÕúUÉÕ¼¨ˆâ£´S0.1œ`]//îŽ]Ú¬¶EõŒ¢Ž‰…Ås3žãà”ƒƒ~fȩ̂ï?«w\Í ihh #·5Aœþ”gz™~¤â”DNÈf³lßÈÅK¥È°ÁqÒÑ0úg¸ ò3Ù× Y_:!‘¨ºÍ’ Ý(àá…r7ùÝBK¨P, ´bmX €‰’ª>D ·"÷:ªãí­¿˜“.nHÚõ&»è D[È`‘óõÖ·¾žâNUãk¾¶ m´mœ±Âˆ$¾û œëŸ¿ÉBÖ,O„̳,«"X»Xâ•J¥¨³m;tÕV*•BKH¦j®2ãšn*Q(‚*äX2™¤££#ÔÆ¨XJªÜ¡R`Úј$Ç7]’¦µÚÄÕ`šæ€ÝÉ«’¢q‚¯/ZÕŒTcPÔ+FB_„ÚcI3²N>Ϲè"~òB¤$ZHï}ïyL˜°°ÞÍÑP".nèÊQ4±jÅG‚`A —žjb¹Xë\-K¿j¨FljŒì¿°˜rð Ó::0Œå}ÖER]K¬^q¹6 L‰‘ÐDئ ÂzK_ÀŠàMÎÇ¡žï+âåÄèõpK­12p¨ñ$ÎÜûpm½›¢¡¡1ÌàãóÝ-ßå_¿û¯liØÂ²¿_FóëšÉÎÌVÄô_WÖšVªÓ`â%Ùwî¾Ð[FH°Í,Ø5 Yt·píiíj`0næ8ÎúÝY·j¹0~îxo;*Ò~ƒß­•«VÀþ}ûñ^ïÑ@CUk\ ‹s72sæÌJÂlfPÞ„Ùh¦9´šÂp jsN›ÃÄK&²iÊ&îäÎð]ïâ²éšMÌZ4+Œ_UM©D)´‘õMüzªÇÔp ª—8Y(éDIKõpÒÓ½¡‹jì+q™,ítp`9LøÞÆ1®êu¯+¶§{Eúóëó~Í_´ýE¿òÌÝ1—sw0ߘßý¤ïG ƒ„Nˆ)¢“U$€›šÆu)Õì)—«d#²Ù¨Ï b»ÄëI$*'“•FÅbÀ|¨ˆËçš›+]¾[V÷¶fc =µf%®`ŸHã }î©­’®s‡žNGqoL3øWËp]È磘9wTÙ˜ø½Œ÷§Öõ“ö¨õx^Ð^©Te[ã×·/õXVex¯þÖ#ýTû7¶«cdY,|ñE4ÊxxÆ`þ«›|ú~×±/ý³X,ª–‹ªb†L…‹Ó©P‘ÞÆÆÀ ²—¾2ù($œȾ¾Xko®ÆnÅ•=íTåÞqój§ÊY,,Zi=®ã*×]uñZíóDÈDÇ,ñ¸ÿ…ý\ãþ¶æÁ:~¤£¸VóÜòºÏq¤Ÿý¬‹·¾õõüÏÿì­w3G4ä'&zrË(Ž Q ¶Lû-sÿ8 /leÿú³1;{]onnÆ÷ýð}ß“Åþp„Jº÷¦Q'q Õ|O00zu ¢¡QOü|þ*NþÃþz7CCCc˜!K@.²NNÌ[§¿• Ob`ŠU>T ãDá­¿Êl‰Ï%hii©ª-Ÿ.¥)؃UÌ„ü“y2×ÖVÆógø”ž*‘Z5øµKþWy2«zVüóÛ| 7tï“ë¸|/ó½¾Wv24ÿK3-«ªX0L…t!]!W©f¹)Db®Wµ˜ÊªÅ!D1´zra?X¤?–&YHV²jÜÖ(r´­o–¡†sžÃîÓžd~ú3ÁU.çºá'$‘‹Ó Òyå@ñqY”c*y—ó%“A>ñÍX-t&SI„Æ7-¶ÕíyÕÙu¯"&Y*Ô84®[½?ñ¾W«GÊM&£q‰—¡«V˜‹Õ‚’=áxÇÕ&©Z[ú×ÚÏ£^[9W«ýâºKÆß²*É`r¿Êùx™ž+×ÑîÝÇwÌF0œY§ž~ sÛ®+º×ÄkÚ>°•D"má² #^¹Ä†Ñû­±r—ý¶êêTbþ‰G ‘»(T(æ÷ŽX Ö*KÎGÈØïpWÕ¼›¯r¥­êzb4`Ì;ÂRöš?ƒ$Ø„Tt]·"Æ¡išäóù²æƒÆ¨–uš ;>IÂ^úaÿTŸ‰¼k³T*X¤R°m|õ«íXÖñ £¡¡1L1N;º”Í»»xeëb¬·÷-›¼ÿ%6Q*•‘J;²yéK:qq驞jäâ@âªV+§šegžü ær¹nek.ƒÃ²†e,îúKp÷w÷ˆfÛpìXÏôvÇ- «AL¦z‚ÜÛµ\>‹U`_ʈFt¼Ö<Ô—g¶·þÆ-RO_Æ5™¬=^}mëPÕcY½Ç£–1qÝÀ¼®·ô¦ÙݵV™e”nºi¸…}®+6,îâºol¤è¾6¼„–·Þ:8røÂý g/¯ø¾:׫!¹$äDï ø\"‰ªžäÃÙh Yþ Ͳ•1K<ú “9së$È î!ñ}Ÿ¦¦¦0öb{{;ŲƒlØeZ/÷›UðÜœÎ@Éó¢Åãä¹ì²³ìrWCCc„! O<ðížÎ+¿>Ä¢®Þ÷êq]nÛ6¥R©GáápFŠTŸ5÷ZiÅÁ1‹x žpäµÓ9ãŒqƒ/hðø3&þÝcðÛŽ¾[®ihÔ–å0X'[ÝÌJÚ”i]^AO=õ®±$<'á:—-kà©§Ž`ÛCcaÛîV´/·íý¹ì–¸Ô=aLER%¸àÜ)ÊŸÏçC!‚ëº ,Ë 7ƒ²ñ×ÐІðænÙº·O¥àSŸÚºîÒ¤cÞÏ-½#àõ/v½éµ}Ê×ÜÜ’ú¯¡12ñê«_cÞ¼7 º×uC²°T*‘ÉdH$¡'•R]rŠ%š@.!²jJÕæœjqÛ«Á4ͺ’)õôcFEÌ·¡†&±†7б±É¡ÑizbñÉVëœÄ|«õüô”"7/µÒH\1ÛŽbµõçžUã’Aõ¶öÖFA1¢5F/ÆœÅc9ª ÿñ™÷0—s±±±°ððH“¦D°K’ M†-÷HÅbÏóhmmÕñ044F(<àØÄ£ø~°Ç:v ,øl{ø¸5ÐÐÐ8à>¼º¼…\Û˺Ùó<1 ƒ\.×£»A ÑQ@Ìçóa\W‰‡·zÖVm#%J9r„Ÿßús&Ù“0M“ñ--ðmÚ h°`‹YÀ%ð òç6ÜÐ;‹€)Fp>äØ\Z߀ÙL°¢s%`‰_m…+×ÑåÂçÌà¼pH+rôÒ%8ß$€œ¤±¡ó4G|Ø ¡§6¯ÜÞùIøxÖ+DµŒ#&|¾ºLøU9æhÉò'¥žVhu¢²fe$ bÙx6¤:Á,÷mGÞL @º\ÆW]xȇ-ÀA3(Ã"È÷&¼hÃWsð%–ç‚óa~`« ›=8Ň•ø…]Ù—ƒI8¸Ï…L~æGí¤\ÇóÉ`¬,¸ø´\)c·ûÊé/¶¡±ÜWÊi>DÐÎåeå³›7ƒ~—_™o ö¹07 SM˜kV–aš0! {=x­Ó|(ÆÞK,øuùû‡lø®IE8­Þ`@kY¾Í‡·ø0Q”ZLh´`+0Å‚³}xƈî-€­å4¿ƒ—_sæ‰{Ð4444F||NÞo1{Ú,?ÿ×~‹ëB©´ˆóÏ¿¸L&ÐwmÐÄ¢Æ`1æˆGwÿ~ÆO{;Oã¿.l­0¶±ññqpÈ’ÅÂbÓÁMì;i§þù©ìùØRãS88˜˜’b‚ìáacwósìâö+†’††Æ‰Áþ#Ánm~—Á4+R,õ§ä°ä‡KØxl#¸SáaÀ&  #øîm¦ ‹Lªz“-Å9º9U2Ëç-À,ƒÚV®Gä&g[Aêy£|.EP¿O™4*ë‘|†œºLi‡§Ôƒ——óšFÏRê²Ñ¶‚.Þ«\—¡4ÁLuOc¨+ðRŸgÀ%9x7°¨¬è&ÃL¹Í~¦²}n¼JƒM¢k&Ó¶a€›ŠÆñr‚ñ—ò,XÊdT®Uî…ˬèZP.c‚2¦W•Ë,­ÌBÖ®Ÿä1Ë÷•Š¿TîŸ7ÏÅÆm¶܇/—ëIÑý~KåÊİÜC±zÚ´C2òW</þ7cßžÿmæáacMCC£¾pq9pò)ÛÓs¯Ä4¢ßxãµäóÁ«e ®U‡;†“ëW‘‰1G<þÛ_`Âë_亶Ïb¼½òbÐÆ&G.°pÌ{L¿|:Ë—/ç]7¿ ‡>iÒ(`•ÿÒ¤kºq•`¬.n¯[)R$…3š†Æ`ÃáÓ›ööå45ûg×uCa¢††ÆØó‡åçoz•I/^È¢ ûzMßÔÔD*• c:khhŒ^xžG6› ãê5‚†Æè…sø’?}†©ç¿Ÿ7=ÿN¦~qj@âÔRôW·ìÕ–¹ßUؽ¤é‹'w•Ûê‹>Dµ4ñzª‰#ìßk¡Ú¸©õÔy¨il¥¬|•óm›I÷kv<®Wª‡ôj¾å£Ù<‚Z|Øñh[Z˜ýmû¡­÷a8å•SÈ“'EJ Û544ðûž|.‹'O†üв‚XŽ_þòVÆëIJ–£“xÔÐ,Æñ¸iÊC¼æé·ó¦w¾©Çt¾ïc­­­ZÍI’øøäÉ“!SuA’'OšÈÆÚÀ v€Ð­«‡×cý..>~h9éã._)âàhâQCc€øý©›˜Üõ2,Jeu%M&hhŒ-ä/úϾæUŽüòÎ<óäªiÇ c:JŒ6 Ñl6‹ã8´··×»)'§ļ‘p–°âò?uþp‘¡ŸWþã99oöòéõ¡)O5x³•c꿤W ý<%Sn£j¬)¿ÅÀ¯–!§¥ÔÙ—aò•²¬XW)Ç*·KK ð>Fü¢4Ò1ê”2ÔO3VVo¼¬¯¤•6žêÉ¿ ü[V~üþéϵ€Úcá÷1ÿhƵ»¯å™Ægh¤‘$I ìòSf`àㇿ544ÆŸ¯*ppƒŒ•Ã÷ÁóÁWVi†)3ƒíe0Í€Ôp] hE88މa˜a¾\.ŠžJi|¯¼ 1ƒ|†˜sÏXèòÔYÎC•m²Ê.#}?ð¶¡z€rÝà¸mi<¯vzßÒK@\I+JÞr^êtÝ Ü@-§¯úã}ÔÐè+v͇q&žg`ðìå¿ÿÛ “Ñ.U44Æöw1±s-|ãÜsOõ%‘X<¥ÓiÚÛÛµÕ“†Æ(†çy$ ZZZôº@CcŒàÙ9ÏbìϢǓt¦Pœ9—(”ãXƒxu[ÐñBÐQïFG,ŽÕ»=`åJnëMÞ?´Ð‚SþsË›{ì˜|bgƒÙ]&{Çû™^^zØbãäà©<ë‹i‡ ¬L3><þ¬O×¢ ݧ+uO÷ÙÒ=ÙË;mž;è³k~plî‹]ó]¦4˜»ÃbÖ,øÃI/4Tïû”ƒgL5xî ÏÜPo×üÀ“ÛÌN“kîj åvâŠR•Š«JUNéy‘,2•‚b1JŸÍVÖ¯æ3Íè·£¸Îå¢2’ɨN߯”…ú~P§È8UÈyIQ¸× òH>Ï ÚQ,VÊI¥l¶ZÛY¸åt,kétp}.ü?øÁ›åZ6­¡ÑÆñèâòÊI]œñ³ pm÷óŽ&ÌfÙ²_ãy+hiIÑÜ——dk+47ß3™àå"çåE’ËASSð¢,•‚ãÅbpÜóº¿ÈBr’ˆXS_dò"-¡k…Åþ¿/’ÏW¾”åÅí8©¨¾p-+H“(4ïèÚ¨Búãy‘‰x©µ ³3*£µ5xù«ý±íÊz&¥´¶ Ç Îg³•m•4j=ñ2D”ÏuJ=…B0î‚ÆÆÊö;ãÆEå¦Ó•çÅl>Ÿ¯]w¼ýÒÃÎÉ}NG„m>ß½Œjý“ʼn”!å¶´To‡Ëd‚ë«¢±‘ªŽ3øýïßÂX…7q=ãvÏdÏžq¼øâo(‹ZÀ¨¡1Ѿô{NYÀëzÆÅÝλ®z?ð—ò<öØ3¼÷½3¸çž“˜ÊŽW‡mýæ7çVÜã«Wuënà ¿Ãòåoã?xŽsÎ9‡mÛåŠ+ÎeýúïräÈ;êý8ÖÿéÑi?Ï‘û‹±ôµ¡¬Ü¶áMoZ‘#§†2y êSÄãÝ]%h°±¦EÇÄLÚóàùçpÊ)fÕªÉ(ñÝ,ß # ßzƒh¹æºÑ×ÚÚ ’ô‚B¡z™©¸4áñ\k÷óªŒD¬ãe;Vý{-är‘Oµ|ÕLÊ…(•6uvvŸˆûb%yìXD®¶¶VÏ—JEšG™L0æB<Ê5”¼Òµý…BDÞÊxF%ØÑõGˆÝ\.H'Çs¹€à“˜–¯BDærQù2žÑ÷cÇ*ÉWiS&gkìšK>úÝÔ]R)²rç3MxúéM½_€QŠ#Gw1÷éU[E)ÀÓ®Ô44Æ(öœòã÷.à–·í­zÞ÷ýP)A“Ž£ù|Ó4ÉåúXMCCc´àä—Vòè¢Å[_OŽÚaôÆ ƒ/âøc´-Á†qÎ8tˆ­õnDðÔSÓù³? äIíí¢Ðï‘É477ãû)’É ü‚ã8†ÁÃ_ñ8mŸ‡uØâŸvÉd2$>ò'´··“Íþ#ËåÈf·’Ë- ¹¹™wÍÈpñ¾H™Ñ?iÖ©îÖ.ì7- ›ýþꋟæùiYRïü?‹¿Â¾øµxÞpÚ8mp¦ùÜ®?’|WÅ7ºâ|ŠÅSI¥^Kq篸åìk9ûRÓ<Ïó0 Ã8o‚‡m7Q,n µäÍL=s3©ÔRŠÅ6RïjÂqö`¾ÍÄ÷}|:¶m‡a¨J¯>Cò-o ôÇgIÝœ TÚCrv’E׸Àkñ<–‚i¾–Ç»ñ®=Ç™oZŠiN`Û¶ß’J]ÄÙgo%™¼ˆRé·ßÞ€ïÅ0ÞäL³Ï;Ëjà²Ë®Ã¶çR*Ç0 >ð­XÖ©eï3G1ŒÅø¾Àq“J5pÙe[Êát:±¬£¸nÓ<ŒïïÅ0–ñç.aµÆãyXÖÙ¸îR%Åܹ.¦9³œg<¾?×ýl;Êó§ºÛ^¤Ôs]¬žÃa~ÉóÞɼy°aÃ<.¹ätòù Ì›7ýû1}ú–.]ΙgnaúôéÀEœyæ$.¾ø,_> 6pî¹ç«Ù·o<û÷ã’K–sþùØ¿ÿ%¦OÏÎ;I$Y¼ø4-‚;òŽwLæê«KLž¼Ïs™O2™TbÄ$“Ažl6O.—#ŸÏÓÒÒB"‘À0 ˜fÇu]LÓ(\^è¦r˜f‘B¡@:&—K‘ÍfÃz$¢eyŠE7L#mƒ%“Éà8¦iVÔ´7èO2™,E*´TxžW&élJ%‡\.I6›¥¥¥…æææ°žT*…ëºåõ¡Ä¢3Ëíµ°¬Àý¦ÚÆ\.Wîo.™ ê-•ø «W¯fõêÕ¬\¹’;3M›6ñàƒöš÷À waü×û8rä)J¥™L¦ÇÀÐà ۷o§«««ÞͺººØ¾}ûÔe``cŸÒqÓ¦MCÒêÌ<`ø]¼ïñûxä‘…šÆ# £áþÓó™ÆñÀ`æ‚:w±ù蔳q]—R©Z,ŒaÝh¹ÿFÃ|6ú0’1˜y P(Œ)ãh™;ú‹±øœŽµk=ع T*…†---X–E{{;–e‘Ëå°m›d2ZY–5ìHGè›ëhýLŒŒµk=˜¹àŒ3ÎSk{÷ŒYÄ@0–®õ`æýû÷ã}ÿ!¶µñ÷¾…w¿{6‰D#¶mÒq4\ëÑ𜎆uÇK/½Ä¾}ûUƈ!7mÚÄöíÛ+´±,XÀ’%Kظqc¯ù—Üêð–-ÿ‹ã8#Ò¢aݺu}êçpÆÆY·n]½›1hˆ¶ŒÆÐc°óÀôéG8óÌG°m{ĺH ÷ŸžÏ4‹ÁÎÞïfÒ?ßÉ´i‡I$d2™åVi´Ü£a> }©ì<01ZæŽþb,>§céZv.xñÅËñï"Âq$)(ú™;K×Z¯ ú±tFƒ,b +×z°óÀ¶mÛH\÷·@’K~ñ[J¥ .îHRJ ×z4<§£aݱuëV6oÞ<¨2FLŒÇ½{÷ts5cÆŒ^Ùü;wò ?äñÒN^ÿ±1a„÷ ®_¿ž;vÐÖÖVï¦ ;vì`ÇŽ#nìãØ¶mÛˆíƒ\ƒçž{®ÞM3lÙ²…Ÿÿüç<ÿüólÛ¶­ÞÝFòý'ÐóYý±~ýzöíÛÇ\Pï¦ ƒ]¼Úz /?þ8OÜvétšo|ãõîR¿0Òï?Áh˜ÏFröíÛÇæÍ›Ù¹sçˆt³:Ø5ÁŽ;hnn¦¡¡óÏ?¿ÞÝŒ–¹£¿ÉÏé@ÑŸkýä“OÒÕÕÅž={êÝìa°sÁ/~ñ ,Ëâá‡æÑG­ww†ú™;èϵëûƒÏ~ö³œrÊ)¬X±¢Þ]2ŒÅ¹`4È"‚¾^ë±.3œ¸"Ï,ÙÁŒO73éÙ"÷Ý7•Ë.»lDÉ FÃs=žÓ‘¾îxòÉ'éèè`êÔ©ƒ*găÁG?úQ/^ÌÉ'ŸÌYgUïæ #Q 4Z1’¯ÅÿøGþøÇ?rúé§×»)uÁí·ßÎóÏ?Ïi§Æi§Vïæ #ùþM}é˜9s&W\qE½›2ä5ÁÿøGV­ZUïæŒiŒ†¹`$÷ᥗ^bÁ‚#¾Åç>÷9{ì±½?ÐèÆâýÝÌŸ?ŸðÚ×¾¶ÞMr¬\¹’n¸€… 2mÚ´z7iÈú­16Пk=Ö÷â†q¤¯ÁXœ ÆbŸûÓï±.3Ìä2<ü·3oÞ.ùÜçêÝœa4Ü㣡#óçÏç’K.ôš`Lgžy&7ß|s½›¡¡¡Qg\sÍ5õn‚†Æ°ÀX^Èé5††ÀŠ+Æ”Uƒ†F-Œå5 ×eŒå¹@ï444 j¹¡†Æñ[Œ˜‚j¦ÑK–,©w³444†zÐÐÐ=hhhèy@CC#€ž 444@ÏzÐÐ.1Ä£0­ñà¢mmm¡›( Ñ =hhh€ž 444ô< ¡¡@Ï ç =hh 7Œâ`õêÕ¬[·Ž®®.î¾ûn¸òÊ+ëÝ4 !‚ž444þöÞ>N’ª¾÷ÿ ÂÂ2»5×R¬:`53FI¼ÕqWÊ^»'÷jt÷·;&êš›‰Ý7÷å&Á›¤['W‰Þ˜î%Y5šëv%D¢ÂbWŒOL§eG@˜ ›q|ØbGpyû÷Gõ·úTõÃôL÷L?Ìç=¯~õTÕ©ªsªë|ëÔùœï÷´„ÚBˆm! - „ÐÒK •Ëår·3Ñ*KKKؽ{7–––0<<ŒÅÅELOOcjjªÛY#„¬´„€¶€B;@ñ¡- „´„ÚBz‰¾…ÙÙYÀå—_Žáááng‡Òh!m!„v€âC[@h !´„ô})<B!„B!„B!„Bz‹¾šã‘B!„B!„B!„Ò›Px$„B!„B!„B!„´ …GB!„B!„B!„BHÛPx$„B!„B!„B!„´ …Ç.²´´„ýû÷ãꫯÆöíÛaš&>\“nff&H³oß>,..®hûz–çꫯÆìììŠËÐír>|¦i¶õ;t» ¤iÅôÓý×ÈôC:a º]ÒŸtªMÐjšõ(O¿¶ €åmA?” &ëÙfèÅ{x­mK¯•y½lQ¯•›4g=Û ½zo´c ú­N¬W_E/•™´Æzö)öâýÁ6ÁÆù­×š~*ó®]»úò{ú=—––°oß>lß¾Û·oÇ®]»0??¿â<öÊý¶.}6eÒ5vïÞ]ž˜˜(ßzë­åÛo¿½ü¾÷½¯|Ùe—•o½õÖ ÍûÞ÷¾òÄÄDù“ŸüdùöÛo/_wÝuåë®»®åíë]žË.»¬|ûí·‡Ö·’Çn–ãÖ[o-_vÙeåB¡P¾ýöÛËï~÷»Ë—]vYù?ÿó?û¦ ¤¿YÎôÛýWÏôC:a º]Ò¿t¢MÐjšõ*O?¶ ÊååmA?” .ëÕfèÕ{x-mK¯•y½lQ¯•›,ÏzµzùÞX­-è·:±^}½TfÒ:ëÕ§Ø«÷Ûï«èµr¯ýTæB¡Ð·ï؃Ðï)ç»ýöÛË·ß~{ùïxGybb¢|âĉ–óØí2D“µ¾Ÿ(›ÓÖ­T$ÄøøxÁXZZ­·Þ<8Nœ85—-[¶„:¶¯KKKx÷»ßd2Y·ò-W†VÓ¬xttû÷ïÇââ"FGG155”§×Ë@ú›ålA¿ÜÍlA?”¡¶ l2éO:Ñ&h5ÍZÒïm`y[Ðe ƒËzµzí^ÛÒkÏðõ²E½ö[“åY¯6C¯Õ )g;¶ •2õRX¯¾Š^ü­Éò¬WŸb/Õ )#ÛkÓWÑk¿õzÐ/eÅèèèªËÐírB¿çèè(¦§§øÂÛ‰'pèÐ!ŒyêÛ²Þ}6ôxì>Œ]»vattÉd²ÛÙi™B¡€-[¶`ïÞ½ÝÎJ[ìÚµ ÃÃÃÇââ"vïÞÝS²q -è.´¤ è>´¤èW[±Rɶ¬Ú"²Å×ÐVØ(¶`£Ú€¶€ ýn¯fff°gÏ>|;wîÄððp·³Ô2ëmCéñØe±ÿ~ÌÎÎbïÞ½H&“}sÃÎÎÎâСC¸é¦›º•¶I&“¡Jgš&:„믿¾ÛY#Ú‚Þ€¶€tÚÞ¡‘-رcG·³FH_ÛŠ•2h¶e¥Ð‘Fl$;ll[À÷ÒŒd 6²h Hÿ3(öJ¼7ggg±gÏ žæ½L7l(=»Èüü|0bŶmLOO×­põF°¨î°Ëm_+fgg±eËìß¿{öìÁž={T•ÿ•”¡›åPc vìØ„3è—2þ¥[ÐË÷_«¶ —Ë tÂt» ¤?éT› Õ4fÚÀò¶ Ê@“õl3ôÂ=¼Þ¶¥ʬ²^¶¨×ÊMš³žm†^¹7:i ú­N¬W_E/•™´Æzö)öÂýÁ6ÁúôUôZ¹×ƒA(s¯ÿ¶ýÞï)s­ªLNNbrr³³³+Êc¯÷ݶšÇVÒPxì"ûöíÃÎ;qà 7ÔÕ,±r£sÎÎÎbtttÙíkÍÔÔ®¿þzìÝ»7øÀÎ;ƒÿ[Éc7Ëqùå—×=·úðîõ2þ§™-è‡ûo9[Ðeè„-èvHÓn› Õ4kÅ ´ €åmA?” 6ëÑfè¥{x½lK/•X?[Ôkå&­±m†^»7:a ú­N¬W_E/•™¬ŒõèSì¥ûƒm‚µí«èµr¯ƒPæ~ùmû½ßóðáÃØ½{wÓ4½n[ºÑgCá±KÌÎÎbqq1PÆÕªOMMáСCXZZ8pÃÃÃØ¹sgKÛש4ê@hbÕVóØ­r crr333Á¹gggqøðáP£^.éoZ±½~ÿµb z½ ²´d5tªMÐjšµ`Ú@k¶ ×Ë@—õl3ôÊ=¼ž¶¥WÊ ¬¯-ê¥r“åYÏ6C/ݲýT'Ö³¯¢WÊLZg=û{åþ`›`íû*z©ÜëÅ ”¹×ÛAè÷ܱc–––pàÀP¹fgg;ÞY+ºÑg3T.—Ëk^2RÃÌÌLèfU™œœ â/--a÷îÝXZZÂðð01==¸Ø/·}½Ù¾};<ºa[Éc7˱¸¸ˆ}ûöa~~ãã㘟ŸÇÞ½{1==Ý7e ýK+¶ │-è‡2tÂt» ¤?éT› Õ4ëE?¶ €åmA?” &ëÙfèå{x­lK¯•y½lQ¯•›4g=Û ½~o¬Æô[X¯¾Š^*3iõìSìåûƒm‚ÎöUôZ¹×ƒ~+s?¾cJ¿ç¡C‡°ÿ~ cË–-X\\ìû>õ¾Ÿ(<ö /øòË/¯³}¹í½@+yìf9äÜ£££ ]œ{½ d°„û¯ÊÐ [Ðí2Á¦êÑ ”a9[Ðe —NÝŸývw¢L½Væõ²E½VnÒ±Nt¢ÜýV'Ö«¯¢—ÊL:Ë Õ‰N”¹S×¥eZ뾊^+÷z0e„ß¶×˰¸¸„9ô>ÃNü !„B!„B!„B!mÃ9 !„B!„B!„B!mCá‘B!„B!„B!„Ò6 !„B!„B!„B!mCá‘B!„B!„B!„Ò6 !„B!„B!„B!mCá‘B!„B!„B!„Ò6 !„B!„B!„B!mCá‘B!„B!„B!„Ò6 !„B!„B!„B!mCá‘B!„B!„B!„Ò6 !„B!„B!„B!mCá‘B!„B!„B!„Ò6 !„B!„B!„B!mCá‘B!„B!„B!„Ò6IOâyÇéèñlÛ^³üÚ¶ Ïóºrî^¾.„¬7Íîç¨]¡]hL¯çvXÍý½’6 ë>!½ÁJÚ²n%÷§ìÂjνžôrÞÈÆ¤“}ltöÚ²Vt¢Þ7ºŸ;Ñ&Xi>Ø& ¤7aÝïlÞ(<ö(…B®ëv;ëŽçyH$ÁÄÄ&&&:òRá8¹ˆBc€IDATb±Øšå;‹5ÌçZŸ»—¯ Y9µîw×uëÞÏì íBcz=چαÒû;“É “É´œžuŸt ÖûÕ³Ò6°²û¿“va¥ç^oz9o•jÖ¢¯€m‚Î]²ölĺߩz_¯]Щ6ÁJa›€t’hÖÖýÎæÂcbYÖ†4™L®ëâøñã(—ËÐu¹\®ÛÙ"dÝØ¨u¿\×…eYH$u·Ó®A€¶¡;ضM{AºëýÊY6íé6Õ6t»MϺOºÍF¬ûíÖûfí‚nÛB:ÁF´ ¤8­Ûèžç¡P(ÀóŸ/kš,(çóù`Ù0Œr2™ –ÓétÙ4ÍU§o†išåR©Z œN§Cùmåxsss5×Á4ÍàXͶ/·ïr¬äš‹Å2€²iše]×˺®—5M ýF®ÜÙl6´ @ùøñãÁöãÇ×äA½íßJ9K¥Rp©×+÷h³ûµ•s¨¨×.zŒt:]ŽÇãËî۬ܭ䩛°î·W÷Û± ­°’kÒJýkåDï‰r¹¹]t» ¿Y#ÛÐlßA´ _øÂÚ…r¹¼¬mè¦](—kmà· Úµ Íöÿçþç¦u_Ò†±ªßªÛuµm‚å®[/×}¶ X÷Ûm¨û4² ° rœF¶m‚ÎÂ6AsÚ}襾¶ ª°î³î/G7Û+¹.íô.wO´Ó&èT?ì×km‚fû¢]´÷…ÕÚ…rypúWÛ&XN?ôº¿m‚¾÷x”g©T*¡R*• ë:,Ë‚iš¡Qiñx€¯ÚêºÏówiYV'úT÷Õ4mY·Ö•¦_)ª k«£íê]uÄO³íËí»’ßh¹k¢Ž8ZXXÀÂÂ’Édªß쨮èâ ¬þž2ZBîƒ(Ëí¿®ëÖ\/Õ%¹ÙýÚr `ÛöŠBÀÔ+w¯ÇgÝ_žvêözÖ}a¹ú·škЊ]T»Ð6¨×ó«_ýjC»´fÝ.,·½íB½ý¿óïh\÷]×E.—C>Ÿ_íO§Û®[/×}¶ –g£Õýz´ú®QÏ6tÊ.ȱÙ¶ : ÛÍi÷} ×ú Ø&¨ë>ë~”n· Z½.è#lD;m¡Ý~€m‚õd#½/¬¦NƒÕ‡¸š6A«úë~8¿Íêþ@¥R €ï:44„T*M/œëºA\ZõÓ/q©¹öªQ’¸îâ^¼R¢FÊ0 ¤ÓéàYéþË¡Æ<¯G³ûµ2™ †††Ëå£Ôn ¯¬ûƒO'îÃfvåÎ;ï0¸v mP¯çr)Ú†þ “÷p£º_( i,Ë Â<¹®„vo•AiD¯[/Â6Áà³Ömõ]£žmè”]šÛ¶ : ÛƒÃZ÷ j›`ÝgÝï_Ö¢Þ¯ôØ+é+XMÝ`›`ýàûÂàÓÎ}ØŽ~Àºß˜¾eÎ|>ãÇcnn–e ÄFÆÃ0Œ@1–O±XD:®‰ç?D¯ƒmÛ¡xÔͶ/·o§hv³¶ZÔ¼JÌa•|>¨óâ77Û9t]¯å £ÙýºZdÿ……”J%äóùßÃí–»°î·F;u{½ê~½óuê>lf;Î9çƒiÚ†èõ¼ÿþû›æ#Ù†~hÔËËjîÁfû7ªûíN/ôk›`¹ëÖ‹°MЩî×£Õwz¶¡SvhnØ&è,l,O»ïƒÒW0ˆm€uŸu¿1ýÐ&èD½o÷ØÍú :Q7Ø&X?ø¾Ð¥±ý€u¿õ²÷½ð(¾JAu]ñx<˜$X.ˆüH¦i†–ê䣽B§ w2™¬¹êh¯fÛ—Û·“†]×C“™f2èºÞrEˆNÖ«iZÍ‹‚LËåjF)¶²3âñxhòU#4»_[AýÔshšŒ”h4ú«Þ¾õÊ-×¼×Gï°î/O;u{=ë¾Ðný«G3»r饗ëÍ.Èòr¶¡™]ˆ–½ßmƒa í°qlC¿´ „vë_½ý¯ºêª`]½ºoš&²Ùlð;’ÍfWÞ¤_ÛÑëÖuŸm‚åÙhu¿+y׈چNÙ ¹m`› ³°MМvß¡¯`۲̺Ϻ¥_Ú¨÷8v£¾‚N´UzµMÐlÿhÙûÝ.|_6Rb;úÁ ×ýN· N[ÑUéA’É$,ËÂØØXЈ0 ñxаî¯îxÝ*G¯ÒÍ~‚õ:ÇFc#؆A² í<××j_Öýúô}¨Õf¨n¾â-.ãݤQül•VGtòXÝ,G¯²eÜ×q½aÝ_Ù±ºYŽ~e­¯¯qçÙva-Ž×ëç]OØ&èO6BÝg› »Ð6ôÁ.¬Åñzý¼ë ßúÖýÕ¯×ÏÛK°MПlÛ@»°¶°î×g = !„B!„B!„B!ëÃ)ÝÎ!„B!„B!„B!¤ÿ¡ðH!„B!„B!„Bi „B!„B!„B!„¶¡ðH!„B!„B!„Bi „B!„B!„B!„¶¡ðH!„B!„B!„Bi›Óºõ`ii GŽév6é¶lÙ‚ñññngcÝ™ŸŸÇ‰'º Bz†Ë/¿ÃÃÃÝÎÆºÂ6!µLNNv; ëÎââ"» Bz†ÑÑQŒŽŽv;ëÎììl·³@HOÁ÷Bû !@ûm‚¡r¹\îv!Öš?þã?ÆÒÒ¶mÛÖí¬¬š;î¸Û¶mëë2;v ÇŽÃ5×\Óí¬´Å-·Ü‚W¾ò•ÝÎF[|þóŸÇ-·ÜÒíl¬;¯|å+ñò—¿¼ÛÙh‹A¸ÿhÏzƒcÇŽaxxú§Úí¬¬+ƒÐ&„û {6e¸ãŽ;ðÎw¾sÉ×]w^ò’—t;ëÊ ØŽ•2õt¥¬æ·¾ýöÛñÏÿüÏÝÎúº2;;‹|à¬Ú¿ÖàûAÿ¾¬†h ¡/b5¬ô·Þ¨}†W^y%ÞøÆ7v;m1õzêé ´;¾ùÍoâÇ?þ1>õ©O­úÂãñœsÎÁ+^ñоîP™™™Áääd_—avv³³³˜žžîvVÚb~~~ ʰ9ÿüóâ·ë÷2ОõR†Æ ´ áþÞ Bfffº…®°uëÖ¾ÿíVÊ ØŽ•2õt¥¬æ·Þ¨ï×\s͆»?X'6+ý­ù~пï«a#Ú‚Aè‹X +ý­7j›àYÏzVß׉A¨×ƒPO¡Ýqã7âsŸû\[ÇØÂã 055…-[¶t;mqùå—Døž~6¤ÿ„ûöŒö”ûoìÙ ”lÅv¬”XO7êoMZƒubã°kÒ:ñþ„¾ˆÕ°ëÕpÑEu; m3¿õ ÔÓAhw\|ñÅxÁ ^ÐÖ1(<ö ý~³Àððð@̰㜓Þaî?Ú3BÚcPî¿A°gƒP²qÛ±R6b=ݨ¿5i Ö‰ÃFü­IëlÄûcú"VÃFü­WÃæÍ›»…¶„ßzêé ´;Î:ë,œsÎ9mã”n‚B!„B!„B!„ÒÿPx$„B!„B!„B!„´ …GB!„B!„B!„BHÛPx$„B!„B!„B!„´ …GB!„B!„B!„Bú»Ûˆ°îÂã®]»0;;[wÛÌÌ ®¾újlß¾ûöíÃâââªÒBzŸF¶€v€Û„ =[@;@ÈàÀ÷ƒµÇó<ض Û¶áºn·³CH |? „ll$l+i‘xÝÎð:â¬0}®Ûް®Âã0??_wÛÌÌ :„ééi|SSS˜ššÂää$n¸áÌÏÏãðáÃ+JCé]–³´„ >lB€ÎØÚBú¾„1 ¥R)ø‹E8ŽƒT*ÕÖqs¹,ËB©TB¹\F¹\F©T‚ëºm›váû!`›`Pp°2±l¥ñ\¬L ³Vxü•›Î oceB¥IßìZÙuÒ$"iÔëfÕÉ{§[„ë"Œ£GvåüÍlÁZÛ8zô(öìÙƒ;v`jjª+×€^`Ïž=8qâ.»ì²u?w¯´ ¶lÙÒ°sƒÀüüÃN°Rñ**칚µzœÈ>9Z¶²Qù?³Lúhþ›?*ŠØg6HoG¶*ùJ*çJWŽ+ùp•o»ò‘ôJ•ë%é=å\êõ´•ü*ËêzŒ=ï=p_ûÎwð¢Í›Ñë"è°M@ˆÏøø8<Ø4¬Ù sþùç³M@ïõýà•¯|eO >Ï@Á¶m …¶…ºx<Ž\.‡±±1ÄãñÀ£R<,ëáº.2™ òù<’É$\×E,C.—[Q~r¹J¥ ÄL]בL&[>Y{ø~À÷BØgÈ>ÃNõx¯»fbœ¡,[•´F´ŽòWö÷hMÒ«Bea!QÄ>Iõ"Œ†:U…?;’Þ©s.½Rõ¢B¥9Ÿ†ª7¢Q9昒ÎQŽí¢êÅèTÊaW¶*ûˆX)LT¾ó•}r•s‰Ø›`íÝ‹g?öðío£6„ðH!„B!„ÒË8ŽƒX,Z§ëzàa¸Z²Ù,LÓ„eY°, ¹œ?ƒQ<G:†aÔv¤lÓuÅbqÅçVŸN§áº.,Ë¢ðH!„ô"–©-…¨çžJtÆh¸Ïz8Mö/ *ô9 öu”üX¨Š’ªPi¢*ŠP)Â[¾€§z Jzõœâ(ùRר/$º¨ €rN[É‹šG·’½RfþŸÇÂÂæææÍfaÛ6b±XݹMÓ„a˜˜˜@"‘@.—ƒ¦iuEÊåΫ¢ëzݲ²½` !Ý…v`ý±žh>¡W'm½p¤æCŒzèÉ܃å8Ž’‘ãg*ÇNUÒé¨ ?ªî/iíHza¡RÍ›x$Šgf¾W¢ä%WùHYø"¡ˆ‰Êv£r¼Tå‡/Æá{eŠ€š°PÙ_B§&+i*ßÙÊñ4øÂbUAQÊT¬CZfFe[©r.³’. àï¾õ-lzâ‰eïfô„ð(á ¢½ÎÎα[ICé_h!m!Äg¹zN;@ÈàÓKm‚R©T#¶ûiâ4Š„5- -¥"!SU Ã@:ÆÜÜ<Ïkxì¹¹9‹Eèº˲066Vs¬åˆzk¶ë½I6½d !Ýv {ˆp¦.G‰z8Ú ¶UA/‡Z!°žw¤xŠ˜õ¼Tó$û§P EjVŽ?9_aÒ„/Âé•óÄ*ÛÅ[Ñ‹ì_‚®TæWC­rìLåÿt%]UÏD˜« ™IT=<¡¬ƒ’¿<|aQCí|˜Ç•sȶ¬’^ 3k(e(*éãè =!<~éC‡aii pàÀ cçÎ+JCé_h!m!Äg¹zN;@ÈàÃ6oÄÕ vžç!—ËÁ²¬šmÍŽiÛ6r¹âñ8²Ù,æææN§ƒ0­Íò=ŽŠëº+öš$„¶€B;Ð\ø¢Z;ûGÃÚ‘íÍÒ˲ˆâ§lj|K: *!RUáQ-øb] U¯B É*áIÅ#1ª— „7•ãÈüŒ9ø^%½©äGÄÀ¢ _ÀK#,ä©aTµÊ·x4Ч£*&F—K¨?ÿe=LT=(ÓMÒ¨yë”èôÐÓÓÓØ½{7víÚ…ááa,..bzzÃÃÃ+JCé_h!m!Äg¹zN;@Èà³ÑÚžçÕuâT±^:u½( ÀišÁq$çyÈd25ÇÄSRB® º[oÛvpÌzÞ¹\¦iBÓ48ŽƒB¡ÀùÉŠÙh¶€R í@gˆz$.‡³Ì²„%Õ#ÛdÅè|ªw£ˆb2/¡TB¦J¸PÕóOÒ¾ fU>ªóЏ'e•} øÂ£Q9®Ú"I+ÇARRÅ«QÐQõD¨”uõ¼Cu4öh¬7̨³ÿJH7Ù–Éd‚È’oÙ#¶Îº ÷Ýw_ÝõÃÃø馛0;; ¸üòËkŒB+i!ýA=[@;@ÈÆ‚mB°z[@;@È`Á÷ÀqÄba?Ã0P*•BÞ‰õÒ@¹\®{Üb±ˆD"Q³®ë(‹u=“É$,ËÂÄÄ Ãæ˜ÌçóAñ€´mžçÁ4ÍñÓ0 ŒŒŒÀ0 8Žƒd2êä"D…ï„€m‚õ *¶šÞCXPOBÀô´JšªÞsõ<"5ø‚›¦G<%LªÌ7(çVE8™3QæT”cHHÑh¸Ñ¨YDUd‹ %ï’¯¢’WÕ+0*DŠ'£Žú"a´”F}ÁðE|­”ðèy@¥Í×hÛ@z< ¹Ý4„þ…v€ÐB|–«ç´„ >¡MP*•:–.›Í†Ä=MÓP*•àºn XvžÉR©Çq‚ª†a„DÊl6‹x<Ïó iZÈ3R:³òù<’ÉdÝ4„¬”` !Í¡hV<Úr¨ VQ¯='²NûPæ)”uªB¤¥œ[õ T·‰¸WPÒ‰ WGXÜK£:d:’V<QÉŸ‰æžƒê¹$j#qPk²o+4 ¤_(N§;7?v.TÚ‡Ñ6a”›o¾_ÿú×1==½êÓõœðH!„B!„B:‹®ë+9¿œPØŠH±‘BY;†àÏý׊c4Tª ÎG‰™ "6’¦$”ª«Wæ=”ãÕЧ:U<%­|TF½²œV¶«Ä#eïI§Á5ˆŠÍÂFÊøÙXÕ`càaXËL³aÇqà8NãbŽ4hcyž‡[®½oøÖ·ü|Èùá1N×xUZ–…Sïº #>ŠÿïyÏC;œÒÖÞ„B!„B!„B!¤çðV°ÍQ>2ß¡ˆ‡ª‚¢êüŽrœž„ªÈ(b¦xF…CU>áQ2Uê…+Õá{L¢…ôË ´ªPYOøT) 7Ú¶/6Âqšn—ˆx|ÿ~51P ©ïº.lÛÆkï½×÷jÌd×\7ä#€T*…t&ƒ‡n¿Ýßß²€L÷ò“8ó†ðWŸù Ê[·¢èñH!„B!„B:†ÌMI!„îb!õ¶·á‘§žB©T“»wcûâ"<ÏÃþçмòYÏ•?Žÿßÿ‹ïüàm]z<B!„B!„Ž¡iÚ²sHB!¤=ÜÈw=œ:é£x‘´øBžx(Š)€øs*µŒ@uF —jÂ%“uÎ }šÅú‰ˆM=j˜Ò:4›#–ŽÅï¸Ã?†x$ ÕeÇiŠõÔ¿ý[Ü÷ÿý‘ìxH$xæŽ;7=ê{4Ú6þý©§ðÑ|ï*±ûúëñÈÙgãûÿðþ9lOŒã/^ÿz¼ô÷žmã›§Dz011ç}ç;˜}òI›œtãßþvÛ×–Â#!„B!„B!„BHQOxÌD–EZ“𨂇æBdá¨2ß¡†ê&Âó3õC§ªó7FÑ–Y^-žç!“É4Móï·ÜÒü ¹\ÃMŽã4ÏÍá§_ûšÆÔ²|¡Q×ýcZຸ婧üe׆†üð¬•cÿæ+^§Ÿ:æÐ£â /~1þßô4<]Ç«Ž<K7Ý„“^ärØôÐC½ï>lyË[0úýïãÞç>÷~âÈÙ6Nûññ‚W½ ¦mãŠ×¾†çaÿÛߎüä'xçg>ƒW½ÿý@<ŽÍ÷Ý×öõ§ðH!„B!„2àxžÛ¶aÛö²£ô !„ÒŸäP+(zR•ÿÅ;1ƒ°§£NUÒ©ÞˆETçl|aRGm¨TµáT»Áu]8¹œó(:Žƒ+o»­ñlÛ_Ìd€D"ØÇë†BE¡d28ÿ»ß…­ëÕãxžï}X(àäŸü àYϾ/BVÿ|Ìï{øõsÏõQ)K6‹…w½«íëOá‘B!„B!¤‹Äb1 Õ|b±Xhþ X,†X,ÖôX™LCCCÁ²çyH¥R ö«96!„Bú›¨ÄfW¾ ðÅHWY–uâÁ˜«|§á‹‰â¹(b£ÌáTÅÆl äó@©äó¸öu¯Ã\¹Œ?úüçqéÒ’ÉJ ÛxÐu\ú›¿‰gÿÝßáÂßú-]‡¡ðH!„B!„Òe Ã@©T >ÅbŽã •JµuÜ\.˲P*•P.—Q.—Q*•àºnÛÇ&„BHgqÐ|ÎFo™eAH7’Î…/ Ú¨z<ŠØ(HHUÁT–[ ‹ª·f-°, ×=Z3ÈJæIüÄž=¸äÁý(’&ó…@À'ü©Ì—ÛÆ­?ý)LÏó½ ]H¥×ÅÍù†}™DŽã`éóŸ×»p×]wÁI&¡/,É$®¼í6<¹mîú·ÃwÎ9ÿxÊ)øî/ÿ2ž{öÙ8}ûvXn»òJìûßÀÖ½{ý<Åã@±¤ÓÐuŹ9 _t‘ŸçdY4euÙ4¡i^ðÆ7úë²õ$äö ðH!„B!„Òe4MƒišÁ'#™L²¬¶Ž[(L&ašÕnCÓ4‘N§[:¶ã8 ÔÉvÛ¶›nghWB!¤52¨ÎËXõ‰êÔYÔ 6ª"¡HP²¬#ì)‡ï¥¨b,³Ü5šÌÁøßwîÄð3ÏàþÛn« ‹lÛ†ã8¸æ¼ó?9rÄ ?]¥Íãiš/4þ:×ÅcÛ·ãäŸü 8t›z€Ÿ=ð€¿Ÿm¦‰Í÷݇cgœm? ]×ñË.±›oÆ%àÿ|ë[˜(ày ÃÀøOàS§ŸŽ‚ëâ}'Nà”sÏÅs_ûZœù½ïš†oïÛ‡¿ÿÌgËÂÖÿò_|aѨ^}MÓ077W?ä«JTÌç×ü§¡ðH!„B!„Ò€B¡€B¡Û¶Q(àº.2™LÝo5Ýrû´Ê²IË iZÝóÅãq”J¥†û9Žƒ±±1LLL`bbccc!Òqœ`[,ÃÈÈ •9І††Ëå‚ý%´«H$PæI’ã 59 !„N=QRdµè0 õé/äU!R”F´’¾ÙòšÒd€T&“Á=ü`Ãíÿûºë¾ð…€Òö2 ”˸÷–[°tÞy8çk_óEÃD"]×ÅØØ<÷ÜÊEòEÈþæo°éöÛqÎ/üà¼?ú#<µ{·?G£aà«O? CÓðƒ_ýUœwê©Ðu–eáámÛL&ñ±ï} 0*âáíOûÙøëï|ûÞ÷pê5×øÞ‰Žè:þøÀÜÜœ?o£®é4V…¹þÁn)<B!„B!„tÏó`ÛvðÉd2( H¯¶“©B<‡eYC&“ ¼Åò‰D¦iâøñã8~ü8LÓ ‰…òÿñãÇQ.—‘N§‘J¥‚޽B¡€b±ˆr¹Œ¹¹¹@„Uó¤†?³, †aq„B©%:›Å_Œ‡¾ým PÀüÂ/à‰w¾…X ›Ÿ~¼ñøóßþmxŽã{,º®ïMX(àÂ7½ ÿüâã/xÀ_—Lù<¶nÝ WÓð;ÿóâÉmÛ³m|kûvúÜçpóÝwãó>O×qåáÃxÅ?ýt]‡mÛH$ÈV™ªÊÞüW…¿þÚתùO&}Ñ0BóIÂ0BžŽýÀiÝÎ!„B!„BH¯’¬3_ŽtE¿ë¥m´OÇqB^€ß9¥i­Ì Ô˜l6 Ó4aY,ËB®–,#N×ú,Ë‚ëºÈf³ÁùÓé4ÜŠ€|BÛ-Ë ‰‹rlÃ0`šfйÇ¡i,Ë ®™ú?!„²Q‘y›á_@‘§,e?~ÈVU$Ôá‡Q•V…YI/Ò^ëO,ƒaÕ¶Q&šoÐÎåðàƒâ-Ÿü¤_.σ¦iAd‰ø3Ï`ôûßÒ?ð]O<ݹ~m×.¼lÛ6lzøa”·nÅŸŸ}6μá¼îÚkñôóŸ©sÏÅÕÉ$ÎÛ±ÃõÇ?·ãàæÛnÃo.-aóÜ<]‡Viä¡w½ ¿uÚi8㢋0mšÐu÷ßv.Ú¾¿–Ncxx8È´…†¤G®º´É¢BãÌÁ¸ÖÐã‘B!„B!¤Ë˜¦‰r¹úÄãq$‰¶çH4Mù| ˜››C6›…mÛˆÅb!¯CÁq†=u]G©T Fï˺èy$Tª¹LX¯x<Gæ¤ðH!d£}*™êU–mTEC¯²,^Nåcõʷx8Ф¥U>²Ü ñ±¦½àºpžçáâ‹/Æë^ô¢ äêG_ò<ñÎwÂ4Md+¢Ý·¾õ-`hð<üô~;.» ß½ùfüÒÌ þþMoÂO>úQüÃè(N?ýtxF¿ÿ}œ}Å@%Dþ[®¼˜›¼÷?þw?ÿùØöš×àg_ŒL&ƒX,†D"Û¶ñ¾Ï#©výÙŸÉ$ …†††ðÃ+¯Ä•¿ýÛþµ_«ñLÔu}åí›d²:¿dŸBá‘B!„B!¤ñ"\)2§¤ŠaH§Ó˜››ƒçy Ý®§årˆ¦äA¼ !„Ž*4Põn¢¢­¬|2Y6Ð|>Gë8gc$ƒ_ŽÅ\.‡\.‡o=öþõÀFËÂ}à<üÙÏ"‹á¢áaxºŽòñãp|õºëP.•pþãcÛ?ˆ­Å"’É$.]ZÂÅø‡¸è™g0”JaÛ=÷s&¦Óé ¤ýW¯½ùR ×~èC¸ëÔSqÊ%—Q#NÉá‹. …@M&“H§ÓxÓ¾}µÞ‹í0í! „B!„B!=ˆx#®Vó<¹\–eÕlkvLÕ«Q=V,ƒã8A'\Ô[Ò¶í/ÈF¨áV-ËB¼“v„BH£>]ÔzAªËѧn½§p|™4k>{ çù™Ó:4—µç¶ ײpÇm·áÜK.Á/v`Ûxø³ŸÅèÓOã‚cÇð‰ÑQ\zê©ðJ%üÜŒS¯¹}ñ‹8ç~Á/+¡SmÛ† àc_ù N_\ÄÖ׿ÞMÈfá8‰<Ïç^üb”J%”J%¼ñýïL3Èc>ŸG>Ÿ¯iãèº KOªPx$„B!„Bé2žç\òI$Ð4-¢«^ºFsÉÜŠ¹\.”Æó(<B!­¡øÞŠQéKžªjhU!Ý íšá8þGA×u,îùøÇCé}ôQÌ€ëâœë®ÃyGâé§Ÿ†fY8zÞy8óäIŒnÞ Ø64MÃùwß'6mµ££xîõ×år <†§>øA¿­³°à ŽJ{Ã0 ‹Å ¤ëz5Ô|2 Ã0‚e¶SVÆiÝÎ!„B!„BÈFÇqÄb±Ð:Ã0P*•B#é륀r¹\÷¸Åb‰D¢f]×Q,ëŽÒ×4 Ùl™L&,=Ï B¿@©TB,ƒeYÐ4 ®ë†B’µB<G.—ãÜŽ„BH ¨ÃŒtø!Yå)ž„’UDF#²½¸®ë{ Ú¶>Ô4ñèü¶þüÏ£P( ë8ø¥gž©î`šøû'žÀÛü÷;1rçø±1Œ^{-¶æóÐ^ó,Ù6¶½ô¥@¡MÓðä߈Mûöáô«®ª†(5 Àu¡i^ù¶·…3¥´94MƒmÛ°, átšÃ0ZŽä@ÂôŒÇãÒÒöïß«¯¾Û·oÇž={0??_“nff&H³oß>,..v;ë„A;ЯýCÒ7ÐB€Ölí!ƒÍFj”J%”ËåšÏÜÜ ÃX6*:f³Ùв¦i(•JXXXBˆÉr3‘0™Lbaa!/¶°° ÃÀŠÅb°]Â¥•Ëåšc—J¥p)Ç(—Ë5ë QÙH¶€RŸbœÈ²ùV‰#2U‡ïý¨z:vdX놗½&½”žXày8ö/ÿ‚‰‰ ?Ü»„ZÂ/|!nùЇðöÉIÀ5wÝå—Ýq`%“05 '_ò¼åâ‹qñ–-xêãÇžO|·oÚ„g>†wíò½]ð<\ð‘`Ë/þ¢/6J›I×Cs1†ˆ¬O§Ó Û!š¦Qx\%=#<ÎÌÌ`vvïyÏ{pðàA c÷îÝ!ã033ƒC‡azzÄââ"öíÛ×í¬B:í@cr+\_èv†I[¬µÐ춈5…¶€,o h|Ø&è,º®Ã4ÍàÓ š¦éyFÊvvÌ‘µ‚¶€²Qì@Th!RíÇ1ü¯#,4vBxt]wýîï†W6ïîgØ À¶qîç?¿ºür|ú†ªÛlzâ œý‰Oàì×½.ØíÑßù|æ¥/E"‘À—>òlú•_ ¼$u]Çößû=¼ðØ1œùÙ¬/jZ8|k´m³‚Ш £ÚyzFxyår¯þèGýp¨žèzþ=¥†SUÅÆtdæÊè2YWzFxŒ²´´ZžŸŸÇââ"&+.¸0::Šññq9r¤ÛÙ%„¬ƒ` Q"Z­d}T¬ô”ãg”õ"dy‘õªsìzéd}=J õ=* ¨/„º¨Ëd}=R ®AªAzÉKôúHÞÕó¸ðE·h™-TEÀœ’ßLå¼TE?§².UY—«×®;W9žü%}¬²-S9Ÿœw¢ò«üï)ËCF*Çž¨üŸQÒçŒ)ÿ˶‘ȱ‡*ùÑįº _}ыР‚- „´j hÙ˜ r› ‹ahh¨áG æ\$d£2ȶ€ÒÁDûؤÿ ðFÕ°ªQ½NÍœüà7¾Í÷Ý^©„Z}ïïü^{ÅJ¦­ ͯ>ïyþáqúcáÎ;ïÄÒoþ&~ò‚àžmÛpôèQ?]±ˆo=öþ\æy´ml{Ík|FÃh.¨†U¢‘´nÎnINëv„믿333XZZÂèè(:„ññqìܹpâÄ ÀWÇëÅs&„ôƒhø"Þd›ú˜tQ“Ê: *¦•ýå; _T’Ç¿ùÊvUq.SIÔ5ªx&#ª %½xÑyJ>íJy¼Ê·4zR•ÿÊ·QÙž¨ì«–Uò-ç’‰±5e½ XYg£*Hf”*ßfå[«|Ë5}bÊõSË’¨|ÛJÙe(ëÈ~rÝÊÿT'ùFå74¡\ŸReY¶›•sH~Ó•ï$ª±ûåzÊv³òÉUÖg*éµÊqäx…ÊùôʶO}ë[øÑw/{zA´„•ÓÌHçí!ƒÍFjhšÃ0–ë0N3¤)Ùpl$[@©O?Ûø¾ÜlÆÒÿ%ýIªý‰ª§£ôIEçwT1°<¯¡HwÕUW¡|èPu…ã„æ||×¾„_ÞóÂÛyÿýxfx§ÚvÕ‹±Ù<={œž/¿ür¾Ûôðð0æçç±wï^ ·}ìþð‡˜™™Áää$¦§§»]TBºÆ¡C‡pøðáꨒc-í=z{öìÁŽ;055µnår+õQ)â•pcÀ†/"‰H'v²…ªX'b˜xö‰g¡¬±2W9®ˆdväœNäøæÓFU€Ì*窢œ4M¤$e°•e¹@U(OM/r\ ÕQ\â1(çôTÅ=õ˜âÍ(çN¡*rê•ã™JE¬‹WÒY•ë'åÕPõØ”2,(å—ë¬)×'ƒª™EU(áPÎ)¿ÓBeÿdäQ'WG®•*ßi„Ãf+ß"D Ie½°gÏœ8q—]vz‘õhlÙ²ìvQ éóó󘙙ÁÑ£Gk^Î{…µ´<òöìÙƒññq¾ ÍÌÌ æççÃ!´zˆµ~?¸å–[0??ééiŒwµ¬žçó%6£ž0é8´ÊHp]®ë6=~+Ç!ƒ ßø~@û ׶ϰ•)‹¤ÏJÕ9å28]%*46±ÐqÂÞ‚–å‡6­Ãà-¡‚xÕ¹ œëY8ûé§ñè‘#@Þïû›ÀßìÝ‹›_õ*lû«¿ÂsÿÇÿÀÍ7ß gt4¹¡’]×ývI!2±Bu…éé鎴 zbŽÇÇcii)ÔàWéèä¯õ\£»=2‘Ò>ƒn¢ „¨xUÑO<Eì‹z8:¨zÓ‰7Ÿ44T/7 ‡ªUÒKc'^@Ü$´¨_&ªv•ó&QYe*çÍ¢ê9˜­¬7à{çɶ|e]²²>YYWRò6WYoVþ—ãÍUÖåá ŠÉÊ÷‚r9^¼’^WŽ1§\½’NGXA4º^Ý®5XO:Ç ÛBHk´j h\6Z›@Ó4xžÛ¶k>ŽãÔÝ'•JÁ4M?~ǯ›6‘HÀó<,,, \.#N#•J…æ‰, (‹(—˘››ƒmÛ( ¤Øh¶€RK¿Û§Åtª“€º_TTl[Ž‹¶+dÎÆ\¥Gpl,XþŸ>ŠMûXU,¬ì›©ÌåxöSOá‹/ÆO+¿ÃŸïÚÓ4¡ë:Îúû¿tß~è!h†Ñ0¢B FÆãaÇ;“ɬòHd¥ô„Çc+.Ñ2òèÈ‘#!c1;;‹;vt»„6T;Ñd(ë¢^@x^@ñDáPAñž¡QÁLeYBpŠ÷ ]Y§†]ˆ£VUÒŠ—_¾¨'¡SeîBUo=KÉ P@Å3RB˪^~’Ÿx$²¿*öÉøê"ÂHš|d½Ù.h‘oÒû ª- „¬Œålí!ƒOOµ 2¨í5”°ÑÿièJ,ÿx$M¡ºçyp±X¬æôõ<Çã8(‹Ð*¡Æòù<&&&BilÛÆÂÂBÐÙ'^‘…B!ðŠŒÇã0*^†aÀ4ÍÀû‘nÓS¶€Ò6ŠÇFÒ›D7ë¨ðè8þÇóªs7º.Éž‡ó ¿±oîüìgqñ[Þƒ»ÿýßáxxÛ6lÛ¾çœ<‰Ÿœu.zæÜ @•´OŽÿüÏãømzD= ;‰eY¡0óž×JÐ[Ò zÂãqrrÃÃÃØ¿°nvv·Þzk(ÔÁÔÔ:„¥¥%À0<<L"Ké_ÅÔólÂaKÕ9å[>Ò?!¤Ì×õdQú0TGñÚ“yU/>9–‰ê¼„ÙÊrR9–Y9¾š^õâÊGm6ˆÀe}õE@NM„A±„öhÅÐ2ØôT›@½êGoð¿|¤!ŸFu²ïèþLÓD¹\®ùÔ {jYVÍ|ŒF¤ÃNÄÃB¡€L&|<Ï u¼-7¯$!ݤ§l!¤+ º( :°¨ŽKŠ6$2ÙÊO D1pݪ‡£ú¿ãø!WÇqZùßq”J%<ïk_ÃOŽcš€ëâù7ߌS_ñ \ðªWáü7¼_ýþ÷q|ëV<÷‘GÇCm‹.¾¿å-!1r­ˆœŠF‚P·7ðE:COx<ŽŽŽbzz333¸õÖ[±eË,..bjj {÷î ÒMOOc÷îÝØµk†‡‡±¸¸ˆéééŽM"KéýnÜÈ·„8ªy´Z{6Êv£²ŸÌ_(ó;Š€Tç74•uâáGXÔS½ UTÓ‹8©¡Ú°ÑQõZÏÇ(<ô0$«¥ßm!¤3´b hlzªMÐh¾Ùཅ4«d¹Î»F£ú&áÎé5zÊBºÂ ÙÂýuA•È¤É ‘ÅÔþº£ŠqjÈÔÊ\Ç.¸ÛdðR*JáÉ“(&“0|÷Üs>R*aüÒKñ£ .À»vÁ²,”’IüãÐlMÃõÿ84M †R#+¬5…BÙl6XV…G×uC¡W%Ä=YV%<...b~~ÃÃÛ|yjj ;wîÄ‘#Gøett4”fxx7ÝtS0±åå—_Þs†ƒ²zúÙäP I* z1ÜeÅ4ªÂ¢„QPçFT·«¢£ œV×ò4ü¨êe¨"Þ“Ùéµ×²Vô³- „tŽålí!ƒÛ1 ¹\žçdt”¿^U) …š{ÒIh !ƒdd %•h5(iÔhf‡jˆeŠÃð=- >ú(î¹çlÓ4@ÓÇÁS¯}-Ç3¿ýÛø‹W¿?xÞópò ±åsŸÃ/œv>~Î9ø¥­[«¡Ù ïüû¿G.—«Û¾XKѱP( ™¬ö|Z–2Ëu]躴“Ça »ºÆ4gffpøðaìØ±#˜¼õСC!·æññq¼ç=ïéÈ$­­ ™;Û¶aš&2™LHÝ'¤_èW; †TqQB ÈØ™¨ç£^Ùî V`ÔPÛ˜ÑNQ!‘ã¶ »H/Ó¯¶€ÒYZ±´„ 6¥M iZÍH|Ã0By¦iBÓ4d2äóþÄL&<ѤišÐu=”Æq¤R©`™~a£ØBHcÉxË,‹—£Ú/¨c¢#öx|1—<_ûÁðàÖ­~Ÿ£a¶þ¹ŸÃ[?üa$ŸyÙ{îÁ.» g\r 6=ç9¸øë_Ç¿òüÊÄt]G<î»7†b±¸ö×Mpå-\6×uƒ4âí(£šÆ0Œš0¬¤³4œãqffÀøøxPY±ÿ~ŒãàÁƒ¸á†°¸¸ˆ™™™n—ƒTˆ¾¤Èdò„µG©Êzµa !QÕ‘JQFu¾F½Îú8Z‡õŸB!„ÞÇó¼`®¡zŸh瘦i(•J°, ccc©ëeP,aÛ6FFF011‰‰ ¤Óéw!„BÖ–¨ÄåF¶Évy’Q;%ôª<Õù…tÚ¹jøoÿöo8õ¯ÀÉ?ù“À+òE×^‹x<Žï}å+€çîÞ :„«¶nÅÍßý.žÿ¶·ùyZ§ªB.— -Ôù++DûBëé%*Qñ’t†ºKKK8pধ§Cq’:¸á†B®ÌûöíÃüü|G¼IûضŒ”Œ*ú„µAGaïG©}RU[1*!JºüX–…x<Ž\.šÐ™B!„Ò{”J¥–Ò•ËåàÃ0°°°Çq it]¯é€“4Òé¦ëz¨@=ÞJóB!„ÖðZÜuBPû W¹Ìq|ïF•BÁ#=OŒ£”Íâ+¿ò+8í³Ÿ~ã7€R ¯N¥Çñýo~ðôæÍø— .@,—È´:Ô×õ`”0¨BTÛˆŠ†2Ocöµ’F<1% P ë ÔO:O]G‰•<55Z/â¢*:îØ±€ï Iº‡ê: øÊó<*ö„tõçn”F‚I#“?«B£êá(¢c½ÇÛjB¡ÊCTípp]·&ì!„B!¤ñ<CCCp¦iÂ0Œ`îÆzMÓ B¯B!¤÷0á{:ª1 ¤/qUÎ –xæÊ+}GÀ÷|ô<À¶ññ‡F&“A¢PÀé=ÛóÓD±XD2™Äµ×^ T½\.‡úÆ7ªÇéÑSV%Ï¶× KÕE¢Ëõ±Ö[¿Ñéôõ¨+<ʬÑÉWgggÆH¦ð¸¾D+ˆeYA cÇq‚oÆ*&¤³,'áÉ„ÐY„c²Ëÿ‚4:ä(:zGl€x>GCÁ„6ŸB!dc iòù|Šubb¹\Žs7B!=†³Ìr+¬vnÇGÇÆpÙ]wUû‹÷Þ{/pü8~ñÿÿôG„÷|èCxð”S‹ÅÉd‹Å ë:Þù§ À¼”L&1ý×]ëAÙ&QÇ©¨ž!:GµHn¨ïSÒ¨Èö¨ Éd®ë:ÊFF-¿çyuÃÖ¶C]áQÄÅ¥¥¥`ÝáÇ—_~y(­Ž ³º¾H) ÁM"FYGY[äñó“†/*ªÞŽm…H¨ƒŒ’‡ƒêƒyÐçyŒ686¢w§ØþT*Z?è¿=!„BÈ "j¶m7íK&“XXX@:F6›ÅÂÂB(´X¿"aÓä݆Bég¼:˪QÓZ¡ib,æ‡UUmÀ²àU±#l¥¹9À7~ó71üò—ã¾÷½8}ûv‹E˜G@%ä©ëº°,ˉÚávF½ˆÑ娤èÑoAÔYǃsHXWÃ0j޹Q…Ƶp`«+<Џ¨ž\æw”ЪÑõQA’¬-j\nŒ¨Ø ë6jC¡fÉZ ÞŒj8UÕª‹]F Õ9UŽPªƒØgy(Dë=Ð8vy¿#å“k Þœ¹\žçÕ4ÉÛSDU5¤®çy˜˜˜€eYÁïŸÉdÖd´!„BY;ÇA,ÃØØXàÉ822‚T*ÕP€Ôu=£ªuØ !‹ahh¨æ‹ÅBù‘¼¶‚çyÁÐÐPÍ 9H722S®ÅF÷J „2Xxð…G鵉:+4%:Èܶq÷Í7ûÿ»nuG]ÇUïz®¼è"œ¸æÀqðôè(>zì<Ïõÿãþï­·âÆ„mÛH$áíÉd嫯Íh¯g3Úg×,tªüßÈ£ðÛA"*ÊzÓ4Cs[†ÒRâñ8,Ë Ú¥½®óŸžo¸½Ô‡‡‡±wï^8p»ví®]»0;;‹½{÷iæçç±ÿ~8p{÷î­ ËJÖžè<ŽÑÎø¨[ñ íPW½?°CH§QIrÕ®¬SC©ê{?ÊÿªÙ.Ñp¹\®®©~÷;RfUh”Šã8ÈårACBÝ¡üÒÙ$¿s*•‚ëºH¥RÁuë"ër¹GpB!„ô ":zž‡R©„r¹Œr¹Œb±Û¶»&¾†R©|ŠÅbÐ] Òѧëz݃–e…Ê_*•‚v/!„2¨¬¨¿0òü¼ç¬³pÎw¾ã/¸.Jù⤮#“Éà¹<‚‹xÐuQ:áíX Þçb#$<`ÔpÌýˆ”Q¼ý …B0¯­*Bªß–e!“ÉÀ¶ížߢE<¥‰D"«-åÏd2¡C.— FxÉ(.MÓÊÓ“B!dÐÉd2Ð4 ¥R)äiÇ177Dµˆ"#ü›‰’õ¼ Tš ÚÕ4-ð¨4MñxÉdrÕmlÛ¶Ço•B¡€d2*¿išH§Ó=Õ¦'„B:DS3á;+˜-ï~fÿÑ)§àŒW½*œÆó`%“È<ú(^ö²—ùëL}ûÛÈd2ÈårHf³€a@Ó4|ú+_aµÂc%L«®ëh…h›Dœ¢iTÔíÑè:ô@‘ã†Ò¢Â¢ô©é£B¥”çmç¿mõ¿ßrý¬9øÇê²Òœiwª¨+o»²z|нêB „m=tûC0\ýÀG?=ç§0`àè; LÛÞÕë477‡ýèGmåï”f§¦¦pðàA«íGÎÇ|úc§×Í„ÅWåÕpZO=‰ô˜E¯»öu¡0ª"ù§Õ[ðÃÛ…2£ÀDuñŒwœc¯>Vý=£×ÐCHh<öÑc!aPÊZ½PÝ Ç.<šÔÍ)i]Àƒ»?r·/hz@<ò¡G€p<}i;;þë€lûì6QÄú`#ÿsóu||¼­“•Qo¢tVG+°š^D*­„, QAVÄGñüÔ¹-£LÊ](êŠÑ¤óHm“g‡ð¼ŽÍ<ÛA^ÈÕú. Q1²Þ¤Ê½L4¦ºêÙ'u=*8ŠÀTZHYMÓ &Œ^k­Q=S½OUÛdYV0@BlšeYH¥R( ( H$ð|÷»ß]¿šB!„ÔEÚï͘I[Wmßær¹ ,i6› ¯ Ò®\XX@¹\F:F*• Í^,Q.—177Û¶k"rˆG¥|2™ …B­GD X–MÓÇaF(4š”ß²,Œï@Õë’BégœÊG]n©÷:Ú÷ò<Ïö{îb1?­¦ág_ÿ: ÏÃ…'Oâ /ħžýl@×ñ[Ç|¡,›ÍíÃ0š;1ÙjV¼š>wuùþOÞ {Ê©ý”WÜ{EèÙ¿é‰Mˆ#J#}aŽã@ƒ†×o}}]GØ}öîÀãѶmìüâÎÀ£Ñq\rã%¡v„Ú—¨AÃÈ£#¸äÁK|Ð/â%xÀcŸz Kÿm©Z‚’&lÛŠmŸÝ¤üå½ëG¸ÿÃ÷‡¯ÌÕe_ø¥/ø×2W½n÷ÞroåÂÂ5bþ>ÛÞæÿ?æïsþþóñÄ;ŸRÀÉD ß6ìpáâ¯Æÿ p‘÷Ž®¹é œù•3qÏY÷ ñhOþþ“¸âÞ+ð'þ þääŸøª7€{^zÿîãxòá'ñãÿ###-ÞÙõi(<ÎÏÏÃ4MìÙ³{öìÁ®]»°ÿþ¶NFVŽ*8ª•8^1*2J#~çÒY_Ï«QŒŠêí$û½îѳaT +©–_^ Õõ@x¾?²6È#ßFuþF ;ås,÷‰êåí ˆÆ:ªbœØ†nzA7 © zÕy Õ:¯†WÕ4 žçe‘‰­UQNFƒ«Ûëå¡ÙµVã›G½Í£a­£¶&*ð©ƒ%D„T¿%­ZV=Ï Ê$âb6› Fˆ‹W£túˆ½QÒ4Mhš ;+y±mŸÿüçñµ¯}­k÷!„BHßà8¾gú‰Ý}ßó¼ðv¥Q³¨õ§Óé mœN§C!På]¹X,û¦ÓiÄãñ * à¿/ˆG@¸èþÜ“òÉårÐ4mUÓ» Äãñ`_É‹´¿³ÙljÖ²,Äb1 !‘Hðý–BHß#¡U…–]F¤P¢zI›ÀðwàýgœKNœð½“I TÂ)'NÀÌf¼ñøÊ _ÀÖþú%¿^í3«¤ièÀä $<ÖsŽRûÅ.=z).8rAµÌ‘~µË~|™´‚¯8ï5¡SG˜øÕŸþ*æJspï¼çˆýk,\w~q'tøáUá#Ž– :FîÜjŸ™´{âñ8L˜8yæIìºm—/øYÀÓ×>Ì«uêïž ®/Æ*×Á€/ôWsáèŽ/Zæ€Kn¼Ï›~žŸÎó×ÁðÓ"˜¶‰;®¼#Hÿ¶/½ ¿ö‡¿æ§+þž¼çIÿFÉù­y|õÚ¯úÂ`¸÷©{q×]w`ÓŸn‚øÉ€9àéÍOãs[>‡?ÿäŸãQûQ,·„ÿ{íÿÅu›¯ƒã9¸àØøèäGñ‘_þ>{ùgÏyÓsð¥ó¿„^ðQ¼ûôwã‚ýàC/ûþòljýÃÝ<ÚÖý~Z£ 3338qâöîÝ‹ÉÉI:t‡Âðð0ë®#âV\O¤ Å;Væ÷RÕÿFûö"2rA^bäeD<›Ä©/ej(IõÊVÜÍ»êy%žX62[1î‚”Gö·w˲BÞœŽã#7ÄÐJÌl9ö ˆÎ½„‡j8UÕ†‚‡µñp …²•IŸ©ÓÒ©P¯ŽËh É´žó¾Êý)甑Í"¨Ù¶ ]׃‘Òê€5©z,×uƒ:žÍf‹Å‚¹^Òé4r¹\0ÿ‹ŒÔ’Ž—FÀ®ëB×õw¢L0-£¯ÕQTjLy£_¶‰ý•:+!DäSÓFË$õÕ¶mäóyär9d³Y¸®‹d2‰x<]׃ðRù|Ze.yÛ"ù÷<7ß|3~ý×}Ýî B!„¾Å²BÞ‚ÐdÑÿñ¸ßù'¸n8Me^% Ú &ïõhÔæW‘6¶š¾žc£ýëašfM˜ÓL&ƒD"………–#-©ï±ÒÖ—¼X–t€Ê\’@U<•¶ ëú^C!„tÕhiE hÁyAžÝÒH§Êó÷ç¾ùM\U.cä_ÿxæ?Må¹Ëåð{§Ÿ¸âµ¯ ¢m•“e >E´ºzn„ÕRó_™Ebˆö¹=¶ø˜’u/$<ž{â\˜0ƒ~r&nÒo úèâˆãÍÛÞŒwXï€iš¸ñ’ñ–{ÞëQ ÷Þr/~õ¿Š³‹gãÿ ÿ?ÜT¸ ØŠ@h,8{Õ1l³¶arrðä¶'qÎ@<÷ÛŽÿhš†ç¾ö¹¸õ‰[a{6þúÊ¿ Àß½þïúç6Ù›0Þ<®Ì\é{œØðEÀœŒ“?<‰û!|¬ø1Àø‹ðЦ‡ðÒØK 8yáI<ºïQ\ø’ 0÷ð>pÞP*–€ à©§žÂwŸõ]\Z¸ð®‹ß…á]ÃȦ³ÀðÞ?âÀc0—ÃS<…ÄÍ `X8¾oÂÃ÷.ü>óíÏàÎ 0þ×ã8÷cçBwuKE<ô†‡pú÷N‡öß5|üÉã‚ . àlýlüaîqü’ã|=åãŸý8ìŸØx»þväóyŒáxânãH­PWx\\\Äìì,®¿þzLMM&''±k×®š«dmŽaµÃ[¨çu–ÎòFs$ô""šE_$¢öªÈêºn(¼¢”¹ÞhkM&“©+$ …`Ħ䭑 lYVͼ²’rDÃ,"TÔkЬ ¡D8¬*P ÍJºµÇ ‰^RXþêw>ˆ'2©r#äþ‘o!ÚéÑl»Ô;Ù.÷¦ˆsbËê "Á\F:«%"ÊIH(e²kÕÛO:*d9NC×ud³ÙšÎÉ¡P„Y¹Ö"а¯–O1¯Ú9žˆþr µÞŠà*⩜ét®ëù”P©š¦¡T*…aÈ÷JÃhG;ÔßüÒK/]ƒ»—B!dÀhÔ§²Ü„†Ñ0´×U.J=/€è»³ºÜhn½§+¿Õ°®ÙV® ªƒ£ê Ýèñä"clllÕ!^ !„n!=w2Ô§¢{ðû[Nã8þÇu}OGåYùàƒÂ{rW[BCÈãqÓC›pÙ. –¯ý굸òŽ+!sÛÃÛpɱJèRxËo=xÖ[ž:îüÇ;1|ÿ0®Á5ØuÇ.ß[qd6üg¸è?.‚éšxøú‡qí÷¯Þ 9ÆÝ¸ø\rî%¸Ô»ù¥<~ráO Øýï»ýЩwŽo*½ /ÅKqÆg@×t¼õÒ·úáLÓ²ÀU?>}òÓ¸ÿ™û8ðô?<ýEJKiàÞ{ïÅ_~ó/ñ†ÒxæÊgpªyª¯{ÀÉwŸÄßßþ÷ø˜ñ1Ànto„eYXXX&€[_t+ž9óÄõ8`÷ù~¿ ¤ùçO%R€Ž ý3Î3£ÒÉwœ„û§.\Ç…ë¹pßæÂ½Ù…æi°l ÿû<´ð’É$r¹\ ¨Ò'œJ¥ðà‹ÄvlG<G*•Â߃´á;oLLøWJ£išHØ ü~ì÷1‰ÉUßûuC­...FGÃ“µGõd‹vt«bƒŒTEñ4jõ`½Q'——5¤¡:š:?šªR^y BÂÄ4zQkDT̉®.«¡å÷2xžxl¥R©Ðœn U¼¥œ2¯[.— •[B5б’¦iß"Räóù`»Ü*Ñ’dylTÃ{»•O¡NºN0U½ïd¹Yé\ˆÞ÷rÕŽ õWÃ|ªßr«çˆ†±P{¥Ú-¹¿ÕmQ±QF/«çó¬Å6Éÿò-Þ™FUêqThl5@UM&“xÎsžÓöDÑ„B!¤}¤Í[oÀ4§e€®ðÛÙl6ø¨‘IV‹¼³¬ä82È®T*…>2¸ðèÑ£Á;qz9BéWÔ½è&VЯèyá0î® Äb¸ò¶Ûpñ³~wŽŒøÑ*ý_7=ê?SM( xÞ>ç‰çÔx0†2é!$4½é¨ÿO%|èðýÃ8ûÞ³ƒíÏ}乸ðä…þöpö#þ¶r² XÀÎÅÈ"[Ïq\y啸îÿ]‡mŸÝ†Rxü•cø‡Ã¸*}6?½ϺùYÈ#WåÕøñi?²@&Ç.8Ìüþ#РaéK€<ÿæç#‰$yÙ#@J A‡^õPÌöÌŸù¢_Á/Ë >ðŒo~Œc¯:Vu Ò€<ÿ#øÆƒß€«¹@xxÛÃÈ2þf{êßú¿«â¸àº®ž5í{wý‘Iàú{®¯ÀŠûs2J?ê£Ö£°`ºÉí¿r;\T£«yžô'Ú¶ã[ý¤jT qâ6¢LåôÅo}1hŠSˆ8‘ˆž $“Iœ{õ¹xbÓmÝû§´µ7é8ÑŽ{ÕS¨6ðÕ(rÃÈÈEµãºÕp›k噋„›Q;üÕùÆÔ}õ#! EhT;íE`S…W K¸’2G=å[ò.¿It~¶\.Ïó‚¹ÓÔ2 …è"ûÈ:ZEp”Ñ¢Ñp³R^UlÌf³Áü"^¨B†¬W…–L&ÏóH$(>®Õˆ.ª#‘4T~ކOUçtT_£s7ª Bt.ÄzžÓru*,ªÛÔ{W, Ëj=VÅÆhýÂõKÍ{ô¾—Î¥|+í|ºV wè¡>ˆÕ¥²]@¡ÚfyЫsíªâ©|«ÞÚk…ØIU¸•ü\}õÕkv^B!„²2$Ô~, µÕmÛF,ƒçy5ƒí䨾7¨mL5¬©¤‘yÕ[E>@>‰D"4·z£tj”5Z‘Šãþûï‡išAXUõ¸™L¦æ|„BH¿¡FSZŠiåyÕïòŒ,ÛÆÉ3ÏÄ™O½Ïù߀Wé¼ãÃÆø 7ø}hñ8`!™^ráKª™Tß þ|†•ðoÏÜñLå|RÀýwÜ—=ò² ù¦'6!‡žüý' ¸ðä…H!…#o?â{ >ó N?ýtL~tÒŸk&®¾ç-‡mŸÝ†—_ürœýñ³‘ÒSX:u _:ÿKÀqàŽ+ïÀÖòVܻӿNº î¿è~À/¿á—áÀÁ÷¯ý¾ß9›4h¸ø/²þòS7úÞÉÊvWó—5áR7_»9(Ë¡_<ä_‚È (Û¶¸ñ’CsS?´é!µÎL¶miàg| ´Íƒ¯s¨m$ésœ[˜ƒ/4•œô÷‹ž m!ÑSd™£[Õ‡Ç µ =Ï«éK²ÙlHO‰ÇãØ¾}{Û÷ûimt”hˆÕz»“«V^$ÔЪ@5Ôj+HÈ= ibYV ZÉ‘«]¨†ƒ•Î|5ük=¡C*­T)‡:ça2™ y©ÓÕŠ#N-£”I\»‰ŠÅb Š‘Ëå‚ãÈKU2™ F™ª^2"SÎ¥®„]”‘§"²¨ó>JY‚…ü/ˆQËXÅ“)N,—Ë…ÂSŠXr÷Ýw¯ú·ÝHÔ“ã%»£,wÛ¶ƒû-:W©:¨ÜWj)j¨ Zê½$ó ª‚ ,‹X($õAèºnhBhÅ^©÷’:PBíiTyˆªƒ Tñ]ʵZ$$±–X®ÔU5ü¨œKê¬\uÞ\õ.ùSÃͪ6,ÚÁ²žó¯Šðǃv gÿà÷ñæߌ¿ð“3ÎÀWnýþàÓ¿‹ãÇýyü¤ƒ3ŸÏûšIø£Ì/¥PÎPËÿÿ¾§ï莸À¹/>,Ľ8à»:tœòà)Àà=W¼…» ÐÏÖq…~rno{^zÏKñäËžÄOðœÿîó1Ãm߆ÍOo4¿­óá‡á]âaJ›ÂCû‚·§ªŽ† 0þkµîú˯ÇÛ7¿(ð€/~닸ָÖßA^þç/¯¾pjÀ øâjxÚ®ö‹I¦ôÍ—¤ÒïòÌ“. í-éK”tªF³øØb"¡Qóù| {H¨TÓ4‘N§166ô/ÊÜ”ÒǨ ‹âœ!}þB<9ƒE·Ë²ªE·½õ­oÅììl[÷7…Ç@€¤C@Èã‹ij¹ªV«ÞÍQnt¹ù$ü‰ˆjE’<©7¥ä=:OœŒ´Œ†!UçPÓ4-4σ”ÅuÝÐÄò"^D=9›½t¨ác¤Œ™L&ô­z’IeŒ†Q•¤Ñp”2òA–Uï0µ 2?\ #© 32²UX­GWôwW½-Õ2ær9|÷»ßåK[‹HõjÉ•ÖP;R©]T/g©—êHõá >$äá ®':oLô·—ê@±Ej†€Žþ¯KÝ,u\¾ê<‡bkY5¿BµA²¬^ÉŸëºx/ y¨Gí®jgÔÁòéq_̵-W_}uÛB!„Ò9DГ¾ Á¢ù|>´Xo²aXXXÚ¾ê±ÊårÍñJ‘9(KËÍ[Ùb: óÚˆ¹¹¹Ð±Ô~`}îB!ëA-x;Z–/6ž‹•þAÏó=ÓiœeÛ8yæéxïÔ{Q(ðšóÎÃäÒ«Ïúý?ò8µÃ4|ïFáÌJ&<øétÀK{øÉ‘Ÿ`›½ p€³^|bˆ!ŸÏÃÔL\;q-,XøÙÏÿ §\r 6?½l66cç‹wâ~n6nöÛ1q@Ëi¸ð·.Dâ%PÖ¨ƒÊZ÷Y6÷ìÙSw}=WËûî»oM3:¨HƒZmX«úÑI×%MTpT_0¢/%""¨ë¥Ó?ÎU–Õ $ùA1ŸÏÇO÷TaM<±DhT=³¢sºÉ9êyýECÁ,W1Ä«Pò®†y”ð2€/©˜’'õ»žW–jX¤ò‹aÉçóàTc)«a/E TÃŨk»¨/f"‚ … ï—]vYGßX¨aä—‘1/6:'õ[Ä™+P ÷"˪p*¢‰œGUÏ' :¡tÜK'~§o|UÄ•>ŽÉÉÉŽf¤P(„¼''''qâÄ ÌÎÎbjj €o`¦¦¦‚ån¸!ݰcÇŽ5¿XDõ(lä}¤v€G;·UÅ»r‰“*±ž¸ÐlYõ~, Á «zLÊv5Ÿ¦T Y¨z 5r îê5Íf³Èd2AT7eY z*ŠP¯¿êí¨~«#z…¨ÁQ×ÿ÷ïvöêÒëv Qa%DçR©à¡3Çå–û5Zÿ[½ïÔÑóÔK 4h@ R‡U»¤–):âFDJ5,ôz¹õ 2P@ìX6› Tµ¬½T‡72½n !ëÃr¶€v€Á‡m‚úDÛ±„ :´„~´ªÕ$º©¡¬kJ*å‡Vu]_tÌåüålH/ú—1Ä⦅;ô9|úæOã¦Þ„ý_Þ³îñ=a¡ÂM‡rµÒ±ùû>€kÍkƒ0¬±B %½tzº²Áîyï=À•ÈmðÙmŸ…yIE¨Ëúކî÷Uæ‹yäCÙ`.C5‚›N¨ íkŒö®•êÑ(ËÒ(m®L&äÉó¼ oUò¥Î©(}òjÿh´¬¢9ét:ÔݾËõ³Fû;»æñ(,--îÉ{öìÁÌÌ fff°gÏ\}õÕ˜™™ÁÒÒRÛ™X\\Äüü|˜yà 7†b~~‹‹‹¡4£££Ç‘#GÖüBušB¡ܰC‡QUê/’F½—£žÀ©.«7gTpŒ ‹zQ/DœˆÎ5'!™L†<ŠÔ¼¯‡!\ÄNq7–P¨" F½ U·du{£ŠßKá…ÛìUúÁhðí â¢:ð ÞàƒzõBlZ¯:E´>ªß"Š×o4$²ZUMõxì2ÐAQµU=»O?ØBÈÚ³œ-  dða›€ÐBúÛ¨"£e¦lM•þeMóîær¾§c¥ëéï?‹~xLÓÄüÂ`ÛõÛð{_ü=<±é @ñ\øó–à‹ŠøÙ?«8yáIذqìýÇÇ·‡‹ÊpðЦ‡ ëzÐgùЦ‡`š¦¯è85áGúýmÑpªÑåè>QÁn­úìÄ£Q¢8Jù$¦iÛTFí;jõ„Åèvµ¯4:[tûr,'ÊF¯]W…Ç¥¥%ìÞ½ÀÎ;qà 7ààÁƒ8xð n¸áìܹÀîÝ»ÛÅ%zttû÷ïÇž={°ÿþÀÃNœ85fË–-¡tõxê©§ðío{Ùtë:·£*<¨žAÑ›N)WZÙd?uŽÅ¨ÈPOÈPçsPãJ  F‘ùÑ¢s¹©ËëéY¤Îq¨^»¨!Èr?‹õDÐÅÅEÌÎÎâ±Çëvöêæ X;;=öfgg»>σú0“e!*ˆE{uÛJ„îèÃJΣNL¬3ZÕù U!2šNøE$í¦è(ejfã6"³³³øö·¿§žzªÛY©a½Ú³³³Ý.*!]eii ³³³8vìX·³R—ålA»m‚'žx"Ñ…Êüüê²P(044 zŒÅbˆÅbÝ."éaø~À÷BØgع>à üȦ.ªO³•OÓhj–å{7¾d¡ºN×ñÑ/ÇËå`Õé_<ü’?Æ»^ÿ.Œ?1hÀèÓ£8çœsü“&•“$€»~÷.`¾éGŽñu 8~ÕqðC§šÕЧ¢#ºøP(‚˜DC¯@uGÛ¶CŽ Qƨ8 ­]^¯~yUUûAÕ|Hh½e)›ÚO+ÑÕ²‰ãÓZ”¯“Þ óóói4gff°¸¸ˆƒâúë¯ÇŽ;099‰ÉÉIìØ±×_}+yff¦#…Úµk†‡‡1>>ŽÅÅEìÞ½»#O>ù$æçç{b”“ã8( ¡9ܵc\_L_¬z;®æÜrN¹£Âa´s>:ÙiTøˆ âU$ßQ±D-ËZU¹_¯sö:ÒˆxüñÇ»•†¬•€Ç¼åF„:")ŽÕÏåXzƒ‚s) nY×õe=n›ÑÈY¥#uT„EÕãZWRæfU?+ñÀîk9Ÿj?"íO>ùd·³Òµn°clt$,Q¯ ÂZÙ{áý€nräÈ‘ž…µ|?áQ:+{Õ[@¥‘ ¥P( •J!ŸÏsÐi¾ðý@Ų,d2™†Ó³¬52]T#d ¨ÕÐì¸ö¶ÞgØ*^ƒõ5=T±˜ïÕèyþÇ0lºÄã8wó%¸ÿgþ×#€/y†màÎwâ…_y¡/2ÆÓïôàä„m»ã‡w„¸€?—#*ºAáQ<ƒ4Ô𣲠 Æk¯YhÕz}‰Ýê»jÑ~Duú(YVQõ9N¿¶ÃŽ9Ò‘6A]áqqq‡ÂÔÔTÓ¹'''155…C‡ud„`2™Äôôt0ì–-[pèС¶{Î9ç ®×ÝÀ¶mÄb1X–…B¡PãE FlŒz#ªq5•PÎéºnÍÜkâ™TÏU¨ Œªg£ˆb$’ÉdÈ`¤ÓéšrÎõ¼î¤Êää$¦§§qþùçw;+ Y+;çŸ>¦§§[š£VB íÏë¨"ÞŽª§3~ÀÕ _ t&”¯:Q±,‹¸(ÕÃ1š—zùØè‚~?2==x<î†ëQÖºM0==Ýí"ÒUFGG1==k®¹¦ÛYiÊZÙ‚­[·bzzº«ï„ôSSS˜žžÆÖ­[»•†¬åûÁ5×\ƒééiŒŽŽv»˜ü÷íz£ã8ðGÇñEÃÓ4à?4üðS·!v<†+q¥zÀ…g^ˆÍOo<ëñgùÌ#ðh :5 ùÖûn Nsò“•Sûç¾çá{(S³U\1ä^‘õŽTþWÃúÙ_^¨±Wœ¢B¢Ú Ô ‘QQUÞ©ß™ššêH› ¡ð('i%#:2Z8z¾;vÔŒ2¨7Ša||¼ís¯%¹\¶mQõ!£†M7]UaPÖ¯¹ñU±SD5¬«ê *ߪ·T6› Å5–ЊQ/ɨ1!Íè%; 5nÙì+Äu]xž²QïFõ»“®¨M‘óÔ çªzAªÞÊ„¬½d !Ýc9[@;@È೑ÚÒ>Š–e-ûN@Ñ‘ :ÉÄA¡~Æ(™L‰D±X¬F Q/‘H„Î366vÉdsss0 #Øßqd2Äb±@Tm•ëºÈårH¥RAB"‘ú>$O®ë"‹!—Ëû¦R©à¸‰Dñxñx<'‹ÅÁÐ0 äóù@hÌd2 •Iú1R©†††066†±±1xž‡|>\.ˆŒ### Î?22œ¯P(B¨kbb"tíåÛ¶á8R©r¹\ÈcTò)ÇVÅš\.üN‰D###˜˜˜¢åÉ= ^¨"¼Ê5—k+×W~ÇB¡Ê›”A½î¶m#‘H “Éå«'÷ýb¼ÊgÙ+iÛ¾Ð(uYÓ|G8nßÐñÃWLãŒòÛñÕG¯E&“Áï½g97½â¦ nëc/~Ìï¸ÔýßÿÃû"ÇÇ{,ø]½Êx¡eùÆKn„išU!R‰¾XÏ¢^ÄAu9ªgôŠÐ%浞ǣZ¾zޚݞjª×¨+½±úƒ^´üg¶<»ÛA<Õ»:jY ~€Î<”MÓD¹\Î#džSjç}ìµ:M›^´„õg9[@;@ÈàÓKm‚LÆ‚¦~§þÿò)üO,æïMÓ¨_·ž×£eYMŠè˜L&):’£—lÁz"‚Z=ï@E€ªÂŸˆVsss!‘mbb"ßBÂa"‘(‹£àÛ#±/Aµ¹¹9¤ÓiX–‰ccc­Êf³ÈçóÐu˜eæææÍfLœ5J¥Òé4‚ý“É$\×E<G>Ÿö•~T9n:ÆñãÇqüøñà8Ùl (•JH&“(•J(‹H&“0M–e!—ËAÓ4ÌÍÍÁu]äóy”Ëe”Ëe‹E¤R)$‰À³+›Íý¨ª )‚«²R>y%Ÿ²¿”=“É —ËÁó¼@°•2ÊñDM¥RècYVpÍ'&&`Y<σ®ëÈçóÁ9Äû3‹A×u‹ÅÀëQ~7MÓ‚ã–J%ÌÍÍá{ßû^·oÿúͨ’ž@ÿ«EB«ÀŒ ˜¦ßx@ xܦã?¾9‚£çŠK6]'?ø$zè!<ò²Gpå__ ¤xÀg?ûÙÐ ÿ׿ý/ÿ¤qàñW>N`Kê º®‡´ ñnŒ¦Q2¨ÎHÁ©ëˆqýÒ.‰æ]í'mT–~)[·8­ÞÊÉÉI8p‹‹‹ËVÌèËÿjÆää$fffð‘|ÃÃØÅáÇqýõ×é$¬ëÎ;1<<Œ`xx;wîìöulˆTR¹qëy=ªÂXt.Åz‚ÃjÔs1T÷hù?ZI¢áV£Âd¿‰mÐôªÈ« Ú›Éd ë:,Ë‚aÁË@=¢"ùZ<ÀTqQõªªu;úbCñž¬'½j !ëK+¶€v€Á¦—Úñ¸ß¨¢ë@:]û¿º]¾5­6M£±…ñx<a(žç@ñŠ‘íÒ!OÈ ÐK¶`½( ÈårˆÇãH¥RXXXà N©T*ðTï»\.ˆbÑL×ud2LLL N‡¢‰÷’¦i°m uéHAÓ´@ø2M³îþÅb1÷ÒŠ”¹á¤$ŸÏ×\Ñ,‚šLÕ,M£èMj­L%×X=~´Ìêï£ …õúLD˜µ, ¥R)4½V"‘@6›E¡P„TµïXÎiÛ6ŠÅbM¨í±±18ŽS÷šËõmt] ü3MÓD>Ÿ¯Ió¿ñ-Ü¥ëK?ÛM¢¨yžïíxq¸-üÅp• Ü©¯IðÜGž‹Ÿ¼à'¸èŽ‹ðîñwã ÷|û¿´i¤ƒm?þñC'´ Õ~½ÿý‡wK5êÚWïû*€pߟ®ë!­BtœPOP”õQ/ÈVç¤îE¢eŒÖ£h]gisê 2ŠàСCËÆ8—8ʲÏj¹þúë±oß>\}õÕÇüü<öîÝr¡žžžÆîÝ»ƒ‰d1==ááán_džˆ[¼TBµ2ÊCHAÓ4—“pµ/"2¨Ç‘!ZId½4 ¢aWÓÑ7*B:D¯ØÏ“„A™yÅÔ ­ øõÎó¼ þ«ßkÒTÂ"GµGìnÓ+¶€Ò]–³´„ >½Ò&hô®6Û5áÕ>¬VšùÒ¹gY’É$ …²ƒ¥s\Â$6ê'¤_é[Ð)<ÏC¡P…ö“¾CñPÌf³H§Ó D:˲o>Àw¯µR©TÓ— F/‹¾çËyeÀB£HKÅb±îz]×Q*• a†¦iu0õÜ«­¾Ié‘©¨ѨVÊ›Ïç›ÚZ ½nžçÁ²¬ºÓU Í<ØíÓ º®Ãu]ضÝwScõ£Ð4½ÊnÅËñwÒ@&ü³ üœ\ ß®ð®€÷”‡¿ü¥¿ÄÛ¿üv¼/ÇK®x Î×+sqzÀý÷ß_=fðr^àe,ˆ& jŽãédY¼Õ 2%\tÇx<^#X.§mô2ýV'zºÂãðð0¦¦¦pàÀ\~ù娱cGÝ>Œ`jjªí <::Š›nº)æ5êm9<<Jsùå—÷dB¥RoYEÏX^)_Í˃züVâtst$é½bDxTkm;~¾Ò¨Së¯ú0ž››€`´áZ# ßhHU¡Wã­“C¯ØBHwYÎÐ2ølÔ6A<‡mÛH&“°,«®GŠ z8æóyLLL —˱óŒ ýj dž½¨x—J¥/ÅãÇð£%Ù¶x3Ê{y2™D.—C2™¬ñp“p¤êÀâ(Í쇈ÄÅåhwÐôrÂßZ"âÊjÊ aKW»¯”}µý¯íˆ®rþf}Õ½J?Úà–€Q-ÙóüÑM§À.ðˆœ¯ÏH_zÿ—ð2ýex·ýnüìâŸá”Oû,7t’µÿµú›V~V±'BB#P #õV´m;$Šv”Ëå‚õR·%¼j£Á­ô®u:¦nõzž×Õ¾»n o"u㺛¦Ù—ÞŽ½N¾Ó¢ O×àsœŠ¸X!çï*1Ø ~êŸ3³’À˜ ¤~ô¶ß xrÛ“8¶ÿy?üpõX•ÛHê³x1ʲ|GçqT—%,³¤U=%UêÙ£¢3•sZ³ÃÃØžžÆôôtà¢,ôÂÈ^DDÇhhÓèŽÑŠ*ÿ/gøW.EŽ¥°Qè×<¤»¬ö±©† ‰>ìƒcW¬f !„B!dð‰Çã±Ròù<ÆÆÆJ¥‚ŠŽã ‹Õ¤-—ËÝ.*!}‹mÛ5uÔu]$ d³Ù`þ3Çq`Û62™ ŠÅb :JÇ¿x;®'„…õ<ÿJ¢¿uµŸ´›t³¿’ÂcgqÖˆCÃ#.°IYûþ p¡|£ÄbtàÅðUÍO’ ù¿ÓÃo~$/ÀÿþêÿÆï]ú{ØzÕV|ù‚/ãJ\é+°ê)yrÝ QÙäÃ0ÉdB‘£Úê%)0”;i•ÓZMH¡±5$L{,D«ëVB;9W·¬„ô:ËÏ„ZgŸJcu°Z×äá]oÀ!„ÃuÚxB!+ *:d³ÙšÎ½hšFB…¦iÁ¼qÍÒBVçyˆÅb5áQ-Ë‚aÁãÿèÇ*ï‘ïµ'u<¾ùqà× À>ëaxž‡d2 bÐuÝ·•ƒFC«ª}:U ¥ª†VŠïr?DïIöY’vh[x$U,Ë F Dc&þ\ ÝiHÁ‘åqà.ZéÔÈê!ù?Ú8ú ñ‘BHpݰp¨’ÉTæáp‚a.ç‡Â™˜ð?jÈ:Mó?¹‡‹–B!„Ò_X Úp…Bét:„ ‰DŽãÔx5‹E?~¼æý?êy´ÞÔsØçükÞͲw³/h­æ ÝHÔ{‹t*~ªW>€‡ÀþÉ>¯Ìùyø±†³\“gžô½ \àæ›oF&“A"‘€eYp§zÏÀ×øzMÔ¨ç£:¿¬,Ëö¨ð¨öSFï ŠdµPxì ®ë•^S.£›º *„,ÿ9¿Ò& ëº°m»®§£4*Õ†5½ !kŽãø"ØZÑH´ëD@Q-K&ãoqQ% H&ýPª•y³ø¢c>?î¯O&ÃûYVýkfY@d¤<_ðl&VÚ¶ŸWù4ó¨t]ß sdòÓB!„e‰F5¼û'“É a&“ã8XXXh¹ÿ­Û!?¥Ÿ¢[t{ v7½=»=¿#ûˆ;‹ú&¦ZŒà*o׸ÀÝžïýˆø¦ ŸG<‡eYç#4àß–þ­&Dª¦iA$6Yçºnhð„„` òWGdŒ„ÎKÈ ¡ðØ!¢s;ÕÊÛk^MÝIÕ-ø0%+a¥Ýè^Ž^uD‘4äE|ÁÑð42W3ÁdÝŒ­Ïõ"„¬+ Ë)T”TÊë­——Ï _€K¥Âç•ð –U??‰DsñQõ\ ¢çïÄF×Îqªûˆ(¨ë€iÖÎÇ87狇 ¾ (è:Íúû‹¾¥^›/™ô§hÖ\Î¿Ž–åÿ*²mlÌ Õëéºþ²”Éqj÷WÑõjž‹Ez_B o-Û¶k¼'Ö¸©v’Ò‹8ŽS3ÇY.—C2™ Í›&+郒ý7¢ÖMÃn—]ú†ºE·çAAµ òôt"ë^ û[\3¸<üT~ªã–m·ƒŽí?†WÝü* d2hšQq¨ŽŠPçc”{LÂ9 Ñû®^ˆ®ë%Mƒô;„4ÖÕÊÜ‹ñÊWÚêw깈²+izÊKˆçyxüîǃ—f¹ï6?½9äõTâ6ꫜ™ÈzéGŽöß;Jz•Dä›ÒÈ\Ñu‚ç…— …ZÑIDèð˜Ëù¢“´M aøiå¼…‚/xMLøëÔãˆÈåºþqDÄÊ媢_.ç lvÝ×®0Rž•xá¥R~¾r¹ªø&Š##õE8UˆÕ´ª™kÙ¬=âñZArµè:P.׊•é´¿>™¬-6ë  É¤ïE©†ë×õêºbÑÿ–‘¨žW_ôM§}‘5÷UB!=E,ÃÐÐPÍ'‹…„¹X,†X‹ƒ{<ÏÃÈȆ††j„ÏóJ¥022sll¬îùêåKò¶\š¡¡¡ÐyÇ +‹add©TŠ$éI¢û"š‹išp†a ™\Ù¤-Áœm]¢ÛQ˜º-¾uëüÒGÔ-èñ¸vxP„Gõ•ô&ð‚$8©ûo0Mî1ðOߨ‚³^z^þ–—ר”ÀéáeÑ"TáQ~_Õ) ¨­óõìÏJí! ðØ&j,w¡˜ËbµÛ•l6Û3yYâñø†*/ivÆ÷žzש8ëá³B5†×=²ñ,’Éd²@×õÚaP)T[(ª³Tg*ëø&'ä*u«r¬FÂfy‡Rßñ=4÷¼ŒÎ˜­ˤkF zD×k-«§lë”wj§òK‡BÁìÇ£D”pœ¹œ¿N¿lÖÒÔNH]÷E+™ÇP Ë™NW…ÇtÚ¡²Y_Àñ*÷÷—ð¡òBR(Tó’Nû"W*åç'“© ¹œ¿¯ÚÉiÛ¾ç^4Ô§”1— ‡†•üÆbþ>*†+u½Z®R©š_Ç {#F}ïĵ$¯ÎtÚ¿ÎQ #ü{©4Ê»¦UÅáV„_B!=ƒa(•JÁ§X,Âq¤ê…än˲àyt]¯™§.—ËÁ²,”J%”Ëe”Ëe”J%¸®:ŸDlQó%ŸleðN³4%eàŒˆŽžç…Î[,aÛvèIH·q]žç…îK˲Bý|òž_TCð·H·…Gu.ÊnÐÍŽYtívÙéÓ£¶ÏhS¥¾ÝdøÎ÷ëþ»› =z4ÌcÛ6n½õVd³ÙP žç…¦}“Aõœ¢¢Ëêz d­8­ÞÊÙÙYìÙ³§Ûyë ¤á, ×uƒª‡ůî@ãIZE43Ëx.€ˆ¬Ê>jmøž‘éÊÿ¥Ê¾¶’^¯¤÷*ÿ‹êTö“ãh¨Š¥Ò·©ìãTÊlWÊc+å))åL(Ç4*ÇKWÊ/m-½’­Rþxe»ZÞœrõ¶*Ç•ô’«òí(ç((¿¡œ×U>¨”ËE08,TgW®© •e)Ÿ¦ä!^É“^É£Y9¾¿Qšô×=öØcØ|ëf<þËã´/œ†òÖ2μáL<üæ‡qÛ•·áõ[_³ï=Žçàù7?gï>»šG¹—âÀøûƱ0I¯§žCBŸŠ×ˆ†ªSBŸŠ÷à‹nñxmèQát½ê‰X,úië¡ëU?MóÏ?7Nûçõ¼ªç^©ä‹ƒê±“ÉZñ/—«æ[ÄÒi?ï²^í€ÈåücE=ô’ɪ°)ùH§‹trmz5ܼ¦5þ]VƒiV…êr¹Û¥#„Ò"š¦ÕˆŽã ·Ê9›mÛã ä•A.…B!˜ŸN0Mét:$¥·øƒ ÃÀððpÈÖˆW5Pu]l”:Í“:dTà®' Àh¿òñWâ§|ÛÞöODy·HÁœ’ðŧ|‘É@ÕãÎ/”á GùÊð½ãÊþ)ø‚V®²o\ù_-µ]‘©,'*i4TÅEùPÉ£ˆzª‚£§ä•ü»Êyep¨š"ºš•´ò¿ë硼µŒ¡G‡ªÇÎ)yÔ*ÇI"ð=zêQ\ä\ä¯ÏVÒ&•|»‘óȺª¢fE0üÙ¡Ÿá¾×݇è/Êô“üg}ð,À—Þð%¼ðŽâ<ã<ÿ\ZåzW®Û¿ñÎüÊ™yìØ1üôÔŸâ¢äE@xä©Gp~îü@€=vÁ1»à®¹ëüì]?Ã)'NÁ»îÀ5—úËŸºéSØuÛ®@4¼á†ð†g½›¯ÙŒO¸Ÿlàg¼È?xÿð`ñAœ}òl<ð–ð¬O? zäCx×ހç^ñ\<´é!=Š«žº ÏÒž…ù3çñýï¿ÍšCÚÆó|ñLÓ‚œêy(mˆtºÎ4T¼£HG†aÔŸp¥hZ­°gµs!Fó'yÁPí`ÑõjQµ½$"e£ÎõÚHÞẠ›Ú$“þõãK$!„ «Èìy,ËB>Ÿ‡a‡£ôMhšVwNǵŠ$á)óù|]OMÓL&‘Ëå(<’ž¡^˜U˲0œG!ˆ£ ™°#\”®çTžƒ•¾žC‡Áþ‘šóU}F{ž²G2ØÇ¶íМÑ9£¢b=‘‘šY+Nk¶qzzãããÝÎcO#•Y­ü¦i†F¨ß„Þ%‰°\Чœ„[qú£þ^ï<ëxpóƒ¸êÉ«ðûoú}_”Òá‹añê¾{¥¦œP<ê ø¢b¬ò-â˜_ôOGy_ŸSòeÀ(%4«†ªWPö—ôs¨zü%P³¨ œª*ƒòÒ¨zAº¨zþ‰×¥LOgT>Ie›¸—ŠXY™S[ÄÀwÜý¼ïÒ÷áÌ?>HïyÙ{ðî_~7ž¼þIØï´ñª¼ È?¼í‡øÅ›~÷¼öœŸ<¶kc|Ó8Nÿðé8ï­çpòM'±ÉÜä_•8ðÈ'Áþ»÷7ê7¶íÀ‹½P(Àó<¤ü‚¿'öüÊë~üÇ h@*•‚fhÈf³Á:ñxÅb'¾q7nºŸ¾íÓ˜û³9’¤R)\ÿ²ëñîâ»ñÁßÿ Þóû‘xEGÿè(N9Ÿ:ýSØ÷Gûàé,ÝB¡PÀ‡†?„ó7âŽOÞ'N}3Þ r¹²Ù,´¸†{Œ{‹ÅÍfñjãÕ8vì.}í¥þHrWÃ-¸¦ibbbžç!ŸÏC‡Ž·}ÿm¸üÙ—¯GÕ"͈Åü°˜Ùluþ½fšxF©'®'­œ»•Q½j{)*P®”‰‰êu5 ß#s£À‘ó„ÒQbèü,%TÇÄ Ñ©\lÛF¡PBš®˲ iâñxÐ))€ßјËå066xš¦Yã¹(¥]'|·¤k–F°JŸI³NÓ4‘Ëå`Û6½ÀHO ÷­¼ûçr9˜¦I!BHˆša4ô!ìžÛ C3€ðþ‘÷ã—ßýË0uÿòªA"‘@:F6›Å]ú](¾µˆ/y_B<‡[pñ£ó„×Üò`øáôqæg÷ú§Ëårp]×í4 ßýåï¢ðöÒét`¯ÕF—4줌zê%¯~IÐ+ 0 ®ë"ŸÏömض Çqð±O ¥R CCCH&“Až¡‘!‹EÞX€¦iÈd2(}­„a{‰Dñx…BsssÐ4 cccH§ÓH§Óð§PðCªº®/4.,Tç&Ô´Ž„uÚ>¢ë@>ϰ£„Bú ³Ú¬}E¬Š'¢ã8Ai»GÛç†a Nm啜¯¤]\3`QA:S)ì^Àqœ` ¨ã81!„ˆà¨¾‡KO€qe¡`¦€)Eüû9 ¸ÈÎÉ3zjj ™LÉd2t^oNǨ¤<[¥¿©]‚vŒ¬§µˆ‰ã85 õz€Ò§xu–=`äȶ}vÐÀ¥K—âøñã0aâÆKnĶmÛpõ׮Ʀ'6áîwß+žºÂÅ£ÑUþWé°3Žçy5 ˲àºnÐÉd2A'†ëº°,+xÁ—0¡‚Œ´’ÆI½Ð jÇ„ê}'#­ÅKP:<¤ÃÁq†x<މ‰ ,,,ðM" †äUFV'“Éš8öòíyR³)è9ÖýJ]òCÁjZ &“ÉÐuRG€¥ëÌC·’ðV EBx`Û¾Gc£ù™Ú´¤N›ÚR–Ðq³Ó›¤Óôv$„Ò÷ˆÇÃJÚ£"H¤Aö½õ­oE.— Úá*k5ד , uÕ‰ØÉw¤W°m;£Þ„%F#.¼ ¸â~ànxÚ.PÞÖ§L|ñÿü\ 3è;ÿüóëF¾9qv* ¡Ð©QáQú¾šõKÑiЬW‰Lú.ZŒ+/!ý…‡:“@ËÑÞÄsÑθÿ À~ö#˜ÇMxðpÇð8ç§ç`çwúéMàÒ¥Kߪì/fAo±MlÛæô“pHÅbñx<ØfYV°œÏçCb`TXŒ†5R·KhÒãÇ󆤑eñÌù|©T*”7±2ÇŒ¦i5ášÚ *!ME°TÃŒÉáy¾W£ÚÈdü«ðjlxZøæ*:nÑ­l‹¶Lø/CÑZ`Õ9F3tÔY»óPt$„ÒgH?ƒJ.— Ð5KTC»®Ûp*˜\.‡û₩iÇ–´š5z¾åP#†ÔCÚÿÙl±X ±X ù|>h“K´™—œ^ÀuÝPd³FÓ[BˆÌRt×#ÀÙp­ |Q¾ì ðBЀû‡‡ñ¢JT×uñ³Ÿý¬¦_N×õ`?àÛ T*Ÿæ,‹¡‡„…ÄC;™L^ˆ‚Ø0ñˆ, Ðu=X–ãK>æææ`YVÂIÄɉ‰P:Ó4ƒŽ ™ë°ž7a§YiG !£Pð½³Y_€ŒÇýÿ§sá>¹+>‚z…F³$9'lª{ãùµëþT²mç}-S§ÕY¿’¼Ø¨õV'„B:Œã8¡) €êÜOªàQ/àG‘6z½PjÒ¶/ (•JH$5Ç‘9ÂW"°HH×zyü…êÜæ™Lccc¡4¦ibnnŽÂé\× Õ#ö÷Bê¼wŒ)ÿßä ŸžûðE € W^( àØÇà8òù|0匪—£: G×uèº˲Bƒê£ÏM:E‘^¡é{öìÁöíÛƒ8p ´NÝöÿ³÷öqrT×÷O ! ‰Õ€-ÉbŒ\ÂX²ã¨âŒã˜ê€0~#©QòØ£gMõz7±ì]9ÝI ‰íì']a6 γÉv‹]mâ$fºlãdw%~I<%ˆaS $,¦¤‘@o@?Tª[ÕÕÓ=Ó=ýz¾|Ät×Ë}«º§ï½çžsÅÜÜ®¾újLLL”ÃÕW_+¯¼»wïÆÌÌL«Û0äG™" Óš)ÈZÈÿi6½&“!þöxùå—‘D*TœÙvk×bvû,.{ð2×dh¢`>7Ͷmc``ÀwÁ Ë2&''ýI¹LJ&“n}"®Mw²OrGJ˜ÑÑQß«ã8¾K¦\.‡\.‡t:í»—6 †a “Éø;>u]÷•‹ªªú>éiÑBÓ4ÞmÅ,šŽX–kíh®p­î&'c}gÃÕöE0Ö 1—?X‡Ê;ÿXĤÿ `¯üpúá Å9U¡œf…ãB½VŠôT)²T¬B•dvÜñ8ñš«p}%mmzžsK…¸ñ%Z'ñ¸ç ¼b Ï4â“~ß:„J² íäÃ0KFG A±XD©T*û799ZD¬tyÉd2˜­˜Ïä䤯à+‹˜žžF±XôÿMOO‡Ö5èøbÊNÿÄôHù899Ê“âœ3L5š% Äͼ²,s\4†i#ÚiLàOOÇdû9`£ È2ð¶rEà©U§`Y†††Ëå`Û¶¿~G†²,ûk…$‹4M+sÉÊŠF¦]‰µxÄ­·ÞÚ²BíÞ½ssseÇÇÆÆ0>>Ž={ö`ppcccؽ{7î¹çž–•b ðÎ<†iÍ’âϵÀšE0jHÁWB¼ø 6^¸GûŽâs'?‡×–^‹7­z°xzóÓ8uøFŽàåÕ/»÷.P …Ð`¡P(ø;’ɪ&줤I»èß‚Þg³YÿR0Òñd2r£i2™Œ]2™Äôô4‰lÛÆìì¬o%©ªjÈÍÁ›.˜¥¢cƤlL¥\תÙÙƤW‰x.ŸË8 `%€M‘Ë8s¼È1ë‘Öëéñò}Ž 8ÏÒû#ןÌWumøxî뀮 ,mW÷¥ÇXæï&6®ªæs€¹ Èlˆ\ÿO€µТ…7ÄÚ AÜ]¿¢†¼vÏDŽ[Þ3ÉFŽz×*‘ãÃ&ËÛ ¯²špW9˜Bà—Ò–…²Ê^z€$‚÷£€@ù˜ñÒÒ„ó9¸fýIïÞ”—¶×6·žw+¦îB»' ÚN0 ³¤t̘ Ã Šfà ¥Ìbi†, 9/½§¼™–aÚ‹vdnðúf6p¥ Q7»uÅbÑßèOÇ€p\ä8ת¢<]BhЧ1†©…ŠŠÇ={ö´¤@{÷îÅñãÇcÏíß¿;wîÄήÝòwÞ UU±ÿ~Üpà M-§hê¬iÚ¼ÖJ Ã,ŒfÊKø› ‘⑬g¼àg®|?¹è'8 À—ðgoø3¼pêlÿµí0MR?„ΊEÕÙ²,˜¦ UUá8FGG‘J¥üXôorrº®ûr‡b)f2X–…ááa·óôô4wW3Y3nÌERPR¬FŠÑ(ºCw6‹ƒžp1Í¢SÆ\ת© ën\Ç:”ñæsÀèÊtƒ¬úœ•€µ)&¡3€½,æú³€½6’.§pÄÍ ž7{3`}/¢»sGœ¨ R 0ßè¸Ê.áxNôB Uó$`­)§ ÀšÐ9þ4`½ àŘÇû½11*£}du)#°j—à*ÅÏ@ $¥)ðÈž~+F½ë³Þ½²wnÔ»_B X¤ûIÛªÂUÊp•’”¯î呞»¨,-Ï ÿ¸ª—gÁ»'í#…dÁ;¯À;ü­Ü·° q/PûPI´`fÉè¨1Ã0KF³dmÛ!ã^Èg˜ö¡Æ4=—¢Þ€R³€dŽS€ë ,ËÂìì, Ã@©Tò¢…#­ ßâš6ýG¢¼bÃ(¦]8¯þ$ÇÔÔr¹>÷¹ÏÅž›™™ÁÈȈlpp[·nÅ£>ÚÒr“ÕÃ0õÓ*9@kÓÚ„ÝéÙRÀµ\‹ÇÏ<Žwy§êükÎǼ1«Þµ "M.JÀ­‹ªª~ìÇqN§ýMŠ¢@×u_éXV?O™™ËåH$ü‰ªªþ?ŠÃÈñ™v ãÆÙ¬«x”$7¶c­ ú˜}KÎQÀYs­WQ¦Ùp•†eIoœU‘ MÀz àœ„«„ÊÁU|%ë Àz+å\À(`m¬›¸M¦çÑÆºÌL»õ)¼°·"äÞÓþ1`)€³µÝ(àìœe€ýûÞq @0¿X}€ó×B;å{`^ WÁ7ä^‹`~ 0/†kiH®Es»¥ã¤dÔ¼4†('á*å¼òÁðÎá*ï¼úÃ+ó'½¿ïZ²H,"PNJÞy®²¯9/{éLÈ{eUL#°ÖÌx÷L{i¨Þß”¶î¥¥zïIÊK¬73Þýš÷ÙSR>sÅ3µ½«-¢’,hK9À0Ì’Ðqc†a–„fÊÛ¶C›oy!ŸaÚƒvP åñ˜“$Cþ—Œ¿[ÿ„¯\$fgg‘Ïçýï¤h]©’‘!IR™ÇvÍ´+Ë«]0>>Žþþ~Üpà Çþýûc¯Û·o_]™››Ãm·Ý]×±uëÖ²ó´“AÐßß©©ùÝC8q…B333þއF ªjÈò‘aÚ‰‰ LLLàÈ‘#­.J,K)àÈ‘#ÃÈÈHY„ü,‚e îB®gýòãc?ÆUë¯àþØÚpË6,ó‚óá8μ“MÓ|‹ÇB¡àÇk,•JþñÑQ׬†â'NNNÖ¬(”$ ©T š¦ùnh°ÂŠÆÞcll ‡B___ý‰-ÍLLLÔïÝÁ¶]÷ªÑ>TãŽh@B¢Û,ÏÔÑ9H›)/¸Š@2ϭܸ °ä ƒë °®Aà²ÓPœYOy7ê~‡ 8oñî{#€X䀓œûÝϰà*Ã~à=®VüªwmÁU.B¬;™âê€ù^¯n_Ôð­-oÎd= È |«?û¬wü1@%%¢XÿêµÝÿÔ?òQL p.œ_¤»Ç}£Y†¤ìsà*óÈ ,7'½¿ ¯®Š>À5EÅ9¹_Î÷&Q’1%SP}ËBŒÎçIkffãããxðÁ+þ&¶šùdA½c‚cÇŽall ƒƒƒ 0L§1>>Ž™™;v¬ÕE‰e©ç>ø ÆÆÆ°sçN ¶ºº Ó2x~žD-¦à5Ãêk†©I+ î¼Îq€¯Y€¡Õݘ àÅo„‘) Å’•$©lm1›ÍúƇ:b–šññq<ðÀu *Z<ÎÍÍáæ›oÆí·ßîï ˜™™ÁÄĶnÝŠ¾¾>LLLàøñã ‰™ËåÐßß¿$±%W®\‰­[·bÛ¶m‹NÃq,[öõ¡Ì0íÎàà FFF°fÍšV%–¥”°fÍŒŒŒÌ¿¨`!ˆ•¥À]hW€“+N‚…ïù>€òþ_Mär¹Ð®¥t:\Î52M†aøƒ ²>Ìf³¾Ü‘$ ³³³Èd2Ðu}Á±XHA·;Šé=FFF°uëV¬\¹²ÕE‰¥c‚†(Zr97žc”ZûØs7P JoÑã¡ø‚6\¹”†«3ܦ7ï°? W™˜vÿùJ=°¬»‚lŒ<`î¬/¹ÇÌõp•UI·`æÇ¼4TÀ~¾…¦ù6/O²®SÜtl¯,ÖßÀxyV‡ö“Þ}_„«pó¬ í½ë÷éÝÞ=Ó€u½w½ë*R%éµÀ¨gheg{<ñg@òÀþº«Œ4ïóÚÁôÚLõò& u*Üþ‹¢w¼ˆ°;Ù.YƒêïïÇÈÈ6mj_7«K) V­Z…‘‘‘ºæ Ó lÛ¶ ###XµjUý‰-K=?Ø´iFFFÐßßßêªbÙ²e¡ÍôÝ4Ͳµ†i4>¾d^/¸à¼éMoŠÝ Q+´ã€b¡¼Ë u÷2‚ÂLU½žQ„oÄAz%J‡¼¬ÙÂ6Qh&ÇûNa›/½à 6 A(&KÈ' …Ã4Iï˜óŽÖÍŽQÝïxÁb6]' BÄÿ÷-~zå,µ€µk×ΫlPŽyè¡nëž<ð$¬Y *T¿ß/ä‡ÞqX–åßk²Y×L†$gÒé4TUõسœa õƒv´nhÖ˜ nÅ#Y;ÖØ?—¡ÜPÎ9 `£?ñp…upþ»wÁ8€Ãâ åž§\„ ȳ€ýË€õ8 ü-Bq“÷êÝ€r àÜüfôº¿dèm°e@NænÀñbU8›€ô& ó·€|£[.®;Ô‚î‰ÂJ¬U€ñ@ʳV´T@*¹Çð %À–Üt Xè© ôbÊ;.©@a2ØBúL ®rÑ@ðX`¯†oÔ7²ç _Éaa–‚"]ºW£¯¯###˜˜˜huQbYjY@ŠG†éuh޼wïÞV¥ŒfÌHñØŽ—“hH†Y x~žضÍóp¦çÄàà`ÏŽ ª­VB€Õ/kþ ¸_ÎW€SI¸³^—‹.º'Ožà®Þÿýá4›Íú‹†aÀ¶mضí»Pc02L/Ѳ *–åºP±¬šÜªÒ(‚~Küd<—ªxî§`´=K<ë°«0“ÈBÏÛacȰ½f’Wé4 d?˜÷ºÇ¸–“ÎGå øc e#†d2Á`?†r£wï†p(DRÒïv€¹PgƒëèÀ ­H˨4~„y¤ßY xa!ÁÝ¢y×&„,ÌyyÐk5`¿Àùþpn Æ4ΈŽè·5JA¨ÄZ¨”N%âÆO½N5Y@;[&†Yr:bL°„d2î/¨x¤ÍŒ4WX(¦iVõœ½†æ)•æ% ½žaJ+deYHÕ>a˜¥§ÇÊ!ÀÚäÎGí³/Ãð# 8,‡ý}ç;ßÁ쬻@¿—+W®ÄóÏ?:¦ë: è½ ÓÆTT<¨)ÞÉŽ;pûí·cbbbÑ;wîÜYvïÄÄvìØá :ÿ裆„ÅÄÄD]JÏZ0M³â ¾Õ±ÑHñUh‰ jÜ…¹ ‹Râpðh±Ž¬Ó¬)Äæ}§tHÙEÊ/²°ÓXRYL^âÄ–”„{€@ñGûœP]8o Çr^Ú´ÐH‹“”.•/ïÓ¶J$kDaM·fD…nÁ+Ç$c¹fB‹œ´À]©€ÿ~ãM.]uZ%œèÚHä­p?øÊƒ°¦,8¯x›`!¥¤B~Øãˆ³Ž¦É·išH§ÓþyMÓà8TU…a¾KT†éEÚ}LÀu¯jÛnlLj[Uó.@ùhD¡uÀÚH&ÏãýC?^žð–J€ó ©ùa¸?bžÀ*(¬ô¼°euð¨É€y  ¤K¼<„ˆ¤ßAR¦þý³¼câæC(6ýβOΓõ?)É2QF0ÎÈzeÇ+Ì,‚M7T&Í¢á¢îÕ7/|—('6Í.X(ɪ2ú[M㢨6E[+)$Ãû[F…òTï|Ìõq L "W„Þ…ZÇé\Û ªÉ‚–ˆa–œväƒÆZêÐ!ϳMeÙ²e(ƒ_“\.çÇ\‹ÈL&Ó4‘H$099éÏ/’É$,ËÂä¤pØ0 ¤ÓÁ6[EQP,ý9DzeËÉd`†¿Ùš<²Û7I’üó ½žaê¡Ù²Àq8ŽÃ!J¦h§1!° Pòèß/ZÀo¦¶>|í¦M›000¾bñ=ïyòù<¶oßî_§i+™®!VñH.—¢$ã:9]355µhÅ#™rG‰úXß¹s'ÆÇDZcÇôõõaïÞ½èëëÃŽ;–´‘ ÈÝéÔŒ´h‹w´>é…ŸóÓ_²h %£ w±‹”¢µ-",6Òb¡hÕG‹qI!OZD, eÊy×ç,$f¼G)=>Ê‘¿ Ý“).,kF[1<­µ:€ÿuð œ×¼¦­ÂTµJØÑ/iÆ[‘­ž°‹ÕJr P(øÊDÀuŸªiòù<EA&“ã8°métÚ—1MÛUiÛ@§.DÝ[ÎW²J‹î¸¶m7>àûV”òk"ÏÝ¿NL»Pðƒ…pÓ¿Sºî^oÛåiD‚‡C–Ãõ±,·,’äÞ¯ªåe¥)Å^#Ö×cÕðð?¨ÅÑîcÁ;§ieï^â£å!ñ$€í¾à=p¨Fü€ö¯¸®©a°¯”e@aà¼A,Bï•ôÂ&úÖ”mºIÀ:÷8mBÅYj^–´‰ˆÒHyiG-$5ãrmJ¿µ ᯠ`îoó¨wý¤w}1r?¡{u¡ BQÄ=!â1ÑéŒxN ¿8Ëi%`¬ _K´¢˜BûøÁxI|®´‹Ú’ Å`ÔŠ±€°gƒèñ¨wŠ‚1"ÇIñ(ÞCyê¨Íâ’ò¼íI-² ¥r€a˜%§#ÆMÄ0 _¹HŠDrÍ–J¥L&199 Ó4Q(|¥#Í7²Ù,t]÷½¬†á[U®b“…£££H&“Ðu¥R Žã`xx¹\οg¡×3Ìbi¶,°, ’$ñf`†i#ÚqL OÂçd{Xá­í\›ž +8€óÏ?€»Q'‘Hàúë¯ÇÃ? Ã0üµÅNò®È0ÕˆU<ŽŒŒ`ïÞ½˜™™ uê¸NNÖ‘Ípc²gÏÜrË-¸ùæ›Ñ×ׇ™™ìÙ³§LAºÐ.>ú ,­â‘, sÂg X´…ëD7i¤tŽ2\…¹B³„¿ \= )ó¬Èj€,iq‹¼QRÚ4 Å¸¨Ú„®‹—"1Ï5ÕÈ pǯ¼7- À»þò/! n:‰¥ ¼8f¢ù£÷BGû<¹WWBŒé˜Ïç]w«¶oÞ}7œóÏ÷ÝݾaÞ~ë­Àå—{R\?‡D2é*H!%Ë@Vð ›Ë¹×(Š«œr Ÿ+D††Ü¿äªI×Ãi ®òJTŒe2a%YTGù‰åðêYÊ!’H„¿kš["”hÄäd¸†NGUa78L³<ŸL&ìÓ4à ¿¸X}T±ÍÄrضÛn"²\®X4 ÷ùĕղÂeU”ðs¡g#–5N‘÷lºœ– HY¬i•Ûù9‚µ}±û×\ë‰Oãcmò.¸0f”§Ý7á< °0×ÙL?˜ôâFÚäyLc/¤?†  Jâo9Ý#z ëCrkNç€`L0)äEe"}i^HW‰ä#¾íJä{b‹W…©¯8`e8ž2¨IJÇ¨Ž”¾)ü¥NôÀóBá8ÍäVžÒ¡üÉ«n&rœ6léB~¦p\Ì—Ï@` Kù ¼ùJ|†ÔöT×€t?:•VÎ †iš! ô6°O¥R¾V*•‚mÛ( ¾â±P(ø±¡(>$¸j¥{eYF>_¾¥W×õ«·B¡à+ %I*[ÿXèõ ³Ô4JD½1 Ó94s~ yË‚Òóvø® ¶€·I˜;õ{sܾ};8˲ðÖ€4MƒmÛ!Å#gÄt±ŠÇmÛ\ß_ãããØ³gϼ Œ@쮃zøÑ~Tv¬¯¯÷Üso‘¹mÛ¶%_X K'r²q·:¹$£!ñœhÁH dwiÂÖŒQ¥]ñÖpC‰¨´ÈyšbEÓ«uÑŒéF´ÌM¢;h–P(!ðÉKf7ÇTÑ4­,Vã|ÐÉÇ?ùIhþçxçš5€aàEÁ%™ 4Ms–üîﺊ,I*·ÞËf]ÅY¬E•ždu%ZþEwg‹®‹”…Q9Uvár˜¦«<E•†”/¥·Ø (Áñ¨eধinÅm›è5Å8†ª ”Jó_£ëåeR-E©~M*5 ÀZÊZË.ñjåå²tNOLVO» h—1€ jZÙ)_±)†}Êûp™™`5 ¿ XçöÖuÖwé5Þ˜@ ,é7?ƒÀ:mÒŽíUö‰=JA`)õ<@’D¥cQÅa•7³ŒFþ~Ë}aëÅa¯éiÅ|¦Ì´!Ëò®%åY•Šñ,5îWIÑHÖsš’“Þ_K¸B(r€çÇe¸ž&ÄøÎ4$E£À{„h9**ÅwAÊ"øÛ÷½ïzæ™¶üÒ•-“ ôŒ¶4-2öe9äÖ”,(4M yQQUŠ¢`xxØ_Ìôç!qëóY|-ôz†i$K) ØÍ*Ãtí2&P¾ ÀÔ€ËÀ×Ü ìÏn|šúk‡àÊ—~ô£¸ë®» I’/kD™CᘦӉU<öõõáÖ[oÅÞ½{188X1Öãøø8öîÝ‹;w6\ñ8‹uéºPD…ƒˆa0MsÑ.iA‰”‹´Fñ†ÈZ€ßDë‘h|Ǩ5A”J‹y<œb:‘FÊ €*ÁU:&Pnzë!NÎc'Õ–åZì…¦÷½ß»è"ýæ7ño/¿Œ’„¢¨¸¬E±$I•X’TnW^øù`qJ@U¦§çÏ£–˜·Õê-C ^¦·iÖ˜À'•ŠU:€sÀvÀš´k¸.Ø à"0_ËÎU€|ž`!§±ÉRŽÜ›fXʑ⋬Å^¥Vø\‰jÒ'*éª|ÚɶÚGtçN @Ñ=­Àz0…À=­Àº0‹`£)UV¦\!1‰ÀÍì0‚a“pŸ…Àu½æåKßÓB™‹,Åëi¬(#PXf¸YB`Ùj!°:¥×6³i~xäN,t M— ô%½& ¢óš{Ä­cLNN¢P(À²,ß2’bD2L·Q¯,=1 Ó™4uL`€|D¶é€ùî‘,¹ð ñÒK/áoÿöoqúôiÿ7\‹Y[P…LWPq•A×uLMMáöÛoÇþýûC>“'&&011©©)lݺµªUd§’ËåBƒy…¨k½…¤‰ÀåíT'QB‹yµýyÄ0 ¤€`õVþöø;}wè]T¬Y–û/—T¦ªB1 w‘>“A:‘€,ËH¥Rø«„sö,2ÿöox«móN`†étª¹; WSD&uî¶ÀùG@úUJàúœI„c;“%"¹H%K6M¸†©ŒóÜÇ“‹Y1>²9F›º$<ˆâæÍ¾¢OÒ§¿Ź´á*‹[¤ÒŽÆ|¦ibÒg¦¼ëÈâQG œŒÛ,ÝòAu 'Îb ʸ±ã¯~ë[x]-Ö3 Ãt"¦i†(mÛö×(ÇA2™D6›õã?’RÑ4MX–…T*åߟN§Ëb<2 ãbÛ6[<2 SÍ€4w’å9F"K¢ûìûàØÁ† —^z €»i袋. /¼à'·Ñ× ™nà¼J'úúú°oß>ìÙ³333Ø»w/víÚ…]»vaïÞ½˜››Ã­·ÞŠ{î¹§+ݘ®e£ã8!+'˲ü]µÄ, c‡Ü…'•#- MÂÝIŸAíJG†aŒ¸™Hž;ýr¹œïn9D. ®KS)Lýë¿B2M “ãÅMÑuÝLO Y–yÁ0]€…°Ø€à¤÷ù4\­O®‚Ñ ƒí¨@ò­ù¥‘ÅRÎÈ–m¤X­™…£Ámú Å#ŒÇÄc@ ðSüñïüŽŽâJG™F`…hx1be¸ã¼¨ |ÑRÕ¶mßU„kõÈõJ…ë+Õ•”–‹óÏÁ´-ŽSîra˜ž€Ö'W™˜Ëå|Eb2™„ªªÐuÝW>RˆÛ¶‘N§ýïÇ`d˜xlÞ,Ì0Ì<_©PAXé(L£ë‰kÖ¬Á׿þu¼öµ¯ g k¦[9¯Ú·Þz+LÓ„išØ·oöíÛçïVKG‘B¡ Â.Ö+ Ô)6c®¢1‰°Ã$ÜE  ÜFНÄ0Ló±Ïø‚X ¼ñb/*¸ÖNù¼W/›$ ç<ˆC6Šâ‹. H$0M“ Óé,[æÆQõFXl XnˆlX—#0-+ÜkXrØ”LäZ•Æd¹FŠ# ½¥DªÇÃD:ï^Þ²¬ø(H§ÓÁFµ*u#K”JضÊ;—ËùŠMº?Z6î«— ™f™«Ñ ß7¾ñ <ûì³ ic&Ër7*¥Óa…¡ã¸™èY¦Ó@"áþ âɦéÊ¡÷Ú !!à8îµÍVNš¦[Ï÷[†aEÁÀÀ†‡‡ýXŽº®û¡`²Y7Ò²ªªH¥RH&]'ຮCUU cxxÈårlíÈ01И‰-†©ÂSŠï€;áÛ”;´ÛÔ¶m8Ž2`z饗ðÓŸþ4”žªª¼ˆéJjè288ØÔ8Ž­Ä0 ç mÛÐu…B’$Uõ±L1xD+kr£6 W8‰‹ˆ¼‡ŠaZ‹½À÷¼/äÀtiÚ?ô'¿ò+øúáÃÁM1JÄ—®º ±a2p³³³¾ÌàÝ’ ÓáR'2c"8o°nLÇ<Ü@{€«‚˜Ì@yÐu½¢@ Wª9¸š÷wÒ;Ïû¦Ñsƒç`š¦/òFÿéŸðîÍ›ç½Õ4Mß‚%—ËaÔ[läÁÃt¶»áÀù®÷Ö'NÊQ›€4ùÒ”{upwœ #pµI)·ÚûÁB,ú,iÀû…Zær¹YHŠîê€r«BÃ0|KÓ4‘N§ýïtŒ~'lÛ†eYþ‚.K{ŠÃ00<<ì§AVôCCC!E •ghh£££~Œ.R" ¡P( ›ÍúîVÉÍåGm *>S©”ŸŸã8Èf³Èçó°, £££øÆ7¾ÁŠÇÅ`Û®phÈUÈ a+CUu•o¥’«0,¥#¡ëî=¶í~ÎdÜû2™°Òpb²ì¦‘χ{@O©äþ‹Þ¯(n>¹œû7ª¨TÕ ŒŽS®Ôu7]Ms•Œâ¬¦ùON–+5%H¯PpfÄþ­(a…¬`Ñë“N»mM£òÁ4Ýr%“AE í³e¹×F Œ¥û‡†ÜsË–…ÏÑó6M7í¸ü)_J+š:ÜS(T®'ওNÇ[’õlÔ"6™ Àq±ô¼,Ë=ŸNÇ[Ö2m­M,Æ‹î¥- ÃÄÃÖŽ ÃÔD @Ò6•oX ¹eYxì±ÇëÖ­ÃøC˜¦Y&gØâ‘éFj¶xì%hǹh­$*%I*Ûo"p›6‰ †#Ã0ÀúHÀ‰'`š&®˜›íóï{òIüvdrN±I.d³Y$“I!:+Z 0 ÓÙØvx!Ý«A< Wc˜uKk‚XκîZ7Ú\|fá—ô—ƦoáÐnÌZ'=†aÔì¦,ÅÝœQ«B:O×Û‘…s²ðÓ¤´,Ëò-W©(JhB—N§}Ë?²þ#…_"‘Õä;•A×u?-Rþ‘›:˲P,‘L&¡iÇñëIÊG]בJ¥0<< ˲Íf!˲ߺ®ûñ·t]Åì¢c™L¶m£P(`rrÒWˆf³Y_Ñ8<< UUaY–ßÃÃÃ(•Je–( iöîÝÛä7­C‰ÊIr•e™L¹B‘ÎÇYì’¢‘úÎb\Vrß>_ßÕ4÷_TáM³ZÚTßJ‹²qçÈâӲܤ€£¼d¹z{LNºJ2ÓtëÍ#,"Ia'*O5-pwKÊ6q¬¦ªîõ†á–!úìL3¸_Ù&"ËBÏqÜòŠPÝÇUøQÝE+5ÑrTQ‹XUußRøÆ=#I Òµíò÷uxØU »å'E6/r1 Ä y>Ã0LUT…ð7ñ`Eiš8sæ àÚk¯Åõ×_Ïþó­.9Ã4V<Æ`YlÛ†âÅj#WXärA’$dž»æhÁU4’»4ÞÅ0ƒz7\EÂ4ðtßÓpvðîçŸÇƒ}}ø“ˆ™xÐb4-R ùÊGñ8Ã0N.W¶8k=àëàº:ÈÐë÷¬b>$Cªpu•ä ¡YË q÷LʾZåYöUº~ttyÏ*‹bß‹E¨ª Û¶‘L&}÷¡¦ibtt“““¾BŽ”xäž´P(øé $“Id³Yhšæo Ýʲ\ææ-jÙHu  fÃÃÃÈd2pÇ·¤ØX†aøcDMÓ`š&‰,ËB&“A>Ÿ‡mÛ0 Ãß|¡5==d2 Y–¡( Òé´_fÊWT–Šå•š€ëÖn2¢Ü kHJ3—Ëùm‡,˸øâ‹þÞu …B 0²,W!EJ'IZœÒв\åV«\‹õ¹•¤xÅ[-èz  [ìý•òŽ*ú¢ˆrЬ;£d2aw¹Ñ¼É n\R)÷¼eÅŸW”à=ŠºÁË5;äoÛÁg*6Ÿ>)Kç³Ò±m×2•a†©‡Ja¦Ôp×MøM ‡}‡…´€»ù4™Lâ–[nÁ¦M›J¥ IÞûÞ÷–m²e˜n„ WU´ã\x(^ü‘a¸ ‡\E#‡fg˜EP sWÌÁ¾ÇFîàA¨ªŠJ˱´‚‹Å" …E©Ùˆa˜6Ƕ]÷uâB­ 8îGk9Ü€×—zŸûÕ„;>0áZ6RøX²Qi–GR°©jm‘!I)Wëõó)*É2Γ’L´v¤ëè~EQ|—4©T £££ÈårH¥R¾‚6„‘‹Qº—¬)]]×Cå"ËCI’ü˜ˆù|Þ·Ìf³¾²qxxÅbÑ¿†v¾“b5’üw'”—h9÷{ ZÄ‹çkQø’ŽJˆVždÑÉ“ÚEBýŸ”9•,+ÝŽplW îFkÓ&èp÷+ØpçäÄ7 wC£ W^$áÊått)4'\?êýÕ½¼d²Þ9GU!Uqcl¢z×d¹Mï¸e-¨-å9ŸÒw¾ÅfYž_é:Ÿ%(1ßýѼ£2¡šr•]2 Ã4ÞDÌ0LMœtÜqm>ÇmvăÍ ÿ÷ÿþßX±b…?Žzæa˜n… Å'½Âä ×µ*K¦ƒ)À7S6M3´X_i·£$I¾ò‘\Ú‰®ø†é¢®ê×Âñ¶à«™Trww!Þ€»ðoxßiA¾Ù1ŸµU×¹’]—F‰ºMµ, étÚ'¸Öz£££(‹H§ÓÈårPUÕ·âSUét:äa"™L"“É ‘H ŸÏûîNUU…ã8H&“pÇ?7<< MÓ|K?*‹¦i0 ×ãTVߥ<÷†¢Å ]G;QwsI¥6 {Äß Y–ÛÆÕ¶,ËóZ;2Ue×ú¬ }œ”†w¼W‘X€Ûÿ œË/‡²aƒž\3žbÁÆFÍKË@ p”„6Å&a"ˆ9OŠOºFPxȾùÍP~ë·üëRpç6ª÷d˜$ÜŸõÊozéæ¼úQ]I…NÊTš')ÞyKH3ý‰OÀyýëý:¥ ÅTá^jÅk‹œw¿"”¤ôè¯éý#Åh@jrÙ’P'½éBþT ¡!^g ψò ö"%±#þû½ßCæ¯ÿŠ÷›b m' éHÞwzT¡ŒªðWE \¦_)º,íSBYUo|JíIYæÄk^†a˜^ÇŠX,1 ÃÄò2€'-ß}½U(„æÞ¢±Âßþíß⪫®ju‰¦é°â1),Ë Åuàb‡ªúlMV:ÒŒ4Š`K3ÍÆEÒf¨*Ø,à X˜©´­?•ªl—$Z¸J­VB Ãt¦Y®x´Ü àÖÆå€ò)ò»ª£Ü ¨Ù‚&;•H§ÓÐ4Í_\7T®›PÑÂÎ0 8ŽƒL&I’`Û6Òé4ŠÅ¢¯|#ס¤ð#…!ÅU$W¥â}äÞT×uär98Žã+Y%ær9$ ÌÎ΢X,"—ËÁ0Œ2·ª¦iúÖŠäò´9ÍVëLÎ_ÒGÜ¡¸w.ò2W9D »B p–Ãp¯'Åž@}þy$>ÿyàÄIèÓÏÃ~«Œâ=€|1Þ ¨OÚyL@ù} —$Ðl ·.ìYÀ™R³€òoÒ¿h_äY ðQ@» (¼P¾¨{ë3ÀðoÚ?ɬ‡óỀN PZ‘"’_2ë%`àB@:ç)ëV¸òŒ¼¿PýÈøÛ3 )HUC”æ{Þã·«-´ )ýÒ¦<´™+å¢ÈÞ}’ðWG ÔK#Pš¼<@ÙIi!˜F‰ÖªÃÞqRèÒ5T6R˜:”Ìt¯@êëCú·$¥¨½Š^Þ¦¾%”“Þ)R|’r•žOÁ4ÚŒ®QàZÁ@ñ3ŸAòÚkaÃÝ4›ÚNñÒÙºµ¾NÂ0 Ó%°â‘a˜JÐØs‡€ïüØÛŽã„BzÀ÷¾÷=H’„C‡aÓ¦Muå[ð²bOÐL'ÁŠÇ ‹E°ó¶!ý]T&F·:Ál’f¢‡;¥hN¸žV9 ”Œ9ïzò¹4ì]“B°m¶Ó¡mÍÔVl“Ž‘RVlOª7m9‚íÄ´=º 6ð¶go~as«KÔø{‘<Ÿg3ßý.2†êN•eÉdÒÑ5Ÿ’’a˜Åq`½ï}þO'@¬>÷£y¹÷÷ÚÀâ%…`ÿO«mÍÈZ°¶m#—ËùÖ‚ÑEÑõ*) E7žš¦ùŠEÃ0Éd (ŠïÊT–e8ŽƒÑÑQضb±Û¶}+HJ«X,bxxØWN&“IX–…ÉÉI?‘l6ë{¤e©Tª¢eg2™ô•«¼ˆÄÌ‹iº®’TÕwYIJ&{U< ¿Ó€±ÊSˆ¤ç€aïÍü `o4Ð? >èwòC@ªW TºÒ?‡óã)do]éæ (Ù¼²è.ôQø¦}:ùUM!Ð(©î²›| €¤®PRß° @P$`ú~@þÓ4r/¼Êk ʧç7i9Hïló´wÀ‘€ÂWí{0ò@>Øßäƒny341¢F³g°¶Ò)@ÙXk‡ó…ÿ õ— w¾byCÓ3€¹°¶Ö9@Ȭ…¯³/ìþÀÕ,Y’ÂL²„ À<¨ëÃó4 ®ëÚ€¼mC‘åòÍ£6`ÊåÓ"Õê¼TÚ Š°²“Þ-UøWË(’ò¯4=‰fO–²2ó=ïq§@'O¢°v-$³¬9@ñ~Óv}ç;ÀG>RCI†aºÚ´Æ0 -ÍgïùÌÇ»uyaRBÞ¤€öžµöºš"ñôpîÜ9œ¼í6Øž+¾j ß…]*•ªè–™a˜Fב~Ó›‚EaÏÈQé4à¬r/#—yd]C?OKáÜ:Çá8NÙB‰(Ï¢çu]÷c1Šܶmöm躎t:íǦ˜œœ„ã8H§Ó¾‹ÑÑÑQߊPtO:44„ééiȲ EQ|/™L¦,.¤,Ë!w¦dÙHç╈Qw§"ó¹IeÛž X>( ¸Ã¬I°®’g½a½$@:Lÿàôö o! ww ˜þÄËC»Á‘yƒüέÀ—RÀZš®¸~f{4Ž×”b®"bƯ2¬µ À+¿h®R0{\ÁUô®¡\ ÆþœIý“zãv) èâ¦Å,sÖ"‚ ‹4Ê íàùP•¦óoübx·;¥@ÉxAh7šÉ^Þð3ã¶•?£c£áó’0|U¾ä> è_œ×æ žƒôÜÓ°¶C9å¾oJþN™w=ù®…ö†a˜®#n<Í0 CÐPLý«À'´²Û´qÞþö·Ã0 ôõõUÝU4 ®¢Ñ¶Ýã¦Ù¹á¼iI¢E«mϰaÅcÑ,Z\ì"ÃÂØ¨=¤Ø±àrAàë†L!HQFz „B FR ÒJ'ƒòˆÛM÷“@JÍsN†ëSˆ”£¤Ì'Ýmõ¥€*dE ¡<¸“dQŠ–––p¿è‰”–¢Ÿ"q 3]«Âà“/' I‰è÷H,?)mIJíLm·~;‹ È ½6‚€0´…8‹@IIø/ж£°ˆá+ E«KªGôE¡{ĺÏFž—¹—šîØuöa@: @f—åqÕ¿ü þó5×>XæŽÁÅI¹ äZ Ó¥( ì3€sÀ ǯ öÆÁÏ–Ê;ÉœJ›RrJ®R Ã0BîO‰„o-H± ) ÍÎÎ"™Lú¨T*å[Gjš«•e9ä®>ó0ªL”$©ìšF,øP; °’™ŸBÁÉ 1?i]ú4Px#2ëWõI ;`^(?¤¤ Óf5qÜ]‡?¶ÂJÇJˆé5b“¢¸³Ý*_½ËR)¯¸òŠ×ŠåNœl¯ïS3 ÊSrN‚> E!ph,K[Ë©¸´™/Îk ‰i¾”>2 åóÐ'¹ijÂ=¦w-ÍĹŠ8Ì#œGxÓ¥âµÍQÈ<Óó{ªüâ1ë€Ãp¾ »ÿÀsjšsІÊ@,in”>O e nð· ØÏ»nwµƒsÀ‰“(¼Ðñê8 íÅ ^¬úú0 Ãôì%ƒa˜ê8ÀµÁ¼–Ö -Ëòç»–e!•JáÞ{ï-»Û¶ÃQ]Há8Áp½Pp;Žûϲ€vžÖ:NX¹hyÓ¤gX“Ϲœ{,†áþu÷\»(&Ågã8R˜êG aÛvëè8îs±í ~ô½Pp?7Kñ}¯r9@׃gA×P¹MÈfÝr:Ž{½¦¹Ÿßö¶µu—‡1(Š2.xÿbU &\ÅSîÄ”q܉&µªwŒþ’u_”è$?nõ²‘‘|Á©&ÊÕ܋Р¢R/®qšÚé*ç«å/æUmu—®UcîæoKZ숖‘ž!åM‹&Åf ÕÛ)®Î‹qó:Ÿ kÞN8”'ÝÏ+æöa|óf<ÕׇT*Uæ"Á²,qžÝu]çÝ ÓåØ+<€`ÓPÀÛ‚ó䈠ãÇqæÛè8lÛöwjg2˜¦²04 Ãw‹J‰†a NCUUäóy ›Íúʺ|>\.ç»+Íçóò-ãX膌¥”¥³³³K–6Ó%8Ž?$ÝŽõ0 ÷† `: H×ÕÓÂKÂâÆlº^C¶YärîŒ3uÉ¡ú ¸y »bK(Ñ¢GD>lj RF¯‘€ñÜéFE”8.>–¸Ç$«6Ž×Éž°æ/m„t“ëjKþ‹˜ûÄú¥+}ŽÖužy#Mc´«€‚§È•vpþÍåéü`óÀ0 ÓËDã³1 )|Ä!í•å`ñž¾‹Çèžè¾QEq¯‰~&DÅF¥kÄc”YÈÑwYv‡|E€¢ Hž—Yvó0M÷³¦¹iØ6ð${A˜ÖÚî&BÚ lY–¿yÁ²,hš†Ï|æ3Èår¡4hߣ,ÏÛ4…)ÇUеré‘hÕ"LårA,Jz—R©@©šH¸ï øŽR]‰ÐІAíçíI†m»ßI1HェºÇI—J¹Ï'vÛÞ²Üó@p®»ç í{*ÔMUƒþ'þ´P¤ë¨ÿîq*‹h%J}™\íŠBFG]Å!å•Nå¢gà8îqÀ-£¨ðÕu7 Ir?Ó³SUà+_Yw¼£¾ögÅc ªªú;  ý¹Y8’K®»Uà| ´;¶]  íb…X7o«$T+)„»¹-ºë ¸»â<þ‰À¸ýv·íØ…tÛ¶ýAƒã8p§¢ @†a:œˆ/{Æ;®¹ÿÈË8"c—¥&.£H*•Âèè(Òé4t]G"‘ðe–mÛ0 ÃW6ŽŽŽ¢P( è)4MócÕæóù²| ÃY%NOOc>xSÓQd‚{ò, ¾X+ݘŠ) PðÛhÌ>™tólE?¡U±VA³åˆ[{±D])=dªiÂ9}X¾¼)SÁ,ÂÓNù¹çàŒŒèÒ6f†i½8Ç'K*E ¬E•ˆ®»‹ÝÑÏ¢RM–ÝElÀúÐâ7‘ɸçEK.Ãpó#åZ±èÞGŸÉ;>AŠ5R Ä]S,ºçI¡@ùD¯¡û$ÖRÅ¢»Ðï8ÁõѶ¶[ôj7RœåÏ'“qÛ̲ÜÏ¢Þ‹ÜvÒ³%ÅåyâÄk걺“³e›ÂR© ÀªªX·n¿q¶mûH¬%)šÉ”¤‚k—Q9Gý>™ ”TŠ(AI)¦ªAy貚3M7-î S-ÿ³¸Ü`YÀ𰛇¢V‚@`©iå!§¶$eõ›t:(;½Û¤ÈÍdÜtH‘G}‹6 ²”dõ{Rð‘"PÓÂÖ§–U®˜ÍfƒöÈåÜ¿´A€Ú"™tó71¨jùÆ*g*´•at4øNr“žÕ{r2xnšà!زÜóÓÓå1D'&¦11Q߻ŊGÃ0ü Š¢ )˰¤N™Up5c#…À²qA<—ì"3gº†¨Ys´k*JŽq[‡8¯Ê ƒÀWÍ)rÉJʽdÒý¬i®b’Îéºû]×e')#É2“¬þ¨>ɤ{,•rÿ‘ì"·£é´[öògêž×õp_ŸÅ|S ²<$e¬8#e)m Ô~Ô¾ÃÃn$K¢ŠÜBÁ½–ž½cä²—”¨qe§h#K¥ÔfÅ£€ûè¥0¾‡¢E% ­}Ñ¢5,„ËrØòˆÊeÛaE]- ´jŠ­LÏob:qmýYŽSZÄ¥MKü^ËO=/ç0 Â`öÿš…òÐO¼Õßà òC×uŒŽŽbëÖ÷âÿðOýÛID}‘÷¢Ë\RÑz4)¦H™HнJF/”>9X!K½ÑQ7=M +i­<› Ö¼s9·o“Šò¶˜¦[Šg„].”|>Øì@yâÚ†'Nà#Ô\á’€;C+ÀµvÌ¡£¶Š’’Œ”j$4Dsz:ŸJ¹‰Ì˜©#“YpTùF; òù°6þ‘4u02ϦNA¾’S©°k ¨Kƒ0Ñw2 RQ1HÁRÅ¥I&âäÙIžT&M ·)-i' Qé(ú\O¥!î¿“[Q ÐNqG‚™:‹ÁwéÚÑQ7=q7Lt¬uá¶Q{j+›-ì@? |40W’$?¶™x,—ËÁ²,äóù¶Ý É0Ý@KÇ–åï!Å£µÚýK¡›ÉÕªï¾nÑYYÆìì¬?aét†a ŸÏCÓ4èºÓ4ýkr¹ŠÅ¢¿)btt³³³¾RQ’$Ȳ ÇqØb‘éHj‘uËÛ~À¿Ê°_´ CÂ¥ÒÎÐà·@ü¬·™ÌSï%^µ¸Þú²eÀ©S›¬xí‘GÛ…ÍìÚa€a˜ÖÓ,Y°ÍÅ´~EnHéçM´Š.–Ó¦õÑ40] 6¹‹Öwdœ/IÀdÉ]’ÔÌC,¸r<å}Îx?*b8UuÏ9Ö˜L›'mo2Cµuà.s’GáhB–ð9×ÛKt˜DQ©è/bÎWŠP$–Ýñ®mƪÕ|ÖkLûÑÒ1÷E=z ˜ü&€ašÁÚ!)5Mƒ$I8z´õW⦛Þ Xf )9­5“²ÜrÒººhL ’IWÙ—Íëܹœû]ŒçGëÞdÄ’NqþȺ’}äÊ—†É¤ £X @8!!IA¨üõ„É%Ù'.ÅÊrP®hüG:N×׫\[ÊiÉóÅRÍਣܴâq÷îÝxôÑGñ¹Ï}}}}˜˜˜ÀîÝ»qçwú„ Œ±±1ìÞ½÷ÜsOÝù[‚þS}}è_»úŸ¸®)C®Õ#­4¶x¾NJ,²î­øÈìØ0‚5 ѧ8 €hw€xNÜùD–{ÑàªbÀdòÿ,I®Œ¬óè¥Mȉ°Ÿä¨OhòW-š‹Ê8Ðù|°#C ÖLew~ˆ~“Ekòu,¦EìäqÂHÜÙ·[AÜ—‡¸·KL44‰îô"_Ñ$ éˆs‰aYîÓ¥—.Í{Y/M• `K€|â/ÑI8U$µã8Èçó( »Œa–˜–Ž ÈG‡$wø¨;ǰàN€ ¸“|ó‡s®I’ ëzh—$Å„\‹FEQüó‰D©T Žã„,%u]Çðð°?é‰.˜H’Är‹éHªÉ‚†ÈÃî—€BÖ€¾ÀUXZÍ mËm•%q+7!XVÅ•NR†-ùw~§îßÅ¢^v™(Hé°M(­^'`¦=h†,¨ÅÕ*ÅÒ"%"Yû|ò/€þŸ6n ™iÝm4(ðÊ[óïÞðz ;¨¿(ú,¸vÀ_o4(=„PàÎC Þy PœI<²XÞwGøá˜83夃` Ô®õ ¿ò®£ÐÑ`5²¶,”AÊJ­mzÕÖàF²²x•ËBûìU! Ãû«"PÎR>¤ ¥û©žïzrl·Ä+*I©Ì†W>É»‡²TGQyªFÚ]ò¾SYS^þôŒ%ásÞkW:n{ù‰KÂmju¥6¢çEu·½6Ê”‡,äùÂæÍhGZ:&0½{áTóœZÿU˜æÖÑ͹5MÃ?þãÕ¸æšû0$+Èí'òÐ1R_ZÏu¿“²qx8ì”\³RLÃtÚ]÷&£q (_‡®e¨HÖd¹YÍr¯—é奘¶P<ÎÍÍabb"$(FFF011ûî»Ï?¶ÿ~ìܹ;wîÜyçPUû÷ï/ÛݰPÈ<úô{ß‹·>÷"¾¾z ¤"Ü_‚I¸«‹bZâù)ŠÈz^RRê‰Â„ˆé´ûYtEJBDÜ9¡ª`²f$…#™JçóaŸã@xm$NR:qRÜ™·ÆRM8UÛ õœg5(^·´Ûj7q÷D\[Šî/4­=ýµ7[Xßp3 ?“þ_¶ŹÒDò,躎LÆþÒîÅìÅu¥B¢unÔ5Ãt#-)ý0ÏâÜÜìNÀh2ר…cÛ¶aš& …4MƒmÛ!O¦iBQ$ LNNú±ÉrRøq%ËG†éj‘ ‘?²aýÖÇ ÿ1`h’ò‹Üp´Ót'•ý,5¤p­0ø_òö§Uà[ÑÖ¯÷W§ÔL«ÔŸ §åc†aÚ‚fÉÑmbøx{ìŠ_þpxúi`Û×€ ‚y‚ Oé#{ÊœT à³¼*€!ïzq$@qãI™D«¤l¢c²)·rµJ6QGJ´œpBRB>¤¬ETÖû[ð>ûJR¸s#R2ZB:´q3ã•¡ˆ°e%åo#P´%à*Æ4!}²PT‘‘ò7…v\!¥! ç!¤¯{ÇÒ+D)Ÿ-¤“Ê£ P扊WÀ(…&¥CùǤ¶²„ô†„zÓsE¹r—ßZzO’‘ºHBÞⳡ68rõÕh7Z=&°6é"€OØŽ_y#Lsw¸ý¦iâèÑ£xá…§ñÝï®ÀªU® Éç‹C2º©Û´Ò0Õ¶Ýa´Ó,3™°…æ"¬7rœ¼ô1Lm¡xœ™™ÁÈȶnÝ:¾mÛ6ÌÌ̦¦¦üëˆÁÁAlݺ>úhÝ Û¶¡( ž{¿†wþÍHäË Wò.Á,8j-Z/Òq1þ)DßíÅbÐÁɺ–uG²Š¤tÀ„9^œÐ¨ä*”YZºEÀ7[8³€b[¾?àT*X? ضíÛ ’$#‘hŒŠç@–Ä´cItÉ"Z!“û‚…®‰nIΈîw ²–¥<›ù^‰®—¦åcú³ëxqUh‡m#]þض MÓ| EÇq iFGGý²,crr–eÁ0 LOOûêEXéÈtÕdAÃäÀwM$¾ò hý€|PV´ºæMÀqêOc  Å®%­w.׺-Ù´Ã3.V餩ZËÇ ôÍ”QÏ!¦ h:°îsÀ¹_Ì•À;à:FQl€ûÛ5 W¾’rNàœ¬µîÒbÜï›JË\­œgò¦‘Mˆë zÉ”QA™ø.MÔ4Ù€,yÉxZ']4‘K*i»< §"šÀI@J4¤|M@! i±(î"]n¹×è^9H&È/U P3𵡚øÓl)Ò RB=àx›ÉOÊ/¹çýÛ½²NÒz yJ{ÎåMdÈ‚M¯îʪp@'ÍåBqí^À¼зÒæÚn#…§ @Ÿ#‚h`¤¬šÑŸÇÒ9 @áa@[ èW×’bV°«Pnl/c…V ¬ßÌKàÍH_‚ Ìat7‹sñB¡€ú§cË–ãá‡ÏÇ5מêD/‚bLÖjnâr€,—‡ô¢óæä‚éBÚBñ¸uëVìÛ·/tlnn÷ÝwŸ¿CáøñãÐßß©©©ºË`Û6žøìgqòª« ~À—¶?o–( 㯥ÔëÏ÷]¤’5 óÌ´ç@¿ó|àío Ã$¯pi×™¼,N M3ð¿J‹ Ñ…J*Œè_U–Ešr9ÇÔiŒ(@%SÍ–Îj@ržÎWàHÇ,ËeŠGËî¸ã< ¿ŽeË…?àîz¬ÐY„→Kcò³Ý‹,…)èpTOkU´£I JM®(½B!¬¥´)>¨¸áò!×Í€›ÇÀ€+D+b’]4(¢{ÈÅ1¹‡ rˆõ$ lqÍʸÊPÚ/e\,Ã0Íf‘N§}÷ª…BÁW>†Ó4cŽ Ó­T“’¶,Ãé_€l3•Ž­Ü©GcüV•AüQ 5Ì%¯w«d)í2m%ªÚ”˜Y¢Æ ôŽfÉq- à“'CžÙàÐÀþu@»l>2e¸æ‚ÞfE)ã)÷úh]é9r»víÂ; é$ ¯mbwEY:_íµÒJ«Çï@8ªEWBƒ—Vå]¡ÝÇÆÆ055…#GŽ´°qjc)æßøÆ7055…={ö”YQ0L/±k×.?~[¶liuQª²TóÇûm$àÎÿ løµy–r¿Š@¹$úF%¥ž¨ø"©äTB`ÜàÀU.ŠÊ1 ˜Ž)¨&ÜC?ãQ…C&r}Ñè^ô;ZiXBóhÑ·«˜†è–ÒËY) !S¨œdé}¬âz YiŠmTŠœ—bÒˆ{U²1iˆ-i‰Sôs+–AôK«À}®ôÈ¿”pÔÈÅþÉ^žb°FÒ’ÒÛ”Þ/±j$Y¸Ÿ¼ú‘o^Úù%ßùÉwðƒü€× o¸ÁWfÆ!ïrÝ<„Gd|èC3xàûðÎw~ßûÞj÷ZaЧóL§066†‰‰‰ºÇm¥xœ™™Áí·ßމ‰ Üzë­Ðu}}}u§{É%—à}ï{ß¼‹*ß»àlyâ´·\Ät!œ¸HN«ò©l=ã/‚'MÒK‡Pø§7Cêæ CÈ*®Ò!“réûŠ·\.}¦§ƒÕtQFd2áÀ~Qª ]E©îæ‡bGÑjyt¢Lf3$Eã0D-I\YE­™Eó‰*u£«è¤‘!ek\YI£B¸4æ«à¶7™€‘Â/Úæ¢uh¥äbÙâÚ”LÒ(2p´ÝÈTKlã(QE¤—ù9ßµkÚ•¥’pÙe—ùІ‡ŽÒŠÕ8}á;`Yë5“ì/ì“Åœ$¯¼òlßþ눎TéQ-[æ~Ïd…#éò5­ú+\+$&Äû£¾ÚEœ1€¸¯ R~b]k1( .)KÄ… ª¥=ż㔺™Løš¸úˆyW2 óŽ+‡èÍ­Òsó®%äV¥|’Æx#&&&011]ýâÑ’1ýÞ陲qÍݪm&Ìår-Eñݦ@Ê{9ióƒeY~ÜFUU}yDÊI†i$´kxll¬ÕE™—¥’ëׯǾ}ûPø;@9 d.ob¥’ÉøíÎÍ@{·ÑÓ<ÈeCÌ;Gs{u~pã7VÜœÌ0½Ä¾}û¼ùÁD«‹R‘¥ž|éK_‚ªª>lø"Ðÿ0ð;_.¤9ë4*›è‹ ~WTÃ}¨r_³-œæ+›„ÚvÕ2ìiD:õ¯Ô Ÿãòˆ«{Ô…Cµ:É5\_©Nâµâ´ÒÆv1åì»þè]xÞ…Çv=VW.%ÍZ3,?|”án8Öu¹\Š¢ ¿ÿSxàk‘É Â0Ö‡B£¥ÓU³f˜¶bÏž= ´âqjj ·Ür FFF`š&+^݉XïÎÄt:•o½o{òÕðÂq\«@ ~&*x, ¾ù¢ªÂø¯G6–iËÈçeH¦»¸Mº7w Q ¯„ÇMþçSNͲ¥Ö´ømµÄG©¦yhDÑ”¸²Š¦Wµ¤Q©¬qŸEÄg—WµºH‘w#.ŸZ©:4ðcSåÀ7ùJ`îŠ9Æ]“3×JI†e¹q†q©Ô4$é÷|+$zTä6”a˜ÆÐ’1ç©›dw—«l:j=fÎüÕðLxeYÆðð0lÛÆää¤oí…]«2½N-² ^9`m…ï­i´Rñ'úóî5h°ÖÊqr«ž=ÍQ:ÐW+× †i–Zœ8q>v Ð4Üö‡%|`ýZ ý‰  à[4’æÐ¶Ý˜oäÓ4ÝK£†j­ ˆ±¥ …‚ªÝˆ‹E µQwr…B’$ùg¶mC’$†á×O–e†MÓ0::Šb±ˆ\.MÓüôâbøUj'Çq`R©”¿‹…òÍårÐuÝ?Ni†L&ƒB¡MÓü:R:†aøeQUÕ/o:†ªª~Ù,Ë‚ªªH§Ó¡¶ zZ–Û¶¡ªª_v˲ (Šïâ/N£X,úÊKÇqü²YmºÍ¦ÙrÀYwøÙ1ÚpÈ;¢ ™t=-ºžÃqŠP¥-ûÃt+-d³îlà7¬¬k\ÃG1G-P¼F ø]ËårÈåreÙl’$5,Ãt+µÈ‚ºå@.ëŠ÷C9½¾ùl¥Õaµp K‰®·vËw+­[mÅÞQZ¹NÀ0LûÐ,Y°c×ÿÁYàÁÿHÿo«kÍ0ŒHËǯœ€2ýŸ÷Ï;ŽÇq`š¦¯`´, š¦ùÊ´eË–!•J!—Ë!›Í²,躎¡¡!¤R)?]×ýòÀðð0R©FGG‘Éd`š&t]G:F>ŸÇèè¨ÿ7›Í"™L"ŸÏò,˜¦Yvœ‹CCC!%µ)J“É$ŠÅ"Çñ•–în˜´÷Z¹KÙ™LŠ¢ P(„”™ç˲,H’ä§AJOÇqBŸé¹K’MÓ|—~¤˜L·¹Sñ¦Ë³Pϸ1Á¥Òu¾KdE‰´ßž Ã4V )Ež0 $%W鸟wÚB¿eŽã ŸÏû¿$φ©N-² n9P(øn(«›¬xlµª•´:Æd/ÓJkÏEÒÊu†aÚ‡fÉ‚‡ã l|¸FckG†i7Z=&°/½êÓ³þú€iš¸ùæÿŽóϾúÕS8yòó¸þúT¥Ú Ó“,+•Z¹åuq°Ù¶m[M‚cll ###¾ÉµÈ'‹‡Q\Y£O|Õõ¯˜JÅ.¤Ó®u£e¹s¶f͙ɢ ph¤¤"e)¤dYF¡Pð‰×’B¬ÿha”¬çhq4‘HøJÊÑÑQ_y©(Š=)'%IòóK&“~UU -®Ê²ìç#Ë2LÓôcVQ”.Yär9aV´t¤…\RÀÕ²xë8ŽoùH÷¤Ói¤R)¿ît}§:ϧ„ïx»2<<Œl6 EQ°k׮ʓ;„…Ê¡zx™§^…qW Š¢`|üçñÿ°ÓßLPÉB–aº ½gÏžV¥îzõ Ò§ýŸù·LËLÂíX+–eù¿9ªªbhhÙl66F,ô ó“;…E žú)ö ùµ+´É€aº‘^œtËXˆaE·ô‰ÅÌlÛÆ_ýå_bíûÿóav‹Èô6½8&¨Vïeò“G ¯‡`Ù2@ ºärÀÎñ©Om†e¹òÃ0z{¯!Óù4bLÐ ¥‘ #Ó/–pÕS/ÿY/3]Ìå‚¿¶í ÁëꢰmÛW؉†¢»ÍD"UU¡ª*FGGý˜Pº®£P( P(`zz†aÀ¶md³YßÚfÓÓÓ¾¢/™LBÓ4X–…ÑÑQßò”xÉd“““Èd20 –eù|¶mûrIaH.@SžoYR.Ú¶í+â剤D´1ßTt?G ·ò€$IeyP=Ä…`QÁ] ®¤\ì$¥#XPv uÉǵý­À©“8uj#GÅÁƒô~¹ïïðð0:p_Ãô 8ð= ö7évÀ‚Óq¡Rž~û‰R©òù|ÇýV0L'²h9ð#ÎÚ• r§Ì0LûÒÉ(†i‹‘kO¼°â_í+­®Ã0õ²cåŠõeóÒŒoÆÝw»kŠ’äF`˜^ç¼V ¥ž¸j9.sŽºß…“e¹ɤ{8•r…Æb”ަi"‘Hp-ÉÝh"‘@2™„a0MétÚ(IÇÁìì¬o¹˜J¥Íf‘Ïç!I2™Œïö”“¤ì#圪ª˜žžF6›…®ëÈf³Èd2¾¢1ŸÏcrr²,C×uäóy_i)I²Ù,dYö•u€«¸•s¤ìŒÆ#d˜¶Å‹«$c-ž{îuøû¿¿ªv‡P«‹b†aºË‚uɘ?$ HcáJG ˆA\*•Ú6ž.Ã0ÖeÞ¸¹Õa†a¦¥œ{Ý[°ù‡ç»_Û4ÑQ ‘þEc5§Óîñ¡!`Ù2÷s”eËÜó‰00àÞMcÙ²ð?1PàÞ+žæcšåiÔ’OÎgqù ,<oxAùDÏ×’Ot~*æ30ÿÎ2!ä¸ÝÐ^¦¯dTï|ç›fŽ,À0jñ؆ãàèk—ãâ#àüS†á 2”K¥çßܤR ¾t: Y–ýxƒ©T ¶mÃqLNNú‹”Q눨eÞBï‰s÷ÆÖLÏá½óòÛÛ–ðž÷<¯}m“Ú0 8ŽÃî¦W0Mལ°? X«n|ÇZ ªªú1vÞ¼À0€sÝ$”Ã6´º$ Ã0 ô’#C—âÅ¿Š\æ»È þO Ÿ_@ñ–$©\¸¾Åõƒ¸µ»èü º§ëá4âÈd\e¤$ET(•Ü2R™¨’4“©î’ÊJ÷F Šâ^£ªî9Ë*×´P>¶]Y S,º÷:N|ݘuÏWJƒÚÚ$n“Ú­Òó¡úˆÄÕGó€FÛ”˜žvÏQ^qùLOÏζËË+>Ÿ¨R’˜œ¬¿>µ¼o À|î9`ãFw²»~¯ú"áÙgÿú§»49n<ô9½«x,`¤~Î| oÛæ¶,wÓ‡$¹¿ Ñ󉱓ɤo½X(0;;‹t:ퟗeÙ_œ$XÈ0Í!¿T*Uö<-˳Ï>Ûêוa¦elßûGøÐÃ/CýÎíµ+÷†é~L–¶ª ü§ø|ñ‹ûqÁ¿…W^¹Š>|ØWÆ0L˜žUë%/–å¶%µY´íÅ÷AQܸmÑu#º¦Ò³sœòØqôžÐsæ¿_|ÖŽÄ£X€=ÌCŠuY«KÁ0L»a¿ø"¬+eì.ù¾›qÅW`n.8ÿÄߟw<Ê0½LÏ*§–¯B¿ó€`|–ªqå¬ÉÍ,Ëe“z†aÚ p.X†‡a``_ùŠ;ÁÊår$©lAa˜àZ@>È+jíHHl)Â0K ‹ç¹ÆL§ÓH¥RF±Xôç €ky§Ï$Т€IDAT뺯$Ô4-ä’)ª¼Š*ꢋqrGt*~/«ó<ÊÆ^ ™MŠâzî_êöWU•祠Pp•€¢2'›ľ8<(€W‰$Î#lÛÝÝl Ñå''+»pL&Ý¿’ä¦Ï££AÚ@8ÿtÚM_L{x8HCQÜë)|>—ŽêHuˆ–‰à3åmšn:Ñw9‘k¶ížŸo%ZþhþÉdxW¸iºuÛ¼X +ïFGÝëèYÄþ@qº€@ §ëárF˕ɸ׉ÇâòN§ÃÏ:• ·Q.ç¦!–z:¬ì£6¬Ô&–å^CAÅ'H#—sŸ)ÕS’o“‡_ß7¬Å}_ŠñT xßûЫ<ûìª^×½2 ƒ¥ëPÏáèáóqÁ…À4]‘©ëŠT­ †é1zSñx»‰Ç>yÞñÈÈå~†Æaš&LÓô]!éºY–Ùº‘a:ÇlزŒ£?= U5¡(W€ó‡]%2Laö¿òM€tùüd­BîùÈ… Ã0Ébö&S\D²\#7¤Hœœœ„¢(ózOà ÓæÐ_üöÛééù- ¥\‘G˜¦ûOTLåóAz¤ÄŠ*ÎDt=(ç訫x"%iO’ÉàX´¬™L T‹«‡$¥R`Gÿ4ÍU )JX‘).ºÊrX¡–˹J3Q‘¨inùE‹=‚bàˆ×+ŠÛFâ÷¸:‰éÄ­Õ(JøÞès¥v•¤@‰™É¸ÇTµ²5g±<³¸6M¥ªït7l»<UuŸ‰ØNt =Oº×‰¸ý£çiÛÀÐûWL‹˜˜@¯ò쳫põÕ­.Ã0í†uÅ›!þuõS8yòRX–+οýí9˜¦;à5†‰§÷¦‰Ü‘V¿ô xÓšg}«Õo3ýø"µ¸b¦M9`ÃþøåxñÿÄÁŸ3‹¡¡!äóùP "†az€Ï`øj൛¡c~ë'ŠGÆJG†é-Ä8y…BÁéJ.N¶$d˜®B’ª/Ô;Èå\¥—,—+ÑDR%DåÞäd¼›LZo~S­Ôš¸s%:߆lIr•d’Ô-ªð¿ åí/Ióçm“Jç«Éj1 ±L”÷|é7rSz-sÒJïhµ6ÐõrÅ$ƒ_þ壨±ãâVƒa˜6Ãù! ?Œ_t§_¸šFŠG×¥>¯ 0LezOñ˜Ë!÷é;pÁ¿~O=õËÈf+{;±, †a@’$¨ªÊñ›¦8%Ã~Ãf¬zèlxs0±ÈçólÀ0½È·’ÀíPú╎“ p7!‹Ež\0L`š¦Ѳ,d2_ÁÈc†é"ȧèšr)QUWñ3:Šy$jÝYéºFÇ­§r.4–Õ·–ñ“e¹ŠGÞì½tˆ–¤ŒÏ»ßýø§a˜(ör@[œ<ùC¼ç=ï€ãl‚$}}w³áÃT¡÷…¬|ýæoážÿ*òø×qȲìÇca¦ó±ns§“°ý#³6£P( ™LúV Ãô¹p °7½±¢¥#ÅmSÅw­ÈŠG†énlÛ†a¾e³¾ÐEv†a: r!‡íý€ @à Ø±dG®ËH{Ÿuï>ÑxQðyà% xIqÏå"ùŠ÷©BþÑkr1ŸÅ|dá>ºFBà[^ñò úXÞw%’ŽéýU¼k¢ùP;H‘tl¸oÔ€×iA:Ž÷ODà(ÀFPµòúR>9ïZÅû¬FÒ°„ë)[¸_¼FÒs„ò‹õ‘„çGµ˜¶ë#¶¼2ÆÕÇòó¡çòQcÚ-š"\/G®‹ËÇòŽgÜüú§ú±êÔ*0 Ã0þ<ó:R'£GB×LLl(Š Eá9ÃÌGo)m¦ª¢îU,{æ&hZüæÀt: Y–‘ËåæÏÂ0LçáܼA+áÇqÝuî1EQØEÃô"ß0aËiÖ•B=K’„d2 UUý8n Ãt/…B’$Á¶möxÂ0½B¡Äß³¼£Þ5¤ÜRà*„,ï³ì]…AÂÊ%RøÈðïó/yדrˆî³#÷‹Š0ºÆ¾‹ˆ ,+æ3)Á2^ù-¸Ê4Ç;'*ÉèúlDò"1YðÚC¹æføÙ-WÊ+_TIiæÝó•ò‹V$±|ZL>’—?]“©/Ýg"PpFŸ±)_4ÅK‡®Q+Ô‡î«ô.‰í ÅÔ—îKzó ȇÞIÂ.=~)úGúÁ0 ÃÎÝ÷ŸÐ!?oÈâ ]ݦéþhðÚÃÌOo)eæ'¾€?ƒ§3Ö¿eYÈår(‹HU þÍ0LÇaŸ^÷“Óø1ÞE)Âq azzºþĆé,^–û/ÊnV …&''}eÃ0Ý‹mÛE±XD±Xluq†iëúS7–bBs•7dU–ò>—bnŠîGÐËÙ ŠJΓô ×Wº/ΰB¼¯Ò>Ê…æ· R¬œ†ot§»IIœbTß§ÂùªS T Ò'}¬âåã ƃ2¹è]é>Ñ(°–úˆ÷Vj{¥X®;õËH…´¥bÐÔd *WFó!#L¹”ÇÒÊó‘Hº`[ K£QBéùXº›ž¸$f§üŽ|ïH Š©Û¶aÛvȃ…q ¿¦iB’$ž!IÇ$IÈårÐu¹\©TÊß%×u¦iB–eØ^\Xú¬ªjÙµKq,Ë0MÓ¿6“É NûßUUõ¯£v©õžJù†l6‹d2‰T*U–ã8°, ªªV̇î+[¡P€®ë( ±e£¶˜¯ ‰2™ …Bl}(¿¸{Òé´¿ù-Z6Ã0ÉdËåÍfCeŸc´>©TÊo·¸¶¦wÐá°.Žóõ+ z–eáüóç ËoõN9¼6À05Ð[ŠGOmz Žs—_.ņ&( ˜žž†$Iì^•aºûò‡ñÓ#›°bÅ—ücÙl–w*1L/ò¾,Ì_Ž_ÇÜIÞää$Eá1Ãt9¹\–eazzšÇ ÓCœ^½ø³, I°7Ö®r‡Œ °ÕZ)ž„¿äùÂñvÆDØ3gT!çuµÓXHH'ÝŠ:Ç)ã¼rj¸6–k®þÌ3-¨aûâ8Žn€¯ø!åà*eY†¢(( Ð4ÍWD‘B)™Lbrr‰DÅbÑWѽ…‚ûÔ4MƒmÛÐ4 –eù 4r/Ërè¸ã80M3¤<"¥–X˲ü²FKŽãÀ¶íŠ §ùÎ(SÀˆù×;¦ªt¿¨¨­t¾ZÞóÍïDep¥rÕ’~4 ñQ½GQ”Øóâ5qåÓŸYµöϱâÑc¯…Âè-¸þÜùøOÿéǸ馳å·ú1àó‹˜aª²¬T*•êO¦½ÃÈÈF®AÿŠWqæ×ÿ§¿öB׆I’|áÁ;˜nf×®]Ø·o_«‹Ñ’z¯WÞ…ÿñÒoà}ÿömüã?^¡¡!d³YGÃô ˜˜˜Àž={Z]”¦â FFà6»nVã¦Éd’$±+f¦«ûD/!Ž…lÛö9ž#Ó«ôâü€ÆBÿñÐoŒž(Åp€´2À³¦PP@5ŽW阯áÚ8x~Œ…,ËÂèè(òù<Òé42™ †‡‡}O(ZTÖµb:†išH¥R ›G òùî8r¹œ¿[¹Ó Mª´‡ÊÓ§@QË þ€ªççÛaÛnº —¶íþS÷þjÍiYAù©Ì”7ÝÝø+ÖGüLH’ûî‹»¦—óyê©ËÐc:Ç2‰R©TÕy€iºí)ËnÛIRð9úÞÒ3‘e÷œx^¼÷CB¼/úÌ9ŸùóÜ´£××’}Ÿ¯‘<‹«,÷©ª{žd øžPöwJÏ4Ý¿$sÅ÷MÌg!?QŽã¦#Êz1Ÿ³g×ÔžX±þ§ë1zàŒ¸7Y¹È´2*{Ñ’B¼§\fa¤ÓiȲŒT*Y–}÷ëd·Qmý X,ú®8E&“©ÉÊŽa˜Æ`þî¯Cy øÁøóxë[Äõ×_ƒt:Í“fôŒâqù‰0½ý/ÜŠÍo~Àzÿ\:F>ŸgåÃôOãrýÎ 4 ÃÃÃÈf³láÌ0½È½,(Ðκ_iùÿþßïᡇ.Æw¿û.lÚ´ §OŸÆ/üÂ]ÿ(`çÎàs_ßSX¾üúúžÂêÕÏáÈ‘w.¿ü.<ý´{ÍììvÀÆ¿‰3g>á}7°nÝ:;– iãÆßÄsÏý÷-ò@L&\_©y®I LexÇR1×+¦Ñ×÷ ææ¾]s>«V݉ 6ààÁ Ê'ZŸµk?ˆ“'7Øçw7îÆ¡C#pmNÈq˜†¾¾>,_¾³³³¸êª¿Æã}}}˜›ûÏ&ý4V¯~«W?‡õ뿇Çßæ5¼²ˆŽîÜú¸iüo¸Ë|)¯Çñê«?F°ôç~^±b.ºè"œ8ñœ;÷#/M€ƒ¾¾âÔ©{qîÜÚH›h^ú\rÉ%xá…O¡TZÓnÜ€c“8 ÔGÅWüg<õÔ_–µýÀ€ÙÙíØ°á¯qøð.¼ðx饫bòÑð‘L 1MÀ0¬Zu/ c5þøŸÆ/üÂwü>žLþ ²Ùß ÝóÆ7~Ï??ˆÙÙíØ¼ùilØp¿h¬Á(ÇÇu×]· çÖMX–å{@¨7ÔB£=*±‡&†i.öýÀ›ÎÂ:ôçøË¿ü¿ø¥_r`Yže˜ Ai{§é ÓZzÆÕêŽ+°ã}¿ŠgJáÃ#+°aÜ>}ÇŽÓ_|ûõaãÆUÓ’½ÿ¦“éU· qÝûññú Öø;xü/~¦iú±¦×èuWJWý×OcàF€™ Ã]þù¿G©ô¬[·²ì. Àììv\qÅذáV­:…cÇðÄo†£<„k®YŽ‹/^‰^¸p饧ðÓ³€Ùu‡¼4ÎâäÉå8{ö<¬]{kÖ¼Üê¦èH6l؀Ç×•ÆæÍ›qúôéyÓqÃÇBÇV­Z…U«V•_ëÖ­ÃéÓ§qúôéŠç×­[‡ƒ.U†ÚpóæÍxðÁñG/ÿQOºZýÙÏþßøÆ7P*Í⪫VbõêçpÑEOâå—/Â;Þñº%ÉWŒ÷cFÍõ<ÄÅEQÁAÇ+)=(¾-²Ó‚i­Çhñ;jQJd¾Dõ(&Ä…òùþF©TÏùÑ|jƒ¸ºGÛ'î9Òs6M3¶œÔfq ÉÑg.~?vlëÖÍâÒK߉_|Š¢øu$J¥7`hhlÛÆK/]…mÛÎà±ÇžÃªU§BùPZÄC=„o~ó›è%ıeY¸ã¡;ðÔSOáÉ'ŸÄÉ“'ý뮸â \tÑE€skÏaÅÉ8·öNl9X¹a%JÛK¸ø¡‹±víÚ²|N¯>#—ÁÊ—VbÕ©U8½ú46Ú[¦cÇpüâãXùÒʲko:Œ3žAÿ ýX7»Îÿ—Ÿw9V=» _ø8ŽŸwÜ/Gÿ ý¸jåUظq#8˜Ú8…U«VaùòåXÿÓõ86t gΜÁéÓ§ñòË/cùòå8sæ Ö¬Yƒ ¹¯yÍkphƒ;žyñűråJÿ:Àý}<}ú4Μ9ƒþþ~ÿÜñãDZfÍœ>}Ë—/ÇùsçcÍÙ5˜»d®,ŸÓ§OcíÚµþ=qùDïyñÅÑßßß±÷¼ôÒKxòÉ'±~ýz ¶EÙΜ9ƒë¦¯Ã_}ê¯ZÝ=› Íî½÷^8Žƒl6Ûê"1LKéÕ5C±Þï²€Ÿü°ˆƒ¯ÿcl¿nÖ<~eÈP @õü&Hæ½T¨ Á†í_KŠL ìHd_•}20M¦']­Ža||sss¸á†°gÏ V½ïÅÇaf÷ÿ‡e ú>6ùæ#8»æ,ìOÚø>¾º>ºsÁöþ\`Á‚ :Ê]2-FPš H`Âô?ðÏ1 ³x9pzù;¯û…{±åÛÖ]½ŒÐ¼äý'C®:Pû¤ 2ä²ÁAµû©o[° C†Çï÷¼Éaæg±²rﺯyî‹øÀñ?Æ‹™GpÞï®ÀËvJ?ÿà€{c&*¤õC“êÃ$^ãÉ/âç”͆íËúîÀ[ð†ìgÊÙ¼ysÝi¬Zµªj:ëÖ­[Ðñv«c+Óo&õȳïß…K?ýdEÆŠ+cþû½khÓ¡Ëï£ £Â”Á@Øb ZÌq­†ûQjY:’Œ‹H¾Q;©PaÂôÏ•ŸbÊIãFìùPÞšä¶»æÎÏdMßWÃþ1 š¿°‡ ³lþF;Ù¡Âö’ð›`ÃöÛAR%ÿ;á·w?•“Ò¢1§ØVÔ¦ HšûP@Áj,X~9é>÷÷):W´„ß+ Wh;2Î}é¯_ZÌ[Ó6,VœZu ¯™{ Ž*G¸ððë°éÌV\xá…8~ü|¬^ \pÁIu.Ä©S§pÞy«kמé“›0-ŸÆÆË03óúàØ±Ÿ`Ý: ÇŽ9زe <X¶ìYœY~ .¸äœ={}—¾Œ#GÇW\§žz¯ýkð“Ÿ<Œõë·cnîE\pÉ9œí{ +WE©ô:œ={—^z!žzê§XÅù8rdëׯǑᅧk®_ƒü3aµ¼ Ë–=‹sç^‹åËÏáìÙ³X;´ ßüÙßàŠ‹¯ÀS›_ÀÞ°?þñOpÕ‹ÿžêû.Ölq¯Û||-Ž^|ñ$Ö^ûc:4‡õ¯À‘mG°iÓ8tè(¶n½OÃëžûyœþpæÌ›°|ùr8ò#XuÉ*\ðÈJ¬Y³ “¥ï`ËñÓŸþ—½_h¢¿¿.¹ÄÁ±_Œ—܇͛§Ÿ~—_>ŒÇo{ÛÛðøãßÄM7]‰¯}í§xÝë6á¼óþ¯¾ú&À™3§±rå*ÌÍý;ÞøÆ·âñÇŸÂõ׿ ܃¡!7þþ~ÀÞ0‡Ã®À‰åÏãõ?Û€Ç?ŒmÛކǤ,ŸþwŸ„$ÃÙï»pHQwêÔã òyàqlÛvž}ö'¸gΜÁå—ŸÄÌÌÅžÒuÖÏçÙg‚•6àÉW÷ãmWâñ{ÖcÍ¥çaÙЃxùåÍ€³çÛ‚!G/¶Ð']Œ?Üë®Æ£~ ƒƒn}_W^yÃ6ž;]ÂéÓ%¬]{G¾ ¾åµxîücÛê·àñÄM7]‰ù—¸ë×?Ž#G®òÚí V®\‰—^z ëÖmÇÁ‹ÿ›7¯Ål±„cC+qìØ\xáJ¼üòù¸à‚9¬|qe«»sKdÁ?>ô°>`áÓoût««À0LÔ3?Ø6¾«Ø€ò+xã÷~7z'þãOÿ#àú+®­Õ9pÇhï¿Z±¼ÿ€`mQßI¡µ”}'HYïú!Ýßnëâ]ÔÍHþ:‹ûÍÙèy°¢¶=è(‹G$0ÆÆÆ÷ÜsOÕûެÆþ˧0òiÜÿ™?F:†ªª vW@;¢»¢lM*=%#Ó]D-cÅg,*” O ²r[¼&Џ~äGðÃØêfZ‹•°ãÓ‚ý4 Ïü=~ùèµøµu¿†K×\Zv]ذ¡C‡ ;´ˆFJB6L˜!¥Aܵø#É´‹íµB}R|oZ5Š.vš0¡tdµÎÜÑ[Ϙ`ÇŠx÷NâùË> oÅG.ü9 ~`ÿ?ÿºñCøì;? e¿Ïìõ€éFh—'Z<Ö3&صkî½ê^\ý+Wã?¾õ?Öô[ *!«M𣛗 q²M¿7ℜÊJŠ3qbM‡ˆ´Íôþ£q‘X7Ú4!n¾Ð ù劶àÀ½ì·‘änt¼ý.þ–Fdw‰iŠ C±Íè7R…êo7….öÙ)lkAlSúݨUZ’˜ž-}¦g$>{º/ú|þ3ŸÇ½poßÎæ±XY011¯~õ«ÈÌ® ÁÛßäZ®ZõUÜpà øä''ðÑnÆ]w]·½íÿ€o)ös?÷o8vlÏ<ó R)_øÂý¼‡ö-ËS) wÞy «V­Â7þßø†;ï8}ú4Ö­[‡×½î1lÙ²û÷¿ŒíÛ×AU\.\F]Ž©j;¹Ò5âg‚–<(Nm#òÑ4 PXú|2 .χb–RÜ]Ó b¤Vˇ®«–3VÌg!õ‰¶C¥úÐ}ÍÌG|VÄðð<øÏ륞ùÁÃsã§7þß}ÛwkÊK܈#Êìjc„ZÆ ÓjzuÍ,¿ý§·áÝÿõïqéß­ÆÌ‡E:†iš˜œœ¬šÆB D¢c? <ÞÇsÕ6GŠy8¤¤køÆJ„7U‹é«PËÖ­ãŽ1íC½k†¥xTUÕß©333PUwÞy'n¸á†Š÷áÏv<#kžÂ“¯î…ã8H&“Èf³×±ˆ» DAVÅ,ÌÔ³ƒ!n2OB½V¥•„~œÂªUtòÂÂbåÜø¡ßÇ}ÿí«¸éÞËðºç^Ç.THÜà‡¨¥OŠƒ ê íÃÑþ»–Äj¥™ššÂÜ·çpÛoÝVb- ž1Á–ç¦ñþÿ1üþÈ¿õý~<—FO$¦èdÅc=c‚]»vá¶Ûn+‹—Æ0½J'»U[¬, R[¶üΜ™Àèè(ŠÅ"r¹2™LEw¸ Ó­tz(†zæ•ÆB4‡­kæ³¢g˜n W× wíÚ…}ú§¸|æ?aúŠIüYövœ9sØw¡Ï:¦—è)W«SSS˜™™ ±uëV<úè£U…Çšo¿?÷ÃW‘>–†$I·¸Ø ‹B¤?ë¨r¢Ò »塘×B‰*CjÁRmR>ŸB¤]L½ÿîàßµº‹¢^9 á ôì/B×õŽ]dlå¢Ð|ý¤–>I׌á‘ ¡Ž,¼?4bgh#6tú¤.<~!&NO´º‹¢^Yð©·à¼#Ûñ-Gúî4²Ù,t]¯–mÛÐ ïÐÙ‹ÜÝT‡N¥^9 §¯èÙ±Pz±ŸöÒ³®W¼ð ¸å–7#ŸÏczz²,ûÊÆn•Ü'z‡^zÖÄQižÛ ‹½ô~°¶º,ôY÷êšáÔÔ¾ú?ÿÓŸÎãêô—ñ>ýÍH$Èçó£tì†~Ý ý´Æ=ö|ðÁºÒèÅãñãÇ ì¥ëïïÇÔÔÔ¼÷ž8qWîû_xògObô/ÿ;.ºè"LLtÖbë¡C‡ðØcµºuñØcáСC×öQŽ?Þ±uøÙÏ~æÿëDê‘tÿ—¿üeô÷÷ãø>Üê*-ª :õý#XžµžÇ{ Ï<ó Î;ï¼VeQÔ;&¸þv¯=þ6üü­¯Á+¯¼‚ /¼‡î™ÐéïÑ ò¬“ëðÒK/áàÁƒøáØ‘“ºFŒ îºë.¬Y³—]vY««ÓºEv,”Nî§‹e!Ïú™gžÁ‹/¾è÷©N£^YpèÐ!ÜtÓMÐQczà>Ñ;,äY÷úüà¾ûîÃc=†7½éM­®JÓèEYÐ k‹¡ÖgÝëk†çÎÃû÷ Xqð¿á¢o}ÿõ‰‹ð…/|gÎœé˜¾Ò ýºúi§;žyæ<øàƒ8{öl]étŒâ±®¾újüÛ¿ý^#½luqE__žþy;v¬ÕEY4gÏžE___Çv:bË–-[‡C‡áСCظqc«‹Ò6n܈D"sçÎuì3ìä÷`yÖz|ðA¼òÊ+صkW«‹Òt®¾újäÊáèìS˜›ûðs?÷s÷;ýý#ºAžurNœ8ÇgϞŶmÛZ]œ¦£( ¾õ­o¡¯¯o|ã[]œ¦Ð-²c¡tr?], yÖO<ñæææ:f'#Ù¶mæææpÁà_þå_pÑEµºHMûDï°gÝëóƒ}ûöáG?úQGÏQJ/Ê‚nX‹X µ>ë^_3|ã߈ÙÏÜŒÕÅ \sý5¸øâ‹;®tC¿î†~ÚéãŽ'žxGÅ?øÁºÒé ÅãM7Ýäïbd¦wÙ»wo«‹À0L‹á1Ã0ðû¿ÿû­.Ã0-¦¯¯_þò—[] †aZ φ€/~ñ‹î‡Ï¶º$ Ótœ…8Óè­[·¶ºX Ã4– Ã, †a9À0Œ ˆa– ð`˜v¡cäŸùÑG Ÿ˜˜Ààà`«‹Ç0L`9À0 À²€a– ø°,``YÀ0 ˆi7:Fñ;wîÄøø8æææ¸nûúú°cÇŽVa˜&Ár€a€eÃ0,†qaYÀ0 À²€a– ÓN,+•J¥V¢VæææpË-·`nn}}}˜™™Áž={°sçÎVa˜&Ár€a€eÃ0,†qaYÀ0 À²€a– ÓNt”⑘˜˜lÛ¶ }}}­.Ã0-€åÃ0ˆaX0 ã²€a€eÃ0,¦èHÅ#Ã0 Ã0 Ã0 Ã0 Ã0 Ã0 Ã0íEGÅxd†a†a†a†a†a†a¦=aÅ#Ã0 Ã0 Ã0 Ã0 Ã0 Ã0 Ã0uÊG†a†a†a†a†a†a†aê† Ã0 Ã0 Ã0 Ã0 Ã0 Ã0 ÃÔ +[ÈÜÜn¿ýv\}õÕ¸òÊ+¡ª*öïß_vÝØØ˜ÍîÝ»133³ óͬÏÕW_‰‰‰סÕõØ¿?TU­ë9´ºLçR‹,è¤÷¯’,è„:4B´ºLgÒ¨1A­×4£>:&ªË‚N¨Ó4sÌÐŽïðRË–v«s³dQ»Õ›™ŸfŽÚõݨGtZŸhÖZE;Õ™©f®)¶ãûÁc‚ÞyÖKM'Õùæ›oîÈ9v7¬{ÎÍÍa÷îݸòÊ+qå•Wâæ›oÆÔÔÔ‚ËØ.ï[SÖlJL˸å–[JÃÃÃ¥ûtÿý÷—î¸ãŽÒ–-[J÷ÝwŸÍwÜQ.Ý}÷Ý¥ûï¿¿ôÁ~°ôÁ~°æóͮϖ-[J÷ßèx-ele=î»ï¾Ò–-[J¹\®tÿý÷—n»í¶Ò–-[J?ùÉO:¦LgSMtÚû' :¡­®Ó¹4bLPë5ͪO'Ž J¥ê² êÀt/Í3´ë;¼”²¥ÝêÜ,YÔnõfªÓ¬1C;¿‹•Ö'šµVÑNufj§YkŠíú~ð˜ ñkíVïfÐIuÎår;Çî†uOÊïþûï/Ýÿý¥üã¥áááÒñãÇk.c«ë}&Ký>±â±E?~¼l@P*¹/ñÇ?þqÿûu×]WºãŽ;üï?ùÉOB÷U;ß,r¹\éƒü`ì [K[Y~ðƒ¡¼K¥Réãÿxéî»ïî˜:0K-² “Þ¿J² êÐYÐê:0I£Æµ^³Ôtò˜ Tª. :¡LwÒÌ1C;¾ÃK-[Ú­ÎÍ’EíVof~š9fh×w£YÐi}¢YkíTg¦6𹦨Žï –f­¢ÝêÝ :¡Îwß}wiË–-þ¿N›cwúç£>ZÚ²eKéÑG·^"[šµfîV[ÄÌÌ FFF°uëÖÐñmÛ¶ann055å_G bëÖ­xôÑG«žoSSSÈårøÜç>{®Z[Y™™LMM…ò€;ï¼;wîìˆ:0M5YÐIï_%YÐ uh„,hu˜Î¥c‚Z¯Yj:yLT—P¦{iÖ˜¡ßᥖ-íVçfÉ¢v«7SfÚõݨGtZŸhÖZE;Õ™©f­)¶ãûÁc—F¯U´[½›A§Ôyddûöíþ}ûU‡V׳Ö=ûúúpë­·–ÕA¤SdK3×l–7­VLˆ­[·– Œ¹¹9Üwß}þÇñãÇ ìÇ¥¿¿?ô£Sé|3˜››Ãm·Ý]×c;_µ:ÔzÍRAþ‡qûí·cffƒƒƒØ¹s§_Ÿv¯ÓÙT“òþÍ' :¡í “™Î¤c‚Z¯YJ:}LT—P¦{iÖ˜¡ÝÞáfÈ–vû o–,j·gÍT§Yc†vëTÏzdA-uj§>ѬµŠv|ÖLu𵦨N}‚êÈc‚¥Y«h·gÝ :¥Îƒƒƒ\tZ]ÏnX÷Äž={¸Š·ãÇc||[·nõËÔ ²¥Ùk6lñØ&ìß¿7ß|3¡ëz«‹S3¹\ýýý¸õÖ[[]”º¸ùæ›Ñ×ׇ­[·bff·ÜrK[ýÈ0½˂ֲ€iX´–L'Щ²b¡t“lY(,‹˜jôŠzW°`j¡WdA¯Ê€eÓ=tº¼î]»°ÿ~ìØ±}}}­.RÍ4[†²Åc‹™™™Áí·ßމ‰ Üzë­Ðu½c^؉‰ Œãž{îiuQêF×õP§SUãããøìg?Ûê¢1=Ë‚ö€eÓJX´•dÁ 7ÜÐê¢1LGËŠ…Òm²e¡°,b*ÑKrèmYÀóf>zIô²X0O·È+²Þœ˜˜À®]»Ð××ç[š·3­¡lñØB¦¦¦ü+¦ibÏž=±.n‹h[íüR111þþ~Ü~ûíØµkvíÚ Ðü/¤­¬€2qà 7øî :¥LçR‹,hç÷¯VYÐÎu ! Z]¦3iÔ˜ ÖkM7 €ê² êÀt'Í3´Ã;ÜlÙÒui–,j·z3óÓÌ1C»¼”Ö'šµVÑNufj£™kŠíð~ð˜ 9kíVïfÐ un÷gÛéëžkUddd###˜˜˜XPÛ}í¶Ö2Ör +[ÈîÝ»±cÇÜyç±¾šÉWn40çÄÄ«ž_jvî܉Ï~ö³¸õÖ[ý°cÇÿs-ele=¶mÛ›·øãÝîu`:ŸùdA'¼ÕdA'Ô¡² Õu`:›zǵ^³Ttب. :¡LwÓŒ1C;½ÃÍ’-íTg y²¨ÝêÍÔF3Æ íön4BtZŸhÖZE;Õ™YÍXSl§÷ƒÇK»VÑnõnÝPçNy¶¾î¹ÿ~ÜrË-ó^Óî²¥k6¬xl˜™™ñ5ãâ?Qc¼sçNŒcnn°wï^ôõõaÇŽ5_J¨Óˆÿ„«ÖZÆVÕ£¯¯###ó󞘘ÀþýûC.ŒÚ¹LgS‹,h÷÷¯YÐîuh”,`9À,†F j½f)è†1P›,h÷:0ÝK3Ç íò7S¶´KæÊ¢vª7SfŽÚéÝh”,è¤>Ñ̵Šv©3S;Í\Sl—÷ƒÇK¿VÑNõnÝPçv¶Ý°îyà 7`nn{÷î Õkbb¢á㥢k6ËJ¥RiÉkÆ”166zYEFFF|Ásss¸å–[077‡¾¾>ÌÌÌ`Ïž=¾‰}µóÍæÊ+¯Ä¾}ûB/l-ele=fff°{÷nLMMaëÖ­˜ššÂ­·ÞŠ={ötL˜Î¥YЉï_TtB! Z]¦3iÔ˜ ÖkšE'Ž €ê² êÀt'Í3´ó;¼T²¥ÝêÜ,YÔnõfæ§™c†v7# :­O4k­¢êÌÔF3×Ûùýà1Ac×*Ú­ÞÍ Óê܉sìnY÷Çí·ß޾¾>ô÷÷cff¦ã× —ú}bÅc‡@þ‚·mÛë³½Úùv –2¶²”÷àà`Eçv¯ÓÝtÃû× uh„,hu˜î¦úQ7Ô¡š,è„:0½K£ÞÏN{‡Q§v«s³dQ»Õ›i ÝØ'QïNëÍZ«h§:3¥ÛúD#êܨviE–z­¢ÝêÝ º¡ÎÝðlÛ½333¾›ãn_3lij`Å#Ã0 Ã0 Ã0 Ã0 Ã0 Ã0 Ã0uÃ1†a†a†a†a†a†a†©V<2 Ã0 Ã0 Ã0 Ã0 Ã0 Ã0 S7¬xd†a†a†a†a†a†a¦nXñÈ0 Ã0 Ã0 Ã0 Ã0 Ã0 Ã0Lݰâ‘a†a†a†a†a†a†a˜ºaÅ#Ã0 Ã0 Ã0 Ã0 Ã0 Ã0 Ã0uÊG†a†a†a†a†a†a†aê† Ã0 Ã0 Ã0 Ã0 Ã0 Ã0 ÃÔ +†a†a†a†a†a†a†©V<2 Ã0 Ã0 Ã0 Ã0 Ã0 Ã0 S7¬xd†a†a†a†a†a†a¦nXñÈ0 Ã0 Ã0 Ã0 Ã0 Ã0 Ã0Lݰâ‘a†a†a†a†a†a†a˜ºaÅ#Ã0 Ã0 Ã0 Ã0 Ã0 Ã0 Ã0uÊG¦íp–e5,-Ó4—¬¬¦iÂqœ–ä]/í^>†Y(•Þç8™²”ïÿ|ra©ó®—v.Ã4‚…¾ã pßg˜öa©Ç’ íÜ÷Ú¹lLoÒÈuJÇU6¦7©·ïÏ÷>GÓæ5ÄÊ´{ù¦¸ï/M»°â±ÍÉår°m»â÷nÂqŒŽŽb``ÃÃî{baY‰Ä’•9‘HT,ãRç]/í^¾^§—ú~#°m»ì}žO¦,åû?Ÿ\Xê¼ë¥ËÆÄË– c!ïx:F:®9mîûÌRÁc‚…±Ôc‚Fʆvî{í\6Æ¥WdÃR¬<&èIJ1½5hDßÌ—6¯!V¦ÝË×ëôʘ`©à¾¿4íŠÇ6§P(„Eô{7‘N§aÛ6fggQ*• Ë2 Ãhu±¦%ôR߯Û¶Q(0::ZvŽe ÓmÄÉ– Kƒiš,/˜¶ÇµÑŒ1˦èÙÐê1=÷{¦è¥ù@=}¾1A½i3L;Ò+c¦³XÞê4ÇqËåà8$I‚®ë$É?OÚ~Y–¡ª*LÓ„®ëÜÁ$™ŽjšEQüûÒé4R©”Ÿ¶¢(Ð4ÍOO’$¤R©E__ º¾P(p8Å着ÖÔ.â.]×!ËrCÏWb!í@ÏnrrÒf™L¹\ÎO‹¾Ó3¤ggÛ6LÓ„¦iþ@AUÕØöq†aøÏx!÷.¤­%I ½Cb+½Ÿóµc&“ñ¿›¦ Û¶ýúGŸ‘XþZî¥6©·î­d¾¶¯ßS›ÄõýVõ{±Ì­ìûÍè÷µô¿ùú>=?j—¸w¢’L‰»ždƒ$I • b{FeC+äÂ|÷Ósîv¹ ¶O§Ž TU=V õôýv Ð{"Ž èØèè(4M›×MÚBÚºú> ÂíÓ©}¿›çõô}z~Dûm#dC£å‚Ø6b[ˆý›Ç‹— Ô&½8_h¹PKÿ­$xLÀ}¿ÛÇÝ<¨gž_ܘ –´£×vÛâbäB/ÍxLÐkˆõŽ zµï×;&è‹GÇq044äwþB¡2M§Ó~Ñ®ꀆaø»`ÇÁððpè‡Î;Žã°4c‚h;Ö+–B.PÛˆˆý›Ç‹— Ô>½8_h¹PKÿ­$xLÀ}ŸÇñtCß_옠–´Åw¨ÛÖë• @wËtïb½c‚^ïû‹®w©K(‹%±:³³³%UUKÓÓÓ¥ééé€Òôô´^–eÿ<€Òää¤.›Í–$Iò¿(e³Yÿ»¢(%]×ýï©Tª¤ªê¢¯ŸUUKÅb±â÷ù˜œœ,«·ªª¥T*ÕóÕXH;äóù€’ªª%Y–K²,—$IòŸ €P¾ÙlÖ¿—ž}&“ PúÒ—¾TPš-˿ڽ³³³5Õ±X,úïŒØVš¦ùïä|ïg-yˆDߟh:©Tª¤iZÕ{ç«{-åj*µíw¾óŠý¾T*Uíû­ì÷¥Rëú~3û}-ýo¾¾?ß{PM¦Ðõq²¡Qrî«$Z%滿ÛåB· *«D=}¿dÃbdz³³óö}ºVQ”?ªc;÷ý^t[ßïÖù@=}¾÷ ž1˜W½²a©äå!"–‘Ç‹“ ¥RïÎÚI.Të¿”^œlà1÷ý^T:V‰néû‹TK»š\èô5ÄÅÊ…juïÙÀkˆÝ½†XWû~½ý¾k,iZ2™ôw«‹EȲŒB¡UUC»Ô4MàjpeY†ã8¾¹4}ƒ~Š÷J’TÕÄu¡×/qõwüÔ{~!Ï¥Z;ˆ;ަ§§1== ]×CZ}ÑŒ7nÇ¡h‚NfÄO>ù$€ ˆ+=÷Zî]HÐjÛ¶ËÚJ4ÅŸïý¬J‡v#˜¦¹ 70quï$?à•Úö¨ØïÚú~'ö{ ¾¾ÝÌ~OTëÕú~µÈ`~ÙP¯\æ— ,–ÄSOßo7Ù°˜1ø ãú¾mÛ0 Ùl¶î¶æ¾ß¸ï—ÓI󢞾G½c‚FÉ– ­a±rèÝùB;É…Zûï|²ÇÜ÷yLÐM}1c‚ZÓîÖ5ÄzåB¥ºwƒlà5ÄÞXC\̘`!÷W£Sûþbû}W)‹Å"×\tÙ²eH&“0oCÚ¶íû©ÿu¢êN†Ú[L©TÊè‹ATŠ¢ •JùïÄBî­Ñïqó½Ÿõ’N§±lÙ2†á ¥zhÕÝb©Ô¶Õ(÷ýö¥ï`­2e!²a1åšO6°\X:xLÐÔóFïëû¹\’$¡P( Nò,ضí»fYÜ÷[÷ýî¤Þ÷°Þ1A£dË…Ö°X¹°lh–zà1ÁbÛ­Ýá1Ag³}¿–´8 {×-S÷VÃkˆÝÇR¯42ïnéûµÞß5ŠG È™Íf1;;‹ÉÉI ÀXI€(Šâké_>ŸG*•*‹ëщDëmšfȇo½çÅ|/l­/³XVò;Ld³Y_;_És¥{kA–å²bó½Ÿõ@iLOO£X,"›Í.ø½­·î­¦RÛ>õÔSóÖ…û~åóÍê÷qeiÔ;X«L™O64¢\óÉ– K *SOßï$ÙPíÞ¸¾_Opø(Ü÷[÷ýx:e>—_#ÞÃzÇ’ ,ZÃbåÐÛ²¡]äÂR¯<&Xl»µ;<&¨L¯ôýÅÜÑEèÎ5ÄFÈ…FÔ½Õðb<½²†¸˜1A£ò:·ï/¶Þ]£x¤ ¯TqY–ýMÓü€ÁÔ@ôÀTU }‚@¤íBôaÖúpu]/«·¸‹£ÞóDQȲ fšN§!ËrÍ!LV’$lß¾Ý?FÁ¢ Ã(Û¥wïB&𦅝Ò.b¾÷³Äg wu’$ù»%âvUº7®îÔæ´c§Rۊ©þb?ç¾¾™ýž¨·ÿű™RI64¢\óɆVÊ…ùîÖ½›äÐ}c‚JÇ⨧ïwšl¨åÞhßWU™LÆÿGr$“É,صI»öý^Ý×÷»q>@4z\PQ²a)åß¿yL°x¹ô®lh'¹°Të<&˜ÿþh»õRßïÄ~_éX½Ô÷“öW\áë¶5ÄFÈ…hÝ»I6ðbo¬!.fLШ¼Îíû‹í÷Ëk.y›£ë: …†††|a¡( 4Mó5ʼnDªªúIjøL&ƒt:í Û¶}³ÖV#IÒé´ß™£ßçC–å²zK’Š'PÏùF“Ïç‘H$B;&òlÛÆÐÐo\<MÓ i’Éd(íZî2Å…¢(°mÛ¾Àüïg5t]÷ÓuÇ$S}r¹††† ˲ÿnÓn†ùî¥r[–ª{»¼ûµR©m?ö±á’K.‰í÷¸ïW8'/—²ßS»×Óÿ*±™"ÊÚÝÔˆrÍ'Z)滿›åB· *«D=}¿ÙcjûÅöÁZï­4.¨—víû½:&è¶¾ßÍójûF ;&è¹T– <&X¼\zw¾Ðnc‚f¬×÷y>P½}zaLPéX%z©ï/&í¨²¤›Öë• Tîn• ¼†ØkˆõŽ z±ï×Óï—•J¥Rý¼} í,íV ±,Ëo\Y–‘Ëå`Û6òù|èjÐvñQ-–] ZKßkÁ¶íÐŽÝFŸ_Šú.$/Ó4‘H$P*•üç_ë3¬çÞùÚZ|ÿ¢ù¨x¾–eÁqœŠÏ=Zv rL&ÜóÝw'mÛZú=À}¿ÒùfôûF÷¿ùÚq!õXŠrÍ'Z!s'Òíc‚JǪQOßowÙÐ ¹²Ú­ï÷ê˜è®¾ß­ó¥î¿‹,K!€ùe /ÄëÚ­ –Z6´ƒ\ˆÖu!yñ˜€û¾X‡nT:VnîûK™v7¬!Ö+âÒèDx ±œn^C¬·ïrß_\¿ï:Åc¤žœœôµÉ‰D©TjI5ðÕ…U%æ{˜õÞߪr7±ó7êÞfÔ±ÝÚ±ÛèÖ~ߨ4ZUv‘zúîR2_¹X6t>Ý*ºE.Kó»ÞŽõlE½ ÷ýîîû­€åBçÃr¡ýåB=𘀩÷ýîîûK ¯!v/,ÿÞ´Ób½cîû‹£k\­Î‡hL®ÈŒ´•Tò©+2ß.zïoU¹;fÔ±Ú±•tk¿oT­*{§Ã²¡óéVÙÀraiá¾ßùpßo¯rw,:– íUîNû~çÃ}¿½ÊÝ °\è|X.´_Ù;îûóÓ Ã0 Ã0 Ã0 Ã0 Ã0 Ã0 Ã,-絺 Ã0 Ã0 Ã0 Ã0 Ã0 Ã0 Ãt>¬xd†a†a†a†a†a†a¦nXñÈ0 Ã0 Ã0 Ã0 Ã0 Ã0 Ã0Lݰâ‘a†a†a†a†a†a†a˜ºaÅ#Ã0 Ã0 Ã0 Ã0 Ã0 Ã0 Ã0uÊG†a†a†a†a†a†a†aê† Ã0 Ã0 Ã0 Ã0 Ã0 Ã0 ÃÔÍòV |ñ‹_Ľ÷Þ‹U«Vµº(‹æØ±cXµjUG×áôéÓ8}ú4Ö­[×ê¢ÔÅ‘#G°~ýúV£.Î?ÿ|Üu×]­.FÓùèG?ŠW^y¥ÕŨ‹nxÿXžµ§OŸÆûÞ÷>üÆoüF«‹ÒTºaLÐ ïÐò¬êpüøqÜyçluQšÊ§>õ)=z´ÕÅh*Ý";J7ôÓ…²˜g}É%—àŽ;îhuÑ›ÊÌÌ vïÞþþþV¥©pŸèú¬y~йóƒÅЋ² Ö"ÃBŸu¯®ÞtÓMxÍk^ÓêbÔE7ôënè§Ý0î8~ü8¶oߎOúÓ‹N£'‡Âoÿöocdd¤ÕEY4cccéè:LLL`bb{öìiuQêb×®]Ø·o_«‹Qwz‘W^y¥+ž]§×åY{@uè5ºaLÐ ïÐò¬ê066†™™™žS<=z´ãŸÝBéÙ±Pº¡Ÿ.”Å<ë^œÌÌÌ`dd„ûDÀò¯6x~йóƒÅЋ² Ö"ÃBŸu/Ž àùçŸÇ×¾öµV£.º¡_wC?í†qÇ]wÝ…o}ë[u¥Á®V;„ÁÁÁŽß‰Ùßßß‹Z[·nmu˜¦Þ?–g SÝòþuƒ<ë†:0½C·ÈŽ…Ò‹ý´WŸ5SÜ'z‡^|ÖLíôâûÑ k‹¡ŸõbX»vm«‹P7Ý𬻡ŸvøcÍš5èëë«+ž°xìvîÜÙê"ÔÍÖ­[»Bvòn¦óé†÷åÃÔG·¼Ý Ϻ¡LïÐ-²c¡ôb?íÕgÍÔ÷‰Þ¡Ÿ5S;½ø~tÃZÄbèÅg½.»ì²V¡nºáYwC?í†qÇe—]†7¾ñu¥Á Ã0 Ã0 Ã0 Ã0 Ã0 Ã0 ÃÔ +†a†a†a†a†a†a†©V<2 Ã0 Ã0 Ã0 Ã0 Ã0 Ã0 S7¬xd†a†a†a†a†a†a¦nXñÈ0 Ã0 Ã0 Ã0 Ã0 Ã0 Ã0LÝ4]ñxóÍ7cbb"öÜØØ®¾új\y啨½{7fffu Ã0íO%YÀr€az0 Ô' X0L÷Àó†ax~À0 Àc†éšªxÜ»w/¦¦¦bÏa||{öìÁ¾}û033ƒÝ»w/ø†aÚŸJ²€åÃô<&`¨O°`˜îáÿgïíãä¨ê|ÿwÂC&©5Á8&Ö$BL¢@ ˆƒÂ¢ÕdWÖ¸Ýã^EÉ^Ó½z/]G»uÜÅ»Þn+²îêvÅßטi/«î"Ñ.å2"NEV2 †)ƒC$qa*’`~TªêžîyÈÌdò}¿^óêéªS§NUwŸ>}>çóýÊïAä÷  c‚“ p¦º³„évOˆðØÑÑÁyçG{{{Ý2Û·o§µµ•ÖÖVZZZ¸õÖ[éééaûöíc*#Âôe¤¾@úA˜ýȘ@˜˜¾@úA˜ùÈïAä÷  c‚Ù„=†²à¡|aŒmkùÜ$^ëd“šêTqB„Ç––¶mÛÆ¶mÛjîïé顯¯–––p[cc#k×®eçΣ.#Âôf¸¾@úA891 0þ¾@úA˜ÈïAä÷  c‚Ù‚ÍØÄ8p«ž‡;Š2qJc(ë26× SãZ‡k›[u­#‘«*opnU{¦Úyê‰8Icc#u÷8p ¢cX¸pah­M™z¼ð <úè£,\¸µkמˆK„iI__}}}ú(/¼ð ?÷tÔ:^N&عs'{öì™’ó·/PÛwLpäȺººä÷pÒÓÓÓÃ8räÈ”œªìÙ³‡®®.Ö­[GCCÔÜA˜Èïù} 2g(s†ÁXDA*Ž•Ї)ïeFÓ§ÆñÆuWסÕ)_ª*¯„ÈlòVp]éQ¶½º|!h»j¿ìÏÄÚ¡î$€þX… m% YãœjOOݽ½ãœÐSÅÑ£Gééé‘Õ ÂIO__]]]:thª›2%:tˆ®®.I,-œôtuuÑÓÓÃÑ£G§º)'5&¨•¨^N&8@WW×” Så÷p²³sçNººº¦Lxœj”ð¨&+ádE~ÈïA9C™3œj¹ìÜ1”¯vÆ|JH­¸éÔ¨£:”ª:W½º‡ ÕjW•¯~^}-ÕB¥UÕ¶B¬êu¼C¥#ÓšñEÇRð<;.øßŽ;ü¥–Õ"rTîܹ“¯®ZÅ7¯½v”wº6'Äñ8Õœ}öÙ\uÕU²rI8éiii¡¥¥eT+}f#K—.¥­­mª›!SN[[]]]'åk‚Occ#mmmÃæSšÍ,Z´HÆ‚´¶¶œ´¿.¹äé ù} ¿Aæ eΰ6¾h•¯ÚfŒpŒB‰qµŒC]‰6¾ÃP9•ëO§ÒÕ§{Ê¥§Èm­;ªŽ«2S@'¾€§D;;8µPèíQõW‹¦ÕçSBžÆPáPµ=Yu­^ìÑ êÌ npZ¬l6h“Ô©ÄRuÏôXÛ øJu'¨_ÕmZ[Ùýâ‹üÉÝwÃ8¢M+Çc­Ž­:ôÑhÊ‚0s‘~@¾@Ÿ‘>çÒÂìGÆ‚ €ô‚ H?0”êú.ob­Ð¦Î(˪m^Õs%šÕÊ©r* Á1 †:íXêX‡Èy¨Dº¸?§Eäl"_ ±²ÕŽF%*±TÝ•¿Ñ‰•uƒ²0ˆ/&:±v&c¯‡X“D«Ô‘ ŽOõ6‰ÇZìQµC‰˜Fð<œý⋼þñÇÓBxT«ŠªC©¸Ê£-#ÂÌEúA@úA|FúœK? ³‚Ò‚ ýÀDâ14ܨ5†ã«…Ájgaµ«¯:t©Ø ÒÁ ªêK0T8TûTyµ?kWÜMXªª_Õ£r'jDîÀZå•È©\†ÁqVÐ>%Z¦ðàÔi½@1xÞL” ÒÆ3ÁsÈͩڔÆÏÕ˜ÎoeÓA´ªòÊjåÓDew¬MÊIYÚg÷¤”vìû¢6ÓBx?ÄKGGlݺ•††®¾úê1•aæ"ý€  } >#}Î¥„ÙŒ Aé A~`¢Pùã —ƒ±zŸWµ­–ðXíX¬WZ½,|qL‰¡…Ø9 2?¡r¦cu•båT;4"± "a0CeØÑæàx%Lñ…¹xùøñJÌT¢  õ`»üéD¥û”#Q…Mã €J ôð…Å|°/:ÖŒ=WmM¹«é$ kkÿçƒë£jŸºO‘©„Ή`Úäxlkkãúë¯gãÆ444Ð××G[[ c*#ÂÌEúA@úA|FúœK? ³‚Ò‚ ýÀDã‰PÎ0å¼Xƒ¡áN• è1Ôݨö›UÏUY%ÄÙøbÊk¨ÄQ'¶?ü©Ð¨)"¡|× Í”#QÚ¬r)DyE|·¢+ ‘€§r&êDÎA=v^uŽrpO•ðÚKíÜ–i*ócšD‚TŠŽª}qÑ ?k¿×•ŽHªêQí‰;\Ýcå„ ×‰ ÛÐÐÀwÞ&²^·nÝNa4eA˜Ôê ¤„“ ‚ÇßH? ³ ù} ‚ü>dL0™(qP ÕFˆòBeØSõhWÕ§ò–ˆòÚD¢[¼¼9u|qNÏÃÁ”#±lËJ8Ôñ݈JŒ„(/¢*§œ‡ÙØùÒÁv+Vo2VN¡Î‘Œµ¢°ªP)ê±vè±ã•‹°³Æóá†Zò:£Ç¨³]‰Œñº”;r¢˜6ŽG…ŠÇ<Þ2‚ Ì\¤¤/Ág¤Ï¹ô‚0û‘1  } ÒÔ"/£(ëÔx^:µ:Ç¢VµŸªçÊE¨Š*¢Ê™¨Â Æ]ŽqÁ+î4žƒ2+«Ê¨¶¤ƒkV"¥ÒªïQu¼:o\t‹ µ„H£ªÞøý0êH¬%8Ö#;†²0 çqÆ7¾7ÜP±Y<Ïãßø<ðmmmÇ}Ši“ãQAAAAAAJÔ;ªsñD_Є( :±çNìQ‰„*Ï¡E$ØåðãDaSã¨rJ¬Ty k…» ÕqÃ… ­%$Ös Æë®õ¼Vùj!ÒäÄàºîqkY~âC¶Û¶M"‘àâ‹/æÒK/WûDxAAAAAA8 p†yTŸ;²„┪r*/£†Ÿç0.Ò©<‹zP^…"­v<ƉµžWw+ª¦õÊ»®[Ñ&•r´c,?·ãHär9<¯¾¤œJ¥ªÿµ, Û®ÊÈ*—Í›Ç5Ë–…õ«G]×1 ƒ-[¶°zõêqµ_„GAAAAAA„„[õX‹Z9«å,¯êÑ"rïA*|ªÏóp§Òõ–e‘ËåH$âã±?ÿsR©žçñÛû7VíÞeY8ŽC*•¶mš››I§ÓüŸÓNãõ>8®ö‹ð(‚ ‚ ‚ ‚ ‚ ‚0ƒ¨%<檞+éM‰Žñ|…µr>‚/@f©ùÌØ±VPF‰ŽÕŽÃ¸pX+ÇbœìÏGb8!±–ðx¢p]ÇqF@ÌÝè8ùÀ}8´˜‡ëºd³ÙJWcp®%O>I¹\¦¿¿]×Ã}§Ý{/®ë²÷®»p5ß›¹±¡×u1 ƒ†]»Èçó†ÁÆ+˜øð¸®_„GAAAAAA„Œ¨•g.lWá@ë9!•HÁ!‹Dâa‘HtŒ ZÕqÃ…B­ÅXÕêÃìIøOžÄ•U„3µm{h¸Óá(ÂK¥‡{zØýÕ¯FûcîÄææfJ¥RØþûnº €ææfôBÕ¸Í;c2• EÉï¶´ÐðÁò…mÛØ½jßúØÇ°mMÓ8ïþOÒŽ®ËÂ'ž`ß«^5®Û!£ ‚ ‚ ‚ ‚ ‚  ¦ZfS2˜#Õó¾©d1ß)é0TpT¡RØÿà‹Ê “ u<:uÒîÅ(܆õB™Ž˲H$Ñ× >€ç¿÷=Îx챺mËd2•çw]~ç;ض®ë\qìË÷îÛ&“ÉðÒW¾Âíí”ËeÊå2‡ÿöo9ÜÓÃcË—óuë¸à¥—høÁXwƬyþy(•p î=í4Ž._Îò£GÑ\—e×\ÃU—\BѲÈϾõ­`Yà8œúÜsãO÷+(‚ ‚ ‚ ‚ ‚ ‚ Œ‹¾X7š\„õ¤5´S qßQõ<3îû/£ ‚ ‚ ‚ ‚ ‚  ƫzÏéhPé>T¡Rã¡S‹Áÿq7c­ÕÈãŶíQ…D=Òé4š¦áy±»üïy®ëV:!ãÂcëpÁ~ÏóØó½ïQ¬®Ûu)çóÜññÓ²lÉ|ž#_ÿzè2ܱ?Ǿõ-þëöÛY¼u+ó{z¸ìw¿cርiÝÝ4ÜqgîÛÇ‚Ÿü„7¿ÿýܵ|9§>÷»·neùòå~]¥’/ËÿáXyǾhèºþvMcÑEÑðÌ3a¹è…÷÷‡˜fè’$›e¢áQAAAAA˜1Tˆ ŒëŽÖo&ÏHï¾RÕs%ÖúDx±ý‘°¾˜˜í7©‹Ñ RxÔ™8ǣ뺓öYN¥Rþ=ˆ×oYxžG"‘Àu]\ׄO%<:ärÜûÞ÷rß²e±›éAs3m~õÞ€áºìþÅ/üýÓðÏ^ûZÞºp!Ë÷î¥ýÎ;yá›ßô…BàƒŸý,«vïæo|#swïfí‚,8rÄ?}>ï ‚ù¼/.â»6ÏýË¿dé#pÙu×Aw7èºßVÃðËÆÅSUGg§ßžl¶Rdÿøø1†Qù|‚áQAAAAA7*oÚÜi£`$ÁÏqlÛ&•J‘Ëå†ì/•J4551gΜšûG:o¡P “ÉÐÔÔD!Eèy…B! ËØÜÜL&“ ‘R˜hFzGYUe•¬”¡2Ôj!د$%õ¨V»G+=é ÍãxÜ×:ÖÏ]}¡P ¹¹yH_cÛvèfüÔÀ ž~:¾3ü×ó<ÞÿÇ… Ub^©ŽÃ‚#Gx:žçPÓX½š‡>þq,ËbÅ•Wòü¼y{ðA,Ë¢9“¡¸h =DSÐÿÜpà 4<ó wŸu‡–.åÛ«Vá™&‹þôOAÓptÇ>òVýæ7¤UnIÓôÛéy¤Ói.úÄ' ·7öè~; c¨C±úy>_û>ŽtÜ £ ‚ ‚ ‚ ‚ ‚øb@\\2ßóÌs6 ›&ZàŒÄ0¸ò¿ÿwÖÜrKåE†ïVô<²J¬v-¦Ó¾y¼T[]ÿpê„×(‚ ‚ ‚ ‚ ‚ L ¶m£i†1z9¡P( ë:–e…ÇkšF>ŸÇ¶m‰†aà“ᚦ‘ËåH&“är9 àX,â8ù|>thšF¡P ™L†çð<]×±m›B¡@:F×õPÜ+‹är9\×EÓ4t]§¿¿?t')¡Ñ4Ͱíñýªêü®ë’Íf1M×uI¥Raž·|à R9áÔ1^à8J&“¡Ð¡êUb‰a¤R) …BXOÏó"GU}J¼U÷¢T*aFX—bÓét(ÈêU¢A¡P¨x]j‘ÉdÐu=2b”J¥ð¾ìÞ½û„¾W…Úij*‰^ågôð…Ç\ð_pTèDáX=FÎÑh0q¡SÇÊ[Î8ƒ5ñ0Ÿ¶ Á{üÅU7ÇÁñ<Êår¸8áõßú—þÛ¿±üÚk1L3ìO•ËüÁoË¡Ûnãæ/}‰‚¦aû5McĒ'ŸôëUí0MöŸs‹úû¹ì'?áÌC‡ü}ŽCË72°kßmkƒæfî[ºïî»IžuÛÞñø“?ñÿÒiår\ù÷OòSŸ ÛŽaøa[“IÌzâa±È°¤ÓLwDxAAAAA˜(Q  \.cFè0ÔuÇqBQÑ4M à “ÉP*•ð±W˜|ìö»±rÕ!R5†ær<á²—ç qò¹®;$<°ÚÞ´?Ú±cQ9×åÉ{îA>÷ö·sÅWðá@¸ç€üÝßqÇÊ•°cG×­céW¿Jÿ¢EèŽÃò|€yASl›ß47³ú«_å¿V¬`ùºuÌ{ßû —ƒ+ P`Å-·pÿý÷sêi§ñƒƒÌ)+úÂ~å+°r%É|,+º6Ó¬¼VÓôݘBˆ‚ ‚ ‚ ‚ ‚ ÓˆL&S‘À²¬0$ªmÛaxÍ\.‡®ëŽB•'Qå\TÛâŒ$6é'±[çxÐu=¼gét: iªr[Nµò4Ž–!ùò„i’²¼à1rUâï„jJdýÀ©«ò%ªËõòŸ¾ÔßÏvíâüþíSK–à9¯Þ»—³~÷;Vwtð¡«®Âu]~þ­o‘X´ˆ_ö³4}ò“ày,Z´ˆE¯y sßö6vÿèG¬\³Æ‹EpVe³è?þ1O-YÂË–ùDÇ Û÷µ×òá/}‰w:Äç`Aµ“\Ó@}ÞâaT #ºVu½³Ÿ§··75qܳ”“­¨7èP™ÓQQ˱^nÇãá±o|£þNÛ®tþÙv(åV4 ßm™NC>ïo7 ÿ/&à/¼ðBN»ôÒ‰}Or¦ðØÞÞNWWŸùÌgضm \ýõC{{;´µµ±mÛ6úúúزeËT7]„ âdêJu¶»u¶×IQL®Îv«Îv0'ޱÜK§Ny·ª®êçÕdêl¯÷zWŸg¦p2õ‚ Ôg¤¾@úA˜ýȘ@˜}ã8$‰!E˲°,‹b±†èt'̇Ïë˜L&ý }A8 ˜Éý€ÍȹëQí|ôð]Ž&•ù«=µå½+ Üwà u÷ïØ±ƒ‡ï¼³rc <ª…™LÆÏ‡èº¡ëPÓ44MãØWà¸.Kþú¯¹úÒK¹é¶ÛpM“9Ê5ôqW]uÏ ¤,Óô‹®[Ûe¨Âºû’Éd趬Ø_íGc¡ƒÓ„×¾öµƒwÜqǰÛÞö¶· ~þóŸŸÿö·¿|ík_;x÷Ýw[÷ç?ÿùÁx`ª/Q¦ ×_ýT7¡&“ÙLÕu÷ÖÙž­³/[§¼188Ø?88Ø]µ]«sœQçüé:õwרÖ?88ØYçšÊ5¶ë”/Ö¹ÖZçÌ×Ù^ž íª½UeÓ5¶wí﮺¶lð×üõ÷+”ﯺZc:ƒíÉØþøcqÐËA™äàà Á9ô`{6(£¶±swǤƒú:ƒ{[ Ž{ßSO ^÷½ï NGdL 'Žéü™©/˜icA˜ÎL×ÏÄdŽ xàŠãádg:&fÛïƒþþþA]×5M4 #Ü–L&5M,‹eûûû÷T‚0fNÆ1Ád_·š j.ˆA'ü¯ ús:ª®êù½ÞQÖ?V~öå/þôŠ+jïìîü—^:xïÒ¥þóþþÁÁÎÎÁAÃìí¼yýúÁîîîÁr¹<8˜Íšæà ÂàŸ\qÅ ƒ½½½ƒeüÝ‚ƒ¿¼ñÆÁí\0ØÝÝÖ?X.ûõåóþ±ýýƒƒªÔ4=†Û' ËDŒ ¦ã±šŠç===ôõõÑÒÒnklldíÚµìܹsª›+Â$0ú‡Ún3¯Îv‡Úî8µ=WµÍÃ_5U¨Q–ªò%"§e|¥•ïÕ(oÛK5¶ÛøN;/V§ºÞøµY±sǯ«/ëŶW߯TP6îúsDðXŠ•µƒò^PÞ Ú‘ ž[Á~uOs±m©àø\Pw.Ø– þš‚6‚ý) XÔQˆgÿëUÇ4Ç™A#اÊiÁ¹â×çùàz°Ý’@1v›9±ë.åSAݹ`Ûw—.eñþýÌfC_ Âø‰÷ÒÂɉŒ A€™ÝxžG"‘@Ó4º»»q]—\.Gsss^5îbT® A*™iý€3Êr.QÞF+8Î$šßQ¯ª3·NlшßìØÁÁ{ï­qA”J{ýëý¹%×õC ê:8‡ÿõ_yý±cÀ=ögt<ûlèv|©¡›÷íãg èºÎ%—\ÂC+VÐøûßsåŠanÔ0ª®ûÎGMóÏ«úȪp©C\¨SÊ©SÝÅÍ7ßL{{;466ÒÑÑÁÚµk¹úê«8pà@Eç°pášñœã<÷Üs”J%úúúhmmêK„)£««‹®®.öíÛ7ÕM©Édöûöí£½½–––!uLþ€Á£2é³K$Ò¥«Ê»ø‰bl›zTBN$ΩA‡?Q\HŒÊÄÚ¡DµîØñvP6.z:Á6#øß ð`hxP%p©k5bשʧƒ}zP^ öç‰Äµ¸˜Z ڪέÄB½ª­j{–H˜óˆÄ97v¿t"ñ²9hƒ†?h³‰D=3h¯j—´9;¿ºOFð§íUj!(Ÿ'SÁ¶tÕñVÐ5¨Ì×S¢ò=bû­ªíi"Áµ›(¬FuÛÁ?òè‘#,Ÿ‘Q˜2dÎpòæ G›þÆ®q\|ÞPÍC©P«'‚³Î:‹K–,‰6‚#†®K¹·—ÂÑ£Ö¿êUð«_çq÷ïÏ‘?þcÝu×Ðð§à‡F‡JUPVˆÓÑÑÁƒ>8î1Á´×­[^XCC===lÞ¼yB=óæÍcíÚµá9ád¥±±‘––~ö³ŸMuSj2™ýÀ™gžIKKË ŸTPbšŒ ¡<*C«çq‘‘Ø1û±câ.F%0B$*‡›{îû•cQ Šj»r/ÖrAz±ú•h§ÄP%š*!Í%.©:Ÿk£r÷Ü£B¬­Ê-©êÑcû•˜©Î©\ƒNl»zŒ2aøçËÆ¶«ö¨6¨ãÕ9ˆí3ª¶+´Øv3vOTy5tê®:NíWçSï‘|Õvªö×ÊäaýUÛôå[ZZXôè£üþ÷¿g:r"Ư{Ýë¦ú2aJY¸p!---ìÙ³gª›R—Éì æÏŸOKK .œêË„)eݺu466â8£]‡âÛ“÷û`ùòåÒþïƒGå÷Á¤_‡çyaþF%0¦Ói4M#+¹Å„)Fæ 'oÎÐe9uÌ rN°z9‰”Û\ÏãšgžÁu]tMós5 a>Ä”eAs3§Üsÿ<•ž?xÅ¿ù Ïϛdz?ÿ9¿Z¿žs>ùI´;ï„5kœ¿;÷\Ö¿óðØc¾ÀXÌlU;¥ßœÖ­[ÇsÏ=7î1Á´ûúú¸þúëimm Wõôôpýõ×OÈ*äÓO?×½îu¬]»vª/U¦”ÆÆFÙºuëT7e“Ý€¿JçD»:jMáÄ…,5 °ˆ%'ö§Ü{‘ðX¢rÕ“Uµ¢žÄê¨._ rÃÅÅAvU¹K±ú!Д0©êÕce”Ó3Ô#Õ)lOmÊõhøaK >3¨¯_0Ìã;»ƒs'ƒc²øn¿rì8ß5iR¹¬´×$O‰µ->ˆÓjl‹o¯&[§ütB}¦£»áD ¦«ÃKN ´´´ÐÕÕ5ÕM©ÉH}Áx'”ð(';ê7òÉúû@ ‚p²#¿&þ÷ëº455‘L&)ýxF‰D]×IÆ=º®‹è(L dÎðÄÏ*rD‹èã á¡rA»Á‰ŸkÚ³l§õõù¡TóÁ2yÇ๹™ƒK—¢Ù6hÿwõj>›Írç¯~Å{—.ËâwçžËû[nºòJ´»î¢¸l™ïl´mpÖß|3¦iúχs1V»!Å!>)¬]»–Œ{L0-rþÓŽ=ª¡qÑL¹% ¢ÁH–HT‚!±Ç"‘•¢\>V2h—ÚfÛT=½Á9Ô¹“Ác1x4«¶gcÛ²Áö<¾h/£Ú¡ÇÚ¯ÄÁbP^¶D¡DU»òÁqåØuhøbeü>(ôªGaú0›ûAFÏhûéaö"cA`æö™L†d2‰ëºd2‰à‡XalÌÔ~`´¨A™”I@Íó?‡•åÄÏeí;óLNÛ¶ÍÁü‘phÏ{xäüóyâÝï¦á¡‡¸oéR_(4 ^|ÃxÝe—‘Ífý…Ù¬ïb4 Ðu_tÛpb¢„VQL áq4–hµâ :lWW—äb„YÀlí”x¨9*…E¨Ìm¨„D•ÃQ &”p–% åÏã ãÛ³D±ß³D‚¥æT®AÖŒ•͉ƒñcÌØö¸“0^_’¡ù•2.¢ªöU ƒÁv%8VªF;ÔµO3ÙÚ‚06Fê ¤„ÙŒ A€é߸neö6Çqp]Û¶Éçó‹E<ÏC×õ0¯£ ccº÷2%( ¢ù2½Æß¤àÍFùÐW¾ÂëW3oÏ^zè!~ðîw‡áN?zýõ|ú‹_ä…o|ƒe×\ÃÑ3Î N“N§}!±XäÑ#GpÃ0Ðãâb <†˜¦ˆ‹³ˆi!<¶´´ÐÐÐÀM7Ýnëêêâî»ï®°8·¶¶ÒÑÑÁÀÀà‡ƒihh“È ‚0s™éý€Ê—¨Â"ÄqcÛ]üp£q¡M…''‡Ž;•Àèâ_Ãjµ“zTa”c1.±úâm0cǨíª.µ-^>îL¬Þ®Ú]k 4ÖÁ‘ü$;ù˜é} Ãhúéav#cA`ú÷™L¦ây*•¢T*…ì†aP.—éììÑQŽ“éÞŒ•Q$ˆÜŽP9fP)6N–$çy]¢P€\šš T⥠/äÛ«VqƺuÌïéá”®ºóNH§)äó4'xp˜H$x×»ÞÅË^ö}ÊÕ¸gÙ2V_uÕÐW;u‰K6›8®}}}ôôô„¹aÆKcc#mmm´··s÷Ýw³páBúúúhmmeóæÍa¹¶¶6®¿þz6nÜHCC}}}´µµMXYA¦Ž™Þ(ñ0þw4Vo‹‡út‰„¿¸Ðg‰JäS+žª]ƒà» ãäëlOW=BäF¬Þ®˜ÔU‚c¦÷‚ L £é ¤„ÙŒ A€éßض]ñ¿ëº ßí#„0ÝûÑàÅþ¯eXPs‡j°V>ÇI=­Ÿü$ŸøÄ'üPª¦ ®ËÝÿôO\ýðÃüx|õjZ[YþÎwrÁ[ßÊG¿ñ æ-[FöüóáÐ!À#ýü¿È‚åˇœ¢å†|!²q7Îj†ÛÛÛÙ¾};6lc(wttT¬.X»v-ŸùÌgÆ+¹µµ•«¯¾:´C«„¶q¸óÎ;éêê`ݺuÓ¢ãab˜ ý€?@p‰ NlD¢ ÁÿY*ñ†P) ÆW@Õ[39Ò×·|½ Ó•ÙЂ0~Fê ¤„ÙŒ A€éÛ(ÑѶmLÓ Ã®zžG2™OÕ‚ T1]ûÑRKl¬FÍ*SB5ÇmpœHäó¼H`vÝqo+aóf{à@üõÏ~ÆÕA›^yÍ5¾ì2>ýGÄ×ûwî¤xà ~][Ò0 øú×kžÞñ¤¤®ðØÞÞÎÖ­[Ù°aCèjìëë㦛nbíÚµ´µµ100À7ÞH{{;Û¶mwcFë œ—¥ Ó“™Ü¸ø_È^ð‰ÈŨá2”³Ð#r.–‚ÿ•€¨ŒÅªúÕ~Y7)œ Ìä¾@„‰c4}ô‚0»‘1 0=û%<ª0…®ë’N§±m[&Úa˜ŽýÀh¨%2z5¶©yÂZåǵ”¡TŠ„GÇD˜³c W®¬Ø¿{Õ*Þ~ø0ô÷sÙáÃXŽÃáž>zýõúÂ(‹~çy`ÛÇ×&u‚þSBQÏ>jæx`ëÖ­´µµqë­·†ÖŽŽ€pÛ† øÌg>CWW===S}-‚ “ŽMev…Êߨ]üAD<|*±çqWcuœvõU[o%“„<AAA„©Åq4MÃqœð¹Êé(‚ ¨k…]çs¬åv—ðèVµÀŒÎÐó“ŸðãÝ»ý…¦ †Aߥ—ÒðÒK<³bG?ð®ûË¿DÓ4Ì|ž3÷îVhڸå:Žö¡“ÁdÖ ±ü˜Âj ʲÜÚÚZ±½§§‡µk×Vؘ7lØønHA„ÙŽM”Ï1ŽúšQ‚£ µ ‘ãQ "Fl{­A… ‚ ‚ ‚ ÓL&SbuñâÅØ¶®ëèº,¡>q)LÍ'Æ#¡ÕbX?àHâZ)6“!•h–ÞüÿÁÀ’%`|ôßàìW¿šk{Œy·Ý†eY”J%ŠÅâкÇVz²…A˲Æ_I<Ï£P(ÌȶŸj *ru ä®®®ºVeA|ÁÑ‹TŠŽÕƒõÕ<¢ãXWÜÈ AAAAÏó°,‹r¹Œa”J%4M#™Lbš²¬X„‘‰{ãnÇã¢Tª½=— s0†‚£ëúBe.Ç®;îàÜ×½ŽG–.忾üe>xÇØšF¾\¦áÊ+ÃjLÓ Ýçy“:'i3ìpL¶hê8Τ¶²©)<*qq`` ܶ}ûvÀOÊG Žk×®êkA˜tjÅYW_3Õ„$þª!J5.¡T*…_P£ùY2Ö/³T*5úkrÝ1•W?²AAAádÃqt]Ç4Íp">™LÒÙÙ9ÕMa†Ÿ_TF…ãëͺ.»wïÆv|ûÛþ¶tÚÿ³,οé&ž}öY~ûgFã±c¤ËeJ®ëÏù¥Ó€?™Íf1MsRÜÜ“jÕó<\×Eu°m{RÅÇÉ'Ó­ u„G%.Æ'–U~GZµz{µ )‚0Qkp, ›k„SÌ0¨jžs<ç( }°zžH$ÆVµÉ²,ŠÅbèTó’¶m(hÞñÙ;¸ä=—DíðÍŸƒL§Óá¼b2™ ç:ãyMÌaïMõµ~óaüdÍÍÍtvv’J¥èíí ç' …étšT*n³m{ÒDåS‡ÛÙÚÚJkkkÍ}mmm’×ñ$¤Zh„“ —h0àà»=üœ¸ÇvïfÙ²eŒ`e´«Vâ!J•Wk¥˜Ç¡\.ãºnMaS9þÅb1ÌK¡ŽI&“á±…B!Õ:;;+έë:¶m‡íR_Éd]×)—Ë¡gF¸ŠG ,4M£¹¹9>³Ù,ù|>lG&“¡X,†‚Z\,,•Jí) á—µ'{{{+®Ý0 Êå2àÁ+füþvvv¢ižçU\« Ϫî§çy躊‹Õ_жm“ÉdÂk©>¿KÁE›ššÂ6©A‹aa½ÙlvHy5À1 # ƒ¡ëzx^%8ª:’É$_üâ+r9 ‚ ‚ ‚ ãÜ(ñ…¯"< ‚PZ–Nq"‚hÞ{ï½üIPßeà‹Ž‰‹<±r%þêWsúSOá–J\´y3û^ÿzŽíßÏÖw¼ƒ;¾òvàÏsÝvè7B¸`_Ó´ŠùËãÕJ¥RhÂEñ£‡cÁĬÝ”Ñ@Ímær9<Ï«h»ã8£×¾ÿßçôóOëµ,+œß[4¸ˆýû÷‡F­þ»ví çEãmXøÃ…tmïB¿ÏŸ{ð]òÂå/à8©T*ü>Q¦/Îÿ"Wú;tÃ/ßÑÛÁ?ïúç!mÌåräóyìœÍ• Wrɇ.áο¾“läûÿøý°~eBP& ;gW܃C·òß<&·ÓŸ[½ôÒKùå/9®÷æ©#èêêòoÔÂ…B£ˆŽÓ51>ZE¿T*)Dssó }A8™p ¨@ìÍu9ây˜ø‡zâc|åÊHáA-Ë¢\.‡N¼ê•4žçÑÜÜ~î‹ÅbøEšËå*êW"[:&ŸÏ‡_ü %$Æq1®åÔSNÀ\.‡iš‹Å!e•x™Ëå*V)±1Ž®ëèºN*• ¯M‰kJ̬>&™L†aH“ÉdMÁ5N:ÝœåryÄÁG>Ÿ'“É`Åb1l½WgggX¾³³sØþX×uŠÅbè@U•zmÒuÞÞ^,˪$¦i†?z•;S¹f«Ý]]]áw¼ ‚ ‚ ‚02*ÚNüwž,Сµ„Çxqüž<Àuyñg?Ã}úéÊ}ŽÃ{vïæë_þ2°x1çvxKy„÷µ¶òóÁA~´cd2‘¼ räÅS'Õïêiª¯Tó j¾PÍGÆ Ã9Õ¥ªßËxhe ˲¹RePeÔ|UïhC­~öݟ岿Œ?ó`hðPó¥Éd’%/áÚ•×òáÓÙÙÉK‰³œåׯ&Œ½hÒü¥IãÁưÉ{“,ýÕRì}þþïœÿ޼ùç´žC©Tâƒßý o~å›ñò—œr omàCû?DZ/ã?þðŸÈ…Ï^H'ùØöݱ]÷íbç¼üWÛñÓ¿ÃgœÏpËš[øRîKär9tt~4÷G¼¦ðšðu¹cå¬úæ*î½ô^Öç׳xÿbθü v=·‹}¿ÚǾöçÝY_xìééaË–-ôõõ…ÛZ[[¹ùæ›ÇuBar©5ŽxøÁ‘¨Ž;<FZ ߯ÂOŽv‚Z!1Zá´T*a𿍄իÆ{­ÂìA…X¿ïÏ÷8ÀŠ={Јò=V£D=ðŲZ_|ê3¬¬û¦i†a9«óªçÝÝÝ¡¨¨0M3ã.Ge±¯¡Ô€¢P(ŒJŒ‹‡-èîî±o(‹$ LÓ¤³³3 QZr¹L©T¢X,Žø9TbœrDΙ3gÈç7~.åÈ-J€­UW- à»»{Ôõ§Óé1…ÿ°‘ÝÚ̓Ëdî¹\²älÏ7]¤½4::ÞðaÊ¿.S¤Ha_¿]ð·Ì½x.Wýü*æ¿j>˜`ê&X`h‚Fv‚›r9ø?rÉ×0÷œ¹Ì½{.;îÀýªË®†]<9ð$Üï[ö>ì¬ÍÞîåš×Ðýd7<°þXú…¥ô–{9÷Ï%ÿ|žë¯¿ž§Oyš§_û4«w¯æ}Þǧ^ø[Öláš=×ð¡áÞçÒs]ϸÞósëíhooçÀlÞ¼™mÛ¶±aÃ:::hoo× …±3±o¤¼qñE½¹9˲ÂôOŠoòÛP"¬CíËd2 ¶®ÚŠæif‹ lu¾n¡9OþO¾vÐ9ØIgXüûǾÏw¶}‡ÎÎNúûûIºIn¾üfÒé4ŸÏçXÞµ|Hý¹\ŽGÿãQ¼ŒÇÛ^ó6o9̲–‘½(Ëßôý œñY#KÃHšIpaþïæsæ¾3IÒ‚Æw5òLÃ3,ê]ÄÏ~ö3nÿõí<ÿód,i7ÍÇÎú{®ÙÇ>Äc/<ÜÝx7×Í¿ŽﻑÁ‹ýÉçTð—ÊT¨Ñ -ÁŸÿþÏùýY¿çöüß:ë[Ü:ÿV\\v]¹‹ä`­¬±|Ýr®½öZrä8õžSý7XÞ{ú{1 &™9æÝ0•+W²ô†¥\°ë½fº®óük­á±3ãç|˜­È’å’Õ—Œë=_Sxìë룫«‹¶¶6ÚÚÚhiiáÖ[oeíÚµôôŒOéÆF\ð õN,SùÏ  ë‰wŽãP(°,‹D" £m«JˆZ¯­J8QŽ,ea®Ww"‘ ©©‰¦¦¦Pp‰wl*Œc­cS©TÝjÆâÅ‹Éår$‰ +u-J¥©TŠB¡@"‘’Ï­úZ•/_«l.— ¯OÝKuÿ«ÝnÕÇ …0ÇÝH"®02@I¿ê]PKÊUÒÙS·ÜÂ3=Dƒ‡8J8WâX­ÏR©TBÓ´Ðÿ1cFøWuÕ Ÿ©PB¢¦id³Yt]ñÇQ­0¦ÃQŠa$â¹ '“êAËd%ÂAAANT¸=‰v%ÂXXÔßÏž={pñçÕÒx5£6æ¥ò¹hGx€óO?È|ûÛP*ñÀÚµP,2w÷îP#xéÊ+Þqϲe˜¦Γ?vôhhòinnöç&ÑB—¢êïj¥5RÛ”ƶmžíx–…O, çÉ Ú®l#NS,yóÚ7sóú›1M“t:Íÿîþßäɳÿ7ûý‰W (ùõ[–E'\¹ëJî¿î~4[ã}óÞÇ5{®á}‚ëνŽe{–qí ×rpãÒ!«ZW±{Õnõ/ò'y= E˜~é±»#K–.ú![Žl!³5ÃÿุœöŠÓØtÖ&¿Þ„éàO%éôàöwÝÎÆ³7²éõ›Èky¾tôK¬™·†ÕKVóå—¾ÌòÿXÎú»Ö3ïùy†ó®>;oC',øÉ?Œ^2¨OÕmà‹†%­»»›¿^™7¹~ïõùÛ#¤´KÿçR ˜-â×,¢X,²è5‹ 7¨£;¸î‚_ßÛw¼ïÊú›×‡sÇ@hHyëgßÊ—ßðåq¿ïk†ZUáU+¶·´´ˆðx‚CO¡„©zN7µ2K•‹ÇBVÄÃ…*á*“É„î#%Ê©‰}e{VçWçPùéÔyUèH:1—Ë…‰e‰étšr¹L"‘Û£¦iúqÑDÓ4òù<®ëÒÔÔŠ1*„eÿ8[Q€IDAT\tPÎB•—MÝO•/ŸÏ“J¥Ð4 =°–g³Ù09­,”@ªÕ*7š*ŸÏçC‘VÙ³Õ}R÷Y×u,ËÂ4ÍðZãd2™ðþ˜¦Isssx}Õ"k¡P¨X}’Ïç+ró©0›Éd21óù|˜ O„˜ÑcC80¨¾kz𧜸õPa âŸúœ9Žƒ¦i …0T¨išCr©jš†¦iág¡X,Ö̧G¹OFªÃ6ËCAAAatàChh||åÇyçúwrdË¿þ,XÂRs)¦i2˜$Mš¹WÍå‘KaíÏ×rìŒc¸®ËÞ»ö¢¡‘$ ßcžÁ‘µGØ»c/ù»¿äœçøQ“·LÔÏs€WÜyàWßÿç{çóÔ-O‘$É—·™Ã8Ì ï»J€çüÅ9|ö™Ï’N§™[˜ ýA=%|ñ±_ Ìø/à2cŸ¿áó4x àø¯Õ7ø°‘>ú8—sý6uûmIÚI?*›R›Uäî4•Ž—Àg7ˆ¨p³ét×ukF¬«iPÉã‹§f0?š&ÌV¯Xé<—¼çž¿ÿùq½ïO×ÑÂqOv:J”¨‡ê TLbMÓê:U|f%D©7’¡<Ï£©©‰îîî°>ÕÁÄÃ#*E…JM§Óayð4Û¶Éçó¡g¹\. êy^¨¨'“Éðƒ¢i¶m‡D m«XJÌSâ\-çU.—#ŸÏ“N§q'ÌS™J¥Â0”jШÄÉx^4å&TâŸeY¸®[3žiš¡“1.4ªóW£®U ˜¥R‰r¹^G±X cTkš:2Ull•NÝÏóB‹ºçy,^¼˜¦¦&LÓ$™L†Â¤¦iœsÎ9“ü.ŸØøý¿úDU{N•ð¨>Cµ>{ÊÙ[Ëq‡ªëúˆ¹þŠÅ"©TjÔyPOVâ±â’ãPAAA+–e‘N§Ã¨CSÝ$Afáÿñ™ÁÑ:•QðC¬G{Œ¯þíoyN4MŽÑ,XÀ×¾ö5Ö.ZÄ%÷\BòKþÜðÿùêWyW|mA×u\×¥»»·ärþ÷Ï-nÁåM¼‰o߬h“2}rî'IÎM²¹´§äð¿/úß|{Ç·ÉzY.½ôRžŸ÷< XÀ‚¿]KÞ³Ó5Á†9™9üÂA^ê}‰_íú;–íàϾýgèè¬Ù³†] »X½{5´<Âù‡Îçå_&ñ®Ÿÿóϳñ³¡ß)RÀWrÓøB›dà¹w<ÇÊc+±°H?’æàiYÿýõtÒ‰sÀáÌýgú"œî×sÅŸ\q·á×£^ À}X11\T¯gì5!OÇqhXÑÀœs¢}†z‰êÌéf•­^·±D¬ÃÄ¿OñúGxó½pù š¦Y‡9“É„!P]×Å0 ²Ù,Éd2ã”°©Ê©6zž‡ëº¡S0ŸÏW$€U!`Ëår(¦©:ã"¬a¤R©0Ö´¢žøªD¹t:º*¥XÕ}Tb\ww7™L†|>_q} Õ$“I²Ù숎)% ŽVTV.P%´vvvV¼ÖÕq®•{R‰°Õï‹x‡£\¡Õ÷Y}iüÕ_ýÕèÞ¬-”qðûjõ.Ó‚?%º×•‹µÖªHå²õ<ÎÎÎQ½ÇÔgR¨OõgP¾‚ ‚ ‚ Âñ~¥¢e ‚ /YüyÆ1ÈF”J¥!sÎóvîT¦;®à 9ý§¬O§¹ô;ßᘦñÒÕW3wî\ž}ë[™çüP;xüر0b!ê J€Ô  `&ý9é÷¯}?óíù,ß»œ‡ïy˜;~pùd>¬c%+YÈB®ùÞ5llØÈâÄb?z˜ô‘4{ÿÇ^šþ¢ N]L<¬\p3~°â|ù¿¾ÌëàîÇïæ©COÑ‹Áí‘W>¬ïZ‹á´ÆÓÐ WÀF|A/‰/¤GÀ ðµ/PøL#[Ž0píl¼Û³ùâš/òÎÇÞÉ‚w‚¨N(&†sìqPc†á·Ã]ùðüc`̑ݦ`*Y„ÇŒé꡺d2 gñò–ea†a„ _•ØÖÝÝ Dâ‡çyX–:Á.âŽ*Móc6+—b±X$“É`F(ŽÆ;5•÷0‘H`šf"ÒqŠÅ"†aà8N(ö)×_2™ ŲáÜZJDÇޏØfF…èª:å8ÝÝÝèº^»¸š¦)L¥ …9ZT{u]§³³sD1)›ÍŽ)Gžz ê=F‡rë×’ÿûî½—Ò?ýZì³G òõd³Ù0Ôðh_×1­h9‰‰‹Ãõ¹‚ ‚ ‚ ‚P•ÇL ‚ £EâŒ%— ±úÁ'ž`ß?þ#úùçóðêÕ|P3Ú0oÞ<~vÖÙœ}Î9¬î>ë,Î;t5—Í¿ MÓ8ýMoâ·laõêÕ<ððØ]…ó”qcѳ„…5ý}öÙ88¾ì0«v¯â£g|”$I®|éJNðãÆñC§¦}=À0 "U…BUbc|Ú?_êI>ŸÇ4M®l¨l_0ÅZw®µN¸ê¾»X,‚î;5…É£¦ã±±±‘¶¶¶ÚíÛ·³eËÚÚÚX»vmøÜ¶m¿ãèèè ­­ÆÆFÚÛÛÙ²e wÞyçTßÇQ¡b)Woós꩘¦ÉK/½Àó÷?ï?î|Û¶I5§xã¾7êÓl|‘°€?jàO€ªµüï„ò¡2æûMx6¼v¯èyÿùÆÿ¤Ü_æFíF¿œJh›¾†‘Äw9ª ïf¨ðX5ךN§'unÅ߯˜´º…1äxìêê¢'PÖ×®]KKKË„6IJ¬ ÷dKK  ««‹ÖÖVÀï`Z[[Ãç·Þzk¸ºaÆ S}/k¢Bžf³ÙÐʬ¬Í9 óù<…B!,§þW‰«•h©iZ˜Ôºž`¨Â NÖs:»óù<žç)¢0}˜Îý€‡ÿ½«ãû½ŠÏ™¦ia–r¹,?J¦]×I§ÓaÈèz.saú2ûAN#õÒÂìGÆ‚ ÀÔõ¶m“L&)•J2Ç$SÌLXøºš:ÜÓêR‰bЮjâi›p]víÚÅYÇŽÑÿÍo¢lE-_ΛžzŠk–-cÁ‚¼ò•¯déÒ¥=ã(ÆóFÖà…ûîãÖÕâ× @É-ñ‡Wü!gq¥R‰ÿyãÿäò/ÇÀ`ÁÓ øÔUŸ‚w㋆üÉÏ4QXTö\³‡Ä5 › ¯ÿëyà pÞ²óø³'ÿlÈõ„ŽGJ¡±Ú¨8B @1Ílæ·s`` ´'oÚ´‰öövÚÛÛÙ´i_|1ííí Œ»}}}ôôô 3o½õÖ°£èé顯¯¯¢Lcc#k×®eçÎSzãBb5*4ªçyaèSµ=¾_…L§Ó†A2™ …E%Vª˜Ë*¼i=ª‰'†a`š¦ g 3¡0¨ ·jÖxŸÅó° Sƒ®ë!£åµ˜YÌ„¾@„Ég¤¾@úA˜ýȘ@˜º¾Àó< Z|/¿+aê˜ic‚¸è¨ýI= …Âm«?üa~þòË,ß»—yóæqÕªU<ù¡a°ü[g0þ|ž}öY.;÷2ú_ÓM!QàO>ó,ùðvݱ €Ô~ßáøÅ˾@óâf .ýÂ¥4ìjˆ\JlÔñæŽDÓ4}sE:õÜëÎeÉW—ðŠK_Qóz Ã>S¨ïxàú믧§§‡ÖÖVZZZhhh÷uuu±uëVººº¸í¶ÛÂ}ÇƒŠµÜØØÈM7ÝD__´¶¶²víZ80¤ƒY¸paèÄœ*,˪ë>TŽFÕd³Y,Ë 0¥R ×uÉd2aHÆt:=D8Ëår€ƒx:…6„‰b&õË{Œ=kÖ øu]Ƕíqå*„“™Ô‚0yŒÔH? ³‚S×TGΑItA˜:fâ˜@õ I‚´‰#Dãr]7œgüîùçsí¯~ÅþýûYÜ?o§wW}èCððüøØ‹Ì™3‡·¼å-Üú¹[9÷és11¹nþuüÝ‘¿ã´ƒ§±úI?Ç£†Æâý‹YüÌbÊù2g¼ó ö>¼—ìײðppr3hdßuaÄïú4Âpª†a€g=|VÍë‘yQ¡®ã±½½¾¾>¶mÛÆÍ7ß̆ hii¡¥¥… 6póÍ7³mÛ6úúúhooŸÆlܸ‘††Ö®]K___(|Ž—gžy&tkNÃuÊ ª+®ëâº.ÉdMÓBA±Z´P‰^Ë岈ŽÂ¸èèè`Ó¦M<ùä“SÝ”ºLV?ðä“O²iÓ&:::F,kÇþÏ9]×eÏž=Cò7š¦&g„錊bðÌ3ÏLuSê2Ùc‚M›6Mõ% ”ÒÓÓæM›øþ÷¿?ÕM–Éê öíÛö…‚p2£¾÷íÛ7ÕM©Ëdþ>øþ÷¿Ï¦M›D¤Nzä÷ÁÐß®ëF.d]˜ýÈœáèç GÂÅ7zDi ½\®ëB©žÇ¦ªqÙ¹s¹æškü~H×yéå+¹ñM7ò“7ÿ„|ä#dÉòÊ#¯ä¦knÂÁá }_àŠÆ+°±Ùݺ40 &X°lÏ2¿â2QNG•1CUcøp¨,»iÙ„Üaú t´ñŽ j:ûúúèèè`óæÍÃærlii¡µµ•­[·ÒÖÖ6.×#øN?§üIüŽŽn¾ùæqÕ»dÉÞùÎwNx^Jð; Û¶ëî·m›t:M©Tª mÛEÈd29¬CJå*„ñ¢âœOç ÷ÉêV¬XÁ¶mÛF]Þ¤R€ßá¼8•¢¿Fùd2I6›EÍ‚0µlÛ¶®®.ººº¦º)u™‰cA˜I¬]»–mÛ¶M{á­^_0Þ-K—.Ó˜@f+mmm'íïƒw¼ãá=„“ù}0ô÷ëºCL‚0›‘9ñÍG\b4j„Rã8š¦az»žy†N¯“çÎüx‡~M 8¢i¬^½˲Hë:óvÎã³.äµs^Ë/öKè»Ùfý™ëY~×rž¶ïîù.¶šÙT™âJ@2z†¢]ôŽIüðªÇ“¹íäÌö6«ikk›1AMÇ£²/·ÖIxG•™ˆXÉÕçÛ°aCØE­U ÊR=ŒävôU=Z–E:Q¬8Yó5 ''Ó©رcàÔ§Ðó¼aYäóya˜N} SÇH}ô‚0û‘1 pâûÏóÂù8Ó4Ex„iÀL8Ž3bŽG‘®‹kÛxxx‡}­ð£Ë—óþßý×u)•Jx±iÁ‘œ{ø\®zø*(@‚¿~ׯAƒß¿þ÷=ã(&&§½â4_pTáÜÌ@oPÝšm!Q˜(j JÍlll±Uf< èºu뀡âe¼ãP+ªËtuuª“E-·£ ¯ªr½éº^áXÔuÝï(f³ÙHhÔª-@MáQ}P«W Ô¢úÇÿñÐÐÐ@KK ííí ~§°}ûöŠ0J­­­ttt„e¶nÝJCCW_}õ”Ý@%2*ç£çyût¡P…ÅZlj+J"¦c?°wïÞ0œ¹úvgÜa¥A¨Ïtì A8ñŒ¦/~@f72&¦®/p'eþN¦–™8&ЀÁþþP;Ž>ñÏý炦qù¾} œýÿ±€7ó'gý¯é g¾p&§:_øqïXÌ_¹€•++òC%“I®\è;=øæµßdþ§çGŠøBcä¬cÇøúÁ£<ýþ÷pÊK¸…§¸¨ÿ"Z/nå‘óá埿Ì`ç ;¶îàèG9vÅ1è&tKäóy3p6¾÷;ï\f쯟J‡£Â$Q3^`CC­­­lݺ•uëÖU¬ˆ³}ûv¶nÝJkkë¸?ÀÜyça^«mÐ eÖ­[7é‡ëº$ úûû‡„Uð<¯"ôøÂ£çyär9’ÉdÍP º®S,'µÝ‚0™.ý@­µH:ÑBar™.} SËH}ô‚0û‘1 pâûÇq$¼ª L3fÒ˜ÀÃ×ööõ…ýIý¾™é,ŽñO]=ÌŸ?Ÿ-ûÖcbrù¾Ë¹ï®ûXѰæÂšÖðÈëáï¶ÿÿëúÿÅiœæ«œeе`¦²*tê3+ža KNø=„º‰ÊÚÚÚØ¹s'[¶laÆ ´´´„æ¾¾¾ÐμvíÚp5ÁD0š­ã ë:Vâ¡TMÓ¬ØÏáX]ÞuÝ!åõ¶ ‚à3Ýú…Zñ¨á"A˜\¦k_ ‰e¤Ï¹ô‚0û‘1 pâúÇqÄå(Ó”é8&°ðM qóà{÷¾~ ´Ïó"Òó¸ë曹æ‹_ ™{Û/ø£Ó.ƒ#``п¨Ÿ‹\Ì˼ÌOŸù)-ºˆ%w.!û,g^ft2ßÍCŒåáRWxlhhà¶Ûnò,:::ؾ}ûý›7o&NÏêÕ„ÃÅaV‡ëºáÿŽãL&ÃGAf(Ág?>@°, MÓ|÷ãT·OAAA„ g4¡A.Cç ×ìÜÉŽŸþ´b[hlú‹ô»83âË\¸ ƒ×>‹«7À#oã—§ý’W½Èëz^ǹëÏ¥áÜØ ::‡þëPTiµ¿©ªëZ°eÁTßá$åÔáv644ÐÖÖF[[[hQVœ,« ‡K¥Åb‘R©nsgÈ6Af»ví‚'Ÿ¬Ø–Ëå°m›r¹Œ|ºAAAav⺮˜ Ažm³``€‹ú/ªÜ9¨C¯Ã5{öp˜s9íu¯à»š9ôâ;À\ÎÁÇã§«Ê+ú^Á¹Æ¹œR8…ýÆ~ÎþýÙœ¹>æbÔ*>Æ‘ˆÑÂqêh ž,Bc5ž74 ¢mÛhš†çy¡»Qm?é´¬Œ„™ËŽ9sX°`—NG×u) tvvb†‚ ‚ ‚ ‚0Kq‡l6;ÕÍa¡¬KÊùèº.»­à¢þ‹h¦9*|@‡þ>ØÅ\±GgÑÀE,úür0àý–¹ËXûzÐàŒågà&]ô’^yb…iÊÜñVÐÞÞÎyç7Õ×1iÔrÏ€8ö±c ù‹ žXù˜°æ¶5˜iÓŸ¸ŒwO²FB˜¦Œ[xœí(á1îjT«Ñ¶mlÛ–Q‚0Ãù÷Ç9íÞ{ùÈgþgßó¼0Ï#øQ ÄÓ,‚ ‚ ‚ ³ ùL"™ ‚P%*œØ£’•–L&é_ÔOóâæhûƒX¤ã9 xot_Q|òÉ'û·îö'!M|ÁQ£rRRÖHÓGÀuÝ0¬ªz®PB„a¸®‹išèº~\çazðàãsê©§’N§ÃŽ®ëV|¶Ó@~ª*‚ L/< ÿQa?G§qîïKSŸ{nª›!‚ ‚0-Pb B=l¨™†É ö-Þ±#ܦô•ç±ü6ì×N$Atµ"Ð ”áæå7S*•(•Jaj·Y!ÌDx5؈¯rR ¦ãy•8wD ‚039pàoxñE€Pl´m[‚0û‘I–‘) : ¿eÁœ9ÐÔ¹¨†¹d2þöLæÄ¶³Fª€ r9H$ ¹™Kî¹çĶMAaš#nGA†Ãf{ 8|ø0@¨¬|êevŸõcüÖ·XðôÞyÆ;1âJ¢$àSK>…¦i˜¦I>_e}З£0#áq\×­Á#u]§³³sHyÉÿ&3Ÿ½{÷2oÞ¼ð¹r9ËÂAf=…BäÐóûÄÝ{AA„iŒã8’ßQ„©%>ªP«‡F×õ°/i<õ[¼4ç+ô–{9­¯ð…Çwý.-ZÄ—ßõå(Ê¢?øÁÈår …¡'©µ*Ó”S§ºÓ%2Æq]—l6;d»®ë∄YÀžeËxã²eáóR©$?:A8ñØ6èºÿw¼¸®_O:=rYϋĬxù\ 4Íÿ›éäü X˜¦/ ªëO¥üû¥šÄï¿ãD£¦Ee ¾¨ØÝíß»ê…i…‚¯MÓ¯+öÕkà8‘èÙÙÝwÏóEEÇñ·9ŽßE<Ôkµ¨šHøçQmQ‹êL“ÇÛÛi™ê×EAaš òª ‚ G-á15™L†©Ûæ.ÞMãoדù\†3ô£üvà,þþ™ ÿ§ÿÿ°úÔÕìþán2™ år4xí_KòÒ$éZ¿åÅ÷$Ìj:»ºº8ï¼óFõ·uëÖ©¾†I#ž×Íó<<Ï’ë |'”¸aæãº.ÇŽã­+WQx ³"œ(JU.&¯J<È)ѤÎóáŽf–5Ե溾p¦\m#…ÓtÝÚ!>•soñ⨎RÉÙ”¥i‘ ÖÔ4²ƒ®Óí=¨î©çùn¿ê5†årôMÓ¿Ùl$ŽD­ïÛöÅAӌܕª.µÏó|°–Ó>Ÿ‡Þ^¿ Õ¯:íïSíT¨óÈw™ ‚ ¨c c!.8.Û³‡å,çú_]-bا¿ü& Àuî^ýÌŸc`0w®/ÍÌŸ??÷.ßK÷`7ù|¾v_$?ë„BMÇãÂ… ii‘µÏ*Ÿ£ã8¸®†[¨õ¡OÆM ´Å¾tô( ,@}“É$ƒƒƒ’\~šS(ÈÆ'Ùg–e…ßžç‘Éd0 ]×ñ<¦¦&úûû+ʆ®œ‹?O¥R¡+?™L’Ëåp]—ÎÎÎp°_<óøã‡y„€ãøÂç ­lÛwÛ%“¾0ÖÝí‹N¹\tœÉ …ÈqW=QÂT£ê_`Tu$“•޾øsEoïÐsT;1K¥¡®>ªµ»»òzÇC³Y¿Žzb˜ëFçPN@%*r9[’&vÍ*Tj\\L§ë»?5m¨YÍDL@™¦޵ÉäÐûXÝF%F×Öøë£\µ^[AAaŽãÈâcAŽ›çþæoøCãc¼òéWÃùj«‡/Oª½.k¬åçoø9W4^AÇÎ>šú(ÝÝÝ4ÍoâÜsÏêË„qSÓñ¸víZ¶mÛ6¦¿ÙHu¨UÛ¶ëæy“ÕP‚0³q€/®YËoxÃ}'ôG‡5Æí3j'žmÛÖ»úªu]7ØÀw ær¹ºn?Ïó†u Ž˲°bÎ0ÇqÂç¶m³xñb2­T*‘ÉdÂç*¤O¼<@&“Áu]ššš(‹áu777‡‹c2™ ¦ibš&ŽãH$H&“¸®º(3™ MMMáóB¡À=÷Ü3i÷B¨"“ñE ¦&_¼kjòE8ˆÄ<Çñv*»vÀ=v}÷ö…×dY–ßç×·ãs;²®ëR(Â>Ù²,æÌ™&Øö<îX~5×uYð êºTãB ª/LÖíú"g\˜t]—T*ž«©©‰Å‹‡¡·ãÏmÛ¦”)ñ­ÿõ-ðüº7¿m3ÿü¿ÿ™‡ÞýÏv<ËWÞý÷æsñ9~ó£ßðÔ5Oqøß³éO6ñ±?ÿ÷]s{¾·‡k×_Ëo~ô~û/¿Åu]–}oŸøÓOpÍžkø÷[ÿGî{„l6K1]ä×þ1Ý÷QÒzš¼ž'N‡"äwoù.u=†[pÙ{×^v}p§÷ttMçÖ[oåÊ+¯à ,7®ë‹`Žã‹d‰„/*<Ÿ÷Êé‘»Í4+]Ùl$:‚¿/“ñÏ¡~ù|e.¿xHNåt¬ÎÙh#;┓N93!ÊUè8þ>U§aøí¬ †1¬¼^ˆò,ÆÝ—¥‹Ñý‰‹£ù¼¿O…?ß']¯5OVÊå(פ ‚ ‚0"µR, ‚ ŒÄ¼={ЇWzOq#C’§¾™Ì XàpÁpê‡ý`”‹-Âu]á¹ç²ûÀA75C­8p€®®.8P±ý¼óÎcóæÍ´µµMu»'Ïó† QgÛ6ù‘Âp ‚0ã¨ÖÖ&tzV‰nj®ÜL|Á0ü¯Êäÿ»€d‚éø¢¤ì+ÿ;ø^)¨O•!8§œ£äƒç™ ª®{ð:Ž~à(üá#ýÏ£,Þ±˜%üð?ä²ù—ñšî×ð嫿̲'–ñž«ÞÃòÏ,gÏš=¼ç”÷ðRæ%.¿ërö¹7ýèMÜ¿î~îÛt7¾ãFV‚mK·ñãÿûcš^ßÄÛz?]ÿSûÙc<÷Üs¬a=?|÷øÕýä_óßþê¿qÁ² Øõƒ]<~áã\òºK¸à‚ x¢ã zŸìåª%W+¿’ýoØÏÆÏn„ ¬ºhó¯›ðˆõ‡–âò›/‡÷ù÷è*ó*ø|po˜§Ïc…¶þÞ¿Å‹Xo ^–K¢×Ú‹½&êQ‰ÕJ,V¦1/ö~(ûÛ üíÁûk.sÑÑézKOv=9Ÿ&¡.Žã;òT¸Ë‰\ÄdÇH­±Ï þÌÛG”öƺú{¬ã¦‰\]žLF9 UÎǸ[TAAjP/Í’ B—Ḛ̀wï^ÓKÏqáw.¬.ÀB ¼4¿xÃ\žžóJxÚ€'pòqÞÎy¼á o@×u‰žç…iva&#ÂcâŽG… <av2–h¢£F‰Š*Ôª3(ñ0”q‰„"åŒL㋃‰àú®î£±Ð¹ËÑþ«xä©G¸Ì½Ì¢løÜ>Ç'œO@¶¿°n¸^³×?O'”ÜÉ|tðLïoú>ï5ßë+¾Ðˆ÷Þx/s9—•?\ Iøîùßåñ+çéO@þßoÿ·¿úv¾^ü:hð/õ/|zϧùqùǸžË_gþÚ‰šîæF÷FlÛÆÝç’vÓè¢ó&ýMlüÓ¼}ÙÛ)}¦D¹\¦%ÑBòMIô¿Ó9'y µ…|Àû@è@Ç‚åéåáí>ã#g ¡ oü‡7²ªc‡:Ì\ü¬¹ ×͹ŽüÃ8×<—Î öx~Œ§õ§¹V¿ÖIœ´¿¸äOàIûIt]¿VåW±ŠUáf‹X¤-òŸ—a ‘ûÓ(Æ„–ø×†R´ëé0ÉûµØqzÕc-íJ ^»x9µ]ÖÍœr¹¡Âb>…U/•«#j8n¸B_X¹]­i¨F•G»ø¢žP™£öÛó„ÓÙé‹MM¾ Sò ‚ ‚ ÃàHŽpAFê)†ø£]Ã4ᢴ·;ð„X\×û5¿Ì_¸°7:ä¿}€B¡@™2ÙlVôaÖ0wüUÌN\×&¸Äí(³5X8ëØ±ã« 49Ôâ!SÁwfˆB«ø3ó½DbcšJñ©<ÏÃÇþéc¾ØØÔ¡m:<ôÒC¼ùýo¦ï_ú@˳ÈwæÙyÛNHÃ}O݇™6ý6àÐM‡ü<‡b`Û6·ûYÃ8„¬ZYŠ ¿F‡eÑü“®ëaj·t:-9f…Yƒ5( 5sÿ‹Ïc›6¶m“ÉdÈçó8ŽƒeY|ö+ŸÅ0 2™LØwær9lÛÆó<4M#™LÒÝÝ ~š¦ÑÙÙY!Æ×@+pu®¹e ôSÛÚ%“ëú¶ ‹C¡å¬Uœ:#QÚ×8–Öù5vìö Ýì¼Þ‘õïvרþx5RÚx·¿Fýu®«ž Yª³½Pg{½úmÆH>?Ô…Z¯ò5–­†–AAf7â6a¬œýë_£y—œrŠ¿¡Á€9¼ì2äǧüi4çeY¹\nÔ焙´¸øâ‹éê겯½½‹/¾˜óÎ;-[¶Ð××7áçWæjâ[Mˆ‹ãQN'º°—øÃÊ¥aP®F¥¨ü‰‘ð¨ò7惿tP.ϘÂ^ªU—JÔ4 MÓÂí…B¡¢²,Ú¿T*áº.…Bîînß•¨ÃÒ÷.¢02¹\ŽR©ä‹›ÛÛ0 J¥RX&NS(°m›îînR©Éd’l6‹a†A6›%NS,1M“b±ˆa¡8zÂHŽ¿ az0Õc‚1cš¾ð˜Íú®Çaò/ÖëxÚΊõ<öòåOopèfï¸ÏÖØ~œÚít~Y£/ƒýtUÁc-qÐz¢Æ9ë]¯¥{‡n¶‚½wèvdžR=ERÓ†:N-j+¤µûþÃ'TSïwc­‹u¡¦eÕ&<ãbh!(ïÆŽwˆ¾jÕïaû4¥^_0-ûA&…7&aR˜Ì¾@B­ ÂÌ`:Ž ’ÉddZšc §i€Çb‹ëc?MÕ|\>?-’•„2¬ð¸iÓ&Î;ï¼ð`ëÖ­Ûâû&Š-[¶000t櫽½ŽŽÚÚÚØ¶m}}}lÙ²eBÏ­&öã¹½²êINSÒØ6‹/þ§öq?¤j‰hÒZ‰Œ:‘‹Q…MçcË2jAL-€ÿÇOÜ…mYº®Wˆ‚𦅂£ëºäóy<Ï EÇB¡@ßÁ>pà/>ùá`Èó¼Ðyèº.®ëR*•‚Ûa“H$èìì$N“N§Ã¤Éd’þþþPP4M“tL`©Õ‡ Âñ0•c‚1£ë~HOMóvÝÝþ¶¨Ö~¼ÝþããÝÚxGk×ëžÎê¡ÛÆ ådU?g_^Ü9ä¡uVƒóÊêJÀ› Þ¿W^ˆ³+8÷ýUm|ìUCÛîP[¤´»À©‘‰ÜyœÿªQþ8§x«£E#¥'¢à $íà˜øÚ J[ €¥ªòµ@%ðC_—€&|qQ£ò·ñ¿oœ ls°-«Û ¶«ï¤L°oNìX¥n7å2±öu¾ýÿ¾}7nê©ÕLË~@„IcF A˜4&³/P{A˜ÞL§1 >|¸rÌÁw=þ·2\¢d@Ö"£š‡„ÙÄ©µ6666²yóæ)iÐÖ­[9pà@Í}Û·o§µµ•ÖÖVn½õVLÓdûöílذaBίÜ>ÝÝ݃ q; “M\ŸRóÀÇó®s S÷ {ŽéÌ”õžWyÏë9D”#F ³ø7] Žj‚ºzR;öÂ8ŽS·_q‡B¡P†4N“Éd(—˱æz8ŽCss3½½½X–ÅâÅ‹éííEÓ4²Ù,º®£iétš3_u&/ÿÍË|ì/?ƾõû(•Jxž‡ëº‹Ešššèìì¤\.‡ŽÊ¸˜˜LFª©ˆŠÂ‰`ªÇ£FåtTù±ÏIn?äUw8ËïR*–6í÷ªûsç’`ûOA¡Î[4c7h/öS®JiX *2üížÎÀéD®ì`!¦;_ÜJ b^7x?Võ%À¾Æ¯Ïñ ¹?'m¼‚»>8oÐm8ø‚¢¹‡0OkhÚ;úÏ£aŸ öeAFt#¼ÇÀþ@ìæ÷ÀwaÕµ‚/ÎiD A„á˜_”3cåÜà¯9(£ã÷åÉ`AÛ­àþAVPÆŽî%‹ƒºMÿÞ@P§Fž[}¨úÍàXÕ®2QÎ`;8Ÿk‰(¬·rÙ«ADè;*ÔcE÷Œ¤_ß‘5âñN3êõÓªaR™1cA&•ÑÈo]A˜ÞL·1A¸ä'§°¹s3ßÎ|Ûÿ V°áô2œ¡Á#jÕoŒ`rV¥!’Âl¤®ðØÖÖvÂÓÓÓƒeYÜvÛmlܸqȾ¾¾>ZZZ*Ú¹víZvîÜ9¡Â£aC>ð2ð˜}TOèV?·ñçï”"‡?o§&ˆ•ÉM͉æðçU]J³RkV´àOiRJ¿ŠGP3‚çêëÈ$šŸÔˆæ#KDáéôØ~5gÌ%†©X›L`îë^7Õ·¿.SÝ„“ÿÕ¡íi"‹ŽšÎTÙPJ¥R( 455…aJu]'›ÍbÛ6¦i’ËåÐ4|>eYxžG±X$‘H`Åb]×I§Ó¡â¦ëº<ÔþŸ:ð)ž{î94MÃqœðXÏóèíí­èëTÈUA˜ ¦º/5¶ Ž–½½5‹x@aQÔ7‡‡¾üó4pnTØ{!øw,>\î½ ¿ ¿/*€|ù8³è‹#Á€{ºßï4(ý´ï€™ÛÊà^œ+èà!\eDáCmð4à#à^N”¬Ò'ˆ¥á–ÁË‚ˆfÎ}ÁöïW-$Ám>ÎG@¿ _P³ÁU‚å÷ÀÈà÷½%pŠA>úзú÷Ì~¼3À}7è¡°é=-k¿r4z±¶«Å#I¢/_ŽU¹Ù³D_ªê‹5ë·+¨|¾eÿºI⋎ù ^õ0cmÈà ·Ê¡hõª¡èpß3q½Ò¼õØ>%„±2U¿iï{Ç}´ÐÂt¥^_0­úA&•3&aR9}Áp „A˜z¦Û˜@eƸ®ð3®¸˜ô2¾ïB1)ÃûLXlò¡Ÿò”ëV̹¹®‹eYfU˜µœ:þ*&†n¼ñFÒé4k×®²_­dˆw .¤§§gغ_xá}ôQ.\X³î8ÊñXÓ%¾ÕZÞ”@¨ iMDó†&‘)@™%ìàQͪôIq”¨þofhÊ$5'×±Ô9•X¨êW&µO‰“ªŒ$•™C]Kõ»Ó"2h(±Ô–íÙCøáUWMõËV“Éì ÓŽ;wÒÓÓ3î1A]áq``€ë¯¿žžž6oÞ̆ ÂhóæÍôõõ±}ûvÖ®];î°¬]]]tttpçwNÊÍ:û쳹ꪫF5Áèºn… èd£b".†EaRÍ‹&cÇÄ]‚y"— F”bH9ö”“/±R×R±mzìQEËTÕ£Ò,©:L|±°zÈh…MGƒ(E±: 2;¨òzÕvu/ŠUçËpUãöã¡¥¥…–––Q­ô9ÑLv?°téÒaû«Š*JPTqm“øo0ÿ¡¶y7Êaèy^˜PZåw,‹X–E±X û¤q/€B) B[[]]]tuuMuS†0ÆÃ’Éø.ÇÑüHØ\Þ墳…Á?õ/IðV9ü 2Ÿ†ÎŸ~ᘀ}Ÿ×±¸Æwh§ùßo^PÔ¹Æ!ë½ÈßWŒÑw²úö΢¸D‹~ÀÿŽ,Û¥AˆïåÑ÷±‡ÿ½jíP"¡ 8fÐæ+üï]µ€§ nÂb¿½êû;¸gFßÇ*õbSP<¸EaÓÔ |Yªn¹„/Lz½ %ˆB¨¨®½zħÌÕc!5ª&G¥ âíÁÐ1*Ÿåvz=Yc»gUo‡ÑTj…öööQqb™ì¾`Ñ¢ES’ZB¦*ÒÉúûà’K.‘¾@ßê÷ÁÇ?þq²Ùìø+„ˆÌ.õ˜@E§ó€Ÿýìg´©_gGœ!å ÃÀ¶ý_ßžçaÛ6ÉdRúaZÒÚÚJccã¸Çu…Ço¼‘¾¾>n½õÖ!1Õ‡°§§‡ë¯¿žq5B…9ºé¦›*¶···³pá 7eOOÏUɹJYåxœÎ(ÖxPé’ rª‰Cn´3ئŒ^jÒ1ž§Pu´zl_3Ñä—šÄL¹ÿ”^£\‚ý±òJ¨‹G¹Ô½€§Ðá^A%HÖBÖµMSÕć‹T~-ÿM¬Tõê™êQ~ã¡S•¸˜L&I§Ó8Žætô&ü??ª³ì ÁwiðûÄX}7ÛŸû’¡ÍÈQéÎSßJ°S(aO¹!•¥¹ø¿‘´XÈUhÆž7Ï‹Dc¿Ë,‰vJÜô‚2êN)hw°_-*ÆÎ¯îYõ? M­8ÜO4c²Õ[ M×úeÕÏ?µ¦DÝ'uîø‚ªê|ËVP^Õ¡ã®Gµ]‰¥Äž+Q2¾ÝŽÃ¨Ú®ÆRj—Ú®^c/vŒ*Ÿ& ¯HP9ÖS¢³ ¬fz2R_0åý€ “ÎŒ‚0éœè¾@~‡ ÂôcZ ‚¹BØÏ¨…@:Pø`$n©îH¹»©tï©õ•Jزˆ„Aµ¨GÔw¶!ââZì¹Ô­Þuª×*Çö+ÛIýEAJp$VßXJÔ“À€/<–ˆÆBê~)w¨º_JtT^–( Ác‰HlU_j{gP—+ïÆ®)ž7:îXTaèUÎêΪíÍT.È*Umï%+jÀb*EV5Œ—Ë_ÿÇÌúÆpçO £é ¦´aÒ™cA&Õ¨…Á‚ L?¦ó˜àÜsÏå¾¥÷q‘s˜éèÇ|ŒR©Îùår9t]'—ËI~GaVSSxTñ[«HÖZ] ÊôôôŒ?_Ò´µµqýõ׳qãFèë룭­mÂ’_{žwÂìªUë*\—úƒhBÍ Q¦¹ÓD£Z‘oâOD¥cõëÔÎu'>Q¨&ÂD4¦#“Ñ,Û³‡‹x>õ©Je_}øâñ×uÉd2¡“1N£iär9E¥ãø‚úSX–/n9Ž/0™¦ÿß_*ùBH2é—\š›ƒë1üçåre¹\$©¿¸˜åº‘`©¬êU ¶¹À¯U‡eEmðQB£ZH¤^Õtì%DÖ Ãž®zŒ× •¾Z˜5ê«%$Ö«c¤å“¹ÜBoGnÍ‘è§Rõ*×e<ç£ZüeåºÌE„(ÅŽËâË "ªrR¨tEº±z\*Ý”ÙØvÕªòªm‰Ø½NÇÚ‘"Z¬¦¢^ÄC·*‡¥;^…Yõ€—¦¡è8Z¦´aÚ } 0þ¾@™A˜¹œÈ1ñ0ØÀû_ùJþèðù5ütU?¤³Ù,¹\Ïó(—ËâtN j ---lݺ•¾¾¾ŠÕµV(wäDÇJ~üñLJlkhhàÎ;ï …ÑuëÖMhÇaÛ6Ú$;ÔDU|âJM>©üIJøS“qÕ-Êi!qÔäg'c3fI$iaºr¢ús~ñ V«\µêÃ¥’‘üo­N˲Ð4¤¦±ä”SøÅUWqï­·â$“477ÓÙÙIR×É •ÂQ±X¾Ñó|!-.NÆE%ÓôE¥t:¯âèz$29tvuàyž/~¹n$„cÙÃJ¥JQPÓ ¿¿²Žø5ÄÊx¶íoWâju[Õ=%NV×áy•¿j|ñÕ4ýs©ºâ†?t½¾1ŸÄ½zÑêë¯Æ4#±Ò²¢×¢ú<íª¿vñzëµµ½½Ìt¦bL0,ù<%M#½‹Ê8•*¯ãü>#øØx ‚ǰïó=TÆB%ø}² •X¦Þ!Êy¨BhV›°wô2ÖŸ;Ù1–ŸJÌåþ£ºOQ„%›ø&T%Þªõ&iü…\ê¹Iôz49FM|'¡+¯Âª×DýîTÎQ•³@åâ2åD-9SUy"?kªG9/ ¢TÄ‹‰ ÚTæ¶V‹×Œà±ý¾û8{’NÕ}Á”ö‚ L ÓnL ”0Y}ˆ‚0s˜ò1Á€ `ùÞå¬Ú½ ÞNª¦j…m¡P@Ó4Ç!‘H0X½¸]f!5…ÇuëÖÐÑÑA[[Û°tttÔ´;O“鬜LÇ£šƒT¡¼ 2DÖhÏÌ«˜Éd¸Ï0M …¹\Ž\.7!NjA¦ÇñW.jxàñ"œW᫊ÿ¹{𜿠Àù€?6ˆ›"•¸w1Êb¤ñãºî˜„GÇqÆôƒo¤ð¦©TªBLÔ4­®XèºnExMÓ(—Ëåãm+•J …p¿mÛhš–) ç¯^­oYVEÛU]êÜzë­üîw¿›„WEÀu}A±P€ææÊè ® MM0gŽ¿=—ó#)ÄI$ü?UOõþ¦&1”ª§:lS\´¬%lª6ÄÿÔ{ÅóDAA„:\ñàëY48Ⱦ+  •k˜<ÏÃqŠÅ"Ùl¶näA˜mœ:Ú‚³"c=\×=.G’¯UDýTN2 ‚0½yõi¯ö?´Ñj5צ&ì£j òù<šmƒ®cjZBAVL Â, æv¤€ÿÅpÿ‹Þ²àœfQZ=I”ëYÆ‹ëºb"ÓétÍò©TŠd2I>ŸËÇŸÙ¶çy$“ÉP ‹ÿ@TâŸêã]×¥P(ÏçÉårèº €jŠa$“ɰ­‰DÂÇÉày¦iR,ijjÂu]²Ùl˜XÓ4‰ÝÝÝç7ƒÅ.¦i†£a"¦:¶\.cYX–…eYd³Y®»î:^ùÊWNõK83Éd"qNÓ ›­ ɬrÃj¤Ó•ã]÷·¥Óõs(«ð»õöwwG.Hµ8"ŽçEû-ËÞÛ•SíJ&ýëpݨý–åTÈ(σr¹²nËòÿ’I¿žZ 8•c|eYSÝ`A8¡ŒZxœí(ÛóXQëŽm ŒŽ‚0Ù°çµðøäf`_!pB-˜˜Žææfz{{I45ÑÛÛ+qÛa¶L†îf`p°ÿ ßÅwp&$OS??ü¢&þØ@'ж2r23Èår¡pwï×S(D«ˆuݯG‰Âñ6X–_õkV(ø¦é×|ÃkS W”@«^SÏ«/¢ª{PýÛÔó|¬ª¯»Ûok.ç×/ïºaîñ°.õzV¿Ö® …ÉÉ å+‚ ‚0 yâ|ÎgÑî2$üTKµÆ»ŽãP(0 Cæ …“ ÆâxTÁªT°¤n|RŒÒ‚03iÜ}ÌÏÓŸWsƒ‰ªZ“L5(‹aÒÙÙ)ƒ A˜%äþåk˜oiÁ\½Úßï'Cá ½‚P|TŸü4¾92I$8ζõÓŽãàyÞ¨ÆO¶m‡®;Ó4CqOåÂ_L4MMÓÐuÛ¶C±Ñ¶m …åÀq¥Î­ö' <Ï£»»;«”Y–: …¡XÙÙÙI"‘ T*‘L&éîîFÓ´° †a`š&™LMÓÈçóažŽx¸œR©: Ã`Μ9”ËåÐy©„Àt::•ÀªœJT× DTå¤WNÊ|>_VU ”ªÊѨÄÏZ÷¤³³“oûÛSýVšÞ(¨PðÅžØ{¶BœEÈ$Д¸{-\NPÈådrl击&n¾^ȶ‹õ€š {êý\eB‰–¹œÿt•˜XO4S¢\.ç×áy~HYˆœù¼¿¿^_¦i~û•ÈX,F÷R ¯¶]é©„>Ï‹„¿L&rÆïŸ{ª<±ñ{Qâz[V¥ÀªÚÕÛmS¡{ÓéHÌ4ŒèÚ‹Åèý„áýùÊ•¼clïA„Y‡„@a4¼z÷^Çï8Ì ìwA+Q™P%B9ÕoMA8Yá1 ¾ |8|ÁQ…LËâO$ζÉDA8™X=°Ú_Q ¬IŠtzTnGå2Q9ÀÊÕO‚ ÌL<çÕË¡±1Z\d€½Àÿ×¾ÌL4³R“TÂãTN]T‡hT8ÓZ?ž<Ïò,’É$º®cF…¯C ‹©TŠ|>O6›Å¶mŠÅb¸?ž“P9mÛ&“ÉÐÙÙ† Uý°ã8?ì\×%“ÉL&ÜŠjÕ©eY¤Óiz{{q‡\0áŸÍfÉår¤Óé0ä©ã8ásðÅ¿ææfÊår(N¦R©ðžÆE|ñ0¾M¹,Õ¾ê{©~¤ÆSOôUmUŽÉz†Á=÷Ü3)ïYrÓA¥;p\üE‰ñÒ~øež}–l.‡ŒÒÁv=ö¿Úž«Ú®ÜÓ¥àÑÀ_7åeÔþlP&I(,Ê ¬s£@ ‘b¿yFr[ÆâÕ(Q-Ÿ÷…²Þ^_«U§¦EõÄDy7¸6-ŸÇÚUóÓ ®1›D9Ï«ô4 ŠÅ Ø ®; ‘sT‰Õm,}ñÑ0p‚û”ÿº”cT×A×qô#¼¶6ŒO}*:^¹³Y¿½õ>³étä Õu¿½J¬-—CáÔôáܶÅ"Ö’%á¢òw÷¦M£z?‚ ‚ œì¬t÷ÐÀ.\t–‹¬?.¶, Çqd®P8éá1 :wO=ÔÄ€‹ZUU·júm¦ß»ÏW}¦»ëÖ}«º§nsϹ@ZÓ`Ã3pR;#B= äͧ>Ò„òÉ(KÆCpŽÚô4B““®±V,/ ÇhK†cÀ/òMƒ©ir¿Q½TIB:7÷£0ÛIºö² U–¡æÎ‰oÙäʶ¨ï¾ô%àòËö(Š{ѽFíÖÈØ(IHçÊPÎ: J*…´ªú Ôt-]ã)åÈH_øÒ‘ô\ZS¸O_Y½ºœQÁ0 Ó¶ˆóQ†a˜b¼xÖÛpKñ‹°±Äû3mÅÁ0sض]T1cÃy9KÁyl´2‘a˜Ê #ÁäòI¬8¶bNƒZô¦ÑuÝÝO˲,À0í‚eÁRUàQ¯Á™ ä¦ ±§€dnk<ãBG›Ê& Ðhµ…‘ sXH&¥Óiضí.–H&“¾0Ÿñx±XÌõª ‡ÃPUÕ÷âF‘Éd\Ât: I’\B1*ÉÉx<îîoA¡K5Ms= ) E"‘@2™Äš5k099 Û¶‘J¥`š¦Þ4™L"ûB¬+V¬ÀÈȈ"• ’£/¯àyâ÷rŒvÍ`h,?æíÓH{ @ÎУÁ™;„ŒÃ÷d`JŸŒ…ž¡Nóîg˜“Ø ¢ÿk_Î:‘G…þÎÀ4`¯ÒÓÀÈs€5鈛ØAÀø¬g Þ¢‡Þ¨ð[?€ØÖÒr@yÀeNžÆ«¯"ºu+"ºIQ Á3:šge¡×F€vY™kÃI ¾Äy }ýÅʵ7 ¸FDE¨—±r%4Ó„~à HnÛæý(,µœë3 žÇg4÷]ŽŽ”Œ¦j®Í´Ý.½·)¹ïVî7 @²« êä¤k¤ ibðŒ¹£¹¼“ÂùI!ÿ¸PgÑøl÷M1Ÿ+¯r¿I§OCþ·ƒò³Ÿ+W9C4«ƒ×:Ï)ùÞ÷`½ü2ìHÄ5xk¹ÿ´X6ψš¼ðBÈɤû»‘k3yi¾Æ†G†a†a˜’ØfÎ,†q¥Š×O^R2=mÁ B™Nƒ €oU}>(̽L³ ‡aÚRêÜ÷žû°õèVç‹a”µOS0ü)ÔÙÛ‘aÚûU_†3 뢀&ðæ µX DF¼j‘L&]¹E¡M Ó4Ý}OÎp –ôòdY2™Œ»(#CUUȲŒd2éÊL2¦R)×[¬Æb1×°Í…·Ô4 Š¢¸ˆ²,»áT'*…s B2š –”¦Ü=½™Ã4þ~7ì&dÙ3Ȉž”%@r°ºœq¯Ÿ´}@ôã€ô:0ò)Àü*û! <èDW;ÙË/˜o= iï-N\ûcŸ€uÀ `ä[€öxÖºœ`Ñâ€FÖ&²J©â9'>rw´ŠÊFÈ»rÏÀsŒÚnE⯾é¹ã@:$€DžÛà­šbºÊ9÷ÄÅ4MÁ–>«@ÌÊÕ+éýÀw÷æ×¡ýð~غê¶m›¯8(pŒyAèXpÄO¾§òœkß~;ú?ùI¤V¬p·ÍßKT¬C¡½8óý>«î†äÁƒ°?÷9×yñEHï~w®bÀjĆcx$/M–.vì>÷9À4Å«»8Õ'´®ªzáf1û™µã¾û€Ï~ Ã0L5ç٠ô6€Ý§Oãƒærœ¼â£¸ûðÝ(¬^Ó4öxd:6<ÂYy@ʱ ´Bp^DKïöÆ0L«±iù&àM8JÇPÈÙ“§Ä ‡®ë®‡O&“ªª%=§†i1(lè9ð\hb€-(wÉãG\”T+u훘(°÷,…?%Ãí_XÊ‹Œxþ”ò¢p€ã=Iéãñ¸[F<w÷¹¥ýEA4E"‘p墸·y;ŠûŠ^‰ä)é¿,ßo…D¶m##‰ Nc||¼FW†iylÛyþG"°¯¸’¦Á‚c¯S¤v~0»€ˆD#€ô0ò?Ìgå,@Û ×@˜xÀaÀ¸0/°P^Z õi xî'0þøX›r¡[7êD–# ñ øÝàD·8²DåbÊWÀqÙ£¸££ðÜÒ±…ÀQø¹º&„|Ä Uxa$•Inrô›)üx›.ZÂÿãž5 <« ¯¤d.]@(g £©TžëeÊ©¿F®•äNH®‘¹,R Vx×CÊü#Æï: |7æö«L.Ÿ'D}=’û=íe-çêàÖÍpΑ)¾*Õú‹\ mçÄÞ ¼ò9è+i ýdµ×ñýB?ЪWÍ+C0Jn¤”ç*Ù¹wãN»%qƒOZ CõÿFxÀM/–,]gù-µ Ã0†)†à•·ÞÂW’Ëñ«ø& g† §Í½C†ÉÉÉò Ƀiú²Ô›ÀÎEÓš¦óÄ«`†ioØðUâðö)½ãÃ0-K@4êJ<ýÈ{ðï‘Æ!í¦M9ßæaâ^k8zèz,90M³èJI Jsò: æA^ƒ±X –e!Ncdd©TÊ šN§a’ɤkè#ƒ!y=Æb17ìªh ˤ} Ecc5(Ç»œÊ ‡Ãçy ㉉âG½0”6€ä) ½ˆ%k;;¨OjØÙ’bY*1ä]u@!8×Àñ””º.îKñ8¤%K\;^Á÷x2þå˘($€ÄßS¹ÿfÂÿæ@½Õ<çÊ>kyÎ+T>˜pZ//:¼(©#,x†8C(^ÎÏh–Ì+JUx1_©.w¸ÓÎÅ¢Íý®Ã{É#wK)—o³§#SI ØôósûÞY€jIÀb ÖHŸ†#€F%÷a {Ù¢‰„Ï.W·wÓF¾+ \„ ÏBbB\é!®Âo””0;nªˆ`ƒÈq@Kxá³ ÕGËóY,¿Ð”Q̃ê@õ4â@Ló®CŸ œeyí—ç—òDL+À1û!D›~R½CŽëÀ“&0¸¹Í3ï[{>‚€a¦ùÅ/~Ñè*0 Ó"t?û,€4Î?_-õŒ¢Íg«PÈ™.’ŠÒ0œïóUAæ3,–kx$âxŒêÌ6¾Y–óŸÎ§sé¸mûÓÇãNÚz©W“I¿5™tvÚ Dcœm;ÇÅë`þï¢ÑÕ0œs ÝA#f)OÒ !°Ôî`ACb<îýJ&ý×ILošþôO?½ ¿þõ…õõÛ*:» ÏQ!–„³¸TŒâÃFG†i?LŠ-ãºe×yO½2&²,»a†iSâqØ×:ÍwÆoÖŸÂUîªðtÜ•,N* 5ÅsÉ0ÀÝëP×uß>‰"™L©TÊ·w"'UUÅèè(,Ëòy5Æb1d2Dr3Rò~,ö’Å‹2˜VÄ|Øù«? ]@ä{ÀèÇ™8 m€3qHÀž´Lø]¢P˜Tú\ Eq–ùYÀQ3TÕÑp$“ކH$üÚ9÷TÞrqE¦ xÌ«2ÀËç¾\ÿ~a†a†i!,g¿q¶óé2}'…BE‹„Îч:*`-˜Þ0Š ‰€zlšþï¶íOO†ÃBéÉðSúà¹ñ¸×6ªß÷¾w!|ðª¹u~€Ž÷xÌ'âpÖjp©6‰ç/Ã0UæWÇŽá7Íå¹½ƒŠ/)§=ÅýÍR)Þ‡aÚÃþNþ]¸°—æ2Ça…¶ï¼ùA%ÁéJy0pWHêº]×1:: EQ`Y’ɤëy …022˲`Û64Mƒªª0 –eAUU× FÝðÐb•ÊÉ–”÷¯e:sµóWïì…Ž­H:ÏËmó¶ úFP<î†vWàE­ô¶Ú¨øFBû+"/´j9lk„á‘ÊjN*•­ånSªí,â†axG†aJb¸ðáEÎE)ùˆÞÛó;S8Zô ð¤D:í÷Ò †Ì½ò€ÙžqÁ) hlM€g¤Ï ›Aã$yi(/2bÑkäÄòTÕ郠a3µ¥Üi3y4J’—·–ê*'ᘆö¢‰ÔvÑhšžQ–¿Ñ¨ó™öæ ö¥XŸtÚI£ªÎgIò®5Õm;¿…BNÚtÚKCFDMóׇîòv¥>…œ4Ê·¿ß)óøñ¥¸îº§¼»¼ŽÏCÇ{<þUù}‚ o †aÚ“_¼õ¤2µ}²,#™LÂ0 Äb1Þ/ŒaÚÖ¨À0 æ< L8ºíý¬‚ÙQüæŠeY0‚K(¬3‰D022âSŠŒŒŒ Ã0 ŒŒŒ@Q¤Ói×Ò¶m7«%Ìæ5Mó…|™Oø†i Òi×dýˆÝ¨ÿÈ„éð‡Ö¬–#¯°´5´æèºóv9oëªbNû«!sLa”ox$­X®fùsõ.çE$ Ã0aÃ#Ã0¥°§k³gI*ømB‚«[>/À çè(ªÉÈ'û‚Sù a1èA4$Îj—í÷H ¦#C"ÜDã$ð’I/k$âë"`tÔûNå ¯a>#j<î´OôÌëûÛû½ûdÙ9:¿õ÷{m‘$ÏPJiS)¯.ô{(佶Ȳó—ö¹Tïu&öÎWÏh¨iÞ÷Hd¶a–ûN×óÈ”¥÷$•OéÃaï¸ey!kÉhMÊpØ».šæôK¿×4:Æã^½èêz—]ö\£…=g)ü xÇJ<ê -ÞriωaJaÏtC¡°i¥’‰’ɤ»/Ã0mŠaG4اty?ëpµ#U*F’¤Y Ã0ÜQ •¼Ãá0EišˆD"Ðu“““°mñx–earr™LÆõÒÖ4Íõl‰D"®G%Ãt4¦ ûç§!Åë@[ $®CÕ_f™‡B!`f2æn7«ˆ Ö£Þ¦†Gswm¥r£ •„te†is^}õÕFWa˜fÇLØuü"<œ4°©HREQ6×£™#9ey¢åóDTÇDžl^žþ´âþd´÷]=ðè7ò0¤ïTã’Igz)NÉ3‘B˜Ò4>vމtâÞ‘¢ÑŒ¦¿¦éêȘ¨iž6ñŒjd£|É jYÞ>…¢7"õ樿©íUô~$#*‰xûjö÷;u ý£Q'ïþ~`rÒ;O’œÏÔ'¦éí‘H^†Ô¯Šây*ö÷;çˆ×‹Œ—2Õ¶½¾§ï‘ˆÓNò¦Ô4ï<2X“1³¿ßIOFêPȹÿÈs“ÚFÞ–d$¦>ß¹óЇLÓ§§§144„{î¹ÓÓÓèííÅàà 6oÞìK744„ááaLOOcóæÍDoooEe‹J?ŽÝ®æ¾L–ð×Êjç>Gàm8{—¹Ï´©Tž»EXÈW‚£UeYp^Λà]›a QO9`/¦ß~N>ÿ?ã=%7ºP–e$ wuëp¦ú4rN 7;Õ` {2TÓ‘ÎÍp-Ë‚,˾Щ€ZU–eô÷÷ctt±\¼ ˲‡1>>À1"RD¤„p’ЬÎd˜f¡YP±0M„¿øwÈÄ#Q¹'s!|£Þìr¿×Õ­<ÞHäÍE”5râfަ¢Q4ƒÑu4|NÀ0LSPkYðôÓOW­®6¼hjÁç<9;ˆiu84λ©mø/ wn~5¢‰Ùê>ñ{\8—ê•oÝÕ+Ÿ/CÞz%W&µÍòäÒR[Äò"B;©‰\ þõD:€Lî˜ ŸQ»¨.È/ö…šû T>ϲóômÁ!•8êPÎ2!Rû*¾˜ï›8·T>viMCçt£F€š:$ãÏ/NN[4Q¨Õàº?2Q(N2z‰^w€gÜ“åü!; 1\)½æ‹Fòô¼°¥dx¤òÉ*IÞÞ‹âvâ¦éßÈSŽŒŠ”g4ê|¦P§´ í @žƒ–åívE¡BC!`Å ÝÉ`Fy‰{%†ÿ;Õƒ |dÔ$£y’ÁNôC£t€Ó†™gÊ{ýF×€Œ´´u%C }§¶jšw"§¼pØ1$†Bž'¤èEIùõ÷{ÆNQʼn8ç“Wf8ìÔ“¼2£Qo÷ Uõ¼l©Í¿ÿûÏáàÁʆMÓwíÚ…àæ›oFWW²Ù,víÚ…Ûn»Í $8H` a×®]¸óÎ;ç]®¸§QÎC¡b…Cp&aÁyÒ۹̣¹ßðf$ôÔÖ¡§»ï©´ŒNÂ{:ГJ$ ïi—Ê}ŽäÎ1„ºIðžúäöiÀsñ ã9A‚ñÜg¬R.Q+kåΧuÈå¡ ŸÅM_)À³Çs¿ÓS3ÏH x3ÀÛë…ˆçÊ¢Íüˆr S|=5—Wþ]'Ñ ÎÚ6¿˜êJFá|u¡ÙåA÷ ‘ÎÕ%.ä'æÑٳ܄SÞêWV—ÙðúRO9`ž H6ð¾—ÒÏ—4<ʲ Y–‘Íž†aH%cW й­ëläd:‡FÍ \F'5®°Â¥ô¢^­H‹€ê]×u˜¦ Y–ݽǸ(¾¨˜¦‰t:L&ãáðÏL;RJTEX õR„m@: ¨KjÓ–B{9RþÕŒF/8 ¥ÉÕBFùEZÝ(y;eÏ5¼Òý pd0¤£¢±ÈEilÛó8´mÏGû$^ÞºîL7)Ü(å':OЀé´ç(nCN{*’aŒÊ¡ðªê²()yȉ!EEC)­{”e¯î"Ty$Š{?RECáø8°fçmHáOɳt§5ó–½)Ì(ãÄ×2ÆûX<®ëþ©½¨'¦~¡kO×UÓ<Ã"5Íóô¤üh½b$âíùH}C¿Žc¾W<2îNNz×DQœôd8¥<Å¿ÄÅŸjÃãôô4²Ù¬OP ›Íâž{îqÛ·o¶mÛ†mÛ¶n»í6¨ªŠ}ûöÍZÝP.–eAQWg0G¥bÞŒ€ r&c AË}Rp¤ø8Š/%1á˱‚Js ø&€QxO¡8¼åQÉ\1x›[Š3 CI–{qãKz¢ŠuÔá=QoE¥£§&=)é‰Ky&séûsßSB^ôt¤<É0IFÅ8fk…5¡>fî‰3’Q ,/Pñ)/ eÐl€ú2}Sl§R _šUg+Õ‡f‚Ô¿¶Ð?tŒú/ßýdÂ1xÒÌ Ð  ™ÍH¸îrà8 ˜Àòéq@ Múã?Št:ÑÑQ¼ðÂb÷W‰á‘VÚPX2,ÒC2öV $Î_š„TƒàFÓ€?ì@‹.ŠgÚ€FÎ \h‘Ë{ýb\Eu º®CQ׸¨iÒé4úû‡ $IH¥RPÑhÔ ™*˲ëýÈ0íJ9² rÀ̽¥¥5 vª¶mråG,æ¾=‹J¢º ¾í6Iª®áo.óÒ64ŠF}[tb×s†aN½dRäe›¼úò­ÈëT31xžŠ´ŸÔ2!R‰³z2bªÉ\½Òh|9j„¼uõ¢¿à"UùhB:Z÷/¦#Dõµ#˜†|3Èc1_à6RÃÐïiøUn¶PŽx­Ä@r¤¢”ù‰ž“PðŒ¶Tç üþbý©Þä@÷€-œGFjò1ð—Ò+B‚ÆÐ`{ƒÞ6U.]§p.Q¡ÏÉXLjbRýJöþíßó7eÜ5õ£Ñs{!`œ ,?öb]AÅ€®ëÐuÝ݇K/õ<1Ü&à…÷T$#y鑱ðö$O@šÖ’~‘ÒžQÜ£ŒfqÁùGÔmR½TÕó¬#£í-HžzºîÔ¤RˆSÑÀ¨iž§ AÆTqJ,[ ŒxQYöB Ry¤3¥½ ©,úLž{äåH†Bª÷ȈcÀ}¢š… ¥ôú”ï8-Åöˆí%ïHUõB³R^¢·!åoÊN¯N…Ž—3Í_Á¨ŽõX‹Ù†Ç‰‰  ¯¯Ï÷û† 011sÓ½½½èëëÃ*ªªº¶œ’¯à:üÆ5Ž„'µƒËklx0¢ØLžóf<ÍXÄ'™hMä9_\›ÏÃJ ¤!ã–˜&–'ø],ƒÎ›™c» ]¼~x¡d¤$txF¼RP?R‰ùPÙIø Ÿ4ã´ùt9:µDzŠe‘ú•âYˆöEáºßräìÅÞ9vrm©·0O§ÇÛÞz¤ òôS™Ì;18¸ñ¸äz Ò£”^IJœ‡£¦yqÛiÅ…P/¤­@¢ãô¹ÚÓÃSüKñÇisàxÜ™P¨Ãp¾Ó†Í”Õ—VÔPøZS¨@ùú4qD1Óé[KÄÉXµ™kT»-ž£žu¨ž¸o®è±_[ˆ¢-hš†d2‰d2‰T*…þþ~hšY–aÛ6t]‡$IPU‘H„LGQJTKØÿkÒq@^Äשqô›£î¡VGªµSí< %ØÕ‚·’(q³Ÿ¡ás†aš‚FÈ~@ZwOÆ'RsÕ_AdÌVK_*û\_õæ²ä\Î)vž¸03¨2ŒäI'挒L#ª± õSð)¦åÉCL£Î!?¹@ž¢+ôn<7ß=P¬ó¥/un©ë,ú\ˆ}N×$xþ·Oœ@³Ñè9¹H¾øÄ?Ý_]p ï*.‰@Q ]æN¹Ä½Å5pѨZ¦ižžL JaC3¸LÀÛ+PÜgö7¤òDÃ"©^ªê IOIF*òÆ#ïÀ  à7P³Õ«Áigp}‡h,¤ö‹†KÒÒžŽô_ôö#DãõE&ã9W¤RžátŸÁúiZñúÓ—3­¦<ƒySËÍ«Ò)|©¶Õ‚¦0<öõõaï^¿dzz÷Üs»Bajj |º»»166V4ÿW_}étn~„aˆÅb>G³Y'(§#p¼Å¥*ÀlýB¿ ió) 2ùE—ÐrJ#îFJK‡HªW€DµÐT>‘„·Ì¦ÖPèR·Ÿr 5Ÿ®e¹Æ¿RÝH­„oyT­¡}?iv4 çÈf³Èf³8räH*V>µ–päÈ a``öE˜>zgVôbaé-Æüþö·_ÇoœÂ‘#Þƒ/ *€ñ¸"@ŒNCT U@Æ@2FÎC“VäPXJ+nRLSÜrÓtVîb|pÊŸV Q¨À 9N;厌ø71¦¶ÒwÚŒ™ÊˆÅ¼pÔô@§É©®”ŽVaQ]hB$†BÐ4LvÊ“ÚOFWŠN«‡(N~"á>iU­Ü¢É’Ž‚V&‰}@«ËH|“‡*]/ á NttÝ 5A9‹a!¨­”¿WdÄ1F˲ó9ç çn>2â]ºohSqZÕ•N{÷Žm_ÿú–.=×^ûÎz ï9Q¯9A6›Åàà ÿ mºØ ùWWC·mš&¢¹FGG¡ë:4Mƒªª°m±X š¦A’$ÄãqȲì†Te£#Sm&&&0<<Œ‡zhÖXjJÉ‚JçÇŽÃÐÐÎ~ë?BY¶™Mul-Ù…·n±c¨öî\W„Ð2ðFy|R ¥FPÀð8<<Œ‰‰ ;v¬1õ*B=Þzè! aÛ¶m¼'$ÓÑ áСCèêêjtUfQ÷ƒ§žz ‡àE\!µ^ƒ$:Ã̉r§J¬3ôt†Á<¬gå4°çþÏܰø˜ÿÜ»î:@ÂîÝa$ üÞïmœ¥›"½M‡Eé€OgG:(2 О†ô*Ad GQ‡ÜK˜­;ŠF½ä’I'ò $$é ۧô[¹NJü.B†Åà~”ô åBi)ì(&I¿©ÍeuF…šÙi`xx<ð@Ås‚¦0<Ù·o†††ÐÛÛ‹H65;çœsÐ×ׇ 6ø~·swºªª>g1ÎL# ÏϹïä5‡°ÌÅ$áì$€‡ `<§¿Ùö w2¹6ÑHM¥ü›·%“~w*ÚU”­ t\uaÞÚ,+Uà{ ]÷´ß¤ •šôRNäÙ$}DðÇ‹*#¢ÚÐ~”dp£°®…˜‹’B/#=yÀæöQôw¯5â⾘ò{{{100€|°N›?Õ–°téR  ··öQSæþð_ò¦¥Ÿüäqôô¼Ó¼Ò(ÐfÊc~üF6Æäe(êšb1gèÒFÃô@WUÇPEF&À{0Òäƒ&.dH ‡1Bضð¡0­´RŠ>WÕЃ–†3=èIÌÐqj3åG†,ú xm¡¸ãä­IF<ò¦$—FÂ>ÐD‡ò¥ólÛi+…¤•e/ä%©¿Dã"­–¢>¼8ìäåI¡$¨oimG:íÅK'#$‰FÊ‹&}b(\š@Šqø)-M I„ŠFHÚ;T }@÷ª3ç//ËNŒ{Zû¯%µŸ&Ÿ–ÌÌÅøøV­:Zë¡\1µš\qų¦ÓÀC:0= $üAªå¢(Ši!·O£mÛX³f dY†ªª>C#)¦twwc``ÀU²5;AYpàÀŠò[¼x10<µh Žµ”gS‚¹h|Å¥ã€4@ H»7lØ€ÞÞ^˜ C[&µx?X¹r%ÐÝÝÝèæ1LCÀO<—^z©ÑU)I-ÞNœ8õë×ÂgtLU˜/ô¬3ôt†A¬·èS—}Kžµáî»Oã‡?<‰¯~5Y–Ý¡bä2ұɲ£×¡ÿÉ$0:êèrHßx:(À¿_"¥#'Ò®YãíݧªÀÌŒ“4êœ&îI^†€£ÊçÑ(ªþƒßÅСåPj: ]\=ßõØ…Öý5jë÷fgÆ xõÕW+ž4•áqbb7Ýt²Ù,vî܉H$R•ÕV‹-ÂW\1ËÛ4MH’䯴Ž^rz'¤åàêÐ8 ËžûR&ãÝÅ“@,îiÅ¡²0 E2¹‰ŒŒxAžóÞR£BUcP%àIx¯J’tä~“oÔ‹›Ð%“Žf[̇ÜnˆHPRŽáÕðT¸(„%oéù8á°wŒ´â¢Ÿ´i:åˆ~ä©”?xÜ©ße ðB ®EØp: Ä…¶‰}÷aŒû ¥‰Äì¼MxÀ…¹û"p%¤%'G<®+T ¥zFk2âRÈZ$¶‘¬OôÂ/ZHÏ…Š® ÅÀ$t¸\ú'†BÐÛ2Ä»×4Ñ àÿ4ñ‹u­ä,[¶Ì]µô¶G¦°îœu€²1oÚ'ž8…G9ŒÃ‡OâС‡È>ã ]V>äµx†,À[7à:%«~geÀ(üõO6H<ŒûÓ‘( FR£|ËѹQ˜ƒrÒ£Ô¤@<®iÞÐûŒÛCÆKA±œwŠyQ,xñüLoáT*ÿç|åËöQ¾ ø[¾xâñàÝÁ4ùÎïÇ t ²Ù#Èf_C³Rë9Á,/ZmðïànŠçÀ_­Ep¶mCÓ4†t: Û¶‰DJ¥ ËrnzI’àY0SCºººÜ}Qš™ZÉ2<Þ5 (‡\ZÇF‘›}£Æ8i+r³ÚmŸ‹á±ñ„ŠQÉæà•-IÐÐ;òž={V¿RÔòý€ ÓéÐ8hFïg¢–ïË–-ÃÊ•+…óha£#Ó‰ôöö¢···cç¢Îp«€·ï{w^û¶J³ç”G¾‰C‡ÎA2™Äèè(OíOžŽ™Œ£B&C-Ì×uo9E죆тuqQ>à…F½ôbÄ5JCÉ)Â4=Jñ8à×U¥ŒÕœb7³`'Ñ×ׇ©©©ŠçMcxÃöíÛ100Ã0 †9›e@ ~/˲ ( ú!DéIø’ü_ÕY~¬€ôçb’FY–½%¢Ñn‰Ç"À xÓ ¬„(G£\B0ȹWH(ù—Q‹/ûùV†ˆ  13ã…*"WÀ+o¹ üQ XnÖ”“¤+\™–ˆ¨å À¬ªÀ÷ `DpE}Óép·êž÷k xXñvò.T>È °À>˜§3©M‹%Çûu-üF?rM£X‡ÁkoÛžô'Ÿs±ô„¢'¹r‰ùXp8D4 -ßTg[*ÈÊ4ñ‘ÇG3RO90öŽÅ^8Ç÷­>²,àÁÄøøUxöÙÕˆÅ.÷…#%/21L­¢IÝN¢3q¥ÐÚ’§bJ‰?ÑÛi?1'°ÿâ/ ýò—À91@âç;ëW"¨ÌÛ1CUU¨ª Ã0 Ë2"‘lÛÆÍ7ߌt:H$I’`LÓ„ªªî¾"–eÁ0 7«®ë°, š¦Á4ÍY†Ëtγ&‘HÀ¶m×›%N»ž•„,ËÐs+&(ô+Í“È;S’$X–åLÓé4dY†¢(0MÓMO{X*Â@¦üE$I0M¶m»çRZÊC–e†á¦·…½eY¾¶Ú¶íþ§|(OUxZ–å¶…Ÿ‘÷©mÛnžÔÖJÖ‘ÛZNúZÓìNåÈ‚Šä@<{óVHï¹¶&õ§{K¹˜~î9ýéOãÛßþ6îºë.LNNbãÆ8uê”k¤½“ɤOIÏ)äûs‘H9L3:Né“ɤOéN m"N» pÀ3Zˆ†:ÚS’<2E)µE£Y8†¦i°mÛ52(Š‚d2é. Ãð<EqëBu c¤Xßd2é3JÒ¹¢q1h¬¤ß“9×s2hˆ†Çh4ê7‚ÊýbˆŠÿ¹4å32Ë!c/>ò_©ODã}&#] Ëß¿ÿœÛWŠÉ‚ªÈÓ„õ¡ÏA9 `uy§Ð=‰D\ã?õ1Ý“â}ŸûÞû^¬<|á{ï-iè¡û–Æ©XÝ?´ €î72ª‰¡›cp PÖ]w¹‹‚FRñ~£{ɲ,$“I$ Wn‰ ’ɤk Òiü_ýÖ[8;×ùŒdb?S»¨~ÁÅâøÊW&ÕÛ4MW6üjÛ6h± é\qW–Šc7‰À4Mô÷÷»2'x IFŸ_Ø´ ïyÇ;ðBÞ–¢Ñ–Œ–$§èˆ!¸Óé´ïº+Š‚8iµP¿¹÷Ëè(þK?p÷ݾz’ŒyíµæŒ‚Ј9Ã0ÍG­eÁ­·ÞŠÛ¼E‡a8:=zLÑ#÷;¯oo†Bt2üP:ÀÛÓ!ÏËý–ÎKäŽ[BYâæó”‡ˆh#µœ¨,œ§Àyñ1„¼)q_*zìjÂñ˜‡o3LjŸœkƒhüãÌË<’ðo[|#ãfpgYè#2®Šú˜`l{2òU’âôMÌCìÿrëGùÒ« Ý[A#)BÉXL×>X/Ñ€Èõ›ˆÏø¬Òªp^,—>W®¶¤ŽßÍFÎ ÆÞ:ƒ¿u¬èÕ®®‡Ü¹Ÿ¸íC¤ŠŽ ¤Ö&b0©¨:'Sy;Š>4t~0ŠW¾²ÈŸ%_èS^àÏT‹¦0Œ¯,p<,J‰8ߢ{8M:$xò¸óyú²it6WIò` z˜¥ä%¥)«b±˜¯í¤D …Žªª¾Õï¤N§ÓÐ4 ²¢@ÎãI+z¤ä*RÇ+_>õ–=/Ç'GY›É1•V Ý{ïF$î¸Ã¿‘q¾î v{“v1ôšëaœÔ`©þE¨ù ?ÑhÔ•ÑT·÷¿ÿýxàpþùçãÉ'ŸÄùçŸ{ï½o¾ù¦k˜Óu£££®B=–s&cîHao&''a†kø /ÈX Þ‰h¢ç†Rd±y]J’äË+V ^r$É;×(¶Øs²XÿÎÃ0‡}¿™¦‰‘‘Ÿ12X¦hÌ ¢áW4fˆ–t]ÉCa¢UÐËIœˆÆʇú?hh,Õ7A£ÅHžÌT¯›o¾yÞý\KÊ‘U‘o õœÙ?“AŒ®y°Qÿ’¡ÆÎÈȈ›ŽB%S‹óÛx<ŽøÙÏpÍu×!ÒÓã»ÆÁym¾ëœL&]ãÓøøøœÇÉ‚ `d20B!ÌŒÏé\X³fÛnq¼[–åóÂ.$ îþÙÏðÒ¥—Bëé™s8éx<î~'''ç왼`Á<û¹ÏÁžsÛ-ËB? Ãpet&§Õ½iŽNFY:žL&ñ°eaÁƈmÜèz®‹×/N#ò,ŒŽŽúd&ýnšæ¬c$sÄÅD2™tß)HîÌÌÌämãŽ;æÔ'õ qs†aš‰zÉ9›_žá.¿gšh@̧nm…ÔQâï”·¨S(Çæ£åÉCD4rB |ΗO¬@zBœ†”óXÏ—F-#1MóCÌ»ƒˆXNªDå”SNú|÷I9mŒ”H)ñ=xžÈoÇ-Ø‹½eT¢~4zNpöñ)¬}ö ÷;…P¥)Yw÷+øOÿérÜwß âq/p]2él×ÏöÝéŠÄ|áNE¿œ z—< A¯ôAŸú^Ê߇aæKÓgåBìÝë»ÁÁAlß¾[·nEWW&&&0888ïXζmã’+®€B«r>&màÁŒ7zu=ÿ†_Åà­Tªáp±X Š¢  !‘HTmcÝ`Åãq$ 7„ÅÄ]R ‰á{lÛF8Æè訫¨3MÓ}1§óH +æM/Ù¤xM$îy¢rV–e|õü¯buhµSápë[±2½Ò}!'Em8F"‘€n9ži=”’B8F*•‚¡;«Ööó=bÔE2™D,s=4¢Ñ(2™ Âá0Eñy_RRÓ4÷{<G&“A?2™ B¡2™ŒÛÔ¿º®#‘H¸¿ÓJmZ]Oa¦b±˜«°èïïwÃéCÚQ?Q=^}õÕúÜœs Þrà¹U]8söbÞöš1XÓ€Ûo?UõõMfËg˜¶¥Qs< Øû|Ä[›O¥Ç‰D …|F'Ã0ðæ›oB–eüÞïý†††pÝu×áOþäOpÇw¸ÏNRº+Šâ*¨¸ŸÅßD%sð÷|=Ñ€¦–ñ&1WãÅ\ÓÏÅè8ŸüƒˆábƒÞ_å–™¯Îâùù>SøV °Ñ¶P_릕³ÑnX²dI]Ê™+åÈ‚Šå€iÂP/DðJ¥Ói„Ãa×`/zÐF"×ø–ÏÀ–ïºÇþ‹K–àPOïX04q!TUu=”ç3N* #ô„ëLïù ÝT¶)´}>e'“I·¬ù0Ó`û胼¶Åc"Á÷°|õ-$_Hf˲ìz­‰ßƒåÄb1×XÚì¡•óѰ9A“Rlþð<ÿé=˜þüêºî†P§2qñyÿŠ ™è~£±ôD&ã:Õ+_Ý yˆõ ùÂÃPS?P{‚cµPŸŠã.˜'-¦¶ä[ÈE Uò›ËB*C¿Ý¨ìÍJ½d@¹N³QÌ~(ǘÇ0LMhøœ`æ œoŸç~M§“Áè(ð«_Ã/~±÷ÞëDT;ë,' m¿D;µÑoX„¦ŒÁGUPüSèTÑ[Q]×]¥—¸";X.MhW¬XT*åü¨lz‰¡ßibÇaš&Òé4b±¢Ñ(R©”kœ##}‡išÐuÝ5ƉFLRÖ‰«Å-Ër÷¸"£!½p‰{¬Äb1ض·ð–bAÇãcÊÇ|û®P9Ô—¤ ’e©TÊM‰DÜÅôâ"îÿ‰DÜ:LNNº/câŠã GíëEùÒŠcò€ ²¦i³^Îh55]SúKŠŸÑÑQ__¦R)_ÙÑhÔ}ù|¼ ÷x¬·8ø®•8³úJwûMMsþ&“À}÷MàÞ{_„¢ÔfÏ'†a Ó°9Árëc•áð+ùt]w½DµL&Û¶ñ[¿õ[ظq#þáþ“““ˆF£XµjÕ¬½™ú (Šk )GùÈ4åÈ‚ŠåÀµÎ<ŽfK†a ™LÂ4M$‰‚ÆcÚãp> ýD¯×ùÏÈZ΂‚Bç oZîùÔŽByR–Óñ¹z@ËžïXzÏ2ÞWç|Ê.Öv28ä;^¬ßK‘Éd°fÍšy]I£æÕ†ðÒ»,è‚û‹ÖôžJ†A‘`˜\¾÷çBá~óAu!ÏXºóÅPÀ…ò zè¥C–‹!‡)lu°lqAm¡<ÄpÅb{ õ_¡ïA(O pˆöà~¬¥dM±4”W¾={I!¶•Î=óEÝ=×ÄXbùô»,ËÆ•W^‰f£²àÝÝN_þGŽbÄ0ME£ç÷_9~çït¿Û¶ãÀ`ÛŽñôig‹&Ò-žÁ¾ÓöMô()HQöƒÓ¿ ¡q®¯$Á©z |—@“ç Ål®+ç=zÑrüýC¦DF€Vyµ9…!"¯½t:íëlÛv¼írJ‘‘wOZ­J«ßÈ€E¡†èXÜ_…ò'OAò¸#=z‘¡ Z¼fÍw/š€F"wU7M\Gsû’q”/ô"N/΢RF4ô‰7ù^ªÅ’|¿Žñ4‰¸ýD+ƒu£Õéô7hÄ+’LôN RHQ¤P¸;ñü|ЬR+éx!%˜¨ø>räHÉz6;ÉÓ—ʰmÿ¤À0€eË^Âùçß € ÓìTcN˺Îõ+a½Ó1<Ò“*CUUhšæ>CiAMÐÓ)‹á²Ë.Ãe—]†5kÖ`dd„W«7òÌ"¥m!#ÓúÌWŸpư G¡ …‹Å ªjÑûE ;_*1†«ªZQÙ•@ïù Ãb­ŒüÅ såž_iÛi¯È¹Ö¡Ü²UU-jxœoÛ;åYT•9Á R´`7ß¡ˆ4â>¼t_Ð"UU}žŠí‡ÌŠû¢’aÒ’ìë%F½†Á}“üÛ›”Þ{® )æ»ø \‚Dž¸ðƒ ¤ó$ëò-ì¦ë&†fWEÈ8J‹°EŽ˜&‹ùöÑÇã®~ƒ¼ðÅE Ápàd¸%C¬XÛ¶‘L&±páB\ýõ5»6õb>²à…Å‹¡„?´j«cYù7p+–¾CžLûS‹9ÁÁKºŸiM‹iÁò‚C§b®÷e­ïCQee°ìùŽ©B2X–åY22˜¶˜ü&ÆbýDÇKEÔˆÇãî¢wÑÓ±‰D÷Þ{oSFGª/,^ Ùðö<- ˆÇ=‚e9VƒLÆoÐuoE3—ƒ{ê.Xàÿ®ªþ­ …üi‚åD£žeƒÈ·w/勉„óY4z—S6KÄãŽkW±²ëUΊ~ËM9匌ø-6å”C×LÜ„/XN4ê¹°)г¡Ÿ8ÖÄ{C¼®Á~QŸ˜¦S_‘Db~åäâ+Gkg…Zð‘·Þë~¦ÛÁŽÎ³Õ0œK (ù{ôøW”â†ÇZSát’aʦc c?ûžùÒ—ðÏ_þwøsT%”­*¤c‰DÂð‘‡a*•‚ž›(Ðqz1™r¢ã\'“…&¹¤T  ‹)Zb/_ CüŸ .lüÍ8ú¦÷Ð¥ÛF×k·ZŸa˜&ä9v÷2úž ´x'“ÉøÂ*І‰þþ~¨ªêz$Ðs–ŸCÍE¹ÊS¦³0/¤%p·0(ÇèTîq(F™•ÎÕ+õ6*t.E)§íóí?QηJÃ.—{äƒú½XùÅî‰J®ó ïÛéÐ{}2™ô½3“̘ËýÈs¦žÐ¾´s¹GÏ=÷ÜFW»a<» ×>Ø_âi`|ÜŸ€ä³¦9†²  Ã3Rªª“ŽŒ”ATrÊN$üFªbm¬u9ããŽåƲò»‡‰åçgÐÒ‰8ד Êùž‘££þó‚iÈÐ(’ﺖšóï™`9²<;M ËùÅ×¾†€¤Ó°&'hË–-s–$¯;c±F2y &'7AUcé´g|ëæûÎ0íJÇ_}õU€²ýÏ€«+Ë‹¼Óé4¢Ñ(ÆÇÇÝp§´T*•rCç·#½˜zeo=†© ¿þñ¯!½= 9 ÜüEãB£< †i¯x/“4ò)T=»ó){)J€$IîÞ¢7Ã0Í}5ðö§Ÿ„iYÈ”R”¨ÄE4RV”k€÷ î%ôæRUßùÎwÀ·ïy>žyæwA…{¤w*q7úK!Žèi<:WÜ÷.˜mOQ æ{íÉëúÅ_tÛ*î!äßHÛ]t‘¯ï)D$Åþû Nž<éÛûMÜ÷®œ};•x<îGGGya"ÓRåSœ›þþ5¼÷뛋ߖßTJö7eËG-u ¶íx³{õPUϯÝîѱ”&Ÿ‘-ßg‘Rr_’J_×jÜu.çà·¿ &‡iÂʱS–ƒ¤C:íØú7n|k×þGÄb]H¥œ¡(IŽó(‘ÏðÈkÁ˜N c Ob%ó( _Q>¶m£¿¿ãããe™Lñx²,CQèºîSdˆa3øÅ…aÃÄ;ââÇ_„}åE°mg•’Åà—3†é0Œgp¤Ð^oáp@q³išˆÇãE4E&“ág;ôÖµ€­ÿ´hxËBÔj®Ü·M4,Ѿ`ªªºÆ#2TQ8½x<Ž‘‘„Ãa$ 7L4ž}öYœ}¶ó  … ( ’É$2™ B¡ÆÇÇÑßß‘‘wÏKÑC’ê$úb±B¡FGG‘J¥ð‰O|¡P™LÆ5Ú˜¦éþž}öYÜqǸóÎ;Ýí%b±¢Ñ(FGG‡‘ÉdF122âî'©¯¨Nº®cddÄ=‡"Ï„B!¤R)˜¦‰ééi9r+W®tF£n¿Ñ¾T_êk2xÒö$ïC¡&''±bÅ ÷{"‘p¯‰eY®Qõ›ßü&àÀ¸ûî»ñÍo~ªª"ûò¢ú÷÷÷çíûS§N¹¿%“I÷Z‹yPßS¿¥Ói:tÈ×öX,æöí‡wÉ%—ÔzȵdtÌd2¼ ‘iIh_O¦<>þ6–;Œ·¦E ™œmˆ“åÙñ†™3Ö{Þƒ&°dÅÅã"}ô,]œ!G¿‹kºe¶‡c+І™+kxüÕª~\ñÂRo§yBÞ º®#c||Ü}ÑL$-¶”aÚ•cÏ<… Þ…ø·UH²ì,j ‡Ãy÷å`¦Í ý-”C€´Xrꔫ°§} !˲»óèè(/Z`˜Ã`§Ó)±OÖ|!#"Ÿ‡ŒŽŽâÖ[o…a>ÃŽFGG‘L&¡i,Ëò… N&“®Ç5-v$yE{¶Çb1w7òh“$ Ä]wÝ…M›6!‘H@’$7ô)mù@ûÅÏ…¬7mðoÐ`³`ÁƒœèY¨iTUÅÈȈ¯¿è9@ßi)^ó-[¶àúë¯ÇáÇñ¹Ï}Îm;'''!I’[ÿ|}ôޤ6“'^¡¾D"‡ÃH§ÓX¹r%žy晼}¸cÇŽ*Üõ­mÛ…B°mÛ½Ö ÓŠ°áqnýÍg°tU¬u­…BŽÖhŽÃ0ƒeáç7Ü€u06¶¶íØùMÓqbH&k¯ÆÆŽñ‘Ö!‹â·‡U†iG:Òð¨ë:]y=Þ³émó:ß0 èºîé…„^\#¼¢ˆaššÉ%S¸øð‹ÐõÕœ @<Ÿ2Œa˜ÎÀºÚ1:*üýß—µA×u×Cšöwd¦µˆ?ü0¾’‹ZR –e¹û¹Çãq$ ô÷÷»ûÊkôùرc¸á†ðáx–áþÎ%ükpZjSÐ {õêÕ8yò$–,Yâ ¶¿”¡¥Uå]OO ««Ëí'êÑ»½Ð‚êã`û õý^*w¹Þ¶…ò(ÇÓžÎ]¸pa5»´í £c×›oâ_¿ót_}µ³?šeùÃ,Ú¶.Ų #y‰×È0œ4²ìi!űeÛŽÖÒ¶´ä™$ÞT6…I z/Q7Ñ­B,Ã0¼4¦éϧ¼)-0;œd<îü¥°†´Z°¦éä‰ÌîEñÚ*öÕp~§´Á> ü¨¿óÝóÔ–Rš]Ërê!æAm§k¢ªþ|,Ë £ª³Ë§ãäÒBm öå¡i¥Ã7ª;õ…¸—_‘¾˜¥›2 çXð:28ôéOcÕÀ@£«1ZôÙÌ0Mmã_®Vðg»”å=îàðáÓàòËW¶»ò>Z¢L'Ò‘†Ç#ß>‚³¾qn8kAÙçˆ{`¤Ói÷QÜ+„ë1L `Ç–/ëÏ,ö½÷’RˆW53L‡a– à àôÁ'q÷îÝ-¢ì§Ðy†aÀ4ͪìóÆ0Lc˜Édпf͜ϳ,Ëݯ¼)䨦ie¹ ÇŸÈe—]ÆûÂ2u…ïµâÄsF¶\woÚäü(IùDɤ£EÔuç{*å×*’AŽŒ‡š6Û˜ y†42$å+K–ü‚†"]÷ʧt9¯YŽ!M׿‘ˆß@Iu¤óiC*Ñp˜N;ÇÅ‹+§iþ6ô÷{eSŒ9ñx8ìey¶Ñ-õkg% ÷cµ,' ]‡tçi†áô£È訿Œ½O,6»¢q7èšb^É+z%“ñ8÷ÎO$üy¤ÓÞ=‘L:Ç µƒ6ËdüyŸW±˜ßPœN;ý-̃ âѨó=PeO? ýk0-ë1¦&™ Î?å@NŒ†áˆÎ»ï6ðôã†.„®ûÓ<åb˜5<žXÿvLžê²EeŸ“N§Ý°F‰D‚½¦UÙoÁü¨‚ž»& iÞ»Z:fÃt"eŸ—¡,ø³?CDÓ .$², kÖ¬$IH$ìéÈ0-í¿WN:˲N§a"‘Òé´õDQ×;q.ïsÝW²š4Zv5rÁf£‹6r‘[#ï¹f‡<—3™ «*ðçîÌÎfÐ’äø,xšH;—Ɖ9¥Üq @Nx@Db3€ )䟅ó! ”+7@Ë¥C O9çK¹|ÖÍÕE×Yn°»%ç7²ñ)Ès†Ä€0•›ã}*ðùq`¿ääOmÉÙÞU0ÀErõ¢ãeÒiC\(7ç·$-ãõõ)æ‘Ô„“¾?×¶P.­ ­:u 2¦M ®¸§BpYøˆ,–¼üC^öǼ¹ö‰åGX@‰8ŸuÇ,ï¸ @V%ãÔ‰ÒB_Gr)Ô\—‹ýØ–qê¸ÖžWCöòˆÁ¹_Nš%W·\yУÉ 0©zåêB=@KrÂ9¯ÇVçêa;y­™X~Ž÷{mIØðÈ05á[¼ˆ+'—á‰Õ3P/] Ãp¦¡°lÙ×ñ©O½oVЀ·We  ¯Ýz+ŒÈõøNLçö”LÇÝpk´çG£_V†©€-Ø’Šóž~¸Úû™=¦±,àk`ÞñÎzôiüòþûñ/¢§@I’ܽÏX^0Lëcš&4Ñ{'y6†á[|(n­PÉ{A#ß)m€jtù ä;_ýªö`I€.9F Žá‡ŒŠ*#RRÈ@0.üf#gÌ¥rFË\6£P$—·;.:¬År¿·9•áð’¹zäêeå~£:€,ÿ.W†X_IHƒÀgÀ1°†áÊáÓ–Y&…6š2Mx†òÓð<ƒz8øÂ¥À™üûÀ2 Ãt"o<û®:ôo;–à¼?ùÉ_á•W–ÏŠ®Í0ŒCÇßö•[`þÑ¡œí•Óé4t]‡eY$‰½¦ 0?~- ëèB7ÂíÓÆJ0†é0 € ãÜ%¸V׉DŠÊþþ~örd˜6‚£±m¦i"NömŒŒŒÌ#w†aZÓÄR)\øWåý–„c¸IÀ1€Ñô€ WRî˜ ¿!)Sà³ÈcïD´Ü±<Ã[!G&òþ‹À3¢ÅsuO9OD,?˜~ržv6ÆòœCFÁ(l1oòp…ßp¨åÚ’Ì¥Ö‡ŽÅçª?à³CÎJ/Öp®­šçœDÏ…Ú—ï‘{+`K>ã|·„s)/1:,E7›F{öwsÝ!yç’s\pK2`ÿ! ŸÕ-0ý] |Ž!íðì>²—:ý£¬÷ÎU(¿?p‚UXQϹ“¨Êè–óµæœ‘wþ|Ïõñk@ÆÖÀïÿÀÝN¿T‹±înœ\¼¸z2 ô2é4&T×þd À×yáOÿt ±Øb(Š·Š„Õ 3›Ž3<š›~×îŸÞ×U ‰P(MÓL&]Ã#Ã0íõ°Â:†ø—³¡ªË`Û6 Ãàý¦ɘ0¢ŸEÿÁ_Á”¤Y y2@¨ªŠP(„L&Ãs†icLÓD?ÆÇÇózBV‹FÊ‘F˰Nß×Ò0ŒÊ3šªª"™LVžQ›Òuï½8rå•€$!~ 0lÀÌc=$Ûk+@±«ìì¾àRÿo&\Çkq}ù­Ì(€ÂùWX`ñlã`¾¼ÌbŸßàòÚèÌ Êèðeþ—¿.æ•yêµ ÀXž¿mÕDtd :µŠÐ6žJžóÍÇæŠõÀšñœZ]nÈý¯"S—\‚îîêfÊÔ Úƒ:ߢ"Ó4!Ë2,ËâèN 3OìÔ?ÁÖ4|üÒKð¾ ’Ià‡?ü{¤ÓiŒæY¸Ì0ŒGgeVƒK­©‚†GÀy1‹Åb%C®1 Óz<°ù%<ûàó¸1¼33ž·#u†é@.Wa|ôRÈßߛד‘<‰‰„ONX–ó¿Z+mÛù8á[LÓÙ'‚~WÕ\dXŠâ”-:ÎH’óß²¼4A§"Yöò ¦'Z©ñ¼BåˆçåËC’à®\¥ò‹•Cv‹ù”3—öÔ³œW^a#à(èLÓD&“ñ¨lÛÒý]ÈqîGÛvú>ßý==}†áåSêþ&¹L#Þ匣‡^@ÅÁƒ—ºå×ë¾3M`rrË•¡ô»ªúûÌ‹Já|6M¯ï)Ì•hG¤ß‚X–W·_\Rô ² Q¨Œ¹¦i$<ßÍ…¿þ5V;†}7ß‚ø)@ZIJ€rP.¯aÁ—À1æã]sÈ'˜va.ïªtüûB–â<]e¦½$W×¹¶¿Zm+`Mîó8æçQIÞ¡•Ž:@ú(9¿öíÎŽ!{äHí j1Èx'~—$ ét²,Ã0 (ŠI’Ücº®#‘H bddÑh‰Dñxš¦!N»CÚs:cdd¡P333X°`2™ B¡b±LÓ„¢(>ƒ£®ëî9£££èïïwÏÉd2H&“®á‘Ú`Y‰t]‡,ËH&“nÝÄ¿²,#"‰ ™L"‰@×u7J‰D\C§Ø_étÚM.übÆ0íÇyÿò8Þñúj\•3ÐÄ‹a˜ÎÃúJ ÖÅÀd"=ç ’6Œæ™gðæ›Û±` ªÅYá(22èºó9‘âqÏ 8Êtñ¼L…üyÄbN™†1;=à(±ÇǼ%É+GTÒ«ª“.™tþRÀS¤kš£§sdÙi¯ˆXv"áï:.ž—HÌî“rÊQÕ¹—úúb9ªê´“ÒSߌŽzýÉá°ß€ìïÑQ§ßĺd2ÎqÃp®à\sÑÐBy+ŠS×PÈ3ŒP?hšwÝòÝ™ŒS†®´­¸Ø·”·xP½è8õ¥qÒPPuÝù‹=t~û·ß@§bNßÜqÇ›X¼x®»î:ß=3×ñ 33ÀŠ^âu€+>‡Å‹×•]ަyã[dr2ÿýM÷e$â܆áü62 ¯‚i¾ ?ü¡wˆ÷w°±~ùêJý@}IiDd&ãÜ—?œÄòå2t}îåÄbν¬ëN™šæÈ…Byˆ}èð>£X´è,ð®Õ‚³Ë)uÇÇ59«=ŠÉþñq§í ®uËK$œsèK’“ƒ)ïpØ9–Jym£ë‹y÷†¦9ç’,û>Û`FGÆE>Ñ4 kÖ¬ÁÈȈÏh‰x›cJ’äÞlÛ†ªªP²,»º2LÆb1Ȳì~ÃpŒŒ@Qd2Îæœ333œÐðâ‚iÑJùSÚà_Z\IFFj[8v=¶TU…$IPU²,»FÎþþ~hšY–¡ª*TUuÃ¥Û¡iš«CëIù‰çÐ_j¥×uÝÍ‹úÕ¶mß9Á¿TgêÃBçPÝƒå‹Æbºf¥ê<ŸvÖòº~„h|¤kOÆm‚®S„{Mè‘8–¦÷ÃÄopæ]?þñ¢ÑhͶd`˜vbÁ =Ú˜¡¡! àò‹°b50ü“q„?°Æ—&cãÆ­xùåsqÓM7¸/jâª}úÞÌ«X¦vìØ½{÷6º i÷Ÿú#¼þôüè“ý$  !•J5<üÃÔ›l6‹l6‹ÁÁÁFW¥®Ðœ```úÀ®~ý³§ðѾÏU"«*°bÅ1;ö\pÁB|ìcŸõyÆ)å¹×à-Õ¦(â˜è$vìØE‹ö"-zï}ïB|êSëÝq\Ë}ZB9ë)ë‰a®D#ö¬KÛÉ[±Zz±¹´½šeS^ªê( M3 ÃðÞ)EO˹z›Š^ªù1r !•Ê”(GB$sÛlö<_{Ä~+·=T÷Z—S¯ö”*‡>Óy ò4 /ܼ¢xÛoPtE)\é|)Qï˜H8ç‘.7öô†´`‰Œ‹Wâݼ„·-¼Ϲºs§e™£¦1L9tŒáqÙÓOãÉ Ï ûþ‡°ûøÛqði[Þ+!’ÉH$¾P ““Þ¹ÂÏ>2o&QÑ|`’Ñ1ñ I4) ßÅÉ@ÐPDùGâd‡ŽY–3a!o G =M!ÍÈ(BÆ?ª·xܶsŤØöxÜŸ'}'h"$†‹Ë¢4ÁkùB‰¡ÙÈ0I¡ÇÄúˆ«ˆk".™t—Q{ÅpµS§iN;ÉèkY@¿~)xî #yç+çâ ºkŸáoŽÜ‹Ç?õ8¾vñ×p.‚ ò¼é0 Ór|-ŽÞý?°ð 2"ïY … ª*FGGÝ}W†iOX³f R©T]ÃM)Šâ*.êßæÆÊµ`ø¯zÂ!Ř|Èçh– X†÷nIŠez¯¥ïô~'.&¦÷9q±i¾w>QOñ}˜ýÞ&ž̃êAç9çËC|Ϭv9¤À¶íæ¯k³–\Ô^­rÊ]ÿÓŸ®ÂyçuføÀõëOà²ËîD6û2¢Á8Þó5Ê”zUbì!=bÐ J{)· Õª+郿åû4ЊÑÈøyùƱX®¸ÅA¡r€ÙòðëÅô¤¤°ö¦é¤)Vޏx0•-Æ«}ZëE`¹y3羃kágc¿À7<€÷¾÷½ˆÃÂ*œ‰‚¯`bjõÆ—_Æ»ÿÛÇñÚÑϲ'Q—O.‡ +h#–<(P`æm(uo¤Y Ûv&tä©gΡ«FlÛóĤG*U¿+ñ¸cèÌdœ™®;Ƹz”O{ÅÑ•^ ŽkÑötÚÛ[«¿ßoˆ¬%†á\÷‘o2D‘|tjØ„¯}ð³Øõ¯¿ „å“ËÑ{¦¿qáoÀÌý+† $X° B… &LW&ȹ4é`˜f§ÓC)ø§4þß›‡ð§{¿ëþx@±ìÎîÆ¦M›pÅEW¸ã î|@‚ä;– Žb]† 6,XîgvéŠ2Lxî¹çðCßèÈP«Ÿ¿õóøËûþ—|üX°`îË8}öÙg1==M›65¤í†a`Ó¦ME߸ííÕö3gÎàþûï/Úö×n û?»¿îuk$Ùlÿú¯ã—>‚¼n`ù& Ë—×]> LM«œ)ž{8µÄÆâ“ŽRñª«€ï¿ø $kÞýî7ñ‹_œAww7Æ—ÿoûRœ:5‰žžn,yâB,[¶ o½5‰Ã‡—£«k^yåMtwwxïxÇ84Žuï}ÿÞ)\tÑåxå•CX±âíxë­WpÎ9§púôz,]ú€§pâÄ2œsN7NŸžBoï;ñÄûñž÷¼?ûÙÖ¯ßËú.¸ „—^zgŸ½ gŸ}ÝÝ6€œ8q½½ïÄãÿW^y {ì1¬_¿<‹}èxôѱté2‡qâÄ2,]ºÌ=‡ÊùÉOžÁÕW_Ž'Ÿü1.¹Dűc¿Â9çtcjêu,]ú*Ž]ƒ%K^¦M ã(.»ìŒ›¸æškÜ<~ØFOpò¤Ó§»×ãío—ñì³ßÅWl…e=Œ÷¿¿Ùì#X»öZ<ðÀA¬Y³§OOáõןDž^…'ŽcãÆ‹ð£=Ë/¿÷Ýw>ô¡á±ÇÃ5×\ŠÇ{çw1Î>ûNœX†S§–`zz6\ Ëú–-û ž|ò|ô£}øþ÷ÇpùåïÅóÏ?„îîõxã7pî¹Ïâmo[‰cÇŽá=ïy'¾ÿýýøÐ‡>„‡ú%.ºh#Ž5Ð×÷~<ñÄk¸à‚I;ö"–,‘qâĹ€Ë.;<ò¼ë][ðØów£ï·/ÂS?ŸÂåç|Ï»ý{þù¿ÆÉ“ëqâÄq¬_>x 6\‰§žz}xôÑA(B6kã »ðâ‹OᬳœýNœ8Ž¥K—áøñŸâïü8&&žÇæÍ—ã®»~‚5k8gº»»ñúë¯cÅŠS8~¼ gõÖ¾Ú8ŒË/ߌ'Ÿ|«ÿÃB<ø0ÖŸø¶L¬ÃÿúÃ/5zxÖ•¡¡!¼qýHËi„…“9¼(ÓÙtªÎPl÷ú'ÞÂøwˆkþ}?¿òÿ\zðR\½új×`Á‚ Ó}÷Ÿ¤cP¡Â†íêé· ¤‹æ!åþ)ì¯ÏT‰Ž µ:44„ááaLOOcóæÍDoooÉó~uj)^ëú]¬~ Ëürâ—Ø¿?N]| K?°´àÀ4` 44h Á„ép&lؾ•°|¹„½ŸDz3d"iô#ZÓÁïæ-‰Q²¥º^_»8Ž“°ë²òbñŸKQceÇèºá³&t9]yÆepê3€¥kˆÇD"Ž!ðü?Ó+z̵í©ÜÞ-² üíƒ&ÒJui½ lýŸtݹ4 IÄ (Íþíú«KŸÔŠùÊï) €$¶ý8ÿ¿‹H$åBo\ÒÞÊý!…¤i¤aÁòizIãe>hBQ¯ÕQ¢B•Œ©ÔvªO>D#k>Ȩ´‡VÂ%c—4º1_Y°ø…p[èxëé8þâ‡ðO4.$¸Á'¢  ñYhŒSz#4¾ñ€^Èp):ò½DPQVˆãµ˜Ü0`¸éĺó F$ýPXÙèZÌŸùÊغo+^ú÷/áÓøô¬1—⢃Jùú}_Ç3Ï<ƒØ¦Æ(6¤mÉmØ´¢þ°bm§÷¬ ¬1ô€»¨ƒænt½H~“†~— 5mÛKTDÑs…æ¬ÅM,X -ÜoÜm+ò·Ý„‰½ô£º÷I5©Düà¯×à}'U,Yâ<3;†—ãþûïÇâÅëpÿý÷㪫®Âc=†žžœ:u ÷Þ{ ½==xê×ÿEù8Μ¹}}×áèý/ãºë®Àý÷DÿEWã鳟Æ9çtÞõ®#X¾|9Î;ïV¯^„Ç;Y>ƒW_µ±náU8uÙc¸êª38xð5,_¾ÇŽÍ`ñân<öØ>tw÷ »»kÖ8y;6ƒõë—àôéóqþù ñÞ÷ö`õêÅèéÙ„žž…8vìíX¼xNZ`/^ŒS§–bùò%¤µèéYIZžžÅèé9\Ð…k¯}ËM pÎôôœ‹ßú­‹sçnBOÏ";va.Ý)]X¼8uª Ë—Ÿ‹Í›O §g)Ö¬¡òœ<–-{3wN—PÎ),_¾—^z=zzáï\žžsñ¬EOÏb¬^Ý“Kw.€K„ºuáúëW£§§^ø¡]çã¼óÎÎ¥[,”Ó…åË©ŸÎÁ»ß½==çcÛ¶uèé9ÇŽ])´‡>¯Àòå˱må¿ ==çàða==ÝXµj‹¯Á©S+íYŒžžôô,ÁúÃïGÔƒ ›£§ç,;&åÒ-à}^¾|9V¯vÒôõžž¸è¢ôôœ‹U«žÀUW]€S§Öcñb§M§N-ÄâÅ‹qìØzzÎÂáÃK°z5ð±½ÓÉã°‚åË—ãÔ©SÂ9ÎçU«Våú «W¯ÆÁ³ÏÃÌÌ[8ç¥ÓÎ ‘ÿºç_ñÚG^CòãI$‘ÌëtÀï»L§Ð©:C¾ÿ~<}Ý=ÀIŒNÈøÖ“ßÂÛ QÈ»£P>9l¾wqqn[N>…ÒÚ°E´¬E“d ê !Tð\QçAŹx£ 9~)ÝÿF êNL˜®mGÔ“¶ 1Ä ¶É‚zÞcÕж”Ç# CCC€;ï¼³äyÿ|õ!<üÛaýÚ»޵+V̯Z ,X# 2"ˆÀ„‰$’ˆ R¶¢/ŸÑƒ*ókÀÀœM& С#‚ú¸ýéÐ]o°|ßk‰ §Ÿ”1p{ ‘ðÕïXH}a b¨R‡ú™„MVëÑvºîtŸ‰×”8¤4W à?ø~ù‘_Ö¥_ªÍ|å¨;?Ÿ|å>ü—ïþV[Q÷ÒÉ€P Hfä3^‚Š=­‘C‡á’\‚¯ìüJ£«2/*™lùÕløß?—Ç.øGH¦„t: UUËÚÓ‘aÚ ònEÇJæ;vìÀúõë¡iZÝ÷zÖu–eÍYyQ-B¡‰DC®6CÛµ¿·®ë°m»îóO±í™L¦àñVön˜¯,Wr›¦‰d2 MÓ‡‘ÉdN§‰D`Y$I‚,˼7<ÓÖ´zD”JÞ®¼òJ\{íµ€ä h_­££ÔKá]ja1㇮Q¹h1’]Sú h~ãÆOoÿiËFA¨ôý`ïÞ½øïÜ„áOÜŒ?ùæ~{U/½ô Ã@*•jtóæMq0 Ú&ÈéªV‹”óOE#lpñvb¶À¿àdC²¼˜Ñ•‡·•´½:ÖòxÜ·o¶mÛ†mÛ¶n»í6¨ªŠ}ûöaóæÍEÏ}â²³!=ôdÆF`YFFFj¢\”!#…âˆ# '8· TörÍfÑÛÛ‹ÞÞ^hЊ¦"ê– )¤JžS-4h}üb¹011‰‰‰š)¶ ]Â÷ H°ü :(÷}ááa÷ ¶]ô~U ¸àzGÜ24ƒLÁ‰ä‘ôà#u«ZU©Dô¾q.^?ÿ(’Ç’ QTcb_èþ+F³y7‰ò¬U©µ<«Ùç²ÈNe]yS‰,øÌ¿ÿ5ð–‰/}÷/`å(%Ij£c;ÜÀüäY³Ñmhe*‘fªöÂÇr!ÙQÌøÔŽmÇi§´=ßs¢‘m¯5•Ê‚x<UU!Ë2TUÅøø¸ûhüÞ¨Õ¦Ÿ]í2wš+v­+‘çž{®»0½?7Û{tµé´ûh]Ä|˜ëµÞqßà³®õü¨D9rö£?ÆÈ‹ÄÐgþÄu\j£c¡kMºy2 “— }®†í¢åÚ&ª=NmØH"9Ëø/üá7º*ó¢Ò9ÁÃ÷ÿžßká[þ0>ðàæ›ont“æD«ßD;ȳVnÃñãÇñÜsÏáõ×_Ç–-[]9Séœà¥—^µ×^‹eË–aÕªUnN]hÙ1WZyœÎ—¹\ëçž{ÇÇ;ÞñŽFW{^T" º»»ñÝï~‹-B"‘À²eËÝœºÀc¢s˜Ëµîô÷ƒÿüŸÿ3Î:ë,ôõõ5º)u£eA;è"æC¹×ºÓu†gΜÁÌÉkð®ßéÆ?ž¹‹\„#GŽàÛßþv£›V6í0®Ûaœ¶ú¼ã¹çžƒmÛX¿~}Eù´Œá±¾üå/ãË_þr£«Á0LƒùéOÚè*0 Ó`xNÀ0 Ü}÷Ý®Ã0 ¦¯¯>úh£«Á0Lƒá÷†aà‘Gq>ÜÑèš0L{ð¶FW€a†a†a†a†a†a†a˜Ö§å ù\T;)Ã0,†q`YÀ0 ˆa– Ã8°,`†åÃ4-cx¤øÌðýžÍf;nS`†éTX0 °,`†åÃ0, †X0 Ãr€aš–1<À¶mÛ0<<ŒééiÀž={ÐÕÕ…-[¶4ºj ÃÔ – Ã, †a9À0ŒË†a– ð`˜fbÁÌÌÌL£+Q.ÓÓÓØ¾};¦§§ÑÕÕ…‰‰ bÛ¶m®Ã0u‚åÃ0ˆaX0 ãÀ²€a€eÃ0,¦™h)Ã#‘Íf6l@WWW£«Ã0L`9À0 À²€a– Ã8°,``YÀ0 ˆiZÒðÈ0 Ã0 Ã0 Ã0 Ã0 Ã0 Ã0LsÑR{<2 Ã0 Ã0 Ã0 Ã0 Ã0 Ã0 Óœ°á‘a†a†a†a†a†a†a˜ŠaÃ#Ã0 Ã0 Ã0 Ã0 Ã0 Ã0 Ã0ÆG†a†a†a†a†a†a†a*† dzz7Ýt®¹æ¬[·ªªbß¾}³Ò ¹ivíÚ…‰‰‰9¯g{®¹æd³Ù9·¡ÑíØ·oTU­è:4º LëRŽ,h¥û¯,h…6TC4º LkR­9A¹iêÑžV¥eA+´iOê9ghÆ{¸Ö²¥ÙÚ\/YÔlífŠSÏ9C³Þ•È‚VõÒU4S›™ò¨§N±ïžtε®5­Ôæ­[·¶ä;v;è=§§§±k×.¬[·ëÖ­ÃÖ­[1666ç:6ËýVÍ Ó0¶oß>Óßß?sÏ=÷Ììß¿æ–[n™Y»víÌ=÷Ü㦹å–[fúûûgî¸ãŽ™ýû÷ÏÜxã37ÞxcÙÇëÝžµk×Îìß¿ß÷{9uld;î¹çž™µk×Îèº>³ÿþ™/~ñ‹3k×®yþùç[¦ LkSJ´Úý—O´Bª! ݦu©Æœ Ü4õjO+Î ffJË‚VhÓ¾ÔkÎЬ÷p-eK³µ¹^²¨ÙÚÍ”¦^s†f¾7æ+ ZmLÔKWÑLmfʧ^:Åf½?xNP}]E³µ»´R›u]oÙwìvÐ{Ryû÷ïŸÙ¿ÿÌç?ÿù™þþþ™©©©²ëØè6¯I­ï'6<6ˆ©©©Y‚™ç&þüç?ï~ÿà?8sË-·¸ßŸþyßy¥Ž× ]×gn¼ñƼ7l9uld;n¼ñF_Ù3333Ÿÿüçgî¸ãŽ–iÓº”# Zéþ+$ Z¡ ÕnÓšTkNPnšZÓÊs‚™™Ò² ÚÀ´'õœ34ã=\kÙÒlm®—,j¶v3ũ眡YïJdA«‰zé*š©ÍLyÔS§ØŒ÷Ï j£«h¶v׃VhówÜ1³víZ÷«½c·ƒÞóÀ3k×®9pà@ÑvµŠl©—ΆC­6ˆ‰‰  ¯¯Ï÷û† 0== sÓ½½½èëëÃJ¯cccÐu7ß|sÞc¥êØÈvLLL`llÌW6ÜvÛmضm[K´imJÉ‚Vºÿ É‚VhC5dA£ÛÀ´.Õ˜”›¦Ö´òœ(- Z¡ LûR¯9C3Þõ–-ÍÖæzÉ¢fk7SšzÍšõÞ¨D´Ú˜¨—®¢™ÚÌ”O½tŠÍxðœÀ¡ÚºŠfkw=h•6 `ï޽ػwï¼ÚÐèv¶ƒÞ³«« ;wîœÕ‘V‘-õÔÙœ]·V1>úúúf ŒééiÜsÏ=îƒcjj f=\º»»}BÇëÁôô4¾øÅ/"‰ä|¥ÚPnšZAñ‡{{{qÓM7abb½½½Ø¶m›ÛžfoÓÚ”’­rÿ“­Ð†jÈ‚fÉLkR9A¹ijI«Ï €Ò² ÚÀ´/õš34Û=\ÙÒlÏðzÉ¢f»ÖLiê5gh¶1Aí¬D”Ó¦fõÒU4ãµfJS/b3 j#Ï j£«h¶k]Z¥Í½½½èííwÝÎvÐ{öööbpp€cx›ššÂðð0úúúÜ:µ‚l©·Î†=›„}ûöaëÖ­èííE$ituÊF×utwwcçήJElݺ]]]èëëÃÄĶoßÞT¦s`YÐXX0ÍËÆÃ²€iZUVÌ•v’-s…eSŠN‘@çÊ–L9tŠ,èT9°,`Ú‡V—WCCCرcöíÛ‡-[¶ «««ÑU*›zËPöxl0¸é¦›Íf±sçND"‘–¹a³Ù,†‡‡qçw6º*‰D|ƒNUU c÷îÝ®Ó!°,hX0„å@óPHlÞ¼¹ÑUc˜––s¥ÝdË\aYÄ¢“äÐÙ²€ßO˜bt’,èd9°,`ZŸv‘Wä½™Íf±cÇtuu¹žæÍL#d({<6±±1wÅŠaÌ;àò­`ÝaK¯ÙlÝÝݸ馛°cÇìØ±€gùŸKÙ³ÄæÍ›Ýp­Ò¦u)G4óýW®,hæ6ÕnÓšTkNPnšjÓNs ´,h…60íI=ç Íp×[¶4C›Eê%‹š­ÝLqê9gh–{£š² ÕÆD½tÍÔf¦<ê©Sl†ûƒçõÑU4[»ëA;´¹Ù¯m«ë=i¯U‘ ›ÍΩŽÍ®»-·Žå¤aÃcÙµk¶lÙ‚Ûn»-o¬fŠ•ܘ3›Í¢···äñZ³mÛ6ìÞ½;wîtÿÀ–-[ÜÏåÔ±‘íØ°aC޲Ňw³·i}ŠÉ‚V¸ÿJÉ‚VhC5dA£ÛÀ´6•Î ÊMS+ÚaN”–­Ð¦½©Çœ¡™îázÉ–fj3P?YÔlífÊ£s†f»7ª! ZmLÔKWÑLmfæF=tŠÍt𜠶ºŠfkw=h‡6·Êµmu½ç¾}û°}ûö¢iš]¶4BgÆÇ‘Íf111áZÆÅÿ¢ÅxÛ¶mÆôô4`Ïž=èêê–-[Ê:^KhЈÿø6V-·ŽjGWW044ä–Íf±oß>_£fnÓÚ”# šýþ+G4{ª% X0ó¡Zs‚rÓÔ‚v˜åÉ‚foÓ¾ÔsÎÐ,÷p=eK³´¨¯,j¦v3¥©çœ¡™îjÉ‚VõÔU4K›™ò©§N±YîžÔ^WÑLí®íÐæf¿¶í ÷ܼy3¦§§±gÏ_»²ÙlÕç!µ¢:›33335o3‹¡¡!ßÍ*200àÆ žžžÆöíÛ1==®®.LLL`ppÐu±/u¼Þ¬[·{÷îõݰåÔ±‘혘˜À®]»066†¾¾>ŒaçÎl™60­K9² ï¿ ,h…6TC4º LkR­9A¹iêE+Î €Ò² ÚÀ´'õœ34ó=\+ÙÒlm®—,j¶v3ũ眡ÙïùÈ‚VõÒU4S›™ò¨§N±™ïžTWWÑlí®­ÖæV|Çn½çðð0nºé&tuu¡»»-¯3¬õýĆÇâoذ!oÌöRÇ›rêØÈvPÙ½½½]œ›½ L{Ó÷_+´¡² Ñm`Ú›VGíІR² ÚÀt.Õº?[í®F›š­Íõ’EÍÖn¦:´ã˜¨F»[mLÔKWÑLmfªK»‰j´¹ZýÒˆ6ÕZWÑlí®íÐæv¸¶ÍÞ†‰‰ 7Ìq»ë «q-ØðÈ0 Ã0 Ã0 Ã0 Ã0 Ã0 Ã0LÅð Ã0 Ã0 Ã0 Ã0 Ã0 Ã0 ÃT †a†a†a†a†a†a†©6<2 Ã0 Ã0 Ã0 Ã0 Ã0 Ã0 S1lxd†a†a†a†a†a†a¦bØðÈt4ÙlÓÓÓ®Ã0M˦•áû—a†e!Ãt<æ™N€ïs†a˜êÁ2µ¶°á‘©cccرcÖ­[‡uëÖaÇŽM?xwìØ4º ÓR cÇŽyµ¢È˦•iäý;44„uëÖ5º †ibŠÍ#€êÍ%X2LëPqÏcžéÚé=µ•uõšË0 S[ÚI¦6#lxdªÂÄĶoߎ®®.ìÝ»·Ýv8€]»v5ºj ÃT‘ééi ç=Ær€a:›l6‹={ö4º Ã41Åæ@{Ì%X2ÌÜhõqÏcžaæN+ûN˜Ë0 ÃTƒ³]¦=سgº»»qóÍ7£««Ëý}×®]C___£«È0LŒahhÙl0000+ ˆé\¦§§±k×.ôööbbb¢ÑÕa¦É(g´þ\‚e!ÃÌV÷<æf~´â¸ï”¹ Ã0Lµ`Ç6ahhÃÃÃÂ5×\ƒuëÖa×®]˜žžöýV+÷þááalÞ¼Ù÷Pݼy3ž~úißC• [DmÙ³gTUźuë°uëVŒÕ¼Ë©Ã4 õ+]]]èëëÃÎ;ÑÛÛ›7M-ä@£dZ– L+Sû÷‹_ü"6l؀͛7Ï»÷œ0L1æ;6J»f›GåÏ%æC3ÈB†©&åŒárå@#çܵ÷<æ™N xŸ·Âœ¨Þ¸ï´¹ ÃÔƒF˶ ´lxlhåÍÄÄn»í6 bß¾}øà?èû-›Íbhh¨êeÎjŸ‰‰ ìÙ³{öìÉ»âojj Ùl¶èjÀ±±1 #›Íb÷îݸí¶ÛÛ·o¯ynß¾½½½Ø¶m[MËb˜jPϱÒÛÛ‹ÁÁA æd×B4J¦å« ˦U©Çý»gÏd³YW壯}£æ SŠùŽRã®™æT ¼¹Ä|ú°d!ÃT“rÆp9r ÑÏ^ úãžÇ<Ó ä»Ï[eÎ TgÜwÒ\†aêE3ȶ ´jµèííuãÀÀî¹çLOOû~+5™SSS€}ûöaxx½½½˜ššÂÐÐvïÞí¬xúé§Kæ9==o|ã³Âd³Ù‚á *„Ë–-[°{÷îªçÏ0µ¢Þc¥µ’i",˜V¦÷ïÄÄt]ŸJ(H«Œûf‘© d>c£œq×L÷ü\æs¡™d!ÃT›Rc¸9ÐÈgo-Æ=y¦(tŸ·Âœ»Úã¾æ2 So:í½œuµ mDpàuww£»»»ìó³Ù,vìØQ4M± Ì=÷܃;ï¼Ó pÓM7ᦛnÂÀÀ@Ñ0…Ú" —b“ùJë=66]×1==ÁÁÁ9Õ“aM=ÇJ9T[ˆÔ[¦±l`Z™¹Ü¿•Œ•]»vaË–-U 1Öèq?™Ê0õ¤Ò±Q,ßfšGÕK´ª,d˜r©Æs«ò¥Yt <æ™N ï©í4îÛ}.Ã0 •ÞËY÷×¼°á‘qÙ°aöîÝ;ïó#‘ˆ/^ùàà †‡‡1<<<ç;—¦Jë=44„;wbÏž=Ðu… ÓRÔs¬”C5å@¥°l`:™¹Ü¿ó+6(‰ ›Í€»ÇC6›EwwwÝ÷1©tܳ¡‘é4šmTw.Ñ©²éšå¹Õ,ºóL'Ð,ï©Í2îÛ}.Ã0­H=ßËY÷×¼°á‘qéêêš—»2­xN®ëõ4ßzƒƒƒØ¹s'ç%‚BÒ0L»QéX)F£å@-Ú˲ieærÿÎw¬LMMazz»víšulÇŽ¨Ë‹}5ÚÂ0Lij=¾j1—èTYÈ0õ¦Yt <æ™N YÞS›eÜףέÐ6†i&êù^κ¿æ… ŒË|]“ûúúÐÕÕ5+Î2Åy®F¨ZÔ[¬?à¬HÚ·o†††pçwÖ´Î ÓjV¤Ñr íeÙÀ´2s¹ç;Vg­ž={ª¢h>Ô+|Ãt"µ_µ˜Ktª,d˜zÓ,ºóL'Ð,ï©Í2îëQçriF½Ã4‚z¾—³î¯yaÃ#ãR‰kò¶mÛ0<<ì®  €]]]¾Í“ÇÆÆ044„Í›7WmSåj…JèêêÂîÝ»±cÇ ±k5ÓvÔ:¬H#å@-Û˲ieʹër¨ÕÆ=ôÕwõ_åÎ%†‡‡±oß> –Ò°Yd!ÃÔ›VxþÖbÜó˜g:|÷y½Æ> stream xœÜ½K¯6»‘¥7ׯØCi Ý¼“95`7`°Ý§fF¡\—Xj«Ë(øï›±VDäÞß9:’eØhôEßæa2“ùf2ùÄZ þ×òY?Šüüï?þñ7õCþÏ¿þçßÈßu·S>žRÊÇ¿þóoþå‡es—ÏÖÏÇ:OýÜó㿹íÏZ½ä^çŒÞïŸÿò­J„*ߎ˜ÿ×oîeŽç)íãû?þÿÿÁ…xÉSžÏGÚùéÝðÓŸu|ž¦Ujíç³ä‹ó’ÔËÐPü™Úe~î|E^’Bò?£¡Övÿœ3ß.–¤†X††âÏhHî×yÚúøþû“ÿ×ßT}>ð?ÿøÇÿîï~óïþÃþ¨ããïþå7öÔÙ?‹Þ×µ?×Z÷ÇßüÇß–ßý¾=í|ÖßÎßý¾ÎÏÑΑÂôÏVîÝ~úoëÏUÈÿÜg~¶êu÷ãíÞ–/ÿ<ŸíÌÿôwÿãoþû¿ûÍÿú£'áœÏ¾ŸôHþôÃgpÏg¿j±­ÝVûl#µÅ’ÜVÔb[¹–·µzûܯ¶PòjËky[©–?¸¥ôûÔKr[Q‹måZÞV¿OÌn¹-”¼ÚòZÞVªõkŸ¡Ñ>KŸò‹ôÏuï5Ÿ!û-—ü–¿?}–ñ´¿û§û_õ¥bA½eõÆŸ«‡öÖŸ©wŽÕ;?WO¶ÿøQ—té?Ýÿ÷O¿j4ü6}û~ú…¡Ì«üÙôŠÛù1䇸½ü"÷½Õ_c×ó¹û¶_ãßßÎ~¶ûÒþöø][Ÿó´óÛÿé¾ÅçsÔ9~û?ûþ_~Wï@0îËø“ÿëßýî6Õæs~û·Þó9N™¿ý?~×o;õY¿ý×ßݬ­:ûÏ¿ûýÓ?û,ñþÚåþò€Ô_Óú~ûO^=ŒŠÿæÿú‡”ýo÷ç«òÞ×ôüÚ“{ä«÷S¿¥Ïýyž®a”e%ú5™Ïþ”wÉJÎ-YåþºüÞ=”Ü'méAí³ÊA«;‚¡¤U)éý¶w¬¤/)¹cÃS‡•Ì-%³Ù_[]õ³-¹"×};ê:V¢§¹×ßæ°‚ªÊˆÖ—• -‘ëohfJÃ[®¿à¨Gz´ïõë õ ,÷½~yÒ´dÊõï{ý{+ÑÛ°ïõŸ¡ÍÌ{¥dÞûÑ–• ¹â-}¨zò%/í-¹}(ϰíõ¾¨Ç Žžüö¡ÙíÜŸZãþoÇ ¦œéÜ.Œ®­ëæ‘.Ôe%S®ïHŠžûAÉíýAV²äTçöáþîwzQìg:· Ç&å>ˆR²äc®s™j×w¤ ÷6Ý’&s!)¹](O®sûPJuû.ʵ7;׸×~KžÛ ý6h‰tô‘kèÙ§ýžÏíÄlzÔí±üzt¢êÙoƒZr;±žÇJŠ–Ü^ì£g?6mzn/îØa%ÛJîŒjÈQµ|Ê>·wt”‚zgKR"hÕªhGéDéVgJZî…5mÆžÉZn'úηò.܇Ý·Zn䱕’³´Dú í.;w-Ò=÷ý͵àvaë‰Î}6­ä‘Gñ–<Ÿv̾Ý]V°«–Ü.éS+2Û”’Û½}í¾™Úp•4)éöÔÖ*]‚aoL­÷_ú È3e%· Czy?ÝJnôÉiÚ£z¯IÛcO~­Ò9O/rZr;P­dYÉíÁ‘Nöz??Zr?wœúNŠô!©õö@†(yô½«­è]“qÓnôí÷õzštAÏuïˆÞ‰&]‚ýiß =ÓU¬äöaJ'G±‡¸¶Û‡%U¦DZòȵä)´*Ò…fKop“.HA·—¬¶ûªë;&np¿=(z¦Ã’ª¯À-¹ŸZ=êŽÔrë™÷iÔ»ÕíhÉcGÉUT;JÇÌÚoô1¿Í¡w«ß>ÈHöÌi/Ç-ytü~æ°—¬öÛ‰=í^Ø“$ÓŽ#ý”Bïh—^4ëÅÒýrÑzÇN%*¨óóÁW¨n*µÎ´éCÝw¸z&ŽÒ‚®ó„%¹=³ò‰–¯ïó<’ò‰ÖVÝ·wøÞ¥¼­wú%ÏÝ-yð*î­Ù[rx}· w·NÙÕÜ.è~ï–uóH.ß•Vчsû°k§h;çöáŽà·Ž ¸RpG¹GN%ﺞ\>Ñ…wToº|£«ÜÑ;F>Ú ùFß'è–¼hG:!{ÎÖŸU/ØFŠsô¹%CÞb)yô¹­<ø2ÈgxI7ï|^oŸ|°¶žhÚ”¢ÊGãH/-."%· GNÕ¼,Ê:%ƒHYvu¾På]åTc霧Ê÷¹u»Yöø=Ò‡j:vréƒù:IÁíÂ3Ý‘B—&ÏË”nÞ‘b-¹}XÚÍaÃ|»“ÂoeÏÖýÄ7yû·|„ÏÐéÃ-¸ºaUlÌÕƒªÜ9“¼ÍJÂoÉ ¶–Ü.4¹â;Ú•©%· ݜְôAŸ›bÝlw. Ãò–ëÔ¡£Ý­Üÿ{òmÏh»_3yánË[n’”HaâZ¡³³]6b÷+YäÇ×’n%—rï‰xÁò….r¢Ýäg–’Û…*ݼ£Ö²fošÞP¼óíþx2„ß:w®¡ÝlÒ9‘ÌÏ­¤êÌú–TiOJšNÐoI±;Úº>ò·`Øûr¿áú.Ý^–Üœa/C³†§†Ê¶L©tŠÖä]äT÷èf%Ò iÐä]õ†NûÄ4ùF79Õýœél¥uz¤ŸcãfõªSÙ-sªÇJ¤ÒÏŸª;ɸ‚eãsëCoœ>[¨rû°·5lOäË~oà´±Ãb0¸¥ÖùD—†»c%ˆ(UyÏ,Nó…©áÿ2œ‘9p}å@8¾9P®ûÅF†Î™^¨Ãâ‹õxq Îõ!Mˆ§2q`³§)`³LÁf/VAùE^Øì.666Xv»ü„`ЄÝ~‡„ݾ® »}“‰©—ØmO8ôI8ì!MîJ8 A‰R Í’¿ýN‚¶úº:JÉ›µŽ')ÐÙ)PJæ‹¥D‡§@ù é[î¨%Ê…¤@)QV#JÖ :W;j‰Ö!Êeé\Ó!PJ–ž›¨4®í¥Ä>¦„@ïj˜ T@·` ”ìj‰10PÝ&‰Ä@)9yà@…xƒGr`)˜W8–‚©¥ƒ p½¡!Að–ØL×APJ µ‚wÖ0Æ‚¥ò ‚`!;Jx@;ê,xKìCí,xKªQ(YA…`Á‚÷>Xð–ØœÀY°t›@9 ޻·WƆ$Á2Hu Á2HlDÁ[2 ‰‚÷#`wÔQPf€C  Í^3 Þ ~¡ =/½KŽ‚e¡Ž‚·ä1ô" – ¸v¼%6£w,|J ÙÆQ°ÌÕ˱P^ `Á %PPD)«C¼³èn„f¿ÊÆà(x+X7o§–Þ>GÁ‚Oe `­ò¿o;À(X1] ”¨vÜQ°X³äÀŠBp ÜcŸ¸œ™IPwö{‚oÉ´ÙIPKl  j‰½›@A†ûÀÚ¬ýwÃÀ[°ÁŽFZ°­Q£@+1.4 Ô’eu µÄž|`àÚ-Ã@-°Sj‘(Pƒ‘ÛhÍ(ÐJŒÖŒµäX‰Q éÃ!Pk4k× ÐBšÆsFZg]Z»:ßêQ/ Ô’iGj ´™j %FZ¢O1)ÐJ Îì¿i‰Á¤A ­Z„Õš¹háÕñhñà pÕ{Ô£ŒOZǨu–A–A †iíwêØ™µí ð,‹ê­$C wíµŽý¼V`Wch!â Vbf¨%ÛxÎ PO¥Ã !P[Ö÷¨ÑTk¨YÚ°2 PëtÃBƒ@­c¡@ ¶Œv ëJ‰@àPØkúÿçþUUWßzàOç‹·=ÏÎ:ÛT#êôN±ÈY™c ÌN‚òáVÌ£(Š’ªv®Ê×UK\lˆ…(#¨6ãz Ì”û\¼ÝT¬=ð~RtÄ=°U»í¡V¼8¡ÊçKùÌõ@ñ$|d9P¿­¡Jì­Ê ùÈR`ƒnZ`Û:è„h”¥À6ðõr)°U²µ@yŒð(JÃFf;£˜.Þ/†M`\ ”'ÚÔ@¹d;Š(ßN«C Œ—æò!v“C| ©½Iïj3áPíK™Ä@LÊ;Äþ$ºìèr`‡0rà ‘º¸1; 9 r ¢£I|0Å 9¿!ðÞP»Y¡Rp” ‹•aÍ!ð>ý €>ÿrì¤GÀÎð¸#àí$ðŽ8Š}ˆelýÈØ]Ö#¢¹àmÆàŽ8(þ†¸Ø PTk†(·<àmÕdHÀûá3bu”Óç€ò%5”#ŠTiŠ]֭רÍPâùVB¼GÙâ (J$pM€¤3 H§&ë¹øØ—Âpò©qœ›ê kò‘3 Ì'­2`çå8%È€÷ ÃZg@™5¿pS‚¥Ä´?2àíù~3àjøµœo' @Å{eˆG œ ocàýÊm”ÅMg×C ¼%ÆPŽ÷Ús@ œÓ ¼5ìq ¼ç¶çØ)ÐnmÆÀ…Hh`ಙ¤Sà¢Äî¸uGRàfPÂ)p?¸7N·p+)P$â kZwÇ£äxgy6D:Þ'Ú!pó§rœ ­Càý9m%.ÌPãä„@Q\í Bà&K:.~Í7ßFçÀM#ƒƒàf`ÏIpñ: ÊTÂ($¸é p´ùQ&Á=ð´“wýB‚‚FZ$Á{Ì2Ê# vê(N‚â¬6b# >åÓš žI}$x¿°(! Šlñ&Á…ë Ü>‚®ÄÀû"BÄ#Rt ¼—P ψO…vå(ò 9po pN„_À÷q4’u<ØÇ9ð4@•s þ¤X0€ÞC ÃÈ€wÔXo<ˆAÞ±Ù:丠Àži£~@à½Þb%„ÀS- é(ÛÉ "½ÙA„À {Y@ 8î71Žx;ñ™Ox»(“w;ˆxë4«C2vŒ‡€¡îþ&Ñ’xykI€Ýe="`ǧ+°sJãØŠwIæ…€ƒn&GÀhi  ,f3¼#ŽCexK¸ôHÏ{ à û:¬Ù œ\ä x'ïoñorªä(Þþ·øwgæöc‘oÁóv€Ê‡åí•[úfÀE 3à¤[ÉðÖÁbE0à‚«;p ®Ç#ÊåÍ%ýÏÌ_΀‹:“3à¢åØpbP µG@y1>2.:÷œ=¿A€¢ˆC æ¹4d#·“åm•µ0t¾pÄb- ¯ tý¯ÃÇì¸6Õ>_ ÈHKèëWerö‘)ðV˜æKù9R )P~wã7_ ˆÐ{` W±nz”eÂð¶€®«"nÌD‚÷@4Á9Ð_˜X èfN—ÿ©/-´ËqXZç$¸¹Î 8&ê‚"±Ú¹ ‚Çñ‘ (ë‚Þ 8^1Å?Ž£‚KÝòõįé(Í[ü»£>`à¡KØ1ð4¬Kt œ”\itv ”:o èu<ß0пÀ@jÂŒ¼„úW1ª;>ˆ ' „$8}Ù!Õ¿NYÑ1 Xiµw ß0PÔô@bàÄ4<0PÄHƒ3b <ýYýÓ¥ˆÀIràì\ûG äZíÀ@J¬.þw¤Bü”úøCÿD¯ÈhDü‘µ¿ƒ•¡ýM¬– íï XâY#‹¦¹ø'#%J@w"‡¥‰ÿN%Mºø×q}”ÿ‚J!ÿ[ X&õ@ªsÒŠIõoº9“êßÙ´ŽÅófœ¨ê—4‡ú÷Àyêß½WfY õï±ñ:\ áÌ$>/pkª¢·ø`…p€<ÝIÄü5@>èÁ€ÅÕ=Ÿ— T»ÝíTešaa ç¨ÿš|]ÿ›X XÀ¡ÿq}¨›@ïT2jÉ[þ›‹‚ !°p¥¢Ë›?ƒS`ÁÈûS$|k:éÉIÆÆÞPˆÔE¬ãiÙ¾V‰ƒPåÛÌ7óçº}¿ /ÉYÏò þ˜þŒ¬g}6uDC^’bŠ?£¡Q´¢·,I ± ÅŸ©¡e!ÚÔKrC(cCþçß:¡[“«ûú£„neÿ|æ5ËèÖr–¶¯©Ùî?Ÿý£ŒnO´‹ ùŸ’dk{’¢= ÛÆ»”VëG£ù€^yßÐVÊÕ†¶r®6¶µØÖ+ïÛŠ\ml+åjó¶¼–·•ó¾ñÉ\mh+çjó×Ëk±­WÞ7¶¹ÚØVÊÕæmy-oë¯ÈèÖÄ $s…ft›¿”Ñí[¿ŸÉèö³õ¾dtû¹z_3ºý8}à;£Û¯¿B_ÁŸ~a,ó*v(ýé/OŒÖD^d’¿œm{b´WƲôÏ¿ÿAò²¿]j´?ý ÍjÿZ‡‰Ó'I»…ïÿ²$i»´Ã$i·ð[’´[öoþ¯øA™'Ik¿œ$­Á³gËÜùŽMÆ@í{yÄIn!PDÈ }=)·Y—ü¶ð>½.‘ý3níZbº‚–hȨKhš‹·•˜ºdç°„€XšÝ‹‘œF9—µ<5¨bÞ¡%KS[hPS.©l‘µÍ…»ä˜X{Üí’í2,¨©ÍTµÎزb=¨ÖŠD§ˆõÚŠÁWíÞ’Çà¬t›©÷Ú£³;ÞV2>ÔXqÖ«ôáC–ÅNµac³_„ƒÇ¹=ú%$x,ni}è±è6›ë­Ðc1mâØ[¥Ç¡÷ÞZx,P§Ñ]_ Iîüîø = Ÿõ6Ž¯Ð³›Ü&]Ë&Õ½-ºë± ©· —Åc‘“ÞÎ0<ëÕBc½=±‰y^ê!¶Ž$?ýþ0Ø#-Ún2ăõ-aˆ­²Ngˆ­³Û˜¦õô>b+†Û½/ÆØ¡÷16IÞ†#ÆfOFc{,vÜGiîÎDIEŒM²Aéý1¶eBÓ-AŒmÃÐGGŒmOÖcÛƒ1¶ýà‡¸Ó,#´[¢—w?Šb“ÁToÎ8±XûxºÚŸê°#ÄöÀŠÑgEŒí`ÅÌb"Æö Ä|K“é¸h¾ÏŽ Ûá“2‚l+ûœ²=ˆ~öi.O¬¨½?‚lle}Ù$ vs>²=ˆ#õe˶”’Tðè«VÓéä­Ö‚V Ñ*Øå–<&ÓI¨R{°ú1™Ž¶­¾Æ6™Žþ¦¾æ2™®"ÔyŸ¤iˆV‘ž¬¯=!Óhï`=>Q`?øzºét \ß6ÚXíù®:ÇÉÝŠét),nÉcŒvKÐŽtB °¤»ï±M¨ëàÃ.s'êf³x@ßkšPgý•’= Ò=¾Œ6Lª›ˆn÷ýtƒ´ ½¾Ÿ¢Ÿ­c¯Þ©:hžcNÓ¸Ø.¹ËJrka±x?)·–·lIä4iÝÂ3-åÖÅ«²4̶%*aƒ×ÙH¹%‰Äì ƒ”[ÛRv¤æÔ*6ÄhB‡f ëì¹ËB÷&ç–ä"z*ʶ“Bm×µF[2×@ëO·œ[µ`mp—H”æÜz Wtâû l‰‰ØÃ-ã†äܪžå®CÀ-Ì>–rK¶Xß9UƒË~È·ZrnÉ—K_Æ!ßjɹU;bqC¾Õ2Ù¯£â(º`ê´íÃ7ŠI-·áØ!Oˆ$ݪÙO†üú’tK2ú| É %I·ê€ï~ ðî:ñ]rw%ëVˆ”“>õ( ™ ¹—g“©Õ‘uYv=ú Òåªç:v‡tYÒnÕ%‹C2ž‹áB½æªaá[€ïʨæyÚ•îQÍx|O>-R9ê6ÃE]ȧ4ª…·LÌuõ1Ã…tÔ.¹5\È©ìî´j†‹¸ò­Ã…Ü fž<íƒÎd†|«Û°:ú¢fIœ¶öÅÚ™f¸¨–*£-c¼zªh%,ØVï«Ù3\H'ìî´Ç Ó–»=Õ·¤¡N¯l“˜šÊ|ã~¬íšãBÂgÕJº9.ꆣkÈ—ºé‰°€yôiŽ‹ºà}™ãB¦AÛJ¶EÛê)¼¼cŽ‹zvôG×um‘ítÆ6F1ÇE=|pG5ÇEý¸Y‰EÛÚýŽØ{¶ü®: ùTKþôj²éµŒä­ðfÉ—ZFòV6ϽÌqÑŠ-۹ǘáBN´­äX°í> ú§fxÚ:¯Ó&f1»E³û.%Õì­Zò˜ÛB´A«Ù,Ò&R žE¾ÑEÏ‚ÕUC¾Ñš^í²|£e owúd§–©Œô°cá蘧“3É‚J-4dÒÁ[ј‚ ÒCSÄnÉ2ÿü-A Ë:EFð6¸*Bí6!ˆ%vU­ó؇`¬®çn‹¯÷²L¡Ú)»5ò‘–!\¢§*±eÓ±-[ è'y¬­†Û²U ‰tM„Ï1`I..½£X 6¶Mwn'ÅÛ æz=Û ô¤÷TÅ&5cK'¤°Ž- [c¯÷šGC6ötj€cÚcwgÛÒ‘-/õ´vúÙPJ~mº´îoHhñ~GB$\|!¡}3Ê !%$Dº†„„üÂ"—XBBH ;>{„p–$$„?>1!’D: lÚLèIµœ 5—˜P“X0¡Ðg±fÀ„RbU€„Rð}  Zlj„Zb¸G$””: u$ˆ5H$2ñU a” ¹l%°`qC ai$7"!Ct„®Û@Â×m ¡Ð°$ZG ¯#a±UïA„ŠSa9,!VÞ ' m?ˆ°ÂŽD(Ñk‡DXm¥qaåSê@(”m%&g +²'6¨¢„L@ØIŽ@È5„—C l˜Ž6¬É lðU6èÌA„LjD(Cš‰°cÎDØñ9 "ì|ÏA„jê±N8vF.œ™i$ˆ°cˆ°/<N„2‰³ $Â|aÇâh¡š| |A„Z(k°]ÐiH$´LØzÁ@B=ªÜ .»& 5r`ݪ'Àâ@B= øyà¾_lø û}1¾2$Œ•ÆDB³¶á»X#0Ðl5N„¶¦Ù í÷fª!ZZiýY„æÄÉ@h–«sàº8©„¦hf ‹9ЬêÁƒ¶Nö#pÐLèÖJ‡ëB 8h~CÆi®‹Óð¤Mpµ3m¸.ÌÆÄA•½í§Z¸Áp«„íº Ô …eàA´5ø.ÌEü0šw½Ú88(¾f{nˆƒ…ËψƒÇ0†Š…Ú.4(gz^4(ÉŠ‹‘hP\ÖË€ 4(jG Jìc¡Å~lì@T[µa&hP­ÎvªÅ̲%2_4(á€%ø±^4(¶ePhPzÑ Ú÷G¢Aa|$”flNÔÞY»“9˜ñ:8 J åe¥Ž]1aPMÔVò0³SœÁ 8¤nƒ’îÙj€Õxm4,w>nsk² ÆoŒêÀ‚2kzŒüÀ‚šê×è,(uš|33ÑŠ,(s­j$ ” ÐýÅ‚’Hú…‚ž©DAïX  ”¼QPÓ+[«@Á2‘™ÌQPl'*^9 Š–kÏ QP²)[Ä‚((%6û& jºçD‚rrÃ3€`Ù )r`gÎGÂ@©a¿?0P¦ öx’ËY¸r œçØ™Áò¸ÛOI”3õJ@Ê^2° Xkt¨s”SM2° ¼5ëƒEóƒâÈ1  –ÇV€9 J ëØ¥™eu@ƒ•ã˜Ó`-ð¡9JɰËÊTÛ~â ä™¶p°V¾QÄA)1f jäËø4X™ƒÓiP\Eň4(ÍØ @¬uóT ÁZ J°ÎÒ œËÂ+¤ÁZà¢qÈ((1”{j1à Z•? »DÁJÛ£ Üòau€‚ *ÖPPã˜DÁ_™4-Ñ i jŠ15ö€u±ÚƒHƒšµê%êä×J@ƒ—Ý8 Jr!S¼Hƒš{ ’¡Ñ`: 4¨†ö—@¨ùšŒ*Aƒž–ÈiPó3YË Á‡YñC!Dª'ò+„@8ûWp"Rá´5á¡ÆAÔÅæm%Ð'² †>èsB‡Aú€×!07' n„ƒ76Ñ ÜÈT0¸)¤9 ÒÖ0¸:‘0È•‘ƒ²WÇGbÁåj%Ypãn9 nì,¸&­Î‚·Ä¦a΂»PÃ# îI½,uÈ‚LÝ,¸°´.`ÐçÃ\î0(Ý5½0¸ap<”t…H‡ÁCúr<Øã%`ðØ*/gAfºIâ`ûÊ‚»áÙwÜ”æ7u gÁmY) v.~CAñ”7Œ¶‚±ó$RwwÜÂ%†‚{áZH‚+®‚7ãN‚>† Á]Ȇ$A¿}N‚ò#ØQ$Á(! :œO¡I¼%óM‚û· ÊdÃê€7–æ ÊlÃ$¸ ”N‚ii‚rB žJU(xr<|?œm΂«ƒÀ`ÁnŸ‡`ÁÃ^° Ïî,è÷4`Sæ Ú{–iÐBzAƒÈ®48™„A¦¥I08 = ò³ã0¸¢aP–2³£9ƒ‹ƒOy‹ƒz®cG .ÆfT 4h‹¨í\‹.üÁs) ÚOcUMø³ƒ–UÈØªÄZl €ƒË>òAƒa• j7M± j‰ëAƒÊ×V0aÁ?‹šã¢˨ƒêã¶É `P2¥uU¼Ù†l ±Ög‘Íÿo%ù·ª‡ üƒèaP»™aP ,Æ´AVÍ¥mhºiÂßoeÐ~» ƒ–lέÀ„ ­ã¦Í5˜ð]„ jÃÃÎ\›¢ß IR ƒú˜ kfM·x@NÜÈÁõpÔ»š&üƒ¬dA»]Z0¨ W‡AíäŸLÁå‡t¦à¢6Ô£2 êk‡V=øØQ€,¯YÐ~–Ì‚öÁÐSÍ!cV# WÍ8¨—cÊ4xpy^.ð`ºçàA{ÒõŒÕöc­,šð©]õúìÇÆ¢à ž:Ó Ø{\ž}Œ4h%vT;>„Û#´1ÀÚÈÁuª8h8kÙpЦF•†ƒ1"ê# ‚5Ô£ ôjú+ŸH`aÂ$pÐòš1JÉGÀ Îp,„´µlVÇ`P'-àe÷ËÒ e÷0¨Ó?e0¨sc m®n g0hË`A›E&Ôcì Ú BùŒmÝ¡ÉxPWdÚ“ÔH±@èуÛHËè.Zb@µ ½ Ùœ ó¿9ìá Xáw,dgÀB °`Ug0`-¬C¬…-“ â Á€RuäBò`@®—I.Ñ…³»Ktan.ÑN Î]¢ÃáäÅ–+É%:¡_…KtÑ[J—(ýQáŨ•\¢Xe“$Ad­L.Q$íM.QNËÃ%ÚœùèEªŠ @Ù5äí­˜K9V$­ äæ²q‡5 ¬Ò€S ãË•j•c îÖý‘1ù½'ÝŽ Ûà29W``ãlÙ1° J‹ÄÀ†½>Û õD2®ýÂ@YFoÎÍɸ,¤àØšÄ@qg½1°Wø¯ÝCKìXˆèœs`Ÿx”;òÖv¤vMšà"X¹&ÈØDh‚ô¬†&ˆÏIDRà—&xÞ.ÑÎg04ANÍ'…E{‹B\Pˆœ;v¶Kš ÃSN‚r1Æt$ÁNçrh‚°Ù$M°ÒÞéš VU$Mëÿ‚‡;>]äèšàú¢ ŽM0% Ž^N‚"$°‘‡û;I‚IÑ‚²>; ÊÊÜ7 N„ƒ'f'Ái¡ôÁ¹ñ¼9NJu‚“þbÁI£ƒ ,üÈ8M¶ \¶VPà²Í¯žó’W{;D#QkP XO­RàâÓæ¸È›N‹š¾Sà‚p¸&ퟤÀåz)pa§‹ À]ñƒ;nzàw£ü Ü®G’7’òrËß À-¼ƒåÁ4}¸‘RÀ1pÛâÝ À½©åÈÃŒVˆùh·ûJwÊÜ5AÿìµÅÅUÎHìž8°~åÀck³"2ñÂ@›k:Òm7H`àÁ,æ…6ws ¼eÍÏ!›‘ao 侕AãÿNr…>ˆºÞãø Çg` wVLøP7t $}»&ÈÝúB,Xy¢`ÁŽ ¨. –‘šà=be ÔVÁ›Ôij M;/‡&X*©š`ÅF­¡ xÐC¼3ªùV ì‡,X¨ˆ».X±ß‡ë‚µ}Õ ¾õ¡ 2‰k肵ðr¨ V¢—ë‚’¾Öê@¬í«.Èrè‚ÜÄ,tÁ Ç^è‚ #vè‚N»ÃA. V*¸u×ß—0¨%‚šÍ´0ê‚…Ë”B”åEÎÚHƒmÔdA©Ñ^º š̹ ]P.ØnuAéæ~¹D¥‹ÚPô5® ÊúŠ“QÐ6‡¶:Ð%ÍÜœÐņÐ^.Q]–ññ‡$ L=( †HîºàB—EŒ·ŸŠÒ`YÈæÒ`áVé! Nÿ‚Œj õù2ŠbML^;h«÷³QÔ&2aí”ýÜ( ¬MFQsÒ&Ÿ(v£L>ÑEtŸèâ¢D÷‰n:>Ý'JUP¡Up$tÁÑ‘pPâ $´YL át$N*zŽ„ó®@BŒ¯„·=£"¡Ü¡L„’`úã„x2Ò²Alå“€zc^6¸ßQÉtŒE‚ÌÌõÍ#Ú©„8r·ì Â>ˆš¾lN'ÂŽŒN„IÒ²AJ±l‰Ó²A>N„)ƒï½o"ü¾lP’¿…ÁΕ7N„·8Ò— "cxZ6hj~Z5øÀÖÊEƒ(ƒ‡¯ä#JÐxÐ2‚ddVœàÁiIýåÌÖ qp"£Qàà¢ã×q‘ND©v( ¼3i %5#èÂÁ‚Üž‡ ¹h°ÑJ´,œ™÷ár?Òài„½…@¿½ÌNƒg}]3(SÈ7 ž·(x!Qpψ‚vƒ2 Ê ¿ˆ‚ˆ8 .¤‘M+‘‰>­´å ±`PÒ&MPo¬©$Á;  rê A·­; >Ø=$ ú¹`°ÒMë  böIDŽØX0X°w,ôÈ–/,ÛqM°€ê|½àõ€\/ȸêk½`û²^pâáóõ‚ܦ.Ö 6"× 6K³ËÛ|à~ÚŸ ƒê]Ä™¸^°wŠ{\/رŸz¬lŒ§øzÁ6éÚÄzAñ7¢„Ñΰ‚D­ÏnôʸAT}ÛQ0ˆÎÍD?Tîí@F‡hCÈ ¢mÓÚI‡(7Žt‡èÀ¤Æ ¢ñm7ˆvDRà *¡¥×rA±RšHè NçþÐ1¾Z°t ž„?TÖ ª·à‡µ‚b{»C¹=QØC'ç¾´‡NÄyÃ:‰ªnµ7'PP6Äí¡ÓvIîPwqÒŠ<éህ=tÒ‚ëöЉn»;tØîÐ{gÎk¥`qýÔÝ¡O!‡Òºͪt‡.çP’à|ÞŠ ®†RGܘ@€7„‰d} ö¹;”ú†“àÂA‚Ië‚פ_ÔÝ¡X¯ ¹J7 rÎ kwî3Ô•¼V‡$ÈPrˆ € Áƒ¼ÐA‚; ŽM$(ÙͬIp7Ò"IpÐ]I›ÊIpNÚ6I‚ëòœ}- I°ëDÇÀA‘Ó1Pò½÷æÚ@Ç@þTŽ}¼W JÃv#W¡ý’8ø’Øiìuä^åÁn›àÀ‰m[ƒiw Œ39¶Ž{å¸;!”xˆYŽò®Sà³(ܹ;ôжI 9ÿ…¬ø`­„ØÅ,0p;*Ö…Švkiz<¥Ú¼sÇÏ‘Ó|Ù‚åî%ð:ž ík•8U¾ñëSª}¿ /IyÇ^'øcú3òŽM²Z¾H/É ¡Œ ùŸÑЧ¤VìÏÔ„àxü;¶Ä ;ß*–¤&X†VâÏ¿uµ),'÷òϤQû–îÌÒ¨õœík>´¿Iµýü²2öFíGàèx-¶ ÒØVNƶ¢Ûʵ¼-Oæm¥iÞ–×ò¶R-Z=AÛÊ Òü•òZl+×ò¶ì~@¹»C/Lµú2‡Å@þöÕ7rþÂò.Ø]c[3‹<ŽK>Ò–.) %ר‘ì¾XƒÅ°PÿþŠT§÷ËÅ@ŽÆ5&|öÒŒ^ßXðÙsUø>{n@ f|öÃtô%ßgnYi¯‡|Ÿ¹e¥µ1+|öcáZ$¹øÀ.7ØÙ¸Ãg?0Ì®9à³Ø3fÍÙ|·’ií,øì Rë~•`‘ƒK}Éö]|k¶³|¡ qVð:äôc·äûL‡œ=kò¦CÎν|öãàÑZ}¸CNƒkع¦ùìǃ[.;x-læc£‰ìàe»•`±Ã’-¼Ž*vò£½Ô±£í²­]`´g¾%ßg¿5v³vƒËÞ/f÷ᛕhLrí—ýÀ¦ÈÊಟ…;Ž-¸ì¹Aú’¼°Y‰~Ú–l൱m=I²ƒ×Ai%Œö¶—%Ÿç‚^ê‡É÷¹bk {(äû¬9ìwÁ>û À^gÀg?a{YgÂgOÙsŸýllxÃgÏHú’=¼6O¥7]öð:ánÔ‰ëA?íuÐI6ñ°^é~_ó#vcµéNe/ˆZma´·áXÇ+ôJ¯FÿÓc Û@¦ÙZ¸ï„|Ãé›´uKØwÂn»šÆà­´‡Kó`õ²mÈ&ò›Žáæl䕱½»å ] ùj¬ßB³ÃJl ¹bIÙT¶Öx¶êL‡;¬ŽôâCõg½@ ñ+y¬áý@Ù6c§Æ5|œÍÚ}¶yä&œ0ªÏì «é-›xaWm¶šÎgûºj»ò.Ü@Vû­¡ l¥ãÔ®öœÙêe«Ì!ò먽YpcAÌe<_Xy·_,hÓØ ƒ†l΂ “ó`A¼8‰áA l˜ 6Ì߃‘Ð;± ¾÷‰9D~Ä‚é,ˆ…Љ!£%Äóí0x¸›ªÃ çjs”’‘aPMB†u€AÁW€`PJŒ” ƒ2 Øž0ˆK”; 0(3{ã Îõ Ѓ‡i-¥d¾aþÉ€Áb"^° ³’ –ú• ÉÀY°@[ ,˜ ̳‚ž©ˆ ‚‚³`±Ì!‚ÅfA‚ë‚eµŽ±!IPp°!Hð–XÃIPn½!I°BQ°B ¬H(X±ÔØQ°V6LF×N8 Š?Ç" 2M\  ,¡A PPv¹µv€‚ž†@Á 'I `i Vøæ«eV¬X|$XIÅN‚•7ÙIP2Ò}dd2¨ÁúLI‚Õ6¬slX($ØÛ H°!7fÀ`Ã^ZƒbÕ9€Ó`ÃŽNƒ «e‚r” 6ˆÈAƒLn4Ø, `À`Ã×3`þ r[Þ Á†Y‡4( i´ŽƒÔë8Ø"2Zà`Ÿ,!vGFÅA¦Q ìXì<ØÍ¹8Ø1ðv¤'ìH²8رh)pð–þˆƒË„;9öͳû¶>p°Ã¶â<Øm¡xà`G:p¾ÀÁŽýƒÝ6‡ ìØÁi°óõpìø¬ ö‡(ê4hË?Å™j—GìÈR0Ø‘¬/`PN®·/xÛÂ%tÖs,àkçÁÑH‘äÁQy.ðà(Üœì;ÁƒLø<8¾ó ¤ˆàÁ/gðàè„4á0^ð hgFväAîž)„$XòÈ’àóM´g-$A¬•M’à&‹¹$ˆµ”IÜÕÐ Z¡ "5yh‚f’&ˆÁ?i‚…Øçš ’J&MËr›…­‚a}Nˆ™yâ@¾v! "o’;niH‚Ø$;I‚Ø@*I‚Ë"oIÄxš$AdÝO’ rO$Mn⤠Bõ M³ˆñ›'QH%<öë%|¨è9 nÊ9S að–…A£º‘Ï5PppTíCĦ¾IÜÔë\\˜ü†4È9Œ³ «ªÎ‚½ó\. Âá0Ȅ냲yÀ`¯,qiKºLÜIDBˆ$ v Ö½¤AûmB¬D?—! vìÌ‘¤Ar]À ÌÀƒEM:t¤$¸Ù†£ ä@AàŽË‚ÈP’dAä’M² v}H² &t¡ nLù²,h² '“Y´—tBW; ÎUAª¼¡ ¢¢c 1ª  0²Q` M¡’*¸L¡ Z´/‰‚TðCœ$3 ÏEA†IBÄèœDA$¸O¢àÀ‹¢`')RøùCÄ·?©‚õó‹(ˆDPIä ÎhoOÄBœÐÕC\x17(Õ5Á©.4Arh‚o“¢¡3 ‘?9!Z‚©ÌN”΀˜'ÄRÍÄ€p&½5ASØÈ€ ‰$ ’Zá)Jš 2ƒ%M{d&M¢e0 ò_%M›$ |ð\;bC¢ÄÈ“8pSÝs„i,qàÆO¸)RìTî\D.¦¤ v"gÒК`ÇËš òé¼4ÁþElÔò\lŸoœØ®éÅÐò¢Ä%ÁfãKÁúE,LA$|i‚¸b²àB¦÷¤ "èš 2õ¼DACÊË7Q°@ Dv¦Dƒ £?“:-à@ÞR !%ÄpXÃ(° (›N¯@8`.:E훀6tlXoó‹X)):"Äù@›S:6h¬A€«Rƒk+¶ZM¿H2†6{J’1±ù0†"uc2†â žŒ¡dO¾ÐÙtøB‘“%A ¥Â [(¶% ¬È, XyG Ì!I ¤BW; ž."╤@l’š¤ÀIEÑ¥ÀÁ³»¸(ü¹¸k.ÒÊ )ÉU’x̺J 6ÝLR VŠg%®ZT‰€µÛÐX‘-°"•s  ˜_­Äµ@Æ^B 4‘'Ií‹+Tª[—±d6I“héR õ¹'úR C/Ž€“XæˆF ßüÇÍ[’ˆ}¤“8ñÊg!p¼-¡ò®½ùï¶u%+d“HpVmzàüWa˜$þU„Óþê!2’þ*j&ú£’…@㉠¿NØ£¸ˆƒ.Ò “…@E]?Áq¤?FÑ’ˆ&I ´o&%Ц¡jxI 2ø‰"ù¿†…v¡ã ¬!Ö¯~Ð^¾€Ÿä´0ds!¡¤Rܰ@¾°bZ `u†ˆ_RýžŽ~XCB+ú!"”ЯÑÛéà Æ¹È':$@Dt“H_ZH€È ž$ÀΣ\äÌ5$@øˆ’8 S‡ˆdF!ê{®bÕ|Ò‘*#i€Ø³-i€ÔTƒþ+)¦ Íð¡Òìð×'=¢.RC ‹“ˆ¼ I¤}×°Ÿ¯è.yÀ¾iø$vË®ü'}$üëCÿ¸k_à___ñ¯CZ üë…8òŸ‡ƒœÿ:=ÀÎF[~Z‡?&÷ øëH›4@(_ þøNþ:‰ó–€?¿:‡¿Ž©u‚?Ó ûV¡q,‰€´ „HeÖÙÏ£!R« †ZG?ZñýF…ÿÒ%@h ID~@?Zèý¶oJ òd8ú §C¢ß@ž¶@? 5¼í ¢‡¾í {9ú!üää7ÞàpW'±Obæ%öI0ÊŽ"ö 8$û2­ÿiÒêÌäÅ€‹ržÛAaFy- œßì 6¡ ;(ü)ÉêËüÜŠÑ,ùA-ªvP„¥“”jNØA©§„_è@À‚È~ `©^”íª>2Ë_XÜÖI”ôjo,ÔŸéÎ%ÀYËU@$ªJ* —F9V¬{I*à þH¬˜\%¤Ôå2àÆoøÐ¡éøØ€Øx!Ö¯fP¦Ÿä6É€æ”H*àc… 8¿šAÛ¤»ÒU@ªMN€ éƒ@€Ì]ØV±96ªÉŽ€Þú@@Q„ 5‰€Ëb;­ÐŽ€½ñbˆ€ëb»¥w t-Ì °Ûî&A€¹ ;vM ìXPØ×W °#̨ËÏ?2ÒÄäHwTZx¸VÏ×riˆ€\‚" ²1%okˆ€°ç"tˆ€‹~¹ä, Ÿ=gÀp¡Cà€;9(Ð]BNù,ƒr6¬[ ôÏ')Њ9ºµÈ)pÀ‘8HŠ¡r=ŠSà@â³ ÀѩݑG£“8è:t HC“–bL˱sjPà€g>–b‹¶´GA(‡Aƒ† b-F¢A@LÐ`‡ô4(SX£AÏ–¶wçz2dîy¦9j#EëxUâ Tùvįϖv$ctRÛ^’Ò‹± 9‹âÏH/v$5Ÿq#bInelÈÿŒ†IújÊÞ²$5Ä24¦†ä‹hD̆X’Bò?ÿÖ™Ó¶°Üל9­ÿŠlh‚;}÷o)«~¶î˜¿}~EÝqî@Ò_YÖ¾fÙú5 ×¾?Ò{ë–ô9éÕay=ÞIÙÐRJ¤f-å =û•ã–·À‚ršM§F÷ë©4§±[½œ³,(§KÜí¨mA9)™VrVÊØ¶õ`.y×Fà(áª)©”;Ì¿Õn•+9WKÞmiŒšy‘çMjë"¤cívŒ\p[²ßï…¥óvÔ¶¨\*9•ÓÕôv=…å¤Dš9’]khêHªßz¢>ZÒ,*'%Çêt‹ÊiÖ9kfŒ¶(åh†ífËJæùÄ}åˆS‚rÛÎɧ½÷«ÎAP®ÀÉvʃ ·Ì<µ (Ç}N­ÊlípjCP®À)t6åŠÍÃOˆÉ,®¾%ˆÉ•ʆ'brŽìKYÊHO§n ÊYºw)8ÊäN9õAP®@È9­ (W y…mPþ}”+È‚Z· \Á:¼Ó‚rùšo ‚rÅÈ_DL®ÀæpÚBL®`µõi19»³Rr“+0Ÿö &W†=µ§Ää b÷eELŽ©Óbr²Ó;bršù…RÄä äæ[b1¹çóé19$G8}!$'z·úFH®`=Îé!9ÙMF DäŠ)8w(A@®@“¸³[ä ö¬8£! WL¡¾Ÿ¸êºŠg Äã 6N¾%ˆÇq·Ó3&âqÜúêŒeñ¸‚íÏØˆÇ¬…82ÈÔ0­äî¬ÓYÏ™ñ¸‚mgVÄã¢N«Ì¸¨˜zf/̸¨ãn:„Þã Už9Œ»%:~Ÿ¹Œ‹’h\Á~/w$F4®`œ˜¢q+ Î*ˆÆÙû¾*Bq²Å…UhˆÅqÓ‹³zqOݰ’ÔÑv!k %Á8É©¦ðF{Ÿh¯0ÕYƒ`\µí¶Îz‹+08Ÿ]‹«c㮈ÅImx7Äâ*¶.8»#W¡<ßÄâ*öÓ9{<ž_ãØQó0¿Æ¶†×öü°=òqn°HÚ¶bqÕ$í³„â*‡°SŠcRŽsª…â*òãœÓŠ£óœŽP\ÅÞ©·¡8î{rî [2Fù6›­²÷‘os…wPƒ3G¾Íf«ë<×A4Nç9Zò Wa<ªN«£ñ¥£W†<"6ì"y„Ö±WÃKÖð²Äã*f7G÷üÔ:ØVëÈ¢Ö§²J7 „GÒÆ|ù:W¦,±’ƒx\…ÓüÈÜ…JÏõuœK¿Æî*?¦¾ßlõÃm¨ì Žp÷¥z$¿íBñí‘ OΫ`"Ç|)ìéÅ]‰µW|Ÿi>Öð™¾-±~ù>7ú$µÝ? k•Z«ŠÝ¹ ýÈUÄdŸÚ«H¯ðȶ^§ÒøH¼EpîôÈÆ^´Fw+ÙÉ™Ü!%!¹ íá‘tE»ÂV““£ôì­"&W¡§ß¹žÅä*"¥OëˆÉÑëyK“ãúÄG6öZXo|ìT1¹ Õ命¨Œ7kg[PNš±ƒ‚r\æøÈºàTöÓȺ®ŸG>Ð pû‰{CPNJôîô^°@+¿nɃœ¹Ç¾]O9s‘È䑽Ö¶êÛ÷ÈÆ^6W­žn[)ØQVrÈ"dyß¾‘‘/4ÈêPðÈÚr½Úaæz=DÇõgØ.Ñf¯µFäúa®VgX£ž¤17†q?J¶‹Gu2ýȾ^}VA„\OD(!"½d'‚ÅýA„ DX`: "dJÍ B Y ‰°`9Ya™7a1gca{:€°Éýje-ªµC ,¶J x°`‹ÒàÁ‚­±ƒ |×Áƒ’Ô( }‡BÏÅO(Ô½ŒÝ…š Âô8@¡á­ ð1Gv‚Bm%ðìON@…R`_b—'8j*~ãDʃ“ßo—'ç.ÊûkìFypbQ~ȃ_ '¹ÇõÁ¹©ýQdJÿб_|ȃ—™/#äÁI`qypb­oȃ i]B\”\\Ø|ÔåÁEÔåÁåº#åÁeéSCäÆ!.¬)yp!ôòàªäFʃ cuȃ ©ƒC\X‰òà"°¸<(-8R\0Þº<¸J+äÁ…]vB\HÞúàB¶Ð¶ p!_d(„ ™P¹‡s(„r=™ Wrû.KÍP¸*µH@áÂ?…Ül! pÁßP¸l«ƒ`ÂÕñã9.ì{ïLÈ­ ƒ o+ûÍ„‹º3¡¬Ê3ÑL¸ø¾:.F™œ V.Æœ gB¹zs —íL¸ …k¸,XðXRáBJÌ Â…¤A… )ƒ å‘0ú$.ŒôA…Þ§ÂE‰Ý©p!BT¸ðU *ôçÆ©pQÁr*\HfâT¸°¨$¨Pºn—C*\È¡T¸§=¨pÁÝT¸Ê#.¤ð*ôfœ £©pa률B@"‘p!×X á‚<Ð{éH¸&n„#áÂz½@ÂÅ0ž#áb8БpaɃ#¡4ó‘‘pa¥s ¡W!òùt \ÈH@¸°WTá¦.„AƒìA„ Qƒr].–#ár%H¸¬ $”wà#á:'ÂE!ωp-¢&‰p!LëD¸%C¡Ž){$ÂEàr"\¶6 ˆp!ÒDÈ=σV'Â5x5$Â5x9$Â…iA„Ãà8¸°| pPƽ<âàBF”ÀAy>­ q_—ÀÁ5HžÄÁ']à _/qp!ùeà TH²àšä*² >?‚¼»N‚òTA,1t¯‘ù² ®E‰$¸úWapš£&@P^ž·.¸&DRA™]½ApnJqAYe`àEäã븰Î"8PªX3ä@¹Éo\û+.,œ \ƒø™ý ì  x8ü$Uú£/'èOJ¬™'2ví7ýd,LôW¨í‘þªåŠ ø#÷üqƒš€¿¨Cø«° üÕBË)á¯`» À_e&=‡¿Êý¶þ*Tü,àø«…®OÂ}Må¡£“ðW°]DÀ_™]<]ä6b¡ÚîšI|¾ ‚Hcì';(}q†ZVª@¿‚Dö~¥¾õÀpk’ü %c¨·Bò+éÆP¤óHÆPlŒ¡í‹¨ î¾C a ¥3œ¡Èœœ¡œý†3´ÃÌÎÐN¥‘ÎP/pg(Ö,'g(œÓÉŠ…ÄÉ á89CVOÎÐç¥FD:œ¡H󓬡Sæ°†rRÖPìÈ™¬¡3а†rrÖP$ì}YCQÇ­¡îòtk(•a ¥z›¬¡ö”fk¨ÍÖŠl±Éºžî ]„J7‡. à$wè¦LçîP| ’;tÀ\ܓúٲK‚›"a²‡ÚmNöP¨. b\J’à¡Õ%Á‚ÈöP{äB¤Êê’ Á ëB×ÞMzàƒß%ô@Ä4“ˆ0qÒLdz=ôùæµzà¡æ–,¢öl;üUä øcìðǽÊþ*"!Ù!jϬ³_¥äÑú#‡¨ñ!Ù¯2~’-¢_ÁZIƒn­_A‰?dô»Uìg‡($B:DéÛÌÑõÅ!Ú Ûe‡(H4YD¿9DígIQhtî…èå%‡¨¾Ù!jÏpvˆ–·(OîGf¿ÚpyÉjÏZö‡ÂØ™ü¡6Œf¨½†áåÈŸü¡†Ñð‡Ú@þPŽáÙzÞô>S÷‡v<úÙ q2ûCÍ£éþPxH“?´¾á¯vXò‡Ú<ùC?ùUø’9t|¾µÀp‚&o¨Í·ÃŠÌÉÊ ®{Ca]ÍÖP(vn E¸d ¥/5¬¡ƒ†R·†"ýL²†âƒ“¬¡ä¯°†ÚþÓÉ:à˜ÌÎP»wÙº Ñ’3Ô&éî ¥á5;CßJ ˜> ëܺí“ô2†‹„1”`ŸŒ¡¦‡1¶¤—1t¿éï‡ÆPk'C÷cè¡YÓ¡XÀÿ2†šJ eÑ0†â{ø6†Z‰CñÙ cèøn 5$ c¨}x_ÞP»àì µGôå 5NËÞP;Wò†B÷KÞÐó&ÀjY3_ÖÐúE|ð“gk¨‰ŽÙj(GlÔ.à i, ÈI([©|üEy×^«G»Ciµ w(ìîá»Â:°Ÿp¸C‘t.Ì¡0$s( ÔÉ [B2‡ý“9Âv2‡2y˜C±x2‡>¬C,D´`ÁJ=´AÙ“ ˆ=X°4Êl΂ÈB,(V#Ã1gAlÀX°“ü Ö×*Aåk‡B`A°5„À‚¨Me‘;)ÊÄÛà B`Ù„6‡A8B,¾pÐip¾Ì¡:qüBƒÔÇœa H4'v¢AÎ?ƒ g©  VìË0X±ãP‚A.r¬6OÂ`%®: Ê—÷#³`Å>ÂÁ‚•‹ùÈ‚ÕòÀ VFö+Ý]Ž‚/U  L5¬„(Xü€‚Õi‘((K+^ÖPý6Z QðÖ±ÜQ°"(ÈOa  |çÞ(XMwd>ñ@ÁÊè¹£ ¬¤0># V¨ô‚\[á((¬5Lä§&P£r`åƒí$ÈÁ=HPŒõïu‚–ƒ+vǬˆ† r'´ AîÕ$È¡;H°q,I°Y¢üAùŽö«m Xñ~86®7s l|h‰RðVÆÃ Á†¬uA‚í›34JH‚Ôä$Ƚ‚mtÏ$ذ!} e‚I°ñuulÈ„$Øh‰4l$'Áh–(ذ‘u `£’î(Ø(œ; 6ì8(Ø@Ž‚€á(ØHŽ‚~ÁŽ‚ ä(ÈÝÝ%›ùG"ÁÖq÷œýÎ8 ¶ÑI0JH‚Lã(ذە£`£hê(ØW%¹¦AQ°u. $ 2—f ` ‰‚4gÁ5$`Pn…•G.‡Á†u ƒÍ•AÂ`›\¯l$Û[´Ì[™Åb'ÁÆ€š“`ö%A‚m’:I‚‚““`s“'I°MQ°!Iw `£žà(ذY‚Ó`ÃNTAƒm~ÑÛæ‚CÒ`#ª8 6ºR ƒmу’ãËl ¤ÁFÇ©Ó`CT.h°¹šHl\uç4ØèJu”¬oЯØi°!ßvà`;$Oâ`#K96¤ lK‰ƒëç26 Z΃ iÌ‚i] l›„d®ÙàA:à‚ýŠ¥a+!¶ƒ†Ûóu¡`;TÿȃmÓ+Jlç«ذ)uð`/¼ò wÒ ô_ÂxÐqä. ÁƒÂ|VBäíÁƒíqBÊÅX yÐo…ó`CàÁ†ím‚¹E{¡Ì’íìB{Jœ;,§A™ }dìå#“ ó r÷ Á}+%]«¥ê¼hyŸZ5Ÿ¿—üÁëx µ¯Uâ TùvįOºVËÔt‹©m–¤Ìd,C£ø32“Õ" þú«!”¼²2oˆ¦†îà²>Û«·(É ¡Œ ùŸ¹¡ÓÞÍœöµ‘ÓRçKú·¿M²µ;äêûñW%[«óWçZ»“Ô_kmôùÿ4×Úžä ¬j[)õÕݪ“ë\ mE"5¶•3©±­T m½j±-O¥æm¥\jÞVÔb[¹ß+O¦Æ¶r65£ÚzÕb[žNÍÛJùÔ¼­¨Å¶þЬkÏ#Úÿæ²®ýšAô§÷ ømÈüéÇpFæé}·òg]“œãíν~1óšäûç%Dû–yíío—ymý Í?ýÿ>ßÚýeZf?Ø9_¥Ÿ×1¹¬¾ d2GÛ°¿ŒVnÉ}û°`_ÜÓ>»‡lµä©,Q^¨¥É¢P¬²GÁó‰3m”T¬Ô6̼2¿BJØÄ2o ;€üp·d–Tµ°¾á˜Ý­KÈ%Kn¸ ­° éûéb°4_J–,k§KÐÆJ¶µÓo˜‰ÎÎÞ;Öiw›¾ÝÉRl±ê‚öÞ[²FŠoß¿7VØ7ü÷Ó¸ ¾£‹´‡MIk³’Áßi°Ãfº·„=0‰ìȬËûQåv€)ìb†$VG°Ýº=dÑRX˜iÑ.J؃¬Û¯¸¶§ZÖûδd92l”`…öü´.N‘hP€ƒxý0šÞ^?Œ›2…›^bs|B+°Nñ?"CÚÝíYÐçÉ B\ÿ±«]²âÚä<«KSY êÈ"$ˆvêÕ0G0kä-È­ÀîÔâåCÌ»%²ŠIЮø³Q%»}";€uzúÉ\(y˜aÀÙÑLÏwt€%ºË’ØÅlAHÓGªµ»e—)Ô±›µÇdŸœ+ºðà(vÁ •·`7t»5ûTëÓÆ­ÙOù„6Ó­Ý;±¿ÑÇ#+ÁOpØd7¸%уeíÙ´ëÝŽ¤s‡.d—w&hbãU:«2‚½£'z€[|¢¸ç)Ÿ“ðD˜Î޲1Ïä•¶’‚Ù"ÐJ0><Ñ<ŸštÛêØí”¥Oãݰ:v­a´Û'S-X¿ŸS?‘U¢KöûsÖZDo±»ÅòYÁ1ýÝ6ûdwOEöi¡Nô`£NtAc©UÞ/iV²Û'¤¸‚£NeöH<å©"+.X„;(zúäËQì®õ¼Ž©mà¿ËöpVÒ­ò=FfûÚÖ*»>[ɰk©ìð·$:`/÷=qeIǹžÂ.5œëyØ'{øj+‡}²Q®¶ aÕ-aì«][_ï¿eÁᇪ˜6£¨òAFŸ´º°&«ÉäÆ4öéA;Ñ–X‘;Â>öµ×ýyÞu$šg%Ýî_ïhÅ>þµGjÌÁjîO×?a,E³»±S UNe^‚‹yŠ…ŠE;¥Ä»p¬DvC‰$›1õ†J6CŸðÈn`è~§1p"êˆØÜ¯Žè^¹±Û'ô抒SÙ©gzÊ'|¯-?Ï']¸Ö…]@§&ûPù\Ëv`ûu.Ù ¹8ª]¡„VàÌÅ]Ÿ“Y?ìÞÈw9çø¸%ÑÖa*ߎù–Ø4í–<ì•z•ÃN ;hÕMãðFè‚kuEêŒÁûVÙ ŒIHì×b6»ù2×w»§²S6g¬ë[Öóx‰µ»uOgkÙνëf¯ê´Å^;—ì†^Ù¬»îèÛaÙ ½ÂK¾7S¢ ÝSÙ+¼ÐòqF‰t¡ñÍ<ìBãSrêöNÙQGcüv”ýT²Ôíè–=v”]ž@'­v9‡]h)»€Ô9̵b>å“ön<Ÿï#Ô ‹»Q¯ßÏû¤ëGCm6ükS«½‘¯~E¾|#1U~÷|¼5|Ðòaë¯óYó%óa² ³ü}GõUÅ>ð‡ ꃉ4Q_ÃMêãM êãêkߨ2p¢>þ¤A}³m§¾ædHê‹R_ÃÔ-6Q2Ñ9õA¿uêsdvê#2;ô5â¦C_*ñ`†>¢˜k;õuþ¼N}€SŸÃ¸SöòKØgù ú°Ë©¯ó×wêëüõú:gùN}NôŽ}Nô3:À£ØÎßÖ±ârâ¾Nž$÷uB´s_çÏ?ÙÀŒ.`ºëàÇfû``KÜ× ÕÎ}Kpðë˜X¯è¿îÐIjê„¿Î×ÛÉÏC ¿Î!ÁÉKÓù ¬“¶€Jäça '¿ÁWÙÉoà qð 89ø þÞN~QBnІ‰~ú Lý<r¢ xFNt¡ƒ¾ÈMƒ#‚£ßà#áè7bpö í]`•è^wG¿Tò°SˆÆý‡ G?,;OèçÑG¿ÉßÎÑo;ýŸ g¿É1ÁÙo0žèì-³qû09-vøc`‡ð79[tøœ<8ü1`ð79kwø›œQ:üMòÃV¯&ø›ü;ý1†ôS[¢??{eH®¡ üIøÃ²Ó ^üMG½è` F&‘è4 “S}‡??—ÃßÄôÆÙ/ª°˜Ü‚ý&§ `¿\Bö›œL‚ýr Ù‘´`¿I’nѧÁÇóz‚ÑÊaˆ OØÏwlvöÓv`̽ véìÃúýÜ&ìèç8¢Ÿ†Û^è§) ýô Ô‰àéúi;(©›}/öÓ(H¯OÆíð¼fÅÏ?¢ /ô‹ˆ!ÑOOì<Õ7˜~¡Ÿ–T”<ìڙх ´Š. ÌôÓÈ#êôé±Hãì¶9qîƒVV÷`$މ>€Ðfô%Oa ÑôyÞÁH²Ÿ–XAÝì”݉=ÀÕ,ö`sPùyöU'¿rùEˆ“ä§¡R+8žiõÅ}®$÷iðZ9 E¶÷yè”Ø—.اU@cìÀ&ov€Wb_>ÕÆõ¾¨O pê§°Kwô Y=˜/ì‹@.±OKpTŸìZöå£fg§ðrœèl‡]GŸƒì÷y²[?-yŸ†Œ_àç{ê8øyîݤ±nþ‚ j þÔô‚?¬CHð÷PT©LV‹ Ë×acêì÷PåröcP0Øïøá臕• ýÎ0ýÐ/b‡~qTô€GÍÁØ%@îhÏVv÷˜$Z9±/ ÐOK^‚_: è—Kêa@v _®Ó{Mèç9yýòÙ¹@ØÞm-š<ˆ¹8ðcPŸV` ®}q®6xí8H}¹¤#<ÄW“Ô§%/ê{ GRŸ'áöé߸šƒEå…}¾FбÏ7°pìËu ûr zP]Jöi;à5£&]:¦3ìÓ:ïŒû´TgÜç«Á}º,íF(Ã5‰Iª!ÀOñ 1?®•rDà>uσÑ…†}iüÔÛ¨3jÊ%~ÚN~ÜtÏ–Ÿúú{³ •ð{C®?]DcMº6ç¥øyúHç>-At¡<f€û¸ÌƱÏWâ8öé2´bاIX‰yXz]©>ŸXŽßà¤Øp؃Ç5@c&ä§üC`ŸZ·íûtÕ/êöé:œ }ÍnPÂ>0ˆì{l•Çû|`_þ»béu'§ût•2@0º€Øç˾û|’cßSÝìÓåÙ/É/ÝŠ'ú0©¢!öé-žUöàeØçK¸ûty6JØ:@ˆ}¾ícŸžhhÔ¤÷ ˆiا?ÕKôÓ» 44ìóuÔŽ}º$ ¬UYÃþlh‚ aŸ¯wìÓ5TP û|q¶cŸ.Î~i~ZHgÔäÛù8ö=µ¹¾hاËÉ@V«¯©|ûô jqÁ>@«qi;>Èe•þb_úe)ùUÆy‰}ú+8Ùÿ·è&¥”ü*§‡äWuÉOzð–ü*ÖIRòúPü* K®øÅ£GÅÏ_ —ü¢(~éRoůºrMÅO~< ¿Z)¬SñãªØPüüc犟” ÎæÛÐO¯@ ÉOZÅõBó«>%?æI ÉOª NtÁB—üîNÿ‹9ÓíiÆàí=œ}$ÚCä×iï‹ÒG“i/¡ h/\ ¤=­£-H „ÚÓ’íå’ =ÊzÝ} èh/<™ö0qÚã1A{¬´Ç’èB{ }©N¢½ö²wjÉËÞ™K‚öØrÐKR¬àKúþrqä=?€¸ç÷Ή/•ÄõC|ûvýN|QBâ£÷%ˆ¯pÚèÄWœI|q.ïB&¾¸»$¾¸»$¾¨Câ‹>‘øây˜©¨= „\JGøâzI|~‹ |érÎû–ÏèàƒÀÍøR €ÏODàKU|Ò@-õ%¤¥òÅâ™.˜À§ïɳ’y/Ù©/‹g4â¸ççqï¡]ÙyÏŸ×ù6Å…>Þ²ÃL,ž-‡Ar}óx®—ÐþÍðx"š’<žçE|æt%ƒä7çóEè;ŒÛ¸Ðw8ºÒNöá¸I˜\é;tåËßaòßLž`KWúŽcXX$YIܯäò„È&Ïó">ß·ûåò<,ñ.º(’=üÜ·HÚŸÔù¢u>¯Âð32ßÃ)ƒË|QIOŠŒaòtt“gÿ"ó=xØÂäùRùÎÛ’ÇQôäñ$Ë…Ç“F0ÑLOµ’Çó|‘ùð}ÏO@"q¯ )iðžÀ{a¡l´Gb†›-žÁ{¥ð>%‹'î7y/Õï…Í2Y<1±KÏñæ½Rø+%‹' +ž¤9wx£ ˜'‡'¸'9<ÂÉ≅Ãóyó^&“ÿ;<–FØ#ñ«$‹'íš´xútzp»øúÅâYlp‹§[3³ÅG…=’¦Ï°x~sxÒ‡] ï2ºðƽT%Ü‘T Ãà‰ßÒ ž¬O–D¾ù;ûÙßyPþN@Y<ÙàùÆ=)ü] &s$Ú ƒ'iŽOCƒgsÏöI¸+4’OÃ9Þ¸'%,ú;Ý éþÎ8ŠþN:ÑÂßÙ8h%çyã^iÔuÝßI°¤¿3Z çúfð¤–} I’Áh™ žˆ˜¸Á“6·0x‚"£`Z¸;;Yùÿæî]ruG’-½¾F±›‘ ÑßÎ ¨:H@ àâ6¤Vf)!èÎ_4³µ–9ÿ}"òD*•nïl?N'äO÷Ï–=àÝIW´tï„ïZºwÊt'÷N "÷ÎöëKäóô[q%‡wg„Äÿtv´ƒú8*¦* ±¯Ñ S"Ÿ\á$òÉ·¬dHÜý¡òõožrŽ’Ê×)UÈÁS¡_Rù†ØsÜÊÁ“Þ'tð4oËÁsÐB/ÏÉ{#Ïù-¬OLrð¤cA:x.)xtðTL“<—ðº\è®É9h Oí'áàÉð%ùwn!(<“ž[‘uœê¡ž›7Ož·œ7éyó!ÈÁóþ?ß¡¥>[‹_.ž¾fzƒÀ¯w~ Hð£Å,ÉOÎÙ"?®I~\Ý’ü*©Žà'jŸ|¼E~ü:“üŠÂô.y³ã‹ü*B?}l$õUaÑ/[º>xĺœÂýB?oÁQûä¦L±ÏÖô¡ØWùã ±Ïr oÎê~÷ÕÈ94ÞŠ}—<Œ)ö1‹AŠ}—\ƒ)ö]MàÉ94‰†œCã¦Úg-Œø ¥ìj¸ ãJµïBUŽTûXÆ4Õ¾K";Õ>;* ”YG ±ïêü¹Rì»tK±ïê ääZK±ï¢ó­Ä¾ ÁÐú.z@Kë»ê‡‹§§•¹xƒä Þá}~uJÙ3 ¤>Í@R-ê|×§{§§”?u¾+½.ƒšäŽJ¡ï¢?%u¾kÐFMï±}^)ʯ¾KÕ#6Mî(¨ó±Šlê|V< Eð”¦~rÃø1ô˜à7yß~‹Nî›ÔUÄ}\–“ûäXs äæ˜“Ô4¹·÷É[NÜ7I”?M©q xпIýXàGç>qßä~]Ü'7Gߤö"ð›¢ENaÑ–!𣞸oñNˆû–ÂëÈ}“¯¸8É}Ù’SÀZÜ·ÈÚâ¾E½Ø·äkJî[ŠÚã Òé2§€~´Ù%ø¥&Á6;‚ߢ¹@à·¾EöÑ‚˜ä·2ŽïÒ¤èðysV ”»ä÷Dmä·èé<9@Öã6•ÈoñUù­__à—§&øÉOðˆìÃ/hr ûÃÓňðÛ ¿+òܺ?ÀoS¦ø-~²~[z!g-ä¦laÙc0±Àoó ømy…r [tuÌŠÑiË“ì´ýGðÛ ¹#÷-¶¸o3L/gP_ä·yË7Ë63ä·é´*ôÛ¦…~ûÃÁÓ3CÔËë‡MIì·ÃêpæC«ãGΨ¦Í´<UŸÌ‡öÑ%b>´Ï#þD>´j©ßæ96[ÎÄahcn!ýydk–v¯Ÿ±åmHž­ÝÞ‰ÕØò(Ú4ÿ<ê•’€n[=ÜÂÚ«ÒŸÿò¼hu9GþgË‹öý®£6FŸ29Õ^áëLįYŒud<ÃX¯Œgëè…±^½8Vf<ãXgÆ3Ž•½8ÖÙ‹¿¯Ìx†±^Ïø£Ì^ëÕ‹ceÆ3ŽuæEãXÙ‹cýyÑž=ž‡÷ügË‹öÓßÞÇoŸÎß~üŸŸÓßy{ߣüé¼h¶ï¶½Þÿó¢e ´ù£ iÿ /ZEaÖ?J ß±d6DLÇNþ¡…YÇN¯ŽQh/­h™­££L¥‹½rKɵ>êØÊ®Uq®;³kÅÈóŠ©DKé²—Æ"?ùYEÊfã0DÙ…9 ÎÎDSqæ9ŠÂÚâêæ¼†cæMkéDŸµiÝ8gÀ€¤:oűÖu)0'öŒuæc=”Ø(‡±©®V¥€ã¨þ2}ÖÅ9 îÓ2/ÙpÓ¶ˆI­µßbk]{)XsÏ·ØZ÷õáBò@¬,‰Øií*ŒŽ–&Œ…–. ¶ ãjö”)1LËO‹L‰W³¶ZâeÛ{)É Æ½'‹a€¬n¬ˆ–°U‹U )}ªìpa>yös²Ãá5¾»ìpØ•Þã¢Å wùž°Ã¡Ã¼i° µíùŠË Ƽzo™án r˄ѮkÈbµ£¥tY¬îh©MÖ-œB‡ø¬—…+ö²aqä!Ö>& 0øµkmÚCxÌ^ïxœíâhEi…sj)Ö„àVj“‰}Z%y7ôé…‘ÎæŽ§å¦ñ ˜ª=Ä)sF^ ØÐvÛƒG‚Ôh`Êá…ŸY«×ÎÅ©+§@{Á&ÀÃQ­ çpT/ĹЖC‘éi¹És<;§°áÂÚjLáæê^ïQï) ‹Ó®!DEKéœSü‚ZËÄKÛgpc©h­¶Ä§íÁ–Kˆ„øÜÓa¡µ¹é_‹·¤-³¯~kÇ4œú¦×®ÿÙ¯A—áX¤šQ Q¨[¯ÂáCО­ =QCãi×oNÄÑ€Ëgm@kÃ:DZŸ›3ºqòµè[‹_aß“¾µñ™mýž¯œÊ(-xelû á°³µÑªâpâjF/œT»Ú p7ÇÓýÂÙ9‡¢³¯¥@œkOºrwŒsà–Îë}¦Y2n Î4ë‡×}3~ˆˆø³†{t2.†{, ;nwÄ´çÜŒWÁA¼~î%ž×l²{Ë[7x]ò¸ÇGnFÊă´…™Ñè¡ËÇ’ßVΕ5.ëábÖ€Ç=“:´5·‚õ0òZœÓ>9œŠSÐ×ÓÊv¡%d—fe»îhÁÍÚKa³…¹D8­Ë5ðT6g@ëòÓ‚0Á@ÛSˆøiì‡{¤h{Ãßžû¬¢%Nuç ð¡¹9š›[¹ã(¼EwÃãM´e¹à‚£aÀÝž1ýO Üí¿Ò7gÀí^ðVgTr»7¼Õ*÷ wûï`·’]˜TÜân5»öq‹û•3hèÒpy±ô+ ü- 1.>¥ 7ƒBºÌ­•hÉëïx¿xý‹Wr6ÄÊÙ­^—OˆÞ•½”Ø”|xZjlæÊ M¥[½®;úÄÕM Î\r¡?w[9% ;7ŸR<Ø^Vl„ Ô½ìØËn}{ánlŽ{Í)àNÔÒØkD¯Áª^Ý)&nõº0©†–{¹Âd’ýY“ñ7ÆÅPÊ4 bÉëfϪÑ#ŒÆýÙÄ2Ìuâ {0Î5L´úØ0¸ 3¨tå&mûûÊùŸÊ–ØÇtØÄ>ºi%ö]ÀµÄ¾ò}Þ“ú´õ1ø(©Ugê«DQ?²I}LE–ÔWñsNêãúDêc²2R£Ú’ú¨™Ô‡$| }y¡¹»“ùèB–̧1õ’ù8Œ¯ èˆ|ô*#òé¼~бˆïh¹9#€/‡%ò‰ñ…|jÙ9ƒXWˆ|gŸÚØ‚.­*«Ȭ—wV· ¾sœÂ"æ0îÚlaŸ½8)t¹'çrï85€ÏûsìÓªæ„>½pR³qqN<Õ¼>þ¾5'´3À°Ç ÐrOµ¹®¡IÅJ àË£|Þ0ûœïl—Z0ò¸5«XçøÎq×Ö¬^ÀwöÉ9D—rLTVºZbÑïÞ;ûôò1©’SØ »oSï—³öëz{ç ,:£AÀ{GŸzL}jcË~ñÞÙ§NŠ}Æ¥I½xÏûÄ4kNa¼w޲9FìsÀ{Þ8u Í XVúû9µœ»äp)À½ã qiFè2nÍd9·f÷¸wžŠ3àõÞï‡Þ;æ Þ;ÞEð^^pï¸1ýóú{^?G·f sL´wL´wt¿ŸóÈë_/Ø;ûT–ǵúžPï¸/@=ïÌëgŸœû¬õ1% ÞÙç?%G½cÒó˜A4µúñÚöÎ>ãúøáö¼§žïÚ„½s˜=?~I ½cÐ^ã°w Ø;®eå ö öŽAF¦E—¡MºÌý1# Þy¦œnð:&šºúÇO ¬wå¬wü”Àzç(=³¤ÛŽ) !g€.s¿çÔ;»ìù~J@½ãÔ÷1´x¡ÞÙ§Õ×zg¡mû íã8î1ôYëãÕë}îñ~Pd½|d½|÷{gŸ÷öò1öÎó í‚Øgj#ÇQ å˜Á ÷ŽàÞqpïìSëû‹@Ü;Ò^¼—?(òÞÙgîY÷Ζ­­Ü ÷ŽajNÌUÚÇœ*•IuiÚáD€=ïB¸»ÞƒäØcî÷âJÜ;ûìÜázoí‚ÐG"?¿ Ä=ï·¼åvøËü|B4Ÿû8'ð¥£mß}Á:FÞs)X6 ½j1>— ØrË5Ö¦"†½>nøf¸®AyÂPÏ[XµÑÿt:yñ÷zþÿG¡8q)çEÔEø»å­‰>kSœÀ¥ðâÞ²Þ1Ì¢8FÃYÏ•0Xmô?Ý ®V9%Ðêâ¨æn"űAZYÇò¨µ9)\Ì^šºÜ““"¥]r, cTê{›¸-}Žn©ïQ!H}oC€„¼·% Nù–q)ß²ù!ïåÅleÔ £\Ê{†›”÷ö¯Ô¨îm¼wwN }ˆ{,˜’âÞ¦<*qo ÓBÜÓ‘ºÇHäT÷¶ÄÇœeD*cô KuqÑ©îÁ–âž4™ë˜¨-§@¡ŽÂCŠ{[ÒÝä$1.ŽýMÜËsçÀ«%§À*c›+ªÄ=„W§¶'ÑKÚžîMÉ)¬ëùãÅ8)Œ¡aí÷µPÚÛ‚Jj{|P§¶7@m9œúÐöæ7mò_J{ó…zÇœiÜvLW£àZ¨ìÍ饫æ©ìaÖ¨ì½Hï8±„½M"—°ÇERöò¥¡²w±ÔQ*{ºyS€Êʞ‹±öRöòM¤²——Ke^¯ö²!/¼Hïl(vœž~üöŽNwwä ð:SØË_…={8 ÂÞE·„½|úöòöŽœÄŸ‘sÀ½¡°—o4…½ã !ìåQ!ìå¸3çÀ9< {ÇQPÆôx)í]ûƒöŽiRÚË×|æðQÛÓª!q/ ÷òq†¸—ÇPÜÓå­c@·cTò䡾¡BËySÛÓ÷€ÒÞÑ嘮.g°^¼w¶y¨Ÿ¼—3 ´— ör;'#ØÎ àÅ¢´—¯,¥½|i¨íåý¤¶—#ß9ô¹søŽPÛË‘CÛ;Žéò±Çƒâ^¾Ž÷òÃwç Û-¹¨óÔ;]ÔA€÷x?(i{XÚž>|÷ô-¸§Ëƒ¸§#qoˆÄ=݉{º8‰{ǰÇ0έ}NEu/ûPÝ;Zª¶r”áZy?È{ycJN×GyOo§ä=½Á’÷®M§5AòžÞÉ{º]T÷òò¨î夨îÙ'}º6sóT÷ô#”º§ï»ä½œ&õ½£eçfgºÇ{ß#}/û´œTLê{–5∎ÿÝKAÕåƒö˜g*iOŽ¢=%ÚË–ª jÕ2Ö!íÇs’• 4'ì1;U“Q%íé û#›ÖéÌI§Ëœ®îpæ,°§;z8s²e”÷ßÇ 0î1áR>-º–’•8Áž.F°§Û'ÚÓ¤îoSîe Yé"j ÷ôš÷Ž¿ï—í>¦$Ì)°…¬Ä+NÜËâ¯/yã$ïeË1‡Þã-MÞËsÍû= y> É{ÙrÌ„uÌÂi)[È{yOW,àË>Ç>œ9³…¼”-k¿ÏMâË3‘øø1IâË–cÑ@`ÒÀ>¾I|Ù‡ÄwÉá“ħiÖc /äË¿÷zŸ‡È§B>GÈ—}Ž|8sêzÅ|9ÎÈš£tï¼}_˜/[È|WüÉ \‡+gæÜLâãB’Ú’Ôö˜´<‰%RÜc±„d¾ìCu,Ç¡:ÆR É|—\@)ïåȚǾwË ³(·è§¾wê{š¦¾ûCàã½Çõ¨{7·ÜR÷tž­Ì¨PŸ„{1*”½›[ý™×?Äy\;è˜î¤=ÝII{wŠ}YÌHi/Ï•×6–¶§ HÛÓ¹¤íé(ˆ{¼ b½˜ó:®?f´ŽëG e±ûƒôŽIÚÓû,iOïÂúvýë¸~ Ó¥Ü2¸~I{:¤=½Q’ötnI{7õìsPËç¤íénJÜËëÛÊó!îÝ’Êr ˜øS¸_¬w\Ä=Zâž.OâžnŸÄ=¨¤¸—ç^ëcš÷ò\÷nBµ½û›¶—-9ú\¾§@m/ .Æ ¤¶—}¦âr>µ=N µ½l¡0vÓöîoÚ^¶PÛËj{÷‡¶w§’÷9i{y µ½¹Ôö²…ÊX¶P˪{ü±¦ºwc÷IuO~šÇ 0Žl¡¸§ƒ¨íej{ì"iïûˆçÔrן̓vÆð•ýŽáƒ+!¨µI“úèdÆð½©ïŒÆ£7g=Ò›spG/êcö•ôæœ<»¼9§<3éÍ9¡GoÎ…°zs.zf2üºa†¿½>ga4è3ÁÐÁ¥Ï…|ñgò9-i ®|ïWôž'rüÆ{ ªë YûP÷ä+Þc)‡>jÍ |éWº•rQ€·rîáÉŠøXØ3‰Oñg"¾3qßGâc5Kß.Ç9(®r§B‰.¤¥ ëYs¼$ñéeñ±ºYýÍOd–ê‹E|ŒÔJâc±)Kó$ñÑ<‰ŸJñˆø2ÌIćJA |·>|[tìöú` JŸ/à³p(œj¨Ü ì£|*["àS1Ÿµ@&äïCà+(ú-Þ+Œ}ïY82|.Á{žÂ=[[jœA£DIÜSå*áÞÑâ¬d¿œ9ïÖ+,µ*Ö+,S*Ö{Zè= T²Xø[•¬Ïö¬…~›¨–3>#÷,þ(Ç °¦$`¯0ä°W&UD°^áõŠbÉzéq„z<ó–÷,êâåÈi} Ãô.FK¸·¤-2po¨¨g±ðÝá¹oŽ –bØ›¢¹·<ÇÈ=Jì¹·ã¨È½;õ4ƒŠqö¶ùš)tï¦è¢Ð=æ¸ÎÐ=ñP(|õâs¤ÂWe_¡ÂWäH…ïii¡{&T)|ªc&ܳ8¶ÜŒ!¼aµð)PáS\‹¾ÊŽB¾ Ë2¾Ê²Røj\B¯2=±¾Z†y¬2æB ßÓRˆ¡ðÕ*T„Â÷œ¯ ¾ÊœÅRøj¥ty¬2DŸ½.ೂS_o¯²\¹>;Ž—œBãg„ _­R!UF…H᳑qnH|¾ùkbŸ7à œÂGô^e5>)|O >Q¡ðUÅXRâ«L)ï9÷“Ÿ-'ôñÄXP]ßsTk|µë\Ðøìúp4¾ÊÌ¸Òøªâ ©ñUºcI㫬 ¯*Ž‘_íNÖ‡¬¯61'ç0i¤ÈWƒN‘¯²Ò°D¾gäòà«\”ÆW™áPŸe;¸ÏSOâoÈž# %Qã«3½é… #™Ã|¤3oGÊ>镃 oî‘7ÌFze ãËž}0Ò;F:²†ùHgf1Ž”}8Ò?“Y¬¯°úÏ•Xì'¾P¿½¿8ß¾G¿ýð­}}£~üÒ~Œòç‹õu›aàðÄbÿÁ˜ÿ§Ó‰=|ø-˜µý‡þõï?hc:±6ÿA:±n+E<¤É_•ŒX¢“¢ÖP_y£%Ì ýnŠl)èÓÙ|Òï¡È¸ ÝæûsT¿ì÷Kò½aýîù†õ»c‘×U˜>,ìOã*HÌ5.ÎIRŸYðÑ¥))Uì2ÇÕ•Ñ)¶[7NºâãÌSŽN±-×ê4Å6x\»ÑX«»+É<Ò5Œr•7ÅŽR.nÁƒQG©×¹—zþŽmгƒŠ°…Q0…6ÕSèIJQFlƒ:þœ±L?ÊŠ=Ð`^àQvìæžŽ‚ LË0£TL»–°m2ÍÓ¡çáÆÆæY|ý﮿›íã–ÙÙp5µÛ>n]…›ôQ}ëª0êSX–n= gÔÕ£Ew³n³i=¼‰Äj£Þ†¥ËÒ­AŒfE ž–Å”D£ù –=¿°¨>-6ƒUTñ`´j&¡e׃”žŸßsL©Lc„ÍÔ²Ò'-ÃÌZ«4$-aÛ”J'2Ž3(ƒ9±ÇCÞ²H°£ÙÉZX»âù€ø lµOp'¬°IUÕ’~ZbÀÝÿè1ƒÚW4ºÍÀr£‡!tôî)I™ZæÙãd­(Xâ ÓŒZ˪“àÚbñ\ÍLØñ”z\S¥œÑãú- zXÜÆðêK«)Ýf}Z«0=-öƒ}ZhEÏõ™) s|nŸM©ÝL×6†M¡›ýgzÚ—áylvÖÂRc,³j­ÞY‹a Ïûú³ÀÆWoŒÛ¬ZëY‰9Ë3è7r̘Á¨ôðzZîhÑÙ§±µ°¤Ì˜mùœž;Ê>}úœ6ƒKžK¶9Xr¹¸Ÿ3æð<¾0Ô¹:pÄn>'Y`Æó=ñ9)]ÖX¦<»¸ü~-/ôûì똿ïiñ¸âƒ£bVÿ#àj<ÏÃ[L=ˆwzõé;Æ­§²Æð}æMZk>gZ¾8&¦àÖ¥˜ÃŠ9˜Ä3Ùãâj;žq1¶%ézn¨|ö4˜Ië¹5‹?ö]ͤõœ›Fçqû ̘à9v7ƒÐÚž†w=_¸‚C¦´– q}žCŸ\àÆÞÍ'd? œ8._L1î¸|K!{Ú±§e1ßü°•ÂF®T„†Ãïs5Ê@9î¶üE{~<áö2nLÀ¾íq}÷@*aVM÷4kÐ2¡0.ð^ž[xã“ò,ÈÏ‹ùö†-ÇÏŒ\‡ô–yyåµå㈖¸þÔ*ž¿~K(Îþç¨Â õÏ=Z1£ëWtéfÌznìëóÃç#©b^qõ»±Fó¼xù”qæµk´sÛåfñÂ8Ï ô˜¶[ŸÆ‚›O‹™²¼%<‘gÁú?·YÚò9ºÏÒm ´l+?gOg[ ç>t|¦U·zætw.^Óª[Ùœ¬jOÜ™3°ÍÀƹl ^Æ;FyÖãço¯¬àš¬õ4Xi¥‰Ûÿ,·TÇõ׺ý!5êÏï;&й«›°qâÞ™/4nŒ3»?¥=°vM[)lJ•{Êi¥­À|¼`ÛL>-úË|äçïJÍãùþ\öÿ”7§-Æþâ1éÈl¾'ðÛ¶áÙÚŠ95ØÑgë3 ¿ô³a›;«çÇà3°Íh”¾˜Ö2ùl­´•'ÄîØöÇv*æáVÚÊžÒf¶¢ù,Ç6,÷³Ç|g£Øjì€Ì22³7ÛmßÌ`”n; §Ïŧ߇mž>Ü©>«…§ú¶BǶB÷9,ûãý´âVÞ2cS<­¶•='ûU5´Üþœ¿¿óY‘Ÿ¿MÃߘ‚•¿‰1| Ë ø„]>[†h¡š1Ÿ%ÙŸTg&gyó=ÙŒñ›vçìjX pÛêX ·_søöµ¬¯ÓŠ[=-å¢è1gØ.î{aíœVÜ OüyEm¬Å5mE¶Yi‡>§ÏaÛG |úž{C-u>¼¥4]Íj|TñAs×xÿƯ¸¼0¤Ü%"çò@¯ý¦’0Àö*Ðãv6Ay¯ô*~c zId^1X´z¼á z,$EÒ³lWAz™‘𤗍‰zîñ‚‘—*@c‹sq[ yËM;¢ž\þ…z¶lž¨§â”B½‹B™PÏ”LŒÒå„6!ê]b2Ò^¡<)Ú+ IííÿI{…tÑžägÑ^¥û„hO!hO²h/ä  \—Õs¨˜CCî.О3îÄ0+<I>`ÏÈ•w80t:¨€ö ƒ±#l˜€"[bC4°7mÀ6Ì`oÚÛ Ð¸þ´,Œ2‡Á¾GÄ> ‹yCA{Ó~ð  ¹Ã`3¹,hoú¯Œu…ƒ•Ác•ða¸Q! °ç„½ÀràÕKÐå´wYYc¨t]÷í]•Å}‰{Wcn\âž9¿!÷lYÀþ¸guÒ°îÙ’ŽG ܳ(Ø.hÏ„¸ú¢=ÿÆFCÀÞ5³‹ÏÀ|5â¶8ì]Sc'Ùšv¡%XÏ„;äd=û=ãG Ö3—šÍ–;Z¸ù$ë•‹•+Ézå¢+YÏúàÆ8ë•F=²žiKölÏ níYM6ü$A{f"¾ASA{fgù•´•Üþš°g"!~ë€=sÖÁö¬pس«0qöª2Éì™·ÁävIØ«–70´ä…ZÁOAK¶{­„;§=óñÁ¸g¾B˜&p¯v&’#îÕ9 Kvªù¾ª­9Ïà-·rtÀW½Ôã_“÷L|„Ù¼g»ä˜6pÏ6ɸyÀ=³§`ñ>rÀ½vÁš´×žM Š ´Ê°¤½–w¸W]O‚øÚbO_3Ã#ˆ*ˆÏ|ÞÄgÅè& S° °/âk›µuI|íÙ aäk›n8d¾ÎåD¾çäñg\3­‚–Ú‚Å0x¯Ù†€¼ç{z´ï5_Ïÿš¸×+S÷ºùvî—ú³µ+/ÞëªÊLÞër°"ïu«Ø Þë} ?cæ50ŽM¡Ï„.ã½.ï`_¬ùAà닦4ŸUÛãQ13Vá LàfªaòÞÐÆƒ¼gµõ€{CqûÀ½§…«po™ú4ŸÁ³LVð”±’ý?¨¸g-`àžµŒî™YÔÜór|¨\ĉ{Æ$÷ ÷LÍÔï­ç+Fˆï“”ïY¹Àëà½çOÚ8xÏÍm7xÏ[.pšóÞÓ¢ßRðÞ²Âxºà=_É„˜ÃÍÊÝä=ó$ä€÷lMšÄ;·y3i±ü‡¶|ý˜ÿ›e•|ÏÕì° |³¾hÏOƒ– =kÁ'´gU .ÅioÍI7)ÐÞ²åqž´}bœ ½eÎåd;(ÕKo,hϼØp…F{ϸ «=ho=ûvþp'æ0ô²MÌapÚ{Á@{¦ççA{¶\îùbVà=+·ˆJµÝüŽBÇþùDb?¿/ðcõ?¦Ä ùeu’_Öh$ùÝz I~G:sŸ [8×Rªu$Îù¹Ç!Î~+W9Tµ?Ã`”ƒŸ«c@¸˜‚-‚ =0…ÆWŸ’ïKâ+²ªSâ+[¸¯’Ø¥ñÉ.5>®½’øø÷™ÿØ‹_Ã9÷µ+ÿ¾éׄC09C ûšv¡Ä¾º„d&ÖMö5&ìöµ¼³‚Byõ™xtj|~1p„}]Àì¬Ðì³7öuz› ûCW…}ƒ—„}]ò±¯ÓÛLØ×e±'öIÊ$õuZ³„}y9S°§’Øç§Æ¯Å°/.p]úüáw AêãKOè«LC#èk4T'ôMá¡oò!õ=)êu ¾^t°¯iØgv5œÉ±¯H¢&÷1‰ûÌl À>Ûý¡ËŽë›Fqbßuq"öÙ7 oU`ß´2âx}Ó,«ûľi®¬°uö9ô׾iåÉ}Oæ^ö=}ŠdÀ^ß7‚ßA}ÏA·@ë ¿õ§¥Ô×0…-Ä žÝ:~üA}ÓŒ¦çz¸­[IÝ“úNC†Sßuo‰€A}Wºf€ú¬åzI|æ5‹wÔwÝbPP_1‰ªß€ÎÔ^¤¾’Z¨ï²}Z‚š ð¡öY 8 ØçFfeØçÅÛ_Øg¦jÜ pŸ—|GaC¯9Àïtµ!øYåxÒX€ŸÑõÒùÌ+(ÈÏ,+é0…ŠR$ä>3pc÷™}’¨sßõ¬W×Ké»äzOî3ÛÐõâ¾Ká!ä>óàÀ^ÜwY€Ž î»Tü‰Üg?Mì‚Á}Ï^HÔs0geð Ø¯,z)“ý¬D‡¿²™r‚ðWÞäW°Ó÷Ùš ÜW£È}…Ý8¸Ï⦰™÷™ÎØWT5‰Øg-ذûü§qÈ|öw?d>ûY`çì»¶„V`ŸE‹AžöÙ&ûj`Ÿ©(dº˜€Íð`Á}vϱ÷÷™ám¼t>{Å÷©ó=-Ugð³ªv>bƒûìñƒÀ}—iè ¯à¾ËÅ_Üg¯ÑÂ(Á}õÙŽ÷™ý‰ü¨A?ä>sŽiÜgã`“†!÷™Ã]¡®w™áˆÆ`_ÙŒc#öÙk b*ëâ @}eRW!õY ¬ ¾’Z1¨¯t©Ý ¾4’úì]¼ApA}EÅwH}öí±X$7:`ÐWž±ðã÷ybœÜgVT²apŸÅ.R? î»ínä>kyaŸ½Âý…}æ½Ey.É^aJo}לÚêŽ÷w½¨¯›Ã†˜Ï ¨¯?·“JaPŸ½MëÔø–éáSêkW*ƒA}­1t”Ô×./è­½;Ë­ÿq6±$½òáÌI•$=…dˆô˜à%I¶Q‘ž}À~ =Uféeâ5’ÃezøŠ‚žêHzö]„èç¤W$}‘ô¬*ÕKâK¤LÒ›’Izò}é n¿Iz…‰ìNÒÃVÿJXeŸ[1-Ø”¨­€¨×„@=©XD½Î€_±^¯òïÄFz|’“h&K‡N„å¤?§¼‰ˆzcÉ)SD¢žqh*IiÒäÄpm Þ¤M/QoáÇ"Ô³È~Œ‹)Ø:!¦°Ð'Ô[Œê™ïFí™ ¶í=;aìI{f{‹|ÌR ‡ÎÊùpè´ á/:#°-‡Cç¥Òjôè´ÍÔxyt:÷ héy'ðìi)¥¶ðè´Å¯“í.*b‹ª_|躼)òu=àùžsО¯¹7þ"Ÿ¡qˆ|oá^ã¶-y¯«…">±Â½J›¸pOḉ{r´#î5y% ÷Xc–¸7ñÜ‚öz‘¦Ú¬1,Úrù%î=-à ª|Í(ÃzK¸‹ LV·¢Êgú!DU¨|vljr¡òÙþ ¾ÙPùl9¢¯h•… ï¤R¹xó òÙJT>ÛñFCä»vÿõ¥ñÙNàÏ>\õ%ò9–Ahà î®>@¥-—ˆ|†\0i@ä³D9<:-ä2E¾^4 tÊ.ß[à^9¼3•l[³_.¥kĽ~«pï¹Ã _à^YòwîÙÆ ïpϰ¿TàžÐuܳ/+Ø.hÏœ³±€öŒ;è' •Ïœ›ÁWùÒ´g-ãöê%1°WKʇÐ) Â^2Ÿµàw Ü«ò¦“Ì×*EG£=ÓL9HÐ^•[=i¯69ÿö,d“}0ƒÁª˜¤½JMŸ°W›öB€½* aÏ›VÀž‹ºÑ€ Øšˆ3.Ù™0Êí—Ë D½šÒ hÏ6óû%ô–ðÝ,’(à»ù• ðÕDcŸI×oÇN¡7®'ˆÏZàâóÕ÷ú-ÀXW‰§¿<;‹mñ^ÄWn~íI|±Û!Èa›±Å$>c€;ˆ¯(û‰ÏÆáQA|ÅL5/â+)ó‚øê5U1š4ùì²ñÊù ÃÐ!ˆÏÈwA|u,iv ¾EûŠˆ¯É©ÄgJ.ħÂó"¾‹Â:‰Ïn ˆÏüàˆèÄg{¯·Òg·¾ŸD¾[za“s":0ß]Äs`>KEðRúüŠá3Ê9Tì Ä|›ÅAÉ|–?eœ®þ…Z§k§¿0'ôí.]sPx¡ÏÞBâ[ S-,VAè³ç€Ÿ ¯šç®& Ïü1öKì³ÀT¼& ¾* $©¯Þ/¥Ï^¼Ã@>‹1Á­qækf„Ã1`>ã Ð[LÀ"-ð’€ùÚo¥/?D>‹e‰€|¶Ä0@¾I_@!ßs9÷Kè³uнógÓŠø÷¦¿&¯KÒƒFÒÓoòÊQ/<÷Kæóddh¡ƒgW´<óÈÁ“Ì“ž›;29x2‡#èïªéΉU]ÔF€•÷–èe×_ô‡ø?ÒŸ ûÒùdnýu±éoËáèô¼Êt²¤JÆ„ª¢?qÐâô7äRCúÌM!ú›üÁŠþSx‹þÌ)áMæ9ôVúÒÖørú`–tütðt7AHkˆ…³,& °ˆ…sÄ¥Õ;€‘zˆæU ˆæ3w3P¢ùæ¯&Âù¦68 ç[¢†ómÉ—Œç{ÞãrÒŸGæQ“+°rŒð‹/^mB¹@'sµ»ü³x>‚âùZ“ªÈx>fP@ß`(ÖÏ×N©ïùüJÁV<ßz{xú™|ú3ßÑW<Ÿ§‚þ¶,&A7Ólþvž'èÏlyƒþ,) öÉ ¿¢šØ¤?÷[|Ñ_)’&€Ö¢ø½ð‘¬ŒÍý•ª@6Ð_i4¨‘þà-\ÿ`˜’|<;ÖDæá‰’ãúôñì Z•‹§ ,\Žð7÷G8_Éà=Âß¾ø‹#üm¹ÌþÒ=—ð·d¦!üÝòlü F w×¹Ê9*ø»†Æ1ø«–È0þ„‡ç¥O]<íÎÀß’ÜèT¶xÀßñX@þ ùx&°ùU<}“_éÚ~S'+Š„N¶Áëðg7+àÏ2ZÀŸ§ä{I}¾ÅeKÀßÕ?áï’Žú³Ç;ßôW?¥>£Õú+"J} ’!ý)C"ðïêrê$þ!“eÒe\Ò_Jý ëàëôó ¡èW Gù]Ìí”äǸfi}]ü"?[Àyò;tHi{W‰w.” ¿Í ‰"¿%‡ä·%‚üVçü}ÀE~[áƒ?fL%øUßÀþõà¾}I î3XÀ–>¸ïb”;¹Ž Ä>N´û¸m÷¥R%¥Þ½Ä>³~¼…¾:>âùüÁb }]Q€ú.A„>K–w8xÚ1à.‚k—§&ˆiè­¤Ò§Ð~Qßj":Pß*:”¾•^¡Pú67mI}_*Q­:¢¾­¸[PŸõ©`º\ÿ‚úÌ uRßKê³JÆ#õÉ'œÔW±+ô•)œô5yYú´´ ú:Ãw}öxñÀ}öf#ÖѱϷŸñû*œÆÁ|fÈ/¯Ú: Á|Ƭhä³h¼ß@>ÿò¾Ïn÷x!ßa:òÙ—u"yŠ=‹÷¯Ï.ú«/ßðþízþp[0þªÏO¥Çªö|vÊ£²Óûù´bß.K ¶T#,ñó;Z.dŸ©ç\ǵªáŠm9T¶CY¦çu\•ΡÐv ¥–ªÖ`¼ƒl8†b[•-9Ô¿&OÙ0ç»Áæ‡ò,âLGUm‹P~Hµ·òÅ?« âwû¥ü^‡óŸË"P‹ú®[ã>ÿ¼>þiY¦†’ }#l_óìIõ¢þö£×Ò·uöá8£„STÄ–s¤ìÅ¡Î^Ëòjô×Xhy¥^ë襱ÌÂánÔ -¯±ÔKc½ô3pÒ]ÇXl9ÇÊ^ëìõ³ïiÈmØãðÊØïlfóÌfƬbÌf¶çGÇÈ>6Þ¹Ì~§×·\f¿×ï3—Ù·~?Èeö?Ž?ú}ÿþöûß³³ÓO|UÿðyØŠþ<{ÿÅ‹…>Ø#± ˜ÛÙ3ù¯Ï¤ŸeøZ¿ü/ñ@ÙºùoÏÏøÙ†>høËÿªÿþß,Õ׳¸ùMÿúŸÿb©“Ÿ½¼¥(³­ø¾Æ/ÿç_L"}—_þ¯¿˜Ñʲˆýïù/fWþ€ÿt26Cïùl¬§Éγý8Û³©B26ûs¤õã_ÿ¦ÿýïø×úåÿ¶ïÚ¯æb¡ÿ^?›‹Íº¹Ø¦sø¿ë_ßr±YcŽƒ\lwëÌÅö4~ËÅö´ý‡þõï?hS.¶òǹ؆¹7ÕŽ¬â»ÐäûųÓ>?*oqÉmúRƒw×·t3ì[Þà“iïgG‹{(N÷Cñƒ€jþKß=>Û¾øË7bÏ–êÙB¢Å]é!<¶e.ËÇêCØaz¦"?ëp³ù´k¯5œg—]ûGø –}Ç¿R¤e;é5£Å·Âë¹ô5v´¸Ñc™fÐ}”å`•l}õ·ë-»úR£Åí Ë6Ò·±k¹.ãûõÛ?jÜÇ; }Yi‹¾£Å¡Ì2Ñôf£Ü¨¹µmeF‹c)z¶–€µÍG}Û8f'°[·- uEƒoº·|b&rï2m!÷ƒZ À¶)Ôf-ˆ7Ú6‡ëŽ7ímQ»öÑ2;¼÷ñ¤~.Ö¸baxÚý–{vø>¢Åínÿ®~d}óczP8Z|XóRš·ƒTfÝ^Û7rH¢aqóû~ßD¹éÑÜ€îg‰õR÷²Ã}£…Jæ“^ªƒ)ÏÛñœÃ¾o póƯ>£(Í»¸ù¹è¦sÚyKl½Ý¿¤[ %Ns¢™>2KŒ›É*Ñ'ÈÆí\…ÉAÌqÖžçVÕs·½í\…^ä×vH·\EÑ`¦ê aæ4Kªý>¬¶G`•™ª½ ýÞÍJêûìÂ|M%dtoq.1ß©êWfQš6ÍÂLq%|`¤¯I™îÙù´0øÀ(fÛ4+8c–{GKO¹ÝQ6Æñ>†öÙ²©Ôˆ¶zZ,†ÇÍÏEcûD— WÓí—fyœP]Åylž ?«Jc®rÞ•]žI¬}T]Å eÞ‚zª6‰hˆl5noaбíÞ/?ÕDêz3;Íh@&óên1}Ëã¸5ÏAÒ-ýò¾Ûl𿢝/Ó½ ’â;A÷­4s¦ÚWÇL“LUïΧO SÚØÆcÛ<ÍÁ 9Ü=³ÅÓ²‹çÏåù3.¸·}DK}Õƒá»}jï¼¹Ã÷A –îÞ’O ŒÍ7¶Û‰CºMÁ¦9(÷éïY·4cažïa–í–Ã> H}û¥{Ëd’Ó£Ô6±ïÉô^£Œ`Ã)õÏfa ….š»w=-Sr‡eŸ–!Ç/wè–@Þ.ÓMs~Üꦗêö•…mØ3¢= ûÚî¸ã-0LG9¤§EÞ#–*ÔR.)«ýÔ£ŒDÕUo!äÝÒ¬Áº»xþl” ­tÃ}˺}ôéwìÎÏÝ ôÐìáRósT—µÁƒaº­£e{R¹nK,wžþ©{ÖX}~‹•PÚÖÇ|"üfX¥†ÛOÅPW[©mqß›F[©m¶SÅ]^^Ī›’ìl%”ü;~3è×J(ùw\i­„’ÇoV'°UÝ¿ã7í;+Œ)}{œ§Á– ÿŒÛòä]¼‚Òs*/ñäÏÊ*(ùg\HûJØgÜÌ÷á÷n?fûŒ[*žXzì÷cßq/Í}æßñEÇŽí…¬ü øèìH_ØÍ[:î–ÕP²ï¸ÉØñðìÚíCî%i¼Åü¯íCn§ ³¼eé±¹Mñq¼¶B‰£â5µ Oûgis2¶¹9UÇÍp—b›ha¶V[¬K‘ãWc‹uõYTü-Û«}ȳžˆ'Qó—ÀÿŠza~Þõ ÿ“îÁ´Ó[ЧÊè.èo©~ÛºgÙíÞÒ\îè^öåö/dÕÕ<6o¶ÄÀÓM¥Ý ´h¹ý3Ѳ<üì³½N‚ûE´çv÷n¶¾¿®^CÉÎežeÞ v¿©×óë†ý¾¨T‹Z>OØk«¹@úWüFf•j‚¡}Åï lkyx·{N´ÄòœÙ‰:–Åj«´}ÅÍ·À_›j«´}Åo[Rü¦›eѾâ&ù£¬¦UÙWÜ‚\ý½®îƒVbœ8uÊ(ÝÃSã¨æ¯~”oGªÙ`í+î«~öž³þ«jÑgøf¹›ãx‹q¦ÿ¾ºevóïf­^Ëʾc˜íÏšP9° Ovª “j¥”ì+n+®èV+¥d_ñ›kpµô(ö·£üX›×²r‡•ØǽÍs¬ ’jiLÖŠ–¸ƒVJiãäþ[ŒÍsÂM¬Ú2}Õ˜•+2X¾öšŸËÕö&Áòí|/ôêE‚¾¢Ÿ$è¿› úër êÁ$o{ Úƒaj{¡ £É‚ø94ˆê„¢6̓Ä%„ÎÁƒð™ú­%¶ÞÄAþh ZCÄ’­%ÖJâ ÛÉ€ƒn´ ´†ØÃ­¬\Ú@‘—’&’­% ˆ-åÍ‚GRL° •g€×b°àÕäñ”‡µXðÊ4`ÁK¡OdÁ+]¼À‚³S‘3ý&YðR ²à5振ÓÉ‚—ܻɂג÷XðZJ۔ǫXðZòY ^›Þ!dÁôÅ! “… xÑ%‰ ÈÂL‡ ÊªAe„^${ 9 ù,‚fT ð^,X.´aÊ×I‚…^("ÁB×;‘ ÕM Z$ :Û  ×H‚n¬óY‰U•$¸…^$A·ß} è>`ß%ƒ^Þaлð, ‚Ö%V!‚ µ€9‚6…† ¸½ôæÁ~P°8p«T*9Ðm‡Aà@ëß?rà.|ÙÈn_Œ>àÀ­Œä@k‰L´8(¸™WI(hVÉ ´>¾ ½O$Pp3cQÐÍÑ(h-¾1 zŸ J   \ãä@Ao Æ šIôŠ à.xÙ…‚Þ'¨,¸Yº3Y° ÚÀ‚f6  V| Ú«ˆ‘Íö Gܨ÷)´†;¸(¸k¨‚­¡åÝÊ ôßÀ‹mçOŠ$h- J µ\/´ßwˆ­%X•$hÖâ¸Y Á]'Ñ$èæã ZŸ0ÜÌ­%ܨN(ÜŒÒ&úv(9¡gÉ7)9ðÆ£I¼ã½ÞH¸& ´5Ú-~Â@k/ ´s„ö!õ', t-çë @_[O]о‘¾D ýûâ‘ísçæZq ï§œ¼ÈÚ…‰m=ê/]PK49p³*¹8p3Kèk²½nA[«êKôUÚûmžýE‚Z¬D‚¾Z½PÐ.ÐÑ_(è%8ꈂ¾”;Q7³‡Ò }§4HSaJƒ®ì) 2_JƒŒ²Li°0tJƒŒÙ‘4XèW-iÐ&-” ,) –ù) *¢3¥AÚ‹S¤$•Ò Ó/žÒ hUÚ |cS”¨GiõGRd:Æ”VáÔ¹KMmò¡¤AfrOi°~ àOJdXeê‚ J]AŠ© ŠÆ¤ Nìè© *|Dº`¡W·tAÅtJT¬tÁBÇté‚ÙºàóF® úQ¬5â) Ö¬aP)–% Vnd% Ö­Úâ-ê2 „Ask¥0¨ê+“kŠ+â¶„‚•Y+…s¡`U >¢`åoA,¨¨~±`cþV±`c XÐÒ4ç‘;륋;ã›Å‚ýRª°`§C,Ø»Nl $ šŸòÛTE2 `cg¡`c´¨P°ÞÊõ¬·‚Z‹숂]iZˆ‚½©ÚP°gp:P°+Þ•(Øg–³‰}DW–d¢`ŸŸ²`*0ìLX!|î‚ ˆ‚M9›Iƒ]©@ƒM²i°1™‹hPy’ùƉ;¿¬¢AÓ^48‘4]08D¢„Aeo *`p°œ„`p°ž`p2P[48™KD48˜|D4¨$p¢ÁAßá U½ Å‘8¨¤ ÄÁÆj`ÂÁÉœŠÂÁI­N8H¡!qpòs+œMñààò%œ¨Š&œ N8½‹' 3¢AEn‹ÕNÒà`ŽÑ`ç†]4Ø7%>Ò`~‘BC“2«‰ùA4¸`¶L\ˆŠH\ˆPO\÷ ƒ Y->,0¸•BÂàs»q„A£@?ÂàŒ(’dÁÑÉ‹dAKCv°`oÉ‚»€nƒ&2¼tAâ(Òàæ Dƒ»¶Hƒ 6ç¤ÁŽêIƒ–¸¤ÁïMÂà"' -g¦s“`°!%¢`píƒ ŽB ƒcу}¿ƒ‘“Í%ïë€ÁY9 apÃ&aÐöÿoœˆôNL-‘087ap"Øòdu{৸âkx_ð×L,±ñL¬ä[¬’B«=îx`@X«Ä—ð€Àïâx¡„mà€@´H BËM1ðFÐVŠ$ØŸß>¤xSB”xÃz–b +çH ¼‘²"Õ@Ö!N9ðÆêr¸‡Â-ñÀ@ìf Dº³{<aàE11¥~ ¤Ö' ¼^u` Ô!T$ZæG'1u`à QNx!Ô ×7 ©11Ñ|‡‡è&À¯x „9ôÀÀ+fúÂ@x•Q61N‰òÚ2ob ÷i‰°''6l¸^‹[ø&²`vB Œ¼ /¬ œÈ\¤ Lh—Ø(# é3$ À9)°°&†(°°Ü´@Ъ5¿AG‡ð¿$Ö)šI÷ÃA”ÑŽre0¡@°beM”3’@°R±2²'AÆD Y £A ÈÊj'¾$Á]s}b``bàÆö91E&™!FؘÕZظ/6N\¨D‚âÀFüT:=q`ƒŸØXïX¨ºÚéÚâv¸Î&Ò8)…à’™*)¹%’‘@9!Pi@I–JøåÚ•ž8JfÆÇþA™úH²Ë€±MIÖACÙY@ª·# RICdF *B ,ã% |68Ì@ ,± *hB Ì! œ ×'Ž›AФÀ§O;‡N&à!NFâ‹çÂ=NàÊ“W8éæ, œ±'.–´.ºO‹ëÛ‹—@RàbfUQ ’-‹K0Š&EÜÝ'>}âû" \̃$ |€dx‡2;')p1¸(p‘üE µ‹¹‰‹>‚@ù UO[¨9ˆ]SEÏÉã) \¬) ´4®ÁxÄÀÍû.çPZ„L’È@˜ÄÀ}úˆ÷¤LH ¼á:.ÿÐë¢nH ¼7˜Ix§LH ÄÇ61ðŽbc‰v¦¸>bàˆ‘t}N>½èz!M¯0Ð}i¿ ´†öÂ@/úŠÝC/ü"àzaýH÷Ð릊H÷Ð ×éZPu&ÝC ÒE¦{èEV¹‡^¨ø™î¡ ~ézâ$ÝCÍuΠpeæ€t-¨R—î¡V¹‡VdÊM÷Ð:>DÁ›…+Ó=Ô$ÕêèÚ"s@z‡6&äÚ¨bÊ;´¡mz‡2ETz‡¶ÈE’ΡuC}¤o(mÝéZ±ºþ‰Do:¯¼ˆ>Ó/÷Ððô<ÝCïîØ`Þ¡=¬’¯8Á€¹ô…_¼CGïÐH|8‡Âðt8‡" ùáºc7w8‡Âäq8‡b÷‘<ˆ´*ÂýèàA,"ÿÁƒÄzñ`Ä&â…Kœñ{=xqN";æÁƒñ=y©‚!Þ%–Øš8ˆª ‰ƒx´M4ˆtž/tù1a;ß ¾c73¦0¥9a° â¡ b³™0H&a° éIÂ`l^š Rv0¸¾i‚ÐÁÄ'/aÐÈ 0XŒG4߉àÈ‚••ØÅ‚–î%,XY¿],XY\C0¨Ô»‚AÉ?‚Áv±iÐÒ;¼%Á§OØ…ƒq:ÄÁç[h%lÜ×ÂÁº‘ÄAû|½ã£‰\’¢ÁÆM‚h°1ÿ—h°Q= vút% Ò•4Ø/ÌJ4ØYÆX4؉ӢÁÎ*ìt v¦X# æA¤ÁN‡-Ñ`ç3f|y°3é^ò k*d¼ Þ‹Gù”J<Ÿª`äsú# ì¼G¸ ¢ï"\ðf)xâ ¿þ:iptúq*Z÷*i°q3ZnF 21vF 2ÑtF º§Ñ‚,dÁhÁfäÁÁ­­xp,–ûc° f,¨j d¶çäÁ[¹Ü,X”Ńt*3y°Ñ<8è˜<Èa’™à_<Ø:½FɃÏ{¼ßÁ‚†¹Ñ‡ª +Ó 'Ó¹§,XqO„“Û„“t% œŒõLY5(„*•- œ,~( œÌW& ¬ÔU„ž%îäÁA¯ò`‡=y°Óü%dU¡¾KB³Å€]„“v‹TizIYá âÁAOñà`V+ñ`å§>eAf¥—,Ø`¯IY°Qò“,ˆª#Ƀ6ŠäÁF­Ž88Û‡*8a¯NœØÅ&NJ_ÂA“t¿NÂ!q°ULdM‰T;¼¨RìBFª‚s2fª`Cѹ”Û ,’,ØQq‰.¢p³:\DueÁçKÇ©) v˜oR”¤&YpÜtå¤,8QÐ&eÁÙÈq”’ë§,HTê‚3 Ó½dÁë- ÎI<…,Ø?£}ܸ>Ê‚ófŸ|D[–²àÚQìÔY¥ 28Uº`G͓ԑõ!ü² µNÉ‚¶”‹R7ƒ•®Z$b;Ò‘uK¤Züg‡£Ç™Ïí£S•~tØÏ§ûvYj8³¤}œâoGKfIk£ºô ¡Ôp Ŷ*[r¨n¹÷}L› ÇPlË¡²åÊIPz'6œC¡íJ-ÿê4p–RsÙ þQ¸ký~¾¶ÈWÏÜnŸ ÝžÞëGyàîΚ{ÚRb£¼+>™“ëïåp“å™+ãÞ0Йá#e/õÊDZ2ÃÇ:2¼i,õÒXg¶8Ž•Þ8Ö‘áMc©—Æ:³ÅñwÞ0Ö™áM?ZõâXÿL¸ºm fál?È7þ(Ü·¼?Ì÷;½¾åû½~Ÿyà~œmðîôúþ1üí÷?hg§Ÿø¬þöçÓ©yF{ËBùÇéÔ–Ò©½Òœÿü·d¬¦(z×<ÇqØ?Ý6ѬWøâ_áNѬþACà)䙦 up[¹™¦kÔ5+u3aÌt»B«…iºv,¹Íò6/Z*ïhI/ ·Ð6«PA/Œ¸ÂÚ醖f%† <ík5é‡þiu…á®âÍjÔ4ãúnØÝ*|BZ»hwC±âÖJÚÝ|oùì>iwƒyøi¡á iúZk4¼ÌÓ*TÜÐòãµhƒ†·è0ÓêæŽ$­-ZÝ:âV·A¯µV7¸·~Áê6@6ÏæV·TÌ­WXÝ2 ?-°ºMTk½Áê6Pç®õV7Ri³ Ï *«y6Yà5¤-zf=R¾‹ËÙ°ºYõgoˆhv×6 ŸÍ;Œn ‘¨mÝŒÏ&F·ÍßǨ°ºÑÝ®«ÛŠ‚„mtݘ°££ÛFEß6| d“xžln66Œn7Gðµ2Ï÷{\Wœ¦Ûýü.†U¤÷u´Ûý|ІU.òËï¶BÛæÜjË;Ôw« Õ¢ÁWœn¤š¥æµ NoènoV©FËp{Û¸ !u+Xô|½‡UŽ3/ß$ +ê_±n%y¶Mðù`Ž8Q@ç°¿æÝŠTÜ6mªt[ž/›d‹Šž5x†Uk½£Áí2Þ#æhéÑ[‰‹YÞàE¼†í3z4 ·µy¬ç‰RSÃ*t´hYnkVÁÉ¡¥—H2ëãÜq1·ÛÆÅPˆ^=‡„쟨^#-æ°-¯P½†cŸO›-nl{†øÑk¤uòYöèÓÝÚæ§òd·êQÝo(b«º3‘ëùˆúO·[õ¨±£O<Ûkω–92ªŒk† ±·ÐZ‡YÝÊØ­xÔmóÜpùêÏâüåEÃ܈Üme6³ú­þIí¶2—‡Ä{Õ¢ß _ó{ Ä[bNV;ª×˜ÁŒq–?ÖaU_ãáYñ¨HÝÙÇ2ÀìèãßÂnÅ£ÖŒ)øv¬÷Phýškô)nmVÝÉÝVçË2«¨1½{¯qÝ(ÆÒmq.vª›ï’­ÎÕ’¯_((Ü­~”aòŬ)½G]F¯…7£GšãaæÐ}¼ˆ×¸X˲[ù¨iÌEª•nÕ£ÖÂ1#ZÜÚæ-¾±êV®âyÐVc ãÚâ|Ù™jO·ÕÙÈ·…9Øê\ìTöKŒ>aöÚl1Œ•ÀšÑàw Hõ£”¸>«€e³ìð6ïVAjÚ™Þ§×ð•L»ÕZvžŽd"ÝêGmï‘¶[¹ŠÛÏÔq÷lu¾l–RxŸQsuX ©-ÓCƇ{ñ—t†cÚ°Â3qªíË´—’‹c¬äMòBf·RÃÎÄ !Ý HM›%+}w+ µüL?ÄåE¼üvú¾¾[©m-¡ºZ‹ÕÀ²S-ø^†eí>ðŽï¶8ûçû†­ã°ù Øïg³ª½!°}ƒÀ`¾„Àá9!0ö'œkxR`À8¾A`(˜Ž"DÂìƒá|” ¸¹“"1X" kÄ 鉗h-AsD@úÝ%²W" ¥Ùú:y èÙ²¢e13<6E€±Ñr33Þ  G³|èé±¹*s!Õ¯ÐCS¾þ[ÚN“ÿë^‹ÿ<ïÁמŽ*ZÈËE’#þ­*·øOIµÅžíéÅÖ¶#ÿ¡ÌRâßu‘Óˆ ”'þÅVîÄ¿«…Šœx!³tà… ¦I€7™$À >”I€O—ØŠ­_ŽÐ¿N,pßHdí. ¸\hDÑBdô}`édM`YØ©Š ±QXøZ‹+r$Ö¢ú]„8˜Èàõ$@s銃H€Ôí“ôÝÀµë›ÿ*r†&ÿ5>[ñ_Cb¬ä?“ƒÛÈ ۅ俆âaâ?§¯ÿÜYÇ/‡øç]gFbE'|„¢ÿÌO<üóàO¿âŸGC:]8 ýÜ™þë@¿Íý,ÑÏì ñ$ú¹K Û ÃÅ·‡èçRgã¢Ã¢$…~{üuŸ9¼ûB&òs…<à äçÂaÐaerfäÑù¨Ý1ÈÏúÄÓ%ù™{ö ~ÖŒ ðs_ñ@A€Ÿ™4p&€ŸýO@ÁÏŒ;àêbnf.Áooì£~{#ù·ÀÏŽŠÛNòóìÑÑô3îxIˆ~æ_6I ŸçËd:ý…wvœ|3;3pŠôçÎØî¦Iüs³FlÈ€î3ûàŸ:Z@XEvfîìÞûYð_øHÇAƒÙ™±îÃû:ŽZÈÎ\h@ô¬ÊWëÍìÌ7èîBrfËáxWœÙ~ÆfÉ™kcŸŠäÌ "ºWr=г5¿0Nõ•è]ʉ€añ)Ý÷Ú3DÀ~wdeºu À*HÏÜaÉ"ú¯µŠôÌùzˆ€ž‚ØßI"  ÚHÏlgˆ>þ÷Éðˆ€n?‰,Ðûì8× |«jHuÁ Ò è×ÓÅ€>ì?á€?®°YÝàO èâeÀ"Ä‘ 9“¿½ PrÃÿÞÌ;Ñø„„ÍD@·- üï|¦‰€‘¤ø+ ðé21« @?&.詎ÖA€ýÞ|ÓA€ÏQP4H€n´ÚѲá¿&ôÿû›HìVÑzøà¿¡!ýTAaþ÷ îö$@7Y“»ùÕ“}àG>-ÈJ ÓWœ+¾…n”Š{|ŽŠ\šD@/€Ãú4ãKA¼.D°ˆ­îj|)È€fƒºO|ÆÙä;0 Û©âT`@•ûZýÖø Ý× ´qö‹í bA~öÌ ¼.dƆ0Ú0qL@`·åW´½| #!Pw‡¬[h úŸÉ¨vp oO¼á¿F´ýq¸V‘}7ìÛ!r`#>0Ðó-½0ГO†‚t¿wȃÁ¶k AЧz¼À mÛ_b )L!¿MÔ ³?Iм—b T‘ íή—è{‘ÀG ' ˆ ‡&øí¨r¢ '¯‰ƒ¨>-hRéh–jà@\jªÌR’j༨âQ œuI5ÐÆ h£86‘jàÀCŠ øS pãH1pL Gÿ'bR œìG5p"_ªt#Kœ•GœLdöšÄÁ‰„^‰ƒ“ºpxmgç’ 8I°ÀA3ß\bìç¢DH\ðºK\…ØF\œyÐ"%"`ã+˜[<8;eDòàlñ³N´„;_'.d¿?Aø'fâàä.\<8±«LÔÝZ@ë¡NÔiJ¤c"áägHH8‰‹H8Q0+‘pÁO5‘pE­$Â…ô I„ á󉄋Æ!¡ä"!á wÈ$ÂuAÎ"2Ø6‰p!siáD¹¢$B \‚ÂEf.J¤ÂEÅHT¸¤7©p!YRá¢Ã†¨p¡¸MRáÔ‰…kĈ… K Ê=%>ÓŠW)±`¾Ô@¨Cò—yB!Î#(¤ËIB!k1á„•L8±ÏK&´pá—è)˜‚$É„ ¾BÂ…Ú‰„Ö§".„>$ê êá$®•‘D¸6•<ኂB¥Õ,×S " ð. tìŽq;²7û Fdú ôÀî8jeD6Z6#²7åIz«.„‹èCÞ+ŒÈÆ;+"ô_YHu B;*6Á$B»Â@¡Ÿ*0DèqæÑ2é %A·cÔ89x0~[š9$ìÄAv¡æÚàÄA¿/þˆƒò›ÚQ`ÊÁ´\…Gý%Ž­O<9ò uJ‚qÁÁmÓrÍXWŃúÙ‰Ýý%˜ @¸×Må.€Ð»|<è?çhZ—°©ý·„TN0ñ '‹q‚÷¢¹„<èß1ïBô¯_ô)tÀ_„ú¢ ýTvB»œ Dð GÄ0àAëúz•¸¸ð ñÄÀàA­òBûyÿ®_éÌt¡·ÄÃúJsFðÄ ­%ä½àÁØÅ0ÁƒÞïxз Á÷àÁˆ‹Súvð>y0¶ê>yУ¨î¯äÁˆrˆ>Áƒ¾óÝBÃõ>´<" mÎBI$îù‰€ˆÿJÜðÍnHTI€î8ÂU$ðFä1Iw­%ü;‰€7R$ÞôËšT K´ ØéêGÅÀ$@ÎK¼QL, ð†-? Ð\•N§PÏãUO§P?*ž %A‹ãñ9oâ€$Á€ñß}s êb S¼¯z ›R¼š@¡^“>¢/ú]K4B‰>Ô¯ ìÈÂk©2¿ZêÒ·¤8sJ,BÊj §XûPzà…TtÂ? ˆ8å@èï.ÈÛ“r =Ò8 øgÎñÝ þÝLƒ+ü3Í?ˆî]ðÂ?;Wè²Ä¿;ÞižD?#7¥À¹E~¦q×ùy âùY(DP0ÉÏ¥ü )vxìü‰Ljzµø—KèX}¹„vd“8]BƒºäJ©&=BQßáð¥Ø8_èuU_è5SÃßS>¡Œ¸IŸP:]&"'ÿA´Œg\ ˆŽÈ <1°½Bíj܈ß;0ðzÊF”À KÌAåÃ+Tž ìdG ·0g\àõr õ:G_'V†n‰+|{’Ã$´ÀÁx dxM†"›µ8°lʇGX "ˆåìˆ dàgÆN²âXßq5iaq’XŽ)¬áû‘Ø+ã XáÄ( l €¤ÀÀFGLr` ñ#6ŽJlSŽ¢àÀÆû'ì0X‹™ú#9°ôÅ¡´â@S½ãÉRžÅ?F`',mј/¿P[4úË/Ô\ÇÖKô£Þ¡ó†¼)Ìß‹Ð8™ ÈÄ ‚›¯€@pQâšlè%!P~Ÿ;|S $•¤Hé>•@TTÌØ@r26*®PðF¹?¡àÍW'¥ÀÍ@;Ò ™ºßΡLS™4ø<{ˆ¤Á £¿hð¦…M4¸±”$ Î 7 Ñ Ë@$ Þ…?Ò ¢4Eƒ÷$¢16°£,Ôˆ*Gl "Y26pÐÏB±…Ί ,ð?RlàµèìÉØ@VmÍØÀ‚ê€hëv@$c CnXˆ½Š ”±I±eÞ36°0±¬¢™Á_&6þdIƒÉ}‚o}à(OÒ ]ßýÒí:à .Ñ¢Ð>zˆ¶&> Q9WÊC´.¢=DéÛ¢\iÒC´¢ªÄá!Úyrzˆ¶ a„ ”;”BY£0=D7ø¥‡¨½Š¢ަrÝØçÓA´“‹å ÚR¢£ÐA4ç0hs‚ð(Q°½D;ª±§ƒhƒ_˜üC{ù`AÛè•3DЃUË‹íÝx»‡ÎÍaèjÞ/9ðîH]•î¡ã‚Ó\º‡2ÀIî¡ÊEº‡NÑ߇¬·{hç‹%÷о?`ÐnMl¾åú|;ëäzQ ¤{è@¶°tÝpÈJ÷ЕsÓ=ôžu!x¡ÂbÂà@E¯ô(× œù‡N¸¯ŠU;¹‡F:ß[¸8È÷œ8XÁõ¢As`~Ó`'Î û¤ÒGœX¼Í#ðë¤Á…êIƒkà—*Tð©h°o’'qðŠ"½IƒŽBIƒzÑàh2Òà`(¬pðBEÔÄÁz},Ø-¬ ¶ ¡ ù»F¢àÝaäJÏЛ±‰DÁvQ°# ®öéZáò“8È*RM8 ¢$.TbK¬Œv¤àMlämñ`Åòr$R­#´ ¹{V‰,JÄgF´NyTvúÑa?ŸHíÛe©áÈ3öyŠ¿-™glØ’^kUÃ9ÚŽ¡Ô’CÍç'þ:ñ†æáËVÄ bÜ56ƒ°-ÇÉ–uò´a»©ÿ yÚ·$g‘<­ Ñ>³ ýK’§ýà5ˆ|²G"«¼‹½ÁDÀ>'Ó¢q 3-GÊ^ê쥱”MciÑ4–zi¬£—ÆRZ4u¤EÓXꥱŽ^z÷•ciÑôCU/ŽõÏ$O³•¤{6ù$O[”<íÛóþaò´ßéõ-yÚïõûLžöã·ì<íôåùþüí÷?bg§Ÿø”þÉÓF}>^–»ñ“§ÍÍäiÏ¿þ0yÚóÿÿ]ÿbò´ÒŽÿþÙäiï3ýýÃÿýG)Ó2£Úõÿ}ò´çÊ}͸yÿ©Mw<Äáפ0ú…ðëü £„_oüöG¯ˆ¿Þˆ(½Eüõ†5gôyïÝØ-ñ×;Ž˜¾Þ‹‚¯7¢kFßadsÛk–0²)Ûè÷F®QÃã +›¯û6vŒV6s,ŠsHùå-Îìã¹Ç±jS£‡™ÍK1úÙÇp3››pýäc†™Í« ú%PÝ>»â f6DËÙafCÒkk ç¥tÓÓóm¤WÓ˜f6: =熙í‚oט f6˜yÇì°²]¦Ÿ3¬lìŸcNXÙ¬úaôYp·¸6=憻Ņ2O Ü-.hýcÞp· Ým¬ V6Ʀ?7V¶‹e3—綬%þWƒ‘­@Õzöó0²1T}¬ÁZØÇÆš0²•ŠW`-ÙPp¬ ­áÖ{„³ÇoÁîõD8»ƒËpŸ#÷ÒŒ óÎÙðÒ‰.Î.ÑúËWV©ž©ø+üx¢Ë€‰­lži"é½Õäó† ›mÛ} ^×ÉW®ø“e°¯X݇mäg4øßmn]³y¿z3$-ÔØˆ[g!¤n]«Èå=<®ÓM݈D¶Õ¿à ä2Œ‹ ëADË„¯E…ÑiÜ ¾–,ξákQÃp1ÌVÒ‘úŠK¾ákQG\Î4 Ë„U=J¸ZX2ÿ»ÂÓ¢Â&1¯O‹ZF´txZTø†LK`Äd÷þùœ×„§QçùF²û ZŸ×†£EEf…éY{àŽSÝp´¨¬§eΉ¢%‡¦göiÑâ¿ÿY*-j®OK3³àòäö„Y:<-~Ór´Ü8×GÍLvï¤=-³K-£ã,žUh˾U´$.ð†«-}³^pµ`ŠÃY \-ÌDçS¯u(ybœ¼6¸Z4”IžµÃÕ¢5<ð´ ïÑóUƒ§Eƒn9ë‚§E‹ulZÝ çÞp´`þ­Yo8Z4øÀ<8ެx0[£“2<[ 8Z؇4ú48Z4ÔJŸ­3Ù= ÏWž ¡ü³Íð´°U1ð‚§Eƒ'ë´Åù©0ð†§Ec%'[ýóÝq3ûÅt÷0 Ï^àiÑ5ýlÁàja}üîô_‹§eÅQE°G,\³¦»‡gíì“éîãÔ Ž6Ëhqm·ÓÖæ(` ô´¥9êWB³ž¶4‡§ÜŽË~VÆÆOk ÅÃSnÇB÷,Yð³0c£¿X£ÃÑ”oU¹3|™˜c%ψêËc]Jžá_¤ie¼nè]1‡±Y›e°liFCüzçŠص³lio9d°|–T¸Z4T,™³ÁÕ¾…ðœžö¬»3çOûÆo‰Uò g98Ϲàiß/ž{ÁÓ¾!(xZ)¯µyâ+e+ó…*qsleö¸Õ-🋭ÌçBé Wû~Å~r®Öå,çv¹z“³\Ü®5àjO‡ºiµ¼Â[5#§Õò‚·\Ü.+åµP<È OÓƒéQç7Ã<¾oļø*4mufÄ«kbӖ܈xEÑtOO¸êÅA ®öÂüôZ8æÅ]öâ-~Å^ÖkÜ/“æ&ÓµÞÑWûŸ¹wؘ}pš÷ŽÂ;ÒnNw™0{6 xúÍñ {-rŸŒéÅŠ.~sÌœ.5FE½’¯ß™Q\^ïeˆz%ØÂM‹©z% ÅÅÍ»èÔï ÷Š8ªÀ.+äåð¡ÿË yݨ­¥¼m‰ŽâFø ­+ÊýE¹£¦7¨ÜØÆ/KyÈô·Wôñò'q½Ñ°.¤¿Eì㺢fÔ&‰Ë±|Z¨V²ârî®ršÅ²LkUY|`+ãuÇßîY°JT‹J)Ñ Ýë²zCoˆ•Bqœeës…‹e”Ç#{ï1iý¹Ìio¬Ÿ[Ú“ÝNôwò@Àwþ@ÀJl±¤œøõâ?¤‚JþãÖ9ùƧƒÿàgq ¢üñÌ„#À8ä!Ü3džDÀ GïD@ËÉ-DÀ,ȉ€Y „€{ËD@Ë÷&7÷&m©|'n&c‰€ž¹- è`4ôto/tÔý:pÝÄ%" ·Ì½FcôzÆàO  Ãoœ èîJw@@à‰  µÄC_QúþBb@ÿàû¼É€^ÎñÅ€Þâ7‹ èÂ-Ò%L„@kABàu±…x!„*!é;/h²Iî± ÕeÅ€üI’/$êN¼hg^pI¼©29ðŠ`Kaà…l—ɶּ9ðB:ÂäÀ ‰Ð’/D!&^¨8˜xÝ<ŠXi•XJ09a6 ‚g‚ ¾‚ÞË"ÁךDÁ—ÒDAËb÷FÁ‚𾉂–$Æ! b Q°BI‚Â’ òA% øî% š9!È‹$X i' w ÚÆÀg%4¿Ó6‘ wx"Á²H‹$Á‚„°I‚…›]’`¹yÉ$Á q/I°ÜØÂ‹ r2% n&E‚åÆE$X‘G1Q°–O¬(˜(Xár’,hÙ¥ã(²`½xv²`EG± MÉ‚Y'“+2S& ²Ši²`íl! VäM 2QX²`E.ÈdÁŠŠ¸É‚‰“+µ’+t”dÁŠÈúdÁŠ\2É‚•/˜XЬ#ÑB¬$G¬N¬ønƒÍ,8då3¸X'2­Zâ Yj‚ȈƒÌÕ›8X‘».qƒ• $”‰E¤Aî¤ VŠzùqˆƒHŽ|ˆƒxâ‡8;ËA„;ì,§8Eñç +×ÎSŒаÁô%Yeq°c'-$¬P³$äŽ<ÅAµ ã£q"aE|ˆ°"¡Ä„[K$¬ÜÀ¥8RoaƒµãÐiÖ>µÁØð¦8ˆì‡8ˆ<õoq0Ž’:ˆeïPþ{Šƒ_ 6q”A>–¤A>º¤Aä9hpSO RÏ–2HOeT”Ê ²þÊà"œžÊ`ž”ÁNïPãLe©÷eØ›Ê`#CJ¬CRä“JqFˆƒ•)q0r[4Æ<µÁØÃžÚà-Òß$Ø`<„ACÊà$cJ„ƒú¡ Nª~R®N æþÔ+,.© ’˜éûÁø²œ Õ X‘¹M hb]Ü! }$Þì#Ä¢y€ày'RMNÄ ~€ ߢÁþ Þ¢£AHé+9Ò—8°àçóGÈë¥ ‰I„oס VÈú© ’¶SŒ¨ŸCTé‚p¼?0ðæÉ¥ F³ƒùQ¢ ÏA7º$B {Q`™ O©Fxã!öpÔ;Ä@ìl5pP0¤8qR¤1"åÀõë‡È‰¼¿)Ráú]ô•ç~‡D¿R©ýRÅ#ú,†‰~…6—S ?S  j`XsN50,5§¸ÞìWP»äTâ$ÂãE‘íô%Mœbàýò -p©è"5Û¨S „?ç¡¶5ñ¬/5ÚŸÔ@¤59Ô@:÷ ý “jàÛ)´ˆ%ÞØ¿R €’Üg¹4B擈.É},·s8…^ŸàÇŒ8‡ˆúso)0Z$ ˆ’ @ù”Z("wÛK Œ{,)`r*×7%0úý?ܽϮîH®å÷*gX5èmE„âß Ø“Ú@>€qíQ¶}a྿Er­ÅзOe¬.ו£³™RH”ôIñã"åëZ±ÔK¯œP¬G~È€75HÉ€ç&°â@‡ 8ß¡=I’Kª€õ3#´ÞLæ” HŒWê!ÞÌ•xS 3üSŒ1Ä|(—8@ê©vÐf*€Ñ@æ @榦8(îIĺª‡HüI¿@q_EwøѬàP¡Nð«èÚàW9ÍøU´³;Ày뿊>/ ~ËÍ$øU"°ÀmüÒBð«ÌøÕIMàW±žm‚_¥<$ð«XŒ8Á¯¢œ>ɯF‚`‚Ö¼JîÃâZÉ}k$÷Uæî¦þǨ„¸¯ÆZ˜‡ü‡Ÿvª˜àêÓãSý£z›ê‘NÔW˜x*ñ¯à)Iì»I†Ä¾B QØw½„}ÔûOspcÉ}¦ø‡ò¬CüÃêî‡øwC»MñO§#ñLq_cJ«¸¯uÊtä>v Mî³¹hhp來T¢ä¾†5«“û³'Å} s$_ÛDÃü€y?"ú[|g„ÞH;@€H‚îù~Hì8ȯ|¤„2%ø.E‚_‹øÔŸhžv@ ç½²B'õ¼#+tEž¨²B±ÌÛ«00(+³BQ°pd…vä›fV(Š¡2/M€2/trå…"åþÈ ÝÔ™º1gȼÐ-u‘y¡Ë&e^èf™’òB-A1ØL¥H–ËÊ@HòGe Öö8(}Æ äœU"àõM¬L¥x5椊™™Èʤ@4“!4HE-)ðƒ©>êÅjRñ!N° Mÿ¥¢(Q æW‡ˆ”‹C¤.`g•%À‚X À‚µqÂÀÁ¢?’ͳ0Ý@«pS ë*SÄ +‰•Õ¢ÂÀŠ’©ÄÀ "9PUrâÀŠ.éÉ=ÄÄls—X¿i€*­V ¦YÈë—厪<ÜŽúÀES}à¢ä'0¢[‡ˆÞ‚‡ˆÎi‡¸™* pS9”ˆ•C9 Hd½ÁƤA`C—[`nB´aÏH‚ )+I‚ì«$ذˆX’`k(=6Î&6¤ä'6Α‚RJR¼IcAVÉe} VßJTBTÖbe­ä@© âÀ<”ê™å˜õè[•õ7õGÕr:‘õTN 0ž ³¨RŸY¡­Ó™i•`G á!Æœ3%@F¬SDðÐY4#I=‡ H9 Ç[l,$üg 5”C„ÄwÈ€å£@pâ>œ2àõN mè¾tÈ€Xåü'˜!e@Ì£p1MT2à€î›2 ò‚pEpé)‚Cìøq5‚?N lâ-©€J• Ý…Á³—8Þ¡v©>*ç· A^àÔY¥yê€ý£BÙô¯ ÁÀ6)hMw(ÈE9”@^ÍTÑàH eÄE)¡¤ Tç·”P)§ˆB—C L-•XpÙS ää?•ÀÂÄM)…jœ”ÀñM DOìC ,G”ÈTy!!¾‡È—GJ7’~ Ñ›ôH ½¾¥„òš&îoPHÎM(ÜP¢ QÆòJ 0[R!_§¸ÞTˆ¦²v8©)½¢B&!'ÆzPbíC1aEƒ ù¼%²L^Lh_ò/$I!!“? ç×[ lˆŽ½BÛ»F°A59ˆ°!OóÂHºL Ä´"ä›@ؘ‹*ì8;á ÖáH¬Êî$¶Hí òƒ˜,Ø0eL¤t0Ø.h’‚A&ä$ V,brtN›³±®,÷ì}qÕ'ˆ[œ-Ð>6ʽr£ŸíöëÓ–µ’n; ÃÑdŒ¶ì_”–l2¶¬W_ð#†¢á ¶c(Yr¨m ³†Ñݦáж*-ÇPwÜæІs(ØŽ¡dùgwQó•¥ìŸ]ÔÚ/tF3øi³}ëbõ7·½û_ö/l{ÛšíÕqí³íÖ¯4_ûö€ÏiåÁg¬Ÿ<ÍV@qnÂQަj1ÌÙSãäFèÕž#eK5ŒttTÓHÚˆ#ÍÙ8R6TÃHG?5¤8ÒÙš¿Õl§#ÝÔô×Féi¹6Ÿ»T¼×þ¿N˵¿ÿ*ýíÛ[ñgoÎß~öÌ~¾LúÔ~éO·\›¶LÏÿG ×îküjÃ5Ûô[Ã53þ_úWÑ¿†þõ­õš/ý+ÇŽÖkÏL¸¡õš?[¯™í?ô¯û‰­×êþãÖkÏÏ‹µÛ¾¤<p(vþöY¨‡/êˆÒí…çc‰Òí…Ų¦çḭ́ĄǗt@ÈÕç¾Î¢»ÑÁ+R`u˜.éÔµÇ6 © ‹áMï×jøÛÜÈÕXÀ£iKÊóÙ¢Ñ몣ómº[ZÄèܲÝrGŒÎW·¼Ã²±ÞeýŠúŠå.kD$Ö5&–»DNé4Ë]V޲"DçKÄ6;btÞ¸Îî÷*WÄèÌâÑ¢UJÄèÜâçWB@v‹Çßž‡-btf1Nô”qKìto¬s‚(Ù²7/×9q¶|ˆkbDV™#Ö9Aqë*«cÛ*ûÎå.}›z5¬s‚ÎÃË~À±ÎIDóŸßBÅj—è÷½j+±Ú%–X5zàDû–ÑyöS©GˆÎûó¹aD„N R«Æâ·®”ØiuäÚ¡Úïa¦[Évñ˜´+Bt‡¥DˆÎÇ KD”c¿Z­EˆÎ3­ü”Û!:‹Kûä±xˆîØ©GˆÎóªÜ0"BçÉXq¤X <6‰QV‡Ì‚~‹XÝY¢)üó*iPY°ã3­PYvÈÔ¨,Èyð¹@fA)Óºï 2 ¨û±lÈ,@áuwDè.ô¨_÷˜”Y®Øi"Bg%nnXÐqÉ‹çU‡Ý…Z—Õ/è.þ¢{A€ŽËÁ>x:6†X½!@g“~?ÔóÊ‚Æe+ÙÎ_´«÷¥Œ+ÆÐ]¨E_}"@ÇÕ¾žw1t\gvõÝ…åÏ׸ »µFA€Ž­רÐ]|YŒ†Ý…TÙ5î+vqn}þD€î‚6¸FGŒîŠ©Ñ!º ÍúŸ/Bt’Zcu¥ÛÕ8òFŒN–y5¥Ûyä`Í‚Z³"FwA¼\³]Ê·s\,ˆÑ]H$_ö…¾p,É-ŸÅþ¥-†Sí7vì4£»:^]í7üRø[er~Â~MàfÜ^Ïe- »">w!Þ¿¬Ù»»‘tÙªù‹®Ç.kÁ¿°M|=vG|Ž5…˾КŒÄ[Þ¾ÐMFâÝ ñ¹ ¹*ËšãW¤½úOñÁvÄç.į÷UŸ» <ï«">gÒ]lÓŸ³mFX¶Öªò§bÛò_(=¼c“ŽøÜ…iѶտ62ý•³í#}¡±ÆÁWךÅ#¶ÙˆÐ]Ññs—«qÉb¿Æ»è.t zn tii—–,޳) º ÅÛÿšgRè¶ØËBßËmË-d…úxÛò_‘1EvYÑå6!ºkEµØ¶t=û¶<bt§ÖˆÑ]iwmˆÑ1½ó± HW¢cÛê_ª—uCGŒÎÚÁİ1º‚u·-þ…RÎx(lñ¯ KóÝÓq\ûDû+ܵmß犼׸+­ åqZ»$”ûûû±lå˜üív/ å-¶éB9¤ómKMøXb›Ù!”£¶eÛÒ_›Nºa£ìÔß—û޼éÕ÷¸£´5KS÷)”Q¾êƒÜíB]¬¡ùX¶Jeãy½Í–Êú•¸ûD©l ÕeÛÂ_ xüžØº_¬” ·mÝ/Vʆa7Ê¢Zu÷HЬ\߯>Ïn@ȶ¯sÁâ^Ûç¹ÎóH½mTÊ¢I­0Übůt_{AàloD´[žIXúè @'–D@ô¿=Må± Ó€7AMQ÷@@¬"r ª¼A›"@æm%"?å ÀŽ3b=íƒÑ;ã @|íD> Ÿ—ƒQƒt`G<= •îv$m‰¹Èlà‚@•¸™H‚.„rÙ<.¸º“¸Lš¸°æ©p,Ä€ EÉ€Ö•.ø“ ¸ &j1àBŸdÀBM"àBuj"àÂ1Ð,10ð’×$Α¾ˆb@Û)†!2x ¸P:— ¸ÈŒ¸PöŸ ¸P--\ø°&reºdÀ…DÂdÀµà¦ ú•H´\4Ÿ¶ ªÁ-ÞØ%ÄG3!ÐÆ |#.òRBàÏ¿ pmLö±÷A(3:(ð¤,)0>¾¢¡ÖAX^è @´ê:(½a Do½ƒ‘¡rP òóEÞÑð¤@ß$†š%~{Ä@³3=üÜ ´ÀIœ 1Ð,q(` Gd^èÃâµp€0Ð÷ |º%öš%ž8b Gƒ‚A"Zü  ô¶Œ? ôàO (pn¬% ô~AŠFsCÂz,(087Šz$*úÙ½0ÐÆ‰—1ð°=>à ôØÏƒÈb'P ïôã€@7`2 Ы!ÃÔ ¼‚@pÅ¡½zQàä]ÂÀ¹Ñ}œèçø ´an@ß…H#„¾Mì ô†š}À@_ãÍÏ(9ÐÃ`aš%XŒèÛø8A³ÄW ¨ø9Ðc'Ú†+ãµÚ…8Ѓ^108Я…{NT‡Oq §êþ80Ð ;€è‰ ÁfÀ@Ïæ 0Ћ1ƒÍ€¶ÍîŒå¨pŸ0ÐÏ&vÚÀ± (ÐG (Ð6‰¹.)0 ”ßÂ@w*ð èa:?=b [†[¡¼ 7P Wp¾(ЋãP @Ûi;‚=”Û€}àØè{ŠÝˆ ´qj]P G c'P _œzöm(ÐÈ? ôQADZí‘={;Ž ´ö›/|/4ŸNdc؃L¼.rI0Ç æ% *›Çñ/<Ðúò‡WDBÛ)"ÌMH„f lj„–¡¡bê "´}B1%®Î0‰pu,%!"4KL I„¶W@#€pE%Ê„f &#ú2/ \\‡\@h–˜Ÿýò”m›˜ä}¹PïÍÔA 4K\-¡Y^ª ï›€„¾Ó Í8O 4Ë Úâ „>NˆuB³,X¸o^ű( v,$ Y°c•┟MâQ—.˜§C]°£â0uÁ…) vÊ”;ùSìŒÎH|F‰8dÁNAE²`¿?eA¹)Y°S’,Ø™‘²`g@I²`§%Y°GÛˆT;‚b© v*Ì¡ öNj£*ØQšœª`Ç*g) šåŃö‰a¨ æ0T{LúR´+¨GQ°ObEÁN6(ØG„ŒSì¨gKQ°£²@¢`ŸT ) v†f$ v”+¦(Ø'nTÁNÉJ²`gü‹²`G÷¸”;f) v”c¥,Ø#û:UÁŽ¥ÔS쨔NU·[ª`ß ) v¬³˜¢`_”ó¨ vÆ’¤ v”i¦*ØA R;²ÛSì(ÌHU°3f&U°cëT;: ¥*¨»)U°c†“ªàà$^ª`G¹Dª‚ã¢TGUp D–ª`G†Rª‚=’ $ v4 OQ°c…›VXJQ°£¦!EÁÙ®4Á.Ú‚(øö[|ö0R´ûëÇ–(8LQÐ^¦oQðF©nŠ‚)) vÄSäIQ0¾,§(Ø' š`G¡Aj‚}‘À  òÉIM°G2\J‚}pj‚•.) >ö Zá msâ Þ) ò58ر‚Vâ`눃(/䳞8Ø•“8hŽÇ8;ƒûÍ£{N ;š4¦0؆2h§çöN°#âõ’4Ø [¢ÁN´ vô)K´“;iMìœEƒøÖ& Úã÷†ÁŽÎúIƒöŠ|)ƒí’;Ò*“;RŸIîzÑ ÷Ù¡2øÝ×RÜ^õw ‚{Ť2Á½©ÿ‘/B" ЈÜõ)à…n ÓŒ’¶ƒîH€X&кf½ðBÔ<ðBiŒøOâ—Mü»P÷œ’àÞH  þ»°L[òŸíùä?m#þ»H•â?, “øg;½“B7r3RD)Avg{ç„ÆNGNhŽ”Ð Á##(•)¡19SB#»éL Ø)¡ý{J(,;%¤w¤„ªdJ¨øP)¡ Œq¦„‚ÙΔÐÐ莔ÐöÖ7[)¡ÌâÊ”Ðh§ÿJ oþ™‚M¦„Þ3%0¨”Pe*%”óL %ñœ)¡ÁgN(¤=æ„¢0ù …0sBÃp¤„œÐH„ÌœÐA¡ñÌ ýqÀŸ§r† w¤„Ö”P¼O_)¡!8dJèB¼üL ¥)¡‹)¡÷ þÜ€(5Ë×j ²›9ÑÝwRhÀÕ‘ ÑîH ×ϤPŠ ¿Ìï<’BÇ+)TÑÒ3)4‚3)ô~ÉjøÊ ùcf…^d2e…¢}Df…ÂÞ‘—ýÌ ­oü»˜.~f…F>ñ™NœY¡È=²B¯—èïôÜ”*‹²B±XÙ++´~Ë X²B©hfVhýÐ=‘4°Ri¡ÌCÏ´PÄG2+•¬GV(–#<²B+Þ™Š^<¯¬ÐPf…¢ó‘Ú‰Ê ÅŽ™ŠÌÖL EØ‘*ñH E«²BÔ;ÓBë;-ôfò¦ÒBù–Ì´Ð=5ÓBQÿu¤…¢£Í‘ e4³BÊ´P¬úJ oS¦…ÞZd^(cŒ¯¼Ð'^ƒZÓBQÙ}¤…Ž’i¡?Nú³LÒ8°rB£ÞÿH _oöË”Õ##4`K ¡ƒù–GBèz£ß}ÈŽ|Ð8ò‘ŠœžLLþ<ÒAÛK \Ð !$sAÇö]“ Å\ÐI8S.(ÉÌ•E¹ È™¹ ó'¹ ¡‡f.(‚gG.(“`31#”W3sA•ÖIîã’¯\иžG.h$´ž¹ –Ì m)“A£BçHÅ ÿHÅ‚êâ¾+Ö_Nìãò ‡ (\“ 8©ºIÄgöP©à¦ ˆ‡ H´öÙ6¡ðû,Ó8¶‘ ˆèü¡.ª‰Ä>ŠJÀ¾ëCdrJ€H}:$@²xJ€›{I$즸?³A/Ô— Ú …딑xuH€èO{h€|j”JÝ05Àý-­þŽ|P|Íê»Â‰?ÑzíH ½m†óQh™Ê>¥„ÆOÿÈLUR(ÂGR(frGV(’ÓŽ¬Ðµ±”ʤ²Ì Ýèl˜Y¡Æ1°°‰s‰;i¡,A˴Ќ⃱6ÒB7×åRZèfù£ÒB™ã“i¡[Y Ì Ýõ{Ì Å„ú`@Ì÷_ Xßi¡!‹O ˆ(V*€/_R r)^èu{@àþzå„ú2ö¡hóŰPÔüLà…(–À«1»“à…ÓS¼*Š‘$^µ/¬Òœà…v²)ªþGàu³šà5 /4¥LðBGÖT¯þ‘šõ TÙi>ÀKù§”/Š’m›À,J€˜¤È¹$@{“"ôÒò%@•¤ȆÛ)^ë#)Tïñԯ̓S,56j€|W¦ÈÞÙ©ò+— WTK ° ¡C`A×‘Ô ú¤XI°0Q"`©äKŠ€…“y‰€ëJ¦X˜ )Ð~íomÛ 5bàa˜{QäZYÂÀB^X˜#( ,Œ‚­'ø++Ô,¥Z»Â° CÂÀ‚©±(°°.VhmßXÐL5)°°0VXÅDR`éI¡«P(Š¢À¸ˆ(ÐZ/¾UÀ2È…N…y{¢À‚…s’ ‚À<!ÐÖN~×ZÛð° Ĉ¤À‚u’ “E…º´(° ƒ À‚‚…¤À2¿^¥­h“ JᓠߢÀ‚ÙcR`A˜9)°,r(°,2)°@7J ´C½UÀ}')Ð:±ÿ8!­Ù“Ëø¤À2‰ ¤@Ûë•ê-ÕCx#æ×‹ ß“ÂÀ2ÉŽÀÀ猑ßI ,L=– Ê#–Ea XG’`áÛV(h‡zË€eÈÈ‚:‡PІ‰ÄL¢ Ý‡H²`EšX0Ç 4N,@I¬×× 2¡*i° ­)qÐ,Á_ÀA;»(¼#|R+sÞ„ƒ•*–pкóGÙq°â’8XÁV¢ÁJ‰E4X°ÖKÒ`Q…!iО¤à-Ò  Vу•5~dAû¡¿YÐN&’,ȹv@Â`ެb’ulÂ`Eà=a°"°—0XË' bÕÂdA4ðO¬!.$ VH@I‚6ý}W²Ç’ 9²!IÐö:À (aКϾa°â+Ÿ0XžÁ`Eœ/a°bþ0X•ýI¬…%†„Áª2DÂ`m,:$ V$K% Öm[0XÑ@[0X‘O•0X±DfÂ`<3"ÁŠùE’`öãQßµrϪ{O)ÛºêÑð»¶8¨}l”{åF?Ûí×û®•˺PŸ áhKF[61JK¶%+—õùkçP0¼† Û9-ÇPÏ;f|ÕÓmΡ`;†’åjÕ×@«~³ê{õÑîŸÓoíyûº`òõ[+ý—Û­=Ö_n·v·þ?ÛníûsýðëøZù\ÿöÓ§¸DñUnƒq²—:›©q¤c+ õÚŠc©›šÆ:Ú©i¬ÜŠc[q,õSÓXGC5•[q¬s+þTÕQc-ÕôÏ­0Ö?Òxm{Kú­Ækÿ]úÛ·×âÏ^¿ýôéýx›þüñý6ÒŸn¼¶=Ó¡üqë5ë1ößÖí[ëµwo4¶^ëÿÓׯOFÿ÷ÿôýÖžÛh êã–öùZòèâc¹;+ëW:îòÂÛwü9ÛjæKVýb 7ìaÏYh_®jòñ,´7ËþBÈ÷†¥ ZÀþX|U›(½¯aáéß1W,<}¨¥ß´lŒ3PaŸÙ¾Pÿ~Å×U¿\öùèc¡¨x¾\ô¡Ó‡f <„åŽqšaÐ,Ð,¶&ÂÖq6­¡ZìÇòø€BÜ”F°âÀc¡¿gU–Õc‡Rm¨…åº/ÌL]ºéÀ 7À2NÅ–Pú‘üÅZ¯‡e„ÁE…!®ÞmÉØa‰Ó»Gc°~âHt`c‹…³…÷Õ(GìþŠ3éVGœ¿6—D)ác/ë ¥ú-N¥óüË…çÎa6ë´ÜÇJ~dÉÿcí Õû¸}Ö/TøÏð¡/¶ô‹?Ó… ‡e7X6Âïmµ‡ Q°MÅ<õUź‡åŠ“t!“Çb9ý‡ÔñXFcŸ€¸¢Ã¾‡aÀÕ+Š´Ù8à±lôÀÕ›taáÖNz€&Åâ6aé°Ø’Z?²ûÀc±u’Cd¹Â§ywúÄqÒü¶gz€«5¢Û@ü¹Ê4 ë©g·Z"–k]WügÆ…·°à¹ZtëÆ?:[òúG¶0x,w§K¸v^†–·`=Œ°À¥%"ðXÒ¼äÖ¾¾Y6½Zq¬}±…cŒ²Ë¢WøEm[f-,q±6\ ¬õXî. ¶é÷2úJ¸ð|§¿ÐäŽï‰ í+‚,åq­°<ØÏ Ø>²”ËdÓ°xœ·Ø·[ìøÛÖX{[Z u¸bïºÐ±Mº€MF£Áåõb(}ŠËiÏ}òZ·bW˜>qË› K¼Äl·/t4ˆ—îóßÙ·áù³¢•BؾÇÈ~Œg¯Ø÷¸†åÆ–½ü#ó! @œã±ÐgYâ:¿¯‘w4…¶,ÊØ«^(ÎFîÔc)“.ŬTºÐb”Ú˜›Á>ÉÌè §í“ Ÿ6,£Ñ§‰ã<À§ã¤;¼¬é·±d¶×8íZô)~O¥•IŸ,uЧø]–Fâ·R}@³ŠÇÒ•§ÊQFÌ„ŽmfL…˜aúXJ³+€f&ö*°læ¥âšÛú`lzãØú`lŒgh „­Ên} ­³¿FÃ&7Ôã@7]Ð.éÁˆ³3B¢ƒ¬BŸnl³/úo]‹¤Ð'\›žìð©§1…)¶<,–ÖéSL$ŠEX5oïgvŠcoi4:ÙÒÓž }h¼4}_´à.ô½éžÑqÅ\(·%&s»ñnŽôÇô¡ñ÷a+„Ñ×ÂVƒW7F8›¸1öaFúpÇ2m±âÙcInìµ·œŠ :¯˜Ù6qAg™t —bÖA§Fœž­†|‚ –t¯Ž™.àVÙ at GŸìWçggx…Ÿ¦²i7/ñ¢7f q“½,X5è~¿¾¨†åŽÝn|Ö½'g¥ x¿¬‰^$û,¤Zã›e_fZ6,1ÚX¢Í^»‹.áµÓ²éÁÍ71q{CÑüÕk/ê{žÏ`Ô7ê‹´¨oóH} `<ȯ) Kjjœ‹üZˆÂù5N]D~bN‘ú¿ä×Duéâ ¿ 7@¶ ùÝœI‹üpzßýõ~w¢à–%$ðò üîHì8À/²ûîC6ÈÁ}7ñ«ÑþÍ´¨ûƒûn‚ŠÀR‚ÚHà‡ŒÙünÎÙ~¹ Áé&Õü°ñ~Âq‘ßÍG⦠x nö{ßø›ØtóqùÝ_4lz„§AàwóiøuÞk_çó ðS$@à—{ü:gÀ¿NúîLM+ä×ù8ˆüjp_'†ŠüÒBòú­ùõ¯ðë$4_çC"ðCò×A~¨:?ÈOoœ/níLðF˜éÁø ?$ä×Åp$¿Îß¿È/-taˆÓnCpê_쇖…û Þp°`Œà×ù ü¾² ~ £üŸßÀ[Ü7ˆQâ¾Á‡HÜ7D”<ÿÁÛ/îÓÀľÁ— °i&öiaßàb§xCû2Dî˰¹ïØÜ·† ܧÐÐNðaÙéfìä>îìcìHÔg±!€¨oEryBßœ\^yþ˜Î‘úÖà|„Ô·?÷¤¾51³ ô) %èSJЗÛôÙß ³úƒÔ§¸•¨oMÎ5I}:B_xú“@2ßšœi’ùlZ¶"[ /0ZW&ò­‰oMÎF+ÛVbîGä3K@| ÙòI|krÎKâ;Î$ÏŸçùOZ¶,oâ³½@o ¾…Î+I| I‹$>…ÝD|k‰Ô€Kì¼™ÄÇžI|Ç8 >B"po!)qoM¢qo-b#qo¡*>qOQAñÞZœŒÞlJh¤¹ÈqK eÀ | ù øÖBPMÀ§0¡€±Eñža©jSÚß¼§@¡xo-Òfð{’&ï­Å·AO`Hð¼÷Ö" ÷,Œ׆¸—{÷ÖâC3ÒDŽFº”´·o/io¡ Ÿ´wlÜ[›qYé‰{k‘qˆ{ m¨÷Ö" ÷ÖÊ÷Ör÷Ö"‡÷ÖF˜Š´§ð§hom¥‚öêÔ“özQ$í1±>io¡D2iO\Ñž¶Â½…u3÷ld€po-þT‰{y)Öáàmâüj{é#qom¾Äˆ{f‰çˆ¸·6Þ…;èØ$"R[EúOtP;xÏ+O_¼· â=E|èI’À·‘ŸÀ· Å,Ÿb>³Ä8¾]$Ñø‘ðm4YKàSDNÀg–0À…]8#%ïíB"­XÙ>þìÙÿÆ€½ãLòüq&-Ïãö `i_"BОm hï°÷ìX€¹t€Gg£ILºû ʈ{›¯-áÞ^â+àÞæR¸g¥ÒoÜCÕFÒÞ^Â0ÐÒ^Ô‰{{q¾LÜÛü ÷¸^ qKå÷T@)Üó%<ÜÚóM^¸çu ®À=@÷¼:–p@Kx÷¼â¥ó©ŒC¸§õC„{>, 5”P”:]t¸gYÊÐ_¾RÔ·À=ß V‘w_€{¾Í‹÷Ô®_¼ç#–V©ƒ÷|Œ¼xÏxgŸÿýRú¼ëâKêócÂL›ß6ß–‚HàccѾ2€ï°øö 6IàÛº$¾-"ñmAJßúö úlp}˜ŒïúØù4¡o+ÒAêc—…¤¾Ý Z¤¾Ý…“ô¡ë ©•u†kˆ}»ó)ìÛטؗ£û¬•ñ‡Ü×ùäHîëüNHî£p/µo|½¡oƒ>k³ œ¤Ú‰ ~%ö x öM†M%öM†p%ö1‰ Å>Ä>Jù©ö Ǥöin µOS ©}š;KíÓÄSjß—b_nP1&7Rûâ©öm±"Õ>Íá¤öiò*µokje›—OjßætVjŸ&IRû–ô4ª}›€µ:3Õ¾ýMíÛ"4ª}èWq¨}T½É~êå+öS¿ŠCíÛR ©”mipÁ~ZLìç^ìwŒÜè®0ØO--Ä~jÝ+öó#a”`?ßæÅ~öÊùý`¿½9Õûyãcˆi×¢ò*ØÏ‡Å6Á~^ú"kÍ3ÊÁ~Çe¸Óùb?µÅûy3û©)‡ØÏ÷¢ü·y£(Ò¥˜ûwú ðwZ‚œŽcþ¼R^DZ1qüi17ÁŸŸŽ>·° qpÓ)p'àχ˜ðçÛ¤ /©ï8ÀŸ2«Þ 7ðÐà|~@¢«èQ0.`›½u§ ®]‹?)ü8~,lSÂ5üÏÖ<|€²wø€‘G¥…$7qÆx-€þÔ¨EôçÛ¼èï8›E”ÆúsÏ_ôwnÓºnÕ‹þÜ‚mzÓÓ†qèÃÅ×Àšü5„ßkñYÃAj##úsË‹þÔ}Køç¿ ÿ¥1°´>´´ü;-ÓäÛ¬ òí‹(Q’—vùÀ€I|óñ‘“˜ÈPßˆé ¾õNîÜåë­ð)%ä>LÎ⣠˜ÀDÍÄÇ$§ú¸ÏR:ó?·R0]ôUƒ ¯R ôå^ôÁÒ”€)  /÷¢B@_EBmãJ*ø“È÷ÎëÌCˆ÷Ä÷A¬€¬ãäa!ð¥…ÀWÉK¾ªŒQ_¥à à˽´ þæ:0¸´Ô÷òPß3Ë[à;,ø =($ |\P&>\<ª{\î&Õ=ni®÷¥îÇ©3óúfA@ AQOO>5½|†©éå32Þ§ME/ý¢¢—5½¼çTôòw’^>®”ôìr€Õxò¹ éH§+»˜JÀ+Ò3—òâ‘ËI=1s9ñj‘¢·@+EAſ͹xvG6gùHæ,o¼[œä¦¦—Ãd2'U¾Lædšh&s¾énm)xßòQ\N乜HsÏ\Nü¹œ –™Ë‰ˆŽD=åšJÔÛ|›KÔÛLبÇÙ{ŠzÊG•¨·¯NUoócsdsR'ËlNÊæ¬o]Ͼª€§©ï‘͉¹Û‘ÍɼÑLçÄ0™ÍÉa2›ó¦Œ§lNn“Ùœõƒï˜éJÀ»”ˆY™åúxžfe¼‹VIÀ G:'óH3³Ä#—ïHç„–ٜdªÌæÄõT6'9åG6'î¬øN´$¾»´³9/©}tµÏßå6介°¡lNÞ[%sj'%sbý4ár3—SÁÊåÔS.§ F¹œ Êå¼8¹àév·ô'£\ÎKÙ’Ì„¼˜§\΋ ‘’9uÌ™û¤„Âôaù˜ ©”ees^$~es¾•=ŸeüžpçÐS™ïÇL‰œš£+‘S™ÑJä,œ#‘³ Ï&9£lüÈãÔÓ«<ÎÂÈ‚ò8 å"åqjê¯<δMÜ@î#]À Byœ¼Jã,|?(³ð‡4Ζyœå[§Xj¤ x<•ÇY”‘ÉH”¨yœ…¿åqb6ŸiœBî™.@Cœé·a¤iœœ#dg"Ó8 Õþ™.`”•.·Š&Bø­(3·ag•hÇ<ΪÌNæqæ±Â0_“¦qê2(SIãJãäÊâ$Xd§Îçùã(²Ã^¢-Ú+‘sη°§ G {7'ö”Ç—õ{,ðc"§Òà”ÈÙÁU"§òÔÈÙYÁ¥DÎÎy9Ua¦DÎAmB‰œƒi…JäJÿdäTâæ`ê ŽÄDNUl)‘sêŒéä\¥LÎE¶º”€•ȹx)”ÈÉ„Lä\’íîþ1QU&§æ˜È䔂LÎÍ´=eræÌäÜ„zWÂßV}Îê1”¨‡h’ÞÉM Ç)½8ïR–&9ïR®çä—Bߪç»99Oq^ù¬àÛŒ»%çÕÙ%çÝß8óXqžôãõsB=þx’ö¨‘ø¾ñ(+qï¦ÒGÜc9”ˆ¯R%òU6e¬×Oä#ÍŠúyQ_ã]ÔרT‰úšr=7K Þ‰œ–†O¥o3 ¾9•¼ŸÔ§la+‡%ë1Áy¦T銅¥êݼRõ”]-Uï&§BÕS°T½›‰§Rõ”-Uï¦ßRõîoªžÞ„RõÔjäPõê›ûØåàPõ˜±,Q/ ÒôꇦWß|[Rù¡é7õ™øMÓ£Hbê*Ø£¨§dZ©zRõ˜^{ˆz×;•s©o$¦Îy  o0æ+èœ+ªv¡ƒóµ+UÉú!ê æ… ú¨K&ô¥…Ð7(xú”*è6º@=®bŒý}ãëÌ™Z¦˜‚r2_¦€Ò)¹È4©òˆù&E 1ŸtTA?„ }RI}“™Y€¾Éù¦ MŠèS¥ orB$èSh:A§¦@]1ßäüRÌ—Y–„>馂>ÓèÂ;s/^)Aß"/ ú8AHècAtBß"€’ù–ªþèÁ"MŠù–ªõÈL“O•˜o‰ðÈ|J7ó1(™O2µ˜oñùóQ”ò±Š:‘o}+à[¬ÝöIöI5÷)wTÜ·TzGî[,lê\2 %îÛümôtôHr›IN,éÛô Óqßât\à§œDŸrü~›Ï€Èo‹óº²œ¸ÍÀù!p!òÛ_/QOÏ~J?øIømåxü†LðÛ*´#ùmæÞÎt–t1‘Ÿ´}ßV© ÉoS7ùmÊ×"¿­:»ô|FIìâÃ%QO¡5‰z×7Qïúzetº°ÿÊètËKÓ»”MÊÅ5˜ÔôòÀÔô4†4½´¼R:OKŠzí³ZíWÏöPÙÝÖ‘V-x~ׯ>hïr¯£ÚOvû}Ъ5…Çh8[…Ávô’åè8ÖZ?š[ý4œCÁv %Ë9”q¶T£á5TØÎ¡h9†º+Õ^AΡ`;†’åŸÞ­ÎéÿÅú¡}{¾k¯Õšø1üäi¾Ž.|ñ¬Å8G§3 ôêt†‘Ž­0Ôk+Ž•Î8ÖÙéŒcåVëÜŠce§3Žuv:ãX¹Ç:·âO6;a¬W?4þÔs+ŒõôC{æ{=:»ÿ õCû»ïÔß¾½ö ýí§OïÇ[õçï·‘þt?´çÆø”ñÿ‡ýвõÙøYg´ÿOЭörg¯³ø¡±>|Å׳¡ª¸ákz«ºz†¡«¸:BɵK°ÓP[°PkkŸj ¶0ÎRW-l²ÕT˧!u\jªÔ^GQS­˜\×Á—*S[&CĻܯ"¼çU‘©p˜q±ÐèÂ>CeE`¯cª¬h`ž>A¤ž?d÷:/•äàÜf¹©#XªJr"îTgSIΆåfÃiuŽ‹–˜|?–MÝ+øëùÌ*z7£ÜñNý¬Fâ´¬KQÅÀŽºŠ¢Š3ÕºçR9Š{»š21"YŸO»âŒØ«#Šˆm Åq·×P\±álæz÷f©k)&ÇóÛŠÉálö¥>h¨»Üê#視"®ònŒhÅŸwa˜1 ½î®nïÉÁ¥=2$‡-¦Br¸uÓ¦ÃWkÕI‹»Ô®K!¹¸áí*J´Àr»ªBrÛ4%ÚÇÅz¾–* hWWD+0ä±((·`ø»ÌÅXO0[»Ödøªá@éBŒQèCH­´‚¥[©¡ø]ší',·í/ì•pzÀXO{È“–¸Xe"<Ô1ÈšŒ*Äï§4Þl/×êÕI¦áA¥X~è±T¥©ãȵ)Ï>(ùù4{&¶é™g_aùȳou(Ï>^­Nl?Vãc+ÑG~ní»P¥=—S°£´ô "Z­¥–»(¦g×úEPìcQ¢}ÇÈc¿#¶×ÚT¢ý†e½òp[Û5|_]iÂq—îr½à¶ÝµTã·ÞžI A5^Ôí¾•g¿±M:0hÙJ¨ÅÈCyöpûžÊ³¿q†Kyöx$nº€Ÿ`¿”g§í‹ ¯âƒÔlîË„î8Ro•´÷²ßå“Þz¿”Q»a •O@§ UÏI îS_ƒÝxJúF¦=Ÿ6b :¦!¶A*&mÐ…†(S{&…aaVp7²Ô‚{mtdÚ7dD<dÚ£§üc‹^áü}Àbe ZpÂ[iê¸/óR¢}|ÐÛŒõ昣ÙfmJuŽžéBÅ>éÂ…múE îøì›Ná'52í¬s"ÓžMƒÚ¤ –Pzj¾øcXâ3×|å—°àʬX0ïæý·Ïr ¾öY®aÛ+ˆ@s[t€ý¨Ú‹–Ž‘ç¤KÜk Þ'v磆þþæÂNâülÑ.pÆ»á¹Âm³ï2|йZ³ï2Š'qœŽ${ö"yÞ+rï„='«)ñÀî5XMáó¶·j'ãE}Û¢]3, –‚€Û¿Ü]èÊï«á’oìs£r2úÛ>Ê7r²u›zXrX7ô±ÐƒqÈû¢¬Ï»¯Ýù’ˆ‹uÛš]xò"ì}Ûš](ˆ§ü¶5»àSÇ^­Ð'nCB¸¿ }àLý¶Ï2Š\F‹oo\‰2'ïTƒÅiàöµ·Â‡Bâ¸w¥þm0KÌ?ï¨êgçckvÁ«½î‹^Åî~>ÍçssWú€•…LÂÀ¢¯“ž[<«†eÀâÍkÜrò»¼ ?øÑ*…>ä6ôõ/÷C;©oœÔ×Èt-Ëb-裞ÔÇ—KR–×8¨¯‰ñH}¼&êc£³Ä>,T{p_vÉ}èwp_#…úÀ¿ïúþ›àÇfi ~‡…MµâOR_#‰ún‘!O?vói1_ZÈ|1_ns×÷ß]Áh/–M2'áùÛŠù ˜/-ëðáÍ|Ç6à¥Ãæ[|G‰ùŽmzyÿ}ø@ ”åÍ|ë&½‘ùŽmÀ|i!óå^d>ëFK¸é°™Ø OÔw ãÔwìêË]Òî’ÐbâNb>5Øói'1ŸÚò‰ùŽm`1{˜ŽmÆÇ߀¾c@ß±ÍáBlSZ`¦ÅÏ–¨ïØ ÔwìêÓÅ)‡ oè;†2–ù¾¤¾c.7£mH}¹M=\xc_‰ØwX€}‡ØwŒìË‹SÓ{¥ ºØO ìË=ˆ}¹ ±ïØ&=à6é·ö™%ÎØwnì;ÆöÛûŽmä¶Øãå#¸ï´”ûÃ'pß¹M«>݇àÇÃìÕ÷§e¬¯÷ùûÎmÖø¸O÷‡ýðèUî¯À}ç6­~xð;·é½ ÊZÒÌ´~ÙV“àwn³•X{‚ß±ÅHîø¹0ÖÔ^ô~ß¹MWQŽÓ?Ç øgsøð¿s›­£Øäwlãäw äwZ‚æá¶é×7‹ZŒòHC-Fy6S=RïùÛ¤1ã%ü¹HVÔc´ðçõšùåÎ6©Ø&}à6éCÁß¹ÍÔ¤ø;·Ù꓊qöáˆëð`“©i7Yš!2üËÓ#þù0@·¢©]„¥ ÜF.`”»¼ÿפ( þÛŒõ¾QÄ¿s›ÃikR„m€º¤?7€Àªæu„Ø4¯`2¹¦¤kNÄA†&E95)ê@Æ¥i·ùæA=<ˆmÇÑk­NþŽóüù6üû¤ÜbhVij™šq›¥YHtkR„«'Ñ_'Ób˜v¸`‡ú3íÑ„Ѧ?ùOý΀›q! :Ž •¤,Ü|i 7û% ·ÔCԾő(å$‹ÿ”ë,þ3 ä7ðŸò–Á9nðŸz‰ÿ˜~,üSî®ðo3Œ!Ü) €ÊÃJýn® $TÖ­ÐÆ () ¨žL©ûñd$ûuI…”Ìr'Ê~ /¥ì—ÛPöë„rÉ~ÔRöK %3Ö§ì‡åsÙ{(û- ƒôa æèÃ&NµØÚ—ªì¤ìÇlÍ”ý˜\˜²2SõÓ¡¤úmÞ IRøÛ¼ÐýØj0u?ù$ÝOWf§õC÷Û¡§ì·—ì·¿É~[jÜá,éADaRöc‹º”ý˜ÎIÙoKÓ£î—ê~Ô·S÷£›)ü±ue [ÔEá›Røƒ”žºŸ é rnKõË“™ë}*”ýð<¤êGƒD?]ðzœ>@Žš3jSõÓ¥’ê·jTýts¥úmaz@Ü£׉ÇTý˜Ë›ªŸÎWªßýtGZ:€S‘è·)R’þA/E¿ûMvÂ9E?ÄâÛz?­A›mVE‡¥Ü.‘þô;ýå~§õMééO—†ðw øË áO¯ À_>=]À“GøË;IøË;GøËKEøKz`{zÐÞìwÜ”w—ìw ö˃ûå#=ÒJ|‡  ¸–™ø ¸;ÓØAh`¿|úÈ~ùd‘ýŽ£>`¯õ‘Æ.öËûKöË‘ƒýŽ¿«Rñ_¢_^áyx-±+‹W˜ä—Wä·Ù$Wäwûð#§°üÒo’_þ‚üò.üòš“üKú€+¼ÒŽ;”ÅŽ¤’_^a’ßf·‘_޳Óêqß| ùåÕ ò;¶¸Ëû#+òKÏI~‡%} à”¦B?Ýa¡Ÿ> B?ÐO$ Ÿ~1@?½û„~z¹ýô úé9úéš ýŽsÙ9J]š •7ûéÝ!öËqÈ~Ç6ò!®CI*qp¿ßà‚¿ôœðwXÖxV¹MMp,ÂßædLðwX‡åÎ,[j\MnààX¯ÉƒØ¯¡_n±5z“Ÿ ÞD~*;ùq³¿×-iïz‰}jMAØc“·„½Â<;Á[+$ì)ëO°ÇV… {lõ´‡† {… |‚½¢ÌÊ¢ ÌÙ$ì¡Yëí‘õØ“;YmêöØ¥;a/÷šª»¦å8ì•Ìw–gž®hOç'ÚËmšú3àXS>`ŸÃ‡0 uhà&$¥$“\øÈñÌqÈJ<¸`/7 ÚÓ#!ÚÓ]Øéâ+;]à^D%ǽ÷èBâ^îu¸€ÍtÛ–rÒRZÆÇ߼…¸—–èy‡@*ò’öîå^Ľ܆¼—–ÃZöû'”Ä—–¹ÞG"ñåùù´˜O×¢>|0_îÕê‡Wb¾´ùr2_nsøýðÌ—ÿkUŒ*æÓ6b¾´|@Ÿ|ôå6ýz¿¿úø©Hèc:xB?„>%8úôÿ}lF”ÐÇ }èr›Ì—;¥PEît‡óåÀCë§r›©õS9ÎÒú©Ü‹.`n,è»’ÐÇv¤ }tA̧aÅ|¹™¯%zº€)lOx:S-«8òR·Qn³³_ê úÐæ*™O'3ÒƒöÖûò.ˆùrØ®~©²¨éÀ¡®[T÷Ò„CÄ|¼~B>Ý(!ŸvòåßU]·(î.|@_îÕ5!â6}<~‚¾Ükªí.×LàøLî·ÜwXŠfDЧ# úrŸ;'uD¼lÃGç°d>¹)æKËÒœˆ–­I]û`>åSïÃ…æÓóéE"æ“ b>[̗㦴LMŠ*r;×ø¸Ub>\œD>“È—–Ã…#Ù3ï‘/ÿî×Û¥D¾Üf¬÷Ó—È—–Oùdò¥¥hJôNöôm`išÕÍè“4Ó‡úJöômCs" Ž/´Æû]—È'Kýæƒ/“D¾Ü¦iNô‰|ìeGäË}¾ù ä+Éžç¸Ks"À®¨OãûtÛáC\‹–>Ô(mýõ¶i™ï鹯2?²ZCŤe|vNP•ñÉõ3ãs°zMŸl½’ŸSÒbÊ•B¿%ªbÆ'ì™ñ¹%ιâ)µ¤ÀKY£IPØá€ÀwÂçf»º„@ª ¹ÜLB —³Nl’óHPªR×Oä2¯„À›i®3EK&˜šöIÍÂaj~õƒ¹ÎcR Ûþ$Na}˜Ò݈Pó °Fä’q§ä·>%?`bJ~±PQ®ñ!ùI‡;$?J‡{°²‡yuŽ>* ^YŸf!šÑp à1J¥“—èùùa~òR€0Ü…>½E¿Å’ ?¿À8Lž>wá飪³FÜäÄôgfÊ+áÓË!` úóŹPŸÇ“§.Oú[—TAVɱQL–ù± 6áÏ,ãfAÆàÏÖТºè.ØšZøÛkäJ‘ †¹¢rBÖùÙ>¯|OÛ wžu~¶×Gßý­ÎOšëüJÖð±HNµ ¬ó+躣2¿Ç€Dµ(ó+lì­2¿çô¨¢F®ˆqUæ§‹Ç2¿Rùh²ÎÏ–$#ëE_ɪ>ºP•¸ žI&¼¬ó+U¬‡:?[í•ÊÒ¢ÎÏöy¥{æ¢jªó+,ãÎ:¿›ÑÖù6‰UŸùù®ó;,¬óãšãYçÇ^pYçÇ–‡*ô+‚núÍWº§ÿ:âOÔù™Sï:¿ÂòA–ù.ò®2?»¿`FTÉYƒlƒ2?{v_Éžf¹^ôg\-Vú®â®J¿R”^‰2¹¢ ñ¨ô+Cz¨ô+XQP…~ÞL$,,ô»ùûV¡Ÿ ‘YèWX9¯B?;½w¡_aW\UúåCËJ¿g8ÎJ¿Â*8•úÙ}C‡J¿üÕ±Ò¯°Í„Jýž+±^ðw\O–ú®y®R¿¢r–ú•‰V©_Q—Jý¦r0é­â?÷¡ŒW®§]àëEþ+|ÑŸíC‚D©_a+`•ú•·]‡a@•œ\R¥_A¯Rú¦©©Ð¯pª®B¿Ò™Úé”LO¿º”ÿb"TT"Ç2¿ò™éiA°d™_aU¼Êü —ŽS™ßcœÊ2¿¢9–ù•©=”ùY«lƒ2?;úYæWØïXe~ÖsÊÊü ±Fe~v~8”ù•oe~E\|”ùéÔ½£Ê5¥gÓ4뮕=¤®Ö·V}z~ׯ¦iïr¯£iÚOvûMÓúó‰|õ£áì)ÛÑxH–£=Y‰ù1 ¯¡ÂvEË1Ôx6›iý4œCÁv %Ë?½ÓY·;[ÞÎþ ·˜õá­ßJ}Ûà }´$ûöôÜ»”|v~ûÙ“2öÑ/º>Å(g«1æÕh ãÛ` wÓ2Œt4ó‘Î6c)·áH¯–eéh3æ#MÆ8RnÑ^ ËðC8šŒÙH¯Fdüùä6éjDvÏfþ…úýÝ×ÔoßÞ8?{+ýö³GöóEõÓ§öûH¾Ùóš°ïÕò>dÿþ“Ñÿýî>öâ·îcfûýëß~bc÷±6þN÷±Û>q› Zúnħw×K–Ëf•v|Uw[*<Ç&÷GQó½»j_ðMßCÕ;˜3í‰êÎÆ^– Ë®j8æ3~]… ÇfâÊXf¿ªzqUìRs! ìÓÔ[>üî×m zXú`+é Ëx·S},óf—š…£¯ÆÙÇÙ•<™j½\…@ÄÓK¹8qÉL/S¢À¨çï˜Ù' û„«r¯‡pcZ׸2Þó¶)Qcé^FL‰,Üע̘Ý”ÞËŠ9Q¯˜Äõ:Bî> v“èµDth"Úû"8´¸¾Îóýõ¿¹h·VƒæÔæò Ï7%fuàuCx°/†ƒ{ ¶¿bÜ0=4´ åîÕ_D÷®“›lnY¨÷©]ÝÚ7—Áí-Î?H\½ìÎIqoÕÃCÆ4ñ|~¶Ï ~sâµ'×:x^ÝÚÖ×4.ÃCÛOÏ“Ìõ¿{sžG™kÌô‡ Ýòx`қſKåR¥Ï+Ä?ŸW|ÖÈx¼zïžÿèZC{<%·ûÐj¶i¶Å`ne¿o£`U· S‰-ð#¼‡…¸žÇŸÝÚz|E»µ·¿`  {6ö JaDï¾Bn/pC¹b–Â¥‹…¸ºE#+¶©Ëç6cr§6}B4Ðê¦ws ÌΟWï6æÒ°‹uš`ÛÞ§¸ü‘å6Þº÷yDuj¾$Çó@6¼Àúˆ³¯ÏÇ84}ÄéW;4 Û Ï3sÕbCÏN“?íÑì1}žk†Hû°ß¢ ÃÅfž~FiFŒKûL‹ =OèEƲØÐóD²VÖÉÏÆ¹ùK™u7/+Þ¸}Þ›…!ÝÇâ>Ø“Û?Çfïé¸~³M÷ÊÞIq†óî•…°WïîÕó?.Œü<€ÏóÈr…>áÃÍ.×}‡Áæa=Byžk¶zô¦ϺGãªãͳŠÅ·ž'™kôU—{ÅRƒç~» ÷s–xÇÙ+Ñ,ÏSŽÓYÝ{îZ||Ü>…¾¨™÷õ¼+ž'K¿õµìêíØ%<èêÕÔwxð<Ȉµõm‘V;4 ,òg€{U‹ouïÔ‹½šaís,êš}‡ ®.b¯pÁ›â‡S{ÜîÔbX¿ÛÛëqêÞŒgõçËüìcÒ^<7Û׆}ÎKs û,׸Àñy~îBXà1¸šïý¸ªÅ†ž· —WW›~Ÿ&SƒÇu÷ÉÞ=,½ûmÙLGWxЭ‰g Kx`Wtò‚u&?Xãù0ÿx~ \òiØgÙ|2…&ÎÆ>Ëv§¬|â†eû}©ìm8Jøðwj”6ÝÂÆª£Ü6z~ùøÿæÊóçÅOù°õ±ÆÝ¸Ç´ ÑcX\‚Ó·ONÎOÿyçÅ[z<_äçïÉR¤Q=\î˜/ao7sçÞøæZm*÷\†6ŸsŒ“¿ÙóuÔ8ûΉÀçÏÉ]x^ìºå¤a‹c™GMwÖÇ2—{3[kÛu˜x¡>Èo.˜ 'ó|’ÍE–l û ›KxÂìklþt¶Ó­Mÿ!müy¸7z([œ{ßl†0Zœû°F^ØË¾jv©ÏÝÖÅ2ol(Xvqo*Sᇭ‹e7HÅãö³¼ vÜqöÏmÀ;hاØü™Œ,>O€ÍžR5î=âuÛ~ þ|q™¦çsá-½íëS` Æ­çô†êN7üdw„U§ÃÇò{Tñ†¶8Vxÿ£¡Nzôpà¹qÚ!0—¸Í=âGÄ—ñÜp‰kV>_7ŸÿØmÁév›@ùo¡ÅaþºKÔ‰G‡ÏÓ¢Å.3ûmÁëc |auÜ^[kǯžgÓn7»- û ûmi¼ä>L¶Ü|¾¿O’g#÷ªr¶8Ælá{ž±|d'…‡!Ñ.\ìÿʸ‰ß;Á_n;vàÞ/Ð^‡E´‡²û÷";q¯±¯pŸ¢÷BŽIÜc¿Ä=NÃ÷n+qR y²”xoq*ñÞâ2Qâ½E-[¼·D=ä=­Õ'Þ[| “÷|ÍãïåšÂä½L."ïy×ä8CðÞÁŸÎ{^ƒ«›i& [YÅ£…ÌÊÌñÞuÉ2”Ð@–›Jh k.uë#I&³Ö7ï6‡ï™tVð™‹_aÙ¸€¯ G¼WÙ&ŒÀg ‹1à}g‰|F¾˜~ølÁL6A|«qŸ‘o{Ÿ-ê‚k â3i3>ßêš 9ñÙldB„ÚŸ/1&› ¾õJ¼XA|_â;ø0ÙÄwûBn'ñÝ–xVâ{,Ü@|0sÒâ{,\îÄw/ÕÊ9ñ=o‡¡qïsT'¾ÛdCÜÉ ¾ç¶¯ ¾ÛÖ¡ÁâsñÝ; 5ˆï¶åZ&ï"›GöÏ_<{9ò=/Šî`¾Û–ÃÕêîà  cƒ>1áO'¦ÛJ¸Ì÷¼—¸ˆ˜Ï-¸˜1ëyÞT•·Àů& ïywÝ⬠¦K}tI}6'Æ…õ΃Å@}–‚4±—Qß%ŒÔgï7 ÀtuvÒ&ôYÖxÐwݤc0Ÿ½ï1`¾«v̨É|ד‚ùì}‡ ˜ïê\bŒÌw"c¯`> ÜÙ˜ïRßl2Ÿ‰¡äÄpÁ‚xm€ùJe>™¯C)1•¢Ï  Ï&éø©úl¹<<Ä}öwyQŸ-Ÿ‡kê«EáP_©l%Fê3¯ðõÙ›O$¨Ïò¡pu@}žWõ¢¾j¤àµð¡v½\@}öF&ã3y,G7ê³H^$ ¾j-„Ák}5§{À¾z`_í ALupxRŸE@ È0¨ÏÞë´õÕq“8áÀФÐg|2°SP“-XFMöq:ú,Tq+BŸ-  ¡Ï˜f¼ ÏR´ö n²•zq!@}ífÁÏÄÈ~íÆ[Šà×îõ…ó Úͼ‘à>‹/Ü :ƒ¦fqë÷µÎUgÉ}6-Á}ñÉù=±ÏV Œ8 ±¯-f¾‘ûÚd;^r_³U‹Á}ÎÇÊà>Ûf½¸Ï²ÌîƒûîÂàà>û“xpŸ­ŒãýîZAÌ ?[Òpc§€?[{!ÀßÝE"€¿[‰„¿Û&$/øsêÂ^·zÆþŒÃ¤pø{&Š˜YþŒ¹.Y°“‚#þÌŒüu5öü1!„ì×=±á÷D¿›EC$?ûΟéáàN_Æs~&ÂÅW9Øï¶PHðÚÄMd¿ÇBf7U>g@¿Èdÿý ¿Î¢7’ŸT@l ?[Ùq¾ÈÏŽ„(ÈÏöZdÁ ¿çõ…øÉo1Ù ä·ù­ù-¶;ùu~„E~¸–À¾çÒ1ì3‚‹@"±¯kõiè‹“grŸ/3Yaº"äógZŽý<ÕýÅ~ä`±ßfÀXìg?Õ·Ô§7É~ž ®ëèrÎð!ÙÏè{Í›¹ÄHSûyÖiveâ*-ÐoUÖòú^€ØÂ[¸S(Ÿí‚p1ÈÏ3”±Í­çd¸>˜y¿ÈÏ’¨0ý¡ÒWØÌ_J_)¢ÌCék]J~SJécéB*}˜Hécx3•>Mm¨ôÙ[* 5ÁBlŒãüª¾ø¿vQ#ø56¿ø5¬,îkb8@Ó-è ì»uºÄ¾›©Žâ¾û`ƒ›±VßÍÈœÀïþün*Æ?[ËðEðkœà÷æ¾»I£3Ù…Æ0Î}7KÄ}ÛpŠÜ÷\p ¹Ï¶ Û{5Ü8¸äØgGFèØgcp‹À>»û„Ü Yƒù<¡Òâià»ÝRÛœùü‡ÐOæóß žŠ *kLÀ|ÏaIûsdz¶)o¥Ïƒ8ˆfóyï§`¾ÛòÅÛ)õù ê >hÉ @ßmËß§Öç!%LnƒúÜÒ`qêódñ¢¾k0üFìsKÌ·€}—dZbß5¸äO`ß5«ä´À>l¿°ÏC)Ø&°Ï!îöÙœüØt5~7H}V#¶^rߥÂ/RßUØÒØç)œ îó*…qŸÿ†Pë²Û²XmîóÇ3öà>ÏV÷Ýö€müÜ‚9{€ŸÊ0YEÚ®=Oã¿Ç"®ð{㮽üüÁ¦"éà÷Xu?ŸdB€2ð»íÙnüÛçBöà×Só{,××)ùy®OÇ ~%E€Ÿ%ž´ø gBk l²Z9ªÁMö`àø•Ê¶ ~¶M9ÀÏf‹¸ ¿ë¹qû~×së@ ¿ëy_^/ðóA)ÀÏžOüZ@~×Ý„”áÃ¥Ü ²ßÕ.©‡NULûÙã¸Hƒ;"‘Rbþ.-ˆøóÇüðç/ðüùC IÐßcaƒ*àßóÐò« üó*dÿ‹d¾À¿ç¡¼:…É9À?Œã½üó/\/ÿçoÿ,V1±OàŸY€rA6±»_º_»X¦E¬¶@6N/°Þ ­keAЊ!ñ 3‰»¡¸ãïuK½ï¹*/èë’å(–mejúxßú˜i"ÁOÍ ú.6Èô1 ¡sAßÅøpRŸ2’H}¥Š êööKð3Ãü˜ØWøö•)™0Å2|¯‰}mö]’"”àÙu~ôAù3¾)<3]lö—ØÇ/±O>û¬ž¼FìS’°o+y“ܧï5¹¯Õ¯7öµ¢aˆ} ôûž§?aßÅ© ¹¯²ôUà×t‚¿‹Ó‚_cql‚_&&øÑLsƒÖlê’F~«ŠûÆ%Ñ Ü7ød‹ûæÅëGð{~ªLà5Y¬{95-!Áo á ~›}Ö~¶*FA–ê%% ä·ŸçsŸ q¯O·HÞ‹7]•ò³9© iªÊ"àW¸ˆ?=ù$?­o*Áï’\ ò3ÊÀÜõ¦dɼo’ŸÉšãE~ÖaóRŸÝ<³ ?#0;Ðo1éœäg_ùÙ.5“<ŠÖ‹ü¼IÆò3'Û[ð«\T‚_‘„EÁ¯p/ ~u¥eÌJùüíÆþ©„¿]¹PáϦ.8Ÿôª×àÏgDäôü.[€?;›ö‚?ÛÁÀŸÍ×^ižŽ3ƒ–9]üIÄM ¿­¨ ÀÏæ—/¹ÏTüƒül‰^À"Îßî ¶ b) ÷Yî38Šä§ç—äg¹£Ôÿ\í»Ú- .Ô>›C!ud¥b‰o Ô>›CݯÏK™STû|’†é‡^`ˆ}—f©û®[/#ˆ}×sñ¤ ±Ï&txb!ö]–Ø  ±¯Øjº@Aˆ}Z5‘b_±tÂ0@¯,¢bh}%ÙÐú®UNîóOuÆÐúJUÞ´¾ò<®û¥õ=ŸqâľbSüWާܰM¨}Å®'è,Ô¾bq=0]pŸ×+ÇÓgì8ŸðÁtâúÊñ´ËE64î+¨ä¾b¤úÊñ4EšÀîÛ\X¼wâ¾MVÜ·Ù‰GÜ·Ø9˜ÜçÉ}Eò.õ>C•qè}v–d¯ËDdè}Ö— zŸµ€½Ïåü—àgWŒÒ=àBèü̧ñJô´gíz ~>2Î/?ó;…Þg9Ðr]ï‹®$¿ƒúü&½Ó<í6B‚ µ¯HF‚Úg D<@_À}P„}æ `>ëÂCƒù´ ±˜Ï:€€»‚ù.­õ æ³5ÑÁa`¾Í1ßœâ90Ÿ¥<‚ÕÀ|“Ÿ 1ßb¼˜/ ŠÌ·˜A%æ›â.2ßÖ¯’Ì7Ñ–GÈ÷¼»ù6»„Pï³A²Ðû¼°ý•ëYTpOÁÏ~¶¡øÙk„ù ¡ø•›kÇPñ³ŠŽà bêú»ˆï™§NIuKU=6(øÕ»“ÞLï«wª†¾ÊÄ{_][Ù  ¾K€øŽ|ŸÊ6yJ½or Mð«Tª~•N üš’º~–™H}ï ¥ ŒDð{>¢w~=¡>+4>¢´¯+Q‘µ}–ËR|h¼ÈÏrôîùÙFf+ñ¾»ØmäçQ/dh5Æ]R ›Æ„~ñBÎsðó <ÌûYÛ׆Amß=?kû:r8TÚ7”öÌÒ¾!é‹Ü÷¼q¾ä¾y+%Ü7›´9ç>+=<¹Ï扞[e†ä>ËûŠß˜÷SðãëE}6Íd ' iª4Žzß’XO½Oé.ü¶·)øYß¼3ÍÓšnáoG¦Ù¨‚˜¦"JódSQŸ‰n89¦y é4O¦gÒ•‘ú& TD}ƒŸ^QŸÕNÂê›Ê$ꛬI}EÅt¤>µ^õ=JPßMù”зoi€€>+XãUçg¿Âþªó+j(öS6üidz¿±Õ·Žgk»ÏŽgß¶ûIdz_yCþäUôí}øÛ¼ÔŽ~áÍú‡7ÄÞùÏ-±Ûñ_쾘è÷ÄBÈæ¿Ý“ÿíqú¹¹×üËÿú×ú ºîû/ÿõù-?3Ò‡¸ÿòßô¿ÿ÷¿zWÌÝÿò›þõ¿üÕàñ™Ú[3›š¯«ÿåÿþ«%q—=þòÿüÕÞLüÿå¿ÿõ¿XýçÓ¤Kû§[µY±ÒxfŠÖãäy#ÿ¼UÛ3»B«6û;¨ÝÇ¿þý_¶g«]Õž««ÿ=µS›mztj2æ˜ÿ®}ëÔö>$:µív³SÛcüÖ©í±ý‡þõo?±©S[ùãNmÝúŸ¨añ9ï´Òìm{±âiN*»Áðº®~9Wä5[¡L»W K®Ç‹6ÃØepe¿‹”EüÁXÊÜ©l>#§ç¹z,œð[Bð,f¡ävE{ª°Ä8ï«öLGJ§©±ÛÅbIK }þŸ¯]‚‘£² 9˜ìh?’y­`dlWoEUgA¾—Ëêó‡¯VnWѪýš"ØPº§ó»%Ȭ /Þy,L±(æyYXtY¦çéÖY/@´•o;xeúT±/˜yY™Œ]/øVûéF`£W “ ju¼z,ZÙÆ“-äÁÖÅ~ÔVÝÜÍÑÆ¶ŽV <ÌѦeA'¦ʾ†q¨(ɬÓß{n1'l“k‰Ø+êÙ„AfkE|ù¡ÝO¿r¸PÄm?Õ:oµGo^ùûXXMØnOj|Æaµ®UéÚÃn/-,!?<ë{aYáÙ…A‡f…î(›ÂÛÿx6ÐÂ/÷A"&âߎÙYéxWùëìhPï¯î"ÛIÞÍ×Ò‰“ ¹ÐÚ/ÜaÁ6ÝÕ“gö{¿‡g³ÕùL/Ñ@fx¥Pµw.ú}O_޼zƒþÈK]ÞêyñrZï±eÇR­õ Û-ƹYõæˆ8-úɢ̾“ª¶ü%nágö¶ðäÎç”kv °ƒ>O†š¤ /•},Ù¶ÏC¾MgüúËÏx3B»<­£Úgb3úêoñÙ—B Ý²WüF žU¼Ê£š ý¾ú÷ÙFÕÍûHT_…èG„”ìL«÷d…>î-Ϋ­p ˆˆ½åÜRððF{Õ—B³!O|¨¦–"Ò·üW]½Ì † Ϥi/ÝôMìUó|¶ª· ‹õnèfiKì÷fßö\‚ÀùK:}Å«º ol©%{…ÛÉÄ Û–Z²W¸åÑÆÕ–Z²W¸/Ç^^‰[]ˆcoŸ©ÔUÙ¼fEšÍt|Í;VeôÏþe¯p_a),Í?áվבYeß髇çñ;³uñcñã`j{…›%2—–/zUçÆoÏ’›ßN¾jM²½ýŠ2ÍËÒí%®LŸµw¸BäÍZ†¢¿Ã7—ÙZKö÷¢@?™ÎÔUP‘h•Hö 7ù9Žmi{Yøªq¨áég>L¼°í#m¯p“±ãŠºÒg‡²{X|É«j¥ƒ1ÊööBu1½ZœÚÞàÖVv†¥xýzèQ­ÆÞàfñ€KµÅ–ì n’z ‹¯xåÀÃt¿ÑU‹NTûB_~¨Xv¤z»Sóò†PXím/p¿;Å-ÕµcO´n­¶Ú’½À=;Ø-¾Ú’Ê„Âê–â™a‰mªOôªMÇn7ØzQpsÅNÖIµPTUme{…/kkénðúåôb-‘Q[MÌo±‹IœæäFzVµ´½ÃÍâZDµò‚vÇ3ìÃØRK·‹ Uk-b¯pOLvCuQ§Z娿Jªõ~$xdK-ÍDÜë÷a/p/ø*añà»/-¶Ã2|²j Äqñª/yU]ètŸìël/pK>ìól/ðÕÑï¶XàÉo®¿ö«u8µøbSµ{[©¨¿Kjó¯|=2!Uëæ1üVVܽ¥hõ¢ºØÉVŒñøì*B1w\?Ÿñ״⯱ Â6k¶óûÕno Ÿèï©7:¡èßÅ“ýGôâ@ÿ.¾8Ðg£Fž8à˜µéà@tÞ=8õÙ'þxA`°æÁ€è2’ 8ü«p ú8BÅ>0úH8Be?p| {#ü›˜¯'þÍw:ùo"÷2ùÏâ¸Eü7ч"ùÏz¹Eü7ñØ‹ÿ|1Äÿì%åã ÿ&ŠÂÿ&òšÿ&ÒúÿØ™$ñÏ66KâßÄó›øÇìÀÄ¿¹ýížôg@m'éo]ñ¤&ý-H¹I /¹¤¿…“¤¿…î³Iàð„?rxÒß"ˆþ,åùÇæ1Í'ü™%f¡„?³ŒüªG‚ áÏÿ¶MÌT C=ó c±æ˜ðg–P f¹Oú3C|á‰n ’ÿyè ˜ üg–Hò ÿÙú]Aä?ß Düg–˜X‘ÿl¯HA ÿ™%ÒȾ͋ÿ†:-’ÿl®‰•CÁf‰Ëþó¥?Ãþ³Hìü³MBf'þù;æÇAc nÖ ø³HGL›  ñKLø3‹–=üŠÎFÊáÏµÛ û™>ûý?ß Žðœmü†ÖB%û™%f d¿È"ú¹`$ôó1‚ëÀ~¶ 2:Á~• û -«@ösKŒöóèNìö3 VrûͶÄd?³` .°ŸYXóì7´®8ÙÏœCf ³ŸñÊÅ­xƒïìbìg–‹ii_ZR3°ßТ«d¿‘7ƒýk"ú «sa©}¼À·º;ý,úT™:â3³°B:ÐÏ,Hbò³‘P ô³M.6åuô3 ¤oß…UÙ ~ãM}6hP) ÏÆâ¸€>å<úÌR_ÐçB¶Ÿ=¡Ï¶ AÐ7•lBè³Îúl“ú¢>³Ä$õù0?è›jfLè³³ "ôÙ6oæÓ‚{d>³Äã@æ›Z2”Ìg“ˆgùüâÄ^`¾É5 ‰|6Lü|ˆ|\›TÈ'ˆÏ ñ<“øüÈ?âóQÝkŸRÔH|/¼ø,bO‘ÏcбÏå>’øl§xÑø,…0¾„$¾Yر Ägl䛞´wŸmR^Äg–ØÀg͘¨øl”ÛðÙ&1 'ðÙ(KðÙ6`KŸYbZNâ›ÁJŸYzlâ›âŸŸà‹øl¯ý">·›ùìgpAä³ î Ï,+,†|ÓW=ˆÏ¹q. ¾ÉE|¶‚øÌ2Ö€|fik@>³ô@30ßd¼˜o²¸CÐgÛø´KÐ7¹²  Ï,1 ˜Ïwòû æ›\DÌ7Yº#æ3ˤóYØæ³ðt |óMS‘ùl“þb>ßÄ"óÙÀq{É|“mÄ|~q^Ìçn‚‚ùÌ‚eì~¹}ÛÁ}~%Nî[ÈjMî[Øä¾…®&â>–’ûª“ûV|Ìû2Vƒû¸ÀRrß0$÷q±øä¾…Å“ûÖ? ý6ú%ûY–žÙ²SÂ߆™ðg3Ï·þ·ñÀ'ý!\!ø³CúeüÙç¢n<„XëCügÏJyéþÆûqâßFEtâߎVmIœq$ým4êým”&þíDvº#Xô7™*)ú›þŽúÙ'ÒÏ„äçßÌ'ømÜëC÷‹ãŠûlÿ ülòò!ÁÏ,~q~~$?ÁÏÎÖƒ¢?WÞ|‚ßÄ‚èâ>Ÿ+8cü¦ÖkÉ~/ðóabÉ~¨ŒJÕºLª~¤¨TýÀNÕFSõãz½©ú â¢T?®uªS»Sõcë É~7&[Òý®?%ü];Qø»‚•îÇ¥5S÷»˜Ð,ÝïbÖ¦t¿‹­)¤û]L§•î‡_BÊ~EœRýl1Ö·êgŸþ“úüdÞªï”D?-Ò"Ñïâqý.–9HôSjŠ~ëŠ$úår÷ýlº¬EÑO5Èý.LØ¥ùÌ:%ù‰€”ü +ê$ùH~s?)~…µÃý,+6¶¡èW¨‡èW¸Š”D¿‚¦ýTŠ Ñ¯°‡D¿Ê¦Ïýl›8E?©¾ý ›ßIô«¬\–èWÙ\N¢Ÿ 5\•!¦•‰~m¹(úU-_@ѯf ˆ~U¥:ýrù<Š~U+5Qô+C4!úÔ6Kók ‡¨ù=.\/ð3Ëb“°˜>T5"¦æW‰EÒüZQ×^ˆ~Mý¨(ú©u¾Ð¯Ý*D…èר-ø7Q NøkZðWÙIð§ú>Á_ÝTÝ•ï#Á_Cz?Ù/–w?Ðïæê‰B¿Æjw¡ßsvõ%ø™PÝ^‚ŸÉÒí%ø¹†òáïf„àïæ+@ðרùLðw³ àïæÇDðg3IÈ{ ¿Æ¦V¤¿›µðÏô³°ÿ{ ˆÿW´Þˆ)‰ÿkGÅ7ä¨ä?«?ŒmÈ®øÏ* _’ŸyUàM¦ÞüE Ñû]üåŽô×P±rÐß …ø×QØ–ø×âþ1g"ñ¯£¯{â_#TÿîEÙø× `Â?®s™ø×!/'þ 4CKüX"ñobñ¯£0,ñ¯NÂñïŽÐ__B…}ÇÿØ€#ñoà«øw£î<ño Ú9ñÏ’l_’Ÿ]ã %áŸõ+ n#þõÂqˆ=gMú3.Nü³FÝ/üë¨GIüëhô™ø×£Æ/鯣…UÒßÀÔ+éóD½’ÑH=X’þ~ñI> þÆK,ø»oª„¿}$þNë¶?¾¹ã³q^÷ðar‘À×>>­yÉï! vßÓ.Ô‚øz|œàCRÈ|HF<€ò €o¡Òõ¾ˆ;‰÷fËÉ{ lòÞš¶É{ó'îÙ°n‘Ø·Ð:àH÷ñÑÈtO ™î‰òé#ßóò#ß³ÇÛà>„*D|6¿÷wòA|ûïé¡Ó—àç1Yß)‘ùòźñEfÉÁ|<½„>ನÏçÂ/¹ore¾ûF<Ïö!œ}`ߌ_Á}È8°±…ľ‚¢ËûÐ;6¹m“û"¢IèóÐÞ“ù gFb>ëÀ÷ãd> "«‘ùФ=2ŸšŠù ˆù ÛHŠùØàFÈg)™q("_Ì<Ä{…¥Úä=­B“yžñ”èÙAwÊóä™ç9©*Ï“JEæynLEΉþʧۓuý¹8ä>°_r_}ÁŸ£“gÀÂÁYïó5nÂ?/î“èÏñvëþ ¶'ø+xŽü8¹þ ¬4°ûU¼u‚ý*ªÄûÕêN°_åBHøWáÿ þS=ñ_eƒÐ²–}`ã¦Õ@ºîUÒ\عIŸ°ã¶ÔX"ÀÎ…™ PáTB …BßÉ~78W ¨R#‚@m +¼$ÞØÇD ø<}Å',v%Ô®ÆbÀ9I8Y³H¨©pbW;1àd¹$A Ü¼‚ÀU?¼žV¬Â±@¸¸°»&pÑ÷$4ëî[ôÛD1à`5]1 6¿ÚxNfdÀÉ„ pÒH<{é½ Ÿ§z¥#!Ðæoœ,¨N \ Ð8.¸ÿ–òã'!ОM.m÷P ÐÞöØä¸¤~’m©t¡ekÑ^²ßÉ7yÉ~¶$ð_¢8p_”ôÀ–í‚úàÀUÝœmÝw´­ßPj¸:dT‘àž*ÔŒŠ‚ AKea•¼C‚¶+8Šãƒ½<]Á³)J’9Z~Šm ƒ€àÉ’{àRIu‚ -,Þ~OÛoÔ縢‘càÙ‘…e‘è#^äù)×¢<¿‹ùŒ‘çG'´òü¬*Ý;Ïo2kTy~RQ•çÇÌ5%úÍÅ´>&ú-&˜)ÑoÖw¢ß‹mƒµ7žeìWÂÀ¥´fåùMVSžŸýÐ}æù-VŠŽ(Ð2¿ÊKø³‰»ÎB ´>î×$R|nÖÈ#Úl‹ ´ÇÖËöi˘‰§ÀMƒ(ÐÊ×8AgƒŒW¢ŸmÂöNôÛI|€@Û+ͪ„@Ë^[Nlà@»wQ’màåò!@Њ@ºTy@о/ ´ëä;?a‚ ¥·! h›½Ý/ÛçÙbÓYŒ™~,é/ÜùAÁÍ—EÊõƒÉ rýª‡h‚íT.ám?PRý¬f¥Ÿ‰ hL¼lŸÚ4@°cs¼ÁŽM¯£RýZgÒ@pßp[Gª_Ã~× Æ |Züæ"îûbæ!Sý:ê ¤:nçt-×붨U-SŸT‘í³S¦N?õûuܾ_V´¤2gïSD§\æ¬Ý.ˆ¡¢%†b›†RCª[uíµó¬ÕC±MC©!5¼nvJ-i(´ÅPlø·×q³Â˜Ó>ߟê¸]ó\óBn5gû¬ÈöüsÏŸ ¹íò?M›*JôÓ-1ýù—êiýtcÞÓ‹R¹7Œ•J´a¬\¢cE/Žõ*÷Ʊ¢DÇJ%Ú4–zi¬\îcE‰6Ž•J´i,õÒX¹Ü›~ *ц±r‰6ýlÕ‹cý+…Ül³y2ý~*ävÿY!·oÕû~,äöz}+äöú}rû¹fà»Ûï<"x}{ þñ'OµÔé7­üõzh§D½Õ’üózhSõÐ^uÊÒ?£¬+¢µòo¬ˆö÷*¢ÿ×X¬—öüë{m´§ñÿÔ¿¼6Ú¼êbm´§ñ[m´§í¿õ¯ÿú¡MµÑêŸ×F«ÛKAxz;jÌM÷ȯՔÇóÞ_ÝVÞzàéuV:íº˜b uÇ=G¼œ–zýBF¸¯m›gîö¹Y삌êê}úò½‰-?›íñäQW€S³íkÒ9–·øÅŸèç¡™få‹o&û5ïãg<áÏók¾ë“gŸ“Ÿ*´°÷&o¶[éBBðô†£ýžàç‰Þµâµ¾=—ö|ÅæàIçO›ÀW$¶2h³¯fje²ºVõ%_+ Ö®úV6¬7ʵz!Áz»e°Õ‚üê {g«•6{vžÚìj¶Ý„Û챃B«6û3çzÓcï9ílÌ‚ÂZ··LX.ŠãF«^>ú8;|ÌMÇꙵv%ËÅi(¶=}ËÏÒÁ¶êòêÓ€`[E”¬µFÃŒ}ÍvšpÃÝ­Ý4\ [ˆ¶5$Ç´6mkÅžmkØù«µíÑ69? ýB´­ñÞìѶãiëѶÞqßõŠhÛ}9“´Þ–lšÃGîn»§C}³Í&ܦyãÃéá6+ªìͷᨅpC‘­[Å“£ÞoüÀî+Âm~;Þ…á6èùÏž‹ ãÓÏsªÚÝn+íî ·ÁèÒî¦ ‹rzŸ öË=ẘ^Ç¨Ý ¦‹‰Ï´€ébÁÄÐÆÓÅÄÞžmø.Ò˜Ú¨ð],ßêíi í âm4Ø.ÖdK‡íb»I¬›Ñ6ä/6ÛobÃ;éß‚=&ëb{è´¢_§&ÿ8N®ø‰K›¾ßÎ uo)j;ʯ·TµñŠ8[A¶G³˜úð#NÀ©Yp| œx‚ÍÖK'ÐVù0°˜õÁ´ zw³7øÁ4 øQ ¶†ð{;ŸÆ‘!‹#a[mÏ]¢|mÚ,øs.ÙÎz"me™Ú‘ko½E±Y4åúúÏ{uÄÚn„7ÛH»§h&?žXÛ µµY4êÄÚ öih'v»T‰£6bmÃkù4ƒëj»½ºS;¡âqÔ#©5ÛÊCm¿ƒvµ?´Ýjƒ·ÙP'ÒÆÝÆ›íå‘6¨äÍö€:‘¶…N;Óx!e!жQ¸¥ z†·œÏ¼_m|á¦Û[¹4mïS=Ðf‘¬#ƒwÛØãTûAµn»@µpˆÔ=ÒfaŒË[nµYÜå<ºc'Œ±ü1×m({xÛæ—_ÎB¨­Á +*=;ÙGÑm¯‰SSkÁRÕ±ã wùÈgq;WÃEÝ^Ë'ÖÖ`éVݼm?êlÆuâTۻ܈µUäfuÛêž>­âOÄÚš‹òÝvšלS·] N¬›õzy¬­#ßm·‰ã¸Øã´Û‹ùÄÚlÇ™æ-ˆµÙeú0 ±¶{ð¨ŽXÛínÚL¤õ–@ÛD}Šn›@H›Õ<“¬ ‘¶‹x·M N¤m`÷n›@HÛ‚¤Û&P'Ò6ñÄyèiCe¡noæh³mÎwkof{rŸ=tÎÇ`oæh[Ø¢ÛP'ÐÆÊ¬ýlnçÙÑ{›´í‚»¯-Ú6Œ1½ùÂé|ökî¶Ôó™=+UlÓÛm¨g³UZN ­Ù-Ū´qO´ÞÏ^\íìøá ý\W³CN¬«Û›¹ZÍt3oú0ãvh¯°ºmÕíTÍ3úºmu±3/º÷³W³],γ¥Û6PÃ@ß´ž3®m5íL,0Øm¨uŽB8±ÛnÏýÞLõ›ÏÞË× 4—ʺ½—OÝw{Ô“Û{¹Ø¹lwWïc[YÙ<-y~.¶T³s Ø7»íÕoŸ¹ÏÓö‚ºmž7^(Ýö‚v.3þ£ÆÙŒ«Ù‹~*Û jžSaO©n[A­Óg²Å6¹}Zþ˜þsóqüT÷‘¡šÅ¨Ïc¿Û˹ÚÉ×Å–yöjkg§•3-[þ7;ך¼ž}öûh¶ûŽ?:N5;—1ÏQ(åð´ Àa7ð,þúhž¹šmâÏ?Û j-|ÞÒO¹Áç Žçß jØDÒ~œ—Í/¹ûÀ«ØÎGqüÝšh/ü«ë“ÿ¼^â?7Aeþó·{ðßí?äÿUg;ñ—ÏÁ0$þÃR)ð[Á&üƒ«9ðÏ0Ò‘ø7'øg`ù•é¾› ?”¬Nôëv¢?ì•ð¯Ë„…è&üã븸hr1*´dïB\¨Ï¸ɸ¸ì®NH¬¬°…ýrD€ªt T+àá^º›¶Üö(4îZNØB±6A Õ$ð…")ðÔ6øJhtì+R ¹€|©F ´ß墾ֆuO¨bIÂ@#hÿ‚‰§þÁù‚‰Öçvœžú>ÞxJù¹€9‡xRRúˆ>m1à{]0à…bÁ€bÀ Y0 2ºÝÄ“𚈨ýÿqïÆà?’‚ÿ C%â¿‚,­à¿‚MÁ‚ÿ ,ÕÁåÆÅˆÿ ö|ÿlüWð4,ûm õ@&-ÒÖX± 4Ã…ElQh+BïC¬pÂbþ À†d9"àÙðL›xò%œÅ@vîÛY xòÏ0¤À“Aá,œâ,€à±òùAAëRý €àñœ‡ 8¹Å›@ðä>ûÀÁ“¬ëhT9hàÉeð€ ;ü©@ÄU$´Ø†<AÇzA‹8=:N_ñ&í™QÐ>ìýbAsãû‡L´>—ƒÕÞ{__’Ï~ÅÞ,8'ö¯ ^ž**<{û(@AÕ šýÝ×=DÁÉ =¡à±¿;@-æáË]¢à)Fí¨E¤@(hî1çY¢ µ ´ ¼r¹ðYmœé#w˜ïA ®êÔ7è¼G¶¥8Ðl-¾,#®*äÜ,®ìŽ[r ENš£9ðhê çë+QàÙuó\)Ð<"¾X'Z´Åƒ ¸: 'Íe¿¼@ð˜DÎçB´ˆLsXÜ´ÞcëY \Ђr8žAœÎ@‚f+>H£åK‘ õ&Á³•³´p†|$As ¡$h±gOüÅùì‚åb|€DÁå@ <ƒø÷OغxÎäŸ 8ðü“zµm´Ào1‘"O<±*G³ßýº ˜¾û…ºÄÀÓ⟠0ð¸Ëºã¤cà)‹}ûQާ¥ùÉOlêH+ÄÀj¦­Ôgx"\ÅñÍ1ð9ûMO•îêÃ8ž‚Ñ~óÏ8bÀÀSõ§r ¬g[nÙyÇQã6` —ÜöqÝ­uÆË”`ÀÀ ëY`àñ1y´Ê1У}«Èý7 <Óòh0Ð/Ç¡Ï1Ð/Ç‚þjÒ¿Z%-HpàG&A3ícIpÓÇ%Ü^Õ:@p£€@p2ð ¸rN¾2‚§”HPeœD‚§î˜TÝ!‘à)¥ä¨ ´o¡½Pðp²r´á'Ë"Á³€s¦ NÚ¿D‚§H Œ Aëãë_ 5ø“U¼F(hY¦å¥b!—PÐrS]% šÊt»ôÆ„‚ú‰”‚¨‘PPÒQ°Ò#"¬ 4+vTdnb°àEª# ²P° }~Yðž¤W²àê]Á‚¶xz³àÝ)Þ‘‚˜BÁÛk/ ž,®¯L‚Ãw ¬¾\ ´<h‹_Lrà„’­Ï›ë"õ‘oìÇH%œxn쳪ÚÜ[‚ƒt‚ ÍÉ×KÁAP!ž®¼ ¨‹@ð‰rNé\ÁçõáW(l\íÃðë!*ª@ ZËEAÿ!z hð<¦œAƒÓS êF' ž¢oÎZƒçv½0x™Yô§<ŸhÖý¥è蜞ª–`ð<Îï…0xV=~.Àày•úQ€Á“,ê<<ÁϬ ú+f~%<ïÒsÍ€Áãëò.€Á©aОµ~9„A;UÁ µœð¶`ð¬÷¨ þIÕ´$žY¿÷µp¡`t •%y[A7_K’·§Ô%¬ìB%П’ ONÁWâ?k˜o#èöÄÁmc GM ûÿ¬ÅCÀR7Q“J 7 KJ ס¢ÔyR7\h¡"‚J µò‚ž*yA}™^P<£’Ô3Ñ“”‚lXA¹¶/(=|R­œ€E%pãÆ%pOÒ•@ ;8XR ´Í8¾À÷“m4…x¡èCà… €Ížä?3¦:‚‘ÿ.Ò²øïBÝ®À‹FIà…ã/†€¶ ¼h*²ê™°ÈÚI,•-ÀèC,]Qî´Js—°Ð3H,Ø¡%° Q5 ° Dh@ µ¼!Ðj ;K+ÝÔ¢ÀZ0Ž(±î @«Oæ¼F daÞ$Ú?“ è!‡— ˜0°øNEI¤¯<ô@ ,Ø¥#éÒñ¤RÊ=ﻤzü> °2N ¬í- ë-Ö ÿ'•ÚB D2s  ìÞÈ2€•ʨ°"ñ<å`„€¬îØ u=©^k8°¡b]± l“RƒÛËzŠ¿•ÀÆðïyaeöë(hìÇŠÁb¿Î÷„دóòÅ~z¶Ø¯Cš öë4ÿŠý:½Ób¿Î˜¤Ø¯£”WÀ_§[ôÇBrA ÿ¬XƒÛ;Éw}[BO{ù5Yƒÿž>#ÿÙºåƒÿ¦ ÁÎâ?¤'þógþÿ\ãþ¬Šÿ0©„°þ Øîþ5¬ÿ:-—Ä¿§ÅWÎÂ?#G;á_¡bGüðšÿÐ ÿ.Ì<ð¯QrLøçø­<áA2‰ ÿ(T‰ÿ9\ü7±åqðßD Íà?nü7ñ®þ³ÊDNä¿I×›øo^ùoaíüÇ-ý‚ÿ¶•ÿ­Jíü·¨™ˆÿV#Ì‘ÿ˜¸ê'.<ìãÔD@[ìùÈDÀ-›%pmŠ}DÀMñTˆM†÷…;¸Q†0P"˜pcÇ¡@ÀR¥€Ló |Z^‚ )Üîð$nº¨E€…ˆB”(/=ðÂ.O!^•GQ¼ ý¥¹ŸX‚ÝáB@ØD©^&Õ@˜ÙC ¼Ú%ÿÙ17L¢[e;-K ´Ý+œí(^4¡“ÿârÉæ¸_üg#_Ÿà?§¿øÏü6–hk™ì ¬ ¯üwÊ€¸®1Ð6žxñß)Äá$G1° ‹Kügßo1°Ü<9ÅÀ=õ/Q{±àõ¶….ì«’m¡^Ÿ!l¡ƒ^Í”¸ß,8ç ÎEf“+tÿziÚû4Xpñí(\4FR`c  ’Q>%¢Œ}‚Á BYPVM²à®"?°àî°‰÷àQdÁ kbAª ÔíÇàS d‘êÐ/Úå¤^xk„È­äB 4xpü¢XýX‹™ù…Ò ~·!ìfr ­ü(ÊÜB>äÀ"8 > møVIƒ•ø/¬(Y4X)" —ðÂÁæÛÒ¦ô@fŠ‚À)=rK¤Ò¾r í¯!ò³ ÞpýI „);`°“M#;~Rœ¡’Д8>ÁN‰€ÁÁäPÁàÄοƒ÷Í´Ceò«ŠìÀJ@# ùE ƒ²Ñí½á8-´½7_îPëóƒöt¨TvàDª™Ãàâ},\t;Š·†% n~¢¢A{å¿Ý¡ .«¤ 2š ê§$MÞ·¤ òû$šµ žRà Þ âA{ xLŠ‚²Á ŸÅ!ð/' :¦ïá$O)O0Žbž „œÈ,|L*OðB…ÖÈ,„å šÙ÷E„‹Û6Fž`Yˆd)OÐÞ”.Ë)Opà›Èy‚û¥ .ýÅ…Ï‹Æoeå V¤Æ(OÐ`Þ‡až`«L%dž a­_ óÖö‘'Ø|›…Èl(²‰‚•¯­æ¦ÅDÁ&£'Û&^2SÐÔ¨—*hÉy™‚7/YöPÑ%SuM¥ vdUDª`Ç}ÂÂõö†®Ûëðç4Aø>„æ‘sµŠL¨lá µgäK\AŸô†Þƒ}è ­°Ò†7ôÂçÞÐ9Ér`ÂÅô 1á9 ‰ƒð†Þô¥ÉzÃ9.o¨$yC3³dIt‡Nì©îÐ-KÃ:P'KöÐÎÜÙCïB¸£?T‘ ¢¿ñ0ˆîF´¤AtWÅLÁ .ìÈdÕê0ˆ2¯: ¢êwD  ‡AԪʾp‰OÜ º½fuøCaülQ˜Ù[æPÛÒ•<šC­~ã+MЪÕ9wÈjÅ]}dšCm…äË4Ákà UÆóå·Ì¡Ïª¼ý¡ æšð‡r‰*èîtÒj2ƒŸŠþЉ@«xðx_’àù^’à’m›ÑE6 ¢¨äQî@¸a@hi@9Qðôq`%Zâï̉‚æKüÊ4¸&s i]4‡=”ÞáÆþ†B«·V³ h=|Â}Áš$ 47&Rù„Ö!îPæÉ'w(ªC‡;T& \Øã7€ÐÊ’ø8r‡òÆ wheÚ Ü¡Rû„‹8J ¼©Ÿ '2Žƒ±èN<Ø¥.YJɃ[Å‘TKí~®(±rÏ,ãTîˆBA쓪¢}vŠÃÔ釣~¿–Ú÷ËŠ–(5öqŠè”KÝfþ­ùR£% …¶Š i¨ÑוÆÁŸ1ÈiÐþW:|Ú[‘¹’þ¡©%a›ÆQÿ½~Úm[ ÚgúOê§}«sæõÓZ®‰öYíßR?í§Û`T¯ne¬~º{Cò¨zq¬¨ŒÆ±re4޽8VTMc¥ÊhK½4VꥱTMc¥ÊhK½4Vê÷?+£q¬\M?UõâXÿJý4{ôSLþ§úióÏê§}ûÒ¬Ÿöz}«Ÿöú}ÖOûùV{×OûÇâÏŸoÁ?þäI–:ýÆãô_¨Ÿv[Í«áø§õÓÆbý´ç_Z?íùÿ¬ŸVk½J˜ýný´÷™¢ZŒù÷Ÿª¦EQµëÿûúiÏ•ÃzÁúó[¬¨6Ï;pÂzÁ úgaë·›xZ`½˜°XÞmÃz1½Öýp;/&²î^༘0œßÏ2%øPcåîÍ“°'JØßݱ]k¹‘„=½„ýÝ’°'6üyÖ}Hž0qÝ}! ›xõ´ {!dr÷$ìãÀ}_H¶õìç.HÂf¦û}W$a/xï»! ÛÂ">NG¶m¼x&qsíIPoÞe {ñ㺧GÛNÊúù¸îåѶ±Iñ´x´í„„½e{´ÍZN´í׉¶™¯çÊ=ŠGÛÌÆãêÑ6k9ç̓m'|>œáõ¿<ìãÞl;'ï3<Øv¼?~ªéÁ¶cõ9s8[~¬dõ¹‡o÷tÂÏþᜰó ó5£KCžÎ¹%ÍPqöDÙÈh¹çÙõë‚§ú>9ÆË[ŠÒkƒŽsŸ åí!ìê-¡6æÆßVé«#ÌíŸÞ\µ]î7¸OFê‰{ƒÓî“Í9=î3Z"möjº=3WÏù³Âuqas–ÛŠÛ_° žŠÏ:?a…ÛÝ'ÊvMüP-wÏ?ìw¯‰(ÛåÛ³Ü'[¾ ÿ½Íb«Æ{mluĺۈähvnîÛ*_Í® JÄm%ªí‚Äçw`5—7Bû'>{ïÛEA-—{ß°]0[¥Ÿc»`þ½'œ¶‡¢µà¼(Þ<-p^DËFÍJ¦ÛÙÇuÁ|aÛ:xKqóEñrúãªð^hBãjð^$À «C³a Ú>Ê ïEA®Ê°²*¶ ”V3å4 2ظ¬¿§Ö‹è³a½( »ú” Ö‹‚J.£X/舥Âzq¾ÌQ6?«ˆ [8©¤Âüð¼j`¼`I‚çQ%•øå• ãEŒ³`¼¨Õƒ‚O‹/êÅ«ÛKR‰Ý£^0^TÈô£/*’«G­0^TØ Gm]…}O¡Úa¼`ížQo/X÷ëy¨Áxa#{ŸY´uåy «¤[p.ÿøê‚ñ¢B<u/m]é[í¶Ë…KF+0^TØšG«0^Tz£5/¬bÿ9yëØðº"òá»°ÔÂó±.=é#Åÿ„û°·sAzÿ<ìíì…4Q9î2¢Æ9µUï8‘ßwƒï¢Â5žEŒs0>ûƆבqø.*Æ=Ứ¨3l3¯Ý^ã,/*"×Ã^ÏhðOÝÞÎîƒpØë¹âä¾{ò¨7½sçÏÖeœóm»F‡ë¢"–4Æí®‹ £ó°Í¼ª… ?ó„í‚»7 ,—Û™ 4hÄO‹<_±<‹ '=Òàw«hPU⃭ªŸ‹4H'hÐàu‘ÑHƒò8Eƒ’Ò¯ŠÕšpðjDHâàE8Ú~‚‘ÄÁ /fÒàÕ±Ø Zi¼ý•iðº?ið‚4xÁY4xq]-¼à¯ ¼ ^ð^ˆ­–‹œI ¼`E 4 º|% ,…ûÔ 6R "¼ðŠ "¼¸ì–‹}H„OŸñ& EE‚ ~gA„gañša„O²Ââ‰]Áƒ…kEò`Ç‘u"ñ ƒ!ÁƒUóƒ j8‚Ńeȃ Y8WC|ºø÷",x*\"dnS𠽂mGo';ò ë+ã`AyšÀÁ² šÄÁ²H{ ¢šƒþÀÁ‚ÚƒÕ0 <Î ‘›8X6~CÂÁ‡eà`/p° ¼pààs®ùƒ0¤$„Á?p1á`ñ­æ òÁ%´+vb$–Å›„þ¢„2ñ`ÁC'Y‰ÝIܾ2 Íû'XxÖÐÞ´9Ý’@æ8&Q^\pàFY¬àÀ_Lpàö÷m`à^äM‰‚•t™DA%i‚h &ˆ,þ¤ ¢lpÒ‰ I„f²`÷CD>gÈ‚¤Cl”% VŽ+Y°ð(邾¿|’QžQ²à…Bt! ^Ø("dÁ )©I¥†*Øð U°CeU»b%Uð¦&™TA¿ÅCÄ&²I¬T ¥ VH~)6I,ˆ«†*ˆšIDÕ„\†*5a ~YÜÞEªàæAItô UzmR§¿–’*8j U²¥8°à×hö ª—%tg}` íqè#âÛ ÄWž0¤# ,¨†’„AHâIøtB\ÐËBì`±½ù[tÀ”0Ø$R¬ ¯Û/ï"]`(YÁ´$ B7O² ÊL$Yð‚Š² —\‹HGYp“&% b¦àÀvI(¤,¸I“ÒŒLºà¤V']EÇ“.ˆâÁ/]Ð)%tÁΣ’.èÂLè‚\á‡.ˆÌê‚pç']°/% òg&|Öƒ~CŠ[&”²àÂç—eA¿'B¤ª² 2¨’,È{48ïôÄȈ˲ +T! ¢®{Aì>”dA*,¡ 6У8 A°¡Ê|€`C½á$ bA ØPÇ+@0úHD"g/ü8³0ò aðëEÈH¸¨%ŠQ—%Qà NH ì¿@…„@ÈA ïo¢`§ 'Q°QÍ“(ØðrQy§I”T'Udª`aŸ¤ :¡‡*HOA¨‚xyIDjj¢ÀMæ“(ˆ…ë‹}ÜŒó„‹4I $p†*¸(JDm݄ˀ^ 0püò†$ —E¨‘(pP&¢rj¢@l`ô«sa¢@?ˆš ¶ùLˆ'E‚ÀF•ØtHš`ýúêéÏ4ÁB,”&ˆ½/‚oèfAw(&Ið,ƒþI)µø•7÷UFpßðPâ>è÷‰û*L—Á}\ÅgîƒôV¢×Ëz×îËl(Ç…+ ûVä} (îC©õà¾ë& ®¨Ç’àÇýgüìÝî´Eð»Ðàgå*^BàaW×âd Eî^"?쬦Pø:ü5b…À]%ûAd¦V»Ó8*øƒÎð×q}cŠ•@Â?’g(¾!R¢?HIœ”ô$RÞ S(ÜfÉŠÐc2…–Ô6J Q‹H-°v+l´–R Ü‚"•À0YBÀ “ )¦¦$"F—¤@[C „•'1 `#A ,.…€'„K,A Š_&D¬¢(÷[¢ÀöA„'lä0B ýßÞÐ ÅŸ‚/ù>IÏv¼)P§"^ØW/‰T¢C ¤;Ä@ß iƒ©"Úg§8L~8ê÷ë¨-+èÔv?Z¢äÛTÇH ©äزâ}L*ô¡Ô’†B[ ņ4Ô¾,ÌçY«%†b›†RCÊÞŒL™ô¡Ô’†B[ ņ{M5Ûé~Úç›kªµß¨“fÔÓfûVÎêöí÷ÿ±£o_æºÕ_û¬¿õ;¥Ø¾ßàó”®N÷÷?ÞÎç5ñ*׆‘R‰5)WXãHÑ #½Šµq¤(°†‘R}5¤N)—jãHQ^ #¥êjI8R.ÔÆŸkWó‘rm5ýÈÕ #ý+ØÎƦ'‡ð?¨Ûï˜ÛÏt{÷B˜i]ÜÑ2‘Á½ t¯k!ƒ{!=u]Ü åÝV¹Á½¤¼JA÷B”v•Z±û òdž› Ü õŠVév?A©‡§ec÷d”/{öÞ0P]Þ2ëFx—m§Ö)ÎË9ûˆÁ®yDëì\â þ‰®ZPƒƒÃ¬v¡ÇÀ—i[s,5}à¾Pƒ¬eïç B`ñßàÁSý\s`/cÈ›k­58P²sYuü†sp_ {c÷ eÅÉoä>.oñZ½å\òn×/$ýe¶ÛÆþUp='ZØ¿ Q<«ƒ‰ý«¦‹Rkû6…§Å¿{EûþUÓUµ—Gê”ÿ¸¶ÛZ}ûY=ðÞ°™ñò°Ì¾JEEwì9¼¯Z°›ñô¯xÛ–`©¬Å663ÆÆ]Û¶C “Ëî‰64ܶ#“fÅtÛ;úBjâågZ·ÌÓËÚ]›Û4w95GܨzzßÚç´œçÔó½<ñŸç³–ºð G…†m;‚þjé qlO²¦¹¼Ïxˆ#yÛ–`3÷ƒÖ‡8öFÙö†.8Õ‰ n{IWLâ<³Ÿ§2kGÕê¡:Ë>zmžâZ>-Oq„Ô¶m扳—Çê¶m6qòó6ض!ØBòYÓî:=VwÁ¬¼mC0&ÎâT±:–›Ùö–.°ßúÑ cu—/ƒv«ŒÕa·÷ݼd· oÙÊ/wë R9ÖµÛv8—Y¶#ØÄDÏGÚ|¼|ÐêPÊñây~zòÏ£bÛ;šuÏÿ·W´ åØgÛ;šuÏ{rwÏý9-ÝûØp¿'z_Êžõ3ƒz^éùs ß󪼫†„Öê}VGê,²¶í¶á;8þ…}»%ØÝÍg÷ÉõË=ߤ½ ™;{ˆàÄ8*ÌÌþS½Û†mºžG8ü¼y<6ó{5Ø^Ø¿Q๢øv` Ô–„·¿áÞpb‰0°„p}& DfUÂ@Ö. DЄØq&aà  ñRIˆ·1ºIÂÀ7N¼‚Y´- pb18ñ œ¨ª8áõ œ¨É-¤À¹>)åà‚'¶ÚAÞ@ $gÒü8¹h-_™Ÿ†åˆ œ(P8a  œ^ $ p.²$!pBl œ›€G4 w,$N‚ƒ pnLJHƒY@ kÜN¯À–I®Á€p'¼x&1 BÆIx.±)m` òt"í'q òa¢âpâ@XxBJ ñ' Ñ!@°¸ã( rø’IQã>`Á‘ݦŸ0°º‹ 0pAö \0C&DFup úˆuyâÀ…”Á8Š ¸" ZŸ7 .¨Ö‰a .ìë$¸È$"Á…m̃—§….ÂŽ@pR‚ ®žÁ…2¬‚«ò‚ ìj .ÔO \ˆI\È\ÝŠ‚ ›¹.x“¹W€ ·¼.O× \(Kh×ô•1p¡¾O`à‚y(05!²¸œÁЉ5%à‚W#@pÝÀIràÂZ¸à%\Ø#8p¡R_p f%\_‚8p!—\h _ÊZø ` \.ä˜2;10p¡„ $™¸¼jQ` bgÂ@Y1༬©Á€ éÁ€ ™&Á€,L ¸Þèò|ÀÅW¯paûÀ…ŒÿÀµˆ{ÀçbœN€ ï¶D€xãˆû 䦮A€´ .j \ðVr‡x! ™€Ë„€–Ï€(°hq2´lÅñ€‰DÀåË…D€0W.·.D÷¢ˆj õq¢Æx"@„I€çÜÞ Ä;3 ÜÓ"@;ÊÉMxù¢Hx¢mŽ„€ V&, wà‰*~%þ;%^½üwÎäÀþ;Ú»ÅC‚ŠøO:ñŸÂ•â¿óÙœ $ÿ î*,<×óÀsÉNŸAFðd#;ÝÏçé- Àóa‘OpÐé xâƒÎ„ Àø2‰€§ÏW‚@ë²ürgà3Bàiñaç³yA "¥„ÀóÑx PQFAàù^x¢•>0ÕXîtùj¯z6}An‹ ¸‘Ã#´0áWæ@ Âyr ƒ‚Á›UÄÛ³-qÙA¬&Çþ ?ßûôpìCCìáØwD"ž<`Wúû ¥úˆªëxRV¿ž|Ù¯ÄÇáä 8ð¸Èœ ÁÇÙõRµK…8ð8‡ÑÃ~õDa lËÂ@í ! ”}Vx¼»Þx«œßOÕ QÓ‰x2™^¨jÂ@í/œ OɧXãK <îÈ—x,•Þ<ÃøÏ’é‚*G"T ’@Pû,ÉÎU<€ Ø(ÐaÚo•-ÁSˆå¥ª4 Iðldð"Am% <›8Vµó‚HÐúøº‡$h-+ ‚§á+àÙØÀy x Ez€à÷%׫KAžª&”ÁS/Åù h-öÁSÅûmœþROË Oi–L‚§z‹w ZKy)‚§Ú¥&PÐZ #­šLy¡à‰­ø h-þ…“O§>p`\9púÝG<»Èû‰ÖâëF@àiøJ xöøJh Ž=D@œ…x†pÝh-þÓž ñ.ÀS<ç+ñß©¯ã’øÏZ\“"ÿÍ(|ðßiùJøwö¢ðÖ>þ͆*V¿sr5àßø…öîÿι¼ÅðÏþøNý§ÅÃä¿Émä€g–/<üÀsj¨­;€gRŽrÀøö €6Ž?{€g ŽeÀ³½‡·€ÏÞsN€çr A€Öâ¿m ¼º"ÀÙíZËý"@kñoh NØDÀó);–Q-°ìkDÀ3°ƒ#ð|>20R‰žíXð<“½ÅÀŽí $ò±(œý"˜R lH: 1жòЏ-1•;aFb`£F,1ОqÞ‡b ¦%1ÐÞÙzT¹ð5°­—ȇi¨úŒ%vDÌCäƒ2ä@>¾BŒ£(² ZèÜö($AVI°!0’`s3l(‚U CäãUŠ`GÒP­V·Ë}TùX Eð¹¾ö‚Á#{&üG5Ø×IC~à…úp€Hk D> —¿NX¡¢¢ìz@”'LˆÂ‡!ZQ¬·Ôú8¹QܨÌB`ŒC!ÐÆùÊ:àFñÐ-„t@:|BÜ/þ“1'tÀÝèФH¤5½’tC 7(í¬áEað·ôëà Y2›A}àdÊÑ Jý$›Aû‹ÿŽÓÓ¡LfÐJjLnÐëÅG°Èüw”XnPØ¡²ÔIa…æü2ƒî·¸ÀØ/3(,›2ƒRhÈfз h¹‰3yA}Rá½ácÊ^P?(¬ ¾æÈVÐöaEf’é ˜2 ¢#Ù êZT@ÚPCD=©€ Á‡ HÀ ‰nIÄ&ŽIœD4©€âC¨€×*à$Ç%;¨1Ùzû8”å•Èu耠˜Q´%É€¾#qRQÏ:©€(î‘TÀpSšKvÐ ¸G?(\8ÉŠ¡î‹¶RúAuü  ¿ü 0°&?èõ¢ÀT“þŸl½¿™A;ˆ/Ì o p£ÁË :¾yAq)É ™0yAï/hý”å;Í^Pÿh ÊgRö‚f+hà =[AÛ O(õ›Ôg™­ þS+(vÃzYA• JÁ4{Aýi^P>‘²´ iÅþ o3¨·„Ôoâ—ô…€§c¢Ì P˜Ì ~a¥}5™A]1Ëfбâ—ôL*¼ lÕq“”q®°‚bûÇ—¶Ódup“¦d½éÆLVPB:A~.áÅ&VÉ Š|“”OÞp‚ÂÀ”œ (œœ ŒX…‡“tП)'è$"Ê : Q„%ç’è n8A'19AÑ"'(ö HNP¼’tAÎ '(ò~ ŠJÚIäA¡bKËdEa d…_êe½^ø—F–tAz +è‚4(!¹/+¨ÆÙ ê§ÊVÐþQ¼ëeõQ’´¾áïº8nr‚î!ûÏd'¨Ï2;A¡\JÄnIÉ zýàuN '(^0o'èþ®‹)'(ÄÌlõÏ/A‡s]r‚B,LNPƒá¥*NPF>^VP§¯dõ«ËVÐs(­ 4df+¨ áE¶ÕÛêg—”nÛlõO+ÛA¿¹Aý†””ã†T\'7hÊg7¨›Á~Ø™î/Ô]{9Bw;BN†Pl¤†P”KK†ÐE‹¨ ¡¸ã“!tûÃ=8p!¸¸X`@¸àÞ 4Ë–E¤+8pA› \,¾ \ÜmK ¸ l—Ü©Á…@Ê $?åNð™òáHI‰°J&\@Ð@ÁýëM‚¶Ú|I² n–y nÜ— 7(¸ E=¢àÆ&‚û RàÜØò,Ppc;S¡ –BÁGÁ‚Ò–PPI.BÁ}æ*±C(¸'©Ž(¸±!R àžl! Úá+£à¦("ÜT­„‚›œBT¦‡Xp¯OK(÷« !ðBû/˜d‚™ª !ð¢&"%ñB ä“<”À [‡x•ÔÀc’÷>T/&ÄI ´s9~Q ´€c•@lUBàU( R¤ß>„À«â)Ò\B ø!ÚA/$ H ƒ5Ô5qÁ`Á»,`' ì·&ä&Aƒ®ª Á‚ØaРN.,ˆ¥lå*¶+ÃWTð)e›?L-SŸTJí³S¦N?õûØÊe…¨_ã«%ꓱMuŒÔê“•ËŠþµ×PlÉCy[ y¨çY3~Õ׬ْ†B[ ņ×P«¾Zõs˜U_ƒ¬rpÿžÂkÏøÔõø— ¯•û·ë®=ËÖß®»ÖÛý¿[wí‡ûúaØñk¥ûúŸoãâÚKê…±¢¨ÇÊUÕ8Vê…±^½8–ʪi¬TWMcE/Ž•{q,VÓX©²šÆŠ^+÷â¯U¥Õ8V®­¦yôÂXÿJ¶mh>ÿÃ*°ýÎõχãÏ?~¾…ßÔpŽô—+°m‹?Ëì?­ÁfÅÆþ×O•ѾÕ`³ÿÏlw*—ö¿[‚müP‚íïÿã ¯=ߢ¹ðý+kóóÑÔñòì73ìÏ2ãi¹Y¬ ¤mãáò´ÌÆ·ÓÂ(æ÷@(G×3îÛi©òùŠŒ{kÙ¿)_ѧ qÆ…§ÅŠc£e{ ç€ü§…s@lôi¹;[N0÷i87þœí’ý7Nd~”¯ÈÁZb Û‡mœÂô°¾µlµøÈÍvXò–ê#7«¼–é-Í£tû>-Ï<ߟ“jœÂtxZ΄)µ‰„û‰ÿ¿<»ÇZ0Æv»+Û•«_X£ ÃZ0ƒÅ¯¥sË#}O‹øõÌ©›åýÝb/oi~}ýî¿X3ÏçÝGû…Xýí_xŸ¸šÛo­¾È?q-f;øŠ*{ÏÊëÔõð4}4lNÉÏ{—Åm?ïÍëǼøÍ/äî7[Š_Øý\,·w¹4â37_GUÙrMÌaÁOj-›åš_ÍÙÄ}ü«<ÅñÑÇ?­“~á-xöÌî/™…ˆÅÓ‚9¬‹ŸÎŒ9àrfeŽ9›Þxœûä<)çò9­ëòø±¯kÿ‚؃3/Πð ¶8Ä·Ÿ³J¾ê÷/8À§µnç ÖY|ZFûži‹SÀ^lO çãØ>£èƒ³›^ë-xîí ã'¸Ëâ¬pGnËÕò–á3ß1|Z|ªÅ¿©‡í8+öyæ?žá{"_»:U>-&œy ž–›S¨üH7§€aÊu-5to)˜µSöì¦ð(MÅžŒ¿X[¡y gPq¯ÙOœüÓ³Ÿ[Žz¦€9¡Á>%o¸qyûâœ[6çäÏi;ŒSðÎózàÏŠ!0w2Z|ŽöV®¯CîÎ -oˆ«ß~±%®ÞÉÏY [&ZNý@—+qîíU¢Yšó¹¸ éÚ{<-e²„>ñZq >¹Ú8ª_½‘Qo¢bŒ³góiñçA©¹ÚÑ2«Ï)Æå š‹OKÌ ad«qå->v-Niøå¶29¥-¶E·,¦q þ6--¦àï¢bod´ø,ÛhœÓBËôuÐê¼{Ûr‡‹T¤_¿ ûëõiÙ,ZŠ>¶QË_ ¥ø:ÈúøÈ½ú:h¹Æó44_±ÖÅÓÒq"(—Ît~-Sˆage ~L}N ?¾/NÊ4Qá¤üM^îK•XñÕÝ1üšî:Ø‚[Àv äðû²H f…_Ó}ãÜÓ¯Ï^Ìå=nÌaájbøÑÝûbËÆ¸{sVÛ×⬶Ïs”ÉYáìƒs¸±¢*ƒs€?îié-þçíË AÐaÀâ[pšéK9š~Ÿ–çíÍ/sp©e³÷ÑÉ5Fo(¾Šƒ,Áäæ—wr)½ßåÔõ#RWfLÁ_ÝÅö CKÇQŒCVáœðÑÍ}qNøjgÌÀ×0eÅ ü}õ<Ô&[|IøÀÇà¤|Ú¶MØxÔ»æä§²}ÂX™§Šà¿8ƒá3Z‹ÕPüÏ}qFx7­½9#_p?ÜÅá±ãúqãm^ÿàó•°Í>¿[fíÍ|ŸÈ‡eWB¾ö|èÄ׿Ö‰ø€€¤%„ƒðÝÂ2ßM¦ðÝ\Þ øðeïñ¾ Þ㼓¥xO„*àCYÑ|7@¢Æ °(l1à&Äb#Þx‚ï ü ƒ÷Py4ñBå‰÷†Ø’ÈJޤ7 '&î¡O½ÁÕ¨po¸Š™p/Zb7âÒàÚ]¸7xG÷†Pޏ7\I¸‡j<Â=¤÷âoòÒ  ÷¿kñÌ4 øï;f°€1¶—ï1ß`CÌ7È]b>œšö4|÷¾IDð©€oòþð)Š à›ü*|“_·€o Ô|“Š /µø&î#ò«’÷ìopZLáƒ÷XV?xÏZ|ò^êÞcõÁà½9ùˆ˜1„5fL- ¥9‘"ñEp„Ä7'^ø >ƒøæÄïŸÀÇ¢†|ÖÅoß\ ø"Bà³£üò|s 9…E'ðEÔ…Àg#RAKq…|1.o.Þ¾¹ð}€–"tCÞ›‹ëâ3"ó¥N`sñIæ³a€Ž &nKÌ}È|¬P̧ø˜Ï¢_ 5V°ìÀd- I0ßÜüÈ|¬ÌgGá<1žfp“·Z@^€¾‰úbN„¾t”ªp‚Öbã }Šª‰úRPíÅA}¬æÔ7·X‘Ôwñ õÍM^'õÍ͵.©onÞJ¾‡•DýÔ¢¾Ëÿ$ò]ßï—¢‘å#ò]¼…|Œòé(!ß"ñ¡^C">I|¨Ð“ˆOƒÄ p§Ý1ÜE>Ô—NÀÇeßhï]xìï]¼ÑFÌ'ï1hȧ¼C仸U ù.2ëˆ)% L(|(¬‘˜ïÂcOÈwñžò!¦ÄãÆ Ð…¸Äh(ïÍ‘ø.>:E|ׯໄPqý pßÅ[^ÀÇa|™JÀ§JÀWð€]1@öâðïé,佂`¥p¯܈{+ýÀ½ÂpÚNWï—&Üà ÿB=µ ¾óØÌÄ·*—b$>A|«qMJäSÀNÈ·˜ȇ-åù,:œ0±´k ŸµxC‰œl—Ä·š¨3(‚5Π!ÆOâSHÄ|ÑÞ³pd\?à³ÅõSd/¥ðÒjTH |©€1Iñ^êÀbØyo_ ðÆ’gïíK¢!xo_üàÈ{[j yÏV1`,\êZÚãýä½ÍGxÅ#÷6§Â½-Á¤s @.ǽ-Õ“¸géu§´—üù°¥`öö$Úö¶ÖÛ„½2¥{{Jì1E0`o/þ{[ëkç=ûZ#g°DeKÇ#Ï–í‰xÏZH€5Ü÷à4ç½ã’–ùæÕÅ–KÖäï£Ðâ¼w\ü/ï…+ÜðÈCž1*~šÂüÐ÷´ú—¾7>‘¾'±YúÞÂM.yoñI$yï&Iß»%@Rc\6¾[Bœ |(­œ¾›OEòÞ¾?y¹FÁ{[1!ò÷[ ÞÛŒ©Š÷,Áˆ90K(xiËÁ{{H,íñøl [Q.öxóÞ—ÀÇ|Ÿ¾-¯ƒ¾›¿ |Á)|7|¡ðݤa)| A‡Âwãµ+…ï†á€ ßM Ÿ"Òøxæø¢…3è”L$ð)Ö-o—¤ð1 *%…6•Pø½£Â7`( Ä7(Iâx„ÄÇ`]h| Kä‹3Ç 5ùh ‘wMˆ| «…È7¨wIäã}C‘¡/Š|¯½ù°|ù`³ Á¯Ðø&¾mI|ôÔ„Ä7%I•&Gß$aKã›\Jã[ü– ñM)zœŸ>¡ññ­"ß@!òŸùbŠ|Œîñ"c@!ò-~ßù6WÂ=…> ò)(ÐcûCå‹>¦ýëCä[”ÌD|[THâ£&ˆÛ %â[¼mD|›?!Ý6| ~€ø6ÑBÄ·)™Ý1ƒò| Ѻ@¾Í;Tȧ)ù‰óé¨SÀõŒ4…æS CÌ·%â¡TºÿAàÛdMòÞ¦“`Äõ Ä{ê#ÞÛÔ±Ä{ Õø¶hŽÀ·ùûŸqý ¹¸üöA|úð&«Ùàžñ)*$âSLƒÈ·/ÞÒ+¦€»ˆÈ·ÙB>ÅOÈ|ûâCWÌ·ùPómÁ$æ°ô‹û3"ü°XÖCúöÅïžÔg] éú´\õii.êÛRR·?ü'…ÓÞ¤·>Qö¸ „è®Pï鑃ôÆÛÎi-8*¡p*P‰"\  -P]õàQêEKÌ`¾Ýœ©…¬‡eP‚=öÚÂ+ÑŽJ´(ÑÀ3Ñp#ÑFN´· Íî}îñìšÆåN*¼—z€÷bTò^ôéio;gj0™»ÄÀK«‰å€{é ð^:9xOöð^ú›[Áp ÐR|P¾˜6‰/µ€øâ¹c”îbèàK§ðÅ7@àKÃøÒQëãòÒXtCêÞ£À—Z ðŸøâáÀ—ŽŠ9à÷C/> 9:õ¡Sà‹YÉÑ©YÀÑ©cf̎ɘ¾n_£&â‹>$>ý~D|…Ð/ä+¿>ˆOÆF_‘y4ì šdé´p^øô–N:’¥Q˜dédK²C¢%,÷[á £¥,UÓ˜"²tVºd鬟 ߪ4ÃÒI#cX:ë§ÂgÇ€¹¾ÍA–Îðb†!’ò]X:ûñU~ÉÓÉ–˜ƒD?Í¡ _å²àÒîß ®0uâõžLûƒù*Wøb¾&” [$Ç [䇯·“È×(8$S'½”œ‚<@¾F5¡Ð‰¿¯ ‰| 3!_£è—l8ˆ×ßhñ1ìšmj‘­³_˜8ÃÖIÑO¶N0!=‘ü;<‘pç%['¾Édë„›l¤Ï˜–wÉÖ Mµ†)²|óu’ÄÂ׉Åeòuâ‹óu2–˜¯“±’¯“Ç„±÷^6vâÜd¾Æ5u2v6R æÐ?˜¯1ö/æ «g;éÛlZaí(g'Ç g'¸59;ÙHÎNÜÉÙ ­(9;û7g'V²ÙÙ‰–pvÒÇÎNÜ;ÉÙ úNÎÎöÒù:ï¥äìDCL6Ó˜ÂøÐù4…lìF%cç‡Ðשá&c'È ;¡p‡±SÌ0FŽ—ÐÇÀdövÞà'ëdòv²AÆHªzaŒ\€±ðvÎoÞÎùÍÛùÉ}7Ÿ8óÛ’·“Ò‘Là/M{ù;ïþið\o¹oâŒôwŽOçÀþÎs§2Öäîœ\ÕÈ…cŠÝ“Qy¹;å`’»sq!{ç¢NÇ«_JÍ£5R™Wpwn.BäîdÜ!ÜŒ„½sSû.™9éŽT6”øOj™øOŠšøuð_‘™“ü§, ð_¡ üWˆÜâ¿"†$ÿB¸ø¯ÒF*þÓMü§eøOK6`•’X¿àõNçÓò+I¤'zDƒž:ˆ+°¿óùì¥þ ™g—Â\BXŒCzêŸ9}öÂA °3MØésvQ#çÐéGRÑì¼>àýiñ\7ï ”@©XÀ[Zbèeàà-}('6Péº@y–€z¬£…ôtóËÞ6@>œ±g"@™‰E€R¾D€Lá޾ë5ˆp¨€²Ã®P-¡Q Am¤?™”ErëŠþ¨Fý)ŸWô7ù­ˆþ¦.ä4½àO’ý¨`û… “—¿hçûÉ@+ö[$Q±Ÿ\¢D?fÕŠüêò£vÇåc %ð[\üx)~Püƒû˜#Ü7¹¹âúaÜ÷­oZŸ„qßüôv†|!ð“ Rb t{–õà·A“â¾ÅU‚¸os%!î[\ üö¯îÛTAÅ}Ò7Ä}û›Ò·ù9ˆûd!÷m~•3À×îcZspß&g“û¶Ìä>îÜ·e"÷mr ¹/‚øâ¾0J‚û ¯Àgà>náÜ·e÷sî“YFÜ·/R(¹›±÷ÅÈ}©eiïUŽLîÛÒ 1‡Œdaߦ¯Ôg7 ÔGƒ ÏA—¡¿,ßÐǽwúbXS\oŠâD>nÈ'+o3w[È·e}#òÙ ´äÛå|»Pc$òq{Ô`¾ø¨È|Øp6Ïز9)¦ØùvQVo—_oâÛEì3ø ¾]8ow; ñm®ÒD|ékãñíâßfË~#ß.ÒÒ€|»ðÇMäÛEYv@¾øDgÌa¼‘o3y[È·™˜íÄg 1ÄÇ­‚ƒøvå3aÆÖ›ø¸o’ú*™ÈÇ}u“ÔW½Óù¸ËCß®üVÌ9(}q"Wú*î")}: …¾ÊÛJBW×!ôÕoB_å焾óëÉuÑê}Ý©ZÔtÝÊÔF9ž¿©O®‹öÑ)‹ºhßú uѪUŠy|µ¤Òah‹êBlÈÈšUãëy(µ¤¡ÐC±á5Ô\í]bM-y(oKC¡!Õ+Óô²% …¶Š ÿþúhÕ‹Êü§ÕGû~×»6&k²LÕO·ó• óùíæc¥ÊgëUù c¥^ëÕ‹cEå3Ž•+Ÿq¬èűr/Ž•Ï8V®|Ʊ¢Çʽø«ÊgëU?öè…±þ•úhÏrïöŠïÿIõÑ~ãÁúÇçCò‡Çè?ßÂïGë?¸ƒ?GúËõÑžoæTmÿÿa}´(…6~ª”ö÷ÿõÑê]”5þ¬Ëü§öʯwC¦±ƒþC=ʹF‡[)ת÷¸”ËËÕs"¯÷T°—*l]8jG…­³ ªãR…-?ê(ª°åDûü„C¥}‚ž¾Ð¬£3yÍω=N@ŽÍÏß›Áž…–©4‚‰Ss T«ß‰ÿ(ÚuÝog»J'ƒûÅ´«6Ʀ7`tö=/ÌÂÈÈÀ1÷ŧ<-›î´ß®¿+Ž™ëWhךÖ§Æ ”+Ó fÀ]õž–ÒÙâ÷y{žþobm¥UÂÇm[é…pçÏŸV0Û•-û wíáO¡‘7Lð /oM.…/\ŒêŸ?ëusÙí7p«¼~zž×_#9œ¶Ú*ÑÈCc­öÂL |“Ï»ÕgÅcrVãðú©·:ÙÇø'ذóù{íYçc´Ëƒr›)-íù0™ëá°ßg€Ý^ž΀y­õÂÜ3íFLëæwÒîÍ슳Å\ çš“¹ø$w|ãÕøÎhÃŒ­_ha+·§¥tfOuô©©- A9è[ç&°½uNûÌXËfúnû>”cðºõ‰ «2´¾”›ø vŸs¥ÚÍ)0ß알|*É5[ý"ç ŸÔݓۀÿvwÄ䘧ÕîÛcr›‘ݧSXõvs ôy?Ä9Ùâï„v¹Á7¹Áõlm„†}øþt›÷ôð9œ-n¼Á§p6Óñ†˜uÆ6zᤆ¹/O cBðÓ²=%Œ‰Ðm Äå6tçpôŒ³'µqö}sRø9[b&…GÖôýcËkö^>“ÒCdúNÿ:§Ïáì_†–ûR ¶OªB^ks,ŸÅÈç‡0=«­àíí€ôuv¯Á3vr ÌÝmë$«ùf:~¶¥×ö>ø¦–ï£3Ù‹“ò8r³sõ35ŒSÀG³8‡è3[ðQ¬9}VMçZƒ³ÂÝo{zaV¾6k›s ;¨mÎbh³M½¶_óÂQ ©yøÂíÅŒì=¼ìÅŒYy(ìiÁ¦FMGq¯Ç=‘’xë …”DŠmo¤$²”T·-½¦·øã»Ûž^H@Ühá˜$Ö/ŸÂb¿¸iÏíÞÈG:àVBbCË@N%óéúð·@¿b }öÍ tÛÐkä{­Û†^˜’?‰»mèµ¾bŸ¡§¥!§rb­ó<‹yÅ~îÂ9Üøñv{/£OGŸ±|V,@ÔË)Óãû¡e ŸÕ@ܵÎ&”^9æ„u#¢áׇ³WçÕsvôiÅgå;= ýòIÑ#ÓŸ—sNí•SÐ!c±7„ŵêWlzô´¬ásba ‡èoŸŸúŒþXŸ…–˜¯IÜgdç·‹¤eðóÂØ~X~ünb¹ïÆ%øQdð£½)ÀïÆ­àÇêÚ~·Pà§LQÁ}‚ƒ15¶pXWƒûè î‹p_:Ü7éÏ÷Í›À6bl‰ ê@MÖ¿)!ø©ÖšÈ/µpøsØoò›81˜‰‚ù| ž¿%æ›üŠù¢…̧šo‚¾ÔÀ4±‹n@_: ЗZîò>FW)NЧêr‚¾ÔÄ”úú¢¡/µúRKšX Èd- :0S: Чjw ¾4 ¨/õHs@KšZÀL:·¨O}D}©ÔG뛨o’ˆ…}ÑÄ”F1¥ƒÆ~_ ¨/ô¥CÒ¼¥|›¡O…}© O§"ó¥cåÍ|©˜i2XèK=}inC£>ä>U)÷©¬¿¸Oa3qßä‹DÜ—ú€ûÒÈà¾9Du1Å9`èÜ—þ?¸oUûbTr_ŒÒ¾Í Å ê›ûR`SêîKç÷¥ë÷¥>œ{ìñúÿ¿èAðK}~q-¿Ô'fPßàg-hØj@  )ºûR`_:Ó~rÇ ÐƒÜ7i›÷©˜¥¸O/Å}©¸/õISc¦) ÏÔ&쳴ɯgËT‹s9÷Å(#Íè•æð¿Ô§k—‰ ¼¯Yüò8Ceð¨4\ϳø¥q~é\üÒ(¿Ü#æKS@—;êŽV´¨î(QwãLN}q_î’fŠºTv}À}1ÌÁ¾Ü¡}TN%öå>1|T+fÀ>c}Ì Ø—û,Õ}c_ê³c è³Ó€gµ¾'u¨ïüé9¨/]0¨ïôÁ°·J§b˜B) ¾<ÌÒ‚ˆ§Ú÷ë{"ôÅ0„¾†Ð—û´ú¤—ü©úR‡[k¡zëý%‘ùrŸtùÞ°ï÷|ˆ|ÑÄ?‰/uiZÌáDE×ÿ¾4#_d¬÷ÒŒÀ{ùrÓ@Ti~½à½Ü§j!„s÷ârÀ{y˜ûÊ¿bò^î1´bŸ9?&à˳ï¯Ir¿ú´˜º¤¸ÂýûUÒ„|ëìÐȧ, ßâ®Bb>@ó-»˜Ïú€ðÀ|¸|ªn"à³õ¢¯ |´ùŠ÷¢ oM‰¾Å ßbÁ`_ƒ2-É!ôMJ`ú$LJècñ Pú¨òŒ¸~`®„>ß ¡OÃHèÓåHé›þ…S蛀ð™&@UïbK%ÿmM }¨ó±xqè|ó›Î§é| ¬†ÐG—l}L( ¡U5BèÛÔl!ômꇜB Ë)lŠdÒù˜Ý:«j„Χé|›_‚t>F‚CçãŽE¡óÑ.:ß–^H±j }›¡ }šÕŽ9Ì7ò¥qC&ƒ¸’„¾õMèCp8 }h ¥Aû$õñ¨ú¨ýmM QéƒFæS1AßB©U1ß’Pb”ì(”]ÈKó-Ötó¥£(ôiN%f ¡„X‰E?¡O…_}éú¨ô]ÂB@ŸõyCß¾„ih¡Tv!0bßõ }Öòûâú}éì1Ìb_Œ»f¾«CìÓW'±5gBìÓ(-f1€Ð_¸Ä>ÍRbß%a‘bßõ }ñÝIì“J±OŸ'Ä>!µïúõf¾¸8‰}qP“שÇõ_o­/>Oi}šµ´>ÝÒú4ƒ®øåÝ1Ü÷ûtŒÄ>}+û82_Ì[Zß%…ð–ÿþz3Ÿ ƒ£æüøA‘ùâ«$óéC‡Ô§ë1ƒë|ñÍJ뻄j]ü䋸âk‘ÔÇ Èw”úô%ñŞėZÊë!ðÅÇ9co¥/÷¹Uy”úà­Ê£ì3TyŸÞB¾øµùâ©Aä‹/“ÈO>g¾Ô£Õ»Ì÷ùŠ9°Ï·9ùâùDæ‹ß™/]ÍVõÔ—Ò—Þ1D߈|ñ;ó¥`¾øhÈ|1q2_\ ¡/~d„¾Ô²T­ŠçÚQnË}zÎ útrAŸ¦èÓgêKÿÿV¹­ ÑîV¹-¶ •Û‚Øv}N@ØÇÛZا ûtˆût£‹ûâT¿˜dá.ðYLA-[-ä'ùéæùéá"òÓw@ðÓ,É}›(Šûâã#÷ÅÕübN~qu5f€/›à§;Xàg‹Iµb9Ápk9„>¿87ÁO…çD~Xgý³Bi{õö>[ÂÝK{ NŸ€½&Éo¨ØÖò‚=¡Þcå´à=VH Þk”ó.åZÞ“Q¼×Dfœé,9õ{qqO‡ŒÈ´†h8£Ô1.Ÿ}âòiÀ¼î÷„D{ÜM/h/ZšJm¦f€1¶–tyÉ׉y'_'U¿ðub É×9?|ºš•æ€>„%ß Þ‹>]¥¶hۼ˻Gš0怖©R[˜ƒ€/ÆÙ*µEè"ðEKù(À§q|qaIsðÅQ|éïýñ]í4oHSø0v6Z4 KM(GÜ‹âÏ$ÜÓÀ{rÍ÷RË~Sà½ô7y/Ž!ïEKšÂði_j!ði_´øRË·9”4œ}¬÷7Eà‹>Ým|º>_jù6_œ‰Àç"ð¥£n•ÚRËþ˜Uý6‡ú1_Œ±ÇÇ7EàK-¥|S-Í-iÇ^>[îëcN¾Ô2ÖÇœ|r›øô€ð-î à‹#D|rÁ‘øRŸµ¶ÞÈg}o1ƒñ–ùRŸ¡Z[÷ùÒÈKµ¶Ø‡s€ýôŽ9ô·Î§ B¾—È—útÕÚêTõ.Í šú6"_:ÕRõQ‰‰|ñ!;ó-l#!䋘<âD¾–ÈŸ9‘/æDæK-CÕÂpò˜O¾T{”ùÔ"äÓQŽ|úðˆ|ñQÍö±Y†/ rÇzGÝZ•7òÅ'!ä‹–4oH3x™;ÓÉI|©O}À$¾tL×’P3`C,è`ë³ejE„›š¼?Cò^µcl‰`_|4|é˜^>~P¾Õµªë@À˜L·¾¸b_:×Ö’èí팑E|©%Í-œCáõòþûÖ‚æ?ßâÒ[Ä—ZÒ ¼!&ÐßBŸM¾ÍKë!ò]ÑzÞIßj’íšÖtìÃ)”7ñYŒ{k=Deo¬÷SBÄg-¸¾¥5Ý>1ô©1 ZÑ‚ˆš\Õ‚è­ô¥Qúõ¾ù@|ñéÕ˜Á[é‹ïIÀ-KË!»µêoàK-1¶Ä ªgÌÿ~‰´ìîœ5»;é6‰´¾ñaïœL^“½s†™†Vë{ç’k”öÎE‡¢ìÜ–.ìdâÀ?ä ýj“¢¿Âì+П2é“⨞¸ }Æ?*„ä?VÈ þãVßUüÇ­´ƒÿnžKü‡‘ƒÿè$ þÒåš ò"©öáÃþqcÍÀ¿àfú …›Ã’þ$§‰þö§Ú§#¢?+LÉ ädùY8 ôge=ÞÏÍ|ÐßVÜô·ùLýíN%éo³ä˜èowH¡„¿Íª’‚¿-‹-áoë¶'üí!¤R-@'¥Òþ,ãø{þF¨„ð·—€‘SàÖ¢¿Í½AI–s‚·ðïä·¼ žVÍå•ÖwÒ1^øwrL^øg)þ*ýYÃx9¼ž‰PåüÍRéŒü(yÓX/µÏZî—ÚwZ^jŸ=»p÷þNj{—Ï)Fvø³£Øâð7 j·’ýfAmzG¿Y¸õŽ£Ÿýý¬¸Ï|eö¥³ýNèmŽ~óÔÆú[Ÿ5@‚ë¼ü©~›-HÑsj²Zp§ü¬ õ¿sPÒúf½”6‡TnwIð³š.‘÷´Ì—Ö7+±?ka?; ? ßéóJì³–ëE~Ö²^O{/AÇab_eyi'¿óæÂßœCç]Ï̾ʭªˆ~Ö‚ègG1ÿ™}vðKî³âMåeð´–ûeð´‘I¦H‹«óÃàiGùÛZ™}•„!³Ï®øeð<×ç œ_¼Jì«Ü'Y‰}u~Èd^_åæóÊëk´ )¯ï‡¬çsÀòRi}miäĵ-ùi}ƒ•Ö×¶.i}•Õ×YqMY}½HqCNœ üB?ëCY}â¼ÙÏúP7s÷¬õg´Ý×D¸Í}_.K1µM¹¡Srÿ½jx8À# ¿9Â#ÕNZ7ÿÝÚ¦s]T¯üêÁuQu›¢vÏ\ÚM}×ÒºÈZÑ!ì/ {²•›A¢îò*{„A¢î’û%Œ¿‡:p7”Ä1MׯjåáÊ.{ζ¢CÀŠ@»å!Ì»ý¢ñpÀ‚G+¡”(¹ÏÓWV„¹fu9àV¯s¡Æ>™Vy³åŬ<‚Ù\Ì¢Õ1¢9Χ*>3Ìå^}ͬ¦¼g‰ˆsÍ,+Ö6tã Jkhž>Ý}5$”‚*ûº¾5jfE[BÍžCby°rùÜ6kà¨Öc&Ø#17zñ”><†5.ïùÁ1¬Ìhσ"¦W3ìÕžâ=bÈiOGœ«^Ø•¾'Þ£õj5Gâö§ì-kOÁþ”kp·†¨'F\Ò¨í§#*ÕÝÍö"DÕùY×¥5à÷ˆ¤ê÷ì‹¢îˆnkq êDk {Í’ûOĉ"FÊè^k‘®=¢­A×Ú5§š›ëý¸Gë<€½tÕÌ×:%ó ¹{dÅÂÖüq€¾G†ÓVZdbWjýA¨kosizÜ¿xïm8·ÎCˆƒÖa¢Še@sÙ{)% ªCïm†«œ5LDû¨€^œv[DN0"zk$Ž¡4G(Úà1 · åßPÆH75Ìû¨ªžËÑZRs%§¶'‡þ,Úó {mèü¨ ¾?¢æ¢Š‡Cwë¼㪵¹ëÌAŒkÆÚ,ˆqÕÚ]¡{_ëøññéSO‹TÜ¡ÍÆÂ½—[äµÙŸ8¢} t2÷T€‹?¥}µ‰—NÊÅ0g›<:}±F|wôÅÂ…Ù+¥õ›‡ô“—~ß÷}¿•Ô^ë/úó¾âˆ²PÇ+¤ª‘2ã:uòzáïïÅ záïGg!}19}øŽí¥c%´Gjn3j\§½ï;cMlcWyÇä±ø“õ{ª/ƾüÙ¦VÖñJƽ߯ä‚5p߯:¨öb>Ü#™ Û« 9 ¸W@wž=#×y´þëh‹5°‰[t´ÅÂíŧšŽ¶X8¢ášmý‰#h¸÷GG°,%w¼ã¨oiÀý©ƒÇ”ÿy:*Ÿ¹§5ÔÊ‘5½£? Ïï£CXn6¸†Ç0Ü1¤ãAGmðÛñµŽÆX8*¼ìŠFVðý%»lßïä!pêéM‡€¶\Ú‰¡¹Oß‹†YnÃØqëâ †í³{k¬ƒê©Ø÷[…å&•½¡þîÞ¦ØDÑ›UÜ8‚{ #õ³Þ~ˆJ£¼¾è‹…ƒª9‘ì;'BíI:ÞɈb`]̓ê:,{õE>+=î;lã¨qÇñ=¼âUŸš±Š3¬ïR,¤º·n<„(º;4ÂC¨jiô§«Ž½¸¯ý îÓ@bŸ,L/ì{~…}Š©&ö©^ØÁ>WÛzcŸbõ‰}®ãs°Ïõ#ö9Ý]Ø7Ü`+±o¸Lpb¤¾ÉŒ}¸Zb:aì3â5aêXkÏâ¾lè—Ü7sÙjî›– “ûðÀñ»Ä}aZXÝ—KLsž‰uÁXÉFbúîÛèêVW¿¨ú«½4¥3ß u]U=£ü¢.­~߬.µªÕÖmvÍ…S9ìªë`ð»äIî;tCî»~æ¾ÛšTrN‡v"î»]©ÏÜyØ´Hh{mÛ¡¿7µg‚„ªö?ï0æ]ÖÈD还4Bh‚r¡{€ZÌ ~¯ }†à7öBTgOà7‘®¯Ào´‘#¿ÑU|À܇Q¼¸‹åúá>,–ÍZä¾1Ý ÆÜ727™ÜÙsi/öqÂä¾2¨öÜWÐÞnjÆOAßÏ›ûö6¶‚ˆûÙû›ûÂÙ””l#*%÷ímì÷틼¼ž%÷mŠw®op_AK#¸¯`á~i¯Me ˜ }r«ˆŽÔ·‘>¹‹ÔW Òq–~þè_êÛ#r3ú6õ{Šô•yÎ?¡o¸°¤ ¯¬K]¹ƒùÂ+%#óÌÎ: 2_ èùb·óÍ|tjñ÷’ù"PðF¾‚þ|š®ˆ|]Ð-Nä+vëùÊêò{Šø àäô4ñ{A_YYëQЃ"ê°pžÜ{ÑW ü®¢"-æ>´õÓ4(î òÐ6ä>èÅšzÄ}×ã„CsßU]¼ÕÜ·ß8¹grbMÁ}×°ëÌ܇-„â?ì÷ú€ß5”Ciî»Ö¥?™®¬\aèC\CO› ïB/[ïŒ6ú6B;($ê»8úPß#¯RPÐEïQ&Zô‰úîêÀ›© ù¤˜úð²1㑘îâ¬PSßn!Sß~é›úÖZŠúîb{¨©ïNˆ©Rºè,¨ï>ä*êCüƘEêW‹²}wvÝ5ô•âþx†¾.Åx„¦;[ó™ú Jì~¨¯Ü~A˜úJqlS_)~•“úʾtS dB`¦ ³ˆ}å ‡°¯ØübêƒsN ê‹×¥È°{4Bh*84õ¡%#ï5S_Ý_5?ԇ׷¨IÔWPTF‡€>‚10S…C²éï`&4_ô'H}õöCjì+Ó1c|r¦Kº&ë~öÕÛëHcüì«ã°"±q+}•°û//ì«¿Â>tuó ûêTY}S_E¨ˆ—ZÔW7qŠ@D}ø:㢾ºÜ»ÞÔ‡ßôh?>ÇtL}Ͼõ„L¢¾ú¸…©¯vW–&öml1òžý^Ú@‡°\OÛÔc¡wKd§ªFH}h­WÔ÷Ô•û!õ!$¦Û±Cà&‚¾§MÏ5‚>D}t½}â‡"/@߳ϰYÔ÷@*üP¶ÑÜ#êC+M=î¢>ü¼®o"õ!r¥ùRÔ÷ÀÌ«`-½3ù]¢¾'ú¥i„Çp©Dß?S{ì€_ûI𛩹Y-»\æÛä7íÂMò›N@Hò[âD~0“‹…~Ùö Ñ/ûFýB £sÇè·ds2ùÆKð ¼Ð<ØX›Gèåº36jò[n”ä‡ç†¿åËs?·F2ø a½¿û'Á/×Õ)øÙ'|¿’W\ß\J]ÉíŠG[ñƒy[÷œíŠ_œ m#ðÃWkÏ"¿œ_“üÊ“Ì&ò+ÎÂKò+Oª‚>„êpÉþbÑb_ɵ¿ÈWRw–Èo„Oñ_ø 0ϯÀ/¬¶L–ðó±ÈFpÓ}Ì}ѪWÜr5?’û°Îgp_ìE[4²ÔHqßnÃcôCkJIõB¿1ò^ú…Ÿ˜¿Wè‡ôKl:œ mCrGûA×5ûaD,±‚ üa‹Këš+äþâ3ún¢Óh¶±þ0òa?Ät²ؤ~à¿N…à#Š^ þÐÁW“˜èo E·öLúC DwIÐ_¸¤õ7Ò¼‰QüZýr1ýÍô÷Ú™ð·ÿb›7ýÅ&Öø‚þö&5ÉŽ‡€Ÿ³Þª_A'`Ý'¤¿=2’ƒþöH¾@_¨ùôWð›–tJÂ~K)\:„+}Ä¿ˆ®\ÂÅXÊã)‹yc·ä¹Jkûrs>!àIïp<ù©þxD³0â?ãñ·ñ¢·=‹U ù °x ¸†ë€ñÈ‹Ü á{V¸ßº_Œ(8OÜ¢–À2§›> ÷ˆmÀÀð^Hç!FF¢poá’8À¹Í{Wú5DnA€{Ä#`'_A~`’$À=Ò($ÀÈÄÓ’Xæ~/ág ²÷„·¡)G3øoßÕÕìþ‹ü?Éä¿2«bðÂ?>soÕoßÀÍÔ[ôó3¡Cü·GüäÚ‹-ÊÉa´ä’ÿ ZkOƒÿè×Ñþ‹]”‡p»ÿ\ð_ü}¿ù/BŠÒsÉ{ÄI*â¿=¢P”ð/ü2’]ˆ<ÓAÿö6ObdÀS„Ü´´'ÿí‘j¬ ÿÅÈý–ýb?".AÄä´™‘·,à)B}†È€§}+:ÝQü!C=p俸9EÓä¿2§j) ÿâITÿèRÒW­Û#ÅÝOýI-î¢û©[– üÛ7âÔªFüw¯ä°¦Chn¼'þ‹Û׊^ÀÓ¾cób’ÿ ¦ÞGûÕs·žvò_Ä~ ¬:†jïâŸwÊy´¥bDÒß¹¬l‚þâ9Ðý•’Ҽ茦т4º_Eˆ+)b!ú»5+ ýîðs„èwß/Ð ô‹\ϩڸ‹’ÿ¨úØÁ½}b?¸—,ë˜# \ƽǕ ÷†›b%î¹!ÜÁ=÷<;¸W,ý™öjšBÍJÍ…æ’öš×<úÖH?g} ²¯ÐC¥ŸË9¿&7³’/ôÁ½–Û˜÷V"aW;+—µ<¼×ÒKjbm^‰÷¬)æ2+Ùú¼ñÊÂÞÅ¿\Â=ˆúˆ¡ô´j ÷ê(TÂòEÛØàé†Çà9½œ~<–:„êxkâ^M—˜q¯Z OÜˬ á^MBá^u!èĽgæ~u íhŒ:†cæ3îuwÙLÜëNêNÜËlœä½‘&/ó^wÝìä½™‹[<¯c¼¤Lö•ùV’ýˆë~h+;‘±h#ó#ó!Û_Šhoû{³¦f+Ø›ç: öff›öæcÏao¶Ë» … ªÿ”È÷$fXäë©mZäC^µ>e‘ÏFSä»2Xb‘ s‰sùRI‘Ï©®)òW‰M‘/sã$ò9aMBÎ_¯&Ä[æ{Ž•S2ß“ÆbË|=-Ž–ùÒô–ù>¨‡Eh{{;YA d¾¦¢&=ЦÁ8‚îׇI>cÓ¡0©;uÿÈ|éiéÍ#ò õ°8Ч„z}×ð!¤f:¬TºxDê|—WÖ)ôÝ-¿KB߉2Pèë)2Yè+gDBæ+ô=êëgÒƒ0ih#é­–‚¸PoõÔl…z1"½ÐReª`B=¼§4à õPCâ~<ã ô,ê­¬ÎbÔ[#es }òN¡ïÎ{ÚJ_¹ÓÏ)±ïv,8žrœ˜ûîœq¥ö]/d”X™ö¨TûŠK¶¤ÚWL`Tû®šÁ(©}¨pa½jÞ¬ããñ¼î~ô?Cí鲤Tve7J«}WuoT«}QCºÕ>¼¡­ÿéöðõxÆ~ôí$¥5[þÂ&uóÕ>œc©kûpBŸ·Ú%BÞÏ}}ç2ê…^ŒFVZ+QT¨‡lf-`…z+«­õÖrù³ÞÊ.儽µ\5bß•õ; { =êEi¤½5\"Á´‡Õ—dFÑ„|SšŽ`¸±‚ioM¿sM{kÎ$BÒWqÿz`»= öp"î{5’ºìí1Û¤,öá"éÔúðcµ¾+ÓÏ­õ]ÓFk}¸;…Ö†½ìÕ°wŽÚ°·ªÕ?±ÞLî0ëÍvàîâÄ"Üë!åâËzÃoK³vbEެ‡™ÆÎL²f9ÅzkH³0ëá’è3úýûÊ^Ô[ô˜ó°ý”ä<|Y뎿ó‡ˆóðcm¥Îw] ¦Òù0 IIW&XX滪K÷[æÃ`‘2ßµ_…Â"É|WOg¤t>¬Í‡GOÚ=©ó]ËEJ¨óayì-Lz%µA½®tnòbÅN¤·W«¦L“^IѰ7 Á†½îªº†½½êÓ;̰w;âúÏ{_ù‚Ÿ;ƒ§íiüîŸu¾¼MÃÓ ôÞ‰}ã§Ì>‹óÇâ™MuÓâ™Å·M~QšÈo:và̾'3ò ¯Ãy%ÖØ'jÏyroûfZIÍ}%¢æ¾™l(î»s!`î»Ý6¹¯d>‹¹¯ à ¹oÿýSb_m© Ö¬Ù ¾Á¯ùöIðk©oüú“ù€¿áB¯ ~3ÁÊà—Îø¿•¿GàK} 00t§ã³,†üúGåÊ\ú°b׺_ÔnÑòÑy} dbß^ç âØ×3ñˉ}#ׂNìÃÍ'øÒ,ÏǙط_òZØ›ú–×è}¨•Ò?Ü·®‘¶Qrß‚ÙI;Q^ªÉlª¼¾'mÊÎëK§Hæõõ•p¥¼¾™ö]ƒ_;ÞLßYàüº ‰ üFýø;ñwûú;ç­ƒ6ùe¹Î$¿• Ž&¿™ÊÉoå²Þä—ö“ÊÑ4³à"R ÿ<‘_”¬Ñ§H~kßZ–ñp«äu ô[wÊ”ÍþÈôB ý€%–‰~«±è‡ðmýÈ|+Søøók>·¿e³™Á“è¿îÃ÷|¸o•êøõp0 õëñdiVÇΈ “ÌGàRh}ow絎žGìKªÝÕ7¼ÍOµL(`Â"ëË|-F¾'Ÿ,ª{#c'‰|ÎIIäëéÚ¶º‡åÙÛÛI£©˜JÌWç7©/~¯ OÌמLáÓ! w¶Hæk.ût˜/ÓKÍ|#]ùd¾´È$óŸþ´?Õ+jË{|óýk"_Üš÷GÝCy¥õQ÷r¯µª{«Ÿm|–K¬î­ÇíD¬îaM:>êFtP¡îá œbHu^ÞÁ3Nhÿ¨{85’’¤î¡ ”Bè’÷°'èQÞ['<.y ó|‘ïrþ¥õ=ˆ EúV¦bRñÒ2ÙŠø.ß²–÷@Pü(ïaäÔÇ¢Ÿ¤>¬eåæ3ò-{‹ò¹”ý8‚û|—wV_\_{Iu=Õ"ß“–°Ð÷pmµ#ÖRVüˆ|ö`Š÷ÆHj|ýüwN_p£]™â½åhÈá½–^NñÞ,™?(à;^Î>»@ |I:¾+oªzx©¼Õ½`7C¢ˆï¶#<‰/ ëâ³s7ÏMRlîÄntÕäî¼^*!ݸrwF¹O1 ™µ'˜‰Y«ÛA&ò=¶å'òõ X$òehÁÈ×3UÌÈ·AzšÌ|ÚIBßLaÖЇ*½B-q<|+qßÊ;/ìו7‰¹o¥ôeî»ÝØ9¹o¯”Œp¿Œ©üž }üª{®&ø=ÏÏàWòY1ø=é í.t4œvjðÛû±€W&Sñ*|ÓúÀ–ït Ou.`WyKCæ>l¢À¹˜²xS„Þ)} é¶{.)ðeÁ±ýß—eþØ+€Mtû_±Àm1‰ù¿•ÛåUÿÏgû³Åo}æÏ×ûþšü åS&‹@ý¼ÿ³U¹Ü¨iàæò¯Ì¿^ûñØÙO޼÷ký{ò¯÷~4öÚG^û)˜ÑöŒ®³æ¿^ûñØÙO޼öóŸS¦ YK8cUiðŸT*–O÷_šj@Í™åÆøÏ‚ ’UÿrÿÞï«SîÜv¬ÜïþçõÓ?6-« ýtL¬Î–îÉ¿ýêd„ÉÿÕŸÅzÕ¯Îç=òÞÇÙÊûyoå}¡T2V‰a/iÏ_þ‡<ÿùïEfĽþñŽþÏý•(qÑn^‚ûÇ¿à'"7 ˜½»ÌÝÿ¼·ý¥ì¹ã/ÿÓ_Qw>Ï_þ—óCþ×üÏÿÛ_#´³Ú_þ–ÿúïó+ÿ÷½Êì^í/ÿ-çÿõW8IŸ†òlÿ‚Šóí:ÓÈ?] îA/ç½LETÅú­Zp{!§Zpø—K´=¯ý—ü¯®W>ÿô¶6}Õ‚ë9ø÷ü׿å¿~U ƒg?ª·êãZp{ðWµàöØ¿ç¿þëoŒe-¸ûkÁ5(4(öÍugªg¯Îb Ö[mqÆÅÈLÖÃm79ëÊŽµ6?TbÞá!8R#FÅ= ?Ô,;Bå7¿{Äq¯4㯜›ì~ ˜öKå€ï3Fj`I.퉑Kyd§ÔÚcdÅr5…"vŒ”éá1rÅE€åyŸ =²?ëtø=ƈ‘%Ä'?C)÷Z¬üL GNô^ ðCünÂ^‹ãC=Þ¨p&î)0FV¬öw-ñU{$DJ>‹w6NlÏÓbd.¨¶û4«cæ_Qfû” !êží/ÅÀˆ×&b"cÞ1²âTÀ€‰9b~ ˆ³‚”1Ò9‚b(Ë>Ü»89¡§ì1Øâª!¬AÓ.Ø‚_±ÀyÖÁ´g< L6Fa3Ü·Ó‡~GîÞóâ/ÅH Et3 ƒ_XjA4aòêQ¢m ·“ºZ4ïj¹fdaÇÅKèa8…hâÁh²‚ñŒdhõϰâ ±dØâ6@À„32~÷Í»yäP¿ö½€Æ£Bîî~vG S HÖF°Ž# wÊ1œ»§`Z èä kÄþo˜y.°HÄÉñˆ"W¹ÁìïÂ{CÑ7aØY˜þÚiˆÛ ÿ/¾©ayœ?PSëáùS¢D‹¦ÌÛè ð–¾ñ]Í7^Ó·Íð=òhü>ÊB+ŽrúD «Óž!fkž…T·Ÿ|ŒÜŒì£XÈžÀ¡éC–ÚwC´Vá´hÛŒv'ŒãCOÚ3x¤€Ò¢êÆŒm¨Eá%½zä9rBÂKz?‘È/颇P„È*¾ sGÜ'!ðC”ÁßçŸm*0R‚·XG^`Gé8ÎýfŒÇ· ­Ó¾øÑ4gñSÌëe^Ì×åŠîZQèâ&èLµb“87/è}¼10ø¬:÷a"ÐsjÁ zß¾ðKOÌ0S=õ‹#8†}˜xóÄ XnzÏ£?TÜ9%Jpìãl\a¤„Æ9®òߌUà ÀI³ ¯Óž¿‘N¨ƒ@‰UâÛõ{áè¯RnÐñΈ‘‘ù‚ôžÁ‘Ùxë«gd Açë‹;YáÄ£4C,èë´÷'o¥RXE$ŠE<¿ ¯Ó¾DØfòC5r%c‘Ì£­Ó>·È/%¡´uÚ[ãm<îB!REçïêa<‰þZ°|ó<àõ¼Vß3fÌ‚÷ó¾Ãñ¤sÑXÐØi߈±¬øyAc§çsjÚ/hì´'pœúP4×B5ã/À‚¶N{Ž”º›ŸiуâëÍßå*ö§6Ï3£Cx‡Voç«Äqó%äè~M¹ÙúsÅá> xÿŠãá{“à¯ú Æ‘¼HðŽ…Ç›KLDoä{ñM‚5Ä$³ÉAæt Üs—‰æƒC σC ìƒÃäe œZf&v%c%v¿Ô£R€¡1Eú©q£'"Qðæ1f̸AãºÇ&Æ@Œ¼Œœ(_ˆ—pSR V¨ñ@'b¹¯VS`0®Ú¡ÀKäÁÀý¾>?ˆ>íÇ k/-q^Zµ ¼â´½1p¿åˆŠÆ@uL‰{¤‡; 9E3bVJ}ó»Ìà ÚäÀHùp –4 É£èAKU}r f7®"Ì#_íæ@Ø\b™1"zÂq#Zbn¥dhD^;_ÿæÀ0+9ÅãQt%9p´¸’/„ckMs ¶ƒþI†Áqà‘ ØÂ;ÁÝ1¢Ÿ#ýs0bD#Œmør ¶ðÐrÏ$Áè§ö!Áˆ+ÏH‚±nV‡H’ F´l ¶|ˆ[Ôî">’12µ I#χ°àŽI‚m&D‰1Rú‹[Ô|“`Ä4¨ÔŠ1ò¨GI#j2FÄ@wãÁAˆ¨â(`‹$k¢!A#SøHĈî b#C­ ‚чÈ–Üê3GĈî‹x} ÄÉ_ ØBy"Á‘±.H0J«“1IŸz‰cÞn"Al3Ÿ7 Æw©ÁI°e= –ëÐ"¸£‡Q ážûM‚D0A‚˜÷›cDÖR’ FFúÞ~‰XÓT Ë$ˆ‘ÖÞ$ˆÑíb| Á#}H›\ÎßÄÈXoD`龜“Ž•¶YNÆŒ¢ÒDð©ˆëHƒYÎá Œ;°ƒh®«0ˆø”¿œ0ˆ–ò~ɂ͞K’`ĸx,놃¨EĈÈ_$Ø¢²?EÄ6:H‘ F̘A‚±aI»y>(ˆÞŒœ¶D‚ؤvD‚Ø„‹ £ F4m qu lDAŒÜ4‹[t¾å6DÁˆÓ1 "ÄR¬ó± bä~“ v£‰Œ$ˆ-ß bq„‚QôB(@Ú[„‚ñûx“± cöFAŒ4Ú5„‚%¤gB(ˆm¸ˆ6 b›Å›M,ˆ¸¡~Yöp(Y#šÈ‚qr8!б §³  ›ÏW™£Šyá§È‚Ƽø©`Aì†ôj Ǩ “0ˆmŒ”„Áˆ}êS„A„: Ó†Áøå„Á¹q„A|Š‘aà žu®\ ƒDåï b›*j# bF³ ƒØ¦`ƒïÝñcx ƒ`¾Í ƒè û5¤_­årÒ0øú”`0¶yÃ` ,"a#|„ ƒ=Ráv„Áiüa0Fˆq„Áø}•”IÄ& ?™MÖ… Æ6é2 v|1 b“ö‚Á@󘃯-È‚±&: Ä&\”™±›þð›É‚áÃiŒmÚ«nÀŸ)wppÆî…ƒ(ig1q¬³Hâàð¼gD•oÊsÆAÔçŽ[.që·xqMÝðÄñqÆÁ\Þ%bɳbáð«2¿Ô08T$YšV}K‚fHDA„0ä' N•KIÄ "&²dÁåh}² Þ1Í‚ˆV\oDͼ˜ÈÌ‚˜9¨§š1ßpHœM7E F‚§!8aÍèãl£o|È0ˆÙ5VJ ƒû%ÍS‘0•ÿ¦J(„©ž°j\ç% ╯ׄA,â'' .‡ŸÑD2&Ö„Áåù9a0¶‰=§(hÈMD™Ê˜*Qˆ"f¥„Á(Îßn\*c,ácò™XpYL„¾ÆH¦XW”\%Œ¾î, NMÆG\¹K‚M—# vE—Ž$¸ç8’ uà# VE¿Ž$¸¡ Æ‹’ïv¡ ŽA¡þ—&(ºHMp/x©Œ¥&h-öh‚a'5Á–#];#5Áé8þK|>$ó:—oÖÃúÅi‚{Ä 5Á³b1 bCµÇ$ˆ5Œ(O$ˆê#ä“àšæ*“ Þ†õM‚«Zµ&ˆGRî¤ ¢ìtùh‚·ïöÔïÔ¬ âpõ)i‚·+ YD†-Í’ *ó, ¾v,Ik>(ˆOu5[—$xeæ_\–nô·$ˆl©{Òq¬\U[ÄÝöÕ±°÷I,+±&ˆâTú”4Aœ!ñ£4Á¨jH6”&XºïHk‚¨5Y]4V¨bé *‹—BQѹ`£ï¬§( Bá•à'Q0Ê“¿Q't©â£DAœb¥šP¼ªÏ—EÁâ`uŠ‚p° ê$ "ELne‰‚ø”R$ –eÿ€…ÁjE ƒÅK¾‹ZDûð¯.…-å{¦.ˆo”]º Î#÷KY~3¡•dÁr‰9­ âjrÑoœÓÈ&QÅü‡ÑÁ7ºDAøÎyö, ÆÛð£ >—åP«‚è/Í›UÁ,†#„ÛÜŠQ›(Ä&„Ø-l Bw¯|‚„‚¡« ∂± oQ¡ ΰŽÊª`½Âš,ˆiÁ?G² të7 âT0üi„¬.9T(ˆçrÄ(ײ¿UÁþŒŸTÁh¥ÄyK(ˆ³ÃEe¢àsô<¡àS}ß«]B‰‚(þ" Äéâ%Qeá%» £áÇ[ŒGñ­ ¢Óq6I°yš7 ¢Ã‘¤D‘` öI‚hL¼ˆ˜"Áý)ÞKI‚˜ ê‡[Sü'I‡™N$èÓ‰‘BB¢4 îmê—kSD2IK â]H¹)H°:Š”$ˆPº„B‘`°ù`ô‡ÿ Ä~Ê$ˆt»ú–aœ¨’E‚Qåƒ|&Äm˃2 ¶0ðBÁVÃJ|žHÌ™À(ˆ—É á<¡ôš(8|nŒ‚QÈ…ø%IÒfAÌÜoegÎÊ„AíË[ÄäÙ̇¤Á¡n ƒíI0 6ûÖQbaÒ>ÿ‡Eä®X?|p÷@Š}/d¼%Pá³Ã]jÔá¿®péá¿¡÷ÐQ€CúÚÀ¡hÂ@ƒÎ@UU9 84Õœ‚®ˆËcèPÀÿC§¦c õÎbHŒ®`D®¬„=!`¶/6—æ[ Ä&Ò/M€X¨ô7>©‹÷ʨˋ)Äk¶~œ¡Y4ùs¥œØÜ=À Ø}§›±J×7‰Qt°}°¥Žgl‰a†À–2²!k6Î[†ÀfCPB`Ä3f}~# îø1K$i‘i ½”b®ÒFqîX ˆJ«Ï‡»_ÒÉ€(ðÀGÜ ˆ¾Ì€ýù™{µ¼kìŽK_›÷n ŽBÀž/W#`Ô™$GŒ€h›V?jàH7¤pÈè¥õÈwB@¸¤ëá…¨œ^Š$ÂR!%RÛE'~ Ã9ÈO ç󳈊q×çcµÒ覃I€Óï®$@¬¸‰39¿ÛÝE|G*WÀ鄆@äºó €3­™À©Š¡ÉÓÐmüƒé‚$lü‹—ýG œ’ˆ’þ°IýÐ_ÜÊܱèoÙz–ôϧœ£¤¿e5$m¡(ÆÄÁß8p%ø[–Yþ¦Úí¤)UG:Q®Ðxs¹B//ž“ý¦m‡ýf‚§àeyú ³H55ûá}Ñ^ì÷gjʽ…@߾Х¥øÛ*CçËÚ®7võ¸<¶Ði/iÚBýn?¶Ð©{’¶P;¶Ž/)û™íM?¨l±ƒ·­¢ÉEØÃ–¥’I‡›€ÃÍÏä@+1‡‡ åÍ„ÃË&TsàÒÝŸ8­Ä$b–bº]ªÅ^ÑäÀªÓy8°IZ8Øœhì »§A¼ºcNzƒ ó€à¥™ö ‚ =¿Asä[ Œ›äpàc·frࣘöáÀ¦Iópà%æpà0s&E€Úm{8pÉÑimð­s@0: ‚3½™A ‰‘To0Žø8sI سfª80Ü|Éc•Ç%‚8O¤|Žâ@Ð…ò‰ÄÁR ‚pôÞ†¶Æx¾ÕÀù+5p&+Z œÎiLÌ÷¶I’¹F¤¢Ø>VѦð›"¥Jr¥H É$Í ?(ˆTm.Y2Eðq ÛÆPø²æ[Œ"€ÜÄ)‚*'E°Ù9˜)‚=·qŠ gê“"ø8j}Pá¦7 2yà°àP}©DÁ)ÊAÁåD©Ì¼œ×“,¸m:‚—É>3oGÞm ë¿Ý08½X3 â»Ö'C°ÜöìÓ¥šzà2Í& æj=õÀî<Ût†Þ¦›„ÁTÅ ƒW¦OQxŠVQ± *‹DÍ‚—é+å@·/I5°XùI5°Øi<‚¡ÕÀêHDªò>’1âÄ‚P%EŠKM‘,xg±y¡ DZUô´˜–Ékö¼•˜ÏBjYñW ¸¦ËK ÌZÕVó†xK®¨+)СÎ#¦aÜ xçõ¶Ø´}kƒàž‹X1ÕwŠ F¸6ID Våò‘‹=dI‚¨&ÝQ$ˆNåd’—3ôþˆåv~¯AðªN 5B8½> X¦ŸÃT¯ä3«·COFAôK¨LIöe }šFl •ÛÕ$x•Q$XlLDsb>ß&Á’ç8ÕÀæ·…Ipß' ™‘(> â‰a8E(Ø¢] · FûO’ Ê>*gÑj`†e¬ûÃS œ–¡Œ‚¸‘):¥1´+0gÄõ#b]žv³ ê¢Hê –ä³ ˆë#º%U¢`½< „ät½ÅÀˆçJm b‘D^0 â! cC¦™Ôbà¥Ç3Y0ž‡/Ä78®Ð)iü¸BÕšñ˜B§l,I‚¨ã&~ â¥"k,NŒHħx:_¦P!±YoÄÊmƒ%rÇbAÄÇÇêîM‰‚˜^Ú+A°—‹hZwÍ%s4Å!@Ô·ˆÉ×t&ðÜ v„>¾a,Þª(•ˆ'îúh€Eͳ11÷âA©ÄIq Ögê!œu梲`u´g°#k-ù¿½kƽ·8ÛŸ-~ë3¾ÎÜ÷×ä_ïzl?íÿlõ®ÇVÊ&øWæ_¯ýxìì'G^ûy®¨¸á£õ_¯ýxìì'GÞû‰ [÷~ü×{?{íÇ#ÿéuæJÛo×™»Æï„c¡¹ò.÷sŸýÏ5~«ÐÜ:ûÕïB³Y²èçÛ`Äôæ`?ß‚0`ÌS†NŸ}•Óçß%ä¼³•÷ó)G§}½JÈi_ïrÞ×ÙÊûú”£ó¾N 9ïëUB.÷•[å¾Þåèò–ÏrÚ×»„\>œ¹•÷õ)4W&êpŽß*4×þ¨ÐܯJ þN¡¹ßÝî§Bs¿·ÝÏ…æ~»„á·ÐÜM~¿5ÕüzºûÛïLYï-þÑ”ùÏš½áMü)4÷çëÃݧ¾Û?¨9÷ç‹×}kÎýÇ*¼•ÉÆ?¨ð6²ÂÛ§ðÚ럧Nš »ÕûýÏÿ§5Þþí7j¼Ýù/U€ëó7ª½íÁÿ’ÿbµ·q•éjo{ðWÕÞöØ¿ç¿þëoŒeµ·òÇÕÞ¢Ä0–#‹pÍʵçRu¶U·v#®í‹©õ±øˆÒÖ‘->¤F‘ßÙ˜«à(׫ôöGÛ@ke —\!fĽx?ÕÂxÒŸ"WH“×e(XE,õ© ÞªuXŸ‡ÕÂÔ‹¢¢KÇú t§Ÿ„g(èÎffE§bGõY•éÄ… ªVEÙS¸"äþ} lrYìÙBrh•‘Àâ„ïÚžaޤ+©¶¦Za…®²Ú:=ͺ‹BN™á„Xü♵˜ãYÛbºDÄ]j8{X+Œ Vãš²VÃ@5"w7k|qö §Eo†*vÐé4`°¡öGµÂœÛ]Ãzû„þïmºj…=ºiàøHvK}5„áPà¬Hå(e~PEÕ¨2â×PB®h‹@àãòl5*.ÕÿÉÔ{„ÀèÑG…þ®=ü£4KÔñ¨VØò$…Å_8Jo…>*êø€&!'ð›#¨ìÁ뀶íQ.¬1ZQ˜æ¦1–:/F£¬yl3o†ÑJâá6…¡@´Pç4Ÿk[ùSUÕÂlæ¨Ñ#šš7…˜:«…-…!+b"ˆÚ<éhjÕÂnå&U´ëXºxrÐÚž„뺲Z˜Nzh*”×+ZwD¹°K§ -´ \E‰ U J¢†Ïš£D¹0Wï©h>õ¿bÐB ±@\NÞÈÑ|$ôt½—¢{ߌÝPc©è×åÂ\îêÁûåÂ*ŠKóàýå¦ü'ÞÏ{Gõöb¬Õc 2ˆ™ƒ;~X/¬ø¥øDkÆš5ß9šh¡^XõÔöDƒ¶µÀ(=h¢…zaS¥ÍÊ#ãÕ:vD½°)ÿ⃗ôE¿ÓY¼¤oú%ô]xITÒzä{P5ÃBg垣™:m1‹èA­(vIÐ|¢?Ü>P´j÷A- ÃÄ}óSx«¢èTÖM•g¾˜ž½ÌV&R|дðtŠoÂ+æ‹¿>Ñs¼G]** ^Ñ(#F¼4ÒÚ³ºá0¬ô ‘ †-'>ÑHk±wZªÆeÛ³ßÑ,(ÏÐS ë…õ*×ÔS+ë…¡z/hÔ ËÚFúhUžO¦ <è£õ ߾Úh¡\ذU÷A­Æ3Lû©¬+1°pã6ZQ/ìÖïA-Ô C5¦Á• ³µày Ë…-+ÏSY.¬+æùà cHÚù¼¢÷s;Âsç´P/lùÐH å¦ó,4Ò‚3š2?½Ì&jq‡ ð ÖžÂ£Ó¯6Úhí©‡Í©G" ˆöœXtíØs8ZFÅ,úàý¼¯v£çïç=‡ÏÛÆ‡ïç=‡c æ,õ “Ö>%0°¤Ó•‰öW¡w7g,0÷Ž^Óz¤¢˜Ç¾A«„£Âö>%˜É©à>!ïþ@7䮿£S)” :П°‰‚âOgß­hÖÌ{šÉE?К¢ïCÞÙåßz¢Jæþf„<Âêùàí¸çï 8Ïf= ‡2—@Ot܉Ä3þ¾¨¼·¿ê®zÃ<0óì ?‡_5BvúgCÜψ^fç ÑLkbÀ‰Ý .œÍ"Ç ƒ3û(÷›UwZÔÙ«q\:x0£HÔ?Sç타eüŒ€¬bpâÒ›iA3 _o&ÔJó…€õK€Sg9 °[ZHÌzÞ‰€Q¨”#B@Œp)oÌŠf‰€Pá^BÀäÆÄÀÛ?'1°HÇ:h+öÁ@§‘%F1ŽG¾Çè!•[b /%g$â]$V»²X˜¶1Âö@LˆÚDˆMú_#‚Àh¨øÀLsIÌCàpvUB \X\`Fld*Aà´Ý8!pºBfRଠSAà©~`ÄHL»Ú„ <\ß ‰0<Ç‚À(Ã$ ë¼.å‡Û±b Œ|•A+Ê¿}㈃~;Ù±*?¼&_>Ì´ 2FõëÍL¥à—“Ã¦ÄØ€9úÑAˆmhNDýõá@˜’øsÌàê!2$býÎ /ÛeÁÈ¢>a Šð;ë›ð>2^®ˆ²3χo¯Âw3ëoÏ’‰™YxÙˆO}10«×$–ëÇ á“á™3b¯dK" ¤%â0¯IaBÀ˜`>[ ƒFÀêz›‰€X.p€ “£ °º4V`5$>·ÙX]â<°f,ðòón|¦qÉ€×cÉ€™ËiŒ²Ý¼;Í€Mutñ87‰€è È3j<Ÿ6– 5ÿ¡f7s’ÿ°|‚‰ÿàS‚‰ÿžÇóßÓá1bÅËICì¦_$°«³ù¯×nKþëö‘›ÿБqUó^?ú5ä?ª„Ä+ò_àæ"NüFâNL#ÿaf¹Šÿuþsù ón]Žø/Šks $þ‹OÝÜÏPVÀÒfþ “5—z⿞E8Í}9¸zøo)ð“ü6!Gšÿ0Mð(Ìp;òCÄ¿è Éý ÿ°°Ó&Â?¬ø&·þÝwžðïZ¿+E·ÓúEAüdcÓßåäªÄ¿Ûi¹‰ÅECÿöï£“ÐøÕ«Ëÿ²’Bâæ²’ù¯L†VÿJS¤Ä?Ôuà6þaâ҈𥊧xïŠoÿªk %þ±IÕþ=.î‘ø×Š¼+‰U¡àÄ¿ºèMú{\Q"é > ¦¿æÚIÕ ™Ä¿Ç‹ÅÄ¿Ç5ìèt«ÝÿðnX¤Há_óÒ0ñ¯ù•šü×-_$ÿ5”Žæ4.`LÛá[ÇÀå£yƒá'×3%Ä6ºÛD€ø9|ÛÇp.ƒ p çù˜±â."@P·6!º.ŠYÓQÇ›¾## ^= ÉñMšqÄ€Ñ,˜—dÎÕŽpdÊŽ!‘‚!Æy¾… ¡Ð#d‘×CZ#Ž¥ ¼0ùFÁóŠÍÃÈ™Lõ¿ù̈±–4Æ äŽÌ2ŽÛÁ„¢Â[‚ úõBˆbÂ@KêIuP ˜©9 ‚˜ï¹*0Fus"œH æù!Á,š(¸œ¾•(ˆ’Y\BW"ˆQð5BÄBñ˜c¥ßCTX˜fé˜DŒá9ã"Wˆm´âbfˆÃö,‰‘kbQ¨…(ð=B ÄBìænI ,D’c™*4#Æ2†ë\Q t>ÅÆ@¬çj}c ´N<ÆÀp•ŠÖˆÆc•ÊÃâQe4Wˆ¥­ A‹@ù…=œô$:b`d¦^!â\ˆ„8ôçØ´”µX›ŠR¤XžJ1°:·"ÅÀz$D‰µxQj5¶RýfÊO+,>NõH9ëWÞ×–±¯IDÔš\j9 Àù“%fï‰ÔqÑ¥J€ñ¨,V‡ü«›¹¥ XþIþñâÁ=B„067&JD½úÁÁâòÆÁ8p‚p.¼"ÆÙŠƒòÝ@Ô#Fp„«xá " \¿‰£P€”Hâ â0œ‚ŒƒX×·ˆah+ªVu#ã.)o5'””ŒƒqßPáâ $‹ñ]œ5ƒ§yï7+yÇÉH‡yGÁ8Œy0.Õ^,ZÆ %ÄZŸ‹YŠ#äÁè¯v¿y0ªäQÆÝÆ;T@—¡½õÀS9ÌDA òÖqF°[ušÃ#"Â8¥¼4"Bl£h‰0xeD„qFùå"¸¼æ"Âsc ñ!i;Bü>Å#„1@NFŠ›F ŒoêÒ™"ЦfM!F¸—ª*an·aÄáÔf|pðu"„ƒøT{Ó`xCH<ÂA6E8â`ܼvÄÁ8å]|¸Ð{,= _wºp0¶™üq0:ó1n ÄÍÅß'ŒYžr¯h0JŠþÒàY™Ï Î4µ ¥÷c¥,äÒéGÒ ^oÌ 7 âwßMߤ{_4ˆob&™i0j©ðŒŠ£–bµ&ø%Þ²ó›ÝŸÆaˆIQ&À¬m–˜T’q#3.lÄ ú«Â°Ãø½ p:' éé_D£.pL€3-P¡i‰3}5§*ùX œnÊ›Z FäÁ”Õ9ÈsÒ§“@S œÝÈgGhS84¡î|¡ÃgÔR ¤"éÒ—K¦‰8')õÐx,"Wžm-p¹Ôbj‘fÌýÔS&Œ<†Ði)àcýhÉø“!”œ!Ô6–cu«cuÛcMX:BelH-0ŠŸÅWY ŒÝoChˆdím l¾0‚ \ Z „ÆM„€ðué«–ë„imšŽÐGÆç©íŸ2„V_q`øUßR L£fB`¶GH¼F*Š"Àkù¦5^®gr¤ÀTÆÓªü¢À»ø×Ñ)²rDx;ûí8BoÃGJCÅ_ÞRàО-v?ã”§%Ô‡½~©¦só¥šË,^S¤xËYüÒ%®¤X´8Z k¨%ÞL0ޮƗxïg‚g4õÀn¹_ˆØ×úFÀ{øD€÷°¨üÒå+0â]O^I=°ø×X,öæK”ö^ÞÅF@TUÖ6B@”oæ-`,^ô&g'Æ0öcD…žo3 îŸ)4 ¢•)"&ïu3`u53`õÂ85“µc1`ú‹€¨¢öüJü`]~/™1SrHtsâC€.º›ù‚÷¾0T×·'A0 ‰BÀÇÊŽb)ç-#à“Žs#àY˜ŸNwI hn|$Á'g"ÀÇUÚ‘ø¤MÓØ\=ÿ  Óº¢îAÀâµs"`±ë1°Y36;’ Ëí´§â0`®Í€®òœ›·L¢‚Àžê@B`OÜvŽ“{’Ž(°ßIo¢ÀîI')°»ŠdR Ö­êݱ»Kh$F¡#îFˆ„y*¨†Àlؘˆýn†“’`õmdDk îØ@ˆoëí êJÒé„Õï–ÂZS$–<ÃÂ1îØ’`•¯ °¸óSaZ÷%·~L"Dù#—€p©ptòàJ›œypù„ ‘s$Ÿq DÞúÆÁîÕwÐ ZCÌO‚ ,REƒÝ+Ç£ºßnÒ`¯™3(ì.PôÎ0ZtפÁŒb& BˆÆYœz| ƒËýi ƒxƒ|õ@ðËýÁ‘nn¹“4x d¢ÁYõæNŒVê! ¢¤L¦Nl? ‚{eÌ7i0R>‚`WýÕ„A\8É“‚Áž·°`?AÇ)Œl1%é1Â÷Kf¦ÆjÁàÈnH†Áq¿@oaÒ#A0FÆ';ðñRø-êÎ âÌ›´„‚ÍÍéNvà-&9(èbw'=°:_Á(ˆóQaÖbÃégÈôÀöM„Û‹%£`˜ù :=ðVùÚ“XUžïˆ3“ø„‚Ñ ñ…‚#o1¢E˜³Ñt~Ü¡8LÒ…Qp•´¦ ±’ÕîÐÎ[+“§cw™xla"A¤t]bC’àÈù“XÔ "Í¡¨ÂGÙÉÉCújºC7n¯ñq‡·îIw(\2$g»C« M¦=Ñy‚so›IÒŠl¬[âŸÜ¡NIwèíVðé…±á¢3em#s øXn³9s¦ÐPîPTޤpkwè“fA»C2jwhuÿn¹C§/”Ý¡ÅÉ;é­Ž§;ôîNµ²;Yh\@ÛŠZŠŒIðùdâÁã&²‡ÆƒMÒ’=ºêÇ:mH{(Пä`{(æÃçmÝîUÛC#-ò-¼+˜Ii{h$Òu,?éPü¹ºCK³Ø&shq‘ä4‡>î šæÐâ<«4‡V·gKsèÓ±9´9±)Í¡pë|@w Ãiº¼T"eE¤Ž‘»CÔ¢ÝÑîÐ’ŒÜ¡¨y&7¦Ü¡ûË¥”Ú #~û¸C‘Ö|½3‘ -H·;´´o†à(V’±Ò¿Þr`¸:y.œ!ˆ²õ-*ÊdDZYÒÎÐH;e: ¡­8b n·e,E—¢ÀsטwJ D‘„ÉâBYê­Õ‡è®ÏýÝ‘´ÿÛ»lÛ{‹³ýÙâ·>óçK½}Mþõ*‰öóþÏVï’hmÝ¡åi?þë½½öã‘×~öÂíÒNøÏ×bà|œ¾>;®(Öà3å¿^{ðØÙIŽü§—wkaÿ‡åÝ~U†åÝê»dÛÏuÚþSÊ»ý|é{‰ë*»õóm‡ÇþüWönóçß…Û¼³•÷óÞÊû:…Û¼¯wá6ïëlå}½·Ê}eá¶Ü׫p[î+·Ê}½¶:·¹ ·y_ïÂmù@æVÞפ¼ÞªØÿº¼Ûø£òn¿ºÂ¿SÞíw·û©¼Ûïm÷sy·ß¾³¾åÝþhÂû­éå×SÜß~gšzoñ¦É¦¼[dÇî%ï§¼ ¬A‡¾Ú?SßíúsõÝžçîôïý—¨åtµÿx·Vèûão}ºÀ[Ÿ\àmÿwWu»ëûŸç¿ÿÙo߯:ÕÚþžÿú·ß*ëvçàõÿ}·ýËÌìþ˜1:óý)£µ:ìn†°W~´… è[¬Cöm!Hø¸0X´… 12¢ªí¹h r]¹i éÎ+m{Ë’‡S+ù¶—ò¿0ÂÌðݾóØ>®;³=¶Äx‚!ÚÓi ë«m!(ê1ù©I[Ȱ®¼Gè Áñê'/úBfˆ¿ÛEW–[#7]!÷h­Ð̾øßYÑ"²éƒZ{˜>ºâš­µHÎûÛ«f¦‡£gd¬ê~ÒÃ1RùU“éáíZtQdÂ=—Í-:H0A‡Ñ¢yL´=78  T|Hõ¿Ãê49R™Žtƒ»y"زzR‹ˆV86E¿†ÊMÃÚÄãìqª#’M(kH'ÅËÛÄ*¸![3Jܺkdƒ3!×wAn™t1”Ð@~‹!q&`î+D÷SÓGj„á%º4òDö§hŒ†Œ‹#ý–¥‚†š0óíuaÆŒ( "ä?©­tM~hE0Ú‹Ä›ºEuqŒ»dÞŒ.±[ÔeY¬ÍpcCi”‹m&ø[P=åó##{Ù1À05nÒ£[F¨íSÏàåZ^û”1x¹ða ðr!è}c±w¸“/÷‰e ðRY¶}^ÏîóÊ 8-Bhû¤1ˆL+>íëa ðªŠ`ì3ÂàeKì>^BP*;ïm B.W›Û瀆4VœÜfÒ‚–ÜÍ¢Á¦x8úuÑr9iaÿÔðƒ ˆÀâ@¡äê\bíÊ( ê×Ç£º£€ñÖ~b¤Ñ‚äÿÊÝtF/»Ëö‹vqD“¡k2x)Ú³„@¢³¼œ8·—1ÀË!Þ~ßj°Äý.Œ^KÏw¿+Û`„{ÆòO qp¿jèAhƒzïN?ÈíjìýŒ†¾ÂOMFÓôµG˜भä4„Ün'Ø7ÕUuGÖ¦nÅ­Žkg·»÷ÿÒ7ÙÍMÚAn;¥{+ë<ò&ÀÛ¹èóÊ<—ú4é<ý¹é¹°èOÉ~ÔyúSéÁ}ÇÝ<ÕÝ?uk?­¸û§6étƒàiãnÇåÞŸ||”ácã‹£ãÅ|17‡QÖŽ³ÚèRâÕí^–æÝÞnšAnç•wTjKŸ]û­E7Ƚ¢÷}@O_WšMo-Û°¢Ù~Øè¹óáÄJ#<}C³]î[L‡ÑÓærïy…ävc‘ÖLå;EäµÇIy7(é0ÔÉÔGCa¿èPìí3Gé+é!A0ý”wEÑ4Àýï:´„¡ÄV'ä¤ÉãäʤG™õµ¹9²è¹•éÕñv¾ÙA7Ý ]y‡"”VؾG×ñßÊ*$\ v„íµà&fÛý6:²Ð;;è0Àב,®&@œ9=Ô!„S/TÉî=”m:Rº;ñ]Ûç5œš«©/è[ÍøåxC2)NvTN+¼¡£ßK‘Q¶¯ÂŒ=y‡®ÊŒ4Z⎎€II<} ±Ç›ðê®~³ßKs/¿…U7»ðjFG´ÎƒdYÔŽ>hê÷Â¥vG´É‹Éeñ@´Éª²ñNè‚í^Üêhà}õW¢qEÕ6ºpà ]ØÖ†E}Æ…c`qJ4ãÂAÄ€7aýè¨MË-¢F/.;©£ Zç Uk>4AìOÂÇe  ÚT?¤˜Ùš -šb'–‡i¹öt¼ £ÛK×r‹ñ^ùt ¼ Cƒ·õÍñ8ïÇ?[áíË€?! õÜ7R¿x# 5Ž7R{# ¹Ìh›äA@ÖÜ9è 9Ðvî€CîÀîÄÛÀîÊ €prulÌÒq €Y:.°«jK ŠbÆÓ™h‡aB ê×ˆÌ ö‚¼´˜K¼uAº)ÑÀ[ï‚öTÉÀö‰™Gý¥|pT=‰€Ãž°D@—<3F@ØCˆºFÀá^_‰€Ãiü‰€Ãµ7‡ë2%BLŽ»Æ8ì+Ns7&@Žãaâüð÷š‡ŠÁ$Î+)R¸Y¸ˆ÷zvŒã2# ¼,¼Î’°)L%90:i’ø„€ÓYÉ€ÓÍý§i HgjÜ)p*o8!pzòHœ*µb X&˜‹ÛtåE3`¤çè†éŒ4GŒ|Þ°bÀp˜ñô‰± sÍ€ØFN Õ?ú›[Z$Ì€‘»ôpÏdÀpî˜ø.Vö(ˆYPž¿ÌÖ GHZçH@ Ð<î3`p7ßó‚@Œðüƒç G؆å` જˆr%·#¢ÂEßÔ3fŒ¦£ì`+Œ8À›ýU›± ÓÎ̀؆V53`„ ~J x¹‹0¶áBÎ xÝòù$"À0É›dÀp‘p€ ˆÝ˜æÄ€ø0 ‰‚.1 Œe\»›/®áœÜ±ðr²{2 º9ö^‰BfÀ(QÈŸ#¼œ-› x¹1Ÿ‚/—f@´ðã}b„ÅPo¼¬7%^¹b‚û¹œ2žÐ…!ðr匄@ìXÔ*̦­ ø¿b¾]D°€×Ó xÉÁ– x¢É€n§–x¢¦@´³¾+,Øy(ÐM]“á!yHT‡Q:x©dΡ@×t<x{垘«å¤À[±´CçS¦@·é=X$é ¼µVI ,ÆÝ¤ÀªÕC{ºãœèp‡!ðVwÎÀîÌ€p=_|ôÆ> Xý? ˜7ºðv²ÁaÀÎ%E2`t&d A!¤š„@·ˆH¼[â› _^¾èòÒI¸ÎKÐø fëÍ2"’hŸkR ŽŠŒb ŒÎ¹1Sà0á o×98 k‚@Tã«Ä~=0‚Ÿ/^‚Ÿêf3–[þè¤ÀâÚƒ¿1P_žxÉ‘“X|+½0Psxrà-¨:˜áÀÒ÷v8°zÖLtQ“7ò’¿Ap‘ÅÒæv8°¹Mzr }ô‡»œ[É.}|8Ðe½ºëAO¬‡âž—¬„ ‚SJL‚`q¸‚òvæA> ‚Õsí?Qä-Y·ßœoNHœ*9–,C,ÃøfÁéG'Y0V4±.5 ⸈_bÁeOaÒ D}Š4ˆº|\?š—]IƒËFXÓàKã ⯯i«º‡ñJÕR[,o’EüºÔBܵK ƒ§8\ÒàtפÁÙ’ýž¬-Z N[¦ ƒÓy; ƒËÙ« ƒK1‹dÁè¿û¹ ‹KOl’ $0®éM‚ËõŽ8ð&A¼Æ¸‚O1p)Ì•$ˆ‚×üµ&A¬éû‡£»?%Ì2û‰‚HÊ¢ÆiÌDý#N¸"Áiô2 âV$§& ºáôo%&1нZhñàˆž?ލš¤G Z1pJG9jàd:Ê[ äJ㨩Ò[¾Ö):^zäÀÇ:®QpY¦HXÝ +,Q"?³ +H% ¾¨Îz`s´%õÀÇêdêͲ}êV7Þz ÏhÊN§{ËL8r`ýY¬Ép–ñ)º¨Á‘‹—墳þS,’Œè$GtílËYàȮޗz –Ã\ÔX¼]®5õÀûú =˜·ÈKõÖzO=еÚ ŽTö¤ÆYãžÍ‚–‚›WçFÁ–*90dZ’ÖAA&È9pé‘?r ÃGtÕ€#CêÃâUên~ôÀîuvêŽ9=ЂôGä=Ô£ªÁ‘«•ž—hiïèÞÆzàm‘K(X\0Qk,ž £`È$ür¡`IHO=púÖ6 ¢F½øK,Iä/ëCÅjŽ8ý¥ Øýí ƒ®vñV ¸©6ëWdA·›8,Ø”6pX°èŸ,X\d=Yg‚p(„ì$iO(X\î;Qðœ£àYS¬JT´ñ€ Ã4ÉËpÔ@­Ã_j žÌä@§gìò™4Œ½@P‹Ÿfƒ`¶}O,nd’ ½ƒ÷^ŠÅ(kÄ –¸f50…³$Á•#"A$5r¶KLüyÉX“×/¢<ƒ`µ ‚ÓJi‚à´N– 8d|O,EûM50ï£TýžO,]pqÔ@W-LD¦5Ãg)V­­èðcªª´¦” è†o|ÆG¯­¯èÒë/Üâ¥jtÂÀ•ž0°^?©Õm=.?PIÓÕ¤À™¿×èÎq‡-& ìŠï ì|ÈÞj •ñ7r†S Sh^(ýí¥ »’‹Œ`IÕå“kªŠ¦À꺦@L:’ú,>Bä¤Àê4 ¤@^©äBQàcáêP`Ó~þAq·£2*û&?÷9Hò‹–>_ô»õøôs'Õƒ~à O¢ßÒ|þF?Yíýª¿ËèWUCì Ÿ›ÝôëÊiO!p9É0…À}ulC5úM¯‹-.—ÔO!p¹?GÂßå[=•À(Ÿñ3üI-J)е¨üÝ*›ðw[GKú{T’&éIý<,Ó_$t~ðeBę¿ýsè¬Jœ¿Hç³tÉrPÙ&/ÿÓ zûR¥èjÏÇ ê¦MÇ ZŒréMweºAÝžã¸A«uÒtƒvÅ~>¶F’‡^àÐëå`·f›b`—s䈩§¸¤ò,Z¦t¼÷ˆÓªhŠîJwÐõ¡º‰ÔaÀËŠ—Pnå$Àæ¸Ì‹ï¯¸Fê…&Àîë›Ø s&ÀŒ %ÚYu°ùI5püä æåM5púÞO5Ðå±è:JG L°M5°ûÐS tã…£®taZ ôd‘j [`9P=8ýM5p¦±Ôj ã ‡Ýï5-¡·}‡©ºTÛñ„ÞÉŸö„V/"Óê’‡}+¬rKtñÊÀ¹èI¼Ó%j|¼H´‘ è6\É€UF×DÀÛç&ðÑ›þ¨íg¼Ü¼í¨ãg¼Trâ¨öâ5ÐMoŽh,ÅÀn™"ÅÀ™V‹Cѹ§u‹»µ¶Ó€÷¹ z‰²¯¥˜ÚšÅÀešJG¨gŠ#.¥:1PYàG \Z-Ð5;ßb`ùjÃÚPjËbàt„ßü‡¢¦µ@×ýkŠRÿ]éö5ÿ¡¾À׊’-¼ræ¿ÛÅ’ÿ®•ÞK ”Kóh?  ½¼¥@éT)º.À[ ¼Võø$VïWèìý€ÅÀÛBïK”ÊgþËÿñY±˜Ý«çˆûSô“›:`óã”: Kμ…@.Èþ5ß)vƒoâßcø| â—Ä¿î`ÒK¨›ÿ\Kíð_ID4ÿ=iµ8Tæói{N!°%r!P_žJà´ù=•@7Ä{K —¼¤@ k)Ns· kf °"À;…ü—!Ô¢ž ¡ÓfYàíþh‡32ù’Y ô啱%¥@{¤ÞR lÖ†Àc-~Ib~CàíÎïtwíø=è6o™fVE¹:Þq(ÐuËL°Y—/…&V>äG |$|)ÐfØ·'”òyJ®rw¤@—w:R`•µåH®|¤@—ê9žPÇÄþ‰ÚnYŠã „·¥¶—/”ÑÑ·/”ëã UåŸc Šƒ[èJ£¨m¡ î$w-4§Ÿ$"YI`™h«cæ>N&ʼÀæ¬¯Ì ìò<Ÿ¼@·þ:yÓ—}¡Xw¶Ofàt ±Cƒ%m –O>¡iðÑM–4˜bFÒ`—=äР{œº_ .VŠ—™G4ˆ @<)ºèÁÁG±îäÁÕ ˆÖ[2¤pp©çè‘»<³©¯×S œ’7ŽèbÁG \RÞ ƒXìÊ4+ ‹ÚÆÐXÅÖ·1ô4­5 rIÊÝcå(Ù‘0kµûí =ùd†ÁPMæÛ ïÁ ]Y½+›ÇÎöv†Æbm¾ÁØóõv†b!Z°`,²Â!i0VoRöHƒ‘D£œB§ºtñItÓú“h‚Óo×íÌô@èb6åbäy{CO†Tê·åµÔ‘E{«õ@ä?õO~`Ö×NA5¸?éwfåZÄRKb¤Áûù9?_UÞù·Û¯¤ x;ý ÁÛÝkR¼G‚Á“d4ˆç„"Ži‹î-Óàíä‚“!Xtßž Áä™ÌÌ´­ÌFcg./¶2C°g’ž3 </v) fFÖKTªfJ‚ËËö”WŠ„–WŠ„–—a9%Á¼8) .C£AO¶©º™üQ—£ë) N æA(OÏG,*›8ˆ%å#ÚbjAð¶B”‚àmÇa ‚™ïiDÕÕúIÄ~äê´ x;:b Œ ›ŸÁâRg „% ÂHÛ∈0œ8""Äq ,A„•¤ÿ‰KÆ’—óHStIÑ£ÚÅ~ˆp&ÜYt÷µ# ^v¾$Áû‹„PK§05Áúe¸4üv1áYoUPŠ•¡ð¤Ó Ïù3b¤}s‹%ic!ÖÉ·ÌôWYÌ_“²`ç˪'&¹Ðý¦d•\Ø÷âBÁÑ‹ A|DgI.tÒÑ› :È4Á#*M°úîz¥ Êßm.ĭ‹•\è |ráåpúáB× =\˜nrá¢Ì–²`¦D'ËaI…Õ´ô¢B'-ƒhçÜj]0÷I…rˆ(tõÙwšàø2áõË7IÄ\ß² ®eÿ á5v‡ÞéO$tÇäDÂ{H7^nç“Dx»Îdáe{W!þ¯dAM3õD„÷¥¥da¦ý&FS~JDx)îœD˜wzaºˆ #›#BÂÛ%M ᾠʉ]§3‰ð¶ütˆðÒºöá¥ÕR!ÒÅDÕZv¼ê¼ Ô£l®F¶*Òºì‘ÿÛ»fÛ{‹³ýÙâ·>óçë¼Í;z)hïù׫6šÇN!¦yÕF›Q¶¤x?þë½½öã‘×~Ö>ZÿõÚÇÎ~rä½¼™'‰-ü×{?{íÇ#ÿé5ßPŸpì3ö©ùVÿD7ÐNõWõ·~wÛ§ýeý‰môŽ®Ÿúp?— û3¥â¾÷ò@§ö‘¼~¾qÑ|ò”‘Ó'_%àøéw8ïál¤½|ŠÉiO¯pÜÓ»þ›÷t6Òž>¥ä¼§SþM{zUË=åFÞÓ»œŸÉSü{z×~ËG97Òžþ#âЖþ†4øÿ£q4SþíWóÞoÍûÕúó\ùëÛô×ûøóâ&´•oy¸W%7zëY½mÿëï­è=µÞcªó¶ßcã5ú*×Ï?ÿ»ßØç¯+Òý™^ÿ uäFû­†Üsõ?[C›þª†ÿžÿºó_=ÿõ«jr¼ò_g߬&·×õUÕä0øs59Œý{þë¿þƘ«É•õÇÕäöT¨c$ü?9¹0{Ÿ9óÁ,Êçç2¡GÔ1ÊÂÅ"U‘GTaLFQ —JÀXŒ:vÁò˜£Žˆ˜Àfµ G Yk±YvÌÒqcVÆázâ n>ÊG¿¸ ÝJG¿”I9öò€ùè—â,ûç)Ýö¥1‡òÑš¸¢G´ZÚÁ\ÊG¿¥+uу2Œ¸cÝô ì.úV¡e¸@Çþ6ZPÐà$¢7c=´  @è({„”áÂ[ûäÑ‚‚ZÃtÊ­N ÊaL`ã-(Ã.±&-(¨óñˆ½z #ñ©y]aA‰²Ô3hyÆ»E̫Є2ìÖ˜W¥ %~î¾4  {þ÷ (h+Û}ç„¥&wÑi@Á‡É7œÑ€2œq8¯IÊp#ßy-P†[´Î›m³øÀ¼oúO†“Äæ]è?Áù 4Ü7ý'cæýЂßÀóp?ôŸdÉ‚‰wLc’êÞý'Ãv„yðŸ ÷í{ž ÿIZðæ½h@Ã_U.P¢4`\<¾0  w/ØOÓÑ1‹Pj¤££ OWyh@ÁnxrÊÃ|ôaÇ̦[æ£G±féÌGGÜxòç &¤#ê´¸ÍdB:¶¹9²˜>M3³^LH?ÛÔ»ÐGx±ÔÞ†æ£#M#õfŸQSÙ°}q½+„±GqŒ^«Ú˜>/77³FÄ1x•³Žˆ8FGØ ©YgDOØYWDCð‰hO%qŒýÄS?Ÿ;"ŽÑ%6âVó‰ÒDahÓyêMá¨ø‚>Ïeሞ„=²(Yý›O›¶2)|>8ŠØäáß¡hÑ3Èè“[Рº§º‡²‘­â³]•²Q•!k6¦wÝ~sßa"|È&‹ÅÅÝû5š’®ñ¾G–]„ ÿï[lº¦¤nþxÐÀÈÇ QŽê˜N:Àéáw1Ô0Ù¾6ˆ*Ü3-´[[„¸c@'ôiÃ…)l.4[ëSî ŽŒÆ\àKéí ÍÖT˜‹á…fk‹y¼ÙðоXȵ^ÑünݳxCßó•¼ÌâØq«‹Nð&8ÊøÃò›þÏ–”{ƒ LÑ_TË é÷J<Á¡Ùá€àУ@ÐÅÁ Ç铇f¸C‚´ NC’I0ŒK˜RH0 v¿k»ß5‰‚Ýý‰‚¯?…‚ÝmW»-䉂=«C˜»;Ì$ ¢Vzû° Fè|3 ÂjE9Â,Ø%^' vâIDÑ;¦Q»+x& v+ùFÁH("´=K¼¼ÊJ¼dY;8x%Ù/9"í88èWÄÁA×?8xy•Ÿ8x«ˆùÁÁ[u€ºÈÊáA÷!=I„ƒÅW“‡û‚™‡ý½ÉƒøjÎêæÁ113b€wŸq»Ù Ç”¡Ò8ˆ¯&‡YÆ4ˆ@×CB Ž• )ÌÎíIƒø&^Óàp¥ð¤A|¯¶i0Fb.6 "ðÆ0‡ipèÅ™08ì¶K<á1Ãà¥V{ ƒÄ‘Ê ƒC •“q˜| ™á6/ŠÃȱ ü9 5‡k0´ÁçÀà¥Û&a^¥ÎO/Ö Úýœ0¨Q‡¯Ü‹aðÒ/Nœî¨z`Ð~²ƒ·¿I0˜E[ñUB6Áàt©”„AÄêê§ÓÛ§«‰' Î[eí§ÝÅ ƒÓ.ªƒöá$ Nw8HÄï ñ©NÔ# "¸Hq‚Á鬣¤AøÉo¤hpºfÒ úDòÚ˜pU’÷¯Yú5¢Ál “48ÝF9ipúUš4ˆý2Lƒ(–;ø)Ó`Õê)ipZCHŒÎÅD=Ñàl‚ Ã`Ö KÄQéçˆïäiD€TÐ&Œ€è‡§[/' "¿ÑÓ ‚’¼¾¦A/ƒq0ZÕ섃MÌd€ÄÁ×· §Ë &fÛùäAÄ2ÃYeÄOþòàT½ÄAübò¶q¿x…ƒÃµ·þ‰ÂrI„“å_D8]‰5‰p!²²"BdnÓ*e"ŒRi"œ~‹%N—VI"D€†šž€p5ÍF „™Bœ@ˆÄc¢’þÆñÑ‘ÍúóÂÈ8¸¸€p9ñ*€¨–„€é¸¤«+SXaØ@nt10òè®7C¸0lä,( ƒ"•Iaø­×[ŒÜ1í™DŽ5šãD„á¶e•ˆ0ŒŽå¶ Bi \$Â0®·8x¬µ&Â0öö7†i·h„9 %é…DȤ4î†D5Q°†Õq¾ÂSçÒDÊçM„Ñ@”F"Œ¤¯X£O!Â(ëÂu”€0>$@åaxv„Qø’ËR!öcŒ ì%%Ma¤—‰F „¬VC´#¾~Ž€Ûhý- Œ=sMD Ä€ˆA@•SÞ<ÅUôò`ÔÅáq0ªpJ‰$¢ø‹–DÂÁ(õ¢LĈèâÁø”´?ò`Œ’yðæ4F“ã÷¼õAöQ ®G ÄŽE¨`ó¼0ªÜH $b]Na”ó$Bˆ£ Î[Œúžü*aT%< 1¡0v,@ #´gaüœû…„± =!!Fô  cÇâÓ¥”„ ê ã'w2Ø]²Ö©FÊ­Z§Ò2„„¬$ÄMžËµNÇBÂo¦7Æ— »r2è$$ħ¸À0b„B…‘0F¸2òS?ÆO ˆ0Fb7¢Ð*㮄1ÚEˆLI¨^v ßßL$Œ‘ç„Q¿µó‹ˆ„±gÆx„„ñ)Æ„„ø”ÀWHˆmEH{æ“&$ŒOQšöxsï…QôƒPˆ누BŒðæöZLB‚¨%@%ÆQ·FßÍgšPˆÝè‰ƈ¸‘Tˆ‘§k„ ØFŠ ©0~±¾ŠTˆ¢JºMD…<?b7šè…¡GÆPÇÉó'(Ĉ®§¨0~ t;R!Ft×’ c7Ü‚PŸa@SPßMhbd½¡0 E]o(Œ‘ö†Â¸*)–PˆmÊG!E*dE,~ŠTˆ.þ …ñÕÏ 1Ââñ†Bœ é‚Âø&Ò¦ 0NÎýVy«sÏ-³Ôõ!2a|•FÈ„qc“4Ä„Ñõ‡Š—˜0îQ2‘gBËx!á™+„„1À5º0æÞ*HdFŽMâߣJe·ÞpFÂØ¯”0~ )‡HÇý§*•9vo$Œ3Ël#aÌTa…„12ßH؃¢Þ!^Á¼I„‘Dɳ#$Ä;E¨&$ŒÔ'^a1aüB³˜0¦l wbÂxq Q×£©–,G&ÌyÁH%Á ¬BÂ8‚*9ðò>wDÂ×)$Œç—Ç$$ä‚”ßE$Ä6ýz#aœ?b·ß.‘XHY–Tâ…„8J}‘0&·ƣȃr®%Y’ £œ¬:¹åT™K ÔÞXœŠ“褤ÄÀÇ*Vb M…eà9è^/‡]5>!0ÓcL× Ä”ÓÄ|—ýE &Nw;H ´9(UA, )èq”©o: Á_'U‹až«‚¡ýR¢ >ôa@~Õ<‰‚8êûÍ€1Ò?ÑŒ÷¤(ˆxÏó5ˆÚw ¢YŒ# ¢®y ¢®i“Qw´<ª`I¾³*hmú¨‚ÕkÁTU戂îs•¢`Õ“rDÁj—MŠ‚ƒÃ) >öÔ¤(ø¤MÓ¢àã7zŠ‚ÕŸ‡ñSt## úBQÐÍôŽ(ؤ›Q°é½¢ o# ¦¯+EÁ4̦(Ø5Q05ÓCfQÐÅØŽ(8ìÈKQ°kÎ?¢`O Т Ë—QÐÝŽ(8|ASšC*8¼øKUЖ£ NÃnª‚3 Ÿv‰^¬žª`:hS\†è4‰^ªtTÁ´Ð¦*¨Ä¾# .{aSLknª‚Kžù£ .Uª‚K~ÅÝTéXD/y>Ž*¸4[§Eôrt#eÁÅ2Ç#zYSM¨šOQp™†Ó"zÉ‚”Q;¤ŽGÔzÀñˆ^é+µGôò}“Q粨sÙGô¶(Ñ[‚JZDóCé½$b¥E4y*-¢ 齕5/¨#öÇ#z[ƒK“hIf´I´xEž&Q•?Ñâ9 =¢ÅŽP[D‹£>é-²hQÉöã-ÆÑôˆž{D]{-=¢ÕëôˆV­¤GÔ¥ˆŽGÔ=µŽG´Z9Nhõýi¨ «èãÐPzDŸÔí}ü¨¦Gôù¿»;·]]v$+ß÷SÌË*¤žò!}º‰ D#„v¿B­Òn( ÁóãpŒ1Â9ת]kURQûjO/ÿÎŒ<8ýň»!¢Ý5 ­œµ"ÊJ<"Êx­eY“euÔee‘}P#IªàCŸ“BDÄ0Eˆ¨Üƒ e=’mŠFeˆ(4"Ú/1¢ÜÔÁ:bàÙÚöã¢À“ÙóqA Mö@3@àT!оë•)hÏA¹CC'÷²Î.ÍxfZoNTNf­ #U†hó rþö+‡]Bà™—èhs«2!ðdhÜBà™ˆä \Ê—®9ZÆBWÖçj!ôHñ®, ¸XÁ’¸°ïªÐ \ØoI¸X›Qh‡ökL\|Å„€‹Û^ + íWΨD@“òýŠ—ÒT‰€6BE€Šé'ÚEáÀ€«)ê ¸ýHT̼ÐNç(hÛš9û­œ€Àõà ’m'6ï´³ñ{GÜ] ­’ CŠ×@="2 5 ì h?ʯÐг1±c! ÐJH:—ÞR ±c (pw•¤@;'(R U½j¯ÐÐ%~'Z‹c)p‰ÎI‹ÕñDk~¡@«üEh%ב \,‘(0%.Þ‰VÖThÿîO!p)V*à ˜Q'\K'ðüÊÇ.n­"0±Ž›TÀĬ'©€)‰Ö &%ÀRLOEÀkw­h=ß¡Ö.0Š€‰ß‰€‰[)ILü*Q´¡"`R>E@;Tºh±yEÀ¤laŠ€©(u"`âþERm1þE"‰€¶]º!ðh€I©·ÔSÕ¤žÛá Z­íy¥ žõ—˜f$ºÈM%&1<@ð\ %ñßîòpwè=¾÷›/)·ßÄç‰Ñù×UzmQºI-Wéµ Òƒ%Ãþ%þzãm÷8h¹ÇÙsKÿ,²Ýã í‡-¯qf‰Qfù:Æ,ïæ—Òv™Rr{¶µ×ðÏ+%—ÛW’ÛëÓ®$÷Ôö¯­$÷åÞœÚ?§j}}óÀ泘æ¿â·Q&Ž¿¿ëÄqŒ«ÆyõÂXQ(ŽcÝ•â8ÖÕ c½zq,•ŠÓXW­8½8ÖÝ‹¯¤ŠÅq¬»Zœ^åè…±þœšr [?ý-Õ”û­©ò—o&¾ïMŽ¿|û¬~™,¿ó¼~3Æ×”ËælÙË€WU¹(÷½¢rW͹?U”\N„Ÿ»œœ•Mû§ïÕxû¦œœý;kȵëÿþµÅäúwŠÉý᯾„Ü~f-Æû¸†m©õšq+»åi,p黥µ«¶Àþ»{î9¶€ß ‚º·˜œ*ôiY-îÚ˜h@î•ZËò×kÿÝ’ƒ±3qq·X0ùUI`·À†¸ï˜0!÷ì–ö ÅóxvK÷zvNÆûo+àæ--Ÿã¥_Ø@¥f•aÃDؾµ,¶·¼Zã«vÞn±ð6÷¾'ô©ÇÁØ)í–mÃô>}` ì–îuhS^5#Ì‚ʲ[Öñ-vÖåÙ“LòµC¼­ÅÏxv ΟÒÀn±5ß?fù‘Ÿ}þn‘¯mwË>¯àZünÙçÚx&ž^?×»ex1wÝì¿'K`T“Z>¢8Á^An ¼'mX‹‡—PíÙ-VÈÛ[ú¸ª`°[Ü‚Áúζ6mhqåf·l Ü&ç±Ý²-p›\Cß-–‹ï-g8½Æ+¬ûoØà#œ-NÏ¿¼gƒoI>ÂÉúˆj»¥xÊ9K±íû4|DÅÃÝ‚óϺV}Ÿ?äkŸ?J`‹; ¸}zÆyFìnY~¾®Mæ4d¯ÊŽG»Å¾ªµ¸,ÿÄÃÛ’_–± på¨àQÏùš†QîPô€ P€¿»ÅbÝ>¢Ãn±ïƒGdìõ¹[ðЫý‰NÉÿ® /DÒá.NXÀ`ÑÝ"&žð¹Mð–yg> FyìÁniŒâü°ùFábMXPz°[`Ýç»Å*$y µlšxHVòx¼Š­ìùæ»[,™È[0u.˜P!³ì–§}^±€»a[àÅxW¯Ÿíý£QÈ«µ,´Ç‡Á{°doÝ‚ •³ò^L´¸‡8ۧŃ ýM¶‰Fy g¶iF¹ó*ÛÔsLÀ¿ëü]uËöò €ƒ»<³=ŸŸØÊ*á8¦Ò]e¶ëûéáîc´–õé¢%¾;ö³O61ƒíÿÐÃ甜‹›”íƒìÁŽî Þ-ûìQêÂ猼W[n>À9ËwïàáHvÜÌ–‰_™ ~Zº¬‹ðlæ’&,B—’ âÅ-0Àïýwu•ÖÌý÷>ý;zs·ìÓwƒÜç¼[z…AžcW¥|z ÷&îœÿÕ¢óÇä»[*—z9}5ÓDø&oRÍg d‘¢8V-E5ÜÓ¿[`CgØÐ8gû£Å?Šû¾E ]ÆYÙ0¾~Èuf¥ &ð©…&4ïÙ¶pCÄqC‹,ø‘ à¬l;¸y â1<à |î¿gFíÏ:Ø-ËrƒËÛ­Á²l»EçÏg^Åaÿh¥¸›÷¬à›÷|#ç›÷2>Õä=—nÞË_yKµà=²Ið^ù†÷\b½yëZòÞà·N¼78¥‹÷rZ‚÷ȇ´7´œsÚ|ÁD{™A{A¬E°¥ÊÒio bзè Ú£v´Ç­Û‚ö‚…«lX Ï °‚®¨øÇe8qopIÚ›ˆÖ Ú›îœØ›8ö&BDö¦žÂ >ö.àìÜaÏZ: Ai¼ùöTìO°×§k¶b=kÀ³Ö³–FsÖëT­ÄzÖÒA2P¯Sê]]œôú2€ô:b2zæÀ5h:ÿ—°g-À ÀÞÙÖœõ¬a½XO ÅzmÅzæc*õ¬Åç+²^Ÿ"SÀÞå‡í¯ÆYîCàdÚ»¼ ½ÎàD{wg%ky^¸g-x@€{ֲЮذ–:÷nîu–Êî]}îõ%‚î]ž‘)®Í” œEÀ{w‹ó^_zÖÀ{;Š÷úâs3e,S&àkNÞ;?¯–ìWÀûÃ{ö·÷È{ÖBÀrÞÓ† â=sÜàÁïY8K|Ö€¯skǾÄoµ€¬|IKàKC à»ZPÕ’DÞKH ÞKH2 Þ“ßHÌ—èÔóaçµ@¾¤5>‘™§| 6ä“#IÈ—>q¤ ðøä‹ñ%~CD| Ñ A|)Oçß 2€‹O"“~ù¸Ñs0_’ùb/úX|ЗVKèK|}ÜÍ- ›&ôe|Ä|™ß1ß5Œ øÊ|YxLæËÂp2 óåÏz#_‡ù² È—µˆ%ò¡[ _Öª–È—éäòe­O«,àLäËÈÎ ä“SPÌÇ’;Á|r‚ù2ŸÄGˆ-eÁƒ×€ÈVù2ý©B¾¬ç“È—¨È—õœ7™@˜$òe~Ù„|YO5‘;/ù²D>éäËzHšl˜À”D¾,<"òe½ D>f÷ò… ]6ðm òe½?D¾B¯èÑ'ó=„>†ÏôŠ7‚>f ôÄãô*(‚>Ö¤è+üŽ ú B[ƒú ×^¢¾¢‡Ô±¯eˆ}rÅ ûäÒö•À5ÙÀyŒØWô$û ×}Â>fíöÉ?+ì+(ÝÜWÒ6`=î+TUÄ}…Ê‘¸ONiqŸœ³¿‚2[~E.‚_AdÔOÔ„ûgê~æ5ÄšèÎÁVÉ·âã ô;é¬h MÐov‰Ã@?KÈ$R:úM–BúYJ)uÐφ€Gè§ÍŒ„~fÀz±Ÿ¶RûÅ»Bö³ÓUË¢IxŠÀ~JãûÍ)_?ØÏúà©9ðoáo26_ð§}¦ö<àÐvÂó¥÷Y=]¬*Â+ø³·ð§ý´6L´8üqÓ2±Ÿ6üû)3Sð7‡ô+ÀŸý¦¿àÏNob§©áo2"]ðgÇ‚~ø›#47™@ ü;õ‚¿c8~åð7™,ø›TB³S ûYî?yQ&À~V;Ã8û]' öÓ–jb¿˜ÎÉ~vï02ØÏî&°Ÿý*ƒÚœ›f(K‡ýTAì7™÷!ö³KŒGìgçrûM©)d?eðŠýTOAìg×b½ØïztÀ~q‘‡L $ ô»F)Oýf¿@/áVÑïô³>0sʪ‚@¿ë‰úrèãègßk"™£_˜ò›’½H~³2.ù¥÷ÙañV‚û® Üw=Wà>»,-8}Ékä¾9‚+—C>'ü‰Âo7ëå>¿ÀæÁ÷yÁ´Ÿ€=ºíö/ Ä€Ì¥ô°Gà* j ë<`O}{˜!.ؚؓX°쩇`ë²€=:òö*´‡‰åÂ=†Œî=¯¸Në=%hO‡’ j úÍÀÉauÚ».p/ Ú»¬~‚VÙç HÐÞ5 ¢"›ÖˆŒëT|Šâ:›ÖŒë¼úÀ‚íÝ£"&R!7ŠëDª`„urwÏëŒ;Òâü €2@âÂ"¯„u’3¬Sa9 ël’”MÀMjaã8¨2²³IufdgÜFvÆÙb— 4œ‘ñ 1²3n.C;ãâ0¶3î‹ÇvÆÙ ÙÀ×iȆô`lg“âÊàÎkw†ß†ÁU€ÏàΊ}"¸³ }ÜYõä0¸³"¸³*nÛƒ;«DWwVä×GtgE·ˆî¬Òß§B#ÉËŒî|"Ñ¢ÓÝÉÝï|ÍðÎçS±œ‰³7ƒM¡”‰¼=¸óÑ#Ëà·$ î|¤i2¸óÑsÃàN*ºó‘7„ÑÀ›bß!Ä>ÖÁ ±ïnÊ\ti}MkV×úõA‰}W Ä>}$öÉÙ(±/¢õ(ö5ÉTûôÎKík¤9Š}z%ö5$”†Ø§7j_c†Ô¾¦eÕ¾k ¨}J½Ô¾&Ÿs–„ª, ÜJíkAŸËštª}Cí‹`=ª}O#ľˆŸ+Ø|êž®¥2ž®Õ>ž.÷<Õ¾Žº&¡öÅR”j_DêQíë"uª}W Ô¾®KLµ¯ë¶TØÐßj_×§ÚÇB›¡öuz%÷u¤‚‡ÜÇmBî|Û%÷EÈå¾!ƦÜ7¨,Rí‹e#Õ¾!/†«}ƒÓ§ä>eîHîS“ä¾Á+Aµo ÷:Ô¾¡`Cª}CÐ%*%±o0Abw™±/üûä邨 Š}“éû¦¤4Š}3bK!”M¹G(ö)ÕHbŸb˜$öM~´$öMŠSì»ú@(SH’ľ©?û¦”[Š}“aÔú¦&¬.ÈÔúÂiE­o ©©õÍÏñ½ÝÀPú&#õ¥ôME Àè*}S*™+}S“;•>ù¥ôMQí 씸ÿú–| úV€„¾©§„BßdÄŠ„¾E¶‘зä;š* I¥c‘!¡oé{E¡oéîSè»ZdC (ô)!LBß„`òõÞî ϲ¾¤QkíAž ò ÏÈ¢cçT£<§÷ŒòŒL6Fy†Ç˜Qž7Å(Ï¥¬9Â_ þRD‚þ’2HŠfü%º¢YpJøËZáþ²Ö‹„?©ü‚¿È_"ü…ÍþŠÖ¦„¿Üú+ HÊõ!üU>u€¿*•ÎáO)1‚¿E ®tÁ*²ûU Zd¿'d<°Ó#š%ü=º•„¿U¿þÊ`d¿GBÙZ0Ù¯~Ã~dƒ`?*ŠDö þ¨ þ˜x'öcªÙ¯KÙ öczÙOë±_W$›³_—²Göë ò#ü™ÿ‹-‹Ë‡ö†¿B<ZPþº¢J #D:€êéû ìì7øˆýÆ'Þ'¿‘–‰Ñì˜óE~1gü†Ä5’ßÔ›Mò»ú<œì "è˜äq½$¿)Ížä7'"ò EËÉO’Á/Òu ~úd üb’#øMáÁoÒã(ð[\süVä„êLX  ù­€WpÓÒSâ觯Ðo)‚è·ULò[Š&ù-Š)"?nrä·ÄÉ$¿%N¦Ö—ý±Â„·Ô—ÄÔúCÓ¡õ%ÃPëc=¶Ðúó«(õ%¦¡PéK’I¨ô¥O†kB'K\þPçK’ä¨óq?¨Ðù’Ö©YçO8È8Éxc€» ó%ILÔù²"¡¨óe9È©óET"u¾¬Ø(ê|Y±[Ôù²€:_V u¾, Œ:_Ö:Ðu¾xV}T:ø)ôe¥-QèË_)ôqgöú²h¢ÈG‘‹°•,ó^SçË‘J/‹/¨ó•جºB¥Ê„õJë›QG™/¢Ü¨ó†$Sæ‹€5Ê|…Î-É|™Á÷’ù"Ü‹2_ÛPæË¢(ê|E"”ë|E„üÈgÊ|ë¥ó¾”ù"ÂŽ2_QÜ2e¾ˆæk2A±˜2DL™¯è™ ÌWPi6d¾"âp™¯2/A2_Ñ‚¾… x·©óUu¾ël óů¨ó)I:_Q¤r— ƒq–°¡B#«¨o:_•dì:_Uj,u¾ ¯J£ÎW…)Ôù*xÊ|Ñ…2_…P櫚(óU”€ ™›•…Χüpé|UŽ×ùª`Ôùï#/nÌ ãâyö4çA(«š^¨óUÍïÔù¸/qè|•O6u¾G΀);:]¹RîÆ+gNöö™Ì•n•¾˜+…p‰yF¸2#?R@ìõfÞŠ \˜Q ëq”.\¬ð,PüA=Aáx ¾ ð<÷úaª~5O°ŒÅx c™‰ñ$Ã÷pt‹òúÍÂxh5eVÆ“¨åÉp”‚•ËlîÅ2;½¢ðîyEÝ#·§w:!˜î9rÐOê«í}—éT¤á+±F’½Ê>)xEöQV¡[(º¨t*Â3U6^©èüUV£OðRV¿}ŠûOù÷·jÂû–8,Pl{±*«Ð‰ü¨)5êD)?pV¹ ¬¦B—""­jrÌÁådºWÎ*<Ã5µ„8öw rÈkêîûÉü{Lø«@Å5Í÷ NÔä&„[¬f7ÁúÀ¨œz{Ü1V÷Ü£~T <#ð•ÔüdøvP3§f˜Éª»eÁe9pŸhñ·£æá^†ÌŸÌÁ)ö@MèJQ½–Ô€q(ˆQ ,ÀÞ:»¡T4 ˜@-µˆâÐòdp)jLÕ½ —âbí©`Š0àZ`ÁÃàŒZ°M´ÏZ¦§–Õ?_¬Z÷½™úÓZ÷Õ<)þ¨Vðgk…Sy­OF‹»h6‚%äãšwËB>Þ¸Z;w ëfpoajúoxí*6¤C¾Y}R€Á-ºÏäA6bêS{“¿ª1Á¼R Àt_Xpõi -p;Õ§OD C}«Ï}†Ã¨>³3&}aØ€ [!Ò®õj_dæÛnë{ÄG{²@mµ |ŽÜÚžÌHgŸN÷%Iˆt†ël·0}@¿êÌ€¨h_²ê‰q>-ø¶TK8ó,ø`kO“ uí0a1–¼öÂùlx}ðQ«ûÉ`J„íko ¹7™Û- yp{×Þ™‚µÃ„©¡OwÉ-=Ö}1{$u¤EøJÔ‘=Çêeµï²guðB ÙÀç|À¥þÕÑÎRȤ¸/£-XÅgbô³ZÜ}·ŒñN3¬C6`ÙUlPºUµ Õæ_Ãjªù­‚3²ÎâgÃçÚ>Ì~«ÔãÉH*âõ›nƒ¶Ê²–cƒùº`çì-œ0ç8Ë!S;1gÍy–C¦™`>·=ÕÆi§».Ù€õg]nÃbŒj[ªyOgÙ¦q¦$áE´sö²ø›vVtKµ,v‹o*•?ydXß5ZP“§®ÙaV¤ÕöSë§Ùm¨æ6áÙzlKµéW¿?O‚ …sÛ“` žôÀ€Š¿›gSr»ZkñtJìò³ú„E(Øò$À½ÃMGp ýÊOZg1´*¯Õcªu?9ÿÈ>¶¡Ú¸6Û-ÅóA uÙÇ6T[~i:Æyü„¡kƒû¢¬±¯+)Øwµû¬e‚òšlÿ:“û®‘~w˜ ¿e­ ~ÖR_àwú ÅÁïn™ƒVø]#OÙ€Ù›àwð³– \tð»Fø> ¸†3F‡0 8¬cÓÝâØtÈÁ/jéüºM ~w‹LPK-lÉ/ð³–DsòëZ9ùÝ£thÑC6¨E6¸6Gò‹aH~]‘±$¿†è×é&}µ€äütl‚ß}¤¾ÞÇqð‹Ò„¿{ذ£ä°çÔ§ ì»F÷.èãÜwMÐå€}W—1ßûîãpc þÔw]âüË û¢B#±ïØw·8öÝã8öÝ}d¾˜Ž}öwæÍñþwǾSXåØ×•Mî»ûÈ.tª, º€û®cüîqü¢2%ÁïîãàwŸm`õàw ÀïîSªlŒ9ø]Çy‚þ¿{‡¦»OŸ_løÝçãàwCÞàw Àï:Àïàg-X¶ü®³øÝÇ 8NØÀ>ƒµSù$üîc­öŪC~W6@¿.6=äwäw ò»y¸ÝBH~÷¯+¨"’äwÿÊÉïn x¬0#ƒü®> ¿kœC~—U ¿{”'±j~cà 8ngU^b_lÄBò‹K ð»µÂ ³Âœ2ÈïîSË»ÇÃ2ª·±,ˆ‡ä×U¥‚è×U‚èw÷™¬£ªq먺°@ò‹.$¿¸$¿»M ->ù>’_œ ÉïŒá u`qH~W—8}Ç¡)º€û®“÷]'î»[œû¢ä¯s_\•¬óG(0±ït:öuUÌ öÝ}ûîq‚öEAbb_ ê;£àGN}W§¾»‹aßuËŠ à©ûÎU:öÝ£8ö]W Øwõa@CŒSeúÈ?ŸŸ©ôFò³,ÉMm"¿³É1€¬¾ÒÔH~'òüE~Ö™äg$¿SÅã8ú‹ !˜ Ô¦"ùYVÄüÀ.Áo0üW‚ß`v¿ÁŠbPüT]Šßõ‹Î|£B©±+cª¾?9¥ø©¤¿ÉHX)~S%%¿IñF’ßdñi~3”¸ÇÏW†šßlSóS¥i~“AzÒüÂj~“nui~ªœMô³kÈV@?kÁ}úMeÜýsMò›ÚÉÉÏ©BÐK”’ÀÉ@?¤p‰~!7ý&·®ú]¿úÙÉT ›£ßuÂK&ðèK’ürD¿É=»…~÷Ȇ~vì ìtô³ )pi–L`Cfô$˜QÍŽxŸµ¬¯¢Ý¡ùÑišÝœ¡ùudgûWÍ5º.ÍNKóù„ä•U’Ÿ|¥—äG]€š_’vDÍ/éÑ£,@V–$?Õ!†æ§›"ÍO7Rš_x–©ùéÐE¨Ka©’š_¢n-Í/1KDš_Üj~q‰‹LÐÈ_LpÍ/n5¿¸šÔüTøY¢_’RHÑ/kÕWÜ E¿o©úÅ%§ê—è—ê§Ø ©~º &À‡ ÑO¹ýÃx%úÅ¥èÇ·IšŸr0¤ùÅ=ytþ<7j~Ê‘æÏ+5¿¸2ÔüôØ?°çÒdß*~W ä²$¿«Š_HêTüân7Y€«ÛdO—Š_¢BÁï:¿8?üâéía^P„Zó?]) ~ñpRðKtÀJð #»,àLÁ/n.¿xU(øÉn×ûâ ¡Þsé pè! øF‚ú®‡‘z_Ü'PßÝz_\á!xµF˜€gÔwzŸî÷¾ëO¨}qª}qv3,ÀL4eÁH`G¦k¦óÝgçÌg-Ï ú®÷iÉöY²€vú®ö@ßuÆ€¾{\‡¾ëAôÝ£È>$€¾¸\`>&ãdVÓ åXè à }g`ÛWúâuqè‹©“Ð7ŠÐwêÔ¯!©/¾ƒÄ¾ûìB“ê^âBˆ¿÷]ç îÓ¥!öÅûíØwp¾L rÔyè®u4-p_ÜrŸ&PbŸ­`Ê‹ûâv“ûâ!&ø]wàÉ/î·“ßu­ŠL˜oò›ZO‘ü΂£L®„@$$¿ëŒA~×5¯²ã€ü,b¯yhùo×zíùF„A{£%@{¿â¢½F•h¯1~’°×÷$ØSqÁ^c¹HÁÞÕg1åºPJK¬†cöTÁG°wµÔúþûyU¡ìiÇ>ÁžŠ~ ö®>ƒ)ã…ˆ(Ô' @(éPp$Êz öbÂ^“¶Jػơ ü;lX¥³Ø–Æí,¶¥q †©%Ô`ÑTõ™,üª>‹ESŒ|PÏ~¨ïߘԻÌêÙ¯¨Õ9(Ý¿rÖ³–É~å#Ö;ã %l ž7û«ÀzW Xï:Ö½ûïRßËÂÞeÃø«Æ•HÀÞݧk%”_Áçüüzöâƒõ¢¨wÝ ÞÐþ+Îz×µìEEÂÞÝ(Ø“k9 …}~m,ÿû Ø»Nx±úƒ–Là¡–L@ñh²Þ¹|h©åý›‡+!š Ö» ë]ÀºL@G¥ëRöî3^\ ¥õ‚½èCØ‹4a/.ŽÃÞý›'¿ÿnLÖYo؋Lj°wÿ*,@Ì` xdG¥°’°w °;löNå&opس.P¥2L@aï¿qR²Aê öNýÐWl§õÇa/ª…’ö® \Â\ ÐÞeT)éW5¿^)ÂÞ=ŒÁÞuÍ‹LÀÓHØ»‡,œŠ @„½»ÏbéW´ö.3k˜€.² yNêWy»Â;MȸÃ;q’ï¼2ö”Õ'Ùá‹ËuFw.åÕûRDûoº°/³ä°/Gš°OõNÄ}…Ê ±O5G€}….)`_e´±°O a_¥COØ÷Hª!ö=ð)ìKŒFö «„L<b_—´Eì뼞¤¾N‡¨¯³X²¨¯GTfg¡­ç õ)§CÔ7èÄõH”ćO¶¨Ou&E}‘ÌFêÓ†¯¢>mÞ*ê[¡×5¯7…9IØ·Úsi|(ji|õ×n–KãÃ3üÀ’øTuH_–zL‰/Kyƒ@–YþP Ÿ¶äƒÂ—9«Jáã–ZøŠ‚‹©ð©~‹$¾¢„J|Eb¾¢å¾ÂÙZ _a¾ $¾J•ÄWYcW_ í°£V \”øª¼¾”ø®˜YhÔøFúPâ{˜bD…ïaíY)|Û´Já{Bœƒ±ð£Ä×båÄñÚ¸Ä×”ÞH‰¯}¾¡oªº¼¾H*£Ä×XíJŸªìKâ‹„1J|M‚%¾ÆÐlI|…v$ñuE˹Äוä_gZª$¾®¤J|ý‰¯+f•ß`‰eI|øä1íƒ"yï£qG gçŽ@x‘%ïiè{ƒÙÐ÷F¤Þ%n§Ã+@}O‘ÝÒ÷!.OáMø´µÐ•ÔÇ—‰_„WSà›J‘£À§Êø´m¾© YJ|ŠÞÄ7™Z ‰/bÎ(ñ©j¡$¾¥U?%¾°Šßä>šÒø´)˜4¾©`Š|ÚO"Ÿª³Bä[ŒI¹²úøÔGVc "­©l‘ևЮ+­0¥òEºU>Ö”ȧ}¥¯¬>¤ÁK仲æ”ÕG9ÙU¾ÅêÊRù´  T¾¥=²ú¤Î)#®½c;§öϾ²ú„”Pù´Èº²úCCò[’ ¤òqëx’Ÿ¥ "å‘I}äoߊø Ê|ƒµåI~–V×^ä·´»³d>-I$óíÛ€\oÊ|Ú;þNêíZ2¿¢Ì7"COY} ÁDF'Kª|K_,ª|Ú¼ýJêCÔ™T¾x¡©ò-N™o_ax\"«¯P6SVr{%ó-®˜”Õ—ß±V”ÝãTEr&$ÀÁeõ©ñ•ÖÇ#«/ÅaÕ—èÄWVŸò•Õ—áÆSRߥ´!©/3…êJêã3©á‰TùôYPRŸ"—”Ô—ø”Kå[‡Hê»ôÃ0â›L(Ä<äÄiCå+«YrÌêËš ™o‰Š=¯/‡ ¨ÄDšôªŽ†‘®>é]i #]ÕÑÎHwm4Ž}8ҫΞù«6šôªŸÆ7%ú`¤?«~Ú3Îúûo©|ÚoLD¿|3­|oêùå›ôëTôícúí?Q>­=ö}—Oû‰úh?^Íj²=öÏÿŠªgÏ)Fó×^õìß©zö‡¿h­³Í®¨kfÿ÷_¿ÓÆZgµÿ‰Zg}¶Ì jb Þz$«a…¾_¦Ãõ[˜zŒJϪ̞FÐÿ³fO£üñ³³§‘z¼_Z& A†|Ö`¶×kzºÍbpÁþÒT7ƒ£¥äþµÌsn)¿Š—µä6XE±ŒE¥¿\åm©j¶é {âµÏÐFXº×|MÔRoðEANni<*슷Àp¾âW« t„³@ËÉ—cÚ3¬åìUøÙØ-%}ô$ñþÛ–cÖ‚%RËÇsc˜ ØfA·[Úѧu´`é¿!Æ&ãX÷3µl®ßÝ ="[6ØÇ^ÿ2pl¿òfí¶?m+Ç„Í Äò¶§¤Ó2¨ìóNõ§2Ñb¯ìïI‡àæ[Qží2z<¶¢ì½SÍnÅM0(ø•›`¾9˜YL™ÿ‰u@Z±¢Á6WŒku0>FV‰ôV“ù׬Î3žØ±fµÀw¶[Ì‚±-€©ís8-¸ýþíß<×ãXÛ¢=ö$a6ÛÆªAÛ´¿m­Ñ ߪ[pJ7øõ¬æ©Üã,z\[µâFâPÅ÷laßc;?8PÚf³ª:v‹}0lƒ(íqzaáˆf‚Áˆ½§ö·`±Kº—]æ`k¢*H{ºù×fiºTþ}ŸU{Xîo0kæDÒžcÀl±m­Ùþ1{F݃¶_mÐŒmÄw‹yج¤4À´5»´+U̶f݇UOF4^3_÷ÙÔÃ6[“©xàþÓœS36•mgf؇Ñn{íøŽ?Îü¸0¨rÙÃ*Œ¢tŸÊÒÉõc€¡=ˆv‹9§Ì1—[ëÅœSk¿_Ð"š½5óôK«õÇlDZ€YÏfÈU&uØ=Õ™ V#/`·ýk>VÓ~:{^5ß”9 @É{^5ÿÚ<ýúé”Qªe·çQó¯þcÄÝb&ä”l©ä-0aQÿÙs­9§Ö¾€œiÆcþµ=×™fà-Íük¶‰Ï'^ܱŸÛ&çÓA°cƒíŠ£#¹ #ÑK׆UܱqÍ;uZƒÎ¸˜"f6ÿšíÒ¤>ÙükÙä\ÐY汪ØÌpŽ g³ /ÃÒæÓO‹õÄ0íT1¶îøìexËxðô°ºvg» ¿æÔÅA,0µÏÏnåtZLƒihYǦ}Nîpkö8˜Mæ:DK~§µ?2n‚òDZ`‚íÒᆯþxË££Sš9-½™ûÃl›'éüiÌÿa;“|úW®ÛW¹¸•>—ï—ÃM° Ú-n‚yħ·X\û¿±=ÕqŒ²’·øÕÓýF™“Ë[Z;FU ‚ó·’¢Õ[pþúº÷4‹[ÄI}ÿï‡mqñéÓk·¯²™T¸#m·¯²™´¬¶&Z–ß•ÇÿÄÙ[A"·9ùY‹9ÆNÃcË ÛÃþÒÚ2Èö ù,µÛ“aÛW|r`«lj}*Þ”žýüíW‡òóŸ¸g}’?ÎÆ)þžtû gïáåkº} ,ô†bë8Û æÓÇ,~úçLülKœÿÄqŽ³àŒ‚.ý9™Ú€qMr¶CýÈêL~ØŸ8;sYCå‘ê9ÿ‡;ôjõšìò¹3¹ÛÇøÜŸÌAíc\ü!ô×sÏÂã”fÅ^Ÿ~,Ê|¶{ÅùÛÛŽ#Ãsüìª)ävt[{Ë<…Éóà;Ûm±cÒ¾šþDÙ>bËÇq×kŽ VéòÁßnƒmUî÷Þ>ÆÙûLü¦ŽcU³ˆDo±WÞ¯8ûÓšß§ýÕ¯ú)“žm+)¿l°"a8–Û`ò®Ží%fVµSVÛZl/±é÷ÅçÒn{‰áN¹®×÷7ùãlÈ«l°è?vƒ #aÍÛ÷’á´œbØÞÒÚ±jp·¡ý…{ŽU–$àvžÜ¬Oåôp”a³a_S·¼¹ %›Ïö´ØfbfÕ²"¾h9N‘ëm±ÍÄŽU{ê@Ÿb=ú©´}þ®ÃïŒeÙz m°ÚšÞl…èg³;ónº Ý"2¬†wáTÙÍ­ùq¶"Êø•»hŽ¿×[†Ûpìlhql8'ÿ,uFèûølØ›÷è.x¯|å=úyƒ÷2}ñôuñÞPòyopé&ÞJûïEú?yÏ‹–Ã{'tçÅ{ûÞ%àBèΆ¼g÷·ƒ#|ÚE‹Àg…±Á# ¾¡j‡$>Û–éÁ8“Ûns} â³Å XÈqTD>‹lñï²ßÉò÷ùÄw c…—+ %CÁñ0 ,%øNÑ[\'¾$@”m.7ùŽòI,´ ðEÜ* Ÿq,Ü@> o‚QF|¶‰P':ñ%©J$¾ôà»EàKÚO•Àg4·0ìÁ%£ØÎ³;Äw0– x¯JòØ>7ñ×b¿lßþ:1œÄ·çæ^âÛs=ÅpŸõ /;ñí˜uì@|{¦äö€ >ëó&¾=1ÈÄg|Œ Ÿ‰Ådh'>›d .ƒø,° Úˆ¯ÛþÍ|}j·À|6 #𙼠í Ä×m]CH<ÄgÐMpâ3 Zã:²fíZ䳨0„5ù Íc‡ùŒ1ª æ;hŽ—Î™oÔ‡; æ5S,=ÐwÐìãÐ7ÚD˜oØÁãëÌ7 Pq'ùFìeæ3zÆsæÈ7ì3–ÆKã|䇗Æ\oùËtŒsÏB×8òÍ}}' ϱծÝĸ‡—lSF{pišË”?räËï—Ÿ5¬ñÍãºa‹Y`°ƒôwßÁŸuŸmöˆÀdßl™Ñ >ÛÈù:‡øæ¶ƒ÷щo.E’€øl[I¾N|眄øVêôb9ð­4äcqà[YÁG>;f>Ãw¾¦|ûÜ4Ç9ð­G¿øÖ£ÃølïGªŸí‰­¬@|ëzµøöQôü:ñY J4ƒølIÞL'>ÛC’ øŽÂ[çÀ·,¦&,˜0i+àKFI¿Š÷Öસ—þLÞK5}¾qÏÜà„;ǽ}Åýåî¥Þí ¬hÏb±Ð‡´7PìX´7è7ð]Œà³ÀÐ'€oÏÿý¾4ÍKà3HIJŸÀg[i €ïÄMýÈwé ò=$0_:+{ ˜Ï–Òø˜¯<4\Ì'R!óåàÏcÂäÉùùšÈ÷<\ù]2Ÿj¼¡ï¬z  ï0ůóuÙHè³ 7€ùæò%ò©¶˜oˆ¹ù°˜>ÀWö;­¿,ÙÙþ ø,pÒï)ïTTö¾òpÏhŸaœ>Û—¬¼o²$'¯t>ñà= |\ 'ç=Ûóá½R¯x¯4¾Xä=k!5:+Ó/ÐÇyoHà=ìºAس˜FXØ+‡—~½XÏÄ opL²}¸3Áî ^1ø€9êÙ.K¸âõ,ï PÏöî®õÊ©4î-ŽIUK:¢^Ýßx¼Ó@½j`>ŽzuÑ´8êÕ"×QÏB“v“lçp<@=»6p õªÍèc¨W €qŽzõ™ú l°p?›N '< ž=¦€è¨g;žìõìXÀ^êú…ÞD½úpVW4€EË^Iî?TÞLŸÏE|¶>A2opN ñÅž,$¾™Btâ³ÀOäÚ€ø,˜w¾ˆïD¾¾ØÄ·¤>ø,Z K '¾nK|Ãñ-ízâ;r{Lk/o²Ú5yϰ=÷V¨lÀ= Ó÷¬˜9qTªu÷,Fõ{K;ÙKáKÌ£vÞ³$Þ[Š &ï™à …/©† yo ‰lའ]ÀwJ|)ôH|éa6J|I{Qâ³FµøloyÜH|–kó\_n^|ö  ør°€øŠ6 ñeÈñ1TÀàËSº€/wi› >‹SÈ·Æg‡Bi<ß~£êÄg fx@|{\Þ_nLv!ñYhÅ >[‰“„*Ÿ]?¬|vµ€TÎ{º¸-à=ë‚G¼—•¢ïÀwÙx€ÏÎ ðÙù70£Ÿ}b t:ðr  "o¨ €¯&ÕÒÏØSx€©Ûr¯_½œ|Ýæ¼|62*ià;ãjðÙœÌGѯ? ñY½0N|ûÁò& ¾ýñÑ\ãÄw~…7`w¡éÄw>h8¸ÔmƒoÀ†ŸµŒðٶLj§=Àg=(ñ;ð™×€ÏŸ%vñÅuâ3?âSA|f÷óB>kAd6Ï6aÆ#@>éc@>kA3Ï}¾ºŽ|6Ê‘ÏBÞ9wòÙ輓Ž|ÖBW—#ß(JBò’¥Î;ò=¼Þ"ß({€ùÌ)ÀgÀ™ï¨üýVùN*¦x‡>sIðè}æ¶@þ" od:Ðg#ÙÐgWš‘}öu§ ëÐg÷çÅ|}is0_-.À|æy!;ôõØÞÐgþä}úìá ¯À¡¯Ûú*©S_m×öÙžÚ¨ììë‘Üî;®$ nƒQT°¹ –ùG)ðP“MeÞàw¦Jü,ÐC-ü†¹¶ˆydž1´ÀÏ6ц˜ãÜg P û,ý/·ûFl?ì³Qi¥c߈2Õà>s ªƒ›ÌŸ„ë rÇ>‹ÁÌ ìu1:Øg-ˆoö×VÆÁÍ„Mp´îU{ˆƒûFÑ6íà>{°§"¸oœo–ß8羑UeÜgo>??ká¥qð³*"ÙA~–gÂÀÑoØbŒ£Ÿõá•0ô³·1à‡þìE ã8ýY¢é¢Lwèï¼üÍ¡¿Që ?sˆá±ýY Þ\Ðß,…>ПyÍàzýY¶'4Ç?kÁ÷øwŽò1ü›ûÊ` ü›ið« üö2ƒ{ÿìíîþãæ»ü‘8 ö}n¹Ïraá+îÇ•Nr0 eÐb%öÍl91OMŽôÀþåf@‹gœ ´'òynµ3• 8Ì­ƒWÊÐúÀÑ4'î$'´YðWnCau àùxàïð´t,&€öÁ)TËôÇü €G]G ´>³ãBë3ß*Ð0Ùî/<ú8&‹¹Å±ÍOæ yõx‰X~ä]»ÄªÊY@_~©|zI/æ›ja¥)ÖÅôYrs†<è+JÞ ôqÃD1Ÿ¢ÇÄ|Ò(.æã&\d¾jœ«|Dଃ|‹.h|{†èï˜ÎµøŽù褗Æ7U‰XA…IŠê|xvWT'žCA_Sb@h2˜;•ˆù:S|À|ƒéºb¾©…£:Þ91Ÿ>ŠêL2“Q™9‡ 묊ÐóÙƒH tæ³¥`½5¾ž´#™ïì¤L t`Òæx`>mQLæÛ7ŒÁ¶`¾KI0ŸEMÁ¯æ3‡¿r`ªÚy—Ðg9¡ÔúÕK'ôíw‡{€¾çè܆¦:b„>{?’iÈÔ+óæ }ýõúl}ZôÙÔÝ^Ð7µS1¡Ï,©w`§}êˆ6ì´`5›cßR½ v¦*• öì\Ø·©þÿ¦íO2íAPgµÆ‘Ï–|‚¡ñå$Î>~úÙ[Þ7PÈ75ùùì¥Ã’Èw1opâ;[÷ßœøLNÄ(Ç‚K=Àgi¢Tü—LKš/‰/ÆCáKJئÂgé™X:CáËMª5$>Ó:Ãé_R— ñ¥­„ÄgBöº£:mR„Ÿ}ˆ·àÄg_7šàÄg_IΔN|CîBŸ}¢ Ž|ö‰&ª;ð âQ|¶~å[êÀgHÇNg%[A`œ÷Fë’Y÷L¶¤æH|I{^’÷¦Jû“÷–"C(ñ¥ëÁ{'ކ!œÆ{.ˆBŠsÞ³pLÐø¸íY?Þ§=[Ç¡´?hÏVœâœöLÚäíÍM‘Í{ÖTسE%O Ÿ©¡þ÷á$‹~&Ò:ëY ë¨7í¥ Ø¹¾·_r>¯Žzs¯ 9Å8êM‹ðy:êÍ}k9ù;ê™]ôêÙ¢@ÀxPÏJ@ˆê­# ù²$A¢Ô–X@½µÙ®O žÅts=ë¨gK’„€1G½ÍœïˆN;o„ õN8s¾Qo†S¬·ö6fÀž%_sUì°w®±öl|0{36tìÍSÀ*Y€6ÁÈYÏÄd‡³žÝtò•³Þ´Aó°Þ}±4Ͱ 1÷þ°ž/܇õìÁ”Ö›–iÃÀÏÃz–ðÎûä¬g5e¸wÖ›]E3ÀzÓjí`Éë¬gb=üù`½y¦ˆ;²Ól‚—¬gúˆ´ëÙÈâ«”Ï]ÂÂã°Þ’ÔÁz&çW2Úa=».â¸ÃzÅô°ž…†ãFõ¬n ¨g+ŸéPþœôNU´8éÙëóEz§@8îX°‚¬œôF0¹“žýfr”CIv]ÈÀNzö+,·@zç™Áså¤g&Ì—Ögõô+·a(Ö¤g¥ xýœôæSé™éÙœ€yãžý†¬ï¤gG¢KÆIï\  ”“Þ²+Dö; ´òõ«Cz–«Àû뤷êÔyæ1ÌNyV•Ò0o-¥“ôN-¸z ô¥“Nþ+8/'ËZÃóö‚f½8/=…"(8Ïô|hŒÀ¼¡QAy“•ÊDy¡ó’ò&² ¨ò €—Ê—ZöÐðŸ©oöÇ€ornT\çR m¿Â:j÷ÌâNK ëÔ"Fa‹+ ßà+佑-‘Å‹^fñÙºëŠê´xH|é˜Å·Bhs lñÉü;ˆ|¨¡òñkH™/IìÜ+™Uª|rNøzÒÆ2>#3Íñ™fÆqœøö÷ƒÓ€çñ™fÌL?Ïã;aIøß§â³0}èa >냌_Qµ7ŸÅÈñØHä‹eˆ¯F€ˆïI[ Zz%ñYâ6–‡öö:’KО-± b_Ò¹ö,l‘){~þ­Û9)µ`'О1å´×»îho‹ñc =“t˜€ç6ôpÖƒöLž¡8who„ ç´·a<4{|> {“‘Ó„½ZG.I“.=R- ñE1%fñ=ü€½}q¢é°×TeÎaïìJˆ¿_Ì+[ÐϾ¾ðumÂ@à[ÚÓÀ7FV$5‚:í›C1é ¨3v’gP§y‰kÔi!ÆýÖøF—cΑoEÀó ê´¹ð¦˜ÎÆT?Oä»BùÌ K²gPçÐòÈ·.¹Î °œv'ò–04Ø‘o^¾G>;J ùz€¢™0¯$BØPåòVóç%Sý Hùº|áD¾òÏæ=R:ò­È·EX§­’—Œ°N[­/ÖY#õ8˜ó»3ßêaEÕcÖi®†~:2ÕuæÛëœÏñí5 #ýø¦M? MŸýÏ=˜Ï‚y`>{Wø+g¦§1pÈgIºíB¾¦H >£ò²ßáÑ|‡vZÄ9C_y$ƒøöåÄ|%éYð–ã$ï€AP¢[`èÂsq ìÙCºxï ®ïUEÕ‘÷lÉU/ÞkZ¦‘÷z’j Þk*â Þ³é€pwxÉÞ$3À={ÿ'FܳÄC†:òñèÈ—².1Ï>QÌ¥sä³ôPá!>ó?uJpÅ*25ÙäÈgS*ÙØ‘ÏrôÉêÄJ-Èg/ž3Ÿ=|ðƒùìS„éÌ71ý*ä³KEqÕ‘o>Ã]Ú?^?ÉjïÓ‘xöLêÅpþÝïí…Êïþ!Êý‡ßÿ½ Í~÷ ÿù#Úþ×ÿŽ®xU82"±uá?þÃßýã¿ù³Æþoÿó÷¶.XsýîÄþÕ¦Ù“Ù<µiΣü{óßÏQþ9~úOïñâT-B>ùÏq ø£?öÆïYõoÙöËïÿÞÀeö®ë±ßlä?m3¼Û|ñµBT€úQf‡ÍœÕîÛ~ ö}û—¿›ö­œE-?žÈ©±LLNë -?)ÌášùŸò}jlù“º³†0>ßgÄ–Ÿòjh¸SøuFh±áþËßý_Ç”endstream endobj 6 0 obj 162607 endobj 4 0 obj <> /Contents 5 0 R >> endobj 3 0 obj << /Type /Pages /Kids [ 4 0 R ] /Count 1 >> endobj 1 0 obj <> endobj 8 0 obj <> endobj 7 0 obj <> endobj 9 0 obj <>stream 2020-10-09T14:33:13-05:00 2020-10-09T14:33:13-05:00 GL2PS 1.3.9, (C) 1999-2015 C. Geuzaine gl2ps_renderer figureOctave endstream endobj 2 0 obj <>endobj xref 0 10 0000000000 65535 f 0000163157 00000 n 0000164670 00000 n 0000163098 00000 n 0000162965 00000 n 0000000266 00000 n 0000162943 00000 n 0000163250 00000 n 0000163221 00000 n 0000163314 00000 n trailer << /Size 10 /Root 1 0 R /Info 2 0 R /ID [] >> startxref 164890 %%EOF blis-0.9.0/docs/graphs/sup/sgemm_ccc_zen2_nt32.png000066400000000000000000005565121422157504600217520ustar00rootroot00000000000000‰PNG  IHDR¬táÂgAMA± üa cHRMz&€„ú€èu0ê`:˜pœºQ<bKGDÿÿÿ ½§“ pHYsNNÆÊ/¥tIMEä !1µ˜¬ïˆ ÊQŽÚË]¥D$-4`]"Dzd••£G¡Ô0`&t´(iƒcîP,°ùÓƒAÊ„w”Ÿ¤ø¼,ÎÄ ÅÐ W4×¥q%OøŠ=PX¯Mî¦Ø:ö,v‹Œž=Ú9ДÑÚ7\ˆîX•­E9²°Ù – £6ò:N¼¹ÉD”Øæ!Œ”ceùª¦Þ•Txé‹n!/¶ß;%åp/ ož"p36GëÊ6l:\T™ö¹c8Êd:¨0†[ç%9—r×>Êáîbâv¡²«a|&PÏGÐÙ© H?Òv]08´ôAÉfcSäÅ=˜< Ÿ'Ov&[Ÿ±Ì˜|ÄÌ1"z þza#MA ’C,[»C¯1ÜU\1<›;!†£á]}”ŽÝô6úô/ÀlÙh ÿäüGŠâö¿!‚¢ù?öôó7H7(êó¿-ü]´XiÖx/ÛcaNvPÏR¹7€IDATxÚìÝ{|w}ïÿ—s³'²Ç $Á¨ ã„dn%´¢F m)¡+•ÃÍ>wÛþ &§:ìžö¶á´ÝmÕ‚Û`×´†–žs¤…´ÐBLwZ.!"M Á" AC‚pn$šXqçfýþ˜ýÎîJ«ûJ«ËûùxÈ’÷2óÙÏ~w>óý|×#"""""""""""""²'5»"""""""""""""²ò)ñ(""""""""""""" ¦Ä£ˆˆˆˆˆˆˆˆˆˆˆˆˆ,˜"""""""""""""²`J<ŠˆˆˆˆˆˆˆˆˆˆˆˆÈ‚)ñ(""""""""""""" ¦Ä£ˆˆˆˆˆˆˆˆˆˆˆˆˆ,˜"""""""""""""²`J<ŠˆˆˆˆˆˆˆˆˆˆˆˆÈ‚)ñ(""""""""""""" ¦Ä£,kaâû~C—çyÞ¢´Õó<Â0lʺ—ó~i†©ÞÏõbÊb¿ÿ§‹ ËùØ[Îm™¹¾§§z¬ïûA0§u« ²t¦{¿Nì4*.@ãcÃr>ö–sÛdujöyFö Ìòtì‹ÌÝBcÁböæÓ–•VBûDBÇþÔæÜ¾q‘ehttt<‘HŒãÀ¸ã8ッƒ ^n©T_¬·=0^*•š²îå¼_D–Úððð¤÷ót1e±ßÿÓņå|ì-綉ÌÇ\ÞÓõâÈððð¸ã8qI$³^·ú"K£Þ±;>>u?`¡qÁܾ±a9{˹m²º,‡óîŒëØ™«FÄ‚Åì#ÌÇJ+¡}" ¡cjsmŸF<ʲ”Éd‚€ÑÑQÆÇDZm›\.×ìf‰È2Åb‘®®®I÷)¦ˆÈlLGR©¶m3>>Îèè(¾ï“ÉdšÝdaúcÖ˜iÙŠ "‹§™}xõ D–Åü×¹‘ÅqJ³°PaR(Ã˲H&“X–@¡P lÛÆu]<Ï#™LÆÏõtÒét¼\ÇqH$ñò,Ë"NÇË™ëãg’ÉdÈf³5í7ížî¾Ù2ÏH&“ض=«ûfsÿtÛ4Û}d^ÓÁÁÁøµ4Û<Ó>‚ÏóH$qGÁu]\×òý“ËåH$X–5§çÎe_[–¿¿ª·±Þûv6ï Ãó<‚ ¨yT¿FÕíŸÍsÍþhĶ/6ûs;özl/ű?Óñ;Ó>ðÂj8O0ñ5\Éߦ£>Âêë#,ô»ÃBú«áØŸO`>ÇþŠñ†!Û·o@±X¤³³3ÞIf˜+[ª?hr¹\|µK†´··Ç,æ¾0 î®.:;;ãZß¹\®æj¶¹>~&¹\ŽT*¿2™Lüüéî›T*ï— hoo—5Ý}³¹¦mší>2·9Žƒïûxž‡eYñ›~º}…BíÛ·Çëêì쬻Ì}&Íå¹³ÑÞÞ?×ó¼š÷ÛTïÛÙìÇj;P5éêêªy_O÷\ aÛ¾ØtìÏíØ_è±½TÇþLÇàLû ™LR*•&}áŸ)¦L|oUÇ…Ù´k.¦Š fÝ‹¦‹ 3=–o\˜iM ¦‹Õ÷7#Ìô>oV,X.q`º}°>€1U1ëª~¬é;̇úó·X}€êû×Ò±¿Rú3탩Ž]˜}?`®qÁ´Û,Û˜olPaþÔ'X9}‚¹ì£Ù»87 >ÁÊ=ö'Rauö «°ÒÏÀêù~0õVga¡ßÒGXéÇþBû0‡c¿ÙµaYWvtttÜuÝñ¯ýëãÀøððp|ŸmÛã®ëŽWêzW×Ïçóã–eGµvóù||Ÿã8ãÉd2þ:Ž—5ŸÇÏO§Ó5m3ÏŸî¾™ NÚ/®ëާÓéiï›é¹³Ý¦Ùî£þþþq`ÜuÝqÛ¶ÇmÛ·,+~½¦Ûæ=‘ÍfkîÆGGGãûGGG'µa¦çÎfMfó~ªÞ_¦füTïÛêÇN·Žjß[—“N§ãù&¦{îtÛ>›v-5û³?özl/å±?Ó18Û}0ñý1SL™..̦]³Ù¥RiÚ¸P¯ÝŠ ÓÅ…éž»ÜãÂtûËëõbÁLqÀì“fÅ‚™Þç͈Ë)L·Ò˜hâûË,§ÞcÔGXZ‹Õ0ûa-û+©0Û}PoÞ‘éú ‰ Õm¬÷8õ–ŽúõïŸJ3ûsÙG3õágÚÓ½OÿéŸþ©i}Óýfõ ¦{þr;ö'R¡þýSY)}„…Æ‚©Þ3-{µŸ'0¯Ùjø~0õêß?••ÒGXèw‡…ôVú±?ß>ÀLÛ^¯]+zÄ£ª›J¥â«RJ¥·Ür ®ëÖ åM$ñßžçaÛ6aÆC¦ÍÿM½ú¹–eÍ8Œu®ŸIõÕ‰C’§»o:ÅbqÒ~1WýLwßLÏëë5Ó>ª¾âhxx˜ááa’ÉdMV¦}P=4Ý 6Ëâ«%ªß³}îlA0i™eMõ¾Ëk9³s5‚çy„a8ëç×Ûöù^¹¹˜tìÏþØ_è±½”Ǿ1Ý18Ÿ}0›˜ÓÇ…™Ú5ÓÅ…êíitlX­qaºýUï}k^×ÙÄêåÃÒÇ‚™ÞçK –[˜i,¤0•鎙¹O >ÂB-f zù°úý•Ö˜ï>˜M?`>qÔGXõ ¦¾¿žf÷ f»fÛ‡ŸÏ¹üà€ú+ýØŸH}„©ï¯g¥ô æ»ìÕzžVo,¨¦>ÂÔ÷׳RúÆB¿;,¤°Rý…÷Sm{½cÅ'K¥ ]·n©TjÆA\‹¶úg¹Ö¢^kÌëP˜Ìfxñ\M RŽãN§I¥Rs~îlTÏ0ÑTïÛFÈd2¬[·Ž\.¥…Xèó‹Žýµ¥QÉÜ™bÊ\âÂ|Ú5]\€Å‹ «5.L·¿¦‹Š+ÓBÞw éT?g*síø«°0ê¬-xŸM׸ãŽ;€ùÅó¼©Ì%6¨°0ê¬N‹q^jß§ê¬ìc"õV§ÅŠ3-{¾}„•ržVo,¨¦>ÂÚÒÈ÷ðj=ö}ÜO·í+:ñh&ÞÌç󌎎288H±XäÞ{ï6x8Žg‰ÍO?étzÚNäj0q¿xž×ñî¾ÙÜß(Ó½ág{0T·ÕÔ®–Ïçãì|½úÍÓ=w6lÛžt•ƒYÎTïÛ…îK³ŒááaJ¥ù|~ÎïçFlûRб?7 =¶—êØ¯·¾F¼gS¦‹ h×tq'6¬æ¸0Ýþ²,kÊv®Õ8 ;ÖWRXH`*æ AõU|3}Q˜nYê#ÌŸús·úÿõÖר÷Ùtý€3Ï<˜_\€ÆÅõF}‚¹[ }‚Fœ˜ØÞ‰ïSõ Vö±?‘ús·úŠs}þlû+ñ<¬îXPM}„¹[ }„zm™Ï{p!}„•xì7⸟˶¯èÄ£™ôÕlœmÛX–U3)°ÙÕ/Šëº“n3Ž®fÉdrÒ~1WMwßLÏm4Çq°m»f2ÓL&ƒmÛ³>&N&kYÖ¤«R̄ѹ\®æKÃlž;“D"Q3ùª¹J¦~ßÎVõkP=¹k†X–á©wõ×TÏ­·ífŸ/Ç«ytìÏÞBí¥<öFƒÕæS¦Š h×tq'6Ì&.LõÜzÛ½œâÂtû+‘HL Öb€…ë+-,¤0ó¾¯~ß‹Å9—eõJ}€¹Y)ý£Ñ}˜¾pÑEÅ·Í5.@ãbƒú £>Áܬ”>A#Î ˜ç&®\zé¥ñmê¬Üc"õæf¥ô æºìÙöVâyóÿÕòý`:ê#ÌÍJé# =þÒGX‰Ç~#ú·}ºcÿ”Y·vJ&“‹E¶oßw$Çá·~ë·8ûì³éììÄuݸf®y¡Ì›&“ÉÄ$‚xøêjeÛ6ù|¾f¿X–E2™Œ3èõî›é¹‹¡¿¿ŸÎÎΚ+&æòúAÀöíÛãçæóùºK$$ R©T|ÃlŸ;3»«« Çq‚ ÀS½ogóE%™LÆË Ã0þ4ÛR(ؾ};¶mÇï{s5ÃtÏ5mö}¿fÛ—ë1¡cöf:vzÿbhÄ18Ñ\bJu\¨~ÌBÛ5]\%6Ì&.L–s\˜nÕûL3±`-ÆXر>Sa1,äx›O`6¯6›¥³³3žÁ²¬š¹ fK}„…Q`nVRÿ§S÷&ž™k\€ÆÄõF}‚¹YI}‚…ž€ÙÅõ Væ±_o»ÕG˜½•ÔGhD,˜ë²gÛGX‰ç Ìö¬–ï3íõfo%õ`áÇßBú+ñØ_hÀ´{¶ÇþºññññƾäKÏdaÍ•LaMôjv mÛ ‚  ¿¿?~žyœÙi˱õb‚ ÎÒOÌFOwßlîo¤ê×g¶ëò<ÎÎNÆÇÇã÷Ål_Û…Ï_NÔG˜›åÞG0–Ûçøj8OP½ÜÕðý`:ê#ÌÍrï#,ôø[NçVbÿ¿Þ2êY‰Ç‰LÆypp0Îwvv’N§5Ë>“ê`5•ù¾QsÙËq½S©>øùÜ¥ØÎå¶/W"û]öR¯w!Çïbšª]Š Ë×Z‹Í|Ÿ4zÝ‹õ9¾˜ –‡µvÜ/ö²—zÝ˵0_Š Ë‡bCc—½×;•fÄûË“â@c—½œ×½”šyq­ìãŦØÐØe/åzú¿çÔ˜lE—ZJõ°_3<Ú m¦©êæV›ï•‹¹ìå¸Þ¥¶Û¹Vöåb񱧯e/Çõ.'Š Ë×Z‹Í|Ÿè=ªX°\¬µã~±—½œ×½(.,Š ]ör\ïr¢cyRhì²—óº—‹ÅÞÚÇ¡ØÐØe/Çõ.%õ&[•#EDDDDDDDDDDDDdiÔ숈ˆˆˆˆˆˆˆˆˆˆˆÈʧģˆˆˆˆˆˆˆˆˆˆˆˆˆ,˜"""""""""""""²`J<ŠˆˆˆˆˆˆˆˆˆˆˆˆÈ‚)ñ(""""""""""""" ¦Ä£ˆˆˆˆˆˆˆˆˆˆˆˆˆ,˜"""""""""""""²`§4»KaïÞ½<øàƒ¼èE/jvS–Ôý÷ßÏùçŸßìf,©‡~˜M›6qÆg4»)Kj®¯õ“O>I³›½äÞøÆ7rá…6»KJÇÄÚ1××úرctttpíµ×6»éKJ}‚µãرc<ù䓜sÎ9ÍnÊ’šëkýðÃóçþç´µµ5»éKêšk®á…^hv3æl¥Ë+µ?²RÛ=ŸøwòÉ'óéOºÙM_RCCCü÷ÿþßWäçÄJj÷òn÷Zý~ð±}Œë×ÒgÔr°RÛ :g8[]]]lÚ´©ÙÍX•úyUm¥Æ¶j+9^ToÃBûk"ñxôèQ~õW•k®¹¦ÙMYR{öìáàÁƒÍnÆ’êíí¥££ƒŽŽŽf7eIÍõµÞ³gO³›ÜÏ<󌎉5Bñof 4»ÙKN}‚µÃ¼Ç{zzšÝ”%5×׺··—£G6»ÙKî…^X‘ÇÄJ=–Wjd¥¶{>ño-~?8zô(o~ó›WäçÄJj÷òn÷Zý~ð /píµ×®¸X¿–>£–ƒ•ÚnÐ9ÃÙÚ´iÓŠŒõÕVêçUµ•Ûª­äx1qbÙ”Zãºë®ã²Ë.ãâ‹/fÏž= Mz\oooü˜}ûö1222ã²·mÛ¶æF6ìܹ³ÙMXr´¶¶6»Knµ¼Ö‹Î>ûìfoâ’Ó1±v¬¦×Z}‚Æ[‹ÇDkkëŠþ²2_«éµžM,˜oŸ`¥Z©¯ïJýŒZ©í^Mño±¿¬T+5¨Ýj÷|)L¦Ï(µ{¶VK,P˜Ùjx­Wjl«¶’ãE#-›Äcoo/|ô£åàÁƒ´´´°{÷îšàÐÛÛK__===£ÔîÙZ-±@q`f«áµ^©±­ÚJŽ´l}}}ìÝ»—;wÒÑÑÁþýû«ÒyèÐ!º»»éîîŽ344Ä¡C‡šÝ|iÅÅ‰Ì DV?õ D DDq@d¥Y6‰Ç‰ÆÆÆjþ?44ÄÈÈHM¶¸µµ•¶¶6>ÜìæŠÈ"PP,‘Hu,PY›Ô'P,Å‘åî”f7À¸þúëéííellŒÖÖVúúúhkkc×®]@4ñ;0i˜êæÍ›ëÖs®öÄOP,YCŽEæËL ûðÃ7»)u-fxøá‡WÅ$Å" ÕÛÛË‘#GhiiivSêZŠ>ÁJŸè[d¡FFFèëëã¶Ûn[¶Ÿ‰ÓÅsò`¾}‚ÇœÞÞ^Z[[õý@Ö´¾¾>FFFxüñǛݔºûûÁm·ÝFoo/ÝÝÝ+¾¬—ÈBèû¾ˆèœ¡ÎŠ@ôýà–[nYpŸ`Ù$wìØoXKK CCCìÝ»·!žõë×ÓÖÖ¯Cd­25¦o½õÖf7¥®ÅŒ›6mZµÂEª££ƒïÿû<òÈ#ÍnJ]KÑ'xå+_ÙìÍiªÍ›7ÓÑÑÁ‘#GšÝ”)-f,ذalÞ¼¹Ù›)ÒT;vì µµß÷›Ý”)Û‹÷ý`Û¶mŠ"èû¾ˆèœ¡ÎŠDvìØÁO<±à>Á²H<ŽŒŒ°{÷nº»»ã«‹†††Ø½{wC®B>í´Óxå+_I[[[³7U¤©Z[[immåÀÍnÊ$‹Î8ã ]µ$Bå Àå8ºa©úвֵ´´ÐÑÑQ3'Êr2S,Xè “xYëÌwäµúýÀ$EÖ:}?Ð÷3Ô9Cˆ¾=ztÁ}‚e1Çã¡C‡«)i`†JOœüµÞÐh%EV>ÅʼnÌ6(ˆ¬^êˆ(ˆˆâ€ÈJ´,³m®8˜8ìÀÀ€†@‹¬Š"Š"™)(ˆ¬~êˆ(ˆˆâ€ÈJ´,´´´pÝu×Å· pã7Ö qîî¯±±1 *ÓÒÒO"+"+— €bˆDf DV7õ D DDq@d%Zs<¶¶¶ÒÓÓCoo/7Þx#›7ofdd„îînöîÝ?®§§‡Ý»wsõÕWÓÒÒÂÈÈ=== ›DVDšGq@D@±@D"³‰Š"«›ú"Š"¢8 ²-‹Ä#DW$ìÚµ+m&´­ÖÒÒ 7ÜÀÀÀ;vìPàYED D$2S,PYýÔ'P,Å‘•fÙ$! Õã§2›ÇˆÈʤ8 " X "‘ÙÄÅ‘ÕM}ÅQYI–Å"""""""""""""²²)ñ(""""""""""""" ¦Ä£ˆˆˆˆˆˆˆˆˆˆˆˆˆ,˜"""""""""""""²`J<ŠˆˆˆˆˆˆˆˆˆˆˆˆÈ‚)ñ(""""""""""""" ¦Ä£ˆˆˆˆˆˆˆˆˆˆˆˆˆ,˜"""""""""""""²`J<ŠˆˆˆˆˆˆˆˆˆˆˆˆÈ‚)ñ(""""""""""""" ¦Ä£ˆˆˆˆˆˆˆˆˆˆˆˆˆ,˜"""""""""""""²`J<ŠˆˆˆˆˆˆˆˆˆˆˆˆÈ‚)ñ(""""""""""""" ¦Ä£ˆˆˆˆˆˆˆˆˆˆˆˆˆ,˜"""""""""""""²`J<ŠˆˆˆˆˆˆˆˆˆˆˆˆÈ‚ÒÈ…:tˆÃ‡ÐÓÓÃÀÀ;vì ¥¥¥ÙÛ)"""""""""""""‹¨!‰Ç±±1öíÛÇÀÀ@|[OOàðáÃ|æ3Ÿ¡­­­ÙÛ*"""""""""""""‹¤!¥V …‡æàÁƒÜsÏ=ñí×_=ìÞ½›±±±fo«ˆˆˆˆˆˆˆˆˆˆˆˆÈšQ(–t} I<öõõ‘L&éè訹½µµ•~ô£ŒÅ%XEDDDDDDDDDDDDdñe2™%]_CcccS–R5ó; -醉ˆˆˆˆˆˆˆˆˆˆˆˆ¬UÅb‘0 —t I<¶µµqèСº÷™y'ކ‘ÅáyÞ’¯ó”F,$™L²oß>vîÜ D Ç‘‘z{{éèè˜rD¤ˆˆˆˆˆˆˆˆˆˆˆˆˆ4N†‹E J@º®»$ëmȈÇ;wrýõ×sã7²gÏöìÙÃu×]Ç®]»Ø¿ÿ’lŒˆˆˆˆˆˆˆˆˆˆˆˆÈj–Ë妽ß÷}ÚÛÛ±mÛ¶—´m ñÐÝÝMwww\Z`ÇŽñ"""""""""""""²0™L†b±H©T²¬šûÂ0¤½½t:M6›¥³³³îAÔ½?›ÍNºÍH¥R´··/J»’xÜ·o}}} ^ΡC‡p]—‹/¾×u9tèФÇôöörÙe—qñųoß¾8á)"«ƒâ€ˆ€bˆDfŠŠ"«Ÿú"Š"¢8 +“çy„aH†xž7¯çû¾O¡P¨±†!¶mãº.žç‘Éd&=×qœøï‰£ …Åb‘0 ‚ îó¢!‰Çd2É¡C‡›÷2:ľ}ûèîîæàÁƒtttL ½½½ôõõÑÓÓÃÁƒaß¾} Ý!"Ò<Š"Š"™)(ˆ¬~êˆ(ˆˆâ€¬\…BÎÎN:;;”x4¿ ß÷㹋Å"Åb±fÔc5åWÍßAÄmI&“8ŽC.—›WÛ¦Ó9[ZZhiiá-oy »víª[bµ§§gÆ`ïÞ½ìÝ»ˆJ¶=z”º»»(À˜¹$öïß_ݰsçΆîYzŠ"Š"™)(ˆ¬~êˆ(ˆˆâ€¬\&¡†!®ëNù¸b±ˆëº5ÉBó\“Tœ8âÑq\×˱VÏ×8±ô*DÉJ“Ä$ C …B÷»!#GFFؼy3;vì`dd„¡¡¡I?3=hhˆŽŽŽšÛ÷ïߊ¡¡!FFFjÓÚÚJ[[‡nøŽ‘¥¥8 " X "‘™bâ€Èê§>ˆ€bˆ(ÈÊåû>a2<n»í¶eù™8S,XhŸàñǧ··7^¦ÈZÕ××ÇÈÈ?þx³›2ÉR|?¸í¶Ûèíí¥»»›ÖÖÖfo²HÓèû¾ˆèœ¡ÎJã‹E‰Dœœ˜X¬f‚oK&“ñˆÆêPI&¦Óéx$£ID†a8©Ôª)¿êº.Éd þ;|ßç±Çã–[nYpŸ !#®»î:\×¥··—pàÀöìك뺳:¸®¾újZZZhkkcdd„Ý»wÏú¹ÓY¿~=mmmìØ±£Q›+²"µ¶¶ÒÑÑÁ¦M›šÝ”)-VØ´i:© k^GGmmm¬_¿¾ÙM™Òb÷ ôEBֺ͛7ÓÑÑÁ¶mۚݔi-V,ذaú~ kÞŽ;èèè`Æ ÍnÊ”óûÁ¶mÛèèè`óæÍÍÞL‘¦Ò÷}?Ñ9C3”Æ«.}ZoDb±XŒÿžjÄc"‘À¶mÒét\>5“ÉÄ£!²Ùl¼žêu×kïû¸®?Þ,ÛqÂ0dÇŽ é4$ñX=qëí·ßÎ=÷ÜÃ=÷ÜÃÁƒiii™õ$®Éd’žžžxØÍ›7Ó××·àövÚi¼ò•¯Œ¯€Y«L'âŒ3ÎhvS¦´XqàŒ3ÎP'B„èÄÂ+_ùJN;í´f7eJ‹Ý'ЉYëZZZVDâq±bI<êû¬uædûrN<.æ÷“x\Ž£¼D–’¾èûˆÎ꜡4^†q‚oâhFˆæ.Íår5ó7f2Â0Œ‹ŽãH$p]ß÷Éår òù|Íœ‘–eMY}¿ëº¸®[“ 5lÛÆ²,ŠÅ"ÇoHŸ !‰ÇC‡Å“»VwØ;::Ø¿?### ̸œ‰eŽvîÜ¥6ê]Å "«‡â€ˆ€bˆDfŠŠ"«Ÿú"Š"¢8 +ÏÄ$ßÄÄ`†q"¢QÅb‘ÎÎΚ²©Ùl6‘˜ÉdÈçóq©Ô‰ë3ê•uÍf³X–5)ñÄÉÍööv‰O?ýô‚¶½!‰Ç‰·V3W L7ìÙ”8š8Ñkuà0ËŸø˜]‰ ² (ˆ(ˆHd¦X 8 ²ú©O " X "в<…aXS*µ3§¢11èû>–e‘Ëå°m›0 ãäa.—«%i–“N§I$“ÖU=ºÑ´obyWÇqèïï¯ÛVÛ¶ÉçóŒsæ™gò•¯|eAû§!‰ÇÖÖÖ)G4š„ãtW˜RO½½½ŒQP8tè;wîŒ×ÝÝM___ü˜ÐÒÒ®]»±"ÒDŠ"Š"™M,PYÝÔ'P,ÅY>ª‡žçÕUh˜Ñ&y81 hîŒKªšDäàà ÉdrR21™L’N§§\§çy@eäc½ò®—YÏþýûyç;ß¹ }uÊ÷5 k>pà»víŠ'x ··wV“4_ýõìÛ·Ë.»Œ¶¶6†††Ø»woÍêžžvïÞO$;22BOOæcY%D D$2S,PYýÔ'P,ÅiŒB¡P·Dél‹E …¥R ˆ’Õ¥U'Þ71 hî·,‹|>ϱh—Ïç'µ¡ÞmFuùÔ\.7«ãTÎ<óÌ…íh”xìé颫LÒ0ó<Τµµ•n¸!9ÙÚÚ:itKKKÍcvìØ¡À!²Š(ˆ(ˆHd¦X 8 ²ú©O " X "ŠÒ¹\n^‰G3·bµêÄc¤R©¸\©Q/ùgʯAß_]:µÞ(ÅÙ°mÛ¶Y·n¤l¦†$!J>&“I>ÌÐÐP|ðÏuòÖ™FFÎö1"²r)ˆ(ˆHd¦ã\q@dõSŸ@D@±@DdþŠÅb\‚t®r¹% ‹Å"¾ï×”5M¥RA€ïûqâÑÜ?Q¡P P(““Œ®ëÖŒ\œ«ááa<Ï‹“ÍÔ°Ä#Tê-ëà‘f›*83ª±X,’N§I¥R …x¤£ã8¤R)|ßgppíÛ·S,ãù'&-Ë"—ËÅó9ÖݸЄáBJ¬6ÒIZP__{öìahh(¾í²Ë.ãºë®‹'tY aÆ£ ç’€ôò‘8 ¹k×.ZZZš½­""""""""""""²„aX·djõýÅbqÖIÂê¹\Žd2/ß²,‰‰D¢Ù›½âÍkŽÇéìܹ“믿žÛo¿d2ÉÈÈW_}uÍ|"""""""""""""SI¥R5ÿ¯7šÑó¼YÍÉhJ´ú¾O&“Áó<Òét³7qUjxâ`dd„C‡qôèQzzzð<¶¶¶fo«ˆˆˆˆˆˆˆˆˆˆˆˆ¬¾ïS(jþŸÉd‚ ¾­X,Nz^õ<†ÑØÕÕE¡P`ppÛ¶›½‰«Ò‚½½½¸®Kooo|[__®ë²oß>öì٣ю""""""""""""2'AËåjnËår5‰Ç0 ñ< þ=UyV×u ‚€l6[79)1ïÄcoo/ ­­ŽŽ éxÝu×ÑÖÖÆÁƒÙ¿?###5‰I‘©˜$b†uK©Ö+»:“D"ã8$“ÉfoÞªvÊ|ž466ÆèééaïÞ½ñí}}}ìß¿ŸÖÖÖøö}ûö144¤r«""""""""""""2­ p]¨ŸdœÍ¼ŽY–E©Tjö¦­zóñxøðaº»»kn7ÉÅê¤ãÎ;h4¤ˆˆˆˆˆˆˆˆˆˆˆˆÈt‚ ˆç`4£êD¤IN;ÑTeX¥qæ•x ¥¥eÒí¦ìêDJ<ŠˆˆˆˆˆˆˆˆˆˆˆÈTLRÑ÷ý8Ihæt¬¾O–¯y%Mrqll,¾íСCìØ±£æ±&á¨2«""""""""""""RçyqR±^©Õb±XóxÇqšÝd©c^‰G“\, ñmf~GSZuâí’"""""""""""""P)“ALJ,NœëÑŒˆ4 I„\N™Ï“ZZZØ»w/ˆË® ±wïÞø1CCCôõõÑ××ÇÞ½{'•e(ñèº.ÅbÇq°, ÇqfL(šR¬†FB6×¼===´¶¶Æ%V÷îÝKOOO|oo/“n‘µ«P(`Ûv\N5|ßÇó¼š2«S™8úQ–y'º»»éîî®{_OOæu‘¹\ŽD"'M™Uˆ’Š3Z4£ M¹UY>æ5Çcµª¹]IG©–ËåâŽFuâ1‚š„âÄR«Õ£mÛ®ù-3Ëd2‹ºüy'‡††p]—={ö°gÏ®¾új®»îº%ßA""""""""""""²üA@.—#NÇÉFÏó(‹$“Éø1Õ&–Ux?T3͹ÖAP“ä] óN<ööörôèQöîÝËÁƒÙ¹s'}}}ôöö.ùŽ‘å-•Já8Ùl˲Èd2¤R)ÒéôœË¦N,ÇºØ µ•¬:Y;Ý~~༮y%GFF §§‡žž:::Ø¿?mmm“J®ÎÇØØ—]v“îëííå²Ë.ãâ‹/fß¾}ŒŒŒ,x}"²ü(ˆ(ˆHdªX 8 ²v¨O " X "Š+]¡PÀ÷}òù<Édß÷I$d³Y 2bÑÌý8±„ªætœ;ß÷ioo X,â8NÍÈÐ H¥Rär9þìÏþlÁë›wâ µµµæöŽŽŽ†ì„}ûö1666éöÞÞ^úúúèééáàÁƒŒŒŒ°oß¾†¬SD–ÅʼnԋŠ"k‹ú"Š"¢8°Ò ’ÉdœLÌf³”J¥8éXÏÄ9'Žr¬g­''Ã0Äó<‚ ˆŽÙl–íÛ·ãû>žçʼnÇb±H*•"Â0äÊ+¯\ðúç]ju±8p€£GÖ½ïСCtwwÓÝݲâСCÍn¶ˆ4 €bˆD¦ŠŠ"k‡ú"Š"¢8°Ò…aˆïûñ<Žõض=å‰DbÒòªU'$g“œ\ÍL21—ËaÛ6]]]8ŽC"‘À²,J¥AA|»Iò“Ÿä'?ùɂֿ¬CCC >úÑÖ½odd¤fTekk+mmm>|¸ÙM‘QP,‘ÈT±@q@díPŸ@D@±@DVÏó°m{RéÔj¶mOJ(NÅÌY8ÝòÖ"³ÿ²Ù,Åb1žKÓ$ …B<º±P(ÐÙÙY“¨}Ï{ÞÃYgµ 6,›ÄãØØùÈGH&“´µµMºß\É0±œëæÍ›gœWòÙgŸåûßÿ~CæŸYÉÌü¬ÇŽkvSêZÌ8pìØ1Tß]Ö¼¾ÿýïóì³Ï6»)u-EŸ Þ\"kÉØØ9r¤ÙM™¶SÅ‚…ö Ž?ÎÀÀ€¾Èš744ÄÀÀÇovSêZìïGŽa`` n¹6‘µDßôý@Dç uÎp1™²žÅb1ž·q&3%=Ï›ò±³M\®VÅb‘b±Ï›iÛ6ƒƒƒ@44™Lâ8ù|˲H$ñ>âØ±cÜ|óÍ jÃ) yòž={êÞ~ñÅOºíž{î™vY…BÍ›7³wïÞÆíá²gžy†¡¡!Î<ó̺Id­0ˆ'Ÿ|²ÙM©k1ãÀ“O>ÉÀÀ“æ¨YKL²¡¥¥¥ÙM©k)ú?þxÃæ¦Y‰Ž=ºì‹ LâÑ\-²V>|˜‘‘‘e›x\ìï&ñØÚÚºlûE"KAßôý@Dç uÎp1år¹¸|j©TšÕs¦K<:Ž'«çr´, ˲¦,Õº’yžG¡P Nã8¹\®&aQµ½½=.› Ô-k›Ïçã¿ÓétÍ}‡ftt”SO=uAíWâ±µµµ¡ùÀÀ}}}Üpà [fµ3Ï<“«®ºJYó:::èèèX–W÷/v8çœsèééiö¦Š4]OOËòª^õ D–Fkk+===ôöö6»)u-v,زe‹ú"@ww7Àšý~pùå—+ˆ ïú~ ¢s†:g¸x<ÏÃó<Òé4¶mÏkîÅ™’ÕW'%Wƒ0 )‹ñ¨Q ž»Ñì›L&C±Xœubw*ÝÝÝ´¶¶.¸O0ïÄc#Ä6oÞÌu×]Ws{oo/›7oæàÁƒñmCCC“®JÖUÊ"+Ÿâ€ˆ€bˆDfŠæ"HÅ‘ÕK}ÅQXé<Ï#™L’ÍfgõøzIƉ·M—¼\-ó=†aÈöíÛéïï'—ËÑßßÏàà ¾ïAMÉZß÷I$“F@6Ó‚J­V«ž#¥­­mNW uwwOzüÀÀ»v튃¹ÿðáÃ5Áb``€;w6oŠHC(ˆ(ˆHd¦X 8 ²ú©O " X "Š+]†5åPg2SâÌ”Ê\ÖµœA@:Æu]†‡‡(ÁØÙÙïƒL&C"‘ ««+žÏq¹XPâqllŒB¡@__ߤɨ[ZZèîî&™LÎX#¾µµµníä‰ Ìîînúúúصk---8p€––víÚÕìý(" ¤8 " X "‘ÙÄÅ‘ÕM}ÅQXé‚ ˜WyÕzϱm»fÎÂzs9º®—!]©ŠÅ"]]]q±zŸŒŽŽÒÕÕE>Ÿçt,•JËn{çxc÷îÝ ÅW˜ãØØ8p€>ó™Ï4d‚êžžvïÞÍÕW_MKK ###ôôô,ÛɯE¤ñD DDq@D"Š"Š"¢8°LL®…aÔ&)Íc–["n.|ßgpp°î6X–Ïã˜H$H&“Ër[çxìííedd„ƒÖ-«ºsçNvîÜɾ}ûèííåú믟Óòï¹çžI·µ´´pà 7Ä[îØ±CCdSP,‘ÈÄX 8 ²ö¨O " X "Š+Í|F<ΆeYض]S^Õ¶í81·œ™Ñšfß  …‰D‚\.7«²©‹µ_a^‰Ç‘‘úúúØ»wï´s9vttÐÝÝÍzuÁ\æ‘ÕIq@D@±@DD$¢X " X "ŠËÑ\ç]œj¤ßDétºîc]×mö&ר7Ïe.—ÃqÇÁ÷}R©ù|Çqlv“ì¤ùÅb‘b±HWWžçaYÉdrE”ŠÉ¼f¸²ù8ó qY‚ ¨;Êo.’ÉdݪËY„a8åý…B €(išÍf ‚€®®.úûûãm‚ NÚ®dóJ<îØ±€¾¾¾kcž#""""""""""""+S†tvv²nݺšÒ &ùV„›ë+‘çy‹ÅIû¨P(àº.¾ïãº.®ëbY¶mãº.¥R©¦´¬mÛ+.éZϼ---twwsàÀ:4åã:Äèî¥¥ÙÛ*"""""""""""" ËåÃd2—…häßÄ’§f.ÃÕÌ$'J$¤R©8éXÍ÷ýx¤a’+Ý)ó}bOO‡fß¾}ìܹ“ŽŽŽx>Ç‘‘8tèmmmôôô4{;EDDDDDDDDDDDd …ÙlÛ¶Éår5÷Ù¶½ R«+•ÙØÕÕE>Ÿ'•J‘H$èïï§½½ñññIûiâ\–étºÙ›ÑóN<¶´´ð™Ï|†B¡@__ߤ‘---ìÝ»—d2©ÑŽ""""""""""""+œI4&“I<Ï›4·¡eYA0i4ßjfæ¶Èf³8ŽC>ŸÇ¶m¶oßNÿ¤çd³Ùf7{ÑÌ;ñQr±§§‡žžjîëèèhö¶‰ˆˆˆˆˆˆˆˆˆˆˆH‹E2™LMÒ¬ºÔªïû$“I€UxL¥RضPt'ÞnSZÖ”LM&“ …I£W³%«)Ñ("""""""""""²:‹EÒétœp³,«æþ0 ãÛ&Ž„\MÇ!•J‘N§ñ nBÍÜæûþªL¸‹EŠÅ"ÙlÏó°,‹ÁÁÁ)¿÷ÁL=ñ(""""""""""""+W±X¨I<ÕeU-ËŠG=N¹Ò‹E,ËÂqÂ0¤³³“®®. …´Ï[vÉÇH-Þâ•x‘)år¹xÉ‚ ¨™ëqÙ%Ú 2™ a’Ífq]—þþ~†‡‡§Ü/%j—UÖ'J:Ê/‚†Íñ(""""""""""""«K¡P ‚xnÇj&É8qNÇB¡°â¦\l.—Ã÷}J¥¶mÌXrÖ°m;~βE A”|Ì7~ñ(""""""""""""5Â0Ä÷ýx´c½‘{Õ·U'à&&"WšB¡@&“ ‘HL&ç•@\VIGÃ%J<gñJ<ŠˆˆˆˆˆˆˆˆˆˆˆH\.G{{;aÖíhxžT’&¹¬JŒÎA&“¡P(ĉ×öööºs[®H-ÿ^¤Üð¼J­ °gÏž¦íYf¤c?¶mϘD4ÉG¨$—åh¿  …ù|žL&ƒçyd³Ùf7«q| ”€a¢äcƒóÃóJÞô•¯,hñ("""""""""""²†yžGgg'–e‘H$šÝœñ}Ÿ\.zœX>¢QétzÅoëœUduÊ? dàÈ{ÞÃ7ÇÇyõV¡Ä£ˆˆˆˆˆˆˆˆˆˆˆÈæû>®ëÖMÒ­4¶mS*•Ãß÷ë–µm›t:Ýì¦6aç•X5’åßàÃcôfŽ ,h J<îÙ³gÒmàÀ“n¿çž{yo‰ˆˆˆˆˆˆˆˆˆˆˆÈ\A°"ç94ó8vvv’Íf)‹@T26 C›ÝÄå#À+y4=“@QB2„SžXøxÅy-¡µµ•½{÷6{‰ˆˆˆˆˆˆˆˆˆˆˆÈ˜²¤+­ìh†´··“Ïç±mÇqèêê"ŸÏ“H$H¥R5s;®Ya¹\ôóþA8wB‚Ù¢|-›oß ¶ºy'{zzš½«DDDDDDDDDDDDdž2™ ¹\`E–M&“‹E’ɨfh?™LÇqVEÙØ†(¡PÇ™œt„hôcp`Ëàøù…­î¤fo¯166Æu×]Çe—]ÆÅ_Œëº:thÒãz{{ãÇìÛ·‘‘‘f7]DDq@D@±@D"³‰Š"«›ú"Š"¢8°X|ß§³³“\.—Xu]·ÙÍšR±XÄó¼šÛÚÛÛI$ø¾oC.—ò,\×­;·ãš”ËA: S•u‰æ}ì‡G¯|tÁ«[pⱯ¯/>ÈûúúسgOÝŸ™ìÛ·o¼‘~ô£ˆ€bˆ(,†0 éêê²,²Ù,ýýýËz~Ç Èår ¶oߎïû„aH2™Äqã$c6›Å²,%« ByD(ÙòO5‹(ùhÃŹ˜Wßòê­nމDZ±1®¾új®»î:> ÀÈÈ´µµÑÒÒÂÀÀGq>ȱ±1øèG?ÊÎ;éèè §§‡¶¶6n¼ñÆøq‡¢»»›îîn:::Ø¿?CCCu¯n‘•Eq@D@±@D"³‰Š"«›ú"Š"¢8°XLiÕþþ~Òé4¶m“Íf¸Ôņ!¶mÓßßO2™Ä²,:;;ãù«“ŒžçáyžÕ,+úH™ ÷;D‰Gàá·?̹GÎ]ÐêæxüÈG>ÂÈÈû÷ïŸ4ßcOOû÷ïç†n`dd„±±±i—522BGGmmm5·ïر#~îÐÐPü8£µµ•¶¶¶8ñ)"+—â€Èü„aÿîêêª{±XœtûO<ÁÓO?ÝìæO¢X "0s,PYýÔ'P,Åņ!…BaÒ|ŽË­Ìj¡P  * kÚ›H$ؾ};ŽãÔ¥™H$4âq:Á·—DyÏþíÿ¶ UÌ+ñ822¡C‡H&“ìܹsÊǵµµÑÓÓÃG>ò‘i—×ÖÖÆÁƒimmoãÆoŒÊÑ£Gj‚ÀæÍ›ZÐN‘æS™»0 ioo •JQ,éêêÂ÷} *CÑÙÙI*•Â÷}2™ žçáû>‰D‚ï~÷»ÍÞ„I DfŽŠ"«Ÿú"Š"¢8ÐhaÆ#“¦ôæ2U,ãÄ£9Ÿ`Û6®ë’ÍfãÕ,ËÂ÷}%!šÛ±œÕE"Íbjìoß¾T*USJÕH¥Rtvv’Ëå°,‹\.‡ëº$“ɸãU,ñ}×uI$A@>Ÿ'‘HpâÄ >þñsöÙg7{s§´Ø}‚‰ý‘µÆ\5üÖ·¾µÙM™ÖbÅ‚sÎ9‡ƒêû¬yæ3ñœsÎivS¦´˜ßÞúÖ·rðàÁI¥ÛDÖó™¨ï"k—ήs†™r¢«¿¿ÙÌårñÇb±ˆçysz~ݲ±ííQ2ÎðžçÅ I×uq]—|>O:æ%/yI³7wJŠ"³‹Š"«›ú"Š"¢8ÐÕÕ²–kÒ1 C<ÏÃó<‰‰D‚b±ˆã8d³Ù9-ëC§ŸëÖÕ&÷’Éèÿí핤…ø>tvF™¹ÅV,Fë1£7ç˜PµT ‚€ ûÐÕÛ·W6Õ:ÂQ2“©ÜÞHóJ<îØ±`VCÍcªk0׳oß>víÚÅþýûë>Ö$4'N;000ã²EdePµÎŒ`4¬þþþ8™L&㉿GGGq'®iÑÄÙ†ëº Â0Äu]lÛ&ŸÏQÙÕ‰“‡/7Š"ÓÇÅ‘µA}ÅQh„\.G2™Äqœf7eÚ6vuu‘Édhoo'Nãºn\lVÂ2.ùøÇ!†ê‘é4$„])Š$`x£Ûr20Êÿ4*+W,FY¾D‚LНºÿýwáç€ .=o~ƒ0=/J2ë¶|æ›x·o& £ÝѦ&·Aþ£¿ûû£ÍkôtŸ§ÌçI---ìÝ»—ÐÚÚ:åä¾¾>8@ww÷´øÀÀ###tttLš róæÍñU ÝÝÝôõõ±k×.ZZZ8pà---ìÚµ«±{ED–œâ€¬E]]]$ \×%•JQ,)•Jq‚Ѳ,†‡‡ãºö&yXÍ$«k×›òªÕÉȺµí—!ÅÙÅÅ‘ÕM}ÅQhSbu9]ˆnª| bYa’H$H&“ø¾ÊÌd2 ×_ˆµ˜NWæ1,£ŸR©6éhd³ø‰,íåÓdÃÃ6¶a2Ú7<Š{t˜ ÓÅó`øwþë¯þ(ÊÒØvô3¿¦ë'‰µ~+Þ?@îé”_ (e ‹(ÿX*E£óùÚ|èL™Üã)¬ÓO"Ü=1›õË™=/ªS:88‹í5_³ï†ÁÏAþÎÞö€"ôø¸Å¨-¾ §~60Ü}-Ög>o—÷¥§ÈüÑFÒéud³• ®fWØv”€ŒþLx+xÞÂrªÍ;ñØÒÒÂÁƒ9pà}}} pàÀøþÖÖVöîÝ;cÒ*VÎf7ÜpClvìØ±æ‡Èj¡8 +™ÔÚ$ }߯)W†!…BB¡@6›KZø¾'!“Éd|["‘˜w°î„Ù+”bˆÀìbâ€Èê¦>ˆ€bˆ(,”¹à}9;ÊårxžÇàà ©TŠL&C6›Ï«UWñêï/qß}Gh @6 ™_BxÅ?’þúìF´šÑ€%'J² Ñ}–åádœœOrë_üÚ‡ñý n’ð?%qíKÁŒ@tœrÆÏ«YéyÑÜŠÛ°_¹pëv:[ÃèáÙl9Á Ø¿˜§&ÀMoʉGކ)f³µÉÔ0¤ó³ï!ïÞEæ³—†½ðÿ¼ •löªx'O[‰’UIFË*':ç0Âr:óN<{÷îeïÞ½ŒŒŒ022DIÇŬlFVŠÈÚ¥8 Í–Ëåj:n…B˲ⲧA`YÉd’T*E2™ŒG!š¤d"‘À¶íe]_¹S,Åʼn(ˆˆâ@-Ïój¦âi6Ïóâ)‚ ªâ5±jW:&“©ŒD´¬Íñh½ÁÁrÒð‹ÃúÐÞ)׆QRÑ÷+Ë©šâ1N¹n4 2Ÿ¯J̹.v*…ýá_Ãum`=ž÷R:;a|¼üËŠ–Já¯ï ü“Oâþê@43õT’$¬-ƒ°=Åààäe ß2£ýýð ®µð·ü$ZO&eI]—̯߇}ç?ãó!:'º{ð/¾õ޽¸ñƹ³íhŸ…!üǜņ {œx4;Ù(""²”L)T ¦¾¼mÛxžxÌf³X–E±XŒKE¤Ói‚ ‘HÄs5V_YfYÖ²ª«/""""""""«K*åQ,z Î?!5WaX™nq"ß÷Éår8ŽC6›o7#m;Jºn”4,¢eYž&—ÛT’ƒ‰k£Á€gTn3£ö'ZN¡ tÝhÐ`:•<Íd`t4zNöÿ+¯ó\ $©<©ªî¨9­W=bꙿÂá Ÿž¿{ƒW@¦èR\ï’½r׿ŸôÛ~ÀàçÊm®ÎÿúvŽãDÐÙ %Mšðœàå㺩¾¹¾ °ù¯ºû­¯ [Üí¨Ö4Ñ~ á}g“þÙ3€+âeÚvô¼hTd”4‰Ïl¶¶Ô¨¹þ?‘¨$4ɹ(g¿(!W ºÁ™<Ù¡Y‡„XüÒzòùõ8N´Ìööè¾R)Ê#†áz°^Ugõ3)ùÇðp´ \ÿ¯Òt¾ïÃŒ ëY›(ñ˜LBðùÇÉ~v;öë€d)jÔ\Jév%*e^©Œ Cxæ™;)W,ž7%EDdU2¥ ½hæV4#ƒ ˆõÊNxžG6›%“ÉÉdâ„¥y¬ùÛLÒm®Ö ‚€íÛ·cY–J¨ŠˆˆˆˆˆˆˆÈ’ºöÚ¿fëV›nú,¶Í/¸|¿vž@3 Q±X$†‡‡Ëÿ’…¦¼'D‰F#NoßÇúÙ_Å:wsí†8N%y98H\žµXœz®BÛ®š.Ñ{ÒQÒ E”,1)1h¦uìꊖcŒ%:‰ªr­Dɼ©FÒ N^‡Éþ¹ïÞ…ÛÀû $î‡Ò@XÙ—µ¹²A¶M#˜Å,4éJ<ŠˆÈ*a€étß÷éêêb´\7ÁŒ^t]Û¶Éd28ŽÃöíÛãç¦Óé8¾ïãº.Éd’\.‡ëº¤Óéš©&±Y`4s<*é(""""""""Ké]ï½üÏÿù^ö²-s73 çE?ýýQ"*£T*_üÁ×pÞyoŶmÊÅÅH§+£§”HD?ð¿Ö ç×Üm¶­TŠ|&y9Ó”–é4à%‡!Q} /X@líú<¯6áXÍ©S¾tZõNZV¼c H!ý ÈŽEíµò”¸¼)ñ(""+žçyñhF3/c†ñHÅ0 )•J¸®K†qB±P(®ëÒÕÕ…çy8Žƒïû8ŽƒmÛd³ÙK³Ú®,rG‰GY2™L4Úïgö ×_m|»ïÏ­§aÊŸ†aeÎDSªÔ$÷Ê•AŒg‘ýýýX–ÍöíQR®³3jKU{Â0Z€¦èº“›LÖŸ;ÒL‹8c‚o*S Ì%SåÇ”GHÚv´g1ƒÓÌfJº­ÇqÊyȰܦÜìžÛl'5»"""sáû•Ù—ƒ  ³³“®®.lÛfxx˜d2Y3RÑ”@5£-ËŠç\L&“ñ}ƒƒƒ¸®ßßßß?ï6:Ž3©t«ˆˆˆˆˆˆˆˆÈbð¼(·aÃ>¾üåÝñíŽStÞl¤RѼ…ííQB1›FGɰÎÎ(!˜HDyßÿù›yßûä~áñýfúA3rp°œWôýÊ‚ Ê.š¬ÕÙK*©—*íH&PÙÔ/ÿÌÔD»jT¨I®æ€v¢$ä|e™:éÚ ñ(""ËZ.—#™L]]]å·ã8A€ã8qx .…Z(×nÈçó“F$ÖcF76B2™ŒÛ#""""""""Òh™L”Ð;ùä1žþqð`¢æœÔ\F:‹•9ÍHÇR)º½ú”™mGyCÏ‹–ï8QÒÞÀ5×ü9>º%^¦ëFËrœª¤ÉDÚv4¦­½êyÑó'nÏŒåZ§\ 3'ïÌ\å‘ ›N1,¯®`˜¨¬Wþÿ|’ÊÕsZ.x‘e) CÚÛÛÉd2d2:;;q]—ÑÑQ†‡‡I$ô÷÷S*•ê&ù‰‰D‚ XäKxê°,‹ `É&ïö< Èd2„³\é=÷ܳäûEDDDDDDDD.—‹~Þ󞧸ýö¬[·ááì¤ \žG<¯âDæÜ•Q˜JU’kfd£ãÔ/-jYA¼|×…-[Æãû޽n8ˆ”¶¬)¯êû³ŠiJª6TÀìF &‰’}>¸>¸:Í8ßí±Êm €Nf5rr’ù$=çH‰GY6Â0Œ'ŸÎd2d³Y …®ë’Ïç±, Û¶I§ÓqùÔ‰ …(ù—Ë(/fIù~¥…?ŸÀ4LyY3¯e¡Pˆç§ô}Ÿ ‚€\.7) inÏd2ä¢KÑDDDDDDDDdñ¼hdb©§Ÿþ9^ò’÷38˜œ²âW½› …(ѸukôS,FÉÁR)€8Ó܉¾ïsòÉßáƒ?«ey^Ôqðý- Oüͤ«+ê¥ÓQªXœ[-}sìš}b橬–L&ãýbY£££ñí&qkÛ6ï}ïg9唼âŸ! C\×¥X,’Ïç9ï¼óxî¹ç–v爈ˆˆˆˆˆˆÈ¼™¤Þûßÿ ]]ç•i‡êI§k§L ‚ʹ3ËŠæ\Ìd¢¤ãlGš‹Ýã7üýߟà7ÓbãÆËxË[^àÙgkσÅsLærQ4‘ˆeYàÙQR/GôÛ'—$*oê%ØhÐÜŠ ‘-ÿÊm3#çÓ&‹…'òUë÷ˆ£if.£ºûQ#EV€B¡'!ê™8²)“É”G{åðþñKøÌgþ’dr”|>ã8|ò“ŸäÎ;ï\Ò×ZDDDDDDDDæÇó¢óUé4œ{î`YÉd2>_TïGÏh”ãöíQ0Ÿ‡ÑÑèÜU©4û¤£¹Þql.»ì$²Ù,oxÃ^õªM8N´žd²R–T*úÜd3“=©Œ ÌÚë'Jœ•ˆFæ•G>¦ÓMN<QâÐÚ‰FBΕEãFšDc’(1Z¤v¿Ö³EÐ4âQd™ó}ŸT*DÉß÷I$d«Škû¾O±X$™LaÆ÷›Ç‡aH¡P P(ðš×¼¦Ù›%kT{{;ŽãH$p'.j’j&ј­W<~–Lâϲ¢>¹²k¶£Ã0ê¹n¥CWP8«çš‰®ƒ àÁÿ /ÜÊË^v-[nç?àƒŒ."øÚ×.§¥%…çy ÆE“TË\T›iß„¡EWWÔ±,•\2™÷óË¿|œ|þ}ÁF<Žÿž{óB‹ˆˆˆˆˆˆˆHC Ñy.ˆÎóf³Ùi“ŽFD£ …(á˜HÌoÎDß÷éêêŠ+”UWù2¿«§nôŸÇuݸ¤¢ïûñU-æ9¦„£çyñòÇ!“ÉP,FcÒÍö±s8å”ïòÓŸþ”G½ × éïïG5š÷ªÝà: uŽS©ä†Qâ01ÃUHÕ¥ñóù¨U(€Çàà^~é—¾ÅOz&Ã÷ÒÚúôGÇ9㌗pìX7©Ôãåõ:”J%ÚÛ6mú~øÃ¯óÕ¯FIÖ\ž}öMØv”$Ìå¢vÛvÔF3ñöL°r•š¹ª,®Ÿo”‹÷÷‡!)gdÖæ™gc`àe Ý÷""""""""Ò¾_¹ Þœ3êìl' Ãøüòl$“³;ÇT- CR©‰D‚L&C6›Åqœš©¬ë>íߎkY¸øgxÓ›¢õ¦Ö†[ÁÞZ%íDɺé.¸7# ÍéÃ.¢„a#æH\(«ü3L”ä3IH3:sªíjTòt¦¶™õ„åö‰’K@‰G‘0A¢`ìû~<¢+“ÉÄ Ã0.-i’€ÍÍh5fÄb¡PˆÿÃ0NÔ®ëÆ#=ÏÃu]‚  P(Aüx·œ}ÉårüÕŽµ ‘1ïSÛ¶I¥R呌ÑìÊ—_~?¯~õ‡y≫øò—7Õ<ÏfŸïG‰8Ï‹:VfôálUç2m»RF~ûöèw´Ž»ï¾›-[¶ð¶·ÍiíÁ}÷Ý|ŠD":¶-ËãSŸú0oyË¿ñÿñklßþ#îºëZ²Ù,–ÕŽmÛüã?~›|à­XÖ,«2‚Ótî’É¿àw÷9<ïÔxmÏ3IÍJi×ê߉DepR,«’ ‚¨:8ÝnFHÖ¨®ëºä] ,hö;GDDDDDDDD¦ÒÕJ$(O¥“!‚šQ‡³‘w DçêˆNBL1•™®Ëœ·s]—áááèÎÎÎÊÿ¶ Žƒ½ûMàoНܷŸ=†U>•=«&βÊ.•¤Y'ÑHH³YóÓ`F+6Bu’o¸Ü®N¢äh?QÂ/Ie”£I,E²º}Kµ>थ[•ÈÊT= qâí&IQ°««‹®®.r¹®ë’L&exx˜þþ~²Ùl<Ò<Ç”Gõ}×uãÄe:Ž“9?HLâ±X,âyŽãN§Éd2xžÇî»ï޳étß÷ù…矇övX·Ž÷+ã b’ì¹\ŽT*E2™d||œ|>Ïðpš[oýï|çÜ}÷¦Y/Ó$Ó,+JšÄáDQ©SÓŽè-¿n]¥TªaÛðŠWÈd¢Ò¯åMþ0œ"ñhœÍοˆ¿ˆˆˆˆˆˆˆˆ,‰®®èœO©åó\7ªv—ËåÈçó³O:†at>8“©\ÙnN´µ·W†SV ‚€»¿}7§îtúûûk×å8Ñy¥®®Ês‰èœ“ã@2‰ý·Æ§žL~²®ùŒ¼³‰y¥ªe´[™ûÜ…ëæñœÙ¶1K”€L%7 å6š¹—hžÅfÒˆG‘*…BÛ¶ã+:|ß§½½=NþA@?®ëÆ¥MÍ\Œ&qÑA©TŠKHšßfÞÅ â2ªýýýñˆ13¿£y¬ã8uËPšdGWW®ëF?–…ë8œ÷ÀlüÞ÷àÝïˆ'~©ùP±m¾ÿ‰Oð ÍÞÙ²â˜Qµ&oæ5%E«™Î‘¹Ê$ÔÌÛ¹:ÁQÅq*£ú‰¨cQ2ÍäΉÊAÇ© ä³m¸ñÆçèï?•#GžÂ÷«+îŒ}ûÛ ÉxžÔ–xíkáÖ[óñŶíHø¸î¹D½·µQ’ÉÊü‹ét´mÉdôÛŒ€L&+%b«ó†ét¥7<-#™Œþïºà>w#‰ï}üÝ•Z«fÈ¥Ž""""""""Ëš96<ï2Su™é¸³­™êyÑ 4ˆV Ïã§øÇ¼èäàÒ,¤àȹGØ»a/wûM8ôqxЂ×e£²¡P%™HDœá\“ÉSÖµ’Ÿ¦8`?Q/Wþ±™ÛÈÅ,×jSÙoÃåíµˆJÅz‹¼îe@‰GY³Ìür¹\˲p]—T*@©TŠG:Ž—Sõ}ŸÎÎNFGG)‹qâÅ$Ç!™LÆ ÆzÇÁó¼8bÛ6Žã”ËSµ/})/â ‚ÚR”…B©ËÙ›¼â<ûö·“65 ìr)ʼnQ=nKù±·å+ÍÞý²„LB+ŸŸûs …B\ؼǫKÿ&‰Ê{p§ª¬B"Q[!¢·t"QI®%Q;“Éè§²ŽÊˆ&1™NG}lvïþkÎ?ÿE;öÛ@žë¯O‘ÏçI§ÓñÅÃÃÃñâ‰L’¦/ÿÚ(¶][:Öl«I æÞó=ú^ XñüÞ¿'ûKßÒ…Å‹þ“öö–8§8Þ_$uÍ xO¿ô¯ŒvTu2XIG‘eÍ\n*€™¤#Àèèhý‘Ž©Tå öjæªÿ|~òy!Ë¢†|+|5ŸÎ{ÿÙÖ?ã=oæ›ß¸¼ |( [ÝÊ|ŠÕ§Ìgòú¦0åµüÕ‰¹…p€<•y ÛËÿOUµÛ¥~¢o)O—™ý`J¼6ªÌë2¥Ä£¬fäa=&ah&Þu'Úf~D3W¢mÛ‹E\×G1V×´. tuu†!ù|>./ø¾÷aÛ6yˆNüW×ÊÞº’I>vÓMÍÙg‘Ïß]sŒ™ —iÞ¦Õ·÷÷G7Cåóµ‰PÓ2#úªÛuªr ¦9•_ú¥ßÁqþ Û·gH§Ó<õÔM\~y’ÁÁAlÛŽçT…(1Z=ŠxID=N½³s¹ÊÅUµY-+ªr‘æ+°=•§Èf±mHï;NW<›xÿ=¿B;_¯tÞ,‹ôoS,¼tîbŠˆˆˆˆˆˆˆHS…aTÑÊ\dÐÕÕDƒdêž×2eÁ …èŠvSò&_Ù_f΃[–Åõ_¾ž÷¾û½lyÙÞ´ûMlçGð­á¦Re9£D£ôD%Duz-d~s3Öc•òT’f4¤G4§b¾ü·Íìç•\,¦½«˜²¢™’¥–eÅ£²Â0ŒçN4s&vvv’H$Ã\.G"‘ˆ„ù<®ë’ËåÈd2d³Y\×¥½½=™Ø?á$~"‘ —³H§‰žç‘J¥pƒ€7¼ï}°o_ôI18XÛØ|<­©ë¿÷=îø½ß£ðUÏ‹F$¾þ‰'È}ãgùÁϽƒ»ïæ ÛÆµ,6þÑFxüD»*)³‰è³Åq¢¥t:ú|‰vLtŸïƒc«]5~¨Ù¯š,ß̓ƒL´·Ûø~Õ{d‚T*C®ë²}{'ÿþïyík/âŠ+Î'—×}UÕã+Õ²YSk¾’X¬w5“mǃnëÞWý3úˆç=mooÇu]þîïþK<ÙÌ¥Z­úÿ‹šl4[½Sͤf½fçÛ·G1õóK¥šûÓ¯ø"Ùk-(:q/3š¿{K\×ÅÂu•Ž(®‹íºôw.ÞæŠˆˆˆˆˆˆˆÈâH¥¢ó¼fÐH&“Á÷}†‡‡§?¿•NWʈÍ0UP*•ŠÏ§' .ø· ø»ÿÇ>w¬²Ž‰{̈G(‘—!J@zåûæ{ê­X^^ržÏŸŠYžéhÎEš†å)–ô”º”x”eË”X …ŽãÄêB4¡Iš˜ªfÔ¢)¥šÏGs¹mß¾oûZ®¹æ}ñHÆd2I&ãÅ Él6K*•"‘H”G>‚CtÉÏ>ðJ6­{?oÿñßÒÙ ®Ýþ?÷´â_ðÿ(}ô¬Gî™4ܼp$AÁO08 €ðßÀ~ãš+ùÏ?³(f¬ü)vŸ»µ²íÿ A¦þí?P‰ÿ™Lôybæº.~LEŸ5Å"8fÛlyôÛ÷ávë¿G[åWV¬UaòÉOÞËE½‚Têø¾OOϰ¬³ha±X¬)lYétš0 Ëïxç;+ꔎ½¿+q}¿2o¡) 1Õó”ú¾ïûA@2™ŒKWoTbB#ç]œ¤P¨Œ\¬Î–f2шŨ!ÑŽ­L¹\e´c½²¦38ÅÁ—½ëíÑÉ)z]UIÊz•2– R¬ˆˆˆˆˆˆˆˆ4@FçØªK¬AŸ÷œœt4#Q öÜÓ¥OÍt_¹\.>/3§^|êô‰M‹h´c‚¨²žOTÆ4 *mšŸð¸Ù²YÚr£QRÒœrSUÀE¥Ä£,&©ày^ü7TF/™DYoïwxî¹Oqß}ÿÉàà žç‘)Oüf)étš½{ÿ”bÑ# !ŸO—ï·(•J\~ùY ýaåÒi (ÑÙñ$ƒ¿þG¤½ü·pú?D# ‡³Q]ÉÿõÍ·rÙKä´áaÜ«£Ýî†Ì |!¸¯‚Ü·à´ÇÎWÒq2#z …a}z'ÑœŒû·½8ð:î»ïׇÓO#o|ãŸsï½çóÅ/žË3Ïl‹ÚA½·ªËòšä¶ëFy³h^t»y|‚;¡Ó‹Ž‹šä£8pìŸñî¼›ß}ÇïrÇw`m³ð< \·Õu].yê¶±-êÀÑóðÁŠ®TòL£ˆ:(ÑÕJæ±ð9îðàŸÓQG¦<ÂSE+gKC >”†ŽrÇÌ^ß ·yp†;’°0£- ™¸w…p¥uVÌäÕðŠ4œ›†7–0¯ücJg“Q›»¨\æ—ÛoJBxå¿Í¶L!Ùè+ÂDDDDDDDDdI˜óÒžCËf!|ÚÛ£Qù|gb2±PˆNÐ ÎjŽÅ hoo§T*áû>étº6ɘfnÉ?3/c¦R.5GtîÍœ Ê÷™iÀÊç㤟)wª èW-%eÑ„a”|¨Œ˜ŠÊ%Z–Åÿû÷òÿø*6nÜH©ÅË'Ÿü&§œòunºéKœ8±€ûᅧ––;™––¸÷Þó9ÿü—’L^F.çðÈ#¯ $“.žçqÑEN±x5ccüÌÏ|‚0Ìb?xŒàFî+ï%ûÒ¯ð»/¹£¼žLÆ¢P(WK<ç‡c›ðnkÁ~ùi¿íƒ°JŸ(Ï?·?AðÒÁI`Ÿ ©>óeM€×|à4’I(¼;úÐ …'¡ô8o‚Ä]ü"¤ P<ìS y:$^aþÏ÷ÎÀ>-ÁàÝ{³!xÒEÈÞÖ…å)âþÜs ñ¸ç;`û6ŸÎgt~9J6ZDë5Ÿ#ÿ㜯kö[dm3 ³jæC¸SÊ Ê];îbÝÖqÃÉ7𵱯ţ}?ý[ŸæŸ|­m÷p0|^ù(×<üU¾þý.ÙÉÞ»6sÉ%pÛ­à´Ã]ýùGÈ_Þ(øcÐÿ*°”×Bb#$>ÖCDW5ùDƒ$ Ö£ðä[ŸÄÞ³ °xøŒ‡ùÉ»8ƒ½Å&x<à‹|Ûx½ÿ!ÎuÎ:(I¢Jy@aœÌKS™ú˜ïÎ,gç²åýywJøqpN"šPÚtj¾À‘"<¼ÕŸ°à7‰!ð¾þ(AyĆ{€¿)o«éDuy®¤Ò‘ ªÚœ·à!¢d¥¹Ì.·Ý.ïO¿¼®Tùwõ¤Ò~ÕíP™ »PÞnÕóªÛDDDDDDDDdE‚èÜyDIGljªüe2‰ù|¾ö Õs9æóÓ&Me³\.‡ã8 cÛv\ù¯FµåHg#ËäÑ‚Õÿw‰ÎWÙ埠꾕shf¢F®JJ<ʬe2“«V+*#p|þäOnãË_ÞA:}z¹ja†B¡Àë6¿Ž‘£ÿ“'7>Çşʺu÷sê©»8õÔ—óÔSÏbÛ_â~‡'.`ݺÇù“?¹õëŸb|| -Ï>̦ ï墋6’ÍFÓ¥Ùö©üò‹~Ÿ?þêõä￟­Á•$Ö–½¿þ(¹?þmJ …?^GxÊÕ°n© ƒ³îJo{o#„/ÿ[~òBŠo‡ðõ×Rø2$/or¿m“÷2fdD‰!¨\dF²™«}LÒ©ŸÊhºþòm%¬ª? ‹åßIxðøƒÜqÇôõõq³w3iÒü¿Ç‹»_Ì¿nûWÖëáOàš I¾†àìß?›¿üð»)¼Þyîf®y¨ÜFsÕQx7„Áz¸:¿£¿B|¥’eÚ2ý¾÷7î%$äчÅ}ÇÏñ£ýˆo¿t”b²È=÷ü*£ŒóªW†\úÆKyþ›Ï3òõ‚+‚I»íÜðÜhûzh àöù0äGóNðfŸjA¾ ÑKQ2ò‹åפH¥,D ø{ ²Vù`2ë.ÿ®îŸU—ŽpËû*IN¯|ûÄ!Ñ(Ê~*£«×Ñ¤Ýæ}d®³¨$#ÍnÌ”ÿN”ו)¯ß­Z¿Ù_érÍÛ""e=¦>,2s‘ÎtŸ?!•ÊóažoNl˜‹»l*Ÿ…ÕŸ‹¦¬SõÕÝnU[!®¸PÃ<ϯzÌÄ+ÄÍóLß©Þþ0UË­Þ–êçûUë0³Ê?ÕA™þ£7¡AÕ²ì ë ªî‘Egê˜Á:¥R4*1“)ËåÈçóqõ¿IŠÅèÄü÷ ‚ À÷}\×%NcÛöôeTM¿´¦J šÑÕ«î—˪¤Äã†Q‚¢s÷fº²B!Šcæ>3X¡|b=¢g†‚WfÂüÁS<óÌél^ÏË¿so¿ò¹ók<ñÜsx ò)Ûãƒ}ü××ÜÊß}÷í\}ám|ç‡g`óǤÈ>Ó‰“EpÍFJWBp%ü·¼“M»Ìß“€Þ3ÈÿËx§ÿƒŽo"÷¥ É~¼ÿ Vë6è·‚ÏAêæ(Æf„âïƒ{&Ø_†´¹Ý¾ ÜkÀÿp­(ÙW¸ Ü/| ‰Hå$û&(~ï«ÚáX'AâоüÀ}ÿ ¼uPz8—%’• W‚ ú ²r@¶œKù}È´n‚(Béã@ ¶Ÿ€°ÙGË0´$û€xÕWžÕI†Fª­VD²¨$ýòosÈ$ˆLnÍ!J8¨9!ôý9ÎËþeœk_6ÀøŽ~ …¶m“x_‚žû=‚‡NÇ?þôÏ®áD¸gAæï!ôÀù%¢ÑÙr•OÓÞSyý‹Q;ÒU ²b1ú1ÉNˆêÁ[–EÎÊE#—¿caYÅb‘|>ïy_iŠe˜œåè´»êû&^9Vͼÿú©$(ýªm1'ÍhÒþè÷9—ž/šãvJE½QË"M†!¾_› ‚ .a½õñ­¼þ»¯gÛCÛøËÿ%×üðzæ!¾÷ä÷f~¹Ù[!“LLU3±Þ<&AôyNÕc³D1?¤v.ª–› ú<ôˆú “.ÿßô[ ꧘d˜ ÷Cã>¹`Æ\ãP)Kž§rÑ•QªºÍ¬Ó›æ1ƒDU«~^õ:« Wµ¯¿jÛÍ礹`¨P^V©üëƒò~5û$AåÂ3ÓűÊé¤ò™_]±"AmUƒ‰m¶RÛ‡4m3ýS…!M¥Ô¼)+Ÿ-¿NÕ{À´= RJ«Pµ¬BtÛ‹Þ©NˆˆˆÈbòý¨êŸeE G×øÆ?ßÉ;þëŶmúûûI$Ñ ÷BùY6[žžÇýƒðÞÉçÅÌ´K&јÍÎa¡?û‡6”.Š_õ”x\ż _Ø'J𑉾ýXVô“HP);êFqíØ±cÜqÇøÒ—¶rþùGxÍknåÎ;_Í¥—^ËÑ£¿ÈI'ý&×_ÿ4Ÿýìz6o¾€O}*`ãÆ_äæ›‹8ÅßäªýG¹gài>9~€ ïÇ÷ë”§q΃}ç]Èk¾ûfZ¿ö¿[xè´m¼áäù|à^ÿŸzàR¾¾îär’¯¥p+dZò¤ÿà™çÈܼëTÈ¿þò¹ÍüÑý!ü,”~xsyÔ`´í Rÿn(þDJ€ÌÕྂ õ È^ 'ÚÞÈþ5´¿#Ú7ÃÃås!9p®,ï\3¢­üÅ=ûM°¯š#1'A,°Îû°ïÇ‚Ü7 H@¿)÷˜7ŒžïyQò‘áÊ¢Ò!$Ö;¨½j$¤ÀÚV›1‰åàôèuÝóp‘·Úomö[te(½®fDœIê˜KE¢7D’Jq¢òûñ:÷ÕIŠ™¹?ùΫ»œM›öðÜàß`¾˜/~ñƒ ì XŒý‰8YHÜ©k£ï¶ýI¦ŸÇÓ¼7ëLúœHÀ—¿ü×lßþqJ¥A±H©¾•Ç7²í¡mœ|ÿÉ?~œ7>Hé´QNüøœvâ4Ûñ§ì|ø]œqñ=Üòƒ3xð¤ãœ·eˆw<ü œõè…|þäç-G_F‚DÕµ.!t’%˽´P8Ï㽓ðJž¿‹ËÎ;‰»½›Ó·ü”ïÿ1Xp×éwñÜ©ÏqÉÏ\º­ã-ÛÆy¶Ù¯íjP}’ùònF£&YU=lj¹¨ºß>H%AfFçWL3£×«GÎæs¬ús¡ú³Í$͈º4•9‡«?†'޶3ËœøùR}e“M¥|8ååšÇ›Ç„D}Z»êÿP¿µ Øê vª—1ÕÅt¦{õgrõz¦ê·U_L4Xçþ‰}§zÕ`Æ©M‚šÄ¡IÒšöWïs¿ê¹Õm4û¾šYÞ •Dtªü÷è„çד¦’ÐÌípÙ}—!""""•ó»Žy·ÈãŸÿwŽýÝßñ¿ž{Žd:_ó}غ^ì$|­¡…D¹ÏgÜøÔ üù9ùì“9÷³ç’&Íï¼áwØn¬\\h.‚3s.V_lg.N7}uÓE Äã çûQòÁŒVô¼è¶t:`ä8ÑmŽ\äqÈÜKÁJ€ÏÈÈ1>üáבɴð³?û Î8ãå¢+ènã78üÜSô¾üÇÜE@øç8züòWÃá/=Àß}üdÞu’Ïã'JôMqËÕ·âø/‚"¼îå'xrè.yí­$O\Eá®óH¼í‚“6òÊìyÜâßBk"Ë]×¾ŸÿøÇ$8ÿçñ5ø$>mgðµ­$®€ðb×]HþÃЙŠÊ’Z ð‚àÛ¾îÿǤ‡–íƒd²²?âû~FHü¥Þ=R)'ëºÑ•(‰€ÿ“ÊógrÞ$ž‹-v²Ÿ˜pÕ ‘İînËZø\ù$©Iƹç~ŒÓN{wÜq¯{ÝA‚2™W±c DÉÁtºrr½:o¿¿«‡5»n<Ç*@±XÄ÷}¶=ô?ùÞ÷x׋^Ä=÷ÜÃë_ÿz^Ö×Çðð0aØçy$3™¨/bYQ …râÑ,›0ŒT/9h®ÐZ.ªO®V'!ݪ¿W»,ÜÙ~'wÞu'oâMÍnÍÊÓEôÞ1£k–q'Ý÷£Cpbìçö*ƒŒMe#™Œnó}¸òÊGûÁÙøwÁ±gޱ.\Çk6=Ï¥¿1Lá Í‰õ'pÝ"Ÿÿ|A`qÁ?dëÖ­¼èE_çèѳ8rï%\üØ‹yõûŸØÀëÖàÖçÎà^x/Œþ"Ï;7nû2ŸýÑ{jÚqÎ9ߤýÑ­|ù…X@†;HsiÍcrU·]Åw¸ãb~†£Œ2J‚u\ÊŠåoVcü6ÙÏ©œÊO:…M'mbïó£dy/ðïÜðC¾ÞòcÖ?ÖÁ±ÓŽqOò®Ï½‹Ëéž9éÎþ™¿åŸî‹ê±Ÿrò¼ã…3IRÉ)=½é[<³iÿöÓmœyæÃÜÿÔq¬ —>7ÊM'Z8zâdvŸýwŒ= ‡Ÿ;›oþ{nJ?ÜÅõŒÏr>_àr‡Ÿ>pþãìïð­Wü néääñçùÈK?ÿ ÉSàGÏ¿„Ô¯¼œ¿x?§}!Ïy˜+¼—¯’åoŸ*wZFßKw?|,½æ‰¯ý6ÎmŸd€››ýV]Ù TÊ¥R¹PiÊÅJP©Š`xÕ B“ü3ñ¤:ù4ÕÕÀS•7ª?z IÔYF½õLŒoõ|î4Ÿhbm¦þÓTí«~Þt×%5sdº[ç÷è4¯·ï¦Ú¶‰Ì…0³5± l.øÔMÛU""""+RuÕ‹)ø>tvFçêJ%¢‚]9òÀi?÷sä?÷9lËŽÎ?æm¸ªnuà" þ¼<Ú1$áèåÁ?zñWó[wþÿðÿ@ß©}ìüílîÛ\I&V_i*`T'Í—ÖÊ÷‘[q‰ÇÞÞ^úúúcçÎôôôÐÚÚڜƄTÊͧ4ßt‹®Êx^tò¯k'ø÷BúíÀÈ}¶òød’o¾îúh´Üè06“±ŸŽmO=ùërW„4'~׈ã/9ÎñûŽ7» ²ä}3'j–Jg~®ÏŸià®]ÄX] ½X,|/K&!õ_磒ÞAP©bPàG.wét”ˆûЇ¾ÌÇ?þ6^¾ù NÞ0†5f±ëôcü˜sËS­\tâdNÞò=î:~.Ožò$þc>¯á5Œç¾Ëß³ l`½÷ ïçC1Ä[Î~ç¿ð4§ný8%ë1Þuþ:ž;ök¼íÙ'9îç5·ý ÛOç¤ wòó/œÁuv‘±LëÝWpôèYÜþËòªÏžÇ\ü†âçþç9ãÄ ž{Ý5|õßÍÿò¾þ?¿ÎÑsÿƒ£÷ÿ'ëׯç‡Ç~È—ŸJòè)oã´uOð–_x‚ü³Ãõ]Å÷†¼ÿ Ï¿ùƒ<Ùn‚ÜIë…;¸åÉA®;éQûÉI¼ýÉ/ðº'.cÓ yfë?]÷Ÿ_ñrž~ú}¼ïæØ'Üû<<þ‰g.¼ï—®â–[ÎàÑö|ý+Çù™àÛ¸OúØOØ|ãMÀËÏ]ÏÛÞ¶Í›Ÿâê~‚^xwÝ¿³áøŸrç?Ëùÿ÷ÿÆŸýÞ\šÏãÛ Š?Ùįø<ÁÞKðôkqœ×ÒæC’Á§réãŸ&x|+lÚDòSWÁ§¶”_£×AÐOɲ κ 6o&‘ˆÞ7AÏ'¸î3¿Îï/ÞQ³è–,˜’œ¦Ìeõ<Ì&.˜Ïª*uGœÍ&™'«ŠùngªÌ…‰íæÂ2sÁ©¹°*¿«? Ç©|F˜ 7æ6מº»½ÈçY¹£—ÕyiőڢSõߌÀ³¬J_e¥[’8àS<âS·J†™ËÑu£ïðÙ$|óºo|ê3¬?ó¼éšÿÎÏ}äç¢ïæ"à‚Ž[óýÀ·|‚ µ5E©T"ód†ìDz|Ýù:ÝWtG|]ÕÊóU«¤©4ɺññññ…/fi˜ÀaFoo/7ÜpÃŒÏëèè ££cáð‰®b æ²ö,“¯46Ö!:Á`‚Hy®ïß (ë(ü„£+Wp;=*ÃI d/¿ö+ÀÞáÍðƒî;yWß#|c×\qãã›ç|€×üô5üɉ7ó&ÞÄ©[Oå…·ñÝ-/⤟¿ŒÑ-£Ø¶Í›o¿ ?ýé ¶Ë”–ühü–‹wJ;îËGáv ®t쪱ª©õ>Ü̙̈n[ˆ °,+þ­#Œ“t¶mW’tåß¹\Žd2 ô<˲p‡ Ã0 éèxý××’NG‰½R©ÿÎårñ2¡œ¤‰]]]äóyR©èƒ!•J‘ÍfÉår¸®Ÿ\¼øÅsÏ#÷Äm0Ïu]—d2·ßl'·s¾öìÙÃÁƒ÷,¡ùÆ)·Û£2_Q¹TmM}óóúö}ho‡Ë/ã¥/ý6O>ù$·ÝÖBFõÒ.¸à^óšçyõ«[¹~÷KkÏ(•…YO~ä#ÜýªWÅïuÛ÷¹ýSŸâgÞñ>ùÿþúЇp³ÙhÎEß'>íÉ'¹â–[ذa?}Ç;x®µ5~OÉÚ500ÀÀÀ==+³Öê¢÷ þ3„[|øp „ÿfÁ߸Q<0£JLÙ¼‰#XÌüš&Qá€-„Ÿ7…û!8É=ú ððpùãtç'8ç€IDAT+8{£/(…Þ;øÄ_ý 'ž<ÁŽõÏðÈÖG¸þá—ò½ŸžÃàYƒ\ðØi¥•ÙÀQîã“\C‚—n¹”Ï·€óž>¿¿y?}ÓßpÞyç0ºe”Ç7òÚ^‹Úœ¸û1Öo: —ßÏ®;w±qãFÆß=È9Éo!ÏŸqˆÏ|Ží…ÿ­o‘H$Èd2üöm<ð/ÿÂË[_Îñð8O·¿’;~…sÏ=—¯<ûÞôðø?õXÿì‘xyUŸ¥©TŠáòçÛsgœÁ©ÇŽñ«®â«W^Öø§Ûi¿å󌎎²mÛ6Ž9Â…Ÿÿ<9Ï#™L’ËåøÃãÇyöÛßæÄë^ÇñãÇyfÛ6^øßˆû#wÞÉgœÁ“?ù ›î¾;jÈĹaÍ7ñjKTײwWö·¸ €w¼ã>ùÉÇÓO^b ï@íUËõç#4ó1›ï!µ_îW™‰óÂ×A µ©>Œª^P©º>ñP3•IÌüæ™LíýæyÅb%aV]ýÅ÷¡¿?ªúÑ5QžÝoÖeª är•é¦'®Ç¬; +‡¸ïWÚl•+“¤Ê£\ÇÇ+]6Òi0Uè]·²Îj££Q%-ˆ.|¬¾žÌl¯yžeEÛÖYõ~4%öïš›oÞWÂ(*UíÍ>I¥*ÿàûäijÏr¦eÁóÏc_p뢳¹é¦ÏróÍïoöÛm^æ Vz_¨.3z¡Zu èzóÆ®ì2i •~L,‹s†²(êõªû¦Ú[õ¹FÓ?1Ÿ­f*£j¦Â DýóyoØvíHù|ô¹\Ýç1˨>¥S,Ö®'Ÿ¯ôªû8Õýón¾žtuU.6‚¨¯`úÕýŒ .8ÁI'„m×ö7ªoärwðñ_ƒn¤»û>î½·…;îØßÑEc\zé(·ÞúS~ô£•y1Ò¢|?¨fª™óˆÑ÷ƒTù· Á— ðÑïPøÎÅX§Žñ_ö9óèUœ÷ÀylßÂ?¾ýùµ-¿Æú/­¾O˜Ósåkþƒ À÷ýxK&“axx8Ø"²Ñ'XQ#:Dww7ÝÝQ&ÿþý¸®Ë¡C‡Ø¹sçâ­Ø§ÒÏ‚$µ#e2T‚NÁ‡7…øZ¿eaà" w€ÿeÈ^]7£Àîœ|/î_<‰ûâ×â<—ýÚQÎùéß0òÝ/òÒßOGàãöÛørÇ3Qs|Ÿâïê{.nâ™·nå¯ß*GÎNê±õré;€;àeÑ¥+»’]•á{}’uwÃOx»m¹jÛ$[’ÑÙÕ8¬ýjô«&eŸlðË ¾ÇqªFåy5£Mâ/“ÉÔ$à€8ÙA|B3›ÍNúÝÞÞN:& C‰©T*N"šD eYqÂ1N“ËåâÄ_6›“…¦ÝÕ‰ÏóÈf³å¤ß6N?=ã8”J%ÇÁäë§ øÃÃÃ5¿Kå¡”ýý“ë ]Á5Ë3Ï™HÉ¢ÅQbÀÌiꜼ'„¿¡Õ\B>õbL'1àÑGå _8‰ÑÑQ:v|Žÿó¯ÈäØu[† ¹€û¯ºŠ«¯¾ÛND¯sg'|у/\¯< ´I†_xÖYÜÿý{ÿûù/}‰äÓٳ‡ÁÁAr¹ù|žû€îtšï½â¼,‘`ôâäwÝ»еž²Z4¬OàQ)…hâB è,kqá<àYÒnå"£L¦ü Ó_Oãßèbý xO@pøØ?zŠÔN¯YÝh úÖŸà²gNâ»·—Kž?™±gΆ—yœuÊqŽß{3ÉÜGÈb³Žuìíç]§ãþM_ã™ãÛ¸oÛýüÛ[þ•§7<ͯ8ÁKþãûlÙ¸…–÷±aÝî¿ò ¤?pü×GhÝt{¾ñmN{î瀭\z釸iý“$ ÚÛÛyìÒKÙzÇ•ö]z)ÿqt;'ýÆIAÀVÿq~ñªûxæág8qå;iùö·9ǫ́DªmÛ8ŽÃ–ãǹçå/çù×¼†ÿêWy™ûó\ø{bY9;ÇÈ7¾ÁúçÞS“¤s!þ,­þÌ;µüûµåŸÊ\à`¾_Xþ.»Ï–‡‚o˜æ¥6Ÿ¡›˜öA3Ï'»Š¾ìÙ6¼÷½ÿ¬Ìm ŽE¢ã~âGUÿq? ae§õO˜\4 °ëÏaf*­‹Ñcl{r’Í$ÁÌ.ä®»àÁø÷¶ðä3ÏÐÑq‚¿ýÛ3Ù°áiþoþN¾µ¥fwn|ž‘Ç·rÖYyè¡§Ùzø6~Øœ8í4~þäûñý­;E’Oú^N¾i=/./㢗|ŸÿHR™·Ê°ËË1çpÒUmu¨”™›Ø¾™ÖS5%JÍ\ºfÝNÕ:íªÇ™‹Sª/Ú†Jù»™’ÂS­§Zõm×Sï1Ó¬góí›YÉVe,˜#s±ùœ®žrÁu+ç0LÒÎLÙµI6¨MÊAåB"Ó×0Ÿùõ’l• ^LòË´åÒKGyÓ›æË_ÞÆñãùÀ¾Wj1r¹;øèG_űc§NJ]zitÕç5×üßþí¨ªÛ‡?œ§¿ÿ-lܸ‘§žZÏ3Ï<Ãk^s+GžÅCmãâ‹÷Üój¶leƧ9~üëüË¿ü›6mbëÖ§¸ãŽ­Üÿýq;¾óÇCgŸ};6là—ùo¹ï¾nN=õ?ü!”JwðôÓçñôÓçqÓM²qヌŽV¶çÌ3ÀöíŸaË–ÓÚú¿û»wðÈ#WðÜsgpÞyßä‰'žà[ß:³Ü®óøÎwžàž{ä¼óÎä‰'žàÒK£ªr{÷–€³ÊûÇj‹ûî‹ü'nÎÂq¢i³:;'"‡tºòÑW.dcY]ô댌ãÞ{ÿ{ïµØ¸ña…VAhx(]llÊÚwp^'ù°=Œö­&lµñ¶Ga¸xËÉó± Ÿãêãßá=ßÿ&ï?ûgX÷+ëØòÏ[x7ïŽo¾ø¾O‰^›b±H?ŽãL&I–«)é(+ÍŠI< 122RsRkk+mmm>|xÚàq÷Ýw³m۶蹦£[ g×v&¯÷á{U—¾Ê‚§2ÇÛ àýüg¶þÇFÂã±~t Á–Kñ|°ÜÚGŽnˆò²“ïçvÜÌ}_ÞÆ¦öãüÃ}d¾óÖáÉGïåÔNåÞ–óéú‘OøxWéûžqƼüå/碋.âè¹çâlØ€eY¤Ói^]U§'.µmF=÷8ïÁ÷}¶Ø6zà~çw~¨Œþ Ê B¡@2™¤ày$“6…òè¿‚_ÀNØX¡EX¨ì‹ ê’Ÿb±H:ŽGòuvv2::J{{;ýýýtuuQ*•â2Ÿ…B!-˜H$âu›+5ÂòY ¯Ü»©NF¦Ë‰óÛ$4ÍÉÊ\.G”J%lÛæ‚ .`ÇŽñ Èj&@› ùÏç§|ìÄÿ/× ßÛÛ»b¯Jœ‹…Ä ê@zÀïzàxpž§¶ŽnèÃ/DÅ׃ ¯Ä½”ÄÿþRŸ|-<ð4—]vÁ—âK÷^IËIGy >/9q;}xlÝÚÉé§oãÕgþ”®—ü —[›6]ΑõëyéÞÀÐÓOcÛ6üÕûßÏoÝsùà¤Ó”Òi …BÍûÿßÞüf zßõ¿ç=8ŽCº\ÒÔ¼Íÿ“S”CíëëcÇŽ´µµ5ûå[Rk嘨¶–^ë†ô žê€÷yð`N+Â-ƒÑ| }?›PÂ$ÌÕ¬éîߤ«ôaŸØÀã}Qrñ}Ï>ÈóÏ=Ï--Ïqí¿ÿîó‡(acâã“ d¹o[w=O„_çmçœÃó/}ž 6Ð饼ã¿íä–OÞ‚ý6ãë8ã9hûÿÙ»ÿø8îúNü/9‰'ö*#Lœ_Âf”Ä€ ¥8Q%³î ñÝ®h¯-ÖÚ=øL‹ÚÒÆGCËíQêöÛooG܉Ò_hç.”ˆ`‡ðãÈA µIÐ`³$Äàh¢µÿ É~ÿ}Fû{WÚ•ö‡^ÏÇC[»3³Ÿ™Ýyë³óžÏûó`Ë2îeh¹=6^~å•X|ôÿâu¯{¦Ïgðo§¦ðž¿yâ8´5D"ìš=‚¶Ü€o~ó›¸úuÂKß=Šk–û©T }" I€,£õM_žçUü½³¾Ž–Y¶?NØ þœ?~ÜÿÒ¹Yl–ø×hŸð ¸DÜu·LÍfw‚…ëÄbp"qÿ¢žü· ûØ×`ClD>ñK0mÁ¨3”àÏë+—Ü…>÷éÇ0ôÖë‹__ÿú)|õ«»ñúןÂkoø>¾ôõpáôi\qÅx~Û6üíàÏðõ¯ßˆk¯=ã?†g¿¹?9®pé³ÏâÑ‹[qâÄ9\rI®ºjó¿7 ÙVq𺇰k«wÑî3Ÿ¹ ²üµåD§ŒwÜw´¾Ÿ¶E¿Å¿ƒÿî?ÈâñíÿŠkÝs+‡HÏ›:Æ$½´ÂlÏÐÊÿ-«(†åÁ¥o]ùýé¯NQ©xïÏñ7=†¡¡!<øàc¸ù™gðŸúS\zé¥xþyïnÿñßÙ‹gŸ}Û·oÇ7¿¹ó™§páÂôõõ!›ÍâŸõádÎcÏž=8uj /x^zþ!À Û>ƒ Kð“ìkðÍ>…[o½<2‹_»î:l9ýýýX\\ĶmÛpáÂnO`ëÖGñƒ<íÙÇ{ Àw¿û]ìzÉÜ÷Å/â#ù~ï÷~/½õVòhïzÞñŽwàcû~#Å-_ûnºé&<ú裀÷¾îu˜ŸŸ/¨Ä‚¼Š,J*…!MÃ+_ùJÜÿýؽ{·7r|ùFÌ`0¤Rè 177‡¡¡!¤R)Há°SI§iJ,XoâšoqÒPÌ5.’P¢|3ò+úúéžì'€ï?ü}¼dßK = Èû€€ò§€]´Ž,H,'#Èɼ˜´À§eh9¥ˆV‡·oÜ @䀱À/±§ýdÞ‹|P½Y\`äËõ‡€!*´_ xóÃ᳸Þ_Þ9çý¾` ˆ\_°ˆ\ßõöY—ÈÓ€s°¾(;õ*À: Ø?°ÀŸñ€ö_Bg¼×°³ËÛHÊV ô< Íx뤮‚â>¬Ÿ/)àÐÒeøáÅ+ñí/mÁî…chûåøìÒÀÅK/âùËžÇ]WåðG?¹ç®?‡ÿza Ì.â»ç¼Û .HqË%YÈØƒ.mÅ ½ñ'W<‡þè<¾ôÌÕþ¡{ï®Søö…>ü`Ûó¸ñ¼rûÓ8öÓ«¯Üîâÿ‘ãó`âr8î¾é =Zx¾þï—| ùØ/á+g.Ã;†žÄ•™+qìTáíXŸÚû(î8qPa·¾‡×d¯ÇÏÿÝ Ð݈FcÁå_î}þóG ‹j`@ù$þ2bš–èÊSÖ" üàþp,@z9 Ý83vÎSÞ ‹‘8`¼Á[çõw\ÄÉùKðG.ñ_jp÷y=ÿÅK±”…`påD—Ü!?‚¯ÿä¤Ï]áíÏ`¯ô$þáñÂÛŽ?ôæ|ø³£üÚÞ¯à_Ÿx ~|~·ÿü©ËOás×Zxú‡ÿ €ßüÚoâ—îû„ÿ¼à[Ö vàá¥xÊz øbù; :D)Àþeèþÿ7áU~ÂûìÿŠÉþ'&ð È‚1¹¢žÁß|ô_ñ™ gp+n…5óÀb}èÃÏoý9.{Íe…7›…7ÙŰ2‚ð @~íÕ¿à=è4Mí˜þ› ¼ÖRËç› n¦WŽÂ>ÿX?¿¡Ìeø ðÒ]Ï`ÿ«>‹_yäcø§|O½DÁ¡>ú4\×Åny7t]÷Úˆi¹Ä`Y–¡ª*b±Øš+ÝuÃwÁn¸¶µY¯Eë˜ÄãÒÒ””>èííÅüü|Õu³Ù,r‰Çñ¾·¯ùùÿ„]Âó¿…sçÎ[,}!ƒSOmÅó—=çñ<.üô,~úýoàû—½?þ‡­x÷Oþÿý_þpý–¸~Ë \÷µÿo]þ<ûì‹`žú¼ˆý~ˆÞÈŸ~ï÷®ÁÀÀ‘ÉlÇ÷¯{!€-À öáòË/Ç+^ñ ¼ø³‹^fMóËsþáòè¼7¾_[¾…H”UUš¦ù_2s¹œÿåSÓ4„B!Ü{クöÚký²ŒŠ¢À0 ´ŸY˜O:QvT”ù%?%Iò熣ÿ I!I Ë2’ɤ_.T´Ýu]¤¢yP.©Wü˜ø·8¡+šW.“ÉlÊúýµÎnÑH€³gÏ"vû?á‡Ïÿ¿tz;z®z-®¼¸ _ŸÁ÷¾w=Μù~ñŸÄg¯LãçÿÚ¥‹7 ¿ûÆw »<Ìé[ßú*žÃïm?Š×î}÷½ïáMïyfþÂÂÌŒwAGùÏ)è?Ó¡ª¿á'ÖÕk¯õkv(Š‚kÞüfüá5×àÅŠ‚¹Ûnƒ¢(ë’Øæ9±yl¦÷ºÑ>ÁÓÚgÿ¹-.^²ç^u ÏÞûe|ùËçpñâE¼à߯÷¾w=Nº‹‹/Æ… ^bñ%/ùuœ:õÛ8sæ tý¿al|xË|sÏ£8¾CÂâÅEÜzë­øB*…ÿ»‡ÔÜÞñŽwà]ï²ýÝ!%„ì?ÿ3^êO=…Ç®¹ûöíùùy܉Àø¶×ȯÁgßþvüÇÛnÃü㊂kžy‘ýûx7å9²üoê×ÝûWLX¼<úùCc÷cú¯~¿àXø£è»a"2–––ÉdZÝŒ ·Yâ_£}øÜÕ'ñ£ç$,üò?b.÷bôõõáºwŸù̿ǹsçðÆ7~÷î~Ï?ß‹ŸýìE€ëÿî{>ûY?î]ú…_øÙþlß¾çÎömÛð·Ú]xî¹CxöÙg±pOzæA¨y“Áï Ša1€õV9¬Ü xÉ<á«_Þ¯@Â%—\‚-ç· }ýõxï{³Ø½{7~ô£sp/½¡%ÊÅ‹xzëV<ýôÓøÊÒ>|ùá'pøða$ ¼ü•¯ÄÍO¿7œïÇâùE,½àøæ7ðÄOàšk®axóK_Šä㋸qt333øïx¬} £££xôÑGqaÏü¯+®Àc=†ë¯¿ÿëË_FT×aÅbþ÷’]GO,†ÑÑQ<ùä“P¿|ÿý¸þúëqýõ×Ã0 ØËßY’É$‚Á ‰Ôåï0â,o”ž÷ÿ i"c>ï»Ò«–«¡Äb1¿êÉo-÷»dYöFm«ªÓã§–ÿ=i…B~Õñ}HüÿvYÆ%Ëeœô£áêw½ W]u•?‡öµ²Œÿ7ïûUþ´{OÚ6Þª(\®òrÓM7A–eÿ»°rS课ë]P·Ür ^¥ªH½ó€ŒŽBUU æUq)&nÄ,þwnnét/yÉKJ.uª`_¸õ2ÌÏžÚ‰«• N.ÇCO]V°ÌÍÊðˆýŸ¯}í¿à¾û¶Ã…{yxáÛÒÿˆÌµý¸oá—°÷Û?ÀÛö~ qûwW6`c‡&0ý]¯LÜ+?ÿyô,\…oŸy5€—x‰ºà oø|ùËÞl½¯¸ÿ}xðÁØp!áµ[? ëK8{ö o¹æŸqêÑÿRÐÖËúþ_ûùñü]Ïã/ºûŸìÅÏ΢[€ÿ `K{ÝŸá|ö8÷…s˜½ùá²ý'ôôxW½/ÿÛžØq¾på•8ûèAlÙòmÜqõ?a÷‰_Æ}=Cxí oò«ß‡ûN:,¼2ƒ ¤.d8€ |С!†øÊ€ÌÀ`ácË·k[p‚ƒ Ô‚A›G`à>(Àý ¬å×ñò¼2”Eï¸ Á„êÙó= )¨p–ã²ü€·ÝC2ÞðÏpñ¢r8ôS_|¸þ?Hx3$< à¦g .†–‡pf–€7ÂF Þà‰žìÈå0sÚÁ×·îÆÅ3WâÔ¥gÐwÍUøÈb.»ì2Ó§€ßú‹d„°¥w þø¿ŽTQ6é»gÏbûK¯Ä~nŽo;ŽÛ®Àß?þËüÉÓoÀý¯ßÅÖoÅ#×?‰þg þ$ïf£óÀÛ^5ŠWþ棸âŠ+0qó!üÊ}=Ûøö¿ý·X¸eç^6‡çΞÅkúS¼ö…Ëôé:žìMáüCçñÒ—^ƒà_¼}ß{ `™{"¼ímYÜÿÜýXT¾ÂmÜ~ûÛñÄÛß‹WÀ®§vá5Kg; —ùÈ>‚§~ó)œ8qöÀÕ‡þ°ø ÿù[Å™Üå€I%Yò:ûö½O|è½øÉ‚-7lÁ›—¶•¼Î-·èpÿÚÅ?ýÓ?á‘GAðÞ?NÜï?ã àÄT î_»xè3!öïb€^¸Ë/;~h¼Ù-Yœ›?‡þ3/.XæÚku¸‹Ã8ù“xÁ–àÒß;`åuúÐSp½ýQ\’_¦ðuž’ž‚ëºØ—É`î(XæÁû>‚þÅ1ªª]¿ú«ä½NîÙ«ðÚÇÿ¨}‚ä­ŸÁßÍâñ¥3pЇ7m›Ç÷_à ›}Nýõ)¼èEWàìØq+²Ù,z{€3gnö¿Slß¾€ƒgžy—^z3.^<…]»²X\¼ Oá‡?ü¡_z{{KÎÙ\.‡óçÏ—Ä jëäÇ­'Ÿ|@:ƾ«¯ÆéÓ§ñìθä’KÐÓÓƒ×]qàºØ¶m\×Åõ×_øéOýiM^ö²—á…ßý.$IÂ… °mÛ6‰½{÷úëˆ8_»EßSü??†çÇû . ”|Ê­ó³Ÿý gÏžÅoþæoâÿð[}joh,øÈG>‚¿üÐýx|ñ¿#wéðì³Ïâ²Ë.ÃÏþ>lÝz'ž{îQlÝúU<ûì‹pÙeûÐÓӃ瞻}}=XZº½½o„뺸öÚÇqêÔ) ôáÌ™3þg@Á5ÃG}Àƒ>èEÁ‰'°s§W^€ÿÿ½{÷úËäÿ{óÍ7ãÔ©S$©îuÖò:Í^çÚk¯Å·¿ým¼æ5¯i»¶U[ç?øß'l·¶ÕZGÄ•Zë<ñĸüòËñôÓOãĉ­>­74Àm·Ý†­÷ư„ÎàI<ŠÇ°<é.»ì×ðóŸÿ»wÅ“O¾W_A6{7vïÞçŸ×^{­ÓE<×Ö«]N7|ïïÔþw¾N¿qòäId³Ù†¯v̈ÇFüÙŸýðgåž™ËûÿmyÿcÞÿ'[Ý|"j’o|ãE܆ÂsŸˆºÝŸýÙŸáÏJú* k™ý‡V7“ˆÖYåËoæý¿³ËQuýýýxÀŸçx'€W-ÿ¿¸ ÉmEÿÀ»óþ¿9bÅ_4aÖø&ˆšî}ï{V®«æjÍ¿f¸9Îs¢Í¬¾ù}„¿iu“‰ÚÚ–V7`µÊ îäš¿D´zŒD0ãy ˆ`, "Æ¢vÑ1‰GQŸùøñã§ÓéŽ+ EDkÃ8@Dc1‘‡±€ˆÆ"b j7“x€ÑÑQÌÌÌ ›Í¦¦¦pð`çM|MDkÃ8@Dc1‘‡±€ˆÆ"b j'=¹\.×êFÔ+›ÍâðáÃÈf³Èd2˜˜˜Àèèh«›FD„q€ˆÆ"b "cŒDÄ8@ÔN:*ñ(¤ÓiÀþýûZÝ"jÆ" ˆˆq€ˆ<ŒD0ãQ;èÈÄ#µ—Žšã‘ˆˆˆˆˆˆˆˆˆˆˆˆˆÚDDDDDDDDDDDDDÔ0&‰ˆˆˆˆˆˆˆˆˆˆˆˆ¨aL<QØx$""""""""""""¢†uuâqrrÀ¾}ûpäÈd2™V7©!³³³+ù™ŸŸ_õ~w±9tèÒétÙçš±íz *íw=ï·¼÷ÍÖmûܬXÐ)Ç¥‘XÐÉçD¹ýÞlš­›öy3~*Å‚fíc;ö ºO6›Å‘#G°oß>ìÛ·‡*9oöíëÎÎÎBUUìÛ·ªªbvv¶íÛÍfqôèÑ‚m®W¬lFÛ+÷ÅûQîø7ëø26¬¿fÅ‚V¼Ÿµâ@;¶»ž8Ьv5«ÝÄ‚vŠiT]=± ]ßÏè4»ÝÖ'ÊÇ‚fõ êY†q õ62îoÔþ8p äsÝ û°Q} ®‘ëRþð‡sCCC¹O~ò“¹ûî»/wÇwäî¸ãŽV7«á}ºí¶Ûrþð‡ ~~ô£­j¿;áØ†‘»ùæ›s÷Ýw_ÙãÐè>¶ë1¨µßÕÞÿnyï›­÷¹± SŽK#± “ωJû½™þ4[·íófû,T;'š±íxØ'èNâ8ßwß}¹ûî»/÷ž÷¼'744”[ZZò—i×¾î=÷Ü“»ùæ›s†aäî»ï¾ÜwÞ™»ùæ››ú¹[v‹mÜsÏ=þ1¿í¶Ûšz¼›ÕöjçýáÇsCCCþ~|øÃÎÝ|ó͹{î¹§©Ç—±ac4#´âý¬ڵݵâ@³ÚÕ¬v7 Ú)¦QmµbA»¾ŸÑ'XvwRŸ —« šÑ'¨gÆö°Qq#÷§øsÝ û°Q} nÒµ‰Gq1FøÑ~T„;ÍwÞ™»óÎ;Þïv>6Ÿüä's7ß|³ÿS®£ÝŒ}l·cPÏ~×zÿ;ý½_/ݸÏ͈í~\š :ñœ¨µß›áïÀzé¶}Þ,Ÿ…ZçD³ö±ŽûÝëøñã¹›o¾9wüøqÿ±¥¥¥uùÌ®Çû{Çwl3—ËåÞóž÷ä>ùÉO¶m»ï»ï¾’ KKKþþfµ»Ñ¶×:ïË}NÄ{òž÷¼§©Ç—±aý5+´âý¬Ú±ÝõÄfµ«Ñv7#´CL£úÔ Úõý܈>A³ÛÝ)}‚\®z,hVŸ žeZo#ãþF0 #wÇw”|®;a6ªÔMº²Ôêüü<2™ †‡‡ýÇúûû188ˆãÇ·ºyk–ÉdÚïv?6ÃÃØžžÆôôôºíc;ƒZû Tÿ»á½_ÝºÏÆ‚N8.Æ‚N='jí÷fø;°ºqŸ7Ëg¡Ú9Ѭ}l·ãÀ>A÷ Çàà`ÅeÚµ¯›Éd0??_°M8vìFGGÛ¶Ý¢„SÁû°ÿ~ŸÚ!ŽÔó÷xx¸ä³³ÿ~d³Ù¦_ƆьXЊ÷³Vh×v׊õ¾æFİFcA»Ä4ªO­XЮïçFô Ö£ÝÒ'ªÇ‚fô êY†q =lTÜßóóó0 üàKo÷}ب>P·¹´Õ XKKKPòaèíí-[Ç¿S?~KKKØ·oïäÄÄ„ÿ¯g¿ÛýØô÷÷tŠ5cÅãít jí7Pýýï†÷~=të>7 Úñ(Öh,¨gÛñóQk¿7ÃßõÐû¼Y> ÕΉfíc»ö ºW?&&&x_L—––033ƒÁÁAÿ½h×¾®¸8ßßߣG"“É ¿¿£££lÛvïß¿ßoþy%ö§Yý…FÏ©Zçýàà`ÉÅÇl6‹{î¹§©ý?ƆьXЊ÷³Vh×v׊õ¾æFİFcA·öºU­X .D·Ûû¹}‚õhw§ô ı­ šÑ'¨g™N¸n´lTÜ_oÙlwÞy'"‘HIµöa£ú@ݦ+GþñãÈ‘#PU022RµÄe;IÓé4ÆÇljD:ââ4UÖ‰± R¸ë®»ZÝ´²º-Œݨ\,¨U£ÕØ'h-ÆÍ¥“ßoñ=õî»ïnuSÖi} Vëêå2Îú¥’ááa¿†÷jö»ÓM3ö±ÓPúþo†÷~-6Ã>¯%tÃqiÆ>vúqجÖ¢Û÷y³~šµ~Ø'hbn|ÃÃÃ.­Ú®}Ýâ„ÈÈÈHÁHvl÷àà ,ËÂÃ?Œ‡~ÇŽCooïºôÖ󜚟Ÿ÷ï²¶, e/8±oÔþš Zñ~ÖŠíØîzâ@³ÚµÞçO=± bÕ Úõý܈>A³ÛÍ>AûÅ4ªm#ãþzH§ÓèííÅÑ£G166†±±1+#½;a„êu‹®L<Š;ý‹'æL§ÓmÇP%³³³'£Édü`SÏ~wú±iÆ>vâ1¨õþo†÷~-ºqŸ› ºá¸4c;í8ðïÀÚuÛ>󳀦îc§ö :×ìì,>\u™víëŠy‘Š·YAçA6›ÅÔÔ”ÿX:F:.(‘ÜŽ}]‘Ôžœœô·)>w¢¤Z»¶{vv¶à˜ONN"4µÝëÑö|ét™LÆ“ÿ“×ôfëuªfÅ‚~?ë‰íÚîZq YíZïó§žXÐ 1<õÄ‚v|?7ªO°ífŸ ½bÕ¶‘q½ˆ¤[þà}¯mv¬[/Ùê&=¹\.×êF¬‡l6‹Ã‡#›Í" “É`bb¢íçK¨fffÆ¿ÈÔÛÛ‹L&ƒññqLLL¬j¿;åØìÛ·ÓÓÓ%sU5cÛùTÚïZï7½÷ÍÔûÜŒXÐIÇe­± Óωrû½Ùþ4S·íófü,”;'šµízØ'è>3338zô(Àºž»ëñþf29róóóÄüü|Ó?wëÑît:#GŽ ··KKKèííűcÇü’FíGÊ÷“““Jó ûsƒu{ߨ›4#´âý¬ڵݵâ@³ÚÕÌv¯5´[L£êjÅ‚v}?7¢O°íî´>P šÕ'¨gÆÖÛȸ¿‘Š?×°Õê&]›xD]ôýû÷w̤«Õd³YHnÅ¡¸õìw§›fìc§ƒzÞÿÍðÞ¯E·ís³bA7—fìc'þhL7í3? ÍßÇN:ìt®L&ã—åYïsw=Þ_±ÍõüÜ5»ÝùçKq"¿™í^¶¯ÅfëuªfÅ‚V¼Ÿµâ@;¶»ž8ЬvµÃùÓM1­ÛÕ Úõý܈>A³ÛÍ>Áê—i‡ý Ú:å3Ùéû°Q} nÐõ‰G"""""""""""""Z];Ç#m&‰ˆˆˆˆˆˆˆˆˆˆˆˆ¨aL<QØx$""""""""""""¢†1ñHDDDDDDDDDDDDD c⑈ˆˆˆˆˆˆˆˆˆˆˆˆÆÄ#5Œ‰G"""""""""""""jDDDDDDDDDDDDDÔ0&‰ˆˆˆˆˆˆˆˆˆˆˆˆ¨aL<QØx$""""""""""""¢†1ñHDDDDDDDDDDDDD câ‘ڒ뺰m»©Û³,kÝÚkY\×mÉk·óq!ÚhÕ>ÏÅq…q¡²voÑj¬öó\mYÛ¶á8Ϊ^¿ScA;·¨’JŸÙrß-Vóg\èœöQ÷i嵞ûÓ>ên͈ëÕGXK;*Åõ~íFµsÛˆšç~“Û–£Ž”H$r ­nFÓ-..æB¡P@@NQ”ÜÜÜ\ÃÛM¥R¹õü¸È¥R©–¼v;j¾n=÷›aaa¡ìç¹R\a\¨¬ÝÛ·Ù1¬Îj>Ï•âÈÂÂBNQ?Ž„B¡º_¿ScA;·m³â¹_]¹ó·Úw‹z?㌠վͨ[cC«¯ ðÜï¬ömvŒÕ­Wa-ªÅõ~íFµsÛ¨¼n ë…ç~sÛÆÊ4ÍUß]× 4Mƒã8X\\D.—ƒ,ËÐu½ÕÍ"jÝzî7Âq˜¦‰p8\öyÆê6ŒÍW+ŽD£QȲŒ\.‡ÅÅEض MÓZÝlÚdxî—Wíüm¤À¸@¢[cC«úð<÷©1”·^}¢NÑ­±:Ã¥­n@3¸® Ã0àº.$IB$$Iþó†aÀqȲ UUaY"‘o˜«* … (Š¿ž¦iˆÅbþ¶EA(ò·'Ib±Øš—¯FÓ4Äãñ‚¶‹6‹ÇLÓ¨ªZ×6Åz‰D ËrÝÏ×Z·Ú~Ô{LÄû877ç¿âÔ:.ŽãÀ²,„B!¿£ ªjÅcãº.t]÷ßóÕ®_ï±–$©à3•¿Ÿ•>¯µ>‚eYp§äsQ®í•Öï£8î÷Fã¹ßø¹ßH\¨µõ“zοjÇŲ,ÿ˜TúŒT‹+ùËv[\(~óÛ_Ϻª¿jq@ìw¹XÐÊ8ÿþæ[ѨçùjûѬXP-¬æ|->×Åç RÛž››ÿ3fFÁ9T/öš‡ç~m­èÿ¯æ¸4Úïe¹ów5}±|~lèö¸PüwKߺãûA­ó·Y}ñZ›éÜ_KŸ Îýbì#ÔÖî}„F®æ¿—Íî#H’ÔÔëùdz8´¢PmýNø~P ûÝÑGبëâ3³YÎýõètüˆG×u100àŸü¦i" úÏkšæq—‹8át]÷ïzq]CCCdÄó®ëÂu]„ÃaƒA¿ö·®ëw¶­vùjt]G4õ?š¦5t]4õƒã8*¸ã¡ÚóµÖ­µõñ˜¢(°m–eA’¤‚}¥ãâ8 ÃÀÀÀ€ÿZÁ`°ì1ω@&ö«Þõkò׳,«àΪZŸ×ZÇ2_~* <‡K>Ë•ÖДýÞh<÷ëÓȹ½Qç~=ç_µã‰DJ¥Ê~Ù¯'®ˆÏA·Å zl¨µ.б¡Úñ«Ä1¨ ZÄòÍŠžëí ª“zÏ×rç:P=Žˆ×Ë_^Üœ°Zì#4ÏýÚZÕÿ_Íqi´T>ëíˆÏAqlèæ¸tgßêÓ ßj¿Íèˆ÷z3ûö €ö<÷‹±P['ô¹F(¬G¡™× €Ê± U}€zÖï„8PŒ}„útBa#®ˆ÷z3ûëÒhuØfט]\\Ì©ªš[XXðkxç×2–eÙ@AmðD"‘“$Éÿ@.‘Hø¿+Š’‹D"þï±X,§ªêš—¯@.‹´-]UU«ÖÎ777WrTUõ·_íùZëÖ³õ“d2™SU5'ËrN–åœ$IïQ¥ã">ñx¼à9¹ÅÅEÿùÅÅÅ’6äŽ*­_Ï~¦R)ÿ3”¼DÍøü×ò?¯õ¼F¾ücW¼X,V0×D¥u«íw»×ç¹_[#çöFžûõœµŽK¹ÏD.W=®t{\ïY¥ØPmÝNŠ •Žß—¿üåŠq —ËÕŒ­Œb{•>óÕ¨çùzö£Y± Ú1©¶î§>õ©ªçz¾rqDl§Ür ºµÀs¿ºVöÿWs\šÕ(÷™¨õÝ¢V? ÒvóÛXn¹Nˆ â=í¶>¿ÔÖ)ßj¿kíÔsm@èÆs­}‚ZǵÕç~1öªë”>B#×k}&é#4ë:X¯R,hU ÚúбP[§ôÖëºA­>B·ŸûëÑèøbÈn4õïPI¥Re¦iBUÕ‚a½¡P€—µ•e®ëúÃ¥Åï"›ž¿}À+£QkXëj—¯&¸êjÊ+wòïø©ö|­uWóÕ:&ùw-,,`aa‘H¤$«_í¸äECóßOq·„ø«µ~-Žã”¯ü!ÉÕ>¯Ûw#X–×uë^¿Ü~·{ pžûµ5rnoä¹/Ô:ÿÖr\ê‰+Ý€Í*¿o|ããP_,heš =×Û-Ô:&åÖ}ä‘GÔ>×+©vάæ|b¡¹xîW×êþÿjK«úÀÚbC§Ç ;c¿ÔÖ)ßê9×Ò'X͵r:ýÜoô¼¯t\[}îc¡ºNé#4ãa%Íè#4z¨ Øh.öjë”>‚Ðìëõöxڹ߉ÇT*ÀÚÓÓƒh4  zÇÏq¿.mþO§Ô¥îFâØç%Q×] /^­â ¥( b±˜ÿYíúµä×BsñÜïnëÝÈÿn±–ØÐéqèÎØÀïÝ£¯ ˆu*é„s¿Ùç=Ðç~1öºÃzÄÕn{5qb-çBµXÀ>@s±ÐýšuÝ๿ÖãV¬ãbÎD"ÅÅEÌÍÍÁ4M†I’*EQüŒ±øI&“ˆÅbU;“ªø8X–UPºÚóµÖm–jÖzO„ü¶ŠšÃù‰„Ÿ¯T¿¹ÚúµÈ²\r—Cþ6ª}^×J¬¿°°€T*…D"±êÏp£ûÝ <÷ëÓȹ½Qç~¹×kÖç°ZìØ¹s'€îŒ Àæ‰ •Žß£>Zµ½›)4z®wR,¨¶n­s½ñ… ÿN¾Z +m‡}„æá¹_['ôÿ˵e#úùÏ­%6tr\º76ðûA}:áûA;\(§“Ïýfœ÷õ×vÀ>BmÐGhFhtÛÕâD3Î…j±€}€æb¡>ÐG(÷zͼnðÜoÖ1ïøÄ£˜ðUì¨,Ëþ‰P(äO,ˆx“TU-øX™|´SÔûÁŽD"%Ç!ÿn¯jÏ×Z·™E,Ë“™jšY–ë>Š'ë•$©ä.1a´®ë%ÃëY¿šP(T0ùª¸+F¨öy­Gþûÿ’$ù_v*ÝýUnÝrû-Žy»ß½Ãs¿¶FÎí<÷…FÏ¿rªÅ•›nºÉ¬Ûâ‚ø½Vl¨Š÷½]cC¥ã§(JÅ8t~,؈>@=ϯ‡FιrëÞrË-þcÕÎõJÄç>ÿ³bšæªK¶²Ð\<÷«ë”þ¿°Ñ}€âï« ÄïÝØGà÷ƒÚ:åûA;\(§“Ïýfô Šk»œûÅØG¨®Sú͈ÍØv¥8ÑŒ¾KµXÐÊ>@µõ‹÷½]ã@1öjë”>‚ÐìëõöºùÜovàÒU•6‰D`š&üN„¢(…B~v8 BUU¿~®8Ðñxš¦ùÁÃq(k»“$ š¦ù'5²,—I’ jWz¾Ü1Ì_·Ù’É$‚Á`ÁÝ«yOÇÁÀÀ€¿n"‘(»\(B(B4-Ø~½ëW"†b‡Ãa(ŠÇqüà Tÿ¼Ö‰Düíº®ëÿa …B0 eÙÿœ‹;"‘HÅuE›mÛ.ØïN8xî7vî×:·kÅõÐèùWI¥¸RÜꦸ ö§Vl¨´®hw'ĆJÇïï|'víÚU6èèX°Q}€zž_œsõ¬[é\¯&# ús H’T0¿A=ØGh.žûÝÓÿ6¾PÎjcC§Æ±¯ÝØGà÷ƒîú~Ðêk•tê¹ßhŸ@´»ÏýrÇ€}„Ê:©ÐhhÖ¶óã„8ß›Ñw© ZÙèÔ﵎ ûÝÓGÖÿº°ùÎýf÷zr¹\®9owk‰Œ¬¸‹IÛ¶ýƒ)Ë2 Àã8H&“ˈØ u©‹÷­Þ²ŽãøúrÙèjÏ×Zw=öm5¯eY‚Á r¹œÿYXÍûÙèú•Žeþç±øõT|¾Û¶áºnÙ÷½¸ÝbÂc±\µuË­ß)xî×Öȹ½ç~³Ï¿jÇm5ûÑ q!»åbC­uË­ß®Š_=qèÌX°Ñ}€zžo†Fιv#å°Ð\<÷«k÷þ'»ë¹möš‹ßjk÷ïÅû¶š×ꤸ҉}‚rÛhWì#T×î}„â}[×j—S-´¢°–õ;ûµµ{¡U× 6ùßì>@×$Ëè¹¹9?{ ‹ÅÖ5ã^K~°ª¤Þn3·ÕÊýhTþÉßÌõ7bÛé8v žû«ÛV+÷hüü]/ÕÚµÞÇŸq¡q›!¬ÇöZµ@c± q„}„öÄsmÛkÕ~´k`­Ú×fˆ ÝÅ>ÏýJ6CXíµj?ÚU+¯lÔkl6›!6tS\hÕužû«×ñ¥V«Éæ+†G‹!ã­T©~v¾zï hæ¶Z¹íj#öq3ÇÆsuÛjå~tªõ><ÆÛ q`=¶×î¯ÛNØGhO<÷×¶½vÝNÁ¸Ð¾6Cl`\hžûa3ÄõØ^»¿n;a,èL›!60.¬/žûåuõˆG"""""""""""""Ú[ZÝ"""""""""""""ê|L<QØx$""""""""""""¢†1ñHDDDDDDDDDDDDD c⑈ˆˆˆˆˆˆˆˆˆˆˆˆÆÄ#5Œ‰G"""""""""""""jØ¥­nÀFøÌg>ƒ¹¹9ìØ±£ÕMÙP§OŸÆ®]»ZÝŒ uæÌlÛ¶ [·nmuS6ÔjßëK.¹¿ýÛ¿Ýêfo¸÷¿ÿýèëëku36ωÍcµïõ…  ñªW½ªÕMßPìl/^Ä… °sçÎV7eC­ö½>sæ Þ÷¾÷!´ºéêþáðøã·º«Ö©çr§öG:µÝk‰×]w~í×~­ÕMßPÙlùÈG:òïD§Æ¶»½Û½Y¿ÜÿýH¥Rضm[«›²*›éoT;èÔv¼fX¯~ô£xî¹çZÝŒ†têß«|Ûòur¼šÑ'؉Çééi¼ìe/Ãððp«›²¡&''ñ–·¼¥ÕÍØP¦ibpp/{ÙËZÝ” µÚ÷ú£ýè¦ìD|þóŸÇ_þå_¶ºŠçÄæ±Ú÷ú¡‡‚eY›îÂû›ÇC=„ùùyÜ~ûí­nʆZí{mš&Ž?¾éΉù—Á»ßýîV7cÕ:õ\îÔþH§¶{-ñï/ÿò/7]âñøñãÈf³ùw¢ScÛÝÞíÞ¬ß,ËÂîÝ»;.Öo¦¿Qí SÛ ðša½ÒétÇïw§þ½Êש±-_'Ç‹ü}h´OÐ6‰Çl6‹ÉÉIÜsÏ=Èf³ÆÄÄ –›œœÄÌÌ ²Ù,FFF011þþþªÛ¾ä’K°gÏžMwA¥··wÓís:Þ””Wû^OMMµºÉe­g¼X°Ù><'6µ¼×O=õT«›]ûÍ·Ï ÀûŒo¶ý^í{N§[ÝäŠê‰kí\~ùåùÙèÔs¹Sû#Ún`õño³~?¸þúë;òýíÔXÀv·»7ã÷ƒ­[·vd¬ßL£ÚE§¶›× ëëìØ±£#ßß|ú÷*_'Ƕ|/Š÷¡=¹\.×ꀣG"Ncbb@333H§Ó¸ûî»ýà ‡“““€»ï¾»ê¶'''1<<Üño6Q³ŒazzºÕÍ(±žq ÷›¨Òé´¾µö ˆ6N;ŸµbûDÍÓ®çÄzö Ú¹/DÔ í|NðûÑÆÙŒ}‚vÞo¢VhFŸ`K«wB˜™™Áøø8FFF0<<ŒcÇŽ!›ÍÜ…=;;‹ÑÑQŒŽŽúËÌÏÏcvv¶ÕÍ'¢&` "€±€ˆ<µbãQ÷cŸ€ˆÆ"b ê4m“x,–Íf ~ŸŸŸG&“)¸©¿¿ƒƒƒ8~üx«›KDë€q€ˆÆ"òäÇÆ¢Í‰}" ˆˆq€¨ÝµÍwÝu&''‘ÍfÑßß™™ âàÁƒ€¥¥%()}ÐÛÛ‹ùùùªÛ¾xñ"zè!ôöö–Ô}&ÚL2™ 2™ Ξ=ÛꦔµžqΞ=‹t:þþþºê»u«t:‡z/^luSÊÚˆ>A¹õ‰6“l6‹ãÇã±ÇkuS*ª Äѵö Ο?t:Íï´éÍÏÏcii çÏŸouSÊZïï=öÒé4öïß@ ÐêÝ%j~?à÷"^3ä5C"Àû~ÐŒ>AÛ$÷ïßÀ60??ñññ¦tþ/\¸€ùùyìܹ“hSËd2H§Óxúé§[Ý”²Ö3ÀÓO?t:ááav"hSK§Óxì±ÇÚöÛFô ºa¢o¢F,--ù± ]­g,‰Gq4Ñfuüøqd2™¶M<®÷÷‘xìïïoÛ~ÑFà÷~? â5C^3$¼ïóóó Ÿ[m‘xÌd28|ø0FGGý +çççqøðaô÷÷ctt´¡íïܹ·ß~;;´é‰ Óë¹Óg£­w€Ý»w74).Q·˜˜˜ð'Šn7ìmŒþþ~LLL`rr²ÕM)«V,hôbÀUW]Å>àÿ]ݬß^õªW1ßøý€ˆ× yÍÈ3::Šþþþ†ûm1Çãìì,²ÙlÁÉ-†JOþZ.øñ.e¢ÎÇ8@DcyêŒDÝ‹}" ˆˆq€¨µEⱞa›âΣâÉ`EY"êlŒD0‘§V,` ê~ìÀX@DŒD¨-ÃÃÃ8zô¨ÿX:Æ=÷ÜSPê`tt333Èf³€©©)Y"ê\ŒD0‘§žXÀ8°z®ë²,X–ÇqZÝ¢ªØ' "€±€ˆˆ:Q[Ìñ˜?ÇÌ=÷܃ÞÞ^d2ŒŽŽb||Ü_nbb‡Æ¡C‡Éd011Ѷ“_Qýˆ`, "O=± Ûâ@0„eY%«ªŠd2 I’üå •J•ÝŽ¦iÐu¹\ÎÌu]hšÃ0ªn›¨°O@Dc1u¢¶H<Þ ô‡C÷÷÷— ƒ¸ûî»ý‰-÷ïßÏÀAÔEˆ`, "O­XÐq@QÄãqÿw×uFF‘L&×¼]]×aš&R©TUX–Õ”m­'ö ˆ`, "Æ¢NÓ6‰GÀ ùã+©g"êLŒD0‘§žXÐMq@’$?1(ض ]×Ú®aˆD"ÛVU±X Ñh´æú–eA–eȲ¼¦×w]¶mCQŽ®¤UcŸ€ˆÆ"b ê$m1Ç#•·Ö„Ÿ IRÙ9C¡PÅ’­€7R²§§Á`‚뺀žžž’Ò°ùY–…žž†ƒAôõõAÓ´VN""""""ZGL<µ×uaY–ÿ#æeŒÅb m7 Á4M @Ó4?9Xn„¥à84MC"‘@.—ÃÂÂ\×]õèK]בJ¥ËåÇ¡ëzÉ\“DDDDDDÔ=ÚªÔ*ÑfeÛ6‚Á`Ác²,7\ž4CUU˜¦ Ó4ýäa(B,ƒ¢(%눒â9Y–×4dþöc±ÇišˆD"€‰ˆˆˆˆˆhÝqÄ#Q===Mÿ)GUUär¹‚ŸP(„p8\¶Têj¨ªŠD"……ÌÍÍ!ò,ƒA¿|jñòŠ¢`hhápº®C’¤²IÊZ¯›O–å’­DDDDDDÔ=˜x$"""""ª¢8ØŒŸzÅãqXsyRQ25Ÿ¢(ˆÅb˜››ƒëº·=77‡d2 Y– Jµ®FñhÍFGoQ{c⑈ˆˆˆˆ¨M‰ÑˆkM؉yMÓ,y®Ú6-Ë‚®ë…BˆÇ㘛›C,«8Çc¹Q“b;ùÇYõ¨I""""""êœã‘ˆˆˆˆˆ¨ ¸®[’¨%NóçD,·PZÖðF7ªªêoG,ãº.4M+Ù¶ FJŠ’«‚,Ëþÿ-Ëò·Wi$¤®ëPU’$Á¶m†Áù‰ˆˆˆˆˆºDDDDDDmÀ¶mƒÁ‚ÇEA*•*Xn9K¸&“I„Ãá’udYF2™,;ò1‰À4M AQŽÉD"þèG˲àº.TU­˜øìë냢(°m‘HÄ/KDDDDDD݇‰G"""""¢K¥RMY.—$ö$IB*•‚ã8~(?B²øµlÛö˨*Šâ')ãñ8B¡\×…$I˧& D"‘šËQw`⑈ˆˆˆˆhe¹ Tj=ª% ëM"2ÙHDDDDD´yliuˆˆˆˆˆˆˆˆˆˆˆˆˆ¨ó1ñHDDDDDDM%æ¦$"""""¢Í…‰G""""""j*I’jÎ!IDDDDDD݇‰G"""""""""""""jØ¥­n­?×uaÛ6@–eȲÜê&Q—áˆG"""""¢ ƒèéé)ù ƒp]·`¹`0Xq;𦡧§§à1×uFÑ××ç¯?00P²m""""""¢F1ñHDDDDDÔEA*•ò’É$lÛF4mh»º®Ã4M¤R)är9är9¤R)8ŽÓ𶉈ˆˆˆˆˆò±Ô*Q$ ªª>DDDDDDÔ>š’xÌf³Ñ#G055…©©)ÀÔÔn»í6ÌÏÏ·z?‰ˆˆˆˆˆÖD×u8ŽÓ4aYLÓ,ø¿ã8þ2ÅÿVZ§‘°?š¦Á0 Äb±†Ú …`š& i,ËP~„e¾p8 UU±¸¸ˆÅÅE¨ªê' Å¿‹‹‹ÈårþèÉü§aH&“Èår˜››ƒeY~rR´)ŽIÓ4¡(JÙ‘•DDDDDDÔšRjÕ0 ?~ÓÓÓƾ}ûwÝu&''qøða|ñ‹_D hõþ­ŠX-!&–)þw5I4Û¶ FÞhGI’j<‡ªª~òS”n …BˆÅbeÛ(ªñxÜýX,Çqð·û·p Ï™¦ Ã0Çýí‹m+ŠUUýÄd(‚$I0M‘HÄMñ""""""êLMñ833ƒH$‚ááá‚ÇûûûñÁ~ÙlÇoõ¾µ-UU‘Ëå ~B¡ÂápÙR©«Ýv"‘ÀÂÂæææÇaY‚Á`Á¨CÁ¶m(ŠRô”e©TʯhS\VUÕ‚2©ÕFS^òQŒ¾eh™x$"""""êlM+µ:88Xö91Ê‘åV‰ˆˆˆˆˆVGŒÌŸ?q5Ǧi)Š‚X,†¹¹9¸®[qÛŽ´¬EŒÂm£ ‰ˆˆˆˆˆ¨s5%ñ888ˆÙÙٲϥÓi( IDDDDDDՉшkMȹ® ]×ËÎ+Ym›²,û£ó· ±gÏž‚¶ –e•Œ‚¬&¿Üªiš…BsP‰ˆˆˆˆˆhÝ4eŽÇH$‚#GŽFFFx ÇL&ƒÉÉI WIDDDDDD^"¯8Ù§ë:$I*(AZn9 |iS1·¢ØŽXÆu]hšV²m! AÓ4D£Q$ ¿-¶m#•Jáþà išÿœa°mÛ¡Y¯H$â·ƒ‰G"""""¢Î×”ÄãÈÈîºë.LNNbff066ÅÄÄD«÷“ˆˆˆˆˆ¨­Ù¶`0Xð˜¢(H¥R£Ë-¹\®ìv“É$ÂápÉ:²,#™L–ù(Iâñ84M󓜮ëú‰ÅT*…`0Ó4!IÇA<¯9¯c±P(]×9·#Q—hJâ1NcxxßúÖ·üÒª°ÿ~ŽG""""""*/•J5e¹x<^2êP’$¤R)8ŽÇqüÇk% #‘B¡lÛà%AE’RQ,,,øÏɲ\Pfµ\´\ÛE©˜0%"""""¢ÎÓ”99âtöV›tœ…ªªØ·oTU-;oäää$8€}ûöáÈ‘#Èd2­>†DÔDŒD0‘§V,`XY–¡ªªÿSQžUUÕ’‘‘ùÏ­fnG¢Õ`Ÿ€ˆÆ"b ê$MIŒDÄ8@Ôiš’xÌd2èííEoo/g2ÌÏÏ—$';æÿ~~™LÃÃÃþcýýýÄñãÇ<ˆ:ãŒDä© º1H’EQJæg,‹ÅXÖ”6ö ˆ`, "Æ¢NÔ”Äc­ÑŒµˆde?Ž=ŠL&ƒþþ~ŒŽŽbpp°´´Áz{{1??¿áŽˆš‹q€ˆÆ"òÔŠÝ\×õçL¬¦\bÒ¶mH’T5!é8Ç©¸ýz¶A´‘Ø' "€±€ˆˆ:QSæx2™ ¦¦¦099‰ÉÉI¤ÓéU­èÐ! "“ÉàðáÃM §OŸöÛD´™ÍÌÌ`ll 'OžluS*Z¯8'OžÄØØfffZ½›D-566†ÉÉIœ>}ºÕM©h½ûccc­ÞE¢–šŸŸÇØØ>÷¹Ïµº)U­W,8uê” ;MOO_’Õ¶m `hhÐ4­¤d«ëºƒ@0D__ Ãð·¥ëzÁ6‚Á`«w‘6ø›xêÔ©V7¥¢õü~ð¹Ï}ccc¼ I›¿ðû¯òš!?ÖhŸ )#àèÑ£%'æÔÔúûûqìØ1ÿîƒj"‘ˆ_§TUÅÌÌ îºë®†Ú¶k×.¼å-o)¹ãh³uÎÛ¹C½^qöìÙƒéééVï"QËMOO#N¯ú¡Ä>ÑúÄôôtÛ'Þ*Å‚FK%íÞ½»íú’$Áqœ²ó<Š2¬Å¢Ñ(TUõGAƒA8ŽS°L8†ëºXXX€,ËÐuÑhÔÙh’É$EmÛ‚aˆD"­>$´Dõ¢ÍúýàMozS܈º¿ðû¯òš!à}?hFŸ )‰ÇÉÉIÌÌÌ`bb£££€t:ÉÉI9r¤ìèbbâWadd¤ä®…ùùù’$f=IM"ê ŒD0‘§V,ذ8P<0´ü¯ @Yþ]+Z&ž÷X€ÀÎ{>U¸¸ëº°m»ìˆCUU‘J®`Û6lÛF2™„$I€D"¡¡¡‚e,Ëò“Ž€7G¤mÛþ¨ÇP(ä'5Eªª%ÉK¢VbŸ€ˆÆ"b ê$M)µ:;;‹ññqŒûIGÀ«©|ìØ1d2™ªÒýû÷Ž?^ð¸¨ß,¶Un™t:þþþF"jãŒDä© 6<ÄŠ~Ô埼¤¢\f¹hùPÑóe¨ªŠ\.WòSœtÓ4Kæd,)ˆ†a@Ó4ÿÇu]¸®ë¿&Q;bŸ€ˆÆ"b êDMIìO$›Éd011Q0Ê’ˆ:ãŒDä© 6{Pº®Ãu]?Y\"5¿¼j~’Ò0ŒšIK¢vÀ>ŒDÄ8@Ôiš’xÁÔÔààÁƒôË«NNNbpp°æ$Íýýý¸ûî»ý’¬ýýý%à@Á2û÷ïgà ê"ŒD0‘§V,è¶8 IÇeYeŸW¥ Y¨ª*$I‚¦iH$M+œhRUUȲ\°ŒmÛˆF£þïDíŒ}" ˆˆq€¨Ó4%ñ811À¾,‚˜ç±^µ”õ.CD‹q€ˆÆ"òÔ:Ï»%¸® Û¶ Ë>ŸJ¥ æc”$ ©T Á`–eÁuݲåS“É$Âá0úúú Ë2lÛF,C$A4mõnÕ…}" ˆˆq€¨S4%ñxÉÇH$‚ãÇc~~Þ¿ë V‰U"""""¢Í.•JÕµ\.—óÿ¯( `Û6$I‚,Ë0 £`y±ŒI)˲_‚5[«mQ9MK<ÎÌÌ`vv8pd-e"""""¢&r]}}}#!u]‡$I##…r5[SSSS˜œœÄððpA‚qtt3338~ü8î¾ûîVï+QW$ ‰DÁ`ªªÂu]8ŽÃ¹‰ˆˆˆˆˆ¨¥š’xœ™™Áèè(îºë®‚Ç'&&pðàA:tétšõ•‰ˆˆˆˆˆjpŽãðJ¥J’Tv¹H$UUëZ¶“ˆù.ÂÒ°DDDDDDÔþ¶4c#™L###eŸs<ÎÏÏ·z_‰ˆˆˆˆˆÚ–mÛƒ@0D0D__¢Ñ(\×-»Ž,ËPUªª6=é ÑÓÓSò  Ú#ÚZ‹(ÛÓÓãÏ9Yü|4E__Ÿ¿Mq,*í?µ—¦$ûûû‘N§Ë>—Éd¬$ ‰ˆˆˆˆˆ¨H:º®‹T*…\.‡\.‡d2 ˲Z–|S©TÊÿI&“°mÑhtÕÛ2M®ëB–e˜¦Yò¼®ë0M³`ÿS©ÇYÓëÑÆkJ©Õ‘‘LMM¡··£££þ<³³³0 ýýý,³JDDDDDT¦i$ ©Tª`äb(‚ªª€¦i%s8в¤ÕʬŠÒ­ªª–}Þ¶mH’T¶¤©$I%ëÙ¶ ]×W½–e! A–e†Q²/†aøåcUU‹Å˜x$"""""êMñ811ññqLNNâÀØ·oöíÛ‡#GŽŽ;Öêý$"""""jKŽãÀ²,Äb±²ÉCI’‰D`/×ÓÓÃ0üR¤}}}Ð4­`=×u Ê•öõõùÛèéé®ëÀÐпL½V;ï¢ëº0Mªª" ù¿律¯2_(B*•jÍ›CDDDDDD«Ò”€—|E:öË«s¤#Q¶mðl•¨ª ]× æFÔu©T Š¢@×uhšY–‰Dáp®ëbaa²,C×uD£Q?ih’É$EmÛòG ®ë¼¦eY0 ñx|Uûhš&$IB(òGWŠB(ò“¡b¤§˜»²ÒhM""""""j/kJ<ÎÏÏãž{îÁÁƒ ænìïïÇèèh«÷‰ˆˆˆˆˆ¨yòoYö~×–“‡>EòG/Ú¶·œ—H‰ÇJ¥R½—,a‹Å (ŠÿÇq`š&"‘lÛ†eY~ÒQ,cÛ¶?ê1 ùë+ŠUUKFй'‹ÛR­­å†á'Åk뺎x<î?Ç¡ª*LÓ„iš~9×P(T°¯DDDDDDÔ¾Ö”xìïïG? ÃÀüüÃPÈÇ)]&÷’‚i&'ó"¡æºnÕy‹s'æ//~ܼäg=£UU-)sªiÂápAR³Çq`Û6dYöËÁŠvˆDiþë‰v‰ä©é¹°°°ê„'m¬5Íñ0::ŠcÇŽáî»ïF?Òé4TUÅÑ£G1;;Ûêý""""""jŽTªð'?éx ÆâeŠGçÅã…Ϭî-[<ça>1*2?YXœ„Ëÿ=?ÁXüZÕJºÖC”Y-NjV"ʬº® Û¶aÛ6Ç$I~WÇqJæ¨T±X sssp]·î×#"""""¢ÖixŽG‘„fgg‘N§qçwús<•ˆˆˆˆˆ¨†Qñ9Ó4 aÛ¶Ÿx¬”`#5Mó—q]·)I=‘Ø,ÞV¹‘®ë"¨>âR´±RÒt-Ö”xÉÅü7BÌï(J«?ÞŒº°DDDDDDDDDDDDDÍT.éæº.lÛ†eYP¥ é'Fæ—(¥V À®ëÐuݮҨDñÚ†a”l;ŸØŽeYÀÐп|¹¤©®ëpÇOš–#æ«Ìßÿ¿û»¿Ãüㆎåš@ãã㘚šÂ¡C‡pèÐ!¤ÓiŒûËÌÏÏãèÑ£˜ššÂøøxIYV""""""òƒAôôôÀ4ͲÏkš†žžhšV°Nþï‚aèééñ¿|ƒÁŠ_4‰ˆˆˆˆˆ6»J#-Ë‚®ë°mªªú ÁP(ä/“?¯£é8b±,˪šp4Mƒ¦iþw¸h4Z2ߢø]×uH’×uaY–ÿšùË»® Ã0 ( ¢ÑhŦiúëå'¿ùÍo6t<×”x€‰‰ Üu×]èííEoo/ÆÇÇ111á??99‰™™™’ljˆˆˆˆˆ¨¼â/—B¥„d1Ã0F‘H$‰DZ½;DDDDDDmK$+%mÛ†iš°mÛÿ~eÛvÁb]‘p%KEr²¸ jñ눤¡ªª°, ¦iú¯©iü£Øf(B(òGc+åTÃá0LÓ„$IˆD"#3ËíŸëº‡ëºˆÅb8sæ nºé¦†Žëš0::ŠééiLOO—$'&&ððÃ3éHDDDDDT‡P(T6Á(¾ ֚בIG"""""¢ú‰†•æ7´, ’$A’$?Ùèº.$I°’Ìë‹Ç@Q?9¨ªª¿ýü’ªÑhÔoC<‡mÛˆF£$ ¶mûIK12Q|ÏSŠ¢ø JÑÃ0`š&4Mó““¢Ýå¦ibÇŽøÄ'>EQ Ë2vî܉W¼â ׆N§‘N§1??_ðøàà`£›&"""""Ú4dY†$I%ÉGÓ4 Jù”ä#QýŠK¤ŠÅtb~Çx<îß*þU¥`bY‘Ï' ÌÍÍ! •Ì )J«ŠÑ‰²,ûÉÊD"á?‹Å`dY†ªªþ2b›¦iúóOš¦ Y–áº.B¡$IÂÜÜœßnÇq‡¬ŒÔ|ë[ߊ‹/"CQ¼ñoløØ^ºÖçççqäÈd2ÿ±ÑÑQÜu×]õ¹ """""ZwÅÓ(Ї–Ȳ÷ûòMª¾Hdå1UÇûâñò¯%F=æ'MÓD<÷ï„-&’Ž‘H„IG"""""Úô\×E8F*•ª¸ŒH+‰G17b<‡eYe‘HÄO$æËõè8ŽŸp,Y¨(JÁHHñš–eùßÿDb0‘Hl# ùÏå—YÛ[XX€®ëPUÑhÔ, úmË~ík_ó¤bîÊH$‚_ú¥_Âüü<æææpÛm·axx¸áã¿æ“““XZZÂøø8¦§§122‚™™LNN6Ü("""""¢ÍH|ñwÊ»g+xIÇP(Ã0Ê–""""""ê&•nÊDrM$ù*q]º®—|ÿàÏ»¬ŒpåHóIB‘¨?ùòË´Š„§ã8ˆÅb%ÛËK’俞,ËþwB±ŽX.‘H@UUŽFI’J®²,ã;ßù4MÃÜÜ~÷w–e!‹áŸøn¿ývÿf×t:Ýðû³¦Äc&“A:ÆÄÄ&&&0<<ŒcÇŽapp°¤äêZd³Y8p ìNNNâÀØ·o_ɈK"êŒD0‘§R,ب8þ¨ª÷{#e¹t™üÇTÕ[.ÿùJÄKQnÕ0ŒšeVçææL&¡ª*Âá°ÿE™¨›°O@Dc1§Ü|…«%nÚó!(ø.•?1_~RQ$6%IòG=–K<æo3ÙüDf1EQü×ÅbeG] ’$! !‹Áqœ‚–âyÀûî ñãÿº®C–eÄb1Äãq?‰¹sçNœ;w®¡c»æÄ#ô÷÷<ÞŒ!˜päÈd³Ù’Ç'''133ƒ‰‰ LOO#“ÉàÈ‘#MyM"j/ŒD0‘§\,èæ8 …ü/°•¾ì ùe‰„Ç.Q·aŸ€ˆÆ"b mÛU“õ$&ó“Œâ;WþhG%7' óçuPWâQUU¾FñÚå¾ó…B!;õL©‘L&áº.†††`Y–ŸXußùÎwðéO¿ÿû¿×uñ…/| €`0Xp¼î½÷^<ùä“ ½?k.µº^¦¦¦°´´Tö¹ÙÙYŒŽŽbttÔe9??ÙÙÙV7›ˆšˆq€ˆÆ"òTŠÝD¹UQ>¨ÖˆGA–eÄãqèº^³¤Q'aŸ€ˆÆ"b ¢Ti1Q9F÷9ÌÏÏcbb¢ìEL¢Í‚ßøý€ˆ× yͰݙ¦‰X, ´|ª¦i~òL”3J‰º®|Çr§ é'ËrAR±RB0¿*(ÕZOÒÀšn, “¬"±š¿­T*Û¶aÛvAûTUõo6M¥R%ûTœtœœœD:n¸O°¦ÄcSOòt:™™Ü}÷ÝMÛf¾]»vá-oyKÛ^T!Ú(¢Îy¥›Zi½ãìÙ³‡_$ˆLOO#N7|÷Òz`Ÿ€hc bzz“““­nJYë vïÞÍ>à'Þ7ë÷ƒ7½éMmsóQ+ñû¿ñš!¯¶;1u„ªªó0^B1‹ùåN]×…ëºe¹ ,kq²RÉV±l¥ò§ùÉ:‘ü«§Tj=åX+ ‡ÃH$~e]×177EQ ë:ïæÕjsZÖ3²rbb¢)}‚5'›Ù9O§ÓèííÅÑ£G /wÇÑüü|Ɉ¼3‘¨ó1ÀX@DžZ±@ÜÉ8@Ô½Ø' "€±€ˆÈ“?Â϶mD"‘’Ä¡¢($Éù‹ÅüDœã8e縯4±žŒb®Æzɲ¼¦†aø#u]÷ËÊähþ6‹«æ´JÓæxL§Ó~½äÁÁÁUÝ)4::Z²|:ÆÁƒýÀ ž?~üxA°H§ÓiÝ$¢¦` "€±€ˆ<µbãQ÷cŸ€ˆÆ"bØŒÊ6´,Ë/µ*æ{ÌO$êºî'Å@UUaš¦¿ŽØŽªªUG µ’„«M"ʲ\w¢Ò0 „B!¸®‹h4Š……8ŽÓ4¡ª*‰,Ë‚eY‡ÃSm´ƒ†Ùl†a`ffÙl¶à¹@ €ÑÑQD"ªÛéïïGÉãÅ ÌÑÑQÌÌÌààÁƒ˜ššB ÀÁƒ[}‰¨AŒD0‘§žXÀ8@ÔÝØ' "€±€ˆ6#Ó4 tù£EQUUhšV2'£(µšŸ¤ÌgYVA)Ö‰DêZζmD£Q8Ž×u±°°Y–Çý–e!"™L¶Í(Ç|kN|óóóþ]"Á˜Íf‘N§155…t:üã5“õ˜˜˜ÀáÇqèÐ!d2LLL4eÛDÔˆ`, "Æ"ò0ÀX@DŒÝ$4b4õç&‰Çü‘ƒù%QeY†$IˆÅbˆÇãþsùˈѡP¨dÄ¢HDªªZ¶,k3išY–ýd¤ëº‡Ã~Ûæææ`Û6\×-;7£ªªˆD"ˆF£˜››Û€weuÖœxœœœD&“ÁôôtÙ²ª###Á‘#G099‰»îºkUÛøá‡K ¸ûî»ý‰-÷ïßÏÀAÔň`, "Oq,` Ú|Ø' "€±€ˆ6Û¶!I Ã(y<¤b¹’©b $Ieº®C’$?'ILÓD"‘(X¯8ÁW.á×,¢lj~âQQ8ŽÃ0077W³,k,C,[×v®Õš™L333¯:—ãðð0FGG155ÕÔ» V3$u'Æ" ˆˆq€ˆ<ŒD0ã@·p–eA–e8Žã'×òK¤Ö“(ŒÅbÐ4 ‘HŠ¢ ò,hšVqŽF±zçc\˾‰ÑŽbD£a~ûêÕŽ GaËZVÊd2¼ºÉµˆeŽ?Þê}%"""""""""""¢6fÛ6LÓD<‡ªªþhÀü$dqb°\¢P$÷ÄóŠ¢ ‰@–åŠs<®÷Ü®ëÂqèº^0¢s£çœ\OkJ<ŠáÊå&u-&–ë F×u¡ª*âñ8Eëº#•¥µä—d•$©¤Ìj¾fŒ$ûPü˜hs(B"‘@(òÛ¶^#,[aM‰G1\YŒ|¬F,Ã!ÎDDDDDDDDDDDDdÛ¶ŸŒ3MÓ\Ì(æeTÅ/‹Z<Ç£a$ ªªVLªª ˲J«DŒŒl„išûÁ`Ñh–eÁ¶m¸®‹’e7XSâqÿþý€™™™šËŠeÄ:DDDDDDDDDDDD´yišæ—5M³`T"P:PŒx,—L¥R ' ÅúŠ¢TYŽh[¾üd§ã8þü’²,û£8c± ÃXÕÜŽàÒµ¬0::Š©©)ìß¿###e—›ÅÔÔFGGZ½¯DDDDDDDDDDDDÔŽã””Jÿš¦Y<,žóP$&óçx‰¼jÄóÕF9æoWŒ²¬Åu]Ó4áº.b±\×…¦iH¥Rp¶mûmO¥R#3ÇA(jÕÛ±nÖ”x€‰‰ ?~GŽÁÈȆ‡‡ýù3™ Òé4fgg188ˆ‰‰‰Vï'µ€mÛ°, ±XÌL”µ,ËÀ/³*ˆÿ—KÖš“±Þ9%I*h[5ŽãŒT,N€& D£Q?±‹Å IRI’4™LnÌÁÏç°HÖiZÉ5'>þñÃ0 ÌÌÌ`vv¶äùññqD"Žv$"""""""""""Ú¤,Ë*(G*F?Šä£õ `^Gñ;Pq-V3·£a£5c±‚Á EaPUÉd²,¯k›×Ä\þn}^b͉GÀK.NLL`bbétºà¹ááá 8BDDDDDDDDDDDDÔÎÇ))3*~dY†,ËþœŠ¢”-¡Z«¬j9ªªB×õ¦&%Iò¦†aÀ4MÄãqH’UU …ÖÔÖ ¡˜ƒ7òѰÍl(ñ˜‰F""""""""""""*fYVÙù E™RI’ FDÖJ<Ö;:q­ËWÛÓ4aÛ¶_JU$ƒÁ ŸDm[6^ÂQoþKlYï}˜œœÄ¾}ûÖûeˆˆˆˆˆˆˆˆˆˆˆˆ¨Íˆ‘ù‰EÁ¶í‚Žªªús'æ+YïFY–ëž»±^¡Psss€¡¡!ôc2™D$Ù˜ƒÚ(€¹>›^÷Ä#mN–e€Ÿ +~N$ÅråH’TvÔb­‘Œ²,—Md®•®ë…BÐu†a ™LúóQVjc[Rà•Z]L<QSX–UDó8æÿx£%IB$©9‚Q’¤²Ë4sîÆüökšVð˜¦i‚$I~2S’$躾¡Ç¶iD~Ônþ¦›6Ç#mN®ëB’$˜¦WÃSŒ´m»lâ€_š´ž‘‹Õ~o&I’`\×…ëºp‘H‰DÂo§,ËPUµ½çs,GÁÊ¼Ž xs=6G<Ñš9ŽÓ4á8 Àišs:ʲ\RjUQ”’ù+`,ž;q=~"Q*Fm*Š‚P(T’w+s;:ÖaÀ&G<ÑšY–å'UUõ‘"a(IRAâQ$E¢Qü[)¡¸Ñ# #‘HI²³+˜X—òªùÖ”xL§ÓkÁ!"""""""""""¢vbÛ6Ç$IPŠ¢ø‰F˲ü²«BñœµJ­–“J¥Ö´^5ùóOv¥=6ð˜ l5š?bsM‰ÇÞÞ^ ·úðQ‹‰²¤’$! Á¶mØöÊкüD^~ ÖF439(ŽÑhÔOžv¥¯˜Àƒ6`JÀÇ5à5! É;×”xÄôôt«µëºeTeY†$I‰G‘Ès]·àñ|•æwl„a%%S‹G`Š9)c±dYöGlv¥“NˆF×26`+@wwËZVšŸŸÇØØæçç[}ˆˆˆˆˆˆˆˆˆˆˆˆˆhéºMÓx‰¼ü9EÒβ,$¤P)é(ÖkvòQ×õ‚ß-ËB8.ûÚº®C’$D£Ñ=˜é Ø.Š$À«XX~?µ¦KKKH§ÓXZZ*x|ß¾}ÇÄÄD«5™¦i~’.‰@×u¨ª Çqü‘ù#E2±ÖœŽñx¼ Ù(1Óq»’$!öm(Šâ'O#‘4Mƒ,ˈÇã­>Äëk $@’€ ÀŠ–…ˇ†ÞüšF<Ñæâ8t]G*•‚$IZNT‰¤a~‚€ŸàP³|i³G<º®[PfU×uƒA@0„ëºeªªB–e$“ID"Äb±Væõ3šþê%  k¶ „B¸þïþ®á—XÓˆG""""""""""""ÚA–e8ŽSŒ´m»`d3¸®‹h4êÏ5)Ë2 Ã$–iº®Œ¨TŠ¢øÉÊMÃXþ7¿š¬ ÀVßN½õ­@:ÝÐK0ñHDDDDDDDDDDDDY–˲üD€’²¨Å#%I‚ã8~r/¿üj~ Ôf£.]×…išˆÅbþhËx<Žd2Yv½f&@Ûš®–(©Òç"†àÍ÷ØL<QEš¦!‰øs8–SœÄs'ŠÄ£ªªÐ4 ®ë6e¤¡9iš&LÓD*•‚mÛ~9WEQº{¾ÆÕ°m@QJK­^¹Õ9:€·4þR %ÇÆÆJ›ššÂÔÔTÉã?üðú,""""""""""""Zº®Ãq¤R©U­W<ª1 AÓ´¦•7B2™„ªªþcŠ¢ ™LÂ0 hšæÏG¹é™&J•/µ*èÀåC—7üRkJ<ö÷÷c||¼…GˆˆˆˆˆˆˆˆˆˆˆˆˆÖ“ã8Ðu‰D¢¤´êjI’„P(TuÔd-º®CUU(ŠâpÔu½$É)Ž›¦”j5á0 I€ª&€ro£ @z¿Õ ¼°±—[sâqbb¢Õ‡ŠˆˆˆˆˆˆˆˆˆˆˆˆÖ‰®ëP¥i£C¡Ðš˜–eÁ0 ¨ª ˲ Ç¡(JI2S’$X–Õp²´+Äã^â•r±*pÕ·®6ör[Z½¿B6›ÅÑ£GqàÀìÛ·ªªbvv¶d¹ÉÉI™#GŽ “É´ºéDÔ$ŒD0‘§žXÀ8@ÔÝØ' "€±€ˆZI$úâñxã[Öè(DI’ຮ_R5‹Áqœ’£$I ¬ì*²¼’x¬F¶=¶­á—k8ñ833ãŸä333+ûSË‘#GpÏ=÷àƒü ¦§§122‚#GŽÉÉIÌÌÌ`bbÓÓÓÈd28räHÈÚãQc,Ë*yÌu]hšÖꦭ cµcãQ÷cŸ€ˆÆ"bh×uF‹ÅÚ¢\©mÛ0 ²,ûåUmÛà•ƒ-—dlÖ(ͦsœÖ½¶¯¬j9*pò'~‰5'³Ù,:„£Gâøñã€L&ƒt:ÁÁA¤Ói,--Õœ2›Í"Nãƒü FFF0<<Œ‰‰ âž{îñ—›Åèè(FGG1<<ŒcÇŽa~~¾ìÝ DÔYˆcYÂápÉ㺮Ã0 8Žƒp8Œh4Úê¦VÅX@D@}±€q€¨»±O@Dc1´‚ã80 š¦A’$Äb±–·§¯¯–eA–eÄãñ’ù+•omÛÄ£ae4i®[ø˜ŒÊ‰GƒïÄžG÷4ô²kN<ÞyçÈd28vìXÉ|8vìî¾ûnd2d³ÙªÛÊd2Æàà`Áãû÷ï÷ןŸ÷—úûû188è'>‰¨s15F×u¸® Ó4¡ë:øw‰;ÔDÇÑÚˆŽÍ1P;0u?ö ˆ`, "Æäº. ÀišˆF£0 ‰D¢ås$:ŽƒX,†H$‚x<Ó4¡i,Ë‚»œT«T ¶Fj–eÛÞÏzr .]i¨riðì¾³¸üÜå ½ôš™L³³³ˆD"©¸Üàà &&&pçwVÝÞàà ¦§§Ñßßï?–ÍfqÏ=÷øeii ‚ôööb~~¾êöOŸ>ÉÉILNN6t°ˆ:(‡|òdãÃ¥›m½ãœ÷¹Ïall¬®e‰º™ø›xúôéV7¥¿m ^3ä5CÀ«¦¥i Ã@,ÃÜÜ\ËwÑhÔ¿±> ŒhŒÅb~¢±î¤h»MCdÛë_nU×Uʽ‡ÞÖÉÉIüÑu„úhè¥×œx€ÑÑÑšË ýýý%ÉE±L­;çççqèÐ!X–…‰‰‰²£ÜÐhÞHÔ¨[™¦¹ªeÃá0B¡æææ`Y,ËB2™D"‘€ëºH$þó‰DÂïdI’„D"Y–ý»ÔEñË­Še$IÂÃ?Œ›nº©Õ‡¦,Æ"ꋌDÝ}" ˆˆq`#X–åÏ¥˜ŸäÛ®ëúÓ¥R)ÄãqÄãq(Š‚X,†D"Q²N8ö¯UÙ000à%኱˜—…[ïr§«ahÖ ÌHX~ÇÛUÓô~ô€´Ã;,åœzë)|õM_mèå×”xÜ¿?ÔUóX,“_ƒ¹œ#GŽààÁƒ8vìXÙeEB³x2Øt:]sÛDÔ¨[™¦é—M¥PÇA4õ„ápCCCˆF£eÙï`-,, •J! ùwt©yw+•»³K$-ËòkÝçO²-ÊPlß¾½Õ‡¦,Æ"ªÇÆ¢Í}" ˆˆq`½éºŽp8ŒX,æß°¾Q4Mó_;‹ù#ïú•(¿ZLQ”ÊeVûúVʨF"ÞèÂ⥠Ö_rUÓ¼ÌÝj†—ùËg°¼× :€`³Ì¼‘º ­$€…×ÊÍ•Ͱ¦R«@ãã㘚šBÅÚÇ333˜ššÂèèhÕŒDÄ8°ÞDyS‘øÛH®ë" ! UL"в«ÅR©Tå©$yYµP¨pŽCMó2pɤ÷\"„ÃÞs¦éý_Q¼‘‚ÅÛóDÎÍÕsP½qMÎq`ýÕÃþæ7 õõÀø¥O@ùz €I° ÿ;üGÙKB®vúR×õ’¨Šâí×ò.éºw"‘œ©r“wˆ4­ü¡jÔš€7Âb~~GÅìì,ý; Òé4Òé4æçç188ˆ‰‰‰ªÛãÈ‘#%Ï ûŒDÄ8°Þ4MóKšn¤p8 Û¶¡ªjÙRªB¥¤¤-N”S]XXIªêJ6-ŸØÎòu>W’!‰ëqªê%ìlÛÛ^$²2ÿ£˜1/9—>x ʼģ©Ä> „ž°`ÿä¸êV ô[ð2² À¾e¡ˆ7rå ò2‚Å×£Q?Áè'¿Í¶í%ó§’ô‹¦ÅÈ@þ–w˜dyåeše͉Ç@ €ééiLMMaffétSSSþóýýý¯™t¼ PÏr@wß}·löïßÏÀAÔ%¨‰‘ŠùeJÅHÂH$Ã0 I"‘ˆ_"µ¸£fš¦÷–$I…B°, ªªB’$(ŠRµƒµb®G·B©UUqï½÷¶úð–ÅX@D@}±€q€¨»±O@Dc1¬'˲`š&6äõDÉT1бÚHG¡få/qÓ}~bNQJK›ŠÇóþF½Áþú"3Wܦåù'Kæ‰t]ï9#~£½ú¦ŽÝ”!ËÞ Jóï^|å2,<8#€ñ=ÀyÅç þ—=°¿Ž 8_”Ÿ¡7ß ¹÷ÿBúÇ?÷Ú&®7†÷»a¬”‹íëóÚœLúÇÁ²ªTÕ9îíŽØ¥žo2…ÓÖd͉Ga||ãããÈd2Èd2¼¤ãzÖN#+‰hób `YlÛ.H<†×u‰D`š&dYF$ñ'ás6Š9-Ë*™ì:¿ÓTµ4Dƒ*mW–eìÛ·¯Õ‡·) ˆˆq€ˆÆ"ò0ã@ý4MóçU܆ab±XÉõ¶5³íÒ‘¡—UtœÂш² ÷Ö_¶\‘Ô4½äœäÈÏ5'ãñò"Æã@0èý„B…‰KYFôõ߃ùŒŒxÜ{Ú4·!öû^nÐÜØi@ùå×À~Ük‹¢Ê›ù;€öÅ7@½p?b¯‹E4M¯-‘ÈÊ~/,”Œº¬šÏµ%%UµdzȆ4œxÖ;ÙHDD´‘ÄÜŒ’$Á4M¨ªê'%I‚¦i°m¶mûIÇT*åw¢t]÷çu¬ÖÛÈ »…êPQkä`s]áåù ãñ8Âá0\×ݰ«ápØåèºnÍ‘Žu3ÍÒ¡’ä 1,ºþå8€ôßþŒ7òr*Ëú ú(€`ÿO*`>·ReÕß^¹‘—b>H‘Á̉ÀùØ bï^ÉGÆã+3ã·Â›Çq¹‰»08#}p<üßþÂ9“Io”e~Ë\ç¹É²b+¯›¿ ‘xüë¿ÞƒsçÎ6ô¶4-ñHDDÔîD21’÷—W$<®ë:dY†ªªÐ4ÍŸïQQ„B!hš†P(Û¶FýŽªªÂu] @×u$‹Ë-´‰w¾ó%“²Qç‹F½jœ©”—|Ó @0„¢(H¥RëÞq³¾¸f ýêaUF•ÌÙ2×õ’å’‚y5C]×KąÀ$½ÒÝ7ïåߤ›ã×ëwói@¾P^D]o³5K*Jùá…¡ìÿþ"Äòž*{ PQ’àÍÁ(À­ÞèÄ(¼бåÔ1e“¨ÄZïØƒPÈ[Ö0€}ûÎâôéSõ­XDDÔ5,Ë‚aH$þHBÛ¶¡( \×E0„mÛp†a@–eÿyQ"Uü˜¦é—Hs1ʲ ×u¡ªª‡–eY°,« Ã$æXëm„hÔ„77çM5˜JyeN#‘$IB4]בޢJX*•òoÖ·m‘HÉd¦i¶íÊó7º®·•’z‚$•ίXÄq¼MY–7ªP$Ø$°ß ½Ë{<þy0þ ˆÿ0þ/C1P’j”0Í'ˈÿiå+]2TÇòÚ½°@‚—x4Ô1奘߱âk—IzJ00 ¦|'N0ñHDD˲ü»¦‚Á âñ8lÛ†®ëH¥R0MÓOêºîw¶Ä‹Á`š¦ùÉÅ……?yY®üƒH(*ŠR¶³Vsòk""""""""¢&Òu/é˜JùS ⳟý,lÛF2™„,ËþÄõàº.t]G"‘ð“¦i\G×Þ*2ŒÂ¤£È¦Åã+%M뜺HL¿(ËEåSÈW±·¬<ÿEo¥,q ¯ðFI.Jƒ¢x‰ÈzX–÷>T´™BåÄãòîùs.†8ûý€þ¨wTue°§axû(’Ž©TCTôœ,¯L™NŸÇ‰õíg%L<QÇÒuÝOú‰db<G4E0¿Œƒ$Iþ„ÙŽã QT–@<—H$à8NKæ^lÓ,_e‚ˆˆˆˆˆˆˆˆº“ey‰#‘t€·½ín|èCÿÁ¯êxs<®×u‘J¥ ëºÝÎuÝåëq"(!’ ie*¥š& ëÐ_ó)¸šHJ^FU< •f˰m/y‹•I¹€ôš2ÉH‘ Lòu–€Eps+ ÈzøIò @@®ò"âý³íåù]À‰Æÿ ȯÔ7Ú]^’Ѷ½ýSÕš@ó^ ðWIª;—[—-ÍÛQó9y©5MC0ôKœjš˲044˲‹Å I’É$r¹æææJ¥ü²¨bÆr5ìUUõ“‘\Õu½»œˆˆˆˆˆˆˆˆhsÐ4/©—_4âC àöÛ¿]{NÅX–}91844äOkÇ …üª`†áå E¢Ì4½ŸŽmß§ ýõ0ÍådŸ¢xÙTÇñ6Pg™XIòFñ•M¨)¨Y¶Tæ^ Hs+óÆJRQ ¾É?`eŸd¹Êüu&0Å{O Ã+™kˆß $®"i`qÑKœ¦R^Âq±® G<QÛ2 š¦!™Lúó2ŠŒ®ëú%RUUÅÂÂBAÂÐqVJ¤& ¨ªêbÜÈÄ¢ë6÷Ž¡bŽãø%*$I‚izw¸9Ž×u¡( LÓôKÌ®ç]mDDDDDDDD´1tÝKN‰²œÞHGš¦ÃqضÑÑßÇÞ½{×­ ¶möm†áPUš¦-_ A–e<óÌ6üöo¯”ó¼dÙÐàþÓW rBÑ>(±LH^"Í¿¹^UK2kÁ HäR,"Ö-{)Ì€W¾´ÚA À€0O{ÛÔ4®·º¾RÞ4õþ/J—6bnλƧªÞûìï~À¼Q“ T-ÙZVj•˯DDÔ–,ËB4…¢(0 ï ‹Åü»¨EA8öˤ ¦¹2³Húmôœ‹®ëÕ…ªÔs¯º¾[PîU$ÅsÑh’$ù“ƒ‹DãÅ‹‡Ë.»¶m#û5ûŲ±X Á`¿ò+¿‚Ë/¿|C 5.]- y 0×u100à_?J&“0ͽ(7¢a¬ízU1MÓüÑÑh ËÙ6I’ ª*, ¸úê_Ù3g I…IBEäþŸÃüOÿëÂÛ“'¡|ýV„^·2jSÓVnê×4o°£h»ã¬”"-ǶkLEToÂN”+éÝË¥O•÷!ó„Ѩ÷\ÑìN ½¶H6ä\ex Ñ(¼ä¼ò­õîO2¯ÍÀÄ#µ QŠALD‰D‰D044äwb€ÂZôâN*At:eå¤ä74äu\·FMwáp‰D¢dNɤR)Ôf0D*•‚,Ë@$ñËU¸® ×u±°ÃŸþéKHªB*•‚ëº0MÓOPZ–UUqçwâÃþðÆ""""""""jˆeyIÇü¹ø£çææüÇL³ôÚ”¸a¿R9PÇñžwïùr‰4Ó4¡ë:’ɤŸèÌ¿é? A’¤å©wØQÐVÀ؈e ¨Ê9H[n‚ûØ ØÈ׈{¯-ÊÇʲ׮HdåZ_¹¤*à-gYU® ®æZa€ DxeR1y×E"¨œõÉËë7B†7rÑ7zS[Þf›:c⑈ˆÚ‚mÛ*(*&¾ŽÅbˆU¨ß^<’Ѷ½ŸDþ¤Õ™xµÞc±ÚwŽ9ŽÓ4!Ë2"‘Èò¾†aáöÛß Ó4aYE,Ë~2‘H”Ái^†pXtUÿu,Ë‚$IþÝg=öØÆ""""""""j˜axɶ¹¹Â—ëº~¥«|¡ÐÊr®ë%äTue”^~âÑ4½í+Šw-Íq¼kL‘ˆ÷˜ãKKKx×»¾ƒ§Ÿ~=ž~Z-¹‘^ÉH1÷¡,£4ñx¿‚Èhˆ*?%½€›Ü—Ðá%û"ùÛôÚ+^2+œ#2ööQ$)c±2¯)á%ë¹f¨.ÿ˜ðÊ®ÊËíK¢`”aÝ3;9Ë?Í ’˜¢}:¼š¡åËa©U""êf¶mÃqhšÇq‰D IE)H¬­f^B1Aµ,¯üÁ# ëUÜñZ QîA’¼×FPHó÷É0 ?™(I iš_u×®áóŸWq啯ÇË_þu¼úÕ_öG;ŠÑ‹å&¯%jåçßÍ&·bÎGI’ððÃã/xÁº¾¿DDDDDDDDÔ†á]ûI&K“\š¦A’¤’Õ%ieÔ£e­ŒL&½Ç‡†¼‘“®»’´# ÅK\F£Àå—ŸÃ}÷mÇ»ß}?üaÞþöËðÅ/J ç"tœÒrªºî½^Ù²§3*ð- €38& ¾À{á• ^rMYI:Þµ0M[©~‰xû ­î:`Ýdx‰ÊÈrÛ°¶Q†¼‘“ͤ,ÿèðF?F—ÛZ~<ÿµYj•ˆê%& #£LÓôçÄ“e–eùËÚv³#Q}4Mƒëºþ‡W¼âC¸í¶ÿˆü«8|ø|õ«_Åë_ÿzüÿq9¾ô¥/áôi SSa,.ÞŠXìV(Š7’Q–e¨ª×—zè¡+\MóîÞw|‰Ž—H&æwòÅ»Û,ô:Q¢t„(‘_6]©ÁŸÏ¶Yr™/…e8p¥z‹ÎQ+ˆ¤£,& mÛÆÐЭÒ<‹‚¸Q½I*ÿ¼¦ie±X ¡P¨â€‘´DÒP”^•ú HÏôCU¯÷žT±RQÓc±2•Ç$x 4 ^™Ð¼d_™diÝB(˜ŸqÍDûSð’z¼¤(ËZî°‰Áë|Ä(Hg¹m€‰G¢q]º®XIŠ9ÞÇ$I$ ®ë"û£S©,Ë‚mÛ°, ©TÊ¿ÓÄu]D£QhšæO$\<¡°ªªLþñ‹ë®ëÁý÷‘È!„¤÷º+uB¡Â2ùµõEyTÇY™Ÿ±¸¯{IIÛ^)‘ËyËç#Çñ:gÀÊ$Ú¢¤EÈÖÃ`ßDT÷Þƒßú­—»-‹ˆˆˆˆˆˆˆˆÚ®¯ŒJÇA4E$A¢ZF1Ïj’s¢ÚžëºPUÕ¿–W±R™ey?ñ¸Ÿ0´,ïzTâÃY(oü7°G¿ I½Þ»À¥i+ J¡$1‰T™2)/YgÀK %PXþt5Ì5®W¸ì9/I:„•¤©½ÜöJ6VjßâÆ¼DM`"ËÓqœ’äŠã8þ뺰m¦iB–å‚eu]‡¢(H$$©b@·mÛùX8¼]ÂŽÁÛ?ûYìêï¯SÞroxä‘V2ê`ùe Ãð“âù%Tûú$üú¯¯$¿¼I¤ëûË*ú+Ëyù‚$"à%ØVî€rÝÒR ²ìB× Äb1\}õY<õÔ³ˆFãøå_žÀûß¿KKßÆÑ£/ÁW¾r¯zÕÝxðÁ .»ìJ¼éMßÅg?û—Ðu–e! ámoëÅ+_yãrB0°ÜŠÛóއ÷o¥þWqç.òNMQÎðö5©<—¤¢xÇÄ4W’‹Ž³R/_”TëKÒJm~Ç`šoÿ*Ð×¹Ç[î±Ç†±uë“­ùQ Çñ*_9ŽwM,L‰aþÍò«ª(Vëî~øÆ?|Wžº½ç{qõ5W#1–ðFÈÕ3†@×½íK ÕO*ý@Q ¼óU+;‰xÅlx£s¥›«:€S$ïlxI½ ¼v®6 ¹Ši™VM$CðÊœ†°2¤˜×r5sQv &‰jp—#¥eYPUÕºî8lÛ†$IÐu‘H†a@×u,,,À¶mhškyx•¢(þºŠ¢`nΛ whhe|³mÛˆÇãÉÄrEYIpºîÊ$tssøoïyðøãÀç?ïeÊüayá™3­>¬Ô!4MóâÉdápØO‘l3 ¯£¥ëÞz¡×O‰F½ßÿûKK[J·ß~7,ë9?9¯ë:R©G¦½'Oª0 ·Üò{ؾý½øæ7ùç¹ë¾€7R8"ba¡ú¨ÀՎʔ啄©¦yÿ&“Õ;UÉäÊ(ÉÐöBx Žs‚Áå¾ÝU9ÈΰéÑä]ÿ¡]Üw…õÛ×#öoÉ$pìØÏñÄz›MDDDDDDDDëÈu½ŸP¨t*Ó4F‘H$ü0u±,ïÚq,VºQ€|ç;ßÁUW]\Üø¦q£s£÷\^’/•·-Ó,¬ÍªªÞEºp$¸ã?€ÓÓ‡¹·ÿ%p\xG~þëWÕX/q=n^âÑ…—ØS°’ì ¡ò<Ž*š?â±Ük xIG`}“žm‚‰G¢e®ë" "µùü'ñÆmoÄÜÜ\é5켤žoä£e¬Œ.È¿Q?÷~Lú`™€¤¾J¬FÛšUvT4;¹ÜV+¥T£ËÿŠÃ&“ët,G\vL6´•ŽÀÄ#mZ¦i¶m?‰hš¦ÿ¯ž—ðK&“p]· ”ª˜ƒQ$åÿŸ½;«¼ï¾ÿñ¾r„9¯¼Â½IE'Ëãñô%ìÀß›ÅÙ‰°¬·¼+R„éëëÚÄ ð)R ”cn_ïr ¬&Ü>h­ôùïÿ>Â…Τ²²’D"ÁŠ>6múW_ý+b±†aðÁn¢´ôÀ §ãñxp»­ãÊΓÛIL·Û:Œ­¼˜}*Úã4†B}=GêJ¾î@ï纉F£½Ÿ™  ÒØØ˜ÖJÑî6uøÓ7À´]I`U€R_ÿk<}IúX¬/±øTÎßk¶ÎÙDïr++a­.qÃzkƒ>ë=°!·øàU7ÜéwosNûa¯·¯i'}½< 0ÈlldܼÞQ>m&""""""""“ÎnåèóY·¼^»#¬±XÌéZ58ÒM¶ªª¾óìnÏz-[¶Œ@ @0Äï÷÷ÝóözaÓ&x[ üS>æK/˜Ý !è»—}¹¶§”¥ ˆ`Ýw®$ý>œ=¶¢}¿ŒÞß©·ôúÿ?U|ý~ˤPâQrŽišN«D»ûÓÔ×í¤¡=¢×륵µÕiå –Žzû°þæÌ™|øÃf±a ÷°¦ ƒº; »ø~oKH'‰ØÓã¼í ùËÇÙñýï[/$°únãýày‡Þç·Æc öXÙ†Þ¾¤‰„õÅâŒïê]†ÝBÉßûš'€¿¿ôýÜê»5­˜‰¸g‚Çè6l•!-ÈK~²»rÖ¸aýmš&áp˜H$Ò;©‡O±•;®úÏÔ>ÃW·½“ÒK>Ï‚g®åëŸý §W¿‹'žXL$X‡Kô Àrˆî÷rz¼>~Âþ?‚šwÿÝPÿ~0Ú¡< æ.h+îÍá%°sn†X$ÆÓ/=ÍÆs¹â›Wpbå ^<ÿ"K–,¡öD-ÿ|û?³fÝþáþÐK!6ÎÛÈ3¯`Ù²eÖ¢ÖòÞ„Áq[ÛÀÛû9>¬s¬îBvz7R›¯¯tA šb°Ø…_0·Õê‚Á 4‹°ÎñÝ~x΄¨×z/Ò»Xµè½abëîÞ÷ÝhõÀߟšÝÖ¶°y°ÎÿXï:Þ^UñÒwŽÛûØ^OÀïI™o=++ñ("""""""’B½÷³R†]$‰PSSƒÏç³îkæfN[[_ï[Á ÑX Ö¸ÍÍÍÃ7^™é‡¹)Mÿì&í5ý{ðKe·„è$½ëTÖý0»1MëÞ\°÷5Ö½¯Þçù¥ð(ñ(Y‹ÅˆÅbœ<¹€C‡V±wï^fÌø¯½¶˜drEEorÓM8ݡڿJJÊYºtiÚ†Æw‡PˆÈ.<û?àÁßÛ§£Ùßkçü·péƒ>< ^%øyÓíÆ·ÜïãÂ;ñºw2+`óæÍìøÈGH„­¤ ïbþQ˜ðŽ“$ž›Kðïæâ‹à4Wòx<|ä/þ¢¯@Q0ÏX1ºüq¼ wïj¬ k'‚Ú,í— `å0VÐB¤Œ€ÿ?À}7|»ëV~ô×`ÜÏZOÇTÝ Á¿„@=à‡Ê04nÏÿ‚P)ÚÁc¢Ӌ²}6ëËs¸ºA´÷·Ý/5©d'SEèëÜû»÷sÙ¹Ë8ùµ“45ñãC?接wðó›ÎÕ¯æcgçñŽK;ùà›Ëøà­Äûí ïz>swBl-øÎ@ã» ö¸ç€ñ$~ Á5àÿ'à'8 Ïú ¨ÿ¡UîJB¡­¼ó!x ¢Ip Nøˆ·¯ÿöÖÞýrÞ€h%üÊ ïj¶óå½ûê»>0}Öçý}OfUö–ÁèÝm)û©²÷·à·ËÜÖ;­Ý·¼·w~û!/VÌ“R6û…`ï´½/P™r¸±¬ÑÞã!Øûš}ì@_rSDd8†õ3ÿÄül—D¤0˜èa?‘iB4j5L¬¯ïK:†B¡¾†4Ã% ÃZˆ}3ÙíÆ ‰Åb˜Ñ¨Ó3 àÜWÒ2úeþLÓJfºÇðÔû` Ķ~GèK6Úó¨î\°”x”qIí14³þ·ãa,mm„ÃËøáòOÿ”dÿþý;ö,o¼q;v3¦åËÿÓôÐÓÓÚ‹“T]·œÿøK®]q/|m`52ŒýøÞã¿Â»´•ð¾jbKi®·žºp»­:ÝHàªcD^7ž«?C[à*‚y¢ ÷Û¯Cð pf-‰¯‚±jvCp)Dl¤ñ ‰Æ ô³³À³ã¡üèp{›] þùPùw¼ Üÿ ‰¯í‹®±!v ˜«WÅhÌ ï%2û2Ü>p—ƒÙ¾“ùopχúÔ`lâô9z ¼1í÷0¿ ž$˜ó9«ÅY$lm+ï10½ðX¹ˆšß€Ñ ¾¨¼ Œ3pÃâ¿Ëö!TxBX‰b›=H±=`±,²“O Ò0¶“ZúºØm£¯ÛÜz0ëM¾û‰ïòÓó?%úe+sùU`ãÆ|­ûk¬X±ÂZÆ ˆÆ ðõeΗþïóééí ¡²1hüx_ÿíÖòŒ(z{¿ÿÖ:¼ï‡Ï±{ái¢à…G¹˜Êß¿žÊ°Ÿ`0HüÕ8/¸_ ‘Hð©ÖO6z6Ød>Ÿ¯¯øX ŒÞ'¬&¸}àñ÷½oèv[ |p{ûn­­ÖëýŸârz˜èÑNz;z÷]ë³ìA¦ë{÷Û²Þýa'ø¢ô}žè ¯’Ô¿>–:]êÿöñÑÜn»Lý+j= äë=fì––ö²íãÈC_ÂÒ>Žìma'>W!".‘H8cQ›öà!ÀÓÿý4ŸúÖ§XprW]iÅBÉ_½Iä4^¬ï6oÊßfÊûvëûÞšœ è7Ýâ?Øïsô}§DS¦·{!°¿ƒ)˰¿£ý>§>e¾F¬oRÇ+÷÷þ¦¯w€š”õ´Ê)OY^,e}ìõ³{1°ú©LYF¢÷µ0}ö˜½eO•:_ê÷«-u;Ù˳o®Ø/…z?Ã~ú–ôõ”à#}›R¶wêö±ÙßÿþÞeØ7rìõK¹¾p¶¯÷õAÆà‘Ì …ú:Õ ­ÛTvÏ}±X,­W¿3šfßA~?4[wòjjj0MÓiÙØš2Äψì!‰ln·•tœ Ò”WKÇ‚¦Ä£8ìî>íî !ýïhÔc¬¤ŠŠÎsÝu{˜9s<² ^åë_š³g—ðúë—rþ|ÿùŸqŽÜʺù¯ó¡KöqÝeóI®:Éú¿^û\#ÆJk¹¾š0 ̃n>·æ?pW¿—ˆYO4Ú›[˜sÄî9øn¬$qÖEýGwbž¼†ÊÞ‹ò@wt[ëQöRÿQˆ°Zƒ;yû"»·5ZäWà?ÆO­ømœ€ú3 ý7ǬíQs'à‚À]½ ¯>ÁÞíRRf¹uÏÀýßм"Á< ælðo°¾@¬Þ^Ix1zŸh‰FÁ'¸gCð-ú‚mÊM¡ª_CìehóBgDk æ›V—‹ÍßǺPbóÀ¿b‡€#®‚À;Á˜ÔÇ êAý]ðPò¯€Ù>äòƒ$´»¿´» °[áÙ7Œì–m©ý“÷vƒê|‰Û˱Yý¿`û=Ìdšð~Éœ_>Bt ¼ÒµÍËô;ßyž/ÙÅí7§.ä‹ ðy­|]I«§¤tÁ Zuï×FXuÓtº8¶+0 #e€a‰øý~ºº~È;Þñyn¼ÑÛí¦q¤Ác±¾Žëmᔬmÿ÷Àz,´NðÁ’‹Vxôf屇^Ò“‡Ñ”ÿí–Ž©­/SeúɬÑVºR³¡âN={èë¶×þ9ö{Ç2¼ÓH›+£f†Óuüx¦»b߬ݿ–“'OòèUrÝ×9ï½u~.ß_ö'ži·–Aé%¥`Âc'ã§4ð$1®Ä‡O.y’¥³—òÜÜûùÁüûù܉ÏñâÑ¥ÙÞD…-5y”Ò…¶3ö°™2·í¯Åf¬‡`R{ç‹Ñ÷ÐJjbуõýf'˜êé«ÏØì.üG£ÿ÷LïpNySŸXlÚÔ1] ý»Î~ßþ¾µ×”ÿ}½ëјòyýï¥x°’gö÷µP³Ù¯{†Y†7e[õïuÒ{2°×Õ~ˆÈ }ÝËé{°©9eyz×/H_ÕÞŽöàÁ”2ØÿÛ½"˜½Ë‹¥”ÉGú855ôõa¤¼é÷™©TÕ """"“¬¦ÆºÜÜlÝÂ2M“P(L8&ÐÖÖÖ×%ªUç³ï'þ˜ï†këáý>ŽÔÎàÙ­òãÿ˜@$Àºä:ÿÁâ±Ê~ð^$ÔxœìFBnw_B¢¾ÞnÐtËzohØcÕ&VnàŠ+ö1{öQ®¿þIü.JJN ººªØ¹ó9fÌx77ܰ“O|âVpÅ©8x×]Ì™óG|dãg¸`Î9~âýÜo½ 7ð|äð€§ë¸²þÚƒÛ~¢¸¾÷§ÿkø oÞaMÖQ Ç‹uqß{Qíy¢Càaèøv¿üD¿Ác½7¼ úkÞÞ¹ÞiÅ÷ÆFë Á{xÞÙ— ±·§ÿ]~‚µü DÃÀqð^á' 9冎ßoý””XóÖïæ‹¬ýÂÊ·Dþï„òe¨‚Öm}ëàû3ð>‰S½ ua0–Cýaà^£Vã/¯×jÝV_îË¡µ÷†ÓC›³}Tæû©t»ë[ûfM%}-í›Mý“FöÍ-ûõ8²|‘H„W^™Ï¯ýuΟ7·Ý6ŸöGnaíÚÏâ÷»H$àÓŸ¶ÎÝU«úH$¬×<ç¡§Aù|ƒ¿‹Åðz½„Ãa<‘H„ªòr–9ÂL`î\ð»ßqϤÍ0 øÖ§­Î㱂Gj0³ÄT­­éÓŒæi,k Ô‰ïS»UGêM@›Ÿô'½üôݨµÇfÍý7•Ýê¥WÇ+ì?´?Û¥ÌOö àþ-— aô íú0X§¤ÇÓR{B°y½}ÏÜÒ~Œ3o[ÌC¿²ÆQ¾öÝÖïËgöÐÔ^Ä7vrù¬¾ûÔÎüGŽaéÒ6ŽYÆÏÝÄçgRä~“D—›]§æqÉů²äØÞùžó­Dçá+Kð\ÇUtŸ›ÅùeorèÐ!.÷:+ÏÏçÄkÖØÈ¾%±£:–tPrÔêÿ|Éšÿâçû«95óË—?ʉ+éî^ˬžY”)åÄÅñöÃûéœ}gÏž¥„§ù-/sŒGXÃáL¸{³&&a.áñŸá3¸ñð9îfßúBJëòV޽y ô0sÎn»n~å<óÏðÝãKX÷Ðï8sÑç8»¤)Û‡Z~ë} °¾Sì±ûw—m·h Ñ—Ô²o(Øï÷¯;Ø­Ñìs/5–j°X”úÕ:ÔC*©ÉÇÁ¾bGã|#Lïfz[êÃWžÞjï5Ÿo„e 5}ê|î!æ³RÖÔùCüÝ9©=øv~Õ@øJU=„]kyšúg>‰·¦÷Î|u«ÝVal¡wÐØ/¦? m'iR‹{;_ïß­ ü<©OF7÷Nﱑ¾¡ò0ÛGw¿Äï·Z<¾Ûû¸Ñ[ __²ƒ©ßÑ|ÜÜÞÛ+U¼go”å÷[ûÑIü„À}µµŸü~HòÿïÛ¡þÿöÍgš&‰7,ºý]x\0M7‰D‚Ûo¸­yš«Ï\“]Orá…>æ­<ŠiÆ1M/µµ¯âñ¬$ŠP__O(âèÑ£“w 7Ö—´Ý­æ8Ù-xSÇòüþ÷ñÿï‹€ÁÎ.LÓjqÅïåÈ‘*ÞñŽ|ÿûçq»o!‘€HÄå$½ƒAú­€àw÷Þ±ìm èäæ"+(˜&Gªªxýúë™uçD"ü~?%%UìZ¹’“?î4xæÎ;ñþéŸâõzñù|x"+ïõÂSOñ.HÏ0ØŸ }AÉïOOú|ÐÓCN*1Û¿U£Ý’$õýÑuS]ñ®l#ÿØ »…‘Ýõ]H$¬ú´"ª¯ï—ûïÿÇ ñ°És»ç²ÎsŒ‹/?Æ#]LϬ:ÏvröìYn»ía¾õ­O±ti'·Ýö0cwÑöÖRVÍ<ÅÁóó¸æâÇx{÷Zî?¹€^þŸü।•i-ŸäMî`WñÔCIvŸ_Ä2–ñ“_¿ÁïZÎu\Èof¾ÌKß½‚–³."ÀñYÝŸ}šÓExÇÙ2^ž1›äYƒ£ç;™}º‡#§ÖR2wÝÝg¸Ð¼O}ë£<|Ác\÷æ*ûÖóƒÙ{Ù}örv®œÇ-GÖpû‰Ë8ä®çÐÙ½œ8y’²ùÏðøñY_vœCo­bÆŒ,è^Â'º_ä­óKñu‚Á~6¿›+ÖÜÈþîCt^³ŒÎΙ³d]Çæ²bÞK|ýX€£=ŸáàŠ™]üíãÁÿ| g¥æÜÝDxgÙì>Ís.wÞù16<ý—”¾þ^TÑ ‡gpfþCüé=ïÅxsÉcDøåÅ…94÷R~pö÷9röª«÷1»d=?øòe|ìÖv.Ù·“¶³wã_ð±®›8ð77}Ð͇>îæcA(¹ü{pî¼Eô'÷}v ž’lø=øÚÖëùàóý#¥¥ßqzv”1°“@}ì~¬ï ;áç¥o\àT£é¹(8Ši$÷eêûÁN8Oà¦ýàˆÝÃýÀša€ûã°è¹k³¼±DDDDòL¢÷gˆ:š}/°ªÊn€bòµ/}‰¥xf»i¾£ß?¬nò¸ªàb·u!8ICÓ4‰x­'Ãá0ü³ùϸ<.\¸¬‰ì^2ì½ô=ôXÏÀ‡ôì‡óé{É+y—xlhh ©©‰îînÖ¯_O]]ÅÅÅÙ+P„¾.lFÛg19ì¦ Þ‹!ò_mµ^hýTÞ ¾k­ñ^çÁ<ÁƒyÔJz•'ŽðgÕGxùØlÎ>¹—‹gŸääOçñÕû˜Ùø(φþÐû‰dí’zn={%ßxål8kp®ì~û±ÿ—+¯¼’Å‹Ã&ÜX‡þ 6¸x™›»fâ/0‚>^Õo6îöYÁÌ~h>Èà7÷½)¿Sƒ^=}ãÍØÝ ´MS»n²§Bëa­°ò£a'„<)Ëóauyf7qO$Î`¼ö8IÛ·ÿŒ[oý‘È—œ¤žßïÇ0¢¼óï$9èÌow¶{÷¯¹óÎÏSYùIiøEXñ7„ÿõZ‰z®)}ŒÕ«ßÅRYù*^¯—D"A0¤²²’{îÙKä›wâÿãF*++Ù{Ï^v/zˆž‹×ñL÷3,^|«Ví#‘°’Áßþv„[om$‘H8e8}úôôÜ2©qÀ‡±·5©sqB¡¾^EO:D4êæýïÿ?üáANœø4àfÑ¢W¸ñÆã|âÐÞ¾‰n8Ç%—,Àxþ$Áwÿwøa¼‰øý}Çõ «•n7—_Îù}ˆ†în|>±XŒeGŽ°ì¦›xég?ã“>Êkßþ6óßþöÞYÜÔ××snÎÜ÷wÖÁoÜàñpCjƼ¾ÞúN À* dc¡™²:=nV«%S'ÖqQ‰õ5šSÀîæÐG_Å?õ½0GÀœ îÏô}ÿ»ÝV,Ie÷ZP]½w‘ømßêr½ÁW|…^ø .×^{웽xlíï³ûúòèGyï[ÁÏÔ°Œ§Ó7ç÷[ ‡ÃÜð¥ÇgûOʪ7­1ž?{¹åßøoÜó^ÿ"ÚôÞvþ{¼öÚk¬ZµŠËW¼ùWE"ñ@ïXÂõWÅì‹.âÈ‘#¼;ù(ï]sk6¿›GŽý†ën»Ž—¶¯æšWâÌŸ?€Oñ¿IÜùyÌs.|¾"àO©»ÖzàƒÕ^üš­øx{ï3Á¸ÁÙÁNƒ4ï{{Ÿ³¦¿üE7ÆN?þ ð~ÿ n¸üþRàŸù¨½=z/Ÿï;N:^š‰Û=XJ=éÏŒôôXE‡aÛ¶±aÃÎÌŸ7SdRã€ÝEµIßÃn©c Úò`%ûw) C·¼ËcöƒÐ×Úþ±|€¾—­·jŠ×Û×2Ú~(Ò4­×ík"_J×ñvìOï¸éf_¬ÏÄ€5ŸaXiESžì¶?Ãn¥m÷Ü‹ \†=„ŽÝ=},Ö·.ö5ƒ½ìúú¾–Ýö4öƒ†öy—Zv{½í!,¼^ë着¾mk?hf ×ÐûÐâ¿CMU_ùÁzj¾ª*½¬©ëìv[;ÚŸ´¶ì„"´ñï\C]¶® ȹû"’Š2™ì:ƒÕE¦õc×Eúwú”:BLj=Ü~øÇ®ïôÕõû ²(µ_³ëvýœ[8βSëWv¹ìz‘]¾áêNÀà'òÑ”ÄÔq¼íqÓSzE‹=áo[û¤­ ž»ï8O?øßœ¾ø¾xöÛ[y‹_ýx4Ð74B‰Ûê:Ï49¼úƒü`î\èmY__O4¥µµ•@ €ÛívîQ§éí`ðaƒlzØQ&Q^%íÀaŒ††jkkyðÁ§®1zô£¯µCj7Iö$OǠǹÜKâq0_ï$5‰SPæ™9$Ž_†¿ø0žŠåD¢à=õ<œ!P|”ÀÊ󿛋8ÿ<=\Cg²v€ÿÈiÅÚ͵Ìåûü”åËʹ¦ëûcçý³¯-aïw|ðQ«;EŸÏÇ5‘eD[šð½ù>Xù>f½äæÆà} õ»¡¹Õ Nn 9f!çðÙ­÷Ûɾùš ¯Ë©±ðà 4‹ÅðšVÒÍëõbn·ÛIú™¦‰aø|>"‘@€H$ŸUÿËç/ç3wvñÃÄ1MOÚuö~i^ÄŠsÇù=ÏýÌzåí\dÎæ Å\Çbž+œOÒÅŸðÇx›Öðµ«>NÃyJ¢ûB¾¹v-UûîÃuø ÌypnN+Kg¾ÉV2kí,| 7ò뿼Žs¹xñŹêú«xî¹ç˜»cïÚ´‰@ À+½ÂûÜŸbÕ¡ý¬:d-úüspêŸZùdå'éüf'úó5üäüyNµŸâàÕWpÝ…B`ÿ¾ëß­ø³ÑÍ™¿Àâ—_ã™·Öòîë¯gþo‹×륹ÙúÞ»óÿ~…ƒÇsx÷nV®\ÉÊk®á^/ïÞc¼§7V¥ Ngš¸M_Êw¦óDFÊ]ýÛìécýºíó¿°ŸeMï7µ÷w¿ ÀÒ”inë]šû¯ÿzÀá3 ¯Lýâè»Âs>f¨qjS—y» ïí®“5ë`לý_óö+¨Çc%;V¯þK–ÜH>šp0éëÎ(uL?;™˜:֞ݥº‡ô1þô=œ0Iì„^ÿ™×›~ã*5±}7Àì›_v×Ç©ÓÔ×÷=Ü`Ažú9öqbW1::¬dY*{f»§õÔ.–mmmV÷Rõ™‰D_òÌ^ÓLO6ÚïÛ¿íÄÚž=g8uêEV®<ÁÉ“×pèÐ!æÏŸÏÉ“'yüñƒìÛ·Š™3áùç­¿÷îuáÆdÅ%'9RrŠ^XÀ«¯.`ß>8öêA~ùàjÏÚÏòe3è4MZ{gæÌOpìØ~¾ùͽÌíèË(rÃ[góÊ‘ÃìÛ7ƒcÇÖ°}û“ð„õPÇìÅ‹¹fùs¼ò“#Zr)óæãСY¼¼ó(ËÚWrýâ׸dÞAN9ÍÿÜxc==ð¹ÏýŽ{Nžcé’Ùð:|k!3^{‹XBOÏJÖ®=ÊßõUþð­E𬷚󣺃¬]{5Éä1~ò“ÌzæÔ]z=Æ©2޽õ[*Ánž[YÙ×Pß®îšaˆâa늭ÀU“w O¢œ¸O0Œ~¿SLjµÿ·ß·ÇK Ñ7^¹}= ïz§˜Az—Í£i…-’ 6L1;1–ú]lKíÍç³ê'© 4ðæ³šI­#@ß6©Ö¤ÖEl©u…@Àš¶½Áã±ê öPFUýºðH}Ø&ì{¨É~8ÜïO¯cÛ½ÆÙ57[ÆàîØÃ'Ùó56Z§qe—ÛNêÙÛbáÂS¼ã¯køÿßnΞ=‹Ëõ"ŸüäÛY¹òGÎæCz“††…ìÜ颵µ/É}ûç®»ŽÓÜ|’mÛð™Ï¼ÀW¿z5'NÌgÉ’³\tÑQ.»ìEöí»˜½{]œ:u˜W_]ÀÞ½.V®<À«¯. §'JSÓ‡ø—)ⳟÝÍ?ÿóU¬ZõÁl†ã6)q FßçöµC,„¡Ì mó«`¶BÕC`,ÿ xüm‡Ø½ùgxž{ïžy=óæý üE=‹ÿ9ýéåD"Ùa³ïu{<Äb1êëëinnÆçóïCÿ£×]$ÃfôôäZÿwCóù|Γ ÉdŸÏǶmÛX¿~ýó}ñ‹_äï|gßÍ©±²Ÿ\ˆöþmßOò€Ñû”Kìsà~ 8óU¢gÊ0q“è½hû”|« ~Õ üçž6ÎÏ_ÂU«“”tícÁÒ%ì.Yͱgñ»%¿ãÜ‘½”üîiŠ8ÏÞÖñMß> ïæØ5{ç3çÂc”ÜPÂü×N°æÝïÁuÛ iÅnoo§´´tL«j'×fvÍäÌg˜uç, Ãpo>ŸPoâ#‰¤%áLÓ$‘HàñxˆF£N ÀÖÖV*++ûµ4œ$ Ø‹D"N"ОÇþÝØØ˜6àüœ§?ø³?û3v~y'þh_Ý)£} Ù ÈÔ„¦×ëÅ4MÜn·“à´ˆÑhŸÏ7ø“$9"u_Û7§†³yófvìØ‘íbËxãXIØh4j%#&\ƒ¿rÃ5¾¾J„‘è«õÚwiL·Óì}ªì‘$Ïÿø~ôÓó<÷ÊJV,Þà óæ±{·U9»‘JfPŸ(AœY¼˜9¿ü¥³<Ã0XñÃòÚO°fÍþs÷nÞý'¦¯ÝIvÛÓ™¦éœ3öyÒØØH$! :ÇóP’É$EEE¸\.¦“ñÄ¿|7Ö}ljÇãι”o2R'?LÀKQx(_v÷=ó!¸Ä7{àJà6/àîk[YI¬óFxgWc~ðSø~Ð÷|Ò{æüŠëŠ ~øÆ;¹lVV,ãü™óüK×î-ú5 ^;Ň8Çüˆ}æQ Ün“Ï®þ,çf¾Áßýöè\°”ãK޳øÔbŽ-ÛÀÏ®)aYÉ2\²€âÈçXg<ë¬×±9sxm÷nÊKʉ…cø‚>õVpòÈI­ZÄ9ã‡/]MÇÇot¾;þùÏó¿–.å·¿ý-×_=¿ýío¹ì_ÿ•7ÏŸw¾ó]n·ºózûªÁ õwj˜Ã%óìe67[7Ùì›]¡uÜÏ™1ƒ³Üø¶7™wÉ}t9ïz×a*Vïæ¡ÿ¹$muÞó'gyúée¼úêã,]ÚIɳIf™á¼ß½hGnÏÉ“ 8yr—Ïx‰wï¶’øGŽáäÉ“¼º`?^µÊ™ç®ƒy×áÃiŸS{Í5;vŒîînLÓ$hšÜîrqâÄ Îœ±ZB§Þs´{©Mî7M=Ÿ³Kîv»ñz½c±´Ž+bXùûÚ¦¶´”ûöìá…… ™9s&3fÌàû_ÌC‹±dÉÞ|óM>òÖ[ÜþÆÌž=›³gÏ2kÖ,þüÊ+¹üòËy饗ø—ßýŽ 0sæLk=×®e{I +V¬`÷îݼkÑ"6<ò§.äåÙÖ³¿]s O½ù&×_=ûöíãï.¹„מx‚’’½ð×ÌŸÏ?TVòꫯräÈ-ZÄ?=÷§NbÞ¼y˜¦ÉÉ÷¿Ÿ¯?Î=÷ÜÃ}÷ÝGÝ 7ÐÓÚÊ…^HOG'/¹„__{-»ŽçÆoäé§Ÿæ³fñÒÏ~Æ{Þó{ì1<>_=~œW^y…G}4ãçéTo,˜ÒºPêX°6?}ã-Ùªø7{ÿöcüÐ7VSªúÞéìií&lv‚1‘ò9ö ÔÞÒ—Ü´{ êßrÛžß^–=NÃXÖß„}¿ÙÇš·­!qÜ]àY 1»CƒÁ½×z-qø1xW@â-à(°Òúñœí]d1¸ž¥8Ô· ^o$fôNo€yÒúàà›½Ëö¦|ΡÞé–€çrðìŠÀ¸žm<Æ/&qÜ&ÄÜÀaÌ‚Èl`>ø^ã„õÀmà~üË!rð/ƒ°=Äú kù¾×{wýµàÙ ¾e9h-“›=½Ÿ³¸wÎîý^IùÀª¾Ï©¿B/™3g˜S<Çùão·>dzb)ËØU3ޏ-Ê–ÿ³eL‡w®o,ÈH]È~©_¢Î9—ì^•ÁK:8|ø0Æ)7óÿñ)¬c#FŒU”1‡[XÅ!pƒŸò‡‰sûxŽOQ+V°³ÓÅâÓ¯ñ4ÿÍ<îâ·pž™Ç·ðõ ¢"ÜÀ¿²—ËXÆÿÃ:.&Éq-»YÆ bÄøôüO3þ|þaÙ?ðéW>ÍÉ“Öv]³f ¼ñkίaÅñÌ»z¯.x•;oäÌ™3Þ³æ=üxÕ¹±óFVžX‰qÚÍžy¯ÑÖ½”Ž·:9qâÉG¾>°ï•šôµh¬é Ø‚'°Р÷7‚ǃáöþDžÿ¼è~ÚÏvòçÇ¿Â%§±mþW¹êª«XþO˹á†Àm5XˆÅb¸Ýn"‘ˆsOÝnìb×cÇ£î…Â}ÌB¸‘‰zrÞ´xloo'™L¦UŠ‹‹)--e×®]Ã^xÁÚÑÿƒ¦$MxÀ_6½µ€V º£ÓÀÀ,ƽô&øäç‰þp¼ãSO°-vŒDØ‹Ù{çñžµ²ë‚ xí•b*V§¼g 3Ïeþ’‡¹qv3³g¥êÇ? b¡ü`oÙ]Å\:ÿRÎÌ: X|l1W¼÷ :urË-w±WÝ~;¿ˆÇñù|øSºü4 ƒK|Ö“7ßy'5554zó€äÞ7¾ñ >ò‘8É4°ú¶“y===̘1Ãù? :É8°’þY~'‰‡ñù|NëA;i·@´[çÙóÛúZ]ƒÁ´€ 8<ÓŠ¯ÿïá4÷˜èñx8vì÷<`'Uÿ¡»ˆL-›]^{©ü£í¯5‹œ/Ç<¼7kM[ìß÷¯<ú›÷°nݳ\ðÜ[=»„£ç\\ø ïùЇXù­oñ™Ï|†'Ÿ|’늋ùRï5Çå—_ÎSO=Å'¾òøã?v®]¼­­Ìè}P1[ãS÷>¼e'I™Æ~¨‘Þk¦p8Ì|¯—+W:óÄb1ü~?O‡B´µµñ‡ø‡¼ë?þƒ¿ý⩯¯ço{¯³nè½f2MÓ4yúOÿ”X,F0äó½D¾ ñWõW„B!îüüçiZ»6í!Ê2‡…†ßï' qñßþ-ßDxg0È×B!‚Á WÇbÜu×]Î<{?ñ b±@€z{|YÓû0h,£4 ²`+W®äùçŸ'p‹i²¡·×˜ÎÎNŠ..æ]ÏF"ÜP;×tù&#±àBpë„“&¬óÂÆz놣(KÀ¢ÐÝûpàù•¸¿s/ƯÁ| <÷€ùobîzö.óx›Ã$ê Ñ þ­Ù–žð<:Ï¥‰=i%Üü+vù÷vÎsŽó³z87ÿïZ4‹¦ê[Ù»×Å»~|˜cå¯pf_¯tÏâô¼ð¿¡:<ƒov^pÏÎi ¦_?ßry§Þó6}t9k×vó¾ËÛø§¯•òÛãWsýÂømÍÕ|oÍ^îÞ·Âð¹Ågùí±ãÄH¿á—š÷üŸ¹§øýÓóÒÞ²XC+'äU*YÙoó°SµóNòÛs‡ùåÙËÒ¦‰¸_"`^ÎâYgøöE¯²ñÐ¥Ö~u˜®žE|džÁ™Ù«øÎ‰||Ñ)~î^:3cÆ ºìf~Ï|>5çM¾|þºfwQ9÷gNtòÒéÕœ›qžîïw³øÜRÖ»öù–‡…'²¹hÿóÆ f0ƒ³3ÎrnÆ9n›#3WòÐ-âÚã§Yøü|«ûVf̘ÁÉ'™Ãl.XÔ΃§nãäÌ“¼Þû9{Ϭd38ú_G™ß3Ÿ¯ò­]—³ìÄ2Ìiboò6f1‹³¬Ï9Ýû9?ì˜Çe³ßà°ù¼þJgwðò‹s(žÕÅÏtò_g6páüý¼~ÞÅŠ®8]ç1kÖ,ý'¹læb¾óÚLvnÞàšà <.%|:ØÎ×Âç3Àà,—/}ƒ½³Êøå›Q±à8ëV>Áã=iŸý7þ­ÏߏSç(yôi9ÃK§.eVÏ[\˜x˜­ÏeΞ? ¤¤‚÷îûgæÑÉ|ær-/qø«Ïqœ Tr-ö=Ç\žä?XÅB¬›Çy‹ÿÜú"a¾Î•å_¾ù÷ü=ǸŒ¾óïÐˇøÄË3iæƒ!^™÷ÇÌ<;ºàô¬Óüäwç(ï¹›µ³Ö²÷ô^ŽïßÅ—æH[Ÿyþ _;S³àÑä>~áúsŠß:oÁÌY39{ìw|iq)µ3ÞΜ9søæUË þòãÌ;=S”1ÏÜÅÏu|ö¦Õ¬:´Šƒz¸}ÆãÜòÌ÷85· Þ‚u¾µ\÷èBÀCǺÊ_~šEÉÃÌ:þŒµÎË®Æ÷盹â›WpÕg~KuíW8±b% XÃ3î¸S~×Þ2^¾èeŠ.x‘Õ?ú˜Ð³p)3æáwþ'\¿“S‡N±jù*6œH²xŸ5$μ‹æëÄ‚/gÁ‚Ë8ù£f\ý%fœ}Å‹8?÷<Þ*fœ©dα9,Z}Ko­€ôo+ Xß ß{Èÿ=x0BÏÎû8{ö,sæÌ+½ðo>ÌÙ³g™ñ™üñÖ癿¢7y¼Â¤úþœg^¸¥K—²fÍp°=Â]opá-üd+|ÛúœêÆjødöüæbµŠ_ ßšyu¶OéqÉHà‰û~E¬³›àõ¿‚ξqÄ _=Ñÿs¿9:›§ÿf{÷ºøøÇ¿Nìuïâ«Ìy=Æ5«WÓxµ‡‹þðoxõÀÞx¿ÕkY}=åååÔ××;‚Áà÷ÿÆ£® áÞÖt½Ñ_Þ´xŒÇãlÞ¼™={ö¤½nw9ÜIõ¾÷½KVEãéM\Æ«,Ÿñ*§fž¢{ÖßñÒéŸ0gÎ?±àÌut÷>qâ"ÁBbÌ"8È.Ü„XŸ9˜³gsù¢_súôi^š1ƒyóæqþüy.¿üržyæn¸ážyæîºë.~üãs×]w±{÷n.½ôR°¾”W¯^ÍxßûÞÇC=4èï'Ÿ|’U«VÑÙiÝ@\»v-o¾ù&k×®åÉ'Ÿäæ›o𻳳“eË–‹Å¸õÖ[ö …Õ«Wsüøq.¸à ÍÎ;Yµj«Ržºžìãe$äàÁƒ¼òÊ+<öØcÙ.ö˜M$\{íµÐÞÌ!ptæ Îôôpþ|ê ¤ÖˆÎõÌ›7S§^ÀíNÐÓÓÊÂ…§X°`K–,aÉ’%tuuqûí·óä“Oòîw¿;í<¼ýöÛ9pàË–-ãÄ ëQÔ Lùy§sbú˾޹s'Gåšk®áÿñ³]ô1›h`ÉÓËi>lM3oæÏ97ó æÏ¯åرÄz,9µOuëFì¬YÏpîÜ¿±lY%mx<ÖÍæ%K–püøqæÍ›ÇE]ÄÙ³g¹ãŽ;|Ÿ?ûì³Ü|óÍìÝ»— .¸À‰ öwôêÕ«'u›MÇsÂþÎ{{ïØ¶ÓÅh÷õÑ£Gyá…xõÕW ‡Ãywa7Ñ:Á{ßû^ÚÚîÀ4û·™+§o€–éM ¯9¤us`åÊWxõÕ“¬];‹½{÷²jÕ*<ˆÛíæÌ™3,[¶ŒÐ‘#œ>}š¹sçÒÝÝÍK%%4vtpûí·ó‹_ü‚š’–vtp¤¤„®®.ŠŠŠxaáB::;¹è¢‹xá…øô­·’|öYŽ]|1»Žç÷~ï÷øõ¯×ëuêþ€ó÷³Ï>ëÄ »§ûÿë®»nÈy>ô¡ñä“O:ÓÚuûÄ®ÇØïÝ»×™¦ÿ<×]wà‚ .`÷îÝ,Y²„k¯½Ö¹9pàk×®eïÞ½ÎÿvÝÉŽÐwÍtÁpàÀçÿÕ«Wóæ›o:ÿ/X° ãõ¬|­G%þíÞ½›îînŽ9ÂOúÓl}Ì& âñ8Á`™}•ó3æñrÏżÌÅxgÅèžÕÍÞÓÖ0·¹ÿœGÌI›÷:þˆã|™YÚ(aops9åLó ÷²€mœ ø R–1›»ñZ ˜ž”£O/¡Ëéç9ÆJ`>Vó€.à"Øcž,_þÞxsçÎåÜùóÌš9“ä¬nb˜Ìšµ–cÇŽqÓE/sýë—²xñbž>vŒë.äGÇE§ëNZÈüù¯pωù¬8»„™3grÑÙß±fÞAÞuj!«V}€ƒ¿ÅªU«øÆÁã¸çãüùóÌœ9“–%KøÚÉ“ÎC .¾˜¿|í5^¿ôR޾ü2×/YŸ=jýô(K–,qâã3g²ëøq.¾øbþäµ×xç;ßɯ~õ+n¸á>üÌ3¸\.'Ž>6>Ÿ9Ã’%Kxùå—ùýk®áÏ?Ï¥—^Ê+¯¼Â…^Ƚ‡q¶÷s–-[†ß4Yqü¸‡/¾øbjOœ ¼¼œ_üâÎç,[¶Œ³gÏ2{öl~½h;].Ξ=Ëþýû¹síZnO‰W^x!ÿræ ³¯¼ÒYŸ:Ä]]Ì;—®®.f^qÿÚkÎÃ7ß|3w´¶RTTä¬Ï¯æÍãÉÞkLÃ0Ørùå\ôÛßrÙe—±ÿ~V®\ÉWººXtíµ¼ñÆ,Y²„÷îÛǪS§˜;w.§OŸæÔªUƒ~ÎÌ™3™7oû.¸€Ã§O;ŸsôèQ6­^ÍœGqÖgáÂ…üó[oqSu5ßüæ7³}jÙDbÁç>÷9^l>Æ“þ–ÃôµN¹‚?àE¾À2þKéáXoÏf 0Y†Á#D˜7ïSœ?ž‹.úWúžy»˜{î f̘Áïfígçœ9ÌûgϾÎ-_Ìû÷³téRŽ9ÂÒ¥KÙvâ³Ö®åµ×^cÁ‚Üýúë\zö,óæÍãܹs,Y²„º³gÓîûÝÑÚÊÂ… 9sæ .L;Ž*KJXþƒPRRBGG%%%|ù7¸öƒäÙgŸeÙ²eTìÚÅÊ”ïÜ‹/¾˜Otu¥]Ã\óíoSRRâ”íñ H¸Ý,[¶ŒÎÎNn¿ì²1ÎâÅ‹Ùòæ›|øÃžÔÏI]ŸmÛ¶¸òßÿ²²2:;;Y°`ß?vŒøÂ…Îyð±[oeù~Àe—]Æž={(--eë”}àüâ¿`Ö¬Yü¯ÎNŠ{cЉ'XµjëŸyÆ©o<‘7Üpû÷ïgÉ’%üäÜ9~sÁN]æc·ÞÊÂÿøÊÊÊœ{ÈŸ|æ|¿øÅ/X»v-7¶µ9ŸsôèQ.»ì2çszè!>ô¡9Û­££ƒ‹/¾˜ŸÏœIËÙ³Îúø½^\<ÀŠ+8uê%%%ÚÚœÏY½z5·¶·;ŸsäÈŠŠŠøJ×ü¦ë7Ù>­§4¼ãï $âÛ=¿o÷3öÁ‚qôÌΜùKpúèöþmârídÖ,ëûcÉ’%¼õÖ[\wÝuN]Üþm×wíû“¥®ûóµþ*ßïEìÞ½›ƒNøžá´H<8p€oýG<úÛ¬ZUÆo¼Á…^ÈŒOÓÓs#ÝÝݬXqœyó¬'.\ÈñãÇY³f çÎ㪫®b÷îÝi¿_yå'ø¬[·.Û›HdD¯¿þ:¯¿þ:_|1øÀ²]œ1›h%â‡?ü!?üá™;w9G^ÉÉ“'Y±â8çÏ¿ÈÕW_͹sç¸é¦›xê©§¸êª«œJ»H¡yþùçX¿~ý¤'¼&ÃDëÿñÿÁ¯½›ââÛH&qá…²`Áóœ:µŠ¢"«_£²²2zzz¸ä’KÔ¤?~œ}ûöpÏ=÷d»8c6Ñ:ÁÎ;ùæ7N29‡+®˜Éùó/²zõj:;;¹ûÀîÝ»Yµj•sSpþ>xð s] kÉWû÷ïwn’åãÍ‘‰Æ‚o~ó›|ç;¯²råJÎ;Çüùó™?ÿ`ròä%¸\;¸W^y%¿ûÝïÒ’áÇgáÂ…x<víÚÅÂ… Y¸p!o{ÛÛØ½{wÚµÅhâÉhæ±Ùó=z”K.¹Ä™ÇþÏž=>ç’K.Ad0Óýú`ûöÿæ—¿<ÊW\ÁÑ£/ó¶·wrY±bEÚý?ûïÁ®†ºg¨y4O>ÌóòË/3{ölÎ;Çg?ûÙlŸÖc–‰{†O}©ŽU‹¸â†7èììaÆŒe9r„¹s¯bþüÇ(//§»»;í;Zß­Rhìëƒ‰Ö ¦EâQD ƒâ€ˆ€bˆ(ˆˆE±@D@±@DDrÍÌl`¬ÚÛÛ¼–ŠÈØ(ˆ(ˆˆâ€ˆX D DDq@$WäMâÑwf×®]i¯ÇãqŠ‹‹Ç³HÉ3Š"Š"¢8 "ÅÅQÉ5y“x¨®®¦©©‰îîn¶oߎËåbÆ Ù.šˆLÅÅQ‹bˆ€bˆ(ˆä’¼ã »»›M›6ÑÝÝËå"™LRWWGuuu¶‹&"SDq@D@±@DDÄ¢X " X "Š"¹$¯¶x<@YY.—+ÛÅ‘,PP,ű(ˆ(ˆˆâ€H.ÈËÄ£ˆˆˆˆˆˆˆˆˆˆˆˆˆä–¼ãQDDDDDDDDDDDDDr“"""""""""""""2aJ<ŠˆˆˆˆˆˆˆˆˆˆˆˆÈ„)ñ("""""""""""""VЉdž†nºé&Ö­[Gmm-Éd2ÛEš––6oÞ<à§½½}ÌëÛfãÆÄãñAßËÄ:æê6j½G³ÿ eßgZ¡­s¦bA¾l—‰Ä‚|>'[ïéö=i…´ÎÓñX*djsq;¨NPxº»»©­­eݺu¬[·Ž78o!wëº---ø|>Ö­[‡Ï磥¥%çËÝÝÝÍÖ­[Ó–9Y±2eê¼ï¿ƒmÿLm_ņɗ©Xý9RÈÅr&dª\™*÷DbA.Å4ÞhbA®îÏ©¨dºÜùV'€ÁcA¦ê£™Fq û¦2îOÕúÜtÓMŽë|X‡©ªŒžõ•¯|¥§¼¼¼çèyüñÇ{î¾ûîž»ï¾;ÛÅšð:ÝqÇ=_ùÊWÒ~^~ùå1­w>l›H$Òså•Wö<þøãƒn‡‰®c®nƒ‘Ö{¸ý_(û>Ó q3 òe»L$äó91ÔzO§ïL+´užnÇÂpçD&Ö1·ƒê…ÉÞÎ?þxÏã?ÞóéOº§¼¼¼§««Ë™&Wëº?üpÏ•W^Ù‰Dzüñž/|á =W^yeF»É(·½Œ‡~ØÙæwÜqGF·w¦Ê>Üy¿iÓ¦žòòrg=¾ò•¯ô\yå•=?üpF·¯bÃÔÈD,ÈÆþ)äj¹GŠ™*W¦Ê=‘XK1MF6R,ÈÕý9u‚É(w>Õ zz†Ž™¨ŒfÅÜ0Uq*×§ÿqë0Uu BR°‰GûfŒíå—_„ó;ð…ž/|á ^ï\Þ6<ð@Ï•W^éü VÑÎÄ:æÚ6Íz´ÿó}ßO–B\çLÄ‚\ß.™ˆùxNŒ´ÞÓá{`²Ú:O—ca¤s"Së˜KÛAu‚µk×®ž+¯¼²g×®]Îk]]]“rÌNÆþ½ûî»Ó–ÙÓÓÓóéOºçÈÙr?þøãntuu9ü™*÷DË>Òy?Øqbï“OúÓÝ¾Š “/S± ûs¤8‹åMÈT¹&ZîLÄ‚\ˆi2:£‰¹º?§¢NérçK §gøX©:Áh¦QȾ©ŒûS!‰ôÜ}÷ÝŽë|X‡©ª’‚ìjµ½½d2IEE…óZqq1¥¥¥ìÚµ+ÛÅ·d2‰ËåšÐzçú¶©¨¨`ÇŽìØ±cÒÖ1·ÁHë ÃïÿBØ÷“¡P×y¢± ¶ËDcA¾ž#­÷tø˜ …¸ÎÓåXîœÈÔ:æÚvP p¹\.¶lÙBiiéÓäj]7™LÒÞÞž¶L€mÛ¶Q]]³å¶»p*..NÛeeeÎ:åBÍ÷EEÅ€c§¬¬ŒîîîŒm_ņ©‘‰Xý9RÈÕrFû™SÃ& r%¦ÉèŒ ruNE`2Ê/u>d¢N0širÃTÅý©ÐÞÞN$á¾ûîðz®¯ÃTÕ Íìl`2tuu 8ŠŠŠíÇ?_ìÚµ‹®®.Ö­[X_uuuÎ>šõÎõmS\\œV è/ëh¿žKÛ`¤õ†á÷!ìûÉP¨ë<ÑX‹ç@£YÇ\<>FZïéð=0 q§Ë±0Ü9‘©u̵í :Aá*..¦®®°.L»ººhjj¢´´ÔÙ¹Z×µoγuëV’É$ÅÅÅTWWSZZš³å.++sÊŸz^Ùë“©úÂDÏ©‘ÎûÒÒÒ7»»»yøá‡3ZÿSl˜™ˆÙØŸ#Å\-÷Hq`´Ÿ91l¢± PëF…j¤X`߈εý9u‚É(w¾Ô ìm;T,ÈD`4ÓäÃ}£é`ªâþdëîîæ _ø@`@5Öaªê@…¦ [<ªîînŠ‹‹‰ÅbÄb1ª««Ùºuë ŽKáÑþ›Ž…éKû^l:¦7íÿü×ÐÐÀæÍ›iiiaÆ ö`Î%7nÄårQZZJ2™dÓ¦M9}¡\QQËårn$“Içï|ÖÒÒÂÆ)..&d»82ù r‡bAáP,˜|… ¦—|Ýß‘H„¢¢"¶lÙ’í¢LH¾Å½l+È…jÏž=iÿ×ÕÕÇijj-—Â3Üþ·Ÿj’éA±`úÒ¾›Ž…éMu‚üg?¹ÇÙ¼y3.—+/ö] H»aàóùhjjbýúõÙ.Ú \.÷ß?µµµø|>Ö¯_?l—¹Ì¾IÇÙ²e @ /nNËÐò1 î½÷ÞlmP…@±   Fê#ÛT'È.Åé%Ÿ÷·}úàƒf»(–ou l+èƒeœóõ e(NÞcYï|ß6™XÇ|ß0pÿO‡}?ÓaÇ a»dbó};L×ïñ(ôuž®ÇB¦Ö1ß·ƒê¹Ï$UEEZ«æj]·Bdýúõi-r±Ü¥¥¥Äb1öìÙÞ={ضmEEE“R_˜Ìsª½½ÝyÊ:‹QWW7è 'Õr_&cA6öçHq Ë=š8©rMöù3šX1MF ruNE ÓåV ÷bšŒl*ãþdˆÇã±uëV6oÞÌæÍ›¾–Þù°¶©ªŠ‚L<ÚOú÷˜3çüCCiiiI;mÉdÒ 6£Yï|ß6™XÇ|Ü#íÿé°ïÇ£×9± ¶K&Ö1ß¶ƒ¾ƯÐÖYÇ]Ç|Ûª䯖–6mÚ4ì4¹Z×µÇEê¿Ìþã"åZ¹»»»ihhH»!ÐÝÝM<§¬¬,¯âHmm-6l`Û¶mƒ.s:ÖòU&bA6öçHq WË=RígæÊ5Öp± ŸbšŒ ruNE`2Ê­:AnÆ4ÙTÄýÉT]]ͽ÷ÞË–-[œ€ 6°eË–¼X‡©ªš‚L<‚uP7559O~oß¾—Ëņ ²]´q)--%ÓÐÐà¼ÇþßDzÞù¾m2±Žù¶ F³ÿ§Ã¾B[çLÅ‚BØ.™XÇ|Úú˜˜BZg }2µŽù´T'È_ëׯ§»»›íÛ·;¯ÅãqâñxZɹX×µ“Ú Î2íãÎîR-WËÝÒÒ’¶Íp¹\-÷d”=U<'™L:­`RRŸšžnu£|•©X0Õûs4q WË=RÈT¹&ûüM,ȇ˜&–ÑÄ‚\ÜŸSU'˜Œr«N[1MF6•q²ØI·Ô°®k3ë&ËTÖ ÉŒžžžžlb2tww³iÓ&º»»q¹\$“Iêêêr~¼„á45597™ŠŠŠH&“lÙ²…ººº1­w¾l›uëÖ±cÇŽcUebsy µÞ#íÿBÚ÷™Tˆëœ‰XOÛe¼± ßωÁÖ{º}dR¡­ót<;'2µŽ¹ºT'(?_cA.—Md(C³ƒ][ŒåW\ÈŸòIáÉæ½ûùS>)l™ˆ“UGO9†Š“ýÙ•ËeÉû.[ä¤ÆÆÆžŽŽŽlcÊuvvöøýþ èñz½=mmm^nkkkÏdî@OkkkV>;—·‹ŒÝt=÷3¡££cÐãy¨¸¢¸0´\/ßt X9c9ž‡Š#=^¯×‰#~¿ÔŸŸ¯± —ËVÈtîß`çïp×£=Æò«|…hºÆ…lßйŸ_囦c,ÈT˜¬:Âx &û³'*—Ë6]MǸ0™tîg¶ljñ˜£¢Ñ蘟ž+¡PÃ0èì줧§ÇC8Îv±D¦Ìt=÷'Â0 ¢Ñ(UUUƒ¾¯¸"ùH±`jGjjjðx<ôôôÐÙÙI"‘  e»ØR€tîÝpçïDêŠ ’+¦k\ÈV^ç¾äªé &&«Ž ’+¦c\ü1;ÛÈÓ4‰D"˜¦‰Ûí&àv»÷#‘†aàñxðù|Äb1`5sµ›Šúý~¼^¯3_(" :Ëöz½øý~gyn·›`08îé‡bOFðù|ÎòëëëÓÖÇ^Ѱçx<žQ¿?Ò¼CË6±÷c[[›³ÿìõM]Þ`ÛÀ0 b±~¿ß©(ø|>gÛ vÌ„ÃagŸuþÑnk·ÛvL¥®çPÇëpÛ²¾¾Þù?‹a†s ¤î£þej^{?ÚÛc¢ë=ÕtîÎDÎí©8÷Gsþ · b±˜³Í†:F†‹+©ÓZ\è¿SË?šyó%6 ·ý†‹öz ²RËœ ²YÍûCÉd,nŒå|í®ÛÇÁPqÄ^v[[€sŒE"‘´sh¬ûBu„‰Ó¹?úeÂÔÕÿDz]&Z°÷å`çïXêöô©±¡ÐãBÿ}\(u„ép}0Ѹº\ÈÍ냑ÎßLÕ ìÏšNçþxêùpî÷§:Âè— ¹YG˜È=ÂÔ}™é:‚ÛíÎè}‚ÔíÙ?d£0Üüùp}0ÕF'×ëSußÀ>f¦Ë¹?u€¼oñhš&%%%ÎÉF©¬¬tÞ…BαŸr±OÈp8ì<õbš&åååi_2öû¦ibš&UUUTVV:}‡Ãá´'ÛÆ:ýX…Ãajjjœƒ# zy555Îv0 ƒòòò´'"†{¤yG*óh·‰ýš×ë%‘H‹Åp»ÝiýPÛÀ0 "‘%%%ÎgUVVº}ì÷ì@f¯×hçIyy¹3_,K{²j¤ãu¤m™*µUYY™ö~UUÕ€cy¨yŒ¬÷TÓ¹?ñs"qa4eí6Íù7Ü6´¶¶z±?š¸b…`øØ0Ò¼±a¸í7\°·ÁP±`ºÄL¼?R¹3 †Û£=_;×aø8b^êôöà c¥:BæèÜY¶êÿcÙ.­ÀÐçïhëöqÐ?6r\€Â¬#L—냉ÄÈ냑ÎßLÔ ì}=Îý‰Ö 7ÏýþTGY>Ô&rÐ6u„LÞ'€¡cA¶ê£™?â@ª#ŒN>Ԧ⾽¯§Ó¹?)u€l÷›é>f;;;{|>_OGG‡Ó‡wj_ÇÇyHë¼±±±Çív;ÿ=Îÿ^¯·'8ÿƒÁŸÏ7îé‡ãóùôû ôƒÁ´òŽfymmm¶ƒÏçs–5Üû#Í;’±l“æææ Ççóõx<žÇÓãv»ÓöÑPÛÀ>êëëÓÞz:;;÷;;;”!õ8jþѬgkk«s ¥n/»ÏøÔϱ¥¯£ùŒT©Û®ÿ2‚Á`ÚXCÍ;Üzçzá:÷'vîO$.ŒÆX¶ÉhοÑlƒÁú.®z\°÷ÙP±a¸yó)6 µý~ùË_zzzFŒÙŒ==cA6ê£y$™ŒÃmƒáæýÞ÷¾7칞j°8b/g°éò!jAçþð²YÿËvÉT`°cb¤k‹‘êC-7µŒƒM—qÁÞ§…VG˜.×ã ==ùs}0Òù;Þ:Áhî Ø ñÜo`¤íšís¿?Õ†—/u„‰Ü#阘H!S÷ ìù†ŠÙª 7>ÅþTGY¾Ô&ë¾ÁHu„B?÷'£÷-í&»555Î*­­­x<¢Ñ(>Ÿ/­Y¯ßשּׁ­ÇãÁ4M§¹´ý¿MO]>XÝhŒÔ¬u¬ÓUjÖÑ6Wl;¤>ñ3Üû#Í;–}4Ò6I}⨣£ƒŽŽÀ€¬þpÛ µ)ºÝ8uÚOKØÇA#Í?Ã0l¯Ô&Éïa/Ã~!‹ašæ¨çl½s½pû#›È¹=•ç¾m¤óo<Û`4q¥PãLØ0Ôö{â‰'†Œ0ºXPèq ïev» wδ ›÷w¿û0ò¹>”áΙ±œOª#d–Îýáe»þ?Öí’­:Œ/6ä{\€ÂŒ Óéú`<çäÏõÁhÎßñÔ Æro`0ù~îOô¼j»fûÜïOu„áåK!÷‡’‰:ÂDïÀð±@u€ÌRadùRG°eú¾Áhë:÷ÓË;ܹ_‰ÇÖÖVÀj:cÆ jjj€á+~†a8ýÒ¦þäK¿Ô…ÈÞö©AÉî×Ýn^\ä½Áä󹟉ó~4Û5¨Ž0²|¨#d"LtÙÃʼnLœ ÃÅÕ2Ku„Ñɇ:Â`Ÿ—Éû s?SÛ<ïö€¯öŠz<çKÂï÷;ƒÛÄÞI>Ÿ/íè|4Wd*pÛ!õi¯áÞiÞLòz½x<ž´ÁLC¡gÔ'BÿÁzÝn÷€§Pì£Ãáð€æÀ£™8~¿?mðUû©ÛpÇëh¤î‡ÔÏp»ÝÎÅÎPO 6ï`ëmoó\zGçþÈ&rnOå¹o›èù7˜áâÊÚµk× -.Øÿ†‹ ý×=WcÃPÛÏëõ`úÄ‚‰žëù ›÷Æot^î\Š}ܧ+ÑhtÌ]¶ªŽY:÷‡—/õÛT×ú_[Œ56äs\°ÿ/Ä:‚®F–/×¹po`0ù|îg¢NлæÊ¹ßŸêÃË—:B&â@&–=TœÈDÝe¸XÍ:Àpó÷_÷\ý©Ž0²|©#Ø2}ß`´u„B>÷3]˜=¦­’ƒÑh”’’§áõzñûýNv¸²²ŸÏçôŸkoèúúzB¡< Ãpš²f›Ûí& 9'÷Dx<žÛÁív§õ<ÔûƒmÃÔy3­¹¹™ÊÊÊ´§)ƲO तę·±±qÐéü~?~¿Ÿššš´åvþ¡ØM±«ªªðz½†á_þxI p–kš¦óÅè÷û‰D"”””àñxœãÜ~’! 9¯]æD"‘¶Þ¹rŒ´=tîo"çöHqc2LôüÊPq¥¨â‚½>#ņ¡æµË±a¨í÷‰O|‚ /¼pÐ8L›X0‘:ÀhÞŸ 9çF3ïPçúpêë멬¬tÆ@p»Ýi㌆ꙥsxùTÿ‡©¯ f¬±!_ソ®…XGÐõÁÈòéú Û÷†’¯çþDëv¹sñÜl¨Ž0´|ª#L4djÙ©qÂ>ß3Qw.d³¯×#mÕ†—Ou˜üû0ýÎýL×fôôôôdfwg—‘µŸb²7@"‘p6¦Çã!‰`ÍÍÍiÓØ0Wú¥N-{&ëİ3ôƒe£‡{¤y'cÝÇòY±XŒÊÊJzzzœca,ûs¢óµ-SÇþŸ ùþP‰¦iz\ô/·=à±=Ýpó6¾Ð¹?²‰œÛSqîgúüL6âÊPÛr*ãBêr‹ #Í;Øü¹ªÿöM€é &z®çz,ÈÕ82Õ2Kçþðr½þŸOçîd.[u„ÌÒõÁÈrýú ÿºå³ò)®äc`°eä*Õ†—ëu„þë=Ÿ•+1f¸X:ÀxæÏª#Œ,×ëÙºo0ÎýL× &ñ8;ÝÖÖæd+++ ƒ“šqIj°ÊhÜL.+›ë1Q©'&矊uÌ¥íX(tîmYÙ\˜øù;Y†+×doÅ…‰›q`2–—­õ€‰Å‚lÄÕr“Îýñ-/[ë‘«u€ñR\È]Ó!6J\˜(Õ tîe:ÄÉX^¶Ö#Weó>ÁT}Æt3bC!Å…lÝ7й?vyßÕêpR›ùÚÍ£í&ãÙ4TÿÙ©FûT@&—•ÍõÈUS±ŽÓa;N5ûc[V6×#_Mö6Ð6ž¸é&cy¹þ¹¹Du„ܤs|ËËõÏÍŠ ¹k:ÄÅ…ìѹŸ¦C˜ŒååúçæÅ‚ü4bƒâÂäÒ¹?¸‚nñ("""""""""""""Scf¶ """""""""""""ùO‰G™0%EDDDDDDDDDDDDd”x‘ SâQDDDDDDDDDDDDD&L‰G™°ÙÙ.ÀTèîîf×®]Ù.†HÎ(**¢´´4ÛŘrííítuue»"9£¬¬ —Ë•íbL)Õ Dª¨¨Èv¦\2™$™Lf»"9£¸¸˜âââlcÊÅãñlA$§èú@DtÏPD`âu‚====Ù^‰Éöð,Y²„믿>ÛE™R=ôï{ßû²]Œ)µsçNV­ZŪU«²]”)5Ö}ýóŸÿœ‡z(ÛÅžr7ÜpýèG³]Œ)¥sbúë¾>xð .—‹/}éKÙ.ú”R`ú8xð äío{¶‹2¥Æº¯wîÜÉg>ó™i—|¼ûõÖ[³]Œ1Ë×s9_ë#ùZîñĿǜï}ï{Ù.ú”ŠÇã|õ«_ÍËï‰|*wn—{º^|ñ‹_¤»»;ïbýtúŽÊùZnÐ=ÃÑzßûÞÇ{ÞóžlcBòõû*U¾Æ¶Tù/R×a¢u‚iÑâqîܹÜvÛmÜsÏ=Ù.Ê”joo§®®.ÛŘR TTTL»›gcÝ×íííÙ.rVÌ;WçÄ4¡ø7²x<>-ŸòW`ú°ñé¶ÞcÝ× Ù.rV,]º4/|=—óµ>’¯åOü›®×oûÛóòœÊ×X rçv¹§ëõÁ’%K¸óÎ;ó.ÖO§ï¨\¯åÝ3­åË—çåþM•¯ßW©ò5¶¥ÊçxÑ&"gÆxìîîfëÖ­ÜtÓM¬[·ŽÍ›7èœijkkGÕEÒÕW_Íš5k²½ŠS.Ÿîñª®®¦¬¬,ÛŘr…²¯'3\vÙeÙ^Å)§sb¡Ådã€IDATú(¤}­:AæMÇs¢¬¬ŒêêêlcÊÒ¾M,o _åëþÍ×ï¨|-w!ſɾ>ÈWù Tn•{¼ Òw”Ê=Z… FVû:_c[ª|Ž™”3‰Ç††âñ8÷Ýw;vìÀår±iÓ¦´àÐÐÐ@SSuuuìØ±ƒd2ImmíˆË^²d .Ìö*N¹éØwqqñ´ g_OfX¼xq¶WqÊ霘> i_«NyÓñœp¹\Ór¼²BÚ×#Å‚‰Ô òU¾îß|ýŽÊ×rRü›ìëƒ|•¯±@åV¹ÇK±` }G©Ü£U(±@q`d…°¯ó5¶¥Êçx‘I9“xljjbË–-¬_¿žŠŠ ¶mÛFwwwZ“Ζ–ª««©®®v¦ioo§¥¥%ÛÅ‘ PP,ËH±@q@¤ð©N " X "Š"ù&gýuww§ýßÞÞN2™Lëß·¸¸˜ÒÒRvíÚ•íâŠÈ$PP,Kj,P™žT'P,Å‘\7;Û°Ý{ï½444ÐÝÝMqq1MMM”––²aúºº ,ZTT4â ·o¼ñ†30i!ôu,2^MMM´´´°ÿþleP“öïßÏæÍ›Y¿~½úÚ–imóæÍtuuqå•Wf»(ƒšŠ:AQQ;vìÈöªŠdM{{; ìß¿À¹”+†‹ö̓ñÖ >ÌæÍ›)--ÕõLk ´··søðáleP“}}ðÐCÑÞÞN]]]AtO&2^º>Ðõˆîêž¡ôuk<Ñ:AÎ$íAC›ššp¹\´··³eË–Œôé{á…ò| goªˆL»»Í›7g»(ƒšÌ8pÙe—éBBرcñx<­K’\¢:Èä+--eÇŽ444d»(CšÌX°|ùrÕ DÀI¼O×ëƒ÷½ï}zø@]èú@D÷ uÏPÄRWW—‘:AN$“É$›6m¢ººÚ©ô···³iÓ&Š‹‹õ”È4 8 " X "–‘bAqqq¶‹("“LuÅQÉG91ÆcKK ÝÝÝiOÚM¥ûþ:XÓhu‰"’ÿD DÄ2ÚX 8 R¸T'P,Å‘|”‰ÇÑ4‰¶»<è?l<×Ï"@q@D@±@D,#ÅÅ‘§:ˆ€bˆ(ˆä£œHŸ–––Ó444pÓM7±nÝ:jkkI&“ÙÙr"2)D DÄ2R,P)|ªˆ(ˆˆâ€H>ÉHâÑårár¹¸ãŽ;غu+ ~FÒÒÒⴜܱc‚ƒ=†d]];vì ™LR[[›ím("¢8 " X "–‘bâ€HáS@D@±@DDòMFºZM&“QTT4î§"‘[¶laË–-TTTÐÕÕE<§ºº°Luuµóÿ¶mÛœ§Ö¯_Ÿím)"¤8 " X "–‘bâ€HáS@D@±@DDòMFuuuš?™LÒÞÞ>`9Û¶msþnoo'™L¦!Y\\Lii)»víRðÉsŠ"Š"b)(ˆ>Õ D DDq@$e$ñhK&“´´´ÐÕÕXO¤žìÃÍV0غu+Éd’ââbª««)--H[fª¢¢"ÚÛÛ‡]þÑ£G‰F£$“I牑é(Ç9|øp¶‹2ÀdǀÇÓÐÐ0êØ$R¨8xð .—+ÛE`ªêñx|ÂN‰ä³d2ISS;wîÌÉïÄ‘bÁDëGŽ¡¡¡ÁY¦ÈtÕÔÔD2™äÈ‘#Ù.ÊSq}°sçN¨®®¦¸¸8Û«,’5º>Ðõˆîêž¡X×O<ñÄ„ëã`ëÖ­ø|>ؾ};Û·ogóæÍø|¾QÜ7nÄårQZZJ2™dÓ¦M£žw8óæÍ£´´”²²²L­®H^*..¦¢¢‚E‹e»(Cš¬8°hÑ"***tSA¦½ŠŠ JKK™7o^¶‹2¤É®èBB¦»¢¢"***XµjU¶‹2¬ÉŠóçϧ¢¢B×2í•••QQQÁüùó³]”!MæõÁªU«¨¨¨ ¨¨(Û«)’Uº>Ðõˆîêž¡X×™¨d¤ÅcêÀ­ÕÕÕN64ÓÐÐ@mm-±XlÄå§ŸfŸÏGSS÷Þ{ï„Ê7wî\®¹æç ‘骸¸˜ââb¶oßží¢ i²âÀâÅ‹u1!B߀¹ØºÁ6ÙuÅ™î\.ÄãñleXCÅ‚‰v•d'E¦;ûyº^؉G‘éN׺>Ñ=CÝ3”é%â÷û¼n÷04Ñ:AFZ<¶´´8ƒ»¦6Á¬¨¨`Û¶m$“ÉQÝÔèßÍÑúõë¦Ô¶ÁžbPBQ¤p(ˆ(ˆˆe¤X 8 RøT'P,Å‘‰ˆD"iÿ¦¡àDd$ñØàÖTvóäáš=Û]íÚµkÀrmöòûOÇÕZ¤(ˆ(ˆˆe¤X 8 RøT'P,Å‘L°¡PÃ0†L<&‰Œ|^FÅÅÅC¶h´ŽÃ=Y`wõÔÐÐ@ww7`…–––´n”ª««ijjr¦Ù¾};.—‹ 6ddcˆHö(ˆ(ˆˆe4±@q@¤°©N " X "Š"aš&‰D‚D"aD£Qb±†a :mÿ–‘ã•‘1ׯ_ïôÿ¼aÃg€W{ŒÇÑ Ò|ï½÷R[[ËM7ÝDii)ííílÙ²%­ u]]›6mr’M&“ÔÕÕ¥uï*"ùKq@D@±@D,#ÅÅ‘§:ˆ€bˆ(ˆŒWUU>Ÿ°Z=†1dr1‹‘H$øøÇ?>áÏÍHâ±®®°ž"è?­=ÎãHŠ‹‹yðÁ–“ö€¶©\.WÚ4eee "Dq@D@±@D,#ÅÅ‘§:ˆ€bˆ(ÈôcgÈ÷Ãá0Á`pØe$‰´ÖÑhÔy¬D£”´_ÏTW«I<‚•| ìÚµ‹öövçäëà­#µŒí4"’¿D DÄ2Òy®8 RøT'P,Å™>"‘õõõC¾‡ñù|¸Ýî!”ö8Žv³ÿïþì¤ãSO=5áògdŒG›Ýßò–-[X¿~ý˜“Ž"""""""""""""Ó•aNâ°¿X,†iš„ÃaÊËËÓÆk´»Qµ_·[4úý~‚Á ÇI@¦~V,Ãív³gÏž —?c‰Ç¦¦&6oÞL{{»óÚM7ÝÄÖ­[]EDDDDDDDDDDDD¦+{¼Å¡$ LÓLû?RRRB8ÆívF1MÓIPš¦IMM ‘H„D"A$Áï÷ã÷ûÓv­öç' *++=ztÂë—‘ÄãöíÛÙºu+@Z¿ÉÕÕÕ<üðÃlÚ´)c;DDDDDDDDDDDDD$E£QgÌÅT¦ibš&†a8]Ÿš¦Iyy9UUU¸Ýnb±Á`ŸÏG p¦³‡B!Ün7>ŸÆÆF§•£Ûí&àõzœ$¥ÏçsZCæL‹Ç¦¦&ª««Ù±cGÚ ®uuuÜÿý´··;ƒºŠˆˆˆˆˆˆˆˆˆˆˆˆL7©]›ö …$$Ãá0^¯—žžZ[[q»Ýø|>Z[[ñù|Îrì®RMÓ¤±±¯×ë$=“lL]n("‹á÷û©¯¯ÇëõfdŒÇÙ™ØPÉd’õë×úž=Îc{{»v‘i)‰àñxˆÅbÔÔÔ8 A;‰Fq»ÝN Æh4êtêv» ƒió†AMM ‰D‚`0èt±jw¯j«¯¯wþöx<€Õš2‘H8˳8p`B똑ÅÅÅC¶hL&“@_RDDDDDDDDDDDD$Ù­Ç3_8vº?D"NËC{ÜGÓ4ñz½†áŒãè÷ûeØIH°‘­­­$ 'ØÚÚê¼—ÊN6¦þ q»Ýi­!×­[—‰Çõë׳}ûv¶oßNww·ózKK µµµ«µ£ˆˆˆˆˆˆˆˆˆˆˆˆä5Ã00 cLó˜¦IUU•Ó1ÐÚÚŠiš@_—ª>ŸÏiÉFñûý’ˆ©ìnW>Ÿ/-Á8¿ßꪫ®¢³³sBÛ'#]­ÖÕÕÐÐÐ@CCCÚ{¥¥¥lÛ¶-#""""""""""""’5£M<¦N …hllúZ.Ú]§VVV:IG¯×ëŒ÷ØÑÑ1âç¸Ýng¹£a'›ï’K.áù矟ÐöWâ±½½‡~˜ 68]¨ÖÕÕQ]]M<wºW­¨¨PKG)†a8c0$ <Ï€–‰vò¬d_ssó€iì¤×ëuZ<‚Õªßïu ƱJM>¦úèG?:áÏWⱸ¸˜ââb"‘ííí¬_¿ž²²2Ö¯_Ouuõ¤l‘lKmñF1 ƒæææ´ib±­­­º3ŒÝkêÿõõõÙ^Íq×.—‹êêj¶mÛÆƒ>Hqq1ñxŸÏÇÖ­[iiiÉöz‰ˆˆˆˆˆˆˆˆˆˆˆˆdT"‘HK<Úã1ÚÝ©‚•t4MsTIG°Z>¦¶>Ìפ#d`ŒG; ikii!ó…/|ÁéjuÆ ¸\®l¯«ˆˆˆˆˆˆˆˆˆˆˆˆÈˆìîT½^¯óšišiï{½^LÓ$F ‡ÃN÷©~¿?Û«ãjñ8œõë×sï½÷òÔSOH&“lܸ‘öööl¯«ˆˆˆˆˆˆˆˆˆˆˆˆÈˆLÓ$‰8ÿÇb1B¡±X °Z:†A,Ãï÷ÓÑÑá$MÓœ´ñs]ÆÉd’––ººº¨««#‹QZZšíu‘i&ŽyžX,F$qZ9¦&}>555ÔÔÔ8ÿÛúwÅ:ÝL(ñØÐЀÏ磡¡Áy­©© ŸÏGmm-›7oVkGÉšÔ–‹c.‡ŽÐ×ýj,K›Q&xlhh`ûöí”––RQQX-·nÝJii);vì`Û¶m$“ɴĤˆˆˆˆˆˆˆˆˆˆˆˆÈdI‹Ñîu4ó¤N—H$ðù|„ÃaB¡x½^¼^/>ŸÖÖV<OÚ©Ý«¦¶‚œNfg¦îîn¶oßN]][¶lq^ojj`Û¶m;¯×ÖÖÒÞÞ®îVEDDDDDDDDDDDdR…Ãaêëëœdb,2h·f쟰lll$H$ðûý$ '! Òæ™®ã:¦Wâq×®]TWW§½n'S“Žëׯ¬ÖJ<ŠˆˆˆˆˆˆˆˆˆˆˆÈdJm¹hw:Ô¸‹†a8]¬Æb1'‘hǃßï¬.VS@€p8œ¶<Ó4Ó¦™nÆÕÕj<Àår xÝîvµ¿d2™íu‘fš&‰D°‰‰D·Û=lâ15á‰D())¶`ôù|ic:ºÝn§e¥-‘H ùYÓÁ¸vr±»»Ûy­¥¥€²²²´ií„£Z;ŠˆˆˆˆˆˆˆˆˆˆˆÈd±»B+XYYI,sºKŒ¨Lí’Õ4Í´±mn·›`0˜íÕÌiãJ<ÚÉE»é)ôïhw­Úÿõþ I‘L …BNÑî*Õívã÷ûÖýÙ¯†Ûí&‹ ‡2µÅc©-$‡š¿ÐkŒG—ËÅ–-[ؾ}»Óíj{{;[¶lq¦ioo§©©‰¦¦&¶lÙ2 [V‘LIí25ãóùhnnÆív¨¬¬¤³³sÈùí1}>߸‡ý»fŽÆ•x¨««£¸¸ØébuË–-ÔÕÕ9ï744Ǽ.""""""""""""2‰^¯×ùm·Plll$‹9­"ëëë1MÃ0ðûýN¦okÅLwâ ººšêêêAß«««Ó¸Ž""""""""""""2éú'‰Ä€ˆ~¿Ÿp8ŒÛí¦²²Ò™ÖN4z½^§«ÖéÂNÐfʸÆxLljÇã´··§½®¤£ˆˆˆˆˆˆˆˆˆˆˆˆL{¬FÇã$K<ºÝn:::hkksæóz½ƒAÜnwF“p¹.RUUE(JKÜNĸ[<¶··S[[K2™t^«®®æÞ{ïÍöv‘i¨­­Íé^µ—©^¯×óÑëõ:]²¦¾?Ñq=OÎŽõØ¿u£=fMM ‡²²² Ƹ[<644ÐÕÕÅ–-[رcëׯ§©©‰†††lo7)0ápxÐ×+++1 `Ȥ£-õu; —úZ0œPs5éhUUU˜¦é´n¬ªª"‹ÑØØHMM ŸùÌg&ü9ãJ<&“Iâñ8uuuÔÕÕQQQÁ¶mÛ(--ÐåêxtwwsÓM7Ǽ×ÐÐÀM7Ýĺuë´¸‘¡8 " X "–¡bâ€Èô¡:ˆ€bˆ(„B!"‘È€×c±†a hÍ7’\MfJ"‘ ¦¦†h4ŠÛíÆãñ‰Dœñ-ƒÁ ÓýìD®¶q'Š‹‹Ó^¯¨¨ÈH¡jkkéîîðzCCMMMÔÕÕ±cÇ’É$µµµùLÉ-Š"Š"b,(ˆL/ªˆ(ˆˆâ€XB¡•••i]¤ÚìÖŽ@`Äee¢kÕ\‹ÅH$˜¦‰aÔÔÔP^^Ž×ëÅívc¡Pˆªª*§kØúúzÊËËyóÍ7'ôÙãîju²lß¾®®®Aßkii¡ººšêêj§•e{{;---Ù.¶ˆd €bˆX†ŠŠ"Ó‡ê"Š"¢8 }±XÌé.t(©IÈ¡ø|¾¼K<·Þ‰DÂi凉ÅbƒA:::ðûý˜¦IMMÓÒ±¾¾>mþŸÿüçœ8qbBåË©Äc{{;‘H„ûî»oÐ÷’ÉdZ«ÊââbJKKÙµkW¶‹."¢8 " X "–¡bâ€Èô¡:ˆ€bˆ(HºþɲÁZ>ŽEj÷¬™àñx2¾ÌTCs ‰DˆF£ttt8ÛÆ0 Ün7õõõ466ÒØØˆišTVV(çßÿýß³`Á‚ •oö¤­ùuwwó…/|@ @iié€÷í'úwçZTT4⸒G%’L&©®®ÎöªŠdM<'søðáleP“>LCCëZ$544pðàA\.W¶‹2¨©¨ØcU‹LWÉd’¦¦&vîÜ™³ß‰ÃÅ‚‰Ö Ž9BCCÅÅź>i­©©‰d2É‘#G²]”AMöõÁÎ;ihh ººzÀP2"Ó‰®t} ¢{†ºg˜«LÓ²Õbêøv Àñ& GÓ%ëXøýþIÝ.±XÌùÛ0 *++immÅ0 |>Ÿ³m‰D"Ö/8Û*µµgSS Ì›7oBå›PâqóæÍƒ¾¾nݺ¯íÙ³gØeE"ŠŠŠØ²eË„Vh0óæÍ£´´”²²²Œ/[$ŸSQQÁ“O>™í¢ j2ãÀ¢E‹¨¨¨ÐM™ö***xþùçyíµ×²]”AMEàšk®ÉöjŠdUQQÑ=CÝ3̦i:ãÚ-ò|>¡P¿ß×ëqLÇ‘ÞÏU£I˜F£Q à ÐÚÚê$Kc±n··Û×ëMkméñxM:¥´´”®®® × ÆxÌd÷ñxœ¢¢"¶nÝšözCCEEEìØ±Ãy­½½}@Q E‘ü§8 " X "–‘bý¤â€HáR@D@±@D¦Ã0ˆÅbN"-âóù‡ÃcjA8™c+N–h4: Ü555ƒA§5£išÄb1"‘†a ©¯¯Çãñ8Ûi°.^3ÝìhdlŒÇx<îô—\ZZ:¦'ª««LÇÙ°aƒì÷wíÚ•,âñ8ëׯŸò '"™¥8 " X "–‘bâ€HáS@D@±@D¦“X,†Çã!‹aš&†a :]j2µ»Ñ|Ö¿ëTû5»kÙP(DOOÑh”X,F pºSµÿ÷ûýƒŽ‡™éndGcB‰Çîîn"‘MMMtww§½çr¹¨®®&Œ88µÝ”»¿þ ÌêêjšššØ°a.—‹íÛ·ãr¹Ø°aÔo8É,ÅűŒ&(ˆ6Õ D DDq`º°“Œ‘HèËÑþ]( Æá¤v[RRB}}½“€íèèÀï÷SSSãl3»KZÓ4³’`ʸÝÝÝlÚ´‰öövç©;ÁØÝÝM<gûöíÄãqî¿ÿþ“£QWWǦM›Ø¸q#.—‹d2I]]]F–-"ùAq@D@±@DDÄ¢X " X "ŠùÎ0 <†aàóùœdZÿ1‡j™kLÓ´õáPü~Úº¼^/%%%Î8v—©‡@ @,£ªªŠžžžl¯îãN<644L&Ù±cǠݪ®_¿žõë×S[[KCC÷Þ{¿gÏž¯¹\.|ðAâñ8eee "Lq@D@±@D,ýcâ€Èô£:ˆ€bˆ({\G;ñÖv—«ƒM?˜Á¦Í&»¥æP­4+++ñz½Ô××}ã9†Ayy9x<zzzœ.hmx½^jjjhkkËöªj\‰Çd2ISS[¶lv,ÇŠŠ ª««Ù¾}{FŸ.Ëø‘"R˜D DDq@D,Š"Š"¢8oªªªðù|˜¦é$}>ŸÓúq8^¯7ÛÅR"‘¶ëSŸÏG8vºSmmm%‹Q^^NsssÚºõO^Úï%‰1µªœJ3Ç3S2™¬~“GbO³k×®l¯«ˆˆˆˆˆˆˆˆˆˆˆˆdI"‘À0 B¡Ó2ÐnñèõzÄãP‰Å\N8ÚLÓtÖm0±XŒ¶¶6¢Ñ(‰D‚H$B$! âóùF•PlmmÍ©qS+ñh7WlP×þìiìyDDDDDDDDDDDDdú …BD"‘‰9{ì‰ʕd\ÿñ)û—1‹ …«Ucgg'Á`pÔ˪×\0®Ä£Ý\Ùnù8{5q™¾RŽ#µ^®Õ`v".†aà÷û¼ ……Bx½^ÍÍÍD£Ñl7ãÆ•x,++ ©©iÄiíiìyDDDDDDDDDDDDdú°[¦¶´»ªu ýº€ìŸˆKbr2ÙÝǦ®WMMó4¥¼¼ÜI´ÚÓ†‘Óc5Ž×¸.—‹êêj¶oßNKKËÓµ´´°}ûvª««q¹\Ù^W™bö8†`%êR“C%s%±8’X,F,sþw»Ý466VrÑívÓÚÚŠÏç#‘H8­3ý~?mmmZGæ»Ùã±®®Ž]»vQ[[Ëúõ멨¨pÆsL&“ÄãqZZZ(--¥®®.Ûë)""""""""""""YпU €kr1[𦙶n±XŒp8Lcc#†a`ÍÍÍ€•ˆŒÅb9=FãD;ñèr¹¸ÿþû‰D"455 hùèr¹Ø²e @@­EDDDDDDDDDDD¦‰P(„ßïwºíŸx/{y© ÈD"‘Õ±‘HÓ41M“úúz‰555´µµ¥eÙÑÑ‘µrN•q'ÁJ.ÖÕÕQWWG<O{¯¢¢"Ûë&""""""""""""YPSS“6®¡ÛíNKz½^§Åcÿ€©ÉºÁx½ÞÝ›fKee¥Ó’Ñ4M<^¯—`08âz¢ %S •hlhh`ûöíìÙ³'Ûë*""""""""""""“Ì0 ‰„“Xôz½x½Þ´V©‰ÇþK$ަ[Öl´|lllt¡n··ÛM4ÍÉna§ÂÌl@DDDDDDDDDDDDò›iši{½^§«QŸÏ‡ÏçKk©8ÚÄœp4MsÈyÜn7===S’xŒD"̘1Ã)[ee%n·¿ßO4%à÷û'½,¹(c-EDDDDDDDDDDDdz ‡Ãx<'ðz½Ô××cÆ ‰¸Ñ´b4MÓi)™Úuij¢sªº4D"´¶¶RUUE0¤±±Ñy? ‰D¨¯¯Ÿ’òŒ‹iÂ$¶ÆT‹G7;hu}Ýžú|>00A˜š<Ž=Fä`Ÿ9•ì¨ÏçÃãñ‰DÒºõx<¹t4€? ClÂK’Z<ŠˆˆˆˆˆˆˆˆˆˆˆÈ¸ÙIÀÔä`ìdäh[(z< ÃÀ0Œ)kÕ8ÔúÙÉO;‰Z__ïŒë˜7~’€ŸÄ`'ÐLBÑÕâQDDDDDDDDDDDDÆÍN¦þ?œÔdÝpã2ÚݳÖâÑ6ÚV“£‡©ªªr–kååå$‰Ÿe[™7à2 Ã„e@f70ÎñxœÍ›7gy눈ˆˆˆˆˆˆˆˆˆˆÈT³Ç]´“n©ÝžÚÔÐ~°Äcÿ×LÓL{-uÙ™îrÕçó‰DˆD"N¢±££cØiÞhIÀŸ5Æ£H¾Ì~ĸEEETTTd{󈈈ˆˆˆˆˆˆˆˆˆÈ ‡Ã$ êëëI$$ ' i'ëFj 8Üûý“|†aàóùF5o&Öͧ1‹9ã9„c&,è]/ÖX¹x,--eÇŽÙÝ8""""""""""""2¥ à ãv»©ªªÆÖÝéx’x±XŒ`0˜ÑuH-GjâÔãñàóù‡Ã†át÷ZÖzáՔģ1¡¥ j\c<¶··³yófÚÛÛ³¸uDDDDDDDDDDDDd*…Ãa|>~¿·Û6âhº=õxŒ»°Ì‰ÜbZÉÇ WⱫ«‹x†B¡´eøý~b±`µx¬¯¯wÊiš&>ŸÖÖÖloâÉ‹ÁƒH€ßÄ ¿Ÿ¥mmþ%EDDDDDDDDDDDdH‰D‚òòò­Ç£¾¾Þi8\ÒÑívãñxðù|ƒvÝÚØØ8èë‰DÂiщD‡ÃNkÌH$âL‡¿}>ß -' J,³àÇjñ˜HX‰Ç% ˜„æföâþ%EDDDDDDDDDDDdH‘HdÔ­Ç2¾ãpÓÚII;IÙß`­ íeúý~B¡555´1=“dŒD"iÉÈ‚f°Ømoë`{NÖ[-!3@‰G”išƒv±:Ç“‘1ëëëñz½£JdVUU9G"LÓÄ4M‚Á •••Äb1¢Ñ(±X ¿ßÛívŽYÚ²SÌ4á¤×ÓÑë…úú¾÷üX¯gÀì‰Ì¼yóæ¯mß¾íÛ·x}Ïž=“¹¹DDDDDDDDDDDD$ƒ"‘555£J&z½^‰õ© ­ Kò2‘H‰Døý~ü~?åååƒÁ´± ËËË.\;:: ¿{ÕT±Tayïÿ©Û׋•xüÀÄ?f\‰Çââb¶lÙ’íM$"""ãôÔSOñì³Ïf»""""""""’à ÃÀï÷ÓÜÜ<â´n·{Ìã?z½Þ 'ÿ‰@Ã00 ƒÊÊJš›› Âá°Ój²££Ã)ëXº„ÍðFíëæt*õô@hˆ÷ü@†Š4îÄc]]ÝÔo‘aCVØ ÃÀ4Mþó?ÿ“Å‹g»¨""""""""’Ãb±Øc,fÂx[Gš¦I"‘Àçó‘H$0MÓéF5 âõz$èh»ˆ2±˜•xc’vRy€¸lÅeįOhQ93Æcww7[·n妛nbݺuø|>ZZZL×ÐÐàLS[[K2™ÌvÑE$CDÆ&ê{DÉ0 b±555”——cšæ óÄb1ÊËËyê©§¸ù曳½ ƒR,],P)lªˆ(ˆˆâ@6¥&÷r‰d¬©©!‘Hà÷ûill$‹aFZkÆœK<ÆÔ~^y9ôŽgI ÷g0~X¼gâ &œxljjrNò¦¦&6oÞ<èÏHjkkyøá‡¹ï¾ûرcëׯ§¶¶6-€444ÐÔÔD]];vì ™LR[[;ñ."9Aq@ddáp˜eË–‘H$‡Ã$ –-[FII ¡PÓ4q»ÝD£Ñ´ä£a„B!b±^¯—›nº‰ .¸ Û«3(Å‘câ€HáS@D@±@D²Å4MB¡gÔ]¡NÖx‰‰D‚ÊÊJç^W("ÒÖÖF4%bÑh”D"1`lȬu©:ô Y­§‚aXŸg'#½?ƒñÁ¡šðGŽ;ñØÝÝÍÆÙºu+»ví ™LÇ)--ÅårÇéêêq<Èîînâñ8÷Ýwëׯ§¢¢‚ºº:JKKyøá‡éZZZ¨®®¦ººšŠŠ ¶mÛF{{û O7ˆH~QœaTUUaš&Ñh”p8 @ee%`%"====´µµÑÜÜŒßï' QRòÿ³wïñQ•wâÇ?á® ' \#x‹ ^'¢¦UªTP+ÕvB/V¡[&µÝŠÝRgÚ­´Úm7³¥[iwÛf°Å^v·d~Õj­b3õZÒJ3x#\„Á€ B —òûãÌsæLîÉL23É÷ýzå™ÌœyÎ9s¾óœçû\fÙχÃAÂá0>Ÿ|0Õ»Ö.‰Bè^,8 ÄÀ&u!H,BHèk¡P¨Ã¿•””‰Dz4j_&ø\.³fͲ×s,++CÓ4 ବ̞bU×õ®ËÑß#S%‚âb+騤°Ó~;Üù ½m¯÷Ýwuuu¬]»¶Íz«V­bíÚµ<òÈ#ÔÕÕÑØØØé¶êêê(**¢   îñùóçÛ¯­©©±Ÿ§äççSPP`'>…™Kâ€ñœ#Uo-¿ßoW¬LÓD×uB¡P›é.<š¦áóùÚsÝ›¦‰ÇãIõîuHbºŽ„ø¤N „‰B‰}É4M»ÃºS0$++‹H$BeeeÚ‘ÜnwŸ¬Y\\ŒÏ磼¼Ã0(..¶GWVTTØ#Ãá0@ Ã%ˆkô߬YPRÒÇG¸Óe•£¿TTÄþßÙT«À°£Ã_?>¡·ëUâ±®®Ž7âõzY´hQ‡Ï+((`ÕªUÜwß}n¯  €õëדŸŸo?ÖØØÈSO=e”††€¸à››KMMM§Û?uêÛ¶mëòyB tjTò±cÇR]”6ú:;vŒªª*™ß]¤55…jaa!^¯—úúz<]i*++Ãëõâr¹ìùé[Oár¹¨­­ÅçóQ[[kO5áóùp»ÝTUU±mÛ6N:•êÝm£¿êUU‰-’-D¦S½†÷ïߟꢴ««XhàäÉ“TUUÉýôjjj¨ªªâäÉ“©.Jýq°ÿ~ªªªºì,-Ä@'÷r „´Î6CÕѽ½Ç}>õõõ=Áèv»“ÞáÝ4M¼^¯]–@ @eee‡ïïõzÛ_“Rr …¬Ä_8[÷°¿¹ÝЪ=Ï)N,/é÷ƒi‚?âÁ¨¬eV¡FI‰õø¬ùø¼õ¡äåÅf}­©©ápîa&î˜Ðîõ:ñ°téÒ.Ÿ»xñb»a£»6nÜÈm·ÝF~~~R²ãÍÍÍÔÔÔHï1è©JÄñãÇS]”.%;?~|PV"Dúóûý†a(//·§ŒÐup8Wiª¨¨°ï¬B§iÓ4ñù|TTTØíÍÍÍ©Þõ.õU@Ä`×ÐÐÖ‰ÇÖ’ TâQîÄ`·uëÖ´M<¶Ö÷*ñ¨+…¬äþ@î„6ÃÁÙfŽf›Â޵C¡áp¸OF-öTaa!~¿?®|.— Ó4ãsÒ4`0h%)Uf­°ÐÊ©ŽeeP^nýÛÙÈȾärYïߊaXE z_4ðò©³fYÛ1 ðù¬™V#ðN£ÁšÕ4Áë…ÒRëµ[·neǘ ?6<¡ÝÖ›©/㜜œ¸ÇÕüÉNê9555mþÖZ]]«W¯¦ªªŠ+VàõzÛ¼GoŒ7Žn¸¡Ë÷b +**¢¨¨(­{÷÷U˜4iR›©¡…Hµn£×ë%‰Ø"Ã0p»Ýmzm¹Ýn@ÜÈF5Dw*‚ê}TϰU«VQUU•Ö7×R'¢oåçç³jÕ*Ö¬Y“ê¢tª¯bÁøñã¥N ±Îăõþ`Á‚ „@îäþ@i3Œm†jv,]×1¢#ý~?Á`Ð^'1Âá0š¦Ù³~†7*S×u***:-Ÿ®ëhÁ 5¼b ÆHÄúq¹¬,\ª’«Á UG;_ šf%½^+gÚÛâ›P1ÒGhááº.‡ÒRëØyÎb0 Àu—õ‘ˆõþ`ÝÔn©åð?'´‹½J<±nÝ:êêêâ†8çççÇý±Ñ‘­ç`n­¦¦†eË–QTTD8n³çóZo««m !2ƒÄ1Й¦É¬Y³0M·ÛMii)º®ãõz ƒ†ÑîT*áØÞÈÆî,ðír¹(//Oõîw›Ä!t/Hb`“:$!$ô…`0ˆËåÂív …v»T»Ó”öµn£aö `º® ©p¬QhwÌD¬ ] ••v"ÏãñXIÇòòøìš^µ“)NûZèáãPFûéuD¢ÉÅ@À˜éõZÉÁP(¶{=™µVÍ øÆÜc®¥üÿrˆD¬­wY;4êo¦i%?ßYòUçT±€½ÞÏ^Mµ:þ|6lØÐåsÕs: ÊÊ•+Y¼x1k×®m÷¹ªçQë骪ªºÜ¶"3H™išv¢±ººšÊÊJ***¨®®Æçóa§ÝÊš.µ½Þ\Ýkß•ÂJUOI,B@ç±@ ƒÔ „ ±@!q /„B!{ÝÄp8ŒË墺º:eIG°Ú®|>Ÿ½üPYY§ã%† ÃJ0jš5ohtd¤Çãêê¶CÝîXV¦2 ¡¤„H$6`2Q¦}¯H„à×vÈ^MxïlB¿m&ðéW­©PÕ®·Í™vµýpØšI6¸à!"û'ãþö£ÇÔJ^Æ5)º€VMŒÕÕÖaL–^xÌÉÉaÅŠ¬[·Žüüü×zܰaëÖ­céÒ¥^àjþ䢢¢6Ó:äææÚ½–.]ʆ X¼x1999¬[·Žœœ/^œ¼#"„H ‰"ÓE"k*‡è·´ßïÇårÙÓA„B!4M£¼¼¼ÍFMÓp¹\Ž^L‡¹õûƒÄ!t/Hb`“:$!$$[$¡¸¸Øîä®Ú­ÊÊÊR6½ª*—išmÊ ÚÒÚ¥Œ.—•0Œ¾¶ÃÎ÷=§h8lMkZ[ øýDžm$0ñèù%hO TuãÄdÀÊoF"ÖæÛ™¨ÌÞX¹ÍøýŠ­¥è»sáúÉTßù\eó ÚBÉ®F߂כe¿¦¬ÌÚÒÒŽßO1ŒØˆIß’øöý÷c‹qÝr¡ýœ6‡OZ•Óï·’žn7=Ú«´aœ^oÁëõRSSÃêÕ«Ù¸q#vÏ5/¼ÚÜÕüÈ*`¬\¹²ÍßŠŠŠX¿~=`Í9¿lÙ2n»í6rrr¨««cÕªUI›ËY‘:D¦ ƒÜn7eeeVåÆëõÚÓT¨ŠœÏçë4yXYYÙéèÅTö8ëO „нX q@ˆMêBX „8(5}¦RZZŠÇ㱓yª+UIGµÎ¤išÝšÕË|öÂkkp¯ÿ¬µ_*ÉØûŽuý~+i ‚ûHÅ›}¸Ý§`¼†yíÊ6Ý…ëµõ„j€ÐïÐàž/Bé½±a‰¦‰±gúe¹ƒV’±¼‚?:Nù9ß"r²€’'îÀóÙÑdâd´œ3¸V߀ç?¯Æ|}Þ`a\1uÝÀÏï·kTÉSÇ: ¾õó@«¦uÚµÍa a%[òè`OFº˜/~qsBç5«¥¥¥%‘ ¬[·Ž 6Øk9*ùùù,Z´¨OeUÁfþüùÝ kÖ¬±Èb R=.º;zùòåö—r¦êi(û-RK­Ãèv»)))±×f4M3.áhš&‘H„òòrÜnwJ{ŒuDuÊôÅÓ¥N DbÂ5!u!7®‰žÆ‚R"YÊ5!÷B$f0Ö Ê~·Ç4­ÑvÕÕØíU@€êêên/ÝÓ—Âá0@€Ï~öŸyúéÍLž|;?úÑ…>?p÷~\ï>EÉ£Ÿ†1cœË:vã½b£KK­‚µµÖhAwÞÂß~‘²&Gr{Ö,+Iéóibîi òè[¸wü—Õ_^N¨èGDLÅ{ÕkÌúÝ÷Ðuë="UÍo¼OÙ©Á5ßÖÏaj:yyÖFçØÿÇwà}î3èY·3æ›G0ö Áu]NÜN˜Å%nx}Ç“3¯Çœ{ee=œ&µð7êÑ1-?¾Ÿ9så¾ûþ¹×ç6á1“+V¬`ÅŠÔÕÕÙÉÇüüü>;Y*BÄSkâ’Q€ÄÑ?T¥Ìëõb~¿]×ãF:ª¿¹\.{ÊÔÂÂBt]4Ó£¦’Ä!„Ä!H,BX$!$ʦ5`åå—÷PRR‚¦iø|¾´H:ƒAJKK©¨¨–ÐÒò/¼0 È­GøNÞ=ßÄ\ý#fÍ}Èi*Ïþ;õe‡) ù0ŒŽ€5¢Ñí¶žSRõõدñz­d]$¡Ý—R}ÃOâ7PQ+ˆ¦¡i¥ŸœIyùµv|xÊçˆì:ŽçT-•Ãw~9r ååÙD"Ù¸BÐºŽ†52Ñ™(ûÃ<(ž+XtÝÊÈS§)>ö(-!ðx0¾øh~άì}¸ÎŒFw½CÙ+Ÿ…«<q÷,1PF›ÑަLy×]{©ª:™ÐùM|²Ö¨¾N6 !:ÖîB¸Bˆ„D"JKKíÞ`j¤cee%¦ã¢Óu=nD£J@–©Q…B!„B!Dz …¬©3~úÓ—ÐuMÓRÚIÞ0 Š‹‹)//§´´Ôž)Ìï‡ë¯ÿ‡G×*t…16Âÿ§f¯‚çÏRY9×Ðja+ièñXÛVkš¦5X¬ä¢ßo=G%Ö‚Ak:T•°¬¨€ÒÒ!hžã ÛNFSÓ¬Äa8l%èÌ¡‰šHÉ+ßÄ÷£{ð~ntüËu_ÜëÝîX.3Žs!Ç蛸?ã DtŹg0ïÅ}ágÑšFZO7À,ÓJTFÏN„Ÿ6#Á:Flßžø¹NZâQÑ÷ÂáØÏN‘HÇB¡X†ØŽ"žšK¾´´”H$‚ax<\.†aP?è²g˜zB!„B!„ýÉ4­éD½^«ÝøùçŸÇëõâóùßx/†¦iÚëIVVVÚö ÃÊ·™&„ÿØ„/PBxòj*—>Dñ†/à[ªÚ¾gÚI:çô¢‘Hl„£¦YÏõù¬Õ´ªºVÕßV®iVò<]î‡×kmÃ4­ÿ«Š‘xîÝö­Ú=žnL‰Æ·‚Ñ$ç†âñ@IÉ4|Çóêë{yBÚ>¤ëÖþ$k0¬$…È *8¶þŽˆDÚÓ+¨–”X«Ž¥¥0uê×S½+Bô©P(„ÇÓy…A%ƒÁ =JÑï÷ÇM;ÑÛ^`.—KB!„B!„¢ß†•˜ózaÆÝìÚµ '5køúý~"‘‘H]/#/¯Y³f‘“óܵü$Þì_—ârYe..E©·žPªŸ€²Ë¬ýhoƒAë5‘ˆÕö­F5VTÄ,–—[ÿš¦õ“hbMÛ’+Y§¶ßívû½£mšºn•Yå¼Þø¤iïw¢ý²%sò6I< Ѻ b‘ˆõÈÎ`ÐzL”ÖÕ0¬äb{ÛíhªÕPÈ á0öüØ>¼ôÒsÀR}˜„HªH$‚ßïÇ4M"‘---˜¦I8n“„ ƒv’Q×u;Qév»)//›:µ7’1mE2*CB!„B!„bð…¬'õõVÒ¯¾~3¿þõwnëRÔT£¦i%ÝÔLŸV»v ®3¾ÇãÁëõòàƒ/ò›ßÜÁ¿ÿ;̘ñºèxé%B×…'ðzG3k–•@ ¬U[v{4ÍzßÂBë÷êê¶£[??Ñv6Ó´ÞCÓbIÇ„Ûþ®[ùçþ'%éØdŽvI< Ñ-=MÑyžM+« ‰D¬ Y¿«QŠj¨·ZÐV½—ÛmmÃåŠv …â‰.—X[®ŠD"<õÔÅüæ7Ílß¾ž††‰Ì`æÌ¤ú ‘ápØþII n·—Ëe÷¤Rë4jšFmm-áp˜@ `¯Ñhš&^¯—’’LÓÄår%­"–¨’«‡VëØã\d»»º3T!„B!„Bd¶p®»îÅÅŸ&sù凩©ÉëÕ¶"« J%ùÔÌzêñââØß"X²d =ö0µµá°ŽÛ ………TWWsÿýw2mšÕ¶}üø&®|벇Ï%<âjŒ§(þðp`8nw÷FÞ©r9gúëk*9çõ¶? ³g' (ÆJ6º°`FŒ•']V}ÏV’Ù$:¤Š.Ä€Ò“u£KK­ŸpØÚ†êq‰Ä†|VV=&Ün+p†õ·ÂBkˆ¸aX[²d[·ž ¼¼ÞR^X³gï‰+GII ÇŽ g߾ؿÿÿùŸu˜¦U†‡~£§‹Î ‘fÔ‚Ô¥¥¥ãñx¨¨¨ ¬¬ ]×í‘>Ÿ—ËEII ¥¥¥˜¦‰išTWWS^^n'ä"‘HÒÊÖÑ(äîï›7T'%¶Èvä[1 +†Çzy9E"‚²¸«B!„B!Ä€¤Ú‰"«­8.A×ujkk).î}ÒQµ7[íQšf ¶©¬´Fû©ÑeeV’ì…FeÜ}÷ã¬_ÿ<%%ðè£Ïár¹(.Ž% ¿1õ7¾ñ‘¡ ˆ ]€÷ÊWÑÎÞ£¢®[mbýÙÏ^µÛ'E¨j7V2Pý¸€ `ûb‡´;Ýj2IâQ J=Í/¨ç·~š.µõsÕš‹á°ŒJJb#««­@¬i±ÿ«aãO¬'C$¿°®Ëe½~òäÇ9uj[¶äñôÓ‡0MÈÊ:Âîݻ㒠†apùå>~x5[·ž@Óàšk¤Í¨.!z*++‹ââb{aêÚÚZ*++)W“ªc}¾Ãá0¡P—ËEYY™½vcuu5>Ÿ]×ãFF"{QëDùýwXè*išØcªg™ê°[ï£z²>ý‘<ûl£½~åË/7Ø£B£<“™dB!„B!„©áì ¤I/pà í¥„z::/´Ú›«mJp¬®n;²Ðå²¶írÏgâvû©¨€¯}íÃ̘1ƒH¾öµÓ@¬-LÃäÓ›Ÿf×u·Ü|)î6¡/_7K`w%5ØßÂX£[ϲ¨eXÉÁÒ>|ï¾JjFÉT«bPQ£üþX ìÎ4ª¡ ­×CKKliÇêÙ Ʀ< ‡±Åõxâ§Buþß¹-X C·['±’¦ »vâ7¿ÙÄ‘#;yþù¹¼ðÂ$¦Mû[¶ÌåÎ;›iiY‚Ûí¶“ VRÁÍ–- ð°k×¶m;À>p€ &¤úTÑ-¦iR\\ŒÛíF×u;a‰Dì¤"Ð&aèr¹Ek+*¹XQQaÿÝ×j®5=kk~¿õoYYì15o½ºŽÓNÄÊmUÐÔHf—+~ŠÔÒRk›­óœ~¿uÝZÿªQõ¯Ë&%%%<ûìCœ<9‰-[NRQ1ŸÏDZcsñzŸáŸØÍºuy?þÏ|øÃ³1Œ =å¬Ë墴´”o~óŒ92Õ§X!„B!„BôjwòxbmËçžû<Ë)+‹M• ZmW&ŒD¬ö&ÓŒÍÜçvǯ_èõ¶? §JJš¦5+Yeeetæ¿KÙùÊ+,ºðqf-Ji©ÕÎår& ÿÖ·¸Ã÷/Ü™šK·ÛÇz:A_ŸMEÚºP‰5«zž‹äña²ìC’xƒJII,™§ŽÁ`çAÊ9Tb£˜Âa+à–•Å¦R ¬m†õ¯ ší­¿‰Dðxj!î@ÀJ0ªŠ£ŠŸúÔ6løwî½÷rüþ-ѵ,wQ\<“ÊÊJ>ò‘òèbÝðüóçrñÅc `éÒ=lØp¿ùÍ…lÝú+{ìjÂáá™g^féÒ<æÏ?È}÷¥úL !„B!„Bˆî2 «MIÍŠõÌ3|ýë×cš&¥¥%q3Ýu6àFµ••ŶW[Ûö5MœçrÁKO?a Åëõ¢iš=*ùÚ¡¯£;ͬº›bíïš×¯:ô÷f2W2’q¡èk„¡†5j'æ¬cÑÉßt¬iXýXÓ®z±’ý8µl"dªU1 µ^_-´æ¡V G5*Äù³²Ú_—M%Õ‹ºn5]õq95ýj0Ø~/ Ó´F+ùý~òòòÈËË#   D"jjþ Ô0tè³ìÛw5`%_¶lÙÂÉ“£hnžÏñã#¸ôÒ3ìÙs½nc8FÓàŸþ)€›nšÌĉhš‹={öȈG‘–Âá0ÅÅÅD"ü~?…Ñ +++©¬¬Äív Ñu—Ë…išq‰{§sÏ xÙ»÷›Ýzo5rRÓ4»3By¹•ü«®Ž%Õ5­F@F"ñÓN¨)PUÒ²¾ÞŠyÑéô}¾Xâ²´46…Ä¿üË;üö·Í|ó›{¹å–?1qâ—…‚D"A>úÑ-üõ¯MÜwß?SRRH8Æçóáv»©¯¯ÇívÛ XÀ[oK0hU÷»™¬\y’íÛ·óÛßngúô%ÑÞgï½÷>×]·9Õ§]!„B!„Bt“š’ÔëµÚ¬ª«áé§¿iš¸ÝîvfùjÅÅjŠT+X[km««™•p À•߸‚ïyÓ4ñù|vâÑãºSÓÑ~ócôÅsqÁxýx›m¨YÂ:+kßH`PýÝÄjŽW³ž•bMIÚ—º³¿eÑ+ Y˜„÷ $¾‰®ÈˆG1 Íšeý«~lÄ’J8ªžjÑ]°­P…ÃV2A×ck7êzl$¤J@šfì=t=öà‰Dìékkk”–Z6{<"‘ˆ½Ûg?û:;vü ˆpçU¼ø¢Alæ0 žæùççrÍ5ÍüéOÄM©iV· +)¡cš:¿ÿýL³¯#¦½SRb}Ó—––‰D(++³{KAlúTMÓìÇæÍ»š`°íµ6vìB`!3fÄ?nšV<дغ©*™¨ëº½¶ªªtõo4Jee,éèrYq ¤**¬ë~Ö¬X¥ºÚzO5‚Ñ0 /ï—_>žââ#TVVðÏÿl‡ùþ÷#TWWsá…—Ú‰ÕŸÿ¼—Ë…®_`Ç«lñµA—Ëz?³|p$]tÙÙ3¢ñIç̸ôÒ]ôù„îB!„B!„")‚A«#{uµšÕ¤¸x¦iR^^Ž·ƒcËsÅÚ¸¼^pmýî²;»õÞÖ@P(Ä—.åÂäôر|»äH¬AÝ4Ñ~";ÿ Žëö áörÜ£NB;Ëý8§íÎrhI§a*tŽèô›Þ´+éçiõœD™XS©v—×ñ:+ùÊK32âQd5maWT Ry8ÓŒ`RL%]®ØóÚYâÍ^ÏÍ4c ùï¼s È=_õÆáàÁíF Ç×Ùïe†=U¤¦iT:¢ª¹är¹(++Ã0 LÓŒŽRšM&Fؽû †Ýf¼¼<ž~1üàÇt“.^yöY¾òàƒ=4#:JÓnš0|ø¹@„)S¦¤úTŠA, b………Ìš5‹p8l'ÜËËˉD"x½^Ün_\b͹ž£õ¯¾:ÇžÞÉšÖáˆ=…)ÄÏUïñX±$/ÏJêºÎĉ7`šVbÑYÑÑu+~x½ñ«£bƒ®CiéæÏߎaƒALÓ$cš¥%ƒAvíÚÌO܉aø©­­¶§Œ­®®¦¶ÖJ2z½^|>^¯Ç7EFW¬u ãËÎÎÆ0\ö¨n^yeûöíKõÇA!„B!„BtC0hµù¨¶è@ €¦iTWWw˜tT#Õ@j¤d¹7‚öÀWÛŸ°Íû)..ŽÎäç—_ÎÄ¡C™¹yslI•ÕŒD??Üî¸àùÜÈ.§Rm=ú±ÏiX‰»öšÜ\Ñ¿•cMsZ 8Ç%*ÝfoʬGË¥ŽoÖHȮ֌ìg2âQ¤%52ÑëMq¨iVÂ@MmÚQ°RÉ@óTBBӬ탱‰jc$›±£íé:L›ÖŒ®g³uëÿ‰Ü‰iÂŒ»xøáèúµ466ràÀ(®½ö'¼ðÂëhÚi@' 0M“ÊÊÊ6£”Ê£…UkšÆÛo$/Ïê 2jTúÐ(6m²’/á°›óÏsþù—ó±B×­Exë¶MåÐõ×3,;›÷‡Î¬Ä¦•­uqç…[9klåDãÌTŸb1ȨœsÔ¢Zç´¤¤ŸÏ‡Ëå²×=Ý¿5……Ö4*çf­í¨ñÄâ ¸¸ývÉ“­xt9HêëÕTÇããÖ_Õ4«b¥¶WYiÅ—âbxæ™òÊ+Ÿµ×jl­½¥"U…ÈJ>F˜5«„Ï}înÖ®]KQQÀÞÏÒÒR*¢™À’’V­ú)7ܰšÒÒR\.W\G„ž${BÅRÕGÁï‡Ï~öÌžýt > B!„B!„¢»"«ã|e¥Õ®eš&@€`0HYY™ÝY¿=jæ>M³’–v³tiÐú¥“¡††aPZZŠÇã¡¶¶]ש¯¯ç±‡&{É’ø>%%VÃSy9îb«í]µ§u'¡Ø^{\Ÿ b%ë:yèþ¨iNCX ¿dŒ2L$Éêr¼^Çš.6€µ.e¹ãñ’"å‚A«Ü)²â•aX%œ æjzÃŽ¨ÑG*Qéýãv[«)Ó¥Z£•Úßæ˜1OË/¾H8 àÆ_à›ß¼wÞùÙÙû6ìQΞÉÕWOÜ„¢ ¸©µ].W4yÏ9udl4—ZKR''çŒýz]×ÉË;ÂØ±ùx½±ãâvÃdÓÇÿß@óSï²kWN,9ëóÑâóã{v>g999©>íb ‡Ãøý~.»l3YY0{ö>øÁ_QRRBii)áp˜`t~㊊ \.~¿ß¾6®»n#UUÓ¨®ŽPTÆŒÙÎ_ÿ:Ÿ.½ôö\ô±$e8‹ê:WS:ózjºÕ²28|8—Ë/¯¦¬ {ªãH$b_»€¿¿Ã0ðûýD"fÍšÅì¬çy½^¾ó•˜¦Ç㡲²Ò®˜¹ÝnÜn7Üu× ¸\.ª««£•û–×kí§:ž†ÕÕå<ùä“©þ¸!„B!„Bˆv¨õ‹‹ã—ö)..&SQQÑáHÇÖâ’Ž†am¸¬,¾±ÌÁ4M^ùÅ/¸kÁ«MÚñ·%Ë–Å'+ÕPJ5ˆ^N›[a¬VênòOŽôEËULbk@ª•ÉàÆZ›²6º]kíÊ<¬D©Ñêù=æµ—dÄ£è7á°Ï4-6âÐå²â’Ïg%««­ÎjjÄ@À ª>ŸÕ`®âh4Ÿ×.5-¢iÆO˪Ú÷ ÇÅæõ®]O³eË,\® ÚÝî+¯4rüø ÀFëj³uëí„Ã×âó•°cÇt{lpÜܳ¸\C˜9s7ápŸÏG8¦¼¼¼ãÞ'±EæìOZÖ`<º®sòÈéhrTGÓ4ƯgîÜáx݆•¹-+C3"\ÕRþíè—ŽŽvX_$ee‡Ùö?ÿ“ꃀÂá0¡Pˆ`0ˆ×ëeâÄW˜=ûašš>ÇîÝÍÜ{ïÏùÿø"cÆ,#žÇäÉ·SXóçÿxW^ù<òÈÊËcŸ_5jÑë…/y¸½F£iÞ`¿·¦Y?nw,±¦*dÁ Ú«GYIÆee.þõ_ÿÒÒÿ¬¤£®ë†AYYš¦ár¹â’‘åååüÛ¿Mã¶ÛÆâri&#œÝ]Í+ÑÇT‡ŒŠ غõ£ìØ1.¥åB!„B!„í+-Í ¨rz~¿Ó4©®®n3«^‘ƒTÎ.Š[‹·;ö{+Ö²A&ÚÏ~†Û4áÐ!«Í95™Se|&«ÛÍ_A¬¤^kô¡+ú{k]Eoô÷¾˜‚µŒ¶I¹®¨ÑÜĦ`uGïI“_€®G[ö”NlúÕz¬cêÆJ@êÑ2êÑ}.Z’øÞí"éœÓB«|šaÄF5zaèœ"°¥ÑiÝõõÖ›«^ìÝlÿòùÚ_¶¨íŽb%áÔˆB5ª°+‰ÂJîGŸ—LÅXÉÃÞP#k‰%óJ¢?Ý]k±7#B»K#–´­þ?„5]loGiöŒxIWRe¤F!©µÕÀJæ©Q‰Î¼¥¨¦õûã;^¨ÄËeu®ˆDÚN©‡‡=Ñ•!Æÿ$••&ßÿþa"‘FÂá0cÇþïÿy,x†Í›]üô§ßä«_=Á³Ïþ+#G.áàA‡ ¨¯wó›ßàŽ;V£ë:a;a‰Ž|z,:ÍâL.ÖL.ÕÌ=·CÈ^/á‹tNróè·¾ÅÜ#uÇv/“¸,ȬYÖ·‰Ë†K ^u<ôï:[v?¦} ]×™|â…û·rÎÍWÁï?ø’ü™Av®«ºuë n¹å Á`ÇßÏöí×0yò…\{í2¶nuQX o8´>Ï%\{­—Hd ·ß~)÷ß?ŠY³J¸å/>ß545²ß×ÙÙJӬˣ¶¶mùÚ«`YÓ«¶0}ú)†Ÿ/ŸHØ„i~´„sIµÆªsÄ¢/Z;òx<¸\.4MÃçóÙÓ°:Ë׫©#’Á0Ú¿æèHh•­uÐ\öUÍw¢?Ï¿÷ÇçÍKQá…B!„B!D{Tûºjö)--EÓ4‚Á >Ÿ/~`IgíCnw§ F€ÆgŸ¥©¦†¢ýŸ®ó·1c¨¬¬Œu²÷zãñ“IÇõçl[Ó+'6ÚÑ5M¨™Œ±5‰nC•Qý_Ü,‰–QÖtaàlýÚþ a%s‰à’¾[I<Š^1M+1èõƦCT‰ÆH$6bIåÙœ£­u=–gk-°þ¦zE8¡uÆOµNYy9Ü{ïY†0cÆ!ŽÊôéO3bÄI&MúgÞyg:_ú’•lp»Ýüð‡ c.ÀeL›öŸúÔMüä'ûyå•gñzg`Û7k×~ ÇZW1àóùx½^JKKí¸­íVôÓ÷[…DÀ펎N´žßâv³¤£íõÆÄbŽaŒEÿñ=Æ|F½em·yã‡q]'ë4оǦ,8±‘G§Ÿþ¯¼²—ðcš.ºh—^z)GŽòÆã=zµµãq¹âcõ×~•pø>ª«Áåšt¼Þik¦‹-­™6 £ÍHCÃ0ÈÍý»vÝí·^Âwþ†pø&"‘ñöÛ±iÃá0••]Ïgàr¹ì)’ÛÕ¨FUö ÓŒ w«ÒÒØqŸ/þÀøý±9ªMÓz®£‚©=ü#"%à¿ùUU|öê«û¨ðB!„B!„¢'‚ÁXÛ¸j ‡ÃƒAÜn7^¯×î,o+.ŽFt6Ry<N¥ Ö,f†aà6 nߺ•—ÇcÌæÍŒ¹îºþ›Ù««1¼³&B¯ã_kýB+á"–˜ôѳQ„Ý™Ø]nÇ~¸±FAF¢eD‚Ñý0è¿Äc{*ßDW$ñ(ºä÷[Á®¤Äjd/+³Ú»C!+Ö×ǦA­¬´~Ôô†*á¤FNµN<ªvtçãêÿ¡PˆC‡®ãøñ}D"gðx\ø|ûihˆ0~|-aLsgÎػך5 RVæÅå²zi¨ ‰D¬^½Í4øÆÍ‡ùõvøæÄ‰4ÕÔð™çž#èraš&åååœøÜçp…GŽpÝ¥—rÞèÑèºÎe—Í´ èóá>þaXv“]vk·Ý]'WZ}Y¨2ªø®ëî6“¤£èŠê F†u­¶ÖQ§¨_ü¢‘3rðù"\ý×il|†éÓs¸é¦›˜6-Âã¯æ³Ÿf|À|¾ Ûlëºërxá+†¨‘‹.—«[•˜ØàcD";1M·ÛaÌš5‹úúz È›.õ™g*(-MYY%ÕLšô:Z;¯*gÉšr¸u®['&ŠÍ7­æ–v¾ââø)™u=~ȧR^^[¼[K5׬ËŸ¸tOk:þ¥TUåóZUMÊ‘B!„B!„½ Æú;ó…~¿¯×kÏØÕ†®[/4 «á¾“щj&¯P(d ¸bÂö®\É…·ßn7ŸíïõzÒD§¦uþ®F±’‘:ñ##;<}¸O:í'T]}ü¾iD¦ڨÕСՠ Yw æÃå²Ú¼ýþØóÀZ7¬«ADºÞ¦-°ªsÚÂ]»6süø>à6"‘MMçòöÛ/PZú˜=R©¸8@Et4OIÉ,t]§²²ÚNhx<t5À¥“&1cófkçž{ŽÒÒR|>š¦1ê‚ ¨9wm-×çæ2|ëÖøÄ…ÇCÇýG„èjÄ¢×kå¢JK­kU­hšV~ à OàrEøñçc%%%†3aš{¹á†‰ø|P\|5Âý÷— ÆW‚|Lܾrå8¿Þª×ëm7ñ …p»ÝD";Á˜ÍSO=X¤p8lO‘Z\\Œ®ëv'µÍŠ Ð4kŠÔwÞÝ79´:Uy<Ø5u`úËËc‰A5­sß['A» ¢Î‰ò[W&U¯õÿVÛNéÔ°B!„B!„¢@Àjg//µ·™¦i/TÖz0§Š «Q¾S¢âñxTVVÚíÛ¹/¼™§þ `"TS…&› T'¸ ±)LÑr–b(ôD÷C>®›ú”è¾%g\BÏÊ;HHâqSÉÈM›XmÖ>ŸÕ8 Z%ÔL ‘Hlù°òòØc€õšÖ˶§½¿†A8$´Vt À4uæÏŸÜF8¦¥¥…×_ß‚®›âr¹¸îÒKñÍÛ·Sh†7„K·|sŽM·å+++­5â¢Aù"GyÖy<”””ØÉ”‘>È‘#¡¬ŒáÑç”™ƒ¤{‚ÈH'O`öì¿ mÆ0 n¹å7„ÃÙöš_øÂnî¼ó)þð‡õÆJvìXBU•Ë^ÓðSŸºï&á°NYY~¿ÔHJ—«ûKŠjšÖfze]×1 #.Á‰DðûýqS‡B!¾øÅ|0Ö««¸¸Ø^H»¬¬Œp8lwˆ½gì}n¿½Ð [WÚ²²bo¢iÖóT"Ð4­SVf½¶u¦¯õèE!„B!„B1(©¶6µ¤˜j‚ ƒ4M‹µa+‘Hü\šÖi[“a{Ù!]×cL¬‘‚:ñÉF•Ð a%ò*H~Ò,‚µnc¢ÉGE‰pöçG÷!}?7Vâ1@ÿ'I<"‘ˆÄÔˆÃ@Àz\%ÕRaá°•§óxˆNgj=·ºÚz¼°06˜ÇåŠÅÝY.NMoúìfîÜoQZú4Á`MÓpE§5]yÇ|ðæ›cþKJ8¸lÞH^>œ‹«ß!‰DXõOÿ=F¶ËÅ\t—ä#ÜÔzWgGÖSëdØË墶UÀn=¢KëËaCê8ª‘¡‰Â0Ö—‡šC:•óG‹>Ãw¾Ó„Ûäôé|víú¡› /|‘3Fco¿½‚ìì›5ê—^ú8=ô šÿñe˜æA,Âõ×›ƒAîºë!¾ÿý¸\.;1¨â‚ËëxÐS»v=M8<MÓ…B躎ßï§¢¢‚’’*++íëέiY Å‘qÛ©¬¬´ç¶×4âââNG\öhVUÕÅ b 8ºÝñYÖ––ö“ŠèP(]*0B!„B!„¢jÒ,]Ÿü* QZZJYY^¯7Ö­fÑRúÎLe;BÑi KJJ¨­­Åçó9–øŠ¶s©d£+¹èX©šØÄ’„&±µ Õt¦]MiÚ‘p/_×Îu52ÔÇï=ÈIâq‹DbӤ꺕œ0ÍØº‹jTckÎFz]­§âQyyüsœíýqÉÓäį~Å2æÉ'¹xçN>«ëxþãJK¿À®§M^d3Üã¬\ÉÇÆN›Æ7Ò2~<«³³93c 5-~xù?ÿ3#4 Õ|­} i‰FTÃÑŸ2¬¤ ØÔ…XA[ aŲèßÉÃ`ô¹žès4 ˜X`-ÆêéÁZ|·‹YEšRIhÕÉm]Ó=´‡aÃ^eÓ¦éTW’ææiŒÿa '®õ¢_GüG¨®µºE"{0Í<óÌïèçÚ„b7Ÿ¢åÍ2&›7áº4¶¢¦iöu®ëP¦Hû<êñe45Ó¾f"‘cÆŒa÷‹¦ö™9Ì›7æ¹ÍÌ1úŠzpaÿ‹‰Õ“ÊÄú¼«J€—Øuò@o‹g ¸ËÍÆÛ6¢•hB^ÆP×õÑJø¸Û*oxÖo¸3ÑÂæ¹áß+­¿ø¼pÀ ok±k¯”Xo( «"V¬ÇæjDËå\$:Ý5…ƒz b=ÄÔôjª‡2¬ëÕĺNŽó¯¦…P¯s›ÇÇßÔûhÑ2™Ä÷â’d¨BQ1J!„B!D¿Síöª=]ͦföjÓɾ¤Äê_YÙiûwii)º®¨¯¯§ºººÝ厬7ÅjSªè¤ ª^ÇóU»¶ßñ7V;•j“RmVÎ)N â•© £Þ³/¦6I< ‘ˆ5ÉåŠýßã‰ÍüWQÑ»íjZ‡ƒ‰D"¸¢# ƒÁ ¥¥¥hšFmm-š¦‘õoPvò$Í£G³ÿÚkÑ£kéºÎ®§ŸfRc#h…BtLJX¸ðo¼úo?´Þ7 ¿²Ðú<ÿ±^FŸŠ@È„3&œÊbS<8y2ßúÌg¸í{ß‹‹#.—+.èé.f$Ò¦>Ÿ¯×k—£ÃÄ¢ÙIRÒÕP¯zc8G ©¤F˜Ø¨ -ú¯sb€Øœ×µÑ×”Kö©JžèkÊ£ï]ŠˆUB±…Øè*uPʉ%#X E•l)þ[á(‡š2U%@Lj%QÕÈ(û€…0æÜ1½û`ˆŽ©‘eß[¨ë\ùX è2bŸ…Çß50ÇÀ¬çÀl€ÿ¼á8óg?‡×MT\îã­ÃÈÍÉk—|œ9£/ÏcÖ¹þ~¬8îJâϽú¬©¹ÍÕû¬¿yž°âÉ¡C›)¿aU1&srüÉX"û÷ïçèµG9î>γæ³ì½a/Ïð ¥…V§ƒ²²2.=s)×o¸ž9Ρ¥¾óË?†Ò?ÀÂÌÕÁpC¥Çº¦üÀ\?|?Ãu(ÒáÝè1q›æáãe°¸ÄÏiñǬ^ç«àèÑm«¤¾zã§P¼Ä®çŽæ­wVÄÚ9XÖÎßÝ­^ïê`{ím·“uÃ;-‡3&èí<'š„<ÒtNwã=„©g8þU=E; êLÊ]Àð׆óÒy/1¡aO7æ°åp®iß{ö6¶¼½%Õ{(Ò]ëeõ«>£®vž£ê>¦ãùªCŒ»×µÞ†³Þ¬:ô8gÀñ˜s»†ãµ´óºö¶¡Ê£–*pwð>~ÇßÛ{Õ©ª,ú\uÝ:ª«¨5utÇû:¯uµO8žçì%®:*ª²jÄ«2Çûªó :)©c`r{ „B¤È-u¥•€•°r.ï§–½rÎvç\ Ëëµ^cšÖÿ«Mb«Ë¨íº\0]+ô©`0–tôxÔcAü~?‡ò²2ë j½4çô‚í$MÓ$zUµÇÍØÕÉ>Îb9Û Ú[¦ÉÙ.®’•b@’Äc†0M+æD"V’±°0¶Æ¢ÏgªN¦tî’aƒÖ]µ×른¸˜M×\ÃÖ_ý €íÓ¦qþñãÅÅ”––âñxxø+_á¿þ55;v°ðê«É*,ĵj9×]GII‰½~ãu«Vµÿ¦Ž8nÝÍUÇ®jûw@sivO ;I¡þ^‰ÕSBMYªzJ¨F5OµsZH°‚jYôßV¢/èx‘TL,aDôýTPT£›Ê¢ÛV‹Ô†ˆM}ZNlˆ¹F¬'Hëï +á¦íT¨jT$ÄFIv4]bëÏ@ëä‰níëñïïý‡e°QŸgãŽm¦Ä>GêwõYt9^ãÇ1¥'öù …ÀU‘˜Á³üÿ rø¿óÿÎÈgFboÄ=ãA\.îÀuö4¨6uîvNMµY{ºÕ`µ›¦‰‰Iäƒ+éÖ0]&ÁHÏ5BÅ!ª««‰D"üïç?Ïß.däÈ‘¿ç.¸ðBò"fß0ÛšÞ×­öm˜©ÁUÑ‚©²7zì®õÂ9 &vý)ßw[-v<Öz?Õu[Mìš 9ŽOgu/ÕH8¦#mo_¢ Іª½£F‹y‰ÿŒŠîI¤WcØñÿvpêÛ0âoÀõ±æah¸¢¬#YäœÉìq?Ó®™ÖfæƒH$Â!°óÓ\5~8õÖ2êÀ(FÀ–#[˜¾d:MSšvt5M5<óÌGÙ»w/—\òãÇדw$Q'G±øy+x=µð)?¿˜¦‘MÔ·z †sL&Ôí¡ñØ"çBîÈŸ“w$S§Nñ‰†Ë˜ÒØÄ¶ £øäþÜ6î69ú¯Ä¾¤ ‚„8—o‘ÏX4OÍWÌ]8ó#Æ=Åéí»9rþÍìxs:?öUŽ¿¿¦Üf6f_JÎÔŸ¦úS18¨¤szòöu*i¤®5õ·3q¤êÀ›š\mG%¡Ô÷šU'-nõ>ªŽ«ž¯¦wj²¢ÿ¯$Ö!NÕ‡¯sG·YLÛÞÐ΄ ³ ³÷s ÿ+.ÇóµV¯UÔl$ê;ëõ­7œ×º³SwuÃÔÌ#*ÉŠcŸÔTèAb÷/긺ˆõþV3²8?#jÿʱ:h9;;ªp଺¢S ͱï-uŸ=3?6³‡A!„˜LÓju»­UÒOÓbƒ@TþG×­öZ°€„ÃÖú›ÛmnÓ´Ø M‹å”\®Ø ·Ûú=ЪTYi­VÊùee±Á)*‰å|M‹ÝiZôÞ(:hE5Ëèºõ·Ûzì¿þ+Õg`à ­åÌÊoOäO4­ü5?Ÿ9“ïîØaM­êvC^^ì$FôÃ⎵-c%* êà†ÇãAÓ´¶m…ÝQJû ¾$£I<¦!õ…cšVl‰D¬/5uª®CKKÏ76 ŒèOKe%ן=ËÁíÛ¹¥¹Ùº÷x0 Öý+Ã`æÌ™Lž<™_ýýï,øæ7©øÞ÷…BxÔ·Ù°Ð~@Ãþæº7™´oš©Å¦”TIu³­zäÃX×XÈnÇu3íìuá¼9V£!Öð«’=j±[5âL@TÉ‡Ö Ží´¦^ëlX6ˆ58«$†Ú§êèß"XAÛ9©«Æi{ÔV«Ç #ÝhàVÓß¶þ7ãr¹ÐtYЩG´mLsR Î$¯³±-ú1 Ъ­J\(‘`–Z×ø¡Cg¸îºßñüó‹ÉÊ:Bhk)Ï?ÿ-&Nü,…ç~âþIçåT5ËÖ• µ@k;=Âá0“Oœà«K–¨ðùX|ÕUܺs'ztJä•ûÅëÖq|Ò$þ½¥…†¬,¼••ösÎØ§ž²6z÷Ý*ƒ›:4*‡¥´Ÿø+Ü­jnÚ&uTƒk{£ÇÞ™Œèjžz'5—­\"¢3ª1ìÃ~&ÓD8ÿ»¦Y?†»U½^ÕM°ZãÙ0¢÷<ÛÀxôË ò ¸®Š=§¾¾ž@` >ßåÌžÝÈ[o ãå—'°páNvîËž=àÊ5ñ6h„€æÍ4g7sòœüó˜ã”¿u>µgë¹oúq¾¶ýb.œ´Ÿ3gΰçÈfO~–+]ÁÃ''qåð£|fØ1¾Ó4%®cäOÇíâKGgð™1ul>~†ÝÌ´ÿîNóÏG{.”ñæq M¼Æv.çr\À¯©f(³¸™©ç^`ÉeÇid(SG™zâ´dMá‡#~Í3ï_˦?eĈj¾/äC«™yf Kªq×™¯1«ÅäíÃÙËß™2~$ßÿß)Ü}ú~ˬÏZÆ»-çð: ™ÕÄ]£÷ò—ý:EÃ?ÅÔæ×ù#rÁEîdøÚÐï1zô ú>ÿôö6^5?@ùCêøRî>JÍ…¸&˜|àü&}e%gFp97³þ?;¯ÿ áׯæX%ƒ:Á5É+Z‡L´š ¢³„Û<Ä{ŠªO¨QýjF '5¥¶S{k ¨i¼URUñ#êÔs[ˆwnK%9ÛûžvÞwÔvp Ê:x¾sŸœÚ«wWvðÿŽ^×ÞsºóïlXé¨CRW3t§y9±Ž’íÑÛR YUQ$;:^¦c».¬{5óŠ«ÕkÔˆÈhÄv“¬A˜yxf7vJ!„è?áp¬yÁ9Išº—Q 7Ÿ/¶VžiZ÷/^¯uŸ±üÚ†ºòù¬%ójk­¡J:‚õwÕ¡Q-k¥’Žá°µÝ²2ëïª<~,¡ Z‰Bµ굦{Û/¦f°k­¾>– õzc‰Èö¡øÚi;tδٓÁp"q‘HliÆú-{pO[ÉôGÿÂÓ³góÈŒþèG©þíocS«VWƒæŠ-¤î%÷ ^¼üéž?qÓƒ7q6÷,C#¼·Àµ×R¡ëD" )++Ãï÷Sû—¿—•Çž¢Ç¸í¶;ÁOÄ›žGí{IôxD{Nk¦†fhVàš$Ue5Ý©:f&V#†J–?¿´šž¨’øõÐçqwÎ-Ý:hª¿õ¤Gs{ETÏâRˆx"èºÎ¾Iû(ØPÀËÆËä¬Ê!çL//àÒ\†®ëƒAû¸z½^‚Á ‡HÄÚÆž={`œ žNoëÅï÷Û¯)++£°°òòr€ýZÀN0ú|>Š‹‹©¬¬¤¸¸˜ŠŠ JJJìßËÊʇüóÎ;=þ¸§“~‹êËY}>!Ö˜¦¾¤Ucãs Å*¸ª÷šÇcõZóx`Ò¤×yöog2¤3g6ÑØ¸†ãÇ]>‚Ø…Ïw·û×VMTmÐíŽO,ªù5ðp4!‰D0M“OVV2fÇÞ_½š§O“sÛmÌ~è!ª««)..æÍ¥KùýìÙŒzòIf^~9cæÎ¥lùrÜn7š¦Y»ÕÔÄxsÜnÆ»Ýq—ÑØ>þñö¡º>]t<’°£Ç[÷¸R#;«µî(ÐÙö»[‘¶ú½N ÖïõKª÷ñ´ êÆ×Ygp»ÛN»£n´•²2+l„ÃØ Aeܰ÷ùôÔ·84sÿ¨ºžsÇã²kþÌ?ž½ž#CŽpêÔ)†JåÿÀKuç‘s6‡¯…Á:¢ƒ¹ŸP¨ÆÅÞRGí?çÒw| ©ܬÿy>ùË_2ÿž{xãÅgùïó§sø±pÞXÈ=ÞHÉó8uåçyõªG™>ýZª« Ðþ|€÷›ÂŒœ±›š×¯äê«ñrK ÿô±CháÑÇóÄßwxf­aKý4j¯ñðÃ?~šÇÖígnY _üh óŒñ,ä\^ß;‘õ+¶óÇÝ3ùÎwæñÙ˜uדaÛhB/úðz­sýL‰›OÊʧ¸Ü.(÷€iæ£ëPh@8¬áñ|ˆµŽXÌá´ç‚þXOh·B¡^¸áFŠúöcܧRzo ªãªîê&–Ôi›Üsªwü¿£Ä”SWS|wT¿Õ»ØF{ÏËpÎQÎQ ª‘Quº€X#¢³QSÕÝT#¢óùŠzóÿ*^;§C øcSœ9¹ÝÑN!Ñ*ž£U,w¾NMæÜ?wtw$Õ`@8kü«Á³4:ò²Ì!|ã­Ëe­'þÆ+W§úÔ%$­Ú „)#± ¨©<[Oé Ö÷J8Kþµ½§¾ÿÔw¦®[ÏQß‘ˆ•œ5Ëz¾s´Ÿ¦ÅfÓõØ=Àá,ƒz®ú]ý¨‘j´auuì½UÂN lÍYgpr΄©ÖësòxÚÿëãÖ用ê={»¼Ö@×/q@Íx§¦ÍWƒOT[¿š¥ÐJÿƒ]G_å¡áÃ)^°€;þå¿øà?›í$ ˜Ñ ù`OÃÞ=ô.¿˜ø š>ØÄß¹ƒ=íᆻnঅ7ÁM0„!ñîÃÄí8;!:;¹©Ç5b…H²ŒJ<ªÀ¡Æš5kX¹r%<òHÿD­¨z«/ •¤ˆDbw¨\pX#r0Ú3¥é?( ¹1š¦`4MÁ5a?ÞÏMC¿Ê> î“O¡ýëÇcZ¸a{»öŸàý7Þ§áå¦ízžj9˜ÕÌ“È>sœ_~õ«œ8qúMçÜ6f,UKwqý¯¾@é‘9ܾþ8cþk l'6ѵÀàIk_\š‹Z w-¸‹œÒðÂ'ï°FòU›žHÇJ¨àæœR2}Ì9Å’Ò:)à*n÷ÒuN-Õú¹êpGGòAl=#ç¿€?–œSI<µ^¤®ë{½J]×íy°U2OÓ4‚Á øý~;©×ÒÒBVI/ýô%®,¼’ÊÊJ§Â|êªOá÷ûÑu—Ë…±Z(TÂQmW …W GeæfÚëjª…€Ýn7º®ãóùÐuÊÊJ{}Lõ\{Ú¨–èpØŽþõx<Ü{ï½ý{Í$QŸÇ ñÓyh¿SAôFtf¯`¬¢[^nU(:ÄæÍ‡˜8qáðÏ8yòCƒ#Ñ´Ÿš=›ËgœÏ9³†±pQ ãkk­µSVtn3]gÏWpîÖ­TÈþÖUWñЉÜð›ßp÷¯~…Çã!MJ«ÏÙ–@€ý[·òÑ xïàòo|ƒê/~]×íÏ„’ý·M‡¹Dæq†äŽëÎô2õå Ðç± †ÿ†=ÀóÀ¼â³¾£œS÷Þ¯ãP­÷ª¦Z†Ø÷ZÐzmøn0? ®k!#ËšjÀu.è¥PúUë÷Ÿþt3?úÑ<ò¢sÎ:s„·Ê‹¹õ¼Zwï´ÀŒœ ;=“igÆq¨ñm^eþ‡ØÃþƒ\øÞàcòÑeÓ9¼;j,“'Oæ¥ _åß÷Urúôiö¾Làìÿƒ¡æTùïæ³çèmœšý7æG>Ý‘?pãĉýÅ/øIUwÝð)þãÏóï»Ȍû8:z¥gptì•<9î«Lž<™³—œÏm¡3ÌxÿÛüqÊH>¤OåÒçÿ›Q?ù5[¹’òo– >Ìo¦Mãw›_çeËØµe çÏÚÉ{g¶ñ1·›-Æþ´m^׿ñFCç^ty/½ÄÅŬþÀ<ž[‰DÎcòСlÚ÷yÎ;ï<òß}4ϸÝ\e\ýnýšËÅÇ[µ"´üâÓÑÿÝý÷ûoWFÿý´ý¿x϶y$úáø¶õÏÇ£?Á-·Lã–[¦k÷¦“bà \Ž›øÜR½#YUÙN²JMçÔšêÕì|jl)+[Áã×ôüI}œë7ClšýVîˆ`uRRõÔ¿6¥F-«d[ë$›“3ɦzà«D5Rºuò«½šš©E5ê[%¿Tgh;ê@QÏQ³½¨×[“(±Þ§£©Èª«­%)ÔöœS‘©²ºÝ±²83•òr«Nç|ŸÖe­¨ˆ½·Z†G·Ö‰LUþÖœÉQ5ÚÉ“'©©i4 NòôÓ¯QYyùùcŒ>úÓß?À©7`ÌØ±¼9@s^ûÛ4öìiâ#WìáЫ§FD-ÏT÷Ú®¾zcÇž¦®î(#ߪeúûœ9ö{_3OñîÔ·ïô퇳¤M;A:Pˇ8u¶¶©º§bXÐ>Õ9ÆîðB,i×úûI=®Æ7øý±Ž5ºn}ç©õ}¾Ø÷²JôAì{:N²©úªJ¦9ë ê;±º:ö}ÚѬoΦŠÖucÓ4)+‹Ï¦Xõ«½MµZßóÂáØÁpÖŸœÂá0¦Ù¶²íœiÌÚ/-î÷ÎÏO|%Cµs†׿ç|žjÃlýÚîR퉱ý5ì6$€‹.º¨WÛMýr ¦Éwc –ñdMžû?¹›ðž ðæüŽ!gš˜pì kGgæÙ™”L sÏ·§2úàh¸ƒ¸ÄßÞö²õÄVÍ8ÄO‚?Áçó …(/³Ã4M‹ïLØÞÿ[D;z¾"#`EÉjiéñ¤)ãv»íž uuu¸ÝnÖ®]Ë¢E‹:|Ýš5k(**¢¨¨—ý¹ëö±‚‰šÚSõ&(…ȟ°ßO(ÚÊɺŽHËeTÜ3œâÁ5ÊÏÀ¾Iû8Û|˜¦“M”Ï®àÞê{É=›‹?^x!Sš¦pÞûçqΰshÙDÝ—ëÈûyÌ­›‹V©Ån"TrP­?÷ºVû§ÖQ£ÕkZ݈8|êËÏårÙÉ2õű/3õ‡ñz½„B!Ün·=mk(ÂëõÚëGªQ‚€$t~ÙºÝnü~?•••¼^/@€òòr íÇ].Á`úúz{ÄŸ5hšf\¹#‘ˆ]ùp&öB¡eeev¹Ô¾kÚ½hùòå¬_¿>ÕÅè•ÞÆ¸ýV ëZŽ6PáNš°#K¢™ôـ˅ajöè¢@ ÖC äº]ܼü]^xaÇŽ½Æ‰­ó•­[˜œMËøñlûØÇ˜°t©½vËšõ.ŒüàÙö±¡iápMÓóÎ;¼°oû –––RYYI0Äçó ñz½öu¨ëhÈ‚èSUUUTUUÙ×R¦IZÀ~Û\±é+€ÂhKôxÌ–ëàòƦó-)‰õ6ølæ1æcÑ%€gçlG?¾‰Àöc ñþD 6#·k‚‰÷°Æéá§yô¼Wu8‹÷³†á9¡qYóY®eä:>L#Ø@1yícϘ ¨;·Ž·®|‹Â¿ý? k·0üÌ1šÆLaèˆìñ]æ˜Çûï½Ï^ï/8ÿ0JçðèÝ4ŸÍKw}˜G^yÅ^Ïùàµ×òú /pùå—³nËn¹ç¾½?n·Ã0¸pòd.ÌÎæÈŸßdÌ'®eø£ë}çü¶ª ŸÏG8ÆãñØ#ñ ð¿Cœßë"}X£§BÜyç´ÞדS(á:Á®·ê½¿w4 }Ý[OÜ xý°Ð#£ŸéÏh0MuŸÇj•rfâ:˜ÞÜ™”j=½q{ 4•ìj=@­ÓcšV"º¸Øª“TVZaÉÙ€¨’fÎ¥Š‹Û6†BÖÏK :©„ ÚµP<ÈÈ‘#9rä—_neÄ·lÉ㪫Îå²ËóðwÞŽÛÆõŸŸ?ýiãÆ½ÏìÙLÛ¿•ÆÙößß9~æeôèk8pàSšþȰFÄmãÝKs88b'OŽbäÈ&æÚÅEïì`ܰ£Ö±m¸‚woW_ÿÂîÝöëÇž>ÍþÉ“ 9âÓìÆF>µw/cOŸ¶{è‚ Ø•“cÿ¾à•WøÄÙ³=z”Ó§OãÞ ©û…ÖýÔÊö¹ ¶l»Š„j™z¥’¶mAY­~o}ãhç}þß!äž=ËkÇsjÌ~2m;ÆŒaøðá†Á†傆† Fss3oæåñ³œxM/w¼}™¨·± ­ëBΑªS¤šÊÙÉ9šZޤ'‰Çñ³»t&º´ Çû©öU.õþªaV)ïæ{ ÎÒª“†e­:„8“έ;‰@Ç£¹œ¯ëh4÷™3›yýõÒóšè†”µ&‘ê ä\·ÜÚ·øu[wšñxÚvšqÖ-tÝE¨^çLª¯ÅœœC,X0‘‡ÚÀ§>µ—7Þ÷>S¦4qàÀ(æÌ9ÊØ±Öwgw’kNª³}"Tc¢Ûi®ëv]¢½ûÕ¨5(­ïwœƒ%õ»sö²d”W½?·ÆŸz¬u9;Û?€ÿøÇ<þøãI?¶ý!)m†N±ŽˆàŽ0î6¡Î€Š Œ•.Âõà¾fý¾0â¹÷Ì^† 9ŠÓfMÞ/8wî¹L¿6Ú5,ú}ù§í"û¦ì¸ëÈ4M|>†aônÍF!’ õäŒñXSSC]]]\E ??Ÿ‚‚¶nÝÚiðؼy3ãÇ·^û¸4à(ð;wl½¶2 4Ç—Ö…:Üâ…Dný*ˆ¼ûÆÕyÏOÀ<9 ÷êQ„v\D( Ç-dá´ÿãùS˜ ïaô‘F>3áO„³ÿŽÛm}©ø#l Ð( žh´J >HÜèµÛÜ·±›Ý¸\.Ê(³“`¦i2AŸ@$áj×ÕDæEÐÜÖè<·×mýëqóío›ûÃ÷Ñ/@tÂÁ°=ú¯¢¢ÂNÆù#~«Á0MbÚ¯‰[Sxªé>‹‹‹©®®¶§d …BöôŸª¡R•ú þ€IDATSIÓ4ã¦U‰GÀNú©©BÕ¸¦i„B!"‘eÑ®úêæÞårÙAØçóár¹ðx<¬Y³†M›6QTTdo_½¶2Úý©£\»ÇÓñ°,UPç&•ƒdÊäDbO$Ôë _ B^ŽE`´ZÝ{"Æ­ÿ‹ñ´µ¦V7Ëîþ#·ÿøÆŽ=Í’%OrÞ ¯ã­«CÇÀE„ȳ&_Ú7›©S§2yòdî¸ã²ÿðÆ,YÂÞ˜~ùåÔD+wÅÅÅÖÚ@À¾–*}>¡ý3MmÞ<\“&áñxìϱúœ–GçòPwTaL§›¨þ4X® §Át®“R'x÷BøjöD{Þ\Y ¾èu¤-ñÍȪ—o(d5,þòù—ÚŸ3¶ö/üuó°èÂW9q*›ÇN³¬úI²òþ¨ìÓ|¢ù9þB=»9C„O±èÊGYµk3ŒÂŒ£‡ør-lŸ6û?ô!Æ|øV¶ÿ ûûÞ]x+'¦Mã‚ý ìŸ6’Lø1S?ô¡hy"äÜp «ò¾hg›ÊÊ?ð/ê{ÝïÇSàá…ÿ¼MÓxðÁ¹óÎOâv»™¸`.—‹êêj&¹\LŠî£,ÜîiwEÿ½ýfʬa{vLòEç%ê(¥"é˜Ö Ê}¨'ñÏçƒ5köÓR]ìK´NÀõ~x%Ú’0RƒÉ.ÐÜñ£• #D4b¾o5¼iá`Þâ²’s!ðÌoÆ¿®$¶Í£G)½â»/Ä4­cüʳ{yzó û)ãÆœ"ðƒWxè¡ ðæyÿ%‡3‡ÓÜÜ Àž=Í9’DZcسg3þ¶‰/gãÕ7F OΦeÖYî¹g$§N aÁ‚üú;¯ñõQy\M 9YGxaÿ$þÄ4{4ÁÖ»÷É{ÞÄú¼¥çÛõóÒR+7à#– A`ÛÎ ëßkÙ°Áº­jý ÌzÎ9ç† †iš<9v,3';;›ææföL˜À·þ6ŒsÏý_Ž=Êå--|¹®€±cÇòþûïóTóB6üí¸êª«Ø¹s—MœÈûo½ÊÉ©Sihhà‚‘aþüÊy444pêÔ)öíÛÇøñãyóÍ7¹à‚ Ø¿?cÆŒa÷îÝ,\¸;w¢é:GŽå0fÌŽ?ÎÔ‚^zõU¾ð…/ð½ï}/•”ðÚïÏ%—\Âßÿüg&ßtŒË5×XIÒ‘#Gòò¼þúëÜsÏ=ø|>~ùÜsø?üa>Ÿo=ú(¿¸÷^¦M›Æ‰'xÿý÷qCtf–’’¨¬$ËqŸUYY‰VR×ÁÌO¬!S݃Q\Lmm-%%%”•—3¾°ï~÷»üéObáÂ…Œ4Mf˜¦}Ÿ¶OÓXÕåÛÑû»%%<^ô8wy‰Ç¤Ä‚— ¨t´ÌÓa¾›N=Ï„P«,ŽÇµÑÖzØjÀŽV à+ܱ½Å±FEƒQð@.<=chw‚>ꑟ;¶ñap-Ö‰·Þf˜×îÇ|ëžþy.\HøyxWÌ$¸iMÂü枸b¸Ÿ> îÙÖhè0¸—6 Dw®¸¼9Á¬\Èw£Àhó$h7σçïà¿xÊÿyàÀ_ýà9ïlŸˆ±hÏùø#£¬V§¢£œ9s†Â™àåã+  n˜ÒÈžƒï²óDMc›Z?”Üa§øøWL~ùßsð]bò£-ÃyÔûœ9{†a'†1ozÇg çÅç&scþq²Î4ó³7Î%gd3'­ åw¼Jé¯/àŸó³µþÏu:¸nô»Üö…z¾òãy¾¼ž [òâŽÛ—fÕQ=<—Í;r¸røQ®ÒΰöÝñqÏYÿ±,ÿ£µ¯}Ÿ—Oà™S±éüÜÔ3aé#lØðÀše;þ]à‹9¯ò¬óˆ4h,vš«Þ?N€ø÷ùÉÏò•Ý×YLj°Ÿ°ã»ÛÍn´_&ô¤Ç~ŸVy)¾Ú77»1Èã™orøS‡»¾fÒP¢± ï¯GàÇÑkô0ð¹àÞèçÆTEàõèµ3ÖzŽYê&­jºƒX²óýXS«û¦lv›@¸¦LnbBÁªžÌãÍÓcØsz ?üÜ&¾ö›ð™©u¼ux$o7E§ €¹cަ1ÿüq4ÀWø‹¸8ŠÉ0tšØ»u+ËN,ÀÇ<ÞÙ¼ƒÑoTÑÂy±4àÖ¬£’çø'rXÀlû)[Ø‚J*£ßô³þñjø)‡þ4};'>Èåõ Ù’·…½c_¡ì­øÄÈw.ù#ßyu-Ï_õ<ú[&ùoµÿ¾'oÿ}^?xåø}~ÊñÛxé²÷˜`^Á{. þòzŽÍ¨ã¼Gß‹{Ϋ߯%ßù°µÍ¥{È{õMrvœ‰=ár àh÷m²Z%IKu¨Îî LX«‚Œþ<ê‚[­ÏÁæë6³`öPØlÆžã|£Õû„[½O Õû8‹ãx|À³‘Øûtktë}ìý>žèì¿Ïÿ\Ÿ’’ë^:ܸí厜íͽ¹‡ma¡mk°¶E´–1‰Ç††€6ºÜÜ\+™Ð‰S§NñöêCxVü‰YX£N ?‡½³ŠÖðSœ=ÀÏ?ÔÝçñöЛišMKËY²÷5s¨| »XÀ‡_ý(ö|ƒ¡C‡’óþdŸ=Lõ+a¶`&Ï5xþ(äää0}ÔtöíÛÇô¦é˜¯›\vÙeìÝ»—éÓ§sþGÎàî‚»©¯¯gܸqüìg?ãÁäž{î±ÿ2e ÷ÝwK–,açÎL:•qãÆ±sçNæÎËc=ÆÚµkùÙÏ~ÆèÑ£y衇>|8Ï<ó ---:tÈN¶½ýöÛ455±ÿ~¶lÙBvv6UUULž<™7ß|“›o¾™¼¼<šš¬ŠÍ”)S˜2e Ó¦Mcîܹ9r„Ï}îsŒ=šM›6ÑÜÜÌÆ¸æškhnnæž{î`þüù힇ææfî¿ÿ~<Èücš››¹å–[8xð ÷ß¿ý¼ƒÚÿ^sÍ5ök«ªª²Ÿ?zôh¶oßÀþýûÙ¶m[ª?®ý®¡¡!î˜tä½÷Þ³2Q"qàôéÓ|ä‹cKK ×;Ã{CÝ yy'oN»ŸÓ§?NSÓ_™8±‘=uÏE_a ÿ ÿ8À¤I÷2dÈþøÇãÜ0q"[G`Þ7Rü{“_þò—ìúüçùò—¿ÌÿüÏÿÐxà üA×™zø0o:@a}=ÕÕÕ̘1ƒÉ“'sæÌ|ðA:ĦM›¸%Úï4zôènÛŽÈ51xôä\oÛ¶½{÷2dÈT»W­¼ù£ ·2#ëƒ4ŽžÍ)¹ ÿö×1MGžCnî?8{v&pê”sš™B¬&u“@Àx9眷øÊ¨:þ6v';šN1fÌæÏœÌ‰;>uüé—˜»j[ÖTðàƒòÐÿ<ÄÜÙsù¯¦é|¤¾ž‘7.¥º¥… ‹Š8ùì³ 8”'>ÁˆÚ<¶än¿ývvìØÁ´iÓ¸˜:u*‹÷êSÖ¿÷ßOUU÷ß¿ý}ë4iÒ$æÏŸÏÁƒã¾7òu²mÛ6öïß? ÷±=Ý'Nœ`Ïž=¼öÚkyS—h ¡¡%#¦R3aïË¡C3}|4ãŠKØ·o=§NA•b±4ÛèÑUŒÜSCÖÿ~“S§®¥¹y;SÿElzˆPø¹V&Â$0¨L4L4t ÇáK_‚+®¸‚;wRóÃ1|ö½÷>|8gÏžeÈ!ÜþÒ$š››ÉÎΦ¶ö8ŸÌÉáwÞ¡ôìYNì:Áž .àþµ»)(( ¾¾mìXžÚIÍ铌9’C‡1úC"üøãö½Å-·ÜBåöí̘1ƒm'OrrêTÆÏœ9sÈÏÏç/ù ¦ÇC bÄ}÷ñÝï~—ÏíkðÃrûí·³sçN&ÏË­ÇŽ±ÿ~®»î:~ûÛßòoÿöo\ḗ9÷®»Xð³ŸqÝu×ñöÛo3uêT>‰0|øp.¾øbž}öYöÜu—}ÿóÕ{îá®»î✟ýŒøÃöñþÖÃqãÆQ]]Íí7ß̇FfÉ’%<öØcL[²„ßÏõ×_ÏŽ;˜:u*—¼m´œ:u*sçÎåèW°é±Ç˜¸d áÇcÉ’%|è±Ç¸ùæ›™4içNÊá~”;vpÅWpôèQæÇ—\‚®ë\y啾ì2ŽÏ™Ã»óæqî§>Åä©S¹:—q”qÄþýœ¼â >óË_²íäI|ðAæÍ›Çƒ>ÈÉQ£¸þûß·c¸zŠåª.¨î³ÔïO<ñ_GTÿw¾ÖyµiÓ&¶mÛÆUW]Õ¦n©îÓÔýÛý÷ßÏo¼Á7¾ñ ž|òÉT_Ö½’h,xíµ×ð]5TOF2jä4™‡Ýü%ûM®Õ׳eÇÍdee1ôìP¦ýð_9ÚðûÎŒ`ÆÄÍLjlà·'>Êb£ƒ®}ð»¼pà>®›ö}žå›qï}í÷~Å«#ÿJ_dÈoX8åžåaÆa2ïÅWöñOòê©hii!ç?ŸfÖ±s9ÕôZZ.fcí²²øÅ߿ȩSÐÜÜÌ#U?%·vYYYœ9s†¬¬,ö<ò(NŸÆŠKó Sà˜Ö(›l|¼Ì_¹ž“œä0ãù»aÖÌo¯XÏ[Í>¯[­ ħ¶±Çúç{Â<ô¨aÿ{ˆoáÂ@F@“͇&0“f3›I{špñ363ó 7a"¸øÉêÍ|š5ìbÛþ¼‡U¼ÈšibœË;f3¾~¸‹áÛO2›ü‰×Øu&2!C†òÌo÷q[ö­œ{æ\F×bň×ñ9Á™a{rzy§Ž³ê¸¢Ÿ3G7sïáýlò$-ÃZh¢‰QŒâÙw'òÌè÷Y8ÆÐC;f,_ß}†%Ó i©oáÍ‘#¹õØN–·ÔsbÄ ÆŸÏè1£¹ýÉ}|sÁ+lÞ¼™¿ì2~ù7wœ‰ïO$;;›ê!ãy¤e/S ò¨©¯gòùçã­ªbÆŒìÝ»—)S¦°zÏ.ÞññT_Ö½’H,8zô(/lóðÎIœ2†fFÑ8$—3½—š#ß§¹¹™¼È_8ÕX@õ™øÙå/øØr @GUx'3ë~\ÄVùåK¼ÄDÆq+õænfo˜bYYCÈ’Å™¡g¨xâU¼ú•?~œwF¾Ã=Ã÷0·å#† …†ŒÂoMeÖM¿çlÍHí<Ä÷G}È~ŸS#O±Ül¶Ì}•ÉÙ“©o©ç"í»Ìž7œÓõ§ÉÉÉaÖ¤ üê¿âÝwßeÒ•“úèÿ°ÿ½ý >œÓ§O33g³.»‚æ¾@UU/¨½ËKÞ¸œ#c/à¹+Þbΰ9Ô«£pr§'þMÓh<ÜȸsÆñûÍSh¸oˆý>Õü“'ÅögøûÃùÚ¯.fÅ}+¨ªªâ‚ÿwN¹›sÎ9‡ÓïœfèÈ¡Tí™Æ¾©7rÎ×Îá•¡¯ðÑ È?ç¿ÑÎÕ8~à8¹¹¹üì§3˜ÿðlÿívöÝËÐ÷v1aÚ†ŒÂÙãgÉ9šÃ7×]ÁgîûŒý>“îa¤ 31¶e,/o»€W.\À¤û&ñÎ;ïP85‹ÉSäœsÎáèÛG­Ž¢ë&sqh9ÿøÇ?˜:e*—dýÓf$;;»Ã÷¹øœ¯1qüDòvm¡yÔhžÛ¶ˆç/$ÿKùÔ«£`êIfNü9ÇÏgèÈ¡L9•ŸýtsBŸæÿøޏ‹NÄŽ[ss3CßJ$24Õ—t¿Ç°ÚL¿“÷;Ž9Á³-—PËYtxß¾‚áÃc.2Y°`/7~ƒ³gsÉÊ:BKK% ~&NœÈ¨iÍ<ùþû|°³ÂdÊÝSXxÏB6~{#ÝgµÙgggó׿þ•o}ë[Ì;7îý›››¾wma¡3ÓÛ"öîÝ˶mÛn3̘©V«ªªX¾|9;wîŒ{|ùòåfóõ«_±ñ;aŽï½‘¿ÌÃ<5‚áÇ~FŒø,§NBÓ"47Oãý÷Ï#/ïMNz‡ñã[xûí¿2oÞ$Þ~ûm>ðpðàAæÍ›ÇþýûÉÉɱ*‹cÆ0aÂ>ÌìÙ³y饗¸òÊ+í÷ïßÏ´iÓhjjbÔ¨QvrOý„ V’rútûßQ£F%|Ì:ÄĉS}êúÕÑ£GÉÎÎfĈ‰o,ƒt÷\ïß¿Ÿýû÷“››ËºuëR]ìK$|úÓŸfëãÙ¼™•ÇéÓ'+ëM&Lx™ÆÆ½œ{îU;ö……Gxûí·™7o{öìáâ‹/æðáÃŒ=š¼<«êôéÓÉrM =9×›7oæÌ™3,_¾œ›o¾9ÕEï±Dë?úÑà ý£ì=ƒ¦¦)Ñ€»--ã9ò¯Œû.ÇŽËøñã>üy.ºè"vìØÁ¼yóxçw¸òÊ+Ùµk—ýý0{öì>ý^OÄ`¼&N:Ess3ãÆK|c¤»çúèÑ£lß¾S§Nñë_ÿšÇÔ’™ Ñ:Á÷¾÷=~ô£ã=zÙÙÙœ>}šI“ŽÓÐð3g~‚Ý»w3{v#{ö¼ÌŒ3xÿý÷™1ÃµØØØHNNû÷ïgÞ¼yìØ±ƒ °yóf-ZÄK/½ÄìÙ³9|ø0&X=ÆÕÿwíÚÅ•W^Ék¯½Æu×]Ç®]»ìX¡:ªx¡þ___o?GÍþÑú5»·P¯™={6é"Së#™ZîžÄ¿;vÐØØÈ%—\¿þ뿦ºè=–H,hlläŽ;î༛¡C­FÖáÃ_cèн´´Ôröìõœ>}šsÎy”÷Þ»•)S¦ðî»ïrÞyoðî»O‘›{MM#;ö]Μɡ©i$ÙÙÙ˜¦ÉÔ©Syï½ÿãÒK/å•W^aÖ¬Y¼õÖ[hšFSS“}_ÑÔÔDnn. hšÆÛo¿Íüùó©­­å²Ë.³;©¸£Ê=tèPŽ9Ò&©ßÛ{MGq«³×L›6Í®÷¼ôÒKÜxã<ùä“öïÅ:ã.¾øbû5Ï=÷œ}5aÂ;Þ9cÝßÿþ÷^ÅÇÖÿvç5³gÏîÖû¼ùæ›ôè5½ÏôéÓ9qâ„]L¤lκçìÙ³ííƒU'3fL›z¨óœ)ƒùþà‰'žÀç«`ÇŽeŒ»“S§N1~üxššÖ2jÔJΞý3cǾˉÙœ=›ËŒg8}z'º®·iÿÛ¾};K–,ᥗ^"//úèÝêZq¶>ùä“\wÝu¼öÚkíÞ[¨ó|ñÅ·yŸ—^z‰ùóçSWWǹçžk¿¦uÛ¤ºþ>ñ‰OØ¿¿öÚkvÙòòò=z4ûöí³;ÝxãmÞO•m×®]íîz#n¼ñFûó«^£ÞóòË/çïÿ;×\sM‡ïÓÑþ´>í•M½zŽóüþ÷¿çŸøD›×¨k²³ýÙ»w/cÇŽeÿþýäååÙe›>}º}e»øâ‹ÙµkWÜõ§Žµó¹jûê÷×^{éÓ§÷ê8?;Îc0gÎÞxã.umm-ÙÙÙ466òâ‹/¦ú²î±DïV¬XAÓ/?Ls#޲#k' sæÌÓdgßÄ©S§¸âŠgxùå!\yå0ÞÍùçŸÏ!Câbªú ¦¢.>îû3µþí”ém;vìÀ4Í„ëƒ"ñ(„$!@bBâ€Â"±@ „„H77ÇZ{C£ R],!D?’8 „‰B‰B‹Ä!H,BH"]dLâQÍϼuëָǫªªÈÏÏïÍ&…Fâ€$!$!, „ ±@!q@ˆt“1‰G€¥K—²aÃX·n999,^¼8ÕEBô‰BX „8 „°H,B€Ä!„Ä!ÒIƬñÖâæË–-³<¯««cÕªU,]º4ÕEBô‰BX „8 „°H,B€Ä!„Ä!ÒIF%•ªª*æÏŸONNNª‹#„H‰BX „8 „°H,B€Ä!„Ä!ÒAF&…B!„B!„B!„é%£ÖxB!„B!„B!„B¤'I< !„B!„B!„B!&‰G!„B!„B!„B!DÂ$ñ(„B!„B!„B!„HØ€N<®Y³†+®¸‚¹sç²råJêêêR]¤„lܸ‘åË—·ù©©©éñ~g±¹í¶Û¨ªªj÷oÉØÇt=íwwÎÿ@9÷É6Ðö9Y± SŽK"± “¯‰öö{°}$Û@ÚçÁøYè($kÓñ8H`àilldåÊ•Ì;—¹sçrÛm·µ¹n!}ëº7nÄív3wî\Ün77nLûr766²zõê¸möU¬LFÙ;ºî[ïG{Ç?YÇWbCßKV,HÅùì*¤c¹»’U®d•;‘XN1Mt®;± ]ÏgÔ ’]îL«@û± Yu‚îÙâ>'#dÊqI$dò5ÑÑ~¦ïdhû<Ø> ]ÉØÇt<R'˜ÔqÞ´iS˦M›Zî¾ûî––††û9éZ×}ê©§ZæÌ™Ó [6mÚÔrß}÷µÌ™3'©Ÿ»¾(·ÚÆSO=eó|ä#I=ÞÉ*{g×ý²eËZ íýøÁ~Ð2gΜ–§žz*©ÇWbCÿHF,HÅùì*¤k¹»ŠÉ*W²ÊH,H§˜&ºÖU,H×óÙu‚¾(w&Õ ZZ:Žɨtç9ÒCÅýþÜŸÖŸëL؇þª $6ñ¨c”·Þz«MÎ4÷Ýw_Ë}÷Ý—ð~§ó±ùÝï~×2gÎû§½Šv2ö1ÝŽAwö»«óŸé羯 Ä}NF,H÷ã’ŒX‰×DWû=¾úÊ@ÛçÁòYèêšHÖ>¦Óq:ÁÀµuëÖ–9sæ´lݺÕ~¬¡¡¡O>³}q~o½õÖ¸m¶´´´Ü}÷Ý-¿ûÝïÒ¶Ü›6mjÓ ÐÐÐ`ßð'«Ü‰–½«ë¾½Ï‰:'wß}wR¯Ä†¾—¬XŠóÙUHÇrw'$«\‰–;± bšèžîÄ‚t=ŸýQ'Hv¹3¥NÐÒÒy,HV ;Ï‘8zý÷ûC0l¹õÖ[Û|®3aú«4 È©Vkjj¨««£¨¨È~,??Ÿ‚‚¶nÝšêâõZ]]999 íwº›¢¢"Ö¯_ÏúõëûlÓñtµßÐùùç¾/ Ô}N4dÂqI4dê5ÑÕ~†ï¾0÷y°|:»&’µév¤N0påää°bÅ :|NºÖuëêꨩ©‰Û&ÀÚµkYºtiÚ–[MᔟŸwæÏŸoïS:Ä‘î|ÿµùìÌŸ?ŸÆÆÆ¤_‰ ý#± 糫8®åî*t÷=û#†% Ò%¦‰îé*¤ëùì:A_”;SêÐy,HF ;Ï‘8ú+î÷‡šš‚Á ßýîwÛ<žîûÐ_u fXª ÐÚ|rssÛÇ?Slݺ•††æÎ X_«V­²?àÝÙït?6ùùùq•€Ö’±êñt:]í7t~þ¹ï uŸéx ´–h,èÎ>¦ã磫ý ß}a îó`ù,tvM$kÓí8H`àÊÏÏgÕªU€ucÚÐÐÀ† (((°ÏEºÖuUã|~~>«W¯¦®®Žüü|–.]JAAAÚ–{þüùvùוڟdÕ½¦ººî Ú4>666òÔSO%µþ'±¡$#¤â|vÒµÜ]Åî¾gİDcÁ@­ T]ÅÕnç³?ê}QîL©¨cÛQ,HF ;ÏÉ„v£Á ¿â~_kllä¾ûîÃëõ¶I¢fÂ>ôWh #ªÆÆFòóó ‡Ã„Ãa–.]ÊêÕ«Û]p\ òÈ#©.JÂ2­”jzÄc{çLýBéHQQ‘=‡wOö;ÓM2ö1Ó´=ÿƒáÜ÷Æ`ØçÞÄ‚p\’±™~ë÷@o ô}¬Ÿ…díc¦©¤?µ6ˆSQQEEEmF«¦k]·uBdÑ¢Eq#ұ܄ÃavîÜÉÎ;Y»v-¹¹¹}R_èËkª¦¦Æîe‡YµjU» NR7JÉŒ©8Ÿ]Åt,wwâ@²ÊÕ××OwbA&Ä4ÑýX®ç³?êÉ.·Ô Ò/¦‰®õgÜï UUUäææ²zõj–/_ÎòåËØHïLØ¥¿ê@Å€L<ªžþ­欪ªJûCÙ¸qcÜŨÔÕÕÙÁ¦;ûéÇ&û˜‰Ç «ó?Î}o Ä}NF,Ç%û˜iÇA¾zo í³|Hê>fÚq:AæÚ¸q#Ë–-ëô9éZ×Uë"µÞfëu‘ҭܬY³&®A ±±‘ªª*æÏŸŸQqdåÊ•,^¼˜µk×¶»ÍÁX7ÊTɈ©8Ÿ]Åt-wWq »ï™.÷XÅ‚LŠi¢ëX®ç³?ê}Qn©¤gL]ë¸ß—–.]Ê<ÀŠ+ì€Å‹³bÅŠŒØ‡þª 42ñÖ‡zÆ vÏïuëÖ‘““ÃâÅ‹S]´^)(( ªªŠ5kÖØUUUÙó¿÷d¿3ýØ$c3ítçü†sßmŸ“ ÂqIÆ>fÒqïÄ ¤}–ÏBL²ö1“ŽƒÔ 2×¢E‹hlldݺuöcUUUTUUÅM‘œŽu]•Ô^³f½Mõ¹SSª¥k¹7nÜwÌ׬YCNNNRËÝewªªª¢®®Îãüqöšlu£L•¬XÐßç³;q ]ËÝUHV¹úúúéN,È„˜&,݉éx>û«NÐå–:AzÅ4ѵþŒû}E%Ýœ?`Ý×&;Öõ•þ¬ $Y----©.D_hlldÙ²e466’““C]]«V­Jûõ:³aû‘)77—ºº:V¬XÁªU«z´ß™rlæÎËúõëÛ¬U•Œ}LçcÐÑ~wuþÒ¹O¦¸ÏɈ™t\z 2ýšho¿Û÷@2 ´}ŒŸ…ö®‰dícº© <6l`õêÕäääôéµÛç·®®Ž•+WRSSCAA555IÿÜõE¹«ªªX¹r%¹¹¹444››ËÚµkí)Ò-Ž´wݯY³&®¡Ô©¨¨È^l ×’dÄ‚TœÏ®â@º–»«8¬r%³Ü½éÓD纊éz>û£NÐåδ:´ɪtç9R¯?ã~jý¹Î„}è¯:Ð@2`Šš}þüù³èjgí!¹ùùùÅíÎ~gú±IÆ>fÚ1èÎù ç¾7Ú>'+ „ã’Œ}̤ã ߉Hû,Ÿ…äïc&©d®ºº:{Zž¾¾vûâüªmöåç.Ùåv^/­ùÉ,w_”½7[Ý(S%+¤â|vÒ±Ü݉É*W:\?)¦ t݉éz>û£NìrK çÏI‡ý]Ë”Ïd¦ïCÕ‚ŸxB!„B!„B!„Bô½»Æ£B!„B!„B!„¢ÿHâQ!„B!„B!„B‘0I< !„B!„B!„B!&‰G!„B!„B!„B!DÂ$ñ(„B!„B!„B!„H˜$…B!„B!„B!„ “Ä£B!„B!„B!„"a’xB!„B!„B!„B$LB!„B!„B!„Bˆ„IâQ!„B!„B!„B‘0I< !„B!„B!„B!&‰G!„B!„B!„B!DÂ$ñ(„B!„B!„B!„H˜$…B!„B!„B!„ “Ä£H;¦i‰D’¶­p8Üge ‡Ã˜¦™’÷NTº—OˆžêèóÜ^LéËÏgq¡¯ß;Qé\6!z£'ŸéΞ‰D0 £Gï-u!úOgŸ×Öõ€ž~¾;zn²ãBoÊÖŸÒ¹lb`Jf»€Úž\û=—ÎeƒC¢± /ë½)‹Ü‘~äÚï£ãÒ"ÒZyyyKmmm‡¿$õõõ-§hZ\.WKuuuBÛ¬¬¬léË9ÐRYY™’÷NTº—o°L×~2ÔÖÖ¶ùgeeeƒA{[êwuÕ¹3 ƒp8ŒÇã±+ n·»Ýãcš&@À>Ç=ymO޵¦iqŸ!ç>vôùìì8–••Ù¿‡Ãa ð÷¿õ9r–¿;¯UÇ$Ñ}O¥ÎŽmg×½:&í]û©ºîeNåµß×}w®¿Î®}uþÔqiï3ÑQLiïù*6hš–Ô¸à<ž­cC*âBg¯Wç9ãB"uu c,H‡:@"± §ßã­ëÅg¹ª««ìÏU0Œ»~ºKê}c ×ÿÝnw»uG¦_û½­8?Ý©´Ž m;ÙqÁy¬¥Ž\rÐùv =ïºsíöU@ûÁxí”:AkRGèz[žu„DÚÕùë‹:Â@hCìM ÓcAkRGè|;žu„T¶ Ök?Ñúÿ€ñhš&³fͲ/þP(DqqqÜTHõzQ` °{Á˜¦IaaaÜŽú»iš˜¦III ÅÅÅö<à@ ®§[OŸß—JKKíý6 ƒÂ¸‰þ½3=9ê1—ËE$!£išý¡”––Úïí÷ûí׆A0dÖ¬Yö{·9ÆêqÈzòÚî(,,´_‡ãzVuõùìê8:µ®@Ç=§¤¤ÄþüvõZ )ûžJÛή{u|:ºö3ùº‡Ä®íþºî»sýuvíƒU¡©¬¬lsÃßULiýrƆdÆè86¤*.tçõ™©¨ã1cAºÔ‰=¹^Û«tCT¹€¸#zJê}Cêÿ×~oëÐýz@{q¡³m'3.€ÔúŠÜ´/îºsíöUïµ?ê­I¡c™PGH¤ú®Žémˆ‰Ö óbAkRGh_&ÔRÙn0دý^ïwªçŠM–ÖsÎÖ××·¸Ýî–ÚÚZ{NoçÜÆº®Ûâæ ///oÑ4Íþh)//·w¹\-^¯×þÝçóµ¸Ýî^?¿3n·;nàÖ¿w¦ºººÍ~»ÝîŸÏ—”¿w¥'Ç¡¢¢¢hq»Ý-º®·èºÞ¢iš}^€¸÷-//·_«Î}YYYÜß–G}´h©¯¯oóþ]½¶¾¾¾[ûXYYifœÇJÍï|ÅùùìÎ{8µþü´ÞŽÏç³×›èìµí{&ÍÞѱ}î¹ç:¼î[ZZº¼öSyÝ·´¤îÚïÏë¾;×_g×~gŸƒ®bŠz~{±!YqA½®£Øª¸ÐÙë35.ô¶ÐÒ2xcA:Õ‰]½¶³kÝ©½µ ÔvÚ{žÔÒÃ`©ÿwôXGʵßÛ:@KKçõ€îÆ…ö¶¬¸ ¶%u„¾!÷meÊýAWuxµ½¾¬´´ ¾k Ô Z“:Bû2¥ŽHagŸƒ®¶ÝUœÈô6ÄÞÖºÚ÷tŽ­I¡­L©#¤²Ý`°^û‰^÷fÄ£úYZZj÷V©¬¬D×uB¡n·;n˜¯Ç㬠®®ë˜¦i—V¿«ìºsû`M«ÑÕמ>¿/´·ßÎ?‰þ½'祫ãàìqT[[Kmm-^¯7.«ïÆÛÞmçt5Œø7Þ°{K¨óÞ×:ÏW Ãhs¬œCñ;û|&JmGõF‡Ã˜¦Ùí×··ï™4xGÇöïÿ{‡×=tïÚÏÄë»¶ûóºWººþººöÛÓ˜džDãt$.$Ooë0xcA:Õ”DbAW¯íªОή™ž\ORGè;Rÿoß@ºö{Sp¾¾³z@*ãH¡/ÉýA[™rÐÝ:|¦Ö @®ýþ"u„öeJ!m„IF!SÛí{:ǂ֤ŽÐV¦Ô”T¶ Ök¿·×ý€J; ÷†3P¹\.|>Ÿý™èÉk»Ã9ïq{:û|&Êï÷“••E °ƒR"RõE×[Û®¨\ûé+ŸÁîÆ”žÄ†Þ”«³Ø q!yz[‰é,‘Ï]ë×ö´ ^Ó‘žTü¥ŽÐw¤þ?0õu=`Ë–-@jãH¡/ÉýAæêëvk _ûNRGÈl} º³íÞÖ2¥ 1Ùq 7ûžjRGxRÙn0X¯ýî¾~À$Õ‚œåååÔ××S]]M(" ¢iZ‡ÄårÙÙcõSQQÏçë´r™)Zïw8Ž›Ã7Ñ¿'KgØî~˜eUó+åååvv¾£ù›;zmwèºÞ¦‡ƒs}>¡¶Q[[Kee%ååå=þÜ&ºï©ÖѱݵkW§û"×~Çï¯ë¾½²$ë3ØÝ˜ÒYlHF¹:‹ ’§·uܱ ]êí½_O?w]½¶«z@{Ô ³'_W7 mGê}Cêÿ,×~G:«Œ7Hm\PÛ’:BßûƒöeÂýA_· €\ûùÚw’:BÇ2¡ŽŒXЛ×w·Ž‰mˆÉˆÉØ÷T“:Bû2¡ŽÐ^Yú»Ý`°^û½Ýï“xT‹¾ª×uÝþ2ñx<ö‚Áê©æv»ã~‡ØB¤é¢õÉìîÉõz½möÛÙ‹#Ñ¿'“ËåB×õ¸ÅLý~?º®wûbh½˜¬¦i\~ùåöcj±è@ Ðf8p{¯íI¯Ç·ðªê£töùìç9p.îjš&š¦Ù7<íõþêèµíí»:æ™Ôc§£cë\(\í¿ó:—k¿ý¿÷çu¯$zýµ§'1¥£ØŒruR:{}ë}Ï„¸ÐÛ: ÞXNu%‘k®;¯í¬Ðõ¹w~6B¡P¦f©#ô¥ÁTÿïè±ö ¦k¿#ÕfÏžm?–ª¸RGèKrÐV¦ÜôU»@ºÔ }¯ýL¯´&u„öeJ!± 7Ûîn!Û“Qh½ï™ Z“:B[™RGPRÙn0X¯ýÞ^÷ú]ò4çõz …BÌš5Ë.— ÇcgŠ‹‹‹q»Ýö|ºêÀ—••á÷ûíàa†=¬5Õ4MÃï÷Ûsëß;£ëz›ýÖ4-ný€DþžlÇõ˜èÉy0 ƒY³fÙ¯-//oóǃÇã¡´´4nÛÝymgÔPì’’\.†aØÁ:ÿ|vÅëõÚÛ5MÓ®$«ý ƒÌš5 ]×í϶êÍÐÙkU¹#‘Hܾ§Ëg¿»::¶wÝu'Nl÷ºäÚïàïíÅ˾¼îÕqOäúëHObŠ36¨ÞMÉ(Wg±!•q¡³×gb\èmo,èêZïï:€:î½½æºûÚŽê)++£¸¸Ø^AÓ´¸õ ºCê}g°Ôÿ;z¬#ƒéÚïLGõ€Ö !©ˆ u„¾$÷meÒýA´ €\û­NÐÞñ:B[™TGH4ôfÛÝ­#dbb¢uUîL‹í©#Äˤ:‚:î©j7Œ×~"×}VKKKKâ§<}¨ì¬ê­ H$±®®ëƒA ࢢ"î9ꀦËÕβ;­U¿w‡av†¾½lt¢ï‹ýíÉ{…ÃaŠ‹‹iii±ÏwÏa"¯íìX;?­ßèðï‰D"˜¦Ùáyo]vµÈ±ÂÝÙkÛ{}&j}l»s݃\ûý½?®ûd_ÇžìG_”«³ØŠ¸Ð›×g‚ÞÖœÏK·}îëXu€túoOoâH{¤ŽÐwzý¿£Çº2¯ýžËdïG2·+u„¾#÷m¥ûýAë}íÉ{eZLI·k Ô :*³Ôâ¥{¡õþöÅ{¥CœIÅýA¢u€ö¶‘‰¤ŽÐVº×RÙn ×~ï®û—xlÊFWWWÛÙäââb|>_Ÿfà»â Véìd&úúT•;Ùœ²^Ûû˜nÇq ¨×}²¶‘ª²;%ríö¥ÎÊ%±!ó ÔXÊÏI:Å‚Tĉ™A®ýô®@úÖzKbCú“¸þu‚D¤*¦ÈµŸy$¤!]IâÀ%q!ýë©l7k¿wÌT«q VS'¨a¤©ÔÑœºNõHôõ©*w&è} Ç1•êuŸ¬m¤ªì™NbC樱 •Ÿ“Áþ•8äÚO¯rÒŸÄ…ô+û@ ×~æ‘X^å$d>‰ éWöL ×~çňG!„B!„B!„B!Dß’ê!„B!„B!„B!2Ÿ$…B!„B!„B!„ “Ä£B!„B!„B!„"a’xB!„B!„B!„B$LB!„B!„B!„Bˆ„IâQ!„B!„B!„B‘0I< !„B!„B!„B!6,ÕèÿöoÿÆ–-[ÈÍÍMuQúÕ;ï¼Ã¤I“R]Œ~uäÈFŽÉÈ‘#S]”~ÕÓs=tèPzè¡T»ßÝ|óÍœsÎ9©.F¿’kbðèé¹>yò$·Ür Ÿþô§S]ô~%u‚ÁãäÉ“œ’©åîMü›8q"?øÁR]ô~UWWÇÊ•+3²N©±@ÊÞå¬÷ÿ÷ÿÇã?žq±~0}G¥ƒL-7H›aw}á _àÌ™3©.FB2õûÊ)Sc›S&Ç ç>$Z'‰Ç×^{o¼‘/|á ©.J¿Z¾|9ëׯOu1úÕš5k(**¢¨¨(ÕEéW==×Ë—/Ou‘SâÝwßå‰'žHu1ú•\ƒGOÏuUUUUU©.v¿“:Áà¡>ã«V­JuQúUOÏõš5k¨««t‰ÇC‡eä5‘©×r¦ÖG2µÜ½‰ƒñþ ®®Ž¢¢¢ŒüžÈÔX åNïrÖûƒýû÷ó•¯|%ãbý`úŽJ™Zn6Ãî:sæLFÆz§Lý¾rÊÔØæ”Éñ¢õ>$"m¦ZmlldõêÕ\qÅÌ;—åË—SSSÓæykÖ¬±Ÿ³råJêêêºÜvNNcÆŒIõ.ö»‚‚‚T¡ßåççgdÕD ”sÝ—q`ìØ±©ÞÅ~'×Äà1ÎµÔ ’o0^¹¹¹ƒ.™ë\w'ô¶N©2õüfêwT¦–{ Å¿¾¾?ÈT™ ¤ÜRîÞ’XЖ|GI¹»k Ä‰]ç:Sc›S&Ç‹dJ›Äãš5k¨ªªâ»ßý.ëׯ'''‡e˖Ň5kÖ°aÃV­ZÅúõëí©Qº2oÞÂâÅ‹Û]×qÕªUn# ²bÅ V¬X@QQ TUU±téRÀ 0j-I€µk×Ú½-Z”êc)„HÄ!H,BXºŠ„øþ?{÷GY÷ÿÿÕ=§PhK -ÚRRŽ‘ ñ­ßMðLoéî¾7os»«þ@o¸Å]Í­"Þh¶Þw=¢Éz£ @5£‚Ј©M9”-¡´ÅÒiÓCzîïÙ™l=&mzx?<’ìÎÎiw¯½>×çséš@D@mˆ¨9ÖôJÆcKK £Fbúôé´´´ÐÜÜÜågonnî2?ä}÷Ý5ÍÍÍ´´´tX¦¤¤„²²2/^Ü×çQDzH퀈€Ú ì¯-P; rüÓ5ˆ€ÚQ; r,ꕌÇ0›±¥¥… °aà yйAèN˜]RRÂ]wÝEKK %%%TUUQVVÐa…FµßÀæöíÛY²d £FŠÖ'r"jii¡¥¥…M›6õõ®t»opøÚ€M›6ÑØØHII %%%}}È"}¦±±‘%K–°}ûö¾Þ•.ŽÔ5Aw9‘´¶¶²xñbV®\Ù×»Ò­ýµ=½&غu+ú~ '¼ææf6lØÀÖ­[ûzWº8ßV®\Icc#Ó§Oï¶r“ȉBßôý@D}†ê3àûAo\ôJÆ#À]wÝ…mÛÔÔÔ0oÞ<æÍ›ÇìÙ³±mû€ÞܳfÍ¢¨¨ˆ²²2ZZZ¸ùæ›ø±û²mÛ6š››5ºANx---466²yóæ¾Þ•½:\íÀæÍ›illÔÄÒrÂkll¤¹¹™mÛ¶õõ®ìÕá¾&hllìëCéSaY¢£5ð:\mAxÔ÷9Ñ-^¼˜ÆÆÆ£2ð:œßÂÀcØY)r¢Ò÷}?QŸ¡ú E ø~Ð×½’ñX8qkUUU4R°±±‘ššæÎ‹ã8û]O<ê4ضM]]wß}wöoäÈ‘\{íµ¹$'¼0 ¹·>”‡ÃÕŒ;v¿óÍŠœª««ill<ª¿\ëš@äð*))¡ººšššš¾Þ•}Ú[[ÐÓ9ZF­kèPžìhu8¿\rÉ%j DÐ÷}?QŸ¡ú EUUU”””ôøš W2,XMîZXždÆŒÜwß}ш‰9¨B3gÎì2Ê »ÆOå‘DŽjDÔˆH`mÚ‘㟮 DÔˆˆÚ‘cI¯;OÜZ(¬‰¼¯ÑÓ§OèRꨰá×ßy™°ö²ˆÛÔˆ¨-‘ÀþÚµ"Ç?]ˆ¨-µ"Ç¢^ <î+õ2 8îkdAQQ3fÌ ¦¦†ÖÖV h,XСŒRUUuuuÑ2óæÍ£¨¨ˆë®»®¯Ï£ˆôÚµ"8¶@í€ÈñM×"j DDí€È±¨Wæxœ9s&óæÍàºë®‹&x çx,++Ûo­ô»ï¾›¹sçrñÅSVVFss3sæÌéB]]]ÍÍ7ßM$ÛÒÒBuuu‡ò®"rìR; " ¶@Dûk ÔˆÿtM " ¶@DÔˆkz%ðN¼:oÞ¼( çyÜŸ’’zè¡(s²¤¤¤KtQQQ‡e¦OŸ®†Cä8¢v@D@mˆöר9þéš@D@mˆ¨9ÖôJà‚àc<gñâÅ477Goþƒ¼u™‘ºŒˆ»Ôˆ¨-‘ÀþÞçjDŽº&P[ "jD޽x„özËzs‹ˆˆˆˆˆˆˆˆˆˆˆˆœXú÷ÖŠêêê˜={6ÍÍÍÑm_|1wÝuW4¡«ˆˆˆˆˆˆˆˆˆˆˆˆˆŸz%ð8oÞ<îºë.€u“«ªªxüñǹùæ›ûú8EDDDDDDDDDDDDä0ê•Àc]]UUUÌŸ?¿Ã¤®ÕÕÕüð‡?¤¹¹9šÔUDDDDDDDDDDDDDŽ?½xliiaæÌ™ÝÞWVVС«ˆˆˆˆˆˆˆˆˆˆˆˆˆ_z%ðXRR²×ŒÆ–– =)"""""""""""""ÇŸ½±’™3g2oÞV9Lz%ðX]] @MM 555î+++ã¾ûîëëã‘ÃèÍÍÍ<þøã\wÝuQ ÕêêjªªªhllŒÊ«Î˜1C™Ž"""""""""""""'€C <–””PRRB6›¥¹¹™™3g2}útfΜIUUU_“ˆˆˆˆˆˆˆˆˆˆˆˆˆa‡x,**¢ªªŠªª*Z[[yüñÇill¤¦¦&Êrœ9sf_›ˆˆˆˆˆˆˆˆˆˆˆˆˆ!=žã1 B†,X@cc#wÞyg„¼îºë(**êëc‘äo¯pæÌ™Ü}÷Ý<÷ÜsÄãqZZZ˜5kÍÍÍ}}¬"""""""""""""r˜ô8ã±;---477STTDuu5ÕÕÕ}}œ"""""""""""""rõ(㱦¦Û¶©©©‰n«««Ã¶mæÎËìÙ³•í(""""""""""""r8äÀcMM óæÍ£¬¬Œ3fA¦ã]wÝEYYóçÏç¾û¥¥C`RDDDDDDDDDDDDDŽ?‡Tjµµµ•yóæQ]]Íœ9s¢Ûëêê¸ï¾û())‰nŸ;w.ÍÍÍ”••õõñŠˆˆˆˆˆˆˆˆˆˆˆˆÈapH‹/ ªªªÃíap±0è8sæL Ȇ‘ãÓ!(**êr{Xvµ3EDDDDDDDDDDDDŽ_‡x ƒ‹­­­Ñm ,`úôé– Ž*³*""""""""""""rü:¤Àc\Ìf³ÑmáüŽaiÕηwHŠˆˆˆˆˆˆˆˆˆˆˆˆÈñcà¡<¨¨¨ˆ9sæ0oÞ¼¨ìjss3sæÌ‰–inn¦®®Žºº:æÌ™Ó¥,«ˆˆˆˆˆˆˆˆˆˆˆˆˆ?)ðP]]MIIITbuΜ9TWWG÷×ÔÔÐØØØåv9þrà ªªŠªªªnï«®®Ö¼Ž"""""""""""""'ˆ¨Ôê¨Q£:t9qrà±¹¹™¹sçÒÒÒÝVUUÅÝwßÝ×Ç$"""""""""""""ûàº.®ëÇ{mýõ555lذ9sæ0þ|fΜI]]555}}žDDDDDDDDDDDDD¤×u;üH$ð<¯×ÖHÇ––©®®¦ººš3fpß}÷QVVFssswªµµ•‹/¾8*ãZ¨¦¦†‹/¾˜©S§vɸ‘ã‡Úµ"Ø[[ v@äÄ¡kµ"¢v@¤;¾ïðržçQYYÝfÉdÃ0zm9ðPRRÒáö3fôÊNÍ;—ÖÖÖ.·×ÔÔPWWGuu5óçϧ¥¥…¹sçöÚÉ‘£‡Úµ"è®-P; rbÑ5ˆ€ÚQ; ÒL&Óáÿî2=Ï£¢¢ß÷1M3º=›Íâ8™L†\.ÇÌ™3{¼?‡\jõp™7o6lèö¾ PUUEUUU”eÙÜÜÌ‚ úz·E¤©P[ "½µjDNº&P[ "jDö¦0ðèû>†aà8žçáû>‰DÇq0M“òòrlÛÆq’É$étÃ00 ƒÏþó=ÞŸ£*ðØÜÜL6›åž{îéö¾–––Y•%%%”••±xñâ¾Þué%jDÔˆH`omÚ‘‡® DÔˆˆÚ‘T*Õííˬ¦R©¨ljEEE”ɘËåH&“Äb1|ßÇq\×¥¢¢Û¶ñ}ŸT*ÅûÞ÷¾ïëQxlmmåÎ;ï$SVVÖåþp$Cçr®£Fê•y%E¤ï©P[ "}µjDN º&P[ "jD ½$j˜ÁèºntŸeY¤R)<Ïò,lÛ&‹Q__O,£¶¶6Êx¬¯¯'NËåhjj NG÷T³gÏfêÔ©Ñϼyóhllìp[øs 'mÔ¨QÌ™3§×Ÿµk×RSSCMMM¯¯[äXRWWÇìÙ³Y±bE_ïJ·g;°bÅ fÏžM]]]_ªHŸš={6555¬]»¶¯w¥[Gâš`öìÙ}}˜"}ª¹¹™Ù³góØcõõ®ìÕál Ö¬Yµ…"'²ð3qÍš5}½+Ý:Üß{ì1fÏž­I9áéû¾ˆ¨ÏP}†rtó<††,ËÂu]r¹@”¹èû>–eQ^^HÃ0Èf³”——cÉd2Ê„ˆÅb†eYÑma­§×åA%%%½ú&oll¤®®Ž‡z¨×ÖYh̘1Üpà ]F<ˆœhÂ:çGãõán&NœÈüùóûúPEúÜüùóill¤±±±¯w¥ ]ˆeeeÌŸ?ÿ¨ ¼î¶`ìØ±º&ª««NØïïÿû£s r"Ó÷}?QŸ¡ú åèVYYÓé4Édß÷©¬¬$N‹ÅÈf³Qp2ljÅbQd!˲:, Á÷ƒÞ¸&8äÀco^œ7662jÔ(îºë®·×ÔÔ0jÔ¨oúæææ.éÔÝ¥W‹È±E퀈€Ú ì¯-Aª9~éš@D@mˆ¨ñ}ŸÚÚZ|ßïPf5‹á8¹\Ó4£ß…:”C 9y"Ò{Ôˆ¨-‘ÀþÚµ"Ç?]ˆ¨-µ"áÜŽ ”——“L&±,‹\.‡mÛ¸®‹mÛ455u(¥Ú—zxlmm%›ÍRWWGkkk‡ûŠŠŠ¨ªª"STT´Ïõ”””PRRÒåöÎ̪ª*êêê¸îºë(**bÞ¼yqÝu×õõy‘R; " ¶@DÒ¨9¾éš@D@mˆ¨W8—c6›¥¾¾Ó4±, ß÷I¥RQÖ£išGMÐzxlmmåæ›o¦¹¹9u[[[illdÞ¼y466òÃþp¿ÁÇQ]]ÍÍ7ß̬Y³(**¢¥¥…êêê^Y·ˆÔˆ¨-µ"P[ " ¶@DÔȱ%›ÍÇ£ÿ]×Å0Œ¨TjXB‚`cx{€H&“Äb±¨ëÑä555´´´0þün˪Μ9“™3g2wî\jjj¸ûî»jý¯¼òJ—ÛŠŠŠx衇¢‰-§OŸ®†Cä8¦v@D@mˆ:·jDN<º&P[ "jäØçyŽã`Û6ضM}}=žçQQQACCC4GcwÙŒét€†††ïO.—#‹õÚñRà±¥¥…ºº:æÌ™³Ï¹g̘AUUóæÍëÕÑ3¤ˆŸÔˆ¨-µ"P[ " ¶@DÔȱ!Ìp MMMø¾O6›Å²,¢û·p»½xì(jii‚ºÉû.³xñâ#qŽDDDDDDDDDDDDDŽJ¦iây!KKK)//'•JQYY‰ëºGl_ljö¥·Rà1LWînR×ÎÂeÂLjˆˆˆˆˆˆˆˆˆˆˆˆœh<ÏëX4M“††êëëY¶lY4wã‘âºîÑx Ó•ÃÌÇ} —QгˆˆˆˆˆˆˆˆˆˆˆˆœÈ,ËÂ0 \×%›ÍF¥N à cšæ^›Ífx;a6¥ïûû\‚ÌG€7öøø)ð8}útêêêö»l¸Lø‘AÌår8ŽƒeY¸®K"‘ ›Íð|Žác ag…·{žGEE¾ï“Édº,›J¥¢Ç„AÐT*Åܹs{|¼‡x,**¢ªªŠyóæ±`Á‚½.·`ÁæÍ›GUUEEE=ÞY‘cEyy9±X¬ÃÜŽayUÃ0X»ví~×áû>•••ÝÎéû~hÈår˜¦I}}}—Àc˜e*ãñ8™L†l6Ë+¯¼Â;ï¼Ó£ãx¨¬®®fñâÅÌ;—™3g2cÆŒh>Ç––Y°`eeeTWW÷Ú$""""""""""""r4J$X–…eY˜¦ISS–eEÈx<ó;š¦É‚ ¸é¦›0M3Êh4M“t:eYQð0™Lv;'cX‚5üí8¶mGÙ”®ëbY¾ï“J¥ð}?ZÆ0 |ß§¾¾ž;3^x¡GÇÈÇ¢¢"~øÃ’Íf©««ë’ùXTTÄœ9sˆÇãÊv‘ãN&“Á÷}’É$†aD·‡F€úúúÄmÛ|å+_!›ÍÇÉf³Ô×דÍfÉårõõõø¾ßežÇT*e8†%TÒé4@p¨¨¨À4ÍG˲ˆÅbÄb1y䑾 á555L:õpoFDDDDDDDDDDDD¤Wyž×¡„)ÙŠa–ãÿþïÿòÚk¯Á¼®ë’H$Èf³$ *++£9C¹\ß÷£ `:fÙ²eQÒ0 ’É$‰D¢CÉU‚‹¦iFûPd, "†ÂeàhxtÍÂì ½–ñ(""""""""""""r, ³÷–™˜ÉdÈår$“I2™ Žã°víZúõëÀ¥—^ÊÂ… `¾Å°jSSÙl×u£Ç‡r¹±XŒx<ŽaQ °P:Æó¼¨ÌjÈ4MÒé4¾ï“J¥öºß…ˇë+¼­ó|“½EG9!9Ž•=- ÎAûüEEE|ö³Ÿå‘GaâĉLš4‰¿ÿýïÜqÇ´µµ‘Édp]—X,Ãaqq1®ëbYžç‘ËåhjjÚoð/,¡ÚÃ0¢Ò¬ûbÛv4—#°]›w}×a9Ÿ <ŠˆˆˆˆˆˆˆˆˆˆˆÈ Éó<,Ë"“ÉL&;”+M¥RL›6)S¦PWWÇ»ßýî(˜–`õ}Ó4I¥R$“É.ÁË0c1,¯–==\‡Ý‰”’0»xöaÙÖaŸãQDDDDDDDDDDDDäh–Y5M“\.‡ã8d2²Ù,>ø +W®ä›ßü&¿ùÍoðÿùÏãy†aPUUÅwÜÁW\A"‘`ݺuѶc±Xß–Ií©¤ ÍLJ¹I¸Ï²c1Èg}öÔ!ÍñØÜÜÌìÙ³innîëS$""""""""""""Ç9×uñ<×u‰Ç㸮Kee%¾ïGÇB¦i’Ëå¢ù?÷¹ÏAyÕ×^{aƱlÙ2ž{î9’É$Ùl–•+WFïóÒ¨½mµ ³ÓAñbÀÙ1(/ÏcàÆ ikëÑ&)ð¸aÃÙ°aC‡Û§NJMMM_Ÿ69ŽTVV’J¥°, Û¶Éårär9²Ùl·Ë‡ó6&“If̘Ák¯½†ïûX–ÅèÑ£™0a†aàyžçaYµµµX–+ÀäqãI6䃴¦ 6°Öþ6MJ¿þuÞóØc=ÚÄ!EDDDDDDDDDDDDE*•¢¼¼œL&ó6v'¼=ÌvÌårضmÛÑ}aа³0@iÛ6þð‡:t(÷ÝwŽãðÖ[o1zôh kf£ëºÖqÜYmASØvxüR,(µ ¬üøÇùë{ßÛ£Õ+ð(""""""""""""GD*•"›ÍbF¹G›QàQDDDDDDDDDDDD;ß÷Éf³Ô××cYžçá8¹\.Ê~Ìd2ø¾OeeeÌf³Äb1jkk£ìÄt:aA´ðw(—Ë‘J¥¢Àf2™ŒÊ¨®\¹’úúú(k2NwÈxŒÇã}}šË‚ª†îïsnUû¢À£ˆˆˆˆˆˆˆˆˆˆˆˆ6aFa.—‹²MÓÄ÷}2™ Éd×u£ Äòòò((X__ϲeˈÇã]²ÀaX5Ìš ˲& 2™ ¥¥¥˜¦I2™ä¿ø±X,*ÚJ¥úúô9&йzlsÍôÎ&öõ1ŠˆˆˆˆˆˆˆˆˆˆˆÈñ) ì¥Ói2™L<4M×uñ}Ÿd2‰a¤R),ËÂuÝè¶pÙît¾=‘HP__ëº444ày©TŠx<ŽeY]2#mÛ&N÷õ):rLÀèt[,{9°°ç›èQàqöìÙ]n›7oóæÍërû+¯¼rØÎ“ˆˆˆˆˆˆˆˆˆˆˆˆ]ªÉd’l6(㈲=Ï#‹áºî•< aÙVÏóð}Ó4£Ÿ¦¦¦}®ã¸Ó±P.¦ N>ݱó![€'ÿñdÒ³MR౤¤„9sæôõi‘£T.—ÀuÝ(˜Ø9‹±0k±¶¶ Ãœ‹ûcÛv´ÎÚÚZr¹ÜÑLô<ðý`ÎÅ#¡¸ ’IºÖY-`ÈWFÀù=ÛÜ!«««{õ¸[[[©©©áñǧµµ5ÚÆÌ™3;,WSSC]]­­­Ìœ9“êêjJJJzu_D¤o¨P[ "i ÔˆßtM " ¶@DÔë|ß'ãº.Ð>cÈ0Œ.·¨0˜.³ÙlTªõ@²%ûŒãÙ‡GŠeÛÜ_0׆?èyà±ÿ‘;²}›;w.?þ8÷ÜsóçÏgæÌ™Ì;— DË„ Guu5óçϧ¥¥…¹sçöõ®‹H/Q; " ¶@Dûk ÔˆÿtM " ¶@DÔë\×Å0Œ(HØyŽE˲ö:ãþär9r¹”——ÐÔÔDSSÓ!3ÐI ~Ž”ÚÚ øhš%øéNÞüØ› iëY­ÕÍñPWWǨQ£˜9s&uuuÞì…æÏŸ¿×u´¶¶ÒØØÈ}÷ÝR˜1c<þøãÑm , ªªŠªª*î»ï>lÛfÁ‚]F7ˆÈ±E퀈€Ú H[ v@äø¦kµ"¢vàXäû~‡àb˜ñ˜Éd€®%T4ã1›Ív(©Î Y__O"‘À4M²Ù ¢vT!È><’¥`MêëhÑÒ¯—â]íõhs‡œñØÚÚʬY³¸ë®»X¼x1---466RVVFQQlذa¿óA¶´´0cÆ ÊÊÊ:Ü>}útZ[[hnnŽ– •””PVVm_DŽ]jDÔˆH`mÚ‘㟮 DÔˆˆÚcQXîÀó‚V˜ÑØ9Û1¼ooÂT*…çy8ŽC*•¢´´”ââbÇÁ÷}<ÏÃ0 êëë£9hnGÇüÜ“Gœç?‡»Ôªã@> 8àím>{3cßÛ£MrÆãwÞIKKK‡‘¡pþÇææfn¾ùæ¨Ø›²²².‘­­­<þøãÑ… 6th<FEsssN‚ˆô=µ"j D$°¿¶@í€ÈñO×"j DDíÀ±(›Íây–eaFl ÿïÌ0Œ½–ZÍårX–…ã8455EYކaàyÉd2ZÖ4M<Ï;°²­™LPzôHfJ&ápÏAcg.°„з®àÙ—žå.9äMRÆcKK , ï3M¹¬¬Œêêjî¼ó΃Zÿ‚ ˜5k%%%½2èÚµk©©©¡¦¦¦Çë9–ÕÕÕ1{ölV¬XÑ×»²_½Ý¬X±‚Ù³gSWW×ׇ'Ò§fÏžMMM k×®íë]Ù¯ÃuM0{öì¾>4‘>ÕÜÜÌìÙ³yì±ÇúzWHo·kÖ¬‰ÚB‘Yø™¸fÍš¾Þ•ý:ß{ì1fÏž­I9áéû¾ˆ¨ÏP}†yžG6›%“ÉPYYÙá¾0ø×Ýc\×Åó<âñ8¹\. @ÂÞŒ…ÁÃÎëK§ÓX–…çyø¾eYär92™L4¿cÈ0Œ®ÙŽž¾üÎLlè8`ÛPQqdçZ„ ó0>¼ÛÈfƒcÌŸ[Ç ~R)èç€;18-ÕÔÔðþon~³G›?¤ŒÇ––€hDÁ¾\wÝuÜu×]466vqÐÝzÃeçÌ™C<§¨¨¨Ççx̘1Üpà ûݾÈñ.¬s~4_P®v`âĉûœoVäD1þ|illìë]Ù+]ˆ^á¨á£=ðv¸Ú‚±cÇêš@„öjE'ê÷ƒ÷¿ÿýÑ99‘éû¾ˆ¨ÏP}†år¹¨\j¡l6K.—£¡¡Çqp‡t:*c±¶m“Éd¢R¨d$v—ñ¸¯}p‡†††h{@4Ïcˆ,T[[Ûq%‰Da ƒ‹ñx”3Œ ð˜JAÉ£}NȃáºÁq×Ö‚iâºA|5<äú¡ò.H»ðЫ««{åšà2Ãv~cWUUuyƒ†Ëìoass3³fÍ¢¨¨Çq¨®®î¶áèn=ë;‹È±I퀈€Ú H[ v@äø¦kµ"¢v /är9Òé4Ë–-ˆ2S©T4ßbhÌf³ø¾ëº$“IÒé4¦iFÙ…ó;î¯ j¸ Œõõõ]–1 ƒD"AEEE—ìË.Ít:<65Áž=ÁmŽÓ^æÔ4|Æ#ÁÔ‹ÙϾtxVnYÐЀkÅ£Ckj‚uë ¾b›!vV-/‡ÊÊŽSAö†C <†£€ÂÌÇPIII—Bá2û{ƒÏ;—ë®»Žûî»’’’½n³ód°Ý./"ǵ"‡G8‘÷±BmˆÀ¾Ûµ"']ˆ¨-µGZX25‹aš&–eáº.©T ˲H&“d³YR©®ëbY™LÇq°m;z ÝAÆã¾aP3̶¬¨¨Àqœ.Ë…™“Ë–-k__*Õ^RµeÁ²eÓúêëÛKšfûc|¿k9Öp½á~d³A6aA‰×ý Ëž¦RdÏù6©›–cÛýö–(è=/X}iiû&‰m“H»ß¥š¬É*hh~ ·ß[©ÔêôéÓ öóþÊ’„u‘÷õoll¤¥¥…3ftIá5jT´¬ªª¢®®Žë®»Ž¢¢"æÍ›GQQ×]w]ïž9âÔˆôް Eai‰L&ÓµÔÄQJmˆÀµjDŽoº&P[ "júB"‘ˆˆ@4¯bXbÕ¶mÒé4®ëâ8–eQQQÃǹ®Û!ðhí¥¤©çyär9âñ8MMM”——S[[ÛuÎF‚¬ÆpÛñ°tj&=/4z^P[t%T ï/-mŸø0Öé8ÁoË æKL$‚û*+ƒÿd®ÆT jkÉþ÷kï öC+°? öïÃoù4†¬®¶¶ý œÎƒâ8Áz‚lƧÑÃò¥Wm;Ø~o:¤ÀcQQsæÌaÞ¼y”””ìu®Çºº:æÍ›GUUÕ~Œ\èlÆŒQùÖêêjn¾ùæ(­º¥¥e¯iÕ"rlQ; ÒsŽãH$ð}? 4†µöj D¬-P; r|Ó5ˆ€ÚQ;p$¹®Kee%¾ïÓÔÔÝnš&©TŠd2Ù%°ín"d3»[¦´´4 .644Dˇ%^÷ƶí èüDí'FÁë&ðèûA1~'“± *çyA@Ñ0‚@a<Ü®7ÖY[üngÿ'Ç·0¶M'³Ö"ýå6â_™@j÷-¸³§cýp;žw™Lû¡¤R`ìZ Œ9ð'0 Ú6Ž¬Ë²‚2«v5˜ùŸè|§`?•pØ!âñ8ÍÍÍÜu×],X°€²²²(¥9œ|²¹¹™²²²ýfEVWWЄîEEE<ôÐCQc3}út5"Ç µ"=–¯ÈårQ }Çqð<¯CMý£™Úk ÔˆßtM " ¶@DÔI¹\Ó4©¯¯ï0Wb˜á˜L&÷úØx<ŽÛ©^gXuoþö·åضmÛd2™.ó5îKt 6 oó¼Ni~@*Eå÷fá´^qº0Öè&^,çAnóÙÄ¿·”ÜóqjãDëõ¬X{`®»>¶\.ˆlÆb`AÕÖ{‡k&qªÏÀc8ñ‚øyýO·“ºý)ÜUWQ_RTÕ•âbìk¾Ž÷›føÓâöz¨áNû~ð“N;ŸHé‘® Ë–‘ÍvÌ–Ü_Ògá®ïã)>(‡x,**bþüùÌ›7ºº:™7o^tII sæÌ9 Fá`užGRDNOåB›äÝ2m›ôK °jqâëpO›KÜú~ÇÂvÝöº¬á±Ú69׌ªÁLѲ,ó@rà14gÎæÌ™CKK ---@tÔ¤­"""‡ïûTTTÐÐЕÂH§Ó8ŽsÓ4£,Èd2‰ã8<üðÃG‡‰ˆˆˆˆˆˆˆÈ Ç÷}R©¾ïw;§âê8,\Wçj\™L†±cç³|ùYLšôÙl–ô~æKìP Ô÷ƒà[wÁÊl6ˆ¢Ù6afEÄfìÄÂ%ž*¦²2(AšËAŰªj¡\.ˆmæWE.·Ÿjhö«´ §–tÓ•æy4|eÿç/:]±¶n†®sHÆbäˆ3ó‘ÐdÿÚ›¨¼÷¬ü®44Çt0âñ ~™HÀ“OžÇ-·4Ü :éߣG())aÆŒ̘1CAG‘^S©T”¹˜J¥(..&“ÉDÇ\.Mú^ä¹®‹ëºø¾3™ •••TVVrã72yòä¾>DéC¹\Çqº”XíMŽãDóG:ŽCCC§Ÿ~#“&Ý‚çy444ɱ´òr¨¬ ažÜ–Í·ç»Ç‚H¢ï·×-CSž< ¾j;,‹X,ˆç…ñÂd²kÐÚ§~´íàïúúN x^d,,kLâ »¡}ŠÉC8§–Õ}Æ¢çç&±â‹ø7ÝJ*kRü¾ €à<…AÒ‚):»jì®ëM$‚ß7ä™gÎëÑóÝãŒGé=…£¿*++I§Ód22™ ±X,Ê`Ìd2Äãqlj.ØÂ cøÛq,˶m¢àcSSÛ¶m‹æ=‘çyär9b±XP¾ô0Èf³8ŽÃºuë(--åwFñÝïþ,Š×ýîw³xñÅ7yùe‹d2žÅbÁt†áoÏ qÙ,¤cÁ|†Þ¢õ˜æ¨î7jš¸ù2ª’"ó}naPo_I–§,/² £ÓdšÁOy9,[Ö¾`2‰—í>&z0**`ÏžŽ·e2Áñä~W„óì˜fp á\•¤¨§CðѲ‚C0Møå/—°|ù À5‡¼ï <Šˆˆô!×u;d)VTTP__iš8ŽC"‘À¶mb±‰D‚úüðªÊÊJâñ8ét:Z¦óz È2!ÃlÈð·‚Ž""""""""'®l6K"‘ ¶»”¿^bšfÔoÇyýõ+WŽŽÊ Nž| ®kbÛᔉžMEïÃ|y"ÅÏÇ4-2%Ûñ.Ô1ØI·•X÷SÎu_,«cr#lÜóH$‚ûjkÛ÷¹K†äAƒˆÙlTôýàoÛn†VTÙƒžIÉïz“a´oó´Ó¶²|ù¡ï;ôb©U9ºyQºˆM***¨¬¬Äó<***0 ƒD"A6›Ú“ñxœeË–‹Å¢Qh–eaFŒ …saÆcÈ0 Íë("""""""r‚s]—D"A:&™LFÕ·zƒçyø¾M”H$¢þ¨d2ICÃh|?È:ô}زåfÍú]—r§a—V½ÅšÜŠñ燩½ö!\Ì©ƒ°,¢àe÷ÇX0'd¨Çiš]·ç{#•o~“\.ÜårA¤ïïge.à T^þo¿}{‰D0_ciix 38-+(§zHSr6Ö!<î (ð(r‚ƒ"²žç‘ÉdûvrùY©=Ï£¼¼Ã0hjjÂ0 2™ É|݇p2î‹À†††½®×0 '‰ï¯ëѤà""""""""rü Ë«&“IÒ‘x ¹-åååd³Y***p'êß‚`ÞÆd²=þgÛpÞy#¸õÖí1AÏ "xÁ¶ìšƒôÁ¦&â fQ[”<ÅÚƒ}ŽÓ5Øb`n/L3صT*øq](¿ó:ü¢‰44ÙŽ¶”,Ýoi– 貎9‚ $Á!/[$i¦Óí¥P ÷ç¦äÌ9#•Z9A¸ûþ!"d2™.F‡Êu]LÓìvrnÇqˆÅbÄãq***H&“†ACC©TŠd2‰çy²„ç˶ Ç 8‡­N¿ˆˆˆˆˆˆˆˆ[r¹Ü~û½ÿùÝlØ`Q_Ÿ¤²²2¿Á¼‹X–•BÝ[F¢±š ®ëvˆ†Á!?âé§×1iRŠ/Ä÷ÇÑÐÐÉ–îÕšý""""""""rìÈd2d³Yî¸c Žcɵl6ðårÁÿáüˆaYÔ\.ø}à «¹ï¾q¤ÓðÐC­¼þú÷9ë¬bžÞ&‘H°¬›hŸç}eõõí¥OÍñmØ­¿ËÂ*¬»ÚÔD7MßÛË4‘ÃÆ²‚ ’ÊÊöARÝq]7ÊöååŽãPYYÉOúÓ¾~ªDDDDDDDD¤—y{™ˆÑó<2™ Éd=?úÑ´hà|Xµ«0á0‘óÇbA¦¢iA½mÛîgÖ¬{ùË_¶óì³E|ìccùÞ÷>L*µˆSOýJK»n×q‚¤€ÂùÍþËq'ßÜQ8èÞ²‚¤ibÛDY{“Lö0ó°œ à˜!ö%ò?‡¹) Yû’&:æò?åôNä˜I"G‰0øÎå ÃèPN5™LbY†a`Y¾ïGLa`1ÌÌŠÇãx^h·ðâ‹/öõáŠ6aI…d2¸H‚ð¥ã<‡®ëFƒ©T Ã0¢ô@ô>«¬¬Ä¶í¨ôj:޲#ÃÒО±¸jU¯¿¾ˆßÿþø~ŠË.{‚\¦M›†çý–D¢ ÃMSSS·ûfB†ïï°k8Ð ‘HP__•a 3&Óé4™Lp±–n…à<ûl5S§^˳ÏBCC¤¬®®æ®»îêë§KDDDDDDDDz‰ïûTTTÐÔÔÔ¡Š–ã8d2,+N,f“ÍÆÚÚö¬Â° :ì[ o·mxä‘-XÖ£|úÓW‘ÉdxñÅw3tè¾óOpï½³°mxæ™ Ã1¬æ8Áú:ú²þÏ™˜“&î÷xŒýdøå ™<‡ ÀXKÇLÂ8PIäkâð•$­öÀrñü@Šö ¤Í¡s¶#(ð(Ò§Âà…ïûd2 à¡¡æ…K§ÓQiGÇq0M3 L† ?@,ËŠjg§ Zݰ¼j6›Å0 Þ÷¾÷õõ¡‹ì—ëA´ð÷ò¼à¢$ .j øÑžâÑG+Y·n]@ô‘Èog|Æ÷¾Þ˜¨ªyÎt6 ûpeè™t Þ™ÙˆY‚àd– ð×›åW5k1ìîO.“Ñ8 ͬë0QàQä0ñ}¿Ë¨’0È‘Íf£ a.—Ã4Mb±¹\ŽŠŠŠ(‹±° c,v`­[X^5dÛ6™LÓ4ñ<Û¶9rd_Ÿ‘ý G]…¿Ô3Ï<Ãe—]Gé4\zé|ßç‡?|˜ßüf<Ï?ŸÞŸ™L¦Cæ`./³Y>ütÆ{Û.¤Âà`˜f$‡™“±XšpUß÷ñ}Ÿï|gË—?Èg?›bîÜ­Ì›WÉÇ>ö6‹½ŸíÛcÜy狼üò=œvZµµµX–E6 +WÚ8NÇ2á>ž£ÂÚõ±X×À£aåñ]7XÞuÃÒ«øÔ§¶õõÓ,""""""""‡Àu]2™ ¶mÇI$8ŽUÍŠÅbd³Yî¿?Ë7þ”ù3*§Ú¹ɲÚKšVV}IaŸÔ~ô ,«†††<ÏÃ4ML³ãôF¦ô§…o³ËVaÞÿu¬iOA KuaYûÏf ×qxNÞ>î3‚z~~¹A€²·²{ZÆ5ߟ àÑ1[ó(¡À£H/ ç€ ƒˆ‰D˲¢ŒÃ0ÐÇÉårQÆT˜–FöšÑ´?v§! á6ÃÀ£išlß¾½¯O•œ:Å–çµ® '²Þ—0+ø/YÃe—ïG˲øå/±víW)*ú,÷ܳÏ ¯ª\FŒø ›6Míð~sœàÂgÙ2xýõq˜æh\7œDÛâã‘÷½ïµ(c9EfÏ?ÿ¯¼r¥¥×FÌÏ}î|<Ï£¡¡×uù¯ÿz•o¼/?A¶mŸ‹aÔ3~üJ>ÿùeTVç­¶6¨¥NäËuÌhô¼`äX¾ì=ÁDÝG‚™f{ÉŒL&ø=yòY³æ}ý2‘ƒäyضM*•ŠÅ755EÉ\.‡ç™ ¶_ÿz0@0ìĶm{€õõËEDDDDDDDDPX´,‹úúz2™ ©T*ꋆ `Çy×»¾Éw¿;8z¬iýtFÐçT[ô-¥R),Ë"‘H°lÙ2 cX· …%Zq]p]Œx<ʘŒºÃö7!cŠ Ôi† `VìËa <šùŸ•&˜[ÑJiψ }# ^öæ±Ôdfzù}ôÎgAÉØX~9—Ÿ_²úÞÕ‹û|ß'•J‘H$¨¨¨ ¢¢‚ÒÒRúõëGqq1ŽãPQQA.—£©©)e’ËåˆÇãÄãñ(˜Îþf n…ë`&Ë9D™Lp³lY{MwÇiŸ¤ú@F{0|Ùf j88Žý‰DtÛ˜1×ò?ÿóŸÑ<Œ¾ïóîwŸÆ­·^²e |àÍŒQ”)S¸ï¾Ÿ0qâ÷¢uÞ|óg¹à‚{9ë¬åd³YJKK¹öÚŒ{ßùN#·Ýv)ýè| ŨQ£¸ãŽ \qÅ<ÏÄ÷aíÚ x×»ÆFs­†¥÷ö>ˆ†<2„uëFS[Û~á‹¥-L3¸ð«¯o/}‘L¶_ &í‡{ ð:Ö>ƒ…‹Kpë­·r饗öõKEDDDDDDDD뺔——ãû~”Ð’L&±m;ªª&¤Ói^~yx—Àmt.GõQþ·%KþÍ›_Œú­:L'´~ïtSîÁÁú°æ*{O$‚¬¼Pœÿ%Œ5óJÁøÓa<™Ó- ‚|A@/Ì4<˜ysùŸÞdç÷-<ßM„SzÛ*%8¿½½Ý½PÆ£È^xžMÆk¶mG¶ëºÄãñ(ð‹Å¨ÏI&“$ LÓÜg϶í¨4äaå8œWR‚mÛ†ÑõƒBä0ð¼ö Ú]w-fÑ¢R**†Fó v~Ùû~Ç€™ïÃyçí —­ïÜs×ð⋟eÚ´q¤RUUU@p¬­­Åó<2™YÀ÷0 ×u£’«\œ-YòÞxc.D»[^ü“ËuŒFÚ6–ibšCÀ°øø¶mG$ãZDDDDD,Íâ˜W£IDATDDDz&‘HDö’ûL#,ÍbþÂüñ\¨øa{  fyU“.ºˆÛ.½”¢«®âÿ÷‹¦ êÀu¡¢¢={ p]†9uÞ¥×À½NÔ- +/|Hçn*‹ hVxŸK„Læß“.öžvÏu¼ïÉï›O{¯_þ¾0CÒÈo³§ó;Šp›ËÎßa¦À£×\×Åó<\×Å4MR©†a˘‡5¯³Ù,Ùl–L&¥’ï«cÞ²,\×í¶AÞ_‡¾a]¹\ÐpÛv =l;¯3,;™HQ%ÛF©$“í‘"Ûæ}?ýi´M91x^ð²çÿƒ®1éýqœàeèûxtøÁª8ë¬à}Ld¼ÇlÛeÕª2Ö¯ßJ.—#—«çc{˜‡Î¥—~‡ .XËo~s9[·¾Ä A»Y¹r*o¿ý8Ë—ßD2™$Šeý˜GYÌc}ÚÚ${öz@”|ö‘ýýì³±m› >ýéöþì\.èàsœö~%Ó ú§b± ¯ªS?µY=+vê¾ÞçîHöbx˜PáОαAW^ì Nj’Þïþ ×WäóóÇ–d5òûy0ûÚÛ2ÁäP(ð(Ç4Ïó:d†ó1Z–…ïû8Ž3™ ñxœÚ}¤&…¸mÛ]ÒÓ»6Æ{mð]·=€NäC¾ «ޟͶc± €hÁíaºZ<Þ1­*• >|?4&“ÁöˆSx{,ÆàT çÀGÃÈ1Ïó‚ŸúúàåTQ\+làÑ0‚—U8˜)“ nÅöŒô}:t!N>7|­—––âyC‡~…Aƒ®ãòË?ÁÂ…ð›ß´qÖYçSTtÏ=÷>N9e"ýè Þ|óa~ö³q ö Ë–-Ã4MfÎ|žI“&ñÜs§qÆï ´ô—47OcÈóùêW_ÆòýïŸo¼‘?üáüüç?ï0 ]þÙëï Ï NV8 LJ¥‚eÂ÷|xîŸçuŒw0®¿¾\—tº¬ãý…5_݃)0/""""""""G›l6‹eYttÝ [(a4á8\÷D4=‘H`Û6Ùl6¨ öÒKítøçì.µ;Î÷ök‡w£»<Ûî0åc»03ð`»ål‚,ÈAðÎ$B&hŸgÑ%ùå»;mÁÃ9B¿ð|„åOsùãö~uÇå˜áy¾ïãºnÐÈår˜¦Ù!øÇñ}˲:d8…âî‹išø¾¿÷”òN,ËÂ4Í } Œ…õ, c¯‘Û¶ƒýñý .ܦXIX–lÿ¤è¼ïét×Ú™–{öÀ¸RH™A#k˜pc**°Öíé‹§Nú€i×U61Œöâf?Æbíñó0Ãç?¿›%KîaÈ6’Ét~ÝAàÿ…>J[ÛÇÁó<’ÉdôM&“Ü}w#óæMä†î`áBhm½‰ÖV°í8®Ä× ¸îºu€Ã'>1>*iüÜs¿Çóþ/K—ަ²rO>iP[›Î?&Á—¾ ð}Ÿ¹sçFm…ã8Q)ÖF\÷Ö„ÃÎ[í“\ú~û`‚P<œÈðq³-«c¹ŠîžÜpBl/ãÂu÷fIg9¢\×%›ÍvDßA*É$¹‡O¹¯™ìó—AwS˜Ç’ɉ:©TЦ¦¦öªxAÀ.N0÷ßãÀY6LLÃC¬ žÕïo/ƒ®¯½•Tí¶KÞ%è?T…§#I{3,#Σ˜Ë_®àqá~öÅ D}íx„(ð(G­T*ÍÁèº.~¾å2M“X,†ïûÔÖÖp0a¿s™yÿ4t(YÚçpŒ2 ‡e4ò¶móÍ“Nj¯oÝya úÁîS– 1\d­ ¡ŒsàÒgó§°¡Ýœ†+“ÁÈ!Ìó'Çž° owŠÇƒ©ÿ‰p~Ehjj&&“ÝV²m˜<¹•l¶ˆt:|ŒÏ÷¾÷;þò—5¬X1€ššV>ð!<ü°Á AeÇŽg=z4ÅÅíeM Ý~ûõlÙëÖŲ`̘çY³æ\’É ð<±ØD èßÅÅÕ¼ÿýó¹ñƘ?ÿãÜ}w¶ ɤatÌ\L&“†]@]~ùåxž·÷aa€°ðÄe³í™‚†ëÖu|Lqqð;¼šJ&;¾ÏörE•·ŸvADDDDDDDDNlÙlÇqp‡X,F,*‘ÙvÐçgÛà?ó þù"µò‡ØÅoÒð€}ëd\×Å0Œh²X,õ›E<‚>h‹ p/HŽñhL¦ú”Ã`žYð»ÀAÍòerðÙŽ¢»PAXÖ#x&Ãv¥¥Ï8Že0zžG.—ëp¿a$“I|ß'‹x¶RçT.ßo/= Á0 @Xƒ¤Ã¹ýüºÂŒÃ`§ºl®¼´† ÖÞï4ÚFþw8Ñ­I< ÕÎß×¹‘u ó0i4ˆ…u²ÃÉh;ï’¤¬`BÛÂD­¬|HØ0éI‡ùÙ•¾ÖÝÛ _åÏ î ú·^xÑ’ËÁSO=ÅOzŽSŽë ô?$“%$)Î8c5ãÇçØ¾}C‡þ’E‹¾ â—¿ü7Ý´•)SNႠ쎿Áë×ð¶qZ–ðéOà¶Û.`„—¨¬œÆ!ßdÉo$/»œô w˜ð ªðÖßâ¶ÛnãÓã½õ¿ VYØ.˜YÖ{pª çúð¨Ëª«ËˆæËx޼W>Rkóuh‡šp~ îI·_dí2aD >U ßÊïS´Oüì3êa0Ä€[íï3 ¸ïšíïËÁßnþØM:Žæ ßÿ©üri‚šï]ëÂ;ùÇ[´·!¡8ííC_ŒÖ‘ó}Èf=R)Ÿªªkðýú¨‹:› Š_e2ÁrMMP¹â±öü•eßû=Äã8ŽC.÷<©TŠx¦†üraÿXe§eêiï§Šç—Ý[¿u¡n惀Ⱥuùz’À-)ØæÁ 6,Zh•aÍ“†eqœà¾@º= +ƒ›É·Møío»tl m‹öQ"ávÉÿŸ%(4Üæå·Wšl}þqሠŸö”ð¦üúÌ‚Çw×hlj·=q[_½¤PøA¼ŸYÿupÿØÅ7&éXî´ÞÚÛÁ¸‘ V ¦Éðµ‘t·Oúúü×ùPæt^çéþãùëŽ+˜h¬åž÷0mÑ4.ºú|**,<Ïã›o~“ÿ7íjÎø$–QÅg§?Èïv§™vÿ4~7Êg×ë»xªítâÉ8+ÏYÉÆ)9í·§1xð`þùäfý[o캲má‚&¾ìÿLÿ—Î9ƒÔÖ×B1ìúæ.r”2ð¶ÿÆ~;ö‡ï†¤ÏÇÛÏ_m Ög`À 1.Ÿñ nŸ¶6 ºól ~eÂç\ÞÑsaà V¼—Â`_¾’21`‚Ý^‡=l²ÁyÆÈŸ_£à±íï×ÂçÚ/ ¯ûê;mÚ÷Ú™…Œü¾øùÇgioçríÏyáåˆWFôâ‹YDŽIåpÉØK`F_ˆˆˆˆˆärðÏÿ¼ƒ¶¶1˜¦Å½÷Ú|ï{A×·i²R)ÒI ’É ¹àâþ¤ÓïÂ7ÎÆÉåÈf³˜¦I:Þ2O÷ó2 úsý×ëhïßoÜ‚õ…}ÝaW8(?¼-žÿ»°ß«/hv¢ÃJGé5žçEsºQ6£ëº˜¦͇‹Å¨¯¯o/3êûA°Ïq‚`aÊ·ëõ! u.kè8AðѶƒÛ Gndõ\T XPGðkßËŽ‚¶mç³–?—àÿ8Á2A@Ф½aŸ[v(ØtŠuú»œöÀF˜ÚfG† °O0ém’ör©ÓÃh‰Ò|5÷×·¡àc¯ÊÐ>òÇ ={Í£ëk ,SÁ‡l,ÿ¸Â¬8rùù+*‚E›^ÿm`ðI°Wµà-sQ «Ô –·&ÓatÑ®[v1 rO^ö$¶ŠÏ4¦|ûï<;ø³Üýñû2d¼”×_éÇî rÝÏ®ƒ«á®wqÇ£w°cÄVÎ_‰ýùx<2íÛ|ðÂòÚŸ^ãïú|úÄì§žs*«ß³šµžåü—vÒ2ã/l=g+¿]}¯¼{ Æ¿ñ¹Ï~ÓJîçö“ëùáÊOqãâ9PỼ'?'éÀ¨ø;X [uü΄óç7$;Í{š ž—O_òi˜HðÞqâðÀZ‚RÆ™üriÚ ^5¼÷Jó¿“t­^T…ÁÇÝé7{ù:–@ßóñ}<¦»²Ë*ÂF™•a»Kó¯‘óç±úë‘ã\8!¬¾`üoÃ%ß¹„%³—ôõ^Š{¨ÕYx–Œ*,Çäíc=…*…ë:€Áe‡Ý‘E.""""‡,“ÓN[Åœ9£Ø¶í~âqt:×KÆý ú˜É}ߎÉ$¦ ¦™¢²ÒÁ¶mÇ¡¡!èû×}Õ?=Ðkå4«s…« û® û¢Ã¿s×Ö6íÓ™´& “v丣À£'ŸIXXÕ0Œ¨LjȲ¬(kÑ0 ¾9p‹O¿‰Ûø^0dã®j—8𺱠ÜÕðÇž1i¦ŸOjôÏÂûÜx/—ÀFð]p±éªBíÏâ˜f¼kúv Rk€ª4¾öéÛC”e˜Ý±f¨ø÷ o öZ0vA,ìtˆé|2å60~ Æû!ž£6¸ÏqÀû)ä*‚CJކt?:NhK0Ço8eœiUY!8ÎLr{ ~)x­ËÐ>a¯“X,<Æ0H•ϤôF[°L¥Ä`Âøn6¬'ƒç&=××/©ãK˜Í©Â?‹Ãû¬µp™ÂåðÃ8Löw@å“ABë2Àl‚ÒÊöéFÍçÀ ñ*Èüø­P[î àîÎïÖd'èo³l2N†l.‹×êñ‰ñŸà´§qÓÇÏçw›L¿x?øÆ:Ì9zQøÇÝÁ ‚?ÈËÌö—·óz¿×¹÷¢{ùêWŽiŽaèèU\6u ¿ZòC®x}_™;be”•—±¡ÿZîxóö4%/¸°Õ‚Ázÿ¸0Æu½ŽqãúaLø¥ñ"Ì;¾ã“ÝÏ‘^8AP9Cû„Ì]ç/ÍgùUµÃòáŠÂ,ä}]h…Ï•G÷%":?—Gƒî&ª6;ç ƒ^àÕ7_å®éë½9ü « ªƒ `ìM&¿/q:V/Ù{yŒmmm,ÿ¿Ë™ö£i´¶¶²âÚŒÞ3š·ž~‹1#°ôµ´Žiåé·ž&Qš a]eŸ,ãÊ;Fð¡;Ù¶û%šÇ aɺU$ý$u“긭õ6î8ù®yíxä „Á®0VøZ 8…×…_äCv§ut.õ Áë0|\8ª0£>D—Éÿ_K×¹PÂÏà0£Þ¤k9ð 8_šöë¡pìüc3ËWtZG²à1…ˇïk¿Óãh¯ÀAl§è=×a›— ·l?ûŽî.|~öýòûÏŸ¯ÂsfçW8°°2{2 …Ó1„ Â×BØžŸxÁ1‡ÏAŠàûF8¾S>""""GŒã‰¦ü®¬„ßü¦Áƒ¯çŠ+N&™LbÛÉ®ÊfƒÎÞ|£çyQ9ÕX,†eYø¾¿ï@cgYlžÅðºò`öK¥÷²Œw +’c‘'0ÏkïÛ÷}øíoW±jÕ*-ZÄ!m ¼ÏóX´¨‚;ÐÖúeF¸”‘lv÷ßÍÔ©/ðÕ÷¿‹úE•l|« gùYx/mÃJ&—ƒú8d3/ñŸŒç¶;Šð¿=•Ô³gá½µ» 4`ÐÀ%$F}oeÿ ‹ë¡ ý¬u!3üq%ds4˜SÁèÖ4ˆ]Þpÿå÷@­ ¹Íà¯ôOÀÊBƇäÙA#žú؃lì$ÊÁj‚ô»ƒs`m‚Ò“ æƒ;|'ˆ—š&¸O·¨‚… ± -††oÓþãP<š¾f26†7Í| 1?0%kÏdKgƒv¶²š~Vþó!áK ±i` ‡TiðüÅbÁýÙ,¤«ƒu§‡Cì›àæ‚©- ?Èr¹öÀ• °†yXB3Õéþ4í²Ë n;óÁnw˜×ô{wê\öm0 >³0[ÀZ/ýô%°¦Q_ìPa=vσ]S–òÊ+â´}€ØÄÚKïSQL"m¾ïG% /@nó}ÈÛ¶qÚk¯1ãúëYüÜS¼ÞÚJ}}=¾ïóÐC5ÔÆãð‰O0 ‚ê„ Qçãú›ÖsyõgàÿûrûÁg¶—{˜€] æ'.?°ç%–?ïaVqÓ^–ó –f$Øؼˆû.ÁÐÓ€FØ4u[ßÙÚ×»qìr^ƒá¨¿c€çŸa°·ÿ£fû •x<ø»ioù\.ømç5ÍöycÙ ±÷qh˯` Ä*ÁÛ ÞßÀ¾˜>¸ƒ72nÜ`¶oN: ï¶ÀWx–‡n»„=#÷°«ß.ü0nÂÞuÆffÛ˜mÜZµ‚»¾}6+× ଒ übü(RϦᛸ`ÒRv¿9‰ÅÛ³g÷úõïÇ®IKùôÀ]Ô¾q&­#Z¹gÐ3Üõwñêæ30Nò>d w¶ž<ÆCT­À•Û.ÂãxCÛx}ÄVZ¬àÚ¶KøÃö¡ü¼­Û?Éw¶Œíý†ðƒÝCh83Δ·ñâ ±ìùö¼{×;x;Ïå þÆ“\ʶÁÃû?Æ¿¶ý+&Ïs.£™Áü3³‹—™Çt~·ð4¾Â#ì~îqÎÚs*V>Rtn¿q|sÒÿãíœÇæ•›¸q(h\D9îßšÄÇ`Ùð_²ø¤¯òÕ‘ÅØ}!ß_w5±uwÑ8òê¾~yÛÂrøaV\ø^) ìVÄ0;-Ó9˜WØ ;Â2þä·‘î´ŽÎ%¸ 3ÝDwÙyággØÆ™þ a€Ò ½:@gõë2h¢Q°»`™ÎzÂlx8GráqÛ×]¡°@笿ÂN=teÓHÝ›e´gFv^G8ÐÁ'ø¬Hus<áÿáë¡°'< û–Q/Ï?/aI¬X~_ÃóëÜg)AÐ8¬‘ ýúgOþ10éŸ&!""""‡W"Ññ»õwþ™§žz“Núóæ}˜mÃ2ð• ”5´÷G:1¶þÓ?±ú«Ò¸šÏÿþó|¡ê ü¿–ÿÇ%O_ÂÐOŒ°ƒ*¼¾/üþ–8 ¯Ó°ã‡‹ªs·xÈx€ea‡M |Ü&(üÐô+Hÿ¢ë9ˆ/hÿÛyRƒ=¬ËÁxðƒ©|&¹\ÐáÖĶíŽUYb·€Ó ±_@æ‘àœ6„×uÀd2ÁyÅ‚ã°-àƒm†ìæ s²¢"X¦°”v,<7©|«¡¡½Ó7™„yO¯ÇøühþûK+¨«+áÇ?^E:ý»v]€»bÙÛ-.»ìI¾ò•),\ø}t.S§>Ãý?¿ŒMwðà©[pžø5%%%<ýô{7n%“'¿€çýŽÚÚ8·Ýöß,[öå¾~ ;ÂÒtaÙÛpdy(ü ïfÔO.×>}h*U0és%¸™öåÂ×P.¼>l¾ÿýÝŒùsJKï ²Š?é²Ù,¶mãº.W Æ–•+1÷MšÄ—…óâq à ¯Çô}Zo»•+WrJu5o¬_ÏŠçŸ'õ‹_Η$ýóŒLÙ¸‘u›7S¼~=6Pns9Ö××sÝG?Ê•ŽW^ À¸X,Èj¶m|ßþ6Í`Ç;¨ŠÁÄ &v ʎƧëy8 a‡gl?Ë…³{£þr(ÂÒÊá‡1ðèûíóÐ>è$ Úvp[, ƒa Ðq‚Ï™ââŽëMVAãËÛxêïƒy¯µ“±g½I]ݤËüøÇ ùÁ&PZºž… 7óüóÃéÿôYlØÝ€Q#Ûøö®ÂÙ`ð/ŸÌ{Oþ¾U´a+)¹”Ÿ®ÙÌXþÌë#+¹t÷)\󃧴³ˆAÛ±‹1Œ` Ûï]ÂR0™ó1ÿü[žà .ã_€qÀ8là7å÷ñ?|š%|ã3?çò×0dã`<9¶ðÆÒ·8}å4>¼§Ö?ÆIé·øÆŽ+ØÖÿ$öœô~v´”P{zš=,¥|k3–40xH¦î˜ÀÓÃ*ð·Ÿ·ÂáÑ—pÞæeLÝàò^ã›/62x{uÛÏ#×?À³ÚÅÎ7þƒ«È`8›wªmc°ÛàÔ –óäÂÓIžú*ßù ïÚókžÝó.*¹›3±yöÜÕ¼ýv —·¾ÆÆ!oðÐŽ«YºåÞ5öa®½u7z|å…ÒÓNâ[üß|é*ßú*· áÿÞ¼†“ÃoÏ{…ææs0Nú¼5ÃI&Ö“©}q+ö¬"¾™‚çLðû_ÌûÞ½Š_¼ÿ*^ùÕ¦ž3„Ü—ãÑk ‘­g}â ”õÁÛ踖í©tWÞ2 ¸…Ÿ[áçXçÁ/…— u÷YÖ°—¿÷f¥¾÷Æ:Èå÷·í½µ™æ^–ßײ’…|(2ÏMpÔºeåTÃ&PßqPG˜AiY+¢„í}8 Ä0ÀðÛgÕ‚ÛÜSÁÈ_~Yùmø~~±ü`‚éëÍÿìã@6ÿÙð0š( Ò¶Á?v½|Õ!œ(Ù_yûŠŠàz±¶úõ[OêÜ»±j?Z»–{îqˆÅbüÏGaÄ·ÿâ©`Ú°í¨2ÚÚï­Å{Ö£hb?ü0ŸúÔ§ø·[þiÛ§1mÄ48àÚ®°I8 0‘ÿ¿–öĉ0YXE¤—sÇššêêêhmmeæÌ™TWWSRRÒ7;ãÓþ†qÈØá—ɰãÐ ÙGIÁHçaˆ*ÿü­¾œ·Áy ìiÀÖV¦X˜ÜÖŸ??9š~»ú‘úþ*Û<Š[&&‰-›…Íz¾»øfðÎy*ãG¡qõoùÆÊ[±qhØñ\´ à-A墱4¼ÿpeé . wRwƒ³¸Šú»À\}et;>¤W« 7.hT‰àØ–-+ˆMíZØñbƒá‚ùÏþ0˜_èËèNíÛÿN}µ?7È ñxü±í ±¿á†—ðýqÑ”žçñ®w½‹Ûo?‰Oy~c$?ÿùRgu”¦îe=lÛfêÔžyæJ¶o¿ÏûX”ÖžÉd˜õ±¸í¶É¼|ÏÏ8ï¼b,«…Tª}ȹëº<óÌclÚôMxà*Š‹/¥¡¡ŠŠ êëëùÜçþ‹ÚÚ'€‰|üãO±zõKø¾‡iz̟ߟ/~q K—þ—_ž¦¹y?¼’Dâ?ø×ã8>x%¾yEEE<ýô’èøÇÀ4M¾úÕY|õ«Á1<Çãam 8ˆçíë.8ÖM'œë¯ûø «1¶îaÙ²ñdò<Éd{“i‚ç9¼ùæfÆŒÙÅ/~ñ2™L+E˜|¡ô—\sñÅœvôðÃ|ò7¿!™L’ÍfI&“Ì©¯gdÿþ š:•ç à²~”ïíÚ…mÛär9¶®ZÅ„3ÏdäÛoséüù´­\Ék·Ü‚ad2²Ù,/Ý}7cÇŽeÓ A¬Ú¸‘ñãÇÓdÛQ€è9/fSæÿéº@œî/^Â̈ž:Ð@¥‚‹Ç­#rMð7îô nB£´ MÀ5>üÂÇÜûkq/å=½{Á»$èö¼öŒ@Vƒq*ÓÛ³ãñ`°ä;µÏk8?Šà´[ùÛ¢ <¿j›7m¦ÿîþ »„§Ÿþ+W^ÏÀùÊU?ãÖK¶ðÙ—nfÀÆ+€é˜uàð..I××ãã#>Àe›>Jó Ë1bþ'Û¸xÊùâÂVÎüÝ®>i9›žÊ€cø[QÛ¶mciÛ˜W¼–ó×þ•o½Í‡G¼ŸY›ãÅ‘/p.ï®ç›ïþ&ÿúø>ï#?èȶ)u].J¥x(™ä?¯»Žâ¿þ•›‹Šhks»a3¹ëc|ó©ÕüÛ/þTêjêm›gÌÿ½ž|òw\öѲ~W?LóŠ $ôK2kíZð<†]ÆÐ%KØñØþëñŸRÜoŸú_¾d+o ¼ŠsÞz‹wvï&öáSy{Ä@`fð9ïy\¶é2^}µ˜ë/ºˆM›61âƒ`STáy¦LâÛýÓ~ÁО €;)ñÄmÖ1÷• rØÛ°\iÈ"øòfè…s7ÐþÙV_°üÞud; „A±Â`Yx;´·gaÀ,œ‚‚ÿãq¢ë Ûî:ˆ²C†4íËVêï…ûašíˇÂï Ä ú…ƒ3Ç™üw„d²½I¨¡¡ý¶d¾‚‰SPnÕ0 ¾¾}™e˺®£ðq…Û +‘„ûÚy;Ð~nl»c¶y: uù“Ár Á6\·=óÜó:ZI§Ûÿö}pW+ÛÅuÁ,ùSk_¾Äzì¨ê'èk^ÁïÎÙ6íYaf®:å8¢¶@DŽH;ðtáJàíà3µ  šç×p¹\p7mÚJNÙõ¿ìú÷¿ñå·ê6hoW\É-cîfì† ®PáÁÎŽ±ê¶¹ü¦í7˜¦Cee%õÉzœV‡xnÆŒ̘1£g;ÎÕf*…Ùa§b˜ •ua±‹7p=¬?ÿ‰Ì$௟¸˜Ä·ãí·{<ö°åÄfM"÷Ð iî'×ï$¼=ÅøX¸|äCá+×SÑÚ¡[‡rÖòÉvm9UÔ_ÄÄ¢‰l8kÓ_÷¸Þû"{úÁU#žåÁs¿ÂÐßü¦cpÀuqþT„ñÆd¬a´—d*œË¤ž½fy^ðeyÙ²îkÁy-ÈðêœYòÜü·à°d s¸v̵¼öÜkœ9çL2™ ñx<*Î7 c±©TŠt:M*•âÿ\û}¾ðo¥ÄÎ÷q6z$“.¹\ŽáÃOgÅŠ[3æK ð ~÷» ihh •JQ__Oee%µµµ\sM?ÞÿþÍœ|ò9çœñÑ–¶mãy–eq×]?Òœ{î=QZ<'—ËÇùЇ^Áó,~õ«¢ÀLx̦irÇ[inn£¡¡û¨j6ýi‰·ß~;7ß|3MMM”––ÒÐÐÐ!PXøš‹ÅbÑë¶ë1xæu”Kcc#TWW÷õ®’^¿&ðè8¹ùÙŰ£ Wü\67AÆ8Ao¶ã@e.¶`¢•Õó¾þðß¹M+ñZâüc,˦Céâ`•|¥?|¯/n;‰-Ʀ¿9Œ‹wôgû»_æáõ›ÔúŸßöWÆmÇO¶ü;_`#ø NþCú!nãó\Ä$&ñÒ°G1·y Þõ"a£õê¯2å©ó™K¯¤î]rÕUWqÿý÷óƒK.aâ½÷²}ʹüåÕ—¹¬øT¾´u2gÿÓÇXºt)îÆþð4WdÀEh^ÖÌeý(·<ûl4hæ[·ßÎ3>Èõ×_O˯ÍŽ~¶ñã£6Æq>;éf^<ëM,ËÂuÝhÒûÂ9(jŠ–ƒ8NõÖá]ýŸùÒ—öü:¹ôÚ5Aá~…%ˆÂrëÐ^R4œ£°p~à°ÝèÂÌeÈ—ùÏïG¬*,Éf6‡µÂ ¿ãñ|ÉþTð;î «­mð%“Áz;—U. Ä54tœ»Ü²‚í¸nð¸d2€e2×QL&;îkx|¶Ý¾íd>ûÙÕ 2„Ñ£GíÞüãr.¼p7§6”¥K×òƧ0dȆ]Åõׯä?8‹‹.ZÇ”)Yµj(7dÑ¢EL™2…÷¼g;Ï>»–§0~|«V öséÒ¥ þ2—_~+Wnáå—×0jÔ(úõ{=¿vô]dõê ÒÆèÑAM×âõë)^¿ž×&Mê2·Nñúõ ݺ•¡[ÛKœ7Ââ•+£ÿ'·¶2rçÎèÿ²´¨¨ý¥iY˜®Ë¨×^ãÕ‘#™²q#‹Š‹YTÒ~Ѻu\´n]~ÿV3zôhî^½:¨œ¯˜ñ©mÛ·eKûkp±¸í”Ûøç·ÿ¹g/ä>r¨mÁQ-”£½ºt,ß í%sÃë—pNV§Ó2I:ÎKZZp¿A0 ê`¾„óË*l;ùTÃLïÂlŠÎÁÐÂuužËÕØÇv<‚~ŠlÁmáÊl'ÜþÞöuoóèî­4]áy ·Y¸k/ë\.:T8è5 nƒNÛ±öò¸î„ËÎùÛÝñlgÑë‹øãò?½ï‰ýèó>CÉ–k¯Â pÉ¿þ `‡×ar@¡p¹p†/¼°‰W_}•)S¦ðꫯrÑEëX´¨˜M›1eÊ@6nÜÈÆÁ`ºU«†2eJðcã0ÎzôElÛ6¶¶6†J[Û[@‚3Î8ƒ+žïë—Ó!éÕ>ÃP>ÉønžÊº|ã\dÀ7ÖµÆyPù0ä^†Ë/mcêÖ¸dÅó|}ý×yñ¤?3dç'é¿ûb˜”„¯Ñç˜c;Qÿs.—#‹‘ÍfihhØkŸžÈáÔ×ÉÇTàѶíh¤@KK ¶msß}÷1sæÌ½>ý,ï}ï{¹ñÆ»Þ~¸…e‘Z|x5ÿé7Ò€[­ /nŸqð®Š7h(l>8¯m<¹oƒõ@-™Nµ4ÝÕ‹vröºÍÌåѲñ° V \ÅÅ#`ãˆKYX¾„þìÏ¢âEŒ«™µK—²ƒ\É•¬b¿4×cšf4÷šaQ£cÛv·Y_ûÚïùÆ7®)œs6êäëÜéמçDˆmncðõƒq' ®¥Ói***¢ ßõלի_Šãºn”MUUõ:uu“X¶Ì‹‚#ácÃízž‡ïûÑ>„ëíîwác càÑuƒyï~üãsõÕWS_¿‡?ÿùlÆ[ɽ÷áyÞáéÜìF8¹;agË¡»SWWGUUÕ/,µxÿûßÏc?{,ø"œÉKàç?Àm`•Ÿ¬ÃÀ«Lá,? û “ø`tT: ååíë´p9ø_XóÞ´¶^ËŽoså™ l_´ˆµcZùÉ…ѲEEE\xá…ìÙ³‡¯îÚźuë˜|íµ,\µŠË?ð>ðå/wx=C ;ŠÂlÇðýÃ÷×G}gÛ~ôÊ5Á½ÌÏÁkÜ_ ‡i(ÀbÀÇ­öŽ3 ªX>©Æ­ o§‰ÊùØ¥ƒyåÕüzÝ >qÚüÓ[ÐÔNjcøÉ[øÓ˜~|ãÕ[ùJÛWøcÙÄ79‡à‹âš¡kømù`É=|æ­Ïð·‹ÿƕϼ€í†ó’3Xµã4~õ©KÙ¹s'ýúõ㜷ÞbÕO~BUUuuuüËüù”ÌþWœŒC]]ïyÏ{hÚÓÄåm—³áð-ŸÝïÛçyÑçúªªx~Šλòʨí9Ÿ‘GBKK ---'\'ÒÁ¶Çrg[O® fÏžÍüïFkm{ƒ]hZ×lLåý:o¢ÒšfË“¸ú¼|¯½‡IüÇï&Û|y4 )¼îóýö¬ÀÂl·ÂÀ^(ÌL ¯'M~üã6Ö¬YäI“°,(+[È£N`äȼç=kX´¨˜‘#w2bÄFŽÜÉßÿþëשqãV²zõ¦ ]Bëò“ØuþN¶nÏÎZ¾¼Ã~üùÍ7Y5´=07¾­¿ó[·neÕСŒokãÑ X²ukÔ)rÕÒ¥ ÈwÖMš4 €ݾ·Þz+„s;öâ;tÿv|¢c_ywSì~¸¨ˆ³Ï>›gŸ}€çFf×®] 8mÛ¶ñ£-[øÓäÉœvÚilܸ‘K7nä¥K;¬ãsçÇ2tèP<Ïã‘¶6ÊׯîÿëÈ‘Ì>ýtN9åÆÏ /¼À’—^ê°Ž'/»Œpþùçó÷¿ÿ/lØÀ –ùBy9¿X»–+¯¼’'Ÿ|’ŽÇÀ¿ÿÑ£G³iÓ&6Ÿ}6wÆ!CذaëׯçÁüƒ­[·rê©§òÖ[o±ûÃæ__~™[n¹…üà|óì³üÔSl>œ·ÚÚ6l/\vMëÖ±~ýzž|òIžøèGyæÁ™5k=ôÌšEMk+äñÇ?зßQåPÛ‚#z-伈 \aɳ0ˆ‡Â`"´0³7_‡ -/´P²£¤=X–MÛGÖBØ™&¸OGñ`ý ÜÀ-`ÞÖ)w °¬Eà^Ÿ_~i>h02¿ž¯ƒù5 ¼Àø!ƒ ›­›SÁ±‡ {ƒµ¼¶à²Fž„øÈŽ6@|@û:Âeìƒ?sÁ|ìâ‚eòã­â› » ˜öRðÞoA™áÎÛYñÍjs40 Ü“ ¶1¸/w1XO‚eBÎÓïlð߆ô:ÈMÊÁZ«q9)؉ÉÀÒ¤§‘Ú¬ –OÑ´çnÄ–îÆc ® –1ZI‘„0ØéIAQ7Û9xÒ“:X õë 2œèv$0 bkòÛ¹(x.M¶ck—í,™û0Ÿøö'ÿ{â08Ô¶ Ç×Bá{·» µY°LAPÛßî«Á]V ÜùÀ«`^þËà5÷¹kÀ< ì[ ›‚;w2ókO𿟹˜¶-m 4AƒqÞåo³èùb^jÆ´’-Œ=c3O,<…ù-;wîäò«ÃÂ?U7ΙÜ̦wNåu§D»zFñ?8¹ìoüà·Áud2™"“騍\:ö üM&¯n>ƒ)ÃßÀáñ×5ïíø<”epš“Ñòk7LdÙÖ3£û'ð»ù«øqþ–~À&°€6†0–Òʵ¬dÓx pYÃͳ>¿Ü\†rE|ݼMùF`ÐÀAœ6jk?Ënÿà =÷ßi{±}Ú¡3OZǶQ/±só¼½¥„S‡µ0pø¼õË£eÈôó>Ë Ïÿ'»vîâœq?æMï –¸‰Í»O⌢WycØ û=œ<´?.ükŸ Ê—¸“;òÉ÷ý–'ž¿”¡Û†rÁÄ¥Ô¿y&ã· á­mC˜:|[ÏZÂŽ—ÏcäÀŒ›²˜g^>“vœÄYÅýÙ²y >÷9¾þF)çlÏã·Q7ò9N~ñâh_‡ †?ÔcÈ®ñŒÜ=’‹§mà©uƒ²f­­­ñs#ÿ¹e §­Ê»Çnå¥âm¬yc87Ø3†ïäEÿ$[»†õëÏ:´÷Cëñ÷ƒ°¯ÔžôáMî2ƒÿkGØäÂd æÙQ%ŽŠÉAò̓s¼Â>±í~,\V~“ÖKZ™ðï(z¶Ç ú¶3™ ¦i’Ëå¢þþp:£0‰àP}aÇC?æñÐÑ×ÉÇL]¥æææ.OXII eee,^¼xŸÇÊ•+Ùê¬Á¹·ëÍÿø3ìðàá&Ü­ ºÈÁ¿ã6¼ukqó_aKŠúqƯÇóߟƪS·òѹ¿æKÎMP¬×ÆáÌ'IÃÈ‘ìÜy¯MzƒmÛe؆ï²eËâhûå÷¿Ÿ¾ 6ŒÒÒR Ämmœwú›¬øë Οq>{Vïáš;¾Î¯ýkîºë.‰ñxŠ~ù/ça°Í4M2™ étšââb–-[Fq¿â(¸—L&ùÉO~Â'?gɨ¨x:jب¬¬dݺuÑ:2™L”ò{؆υ¼0ðyà WàûÓ£NÊð>Û¶0 ˜×_oÅ4MÖåGÞ†qîä>&skÈOªØù÷¾Fw„™^;vì µµ•¿üeO> “(ŒÉÉ쮽ƒý€ÞÜ• ó,¢'íÀÚµkÉNzoóFâÜ £FÁë7Ñò‘SùÃÖ³lþ:>ðž=|×jbã›'ñbí¹Lön»‹¥+.açÎpùåÏr/Q„Çã%%¼¹};ÓgΤiÁ&Nü9¯½ö§ö^þ¸æ/\yö•\tÑEcYŽãðÿýÿ©TŠ¡µµÜŸJQ{ûí¼–Íò¾3¨¯¯²÷özçf _óû{M7662cÆŒcúûPœ(ï‰B'ÒsÝÓk‚Ö…›È~ü§›!6΃Ûcø×ãž ›6mb㿳hüV­ʪ{Ö°fÍvV¯Æ…~Ÿ'žøøÀ}¸LúÚNù;bÅ?¾DæíÃÉ[6ŽäÏgOàÁ·ÿÀYgÅÛo¿Í•\Éìq³™6mÿña.i=…ãÆðØöí\ýGðë~uN}8蓲» ¼¹*ÿž;ïÝO~’I¶MìÞ{nš¬»ùf.ú|0ºõz‚Q±Ý 8 Û“+/ ê¨Ûûúà:µ´´Dï‹ɉÒþõôš€S|Üw]¡ ãdzdéZŒ% yôä \¿d%ÿ5y9­[óÒÊqL\º”‘ç>ÊâÅÁ{ëSŸz‡F>ÈÉ'o€2` k¾ÍòuËÙµk/ÿéÎZ[Ä…»ßaÒ®µ,4ˆ¦“Æ’L6bÛÅ8ŽC®¢kգЂŒA× î¿| íµ Æ*‡ Æ ''t  ÝQVÆoׯgÚ´i¼öÚküû¶m|rÕªèþ¿|2_\Ά 5j¯¼ò ¿Ý¶õë×3vìXÖ¬YÃÀ .àß_{©S§ËõëÇÿøýû÷çÂÝÁà¾nº çG?¢¾¾žŠŠ þã½ï…uëXsúé¬[·ŽââbN=š#Fpá…RWWǽ÷½<ñÄÌ;—ûî»L&ƒ•L’L&q]—ŠÒRýýï¬^½šqãÆñòË/óŸóçóÞ}(ú¾sÕð¥ÛnãŽ;îàÏþ3“'OæÖI“p]—ÚÚZÇ¡y9¹ºº(0wû—¿Œwÿý¤Ói²Ù,—N›Æžy€ñãÇÓÜÖÆGçÌá…üÀÇ|ä#¼øÕ¯ò?ßÿ>Ÿ~àhz…òƒ-MÓdÒ¤I8ßùŽÌÏ“Éd¨­­åÊü÷«\.Ç0Û&[0XÌó<®6Mö ðñ‰O0Ý0˜štêº.çY;fÏf²mcå?_¬L†%K–ôõÛúôJ[pr{äßÛ=¿äbŒ›nÇû!KÁ¬y·ú?¢el>ü¥Ëøñ˸i ç^µ†­¿ÿ#olêùŽs€KïžÉ#ÿ977œÄÍŸy™æÞdOÿÐo ìÙÉÔk6rê¤rfìÆÍüóðF¾ýÇa@…êcpÏ‚¸Ó ¦È¸ôÿ=AÛk£xÁ¹È_ïUÂ{ßûÕàúĽú¿úUÇ)5>vòøûøñ,^|=†áññs~Ìý ¿Òa™/˜5|Í«†ÛàêÒ&Nç5~´þ&Ê~ø"£nàÔKÿÎsÏ~˜ýÿÁûÞ÷{^ÿËÅðôë×]ŸÙÅé†ÃKÓÆ°ê‹ïfðàÅÌ0Þlù4ýû÷ç-»é׿?ÿ;âË,}¹†ÝKvsÊ)OpÎÛ#XÓv~º‡Ów­åú!óöKÿÊŽ;h˜üß”.¯ÀÀÇÇÀ_n°ºèw8#w²{Õ…lßþ2Ù¹ˆ±Ëós”.~ý똇xfÀ­ì\º“‡ŠûÇ`Ø2Ö·/sáº_0lج]»–_™â½ÁýÏmís8üfìXÖlÂ`ãËSp)ǃƒïŸd¡ùíü _`À"Ÿéø|"Ü×5Á¯;y‹QkÎã{Çž¶~º.¯Àe2>#(J”ÓZÃNïÖ/z’–ÖŽ¹ƒ®Ì3¿ÿ ﻾Ž?>:؈C0Ñ-ƒÿ—æ¡SøËús¹tÐF¦¿à'oÏé°ŽªämÔñ#ØÁ…uuL¢?«8€ cÃ3‹ùöOŸŠ‚lÿY‘`.w2¸`o-]B¿Q•LÞ\BkÿÅœòæk\òaôc—íþ=8“Á/.âÓ»ß@[¿µœñ‡¼u'{Ø`躵,y?ûK€ß¾€;ßfÀî-ô?i<ž9‡©­ýÙ6yC×?Á»×\ÅŽ‘WÒo×ëì<‰¥ÿôiÆœ¼†#w²æ=E”þðë ]½~;‹Ù9l';vì ¾r•‹ZÙxÊF¶}gæÅìܹ“Å¡ø?10¦å³v¯€Öaðý‚@LpOOÊGþ30?«k‚ÇœbÀOëÛ”5<С½à=1˜0+?xc,l[?þxÇeþo~t ïì~‡?žu&±~ ¯»0h&ZðÝt40„Ú3Û·³ ñ™Ô”|©ëþmeËÁèV‚i7æ¤áGÁ Tb%Áñ¼êÂ;ùãÝ`1ë'³¢ã™½ ¤ãñœ\ƒ Ç3yÿ¼2 /䨼y3ÃÛ†ÃxÏ}iø‘Œ‚k ¶³¦ b>Úà†÷”_æXÓ+×óq>Óˆ·h%ÞŸxé›Ðt?ž[¶¬dCÕP}´ŠbÙàÍlß>œ²²Oñö†+±y€Á»þÎgÅ/GŒÀŸSK&w3µµµŒ*õLJýܦi’N§£$£Þp<|<ú¶NÔ¾ˆÎŽ™ŒÇÆÆFfÏžÍ+¯¼ÒáöÙ³gì3{ë#ù£zßßþ™· ‚MÑ×üðÛ}aíŠ`ìíðá7²yó‹œ|òßxçÝœ|r¶mÛ–OC†ç5Š­[·2iÒ$–/_ÎùçŸÏË/¿eòY–ÅòåË9r$7nˆþËt÷{ÕªUŒ1‚M›6qÒI'qòÉ'³}ûvFŽÉÚµk3f k×®å´ÓNã­·Þb̘1œtR0òmÅŠLœ8±OŸ··Þ:‡ÓN;r_b׬YÃðáÃ1bDŸ÷‘v Ïõš5kX»v-ƒæ©§žêëÝ>h=i.¼ðB&>Ÿà/\ÊÛÑ„¥…ÃŒ]F®gýúJ†_ÃŽÏpÊ)o°}ûv À°aÃ0`ãÆcýúõÞ«Ë—/gêÔ©ÑûrãÆÑ{qäÈ‘}vÎôž8qÌsÝÜÜÌ®]»¸öÚk¹÷Þ{ûz×ZO¯ Vþ~ ëÖ}—W9ŒÎßSA0„Ñ#¬mÖ¿ÿÉ <˜¶¶fŠŠÖÒÚú§Ÿ~:o¾ù&gžy&mmmG¥iF½×Ïõ°Û†íÛ·pòÉ'‘sv"¾'6mÚÄæÍ›;vl_ïÊu Ïõ¦M›X±bÛ·oçg?ûeee}½ë¥§××_=Žc³}ûgó·„µìR ø%vî|•¡CB[Ûå º*è 8~ýÖ³k׳ 4ˆM›6qòÉ'óÎ;ïpî¹ç²dÉÎ8ã ^ýuN9%È 8«>¾e ýúõ㤓NbóæÍ¼6i¾ývô=ᣧžÊæ7ߤdÄ–íÙÃàÁƒyqìXÚÚÚ9r$Ë—/çŸÏ8ƒ¥K—RRRBKK §••áø>ãÇgÓ¦MŒt?®Þ¶#F°jÕª¨ ·þ>&ü¼ÿÞÛc6nÜÈÈ‘#Ù¾}{tmþ½qãÆn¿¬]»¶ÃcÖ®]ËÀ£v²ð1áúßyç#Ö&¨cõ:ê`Ú¿+V°iÓ&N9å}ôѾÞõƒÖ“¶ ¹¹™}ìcüýïÏw¸}<¡XO‚Alâþ‰A¤˜·½“ì Å|…Ne?e2o³›ö,™ÝwóêÎïbägöÉ`PÅÀÙ½{7ÆÀ¿³»ÿršw¿Ã€“ikkãLÃÃðMŠŠŠhmmeذa,ÞòÛ‡MgÇŽ ÔÂé{ö0zGзsçN† ÆÓ[žâ䓯áwê8ù䓹ðw¢÷_ÿþýi4ˆ¥»v1zôhV®\É'2fÅ Î<óL^ýuÆÇ£«W3ð”ö̧OnÝÊéùï@;wîdøðá|nÇŽ™¶r%ÇgÇŽ 4ˆðÚîÝœtÒIlذ©§žÊi«V1nÜ8V¯^aüþw0fLÔ6œ·cömcРAlÞ¼Ã0x¨µ•óÎ;W^y…É“'sÚ’%†Á¶mÛ‹/æÌ3ϤµµµK;¼iÓ&ÆßmÛ]Ø?´·Çt¾>|8ýû÷–º<æÜsÏåÅ_¤_¿~¬Y³†Y³fñÀôõ[û õ¤-øâ¿È¯¿¿š—üÿép{崒Ά?̘g0xÏú÷ïÏîÝ»8h¯n»Ÿ¡CçÒÖ֯ĉ¿àäc0Š‹Ù¼y3ƒdÍî×xkÀŠèõqîé§3üå—£×ëäÉ“ùÅÒ¥˜ù>Ã1cÆ0aõjFïÙÈ#ضm“&M"ãº\sÍ5üþ÷¿çšk®a÷ïÏÙgŸ½·oÙŠ¢ë’˦N¥õOêÐ'™u].¾æ/^ÌÉ'ŸÌ„Õ«µ{wôÞÛvÂþÌ¢¢¢mç²AƒxfÇN;í4¾õ⋵ŠÒRV>õTŸÏóÏ?ψ#˜²qc‡íŒ™<™ÿzæ™Ã~<‡²ðxJKKY¶lÙ~·óÎ;ï€aðÇ ð 'ã>FôôûÁW\Á€§kx’K¹——ÀF–ô$ â) ưaÛØ²å)Š‹±}ûvÎ8ã Èž={:ô÷/_¾œsÏ=—·Þz‹ÓN;í°Ÿƒãá{ÿ±zý]èXï‹X±b6lèqŸá1“ñØ?ÿùÏyýõ×9oÁ÷¸õÖ[ î)[Ü]^/ÕÁ‘£Âßþö7ž|òI~}å…·¾÷mºo Däx^<ýôÓ|âçÜ^„6‹Èñ¬k€%|ØTpÛá»&øN_Ÿ¡¬¬ŒçŸ>šÂ Ý»ò?#€?uóèÂÛ¾º—-Ιy$²~qX×ÞélØzajcå`Ü{ï½t߯ZxMpõ^}GÁ߇vÝp aÞô,Óë8RÛùæqv<ß=ζs¢ 4þô§?1zôh.¼ðà‚‚%l:¶ "²/'DààÌ3Ïìt‘Ñ•W^Ù×» "}ìÌ3ÏäÌ3ÏìùŠDDDä˜w¼•‘CwÕUWõõ.ˆú÷õ¬æææ.·k¥¡D¤gÔˆ¨-µ"P[ " ¶@DÔˆ-Ž™Àc8çâÅ‹;ÜÞØØxLO6*"N퀈€ÚQ; "µ"j DDí€ÈÑæ˜ <TUUQWWGkk+óæÍ£¨¨ˆë®»®¯wMD޵"j DD퀈Ôˆ¨-µ"G“~{öìÙÓ×;q Z[[¹ùæ›imm¥¨¨ˆ––ª««©ª:µ‹ÈÑ@퀈€ÚQ; "µ"j DDí€ÈÑä˜ <†˜>}:EEE}½;"ÒÔˆ¨-µ"P[ " ¶@DÔˆ ŽÉÀ£ˆˆˆˆˆˆˆˆˆˆˆˆˆ]Ž©9EDDDDDDDDDDDDäè¤À£ˆˆˆˆˆˆˆˆˆˆˆˆˆô˜"""""""""""""Òc <ŠˆˆˆˆˆˆˆˆˆˆˆˆH×Çšš.¾øb¦NÊܹsiiiéë]ê‘ 0{öì.?ÍÍÍ}Üǹ™5kÝÞ×Çx´žƒ½÷<ÿÇËsßÛŽ·cî­¶àX9/=i Žå÷DwÇ}¢}ô¶ãé˜OÄ×ÂÞÚ‚Þ:Æ£ñ<èšàøÓÚÚÊܹs™:u*S§NeÖ¬Y]Þ·pô^ë.X°Û¶™:u*¶m³`Á‚£~¿[[[¹ë®»:¬ópµ•½±ï{{ßw>ŽîÎo_µ ‡_oµ}ñ|î¯8÷û@ÚÞÚ¯ÞÚïž´GS›&ûv mÁÑú|‰k‚ÞÞïc횺o zëšà@–Q;Ð÷Žd»¤Žçâ‹/îòº>ŽáH]7ö§¾ñoì)//ßó‹_übÏÂ… ÷|èCÚó¡}¨¯w«ÇÇtõÕWïùÆ7¾Ñáç7Þ8¨ã>ÎM6›Ý3eÊ”= .ìö<ôôÖs°¿ãÞ×ó¼<÷½íx<æÞh Ž•óÒ“¶àX~Oìí¸O¤ÏÞv¼ó‰öZØ×{¢7Žñh<º&8>…çyáÂ…{.\¸ç3ŸùÌžòòò=6lˆ–9Z¯uüñ=S¦LÙ“Íf÷,\¸pÏwÞ¹gÊ”)½úº;û®ãñÇÎùÕW_ݫ绷ö}_ïû›o¾yOyyytßøÆ7öL™2eÏã?Þ«çWmÑÑmA_<ŸûkŽÖýÞ_;Ð[ûõÿ·w‡Úm+kÇŸó­ƒå+m€LKLwbÖÄ´ÙTÄ4)¬Hi B·® ¡[W`Ý€?Ð%Ÿ8q,ÅI3£ÿo­®µ·ë&3š™G¯$K6Õîs²À¦LCµª,°u<Û¨ šh·K5Ávû~˜¨ 꼇°C[¹ßf^ÏkúÐV äo/<–'cJÿþûï›vÍ÷ïß·ß¿?»ß6o›Ÿ?n?}ú´ûs¨Ð6ÑGÛ¶A~W¿ëcßûl" lß.&²ÀÅ5QÕï>ìšâ[Ÿû2ªÖ„©>Ú´¨ üõôô´ýôéÓöééi÷Úf³idÎ61¾_¿~Ýû™ÛívûíÛ·íÏŸ?­m÷?ÿüóæ„Àf³Ùð›j÷¹m¯Z÷‡æI9&ß¾}3º}Ɇæ™Ê‚.Ƴ*llw0Õ®sÛm" lÈ4ÔS' lÏ6jÓív¥&Øng©š Î{Èîµ™ûm¸¿¿ß~ýúõͼv¡mÕ@>ñòQ«Y–)ÏsF£Ýka*Š"===uݼ“åy® Îê·íÛf4éááAõÑÆmPÕoéøøû0öMðµÏçf ÛåÜ,puMTõ»û&øØç¾Ì…ckÂTmÛÔþ ‚@³ÙLQ½û[kÝ<Ï•eÙÞÏ”¤år©Édbm»ËG8…a¸7Ãáp×'r¤Îþ4½™;ÃáPEQÛ¾dC;LdAãY•¶¶»*êþÎ62ìÜ,°%ÓPOUØ:žmÔM´Û•š@:ž&j‚:ï!ìÐVî·!Ë2Ýßßëï¿ÿ~óºí}h«òÍ»n@6›$½™ ƒÁààsü]ñôô¤Íf£‹‹ Iv‹Åb7ÁëôÛöm†á^ðš‰>–¯Û´ ªú-ƾ ¾öùÜ,°q ¼vnÔé£ó£ªß}Ø4ÁÇ>÷e.[¦úhÛv &ðW†Z,’þ˜n6%I¢(Švcak­[žœÃP···Êó\aj2™(Š"kÛ=wí¹®Êþ˜ªÎ]SUë>Š¢7'‹¢Ðïß¿ÖdC;LdAãY•¶¶»*êþÎ62ìÜ,ðµ6òUU”'¢mÏ6j‚&ÚíJMPnÛ÷²ÀDMPç=.œ7ꃶr¿iEQèû÷ﺹ¹ysÕ…>´UùÆË;}U…Â0Ôãã£5™Lt{{{ð ÇáÆ%æB1ö(1úñw_ÇšN§Z¯×º¼¼âÒfåIÒ4M5›ÍtssãÄÉi¼ÏÅ,x/îîîºnÚA¾å€DøèPT=£kÔÝ"úÅåñ.SýúÕuSÎæZ Ô5¯ïx% |Ø.&úèúvèë~à¾÷¹¯sÁT]ßÔö+¿ä¥Ñh¤ÑhôænU[kÝ×DÆãñÞ6¶;Š"=>>êùùYÏÏÏZ.— Ô M®©,ËvŸ²~||Ôb±8x‰ÚÈ~&³ ‹ñ¬ÊÛ]'Lµ«éõS' \È4ÔÏ[dzšÀt»© ìË4Tk3÷›¦©ƒnoo5N5N%ýïNoúPj«ò…—ËOú¿þbÎ4M­ÿÄÐ{ÖëõÞb,åy¾ ›:ýv}ۘ裋۠jüû0ö§ð±Ï&²À‡íb¢®mö§ó­ÏÌí£kÛšÀ]ëõZ×××Gßck­[~/ÒëŸùú{‘lkwQŠãxï„@QJÓTÃáЩ™Ï纼¼Ôr¹<ø3ûX¹ÊDt1žU9`k»«r îï´åëX¸”i¨Î[dzš ‰vSØ™i¨ÖFî7i2™èîîN³Ùl÷G’.//5›ÍœèC[5o¼¼ð(ý™ÔI’ì>ù½Z­.//»nÚI¢(Rš¦Šãx÷Zš¦»ç¿¤ß®o}tmÔÿ>Œý)|볩,ða»˜è£KÛýÀy|ê3sáLõÑ¥í@Mà®ñx¬¢(´Z­v¯¥iª4M÷‘lc­[^ÔŽãx÷3ËyW>RÍÖv¯×ë½mDZ‚ 0Úî&ÚþRš¦Êó|wÌË?/?5Ý·ÚÈU¦² íñ¬“¶¶»*Lµ«éõS' \È4üQ' l϶j‚&ÚMM`W¦¡Z›¹ß”ò¢ÛË?ÒŸãZÓY×”6k Ÿüg»Ýn»nDŠ¢ÐõõµŠ¢PÊó\‹ÅÂúïK8&I’ÝI¦Á` <Ï5›Í´X,>ÔoW¶ÍÅÅ…Þ|W•‰>Ú¼ ÞëwÕøû4ö&ùØgYàÒv95 \_‡úÝ·ý€I¾õ¹sáК0ÕG[·5’$Ñíí­‚ htí61¾yžk>Ÿ+Ë2EQ¤,ˌϻ&Ú¦©æó¹ƒ6›ƒ–Ëåî‘F¶åÈ¡uÇñÞ‰Ò—F£Ñî»Á|¯|b" ºϪ°µÝU9`ª]&Û}jØ–i8®* lÏ6j‚&ÚíZM ½ÍS5A÷Ýk3÷Ûôz^»Ð‡¶j Ÿx{á±T>}8:ó¥«ÇE±»%7 ÃwoÅ­Óo×·‰>º¶ êŒÆþ¾õÙTø°]LôÑ¥íÀ~à<>õ™¹`¾.mjwåy¾{,OÓk·‰ñ-f“óÎt»_®—×òM¶»‰¶Ÿ¢oµ‘«LeAãY•6¶»N˜j— ëǧLó],°u<Û¨ L·›šàãﱡ¨æÊœt½mÕ@>ðþÂ#€æyûÚÃ…GgãÂ#€³qáÀÙ¸ðˆ^KÓTEQtÝ –!à æ*…@ß°æÑWÌ}0‡LmaL–ešN§º¸¸ÐÅÅ…¦Ó©õ‹w:êéé©ëfNI’DÓéôàß¹˜‡ pEWsõX”ÿåË]\\èóçÏŠã¸ËÍ CmÔ d!àë¾ËZýغgÍ£i>§º|î jÿïr߀>ñ)SmÄ…G‘ç¹®¯¯´\.õôô¤ù|ÞuÓT…’$9øwäÐÇr@úó©ÁÛÛ[F#=<þ¬‹‹ ÍçsE±÷ZS·÷'I¢ñx¼·SÇz~~ÞÛ©–8öé ²/«Õj÷˜’««+eYÖøv¬Ó>Àm®• E‘f³™Â0<øž&r «L{l€+šœ«ur@’Öëõ›ññx¬¢(vêuÚjCtY“ ŸN÷u×S[sÙdÝp —²¨£Îv¡ÆnjÝ7]«×Y÷¬ytáõÜw!$sY`Û9“}ºÒuFp]À\xôDùÉ›<ϵ\.µX,´^¯õ×_í½–¦©ñG}” 4)Ïs­V+­V+åyþæ½›ÍFišü»—?/I¥iª»»;-—KIÒõõuãÛðúúZaj2™4ú»Ú\+aj±Xh±X,²›È®2íP[ȸ é¹Z•’Þýpùþ—ë¾* lÈ®jôשó¾Îzjs.›¬NÙ†.e!PG5l{ÝÔºo£V¯Z÷¬ytáÐÜ·=Êß/™É›Î‰˜îÐ2‚ë~àQ« Ãp·G£‘~ÿþ­¢(ö^«*@N±Ùl$ýù„_’$ ÃP›ÍFqëîîno±ŽF#=??WþÌ¢(ôãÇ7%HÓôÝÇœ£ —ËËËÝ£Q´½VÞÓDt•i/‘ p…ísõЉ·:Y`CØ’³èSæ}õdÓ\þHÝð.f!PWÕ¶½ÆnbݳæÑWïÍ}Ûs@2Ÿ}¨o€¶u}Îu?páÑ#¯Þ`0Ð`0¨ýïÓ4Õt:=úžcÌïß¿õëׯݣnoow_®~ì1ïõåe¸¼üoÓíβL÷÷÷*Š‚ï^€sÚ\+u˜Î—ÚÎ4²®øÈ\m#L:7Lôù#9 ˜`bÞ¿÷smª$³uƒÏYHæöG]ר¦Ö=k}eâ8Õ†ÛTø^ß]èºV຀¸ðˆáp¨‡‡‡“ÿýÍÍÍÞóÊ‹…’$9éËÔ?run»ã8Öl6ÓjµÒýý=!§´¹Vê0™ç"Й«mäÀ1&.ž|Ô¹}æB#|a[Í ™­ÈBøÎ–ý‘-ç Xóè+[ŽSmÉßëÀEmƒsîÏ^\xÄN'Ý®\ѯ¿$¹­£SÛ]Z,šÍf’¤Õjµ{L à›s×Ê1]ç@ý%àŠÌÕ&s@úSôKo)V~÷ÑëŒhCÓ}|Ôôºi¢n vØrÞ€5¾²å8Õ–,h£Í.ô °I›Çàœû³±sê­ÉQ)‚7ÏY.‹î¦?Ýwî-ÕeApss£õz­8ŽõëׯFÛ t¡ÉÇŠtMô—l€+>2W›~¼P ÃPY–í½^þyb®M<^ ø¸¦×MuY´Ã–ó¬yô•-Ç©¶dAm®ËÆó"@Ú<çÜŸ½¸ðˆsnMžL&J’d÷©€¢(4ŸÏÁÞ—'gY¦8Ž5}©²©G%A »»;M§SÅqÌ­ÕðNÓé2šì/ÙWÔ™«m<^h2™(ŽcM&EQ¤<Ïu¯Éd²÷i_ײ°™éõÔVVÔ©’$Ñz½Öb±¨u×kY˜âÂ~µ‰uÏšG_šûmå€Ô||tÿßt›Mö ð]›Çàœû³±sέɋÅByžï} ýøñc¯ÈÞl6JÓÔè£FLÞ¾=4•$‰&“ _ú ¯4ý¨ƒ.s éþ’ pEÕ\mã‘'³ÙLyžëêêJQ)Ë2EQô¦pw1 [™^Om¬›ºuCžçJÓT›Í¦öÏv) S\د6µîYóè«×s¿­šÏ‚SöÿM¶Ùdßß¹ô¨Õ—8÷gÖ¶Ûí¶ëFÀY–튜ápxp§š¦©Ò4¥åë8 9°Zp6îxp6.<8œ ÎÆ…GgãÂ#€³qáÀÙ¸ðàlÿÔÒw™ÿõœ"%tEXtdate:create2020-10-09T19:33:40+00:00X…k %tEXtdate:modify2020-10-09T19:33:40+00:00)ØÓ°!tEXtpdf:HiResBoundingBox1728x900+0+0×ì&ŒtEXtpdf:VersionPDF-1.7½8;í(tEXtxmp:CreateDate2020-10-09T14:33:13-05:00NÆñ6tEXtxmp:CreatorToolGL2PS 1.3.9, (C) 1999-2015 C. GeuzaineÛ©AJ(tEXtxmp:ModifyDate2020-10-09T14:33:13-05:00úáúÈIEND®B`‚blis-0.9.0/docs/graphs/sup/sgemm_rrr_zen2_nt1.pdf000066400000000000000000005604701422157504600217260ustar00rootroot00000000000000%PDF-1.7 %Çì¢ %%Invocation: path/gs -dQUIET -dNOPAUSE -dBATCH -dSAFER -dAutoRotatePages=/None -sDEVICE=pdfwrite -dLanguageLevel=2 -dEmbedAllFonts=true -dOptimize=true -dDEVICEWIDTHPOINTS=1728 -dDEVICEHEIGHTPOINTS=900 -dNORANGEPAGESIZE -dFIXEDMEDIA -sOutputFile=? ? 5 0 obj <> stream xœä½K¯/;rÝ9¿Ÿbo jw>Iæ´·†wûÖL0µ%y`—Q–!øë7W¬µ"˜ûœû*Ð Ø’|÷Ÿ‡Éä›üe,ÿûÇö¹løý÷?ýù‡ýÿó/ÿùüÞû1¶gÛ¶ù§þù»awß>s|´ñìŸýþøóóWÿÜ÷ ù¯g\ç9þó7Qê!Eùæ‰ûãþ0³y=Ïv||ûÇø·?ìÛq}^mI3Cžíù|ÎO ÿyù¹_Ÿã`”«ÏÖׄ²&¤0'”?—„žóøÏšCÖ„æ„òg%„bŽçhßþ1[ê¿ÏRDóé?ÿéÏÿûŸ~øßþCÿد?ýólÛ}¶Ùçuݳ­¶Ö>þôçþîÇãÜïÏë×›ÿüóº?ïóÇëKè—íÇöóÆç1îÿø§ÿó‡ó§þïïô”{ŒÏ³?KOùé»]£Ï§¿b9­¾÷ûsëKZYÓªXNk•i]3Ã糦¥WZ+ÓZbeZýšy]“bÀ+%ÇÉ„*Nöÿí˜ù<–„²¦T±œÔ+Ó:·™Äµ¦¥WZ+ÓZbýÖ¾vŸÛy£eÏ9*nöµì }âãã˜éžÇÇŸþqíˆíK¼ííú•hÛÃxí·%7~.Ú—Üí_â}ï‘èä÷±7TÁœÿ÷¿irüé=Ù}3þô½óž¿?j¾¤ò M7‹ƒÆCÃý-xll½~Þó5­÷oga?cë?þ8Úç=Žñã¿ûÃg-]s*øñßç?ÿ_ØçsõçÇŸüWV_ý˓ֹv¤{ÿ<[Ÿô}~ö1˜•ÿñ‡s¾µí÷ÿo¸ÏqüøOùןgNÎOä©þúûü×ÿ¦¿úò×ßç_ÿò‡9nfÿÎÉÉž÷ìfߦö—üë¿üáÎè_¾ó²ÿú‡?ŽÏÞžóúñ3°ÊVÿ5ÿú‡ï„ý?³f~Žs_z!ûßÀª59È»?ŸçqañÙ?Ç®yàÚ°@žsmÀlq?ýózŽÒÛç>fHÛf[÷9£msrŠY`æm®30æÚç"Ú÷9ì‘J;ϹtÍg޽}n;Bæ¿ø«£{¶¶nsµë×y}Þ˜KÛL}o3û8g‹çó¸gwdžÌcç|ñ¾ŽÁÔÿc¦ÓúÉuä›OuôÅ™ùGçç,¦Û>ó>Ö[Û¸äöY€™è|èØ™> 0.$Óga‘>»&Và>îc¶"BPˆ}¾¼?C)ÏBlÏ…8³±F„<¨×>žûs ä³S¨Î§Ÿ7ÊÐgÎ qf]4ij ³bðÔõy á2ìxjÖðƒF(ÄœñǶïÌà˜…˜54ãÏçqf!ú\gž9iHf–aÌ—Î Ÿ3£™UðㆊdP†ãœqæ'B6¬DóÝÑc–a°;uóÍ¿mÊÿ>óE›Ìýh¼ÃüŽÊ;G„Ìü7”qŽº“é ÿxÓ­>C¢CÍöoìùû>‹€î6f׈RïsÏzœ5s!ç™eØã‘Ÿc–aW}²fŽËÔ|jëj—¥ØQ¬·GJ†Ú9QÌr¨‚¨ŠÆ„g!îΦ‹n=ŸÞ>Û½ÔÎÑ¢4Q£é¢ ; Ûò@°q}ßY`ôÙC5Ò=g¶xÓàßOt…†"̘%˜“kô‘»³fÝèÄ»ì~¢ûZç-=“yP~„Ì"ܨÑíTý³ ¯ºNµÌ‰}³Ž†Ì2Œ¨Ñ{NÛ‚BàíÛ¡8X8f"·^=7sG wNH3Ÿ*¿k̹*BfŽ›cõˆ"\³'ЉFe:(BThãı_(ÂκaÁ¯Y„ûaƒ³ŽM_è¬7³7‹€}Ãö<:^T郜ÎÅ‹5s£xÑyqaÛo!þ]]ÿžéï¨N̶Q¦kV´w¼ùÆž½æê1_î÷,Àu²“AP›sML@º›ªKZCÏ!3ÿœR7®%sŒÝ˜.fœ %CÈ8Ê8ç€À›‹3–…ùN y¬Î{ ͘;Vç=æÇ¦vi³ XÀ±1h ™…8ñ® Ìr›…¸n2ÎImâ>YòƒoG)v–‚£¬¡HæÑ ë³]¤‹ÒÞA¾sŽåxïsð ãÌ>û‰+ôvqVºù ‚ž‡F"Vè¬}–!&ð³q}ž!OLਯ(Bï#æoŒ—ï³÷Å•<—꘿·ÙO"Ê@PʹʳgÄô='$‡YLßÈ^,ûÀ_mínXŸ1ƒÏŽ‰ÞŒY„Xî¬v¬ÏÇÁ"4¾ E`_ŒÒGg*†,Bf®Îi•ËÔÀ芶‹¾:CžY†˜ÂÛ…~‡”¯šVúsÄŠ½ŸãÎ+ð.V×3·‰1…Ÿ]Õ…%:æŠlr,јÂç USa‰Ž)|ÎÏìÛØmÄ~c©Ž”bôM3V’KUz ác›…À޹-æýc›…ˆ)üÚ8Ás/s8+Öª¹È1‡ïœž‚B 7Çձ͉9Üù;°@cß±•ØòpŸuq2;³ 1‰Ï§ø¦ïŒ24¾ e@1‡ºä9×›•‡!³ ·Êƒñ˜ËçðÖ¸:ø7ÌáXS™Á9#sŸÿˆ”!ÚsãâpUç;íÂ>ûªê©í}™<¬Ð˜Âç,Âéù˜mÇ)¼i“6!ðŽ)|&nž%ˆÆ<ØŽc– ¦ð[+Õ 88…Ï2 ¦ƒÏ!(e¿É"ÇqoœÂçSÓ¹NáYX£cÇ~:êktTñ¿À ƒ ôÆ'f ŽÆµ­rÎÄ>wA1ÙM¸º8‡ïÚ@ÌìžœÃçn¹;QVÍÁ€Y€˜ÃgÈàC³1‡× y8‡·[ÍŸ].Ž&3óÏ)¼sÑI¶Çò{ïÿ$ý ÿëbÀñœ˜´s“v1 {b1`{öÁ‰I ØÌýbbÀ‰’÷4†ÀöLt®mlÏ,}Ô °W¬Ø0°£'nsÍ‹ý~Bà6תX.1øc]OÜ|&ùX p;7îW Æ# ØPGÏND/ˆÝhB öW1ç΀›»„@LÙ$>1`¬xbÀ¹ûa{&Æþ7R1bÄŒF·ˆ3 ÆÇ¨& ˜ ˆ•lŒaQÌ€s>eݘ窫›É€˜Fcn3ÎWuövCà y¸‚ûú î2fu;† !p†\#æÀ~ ;¬ر­AnœÍØÙ#ÍBVΧvV†9°cª‰}—9pæùâ„b옹6 û1NÑ„@°c‚ä;‚»àŒ3´ÇÎtôMÁ 8ãð')p¾úѦZØ1ïŒCì1¯‘û‚U“àÌÌm# ÎKË+I°sb`ÂBÁ(÷BÁPƇˆ‚3äÒþ](8Ó9´Ë Î:>E;FÁ㊳PÐåF—äÖC8¹D$âÀùˆ¾›˜£Ü+Î~sk³D œ©Ü(Ha`<î0p†œâTaàLæ\ˆ£KˆAÉ}.uÜCˆ£ïs¯)ìˆÊ½°80^~ûÈѼܿ g+" ìpÚ… #ËÜ[ çS»ßEœ!§Ÿâ~,ÒÙ ”ÁÈóF $ÆSÌ 9phŠœi\êÍñæóÅaî³fÀ€c@że Œ‡@ ŒqaP`Ì Ü±Š1ž> #óü. œ!ú^hŒDˆ|„À%+„Àh€m…ÀÈ?Õýâ£0F¶È‘nÆøâçB`ô3nÿ3™Æo †Àx7·û‚ÀxŠ=OÝž p¦ó€£ #ÇB5Bà|ꎑζBàRAàŒã~/œ!—æ,Aà éšsŽÐdCà>z§ 0VqÂjƤ@â#F©øýˆ …:‰sdÀ(1B ã€ÝD¸ŒAàR9‚Àá‡2Qà2.EKƒŠcàèFH')’£v¢ÍÑG9#‰ã!aá“72NÀ#F‹×3N˜ gÈ£©EE+ÎÌìšÑâ;Ÿ"ÆS„]A`¤,P$Î8CÁËä,Œ*(#ÏÂË€À™Ì­> Œì<+Vv 3dçºeŒE“€G¬V嘫¥Ì€QÉG2`t~pM‡Ãá"’£rxÜz/qÕ» Q*ñ!0{Ž0’yBŒdNbá„À¥fQ&>A̾fŒ9P‰€‘ ©ŒX½ÆX©£^ˆŸÀ%ò_ÍZæ¿%÷⿘®¯•ÿ"„`Nþ[ZI¸&CŒ2mä2"à’Œ0j÷$˜£{nd·@À(% %\*X½3a"àš 0*‡ß(Ä€j–†Aãüß}\zGüÿëß„¿=,ªoKà‰Æ^-];#S`Çà‰ 8-ñuyµâÓXlŒÒx\"¯_0æ!L˜ùc|¤)pBK–ˆv‹}RRàùèëPRà9™ï~™ÏIŠíe <7™ÈLçÑ') Iß)}™øf ÄŽ ¢Ñ{‚Í€'@#Ò5žX'i$ž· •†À ÛÈ!ðl27$ž]9ÏK½² pf8Ì€ç¡ÉÄ xNä:O<çÂN*4¢+Þ4û‰ÏKÎ’Ïçä!»Í˜°“/XRêg<1Ö‚¹Ì€èÓÇjŒmÎXmÑâ¤93`ÖE2 ¤Sщ“ÑÀƒÖA1à9†ÌfÀ{ÜHÇ ›ÝàV3à‰}­mbÀk'žãþ€ç³k6ž­›%ŀצjɀ眸w7^sà ‰Yc‰Ù‰Kž…×¶¾(°^% Ä›¸Ü›Ïnã)0ë4)½‡;(Sàùèƒ_R`¶zR J.â(ðÄv—Ù"„»@ƒ J5Vƒ`´–,yALšdY“àµéÛ§IðÚüqÛ$xmÝ'<±œ2ŽH.k¤HðÄFŸFC‘à5BHðÄúÑàùܲí˜QN~ 0 ";íE‚çy«.L‚˜1X&AÔû¶š£v¸¿4 ¢Ñ Á&AÔyÜ$ˆþÅ^iDkÚŒ‚èq4 V4 ¢ë(‚PwŠfAÔÛÁ,ˆ]/<›W ƒ9@sX' ¢„‡âA G€y‚o7¢Í¹O5VWbœþ „9Ÿ&ž1©,Dxm¦au!zÁ³áÙm>3VŸ4V×1ÖÀ2žÏE3—°ÚÎ@x›… „è .¯¢T.!Ræ1¢ù(0¢O‘"Ƀ˜Û9:̓åüäbD‚̃¨œg5 Æs¾€m%3!°†ž° e D¯àp0¢|¹€5*;¡€¯ê/ ¬Þn Dë½°†•)sò2Ög"¬®c"D%sP QDu#ar#!BøõÆHˆc„hOÎÿFB´ùµÚ#ƒ¬T#aÍLFÂ#FB¼ënšÉÏ/Hˆê9V»`T×]!!^ůFBŒóF+ 0J$Ì4‘…0f©Œ„x“PSHˆŽ+{£}‡M‚ÙWUè’ŽI0Kž$è &f&f]$æ«—à"Ì,'f±3Ë ‚›.‰ˆ³Ÿ$f&./Ö‹ŒG¸DÖ«ÒXq„K2ÂÀå)a 21†ÄÀ¬õÄÀÞ…á6Έíe¬tŒ9ëíÂÀ¨B[Ÿ(DvS Æ47I¦À-¾ì9îM9}$"dQ`U )°ÚÓXUj Ìᙸ¤# \Ò.qDÕ¿Lê€FÀåÕB@E¸¶¶Œ•俜é’ÿ_ðWÍjø«\þræKø«îaø[BÕ K:‚¿zÊðWq •CÁßEð·$#ø«¾iøS¹M~U1&¿å=$¿%ŠÈoyȯòbò«7›ü–¡Ÿòbî«dÍ}Ž è["úªr }5F }KÞ}KR_%lê«ÌšúªL}¹Z&õ-!¢¾ØDÓ~GêC%,ê˵;©m„GQß"ê«!kêC:V5Qß"ê[BD}•Ž©o‰#ê[BD}yA_BÐW96ôÕ3b>p2ó!DJK1BÈŽf¾%Ž˜o óaË$㡘o‰#æ[âˆùÒ_Ì—[¯d>„ëÅ|K€˜!2³‰ù–1_¾*™/ÓIèËiÚЗ]'¡/'û„¾%Ž /8¡/„¾%DÐçµ'™/;r2_=dæ«›ù*ƒf¾å)1ßæ[óå–Ì·dFз$"è«rú*Ž¡¯²gê«w™ú–tD}KQßGÔW¥0õå€0öU!Œ}K2⾊cî«„Í}Kq_½JÜ·D÷Õ«Ì}Kqß’Œ¸o‰#î[Ò÷eþº5pûŽ50Ö“×¹ÀA†ý¥sÐÛ¿ðî¤ð‚@Ï5 0!®¡g¿Óyàù‚À¹ÈÄh„öêbˆ j±Øç%¢ó=/cà±I~Ÿ8‡ñÓ8»#?%ÎnD%}ã‹FYO KÚõ}¶ô ­™÷, 06þ¥4ñ©Ž—ÂÅ艳¿p/–øwœ)eĦ*ØÎøÁLÀ±ñÉXAÿœÚy«A¹[ð/µ–¥ý9fÀÂ?X‰^üýc|NIþ;îZƒƒba‹ãß\üø¿Ä ¨Ø¹ƒJ+VZPhK *[)A­&+%è ‰]D)AC’‘äí˜Äš–¦Ž-e 8£@cže bè ¡¥"e ©à2ùa:¥4ÏðWR"ÃHh™¡ay^ðWb§T‚¦ê&• sdKø)%hX ÚÛ%è"øK©I)A»Žw–´âX Zï²´ë£ÙQxœ%µ 3„†:KAS`–RPëg-¨uVÖ‚fº©µª*¥ ‹ðÓRÐKö5£_)ÌR Ú¿JA-_^¤ ))¨U§%½õò”‚Ι-OÝo)èõh3œRP,5ë™ÀÐ2$Z Šéë…~K:–‚¦h7µ —O­R zIÏ_ZÐSêýÒ‚žÖR§tNmÜ«§ôÔÌQbÐSJ§RƒZ5^jPOš¥=¯/ ˆtX„„f:)=©å(AhfÇ‚ÐÌM BO àRZéZzJaTŠÐÌM*B+Ž¡¬—"4³gAh–;¡ÖÆ— Ô¥tVÍ¢#€Öƒ¦3õ §E­©Í*N=(ŒÔ|—õ –ó—ô´ªÕzP/f¥ÅùÃhÊAÝ )õ*Yzй&J¶)=¨ÉÒƒZ±TzÐÒ^æ?„pÔ§ôÌcŒÖƒf:©­ëA½ü–4µñ©=‡†}êAçSç +‡)!+Æ®™–= BáÆáE‚˜öŽ "d=Ù“aÏzÐÌpêA¯Mâ”ÔƒúPEéAgœg=¸d'õ Ø®‡×ëAçÛulQzP,¡/ã_6yéAq"‘g÷¬u—ôì6íY:_%•¦¡8µCV´ '©_Ö?œ/ØÞ‚PI”KZÉXšQ,Í()…ôêeû[B,õV®ä ×pëAgŽ¿èAç»(j¥t ½80s—zPu’Òƒf5¤Ôݦ¡×i ¡N7¡>›Q‚ÐÌm*Bó! B¯ö>É.­,¡õ õ"ëAÝ©KšMzÐ,AêAÝKš¹±tô·´B¬…Lñ­­„­õP-=¨ÇF B]ÎŸÒ ÌNÝÞ¨7Ê—Ì}ÇË/™û†”)üu$&yïÞ´Œ&ïÝ»ÎÍ%ïa·t¾Ì}÷¡¦LÞ»ÏÍ™¼?q±%ïaLà»OœIÞƒ×Ê3Í{wì®öîSŽQ’öîK‡÷îS@hÜ»çè ¶3í!•·©ï¾µ÷JàC÷g¾;×…÷nxØùXp™MÖ›Eú|ùæ¿…zȉT£B½û†˜ôðjLz(Nø‰ôÐ ’ˆŠôÐÔcõþÕò¬¤‡’‘Þ}û0¡IïîöœbÒ»o鳓ô°[Õ>‘Þ}ê j’Þ}û´™IÅz¹‰Ú¹^¨wúÈ”¬‡~v¾ŽýeÏKÖs¯2êeoMÔCþd÷ë!7JE¬w_Fw³^ìåiÃëÝ÷°•¬w_‰¢b=D!H õÐ)¤Ñêݧ¿xõ*F½û2ÜõPîþ:õ‡¾4^ZÏ;ëש?”Jg…zxǨ‡ørÿ9uì/a¢h‰5£šŽöa£2s¾´žx¡Ü¨‡>Ú^ÿ*{F½ê&F½DF=d¸¿ÎþyHÒ»Ï<Ø'ÔC¿¹W©'ª˜­iÔÛ¶—Ôù#)õnlØW01¯×á?”A‰zÈðù’z.¹ë¡íø‘À¬‡¹cȬW}À°‡‚³öª†=Äi/0(ÞþÒzV×6ì!„=а‡öÃ^Í1‚=D9^bÏóÓê&BÚËìw=½kø£i¯²#ÚCƒlb;Òró>ý‡8׋ö0Òî—Ùoɲh¯ž2íaæ<^bϪ ÓÞÏ5Ä4ÑÖvnÓÞ}§´S´‡™“ÊIÓ†ˆ¸‡9†eÜ«Å˸W…0î¡Ôæ½\zŒ{È1scÜë$·îUŽ{x¿¾÷·Ö/—Q¸‡rž/ÜÃS”U÷ªœÆ½\h÷P–p/;wâ^V`âÞÝL ½|Uâ^¶UâÞÝä¨/qïÆ§h†ˆ÷P;ýuþ/׌¾›Û|Yï |U,ß 'ŠŒ#àË–HàÃÄ#t>äð.±gVqjB>_D|÷ÜsS=käC²÷Kíé­Qß=·Ï÷Kì‰Ú"ÖùîÖ¾œDœã…|ËSb¾»Éý\2ßݺÏó úåmq9ægC_.¨ }è€Â7A*T^_}˜Û_gï&Gwf¾»É]Y2ªœB¾»¯.`"oôŽcÞââ=tšãeòCþC§ùS9ï>x¸w°üVÎ9£üÎ:NºØþ¥R”ožøu§Ü³è±­ª43dqí09À­Ÿåû-‰%!‡¬ )Ì åÏJè:m-bü\’ˆ=¯¿ÿÖŽ¸Ï¹ÅÜÎwÒðÿ„Ÿí==ÿL„rÄýôŒà?᣸§wØo{ÇÇ>ߎ¸¿×æŽowÝJkq±­´VÛN«b9­—»n§U.¶Öâb;ÓÊX™Öê®Ûi¥“m'UN¶3%ÇÉ„gÝîóåb[ ­.¶s d,'õr×í´ÊŶÓZ\lgZ+Óú+qÇqñ«ÿŒ#îûq»se¼ï;âþ¹h_qÿJrãç¢ýŒ#î··ù·#îß2!þôžà¾™þ~úîÀyM‰ß5_RùÝ>°qÄßß~ÅvOØ/ÕËŸÿoÕ /ØùNj{þ%Ùm|ÇvËç_ô‡Ý·cØö üÆö û×üë¾–þ°_ö‡=—{|TK¯fŽá’ _Sb©~à zyj=­Á\l åÜ6¦>ä‰÷„ æylœÜœðDö\Ëîí„'2,èí”Òu†<¼ ëƒã¹Á?"ˆžát9¼PëôÚ ç¤ 2xŠÛŽÊãÞJ/z°d]èßFHqe@ÀÅ:>¥ŒáDŠoêô«ŒÍßÎdý*‡É&ºUÆŽ1Œˆ'¤=pË k},æçAWØn¯Âïål"ºU†â¤1ÎA·ÊÇ#÷£'^¿œÇ#'7' (ðËyØ5Ü IáZùÑYïºÎÚ‚Ï‹“ɰÀsžçFV9ál+|+Ÿ›ÛùOô­Œ©>¢Ìv¿œ8ßÏ=+#•øÞpb?1âæñÍyžô¬ ÿꓹèYù„5—!7=+#=vd|/ßãU’žg§gexz>2èY›\v[PÂC77Ä'ŽeÁ+'ÞÈüy;‡wÇg‹ó:èXÎn…г2¶ÆAóçuʳò,CcÈž•ñéŸ-uÝô¬|B"}àjô¬;ìèt¬Œ²1¿× gå¦à) x&¾gÎ?èXçÙƒ£Î{§ce”2^tô«ŒRœøpØâM²Cœø¶Ÿœ¹ç¢_exbhLç¦_e´XãyG"PCð'/ |ܘ—ýrÀ?ÆÁdúUF—àjý*Ÿ‡ü*Ÿm§_eô£°”Î\ѯ2Γ+€n•ÏC:kšn•ññ1>¿Î¡[å38ëlü<æT "¶FŸÊxsg^:Ý*£ÐqF¸Užƒšh}¶‡n•Ñ#`.è%pçì;½*Ÿ¬í~Ч2&]ö~Чò ߌÑöý¤OexÆ`”‹>•aNbÇΪÇ{ôUúì>•çfYÍWß&ŠÑ¥22ÇñÖºT!‘ðÜ÷…Keä† 0öø ίÃubZ?c¢ÑGÞB—Êç&&=MÔ1‹°ÊÇE—ÊpCÃ)lÜáRùÜô:±ßÔéQŠ2èQ9ç8¥C妹òÙèPùôé±óAvf/°ÿ|zTÆ,ÅE— œ¯Ü<\@Ð9ô(çsÑ¥rMXç㉯JçÓèSy®~; ±ÖèÃå5¦Ü ?t©|î*Ä…Åy»ùTtÇ ‹ó~.õnB>½|†„OeTŽ¢'Ì5ä¢Oåå¡›>•Qƒ/oô©|øÌÙµuúTÆÿ›éð–‚x*>Š_8¹ˆÉ[‹Ã Á‰¹˜¼·ƒê„ ‹ó¦5*>o_Xœ÷‹!ñ­óÂê|œLgcœ“>•Ñuâ»Ü^£±°\.yú,?ŒÒèSw†Ð¹U$|ò)8 ˆ—w6ñµ?ô©ŒtbÞS~øTF2,Õ±Ó§2йîÂ꼩ï0;X÷ÆÕycÈIŸÊxyÌ&×A4Q*6(VwÌßp±_ˆ.쮇é\|ªÓ©rø©dÈ SeúÀ\bþÆÔÐùæF§ÊNgñÍN•aO:øÔ Såêá´b°L±B^8˜ÞÛ²-¹àÌd\kýÍÖ‹9üð1¹ Ëó¦-ÆÃ8g8UÎÉáÂê¼k#ÅŽŒåùPω øºý*#á°͇èWù°Ëß ›fÎãRº^×~•sF¹`«ŽyÜÕuït«ìÙlЫ2CzUιëÂò¼kf°b>a3ÜãÌY|0ä i-“WCvÎKì~ eX¦·ðpßåÚìjÇà4ž3Lƒ^é^ˉz»¸¢±ÏbŽy|×'Þ ktÌã^õ®Ö/Îã›ì">p×E&WÃÈm챩¼:gëe^š Ä=xÖißîÁ³t”bûÙµ—9jvЦ-¸{E|¹ùª›É´P®ÙhgÊ¿Õ+v’ ,"ûõ"ÁMî*D‚íIgó"ÁöØQ»I0Ip±6 n‡¼á& BÐHg"A\"C€oׂ°×GÉaŒß^ xlrÀ ¸?§ÁÁcv…ˆI ÿtÜÀ áV—qƒ ¸jˆû‚ØK’TE‚=z CH‚á[G‘`x$á™$Ú¸U ÎùT7 ö ÛæoÈ©dåŒóHQ?ô•Þ(دKÌ‚%ø1 ΔO~T3 Î]¢Ü“{lCÉpDÁ¸§Š[H¡à„ýa8$ ÆÛ‰¼DÁ qc-,ÕQp>$×öFÁ~qË],~­Â¢hœãENü ƒ3DZ6Ãà|—„¼†ÁL™0ØKävÁ`¨€ØZ‚ÁYÐ[ÛUÁà 9´³' öû¸9!˜# wå¢Á°Û†fÝ4XºÓ`ˆOé,à^€wQgqºeƒ3JW –Ê4XÆhÓà,æPÿ.!ÂÁ’®CÛÀ6v¬UÏʃó)þ<­²ð¶]08‘{]Ã`è£8£Üá–ë‘æÙ0!¿‚Áè³l\Á`ø3b/ Îz0ÒKÎaœýºsßgŒ§6RÚi•…7š£ÎpKd±Ë”eŒ†bŃ3Ž´•âÁ¨q~p†^‚%F¿€°£æ ébÂèÄ(Q*‹CÅ„!/+†ŸAĄѸÏÊ„ñrŽ_1aè.&<¤²˜Ü{®P!ü€!(,¼¡0Zü^¡0žVYðÌœ™0äLQ.‰,òådÂ2eš £É7bc—Èâô—/A!º¬ªKT(=›‘0³¯Hb0.B­8D‹Ó_£„„e6FÊQB»p ã)V(‘04*犄ñ*Qìc…åW&°ඕcVØn‡·.Œ–ÆÐD˜†`a˜œßtK_5ƒojÖWè{Ÿ0ÌÛ¢Ñ!Å¥ïÂ’K”g \ãX˜…„eÍ6Öà¦HÊ<²îóŃ¥¦0FKí+V¯0Æ0c­“KËdŒW•£ŽI/âÁÒï˜C ÀÆ– È<UÊ=¨x°TæÁxW˜Ü̓ñ®Æ8ô˜£_övÉ+¤  ,‚i° ¦Á5ä’ºÂÒã`éUŒƒ%Ñ3FõÅÆÒ8“À`qp FEð“€p°DŽÆÁÒ £ÒY5ÄÁõ¡KòŠzˆ!^Å, —N+¬È8Úò>qpé[ÂÁ¤šKƒa ŒWñ …€0žâ§áò*a´G@Xs‰°ãN^²Šˆ0ºÉ „ëCB(@AÂRµkŽ4ƨ×CÂx(ö3Âx7ÙS@O±äÂxJ°G L…Šy0òÇÊ–È<!_ñ`G4Ñß&œdhæÁé .¹.m%,•’y°„BæÁ¥3Ù¼ÕF…Ìov‘]ÆÁ;®-$ì¸ä’š"©ÄYƒt;e¼½ Hãà%%"amâ„9[&F¯%݉ ³²“ SÖLØ­É„÷8GLØNÌ„8åñ26êú&lûi#ž˜°áèþjŒ—÷Õ:8ãè £dBbh+b4é!1aƒj˜!b†¾"&lo$"ÊIkœJWî´Œ„µí4"™cµöеå„„ ;?Æb_Ë ‘ŠY8Œ„8¿Â∋PHØpkÆ1˜HØHغ|$¶vå„„ > Wû`¤Ãž‘oÒžˆ°µÇ´'"lã0GŠ—ìˆ17°£˜±·¿ó`œh"l½Éi"l ²œˆ·8“FL„ žÚWûàÌò0Y QðÁ‡„„Õ2‰„s£Ì/FBÌxÜœ ‘Î8‰„r0‘Hˆ ¤mÉHˆtˆn"Âjr!ZOfEAáœe”Caº!0¡° ]ÏE(D»! …ÈïµZ#ö~C!ꆕe(l]Æ|3aLô«pDfÂÖäw9™°Æ¢™ê6Îf†BÄá1¶æéÃPˆ!É@P¸Dbö  ‡ö_C!âDÌ„è%2ð‰ ó²o3a !3a_3!ÞÄ"˜ Ûm€™çØÆ‹ ÛM?lj„H†_䌄SÆ‚„ù‰oÚ_DXo2¢Üûj&Œ8âH"a»ua["aÊHˆ8 FB´Ç‘¯j/*D:\›L…U*Sa5§©°Þe*\Ò¢!hê6¶Û’S! Ê1$*D'å§QS!: —eSa¾*±ÉøD…í¢” ¡–q‘P˜õ—P˜ùM*Dw¦B”€ûWSaŽ¡¤Âì'I…˜Ij¦Â‹I…±y#u‰ ÑzMFÁM“¸|'"s5ƘiL™Tˆ(‘OXˆ©l{a¡¶’ ¶®ãø‰…K–……9‰ «.Œ…•°±°jÇXˆ9‡Æcá’Ž°Ãüaˆ°M~……9w%¶K°ÄBQ–…… ÎoHÂBÄ!pš Ûõ˜×†Ø-]«™0BhX2bÜ³Ž †í>l8"í-C¤£8ÃvK^•`ˆÌ †ˆÃ¶2â]m€CÄ‘©N`XÅ4âí¢>‚á 0Īp¼À0·Ž †x!Á`ˆà †¹ 1°HÜ' s²H0ÌE.Á0'¯Ã\À ci#* +;Ã\! ‘ÃëE†ˆC;¯É°¦“aµ±È0çÀ$Cd‡¯2.qD†U,“!¿˜ ÑÿÙ &ÃÜ&Æq0>%4Ä@gÇ0¢š ¼FC¤³Z kaI2l\–Š [“'Ép‰"2Ìu%ɰÊ`2¬YÐd˜)ÿŠ›ì¢Á+îÃXiðøJƒìt â6êë%=6]^’4ˆàÞÜ4˜^¥’!5QÑ Ž€¾i0¯ JÌ›5’añâ˃NJ"„€‹²a°ìR‚AœËä®Á0“Ó)s aðbvM‚רmè âP&w±&A˜¸Ë1 ¦=Ç$xor“${Ó¹êDã‹?Í FÁú6nÌs¨…‚>™(ˆÏåä5‘ >¸±1M‚€t¦"¬ÏûA|Î’ýP ˆ¯tüª-ÌelÖîýy&90?_&æ¯äÀ»ËR¨ó×þ¸UvAç*!r'•xwzh+³à|è|™!Ü£%âb&¨Ì‚c—9Öˆd¸;5"äÅ€3 ‘UpX¹i«àÐYð´ ·cZÇm˜3·~Z @Ó*øìfT#àûɲ >þ VÁñ|± "Îñ¶ >þĆÁ!×ÌÉ€ÈéÍvAxÊ-¼ŸËd)Dª´$ŠóD\ Ò Ï§Yð¹ŒnFÀÍj># Ns¢I³àcÍmšA.³àïâe|ô)½Ì‚ÏcJ´YðiÒÛ,8â®=Í‚Ïþ…oöù´ yIþ»¹ÁYø/{‘M‚ƒÎË"8,`N‹àŸÝ²ù(‹àh¶Ú"8Òˆi‹`vé´K®Ó"8è°· ‚ã²)ÏÁáõ -‚c³aÑÁ¬ [ëݶV¶ŽýóEÈŒŒ†6ºöÒ$8äT·L‚C·•Ipè¾…2 ŽCKFšs€¥I0ó—&Áüx™&Á¬u›‡¿f¦I0sl‹ §„2 *JY‡\®–EгFZ‡\Ó”EpÈkr™%µ=pÈ}Ù‡Õ‚iV5¥=гJÙqQ&ÎöÀ1¬¿´=pÈÑrÙ‡üo—=Ð3OÙ=ÀÒølFJ5Õ”=pÈEwÙ=Ÿ–=ð‘`/ͬ§¶z2-kàŒñÅl |¬6Kkà#w±e ¬[=Y–5ÐMYŸ´ôÙøØP›Ö@ܳªCc cHk $i«:4òC#íùê´>6 ÚèªJkà#½SY+ÄÖ@/}žÊ ú¶ý«5ÐKBA_ÆIèÛNY^Òè5¶¬ØõóUoLcà#ýyY÷˘½&ÇÆÀŠ#c k+m Øi Ì‘¦@®ˆ ñU·OS`¦kK`Øø\ °0›:í€ØB3Y³›§!0»g3½–!ÐkpŸKŸ2ÒèFI; —é²V2¶>·`8 džÀÇz×4f©ÒøXù†ÀìùiÌnC`޹4>2¦§°Òµð±e<í€9Òè]ØïpŽ]äwÆ»JC›¯%ùÁÏDÙAeÂ(‘æ÷ëuH³ùۈÆÒtŠüöw&-ÒP9^+iè© ÇJŠÚ{ß~å«, ½l$2ùÃhf0ùíô?RäïÜ"2‘ß~_²Y™ü°LÜ/3 è2ˆ?„èH à™àÆNðW¥2üÁÇ…øPð·„þà³êxÙ‡¥2üEy `‚¿%Žào?mZ5ý¥›ò¤¿ýoúCéømßô‡HÜÑšþà–CºTÒ:ÁµŒܸ™þöëÿÐzÜËÿöKêÿb $îy0ψ”y͸_>¤dD:(# â°¾Œ€hÆñR†âè ñÔˆ $Þ‰Ñã% E­KÀ)DIM¸û›¿yüȈéME€Ù_ºÐjpà~¾ð¯Úßø‡GÆ ÿ*ã_õGãúõ½Œ§ö—.Öü—…¼[{½Yø·¼Yü‡4hÁ2ÿ…r›ø¯*Æü‡üÞ/þCÊŠ#þCmªæ?4d{ñÒ/ļÅÏSÀýë9Át}5ÖdgDMwâ?ÏiÜ}d6°ŠmÄ¥² Š÷]Go“ñòû…€ûöFÀ=ÏQ÷Íûg# ∠I€ËC"Àz‘ °" ¿ì~xH"R q/»ßò* Jù¶û¡dX¢n„„ÀÌ‹ù[«c=oæv߈4@´õt`¤K:5.q€¾{%ùQ±lþCþ¹7ÿ!7÷K º„ˆÿÐ’ ÿá7™Æü‡g¤ÿUmšÿª{šÿªæ?Ä!Èÿð*r°×¸†«QL€õr`eИÍ`Dm‘4Ì€ÕþfÀ=O& 𬇗 5VwÖCFÀj)# ¦‚·Å/3lD‡}Ùû*@XE2âF¾·Ãòy)Aщ߸çH Jy¾ì}UÃÀ¼®4%1M€5ט«ß¤û)ïøÆ^H/Ü;¿l|<þý‚;PÚøÚø| >±“>^ 7w+:Ûnл°¿|‘Þ=ú[ð™gkRð™'»Lzé—²Ÿ§Žo'é•ÝǤkÁËÆ×6™ú“ôÊ‘‚ÏS_!Kð¹ß±à3%ƒ&=¸½¡lJ¤—b“|ÞÍ&< >ÁwLÆ‚O:~]H¯o§ÕœV|öÇP‘^Û|¾%Ÿø-ÃI}‘QzØj²rLzØHÊ¢˜v¾´ê‰ôú©|Lzp4ÎO&½~ùìI/ßmÐë—¼Þ˜ó:*}u3£<úàmÎÃ&–[Js^¿Õ%yzYFæu8WùX(¯ß§e¤¢¼ÞåM5)¯ß>4&Ê›ùÓÍ”‡(â>a^¹92æÁyúùR{bÜê)qÞ’A¹‘O ‡áÏÍušúüq(A¯·KûdƒÞò*±^o>UdÖ›o—AN¨7û7×&½Þl6éUêæzi={Ó¡¢=d殀h”çEzÈÉx̆3èð$Ÿ@Y!ßôúÐå zá÷eèëCôz?ìF ×¯IÎC”þ’z¢ØüZ`ÎCŽ•óúh~·8}äyÿ›ÿOPaÒCœûEzž=ÔÃË·õàsŸ³„Q/`ð'Ô«Ê1롘첆=¤s¾´ž(Äõ{VÃ^ïòS˜°WE7ìušt"°‡bñKŽiãùz©=ûRãd#îõgSC¤Ú3eÂæ=ÄÙ^+ó^ÔÀ‡‚ö—Ú³?W" ¯?»ÝÀWï2ðá]!><žlà«1#àà í¥öìE!¾Œ“À‡8<ÄfàCˆ„š>´ãµšüúóX4*àƒ;èóu °?:ÞŸÌ×¥1ômûr !Ûë`8š~D½ót’¡/ë4¡ﺄx„>ë~é=ÑéÄЇr }x9YMÌWù3óuL­ ó!•ö²ú¡Ú7ZÅ|•A¢»Ä|* óáÝR` úPn±¡ɈÖ}ÈŸBD}cÓ§Ö¤¾±Ù™‹©ol:‰žÔ‡î@M}Ù'“ú*Ž©¯òÔWUnìƒ×p~0öUƒû¬`RÜW6÷-!â¾js†Ì)î«ö6÷U¹Í}HXÇîÄ}¸Šä~D±Äg¿*§Á¯Êið[’øMÊ„¿±ÙPnð«R üðþ:ˆ‡ø]ÂàWÉü0/ñˆ©Á/Ü·¿ÄžƒäeêðËÂÂ>”€¢>Dá¨3õUQ²¢C‚¢>DÙ_†?Äá—Q_=dê«R›újN2õMg´ûªfÌ}Õ,¿ì$æ>´¥¤ â>t ÉEÅ}•°¹/×Ñ=q^Åmæ>Ä9V'’9^:ÏÊŸ¹¯ÚÒ܇dö—彘#Ü܇,7žLÙ7ÎÜ—§Ö¾·Ð1—KXÇI×_£ÔCŠòÍ¿î#ûF§n«ì YüR;L¾iëgy§nðÙ2ž%¡ Yr˜ªŸKB}‹N¿$ä5!…9¡üù·ö— ,Å}>ßõ—ýo×t‡}ýZ„ßì/ûÛžrÃ¥ãýö—ý½®q…6hå´Ê¶ÓZ=a;­Šå´ÖX™VzÂδOØ™VÆÊ´–X™–}agRå ;SrœL¨âdÿOOØNhõ„ƒ&c9©5V¦•ž°3­Åv¦•±2­¿Â_6VˆY-?ã/»ÿ‚¿ìoúÎ÷ýeÿ\´¯þ²%¹ñsÑ~Æ_ö¯vò·¿ìß29þôžì¾™ úîÀyMß5_RùÝþ²±¦wLi¿è/» ûËžý¢¿ìùïÿí;Õ¿þº¿ì÷+þòÔþò=/Ù×ÿ÷^²ï“j¯ÏGÎ -üfË,ãCfßyr!=®4gv†NQoò6sc~g-6³IGïûýnL¼¿L®&IGï±î甎ޞGîçÒ)jµ¿Ÿ»tôA"³uŒŸ ˜r·Ž^z¶ÙÑ¿égÈ“Î0åÑ1j¿ªm›tô]X>):z[Ov,VcòÚÒí´Žþød”ËŽµtuÔ|tô>GÓ¶&!}Ó z Îùy€‡¦’†i‘÷OÊN3C|{™¾·¶í±k-‡ì›uôê rÂ&bAÓ-t91oßðzêö2wÒ†]ÕÐŒÓùÔ-%½Ý´Í™Âε8èÛÞ÷¼…RQ†}ké+ò ¡’Þ³À¤\)é}Çc;6)é}_;v_^¦Ã` É6ô £F‹kÉåO/f»v\Óûê@ãOL\ßÕ$¦wOnG—˜^^±nUá%”ZRfˆ´ôöqÖ°LœšÜâkf;7jé+`—–^'ÈÚyHKëfôŸù¡¥?ôU­ï.Ã)¾øÈ2§^‰éq g´ø¨vÁÒ¿;?ªÁôæÏv{Ö’–¾ayæ” «3¯ ”+µvm’ÒÛ[X»vIéOù}n¸>—WPÊ©\ƒ§Ì˜Á³#]—¤ô~ÕuKIêK»šýjÉÑààðÑå~ñ‰ªÍš·órü`y߈0Á0w\¨cAdÓbyÆÃPÌuíÞ¥¥?uÙCÃYBß@ÉnŽã ”ò–Øb {>ÊûVCo¦oD9ín8¬Ç(¥“oði3®eÂn¸™S¸߆šWPžÎáC1½ý’5L¹»|Ü… ©a1½½Î…Ubz\ÇN_\¦¾Ö.ié/yÔm8ê½ÎÅ-Žïjáo|¨oy奩é³*p#3kÉ]fÃjúóÖ×·‚hÍødÚ°@ï‡'ãÔ{‡Óú)A½/Ölý’ ¾Bn ê³ä0+Æžw2Ë%gZØèQˆl1…×Ë ê}WiÃ-çˆX¤÷cÙâ4,Ò¡¨ÏZ§õ9â2—óÕ|ã–¢>ûÅhRÔ{ãÖp+s[ý]5ÜÊÜ÷µ¹p+óàC;)ê½yj¸”ù‘—»°Ƕ>æp_©Ø°Jïç:ö°JóÊ]óǃBpÀò^n\(~¾&Ö§íºR޼ÛÓ7Nâ9Çàfæ˜Ä³±@}õ9Ùp3óØ—®Òq1óÐxŒí¸™ùY;Oߨî¬;“;–é]Þcaìoí®–è¸ù$fqÙ¾¡ÜÇ„1»ò&·?Vv\ñ@··/ C;quŒŽë™»VÆÙ隸æäPü­³ 5¡Ïš,Ó›6©¼<>~Ä6‡x¯{l4SÕWœjW̓ØN§¼×%‡?"bÃMn7˜ð¢¶ŒƒˆÃ%ÆÁ£iƒøTÃv0B_w0Žppy—p—\„ƒé#>q—Çò;‚q°>ç˜ÏÝ»zóàñ‚Á°$Çgô¿‹qIñL$˜õ$ˆËÅ6¾C$ˆ–å¦F$r0qIØÁÝ’I›T“ 2'® B3vÆD‚x¹hQ$Ĺ^$‹I‚¡FãS"AÜ!Â(Á¸…°(<:Q ‚p®?„†‚¸D€àeŒ_ ˆìqlÄ5VÜqwjAøå|q .˜àv݈[žnBž8ß¹×5䘌8ù{BÄY¬Ps .2D-r`Üí…2Bÿ'Èö"Ä-(Ü•ñ2±Aq¸ƒ âê-î,‚q[  âšeG(ˆú{¡ .}ãþÝ(ˆë·î Æ,$6¡àɵ9·=p×mćY¶“A0./‰¼‡ûJƒ`µw€`õ`ƒ`ÜyóÁãÖ}@ ‚¸‡IØ'Œ«Î"3Á¸õO +3AÈ'_ˆnÄ=®9sÈ!ê#¢òÚ‹áχ›ps ®Qã B9Âê3â^-q–8ð¼ºCÄç©3ÉqùÉP XžmãÎ&Að<$OD†B‚èº!MMá¦EæÑÁ½ ó›-‚¾á•Qpn>V Ì#eÄq÷žûn ‚æˆ4 î<•Qð‘ û¤@Tíñ2 â)2¨10TvÄ5a š¨¿00ý·%¢‰¸Ù…õ% |“ÑÐÏ‹af%­|.ÜGÈŸ‚@ÜÛD¾â54Ÿšc/C#¡M‚­ ÅÍ€üƒ2Û7ͯɀØÝ/„’Vv3àu߶ˉ/Ü…E+œ ¾äÙ*iÜš™xuÝo“ˆû d~¢®G†Àk¢­·†À8eÁ8‚ÀtÙg ÄHzÙ/.¶ ¢ºˆ’†Àüž–ˆ8üä`Äɧ7âÜÊù‚Àëѧׄ@Fd£^¸óca@TÎ`ˆ·Hí/› fƒ‹¨E Ä`×Ë&ˆÚÚÈg"Áü˜(˜íPFAû@LD}m+ ^Ýö £ zŽl–BA|~¼_(˜½«Œ‚Ûa8 ⦮hÎDAˆoß(ˆc4\‰‚Ut£ úm{± V± ª§1eÁ Þ>V« ²Lë§aE§Ë0˜=°¬‚Û¥§ ƒÕ†Á‹òô…³Ñ“󮳤Á*ºiðr¨8ˆáHK°q#‹ÍeD_ŽÉÀ8ˆ‡¸÷7bfm/»àã?R8ˆ‘ÅOiôíW‰ƒ×ÜI±;¥að^¥e0;†q£†ï V¡ŒƒèÿÜ)+ã ž:_–ÁçcÁAxåŽÜ8ˆÑ)næ­t‰ƒ¨šþÂA¼ˆ»Ú/yà.»ààf Ì‚^#Ë,è›ö’ÑkˆÉ¦Ašv9ÁàÅÙ}AÜÎ& h0'ͤÁjÓ ŠÝˆ™¢At>æO0˜—è¥Qp»µ6 ÂÅ*ÑÔ0x y^NDŽÇË(ˆB/ÄPOVÁ¹|0{†Ado{Á ªX)¬±jÄLËÖ5 溞4Ú~ZóDƒèø2Ì ñ.Κ&BÓ±‰#“Œk"D~.ZE„¸}ï\­‚i´I"D–9“™kæ7VvL„U,a:»M"¬©ÃDˆw‘ÁL„H‡ßM„^¬…_(Ò(¸íòhwíˆÑ/hÆÖ i Ä3 âr¹yeb?6b¼±£ˆsýM Dkʲ( DœSøG ¬ÅË@ˆa¥— ±–2@<ˆÆ<iâÁ¼e²,‚›>l&f—LÄA济‰ƒ(8!- ‚gëÅ ¨šX ‚Zrƒ ä…ɃèI;±M<ˆü=+¦åäÁÀ>$Dvv²žxe ›Ëb™q·Ì¯8Ä.Äáö·*”‰ζPýºœta@}(ÄÇF•ð–ŒbÀ!õG2 TŸû‹/ï+ña! -Š‚@àZ!𦛪d@½bfŒ€ã28‡¼ÒžòÁ_ºÐ}|A@PÀѺP™Éw†¶Á¹·„¡Ã†? C7[*SêY" ÆÚxM²8ZêÛSSúÜ^¦0ÔÆ™†æ; Cíl»„¡ÇóEzÊÅÄ/Cí»„¡¾"«„¡¸]âcAÀ¼}¯t¡·Ë”ºÐ¦ïnÖ…Ê)aéBqÙ‘ϺÐT¦.´ë@]B`º®,]h‰T^Úu]i Cí«²„¡Ïe›ž•¡ò¥ZÂP “qÄl[ éH3Gß·0´ÓëØ¢ Žb]he/u¡‡-ƒÒ…Þ:¸]ºP_9XºÐ&KFéB»© •Sì—,”_˜R*ߟ‹*”7k—(Wî¾E¡Ùà% í¶¦*ô´…ΪP9 NQ¨ý…—(tXÔ˜¢P{ú,U¨œ«ÿ=‡QÓ¢ÐR›J:lMJQhÊ;SjßÏ% šÖŠÿä¾´4¡– —&4Õ¦© µ¬º4¡î±¥ µó÷Ò„Ú{v‰BÕ³JjçÔ© õ凥 mÒ@”&´ ¦¿Ölø³&tÎùlºÔ„ÛpRÚuniB‡Íº© ÅÒNŽëå`yÑ_J«Kj¿×% µoì…Z*œšÐa¦5¡OJ5­ µÇýd¿%YkB»Å°b¿z‘Ð/ç—(ô9ýŒE¡öz]ªP{£.U¨”ê% }Ò6hQ¨gÃ…z –(tèxv©BëUV…Ú±p©BíÚ•ô­ØÃd‡ï[µÐÐøWÊ>ãߢËþÁÿ yÖø×69µKþk› Qæ?,‹4Ñ™ÿNñ_;äb1ùW)ž ѵ:»‡¢sË%Äl}¿¬ñ_"¡q΢4ýëåÀå) ’ë/k`Ûõ-8°ô@Äé/k âðÓŒþ‚HŸ@Ô‡´錗,[ã% ÓÑLGˆÓÑì^Àz»~N(¬VóQo4æq§åý@dçyÉB½ê$ÿ¡ÚIF© õíÉmëæHñ_õóz{¥!R  Ñ+÷·*Ô^¨ €Hx{«Bí·< ViªB9ùKD9e´*ôéV—‘Ìù² b „­ Å-÷/UèGˆNÙ^ªÐ¶Ù:jÌ1’ ˆcô/“ *§Ñ'D2‚7! b¼L‚nÏDÀ¶5G!bBÞ_˜÷C$jp/ˆ…»3Ž0[&0»…0Û7!TÃÓg{"`ÛµåJĸºÈ–B@ów8É^,‚Ûr9hðБƒåŒàáÃõ†Ú‘v C9¨3‚»-%yFð´¥Ä4¸ÝÚ·f¼ b¯´ÊBg€A™±1",˜÷¶Ùh(Ü¡yÁ 60oY(ö+o„¸ðzÑ ä}ŒcÄžæ¤ùO4xú2’4 àýÒ…çm¥(ið8å+ið¸lÈIahÓ«†«ùLƒxêeÄÎh5÷nd MbždAÄáÝ,x4TÍ‚xŠbÁ£ëcE²àÑv'lYh—Ä¿d¡ø˜'!aðè>jfÄÆ²K«B»N‰—*ôÑ=¯„ÁcØ>mÄ¡PRE¡C„‘šÐ¡“^‰‚)ÕKÄ-`ûëŒ $KâRkBÇõÅþghÙ³&thÆ+Mè³™ÐÄ‚æ-šÐþù’„b«÷±€ :'?1¤"Ôò´R„JÖX‚Ьª„¬­}Ô§Ì©h+Ah1¡™J Bgf8±¤ Û Æ± ô±¹¿¡’É— ô‘V*Qî|nY%…OÚ…‚¥¹KA(‹°E„Š‘›¬Ô„>úFóó²Ð|w²`8zٮłHEéŠ!ÂãÑ ³à¹ÝFJËBÕNYè&o]% ͇›zÃ`e0e¡G0áêñ²"?ÔñÔ KÅ(DÁ¹‹0 žöFRºP7géB·GŠ%Ãà¹}= ˜GÇ&§†Â¥ ŸJa¨å„) M%£apZºé#Q)C7Í0 B•x¾L©8Maèö|# õ1ц^š “B’…¡»¹¥0t׎e†š”ƒU9© Ýu R)CK°ie¨1¥ Íw¥8tOúKq¨NÒ/âPç9Å¡›Ï±¦8´$¥àA$Ò_§—‰«]Jj´OqhfÆ<ˆtÞÚÐ_5Kº_>ÉgmhʦKêc­© Í^›ÚÐÌqjCw‰Omè®óЋ6t—ôÒÒЊbiè~XPšÒPç&¥¡ÛðáCICw¹Ë*ihʇSZ SKCK©ji¨¯´,mhÆImh¦SÚPWiÊC÷æ“…Ö‡îþð–úÐÔ™§>´âXºÛ‚i}èîO ©ͳ©Ý}æ3õ¡6(”>4N}hŠðSZq¬Ýýé#õ¡{ÿBƒKëC³RSŠ*âCéCwŸ¦³@î|ßÑÝç”S š¢æˆîþÐ’ÑÃS ºë¼} DáIŽY!šµœ Ñ”á§B4ë4¢‡¿¶¦B4Ë™ Ñcÿªu:¥=òD ¢‡®;+…è¦[]J!ºë†¹RˆnúÚQl’ÅQ/%õ@/‰¨Åï%õôUQÏœ)͇R"ê5­$¢›ÔÆ%Í2¤DŸ}b‰¨ç¼ïøÌ^Àï¤Ïì¿óÒv7ÁïöQª¿‡‡²¢ƒ½­€».X.îk¶,¤ÐW”´ Nîa`ZzYáÿ¨½Èï[ÿ0û³;ŽÈ®'›„Ÿ’‚ÂS‰Ä¡òãuº‡^ûu °T” ~ ‚ÂüË;LKîó†(… sËiji%õ!¸‚î·1T܇F<ÞBнټ(ðK r AO¤*!¨-­&¿”U'ùýq2"?H`÷—~¦Ÿ—!|ÈRÐÇ>„L~áŠúc¿k{Ô• ~'Ô/3àµé›$?(`™0Í€›Ïª¥70‚µ çng0b¿óÙLzÖ‚î²§tÓ×Â_’‚¢{¿ÜÃàVfÒvJA7÷딂ºT«¤ ØG‘‚®ä‡÷èß­=-¶N(gè)¡^é@óó-ÝåR9e Ørµ¬½u¿Wé@ÝÂKë@Áw¯Ã€ð¶ÃFXu oß0ኔ¤ghúEJè~š­=©î*hJ—~¡p›:ЇÛë@qíñË:Ðã‘'Ë@áKé…~×a›Ñó‡ÞdèyÈÞ(èµÛ+U ¾Ê»T çe«¥U ³Çî/hêfJZq¬½ëB­=t+C©@Ïf´ ô8Íy©=¬µ ôÔU÷¥…CyéB©µ½T §…n©eÕ.èwé§% ×n¦³¾>ìƒ ýyuì/`öüEjÉX*@¯Ëhhè}Y[j¨û„ ùî€ZT¾@­ŠJhv€ÞÛ—ó€y«D @¯Ûôh(üÈæ'èhæI+@¯ÛhhèýKSzX_—ÐËÊ®€f2¥•À©4 ¾m¾4 ¾n¾4 ¾£4 ÷µ˜Ð]ÎJÊ+4ê»öÃ^^,=te]Q–úב@xPÞÞØ7ÒÂgèá㲩ÝÜ«Sºñ»Â¾'¨Æ¾G‡ ûÛü„}c´„%öqç±p_½;¹ïáIü¾gscߣ³Æ>”‰Ï˜úð¹…/²Ô+EQßÐMVE}Oûr 0ó›Ѓ'Šù›S _}oæ:„SÌ÷Ø®™Ì‡ñøb¾ª>3ߣ+ÒJºk#XÌ7|Þ/™ïÑ-oÅ|ú“±¬=(^)ä{l²LèîC—‰|>îSÈW ù3òU7NäÃî+ò寠’&¢š‘ïÙ%fHä«8Ö€zÉ.äóa£Ô€n wF¾qÑ€Vµ'òá¸6üY áàKŠR]o¨·h…|8œð>øtÛûŒ|å¼E »U– tÛìáÅ*Ð- ùºœÀòጃΠùºn!*è¦KKºIP*ÐmØ‹ï¹L…Vn—úB>î}W(|¡‘­­WYºÉ$¾¸ËŽ+gîÕKõ¿4×êÖqÒùõ×(õ¢|óį»Ë-Еf†,Ω&×´õ³œSѾx¹Î5!…9¡üY =ƒ-¥tȒÔPýü[»Ë;®¾¼~³»ìúwŽû/yÎþ&î/8ÑþYWÃßv¥¸½¨¿| ¯ëàØøÛç¶RZüd3¥ÕM¶SªHJéåqÛ)•—l¥´8ÉΔ2’SZým;¥ô’­„ÊIv¦ã(NfñµíQ²™Ìê ;SFRB/_ÛN©üc+¥Å=v¦”‘œÒ_áC×Òìíù_݇öo™1zÏ€ßÌ?}w°¼æÌï•/©ünÚ}®…sÿÙs»»üõ÷ùׯúÏF¤oüg¿SÛó¯–}ãIûýZzÒž{ÛSž´øÕ“6Âþ5ÿú‡ï„Ù“öñü²'í9ìø½ […pŸÆxÒ+?÷[B‹®³’qk—ì+tQ0Cø÷–­8®ŠÕ¾{mÇ;ñ½Í{Ǹ]…'¯yÀ:qÆG•ëãÐÑë[;ë>Î=™{qéƒîúV¿¸¥3‹¹4èìõÐem«f(77œî£Kx¿éÇìiߌè .åB¹yú‹ô³IxHÞá@.”›°0Î!á½öç´Cf&úsé“>=v†Ø#³]ð Âû{8&áýl=~åº?¹qÖîÏð¾é»lÇîøâÖT[cÛ(¼ïºxjl»=27ª æä­n§ŽŒí´òž6òÙ˜vÈ,Cÿ ÑG7ë®ÇvSxoéøØš„÷]vþ *Þw]¹>àçm´:g1¶Gºû¦o¹w­Æ7·®›².¦?f™q.ƒožƒ®.<å=¾ˆò¡ËÊ{yE¸žÊ{7Æ~¼ªòàË›•÷28ðж¾iè“›;ñØ+ïzÊ›PÞ[h?Ž]ßÜ.m˜ÇqHzoâpRy¯cã¸$¼™> ‘ðÞÇ<Å'·J¶Ù³ÌPÎÎUÍñsHv_É>’Ý"H B­iuú#´äýÁ0nyâcÛÅS¼ã<%¹·Ú{À›Jˆ5›<¦Ìjî}¼cœ·4÷V(޳Is?äbton©ûwÆÒÜ+»÷ò­:®M‚ûL“Rî{×À˜ Á=¾«0äü"¸áÚábf.¦séc›¿UŽØ˜í%{°R\‹Ì|àØ£÷ß4¤¸·lÀÞ@©¦¬¦Gô©¸w©pä)÷Ù,˜•¤z¿å”äÞ§n\¡n:KÄ¡ª{[³ƒ)($÷ÏN®1¿Hîc s‡%÷ìá‘ ÕˆIy ßÞcyBÏPÜ?rá4Ú.Åý#çt£VÜ«úÚiÁ½nÀí‚àÞÇ\æO í£ÝÜg©A&1mû Ó\ä†9‡urÃüÈuÙhÜ0?î¾É 3GNßåƒ9Gu?äƒù¡ÓãÑO¹`Άì§\0g^°(Ó‹¾Lí#6´ån~`MŽ9û‘uy`QÌYq£Ž/p­c<-¥+*cçQëqpÅãfŸýã”f™ò¿œ¯—ü/g‰°ÇŒíã?¦Ø¸K˜cëñ®WqaCßÙl£ãÑIëûP§‡Ý÷ÒD¶•¹ÕIëûѲ p|g³ýe<'ý/çrñœò¿ì£póM:i}7?tËÿò-åxšü/çàÁŠs¶O°ŒgXiï>ñ<ò¿ì§žm“ÿe×û³íò¿ì.ûl‡ü/GW{ >nZcl?pÛ×Nòà¾f­ëŒqëœuÓìÁ¡Wž•Òé© 2ÏJñ5CŽ—q9rÊ¡ò nÌÚ]•>Ç#§Ë]Ú'¼6æ7–«k2J]9äwÙ{¶®ÝbÚî²?p¸v=ksbŸM_Gº æC³¦Õžµ¦ƒRÒ•=a0?×êÃGøçXzãù¼ªá¢€#jódÈ~äõ'ƒ!0ÂÝuî¹4¦í˜'Ÿ‹—ÌG6Žýûž{%{wÎÙŽb8oicY&¸ûèm1£>8¨Óv\j‹¬PáDJí rÌÚÞÊ>XWG+OP‚Ê;øøÆ³v—ÓÊgÏ{Y7ó[ Ž/þ¿Õ]¶y/œZ îÍ…¬‰‹„{ñÅ›ü´nÓøMV´7C䛯´ß»éßÍ´‡[mcÆOÚÛ6éU’ö0‘EK$ím»|å$íá°9Ò´·ºÃ8i3àNjím‡œ'íÅ—tÒ§ho;Oɱ‚ö¶³þD{ÛuD{ˆÓ^´·Ò¾&ím—ö\I{Hg¼ho»´¡JÚÃ]½qoyH¸·Ý·Ë¸‡§˜á^%cÜÃCܵ÷° q;aÜCÈEæï!îeÌ{Û\¿E¸‡‡¸•4îEQ˜°p'y¸éî!€bÞË"÷ð™%~â^žJÜC÷^Æ=H-ÆÊ{È/éÂÀ·<$àKMZâ@ |•cß"æ«bšù¬í`ìÛšÔ&öÕSÆ><Å‚šûðÔÆq_hJlä>$šûÒUcr_eÙÜ·„ˆû–W ý*ŽÑ¯ªÐè·5yÙMôÓg²ý²ë˜ü¥},à·<#ð[Ò%ùmM©“ü…6ù-!"?ûôOð«º1øUøáºp¦bð«v1øUEüP}쀿,¥¹¯JiðCH'Q üªÜ¿z¹É¯â˜ü0Ï+Dä·Äú¡†ýª‡ý– ýªKýj˜ýðû£ÑO…Ø%ѯú¾Ñét˜èÙ»"ú«Ö4þÕÛËS¿*¸ðoy•ðoÉŽð¯&ã_U†ñ¯: ñ¯Š.D– °z… °²c¬R—!à’²°ÚƬDw#àò.! Ò!«µŒ€K!`öd`Õº °†• é2аŠ`DÈ«P@ŠßÛ €[{Ñ_–1é/*é/»~`&›˜Þl €ËC"@)0‹”¸„ˆ³?&fë³:«†@d¬iÌ®•˜M™¸ÄªöŒ€9Aü·äDü—Ý#ù/;^ò_¶£ù¯êÅüW-`þ[â½KþCÓ°‘̈¢`öÄÀª:`v¼@•ÚôW™3ýUÝšþ°qéâÁGsw>%úËÍWÒ_Õ§ñoyJøW­füCëü|”½`šä?„Ü/þËIMü·ÄÿUŸ7VfŒ€Ø[‹…€U3à’1`u 3`uC`u{C`½]X ÕP&@ŒDB¹ °†­ 0+ïw8ËN£ßŽ/›âÛà‡}m‡ì}éÞ:í}8ið¼ì}P¾RZdľ6HĘ7È$âî—ûeîÃÖ—"&àAyÚ€ÔÉD9 ŽB÷€y8"!T±©Þ™Ã8×ëƒê €¸^çz™û*Žp‰#„ —vNàGˆtèÁxPéµ`^q“RáâR­çïy\Ȉ~ëâ!L€8&"  !üÖiÄSbÂË7ît}¬7"„_6E€K2íË•;I€ËC"À%;BÀʲ0k'Oñƒ­0ë"0ë+pIY X94"D)‹³Í€y®&p ÖC†Àƒ8j¬–2V~E€•ª =2’«Ø&ÀåÍ"À%a`5ƒ Ї‡«] €Ù#r¼0oÌJ¬¶3®!<_¥2"äf2ÀååÀD €ÑSÀÊ 0]V$¢–¹4"dÙþªX&À¼+°rhDȳ"`5¨° aDÂý…€U,3`eÇ X/VÉÍ€x¹,†bÀœª’"rV UrCà"Ä»"¬,+?†ÀJÇX}ÙXUXUlÄØà «9 am—ÌsÖNDò§!q †À\3«J šL€K""Àå ˆ8&ÀªN`Õ„ °:¶ °â˜ñr p‰"¬Æ¸†<šÄÝ*&Àê&À*„ °*ÝXímTeÿªŸÿ–á_ qã_µœø¯Þlþ«Ê2ÿU'1V¥«¥ €K`Õ0Ç]2`îN’óeþt¼-€Ž úË"šþr0%ýåÌ’ø·<$ü˦Mü[²&üË7þÕ«Œ9e%þeGKüË’ø·„ÿPlY…K`ø$À„ È!_.¬dÌ€•Œ/_M€UFÀìÒ‰€¹¶%.銳«%fö„€ÕAŒ€9'V+ë)S`åÏXå6柘¹1. «†ÀjqC`®á 9êêÁ&ÀûI€U™&À“I€•}`Ž·$ÀÊ­ °ªÓ˜ã6 °*ØXù7&g$V~D€õr`ÔXÙ1Ö2fëþЇìR{òæÔ_ ?xú(ò;6]?Yä'mdA“_ÒM’_†$úyþ-ô»Ì”‰~×e¬3ú]º4±Ðï¾Ó(ô»uUA¡'ëýnyþ/ô»uåÐïÖ•&…~M.ê ýÚn›Ñ¯Y›èך­xF¿v¥®Ów­–5Pè×l$Ü^jÏÌ^rŸSIì»e/ìkTïõݺ´¥¨@!C ©Ož' úš<ùôe£$ôÙË_A_Óu}P}'¡Ï>- ú<œ úÚKí‰ÁBlMâó·E|Møš®æ+â«÷˜ør&ñµþE‘ÏÄ—íoâóìSÄ×,Ó4ðU*¾ì¯ |í|ýªÊ“÷¯ç(ܳ_ŽÖi½¼$¯p/NÜs—HÚÛt7‘hÏW&íݺϫhÏ™KØs’õÜŸõ*#F½¦† õrð'ê5 eõrt%êyé)Ú˱“´ç[Ÿ“öt±vÁ^¥bØ»åÁ±`ïnšãö|vÁz)C{÷¡Y%a/k8a¯É OÁ^Óuõ{Ù‹ö\ÇÉz99%ë儬ç–JÚ›5±‘ÛL{vÆY´w7K.M{ÙËM{ÞíUÓžWü¢=X^zO¤Ã>´—Ý/i/Û7iÏUZ´W!¦=¿½€Ï{’>ܾGë™oÓ-fÉ|®äb>#y™ü²[ó¹ó¹#óe–Í|·n–*æÓºQÈçÊ)ä»yŒ¤ˆÏ5ZÄç>ZÄWɘø4Ä ø²”¾}èsuß-XŸ{vŸ{W"Ÿ· …|êØE|YWI|Z øn°)àËê4ñy2)âóö£ˆ¯é¢Ÿ"¾,wŸ³—À癬€¯ÉÝTŸÃ">!¯’1ðy…/à˦Kà«WqšðÏd¾¬ðd¾ìÉ|ž\Šù<ž‹ù2{É|MQ‹ù*e3_Óý‚Å|íø¢üÌ«»‹ù3µàŸNø,ø'ÅCáŸÏaþY]ø×^ÂÏ”ÉûY[ì×ì%Ù¯¥O³_Å1ûáÀòËÏ €ä.ë" &böÃç÷•ýpAÑ›ýÚ°ò2ÙoSÝ%ûµaç0f?`åSf¿|y²_׉Ղ¿Šcøk>™ð×|åVŸã$ü9JÁß|å'ü9ƒ}ÓWä„¿Šcøs–þê݆¿z•á¯ÉËtÁ_{¾+Ë ð¯ú2ÖS ù®„¿,DÂ_çElÅ~õÙ/£äÉ¿|“Oþ¹&ýêEyôÏE¨£êLËÑ?WEý˱_äѿǂÍ<ú—qòè_†äÑ¿|yýË8yôÏ­WGÿ\ˆd?WNüË(yòÏÕU'ÿ\_uòϯʓ.Uüsþêä_&“èçÜäÁ¿|(þùME~z¨Îý9ÃuîO#¯À/ß]ÿüª?'œÿt+@üËÌäÁ¿L%þenÌ}§¸Ï¯¸ÏÝØÜ—¯ª“ÎMqŸ2\ÿò¡<øç~S'ÿ2NbŸ“Ƀ®¬:øç‡êà_†û² ÔÁ?÷­:ø—OñàŸæøåàŸëªþe"yð/Còà_¾:þeHüsMÔÁ?ÍóËÁ?ç§þ )áëà_ÆÉƒn˜:ø—)ûàß°•/þåCyð«×rî/SÉs.CûsÂyî/£ä¹?†:÷W!>÷çbÖ¹¿Œ“çþÜ4uîÏUQçþ2<÷熨sŽSçþœç:÷ç”ëÜ_úlñÁ¿|(þùUuðÏ…¨“’'ÿÜuò/_ž'ÿ2$Oþé©åðŸR^ÿ©³/‡ÿ”Îrø/ÓÉÃìuö/Sɳù¦<ü§ÊYÿ©.–Ãù¦<ü§­Ã‡ÿüò:ü§j_ÿåSyøÏ/¯Ã’‡ÿ2$Ïÿ9ƒuþ/Cò †ÄrÐUZGÕ¿–#€ÎaôËë`…<9ë!ƒ_f'Á¯B ~õ”Ïf”<˜!yÐe¨3€®å:è–¨c€Îr’ßò¼gòb?w¯:èìÔ)À|UžÌ8y 0³ü¬‹ér Ð]²N:‘:˜qò`¦“§3ŽÑ¯ÒÉS€.wt¹ë`¦“§ó©<è:èvÈS€%Oº&ê  _^3$>öö›þ±÷mÇ•Z‹Ö} ½]¼½:Nz»þ¥R”ožøuÿØû,nXÒtÈâÚar;[?ËõœF QxeN!kB sBùsMhn±_ÉÄïW"É$øãoí{Ðþkýb_¿Ã/öuýU~±¿Ó…&4Ωéå0ø»}áw,¥UN¯ÖêõÚi-±”Ö+–ÓJ·×™Öâ÷:ÓªXNkå´ìú:“*ß×™RÆqBKŒt}í„Vß×9š*–’zÅrZéü:ÓZ¼_gZËiý>²Ÿwôý/ï#û·Ìš?½gÁoæÈŸ¾?pÖyógFÍ;•ßí#{Çýs‡ù‹~²á!úŸ¾çÄú?ÙoÖ ?Ùí;©ýåÿ§Þ±g‹Ð[Æmð÷: ;¾Š… w†\Ü— ùk›!qQß.ów‹ïnû­ëOfüíAЦT3ŽÂÛ‹fÀìÐùøhü¾ÛFݰ´i¤+.oÌ̱Sw?t}ý ™E™½®Óš!,®xڔΥ umç ð—NêKõ ‰ë-/Yæoø§{LJ¬›Ç¡tY†ó–cé‰,¼‚—B†È“ì ÁÍ›¼GQpйµd†œ¼ÔŒ÷#EÈuóþ˜¡ú;YÜ¢^ÖòPª3ÇÅTG¶É9è›ïØÝŽqÑ ŸyX½qÛÊr­B˜}¼M!Ì>.‡RnyEQ\7˜2n¿j¼ëRœqá•\ÊOÜε¸(!íŒ"Aá«^®uP¢1Ç­,¾lþ†×gäåv“ÜÛÆ[Útµ BxTq Ù—HÝŃ]Jw™Ôen•{g…à/¦£}âW™õ«K©=C ç=^›BpBq$Wœ!Q†®Öü­2ti=ç¾pÛ"dðªNƆ{¬Çé±0fàîrËÉg° éÒw†¸ ·§šq¶˜$ðB6ÀëDÖñ¦87.[sXoÊkAØ4ÜmZ€stQ4éñ¸÷„{s£Žÿ èÎ/û¬7e1Ô2µbc!ä¦Tc?²#µ®’ ƒ¨žï àæQL:ÆëÄÇšF(ŒÝ´©g "[0û0†Ÿ°éRˆÏ/8M8õá bŠÜœOtQ>§Æ‰ú‰.ðí}hb%E)Oô5žû‡”“6à^±ùñM¡ gæˆ©ç²ø.‡MC_„ßå‹ð6çèaRk.ßÐäû¦È€&ïZÜ÷Œ”KŽÚoÊs„IØ ««ž8Mïñ¢ë`œeJ«±_5ízS‚Kžûïï8yàâ÷ç[ý0HͦØò¤ÃÝ ríG£\|"—ÞÚóbõã0D¶Üåê+ª)R§p9ãLh¤hûÑ›r.[Ä1ìÄ—ÿ)G›½)aAÓÞˆ÷·LÈfÁWòü´e›1ÂA|Žm]îw|j:«r*Ësð‰¸©šêÉ#ÿ}ôÏ™hÓ} 'Êê©Çà`æ›_}‡[èÍa}{ŸçÜUÿ¦ oŠê¿-ê+fA¸ª«Øûd¿Óν7å9hSË<ÏÃ~§ÝRog• ýpóš€å/õVÜvñ^ÊÒŸ’‚_£Ïwö»Ë73Ü'¼¿gãCѾ¡7Å&hkÜ›bý'B#7Ž!œ¼)RÜÛ÷í:nÅo¹h“?§ç”ûµ2¡é¸ç7¥w§ðÞ8•ù¡ ÔŒÀçM_ßßëâƒÒî…7å>ýXô0§,hÚ†‡6±{ð;«·MêGëäLèЦKŒ“}MNûoJã\N'i¾ ¶@|ß™Ðäoû¦Ä·xÞ])ë¼isÙûûމžè¥RžƒF制hBž"ý_2aÒ7.F¿<ôÜ×üaÔñÌ㚉“™Oï;TÎh? ·lx»‰ï6ôÃußêj²_drÊðpÔ½ÿÏqÿ0j?®¿‚¿)®¿‚çjMÀ7@öF>ŸŸë]!%ñ+Lä›Ï•S| ߌy€ròMœmÀ ä›Ï8,D¾8ƒ^ä¸U="Ržò!z»0[̇^$ä;šç\F>LnMoD>¤ÜE[ï˜)zrb¾··øÉ‰ù¢^̇«D:Á|È¡g+æÃ íZóáYšÕÈKHae„|%¡Q6yrYHÄWz€ˆÓ|½¨"¾šBZ øRº(•ćÑe_é5">¤ôñeÐæ$>D¿×½E|W?‰¯¦ø°!E:•ˆy´%âÃÛ«áGÈxqSà̇ù2>¿˜;àŽó!ÅEæËx¡É|?¡Ï;é’ùŠ_Ë1b>Üúþ0_yÄ|G3ú˜ùj™)†¾½,Iè;è\óÛ†>¼SšÂ ú¢I¾ )Â.A_M!3Õ«ÈL5…ÐWS}D5íôeŒÛ„¾š6dûúp(f‚>\!Hô!E$êÃUšÞžÛcš§Ú‚>¤Œôåa }%EÔW®õÕ<6A• ê+ûŽqfb®­‹ûJCˆû02÷í7ÊÜg_MòÄ}ðçPˆûö;fîCJÿp_n'÷íwÎÜ·ß9ƒ6J œ~û-4ùÕ«ˆ~ynF¢_n¸LöÃUâj±_M!8!Eóz±ß~Í~x{Ï5‡mÈ y· ›2IN{œ0üÕr ûKaøË3Dþr,1ûåñ É~% Á©f!û•úûÕßd¿zͶ@õ¶@a;’ýppùýa¿’GìŸ# ‚¿ò:O› CÍþÐÆÏþÊýêHsʃýÄýp'LF?¼¢¡nÜ ƒœõ\eú• ýGF ý\q_-ĵOn^Y{Ô?̵„àÞZúMð«¥üð Æ~˜'‚1ÐL¼?”c<#8ÁH­üJïø¡>Z{ø9‚yr¶•³%îu}þ?´ö 'ê+OMØ·/ö•‹×>LJg×^ZØê÷ÿvTl“_à¸?b_7Ú[ì;[ól–b,—øGbßuZ¶Ö÷ŒôÁ‘ØwœžðZìsX³-öaÅ ÒúzN¾¬õáÀ?-@1]DÙUbZž”Öw=Í’Ph}yÜoj}p88Yë;rºk­ï8,‰ü®Ç‹´©õ½ÿ¬¯ÖwÉyûÀ‚ÊCòƒ:i©Žè×­˜üPÌ%ÈdÔÈ™…D¨¤kXCùáóæê’üÚË^¦:’_|Í‚4àò¢œÉ¯^EnÂgRZ…ȯ£"?< SÉÁïtÁ¯µæ„?8â oüZ)’šZKáYà×pìžðŒà‡<–í~hdÍ7~­'¨ üZÏ"ðCm´.!ðƒB¬i¾È.þ‚b‘_éÔA~­/7ƒÈ)Ò@D~­w÷‘_CŸV Ñ5–Ð(ôCŠ!Žè·EáЯõ©I‰Ñ¯õÇo”оҫ-÷½4µ²Ð¯õÇRT êgéÌ6Ü)ÓÉTá+÷ËŽb?¤èÉHîCÉN!üa6ueÃ^ÀX¶¡»þB¹è^'”,üeä5Ë}w…h„¿6ÖrNÝV¯üµyyµÜ÷æQ¯üaŸ‡(“ì£ÄÅb¿z+™0–Ù^ì÷¾øYA‚S›Gª†'T§È}È @#ù¡ašRH~v-Éehx´Ü7­$ýPKyD¿6ï„A¢î嫈~ŦÇdó ý½žÛè‡<ú†ú!fâõA¿#Êo›ü )üa–§}‡M8 "?xõê,òÃUëC~È£i½Èo7…É/vñˆÚlBOeî”Ùú°ùµé/€É/<Œ…c$¿rg‘R4Ý=mÁÀsn$6ˆüp+C(¹iw|“RÄ"?\uÈ7WÉM¸­6\Œ?9­>‰üP3É×Å)š¸Šü¶I— P7÷•‡-îCÝLlä¾ýî˜ûP5ž¸¯<„à>ø'<îkë0ˆûb‘Ì„;­÷¡œë#ùá*ÍwÅ}¥ËˆûÚjZV6÷•ú‰ûJû‰ûpKÍ*­ù¥û¹9ôötÛ`ÿsR$cˆûJW÷ÕržÃŽN¾7¹õ˜ŒßÙ ðÛî[?¸PIíùD~(Gsö ¿ý™0ù¡ßˆë‡mèî'"?¤X”$8í‘Dàw­®™¿¸¯X î+m.îƒÝ¦E[+â>lЖ¸%ûªÙØÏGõ«÷&ú•vú5LnUc’S)G臾%aKè—ñmýŠ ¢¿2/Û½_ôWïEtŠÍb»u}†KÑJª 鯼g¢¿bçm./¸‰þjòì”U¢¿Ò·,ûåwËôWÆCá_ù Ü´áJ½ÏÏØ'l1xý¶ù…Jž–áEXâ±Wæiã3uø‹ˆØ[î‹&ý8x^éÎ)Ïa“Ì—ÛÝ“ù2¶Y2_†^IèËG }ïäÆna‚¾ãÉy™ ï¸¤÷æ©°Z;…ÔZÁ£lxr%ê;·¯©ï˜xÖÔw<bM}ø\[Ý#õGºº‰úÎãH§IÚ€`V÷MÈ£¹¥¨åhŽ*ê‹}cêCŠÀJÔwͬ-ìÞðâãùNTŒA}8æêùøx"ÇúPf ¢*Bß{åÛÌw—SwõÓõUÌWSˆL'ŽÃž‘ù¢ùž˜/f?º¡¯¦Ð‚ý;³¿œ{|<\“)ϯßR}¸JP5lÁm1zØ‚ÇsOA_-‡Ð‡<ºˆÌ‡„õQûÞY“Üòùj¶ ï#ä+uòÁn%øêE$>dé’äH|å"Õ¿d!,¡rçÇ¿óŒÍ¯¿mÞÃEíãÞ‰‹Ì¨à=ä°· ˜ÿdÀùƒ{gà—¼‡)ä=TÏ. û¼±,yï›Ö|Ä{õî„¥ýT„{;!hï<¯ÒH{5… Åž-pã öÎóJõ°‡  ÇGéCkˆ¤½z+°oeòYŠöj²R¹•>oqNÞ‹¬±x¥X¢³ =ɰTË%,!E q¯LÜCŠ„Qá^1óÙ&¨¹› 5ííÖ"ííbM{¨¯¡Œ¸Wól \ʶÀyK(GüGXB‚¦Ó¢½šBÚÛeÚ+yN›Ð“ÿλn˜ í¡*æ6Ò^6¯a¯JØ+7>]ÿ]Ì6À7&,ÕÒRDa¢½Òž¢½r•h¯ÜëºÖ7Gû6”h¯æÎç«I{5i¯ÞǸ˘÷j²RÖGç+­%Þ+VŠ÷ÊÝ[û¡Û°SÈJõ²RiOñÞîW½š…¸÷>TO®›MÈ<½šBT*&Xæ{rò*ÜÛ7Ú«—l œ²-°¦GR*V´W*,ÚCŠoMÚ+WmBÿÐÞ©K„zÅF¡^M!ê• ê• õÊc6À_£^é4B½=òõÊ!ÖsmzÅ@ |ŽE’ ·Û_œWn,ÎÛ#09ïüºvæWÝŒWZqºêyâQi#«{ŠT’„WI„·@€—ŸHók¶\ñ´_p·+lW«A¶+uÛí¡níº+‹Ð®ô¡]M!íˆÑ®æ!Úí–Ùíi‚ÉnÏ—Iv¥PÚ›œLve¤Ú«…v¥¡¼Á7g|F;tc­tYÛÓ#û'â^Ê O‚Šy¤ w‘ô9þÛÒÞ žÿ`ÞÛ¸‰Öö–­íVË«¶÷|0/(Üâ^·Â›â|3~÷"†Òo›ò2ú¿µ½‘[²¬í9¦|RbŽ[W” [3´¶7Ó M”‡K>NX’g o¯yòjÁ„<óè*™°ZnœZr2Õ…¶·ìmÊÚʗòÊFIaB]¶ÙÓ¬% nÏê„y×}9ŒtÝÛ7TÊ¢õ‰Ð¤ìa¶÷ÙÇwÝwîì îåÆ ÊÇüúH{×s¹‰òðdžO'b€éyØ z\:¯ç°s¦ëŸ~«b<ÜÉ⯔KÆC‚NºÞsIG®ÿñŠÂ,ĻޗÍÚ y„­b¼ëÉ51R4‡ã]8™ZydÀJÏaA®úªz¸Ê HÊ+ !Ê‹®¯”çü¨ÙVõoˆJUïÆÔå­ê-Ý5¥ˆÃþÐVõû§¤ªw|ü9!‰[À“¤w¤,iIïH§ZKzGn¾ã•¿”ôŽéípd¼ëñðaAïHçÝ{Wÿùîß+¥JÐ;¶6'Egö|öïÁ¦çÃxÅ+zåîÒÃÐÕB=ìÜ Ùñ|:„5½ÝVb¼vžI­éç;øÎ–žô°í»`IïÌU6KzçLꓤwÚE%%½íx`I/+˜’èQ0zØ[îòâMtÒôòN©é[“ g:ÝYÓËæKMïL6kzgªsÖôÎt±³¦w¦€tn$ôPÓ;½Œ’Þ®Š%½3wh‰òò¨Ê-é½WigÒ¹ PSYÓ+7–$v¦‡¢5½÷Ûþ|(¯9ÌÖôv ­é¥#Š4½mtP^»R)²¦wæ¶.kz×ùƒ7gM‘¦w5«õòCyðxéÞ×GEl·U½ëòú¾U½ëò¾D«zgj™TõFBgìšeQïLéâÞù!<<)!Vô°>ª½RôÎÔ9¬èëÄCŠJŠÞ[ÿñÙŇrÔÂVôÒkGŠ^Öß‚^öÄþ­¾Å¼ý˜-æíF±˜·½Å¼+‹yWîèÞ¡dËr’ÂrÐK1ïJ™ÐbÞåuo‰y×[øÊcµ˜wuï´³˜÷1•BLºÚí‡"ÄCwÕ®4ËyXünIÎ ·hCΊRÍÃÞÀgéÑVóö“ Ê»$;YÊˈ)åí^g)•@ìH·s+y×ðYq^i<+y—ç©©ä]¹ÁÌJÞ¹}2wý­J+W… v¶•¼ërƒ[ÉÃÎU•"v­äí‡k%ïÈM§Vò°òƒ{˜r_%oßËJ^Écv9aÃuûó@%ƒÆ‡÷¶ç]JyGî µ”·K±”wæöBKy—uŒ”òÜÂ5°Ù…øwœÓ[ì.Í”g6û!˾ÈÍ~¼ÂAaþF€³÷ãùL)Û)5¤˜Ò3(–¸d/ÛĺRR>1- òÏRP¿b2W­UJ-Hi.(þ‡:‹yôüw:ÃYËÿß:û}—º"dÂ7êÓÏú:ú7—Ê*!ÌTÖ'„™Ê*¹TÖ'—ËÚ!Ì\V aæ²v.—Us¹¬ bæ¢J3—”y\PÉãe‡0SAŸf~»v.õÉå²v3—U¹¬Ëeý;wxÿÏèìoŒ¢ÿøŽŠ¿3ÿñó§Ž£ðÖ|Kùç]=‚ëÿÿ*Ðٙ͟…<û·ÿBž]ˆbƒjF,t¾Žá6$Âk VìŽt!ŽÀ;ÀŠŽ?¼#¦jóÖõk̘©­i·ù7%fš8b¨˜3Í{YU¿ÆSµûð¦±kıôïa ƒ®yÄT ᢗRΘªaÿ>=®É1ÔOÿ“—¸ÞÚ<<´ ~#0ì7ÁÅß#&jÏò¾ökΘ¨!2´ 1OC–®BVÌÓžÇnAפÏã ö5À8S«'×Âò R¦æO×:cžö¾ZA~q°Åh; ׊ˆ7œ\Þ…ØG¨R„ûàñBÓ¿?áÄÒTÄŒiÚ=M×Â!=È£óJÞ”;bIbõüÔmLÓîp˜`É7 €D@Y¼yçå/4'pzÝØëý¦4{Ç\76ñ Åþ’ר¼ï<#o$ºõý7&¼)9å»×)ÍzÅuß+ŒjæŒë~"ªlÉót±¥Iàïd¥‡QˆÎÊÚ<²K·º*ö.„…`ÁO?èuˆ°®gÄ‚ŽQ¿Þñ÷†€ Ç†È‚'SˆïÈMº ®G&Lï9º©“)øÙŽc„EËé- Å1ÝZ„ÀºœÄ÷¿Fu¹–ÖŽ0`!®:+|Þn–Ó•¬¢œ'S&~/{±·8Ùì—8 ƒ¯×;D®0éæâMpý!W;m‚{Z ÁëSð‰=6H¹µ@ÐðTaBV誘¤ÄÍ aí” ð|»”Bn»‰µjRìYØÞ›°e¸mêz“_0´iŠ”^ÌaÔ²·ñ˘4á+¹]ãýè5¦8,]‹Å-VOFáãÇ|iì Q:ë)jZÑjM¸p<ŠÊ °T®kîÅ+šj÷̰ ¸F£±¨{¡Œ¡±¨Åú†ak²ÀáGZ³S/jkýdJÞª ,VÝ ¨Î”Xn{šÃ¶ð‚fcéÀG÷aCpÈA“ü®¼Ÿdü´Kn›®ÿ¥åã6wý¹|Ü&†ýÏ{!¢=À‘6NËÄ 1´ºú¦<º[o"v:‡Ó[WÉ„1ÊñÍeÌzN{î¶; ˆR4rß2àm`}|îɉÐr\Í÷µ]þÀrM³Ý÷¤UM j ÉxPMKKí‘ ïL†3”ö„ ‘¢Ñ‡nÅ´áÑRs{?Ë|pœ6|•ÏO—ÀWùb §#oÊÃDzS†Ú%b¦÷y2Ï͹Ðt׆#·&ZÇÇ!Vývwœ¹u×.ÐÙ€?)´ÁwêÚÔcW4ʘêÔŸå‹¥rA­Ã˱±Ëv]% º‡~Ø‚¡çÒáý08¼sRÐá=ù\øaéá#óK˜ÅW¼ãÀ­›S¡KW5NçàÀ»Ÿa6ðñ§LXÞ#ÐñYFÊe%¢ã³|qÖt£Å©P¾cýä{*ÑO™ð>vã~Ù„Ç%ƒ…æ§zy®æÂ[7kx)a ~‰£Ãرûûe~çØ·Wµû%ö£Âw9æ±S߉ƒ‹o©~7§C€v›ÐÅ 1|.ZìØï|o6!o%¤ÆÌ±“ÝÿfÌ31ß|Þ©u»’ù"€§2„¾‹ƒâ7BߎÐdè‹£ˆŽÔw̵S&âNzõ»©oï¥0õ·÷Ášú°OB*êÛž~¦¾íüOêÛŽ³¤>ÜçQ¤>Lc.œr¥÷¢´±o»«ûÎóˆúøNü–з‚¢ÄUǰE·øŒÐ‡¸ Bß›rk¬ô½åta5˜ïýé ×b¾÷ÖžÌ÷þôN`3°Ëe.ºba¶Rnºbuó>‘oaØ0à±úgó}!ß §*^Eæ[:fï·d¾3t6 ™o¡ÃN]æ;‰É„G°i[ô&ºãN‹ùâNzd¾(W d¾°A¤Hæ‹{qLóŽÔéÛàgf>|€Ôí } ãøRЇ»/C\éûJ ›­òlÓt)†£‘ úâN—èì /ýð>5qßåq@ÜWZPÜ^lš•¶áürßÂÈ;tÕ #úж˜À¾Ï]鳉…} Ý£BdB÷†Gq_ܺ µN:¢çˆ}+fpb¯FWú‘„Iì‹[édÁ‘msÚû ûÂJÍê€}qkSÞM_úÝÂ侸7WÄ}+>½"/›pÈ}‘"²"÷…gåQ¹/JÖä†ÜV™1éw“^¶ai;Xp_äû¾†MWl×§~d¿ÚZd¿oÊc«\Šl(µYœí„ìW[Gì·íû•{‰ýJ·ûÅ“áâH°_üÖ%]E|6[dÎ-šÊ3ïï $ò+-.ò+TäWîLð« gó e6$÷í§-9À’Ã\Z8øÕMΆA‰ kùubö•þ!ì+=XØWŸ±ï“" ~×—Ø÷ê³~|ûY`ß'‡,ÈÞ`ìÛ=FØ÷¹Ó=¿=ÏØWJ¶C@I± vÓÀýìŸ z–rœ&7ú-l?0صpëÖ¹„~;ˆ“ÑŽŒ–îˆ~Wxqý¶Éat¾ä‡]yNØ«ð%?¸öÞ×þ)"#ù!åo‘üØà¿üà^¸5@ˆûp—IîÖicâ>n–ømcœÞ–ðQÕ¿›gõ?är üö^ƒRN s?T°‹ëZƈ(à‡ºXݳ-¹Žà´Û@è‡} bA’_­Éè ý÷íú Ê¯ ýnH”/ô«yˆ~åÉ ýrkÉo;í›üJkŠüÊ£ù¡íÄp"?X)ù¡2Z*ùáòŠüÊÝE~¸»¸S䇒o© %w¥ü®e?7’ߤgòÛÑ>L~µÙPJ!6írL~x0£*~q•>c"¿tË4øeŸ0÷!¡}¸ïíã”Ç6é¢ùp#M¯r_Ù6cîÛ=Ë܇êJ#:mÀé<â>4°f?4–J_¾æ¾ýäÌ}»¾ç6@_|aî-}*°6iÞ%ìÃ5Uí‹LÄ)êÛ)èÃ(Ò$É™J¹‚>”«¹š ¯^EèC_EèCËH@ôí @„¾Ý‰}•ÇÌ—c ‘/‡,×6Wß-Ù\û´Gćî¢% _é†"¾rk_i~_yŠíþ òD¾]Y_¹‹ˆ/Çgß„ |¸‹¼»ú+¹ÌÕ÷Sï•ç#ÞC+˜ |(ø |ø ê‰ð•xØÎ0ïÕ,d¥ýY2ïí¦"ÜÛŒqoÇñ3î•bÖòÀ`"$íívì•Êì•wsÚ€ÓKFÓd»öÞ/´GÁ^éS‚½RÁ^éÿ‚=”,¾Ÿ6![B°WkLR*Ã`õ1qýS®`¯¼i‚½bÕ² þúööDÓ^iÑ^RD{×Ô&$Ã^-Æ&ôñŽœþè öö ¬Wž”XuÑ¢–XoϳÌz5-Ø7"'íQF¨Wê+ÔÛ]M¤‡Ù‚–Ü`‡|“Þ6@ W/@¯<^yL½b¶@¯<ÜÇœ) ”ÊÈ#ÐÃcÒEf@ǯUâ‹AðJšÁ9ª»1/‡'RÞ~öļÜ;kÌÛ£±1o7“1uâÚï<ª}î¯5æ!xìÐäÇkÎCõ¯¾WLçíçHÎþâçÃy(呜GJ*•èí`Ò«µ!éá*bÝi ß W*,лd”·èíO•Aíw+¥kþæƒiz;’¦A¯ÞiÞ~RÖ—"†zk´A¯Ö† WG ‡‰¾½ÝÑÄyÜ"óWÍ vqÀøÚ`'ÂU9¡ÎÉéÍšžO¤ßš^ÆJMoyS|jzËü¥¦‡$Ö³¦çcSÓ[éhM¯¤HÓÛJ È®¦„ å75½æºˆíj Ù—ÏGÓ;–7ÖîpÕóqåD+޶ óXÕ+)d#\eçNÂR¤( îp•d±EvÛõÝ}R?ýMFˆïŽ52ù®–L¾+)·mH;ïmÃüð]±J|WË!ßÕ«†j,º· ‰|iƒSGµÂQ-‡€WòðJ9¼Ò:϶ÁhF:ª)Ä£Z¯æàÕ¼šbò9<Ûט|´Ë5àí« x»dò(áGLxµòQ-†€T¯š¯Ñ2ª¯^CÄ«×lLb6Áfñj"^)GˆWSÈxõªmƒ•<Ûv òjÊúÚ-È«õ#å•{‹òÊU×¶a}0¯¦”öƒåÕ,¤¼R=Q^M± ûªuLPÞŒy¥ qÞ®Š8o™æ¼bcÛõw1$¥šBRªWôÊ­z5 A¯s[!@¯\!Ò+6‹ôömDzõ"’^Éò»êwW¿¤Ï¶Aí%â«yš&vf·~þðZ‰øj)ãùáÉ<¿³AÄWóÜ9)r9Ïø>+3ßÎcæ«)¶a§Ø†§@_ýÿq|m2õÕkæý¬šúvÛ˜úbw±øó_›Œ}%°¯¦\—ŸÔüÈ{H‘×ÏÏ­O›PR8#š–ïÂümS <É-Ê9²¦È ¥¦'ÿΩ„éÞ90ý;wŠý;§÷g¤çìé‡)ßÈ9ržü;ß”ë#ò!Å%‡':£„A›à(éß9½]+ý;ËUò,)òïDBifòï|STûw–Ûà5éßYRä‰E+yŽÊ¿sæ–Súw¾¿í»)ÿÎ’Ã6Ìý;§÷†¥gæIÿÎém¨é߉HûL{ç\éÌirÏŽÝ;Ï­ÇÉ9r#ßÈ0¿?åÜY •sgIqý3åÜõ×ö;w–ywb<…É»³¤È»³¤l\Ž-ØyäYRÂ3²ü–w'¾GbMywbš ?Myw–ÛWÙ»³¤È7²¤È»sîýxòî¬)ôîÄC2Þ¶Áylƒks¯ïòîœ>òk{wîywî«ì݉p;rÂÜô¯{g¹Êî‘%åùõ[ŸtïÜw·{gÚÔ~°žû ;x–9xî2ìàYòØÁ3Ëí¿³ o \޼#·Ývðœ¹7Íž»'Ùóäy¾åŽmƒrØÃs:–êöðÞAjÏeÓÃsîÝ€òðôŸž9´¤ƒçÎ"ßÈeÓ¿3Çüíß™Åпs×Åþ{ð±çü:wæ°¼;sY:wfUÒ¹Ó¤íÜ™›dç6à\Ú32‡O;wsgI9Õ˜r£HçÎ,emt§tîÜ¥Ø3rç±wç.ÇÞÙöîÜv¦wg>„ôî”g×Î4;];³ùè򪧮tíÜFÚµ3,Ø®{ëŸ È¾˜®þVo×Î4 ];wýäÚ¹¯²k'ˆP|e×Nm9ÙžY°<;³Øôìô„d{v¦áöì<Ÿ”÷lBnœµgg©Þ=¿¯S:vºm¶c§«·;]ÁíØ©bì×™?û§úÛ±Ó­²;ý¾mÇÎ}—•³9×ÍÕ÷sÛŽîTÛ³Ó¯SºvîrÒµs_e×άói|ÍÈ éý¿m¶];¡B©ûvîùvNïOßΜ×nßÎ+·ÌÙ/Ò3èíÛé9ôöílòƒÞ¾é*ßÎ]®MHVûv–;Ù·sßɾ»ÜíÛ©rìÛ¹}XíÛ‰HÄ¢AÙ0Ưd¿ 1¸Jxª—í&âÏÞ5šòìh?dÙ9ÚWü1Ð~_!§|"Ž•ü×ò³„.8þóºÌ)µ ¥¹ üY Bì˜O05§| bZ䟥 ya¯Ñ§Ù”R Rš ÊŸµ ?jÿoAå™ÔGô•­ß1”|¢²„¸²ãÏK!Äïõgܘ¡ýIŒø³¸n?hûI÷zÎó«ê'Í;±Iô‡ n,©^CIŸ°k*©äQIßn*©„]‹’jÐ5—´ó¸¤O7•´Ã®EA%èšËÉ.¦oÓÛTB®¡˜OÀ5÷¦G}ƒ·©¤p-JªAÙ\ÒÎã’þ=AÙ:–Wÿ§Éö7Fõߢß1ü2ï,õ%ø÷Ädëxxíܘlÿö“Òþí?4ÛËÖŠº†¿þõ'iŽÄÖæ_Dbëø®N<¶é×EÓk®#>Šoï’7RDóÀFþœ:!R ¾w@NVžN½ÛÂ9IxÆô–{…xx&Ü0Cá´àYôrÃX£»ßrkžâ ôâɇ“ÇsÆqx—Ä80ª5Ä©yø;lXX ~”#lXXc¦ƒÎ8ZL#:½òô˜4N(%‹)#&ÁKº÷ŒIãÂBúÍ”“Æ{ù”žqІõ8 ý@$êL2â´C„ª³çØà‰)A†+]ã¼Äxhú3Ægx£ûˆMüòf¯ùq†°ídˆ #)&„a"¸Ö<çFQ‰•rG ˆë­ÏRž‡!7§£Ô‹Õž&ÂÈŽÀˆޕˆXwëzx A¢OÆb}¯Q,Žõhu`\aÁÿ°.™€s”gu‡ù"€ l±P´§D¿c™)8a!âÇ9òÏh4ẦÐG“ XäTž+"bµæ“²ß×ïf´GårƈàP|£Fœ\þ–Ûg–2#ªWÉæ³n²á} ”LF»#&pp9ƒbuÃè;XðÃØ|‚ùèçÁpK ‰ò&<ŽTÆ{wZ€h¥ôGÄ^!>¸ÞÑ.ͲÆ;銘^q‚‹Ræ`d%o9üÎÞ _¥°þ8Nfª¶¬?²:À8"¨\¥É§cœ?õŽKý¦“´–Ä<•Ì¡ìÞ”ˆÕ†O!óbL,øžóî³EP¯+u¾1ûäL)bŽxÔM‹Ócʆ÷åV—ÁÈ…ÙÔ ¤”&>°jØ'xÌ'‚zµž¯Ø:Ô q”rFP¯8`)%lˆ•cZµdÃãpücµŠ…×G–/ÄÁ@žÛõY#âz]ïÅzàk¢ý†ãÒE®•Ç’ £¶w@CJ„mcö1ø ¼uçýlt>¨®1wvÙ£åì´!6«*Ïsrˆè~ pØç+;GœÇ|ã„.½:ï§ùÓêƒ6”·`È8†²³a…&ƽ[˹óý8dzÂÁ*gv¾M>djŽp\)“”ùÞÑÙÇqžƒ6ÄÆ]–Ñ£Ù‚\¶ž“0Šú¨-pX¼N3S®›¯¶,|›ÃªC߬9iÊ=u'ÛàoÔœ“¢KǕ͹8ŸC?v‚ys>ô~ZøÏ…ŽærsɄۛœsy¤ëV; ›ÑïTîÍ~>Óìy¥‹ÐÈ~8~C[gÌ~‡Bì7qü†Ü–È~ÇohÁ›ì7[AÉ~@c nšÏP8l¡ß|°qŠ_;¡ßqx8$ú94ýަãÇL~X|ÔçZä·þM~;º–ÉóhM®D~€}EE~WÓRƒß>sÍà·å3øícŒ~«ÃëK(ðÃüú-œ¶sUô[Ð=]N Ó‚l ô[˜þiù‚è±× \Á~+NíáÝ ëF(']ÕnF^}6ü½wöWRð·0VèAþÖ31[ð·pPÀ¹Ë‚8Lé·d¿õ¼Ÿ×Ápȧƒ´‰ý" pÆ è|{·àï½¹£ð þV8C‰*Ç;cRe 3{ÿpZNÀRJÀ_ÜG›ð·0-6Rüa=Æ„+ø;Îäâ) n‡x6üa²ªwƒðñû ‘Ñ|šYþ"ê¿^ï€? \z)ˆ‡®!8ÁSëþÀß±|"¡á¯Þ(ÁßñNpèÊjøƒ×ù¿ãô7Èð‡<ÂÁVnÔM°Ü€Hø ŸSÖ9àoG>5üA2¸uoÙ€Ù›îDpÂDÞˆFp­µ4ÁòœøÃW`~àïx|‚°áñ&Œ$§ú? ÆüÀÂj)à/*0ûÁ“MÝMìGØK;ªŒØ/¨a)å¡Qžý™ý`”º’Ø÷2ÆÑœÑÀeXÃåÁð‡Mq²ào‡ 7üí0à†?ÌÏŒŒCÇ[ì;þÐK š´“¶)• Ð X×Û$øCìh~ á%$´;ÃJG±5ü!Ú¾ÚFð‡Øãûà„„¿Ó³IÖ5õîþ ‘Ÿ*‡ðw>Ò5Ì~hœÓ¤Çã-{å$ûÖ,Ì~89]MJö;5¡7úáÀÕ[„& nGÐ5úá•ëô»Þ™Ö¡Ä~8ò@o”Ùk.L úmñ!Ñþ])´àÈ©ãïÇd3ýÙúC4ðãC8XQŽ>Vþ,þÞš? ¹ ?…¿Üœeá«%ü-±R섪Cᣑ>Ùþàâ(¾ ¿ˆëH$“ð×ð×Þ¦w Ù)ºƒ®;-ï2þî}AÆ¿Þ-¬ˆþp<¨&ò¿qäJ¢*ÕZø‡3Óŕ¿µR9 ü{‡,WXø7ß®¬%^á ÍIÞ6öä@øoÙöÁ? ÑñÅ¿ÇÁkŒq„¨àS6< "@œ0.@¾#‰gå"@L»4· \¯)¦F v—̪þ½ wR¢ðι»p>h%0¦›¿U<>I€÷áˆ=IMˆéKÿÎo•wõD€qºª®!®¡H# €—Cf×t )`Ñ €8hW`F¼‡ë6.m/ ¾ó­öÀµŽL 7–»xo ¾Â= dïUý{ï£ Hûh±¤¿ãÈBY}œünÀ"þÁ]ù6ì<ÝÓŸRãß}9z›ñ¾Æ‡ ‘øWŒa|X•ƒø7‰w÷”Îø¯g+}ĿҸƿݡ‰Ñ0N‘‡þEm4÷þÝÝIÿp¯£j 'òJšaCžG'ü{¯¹lñ/ZoTü{ë׬’ÿ|®U.ñ/ZGO“ø÷Ö/î%Î#L6,;í ÿÞ«|ö€ðo—¬þÅ:‡u¼‰;ÝÞ(ü‹÷KïÓ’ Ó‡> ÿ¢ýΪýÅ«â_­ ñ/JÖ`Cü{kó$ÚɆ½êBü[±ŸLhì÷r9Ñ^ckq:›ÆòßÂ4Áû-–w~Šÿ¢~מÞÚ\~ÉÑ¢B»‹‡Ρ‘ôWí~dÁÓ¾Ò_ô«Ò_ôQYIú[wìùMð·à#¤×ƒðWš\ðÕUù[áò/¥M`®," rж^Øx<ãò.ÑßkÔíù 鯀'ú+Sô÷ÞˇïˆþbéËù`ÍsŠªü½÷öZ·è/j|X |ø ùtkÑß›ç±zFúûä ~*/Œèo?LÁ_9&Oôo½æ§LÈ>ôo‡ëˆSa¼à+ø‹ûÊfÂßBŸáþÞBìž þ‹SÂØ¥úOÅþERFü‹Q¬Uþ{«³Rˆ þ{¯JH'ÿ½·Ú4&äûüeè1’ÿâ!Ý•ÿâ!™í‚ÿ¢ ¶Éa’ñw4p[°!þEÃ|´¿²(ü ‹d5ñ/ž‘0,˜>›@ø‡÷ˆUˆe<þÅX$Ž ú{³\y£ ¿¨¯È‰ôOÛ‚¡LXÖsDå{/ú‹·Iz2é/J±œ«ú«]“ôg )ƒ-°Sžà/ZϘ98Z¹¾Aø‹¶Ñ‹Lø ¤µþâ*-= ™0=ýýÅå΄°Â[…¿H™þâ!|„¿J— R&”kdÂ~mIÑ6–!—Ãí¥%ú«Ý^^×h®þE×Ò €\µ1f,ºAÿy´6#êó!¾ç½ïÉóQ“øf·úzÆ1M¦B#_ž %ä ¸(ùÎþá½½?=Ï'™P¼—AÂÍ{P^íØ Þƒ?Ñ­佨Ej$ïò%ÜI+»¼ aÞkˆü‘ûú úÏÇÑ;@E¾ã+>Žžx§4?ð?í“)¹ 'Õ ¨|ï êïmßÀv ý|轚SMóÞÈ ŸöU½=M3ïOºmš÷|ò‘yo6O!Œ{íIýO¸7}TâÞ™¢Æ=D85r€€ŽXq¯uѲio¥S©õ¾ÓÁ@M{÷Û0šÜ›öÞiÑñ¡=LÂ= œôãb/HÞî,«¯g@‹47ÑÞíuŒÔûN}] {…ƒ {ËÞµVû`’²öžËÞRíÃÁCJ!-í3 {˜ª¨!¬öáÕ¯Žžeh7ìa›£:‰Õ¾iß©}÷z X ËU]=ã>b^Á>²ÉjŸùPÕ¿ò%°Ö‡X9i}WÿÁÏó8í •ZN›f‚¤¾÷£#!ÊR_Ë91¥>Ìw•œßF2ÙKd¦?I}Ø£-!’~žG?Ò[”¬‡mœò‘´Ô×®í$õ­tóµÔ‡¨â8K}v³ŸçÑ켕Rßn,J}w2GJ})¿Yêëé)Öƒ¨¨Ñ*¥¾í5)©o7¹¥¾i_‰Tú–»¢•¾'… +}ÍG#¤Ò·,(¤Òwæ‚•¾üò¤Ò7R–²Ò‡ùŒR¤ôµ3M2Ù‘+}p®­¨÷ÖØÓƒTúÆ•.œRú.ÏýSéÃIÜ*YJ¦i‚?)}ÃªŽ”¾–pj©ï¶·cJ}»ÆÕÊþ«¹N2™K¥oÝÉqRú°RY/òØ=SJ_žñm¥%«vRúÎÇ#Ëdé÷L¥‰©ôA“^d¥¯ù8^K}ˆßñTØ+Žñ)õ^‰I©¯{]#¥¾T+Sê›ë-õÁ)_“OI}ˆ¤[Yé{Ì4TúOŒ&¥ïJ…ÃJ߸R³“Ò·od¥±{ÅŒí‡ÃìSé›^¢J¥ïòJl*}y¶zJ}Wò ”¾~Ü<Ñ‘,Ó…R†pÕü)¡¯ù¸ñúö#°ÐwzZl©^‡b4U¿y*·¥¾œ·[êk–à·Ö·o.­¯åœÜZßLî¡Ö—ý^ZßãMæ©õå™°©õ-/ާÖ×|ØVÕú$2§Ö—øm­oy=(Å>L>žžE(³Ø‡hÂ2‹}>iTb_÷~ìû ³è eÓÒµ¾{&"Jëëwº”RëƒT¥,’úr'¥>ÔWô'Æø²^¼¬ômÕJ_d/¥‹ÞÂ-¹ªÆv5¦È‚¢ZéûÈ|.B—HæK±iË|>7}<Ê#ïÍ£gkÏÓ*‘u>l²üf/úÐù"lŠ€LBßeIc }Þ“>žØ0¦;QèC/:*êEm¬CRèƒü;¾Jßáù´•>¼òzç¬ô½ãýõ÷”¾ãwJ_,I|¸oóš÷ø­Ü­'îËIéç™ûwÒÏszWúy–rOx÷ Ñ.›rü$5aðwÁ$¿gä~ü<÷é¶òóœçäÿÍ×E~˜ÍX ”£'NFQ¹Ä¦cï%ùÅÀ+}ä‡/DÿúªõAÚ€ÁVßZ‘ß>öÓä‡o†&Æ"¿’A~O$óý ukb"ô‹3Ã?è~2Öœð Ñì@è˜s9KA¾žÉ~×L•Fì‡>/ÂûÁ v~œ=ÑŸ-’œvØy²_¼µúMøCÆþ‘úà,à z##úlô[85\ˆ+ø g aåýC /ÃÞëx„?|)ŸÖÇËk´!&­Q¸Ä¸÷õÁ?|¯îÿaÔ®>âßu©ï›þJë‰þPŠú¨è/=>Rßu%‹þ0H__OÄûÒ_|Н'¶Ùˆj‚þà!Ñ>R¾Uj;ÑžÓ××;™„¦4ÃÙõá¿p\øˆ}(X)±ïê9oÿÁ#‚­)þ»®ÔhÅ肦9X1ÏŠÖ‡Ë-QZZn}øï:ÇwŸß[Jîçÿ¡©ºÒúðæVöh¦R­Ó%;`’ÿP޲Pê»ì JöCó¾¨?<¶E®:¦JçÃ+e%û¡“=•ýâÌ»^RçÛ®ê’ù©Æ{þ;³ýÖ5½sT"ÂЩé$ò]=‡‰|WËM¾!òa;…Ë€óúAä».‡d‘¯ô ‰|YG^Ÿùð 5„HäC9z‰%ò].Dôtv•Âßk¥PCñÞB*|¸‘VBá«¥Pá»ÎôՔ‡çv|>ÜÉLG¬¼RøÐ§4ÆHâ‹y{õð\C$è”Æ‡‰»‰Í6äØ%NŠ­4>4ÖÚÛûâ-°ç(E>5ž><Ùã£ðíÊYáÃÖ¬³îí‹Îù¾…ýÇ:*|èzw…¾8Û¤Uè+/ >ìÓ3*RÛ§JRá»ÆüµB_éÀøð,%ºQß‹]Ë¢@Yww&PCØ' ~”Çà&V};cTý%ïá•T;HÞ©­$ïáÛè‚£þÙç©ï!6B¯ÌW-–¾‡!QOIúÚ©UÿÎcÁú^|§uõ± ø)·Qêcè®bV |ø=7 |û ´À‡[>{{_ÔÏb"5¾ý•³Æ€?ßÕs7¤4>t?‘¶4¾<ÙÌZTU–Æ·'ÔøPˆÖ¤ñíÃã¬ñ•wAß­ñí^ß>¬Ö_y¼’øP̪›ûbä^‰/ÏøûG†q‰P8Áw-£¨ˆï®ñ£'gD™û­àÝ“Ñå,ë »~mYo¥o§B¸œŽ½=9½˜žœ=¶C¸àè29F’ïÐlš!\n‡¡1ßõ''áR¾ȓóÉùŸøn´ôÐß½C§¿Þâ»y*ºñ®øÄ9‚Ëö2ÞÁÕOy„w “ýêÉyãð«aœ;èÙÙ?xwcªùÙȇ{`Ò„çÎɧðš—󞘕þ¶é®ìÛÝ!þsÿÐÝ£*{7Ð\Ì ºƒÃ¯yJ!PrCQ\VÎ-Åã©tËÿ­J{±Ö§™èî¹óù*ŒKÙT¤0.ŽZ) ク´HWa\ >Èr…q9¯fYÎQ\N‡Ûh޲¼àQ\Ê‚»£¸ìEyEqÁÚé¨[ùbSÌGÜ+{NÅ•±ë©¢¸œýëÉ –³nå‹Qö¹T—ÜÀà8.%ê ã¸d4ÇqIŸ\ÅqÁ4ãƒwÅÏßq\ÂéZµ“íRª0.XIPã)Œ âRJ‹¼‡èQ}9cY±Ê{7f†ŽÆEòÞÞâÍ0.èŠZr—FQ\Ž•—(ŠËØ[Åó/s˜ÂÐäÊÞŽâ²ÉLP†Ï .¹ ƒ¸ôŒ(¥ .˜)x?`qÉàÄåHDTüxKíSüLR”‡Ú^‰ùÑöÎÍ3†ËuçV:Yðò´E9™06x)† ”¸‡U¢g„¤°iÄp9ºQR&”@0Cc+%íaº6>\®;Ù×\rkˆ¥½HÉ\zŽF’öâˆNåQ—î£3‚KÆZÈ.ÃÇx:‚Kzžd—;áR6äÙ‡;‚K²£´½˜W/ÎSW§´½ÒC¥í•¨=£Ð¬$:Ù™éÂ¥Díq¼Óº*B¸¼èm…P!\ºûM†pÉ­íí¸4Âåöø¾C¸Lo`’¶‡^"}"C¸ÜŒ…ÚÞu ü"¦Žß\fúƒ*‚ËŽšÂ.‡Uw—•;ô¨í!ˆc¯8‚Ëœá@d¦C¸4/ e —ácš3†KvœŒáò~Øf%½xTšlKÜÛ!„ÃNb+Ayö¦=ÆpIEâúÏ6¾8^Wô% ž•ÛmÁáÚIÞ‹KEƒŽã’¥$ïá¯JzÑM,:‹»:å=$/»n Ktص“ÒX>l©{»g—;ã’8Ž‹G› ã2Ç%îÅ|By´ .‹{p%û¸rFô ︣¸‡q/b.+‡Â¸`\ªœ­içN‡qÉvº‡—ÙA[Æåô t‡qɧâ|÷JÇRÙð¾ ²Êa\Ÿ•l}OîãËùæÉˆB ãrÌÌ¡0.;TŽÃ¸ÜŽ e}/\ñ”Ç!P²µÆÅ~›Šá2½þœúæbL ”;„SÆp™Þ('il‡‚)!\¦RbßTã.øô}C¸Üñâåÿj{W8ý-¯D¸Ë=|Ë"FJ{YYïáÛ?£Û^¥×Á·Ü Þ9\_1ïý¯ÿËû#‡”ð[æ˜x6Avÿ×™öU;ÓÏ.û¡·7÷ûÏ‚3ßê©ÈáJsÑÿµ¤ZEèØ’Ò.Ê µ(¥•¢2¥ï¯w€ÞE9¡¥´RT¦ì¢þcÂ]c|KÄìú~guŸÖa„ïžzï;CX–„úC†™‘ƒ’¡~GÆyý]¯OèÙ½æ?ë#¿“ç_þῲ™þéØÚ?7ßùä„€7ÛÏck¿S%ÅÖÆ_|ÝË_ÿ%ÿ÷ÿÖ_ë_þŸ·òp½®üïõסµ‘©„Öž™¸ þ·üëw¡µ‘¸ËQhí§u…ÖFâïBk¿iÿ-ÿúן¤ehíóÏCk¿LûN7úÛMž‹Ç"b<è¾—=…7­û;ÓïØÀ‚úŒÏÑÛA“¡8¼uÃ$¥ãD›˜êc£ÀÂg÷™Š+6#üÇÚŒøŽ¬1ý~gqﯮÉÊ&¾ƒó@p›˜tNlŽšî Q—ßÉü¸gb@{ oœ÷ Þb"<ÆA„ëzoó ×1úcŸz7&[Áí !N_KbY0Hy5DÂçÁg.hG1Øô€[!¾Ä£cOj¼Â£òBÉŠe‚ÛãåáÑ-¢a5öŒ‚%è®ÛyPÌ}†ô½°×ýÅ‚s/bÚvGÄ1”‚y(.ºa‰‹ºVF±'á…Ü_F0G‰mµoû¼y†ü²±íòý6Äê‚5Ý{ ”+]û|~Æ;úbïÀñ>1°÷¸EÊû_>nÞ¯{‚ž÷eŪv`v]+>m À{”ÐêcÈ»ñÛßyÉ/\ƒŠ” ~ʨà#?¡ˆÆõŽcb±9ò@Ô~p÷C>6 8Žk—ó&D/Œ›¯ø‰Ý†ïxîa\âßwÖz6œ×[ö™ÄÒØ Üy9¨ÁqÄ9WñÔ¸ôxœ8h`žM ÖÔr Âaïh±£(Àר ðeïKewôƒŠËÀ‘™ÂðÑǽ€J ×ô·†ž©c÷Á½m¯=à 8ÅÌx<±evàýæš‚áýÓ³_YTŠY®¸çÀv. #šÏkß@‡á"âß ç¬[ôÈ0/Û ì¦¥‹àÉm1»áŽ,ÈâA­ÃK7p|»v6 \žÜü´,…˜$ï5'‚ë)×»ú"Ùáú€N:›ÇÂW÷ºû êç{Ñ–³±¦„÷l]ކžg·C*V'ì¼¼/²…[ͼù Žr|(Ö‰£ë°-À[è´ØnÄGÑìÀ4:žòŒM!± ªã¿^®Îί³º[(âc5 ˆ\ÛÑù14°ä±«¸RÊ<¯Ìfnñ‚Ð…1gæÓÈV¸¹Œ¨:[òŽÀç¬P¦mO,Ä¿`ÇÀÇcà8uÆ–‹x}îp8È „âÐñY¡ß±ÕÃí| Œ¢6çaùæñ¾™>Cå s-³cuf^ ‹ Ëw¦¿&¬hRÓúûA‚yXöúû;Ž<0óòÊà8ÿ{ ²¢U' ˜åé>0š_Ž[žƒƒÃ<„bKËZèÍúÍsËÛn†@o¹ö·`µ8,P„ ,¦Ä8Tž˜à¿yrñ㈰cQ´æ逮§¢W|J¾Zìl±mðÍ“K8ùA‡‹ÀùÁ×Í걂Õèº9¶´ÂÊ•»ßW8~ÅZ¸V¡îت1â^ÞFü‹ã|R8>xÝ5 ÆÂ;òµÑÃî]ÔÂ<¾ÓÅ×tèŒØKÈqŠÓØ&ÜfỈóƒûbe¨`óõÁùÁÆqü#_qì.\ß {8?8†ñSûAµr1bþçÆ(~¹wá+ƒÅrüv|¦c¿| ¾ÔÅ‚Fº9ˆ7ûP?qŽs­ð39ˆ7…P¾p|ðXü‡fx!øn â]Aü/¶+>ÁšÌ]•òâ½ã¹Ž8Æ9z[ô¿ëàyÝÑ¢‹™Q¯)[tœ _éSf.VûŸÐG µö µÆW¦±‚ÔÀ#OÜ*¶ =´!Fœ+ÔXØùèèî ŠmŒápHŽ›c» Æp ƒ)ýä~ëq^qèøÅçø „zNrL‚p«#ê›Q.!Å$xæ™W&Á8X—D)ÌÞž$x.•$îGn<-z›‘ П“À/Êí‡kŒ³‚?iÉoâÀèÌ#Œä7qà™"¾90öè~8ðÜ[üÄ8ü‹ÌdÄN­<ê/æç|2. 9p—lÜåˆáÜhŸ;r ö[ËAIˆ‘¡ÙÕ,æØÆä·Èq¤ªb£Ï<†D$¹åÍCÜç¤ á·> xn ‘`l#¶'}Ì#ð&ù¸’àYv! "E>ÒÁ3Ϲ0"P®ÃÌOѤ(0vܲ.¢À8ùšyH(ƒ]ØxΞ)ÈÏôT1†Ï iNˆñDyˆ€±ßöƒ€gº[1•åØlÄUXŒ€hp.¦‘ÂGkÔ¶bóßnà™'[q#ú8wØqÕ—÷h$ܵ3Â&eâm%ŠÏtŠ1žé¾`„ȷиË1ÆžÀ0˸ 5b¯žxˆ-‹ôN1ÆöÃè¯FÀ=^ Ñ8ª±ðtH¨D@Cº¦QI€Ù“cË"óa§Ü&ÀØcÉ,"ÀËÞI€§ÄIÄU¬ž0­L¼|ŒS Šy˜"Ü›sàMD91/IÌ`I€9ä“Oû•ˆBXªðôAT €z€eˆqÒ’ð²¯OBà.Lj!6¦‡ »¾†ÀËþ?  ‰Ô†ÀÓ¾q y¤!ð²NB`Äs  w1†Àóá¦ÏdÀ]3 ²mÅ€§=E÷Ã4Æ®^$<í–¸›Â¸›Ý˜âÖ?q»èqžlÕýö·¨R‰Os»Tío Ø-Ó—­> ¶ÕÀ>«x ‰S D šXØjàP¨ËTñÄZnª‡ÃŸ¤øÎØ¥¿YÄ&ˆxEŒ˜ëFOI9ï)iÍr æq1ĤxzOKb`FZوܿ ·ù`U‰€yNi2`΃“3¢P2 OuHVk—w1'fÌ“D@ìßüÞ5“JJ&À,Ƙs‘M€÷¯_ /âÊÃçú$ÿeø’ä¿Ø¢Rñ/[/ñ/”Øøç©tâ_ŒIü˦Iüƒ÷?Sÿ|rù/Ñ#ùozhò_6Mò_BÄæ?ï™LþKÏ^ ;ìÀ$ €œü'úAmþ³ò–ü·¼m1ù/póŸ·?nþë’°}Rhòßp„Àå/6ÚSž8}Dàðï €ŽŸ˜30xà¾Q ¼Q6æÉ« €~¥’ÿÁ\]Ì·Oáþ%='þaû„·þeã%þÍô^ø7¬€&þm 4þ ŸÔ`úËNbú{ï$yÑô7‡69™þ†·Ç'ý9KÂßXÞ‘jøËñ(áoøØ³„¿™›|M®oÂü)¿ð7G$ñ/ ÿ†ãÿò¥Ä¿ÜÛ•Ø×ؼ¶”˜GS%æã6Âg &ÀÜý‘8s% æFHœÞœ8–¶=$æ:BB`v­„À¼WB æ L1fó$æÈ–èGnÞ]– ˜½/0;[2àôñ:É€Ãq‰Ì€Ûªd@÷ŠDÀ\IœŽ›˜7OÌ—*ðí:dæd@Ï0’çÝÑ7z,ÜèuËM€þbnÔW*Ы ݳs¾¶ÐëyÝ›mQ`>îM€CîQ›Ý‘6"þìG<½j ö Ð#›PŸøÀ]ß$ÀqûÎ&@V?ñO½!é/;Õ¦?u7ýMÅ%Øô7¢è/ÎuúÒ_Ö.éo*ä̦?÷!Óßéã¡7ý¥II4)Ñϯv²_.5nöÓbi¢Ÿ—97úåó0úí–Iô›r‰Ùèç…Ï~Þó”è—_Ý¿ˆ¶¸~8¿¸×óÞ£%· |§(4¯i{åvÿZÏüc÷ÏŽ3$cÉ-t?ìÿ;ªûçÚR÷C¤ïA‡Pë~·ü+¶îwË%oë~·0ë~·=ðu "ñbmÝï–_éÖýìRt?m­3ðE¢š€¯¤ˆø"%z™ˆ/P8ÖäM|‘ï…‰/RbnâÛyL|¹€N¢"¾ÈŸ+_ä¡€Hä{$ù"%¦SF>†Dˆ› ùJ!_GÜàøºùJ!ß¾—‘¯¤ùv9F¾È3#_ä9ªh䉗ÛÌWÊó•{ û"O zƾH‰áÇØWòû"…«˜â¾H‘ŠGîÛwÏmH¸û]µ¿]sß¶ËàWóüj9¿m»Á¯–Cð«y~ûé˜üöSùÕ,$¿šBô‹”*ýÕ,D¿Z.Ñ/RÄud¿¾ûÕ²_¤ŒÊ~û0ûE èWŠú•›ýöJ”Ñ/²p–'ôÛ¯–ѯÔFèWkCô«7ô«ýJŠÐo¿éF¿m”ЯÔFèWî$ô+µúÕ«ˆ~Ÿ”çW<œž‰ýÊ͉~¥¹„~;K÷Cù¸€Ö’_¹È¯æ!ù•R ~¥a~Ÿ”‡ã¸¼Ü³·‹!øÕ;üv_I ÷•kÈ}1†;bËA¼9ØÅ¯×¬µ÷•r‰}5 ¹¯¦÷ż«?¸¯Þ‰à·? ¿šBò+‹üj ɯ¦üj9$¿rw¡ß'%ÐoáÌ~¥Å~5%Øo7ŽÐ¯äú•; ýJ…~¥ÆB¿zU _-˜èW‹!ú•Úüj)$¿’…à·Ä}¥›‹ûÊ[)î«)ä¾R ±¯Cì+/®°¯\ØW‹%ö•‘FØWË%ö•r…}5…ØWJö•ÁÇ»[ËU侚‡ÜWSÈ}õ*r_©¡¸¯æ î«Åýv£ß«~»`£ßþ,ýö›'öÛ]Àì·ûÙow?³_½ŠìWSÈ~õVd¿R²Ø¯äû•{‰ýö°döÛ¯¢Ù¯–Lö+õûÕK5á¯ÞšðW‹%ÿ•<ÀšB¬)ÀRް¦÷ l¬åëUÀšX€¥[#>˜D92àîÿfÀR1`)™Xê'¬Y¥•5…XS5E;?³:ÿDî¢ÿÝèI¯I6Ý@8¬üOöú€• „ý¡N¾p)øÂBÏ©Š5º@âî?+€M‡Ý§Ï˘yo0UB+€x5gu8Q‚BAom¶Ú X¤X„–Ç]„[ÔúÌVÏóGP¸6†H˜ ࡘ۩ž“±¶xòœ™-ž\«Þúߥg²õ¿K¡ž·þ×ä1Rô?¹¦èS2ŠxÿàÚ˜qëö·Ûú¢ÜÔÿºvc7ÐàRüóYÿ¸€¼µ?¯¾Pi[ûó"óÿ¼&²Å?iÅôëÿ‰pqQFjKqD·ö‡c{¨È¥øgO«-þùàéÿÒ/r‹‡pSü³ \@ªw;€vo LõÏg¦§úg}º¨K‹º©þ9ÆÕVÿCÌê_®Å¦ú—+¸[þóBuê'õ¿ôÜú_ s©:À\tNp§¤è’SÌÕâ}|E깎ŸúŸµÒ­ÿYIý/—ßSÿK}mëò1/þŸ–¬ÿ¥ ©ÿy‰³èÖi¶¨ä”­ÿ¹µRÿŽd»ý?SF´þ— ÛÖÿ´hŸòß.8õ¿çÀaåRþëv–£ü×»wëYþKWÞ”ÿÞjˆ)ÿ!r½4-ÿ!Ê*yÎòß>ôÁò_úG§ü—/LÊ(ïëÿ¹ïný/ïž`Ë3,ÚE!@„TôD €ØwZA0.ò‘ÐÖòëÿÙòdv+€xSìƒÜ ‚¯0Å `6N*€YnJ€Ù\)ö+£KlOÆ’˜Ô)vÝ–`?2R­4Àî3ÔRìí×ÊÅÙ`ú—§ØuHLJ€Y½-ÞÞ®g p ‡–ÓK€é9¾%@ùB§ص‰d+€}jgo*€é¿‘ `÷ ©f<¿­6ïñ³˜:q*€9§˜ÃüVåÔ³ÀáÓ\SÌK€ÃÇT¤˜ãBJ€[a³¸µ»”}ÀÄ–=2¤˜¾ ©Z}* ½Ò·è‘+5À–¶è‘Õ`:ɧ hu¶È€ª· ¨é@Qó¢T`Ë€‡1Ï2àû9ÿR´¾”2`JA)êSµU@ß¶ 8|«€[½³ (—œ-¦ü•" Ý&Šh9Ž"à¾Oª€ å½UÀѶ ˜)±Áš[öŠx~6æ¼­(úþn%оßE ´J¶•@?Þ­JX/JàÒNÄ-V ܳƒ¢jг¥@ËÖ[ ´CN‘oíü“¸Ÿ|KK¡ Ѝ€²E ”GI‘Ý [ ÔF§"*œÿO¢rÿí9àò¦½[¾gO†e1ía;^(„ÛßSÑSL{/»éœ÷ýE;¾I{÷!ïÏýE ‘´—CÉŽþré\‹ý徨Z;ü‹ƒöîð/'O1ì! &÷ïíè/:ñtGy/¦sgFq Ô„=„ÊwO„uŒy\ÒBJFÁþòRîü¸{68JÅ5¦=\óÝõ‡<ñP÷šOŸJÜkóüa×_¦;áÂH^Uü 2RÌ{ Ñ£ó:æ¢(ÞC(ô@BãN+ŽÑ&q/#Ø$ñ5Ÿ”Ä×Oí®IäC9¼ÊÈ×Ϧ­xF>D¾$àùz£ŸÄ×°{"8ÑÈ×}HMR_{ÔM’úp3ÝFM}ýôLÎÔ×}´¡Y8C4ô½Ìþ‚¾žgú0^Ÿ]o×UÁb¾ž'k˜ù" 'ÙQÌ×ó¬3_ÏÃbÌ|=O 1ôõ<çAÐ×»cdúP›ö¾ˆJ|ô!\<}½ËÅ7¡'Tkó  y86ôõË‘„ }å^‚¾l3²Ü§ÏÞÒ£SЄ`[úúå(Á†>œ©Íé‹¡¯ç±†¾Þû¯Ÿð/=©2óõ<}AÌ×ó´3¢5IæóõgÝÔ‡<\6óÁ" ˆb>˜t}˜&æÃ+äCÉ|¸Õ6!ªã#ˆ|=O{òõ–Þ›B¾ž§dùðä2–|Ìúð6&#žåóÙò‡[ùà©`¾žçz˜ù:é«0_ß§Þˆùú>¬Ḋn­Ízb¾üø0_߇§ˆùð8µ_Ȯf_Š'KæëX¨'(™/;›‘ÏLX(æÛo™˜5þ¸}ö<Ê̇ˆ¥ìùf¾ž§«˜ùP™ë³ñåÜuã²ÌÛ'¬”¯¨ AÒ„Ž‚>t9‹ úPc§ o÷CßÎcèÛ4ô!t2W }¯Aš¡˜vrÁÃ̇<òÅó¡ÆäCVØÈ×ó˜(#_¼“Ì#äCž£ÊoÊ­¥P#ßn.#_ŸÞ­häëy|“Å|ˆFµãg¶MúÒøé:—'‰¯û¼)nôÝù×Câ+yD|ÝÇ_%ñ¡m¨ ø`äúìüñ×gçò|‰¯/™Ä‡¦iŸ}É.‘$AùúbîÓ€$>o¥þeâÃ}>Ò_>ƒ>ô‘ñqýDu?¼×'AN°×}gÂ^)C°—½*a¥^ŸM0çúD~É.mÚC1_·O Píãö™o\â^I›: p‚NœÄ=TOà&Üës9ZŒpyžOä—’"ÜëK» ÷PΪ¢_<'$”Ý×3â ž ÛqÖœyÖ9j¨í2í«v¦Ÿ]ö׺f÷£„Õ΄ Ûi;îNÙ±°Û=é"’E9¡¥´RT¦ì¢ÞÊQl_¥HØ%èçtT–þ(*÷z2Þ°ÿĺï™qÿ ÃŽÊý¬Ìà?1 ¬ û»žòæ£ÓÁŽQü“~Ç÷û¹[å”xÛ*¨ÆÛvI;—‹úÄîvY;Þ¶Ë*ñ¶³¬Ì•eÕØÝ.kÇÛvY%Þv–•¹²¬»ÛeíxÛ.«ÄÛβ2W–UcwûEÚñ¶UV·/`ærYÿž¨ÜÂÀûçgQ¹ÇŸDåvßÊ|?ÊýGÙ~ŒÊýÅÝ”í¢rÿä%øFžÿFåþë±ñ¿æ~6þãgïΣãO_žß—ôOľâ¸÷û¯b¯ ˆý W]þü/?‰\íØíüûß~Rð™)`ö¼{f‰ï_ ޽Žëvpì7ñwÁ±ß´ÿ–ýëOÒ28öõçÁ±ßY@œÙÔ¡îm_½–œlh«ó…X/½%_]p^ ÇžyrbÛŽC.ö“³õvœÁêãÀ¤êŒ”+uV†.æá)í{wÕ›òpEaúV¤ôp{Xƈ©Ì;KYŠÊ"ŒoJ[¬I^DÈv¬˜¹œðk9 N.£•E¿†øÚ 4Ô‚G;aâ*·Á£eÅ¢¤Bœµ“Ǿ´* ½áè@ Z{?D1ýmßÑ/´!bmÄ*W‹øó*¥œ\bÃIjl¬‹ûéß[7NCNPŸM¤ð*Qúò¼&ù ‚Ïæ´Òp€ø,–¢z8³)¾)CjF‹s}P;½ø çEtÎcøæרâ8¸° O1¢s:ik'רpÂÌ`ž‹klëT †yEDÃn ÄÜZãâ~²“âì@Ž™L¡ïA2ÔÝ'ÙæÒPkk(<çp97ÙpÜÛཞXdCøËø·~(È2Â_F5·‹ ™±bÑú¥ ˧‚f7,ÒE|Îgr_[êƒ,+ânÚÃö!Y6̤">g×ZbÚŠ!;yó¥ Ëï;Ó¹†ØçŸA[™çiŒÏ鈧 'zF|N¨gÑ1Æ© Ë#ÂÐqq™í~Sb*ÿ¦(È2¶°œÆe67Œ¥Îe6t6Ï ÂaQùF 2‡ûäX\gCPÔÆKn.´Íqk@Aõ²ìÐm\h›8‘)§‚,w?<A NCžÐjßYîŠ'ÓfãBBžO–Ód¹wuÊ9¸Ð–q«Œ Ëýù• ‹ m§÷«c¹‹qÛäQG‘:nhЗbIóÄÌ)Þ£Õ 1¸b¹ëI¡ÃŒ‹²Ã=©!<úd”t¾ÓˆÍ9#"°4궆‚,wÑtCg¸XÅ,EYvÔÛÔ¸Î͉¯ÌzeÙá~Û}p ÁsSNEY^‡î‹ëlXôâè…Q–o.Y4„  ?»",;õ;ÀÆ"Œ¼Xèt„e÷F„༃‰sÜ¿oEX¾¥„µ›¡z".~,†µçà*"Æc7œî±ó±ü ú0ú€ù±jÚpºo„Xž:²=Ël^µáxß¡Áƒu~èŽ0¢A"a*ÂòkçbÁ0‚îYì­Ë‹kX >ÞbÈÆw³ã}(v}H=ßè“-~O:¾Ñ`=k1åa˜ü“ïO?š,+ü~ÇѾ%¿ó ÒŽ“}cÇ™°Ì2¹Â†`û‹•Y\b‹Ó%¯H¹¹ÄvcÙŸW=Н ‘ MÕ8_GßëøB|pµ¡ã }ÆÀ6¹ÞÏKñ•ý!èá;tò±L¦tXöèÓÃqãf4tV0´éˆ#Í&î]n”ØÎaÀV£€G=þ¼8`Æœ¢_ã+û5ìPhcüÆfÎH¸^uz˜¢ðÊ·Û_h ßkh@ÓéC‰3ËàbÇÇ'»ÇѾ³Ü¼ÕRxå÷;8X›[á•o–î8imÕhÙGûFxe|ÿ¢'ြ½±,wÇêÁ"ÝñyŽÑóð ŸgŒÞ=¹ãó£÷ÒT¯ãhßO„厣}cô^:аãh_†Xžz [côÆÔ“W±'ÆÉ¥ñbví£·ã·w•bÙ/f‡æø´±¸ãûÌË‹‹ú=T‹_"ØýÁ‹ºC,+ |ÕüU‚Qw¬Ó1Äò­¾…eЮÀܬ2N÷óÄ(ÕûÃËÙpºïŒ©1®ãpß¾Ÿ“s ŽÃ}#Fþ9ãÔCÆ—ÅÇ9bä_òÄîø8Ÿ'ßÍXLîqxÉSGð{)\öÃ<«3F~Ó¹ÇSº®HÒºŠ¦*ø„1/g‰¾ßg±<0´Ç yÇ¿ëæHö0…gçŽ{z 8Gð‰ÈÜ'猟爑r´>ϧ e¯ÅçùŠù¢duò{=ŒªË‡ü¶Å>8"bÖ#xæ‰3Np/øEEœ.Z™&uœn±¢Mõ±è+ŽY. “–[ôâE}2F¾u®… >ñƒ)ô@Š/äÃ{k5æ>Mþï†ÇNÄpû~+ Ùm¼tVh’ "]sÎo¼§"•ûsJÏ3 vÈ*ü ûƒ8D8¡ „ #<އ/@’ „ fäñQ ˆ¯ ?ÉAD0ãÛ ˜qI ‚7A0=ßq^p|x3ô^‚ ίn,G æ$·!D…ÍÎ936bŒåÔÓˆZU?qà.×(ˆa–ó{£ μd±ðÏ©œQðïRHlçÚq(ìùAAœÝz°d¡`k^¡`ë?¢`{j;Qâ~h‰‚/›höil8ë5*hÊ…{T¢ Ž›åTÍ(Øy' Â'@¸(l8·H)„;›Ù(ˆ<|ÄFÁmºPž$8‘`»5ì$ Â#)$ÁtÒH|g‡BU“àn/‘`z $ öC~aI‚ï Lµ¦ Ÿ Øi± ‚ø"~AR¿R‚鯔 øÎ“ô¬ ‚éþ‘ ØõS·+b‚)Ÿ^Zˆ–ŠAR`´2SDp» ìšÑGØš¦@øF±íLpD!{›1WøR Zœ (|§VñÁM„[Öú0`çLµ0 ž¨ÈQˆÔØ#ï¬XC’!N%ìV¦À|’†@C ü½Ø †@x¶p=Á˜nc 麕¸ïe„| ï\ZäeÜf™‘‡‰á*Å>,„÷Lj÷’ËUæÀôÁJ ïÞ[h¬Ä@ô6§1îȳ>ˆ>@3ðÈàÅo=®á›Ç·Îˆ7ŠOˆ,ë‚ptã0f„Ógý&A,brªf O¥˜†™á<ó!Át>JìM§$ b ", sŒJLÿ¤DA»_$ –rE‚H¹>$˜‡ü% ÂÉŽs#“ :'Þ&A¤t²¡HMq2…$ˆ„hâ$Áô±JÌ·3Qí× ~BÁtYJÄU1U2 ‚¸ˆð`ÄEœØšÓÍ.Y0}þ’ñ¬H¼†ÁtèJL宅A”L’2 ¦eÂ`zý% öFOódA<áÉ,`Aûñ$ vÎ, îÇkLg¤DAÜFW ñ)— åKWPW‰T…‚ég™(¸M2 ¢äA> bdx˜"DW§•BAô?bQ0äw¯5 æ@•(˜Žc‰‚éÏeLµDÁÝÛÌ‚pÔ˜„/± ÆÅÁ`ºs% –«ƒé¯—0¸ÛË0 &ˆ÷ã3 ¦ g²`új% ⪛€FÜŘÓc&Yݘ]Ô,ˆ>a³`ús% ¢Sr\2 –rÄ‚qØÊfÁýʘ÷(iLo¨„ÁÝ ƒö®5 ¦¯V² >**E,¸G!Ã`z% ¦ d Ê9J°´¿'{Kƒ-vP |.Íú„áwÂ}@po Mmð¢z¼0ˆFy¤ ÂHy„ˆÂ~Xª1Âg—«Ì&Âü–$¦“~azG&æc5â½h",Y, b9])$Â~Ó5x+ƒ·ÂD%öw Ìú¥2¨M"Ä;~ˆpœ:Ì4‰p‹z© Òs±áÀ¦„88°_UR ÄÁS+„I„8ãV)ßYðó!Âц˱8C¦ˆ·šiqp'ˆÁ œÌ¤8Øš LD¸¯2ˆa"|-Õ6ŽÎ•²ÂÑ­3ÇŠ„ƒ“Ë„ïÓ⪻yp'¼Ã+ d=ñàÀ FÞ¸MSÒ¡Zê¡xƒ/Åóà:íÒ<ˆbø:˜‘åü(ƒchÅ?0Ï'N ³©Q²¨L@³¨ÊQΔH „¡]ˆH DëPg1¼¦K1!êå"€™pLÅ­ "ƒÈSLˆBúG,…ˆ aû–™.êdK3ᘧfàfBhÜ\O2îþg(]+¡I…¸ŠDj*D¢†©pàð×–«H…È"¡RTˆ”¢6óC…»S!Þ ƦBä!Ÿˆ w¹‚­í &[¼FP8ÚR0"…ƒ¡õc5âVtÌ0¢dŠ™†ÂÑt¸[Bán-Cᮡ°ä"Ï]ÕA \*2ÂÐçC…Ù†B<»ùB¤pÙÌTˆ¶—©pßÛTˆ¶àÃTˆ«Ø¦ÂRލpßÝTXî.*„Y4BTˆ3Ñùµ2æ)éI…H!™ Q WÞM…Há ÃT˜ÝßT˜÷N*Ì÷!©0û[baÚX˜ý6±âaЏ Es!¸¸•±'qÉX˜gb!йŠÄB¤prj,D9"0ÏÛHÄaetù2^Ç­©žÄÁ÷ôÍÞ ‚ÀëÖØ]üCå†eÄæÓë£ ¶v .…€; 6b£©ËÞ¡Cçç$¶¥Ch·wèZG1 ÷‘oçÐgÙ¥”˜;¹‹s¨üü±~~COFIì§e°tµ~aì—"™$bAùø –óäç)ÌUÁ@¬}qUܘ  €Þ3iþC²ºù/°…õÿaèüð߯nóv6]çÐÜ´–ü—»E·"èi €¹•ˆѧAï[Jľ°ñA@îúJ9pÙ1Ïü—;¦¶Ø’­®)›ÌHiþËS©ފ¾õÀ¥ð[\zR¼´që÷a-ÒzàÒÑÏ[¼»]<­Þ—!Ízà­äÖo;Ò¦x[Ú1þáG‚”ïÇ^ž,djh1þa糆³?¦ ˜¯| ‚ù8SÌ–° ¸R3´ ¸tÈÃo… Ý‚àíém ‚~Ÿ· ¨öK=ð¶r–z ÔÖo{)¦ xŸ*Åzà-Gù­ºóoAЃÂ³Â)z(Ù‚`–œ‚`•‚ _Ä-z4IAð–wóá¿AiÏ‚ NtåEoL ‚wj˜ït¾” H|H5pÿ¿ÕÀ¬\ª7ã:ýwòÎ%Y“[×ÎS©Täƒd’ãÐÜpO×q:ž¿ÀZ à¿÷QI 9|§¥Ú_`æÏäG<˜ÆÀw¨¥-ëgÚ#ÏBá>«toܧU,m欱ŸÁǽÛß™éøYË æ¿# 쎡V †'k y1þ(ègE›e Ìfh Ì24¦„Æ@.ði œ Ð2.:²ÊX$0rUHcàDÈŠŒü5§1p"?w§(“Æ@½±2‚¶À,[ऽZ¶À @—)0^+Ùù9J; ~_²ÎF«퀳ÑVH; i„…V@|>ÓÈ—U6@½á²¾EVõͱɨ_ºl€úùÉ8i$— ð­/RÚõ• 0Û¡ »´ro‘6À Ø• pÑ. – 0ž €œ)Ùÿæ‚G)ÍÜg¤ùO¿Y™ÿ& ë2ÿÍG¾ 2Kv‚Ÿ%pºöÀÀ…ˆ|¸ƒZš«Èü ÀÀvѸ¦ÀÀIwKºƒÚ"V#ÛZøŠüŽó@¸YºƒNº•Òô ¿ùt½´Að;î†ÓSùƒÞ2=‚ü,÷E~ˆ~G£Õ èg·öÆÆ•è—€Kô;­‰~žC#¸ègy¯È~¦ÃYÍH¨UØÏÒwD _ @~Öè§"$?k°ôËŽˆ~‡ùGoÞ Ç… ¡Ÿ=Ÿ2¢ßq3dˆèg^¹çæ ê9ÁªíÏžKœ|“ýŽ»c³HöËpQ²ßaŽ`? úÙÃ<6gPÛŠÀÑèg’±ÅÚƒ!Ð/_¢ŸIb¾ˆ~–ÅìÞâM;6¢Ÿ½8@È ¿þlº‚I6¥ñ*‘þr’IöfÇaéÏMèÏž^¼¤¿Rôg’kÃ?k8Þlâ_é øg’ü³¶ ÿ,"âù€ÖWßâóçIüKÕ‰6=×fý³2Å#TÉð…¥ðÏ::·¸@-¤¿|³IY‰ôg:Û€6ÇdžVæØÂí§€@ü;,hds 5¯‰0yÿŽ“ö{ ‰ Њ´ÍúwDâŸeŸ<7üóÍüæjeZuµVãÿlé}6‡Ðã€WšðÏšYþY®Àðï&þ™»þ¹ÙþŽ'@¤?_¼¡¤?sú‡Ï(èï %0ЯTú¥JD¿ÒH _©öc«¿œ:’ŸIúfõS<ÁÏlø™‚±¦’ülê@u ?“À…äw ÄKò³¬NÏfô³2»+èq`«Mò³ÎcÉ"ù™dnF?=I‘Ÿ”ùéJ ‘Ÿ†Cô3AØá@~êIägn›ÍÏúŽco¢_©ô3¥`;ú•ñýRBôã{%ò³Wx'?«Ô&ägj®ü4Ç$?{§á? òóMMµù½[lþ~m-áb€ŸKª#hÖ ìó¿Au'ïÜ™Œ¼xçÎÜÉÏÒÂ[óæ;´Õýìd¾W?P¯N€`¿æ‰?kP •ù‘à绳W€ŸW €øy™€C€_©åù†J•‹î½~.¹kD`™Ÿ—‰}0ÈÏ[îÕèWËL^¸ƒ'øÙ‹æf‚ŸMÕØ¼@sò~Þ¬uïÛáùA€_ ÀÏû’øùøªÍ¯<p_QàçoÑ*ñ€e0?—¬Í T–Â_y,€¿òÞ¼7¯Û™q¼FøóZ«:z™U½@ËKA´ñì“S,o0• jíæó–’KW @«µ9æKlºö’è öÅÀò“z­Àg`ùm‚Ë,–WX%. s'0ЛK–43òè6Ïoòd'ïEšÀjè;;Á{»³4ôrîÞžïVëØ2Á\šÓÛó†£oz{^'XIÞž]¦È{–'¡†t÷|ÖwÏ“üIwÏã$ÒÝ“>ÄÅÝ3À ¾žs~¤I; iϤ<íµ…rÑžùÈA{=2Ü&í¥w œ=3é =탕èìiîÖ›©¯ÏÁ .tö|9rö\ ‘³çÓiÙc&˜7,¥³§¥•ýQxÏŠD àÞ8hÈ<0×`»{ãDF\áÞ¸e›îÙo;öªÄ=Kùûfå¹”[¼—)g2 #ŠÈ{™JDy`î‹ÙcÀ{¥ óÀÜ|ZÉ{–6ÔR˜ÆÐ3ðžgŒ –ïYVÙ¾ñÞ´{’÷JðÞ“ÜÞ ×*÷J3à=[ÕhÞoÉ{£wÁ{ãa0yÏ”XïgÐÞ]F9ðÞ°KÍܹv…{™~'ÓÀ|ŽÐ¤QjâžåçÙq/{íåp3 c´ˆ{ãA–Ú’Fe€{gh‡Y`㯈{–¥^¤Ìc¿×@KàÞxŽ…õl¼q"Ö³/˱YûìùÇkMÖ³Êí™àÞÂÿÆDŽÚÌ£¹íùþg¯HÛh/µ&íYÖc!hÏ2ÝÀ§´g]Á÷´ge¶è?›òx!H{ÖU,¤={tÇ–Æ3,ÿ(¼—O޼—=î•À=+60Ÿ5;6âË'IâË|>D>KîœHä+e€|–â'|/A|ö\à â³ü=c³õYz¡øj’ø¬«° “ø¬ÌY“ÀØÛOPŸ%ý‰'Eâ³lB} þ³ñµ- Œµ36[Ÿµ©C@|Ê8$䳆‘_ÈgÛ¡¹Eÿ‰h^!ßX2ù¬VTñN*>›¿`.ðži€Ð:ç\¼—=“÷¬ŸµùxZ™«†þ…ŒNâ=îù7@dè3Ilìhè³çXKCŸ5&$úl:[_6L[ŸUz6/O¿í#øÆ>{k#>{–k³öYËà;Xû¤}ÖÕØœké\À|Ö9ü(Á|cá: û¬ó05ÒØg3qU?O«zÒØ÷°•ÓÖ—3C[_Îm}Önp}cÁº¯0-4öÙLDŸIÂN{Ÿ}BÎÍÞgí>°÷YÈ(„½ÏÊìI`LronžE“_Î1‘ÏZ§D"Ÿ¥ƒc%Œ~6äÂsä3¼ùÆBt´Ï¾7?ÏT”ȧ¹ ñåùòGE›_¾û´ùÙÓ‹6¿1~ù hôˤÑÏ~öİûåÒð—ï-ùÐò—C¦å/_Iå÷ˆÔ+ɲ= ‡+3´>~× aY¢f½þ(”µ²ÐwÕ~,»ûÍL%Y¶%95e™ 6%™¢z\=.åfS”¦(˦RRšzŽ8óPSÔ¦ +MIòO'ζð'»àçÛÄÙߤ½Ž¼ØíWþtâì/oM¿‡»2”4Âß¼#íös¢,Ãv2%6ª)±ÙR–bSµ”ÚRJlµURb«-•R[¥”ÚRJlµURb«-•R[¥”ÚRJlµURb«-•R[¥”~TJ‰Í¶jJlýUŠmýÄÙÝ“—Íïg?8ûË«ó}âìWì3qö/š›ÿ®Ø¿IœýËw|Oœýëuò·/KÞwËâoßýv>WÊo<_[úˉ³»ÙVmmûÃÄÙc2qöû¯?Lœýþÿÿ¥1qöy—ÿýëÄÙ{ÿú¦á}—.»ý¿O—í—ÑÙÉ®%êëú1ŽŸ…Û¿‚Ÿ´5Ï{×\2ý¤­Yz:ÿ†{Ê#;Úµdtg”‰sófiåÜjá© íh×âïËâ†3Æh± òl1v´kY÷¢eËùq‡À·žeà¶®îÉ"ÝÏÚ<¦#Ú~@à‚3ú~ü¨­™~Òæ—&Î(Ns.ñc«ÞÖŒmC–´Þ?is‰ƒ¤G–Çå‹8Åí=¦ ù@>> »Câ;DӾϭŒéÿÌz¬o›!y¢Èƒ;7²Ìô“¶ZfúIÛ+¹ñzØ8Lb¿Â^~ÆæÅýDÍ9§60n?cs‰©øùàÕBÝÚ9ã}oe†Ÿ±¹ÄA=ŽdÖVkú[­5ý­J–²•Z¶#™[_–5{][™ øágnßè–ÁXbáóÙ$ÝOÙj#ÃOÙjGqªT%ÓOÙ6‰ÿ’ª„Û?Iæá§l¥wË9·¾æåYͼý ­Ö2-곚ÝÚj¥á·šÕ†?i«’y„©¤HV¸ÆeW¦D¼in7êëx)Ñß$|áËXÖåÇl*pû[ir5?c+3nÙÏMÃ5üp¨–‰Ã_—øAÒû‚û![þš~ÈVk-?eËZí뵯—Úì˜-+ s¯yæV)Î÷k¥æÇlUÒý˜­J†³U‰)± ¦Ÿ²å;ûJü˜­gù1[Îyø1[©už#Vï,sõX½ÕŽ]Ìþ¬MÒîX½SÒ¯X½³qÅê’çŒÕ;kÍ#Vï,cZlE–Ÿ³Õ¯ã‰Õ;%çˆå;%Wå[í\wÃú-I»±~³sÁR–'ÖoIžë·úšÖï”,¬ß’¬‰õ›}ݦEmØL¶­«ûêX¿UénX¿Ùð>šUÒ/®ßlgœ?·¼ŸC«8Ž,¬›diG3kjÇí¾Ç£U<ÊxòÃíGb±vÛ*><½Ö¦¨Ýî7¶¾ü®Æ¾IÆ©U½?Vñ3–˜ñ~£ËŠ3ì}ÌM²&Vq|ÿ†} ¯¾IΡU<:²D/m›Q ŒîÛãôÌ*Û”Z\üØ~–WãÙÔ|¿MZÅ)YZÅcí }ì}­ùsØ7úÜfÔ¾Ó×ö<ÇյУÌÝ´ŠGW£Ýû*>Ì®¸Ønl›žvcó³wõ,.ä”Ì©µ’5÷µ<R9‘«äêZË!¹›ÖòXÑ숶­;–#|_Ë-w?×rÔ2-¶†Ã R%sj-G3ëÑZeìC}l ¬'v¾6Éå'nUr·ÅÜþuo}Í~},æ–m¹o“j·6s1G;ÏÒbÉt'‹"XÖò˜;û¾–ÛÇúصõ¾–Û÷úÚžè2%6A¿´–£«qj-GWºI–ÖrHæüXËݤ¾<9­Íú¢>îm:·2æ£1¶2wÓZI»µ–CÒ¯}-Óbkø9öµü•¬}-ÌedôM²Üæ[$->¯MbJ”|ìÖæm-ìs½­åq²éiŸë«~³ß*ógóf$löö$|&¡ŒHhóc&$&Øð•ÀZL6ì~‰ýDÃî7͇$а› û‰ž ßéƒsÑÐsáÇ™ÐгÚ? =—‡[7†>¾;è,а›Eý‚ 4|‡/¢¡_wU4ìnv® »-é… }†[%÷Ýð”!vóµsSÁð•ÀÂG0ìFRîÍ@0|çæŠß/ÁП‚Ûg †>Gà[€á;7x CWóI€¡?‡;Z0t5gŒ'À°›ÓÞ TtŒsÁó„`øv~„Ñž`è\! 0ì×…€‚¡g„$À°Ÿñö&z™P`øÁ«Ãn® wÔ 0ô¢Ãw„HlB0|ǃ¸]‚a¦xvsrt4‚á+¹ÂOƒ`د¹ †oçpÃ!ºd¿úGCè#*¾Eà6B0ì~Ã:œÃn<û©,ÁÐçë ò 0ôÎ}% v{°¨`د†Î†¥w€¡KÎ †Ý<>C\øg°«— Ë{.ô°G•à·Ìf'ra7¿wb!º–W°Zp¡÷ìælra7““»Ã“ _ÆÏ(Xèo¶GÄ »½¾±4 ½ó;š ,|ŸøI ,ìvÉvì¥ _¼þ‰…þ4ãù ýʼn5XèÎÉñþ }y‹é¾ø 3 ±ð휿``¡¿GT ,,#vû º³/±Ð•ˆŸ0°ðà…µXèÉ• Xè/$…~;Éí–WXè³üDË…ïsÅí_ÀBN̰Ð31d`a-XèÃq‹±°¼’ÀÂ~¹_YRa73L‹"A…þêĈA…¯V=‚H…o-øÃ“ }€þq'¾ZÁƒ‡Tè½@aY–…^¿Œ„Ân7´ûfˆPØá–•PXÆ(ôñÅjPè¯0 Ðg+~W€Â·áNH„B žè< ðUjby–µPèí¬ …¯ñ_„BŸdŸvBa:ç ]-ÿš }Â|ãJ(|ÛA ) Ð_‹Ê„ùÃ'úú±*úï3*úí¯þ|‰„¾´8Ö"„ïÜ`"vó— ½"a˜Öù«#ÇÍ_ÈP¸0«ðæžMvÂŽ y…뀼 pÝpÍ#f8Œ¨PñN¤B¦¾ð.„`Û%}ÞNP¡o¦Ÿ¨TønÊqó©Ð7å3$A…ïnŸtRá»!Ã-¤Â· .ª!憂Tè;žØ ßw0 ýõ¸ª¥ÐWPëBÁw‰ïdµÀ·ĵ ý*àØN m7Ò«¥Ðߘ¾="[«°P?na¡%šÛ°ÐB"FµöûD¸Ð|.Ÿ ÍÃrT{a·-Õµqá} ›·¸ÐB+Žj/|¿ÁøÐ‹ ÍéªöÂnqÑ °ð~ß& °Ð6Y1@b¡dø´;š XhýÜÕ\è öâE&ÞGûY­…o?DTRámïs4*¼ƒe ÞR_Š -s_XÚH…÷‰ÌÄ¢ÂûÆM±¢B`X¼H… *¼íŽÍ€ mÈ¡9±Ðö¨°û oK?ù£P¡øÞ¨ÐBLÐwP¡Ý–o ©ÐRÂÁh*¼íf¤j/ì¶÷õù#æ“#Z†Âð f%P¡.æÞΊ M§IPa>’ ¨#‚à9«·hˆyä(¼†xÙúVÝE_Z»iÐÙ#&æF“˜hA´yE@ -HÕ4èkMÌ УÄ~Ôå™B@½½B@ûrOÛqü(ü§ÜÞä?«ÞÿÙw<Œaä¿vÞ´Þÿì;Þ6» =™€2òŸ}ý¯ÿ,åv@,ùÏƵñŸÝZ20ÛjµñŸ]Wvnüù«Í¢0Õ]£ä>üÙ5iqH@øS¶CÁ_my ?K;G¤?%ý){¬èO×p‰þ”ZWô§Ôº¢?Kß0ª¯h™ÒŸ%Ò ýÙΩºŠ*G£ØO9hÅ~ÊÏ+øSzmÁ_[äÀŸòŽ þ”øWðgOéØàÏæ/ €7ó/7ØÁ~–û1N0È~þÛŒvØëøSÚdÁŸ²¼ þ”QXðטÊTð§$£„?f2û)¯ØÏzŵüËb?‹rŒÓR²_ƒÇi€ŸÅEÆG‘à§÷Jì§ ìb?Û8Çá.ÙÏÞ«V=EóŠE±ŸrÈ‹ýì·à*ý쎾P‰èça\•@? ¶YÕQÔk­°Fý¬L‡d1{~Ì ÑÏrÜßÕQô•À!Bèg7I†é‘èg‹<ððæu¬2ÑÏ2ì‡uˆègz~V&æ‹èg™ñ£ÈÏ^âØ¢’ülÅ T&ùYç£ø‰úòÛ)¢Ÿ²ò ýìy†D?åûûå3'ûÙZÌè§´0B?ÝÖ)ôS¶¡ŸÀôËGEôKʼn~¦ø Úú)źÐO‹‰ÐÏÞ7øsý”^èWjýJˆ~vOóØÐÏÒÌ ýt²ÐÏv±ñ%ú)å±ÐÏÒV/ÑLí,ò³Zõõ2Ðäç¡ÎQæÉ Ìñ &ùimùåÚòSºj‘óJ'øµ‹ìEð³Ô=!!øµ ï¾À¯À ‚Ÿ]ẃŸ]]}üìZ'H~Ù Àϲ­À>ðk‹&‚_?ÚPàgµâ•$øù3 øµ…͘ÀÏjÅ2Ið³¾æ~¶ÔÕhkë¯Qܾs,¢ À¯¿[Ñ8Q!øu;´Š:˜Šé¨~é¦~úö ü”+ZàÇŒôâ¾|æä¾ü0‘ûôý÷)37¹Oy”Å}ʾ,î³d919?¥“ø)[»À/õøé$÷åw“Üg»©ÍE´¶ ðË_ÁO—üL«ö7€Ÿrm ü”£^à§dÛ?ýÒ~J¢/ð³2ÅCÔ¯g¸1Á}ú6‰ûlM[1>pŸ}SލðËžH~6+°.ÈO çE~öÄ£’Ÿåê 'R€Ÿ½ÇA¡?»Ìõ ÀÏÞìçÏ™oÌþ»­xâ02Í–ÇÇ7c6ˆ»ÀÒGô¦ù#ÃáXUÂéÍöGN¢'IN¢ &H'QEÏÉI´1dIN¢ôóM'Q:è–ÀÁ‡1%p÷Œ—ÀÁ¶“`•”ÀÁ¹y‰š$Œv%n¾œ%nޤ7øT'ÑŒ’(qƒŠ TÜ #¦jÜ`«N¢éR\B¿W¢gµVI‰1*z°Áœ•уœÀŒ”Dу’(z¦Ÿ ägð %<ØhTð`+N¢ïŸ°/”àAI<(‰‚a*Áƒq•c‰TŲˆB)Pä i9ˆ"8¨" ”Dƒ–?ªˆUDƒ’(pP¦„ƒ’0p°Ãƒ §ØA•Qì $ ”Dáƒ}ÂÒy†J¢ðAµ£ðÁ”0|P…BRÂÑ{†J ðAURø $გ(|Pí(|Pe>(ÂUIგ(|’ ”Dგ(|pÐh¨ðAIÃ%Qø $ ”Dგ(|0%”@ეdøàØ©°J>(‰Â%i ÄŪ%|P…J¢ðAI>˜†J¢ðAJ>(Â%Qø ­ˆŠT‘ÆèAQð Š0xPJ¢àÁ”0xí*v‚ ¤@‘ƒ(pÅ RÐ6H¢)PÐ Š¤ Bõ#)PÀ /H]3^E.H¢)h ¤@±‚(TE JÀ@A 'HÃñwF R  A #HÓ}ÆJ¢AI#(b%QŒ`J#(‰b%QŒ %#(‰b%QŒ í#¨2Š”D1‚’(FPƪaŪˆbUF1‚,“1‚’(Fµ2FPÅJ¢AI#(‰b%QŒ`J–VlH#(b)ÉAI#(‰b%QŒ $Œ”@1‚’(FPŦdiÁŽ3œŒ”D1‚cÀ,Sb%QŒà UO1‚*£AI#( c%PŒ †£A•QŒ $Ф$c%aŒ Š”D1‚’(FPÅJ¢AÌÅ7y´7Ô›÷Žz a6B=¡Pïy˜†¿£3»Ú¿÷ülüÔ[‹ÑuD=KÚ&üì&¥0ÈóÓö½môü´¬«!Íïè – y~"Oý,§'rÏÐóó ¯Êóó0¤çç$’ÁègPpЄÑÏ‚6›Ÿ%Ù^õºm“Žø~Ÿ†ÂêwÛÙç$½~N0}ú}^¸ÇDF?ÛZµ(C¿O:éËï“Qé÷ys-¿Oúñ§ßg§ÁK~ŸvwLÔ‚ÝϼYïš'Æg hè÷I§ÙýÌõ¨¨×-¯'†?óŠßì~×CçFšþ®Hzú;ý>z ÓôgټÌ&¿O;$‰20ý]?Èôw-FFÒôwÍš#Æ­µI»ßeçR›ÝÏR‚·Íë3íËòú<.J`÷»ÖIk!½>:;ÒëÓ®?ùðú„…,–³¼’ž[©ãQÊëóÀ%géõ9 öôú-µe”¡Û'GÒíóòØÜ>¯Hš–^Ÿö ­œç»s÷ú´Ë7¶X@9p¤×çI·#z}âoÙþ®… ›ÒïóÀÍcé÷yž°ÙÉí󂯜Ü>-“jHèöyÑSInŸ'î!O·O>ÍtûäK›nŸÏI»Ý>ßu±‰tû”ç%Ý>_0@º}^ð¢I·Ï”Èí“OJnŸç¢„nŸžºÅÚëöáöIçLy}žô¼”×§ü¸äõIáâõ‰à‡ôúéˆ\Ü>õ^Èï“nÚé÷y#KZñû¼ñ‘ßçÍD-òû¤«Ü>å,·O¹A»íï ÌKàóïTœ_Èíóèt¡¤Û§ÞZ…ÚíÏa~c(àÃç«PÀ‡S,·ÏsÑÉ“±€\r2pуX±€æg¶ÿ.3üHò{‹ÐC¯OzåËöguâ'£PÀÕi‘c( yÆýHøóæµÙþìuŽ:0ýK0pâ²· \·¼@øÀë"'©Z€S¶6ú|2¤"'½Ñ¸è¾¬@@õ¥@À)"õðäóy6wÈpâ˜q€Ï¤(ãg'G1pâ®¶tùÔÏC€ëÂW àZte à¤ùR€ü²g  ÙÍ¢/º|žH〖¨#zG$àš,ÂH@ ÷­è—Œ4£]˜ßèóyÂ-#׉(WFšq7*1ðipW$ Þ EN\˜NŸgÍ ãýÄê¢0À…; 3 Ðl÷?jà\Œçc ~déïÉU>ƒß_úèïyàrKŽA›£Ç¤­Q€c0¸pi†¾]Ýá˜É0À×Ð( ouFše0ê0 pÊÊG‡Ï³ï‰aòךŸï×Ö©’Iûyî01eëz‰ÇŒ˜!–%jJìBY+ }Wí×™´§ýBî– KPrVS–kS’9«ç{úk jS•¦$ɦ–}ÌŒd¥.¥)ʲ©”üÓ™´§e&±Yù“™´óŸÏ´µé’j)ûùµÿmâ/¯Õó´õó©y‡¿y‡nû&ÕdÜh¥¤ÐŽfjm¶“…ÐЖŒ›-em´Tòg«%bK57[ÊôÙh©dÏVK*Ä–j"n¶”ɳÑRÉ­–Tˆ-Õ4Üü­eêìh©fÎÖOT…ÐÒßI¯ýXž;!þN¯ýëÅó·/ëàwkåoßý^>—Ïo1_[úËéµíæ…þÏ'×nÇPrmþ_“ý2·¶ú’[Û„Ùî© ýëK–mf‹‘eûÝíÞȲmÂÏ,Û&ûßú×ÿøFÆ,Û×úã,Ûïïþ·Çžñé.,À‰Ç~D~î{ã@òyü-Žp }^ Î}‘úy&ý-@Zï6–þp+yæA @ðcŒû IÄ…ÌKÙšýÏ›ÎiJÕfžæØ=Ížyš#}:·<ÍÏ|2O3Ê0¯$þ\yšŸu|äi~Öù‘§ùY×µgø|,óÚ–áó±ìlýÜ%kÏðùÎ\æi†ddžfHžÌÓ ÉÌ<ÍáufÉØ¶ Ÿó8”§Ù‹L»žš>!¹2O3$wæi†¤ÑÝž3¯„î’t¸[À;iƒî*òÐÝB’Iw ÌcÑÝ‚e΃î’œt·`_–)ìÜú:oº[HÒèn‘º[¨Nw IÝ-Të»…ŠLº[H²ènAµ®ƒî,c?à£m’‹î’Üp·`ßžÛdmEÝ-$ét·dÐÝBí²5¿{…ÌÖ ÉøÈÖ<ís½ekžkf¶fÔZ™­Ù%ë8>²5¯ãÌlÍÞÎ:®ÌÖ ÉÙš}ÌËî|~έ¦lÍôlÍË8uËÖ¼ì{½eÞ_ö½f¶fHÖG¶æe&ê­Èyf¶fH®lÍïÞê#[ó2ƒôæ½ìÖççÚÊôgϼ¿,ååÜûz2[3$ó#[ó²ïõ–­yÙ÷úª/ϲ|o[¶æeI»öJwfk¦ä#[ó2só–­y™qùÙÛ™­?ÊÖŒ"ó#[ó²Ïõæ½ìs½y@/û\o™÷—[e¶wÇLBmÓÓ‚xÚÖ—eã蛢2<ö¾ÆÐ¾ež¾gÞ_vïóÚ½·ìî«EJÝ*±´{›šö±¾¶ŽÚ}ìûòW²´/‡¤Í=óþ²X>îËc*,>ll¿‹ÛöåïêÐö}ù²H–µ©i_ëm_¾ìk½ ^%ÎMQ¿oêÙ%kß—‹Äÿr®íÃóþ†ð'I0Œ³cR¡…¦ïT˜RáliN$L*\ôƒ"šÕ>οI…ŠãšOdR ¾ËܞȆï²&L±¡].G6|òaâš$´p64¶‹d²¡¥Z$Ú÷$ζɆï>BEĆvi±×ĆËrúä ÍÈq@l¸.d/š$²ò‘ ×Í dÃuã~X±¡õñGdC«µ*ª’Øðý¡†ÁHlè6—(6´›—Ï ­–¿7bC+ãaâdÃÕƒ&6´J!–:@C›¤'ÚÚ7ºg ³o¢¡’¢ ³¢a‡h(÷/¡¡Õr[­ÐpÙȆ†fz¢@Ckxnhhjùl‘ ­ŽÛÅD†Ön ÈÐÊô Wë¸ ÃR dh?Ù–f@†E245ý§'2,š¤Eç C›.ÿEˆ WC¦‘¡Í…[åD†& ¢Z¥ KƦÕÜÀp¡QP¡Õ8C*,m€ ­Ÿe@…©$©0§†Thµ6(L …ù ³˜0Ÿ™ÐÆ×¢R0¡]]î ™˜ÐŠô K3`ÂÕO(&L5É„ÖNlBÁ„VÉ{bÂR LheÖÆ„6@ æ“#–vÀ„¸‘½0a*J&LµÈ„Ö»/€bBM)‘pù%ã…m§Þ£#Â|N$BktFaŽD˜j“MþZ-·èˆ­LP#‰0 ÚðÜÌ-"ÌÇ@"Ì’³/¡ôšžn–V„©°Ôæ\s.„ù5ò`>\ò`jI,=K-ð`¾×äAû6Ž x0;æ¤mÒÏà8à`)ÌóE"–JÀÁ|šÄÁ"–΃&¹þ€ƒE4­|Ö…ƒzzÂA=aá Õr%„ƒ6_¾?Ià ž§pPúÂÑ0pÐ$#†ÔôWì5§ÂÁìŠ8X*s.ˆƒ¥pPó.,µ€ƒ©qPo“pÐÊÜšÀA+ã @|wò± f%Ð`ކ4XŠ€SOÒ`Ž˜4heÜïI4Xj hÐÆwG3 ÁTœ4(¥ƒ) Z+¾Û êE f% ` @‚ùÀI‚ùú‘sjH‚Eâ+…" æ¼sÆI‚ÙIP£#jÁælsî‚Ù 8ÐÆ‡Jà@+2£ 80U"æˆÁÙ90ß4r`•,,áü’%ù ¶…‚éðô‚‚™õš(èA á74èwð³»9E><Ð`?üNHƒý´À‹àº ÁW/]Òà+Y±ƒ' öó¤=4ØÍWéª4øJž˜Òà+™áx|qù YÐKDÚt°àûTp—”³ ÿ~N`Án+Ö b;xoÏ   ú}6G°W° ßgSÌ;oÈ‚›÷öX¾ã༎{{ŒC2poo " z;ÑÌäµ=!sáÚ ú=HA6 A—€½.\ÛóJüôfÏ4Þڃ˰‚žÀezÜÚñ½ÈÀ·ö¼eîLÜÚ“ /\Û£†A‚UrâÚÃíྠ÷ö¼’enÜÛc^?k3 ×ö¤$@°  X~âÚžëÙAЋ¸½œ$è÷ÕFXš fx’`ÞrtÁUI°6ÓpqO6ÓqqÏOP’`mçÁÅ=Ò$èeÎ`Ì…‹{ôh@‚¥`™/`y €‚e2€‚›$.îɆ;.îáÓ –×0X^&À`þbƒ^+Ê39?a°–¹poOJnÜÛsÁe4è}=ÑNà`ù©˘ó—,‚€ÁÔ,˜ëY°è ,O3X°t ,à æ idA—ÄX°v,èíÄ9 XÐ%gÔš]w¯¹Ó Y°ô,eÀ‚9`ÁÒ9`°Ì°Á`yÕƒåÁËLk³ƒµ€ÁZ&`°¼è€ÁòS –Z€Áò£ –Õ0X`Ðkõb¬EÆ£E<h°64˜¯`°,€Á2â€Áò› æc –Á³#°`YÈÀ‚eÁ –Ÿo‚`¾mÁZ&@°è X‚Em€`þZ ‚¾Ïj¬eËÔóU' –¾À‚EuÀ`• –—0X´ Öñ¬íyË[Ìoa°$üY4l°áÏBÑ üudóLøë7°Xð×r· þ:®™JøëœÁ_ï„HÂoÖLøã5® #’4&ûõ Ò#úÙ•ƒd¿#L²o¢ü‹Fø°ÓˆýÆIj#ü š„Ž» ÙàoÐè"ø³ëªл »–àoÐ!Gð7èH#øSç‚¿°lŠüÆEú"ù Za„~yÞýpwm’ß ±Iä7"†Wà7hqø ž· üÏ”~&qŸľؘì㯉}œ°O] ûö…}#ªù²Y2_ìÅ*óI"æ“Fb¾Á“~1Ÿ#æ´Vˆù† u`>>!ß u@Ì7> €u|d¾ì›ÌÇ ò©’OÃò¥„ȧ†…|ƒ–1!Ÿæ\ȧ!ù¤·˜oЈ)è³üòÁ’¤>u.ê‹·^ȧ_)‘O¯¸5È{œoážÞgá/œKÜ4â ÷ô ÷† Ä=v%ÚÓ$ˆö´`÷Fä%HÚÓ"´—5H{ªAسéö:öìAEÂÞ `OÁÞÛά–¿²š ö´” ö:îâNØë¸Æ5a×, özä¥HÖ³%6Z!ëõ©’õ:.,IØëHF°Ç•`=‰õúb Â^"O@Â^JH{Øv>Ò^§ë†h¯·ø¬'íõ¸¯$a/‡GØë¸a%aO ö4¡‚=Ma¯ÓõE°§¹ìuäOØË† {Qq {z¾‚=½]‚½·©„=ÎEÂ^‡ÿN•HØc_I{¼-\´÷îjÂþ!ÜãŽ%q‹¤=ns’öxQyÒž]Œõ£Àg4aÛž„½^@ÉzÜ”%ëñUJÖ“Úb= F¬gW›T/Ðü9$ëYÖ `Fž%žªv¿|ß’öø€…{Ô[´×qQÒž¦B´ÇKæ“ö49¢=Naï]4BÖËfÉzzÚb=®mÉzª%ÖÓ¤‹õ¸¶%ëõ6d½ŽK’õø‹IÖË2d==*±U`=ý)ÖëðSKÖãn9YOo‰X¯4’õ:<“õ4çb½ÞØ;Y?Öd=ýÅz|2b=ËŽ$GØk¸ÀI°×qu[žF#Øã¢ž°§ ìñ½þ É´Kt wsÅM<%:pÆ)Žü@3\~ 6Ã{t ýzT7Ð{ÑÅSÁÈ@S‚fp $Š”Dñ„ž }IµÀà u-XíÜ@PZAÚåß*”Ÿ¬HÐsômib,·.L~ |%OXëø‚yd­Q@ $?6Úù$´£ƒêÚl}xU@`|vj@`J<ŒÁªFJ¢€@;fùQã%`8 >„…ု¶¹†p@³ù…¥á€ãˆóì Ì2 ´Ë½ª ¨Kžè‹á€)a8 ÛQ8à+èÕ Ô%0é1pàNÐ ŒCgÅòOâODf{Œ'm{ 'Ìr Ì2 ´,­ÕþçXݨ‘* P-+ PãQà8`0Qà8a‡Q`–a`–Aà81• Œ‰P zV`JÈG–A€zB Ì" A€Š‚5 Ôô)PS¬ À,à À,à @Mº‚UKA€)a eþÞØÏ$ñ`˜-# 0ŒL ³ajz¨éQ  $ ”¢ ÔãT$`–a$ Þ.E Bõü ÈŸ·B5d…fW Ìá0Pe ¨§NöË×–¡€Y„¡€z ˜• /²â¥€â³Æj¥Q &Bq€Ñ¬‚õT¨*ŠL Ã5˜Ô਱) P“ 0Àìša€ÙÃõ¨–¨Ç¯0@=%…ª…ªw…j„ L â³sÆn¦ÀZ€A€Ù3ƒÕ³‚Õƒ£UEf †ÉÒâÝö@4Âø¿,Àø¿l„ñ)aü_Öb jø L 5 TW ̆¨ç¨Àl†€ ³ej S [Î@9ÙW¦„€ì=S‚Àl˜€Ù s8 ä‹”€Y†€j‡€Ô<Õ¹ÕŒþDôÆŒþË*Œþ“’ŠþÕß³¡9†þi´ŠýK cÿúÉh;ÄþE? üË üSÏ üÓ`ø—µø§éfà_aàzfÔ_ü©?©§˜?µ  ?ͬ‚þÆñ7öx¿,Ï€¿”0àOê*àOª(àÍæ¢¡~¤Bý4[ õ“j õËZŒõËZŒõÓ0ë—eë§Á+Ø/[f°ßØ#ý4Eú© p5æ—5æ§næ—m0Ì’’Aû<,Œ­¤n=Ï÷ɼÿRX–¨©°? e­,ô]µ_gÐ>1Í%.¦ äª¦,“Ò¦$sU¿Ë…ùEÔ1BP›‚¬4%Imj^[CþçÖŒIj#ñ÷?9û´ ïãïfÎn!svk+sö××é°K¤fÍ)üÝËs>ùÐãG;™› Õ¼Øl©”BS[)¶¥ÄØj«dÆV[YŠmÕRlK©±ÕVÉ­¶²Ûª¥Ø–’c«­’[me)¶UKñצôØl«æÇÖ¯4K¡­¿“E{­·ýç?=‹ö¯Ðß¾¬…ß­—¿}ûÛùXB¿ÿñ|ié/gÑ>íÒ¨w;ô‡y´-ƒôÿü.Éõ—<Ú{¾ë"öø¦Ýý7Ížý>6‹çøá÷ ¾ÛIJÚEòîÙúJZœ»ó"ùWâV »=©Åß#<,nܾôJžÛ¿_÷q¯d^n¹áêóJì–Mb?mû€¾û 0ÉúÙäuô¯ä”‹E‹¯÷e!{èÀ3âWÒúf~%vÐj\kÿJnˆï¡ƒ]t†äŒ™ð›]BòÄL\Ð×È¿(²w µìž¯µ¸_É«CM-þJnxXd-Ë<´×¢W<¼’ÑöÑ<÷^câÌ=% î’´ãøyH AJRƒ'zjH’Ï®YÞµ@§æ޶2~§àÖθ©%ÔÏkÿûÕàÜúé¯ׇ¾1üþ) ÏxezŸU¾ ¿ÛUç{-so,ÍZÀ†½‰gdçx%ïgíU˜÷’sôÈÔþnßÑJVüšÎŸ¡ò8'3¢™q= »3$-^ ¡ñÇŸæ»÷c!({#öÅÜ™'5b­unuž¿$1~tü¼£¿¶&‹+îAeX u*CÉ—Ñ?9zJÞÑïú<ïèw}žu|è3c«3õñ<æ¦P-Ë2¹õd7¿ïZMs~Þ%¯»V3u`;©ûZ%¬µÖ‡VëøøûœÔªÇëíé÷2©%­J^v­ÞÏòÇ‹·žëC+»bvVë‹+uˆvÞoÿܵ²ÏÊ^ÂÂ0÷÷ص²Eg2ö˦”XDI{Gw­ì5 V”¬cV¦Äþ¾Yµ­NꀞÎkoþÈç.±¬t»ÄüywIj@É ÎWƒÉ:ö'õJÖþ¤Îë˜:]çó¡Óu}Ô¹÷™²ïñ®‰WËíy ¥YÆÌØ-‚»NWjÀžR–YëCâwÎî’óÙß¾Ó.…\[ï7uàß_t°ïñ¹—÷Ç“²»Bï½§y~hu¿:ôú %ëã¹Ø…λVv¡ó>ëv¡ó¶Rœv¡óþ¤ZÛ߀–:°•Ô’çú”ÌóC«¶Ž­ÚZo[OP«C‡û Æ{%×øÐÊ.tÞŸUomÿʾÔ¶ÿ=°—»ãO)æèY~åƒôþ‰ Pü9ì~ðçùìû‚sä )Ñ ãÏÖ>žŒÝß¼ë0Æ>£ö->÷óüyí;%ëCòs_±Ïç|>Þ·ç*٠λJÏžÔ-îâÏg®}Žw•ìs¼¿ZÏæñ±{{×±§>Ÿy}ì2 Q ´ö¡Ìì÷‡2sú|Ê 3gy™ìë»ÿbìë»+ºŽ ’ØÈÒãÏ{ßïüÙ´×":»Q³_Ñ‹ßcÝK}äµð;{"βB’è’Ht É’è:òy%Ñõ¸{1Îlá!ÏYŒçÎscÅ™QòÜ—±'Îu¤Hœë‹Ã œ‹‡/8g¡¡(œ›CÃ…±v‰së ’çVB`háÒàĹÕÙ;qnMláIsk‘@s–üFWn²Ã[”p“÷qE ŒhΜsjsðrú=aÎn"='$>~Ë3Î21þZ&hÈÊL” ZR¦æL‚yÌ-Ëb·Áœ&[9ËVŽWÑaÎþÆÌæ,Ã9*`ÎŽÖI8K0/ºxÎŽoH 3¥‹çL‚×Ô ¦3 ^rg:¿š6t|¨BÇïø¡Ù:†×PgEè+¸Î/¦~ÀuV ¯ÕC ž®³2äÃ`"“àl\gÎ| pµƒ—ѹÎþÆÙ¸NÙêÅuVfÅh&u˜?Q)h]ø3˜®öLg5v¦+c›ö“ãçX‚‡,+>û ²2«0­WÌ ˜Îê°D0rë‹éj+ÁCÊÈ/¦3 ~¶`ºÚN0]-LW[NX‹:PB¦3¿„Ìt¢Žç?ÓY‰XÈtæ`è© Ät&¹cߦ³Zì)ˆ¨Ö "ª-Óéæ1]­Lgen0uP­3®@0µ1P#˜NwˆéL2£0]-C nõL .,sdº:– "»âàØ˜®´¦+}é¬ vâWèpaù ¦+­‚é¬tµÑ@ºZ)Î*­..RDº\ˆtöªMR ¼y…tùƒ'Ò™„Xu´ôã%Ò•×HW{ ¤«µ鬧‰ZtZHHtùû!Ñå@¢+ÑåÊA¢+Ãq¢ËÕ†DWë¤ 1]ÕÑÏ%Ásetà¹ò[îÔ€k y®ŒVà^©Ü+=÷ÊGÄgÛù#¦ЧÏ÷_Èq–¼Ç~pûÖÃ]2°O¹ì}Šwö)PAØ·@`¾eÛ_ “mn"^¬ë–%- oM¾\¤¾51žS߻ٿ¸Óõ­·ìS}ëų›3Ó[«GÖ`Ÿ9ÿcì3‚ c_?Îc·â½­‘Ø÷JΟՈ×-d€ŒçÔÔ-ª*õù`Z¥>èØ÷–ðM& š†}ux·gª;–þ¿cŸ— ™Ï¹¯›ïäªÜçãÅö±Qƒ, ^Ú¹@pNM^«CâÔôJz¼û¼ÖªÜçeð¦÷½’Ge\‡ëÀ»îÜçmÜ‹CÓ+™‘™„Ü×ÍûÔÜWGÜWGשÁC‚KfLg`Ÿw5ÐŒcŸK@ÞÁ}.YÕ’÷J¾AÎ}U¥ž*\ļ#$‹€àçµàÐÁÏËÄ`‚û¼Î}> Î ÌE0MÝÂWZžWró= ìóJÕÀ>¯…fÖU€b9|¨ü`ø©P`_}J}^?äÀ>—ÿ;Ú äÛ*8ò¹¤æÄçK4ê`ôo‰³ñ¼ tÎKåËàÛëÀWVNŸ—Á~/€¯Žï ·î|>'˾ªrßÖ†_KŸ×Â6÷J V5âmí8.ù2~¨Žù¡S_m9ˆÏg«Ÿÿ½ñÊwÄç_ךs\²Zñ§ã^ºÀ½òiîÕ©¹©€” Þ«Ã Þ{%'NÃÀ{[ç= Æ`o«ÀÑ7ÎJãèVƒö¼è4po+³btž¤ðÀ=—€§;àî¸W'"pOà ÖÛi±ýIŒõê# Ö«º§›Ï7I'j-l€¤dО·Á6v`Äh¯ö>¨€Æ7¨CÖjØ…’zeç¨çƒ‹cO ž7Š™ ÔÛ$T [Y‹*¡L°^Y0õêò¨Wç*P¯¾àÇŸªp¸õ\‰ð sÖÛêÌ“Jaƃõ|k; ˜ÌI ôæM¸Eç[¬gµâÏ»S#¼Cz>60\í›-ÕšW§aúðó™çÕ‡œ·lÅîçX°:ó\rTΫí®}ôôç/ú¹«ì^Ž[›‹¦îòL²{ýƒìL…Í gÔ*ÙUè ¸+?À]yw<±.hVwÔXd§EdWV5]ù¸ˆìN®À¢AóMoœ`È"Ùåv‹d—’6½$»·ÚüÀE¹$Ù½eàªJ²3SXdw5ÚÌHv¥Œ«`óQÉ®ü ²³£%ŒdgÇn;ÙÙõ.@ųì,?:ÌjÀ"y¼Twß?«g¦èÕ˜W%Ôe£„ºûä1¡ÎδQ Øi4h Ld'áÕ9së Tw·ÈÕTw7™C…K@™:œÕœçjâM$Õeߤº·]$‰uf¨š^怅:d-`QŽ`gËœAv÷MS'Á®Œpí#&Úåí^ Îhˆv9>¢]Žhg¾à@2 Ý;>°4ÑÎøe¨ƒ´"Ú•¾€E¥/ ]Ö ´ËD»·o´B´³O`*u@%pQ˜d—J²»ogDvwãÉ®t•*Ð+3Àèíñ¨~šõiÚå\í²Y¢]©CžEíl³J¥šd»RlWZÛåˆ w9ë¤;=Ñ~g ;½%Â;i%¼Óø„wšbឯðNo¶ð®ÔÞéq ïÊxÀwúuŠïî[ַСóä=ø.[%ài½ài5áÝN£„x¥ 58‰…à#3סaðÑ[ Û ž–Hžš!àÝ×S-ðñ×sáV áVGáVfá˜æbøúð ï<:ý÷BwÙéÎÌDà=о »l l¶¼ò¡Ùñ[*¶³=šÛi!¶3o 4ŒÑsO!´ã™ŽÈNì²Y‚¹eÀØçl§íØ.[åðo*D´+•@FæËÛÞÒhTÏÌ2þžãG3$;v‰ìrwv=\ÚÇl—§>d;óÙÙN[-±Ý9qC´+E€v×é»í´«ÚåÙÐŽ'•B»|D»Ô’tW$ãÞæŠt—…t÷ÖiÕWž%á.¥wy¼EºÓÁŸè.LºÓžè.LºËw‚t—JÝ•¾Awe| »œbâÝÛÓ ƒu¸aÞå‹O¼ÓÙ/Ÿ/¯Táåáé|*¯Ô™ç>^®$¼óᇄ§Ÿ/_#^>2çá/¤¬NÞ»<ÕXµägL†ä b Bò8GN&N+œ (“§B©èÀ™¡%tàÌ0zp¾l«’×hk¢ gkªÅ¼G*EäÉiRyM–ºˆfëŒDTD^§ó(ò$ (¯s£«p¼”0˜­“cŽ—†ãunŽ7ð Îp¼, d‰eË¿Ž'ÈU8^ÚäŽ7 ’¢ñ$àø%`0›Œe“€‘x0oaˆ—ŽžÏkÿ›¡lcÇ=—Óˆ7>|7«$‡OIŽýMÂX¼!CÂñŠ„áx)¡ü;u˜›÷æ&Y?÷ZŠÇK ãñRÂx¼”¤”0¨-% jK CòR¼”,Œxmî››äSEåeµ¥„y)a`^¶óE‡ç‹ ÌK ƒÚRÂÀ´B`^þÍÀ¼”00/%_tP`^JÔ–楄yú)0/%©(1Uè•÷J%ÆååߌËË:ŒËC³–—ERJÔ–µ¥„ayj˜QyY„Qyß™ôâÁYK\{ŠÊK £ò²£ò²L*À2©%ŒiËZŒiË2ŒÊã§$£òR¨›ÞŒÏÃ7Ãó²5P·q£œÑyM>”ŒÎkr»Ìè<œ4):O]•è<–Éè–Ôï<_Zúë¹Ì.Kbvýÿ•ËìÔ¿ÆwYÍþõß «ÙÕψ2ðãjá—°3,úêväeºßñwó#ûûæðêÝì›ÝÝ€/íð#û6gJÜìÐï†#Õ«?nvèóBÌÂÕ§ŸÙ[ŠUTZ~dߺ/]ãð#{;䊭Ä5N?²ï–õ –»ã¹ñE±w0ÃŒ8¡Ò°»‡=süÿîöãývÅYÍ5†Ø[.ò8º~%~`ßn•|%Ø{:rŒ.°äãa.ºFh0,IG´ó~b?Úä„>§ŸØŽë ýÄ~¬gë×sû‰½ÕŠsþëq,f­@‡¤_Éð3{ËtÆŒWâgöÖî2ŸÙÉ­ë™~hoäd >¨81¿&tü‹_’…L§vÍˬå°)^–©dZ˸´ú•4w¾°¶‰ÝÁiûú­„¦~CßÔ¡óÉÌg†¤!˜àšÓ¬ š]î{ái×£’Åë÷ZÄCäß"ö¢ÇܬÐÀúÆÓ´$“\ô|»Vs¿…§éͱÛML§÷¼’w1öù|ð§{^<'s¼«¸+ð\‹Äøû±`¸k„¤Ã{îöЫ„`ˆÛýXc('Š\w¨D?°û t ~?®¡ÀÅàÿûèîµ`ÜiÁš 7†w×hß4o½{\w¼ÈYx—Iw¼èsa‘x?ŠÒ æå>© ïÓÝ»½åð&»ßO¸+ea}gHnw¼x0”³¹×ÅÓè{pŸÿû{xÐxÿGØÚî—7]Ò`ð¿ÏÇU~`¿_6 èjpŸË.ì7~q÷u¸Ó…IÂÍá¾0þÆ`á÷Ëç. OgÕ}Ýî²ð¼c„_Í.j­îN6àX5^ÉŠ÷솛È}A…›~Œ÷å:¼¿ÀŽÑÌ'þsñý¾y¡ÓÄ öîTÜéâé\Mïw>ã)E“7†ßè•vß~c Ü}·3$Ì‹·mGLJdÅO‰VÔû3êÈ”yßû\tûac0T¯ü½âÁc»ÛÑcq`Ž„w(-}Sîv¹×…½ ˜¦æNöHâO 0˜în¾]8tA²B!tßmÌxí ™w{žPˆŽ2w›#^;=‘æ ØmÑþgÇø;£ÿnûŸÛëb{dÓh |ï~_¡ÑßV÷׸¾š½ñ’éáw¨`ùfB ì†a4ìñ>U Ï:1ôð¶§³ròÆáO~aq¾ÇÅý»¯ã›XÜWH>eàÚúN~„FŒæ}%+Þ2ýÆpÇ‹ò¾ (`gghyŽàNöW²z¬Z O Sk=g‹ÇÖÖÛ>ÇgLLìTî:XÂø˜‰:ä{æ]ÄŒ7´ÓM}Ï)[~žxN ®Ô÷:]˜ï‡:h…³k³\2ù;µk³L«qÃÏíž×½×¹/¾}pÛçøÚ^ü òÉLèÐo|ï9fHœ³ÜXÛ··Àò½Öêñdp§½7¾láñr/è½/w|ðgßñûý$ï·3Ö-åöA¾bÖñ.ÅE\ï›ÃÌiïÂ2?~Aë‰mÙâcþÖñ)â†æ¶ÐÙQßÉæ®VfÅO¼y¨QtæˆvP….í àøøn¢Ï褣…~P¡ðÆoö=¾êÐÞÿŒU›GíàðñoGŒÞ¶êßúxW±Ö4»:kÄÐbkÚÎ3¶@­Ã§±ÙÕYSˆf÷f­º2¾+ðY¿òíÄøsüšóúÉnö9¾¢VƒäÁˆéYÚ9÷Ã¥ +m¸éfÓŒ‚FÝ?´++rÑìæ,SéÄ5p¯¤ÅÎÂìã!½_dÛÍ ì‰Û®…¯Ù÷øŒvzzžØÖ-|âÚ5÷uhfÅè¾±EçÉI~ÓÚMPã¿Ï÷þdº3¢x‰zž* |Ðýò»®`×.¦2ŠÁõÚj·0nDšÞeGÔkë¹ñêµ5ùYê53³‚É‚õ<.8¬×ÖÄ& ¨÷ KzªXqÔ³Èø ÖUÓP#0©JFdYX‚ žµ‚"Az–Oô2€‡¤—A$½ŒÂ$饷IÏœ(A ½ ÂÒ“KAO1¤äÉy AÎËXr^zåç¥s29Ïܲo tx—'Ð58O>«Ä¼tË%ç¥o<9/½Ä zÖY*ÜÌñGг+ 'ÚipPï„L€^zaèYO‹àû‰e„¤çW0a4ÐÁr´£•%³ø:õŽvqoÖ;ZãάgZ-Ðt°Û’ ꋬg-¤¿ðPàÍ¿ç{‡í—Ð÷ŒÌYþª¤êé¤'‘°g}c{ Ø3­N°\Àžõf Ü3’UÐ>ö¤ Ügƒö¬ï§àžµŠp¯J÷¬Ù¶ážIN@5àêCÜ;Þ=L˜áˆ{Ö7ö›À½Òp¯Ì1p¯öNÕ¼B‡¡ÑÌ'zîîÙå^8î™d€Ë÷lƱ/»©A4rsøê¸W:î•iîY™ Ü‹ÍÌï¢=OgÈJóÙ4vÚ+ƒöª$h¯ ´W:íùgÑn£ ‹Ï$±øl4x£|ùR÷LLïÕÎC…‡ÓÝ©‚€Ï$„¹¦òóð•wÀg €o“@…l9UÀˆA|6BJ‚øª$ˆ¯¼F}ejuèØ³úÊ£ô•¾}ÖÎ}&iÀ·€>¿:µF$ÃQÞLB_ùýúÊ\úJ_€¾òCuè+¯ ¯Ö¡š‰‡:èÅô•¾}µ€¾|•À|¶Rè*èËAæ³28óå·„Ì—>Á|öMÙ‚ùÊWÌg=Á|ùá%ó•Ñ€ù¬oÔùêøæ VdÇ`¾üò’ùL‚c”E˜·ˆÌWúræ+ãó•ùóÙ÷ç¡$2gS“ÀŽSŸIb¤­Ï$$ª°õ£oüçX=.è•þC†<‡§ÁäZâ¿ÑT#L}ï6³,þD.òßs¨Ç¿”)þ{%<zÊ2ä¿"ÿ%;ø¯”i0ƒø ‘ðaœ0L|$|ñÿØ }·)|!%|Nèé‘–X$À"qÌÑ&šA` z*ÐÓÃx"`–!f_$ÀJÀ€žKDvÊÇBþ3¿ðbè«=ƒÿJ‰Ôã%ÿ•2`'Fø—ПF'ú{.™ä¨Á)„z–¢¿RèT$NÁDOC†©¯líHæù{[ª@ÃØIOEô—:þ¤8éÏBS` ¤ Ù0U¸99Ä¿T"ðïa¾7á_iø—⟔ð/LüËžˆï ëñ/ÇGü+µ€ù€‰¥¯ç£Ä|ê‹%üK ˆ…Ù ñ/µ$æ+A,µPÙ; 0µ$> ¿¤Á/·@À|.€ù70ÇBÔ"&L½‰€¥Lj@ 5ÞDÀÒø©”ê%–Jklsòˆ€9`" –|!`)ÔçFh„„¾ ‚mÑT(àSé 8˜›Q˜/q ¿"Àìš8>[`vML)Ì~(4dÚÌ~…†GªðìXÆ|ÊÞI€ƒ1° ÀT›˜ã{RJRÖ>eß$@mJD€oß 0çëIØrꀖ‰€9;DÀì+0{"fODÀA)!`Îð•;–v€€z-H€ù`H€© P;4`6L,eî«vDÌPŸkýŒÞA‘T`q‚É9Àœ ¦F¨Z@i ”Þ @j,žJ£ÀÒPƒêê-ŽG;À“6ÑÀ싘#$ê¦Ò@½‹À1°Ôê7&,}SõML­€9Àl‡˜}õʆå/Ï…€¥0Ÿä"þ+Ãÿ'D«[8f‹ø—Ï¥8“÷?“MÈgñ&Wšü–ù—ÄÜä7™ó¯¦˜Áä7zS?%¶–ÅoðÞYüJZüd×¢Åo0c§,~£Ës&¿Á›hdò+’Paü„õ®]ñgG£=òªº¯ÉâWÊŒ8²Ÿ :~"±ú+%iPÈWkòm’3«G®œW$VÏ–ù6IèðìÈ·µ;Ž/’H­^j=‘Z}LIæC­Fe>Ÿ‹Q;½LµùUÅù\Ò«Ío“´“J¡+C¾­ª0 ©3U€à™‚ùP%ÖYƒ*­êÚYËðÕ±¬Ô€µî‹’J|[3ý JŒc›Þ¾­ HÉ øÊX@|Ùˆ¯TñÕ"?GàsÉE¼;(a™—Ì”2ãKÀ·Õ¹O¯+€¯ï¤j7€o+sÝTŠeî¸(§”iç‡VgêÐÉ€ÒµÆüÐʈoû{>ÔŠ’5ø¤ â«}_©Ë\÷§ä¾¨½BÛI­ØN?>´ âÛ$_t¸>t0âÛj¬ñ¡S_-Ä·IRÌçPÒNJFµùmíôEXkÌ÷F?-ZN|[‰µ·ÄW{â«ýñmeî‹:Q’°VjpU/Ï­Ö˜Ôé¨^žÛçøxNíC‡ž:ÕÎöñ› ä«}òÕvù¶Zý V’¬çÒSJžçç>ë|[™Õîë€!_-1RÌÍHÐn0ßV+k­~|¬ Á|›d„Õoð0ßVfŽ­‚ùj™`¾ZƘ¯Ž/˜o«Cžù6I?¾HÖ¾‚ò•$oëŠ*dªÀf‚øjOA|›äÚÇÄ·IÚ¹}V|å à«EÆÜ¿³à½M2ÇþQ Þ«¾R`*@꺮OÉ}íušöC,Ñ]%üÞwæªÀWWŸ¾ZiªÄžÖÇŽ¼WúïµÜy÷6É}í·so£??%Ú ±ç1ù”ØJ*°ßVfuJP&€¯– ૽ðmeîsߥ:ðm%¾èÀ·•óC«¾­ÌZ_t¸¾èÀW{àÛÊÜç‡V|›Ä-~Ä ðÞÖõ˜”€Žƒ÷êÔðm’¥=:BLqiùN®J|/°Áóð¯¤GýÝ¥Á/=ÖÂàgcÅßað;“ö2üìuX›Áï4›2ÜFÃàwšãÆÛç)\¶Ø¾ÓŒV›ÁÏr­Áþƒß9ïÝàw>§ìnað;ŸNJ7øÏ‚#\ü,/ ¢à`ð³· Ñk0ø›´9|ZJ·=¶Ï$t5…‹7âÑâw®FWRXüJXü,x~®°ø]Ç^…ÁÏv›Wqø´œ4*\ƒMhñ3 ­ya-»,!9È.,~–ì¦ZXü¬Ì IXü¬ ž%,~öcšÀ6¨`9É! s™í†ŸÍâw¼.‹?K¬s%þuËË,,~×É@(Züª$ìe—]»²YüLBŒ ‹ŸýØéw?“ì>Ÿ¶[§Ý :XîGØóÂbv] Æ%ÚüJï°ùY;Õæg=]›ÍÏâe4H²'êÀK„ió³¾i¿ ‹™•¡å-¬~6ÇpY‚ÕÏ2ž]Oǃ:Ðß™V¿Z&Lf×Å!Âêguà™ «ßenô„ÕÏÞ¥Y!ÐË rV?“À»V?[†á*«_iV?㨶™ý¬–\ûßaô»ní_`ô3 cúÂègBP;7È2a23Éfó«]…ͯvåøJ’Ãæg³­ïùlÍ®Ð/L~&!‚…ÉÏ$D°0ùUI˜üLBÜãø…å É ÉR_OU˜ü¬ ÿÂægxµµ5¶¿aó³­b±`ó3 <ó`ó«µÂæWË„ÍÏ$°™Ãæ·IB‡"¥÷0˜Ù;I«dØü¬ b¯`ó+í¸ÍÏþ~6£_-hô«’0˜•ÑÀèWÛ £_yæ0úÙï ®µ0úÙ|÷Â`Væ F¿ò¬`ô3 â¼ÜèWÆ£_Í“:Ü[¬_™?ýüWN3à ­Râè}Ê £_m'uX•«0úY­»"` 7úY‰¶ý®†˜ÚüJG3U`³TAŠÃæWk…ÍÏjÑY4Œ~µLý,ƒ†³¨Â%‡M¨P$a2Ë!»ÍÏþ¤_hýj³aô3 ¾™0úU¸SF³ò¤`õ+O V¿üuÒê—k­~Ö¼&Tá(V¿M˜ýò]£Ùo“,® ú ³_®‘4ûåÇ…f¿ülÑì—ŸCšýò{M³Ÿ¾ª´úÙ‡÷u.¬~Väš¹ –ÔžNž¡‚~ª´úYGçïwݛɯv&¿2 ß®nÞbý¬UÄEÂâ—› Zü¬¢añ³†çfñ+¸Å϶b H ßœ6ƒŸuÝaH ƒ_-3±£{öP?+2+ÿ•"0øì}³ÓÝ3Ó¤Yj®L[õÂݰ4³¤IC‰-MÚ^(k•4ißTû iÒ¾ ‹‚-!ÙÞÅIÉmÖïöl¹Í(¨MAVš’¤6eUjÆ5 ¶¦BV›¢¤45^$ÎT`ÿ•‚Úd¥)IjSÿæaìMí¨>²¶¡ŒZçuÔmùû÷â‰ÓD‰[œÊ„–W;°ß.|+yÛF=F|ºcY· {zb/9Ïè§è¯V–F»¡åÐáEJŽø ÞïEœçYË ôÓØW«f‘˜w kÉþ.ê`$b:»B"fýj¾¶3£À¥~…ï›ø„ ï:wðwþý`Ͳ…s0¾ ½ HׯåGƒ¯þ|“îÃíœ&Žû4{Á)q ^ôC{¿/?Wëö¾…à¶‚]ú°…|›åÑþ»NøÑ ç)ÑÝÃß="_È;4è†1·›2^µoüßQøÉZkœˆvÄgÛBÌ¢ávúÉ`ëÞ”ø'º_Œ1|çmò©¼™Â‘ëïgkOä_;Q£ûÑ á½jÃ-·9Þ«øæö±`›è-Æßýì‚~ïôuŒäŒ66æöx¬Y+±n¼?ö?BkSÅ4zÖO4sGö/Û%£Sà9™Väý?¾»8'~ÿôSµqð’ž·5?4ã¦ÒçÐ’¥ð>dWÅ’6Ú1YLÜÆuicœ¦5¾WÙ³ {£÷qù©še)Çx‡Ÿa¾ %mD"Ê kšåxŒ”[CûCòø©š%vÄOgL?U³£4»þ„ åO Áò35³»áiiùÿˆ"óŒ`© ^I¤;™…¥Ïˇ­hh&˜SeôÙ"}ÖÃ{yûì‘>ëâqqŸÃ3ÿgŸÏÛ÷¼ÓØçŒ`“”Üg¨é ú‚ –V?jY˜ú+™7oÝ{%‘>k2SÓû>*wd³KÐp¨`ë00ô*Ø'ï„yÑÎx'´óDö¬‹g×ýý4¿uìÍG»þ;÷ÉŠUn؇ٳÍ=Ps'2€1â8Bß(´\~¦f7Ê„]qX(³¿‡3ÃÂö `ãè~,hF¿í„cöŸ¨* K߆áÌ@£ƒ?ß÷_W]&†}—‘Ë5&kØwùŠÜ©áôüJüXpØFìŒËTzkÅJ7®)À¤Á ?8”èv˜?…q¶¯Ãn{jJ²aW‰™Nø†e}_ÑNœ†ŽÛt(sõ~–#O[ÇŸ‘?K™^‡}“M¥9ø‚Üwdqµ[4Ò³šá•¹C˶»¹÷ ØN-ž€ÿ[ÇjØUbOͺ7ì*1_h©v•ØŠ¹Â/¡™¶Ô„Ýb4¨Ð™(wØGÙ“‚Ñj6Ú)ÀÌì3Þšo„Ì¿óÛzäëL¶ëè±³«Pá1ó:†*Ø[ÞÑÌŠD¨æË]Ùb3~º(c7ŠynÚÎßÓûeŽ9ýòèPáa^«Ñ¡‚}Ëâu´£š+æ¼£§ÞcßÀŠïw.2¡êÓ2Þ§뜦Ë øÍ@‡ƒw±»QÌ$“F1â¸ÂòuƲ6ìF±ùððž¼oh¼[ÁÃ>ͦ՚8x:tîÆ2wÜx ¹ädʈ1žH‡jŽhgF:Ô¼6<;Éܧ㠖&zB²bõެF:ƒÙï¶­ÁÆ~&°Ÿyz ¡Øï±ËÚâ|ì÷,9J‘ýlÆÀl`¿óC\9B !ûÍþˆ<ƒý¦yBì7'³]ƒý<§ÍÎíÖÍÅ ì缈})Ùï kÙϬ#çÆ~™Ä‹ìg7X Æ`¿c1·ÙX’ýÎwN±s&û=~Öd¿ë¸Em`?»¾-ö/Á~2W‰ýF»’ýî†èQ¡ßÉBB?K9ßp Ÿqö@?[ÂÔ ôë!ˆ~¶ãÏýš}© 8 :Aý^:â<ÐÏ.Cúõ SH~f={ É϶Å׆~…D€~ö=8ýŒW`?ËêŽM9ØÏ¾}c?Û*ßÀ­Pa¸kÅï‰~eçäì7L°`°ŸýúÉuÁ~ÊÏMô~OÔïI~ö.8™Wv¿LìHò³íÞa_&‘%ùY×x%@~™89ÈÏ÷Ïø»aSßÐjŸùƒ¡‰?ÛO‚ ~vsß È*Ðo^Œ&úÙ\ « 'sk`²@?ÛåE3 ?»I• ègã7èèg¿œe8úÍ“N¢Ÿ_Oˆ~sêw ô›©íˆ~óÑà€~f|& BU`бiù}i¿'ùMÛ` ™ ?_öBàg«Î)üÖEþ÷™¯.¸ï]áñ‰'÷yPj÷ÙÆHî›ï‡¼ÜgÎl’„§¦Ügen0]`“9¯á¥÷Ù—alÜgG}``ã¾áwÙ£]è`$ .…·Žþ@~þíÖ6-#ƒ ý–_6÷»ÈoØú¿“ßšýg¿á_ ZPÓz¸Ë#øSûËà>Ÿ>ìnƒû†%HÃÎú„>?O2 `sjžë’?K l ðóÙa?0WaXÞVPÇé*ÜÌìîÜ7¿Fî÷Ä>{*Ap¹F'2â‚ú¼ 4á£÷N€âFÿ¾Ø¿ÃmôÐ7íí}G‡>osÐç/öø·+pkgnÐ7ìjRìæƒú¼TðÃð|[1”€>=N4âÐ÷Î ·Ø7Æoçê:Œ¿3#6 oXrQ€W@Ÿ—y*ôUú†]z%ô Ϻ6 ìÕš81 OZóÐçzãôYOñ§ß°TW8S ä¶=!ïW†ƒƒvا¥÷Åç!ˆoxJ–+dl0;]AfòðCxàæTºàæò àóiÀEŸ &þtÚó™\•öâ‡ãÚóÙ»íÕ2A{þã&ÿ9íÕ÷Ðhï-qã'°7Üäz`ü÷±€=ÿ­ÝM‡=è°ç3ƒå#`ï•0íÛæ85ÈvÇÇC ÕVšþ?Ÿ³Ä÷Ø›T‰oÑ‚$â[L%AcŸÞ%û¦2ËøÖµYúlC°YúºùkÃÏ+hÏ“Ñm–¾·Œòí•ü´ôÝïŠKûÛ ±k³ô]S§± ½tÄ'íÙ†»²ƒ¨tp3Ú»›NhA{×Ã{¤½6™‘•´wÛ…‚íµ6emƒ•ÌŽäAnA{ö’Ÿ¤»Ã.®Âña¯ôa'ìÙ¶m£½w3ËCgÐ^i¤t<âÌ€=[b°ùì#`Ïü‡±©ìÙoôÙaÏbW€r ¥ìw¹‚ü}‹ô–¨w3ZC¨÷þBiÁ#ê1ýQ¯Oæùê݇,@=Ëní’ÞÁÛ¸“ônÙô«“©.‰z: $éiÏMÒ3¼ ­Az2zÃÈzvk+ ;Ÿß`ÏÖ3ôس û{ÅŽØËsUž0Çç&`/¯L سÑÁ ØËƒAҞŮö‹Úì|v¡6‰ ½ñ L`ÏîÿŶ°g7¬ÝÎgg'íÙ1ê±ÑÞ²­‡¡O7=ÀÐgÑ$€Ê€%[GaOíÙà(¡O·nÉÐgž*h SJÒÞ°SJ  }ƒܳÇv÷ž“ûUúfš;Ì…x|v‚‹yðy8H†¾%‹= } |cñFŸe€a0ô™kö|yŽ }'C›|v[ }«Ã †¾w³6wKŸùÌ£XútŠJà3ÛÊÐÔgÓÈ‚­ï´ÒÖwÑ]Y¶¾ÅP5ÚúòºÙú®Kµ`ëÓnD¾ò6¹­ïyWwZaë˧G[ŸNÒeë;uF¹h(ãÁ¯l}ù„ië»õû±ïyÑØgãÁš¿¨ƒ¼hìÓ•Ei쓯‰ûìú<;P_^'cŸÅÁñŽý}£±Ï.Cº@k´”QûtI˜Œ}}ªiì{¿7¤>»øæÚ¬}²„úòáÁØg_ñhЗwÑØgfcì¿`ìËËqdì“Ååüb*ƒ±Ïž8­ˆÁ|öS¢!Æ>»y@÷Ü|.-C]Þƾ¼%ƾGü êËKh쳟ã³ûtÍl}¶EÒQ=nØúlp¸+¹ŒÊÖ7xÂK[_ÞñE[Ÿ½8¸i¯x‡­ï¡Ï}ãÿ÷îH»ã\–žß£8fµÑ$xŸ@ËQ„‘P´#«ŒvzþâÚë²Á“'/E)dÈÊó!ù‚$‚x°ö^œ•Ýb_çϲØ×‰„"öu׳Øç¬}ÖúÐVÆÇ+ù~t“û¢YìkI[bÞq‰}èjq‹}—£Gì{oáþŠ}çæ§/±×· â$öÕ7ùßÿK‹}»ãhGìKÆ4‹}háõ+ö]ik}÷/•Pë;½D­oºÇh}Žu­ïÔ T¤>Ìm’ÉòîXéÃË+\´Ò÷Dw”Òw.îžVú2‚Eé»´°…¾ ú0©Ô1C¯›†+ }—ç›úÎ=\§;è ¶Ð—,qú.~"ôuo´ÒwD¶Ò׺²”> Ï? ØfÞ;± >ñ^møº;Çþ› þ„÷žšïüû„{—WÔC|wB΋ø:QIˆ/Ipšø¸YE|Ølkw¥ˆ/Û–C|KLF"¾mm‡(q ;môU6ñWŽ!ñmÖ’ƒ"GßuxöfâÛ2ƒ2ñvÄ€">l;—ÈVÄw*“W_<„&¾ÃaB|§“0…øZ…3òÝZå1ñ›×KC|˜Ÿèä">ÄÖ“~Æ;xtÏ+D|ÇÍÄÄ÷ħUÐw"¼Ž ôAaÓ,GÐÚô1¼Ìl%¨ úàÚÙ>Ї™HAÐà8?Ї1b|¼°à~D}ý©‰¾ ¬ï9Ï4©Óƒâ®1Âåè{ënï^³Ðn…zˆê!3á˜óC}92R®ZÐÓ0çPF¦¾{8qX$>™¨ë7šÌõÝ«¿ö¦¾f¹¹óz–\‹4¾;6ØÝwÐç‘Æ‡p{'=5¹°ïY"«[ãÛs.‹|€/á˜D¾¾KŠ|ØÈ?Kã;ÿ ñ=a k|{„7Qt5—Hã;ïÈhÒøZ”²Æ‡§9Ùá ³ùÞ†°øFê{Öôj«|W|ÙTùN¥”n•ïŠà(…¬èoæ»ßÇô|˜¯õU ä{¼Û«5¾#îdk|ïk)ð±ÆÁ$ߤÎIãôêƒ|`-lQã[–Ÿ5¾=Pcïrìh|ã²Ä«}tÐÕ¤[ãCÞËò=O–,òµi•ý±w"ÆñR*ßÓè(•)‹¤á•ʇ ú[*ß•…A"_‘J„|8“K¬òå=œT¾ò• c%P2ßå\­Ñù|G%¾o™…>ã¥D²ËÉ›%ôùùªÕ%ÐùJ²Ó4QÈ÷ÄB¡ï_gýXó# }rD|ÏsÅ—)ïðºü¢;X¼H"àûˆŒ’ùrß’ùÎ-^É"¾êòÏYæk‰QÄ÷húlïpyñ^)ƒ’[¬ñÑÈ{'ò0JͲƇdú•4¾Õ…ˆ|ûÍ‘:en@"ßâ¹1y¯:Ñ1óÞYÎs’ùúz­ó±žZç[ ¨u¾PŒu¾8¶Îw;UMt¾®1ð… È{»7#ˆ÷¥eŒÊ‡~>{;ß+¹|ýƽ¤9î=!nãÞ1ò+ñ^3u¾­ýŸ’Éî'%ÒùZd´Îwí±{–ηÅÀ,»æy0%”õ=Xç›j‘Î7i’úÞzÖøê©¨‹[êÃO¼z_ߥI^ïë»Âu’ú¶áàÙ×g‰2ÞN(á’µ¯Ñ7fö«<{C¿Ò¾>¤3 j_ßÈïë[¯x9ËÛ‰•hk{ÊU«ÜEB¿ß˲vž{líGÌž²v:ÀzœÉxkòƒûS‡Ü j¯o–¹oy‚ â>¼ãš‹ûV$ÛÕ1ྙgðk&6øá|Z-øá\ð[[ÆÄ}+lª†àW¶ª!ø­{æ}¿õЗ¯güú:Ñ+5•ø­pzJƒø­Ø[õÙÒ‡ÝÉšF üV¹Ÿ-}ˆå±}À¯Úõ~-¾ÆÎ©~x±¾›úðÞ﹪ºæ6? ¬×‡üpŒÎ^ä·.Þ»&ð[’}äùÈ}xšÇÇÚYc¦NDlÂ1ëgS†˜í³«¯”øá‰/ðÃl üÐéŒqu 'Yn—â®)¨Ào>‚à‡c´åMà‡Gç½€¾ƒÃSd:³ly¿šKYÝ+nB5ÂüÖß®ÀoêÆ?„’ñ¦¼º‡Ý³(’&iÖ‰M`ÒäWÁg>zß´ÓWä‡N||ȯËbu/wp|ܘþ]{ç 0Žä·ZÊ#öM—WØ·"'ßÇݹî½cÔ„Ø8ÞHjZ÷Ø?Œ û‡üpÌú!¿õØ#Éùîß>à‡W÷ú˜;×Ãneqßûß>Ø÷Ž'ÙäwŸB؇ƺžn`‹O^Ø7õ)}ˆè7>Jß:®.‰}èÞ{GìCŸÖ‹,¥oz&Â>DÔ°Çè1ûp®­±¯ŽÐû&ìCßKé›®FØW!8#2¡ᤰ}Ü.L*}8Fï¿°oÝœ¹ÖJ:/çñ-dŒ•з"ÊÔgW^)ˆw½«¥d>4ž8Œ*Žð:_ÿÕnOpµVn•_,ýˆ"_¿LF>\›É‘"_±ÔÇÚY!gæ«c¼3Ì—[ ÈWa¤Dbùðx·E>tzo¼#òáò4Q•ȇ>}ëŠdøÏ6S_K¤%•㊸D*ß;ÈÇëI•ŸXkzº sS_]Ÿ$±RùP¹=˜TùpÓ6Rå›Î#•oº:É|xq…æ£ï@4É|u#:†Ô„–0sRæëÏ»e¾~çL}Óöa|µ™sùþoJdýZåC‘‚#ìC%ÏgKÆJ¡—°¯íûæc¨‘á-Ðd\2_÷"©|8•<‰Rù0bÝM}œ®}T>ô´Ï޾~ù-òáZ¼/"îÒzE>tF­HHåëžU¾©Ãî}>†"Y#,óMI2ßô>•Ì×· •oEdà[ÈåIæC~>;ú¦÷@:ßÔ‹¤óõ¨lo>—oÁÓQë|Ó»"¡ÇH}—Їz4l”Ї¦Q•Ї«Ùt„îa;¿àWM#>—ЇzŸÏŽ>¼-$ôMSBŸ¾ÿVùP‰^*_né÷Än©ø7Ãw?;9ïu„ÔÄwؽôÙ»±Ï»ð¤ím–õ£í%—D´½çúÙÍy݉#mïÚ¢4JÛ»«Õ|wìÙÖ@7çaÖ|·wÔ5j{Û{}®…|t †·jqÌ“+Çð0-µjH›âzˆðóbù "ž®mÇx_ž¼ÏˆPGÆÃ'û4Ó-Ô¯®¸7…‘ãM+1Þ}9ë±ó:s ©w×òà¡;?›÷°KÉzï»3^¼L_žOÜ–š( áV®Þ‘@È»wý yvÔ=ldÚçÝ{µKÅÇ{¨é–ê!!!`§fQ‚¼û>‚Ýß] oyµÊé=s„<Ì‚˜¥éÃ]Óö=L¥Ô—ý+®šy‰ò ~köHÊ;Wqÿ˜:+F‘¿›öoøÖô+2^u–÷jE8LÇ5¡ÕîQÞY‰n%Ö 9Ø;îʆe#dÇnSçY¯’ر(ïÄ+ v åÕˆkŽÝrb¥Âûþt«Ãý‹òj„Hy%¨’òÞIWï­+Ê›øDy'ÐZý”wâTïå½÷ñ”7oˆ"åÕ|P½†”W¬¥(ïÄgóž)¯VXíšÔ<±Ú’òæ§BÊ;kb=S^­Ë3嘟kæOЛ–( ôND+ý„o©µæ}ßrb?±Ï]œTSÖuÞÆw⬥@¯öhYÏç½?J¥K·%NVKÞB}ZUBu¬Bª ìŠôNLD?Ñ[N|&}r(|ë“&¾t kdÖK·€FŸwñ­ÕQáCbuj¢^털­ùÕ6>LÀ$úõꊽGO÷pœˆz'Â%Ü7½0D½³& À³ð€]¡^ÉP©{8®Kûø0·óÎ>*|+ò÷þ®3¥ðaÆ5fÔ›»›>tßîa:;õ±õòtÅ[ùÖóš#¸œˆ…«u1)|˜kJ+…¯¦ÿ³©³^"6u—VøÐ:@*|xæë,ñÕ]i‚%‰„äØ0º@ŒjÖ=\?ñ^==ù¯JãC75>|co{8ÞÕóuuÖ™®ÏV>ÜÕ>Çp©Ö±zH‘lº>É|øš²JæÃ—Ùz"e¾úžÏ1\êoÄ= D€M›ùÖ'Þ0É|±þJæÃú©TÉ|À;E‘̇~|Ì1\NL…íФ̇˖p&™·&F‘Ì×C—e¾~ϼǨýj;ßÔžµ9Gî™øêzG…B_¿/ÞχÿŠûù*¢³øNwp¬Ž£¸BüÒùÖ$’²Î‡L/ÛL|õ¾:²¸l“Î·Þ Æãý|ïƒòŽ?id‡m2ÖùðÌÏ~¾©9¥ó!ÄWçC œñÙÒ·Þaué|hâç£óaÎmO&u¾©«Içà 3ùªAÇGçCÊus }5ÝT½ÊÑPtäM}w IìC¨í}övžX9˜­Õ8ÛGëCtøi}úÙÖ—‘ÍZ_eà˜·õÝã#©ihlÛÔœž Fê{Ÿ¯ ¡ÚÖwkíÓJ_…î˜sײÔ1á-~,ËGëƒe±&S¯ùý—N±ësTêzŽ Ú5Õ¥’O]9*uMG¹®Jas?S].™ëê£\×|Têz¹ò·1WÅ‚OM>&õ1©§˜øS‘J>5å¨T5•wª¢íS].™ëê£\×|Ô?íkÐÙ·O‚ûÏá­Ï¿o}Ÿ?÷ëðÖvØÏá­ÿ¦ºûÏû“ðÖ>îW?ùExë2Pþþó ÷‹añ÷_½Åÿí½é÷;²\ÿößÿë@à‰}ÿ·ÿý¿þ7ÌMß!áßþüïÿ±Ÿßïýño¿û_i¦9Æ6¶ä×;XW^Žû×1¶ß“blã_€½Oÿú¿òW{ Å~[*ÿûúûÛ8h ±}¦°kûŸù×BlO¦Û϶+Ä6 ÿbû-û_ù×ÿøEYBl¯b1§ÞAëí&˜FlöwJ98¯&B/šý¶¿3þ[-eÏÅk1DɈfõΣF9o0E€±þÂgß°šj`ûò‹Ào BjaVAÒßÁ¢² UÁ;Lmà•ZFAXØ—ŸÞAuUPw"ò".†gÛM¢poûªšgE_;¼sqàÅþÑýýý¶ò@a3ðñÎÙ7¬Õ7‹Þ]IQM-R¾ìýÑJìÇ6Ïë¨ñ\þAlªz»ü[rHUÁn|Š7ìE¨Õ¢ÚÚøž¢2SÕjö-ÏŽc¤uaSÒúVŒME>%:Þfܰ4R«ˆ_·í8f[ÜØÐ¼¡šSS˜ó'¿äÆãyq÷­g“mïFä¹õ¼“Äâ%Ħz¡rÚK­ÙÜ%òR"yáƒ/âêÕþ¼óñ­¶°±äýù;âÖ1…çõÂJvÎPïÖ-|‘vŠñ°y× ‚}EÕm°>ûÎLÞñ„Ÿ÷ŽQŸ19ã*zÞ;$0C.^®óÁÑA—án¿n|±'2ÿ š«K#CÀgô¼Óãm,š¾ƒÜ{ÌF•ÖQµ,$x~ßé4Îíà[XÂU=áZ„Üàÿ¯ ´f—o5:ÓºPöÞ*Œ+Ë0DŸoÅX…áº'ü¹N~Ú;W}÷o/ì ú 'š–•ãyÏõlÚ­wã‚›Bf–P©ÌT\¦Ã(ÞTCAk>8Ãznˆš…læ·•ûž7t.ôÔbRÊ»”€¹oޞĬ]™ õ=Õ£_¬›âQ=ÙÏ^‹5ï\ áh®1<¯çÍ\X•+løL¯:G|’0ˆ×·çªTÏu£uŸÈ0¼áܧB¨a Þ?CzâQ}ÔR* ×¾; 9 á=üá•«!ªIpåâ-¸¥+£Ó×~Øwëäháµ±Iï"—€ñ‘®!<1°•¨†ðcó1•éyzTH0Ì!\ ×î7o Áp áŽ<>`¸†pïzØ3UCø®tc)ÇÍ{ÈQ pïø@×®Ýßç¿aàû\ã·#) „Û6~”žø99~_Ú@8*»ð3õÙm5„RÊÂm1˜W×~-\ŒXJ¯!)„Ï*9áêк=§Ò#|1‚—¯u\5ÄU?ÛyÌ}qOC`i³Fð“©›r ïúHñÄÈ-|̯ÆÔòêØÂƒAº¦æt mé²n¹…kw´ý$†nòfÉùpÏåTŽç ¢›j0ˆtM­Jø•˜q"ù0Å‚ÝÿÌ‚è\"6± Y¬F(ˆöT2d¡ úßñAATÃ5£ š˜>£ êq"¢ ̲E ÑZò'’ë üÑ ¸´!F ˆ{z쫉D_ŒA~EÙ¤È86ýˆñ"*49°ì£Ú¶Oĵ(\…87 9Z˜A2ˆŠ¥¨‹§­¦â@Ôc=Ÿ8ýJØnD=ÞÂJ\bU2.勘8p9‹–ˆZ¸ša\õÖˆW(& Ä<Ÿnc`¾ ÁÀî±âÀ~RæÀÚÌÚlDŸa6vûûAûÔ†@lÜ& Ñ2YC`?(C`?C œ*)D ýÀ˜7Êد¡)W#ìöÆrS`?(S`ûÆÀ¾c`wHc ÞL.1qWtzëSHè¢"²0ÌÇk \dµ .vD…qWã¡ÀÅ[ˆCh˜(°v¬2Ó8ÁŶ½`íPgÅ"A\ÎΑ`'$ˆzVÒ—H0ÑB‚ƒ»~e\Êï5àbT@0Ï* X±0 ÁùO’ ®e°Z‘`BH°›Ø$˜ìAAøçj$ â\EAAÜ &Ü~Hp±,$ˆ¬MÎu&A\ÎBê$ ¢š‡Õáæ™D‚ù®†+;KD‚ØÉ-Ì æÅ3 âòˆóÒ‡=v3b†ó–…qÅ;¥ÿ‡{’+—À,  *DZ§ý+ F´$x/?K‚ˆxR%‘m$“6Ñ®ÚpÑE¬ "zÖ»7£ Ö•ªÕš MÇ‘±Y»î(’ ÞSŠ„’ס9‘kŸEýÈ’ ¤ÿúBDÄ®¥{†Á­v¶–lhI°,åU%A¸…I¢’áp¯1&’ |‚µFI/w Û‘c¼Œ$ƒs©˜MƒQ" bbO°“$¸:Ñq$A˜Lë Ö¦äBHK‚|ê›OmK‹$XŽì*1 Â/G-Ï4¸:øBh.ÚZ^ bãR+4Ó_õ¤Ð üàÔ Mƒ°ÌQ%4 –ůŽ1 Â+Z„§xû¨‚0_^,O6aK4XæY"šh&IμMƒX Œ‚ÁÚLÍjƒë彡Áû™Lƒp‡~DA¸ùe6 â‰Jµ Ì$. Ñ‚dà 졒êƒ0*rá×0[,ñÕ0˜‡¬m„¬X4Xv`Rœhÿ]?4˜»2 ¢ýî(¸fó—a°¾e”áƒ}W†ÁÚG9O0ˆ3p~&\CÒ0¸–³~bÁ>·YpM˜I³ ¶–sJbD¯àY,_çòQËÙûAtIÉn‚Áv¯a=&vá¾?0XûT>0ØcìK6 ¢q•‚Á6½ñ¬T"¬² ž‚6†ˆÛ©mÄ1_Yç>½Qå7]ðóÁÁ¾Ñ jÙ>ª`S¦A|UlŸ' –ßûCƒ=x˜qW i,ì»2 ®÷ϲ ž•v›Šq.muV þŠ8ˆGÅ7Æ8ˆ®Ã¦0vã˜×ÓÞ̓k ù?&ÄÃì‘QÍGDÇ9?²`M| §"Âîè&Âî’&¹L„xVë‡ûW&Âr…S(â9r™§zD„8×ñ‘ËTÏ_‘1æÔ]1Üqÿ‹‰°»­‰0 ï÷Ë‘^ h ¬m„=!I‰uBœœKB@8H@˜!;@˜>@˜w<@ا6v=&BÔC´fT¢ý6•ѱëU ¢ý$üû+D Ï-"ĹE\"BtÒ¨‰°+6vwö“2f8 ®ëv'6ö-™»ƒš³cñobs7>åx™pS@ç¶…^Zml\´µ. 8¾ÜaÀ6ûÌ€ðØÕ’AÁÛÑ[K¹° ‚@R£AlH¯Iq ‚ν؂ 6¸Õ¯¢^ÚLÔŠà%ª‰"x)Ï}+‚—¾¶"xi·~+‚—Ð#Š ˜¨fÎQQRï[AóÃ*‚8¤¹(‚ˆŽLN´"ˆ’š¦DD ­™–ó+Cà[®QQ@áNŠ`¶ÝGÄ!´sŠë˜ý£ÞŽÄkˆŽ\cDÁ21Ö©Ä€}.3`ŸË 8#¬’mV«äœÁ¾3`]OÁœ°N5f¬’茀݀FÀ4  °ÐXç^f¬c8!óÞ¤œÊ8Cìû4Îç"ÎÇsFÀùTDÀ¹"`ÿH8ös1V '~ÀéDÀî‘ÀnP`÷càü+`½ œŠGG Ö1*`•ЫI¬‚1`U3&[h½yçl ®O8CœÎDì·Þ8Rü7AþÝWü75–øozr⿹„ü×ýÚü×çþM÷$ü›Bø7µ°ð¯JtÄ¿ù‰Ó1ûò¹^ñßT­øo:µø¯ÍÓ‰Ä}O¿¹âßt—ÞÆ7UCü›]ø7Õ#ü›êþÍÇÿõÕÿÆ;ðoº)áß\/ñ¯?Æ¿ù˜Â¿ùâß|*ò__ðoªEø7]ðoº'áßT±ðo>†ø7=oáßÔÆÂ¿érøM/‡ô7Rð7Zð7½»‚¿éõNш!øë©áo®§àoþéoz¿Es5¤¿éõýÍõþ¦cDÓÉEó1¤¿é\¢¿©Šþ¦[ýu þ¦áð7uM[¦QUô7ÕBø›.Xô7Zô7U#ú›NåM¯S éoº)Ñß\éo>†ô75ŽèoþUÑß\@üëK6þuÅÆ¿î’Æ¿®Çø7×Sø×weþ›+&ÿÍ?"ÿu›šÿæS‘ÿæòßTø¯ÛÂü7ýJü7Kü7—ÿæ_‘ÿæsËçòßt›â¿înæ¿ùDä¿©ñßt"ñßô+ñßt.ñß\Bœë!öÛhœ®P8—ÎHœ/‡8#œ.G8]Žpª‡8]Ÿpºà|*2à\BœKÈ€óåhChJþ…ˆÝ“&XëŸm‚ò8þÅ6A8øÏÙ zI̓§ò‰6^'W°ÂƒÏwhíÖ¨¿ ƒñZ1’( ƒ7Jy bj_„|nå" >7·fÁçÑ>›° r£ó7!XÖõEÄ`Së3m«2æÐ‡¾#.Ž9oè£\_í EÓ–ªh90§ŽWLäÀe¥}©ÕÀuðž¢"nÎ2yC7„誇¨ÈK±}Ô@C÷I DÉõUSb5°Bô|6bÔ­uŠö†¾=æžIpC„ôâøö†6noèЦËö†nŒÝÖÐíà}¶5tSﶆnJÔÖP›Ûj^[Cw:Ûï^œ¡ûf»æä U‰¡ö´3tw ¯ˆ“t‰³ˆ6±¶†æ[CãcŒ5ôXL±†:’z¬¡ñ#ÙwW¬¡v´´5ԛɺí =”)ÖÐÝéb ݪ¼­¡ŽkhÂÄÅêGÜÖÐxgk¨Ž±5t“¯¾­¡VŸc õ²­¡ÚkèîŒI³5tùÈ e)ûB‡÷øÄj3DC‡SJÇêW¦¡CâøB+-¾P–¢ÃÓ¾P„^ûHqA·/4‘³â }O%Ÿª}¡ÃÑ¡â ]㼬‡’,1ñ…¾ãáýÑaö^?{§ûB—ÏAŒlÏL‚õo”+4QÚâ E.©™'oa\¡ø(§\¡¹àØB—d»“/¹ãHcö….šÙŠx_Š5(_h—Øš$1†ö©d ]¾®Ðþÿv…Úß®Ðu$´\¡‰ÇWèº%G\¡ý+»B»f»B×N["Wh×cWhcWèº;º®m¡«£@ÚšH}m õSh_¨=¾ÐÕÙÚÚj·a|¡c9¡`ì!0ßÄö…®Þk(Ì}öN¿²54©Wb ͯb E Ê8•Øš—,ÖÐ>ÆÖÐÕ9b Jh E8*Vckèzz㡽¡}*{C‡“gÆú–pKo¼¡ž3´74vÿxC‡S;ÆÚ%ö†v‰½¡Ãñ±ã ƒÞ‚XCûG²†çêˆ5Ô¸½¡N)ÕÞP‡·lo¨_{CÇ ¶o¨·—´7ÔÜÞСh í õ¶7tÈ_×ÞPâí õÈßÞPì]'±Ùê©Q{C‘œVP›CÇɲ͡~Äm}cü-<€JVÌ¡úè´7Ôû2Ú:mÔ‹7Ô_³ö†emo("Ïì í›C‡’¨´9´k¶94mshî;æP$óã12‡ÂÍ÷5‡æ¶âÍ%Çêj»C±±ÿ³O§âdÍßö†¦ÀÖÐ.5´OlkhŸÆÖдU¬¡#‘ªþÀ{’ÿt±÷†xc’ÿ´—©å?¸û¾P­ßµôÒþû¶€î *ÐPý´€æ6š §¶ ÚŠégM¾Úzsçs  1¶ôÑžÕ8@%Ðб)¨p cc½á½KëÇ:*hö„{ã>¾Ò߆H$4ð%®ýŸo³pŒˆÿ³»u–þêÜÜ~gàÛ†â9ø€úø„„ÙœÙ&Ä· 9ÓM|˜>âCÔêõC|›k„øÐ³÷ñmNBâÛœÕ)ćÎL 2ñm›B…ø6g ñá&ªÓ„ø^“;ôL|›Cíù¶C{¼‚|¸ÂããÿĽ³f#߆®Sª¢‘×\ß» _JÂ|Ûm–™os¶#në˜Å¿÷ršlL|¸âå³pÛcñ! ýú!¾m_~ ³%£‰‰oK:ß¶y6`âÛœ´EÀ·%-‚1LÇø¶ë´!TÀ‡xLRí|hø¶¤2ð¡mˆâ½-Y0Ì{8íãþ܆¶„÷¶M[]Œ{é\Á=œ[‘[ˆ{h™ûƒ{[Ü÷¶¤ö1îåÑ™ö¶dƒ0í!Dû3›?·ÝÁQ | ;ñ^*á”xoKnó¾ ,ß–d$>ÜÔõñ~nIabàCÛ» |[²†ø*ÃðmIîaàÃUÈoYO%càCÂóç|¸Î |}y¾-é_Ì|yºF¾îøF¾-™›Œ|hÅŸòuG2òåU5ñm[â„‹ø¶Î{EâÛ:›’ˆ¯¯ÆÄ×}ÍÄ·%»‰C’a‹ø¶äñmbOЇž$LômSš#BNõÌê_ÝÃ>«ÕÆãcþìWÓÐ×Üзu’ A_FÚ@ßÖIV}Ó¹}}‚>ôÕ¯ù/Š ˜‚>|^ùsœ^ð2ôëøíãýì&óaX=fù¯.OûÅ|x9Ç,ÿU“ /Å|Ûáà¹f>ÔóÝX©Èab¾þ•™oKf#3ß–|.f¾- ÒÌ|ˆ:½~ÌŸù”›ùò- óm‡S€˜ùðô¤+Šùð«ûcÿÜ’rÊÌ·%›™¯oÂ̇¡æË|¸ vw3_ÏÌ|[Òd™ù¶$ß1ôõ]ú¶ÓÛ® }›óèúò1 ô¥+úÒ}øØüŸø ®³Xwþ| oÃäO%„¾tƒ@*Þ?дW ç:f°nB[}}[†¾|i}é–¾´{ W8íÄf@B߯ÍkF><ùA…|¸þë³EÑZ„|ÈSò!¾Ê«3‹8ÏOÄ—®âCÅ÷,þU‰À‡9;|Ýâ>œIÜ(àëaàË—=À‡N<>aP"ùMÀ×M!âéîÏv@BlòuÇ2ó¡ÝæÛN¥Æóá®/$^ñ£…Û)€÷@´— »#)¤°Ä¥õ1S(îŸêŸå _üêïx¿m@[Uêí’•í²„ÉMÁ*{»OšEºª”LU©¬«rÁTÕþ²Ñ|«ü³+©‚ÔÀ¿þÓƒvoHÌôgA»¯'шýO sk¢$ÿÉ´û¹r€ÿ‰?WÈþ±§ DsÚ¿A»Õ1ŽÊ¸ý ííº:·ëšÂq§®•ºæÐÞªk Ç­ºæpÜ®«r]ŸÐÞ®+¹]UäNM>&M½]O‡ãvES8îÔ”£RÕÚÛïQ‡ãV]s8î¼~9ÊuýG‚v„‡…è—A»¿ÚíΕã~´ûÏû9h÷ßTwÿÙa´ûoÁ72ý7h÷?ÿy ûÅPøû/_žŸ†Ç_¿;¨é_Ž—=€úÐþ:^ö•xÙŸhÖÓ?;ø´#foëJÄìÿù‹ˆÙkþ¥xÚçý‹ØÙgj|ÿÅØÙ×2nÇÎ~ ÿ;û-û_ù×ÿøEYbg¿Ž]á³`ðAü³5cX/ãÒ0½cùóѦ¸ñ<µ1p`*Z«Keñ¨UÝG,\ÊÔÑìPÂ6®©×Š„bTÔ)|â÷E«f …D‡”.Fcz¦ÀÓœ†|`+kf°íZ´Ý®â<ÓÎsn™ßTZyéÞK­í+òmÕT»6²#„ô¡]?ÒˆUèN,Ô$¬BwbE‹?CwîZMªÝÜÀ4ĸÞXî¡‚ßµÞZûŒÇoÛ•Fb=ø›‹ël‰ÀWû²*üò­GµÄ[á—®³lHmR‘;±d_ÕŒ• mˆ²ZL¶Á…6„f½TÂ…6JÁT­úVäNìeÉ~+r§üy…¶}YvNC_RåBú 'H—SŸ¥—m+RÆ^Kˆ¬õá2ÛskÐ;rr™ n¥ZûÝÞ§€kØ‹iêWè@¸óÙ¹µaNQ;阵¨€œ#Xog—À<÷Ágd‘/Áü ݘ|;‹Çw‡lâíª•¶:CÍÙߊk)b/³@à&Þ¿wEj}»s-´í啪+ö´n©îmµÊ¶/Þ ô–Ô2ÛL,Ùj™­.¥–̶½Âï°x¬<ÏQËl; 0;KÎZg«Škyñ½éZgÛ+SÝõ~×:Ûû«Umµc>“#üqÕs,µÎ¶ãUcÇ?VE^ÆÖçjįÈx£ø«¡àËï@Á§yl ¾ ]¡®çØk­žËÂzŽZgÛ+BK]ÏqÖ+Õ膤£õýß•Jþ%ªZgÛA£yj­n“î\jm/¯MuØs­u¶º)ÖƒÐõÇ:7à9j¡­™Ýïܘ§PIFë aÀкB6² >¸M§ÜÜð-\ªI™ó£±ÒV÷­S=µÒ¶#š[­Õl’ÇÅjj,Þ®uå$êÐò×vZi{C©×6ˆ[ÇàM,ÁM @álÞA¯VÚªu8,`–uÕ}îǺò®ûTô•íâàY÷ ŠïZiÛ+y6&]ÙAæÖJÛôÚßk­´íK%XCÁ¨…¶½L.'Kj¡mþÑV mÕsj‰¥âïŸ+o«®æÆ=ÌlBK\¼Æ¬Þ?xî»ÖÙ¦[@`ÔeçûÀ—ñYj¡m‡_Ž©€Ç:w ¤;A­½UléMMÊÏäÃðˆõN⇖h÷Š¥rÍíWq ÔuÖË”u¢‹¿zÇqÑÆ¥Aî%ÌîV¼_Æ)…;2s×Üi¯LÀ8שùËŽLÀÇͳ¯üÃqÔ¹.–<µÊÆÇZ×!¶†ñCÂîM•Ã8ÿÄÚAEŠÛøçÃ1üú¸ã½~:ÍF‡hê{­Øí,)èŽÕµÃO­¡îÈ\cø©EçY€k ߥ+ìÈ|Þ,©OÞŽ,À5†Ê¹ïôVõghGžÁGíÉkÆWºÆðSzÀ¾W>æjÎúšíøH×~JxÝwâ®ñ™ ¼3&p]2/‰€9†û&vîŒß>UX阫½j"²#ëKáy¸ÆðC‹ë;ò×îOÊŽ<ƒÃÝîøH׎ì%¬yWâ,P%ëÁ[ðÌor×~Ò‰¼#ðö=Õ½q O÷;˜W»Fƒ‚‚©€OÍ4ØsÎ2u×“Ùø÷Ã1*w=Lük Ïå!ÑàsÌ/>Ò5†§Eñ‘^ÇÜ)ñ‘®1üÐòû:¨1£ k¾7Žá‹Ü);R×¾(>ùŽTÀ5†¯š-ï•ðf›¦;òÒÔ~ȯ´_•¹: D„’¾õŽðr.Æ^¬6Þø£ãäž®ƒ¯táoŸäpœ¿Gÿ4~vHÆ“ëžIéï¡WÑ`f„:%# ŽËQþ ƒã^Å×08îõäwÅ0øB‚âé2Ûpf(žA`ä`7 Òìä:Â`]眂Á÷öL¢ÁäE¨ ¢g’­ƒ¸*òŽa°>¤8Á`¢›„€ø1± r@sjDØ‚¨`p×O0¸nÂ:³ Ò‡>, "ú§ fAGá âÓQoVXv"ÎÏÍ‚‰€›bj‡ñ!ÛyŒX 9ÇÌ‚Q&ƒ‚0!ð’àØÌõ‚Á÷¿š"aeàDÖ086ÍO ƒoužÚ±ú¹ ƒƒ-Ý0Ø#Ãà{Œ'œ†A8 V–K’Ypƒ"£Ë! Öýo ¾g’aÏ0ø^±6ÁßO/ŃïÝ1ò´q°‡@!¬fã\’8Èûç!ÄÁº^’“pð-‘Ö8¸qþGã`]1gŽÂÁ·äÑë+,û_Mãà¸<6âÉgŒƒxŠÄ6Ñ aO VãÛDƒõ#¾ Áj+¶§hpÃÒî‡7$C沃hð}–ÚgdÜÆù˜ÙHƒï¯ô1 n•x™ÌF¬ÇpÏ4ø^Þmb$ Ö1¢JÒ`ÕÃN!,¹Ÿ¯¸h°Ž!0 ¾ˉcÜJ‚#Y«³^Á`½9÷ ƒÒ<«€® ôŽcdÁêlr±`¹â88‹7ˆ†¢C²àÔ'Ä‚Õÿ^ Y°Ž9ù«G®‹å0l-r]¬Úrb¬ëá‡@0Ø2ŸapCÖÆu†Á·f}õ ƒo‰¶¥ˆËaÄF ÖÉU1i°ª9f|oKûzLƒå=d Š붸â#,Ç"„h°,~—Dƒõ@9‹ÛŽc¬s‰ù.õ€¨wÊw±*è²h£%«¹e»xo”/šh°S¦Á÷ ͦÁ…8ù –ŸiW m‹Ì¦A(š6‹ß)³„i°:åCÌ!a=r®© «„OFHX°F8b†°ú$¹å¼€+žWóÐya+µ‰°ú‰l•õbSÌva«0&­LšŽUDÂÎÌ„Õ ÆÌ„Õ\|?Å„õ¬¶™ Ë*n$N☰º¶xLX]›ËbÂé5NýKLX½©&¡fÂ*!f‹ Û±.&¬'ºÌLX7Ê"a}!„DÂj.^±°®†­c%½ÿ8vëƒ{e™¨ðöz©Z0]K¢Â"6j4–Á9œÊY"DhCN, ,‘D8½ƒ‘%f—A$Âq)O$B¹ÙÕg §“‡ ‘ÃBê¡,ù¹dÃáV=fbÃÓ]³aö§„ c,m6ìcĆ°à±·› û˜°¡ ‹Í†H°ð‘ ǹú±!h›oMàðe6ö/Ã!Üž|­‡iöƒvÐÍÈ)8ŒË1p§à–|N— ‡ÀÛ{– kÞqÎRa=†M%òäkoG³a „†xà¤ÐÆüÅZ¢ÈÞõ•Õ^väkO¢Ñ?– ½%(hˆwˆ0k4DS ©‚BCû=Æ1Λ QÀ·°á®TÍaÃl<ö† »±!F!R^Øp³ln6ĘA¶ò 6 “6į¸j6Ü”À§Ùp‹&i6¼Ì}fCï'k6„¿•› û³¡÷e4n–QÆžÃ6¦w… ›Æ»)Ïlhli6ÌðÑh˜‘áxô:„ s !C¯í4fÒ2ô 2‘¡ Àd¸I{m2lä æG&Ãí'°J8Ÿn2ä6« •,7`¸> û@È%û‡ §‘ázßüÀNd(Œo2ô×=d8”÷q"ÃG‚JÈð}R¤äa#§É0”2L‰ÉpÈðÑd˜ùtÈp(ë_“a.'d˜2ô*`“á¦4gz"2LO ºû7jÿXƒ¡_ÆCoC¦Ž€¡öC5úš¸pˆÕÂ…Þ·Ô\èwª¹Ðot¸–ú…õˆ QÂ5¢d#በ§cÌ…¹žæBŸÝ\˜ úo.LçzÿXsá[Âw1`è67z᫹ЯЌ…áÍXØ%ÆÂ¼­ÁÂt›`aVE‚…C ¶®FPcá6,/ û˜`¡[4X˜®n, K6žZŒ ææFƒ…o=|À…~É o— ñ%â˜c,Ì·)X˜oS°p°™f,4QLXèñ-XèõŒÆB_N¸°1vÅæÂ4X¸ÐCÌßÔnÜj4YpݳÍvQÄÏŸYp ‘5ñlqžÖ¡õe£`²!“ó*()?¤FAŒÛ$£ hJ"¢P0Ù‚‚ësÚQ*\Ÿƒ}"(ˆM<üø·Uª’PÃ+§4FAl´]~DA ¦Ï1vÜØ@CÆ B¸G„ưPzÏm‰ð±SÌ(Ø¢—QPÛsgÌJvPÐ+¼‚]iFA,VQš0 ‚Á8U7 6½~Õ(·*¯G(è½÷‚™*=À4 f¾|ç{ÏÇ2š]á‚™ôw‹ÔAÁÌlƒ‚È‚Åcþ/5O£ I&(hž î¿  Å‚»%¿  ¶N(¸þ¤ÂÝñ îRn‚M”aÁÓª¥Yð8m$ ú&‚©Ù,Øn %E&Ì©Œ‚ÙRØ(è­“‚‡Rp ÃÖAA‡%h ÷¸4‚yšAAì¬e‰Qp×êW£à~º³àn½,0Ø%¡A÷ŠÐ`€10hq60xénza‡ ¡ÁÅš_`Ð÷Ù0¨IAoxÿÀàú «d’Àà¦däeûTÏOÛ³[(l< öKmD =Þ k'ëO,(ciXphHþ ô=4 ¿}eÂþQPÐ ‚¾àFÁÃRbP0˜7¡ à0(xɦìš‚›ÝÎaÁŒ]†Á 3 ®³i´NõP… ê¶&L‰aÐ{ýíV úݽ&Tž½ s9†A¸=x*Ó ƒ´LøhY¨uÂg³Ô:ám‡etÂÛ¾ÌÐà–Ó`@Ä4T úÑ4 öLƒÛa«iÐÝ©i0a ƒ·NèÌ©BƒÛO¾Ñ-ošs9Mƒ9¹i0·Õ4˜_…Õ'ôÙõÊN8èš…ƒ×Ï:¡£wL<ƒgxÐí×<èÛl´ÂÜÜ“DXœSŠ fü¤ ¶ûÙ;ú–lrÇ §c†UrÎ`X¿Úæ„Íd%¾%Ò¡Ä…oÁíäŠ|.¾$Ös`'¾%Œx!,,/gÁÂÂjœ¾ «„ÏNXX¿ºg…°ÎtÍXXÇ%I…ÕØÛD…u1*œ!V5Ç,¾Wµ|¼£oÒ ë ¡°ºÉ9o$œšÆA$ðĹ !(|K K‚Âz }°~%¸,(¬·AÜH(ˆ[·Î!ÂÕK<Ö[µÏP8WL(¬_ݳ@X/'ßAáÀY"âPžǦhQá| ©°JÈ¢Âò‡Ïú`êÌVÂm¶}p ì$EBáüBa‡®nA¡÷›§K¾%Ñõ†²õ<ú\™kõ2;GëW|N"ÂwRzZû;­ç1#^ÊÖó,Zÿ Ö!³st8Û•p8Y˜y° `ùzôQ1DQ’·tS®{3ă½Òg¬’mÞDX©!ø£K¹zœÆ88’Í88’{Ë8˜\.¦ÁNaì(¦ÁÎeIff¬Û\'ìD$‰¶‚¶ùØFGò±™;Oyp$šypú•x°òôí3v>ó`çò3V ½âÁ·ÄŸ2ñ`e \gÛhå¤.Y8X ×Y¬z©/>JÕsÖâ¥êAFÐ ƒXÐ0Øõ «ÚuÞAØ7iœt(WOs*WÏuÊQ%¬c8 V=D6Á`Ã9´`°ê³48]¡`°Ž9ç„5 ¡¾)¬_Ý$½¹zÒ\‚ÁN©c¬jîYìÜ)†ÁéFƒS=„Á~ ƒuŸ÷lí÷Õ08§ ö dì`†ÁÊ8— öpg¬^έT=]}bÁ©b±`fmFÁªå‘¸ðÇ&Áº1ݦD=¹~‘`}I>$XwÍ‚SyzËÕ\ÊÓóü‚µÑˆÍ)¬cf¬jdë\•¦ç¹¼pUšžGáSÍUB¥‹Xëì\ ø– ÿèTšžG¹\ ‚s=·Òô¤¹‚u}"¸Eizžë·yalóÂ*Š eéÉm »‰ÅÕ|ç¼pºqàÔŽ»Ë8=*q`•0Åo‰™˜ 80ßóÂ*á›)¬Sqx V5‚D‚õ+"Á¹f’à|9$Áú>S$ âÉüh œ”0pºoa`}ÓyÿàôÀ‰õU’˜G œîIX÷Äå)aàt½âÀ©ù½'}ÿ¡µ›÷8sûK!ðqc®ŸãÆ8±J›BwM,®—çlñ„â³÷ r¸ç‚Ó^ 0ÈsâOè¥p­í …Éñ#b¶.ùPBàv{¡WBàÅGÄq<¡û®¼è÷MoQ„@„]>Bà~x㢄À÷ù ;>ý¬XJàŽ$)%wDZ <‡°X³õÍ{oKìÂ' ¾ï$b².t“x Õ±xŒÍ”(!ãÈþÙ-xì@"!ðؽËB "Í>!ðØ%“G<Îl”ˆ_Ý!ð¸¬Y<{¯,‚䕈QLÑd$bû ß[iPBàqöŸJ<ÎÝÛ)¢ʶërÜ ÇmmÜBàq^0#!—Ì ÇiHBàqË!!WóÑ+/‘ˆ«á„Þ: ‚÷RƵˆpûûGÄ©äî”XA€?:àq{’…@4×þÙ0x\ʪ!Ç<!ð¸5[¢ˆ[8>žP„¾?F§oæÛð½Ñ= ¸qB t@Ê3[Ä'‰ë€ÇóX®“x<‹÷J<»¯­âóÇ—Ñ:`](%!ð¸,ËK솰ˆìÙqÉ×ÇÚ­c!ðx´¾!ðà“T@´Ì:‡ŽÉÿ—xÜÚ6 rÏÌWír$@\AÌ Óú‘ÑC¼E ŽáQDCÝ;hß¡%@Ü¡´EI€¸œuÞ*ˆd|--,|‘ûIZįt}Òñ«ócÅÉ¥ÂIÄ=ÐÓj ð\LôÖQ2k€¸d®yZÔ¤©™¯jæò–5@´2 i€SÅÒQÂaÂàñÄ^) 0+ ~Åí@ÖqÌ®’Ò§j¤æTÑGyJ£NÕH<«pÖQóg§`š4`Wl °Þô }Ó-XdÇŽü‡GÇMZ–ÿúâ$ÿáb˜å¿4pä?ô]Šä¿ôôÈ5Ýå©$ÿal³w$.“ü‡C( Zþ;n¥Ú‹üWYNfâ›ZÆòJ®9lLÕüÝ&Ømaù/9¯O꞊¼©RÿpòuŽS§gIýËËIõÏ/xÄ¿ aÿúiÁ¢ýáÄruJûËÀí%ûg`?Lkݯ¬ý¡æ[;©ýuŸ°ö‡†¸>^Ptáuö‚âõãÍûñ/#GÄ¿ô{kÝÀÖþp&"‹´¿~ ­ýÅAÑNÚ¾H(â߹Ġ)ñ¯»Å¿\µ¿ òÑþPÍúñ‚f€Œö‡Ëá’µ¿ér¤ýáökk2ICÿpÈùñ‚âPHüÃ!âD‰¸í”ø‡cÖixÿÐÆÏg‡`ŸJÚ~Ä¥k8äž¡¯Gëh¸qÅ‘ö‡”DóþÀ~¼–þúb,ýug³ôw.–W­ýá›}Î1cºŸL¡µÚvNá\¯õaoÛ=ÖÇLA²>¨–ƒ~ñ«¿­ýÎÚ¸’žz»¤CY»,ÁlS0´>ÇÁÕÁTÕ%]•ËRU 檮…K]UJ¦ªTÖU¹à?=Ì6ØI~fûA²E{ÿ»þq˜í?öš£ÖÃlÿª“ìGh>*u%€vêšh§®•º¦£\WÐv]sm×ÕG¹®ù¨ÔåÚ©ªCh§&“Šú˜Ô“Ú©h  šrTªšŽÊ;•Ú®k W1G¹®ÿH˜m|/v¬ÿþ2Ìöõa¶ÿÐw~fûÏû9ÌößTwÿÙafûo;ù7Ìö?(ÿyÐûŰøû/_žŸ†Ê_¿;¨é_³}lïDƒÛ_†Ù>o‡Ù~ÿõ—a¶ßÿï0ÛëæÀØŸx×fû{ŽŽ™ÝµýÏ_×Þÿ¿®}Tê Ê8¿‚Óõ6bm÷|çI5—>^,¯µÝ"ïµJnZ+€ûý“¾Šëfx­c{è«@êš /qa÷¼9 >öU¾ ÜK†|ÎQxì—BÐû^!•k…¶ÜßaŸËlP<ætêk­{X|¬Ì©P÷*¹¹Ì¶bŸð` —ÙÖSÀ±?\f«Œ-Ur,ŠÊ…¦­ <ÖK»ö.ÎT¬,–OsW„­ãØ–k(%ñqì ˵+RÒŽ!ÁjùéÀ²wí)ÉÚÁ ËÃx=,<œ¯JÉÞùíW-m˜0ÝóšÓ¬‡«jÁä8Wùí‡æöï¹å·wD•ãÜä·÷öñãÜm©?-&ÍÁjO™ímó~¿ø2Û#Éb5ÄyËlï­Mo‰ÜöŽYÌö·xàÀ”¤<š—Hîm™Þw]SûãªÌ1tºãÚ¼ïZ˘ï´^f{èUpØk/×ÄqöÚk1ô¸.yí½Ûø¸nyíoCÞ{íWr‘'vµ$[àö>7yí/i# –Eó¢I⸇7^ËÝòb‡¼öÈÀÅcvzíßËIî}ÈkïlˆÇ}*Ú%ïÂQ|å R"›ªmY4!ç(Y÷‰(žê¡×~(ÝàÿÌù´!󀿇&µùãxÆ‘$:l¿g“ÕÞ{ú_x”Õþ¡Æú‚—œöש^óœrÚß‚ŠYMK)¹DÂo'—ÓþZ}ò[N{'Iz±ëlû"wÚ‰™§’YÕòÓ‰`æ[”IR‘е,š·4¢aouœâ—³¢ëJ”©—îDÄÓE™K=!³<š'—#Þ—‰Ð.­ŸœËíDh‡ÏtËiïMóçòÈiï=./UÊi/õç*›=°~²ÙìO¥=×MYÐÔóOL¬ÊžyÊÊð~hl³×Ž¥wˆÍÞÝñ\/'AS€AÇœÕî\oÚìõ®‚ÇIÐPâ‹“ ikÏYsƒƒý|°d8 š¶Êœ¸èh\UñØí²Wü^3Pïg9ÝÁ9Ы¹œMA>ODí«ÝR΢y"î[¹ì/-ßœˆÈ·é\5=chÿѪÎmu4¥<·!—ý)uï,×ô1·N +ŸL}LÎJWÝF™©N¼LÏܳp¥tÙkŸÂ‰ó¢ñ†Ws;šTÃßgn–bÏs_ä±÷&§s_å±_Ä‹Ç yì˜ïÜ7yìuïGAûSŽ¡s?:Z­žû)½³­ûå húÒû}æw­œt'>Όťüº'>ÎT2O]>ÎTñÒjÉy¬òØ;Ûà ¤ÙÕEkð{?[΂¦¨,'4=fAcˆÂó8œM+Ù'<ÎP°óý() šÄ›G¯âÃcnYì½…î¬õ5þ¨nŸæ¿±ù²ŽÀ·y\ó»yYì/yÏÎs“ÅWU½øÜ; [ø;|œW¥íc—½†ö—óU_›ö·®]û Å×!‡=d¼jbdx®ñûÒâì‰ Ïêùÿ–Ã>ïØuËbï§‹üÎ5z{8Äǹï4>Î5xß@N|‡‚ʰ¯Ý› ö—ü~ç½Ë`ËŒqÞ‡ ö§Ìhç}Ê`Ÿ–@~çÁï¡ÁÆ«KyúøìÊRÁçÍZùëO9½N¸dk?/Î'O|ž™ÅÒµàó\xF$|žkwþ¿óÁ=L3ŒóA¦>ñœ+Ço'\<Ÿkáø¶An翱–Ê«¹oŽß§Üj'&ô5€#*Ž¹Ú¹pÍU°¿¡ÖU2ÜŸýþ\ø6sô–mý·y(áÍZpkw€ ®+Ÿÿ…ˆæ» 2Iør=»WŸ¦¶ÔÿBVçkŸÞÁ Yï1=” i§qåBVç¹/‘Ë…OsÜžpÑC/nÂ×ÊŒ¢½·#Ë.˜ãq埅Ónö»Ê½4³ßõhTèw–Uf"?,¯bAÂßéÜ6¡¿ËÈCØ}ñ¿k[ô#Ãßµ)´á¯R½óÁßåü †¿—eÄð÷’©v«þÞÏÂÐLPð73¶¬-†¿½öžá¯ãþƽ)¦Ÿáïý ù½ˆ«é¤Éï-I%œŒûYHäWJ!ó´©þÑ<_äWNI"…ÈïSBS½í¿—šç&øõ ƒß{¦SÓ|ßxÞçE€ø HµåÄ7øssÈS-«¬ç”§ ]ø+±”Y‚²Øo`Œq‰<õXJúÑì7„±ßÀB¸Ze©Gø„ ßxàÑ èm²Ô¿—KÄ4ú•HÌcYêÅc6û½õ(l»Ù¯Jê~Ë®?é¨ؽäÿ¼S# 諤d/A†­AÆõLø#A’Kè }o-ÛÈ̇<*l3è²gšù–¡&äûª„È·\Ú_aäC+d5!R lÄ.1ß²*jz˜oAváªØÌ· ÅÓ ó-¿Òa¾¾I3°éa5b> {¼™oªẊïÛÜÌWkÆD(1Ú¼Ôd3L{üÆ™ù”‡Ó 3RdèGb>¤‹!o˜ùòÂ|SÍ„>|O84ô-|dô-›Œ4>\¿ž†¾åñ×ÓÜÃÔÜ·ì—N܇ åmüpœšü`s± üð•äÚàWM@\ø-·’Büp¿µ¾ð«2õ#ƒŒ‚:ß 'iLà—nð«$¤:‘Ì’BJ‘_5%kùáNÎL~ðj|Ài=x}â¾åñd×Ü;ÇBŒ"÷-§¬Rá¾å\Ìkâ¾uU8ŸpßrJî ÷!iç…æ>CT÷Á8Âɯ¹o¹´¼îC~kq©À¯[Ëà‡ù »…Éo¹e& ùáäðCóÕ€ð[WÏR ~?nþJà·\Š ðë 4øañ–óß?xjÈU?¤@ẃÁ=‰¤jðC÷#¡üVú±&ðëÀà‡¹ÛÏà·nÚtòCk‘¾L~eà! Šü–GÁÃC~˜ L~Ë#/¡É¯ß`£_·ŸÑo]´,ô[óƒÑ]r|Ðï4gþB?$ákoôÃÕpIÈì·Ü¦³¬Ã\–1ü!Çùý?\ 'ú†¿u•ÚøCëð±ß:”.ì·® Ëö[/¹˜ýp9 +ûÁ”Lžû­‹ÖT¸>v@îíéoݼ4büÃl]&üƒÿаñȉþjOýa&™þÐ)ù2šþ0ž³[˜þÖý›þ0Âó ‹þP Ðø‡+æàoüCöyÞƒño]µK;ø—ä0Á?\ÎEL#þÁW¶|ðoþ‚™ÿú‘›ÿ06ðÓhþƒßóߺjûMø/÷þ[Çà®›¦Ó!@tÊꃀh÷ƒ|'Äõì¬G¸B~á¯È€iÓ@ :Ïž¼?EèÊÙRˆË©7?ˆV^Èo¤Àéa ®fù`à:NÎc‚é_Á@´ÎÊaàŠøS¬´C{’w4É„‚˜?Sëˆ xqÝ!,xïŠô&¾  :ÅùAALè(%ˆ7<ÞcfÁw¦:,¬ ØIª# ög …Àã2ÃYÄñ£Q°»o뀫Ì\“8 Ö7íinSO"šuÀSûV¢®H‘C°“ˆE¸Š¸(ÚžuÀøòÑ1…Y¨èY\•ñµuÀ!Å2àX´å?2 RSPÝ´ ¸(Fdd@Ì„xã–áÛÅID5|–Bñ“ý¤B•œ(%‰“(¿š .J â¨o'›ÝR`MùŠ ,&(s¤@œ\R ND¬±˜¨àáA„¼# Y ĉö™k'—=¬¾š&OA´ÀM™#-qñjxŠˆHÓiMXÇêC¢Žw‚HÝ9bàbE[b "ÊsuÂ`ˆ­*| † î0tšŸ€!QòóÁBÜENca?c!îûú`!C­’ »E……‰ú,ô*t`Õ@a³ qSç ó1âD…Ä…x_Ø× …¸^¾w†ÂVa …h .ë –ÏÛPØ¿2&½\¨0ŸÎP!FÀ…Lj q —ÜL…øtnR‹ kƒÈ ûI Ñ8Ò…¸s6 ¡á$Í “ï0PØ]ÒTˆû¼ø+Q!Ié}¢BÃñÅT˜èº¡Â¤ öÀ.*ÄX»}DAÜèóãü âW+ÁLTˆú•¨0M…ø¢M…ø ò7⟨pˆ>…„؃á×HX;k?’`æAAÂd¦ ¦i‚„þP†“À/DˆŠ×:•¦0£s€Ow!3 ñ j¹(@صˆûGæÁL²Íƒ¹íð`úpx½æ"ë‰Ç­Ä£áAœª&í÷Éÿ&vv3àSÄò7 h¥$èmõ ξÔ8Οì Ïvš mm¯§í O¤4ÚÀÕnÐC ´í=ÕÕÚ *çÈdµz7¨¼Í×ð!6ƒ*Ây›Aá‡úšAí-i3è­ø%m½W=ì6ƒjuÁ^P;tcµç«½ çG„Oc|à¯-¼mU\¶v‚ÆZ'裷v‚Þ^v‰ô±7NÐg‘ÅÔð‡}¾Q°M76‚>^½ âCA_ç# ¶Ë*FPµ]û@Û*#è-;GAmHŠôRt¥öæDí6~Ú êˆãmµx²‚Ê•ÚVÐKÞP;AƼ ±Úzx•8FÐ\° N„ÕFPg`j#h|Œ1‚:AYA½ ‡åÒv‚æWv‚ò9Ç”Éja/6ÐCa*ÛWSl ‡eFÛ@ãË Ô6Ëv.¿}M ŽÕ>™@}ˆ= ±­Úju{@c«ôÏ®óõ“Œ ôT ¶Éj[¨M à0:1cU Ù6^òÅ´ 4V˜@OíK˜L pÛÚõ€ù²¡M Î'æCÈB‹¡¯‰ ô´ø¨|díÍ‹èõ˜mu·ÔwÚzY¿Ž4ÆÁx@ûy@okÈ1^™Ê&Лá«ÚzkÃq{@o´j¨÷MÄúhÓÐ{3ÏÙúXTŽ Ô_ˆv>ŒjÙ&PN'äÃ`ÎÞhª‰ ôQ¦€6b¢öA>Xö¹è#GP›@±3]ºM 1%›ùºæ£öÐmäÙ5±zKAÛ@/ë±ÚÁ×6Л[­'hôcÍ8 èm­º- ùX@/íÇ´«±ô’úÑÐ{Ȫi hݱ€¦›ÇšWÁÐËe, ·b‡·ÔÛYÚšT< ·„–ö€^§áÓP¿ “ô±}Ó&P×Ó.Ð{åõ´ ô¾Lf¶ÞÚß6P|™xŒ| ûÚêQ¬} NuÙFPYqÛzKül¨mÀñzOA=·h#è­Ø}mõL§ ˆ©@iÑFPÿB€ìxíú{YoBÛæ­ÞxjM|Ú (~o|çôœþe3à.Å:ô‡íÛ‡þ<3›—]ÓølttßøA“š²ƒ>ˆ]F%QvÐçðþ7ÛAŸc_µâa/(‚ÓP?°hJÙÐ^ÐÜlÝ–eÕÝèײ¦ÑÓMÊrB¿öØýÀfÿlDÉúá4Ó¶?¡Ž!áýd‹ ˜GôƒMÜaôÃÛÂ9¸ÑÇî~r=šûðNÉÍ}-Ìšû–ÝfÌ q šû¦_‰ûà]ú c¼I“ßrÜÞÕ'òC,=ªšE~ð}öâÿ“Æì=7«â>˜±ÆgàreןÈ/®¤6ƒÊ3ðÃ(òQþîæ4õÅRØnÐK¹jÚ zÉrÓvÐKì%ê[Nó|ì —_bíÛA1r8íízâµ»Ò~Pàä×zo4ûAy1ƒÞÇÏfÐ[ûoÚ z+%S»A/m{k7è=LyvƒÞÚ€ÓnÐû²Àh7(&a¬ÇnP_p»A}…qƒÆ©7è­< íõnâvƒÞž[Ç úh‰©Ý qÚ zk[h»AïÇÛ ÚþU»AooFŠô¾m¶´Ô+^í}¼³#nÐ[9âÛ úd·žÝ ·çµôñ¬=nÐ>»Ý ±—Ù z{ëIÜ ¹­¸Ao+R¦?œœ¨g3èíÍQ1ƒæjbÍ©b} K1ƒ>ʞ͠Ϯ©hÜ ]Oì nÁØAS³í O¶ïÙú6Åõ±ƒ¶0vÐ'"Ÿí 0Ší ¹äØA­€Æš{ˆôñ ØA‘ƒñÇD€8E4›Aoc‹´ £vƒ>+hûdcM;Ä d¬ ÏaPø×æFZAßÈE±‚ò¢'üÃ3¹?{ûj]­ñžÓñÑüºÁÍøÕó“Tû“€¨‡€ÐVPE ÞÖVÐË; €“ÓÒVМÊ¥õŽæiAq‚>_;As1À¶ßÛziĹ)²Å ê%öÉ ê&¡gIX“”w+h0VдÅlÝ>Ø·+è¢5ã¶‚Æ-+hv Ú šÆˆtÙló´4m+èrXf‹Ô¹ã]¼/è¢Ý:í]\kò‚º ãísÙ Û©¬ ‹ *VÐ…[ÁÚ šö‹4O8NÐTÓNPó‹4w'h=NÐE;÷Û šÔw#èr˜ImuÓ´Ô¡ ËO;Óæa@Œ ëg+`ƶ0àTB\+˜A~òjÿ 0Co(0£[(0†oS`†ýP`ÆôP`Æ¥PàtŒ(°/ǘËùExì‰öN†ÇnÚC¶œ¯Ö·k÷@ÓÞí $ÑúVí•i­os=úE ˜­õ)ánK}ÎåØ|φÏñ`Á„h©/fÉH}8#«qäï2‰Ô‡cnm¤Ö‡chcµÖY‘¢¥>`$YNR_O‡cø\ë¿yO›L‚{0K¯³ÒÓúO~O»%‚{pú …{-N÷bÎî!"ÁW¸·"ù/IÍJߢPÓÁ½õÐhÜ[=)ßz.vn øÖ·+‘d |°¾~ìžÛzZïÕÔ$i»çú˜O|¨f|¤¾+÷ø+™ÍE©ÏÙðÚî¹îÞìg»g7…|ëóá½1dk¯çªü­ô9Uu{=‡"¨·×“ó¹ úp1ÔßlõÄUR£³Õó}Rí,õÓ>NY=SŸ¸/ÉãÝVÏ´f¬žÐW>Rß`7 /)Ìcöܬ)·ÙSSÑ6{nñdÚìyh·o¼ž¶bµÜ7ÂÅ^ÏØ†cöÄÚÒ‰úÐ6û×ë‰=Â_¯ç;h)~Œå>ÄéÿÄ}ŒšÞÔ÷[¬ž~Oî²ÕÓÑ—ÚêéÇÐjßÛM®Ü7r[=Wb«ç¶h¢«çfÃc¼ží×z_ ¬ñzîâƒ-ŒËÊ1zb7iÎFOdgþÈ}…÷Ç|ðïàHuücâ=x° mžãCÇæ¹oÚmg—'‚-}pT%O§]žûnr‹ËӶʸ<óœâò<ÍKâòÜ잊Ëót–Øå¹,âòŒ/.ÏMIèâòD³ï!Œ×÷ìƒ{¸r*Ëíò´ÿ,.ÏMðlòÄÞ×íõ³ŒÉÓ>íÉä™_Åä¹þ$ø¡e·Ïæ?´:;h\žˆcüQüဋíò\µ¸Ñ.Où²Ûå‰ ²Œ»ÏùD‚ ä{N6…|ë­Ž—gžK\žöÖ.Ï…›Ï|ë­-7 |Ï)š7ð!b6Íq6yûûbòÄÜŸ4g—ç¢eë&>ü˜ðf›çê§iâ[±•“ (›'ÂòòÛ<1n|ˆ¯^ÉÍß|ªõ!>èeÍÇìŸÀ/Ò›¤f›'HíC|ÊÝ1æÐ$Gßs{ž‰Cûgó_¼¾vybçð׿ Êa-¾{8 Œmž¹¾_žUlžïàÁž›'è—öLÛ<}}øžÅ![ |˜ß³móÄòŒPÀ÷Öeó\ü ñ½ÿcÿè~ë³;Š‹‘ïÑÔ¯mžØšNÅÎÈ÷(fGlžØâûÝü—ÞäCK~7ÿÁ~óÙü‡MDbI;=—Åûíô\” ¬™ƒØ—ùžK0è{6‰ovzŽÃèh§'⛞Ø83vnŒîâ½—&Üa>£x/Þû‡…&R ÷þåúâõäë=íý»/ë|ÞûãÑGùC.åý«Ùû÷Èû×^ÏE8¦ðØ×µ1|H°>•’fŽúêc¦@×?Ô?ËA¿øÕ߇ǾÇSÓš®·K:µË„6S ê‘V>1­»dªJe]• ¦ª|Ó*ŠMî6%]•ËRU þÓÃcÃNû Qþaxìþ'‚°Žõ¯"eÿáØ¿šý§¡…ÿØ­®ëý²_ŸX¿êDæØŸÛ®©ãb«¦),vjÊA®iް­š¦¨Ø¬iŠíšú Õô‰¯íš[uPìÔãC\Í[ÛµtDlU3ÄN=9Èͱµýªu¬çÒ{/Ëß ~í«½±hXîMäÚY"ï}—òÞÛ4{ÓÞ{%å¹±ÎA<ÙêØvé.ëÆ#ë½í¹÷¶È{o‹ìuÄrpzÇhð‹b#o,Ùä¾·ïóF§cò:Þ°ÂoSƒÂÑH§»þ×59&o<²C»&xãå*Ü'Óì½=2ß?ŠrüŽ%2ßߊrï«Ì÷%~ïCæûGñ_Z–ÿþQFû{ßå¿×¾‰·@öûg÷ÙïÁê¬ø¤ý>W¼_²ß{£Ç½ßòß?Š)óv2àç˜c‘ß;HîcåzüÃlõcП›Â<«´”GæÄûع Gqâì¡Ãßo ñï>9ð™%§øt¯û¸dÁïsݲà? ‡ã9¸‡Ù¿ªlt'°ÖUîs•ÿY8–Ýç_FîûÜäÀÏ©Î}áçû|îrà?;û>9ðó0ÏS|8¨XrÉh¬ö–«!,ydÁvuã—æ9†§E_Zæn›ì} yðû˜MüeYrÔŠÜΔW(8¹"‡‡Ç—é!ËøÂ“ß2áç1\LøX®¯F¿™ðe"¿ïU&|7ñ=¸"×§zG™ðsÌÆ¹é˜Ý&|…k¼ïC.ü´²0wzZ•±ýa×^XrÛ…Ÿ’gÏ*¾ŒÏ¢PÌ]²Ú…ïw¯”Üu25ßÏ&¾:¸×=?óg犚_«çP,æG[ùn|¥—Ïó|.¹ðÓ¤Ï-þ­DÝ÷óÈ…ïÑâY®Èá\µøü,«œøΞeȉïÿŸ–㸶 =%tÍmú”µïóYñSpʇÏä›(¹dÄ¿•ZùÁgzݦqýÁgzh?\MæžrQüèÍobÕ0î½OÅx»~ôžŠgÝdÄýí©€iûôdq¾Û†'¯J[Uó)#¾­åÒ8ÓˆŸ’ûÈ0¾³ä‘ßmÏ4}øÚ*ò`ŽÃøZªË\ûÔùŸZzUƒ²É!Œq÷C€àÂQ\é)Ëq¸©‡ç>mÄw«cÏõ3}¾l§¶ÿb5Œøic|¦iÄgJú_é±O#ó ûðÕ!ŸËÇýÝy´ÍmþÕ~kמç†ÌƒøƒÙ q\‡ÆðT|ïÄÝÛ£ö,"yðæ ~r™ùÁ7zÕMn,«ñS½oß âÖß’Gƒ¸žÜ¾ßß1üA^ðCŒjöþ ƒóyÏ·„ ÎÞGUÏrg®ÜÞìò ó3ïAyðf.íR}ðÖNv,|¢×9«E­…Ôî©Ò[òh•¶Pd-&»~þi0íÀàµ`­ ‘q#Å ¡hˆô GYxað-QŒÃà¸.EÂ0 Žë–‚dì8؆ÁqÃ\Çcƒ_)Æ ¾%ŽŒ XyÚ…‡ŒÉürNÓà[â{¢Á Àèt¢ÁÁUÌ¢Á÷ÏËLuQ¤/Ò`ÃÑà[¢ –¦Á÷W Ä.¬‚g†ÁÏ*ã ß’Sw ¬A%að-QTÃàx'Ø¿ñÜdÁ:„pÄ‚ãfBêÀ`~c¬ÎƒõNòƒ*Ò:Ã`ýŠ35Áà€dc=ƒ¹£95 ÎÕçëW+)“08•ëWB6Âà| að-¹¾0XÇð3-|GT½¡†Á:fa ap m6?Ü‚Áú§>„A/±4 V5ÄÑ`ýhýHƒõ+Î#Dƒó1¤Á­Ž‡ ο! VÉM^$ ÖoŽ™+ÑÙ‡ç_‘ë˜ên¦Á*ÙIŒÄÁ*!î kÔ €ëj`¬ë!cëWb¿…Û¨öpfÑ`I¿!Ö!\ V½'Q8XÇÁ…ƒo‰v§»V=<¹p°®ïŒp°¯X48ÿˆdº@á`•pº)œš‹8X×÷Ì8X?â|S8X%;áàtWÂÁÞ«f¬ ä³"ÖxSÂÁé6…ƒsÅÄÁlï«!vSˆçs“ëGƒ“çŠIƒõ+Ž1¢Á:†„Á*àb’`pj.Ñ`Šk Áé<¢Á¹ÒàðêDƒUÉÂS“ëêø0EƒÓ=‰«ær)˜çÒ`kc ip>†48=Ñ`ýªîI08Ý7a°ƒšëú‚a°ÛS,8=K±àÔbÁ©É‚sYpj-±`ŸI(8]žPpº¡`•ðj,‹v5$Áº¼…‡ç‘§‘àô+‘àtã"Á©WëK‡ð<¡àÔÄBÁùa_(8ÿŠ(X¿â:–P°¯H°+6 v›û®L‚ýdL‚}Ÿ&ÁœJ ؽÏ$ØÆ(8Ÿ‰(Ø·`ì·Á(8›(8ýH(8ýH(X§º~‹†p_ŽPpþQpj.¡à|r¢àÔ8BÁ¹¢à\Bœj Öfcˆ§+$ Î?" Öm3 ö‹fìË08=sÁàÔ„„Áéѻ߻§Ö NõˆçcHƒSW ο" N7!œÚ]4X-x²„88×CœK]ÞCþ"N'Nm#œKˆƒÓM §6NX<8Ÿ‹<ØŸvó`ëÂé §ëN·I œªÎ%ºÀ]ˆøhw´›Að_ˆª&Dܳ}ý„Ø;Zè!&Ü@4-Y ôv„¡Âë±ÎPñ'Pnä„(YHw‰A“ò Âì­‰B¸h&…0Y.¢&9@BüªÂdˆ@kóM“@!qIĨ‹Zìj¬&¢wôÁ®Fò ìXÔ¥–‡ºDP«ƒ(™y°~C›˜ÅÁ2uQ.”8ˆ-³:ˆÌ×GD² tRñA¤ÔAì#ẲÕAˆ¶œ‰YD51’êàT uÕ\u0õ£âc!>•:Ø%VQÏéƒÉ(u0áü£fCJÔÁ©©ƒ0ÁíÄ?©ƒSÍR§ªƒëly0õ#v‰åA\è2aœÂ…åÁ®Yò ª! [œKžoš‡èƒÖÓ#âLl ˃}ˆÔÁlñ‰<ˆ’›BŸäAô%b›ÔÁHùQ“I#ê`÷%«ƒý¨¤&‘@äATé«åÁîÇ–§Ƀøçã–qœÔYÌ=XìNju0É6¢ö$ö¹­¢šý£f3–ÕÁîØV»Ñ­vg³:ا²:Ø×gu°;¶ÔÁn «ƒ*HdV§Iì7Øê J–:8#upªGê`?`«ƒÝ ¬ö1V§c¤N%’Q²«%(ÄXìþgy°Ÿ¯åÁéW’»E-NÇHì¾ny0CväÁéɃ(Ù>ò`†_«ƒÝG­&ÿ‹ÕÁ¾+«ƒÉUu0éU¢ö·Àê`—XD‰Èê`ôVûùZÄ1ËŒ„ÓmZìÆ±:Øï´ÕÁ¾O«ƒÓåH\W;¬¢„+CVQ^¬&MÔÁ¾B©ƒ}9–»u,âGcfÂ:9¡,vƒYìæ±<ØýÂò`žVäÁœ=ò 'Qó6FÌ]EÌ[Äd„ƒåÁ¼DÑûL×™aœU˃¹…ȃy–û˃i¿Èƒh¿ƒ%›sõxBnypúÕî\=ò¥DœN.y—üÌLØïHäAœ]2£äÁ~Ö3§Š>Øg—@˜~°[Ýáô# „ý€-&TÂôm „ž'Fă—'}°Ïm}0oQÂL#âÜ‘@˜N`}§ºÉšÒ§郹>˃Ý#­NW#}p:æÙ§0ú ÇÈȃÝ%,öõ<˜iläÁ©Dú`?9ëƒÝžÖ»=­öS±@ØÝÏaß“¾o „¦"v—°@˜ÏtÂ>•ÂÔó7QµÛ$Z›"gÄ~Ù³EôRÂW«‚½}XD¼1Ê„ÀU›nW5®Ú1ßÖ4.ˆ—Iû§ÐA¶€“{+Þ˜ QˆÐ2Â9à²)PQp*©À"›ÔŸ 2].Ä0àT"œJ„€EIä0! †ãU ÂsM%ŠÏå d@ÔCª5"'™Ú˜Ü—¡Àe7S›Q³ ¤@ä ½)Ö­ÎÙª”èÁ@T3ˆŽÂÀeWœ` ~5Ë‚u5tú‰·@6RQ j‘T8[ˆ_ñ+o Ì™ ¨fý@ J(ö4! ˆC¨™‘””s3 ~tÏ¢à|*1`߃0¹MÀ‰ìŠÍ€}Œ°›Â Ø(ì¶1v›QÂi‰°¯ØˆSI¼œ²õp=·S¶æW¢À<C`ß¹)?¢¸h ì'c œ~% DÅûL}&A`ûûÁ»ÿû6 ‰)LêÜP`?S`߃)pú•0°_c`w8c`nK˜>jœN$œN$ì7vÇ1öŧ »m ý }9†À©A ~õ| pºA`w[C`·±!CÎõÀ~æ†À~†@Æ$ö³5N5ˆûM€®Aø‡á’z¾ñ¯6o²Dø‡K¥ÛÑø×ã¥ñ¯/Æø×5ÿºéÌé Æ? ¶×Œ(àB‘ñ¯¯Ïø×·müˇ"ø×Ímü˹E}½¦¿¾KÓ_ŸÛô7ýJô§6úá'46ýº—ýºñŒ~S‰Ð¯Ÿ¤Ñ¯oÛè‡Æºg9°naŸ¡Ý2F?¦ѯßA£ŸîÉÜ× cîë»4÷MW'îË—9Ü—« ÷áWt–üòùøå‚~(9ˆ‚?4½…¿<§€_n"ä—ÉDÈoú•È%´ï‰üØ4Á¾tà`_ß’±¯oÛØçJÄ|é¬a>œvý0ßtŒ˜o:FÌ×·hæëS›ùº5Í|™Ñ™ùtu¾n_ŸÇÀ‡cv …¾~ú¾¾^ßt)"¾t«_·¦‰/¯Jˆ/rˆ¯Oeâë†0òM%B¾tá _w43_÷43_ߺ™/“]2_ÿiæÃL—6RC_w#C_·±¡¯[ÔÐ×lèˈèë&5ôu'7ôMõúÔL|ÉC|]­ˆ¯û§‰¯¯‰¯›ÜÄ—OMˆWÇmàÿ8¨vÃßRI–'ú{çr#ÿ0¯³)4>¥à¸ëšùï2*È}L¡ï‚ß©˜Bï#FM›BSáÔm ½ë»Cpà³A-¦ÐÃbcL¡§¢å·)Al~ÌžÐS‘~Ûzf_aYNEkOhJâ =‡m™ö„v‰=¡çð¯l =¦=¦ÐÓab =•µªM¡ç¦ë1…v‰M¡ç&UЦÐ>ĦÐS1†c =•º¹]¡Ž‡×®Ð·d›·ÎÇØÚÇØzî–å í»BÏ]kŸq…ö1v…ž»Ö®ã =“¹]¡ùU\¡}Œ]¡]bWhjŽ+ôT¼åv…ö¯ì }Ùæ-‚ó¯ä =ëv…v‰]¡ùQ\¡9U\¡}Œ]¡©Ç¶ÐÜCl¡ý#ÛBûG¶…æb íÛB»Ä¶Ð.±-4%±…æ\±…ö1¶…ö1¶…v‰}¡'ÓÄš¿í íŸØz–í Íl M=¡©%žÐ.±'47Oh—ØšsÇêSÅÚ?²'´$OhØÚWcOh—Øê3ÅšKhz‰-¡©%–ÐÔbGh®7ŽÐ\^¡ù‘¡ý#;BûLv„v‰¡®&†ÐGh*Ž#´KìM5eÍÕÆÚ¿°!´KlMÛÅÚÇØš5†Ðü*†ÐÜA ¡¾ºøAS`;h×b;hÎ?hž¤ý ©ÅvÐ>ÂvЮÅ~ÐŒ—ñƒæWñƒæ¾íÍ?hÿÈ~Ð è1„æä1„ö16„ærbí;B»;Bû;BSGh®0ŽÐÔGh®ÇŽÐþ‘¡näBó¨bMsÅÚÕØÚ¿²!´¯ØŽPÓŽP__;BݹÚê»jGh×cG¨¯'–ЮؖÐ.±%´dK¨/¹-¡ý+[Bsr[BÿòÞg÷wYòÛû)jyg1‰D †·öÆ€ ôÌÂÞ¸mÜͼ¿ÉÔ9§ª«×ÀÓ›>?¿S¢(~ÉÌüQº„úõÜ.¡ÙLº„¦UéºKìºKìºÛ±K辺]B÷¯ìºëØ%4KÒ%TÃ`{„ú•Hм]éš½IP¯¸¶Gè®cÐ}m{„î:òÝ×¶Gh•¡ù£ôÍ¡“¡y©ôM#Ò#ôê?z„î{„¦Y麯nÐìsz„z!¹=Bw;ž-ä·iÐ]bÐl$=BóÒéš—NÐÝŽ=Bó¦Gè.±GènÙ¡9ØÓ#Ô‹ìíš=LÐ]"Ð|éš]NÐìNz„î:öuÿˆ¯]Àïúá4໌’•à‡ A%¿©ƒéü®%µ+ÁïRNŽ ~Kù66ø!€Ý÷4àr¤ó¿·äð[ÚëÝà·´<Áo-‹Œ¿uùÄ Éo™p“ü–‚~ˆüÖ2šü–ÎjnòC2œÉo=rÚ4ø­Çò ~YÅÜçR›ûÖm4÷­çGî»iesßÝ©Æàw+}À¿õãi@äºù­rßíÈ+É}ë‘§Lrß®cîCÆPÖ1÷ݧÙPÜ÷Õùswxsß}þÈ}·)lîË:É}»ÄÜwŸ?r_v'¹/¯žÜwŸf:s"8³Ž¹/ Mî»›¡N܇´?lÆÜ·«˜ûòâÉ}÷i„3÷¥É}yqsß­@©›ûv3æ¾})s_ڙܷÛ1÷å#NîË»œÜ—ÝIîË¡’Ü·KÌ}y­ä¾|ÆÉ}yuƒ_v9Éo=nÆä—,É/oF¢ß¾¸Ù/HöC”ܦ´“ì·eöË–“ýîöûùuÜì—všýr¤$ûívÍ~9.’ýr˜&üå-Møó|‘ð—Ï3áÏsAÂ_Úð—Ï!áo7cúË{“ô—ƒ éo÷Øô—=NüÛ%Æ?w0é/UÒß. üË+'þå¸Iüˇø—“Eâß.1þåýLüsï’þ²JÒ_޾Ŀ]Çü·|ø:ù/mJþK³Ì»À˜V%æýLÌ7&0‡h`Ž?`6“˜ýKÌÇ›¸eÜ w oiòßþ‘ù/-OþË[šü—ÝIþË.'ÿeËæ?_;ñ/GNò_^;ù/^òß¾’ùo·cþó `óŸ{¼ùÏu6ÿ¹Ç›ÿ¼ØØüç«oþó¸HþÛ͘ÿv󟻼ùϦoþÛ—2ÿeóß.0ÿeÃÉÙLòŸ‡Å濼;É»Äü·eþÛ-›ÿö¯Ìzèÿ²Ë‰ù£ä?¿4É»Šù/{“ü瑲ù/ïEò_ö8ùÏc;ùo˜ÿö¥ÌY'ù/NþÛuÌÙNòß®cþË—ü—f%ÿíó_ÞÓ促ɻÎó¹É~R‰ٻĿ´ ñ/û’øçñÆ¿¼râß.1þí_%þu_Ýø—ƒ ñ/û“ø—ý1þåHüKËÿr&HüÛÍÿ%ÒöyÄÁŒ¼õ<‘i–X±®SbfÿXiÿ,+ýâWÿ8Òöy »S´½KvLk—eèÚ,(1­ßÉÙç?]tIiJe»)|šºÛ·!þ]›AIi$þü°}"üõ¯FØÿD„í1þ¥Û¿N/BÂ?¼†þåè9Wyî|Êj+Ãgg[%~v¶µk¹­ZKmíÚn«FÐv[¥–ÚúÔr[¢Mí(ÚÙRÖqC¥ŽÛÉ ÚÙP‰¢-íZnªÖòË–a´ÝV£ï讥¶þ•hÛ|¯ÿî£mÿ•ôo?Ά¿˜/ÿöë—ç;‡þÁ»ócKÿt´íó`»?·@ÓÿǯbaÿoÿÝñ¶çH¸íëá¶ÿý¿Ñ ÛïSÑÄL;°,.ÂFÅÒè-\ªÍ“GÔß’Èú~<|ß¿¯ØŒ{˜30J¢teªø·»J8cqsð– ê/J”açTð„EÈýÜ\| n3|K¿üóáø·¤_aÑ;ˆ‡JÔÿ5±ð-Ab:”u¾à-9# N&…}K€óòmiñú¤ƒïûgà«×%Ç~½Ž&T¹•¿š*Qÿ<ó-Qÿ›bi¢äù]kùVž¨Žî9µì[r®0©)&ç[Ò.>#K}K„Cçß¿eÃ~ŠøÇqÙ†Ž ³õ{×-f¤pPonÆc>¤7¿%ÏA«:÷äPBަg0¦E bv)Ÿcâ~´X9‘óùæ”{éW±‹IŒ«¢sD*WO”çšÔˆ-`:Ž·`5NäþŸã>ù tðé-yN ‹’‡­ÙìI ðx›JhAlçñZÈø¬N„X]{’[ª3”g‘wa:XãâµñI>?/é” ûAMÙàL)oÉsÐ*@Éó»Z~Øãë¸iÕôý¼ÎÅÁÖ5;]2awï’ §×'R>k.׫‹”Ïš©§Ú‰0é§¢ç¾/†cF¾x•Ü̵qêpã[bi %' VYÇí‰[¯û:¹Bðj¾Õ®ß¯O‡‘óyñÓw«ŽMèžtMÀ;«ñˆÌ_ñ¦v"K!.ô÷Í•P.>Îõp-w=¾ç‹&”+ݲ™FU¢mäQdˈD¬WŠøñw/ŽQM÷ÐbîòíBÚge}Ö8¾iC¹;7m8üèîȳøtO ø,kqô¸D«¹®Wê9´š›~ÚÚ3)Cí±þ.çî×O5v‚·ÏN–mZy øÖy&«ø"ÆðÓ,àâMëRŽjÕ$⃳ÎЯH|XÆ]•ø^ü<½!ò½%Ó«R"ß[¢ÙF¾ˆâívdôÈ„åu5ï-è^§øÞ¿½Î&ðE ð®Ëð5d#×¢ªÉ€wŒŠ@º ¸ýð5¸-Õ `jÈ‘:TÀ%¢_„ŠøÞ’fŠí2áQ4d_ƒ‹’zÜ#"ú£(}&¾(YªñÐñâHZ&òÅ!ã-¸ß èP -€ëÓ)x dŠÁ‘/—káJä /­¡:| ™`õÈ|}ŠñBÿÇ(PÿB7§W¿bªûd¾(Ë“ùß^¡/B¦ó³*è‹ ¢) Î\“ú¢äÒµúÞ’ÉXX†¾(Ñ=&ôµ›9Ãÿ.ê‹Øë‚iÃeûòÜ‹uÉ};ª»Á/"¶k‚à÷ŽÓÃOŠà%FAÙÐS ~1ŽtO ~/^/8Á/J4B ~;¦<Á/þ^üj%´óAê‹xò­R*øm'õEódPßçW4 Ö±“GZ}Q"f#ùE‰^’_­ò‹Èõº1$¿(Ñp¼mCn.ݶáôËAò‹Sh'­"ùEÉSÉoŸT3ùE|ýÈ&äŒtÛ„ÛèOð‹’[¿ jªï<À¯þ†à·£äüâ7½‚_Ô9ÄpM .š ~Q¢Lòû”,:]¼í;ƒü>udC? à$¿ûßäWêúÅßZ&ý-/![ _ÔÑjð° §W‡m8W•§· ·H~Qò!¿ø‘Öu$¿¨s‰ ƒüê¯N›Ð¼ÌuÚå)ávnàï«p+*5lÃn×6$uþÊ øûü*àïÓ›€¿(UÎmƒ^î¹mP;„¿z/µeÂ_æÔkÔ ø«=ž²a[Nø‹,-z]uÚ üÕkþÊ$&ø«×ºdÞ¢.ÙPJÆp‰®Eú+ïüuõÏí#ü}~rŸžŽ ш6½õf‘þÊ…µw„¿OIŸžç4;®m |m ŒvWsÉÚðìîó‡É›ðW§ºeÜá{[ i˜ìW§T²ß§¤s=´'f²_íٯΡ·MØ%KÓ–÷¯­òߟÃS¦K²_½2á¯ÎlÏO<¶ ·°$«æÍú'‚f'ÿiù\¿ñøã/þ{Æ¥•õ>Œ&~±­÷ „ýÀA@hÁï4¤àwydÁﺼʰâ7´á˜‚ßÈ…¨¿÷^”[ð»V‚¿ãJUB‚"oûâ’c%XHñC`í˜[ñä|¿ŒñŠ_FߊßñX1KÅÏ+; ~(ÃXðÛFYð;<6,øvæ‘à—á­ø¹Ž²âw\_Åî‹br)~¨² „C@ª »ŸqÁSðË`‰)øeÃü2 e ~ÕÜ?Š_†–âwb ¬V"fd[Ö0¥øe¸çTüÞµ·"¤øíòä—ñ²SòïT Úô*^Š.e}ŠDbc%?¸zjIñÃ)¹á¯ã%3 ʄ݊4¿->Kó;GóŽD?Tѳ–èwö©Yˢ߻´Ð&ˆ4¿rmi~áˆúÑüðÊÏæ‡†›ðšnVÛè÷þ=<Ж-8¬`KóÃCÐ{+ͯtXš4va%?\H´ ÉïC»µ–üð#í`Hòƒ™zS¤ù¡Ž¼$û¡Ë«Â_½!ûAÞ¡QõÛ·ó¶wJ|2¯ªð‚Ù‰h5j†¢_Ì©¢8Š~å–Kô«¿’ø4©w²`xycÑ>ÄÚ÷è‡Í+!úãòë.ѯôF¢~£*2d¡F¨˜Õf©˜•KKô;gN`ýΘþžäÍœ' ¦[p¦€GÁ vkI¢.¤o¦D?¸X˜ )ú¥MÖüPEË(i~Û/ÚJĆTÌNx)ù¡/>†Z.צäwÎ\þHòC…q§*hqŠß»Z•S€%?<-.$ùí»kɯÖqÿ7OÚ€aÌ£dsÉM’üÊ‘ä‡f´š”æ§É£ÒüpgLd4azš®#“$úáZÎIôC猂ýj+ýp¿¥.IôÛïŽE?¼)Ó2àC›Ò‰~åaKô+7]¢J.™m8ôÛwO¢_¹ýÊÕèW¯DѯŒ`‰~øÕªèwg|T¿òÀ¥úáêâz©~èáYÑïS'≿÷XX?lC^{l4¦¥û•Q.Ý€`Kºß~ç$û3§MÈQ,Ù¯<`É~åáIö+—ì‡K™#xøðV¤e?L¨.± ù`$ûá“`:¤fV^É~hg|d?LYVÚ(û•^º¬’øzm¬éQ4C;Òý¥ûahŸºV@Þ´î‡O”†¤t¿=Z÷ÛA²ž”<¤û•·Aºæcu?ÌÃIÒýÊÍ‘îW%æ;jfû{CݯG’r_ª‘Ü—çSRïÉUc$õ¾ûîö@’Þwß €Òû2“hê}™T5õ¾rC¥÷¡^y/J¤Iï»o¬÷Ý÷2½ñðØ•¤É£²ËP#¹ï¾ý¡N¹ï9¼ ·Ü÷¶"ÖrŸ$mµ.râ4ieoÃr´Ú—}³Øw§ç«Å¾û±ßšÅ>¼Uì{N+;ûž3åA eNE¶Å>'9ÛbÖ’"7‰}ÏaP¶ØWJd€øÀJŸÿ”̇ìÛ_™ïIr¶Ì‡ôëªãÞkYo™ïiÆÉ|¥Že¾RG2_)‘Ì·¯m™ïé)áÙ€]"•ì骖ù ‹%óí½Ë|ØdеÙ`emÛp ÀlC^ÛJŸsçm¥ïöË”Ð÷ oÈXèÛUlÁÌ*¶ ï¹u>œÙ¬žQboSé|ð ¦…ηkXç»’h­ó=y´ìÞXÓHVêHçsàÈ­óm¬ó=ézn¡ï™)ëÙ†ù£Ð÷xON:_i†:_ù[:ÒÌWÏ(±ògÖ:ß¾´u¾m‚u¾r-é|¥eé|{øYç{ú—ö¢»Ò^¹ºt¾;]ú¬óÁaŠ’ù²{)ó¥á)ó•ÉdÏ•£d²çJF”ΗF¥ÎW~%o—XçÃ6çæ½è°vÑ©óíëXçË÷2…¾Òª„¾R²-ÐͳÐ÷¬lYBÙãm¹Túʯ¤ôíþYé›=ñMJß³¼lk¶A6Ré+mH'ÛVZéÛ}±ÒWZ•Ô·Ÿ¥¥¾|ëRêË!›RŸßTú¶‘–úö­±Ô·»Ó0ÁR_ùd²R"™¬\IRßs{ej©/§¨”úž[;VúvÃVúv÷¬ôí»e¥oÚS=•¾Ý*}ù²ŒmÁQi/Jä¦j¡¯”Hè{n+-úJ÷$ômæ6AwtnžŠ{õnYè+¿’ЗFPçË›g™o÷Å2ß|ÓìÞI#+u$óíl™oÛm™o[`™o÷×2ßs§ú&‘l[i™o?ê|Ïþ¥ÒùÊo¤ó•ߨ†Ý‰dÛ*ë|»Ž…¾}¿,ôí×ÙBß¾_úò%³Î·;hoOçÔùöh´Î·M°Î·ßøµMÐ\}oìÀ)™¬”H&ÛFYèÛ-[èÛÊB_©cš7˜nÛÐ6íÕ¹ÚB_Þë|ïk©éÓ:ß~*Öùötno?ë|6òŸˆ½ÁïŠHP•ü0:?~žˆV"ˆã¹¾Ôg¬óµåå–ÏõaÛBp(ï½oçÇÍ33.%ø!^ˆhGà‡À¬nžÇ;%ÀødߙǑ,ôµ<øb¡¯·ß+øÅ‘A¹ÍQçs4ö­óôגΗyi¶Î7Rª´ÎǨTOð‹’NöÍ3E< }s;ƒve×_GÏžùc¶ÐW®6¼­ˆ­CèÃ{ñŠ„>,stºKJPž£ÒQR$¦É‚ù$Ê‚køñJê{iÂtH¡ì¸’€¥ô½è`¿S)}\cý=É/„Þ^Žö½l¡‘:ÎpVî‹ÿ~Ôƒ} àìõùPMîy *ú!2tß××Åó½P×Ù«|¸´ Ž"ßK#y"~dõ"®d¿Pö¿ýp®w ÙŸ36…ö…$òÝÇ,ò½#ÅDà‡¨:ð{«¤—­D¾b¤D>X #%òaˆé±Jäƒð+Ï 4>ôå6åÑ€{‹s²à¾|:L4tei|/=iüHãC3v ¥ÆW$ îTÚ¤ñáR£‚ßçâTÈPr|Žö!V`ÕøJ+ù°Ò·ÿ¤MÈVn›àXVùPGx+•|pT>¨õÂd©|Ūû'nÛîRù0/šº4ÈOcE>4ò=Ù‡3Ç>€gY©|ÇS©ïý3µMI|Çy¤~G‰6ÎÆ‡ÎÝŸs}à$¦ Ài%Á2\ëÜÔþ¦@j|ä}öÁ¡ãüˆ|ø•œ»ÛNvù¶UVùpZ\ñRùPr~öÕþPåC­éOÛ`ï“&ìCz‘ ãÉó8RùÊe¬òÛC”*_½Œ È˸ÿû¤Ÿ4²ãøBßNDŸ*ÞÂôE‡ïêÞYžU¾r¨òé‰&•¯<%«|Ç‘mHåÛ½³Ê·{g•ïØŽ¥´ãJ‚ŽU¾#]ѬòÞeM•ïØjœT¾Ýgª|‡=a%òb¹n‘/]s,ò•[n‘ïHg/‰|åÉYä;ŽNö¡{ö¨”B¶ëXä;úGû8Ö|Žö¡‡r> ‘¯<8‹|‡}çÆ6aVê Ãu.Îß‘þjÖø¶™ùŽiÕT"ß;·Yu±È÷Ö9?gûœd¨Ô÷ÖñfvŠ|Ç£…›D¾=&,ò•‰|‡·È-ò͇°SäÔêÞùöæ¶e‘ïH)Ý"ßáÅsŠ|GªKùŽtn¶È÷öçøîK,i|Çò©Vi|Ç™§0­ñ?¸wÆ¥¯êÞY•E¾}Ó-ò[z“È—¾_)ò?øw~ÚÙ&øWRȶáù¾P¿‘ÈwŒß+öE#ݪs$y0W>Þ(‘¡Dr¬5¾ý\¬ñËݓƇxÀ>—'‘ïý•ÏÿÙ;íIä{Ñêïÿƒ¾Ò¤¾c¥J(…o++|¥D ßnG _™R­ðÒgj´6YT½P7•vÕhªS# ýPiÿlG@ûùWŽó"¡ÅÊøªígI‰;¦²VÈ5|ÙË9ÁŽ¥)—Ô¦XVšRAmj4îé«]RšRÙnÊÿñÑ‚)¯)"œÀþ¿ˆöóðj³ÅO õ«ÑtŒƒH¹­ëÌmÕXgnk×r[µ–Ú*±ÎÔÖ'Ö™Ú*µÔÖ§–ÛÊhgnªD;sKYÇ •:ngÇ:sC5Ö™[ÚµÜT­å—oÇ:S[Ÿˆh~gw-µõ¯DD{Wn3bCþwí/̨ûqvüÅüù·_¿<ß9õÞ[úç#¢µVÿ¿Šˆvæ¿®_ÅFû÷ÿb£µyƒèžvFõÿk³÷Iâ…X¼a§«ê6g,ÞÆz´Àk3B=½s‰C‡¼%±þœ·c#´¹bý‰%æÐ¯îX¼ÍkȨÍ'o×ùˆÆÛuÄâíšv¯h׋·ë¶ïìû¾Ç$u£Øò|U:ÿFŠÉ5º`§]3–në:ݗ늵ÛêK”÷–ÄÚm]š´ß’k·ué'ì>¼?ªÀîÇÁP6²ŽX¸Å‰CD¤ŠŽÍ®ö^PŒuÛ=¼7ÓVu|m¸ÞúI>ØÿÅþÃa„}YW¬Ý°ëÍuYl’ãG÷¾Ðе[„ªgÁÍ@–@°žXº=‡žâè; ¸½sÇaÁ3µÌŠƒÎø‘Ýêâ¤ÏkÒsúpMx=(±‡Ü Þ¿¹°o7»ÿ4»»D¶’Æ&5±b+xW™u”Ûá ¡a y[¼„+ϧÛïë]°Ä6¶Š¸SÞõtm¨4T’K¨ô¾/'·ÿßylÃáÇÏ; ¿í.ÁüûwlÃá@‘ÆÇCžwí~è72aø¬Eœ$B † /Ä6ÜèÎ’3¾·±žPÛpØî"u‡zàL¨_Ñ´¬‚ð  ¦¶Óc×#ïn#ìV¿/» ÅÞ)Ú²PíÑ>WìÀ„#;|Ê„ÃÎq„&ÆÞ-†ƒ,1öºÞô8£9žáÁcO'\äØÞ‘êåÒ¥dÂ;¨OÕ¹nåS0ýDòèPÕøçûpÏaß»~>± ô=°óuâím[ {ÕZlc¡3dîÞzìcÕ’qÒ¦©-´þ~RùúØ—1ïøBñeŽX{µX°ÂjùÀ#0 ß=üº]GÂΣŒñ…þk>BæôúFFŒŸxHv:ï]ÝoVC{±‰J!oCŸ ²Gä[òР[~¡½G¨Àò®ô¾ŸÒ%¶ïýÖoµûÄ[zøÆ#ö°øŸÒÈÛ•Á‡$Ê>Z÷|p©¤7ÎvâêƒÔ°gÁ·$¶°p÷|©ë¦IMÿ~üÞã2î‹Sœ÷Nú<õI °?ΰ ã= öA–¢'‡~Ò›-â,Øç89ÆòºscÜJyKÎÙËd²ÿ üGuVì_=§w,ßOõÅQçÛ9ŸIƒíÉõë˜|Mô¢_ìéðE0‘k ]½ñ)Éw[X?êjf|J—«ÌÇ&ñóܯëæ#±¯c¿d²ŽÐH!_¬Óô«grÜù¬Ø«‰ÉŸî›}!µ8æ{õ_ã“wAãcÉ€·—ИÄ=ùŽP³ñœnDö|rì]¬#>3ÕZ‹oNÞÏe ìLÖ-ˆïmBtš›vsaÕíåù¼ìˆMo6·¡ú‡ðâ=îª1N~^íüÚo™p,_û– wÕÎu{W3kñmâs ?ßÏt‡‰bñ3ν_NœîôöƒS_³xóhµ†ôû„>w ßãó3{á{Ü8ˆºK>/!Þ)…ýߣóYZùKߟ›K ÓG:äÙ«¾`Ú[Xå£@z~<§¡×i´áé<ް!'éqŒóû÷ä"(ç¼"6§. Gh›ñjóOw_‡,Ç¡ÞÆñpt>úúØb­wj E×*ïÉ@†®˜Ý¼A:pö3Ì9ùÉy'ßèëÔšoœ3—pü||‰£ÎÐ dàKÜØ×Çã\ËϨ«H%_ç®ÎØYMœ·¯ú¹ê8»O³;ç@~®»Ž™]£Þo1™+È„ò“ë¦Q¦‚ñ®«9Áy@ˆºŠK?0íáú‡By?µe²—¡£Ë„}K»M¸É59 š)o!jQKÊkHL$ÐêòËn)‚¼YÅ·_WâCò"Éü£_]t.Ë3‚¼†‰b©ÎMǬa·A^¤”7XtÌrâQC^d¼+äí|„¼ðù_Ã!ŸóSÿ}¦_Ö¥6.úe9³‰!¯Päµí¿/Î+ÞQ⼆O˜úKÎkX œ‚«À¤†ÍÄè5Ì,SŒÖÛ׳1@¯¿.1mˆE1{CÒk±X.*Eèr=’^ÃÜâvo:]œæ¡^Ã;tˆãlÃ%qJ¨- ÇÉz ïÙ©:ÞöéÌ,Ö ÐÚ¨×0Yʨ[&œ@ô–Íç“{a$ÂñM%{a {q¥®’€½¸R¶Ù€ „½¸¸ ‚“fCO²^\imÖ‹¿§d½h¶‹w&»¥¸¶Ö0d½†Ùšb½b‚X/®µr¶áð÷‘°×öâŽjùzxm­±{ s¨1`/œç´†=lƒnŸX/.­Îõê¥ÉzQ¢õY/.γáb=\œºÿÙ—ÓýOÎ éE³ZÕ€ô¢oÔ¦„z¸ ÿ ΋FÏÊyõv7÷ÞûM⼨£9¯aÆ×óâÞ f‰yõîó>%îÿ4n·%›…ͽ¸Œ èEç´j#èEG<¤W¯Óm€×qÝýÏ ôÂF-¹zQ"*"èÅÅÙr^q­çÕwZø Ϋ&çÕËóê èE‰p† cá® W¯ èE‰v2ÈzÑ™VY¯^ˆ¬W 'ë}Kd¾ºMðÙX±^½9d½OŸé¥aØ«cü:ÓoVtɆ|þd½úü%tâÒâzÂ^~¨Î|ü¤|é ½¨cò´ »;ÁJu&"íÕâ^'À½èHƒ¸W¯½dÃ%K6 ö{LÜ«·‚¸WßCòÞçÚÁ{õ^,Û°ûcr ÷¢äeÔ{ x¯ö†¼W{CÞ+cö¶ 9&n›/ q¯ŽQò^½]D¾Ogùjw›õ#v‰|ÕL _™QI|õÒ$¾:ˆI|õÙ=2!‡(¯ZIà«ï /êLAÔÁ…P^JÀW…€¯Ü­¾òpøÊ»+à+[ÀW†ˆ€ïSg[pWè+±¬}å©ú¢¤2_y(‚¾j$¡ïS2ÎÏ¥O™o³¨¯<Q_”<"ºµüF‰ÖH}ûq úJA“ùüÅ|õ†7)ï»d¾z#È|õÚ€¾zóš,ØÐWm"ô}zs_{¾Ò3¿3]úìAÓmCò¯½ÜŸ&Zª{32¹ïaÇ¿[Ý;°'£ºw4§Ô°ºwtG ¶º‡Uf¢ ½ËÚ°Ø!uYOµLy ¯Åú¨{G»´„³ºw4g¶±ºw0ìß·º‡Uï-\ ÚYÁ/üIÝCÜ6ã$Õ=x̉¤î!{º46©{¸ú‘ èw^Hô™Rå±b€>˜-5Lꈫ$ðÕ:aÞµ+0šTƒY¤{7 ÒS¯ˆÚ¥Âï{Id’ø`ÃY¹/‚øöÞ6¬Ê}q-P"Øû¢ŠS_¹!ñaID»m‚SPXåÛg_¬òÁë~”È2–E>Ø}I£Ê‡ç"AQ*_¹RùÊ@—ʇîê(øÐ(ò¡ä6èŸq/‘¯þF4g °È‡»wUð+÷Ó":l"ß~Pùp--¯$ò¡?ÚL=lÃøŠ|ø‘ù‘ Ùî2E¾ýz[äÃÃ}*÷…QZœJäÃýÔÚE"ziÙ:#±B"ŒÒú_"ß¾]ùöطʇ’ùQùöc•ýiEå«íRæCÿŒ¡”ùPÒÅm”ùÂ3_LfV2u2\[k4É|ûM´Ì—“‰U¾=r¬òÕ›Ð-T¶uד:_ÒùöÜh¯<\ }芥5£ÚBßž«-ô¡e¡´„¾Ò; }¸5ZúÊx”ЇkiB_y¸!ô•¾Hè+7\B_yLRúÐß¡:TúʽÛkv¶Àß+}å’ÒWl’ÒW’”¾2ˆmðÉR¾7Ú¢‘ÔW^©}Å©}ûjµ#@è.µ¯X5mÃnÙ6ì’¥S‡Ër«Ô¾í­n¹WWBîÛ^æ–ûð›GBmÞB’܇Vµ7ÒûÊØ’àw »@EÀϵlÃ#q ~û«nÁ%Òr¥ø•k…âWÿ¦â‡ç G‰e²Çk¤Ç½Û¥\†Þt¡Û”Ç}ÞQI~Ûß’®%inÙ†wÞW‰mÈq!ɯ¼’üp—-ñµþ¹7’üöªÈ’zc)Ñ68«Œ%¿òô$ù•1)ͯŒÉ~µ7Öuù+É~åê’ýPÒÅ]”ÌP"‰4d?üÝ*Ö1)Ù¯ÜÉ~¨sUŒÞX,¤n†»³„ŽÎ0%‘JöÛwвßgþ¾U¿m‚U¿ýâSõÛ¢ê‡ÿnâ;¾ÏÉ¢ßGýpÝ®:î¿ßg {Íkáo¿þPbU®%V£ð·‡¬…¿=´¨üí›pÚ‚nB•ð‡ã"Kê~Xј©ûí¡gÝo¿PÖýö•$û•Û-Ùo*Ë~µ„²z#Ē쇒D¾ã·r<ź_¹4e¿Ò_É~åÉJöÛá¢-û•ÎHöÛCÚ²îH²Û„ù9"ÿ‡ñÐL}q¤sût–X]”ûà-¸ªOg„2Zª!¹o:‡Î–ûžô×”Ü7î¤IÉ}Xܨ‰eÓoß–ûŽä3É}X\‹ñ$÷M»&Zí›Nf%µEg㎠վR"µ¯üFj_FKµ¾ub<оÔW[–ÚWêHíÛQK¬öÕ:RûJ;¶Áî—ÛõXj_m÷ú!ƒÕ¾ZBµ%‚h©}(¹…^ÛýêÞ6¸ŲÒC«}åWTûʵBî+vß?Ùpo|%ªeõWTËjê}åÚüʵ%ø•;øltu ~{°Ið«U(øÕ~¥{üjg¶ _Á¯¶B±lwØ‚_-¡àWK(øí«[ðѯsççWÌ>%Ï×* ~õo ~ûöYðÛvZð+uÎmƒ].©™í{aů–Pñ+-Kñ+vžÛÿê'$úÕ’uÛ¥èWkP÷+íJ÷ËAaÙ¯Ü>É~¥É~{ŒZ÷« S÷«íP÷+f¶m‚ÛY_³C÷«¿ îWŒ”îWK¨û•Vú¶@íômEݬôWÂ_±[Â_mùº¿¯•¿2LúýÃožës)åRþj*µ•¿råa ü(Ç6À?¢jVªP4«­P÷+U(ûÕ*Ú0ãÙÿD² ´•ìWDÙ%½ºx~J(û}JÒ€^¡ïSBͬ^ý¾l“–Ï’ýöw–²_ý{ÛàÛp$šQ3+W’ӈwü`•t¿Òé~õZÛÿŠšY½5³RGº_-9ǧ7ÒýʕֶÁu¶ èû–<¶J½‘îW¯MÝo‹õ“ k›`~;rE¤KIöÛÍ„êW®#Õ¯62NÛäF~²àÞ¸ëv‰Æ¨d¿ú«û²MWE¾ZçùÉ„g›Ð?²_¹VÈ~å)H÷«­ÌÃV¹•ùü0+<Û·³–KTp_?<(é~YŲ߾¶e¿Ý_Ë~µŽ-P#ã¬W±ê÷)y¾YõÛÝ·ê·×ÕVýjg~-²êW:'Ù¯–´ö{–ýjÛ £Ïmƒ3Ÿß¨sÝ?X%Ù¯¶{_¶Ê¡ÛÕiÛ†ã#üÕ:-—t®ÓÏïà³ðWëÌã[cÛpTìûÔYë«$üÕ:ÏüN þÊÝéÛ×Ù6ô¿&ü? w£þW’#f´ÝDÀ ÖfŒc;:@O|Žz¦/u Iün·Uõkð˜ýº{Â+O\Füƒ·ÚQô…ËØÇÙ3œûå„Ùå(7гg8ÊWͯ8Îÿ¶o—ño;ÿ¶ñ%>æ§þ§[I:{¦›K:{Ú½"}=Sü7ý•*ã£ô§«g*ýéê™ò{ºz¦ä®ž)D§«gŠÕéê¹Kìêio€ôôL~{zæÃûmõ:==KI¸z¦¶ž®žHëe” »Dž’ÝÉÒ×óz#_O|¤?ìWKäìYJdCÏ‚vöì>"”Þž¥Ž¼={ûz{–ßÈÛ³üÆ6ìÛ°Kä)Ù}$ÄΞÙp:{ö<ïcgÏìL:{fÃÛÙs;eÊY²´,gÉÒòõ|kÈÙ³;R|:{–+mÔ›sÛðuöìyÉΞ»a;{ö<ßcgÏnÿô÷ì>´›þž¥ùK–k­ûc¤ý=w÷äñ¹bÏÝ™¶Mhô«uä1¹ïŸ]>˯äò¹ï–]>K;6Á¤ÇgéÞ½¾—‘ÇçnŸل>ó…J‡ÏíeÏR"‡ÉíVœŸG"œ<>q˜D-Ëå³”Èås;#Óå³Ôxä¾\OöÕØã3}ÓÓãÓ‘tø<ó ¢>Ï<4d‡ÏRGÞ’»9Kâ½ûú{žN’à—§äð‰À7â<[04_¥Ã§cѤ¿çé“«v÷Ì®û.çîJoÏÒ¬ûŸÇ•ì퉌ÚJ¹Jî†åì¹ äë¹C_Ïììµ{ÿ|]=íkŸ®ž¥ ¹IîûoWÏRG®žé¡Ÿ®žåWî¿R¥«ç$wÃöôLéè™KŒtôܣЎž¥Ž-pŽ–tô̱j?Ï<Ì~ž¥/òó,—²ûR¶ ëØÏsVûyæ™ùyæm°›ç¾´Ý<ó˜Gúyæ1„ôóÜ&ØÏswÏ~ži·Ý<÷˜·›çéãøéæ¹ëØÍÿW%¾ú¸éæ¹´ý<÷±ŸgžüH?Ï=>íçyúd}:zâ¦ðNn’ûÛÑ3oE:zftôÌ[šŽži¹=Ón9zæœ’ŽžiS:zBrR‰=Ó¦tôÌ»—Žž¹ÜNGÏ]bGÏR"Oϼ7é鉸 ñäé *¾Ñ,´£'ˆÕã}ш®sýpf'ý<ó´Púy–¾l n©f²Gp¿žžy)==qNOOÄ`V‰<=KðôÌ‘žž»öô,%òô̳Téé¹í´§§'÷tô<Ý›þ“öóÄlÜñ¿eÄ–ˆóõçä¾ý93Û¬ü9‘LIž™òçD†·¯?'>ÝB?ùsbj¨ùÞ’i5ÃþœF9ý93sús:ºnºs.;ê¤;'ÂSKq“;ç:’þ„5Üaºs®+¾Èr9giºsÞé¢jwÎõdP¹s®•Φ2àî¦ûsfPáôç|ë\UÙ‹k]•í"tîUÙ.JäêHÎ ¥›þœ7ý93¤dús–ùsfàÜôç¼ï#(_Î}ÃíËY~%0n°«&Ñ—3'‘ôåÜ}±/çí„té˹ü‘K_ΜXÒ—sßNûrî›e_ÎÛÉéË™©ÃÓ—ó-±ç¦|9×gÆ §._ÎÛG÷Ó—‡¶+ÚEvõ:öå\> ž¾œkf´Y°ì`kWÎ÷Gr–µ+§#ϧ'ç&ìÉY®M Ž<)g ´JGÎüÆ¥#ç;cÈuÌŽœÛl;ræk`?Îý”ìǹçûqé¾™“mºoæ î›»'ößD¾RùfÊù1—äé¿™ïMúo–:òßÌ9Eþ›H^[Á.ÖS:rhÎî(‹éÀYJäÀYÚ‘'¢5V²‹s:óëÀ‰çY•¼˜Ïåk¸k„Xþý©ÑR/d¹k¸kթᮨ´¶Ã]ÿü«¿æúçîdI (ýizWúĦž}Ä^ûn*KJS*ÛM¹àÓÔ}ü1;KjS,+M© 6u½üûûüÜ8—”¦T¶›rÁ§©?zߦ>Ï¥<¨ÿøàÛ㎣vŸàÛ"Áž˜$ÿ,~0»´? ÔÍ ýO*`Öý³ðÝ?ÄáþÅ@{Îó’ø7øzBTùÄêVK%¾v´T£k»¥]Ç-}"u³¥]-}bk«¥RG-}ãt«¥];*±µÝNÖp35F·Z)‘µ£™WÛíì:nè£[ïg‰«–>±·=.wµô/ÅÞ+4§ÿÎCoÿ…ÙýWÓésùßþdb®•þñWá_ ½iå-úo6ôö¿ÿ"ôö¿ÿ‡Ü~9[Áµñ¯ÿò‹2Üî×?¸=ð¥}Ø^¯a|ï 1šð YŽÁ)½í „›CÀ¶ésYãôÃ9O®pžI0¤äZå¹(o<Î6žEyãi^«<·²¨9¥ÏÀD8hD;ó8bùZ! ™¦%,¹Œžq¤è·Þ—$èÇp߂ᘻGÐß’ù¶Î}«‰Ìmïr Y{¸nžHˆ á—·Z&Rô!D8lÓ¥W,"‘ýíÖÅi¼ _32*ýÖþN& If_ {xžûË¿y¶w9—ýý3Ö×p:”yÒ„ÕÀmž4!Ò¿5–ÌXC"ëK®XCîˆßóŒk¼-[Ÿçݱõ֦ءÀ^nfÎÖ¿0CJÎ6¿ùpÖÊ÷‹Äø…9Fg“ XÑò¶b+ ‚FWoîØ D˜å©?ŒßŒ‡Çkõƒñ›g÷Èé´iظö–0€ó{-òáìp’z?Këä™ö÷ „Ù][?ZAFQL†oî9Fú{xôX: À¡(nÌ·Å0éÑ‚zö'vÒw]ÃèåÅø@v'¥š/‘…EÝç¦Þ~ ›ÓMÎÑ€zx¿`Ž®ÔK5žõzòïÉøÍGÞ§q1~3ðŽ7_܈)ɳ·sÈ€ [>-ÀK.#çÁøÇosdÈ9éôµ H•0€ó°ßœ8žýÖÉiΈšAÓ›êŒHäá¸àó}gdTsƼÀy>Y²Àùñ9¼‰t°éѹ»‰é""¶:Ñï¼Â€é„›&ó:ú}z(È“.CÚ¼8#Ï# :ã7dÕÌ`üf`«~4ÑÈð‰Êw‚Qêæ·ëZØIA¿¹ùrn„‰´ï×ô˜Þ žë` g$öâµ×ÉÎH`w©„1¨ï|º+Lˆg 1d‹ïŽž÷Ÿ»·ã8>MX×äðÕ¼#PO›K¼ô?Ôèƒm´q>2mÎB ›¹OFpö2xK>¦‘%!œ§ƒñ½{…EÓ;I`¢Âó>`Às‚¼¥k]#fƒÃßÂy¿í ÿp»7c8OŸPž·Lè~üÏqzŠÓ+a®Ñ'Dá3KwnÎðæÄÝ=üQÃˇ1‚Àļv¼|¸Ò¡]ÒùÈh"|þÏ5â)!ÂmzC8ß<ß¾5ngô›O„ø}¿=n@dµ˜š¥¯#Lè ÂG%aÂBZˆÁ’ÆÍ™/lw ôÕ±¸Þþñm¿ c–;=ï]‡l8Nå:Óû#¯uBNÎ[€Œ.´¨_ø*ãA­C{k¾Êñ üI{KO ä×& ô‰/Âu"k/}èWãâ£râÇwq79Í9Ò…DЋáPÕ9Ø|Öù:eBw:¾wj‰)ë”`p½Ÿe|š­a.|”O>Jý¢Åéê2H®Ö@_[Ùd–úÕ`$ç÷õ•¸%’`gÉÅ8ÈØ½ž,Y¯”Õõ«Å6^<=ކΣäÔÔ}õ°®Ó¼RwóáÓÚ>É'‡ðÒ/°îä,¬!Ò;#9#¦JÆ6÷suYoÕ âySÛçåH †Þ\úÕÝl“Û ¢/Ž.d§MÃ隯6r°!¶]ý›Æ¥P~~ÞÙ «NÇwºòä 7Ó½sòI5¾q1”3"ëW²aèü5nFr~¼ ½ :ŒòÆó…dÐ1w/?dƒ~x)nÀ_ï—¹Nß× ’fs¦»f_þ¦>jK{tæÉ_Á̓¦«)xêóz?.\û8Ëì5ïXÍ!H3ç¨k>\Í-å¿z1;ˆÁ¥íŠéľ–Æë<úU‹§‡¾Íço%[ÈuɆÓÁ¯ÞOñôƒÑý{+E ‚sÑò òJæúºîðpt—Üò˜Þ¼¿VØ3·cs£dJøËq¸ Sçò“þV†^7ýåÝ0ýa!¡MÑ2dJ¤ýa!¡yÑßÊd ¦¿•«Óߊ»,øk”¼þžì×ÀZóýÞIäLÃfÛ½¿od¿vï¯8á/‚VÑ:]ÃÞ×Ó7–ÃåiÕIøk‘ZYwÑ5ìNšüíè7†¿íYÕ €È7Ç^Ù¡n—('(“ ½%”uæÁÁò@H|Úid€/²VzÀHþc$¶„.`É“%lΈøbϲÀ½—+ŒÝ<ÝO` ­1 €å±˜ÿ2g“ø¯l²$ÿe†ñ_lï‰`É%+–ø/F‰x¥ÊÜ# ÿ…ŸŽÿ»øÛ\,hJdhàñ/º2TG4+þõXÎ íV·I];½8ªqEü‹{®•>ñ¯¶3Â„Ë šÿ{%þå¶¡ð/6‰›(mp'ü: r“‰|ÆJBýµ3IS&@”S™ð~îu‡èô„ÇÉß“þ"£š!ýÅ¥ÌmçÃýÓG¬' bˆþ½Àß•û „¿·/þÔ þÊ6§à/ú¢Þ þž¡õÙ¯íÝÄKGKX#ò½íÉ`"_ºÎÈ7ºg\#B’,_“]…¸T›1u'‡2ò½Kb/Y„|ª hæ-ÕD|ãñ>¢‰o Ý­ DLvU$ðÛ;H>ø˜ |ïòIø™À÷¸wf¾-Ì&óy6™o$ã›ùÞòÏ}-‚¡o¦Š%ꮌªöõXìK5 ê{'#=8cß•;¾yz_'±oÝ)ʆv›[„}/¿x°‰ûÀ¶HÄ}ש3NƾHf¯*Ä>œ³’†"ìƒï¸†I`ß»Zô›Ø7±€Ö/ˆ}а% ûp£"±/&çà÷"Îïê›·÷ÒL}8¦ñ)ê{— oÞ©îŠúÞÅ¢5XQ:xn½¯cºÖ‚5¨o‹AW&1†5€E}pb·I껚•[A¾7Ò‚>4,ðô¡+­ê}ogn¯Ë}×Ñ }Øhèù6¡v@äMHÏAnžA‘À4±`*úÞ%‘ÁPÐïƒó#ø½‹f¿t‚¾‰/µðM6 ã7ô]§ã¡ú®æ#"†>Ü/£" ïšÎ‹g軚ÜSúâ©„Ät “‚¾wÙäiMЇ}«€Á|;û¡/–:™€m+á OL£BÐwuåþ0óŹ'˜> ÇGòÃFKS Y0œoÕÌwµMoä%œc˜. ^ºšNrù.=mñžÀQ¿Ž#‰ÚxÜýËcO¼÷.'½õ"ÞÃu´¼w])÷Š÷bÅ$,#ï]Í'œÌ{/hYõïaìYº#,a-féŽÀ‡–õ#òÞ~wÍ{{è™÷ðŠI>ïÁ(-…Å{¸Á¬„·H;ûâ=<ýF¼÷.‘½ï]pûƒÉ„¹éŽ´t5ÇJ0ïÁpé æ½óJ™¼÷®fm•xÃfTÁ/ú³ ï•+ï½ëVKXâ= ¢ûÃ{¸ŽXH¼‡½B-,Å{µY0zŠyä%LHZ? øpo´Tða¿PÝ#ï]ȯfÈ{œn ïa|ë{š°¼`ÞƒIºu¾kÚÃÀ‡ù@cOÀ‡7AômÀ-”s# iiÏÝ>Lµ"_ßž4 |(¹­ï´Z·sȆ¥µ¦y¡$añ:ü‘ûÞfœ]ÛÀ·_LN%kÌø®©üÕæ½roÄ{°ÉÔEàæÀX áu1‡ÏçB> …65¦Mè†.ß‹Dî°ˆ¯<ž¸TM^„ûƒ|²‡êȆ®õ§‰8f#ñá˪·EÄ#nQW»ëÇÑjNƒDć[óQû¢Žh_"><Í%$ñáÚÚ«ñ•a,äÃ×î—¬ñI dþGá·7æ½Õ+潫½¯È‡Oü!°ç]3Ý@…z—Æõ¼úHÔÃçPuäâ™Ùõ2q–D>P®’WIå‹-€ªò½Ó@n¼ìí“h†½ótLqÃÞñx¿Ï´‡ƒZFøÎË™M|m8ÈF¾Üòujø¨|Í2 x_ Ai©Ýé&$ÞÇH Þ>ñfÞëO®*Ì{£¥—¨€o zæ½5óˆ©òÞh”¼‡=~ˆ÷¦cQ˜÷ÞÛᕜyo¦»©oCMßÌbvÄ”HöødgÊ|-÷B,ó])fYæ;ÓCŽ2ßy§ hÈ|ýø§²ÛyrRåëÎmbÞƒŽ5>ž :Ÿ[ª|ÉûVùà‹¢‰|¹ña‘²©(Œ¼iKz4¾ÝJH|év²%¾ž² ä1$Ói’”pM_–ø†à§Ä÷8bHJ|£¥Ìf‰o¤ë¦$>Lè_‰ï°‹J|#µ.Ñ^ésÐK|-{l‰oÚå?%¾wî±b&‰o%ŸZâk¹Yb‰oùóšNoH­“ O3ÊIëùv[âK/¢”øÚðÖ Z¦yÐ 6nteYp[2íáBØC3iø¶W{ |OJ~ø¦§Fñ^q±ï¡×ׇ÷îÇßió^œÕßݵ¤kZß[)s‰÷ƒ'\m+~ôQm¦{óÚù:xF9•øðä´Ú³À‡øŸººl¸·,(òt®Ê-ðå‹ßpt¯ôð|çJ¡¥€¯Jl>Œµþ¾gØ "¾wœkµ,à‹ÁàÃP˜º¯¶#/§RàKsZÑâ“ßLZ²‡ç¾ø°a!¼#ðŰ”×¥>ìGèW²àpÛTøà )¼#/a@Z^”‡‘ôUøžøðÜPaÂÖ])ðaΨIà{M’Ož¾n/4ßý8ª@*|}%&Zá[æ\+|ïgBÃÈ |+>À·ýáSáCÔ(°À7ýòJàƒ3¼”9™°R/µÀ7zR£õ1§]Lî-ú•¾-.YáƒKIõï ©ëú_•­ð¥$e‰oXn²Âw¥;,¾ž¢ =TsÌX᛹a‘ Ÿü¨RàÆøž| ,ðÍœZ¬ð!Š.n…ïLõÎòØ„%…ïr ÞTøÞ…¸Üµ©ðÍ|á¬ðÎÔ·>ûþ¤Â‡ ¢F)|Óé´Ó»óhÉ„Rø°‰®:¤ð]¹¥b…ïЮ&ìö>ÜwŸ?*|ý§Ó}Ïý<é{ºïl‰uòïL >ý;ßA¨`vB?øû¬Ïé¾…SO÷5¬¥ò.=<—ý¬äá¹ÃÙÉÃý3éÑÃóÊu½<öžø‡S7>§'^ ºÒbäkÃè­ Îé;&þÃû'9í` gÌ·Â+™p=¿WúkñAþ¨}ñúmÏx.æ8‘À„ìfçeob-NE;¯µè¯a¾®þB—Dø0òÌñ(úÃQ8ø;Ây¦ Kúkx×4BINºýwÓßÎôï†@'c8/Å‚üÅ“”·±àogÖüÅ…Œ2‘Ïêé¾VáNå<~þ„¿¸5‚?<ÉQÕ¾è 6Kþvò䀿Ó‹~Ax‚½Kƒ8—ëþp Ëþ¦OûÁç[ôwÛ«òdgÄ'r #eeÂbáßÛŽÿpb@ÿbjqËSo¥~büé2ÿEä¾êâ›i¾4ùïÀÄ,#ÿż*5ü·3ŠÿNÍz¼ï}¹ÓyTügX>ü·Yšÿp-InÁ1ùêïÅXΈë÷á?ØéÞ< …|;ºùoç)ÿE;º6ù¯Ú@þ«ÃBü—‰Åo»(™ÿ`‚¾.ä¿¿¦µOøÕŠÑ6F å0¦ôE˜É.Å1"Džâ¿8HV¿èïùÀqTX÷S€˜Õ4® €qòÞ'ïþ[Éì+Œí#øEÔ*éi'£9ßéù&ÜÉЀñ.Œ¢7>8Îù±¹0à îlƒq|«}<<ó®“ÿâ`£ä=ò&æiÚc°¯Ì›iþÃôcWMòßÎçnþƒýZÿ‹ÿvÚ^óß~ïÌx7e‚øÓ‚”ñßNLþÛù!vσ'ÖÏGð‹ÃHªCþÛï®ùïyËÅqÚLà6•²õJçRâ,ÉaNü‡ybTþ‹÷PEXî:0†Ö*ŠßN„-,ï²wܧ;ì<Ü€;+¼wOD(Î}˜p1ò 5þÑ­,öwù#ÿífÄ;Kjð_äâ?ôEz¹ø¯¼>â?Üqá ù/>¡_þÛ¹æÍxöÞ\ÊÙšgRÉqÿLŸ²Ø;ø ù/– Ì€;!/p¿NÀòBM›P€e‹q÷ÖGðÃ1ˇ'lí‘ÿvú]ñ_˜äsz„'¬õµ' þÛ_kóßN€LþÃKi’£Þ·Wæ?´b_RYÐ6{’ÿðBÙ»”zߎÄfþ+Wü·gY _FBÚÐõüU î?½¯+çÊ£… zHñÄ{sú0qJ|Ûu)ñÁoU¿úƒ(.em“ÞœgÆt—iok|ð]sС+çmOÇpqtìŒárä1 |}&4IàëfY"?.Ѐìiª.ÍÞã–øæ“›ª’ø°@”› /òu©N„pÁWísН8?IâƒÚ$™Å1\Öúb¸ §1²Æ‡Á£Õ¸4¾…ŒŸNl¢?ß.#W)ù°–Z§N("ëãÕ‰CñòÞîyP[ã»q&ýÂe¤˜C¸ ®«°O&”€2Ž€Ò~ á24Md—óN:S—•ŽuŽàÒ¶:' vÐGpÉ“¸ árï³~ÔøÊ!™ âÒ%ÁA\žžþš2!OÏf—æÍdk|‘HH$EÌÛ{TùJ0 ‰|ûh½E>¸õŸ[ä‹ÜŽÈFÊCÄe?h|X š×øcÎ .-©8ˆ ¼ª…MâÒòpŸƒ¸tNQ —•‹sÇpÉÃí¢¼8Žßk —{ûŠF — Ï Ê‹@ ‚_R^œ¨¶ïhP^ÄM1*ˆË•çCEyOƼåÅnžö1† öËEc €räAHB^D°oh@^ÄH0F—½{tÙ„DäÄÅL„GÉ}dPA\pÌçsïÁÁciqAyñ ì¯)0-‹àdC&‘åŘ•ò"ÞÁ¨”‡ÔËA¾‹ëJyqNÁ*vøÇqyïèYò „âmÕ§3Ž_ÆÈ%C‘òâî8‹lÀ¶C•ùj $bÞ{¼º¹\ÞœT —;¹™˜7°´9ëI¾ BœwT1YÈeå™Kr^<}]ÉeÇŒq$—žŽŽä²R}d¤ÕQ” ÿ!Î𜹶cgÄíµðœ¡>Ì^Áyñ¨*æEüˆ§b^tÆGé¥u{qå  #ÄåEWãý5 Ê‚éèµÇ%íÎ8.—ãí* B\ Ïó"LJžÚc —™Ñ`ˆyûAe—•žŽãÒ’SÇeøsÆqÙÑIÇe>©(åÅýÓÚÛq\® rs† ù>+ŽË»ÜЪŸ”Ÿ¬ŒìÂ8.©Åq™)e8ŽËJh² '•:ŽËLÜiŠ‚’·Æa\r g—m¤Ã¸¼/C°0ÍôáO†qyF:Vê \Žß ãr%_ò¢Ukƒ ã‚èòÊxu—+YÇQ\.‡ƒ¸Ü>!œA\.GnÈ .Р„gaÁ(®S|§½*þäÉ“vŠà²ØS—e×ö àr¯< €ï€=CÕýe4^¼9RÌÁ¯ó7‚ –j–ü‡a[á‹{éˆ.4át¢%^™'3€Ë~°àòöÒ$©.·¢DxñX Ä‹1_:cT_Š}rÉf’Ç{O€WoD" a¾ç*‘—…” ß‚×ò¾Aë+àÅWÎržÂ·ì{ãð-û}sø–•>%Î-ù.£qOd.zïλx©îý×B»3^ÿ·w¸ÙëÿóSc×ß5~õ›¿„›ü/æ²Õü QX«Wenw×jJ‡ÌœIÕŽÿªí¨¬´ã’Ú–Üï4®vüWmGe¥—”vþc¢\#¨ã˜@Á÷‹ÿô—èÁ÷Èø¼÷‘«gϸÁ.ý¡Â•ƒQþ̰®ß12‘^f=#ûiD\áÖêÿêßÒíç*¿wImc×r;µ–Û:OfDÝm¹¤¶µk¹­Z+ÛgxÔ—¶Tòi+ke[¥V¶þõ¹äÓVÖʶJ­l ûó©m©äÓVÖʶJ­¿:¾à£ßßßD–´oÜê«F†F€õ¸ú¾~¨èHÓã¹úêý¹úÛûF®þ©ÚD®v½_ýä‘«ÿl&üÛOóگ澿ýø¦ü4þü¶üÜÆŸ<5|µk˜j¹¸0~ʼ€(Ñð¸þí·ÿéê]|ÿÛÿôŸþó;…Ä~B)}o;–Ÿïtðoÿcîÿüÿü'œQ>ŸÜÐÿõ^r¼_Ÿyò¡¿ýgt±30¬pÀz]Ýû_Þºï×íXÿö?ÿ§¿º1þíÝùßò?ÿï4ý®0æ¿ýÍÿÊ÷OôŽ(Rï*·5xûô_ô~×g è9Úö(ÿRhì{e8ïÖê?÷ÿ‡½Q©ô¾²ðÿÉý{þë§€Þ(Üí( ÷Ó‡z£ð§€ÞoÙÍý—_”e@ïóÏzã|&Þñ‰nãÖõ.I~ÃÚé‰%GœU}—5 ðŒ’ ÒÛºCØï3€§&ßµò¾_Ì~á#ÿ~ѽsÄ¢3ñ½k+8ß±}‰EëˆÎÓcö®CÄå[oïâìŤö]e£îä×ý[¤3Žó ™U^°{¼Ú½"cÚõ¶Þfl ÂYi¼‹0Æ´À‹¹ÐàIyF¬÷ðiˆÝ™ÑŽßF®3Þú·ûûïZªè»kàäÕÛȃÓÕ°[ãXœ‡×x ¼Ëé\Kä…D‘ïJóŒ »-JÂ;÷ŒH‰Ñ»×‚v¡™©ƒ±+¾Ül&¨Û²££™SzÁ Nü `p{#dó‹Û§ ÎUïýA‰‡ß5gdcˈKv³ËNx㪌¯IÔ)Û"W)§Îc‹||.>I=˜l: §þ9ZR‹g§¸?N6«lU#(ÎH€JÿO- ­cIž¥ôº'£\YDÂ2–QdÉLÉ”/¼t±.ž•FÄ Íøq £Ø0é]^^4Ä©hŸ1а1ɤUH_<âR©Ï]ñi(ï ŽÈé–JÚàñ²Ú›çúÝÓ«Tü#Ž;ÆmÏcå¿Ç·'»ÇB[}4qäü¬ó>ÓçS»Œ#¨í昜–αåïU†¢ý=¦ò[I4.¾añd´­v‡i¡£0¢¾2H`¼nŽZúA ñ½øð¸×ãgòvñÚqDk|~5b[+Zæ–î BŠ[ÁÉÇÛb"¿­"žc×ËÈ}3¨ª1‘gÃóxÐ*>=Ä9Œ‰<ÖͰÍelGã‡uâŽÂ=ùÖСcr%Æ<ŽPÜ.|«=óYácÍyÜÑ„ð±ŽyÛ›“%Ï>ìéqrï¦3]™†CnÎúÎ zñ¥W„–ãÎjuxAž½e''m£”‡ \Ï]»¾ô2”ŸB|¬¿ó8¾Ö1猃'Ûá,.å[}> 8ŒÅDƒÖƉ\ ¢eˆ¹‚²¶P tÃb`4¨>žÈU'RIGÿB m؃æDþP[løTÇDn;ÛÁ(aµ…ªmU‹Ñ(;c×Ç8&òG±kZä1~ÊdÕÊ8&ro?6¤2¾®ò´R¯Y^­v2ðúþ5äNäD®±ÒÀÔñgh->ß, ±§áC}~Ì<f?¼v2ÿ~T ©Œc"·ŽÙÊ8&òìL£Ð” ¹Œ¯:;4ä,[uzmÈeÌ™ÜϹŸ^ûŒOõQg¸Ö"¡ô~ó[£[híÎsåL/hC:ã>Ë”ÒÎxÔw­!Pòlå•m=RJ‡UƒÍPÛ*¬1Mäz’ßu*àѨ&àC}´:&½­”ãí¯ÆùN&IJîy 2VSe‰œ ñ2ÂÅå9 ÒÃÏÂLˆ0<=IfBÄØ!C™ ÓLˆýõ3#!òð®Ø47b3ýd!!¾ =F¿™0‰ÏÊ„HJÕâkd&D€ñ#^|A!”çKCS!ÎÜö0ÚTÊåm0BÁnñÈM…8]Ң˦B`Ý+/Sá 7Ö!Þ8²NÆ ”¸1¦BØ+\L… š%¢Bœ-¾cûËTé…â9™ q(tƽ"Z~©¡0"Ùb(™ ‘/÷Šo®™ðÆJ,&3C!BO…B|®Q¡^&,1â\ÞcÄPˆÃ’×U¡°” ñu¹CC2â»õÄbÌPÈp²è¡¡%OÌ ¦BG¼b•l*ÄŽÃX• Q¢:¢Âè)‹Pˆ \ô5¢ë'CA!>šƒJ¤ §_'u‚BxÆ<\ì GµB!\„.Ò“ K±Bßçkf(ÜIÅ„8 Äáo&D•q&„Íä7WLoƒ›=ât!o»™Þ‚7}jÄ„8ÖqO`0!îÅT2!vq:—pbÂHȬ–É„q–•"›˜Î[QGLÈÄMä;2!†ÜA UPˆ§õˆ ™p‹Í áQ5xqA¡GÞ†BìÑ*1!néP»dBee3Á„¨ÒÕ ™ªóVˆ 1¶'•C1!Ç#âÌS£†˜0M+µ6™'°tsÄ„hg:™z0á~Ì„<Ê–É„p(™\¥‹ hQ¤j1a)Á\ß±SQ[È„ð•™bˆEKL#â:­U$,6 q ip¨ ™—©"!ÏlÒQ•Hß·¡6DBœ!^ͱh°’€“ŒÏ ÆÑ_¹câ$Wó‘6aNs ‘ BŒÐåˆøA„Ø®<›£Ôcms¾ BÔ™ŽúDX["DÁé-A„hÆ~B„ì×!¶1›ôUuì˜<1xå×8È@Èr D‰¿p°ÌRÂAfݲï2ÖV8‚wÉc‚<ødÌ á`™¤ˆƒz{p3D8ˆGyÓE8ø`Ã3­p°É‰Žˆf¸ÞF†=®Â…û«% „‹\MŸu$óâ°ßêä9R ~tvþˆˆvOÒ‡(³%¿ª¦@´Ã§b ÿ¼›\H ¤7.áŒXZ¢{‘ðH]ƒ åâ€ÀÚ!ٳȄ@L„³³!,?#†@F'QqíÎÑNÈa„@”Üü0¼–Ù ˆfh€1‰›D@ >8àžrE€qN›ô$dü–™€S‚ pFL€èÌC–“qè“» Ž # FÀò¸…€µ„XÆ£02-@ÆûÞÊàŠ9¼(ƒmi”Ê æš(ŽÁ->ãVqÈ3`"•A¤¥‹·ÏˆpM3žóVßó(³écÒÈ|^›Â@üB$ie§C‚2Þ&Ë/cà}#fbÅ@$Råì+ Dô ÂÀrS Ÿ#H”Á'~% ÄäyŽŠw¤ÏŠK ãðMìÍñaaÃÂÀ'|S«8ˆx(ÔM›P#˜Lðš002VUmñy b½H°0Æl«ÌäÀ÷®sy`Ä]qsÌÌì ‹AåBsàûçGÆ`"¦šOäŒþ˜ñ_e¾äÀ®—490±!9pöß}Â@ä‘úb`.¹“P1Pb«51Êîñá@¤Ü¥ÄbÌ Æ@8G ñŒw–1³©aà¦5cà^‘læù` »q­‘ˆLxFnb–9ýH†äÀm•9pœ¾¸9Ña¸ˆI4q÷BÍØÝÁ˜‹pCà&C bOì>lôO‡áF@ÄiXGÜ7Ï8–—\‰€ÓkO#`D3"ß™‡&»d@„TËb@ëdÀB|bÀôfÀÒÄ:bÀ=üÌ€8"!­N ±Hjb@:QËbÀ½¡`Ü÷Ë ˆ=-òR2àfI1 ÖWê‚egÀ ˆÔìÒüÌ€Ùˆ!°û4µó´É _uE(b}Æ'nÄBZ¢¤pS¬0‚é@#0Îþèh!p¿ ¦@8&g:¬%pdËYHdMHnï,c¤À‘Çöˆb¢Ó"‚ÀÒ !0º0r¬è!ðíïÊ`ر’@´’&Ftùô“qà`VU°Œ6c ²rè„ã°ß¹(Ð^6 È1Ç1àžü {‡DˆT¨×÷6™!pjCàûAæ·?!0by} 0a±R ‚w‹…û!÷n Ä’…ÛdÆÀm•9pß>ƒà¾–Apoê÷-6F0,¶#Œ$éÔî‚ï0ÖTfŒè÷¨0æÇ,A7‰ØgÜûGÁm–A0B汎@pÞÌ0 îOƒIpï:_C¹^IÜÛˆ†Á}› ƒÛ.Áà6Ë0˜_ª„Á¼§ ƒy“#=<ÉN4˜ƒÇ4èí«„Aö„Ag~JÄq³Æ6Ä‚C1s¾I̵DÁ¼Ip÷Ö$˜*I0_ñ$Áœqq“àP4¡A)ب@p÷D˜7Ř/Kb`®Ió>™sªN Ì >10ß§äÀ®É¹àHÜwA 8îXSÌ) A0×Å ‚H0EIÖ ˜ïA‚`>Zq`¾”Éù$æÜ—AY"Ü=6–:â@œl…ÿ(x²ß—û+w|¸=«úwÁ¡!‹¹oWìÃ$÷<(Ô™û•z ¸oáÙÿ&êÃ—Šœ(êƒþÆGjêCÉ3è!*ñ!„+ô!îðšúFþˆ÷.µ?$Ó{ªö‡CÊ«BUh–Úßc·Rkɱ†>ò_YûÃnÔU¡™A/ùˆô¡€S¦¡¡ðZØ`èCó }qtö¨Ú~E ÅЇ’蟡?¢T*èÃù|~& }¨"tô¡ŽÀPЇ>CJ¸L3ô•–}»Ž¡Ñ¢Dз°·ðhèC ½4Å|(à Ì̇’x׌|(à{næÛU„|(à×ÄÈ·/$â+­ˆøö¥M|µ„Ä›´òÕ"ß¾F¾}·Œ|(™rõ$òíç`äÛwÔȇ§÷̪ü¡DŠ˜¯\]ÈW®Eä+]ò¡í ùj3D¾ú+2_­Cæ+Ýô•.‹úö(5õm•ÝÔWZö•:â¾ýŠ˜ûöà÷•îˆûjr_鎸¯Ü q_-!÷Õ’à¾Ú?r_¹”¸¯Ü q_¹§â¾Z‡ÜW¸¯˜%î«%ä¾zur_¹§â¾Ògq_¹â¾bè8®Ú¬¸¯–ûÊ…Ä}µ„àWEð+ø•Îüj Á¯vàWëüJ‰À¯üJàWúCð+ÝøÕf~õG¿ZBòû”ùÕ‹ùa2m0õRD?Ô™ÎqèW~%ô+/„Я\\èWÌúÕ¢_m‡ìWëþêÕIõW¤¿ü> þJ+‚¿òÁ_-!üÕ_þj á¯Ü/Â_1\ðWîºà¯¼3‚¿òî þj ᯔþj á¯\KðW®%ø«u¥Ï‚¿Z‡ðWÛ ø«?"üÕ*„¿Ú á¯Ôü#eÚüÕ:„¿ZBø«%„¿Úá¯^ðWEø«%µ€ð·'Ãß¾”áo_ÊðWKûöþjÒߕƿ=â̵„üWK€{ä÷ó3–k‰K;"ÀZ‡XKH€õW$ÀZò"`¾žFÀÒ;!`m• Xî °üJX®#¬uHµ)°Ö!Ö:¤ÀZ‡Xz( ,w”Xž¯(°6C ,—ÖR`-!–vˆåRÂÀZ…ø)y8“ïb`½1°Ö!î’"8øF çzPðÖÖSbad—û`!‚®–Û)tÚ.B§"¬¥O(YÅ>¡wr¤OèuKˆO§ÐuJˆM§ÐåÍ4s!¢0èô¡À‰ÙªSè…µU8K *¯…²Àô¡0^kÙ½S`ˆºb QB9Ó`ˆO dF!Œx®zTuèE#0ÜV a7¯ †(!e Q2ÃÛÚ`Ëéï).DhM`¸« qk¸íd.,%âBü†ôf.DB•¹°”ˆ QrѹT\¹îb¿Ç\ˆ’ëÃ…ûÁ˜ qy¼P\¸ „…¥]q!ªôY]Bk Áp7#.DwÙ †û Q2D`‰ÕäÜI0܃Â`¸[6îab0¬í k;Ã=p †LµÇ‚am™`ˆÛóð0•À°” ÷ðîÑo0¬%üƒæÂ}“Í…¥ ±°^ˆXXn©°pßvca-!–Û%,¬%ÄÂÒaai‡XX..,,ÏJXXžƒ°°6C,ÜvŠ ËÝ"Öß K÷D…µ„TXKH…åÙ‰ Ë¥D…û…0¢¤ÏêZë ÷«g*Ä+¼žªÖ_‘ KËññX)ˆ ÷<`*Ü3Œ©°– ÷|b*¬-“ kˤÂÒ=Qaí©°þŠTXZ–«‹ k ÂZ…T¸¿2¦Â=g› QÒ>Ç÷×ÊTˆväH*DAsÚà ÂZ…TXš–{**Dã©Çñá™N†TX¨°ÜAQaé¨0¿*†ÂZ…PXn  °<,Ráþ˜ ËЖވ k ©0²˜’ï…e Ë–»%(Ü_=Ca¹Ç‚Âr%2aù‘˜pß!a1[HXKˆ„µ„HXz,$,·XHXl –1*$,·XH¸g.a™`D„µ„DXn¨ˆ°<a±ADXÆ–ˆ°tPDXž¸ˆ°–w— „Å(álÂÝa-!n „Ûráþ|÷M7îc ¬u„ûqká¾ÉÂruaé²€pÑ „y»Ìƒµò`-yyðóçÃIêVÁï}XÎÅä1¬Q€˜vÊÑ#Ä´á“Ó23‹Ä´éH°óN–Š0â1m8²§İt„PbÚ¿Á·Žó†8@ ºÌ[ê1-ÓD8@LËÌ&ó~p [ Ó2YƒÄì>;B úsOиËEˆÁµ¤*B êè¼¢"Äà©«eEˆi™¡%"Ĵ̼á10êüDˆAb¹y*B .t"ÄìGå10ü!¦ gÅu„L©£ø0¸9ŸsqK‰ Ó.§ pxÜ›»z‚î{“áaò[™áarfxüê—j•ýò¹dtØ=ª/hÞš “O!ƒÃà~•üâJ³ Œ+­J~ÑŽœ2Æ·&cÃìK96 îç`Ê ƒ:7KÏÿüĆA_øß]QÄ…†)×Qh˜}‡†‰òŸÐ0¸W,Pd˜}&ÒÄÔSåRŽ ƒa´TÂÈ0/(ü.ZTd´S¼A£•ù ƒÇ4ê±À=Ê30 î¯<2æ5á· }ÅjE…Áu(‘:* ªœb<†…Aa £Âìî;* rã\,QT˜r%E…iΗZâ‡GzÑ·çŒg;B'lŠšëÿVc×»þ®ñ«ßüãøá¯é±˜b«ùW‰×í²¿7KJ¼îŽ¿Ëñ{ó¯ÚŽÊJ;.)íŒÞ›ÿ,-DÁþ9ÿüÞ‘öéb†¯'##ûŸáž›ÿ ÂŽþ¬¬àâÌÊȱßqÑâ¼ëŽþã(˜‘Û"#Šë·%¸~_£»]Ëí|"‹«­ \mÕhànk×r[ŸÈânkGw[%x¶•µ²­YÜmíhàn«D϶²V¶U#‹»­ Üm•hàÙVÖʶþ…˜á ùÞïû/b†Ï?‹îá”ÿ føÕû1fø¶÷þSµ?ˆþ‹ÿ…ÿþg³ßß~šË~5ßýí§7åÇùïç·åç6þzÌp ¶­?1Ãÿz¨ïs‡êþáÃÿzòoøð-Àw‹£ü÷? ð½2À÷'úvùçÏ!¾ûYÿù¯‡øþ÷_„ø>ó_ ~Ý¿ö}e‹ï¿ì{ív°ï·ð§`ßoÙÍý—_”e°ïöçÁ¾#ú»AFÁ¾rÎÃþó˜:ŒÚ8‡4pì‹~DÙz§klpÅöB¤¶ð`ÈíüD r7òlo}$Ìd”kí[DÒØjÄI΋%s; « 5îàHlG†S¤uŽJ@Õ#çÑ»ìéX³;˜ß³ »×ö ‰D>×z"]Þ‰Œ; ="Ùÿ†ìÌÆÓÏó$I"Ctùl±1yvD¿Y¡rß‹3ng­Ô×ÎË£`ÄVɉŒA[ o dÅŠþž·GŸ.YÜœ‡¶úys;°ãè.ûûp;{2,i÷‘0Auì¿‚#±UÔØ±!Žì÷-3±wÇ÷«s­ÙààHØ@3ÁyàH$ïk¼Öä†àè×Ó½]ܱ%+6Ç­4_½!ê{ñH fµ‡‚ã¼ ‰ïG€‚ïÚƒ$ô~f¸!8ÆäBýع!8 =<,ᆠÒ!=,áþɉœ„B)A’±vXgrCÉ–\Ü€þjqCp@2ÛÓonô=nFbCp6RBÌ4”ƒKËÑ·KÃv4îî+Áb$/ñ¥ûcÞÜ4éø=ŒZÚ{éHÂ’ÜOf\ÜÄîS¬!:º”KˆÚÇÍý@˜À7ÿKÎC9®:þ–„Uñâ¿s8÷1š.–4îâ¶óaÍÆýÀ1•ͱOnxÆmŸüÕà~à@p0tNîŽ%^CòTtOI ßÅý@äTgnîŽ[g _üá~àx¦àÅ”ÛHìªÛuÜŒL¬qׯÆý@ Û¡îâv5¶Ó¹¸M¸÷± ¨’Éý@¤Ö iª#ãã_yl{¸]œ´‹Vàxî1†Gq=ÜÕŒþ~ ðãÁð-Z'÷#MmXµ÷qóc¯ê-á~ ®Íñ¶zìâeœü‡"’ôêeÄŠq-ÞdÎqþí¢á|õÂyfÞ’:ÒýbÇ­8ÙÁ‡ûóÔîP¿îŽ¥4°ý>¹¸'‡»q?p<’Ï:B·`ŸHi· âàìí!:t„e‰yüVZÀ~ÏØÄ€¾Y…3{x¼ŸdîâMëìÎÍÁØÕ×±$:â©`&‡Y¡¥tdInñ<ŸßYи#8mÞFºÔ˜Éϛ߃§sCpvÅÑï8 ;ã–.}îêuü#öWL䬎xA7¯´Xps?Ï“™1σÒL :ùY‰Ñ?ð>cäœDÔÈÛˆi •Ä~à<ç“4É1ŸÊÖ©ò0èÐ"g`Lã~ ‰bn·³¸ˆ¡=ù«›û3V2QòpC0§ÉÈ—Ó8¢Ë=QrrCù1&>Ô1#ÛÚb 7ÑòÅ’Î ÁÙ”uœ‘­ºDɘÇç8©9 $JŽyüY¿³•Å Au:÷ñ±çk6)jÔ_akWã&æ©tɘÄaï2Ò%÷£Š¢?fDK®oÕŒ˜S0ëÿ%ï]’6Ç‘.½­Ä´Í¤0ÞA¬£V fm¿õDûŸãîY™YeÕ¦–u *ãõà â¡_pñ³õ…ŒÐÏîz=aãµ &ñCl\ƒxéÅ»éÂÁŒS3‡ ^Ó›n('^Ó±ˆÇѦ:&Ü¿ÙÃÁI&¬3]Š ë€›bÂÉq(ÖñÅ„°9Q $ÜŒ^H¸7Ý= Áü쌈çsl’ÑôNþâ"EáO5JD„8Oy’ÉD„°\ î¯ÞiE„}¿ç†6è"Â~r$T!,`%"Âý:5 D„± Ê ÷çÑ'îxÒHeBBx¥ˆÊ„„­h"!öÜ qçd"!& 97‘pß·†„°¥q¼ wœpc‘HˆñâN:‘°¼Z ñ%•€Hè"!#>¶îÏ.6O$„«?B$ZëQIM®DBx”— ¡&¿v$⋯„„hˆ#šHˆoLƒP&$DÍœ‰„¸Wd;!\Šˆ8I„uÎõ$BxÎs“1Æ%"BKE$B̪ˆðØdN.$Ä€ŠÁ„„­C"!6–‡$DÂý[7GÂG…Ü„„ûÇ3džDÂ8_|AÂ_’á¸Æµ#ypŸ»·äAw9ý’mã:8ˆ%ÏTâ`ÏšÄÁƒ’á ªÑUÂÁ}¾‰•ÄAø|=D=á Ë„ðÄÁ=ÄWÔØ‹bhø¡*qS€PâàGZþ0ì‡3yއ±§+ „sâ¶!Fð]€$ÁG:0À!C@ˆAÞY€‡¯‡B̹óJ"Ä`Œ…Ë3²ˆð b!nD¬eE„àšƒ¨)"„ !™'‰°Ü)‹ktŠ0>ü0""Uq!$Š$BL܃$'"´ÆE„=ÈI„pמDˆíÃËÖE„p¼¯“E„a|ˆ[œDˆ¶8ÈA„¨d%B § ÑßmB´_C 1•6òž€ý% '–ci1aùêBB½“ qˆ£É„µÒâyà.>™žœœbBè)´Br/LˆjØ’ÃÅ"BBLÈ…Ë17‰°4‰°gIaß§$B\õE„µ¼–×r!¦ª¨QDˆõwÿD„ðp<È‘"BÌÞm‰kI.",¿È"Âc£KR!~o b®í¼F@ˆ2¤÷Â~†áÊÏ@ „è y>‰°—®$BÔL’±áægŸ$Â^’K‡B,ȯ$ÂZ¢q¯ÈÏ „Ø©Å.¢€ÐZ¢~ÊJ ¬·A;AÌ‹ð_HýP˜! …cÇû#üžd'Ä'Õw±¾3ùIPˆü¤+†/žØ­ …ò°+CaÞW†Â O4ù¥¡pK+[ ñ* @vÂýNÃRÚ a æû:턽óK;!v»Û ±Sá†"턽IO*ì­VÚ ñ*à7Þ4Ö³STˆ¸"–¨Ë÷ I…¸‰ÂÍ‘Gš-E…½/I*¬ˆ¢ÂÞ%ÖZT¸soØH8ù%¬¤6Y‰¯f¡¥˜ðØRLX3<™nô ±  – …ð¿(Lgëb )&D´7«É„ñÞäUbB¬Üè%¢Œ$bBx óŽ'fÈI!a¹«bWÇ=œ°â% á¬È½j"!©OÙ3j ù8‘°œ­ Ë7½ð,³¡°UH$,wúFÂ3e‰„(ç!‘õÄbÙHˆüå´&Âyþ‡áu‰è‹/ÚDxé~a…5bHeH|´™å˜'¢€ÐSDˆw,‡8‰°^ÞE„X`9Õ“ bDXÞôE„‰¹ !¡Q:‘°Â… k^HØó$‘ŠËŒI$ÄäßW$üf-ŸÅDÂp|%† ­L"aÍ¥DBì[‰DBýáˆ]-Š¢ÀÛȵãâµÃÍBA ¥wÑ6Ž>šA0aÐ\R¦Á‘¤“n寷 /MZì’‹R‹áRúÃ1p–'hšgzÛn»H"1pÛDÈ…e+ ,l- ,D.Ìå¨9p?K2ë£òË«’ñä±Lr`~jì«’s¡küʈBëC}‚`íþ «âÁ|–sÖ ˜kBƒ`õ‚xš~8~j 0“ó-`¦Á´˜枬90W 3 ¦539°¹*A°Ù+A°Þ‚½SoÌ­zƒ f ò- Vm|7º»–]ððÓyÙGVSvÁ1J"Ìájü$‡{ŠVúŠfÀ|€›_q|Ö=ÈDòý†A [Ç÷$Žkƶ¦|不(X)OQ¼·d8$¾`ý‘_˜òÏÕSÖV²Ÿu¼d¢ îåí$ˆ‹v7¾ñ˜zØ ¦È®@B‚ Ým $L¶/„€ è1?yô]‚  …@p‘BÂDŽ ‚¸ Ìò+|áD½E‚Èc[$hwW$ˆ2›H•$èM‘mˆѸ>݈qÕÅ "A\%Gj‘ ®zĆ$A”ÑðˆÑŸÇAÐ:Ä<:!YÐk% BË]µ’í ¾°ÌŸî#ŠÇn£íE,ˆÕ†gô& Bò·¢æ±»“(ž²cxØ 8¾¬†(;¡ $<ýM(8ÞG¼HË£:,ï¡£ò’Ç ²a¢ ªÑB!¦)þïä©BSG & ¢–>…"AHô}O$ˆ«¦I‚(£GS$8°3÷˜Atx;Ý8]åvk .¿‘»a uFˆ4\ãu D÷6y„Þx€ ûÓÆ2o|ćÖôOBdÖ¡R÷”H:ÌÜÏFôE¸Ÿ å õµ-W*÷sÊ$=*îç’ÈChøvötÁú[Õûyè²!%eôæryåq?/@Ê}çŽóD¿ØßϤÿG_„=ü?àãÍ¡;@ê¢ñmžð‰h†ŸÉ7½åÿ!Ï¢ÆÒÝýiî°åÞÞØàþ§°¶ß°Ç\ô39xoár÷ø€pSB÷DQkmAÑ–½1$pÿÀ§òhÿz/×Þ@ó\.:ãc —Þïï¯Ý”—GµŸÓýŽøˆ§éë~ßøˆ±¡ÄL8Oµ¼Ø¾y…6Zs‹ –˜{| ô"tãÆ¼:ƒ=oœ0¯h‰m2ó':C³à¤‹;u¢9ïžO| „ä!;½÷ºæw£÷^V„†ù@Dö§i®yò+…ûÇFS~rÛ½|àR,÷=Î’')p@·øJú„ o_ÊØÚ9ïÑAgÖÁcìéÀ§IovÞ¼+> <8t«7‚NtÕŒ/è!³×<'´Aàÿƒs!®×ðd® ´DSñsžý÷†^IŽt§L}ïaësB‡¥é±qõ®û€—3VïZ'¼÷ÇUÀÛùàò•ô\Ûàò]3ìrí‹äàùL5q0ÄýšÓä÷V8¹zWaé‰å»f2ìcùîÉ„Oö±|w=ïö½w‡œžøŒM/:D>x7Ãùñˆ<áùÞèüa’ýá^“¹™¯ÃuºÏøh·ê¾N.๼<ß; x¾¾­ÒÎ<×¶ç{)q¯É…²çé7¯çXÁ¿e¯çeˆñvöüÁÛùöH?Çͼnøs^\À«ÈŸ­wؘ=>8!ûñ[‰²ÇXª“ëwMG=¯¥»óå^-éû†Í,¼›÷éë`Ø^ÒŸHôûøco—ë^$÷Á¼úî`»?ð5¶•yàÌ7øâ§Oß–ÖÑÁüHV/^ϱ‚ÃM!ʼÌ\nOP¸ïî®Õ{^\Ã[r\Ã[r\Ã[ÂÔ§öÖÁÙϲ༼¢·Ûǯh-âºxE‡«I޽©ùép.+Î|v.â-ñt`~pBö³¼qBö8l{õL¦ÖëÛ7p@öëm =ßE‚”§w/éý2Í^Ò•‘Ybl÷Á5<H•Læ¡jÆÆEüÔñFc£]§Lýø†ËÆkà€ì÷p­p@ö´ådà€ìiOãÀ[zã̱痛Ç^ oéÃ÷Œõ}¬ß¿›ì»0Χçéˆ×|¸ $ÞptMê Äû±ÉwìáY†xÃ=f#㉑ü.<’‘5\Ûjqà÷"•{¬8' 19ðß!QLø=š¹µ>pZx ¡Áo R G‚ N¾$ â æÉØìnD:q`['b^’ËÍ6A°=åáÝ©1 Þ[’¡@Q_ÓAï¹¹p`y)'b©cƽâ@x‚½d1r`…‚ÆÉŇv†ÅXxï…qâüIÀ"s_@)Ÿ¡Ágº²u °þO¸m±Ë"ÁXV‰h"AfC@ïg#ÁyÀ"Ákê+}¢ ÖË,#œ»ü† û.$ >ßS­zˆ‚ó’‘¶HÆB ât6•$G>BÁ BáQÐ:(œXò^GA²Ø”Pp^oÎ,± WLœ1ˆä<² îË|yYÞ 3Xpb ÛˆudÁ¡>$4 ÊpNˆç5S@DÈϳXÿ9œXà^gAtF˜Gœøfû:‰‚ñDAxVjŠ,8票“dÁym ­ ¢ƒTGœßÈk %ŒW·±bAŒ9ýU“'N…›Î‚óZƒðžd€X <,õò âU¼ë"ÂàÄ)êQ4ˆwè³$igMÆœHÄ \û%Ñ úGÚ¤A¸n&û‘­;¢Ah. Â3…_+’mŒIƒjŠ48ás+Š# ¢ƒ\ö“÷í›\')Ž4ˆs¸,$ ¢ƒÚ„ŠÑAîYƒœ€! §Uî>ƒ˜@“œGÄäºT Ypß6y$ âL†Ô‰gœaOÖ" Î'ö÷mWzÇ„Á92æ aÐÔ B¯Z‚AÌf º`ÖÝ*Áà„÷·ì‚Á‰W=A”,¸ã›w²àœògK´î ñüíüö ü”ÒMÉ‚È麳¢ ¦ÀpDæždC’`xÿÎ"Áy+Óc‚ æ ßß ‚Xv®– h3M ¸c;y8bªþ gxÌò‚ûv¼ôíHÄÀlÂG‚àœ›^š ‚3œ Y† ·›³F óˆß&‚‘°(^ ‚64"ÁHˆ_µ¿«&Áûˆ‘dAøvñØN±àŽÓé¹Þˆ£7’0ˆÇ…Ý„Á9åø’,ø)•óH,øU#§¸dA ûAº™‘Å‚ûv(|)A0ÆJW¿Jäž’ 8áyÂ'U ¸cI¦ÁÏÌIÜÃ¥?‰N&Küºóüt´ÕG øINº3&bd8©Å1À%äÀ®r'/"æÈmè;\çRBW-ì:? ãQáÃ.üŠèœ„À˜Â|k ­A` 9/"ÆÀðMBŒ3h8àbÀ¯ÞK©0†j'8’í¡îÛ¥#ï’½7dÀžÓÉ€;Èo£„ øõçþ)x#Æl¼{9JŒun'Ï£ž—ôØOBB ö»8_ùø%Fj±Ç0zóÌÈ€1ƱLˆã ŸAÀ#Æ&’ã¤\^BŒA§BÀ¸á±•É?|03vãof÷ncà7ý¿E¸)IÞH”e ü¶i2ôé©´ÿhÄIÁá+!°)KŒ¶øýCˆ$ötWMŒÌˆ2Üm:3èÚµÁ"FÊŃi%Üud–|2A0º|. ¸?r¤OŒþ°u‘`?ĉ‚QðQ(ˆãõJ>ü–ÛùÓQpÇ~ÛMþCS´§ˆÿŽ‘_ˆ“ÿŽ‘ ä?4µ/ü‡jø‰8ù/âfÙ”ø¯º“üw %-Ä ç5â?Ì-q¥øïÀÖ•4%þ«y\ü‡Çƒ”&üÃ,Ùü«ySøg ÿŽëáúRø‡{·¿2—vƒÉÝeñhÜ›ü‡iBOòßqå×ò俬B’ÿaxÜÝÙÝ%t¬#¤Fñßñ0ó@á´b½¢¿œ¤¿V<éOý¾Ð–29w’þê)+úÈ“’þÔ£?t˜[¿¤?LBEÒ&ýÏ+‚Húë“ô‡jÆBhJ<(úëz’þêÉ+úÃs&žè3[6>Ñß1”˜ºè¯»œô‡2,"ø;FÚ?þŽ—É¢É~‡ú!ò«$ïE~u8f¡_eò)ôÃ#Æm}¢ßñê;}¡ÒÎ9“ýP†vâd¿cŒŸ úÈ'@[¢Ð½'ó$úSYi ý:OÓ‡Ðï@Lÿ‚~˜ƒ/K쇦v‚?4%°ü¡žw?,ªñHøCo8Óþ´ˆŠ'ü!Ÿ–íä?\%“¤øÏʈÿPfw‡ÐOrkeKþþ‹Ðʈÿ ²ä?$:þ;V# *9äüɬХSÂ’5mî ý‹ŠþÎmÓÃ’ô‡—1§RÒ³üaý¸+à1 ^¡¯»‚Vqž ~}IîÃ0îï#ЏÏ.÷aÊîæ~è —Ü?L"¾ ü !ÇEàw¼Gò£À¯vE~V±ÈC'$ø¡Çü€”à×C—àWOO_>rÅ}xN'myâ¾ÚU÷¡Çs±¢š›((ð«',Áï@æ#9}üòZÜwÜ{⣸’sá¾ZkŠû07óîmî+ÂÊ}¨†a‹m1Öó_ØWeþ…TÞmœ‘Àζ-§WHXh„»&ú+Ù Æ“~ æÀ)?P¼0hÔH?Ð 4”èõdÈ[¹¾Ù'7PœÈF¼@?Á/^ ¸¥cñ½·ì°’ô8%~/’ŒõBÂM¯C€‘ÿér/PôøÜ݉¼] €È“U ØJ !P”¹Ž’MK! Iˆ€P2=<‰€.á]µ¡º„É+”$º„hÃ't ’ôù$º„؃.„€!´»ôŸ@—!‘mYI½ ÐËI Þ¸;'µÐ$@ Ÿº„ =þ]è K€Ü‹¨KH€‹$Ð%A€(Sè KH€.!º„è" $/W! —!z2à" t °%É€. t’ù:º„ è2  9 Š] è2 WCôî­Œ Ð%„@«YèR KHÖ–(Ðk&º„èõ½LP !šD‰Ll„@ý2 KÈ€.!º„æR uXèeH.!v VBh%È€& ú5D@+Bô"A€. º„h‰íæŠM"ìÇ, Ð%$@—]BìU( Ð%DÀ^a]ò1 _B ôÄ@“{M ì:1Ð%Ä@—]B t 9°×õäÀE2¹Š÷UäÀ~‰M ìOr KÈ.!Zãâ@kœèr KÈÞr`½€½1ÐÚÚZSÂ@»ÅÂÀzµ'šš¢@k\ è’Ao‰ è‚ K‚Öc`÷Fhj ­9Ð:#ô‹ˆ‚¦·hÐÛ& .’É%¼†‚4è“M)Ñ KHƒv•hÐ%¤A— º€4h½ zS¤A á _Eôš‰ƒ­yâ Kȃ}Uò`·ž<èeȃÝzò _<èò 7N t Ð%BkJ@è’B]B ´ŠE„.!º„DØ’?HèÝä7"7·“ßÙD’üw˜ø•䇣ãòÝ ë„~8¢i›Ž~Hî¯ð¹Lƒ@®á!€•m]ègY„~ã¾??+æ$Ñï}fäFkô›%& ý°éÝdx”÷'¼ji¨HïϽ(³Ü?ßt‚ûaÿúÅâ‹5rˆ]½šâDÑCkeÇ~‹ÍÒ€_ªåé8GÑÖy¡ÿ܆‘ùíÃã;ØB?Fƒ}E"kæl‘¯ú°sÁÇ{Ôiâ-")¾pÇ7”_‘Žô+Ãt[/büqíHó¡äd>i|€ÐUóIwëëD:R«ùfBi|ä¹XÏÄÒÖŸ¥­ž jªïi«çb>éJNÿâlÎsmë‰|Òß1çÞGs¾ö˜]/óI[o&óI÷3toÌ'Sgã™ïù¤­Ìù¤Mpn™’«Ô{_Ì'ݽ¹/æ“ÆGƈâxï›ù¤Mòð0ñ¡à7²ÊìQ„ÙŸ^ðð˜Ì”ÌÊ'ͬ\ï³1Ÿ4Rƒ>”ìÌ']ã»ØûÌ']+Ùs2t÷ø¹6_µÂòõÑ{î— xõîyðšgïܘQºÞÈï¤yÍ®Bn¡gy Î32JwãH¹8ø(2Ý;/f”î{…xÔy/e¦”îœüPeã5_¦”îÑ%[‹8×ù‰¼Aç°ù5‘ûI‹8ʼn„Q·ÏÓ‰Ä]ÏiÓ`âÀìáOãÄÙ¯éÄyÙïkËÒDž XÅ»ñÁ”ÒŸäa½/3J×Ô™xK‡Ýá ÖiÃ5a5ŒU<gF¢öf‘Û^®Ù$žk¹êbFéÒ©v[û'ŒHï´‰;qhöômÎÄ[zóEgâ-½_6/&ÞÒ±Œkš~3‡¥k2Á(×"8™QºÛ>Nf”î[u0ïˆÝò»|H#TÓ—ñ‰0Ù/´qÓî ÞÑÛ°xEÇ^á}\vÍy0tÏšóÜr /ÉäžÐ<áÅþÚz7qj¶Öp)€S³Çr3qjöë憎S³ça«ö÷à]>añŠÖ"®»„Wô>|Æâ‹x5}á Éeæ'™\ÄóNâäîÛw8ßîcp ÏÊÄ9ØÏ»HïkÛŒÓF/¤®8ȯÂ;zó÷ÅÄ;z{®áP¼£áÃw#mï¦êZ5õws' ÞaÐ9 ñžeÚ‘às)³Ž@ð¹ï,0Eðè¡O„Û‡'9ð Ø"W‘qÈ5cº’d"e~uq PÌtœˆ“°••]ˆ“°çâ],öâ4ª—¹Ä0[q­H ~v¢ƒÁ±¹%¢ŒÒÈ ‘N\ÙÞ‚Ș§î yNIB R‰‹¼8¶û™,Cì¬{I#^Ԉъ}!¢Ìñ°fR ™ëýF ÄEdúÄ@H´½"ÁŸöÂÀqð Ú¢@ÌÐä @”àÝâóØ£–I(B3cR _D ÄUçÁ2¤ÀØ0…µ=)'¥ž Z[IXи7ZÍ¢@X$yw“qÕ³SB ô«H¸j¿ }AãÄ‚Ë"¤@¯†ˆ‹¶àE Äç&¿N D=œ±‰ƒ;" _@Ä7±‘ø•ÿ4-‡QÌàŸh½âªýâUD@! ê¹yëqä´ ‹ ˆšOÞ1 Õ#D[ôAO„dl,8ÂボHô‹ÞB †JGçòÏÀ , U!ì³é­a i$D>ì €êŠàÏô#ü <†‡Ã_¸­ml†ôç#ýÙ­ý¡»{Ø$“þì*ÒŠƒEH^ ée˜|>éw–9†“þü*Ñ_ŒðÃ<ĉ¨™‹ZâŸÍF៹ð¯oèÏšþ¡©Ge>üó:ˆ64Â?ÓIøgóWøgwJø‡2Ìs“øg: ÿ¬á_`˜øgsDøgwFø‡z¦$Ä?Hø‘Oøg#!üëÁýù5¤?ïé¾H’þLsÒŸ©)úó‹HÖ”èÏ”ý l½„v¤¿>X#ñÏë!þÙýþyˆ6m…¸êä{Bøg·OøgS…øgj ÿl¦ÿ¼ ñÏ›"þ¡ŒjáŸKˆö„ÿúÞ$þõU‰}U⟗!þõÜIüÃV'[ ÿz”ÿZ­Ä¿ž¸‰žƒjœüçÝ!ÿõ`ˆÿ¬ñ$Lœü7®].ãÉV±ø¯§Aò´:§óŸ_Eþó«È¸ŠnîɦºøÏú,þÃ&ãˆg"ÐF™hM Ûï=к,´îmx€. ôþ‘½)" U,4=Å€ÖeA KýØ$z=„À~JQÏTI4%^3!Ðî ÐTÆêøPB´ ­!A  — ÐQ KH^)Ðë!â*>{‚@Ìäã"^M"ÄEó&áŽK©’!xbS™ ÉŒ]Y2 ×BD™ãï%¨\àI™2ÎÛ(°´%Òù;ƒï±W‚ ¼¸™@³%a°ÎMHŒŠÉ‚Q ­dÁhiaÁèßt‹`’,Õ JÈ‚}&B² õ<' $Ea ÅCb öÌ+"=µˆcCiÂ* 9Ç‘x°‹©¿ä@¼ ¦rB²¹5p†“ý0‰ßs¥À!á)މøÃ*AÚ: ZÉõð*b ê¡w®(Ðð\ˆSM™y.)ñxWQ Š0]R`…šÉ%4#úU¤@œ¨Êü I~UPàÄâIž#Îó%ì&¢™§ñÞXfêlÙ‘"A ª¡{nB $L­‘ÉÎ}› Ðô¢Œ ‚@Hn7š‚@¿hðlÙ¡Ôx Њyùq‘¼¦§ ÐôšV„@«XÉ)T#¢zh'Ú­ÎHµÁ2„@HÒbIôÆ ˜oL™hƒ,´I DÍ2  ¡ú.~#ZH6¦¢@va WL 4Õ…¸ŠËRb 5% ´qö,ö¼ÚPmv ­7‚À~<V/·Šf! _B´î MI1 Ý2 =1bÀ^q’mÌÅ€6æb@=A`ŸüœˆÛ›æCB`k%¬ã˜mô„€Ö’ЦºÐfДzµd@/C´öÒ›hJ mí*Q -nÂ@{:„XŸ‡ìuÄ@{Æ…ÖCr Å>ç@aB›ä@t‡¦/a !B²Ž¦1°_1‰xw YýˆÖa $Ì+”h³MhŠ ½qb êÙèk+ „äRëÄÀ> <1Ð%Ä@STØ£C ´%RhsKˆkd^$Ú}ÚP!‘;‹ °O°Lìí@B`w8!°ï^B`Ïí„@/C,5Å€µÞ$ö}ID%Lg› ØOb2`p2`ß)1 U,ìH2`?CÉ€‹drÏI‘ hz‹m´Ä€=êÉ€ý'¢?ÏáVÁ-! 5%ì,쩞hš kã–Ø;ÂD@ìNG,ቀ6)ˆ€µˆ&öôK4‰0¶ òÃ$öôK´»)ìe* ÐŸß$@¯™hZ‰[  Ýßs^Þ²ÐÚšN@/CìvÄ6³ÄvŸÄèîù°qò_oæ“ÿz¡Hþ³)!þëE*ùϺL´Š€¦ƒÐg M6à„]Üñ!9x ¢s¸g(þðÐ4]CÝÂô EV$†é¥sh!\¾¡íN*×ÐëNaº†~’©˜<¹†^fX¹†â0qž\CMBìâÉ‚dð¡\C­ Y’5DÐ%H‰y U•, K­ˆXÐ%dA»ˆ(èEˆ‚V„$h‚  È0¥…8ÐÄ@K ´ßd@M@4‚‹A@—º€è KH€.!šDè KH€.!º„¸H˜UÚ$D@—]è" Kˆ€hÇ(t Ð%D@—º€¸H˜UÚ$D@—]Bt Ð%D@“]Bt Ð%D@—Id•6Ð%D@—]Bt Ð$B@—]BìÌÿ ^†¸H˜WÚ$„@—º€h“Gèeˆ&º„è’À@M+a —!zb Kˆ.!z=Ä@/C´2A+#ô2A/CtÉ÷â[~Î\¾SBt AÐ"z‚ K‚v•@Ðîž@Юz‚ ×Ct AЯ ô"A/Bt IÐ%$Á^Ü‚V„ h- ]Bô‹‚.!º„ è‚ ×Lt AÐ%Ad •z‚ — ô"$A/Bt QД z¢ Kˆ‚.! ¶$QÐ%DÁn+Q°n_’  f®äyM WKt QÐ/" z¢ µD´‹H‚]B è%‚V„èEÈ.!º„h½º„èW‘½ 9ÐÊ»ƒâ@ÚoR Õ* ôZ‰.!º„‰˜4(Ð"š€ØWˆ­R1 KÈ€Ö]1 —!ZÅDÀnZh WBt ЛžþÜ$v­@/B´Z€^†hÕý" $›LyÀÖYüg⟠HÝŽàÏj%üYÂ?»†ìgÝû¹„ìW-ÿAðB<¤bùYËS1X•E%Ì;a·÷ œ]É`?¥‰eE”æÙʾ¦40Èåx¹¹o<§>¹$ãArzôßx®²*úS锄ÑÎUL‹wßã„çÿ!g/£ð"øï™úB^ÁHT¹9âáåºÉà?ªxx\%»gÿ!GùbîcûaÁv…‚ÿôwþ!᥌Œ™þeW|Kþ!úR„ üóôJSàŸ ø‡ äu^™ üû$ÊnP `Ž TÉÐ?«‡¡ãÌøˆ ý3‰BÿFæN¯Ð?«F¡8owC$-vŠüë‹,ÿK^¤È¿n*#ÿ*IþY5 ü³‹ø×:(ðÏ üC~\e£Qà_W“¥BÆýµ@aÕ;Eþõoþ™€Ýnþu¥Šû³Ž(î¯ovÆýõÐeÜ_«øÏR¿X¾ ûë9“aHZz/a] £þº{õgM+êÏ$Šúƒgù³Dþ•Þù×C“‘Ý™Œüë‘ÈÈ¿žäùgõ(ò¯ÏÈ¿¿Œþû$7Àý×-£ÿ¬)EÿÙEŠþ—\*ú¯¯Êè¿Ò\Á5Âû××±µ²Tì_߆Œýëj3ñK V†þõýÎÐ?«F¡-ÉÐ?“(ô¯õÎØ¿îrÆþUw"ô¯û’¡Ý— ý3‰Bÿú6eè_f†þY_ú×e2ô¯Ëdè_÷7Cÿz’dè_ë¡ÝŸ ý3 Cÿ¬b…þõ,ÎØ?“(öÏ:¨Ø¿nT¨Oêßo|òAνG{cg‰LßøIf|*üª`‰}»6Ïðó” ûÏh™OÂþãÀÇ_‘è­3Á’¯ÿO|—Oœ·>Á-GàOòUùF5ªççD%"&u ÒwgH˜~ ’øPhµÜ824ìyëouÿ‘½â“¨ûƒoO¬­w@÷×û±¾î¿‹øµÞêïýr?ÿ~«ÿÕÊóuΞç!Éüy˜çl¾?i™¸.]uÄ7Â2*à$¢çç½T¬î·s-tÿ$_ÿ‡™pÖåYÛo|#,£ÎÊÚã÷ÐL¥Áþ¾’PƒWQ8ìýy4á§ñ“9âéð㪞ÀæMiDqp×ýó^«‘ Öx©#ðg´¥grí?ßõ¢oOr™z·-bê7üž?Óü‚#¦²÷Yëî'☬'îQwö½n*Ä_7‚í¡Þ®à…MË>­âü¦ã—ûñ²ï…ø8&m“6y?Þ9ã3@åÜ­ùôÆ¡µËÐÂûóX˰ÿ8êJ«ލ=͸…sO/Ý¢ìñÄI­ëUãVÕNèò{?¥BOÄY*0/óÑþmgir nÞç8Ävwµ±†RÕ,8ºMu•TH°Þã /*Å”i{œ1v¯m*,ÆøçXÛBQœ8Km™fßÿVv}Õj½ã%¼/-Ç)‰ýeà| ¬*í¥€F|ßKÍÎ8MÕ¿àPÌmù† Éü9|NìÇÆÏ‚ù…ÇÝ(Íâý8ÆrŽÓ¿e¿?v¶„áõU‡džšzy|‰wÔ9¨äA¾¥–¦l¹i-ÈÑÅñ`Ï2‹Î8ÍÎU:‘¨Õ?q¶€lÁˆÏ2ANj`#Ž·ð¾–yNN=þŠCê–¿¿ñM°ãýüz¿Î±³zŸC‹3²×®àŒìUœ‘ý.ËC²×Yw]Ë#º_Õ}Á•½¯©{C’¼%×»k5ÐB»_sûeÞ]sê”É-z~ÜR#…ó±Ç2Sq>ö²ZƒU4çRû¾ÖÏ)…ªö¿·úíº'9t÷ܤQÕ3§4Ê–žíÕmÊ«ž}H£*#z¬žÒA+çO÷w™š8 {Ö8<ϹþuĶÍFïáÃß û£þ×`G*ãs™ c{×y‡DÅ÷RMäù]%çýËÚ6Ø}ª±t;¸õ!cí,^Âëj—0Sô íP÷ûªWÝoß}¬¯ =Î.Y&ÎÅ~¢æk²ÿ8{ľŒaŸä>õÜTÍÒ¡öšû+ô¢ýv7ËÆgÇ«x7÷H¦›Ôrnï/:ÍÔ€¿ÔûW±ÂùA oâßÍÚLÁ‡ãN}¨›ßr¤Ý‘¨n;rM ª{ö]aEIu˜æ ;Nª+Na©–V­Æ";Lü|íí" $ÙáI˜jšd÷à³õÍ­ÉÇÓ2Ì7ÉyÅ™ =ÉFÛ1U&¨gØ2ÉîùÙòš »óWÄd÷`¿–ý£ Xn·ä¸P–äGüdôŒKg %ÙÁ<<^I‚ìpŽVö†d÷ĶÙá™~²-êðž?…´ ;äA¿ýà¨Sµ†H/È’Ée\d‡¼èÌ”˜d×™Òí¤ÌÓÐí(?Ø9¢ÝóÍš)('ÚAòh°Èv°x¹Û!O{ªMºƒD]Ž=æ[á Üç¨Q!ܹ„p‡um× ÜA²7ÂgßÄvÀ!"Ñî¼2xˆí6ä«PK„»m×¹3EwÛ^” ¼ƒ M³3ðn;j ï*í|ñ\f_,Èx²â»OÂ$ÅwÛ­ôêÅwÛ¥Ôx8TVzŠð> ½òŠðp¶¾hˆð*Å}Þ·Pñ(^,4“.¡™¿o›:7ª àwñp­ÚâážêÎñûI„x^†œô•ÉgNŒ‡<@¢+1ž• ƳZÄxÈ£ïJoé_œçeÈIȧÂߤ¼Êö_¤‡Ä7ûBz0ò%ÅIƒ=_QIz0èëQéyb’Õ¤·Ã™J¿IzðÏ™N¤çip*ï}‘\-5#Ez^†¤O4ÍQ‘²Ói)éá‹èL°Û¤ÕÐ2!Ôë¶õQï’“öÌóY¨·_µ›êù5ÒÁÊH+CRB²¼M`GR‡õGWõø,ËõvÄTªÇD½:¡Po¿~ŠW‚ôöQ;ƒ =kF¤‡ä’\µ’ô!î?õv|M?J;?P&ê!ÓÜ%b$)ùU$%¿Š¨g¡N6Ä`D=/:¼µ Ôó+JØa¾‚?¢ÎU|…”d=ì ÉzÞŽ4¨‡9Y¯¿4'ëaß"Ðë!¥R2V°^©ÙÁ^?΄½žž {Ö¶`¯’„=/Cà«cA øúQMâë<‰Ïz#⃿¤´dj øúyNàó2×½(u• ÙaŸ ¨ˆÏÔñY‡E|Þ‰Ïz#âëU+‰¯WȤ>—˜¬-QŸ—¹¯µ©¯×Ù¤>xä\*S:h…Lêëu,©Ï®õÙÍõY=¢>«çùMQŸ­u¢>Ó*È¯× Ÿ ¨Ào?‹KžßTøYŸ© ò³Îˆü¬Ã$?Ø|˜é¤ÈÏËHk‹äÔ³6à¯ß ¶¢ þlµ¥‚Þ8 .!:!Óê-$#>yŸK=Æd?ì­µùKöóŠÇúxûYD?$YÝÕ ÑÏtúÙ-˜Õÿ:៽£„5zÿBÆî²ê „̬÷ŽÚlî2Œµ »N$Ó¦Gv=3ÁÉ®×_*Ó®çŒm±í™AHƽW‰«Ë¶÷1×.Ó“l{åõX¶=‹l¢DÚöúKeÚöÆÔ‘PeÛÃ]Ù›ÇG\Ì•P¶½gã¨7´í}P“,'Û\1E–²í½S®eeÛ«ƒŠË¶÷¾õ-]¶½¯¶y;Bƒàʶ÷ݘ‘”HÞ·Ð<Œ{SÙeÛÃ[äDÒ¶â’YB¶½9JmÙöÂv1î…g ljTàS) 82îÍ«,‚$(¤H?ñÔ¦!Nƽïò®È¼ç#o ˆJ4È%cðÛ¨+n'.Èi‘u/\KëNK,‹þ/õH!à×¹².W¿2ÌÓQˆ<ð—!  ƒþø[Úˆ ­ÇB@›ŒB@/Cœ£¾ÕçSÏœ0˜[WŸLO! ÷èõíšñ›BÀpn”„ød“\8•R³О' uX8²z‹§¡I ÄoZID€6€"@<Óoß¶Ô+ÄëT“BhõŠç©#“‹?‰V>!àTâÕ"À:Þ¼ÐÖ§÷7 D€6 "@|ˆÑ¾3í8$@[D€H³¹˜úæ‘ßáÄv›ÄÖ²øožõMüg}ÿÙè‰ÿL'ñß" j°ÿjŽþðÉrˆ¿HØ1Üâ8Ò>G= ýÕ=Iø³fˆN­c²_Oéd¿Íd?ëÑîLúÚ¼WÿËŠ ìéÆAöë® ýzINôëÙ‘è×s7ÑÏÆEèç œæ®cU ý¾ùBOãB¿¾û‰~Öa¡ß÷nJ@ ß÷;-=~=¸"?ë®È¯µø½3ßô ~s×é*~ø8™öFößî½ÀÏî½ÀÏê‘‘¯û'î»Fm¼‚ûz)Hî³É îëéÜgÝ÷Ù-÷Ù÷õ#›ÜWOdbß;Êþ#Ä}ÖeqŸ zpß<”ש¸¯o‚°¯§³¨Ïº+êóvH}¦¤¨/ºm¡¾^}“úº)AŸuOÐçúúÆóõÚ›Ìg:‹ùlöÞ¥A5D`êU(™¯òÙ´òõ‹)‘Ïë) ê*ò’=¦B¾wêÀ\!Ÿ ž˜Ï:Cä›Êj^Äg«ŽˆÏcŸÝ&ŸÝJµ@ÈÖgKˆÏú+â³!ñÁ® g#ϯ!òÙÓ#ä³¥HÈgËŒÏ!_oùzãœÈg:ùlÁ’½Ïzüþ¦C0Ÿ×æ{§Î.è³åUÐgSMÐ÷Õ*\ž¥@˜¯ï®¯â/2ræ½[dkÌÃq¬…l¼·ÜâóÆUޅ¼q—k 0ïãÜ óì/Ìsj"#õú›œ×"a^/ã‰y¶­æÙ&O˜g;àļާó°c?ûó|OÌsÊ æA’^yļÈ>Öµ $Ôówáü”.’&æá*þ…y/ŽsÒöŒ˜÷n£6~Ä<ÌôÜ–ó^|;Ôfœ÷Æg-ç_õÿ¨O&¯ú*£gž?\_xHxÞaVŒ"E©PKÑ”{cU’iˆ×†ï ó˜¸+ÏÖ3ž ° Ý›Û÷ìv‹ñlN‹ñlÞ‹ñlN ò¼ž½THßÎÐàªoé`T¤<Ô#Ç QžíDyÐRßµEy~WˆyØ&nÚs-IyÈ$0Ïï 1Ï6/¯H{Þö+úéyÓ¸g3€´gz“ö ÈCÒžiÏW‘W´N¤=ì.‡=¯°ç*ö¬sd½¥ˆúßíõ|!ì-WìyÅÁz>xd½¥b)ÐQ^ÅÅz¶ëY%‚=H2ò‚°g£)Ø[ÊHƒZ¿{h©bò––2{Kÿölìy[„½V3`ÏÊ€=o†°·”Ú³[ Úëw•`ÏGf¯þWO•–¦•¼š`=²ž_DÖ³y¬·\s>6ã…z>JD=ïQÏf¼P£­o¯B½¥aö¿Ÿ?¡ž—!êù|'g½Å…z6¡õl1êÙ²#Ô³Å@¨·\5¸ê CÖ[Z Ö[ê)²²žßÂjÎ$žÏž÷ùº–•hÏvV¢=Ÿi¤=›¾„½¥¡€½¥¡ÉMÜÔ5 {~ {>+{~7I{>«I{KÍ÷ú$“öléí=8g'Có¤C1qχ‚¸ç5÷\OòžÏ¶çøe''à[$×õ‹V$>_ç@|Ë5ãX_±">ôø^<9]+v×rSòy"Ÿ÷†È·”9s/—šëZo!ŸÏc"Ÿ­ >¿ß$>_H|K_¨µLâ{®½>Zøü¡"ñùT'ñùý%ñù#$ON›[¯Th¥Þ±> ¾å÷ܤS2+‰ÏV_3ƒx¯JÞó"Á{½Æz.¶ãýf   ÙpGæbÓß–\lV¢Ë[.¶?¸&Ó¾üœl熷¬=y4É,õQJ<—Úw¸êѯ¥ʼI¼žëˆ}\j«_^dVOJþó¹Ù Ÿ+7V¯ÿù¹ÙÖÉtÜžêÊZõëÔÁ‡®þ«®µ¬kº~ɺ¦:¬”êYJ©.˺¦º–¬kªËJ©®¥TÖÕYײ.Ϻ–uu©¬ËKe]u-ëò¬kYW—ʺ¼TÖÕYײ.ÏÍ–uu©¬ëßÈÍömÍp4ßÿî¹ÙþdÉüÇo à-’ÿøýIùeÑüƒ§å·:þ…Ül¹57›åLûŸ›œ­“ÀýUE{Wôü'Ò´ßKúSûÿWiÚöú×óG ÛþÇÿ ÛŽ{gæ¯;2ðråAvÌ=Iå¸ÏóÇ‹„V~_q^ä^Û®ã¾yxúüIl@û,zH°‰ž÷“N-Ç·‘úÖ®yUÌûqÃAë>!ÈÜyÜðúÿ1GÅ4φ è|ö´B¢}¢ŒlÇkç„ã?ILùõq7ýÆœð5¢mþˆmåWbKÏ‘ãy°s¤%ë“`ºo[d1ÉÀY.G¶,eBƒOrÿdÐèëg)@?øCel@Q³"†ÃjQ^m”`ðkB‡héR½ÏFÉ«/CG$Œ dW™ñ†VpšáF1ç ‰\ç!™Ø„¢7²T¯tÀ$`ë¯tØãŠ'%éªy|3 o9\Eß±ã½öÐ Cöç›yüM³ÎñJìŒU¯tØÓÏõ[Þ_JFŽè9Ô*²Ÿ‡d>Ô*ÓC2·Èt ±îÛ’]©•ú7S¸§Sr” P‡’k­´®2÷F­y"óÙÖZþƒc#½gê¹ØC"úî᜼3t9;ãf»ž'þx³æ]’ã¤V‡ Äç–:ä=ÿ¶ÔáÓŠOðGŸ%œ^>ɤV½snÏä¨3~ùÛ¼¿y¯øD«åà|{4'¿÷¿tȱ8÷ÔA”À‹‚ZÑ-âüv+ÔêÒìúÞµª±øvg©ÇôÜS‡n+uˆdß!yÞÔ*k¯Ï®ó#=jIçC2Þ«Gù&Ïc»S+ÚÓÏ#uè2ǙϕÚ>΃«ÅÐ3üí¢vj•³ë<Å˽úEj•3ùÇàj‡9J¨A×2Ÿe .Ø®9÷xÁí—Gã:ÎTISúÂ9Ø,àâójRÒ hp/ä¸äMârs^Ïûsø’y^cP¥QeQ…SO7áJÔÒ-¤µàå¼/C,8˜´ö•ä7B÷ 2÷Ø‹á|RxÉS"zz>çAI¾*Äï¾(Ä· e’<÷¤VGµõ¼ÔêùyH’:t™÷ùEOd’y}î#Êô·Ð·Ñ¹–!Æûy_žÊ‘*ÔZ3R89S®]©è®e݈MË*1Æø¹N”Ñ*hºVAJ…ûð2\áçï“ó{C/CŒ÷óîï ïg½•ôîxS‡ºUoêÃ÷"_×2GßÁmQÏ÷}ò¥¤e‡ž¥;3U¨2S*ìp•§äà¶ÈÊœÇ2÷ñzÞ—Š×ó±,móÖÖîù¹ë*éÐ=žc¤äVÛˆ@^Ûžw¾”xc.}¦ùÇX™ ¼þ:¾¶Ô!Ûº¶óðIq}¯çõï·6E]âžëôQÀ»¾’®-5ÈäµµÙ»y¯wêÂÁgO› 'Ÿ _G/œ|öúÚváä³éwóÚ/=0ªäÞ–õú«y÷‰áÕ|øÝ¾ö¡-Q¾0?ì|ÖèÚS¬„äØj[Çj€FÏZä8ÖeâÂÉgËä»pöÙô©u}ïft&ÎYãï™·%¯yÞ_”ú6Üy£ø‘õú6´¹*ªwÞ©/Òg»»ç^›:uøLô¨þíünB@X0%0\^¡ä|¿Uað"MÓNs¡¹ñ”©Dˆ|Û›¦¾uØK"`Ÿ§˜ˆH"¥úúUD@dÔ“²ÐÒ 7›Šàä¤f³‚-ôHhÑ&"@˜&ΤÄ'‹äÿ ´à( —ˆ-”[ç_ ¹öô9K %¶S§ø¡Ór˜ þë˜wá*•íCøgގ¿öýY4„è¯Ù°()Yàϼèæ¾-ø37pÁŸ¹C þ¬)°\+Æ¡K¨À±•Jd?Õ)×@±_ûæ ý¼Öɸ‘æ‘ß‹m«Æäç-‘üÐ’:Cðƒ^ò½øá"YÇ~ßà‡ß9í~8×,§Áõ*Là‰’´ üÞãÊ;)ðƒuKñ€?H”nMà‡þÉR(ðÓI§ÿ½¸MéQ÷½øÔõ:÷-?ü­·±ï=õ=ñÑO“g> ¢>o™Ô‡–å­-êCKÚúàk#ÏkAÚÖ‡A$úp#è{ñ‰OÛBŸ' Mk=ô¡„|‰}Ö2:3’ª¤Á›‘b>4­¬Eb>T,GP1ŸëMæó'ó¡­#ËH…VüT;Ç̇–µ ‹ùp€Þ– Ч#õþ{AÖ'9A$úÜ&èCWô1HÐg÷ŸÌ‡"ZÄ|Þ;2ú7†3Ÿ%ƒ æó™æóq"óyç}‹$ Ïï ¡y­ úÐ¥åô­’©»$tAŸ¡oi= Ïõ¾B‡þ}K‡™A,‚>¿O„>z}þøúüÑ ôù ¹¥Ã›ßW}K˜|Þú–þôÙ¼ó¡3Êô#æ Ÿ8áÑ#zÐÉ|6kˆ|.âóç–ć†õ!Wć|¡9|èNâs%I|Ö‰ÏïˆÏ›&ñùŒ ñÙ(øpl´üž|ÞŸ/Ï{GàóÒÀ§6>¿ŠÀç«€ÏKŸOŸ·ôJ—„ÞRÐ’‰o)ćÑQ ’ˆÏ§#‰õˆY§TèÁ!ðùø¼!$вð­f{½ªÃS*ôkƒÀçk7Ï×,ß§rïNà³¶|=OÄ{ %ù Þ[~_»«(Þëqî-íîy+ì¾ Øû84R×*Ù-ìaÊ<â«ýÔÌÓƒ!Ö³{-Öó΀õ–jÙœ ›ôÛ sϨ;ÁÞrQÀ$ŠQìÙìÙc Ø3µ {¨FûNÁ^xO‡=¿i„=o°‡uC‰ú{vOÈzK_‚õI°žßj²žë-ëðY*äU„=ìÞ›÷¯dsK“ߘí^&?$-NƒL~ß¾QþYâ=»Ãâ=»â½–ÊÝM~/F2M‡Á{Ü2Q‘÷ÞëÈDÂâ=ød)‚_¼÷é2Åï¡LšÇÈ{(£÷Kß{=aÀ¥ëÉ“¾÷:ó­%àÃéÁ©ïýhTpAÞsú?Ú´¨þœK‰{ð8 ïyò|Ã^7øA²<eœñÁom.ć§m5 L^ ‘ž¾i&$òyÍóQØá(V:èyHæ³¶Ä|qµó™Vb>ës@ß½e„yBŸõXÐg÷EÐgã'êóþû¬a¼ú’«ˆ}Øg< öÙèˆû¼BÓu•9TÜ÷•Q`r<“É}^ u0ÍÅ}~± Î~+÷µÉ}Ýãä>ø<ž ÷Œ꤃ÕLnò2ä&/óüò›äÇÎDÃw¬!¡‰~v•г÷YÐÏêú•#X±_Ï·d¿ž]É~^¦tÐIöëÙNöóßd?o›ì׳+áÏF]ðg- þs×ß*”ÛLÁŸµ%ø³;,ø³ÑŸWôg_¢H6ÀAß#?eÍ#8ÕRœìg¢¢Ï´¿ú]Ocz_ï‰D¿~ÿ$úybütÓJHô»Fîý}xÈ&(rÇ.ôC ¤z,ô³ù!ôC/u'…~ý&Kôó«ˆ~Öã»t¨2¿é ôCŒL Ñác‰D¿~Ï’ý–’´%®_ÙÏÚûõ=áÏî•èÏ["ýÙˆ’þ,_FÒßu‹þ¾÷ü»©u²“µ%ü³þþ}=.J#þõšŸøg÷AüwyxAòŸŽøÏFTügóMüç5K‡¾W£tÈÑÿYŸÅØ»é± þ³–Ħ•ø¯wVÉ^F:tÿĽ—Jþ³ÿÁ×>M”óþe¾‰ÿ¬u µ.üÚÊ,€vÇ€¦§ÐF‹hÙoý*”Ídàuæ7@ñ_7žüw]ù¥.ù¯OìiAüªMÞ?ùŸÉO=. €Ý·@—¨ÿg~$JôΠz4qŒ½›ûì$v“G~>'Z;"À~6{Î$Z…€-—ÅRh#!ìû–h­‹{ úh‰ý*2àuäÈ`ÀNÖ’èÕ’aôš²å‘M)1 © ´Îˆ]R*ÈÎ)çy¬9rIÿóìn‰}ße8Æ'±/zvy[ÂF֧ߦ™¯Sz§™w~KÈ£™ïÛäU4óá±^<=qÕHÿP™ù®<9 Í|&‘™Ï%4ó]r4H#–”W%Bƒ»!V¾>‰7­|W:e¥‘Ï:+#_ð›F>¼MÅȇ}Ħ†Ôý–ú¼RÊl·SÊ<çbæó2¡Â“ÉÞE}ÞR$Rз è[ºз” èCg”ËGÐg£õ–鋸äµù Ñ)B>Wȇvt@›Ï«•Ö• ¥¥’ %_ŸKH|>š$>Si–U$`É›"ðùEÁ{ÖaàÞrEàÞRk)P)Ð#Eܳ‘îYáÞR&pÏjî-eJƒ*¨´J"ƒ²_õL¿ Â=›®Â=<Û–Yf—]qÏn”po)¸·” Ü[j–Ýã½t¨2J‹d¼ëïÀ½E¸çõ÷¼7Gé …C¸·H–¼fâÞ" Ü[%s]„{K¤CŽpo¹"pÏûBÜ[${‹¤4ÈzÏÒ ·zĽ媦¥LðÞR&xÏÖrñÞ O–‘UË||íðy Ÿß"Ú)è ä³w„o©Ytïˆ|K[KK™@¾¥æ÷ÑûÈ‘ÏKÜÒÁ$KÞ‘Ï["òy½D¾¥ž@¾Uò«wéPõŒ!I]õ>¿hEäóþùð[©…|^ïS:d-D¾¥LàR½Í|þ{J£÷Fl"ÝØg×(-í(y-„½¾¨çWõ\¿Q}/Iõ=Ç„¨·J¦ô)ÉóJ#¬!Ô³¾Tÿëšê¿ t[î²bž•8|T‰xÞw"ž•¨žW‰ê¹;tú?Ļ¥Ìüeÿ&¼ëzgõ¼JÇ/OàÎûF¸³:îí—™F´3Ç3¡ÝÒ΋†»¥Ýyû×Ùïý\W4Q•8—ùPg½7éQ×ßSšèÎ éìšêµFC@·Ô2ïŸËÓ) ózItK™ãXg•n)s­ýÝK½û…tË5Ï»>9BºÖ‰@·Ôû›Gi-躙ô¬ÿĹErmÒ¨$÷櫉xn)ñ¼¿Ü%òÜÒ»÷YŸ|ñ\÷Ž4çõž¿ôÿü¥ÿÿJ·ôß¼Ÿ°Ö”ÿ&ÎNûü7Ÿ§í{vNbö>¤–xëp mZLjuvD­°GÔ¦ÍXIZêˆuè1ÖaáÖ×@a$e« °[®‚÷NSvϸ“Õv µ-]3ƒì I›%É’´‘ì‰4˜yšÈ’ô[$Ùy’$g†ÌÙ-’ ;HÊ :̲j é`’£U9$>IÚ¹ˆvHÚ¾Úó }8í*¢ÊìIXÔÁ%F¤,án‘Ü-’{_S‡E:¼[ÙáHw‹$àh‘ÝÙaÇ¢»Et·HJ‡’¹žÄ;HÊ6|·H>À[Oi¥ï‡¼ER:”$àÈ$¼E€‡œ.i»!à-e¤ƒ•‘& 8Z%‘UË%Ï/¿ð ]9½méÐeöÒ¡llG6x‹$Ïæ¶ÏîŒo)Cú)à-’±w&ßPšG2Þ^3Œæ¦FÆë ø&ùm0ÞžFˆŒw\!Š»ïøQà.ô#¼sÏí$<”Øk á¡ÄÊ% n»—¼Í$ÞöBxhèJT€‡ÇõÜHÀÛš–}ÐÏ+fOßmI˜ÄwGIðÝÖÄw¨çö®»à;üÊûûdA^»eAö„)¼Ã˜p-º‹)Þûò‚î0¬(ŒAt‡¯w=;ÞáÅÜÞ G °óXdI¾CÒ*™ønëc<Œ+6óŠtTÝé²xÑv´Qì‘ yrb˜°UÒêÞqÅwxܪ°1ÞQ€·ÿŠ€‡Ûœ€‡—¥Ç"¼^Ÿš#ÂC=363oÅ$¼ý‰Ix¨Gi!ÞÆ·àø]å< åþ°<ÜØÌJÀC-ÊÌ*ÀÃPplÒó/‹Ò|~oº"ßퟄ|·Mâ; º XßÁFm*¾ÛßÙÉlHÀCÛœa–GÛ{!ßáEŸÄ»ýy‰wø!Œx×sõá&Â;øºîÉÄ;Ü{ÞanÇ>½½x‡ZtdŽð³çm“«]ïðéŒ4Ä»ýcïð43Ä3ðîøUà†]/%Ù°Ý=УфÂ@£½}ïöï¼Cc3Ïï¶1­þÀ„*êçC¿Û¾ÙnÿPd;üÆ.Ù%ÊßTõü×BM=ÿ5{¢J¼“”h‡!̵v°Ð‘’Av{C#Ùí ‚d‡{Ù;î~`Ù?NçRro–4ºreŽÿd»½ÂÝ~/Â>Â܆l3åkÝ퟉t‡·§7C¸Ã{x¼!0è^¤Î2ÝÕííx‡Ïí½åÄ;ÜÊ[ß‚î¶%ºÛ/¡[ž%0 ¶Û:—Øn2Äv›ƒ+¶ÛšƒØ†NªäãïÏ`„G"’ípwåÛáqMF„;Ô,àÜ¡ÄÛû>˜@¶Ûz¶Øn3Äv¸Fljí`¦NôÛíF‘íVWÛíÏK¶CŦ\²ÝÖÊÅv›D»£šv _DvýšÙKDvø’òLDvǃìö¯M²Û•ÈßÛÁ¿ï´À¯d·¾÷ž®I£•SyÐ\ÁI)ÍéºõGºîíŠuý–®û+¿ùiºÏ§ð_GZì³ÞuÕ‘^;¿HÚâzü×^ʶz\rÔèÎzô×QËözT²×Sì~Îóm鯽•mõ¸ä¨çkoý¬çüÛ·ùÓ§ O-2âiÃ/${½GKÍ?•Q]ÏO¥çïO\0:Lþ©Äã2ˆhYý¾WfåoµàÀñ-»8¹gǯ¼àªa»Fµœ9ÆYÓž5YÁUÓvj:3Œ«¦-+xÔ´çwMë×täWM[Nð¨iÏîšÖ5®éÈ.®š¶ŒàQÓž5Ü5­k\Ó“5Uœ¬ÅïXø„£Ð”‰;aù‡ÛVì”b%nœ—"2s7êqZ¸ŒdÙȽŽ»YrëÀù p&ÕçWWÈ[Y’"¡ N£äâÑ€üH(ë:%% ×V¹‘óU#¡à‹D­* â¤*¾¯|õHÇ÷¢:Þë¾"£ nHyù¾#£ Î?*º!^òŽúïÈ(øKdè^O|Ó†ªßÖ#£à“úüU‰Œ‚o~å{FJÁÑi?W]Ó"¥àhŽJY;:¼l¸• 2?²ám¶ü¹#Ç2¯"’ȱ<œwm—ÈÏðX°be»ñ*ÑÍ“Ómæ'EVÄÁ{JÜšÚÀ7úІÇFAË KHüäO‹4Ñ £¯Gšè„Åq>(FÅ¡”üÕKF󰙯L(X™dÉ)–¹Æ/¬nÝïž, FÑŸþù‡oeݨD–hø¯~Epç­_µ—FA!`I,Ë—mÂ`UÅ?ï‹õϳ„nH´•(àã'Èoü¶šx^íI Uà%Ò+ãTÕZ#EtB\mÌ-RD§R?ë6=2D£©êspÙ¤BRòJÁ(‰ìÊ£+(Ãq.OdWN­)‰oŽ¡%—Rñgœû“.¥ýÌŸãÝñYŠ Àº JjäVÎHèG¥&¥a Õð•Þäç­W䇯{çªD®w䇎³P»JhÁݵ–+-ˆ÷®’7r+£ž¦šS䇯§ZòvÂ&$I¤ÝµàNxL]A°"{«Ä6 °ÖúÃ’îþHào¯*ÓnFöI|)¬‘7•t6¾Ù‹#Ó®y™t67™ÙŽ&Äv||„î›·œ9<8×sÆ\%£4G´šX‹†Ö"?4LP¿n4aô]¥àÎ&àû2ñDîwäV­Ýí¾ß‘[yŒ6~]8SFaøR=oeÿi6¼Ë†ìÜϹˆQ†J,&¢$×ù<ñV¢©1™ùÏÃc3Á¼î™ßVÁ¼üpxåŠ]¹dÃåóÊE†¡ÆU®§ñS5Íaåz+?Õ;ëI…ŸªK:-WŽÑcfPÓ.—lÝŒª\²kaº{{ø­à¾DAø²Øn ¦åûx`LË_ñå’ΑîÒP><£0zºõV*—¤ÂO…y5 röHç›—Ä/å”̇gÇ—Êjå–Ù9¸Ç袖D£Ç¤ŒÅ›b>¾÷Î]0?ô28=”'^ÆþÞ=ül‹åáãËé[sm$ž¬¨ž~¬¬zjøAxuM×´‡ß(±Ë|¦ÎÃq¤¼ñü8‘&¼HO óè>ÌÆ7N·Álüj¸šXÞ·r”sG)o*üBEÍ·¼6 Kˆ+¯ HÎT>å—%ã+¨æöðu¹³õ1ÊœŸÈ'”DògÿIàb±ÌÈ7'½ßô†´µoÌ:ñº[sÊáaÀ¿tMIì9„K’ «%™°zæ‡ÊÈ)« ýG»»4 ý¸û˜ ³³l˜cQɲ!ü(Há­!­`TŠ/UÜ—rIüR>F¢N2¿¦šìºù]n5£, ^O¨çg‡MvõJáÊÇÖ´p~vØPmåh ¬VïÓ2lZðaŠL@”¦È„ÇdQJ¡+4g€‚p¹Ä)Uý°4úBsÖð: çšReÃê™Z½Á‘ã/×´~aZïÉ}Xã߸‹ß¯)/¸’·2“ûàUóZpŽIU²&q_Ïîˤ>¸EÒ´“úÆ€áýþ¢¾‚4o&Ìöá¼qQßä&ê‹ÄñÚZqL©<B_E‡–çNè«Íƒ˜oK!æCz;$*æk-9}’˜¯ÕâàO1ßx§ãÞœ­É|›,&æC\”x1Nž’,fæƒÐ¢Y6˜‡~è"ß•ÕÒM|7^' |Φâd.àƒàC‘ÔÀwƒéU ïFtˆ0‘À÷T~¾8kMDEàÃÙÏœ† |Ð]t/ß{Mï1€s\(Žd–ccàC( PÀwÛõï½ïe÷í1-Ae ï…`¬0* Ý |–ž |éêzçæ=¸>ºÄ¼wO `Âg# øR²¾ m |uýJÌ:œ¡ªkÈL9ô/‹÷Jðeá^ÜÄW#â‹ÑV×ø6'Uȇ¨nȇ¡Õ@À4gº‰|X+R­D¾áB˜ŒÅ|q”±®Ñóãkééh@Áò”°JÌÔŠ±ŠÈ“S`0_œù¬kÈ|p0_Á|£_Álá»6æÃyÍ÷Á|1ìë 2ß÷ -b>œ -[Ї³˜å™ ú"ÿ§`M nO@Gdªúö"¾ã=ˆ/ŽV ‰/¶æéF9–øç’˜Ûm´Ü#æÄ YÄ|õuÏòÅAÌB*"_ÄV Õˆ|¦Ðã ù‚ñ iB½^ÍŸF¾ú¶ù+"_¥ª„ÈW_sk‚»ªµ“|E|¨D[ÄÔD|«·, ðÕ4é]ÀW±[IHà«e6r_œ^ ŠIK5‚bâ«p&õ+¢75†ñáN¦Dß~'™PíÖ˜øî!*ñ%AKó½(ŒÄW›ƒHM|87C+B">\s‰ïhr£i!@Ä7&v&eâCF#_âãY×_ðá‹ÊåðUÿÉç ±ž¿úT8Ó^íÉαhç"<"9ÒNÀàŠ¥iÙ—®ƒö*z„‘ÏÐ[¿"+á+T•€•‱q¯V*cÜC>àªkˆ{ížàFà3È)íáaäŠöŸ-„{hî"Œ{hîr?…{‘0“F ÷p^HÖ½`®@—qÛâ[ßÞćÃLŠhŽÄ‡|gªTć^%„ñÅAú ùz_1 )ΦÐ5$¾á^_ðá‘t_íu2U˜0º €6ˆAN—øŽ¸gˆI|èÏrÔE|ÑWEs$¾†ˆèùïjîðá xµ<,º„w¤% yߪX¼·5Îà½íY|-2Œ³„°}¨„°×âHŽŸç`jàC:6u9_$KU‰Lˆ),‘ EÒ5Ä¥Öò»‹F¥ÉX>äã6¯Å¶kþ-ª|ó^Cè K-šõ—…{ Jˆ{Û«îEVD!!qÜï!fs‘•ðxúN⽆¸d÷p4AÚp¯¡«ÓáÂת0M ±ÀR&”ì,á^‹ ü/‹öZµ?cÚà ô0RÝ1‚²ÑÞ„–(¬Õ_‰ à×äõ&ð æv¡¯:9×úoӰЗŸ¹_EBFª$0£Ð‡sš~E¡ïš±ÝúàìX ¤Ð·ê ù`Ûc, äÃW~,¤I諤«ú<&z£Îw!„]d&tLk¦7ÆH]#déê|ˆ[o;ó ðz§†G8Ôvæ5OH:ßsûÒù^X™ó½!<³$t¾× Ŧ·ý~B:é|W±¯+ì{ï‰$Sç«ö„}Oõy«SçCü‰Jˆ}/6 (eCŸõXç{<Oìħ2ÓÕäIå›ÞŽ ïE ú“ª•@=,¨ï1 ú0ĨbAß5u'«|Øa$ª"ô/µL>¡ïñ‹õ½ÃÏ*‘L–m¡oû‰U¾w"¡7’M†>$Rü9•ox^÷A}ïè¿òάò!ªþÀ¾·O\°Ð‡è/]CpKéºTú°‰J"](}Û/ˆ}éMzã¢>`¶CÔ·©`Vúpƒ8 Bß¡ -Df û6uJØ—ò¤$aߦ½ û`™[J}—OE•Ô‡N))ÐRß-õ- ,õµ6k‘Ö—=û 0 ¤¬õá‘ìCÃçK '­¯.X´ÖWÌÑ"?hyÖé²ô6Ó¢l@D¹´=)eÝ>çTûFq½Rû.Ÿ@iôÃ5Vòˆ~Põ¾„~°\VYí›KÆF¿Ô’¡XègZ܇IÇ¥Ô÷xVŸRFsQ( À§ô%õát‘•u²Û N–ú°8“UÒ©VܚƧԇxëƒü°v®.òÛeEk}Ýs€Èq—EÜY%óhDä‡N­{Œ­o{>k}SÔ0ùiÒOc­ï*S£#ùá#”ƒüÖRùÔún¯(Zê[Z®ÀoÌÑóCê³R5•¾n 7øáÍÜâ1Z°µÙv›ë¤ô¿X@ôÃ…Sèó:Õú¬äN¡o ZYX'¡áÕº•d²K9•$ô%ÇèL¡Û¤Vú–hd¡Ïïnê|¯q|ê|ðÔTt¾¥OYè³’?u¾äø ©ó-UÎ:ÛÀÏrKK£Pf~j}‡¹©õ-íÇZ»euÊ©€ üð¾]"¥ ~ó©oZ=¥¾öYlh¥ïd*©oiJ”úpœµþ¦LÖä!L©ïDo©¾Ò~xÝ’”,õ½Í¼k©ïž0n©oLXù ?l¦’§&ä»ûô¨Œ|ù™ÁžÂ¥gÁšû–”Iä{Ú ¯òe‹ù¼Ü6‘o<_>‘YX âk“²Ù‰½‰º†Ä·s¢#;åÈN´a‘˜ˆ¯Ï°HGv¾>re"2klB_€ŠÔ7GvÖ) Šù *¨DBßòÞÙ¹Ä5‡vö4EF…v¾Óôa$~èCô^w '‡:,Üž¡ ñ¤“Õwn†NvÍà)Aßš¦fhgkS×#ô wÌ1u‚>Ì¡'ôaW®tRK}süžZßs9ÈRRߌšR"stL@º•ÀlÁUã£Ô7† ­7ˆù°µ×øFèÃú‘TK}ØuxJ}X¯:¥¾ìív†> ÐZë°Ö×f µÖ‡pªú NõHë‹ü_Ì|‘”c“ú°YŠ­¥¾Á|íï,¢X@ä«×Ä0+}i~!ÂÚOäSšê)ó=ùóÚ‰·m”“Ð'YÊ*:…x0T¾4#§Ê—üÒ¬òÝõó!òaòÉG`'ÔÏzv"ƒ^IåÃìPO©|¯{¨U¾M-$)•á¤×SåC,³ê!í•–%[ìUdüÑß¶`·U¾Ô¾,ÖÃcŸa8É=¬iÐ<(•¯Ìp[«|©ÅhÒ)[ò¡²wªhVù¦ž4U¾˜o¾õ ÄHT³È—f¤Ãù’çnÒL_™ÖŒ¬ñ¥<•Ak|ÅK.ÖøŠq42õP‘^Í^“³Ä×ä'ôÐÔ  ß=ÇUK|£—_éÅ1÷2Y0k™*XõTùÒô¿„z› %ÔƒŠ*ÿÚ*ßÕ> ^ED‡ê‘ HT¢'”D† Å}R"›±©|ïÁzíšÞ X–«À*ßôÜ­òÍVmÖƒšík¤ò•é öâün¾.Áäb)‚=´nE9ìá»t´ÐÈÒ5…6É|KjìÁì|vâ>¯L2ß[f§tJÈ/‚FÉdOžá „%|:£¦d>ŒYº»u¾Û/]¸·Õ¸ETœf‘̺šD²°d>{ ¦=(¸º±e¾¥JN¯¸íYçË^4ž:‚Á j‘lzäÖùÖݧÐW&r… ÷‡ÀÎVç·¶Î÷:úeê|c€Yç»ÍΖùê5ãC%óa¿û× J×2ßvT²ÈÅ%–ù8E('™=^˜2Übþ) ÆÐ®ve™Ï5H"+>#jª|jË–ø² ‚³Ä÷x0°ÄiYb‰ïùÒÙZ³Î&…o8ãý”øªü)|K™ä5Lf¾¹b…‰§X GéGRø@w–‡TãA¼Mt4`½k1^ërS~M¦oñÖäú¡ðµµM \ƒlÍÏ[ùtâªyïÊ>èI¼/ȧ+¨çû*¥y©U^×àÎ-gy/æê¼+|_Ò)§â½6Êâ=¸%½ï¼º€Að5›+ªs›)Ü«y¦6sTçxES\,Ì,ß|Ô§pÓzã÷0Ù(!špÅc¸ V‚“Ò­Íî!YÙŒwWÜ»ú7{ÑXÞ÷ŽãÈTâ§(’V¼·ÎîEÖNÜ‹‰DàFÜë8èÛ iÂ:QN¸ëñ¶½8;õ¹•P¸×ÓÌn¸‡nÓ-Öîõëš/”¸‡Áï2ÊefÒ¸œXI¸·ã-ÜÃȦ£Â=ø)³$pqùÀ=LmÍZ>&ïAË0¼·ŽEîÁp·âÞgLÜÃÀ¤n&ÜÛΪî!ª¸I ïa *û^>ŒµÊB&Ü‹9èY¸7ó2&¼ÈDúEàZŽ:î! ©{Ï`à^Ç:±ãEi¼? sñc »|ú«’P ÷:ö58(3p±íÀ=Œ¥oÙq¾A·†7l@êÊÛ|—KX œ¾â=xÛ—`”¼N¼ ‚÷:Ô¼‡yI Râ½½ç’÷Јñ.äëÏðÈË.ñEü‡™¯C w(g`¢rîwaR:^œØ‡×éq„Ø×qÄ Ô%r ë.ñõ7{)NÜ·×CLÞv6ì­‘Ü×G÷ñ@Lî‹pÝ‹Ü×áaªi‘û’"Ö~H头8¿ý‰ ~{—#ù!w©ûÉo·œä‡;éd‘’Dê¤ ‘_Ã.‡º“&ÆžvòCúI#<ÉS°›(É/Òc¥µ£ïÏC(ѯá½c¢žÆÏGôCWÍmg¿Ý*²< »&öÃÓ¸›‘ýÐr<“ýöNEöC | žANHtÔŽøÎ½Ó€þð5›Xšô×¼W.È˵Íâ\<Ä‘Íý}‘T ú‚÷6¡eG|ùaT» EòÃ÷VA‘_±!†‹çoðÁŸ]äëðWó.òÁ3}­òÛk!ùm_E䇡%g‘½Þà6l#…ÐßXîŽÐéGc] ¾òë ý0õv‡|úa¦(G€gG˜å’ù`vÖFG_o'×ùmÍU䇦¤YMä·u]‘_‡N}xö Þ©® pÚ?&ɯOGÕˆü0Ü܃ü°]æµ0ä×±„ÿ®=}hä·…¿áÎn Oè·l¢ß6 ýP‹²H ýð¼—!.,€SõQˆ~ˆgÍNûç&úáýå}K_$ºð’üzd[‘ü6LÀüxD¿ýaˆ~¸æqh€Ó6+ý6ÇKì‡$¶Iš'Ù¯õbI1 @ vähußÑ óã¹:æ×’}ÿ(éý –{¡”QïG•½rû@G+{hù§²7~õöô¾˹¦kÇrâH.ÿŠI[°wàLÚò¾sm¤w_Œ³ŽÇ¤-Ã)GÒ–;9æØÊ²Ò¨w#£ ·ô)iK"œ´eíd“²‡¼¾†ÊÞ‹è)á e±üæLð¤$¸QÙÃúÿk´»¸Ì›þž~níµ²9ë æ„¸"'IÒºíÌ9ÜÏù+J{¼Ž-|سsÆr¢ŸÈ딲ç~¥¨Ša#Ò½£^ƒ;•Ê¢˜wÈIØ+Ø• ^¤°‡t±€´ëQôu=ô-E„I׫÷ã QÊz¥M½U²––U/Ž =B9‘ñ\¬/U¯VÿXÕë÷ܪ¼×ëHØÒ0°€¢ö޶#_K«s¢D=,3È"‰zÛö&‰z¨ÇøEQ¯•)IÕ[{-¬ê!’ÞM@Ä»Õ6˜€´Hê>¡ê¡c U=ºžNª^®;SÕÃø}ª^ä†×5´`-YÕà Â}¨z˜¯ÕQ¥êa”PG•ª‡qÖZ U½ xÀ„HÝ.Ì…7îÇ>üÀ#U=¸ùØÀ1_RÖky6EÉzá/²^‹ãfTÒX¸:G$gxúÇ>L‘zb©{ðÍ붇o&×›êÞÜ-`qþ–l¤îa3+RÝÃè¬á@ê^‹ó{XBu“‹E7šyô¥ Ò„>Ϫ¶º‡¾´-Xé¹vÊ»q.„ZlÈ{½»I݃3i¤“ ÛO¨Á«~y ½õ]$ïÁ'`¡¼ÚÖ—¼‡u±r„röyRˆå=Ü=ïw#»­“²PÞÛ:Pè{˜¸žcF µé{qŽ…4Ùç겄òXoÔ¤ï\®C߃"J–¾‡†¤OúÞf”ô=¥©E_ä­?B91g×ÅxNpÆ*|ø ‡À‡}êÞ$' Òó!”™øÓ(n‡\Y |ó¹’|$­ûKà‹¾BA™€Ä ‚:™€E}AÕ±ý ¡Ž…Óq|«ZàÃoÒ̉ç“ …/Îk`å1ø} |±ê© |á?î”w#ý\;> ýø"g·î&ÀÛZ˜wã‰äØÍp†à&K~á E‚fý†Œ¼}|q6ÈÎ^ü±X¯O_49ýŠ_øo’)ðaåÖ¿¢À›¼ /lï!o œ£.)¡³™["Q¸H_´u•Pàëc„7÷ɸQâ>€þøz²›c/Ž;ÑÝ)ð!W¸Âû$ðÅÁƺ‹í^&Háë}¶+)|‘@zǼ¹Éó‘º#è[_ô×c'&ù29/¾¤Y)|‘‡úçŒó9„hTø"u½ :“ÂÞ î¢À‡:“–,@`Þ±‘Mä=D>¼+GaR%ÃÉ NC/ò­Ñœh Š–Î×±§Q”)֗Χ›XùãF8œû!éBße)ô¡+«s{+_/S¡“ ¹ÏŒ+2ažf¥/Îb…¾ŽÕÔó¢­9LT[ù°ùÿæ\ƒ÷žv7fŽ_žd¾äð´>á \aþÓ¿øn°ýžo»2ÕþÍw¿AäjjéÛßû¿?­²ÿü¯ué÷GRÛ1©úÃo¿ùßýQuÿÓ|Ç´þí¿¯ý7’’b{_$%Eëv—¿t5ÿúkù—õÓ>ë[ fUò»õßÿèYø5«þÜe¿ÿî7à—á¬Î÷1†eÝäìo:~ì¡~æNúÇ_}2¯w]oâwßa£ú˜„>$Ëý‡¿þf¸S\8¦(œ‡òéß¾i˜Û3K~y. וcåV• ~Õ>ÓYYì@>jSÉÏ.Ï**Üǽü*U|V6|sx/[m*ùêËüY lÙ~Åüèï¿ù¾X8šendstream endobj 6 0 obj 186090 endobj 4 0 obj <> /Contents 5 0 R >> endobj 3 0 obj << /Type /Pages /Kids [ 4 0 R ] /Count 1 >> endobj 1 0 obj <> endobj 8 0 obj <> endobj 7 0 obj <> endobj 9 0 obj <>stream 2020-10-09T14:31:46-05:00 2020-10-09T14:31:46-05:00 GL2PS 1.3.9, (C) 1999-2015 C. Geuzaine gl2ps_renderer figureOctave endstream endobj 2 0 obj <>endobj xref 0 10 0000000000 65535 f 0000186640 00000 n 0000188153 00000 n 0000186581 00000 n 0000186448 00000 n 0000000266 00000 n 0000186426 00000 n 0000186733 00000 n 0000186704 00000 n 0000186797 00000 n trailer << /Size 10 /Root 1 0 R /Info 2 0 R /ID [<28FB0901CF1CDB3DCC50A2651F5047E7><28FB0901CF1CDB3DCC50A2651F5047E7>] >> startxref 188373 %%EOF blis-0.9.0/docs/graphs/sup/sgemm_rrr_zen2_nt1.png000066400000000000000000011357041422157504600217400ustar00rootroot00000000000000‰PNG  IHDR¬táÂgAMA± üa cHRMz&€„ú€èu0ê`:˜pœºQ<bKGDÿÿÿ ½§“ pHYsNNÆÊ/¥tIMEä !1µ˜¬ï@zTXtRaw profile type xmpH‰ÍVI’Û0 ¼ãy €ôY$o©Ê1ÏO”mylÏdªrˆTÚHÝX)úýóýÀ‘yI$» [,iVÑ‹V+œ”µªéª][—Ëe°a|Õâ#Õ¤–&©4KE »èJe±Í°°Šm¥×¢xB¡±Éž6PÑáÜlÑl‰›*TïVÏd$@`ic.R¹ìE™¯*l‘ ­Íùjæäߺk7ñ9稙®8²Í‰›xsWƒ±K˜µ”Vû÷À¹ƒýêî aî²âÊÜ$‹ð† cs¨4x¿pÂ|…±“'ƒ€ÊþüH'’sÒ‰.Vp&ÙÀkXÜ BÜC±ñèê'ÞÈ 0£M%xŠ!Vnš-p&0m^ѵ.ÏpÂý“Ž4ÚxøG†IÉ=öhT)3Dø^݃„íÀ< ’A÷(âxŒQzm¾vzÇg.9ÉÃt¸Øa‡«F¹bÂW*ˆT˜PN„-h…ÝÁŸGpì÷Œ‹¬ú–³Bxp·gz(ÚJsã@Bm·ìŒ*سâž”~‡Iµà½È&‚ç†7qÔîIö€º)¥³Ö©tVØ!â¨sæ.ñ –¾ûRé–>ˆ êQŽÒáË]¸&-iàu‰óR„W= ¥QÐÌèhQÜ# *"æ±C±ó5§@—¡w)?“âó²8'ýUæ JCs}Q×䡯² ÛµÉÝ:·fÕ{–w‹‚žílj´ö ½º"‚,ÞµÙ[ "ɲx³/3,˜q­‘õV[1€Òƒép9œþEM½+)zçÉ‹n™ Ϻß;¥Ëá^ o–ÂqÓ7Gëe6_Ô<ìsÇ0o(;˜I¤B0¤[牒œK}×åp71ûvqeW;(>3RÏÂéÞ©á°Èp?:v]d8xH‘’]cSôË÷p2 ›gþžpf¶>s™>ùÈÙÇœÑC⟩Wo¤ù£1¨AÏ!/[½S ×î*®žáNŒa(½«¯“ÒØMo£Oÿ>ƒ--ៜÿHQÚþ7FP4ÿÇž~þ"é"Emþ·Ñ‹YXp”7ìcaNvPÏR¹7€IDATxÚì½}œUïÿ 5D“Æ„žî"5 Ž"ëZ­<(x£Ýê«äJªuwÙèÝY«×»àŠ×k—ÎþÙÕ튻AÅ]fÊË *»V\GÁ)–+Ä€08Ä$ SÉð†ùýQõ=}º¦»§{ºgúa¾ï×k^=]§N=œÓ§¾Ÿóý~—LOOOƒa†a†a†a†a†a†a¦Žhv†a†a†a†a†a†a†iXxd†a†a†a†a†a†a¦nXxd†a†a†a†a†a†a¦nXxd†a†a†a†a†a†a¦nXxd†a†a†a†a†a†a¦nXxd†a†a†a†a†a†a¦nXxd†a†a†a†a†a†a¦nXxd†a†a†a†a†a†a¦nXxd†a†a†a†a†a†a¦nXxd†a†a†a†a†a†a¦nXxdZ† ày^CËs]w^êêº.‚ hʱ[ùº0L3¨ô<Çû•ù~þ+õ ­ÜöZ¹n Ój}ÆkpÛg˜Ö`¾Çµô íÚ/´Cý˜ÅE+Ø ¸í3ÌÂSoÛ¯eL@ËšaClõv×êõc˜z`ayQ?™¦R©º»»Ñ×ׇ¾¾¾†¼Xxž‡D"1/uN$ë8ŸÇnåëÂ0 ïû%ŸçrýÊ|?ÿ•ú†Vn{­\7†iµ<ã™L™L¦¦ò¹í3Ló™ï1A­}C»ö íP?fqÐ*vnû ³°4¢í×:&šgClõv×êõc˜z`ayQ?™¦“Édàû>&''1== UUaYV³«Å0L ãû>ÇA*•*¹žû†aæ‚ëºÜW0L›±cîfái…ñ<·}†Yxêiûl'`†i:Rx ‚–e!“ÉÀ²¬"—VÛ¶‘Éd`Û6|߇mÛEûº®+f´ÉŠt&“)*×qœ¢òâ?Tµn?4ÃN®5ëª-ײ,á>_Vj›Ùʬö܃ €mÛÈårPÍf¡ªê¬çG÷/qÏf ¥@÷µÖ}«¡Ü½­ôÆt-«}Þ²_¨f}5e—ëšÙ/T:·zÆò²T*…d2YÓý(E£Çò¹Üö+Ãï3&˜íüækL /oDßÐŒ1|Ürc­JûvZßPÏûB£Æsپ͔Úf¶òÂNÔ6.èĶ_Ϙ@¾&‹¡íóû@ù²›ñ>PoÛoÔ˜€¶Ÿ/" š š;&¨õÜë±!Ö3&à¶__Ûï8á1ôööŠ á8Žp •o,Í€¡‡ÍŠ ‚}}}âbÓº ÄTv—¥#^VµÛφeYH§Óð}_œ‹Ü Ë­«¶\ÇqÄþñe¥¶™­ÌjÏ–išÏóàº.EA6›õÜ©ñ÷ööŠc%‰’çNë‚ €¦i5í[ }}}b_×u‹ž£rÏc5×QÆuÝ¢ç5‘Hm“J¥Š:‡ÙöoÔ¹·³]gnûåËmVÛŸ­ Îvn†a ŸÏõD5ý Ýk¹_¨¦^µP®_ cÏGßÀýB1ó5&×Wó¼/d¿PÍújÊ.×4³_¨tnõŒ ˆt: Ã0ʪe>Ætî2ÜöËÃï5&˜íüækL@4¢ohƘ¨Ü7̶/ÐY}C=ï ÌeûJ4sLPj›ÙÊ[;Pý˜¾Û~½c`ñ´}~¨\v3ÞêmûÐýž/" š š?&¨õÜë±!Ö3&à¶_gÛŸî0òùü´|Z“““Óº®OÿÇüÇ4€éññq±NUÕi]×§§§§§ÇÇǧL‰õ¹\nZQ”ééééiÓ¹\N¬Ó4mÚ0 ñÝ4MQÖ\¶Ÿ Ó¦iÕö¯´®ÖrK-+µÍleV{î###Ó¦u]ŸVUuZUÕiEQŠîC¹ó£{Íf‹Ö˜žœœë'''gÔa¶}«9Ç|>/öS¥èÙJ&“b›RÏ£¼m¥cÈÄŸ™x9¦iN'“ÉY÷¯tîÕÔ«©t©msÛ¯\n©eóÙögkƒÕž[üÞOOWîW*õ ÕÔ«škÏç+ö ¥êݨ¾û…bækL@ײÚç}!û…jÖ×Rv+õ •έž1m«iÚœîÕk¶¶_O»§cÈpÛ/¿tÖ˜ Úókô˜€Ž3×¾¡Ùc‚ééÊ}C¥};±o˜ëûB£Çsپ͔[V©¼…°È÷»Ô3üoÿöoÝöç:&˜íºuZÛç÷êËna¥û^MÙ aCä1AkÀc‚Òëk)»Þ1A­ç^ ±ž1·ýúÚ~Çy<Òl´t:-f¯äóyüìg?ƒ®ëE³Õä®ëBUUA×u‹¾“Ò.ï«(ŠpÍŸ­.Õn?º®—,{¶uµ”[nY©mqîòŒ£ññqŒÃ0Œª~¥ó3MSüoFQ¹@!‘k©)³í[ ¾ïÏx¶¨¬rÏc½ÞD94ÁuÝšB¶•:÷jf¤´"•®³ã8Üö«(·Ü²ùjûD¥68×s«¦_©Ô/ÌV¯j¨Ô/ÈçÓè¾û…bæsL —Ìþ¼/d¿PÍújË®æûl4²_˜íÜæ2& ›¹\®¦ó* Z~è¼1Á\ϯž1A£ú†f îdæú¾0c‚¹l_‰fŽ Ê-«÷¼a'J?ÿúÕ¯tnÛ¯·Ý—»nÖöù} ú²«ù> Ýöë){>mˆ<&h xLP~}µe—ú^nY#Ͻâ\ÆÕ·kÛïHá1ŸÏ]G—,Y‚t:=ëõ}_ÄÒ•ÿjm0LmÐõ•C˜¦):ñ¹ï¤4MƒišH§Ó5ï[ ¾ï—íÊ= “É`É’%"vv½ƒÖz÷o&•®3·ýö¢Ïa¥~åþûïP[¿0—zUê€ùë¸_(†ÇA=Ïa5cÛ¶¡( Ç)ÊãB!\kÇ­·ýΠÙc‚Fõ ÍÜ7ÈÌõ}û…æ0v øîÔ¶ßèv¿ní Ú‹ùjûµ”=Ÿ6D´<&èe+èT!Ðܶßq£ïûP¹\“““ƒã8xôÑG+vš¦ 5™þFFF`šæŒXÿLã¨ô°Vû Ë÷•bËär9¡Î—Šß\ißjPUµd"z üóXKßRPãããÈçóÈår5?§8÷V¡ÒuV…Û~ 3Ïa¥¾ã„NP¹_hD½*õ Àüô Ü/Ì„ÇíI=Ïá\ƺ®7ìe‘Ç­·ýö¤ÕÆêš1&¸oˆ3×÷îšC#ì@åg¸Û~#Úýl×­Ýà1A{Ѩ¶_OÙóiCä1AkÀc‚öe¾lh#šßö;Nx¤¤¯tTU…¢(EɃéBÉ7O×õË(1)3hšUU‹’™f2¨ªZuCˆ'ÊUeÆ‹%Œ¶,«h–b5ûÎF2™,J¾J³_€òÏcµÈÏ«œÜ5(Š"fK”›ýUnÿø¹Ó5o×Y:•®s2™ä¶ßÂ4¢ ƩԯœvÚibY¹~¡õªÔ/óÓ7p¿0´'õ´¿¹Œ t]G6›Ô‡d³ÙšC›Ìç˜à¶_-ÜöÛ“V4ªohƘ€¾ÏÖ7Têâ÷¤Ýû†¹¾/p¿Ða' }êWÎ;ï<±¬ÓÚ~#ÆñëÖ©mŸÇ­I£Ú~½eÏ— ‘Ç­ Ú—FÛ f4â¸ÀâmûGU}m‚ap½½½b ¡i>ò‘`åÊ•H$Ðu]šè†ÒÕÉdDâû¾pseæ‘‘$ q݃ ¨éºû¾ÞÞ^±o¹\ ÉdÉdétZÌb¨vßJ;v*•‚¦ið}†aÀó¼²Ïc¹˜Ñ2†aˆ2ƒ ?~t.¶m£··ªªŠç™f2†Qqª‹|îíü¬WºÎ4c„Û~kÒˆ6XŠrýJ|fŽÜ/È÷¼ÞzUêÌKßÀýBékÅc‚ö£žö7—1A#ïë| nûµÀm¿=iÕ1A½4cL@ç3[ßPn_ªw'õ s}_à~¡yÔk'ªëW:©í×;& z/†¶Ïc‚Ö¥m¿eχ ‘Ç­ Ú—ù¶t’Χ™mÉôôôt÷»e!µ–f2Q¢WºÈªªÂ¶mø¾‘‘±Ÿœ–\¨™ùG¾îÕªæ®ë"‘H`zzZÜïjïY=û–Ã÷}áŸ-«Åó<AUUKήŒ×Ó¶µîßÎÜö[“ùhƒqº_)E¥~Ž4¶oà~a&<&hZíw½æcLpÛ¯nûíA«Ž M3Ær¹¥ú†Ùö-µ»3×÷îšÃ\Ûn+ Úñ} Tí Ú‹ùüÝ^¬v¹\Ÿ ZŸfÙ ¸í—Þ¿Z:VxŒCÊôØØ˜P–‰LÓ„aM«—ÜY•c®t£ËžÏºÎ¹ñ7rß…8ÏV»– ·ýúËžºÖÓ~ç“rõâ~¡³à~¡1e7ºÌùú]¯nû·ýúË^Lc‚…¼Í8S`±õ í0&¨—ùèW¸íw‹­ÝÏWÙ‹å™eââû†úËnµ÷…ùØ—Û}ut\¨Õr¨ª*\¥É=šÂL4“r1÷eæ:»§ÑeÏg][‰…8ÏÅr-[nûõ—ÍÏ+÷ ÷ ){1<³Üö; nûõ—ÍÏ+÷ ÈbëxL07¸íw‹­ÝÏWÙüÌrßÐipßPÙ‹áyåv_‹Æã‘a†a†a†a†a†a†a˜ùãˆfW€a†a†a†a†a†a†a˜ö‡…G†a†a†a†a†a†a†aꆅG†a†a†a†a†a†a†aꆅG†a†a†a†a†a†a†aꆅG†a†a†a†a†a†a†aꆅG†a†a†a†a†a†a†aꆅG†a†a†a†a†a†a†aêæ¨fW`!øÂ¾€ÑÑQüñͮʜٷo–/_ÞÖçðÜsÏáùçŸÇªU«š]•ºxòÉ'±nݺfW£.žþyŒŒŒ4» N*•ÂòåË›]ºè„çû³Öà¹çžC?>ö±5»* J'Œ :áù:£?ë„sØ·o>ÿùÏcÆ ͮʂrÍ5×àðáÃͮƂÒ)}G­tB;­•¹Üë#<_ýêW›]õeçÎø«¿ú+n‹îÿªƒßÚ÷ý`.,ƾ ls¡Ö{½Xm†]tN=õÔfW£.:¡]wB;í„qÇï~÷;¬Y³Û¶m›s‹Bx<|ø0>ö±¡¿¿¿ÙU™3CCCèïïoësÅèè(›]•ºØ¼y3¶oßÞìjÔ}‹‘åË—wĽk÷sàþ¬5 sXlt˜ ž? 3ú³N8‡¡¡!8p ÙÕXp>Üö÷®V:¥ï¨•Nh§µ2—{½ß8€?ú£?â6±àþ¯:øý }ßæÂbì :Á1j½×‹qL‡jû6Ñ íºÚi'Œ;¾úÕ¯â?øA]ep¨Õ6¡¿¿===Í®F]ôôô´u§A\rÉ%Í®³ˆé„çû3†©Nyþ:¡?ë„s`ÒwÔÊbl§‹õ^3ÕÁmbñ°ï5S=‹ñùè[Ä\XŒ÷z.¬\¹²ÙU¨›N¸×ÐN;aÜñªW½ k×®­«ŒEáñØ ´ûà „®Ý;hv˜EL'<ÜŸ1L}tÊó× ýY'œ³x蔾£Vc;]¬÷š©n‹‡Åx¯™êYŒÏG'Ø"æÂb¼×s¡Ãbp¯;¡v¸£Â#{<2 Ã0 Ã0 Ã0 Ã0 Ã0 Ã0 S7,<2 Ã0 Ã0 Ã0 Ã0 Ã0 Ã0L àºn³«P,<2 ô1Aˆÿ=Ïkvu†a†a†a†a†é<ÏC&“iv5æL"‘¨¸Þ÷ýfW±,,<2 Ã0ó‚ïû³þ& ±]__‚ (ú?d2X–ÕìÓa†a†a†a†a¦Mð<¶m7íø™LfΜëºp]·¢£F=çF6ØR˃ €çyE#*¿]`á‘a¦ ÐPy‘ã8⦯¯OlŸÉdà8€pÐ×ׇT*°, étžç!‘H NÃu]d2™º~ì†a†a†a†a†Y<ø¾?«=1.Ž5R,³,«¤ðHÇ('JÊu(UZ?[ô¸JÞžžç•Î8ã lݺsÚ†a˜Ö§\_°Xú×uÅ„üCà8ŽðN¤Y74;'‘H “ÉÀ¶m¤R)±¿að}¦i²,xž‡±±1Q^6›…ªªepÚ} Ó¾ð˜€a ¾¾€û†éûûÃ0ü~À0L Ú‡L&ƒt:-¾APäEhÛvE¯ÂL&SRè²m»¢­R¶™ÊÐ>³íOΕĻj8JÙZÉÎêû~]Âc9IùK-§:‘ÓJ¥kPªlß÷ñóŸÿwÞyçœë,°ð¸mÛ6ìܹ³äº¡¡! cppÛ·oÇÄĶnÝZó6 ô>åú‚ÅÔÈ?<ététZü0ÑlúÁp†aÀ0 X–Ã0ŠÊÈf³˜œœ„iš0 ãããÐ4 ccc®ëÐu–e¡··W̸¡cÒòL&ÏóŠŽÍ0ó †êë ¸`˜Î߆á÷†aÌ…L&SÑŽ7W¶J•,ªÉÇŽïã8NÅrÊ s–e aMÞÆíç8N‘8G"¨,<–:Ù>Ë¿EÙ©$¾/‰š¥î ƒåYZ^.Z9¬X–Utüÿñ—Y´%Á7|³„°HuÃ3Ï<ƒzXáqxxgœq†††Ên³cÇ ```ýýý¸ñƱsçNìØ±£¦m†i]fë S?@?N4“Äqd2(ŠMÓŠ’Û¶d2‰l6 ]×aš¦(CFQär9(Š"–%“I€¦ið<𦡝¯‰D®ë¢··–e!›ÍÂq¶•Ö“—¥L¹>åÊT †Óp?À0í¿0 Ãï Ã<&¨˲* ³­Cö=aûÓ´6HÛ¶…½P.Ûó<ä§§‹Ö—‚öÙ½z5þó7¿ûұ˅ýî‹/Š:’HFu#g ²¹AÆ {¥X« |øsŸCÂ#r¶ëöÈo[ö–Úÿñýû‹rOÊ¢,9„ˆ¼š¦‰ýÝÝ%¯ƒìÝx÷Ÿý™(Óq@Q* «ß×»ŠëŒ‚àú›ßü'tRuLDxìïïÇöíÛ±}ûö’ëwî܉‰‰ ô÷÷‹e===ذaz衪·a¦µ©Ô,–~€~D©#wš¦Á0 ض MÓËåÊîŸÏç‹„ÅjI&“0 ###ÈårÂ#2—ËÁ4M˜¦‰±±1Œc||A ‘H@QضÞÞ^ôöö"N q’~Dé3‘H »»[Ì*ªuFýË3vR©”¸fétZ¶ ‚ hfW|¶O§!Ÿ[=áš †êï ¸`˜Î€ß†á÷†aÌ¥¼gƒ<ê„G ®W]þ­>ŠÉóÎvϸÈGð¶ë¸ãppÍŽqáS¶}ëñÇqÇCy#Òg<üªã8@伯3‰”rÝ}ßÇ·/¼P¬¯$ Çq011…8e†iIFGG1::Š}ûö5åø•ú‚ùî`ß¾}BÿŒ2ŠL&MÓÄwÏóŠB¡jšUU…"¡ªjQ9µŠä @„mBA’¼"Eå†×u122"~pEëºH&“p¶m öÑu¶m‹íð‡[.€ “É$t]9,)œlPUUü說*×1Áþýû144„žž~?`5ÃÃØ˜˜Àþýû›rüf¿Üwß}ÂÀÀ@Å>‰a:~?à÷†a›aóm†óA¹P d3¢hgÓÓÓb{£Ä¾eìK®ëBDIr˜Z¹ÝÒ÷rÓȆUÅýRÚ§µW\!Â¥Ò6dÿ ‚{–-ÃÓ“âøt>®ë ‡²SЍjYYàÔu7|ï{Ø×ß`ß¾‚]SU‹®mï8ïíŽ;NØô†ðè¦Yä‘Hç¡( ¾³t)´¥Kq|ôýî3ÎÀ¯ÆÇ±“Òo¡öÖG4 ¿‰DsÏóðõ³Ïƺ§žß127“Á»~¿ýŸÿðƒÃk£ª€¦áßÿýß‘”Îùñýû‘QU¬ëê7Žb÷wàåÍ›1±b^‘î=seA„Çfsì±ÇbÆ ظqc³«Â0M¥§§ýýý¸÷Þ{›]•¦°|ùrô÷÷/¨Q!]šD?€@ø#GÂ#…YÓ4‹~äãÂc­ÂV­˜¦Y¦•ŽGˈaÃ0`š¦ X–ÏóÄ9¤R)¨ªŠ|>˲ŠÃd2‰t: Û¶…øšL&Å5Êf³bÛ‘‘ñl†(‡ÄJ˲Ëåà8Žð”$oNù~PhY˜Ðu—Ë£ó¥BüúÓàF‹«ilÛ†ªª‚¤ã8°, Š¢ˆP¹²Á¶m!¤êºMÓN§…'l&“išB¨¥ëAõ$Ö4Mq,0ÕhpE‚°<“kÇŽ8ùä“qÙe—ÍësԊИàì³ÏnvU¦©¬X±ýýýؽ{w³«Ò–.]Šþþ~¬X±¢ÙUa˜¦²qãFôôô´m$…zY»v-÷ ƒÐPÿË_þ¿-2®“á÷† a›áÂÛ  ‰g2™LfÆ2Âæ$C6,òÖ£eG^p (BDtGØÔdÈþ¹ôoÄÞ½{q*$OEɦFv=!JFõp†aàï}/Û“­‘lh¯d³ùÁÄ9¯xÝ넇 išxâÔSámÙî•=vâ‰ð}}}}¸ìî»qŽ”’În?æ@ÓàEy#}úi —ë)+ï^]¢Hq–eá¢o|.€'ÈËPU±~Å xž‡ïíÝ‹—¯½¿ºÿ~LÓ5Îç±Çq°ç߀¢(XûoÀýâMÃÔUWö:„L&Ë÷‘ ?öàû<ärðUO¬Yƒ5¿ù NxðA<|Ê)XúÅ/âÅw¾°ëÐ!q-Ϻýv¼ùä“è:HŠýÞÞ½xÚuÑsçÀÑGÃWU¨†?ðÜÅ×õL. áñ˜cŽÁÙgŸ 64»* ÓThöжmÛš]•¦püñÇ/ø¬¥t:-¼GFF”÷Â#¯6™ÙŒ@ó%@Ê"h9H”#/MÂÛêmY–ðÈëîªÂó’B¤’¨˜L&…ÐFb[|€DžšŠEÓ4…· ªªÂ{2“Ɉܙº®‹øç~!™LŠA•Å}ïëëÛ“ø+{jš&It¨ì±±1Ž–®¢(B0$”®/ ¶²—$Õ›„T:çR!xãžô¿ìJÇL&“¢>ÿôOÿ„;î¸G}ô¼ðœpê©p]ÿzÙeXzð ž_µ ‡‚ ÜWU¡h ÓÄÛ¯º tî¹À /àèK/ÅË¿ý-Î|ðA<¬ª°4 guvøéK/Ù,&$oÔcn¼·¿éM°ƒ'“xåùç‡ÆêÝ»ñ‹W¿'}îsØðš×àá÷¿ûöž¨*.üÅ/ðȇ>|æ3xÀêÝ»±73àÕR$¾¹ÐRÂãÎ;gˆƒñïÕlÃ0LûÒiý€ëºÈårÈd2Bì2#·{ x` {ÚUËB„­õ¸Éd²h½¦i!èi áº®ià3—ëÏç„¡GóùðÿO½æ58óê«ñ0€=/¾(êý›7¾ÿ99 €àÑ®.À00ú©O/¼˜xõ«ñàõ×㣿ü%¾¨(BXD2‰·nÅӷߎ¿ýÏÿĈ#§¦ðP´tÐ4X‘ƒÂ‹[·âà[ߊC{÷â‰mÛßT+?ñ œù‰OÀZ¾ˆlªªâ—†ßvuÁ~ê)ù–·à†={QU › ]>Šßô&˜š[Q ’Iœº{7%¸:—C&7×xõÏ~†»Ï9¸òJÀ…wß—/¾Û®¼¯[¿oúÉO`¸úá‡á$xû/‰¯¥R€¢àÇŽ}è!<¿q#V\z)œz*×]‡Ÿ©*²t7y$¾¦ª¸îÁ1’Ëá´õëëz6X 6PšMOô:::*Ü›«Ù†a˜ö¥“úò²£ke9dÆRb[¹8äÍF®kÜ+‘r Æ·‹°:WâuÒucccŠth@ß>›Í"›ÍŠœ›ô>ŸÇÈÈHÉý¨¼l6+DËø9Ë÷¡X¨ëÞ:©/`fîÌÖι`˜Î‡Ç ÃÜ0 ÃýÀ\('<~÷—¿òy‘Š€ðH vJJ×spéR@UED0Ó4qw·XÞô&1áýG-„JMÓ è:Ö¯_/¼%©n¾ï‹P¨Gu’É$|ÏE‘¹(ÕÓÃ眃5Ÿü$Lâá+¯Äq‡áÐÚµ¡=.™Ä‹Ë–¤WQ#ÓÄîÕ«UÅå»wcÿþý8ë _À gÅÂ"€_ûö|ýëXÿÊ+XñØc€®cý­·”n*ŠRöÊ»ß h|ÓÄ1O=Ø6Ö=ý4~ò“ؼ|94Pœü±áÀ‡?ŒƒkÖà¥åËÓÄgªA˜&Ö}å+Øü/ÿ‚ƒK—"¡(È0¬Ýµ ×¾ðB˜Ž):«¦¦ðÉè^¬zðA pþO` Àë"ðgŸ Ø6 „6ØËW¯:BoƬ玃¿ím€ãà¿¿öµ0¢ãjÞ¿z5Ö?ö>vòÉ83Ê%Y-!<ÀÀÀ†‡‡155 õÒÕÕ…K/½´¦m†i_:¥ Pž‰DB`rÌj!Àr´z.žV¬_©Øöµ¢(JÓwá…b™¢(€¦áìO~ãããø›¿û»0w ´þÙÓOÇÔi§Ű7ßpÆÆÇCQ/™ÄÑÏ=‡ÉóÎC2™,‡4y^U±¿»–t>g>ÿ< ªxáž{€(Ò— @(rÚi"%“øPWà-çž ø>>?5$¸bíÚ¢{­( NCÓ´Ðy"Zž°gíZ|ðŠ+ Û¶u_·bä¤N:€oz*EÁgœQ÷³×2¡VqõÕWcÓ¦MèêêÂÄÄÑ]Øj·a¦}é”~Àó<äóyd2™º<ÍTiÆQ)|ß/éq·P¸®;«WÉcS¾6Í<¦õ蔾€a˜ú˜­s?À0 †¸/`fq÷¶mC×õж3YH”·+ìÙ³ðÃ#B4×u]‡çºð<Éd²Ø–Gv?E®ëøíñÇ‹eš¦ÁUUxTEÁ#_\T'MÓàžvÖîÚ%Ò!]½w/î9æ10€WÖ¯ÇÚáa<10_ÓÂrì]»Š¢àíŸÿ<~zø0‚#„ ÀF(ŽÝ¯ªØ k×â´©)x]]"ôë€:ãØcE¶t)n\º:ÂP¬¯¾ûnüL×q«¦A€;úh¤üùªUEu¿îùçq§iâå¿ÿ{üòÏþ i„¢æ™¾ÿøõ¯qágÀ{î9(GƒîÕþýعf Þwûíøýï~óœs [NW=õ^ÿì³PUªªBÄ6~ÙeB‘VQ$£s&NýáñÆ?ú#(¾_Ò&Ki—Õ—þÂ[Fh£Hp¥ m¯¼òʺÓ3-¸ðøH”4NWWn»í6qB7nœÑ)T³ Ã0íA©¾ û9Ä€ýç£ÐqTi¶0÷0˜ÍÙCÁVëõØìó`𠆿Þp?À0E§½0 S;ü~À0 Àc‚8Žãˆ0§@i{ Ùçz{{‘ËåÄúø¶{,€‚Ž»è"x™ `ll 7Üt9d³ŒÄ*À±g…CT`$<*,„"™ à¬÷¿Oœz*à™õë…ÐõãÕ«ÃÀ+ŠtwcÀ0` ÐóÏ`ŸuþiíZîêÂGPðd4ÝÝøÝ÷±ï›ßÄu×]‡BÁÒ@(â©Ç ‚†!°Һ?9âüLÓpùîÝ=ç(““‘®ã…Ï=‡Ÿ>±r%ŽÜ°~Wî‹ö÷O>+¿û]hš† ŠDCØxÜqXùÈ#¸zùr`ùrÄ­¯öYüÑ+¯@O&C¯ÆØþ‰ŠÙØòw?öÔk®¦i%íÉñçb$¶žöyßûÞD¢ó|Ñ2Åc®w†aÚ—vìÇI™éÇTQ”¢áâ?³y ¶b~>ùJÕ¿(,ÃÌ‘vì †i<³µsî¦óá1Ã0÷ Ã,Î~ÀuÝ"Û mÛÈfCI* ›ÅÁ;….N‹pš@Á†&§§Ï=÷\¸R×ñÂYgá… ‚å#ïzðÅ/âŠ~_S¬9xÇGá?=‡¢Ÿj•¬BðèçžÃÔUWág¯=NœœÄþîn\øÞ÷ÂGèuxä‘GbÍOŠUQ½äp£ BÏÆG»º Ke’çŸ`ÉþýxÃóÏcßSO = iJõ ú‘°GWãœåË_Z»éöÖÓ_õ*¬ÿÁ€†!¼’ÀH÷AQ”0¯elÿkW¯F÷Ò¥˜îê*é¬ñºgžªiâžT²—˜é¾—sà0 £è»Z\ ƒ»oß>ÜžNãÊC‡J–óÃþ?üá188ˆ¹Ò29†aÚÏóËå`šfC… J {Í#å¸ÙêRIXÍc’a†a†a†a†a˜ àû>Ü(<*L׬ …°ÈF··yžÏópâ‰'v¿ðB¸‚<ë²Y†ÀÓëÖºŽÛ¯»°æàAœýÆ7Š<Špñ»ÞUUqô…†å#ô®3¬Ý»»/¿'q®Þ·ð¿{zЇPìùþ÷±aÏa/$aQ¶ž{ø0òÑr’Òhýk~ò\½|9 ÃÂZå‘¥¸-§œ¸.T”ïÞ¾r%ÖÝzkti”¡PÐZNøÓœrâ‰"Gc]׫¶éÚ¶]2’ Œ³:|Äm®‘W+|à5¯ÁEÇ7£|×u‘H$pæ™gâ´(7ç\aá‘a¦P’ål6+fŸÈhšVÔ™Ïæå(—[‰jËi&•~PÉK”a†a†a†a†a˜Êø¾ß÷‘H$Šì†¾ï—Ìß÷òñÇ#¸®‹c#oÐ}'Ÿ®ŒlvÉ(Œkà±õë±ôïÀ++VàÄÉIÀ/ßùN$¤2'Ï;û»»ñòñÇCG(ª…·îî0ãâÇöíÃå»wCA(X*½ßþ䓸pbš¦AQ&•xãÁƒ¸êÈ#ËžÿY?þq‘°g(gyt§(\©¢(¸à¶ÛÂsNΔ+UUÅ…gœQØÅ9e²Ù,Ç©éÞÑ9Wƒëºe…GMÓJ¥J:tø¾ÞÞ^ø´>BoG×E&ßô {ÿ~ìùÉOfì¯( ¾óàC>ZÓ¹Åaá‘afޏQ‡MâY¥<…Š¢ýXhšV”r®´rnDµÊ0 Ã0 Ã0 Ã0‹ybqÂÀ-Sj™ïû°m[xqÑþò'X–…îîn¤R©fŸ*Ã4Ù¶XÙÆ&Ûwwà‘ßþžç ;a‘M. ¿éº.N8á±XUUáñHK*ùð‡>„y$¬înôvwãÑ®.xÅÅÓ¦¦0yÞyøÆÖ­8qr:ŠÅ¹¾în(ÞÖY¡‡_´| a8Ô''ñ¦ „öQ ©J¼fÙ²ŠŒzL¸3+l[꺾%Êû©—Éo(;Ph(ïMéûþ¼Ú>u]/i÷¥û_ääây£qêÉ'ñw¾*yĦÓá6A€]·Üß÷ad³Ø½z5^ùÁàº.lÛÆÿy÷»ñÍ¿ÿ{˜¦‰w|Ýõgá‘i[Ê)þ퇘l(¯c:.ûcµ˜ágœa†a†a†aÚL&Sö>N#‘H “ÉoŸL&ƒt:ÞÞ^d2ôöö²,xž‡ `YÒé4lÛ†çyH§ÓÂxNûvww£¯¯¾ïò,ض ˲°dÉd2X–Ã0Ä$pÚ§···èÿ¸’ã8H$q‰iY<Ï+iç¦ö"CÛQû¡©ÏŸy¦È©(JQû}âüó¡ë:Ÿž3¦iŠõŠ¢À²¬"/FÊ]¦( ÇÁØØ€Ð«1“É@UU¤#/l6 ˲ ( ²Ù,4Mßs¹œð”Ìf³…œwm*™L¾ïC×u¤Ói¨ªÊÇcÐõªÅ^ÅÌ/¶mCUU8ŽS$¤SˆU |”1]בÐu ‘€ŽÐfüäÊ•ø·mÛ x"íêÂúßþЛHàî /ÄË(x<ú…<3ÅCòlLwuá>Y„ȸeO+ó?P7Z.Ül-´^{iQàû3Ä×YnŽð Ýõ½ïáÄHÄ-…ì™Xj]%[>|ù¾ûp›®‡ÇÇ£ë0 KÇÜqÜ @Ò²ðÀÊ•x~ß>üäŠ+ðÉC‡€oüøŽ;ðGûÿø1ñ‹_`ë¹çâ…5k°Ìó0¼f Æóy|â˜cð·W_¥†Çò}L¾õ­x²Î,<¶ ò@€f-Ã|­+Í‘MªªV]F­b\&“) 儽³Õßu]8Žƒ\.E. ,6›Í"$ ‘/¶WEÌè ¡‹ŽgYV‘§¯¯###<ˆh0®ëÂ4M†Qµæ*=ƒíp¿Ê&S®¢î"‰ô"è߆a†a†af!!amfòøt: Ëå„ñÛ²,ø¾/–;Žƒîîná=EÞ5¦iŠr‚ €ã8H&“ƒ‰Ö‘Ç¢¢(0Mš¦!‘(d‰#›§®ë…\m†˲Ä6º®Ã4Í¢‰ÏÉd²dn6:g:¶ëº0 CˆšäqIö´VŸì] d۬ƣœ“ƒmÛe¯'³pÈB¢mÛ3r _<ãK÷SÓ4Ì#£¶5¼~=¦£E«wïÆ†o<^>úhh(BÏÆ¯<ý4°reQQT#Eú®Ä–¡ÐXIˆ¤gp¾'xž‡ÿûö·WÞȲ€È^?+® •‰Þ^ìÙ»·âñUU =pßè~W¹®ëB/ IOÞvÖ,] xì™gÇÁ7~üë_ãŽÿùÚ×âÜM›€±1|ï¸ãÏÃêµkñÂÙg㓞è:`šx⤓pç?þ#–.]Š7<ˆß‡aY¶\½?ü!6}6μñF › EØdO®]‹GGëºþjµÅð}¿Hí§Ä¯íB=¡k yAÙøÖóq¼x²^šyEëäïr)¤Å«§P4Àò<¯( WI¢c©PªTV)âÛ«˜Ý‹q^®£çáé»î*k3¿ñoÿn%} Â܉„ï}ßñå/ã,Îe2ïD×{,¦~ô£0Ô©ë}}˜úã?†çyÈf³ø÷óÏG2™„eY8ð_ÿ¥»¶mãÚÝ»qÁÔ^8ë,œq÷Ý8´q#àÇ/¼€›Þüfœ{øpXEÁñÿðp‡†ªëáóϺŽWV¬€ã8Øø©OaÕ1Ç`íWÉd(Lº. ªÇ™ï{_(8šf(>6[Œø ¡ÕEÇxýäYI(OFv//åV^I|+E¼®qÑ4.4Òwš5åy,ËB"‘ƒyðDbbww·˜áN§…礪ª"…®ëÂÓÑó<1‹âÓSè ˲Ð×ׇd2 Û¶Ñ××W6©¶ã8"Î}6›¢6'án µ„Wêóêkgq²ëÎ0 Ã0 Ã0 Ã0­F&“ö¤¸€F¹`dddÆ6”3.—Ë!™LÂ4MŒ!—ËalllÆ;¼,*Š‚|>_µ-„¶ÏårPUU”-ÛÛ*90È‘¾æB|_MÓDˆGùšPKb­ëº"‡eoo/º»»á8úúúÐÝÝ=«íÓu]ôõõͰY¦R©¢óÍd2¢<ÙÆ—J¥°dÉak$ç²3’cÕ–“M™ê×××'DVŸÉnJN ò¹Ðùýæ7¿™ó5g„¦áÀI'(„äf:AÄ÷QUµàñHm9ú¤Ð©#þð„ÿö·˜Œ6wŠ“@((Æå§xèÔJBb¼‡0P^¤œOEÒ¶Ét:×½òJeAÔó€¾¾ðÊ¥HíÚóðºõë±nÓ¦pe‰uÔ^7Þr Î;å”Pä‹Ú^×­·â]ÇC_ü"ÖãŒË.ÃKwÞ‰áªâ¿.¸g½ðÞ>5…ã֮ŕ?ŒïwÞzÞyèîíʼn¹\xO#ÏÆ‹_~Sùv}ã¡h˜Ï‹ê«ªŠl6 ŽÒrèzqxY,P˜l,<¶ñÙ%4ã¥Z(®ù|ÿqpêSI8$ÁWt<ú^«·%Í#úúúDôƒOßifýXËɳ)$Íâ¢ë$‡u Í3 #LêÕ_×u$“Iø¾/dÉdš¦!—ËaddªªÂ²,är9är9˜¦‰‘‘äóy†1ãüÓé4’É$òùS£c}k©þ—© %<·Ã9[Œ¸(Të-Í‚˜ëŒ Û¶K?(Ì¢¡ 4¸‘=[}åòI$çIŒ—g†E)Ú‡¶©t\Ù3MQ”¢Á …{ A›º€~ØåP™ââÓ¾¢(H¥RbGɳÇA>Ÿ? ò OÓ4Q^2™œqÝMÓ,ºrÜ}3òMÊ÷‚„ÒlÌ=ZQŒŒŒàí³Å·f*B¢²YG§\D?ÎÍÈ0 Ã0 Ã0 Ã0AŸd;Ù‹R©”˜¨.;*жžçA×õ"û’išEvÆ\.7ïyÕªAÓ4aÇŠÛæÓ¡‚ŽE67²ßQd2Š@Ìô*#ï!Ê…©ªªˆjF¶B²SNNNEK#,0‘èKN$Ò±åãSZ&]×ED5º~†aÀ0 ôööÂq^6ž “òdV²;›¦‰k¯½VäŽd‰gqÛ/Ý‹"ºÜ}÷ŒrHTþÖþý@”?ª 5àÐtr ^EQ°ê oÀYNjݘ)^tÜq€´\C(>Ɖ‡U¥Ð¬ ¥++å€áº.–}â8¸qãŒöêû>¾ú‘¦ ]UCñ0²ãA€Û/¿“ccð5 Ç÷ôÿx(Àù~(êEÑ Ÿ^·+Ex;N­\‰U>ˆ®cÅsË–!mYèúÊWðJàˆðÓo~›^~ÿìgËÂ¥wßçW­Â]·Ý†óV®Ä‘kÖàÅ‹.ù|ðAL®_7=þ8Ž|ßû€¥KÃzFíï¼ü_—Ïr8Ês!nÓžöxläÎ%ÞÑÔê™Vëöñ¸ä•f—ŸÜ)Æ:•”‹Pþ#.¯§¼†”?‘:çøÌîJ‰ ™LF„J p ´ÕŸªª*â¢g³Y1[H®‹cË!&hÐøÑ§ÄÚŠÂJëÉ[2Nü|ä-qâËEòÚ2Û¾óï¬á)aJQJ,®†r³’æJ3Å?zΆa†a†a†©Ré‹z{{…=Œìf½½½è‹ÂýQ”, X4Òu]DÄ’©5/âBA‘M¤”M¬^ñq¶¨hÙl¶(å\l4ñP¥2Š¢ ™L"›Í SÓ4‘ÍfÅ_|2{%¡O¶¿Äí‹´Œö/wÏÉFI¶Ø¸3 íûÞ÷¾—EÇ3›ÓŒ Ù ÷îÝ;cªªPU£Qο•\( NœžÆúõë‘à! ×nÜEQpÎ›ß z"è©yý«^Uôîv9 KÁLѲQOÈ÷ÿð‹ûÂÑKµg _|nWÎ?é¤Ð«0‚¼™ï¹çì>ë,üø…€(Üð¾‹/Æ<€‹n¹W~ìcøùë^‡‰ÿïÿ ÅÆ ÀË==€çáÚË/Çž_þÿ÷Àì¿ÿ~áeø•ÁAL]uŽÛµ §>þ8¾wË-8üôÓ¸îè£á8òG? s2FÂâ9W^‰ï.[†ÉSNÁ³üÇ8ëýïǺÁA‘£qò”Spê_ÿ5–_}5–¾ãa¸T¹ýÅû&r2ª7ã´q›LŽ+?ö1{ùå¡082h~qá…xæu¯Ã97܆QU”PPÔ4\üéO‡9å<‹• ~¢ ìþ,<.0q!1žÃÑó<јâÞyfÍeHÂ^92™Œ8¾ã83<åãA€t:-êì8N˜¤6ªc\Ä‹ ñ󦺧R)‘dY)@$ ¤R)ö@*Ïð¡ý+y\Qˆ üq•s:ªª*’g†!¼&éXr|t:¶%ê-b“ò1Êßg ÅI‰¼ë¥G¦yÔzOÚ}ÀWΛ7~~í~ž Ã0 Ã0 Ã0 S ~“Rö,Y²@é|\†aÀ4ͺÞç*äÍ7ñzÕ;9!la¥lp³1vøµ«Fx,U_v\˜fKFÈvú½k׊åOœz*–½éMâ^ù ªxpÕ*!D=ÝÕ%¼5@ˆ>BïÄx˒ﺎ…ËÙH¹‰O<ïyë[å‹Dß™L¦çyAÞsýõxô+_A*•ÂÿôO€×?û,àyxé]ïúúpìw/às?ô!¬Ýµ »/¿o>çLŸx".>þøP¸ó}\xÆP=/ üô¥—pߺu¡—$€Ï<÷>Œ[}¿»÷^ŒCÓ´P\t]˜¦)ò!öööŠØñ”Üšr/ÊaLûúúÉdÐÝÝ-âÐÓì9©|ü 0>>Ó4Ål-9œ) Pœ1>8¡zÐ>T×LäZ­ªêŒÝØØXѱh`G×J«¡šïF >¨ °ÆsS2¥‘ù*=#0øcœa†a†a†aB;U&“v·‘‘X–%RþŒD†ï¸=«ÌgÞÄz¨dçlÇIÊͼÎÕD^+µží6óOµÂ¿ìT f@2ʺæàAœ¹j€P<Ì¡ƒQ”>eâßçÍéyÅ^ŽžæKDØ^Žúÿ÷\½|±ðÂCAUUø¾cW¯ÆÛN=Èd°çßÀ›?ýi¼ø©OaddoÄ£_þ2î½÷^ì_²?zòI<¿j.8òÈ¢kÿÚ{ïÅM»vaÕªUX’N‡uPUÀóð³GÁ7¯¼Ð4ìýàákn:t=›7º.t?üßÿ?xæ™B=M0 ¡/a±DÞÅ’}™ªvœÐç¨fW`1ŸÉ@‚¡çyPEˆ~äaHë(¦q<'$)ø³ $$:Žß÷EžB5eÅÞÞ^Q®eYÐu]„"µ,K„-%E9¹µçyB`¤zçr9ºÔó<1˜ÂÆ'»OËñêËån¤;ÞpãÞ£2Ôض]vð//›Í ±¶T õVBQ!jS‚jf~X虂<d†a†a†a˜ö%$ 1‰Ÿ¼ÓÆÇÇ… €°›Í& Ñ„z¢ZP³Å<² VSßzíZͰ‹Õj/¢:Öš2IŽHWËù–²/QYÌÂoÇ0yÞyâßù»ÅÂì²eP|*únD뀂YŠøÓR<¾2Aø'Ÿ§ë qîÔSOÅš÷½O¾(øõüzücL\x!Ž~õ«ñØð0Ök=ñ`ÝÓOã+® Ó4á_p–.]ŠñSNÁk^|w?÷.Û·ˆläŠa„åÉdŽ•BF‡†ªÂ".®ùÚׄS’ª(Àø¸pšº"™Ä/O:©Ð‡’£“ª6,Z§Á L (@$:’øøÆè^0ÕÁÂãPIä¢&N#5EQàyžëÈ“Í4Í‚yãÑ&¾^Î I3¦’ɤhH4Ó€PC2™,rÕW###âJT}Y¥:Q9rfËÉXÀ"’*ýP’i©cAÐ6³Áª¥šœ’L㘋(~¼št|†a†a†a†a‘ÿ«Jªñœ#'†Ùh¶Ø8[½J]—z„Ç…ˆRAÉ:ÖzŸ›yܲ—ckŒ( °fÍÀ‘\ –Ñ·X— ë¦R{ô<ì¾ãŽÊûÇÚäø‰'ÂqœPЄ çº.î¼új|ü±ÇܸçÜy'î~î9‰ž8õTüÎw€D¦iâï¿ùM¤ @×qÖ±Çâè3΀:6†}'ŸŒÃ]]PM3 Ój¡ êºÂ#ÙlxÝèTUDtÄúDUUaš&·Ó2ÂãÔÔ®¿þzœþù8ãŒ3°yófìܹsÆvCCCb›­[·bbb¢ÙU¯H|öQ %O¥Î$™LBQ1¡\‚²W!5 ùGH­J³è;PHÐlY–?ã?bô]íhæKµ” wZë_­3™*mOÇ‚ äàªÖN„Ã,­Ú¸®[4 QðZ>w*ÓZµ/`fa©¦/à~€a:0 ´o_àº.z{{‘N§«ÊÛX-ñrªñ\[/ÀZ˜/±q!lwñc4Âsp.Â#·ÖçJQhš6Cxlu»g»öðØ5×À›%¤2EèD÷#þtÑw Å¡T“(ö€¬=€s|¿ØcÑóŠ„ÈãFG±|ß¾ÂzË£¦iX¿bºûúŠŠÜvÿýÐ4 Ùl+î»éÇÇó>(´Œ~÷»P8t] ÒCþúþûñ³¿ÿûPt4Í0gdÌY+~íPekEQØqbháqhh£££øô§?íÛ·£«« W_}uQç044„ááa bûö혘˜ÀÖ­[›]õÄs8Ê¡N‚Ø@y²°HÄ4¨ÑP"ñ0ý8ÈåRNHò‚¬$šPøU¢Þ†FÇŸO* q¯Ò8t«;TUmùßN¡UûfÐu]¯øüµ{cn_L)Zµ/`fa™­/à~€a:0 ´_`šfM)æƒv «Yc!®q\ l5Qw6äXí4¼ÝûÙËζmd2™Øj%´ßKÏÿÁ5k  (R,6 3…ǸlÝ(káýßúîß¶­° ö¼ïÛ·/ÿö·%÷µ, kÄüúסXÙׇ=_ÿ:ž¸àh–%4'N: ž{.®_½ÿú–·àÜ; aQ£ö¶í[ß*äX¤çVÓ€JvSNIÖTZFxÆ–-[pÉ%— ¿¿7Þx#¦¦¦0::*¶Ù±c000 ¶Ù¹s'vìØÑìê!‡d”=IhT¾ï#“Ɉ¼ŠñN_þ‘5 cÆåQL&“"Ï"í „9#“É$²Ù,´(Qj¹îxÎÅ…þѡΡR¨‰Z‚}}}p]·ä9ÓùÕ"vTÊKÉ4ŽVíâ"v£žU`öçò±–bzzzÞÎy¡ >ŒadZµ/`fa™­/à~€a:0 ´g_@vEQD?zÿ'G‚Jø¾ßö+­>¹Z¶Á´z]eÚ± ^>þx! 9Žƒt:]´^×uáñ¸zõj2u÷õ×#@(2ºœèâ’Z¼·h”%ûþûï/^E¡VÿÛñÇ£;‘(^oYØóo@×u^·G®\‰ÝÇ xnܹ»wïÆ¹O? 3_u øŸ?ý).ºå¬œš*”¥ªâº•ì3gÓ0ÚHXïDZFxŒ3%?dvî܉‰‰ ô÷÷‹e===ذazè¡fW·ˆ¸«:Í|q]·H€\.'¼‰¸ðX*<ªëºð<†a@Ó´b­#* %É*ÝŽ«a.¢å\…ÎR?Žº®‹#ããã%isùQea¤9´R?03Ø’ÉdCÛ_;RjbÃÄi¥¾€a˜æ!÷Ü0Ìâ„Ç íÝÐdøDdˆ'Áqdd¤¦rjMIÔ.žkµØäê^Z´•mFµÞ‹¹ÔµÞó“÷o—g'N+÷q&O÷Ü⃫jeñã¶4G5»Ä 7Ü€¡¡!LMM¡§§ÃÃÃØ°a.½ôRÀ ¨ó€+V”Œç,óôÓOchhýýýœ×ó‚`†ð„‰mÛÈårB,Bq6#¼ªª°, ¦iм•<ût]‡eY bÜ—Ïg¾~¸¨Ürå«QÒØJç;[øÊ8âñ8<<Œ;vàÉ'ŸlvUJ2Ÿý<ù䓨¼y3.¹ä T]¯Fz8ÊtÊsÅ´›7oÆpúé§7»*%Yˆ1ÁŠ+°}ûöfŸ*Ã4;wbhhO>ù䌶Ô*Tê Èx0×1Á¾}û°yóflذaÞߦ•ÂÎ;±OÎÍÓBÌ÷ûÁwÞ‰;wbpp6lhöé2LÓà÷ƒÆ½¸®[râò|Û䪱qµ‚w[§L<ŽçD¬U(n%膔u]Àqð÷ûöA×uéyE¡faE!j™…Â×;&háqãÆBa¤«« ;wîÄ–-[ÐÕÕUwÙ+W®ÄW\± Fjt„ìí¨( ’É䜓ÿÊP¨B€”×É¢­k…ÆlT3©t¦iV}]ÛuFO=P¸Í›77»*%™Ï~Ö­[×0¡¡SËÌâdûöí- IÒJtʘ€aZ™ 6`ûöíjvUÊ2Ÿ}ÁªU«xòÃBx_¬ï—]vO>`ðûA#ß<σ®ë°m»¤Ié*¡(JC£.‘­Õì`š¦Áuݶ´¯’ÇW§@ããÅ:&h¤Í°AÀ0 X–U¼BUÃÀ²×¼¦h±ýYó8΋/¯ë–Ïêï¾öµÐ3ÑuC/C]‡jY=t§üøÇPcª udów‡ñk®Áq‡aõ /®‹gO??øa¤?ó¬zÍk€¥KC1ê“TU #ÂÅÛTö Ààà`CÆ-jubbW_}5àº.n»í6ÜvÛmưìªÛ&È ›ÉSʶí‚Ø\…GUUaFYAQ½Jßš¹Îô©w°Á¢cûÒªý@¹ìí80f˜v Uû†aî †á~€a ýúÇq„ÍɶíëE)kg m³jE˜lËìûJ½©tš}ŸZù>´[?PŽ ŠÚ¿lÇöýÞ÷b×E‰eK,Êå¨"ÌíØð;% ~¾_ønYð}}šVœÛ1ŸÇÊÀÙ;wâÞ/ãšÕó°û‹_Ä–·¾G^p]tQ(,º.öïßW½þõ€ibÍŸü @mEQ]G6› Ÿ?M㼌DK;vìÀÔÔTÑLCr•Ž'-åÝì(ò …R‚…S”ó0Öóc¢ªªðv¬´MüûBÆ7Ÿ¯Ð”¢¼?­ÚP†a†Ví †YXªí ¸`˜Î…Ç ÃíÕd2ø¾_·U ðÑ4[d«Ù檪ª’hù\¼¹Øžy[ÙöÕNý@%ÊEAœ:í4¸@‘·ãÑÏ=‡Õ»w G ±ªbÂc%ï\Ï+Š`Û@* ®+¼¸áºEÛu=ý4V=ÿ<\ËÂ#/¿ŒG»º°æ;ß™LB7M蹜¯¼é&l*a"ºâÙK&9´jÑÂc5.Ñò ž vtt===M­¿ìZO£ëºB|£ÆCЦiu â¡UK/¡g­´z¸Ù„[fáiÕ~ ‚¶3L»Ñª}Ã0 Ël}÷ Óùð˜€a õû²Z–Û¶‘Ïç¡(JCDœvÉÛØhêµÁÌ·(+­Ÿoê½ÿ­ìå(Óêý@µÌæ¨3uÚi¸jj €×½ò þ൯ëtr?ÖL<¬«LÌ&§ÇÆpß_ý^~ä|å±Ç0Ï®‹}7Ü€G¿ò•0'$€{O8W­\‰Sßö6<ÿ†7à©)œÿ_ÿU‘Jϧ¦çn$T•év0-!<ö÷÷£«« ×_½X6::ŠïÿûE1Ö0<<Œ©©)À¶mÛÐÕÕ%’È6‹r!hF€¦iPUµ¨3ŸO!ƒŽ7Û²ù<~­´ûL-¦~Z±ð<étºè™nuo^†iwZ±/`fᩦ/à~€a:0 ´v_àyúúú,Ë‚išENògœjì`³Ù×â©–˜ %È.”À\ŠFØyÛE¸nå~ j$XW×ENE]×±lÙ28ÑfÿÚÕ¡Øzæ1ÇѰ֞N¼é ï¾%û÷ãÛnÃÑ8v÷nl9ï<À÷ñ=†ÓþôO±çű÷ƒÄeï{TEÁÊ .À}‡‡^K—JÖÂó.÷œ±ðØÑ5—&&&°sçNtuu5$ùrOO144„ïÿûX±b&&&000€-[¶ˆíqõÕWcÓ¦MèêêÂÄÄ–Dv®ÈÂ#ýïylÛÞ‰ò€b¾@£L2Ø…"i5 ºLçЊý€eYУXã–e±èÈ0 @+ö Ã,<ÕôÜ0LgÃc†a€Öí ‚ @"‘¢#°ðѵÂþÖ,êuPX¨çy0 žçÁó<$“É9=s­k=ç(ïÛâc«öU lA„áyiYä1ýÌúõxF@3CªÎ¹¥;;»nÖ4“¥(¸ìÌ3q­ ¼pì±XuÊ)Àãçå—‘øêWñ7ÿöo¸æˆ#€oÄw„³{7>ª(¸<ÊÍxðoÄÊ#IJsÏ-G׋ø2‹ŠŠÂãÐÐvìØK.¹DÄP.š]°aÃ|úÓŸ®;VòÀÀ.½ôRáÝÓÓ3à º«« ·ÝvFGG7nlzÇáºîŒ°¢”(ZŽë.‹“óýãWªürbä|Ò?\LkÑJý€ïûpããã;, ³èh¥¾€a˜æ1[_ÀýÃt><&`h;À²,(Š‚d2 ˲Jæuô1¥fØ_çÂBEåk$­ØTMt½)4³¼ ^\¶ @±°XêIªº¥Û¶ð¨Œ\ø?BDÏŠiââ}û0®ªPz{]Ç ]]8ýÞ{á" ñúùþëÎ=©în|oùr@6›Eow7ËŠ‚w~à8ö¼ó€èÚ ÚäùbOYáqhhÛ¶mÃ%—\"¼'&&pýõ×cÆ ÄÔÔ®»î: aûöíuW¦ZÊFxY6ЏèHùàÇA2™?þÍþái‡˜ÝíPGfþi•~À¶mèº^ò¹l—Aô3­Ò0 Ó\ªé ¸`˜Î†Ç í×ضl6+ì‚¥ìq›!PíKÓ´y‰¸Ôjv7]×9²S­ÖTC@B_ô¿®ëð,{Ík ªª#Ìôp”©IY…Fy™ª†ù=/¬“ïÃ÷}†%ýס(©ª¸Ä¶qË•WB¿þzÀ÷ñWÿçÿÀ4M|é£Ås÷Ü˲àû>òù¬œ—aŒ_*,PÓŒB†a†a†a†a:Ïóày^‘°UÉ>UÎr6›a§Ú«Éƒ¨ëz]¡¦ió*ˆPÙ Ô±p4¿ÈºA×ü÷'œ¸üòË¡#Úê=¯üã?}ø>î½÷^@QpÛÛߎéOÄy'ž¸æ¾û°û¬³Ää‚ÂJï{é%@Q0>>¾à^ÞLûQRx$qqjjJ,Û±c€0)« Ž‹1Ì*P,NxžUU¡i{;¢¶AR§¨˜ö¥”ÀH/ Ã0 Ã0 Ã0 Ã,>ÇA2™,læ"’Í&ZU#jišÖâW»’ËåÄõ¯Ç®™L&çdGnĽgáq~‚ ¬ýP‰®ùÔi§!™Í‚¶ÒQÙã±fTG8€ço¾Ï¿ï}ØÝßætÔ4ܲw¯È¯zìîݘ8úhøŠ‚d6‹?üþ÷gå8ŽÐ=`šH§Ó3<9[¿ÆíyZ í»R«ÉÚšßê”I\¤˜å@!¿#…V/ ’‹ß÷¡ª*<σEQæÕ¥¿]àÁÓîÄgï°·#Ã0 Ã0 Ã0 Ã,^lÛn OŸl6+<-Ùþ¶ðd³YíÎ0 ŒÍ¹,MÓædG–Ÿ¹ÀN ó‡çy%mˆ¿ë]EÚ€Ô—Ùrï<ÑC¨ÕÛ+\¿{7Vík…Ñ}õtß?>|õ‡qÂï( þïG>‚t: Û¶ñwög€iÂó<ÜüÔSPUµdÞU tÆ çÜó¼BHÅ×lBV|ýlb^\htbÛWòò£²gۆʡs¡efŠu²0iè‹ÕÅ•¿6•¼ Ë]›rb¥%}:ÑþT'@BÚב¶£ºÅÊÞèÿtôÙ qô¨r+ÑÓÓ#B¬nÙ²ƒƒƒbýÐÐ#åå‹ ÏóÄL×uç=†x'c{“1-Eüy¤—òrf†a†a†a¦³‘S,¹®[uHÌrc5™MÓ,:n%ªAˉ Ìâ¥oI¦2¾ï­J}Áu×] kqœ›å`Xþë—ðâ‹/–µ÷ÿ 8yãîÿð‡aøèÚµ¸¬û:(¦€dSŸú<ÏÃøøxuåÀžz,ßçsôsGlùq<Ûôè“Öd¡pñÏ..¶ÒÉ‘g!å$±,nf•¿…¹ aTI z/ºÑzY@ÓQø¨<-ZïGËé;Põ2Ñ1!Õ—>“Ñ>#Qy#(„HõŠsyDÀ, —™èÿBoE=*/‹‚Gb>úÓ¢sOFŸ~t\:¶ýIãQYtôh{åÛJÇ5£Oòʤ:HÛéR]¢ú8v"V<³¢úç¤e=wî܉­[·bbbB,À 7ÜP×;×uáû>|߇®ëBígÁ-„¯Óî” ûëF šùÅa†a†a†a:² ÌUt,…¦iö”a:òx€ã?G<ú(ÔÓNƒBäMr<«ÊŠî8€Üÿd2€®‡âãºu˜^r ^}Î{¿ ø¾Øö‚ÓNC_&ƒ×¦þÏ_v~Ð(ÝJ(d‘•…‚"…¥n*2‘*žRðø#a«^©®jTV&úŸâÊRHQ'Ú?#[‘ê@Ûg¢å¶T. $õ"ÍÒ(ˆŠ&Bq–' v>B¯À !O)+‰ˆrü[ïÄ$ Â(-#GHÇ¥ëB⣋‚Àg¢òVT¤cÈ>m¥~nÈ‹’¶•·)çŒOª6…h•ÏPP'qÔ³GáõÿñzÔCYÇ¡¡!8p[¶lÁöíÛqÉ%—`xxCCCu°Ý¡Á†çyP¥(¾1 nX˜aÚRϰçyÜΆa†a†af@Ñ‚ €ëº ±u)ŠÂ63†épD~G§Ÿ~:ŽzöY¡†F:Z\ªH<2›ª ÇU÷܃%Ó½¸çùUa~GÇ2¡ËàÃË—ã_þá_w=³ŽãàÀ«O Ë2Øÿ.  Kâæco¿{á:Ó4Ã2ÒÑ~ !<ÔUʱ˜Š¶!¯H JB g$Z(ˆ—9¼ãfYÅ^ƒ by2R˜US:–­§Ü‰&ŠÅ¸8Y„&A‚DÅ"y"–#þÔH³Öy05–?þñqÜsÙ=5¤˜’Å 7Ü r<ö÷÷cÓ¦M3B®.6h¶‚ã83B«r¨Õ]×yÅ´5¥Â©&“IضÍÂ#Ã0 Ã0 Ã0 Ã,H8ð<žçÕdëRU54Ì3 ÃDPJÀ,ÂHœU+ ¾ d«T”p™ëâë®Ã’³þ§ÿŸõÀÅ=@"Üçãþîn\ðö·#ÕîÞøþOâšëÏÂ'WaÅxT¥C¡’w¡Vxò­“8aÇ …P£: ¸JA ¤¼ˆ¤ª’—Ÿ•“DÁÅÓDÁkÒ.B¡׋P¼£ð¦™h=u½qgñrR8Tº¨*f •²WŸÕÜNã¡J«!î5(›’ ÌŒ«ÛFüþ„ßãÅe/ÖUFIG ¯ÚÓÓS´¼¿¿¿ÙçÜ2™ŒøŸâ3Çó;’÷#Ã0íã83^(( ‹ê Ã0 Ã0 Ã0 ÓùAUUÅääZ&"«ªŠl6[õö Ãt4i¡TŸ1'«bäÝz5Fé Nyë\´ë"Ü|íÍ…í÷éP“IA€ááaÀª§Vá“?‰u§~(Äl„¡GIΠ0£$Äy…8 XûÁµ8ðïB¯Ã>„ªiZª…7¥Ð¡²GùÇPð¤P©2TÞ–rÆC‘–BVn•h?ù’ 2$x’gf£¥E.Qïû°,Kt$<Ê9à4McoG†éÇA0Œ™©5Mã‹ Ã0 Ã0 Ã0 ³ð{”¸Ó)IàÉÈdÛÈløc/þéE>‹SŸìZƒeS|oo¹ï-ØûÊ^¬ºgU!¬ªœÓò;š(x#&†A5P0ŽI„'2¼Ù(ÎʘRa]\˜Œ³PæY6Ï …ÇÍ›7—\~ÆgÌXöÈ#4û\æÙÓ‘¾›¦9Cx,–‘a˜öÃuÝEN5@ù™VqÏ>òУe²ÐFËUi9yü9Òz…ˆ äÍGž{ry4ö¡cÉ=2MÈ¢z‘X—ˆö#/Â@:žmGåP”%m{ÊáÞ-ò`+Ñ' ‡´ ‡t]FPÈÕ- §tÓ(L4ó¤ºW“ „"bÈut¢²äëXnßÜîÝ8bïÞ*ŽÄ0 Ã0 Ã0 ³¸ð<Š¢@QN±Ä0LUAÇq°æëxqÆ"›ZÕ½Í <NQ€µ9àCÜL¸ÞÕBƒÐO€SžÇo.=ˆ×|8tÜ!>¼»}oû¯·áèGÆús×ãÅ‹_ÄÒ¯/-ÌJ'ƒ}×P0ªÑwª°\i,eC\%á0N)¯|¹’Í®@gRRxìééÁ–-[¼2;vìÀÐÐ&&&ÐÓÓƒÁÁA\rÉ%EÛ axxSSS¸ä’K088ˆžžžy«åv”¿+Š2Ã#ŠC­2Lchf?@í½=IL#ŒŽPI(Dëe/;…H $\QØODÇtQ•ž‘ʦ± ‹²wŸ/}§²)Ü(yéQ>kÊMu'3•=;79$<•“”މêO!æ«ÇЄ¯øTÙ³2[Ž ß‰RƒKÅy®5„ÊjPQ¾¾–Ð÷*€+÷íÃèUî±ð´â˜€a˜…g¶¾€û†é|xLÀ0 °ð}A<¿#Ûý¦ù´ò˜À÷}hš† pê›ßŒ³.¿Ç¢`o*ht ‡Võ2ÀE:p½$#«Û=nfUU?‹ƒ7IJ=a¿t`÷|POàK‡¾„S~õzûÆcqômGãp×a<ùÀ“Ø{Æ^¬7ÖÄE9t*Ââ‘E±èˆØ6„[ç£zj*™¶¦¬ð888¸ Ù±c¶nÝŠÁÁAlذA|w]WtÔqP‡144„­[·â¶Ûn›÷ú¹®+º®Ï$†©Ÿf÷rîÖV!ƒp€Ò‡Pd²Ž,cÑwòÀózšÑ~y:¯h; ª£Xh$¡¢#رO¡—޾Òº1i_…ÁTBŽŽAÞ‚“Q)uå…6@%¶O|3…Ãj©$ÞÕšÓz.´ÖÓ×<šÝ0 ÓÌÖp?À0 †šÓA ì€åŒašO« |¿ Àýþ„Ä„zžÔƒ€rV™gÌk°€ö€µ*pŽ ¸*°Ü‚ˆŽóâž± Ëhèíí…vº†»?ÆYûþKO[ èÀ‘î‘xωïA÷u‡†2ÊSD§l`£pd6j£VoÁVðpd„ªs<ŽŽŽbç΀ 6 ¿¿¿¡±m[¶lž–ýýý8pàFGG100 ì`Ä÷o¼º®cÇŽ3f7Ìäí`Q†bd˜ù¦Ùý€ëºuíßhP’B!”¨ð·?ð÷9 ¬€>Æ“Ñz à%Ø'•«¡M!#}’MlÊEŸ”Gš<iò“\}j˜9Γþ7¤cÅCKTš3šŒÎ…ŸÅG³û†aZƒÙúî¦óá1Ã0@súÊ×p~G†iÚaL@žÒG¯^ rY2$¿(;QöJFÎiDLyÀËþ¯\à…9Iภx霗€——ô`ß)'ò,|÷£ßùãOriÀÿ~.8íœvÚia‘J‰zÄ¿s·Ç4ˆ²SSS¸ú꫱sçN  ¿¿]]]bÝèè(¶mÛ†ÑÑQÜ|óÍbÝ\˜˜˜v×_½ˆÓ<00€ 6Dy¨âÌŠ+„'æ|AqÜå0 Ã4–Véæ«Ë“—4„ž|äÑg Š”ò:›(äUôQðLJÿ 0.q¢OÅÞ†´ŒŽ <³±å󙱂êM8Uî—«r;¦sh•¾€a˜æ2[_ÀýÃt><&`h^_çud˜¡ÕÇfÕó<˜¦‰3Ï<·GëT ´G£Œ‚Ð0hø†´¡âOSl4øxÀêÕ«±ÿ½ûqÀ=€ÿr€eYÈçóã[dXìz4¦ÙÌæEÀA™QÖ㑵nß¾7Üp.¹äô÷÷£¿¿—\r n¸álß¾jHe6mÚ„®®.lذBø¬—§Ÿ~ZxkÎhÈ¡V¦ÆæÍ›ñä“O6»*e™¯~ž|òIlÞ¼ÃÃà v>$(:g:ePŸšF8îÈ cäЉ”+q áÐB3!1>VhåÞÉ@Aà¤óáW¸æAQ ž~úéfW¥,ó=&ؼys³O‘ašÊÎ;±yófÜyçÍ®JEæ«/Ø·oŸè f1C¿‰ûöíkvUÊ2ŸïwÞy'6oÞÌ"%³èá÷ƒâ÷Xxdl3¬ßfHžž´Lf÷"TƒX£˜V怗Èò§S*ð¨ 8ÀS·?…/®þ"Þÿ…÷#´¸Š¢;SPÞ¤xΣÙRÖ¶²q‘YHG«wLPÒãqbbÃÃÃØ²eKÅ\ŽýýýÀ¶mÛ088X—×#º"SœfÐuÃÃøá†ê*wåÊ•¸âŠ+æ”—Òu]èºÏóĬ†iW(Îy+Üç«€uëÖaûöíe×ÏG(ÊÛLá€BUákPT$A.[ã1ä<ЭJ©q ¿Â5íÛ·ctt£££Í®JYZqLÀ0Ć °}ûö–ÞÊõõæhYµjUÅ1Ã,`Ѿ\vÙeâ0Ìb†ßŠß|ßgÇfÑÁ6Ãu y?ûa÷rP0Ú …”_ÑwÀà P5@5€åp{Oà LŸ>S^«>pÔë‚®ëaÚ¨Ül6;³ßR£ã(æØÇÌÂàà`CÆ%=É}™b$W‚¶iD¬äøñ.¹äQ¢Ô,r©ž/EAj•a€f÷~¹ðŽ/äТ*‰GBÁ1‡Ù'1Ìb£Ù}Ã0­Ál}÷ Óùð˜€a`aûß÷ÙþÇ0-H;Œ ¨ï˜‘NÑDâÇÅn‘°o%€]>Ðå‡áÐà}a¢¥ûߞš>‰}ûöa÷Y»ñíç¾]°_F†Q²¨" ¯Æb#ÓJ ¤föôôÌZmSºqãF3ÅK¹ã ™GñmFGG«ªç\ð¼°0 C„YåO 3?´J?PïË…‹â±ƒû ôh4¢O9”j=Ø 9û…C­2•h•¾€a˜æ2[_ÀýÃt><&`hN_@¡V†i ÚqL A²{ 4úÑßN,4X8G{€ë…¡Ò4I`÷êÝøö/¾GŸ:Œ/<øÀ^÷Ìë …†ÊáQatd˜9PRx¤†Ÿ1PŠøËÿ\èêêB?†††055 ìvìØQFi``ÃÃÃb›mÛ¶¡«« —^zé¼\œxØEžíÄ0óG+ô‹½D@7ú”{ó.½þš/<<ƒ)E+ô Ã4Ÿjúá1Ã0@óú¶2LëÐnc1=0%­ð<ëOFhžÃaxÙ`÷'Âi ùì{>‹uëÖáÊ]‰µ{×rÐò¬~¦E))<Ò,‚j’©Ò6´Ï\¡XÌçŸ>6mÚ„Í›7cË–-E.Ô”{aÓ¦MØ´ilÛnHnÉrÄC+pRi†™_šÝ—ó\ðQÓî 5A?/„¡U+Ι¤X¬¤VÒr¹ZÖÌ]K†i—] „³¥èSV)y"'Ó‚4»/`¦5˜­/à~€a:0 ,|_Pm€a˜ù¡•Ǽü2.øÈGŠ', Kv:²½QײÀw£…$Ü¢k `ƒ*Œ}ÄG>€wß÷n¼ÿö÷#@€gV!ô­<&˜¸ôR<ŸHà¼GËÌ[Ÿ4Q¡ ÐCh {\ÀÖ;"áq­\›nu€ã e{ðpÚšÓ`Œ‚Š£`Óà¦f܆©‰£Ê­ÄC=„­[·â’K.A¿hÌÂyÆ b6A#¨&dk=a]kÁu]d³YñÃ,0ÌÂÐÌ~ ÚvN¹ }„Zž3 h¿ôßÁÀ_®Óà!@9À:]€ú1„B ŠPT´Qp‘Ô¤ÂSÒíh[¡p˜”öS¢å¹¨\òhLEÛ©ÆŠ‹$2Ò;}ZRÔèÄÊ)ƒ¤ ÖÑ%æyÓâuKGçeK×+/Ý0áŒ0ºÖ²‚Dj™ï­ å ðPÇAÏAÏ™i¥1Ã0Íc¶vÎýÃt><&`X¸¾Àu]˜¦Yw9 Ã4žVȦ%bÙ²eE6EåŒÈÔDÎ4iç3}àaø[8èk³ÀûÍІ—±€ F¨Õ«Wã¼-çAëÖ¸_bÚŠ²ÂcWWn¾ùfضááaìØ±cÆú-[¶À0ŒŽœMH¹Þ8Ô*Ã,jM šÝ ò®Ë¼ ð.Œ&4½:ÜPó'‹p ‘v´Qðr4QŒRÑ6V•„£dô%˜F7 ‚b¼rcÑÿ²8HÿÓÈH¯Ñ27ª%¿–C³*(„q¥mÕhy2úÌDË <,IÜ#¯M-*GŽ‘DADÕ¤ÿ)i¦\W3ÚÇŠþ§[§¢àj#b=ÄÕ´Tn¡×g&ZG^¦týôhY*Ú~ óƒ‚ØK¨Éèºf£ó'Ç{%Z®Ç>)Î/Õߊ®!‚iùú@¿ÝÝÆîy:1†a†a†a˜ö…†)‡‹Ð\# Ç­]‹l6[È–Döš NaÒ¿ €nØ£]pûxÁ°¢0ƒü~ö¸X¹¦i†ÚD0[í¦58ªÒÊ®®. bppP¸(>›°Tì»o_  Ã0 Ã0 Ã0LgCö@N·Ä0L9JY³y#9·£ŠB$$÷)À73À”Ü7G}Žnç†ÿA#oˆÿ5M+ØÑ¦Å9ªÚ ;]h,…Ͻ¦ó©ØÎIDŠ\½û «Æx](^ÏÆÚj„âO¢|ÑEâX©ã’çßtl]4&Ñž ?õ¯ÌRVÅ“GAü’¸Ù3¹è“D@ùÝŒfv©Òòl™²i£DÙr5„œ«oµ!ßjª[©sÕ VlNéF\It¥òeñÑŽO×]>5阮TVü™ Z¹ÚV->ÎïOø=^\öbŽa†a†a¦s ‚€m€ ÃÔFÌYI=ýC~M.BÙŒtØEáÆàA)\WسlÖ` <ÏC"‘Àôô4|ß#4²_Ó&T-<–chhÛ¶mÃ#<Òìsi(®ë}çAÃt>Eíœb©*( À¹ ð“@°0¾àr@µÕƒÍô¸Ç$hÍi|0Kå/¤/:Bi®äœ/^™åÕžpµ“I)ÿäÈž›·Ü¹U–Ô>3M‹}òÌ6†i}|à±#Ã0 Ã0LÛáû>Û†™·Â:ugôƒÂDrмEö£/ú@·L˜’„GxSï› }GC.—Ãôt8ã\Q”°oâî‰iŽhvZy !{?2 ÓyÄ'¯5…¼à d²€r@Òe6"¢þ„ F½IÍÁZHlª4°øªô¿ƒ0ÔfËx Åt ¶m×_HfômL1–”¯_óþ©åG½½€mét}å3 Ã0 Ã0 Šïûf•a˜ª‘Óµ¹I …(W²m/Ðvw…¼5ZyT±ÇA6›…ap]‰DBMUUžÁ´,<–!‚¢F2¹ÐîC Ã,4E?à> £¡§Î{ÃEÚ#€~GäX`†¦= ` Â[±î¡A-PhÎN…ÇYLQN ‚9dŒ÷< S˜uàºnÉòË•=§c¶;A$áu+u/\7üK¥Š®-€ð{&ôõŠþá§iDÇV½®Ž3óœ†a†a9j•a˜jq]·Hx¤L=X…Ð1!ƒÐ9ÁrìÐVwqì¶Ã÷DU âé3Ï-*7•J!N#d³aMëdCÓ‰°ðX†ø 't0LgŸl…<}YÀý`] ø=@îI@ <á¢X 3e å«¿Ã1 S”ã÷±€IDATžç¡Ýâ»@™DÁf€‡làq8`»Òá„UU>¡áçû.úMÓ„çy°, ;E1í e‚€g0Ì"bÆË 24À½È\ h{c`/m›D±‡¡hßþ¯7B‹  a†2è»ÃOµ7Ú^Üø~èÕ2ä¹#ÿ•#Z׃g6|? X Ï =›‚ üŒ_7Ï õét(d23…ƒîîШßÝ],nT y\‘ÈPJ˜pÝðØ–U¨¯ Ý?Û……¸W$zœqÝuXzð`³ïÈ¢ÆuÝ’†~ô#\øío/ ø¾ ƒô¸nø\:NølÚ6@/#A€÷nߎî½·äqøüç±öê«qèœsÏCøùð0Ýt€Pœu+ã•9išóÛ”:nTº4~m3™pÿ‘‘ÂuB‘0Ÿÿä (Éd(,NOÏ܇öSÕ™Ëåõq4-ìCè%S®[oo¸nÉ’â}H°ìí û•øùçó…íª FÛg³¥ëÈ´$–e•ô`ö¢öK8ŽƒL&3c’B&“iŠ!•ê&›ú¾L&ƒŒ4Þð¯hì+m ƒ½ ˜ö„…Ç2x’§3΂a†¢— òv5<˜ŒÕÑ¢³£u”:në}Ð^ÂŒ§5OgP†k-Õ˜ƒ –n³1½Ä¾ºtCu*~Êý‰…“¯lÐwœÐàÉÂ–ÚÆqJ‹aâºz¥×“˜¡ ¯Ÿ,´à7ìYVÁ‹'æù ¬oo!4bü\iÿîî°ŒøzU =˜|¿P~ÜÈ?2й\èé$õm» H.YÖ%N"QX×Û;S$uÝpºŽéti¯J ¹©ª3먪€¦á¨gŸÅéÿïÿi>q#µïºxó¾}…‘Xüðwâ¾»îÏjNcê’KðÄÛÞ†C‡ªŠ@ÓÂòR)LMMáÖuëŠÊ‚žçáu=†ÿ:âÜzø0nû_ÿ –eá¤ðþÿ¯œr μþzüåÿø;Ë*Û}ÝŸû\iqú‡jþ¥úÎãžÃä-HÞ}òº (ôQ¥„ÿ Û°®—èâÎ4­:!¯Z £à92RúXããaH&ÉÉpÝØXø'×K×Ã}ÆÇK ‰ñ>"Ú>íûp]Ï<óLãΑi(–e!“ÉÀu]8Ž#f;A ÄÅL&ƒîîn¸®‹t:t: ÏóÐ××ÏóH$Ð××Û¶Ñ××˲„!ÊýÆxžÛ¶‘H$ж£°ÍåD¿T*…L&ƒt:ÞÞ^ôööŠï}}}èëë¡¢úúúH$H$`Û6,ËB*•Û¥R)¤R)A€T*…îînôöö¢»»}}}èíí…eYèîîF"‘@oo¯8®eYH$¢<ª$ ñ~—H$ŤR),‰Ä~¹~K–,A:†eYâ|‚ (3=ÏC:ò2ö}_ˆÃé˜ç1—η¶mÏ>åk_JTž ª7{=2 ÃTçHg¦ZhÒÙ¡Ë4ÊÚæÈÌx¦ØxÌ-ˆŽšä§ŸŸy‘l”ì…Í´+G•Z8::ŠÍ›77»nM#NCUÕ–ñx P»Óíc#tÆâ¹Z S×uašf($Æx€£…‹<#"ª*Ñ3EAÐ<@ywñâš{Û^£×*À·R€m††k¢¯/¤<ÁökÀ‰jXÿÛ$ã}“œ;²ñuäµMžÓº^Ö÷}ض-ĈVóv:4#s´(ŠEQ„ <›Ùu]d2hš&Ö“' Qòlh×u122]×…¸æº. Ã@>Ÿ‡mÛBüƒeYÐu]fô,èº.„NUU‹„®|>… ( ÀçyPÙlAáR×uø¾ÏóÐÛÛ UU199‰D"! *t!N#™L"—ËA×uAÃ0`Û64Mƒã8p†aÀ÷}$“I˜¦ Û¶‘ÉdL&ẮXžJ¥Ä2YHõÂÂã ¼wšôž(áT¹ûêGÛ’x „iûÈ †À”Z°Ô˜üÑtéèX ¼2ª¹6¦^èÉðš[(¾î‚ â+4@õõ# ‹Kö(”ÓËf<ÅE£?OSðæäLƒ¹ ‘‡ê+Qe=‡•b,.„$“åCŽ–Ã0¿Rž~$¨•3^›fa6w©²}Adˆ-¾¦ÚL/ 2Â0BÑÇ00uÕUèzË[f–Qêÿ9@ƒ¿š~'惌ÆÉdRx®A4•Ja||¾ï#‘H ŸÏCUUtww#]+28·ÂïÙb¡á‘ð}^:Dô²¡iTçÞz+Ò®ÞÏ Àž~öÁƒH* >ûóŸÃ0M$, úý÷ýûnÜý‹_ ™Lbõ~€÷?ñDèI³#£ðÀêêÕÐuW™¦=(WDaây0Mg¸.nùÞ÷põÃ#¯(p5 ˆŒð¾ïã'/¾ˆÿèG3ûÓ E¯x›uœP4Œ‚÷°eþ?§¦Ö;>)€ú‹8:´ÜóÞê!³ià"¯ð¨oŒ÷y$8iš†Ç{ ¯yÍkš}ö ½¶ÔÆ5M+ò~SUUˆ@†a •JÁ4M$“IôõõAÓ4d³Y8ŽNˆLƒ(sü¸Íf¡( LÓ„išX²d‰º‰E‚¥ŒmÛð<ù|¾ï£¯¯OÔŸÊ,'Z'“IA ·¾9 à###%Eï¼ÔoÈylH”-w<ºVªªŠÉt]e/EÙ‹ETI¸M&“Pº® ÉĖeÁ4M!þÑ:<å±­£Oº×²H^”tÿèz’HK÷ÄßÞ(R‚çypº® OR:. ´$z’·jª3=—Š¢àU¯zÕ¼<ÿ Ã0íõ©,<2 S‘)]À‹Ë–‰Eº ¸: ìˆa7^ø~¬i…w` çòøŽû#¦]9ªÒÊÁÁAlذ¡Ùu\PhVA+Ìüjµv/Bí„^1çâm! +™Aí¢g»@q·Ka#úd„ÚN3$Z'ïcEådê@´^C¨kÑwº¿™h; ': …Y4ÊßË$ÂûEO­mŸDøû¦DÇ´£m^Z¾¼Ù—¿¥ ;¤úúï×Ñ}(Ù/¼9sUU]ˆm‡žy”#ŒÓe’ ï Ž‚r]‰d²´×_5”2êW0èA%îyTNPU¤ är9¨ªŠT*%f󗣯¯¯H€›žžÆ5_ù Üw¿†a̘ý/׋fÿûQÈAšõO;òÒ ãœïûÈf³Èd2³ƒ —d,¤!Éûƒ)2n’WDxÚªXFû’A–¼,È¢¯¯º®#™LŠz†!¼)È8Û××WäMbY–0è¦Ói\z饵ß{fVj GÛ®¼í6hwÝ…ßuuá_O8áyðUÉ<šaàé4E†fz9‘ÅN2êŸ=[éD‡Î9ÇîÞÉ-[ðæÏ}ù/}©äË =Ó2äñ” «*<É€íøÚ+¯. ài˜Í†m‰6ÎdpðƱì(¼d‘e/]+`Æó.–aN“j@îªD„j©U°žµ|ò -³¯ã8ÈårH&“š—k¶˜¡>_îÈs(ˆ_¦iB×u¨ª*ú~ Ajš¦hÔ—ÓƒŸù9¥ñMüY‘½ƒ ():(òÀ¤ßQß÷…0W %6‰ÈŒWʵ§zÚ°,6–:×rûеtcccEëé¼MÓ„ªªB€$AÑ4M8Žƒd2‰D"MÓ`LÓ^“t^$ŒR¿M^™ô[NBk|ì¡išðÚ¤òHÄ%oQº'”ï’ÄNªŸ Õ‹®õøø8TUÅ{Þóž9_{†a˜N¡SÒ.1 3Ïü@°wíZ±HŒ¶Ún„^Žy¥ð,ÙœÈö•Þ¡ÂøžóÍ2íLIáñÀÅŠ–ŸqÆزe ›]ïyCxÎÌ#¥¯¸wœ‚·c)§j/Z®—Xn!»D¬ ŠE®rµO:~•CDѶf•Ëk…Î?n†ðQâTiy;üè:(ºntn )ôh½ƒ‚øJ^†äyH×’)Ú>ˆ¾û(x›&£í„Îqv¬\òLu£ý ¼TÇPÈ+H:’,lºÒñ2ÑŸÕEþ‘êaK÷ääË.«ó®t¾ïCƒVx ÀÛWŒ LPPp‡4K¬Ë¢ î’·ÜU×Ë/·QÕ0W׬}Nù†ëºÐ5P¯~õ«¸æ¯®™ážIFÂ"cž¦…!$£Y­”3ö;Ž#BV“g ÍÌO&“Ðu] ¬(D1;Ÿ_$’¡„AÏófx3躎\.'fñ“ˆ×××'¢‘±-›ÍŠ0v“““"$œa"<Ð('_s9<š)yP¾-2ÒþTw˲DH9Yp¤ð¿dxÔu]ŒtnŽãc£ïûBœ€±±±"*“®ÏîÝ»ñ«_ýjn†)K5ùH4"”³z7.]Š7]uÎä`÷nœuíµp>ö1!>†zÊGÏ% ŒäÙ2ó Ôu€÷¨*öwwcÏ—¾„kþꯊ„‹ÙÐu]ÃIq]WxH©ªŠ+T#ªŠ¾Þ^al'¡<‘H„$¢Ü¬WÉf ¿Ó¥Â6GPAÓ4…'—¦ie7jù\N´7MÓ R¨éð„Äör5›¨Há-³Ù¬AI^¡tyüHâÑøø¸è'èztÈC‰ú¢øq©¯#‚ÎÕó<ŒŒŒÀ÷}Qz¦4Mƒá¹Ç ï'Yä` y¤Œ„#jòïœü\hš&&ˆÈï#†aT|Fåmi;òº+…,¶åóùš íf•½ eŸ®?]/9n9d¯FÙ(Dc Ð¿S?Eí˜f }„ÂP8Å┋‚Ç]a_E" di¼á4d‰4 Þoztün„Ú •: âœG‘öGT?:†,Ü¥ b$„9ÑÿäI'‡ýL£à!H׃êL" '­'/@ÙiGeP¸X¡‚S)(ˆ“Yë?)´!ÅaKG¢ë.çÀ$1‚`›Œ–çPðH|¤ãg£å BªjÑ>$2&Q:é>.D?êèù&/šà;Ö­ƒúÀ…“ÉåÃ@¢Ýg³Y!¤ÊÂ>õa4‚¼†)¿ Šäå“HuVEx3Qž5*®'mOÏ ƒ4Y€Ê'¯& ×™N§gx2‘("{ËÑr˲DŒ9„~f*#‡S¥…²‡šÜF+†K½‡”»_òý? ³yúÉùk=ÏVˆ 3WdáPö­Öè/o#_Ù#T^.çUl´áh¶òâ‚&yZÊue˜N¦švMã™x{’CcÏ%ÌÒœ w·È“úúúDÚú=™mÒ ÕÆ4¡1ŸÏ‹q E8÷¡q Mf ±‰çyØ´iS³o[Ó)õ<0 ÃÌ š¯µgÏlxç;ñ¬ô](„®“Íù²EQt-yÌH¿ìñÈ´3,<Æ_ëÁG(zÉsPIP$¯BIØ£å$Z‘¹HGAÛ HÃ\Ä*ò‚¤ýhˆKb ƒ‚"íOéàHØô¢:«Ñ'y^ ¡ÀHeSÈPªû8 ¡^5}˜éµI„$ÂÉ‘!{¥íô¨®Tm—D(Ò"ñ3þúìGõ¡ºÆs"Æçúë±ÿK™g#‡¸’dŠ€rþFùx²G¦‚‚8(3S•E¢²,FÇѼ÷Ïÿؾ}GêL<ÏÃ{ù¿âk…q‚Š QKS(Q:5Ú+— FE™[~±¨–kÁŠävòX£Ê]Ü…³pŽÛxqÇãx<¼üañÂ*çK’_r‰x¾#Û¶‘Ëåà8N‘QªT(@2üÓ +‰odÌ$Ï<ÏC.—9 )O h™LFxARL/ÇäMUêEP×uad{~Ñz ¡Fb y(Ñ ¾ò..Îd³Y1ð£ë'‹~²— Pl Œ‹6 I„úÏEÞ¨/’Åj»tÝh’ tãÃ3J-Ë‚—Jå^ëëëƒ廤¼kÔP?D}T__Em]Þ7™LŠºÈ¢,…±TEÔ¼—}ßÞÚtM’É$&''‘Éd„±UYt¥çŠÂ¥Òõ£üsñœnét¾ï‹>i tßè7ŽžyB M’)%_RxŒ.åÜ_$ d21ø!O á™Éd„Á^ÎO˜J¥Ä‹9 Œ###ÂûŽ<"eäsdГû乺âá%åk —_Î0Ȇ9¦ÈP!{骪Š]·Ü‚kÆ×n¸M&±öÇ?ÆÆpçOŠUgŸ=#ô=ûÔÖ EQf$!®ô2âVôÿÜë¯x/ÁÀ~^ñö¥BÁ«ªZ½@F‰Ä”xhʃšÍf‘L&E8aMÓÐ××'39ô1õgr¿è8ŽÈo ”ÔžMÉk›ZòÐt]_ÿÏÿÄ€ÔÇqêKÆFj÷Ô·Éí]²Ù¬5p’CÜë˜ £"‰Èf„R•E÷™Ü\.7Cô­ÔÅsñ‘à+?›ò ¦1PHภŽ,jÉ÷´ž°zryôüþ–ó¬$o›ZÅ09q» ‡6/…¡Úë!Ozˆ#¿KÆû®FÏ\<eX9,l;ÝK¦5)'’!•–ÓäDúNé r¹œ˜<·IêSéý…¶£ˆÔÇѳ-§e Á¯»»»¨^©…ÆcccH§Ó":~i FçÑÛÛ MÓËå`Y–èûi¢…Ζ'ùQ¾w+i|Då¤ÓiÖÞ4MñnE)è:Ѹ‰Â%S¤ŠÌBùciL•N§E;Ïçó"ZÕi||‰D½Q˜|Š:£ë:Þð†7àÑGmöcÕt¸odfV~~¼þé×ãô§OÇϲïBhHt¸~è £ªgýÒû2¥Ù¡ß'N€…ǵ†UP?Jg£‚Ð!ŠBŒš6 ÁJ¹ý¨+)çEG‚Vü••ĺ٠Sæ˜T'ИHáBã¨ÅHÙà˜/± PÜ(|«Ú3¾m|91[xÑJè(›~u¡»iv€oO|ßÇ«~5 ~²?´*áÑ@(8Úv(8jZ˜³Œâû–^ +ÉKBͨøì5Ÿ-2ø‘¸gÛ6\×E6›E^Íã¦nÂ]çÞ…ÓÔÓÐÛÛ+¼øä¼@qÑ“BC/¬ŽãáfÓL`¢îŠ¢`llLxzÐK1ÕŸÄÈx.1Át2rxaEQpð[ß‚àÇ/¼€÷_{-pó̀ˢ—‰l6;³/ˆÔ>yLò¶#ÞV²SRu† Á“ÀÚ߯!ù¿ÔûÄ…Ç»Ã÷"µ§x¹]ÆF!—(‘Ífa£  ‰þN¸= „޵܄/òê–s'¡1HÞ‡ú¢øøí?ù ¾.}—C ˜Ñ/†Q¾Ówf†E®”#QQ”’Þ×å(åi=׉qQ„<0¸ßm,$ŒSëx¾F ø·NÎK 4ΣB6ì—òº+E#òˆµ ²@ÏÅJÿÏ&NÆ¡6VÊ TJdl¤÷L)»ZØ‹‡©†¢<ÉRTzÿˆ k‰DBxý“w ‰\4¹‡r«Óo…¥¶ç8NÑo,åE§( ý„¾“ÀO¿TŽ\ŠÔBTè·„<ŠÎBŸò¹Ñû ‡iš"´z<Œu.—+™ƒ‹"8ø¾_4)…&ÉWäúÇÇ¥rsS?Cïttíè½MLißL&#î+ED)5éþŸÿùŸ1::Úìǰ©4*ß&Ã0‹ƒ“^: Çœ~ ”ÓPÈ}e ´†/Æå þ€˜„B¿Q䟴Ê0í r¸®j¡¤$vÙ(x…<„> ‚*­¯F“=ej Ñö#5–S‹÷œÕ·™ƒ”èØ ò*²C:S žçáÙÏ< ¼½Ë”ÂâVl£'ó%Ê/nÒ;#½Ë¡Jé…°R4 ˧æBÏ„ÿ²þK¼ìR¸½|>/^úÇÇÇñ…›¿ Ê |‡”3ª‘¸HÇ¡¤Šr}ŒÏèI”¤¹Tÿl6[dL ²f1!‡·|þÁ¡žsà”ÉI‘‘Œ‹Iår–Òä¤|>/ÂC×ãñ+C"hüÕ·UšD:Ûqè\…¢(¢ÜR¹zK žh¼žï¾ ÝúF†YŒ´Ê˜à¶×?‰k³Ç@ûŠs—tat4ÐõІƒ~¨ow]ÝÝÝ3ò÷2L»RÒã±§§[¶liZ¥¶nÝŠ©©©ˇ††0<<ŒÁÁAôôô`hh[·nÅm·ÝÖ°c×:À <…4>@aÂ:…0•¢˜ùÅ@xœè¯ú gL«±PýÍ=zâh…ÐÈeç›:N8`°màÏs€QÙ«OÕ"'¦‚rŸCaFFFDH¡D"!^Úå\&º®czzZì[êœrvP˜#Ú^ö¼°, žç!ŸÏåh)÷ÒM³œS©TÑñf¾h映f<¦ªbícÁ°ŠBrøòúwÏØÜE¨Å[’÷ûâﺮÃu]üÿì½{œU÷ÿ ·$’LRÃ%0&Ôä† PCÄ  Z-DvEК¸ë…äY©þ¹\óؽìžÝí–ì ë®Úw£¨+Ó½²ê*D»ÖGÐŒŠS!#·t‘0&SÉÈ ¨ß§¿U§{ú6·¾Ì|߯׼¦»º.çÔå[ç|¯s§Í…׆áÅ_¼w”hÏ.À¥A–Vœ8‹ü_„~ÀýÿïeO*¨ev ¥ýŠü~£bn ð~†0o|§Ø——ÈG7®Ê/Ïà,HÅF z€»p¦8aÎc¢F¥8­aTÒ¹oxþxöJ‡I:s÷@a÷ˆZhª¢FGÐ@AE(ì3ù~P1k¹h6+.{UÚôÖòìü¹%4Z—ÎUaÎ}SZfä?Ó¼ÔÉ_ “&Bƒ(¥ôqòëyÀÍÏÝŒßÝü;ìñö`õ «Å6É|;(x~ðºìMË€UhzJÉ‚zËÊËåjÞFQ”a‘'¤ˆ‹2XŽä+Wã±6‚5 “QD9j$ç¥ØxWŒ¼¼R=ÈÑ0Ú{F6€Ê)([–ÔÏó‚ºPt_SDùÇãAä;e.!h.BFE ïSÚ79« í›jR‡–º?å9J±®¥”|,Ý·ãa@“Û#¦qB-ÇÓ­V2‚–ŠH+År§Üñ3™LAÍp`x”w+3‘²`ƒÚcä—S¤#÷¦vÊèÒ¾ì¼w'~ôÇáÚÁkñÒu/á¼-ç…ýÉä÷—…Í{j^E‘µ»É(' ê-H‘?’h9Ý-1žÆ¨rïú‰¬ñØjÑ3™JÑŽäÌU8ÖT«õ`¤FæÉD« j…RŽÏó‰Dà8N`d²,+¨7hšfê”êF"‘ æ¯iš°,«`NR,7R©,Ë*¨±L©Wé»ü¿•Œ‹ÅµWË1žºÔGÙ“öoÛvM‘ì北2º®#™LNHF9ƒN©sGFèb&K½ç‰–lxd˜æ§ÙÆ+ž>àäpgx£,ÌOŽ5­lÄ# P$=LyÍ0'Œ}ãG?,ËÂí·ß^ò·¬Zºdwtt`ùò娱cÇHS‘JƒÞâŒ\$` LÍXnXÙZÓóɬÀ´+O\(×)й,ºôõ©ÚÜ ä‰K2™„eY%•–Žã ²,Äb1¤R©ÀP™Ëå ir¹Ü¸ >(Ò²,X–(âjQ¢% ¤jì?ÃŒ–fŒˆdo{þy¼üÖ·BpðÝï~Òu3îš1|›|úRçi™à'â£û¬ø¿dh HàÉ …qÈÙ áñ‡0¤µç·u 'QñߣÇYÍï—þæîY€÷÷b&àþI~Ýv#[Nü·7çw½¡q-¸ÿœ_ €AZÀ¬üú_¼/!0à9gçÿ¿bBf0ûƒùåúÓ ¸ûoвH ‹ç\ŒYÇgáés§áéEÓà~pÿ3ßWK¤•uÛ÷? Œ‰q`ÇÒW0sÛLí= Ïó°âÔ¢¦è4„™é|?Ìüg¡ÓÊŸÛ„Á/+ý§ùDþœ¥óŸ é·>„FCº&tœXþw¥hŸƒùßÉHJí6P:$_Þ7€‹¶^„¤“Ä/\ó¾^ø{6¿ßl¾?)àÁ÷<ˆf¦œ,h”­Á§ÞéÈ‹j¥혢Ռ^”ö(LM8Zår¹sZKd£!Ç1ºö­¢Ôj¹1Á¨yJ%è?)%©Öìàà`P£=N£¯¯ét†aßMÓ–‚Ó0 Äb±Š)C)Ë E9Ò¶@aV—jP Èrý¯¶Ÿ‰0¸Ë}A­Në!ûÉ[Π[Î<jÖKp †i^šiL ç_çüþT1WS:ü¾f ý¡¢š†]»v {wP½`Š|¤Ôå­.«†8©Ú ===˜3g®¹æôôô`ëÖ­%×Û²e˘244„Ï~ö³0MË—/ö;y2ÈÂæÌ™ƒþþþŠû>vìþð‡?`Μ9%÷M”+RND¦ò¤R?9„QÔ Óì ```‡jtSJ2‘r:„ÞÞ^ttt ££€˜4^ùâ•@[¸^ÅWü(<’Éë””;®ë"‹!™LëPÝDMÓÊÊ¡ñœ)Š‚®®® ]¥/ª5½ÓÚôööâøŽ;Ö覔¤c‚RÛ†h4Š”®ãõø|íõ×±æÓŸFü;ßvÕUÁ:o[þ6L˃»eQ¸­M9V·¸A­?ï+ùåK$ëŽ]‡«q52OXà+ÆIò€°pr€–Oƒê}$ˆÐi`ƒÌ¤×Þù€ëÛç‹åŸèÞ‚_;ÿ ±+c¸þ××jÉ(€£@ê]€{¦hŸ ús@û   Ç÷¯ÃSû8âp“|â­Ÿž‚¢”H§—@‚ÈÌ”rzúr¢q$óÆšŠ %ü?44„;v`Ïž=xÀ±QIŒuLpäÈôööVÈ%㙚r< >µìc<ÁÓŠÐy(V¼kšVÍUëy¨5óƒ¼ÿF"¢)U>ÕîïïÇÁƒqäÈ‘F7³$=?سgz{{qÁ ­­­êúã þ4M Ò9†UU‘L&ƒgŽþS­CÏóÍf¡(JňÉJuFkÓ鍿c-TKM\KªUrޝ(ãJQçÍnŒ§¨Sù{¥~ÖÒg‚ç(yîf*Á:Ãá:ÃJ´¹ûœÌ@˜±†¢<ˆHGETƒ—\2l{Šv”i†q#Ãô÷÷˘ lÄãÐÐn¸álܸ1ð @oo/–/_޶¶6ôööâàÁƒãRÒ²,Ì™3gBjK=zýýýU½*yíQÉs Â?¯ tLYÇ´ô ¿üòËnJI&RÀË/¿ŒÞÞÞ‚ÂÒ3Ìĵ{®‘7ùeãùˆØ(Ëõð‘» ÜŽ”üjqHH"I…aJË;gÒœÇÎÎËÖ^pXìÇ™+Ö•ëÛ’J’Ôê&Âòƒ 9éHǤa¼\6\ÒrÚ1ž Ë**ùÿNþ³À^²8ýtt˜–ÉÀG\ A¦Õ ´b*¿}ÀïÞzN›386 þc*¸=‡nTÓ}Ó¦MnJI&ZÌ;·bM{ÏóF¡ë:¢Ñh ôi!Õ[“/E´åD5Üd²ÙlMŠñZÑ4-ˆ’kE¨íš¦ ;/e0œåÝFÓÿRý¤HSu~°råÊŠ²`¢hNË傺‡ô»ªªèììD6›…eY£ªY|ÜR%Ê!?+Åå"ÆzÄ87Ñó”ÑÔÞ­Ôî‘U'¢/åÚWéÀóƒ«ñÊ+¯à®»îjtw¦a°ÎpÞˆÆó1 >ÂȤs2ÀóÄ X §þÇãÈd2ˆÅbÃkFZOža&‚5kÖ ££cÌc‚’†Çlݺ6l¨Xxuùò娰a>ûÙÏŽ©@+¥9Ú¸qcÁòM›6aΜ9i\ûûû‡…SWJ4* ¸Iqf#,Ó3*1@9ZK›=LJz†©…FÊGÏ{/âJd Ê^ ƒã^üŽãŠL&ƒl6 Çq‚|í4Ø0MÑhñx|ÌJ„Ñ iâñx0Íd2ãêMÌ0£¡YÆU±,<ûòËP¶mŽQwŸÿgázÊT³À?@Œ¢€ûýüò¼"ÐÜc€và^$6?ýÊûáþD(ÃÈx§0õ „bM¨çÿK%Ù%­«>˜?¬¼Ósti]2TR†'¿<а,baDjK6¿<–ßž""c·ò]Eaðf&¿"Ë©àê{ïÅOzj"§]ƒ¾]Ó‚cZã²XQ_M]3Œ(¯!ÌŸ§8sEpY!O ×Oaø0­ÜЭÜ~Ê­_ΰé`x¦V7ÿ7V3Ifö1‘T“äé] }*Â:Š@(»h_d¼£ôªdPT¤ef>Ÿ)I%Š¡ £_JZî!\Ò™êEë“1­8 “å¤KªÊºäÄ¡˜?}:.øö·oòýª”l†BÂGÙðH (dÙ/BUiÝR~cä3f¡ph”‘þË‘ô„i`)Å,íGNY‹ËÉñ–Ë×X‘–;Òõ.)IÆdOjG÷œ9hFj‘)lÛj=É æ‘¾+KEÁ1 S-3&¨€ã8Èd2)Ö²ÙlPó]×uxž7ªô¹ãI%CZ©9L­†·ZÒ‘6"·¸ý4‡ÉöÕÃ¥Ò:£Ùo+Ïõê% ZÙ8Ë0“f¼0ÿ€2À  8ž(×d@ yB)½K%™L®ë²ñ‘™”4<®Zµ ›7oÆÀÀ@ÁC]ê!§èÈz¤1Ù°aÖ®]‹n¸mmmÀ† †HGC¹hB¡DJ£aÉMеA„ƒá*+¿¾‡P»Dš7ÿ?%mOZ.YePXT‰Æèdp$Ce±|êÎ7¾x9iÀd#)…}Ñq©®tµè¸d˜”µ_ Â\kJþ¤lµjÿHCyÝŠOr<ߣÄr » ¾TÊKE ä~)%Î ]zG(Òñ(œ#%‡òÌÅ1<ìÁCöJè TAn Wîƒ%ýîI÷G¦Äº• ƒ5i^[˜ñ–‡N>„Ó¦ŸV:m]6 Ôø²Çãð<}}}H$AG@Ôo$_ñÄš&­PJêº˲ ÚÁ0­ÂDŽ j¢]Çœ}%fÈNW÷øàíGøÎ“¹Bç­]î`˜ @aMz«h¹Èèäå#c$ÕSªôÊ£ãÐ;OöaJåeY¾vŠ¥Fqt^*Sü +>¾\ˬX)XM}F¯IÑå !– 3®R‡P”zÖ„Ðp€R“êÒzòúù€ÕauÁåtý@˜ª–R½ÒrKÚ?¤å](ôA£š]ù~‘’Úӕ߇Kä+“„0àÑk$½É F¯)yŸr¤bÁ²¼e­TÃJ4Ò„2R2°%á(º’†ô:¦a¥‰%Ã` ârv#¬UIQ‡Ñü¶Ñ¢õiˆf!Œ^L!~Ð)#­OC52`ÆŸ"ïjQm„Fd9å.éùå4lð2Ì^° W¶vŠeÁDÉâ4«@˜%€a˜ÆÒŒc‚b(u©ã8Èåreß_äxX/ƒP)ãæh ž#ÙNQ”²ç ‹ÕÝA£Tºë‘ÖÏ”krÖ]׃½å”Óº®3zNF'˜‰’SÁ@Ë0“…FŽ ¹¯ã¼Eçáù}ûïtˆTGùED=Jd³Ù tÏ)˜©BIÃc[[nºé&lÞ¼ek=öôô`óæÍX³f͸+1Ú”®•p]7<“'ÿQû”Ïå%k|äñ+Ídc×È(IF#aôc§t,ÙøØ¡‰¢íI³E‘Šd¤¢õI IÚ®>„Z+¹“Ž0œ³B G¨¢hÈDþ8d°sºÔÛrùÿ¤u£s0ˆ0ÇòßåÜp]ùÏ”ëŒÚHA:7¤ ì–Ö#ƒ)ieU©½ôiÕü1H¶ÓuI ÐhJ;:¯d8v¥u‘_.G­Ò¹LJû&£%…#ȹÕÈHJ÷Ã@hì%ƒ#Oš ‘a”ÎÝGtÝ“ÒñI#šF¨Ùô€?þËÑꌗøÊC_Áö'·Õhéê7s:&ƒ€P(twwÃó¼‚åÍ€aœþiy&bLPËTñÏéøØ/ß*'¢.‡(,#€ùÞÅr}Eá„lD$ƒ½Fèé$1_¬¡!„ll”S„V$?ŽPëŸåyÔŒ4e™ìÎAà ò’“<ô!L‹ª!’X{&Äp‰jkjC¹ždáõ ß*¹.f áPІLšô%®è–öIË©-ä›dHËéõN¯~bHGó^yC¾Qò¹Ù´{7Ð"†ÇrŒ§p]™L¦@iÔe%Ã45u”!ƶr]׃è‡FR*#K1¥Ú8CV"‘({Œ‘üš…V«ÕÛjí+Í" †i):„ÙîËx:óNG¨ö¼² ‘HªªBQ”)'“™©ËIå~0Mýýýظq#¶nÝZ3¹··½½½èïïÇòåË«FE¶ ªª.ù`ä# :iK­©N±‚´=ä‚.k)‚ŽÈ 40‘ÆŠ´_@h0‹@h‹Òµ’¡g ÔDQÄ¡ ºè7ÒzÉãü´Ô¶ ^6Â(Æ>„FO2hÉ)O)*ϨÍtd#.…pç#cBmšœN“~£´©tN3ZÁZ sÒy -o ÃßR%¶¡s#·¯ÒœM.F¥IÛ–zßTz•j µ•ŠMÑ}@õ>)Ê“)É/.™@zÄ3Q×±Š'¯eYA ¨t: "¦M›†ÁÁÁ@á`šfÅhBÚ®ÞPj'†ajÄuh¸;ï±£iᳫv>ë¼3?¿~ÞnA¯~ò¢h5 |õÇFÓåwWðj/‡RôûˆD} :tÅc_Žþ”%.ÿb¬‰á¯c a V9a ^Ïä ¦xù{#†ÂáùSyEÇÔ¤ýËIh™V¢=1é7‚ ‹rJWj+ǵW§»»†a S´“Ñq2F0 3>d2™ Ö»ëº ©á^Ñ:‹¤#ök+e’‹D—Q‘óÖËþ›4ÐóPøR¦ÜæÕN;éwäò6²Gey*ηONÖÅSIÒQÉ9ý‹/ƒ'í'ÿyÆs3z ã8 w`¦ùyòÉ'qíj^$B—X¦^°ïûAÝg˲Z>m9ÃÔBYÃc[[¶lÙ‚Í›7£§§½½½Ø¼ysð{GGnºé¦Ictto[þ6À¬Æ‹BhH<„Ò†Ç$ÂÔÍFу4¥HGú¯@hŸÈ0GËH3ƒˆzT1¼0øŠ \d€#íT,ßpJ‰*ÞÒFµ ›öI9¾hŠ‚¤DZ—Œ‚òVÖÒk·JÍMŠáÔ7:Åèr6Mú4¼£ŽW\ĪUP1¼Ff+ö£^äá¿Z|jxzž0,¤ÓÂøXLFxضÔhñ<Ùl¶ÀH¿–ÝW# ÃŒx0Mà,!ú”€ÅaZìËÂUšôXSD# B.Â(5a¦ðbI@ÆJL%õÈXRB“/ÎX¥m¹¡ TÑx“sr a‰ Ì^DÆCOÚ_Щ „)b³@äQD…©ÍÉüñÚê{(û¥*p:™gf&/$Ê¢„:Êr”D¨ó‰æÛœEá`S$ÈFJÚ–Jê¸pö…pþwi¥ùTÇG ÃTãÐÉ'c–EÓ´au Û¶‰D ë:0SŠ“ª­pÓM7ᦛnÂÀÀ£c=S«Ö‹5»DJYûJ ù—¥´ÿ`% iI„WaŠÍL~=Ê¥e!,¦CÞj@8à£1 ¢i¥29•s$ÃbqQ§>”ÖFf)KQJŸBý‘™H·ùÑŽõÆKûÊ:¥© ¸*гhQɤˆt,£(#‰¢Ñ(<Ï <ÇA$)H«ªiZÅ4Bš5Å0Ls¶ d³Á;ꢉ÷>)Í® _•q„¾HÅ;Iz×uú!‡ì5)ñx|˜ì‹¬‹Oi&“¦i5È(O(“Éd`X$åt:-Þ<–e!— ±mñx¹\Š¢ †GÚ·çyÁ¹"G£ŒÇ¾eYP%XÿÙgŸÙ™\Ðy-¾Ï4MC2™å^†™¬P¹EQL&¡( r¹\MÛ’œ™è*Šž+Z¦fT˜1³ r/0ŽR.qÊž„X/ÿß0„žraDŸ]´ŒJºÈÌd°“³=„¹ÌÉxI†0êe‘"go9+’,®3(%êgŠóÙË%häí¥ï”퉜ºUˆlJ®ôYFV>»†?¡^'›?‡BP2¿< À—ŽÓ'í¯øZÆQh¸ÍJ}qê€rEí¢Úãr.Ò Ñ¹°;¶O;8²ûm’Á ÃTãÉÙ³¡<Žáói]/ñ¨iZ ÐÕÕUr¾Á0“‘ª†Gb²‘gÙq(+” MZòM€¾ 0~™_©ØHi+hKƒY’ˆA:y›b°'§@%ceq~/¥ äEWL9X¹ñÒhd›“ïGvÛ2L³¢- ‰ÐŽnY"EB\×…ëº0MÝÝÝÐ4-PòjšÇq†¥U"%t-^Ï Ã4)±˜ ®ça* SBwIlPv+ÊŒEÈ0‰€ìKTJw6á4¹È!Y;QÄãb@VKm)2Æb±²ió\× Œ†žçAÓ4ض ]×áºî0Ã"E›¦ Ïó‹Å‚ˆ:Š˜I$A¤išp]7ˆ¬O$éÀTUE<‡®ë°, žç(¿mÛ†ªªÈd2A:;;‘H$pß}÷áÍo~󔯇D‘¤rmÇâß9%Ã02äÈ‹ÅÉdFœZ5‘HŒn@)=)<¡aÉ‚0@y£»!I„a÷´ÊÏMÑ|¤£ ç*Šº£4 4`¡¢ÈY§KËãùvPy2ZRv#ŠZÌä¿Ç! •Ep)'h9û’†0r"3åÌQ>*#äc•Ó½¨EŸåïtLz-“N%’??vÑzòþJÝ *{¬‘Ѳx}¹µÜ'ùXÒ6{¯Û ô‚a†©ÀÎ×_‡.G•Ë” 8ŽÔu.•}€a&+'4ºÍ€mÛˆÅb8ó‘3áþJ,ófúC \Ó>°Õ n4xÓz‘á`(ôH£ý(Òzòw |=>‹Ä£4& 3‰xáS/`…¶6|ü2íX¡‰mÛpòL†a NÃ0 èºx<+ËUU­¨Th™º' 3 žgUò!xψE?½j¿P"åßÛäÛH€ôi@øúŽA šqªaÛöØw2JÈAƒp]7µ¥p]70Ô"R­ZDšmÛAŠìâ}“±ŽˆD" ~4At]Éd² Ývgg'ÚÛÛáºn°/ù÷T*Û¶áº.¢Ñ( À¢(A;(’±ØXÙÝÝx<Ó4‰D‚ «ëºÈd2èìì ê ;ŽÔ“•ß4ѥߩöp,ƒã8¸êª«°lÙ²†]ûfŒ³¥Þתª"‹ KÁÊ0ÌÔÆ²¬ æ»ëº#N‹ÅJG<8†BŠð£è¹$€i•ºòß»ÉëÉÈoKÐ.Äx%a,Öo†¸>„NѺ´ŽB݇ì8M…‹fd,Î%/—‰¡BŲ!u<Ñ Œ™dx¬'T± %}œZ³›Rd)¸ó˜iäX˜a˜Öaÿë¯C•Õ~ŽD"e×WU5#°Ñ‘™J°á1O,ôÓà̇Ä2ý!ˆ<…,Ð`XNRìÈÁp-£¼ž<Ì"Œ–lv´¢ÿ 3 xmßk8€ámm@™H‚ŲÒÚ4Í >J©ˆ2H–ƒ Ó¼|럿U¸Àð€øøòܗŇ‚÷£ü4g¤ï²þ.æDv¬oÇ yå~Çãñ¯š7“É "MîÇ)0\’"XF6¾‘q‰"+£Ñ(:;;%2És2p†îîîàØ´^WW<ÏC__‰D`¨N$PU–eÑd2´‘Œ~ñx<ˆ|L§ÓAŸR©Tð^éë냪ªAzÛ¶Ãa, ÞAÙl60ØÒ¾]×EWWR© Ãþ+ŠÂN/E8ŽS6¢‘Ò«3 ÃíHŽ"cJ›FF"‚0Z‘Ò(D!)bb@!§-M#4,&òë¥Fa]AŠ˜K£²QŽ¢G¥ ­4Õ)®+9Þ´#ÔÏÔe£8ð¾ ¡gREñZp©¤|¾tdÌrœÂ2c¶-þ÷Üaø¾³Ïþ(碯/‡t:‹sÎùL3†{ïÝ%K>Ã0±ÿÅð<¯½¶[¶,C6›ƒëš0Œ.»l5þû¿/‡e©0Í4-‹Dbɤ‚dRA"áÃó Äã*Å€¢$àºâq “Ñ (&4-‹x\…ã(ð<Ѩp°Íd#u]‡¦iAêÐr.‰DK–,×û®Uq‡†© ¹6/K:sPiÂ…Dtæ?Ç¥u©î!E&f!ŒˆÄÀ‚ê%aù—‰š«ÛÓ¡ŽÒ‹”1hÃp~ ØùÔ§¶Äjñ…’Õ9™ ÷‚m cZrÐõÀ:1|WF"¢t7mCÛ‘Þ8Ƹâ!´PÙo×r›=O¬cͬ…€û§býöv «Kì;Ÿ#€ýà ‚Ó¦‰íIMíéì¿w¦K¦%Å>£Q k7`? X÷Š>Çãâ·HD|DÂþD£âÎ –Óz_ýêB<ûì¼ º™†aZïGâÿæ[ÖˆɤxAT(É ªjA…çÌT¢æ“•À³ßŽľ˜1ø§ZrzÊŸ_ JR‹S4¥i•(BvŒg&óœ‡×þlÚˆæé‘â8ÒéáqKrê<‚S³1Lë²O=ŒóÖ®ÅïÎ^ƒ‹?òU¼öÔkðn8pò™g"ŽÒŒTIN«:ѯQÛ.œïq$“Çq/L¹na)E…e%ƒõÉpCrœ.’I†áá ¿ƒ§žºÝÝÀUW=„¿üË$î»ï *.º¨oxÃ-¸øâ‡0mÚ"Üzk'Ÿüå8à±ÇÞ€tú¾ýíoPñòËŸDg§ ÇqqÉ%ƒØ¾]ÁE½†9sŽãàÁŸàCú>Î<óLtw ’{ïÝ×_ï '|çŸÿa,Xp5®ºª õWÇpÖYÏ¡»PUq…^ye,ë(™L+WÁ¶Û°mðîw_üâ|lß.öûàƒÂÂßÿ=pÏ=@2é"ví‰âßþM( 5M¬oWâMoZ(SG(ÿ(»§i …¡®#o€ëc,]_ù²(ŠØ¾»H§x ª²Ùl{ž§ ^Êì8bMî»ï ¬ZõêßÍmÛÕÈ0LU(¢¼ ­µ¬ èEÂX(Ðû9ŠÐ;ÉÎÿ¦å×s t #0Ð@czLÏïšâ Óž‡ü»D4Ó»PõÂßé=¦ªá;‰Œx†hgÖ s˜'ÞmŽ#Êe“‘Ï0íµ|¦Øí€ÑîGUEÛt]´/™ËR©Ð`–ÍŠÏ´»»¥}ìRWÖãÃb½X,\ o,KìËu¥ìúq —ëÒ9RÕ°Ÿ‰„h—ç‰÷7"ÀXÄ?$gî6€¦ªîKYtõ„·UýH¥ÄØ!çŒöÆy€iêÀ}§è¯©öïäO€Ô ⼸®0nêºè]#©ü32Ñoylðÿ¸û÷ïåÓ19àzÎ ÃTÂY(äôbYáä­žçÙhž<êã:Ãß× ÓìLyÃ# ðç*ÀSý^‡ðG!ÿT'ÒX”{Ø5¯¾q«”Sú•8™L&¨57þ'jüwÉ0¤}{;Ïsoñööö ^9…ü„< Ã4„ÿWXñˆ‡ú´‚c·ÃÃKFï›ß `:žjkÃ>„úFÂàH°êYËÑqBÃ#)¾Ççyð<Š·\W(˜<Ï…ëªa+—;çœs] ¨zê©{pƉ¹sçÂ0€_üâd³>~õ«Sñïÿ~GnÿþëÈDžÒê±ÇnÃÌ™waçNsæ\Œë®{ 1¤Ó—àÀv<ð€8ÖßþíI¸úê;ðÓŸîÇ»ßíàŽ;þ?,]zN8á >÷¹#øÔ§LÌœùKxÞoØx≠±rå*\~ùsغu6N:é^|üãóðÔS'bÛ¶ß`ÍšwãÚk§cöìÙøë¿~O>9·ß¾7Þøóñ®wùXºô–.ý0>õ©ÇÐÞ> ªÚ†-[Nm/‚¢ˆ>è: ª Å`: d2mø‹¿ ßæã“Ÿ¿9N¨”_rÐK.7Ü ì8íÁçR~)rÆoRdʯy_ògRþRº6ÈbÚ´Âö‘—”¦ì#°mŠ¢T¬ÇÌ0 OD;꺎˜)Õ\‰CèRH`æÿòé4ƒ?Ãõ ÂLH#E”Ž•ê0æ±íÐ1¥¤+%£™a„é8uãŽÛ€>'4T¥Rad!ó¢Q±/Eº @{ ­Œq†xOÅbâ4 ¨Ý@êÃ@â2À»048Ú¶XŸ £ô¾ÓuÀ÷Ed ç…¿‘ñ‘öMïN÷ÿÔ`RMnˆåé´8F,&ڛ͊÷%õûϽ‹‰0IŽˆuhü”HŠ+Æ„Þå@*6\'­ª€÷ZþóË¢ÔPbˆl6L‡š¸Àã€þ1z~̼#€ö7€a†ûÅÄv±âò@4†K¥Äñ,8„ÞÞ1<# Ã0“pÛåÛ`ï;>ŽyÑoˆB"Q2gv2™„ªªp]wÄzBÏ+LÈ&;«2L«À†G@(TÀþ QasR‘öÒ„$ ¬å ‹4±¨EÔ s,Ë Rƒa„¦ëjyE š¦¿SJ² Éû.š™x<^àéN5—ᥒL& ~·m»¢7\%ÃÕªUÁEõ¦èxÕ¢PFÒ–)K>}Íþe‹ÄòRŠU¾Ñ³ÙlÅëÎJK†™D¸.U—As:àÀÁù¯¾Šï>ù]ì8ñDLó:á+sƒ€ò9’³Ÿ6vŠ ƒÅs9EG?­KéÂTxûÛ߀ßÿþ"$“¡BPÞÏÛßÞ‹¾¾³qÖY3 ªÀöíIlß.”X¶ <÷ÜãX´è®¸b.ø›¿Ù3Ï|ªº>ø(~+ÞýîpúéÀöí`Û;°f pLJðµ¯ý>ºþð*¼ûÝÏãùçŸÇyç=‡Çû1\×ÅOjBU¯B&“Áþð<^yåf|ï{1xž‡H$‚T*™3=|å+”ÿL\vÙÉø»¿[ˆ}û¢ð<kצœŠxü«P”Gð‘ˆ3ÿ¾÷­|ìc4m:èì|þÏÿI£«ëMH¥R0Íó‚óZ›fèà„Æ:ÃïÏô“噼SS*%~÷ýprpÌ×3ììŒë€Ô7!RÉj¡1ß³†‘?o@‰ÊûÄrU ßiôŽ-%¢'4°ªZô.ýP¸-+e´¢vªªÐ%…c2ù3‡Œ—Á;[THSMÍ"\pw‰,ºúG†KêK"!®3¥’5 ñ§(.Á°J0þ½ð±Xå1Šaˆs gœÊFÇçž{®ÑM`¦™É¿¯Üßþ>güê™ÐóSÓ†O!‚Èa©šž¾ØÙ4™ ßAAì±Ï-¦žLyÃcPËÈÜ‹=ƒÂA}ÖÖ)PPÞðè!L·Z šŒT!“ÉEçiÐu¡(ñ½én\ 8?œcâ72PÑï¡Á‹ÒéÂè|šº”Œ¨ˆ¾Ð~‹‘S­©TÞàõMT ‘z`„Ó§D¢Ð@Y‘1(iG 2l ˜©Ü¯L¯¸}tA´+MGiŒG)ZƒvضòµP‹þË]¯Òw9#ÆTgÏž=c߉‡Âº¦ä” —XS3Âi°¥ílˆëí °”…0Ú¹” OnK"¿½¼¥v¦ÚVþxÅúLŠÄ®öŒzù}ê–yÒ¾I&Ò3\ܾJÔÚ¦rÛ²º† ôÜÎ.øÉQœpô„Âc‰’®ëù Dà %G4’>@^&g®©RF²¥)çxÍ´>lxt],Z¸€}ðPø¢”uY:„·"P>ú¯ŒG›LIç¢*Š¢à¿ÿ»?¨£ðì³oÅÑ£'aút¡`|è¡‹ðè£ïm+WîÆk¯ýÞûÞ™¸ùf:V*˜˜xžðBìêûÊf?ù“ù8zT¬kš@__ñ¸jÓ§ïÁ /ü8Pι®‹îîn¤Ói¨ª ˲`YV ð‹Çãp]étŠ¢ ;Ÿ…Öïêê‚¢(ß5MC:Œcªª"›ÍÆ5Ú^[C¦i‚2“ÉÀó¼ *P†–kš†H$‚t: MÓ`å5˜d°ó<¹\–eÁó2 Óš<¿íy@= ¿P÷`åÊ%H=™Â´öixá…°hÑ"@X®YžfÔ2—%Ãb$¦,EBÉ亡±"HQHŠE‚"öîÝ‹dr7Ö­»©ð‘|_úÒ·ñOÿ$ÂÈQEÓ„¬{þù?ã*tßÕÕ…l68ô—f,C.—C4ÅüùóñË_žð}ãL__Ç Þ7𦠋OÉšT ¯¥#;@Qd§ë†Ê8EQjªÅG©3EŸµ’Çf@ŒµêvoÈ3kÊ‹Lã?ʯ'#§m…Bkƒef\ˆF£Ðu3²3ðÁ?5„)V%¨ž!묧g€½€y–p"¢A]¿/™ï±wÙwúGľJMOäÈvó"?AÙr/†!ÆÅỂ$hs-FZg„¾ä¤eÃ#B PvêVþ( àäÇŒ é…×G×ÅØ¯8Ftà C¬¬(0AA½L*B/h@<1ˆTË@X¢ ùe i_„‘/†0*ZC¨k” •´?’7ªôÙBXê)…°LT@W~;Ù(MûOä·ñ¤ßŒ|{)E´ÿN} ‰Ž…°–„ðÙ2óÇNæ'C¦“?©P¨­¨”ŽéH¿;„$<é8Ôö˜´~ …WJkMÏH ™…p¡ó›‚0è'¤>ÚÒþÉ’Ž•‘Îe\º®tŒnéwJC}¡TÜ@(ÈèJßéø@h`†ô»+ý÷Ph”v¤ýÓïZ¾ÝHCû'ƒ³.µÃSŠüùy¡÷(æc®XF/ó2PM©ŠÚ§Í)ƒ€\¥„½²% vÓ{­Ø°HicåÑrZõV£Øˆ\ü}*3å ðÉ=Ÿ„7pçÚ‰E?¥°¼Œ*QÁ.áy2™ LÓ„³èäÞî?¸mÀ|ÀÝ€:’[JÁ”Ù†R«ŽZFŠëÑ@ÑSÕ cÁÚHUÕ~QÚÛFÐWþ§ ]{ ‘I6§Œ sú:€Áõq’QàÈn!4Ĺ tOÓuèB˜!M…0bÉ÷%«t„÷yÜüzd˜Lç÷å"ÔCR” ñìË÷6EEªrRè?C©­& Ÿ»RQÛT—Vî‹#-£m(•4õ•Œh1„Q•‰ü22.z(t Ÿ‹P&…µo#ùmúòÿ)ª˜":馋Éð§hÏÿÏIû!£^ÉÐIms¥ÿ„ÆLÙhìH뻥ïŽt<*áeI¿eò}'߇Ð,SÝ¢ýX ¦.BÃvFڎί‡ÐÐJû°òûµò÷føÜiŸSØÓ6ó  aZ¡2Pà 0Ü‘„†Øò2yÊJHòµ‘©V+›j3ÓT€ìòw üî8…ŽÅt.&ªoņÀâkQÜ·âßÉš~³¬Ð¶Béïé»e‰ãÉÃî‰4Dï[Ž’Â4û¥¾“M-)- >ÞµãOî¸ãÛ¶mÃèóýX,æûðý¬îûÊ+¾ïÇÆÿø÷wß >êS½þ¢E÷øªêûºîûº®û€|7MßÏå|ÿî»é¯Y³ÙÿÖ·þ૪ê+Šâ†áßrË|]ù—_þНi9ÿ¬³^ñ/¹ä3¾ªª~.—ó}ß÷ Ãð‰„?88èkšæÓeôƒ¶†á†áëºîçr9_×uß4Í`D"á¯Yó´ßÖö¤¿hÑ=þš5OûwßýKß4M?‘Hø†aø·Þú=ß4Mß0 ?—Ëù¹\Îïëë ¾û¾ï§R)?›ÍÇÍf³Ã¾—jW5b±Xp ÚªªßE)ØÆ0 ¿¯¯¯ì>åvLfÖ®]Ûè&4¾ß1ßÿóÄïýKöï]:]v»t:íkšækšVpÏ1L+³mÛ6ÿŽ;îht3êNÙ1A1K²þ r‹ß÷ÛÇO¥RÁ;Ù¬õï~çk¾ïg}ß×}ß/÷öÈf…xÑuñ®Wñ¹¯O||ß0Ä2ßâ(2€ïϘñŠ?cÆÁ²\.ç§Ói_UÅï]ôÿ¼óño½õ{þàà ¯(НªjðÎ¥ws,󉄟J¥|ß÷ùË´ø½=88¼?c±˜¿fÍfÿ¼óñׯ?ìû¾x«ªl?žÄbbl4–«aÒ¶ÉBÍÏÄ$ƒÆÙlÖÑ”(•7$ýÉÈp:-þ—w¦RáC?r9?˜HÐd‚Æ)$hJ‘H„Û)Šø/38ö#ëúúD?²ÙÒB+›õ¥ ø£±Vñúº.Ú£ë¢=Åó€t:l¯i?w}}â·X,²Å¿“ÀÄçâëAÛQ;Šû„×Ó4+o¯(…ç‹®m78®G¼øZQ©ÍÅç—^*t Kê àûš6üÞ1Œ°†áÿŸ÷¿t÷a SËX(‹ù¦iоâû¾æû~Ì÷c7ŠËF§7‘(ýÈõõùbÛùåýœïûÈÿ^~Z2œl~»)F*5ü¶o5t½°ŪˆFhë¦òüàÎ;ïôu’ÿ)_˜o»æ‹{”† éüç>_Ü¿é2ûÈù¾oäÿò|þO?ß Ž6–ŠºÒ”ïûŠïŸÿȳþÿ¹å¡‚óUŠÁÁÁ‚9F6+þˆXL¼ËˆâwBñ÷RÃÁñ¤’:<—>ü-85©Âßc±Âá¼i~§q“¼þxö­xÚR<µ‡Å¹\áT(—+ü=•*ü‹®ŸH~Å ××õÂãg³ÃÛ'“ÍV¿2ª®?8X8 ¡q*}§)I.N÷¨í4Äo¹œïß~ûãþm·}yL×bjG<’7 ò…Ø÷¢0µê(!Ë>YŽ=ïƒX²DX½O;í,œtÒYxÿû…Uüƒü:V®Ü… ¤üTUñø]PUwÞùµÀcß0 ¸®‚;îXŽßþöÅÆÇ>vn»- 9‘¼®ë)Å(ê/™LQUG5#ÅaÛvÝ•L&‘ËÅ ëƒX²ä-X´hÎ9§–%LáÙ¬ˆ²nz¤Ó…é&‹ë(G>¯5Ueqš5]ׇ¥É*þ^¼oÙ«A¤ )tA 'îR™8ÉûÕe¯úÝuÃZ\ŠRè@éóD[ Èëz¡£¹ª†÷–ª†å“Ó4Õ£¾‰ó~&§æ'Ÿ|ÇÈoìɆ ì_õ:– Uö8Gñ(žONoÆ0S‚§2pôó'œvZáíííè˜5 ¯!tVÊ­X…ž|â=)d|4 ôõ…ïŠÁA`Ö¬½ð¼yŠD„ZqàŠªû÷OÇß8,³, Žã`îÜwhÇ‘#Ïcîܹxíµ‡ày‘î‚:Ȫª"‹¡³³º®Ã4Í f°<6¡èGú¼cÇ+øþ÷3fßãc‰l¬¥Œ-r4&Ô¢d´#¹|êz8ô<ñ S³b×UU-t-—%rcEU…P¡ˆ79ÒRÎæ@ù©Ÿ½H)^‹Ÿ]E©îêªiáþJ=ûº”«‰]ìŠ+ç,å¬ibR®ßÔ^ÓÂ"^³›BÈ©8^ñu1ÍPp—Êk¨ëáćγ …)‘ë6 ÖåëT\´×÷éq(E¾Ò5-¾G³Ùp¥îE]/ÜGñþU5 «ÏóÇuëÀ çâž‹1ÿüù€ ¸·ØÄã“â6¯ôŽÒ䨗J€µ“ÄÈÒfNÑT^º.êWÊ"º•  pYÔ?ÆU*|0I"*ŒžW"Š®Ôó;ÞµÕ®ûxF¢´Õžu•3ÔQ$d9²(_3£8’´Þ(U~£Wº|Êç‚"NKí‡"[¥{o×i»ÔÑ&F^[øŽžºç.|Ed1¨ÀÓp÷Ý¿¬¸Ž<¤,~È„îh3T@Ö[•#Ý(1ˆÜ6Ï ‡ÔÅ¿«jX6C^ ´•P¢ÒQ'“… ]’IÑ6:'ñx˜Á¡ÔwšžÝÝb¨L:øL&S„"MGè7J¼’L†º|¢ÓwyÊEéa©*†ã„}¦óAÿåkKÉnäs-Õ£Ñ0‘Lqæ+Ò/e³á´†"0i HÛ ƒúHÓZUç‡î)E Kò™¦8ñ8õeâñÇtŸMmã \üúÅ8<ã0ÜwÌ„6¿Êêe2âÐÍiY…W\¬íøáï„¢Ü Û.ºè <ûìã0ŒõH&;îØ…ÎÎxüñ(b±’É$ Ãj%QÚ32vxÐÓ³—]övìXÇ9·Ý6¼­¤`¤Ô¢º®õ›¨®!)³Ù,\× ê ‘´¯¯Š8N;DNhC6Îo}¿P¸Ðy*ü;NÅze¡¬Sdü qdð#!–LF‘JÅò5&£¸ûî~Äã¡q¶I¥BÝA:-2E8 ”Á”Þ6›ו«8ŸáÃëyb‘Há¼ß4Åq)óµQní‡êzÉç2“ Õ”U‹„!0<Ÿ„^4Þ§Ô_zéŒ>,“ðwÖPnö ¨ª:a u†aš”S2xáŒoö-\d¾‰x}Ñ"¬io²àè2V–Áº.äòà`(‹K•€8ñÄÝ0ŒyÁ ]U‡¼ªïø×X±âX.Õ¶m躎_ÿúI¨ê!8Ð…Ç_€+¯¼?HKî8NP[‚ ‹Š¢ —Ë|¯Û¶qÛm?ÆÑ£?(JãLˆcF"!Þò{|¤Ç­ ˜­1“×u‡?”j´”Á†fzÅÈ鳨æýQý'â—*ðž˜XFéÛ¨^¥=£4hrj-šÀ«ÒŸ’7zùu_£¼ÍŠP=ðXIb)ï¢Ö¢šR”îK†úä TX?R* Ó¡Éç€jÀApަ£ôtÔæbŘªžšO&iÑ‚úS*`ÄDÎB¹6‘&­=ßGS´Å‘ŽKýÕ!¥/E¨àt! °À¿e€÷è…×WWÅWpÜüq‚ÛÒ:¶F:_t.éøžž?JåìW/ßùÚ¹ja:=Ú?µmŠ®jå´]§áÊ]WÂ{Ð5Ä>ŸR:F–6‹ž5³Ê:åÃå¨PGp2SÎo¢U¨åÞiÕ¾µ*Aùœ „ªø¹âŠ+­Oµç®ÚT¦™ß—ÕÞlÐ;pâÃ'ÂU%³–=¨øNß²åüøÇ?ÆG>r9€Â€`¸žÜRò—+U @FNZ²ù% ²Ã´œ>Ôq„qŠ|ÉðFS#ËÇ#ç+òi¤ö“n½;_ï”|É)[UE»ºÂßåʸCßÉøF9ä˜,çt=ô«”+Iá϶Ã*dÃ!½ éqȇŒzdã¡>“aÑ4Eßh[@ôtñ†V­ ]鉨ý‰DxžÐž@†M²SP»ÉÀ©ªb_¦ú–’“ÎI&c±ðÚg2â¸ÝÝ¡­m‡†\ªHAöˆ‡ÞÓN;8¦Çfj]`Ö‚YØùþpN\ói”õXˆFC'Zz]7¼±È–J>èïz—¾¾#Áxúéÿ7ÞØÛÕ§ßúÖó𱽎?ù“A(ŠÓ4 ”…@ažyMÞóž—qß}W–íym«ªZOÚ²,D£Qèº^P§NQ)ç´ Çqef¬„›]ñXþNF>òL…äXK‚%Œ˜ ‰ÅBC"y/ÒÃE¼l6Ü/=dØrˆF“¸á† âî»Åõ*n3µ…¼+èºÉ¹ÄN¹ƒì¡Ë‰V6J¥ œ¹Ë?³ÄK«œ³x¹}”Z¿Øù{ݺ €÷Tßñd& ´%âš3*a]×…ëºlxd˜©Ä¿d€§ÃÇ/¾„?ž96Ä\4 ଙ3„ú‡L&\¶=Ükp¸ã’ƒ¡¡C2¹2¨ È]× êÇã ¶oOâðáF>±<Ž[n¹‡°ÿN¨ê‚#ŠišPeX}Ú‘e¨äž=á»g´ûª•Z‚¯*o¯`Üê÷1“ŽaFiÌÒ@ÎSÂ,)Ž@Чüx6¨w$;â‘×89ÉÆ< ÀÛT@‰}?>ôÝFX«ÇCh¸C~¿Tß íSóë|ÆÎp€6-Œœš¯»l Ï<#¬UT\Ljö)Iml4¿M*¿žäÅ\©åBDL+êWpž:Å÷scÀgãÀlÈ Ç|]¡aŸ '[â2À€ð!£ áñŸÌ+-íƒ µdäÍHí*>N":Í+¾¾1à) ø© ÌÎ;ÖJ¢zRÃú’o$Ý7r_4©/29é>Ëæû%ßgFþ<Ð9û©tíJÝ«f~Û$`¬`­z1¶mÃeŽîgí@ìó£Ü9¨UÖMôT3+Ù²T«½ÉÓÏúsÖ᳄̬- Ã0SŒÁ¹ƒÚ¡}àpq•,¾K–,AWWwÅýɆFªMŸé¿œM¯¥’zÈÉ@'¬GÊÆL2ÚÉí‹FC£!iŸôËd„þúBËõ¼W<.>'“á¶dè£ö’ÑL®£mÛ¢myIm ‡p²%P@e…Q–‰Dh<% Q‘í'™ ÛMö¾¾ðš‘!”Œœd"­a„çŽ܆ cü”ɲL¤Á1öØAƒiU´b¯²XB¦¢£ Ý‚a8È"ŒN"£Aßåqa±šãÑ®"O·“çådJÁøÓâIàj=ÜöJ¿v€ ôòÊÔJm„L&UbYÔø(Í4ˆsB"q@ó C¼}„FÖœt.åó+›Ú-_¹ýåÚaVYg¡Á— ³Zˆ8¢í £äý‘’Ι  O蜖÷ÌGpÊ}) ·­œˆɵ£É⨺Y—Á{¦ºc"‘áç²9¼E¹‘ý€q!ÊŽaŸdøˆª Sðõ+G´*š6¶TòÌøsÉà%ỞaFÂMûÒ®‡BV³lùÁç?V¬X[°L64VS5R€S4Zh$(.´7„Æ3ÏzŠD"܆2èÑ~å}‘ቌPÅQ‚ä†ûÏå„1Ž ~†! \”âTŽð$›œ:–Tt -KìÏu‘ϾXÜ$—3"‘.F60f³¡ñ”Œ}Ѩ°5PJQj 3úN8ª*Aö Šf¤÷6µŸÒ Rå¹Q­jšáy¤òi´=í[Þ1d”÷_JåCÛær…û‘·¥Lò÷ñ_0~»CCCظq#.½ôR,[¶ º®cëÖ­ÃÖÛ´iS°Îúõë1000¦ãî{m¾pÃÙ04)Ú‘¢èÈÊláMB^r>ãp;ÝÝ¡GC"‘@&“뺸ᆇ³fÍ‚ã8ضíOƒ£ùXÌc-ÀºuO`ݺS ¾ ¥J5M³ "EQVR@*Š˲ ú0d¯z ‹ohù»œnT^g´hpå•A¸4ÓZÔS<Ý.”üúÆ%o:×u‘L&áy+Ó¦Î4jL0ÝÄñ…·c{{;Î<óÌ`±‹PqßwÂÚBÙl8¨—#䫽ÏlÛÆc½€ÂÐ š€A/›Í"‹á¼ó^€ Ū¦iH¥RèììÄÎ_Ãu×Ãñãcz‡Ö‚¦ip]‹í,pš*å,Å0c¥Y0V9PñèAD$e Œ˜ƒ02% „@>ð10+ŽkQ$×/hŸò ’4Í ¥'Eò°(å¾Mé?U„†Þªýž€¶Ê)`éÔÏôËmGm’·÷¤z 26нÛBr äe@ïâçG—"õy õ½qèL sí§h°êDy&6:ŽŒzÈ‚eg.ãhG†ib©'xòÓ¯â»ÿz½øRÊ PDGÇû0~XÓ­X? ÿ• uü¦¦ïL$Âu4­ðÔQô?D§Ð–@SÚ¯lG à'Ó ë&öõ…¥æ ñŸŒz†1<“R9u¯<Ü'Ãj9J•å“‘ûNí¦~P“|oÐ÷rãœR†ÍJ4r¼Ô4†Çõë×ãþûïÇí·ßŽ-[¶àšk®Áúõë ȦM›ÐÓÓƒ 6`Ë–-ÀúõëGwÀ¼ö0ƒ ~³p6ÌóŸCÙ˜=žLÑÛªÕÅÇ8&¤˜L´,8óЙXýÀê–rÌ`˜©F#õµè¿Ý)x™”w¶m£»»GE.7·ìþr¹0’‘êìQJOʶ‹ _ÂâÀÙ.Ã"()ò‘¶¡HGÚŽ  T~¼½½0Õ&EâÅbÂØ×'º«ë¢-Ô&‚ ~r”0rce”L§Å~Òi±_2lÊÿ©-TŽR”Ê~–4ä&^v,Y+˜QÓ©V‡††ÐÛÛ‹»îº ×\s `ÕªUèííÅý÷ß,Ûºu+Ö¬Yƒ5kÖîºë®À»Ö »NÛ…¸nˆAkËÈÊ?8†ÛÊÈsyòNH&“A¡išPUñxº®Ã4MD£QÄb1tuuÃq€^x Š¢àŠ+NƱcåÛ'R« M«*pèÐ"80`AÉmmÛ†išÃ¢³Už4UU%gb,•f„ÔU¸ÀŽwïAgÿîª3VÏóøY`˜:Ò¨1A@7Ø}ÞnœwÞyMWß^ èjX òÔ#¯»b2™Lðn¶mÿñ¿Æe—àJ躎_üb:l{’ÉiÏu]Ç7¾ñ,þõ_‡†íϲ,d2˜¦‰+®XQàõ8QضóÏß8ñb¦4µÈ‚ñ³ŽLJ~ðàjét—ÁDG<–*LÞ F/Ù%W.3˜(có$¦acxý·¯Ã›¦àŸî:¹Ñ§)C«—9á¤:µSY0Ï| ÎD;ÚÝ]†aJÐh={°pÇ>h³*¾€ìü„ü²ËaÕªp¹ãÚººÂÏd£(Cª•HúËïŒHD ¥eÃ#)PŠêÿQŠÓh4Œ@ÌdÂZ‰D I©>ɸ™É–%K•X˜ˆ:9Åi%¬K#Û«;+µ*Mñ800€U«VaùòåË/¸à %[°ÑÑÑåË—cÇŽ#?¨ ´ooÇ‚÷¾· }{2YXè´9²çííÛ R4uvvµ‘j5N#“ÉàüM^©Á²,ôõùVMÓJFZ) 0gÎ~Ì;XöÁI§ÓˆÅbA”c­(ŠUU‡Õ‡b˜‰¦®rÀUNÁkÓ¦•ñU‹ ffbhȘ€p8†~¾ï{ü}X¶lYðÓ§$…Ñ‘¼ìJAõ ŠSŸÝÝÝòåÏÿü2|ç;Áo_øÂÛqúé'²,DòùÞUUÅÚµWà¸dØþ4M Þ÷rª×‰DUU\sMSø®1“˜j²`Üä€ãàõSæˆÙv=‡¿6=믌<‰i$”+ ¨šubÒQK(¹ _û.Î[ýhnôY`Ê1•ÄÇT§²`Þ³ó°gþžFw•a˜24TOàØ±c˜ß·‰ùó+¾€t]G*•Â+¯\ ¹Š™lt”S–’ÁPQDtb"¦,%d;'ÕU¤ Ëîn±¿t:ÜÎuÈFúNiO³Ùð÷D"LO „ÃTŽÈgÆ‹¦Ð-_¾[¶l)X644„ûï¿?ðP8xð ˜3gúûû+îß¾}Ø´iV­Z… 6Ë_<þ" ªA4ƒm-=°}Ç‹ƒzKŽã)ÏdâñxÞ˜·ª ÄãN>q>¤,­Ã(e¥(@GÇqtt,˜ýAµ¨H¦uéééÁÖ­[±{÷îF7e-`÷îÝX·nn\p#N:çÍh?v¬l2lEQØÏLZÖ­[‡ƒbéÒ¥nÊ0ê5&˜3gΰã`š Š_>úe¨ªŠWò5ÚI±¦€IDATþr©QE,×1–¡úËžçÁó¼ Žs4E*•‚aÐ4 «V‰D¶À±©’"“É ‘HÔµ„Û'>1¯>b&Œþþ~lÚ´ »wïö,5ÕdÁXÇ{÷îźuëðŽC¯âèâ7cf½“”J‰:^´JM«´s¼(WÓ²ÁlÚ´ ýýýØ»wo£›2ŒzÌî»ï>ô÷÷cÆ 2óÇ×]€'«ˆÝö†FŸ†©S}~°rÿJüöÕßbV4º»M‹ç‰×Eg‘¡„(~ÅQÄ•ç‰ÏrúG2´PdWq IÊ"Cÿ‹÷W­¦3:Xg(t†×\sM°Oâé7ÀñWŽ—Ýöïÿ~žyæ$¤R¢äšëŽsÉž@¶‡l6L¯*§R-eô£eª*Œ‰€0vu…Q’¦)Žaa’ 2dÆãâ;™¸ºSM›6¡··wÌc‚¦0<³uëVlÚ´ 0Ç!Æé§ŸŽ÷¾÷½…‚Gî¿ò~¼vÑ PF' Vwþâ Ÿ‹T øêW?Ïó`Û62™LI£]"‘@wwwÐMÓÐÝÝ ÃHÊp¨i@[Û¹xé¥!všeF¥X·n]£›R•ñ–°páB1P±€˜»«âº”.™k–1“‘-[¶ ··½½½nJUê2& t˜§â> ]שÜ#ÎùNùÔªÅ$“qø~"˜”'“ÉÀ‰Á²,¸®‹x<Ã0`Yb±4MCgg'r¹Js¢ËZPjrMD=šÆK&3…&ï›6mjtSj¢XŒÕkyÞ¼yزe ~ñß`æ¾·Õ¿Fk˦å:È1wªÎÞóž÷8'Ã2>Ѓ¦±‚™:LõùÁ–7ß|ó˜÷EOTU|–q”þR)¦RB)caM6MÛPÀ‚늿lVlGÙN¨®¡ëÂa’öíûÀ´iaŠF]† Ü—Œ®SY©òëd³âwÛ}¹i}â¿þ뮿~aè È,"²ÙAlßÞ>ì˜òqèØ±ðÿþßz¨-p¸$um #ÔW¾Ò†d8|ø0úûgÀ÷}lß~:;Åz_ùÊS°m{÷žŠãÇ£­MÔݺüòð,àùçg"™ÜŽX¬0ÓÌßýÝ><ù䫨¹s®¼òE<óÌ3xúé.ìÚuö왎ÿú¯ð¯ÿz%4 8ï¼—ñå/E{{;ÑÑ1 ë×Á† ¯böìÙx饗0{ölÜrK/Þüæ7ãƒ<'Ÿ|2®¼òEìÙ3>z >Œ3Ï</½ô6m:)ØvÑ¢¯açÎaÏž=hooÇI'„?û³“ððÃCxôÑSpÆÏàï|ƒƒ—`×®]˜?>^xá|üã'bË–“1cÆ \~ùa<þø1ìß?GŽÁܹsñòËÏâÖ[Oǯ= 7ßü9|îsc&š Õ–`ðŒ¹h±03E.ÀîÝãW¿Ú$E£b¹mÖŒÇÅ•f!ƒ#è+¡ªâ9èî² • ’ò“ŽEú ®ÅŒ” 6ŒË˜ © ظq#z{{qÓM7Á4Íà%0îXÀÞöëp ½:€hR<ôÕæ‚Šø¾Šl–ÒœêP™L}}}Aô‚ ¥T#†ã8ùšM£sz/×%%Å0­N]ä€ äfù8ÓKþìy²ÙlðÌ’W’aˆ< ®Uµ>µEÈu”ÌT¢®cˆtðüÊå°, ÙlQóÞYÛn(J‘žW2.€a0MŽãÀu]Äb± Ò0ŒÀÐX.µI)y£7 b¨Çd¦.) ÇÁ øm@>¡&5B1ÈDF¹Nrê9&èéÙ ‹‘ý2¦Ù˜HYðáO~W\wEÅu\W )Eb<^hð##EQ¶42NȯŠ4ŒÂut=4@PTa©ìéÙ,°}ûv¼å-g@Qž@,&Æç‡œ9;ÑèOñÿp,+ƒõë?Š;ö£¯ïlœvÚ¿!—{'EA$A:-æ*º®£»»‰D"?2`Û6\WE6«Âqœ T2éÀ0 ¤R:¢Ñ(t]G,æúN˲0kV ªE4šÁ;Þq;¾õ­oáÅÿñxét¶mãé§-¤R $“Ihš]w ( 4Mƒã8°m†á󤫮ÚÚèz ßÿþ~øÃ¯ã±ÇzqË-?Âw~>ø ´µÆÞ½aíÚKpçwâ‡?ü0Î:ëpÅW §çÇX´èxÃ.ÂñãOzz¾†~ô.<ÿüçq÷Ýwãßþív|å+_Ä—¾ô%\{íµèééÁ‹/vbÛ¶¸ð <‹SO݉K/ÂáÃbÏž$®¿þ~´µ½ ¶ý|ùË·ahè9\{íRÜ~û¿`úôÂø{<ñÄ"‘HàÿñçØ¾} ~ó›‡qqÒIÿŽN¸{ö<xÓ›.ÂK/=ƒ#G–ã~àj¼ô’…dò+H&ˆ?ýÓkñ«_ý«VÛnû2¦O¿ÀVœqÆÛ¸xþùéxúéÇñÀàꫯFOO.¼p!žxâ,Ì™3ôá…`÷î%xî¹~üÙŸ½<à`ñâKñ¯ÿz%–.}»víªïÃ=ê®'È£Tðîì/o&E^S„†|ؽ{;w.B$ò6ø¾èû3ñLS¤#É °A-$aŠT9ê·¸#Ã4 McxìïïÇÚµk±jÕ*Ø¶ŽŽŽ²ëçs.þ^+w~n>Þ¿ó ¸{WÀqj{P)=šªºð<‘Þ,•J!W4ʵMÓ¬ª\¬„8 +*˜ÉGÝä€ œú'Ó±fÏnà²Ë†ýì8þ×ÿú¿øßÿ[ 5“7yº®@ŒÔðhÛb?¶¦ qœ0ý ö‡¿Ó2Ódã#35hĘÀ´#þ{¿ Ó4áê:<Ãc{gíéH2™ \WLŽåšÏ€H©ªi‰lÛ ÏÓäºU`Ç'¦^Ô" Æ"<σ F¬A…LøYšZð nTÔ{L°gÛ+øðì=P”î:Ã0- –-[6lŒëºa=52Pm4Š<"‡dñ¾_½/}$æ .ÇA"!Œ¸ày.2š¦†:šWX– Ã0HD‘N§‘LŠ k®ëë÷õõaîÜA¸®‹d2‰U«Î‡m+8ztfÌè‡ãÌA4 ²¯tuuÎמçAÓ4¨ªŠd28O*ŠEQ ë"£«« Š¢å"E ¶%ÇË\.‡÷½ïN=õÛ¸óÎGqè…D"èH 8^ñ5 c'Í­t]G&“A<É×¹¿ºþ-À—¾”F&“Á±cn½U8unܸ Š¢à–[nÌïñcÒÞß×uñÕ¯¾Š¢à#ì>ò‘ÿ|üã_Éï÷ZÀwÒv+¥}\›DMäË èºŽO|BüzÛmWàƒü:¾üån|÷»×Â0€O|b ˆÇ×çHŸÍïëÊwËE€'ŸmÑuʲ'n¸Ï|fK¾­Kò÷ÍB$“Iüà‚\.U]„{î×âÖ[ ÷)Xœÿ¿&¿=°{÷¼ôÒ¿U¿‘@#ôÄo»Ž –üQNhÛâ ‡ž§ãðá¶ ú’'”!‰„X–L†Ž#Tœ€ˆišÆð¸~ýz¬^½·Ýv[Éß)%ÚŽ; „Eoo/®¹æš/³xýõ×±vï^XÖŠšú–eÁ4Mض¼UUEª‚ÕRUÕ…¢œ:õ R79à¼íl,X{?P”·~øÃóñ™ÏôàßÎét(äT²§ iÒA†IZÇ4Ã!”–DNBJÃPìÁäº@ggh€ŒF k¹ÉÔt|š‘7%¥{ÂÁŽì|oš¡Á³¸˜5ÃÔ“z s% ½µÖ]ÝHâL®Tg¤ Óž*PUáLGˆÌü1L%*É‚ñíÛÛñ_'ÿûó1LSï1Á¿?w>ô®~lxd˜f¢Þ² ™šV˜ÎPVø×:”ïìì 2¤‰BáœhÛ6‰ÇA2Ÿc”Œ‹dÌ£À2ÀQ–]×aä•Ëåà8a¤ ÍGH™Ëå`ÛÀ·¿-tßøÆ—£íO6™Ҳ,ôõõ•uÌf³°, ŽãTLu9oÞ)Ø»÷D"Çñ…/¤F¡ªjÐ~ù¸Å¨ªŠ®®.¨ªŠDÞb«ë:Òét Ÿ•1 ¥ÙÝÝ”±¨„:NAɤˆ„Å€DbøMv#›}½ ð„¢e'€DÙ{FÓ7]z¬ýûÃÆFè ˆƒsg`pñeó–þîw¿p%üœ ªœå®µª y"GK3Ìd¥) ½½½ÀªU«†åŽ3gN ,Ö¬Yƒžž¬^½mmmؼy3ÚÚÚ°zõê3Ó¬´Æiï¾4È«\ îFašf`pdå!ÃŒºÊ¼¡mÑœ9‹]W¤RýÝïfáöÛïG_ßË{d@$C¤ayB‘’ô]×…÷#E:Æb¡Á‘¨”fAUÃâÓr-ƒâöÓ€k=P;äA-9=¡S.êNÆHŠÀ”ÛGëRÿ)”‹¿Óy 1ä FÛjZh˜eÊæöRÎ]À‰§Ÿ@ á½Z ¶mò,¨ªˆšŒÇãÁ„Ïó*A™›ä¬J‰ …ß<ÏC&“ã8Èf³%×!£c¢J9EÎ?z{×"“1ã`-PD%}¦ÿ‘H¤¢a­ž5éijWnŠwÕUmèé)\FY°Æ[¢( LÓD&“•žštJ+VüÀ{&þ䀆é $V=ûÇ‚ïôh H†©Tªp`‡uhZ\|Žš€K¨³íгH$ ½ãñp‰D˜öDŽ”¢I—L6[8в¬PƒOç¤x Öݦ`¡°ìIN^‹rj–Db¸–—ÚBû/N+Cû)î7y9Ò¹ÂA¸Lñ¶Å)h(—'Ýé´è›| tæ™øÈG>‚ÿý_ÿU(Ài@KÚrÃ(|‹‹ŠÁøÌà`8y(ôÊ @ ^‹Î4± Š­–UZˆ}ÈÒŽ¤ñ–cY…Øb¯¼RÇ)N» çg¤˜ryŸt™â"›Åm¥óVî8ÀpK‰ëŠ·¹š£ó ¬æ©(÷•þhDd2¡µ€Ö-¶ØE€ÚQ|œZ¼?«õ'?1]´?Z±È ?!:þqgpnâq|ªª×œ–ƒnAù2Ðçh´ô€^¾™âS.ŸÓ¾>q¾äGHž—ÒPM2$Æb¡“r.¦Æ¥ÿrLù1#ƒ#¦Ì¥uä´¶™ „"ÿ£ÑðÑ$c¥üxS¨}ÔºGäÏ$~ Cß¶…hL¥Äþ“I ½=ÔIÐù#‘Jíݘ3ç@£/ý˜똰ÇÞàâ‘“ÏÇk]€qN-køk®ª*œº»»‘H$‚ZЙL&ˆ~dfü­xqÆýøc{g£›Ï0Ì81–1³øïÏÂ;ÿúh +;á ±xKžo4€ÔõÒ‰x<4¼ #¬} ,eh`*—!'Qj "×EÅÉÄròö£}R͈J„ŒŽ3ÜÛ°–ý$Õ­>ùZte!ÃbÈ Iç¥Z[Êí¨-eVµ¤ÜWÒ _k9MN{{˜z¦XPíœÅb¡“Ö—¯sþ8õ[ßjJÃãH­,ˆDJg¢ÈF"uUUE:±hFAÙ…f XlTBQôõõUl¿¦i5ÕTà}ï›…³Î÷)¥™­•RëRÊÚf€ÔÍ2Õ«‘[Ó€ÓOßÝènŒ™qÑäq_ôÞÂsK‘®Ž|ùË?Æ7¿ùIÄbBLÓëPÖsM”¡™aš™–4<Ž÷(0ý¥øésïLJ$Eö0oDò SÌò<|uÁÌ/eè‘5ÌÅ/¾¼Æ¸]Ö—LÊOä„å¶)µNµ·^±‹&H²”´õ•ÚW‰‰~óÒù¦I™Œm‡Zzy€-·_…¢¾•ó„¤ë[ì'{wňÅçµÔ9,6è—åþÈû)6pVêOÞkóÒ½{'öº49¶¼üêøl‡óbÛYºE)XéÖ'ãS²®V%|L‹õ²ÏE)}@)Cr1²(e`–¯ÅhUÊÖ-."%åmu=ô‘u)âþ.lë‡?¼½½k?©“™=.ìë˜qø0€nªáZíÞó<Š¢À¶m躎l6ÈÛ¶ƒÚ.ÙZ-˜ ÃÔ…“ à©EãÊF7d‰ÇkO«Æ0S™ï>÷*æ¡7ÞøÞò+QÄž\ ¼X‡ {y•RÆSÊŽJf¹‚îÅû¨D¹ãËñ©8ŠœfG2a¡u)݈¼¬Y°¬æˆ”â¤Ò9#ÏÊÑœWš¸Ê“›x<œ(å=#g$“ÁxxªñÒK'å<ЉD"H¥RÐ4-ÈbBÎ…ÝÝÝ%#þ<σçyMéHÔ"djI×Ykÿ>÷¹P”ñ³¼P„i³PÇ’’Ž®{÷¾Üèf4?ŠÇ\ÀµÁ2ŠÊd€ŸþôcÄó%ûá0ÌTgê]ÀÑ€ç~õ½@Œ¯m; ]’½òòÏóÐÙÙ‰¾¾¿jžnµL jyCUÛG¹¼ˆ#9N%¾ñlk½Î‰iVßO-ñðʬå8µœû±ö'3ëÖ5Y¶öúò‡%@ÛSO—\ ´¯ÇãñÀk±Šœ 9Õe)Šbf´‹rX/F®-À” Ç>®ãÈÌ™˜¿g” ¿¢jómÛ¶‰DЗ?§Òu}}}M51fFðà¼y8ÿÚkk^?L§T˜ÑŽ” ¤` Œx€ÓØD<ÎdÂ(øR EÈ÷jû–QÊ4×-LËMP¶C¹ òz©T¨4‘›¨¯” RNuNëZVh{Q”°/$;©3ùìÑ1i?t~äæt¾Š£Pês:×Ôoª5MÛQóX,ÌfA¿Fx®ŠIÄb¡/a©vo'ï_ÞG<&/Âó §î®Ô_Ó }å¾ËFx²Q]·ðü“î ¹N7<÷Ü›j~&#?õ÷cÖÙO@Q®Slf2"Ú¬8&Ýø¥h"#CUèF¥h8 ¬ÿ7ZÝ|ÍvZ¡Ð»œ¶”e<õä¸-OQ°=“Á‘]»}&Âo;§¤aβ,Äb1¨ªŠd2¤Sd3)¥?0 –e5UÆ“â¬Îõd¼;Ú†ÅdškÇbÀ_ýU£[ÑDxÀ#;¶ãÃ^é{Îu矟‰DBDF“ïPñØa¦"SÒðhëÀÙßR°bÅ^ÀúA˜|¹Âà:‘H4UІaF‰¼:ã˜{ê2¡Sèë‰étzD‰åV­6®Å˜Á0LýðN9|>×÷Ảì¥ù-‡ã8ˆD"ÈårHæµÕ¥&ÁÍ61fFpë ' uÖYÁwJé†é¸ñ¾ïŒ©pÉg€-¾.ù‹mÏ?YÜwxÏyÀÉ‹ŽGßhþwáq¶8p8´ xx°k®ø,pê—½{/¶»>œºV|Âívç·KŸ œ¶8Þœ¼ xá1àÛo\øË!à'pÙeÀæNàÐߊm¾Øã„û;Ø}²X¶½è]ô¼ Ÿ©ÿÊ£À‹,>8xxáâü:óç½oxÀàg»€ß\ 9|ó`î)À‘üz¿~8­ p¯îmzaðâ‹ÀÑÄñŽž?xd>ðvxöà?§éü5˜5 h?Ä¢À’%À²C@Öþå;@ÇûÅÚ§½§3§,ÌX Ì{82˜;üèðë+¿X>øõû€ÏOŽÝÌ'¶›³صXœ'˜õ°sp`ðÈŸ‹eçœäú€G–‰ãØ/»v ¿·‡W{OÚÚÄþ±ÎÞsÄ=Óû80kpÊ<à¡Óƒù}<1 XøжP\ÇCœîã›»€¹o?8r:ðÄâÑ5þ Зv}]Ü+¯­ÇmZáw9%2§ZÝTé8JŽ 0Mp­Ç©%›XñqJ¥³¯ãP,yô§½=ø]+uÊHFÇšˆ¾P9,¹v ýNi¯)E³|Ÿf2âØä=fÁvMd+oîq𻞇¿¾íd8za€¿a„—ð¿ÿû¬‚Wßd.0Ìh˜z†Ç<ÏýÒÇÕo9*^8Å…Ø‹ ‚Ñ ÃL<àÈÌgqÙ£OÀî¿:48Žƒh4Š\ñàx ¯|†aš pæ^%>Û6®ÐuXñÚR"«ªÔ5QÕ‘¥jf¦ñ¸’+ò9×{Î.[ œ| ðÌN¿Ùù?|Øà^O'+‡€ŸïæwC‹Å²“'ȘU”Ëu?„ò¯-ÿýu³‰Ï‡ÆI''cÞyÀËó<ÓpÒ/ãÄéÓÑÞ1/=ŠC3gbhÿ~œ¸ò4ìÙ³Ûf.ÀηìÄÂ… ñâ‹/âÔ‹:ðµÜ 8ñê“ÐçÂŒËgàà¹/âGÏaÞŠy8|ø0~wÂlì>¾‹W.Æ®]»°hÑ"<±gÌ[€^݃ àû;wbÁê˜)¥Þ{àÐaÌ~Çl âµóÏÇ,oÙµ ;_J^©o?ö½wöìÙƒgç-´=˜9­ Oÿç™Zr3ñÂK;/µ·ãÀà Ž^0}Ï¡]oÇž={°xñb<þøã8é¼ó°sçN,^¼?ؽííí8|öa`æLœtÒIx楗ðÍ7ÌÁÿõ%œtêtüÅ“{±øocúΘ·b}ôQô,Z„]Ø…Å‹#»s'æÍ›‡Ãm‡qpñL>|3gÎÄ#¯‡—ÆÌ gâ£ýaåÊ•xôqÜÇNzçŸ>nß¾+V¬À /½„™'ÏÄáâ¼Ì\<LJ†ð?fbçñX¹r%>·s'.¹öü~Û6¬øÓpzû-Bvh3ÏŸ‰“O>_ùãq´-nÃñãÇ1ëÊE˜•¿gö\»'Ÿ|2¾5s&†††°à¼øý‚—pøða™9¿rqÞÅçáÑGÅW_[‡Ž?„K.¹Çfï‘¶6übH”Xqà <óâ‹xxpÇgGÛ‚6¼þ1à?uâµ×vc埶ã¡{îÁ×]‡=¿ßÕèG²a¸?bç= D¿XU?0©‘Ãd'ré›f¥žZj kg Ðu;`mtûöíƒ{â‰ÈårPç}â˜}ÖYÀÞœ»ùzîj©òDÅéW‹ï¿D"T x^iÁà`hø*Në ÔV7µ–R¾_Ö]p2T•z–äãÈun‹S‰Z³‰Q‰r²ª¸ÏÅëQà‰ÜÎâ>¥R…!k¥ÎK©š.2dt¤’O¥î9%F©c÷¥Ô=@Ë<¯Ð *g÷+v‘K…Qª¦$ÞïwÀû¸†ŸxßÁ‰™I:Äð’.^üuÌœù±F7•ašŽ)gxtVŠÿ ަð·ÿ÷À§³U ‰D‚•‰ 3Yð€§»fã-?ßsµpŒ¦(JÝ꯱ёašŒ¯ÀÙÏc€Þo;¬áº‚RP”£®ëˆ5›g?Ã0Uñ}w~¸i'p \9 ¸,ÁöI„‘Õf‘÷ƒ6ðµ4`,—{ž‡L&Ã0à8<σeYH¥RH&“H¥RˆD"0MÝÝÝèëëCWW²Ù,¢Ñ(LÓ„kÛ˜«i8WQàº.EÁ©® Ã0‚ññxÙlñï|±X Ýÿ8n¸á+øË¿\‚ÓO¾}m¸úꇱaþÀØêº.LÓ„õïˆÿßü&‰â_ÿ:LÓDô㇑W‚«ª Û¶åªã8Ðu™L&¨q ‹¤s¢zb±¬üþìŸý ªªbÓÿ; Ý× (™|:* Þ®]p]7Ø·iš°s9èçž {÷n+W"žNÃ4Md¦ëSkj‡¦i°ÒiÄb1dúú`œ{.2}}ÐçÎE&›…yî¹p¡Î ëë_® më<õ´ÓàP÷í ·9|Ú´iph§œ÷àA('œ7ßv]×á½ò ÔùóÅ:¯½gp:ûða¨ûöÁ žp<߇2}zØö={‚Á‚{!¸|xöYX–%ÎÍ}÷Áu]Äb1¸‡‹cЦMƒëûPòǰmÓÄQÏCoÞIÆu]<òÇ\ýbÜ}÷|¤m<À¢(øÀC5ú‘lÖÏ€ÍØŽžH$Ìa;UÑ´¦4HyžÇq‚ûXÓ´à{¹ÌTò6ÿù?ÿ³³9ÇiùL$/\×…çyAœ¼á Tÿ¨Þ «§.Ä`0/KI¦NeˆcÁ˽"JOUq¯eÁÎd‚1~´8B.išÂÀCQc”йš±–ûPNó<Ñ×§–öÔª­¥ÿlg¨*¿n-ç¼Úq‰Êe±Æ«/r;eÓ sáKÓª—cÎ)Ç1çÀ! ,>Œý’}6›¶Û¡¡! <EaÃ#à ßÜqÇþ¶mÛ|ß÷ýìfߟé½êϘñJÙõƒÏ±XÌ7M³Ñ]`˜qeíÚµnBãúó}ø¾ÿçÿž‹…¿©ªê§R©F7‘aêÆ¶mÛü;Ñͨ;ò˜À÷}ß7}?ñ¬ï·;Žå¯~å_q›ï÷õU߮뾦i~6›mt—fL {&¦k×®õ}ÿ”ïûþ‚ç}?7Š}d³Yß0 ?õ|Uô·lù¾o†ŸH$|~6›õUUõc±˜ÀÏår~,óûúú|Ó4ýl6ë§ÓippÐÏf³~.— æ!¹\ÎÏåFÓ*Áà ïëºï§Ó¾øþD‰*Ã0|Ã0üt:íÇb1?‹U”‹±˜ï·µ=ékšæ÷Õ"l§étÚà§Ói?NË>s¹œoFÉßä101ç4úDä¿O7º9-C,óS©”ŸJ¥ü˜t3ÑrÓ4}]×ýX,æëºî§R©@ŽfÜ488è§R)_Q?›Íòƒö]NVÒºƒƒƒ¾®ëþ÷n½ÕWÅôc±˜ŸN§ýD"QЗT*å†á§R)_×õ@^Ówß÷ƒå$ßUUõ³Ù¬ÀO¥R~___ð}pp0xÎ 7ZNÿûúú‚¶‘*›Íúº®û¦iú‰D"8.-£}éºî뺼?h~K}2 #x}~ýz?¥ë¾¢(ÁõI§Óþg>óÿ¶Ûnkô-Vwî¸ãÿ7[·ú~þ^¢÷uͤRâe›H4º+ SÈ(Ç’SqLP®ß‰ù¹‰ýˆŸL:¾¢ˆ1v*åûª*ô_þò ùwQ£[Ï0ãËxè §\Ä£ÛœâÆÛÞuÀ‚a¿Û¶H$‚T*Ó4aFàÊ0Lëã^$þOXïlñÙq¤Óé)ïåÉ0S ðþÌå°`  žRÙù4™LÂó<èºÎéU¦Å¹­xõÀƒs€ZGÒÝÝX,&Ò¯÷üèG÷âŠ+¾„½{5˜¦ MÓ ëzÂÊ6ÐÿTQXu±,ë˜DQÂì\”©m"0 #ˆê´m¶mW,Q¡(ÀÙgÿº®·|ÔÑxbüj)èFˆªªH—‰fà*"…¼{ÚA~ÃS(ŒÛm>(²×¶mhšD[–D­‘ŒÊd2H$èêê‚ïû˜6m²Ù,"‘HÁ5Òr2®ë¢»»¦iw®ë²,d2™@öѳ­(Je§ª*,Ë ¢ò(bYQ”@ÞÙ¶DÓþÇã8°mƒƒƒDg³YÄãqÄãñ`\Fí¤s ¯ ½ö¢Ñ¨ˆpÎëydyK²˜öGçØ0Œ`½X,UU‘H$‚ë iZð¼uuu¡¯¯Ùl6Ȫ£iZð> è÷®®.(Š<û¹\.ˆÒ¤ýÆãñ@ÆRÛŠKƒtuu¡³³¦iÂ4M´··#›Íï¨d2‰D"EQÐÝÝL>ŠÏ¼óN(Ò¾EÁwÜw½ë]¾Õ«³g‘cŽã¤c¯ ½Ãy^À4¬ã3»W\Œ½ÿƒƒ×A¤Ñ¨øM¼îž…e9S6C;ÃTbêßÌö |íƒ/ ”ᑌš¦!“É \†aZ÷ô眅Ÿ9*>ÿ§bY2™ & ÃL1VdpàÅ%€;ˆû“çâ SÇeYÐ4 ±XŒ•æ Óâ|÷ÀʇõÊÒ¿Ëéì:;;‘N§F¥³ªªñ–[n€@¡ßLN ™5’ Ôw¥ÊÁtøÕ¯L¡Ë0Ìúì©ø¸ò‘†µRþÚ¶,Ëd21ËóÓ5£TЪªm*¥ï6òi“‰"‘r¹TU-¸.ét¶mËä”Úpçw¢···¶›v’B÷_z$i(Uµt:K†aZžGfœŒ3gˆZ ª* @ègPÍéŽa¦2SÎðøÇÄ9 çè¥ çvwwCUÕ fJª–"O ôÙ³°{°ûùÐu1H ï\†a¦.€8~~†3Ož‹u&P©T£ëºÈæëd1 Óútýðéw”þͲ,Äãñ@ÙK \ª­ÇÈ0  &'.M>ô¡SàyÍc˜e¦6󞇧ý98mþ® ;†‰hYV`"Ã^"‘"å(@Ó4#H&“ Z¾ï#‰@Ó4†QÒ(Es›bc žÕX, I¦Q½@2B.å(Kù8¦iÖ<6¢@"öm'õC>ngggAÝS:n©sPʤY¢­ ÀeYµ "HËáºn` „!TŽ•±m;0r3¥µc fRräÄ™xãî?Â4׆ÇXL”Ót]·Àñƒa˜B¦œáñw 0GKz"yž¤Ð°m–e±á‘a&ö%À1¼Žo< U˲ƒ´‰ ÃL1þÓ†{ÆpâÿÄWœ.sœ ¦Àd¸3 SžÃðqÑ£=ÐuátFÝ$†a„½Aü¿ñ‚J¦YÇãp]·ÑÍdf‚ñ<‰Dº®³a¦ ÕŒ‡ÑhŽã†À¾¾¾ …*Ã0“‡ñŽ$f¦uñvö#óþë€L®«BÎFÇ›ªf0Ã4+S*â±÷aà5ÌÁŸ˜o*X^© ;Ã0“‡EûẆ3¾*œTUE:ã^†iIlÀv€.ý#>ùÉùÃ~¶, š¦ñd‚a&9–e!™LrzU†™¢,Y²¤lÄ]<ÆTë™a˜ÉÉOõ4\øÔ/„¹\Žk:2L 19Ùl–Ÿy†™ŒU¢ K&“áh†iaÆC0 ÓÚŒ‡Ø8g9`×]w\׆¦iÍ0£ e ýýýÀªU«‚eX¾|9vìØQuûWÏÀ§_E4…eYH$îÒˆèééA£›1&úûûÑÓÓÓèfŒ™M›65º S–±ÊÙ³gÃ4M$‰–U4N†ûå3VÆ* ¾¸ò8Ñy7}àD£QhšÓ4[Æ!i²Ü“AžM†>´*c•ÀÔsDœ,²c¤LÅçt*]ë±Ê‚ýû÷£½½†a N7º;uŸ‰©ÃTºÖã1.˜jL¥ûƒ˜ ºˆÑ0U®õXåÀîÝ»á}õ›¸ï£ïÄšÌ1Ì룻»žçµL´ãd¸Ö“á9 ãŽÝ»wãñÇÓ>Njt'jåàÁƒP <`Μ95ÝŒ}ðKpáâ#7›-™^q``nƘ8xðà¨òj7­.üZ™±Ê@¤RL$-«hœ ÷Ë3f¬ŒUÌøÅcX˜ÎañçNÃÏ~æAÓ´–’ “åþ› òl2ô¡U1ÁTc²ÈŽ‘2t­Ç* N;í4$‰–ÔŒ~&¦SéZó¸`äLÅó2t£aª\ë±ÊC‡aáÊ0Ó9†³_K"¹\®¥t“áZO†çt2Œ;^~ùe i-cx Ó¦MÃwÿŽ=оs¾óï4ºI#æÀp›7ontSFÍ‘#GpäÈ‘–‚{÷îźuëÝŒQ·}ß¾}˜={v£›ÒžyæœuÖYøþ÷¿_ýêWnΨhåû`yÖxúûûñúë¯ãÏþìÏÝ”º3mÚ4lìS8ðÜsøÚ×®ÂìÙ³ñWõWnÖˆhõû˜ ò¬•ûpèÐ!ìÞ½¯¾ú*Ö¬YÓèæÔ—_~+W®Ä¬Y³°páÂF7§.LÙ1RZù9-#¹Ö»wïÆ¡C‡°hÑ¢F7»îtttà?þã?pÒI'!›ÍbÖ¬YnR]àgbê0’k=Õç7ß|3N8á,_¾¼ÑÍ©SQL]Äh¨õZOuá 'œ€3ìݘöo· ÿÜ1{ëé &Ãs=žÓVwìÞ½À;ÞñŽ1ígJ?ýéOãÓŸþt£›Á0LƒùŸÿùŸF7a˜Ãc†aL™”Š Ã”§££Û·oot3†i04º[·n…®ëcºîÓºÔ" Zéþ+' Z¡ã! ݦ5¯1A­ëÔ£?­:&ªË‚Vè39©ç˜¡ïቖ-ÍÖçzÉ¢fë7S™zŽšõÞ‹,hµg¢^ºŠfê3SõÔ)6ãýÁc‚©s­'šVêó 7ÜÐ’sìÉ ÷Âúõë±lÙ2,[¶ 7ÜpúûûGÜÆf¹ßꢳñ™†±víZ¿««Ë¿ÿþûýmÛ¶ùwÜq‡¿téRÿþûïÖ¹ãŽ;ü®®.ÿž{îñ·mÛæ_ýõþõ×__óïõîÏÒ¥KýmÛ¶,¯¥ìÇý÷ßï/]ºÔ·,Ëß¶m›ÿÙÏ~Ö_ºt©ÿÌ3Ï´L˜Ö¦š,hµû¯”,h…>Œ‡,ht˜Öe<Ƶ®S¯þ´â˜À÷«Ë‚Vè3y©×˜¡Yïቔ-ÍÖçzÉ¢fë7SzšùÞ­,hµg¢^ºŠfê3S;õÒ)6ëýÁc‚ñ×U4[¿ëA+õÙ²¬–cO½'oÛ¶mþ¶mÛü›o¾Ùïêêò×K5[¿™ÊÔsÌЬ÷ÆXdA«=õÒU4SŸ™Ú¨§N±ïLŒ®¢Ùú]Z¡Ï÷Üs¿téÒà¯ÕæØ“Aï¹cÇéÒ¥þŽ;*ö«UdK½t6œjµA `ÕªUX¾|yÁò .¸CCC€þþþ`=¢££Ë—/ÇŽ;ªþ^/úûûaYn¿ýö’¿Ukc#û100€þþþ‚cÀ]wÝ…5kÖ´D˜Ö¦š,h¥û¯œ,h…>Œ‡,ht˜Öe<Ƶ®3Ñ´ò˜¨. Z¡Ìä¥^c†f¼‡'Z¶4[Ÿë%‹š­ßLuê5fhÖ{c,² Õž‰zé*š©ÏLíÔK§ØŒ÷ ã­«h¶~׃VéóªU«°eËlÙ²eT}ht?'ƒÞ³­­ 7ÝtÓ°>È´Šl©§Î椺õŠ)`ùòåÃÆÐÐî¿ÿþàÅqðàAör™3gNÁK§Üïõ`hhŸýìgašfɇ¯Zj]g¢ üÃظq#ÐÑÑ5kÖýiö>0­M5YÐ*÷_%YÐ }YÐ 2™iMÆcLPë:I« €ê² úÀL^ê5fh¶{¸²¥ÙÞáõ’EÍv­™êÔkÌÐlÏõs,² –>5Ó3Q/]E3^k¦:õÒ)6Ó3A}ä1ÁÄè*šíZ׃VésGG:::F݇F÷s2è=;::°aÃÂðvðàAôôô`ùòåA›ZA¶Ô[gÃMÂÖ­[qà 7 ££¦i6º95cYæÌ™ƒ›nº©ÑM7ÜpÚÚÚ°|ùr `íÚµMõ’a¦,  ˦`9ÐxX0­@«ÊŠ‘2™dËHaYÄTcªÈ`êÊ–L-LY0UåÀ²€™<´º¼Ú´iÖ­[‡­[·bõêÕhkkkt“j¦Þ2”#ÌÀÀ6n܈ÞÞ^ÜtÓM0M³enØÞÞ^ôôôàÞ{ïmtSÆŒiš®ëèééÁm·ÝÖè¦1S–Í˦‘°hÊÉ‚k®¹¦ÑMc˜––#e²É–‘²ˆ)ÇT’ÀÔ–‘ÐC#ÿ((¬ZkÕ¶¶6¬Zµ ›6m ŽÝÛÛ‹­[·¤0jæ>0­M-² Ùï¿ZdA³÷a¼dËf4Œ×˜ Öu&‚É0&j“ÍÞfòRÏ1C³ÜÃõ”-ÍÒg ¾²¨™úÍT§žc†fº7ÆK´Ò3QO]E³ô™©zê›åþà1ÁÄë*š©ßõb2ô¹Ù¯ídÐ{^sÍ5ÂæÍ› úÕÛÛ;î㉢:›i¾ïûÞ3f›6m*¸YeV­Zä ÂÚµk144„¶¶6 `Æ Aˆ}µßëͲe˰eË–‚¶–66²X¿~=úûû±|ùrô÷÷㦛n† Z¦LëR‹,hÅû¯X´BÆC4ºLk2^c‚Zש­8&ªË‚Vè39©ç˜¡™ïቒ-ÍÖçzÉ¢fë7S™zŽšýÞ,hµg¢^ºŠfê3SõÔ)6óýÁc‚ñÕU4[¿ëA«õ¹çØ“EïÙÓÓƒ7¢­­ sæÌÁÀÀ@Ëë 'ú~bÃc‹@ù‚/¸à‚’9Û«ýÞ ÔÒÆFöƒŽÝÑÑQ6ĹÙûÀLn&Ãý× }YÐè>0“›VxŽ&CªÉ‚Vè3u¯û³ÕîáñèS³õ¹^²¨ÙúÍŒ“ñ™~·Ú3Q/]E3õ™_&Û31}¯óÒˆ>M´®¢Ùú]&CŸ'õmö> iŽ'»Îp<®†a†a†a†a†a†a†3\ã‘a†a†a†a†a†a†a˜1ÆG†a†a†a†a†a†a†aÆ †a†a†a†a†a†a†3lxd†a†a†a†a†a†af̰á‘a†a†a†a†a†a†a˜1ÆG†a†a†a†a†a†a†aÆ †a†a†a†a†a†a†3lxd†a†a†a†a†a†af̰á‘a†a†a†a†a†a†a˜1ÆG†a†a†a†a†a†a†aÆ †a†a†a†a†a†a†3lxd†a†a†a†a†a†af̰á‘a†a†a†a†a†a†a˜1ÆG¦áxžÇqÆu¶mOX{mÛ†çy 9v3Ÿ†©7•îçb¹Âr¡<ÍÞ>† £¹¿G2&ágŸaš‡r÷s©¹ÆHïÿñ’ £9v=iæ¶1S“ñÔð˜`|Ï ÃL$c}ö'rL0š¶´¢lhæ¶1Ìx0‘÷8ÏlxœDX–×uÝŒšñ<ÝÝÝhooGWWºººÆeRá8"‘È„µ;‰”mçD»™Ï Ó8ZíÙ\×-y?—“+,ÊÓìícFÇT” ¥éýÇÇk^ŸŸ}¦Ù˜ªÏ~©qA¥¹ÆHîÿñ” #=v½iæ¶1£§åÂDè xL0~ç†i ¦ê³?‘c‚ÑЪ²¡™ÛÆŒV” ÁDÞã<°áq‘ÉdZJpÄãq¸®‹ÁÁAø¾UU‘L&Ý,†i9ZíÙ ®ë"“É »»»äï,WF0•äÂxaÛ6Ë ¦å™jÏ~¥qÁxŒ X.0“V” Óó³ÏL¦Ú³?Ñc†™,´¢l`Z“Ikxô<ÉdñxÉdrXx«eYˆÇã•ß²¬à7Û¶ï¶bët</Øw&“)Ø_ñ‹k¤ëW‚¼íä¶Ëý¡—l­á°´¿d2ôYþ^jjû«µ¯žçÁ²,¤R)(ŠH$PUµjézyž\§j)åk9Òí«QéZV»«]¶ía×»\Û«m;^ýnVøÙ¯}åžý‘<÷#ík-Ï_¥þßÏÅ×¾š\‘×lrA>nqûkÙv2ˆ±È:_¥dC#åí¯¸ýô½Ñc‚‘ö·Ú3XI.Œäù-~öååÝÝÝ0 cD× ~ö› Ô¾¿FÌÆ:& ëTj\0’1­_|­ÇK.”ë?ƒåBý©tÞyL€šäÀDŽ ª=¿<&ág¿vx>Pû¾5˳O×h¼Çã­'¨t­G+äsSî\°±<1& óZë½_/¹@ËF"=&Ë|a,öƒVxöÇ2&¨eûñèû¤4+›¸¯ªªã•J¥áë”Ì/¹\k]½ü=×r¹<`\UÕqY–ÇeY—$)vík/ý¾…B!¶ Àøèèh¸}tt´ª âýQkÿFγR©„÷†x/išÞ{õîÃFŽ!"^»dù|~\Ó´ ÷­wÞ”i.Àu¿1&ªû“©÷“=×FêßDç›ö[×oWæ{»0>^¿m¨·ï|o¦Ú.ŒOØ6´²] üjÕ•V÷ &{¾ÕÁzçZoßï|ç;uë>¥UeÊ¿×ýö„ûÑÊ÷éê¤ýÞ½kLÔ/˜Žvò©Õ6p»Ðj]÷üàÜ'¨‘WÚº™ìLT¹OÁu¿1ø}`jyÍöû@3u¿ÞïÝLŸ Ùq*÷DmC3íC„Çc¦út]½÷g³]Ÿ\ÛÐê>A3ï ÍèÓ5FHûµÛû@½ý§³îÏK‹Gš™–Ëå™,•J²,ò,¨ª›½F.4lÛ†,Ëð<¶mÇ–E“iq_I’BSý‰ÊÓhúz¨ªššïtä—¶\k]³ç*Î8Æðð0t]¯Rõëo>Ÿÿ×u=–/r­å"e¢ý'Âuݪ{‰òË›v6åA3lÛž” †´óž/¾½¹îO-¿F–½öžëDõo*çÛH»2_Û€Û†ZLµ]kZÙ.ÓÛ6LwŸ`*ç[¯Nt®iûþû¿ÿ;€ÚuŸfh–J¥¦®×ýöƒûSË/m¹Öºé:×Võ €ô¶aºÚÊ«VÛÀíBk¨uÝ{ì1îÔȫֺ™ê4R¹O×ýtø}`jy¥-×Z7ç;uªùõÇ š'¸OÐŽÌdŸ@̘¸®Ï¥v!m];!6£pÝ—w²uÞ •J€oFÚÑÑ\.u/°ëº¡_]ñ3ÙÊÃL ]SѵA>Ÿí©l¤EA>ŸûÉî?®ëÖmê݇Í`:::BßÙÍ>ŒšÝ¿àº?w™Žû°^»òä“O˜¿íÀmC-¦Ú.Ü6´Í܇⾵ê¾iš$ –eÅâ9k–Fáºß~pŸ`î2Ó}ñ]#­m˜®v¨ß6p»Ðj]wî´3=VÀ}‚©]·¹ ¿Ì f¢îO&ßÉŒL¥npŸ ýà>ÁÜeºÆ ®ûS½npê´œI›áº.$IB©TB©T‚ã8Èd2P’$Õl@h;ýàÂÙ I¿ÿLsÔ»Y½‘=Ï Ó’Ïa‘R©Ïó‡´8oõöŸY–SÑõîCqÆãd°, ¦ibxx8`{2³-š=ïv†ëþÜa&îÃzmÇYg`~¶ · õ˜j»pÛÐ š¹ëí[«îO×Ë!×ýöƒûs‡ÙZÛ0ƒFõÚnZC­ëþ®w½‹ûmÂLpŸ`j×m.Ãïsƒé¨ûSÉ·^Ÿ€˜ŽºÁ}‚öƒûs‡™'¸îÏÄ5'æ¥Å#}¥ "Ërx¡4M ƒ þ…£ÀšªªÆ–(@é\a®<E,˱@¦†a@–å†éd YI’ª^(`t±X¬š¥ØÈþõÐ4-x•f»õîÃFïQñ’$…F­™_iû¦7]óù2+‡ëþÜ¡Ùú—F½vå / ×Í·v–'jêµ ÉsŸOmÃTÛ`î· s­]š«ƒiû^vÙeẴº¯ª* …Bø¡v¤P(Lʽ ×ýöƒûs‡Ùî$ß5’mÃtµ @ý¶Û…ÖPëº+ŠÂ}‚6a¦Æ ¸O°pë>¿Ì ¦£î7›o­±‚éè«ÌdŸà1Ä©°PûtNs‰é'hT?h÷ºßLŸ ÞþÉsŸjÝŸ—º®Ã²,tww‡…¢(Ð4-T‘3™ TU _.é) 0 #l<\×Í`hg$I‚að<¯)U|¶(—ËÈd2áµö¿,œº?ùŠmÅ8›Ž¾ÊLõ Cœ* ±O@åŸkmÃLs¯î7Û'˜ºß1>>>>µŸ¼ý!Õ–f+‘é3]tY–aš&\×E¹\Ž¥"óé¹€xnÓ„t6Ë 4îÚĶmd2Œ‡¿ñd~§f÷Oâºnh6 +í>lÇqày^êï™,72¦tõöMÛ¾Áu¿}™îúWïz³×®$iE» æ›Ö6L´oÚþ󉩶 bº¹tmæR»4Wg£]i®ûí÷ Ú—víÌõÚnZCòºsŸ ýh‡>}3pŸ ýà÷¹ÁL=»Û¥M™‰>ÀcˆÍ°úb¹çBÛЪq‚¹R÷›éLeÿÉ2¯…Ç4H© UæL&ƒ|>ßR•_l¬jÑè÷ fnæ/ ¡]˜ ùµ+\÷gÁY<2 Ã0 Ã0 Ã0 Ã0 Ã0 Ã0 3ýœÒê0 Ã0 Ã0 Ã0 Ã0 Ã0 Ã0 3÷aá‘a†a†a†a†a†a†a˜¦aá‘a†a†a†a†a†a†a˜¦aá‘a†a†a†a†a†a†a˜¦aá‘a†a†a†a†a†a†a˜¦aá‘a†a†a†a†a†a†a˜¦aá‘a†a†a†a†a†a†a˜¦9µÕ˜ üqT*,Y²¤ÕE™2/½ô–,Y‚ÓN;­ÕE™2¯¾ú*Nœ8³Î:«ÕEiŠC‡aÅŠ­.FS,Z´ŸúÔ§Z]ŒYçË_þ2^{íµV£)æÃýÇíY{pâÄ d2\qÅ­.ʬ2úóáþæG{6Îᥗ^Âÿøÿ­.ʬòÍo~?ÿùÏ[]ŒYe¾´“e>ÔÓÉ2•ßú¼óÎÃý¯ÿµÕEŸUÆÆÆðÅ/~‘ëÄ€Û¿Æà÷ƒ¹û~0b[0Æ"¦Âdë…:fø™Ï|]]]­.FṠz=êé|èw=z===xï{ß;å<„ðhÛ6V®\‰7½éM­.Ê”±, ëׯŸÓçðì³Ïbhh×^{m«‹Ò}}}¸á†Z]Œ¦øò—¿¼ ;sþ¼çÃýÇíY{ðì³Ï¶í7°0úóáþæG{6ÎÁ²,ìÚµ 7nluQf•þçÆ'>ñ‰VcV™/mÇd™õt²L巾뮻œð¸k×.ŒqXpû×ü~0wߦÂBl æÃXÄT˜ìo½PÇ |ðAÜu×]­.FṠz=êé|èw<ðÀرc qÚi§áMozÓœP˜ó燞óç°|ùò9Û·oouZ™gž9ç»ùpÿq{Ö>>|¸ÕE˜uæCŸ˜÷ß|hÏæÃ9 ´º-aéÒ¥sþ·› ó¡í˜,ó¡žN…ÉþÖ õý`ÕªU îþà:±p˜ÊoÍï ‡…ØÌ—±ˆÉ2Ùßz¡ö -Z4çïùP¯çK=ëýŽgŸ}{öìi*!<Îz{{[]„¦Ù¸q㜮pÄŽ;Z]f3î?nϦ9æËý7Ú³ùpÌÂa¾´“e!ÖÓ…ú[3Áubá°k¦qâý1Æ"¦ÂBü­§Âúõë[]„¦™¿õ|¨§ó¡ßñ¦7½©éÉH§´ú$†a†a†a†a†a†a†™û°ðÈ0 Ã0 Ã0 Ã0 Ã0 Ã0 Ã0LÓ°ðÈ0 Ã0 Ã0 Ã0 Ã0 Ã0 Ã0LÓ°ðÈ0 Ã0 Ã0 Ã0 Ã0 Ã0 Ã0LÓ°ðÈ0 Ã0 Ã0 Ã0 Ã0 Ã0 Ã0LÓ̺ðxã7b`` u[__.¿ür¬[·Û¶mÃÈÈÈ”Ò0 ÓþÔj ¸`˜…÷ †šk ¸`˜ù¿0 Ãï ÃÜ'`˜ùÀ¬ Û·oÇÐÐPê¶¾¾>ô÷÷£··;vìÀÈȶmÛ6é4 ô?µÚnfáÀ}†a€æÚnfþÀï ÃðûÃ0÷ fªX­.@‚Yûûû±nÝ:ôõõÕL³sçNlÞ¼›7oÆÆqçwbhh;wîœT†aÚ—‰ÚnfþÃ}†a€éi ¸`˜¹¿0 Ãï ÃÜ'`æ?^ð™)ŒN?YfExܸq#vìØ;v¤nÂÈÈ6nÜ®[½z5Ö¯_]»v5œ†a˜ö¦^[ÀíÃ, ¸OÀ0 Ð|[ÀíÃÌøý€a~?`à>ÁBÅàN"½3Éü'+ôMVŒ³'‘ÖšdúÉ–ÃMäoÖIï¢ÚBr²×v"N¡s±zõj¬^½ºæö#GŽ@¬a€åË—‡¦Õ¤a¦½©×p;À0 î0 4ßÐznfnÃï ÃðûÃ0÷ æ6µÁ´$vÉ ¦·(“(K@¡Á´.&'¾9‰s¥ýµ:×E¶Û¤:çCç* éÕéHpt‚4|UO”WA$:ºA:)øßP Ò¾tê©8¶té$®F5³ã±U:t}}}uÝ60ÌB ¿¿[¶lÁþýû[]”–°ÿ~lÙ²ýýý­. ô”-[¶ ¯¯‡juQfêlÙ²¥ÕEa˜–244„-[¶àþûïouQZÂÁƒöp!áylÛ†mÛpÝÉÌ-fæ+ôL8–_T4…ã™BZÚN._5Dî]ßð .lÒú¹-„GšU” ô:00úvn$ Ã0sn†¸-`Æg¢z>_ÛI’ ªjøÑ4 º®Ã²¬¦ò5Mº®CU£¹Ãªª"ŸÏ7”w³®YÉÅ«çMfþ3³Ðá>Ã0· Ãp;ÐJ\T»'-ÖIï¡q÷£$؉ۓ®Tiÿ"ªEFûÄø†€oõg#Ôl!/1¤5…ãʈ„J+qL²$!‘„>¾`HçNb ~g²¤ïòÎyæ‚ýéØz^ÊTöwƒõƒ†Y;"øŸDËJ°,ZL’¥§äGå ÒÓ›b À£YÚBx|sîþþ~Œ¶oߎÎÎN\wÝu“JÃ0ÌÜ…Û†an †ñ™¨ž/¤v@–å¦ö—$)U8Ô4­¦ËVÀ·”ìèè@&“Aww7zzzBñ°£££Ê5¬¸Î¶mtttÀ4Mtww#“É «« †a´úr2sî0 p[À0 ·ÓY6 YÕ‰Ô›J˜|ãH ‰är4)8R¾iûÛˆÃ0ÀÔÛ‚ÙlfÂJ/M¼s™L|²,ˤææ ¨ª ˲`YŠE¾°¦iÈçóP¥j²¤m²,£\.7~Ð1ÿ|>×uaY Lü~À0 ¿0 pŸ`6 Ñm"¼”e/±, qi‹Iá‘ÄKr+J®I)-Y3’hé!²”ƒô”NAd)!ΔķŒ¸0IéKBM87²$W¬ºFþdaŠHä¬%à‘…!¡y×J/þN&½½Qɷʉ–›¡m, òÇÜl†aæ.Ü0 p[À0ŒÏDõ|>µªªV¹>5 ÙlÃÃÃM¹\%+GÀ8mÛF±X„mÛ®7UU…¢(èéé¦iPš¦Mº I‹JY–ašæ¤ò`î0 p[À0 ·Íâ%¾k¥­ E’îQE7¤bäx )F¡¸?寡ÚÊQ ò1 Ž"7 €/’ûQ ²~ôP-äQþeDqMÄ…H$Ò‹å’ ”„øÖ¤ ~~ꋃÉ7©<ê‹}MMÕô<(â;žçÁ²çyØû­oኛoNÝõ¥—^±cÇš9zû Ã0 Ã0 Ã0íD³®N›=v±Xœ²ËU×u«öU%»»»aš&òù|Õ¾ƒƒƒ°, ŽãÀ²,†|>?©r$Íf­7†a†a†™iq)>!QDµÅž¤! Çdž¢ÈèÂù$D–‰žð¡8ƒ…`™K²­a! iI%ËÀ¤§,¬Ý¡VR®'),Öÿ’é'#qZߌ, ÐÙ³XÄ÷6aÙ4MH†QSx¼÷Þ{ñÔSOásŸûÜ”‹sÊtžÃ0 Ã0 Ã0 3}xž?yª‚çy(‹°,«j[½<É"RÓ4  "ŸÏ‡nZk•3-×uS]»2 Ã0 Ã0 3y:0¹¸"/Q\v…ÿ“ù¦Y@’)!Š)h÷,¤^.øE¡.¤'!1È‚P‡/LRLDÑRPEdUHëE È$¥”}å:é•Dúa:†a†a†a&‡›ø|KE‘ÀfÃëlDÂáDù‘°HB¡#ü¯ËNb™þ§xY4–j??ÁòDÔ}»ð<`‚ð ®ë[Ò»V`A8¸® Y–Ãðº®ûÇ$ “Á®{ï…êyXñÐCøõòå8pñÅ@Ovßp~£³OüÕ_á:ÇÁÈüNSt<ù$Ž.^ŒWÇÇñÓ~÷™&þà?þÿ÷/þõ÷ã‚;ð‘nÀ­¯¼‚O9WÜs°bN}é%ì¿ð¦΅…G†a†a†a˜€,Ë1W©PO(lTDd±‘a†a†a¦Ÿ4á±_ø£^¿_ô£‹$ ˆC/å»ì+ËEa_rµJù‰½}©ÎòlÆ@t]fw7ôááÔw ×uñD?P*5š¡/d<}Ï=8sÏ\@B$…¡&w’ˆ˜…£e9ö"—ËA×u¼ã¼ó°ê¾ûðÝ÷¾·¬Z¨*~½|9þíÿü¼iùr<üðÃ8ûüóñ£Ïú /àWÿùŸøÆúõ¸ýá‡ñŸ—^ŠÕ=†W¬Àþ—_Æ+\éïþ7Ü€Òð0ö\=Fÿîï°¡PÀ/ÿŸÿ¿~þy¬Ú½«J%_XUUyꩦ¯? Ã0 Ã0 Ã0 Ã0 Ã0 Ã0s'e¹N%qR–=D‚ lwƒíä:U ¶ƒ´eø‚¥‡H„¤ØŒ„(zÒñjÙR<ù™˜¨èº.>vúé©a%ˆ¯Ÿ{nƒÖ‰\«ص g®^ ¢úŸ@xüÖ»ßÖ¯Ç]÷ÝW•išÐ4 ’$ù%€ÃÿûãŸ}C®‹¿]´õŸÿ‰ŽÃ‡Ý»qç~„õÇcÙ£âä>€ÿß¡CXµaþè´Ópø¯þ ®ãàS»wãý®‹E–X®¨TðÙL¥o|pƒ,#›Íâæ5kpãƒW_Ÿ~æ3è‘e`Ï@Óüòk7ß`á‘a†a†a†™f(6%Ã0 Ã0 Ã0“/òM%*zÒ•)Å\$ARi=-“;UMØOöÕ‚´$*–˜)eHJˆõ" zÞDÎ_'@Œ¹˜@’$\üÊ+p\7UØüÛÏ~7ýüçaHˆÐš1)T:`Îgɪ@OW]¾<^Ï, {ÂgöïÇ6T×¶íð=É0 ض[N?KÊeÈÇŽáÂ+ðÉsÏEÇË/ómÙ¼o}ñE¬]»ç<òpýõX¸‡ýÃ@çYgA]º€ïáš$I‚çy±s/ øü ®;÷\,pÕm·ùeþ‡ðÏ;ï;º=ð‘Mý4§4÷Ë2 Ã0 Ã0 Ã0LI’&Œ!É0 Ã0 Ã0ÌÔ©%ÛÙ‰å¢ð¿–Ø_AdñèÀ·XLëÅ'ã6ʘš8+§m7—A±XµŠÄÌ¿ýƒ?œsà@l»išèééÁÆÇqáØ\²b,l6žY:Ú¶/pª*ày8ø—‰ÓžyÿúŸÿ Ø6Žßr‹ŸN’ðüÿ1î Ž}Ë}÷a×w¿ Èf³0 ¹\–e…–˜¶mã=†Îw½ '6l@çïý.Z¹P8’„O½ø"®üâqÎ'>•! P(à3ûöá Ñ5ª,ØX.—c§cY޾þõèÏS’r÷*MŸ3\†a†a†ažçÁ¶mض½`3 Ã0 Ã0 3gÅFÑ’Q\NKK‚£œò-¾¨ò²‚xœFÕVÍ0Õ÷Û¶ñä·¿í»ku¢3Ï¢ÚÇû·1zöÙxd×. ˆ©W\x!Þ¶r%F«ÃsˆöW”ÐÂñ[_øÐÓã yŽã[V*€iB²mX¥Î{ßûpò¿ý7üò_þ£ƒƒx²« ìÛ‡ßþøÇ1¶buvbÉá9¾|÷ÝøÂ»ß|àfUUU”J%,{öYüìå—±ä#ñEÀÀ’sÅ?þ#þûŸþ©_.EñãQ6"q+“–žš¦Áq,½ã$6Lã/êÃÂ#Ã0 Ã0 Ã0L‹Éd2èèè¨úd2™˜ ¢L&ƒL&S3Ã0ÐÑÑ[çyr¹ºººÂý»»»«òf†a†a¦µL$ÃN?c¢"ÅqLöìE!’\¥$.’4%Z4J‰ÿ“ÛÒ›Nž±‡šœðX,†.Q%IÂe££X72Z>:ŽN´¼ë¶ÛpìÜsqâôÓÃÀMW]…—\‚{¯¿wÝ?~õ[¿…{/ºÿñƒ¹\dÙ˜ÍÂ5MüA__t=e°md³YŒ|îs8íÞ{±ò´Ópâ®»ÏêݻÑuø0^~æÀ¯{:/½g\r ~þw‡\.MÓðÿ®YƒÍ_û`úNjiBè%—\‚K{{CW§$@–qé»Þ÷"#7xåkÄÌ”eù|¾±<š„…G†a†a†a˜6€â"Ò§\.Ãqär¹¦ò-‹°, •JãããG¥RëºMçÍ0 Ã0 Ã0ÌôѨðHNFI$ã-zÂ2ÉV2ânV5øâ#í_@º‹U¤¬Ÿ.‹ÇkÇÆê a]]]0 #Za€ë¶mdzzÿò7ãÇ`´m\Ø×‡A]‡aøÃ‡Æî¯|r`Íøßþýß±d×.\{Å€¢à3×^‹Kî»ë/öEGÏó?×…«ªùÒ—°äâ‹qü{ßóÝ›:EÁ ë×clÅ dÆÿüÏñÌç>‡Ï®X{?üaüøþûý´…P.££§ûöíƒ,ËPUñ몪ÐuËî¼3.’…ã4#I …fä6Æ©³r†a†a†a¦.iqÇA1%vÉd0Mº®ÇòVUù|¾!áÑ ^Ö•”—_Çqày^ÝxŽŽã@’$ÈÎÐe†a†a¦&|kF‘h#îzÕFä•þ—Y,Jô -¹RMëÑ'-UÔŽ-9! Qâ¹çžÃO÷wqË÷¾OW,ÂÕ4(Šâ’§Eâyøþ÷¿ƒŸÿ<®]´È_oYèüÖ·pÚEÁ{õUȲ ˲ð¶ÁA<÷þ÷ãJ×Åá]»ð›¿úU($š®‹ë~øC\ ²Œý^ˆ5ž‡Œa`À“]]Xö䓸øî»a˜&<×Eþ©§B‘ò³Ù,dY†ÔÛ‹óUgÜtS$J–¾÷½øØ{ß‹‰ïJÂ;UxnÉ÷¬Y²JœIØâ‘a†a†a¦iV°“$)Õ…‘¦i¨±MÒpÝÝÝèééAOOº»»CÒqœp}&“AWWL3šgÝÑÑb±îO®]‰l6Æ_×Ñуa†a†a"boØDÜ ’DG‘U£'|«AzI`"ëF’¹H¸$Y,Mî"ÁR¤(ƒ5N,pg ?„¦(øàoþfU²§ï¹®eá]Ñ$ÌàÁ¶m†o=ø ö\}5GGqbÃ<½?^¹øb¬?~?üò—!¹.4MÃ%Ï=‡?xè!œöòËØwÍ5Xöì³aÜF]×qæ_þ%ÏÖ$¬ýÂðçŸÃO> Xvçøëÿwttwöíh²egQÓ4˜¦ -IUUÇ`TUÿ»xS¾zs †a†a†aêÐÑÑá»óÉd`F'‘þ·m;L“ü®µOžç…1Iè…Ú4ͦãphš˲ÐÝÝ Ã0`/ûi–"Ùlªªbtt£££PU5 é{ttããã¡õ¤(pš¦‰r¹Œññq ¶íPœ¤2‰1&-Ë‚¢(©–• Ã0 Ã0 ³1¹W"щu„‚H¨ônÉ( ‰Ó³± ÛC¿ Nh¹è8\ÇÁcßü¦o éyþ·ëâÈSOÁ1 |æž{pÃ駇»îêÂÆO~ô/ÿUUqþM7áÅ_Ä»váЃâ‘%Kpʾ}Xõ÷˜¦ ñýïCr]\ú{¿ç Џ.Çñ]¹ (º.òù<>ñÃâ莀$áë»váþ3Î@©TB©T‚¦i±Ósñ²á‰¢… ëÇjœÃ°«U†a†a†a˜:Œ@]‘ŽÒ$¿ëí“Äqœ*QR–eHMΊ- PU–eÁ²¬pÖ°¦iÈçó©BŸeYp]…B!<~>Ÿ‡ëºøÆ7¾×u1<<ÛfYLÓ ã†ÐÌ_á `&5Mƒ$I°,+t1$þÏ0 Ã0 Ã0Œ/*&ß(Dá‘\©Jˆ»@—µÄþù –'EÂ}j ÏÃÑ£Gq¦ø¾á8€¦A–etÞx#NìÞíÇhTÀ¶qðÇ?ÆÕ'ObݪUÀ¸¬T¾üeÜù£aümoÃ-÷݇ÑK/…êy€,ãËÇŽaÓ-·@ýîwqôÏþ øà}+Ã\ª¦á£çž‹w8”J%t± ET5|Wsù|ªªúï2¶ ìÞ EQàºnÍw”|>?¹wµZ±3_”œG0Ùâ‘a†a†a¦ PUãã㱦iÈf³©®R'›w©TÂðð0Q(B‹LÑêpŠ¢Ä^¤eYF¥RÁÐÐP¸œ<†è&u"ÑUÓ´ÐúÒqœº/õ Ã0 Ã0 3ßi4v¢háH=r Q¬F +Ó$Ai‚å†qœ¸Ec‚çþáàˆñêÉâÑó`š&þbß>¼rà€/ôÙ6 IXôôÓ8pÎ98çÀ@’pî±c8üû¿÷=ú(6Ür I¸âÚk\°,üåÁƒ8ç#J%œyõÕ¾€Gï!Š‚;‡†üw ZGÞd‚‰†a ›Í†ï%þÅSYŽÜ§Ö`BÑѶ!EÝtÞ”#g¶%,<2 Ã0 Ã0 ô)d=h6òš‚뺾û EQÏç188/xéO£YKˉ +L*YA2 Ã0 Ã0ÌBd¢H碥#M×#aQ‚/>’u£lkÚ©§eÕÞæyxñ¾ûjìfá_ÿõ_qøðáØúçÿå_ðÈ'?‰lW2Å"¾¹e `Ûp‹EÀ0°bl «^xÁצƒ• ^yä_TU›ç’yY¡øŠù¼o)Ë€$U¿_Ðrw¥R 'fÆPUȲÜÜÄHÏ«ýD摵#ÐFÂãØØn½õV\~ùåX·n¶lÙΤéëë ÓlÛ¶ ###­.:Ã0Ó· ÃÜ0 ãÓH[°Ú²Fœª çyŠÅ"¬”ÞzyʲŸõä•Éd°fÍšXÙÛ¶o‚¸»U˲ªb¦0 ÷ †¸-`fáµÔËvË@d(!î‚UN,§Åvœ,Žãàá/})¹2üw÷}÷aÏž=Ñ6Ó -üÇÁ‹á=+WFÛËeõ”ŸmG–•£RËR0ßTäÊ™!p'[e©6+·§¶ºD?n»í6lÚ´ °qãF¬[·ؼy3`çÎØ¼ys¸|çwBUUìܹ3Üa˜¹ · ÃÜ0 ã3Q[0ÛÇqÉdbëEA¥R‰ÍÂMKããã©ù–Ëed³Ùª}dYF¹\Ná+I … ÃKÏóBD•J™L–eA’$¸®‹B¡0a\Ç$š¦¡X,rlG&î0 p[À0ÌÂl’Ó …H‰P‰‹2€ä[õ¬›µ¡»ï¾û°öᇣ®‹ExäÈ>ë,\,îx@Éf³ø§;ð³Ï Ðuxž‡îŽt:„K®º (ñŽ~’$á7ÿñµk«E8rš\?‘kÒv± l$vc¥ÒêRN;m#<&‹- add7n ×­^½ëׯǮ]»ædãÁ0L}¸`à¶€a±-˜í@¥Á—͉Ò …ªø$’$¡R©Àu]¸n4_z"‘P×uhš'p§¤(J(R*Š‚áááp›,Ë17«i"hZÙE©)˜2Lî0 p[À0ÌÜjH@ltzžßµªÈº‘ò­ëå7]ѯ¿þz,Ù»7Záy1W«½ü2î~î9¼?X>¹g›&޾þõ¨T*PUÝpà»ßÅ£×\ƒO,_Á{ Å|ÔõP´ŒAë%.6¶£EcE‰„ÓFÛ·Ývúúú066†Õ«W£¿¿ëׯÇu×]ÀWÏÄX¾|yª?g‘W_}Ï>û,–/_Žõë×·úT¦eŒŒŒ`ddGmuQR™ÉvŽ=Ь^½«W¯nõé2LËÀ³Ï>‹W_}µÕEIe6úiû3ÌBbll »víÂZ]”šÔk víÚ`ê}‚ãÇc```Á½$ÅÁF$©¦@Yo37‘#GpüøñV%•™~?8pà°aÃtvv¶út¦eðû¿0 Îܘád…G%ØÇAµ«U¾;Õ‰lùê0pÝt/…Ç¿ðœñÜsQÙ' àùçŸÇEþp¸üêÁƒX<2‚—¿üeè?ù \ÏßlތÕ Nß½ê¾}8#›¬%]÷'3NvA–ãVŒíbÑXr ø¢-ý_#LF;0444-}‚¶7lØÀ7›îììÄÐжnÝ:-ÿ'N`hhguÖ‚X`˜$###ÀË/¿Üꢤ2“í¼üòËÀÆYxd48pà@Û°ÍFŸàðáÃ<°À,hŽ9¶íÊL¶$<Ò,h†Y¨ìÚµ ###m+<Îôû «W¯nÛ~ÃÌü~Àï Ãc†3;fè6˜F”£»íú™L&Œ¥˜¹#íèèÝ1L³Ðsu¡¾\qÅm×0L+à÷~?`3œÙ1âüÁL,“訰¦³0–•.âY–oUØÓã c¦‰={öàøñãpm;zÿ$(Žƒc÷wÈ‹xôïÄÊÁAþÿþ?ô”JÏçÑßß+W¬ÀÓÄkkÖ`üì³±êê«ýýÅm»aËËym™LÛˆ‘›7oÆêÕ«›îœÒêüÀ¯ccc±ÊM¦Ò;wMküx–2ÃÌ}¸`à¶€aŸFÛ‚ùÔH’EQP©TR?D>ŸŸ´»T†™‹pŸ€a€Û†aæ~;à4™VN|7¿Ñ«!ƒšfCÑqËÂS\€SßúV¬[¼Ø__(….ºûnl;~߸å,yåøú×qv©„J¡¨*6ûÛ¡òÒw½ WúÓQŒFr©ª(3.<:NüІ1£ÇK%“™8Í<œTÚÂc#f›4óˆâ¹ä…‰cšfó™0Ì,ÂíÀôàºn꺖“Žl˜|Å8Ç Ãÿ&AR’|ëG×îß3ÿüÏ£í®‹3^}¯]z)®_²]==èêèÀ“]]xíñÇC±óÒK£‡$:Šï1Š2ãq“IKÞwÚ8žãLÒÂãÆÑÙÙ‰[o½5\700€x æê`óæÍèïïÇØØ`ûöíèìì ƒÈ2>Ž|>\.>#LÓD¹\Æøø8aÛöœœ¸ÂÌ?¸OÀ0 ÀmÃ0ó¯0çhÁÅ‘ø¨ÿKÁúI;'Å6UõÅÀ`Ýh¥‚Ý/¾¥Éd0:>Ž‘‘¼ðŽw@×uœ|ó›qìÜsqòð‰‹/Æ#<‚_œyfd½¨(8~Þy8±j–½ãÂI(3îB4ùÞ’ÇÅlj½+Ù¶ŽŽŽ-Ÿp°Ú˲¹ŸGœ:•FFF044„ÎÎÎi ¾¼yóf\wÝu¡9ôêÕ««Ì ;;;qÏ=÷„-7lØÐv G»@âCOO …BÌ=ÓBf8H3l²ÝN¸® Y–áº.$IšsçÎíÀÔ±, Š¢„Ž™Låræ¤ø4 Ã@¡P]Ô™¦ ]’=…W:ç\.‡B¡Ë² ª*ÇA±X„ã80MsΞ;· ÷³Ú$=–S×ÚF4õ8©ÕéÂ:ÕS› ñä4q0ÍâPUÕXœG zq.—ËaŸ¯T*¡§§'–ƶm ‡îYóù|øœMÓ 3Eªªì=…i¸OÀ0 ÀmÃ0ó«H‹°X/¶#à¿Z¨ˆÉI‘œ¯(¾e£¢àÕƒ±ò¢‹]÷c<:î¹æ\ýüó¸ïèQ(ögøùÛߎ=o~3^wð nyøa|móf\@îS]e¼é“ŸÄñgŸöïŽCÖŽ3y-Ž–eÅÆh¼œÒÚ¶=»Z ‰½µÆgeÙ¿þóŒºÂc__vî܉M›6…3úûûcfÍëׯÇí·ß>-AZ2§Kìœï±PÇ …UUaÛv'g¾còù<ŠÅ"òù¬¬###¸õÖ[±~ýzìØ±wÞy'FFFÐ×××êó`LÓ¬hŸïÂ#ŸeYp–eÁuÝ9kéSëi¼çyá9†×uaYLÓ„eYᇙŸÔò]nYVXïÓºbÚvG<'ñœ“šaa°m;l¨îÓöv¢Ñòй“{Ÿ,ô’–z…izÑ©ArÌ;-ÌPrì-9.šüž5T5r©ªª¾ú¾÷² ]×!I¾¹g (ñ±¦¶ØKÛLŽƒ&½ÀÕó¢1ÂZÂ䌣ª‘P[©Dnhm»¶Ö9LªðH¾’7oÞ[?44„õë×Çü'oÚ´ €o ÉÌ$ºÑ 6 T´m>ày^hÝGÖ~ä>–¬:i™„ip¿­=ÓfUй¢¨bšfø¡óGÛ¶CsÑUÖ\±nc&Gš5 (BŠiÚñþoºÿÅzN«(,¨r3J×€Ò'­&g«ìgQ´ÄχÖÓ'—ËÁ󟇮ëÈår­>m†a†a†™×$Gê]ø£-‹q?€S/ÆÄ5 Wär¥u®‹‡_yk œõÐCøØüžÿøÇqà{ßCå߈ÇPTU XŒ{Ô Æ ¦ ''LÓ ÇµüSsbczôΤiZ86XË‚1mœTӴиgÖtƒLÆ¿nÂy†¿Q c<ŠçïºnÕµo–TáqãÆØ¾};ÆÆÆBñqç΀ 6ÄÒ’à¸~ýú–]¤…@Rtâê= ~Ó¶v& ‰eÉYd¹(è“$]hp½Õâ+¹€¥~ú=hÀŸÎþ§s!áþW%lÜ©á§ü<σªªÐ4-œñ®iZL¸LbÆ´6 ÌìAb=pÅߘ¾Å:/Ö‡äC|¶ 1P,;o–e–e¡P(„Ûs¹\(Æ']¨Š‚;ÕqQp/‹Èçó0 š¦…˦i6äJŽÄM금å¤ë(ÆYERªÃT÷H€¤mIñ4yn$¦R›AÂt=ÈZ¥R©„nTé7"¡Q ®-Þ¢•(µ;žçáOÿôO±nݺY¿/†a˜t*•JCéÆÇÇÃÿEÁððp8áF–åªYÁ”†ž;²,‡Ï1¯É–ƒa†a†a˜©aÃiôV>Êaž·<ô<ýÉOp&‰XŽã‚4Šçáо€Áòß¿ø">–ÏcèÇ?Æ¥>ˆ{?üa{ñÅУâèèh”w06Ÿ¢à˜4:H½¸%âˆc\¶m‡ã…´œ×u¡ëzØÑ¢ÎVò{²ˆÏ I’ðóŸÿ<Õ2†a†™xž‡®®®˜%$=ûÓú¨­˜„Ä0 Ã0 Ã0L:&â–4‚7áh­m‰ñœ‘‡ÆÅø€/he2€$áä›ßŒÅ>÷¹Ïáuñ@&ƒ“«Wã¢K.ã88û oà¿'|÷â‹‘Ïç«ÇuÊ$ÆÉ8Šò¡ñLZNާÓ•¸N +FÛu]ÅÑÿ¢×Dƒ§1FÀŸt™sT¥ö˜iš9êtàyÀ—Mà5Ù Ãÿ%iÚ,ÿô0Î~ÃÙ5·‹cËbb¬h ƒƒƒøÙÏ~ÖTyR…ÇÎÎNlݺÛ·oÝ® Åܬ ¡¿¿ýýýغuk•[Vfz+œhé˜T£ JK‚åL1YñŠ„CÐ-ˆh{r€°Ñ |²z"³Ôˆ¨ª:é8‡¢`@–J$$M½ÅÙÅb1u'‹‡,ž„B]äH¤#ñT×u†]×Ãz©iZèf”êà[ÿ‘%YÓŒ-rAW,CñRt‡šü­•©ÞŠ¢c²JФ®ë†‚?•OÓ´X=§s"7Éb€,›AlOHœ¥ï¯|å+8ÿüó›>Ã0 ÓÈ >“É„Þ0\×–çÃ0 Ã0 Ã03 Y<*TLBﲬ˜ðøè²exÓ­·™záç¹ÓNÃs–…âí·c$ ϯ]‹øñq†e¡xÇƳ>µ{7Æ¥ú]b ãÇ4ñˆ,éh™ÆÅqé¤ËSqYô Fã ¢WH“a§h;ÒvUU¡(J,äD¨xŠ}r‚Q­³]¼|9À;ÁX ,óùôØ™v¼Ü{÷½xÿMï—u鯀§„c ûï{jÎûØy@pø¡ ¡Œ²¯Ñ8þõÔ ÅôfÇ O­µ¡··«W¯]¬nݺ5fZÙ×ׯ|lÆä’IGt!Jнï°ž/âÙ°tJúþ­ehYVhy'äS# ZB‰3èCB[Rx¤e jTH€4 £!_͆a T*…çBV“TVéÛ0ŒXƒEÇ-ÅߌÊMLd•EBY8‰îSëý†ÌV'±ÜLº®6¨–eá¼óΛñ{ƒi£LÓ Ý&Gq& Õ§¤l2ÏäýC÷/¹áÅ3ßDÁ½É:! £¢+eÑš™–é^c—ŠÖ$ô“ ¹x oÑB8yþtMLÓŒÅaë. …¶mÇÜ “u²Ø–P~4i€DNÑ•¬8!B¬×´&Ix*Z6N'¢uÒB|×®]Ó~<†afv!—ÜôœjdrÃ0 Ã0Ì\‡Æfâ=šaf ‘U#-»Á:%±­~F^ènÕu]|ôÜsQ<„….=ÿà8øÂÖ­è.}q«TÂÛF!0r¹p,}:H‹…GZ¦ñüs E£BôNvÇÒ;ð¨òhlL”&ýÀÍ‹nÆkÊk0 ²,ãêÇ®ÆÑÿ~44Ê¡ühÜòoÎþü? ÀBmá‘dú¡ìà¬qéo,5Í‹Eà%ÊGQÓÊåàgûè1,ûü2 –M†PëþýnùÍ#X¾|9à+ÆVàåO¼Œ3^=Ãß' `€Øuo:ö&<ð[àº/^‡/ž€ ¿üã_G€K®º:t|ã{߀ªªØ³gÎ<ó̦î…Sêmܼy3¶nÝŠ­[·âºë®‹mëííÅž={Xtœ!ê¹ö­Eh; „Ó w3Ld-™tùšæÒS1VcÒêI €ÈªçéCƒóº®ÇÒµh^Ë¢/iI‚‡MŒËfFìĸŒdUH[¶mò¬XJ¢B>Ÿ-µÄÿ5M Èô¼Ù#qúMH¬€sÏ=·©ü™™'Ͳ.éÞˆ:Ù¢^ú®Ï“ò 3å/Öѽ³Øq º+îGߢ¨.Z<ÒGŒgHǧºB®Q©^+ŠÖ ±Ž‹çYKh}Ï‹1“±]¢s­©Þ5"•IŒ¯JŸZí¥£ó#kM:ï™twJ3»Hà­E?ò‘ÌØq†a˜æ gSÒ%ÔÖS¸ùõ)hBÃ0 Ã0í…뺱ü4ÒÂÂ$óH{Άžžžª>Ž)—Ë!“ÉÄÆGÄq”© Nò®—aèîᮘÖâÀתÄeº‹&Ý‹&ûÇ4Šÿèy»ðBœräúûûñxà­’„=÷F0™¾®† :99?YWÒ굸œôÞøö¡·ÃsÒó ýÈ0ÞsÚ{ðÎÓßnKºR½ñÁ‘éÉÀu]üòù_⺇¯Ã5\æwÁ×.óT¡â#¯|ËŽ/N¾øHªpd‰—ï}9ZvçŸÞ÷—ëúŸ}Oí‹]«_?ñk»ó éÀq ãgãøÒóÀ1/¿Wp.{ß½7àóðáÃ8ùÍ“@8ãþ3ðòÝ/‡7φðÓ?ù)Ð »ó,XøË«þð€·€ ‡~û^÷¯ƒ ×=|ÐÜøà8°ä^?òz@~2òœrÊ)XÛ¿6<‡®®®ÉÞ•1jZ< aÛ¶m ×mÞ¼·Ýv`ýúõM˜©hÄcº‰ ¢U‘XÅózBqp]’¤ÐA®L 1~šhõGÖ€ÔØP:Ã0beH‹¡ ÊhÒš‘\M&gq'-±Ämµ„GÑý(•™Ä–b±¦¡oétí‡P.—ý{23ªy?¹ˆ¹ìÝÀÞoíÅYg…‹?r±P̸Ð(Гשª*²Ù,J¥R86#Z¡ÑØPÒ£õIx½AѹX- ¶zãlÅ9³Øˆ\ªŠ6~ û+4M€ê{Pß^xôQl\²FFðêÁƒ8­TÂ~Û†ôôÓØwÊ)PÛ¾úU\]º÷ÒÐ}'žÔøq©YpQ¥Š®SO}éT¼d¿NµºwaÏ/ö„i—þ|)ÜG£qͳ~u.|úÂð>” á²³/ • (`ì±p|òÞ%÷‡€?ø3ȲŒþµýøÀÐPvËøÛ‡þW<}àoYû<²ë<÷þçpQñ"üõÞ¿Æ»ð.,>º(…K ¸÷×Pó*^Yò ºwáÃ÷~Ø?ß"|AÔ—pÊ÷OÁÞø\gøž@Ožy¿Øó ¬Úí ˰ _ù0®^}5 ¯{êuxéô—pv÷Ù€ |mó×ðæ=oÆÕ[®rÀ˧­Äê¿z8À®çBVJÀïЯœ÷¼}üí8¿èÇV\ƒ5¸çé{ð¡ò‡€n ëfq[×mx›ó6œúSñè²Gñy÷óÕGñ“u?ÁÞÿ¹×“u8½º­n˜ž ï*ùûóøõ» 혆¿û[l\µ«>¶ Ò‹{ì1\ròýÓ£(9%<ðW`×Ïw¡o¬¯©û=UxÁÀÀn»í6lÞ¼°qãFÜxãjê€L}ÄAýzÖBâÀxr[š‹U²ò£N‹eY1q#iG‚¤hÑH‡è&•ö…Ó4ÃY b'‰Ò‹3€¨ ɇótùhÝ<ŠdÒÂQŒÅ˜´Ø¢kLJ' °4‰®uÒ¨ó7“c-¨³Anéš |úÓŸžõò0õEzêô‹îH‰¤ð(NB ál"‹GÑmˆè•,é#ÆAL‹×H~ê,$Ý)ˆu‡&#E6}D—¤•}ª$ÛKªËô¢‘ÏçÃz ²Šö™*Ã0 ÃÑ,û¤¸H}¹îîî06¹=ËëÅw¤gt­ÁKê §õY陘LOýèÉ@“¦h`-y.äEE<žªªÈçóáÀ&Ã0 Ã,,ËJ¤ &Nˆ .ˆžµ²,cpp€ï¡@Ó´P€KÐ8Y>Ÿ‰k¹\º®cpp0¸D‹<]בËå`šfÕä¡l6 ]×cùQ‚ú.t¥R)–o¹\Ž iýEOjõ¬ɳƒPy“b†³úñº§“úpM¤¢qÏóÍfñ;?u]‡aÈf³á¹‘g(,•J¡«Y¯Ñu=¼7È E._6z–aY8Îø†Ñ7@…–Ï€/^ôEœrÇ)8±Û;øÚ«¯áwìßÁGßñQ¬:± ¿ú5 ^k\ƒó–ž‡%K–àu§¼½÷bôìQtI]°Ûøßøß8ëWg÷/¯|ÚA /^ó"–X†•òJ\ñìÀÿ  H–„lG÷\}~ñ‹_àSÞ§¶bCV}w¨{~±×Y×.pøÚÃø_Ëÿ¾óýï9à™gžÁŸŸù縺|5`Ï\ô ]ö(>uÕ§×wgz×ÇîÂÕº/L~ᅦ q¡/<ê@®˜ƒ&kÐó:PaþÛ¢ÿ†áÁa¼öñ×à<í„cÂ~þQصaÿÌÆ¸:ŽW¿ð*^rò!9 ·hÅ"hšÖi+.‹Xrñ[z êÛUär9|_EY*CÓ4|Úü44hÈ+~¸8Ã0àÀÁû¾¿©{>5Æ#¹W]½zulýÆ›:SѪˆ~I+" .*’eŤtIk'±!ú++Z4QD´L¤8†@$‚Ð7¥­EqO´0¢²‹b˜§‘,ò¦êÐ,%:*»øà¢Î‰>´žÜZQ¹h½¸]–e …XŒ·VC ú*¦ýëŠèR•¾“±KŘŽÉNx­N¢há(ÆXMºuN¶ I«fÑZ’¶‰â(Y]‹ñ©®Ó'¹n&IÖu1–d²LK²Þ‹ Ã0 ÃL7ôŒMsg <½otttÀ4Mtww#“É «««*ÖY*ˆi(ŽŽ‹Etww£§§'LÓ(“}F’5õ÷i9yži±ž4M›Ð+Ã0 ô‚™ŠELïëILÓD.—ƒaá;»ˆ \×Y’õYù‰‰I t¥R)æÞ½P(`||¥R)öÞLÐÿ¥R ¥R©jòÐèèh,?5 EQ0::ŠÁÁÁ*ñŽDÄzÃ&¾¨P(„VŠâoW+f\Ý'ÇK¥*•J8ž¢ª*ÆÇÇ1<<ŒB¡€J¥öK¥ÆÇÇ1>>Žëј¢R©`pp0Ìcpp£££1/x4F›ÍfÃñ&rí_,Ãñ‘R©„r¹ŒgžyfJçˤC£òt;‰åÔ±zü,+´v„ãàŒûïÇÏž‹cçž ( .Ø·/¦)\ñ™ÏÄâ –Ëåj¯â2¹V·9ˆ‰‘ɶéµC¯…ÿ/9°:tŒ=4Øðâ†Ð•*<4ö®9å¼xß‹ØÿÙýÄ z~Úƒwî~'Vþp%V à-O¼®ëâ‰þ'ð²pÊ5§@‡ŽkŸ¾Ç–ºîŸ‡{9àÌ“gBƒ†“gž×þïk0`àœ[Ï*òÀºÅë|ËÆ<X²d œs÷Ÿq?F/õÛSÉO3¶b ·½x0ì/ÿÆ¿ýþÉÃþöpϵ÷DºKø¿¿ùqûs·ûV“ðô¢§£k¥/~¥Ñ’|9 3áå=œ¼ú$\ã±’ Gw`Ã'g;÷XX÷ ÓÀ_}à¯phÍ¡PhŽo’I“\×Åm/Þº¨P5A¡ˆbØž*Š‚"Š8xþÁ¦îýSšÚ›™ÄA~H„ãÒƒ–nú¦‡/¥K{ ŠŠi¢£è•ÊL'Z8ÒzÑO;‘Œß(ú'Á‘DGú_œa=]˜Ø)-ÇÈbŒ:/IA‘fa‹.¨ƒøS¨üÔi¢Î@ÒM$Ã4JR$DÑ@,NAÒ5h-ñ^¬Ëâì¤äñ¨Ž'«‹b£’òJŠŒ¢e£(DŠb_ÒmÈL!/YÑõ Ã0L+ gn½ xI/"¸H4(Eñˆl6 Ïó0<<ŒñññÐrP #P.—1>>ŽÁÁÁX #B|/!whäþk2ÐÄ?š¨—Ö<¬u'mO³ºd†a˜v -r£$'àä.Tô*DÏ`ò´E–qÂDôô¥ë:*•J(t‘(H"Õàà`ø\%¯•J•J¥®µàD4²o2´Šh\1[ˆ“Ÿg{r~2S#躖9MŒ¦1ñ2ILŒÝK¶m£P(„‚%Shš†÷½ï}³zM¤á*jžW#Çw:8èÇy î‹7HoÀãkÖ„ñ;öóWÕp]èÉË•|+Fq΄8wQ¶Eصq½v(,ø“ß~î¿0L¾êÅU¸bì ¿å8`{;÷Â…‹Îww9@ñ¼~ñë£ØqÚi§á_ÿ^¿ãõpáâÔM§"‹,ÆÆÆ°é¥MX<²Ï,y·Üw u<àÁKì]³×?îÇVA‚„C74àµÞ× @ÁÉ«O Ðù®NØŠ)¼2°ìŸýX$>ž²ýŒ¿a<ÜþüÇŸÚeøæ›¿MR(\ý@8> úùPð³øç¶ëÀ®h»¼°ì…؇Ç÷>2Fó£€i0¦iâ©ÍOÁB†kìÂ1ÈŠzX$Kör¹Œb±ˆ ý(Ô5h;€ÐzšÒÓ{”hÔ"†š¢öBlTUųç=‹=oŽ\æN[ŒÏQú¼D#à‹"ÃD~»“ˆÇª%2$-“–IWŠâ7u2h™:¢Ð˜gc*U.Y–c³±D±1iõH$ây¥‰– Ó(¢ÀHËIÑ_lÄz"ºÙ·Md-œŒçX«Žb@u1&ˆè2•ÄŤ¨GëDn³Qÿ“e¢AO±=­Á̉æÂÚ¨öj!îk"îå"9a†™!2™ø'!ÎÁqªÓ$† #¾=¶»Ÿ¶ÞàWÚàT>ŸõOéÅ”ò¤YÍ´o>ŸÅ:§>.yQHZnP,!úPlóÉÔ‘†øÂKîÀ$#7í™LÈf³sˆa†iKj‰‡D-×äämLÄó¼Ð:Q´P¢|È;M€ãöôô@Ó´ªñ)qÒ¼8Y|Ž—ËåYu¯ÙNž¸fÛ­èTEÏf…Y²¢lä|Ï:ë¬Y½& ÕžKeDÚX ±ï›ÍúËžç[;Ò»Gpuü¢{׬çy8¶t)¶lÙóöG”J¥¨ÔåOª¡vP €üÆŸþVŒ­ðÓßú×ßÂ_ïýëðd–_–Þ¹°«^&î»å>À$Hx²çI\ð AÃhÿ(²ÈbÑØ"ê<„%w/«¸xö…gñdד€¸ø`ô £@Øó~X°ptÝQÝ´Ž]8€eŸ_†±Ec¸ðÚH­ëeZ¼Nî_±?fE>zöhðSøè‰åOø—(1n›öþøÂ¡/Ä-«!á†Óo@ד]ó-B)äÝØ…cPT%ôrCáµ(Æ.Y0’÷ÑÊ‘&tŠF”^¼ÉeB×õسCUU¬ZµªéûýÔ¦s`šBEW§IqO´j"!¯ÆLqf4©ÛI1ií$šâÓ¾´^´4M3쩪‹ÕH±ÓD±‘¶S¾³5ÐOñܨRÒL²ÎâVŽ@ܪ ;Tv™©BAÈ)^AÒÝ)!Ö% >㪢Y²î‹ˆ1LÉý =¬’¾þÅx¬b'X|™IÖ¢žHê >ãËDÜõ¼ @ƒßÇ‘á÷‰$ø´´`1b”$Ëøõ»ßí÷© dhv®£(ìgùêˆ@QGÐAÔGK·‚rˆ¿†ìGÛm!/ÕBb-TámP³Öþi¨ªZåæ”â 74Fï<²,‡î`ʼnPÉ]Ñ ƒÜ€Ù¶ááᶬd†a˜‰&Æ$½"˲ª&ÿR<ãááápð›\æ‘ebr|ð…C`òc¢÷¢V@±[A«'4Õëó¥!ö·¦*B’%ÁÞ$Z|ªÆ…'þÞ`Y¡u#d9zÏp]{ûÛñ»g¾ù%X–…õxãKoÅŸ–¿Ýc€BðÎá·øS‚õTü"kÇœÿÿ¯^ù,XЊþ8Úg_ûƒ1tvvâà«Q@ïüØ;ñ‰¯—á2ز i‰„ëõëa˜>µøSXùüJ ?¯48²ƒ§;ŸÆOÿWà ¨ªŠgœgà½ÍÃæòfì7÷ÃÌ™8ü›‡q5®öcÞ£•Lô^âiñzôè;ÅuòuáòdÛÑ`K·t'tYê_öxX<ÚNcŸ÷§‡¦§ööâW.Féìº_ë…Eò(Ce.‹°,+Ô+TU=Kh’¦hˆ"Ž“XYKxLÆŸâÞUUÅg>ó™¦ïïº[¶lÁºuëÂÏöíÛ100[G¦y’7¯hCˆ¢CÚªÞÌ•¤ÀH7|š Öd<¹¤µ`R€Ëçó1÷£i.U“yÌÉs䞀*.!º¯¬»Pe¦ ªdåÄgJŠG1ˆ¹hy;™¨x¿×š¨@Ç$ ëßñŽ°Þ¼ýwgÜtSÌŠqÕ† Xqíµ8åškÂt½ímáÿbý§²¦Õ/ê˘ŠðűÙàcÛ»d‚-wèÖõÀØ(œ°o€¯mÞŒnDººƒõtìîài2Áþ&"ÏB$v’p(v5ø}7H@-û Â5IˆÔŒÃw7_ þ§Ï ðQà»” Ò•ƒ}ÅuÈT)HS ÒÙÁr)X'Øö¦7ág+W6|1 Ã,hT5þIøHRušäsOQâÛc›ü'F=« êÃ'½ Ä‹-×zÞ‹±=¦ MÎKŠšµ ×ÉØÑ’$ÅÞA’1*)–ýàà`膈a†aÚ‰d¬@‘dxÀž‹nÏÅ´–e…ž ı+×uÃØ‹iÏpqÒÎdhñ­U4ã"w:h¦OÃ!bæâ/&ÁãѹZMýEmÛÿŠâOd¤z¼ܰl–Œ^£?9 ]×±îºëÐõdWT¿lDƒe€?èåÀH+/Þ÷b´Þí=ä[ãÙ~!W½¸ .\¼ø±è:Ü–}o`Ov= yå@lDF nÞEE¬üÕÈÀ÷ø2pú¿Ýzèé‡ðÒ©/§çǤ4UU‘C.´:L‹õ*Ž;À•ß¹2~ݬ+b[(†ƒ  âvõ€È C´€$4bèÄF,FÆ€®éÈårQŸ^<ÅÃþýûqå™W§¨À„‰+º®à·m⺈"‰Òˆ$ߦR§I¡÷Ò@h¬V SAâļù|¹\.ÜŸ¼DÒ„JY–Q,ývGpØælÃ-Ö-1ÍDœŒ@Vt!—ËUy’=â‰á­€jí£–WÇZ¬[·“¾ž"©«W¯Fooï¤>ÓÁÎ;¡ª*Ö­[UU±sçΪ4}}}¸üò˱nÝ:lÛ¶ ###ÓrìÙ„„ñ/΀"a‘*WZLµ©T$Ê?)nˆ¹q¢Š+šìбÑh›èânè¤ ßŠ@Ñ"äû>i9Ê´' ¥"+dѺAŒ³$I¿þõ1ka¾ëÐøÏ~ß¡¾HG–‚&"W›°·³Pœþo¥~qÿý@¹ŒçÞÿ~`p]}5:\¦ªâù‡Ö¬Áî¯|÷ßt\UÅ«gœ¯âøÁ߈k-ÂYg…óŽǺŋqû%—àƒgž‰g—-Ãñe˰bѢЪèj4È*°|ÈROü”‚ï2|k¾¼ð)!Òø5š-FhÁ~åࣦ¤AGRt"7¦ÀäEǹÄãÊŸü¤ÕŨÉBj †©ÍDmÁ|j …\×E&“‰Ípµm™LžçU½0’høƒš4A@èõC´"$+‹ÉXÐdIñ“ÍfÃÙ¹õÒÑ$K×uSÊhšá«ªjèVUÌ×0Œªã1 î0 ´g[0ÑóTtÛgš&2™ lÛŽM²1M3t-ÞHü½éÏjµÕ\ÒÓÚl’ m’ás&C«-5[M;¶õ ãB"ml @$.OÃw·J þ½HÆÁW_…'IxáÙ°ï‚}ø{~_ùØWðÛ_ý*ºwE•OФÁS‹ï¸pâý'8Üu&L¸õ EqéýäßÏúwX°Ðÿî~@ï|<´êƒ 8pB‹MeHZ.Òw-¡±hug‚™ ©â¦üg~à€“Ÿþ4dYÆÀ† PŸÜ¸ݹz<ú¾÷¡ß ¨|Ó2à» ¥˜‡Z°Ü|þàŠ+€ÁAœxç;MÃe££€,Cwt>þ8>õãã¼GÅŽ—_Æ•?ŒOþüçX¼x1^ëìÄ%â-—_yO-Z„»Ï9%×Å×öïG‘«Ï |!¯‚H$¬ õ`½_ ¤õ¦Kð›Ï‚áB`¡µ ä3Q[0ßÚEQÂXŠÝÝÝèèè@GG2™ $IÂàà`Õ`£¢(èêêBOOzzz iZLœ,—˰m;–&ŸÏOJÀs™L&öñ<•J%Vž´t™L&t³š6«–Þ{h†o¹\†$IÈd2áùwuuÁ¶íp³°à>Ã0@û¶ôN_Ër<X–Æo$‹G‚&‘÷±Ù†ãüÍ ¦Kl'¨Í5Úµ¨Y<ñp=U$Ã-œ­úbdëÑ â¸ÂóüÃ2®ÿáaÛ6–_†®®.úQ¸Å"Þ“Ïã™;îÀM×_«V¯†¼f .µ,h\€§^}o ž~zXöw]ziìü¸¦1ÓÉ|n †iœ‰Ú‚ùØø(†`H‹gB”J%躺iO¾€*Š‚áááØ»å5>>^• Ÿµ–k1Qº¤¥¦½ˆþûE¥R ]ܧ_¸pŸ€a }Û1lJš8Dãp4¦V,c“üÉZÚsœa±/¸P'bµk; ŽäÑ” ‹Çª© ®ë‹ŒÔ÷€uà³9@Qà‹øÀ™gb±ãøãˆ{÷mû< ÃÀ'.þ:ï„ *T`|‘ ðHdì ¾-à™ÓžÁ%·]èÀ}»ïƒy‡‰?¹þO°ö×kqu€ ]SKŠ‹¢_»àk±‰ƒª¬„.IE/n9)‡÷½ó}±4"É60iñ8S÷>•tñ\H7¡ó¥íI GÑóŒh™IÚKrf>Ÿ=;’×"Mt­G;¶ 5…DZ±1ÜtÓMÂæÍ›±qãÆP` - p÷Ýw7%>ŽŒŒ`hh¨ÊeëwÞþ?44„‘‘lܸ1\·zõj¬_¿»víš3/tC¥˜NªÖ$NÖlh²˜´m;Ì'\TTâ“–s¹ãñçó½ ûp&¤ªú¾ÚK%ÀqpìÜsÑQ,âø²exþãŒ]=Tø’2¢II| žà›-ä6”æ¸ÄæºlØ€6l€ëº¸ø•W ( –þ“~ÓÅN¼eùòV_>f1ßÛ†ac¢¶`¾·“é7’v® w;ÿ0óî0 ´w[@cvI À뺆çyP%t©.ÌK’×ugÌŠ§­¤¦qÊV”c®÷1æò8íTiçv þXžßX@EÓ‘ÂUAë÷f7—}!R’pÁ?^€—ÞøFt€¢àøÝëqè[÷âÿ¼áÿàg§þ W¼‚—Ï~g˜gDVŽ|åS†?€¨¡Ÿ¾ýÓ(ÝT‚,ËxdÉ#€¿Yû7(ÀŸ,èÁƒã81ψ¢ëhšøHëDí¡ž¡’¦i8¶ôX¸œ´zTU5¦•ÌÖ½®ªj,<…¸Le$«uñܨ|â"™§xnš¦ù“U†ýßÉùLMᱯ¯###¡ér’M›6aÓ¦MضmúúúpÛm·M¹d½zõjÜzë­ÁêÕ«±yóf¬_¿päȨ*ËòåË144T7ÿC‡¡¯¯7nœ¶x”Í@ÖŒI«4Ó‰¬§ÓŒž”y1~\Ò ) Ɇ¡Mu™©Ñßß;wbÿþý­.J3ÝÀþýû±eËlÚ´)œý4ÓÐó:÷\¬üÙÏ€¿ø‹ÐeTkŸû.¸×8€ûV­BÀ7OžDañbxˆ[’Í@q—¢´dÕL³‘èÿ¹Þñf&Ç–-[päȼñoluQª˜­>Áòå˱cÇŽVŸ.ôŒ¡¡!ôõõaÿþý©}ýV3Q[ÐlŸààÁƒØ²e Ö¯_ßï Ó*úúú044„ƒ¶º(UÌÆûÁý÷ßdRž ³á÷ƒ©½ضsÁø¢£iš( áûv9p“(ËrÕ¹^­ç`&hñªåhuX&n·‰a‰É²1iåÄÌ?Èúš5kZ]”šÌT;kÖ¬ÁŽ;fMtügº àñ×^Ãc{öà…ÏOæ3~çA×±ò‡?, oýÁ°ê¾û {^èá;‹CAm7¦S“ôéŸt«ÌÌvìØÞÞ^¬X±¢ÕE©ÉL÷ Xtd:ëׯǎ;ðž÷¼§ÕE©ËLµ+W® Û¹ˆ’ašž‰+W®luQj2“ïïyÏ{°cÇ™¿LîýÀó<ôôô„ãj„a¡[U1žr2NWr}+­^ÚE€df‡¤¥–NÝH"¦’mÀ2¸² 8ù_þ ®zá~Œ>pÏ=@0yáÀ# CÆêo® `dݺº»"K((ERu*››VŠ\HÓvãÄP¢‘‘6¦˜çÒ„Èviƒ& -—´jL–[×õ*ëͤ¾.·Ç)ׄt´fû5…G U4J³k×®¦OJ×õðÄvìØåË—£¿¿Ú/Þlãº.,Ë }ÿRœG‚*«h…4ÕJ7‘`™fÌ‚#ÓNÌ·vÀÿÌûÌg0ðoø UŪûîlç?÷Öþ¯ÿ…·üò—xïÐnذ%D~ßgªëÉg»<ì˜mÃ0SƒÛ‚tÒfÙ2Ì|…Û†a€öj ŠÅ"<ÏÃàà`,N£išÈçó {£Aj~g=UµW;PõŸP|$+BIòEÈP/Ãõ‹GFðòË/ã׋Öú»Ø6^rW<}Nl8SöHÀ%—„‰G¯<êgáÈÿö«:t26mRh×§Y8RÛGíXZœÚ¤Ö IRlR­kÒâK&Ãâ%Ï-Y'Ŷ?í\©ÂãÀÀß|y"( íÓ I¡sÓ¦M¡J¤ÍbhçÙ‰¢À("𿢛әètÅ£(>аðÈ´ó¥ 7ê¿ö¾yò¤ï.ÁóÓr9_x4 ¨®‹?ùý߇¦i8{ttVÊÖ.u†©Ç|i †iމÚnfþÃ}†a€Öµ¢EQ,CWª€?öW,y y´ZDkõñJ™§›¹Ò'%=x,s`Ÿ ìõ€înù·5?8¼¾KÏ{/^>ûÃ$ ¯_üz|iñ—ðZçkXrý@>Y0T€Ü÷@9Xö€±±±ÐUêèe£Áa#‹Ç¤‘"NUÕШ ˆtqßd\CI’æL7ò).‹hšV¥ãp¬OªðHîU“7 JÓLl˜ 6¨¶šOù'Ó 4$¶ ×uc™*-ù<&ëÆéð/>Ѭç¤à˜6ë€aZÅ|k®yòI\ÿÌ3[´#‹®‹“¿ù›@±˜&.}í5HÁÄ]×!Ëò¬Çt`˜vd¾µ ÃL‰Ú‚ùØd2tttÄ⧈†ŽŽ†ÛG\&LÓDGGG8XšÉdÉdZ}Š 3)¸OÀ0 Ðú¶ iP@c|IOBÅb¥RiJÇh•ƒVzO ˜i­<~+¯ûTÏ}:ÊL÷æ­nšAA<¾c® üTòÝ«þ¸áßë~ì& Øsð$VüÇ ¼¶÷5È–Œ=µôüaчù.U=àûû¾å§ßßCŒÝäÀ 5‰'Ö> 2Š"‹F±­#‘ÞKèžM¶‡Im!Í p®ÜkIÑT–åªsIŽÛNi¢IÀþM©27bªLihŸ©ÐÙÙ‰7¢¯¯/Œ900€;wbÓ¦Maºd<ÉíÛ·£³³×]w]«¯c]<Ï ;&i³ f«ÁOvЦ˜/í€ `ô²ËðÜ%— sï^,zúiß}‚çAb8°;†©f¾´ Ã4G#mÁ|m’³‹‰Z‚dÓ4‘ËåP*•Øê‚™ÓpŸ€a õmã8±g3ˆäóy Nz¼­ÕãsŠ¢´Ìû™ªªlÙ¹W*•–]EQ¦,RO×ñçÚxT«Û©"ÁטjöȰmà\X§²ì{K|áÐÞ´üí€óÏ8½kzqìGÇpbÕ ?ãÀ¢ñÀ9bÙŠmÖØ…c±u­~ ’$Å4 Y–C—Ñ„¦i±4$*Šõ&Y‡ÈÛâ\%Y/’ÖšsUTm©Âcgg'6oÞŒíÛ·cçÎ5wÞ¹s'¶oߎ͛7£³³³©‚ÜvÛm€Ë/¿7Þx#¶lÙ‚­[·ÆL¨{{{ødo¼ñF˜¦‰ÞÞÞ¦=“8Ž“¬Ñl6ËeŸùИðݬ®ºï>,>z'ðÚ·¾åw$( …9ãr€af“ùÐ0 Ó<µó±Ð4-U`tžçM8@Æ¢#3ßà>Ã0@kÛ‚ä„ ×u«§ …”„œV{>šj¹™æhõDôVŠ®ÍÐÎ}þX y>•1Å£e÷fÃŽ/<@Ñö­%àûÃGðÜûÏÇGžùVì_·¾õ­øŸþ‚ÏîÝUÙ’1zÙhhÑèº.Ž-=Z÷QûFú„mÛ±uIWÓiŽIñm.sN$42“ãÔZz{{±k×.lÛ¶ ›6mÂÆC³ä‘‘‘pVÁúõëÃJÝ «W¯Æ=÷Ü‹/™4ƒîì쌥ٰaCÛ¾Lضl6¾ð‹3TU…mÛá·,Ë_‘a0·ÚþóA6 ÀÒcÇð×?ŽÿùÅ/bñѣط{7`šP% *=“±\a¢z*•   (ø¤‡°%XÇÏS¦M˜KmÃ03ÇDmÁl¶I#Dzu]@’üåä\CE‰ÖÑäeá•iã=²,‡nÄ÷Z®?`Ñ‘™ŸpŸ€a um Ü‹czŽãLÛž,Ëszž™]È*m¡ÒÎ}2B¨ë”d z¼N×l€ <¬wý1;xßÞ;qÊÛ^‡Ê½~îW>|%®\w% EzÜ~ŽãÄÆiyÿ‡öCù¥ @äj˜DÆä2à‹ŠÉº®#—Ë…Ëó-®-[0N/5…ÇÎÎNÜ}÷Ý0MýýýU–غu+t]ŸÖ ÜH¬ÈfâIÎIódò—ìy^j Òé Òü(3Ì\d.´4¶H5ŽÅK¾û]<ðýïãé‡ÂòÇ#GÂQFšÕ–6#¨¡R“¢ÀEÑP áëø+ø¸]5@ò(Ë6€á–^Òéîƒ ¿3¶PšFþo­Á¿J˜ Šy{3Ú†afž‰êùl´Åb|™Æ-Ë5­:M¡­Ó4_¤ÅÉZÍÉê1)< …ªYÇ‰Žº®Ï«—†!¸OÀ0 0ûm Ò“ØèylÛn©•"³paQÄg.ô hH*íÇèà`ƒü±î¿<`LõÇç˜À 2ðÌÊgpÉí—.àÁÞ«÷ø¢£x+(€c;¡AßÔ~<ó$„„,Ë1/ªª†B#¹LÕ4­jŸ¤µì\´žef‡SëmìììDoo/z{{ÙD«+p»C•[¬œŠ¢À¶m(ŠVì鬜<ÈÀ0³‡|$D:×0€Ü×¾švä©§bûЃԉøâ¡¿£á!¥àጧÐä24£ –+rÁvuø3¦ˆ´w¤.D=£‰ t*Í×d-+é<©“¦ eLËË Î™,;•ĵP‚ëa×WC$ÀBø ¨ÿ¥`f?Ó9RùESÚF°áß?z°oÑ ÚƒÈ·G‘B®Ýÿ»V˜Ä†a.•Júz±û–¦Ö~õÐ4 ===ð¾ê§Gºî½ üg‰Œc£Çày.LÓÄÿ+€µ_ëÝ<ôôC¸×ùûçq—Ð@uûEª±}ÈK[RË` ƒ™* µèëëÃöíÛ±gÏžVŸK[¬äÂJK®PÉò‘a˜¹u$Äš^ðÍïÅú'¸¶‹åË—C… >:úQ>ý0ö½°×=|߉°á‹k€¿\Bd‰LÍ’°2üNH#hÁ ‰rR¢<:"Ë:;(7ÅŽ¤‹"# %!o ‘@Ib¡ û‹Ö…Š]²æKŠsáø@ÜõDò<ÒƲ°.Y ‘µà0|‘SéÚÙÂúb"²¾„pm*¨þ½óÂyYBþ¢¸Iy‘«ŽBʱh?ñ½X¯÷ß¼GŽ€a†i?È­‘®ë°, ¥RíÙG¢…c©TBOOŠÅ"»c†a˜&q'´ "7«õžÉ Ã, œ”uIá1/®ÛïG…ž Ã0 ÃTã8Nhýã8lÛf/f ÄÔzcO}Ëu| Ç›‹À÷'-/]ºù|Þosa¢`˜É}jÒ½ªmÛu…Æd›Fqf:`W«Ó€èKÙ›B†af~§Â9Pöò…l`Õ}«ðWü\ý`ØœXu«^¿ ßùÁwZ]ì:'äúÂÆBëP¸®/ Ô³:wÿ#Ë€$ù±sfÛþG’"q(éóžÒ€¦µæ:“°2IK¦ p]À0€r¹ù|êMz0 @Uzqj責êû|®bÛ¾P¨iñs·mÿ|]Ðõú×ζ}áNÞuÁ´ª££þõ-ü¶"‰çEëÇ·¬Tüÿ=/^oÇ?^½vËó"qX×ÓÓÐìº~~<“µíHNT, U1U’i’Ë„$I0Ã0 Ã0éðHõlñÈ0ÌDPx¦*þ©˜ð­ ðÖ"h*`»ÿ~7î¸þ”J%¼ü¶—qæÏ ]©iË"$4þ»€ªªÈår1!QLCËI¸c¦ ¶xl×uáºnÌUUPMÓØÊ‰aæ &€Ò1 ô·€ü€,п¶{;÷†|UUñÊůàКC³S0('=¸®o…c‘5NÒ⦻Û_OÛ“ÖL]]~š®®(¯É@ƒ÷ô?•Ðéÿ4ŠÅÚ–H¦é—Ųü|’“=h{.ç—]°ôˆåßÝ ttø±ž]Z×Îu£ó ‘²Ö9Ðo‘ü} #þIž¯iúûårþwGGu::üòõôøÿ'#Ëò÷§ßº§'¶yùOàÍ=6¹ß•™ÈÂ0y'ë:­1 ÿþqÿ·¯W—H¬¢<é~3 _˜3 _|+•ü4óÅݪmûâœiÆë7]äú4òy_\,üO²¿'Iþu#qÑuýkšÉøßÝÝQ»KûvwûÛ“í±eù¿EZ]/ýu]]þú‰~#šTQ.ל†a†a8äu€ÆõxŒa˜‰p âÍ»`¥äo=(íê8 WX¼xq¨'üøS?Æ×|ªªÆB.$]«Ò2}S¼FaÉýÉ­ $ùÛU5ncšq7~´-éÚo|<¾ÜÓ¹”$@?i±GbYs‰V²ì¯§}“¢‹,ÃÃþþtD$Éß^ï÷ÓõÚE„X¦Z¢-Y<‘ˆ)æ)þfÉkKÛ“Ö+É2 þ~$N'~ã#—_ŽŸœ<‰kÀ´¢u¢®GX>ïß#âr>ï׺¿uÝ_Gº†áß_ù¼Ÿg.ÝïTŸtÝ_Îf£|)çÅÛIŠ,»»£ãMD6Û¸Õ¦çù÷j²¾{^z$^7Z¥1«LJCçIhšÿ¡öu:‘åè÷u]ÿú‰×·TòÏ#ÍB’ÚAÛöÿ¯…¦ùùÐ>õÚ.:?†a†afB\×…IâÁx†a&‚Þ.Õ}ðÅÁÞGà°-àaø@Ťõ€Ÿìÿ À¢($ …B!6®(º~&o‹äyQt­jYVl¿¤…£ªª(‹±ñË|#ïö 3R…ÇåË—cãÆ­.[ÛcÛvØ 1M3\Ÿ¬ÔLsP£]+*¦_dóИ è yyð}oëð-ÚòðÅ9%XV‰ud`é­ ½äã(ÿÓvqñÄ@:Ÿb¢,âÿÎGþÓÈAtLºEᘴ|g¼îc›ùnž@¯  üc@º@/váœãVäÞ€Ú]×'Ç•¬ld9.yžoÅøÍÅ¢/6‘EÂbòX$ºM„,×N§ªõÝðézd¤(µE/rHy’¸AV7iùjZmW°IÑ/1ãË•eÈ»$Õ?·éžÅš( ¤–±X,†÷ŽaÛ¡{=Ã0Ä l6‹r äd #tGë%øñ¼(¶$‰…†¹€mûbÕoúÝ,ËÿÎå¢úJ÷?ÝCdýK/ ù|T‡T5²T¤ºBÇ"¡ŽêY½ºCÛòùȪRÓüõÙ¬_f:¿½"ËÍ´{жãbYèæóþÿ•J4‘ §':?Ñu1Y(+Šÿ±¬H %Á½Þ$Z4acº©w}¥¾"c’Zå,gî<˜y‡çyáLiš=Óˆ“7i€…a†aÚq ðŸ¿W1 3áÕ¯„€2€/ÙÀzØïgÉþ n08¼{¡êþ{ºiš8qân½õÖ°_.ö×é[’¤*ת䕑&J$5Š´>7ÇtdfŠTáqýúõرcG«ËÖö˜¦Z4б5M«2ž)D± ˆÄ­F_Ý‹ˆb×ÆÎ aìÚ$ÂÕÊ')žÙ)éi½šXçŸdúLpNTNjsˆ„7M8–|ÓzMD" tl²Á2ýÌà›ÄH/(åiåòà‹z@dM¯û‰Ö!º®7‰Œd¥( éeáúYA>†°¾,œ§ŒHt¤|ÿòþO€ëxC¸ˆîm#‹iÍ0ÀØv¯”,õD(¶¢¦ùÖõ:±N¢X„Ó¢øb&YT ¾KU±ïS*ùQ¨W_ +ÒÛ;Ê'éêE×£üãÛj §dY-^ïdûÛ ínIH×e¾Äå\@Ð{}Êå2ÇA.-fñÐ3K–åðÙ'R,aY*• ÆÇÇ1>>ŽJ¥>—I’ªÊEê÷ÔKCïEô,#!”ŽY.—ÃgÞdú8 Ã0 3“ˆƒñìŠa˜I± þânxÖ˜þ ­À“€ã†s@©ˆ?ö"¾÷½ï…á3™ Nž<ŽâØžªª¡kUÊCÔ(Ô8Á“*˜™"ÕâñÈ‘#À‘#Gbë×­[‡­[·¢···Õån)Žã@–å˜Øø3 ’3†Î¾(¦#²”‰ˆI—™FðmÁ–È2ÎFN Ò‘Õ‚ô%D~d)ç"²¾£c“õ^"+Äc’5# ‹¹àZºÂ57=±LÎÍ’‘¨T!}â°£$äÉ‘=ç>öQÀ9x'üc€|b?,¹/¢Á¶T²Ù(#¹"™ì$×ÅC¿ó;¸ñ_ÿ5¶š¬ÛHh², ù|–eÁ4M ÖíL†z‚aZê$”ž,íÈzO–e躊’$!—ËAUU躦! Qr_Ëå ëzh‘ÏçØ¹¦é[šR¾´?g¥Ra¡u¡$IáÀ*Ã4M”J%(ŠZ2RŽÄB²4´m¥R)œuæ8NhyišfLØÿ7 #ôÁot]‡,ËÈf³¨T*ay …BÌWIpµX(ÂßDü_Œ\ë¡HI–%4°«ª*TUÅ·¿ýí–ˆÒ –l6ªïÙ¬/6‘0—& ‰V‹í•MlÓ’±“ë(>e=êY`R ËF v‹bg¦YŽOÇù·+Ä¢eÚzŽŠÐ³g²Ø¶ MÓ Ërøì!ï-âñTUE>Ÿ ô ¯×h$a$ •J%Ö'¡gvww7 è*'Ã0 ÃÌ6>‰a˜z8Âwr4P€cð³Ÿw}‰öä<8+‹9çÀ9èééÁÙÒÙü±œ\.މ¤ø¿¦iÈår1Œ4&H}mÑå*ÃÌ6§6ŸÅÂò¬Ô—jY–ªÈI÷¨€ß¹Â7¹á$ÁܧŠ.ID×ÄX„¢Q>èÒçYÿ‰± +ð…Â|°_9H¯Â·&,à Áw)HGbg9(¹4%qÖ‘HHé ló„ã‘;S²ü£ëGW»$lGpœzC‚ÜÜ2á> X+Gò—D÷Y‰Ô­÷…‚/0HÒ¤EA**˜‹ÎÇÝ~ŠÖq¹\.´|³,+ÖH”#!2é –,ñ蘖e¡P(À²¬Px$÷ž$¤¹®‹r¹Z' †y(ŠsQJB^¡P­5M ÅE:OOI¤ü™¥®ë†.Is¹\èšT%)­,Ë¡KyPZÑ"в,‹E tww‡ëH¤•e9,¹Ô-—ËázMÓ iZÌ•+Ý41EÓ´ªßo4p)®Ÿé h…+>»Î;ï<ìÛ·oFÍ8Žoá¨i¾•àðp$^±@43à(˵ãʦA11ký.l‘Å´€ÉÆ]¤¾M´¡I8b@’¤ª> €P¬œNhÂV©TJ%IR8)‰…G†a¦˜˜Ç ÃÌmÄ7Cþ¸¶ Àù9üïke`Ÿƒ˜ðNxÀoË€¢Àvm|ä#ÁmÎmáÄ}ÏóÂ16q¬)i¡ªjl¢DÚø·eL«`áq ˆ@“‹ÖMäˆÜ£æh#ÝDëEOXG»MŠ“H–‡d˜Ö“( Œt|‘¥! ˆä2T‚ï¶“šEQ¦ õd§•ü¦8ƒbÞbjâ[l'~otxž›T¦YÜÀs­ÿ¿ÿAOxÇqªêúUúñÄè!Oß²œjá#{®…aaŒ%˲pí=÷ sï^¬]»6¼TU…išÐ4 ù|>×È­YwwwÌʼn~$ ’ÈG‘¢ðHâ¦çy0M¶mctt4œ|Aׄ\~І€/ÒÿÛ°R©@–ettt T*…eWUÙlårŠ¢ ›Í†Vt-(Žu¤’.­©3¥§ˆI¸Š¢„ëÈ¿}²ƒFþñÅrˆ¿Y²ó&.³|¦ M‹â&-g0þ^Úd§Ãðpô¿m7~=/Ýý-!I“ÉÌy23gšÏqˆ,õ “l'È M’'Å?¦»»;|Ó³\|Ž‘@Y+þäDiD³^lò˜ÐH‰a†af²äg†iÞ ¬|‚q¦•ÂxÓ¹°T ÊIš5kÂÉûªª†ÞGhì‘ ’}mZ—t±*ÂÂ#Ó*XxœIÑ„G þË4à‹€6⢿aJºV%p Œb<@ú¦á±<"KBQLAEøˆ¥,$¾¥ÄwrØm¢®0óçuÑÿGáHpüú¯( nþêW\.²lœÀŠ:õ:d Ùl?¾új\é8ëêÂ_|Š¢„¢YRÞ†a„.VI€gN‘«SCÈËuÝÐý'•\‹’ HƒŸÙlÃÃÃèéé ¯…ã8Ð4 ¥R)EË:_ûD‘pX ÈM(AÇd÷Ìœ%ŸON˜"4é( MZ!Ïü\F\„l„zÉXYÌVd'Šƒ("Ëò¤?ibíG"c¡P× …Ыy ´ôÜ"WâÉrÑó¼^ŠAÔ!Ã" Ã0L»@k†a…z¹d ä¯ÞÿO˜D¨|ý¼ïD±X„aèêêBgggÕdC›£IñdL@}kê?‹ß¢g.€ÇјÖÁÂã$¡A{1.ÅýJB„â ¡|LD‚$2ÒÌŠ{XFÜÒ‘„Gj.òÁ²Œêø…@mËBž£Ï0u°çÇ€rF\ào"÷¡¢›I’ðû›7ã”ñq §Çk¼ ˆ®S)Ÿä [&“ Ýx’kOI’P*•pÎ÷¿Xüú×Çf3e2 †û“;OÚƒƒƒa|EÇq Ic–Šä–M<Çr¹Z är¹ÐÝ(Y’‹SY–ø²,£P(ÄÄUÝI2 Yö'%49°ž&<’ ödÎä¶<-š¸Ô Òj2Ù¯[™­¡G²î1 #œìÓˆ8GnÂirÍ–¶,+ö<&+Gáä%zîÇâÃT&ˆK]/ Å6®gA’æö•a†aZMÌe†™ˆ°û" œãÿ+/†?ø¯°ËÀ£B^öœÜƒ Þ†°o>88j Ô'&OcÅtûÓi$È@‚à±8¦UœÒê¤166†Ë/¿UÛúúúpùå—cݺuضmFFFf­\äb¨~1N¾@;ðöȵª,ÛÂv)X.ÀÕÄ7Y&ÒGGÜú0çaæ-kÀ¼Å@a ¢cÚ`=È×¾å-è*}×{ufERÌD îJܘRçÁu]˜¦‰L&ƒ\.Ã0à8úûûñÌÊ•8ã¾ûP,áy^hQH  xçBÌß0 ‹E¸®‹\.º[5 ÃÃÃÈçó(—Ë„¢((—Ëá¬+:–ªª¡…7Ͷ"×lblE¶^`š¥]û©xž/Xì0 “ñ¿ É¸enõvÊzšì”–>m½…tŠ5ÖÛ5Ö×ʧVùÍë'IÑ›L&µÖ×:©â ÄL+µÚ‚¶kfz›¦ÙPzr³J“%iâ”$I±X1$JŠ¢ ŸÏcpp0t³>]PŸ‰È4¨Ä&L-æTŸ€a˜c6Úš¬Ë0L{ÒN}‚ð=÷a@:y — `Uø™@ 퉌ž= ÇqBo_¬ò°F1iY’$(ŠëO§yFINšàq9¦UÔ·lÙ‚uëÖ…ؾ}{l¸mºØ¶mÆÆÆªÖ÷õõ¡¿¿½½½Ø±cFFF°mÛ¶Y»XbÅEI’ªfPÌF3øßBFŒ¯(ËyD‚#‰I¸ËÃ,$ZÕ8ŒoÒ¯#Å@d=pú‹/B…ëôc«VMj$åøÂ# w†a„q‘(?MÓ088Z 꺎ÿþïàççž I’P©TÂH±ý©Õ¡Ðu=ÜgppƒƒƒPU5´ž EÀï¤pÇ„iÚµOJ.d³¾ÐH±lÛ·„žj †“ÕÖÈB2‰óbºîæÖÈ«x,=çxúzóÅôõ“<ÓÊn×ʇf‚U¦Æ&O÷‘©éM³Ú"r6¡ædÒ§ý€Yøî9æimA[¶3Y+6:JnV+•Jì£ë:,Ë =¸‹ÅT!p&ZÉ=T-1“„Nž‘ÍÔcNõ †™1fº-ê0 Óž´cŸ@½ОÞWì·6à9À0¢øf£gâ{ßûº»»!I8 šˆG"#M-½DXd[Å“ø˜v!ÕÕêêÕ«±uëÖ–hûöí8räHê¶;wbóæÍؼy3àÎ;ªØ¹s'6mÚ4ãeÝ$:ŽUUýXj f 4áõð­%D®NÅ=(f#R¶1ÌB£•í€õ!ÀºPƒibL'Ïó íÚ~¿þÖ[qý$çÈ,K¥RØ) @Ó4aš&Êå2²ÙlgIQpí>`ò/AIïIaQIiǦմsŸ  ÏóEF]ŠEÀu£ÿµÉ99wà‹nåI¤wŽX–(ÒEºZëÝÿ¼WPå³Õ{pÎÔ3éÎI@錯/.­z¯˜Ëª×ÓD­Ôs:`euzû0P8;‘þÀ=ÀÅ)P=£‹n‹? Þ–RÖS ¾Eë³®¯“jW,ªƒdÓ‰AØÇ ŽIÇP…ˆ¾D>vEýä:ÃPBäj#ìCÊ- ¯º—œ£ôº½x´z¦p;Q«-h»v`="Åb±j¢cZ:¡ç„´]×C±Q×õ0N y, | ÃHXY:nZ™¿ŸQ(ÉdÉdP*•¾ˆmÛa¼éd\†!æTŸ€a˜c6ÚòÀ0L{ÒN} ‹ê7¼o—?r.H D$p]§Ÿ~:*• dYûä¤7§1 ™$†[âczÉñ<™v¡¦ðØÛÛ;ë…‚iš¸ûî»qã7VmÁÆcå\¿~=víÚ5k£héH•Ü€?ÞcÁÏ¡ñ QÌ%¢fm‰&–·{ý" °(¾Úó@>ÀŠÄqOÎ/-Q\ç7çY@½"‘Ϲþ;•(_7–$ÃÌuZÞLÓôg2ñ ë‘ØXÇzÇ`ì*kãëk…Ä‹€»¶zµ{°/JYÀ;3eý2ÿ‰*áѾ TgâÉ€—p«ê<à À4²Æsç kÇTZÀù™ŸÞ½o‰NÔÙàÀÙ ¨c-ÝÀw à> Èç"ìD¹.`qKCÇo»ÝU€÷)@º^¸ˆ¢ÒY„ß3¢r!¹,"Ÿ÷Ô‘ýä“§ØàÙO+å°‚<äàêR°o5ØVB$<æàw-ø‚#å´ƒe9øË *GR½¥›FGܲSö•] sf\½¶ íÚi€šMWÏjPŒM®ÛÅØ1@õ,éFÊÕhÙID¥¾ ª0Ls®OÀ0ÌŒ0›mëºü\b˜6¤ú4":¯!¯¯Ox‘–¦P1hÚhDˆ… 6ŠcçMcËNì¼êùcöÌήVÒJ+íëõý|ôÑîÌ™3çÌ˵çœß¹®Ã÷sÏKuxsÎ…ñ•ãÁD?Çq‚v×þýû¡Ñ0Œ‚É€à{AZ–UàÑ(¡T……fûöí VÜ&˜RxgË–- ³mÛ6®ºê*FGGdÛ¶mŒŽŽ²sçÎyé¬Ò××Çwܱ kåÊ•¼ûÝïž—AµfŠòhz~ñb ÍÊÆ_“Iy2FñÇzdµ¡PqηnÝZë¢Lb¡íÀ9çœ3µÐõÿÜhá˜nûáÃè¶ëxhš6ãúC*ܘiš$“I†††°,+Ù’Íf‰F£3ÊF„Gaرcƒƒƒ ÖߺnÔ&˜’Å¡GØlô½ƒp¥°¸¸(­›óTœ;Á\‚o¬´¼Àhs5`·ø|>½Ñ àŽà­wÐ?ဳ_8\¼Ùϼ»O‚{2$-HÜÚ·ÀÖü²»g“÷‹‚û)Ð_{9XwÂÈAû98h¯ïrÈ.ãKÐó(h»A¬ë—!u=x/ùu2ƒýQBHôÓ`ÿØKsQCßúð9°ûýÏF;XWûuNó« ]îí`$s×1–¿ÌA×­x;|ø\Móÿtå‚üSÆ_ß±£(?cŠüg|~æüäÍŠõë׳cǶoß^Î’…¶«V­š¿É‚ÐÀ¨¾|«öÞñŽw´üäAé„ûžç‰ð(´$2fxNeýÑaežÒsý:¿×yÇwpâÄ À·1O>ù$mmùuK4M ÖyT“ôÔúáI{bŸ„…¦··w^ÚS 7Üp£££ÜrË-“b «†ùðð0[¶la||œJdùòåÜxãÛKy$ Oš‰X™‰žçA4 Ù,†aÂãâçžòžÅÞ JUÊ£ævÀû\ÿcø'ü ¿ø+'ø•3Cß4Í`6R&“ Bª¦R)t]/.g=ã` ô€· 4 5·åâyþ_~ˆœ#ÚgUnÿIøÂ@8_÷?º{€uäb²ÿ–Kssn›ægîŽåÒ'y! Î¥þ6íðõóu¯ûYÐþ¼3 ç+ý'0†ržc~(×ô^ˆ~%8¿mܰþo0ž„èÿž…¨YÒ™|4PEÔ¾Ø?öA¿ìÕ9§È‹ÁºŒ(8§—ä¶/É-a˜ñÛRús`.…äÙÀÙ¾2ÝäÖÓn+å;2¹óFɵǖ€«K€k q2‹ÒG•³"™LÁúœÁv(uŽøfªíS1ÛôÅ^¯j%¶Ï&zb&[ f:×Ô‚° 4L›@„¥Ú¶@<¡þ¨Ç6±œós‘×âwê\ÀˆÁS…iO;í4FFF_8ÜJ~¿œ£ûXë æ6عÉöÁÛÑ-óˆÇ ú_ôÞœ[àþ’É$žç‘J¥ð/ªEæ—j· èéñ= c’ðh·-0p8¼Q` ¿±`ƒ«<Wä¶åÜÛœ.0^†¬ ªƒ÷Mÿ£y²/^q:$?ŸóÄ{ X›þ”N™j÷Û'ᢅÂ]2”>AÞ“N‰fÉ\zµ¿3—>A¡·\.Úk Úä¯Cx²§ËTÕ¶¢¹c¦³–±¢ôÓ…´×/CôŒ¼— ¹s¸¹¿pxRµ-ºfZè¸,ù²ê»úoá{>§WÞ—áôÉÜy”G¤jCªîfXuséµÐŭ¶¡ë¦Î×™Û–*Êß Ý%:ZÀ+¶mã¦ýûYØVüÂPS; BÝ ¶@˜[ ÞŽ‚ÐØT³M ©ÎäAà.xŒÙ±Ì‹‹Áp×®]“¢¨©ij¼QÓ4¢Ñ¨Œ! MAIá±»»›[o½•ÑÑт٥f(ïÈùŽ•üðÃOÚÖÖÖÆwÜ£6lXÐ΄mÛÁ‹¿çÐ!£iâ?}ë[¹Žü€Wj.'aZªi¼£ …,âw†‡ÉÚv°¸óL?úº®1Ø5M#‘HÈÚ‚0OÔC› @Í>ŒFÁuK‡?VŽ9œ€Õàœ€è{ñ Iðü5Ù éÈÅõ´IÒ?ƒl{á)”N©ÚJÿ» ýn“µ”¨…¾+Ͻ „*¾¨å¶…Å=å9§¶é~§ ç5òÞ‹”™>AùÌd]“—ýúG®Ð5P×£“¼¢=Ý\Zå©®—“K¯ê^ß|áP‰¶zîÚ¦)UØXVVÝ“¼ð¨¼KÃÛÕ½QªÑÐvµM­qi‡Êy¡SÕ9·4höUû÷sá±c³¸òµ£ØÔÌ‚P3êªM BÍX([ £ 4õÒ&Мð`%þÄä,<»äYr t…K.¹„ûï¿Ïó ÄG5föhŒF£³9½ Ô-%…Ç 6Ð××Gooï´ôõõ”tw^(Ú³Rá8N~1W5°˜ð‡ÄN,]Z°ÖH ‚P]æÛ¸ÏMöXVÕP0M³Àº˜žž2™Ì¤P«‚ ,Õj¾è˜Nû¡×5mÒÚŽÊ:8¿ó"õ<Õ‡8„¯úX*q¬þçX*/>™ä×L¶ç·)¯F_ÀÊäÒ…œ# DÁb!O…8ÕBßµÐ÷bA±øøf׿™‡•mçŒ~*pªÿ9ªU †÷úSŸ£Ei•g ºþújrkn›ï”˜"ïá)J¯Ä4yÏÊT._‚Pþ:ùpþI|1T‰Ò©ÜµMçÊ©ÖÐLá?¹´*LìH®\jÍâX蘟üèG°1¸ñ¨ª¡n[ Tn ¤//O5ÛúCÀ.è®/÷ßyp98WBòJHåbh†ç0êø¢£ õi†>«5‹Âùh‡4s—bá1Áäµ)Á÷*T!MÃÇô‡¾;ŽÎ*tjñµÉýV:M"‘(Ãh¡ã5üu‚S¹çKm—%–Û®ŽmcÛ6©Tj’ˆàyo9ýt¬%K0(ô:m$áXA¡Úˆð(ÂLýø‡À8œð8)²YHÁm܆ëøö¤8rÚ‡?üa¾ô¥/ß©&6 BƒsÒT;ÚÚÚØ±c½½½ŒŽŽrë­·²uëV¶nÝÊ­·ÞÊøø8Û¶mãŽ;îhÊõ”Kó/¼Àã_ü"Ç|âJ„&ÀÆa‡süÿ˜=¹pÓ3áºnàí˜L& Öy¡É)ŽºœnÏ}~_-L&8è/û”4àý[þ0%‚) s€|C‡IÂQ+¡¼ÊËÁqœI:åù§P^¢Å„ïAxØš§Óé²ÃÝh¹ôÓÔr‡l6;mZÏq‚òض=í X6›¥û«_e ÿyŠ•Ø>þÑG-û: ‚ ‚ 4;Ò§a:T$"ó^0¿Úaþ’,9TÿTy4®ZµŠ¾¾¾Iý/±9B³rÊL ¶mÛÆ¶mÛettð×slÆÐª ðr ½Þs옿QÓø˜¦ñc(9»\„Å÷þG­¿ŸãÀí_ ¡ÅžÃ„ã°«E¡ Ã```Ïó$‚ ´= HÜÆ%¹ Øÿèt^Þ_ƒö|wºgÀ8)F5{q~]A“¼7› õv¤Ô˜ìX٨ض]vje_ËÅq\×-;ÿl6‹a%ÃÚLUvÛ¶‰FKûˆ¦sŽà …†aàºnØ£Ñu]ººº ö‡;ŠK²Ù,¶m“ÉdÐuX,†eYAþžçaYVp~Û¶§­W2™$‘H‹ù’䨨=öXÙ×ZA¡Y‘>}}¢‚Í3D×Áóü?MóÿŠççF~xG¥×4ÿ³ëæñ¼|¤L•‡ãøûM3¿M•CÓòå §ÊaÛ…e‰Å@Í«4Mÿ|Žã«ë“Ë.·¦M½Ú‡P;̃`~®¡>!PЧmooçâ‹/ž$<ÊšŽB³2£ð¨hv±1Ìÿ¼ï>þ Ã`í#°ïç?GF›:$™ ´$.8çç&8_vY0€]jà6,6†¦i$“Ib±XÙØ‚ 4Žã÷3™`SÖ„¨òŠÓµTÞE|dþ?ìÊå…žwÉ\rµ¤ ¡™¡¹I&“ ••ÖqœY ®ë¤w]Û¶q­TY à¿¿Êó+¯vÏóH$3QÇAÓ´Àî[–…çy¤R©@xÌf³$ \×%Nëÿ*TýΤÓi4M „Ùd2ä¥Î¡ë:]]]ŒÑÙÙ‰®ëAÙ"‘žçeêÜák¡ÄÆl6K&“Á¶mºººÈd2Ü}÷Ý|ä#©Ýƒ!‚ ‚P'¨v\+á8¾¦PšãøLü¢QHæ"G¥RùÏá<TˆD Ó øÇ9ޝÕ8NáyLÓ߮ޛ˜È§×4¿Ìj•%jšé2¬g2ùr$þ~ËÊ {ás'¾XŒÄ0üskš__ËòÓ›¦ÿ?õËcÛ~ZÃÈçGèëæÏ«®u4š?.•òËíºyAS­üáy~Z˜,’F£þgÇ)L£„RÓÌ ¥j_Xf‡ß‘×áøw޳4±4¿+÷R9ŽÃë_ÿz–/_ÎOúSžzê©‚ jÒª 4e ­ÄOï÷àÞ{¡¿l›7œr çYD£Mãu ‚û.ˆwåBÑÅb ã¸?ûÙ”ž3j0\­ï822B4ÑQš™âéª9œ•¹õøìÜŸ æ[€vߣ1q9¸¦IAM\Šáï‹‘ž ,M3÷ófëÁ8Óls.TyùišV°¾îtaZ=Ï#‹„fmoo§¿¿?°ûß|Å€IDATñx€h4J6›%™LbY###8ŽCOOO $*qP‰‰¶mëÿBÞÒqœ@ðÔu=ðZT‚ ª“išØ¶Šš¦100€a$“I2™ ±XŒžžLÓÄ4MR©Ùl68×Ùl]×Ñ4 ×uƒke–eñ†7¼¡Ö‡ ‚ BÝP¯Â£mûâPØ#N×ób–€™Œ/˜%ÐÞ^˜_"á S‘HÞÛÏuýc”(¦¼ñŠ {àiZ^ ïWž‚Ê»p``òñѨ?ô:ÝpÊÄDþs9s%nÃçV‚f:¿Å”š»>÷@©EÜ‹Î]*ߩޛêÜáôÙl^ÐÌfóbqqË0òB«aø÷W µÊ³²§Ç¿ÇCCÐÙYx_R²¶XùÄðÃn³ôÞ¶=P0ލú_‡à /ä /ä«_ýjAß1E¡)á±'–.åo_xÁÿbš\ðàƒ<_§ A*Ã= úsZ?­}¥”‹1 ÏóOi B³hQ~ê«"'2òSòë:ÀiùÝÙ¿ – <ø}“j¬Ûèº.žçÕÅà‰òœn:&bF Nç}žªD¼¡¡¡ ¾áz»®K$!‘H^†Ê;Q q‘H„X,tûûû‰ÇãÄb1†††p]˲pÓ4ñO‰xjíEÓ4"™L’ÌMÿVž—º®ãºn ª°«AûûûÉd2ˆ©®ò†T(SåF î¹)“É$ccchšVàáiš&ñxœw¾óµ~<AAêÕ6¬6Ê[Nyªyž/È)Q(•šì™¨šÂÊãÎ4ó"”j÷ôøûc±¼ˆ¥Ä§lÖ¥2™Ò"Y˜R«„ª©†DÂÛK周‘w‡®³iÔ=J$f¾naÁrl,/<ªÿá±yOMèçĉµµ®nÝ£Änd§ÂËKÖNòZTJßò–·ðÁ~Ó49pà@­‹/UA„Ç"ÔD‘Ÿ¿þõ,å…ŽÎç´:´¦Ç¶í ôe5(öÆPá7§Ú?3 '“ÉÀ«A}Wƒ³¥èéé!•J‰ Vö1ÐŽm“÷M5HžÍfƒ°vS…é¡ PÓ‡Uü™îësi|2Î 4“غÜ÷bôðû#&¾YÆD×ya¶Â£eYD£Ñ²»ºººˆÅb%Ùzžü.ëºxà§<•¨¼ ÃÖ1t]׉Çã8ŽC*• ~ëMÓ¤³³“¡¡!2™LàyhÛ6žç¿•àÏ6F£ÄãqaP ž™L&(‹mÛAHØp>*´öØØX'¢Z¿Q]·ööö@˜TáZ¦iÒÕÕE*• B¥ªãt]gdd$HÕ÷ðoN©ß¨X,äé8¶m322Ròž*!ò»ßýî‚?‹‚ ‚ ÀB…;Ìfó¢`XL§ =MÓß®<ÃÞ~åP,îYV~eñðP,–å)4/ªþ_ìÕ¨žÓôŸ‰“N:½ÖÅ®{ôÇáÛ‚-ýp–Né(°žçýÏ·¼å-¬Y³&ÓÍd2ÓFè„fá¤Z ÞP“‡ÆW®Äp]H§yçk_[0hTÏØE×ÓétÝ,Pëy^ÁšC¥Ê^\þéPž ˲¦Í¿’¤ „ÔÛ¶MOOOÁ÷ð~×uééé î…*«ú®B¸)Ç B¬©ôj 5\_5ÛÞÞNWWWˆº6Žã`YVP~ÏóøÎw¾3çkÑt¬È{"•P ^kšF¦Ñ¦È ‚0;\×ï}y^~Ú°îç>þ_ø®‹¾Âx^~ÍGd Håv«–Dµ¦2Í´Nbñïbø·¢Åë†'ܸ®K</øíééé ~ Õš„áð£¶mcYV°N®ûÔúƒº®¿{aOÈ®®®à77‹çR¿‡®ëâºnh×ÕÕE4ell ˲°,‹þþ~‰ýýýD£QR©T Ü©ð¤jŸišÁñ@X¨Ö{T躎a“ÚÅ⡦iS®C9”øªi©Tª@Ð-…išœ}öÙóv~AA„F§Ô’+åâºùuãq?xJ<ž÷d¿[‘Jù‚àÀ€ÿÂȈ/@¦Ryá±Rb±|7¦©Té°¢BëbðüógÔºõÏIKáQné„+ ž=åÙ‚¾·š@k?üáY¼xq°O×uRÓVhDx,b 7 °üé§ÑÒéš„YðÈ«¡e`Ûö$C7›5•’Å+BÏ€Z©Ü²…4ÃÞª¬áÁ±H$RPžÎÎÎ`Óó<âñx°&qÕu]:;;ƒóÛ¶]ðݲ,-ZÔ'›ÍÒÓÓä¯ÊþÔG V*Ô`¤:·òþp‡t:M<Dz¬ Œ›š cY===×E$ahh¨à8ÏóÈd2“<@Ô¹T¸5•Ÿ:Õ ò[ßúÖYÝç¦æBÐ^Ï]t»¿úÕà} ¿÷j€òïˆh¡‰QžŽ†‘ïù'½¹ý‹ ùÅç×kT¾hfèsµûôÊ3{*Š'ìÌäþTáIÕï¶²“JHÔ4‘‘‘‚¡š¦¿aÑh”ÇÁó<ººº!T…9Õ4-ø´,+ðJŒF£ ¢^$add„T*ÅÄıXŒlÛ&™L’Íf‰Åb‚\Xì+\Rk7*Ô±S1000«ßƒJ³fËÀÀÀ´!nAAŸrÆÎ¦J‰ø"cgg~yxÃð×ÐSbâÀ€ÿ?•Êw/”‡c­ˆFçGàš]‡SO}¦ÖŨŽ—Gá„Ñ(Ï.]RÒáÅ4MöîÝË9çœSÑéêħHf…„Z-bÿø8Üz+$œuà@eë"¥É6*\üÅÊò<È~ô•`~~†Ä. Ãº¯®coÛÞ ÜžçùkÙ&$ÀvlÀ+·>• ¦èÏôûlŽŽgúB™Øs]—¯áë|êæOy¡Py}Ù¶„0Óu=ìSß¡p°-›Í„aƒ¼ç‚ ³ÇZMy9xžG*•"‰ë1…¼Úúûûq.NëóE£Ñ‚™*LZØ;#ü½¿¿? •ð§B F"2™ íííÁö‘‘‘ÀÃ"“Éaã²Ù,###peYžç×@Õ=‘Hàºnúm ¤] Þ!Ùj§p~*ìš »÷ÿðs®› ç0Ž>ÄIûö±çô|8‰âµÁlÛîƒçyU8¡Fè:Î)+Ñ7êhª£àç瓤DŠInŒQÀ"/DÖ‚â6Lñz‰Jô3MÏó°,«@¤R¡H3™ žçëªÙl¶ Éd0 ƒÎÎÎ`Ÿ>5M ~âñx°ãÀÀñx<دÖT⣲µªÜê÷-™L¢ÚTaÖÕ$µcØKq:ÂiË¡žÃšËAA„ò˜i¹Ç®._H4 _\ŒÇ}ÁXÌ÷`Ô´Ú ‰‚P)Ž®¯u1ê ÐÎÞoÂéþâ™ÿvÕëqÿù–‚t'Ÿ|2O?ý4ϸnvxÁW¼WÃL8øâ^X`ôJow]]Óq¿ \ë“t†> éíTÊ ÿÃã<øÌƒþ@œA0X—òR`ÀŽ~€²ÀGÁq}Áñ£Ÿü(|Hï`wf7¶l€ ¬¾e5ž=Àš5k}ã(ÿ5þ_,ýÞRøºþÉ›“xX4Æ£ÿü(×}á:nÕí\»òZ=õQ~³ù7|ï¾Ç;¾ý,Íⲋ.ójY¸öÊkƒ0jÑh”xOœÏmþiš&_üôyåÑWòÍÿü&ÞGrB©iòèå;·ø!A?ö÷cóG6“H$¸ãßÁèâQúýn?Œiš$ ö|cxÃ’J¥‚AQÃ08ðã$“É \Ú׿ðuŽŸvœT4)xðƒ2öþ1.ïå‹ÅÐÒÄò—¦fbö›øÜyèN ÃD¨¡¡! Ãଳ®fÙ²eüÛ¿]h áºn0øö°PÛ¯qÕ>_tÕñ~Ú¹~Ó4}¡ÿYÐ_æ{ýϪ¡¬iɤ/`ëk4Ì«Á|FÇ> ¿þõ[kü¦Õ ¹ëhüäG°‚Èð18ã¥òÝ/žŠ¼xæj~ûò)üñ_žàµðÕ›×ñŽe¿¤íç®ÿý›žº €5ßX{àÞÅKyü…µüòßV2´ê©³Rœ³÷¾{ÖwyÇ©ï€ã0t͇âÇ]?fô£œþýÓyïò÷òä–'‰îŽ¢ë:û÷ïçÕ'^Í'Ò¿V:ìûù>Ú÷¶Óv‹/ïÚ¼+á½Æ¾ÆÑý¬ˆ® á&@ƒuÖ:þýü;‹- ¼f"0bŒø÷ņO9ŸòG†»üs]ä^‹@Kh$Høû\ðúÀùˆN6­ãià´Aê5èçÇH~Ì7wjp½Aò/ }ßbƒÞu1p Ä^£á=aàéÚÖOÁ{bŸ„ôßAö¡ü#’¹Ü]à<ÆÛÇ!}_~¿v ­ÎQÐÛ ó2dÏÆÀy´%п²çwDƒ~5ðx6Ä¿ ýg‚óFX÷Ë«kýºÕ.¸úËhé,®¹wûvÀP/³¢J¸ ·‡,«0ð÷‡ß½d²P5ÍÂ<ÇÏ'|Þh´°¬Žã—Ïóü¼ £ôu×õÉa²Õþl6Œ®ûû‹Ó¸®ŽéØRýEØ,Ä*1X­\L8ßT¶N‰½Žã—¡8žЧC=_¥Î¡FÑU›y$K¡LŠÛÍà›ËÎÎüºŒ±˜ÿS£Ìr4Zøó.ÍÀÑ£¯¬uê?Ø‘î>«ßQ¿­§ÆÃK5% ‰ÉdrÖQrTÓXu#T³°»¶á® øÍqÕ¤×u¿Ij¹Þ¬šÃ©n¯êF„¿»nãüNÌ·,Âcˆ/|ýë<ø©OqþÊ•ìÍMY*ø²(³ø#Œ` ôQË¥3rŸsS!¼³À¹Lâ:XoõE¤¾#kYõ<$^s-hÿÛVŒÑ+VŒqáø©d¿x&‰[á’ñKxàÊxáÄ |r×I¼°çwyçs—ð“+ç†ÁWóŸ//"zÙÓœrï/øÐÊÅ8'4Þ=ºš¡kák_9ÎÏñ;O¿DbË)ü÷¿ç?Îü1íGÛéþèj~Ó÷~¸v)Ÿ\t'?w7G¿m•Æ÷YÉËKá³§,ç¼øJØó’çþ'î˜ÉЪ—8É=ƒ/8“UÏŒñ¡­/ð{‡~cOcÝà:0á,û,¢‰¨}"°Ò]ÉÊ® ÂÞãœã µÊyÁƒµÆZX›»~䮥ú‹úiˆå>Ç!yoãžs‚P£¸@¸okD/#êßC{/ØWBö§~²˜ F Ü p9DŸƒø:pö€ö·;´Cö/ýüÌ6°H߯JÐþR=c¸ ô÷€}7h¯ídðþÜ'Aoíÿý48ô-à¥Aû5Ø móC`Ü ©Ëýkäý œE ¯ƒ=àuƒ¾®Ì]²q°’à úÁï½Ú’3ž½L >ñþÏŸ«õ+W{pÍ“à꫹{|<ð Qå µ>§eY¤R)Y/KZw5ðkàóø¿Að0Ÿ+çù¨æõ/pYÒé4Ùl–¡œ° ÖqVâŸò}½î6„ƒ§xžßÔT] U7Èïwœ|]Õ\Á2–Ø]0T³^5ý³YßÎ+¡WÕ-Ü„7 ¿ [-¸g®ë›Íæç1 ªŒêyQu±,ÿ÷KÓòsV ÿ¿iú]þþüóû]ÇÑÑ3+.—!úÖ®eÅØW¼ô{ Ͷwð­ŠÇT¿2IÞ­ÁÊý%ri<ðÆÀ€s:ÄŸ} $ž{ Æä ÆWŽÓÖŒ€·éºµËÏÛƒ=ȶ5ç²æ÷Npîß·ó†¿å¤]¿áÿ{òb–žrý\—»ÇV²Ù¼›ã?;OþÉ2®ù³6<ïI²Ù,dš<ù'ßÂnû]Þ¼Å7rOþhÿqä'<§?ÇG>v5ÑèëI&“ð^Êdp]—lvœhtš¶ÍÁ3| ¸Zo ։ą¬ºÞΫ#00°–µ†¿Ý󣮡'lÿ Xë?Ü^ÎØ8ÿ ‰ $Ó`Æü¸« ´6H} ìû –Êñ˜Qÿ%Èöäf¼ô+ ëCâñeàü¸Wƒµ´ `}ÙO;0Öݾ‡i"7¶ äúþÞ_ø"qÿw dž®õÓE£¾îYÈ¥)¶+ý¡p½CE9gÏ‚<ßÿ¨‘÷œ)5t«‰Ÿæ¿Ç®í,1&õä²'+zWš†Ü 2¯¿[ Àà aog5ˆ…árAhbÒé`0Ý[Žÿc¦ãê7€æGRQ ªâݨ„A…òTTvÉ0Œ@4L¥R t|”ǶZCYm ÇþÜ ~,+XWÑ0ŒÀ.{T• Ä…FDG¡bTïLMÁUÏ”òRô¼ÉžŒà§›éP^yÓ1‚ýlÞƒ¹¾3šVXÖ™êUj¿®Ï|Í …ÉbŠÝNÂ^§0Yà+E*•/‡1è„þþ©ë94ä§›jt(,âf³“Ï>o¥®U^t,>O4êïSqÿŠGrÔýR£‚ B@Ø+)Î-ƒ4sÓWš†T ü&`G­‹R_¸€žžÖ=ìNJ¢ë:ÙlÓ4Ñuþþþ`"ð׿þÝ‚´JèQsí”h¥D;µ òóÈr8r:O7T$Ë—S W¶ºÂóöuÔ~Ïó뢎ULâñü\ÆT*§-xùk§„H5ŸPÍT]Mu=•¨©šó*_ÕePu*ЉøÛu=/^‡ÅRÓ, üžçØÕå§I¥ücÔÊmÛÎà•:?‹ðâлߑ͢i¦i欔§£N^„´ñ¦hn›KoÍRK­\ ‘;g!s%Ä^‚ãÿ}œ¯ŽaÄ¿ÀÍÿq3»ïâsoùgq–g±òí+yå_É“ÿóIþÏÿ‡%'-á”37³ëÔ.nøû7ò–c÷ó¹Ï}„ÿô?så¼–K.±Ñõs‚†’NÝ¿rñø/R:íïW}ùžžÜ‹úæüDe5£Ì² ù·y¢^LMË÷ûÕK®ià~ì{Áx"ÇòÌ‹ãí—Ç)6à¥ÒO8.I8Î^©}BÝà| øúäíÅ!’Éd0KI„ÀóüVØÛ}cî>…/8æÆ°ÝÓü¦€–Ûì²0£Z£Pýžg³Y‰D U­ƒ¨PÞjcµÆ²ZëÑ0 R©¦i¬ý¨¶‡×T ç«iZ H BËç{vj"Bx}ÂjD?Pý (426¾R}5±M ¥'tœŠ bï˨þŒ:ÎËíŸKj¹F'T6U~Íðϩʪ®‘Š6.—Ë/ÎG]“ð1Nî»—ûÓÍœ|M ÃO¨&¥:¡²8¹¼ƒØJ¡ãÔ5 MB&w,\ÀÕóÇ_[¦ª—Ú®¼ò5 ¢©ü²fQ%Ô(Oñq‚ -Žj/ƒ?à›LúcW²,±ÐJØ6üàÿw­‹Qä„G7ªšMæ¤ãT*E<Dz,V¬XA$all Ã0øüç-XA‰NŸhYùíáÀ'‘H^„š¯ÕŸÂbëúçÉ \ɤ?ÏM‰[éôdñLÙFÛöÓªò)Ï»â£ÅóêÔ>åUØÓ“Ÿß©„W%Â)ñ̲ü²¨¹Ÿžç§Î¯æ'ºnþìÄ0ò"cxµ‹ðœ=%Šf³ùíÙ¬Α‘Ò«¨<Ãs(‹çB†W•p??uUy•W¢ª¿#‘ü¼Au ÕµPǨ}jþ¢z΢QÿøðÜJð'Ô(/[umÔŸò‚ܳçq+{ÎDxÌáhN\ â@Ê=íF_XLæ*8~Þ î¼o°÷uÐ/ßø2ßøÞ7¸þë×co‰¾…=Ö^ø/àyžçñƒÎÐ~¸G¾ÿûüÇ0M×us ¿Ÿ \ÍG?º« Å¢ˆ4T"bØû`!Mó c4ê?ðê… Ÿjh(ÿ’–š5V\¬â¾øLãž©{ó÷jB‡Â x‡@{ 8yš4ž'¢£ ´¹ék®jQ¶·:×HÖ ÇÀMü`s³ />_Œã8$“ÉÀÃP×uÒétà…­G:;; &Åb1’Édàµèy±X¬à<ÅB¢QOq[¡Ð4¿ç¬âîèz¡Ð¤?ß#Z-¹“û ïO(1hMq€ ÁZäfîØ\§”üåÂ$rù)·k?jŠB/:n¿Ã¢15YNËGÃÝCÞÐé¹miò³,Ô9ÑÜöxè<Ლ¹4ªŽÅuSL‹¦(kñ5Qe-¾&¡ò‡¯Op_‹Ž ߇ðuus媬Å×5|ÍÔ5ÑsÇé¹{™&pYÕóU\Ö±9<¥ÊZœG®ŽQ§AŸAX@T›:™ÌGE„V㩧Ωuê8~óÀaüFU×uÑ4-/¿üò âÀÙg¿gR¸TÕO9Â(O6åÙ¦ÄG%òó(E8lhX Sß•g]g§ßÕQqà wjµ×õ‹ /‚YÖäU¢Ñ|ž9_' ôRæSyTªüÇ/C*•_U@‰†Ê[Oé êZ(ïÅtºÐ;Q‰·Ê›0ñ¿‡‡A¦Q÷DÕC}/5e¦µ~•°:6–¿a©ð=PeV÷Kå]¼t=ø×)‘ùw^ç¤uU§ÜK׃HÚ_ë óIˆ~¼7ß@ÊKÁ_@2ù×dšå]ïÙéƩXžE?š¦áºnïùOþöOH¥RD£Ñ‚µšÇ \´3Ó­­RG¨tªR :[L/ú/Ó`ÿ£û`íÚ`ñg…j48ŽC$a"¼¾ ÍeÁùQÜ_—·ÒqH-%TÛLy=Îe_‚µ‰)\B…}Vâ¤mÛÇ¢mÛD£Qt]G×õ`ÝE…ZƒQ}a–¨žXHëyÁ|±*‰oRäÅ"Õ_PžjFèsñkhà mŠ© I8úh9M‘RŽ˜áãÔ€@±§b¸ªC®¼U]bä=ý&y’câÅ„½ UákTÊ4÷¡4©P>¥®ÉX×ibŠÏS‘š!Uî鎛 ß·ÔCÛ<Š<-‹®íù™Êê¥/·¾.üð‘òÞQÆÅAh^üI{þ@µ„XZÀ·¾õñzœ„ Î)§À_øÇ øýx ˜<<¼š/~qþg¿Q¦Ä<%()áL…/UQ•W^¸ ¯D/µÜ¹ Èö T‚£ØTxÑdÒÿÞ®<þ"‘¼0ÞgY¾ýS+$“þöpEY‘Ë@“Q×§ø»š …º‚ê²E"…+!”#¾Í†J´ u_§Ê«”pN3]¹•€8]š…^_r:êFxgûöíÜu×]ŒÓÑÑAoo/W]uUAºíÛ·Ó××Çøø8W]u½½½tttT|þ{/†GÁÌõ€¯>ëj@Au°5°ÿ²Ú Hßz»ß§Ö'ÀM€Þ ãÙq,Ç ¼ c±†aðä’'Yÿìq²"››ÖFÑ4-XTaÒ >ÖG„jRU;à€Ó>†Ñ×ü¢©|ð ¶m‹Å+gK„ù¢¦mµ(Á‰Ü\Î8›kè*ǦJ-*ÏEÕYñóvìØÁUW]Åu×]ÇÎ;ƒ4Êpôöö²cÇFGG¹îºëæåüO¿ü2çýúãçûa‹`毕„ÈŸv¤l|¡ÿ› ›~ãDÏ…üyè/À‹úÓ{ãñ8Éd’/~1ŒF£Á’J˜ŒÅb$‰†ñj„… ªvÀû¢v̱±`fR4ôkà8¶m“N§IV²Ê± ³¦¦m ü˜A?îo¶ñ5ˆ|§žâåÄæ‚ã8d³Y¬œà¡&<¨Ïš¦¡ë:CCCAXÕD"A*• þÑhTÂ¥ MÇL¶`Þì@2é÷È÷ãO<´s)ü¾Xt¡jÔzœ@„ú Z¶ààÁ¥A¸AAhUž~zm­‹P’š¶ ‚Õë4œuŒ§ ¥ª¼ ‹=äáõ!•פZR…óŒÅü¿±1ÿ¿òôëï÷Å»þ~_tT^…*Ì©úS‡D„ÙRããã rË-·³º»»ä®»î ¶íܹ“Í›7³yófn¹åLÓdçΓf7Ì–G^~™wî¿€óN»”¶½mþš"¹u9’«üå92±óÌ(pðáÍ8ùt]B¤š¦‰aضMOO†aLë… ÉÛ-´(Õ¶ö+@?Î%¿ý-_Îfq]—h4x )od×uƒuRAXxê¡M€ îs »Æß¤–›¯xžç“‘À"ÕšÙl–h4J"‘À²,²Ùl°fD)Ñ0 iCME9¶`^ì€ëú#ß‚-†/4Ƙ{ eAæºi‚PSªi {ìÒy_ãJÒ³^¨y›à ØWç>Ÿ¯ü§W’= …[5pœü2'ÿõ_—æ¼Gó‚£Z³O ‘™L^ä {úMÕ­ïï÷ï‹ ‰ þV5,\B~Hõºu a!¨ ÇÑÑQº»»Y¿~}Áö 60>>ÀððpNÑÑÑÁúõëÙ½{wEçÿù‘#ì;ï<Þ³ë"Þrú[üÍxoç,pÏ€3!öIüÁFÍ)˜á ¼lÛ&›Íë2Åb12™Œx4 ÂÔÂîalbÇq‚uÕÔÀ}<'N^G‚ T‡Z· €` .÷½ÀRÿ³’ú*’ÇñÉ@¼ýðaÎ{ÐÅ´_ÇWîccïF<º¾Æôàÿ(†ÉíéºN4 f8¤ÓiR©–eaÑT:A¨5£££ŒŽŽrìØ±Ze mŽ;Æàà 8k: ã"ö_{-ÎÿüŸ@þ}‚Ia@š…ÁÁA~õ«_ñüóÏ׺(“¨V› ÔñAÜLÈ úó¾—£êT2éÓuÝ`5II­-«¼«£Ñ(®ëâº.–eíiGóÍøø8»wïæÀµ.JIf²•¶ Nœ8Áàà ígŸÍk®í‡/SÞZ‚Ðd säÈNœ8Që¢L¢ýƒ088Ȇ hkk«u•¡f´zÿà?ø “Nϰ–˜úSK4iäÅ·~Øvðg,º läÒôäöäö[øŽtQÚ 3÷¹Ÿü’P ³è¸ R”Ç~T7—üšÍ*}*w|ñ1ás£º¦9o"wÎl®œfèÚ»nê8¯è8'wîâú…ËÕ!›ûläŽUëbä–Ï"–Ë#,„¦rutCÇÆÈ¯ó­fœ†ñByé¡ôjŸZïZÕ[ ',ð¦rßU>êÊ„Ê~–ôPÞ^.­^¢|äÊ” •U×Í}6ry«gÂÈ7¾}œ£Gòæ'êNȪö˜á¤5!Æ«@;°6ëðƒG_xôÇuî¾{œýûÛ8|xÏ>ëæ8yïQåAjþ$‡¹’J‰×¢°° ÏK› .„ÇbvîÜÉöíÛéè蘴Hë\xî¹çfÙ²e%…ǧÎ9‡ ÿàk¼÷á÷‚Îù µAÿùºaA1N“ÍfƒuS©TbUêÑÑQyæ™gj]”™o;ðÌ3Ï088Hww7Þ¹hg-æá'ž¼ŠÂ È»,4%ƒƒƒ8p !تMpøðáÉÂc6ë÷ b¦ßÑ<Í_ÛYõ[£TæñèyôôôH$‚ú(ïjòY×u<Ï l“ ,GŽ lA#Pl *µ¬„ÇŽŽ^sÍf¸†Ên„d÷îÝŒŽŽÖ¥ðXÌBô”ðØÑÑÑí"AX(Z½°oß>ÚÚ.fåÊÐŽò‚ä…)µM Xä; :y¡NÇzЇt|IÃÝ ò"V‚¼`¦çþ&ð…&|d%:(ñ",–N”¨ä¾È¤‘ÃÒä…/uް×Uqǧ” ;@¾³Tê¼Å„W±qr×r(TŸ©˜N Voø>©?È·ïÔlR=t-< ëì…Ò¨29Eyh¡<¨4nn¿IaÛRß ÿ é¡4FQºðì×âó¨s›”ö*ÕCi½¢m_Óç¡Ùl–¨õ—ÀH™ÁR÷½Ô穞ƒâ4*„m©h³Í;÷9™Lú×ÍÊO¬wmI¡¬“%•J‘L&ù§¿ú':ÞÚCIF‚ˆ;º­Ã‡ý>ëÙgŸ=‹«ºTk̰<Óin Ø)éôÓÿmm{qœÅ¼÷½þ1±ØÔ£ˆ‡B=³yóf:::*nÔð8<<Ì–-[èîîÆ¶í’3 Tºb¯ÅR^ŒeáÂÅ<KO°çú=œö­KI~9$&$Šq]''!cétšD"1ãúK‚ LM5퀳fê¶»mÛÄãqFH§ÃÛ}Ñ1“ñEG˪\xTBf6ë6Mÿ<Ę̂E¨‡†üÏõg_‚š´ "ÿå».áO:2ÁMåíÄ\^=Ïó°,‹D"AOO™L&èDwuu•¦S2³AhqʱÛ,…ˆ‚ Ô5ió‡ê@I'F¨…¶?ü0/¼pÆ ø¢P9^xóI>i lÛÆó¼`I˜°LÚßâñx°T&“!NFééé!‹‘Ífùösßæ9ý9\Û –ŽêêêbhhˆH$B?Éd’L&,¡Bu^µÍ0Œ`ù~R‰—‘H„`ì íOÛxêOñ¾?y_pžX,æ‹`¹ü•“‡çy˜¦/zž‡ã8¸®Kgg'ýýýôôô000D¤ ᲆA6›%Mš;åßðîöˆ?ŽišA?-,~úãBÁdÒ°ð™H$A2|ÞX,æ ŸšVpn%xZ–E*š‚t¾~ÑhÔßžÕý ×!©K•ÓuÝ‚{®ëz †©ûdFpŸ‰ïûŸïã›ç}“o}ê[†QpŒ¦i†Á?üÃ?TááŸ=µl¸‡Ç1öÜOÿ¥>ÜN*•"‰ðüóëyúé7ùŸ>ÓôÇñÏ¢E…߉²&“Ìò,u51LÕÅ4 Ëê8~>aR©B¡3™Ì_OMËÏ$U¨Ž˜ªK4*¡:d¡mÁÑ£G¹rÕÝÄþôj¸”yÃBšÂq|/»Ÿ<ôþ? ¶'“É@ÀRkÁ+¡Q‰fš¦^€Éd2´²ÙlYEETQcJ´Ò4-˜ ‹ÅxéË/±ÅÞBT‹„èº^ÍM‰VáqO%vªÏá}ª¯£þ—špùæÈ› ÿ£ý˜¦Y–#‡:~``Çq‚åqŠóWç-‚3‹á8Ïÿy®¸é ¬¬5i"¨:N »###8Ž8¢(Á0™L266ˆ†Žã`ÛvÁ=Q×ÏuÝà^&IòçõçX–ˆ—N‘2¥_J-¿¡X%ÈÆb± ¬ŠðýPŸMÓ$“ɰäWK¸ókw’Цj,»¦m‚#cèÿ.ôßå±±lØð.t}úн|ýë_çä“Ïg||eð~íågEhEêBxdtt”îîîI.œË—/ŒÅæÍ›éëëcÓ¦M´µµqë­·ÒÖÖÆ¦M›æt^ëMðÒâÕl²÷ñòÚßáfo œ>½“mÛ8ŽÌf‰Ç㌌ŒÔú BÃSU;àÇ1ÀÎ5ýF ß¯ýìgw³råï02²fÚÆŠË®úîJÌsݼà§úñj¢¯®ûßUß¹Ô˜LŽošù~²ê+ÏH]‡þþÉ^’‘HéÅ«uÝO›Nû销iЕ[~hÈß&#¡ÚÔªM¾øbÞbËð£ÍfMGÕ™Tp˲‚vC?ñx<èÔJUA˜žrlAÅvà¦, x²¶£ Ô)µjÌ Ë*œI¨i~=L2éoW…b!N¿Æ€“ x§á{B9ä×}ë4à*îtà9Î1ó!û `Ä„ótxp¸?’ƒƒï ‘ưăW9p‰îÒD¹×„Í!qïrà»F~=°,°?+<¸Ø`ú"MLÓä_þå{¼á ã<þøã\yåWrïé³I$ #éúdOånÏ©6âlÛŠ‰PèçRýp·¿ ç o>\ω‰¼pÚÙYX¿ðت_¯ê¦DÖh4?qZyy*3é8þäbÕŸŽÅ ÷WÞ–Ó‰Ê{´ÔuS“ºÃéÔ½µE-Ú çQÀðǺRÌ^0 #ˆŠFƒP<ªs(íA(rlAÅvà7ž?À/B]RË6Á$”°¨>ÇbyA' ìÏ¥7AóÀÐ|±OÃå²@jÈŸÕdoö ÍƒöÜþW Êá x¯!¿Ö@?aÀô׳;È ‚»t?C¥] çòSùDL¿nÎÁ-Ó¹4:pš/›ùW†ê§ò¸"d;sÚ%N.//÷™Ðö\ÿ(د®+tX›û®þÜÜüL0è'/¢ªqøln!>-W‡”é  ¹KEð¢ù0–Ñ\þ‘P}³QУùµöv¹ðU-'žæÎ¹/WßÍ XæÀ£º¿]Ëå3hÀÛûáÇ<ø=ür¨u-`T‡³3°Òƒ;,ðr‚¨™;ïÿqà¼(¼ Ã2àlÏ?NÍ„û¾æç±×ƒå&<ïÁ½¹¼Üß^.2à1 Æ8KË—3 ¤-øzރˢð  ûò÷+àñó÷ÞÌÕ°¯:ö*ŒÄŒI§%,8*Q/(ð&ŒÅb?vœÔ•©iEÅéöÍ%Tvvv244TUJÓ4"‘HÍ9¢Ñ(š¦ÑÕÕÅØØXUûh†aFk6U…dD" µ´G­Ûö¥ç‘ø©üžìÝûË–µaÛðÐC32rnÎaþ²Z_*A¨êBxìíí-kA÷¶¶6î¸ãŽÀØlذaΆÃ̇À{.YLü%0~ ™Nœš‰ãy^ChA¨wªjú½Yí¼ó‚˜øçžû~^xád^ýêOJý?“B¡”B%idÇ¥RÕTÛÆÆò"žüÔ˜‹šTœÍæ£E£þ$\æ5‘ÈOÜ6Œ¼¨¼4Áß–Íæ£,%yM%b¦Óy1×0ü¼ÃÞ¢áýJœµ,?m4Z8ùX­— ÓO2Q…UßKå••@k“ ×u¿^JH _çb±W޾“«ò(^ øÜáTL-Ú÷‡`˜ùñ²Ù^Êl6ˆŒ¶m‰D Ú Òn„ò)ÇTl\ YàQꕚµ Ô̹pc1›…g4x•î ŽnÌtø“öâ7$®ÁßoçÒ@^ŒÓ×j`j¾'ŸòVœÈ¥7@ÆBŸs“£pÈ/>]Nc%5ÅçÙPN¡è¥”Š(_ަÎ;“ûS 3%Lªz;Ey*¡Ô$/*ªÉ˜êºê¹ÏzèX·(—u_¬5Cé”åá7 åãr™-6a1ð÷ø÷_á—§òçûÓX>ÛÿÌÊ¥¸_ Uõ×óy8øÂôñ\™ÔŒ¹ý1¸[ÕÍ„·„ÊáZ .ùù??ã®@¼<Ñ{~]“äªa Î:—tÛa´×­(+½çy¤Ói ÃÖ ¯½Øš ¬Â—†1Ilêêê Ö \qq:,ËÂuÝ lÕ&‘HN§¶š(x`` &Cãñø$ÕjÖ=›Í•BÍÚaÞµ9ôEçøñÓr‘ÈV±nݳèúéµ¾L‚PWÔ…ð8[TÌæJ°ŸƒØD?·tžŽwÚÔ!Vƒõš ˆ­ü0„GŠaòÂé®[.&‡ÔÏžTÇ” ËÆ4 G—Ë9O6›WÔkñu2Yè&T¼¾R„óƒ¼R1Õ5)uÝJÌ7Êy««üН}©ó_ûÙœgªúç3E}×Öaø”ÙR‘¸ø#0ÚÚp]—Ûn;—_^ËE% Ë[µv˜b;YJä ·_Kí{f¦R“ó v–åçŽ.¢DE%&*OK%©¿¿0O%˜ªcT$$y(¼Ì*2é¿F©”ÿÚd³“ÅÍtÚÏ;õ=7Ãô÷ûçñÚ8Îó§Â£Ákòëgk ¢Ñ(Ñh”t:mÛô÷÷td«=˜ ­ÂœíÀ3Z¡×Ž  MÅm5ã-·AUgýÐ œA>¬¨º¢ä½ëT¸ßÓ-ìõXŠâíÓ ‰FÑÿVA‰‰8„þµ+2ì±fý/ÎJ_ϰp:•&Χ”—ÜLBìTeªåÜ÷¡ò˜Š\_|‘#¯8RÆõÍ\lÁñ#—ò‹eG3¦Ukñ)±pdd„t:çy‚c˜©„=µFa©uüuÞt:]ï;ÇqH¥R5þt]Çq"‘HÁZ–ÕB ž­X÷j1/ãE˜+Ãß,J‹ÁÈÈK–ü ?D€ Іçg ߇÷^ôÆÇ¯dä7%å;ïÄЊSž´z4ZZ, »ÛÌÄ\f©ÅÞÔñ¥Îã8ù?•®”ø·4­0¦£m×" xñv%p†ëS\'uÝ”ËP*Uxžl6¯>Lw•F‰tS'|fªO&3yvëtõÑ´Éç±íéÏãyy·+EØ•L•µXÄž©>¹g6¸¯SÔ÷õ?N+cÇÂ=|“¾¾µ ®'‚µÙ„ÚKM)ÖnÔ÷âù ]/ÌG™>åÅnk«W}l,ÿ*ªùª\jijW•¡xr|¸JlUó¯¹2_ůª®–mª¾`ø¸‘ߨŸeF”wäÐP^@½ï¾ý<óÌ~ü›¼¾ ÷/À9#¿´ÐlI&“躎®ë%g4 ‚Pg||`v ¹ ‚ÐܨõñÂëûYäCÆðšv|Û£p¦Ò\½üA¨9wn<Ä‹/¾¦ä¾d2I"‘D¢žžb±XÁz~sõ‹D"A¿¡Úžoš¦aÛvÍÖù3M“žž¢ÑhÕë®&›÷—³FÍÉÍN$5¹ïCCCæÔ:#ì¹°HþD žçõnÞ|»wKˆUA(¦%…Gåg<»w_Í›ÎËÇê üXŒco|#·ß~;»~ó®èíìq60Ãô1Ø9M93ýÅb3çSÎY9e­Æy‰Âí¦:ÏL窗ú”sž™ªårÞyh*Uñø‹òš†|šp5ÁA-mœ|òÉôÜ?‰DÂ_óϲ&Gå*‡Âçü"áó/׋MZ¿dõ×¾Æ5>H{{{ÞÛ;Lñš$圧8RÙ4õQa^ŸÞ¸ÚÛì<¥êóÚãÇé}æö‡ûm pž©êsøíog÷©§ò¾ßùhk›|žâ{\ÎyŠ#ž9Îän¹Ð¶¦iúãÛÉd>t“ú_#/кŶadýíW“L'Éf³\tÑe,^üé ’Ö_ýÕŸsß}핟KšŒ–]Àø|öÝw`p'òZø»¿+™V…L“Y ‚ÐüèGÜþþ«ÂËT•sMóÏ5Ý„u•‡ëúÇ/…¥i¼ú]ïâèÃóòïý¬X1¹Îêy0ŒÉ¤¢¸ ¥ÊZœN×ñ\—l6‹ã8 „ûe~i\û Ýß‚/}éaþà®çÛß>•^è …Ï~ö~¾ô¥¿%•º¼Ö%„º£%…Gç)HÜ_x~9ù“'9g Ñü sÕ.B}â>÷S–ÐX¼ø‡\{홀ßè­vl}AêûüßyƒÙyûxž‡išA˜ A?’¢C~—pØeü¤-´¯œ‰ …SxI8rçÓ¦É˾{ð N?——/ç¤#GxÝòåËWEƒÜµk\p—Ÿyfɼ\×ÅuÝ ¤™çy8Žƒiš8Žƒa|ùþû¹öüóýzæÖ~ÒuÏó?ùd]µŠcÇŽ±ìÅY÷ì³€ß_Úü¿þ##lÛ¸‘OôõqÙe—±k×.6nÜÈ®]»XP|ÛÄ¿:q‚§y„%ÝÝÜsÏ=\}õÕ8–ÅÇÿèøôw²õ½ïåî;îàâ‹/æ¾»î*˜Ð¡ë:ßܵ‹«Þð¾õË_rãÕWcY±X¬à¿iš¸®‹®ëõVÿUÚt:M4%N“J¥Èf³A:MÓ‚I%š¦á8N4%™Lò±Ïž;¿øEb±X°˜mÛœsÍ5üâ‡?dÅØXPuÌ'oº‰÷žqkÖ¬áò?üCþŸ¿ú+,ËÂ0 v>ÌkV­âôçž ÊŸÍfùоÀ¿øE~úÿˆ‘H°ýàoþæoxûæÍ<ñðüvõê ì—®ëØ¶M,㯿ö5n¹î:’É$™L†xiüõåg]ZŠ¿ºpÞpƒïy–H`YÉH$˜˜üé={f‹9Óò:º>ÉKò)×ÅÉfƒß›Rif}%ŽÍP–ó?úQþìŽ;øÍùçsI©ô3åQæy¦ÕïóñK/^4¬ð<¥ês‘irêãÏþ<åLÒ)£¬ŸZ²û‰'èß¶­tÔ-ÃÈ Ss¦çdŠgÉ0Œ`©ËÀó°/îâ-iX¹òZº»7sÏ=/ó{¿w†ñFnºi%Ž“K)%hMáq%œxå)>ü•Í“÷;NР~üAh¼¶38ãG,Z´(hÃ¥Ói ³*­ÊÕþºÏú’ò"¹Ð6±rÖi¡nñð£*ªeÜbÌÎóy&\×Åõ<Ì\#Nƒa`‡D1ðû*t3øBýÒé4‰D‚·%“ô÷÷‰D!‰ÉdhD"ÑÕE?í==d2™‚5©TÇórÞy|íæ›Y²ÄuÙ˜«O_»3›%ó–·ðÀÏ~Æk_÷:þû±ÇÐ4ÿñœÙÝͯW/]DŸ±m;蟭£ãÌ39ðÿ×Ý=i¤ðuUuV⥪‡“óPáÆǙ䱮ÄFu? ÃòÕ4 Ã08ýС‚ïêüúø8çoÜX ~‚?Øwñ9çð—_ûïyÏ{è»ðB4M ÖÙ2rŸ!ß'M$gÅî¶6âœÓÖÆ/¼k/¹{|Ã0¡TyèºÎ›_ýê lš¦‹ÅÐ4h4êŸ/·Ý-öÆhE’ø†Àfv1×Ah N9z2ˆÅ‚ßä¡¡¡`ÿB®Å§~_kŠÞR b±Xð;Y ,˪Yt;5ù§VcPñxœL&#c`eà?Ž£¯á:þiìm¸.9r¯zÕñ<®®®[!BžEµ.ÄB³}ûvº»»éîîÆÚ?Üð(÷|‚GžÞXÖu]"‘HБ^‡Ð|lݺ•;vÔºµ©÷ÿ‹®0xß?~¶ûóÏÿü1€`Æ»„IZ…ÁÁAéíí­uQªJ¸M °> ÙÿÆZ0ñÿ¦Âó<ÒétÐN0M3ð„F¤Ô;Ñ ¨¶P¾Ça?s‹¨˜Íf‰F£@—N§1M“l6K,£««‹X,F6'ÒY–E"‘ NnJøQ"øžçiнð4M <ïÔÀ•´´m»@P*nÛ¸® ª ‚¢ûA[èþûág:¼>åÏ¡q]²oÿú `,ž¼[…ÿÑ4­êƒ‚ T奣„F„æç¹Ó×Àý±©g •AOO@°Ö¡ò 2M3h;4¢ˆX ­RÏÙP‰gY5¼GMÓ¤½½}ûöUùÊÔjwy~AàY¼Dœ{ß;7•‚tÚ¶íšzÍ B#ÐrÂã}—˜œš~ŽÄ@¡;2™Ä0 q7„&Ç›¸÷`ëÖ L‚ÐÊÄ38+t¢‹KïVžNš¦I8fAh²Ù,ÙlvN¡ðAhL–?½Ü_Û±Œyˆžçx@«m**Bx»¬%SÉ3QçI×u:ÔÒ£Šx ï¯ Üã’]çÿ®ßõ¯ÿÊe—ýøð=…ÅNÂÌ´”ðèÇÚà Ã[üAÅžžt]OGAhÜ—_`ߨjâ—]„ã8“Ah!Þo’}5L5‡\ &ŠÇ“ 47žçÑÙÙI,ÑQZŒÇÏ~nž>뺸®‹eY€?q1•J¡Ue½xAh$œº ß²±>ÚË•ûǰ,ƒuë>ˆ¦å׫u ¡îi-áñ8íÜ—yñÕo-ØF¥!-Âñ—a•ýÛRo <™AhMœÀÓaªiGÙlVB- B“ãy===2x Â$\×Åqœ = BeF"Òé4étš‘‘i'BðØcq饗211Q뢂PØ+»pŒõœ{Í€‡ã8 IfAK w¿ '~p]]‡ƒm–eIGAZˆ{ÍKÑ¿ôÆ»ééé‘ðÊ‚ÐÂØc`>œW¸ÝqºººøÇü5«W¯ÆóÀqü}†–ºîÿضÍâÅòÓŸ>ɲe/²zõq~ýëey^pÁÑ`ÛêÕÇ9vl1GžÂÞ½m=z «WgãÆ1víjçØ±Å\vÙãÜyçš‚<6nô…‘]»ÚƒôÅi®¾ú@°mãÆ1\ÊÁƒK§LþÜlç9í´Ó8qâ7ŽqÁpûíO5t}ŠÏó£­âüóǧ=z–¦;ÏÃ_Dw7-K©Èžçᨗ^Z„£GÖºuƒçy|÷»¿¢¯ïg,[ö$‰D?ž¶ ® †1ÀæÍG€–±˜N2™?þСC¼ím¬^½šo|ãšæñÁ®ã‹_<ÄYg¤Û´i”/ù% ÿ›àyZæðáÃ\zé𔿠/¼p&ýèJvíÚüö\qÅK n(—YüÛ³kW;{÷¶pþùã\}õn¾y]ðy!~ãŽ[ÌæÍûfõ[zÁG¹çžWÍê<Åi¦:ϱc‹ùõ¯—±zõqV¯>\—rÏS|>üáG¸í¶|£ò¬³Îâ Gùõ¯_äàÁ¥³>ϲe/rôè)lÜ8ÆêÕÇ ÎÎCå­Ò/[ö"gžùBPVUÏk¯ÝÏí·ŸÃ²e/²qãXæàÁ¥\pÁQV¯>ÎÀÀË—·¦ð¶lÙ2A°ÿ|#¿·èE~:¸‹x¯xÅy¤Óit]—qDA(“–wŸ»› ÷þ’·½íÜ‚ífQZƒu‡žàù±“ƒµÛäý„%™$û§7m?×õ5 >þñ›9tèz`‚?û3?é%—ü=´…ññq ¨Ž†Z×ÁÃáž\ žû ‹/æ”SNañâ¿a|ü“´··³jÕÏ8~|5ããçãA‘ÿ…Gù0pœ_þò_xâ‰Ë9~|5/¼p&¿üåXºô ûöm¦­m/ƒƒ÷ðÄ—pâÄ :Ä£sàÀÕìÝ»‹‡zžgŸÍr®X±‚G½7Hóè£wŸ{÷î`ll#K—äg?Û5)Mø¸½{wqüøjŽ_=ešjŸçСCœ8q‚+VÐ×÷Í\ÝßÏêÕDz>SÇug>ÏÁƒÓŸçÈ‘#ÀZ‘o}ëñø/yöÙ­X–Ûšðßïþ»l~„„³Îú*§vûöm¦½}k×ö±kWº ßÁ¶µkû?Ÿ±±S¦ V¬]Û ç©áy|ðº»ÿˆÅ‹ì;pàjöì¹~ÊcM3B9ìÙsý¤w·–×qÍšCe•»q]øÂNðóŸa÷î%¬Zõ)öìùp)k×öñþ÷÷±oß+ ŽI§óít:Ž¿H¤†ß&€¯~UÙp¹ùf›â…$Ói+ØÖ×gzî/Ïí·÷±hQœÃ‡Ó×g±bÅ'8qâ'Nœ`ß¾1~ýë_óâ‹oeÕªg¸ù毰víg9tè§vZ.ïÏqÚi`ïÞÇøíoOá”S.àÐ!ÿžÿêW§Ñ×÷Ö®ý,?ý©ÿûà8§v+V¬àСCÜyç¹à‚ øÕ¯^Í™g>ÁÏ~6Zðü>|˜;3hZ"wžÒ¿=™LõKŸ~ú6††Þω'Q7|ÜÒ¥Yºôà¤÷Dåqøðaî¼s'~»lß¾}¬X±bR›âé§o˵ãüë±bÅ öí»uë®æ7¿YÄ™g>ÁóÏÿ„“NÚÌáÇ9í´Ó8묳ü2‡ý §œr }}_ãôÓOgÑ¢/¿¼€ŸþôQ^õª{øùÏ7羂ññÛ5aà(/¼ð%V¬xÏ<óÎ8ã!N9å·<õÔ¡Ú<ÎÖø$mmmØöoØ·ïíœ|ò~Î8ã(ããw³nÝnöìùøÀI ñšÕ=_þò—yÓ›ÞTëb‚P'x÷«Ç²xñ…Üzëyضÿ;.k; Bù,šh8Û·oçmã¯dã§?Ä’×þ3'~µÏóˆD"¤R)1B˱uëVvìØQëbTëc_àëã\yÕ´µÝ„K„VdppÁÁAz{{k]”ª²}ûvº»»9ëþˆÎ‘~8 7~ðqx`œññ¯pê©ßæÒKÿˆK.ñÁRm]×ÅvMƒz'º[ÌíqëÖ­ÜÿŒŒLðæ7¯çío?‰7b…ÎaÇGåé¬pÝÂïàObPdž?¡a>Pž×Õê¶8Ž_vÏóëèºþwMËVu·m¿\¶]úº…¯º>áó_'Ï+ü ç©þ«ë &°qÝ|ÙÃeQiÃÇ©ºª´žççßÙ Ñ(OjWžm±XþáòwuùÇLw¯<¯ðš†Ÿ9u]Â×4|UýL³0õ¿TýÔuTÛŠ=ùþßÿ÷|󛟫ÎV' òï óÅ/~ˆ_ü5`óÒKßç]ïz5¿ó;˸ôÒKK.Ë ë:®ëÖ|!N“L&Ê’L&I§Ó Id§âº.]]]Äb±ºôŒ±,ßN;øµrÿàĉlÚ´IÞA uÇ ÃõÞðÐýõžûÎ+yæ™%$s Àz´é‚°ÌG› á<·oßN__ããã\uÕUôööÒÑÑ1ãq¿<>\{‰BÆq¢Ñ¨4*¡™«xtÅ£†5kžãèQd}GAhpæj Î|øa¬XŒs8Á¦wbÉ’KùèG{¸ãŽ;èíí%‹•qvAê¹Ú€Hd·ÜòNL³«`{XK˜NW(5ÿ@¥Ÿo=BÓª':Âd!/ü½x_©:OUÖâí¥Ò)1nªcË9OøÞ”JÞ6UÝ2_Ì[´¨ðØXÌß7¦ ‘ øÿÃ$¾ÈgÛ…ùLu]fª_XtªÎ¥º»ÅÏ“i¿üË“42sµÇóÌ3ãškžâ“Ÿü$ŽszYí€z˜€”H$0 £@U«eœ£¶èºÎÐÐP]<'¥ˆÅü¿fd®¶à÷ÿ÷彄&¡’þÙ,ÃÑ(¯|â¿zðZÇA×u'„YÒP1”áèííeÇŽŒŽŽrÝuוulöœ œæ<ÏÇ>ÖM:&‹ÅDx„£;ðüCg@žyæÛòþ BƒS‰-XñÓ2Ñ?gßs¬]û î¸ã+èºÎŸþéŸFk]5Aʤ;ðØcI[@˜Óôæ'& ÿ¦Á÷vœ˜ð/>6•òÉròʧ[pöÙg34cÿþý8ŽÓpƒŠ¥¼.kí‰)øÔ«èØÌTÚ.¡ñ™;ðÏÃûxÏ‹ÐuÈf³²þ» ̆wîÜÉæÍ›Ù¼y3ÝÝÝÜrË- ³sçÎ}pÎY?Û¶Ñ4¡¡¡†hÍ­-Õ¸Œ3::ZëbTÌððp­‹ÐÒTbÀ±|ùò†zÿÃ4Ãó'öL˜*±ÿ²æÍÖÎdÕ·c|éKÂ÷¿ÿ}Ç!‘H4„mh–ç¯ìY3Ô¡‘©¬Mýýý-åÝÐ,¶c¶´â{Új÷º[püøqzzzèïïo8Ñq®È;Ñ:´Ú½®´]Ðj´ÚóÍ11Zé^WbŽ;®Ëß¼9J›õ2ÿë–×ÓÕÕ…addÆX3ÜëfxO›¡Ýñì³ÏæÖ’ž; #<3::Z°þLGGëׯg÷îÝ3ÿÎ/?Ä»î¼ÏóÐ4­!Ãôõõ•UÏzf÷îÝôõõÕº³}ûöZ¡e©Ô¼â¯Â5ê@c3<bÏ„J©Ôüx|=¯°Ž²ukð@"‘h˜Ž4Ïó× ö¬êШTjZ‘f±³¥ßÓVº×óa ¢ÑhKy§É;Ñ:´Ò½–vÁìi¥çCÑ cs¡Uîu¥v`ÿþý|ð‹#ì3×Òû¿ÅqLÓl¨HÍp¯›á=m†vǾ}ûسgOEy4ÌGŽ(0Ë—/ŸQÍ?xð öþ­õ©O±lÙ²ZW§*È;Ñ:Ìæ^·zÿà3Ÿù Ë–-ã’K.©uUªF+Ú‚f‹˜ åÞëV3<~ü8w|ð-œÿgÿÉÀŠ¿á¾^ÆW\ÑPãÍð^7Ã{Úè펇zˆ‘‘–.]ZQ> #ñ‰OðÄOðÊW¾’W¾ò•µ.Μhä篙êÐè¬X±€«®ºªÖE©:ªMðä“Orùå—׺8-M3Ø‚F®Ã³Ï>KGGGÃ×c®üíßþ-¿üå/º ”G+>ß³aÍš5<óÌ3üîïþn­‹Ruº»»ùЇ>ÀÚµk9ýôÓk]¤ªÕ[h fs¯[½ Â06ªð:ZÑ´bgSïV3ü»¿û;~|û ¬>o5oü`ªÖÅ™ÍðŒ7C5kÖðÆ7¾±â6AKgŸ}6þð‡k] AjÌ»ßýîZAê‚VnÈI›@€K.¹¤¥¼a*Z¹MH›@r´²-þ àʸ¡ Ì_› aÖxT”r^¿~}­‹%B; ˆ-Aì€ >b A±‚ ˆ„z¡a„G¥´/.:88„‰¡¹; ˆ-Aì€ >b A±‚ ˆ„z£a„G€Í›7Ó××Çøø8·Þz+mmmlÚ´©ÖE¡JˆÄ‚ v@±‚ €ØAÄB=±hbbb¢Ö…(—ññq¶lÙÂøø8mmmŒŽŽÒÛÛËæÍ›k]4Aª„ØA@l bAð[ ˆ-Aì€ Ô %<*ذammmµ.Ž 5@ì€  ¶@±‚ øˆ-Ä‚ v@ê†AAAAAAA¨/jGAAAAAAAêAAAAAAA¨AAAAAAA¨AAAAAAA¨kÈøø87Þx#¯ýë¹ð 1M“;wNJ·}ûö Íu×]Çèèè¬öW³>¯ýëœuj];wbšfE÷¡Öu—rlA#=SÙ‚F¨Ã|Ø‚Z×AhLæ«MPnšjÔ§QÛ0³-h„:ÍI5Û õø /´m©·:WËÕ[½…é©f›¡^ŸJlA£½Õ«¨§: åQÍ1Åz|>¤MÐ:÷z¡i¤:_sÍ5 ÙÇn†qÏññq®»î:.¼ðB.¼ðB®¹æ†‡‡g]ÆzyÞª2f3!ÔŒ-[¶LtuuMÜu×]÷Þ{ïÄM7Ý4qÁLÜu×]Aš›nºi¢««kâöÛoŸ¸÷Þ{'Þ÷¾÷M¼ï}ï+{µësÁLÜ{ï½ÛË)c-ëq×]wM\pÁ–eMÜ{ï½7ÜpÃÄ\0ñÛßþ¶aê 463Ù‚F{þJÙ‚F¨Ã|Ø‚Z×Ah\æ£MPnšjÕ§Û3Û‚F¨ƒÐ¼T«ÍP¯ÏðBÚ–z«sµlQ½Õ[˜™jµêùÙ˜«-h´w¢ZcõTg¡|ª5¦X¯Ï‡´ 欢Þê] ©Î–e5l»Æ=Õùî½÷Þ‰{ï½wâãÿøDWW×Ä‘#GÊ.c­ëP|Oúyá±F9rdRƒ`bˆ?þñßßö¶·MÜtÓMÁ÷ßþö·ÇÍ´¿ZX–5ñ¾÷½¯ä[NkY÷½ï}瞘˜˜øøÇ?>qûí·7L„Æ¥[ÐHÏßT¶ ê0¶ Öu“ùj”›f¡iä6ÁÄÄ̶ ê 4'Õl3Ôã3¼Ð¶¥Þê\-[Toõ¦§šm†z}6*±öNTk¬¢žê,”G5Çëñù6ÁÂŒUÔ[½«A#ÔùöÛoŸ¸à‚ ‚¿Fëc7øçîÝ»'.¸à‚‰Ý»wO[¯F±-Õ³‘P«5btt”îînÖ¯__°}Æ Œ0<<¤Sttt°~ýzvïÞ=ãþj1<<ŒeY|æ3Ÿ)¹o¦2Ö²£££ œà–[naóæÍ Q¡±™É4Òó7•-h„:̇-¨u„Æe>Úå¦Yh¹M3Û‚F¨ƒÐ¼T«ÍPÏðBÛ–z«sµlQ½Õ[˜™jµêõÙ¨Ä4Ú;Q­±Šzª³P>ÕS¬ÇçCÚ>ó=VQoõ®RçîînvìØÁŽ;æT‡Z׳Æ=ÛÚÚØ¶mÛ¤:„iÛRÍ1›SªV+¡€õë×O2ãããÜu×]ÁÇ‘#G&ý¸,_¾¼àGgªýÕ`||œn¸X,Vò囩å¦Y(Tüᎎn¼ñFFGGéèè`óæÍA}ê½Bc3“-h”ço:[Ðu˜[P6YhLæ£MPnš…¤ÑÛ0³-h„:ÍKµÚ õö WöÔÛoxµlQ½ÝkafªÕf¨·wBÕ³[PNêé¨ÖXE=Þkafª5¦XO£´ f¬¢Þîu5h”:wttÐÑÑ1ç:ÔºžÍ0îÙÑÑAoo/à oGŽ¡¯¯õë×ejÛRí1ñx¬vîÜÉ5×\CGG±X¬ÖÅ)˲X¾|9Û¶m«uQ*âšk®¡­­õë×3::Ê–-[êêGFhÄÔ±B= v öˆ-Fµ³¥™lËl[$ÌD«Øh][ v@(‡V±­j@lÐ<4º½Ú¾};[·neçÎlÚ´‰¶¶¶Z©lªmCÅã±ÆŒŽŽrã7288ȶmÛˆÅb óÀÒ××ÇwÜQë¢TL,+xéLÓ¤¯¯OúÓµ.šÐ"ˆ-¨ÄµDì@ý0•-¸êª«j]4Ahh[1[šÍ¶Ì±EÂT´’€Ö¶Ò?¦£•lA+Û[ 4>Íb¯”÷æàà [·n¥­­-ð4¯gjaCÅ㱆 3VlÛ¦···ä WjKØv¦ý Åàà Ë—/çÆodëÖ­lݺÈ+ÿ³©C-ëL2W]uUΠQê 4.娂z~þʵõ\Å|Ø‚Z×AhLæ«MPnšù¦™Ú0³-h„:ÍI5Û õð WÛ¶ÔCÃTËÕ[½…é©f›¡^žù´öNTk¬¢žê,”G5Çëáù6AuÆ*ê­ÞÕ ê\ï÷¶ÑÇ=ÕZ«aº»»éîîfpppVe¬÷±ÛrËXNkÈu×]ǦM›¸å–[JÆjV±r‹æ¤££cÆý ÍæÍ›ùô§?ͶmÛ‚?€M›6ŸË)c-ë±aÆ’çÿx×{„Æg:[ÐÏßL¶ ê0¶ Öu›JÛå¦Y(š¡M3Û‚F¨ƒÐÜT£ÍPOÏpµlK=Õªg‹ê­ÞByT£ÍPoÏÆ|Ø‚F{'ª5VQOufG5Æëéù6ÁÂŽUÔ[½«A3Ô¹Qîm£{îܹ“-[¶L›¦ÞmK-ÆlDx¬ƒƒƒŒŽŽÊxø/¬oÞ¼™¾¾>ÆÇǸõÖ[ikkcÓ¦Meí_HÔKþ V-·ŒµªG[[ÝÝÝlß¾=8÷àà ;wî,aTÏu›rlA½?娂z¯Ã|Ù±Â\˜¯6A¹i‚fh@y¶ Þë 4/Õl3ÔË3\MÛR/u†êÚ¢zª·03Õl3ÔÓ³1_¶ ‘Þ‰jŽUÔK…ò©æ˜b½<Ò&Xø±Šzªwµh†:×û½m†qÏ«®ºŠññqn½õÖ‚z Î{;d¡¨Å˜Í¢‰‰‰‰¯™0‰íÛ·<¬aº»»ƒxÁãããlÙ²…ññqÚÚÚ¥··7p±Ÿiµ¹ð ٱcGÁ[NkYÑÑQ®»î:†‡‡Y¿~=ÃÃÃlÛ¶ÞÞÞ†©ƒÐ¸”c ñù+¶P‡ù°µ®ƒÐ˜ÌW› Ü4Õ¢Û0³-h„:ÍI5Û õü /”m©·:WËÕ[½…é©f›¡ÞŸ¹Ø‚F{'ª5VQOuÊ£šcŠõü|H›`~Ç*ê­ÞÕ Ñê܈}ìf÷ìëëãÆo¤­­åË—3::Úðc† ý<‰ðØ ¨xÁ6l(³}¦ýõ@9e¬e=Ô¹;::¦tq®÷:ÍM3<P‡ù°µ®ƒÐÜ4Â{Ô u˜É4B„Öe¾žÏF{†ç£NõVçjÙ¢z«·0?4ã;1õn´w¢ZcõTga~i¶wb>ê<_×¥uZ豊z«w5h†:7ý­÷:ŒŽŽaŽ›}Ìp>î…‚ ‚ ‚ ‚ ‚ ‚ ‚ TŒ¬ñ(‚ ‚ ‚ ‚ ‚ ‚ Bňð(‚ ‚ ‚ ‚ ‚ ‚ Bňð(‚ ‚ ‚ ‚ ‚ ‚ Bňð(‚ ‚ ‚ ‚ ‚ ‚ Bňð(‚ ‚ ‚ ‚ ‚ ‚ Bňð(‚ ‚ ‚ ‚ ‚ ‚ Bňð(‚ ‚ ‚ ‚ ‚ ‚ Bňð(‚ ‚ ‚ ‚ ‚ ‚ Bňð(‚ ‚ ‚ ‚ ‚ ‚ Bňð(‚ ‚ ‚ ‚ ‚ ‚ Bňð(‚ ‚ ‚ ‚ ‚ ‚ Bňð(‚ ‚ ‚ ‚ ‚ ‚ Bňð(‚ ‚ ‚ ‚ ‚ ‚ Bňð(‚ ‚ ‚ ‚ ‚ ‚ Bňð(ÔÏópg^ó³m{ÁÊkÛ6žçÕäÜõ|]¡ÚL÷<Û± SSïå„J˜Ëó=›6‰¼û‚P?Lõ<—êkÌöùŸ/»0—sW“z.›ÐšÌçX´ æ÷ÚÂBR黿m‚¹”¥mC=—M情|Æ¥?à#ÂcaY®ëÖºó†çyôôôÐÞÞNWW]]]óÒ©p‡H$²`åŽD"S–s¡Ï]Ï×EX8šíÝŸ\×-ùÛ¶ƒÙmÅêt2™,È;›ÍäWüÃ5ÛôS¡Ê™Íf Ü]Õ ¼p}ÊE›N§ƒ:‡¿—J3S~åÖÕó<,Ë"“É i©T ]×g¬›º_žç÷i¦‹á{9Ûã˹7SÝË™žÃ™î¶í‚{«ÎYªì3;_õ®WZáݯä½?Õ»?›÷~¶u-çý›®~ÅÏsñ½ŸÉ®„Ó6›]Ÿ·¸üåÛ̶¡» ®W)ÛP+» Ž™OÛ0ßm‚ÙÖw¦wpººÍæý-~÷ÃÛ{zzˆF£e_³©î‹¼ûõC+´ TþÅõ)—Zö*m¨ûTª¾³i¨ôÅ÷z¾ìÂTõWç»P}¦»îÒ& ,;°m‚™Þ_iä‘w¿|¤?03µîTòî«{4ßm‚ù'˜î^ÏÕ.„¯ÍT×BƧf!Ú꺖ûì7’](µ­^Ç+Ñáݯ¤MPÎñóQ÷¦=Ï£³³3¸(Ùl¶ÀE4|“Õlõ§Óé`vŒçytuu\tµßó¼ AvŸUÊ\ÓÏ–t:M<f2Ì&ˆ:VÍ„(þ^*ÍLù•[WµÍ0 ÇÁ¶m4M#•JÍX7õòwvvçŠD"%ë­öyž‡a³:~&ººº‚ãlÛ.˜Y5Ós8Óµ cÛvðŒF"‘‚ý===“žÑ©Žæ¥ÞõJ«¼û•¼÷áã§z÷góÞ϶®å¼ÓÕ/‹100P`+åØu›Í.Àô¶a¦c¡ymC%vA]»©lC=Ùu|½´ f[ß™ÞÁéêVîû[êÝWÄãqb±Ø”å ï~}Ñ*mu|½¼ûÕlÀÔí‚rÛê—² óa`jÛ v¡6LwÝ¥MPxìtv`!Û3½¿Ò&È#ï~yH 1ú•¼û°0m‚ù'€…i¨kFÆËc¡Úáýå<ûdJm«×1ÄJôƒFx÷+i”sü¼Ô}¢ ˜WmlllÂ4͉‘‘‘‰‘‘‘ `bdd$دëz°˜ öe2™ MÓ‚ïÀD&“ ¾†1‹Å‚ï‰DbÂ4Í9§ŸÓ4' ¶‰D¢ ¼åæW|lñ÷©¶M—_¹uíïïŸ&LÓœÐu}B×õ MÓ ®ýTuS÷7•Jì&ÆÆÆ‚ýccc“Ê~>¦:¾œz ÏFøYŠF£Á³7ÝsXÎ9„¯]q‰Db"Îxìtõ.§L@«¼û•¼÷¥Ž/ÇÌ”_¹u-çý+§~Å÷zbbz»ÒìvabbzÛ0ݱÍnæj&&&f´ µ´ ókæ»M0ÛúÎôNW·éŽý÷ÿ÷iß}•Ö0Œ9Ýy÷ë—Vi¨üëåݯE› Ôýž©¯1S»`>ì‚Êg*Û v¡6LuÝøÃJ›`ŠcKm[È6ÁLﯴ òÈ»_ÒhŒþ@%ïþt÷»’6A¥ãªÜ3Ù†Jì‚:GC,…j¨ëZî³ßHv¡Ô¶zC¬D?˜¯1Bu\½õ¦;~>ßý¦ôxT3Óâñx0“e``]×Éf³˜¦Y0{M…аm]×ñ<Û¶ ¾‡]¦ÃÇjš¸êÏTžrÓÏÓ4Kžk¶Ç–ú>Õ¶Jëžq422ÂÈȱXl’ª?]݉Dð9‹ä ù…\§ ‘2Óñ3áºî¤gIå.o©ç°Tj&‚mÛ³ ÁPªÞÍû»•ÞýJÞûâãËù^îµ/·®3½s©_9v¥Yíˆm˜Š¹Ú(Ï6Ô“]€újÌ¥¾Ó½ƒ3Õ­Ô±¿þõ¯©ß}5C3“ÉÌîB!ï~ýÑJm¨¯w¿QÚPÚ6Ì—]PyMeÄ.Ô†©®û}÷Ý'm‚)ŽjÛBµ Êy¥MPy÷K#ý¹[êûTÛæ£¾óñîÏ5_˜~¬ Òq6A=²m‚pþ0ó»ÞHv¡Ô¶zC¬D?w¿°¼³}÷›Vx|7ÒE‹Ç¦½À®ëquó}y„™Q×4Ú ‘HF{.)Ã0H$Á½Ÿíñ3áºî´†`ºç°’É$‹- bgWúc4ß?fµDÞýÆe>žÃéìÊ®]»€æµ ¶a*æj@lC=PÉs>vªwß²,4M#›Í¬ç B³”‹¼ûõ‡´ —…n„û¥lÃ|Ù˜Þ6ˆ]¨ S]wiÔ =V m‚¹]·FFúÁB¼û³Éw6csy7¤MPH› q™¯qw®×­N™—šÔ®ë¢i™L†L&ƒã8D" Ã@Ó´) ˆÚ¯n8ÌV(Žû/TÆtk¹²çyAZs8L&“Áó¼ ãPj·éŽŸ ]×K.D¯˜î9 Ïxœ Ùl˲)X`{6³-*­w=#ï~ã°Ïát¶cÙ²e@sÚÛ0sµ ¶¡TòNwìTïþ|uåݯ?¤MÐ8T»M¾ÿ¥lÃ|MgÄ.Ô†©®ûW\!m‚:a¡Ç ¤M0·ëÖÈH 1˜w.ùN×&PÌÇ»!m‚úCÚÃB€¼û qÍMéñ¨}UD×õàBE£Ñ`1að/œZXÓ4Í‚ï_ ´^hoº®,dšL&Ñu½l#]¼¬¦i“: jÁèt:=i–b9ÇOG4-XxUÍvQL÷–Cø ŸCÓ´ÀhL5ó«Ô±¥ê­®y³ÌÊ‘w¿q¨ôý+Åtvåüó϶5›]Pßg² ÓÙ…âº7“m˜«]± µ ’w°Ô±7n ¶•z÷MÓ$•JÊŽ¤R©Y…7‘w¿þ6AãPí6Aq_£Ø6Ì—]€émƒØ…Ú0Õu7 CÚuÂBH› uß}é4óñîWšïTcóÑVYÈ6Èâ\6Aã0ßãåêõþîWÒ&˜îøâºÏõÝoJÇX,F6›¥³³30†aF9‰`šfйT7$•J‘L&ãáºnÁ †Z¢iÉdÏó*R½ë…þþ~"‘Hp­=ϛյv]—ÎÎÎàØ©ÖbˆF£D£QâñxAþå?Ê»§§Ã0p]—X,̘î9œ‰X,äëy^ÐŽF£X–Egg'º®ϯšÉ‹Å¦óZÈ<çJøåŸÏã«QÇzºŽ­†¼û³Ëk¡ò¬ôý](¦+—؆æEìÂìòZÈ<+± aWä½onäÝŸ]^ •g½¶ ªy jua2­`!¿JY(»"ï~óÒ ï~#´ ê'hMZÁ.4B~P»qy÷燦 µ:º®aT8%å^ZK¦Šµ¦Ü9ó™×BæYoT£Ž­pëy÷g—×BæÙhˆmh^Ä.Ì.¯…̳Þ÷¾¹‘wvy-dž†Ø†æ¥ìB#äW¯È»ß¼´Â»/m‚…AìBóÒ v¡ò«WäÝ/Ÿ–óxAAAAAAaþ9©ÖAAAAAA¡ñáQAAAAAA„ŠáQAAAAAA„ŠáQAAAAAA„ŠáQAAAAAA„ŠáQAAAAAA„Š9¥Ö¨ãããìÞ½»ÖÅ„ºaùòå¬_¿¾ÖŨ:ÃÃÃ9r¤ÖÅ„ºaÆ ´µµÕºUEÚ‚0™îîîZ¡êŒŽŽ2::ZëbBÝÐÑÑAGGG­‹Quk]A¨+¤ ‚Œ ‚•· MLLLÔº ͧ>õ)ÆÇÇY³fM­‹2gî¿ÿ~Ö¬YÓÐu8pàà’K.©uQ*â{ßûïxÇ;j]ŒŠø¯ÿú/¾÷½ïÕºUçïx¿ÿû¿_ëbTD3<bÏêƒÐÖÖÆßüÍßÔº(U¥ÚÍðüAsسf¨Ãý÷ßÏõ×_ßrâãûÞ÷>.½ôÒZ£ª4‹í˜-ÍðžÎ–¹Üë{ï½—ÿ÷¯uÑ«Êàà 7ß|³¼-€Ø¿òþAãöæB+Ú‚f‹˜ ³½×­:fxñÅóÁ~°ÖŨˆfx¯›á=m†vÇ/~ñ Ž=Ê·¾õ­9çÑË–-ãÊ+¯lè•íÛ·ÓÝÝÝÐudppÞÞÞZ¥"†‡‡›¢­ÈªU«šâÞ5zÄžÕª­F3´ šáùƒæ°gÍP‡í۷׺5aÅŠ ïfK³ØŽÙÒ ïél™Ë½nÕþÁ%—\Òrχ¼­Ãlïµô·0ZÑ4ÃXÄ\˜í½nÕ6Á©§žÚðïD3¼×Íðž6C»ã¶Ûnã?øAEy´„ðØ lÞ¼™å˗׺±aƦßÓÈFCh|šáù{&•Ñ,Ï_3سf¨ƒÐ:4‹í˜-­øž¶ê½ÊCÞ‰Ö¡ïµP>­ø|4ÃXÄ\hÅ{=Î9çœZ¡bšá^7Ã{Ú íŽµkײnݺŠòá±Ahô‡ ­­­)Ö hÅ8çBýÐ ÏŸØ3A¨ŒfyþšÁž5C„Ö¡YlÇliÅ÷´UïµPòN´­x¯…òiÅç£Æ"æB+Þë¹pæ™gÖºÓ ÷ºÞÓfhwœ~úé,[¶¬¢vîÜÉþýûkrþélÁBÛ€ýû÷³uëV®ºê*6oÞ\“k õÀÖ­[9rä\pAÕÏ]/m‚åË—O9¸!­Àðð0Û·ogÿþý“Þ¥jP©-PÛçÚ&xüñÇÙºu+ëׯ—þÐÒlß¾ááaüñšœ¿Öýƒï}ï{ ÓÛÛËúõëkr ¡þôAÆ ḛ_¾ÿ~þó”S`ãÆ²Ò; ^¶íKy¦iN™^}ÏFîÀó<4M+Ø ¥O‰Ðw7”ŸúoNq|˜,“…Óð±ÅÜ´o?}ñÅIõ Êh¡}VnŸ::÷=V¢ìJHüÍáðbà‡FM„òŒý¹|T¹Ãå}í\³¦dÙUþN.½Êþ²};Y`õêÕTÒS®ŠðXkV®\É»ßýîš ªB=¡Â lݺµÖE© çœsŽt$رcƒƒƒ%kov¤M >ëׯgÇŽÓ†5kfV­Z%mA€@xoÕþÁ ;év€IDAT;Þñ™| Hÿ@ú‚ c†2fXš]¿ù c¯xEÙéÃ^t—.eW{{IñÎc²×_±ùýûÙ“øÂ›ÊïÏ=GtÉ’à˜$¾¥=øÒ”•è.»›K?•ðø£U«8~üxð]y¡ï¾°hSèM©B£†EÓx.­“Û×¶w/?{Å+HçÊ•Î]›Xn¿ôä¶¥B×R¥=´fM „zä…Jµ¤™Ë'ž;NË]‡§z{Ùó⋬¬°MP•P«‚ Buñ¼ù NPˆã8XV#/Ï\[ÇÁó<<Ï#™L⺳]¦[AAAA|¯Â…Ü}ÖY`Û¦;“ ìÛ·/øþƒ—_fÏsÏ•Lë”ÈO tª>œ|rçbX¨tÝK–ß=òbÊßuƒó8z4*1ÎʥφÎCnûÐØXɲgñEÕÃííÛÂùßþÒK¤ñÅо@¨ö+Õkã‹€¾xÆg>îöv’ä=)í\Y“À%<¹´±Ðþv|áñ¤#GSy4væÎ;’KŸÍ•+ƒ/DƯŒóûO?Í÷ß?ó2 u%<–r{.wRNA±¥™­8ǧÝïº.Édð̳Ùé#y;ŽƒmÛ8ŽC$™1}5ë:ßxžÔ5™L×)ŒmÛX–\;•.‰LJïº.===D"âñ8]]]´··ÓÙÙI:î•eYAcÑ¶í  ===¤ÓiÒé4‹- ΛL&±m›t:MWWÉdr’ ìy^pïâñxPÆööv®¿þzöîÝ[Ók=b A€™ßs±‚ÐüH›@[ ‚Ø©ˆD"8ÎlWWœšVð5<òä87õ«ùïÀ#k×Âáî%K‚0¸0y]AµMýWŸÓé4_t·íÛG_l òð¼@(tŠòëÉ}þÚ½÷‚mç+ÓäÅ>=W.3T†o<÷\°¨< “¹s\œæ”hhçÊò¹]»øÜ®]Œ|hÏbÀÁ¯ð=4ðÅÁ,p÷ø8Qààõ×ÓOÞ#ó©ûïÇÞôè£üû±c¼Ü×G6—w_ Là{=jä=KøÂ¥úþ†ú'>12RñcS£ gP¼Ðëàà`Û¹œ4‚ 4.b¦§”ø5UÛ¶K ƒJlô~þ8–,)8N x¾xÉW¾Âé{ö&¾°˜9÷\7rÖ¼ñ—¿$‘Ûçº.ëž}–ý'ŸÌ§ò“`mÇ4¾¸"•"aÛ<{óÍÁ¸îYéŒ\YWßr `ôž{ðBã¿Û?ð4àà»ßÍ™÷ÝŽƒ«c,W¿Tè¹ë¥„KØ86Æ¡o|ƒ‡~˜û¢g­nÖxܼy3}}}lÚ´‰¶¶6n½õVÚÚÚØ´iÓ¬Ò‚иˆ(òªS¢Q)Ç (5+Èu]t=ݲ,Òé4Ùl×uI$Äãñ`‘æl6ü™¦‰mÛd2™ m,ÃóúQ~~ä¯[¾ÜƒJshÍÜ£G_ø[ûÈ#ì;ï<zþyN~é%N,]ÊøøxÞÆ»þzñbÎê)Þp×]‡ïA)Ñ1|]ãa“DÇzGl 0ó{.v@ši‚b A;0-©—.-+© #ê÷t+öxTãs®ëòÔ9ç002Âë6nÌ{ 愮ǯ¸‚ç.¾ ?dèZÇóÎã¿{Œ_tt°øØ1Æ6n|á.ð˜\º”¼ÿ~þuh((C_ MÏvw3ºf Üp¤R¨Q°¡þ~üá²xt”ÿŸ½ÿ“£®òýñg€„ÄIjŒg 5òËeS#‹QÀ5 "àÍnO¼«¬ä®éÖëºèÞh÷þÝ‹ww»u¾"®¿º¢ ^q?fúŠÊŠÆíZQq ÔÄ!„¸a* èïU§ºº§çW2¿ç<I§ßUõ®wUW½ë]çõ>çXßÿ>¸.¿{ó›i;í4<à´l–®ùÚ³ÙÐÎçyì]´‹ÐÛÏ%ô0LŠŽ$ÎC©Tâ¿~ýkظ‘%ÿëqz”ßÒÚvò°ëßàÌw½ ß÷C›¤ïc'ê°€ýû÷ÓòùÏ·yÜpCl‹¼ríZöÜv^ä¨þmÓ&:æÏ¯Iý$QæŒR ¶Y;j¢Õ‰­W¢¿=sÛm@ à̬a®ÿ4ÄQàÄ¡à–[náMozÓq]–“.<>üðà ˛šš¸õÖ[ck×êF³Ž¢(3ƒF}Á\ê’žlIA«T*ašf,øyž ɨ†aÄ™ “Ïç)•J‹ÅXD$4j:®ÏÄP„¼¤—ÞpÈúÒÖ¤@iY­­­ñqA@[[†aÄ¢œ¬Cy¦R©X„¬Q“m“²z±/yNësF†Q³ß‘Ž5¹ÝtDz¬šß]DÚ銎 Ecï ´P”ÙÅ\?PEßE Ñ1Áèñ}²Yî½ýv®ŽÊ\ªB„ѱ*•J¸~ýöÔ†Hø?Ìßù>/\UèB”ªÇ¶‘”GþŸÿ9˜&ÿçèQòóçãüÍßÐ|æ™ü`Ã^|ñE\}5G¿õ­xÛæ8á„X¾{7ÿìgAÀêG᥯|e4<ôásáwð3Ç¡éÏÿœÔ™gâû>{"aíè¿ý~@ðè+_É=÷÷>þ8ë>÷9®:HÙnœŸ28'"<ÖS*•xÚ0¸à¾û¸ç¶ÛX`YÙwÿíß²ÿž{BÃýûq]7<÷žÇ»wC$Ð68@óþgl³•ôNâ±ç¶Ûj>ËóÈ|ûÛ@hãG±÷ŠM³£££Æ± T*aYVœvÊ÷ýØóˆmƒŸüå/á’K^;…BT*E{{;©TjPZ­3Ï<ó¸®Íiãñ(H<æã]GQ”™Ëlí’♄#M¥R±·ž<”$—_GGG,:Šgžã88‘ë½x¦R):::ÈÊlžq·‡ða+áAašfÃШC1Üú>µP(Ïçãü‘år9ÞO4£i($¤i²Î±ôú«g3É·2Àiä59S˜­}¢(cc¤û\ûE™ýè˜@Qо@Qíêñ}L“½{÷ÆeIáQlbRùÀ`!ò޾>8í4ö>Ìo;óâ(°wÑ¢0j´Þ‘E‹ð<3Ï„  Ï0°œï³èða77sÞ'>Á‘¨æDËzz8uþ|ž¾óN‚§ŸàèÑ£5B  ø®Ë’B‚€¯|+ŸÇ‰D¹eýý(•pö¾§o¸EË“‘ãDxL%ê6ßEh`þ§?o¿ø¼óxÚuùÆ?ýS¼/‰ŽçM»v‘ù§Âq.¾þzŽöôÄ¢iš8ŽGŠs'ÞW.—£T*ÅN"–eÅc2 \&“Áó<\×í£A`Û6étšR©D¹\Ž;•JÅŽ-KŽ­žØ ˆÏ‡¤¹’tMÅb1ÎË)Ûÿö·¿=®kó„ãÚZQE5ŽãÄžR©?Ð\×¥P(Äâ <|\×¥··—J¥B:®%{zz⼋IOB!9˜YH“)@ÉÃTrvuuMšÇ`£ýÌ´P£ÇŠÌŽÊd2´µµ +6+Š¢(Š¢(Š¢(Š¢(3—{#OÄ#‰P«ÉЩ"<ŠPæÕ­#ÞŽâçöÇ£Ý:¾20ÀÀðòÏ~…Ç¡hðËN °,æ:¥§=ý4Adó<¼s'óâ±nFÖ>û,ýé4 >óž¾ùæ°žÇüûï'ýßu]ZŽ…B!öú£P¨ÿô§…#5ÅæÙ\“^ƒÑsñ¾}q>K“Ðû1>WžGkkkìõgYwíkñò?Y·¢èrétÛ¶ÃýFvƶÖÖØQ$›ÍòØÍ7Ç^™Åb1÷²ÙlÐ)åétš|>ï_¢´‰×qºººH§Óƒì»étšr¹ŒeY¼ïÉ'0 “iš\³xqíÅ9†Èþ+• žçQ,P°4 ƒ-X@ks3¯^²ä¸®MEQ& ×u㇑<`d6Šx2¦R)²Ùlìî.2Ó4±m;jƈŠ2S¥­­mP~ȉ&NÓÛÛK¹\¦§§gREÏ¡ò"ÎlÛŽ=K³Ù숞¥Š¢(Š¢(Š¢(Š¢(ÊÌfß+^ÿPܯ)†‚ºuEˆüésÏðó7¾J%vÿíß‚çñï+Wò/¾Èy_ÿ:+öìáñ•+¡XdÞþ'xgôôTCˆ§ÞqG5l§x]vtpà·¿¥ïþûc'‰ ˜Ç˜„áDÛÛÛyîsŸƒ(”©L¨/ qxÑg®¾:>Û¶¡P ['Ú%퀗ïÙSsìõ ‰ÄÛ°X,ÆÛ‰ öò+°}Ÿt:M±XIJ¬øOì¬":ŠÓˆÔ)¶ÜÞÞÞAb³M§Ó5vL©×¶m~óóŸÄëÈz²ßzûgË÷¿„6äóÎ;wíÞ]]èûÙ vÜuÞ½÷²îŒ3Âv¹.›ûûù“eËxå/ÉØÜÛ{\פ ʰÔÌ€xf2v’1’•¹‰çy5£|O¥RñC%•J‘Ïçã™0IÊå2åryTÞ{ɘßPuÁŸL ÈÔ“Í\¾ßlÛ&ŸÏOëÜŽŠ¢(Š¢(Š¢(Š¢(ÊØ)%¤FHÞÆyóæ…BXBxô«n]¡P(ðØÉ'‘eBxfÁVÜußyÏ{xfÏyßûÀóxîïäõ‡sú®]±0°ç«_Bqlճςç±ã¶Û0MsPJ¤]_üb중Ífyîë_¯YžtÐH§Ó5‡–eA.G*•¢§§'¶}Š °®¿Øóešf, &Å=É©˜´¯‰ý¶fÿÑþLÓŒÇd>Æ$âá(Ô‹‡â„ÒÚÚÊyßû«W¯ŽÓhɧc½½uÁž=XÀòOäÀ½÷ræÀ;ò“Ppô¼0Ôj¤í\ÿ/ÿÂïN: +²Ÿ>qË-œô»ßqÎc±`Ï^wòÉ|éKÇ|m&QáqŽ“K¸Ø6B’ ™L¦æ{½0©4ÆuÝšs-‚ÓPHìçäöÉs]/ªxž7§òØÍDä÷“W>ŸÃª¦R)Êå2Åb1~(V` y—J%òùü˜ò7Î’“$t„¢(Š¢(Š¢(Š¢(Š2q§Æî›´sI¨ÕxYô)9Ex<4>­„žŽVÝúpûCQ(BÏI±IG¶ÌÕ«Wðâ¶m¤R)fù^þrþãcÃuÝP¤+• Ê1hóâ”[n‰½G2×a²\„¿®®.òù|l+ñÍ4ͯÁ¤°(‚v,d³ÙAž²_q ±,‹EGŽ "MÓÄ4MV­Z5È^/Ë’mM’<®w¶´°yݺšý§R){ì1Ö­[G! G›ü-_|1FGßBä.ÿÑ “Ëâ…óÏçë›6‘ËåèêêÂ7M^uø0žçÑÛÕÅÝ{÷òÁ³Ï¦¹Pàô xøÕ¯>¦s'¨ð8Ç©7È'Ű j’¥º®[³~ƒ„Ë‘„Ì©DfNŒ–z‘µQ}I†›mR*•jÎe&“©Ù¾P(Ëåð}Ÿ\.W³<:::jê¯_ÞÞÞ>¤¸mmm¸‘‹z.—S!f‚Nü•P§I±««‹þþþ ñD4 ß÷ ‚€t:=ç½ßæJ¨UEQEQEQEQeæâQë‰(ve!‚ØÆ|àÀšme;åùûÆé§ŠŒPZ£u-àg¿ÿ=A6ËÑ–ÎüÑj¼_óüó,<|˜{¾øÅоí{Y¹ Gݯ?3Z.‚ÜéMM¤¢õD$4 £ÆNïºn€(Þ}bÏ“üƒ‚DYá1‰x ®^½šÃ‡®ëläÒ6`H[ªˆ‘¯|ôQ^øpÜVY&u<ñĵN[žÇË-Š×äpâyqXÚþþ~yäN½ÿþø7—cû«¿ú+ ß熻î¢P(@G·vvâçîØÁéû÷³äßþN>™?ø¯ÿŠ=¿üè£<ÿ_ÿÅŠÛnc×~€\ôÄ8ŽÃë.ä²?ýSìØ¶Íî| &|ï± ÂãG’¶ …(Y+T=´ä”NÊK¥Ò ¯¢éê)"ép‚[R4•<|²¾ˆw‚ã85Âd.—«Ù^ò÷Éy‘0“ÉÐÖÖDZ.•J±èè8N,æóùØË±½½=n“ïû±7¤l×ÖÖV“`7IGGG¼¿ŽŽZ[[ñ}Ÿ—§«´2˜z¯TÁqZ[[) ƒf²GãHX–E¥R¡„p³‘F3†&3Ǥ¢(Š¢(Š¢(Š¢L5õv»¤X¡(Êô%$Ý]\×­¹wÅ®œË娷o¿yÉK€ªÇ㮦&€0#ðƒ¦&, Gê  { …Ç_þrˆ„¶ MMà8± ·ðða–þâq(ÒEGŽ€çÑÖÚ·)›ÍR,ª½Ó0 ÃàÂ;îàòõë㲤X(¡KEˆûÝP6Ód˜Qñ¬·ùIݯyÍkX½zõ°Ž"õ}b2ÜjC'†D]g½ìe,þõ¯«Â§ïsq$ÖY–Å /¼P»ïR‰755aYO<ñåH¸q¶½å-”"oѶL†+"Ͷ¶6îøö·Y¿`étš›þâ/hmkcËùçC©Äëœs/¿œ/½å-D àã—]Æ¿žtwÌŸÏž¯~•y…W>ø ^»–wýíßrâ‰'˜&…\.'S)èê‚q²W«ð8æcA¸Êö®S%ò)‚Šã85³DL“õ’BÝPÔw’õbÝH1ªë}4áEK¥5b`²Ý ®ò×ÑÑ·KÖÏd2q‡.‚ŸÔáºnìÚ,í‘zDh”|}’4¶§§˲bOÆl6‡Ãìéé‰Ý¹ÛÛÛ1M“ÞÞÞXüÌd2d³Y‚ ˆ“×6š!Bk>Ÿ§··—t:M¹\¦««+v‘WÆñ(­§T*Å1ÈUüREQEQEQåx ‚`H›˜LR»”|onn6í2·Pzæ"6íB¡Àï^ö²šeò«>uÒIôÍŸÀæf,À$îš|8óLì àÝßùN(¸•J5ÂÛ¾¯=ýÎ}æpÝXXl„xõA("&½“áF…¤‡£Ô9TžDY–¬3‰´óþà8áàAº»»®ÏìØ1¨Þ!E<}èÞï~—e½½ÕežÇ¼îœs8sùòØ™(±C.~î9‚ `íÚµ\~ùå5ŽMûO?×áT•¡IÞqŒyEQEQEQE™áȤx™Ä.ùÅ+Êu]ººº0M3žð.!§£Ø”œX?“;ãñ0’]w<Éård³Ù Æ¥.µyë ¨¦{zꩧ°¨Q®GXyø0GŽàÙµkÃå¶Mý/-ßï»õVذÛ0È^uîâű'¡eY,ëï×ÅŠ<û–,Y®‹™kêô ‡ZoáÑ0 8÷ÜskÂ¥ŠÍ{([¶ìs$[ë•W^ɪ[ná· Z&öþµ·ßÎ)‰¾gH1Uœ¥DËÞ°f ÍÿùŸá²È¹xî¾û(ýèGü`ÿ~^\º”|ÔÞ=·ÝFÿæÍt‹œüÀ|ðýïç7/y ^&áûïçûK–øÎwXûì³Jqxóf¾ÖÞΫâèƒðæ?þãp©r }ßù§/YRõTŒŽgõo˯~õ+ÞüÍoâ¿ï}Õßʶãu'²¯QÇÀpƒ‚¤‡"P“G°žŽŽš››)•Jƒ„* ûiY¾ïS(âØÊ"LJWÇqbQ˲¬ØPTR¯Ô#H²ÌqœÄF! ’Ëlj=P%…Ëd˜Ød™$ M¥RxžG[[¹\Û¶) ´··“J¥âAY±X¬Yß¶mz{{coÄÞÞÞØ#Q™(/v-™ì^.—ãÈZ"LɈgPµuA@{{{ý°ÑzÉïÇs "µA@ss3íííc ÉUñGÒ,FØn±3Êÿ‡:/ÉõÛÛÛãP±m(ÄCrÊþš››™7oÍÍÍ<yX)Ó‹š…ÙllszÐ)ãŠÃÇB`Y]²¤z½[¿?zúûã°™Oug¼ø"G~˜e½½^¹zz Pÿ¨ ‹¿þÞ÷€Ð«2V®\‰AÕ˲>ª„Mæn„ÁN2B£|I’eûöí =(HþF¨FHjû=ù—Ãöç=÷Ü áQÚxòcqÎÓOóÄO„žŒ¾A€ì¸í6nyè!ÎÛ·¯*<¦Ràûk„ˆ(Ùl6Þ·´_DS×uÉd2±à)ïè…MD¶dJ&±{Š]KÖ“0²bË;ŒœâH öA±†‹˜]]]q}bw„О—Ïçc§ ö~§ Ã0âÈnâ]*Ë3™L¼¯¤ —N§9hȺb+ME^GI!BTÎ…8‡Èï"é ¤®®®.:::bˆÖÖÖW·´)›ÍÒÚÚÛ]“ŽétšŸþô§Sw(1?9|ïÁC[cW¿¿í¶ø~"æ×¯xE˜“¯¹™æÍ›ytãFV&ÃsW]ÅëÖ…âUt¯ž{×]pÑE•c”tM’zI~'97ù|ß÷ãö‹ÅØËP"¤É¹Ò¶íøØòù|lÏH rîz{{ ;I'‹t:‹9R—¤k’hjâÐÑÚÚªöÃIb´÷«¬µgÏžª—d¹ÌoçÍãÙHP&ŸgßUW…Âb°hï^VìÙƒeYô:$;Â{ÿ¤ÿ8Ç! Wžç1ÿСA9%ë'9$ïÑƃF¶téß,Ëâí'ŸÌÑÚIʶã~å ÷ÜÉ ñìí7ßÌÖydõjÎ8ùdö,XÀîÝ»!—£Ãóøáp÷g?˹W_ÍCþ0ý×åŒ;àw¿ãè%—pð?`ùÀ«òyþ¹¿Ÿ»÷îå•?ü!KššXîºüÏ·½ Û¶yñc#oÛÙ,žçñ›ßü}”®b1ô0 ‚P<4 òýý¼üÊ+¹$Ÿ˯¸¢FBÁ1)Fßãû<ÊË(éÞFƒÄ ¯³1>?މÊàSŸúTåî»ïžêf Iüÿl6[±m;þnÛvÍwÃ0âïétº’Íf+@Å0Œ Pâåù|¾bYVÅ0ŒJ>ŸëHþ¿R©T€JWWWÃö4¢X,Ö|On›Ífã¶‹ÅJOOO%N×l›<žþþþšý¥ÓéŠišqY:®¤R©ší{zzjÖ/—Ëñ¾“û*—Ë•9r‰W*•ðw,—ËñoÐÛÛ;äº×\sÍT7wJïãÎçó5÷—eY˲âk¶¿¿ØßA™ÊårÅ0ŒJ*•ŠûEe0wß}wåSŸúÔT7cÒ™îcE™læê=1WÇBŠ2sñž˜«c!EйzOLÕX¨X,Æö¼r¹\1M³bYÖ ›œeY`m¡\.Ç6Ãl6;êý±]­§§§ÄïΆaTÒétl[ÛžeYÛ¶+†aÄ6§b±Xéïï혦iÖ´C앲<ŸÏÇûêíí¿‹M±··7¶ïÉö–eUŠÅb­OÞñå|ɶÒV±õööVŠÅbÜæžžžAöÑFd³Ù†¶©£Þ†*äóùJÍSö)ç¬þw’s$¿G*•ª˜¦Y³N¼ÏÑ´_ÎGÒ~<–eÕØY+•¹9&˜èã®·ïG¹R©P©TVïÚU±m»rÉ;ßY¡R©Ý3˜fø½¿¿Bdû¶m»B¥RYõÝïVòù|eãÖ­aßøF¼\ö/×Ô~þóøM§Ó•áÔ€ÞÞÞA}ÓXúá>°žT*UÉç󯹹ò÷½/y2+•b±R,Ãû*Ÿ}ï{ãöüdÑ¢ÊÞ÷¾7\7Ÿ¯<¸jUåïßñŽJ*—´´T~y≕Ÿ^rI¥bš•JWWåõ¯}åî+¯¬T òô¹çVòP9¸|yx/BåÈ{ß[ùé%—T¾»jU¥×¶«ºH*U©DçÎ0Œð>êí­T²Ù𯷷Réé©Túû+===ƒî³AÔë1ã`O–çD#ºººâ>´ã1&PÇ)F\ÝevI#GQ±%?¡çyq<óžžž8Ü€„ HzBÊL–ä,…z ú£#yhÕÏxHÎŒ±,‹ ÈçóñzÉp¥z¨}‰gfr–Nrýú}Ëì¡>æó\ò6K†˜TÊÄAMXb™í—ü>—®Áé‚x#wžUEQEQEQE9$\§Ø\×ÃþåóùA6ñX/x=A@&“‰½÷Ä£Ï0ŒØSNBZ–EWWWü=•J5´ù%M±ë‰ç£„UOÄd¶zûŸØ3“QRWÒÃO¼¯2™LMxSñ /ÌdÔ²¡ãiô;@h×lä!(v dÔ8‰(—ôäL’Lc%ç¬ñÚìè許?ôçóùQE|K¦ÎR¦ÇqÙç!´í¯ûØÇjW–ûÄ0Xý䓼îuàº477óÚ×¾>ô!¾tÕUœ;oŇæÞ={ þ%·f:æt™ Œõ}ÛhŽ{2‘kAÂ=wuuÅ!¼Uxœ…$oh™ñ й+Êsr¹x&ôòâ„Á…Ba7àPŒg4˲†,†ãÌêu¨Ƴ•ä¬*ejP;EQEQEQEQ!9 %Bh===ÇTŸD:‹ –ÏçikkÖ0i_«·5 'Ö3v*±‹Ö3Y“ŽÅP?–mÙ”TœÈu}ûCÁ¹çòøÊ•á¹¶#ÏÝßøF67³Ç÷yÕáÃ<@tVT‡\s«ydÐ~éãîÀ’¼G=/"܆a°®¿ŸÛÞñ>üÙÏò{îáªçžãµW]E±Xäß>ÿy–/gÛ“OrI©DÛ9ç°ú#áåŸý,»-â%?ÿ9GÓiÎþû¿çÁE‹øÈsÏñŠÅ‹áé§C0¸ý”SØ|º¯‹î¿òyÈd « ‚€» ~ÿûß³`Á>tà µ“=}«a8ŽC¡öaYqͺƒš¨Kä˜ÉårqÛ3™Lììv<Îh8aª|®!á ù¡ƒ  T*Ŷx,ÊàÁu]Ç!•JaYVg`òáš\*LÉ$ÒSA½Ç£zþ)IýõVXQEQEQEQ”¹M±áWŒÚãi;‹íË4Mzzzèéé™p›ÙDÔ/‚­¢Ì6DÜ»hÏ-^/kÚµ‹E‹a§Ÿ>çœ|2xï:óÌjQ¸Ö˜„Î`YV,46 ½y\ÞÀAz9V$þO?ð@XæyáŸïÇÜy'mmü—¼\—_~ó›,úßÿ›]~9‹÷íã¯7nä…ßü†wüãàû<ÿçÎâ¯ùÿú¯¼rãFæŸz*§|øÃ¤L“?\½38ù/þÊåPèô<^vÖYÜ|Úi|ë[ß ÛjÛáŸi†"$pÉ%—Ôœ;±Ž„;®O·À4w>‘ë¡T*Åiñ\××&Ú†=m„Ç®»î:^ûÚ×röÙg³iÓ&vîÜ9h½ÎÎÎxk¯½–¾¾¾©nú˜Ðª‚ïû¸®‡G•øã"4JØÌL&S38IT”súYO*Í,æJ? (Êðh_ ( Œ®/Ð~@Qf7:&Pfv_ày…B!þ›Þk3ÙV6T8Jeö3“ûÃ+WrX<GàÈ‘#µƒ–Eó¼y,Z´Û¶ñxåÁƒ´,YRxèûñ½mÛv,þÕ{6'@6Âó<þåškj ë=“޾/ÏårÜò‘ð}¨*::ÿý¿³û+_á¿¶ogéü/Üsø>›ZZxÃ?üoÚ¿Ÿ n½Ã0Ø÷¹Ïá{¯¸‚—¼ñJ…Â`´ßï»úP¸éß,+öýúyçUÛgšPçé÷þ÷¿Ÿ®®®Á}Kä–J¥ð<Çqpgܯ‰B4¤žžžšü·ÉœµÉ´;;;éîîæŸø7ÝtMMM\sÍ55Cgg'Û¶mcË–-ÜtÓMôõõqíµ×NuÓÇD}øOÊJ¥©TŠT*…aq¨TÉßèû~ìnŸ ­ÚˆñŽÿ>S¨¿Y¼FîÎÊ´f&ô¹\Žöövr¹ÜTŸ.E™µÌ„¾@Q”‰g¤¾@ûE™ýè˜@Q˜¹}A&“¡­­B¡@>Ÿ#˜"0Ì5Û— s—™Úì¹ürö\~ù°ëȽ¼oß>q+Ê•¸bÏú×­ã†×½°]ï{–e‘ÏçÃþ ò¨®}ùËãûE„GmÛµð¯~øáÚÂúôf ÂCîþè8ëe/«z=Ú6ý==Ü×ÙÉ«~˜W>ú(ðè '°â¶Û¸àÖ[YôÝïÆûÙð¦7ñ‹¥Kؽ›+V„•[V5¬i*U“Âc24´aT=ë&_ )À%¶•‹–Ëåâh‹PÕ†Óýò—¹ï¾ûª®[ãáxÇÇ?Î7ß\]åtô}Ÿ¶¶6–-[Æó¿ùMußgõ‹/rúùçóÊGàÐüù9r„e• {Î=—óðƒj~E߇|ž¾õ­œ·xqUl4 >UÄÀ‘<ÊC/) d2™åñØñvœ uÚõ Ô|ß¹s'}}}¬_¿>.kiiaÍš5ìØ±cª›;j$§£ü¨…dGqé-¦iÎIáQ0µÉ™ÊÌd:ö~"tÌM‘_Q&›éØ(Š2ù$ûíen¢cEQ`z÷’N©X,Òßß?g£’)ÊD3ûAm=óL/\8¨Üó<|ßç™+b¡­ïÔSY­{âÛގÊ={âm†³tç€cÛvq1®kvó³Î:‹¶yój ƒß÷q‡ÓN; ¿nÄîOÄ0 ººº8zÉ%œ·o_ÕK2“àü7½‰æÀ¶ù?õW¼ç;ß`Õƒ†çÂ4ÃÏH°,‹,ú³?k,.JÛ@L«éÛʹ-år9Γ8“Iz?N4'MõÁ ×_= ÐÒÒ¶mÛX³f —]v¨é<–.]Ú0žót"yS'=}ßÇ0Œ8”ªüð¶mºñÇ2H‘¼s•L&ƒïû‹Eg3¡\¬cy8)Š26fB_ (ÊÄ3\_ Æíev£cEQ`fõžçaÛö¤ærÔh_Ê\`&õõ<õÔS=ztø• ƒëx€ßŸqçÜ{//45qþ /T“†Ù<9±år™R©„mÛ±>aÛvì7·ß~;ND¹=ÏÃó<ÚÓ^÷ºxñ­'žÈg¿ö5þõ‹_ää·¿3o¹…{‡ kÖмv-~6˹+V@¡og¥Óºì2–@(8ZVèí˜Ô8ÆQôsgLýt{{{œOûÜÑ1m<×®] „nÓŽãÐÝÝÍúõëijj:îº÷ïßOgg'“~\ÉЪI¡Â÷ýØ#OÄG!{ˆs?Ž–¹|ñÛ¶MqÒT¥–mÛ¶±iÓ&vïÞ=ÕMiÈDö»wïfÓ¦Ml۶혶—{x:$ƒW”ãaÓ¦Mtvv²ÿþ©nJC&cL°iÓ¦©>LE™RvîÜɦM›øÞ÷¾7ÕM’‰ì öíÛ÷…Š2—‘gâ¾}û¦º) ™è÷ƒï}ï{lÚ´iÊ ’Š2ÕèûÁø½xž7é“àç²P?Ôfx|6ÃáNt ‚,‹eò'ܾjG?ÿy>~òÉÌ?tˆ¼ë]±r¸;}4ýN\ÏúŒœw+Ûéya>ÇHëð<§Î:‹‚çÅbæGwíâ£üǘAÀºÍ›øç¥KùÈ)§ðÿìÏøÙóâòËC/ÅrÊe<ÏÃ4M–¼óáN #\帜ÄÆ;ÚsQ©T0MsN89‰Žv¼c‚iáñØ××Ç5×\ÃÆÙ²e C®¹æZZZظqãqÕ¿|ùr®¼òÊA3&Qÿƒ ÀqLÓÄ4Íø{œvæÂ=ž$cU+µHœóéhpŸè~àôÓO禛n:æíëì*ÊL妛n¢»»»&Âta6 e:±fÍnºé¦i+¼Ô´´´Wý§vÚq e¶ ÷×\}?xûÛß×­(s}?¿÷Ïót²²2#Q›áñÙ À¿âì\¸%?û©l|Ÿ—8;Ö˜ /<Ž%ZâšE‹€jØM\wÈü‡¯ÿêWéNxôQ(•Âõ …Xçø<ðÁO|‚7|÷»tuutt°{ùrNoiÏã²?ýSŒ~µÿò/Ìkn®î7‘~®ÆH¼7³ÙZÇq‹„ÒT*5j;ï¼yó°,kNh[¶l—1Á´ðxܾ};5~q•®OþÚh&âš5k¦ú†D<ÇÁqœØí9“É`F,’i¼÷ñÁ²¬]Ä•éÉLè\×­Ià.³yE?fB_ (ÊÄ3Ú¾@ûE™½è˜@Q˜Y}¤URŸ¢Œ/3©8&L“çÿàxö”Sx˲ea™ï³hïÞê* ju,i×N»óN áì$öÍÈ“ÂÔq¸.År™VÓäwßúV¸Ü¶¡Ráæ={¸á¶Û0ƒ€=;v°ðƹg×.ÚÛÛyÅyçXVJ5—£T*Q(8wýzÎ9çœAíÉçóµí—ÿOP*¹ ÊI™L}7åryNˆŽãÉ´Gã-3ê“Ávww÷Œç‰D¼}ß'N“N§cG™UjU9vTtœ¹Ì„~ÀuÝøÂK<ŒE?fB_ (ÊÄ3R_ ý€¢Ì~tL ( ̬¾ P(J¥Æ$“µE™jfR?0J€ U‡Ódßyçðº„0ײdIÍv㥜zÿýµ$ÄÆé8 üèGÜyóÍ<}à d2ººº8ëw¿ƒÈÃu]V=ô«ž}–|:Í%?ûÏžr fPN¥8ç/þ‚ó·l s4Šv]]]ÕÜ“L½ãˆØtK¥Ò¨= Q>JíwGÏ´%óu×]—uwwóýï¿&ÔÁÆÙ¶mlݺ•¦¦¦8‰ìtÆqœøÂ”O ½ (U¦{?àG‰“õ¾U”‰eº÷Š¢L£é ´P”ÙŽ Eéß8ŽC´··ã8Nm¸À F”¹ÂtïF¤.W¡C(/·) A{"† IˆŽ®†GÖ?ó vìà²%KH¿ó4¹.7<ò ››Ù}æ™Ü°j L3ô–Ìf™ÿý4-YR ‘jšµûš"ÑÂI"®ëÆ!±«§túŒïûcÊ ©£ðØ××ÇÎ;ijj·äË7nä²Ë.‹Ý¡[ZZ¹A755q뭷Ɖ-×®];õ¡bžD e¶mׄh´m[ÕqEiÀtí<Ï#—Ë…a¨Mجeü™®}¢(“ËH}öŠ2ûÑ1¢(0}û ½—ËåH§ÓS":ªÐ©Ì¦k?p,xÀ«DT4 ð}lÓ¬ñhlzáVìÙ?ž;½F»')σR‰C^ÈsëÖÑ,}IäyëÀYà’ŸýŒï8À‚+èhkã\à–+X°`A(šú>—|âaI¡q =ëq‡l6‹ã8xž7ȱd$LÓ$“Éh$¼10¬ðØÙÙÉöíÛ¹ôÒKãä­Û¶m«qk^³f ŸøÄ'Æ%Iëh…Ìñ;Ç ¹p¡ŽQðMWúîl6;¦ #¶mÇ/•ÑÑPx”XÉ7n¬)ß¹s'kÖ¬©‰Ÿ|饗¡7ä\Ä÷ýB¼Ç¡T*Ådìά(ÊŒAf1ú¾¯¹EQEQEQEd#˜*oG;ezãºnUô‹¸÷Þ{kWŠú’ÇNµ†d¸Ó Àüö·l‹çqøU¯â‘Õ«yÃWpÞ׿ί~ücnܹ“wÿÅ_„ý‹eAœ#ò?úÑjXÕÔÿ¤ÓéØ)̶í¸ïKt»F¿¥2< …GIÀZŸ|µ»»{ÈÉsYxlô½T*‘N§UpT”J2W«z<*Š¢(Š¢(Š¢(Š¡½`:¤c™mPeh‚ ˆÃ—ì]´ˆ3ÏdÕC…©X«n¿}|w¥ŽÀóèÞxc(<–J¡G¤ëâ q?9|€·¾ÿýqÚ©$†a`F8ábö;õžŠâý8–Tx©TŠb±8Õ‡2£h(<Џ800—mß¾€µk×Ö¬+‚ãš5k¦úX¦ñpL~Z–*Š23‘É2™ þ~Öû[QEQEQEQæ¾ï µ:•¨ø¨(Óß÷ <ù$/‰r'6ýã?‚ã°HB˜#ííí5Dßýò—8øË_†å¹\(<‡.Ïã_Lßüù@(°5òâŽEºcÍ;9…Ô÷“ÒÅ[½T*Õ„ÍUF¦¡ð(âbòdJ~G ­Z_^/HÎ䦖O×uk\wE™™A@Cz;ÊlEQEQEQEQæmmmX–5-„GÛ¶Çä±£(Ê4À08;ùÎ<“%?ûÙ8T™°OJÇ àׯ~5«žx€æßþ6A}ŸÏÜvÏœ{.¯~øa.ùüçYøªWñ»“N2z£eY³ª¯9–cI§Ó±§ä¨ñ` ë×iÇŒ¤sÖ¯_bZÑPxljjbóæÍlݺ• 6°aú»»Ù¼ys¼ÎÎ;¹îºëغu+›7o–u."^7XE E™¹ˆ§£ëºC¾PL‡ EQEQEQEQ&×u ‚€r¹<-l~¶m«Óƒ¢Ì víÚ¶m±@øš—¼dìöE×­ùzôûßç…{±,p]ž|äæßq;,à÷K–Äù÷.ZÄŽsÏå+»w3?Šf¹ï⋇ô žR狱wãÁâã8 ÃЋSW_PŒŠà³}ý¹È$Ê £nû)æ„¡lÙ²…믿ž¥K—²téR6oÞÌ–-[âålÛ¶mPù\C<}ß'—Ëa†>øe5t‰¢(Š¢(Š¢(Š¢Ìm\×U{Ÿ¢(£Fœ”šï½—æ{ï Ùš&ï>í´X$<¦0« ,>~òÉœõ«_…9 ŠE]x!‡æéÓNã7o|#¾eÅaR/¾øb:O<‘þÒ—€Ð±bÃÿ÷ÿÓAqý‘„²Âø4kÔm©ß_$¦R)®\ue­b‰á¿ûuÇçÕ-wëΗ›XîGë»Õ6Ж¨Ï‹þ ‰ïÚuô{xÑ6‰c/NnáÆÙ¸qcÃe[¶l™ÓyëUþR©„çy”ËeàØ\vE™>ˆðèyžÞÏŠ¢(Š¢(Š¢(Š2Ç™N¹E™¾är9<Ï –“v55Ñ´kÆ™gдk×±íÀ¯*D‡î¿ŸÃ‡ó«_ýŠK~8\fY,)•X·l>pÏùçp‘m“Ëf1 ÿ®»8墋ª9(‡óhtÑιðÅ®Ô0˓ݨK(˜YìŸÜGô‰zš’Ña3Ñ2+Ú¶ (²ýÕð¨FôÿP ÅYë=Vø=X_Ľ,¡ðèÕ-ñш–g …ÁTT·8v9oí€ýÑ1˜Q]¹°=Q]…DýåhyŠZïÉú±rN“¤—.;釕 GÅ #­ÐÝÝMww7;wî¬)Ÿ«¢#Ôæ¾”ÙNŽñX’“*Š2½I"8ê‹…¢(Š¢(Š¢(Š¢Ì=ÜDHCÏóÔÞ§(Ê1³wÍ^õøãÌŸ?ÿؼ…¨o:òàƒ¼þða.zè¡0|k$J>úÍoòÿ`ßâÅX–;X@hïìéé «õiÉðžõ^{#¶‹Ú܃>µžt¥ºú|†ÏM(AToýöNb²Ü!àJ‰ò¡H¶-E(¾‰× Ã`EñŠ”vÑ:ó¢í%ä©}¡±=ZW„Yù”ó›£*BŠH™O´)M(8Šš!#³Q¹x<ŠÈêGÛȱ—¢vÍ#2KÑzY 7ªCÄÓq2ƒ)<îܹÛ¶Ù´i›6mbÆ \wÝuã³×Ž[GYD 'ev !”%Äj£ ¿ª(Š¢(Š¢(Š¢(³±Jn/E Ïób¡ï”µkãòÃ+W²à™g8õÐ!ΨTH¥R£ïW"G “ç ­gG²ƒåh3ñÙÕ™ŠþòTÅÇÞè»xŽæ£Ï®h[9æžh¥¨­…Ä>ärËFFT·I,B®K­ã´ÇNÃ?˜!…ÇÎÎN<ÈæÍ›¹é¦›¸ôÒKÙ¶mǵÃÙ€ :Ç©I®ªB„¢Ìä¡?Ô„‚éH^QEQEQEQ”‰CÂ%jEQÆ‚§^xaMùÅ‹0ÿÐ!–>ù$étzdáQ¼% £eÅ9"úõ¯ó_'þ»¾ðèꢿ¿|Ÿù}}<ðØc”J¥0´ªïãº.étºÖÖ™ÍÖî«ÞcQÂrEP¼DxËEË< —â‰(&UïB‡P,Dÿ—§²mV´lb'Ú¿.¡pçEË%¼¨Ôg ÙD;EÜK'ÊZ Å;YžŠ¶ÍEm—°§"–©ÍߘN´YÖÏGÛ@U(Lš ‡’™ŒhY±n}»Áz"vÊñeþ0û¾ö gß6ÇCÃ`­}}}twwsýõ×Ç9ׯ_φ …\kˆèèº.¹\Žl6«Š2Ëû\g2*Š¢(Š¢(Š¢(ÊÜÅu]‚  T*‘­7Ð+Š¢4 Æ£°Žu•Jüÿeýý£«Ðq ŸÅFÄ›W¯æ„S¾²{7ù|€ž~š .ä„SNá¢û¡‡Èf³d2,˪DQïXåø«ùƒs3’(—ðŸâ}(ÉÜ…ñ±DŸ¹Dý]Ñö’óÐMìOÄ:“ªcOTgk´¾}¯>ŵÖè3 ’UÂJ¨R¥\¶ÏGÛHøS9óTÓdˆX“Z!OÄ>¡>ÏâñÊH£™#çB1U~K›Ú¼˜ Øÿ¦ý¸ïÀq5±¡Çc__---5åëׯ?Î323iooTæº.†aÔ :TxT”ÙAñý<”'³iš³úž÷¿ eHþNÉqœWW>–ðùŠ¢(Š¢(Š¢(J­óïû:9YQ”Q!)œ„ù‡Åÿ¿äÕ¯?/¹„zó›WP(Ô~÷ý0´jĹñ<˜7ü²e<2ÿ‹±ýò¤“Nâ‡â¦i’Ïçc£P‹Åá/Æ%ñ„ZÑ,GæTñNBJQ š¦*LJ}vôÿÕœ†’ÏP<ù²T2É?(Þ~P *}BÔJ´+›¨SB¦f£ýŠÐ(ëK(Ó$~Tr5z‰}[ ÖO"í"±ÍTÏ«7o§‡_ýÉ7?ÉýÞ\»<鸶žˆ²ëºØ¶]f5é騃E™=È …mÛ5É—“¤Óé1Ö:½pì…/“”$|{×ë”v¢>?Èr¨NXòß=ª‰$rArr”„ROQÈTJÔ%áàel3I¸QTÉïl7XWÖ¯Ÿ<§~´­™X_òNË$,Éñ,aá-ªd\’ü,ª“º’çËLì/),&Ë­è¼Öϵ3gáÂ1þŠ¢(Š¢(Š¢(sĨ)–E-’žíäW½Šýý<±kýýý‘†ðž+†ŽtYï1¡Ð(Ùl(@ú>Ùl£`pw÷Ýx–Ç¢E‹xá%/a”[Ò2,h«×¢··w䆋IB’ŠØ×NUd”¼ŒâA˜¢jƒªH(¾\]„¡N³„ÞŠ¡ØJ­a®+ñiæ^‘üê½öÊuß“ËSQ½bx´ ‰ÃÕ—DDÈ$úHG`(Ñ!éeD3E™xž{3Ï”{[˜„„Y/Qõ²—IF~ƒuE4ô£í’eIaRò? B]òg¢mMªÑ ê÷gSÍã µbÑ~3ußEœô©Žsd”DvH×Õe$¶•íR.b_Šjä£îs(áQDVúŒÄ§Lð’I^2VKEeEªÄÚËDt”öDǘO´©D8¶’±“´±µ¥˜X&ÇÙüW¿š5'Ä–Q\7Š¢(Š¢(Š¢(s ß÷1 ÏóÔá@Q”!ñ}?Ö |ßËÂ2 ݸ‘ÇÎ9‡¿üå/ù¿+VpðèÑx›{Ï« ©JT/Ž®ËÖV–™&{é¥|Ÿ¡FQø“?¡ô¹ÏÕz6Ž6`[rV{‰jþD wšœm/¡U}BaŠZƒ˜¤ÌðC•GU ¬ Ñ1ÅJnD!Ëñy JxÒ.ª¢éX̾ú*<Ž‘¤«tR˜)â„¢(ÃAÍĂɦÞ1é•'Qdè`F7H {"‰¨&‚¤ˆv╘œ¬$B›<KÑŸˆ€"܉X&c†6ª Ar6›‰õÒTC¦KØuÉqœ›Øªã9v7Ú¶H5T½“I’ǵáá“ã¢áò7‹Wdr"Uý¸ª~œ“ ë. òÿüÛ¥Þ~ç…ùPEQEQEQªxžG:¦P(¨ÝOQ”!qÏó(—Ë¡ðhô¯[ÇSgÅçÏç\À¯>ùINܱF3‰Áój×óü0G™€ÚEQEQEQf>ÉhH“m#PeæQ*…–²ïy/9õTŽ.YÛ€–õ÷ó†—¿|ô•¹nU| 0ÍðÏóàÅNÜÅò 8Óu—goyÿÏ}LÓ¤hkgð‹ArƾöÒT ¦,O5P†ªg¢x$E»R¢Í©ºïÒ+±ýXºÒ‰ö0ÌÊМШ°¥¥…Í›7éo<ؾ};¶msöÙgcÛ6Û·o´Ngg'¯}ík9ûì³¹öÚkéëë›Ð$£|zžÏ˜*(E™ÍLu? ù\' ‰2à ‹>Õp›r3ý?K8!É¥Õ@BŠæ Ljµ 'úKQ!|v÷Љ= ڕ̽\‰Ö©ÔòT½ëÉSõÚëë™É`1óX©9ë—Ç>f"ðÚƒ§ºÃ2Õ}¢(Óƒ‘úíeö£cEQ`òû™”œJ…ojUQ¦žé<&ð<ÏóÈd2,\¸CgŸÍ3çžkoù|ž|~”JW`À£„â£`YÕЫO@çîæÝ&Q<´î¶aóΟ½“+]Qͱµáº\BƒM5W‘휨ÌK¬/b¤`'þ$<—Y·þp†6Í‹8‡hèñØÒÒ–-“›õiûöí\{íµlÙ²…5kÖÄß]×¥¥¥;ŽmÛ¶±eËZZZèììäÚk¯åÖ[oðöù¾‹étÇq&õü(Ê\`ªû pgôc ™ªáL“¡Ò%´gŠP€+Eßå5Gr3vPÍÏ\ÿ\·€þºïCÑH´}ø‰ xüU(3˜©î E™ŒÔh? (³(ŠSÓxž;X–¥¡VeŠ™îc‚ âÏ¥@`šáu¶'M8èÁêè{¶ŸqàÙR)*×AÞ6éïêç· [9mé |þÞ/’Ý•å‰ÕO„Ûøuuz„G ±&Jñj€ªÁ2éµPïÁ˜ôZ´ìg8cb£¼EʬeÔ9»»»Ù¹s'kÖ¬aýúõãÚÇqj¼'ׯ_ÏÁƒéîîfãÆ@ØÁlܸ1þ~ã7Ƴ.½ôÒ ?YÉ8É:ÓIQÆŸ©î<ÏÃ0 Òé‰ òÝ}ÊsYÂ¥æ ŸõEªá?å9^ÈY-åºOE™-Lu_ (Êô`¤¾@ûE™ýè˜@Q˜š¾À÷ýØh† Š2ÅÌ„1A¤Óiî9ã î‹ÊFÕs$ê¬JÃ.Üî„^ް³–‚l–yØýÂß’HÓ¿ì9eàJ²\ ÀŠ+BCbªˆ(ù2‰2ƒj¶4a¨3'Z.I“ÁBbR©÷ˆ µzÎpÂp b÷äM›6ÑÙÙIgg'›6mⵯ}- w#úúúعsç 1óÆoŒ;Š;wÒ××W³NKK kÖ¬aÇŽv‚$´‚ü_šÓQQÆ—éи®;¡/’cY˜ö Ž=„Ïí.ªaFõ9¬ÌU¦C_ (ÊÔ3R_ ý€¢Ì~tL ( L]_ “ Ф(ÊÈL÷1A2E›a,¿à` šœë‚Ÿp¼Û„¾ìð`A¤ü È5ûûÿ€¥/¬ŽÅÀ;.¼£šÓ B#¤A(fd_QÃz¨z:¤ŸõÞ #I *‘(C0¤ÇãÀÀ×\s ;wîdãÆ¬_¿ž¦¦¦xYww7[·n¥»»››o¾9^v,H¬å––®»î:úúúhiiaãÆ¬Y³€ƒQ.ªúféÒ¥±'æP<÷Üs<øàƒ,]º4®o,ˆØèº®&•Vf4}}}ôõõqèС©nJöÁÄõ‡¢»»›–––8 ÃD“¡šwY" —sPQ&ƒîîn|ðAž{nÊ &kLÐh{E™K °cÇöìÙ3ÕMiÈH}ÁñŽ Ž9Bww÷1¿(ÊlaçÎ»Š¥«—V½ÒT=ÅÔ™¢6'£æ\T±cÇŽq4ôxìëëcÛ¶mlÞ¼yXo€õë׳qãF¶nÝÊ–-[Ž{†`:Žã4C˜GqÛ¶m\ýõÇUïK^òÞö¶·“gƒçyض‡\ÕA‡2“‘ÉãõPž&ª8í´ÓزeË„¶ß%|fg¢O•éÇ–-[èîîžÖâÛt(Êl¢¥¥…-[¶ŒÛ‰b¨¾àxs´,[¶lÂÇŠ2H†'›®LäûÁ\ }¢ ïõï®ëj^GeΡ6Ãc·^¹2ÊņZucÒù>ì6©¿0áF09Åû°„¥Ï¯†=8ðìgžåÉw=ÉŠ÷¬€ïPë^™ÌË(â µ^&ƒ=•9ÏÆiii9î1ACGQöå%d¤†ã2[¸~—^zé Y:¿‰$^Žêí¨(ÏTöÉœ®cEr6ç€Âg|ò¹®(ÊØ˜®cEQ&—‘úíeö£cEQ`rûÏó4¼ª¢LC¦ë˜`Ïå—C” VúŽG‡Ð`XØ!ä;pXmi°Òœ°÷›á*ß.ŒÔh? (³(ŠSÓA ¶@E™FÌÄ1AŠ0Ú)†7mäëP*…âc¿ ûm(»p“ ‘‘€º6´<þN|ç·§—{[ïeÙËÂåõBâPaפ>«A¹¢L …G¹QGÓ¸þåÿXhjjbýúõtvv20JüÝÝÝlß¾½&ŒÒÆÙ¶m[¼ÎÖ­[ijjâ²Ë.›“#aVt(ÊÄ1]ú±z6{„áU=ÂIE)ªÏrùSeôL—¾@Q”©e4}öŠ2»Ñ1¢(05}…KTez0Ƨ¬Z…a5)c† °æû@/2á!ypZ>!ZÜÁý˜w€ÕKWó²—½¬ºýX…D ͦL …G™E°mÛ¶+ud›cEb1¿öµ¯eÆ lÚ´‰Í›7׸PKœå 6°aÃÇ—Ü’Cáû~بƒE™X¦º‚±gTÎí„Ïõ"‰ÙLŠ¢3SÝ(Š2=©/Ð~@Qf?:&P&¿/ÐP«Š2ý˜Nc‚€Z-qï‘#œìC‹ ï0! §ÿàtÜ·¸xžÇüÝóYm¯®za÷Lõ‘+Êè8i´+Îf¡±×u±m[Š2‡)¿cRxÌ3¶¼ÍŠ¢(Š¢(Š¢(Š¢L|ßWGEQÆFÂa) äBb:ú|­°ß è=á­ð <ÝÿÝ„ü‰ §ŸÎ!ã†apþÎÂÔPZ™Iœp¼tvvröÙgOõqŒ+ŽãŒ(B(Š2ûîåÂ' ¯êŠŽ:-AQ”™ÀXÆ3®ëŽz]EQEQE™­¨q_Q”c!~£ö ˆòyȃ¯ø¡ÇcrM߇}ðÔwŸ‚w§ÂÐj6”ûË r¹/®~û%í›”™Äq ³ÏóÔãQQæÃÝóbº7PÑQQ”ñ£T*5,J”Ô£ÁuÝ!ëj}E9V’ýS©T"—ËMu“Ž›‘BñçöA÷þEQ”ãGE ò-’`4è†Zý0/ê[ä•û.C°f%¾¥Sphþ!‚  ··7v’Ð4pÊLcÔ¡Vç*<*ÊÜb¸— ±š&/(Š¢Œ®ë’J¥•;Ž3èÅ"Ç!ŸÏºîUO<1¨Üó<‡…BX^*A:þi¨.eáû>Žã`Y¦iÒÑÑA:Žï-¹ƒ  T*aš&¾ïÇÛÙ¶añ¤‡ â\Y†aÙl– ( A/“YÜ®ëÆå–eáû~\&û ‚Û¶Éf³q{=Ï£T*ÅÿO§Óq{†š!.4Ç!Ncš&étÃ0Èd2qy6›Å0Œšñ¢Ôéy…B!.ƒp2›”uuuÅåžça†aÄÂl*•ŠÏ‡iš5}¼a¸®ïËqœx©Óu]r¹–eÅý·C©Tš¸~QQe£~EQÆŠIh;ŒGœ.UÏ…e@ů†^ueüÔ,ŽÌ{ ×uI§Óø¶Ï<†Žå²Ù, ý’2óPá±y™ ‚`Z¸/{Ñß±¾.z„ZS$Š2½©¿ç“c‰ðÊ’ˆŠ (Šrœˆ½X,A,Bº®Ûp2„çy ËÅ/¦Ìˆ¼è–[í/—£dYüÝ…²ä¿ý·P þøä“ùÞš5¼ü¢‹àðaÜT*|ÉÉåB!-ê+}ßÓX)“ÉÐÓÓsÌçK€FLˆð¡àèyÕc/Ãe…BXž(—Ãóhša¹e…Ÿ¦Š·AA@ ÒfÛ¶Áqèì¤éç??>‘²‘8Z<®þAØ.}yÑ”J¥XX ‚€L&‹S"ðIÞzÍÄ Q?é!—ËÕˆ‰"pÙ¶]ã½(ûbÑQÄÁ®®®¸ÿêéé¡T*Q*•â~Mrf‰ 'm“Yâò)í-•Jø¾‹ŒRÞÕÕ…a8ŽC{{;¦iÆ‚c¹\®9?r.õ"ÒÙ¶MWWžçá8N|ìÅb‘R©Dkk+¦i†aÄÞÙl6Þ·´YŽQú£¶¶6òù|œÎC„Ǥéû~|®“žêr¾¥ßHn“ü-d_r È9–óàyÙl66\Õ3ozEQ”ÙŽëºCö—Š¢(I<Ïã±§Ÿ®)3 ÌÑD>ðjž‹ÞMÀ®Àc9XÀËM~ÿ«2¾¨FÁIeŠ2SQᱎdx›é <:DÖ)NªÈŠ%S$Š2ýIæxÑ? ¼ŸRTÅGEQ”ñÀó¼ø¥ÂuÝØ³HŒùIc3P#HŠ\–‹AÛó<Êå2F°bÏšššjwZ(ðÖþ3\Ç0øòòå¼ýÝï¦ïì³Ùô?ÿ'¦çáû>…DZ,‹´ãðO÷ÜCð7CÊ÷ÁqB? ½½®®.,Üê ‚XH“¶ 'V·Ìqœ†ž;V•šs–Øb'a¹ï‡Â[©Šˆ†ŠpI#“ŽAÀÏ.¹„ó^÷:˲¨ß[¼˜·ç;ñ¾Û&gÛ¤R)ì:OÈÃ?ù wþâ\òë_Sìê"—ËÑÛÛ‹™ÉР4µµ…mq3ÚÓ ÅB߇tšÀ¶ÃÉ2®Ë ý(Ï?ÿ< žy&<†žžÆ¿@[[ø½¼îþÑxaŒu•Æø¾{ŠÐeYV,t™¦‹L¶mÇ^‡Ša–eÑÑÑQã‰'uÕ{Z– „Åb‘T*…çyd2ŠÅb,p%EFÙ¾ž¤˜iYVì½'Û‹‡`#Di²\ŽµÑ¾ŠÅbÜgŠŸì3‡3Ô¸®K&“¡\.Çu§R©0ŸÏcF,Ô&= ¥mâmÙÕÕ×-ýº‡’¶mS.—ã¾0•J Ê/^(j<4Ç!•JÅçAú@ù½ëÏc1ê?Dà ‚€öövÒé4…B×uãß[<13™ ¥R‰·¾õ­Sv½+Š¢L7¦ƒ=PQ”é‹LÙ ‚€ÿ÷ÛßUÛ» sÀ ¢Ðª\<œƒ'Ó°Â„Ó 8Û„Àâû§|/îw‚ ˆÇ|Q™É¨ðØ1øM£ÅÓj,x@GÝ÷ÔëP&ž÷ûQ¬kpl"t’Çî=;Û©è ÿ&á9S´ÌSe¼ïå,˪†8¤*4Šá~߯ï …žçñêßÿžOžp©\Çá«WÓÖÖz=Õú>Ï}îsܸp!Ù}€r]þøÆCx"d kš8žÇ›ß÷>îûò—Éd2ÜyòÉ|úûßg¾çqo{;¾ïóþ×ÿâ[÷ßÏî|€/¾ðBŽÐuCq«µz{!v1*Fð<ŽŽ‚  ¿¿?.“°²Ò¦Fc³ïÜp¿ûÕ¯p÷ì =ºr9lË ECÈEÒ¨Rho‡ `ÏŠt©È“ó™gžaQ>Ï“/¼Àò¿ùr¹ŽãÍfI¥R¼®µ•âŸþ)iª‚±™Jqyk+©T ?Å»ÊqœPЈ<“®Y¼˜×Ý}7ç\~9…'žÀ²,ÚÛÛ1€¦%Kø²ibf³±€zæòå,ùÒ—xå£rß°úÿe–E&“Áu]n¸î:~ü ,yÉKøað¯y ¿ÎdxÇë_OºP`Ñãׯ~¹ *"Zd_x{իWOõí0'‘ßAúÊDÐJ†Ó”ð¡­­­5‡Riš±à(Èýäû>¹\Žl6{Ã¥R)ljû“l6[âÓ²¬e(“û Éí‡ÕÛ(u’¤h8lÛ¦···á²FžÓ¶mjw*•j¸_#áÙ =œ Zß?ʶõF§¡BÇÖŸ€žžžX´”ß<f³Y¾öµ¯é*Š¢ÌFêŸ±Š¢(·¥ŸìÜÉwÜþð`{¡Kèùh®§Û°­^Ÿ-8¸Ú›Ûy]æuñ„· â eŠ2Si(T¯‘¤8DûáZBîÊqüáË^6Õ§Z’¼ç%‚ÏàûxBH^prÓË÷FÈóþÚ†¿òá,6˜Õ¤_êvCã³Î”R”i…i"ýi.Hžð\l?ŸÃ&ærXå29ånÛ±ƒ¿xûÛùÞW¾BÐÙ „âƒI/±dÈɤ§X.—ömŠÅ"¹\.^/JAN‹ ÿ’3N ×ui/• ½=ö–J æ /à‹X==±hð‘ë¯'ÿéO“N§iooç§ûöÅ×Ò»/fQ¡çèÌår ìÈS<Ä<ÏãG?úW_}õTß³ õ™Ëåâ—ù|žL&ÿžI/fÓ4)—Ë ßEr¹\Z4•J*¼°iš5y"fI˜ç¶¶6 )7‹‘wÛúü‘õžûöí›ê¦*Š¢L9Bs+Š¢ ů/æÐ¡C4ß{/¬[Wkg6ItópVd›;Òïï‚>Ö€·<΃Þ(*†¢ÌD K—.eýúõSݶ)!™[äx±¨¢DP2Å! ýœ¢ªØ„‚Gh§6<´lc7¨ß  D¿(DÛgˆè†hMEûéåØBµúѾG;?C†wõgÞM‹ƒˆzfâOÁúct¢¶È9}'ùûH’ãW4úüĹ·¨zÌ»uˤMò[ØÑytûLEû)DçYD̤¾h‡ývÒÞd¾Áäù)Då¹h[+:÷~b]hžRáqõyäþ”k`ÌTÀd™ÜôQj°øÇ숖• $/”Ë\8Á€`_ ¾ oh€Åð¼ ?ˆd蓳á`ÆŒö•É„a%„t6[5ö{Ñ?–®ó þ2 ÿÇ Û‘ 7ô’Ùü¦Y½à4y¬¢4d¤¼‡âYÄá}ßÏÃŽD£PÀ¬ À%Û®ùéOùØ‹/òîÓN£ù“ŸÄ¶íÐã%•Âq]òår<É ŸÏÇ/-­¥å  äû¸‘Ñù-oxC×}6ò²[¶nV”gLBŠ ‘ÏçÃú\+·~òÿ/¯/•øþ%—àþë¿Æ^˜§ÿùŸÓöÉOòË—ó;¢Ÿ÷¿ûÝÜûÿþ/þêWÜuá…üÛ÷¿ã8|û䓹ò”SØqÖYü®§‡ço»-öŒüð-·°â™gxñèQžw™L† øÒ²e´8ÀéMM<ºiöãó¾Õ«é:é$>ò œÎ9œyß}5Âã¯{ßÿýï)¶·Ç¡$ÛÚÚbQ¦££#ö J¥RX‘àêy©Tж¶6 …Bž°½½|>ßÐó(ŸÏÓÑчš¯²b±‹P ‹(¡4mÛŽ½’$¢„l¡0ù"*Ÿ"*‰ðxwg'' ÕÚßã8qXÊúëqÑ¢Eœ}öÙS}ëÌ:J¥®ëÆB´„M¥R±ìºnn7u$D8¯|¦†aÐÓÓ£Æ9ȸæÄUE™E¨·£¢(ÇJ͈:Eh¬õ mƒûJ¡ Î÷áŸs˜(:D2ňŽÕ”™Î°¡V·lÙš5k¦º“ŽacדÄ#ÔÄiI´‰þ/„ˆfI϶UÁ®ý‰À•"Ô) „ú„M¨OÈzeª&Ro­o$Ú‘M|/QÍ Y ŠZº:‡ÚP"¼å½÷’ëf¨Š|PèQÜÒvñò“3/ç¤æ·Il'¨xò‰`RçÉPÍÏ—öŸÖÍ'Ú" „"•?ù Å»QΓü"ö£:Dl”õeNq#ñUô§Lô=ÏðaP帒¿W²Ü‹êJÓX€LàI ©Öä FÒSuX’îÉyª­\É¢ƒªú¢: Ë…ŸXP‰Ê/h'òƒ='7Ã:ËѶ%RÅ8”^hÔŒêË—EùÅÒiØêAÖ­½°ªöøáö/˜ð¸•¯Æk>¿»K¡—@º¥tõ¤œW‚3]¸/€ þ< ÍêjŠž…B8¸J¥FkZŒ³A˜OÎ4Ãm=o°×¦ï‡–®ËCÝÝœ{à “~íT¯/lï8p“BÕ—ßõ.Þ÷Å/ÖÖ/çÀ4çv ‚ðOÊe]ÏcéÂ…,<|xêÎÕ,Eƒ6BÂJ^5ß÷Éf³ìûÜçBxÏ#°m>ö¥/ñîW½Š­?ÿ9_ýЇBÄ À0M^~žñÆÁá÷,«æþðyv”P¼mÛŽß}’WK±Xä“ÍÍüÍýo:ÿü¸îl6ËÚ÷¾7®³\.Çyß^õÕpã\ö­oAäý—Ëå(DŠišôþüçxž‡íºà8œ÷ì³\uô(wýÿç;³£œ‹ÏÙ6ŸÉà]u†a·ípbÄpBð´ã äóyV:\M(ò,Êf9eÍò‰¼™Iþê§?ˆÃ§Ššäﱤ—Y2”b½š„/l„œ+Á4ÍXdl4ƬÏ—|ÑA¨Q¨Çäþ’×CG.džJ|ŸRtê_\¥®3ϯ¹•YACáñàÁƒtwwsðàÁšò³Ï>›Í›7³eË–©n÷„bšæ˜„Gãr„ZB&±LÂ]¦£õº¨Šl"Põ$Öõ5…$âñ–!´×w%–‰'Ÿ„Í3Ø;K¼î2Tû<éÖD •>ЉêÈ&¾—¨ê"ŽÊö¢™˜@kôÿTb]»î|¤ûMŠ~"žŠP+ºEžªÐhFÛ %+‚j!Ñ®äoS¦ªý %ìË“CÌáÄ;i‡Žo´CT7“!SGÃPëõŒr{ øÞâÅ£\{n ú8‘sô'ãƒAzæÄE9yáŠëêPc‹ª ªïƒ[€öHv7Mø‡Þêz»ÊaY½à&m‰Â"J•Ëåè‰ÂðKŒÐËà-6¤íª¬ zÃ6£ãù:Õ™&àá_óP à€_3#â籤õ-&üÊopN¾ªö“ EGÓ ?3Y(æyq鋜ðŸ'ÀŸäàÑBõ¸–™Pè¥ù¯›ÙýþÝœ¾¥)ôàºÏ‡wgàh.Ã;¬?üe~\‚§* –ñsÐô¦-¬ºrUâ÷òªâé#>ük¼)q'Í›ü‚–piþ)Ž|à£9¸/ÑN€µ½p³{®>Ï›8iàÇáÛ†„à@Ö‡..îŽzpR v§ÃÊîsðuXù®Ï°è oˆ7Ýó̲¹\Üþ÷Ï.ZÉ‚›n¨¶O¼š„þþª0麡p“íŠÄêR,¿âàA–ÎÑèI}x&ñ€Ìår±q_‰t:¾P<ý4œsç¥R؆Á+ßúV*ü óßõ.®þË¿dáÊ•±X¥Ã‡Ç”×,“É`YV,z$'ë¦i² x!…|>;hÃà¼o«“Dä¼ê–[8籑ø‰a@*ÅÝ>Èmögôôô z™²ż Êc‰e…÷’aĦmÛµ!! #tÊä|¸®ç•L"ÞŒá¦Fa))ü5¢^ô›®F)˲ð©Nâp£p®CÓÉ'Ÿ<ÕMžH®Rß÷1 #¾Ö2™Ì Ñ8•JQ*•†œ¤ (Š¢L,’ÇO'^(õh¨UEQÆÊÙ^Èôœß¤jø‡Ð¨\vá<òä lj£ìäóyÚÚÚ(•JµïÜŠ2C9éø«˜]Œ6Ì‘ !2e"ƒ„…ª¨F´Ž`bìËRí‹ä{#ï*ËêMò½ª×]#ŠT½ -B;¹ýuQ «ZˆÚ æÑ'˜¦ÉÙüà ˆ^âGÿê¯àÝ>ùLê'ï$Ë9+û€Y×Û¶YýÇLþÝï®]Ù²€×[åHH ÉUš¨Â“P“÷<èèˆ=¿ëCjÏflÛÆ÷}|ßÇqœ!_\-ËbÞ¼ySÝÜYx3÷ööÖ”7:÷©T*g¬(Š2W©·½xž7.òN$Q(’û1Z¡P P(Ä!ï%¬üñP*•â¾}¤ÐûõçA¢I$ÛGå¾'j—R‹z)Š2´¶rAï ÕœYâcN<ßîEaVï ‰I’Nˆ#ñ(Êl@…Ç:|ßÓ C¼ÿª9þ’"[оLõ&“yú *t ÅPCÎz½ žzïÚñ!üõ–}cY¸QtsøVâ%X¡B|ÃJH¸F±äÅ ÂJ=Žã„a!Œ{}ïýô{Üi,Æ«x˜ ®ã8¤Ói\÷|ùSßæ)Ûæ¦ó÷°öÃáA¸®þ¶Û£žÔuÉ9Î]q.~íA~½ï×ìÙ¿‡7õ¿ Ã0¨,ýúN}‚ó¢ßëïþ>qâbæ Až7Ó sÛ•ÚøÍC¿á­¼u"n«9‹x뙦IGG†aP*•Bïº `Ã~À€Ë/Ç¿ðB¾~þ¼÷_ÿ•sßô¦¸ŽÞeËh*u}‚ûÜvòn0Ô”ÿlÉ’8rAïYxêþˆÞÞÞZÃÞQ°æ7hûap o4JY Õ( Iºººh[¸Ï487…hýz#Z#ÑTÖOŽ“LÓŒ#0Œô*fÛv8· Ê{)ÌC’išd2™Øãt¨ãN§ÓÜzë­SÝÜ‹ã8±¡@ò5ކÑ’EQf+AĹ’mÛÆq2™LüN#“™ Ú×J¾c‰¨P(â×ò¬“÷#‘ŠBòTËúÅbÇqâý†‡¿–èf"ž¼w …ëºX–E©TŠ=)s¹\| ÒÞzdiGGG||’kÚuÝøüȤOÛ¶ãè òá˜_…Çñc¬ÎŠ¢ÌmvíÚÅ£ï{WøGª3v¡jo;@¿ ªáU ‚šwÔR©÷ÿõ†e&£Âc†2Îäl`ûv½ç¢OÕéI"&Ïà\c­k¨@bC ­ÆÒ奢z¦bÈ+&œ±xRÎE àñW½jª›1­H†S‘0ÀůPñZÅ-Â(Ÿ)†v’‹ÏuCÑñ(p44ÆúB‡ÌK¼„ŠW„qt'>žO]ð)V¬X‘8H8²æ¹\nØp‚®ëÆ/²" HÞ6ÇqèïïÇ÷ýøEWBÈY– V^½’VŸÀŽÜòù<™L†.ºØú~¬…B!.mÛ¦T*ÑÛÛK{{;Åbß÷ikk£««‹½1ÎÓÖÛÛ$Œ¢ë†â_ÒêžWÿ8ËÃÜ–À)¾—Ã?ï •zÛ¶1M“{¼{(ý´Œóå|ÜÓ4q'aÅ,¿W!òT-—ËtttP,ãßaþ…óÙÿýñ êR©DÚMC®ºæªø<'=c’×ÁÞ›o¦ûßÿÛ …ØP’|&É,j9WfGÍòe'®ãñŸ|™Ž;;8ÿž{°öí&ý֬̆÷|GGGlé]×Ë 'œ0î÷Ó\Fúß÷q]7}J…_[u%=v¼ãaŸNÇQrwÝUSϹe€¿bpq°üe@]mÿ4ÓŒqZÝ{ÀkšêÖ? ÖA n>»:¯‚æÚñƒañúõ㓃ÇQR^/ŸÛ)yª à —Ë‘N§ÉçótttĪœßt: Þ/}ß§T*ņú åð¹çžã ‰´s‘±:#(Š2·9¼r%ïøò°@^X3.ÜëÂ~/L´:a¡¶¬8âYñ3FQf*<6`(£TRdLAͬ{1¦IØU+Z>׿œM•è($óAjdþÆÈ£®Qؼ¹Šx‚AÕ mü$úx9¶†ïLÆDN*ÛŽSõl ‚0§^ (GÒ½K˜ß/^݉gÕŽ†L&çD+‹q=%—”뺤ÓiJ·–Xzd)Ëœe¸®Ë×~ÇW>NéÆR‡`ýÌX™m Äb±¿°ÊŒÛŽŽÊårüòžÏçcî#„® ‹Ï\÷<ÏãüÎ`íEky¯õÞx@%aˆdö±„£A.“ÉÄ™)l$rÉ å1²b÷Žä?ËBÓÛfïw÷ò²ù/‹×Ѳ\.Çae™œt:Ï,®ÿ’yá’çÏ0 x5x÷I—r¹Ì—ßõå†m*”ÓÊ«¯¦øŽwC¿ôZ–Eã Å‚?½ðOyñ”¹âŠ+àË+Yù‡Õ‰FÊ_† ‡€IDAT4M®¾új^úÒ—ŽêúSF‡Ìr——"H›À§nù[~üÆ j78,ÊgÔ{O+ôÓ»Õƒ÷뀿jp9O× Ü{X{,<6ƒ÷hƒúi,ºÍàí{eíºò™4i '$Ž¥\¢× µ~²GóMï¶ÛØóÌ3¤R©Úûi¨‡`#ÅÂ>|ºÌf ¢ö 3àc­218ŽC¡P \.Ç^Íš¯QQ”™Šïûñ„C± 7ʘ8“ÉÄ“×Êår5èX†¨”ËåAåý•J…èÓŒÊR•JŪT*åhY¥R©äl§LÙJ¥bT*•ÞJ¥’޾+ƒYóÍsòÚ¼æšk–Û¶]Éçû×ú¯J¥øµJx!IW­„7ûp˜f¥ágOOX–ìaË•Êc+«ôöö†Uf³q_“ÍV¯Ôl6[éïüëX–UÉçóÛ¶+étºbF%•JUºººâï•J¥’N§+===•ßnümå™×?Séé驘¦Y9¼èpåú‹¯¯¤ÓéJooo%›ÍVlÛŽ·*===Ã0*Ùl¶R,+ù|¾’Ïç+½½½•žžžJ:Ž·‘¶tuuUòù|Å4ÍøØäØÓétŲ¬øø'‹Ã vVެ¹¨R1ŒJÅ4+»6ý òÛ¿œ÷Výî#^;ãIªRÛñõ ½êÝwß=#ŸéÇËXÆc%ŸÏWlÂ{4•JU²ÙlåÐi§Uî5Í •Á?GÙ /—úÛ#»·q¹½+,ïùyTÐS©T²•Šý“貫Û•ÚËq¸rçØ?o\ž:TW„åù' »ªc¢lPw¬GÇôT]ùmÌSn4**û™ºóeÛÂ)#5}^\Q±AEvxƒ0+cëÇ @ú+ƒŠÃÑ“¨'ѽVì¨==um’gUo]=ùºcí‰Öé ?'òž˜Î 5&‰b±X1 £R,i{E™®ë=1“™­c¡þþþJ:®)ëíídçèïï¯yV†QI§Ó•|>÷u–eU èض]ééé©X–U*¦iVÒét%›ÍÆŸÞa„žžžJOOO¥\.Çëɳy³Ô”ÑÓÓS)‹ñ9²Ùl¨Ø¶]1 £’Ïçãï¦iVòù|Ų¬aŸýýý•b±8ì¹êêêr™¼£Éÿå·°,«bšf¥\.Çí”ß*NWL3´bÉ{ŸišÃ0*½½½ñoÝßß_yÏ{ÞS¹úê«§ú'˜t’c!˲Úe.1Çc=nëž|²úŽfWB» ý¡ðCùJ¥\®T<z{{+©Tjª[Q2ãäa=7mÚ4¨lëÖ­lݺuPùÃ?G8»¡‡pb¼Ì‡ÊÖ×5®-SF"Oõ÷©÷|Pªœõãc¼÷½SÝŒa™Ì~@ÂáxËÁú áÍ+7öh"­d³ ÞoÒ‡ØÔÄþ8q€ÞŽ8äx£HÉobFœïCfüJJ ¯šJ¥bO=Û¶ãYÃ2Ó×ÿCŸG~üd³Y¾·û{4ÍoÂ\dÆaL%d*•Šó¤ôööÆ!|dæ³ä§K†h•ó%mIÎê W€¿»ìïX’_vœ“è-ô¤¹”}öÖm>‡ÿòw¬[·œÕ\ÅÆq0ò¯—É}ÔŸãvÂøÚ3xÒîT ÆBT:ÿ™¿ú,{£™æ‡›šxòG? —GŽ‚+‘nï.–JîÎLžŒh•nà+„×›ž¤ý%Ø â÷q>P‚àTà’°Ü» øX·€÷Rà}à^@õúÍ€÷î°mÁ¯XÁ£Q}A´¾Ôÿw€Eöú€•àÿ¸(qŸÉËTNC½¢¤Í¨/÷öƒ÷òÚßC¼“ei:®z::Ñ1¦ë*w£2IÚ-y|-¾LÙ-ÏEëKÈñD”u“qà%¶n (GçÙIlkQu锸ßv´/0ö}FèˆÖÏGëm‚pPjFåÉ*I5ɵ\|þÅ<¿þy¦;Cõ“Ýȵ¤áeò™Ic‚©¤P(ÄžtòžQš3–3ém˜D‡JÞ)€žžžØÓq,ᡠ])ù§–eaYVœîAÈçó±§a:ŽCÇŠg¤¼S ÷|i90l®Æä¶étº&õ„¤ä0²–eÅïÍÍÍxžWójÛ6q Ã0øÀ>@ww÷Tÿ#2‘}A2 ‹¢(Ó—é4&8s`hßµâGšÚ¯´`ˆçœØúe¶ÒPxliiaóæÍSÖ¨k¯½–AåÒqH‡ÑÙÙɵ×^Ë­·Þ:.û•F£Aq}.Ç¡ÍFŒ^šúuúZ™ú°¯Êñ1™ý@œ70,ŸZ±19Fð¼0”ªôòÂÝè2yZð…×|ÅÞâ8ôP2 žäñÜŠÉrÉë!yý¤J¾¤×¿°/zù"–=» û*›´™† ´š­q¨" }$"c2t„T•p=µÞ¸0Hl¬£eIKx#ŒobÛ8zô(O?ðtøÛd³¼úïáå _~ü} ¼v&[xLÚH&ùÜOS5&8|ßç?óm¼õŠ3 ×µ<•â£?ÿy¸Âo€u‰ VS-¿˜ðE%þÇ C­î&E°ú³hý;€oÏv äÛÞ)`­poXììó|H¹àýžXxÌÜ©/ƒõ€ Ö%à ÁçÀx;@pSØ6o¸Ÿû´°-žˆ—çAáë}0 8Æ à @ÛyÐ)ŠÁYrŽ °²ó…¯÷†Ç*aÒcí~?°ü½aÖ þ?†å^¸»øör_~úÁ< ©;áÂÇŸµ>EKK ÿŸýÞõ¶w…"žàŠtŸÝ ÛJ‰ªP(“LÂ>}Õ{\&¨ˆˆ×•‹°'"c$âb½Q¹ü%ïÙvªV$f¿„÷–öõP PíkÂtË"\«RDë‰Òkß¿{`"iÔLv? FÛr¹<Õ§CQæ$3iL0$ÅB Ÿé8NœBÑQr·µµÅ“¤¥"HJÈèFˆWÏxåK6MsZ\ ¢"U¨‹7Ù“RDHN¥R±ðÙ(¥‡LZõzäOŸsN|ÿ¼ù‚÷sÀÞº:~¼ ¼=`‹Wš Áß…‹½ù`oã4 Þ¢ò¯€}jXF”îÓœÛÁ¼ ¬­àŸ–[ûÁy-Ø·‚ñZðw†eÁRðL°Þ ,w¯·iý2äÿ'X À;¬'Bá1óAÈ¿?tî~•¯wXÿ ‚"øAX¿¥³t‹`[à=îßIAp ¤›!÷ðw ßç"èýdx0ž Æ{ kg(šzËÁܹÁÚ]÷Eà‡á÷Ü™`öƒû <ÿꕜzâÙ~~AhP“{" þ0_ExŸf¨öû)ª ú„àJŒžÊ=±Ó‚<·“Tħ(³•Ž¿ŠñcçÎ8ŽÃ'>ñ‰†Ëúúújܧ[ZZX³f ;vì—ýK"ðF$ ÒÑÿu(2}É¢¿ÏLe*ú˲ð÷s¤·^õ²ËÂÿðã-xÉQW8­²ŒPÜr ¯™f0ŸîƒÜÿ öš NŒÖoçT­ƒkédpßÕñq°‚±üåàž¥ù+€qÌùá6ÞE„×ë{ÁZ9Úî_@æóPºìH·÷›Áû ïµáå%½]០Ã÷í`Vm“7ÐCòU~1:îç]àŸé(]Öï—À‹&£¦O÷\pmÈ­Lä™—> ‚ÅPzCéÓ`íû0€Ày/†ê ¦ª8®g£¢(ÇÄ´LžçÑÚÚJ.—‹Çµmmm”J%Êå2år™ÞÞ^Êå2©TŠ|>Ooooœ†!›ÍN»0¦IfB:&š$ÅCy·¬Ç¶íšÈ93•‰î üa<“E™L§1Á©O†/Õë~S©¦ºÄƒ«"11ÑçJê¤zFŠ$¦(3™“FZaÛ¶m,]º”K/½”mÛ¶±}ûö†ëÝtÓMÇÕ>þñ“N§Y³fÍ å2“¡>nóÒ¥KÙ¹sç°u?õÔS”J%úúúâCÑh &‘¶d2¼IhGR”™Fww7ÝÝÝìÛ·oª›Ò‰ìöíÛGgg'ëׯ¯©Ã0 Ü#`Ýö… ¯Z÷öޏŸR©T Md&ì¹|Gÿí(å–ãY©­­­q(Ó|>OGG===ô&ö‘Íf=ôÍTÚ¦0ZÏ[*o¡õ‚V.àr …øïYÖ» Θ¤ˆx0ç@DößÙÙÉž={hjjš‚FŽÌdŒ º»»/ºCô.ñ‹mÛx衇h¾÷^þñïàŽ?zŸø_ WÈÀÎÉgPÍ Xï'Q]o^NìIÌ …G÷ÀbBu/¾²„:¤±RùjÄOI)ê­ …8gq¸¾è_¾ Ndß3V‡Ÿ©¨.I!(}y w^íáF]¥KÂu¼ {bø~• çF‘•WnS@é:ÈEb£M5T½‰þòZÌùOp[ }_6.ú3qüK/ £‰¶]ŽÓ$¡\öî~(½æžÆ™TÞF¶9?úš•1éjÚËF—A£r9~Ù¾aùXëgúúúضm÷ÜsÏ {iº0\_p¼c‚ÐÙÙIKKˈï‚ÎHVf#Û¶m£¯¯LuS2Ñï÷ÜslܸqÚå„Ìd2X–E¡PˆEÄöövºººjÅFbÓLŸ™Ì5¨L<#å'Ö÷ƒÏ<óÌT¦¢L)j3ll3ŠGyXÍ˱(,0€G¸£0hÝL&„žê…B!mÆŒ˜ˆ£Ì-¶mÛÆÏ~ö³ã éñ800À† ¸îºëâY}}}tww³fÍšššèîîæàÁƒã’Òq–.]:!¹%,XÀš5kX»ví°ë52&„Q™ÓT'«Ï IâŠRCKK ëׯgñâÅSÝ”†Ld?°xñbÖ¯__cTÐ? ænª¡øŽß÷Ãzó#GÉ(ñĪ'øÒ#_"—ËQ*•0M“®®®8ÜM6›¥··wЀcº ¦#àáï?‡–Züëéy½O%ëׯgÍš5,X°`ª›ÒɯÐÒü-øÆO÷óÖƒYp×]|´©‰«ÿú¿âª0³¨[?ˆ6ú¡æªd‡Ã|ˆœžxÊÚà­šÀ;= -J¼wU÷íS曡*XÉø¤cqmÎÄz ì}Õ0äIÇ<—pœcS*Žß‘3E¨ÙIºÉì‰ay6QO™ªPXŽ>½SªØ’1­'ãªlT· Vƒq"äϯ:ð¦¢e]‰¶Kì€0mb>±n (.‡  < Ü&BÁ7¡àɤ²z•mÞh|†ª×g}y=ATO£òBƒr—¡IöYbl°ß67³~ýzV­Z5†­&—‰ì .\ÈúõëG|?H2ÝCî)ʱ°víZÖ¯_?¹aéÇÀD¿¬ZµŠõë׳téÒ);Æ hnn&“ÉÐÚÚŠçyd2|ß§\.S©TÈçóضMWW×´“:^†1#¼ çú~°†W½êU*(sµ¶ŽŠ•T_€ÐdÁùµžŒ©T*žü™L†b±8«žéÊìaíÚµã2&Òãñãÿ8}}}Üxãƒb ‹‡ÀÎ;¹æšk&s ÝÝÝlÛ¶m½ž|òɼêU¯j8"‰$^Oâ·$x…vÊL¦¥¥…––¶nÝ:ÕMÄD÷K–,RlŽ€ùÏ*( …„Q"aZ|ß'‚8´*ÏhêèèÀ0Œxð¡/ÝãÊV°øÜÅÕ—Æ£SÝ¢é‡ÜÓÑ»a²ÆÇ+<K`ïoöR2M\àX,¼<œéxÒ<+ÌíWæòQ„¸ ®ëÄP`ržlUÜF€Bº*(%#Õ'¹¡jœiÀ}Eu[?*“(ÈIOA¡H5RpR$qRö+ÛÉ{V‘ÚÔƒë©q½ŠˆÕãJQ=ö侤 "‹Ð8”yÈÜæ² NÜ/ÁøƒjÝ2Õ,¨«Ó¡ÆÁ4F~£¤Ÿ@ÕãÖ­ïFËJ ÊE4¶Ô]O²<™R´ÕQÿ›yC´}(¾¾x1öúõ¬êîå“ËD÷"<Ž•™¦NQê‘wä¹ú~ ÂãTÒÑÑišA€eY´µµÅ¹ëßf›2Ž£L9ú~ð*žyæ•9Ú —ŒjL SW³ûå„a„º€m>üa ή=ÏÃó¼ø9žÌŬ(Ó5kÖpðàÁã4ûúúؾ};[¶l6ñêš5kزe ÿøÇ+Akww7K—.åºë®«)ïììdéÒ¥5a\wîÜ9H@IP-žçaFqÇ¥6ZḠó“;P˜Ú~À²,¼óÀ>ªU\pœªð8J\×­MÓ¤T*AMÓ45žûDà‚íÚµ9ÕÔž1c˜.c‚Ñðëƒ`Y]Q¾W÷ËÀû€e„ê({†ëûçPCš s &FªGœ„%µ¢OIÙiQ ‰ê¦%ŒR@bRÒä/•Xf$öc&öÓhl“ÌkôñêµHÖOÖ%‹¨IYºnýúQÚlÕm'뇵ØÁyP8¿Ú6/±½hÀU±P–Õ‹»2&LŽåS¢¸‰úëI)/E뙉ò€ÁcN)ÏEŸÅºýI»IÔ+CÌ€Á¤üŽFbý¸€éÉH}Ìtžê~@Q”‰c& †#r¹©T*—*¡SÇÁóÓÆÙ¶m—]vMMMlݺ•¦¦&.»ì²ã>¾ïÇÆÃ¡Q¦9Z6®Ca‰±UX€êûú`Mýtûz:]Çeœ™ª~À÷}Þ÷‹÷ñ—M nµövÅ ±x4Ú¶çyäóy‚ ŸÏS*•Èd2”Ëå91syZŒiX t SfÓaL0G¾t7|Ò¤ÿ„+¸Ê~8¼ÖÚ øq¸Ü_E8xð€DsN sÿõ$ž³Ò#ˆ $žwâ,)Ô{·%·M¢’HûDàÅêy,mT‡["Îe¨†G•¯¡hþŒYªN¬’¦Ó§ª/§¨z&Jˆ~/Ú¦ª ,"¤O8¤2õ''ÊúT½ QY;Uñ¹ÕS š¯Ò¢*–&‡š™¨½"nʱȱÞöÙÐÛ;Õ?× FÓLe? (ÊÄ3Æ#Q(„½{OO­­­d2™XhìèèÀ²¬9%4Ö£“9”Ñ0™}¾¯+Êôd:Ž ž÷,ë½Õõ—úðbã>D&0ú¾e¶sB£B¹aÅóQ$³IdÉc"¹%7lØÀ† p‡-[¶ HÏóâ†O5Ç„5–Üå~ƒ2±l jÕø^IJT§Ò2Í¿UËUÇíÎQíÕH8-12>U«š[WîEÇ™E="ÒÖ»†ˆ%o¬ˆ¥°nÔ./:7Nâ$c ¹„ÖÌFmÍ Q>–ßU,ÊçãÝAÀÀ²å@ƒ{=›…ryTÞŽ& ª/Ðííí8ŽC±X¤··Wg4McÒ¡zÿ*³Ž‰ŒÄ¿¯]õã¼á»o¨^c?#Ê)êAu¢Î9áxB% 5Z$¯%2½¡‹jþÅTâ³Q/¤Ž¼Ãc öºêwÉ Õóž<·29µL(ø•©†–5 =»ëJîÉÂß/ šV<STsCŠ˜\¤êÁ*¹+ÓÑúâ…DÿOEë‹H˜Nü•£O)OEÛ”©6È„ºþ¨Í„C¨TÔök¿öµ©þ©Ž™©èÔH®(Ó© ‡ëº ŠÅ"¦iÆ)R©ù|žl6‡kWåø¾@Ãÿ*ÊÌf2Çgtu‘ϾÐe|X× fcs*•Âó<|ß§§GgÆ+sƒ†k×®`Û¶mñ ;Û¶mh8ëàxxøá‡•555që­·Æ™k×®·Ž#LÓŒu‡Ð8TóÐ(7£$åi„Cã;~ƒºÄY“Ì£j±JÆ“x\õï)mT-UIDx”ötDû ­Ÿ2å^„4#Ú§Å`%¶P×ÎB¢L,eâ¶‘£šôH„B3Ú¿$©’s$ö!Z±íø„SöMª^/:ù±rT]B’–DI~Õ-—I%ªÉµüĹt¢íÛ¢ò,U× “Û­+®ªnÉß_ŽKÜäxĪ(îª Ÿ¤ŒD¹Ô'‰ºÌD{$>\2‘V!Ñ6q£‘Xq¼qÏ™ LF?°®ÿñÎG0)Çc óù<žçáº.¦i’J¥âOЙ““ŠEha4bÎŒg²ÇI$œfl‚paï+8k÷±ðF`!á3Äë) 9ì†ãGôüêãj=ã,ÂGŽYÉ Oò]/ác£Þl$âný©Hõ™$™·2ù›ˆo`ý¯Lu“”e8˜¬ß¦¶›J¶/MíѤzÔK^Ò†FÞ°IÚ¤°íP3gõ}ÁdõIÔ ©(SËTŽ ÆBtttĹÒét‡Ã\ötT”ãe"ú‚d$4EQ¦?S9&XçösÕî‹9}?‘ÜÓ„ŽŽÐ¡ŽL&ƒmÛ”J%|ß§Ü`E™m4›ššØ¼y3[·n¥¥¥eÈ\Û¶mcëÖ­lܸqÜ…Çá8֮û<Ëwä=ªÜdEì’vñ¬—ÑQ„ j’§4U¯=»n¶DYŠjbž6ªÓéE”.)N¥©zë£òö¨Í=Ñ~š£ºDØ“$B"䉥JêOÆò‹–XSe]9orœ"ÚI›EŒRb’uEûë]6q2E™ÆLV_0 …†a¨¸¨(SÀ±öšãQQf“1&8ýüÓ«6èH¥Àlt ‚€r¹Œïû=E™Sœ4Ô‚t:ÍÎ;¹îºëؾ}{MÌäîînº»»Ù¹s'kÖ¬Ñ+r¦`YV&3Èȓӄ¤R™´\‰¨ÖȳQ¼óÄ…BÂn&…4—ª÷\…ª(–Ì)îâ¡(•ˆw""Šg H¥m"\IŸ'â֟׾F™ )<655qÓM7±uëV¶mÛFww7[·n—·´´°yóæY!:A€ëºa¨D õ”ÎKèN2à„ª—Ÿ¼CHr—ZË” þ’¡R!„LªáIE ”Ä@6¡È(^2@Ï8e"vYTIÙF¼ð$ÜfU1BA®H­gžìC>å¸`°–ünS;•>é‘Ìm( ‰ê'ÕÛØ’Ç+ße?IõÏ&UïM9×vƒú%!S£í{‡©´ ·m£9ÆÑ¾, •è«ÌØÜ$ž8s¿;õ¤ê¥èºË…3•F ÃÀ¶í8‹eY‚MQfÞa°v§\qçÝ,çq(\øJ ‰êóûhí¶¥jEF¡Êäàºî´É»ëûþ˜„ÇR©4¬ðèy^8ŒÓ—Ù aº\7Š¢L/2™ ¥R‰ 0 cúyHKz“á5Iqm(¼Ä:ÉYÛbO¢ɤd™ ›L‰bQµ‹T£ó$OÉ4+ É¥: º=±®¼Sç¨Ú$õHÕ‰¹b7‘bPIÈ¥š2¦@5„€µ19\RÚÈ1ZÔF)’Øçå)µYÒ­dÛ'#iŸM5åŠØ–$S.ªGŽWŽAÒøH¤¨d<ùd¤* ó%áÓ/?{ϺwT—ÔlEßçE‰;Ÿ~šWòÊð‹Ø¯=²Ù†¶mÇy“)™e¶sÒH+lÞ¼™Í›7Ó××G__ŠŽ“Zu¢ÁÀ²¬p\ö=0Îk~´‚C8@‹ò7Å; !*öøA5ïž ¢ÓÿöÞ=N’ª¾ûÿ,,·Ù­å²à2k`¹ì¢H ¨ƒ ˜êpӨĞM"ên"Ý!Op5nìÖD’$OºÃFEóD»ñqEôÑV e¥Kãq w¸ˆSî:,°\¦v–½péßÕߪÓ5ÝÓ=Ó=}ý¼_¯yMw]NSUçÛçœÏù~Oñû0¼E}$l&PÚ¨/HY_Jj#<,†§µKc3lÏD,7Û(mtÏF¥q騌”Ù'娆Z޹ô×ÔNR¯ Q`œûõ||´—zÄÛ±ÂÚv±!º¹\š¦!‹A×uôÒe¸‡Ø àº8ŽÄ‘R8M~¤d©ùí?¤tÌM¢ Ëø–Œûtc¨ËNò¼§Ô,)¼f*4ʸJÈúÁ2€­iÚ¬ƒb¹\@uáÑq®Í†_#„”C& Ú¶|>l6;£¿ÐPÊy·…EEYÚDõÎË›@0QY»Ô…¨eÒ°DJR—W‘åZ$ò‘^®xŒˆ…ÒøQÓ‰"ê ås^9×Pò¦!ÝÔÉÈêx‚IPÅÍðZ"Þ¥D ’ej œ#y(7v¡6äD•´åQEì´‹ÏE&nÇëÀ”Éâ2Ö#Ï-Wü‹¿« HK4,idÊØS¥Kµä¶òHd)«˜wy~%é'À’g– Wáo=!¤~sôÑxó½Gç*Å~”™t$mMÓà8NÉzÏ„t3U…G¡ÛÄF54¢û<`Z^hH‡þ«kóÉÌ6i0ZÅÿByJC/<{PB«ª cÙ®Š‰P®«Î¬ Û²ðØQåg4ªÞší1Y(\ fd0xbq«m{•Oq]?.{6›E4E2™ÄÈÈEGBº™\?œfj°Š_2!^ ‘ª ù?2gH_D‹ Õ*¤9ŽS—×c¹sÅËŶm #•J!Âq bjj üýÐu=ˆº!ë;Þ#B¥x8Ê$Û¶ýp«†a ‰À0 $ hš]×Kβ٬?ÁNÂüHúº®ãé§Ÿn«uÑÚ•l6["„®"™L"›Í"‹!“Éøë¼§ÓÞÀA]“;$ÒRÞX‚qqxÑ{Ä«- ¯1"f_¼ ‡h.¼ÆŠxÏɸÆDñ8uBtª˜®«§†áRޝµ?¯NN/oRŽùÄ¡Ÿí¶«Ë¾ÌV†¹<:3ô_ÎW·«¨Š÷;çff–4%l¬zÿTR‡÷ü&¼Õ*¥¯+ßåž—  `ûêíØ9ºs7½;°Ëx*BH˜{—-ÃÇó‡” P¡oiR©”^¡fá±›Qg¡ÛGÚ@â‡^ .ëHÈ YWÑ@°ö¡4þ Á/³úrðfÆ© X³Âg•° ©‡®1ì™x;ÞŽüïö¬ÞŽ€7Øìº.\×ÅÈÈLÓ„a •@Hc/ö-_e/½È{îÞàHÁ$~qDxT'¨÷úϲe •vµÙ£" sqcÛ¶?  ÃÃÃÈd2¾°Çáº.ÆÆÆüÉ)Ò¶t¦i–x9NLLø“W\×E.—ƒaÈd2ˆD"~Y4MC4…aˆÇãˆF£°, †aÀ²,ÿZ¶m#™LúiÅb1¿}+¿[ét¦i"•Jù÷À²,<üðà ÿð;œd2‰t:íß»šeÄSG¼Nr¼Œdðú%4ž´ó¥O! ÆŠ—‘\Cö‹1 ÊÏ‚5æ¥O#È2âù¢®C¯SÎKÀð–<Êòâmý#·Bêg(çÈy¶P¼§Ô%ÔkȽpCçɶptAMC]+M-“Ü¥iÄ»L\Ûe¿¦¤#yS=ŠÔû¡–U&¨ªý;ŒÔ2ªMT+”7©TJ ¥i¡´,\vÞˆ÷ÂØØXÉo›iš~D¥¹%Xü/!AMxv! œ¦ˆ.<2ƒÒ¥U,Ì£¿÷)á=åšc(}ä§´ò\ÌÆÐ«s6‹aeH Ç•kÖ¨šê2"p†•´Î‚#„:±æ4`õc½ãÕ@°<:¦Öm±ç*$¦ÓiŒŒŒÔ|ü\qM "jxÓt: ]×ýAát:B¡P5m×u1<<Œh4ŠT*å‡=µ, ñxÜš!Û\×õÂ÷'“ˆÅb¾‰Düu3™ ÇÁO~²š¦add–eaxxù|Þ÷pF:ÆÔÔ¦¦¦ðÆ7¾±X ±XÌ÷´Éçó¾7~6›õÓÏÉh4Šh4Zâù(˜¦‰c=vAžI7N§ý5Ûòù¿æ‡x¿ñ~/jše™Ê ª˜¦é÷Íé%z^xT©¬}€ñïÆa³p¥S.Zéì«È@€„BQ·^§³Þõå%]6 ©›WìÀON<«±bNçår9˜¦¹`è„öbïÑ;ôãG¯ÿ.Ô/ÎŒ¾ÒµÕ±@q`ª÷'¿ÝI&“Èçó5+žxµ"‚ÏØØXI•ƒ¢Ñ(lÛöÓî¹ç{øýïÏ}î#þ1Û¶ŠGy5ž~º·ßþk|ûÛãÈfMËák_ëÃùçŸÇÑ¡ëÀƒ~?úÑñxÍkÞ‰¡¡ßáñÇß‹'žˆ#~ûÛgð¶·€;ߎ%Kþ?ùÉcÕªoã†v㇦MãškÎÀŽCøÐ‡ÎÇWhÈfM¬^½–uÎ>{'x` t=†}Xº4×Õ‘N{#À^ÓT/NšÂ¹çNÁq4D"€ë~ ?î"òù²Y``ˆF5˜¦ç1) BÓ4¸®‹h4ÊI2sD„Ýõï],ýOxªñ“EH# .i ¯kX (ç8©>+­°?üˆÐõ¼rU·–yê˜J9oªð÷jë£Ur"UÓ)—שÐý(Gx8Õ{(õæªd°ÕíSÄTI[Í›ä9ì™(e¯Ç°Sß1”ŠÅª—’ˆ¢åòªÞ¯ðýQL­ð5‹üâg¿©Žã8ÆW^ý\»ÌÛ(ýÿ 'u¤Â1Çã‰Ûò,ÕŸ@ñÊ•wCGðŽÎVç0PM¸Z¸ûSÛus9OˆÓ4o¼Ö0¼ÏŽãýÉ÷Jض'ì%ÞõDP“à5®ëmÓu/}ù L&!.Ÿ†‡½ï©”wàã8Þõ]×;×q¼ý"àI屘—¶¬Ü‘Éé´÷?›õ¶'“^š†ŒŒxiÈñŠmo;àåÏ4½<¦R@<îoÞ9##Þ>9V®o€Ò|‚e÷;™ "F£@$âošÞ¹““¯Æ…îhþ‹ÓFpùBÈl8ûLýü¢¢>P=D³eY%b éz^xTc¸ÛÆx™E+!‹ÔN€ò`™…,qõUÔd½È"脺8õó§¢ÿ†—çäx,!óâñxIÈ:BH÷!-„#' ?|Ýq¡yáŒãĉAÆxÂk:v2®ë XITRx3 àá‡_@:íÀ4uðOÿ´o{ÛáH§½ãï¼s3Ö¬YömÛ+®ø$\×83Í`àÏ4;žÇw¾³‰„†áa`x8ÛÖ±dÉK¸ñƃ‘ÉLáÞ{—!•òå~ðƒmøÎwVà†^Àèè°, ®Ã’%/cÍšƒðã¯ÂCý)Ä¡ñÿý¿ðÜs9øÞ÷îAÿ Ø·ÏÀW¿ú]œ}öñx衳qÛm‹°lÙ½øƒ?x÷Ýw V¬¸§œò2^|ñpÊ)‡[nù ÞýîËqàÀExË[ŽÄÝw…SNÙ‡ÛoÿŽ>ú/pùåËqÑE/â‰'ÎÁ›ß 8àåÕ4Í¢˜xÀ²–#•}€eÅ‹°2ˆišÞ ¢e-ƒ¦yŸ½IÍ?7ŸdÝðpàYÑh 7Ýtöí;Ùl0ÀiÛÞ9ºî ˆ^wÝßÀ²îmõ«ÖVüúº_CKkøí¹¿Å²ÅË€O#X;½œÈ¥¶Ë»¡âw+è?‰'ZµcÊQ‹MX,êy¯$-ŽwÕOxäžG`.3.óâu+ØÀ•}Wâ´Í§“Ô°Ê&*‹å ìã‹è5Wä7e6:À²D“ß4Àû—ßjÁÒiï7'‘Ä3Yá"óį|ÞKKÓàÿf ù¼w à•)/Þ.Û|#ûE<ËfO„? ø4 o[<îå]®eAÚºˆ}–åå]~?¥l@p=× „O5MóþÆÆ‚ós¹ -%Ïjb"ÅûpÑ"ﺹœ÷ß0¼üZV JŽyéK~Eà’I/}yä×pãZŒf‘Å…à#ù8òÈ1zèí~›I×Ï(®q¸ º~aÑ[ÂöC¥~ãžGûàà+ýuo½5Šdòoqùå&ÞñŽÞñXŒ|àëÐõ¾â<èÍ Bº]Fù ‘rìlûÕÏù|àÑà ›¾)Ï0œ–¦ïyÏ·KòÝó$W}âU:sË"˼¶=çBÀ.¹ïLL{ãºX‡798 lt7"ÂT ~GÕe¹©r"¢Ë‚`4i–x–åý†K:"œ‰P72â¥{mÓô~—†‡ƒß 7* Ä“1•òŽ“‰7€—V¡ˆ|âyhž0'Þ†"T<u=Ðâqïš©”—ŽeíÇñ~+ ÌáåžÃ¿µâ9¨iÞ±ªÇ¤iz×Ô®¡axÇÊ}N¥J…Æt:È—\7Ü •m"fÊùêøv¸Í b°J4êå#-=>L&ŒŽ>ŒÑÑ} ÿ’¶!=öؼϕèÞâXžF}]`^)ТŽq‚ úÕ(â‚©lS$¯†Ú&}—¬’†,+Ç'”%b¸D#Ï"§¦•(–Y"½ËR"¦Êµce®mËC°„­ÌÙP—:V£Ø«ÑâUV„VYnZ®c(çÉvéé¾j6JûvjÀ;I3¡\CdzP(O½?Õ|RÂûe›^æX(ù“%¨Õ2Ë3Tï™zL€mE¶3pË÷-Ç΋¾‚å¹CƒXÚåŽ-.ÙÁñCÒ«Px„JÁà.Ì«,ă÷ë(¿>µ S•Â{Yû¥N}0—ËaíÑk±Ëýï†aøá³ÄƒSÂC8ŽMÓ§ž22yžï;Ì«®ñx0ív’É$R©”_·!]JÀÛp})nßs;†×YP;ì²Ä™úóÞhË áÃdp+™ f»Ë¬~ &]šæ#w2p%³ì%ê©x D£Àí·ÿ9仈ÅÞ ¸ûî;ðÿx.¾¸¯(öÝ€DâÝÐuÏ<ó[Ü}÷‡qÕUCH$ÅÀ à8i¤RQÄbâñ8R© ÃÀOXxþùoá}ï‹Á0]ÿÒé4öî"›uñÓŸ&˜Åõ]8ÎWà8ÆÇu¼ç=)üâˆú§î½÷ßàºÁ‰'¾ßüæ±èï¶ÅÉ'ÛˆF£¾7:LLäáºÓ4`Y·#‹Í˜¨¥ Ëú‡‘H¹\‰D‰DÂociš†L&3#v™ü¥J†ÆÙ8í´í ð0}Û4Þqø;ð»¾Á©÷„R7¸ïàûu£ÞA ÁH°’‚–,c<æaOÊyÊ„!™¸’Í–NRO¼ “I¯ýËyÂ’D2pïœX¬Ô#ðÚêúƒjˆP¹ŽˆÞ±étŠT&9©žuÒTÄE˜*†LN¥‚üò{&ÿÿg•¶'^¾d|W¢„CÀª¿™åÒõ›63}Ç1+"l–‹2oš¥ÏA ‹ª22ˆ¾µ"ÏIÊ‹^–âáɱïòìØQ=Ĭ j²,ñ¬ вT«ÂŒ5ßåÜr„”Uá­" ÊòÓy”.ÿëÀ3QbÎdÙeÇâÅã â¡¡QKkü4¢Åã’ð|-œâç˜R–\1oÒg’eŽÕ%³E •¨ÕIÎâj1RD6Ù^JZÊì"˜#"ÇJ”F!ÁNò/‚¢zuË2ëÊ5CÇ(^SæšÈ=“穊·XלòYP‰)iiÞA¹êòÁª€-÷ÓPޝ$úуNŸ ä9eþïŽDdññÌ3w@ÓL$“I¿Í266†d2 MÓ‰D022˲.,“É —Ë!û¢¡m{C›7/ÁŸüÉQÈf³p]×÷dT×2´, –eAÓ4ض]³Ý6 Ãok„g¦¶‹ÈHÀ ð7'þ οò|þÎBŽÅ‹Š/ùMÈv?aþaÝI¸öÚGñÖ·Z8ÿü/ã'?¹ À#èëû*¦§OðAüä'à—¿\ŠÝ»wûi(ñ"AB$EÔK§ÓÐ4 ±X ¶mû™걗Íf}¯Ùt]G2™D"‘@:F4E$iš¾è&߇‡‡¡ëº/ì úž{ÃÃÃH¥R¾Çà ”Š™J¥0<<ì{û•óbŒÇã%™2@922‚d2Yô °aš&4MC2™ôˉDF‘Ëå055…xqz£ ¶Š‡i.—ÃÈȈ¼°s^YLÓ„eYH¥RþúQ™LÆ+ÇÆÆÉd`Ûv‰˜jÛ¶/fŽ!Nûâr4õaUAQ„PðŸ”Mò{g.°ãå8aÇ^Ot–i¤R7t]÷ÅaBH—ã¿»îwxfñ€SðÈëúü«j¸ ¶åßDh”0§U"ÅÃ!• :ªwA*¬Z5ŠoûNï0³qkÛV‰@˜-Žj©„Ô ?êå÷$—ËÁ²,_0”cMÓô£)Ȥ—aoAGÿwÐq_äŒÅb€išˆF£¾'¡Šˆ‡š¦ùb§W.ªÂí·†ÁAé˜T'/­’IoÞo”k•YøÙŸáßþ7Â\Ã%@âª$“Á¬q_Rßùðè´ëʃš†z|ØÝGMC¾«‹ªÁ,Q €™=Q5¶#à+ ‹ÉB£auC Ÿô¼Ã“¾Â Ó3ï›ôìe±¹ri¨‹Ã•KCÝ?[âz”£¥FËÇq”{¢n ïW¯/a$^¦£z~SÁ%r?äPË;×x޽DÑ}éÀ ðÒÅ/aůÞÄWõZt¯ŠF"AõˆÇ½G ^ƒºî‰Pò:T@ïF1%åº,ò Œ”†[W«›xDÎÅ«PÌS$âM‚šmÐL^±‘ ªŒL¨ª„˜À… Üº‡óE„Üd²rˆTõºê4|¯ïY¨‚t£H¥S!Ï\"c0Ìêì躎4õ©çñ¡/2;ðùÏ[8ûì‡ÐßÿfÏaýú·á…Öá3Ÿ¹}}WaÆñq;Î>ûí8è ›qÊ)Ãql,[6€w½ëüÝß=ŸÿüE¼éMŠ/ù\{í œ‰³Ï~Ï?ÿ¼îuÓ¸çK—~wÞiâœsNÆñÇâ ^’×D"á{"ÊúGæ,•JÁ4M_蛘˜(çb±¢Ñ¨¿°îÈȢѨïE)žz"ÌŠ'!Œù^||¯Jñ¤AÈ µêEX4 ‰DÂ÷ÄñNþ«LªW… ÂÊEXtR=)Dðo8ÇqJÂpú’'%!deÕ0 LÉ€/†† ¯O%ÈÀÙX™Ѻuëôbw0°ã¼3ñÊÃñzȳXZ—ýuBHc€‹÷ÿ‹ŽX øÅÊ%° :ˆ§cÕ¤ì ´™4Reí! Ÿ&ˆg„nÈ/^üX‰‡a u]÷=Õ6‡ëº0MÓŸ$$ŸÍ@öð½ebÌÈÈHIÈðX,†X,æGGðòìeZí`Íø}V)·õlª¡Ô‚›„T$ ¼¸åEÿçÇ×.:Šh¤.˜ªVZËòµÎæó¥=?•€ò½Qõ½­ÔöÑ~Uœ §¡ måŽQó!ÿÃ=Ô\®T$ ï—<¨i” cŸËyÆOjÔý¶í)*á{68X::Q- MóÒPI§ƒç&¢dØI}v¢¨Ï7™ \ÔY¸N—%ìj–Ë• Ç@SS=Fí(1Ë ®#nsá{–Lï€,~þ‘¢gŸ R¸ý ·ãä}'ãŒ3ÎP\§«8à¶lY0K?õ>ËcP&Íw`Gªh¥P¥*¦é½†áåG^Mó¾Ï%á5gCªI%ÏB¹Gåš1¦é·Ð!ÖÕ…K&k•ù•æ=Ͳ,XI~ç:X)b¦˜™àÖ(ñµÛ‘0™Q0Žô~o{ÍÓ×\xq7£¨>ž˜…×¹©N¥‹úéðú)ƒT:'•t Õ%Ž"bVÖŸT{I9x¯ÜC­Îd;"‹˜&À`T6âjD¿Z9obûÃÂ^xn^½¨BbÕ¢;¥¿ßÕÚ$rìlâ]˜fv×Óéà7R&É»¬G-ζ½{%ße®e­Â£¨ó à,Ÿ£Þëp7F•âñ™kj«]…Ù&J¹®w~¥IcÏ>û <óÌ’únv¡¸ñÆ wÝuWÙ}¦i&N™*h …|¡P(D6/…Ï|æ;…±±B!•*Ö¬ù]áÄŸ/\xá—¾ôXáío°pì±ß(,]úªÂ¹ç~¤F ™L¦Ïçý42™Lall¬P( oûþB*5û55M+Zá°Ã-Äbc…K.ùeáÝ﾿ð†7L2™BaÉ’×þå_¾Z8ñÄ÷n¿ýÑÂå—?WX½z_áŠ+-˜f¡pÅŸ,üð‡¿÷ó*^pbb¢¦2OMM-ìM-’Ïç š¦ùßÇÆÆ †a̸ÿíÀÄD¡02R($ÞçDÂû>&Ÿ÷þyŸóyï½ñ>'Þ_¡l“¿‰‰B!“ñög2Azù|¡ðçþ¿Z} ZÂÚµkƒ/™Bám7?VXó»ßU=O×õB"‘(d2™V†q×]wn¼ñÆVg£éÌÖ&ð™* צ ë?ùÉÂ2Û. Pðÿ´ê—( ý Mó¾ž-Š?å5366VQ~,òù|‰]Êçó…D"Q)Œb±X!“Éø¿} †at]/hšVÐu½P( Ñh´‹Åüó‰DAÓ´’ßLÓ4ýkMLLb±˜ßi6‰D¡]àöZ/QSèBJÚÑBásK?WR¿|òy¯Çb¥ÛMÓ«Ô±XiƒL˜šòÎmQ=éZ¤AÛˆtº é\ÔqoJêDP±-”/ ŪëÆÝÂk—¼ÖëûešV(èzs^#¹†˜¢jäó^Þ ï¿úJ̧[nž©«À3•ÊÌ4•’/Ã(¿¯H¬QÈý­õž”;𪬦U~&&fþôÔ‚ú“$Ï#“ñò]^î|ä#)\øŽwP(&¾Zÿ±‚×7˜* ©B¡ M…ðsSŽÏ¼Nƒœ[(n3 ž}Ñ …‚^üŸ(î‹?›ÅíFñ˜Tñ»YÜ/(ûÅë$ŠZñ/SL#SÜŸ/^G®‘/^Gò•/¦™(ž—/^Ç,–{ªXî„ò— í+~N[j¼±V¹yåܩⵢÅír/3ÅtòÅÏr¼0¥¤7¡ä¿ÊñµÐœaÌ–!¯ŽQ^½X!x-z±MP¨Vî‘BaB÷ªÄýgÜïÝ´YÈd2³Òb!ŸL³ô÷"-ýþ= ÿv̵Ë1—þt>_úûžJy¿ÛêµÕüÄb¥¿_¦Yz¼¦yןšòþt½4ýp{'ܼ­ÖÜí·sb»¾š–ÚFó¾K›)• Ž—ßåh4è’Èsó~×å·]Î×´ÒüȽšWµ –~7ÍÒgnÛ©cLSSÞõd¿”MÎÏç½ç ÏKò*çNLxå•}_øÂ¯ Éd¶ö¥ ôxý+ ÚÀ¸óô­ ë'¸.°jÕ>Üwß}øÂ^løô§ÇÞ½¿ÆÞðj<÷Ü!ؾýn¬Xñî¿ÿz|éKÞÅ·lIÁ²â×#RÃŽmÚthÕ™±X¬èùp4ÍÀÀÀ6lÈÀ4½Y­Ñè÷¡i>ö±?¼éMžB¾zõ €i~ÿüÏ€eõUõ"À²d=%ï¯RôŸ††«*ƒDZ:øàóKf“ض¡¡Ûý‰ÄÞŒBÝ÷”ˆF½™ꬊT*“#3/ÃF°=Ÿ&kZp/Ôçm»tv¡„ÎS£kÉ I7• fªÊ`êl™1*3l;HOϬ”õAؽ{Â>“ŽÀ,ÇÁ‡TõÐL&ÃÅ  éÄùä–ûìßâðÇo&¨‹Ê^޲žR<8–Hx+™M^“¡Ú öp8öl6ë¯3kš&r¹œ¦Ü0 ?<·x º® ˲üßa ã-k'Êv =.!Ì™ëªë=¶:ì´a”Ÿ%Iȼp䀛q3ò¦2=4› t@éTR t*i9$®"i,Õ\„æ’N7ѨûB{HpŠ÷éC žo ØuQ€T:DƺÀKN=V–iQÓ©¶­‚þ<ìù&ãØªŸ:&-ãØêµ- ˜˜öÙv©W ä94FÂɇÃJ¤9O]A<ûËý®¹nàÍ)áê“Éà»ä[<0e}É\®tŒA< Ńqp°4¿òdÄÓP$ºtx¸teµlá@9ª—£”]Ê+×Þ+ïxuE‡l6§nÞ³}CöÛv #ÈÒI&ƒà6–´?|%Þð†'j©ÊÐóÂãiÓ§!F†-Šªñ¤W®ñ¨>hyø›7?Šm۞üº~$.»ì~œ>|étûX¢¶t¿¦LBƒÖB- Þðà¡„D ÒÐf¤nôKåÑÍ4ƒrŠ[²º`¹TV©`ÝIĹ°ÑŠFäV6µâ«"ŸúYò‹õák_{ÿçÿÜ .8_øÂaX´hÞûÞà8ÕˆH%– -îÏj$©pìl9G*°aQ•Ô¥mäñÉšª»¼Zf!Ÿ/u]WCô̆ú£31šy÷»7øÚOèFÒÀÞ̸¸ÊaŽã ‰ ŸEéNl–×Cê˜cÐÿä“8êÌ3a 膑ˆŠÒø“ &áð%s4²‘L&ýÙÚTÂ=†±±1_hóCCËÚÅJU — À__¹’ÐF¡·å~S ™70µt zD/}Ç ÃS9ZMérLà¨'B4õ#Þ–ë+/$²dj¹ÈÅ•H¥‚µ¡ê]Sh.×­&Œª¡_+]k¡æk4zÂR­!á*5¯ÔÁáJÍ«Z×-wžLlVÇ'j ÕÛëL{.ŒàõD˜›@ ì"ŠÀ#³ÕcÂçŽ! Âïyj–ï†rÞHh»ú˜¹¥J«Üû¨žSnÈCÍk¥1'õ˜rëÏ©y,TØ/ãc"øVzï]‚¢„ž5‹çÉ~I+¦'y—õ2âÊ5ôbJš xÏVêY¼ÿ’¶<Ûpゟ£ü©ÏD®“@ 4J9lB¦ÄA{#“b$¿²T˜–q¯¼£r¾ØéÐÏ ¿·Åû{Ño. ¡Îj/ÌêóW=/+£U$™LÂ4M‰-q‚‘®…ŒC a-ÂX.Œ/¨a9â–ºtx9Êí“m2þ.¿ù²2‚i–®² ãÖ2æ‘NŽ2"ðIÞtÝ· —+Ìdü˜ùÛ/Ç¨ãæ¹\ $J~e ãx<y/ùÓõ`yyµM¤®@!„¯2IG´ ©*:‡äWÎARJAò!Ï[]æ>‘ðÊ.mJy/†‡ƒtE_’ö×ðpðüÕåî彡Pîƒ8Äéº×•Ï2Y^´-³å|ÇñÚ-òÎ¥Ó‹ñš×üÀͻڴð8==7âŽ;îÀôô4úûû±aÃ\zé¥%Çmܸ›7oÆôô4.½ôRlذýýýó»hØÿò€¨².ƒ¬É/†mB›,òžNo{Û>rÈSH¥¼<™æ6ض“NBqýÂÐ4o}ı±1ð0ÑÄÕa£ó˜ž©Î¬(×x–qÕPΓ /÷Ñ4ƒ™Òˆ–†»:;Ò¼ÿÒÉS?•ÑÑwbçÎñ½ï}wÝ+‰›\õ¶Ëm©µ#æì÷¨Íœ¨|è¡{šs¡9ÒL;pïã»,…¹l™×ó«ÐËÕu½ì:™„…£%mÁpx8ÉÀ¶]»p 'úaK!‘Ѩ÷76Øòjz…mÛÄÔÔTÉÚ‰ª°(ë.꺎H$â¯ß(k*˺ÅÃÃÃþúÊ™LÉdŽãÀu]¸®[-ÀŒõ«Ñ.¢£w_8xÖ+Ôb ê¶ð•#¿2sFrxí@BHKhY›Àîþç»ñ£~„Óù_ˆD¼ßúùôóêA×½>ëððÌI±³îWÏ—¹˜ÁTjöëÍæ‰¡z24šF÷±Ë-•;_ÂÑ0•¿rËñvú¤­fØ‚Ågc3ÇÃ÷NÞsÕ}—sÙ¤¨ÙÞU³ÌþZìôlžaò¬ÂÎ)êgñHœ-/åÊ‘*s|t–4ª ¹aa¹šÍ—ã§*¤W$÷P—ãòndsiå8ÁCKvâ#—‡¿úÜ4ÎzüK€1‚Ù^¶T*å÷ë@è’n¹LT-„xŠ—šjÓųP"å»ëzkP‹C‹, .Ë€‹€¦zÁ…×c‚ ,¢ƒÈo‹üf‹çb>D~§žTªTÌ“|‰ ‹ÑûD¨öŽK¥O<ñ“ü©÷F"ZV°6c*åý ”N’rärÐ(â›´¯ o&èɤwåšÒSL‰~(¬D‹}DÄÜl¶TÀ•}ê³ -ŽN²–¤LJ¯W ½ã%úE$â•%“ñò:8XzoeýGÛöÚhª˜©iÀé§ßgžÙWW½iáqýúõغu+n¸áôõõattëׯÇM7Ýä1b06n܈õë×ã¶Ûn›ßE³@ßÒ¢¿Se­DYÑK Ä¢Eb//ÉÄÍ~ þ°MÓ4$“Iÿ¿„NF½Ó[~ Õ„I Ô@Ö"î•Ӫ̀üñÏ,~:»Õ·„̃fÚí'Œ£¶?L; aÍÇA.—C¾™S› éqZÒ&‚­Ï''Š]ù<^óš×`‚ÉÆò3$3É%H"1÷0Vš¦•xº®‹d2é{%¦Óihš†ááaŒaddÄŸšËå|OìX,;¤Ä©éŽ”é›Ï$¤vA »Bº›j¶ !v lÚñ Üõ¥^ïpl¬þ‘zBHÃhI›Àö.Þ‹Ót:>vÎÇýp±XóEG ðæ&ÌIdŸfRp¸ÐùmôÐK£Ò«¾lÎÜÓ,7oF);™fØ‚EXcN"I4_[6NÀþ-pÌ3!•pSÅêl6 ˲pç¿Å÷¿oIÈk *¨Î,@àœ¢z¹©¶]EÄ’ôÔ›"ˆÁ9OÒS½+EAK×½ÏéP1MÓ¼vŠh$Ѩ·Oþ«Þ~áвªø*Â`2ˆ‰êµl;E(aOÆÄû1•òŽ‹Fƒ±ƒH$ðèL$‚<Ë=’û!m½Lfæ33Œ Ú xAŠ7¥zÿ¹÷’æÀ@àQ)b®äÑ0Úb”¸¶K|] rÆ ²zžâ90<<Œh4 Ó4‘Íf‘H$ ëz‰wc;…+#¤]h¶øæ¿Bû*ÎRòÖ^Í!‰`jjªæt !õѪ6s ÿ<·ÆËåpü?ˆÅ‹ûMi¸Ë,»pC¯¦ë(¡T”|¶, ©T ¶m#CÓ4ŒŒŒÀ0 ¤ÓidŠ-G³šû?!]@5[Ð;`»VÝ‹ËÇ÷x~*Ú„´­j ܘ¼|Ë[ÞrÓ FªYÞ¤×nÆðÅB/§ÛÈ24bíL¡Úsmd“¯“ç¨5Ã&¼H"ÆëZ]ZBH9ZÖ&(âž;ô9yÛÛ½ ®ëÂ4MXÖ Ø±#Ø.kªâˆrê¶áaïØLÆÑÔ%Ì$”¨„ÝÔuOˆS=E´O:50’ˆzr®x8êz ÂIe-@ñTT=ã¼rqÂa`Uª…RW—ZñPõ˜ÔòÈýoOÕS¯R—ND6ãDl†ø&Tkë„EÌð÷ðùsm#„ŸC3Úwm!<®Zµ ›6m*Ù6==;î¸ÃŸ¡°{÷n(1°dÉŒÏ뺖 Ü3ø®Ùw°¿MÜrGFJ•áJ8Žã‡@3 ±XÌßF±‚Úiªp€×<øàÌoUœú™L&Fa' ÒDZÕ&ÈY\¡á$€Ž‘|ËR)hð´H‰¹/³Þ¤á;\×õ×t4MƒeY0M®ë¶m¸®‹D"×u¡ë:4Mó#(Ò+T³²??æçxqÅ \Ñje2ƒV´ vÿr7–D–À†÷½¯€ë®ë\GèF˜µf™Æ…žSÕÈ&T#¼jïçšy4Ãh§D‹ÿ[]ZBH9Z5N ¼âÅWàU¿~ø«Ù ³ã80 Ãÿ„XÌ›Ä,ëÞƒ¬Ë76æíW×WBñœÌfƒÐ¥B.ç‰hž(B¢„-•ßq™$“’ ïxùMáQÖ•6Mï³aÔ‰IE/÷*‘(?éI½–êÕÖnªýF‡Ûì.,µ:娲e ®¼òJô÷÷7díé§ŸÆÆ±qãÆ`c1ÔÆôÒƒ¡lvÝ`@±®RÃs¹œ/L¤Ói-G†f$íÈæÍ›±nÝ:lß¾½ÕY©J£ílß¾ë֭ÿðCüæÔ±kÉ’Š½Ð‘‘$‰Ž^J¬[·7nÄÓO?Ýê¬Te¡ÚëÖ­+ݱ°?¾¸v·|êSسi4M󽇇½6‚¬÷\i È%™ã8p]ÃÃÃ%"£ì<Ûcš&t]G6›õCµ¤Z±°éjÆÇDZnÝ:|÷»ßmuVj¢Ñ¶`çÎøîºïbñCgá'W]ÕêâÒ2ä7qçέÎJU¢ðÝï~ëÖ­Ã#ß{pŸ~é§xþ°çLàŠ+Nèè©FˆVå»u"*7“^ï¿ëx·ýÙV–Â1CoÌpóæÍ3öýÂxÓ¯š®xîßÿývüéŸnƒ¦i0 ɤ'* ²^s.Œ+ˆ·c:¬m¨zïåóž§Šiñ¸7!: B£¦Óž ˜Ëë J:ÑhêT¼ e;à9^IÈÔDÂûÍ—}ò¿™C"šV‚¿çÍAt´zÛm%ð[°zµ‰\.øwÝ üA,æyAÍUpœ`†’,ì,Y?N:ÉdЀ×4¯‘AH/Ðô6WÛ÷±§ñ¯kÖàò'xA¯´@y9lÛ†mÛ0 ¶m#›ÍúíY7V¼© ÅžB^]¥]béuf³ ±–‹#ðeç·º¨„ 4­M H˜ÞŒµuøã?¦74!íÄBÛ‚g_ñ ¬˜cžD´& M,BC*åõ%Çñ„€tºt³Lt$IOe½µd2+âq`ïÞ½8üðÃ}±AÎ[¼x/.¿|n¾y–-[†]»–Áuë¯ß‰¯}¦¦¦ðÏÿü"ÞóžÃ iÀi§y^-矿/¾x4, 8î¸ßãä“_Â~p –/_Ž^x/¾ø"Î>û+xðÁ÷aûöíøÀNÄü(^zélÛ¶ Ë—/Çž=?F,¦áþáØ»÷,üïÿ½úÐûpÄû±qã¯pðÁ÷Áq躎t:L&˲F‘L&122‚H$‚T*…d2‰T*Û¶¡iZIT*™¼™ÍfýcGFF0<<ŒT*å;ŠHß,|®ô×ÔëÈÿÁÁAäóy¿/'ù‚%·²Ù,2™LÉõÕs%r®D¸1 –e!•J!N#•J!#ŸÏcÙ²eÈçóˆD"Èd2þµì¢Š+Ÿ‰"‘ˆìØØ˜Ýx<Žh4 Û¶Fá8Ž_Þt:íŸ#÷j¶ëµ­'&^õ>ôз€m”Ý×]`×®3L®A>Ÿ÷½5mf]Îfƒ‰b3T‡ƒp¸QñV”}aOI6ÿ"4†×`”íô™"Í¢-„ÇÑÑQLNNbhh£££%û–,Yâ‹5kÖ`óæÍ¸ì²ËÐ×ׇ›o¾}}}¸ì²Ëæ|MËžøíøÐI'c­†ëºþD£ÑŽœ%BH»Ñ ;0ô¥/û·%Ûøú×ñ¦7y?ÒccAÀq¼|™Õ—Lz ùq—v¬Ìîsï¿,Ð,1Ýóù s!¤„8H§ƒFE*4 ÔE§¥¡" Î{ ÝD+llËVÀyÿûñóŸý ãgœ×Ãk¨kÔB*•ò;¥²Žc.—C:†ã8þŽ™ð*è„j±õÚçnýÞñž‡q E~BÚ’¦¶ ÒÀ¶c¶áA|ù‘BÓØÀ&¤]h†-xlñb¼¡Â>×õúߦŒäó^ÿ^& "ˆ0g4Œ@رc+V¬ØXÌ[Ó}Ù2/ýO~òy˜æw‹ÃÃØššòE³XÌà"‘,2™†‡‡qÓMߋͶsH¥æ×£KÂ4MÜs'PÅã:Çaд\1mO¤ËåvàºëžF6û{¬ŽGIcbb‘ÈÕÅýÿƒóÏâsŸ›€a,E<þed2û‘Íš¸á†³qÔQg µð¥/]†¥Kß]߅͛ߟþtvìø,>úÑEÎbëÖ3p챟Ç=÷œ„< ¯zÕRD£>ó™X¼x1Îø<÷Üñxá…Nkxï{ÿ ·Þº kÖüy¿úÕq8ûìqë­«pðÁ7bzZÇÔÔf|øÃGcl¬€dضíTLLôáì³ P8K–¼Œéé?E¡ð"®»î:|ÿûð ý¸õÖU˜šÚŒééWàÜsŸÁ?ÿóÑøô§ïÂOz"öíÛ‡ýû]qÄã⋟…ëj8õÔ¿Â=÷…sÏ}&'OÇ©§~úиöÚGa+ü¼¿ï}oÂOz"V¬Ø‡¾¾—®ðߟ[o}ÇóJüð‡¿ÇAõùQ»&&&_þòƒèï? ¦ù‚ïD“H$ iš?vll †a P(ßkoª×}nÉ8ÂSý=øÐÀ0Ä'?y&’ÉýXµê%Ž5ml̳#²Þ¢87È1ª G= ËâáX vmH»Ð6Â#àÍ\344ä¯Ã´aì]»W^y%úúú099‰ 6Ì+–óS“Oáû~hæ™Èå¼þZs¹œÿ£=22ÂЪ„4ˆfÚ'Ç_pN]¹²d{.çÍ\´ÈÁ¿ÿû¬][zžZÝ5ͳñ¸g?²Ù@@Ô4O@Ôõ A`^ç$<)L¥ âeqáe¡jUŒ”Eª%å°-ZŶƒ|ÒjZÑ&€8ËþCtÏrv­Ø¶t: ×uýÙ­©bÏв,¿óN©N-¶ ^;ðô ¿ÀË8¥Õ…%„”¥Ùm‚ÿ~êqcÅAþ^Ò.4ÃÜððÃ8ÿü ‚L4Îåq ‘ðú‰„×—–0‡a‚‰É²Ù¤?áPœr¹¤ïРë:²Ù,¢Ñ(N8áy\|ñ'qÄ·!™Lcll ù|étÚ÷^³,Ë_îÉ4MLMM!›ÍÂqÙÃ0055MÓ022â{ܙ汸æš1ÿ\•ÙÆ7ÃÞ¤?#ý¹®Dq‘ýò_¶G£Þøƒ®]¿_ ‡C×—á¯þJ&pŸ ×–.=ŽôõƒcV¯~r9àÍovìg´Éxç¼vó‚ .Àø8pÊ)§Î9çœ{.°t©7ö±g`Ëqß}À¯ýhšwÌ9çxã-â¹ê㜢”Ûû;öX/Hxâ‰#ðú׿¶ Äã‹qòÉ^Ž ‰[nñÒúÉON€®§v, xæ™cqì±À}÷ÅñoÿD£Gá°Ã€#ŽXÇ^~ù<öpÅgâ'?žغøÌgÑ8‰`ÛKŠ÷Õ{¦’÷túLhš½'› ÞkËtÝ@&L’Ñüùç/ª¯Ò.-'±z ¾âgYÞ_*åõõÿâ/Áºugâ”Sþ®ÄÛQœGeŒÐ0‚ðÄ2^« ‡‰ÇïHg°¨P¨ôSÙ¾ˆ±Y½zuM†cãÆò]®àÖ¼øÐoðéËWc`˜˜¨ìjœÍfýRiD" !ƺuëüåNe®v@-÷7ÿúY\ùŸG£NûJ_6+‡YhšUâµT 5¤ МpÙl©$ć—™SÙlа”™T^Ã~Ãsx8ãªëÞ6 #ŸÑkÈ󔆷 3V%F4êÝciìI<~¹Ç² ·Ú˜¼{lšACRbüÁ3T½Xe}Q9_Äb9_ ×+3é*éZÒ¸•¿ÉÉûñÌ3wbÆ ­¾íuш6rÀ¢(pÔ /à¹CAÀ¿ŽüîÜDyop!ë‡TD"ˆÅb ÇNÚš²u¢Ã˜o›àßï¿ß~ì1¼ïñÇ[]BZN/öFGG1::êµ…€Ëû¶ƒžÝê¢4žj E`f,¸Z°í™‹»©×*2ª¯"#²r¾Úø’kHþ$¥ŠÏRf:Ni9dÆ¥:ê;[:@Ðð/wjÍÜÏp^‹ëIõž¨÷6|Y(LÊ©†Ñ —Y\kʹÉHÄq°ã'?Á7W®Äß|üãµ=ÿ6¥Þþôó¤ï­®ÃÆu]?\fpKÄãq¤R)wMÓ`Û6LÓ„®ëE!ÐôRB]Šgñuíd)ƒ:!¡d䳄}l;àäÜZÆ&D$Ú³Q庞 + q«HùdŸÜ9OiЇ;j£¿R§Hf†5 ÑVË>F8Ói`jjæ1Åu@ŽÚ½KŽ9N=¶`pл%##3«[˜l6ë{.Ê„²VžŒ™LŽãø‰º®Ïeì!‹ùµ¬ÕCȸExA]?¯—o™L~.G¥íå“ù³Ÿ=Õê"ÕM#'UŠ~Ü<²r¤jÚ“É$Î?5Ž8âZßK5—åšd›iΜž³CH·Ð‘Âc#صtVúXոȮë"‘HàǷߎÿñøå5×àdÕ•Hm„Jçˆáý¢E¥ßM³´5# ˆÚ0O¥JÌï¬W¹ˆJ4Zúk#w–Æ¹Ú Îfƒ…ꤼaõ!<“/|õžÕòZËu¹ŽjÍäpᎆ\Gî‡<ßðu¤c§æEE”5õÇ :;Bxfb¹)IÕÊî¬Öreú—§a÷<èß‹dÒ»5Ñè~¼ï}™® T¡LÏ~S‹®223Ë4½Û4<|F½W[B»ž)&#‘<ÿd¿ŒqÈXƒi"’åóAu ÛdiЩ}s©²Ïuƒ±iØÉxŽÚ9‘<a^‚ÉÄ"(ÖêáVî5 >«ž©’?1;šæÝ“ð„î0å: êÏJxÜðÞgÕt‰i”±(¹Þèè8BK#ô,îkàBÀ²{ïÅ÷FÎEÔœ_øo –e1¬*!mΧßû^<ùÄ5뛣ÆVö—Ã)î3”ãuZ…ô´YÒšm_­„­’­lç§ÖëIš.‚™p:jëÓU¶£Ì¹º²ß)þ›c§xœ­ì¯d²ÃéVÛ>r´9ž'el´ïŠš¦Ü“J$¤gÙÿØYg58wÆðùóÿ _Llý8ñ “Fn¹k@ J<ÜÈÇK·á>šizT9Ʋʯ+¥ºK傚šòö  árÌ ˶½ÁÈHÐèŽÅª “†á-l5Žãu*µ›j âŽ1Hƒ?œ^Xð¬–N9¤ì€÷<*å¹Z:µä¥Ú~YËc¾×±,ï™NMù›ñÑQììá‚L¨­ÆÐu]8Žƒ\.‡X,†|>ááaÄb1Äb1†Q2¦ ޵J¥J¼'I€i^|‚88—Ó÷ i.€ÓìéÛe\êì³ßŽk¯½ÜÿÉ—Ÿlù ›ájã@„t ½)`Ú¹f4舟N: |êSž‡¨L²7Mï'~6/\¾·¤èIáѺ € üæûoðÒẞu¶ëºîy/˜&N­æ·_KÜÅj#ͳjiªi”›ÑöŽ+GµYVåDÒù\§–ûÚˆë4¢<µt^:é:=ÊO^·‹wïxžy½ ×­×— ;©fÞ¢ÑRSS©Z«¯d8=yíU¯C×õ„HM+íßײĮš™¡z2b6ñÙñ,ôÇŸÆÓ“žúùk`ï«]Îf³Èf³ó×g!„t¶mûžÉYqx¢¢^üŸpï½À‰'‹v[o &רA%\7ðìJÃZ«¤RÁ¤ù¬zõËï– X$@.YšN>Œÿ'ÁœIõõ³Pî:ácÊ]'Ý„ëd\Ñ[2ϱGæTÖsß$Ü|,V¹<²?—+½ŽLv’ó ﳺ ^*,ÿ&ÑyÔHUÞ¥ðû&Q=M3(sjpòÿìÿñŽ“V1ZÄIGþxßûГ¸À‡¾ ° k¦W™eÄP¯/3éÊ¡zÕûaÒ ™ 1jÌþzH$JgáI¾Ú& Ë}PWkWÁj¡ò&i¶sÙçZžn)K<öØâ’e0Çq`ë‰išÆÈÈÈŒÈ&ôRl SIûwÛð!{ÏÌÙ[î»oûöyë>Šï‰˜V¾›¤×éIáÑî޶lÜ{¯ÜÊ¿Üâ"™##3ô–eùqØ !]€Õxyé3¾·c&ãu( Ã`hÄ6 –q˜¹ÂÇJ*’ðòã8ij'œÿyG>tbŸ¨íTÛ¶aÛ6¦¦¦000€X,Ö¡š é%LÓD^ʘ $´¢æ ˆE"âˆg}¸š«cñZ»\Ð Y^-üYÝ/éÈÒ`弨ÅÁBòž3%ÇÈ`‡LÜ‘• ÔÐß’_5Ê¡36wêJ²¦±#áÊÃ]ä8ui 9Fë ¢ÈŸðÜsÏÁ0ŽB>_ú¹Ú} cS•z-áñÇÇ1ÇìG> ```òù¥3®#Ñf»Žl“÷@½Žœ÷Ío>‡£Ž: ŽãàÊ+_Âi§Vry—äÞ—{—®¼òÀyç—^z¦yþŒë$“÷båÊ•xŽÂšmÀûÏP<ì˜cvcrò9 îÄþá¹øÿ@ïbÿuÜs8ëÅG½p¤òbÎ¥)»œr1_ÔÚE8¤©ax y-}Ãß³ÙÊ.H­Dfƒ,T@ŒV7 Ƙà¿XâMð€ XÞ”ãºÀÈÈ4ËBß=÷à §ŸC–.R'Œ—[ê&ŸG$)ù?0A&“eYÐu½ä\Ûöò‰Ä166†H$‚±±1 øi$ ßûµÜ¹ñxÜ¿Ž—Æ Ÿgõ\H§½Ï¹\®x"˜˜˜ÀÀ€w½ÁA/¯étÚ¿7êõb±†ý¼©çÊúa¶mû¿7®ëbûv–e!•Jù÷dpÐûŸHȽò®—Îåf”Ó², ÑÞn§7¼°Þò4pef~Þ…¢ôK¥F´ ÂUb>K£3ïI;/P^¼¾ÑtÓH²Ì¨ xøá£`|0ðoC>˶166Ã0pÓ{ß‹³ö3œ¶|y0É€´†àû;‚ å~ÏÔÐê6•p¸Šr6NΑI&á÷@Þ uÝ™0r9¿Ò1ꂖ宣¾‡åò*kÏFx»Úõb?ã½[Y;‡Œ²àB.'ð0\rÉ}¸øâsü}œÓAˆGï pÇ=‰Ó¾ú$¾žzÆ8$.:ŽƒÁÁALLL0F;!Ý„üOì<¼ögwúḯÎ3< !=H ÀÀë±ëþcÿèJ|ìCµ&k@‹‡#½¥ éŸ÷5 ©TÊ¿¾¦iþ55Mó¯•Ïçaš&ÆÆÆ ë:&&&ütu]‡ëº%vÕq$ж|>Ã0üs E—N)ƒ”O>ËÚ»®ëz^+šæ÷ñ …‚Ÿ7¹Ž¦i%ý?9wjjÊ_ÓË0 ÿºå{!éKyåœhQÄ)×Ï”cÆÆÆü<ðCûÉó(7ÙEŽ ÿw¦iVœPë8~ñ‹_4öåï rßvíß…¡súê i*ñue@¹»åV"ü®Ö²ÌL±oR¿D<— üz(Qh²Ù,‰DÉÄŠX,æw]ׯò~g³YÄb±’ÿª½•<8Žã×ÁF¡Ú‘j÷ \wÇ)9_ì–+íM)»¤•ÍzHÊÙ<¹Çr/,ËB4õ¯%i÷õõaÿÖ­ØoY°, _|1öîÝÛÐ{Ó)¼zéξýS@&ÄbÈårH&“˜(†W~Ûø8–ÏöÎ7j‰ j޼NÙ$ð¹ÌžF¹Ð åòZ-¿Õ¼¼Õ õ\§Z†Q=/µŒoU»'ö!Gã¿ÿþ²ï/K¶çrÀ¿üËÓØ±ãAôõ½i†c/‡éEá1 L¦ŽÇK]\HD£Þ ÒÅY&®ë"NÃu]$ ŠŽ„tÅÆÀÎ"8©?èCKÇâ!=Æ0€ïScÏᦠ~ Ã8¿¦Ó¤­@/GB:—å“ÀÞ½ÀùÿÄæâ[¢£D£QßûP„Åt:틃©T ‹-BF ÏCïOÌd2ÐuÝ`ÖuÝዌªð%ƒ¢"n–P—}"ÞI{G¾Ëä+ÉK&4˜¥Ú:IKÎ §=’NxÒ†ô¹*…«.wýp›­ZNDPõzáÏ•lºzL-!µÕ¼¨×-—^-i„¯;×ßžj|t]ÇÑG=§4» ûÀÞçàºzÃ¥×2˜ÜdÄ–È;'ßE´}}}8Ö²J<ñˆÎd2ˆÇãEÏè´/ˆ}ìškðÚ·¼¥ÄëWÚE¹\κǀP€IDATA$A¡Pð½wUOc™p Â[.—ÃÈȈyJl©mÛ°Šy<û+‚›\¯j]€¦i¾·±*|ªùN&“~>§¦¦°lÙ²²ÒJDÀ‘‘¿¬‹-*{Ž\/“ÉøÂ–x2«iJ>ÆÆÆN§¡išï±Ç122×u‘UB-Jy$?©TªäÉä9NÄÇÇ9'ɇzÏ?ÿ|«_Û–é³XÓü:캮?Dî/!¤÷xè•§cäÃÆaOv]à}ïÛßüæEüþ÷+ñ¾÷ÍŒjÛàù-„t$='<:˼ÿ}i9Ì1!BгÇA.—ƒëº~'žÒ=ØoÞ`|èTœýêâ6ÛF"‘àÚl„ô"ðð/à…ÎÅþƒúªnÛ6âñ8b±˜ï DéL¾ð{àè_Ío]aãñ8øÞ‡2˜ŸH$ ë:¦¦¦À÷,ÆÆÆTË*µI,Ëò=÷!õ³üÑåxzß6ôá[0Œö[¯P¼˜ÃžÑªh”Fo±,kFHbšlÛF*•*IC×uº®N^õˆ–Í'ŸsŽïí¬z+ŠÐžËå0<<\âµþ_)C¾è…þ_ÖåÜð)‡LÚPóªz J™MÓ„a¾—s¹|‡=¥e‚H-eÍårˆÇãþ:á•P½¼Õ´dœj¶É2E&‘HÕ&hŒŽŽbtt½Èök®ÁŠ¡!^/[BHoóó׃§îÿ-W^‰\Ú“r9`Û¶_âÀŸáòË?Óœ)<BzQx|pœó{|êòÀ0Öz•Æž„ ‡Ø!„tîcáhw÷Þ»Ì_‹;›Í–Né.Éâž#ß 8'ૈ–eùÞK é|î]˜/UÞ/ò®ë"‰ø¡îÄ‹€²SB…Öâ±7_t]÷½\!aßáû°üèoâš%µäú¶mûÞ{ªwZ"‘ð=ÜD<ï?'´Ö—„]´h‘?ÉAlR¡P@$ñ ‹qå¨$à…=¢ËÙ;¹–„n§µCUoðråÛéÙÚyµxJφ„m&í‰]\Û‘Bö¾p"Î}8˜D’Í¢8–øz|üãpà€çÓDGBfÒsÂãÝ_xû^§aR+ßÐN§ÓˆF£œÙDH—â>~"úìè[q ã0?Üëþ7å÷‰·Ž„ªS×P,×Wh–]`HxBËîcvãïžÝ€äÙ»ì®ë"—Ë!úv%‰øvDÖ;”µMÅóN< ÅÓ­ÚºÒâ -k¥ "fª­V'êZ¯š¦ù!ZI)Æ6ì OÚÇqü¸„òË×ãÇ/¹ˋ’⺞ÐxÿýÏaåÊãp Þq ™Io .ðÜ+&ð¬}¢×Ÿ=c·eYH¥RìÐÒÅØož}áE\sÕaà‡"„ô _¶`]òÇ8âÁ=xù™á²‡$“ID£Q˜¦‰ÁÁA†a'¤‹ø¯Må·çr9ßE¼ÕP}„îañÞ½€Â«_¨;- e*B£x-NLL Nûa<ÅKº’GØ›¹FcÑuÝ_—PEBŸ6Uh’ÌDÞÒ~X–5ký$„ôNþ. rNÝ· ®î…X5MOx|æ™'pÅ'@LM!3é-áÑî<‡Úû¡ë‡ÍØN§ýxþ„îd_aöÚÁ4WøÛóY܉ÒùÜmá»û3<ÿ­Wࢋž*{ˆ¦i°, ŽãøaË!Ý‹ã8Èf³0M“íBz€'~4Àü“·Ìù\ #šËåüI âYè8 ÃðÛµ¬ËW/•Â=†Qf´YPx¬ŒxÑ“ö#™L2 .!`kpª7Ñq<Ñ1›>ô¡Ÿ8Žvœ*ôœðø»áå8îó;üAÉ®d2‰D"ÁYg„t9=µ¯Àk!NŽÉdrÖ5™!]̤œ}Ýü<>ùå+fì¶m¹\™L¶mSt$¤ËI§ÓÈf³ôl&¤‡Ø¹b‡5§ßød2 MÓ`Û64Mó×}VE6ñükæ ¤¦ie½²5MkIÈSö¯*ÃÁêöĶmäóy æ„à\Xg†EùúrÄã^¨U]Þð†Gq×]‡·:‡„´==%<º¯v½j1.8îgáÑu]¤Óiض͆1!=€«ý/î^ÃôêÿÈÈë>!=Šó¾<ž=xßq¿0sHB¡Qp$¤»qñxÑh”^„ô‡~öâÛÐõÙ'¸®‹H$â‡J5 £-½¢)h2²Ù,†U'„øÖº‹±=±fq eönÝ\.‡Ÿÿ|¤Õ9$¤íé)áÑ~8è5/âŠ3_åo“u8È@Hoð´v.x,ÃøÒé,r¹ÆÆÆZ-BH³qkðà<…õï]Zöñˆn…—!¤yX–…X,Ã08Ñ€cïÞ½0ŒÊbLL0 ©T †aPÜ#¤Kax`Bˆ`»Óp^õ€eÁu|0 ÷Ý÷"^z‰ýBj¡§„ǯ?¼<ö œuÖ‰þ6Û¶9 HHpÖcgá‹Æ98ö¹WðÖ;‰Åb­Î!¤XÀï=‹^ZŠ×¾ëÈ’]²Æ[4¥AH—“ËåN§^•夓NªØày?±=@HwóðÃã/þâ/P(ZBH`ÿã•8eò¬8ë­H&½µc±$zER+=%ÃÃ)N#—Ëadd𦱝@HpôÑGs!ÄÇù>ðS¿Á‘}‰\X¿~ÞúÖ(Û„̃Zf±ä—ÏàG­Â9OýÂß6<<ÌõÝé!¶žáy:^öú>ض±±1Š „ô(öÔ{ðÜɯÀ?ñÝ’íét®ëÒ»Àu] ÃuÝVg…Ò¸®[VU×u0Ò#|ö³Ÿõ×x$„¿êeÜß)˜ž>‰°wïzd³Y†c&dtœð¸qãFœwÞy8ýôÓ±~ýzLNNÖtÞôÃÏ`Ÿ¶'ºGð¨\|Nd¾v`×Twù¡“!Ë|mÜ0ø.”{óî ümÙl™L†!˜ é ê±²Î;'ÒùÔc Ot´mÛxÀÉÉ„t&óµ×\s ‰D«³Oiõ¶ à8øÙùá¹_.ÁªU‡cxxb±m!s¤£„Ç7bóæÍذa6mÚ„ÉÉI¬_¿¾¦s¿qÔrÀ>úWg!—ËappÐBé걇î’qÄ~Œq¦!L=¶à¸-¿ÂÿD/Æ¡?ý% ÀëºþºŽ„Ρ;ÉdÒŸŒHé\êµ€ ɲ,ŽÒÁÔc ^ùÊW²îÒ4¢M³,Àš•y8ɤ0<<Ì1DBæHG [¶lÁš5k°fÍ ᦛnÂøø8¶lÙRõÜŸû8îÞ)¼üò3Ð4 ÁÒ¡Ôc;ì0$†‡‡aÛv«‹B©ƒzlÁÖ'i½oÞé­ë–N§Ç9!£;ù|ž΄tõÚ‚t:T*EOB:œzm!¤ó©Û¸.¾xðÉ@øð‡_ÃHÂ4MäóùVŽ£c„ÇññqLNNbhhÈßÖßßU«VaëÖ­UÏúe«ï߇t: ˲F[]¤9±qãFŒŽŽ¶:u1::Š7¶:u³nݺVg¡g©×zè¡0 ccc;ÐØ ïí©—zmÁ'_sÏÀÿúó@4ÅÈÈH«‹U3Ýòþuƒ=ë†2t*õÚ ÷–\èÛ1Wz±žöÒ³®×<úè£Èf³Ð4­glëDïÐKϺí‚^£—Þ¡Æ"æC¯<ëzíÀøø8~÷ñ,¾û——à]ßx/¿ü r¹4M똥ºáYwC=í†vÇ<€{î¹§®4^ÑêBÔÊîÝ» ÄxÀ’%K0>>>ë¹Ï>û,^õów±üõgÿ7^ùÊWvÜ ¼cÇ<ðÀ­ÎF]<ðÀرcGÇÝû0»wïîØ2<õÔSþ_'Rò¯]»‰D¢c×méä÷O =k=<ð¶oߎƒê˜ùG%ÔÛ&Xñ_¸Ï.Á3<CCCØ¿?|ðÁV«f:ýýºÁžuržþylÛ¶ ÷ßÿŒºÔ ÔÛ&ؽ{7>ÿùÏãÈ#ÄÉ'ŸÜêâ4…n±s¥“ëé|™Ë³Þ¾};öìÙãשN£^[055…~ô£pO<ñD«‹ÓX'z‡¹<ë^ïÜqÇxàpÖYgµº(M£mA7ŒĖZŸu¯¾ð X½îZiíÇóÏ^‰n8·Þz+öïßß1u¥êu7ÔÓNowlß¾÷Üs8PW:#<ÖÃy營ÿüç8õ¼S±mÛ6lÛ¶­ÕYš3}}}xòÉ'±k×®VgeÞ8p}}}[é„•+WvlvìØ;vàÄOluVZ‰'žˆ+®¸®ëvì3ìä÷O =k=÷Üs^z饮˜ 7WÎ;ï<üò—Y,šÞ†Gâ5¯yMÇ=ÇNÿ„n°g\†gŸ}>ø 8€Õ«W·:;MÇ0 ÜyçèëëÃgœÑêì4…n±s¥“ëé|™Ë³~衇0==Ý“¡ÆW¯^ééiÜyç8óÌ3qôÑG·:KMu¢w˜Ë³îõþÁ¦M›ððÃwtu®ô¢-膱ˆùPë³îõ1Ã3Î8{nº =ò¼ú¢spÌ1Çt\é†zÝ õ´ÓÛ=ôž~úi¼óï¬+žßúÖ·â­o}k«³Ai17ß|s«³@i1lBàïÿþï[BH‹éëëÃý×µ:„Ãþ!¾úÕ¯?]Õê¬Òt\ …r®Ñ«V­ju¶!M„v€ÐBh!´„€¶€B;@H»Ð1£Äg/;::ŠþþþVgÒh!m!„v€âA[@h !´„´#<Àš5k°yófLOOðÂ&öõõá²Ë.kuÖ!M‚v€ÐBh!´„€¶€B;@H;±¨P(Z‰Z™žžÆÚµk1==¾¾>LNNbÆ X³fM«³Fi´„€¶€B;@ñ - „´„ÚBÚ‰Ž…ÑÑQÀêÕ«Ñ×××êìBZí! - „ÐBQxl»wïžÑ (¼—øø€ÿýÿð 7Þx£ÿý÷¿ÿ}ÉyÕö7‹l6[xç;ßYö…­%­,Ç;ßùÎ’k …Â>ðÂ×¾öµŽ)é\j±ôþU²P†FØ‚V—t&jÔzÌBÓÉm‚B¡º-è„2m†v|‡Ú¶´[™›e‹Ú­ÜdvšÙfh×w£[Ðiu¢YcíTfRÍSlÇ÷ƒm‚…«h·r7ƒN(ó×¾öµÂÊ•+ý¿NëcwøçÖ­[ +W®,lݺuÖruŠmiÖ˜ C­¶ˆÉÉI aÕªU%ÛW¯^ééiÀøø¸œÐßßU«VaëÖ­U÷7‹ññqd³YÜpà e÷UËc+Ë199‰ñññ’kÀM7Ý„5kÖtDHgSÍtÒûWÉtBa Z]Ò¹4¢MPë1 M'· €ê¶ Ê@º—fµÚñ^hÛÒnen–-j·r“ê4«ÍЮïF=¶ ÓêD³Æ*ک̤vš5¦ØŽïÛ«h·r7ƒN)óÐÐ6mÚ„M›6Í« ­.g7Œ{öõõáꫯžQ•N±-ͳyEÓJEJXµjÕ ƒ1==;î¸ÃÿáØ½{7ÌøqY²dIÉN¥ýÍ`zzÿøÇ‹ÅÊV¾je¨õ˜…Bâ÷÷÷ãºë®Ãää$úûû±fÍ¿<í^ÒÙT³òþÍf :¡ °í`“IgÒˆ6A­Ç,$Þ&ªÛ‚N(é^šÕfh·w¸¶¥Ý~Ûe‹ÚíY“ê4«ÍÐnuBÊY-¨¥LíT'š5VÑŽÏšT§YcŠíT'¤Œl,ÌXE»=ëfÐ)eîïïGÿ¼ËÐêrvøg?6lØÀÞvïÞÍ›7cÕªU~ž:Á¶4{̆m–-[på•W¢¿¿±X¬ÕÙ©™l6‹%K–àꫯnuVêâÊ+¯D__V­Z…ÉÉI¬]»¶­~dHï@[ÐZh H;@;Ðzh H'Щ¶b®t“m™+´E¤½b€Þµ´¤zÅôªh H÷ÐéöjãÆX·n¶lÙ‚Ë.» }}}­ÎRÍ4Û†Òã±ÅLNNâºë®Ãèè(®¾újÄb±ŽyaGGG±yófÜvÛm­ÎJÝÄb±’Jgš&6oތ믿¾ÕY#=mA{@[@Z í@ûPÉ\z饭Î!m+æJ·Ù–¹B[D*ÑKvèm[Àþ ™^²½lÚÒùt‹½ïÍÑÑQ¬[·}}}¾§y;Ó JÇ2>>îÏX±, 6l([áÊÍ`QÝa«í_(FGG±dÉ\wÝuX·nÖ­[ PþçR†V–À q饗úá :¥ ¤s©Å´óûW«-hç2°­.éLÕ&¨õ˜FÓMm º-è„2m†vx‡›m[Ú¡Ì*ͲEíVn2;Íl3´Ë»ÑH[Ðiu¢YcíTfRÍSl‡÷ƒm‚æŒU´[¹›A7”¹ÝŸm§{ÊZ«*CCCÂèèèœòØîc·µæ±–c(<¶õë×ã²Ë.ÃM7ÝT6V³ÄÊ /Ì9::Šþþþªûš5kÖàúë¯ÇÕW_íÿÀe—]æ®%­,ÇêÕ«Ë^[ýñn÷2Îg6[Ð ï_5[Ð eh„-huHgSo› ÖcŠnhÕmA'”t7Íh3´Ó;Ü,ÛÒNešg‹Ú­Ü¤6šÑfh·w£¶ ÓêD³Æ*Ú©Ìdn4cL±Þ¶ v¬¢ÝÊÝ º¡Ìòl;}ÜsË–-X»ví¬Ç´»miŘ …Ç1::ŠÉÉI_WÿTÅxÍš5ؼy3¦§§7ß|3úúúpÙe—Õ´!‘J£þ(YXµÖ<¶ª}}}ÂÆýkŽŽbË–-%!ŒÚ¹ ¤³©Å´ûûW‹-h÷24ÊÐùШ6A­Ç,ÝÐ&j³í^Ò½4³ÍÐ.ïp3mK»”h®-j§r“ê4³ÍÐNïF£lA'Õ‰fŽU´K™Ií4sL±]Þ¶ ~¬¢ÊÝ,º¡Ìíþl»aÜóÒK/Åôô4n¾ùæ’rŽŽ6¼²P´bÌfQ¡P(,xÉÈ 6nÜXò²ª ùñ‚§§§±víZLOO£¯¯“““ذaƒïb_m³9ýôÓ±iÓ¦’¶–<¶²“““X¿~=ÆÇDZjÕ*ŒãꫯƆ :¦ ¤s©Åtâû¶P†FØ‚V—t&jÔzL³èÄ6PÝtBHwÒÌ6C;¿Ã e[Ú­ÌͲEíVn2;Íl3´û»1[Ðiu¢YcíTfRÍSlç÷ƒm‚ÆŽU´[¹›A§•¹ûØÝ2î¹yóf\wÝuèëëÃ’%K099Ùñc† ý>Qxì$^ðêÕ«ËÆl¯¶¿¨%­,‡\»¿¿¿¢‹s»—t7ÝðþuBa Z]ÒÝtB=ê†2T³PÒ»4êýì´w¸ej·27˵[¹IcèÆ:шrwZhÖXE;•™4–n«(s£îK+Ê´ÐcíVîfÐ eî†gÛîe˜œœôÃwû˜a#ž…GB!„B!„B!„BHÝpGB!„B!„B!„BHÝPx$„B!„B!„B!„Ô …GB!„B!„B!„BHÝPx$„B!„B!„B!„Ô …GB!„B!„B!„BHÝPx$„B!„B!„B!„Ô …GB!„B!„B!„BHÝPx$„B!„B!„B!„Ô …GB!„B!„B!„BHÝPx$„B!„B!„B!„Ô …GB!„B!„B!„BHÝPx$„B!„B!„B!„Ô …GB!„B!„B!„BHÝPx$„B!„B!„B!„Ô …GÒR\×…mÛ K˲¬Ë«eYp]·%×®—vÏ!s¥Òû\ΦÐ6”§óFH#˜ë;>—öÈlõ~>×nçûBH»³Ðm‚FÙ†v®{íœ7Ò›4rœ@Ò[¨6ÀºOH£¨·îÏö>‡Óæ8AeÚ=„Ôë~óî …Ç$›ÍÂqœŠß;×u1<<ŒeË–appƒƒƒuw,lÛF$Y°i-¬ûåÚ³¥Íq‚Ê´{þHm°¿PÖýæÝ H.—+1áï@2™„ã8˜ššB¡P€®ëH§Ó­Î!mM7Ôýzp¹\ÃÃÃ3öѦ^¥œè5ÛP/–eÑ^Žƒm‚…oÐ6N£Ú­nÓ³Þ“N¤×ëþlm‚zÓ&¤“éõþi=¯hu×u‘Ífáº.4MC,ƒ¦i¥_×u˜¦ ˲‹Åüs-Ëò]L£Ñ( Ãð÷%“I$ ?mÃ0Fý45MC"‘˜ó±Õsr¹ïVýnšfÕ4’É$R©Òé4 Àiš3¶Y–5ã˜jiÖZFy&cccþ³H¥RÈf³%ùSŸ<Çq`Y¢Ñ¨ßP0M³lþ\×E:öŸÝ\Î˳Ð4­äݨöÞÕòlÔwÐqœ’÷R¡¢æ¿–såžÔ[öN`!êþ\ër»×ýrõ¼œ}¨–f­e¬Vg«ûò\¤¼åžu%›Rîx± š¦5Ô.¨Ï*lZaf;_×õ’ûш²·;ÕžÁl¶¡Qm‚ù_‰°]0M³ì¶Ùhu› »0×ßõp»@¶ #Î:µÚ©î³MP û3éäº/Ï¥Ñm‚p½m„mhEm‚Ú`› <Õì@+Ç Ôü…mC·· Ô² ¬ûóƒu&­nÔS÷å¹”kÔš¶zl·!ÎÇ.°¿À1D5?­jÔRÿªMЫu!Ú]íñèº.üÊŸËå|—Ñd2éßD™£þP¥Ói¶Œëº,ùa’ý®ëú TÕ•6Nûá9ærl3H§ÓˆÇã%3ÂÛÊS-ÍZË(Û Ã€mÛ°, š¦ù/½\[®«†:qÙlþµ"‘ÈŒû'ÛÅÍåÜZôϳ,«dfÕlï]-÷Q%Ü€ŠD"%Ç ûïeµs4¤ìÀBÕý¹Öåv¯ûµØ‚ZÒ¬µŒÕêàlub±òù|É$Pݦ„ß Õ64Ò.•mC«ìB-çÓ.xÌfÙ&˜Ïñ I«ÛõØ…¹ÔßríˆÇãˆÅb~#{¾´[Ýg› €ýòtrݦM ÒÛЊþÛµÁ6AeªÙVލù Û†noHÙUX÷çë~yZÝ&¨§î•Ûµ¦-Ï´ÛÆëµ mÀ1ÄVµ j© Õ&èõºßÐz_èbòù|A-âÔÔTÁ4ÍÂøÃ€ÂÄÄ„¿O×õ‚iš…B¡P˜˜˜((Œùû3™LAÓ4ÿ;€B&“ñ¿†QˆÅbþ÷D"á§7—ckÁ4ÍB>Ÿ¯ø½ ‰DbÖm厩–f­e)(˜¦YÐu½ ëzAÓ4ÿ~‡¯Édüs噦R©’ý ßüæ7 SSS3®_íÜ©©©šÊ˜ÏçýwA}¢Ñ¨ÿ®UzïÔãg»†JøÝ§“H$ Ñh´ê¹³•½–|u U÷çZ—Û½î×b jI³Ö2V«ƒ³ÕýÙžo5›"Ç—³ õÚ¹ÕlC«ìÂlçÓ.Ï@ê~9ÛÐè6Á|ŽŸrv`.¶¡Õm‚zìBµsg«ûr¬as¾çRF¹ÇíX÷Ù&` <\÷g{¾õ´ ÔkÕkZÕ_`› 6Ø&¨L5;ÐÊq‚r×ÛÐÊ6äk!ûr Öý¹Ãº_žV· ê©û³=ßjiW³ >†8_»P­ì½d8†Øº6A-õo¡Ú½Z÷¢ÞwµÇ£ÌT‹Çãþ¬–|>»ï¾¦i–Ìd‹F£þg˲ ë:\×õݥ建8¨z¾¦i³ºÂÎåØfPÎM6¼m®®´µ–Qq411‰‰ Äb±U_½v¹‡ªk¹¸ÿæ7¿,âª>ÓjçÎeÑjÇqf¼?ª‹}¥÷®Þ™“ütd6‚eYs S®ìÝß{!ëþ\ër»×ýZlA­÷»Ö2ÎV«ÕýrÔbS€ÙmC½v˜Ý6Ð.´žÙžA.—«h¢M0Ÿã’V¶ „zìBµú[®îË ÍL&S÷ýcÝooبL§×ýrÔÛ&h”mhUv¡6Ø&˜jv •ãáë‡ë Û¬û³Áº_™v# _¿‘í‚nC¬×.T*{/ÙŽ!¶®M T«nÌåüjtjÝod½ïzá1ŸÏðÜJ-Z„x<^õf;ŽãdzUÿº9–u3‘û¨†6H$¾¡žª¡2 ‰Dñx|ÎçÖ‚÷¸•Þ»FL&±hÑ"¤Óiß(ÕC«À Öý΢Þ÷°V›2Û0Ÿ<ÍfhZÏlÏ`6Û@»ÐêyÃç–«ûÙlš¦!—Ë!™L¶m8Žã‡f™ ¬ûí ÛE«Û² ­ê/Ð.ÔÛíÉBlÌ÷¾u ¬ûíÉBÔýZÒ¾÷Þ{tïb£íÂ|ÊÞ)°¿Ð9,ô8A#¯Ý-u¿žó»Zx”…;3™ ¦¦¦066†\.‡GydVãa†¯2ËßÈȉČõ?Èܙ텭õeVŸŸÄ2™Œ¯ÎWŠß\éÜZÐu}Æ 5Jï]¹Å«ç‚¤111|>L&3ç÷±Þ²w ¬ûíM£ßÃZmÊl¶¡yšÍ6Ð.´žÙž¦iËM»Ðêy«[®î×»Hº ë~{Ã6A{Ónm‚FÙ†Vôhj‡m‚öd¡Ç ¶ æ{ߺÖýö¤u>ç}ôѺs ±v¡eïØ_h_š=NШk[÷Yï»Zx”E_åéºMÓJ¼›¨>TÓ4gl“KÛ…ðCï$ãot]/YÌ4™LB×õš+Cx1YMÓpî¹çúÛd±èt:=c–b¹sçÒшF£% ¯Êì¡Ò{W+ê{©.îêº.4MógK”›ýUéÜre—{Þ3qX÷Û›zë`˜¹Ø”J¶¡yšÍ6´Ò.Ìv~¸ì½hïÙU² h*mkgꩃµœ®û¦i"•JùbGR©ÔœC›´kÝg›Àƒm‚ö¦ÝÚ² ­è/°MP;l´' 5NÐ-m€u¿^X÷Û“FÔýù¤}Úi§ùÛºm ±v!\ö^´ ì/´žf4êÚ@çÖýFÖûWÌë¬!‹!—Ëa``À7†aàšk®Á±Ç‹H$Ó4ýƦ›zÎ-‡ã8¾[t¹YXá÷®Vlۆ뺟g8ï²x±¸pÏvn¹ó»Öýö¢Ñu°ÒýšcS*1›mh…]˜ÏùÝL¹gP‹mè»Pi[»ÒN¿ëõÒnuŸm‚òee› =hÇ6ÁBЊþÛµÃ6A{Ò.múzXˆ6Àºß(X÷Û“…üín»Ò‰m‚rit3ì/´­'`Ýo\½ï á1Œ(Öccc¾â‰DH$Zªø«†ªÕx#ÒXÈôêE­ü<·ål·{Ù‹tkÝ_ˆwk!Ò¬§þ.´  mhe›`¡~×ëu¿7èÖzߨ42= =Û;­¸©N·Ú†Né/̶ H½°îwæáBRÉ®Ð.ô´ ­k´rœ€u¿qtu¨ÕJèºî‡P° âjÚJ*ÅÝU©63§i,dzíJ3ÊÙ+÷²éÖº¿ïßWÚ…^‚¶¡9ùéX÷{ƒn­÷Jc!ÓëDhz‡nµ ì/ÌÖýÞu¿9ùéhzÚ…æå©`ÝŸ;=éñH!„B!„B!„Bi,µ:„B!„B!„B!„·Â#!„B!„B!„B!¤n(<B!„B!„B!„Bê†Â#!„B!„B!„B!¤n(<B!„B!„B!„Bê†Â#!„B!„B!„B!¤n(<B!„B!„B!„Bêæ­Î@3øêW¿Šo}ë[X¼xq«³2ovíÚ…Å‹wtöíÛ‡}ûöaéÒ¥­ÎJ]ìܹË—/ou6êâàƒÆç?ÿùVg£é¼ÿýïÇK/½ÔêlÔE7¼´gíÁ¾}ûðÇüÇø³?û³Vg¥©tC› Þ? ;ìY7”a÷îݸ馛Ðßßßê¬4•¿û»¿ÃÓO?Ýêl4•n±s¥êé\™Ï³>öØcqã7¶:ëMerrëׯǒ%KZ•¦Â:Ñ;ÌõY³йýƒùЋ¶ Æ"æÃ\Ÿu¯Ž¾õ­oÅqÇ×êlÔE7Ôën¨§ÝÐîØ½{7Î=÷\üÃ?üüÓè áqÇŽ¸öÚk144Ôê¬Ì›7bhh¨£Ë0::ŠÑÑQlذ¡ÕY©‹uëÖaÓ¦M­ÎFÝeèE^z饮xv^Ú³ö@ÊÐktC› Þ? ;ìY7”aãÆ˜œœì9áñé§Ÿîøg7WºÅvÌ•n¨§se>Ϻû“““bèhÿjƒýƒÎí̇^´Ý01æú¬{±MO>ù$þû¿ÿ»ÕÙ¨‹n¨×ÝPO»¡ÝñùÏwÞyg]i0Ôj‡Ðßßßñ31—,YÒƒZ«V­juHÓ ïí!õÑ-ï_7سn(éºÅvÌ•^¬§½ú¬Im°Nô½ø¬IíôâûÑ có¡Ÿõ|8ꨣZ…ºé†gÝ õ´ÚGy$úúúêJ£'<»5kÖ´: u³jÕª®0€<[t>ÝðþÑžRÝòþuƒ=ë†2Þ¡[lÇ\éÅzÚ«ÏšÔëDïЋϚÔN/¾Ý01zñYχ“O>¹ÕY¨›nxÖÝPO»¡ÝqòÉ'ãŒ3Ψ+ z<B!„B!„B!„Bê†Â#!„B!„B!„B!¤n(<B!„B!„B!„Bê†Â#!„B!„B!„B!¤n(<B!„B!„B!„Bê¦éÂã•W^‰ÑÑѲû6n܈óÎ;§Ÿ~:Ö¯_ÉÉÉyCi*ÙÚBz¶ !@}¶€v€îýBû„€m‚^Âà.`ú¹V°‡iªðxóÍ7c||¼ì¾7bóæÍذa6mÚ„ÉÉI¬_¿~ÎÇBÚŸJ¶€v€ÞmBPŸ-  ¤{`ÿ€Âþ!`› °æp¬]ü›Ëñs!Ýê›ÑDœVg DS„ÇÍ›7ãôÓOÇÆ+³eˬY³kÖ¬ÁÐÐnºé&ŒcË–-s:†Ò¾T³´„t?lB€ÆØÚB:ö!ìB¶ º……ÃŒ³‰mî<ÒŸ«÷å\Ä>gŽùIÎ1ýá9æ=[gÙ«Ñáqhh›6m¦M›ÊîÇää$†††ümýýýXµj¶nÝZó1„öf6[@;@HoÀ6!¨ßÐÒ°@aÿ€°MÐ-¸˜›€5WqÐF©Ge¶Ê±ê¹ÞlÌÅCÒÁÜÄ»l(/V•²çæpoDÔTŸí\;TV@|e¯…W48½²ô÷÷£¿¿¿âþÝ»w@‰a€%K–ø®ÕµS‰àÀ’%K°jÕªf™¶drr“““xî¹çZrýÙlÁBÛxî¹ç0::ZÕ&Ò팎ŽâÀš~ívi”;Ÿ^bzz[·nÅŽ;ZrýzmlŸo›`ß¾}eÿ€ô<ãããØ½{7öíÛ×’ë·º°cÇŒŽŽbõêÕèëëkÉ= ¤`ÿ€ýB8fÈ1ÃF0—0«€'˜iÊ÷,€hh[8ýDè»[áxÉ‹*¦¤fÉKX¬K‡®§’C©G¢ˆ¢³ }7ÊõõPÚvèœjùpŠé¹"¦Ê”EPG¹fV¹_ãã㛘¨»MÐÔ5[Åþýû1>>ÎÙ ¤ç™œœÄèè(öìÙÓꬴ„={ö`tt” K“žgttãããØ¿«³Òt¤MPn¡zBz‰Ý»wctt´eÂc«á‘ýÒëlݺ£££-[2XIH¯Âþû„pÌc†å˜O¸R{ç‹p(„Å¿tèXõ¿¤­¯z ÚJšrül’9” §aïJ§L~œÐ÷J"ôÍæñ˜,æa°øYSöKÞÐñ¼«áã“ÅsÔ{–,þÅ‹iiÅí¹âŸÿÕ§žÂçO=ßø£?B=4Åã±Õ}ôѸä’K8s‰ô\vÙes:†Ò¹ÐBÚBˆGµzN;@H÷Ã6! - „Ð4 Õ³O˜MxTCÊù•Ödt+œ*ÅÓPBÙ*aW%,h˜&Çš(,%¤«Ú/âa¬ø}ˆg!ð24x0Šbž˜¨¦/^‚"ö‰Ç ^LW‡'æ @%_Ñâ¶X(¿" ªŒ(ÇHHØXñ| ¥!lub"”ÏSÅt€R¡VC äÊñªèY/m³Æã† °víZ\yå•èëëÃää$6lØ€¾¾¾9Cé\h!m!Ä£Z=§ ¤ûa›€ÐBh¬ý”yÆ._΃QÄEñ@t‹ÛdCUì¡R<EøS…= AxUES…º1aOÅcQÖ/ ¯A™RÒJ*ùœ€çm(œ„^±ÐA°&£^̇xBØ'ç‹Wd¥åDx 7Qž°)ÞŒ•ȇ¾'f9Ö²,˜fpe­Êñs¥éÂãÃ?\v{__n»í6!ëÕ«WÏ0 µCé ÊÙÚBz ¶ !Àümí!Ýû„ö!ÛsÅB³N Û²Ä-«Ì±ªP)¡P³<%œª zDʵtx¡[Û³ü—õ%d©‘â1qÒE ú‰'¡œ+~7¬ iÀöT/ʰ)çV",—¥P^ ×ugˆƒÕ„A-ôYG‹ÈåàºnÅÝ·|êS¥²Yåc‘H¤â¹ÃÃÃH&“ž×£ãøÞ7ýÓ?áÛ«VAËfñW¿üe]Ù§ðH!„B!„B!„ÒA„=Ë‘U>W’±ÂYxŸ‰"4ŠÇbÀpñØr¡úxë$–ýToE`v!eö%f96—Ë¡SyãbÏ£²ÙÒ’I8ŽSºßu‘+ –‰Db†p)÷cÍ1Çàæ5k080€o}+ò‰¿õVl»ñFüÕ1Ç`õGàÇWWþ)<B!„B!„B!„t î,ûÂÒ›*þ…K;t\FùžPÎoGñh4f¹†¬›¨£¼ð¨Wù^­]×-ç€ã8è?ê(<µe‹ZÀul¶mã/¾ˆÇïºËß½gùr —ƒeYÐ4 étº¤üŽã ‹aë·¾…Ó¶oÇiÛ·ã76`éÔÞ¼s'~|ÝuøäWà°«®ÂÀ¢EØyÒIu•ŸÂ#!„B!„B!„BH‡A©€(aNã(]“QÄC XÛÑAæ4,Æày#ŠÈ(ž‰aG3=µîá\‘¢ Æ,¡PsE°*eÄÉl6‹s§¦ð¶7¾1ØoYØù•¯`Û5×à—7Þˆ¾—^Â/þõ_ýr~eçNÜóÙÏ""‹á«}}¸òé§%38ìÀÏ^xÇýû¿cÅOàµÏ<ƒóo» ÿuüñxË)§à„NðÄÍhãŸú~õ«ëº5¯XØ;O!„B!„B!„B3EÀóz”@²fc®xœ¬Ù˜FàŨJafñØZCœ†EF ¥Âd³°m»þDfáñ[oÅsÏ=‡Ó®¹ÆÛ ¡®û××4­ì¹¶mûaPMË¢Q`xÈd0}ðÁxsÑÛðªÛoGþ׿öö8ꨣ°üå—qÊwâå%Kð‡ïzö¯]‹¦ Äb8þóŸÇÁÅkþö™g°-Æïÿ{üÅ–-˜~ñEœ¹g¾\(`ÍÓOcÏ»ß <ò~û–·àð›nÂ…‰ðä“€a££uß „B!„B!„B!-&Ï‹0Uñai-ì;§®Ù(ˆ(ÄŠûåØ(f†n ‡N‹cbÇ6MÓH$à8t½A\Ç¿öÙÏâ•?^*<º®¿¶kF"èºÓ4=á±xþ@$‚Oz(¶t^êëÃ'¯½xûÛqß}÷᤾>üýºuøì’%0c1@Ó°.—Ãõ=„§¾÷=¼ïðü™gâÛñš .ÀÏ>‹|ã8öé§ñÙ³ÏÆG\ß:á\õÜs¿àL~õ«øÇ|¸é& ÑØ'ÅP«„B!„B!„B!Dس1ü]ýƒ'hŠf†Ò‰"£ ]',<†×tœ/¶mÏ{Äjd³YØé´ïY8ãÞ¹îÜB±:ŽŠ´ÈŸ­\‰?:õÔ`¿e¶»n½wÝz+^úìgq÷?ÿ³'F:ŽçÑX,o>ŸG>ŸÇe¯=`ÛØµk^êëÿüË¿àíà¯;ÏþÙŸá;o»wÏmãg…«®º }ô£@*$Èçó¸xÃüù!‡®‹#>øA èñxø{ß‹¥…®,®ùñûïÇ=W^ xî›ßÄYo}+úþå_<¡tlÌ;/U‹Ü]ôx$„B!„B!„BisÌ {*„H ¥êÏI ðŠŒ†¾›(/(–Û֨Щ®ëÂuÝÆy$Ú¶*@,ÇÂò i§ÓiäÒiL µ¥í8%ë1ÞrË-ÐPimÛ5 ßýÛ¿ÅKO?áeËðî|Ïßr Ž8â —ÃŽN@zÿ~À?½ñøï}/Î8òHÜ’Ëáu{÷â¿ù  i8äôÓ±ôsŸÃIO<{ùrÿçŽ /¼pF–4MÞû^àÿûÿ‚õ&Í¢L‹÷#æIÉûß÷>XÃÃx!“¦i¸üoþ¦ø%%Ðã‘B!„B!„B!¤ÅT[™0ú>[ØSp¨z;Êw¥åä'­ø‡*Ç͇9y%‡ÕöG",¿ýv¤ÓéÒ{⺈D"ˆÅb}ó›gI*t­¢G#\H§qõ¹çâÖ¬²Yﺎƒ÷ïÇÎ: zþù8wj ß´ /þçúùZñ™Ï`ÝÃãÚ+®À‰ï}/þæŒ30¶t)ÌDË’IöÉOzÞ‡ù<à‹{ö §iè/#:úèº'Šx¨iþš¾c1Œªiš˜ššª¸öd#¡ðH!„B!„B!„ÒbÜ*ûE˜tPº¦c¥ñâ~&å¿OHTÅC •½(šYC­†…Él ».[¶ Ùl¶ôüâ~×uñ‰ÜóHŒ•Žu]Ïüö·ˆ àñ»î ÄÏ\ˆD¼{lÛÆàà`pb4 Ø6ž¿åüú‹_Ä3¿ý-n}üqLe2xâË_ƾ»îÂücôÝsÎ)†4ýÈç>‡¾GÁ¶cŽÁ ýýxbÅ œ÷Ë_bõGš†/¼îuXú¯ÿŠs?òœ}ýõžh¨xhÆb1¤j >FÖk±Q¥s€Â#!„B!„B!„BH›‘E©Àxc¥k:ÿÅÿYå»*½…EGó`œ+ß}÷¬ÂãMo{l;äjÛp]¦iÎ]oY²Ë–áþM›¼û—-õÇã¸íu¯Ã–ÿüOœóÒK^˜W×õ¼‹i¸–…‰‰ lzôÑ`{Ñ£ðæ~'>öžýû¿Çª7¾Ëî½'ìØÅ{÷âÕýýX¼x±ï¨e³øÑ!‡àßøCL,]І†pð5×ø!P¯ºöZ\ðž÷T,4ZcP[3ä÷º¡Sç …GB!„B!„B!„6# @õû³á ‘VñÏ@階&f®õ–¯ÂÞŽ­’©>zÌ1Hˆwž‚[\¯ð-K–`ô3ŸQ oŽƒ\.Ó4a âôCñÅÇý«WãoÞðüà’KðîË/ÇÞ .ðÅ»x<ÇqÀŠÑQœ¶};àÁÏ|ˆÇ=ñÑ0€tn¸G¾ã8{çNìüÙÏ€Àu±íÔSqî»Þ…c§§qî»Þ…;vàËoznß´ ;®½€E‘ˆ'ŽaÅêÕ8åïþ×?ø θÿ~Ïó0‘ðÖŠ4 m .¯hu!„B!„B!„BH©‡£úîÂET”ÕúD€Ô•ïj¨U•°ÔW£_]ý¸nþÀÿÜv,ûÆ7J‹Çã0MïÝ‹ÁeË‚óL°mœþ£aÛš5XšÉ 65ÇqÏçñ­GÁ%†n¹8ç옚ÂMë×ã/ûú»ûnÙ,V}ðƒ8dr0 <øÁâžz Èå°ãÌ3qÇ /à]SSxÕÕWcù-·`ïâÅØò/ÿ‚+žß[·¿þ“?ñBŸ>ø `Y8lhßzþy˜`ŧ?] ‹ádM ʬ†DmAøÓfBGB!„B!„B!„â†þW"‡RÅïe»‰™£ …¾7ÌïÎugÿ^ôXôv¹øË+¯ÄŸžþŒdÇmÛ8mzÚ[ƒ1†ëºøÑä$~ýÅ/âì‡Âûžx//Y‚ûèGqþÁÃqœþú×ã„;‰T*…·œr .Ø»×ólt]víµ~(Õg_ñ œòòËX:5…‘Bp]ì^³§îÞŸ}4Þ¹e‹–ðC›Æb1ŒŒŒëHšfiØS]/Z}L³-¡.$ !„B!„B!„BZˆ]ã~ñlT=uxb£*D&Ðdl°¬Êß-ËmÛÆ}·Ý†_|îs€ëz#<Ññ?ÿò/qìm·ö\~9`Y½þz|jëVœ¸w¯ŸÖ®l>÷\üãÞ½Èbåë^ç }†hžzÍk°â;ßÁ·ž1Ë©»wci¡àíw¸®‹Oœ~:ž?óLØÌL0 üã[ß øù‹/âðÃÇ×]‡#Þô¦@`L¥€Xlfùu½6OF „B!„B!„B!¤™„×jtQZ5†@h?;u3Øú­o•npœ’Ï;z¨t¿e® Ã0pÒÛߎóŽ9Èå°õSŸÂ”aà;×_éqÕa‡aêÜs±l×.À¶±råJüÇW¾‚cwïÆ²x°m,[¶ QMÃÁÓÓÈX60ŒŒxâŸmã׿°ûþÈËW1T+ °m†3Þð$^õ*üúò˽ýÅ5!aš8ö’KðìÊ• ËyAv !„B!„B!„BÚÕ5UF•…Æf÷|ö³øÕ¾lP<]×ÅíŸü$îû¿ÿ7ØoÛ^øUËÂ7®¹_üõ¯ñÒ#–…£~Ë¦ÁŒÅpê©§b™mãÔmÛ°kÙ2Üö×Ãn¹¥XxÝGF ».ŽýØÇ‚퀷ÏuqÊk_ ÄbøÇ÷¼Ç»¶Ñ(ÉOÑñÐÞÚHø“g½õ­8ù?ÿ3¸©™¶§§§qÝu×á¼óÎÃé§ŸŽuëÖa|||Æq7nôY¿~=&''[uBHƒ  „´„Zlí!Ý Û„€¶€B; ˆ¤`-G T€§R‡a,æí“óD£QdŠ"¤¦±4MóÄKI“ÔLÛ7nÄèè(n¸álÚ´ }}}X»vm‰qظq#6oÞŒ 6`Ó¦M˜œœÄúõë[uBHƒ  „´„j¶€v€î‡mB@[@é];à†>K¨UñvÊÛ1—ËáÐÛoW2Ṝÿõé{îÁ O>Yº¿(虦‰wô÷ÃQ×xŒFñÔo~ƒG¿øE|ýæ›qì%—àßâq|ïœspìöíxpÅ ï8 ×jÛ€ãàgàè§ž D]÷EïBÞvùFDF%ˬͨ—[—‘Bc]´ð¸yóf\}õÕ¸ôÒK144„›nº ÓÓÓõÙ²e Ö¬Yƒ5kÖøÇŒcË–-­Î>!¤ÐBÚBˆG5[@;@H÷Ã6! - „t¶HÿjÁ }¶•Ïñâg@4t^¬Ê÷ùrþÁ—n( ¹K—¢ïé§•Lûá˜&^¹jNŽ×0ðâw`õþý8ãòË¡Çã°mO¼éM€iâÌ«®òB×òyï³®#:2‚¾G)¿Î¢ò¿"$F£ OÛa¦§§K¾crrCCCþ¶þþ~¬Zµ [·nmuv ! í! - „x¨¶€v€Þ„mB@[@é<;àÖxœÈv€tñ³Ž@„Ì·…¥3½zÒóbjb«÷ïe2XÃqü§?Å{ö”î7Mìú«¿ÂD*…7|âXwä‘@2 ¸.²Ù,¾öþ÷ºŽK.¹Ä+K4еŸù œLÆÅ;Q„ÂT †a”R/ÈÙ¨&L’†òŠVg@¸þúë±qãFLOO£¿¿›7oƪU«pÙe—vïÞ %Æ–,YR6ž³Ê³Ï>‹\.‡ÉÉI¬Y³¦ÕE%¤eŒŽŽbtt;ñ·Û„…´°sçNlܸCCC3Ò ¤—ظq#vìØ¾¾¾Vg¥,ÍhŒŽŽbÆ ­.*!-crr›7oÆ=÷ÜÓ¶¿‰³Ù<˜o›`×®]ظq#úûûÙ? =ÍæÍ›199‰]»vµ:+eYèþÁ=÷܃7bÍš5èïïouq iì°@Ç vÌЙç9.¼°©Ž’†6´æË‰'žˆS*ú®¹®ïñx×­·â§=†cÞøFüìá‡qšã@×uäb18¶D&ƒ”i"•Hà%|êà ¢©ù€'ŸôÒ‚Î5•JáNÕ°¨ò(#É‚±yófÜ}÷Ýu· ÚFx\½zµ_°¾¾>ŒãꫯnH£ç°ÃêU«ükÒ«ô÷÷chh?ÿùÏ[•²,¤€#<CCCT =ÏÐÐxà<©Æáo#šÑ&8묳Z]LBZÊ’%K044„;v´:+YH[°xñb aÉ’%­.&!-eõêÕèïï‡mÛõ'¶@ù®°bÅ ÚBÀþû„pÌp!Ç kmeÉJˆ†rŽÒµec3hWô&|ôÐCqÅž=°, ¦eyÂ_2‰ƒÿïÿÅÒ_ý ›¡v>}ýõÀUW!›Í⪟üŽ<±L°l×.ÜwðÁx饗ðÜÇ?ŽWïÜéy)¯›{"F£å×jdˆÔ¦°zõj<ûì³u· ÚBxœœœÄÚµk±fÍvÑøø8Ö®]ÛYȇz(Î:ë,¬ZµªÕE%¤¥ô÷÷£¿¿7ß|s«³2ƒ…¶pÔQGµ­W!ÍDêA;z74«M@[@z¾¾> •¬‰ÒNT³õˆðHH¯#}ä^íˆðHH¯Ãþû„p̰uc†ÃB¥:ÅÏ6f –(¤j.W^x´,|ÿw¿CÀ?ý©'EÂ3~ýk¸¯y •JaÉ߈=]„T*…>üaÜöË_âOs9Àuqìöí8pöÙ8ÿ´Ó°kÙ2,QÑqʇG­RÕh¸äJʰjÕ*ìÞ½»î6A[¬ñ¸eËLOO—„4Wéðâ¯å\£)(ÒùÐBÚBˆG­¶€v€î…mB@[@é~; ë?ÚrÄEÙ.:¼µjU|‘NÃÃÞçlº®cÇa‡aï·¿~ÙlÐu,šÂ·{ º®ãÖO‡?þ8î;ø` ã…þ~h¦ X`ÛøŸK.ÁgO>Ù;oéÒàZ᪤«h á±—h™q^ vtt”a éh!m!Ä£š-  ¤ûa›€ÐBzÃØ„F•Lñ¿†@xl¨Tç8ޟ຀¦á;úà8¸ç³ŸÅÒÏ}Ë-Âs‡‚_ù œ|ðÏGÝvþñ‚ °gùr |ÿûøå±ÇâMü ^ÿÿà‰ŠEañ ÿ?{ïgG]Ýÿ?“’ØÍ,‘ãJœ!&ÑÀ,B!þ˜•4ŸÞÛj!Ÿš{«­Elê½ßZ¨â§í½šV¨­zohÖ¶îÞŠE „Þ©‚?VÄŠBø!ì\‰ÆdüÂ~ÿ˜93sïÞý‘›Ý$çùxÜǽ3óž÷¼gî½ïyÏy½Ï9W\„iMæh´¬Æ!U•c‚I!<._¾œ¦¦&n¼ñÆh]ww7÷ÜsO‹óêÕ«éììd``ÂÁ455EIdE9zÑ~@Qо@Q”€±ôÚ(Ê±Ž Eí E9öú,O,{¢c£\"4R˜Õ¤°˜Äu å2/þç‚ëògžÉßýÝß±÷±Çøïw¾“¾û]üb‘Òœ9´tt¢°ëò­={øÞí·uXÍçž‰Š¦ibÛvàᘠ­jYC­*Ç•㱯¯Í›7G¹a•ÖÖVÖ­[Çúõë¹çž{hnn¦¯¯Õ«W³víڨܺuë¸öÚkYµjMMMôõõ±nݺÖDVQ”‰CûEQ@ûEQÆÒh? (Ç6:&P´/PåØë•J÷ï¤Z,ëS)¾~ë­¼uÇ6 ~èC4û>™¿ø ¨Tè¯V1 #'ÊãÔ †Q»M9®h(< °aÃÖ­[Wã®ÜÙÙ À-·ÜR3£àºë®cóæÍ‡ìõ¨(Š¢(Š¢(Š¢(Š¢(Š¢(Šr,àŽ°MIÉá(¯z2ù|b5ôL¬Ïëxæ–-‡íK—ò’a`ú>+>þqvv2÷Ÿÿ\Ïó(—Ë\00ÀÏ8#a¨°†V=<ÏÃ0Œ¸ÎÃ}í]KÅÏ aj£•â²¼zõêšõ".&EÇ•+W7¤¢(Š¢(Š¢(Š¢(Š¢(Š¢(Š2ÔÛÑI|QÒ ÖÃQ„Èäò°T*×{^à‘µžˆ¦ ¹[V¯æ{÷ÒßßϼG቗_fÏ÷¿ÏÊ|„駆išJaš&¶mó‘õë‡æeL¥F^Ïóp]÷€ö9Êåò¸Õ­ŒLCáQâ ×Ç@îîîÖUY…GEQEQEQEQEQEQ”áIJm°hÕ­³àpÂ]¥–… lâ‰x}*…OèC|qÇþaÅ >ÛÒÂ='ŸL©Z"0–Ëe–\uÕaÏÙ8ž¢#€ã8‡^ɋţ²î#ACáQÄÅhݦM›€ )k5̪¢(Š¢(Š¢(Š¢(Š¢(Š¢(Êð$½ EpøAz±, ËšMr×®]A¾Çq`<=EXOáq¼ÚïyÞ!{<ŽtÞ¾ï“ÍfÇ¥íÂÔá6¬[·Ž›nº‰ææfš››Y»v-ëÖ­‹¶¯_¿žÎÎÎ!ëEQEQEQEQEQEQ”‡ZáÑ$ÞäùV*ÑGß÷ñ€—ž}¶¶ŒïC¡ÀônÀËçÙqï½`ì»ë.lÛÆu]þößÃÀ÷}nŸ1£á¡ÆÓ£]¼«æd9›Íâû>öAû‘Æ×w¸õ‡ê­Y.—kêÏf³8ŽC±X¤R©`Œò«®mÒ¦t:=쾕JehÛóW}ÂHW¯^ÍêÕ«n[·næuTE9H<ÏÃ÷ý†3‰”ã×u1McŒ¡*|ßsYEQEQEQEQer"òá[§&#À‚mÛ‚m"FU*Épîk¯qâõ×c~þó`Ûì¾ývÜ}ûÈf³¤R)VX¶msêùçGÕ‹íi<=ú\×ì[#n:ŽƒmÛd³YªÕj´¾££ƒR©D¹\Æ0 ¬~|çX,’J¥(—Ë”J¥è˜•J˲(—ËÃÖ+×LÊF¶ß"`AÞÉGu»®‹mÛ¸lñ…î/ðÍG¿ @=tU»†u}Íf³tuuEËÛÿa;ó.šGGG¹\˵¢ëÐw­+ZqÇqH‘Š·W\p{ƒó|àxøá‡é;ž:Zîînº»»Ù¼ysÍzEQžM@œÌ¹;Æ3TÁx× uHy×uGœñÓ¨î kP.—G,Ÿ”ø¾OGGLjå“Û<Ï£­­mÄóï™hŠ¢(Š¢(Š¢(Š¢(ÊØhdÁ94¼ÐþóÔSOá¤Å# J&þmÛxç¹çÒôàƒls:bÛ,ضR©D*• r<†¢XÒ1"›Íây^¸v°ž}•J¥ÆV%â]¥R¡X,Žº>Ÿ¯YÞû±½ÑzÇq🧣£ƒl6K¹\¦X,âº.+ZW`a ¹6"ìôÕ“ØýÁÝÑú­·oeà“yûÏÝϽçÞ˼ÎcÛÕÛ¨úU¶Ý´%îüüäóy>zåGyåí¯°æ½kèèèÀ«xtÑÅ>þ† Þ,àA¿Õω8‘žžúûûé':¬ð¸yóflÛfÍš5¬Y³†U«Vqã7ÒÁEQ”€Ñnzõ7Öé} qº+‰0 £!nÿ#q(Âd:ó€FÄ»±àº.#ž«„JHÖ=Ò¹ú¾«ã8äóùaë÷}Ÿt:M±XÄó<:::†›ù|>ªS62ÐK§Óø¾_SR.—Ë´··×\ûJ]øäuýÒ—¾ÄOúÓƒþžEQEQEQEQ”á+L}ì*‘ùJ„ô¼šüa\¶ BÏ7Ã0( Ça*E>ŸDH;’gIÑp8;Ÿ”­9a/åéºnRÔ÷OB©[lZl¤²nöݳklY}ûxü«ãºn$0Š×žçbšAp~ošó&ÎÜræ˜.k9_fáÓ yåÿ½BÁ+°ý¶óùŸ§X,9wfyiÆK4¿ÖÌ]_¸‹-üßžöíX¼Ë_†œ÷UÝWqÉã—°ûæÝä;ò\ûøµ4=ØÄ­ßÊÛ~õ6rfŽÛÝÆ×ÿüë|ÿ+ßgú_L'C†ªW¥ûÒn^}û«ÌØ= ðË~ðEçaîʹüäw‚ͪ¿^Å´‡§qáO/Ä1æoÏþ¦ý|`÷xbéO[[¦iR*•¢ï*ŸÏS,ioo§­­J¥B.—‹Ê†A&“‰Ú“Íf£öH ÜÉl/¹>´··“ÏçiooçÎ;拉¥eÌß»¢(Š¢(Š¢(Š¢(ŠràX‘6ÅZ'Bdê`*ó<ànýÞ÷°‹^z)ò^”÷‹Î9€§_{Ÿž}6år™} DÞ•J7|7 #ÅV&¶°Ÿõá†Íð}Ÿï ðÐ<­Ûý½Ý<øgâºndß«T*¤ÓiÚÛÛ±‹wþ8²+Z–Ukc MˆrüKŸ¸”{ÿú^ °›5p¿øÛ_„—Áãgƒ\.G©T <ô,øô‚O“13|í_`Öc³âúݸþ‡¿ó0%£D±X¤”+ñÃþ"EZh%EŠ‹^ºˆ%û–ðåO|™ž®>ºè£œ´ï$þgêÿpÅWpÕ‚«xºùi¦ÿtz ƒ×Goþ(ïùû÷д¿‰‡§=ÌIן„åX|óôoR¦Ì÷æ·~œ7Ì~—<~ «¾´Š‹o¹˜¹ß™ )˜öçÓ8ç¥sXú†¥´ÓN»×Žçxüõ ehÚßÄŠVpÇwpç9wò™¥ŸaJû><@ -<þéÇyôórΞÃ_\øôX=|â¿?ÁܯÏåëg}¬`Õ½«8ý-§Óáuð;ÿïn{7oz×›øäŸ¤hùÁÞ°ô Ké7ß0Çc__ÝÝÝÜtÓMQŽÇåË—³jÕª!!WEQ”ÇuÝÅ;&MÓ5,«Ì*‚ ßcóù|Mù‘„>iK&“‰DMÓ4n‡8†¹ˆ|Åb±f9™§P¼ …–e‘Ïç1M³æÚ¸®[3(DÉì&ý²ÙlÔÙ?›ÍR*•¢s:³Ùl$üÉL.˲H§Óär9r¹íííÑ9V*• qwø9“ÉDƒ©jµŠeY´´´Db®ÔmFÆB®ŸÄXÏf³‘X­V)‹Ø¶Í6H¥RX– ŠRG.—£\.“Édèêê¢\.GÞ®¶m“Édhoo–K¥RÇ=•¢­­-[¶ŒÓ/\QEQEQEQEèïï§¥¥… µÞŽ)b¯ÈQ)—Aì]™ Åb‘Ky„À ߇«®ŠŠ¾<{6ƒozwžx"O<ø œ{.N¥Â¼SNáêÐ&'v- WÙ°ò;š¦‰á¬xeŦˆMîÔÞS™õýXØûÞíßcîÀ\ü¹~cØÛÞ±ììûÙ>¦ZS±,‹¿y#Ýtǃ‹"‚eê•ßý0[¿¹•J±Â% .á­›ßÊmóoãöÝ·³â¬øÌŠ@É­üQóA\`]Àœþ9ÁE64ø=õï¯ú{²;³ÜÃý¬xeמt-Ÿ]úY.}äRî?ç~Ìí&T![ÎBÌ2fA ÇšòM|ëºoqËWnáš“®aák ™ÿÚ|¦î›JŠeÊ\–»ŒÏ|ÿ3¼÷—ïeÖ¥³¨xÍô÷šà‡0/l—¾K>G'ü¡„ õi÷Æz?ó0;–íଇÏÂú‹L&ÃÕ\ À;üwàÿµÏ%W]Øm]XñÀ øexmz égMQØÖy<܉íÓ0 ŠÅ"•J»`Ó±ºƒS8å~óà ­­­5ë—/_®Â£¢(Ç%õâZ="”%¹$I±­‘çb2Ù¯$o–ÃR¾>?`}}R‡ ’u&)—Ë”Ëe …B³½ÑùȹȌ'êDŠÅbTÖó¼!y ‹Å"™L&Óé4©TŠL&yéIØ‚T*‰­²GGG”,Y’_K’ç®®®È£O¼ µ_ŽDía0•JEb¥GDvétÃ0(•Jѱzzzjbà –eÑÞÞŽišT«U èù]Ôÿ†ººº0 #ú®ê¿3ˆ¥ni¥\r» s¹¦iÉ©CÑW~/rüîînEQEQEQEQÆ™þþ~ '›€G )4·ê8QXÔ!ëS)\ÓÄ2 Îíìäü;¸˜vÊ)`ÍB¡À³çœC*•âá;îàÞ¯ÝË­_¿5˜ÌþѱýNìUår9r¸ïÂûxûo'“ÉÐßÕÏY[΢êVkìUb[öä2¶D‘Ûà2.‹&ýCl‡* œü¾“™;.óSó±,‹å¤H1ð;L»l³+³Áˆ#•98ÌkžÇì÷ΦÒRá¤ö“xàÎxû«oçí'¾=hŒF³‚‹9575XgÀÓç>ÍŠÛW@;|øá¿þÏóØô³MüdÕOxßûÞÇ÷þú{\òø%¼öÎ×ðñ1s&§êô@°¬$¾¨LP.‚=3÷`š&7VoÄ÷ý(ÂÙ´i4ŸÜÌu7pCP‡)+p,ÀòƒÈ×ýJÁúŒ›‰„ÁjµJ[[Õ[«d³YrvŽ$†aDöÀèzt…õæÇKÛLÓ¬±)ŠÀ7ÿø›x/{\Àý›ŸzÐ{*Š¢GHüñáÈçó#z&ã¢'Ã|&ë—åúí„ÇdG)/ž}¾ï+€B,ò‹Åšð£rœJ¥ÂM_øBtL oÐÞÞŽeY‘˜æ8N5.tΛބ¶)ŸÏGáÊÀµ_øB”#ò¬[oåkO=EWW¿nnƨVÉ”J‘çâŸlÝÊÕ×_ÀÕwÝE‡eqÁ­·ÒÕÕÅC?ÿ9FWFè xïŽÌÿîwùåÉ'7ô˜|ËÅGá,LÓ¤R©D^¥R‰ÞÞ^ ¥†a`F ˜Éd¨V«ôöö’J¥( ”Âv6"—ËEå-ËÂ4M\jŠWËv*EÙ¶£öU€4Áä¦úe0r9жM9\W&È3íF©DÞ4)žaàd2´é°® øê‚ø/PEQEQEQEQ„y<ž={¢eƒ@ÖrWç°Ù}\—lh“Û²e §½ø"ð'»wóüë_å2wÝt?|ùežyæVmÚÄe_Ùæ\uÙlÏó¢ôBbßêééáï¯ù{Î9ñœ(ÊÖ[_y+o~áÍC"±‰ÀÎ;Ã&6ÂlýG||þàÁ? @ÛæßFqJ1Ϧ÷M眗ÎášÇ¯ÁölȇGÓךøêõ_vß¾Ó71ƒ¿jú+nÞs3S¦Lá¼þó˜?>iÒ¦iÖ„ä†mÛ6®ëbFŽÕuÝ/9ß÷£<~–eE«Õ*ù|¾¦~ñ@ñ6¯Áööv\ñê+ßúÏÿæor£ç‘N§±m;й^*•p€7\}”ºT*‘Íf¹ô«_¥gñbÞv;¿ð²Ù,ÿýôÓ|硇8ïoþ†,ÀîÝ,ݶ¾ÿüOv~èC4ÿßÿ‹3u*ûô#ŒéÓi2¶ ¥_X°€ÿíßxËÌ™<¶w/«öìáŽU«ÈÎÂ…@0¦¸æª«H¥8cÇ®¾šù7ßÌ Ó§ÓApu‡¦ÿw>M06¨¤Ó|ûÝïæû§ŸŽ7cF061 *÷ùAd—`b–E%\'R£G ZD‘¢q ©Ùp¾{á6ƒÚÉRV¸ðÚ§Ãõ)P¢-Øá2áºTX‡SWÞH,çÃ}Sáy„‘H…¯OϛDz .`Ý8ÿwEQEQEQEQŽW^yå•è³hK">‹ïŒÄ‘¼ ×…ÐN8°~}”rËX°àDfþÖoE»Ÿüñsï½÷²lÙ2 °;ær¹(X2êZ©TÂó< Ãà£ø(¤ÁNÛ/øð¼üç/Ó²3ðÖ|ñ?_ää“OŽì µÿ¯X0cÎ_:XÛ,rä(R$7ã‘y°tÛR(Áœ¿™Êf³™]œ óƒ¶>¾àqŠ[‹”v–È’¥ôx‰*U||ö²i·MƒSOÀœwÍÁ¬šLûð4ø±!,CàÕ(8öúÏëçS{>Eïy½|å_áúëùü¶Ï³cö¬—,~~Åσò&PÛ´cGƒ¤˜jð…Ù`Ö­”klƨ¶äƒAÄÆáœ!&*<*Š¢Œ‘ò1BmÂá¶C«ÏqœèF$È #ñöËd2Q>ÃL&îóÏÇëì¨ ¥*3”¦ýË¿°µ¹™\.µ#éa™N§©V«”ËeÖ}ñ‹|õ’Khzê)¦Ýz+†mó©‹/f/0õ¦›`áBÎ;ï<Μ:•®®.vN™Âý¡˜çsþèxæ;ßácÿõ_T®¼’ÙW_Í÷æÍ£iÿ~öM›Æô?ú#¾zà Lyà>q≜øwÇi?ü!ƒû̘ÁœL†`NJÈLŸN)¬Ûæüöoó™íÛ9gÞ<àë³gcΞ‰v)¢ÉKdgÌ dæÎ¥ä?ö1æ>ó ]ÀîÜÉÔŸÿœïÌK•@<4çÌÁ˜3'Ú_Å\ø9K, ¶„ßL r‰EF !B^…@%±®–µÂzýð8=uu‰(™DÚ—Ils‰ÅOF)Ÿ —%ð‚Mí§3~úSüéOáÒKþ¡(Š¢(Š¢(Š¢(Š¢Œ‰±íhXáÑuÁuñ-+òvs]Û÷ypÿ~lÇáÁ°øs'þO?ýEÊå2¿?k7üçrþîÝ‘SCŽE·H¡P ›Íbc×DuO½>÷þÏpÖ3g±gï~ã'¿A¹\fÆ_Îàš“®Á5ƒP« °lö2Þ÷«÷ñÂŒ`"e¿L×Õ]ìûê>f,šmÄ2ŸÀhUl¸yÑÍx3<0à½'¿—öûÛù«eÅ܇çòbë‹,²ÑL3TƒæYkhj)ƒØC@¨B¢a|ê+Ÿ‚4̰gÐVlã_Ûÿã~cmÂgù-‡K³Å´>Ó4#qp<„Ç£‰…Ç5kÖ4\öÙgY÷ä“ONô¹(Š¢ŒÉœŠÃm ™íR.—£|~IQÊ‹E€(a¹\¦··—ߘ;—³¿û]ºzzøòÚµìÚ²…+6nä_›šÀ¶ùþ_þ%P;ó¥\.ãym,ºóN¾sÉ%<œtÏ=|mÆ š§P`æ-·08á#¡uëVè!~ýÚk8S§R$Ùz·Ÿr }ßþ67ÜÛkÏÞºcž;€ vì`O¡ÀN<‘2põìÙ”.ºˆ¶°ŽÂ”)5¡Ì“‰µm ÐÒµ?9”°¨½Ïg¨ ‹ž=1ýTŠþJ…¹_ÿ:›ûŠxg‹r$÷O ró(¢¶Õ“úòaý¹Ê'1´Ç:€òöOrÊ«¯2kïÞ1œ™¢(Š¢(Š¢(Š¢(Šr¨˜ѶêSú Áó¨x™LÏóxü«_ÅþwËL iÿþ gd?œú~™ßÁ²,ö-XÀ™çžK©TbÊ”)‘@'9Ëå2÷M¿?õþ˲¢èk`ASSSÐÈÐgbÅ+hþq3'œpl˳H‘¢Hûm· Òt{Àr,|ßÇò-^îx. OXru…"<.”J%paù»—ãÿ¶Ï3~†‹ÿøb~Þöó!—FòÝ@í¬þD¸RÓ4¡ rFàra×…<þ†ÇYd,RmøÍŒ™‘ìÈÇ …ÇÖÖVÖ®]{ijiÓ&Ö¯_O__­­­¬[·Ž•+WÖ”Y¿~= °råJÖ­[GkkëÄ\=EQ;“µ0©Ée òP ñJ”ÄÍ’S±&çc¡@O©„ã8T«Õ@8Ìd¸îõ¯Ç3Mv¯-Y‚ïût.\–Å– 8çÙgÙ~õÕÌþêWùÁ¬Y8ÀΖz«UþóŹíŠ+¸á÷~ mml[°€mƒœòŒ‘WÞÇÛ?ýi¾þío³út¦r ?Ù½›m'yíU‰ïß;}zÔ¬0ô©pïÂ…59‹Mâ õÑ õv^/ Z–E>ŸÂÀfšš¢m “v@݇Bõ0×w¬3YûEQŽ,£õÚ(Ê±Ž Eí E9úúI½0ëùçk&“*IynèäÐëy|föln™9“½Ÿý,7Ο³m³Þó®êêbÛ/[yþùçq‡¹mmtY]Q5Žã`c³û{»q¬0ÚÚO­(ôªïûa¯¾A’CÈ€—=Hë­¼ñ”7Ò²³…-S·Px­Àó³ž'³'9˜Á Ø ¸×Ÿçy`Éþ‰A}U‚üBɼ†¡°” óÚÐLs$>¶ø1Œ‹‡^©a#Î £GFŒfàÑØÕÕl½q+‹X„2> +<®[wd³>mÚ´‰ë®»ŽuëÖ±xñâhÙqœ¨sŽC:Œõë×sÝu×qÇwLôuTå00Ùûd¸Uß÷ƒÙ;‰›]}NEÃ0¢°òîº.===‘ˆ™¶Î˜Áœßÿ}vzL›xC”JÜ¿?›“_y…þw½‹·>ñ{¯»Ž.àCû÷3ïŠ+pÄΛ‡Öé}â,<ã ÞwòÉœôæ7ó™E‹° &IxO3€?>‹ ÞÆ~§©‰wŒp-RŒLR`KrŒ¿øfY…BT*Õ0ÑòD1yZ2ù™ì}¢(G†ÑúíåØGÇŠ¢€öŠ¢ý€C0ÙÿÕW_eú‹/Öh{#E¨"=ÏãÎÛnãjà¢G!mtíÝËô… yeÛ6v/ZÄÅ_Ì«=¯rÉìK0 ƒ—¯¾¾GW{îûϱsÊN¶=¾ ÇqøÃ3ÿ“Ý“À³oÖÞY7b‰À`è‘ö¬'^}"Ù²TVW ïZø.®xé ¾°ý A{åÄì`?#°—¦ÂºÄ V¥ÖHëmwâ°ñÝ÷|—³ÞÖaÿ^ÄÑÎÏF¥1SÇZ°»»› 6°aú»»{CÊå2k×®eíÚµ,_¾œ›nº‰•+WÖkÓ¦M¬^½šÕ«W³|ùrn¹å6oÞ̦M›&ú:*Šr˜¬ý@2£à…Éœ!¾™'…GÇq¢íɰ†Ü| ÀB2°éíoggK 3n¼‘Çn¹…‚I@×íÝËÓ¦á1}:XÛ_~™;}”°ë‚ ¸/Ì(ÑÇ»îé—nßΖի9éúëyvþ|‰=å_êÔ²†a~9â›aär¹I%:*Ædí E9²ŒÖh? (Ç>:&P´/PåèêÊZžèxÌzþùa#pÕ§ozþºëزz5?ݸ4½T*ÅâY³xÝ%+ù§iÓ˜2e [¶l¡eg ‹¶.Âó<Î: *0ýÅéAeÌœÃU ®¢R©ðæ7¿€ æ}wúö? \!0FBœ'(lðKW¼„‘2˜óå9Є:}béx–Çwç}7nxX>rÒ0Þ3A–GÈ)téM—ŽÁ5T™¬Œ(< °~ýzÎ?ÿ|Ö¬YÃúõëY¿~=kÖ¬áüóÏgýúõ r#úúúؼy3Ë—/¯YË-·°:ü“mÞ¼™¾¾¾š2­­­,^¼˜G}t¢¯£¢(‡Èdîåw”ð©B}üo×ukr7š¦‰eY\öáW"™ ;;Ù¿l)à„×½ŽËC!±¸yæLJ9sÙ,ÿðä“\µdIͱ2÷ñÁ=¾¸á‘G Ÿç¶åËû˜âÊÑÅdî E9rŒÖh? (Ç>:&P´/Påèë’ŽƒÂ‚»îÖËñ«×__³ü­={xæ™gøõÓOóüóÏóT˜B芋.¢yáBÞò‹‹ùïæf{ì1þì^†žç‘îÔÃ-ßÞÀëŸ=ýsúùí¿ùm ÃàÒë/eû¥ÛI‘bég–ròŠ“£c:ltŽÀÐXO$4w&Õf2lÛæùëžç÷>7Ü ö7Mó°åITŽ^NnÃÀÀ×^{-›7oŽf 4…?òȲ»»›Ûn»-Úv0ôõõAgpã7FqšW¯^ÍâÅ‹صkÀ¦¹¹™Í›7OôuTå™Ìý€„T­Ïå(Ž•J…\.W³Ý1 –nßο<ÿ<ЖÏóÒEñ­Ë/§%,³èOþ„Ç¿úUÎëè ÕÒ‚uâ‰d:™G&LsD¯DÙb¡¹D>IE9Z˜Ì}¢(GŽÑúíåØGÇŠ¢€öŠ¢ý@Mì´:ç…zÞúä“ôÝ?­+VAµsÎ9‡‡¶l¡Üæ™,Ø·wÍ™ÃI °û'»iiiaþüù<¿÷yÞ?€ù5“7þì¡Uq`` ‹ Þû¶÷ráæ yþªç¡¯ûÉë0ÅÚØN`Pì%;ÂÏ&èèÒPDÌåõ[›¿U»Á<G:_åø`XGIÔºqãÆÈuyùòå,_¾œ•+WrÓM7±qãFúúúX¿~ýai̪U«hjjbñâÅôõõEÂ硲cÇŽÈ[SQŽg:;;Y³f Ï<óÌD7eXÆ«xæ™gX³f ´Ÿäh¬_çº.žçáy^$ðIîGÏ4¹ÿ ù“3 Z¥gζ]r ¿=8HŠÀ;qÁ¶m Š--¤&ä›(7õ±R(ËuSŽ=$ŠÁŽ;&º)Ã2Þc‚5kÖLô)*Ê„²yófÖ¬YÃÝwß=ÑM‘ñê ¶oßõ…Šr<#÷ÄíÛ·OtS†e<Ÿî¾ûnÖ¬Y£Â„rÜ£Ïú| (j3<8›a#|â4‰€ï7Lã”äW?úQôÙq«U HƒøOsç²Ù2~ö³Ÿe1í„Ëøý×ÿ>Åb‘–-4íoÂÅåŸ~ñO”ì¯ûÆëøÆôo!Ã[ž{ T`Æí3Àƒ©ïž©D#Eh„Øb N‹ÃÙ*5úÚÑ‹èh‡:&hèñØ××Gggg3y8–/_ÎêÕ«Ù°aëÖ­;$¯GÜt×®]-Û¶Mgg'7ÝtÓ!Õ;wî\®ºêªÏEQŽ$ÎùdPW?pÆg°1Œ~ xž7$_ ŒŽãÄ9‰óAN}÷»Ù¹p!Svîä wßÍï]qFKKmÅ™Œz$*ÂÆéî͇ (Êø²xñb6nÜ8é…·áú‚•+WR½óæÍ;¨1¢k¬[·à¸}>¸âŠ+¢k (Ç3ú| ÏŠ¢6ó6ÂK¼ç€â(å_ìëc÷ÝwÃ'>Áƒ_úwúóYôäóT´Á‡~˜Þ·¾•[¿þuÖÿÎï0}ËT>¸øƒÌ+ÍãƒÏ}~äl˜6€c:¼ß{?9rl?};M„ºM%hÔýÞÏŠÌŠ`Yò,&ò:FŒâ¡ã±Çºu뢠¡Ç£¸/KŒä‘2‡#VrýñV®\µEh4‹A\ªE9ú™Œý€çyQbädÞF€|>_ràÖ3Ïä†éÓymáBfýà̸ývþøŠ+z2ªè¨(Ã3ûEQŽ<£õÚ(Ê±Ž Eí E9:ûÕ[¶ŒZæô={˜†Šýéý÷ó6^e÷®Tä<_÷:0 Ü¿Ÿ»,à™¹ÏÐò?-dœ ³›€Ïÿžÿ¿àBÓ²Àr`î>>Ó.›¸`æˆ<ùñ_Æa×Dx4*Ñ×QQ”Cd²õ’ÃQ<Åãb¯GÓ41M˲¨Þy'¯½ö¸nt?_û®wMô¥U”£ŠÉÖ(Š21Œ¥/Ð~@QŽmtL ( h_ (ÊÑÙÀYø¾ž7bÙóúûùî#€ã°zËöÍÞÇ«œ‚aZ¼<{6Wí¹Šê4îºé.:?ä ÜvͶÀ{1ÌÏèg½ÿ,HÁI—œÄÜÁI Nbî´¹²ÄPG€Ì¿4ÊqBÃ2‹ ³³sÔ|’pUö9Xnºé&®»î:Î?ÿ|/^ÌæÍ›Y»vm õºuë¸öÚk£D²}}}‡%·¤¢(“ƒÉÖ¸®‹a‘·cR|´, Ó4£Xæ`Á]wÑòÐCL}ê)>ð•¯`årë\Q‚ÉÖ(Š21ŒÖh? (Ç>:&P´/Påèë,Àß±×u±,+rl¨ÁuÁ0ø x…©<ÔÒÂyÀô“OãÌ6påÖ[Ùòœmìå¢/â ­oà©3žbëú­,¸jA`ŒÌ6är¹@Xì ª^öïËÀ€¦ýMÁúP Ä¯kƒfRƉ†ÂcSS«W¯fÆ ,Y²¤fæ@’M›6±aÃV¯^}ÈàÖÖVî¸ãŽš0¯õnÐMMM5e–,Y¢E9†˜lý€çy8Ž ""º®ËÌ·¼…s.º‡à¾mÝ|3ŽãÉd‚H*:*ÊA1ÙúEQ&†ÑúíåØGÇŠ¢€öŠ¢Lî~À¶Í"nãzncáßü ³žÿtðï¿üw¦½ùi^8ùÍøÝ> .`Ë–-ðSà*!Ñ ^™L­ë¢Ø2_š÷³™oP¡Q9Bœ0܆uëÖñè£rÝu×±råJ–/_ý™ûúú"wæÅ‹êy Œ%dë¡„uUeò3úÇq¢ÁAÒÓ‚ü/ýÞïñðŠ<7s&Âûv8H¥ô.®(‡ƒÉÐ(Š2ñŒö?×~@QŽ}tL ( h_ (ÊäìÀ¥6j© ür÷nÇÁ¶'RÜúè£<¼d âòGÓ{x`çÎ0å¢K•* À~º˜‹7ó:`϶=\³÷À“Vx VÜœ}õìÚšÓQ9B +<655qÛm·Q.—éììdÓ¦MC¶¯]»–L&£3ˆE9&ñ<×ukf ¹®‹ã8LËd¸eæL ˆb`ŽiÞŽ¶ÞÅEQEQEQEQåxä×O?Í ÷ÝW³.!À†Û¶qÏóÏcq%3fÞÃK¯Lá¡¥ç¼G,~0ë,l^ÈÅÛ>xއ¹7TÍD¥½£4$W·¬9•#Ä #mljjbݺu¬[·.rQt‘¢(Ç®ëFá ~>e ®ïÓ¼p!6Á½^ü˜ꊢ(Š¢(Š¢(Š¢(Š¢s¸é ‰uõ©Ïüú×yêg?àô=§c&ÕBxÈà¿;;¹ ™Þv6oûõröÌùM0aÞkó¸ëÌ»h¹óŒóxjÙS†gÞcÅ<€²Šr9a¬UhTåx"™ô9éÁxç¼yLûú×Ù5uªäkŽÈårÃÇmWEQEQEQEQå¨FB«&©_ö}ŸŸÞ?ÿç×ÿ‡Å,Ž7~¹¶8tDQûë¹rÛ8cðì;ïMܾìv®¹ä¦ZSYpé0Ხ˂§Q¯Eå¨`ê¡V°~ýzÎ>ûì‰>EQ”ÃŽa5ÞŽ¦i²mÁö/[†E0ÁȨ+¯(Š¢(Š¢(Š¢(Š¢(ʱ‰?²|v]ß÷±m›³_éãBúɶ@¦tÃ×¥Ó®†mS¶w0sÏL.¸ã\Ó¥\.3Ø?çe´Ã—7ÑW@QFç…GEQ”c•T* `û¥—‚e±ô‰'°&ºqŠ¢(ÊÑïC6;Ñ­PEQEQEQI±1©Šç£ã¡TS©¯ëÿóNz6ØÏ÷ao°·–?eÿ)`‡‰œÊ°gÏ<ÏÃ4Mv/Ú]{`g¢Ï\QƆ Š¢( pÓ4±¬@bt{W­Ãàïž}V£(Š2¹ðý±—uðŽÓ)’ž\+yÕS© ]ïûP,×­X„|¾v»ã@[[°>^ÉúÚÚ \×eRžkó¯=Ñ-QEQEQE9ªp‡YWÿ¤mÛ6S_Û'{|å–¯°oî%˜À©œ ØAøÔ\°Ï#¿÷žçQ.—yyé˵ª'„r” Â£¢(Ê0ضy¦¼Ó ¶Ùvã}!8Vr›ë/Ïk¼œ«ëÖn/—ƒósÝÆß{× ¼0ÛÛY[(0ó¹çŽÜw¥(Š¢(Š¢(Šr "¹§nÙÄvÅ­gneÞ¾iy¨…§¿ü4ξ’=§ÿ¯ŸûûœÂÛƒSÂc¶}a•J˲˜¿h>$1±¨]V”IÊ ÝEQ”ÉŠeY‘Ç£\}Çôô÷dEQ”ñÄuÁfŠƒã¯B¡v9—«-'âY}ŸeYñ6Ë „1D7ÛÖYV¼_±ˆkù|pÌLèó].ÇŸ'šl6þ,+¾6õ”Jñye³ñ9A°oµ:Tt4 èí ®±eËõ×s¸ïʲ‚cz^í~--±@jÁq…J%¸æB¡·ž|O"'¿ór9XŸÏÇb§Ï˲®R ÊÿýôÓœüú×Oô7¨(Š¢(Š¢(ŠrT#ÂãkO?Ù–ì_û žùúTÞ°ý t³”Ì#ÚÜÅ”wòãæ_³¥R!•JñZçk\xá…ø+üÀ¦Vh4PáQ9*Páq’#¾ÌYÚÏŒ'ehNÓ%ø>|‚¾žðs™È#¾¦¬G0iÅ ËûáËKÔc246¸‘¨?é·`%ÖKò[0ßJ´£Ò ÊPÜ„WGðÝœóÈ#Ì;p†Š¢(ƒã¢XooìehY±œï"S.ˆV•J,ú~ 2y^PORÐ2™@Ø*—¡§'^_­^}Ž]]µûd³Á±'Ø_<椾$#‰¦£áûÁ1l;8‡d=rn®ˆyÉm…B ȹîж×#Bk½ˆ(dòš$9”I'f݈­Z…ÇúzEh±²ÞÓTÊ{^­ðØÓ_¿ä>*VÎâßðÓõëY~ðg¦(Š¢(Š¢(Š¢„ˆÕÐN>çywÙƒËØaîÀö‚mWn½’Î…ühïcÜU¼‹T*Å‹g¿îââe½ñ?5jeRÐPxìîîfÍš5ݶ㎤%¸áúzó]%±O`¦ì€IDATr[‘ ÿ9TAr¢DÍF× ^æ‘ín¢FbÙ¦î|xmD|«„×®èª[/å½ðeˆOf¸=“x/‡ÇôÇNˆ…Yj…E“ÚàɶwžrMŒD¿®œüäü+ ʈ`Ù,Mé]j$|ß§ùÜs#ѱHðjf,)Š¢Œ •J­gZ± "úe2±è±h&žp–”N,Ëå‚2IAL¼óê×'ËŠPçyÁr½×£ëB{{ ¬&Ôµ·b˜ †œ«xXú~ "Ê=«X Î×4´·7niÖzŠçßH"¤9Ó·F»—F\¦>tëpÞœ²_*U+2Ê5KÓ0PEQEQEQIXòÀ+¯Àôé@ <:’£ú÷G˾)œ½÷ì^´›ë¿ž%VoYÍO^÷–ä–°gæž5žÅ¶mRì·ê…¤%4›››Y¾\ç>Ä5qÅÎQ+ú¹uïV¢¼‘X/^Öeb+E ž‰˜&"YÒã- ”ÂzìDÛÒ@5±^ȆåºõE†zÒ‰h“<®Öé{Š×Ÿˆeb¯@Y/؉k —åzI› báO®‘¾KಠñMÁ  bÑë(‹©Äw$B”œŸœG¶®þL¢-Ò†jâ:Ë÷'çMÝ:iGÒû±~–ë/‚h>Ñö\ØñvLzIºÀ§üc¸â ”áiëè Lüç×¶1ÔX«(ÊáDB^ ’ï¯T –%´©ëB\&„éO7߯Ý_ÄÃ$âW,Bœi"u¸‰)õ"¢„òli‰=!8†iÞ]]±`jšñ{²­ù|\Ʋb‘3)® r-Äór¤§¾_›ÿÐó‚¶Õ_›c|>8ïœÆ;PEQEQEÄÆüâôéLÙ¹£¥ëMo¢W"ÝÌ·ØóËïð†íÿÀ”ô/Énϲg÷fíů~õ+Òé4]]]œ5ë,-_Äy™ó&ú´åh(<.^¼˜7NtÛŽI|Ѫ@­)ÂT…@è±ID¨J¢\ÒëN¶{Äá;+‰Ï"D:Äá@“¡ Åë¯H (ŠW ~.x扅6#Q^<,E +‡çVI¯R×.¹"Š ‘hk3ÑÞDÆ#¬ÄõTö•v^'“@ðÁ0ž—ˆƒùD»“‚¨‹"Þ )jCœÊ9‰x[ g%ÚÚˆF¾ £M\©7 ‹éx˜ÀpCŽa§†IŽ•Æ8ŽCÿyçE!Vs„ÿÓ â«bå‚Q†ÚY ò§–»¨ìÒP+^¿wï^fÞ<óÀÚ õ‹²­ÎG ¾ï«(~´ÍÖŠ_®T?ȽÖÓ*؉Ð'¢äHtteR©Ãëåg¸˜%K¥àÁª£#Î ™ÌWØÛ·A<÷’×£‘Ç^Ùw4Ï} “¢§ãpÜQ(Œì!©(Š¢(Š¢(Š¢6«U¼þRŒ¼Áï]rlpá'Ìz+\Àɧô2åŸ]Nzǥܷó>.ÿ£Ë™?c>¥m%,Ëâáz˜ÏϘèÓP”C¦¡ð¸yófÖ¯_ϺuëX¼xñD·ñ¨'é(žIý@<áDGY"ÎÉç¤ÇZò=é½'¡DMÝBÂnŠXHxܤ§d>ü,aA‹Ä¢Þâ h‹ŒÙD½VXïA?ч@¸‘wI庸Ģ™ˆ“²¿´¢È9‰ŸCmˆQ;ˆ½ “ˆé­·n½˜·¯”?án•‰eþüùl ?Ëÿ÷°‰Ž>±‹ª(÷bõ_ʸ?Zé8Ä…Uþt&ñŸHê gÌtfÂÍuÇtS=ØiÀ]x“{PÉ»ê@¿ŸÞåÃV®«Â þް>ùÁêÎEfˆ°x^,„ÞY•0Ñv´ ‚ö‹g”iâºîÐp¸ROèáåº.–"’cÍ0ã|ò;Îçc¡Â0xå•Wxñ߈>ÇŽö75i2mî\¹è"¶_zim,à ×^Ëyïzðƒ‰ïÄCj6úm¹.T*üðå—YôÑÒßÕ„„Ï%×…|ž{ä.¾øâà…p Ûš¤ùæ›QŽ0®„µíà%"[:‡&Íå†÷Fêó6޶³X þýýã^³^áTò$JUßšSÑ0Æ×QB®šfÜ—(Š¢(Š¢(Š¢(Ê!à7X×úÊ+ôMŸÎÕ/¿ÌlïeðáäûŸ„§ÙîSñó=Û¹pçù°Ðàœ‹Îaæ»g2øÎAîÚyVÕ"›Í²úÔÕ|èÊMô)*Ê!ÓPxܵkÝÝÝìÚµ«fýÙgŸÍÚµkY·nÝD·û¨ æTLÐ"0Šg#Ä¡ˆ{‚‘ ‹P+hÉÜ}›Ø /©eˆY “ë¥\qøPÑ8ºrÊ{qxÔo>ñǬtXO>,/^™²_R<õ¨õ¬÷ ”¼ÞDZ(¬Þ4+צÎ${ÄQÓæÑëºìøÃ?¬ñ>(%Km¡6)§ü áò¿¦át~7_ðáïMø¾üÉ3€í±í¦›˜?~hL÷¡šøg W„yÙ\‚?é;ŠpGØÓœiÃÙf<£ ”àÏûMª>,³àãFü‡ý¢?ràQî7á›ðÍX½´[8Ç€«Í8¤cšà8¹<¼T†s-^ûÉÓL:.èéÁ1^ºó%Nºg)Sç8Û ý¹~ŠŸ-’*¥àü 49ÙðSƒï}÷ÿùûÙxѬø‡G"Ö¯|ãïŠ4Ûú‡¸÷‹÷b}ûýÁvÛ†ÿrèûqŸüýßç+Ÿ B_`ÓL¸"÷°ªóHÿÕwñ徫ݜWeûÖçàyx}ÓëùïÿýûùP <&ľÜ~;üþLâ)öOÿ3¦½2}}þñ¿sÁ¥ï:¿»\^¸ë>ÞòÔiþüç™bœOçk¯rÆþ3xÿûßOß‹/ÒºÀbëËóË·¶Ñýä³¼ùîÌ­× xxý\?ñO¹âÑüžf8xb&3>r¬ãt:†EhL¥âü…åòøåßóý@Ü;Ò±r¼dÆ#eç/4G¯¢(Š¢(Š¢(Šrˆˆ>éldº.}^ÈÏ›‡7ÐØÖVø°/ØþÊÉ­ôÎÞÇ…{BCa²WÞö «ç¯æ5ó5,Ëâ‹_äC_RáQ9ú9áЫPáÖ½$Ôh2h2<ªD6”¨":Ö q’»Ñ%)SÄš✙Ø_Ö—ÇCÊ‹g¡ä²ƒ@<4¼ÍD=Õp½ø(å!ÖS¤1±'ÍŽÉð©Ì€0P™H\×å• ø[jEÿ†H°{73}”ǬÅ,ùhn³bÏ# øz ¼8fÐÖ»€¿'á²ká›&F.üÖÿ?™æµæf¦¾ûÝÁ9,ð£Î X,rÅ9ϲôLvù±W"Á…Üþòv6L{…·œ÷~V^õf¾õøfÞú¦·òú7íâkÿÙŦ0wÚ\L³è£‹¸æñkسy³œYœpÖœunÑåÄ/Âcïžþnfù³ànxæÁgxü„ÇYÿëYqÏŸ÷Þèº6ÿðiNxá7Øñµ,øÚ®Ùw »¿i0óËÍó·?Ï‚m6­ÀY—~†—ßû2¿zã¯Xðé°?À3Às{žcãéùà_~ywíãþûïç´}§±èÊE¼ôÑ‹xàK÷2m`;¶•+_÷Qæœ:'8gÛf§çá½µÂÂ|ˆþוüî»Oâ»ßÍqêù§ò+ƒmú$où=¼qÚé|íivÿ󰾟âÕ_½ÊŒ­Njú¶}ëqü¿¸‡…s>ÄgÎíæÊO^ Ÿ„VV+øÅª{ù­_¿“é}ÓyÂ}‚ïˆg¨àÀë~ñ:^×v=S¾y Ü×)X\ïƒæé)‡Ð{•L&E*ž~¶=4—áaÄ/æ•NæþÊ2÷߉ ,ž¡ž´c4OREQEQEQE9~ò“ŸÀ…bY¶L¾Öƒ-&àðó•mô¼´ƒßÛaïã4 ¿<ù—üèG?bµ¹€Ïnø¬Æ•cÇ ñl”Ȉ‡"1êy‰r~ÔJl“‹RÎH¼K4C *B£0œ '30ªÔö_"iÔ;3êê«_?êí§íøÓ§GžºÃ"aOS±‡åë…¯úP£Eàü<”Ý8„g.W“˱,ì\nx.ì–ºr9ÌR)?êy¸®K6›Å/ðó7IoHóÔ?ÏY>+ØÏJa.@Ó DƤ >Œ?ìº.•J…B]N0Ïóð<»¿Ÿ ÚÛ1}Ÿ®ºp¾ïó¯í³)9¶Üº…§~L*• B›º÷{/~h:÷ú/ÒtÁÎüÎ%lõ}nw¾ Ùà¹\Žwüû;¨T*<ô†‡¸õ™[y`áìÚ¿‹®®.²Ù,¥R‰V~Èõ¥ëùóÕÎÖù[ùþæïS­Vñ}ZBñ6 wzÂÏ«ƹ|ò™OâŸãÃ9ÐþD;þÉ…|þóŸçµ¯±è‹( 8ŽƒçyTÊlÛ&ÿ`ž®®.:Œ–ØKð–x¤;Òx7{˜ß4±mg‡Coo/Åb‘…Ï/äû·|Ÿo.ÿ&žçQ,¹éÒ›¸¡ØÂÇÓÿ€a,¿q9†a0eʪÕ*æ'L<Ïcõ^|ßçwò¿ƒ?×ÇŸïãû>…=RÿWr%íßkDz¬øÚZÓíéÌýü§Y`-à×Þ¯ñ<ööväOýßHÐlkk#“ÉB!Ô¾ï“Íf±mk•ņԆH`ë ½7-˶í!¹ ÃÀ·ñDÃ0èíí­Éíiš&½½½8Y©`Ft=s¹x° }Σ°|Ûçoãšë¯‰Úœdpp°¦Þ¨ý¾O¡PÀ0 <ϲ_©TÂ0 LÓrþ _[Èõ{_æö™3¹fß>öOobÚ%o¦ÿýôôôÍf¹ç{Qô¦›FûK(‡ƒJ%©:œ÷ß½}ÀÛ Ö‚Úõy°≯ÿ"x{¹µëE–ú“¡b¢æ34g2c›Frž„b+à ‰ÉñU²í ¤ãâ±yD*WEQEQEQŽF"ë“ç±`áÂàóÝ•`ò‰.¼lÂK‰‡És 87xê®T*¸›]¦ž:•¥,mhçR”£¢7ä Œue†Š‰Q<íº2É.%©W$C’6B½ åðòÄË/ÓôÅ/1¼S&°vW òz Q,ã×…ÏT`³级–·e²³£ƒæ¢’ëºxžW#v ²Þ²,òù<™L&ÁÒét$vuuñ³7üŒoŸøml/ {Í^~ÚôSœ‡!õ:Žƒïû¤R)lÛŽ¼¥-¶m“Ëå¢úMÓ¤««‹r¹ŒeY‘˜—Édð<¶Ÿ·qÞ-ç‘_˜§X,ò³/þ >R+.vuuEj=†aÔˆr0T´†Œÿm³¯åzf„Ë{.¾™Ów]ÂLóôèºÊù Gf”Œ¦i6Þ߇E\Da0›ë®»Ž¾¾¾ m«„T•øÖÌ!6®åï’ÞÍ·72Û46Ì5*§ö/åXe¢úÿ˜2H„–„ª‚?z‘àÛEœ 5iÔv]ho‡>¼rìÉä( !IÑÌqœÀÓ’@ð!PÂ~zžG[[Ùl–r¹L&“Á²¬È ±££ƒþþ~r¹ýýý¤R)^ÿ_¯gÙ—–áû>¶m³oÛ> Û •JQ,ioo§X,FÇI§Ó¤Ói:::¢cŠÀ•ÏçI§ÓضM¡P T*EáJ¥===”J¥(üçyŸ8€?\ý‡d2ÎzÿYQ(W¡ÞKòp²ïôKØÿçÿ-w¸Ü=ç‡ãr¬!Ô'æmçr<1³24ýìgœüÞ÷Â~먿QMc*•à?ïyNÇëK¥Ú\®!uÝBÄp!žýp ]ïöƒ;­Aù­Àöå_žhPþypv6("¸]ïLo,JªÛzÊO7>×Fu8#¬o$<º{Àh´S0]†W6ËŒ|ƒuþA¬¯4X_¥m•º÷dùù¢&)Ãõ“®PeÜ8ªÆŠ¢ŒÚ(Š2ÙúYÏ?Dí’‰â¡!¨5÷—4ž@nš&g ðÜÌç&êR*ʸ1¢ð¸fÍÎ>ûìè°aÆšuÉm‡‹ë®»Ž¡Ö£õë×ÓÙÙɺuëØ¸q#}}}\wÝuGìb5²7‰½F4 ‡ØÆ›¡Ö»1º1“x¯ç@&æ«Ç£r¬2QýÀ¾“Nâ-Ï=‡!Æê2qá±Àð1Ž-+ÈßæTáÞÞ@pÙqÆÊå2¾ïãº.®X‚;::p‡J¥m¯T*tttP,›S©Täagšf$f2™(ü(Ä!C.\Èi/žF:?f<:ƒ|ä#@à9™J¥(—Ë‘cµZŲ,z{{£Ð¡år9HÅ OQ¶mGžs ©ÂÂså‹ÞBGˆ¾/òo?~2ZΦ³¬Z·êÈ5b#¿{Hµ8õ¿K‰ó}3YÇ qÝ ·¨ãŸÇHýW4ìžÛ†Y?Ðxµw"¸§4.ïÎhP~6É©à½Ú¸ÍÞ3uuÈ9¼XW~ 8g=Y™À5¤-4ŽXÍ0åÝçÁ}¡Ñ†avÈx¯'+u€v†ªÁNØr]½~XG½¸Y _õåóáú4ñ}%Ÿ(ïÔ•-‡eÓa{E@̆¯)@[¸ÝiPo:QOñ@5/T¾Ïxê Žõ“²PeÜ8ªÆŠ¢ŒÚ(Š2Ùúk¢g͵à<N2á'÷+‹xžÇÃOЕT”ñ£a¨ÕÖÖVÖ®];! Ú°a»víj¸mÓ¦M¬^½šÕ«WpË-·`Û6›6mbåÊ•ãÞ¶ú ðI[–LHw<¥*Ä‚£ˆ‡3åXc"ûŸr o~á…àÏ\$øóþðÃ)ý®Ž‚x3výT~ñÂ/"oBÉmèy¹\. ¡*Þ„ŽãP­V1 # iZë]B04 ½ù«·ýŠ_~å—n/`š&7o½™Òß—0Mß÷1 #Ç¡«««¦nùzDejsIDW ?ûÄb#Äž¹1ã@9ŠíÉŠÒ‰ê\×Å0 öœ~:ïƒx¦Áp®ÉÅb 0x^Ó- ¥(Â^P1‘Õ?ØïûQøS!gj¹\.ʳhš&ííí‘(y œuÖYœµç¬ ýE°·"ƒ´´M<'aYÖsbDOqDÃþ¼ýçüÏ”ÿá|€·½ïmœváiG®ø!¸qŒ×M ' ?Ò*“}L0„B$ïg:&ø*:"'ç/8;€“‰ȈmÀ¡‡ðC‘ÏûU(<†B“ ˆþw B«šÁ6÷·ÀŸ—£¼û68+ˆE(3ôv¼‚À{Rú¿"x¿”ñ·ÕŠzÞ6áñGÀ¥á>à•‚eïÔ$]t„•îF°· sþ_+ÀékCX¾ Nxùœ-`/$ší冓Uó[Á<J‚× ^Œ}ÿû¡ð xƒ`,v†íÄ2±Ø—'è« âÐçUDJ@é³ðÉä”a_K&|™áþâI™Ü?yO)…Û­Ä#•¨†öŸ™ÄödžüquÕÕ!åzÃu‰c~wýwYÎr&+Ãõ“²Pe\8êÆŠ¢Œ Ú(Š2ÙúÿÚ»—™3gòÊ«¯p §öÁŸ†a7tÁMpaûãOpg˜:Ip]—t:M#€¢+œpèU¸á†Èd2,^¼xÈv™Éì<š››Ù¼yóˆu¿üòË<öØc4777¬{¬$Ã}¹“ÅM"û^4É=iª—Ïãa÷=JmÉÊÒ××G__/¾øâ¡W6Œg?ðâ‹/ÒÝÝMkk+­­­5Û$¼éžBÓ=/øS^0Ëçá±T <ùÛÇÁ²,L;^·kõ.ÚùN5Ø&áV-ËÂ4MzzzpÛ¶1M3 wÚÓÓƒažÑ$è”D@¨Ž÷·WG†x¦—t”Gˆ3Î8ƒ¿z"ù| Ày]_ê:ÄZ¹Ö…Cªåà°ˆ=³ä7Ü€îîn{ì1^~ùå häè‰1A£ýÃ]÷¬Øó™ø¯tH`gƒ:\pß|ôCï> Šš€ÀSÀaËzÀìïûPþd»¾X‚ßEü~¢~Á™ \ö{Áû-à plpó`…"¥÷@¼¿ Áøà}Œ=àK;Ê€ žæK¡îC!ßÿ«ð˜ç>äÖBö³ñØÊýägB¡œpÆV®3Ïš>J•·?R@e);¡†Êu`>ÖsP¶ƒõÞ˜ý`žÆfH‰w`ŽXÏÁ4‘÷ {ò…U¨£o$öMRfy´ÄÝòS9œÒÃÝ2âæÀÀv?ÊÖ­[ã/#õ‡:&Ø»w/ÝÝ݇ü| (G;›7of×®]ìÝ»w¢›Òñ~>غu+ÝÝÝ,Y²„¦¦¦‰>]E™0ôù`œžå(Bm†ÃÛ ë‘çØïíÞÍC3g²ªò$MO]•{ážðûƒá× Ë.ò‚аÅb‘T*…išôöö¢(“Í›7–1Á¨Âcgg'ÍÍͬ\¹’ÎÎN6mÚÔ°ÜÆ©!år™æææq ñºoß>6oÞÌ)§œrІ'ñnÛò=–Lz?’ŽÑãÂU9véë룻»›—^zi¢›Òñì^zé%º»»Y¾|yÃAÄ—|€ßzË[âpvÃo}?©˜jQv]ß÷É :<4»Í4Ïi&WÌáy…Bb±H>ŸššæA*v&' ùpŸÚG3¶'üâö=¾® BÙ~~ÑçIJœžxÂè0Ž öÿ#øÏf D¼óÀ}¬§Á|(‚Fœ-`ý`üü7ëÌý¿ìBævp>Æyì,¨ù‰x}ú!ó°Mðfµ ÜùP,€=?íÜÿ ë°ÁØ Ö—!ãƒ÷°^÷(®€œîŸ9ÍÙAydžT>7µCê%¨\:~Ü3b§òòÕáyüä›!÷Xo‡òœ ¥÷à.ã5°–†ùgA{_ FfúÀx˜{Á •Ø÷ƒÿ$CªBðtXß7ÔLÌ(“è2"]hú(}}}“Vxïç[[['í¸HQŽú|p˜žå(Fm†#Û “ˆýÿ¡–>ý4”ó2ø¡ ?*×NÁG:>w@µZ$"Z)aOP”ÉÀ£>ÊæÍ›yL0¬ð800Àµ×^ËæÍ›Y»v-+W®Œ: µk×Ò××ǦM›X¼xñ!‡eíî³“;î¸c\.Ö)§œÂe—]vØy;•„VÍ “G*š6tåð²|ùr–/_>¦™>GšñîæÍ›7lõÕÇgàsŸ×ÅÀ <`úG¨l„ç…SL¸ù›7sò[Oæò/§}A{”¯ÐÆ81ç¼9,ÿÀr.)\¬˜2Ñ-š|¬[·Žîînº»»'º)C8ªÆŽ¼W€Í…ǧˆ…Ç øï??@0ç“Àz xò‹¡ËÜÀ»ÐïjÈ¿ åГКÎlp/&0Ok+°¼?÷wÀJ—#óÁÞy@¼ßkfѵAÞDÞ©íP™|î€ãI‡˜üBØü¥qôP¨‚m’Û!ŒqFì˜k§ÑÍÎ ¶.Œœ9)åEÁËçÐvf@yFPÆ\‡‚ug†íZæ›ÁxXVN&É;>&qšoRÊ—:¥QY¨0HjÅ!?%ë†+?$—å0ëFâ•0µÂúõë`¯#Çx÷sæÌ™ÔŠ2ÙHÇëóÁ\ }¢ Ï‡Óf¨(G+j3œwPc‚-_ÿ:^ðpù ÐlÃÚÚ§Äú4G®ë’Ëå<º™¢V¯^Mkkë! †o¸áúúú¸å–[†Ä@–?áæÍ›¹öÚk8¤FH˜£o¼±fýúõëinn®ñ¦Ü¼yóYÉGb–²Ìd¨“,CP‰,2©¨(ÇD÷[Î<“iÓ¦ñæ¿ý[Xð/C­Ñ¾Äj&ï¡äd4 ƒL&x*š°-¿ €/tÏóèêŠcó —_Q9DL¸„K&ºÊA2Ñ}Ááº5!U#ê<½p¨ÓŽ|‚ð¥s áÃ}+XƒP¹š ÷£C¤>ÙMPl <ÿŒÏB§Œ&碟 v1ÂÉù“ õEÈl…Ê`¼¬7g)d—Ƈ®2;ü07XoÔïÌ šéG5‰ó^‹øU%;ÃÄBŸ8ŽD9M§VLÖ+ûAY"ÆÞN”“G6ɵ¼ð{(hª¢*hk¾RâèÖ׋€Ùð\ëë…G?lS}Q¤Ú*4E.4(Ÿ¼^£Qdr;oŽÖÈLç ïE7Žª1¢(ã†öŠ¢LÆ~@&âÎaN°Âè‰õ 9øû¸l>ŸÇóg¦Ç¢¤gqÑ?WÂíÒ\+híaý¥p]),ßF Àå‰ÿnF¸\ ød[ªî]¶5ñä8ò™ŸamÿD ²«j»‡8\~ñ¼¬ÿªå:¦êÖ‹˜©«CŽ‘ìzœÄ>VÝú Cs€JÝõžŒ"HÖ=E¸«ð(ǼlŒå4£õ“¢Pe\9jÆŠ¢Œ+Ú(Š2™û‹üsø“9¯‡>,¶}RM¦VJ¥R‹E2™LMQŽE†!»2—_~97Þxcù`.ikÒ¨ íéììäòË/§©©‰ 6ÐÔÔÄå—_>®É'=âýâõx ˆxW,ñ}DϨJ¥‰Òq5Ê'”ËeÇÁ4MÊå2]]]CÚ#9ê$î´išxžG¥R¡··wXÅó¼(̤ã88Ž3âì ×uq':0$ô¤çy8Žƒa¸®‹ëºÑ¾©T**Ÿô8KÖïy^(” sòyž‡a8ŽÕ)ëMÓÄu]2™ ©TjÈy%ë°,‹B¡€ëºQÉúåF"åe[µZÎË÷ýšãH9¹6¦iFß«ì/å ÃÀ4Íè{‘ëeYVMrŒíÛ·ðïv¼™è~`Û¶mÌŸ?ŸÏžùÙÀ›üæó§ã«¦R)ª qÒ²,Ç¡\.S*•T|±÷dò¸f¢=±w¤´77Æ«~øK_0¡ý€¢(ãÎQ1&PeÜѾ@Q”ÉØÈóÖw¿šñœôd£ÙRfóæÍã}ݺu\{íµ¬ZµŠ¦¦&úúúX·nÝaO~]?³¼ƒZñ(8˜î¡\.S©T†}"Ò …HH”†a ¥ â¤mÛ”Ëe ÈÄÇJ¥‚aC’ÖŠ'¹æ²Ù,]]]T*JFAÄ.Ã0°m›b±H*•Џúò"þ‰ –Ïç1M³¦=IñN®…”‘6&Å@)#mð}?j‹ˆŠ¾ïcY©T Ó4ñ}Ÿl6íkYét˲jêN vòYêJ§ÓQ94-ËŠÊØ¶cRÀ´,«¦¼ žo¸Ù·´´Ô|¯ÉíÒžäµO:˲"1R>‹Å!7­|>?¤-–eñ½ï}ï ~½“ƒñê^}ÓÛ0Ÿ™Íü­ókgH·Þ^ƒ'±ã8ÑïÌ÷}2™ ===乬$.¢G  Ntƒ”ÃÍ‘ ¡£<wéÇ0ÿô­ÉŠ/„ï?"p#“[ÍÙÁ›?‹`ápV‹ÀTpþ6Nó(â 5*KCkZ°>C®ÔN”…X$L†€Oz ÊXFC K*Ô{&Š&ËÃéøõáN….Ff<{Es!°;YÛ ÆxJ5)Ԗ¯KHjíºõ.±hiR+X–åp¹H,ÊVÂãJèYÙWB¸æÃmÕÄ1ráº2Ю“v¥Ããäm(‡yQ7Ö'“ç2‰cúÀÞö6Þóê«ãøMŒÖ(Š2©Ð¾@Qо@Q”#ÛÛ€ùpÖÉg±ç„/Á›Ï†g2pC<•Ä6,öfõtTŽ Ë—/gÆ ôõõÕÌ&h4»@¼#w¬ä'Ÿ|rȺ¦¦&î¸ãŽH]²dɸtEÃx:ŠÝ°@zì@B«ú¾Íl(—Ë‘ZR$*‹‘g\6›DÛ¶k¼“bc.—Ãu]J¥R$ú¾O[[Ùl–r¹y*Šçžš–eEž‚´··cÛv$Rõôô4ìÇ¡££ƒr¹\ãU9œ¤ã8äóy|ß< }ß§··7!“ûe2òù|ä µÂ`=IÕ¶mÚÛÛ©T*‘™ËåjDÛL&C¹\¦P(ŒÉëT®qR¼k„ad³Yz{{£6FOOOgâhŒäÅz ¬Y³æ°Õ5žÉ~`Æk3øà¿œ^›¸LÈå‚0«£ ÿKùo%½WUt<‚ˆ%Þ î´•£š‰ Á²Àqhïý(Õ§ê~^χïÛˆ]Ò,ðž–×N;ØŠD­ðV<9 öY¥D,˜É1¥W²êöIÖY/ Êçdù‘þ"GóL 0NªEÅ5EÐÕB]–`Ì—^ó@K¸¾Dð•fˆ'Ÿ¹ªO–6î_ ë´&°‰vO¸Þ× âEé¤ríEd.'Úž#”+ÔzDæÂý²‰6'ówJøV)ïÿ4olÝ:Ñ_ט¨ï &¬Pe˜TcEQ& í E™ð~à^à8¿ÿTÞ±õ`gî/h^mQ±S‹SŽ¢4—,Y@gg'ëÖ­±‚ÎÎN€†îÎãÅx{VŠq(O­ÑO“Õ{ˆ05â D^r"D‹Å(f*•"NcÛ6Õj5òP,‹¤ÓéÈ{JD¹F™xGV*•ARñ/IµZõÛ¶‡%G*?õ­eY5a*GÃ4ÍaQ„¿±– ñ° sÔM^óe<‡»è½ðM@èñ‘üyÛvM(Åá(‹tuuE¾¹\nÔ}”q"ÙIk˜Õcžñ ¡P ÙtsÀ|ôN"V›RàÏk?p^à¥ÖoƒÞ.ä§*Þo9âpîÚ]„¢±Ü1†»;÷hs,߅ꯅMðü—"çäš”ˆ=-ây òCñpñ7M,àÉ÷T" “ž¢ibAÓ"è–ÄÓQ¼MâIo™D[ÍÄKDb#q>± ê%ÖK{$çHž§ù3Î8j„Çá8âý€¢(“í Eí E9BýÀ¶àít‚)Yð*`¥b/¦I/–tPP”c†ÂcSSk×®eÆ ´¶¶›ë±³³“ 6°zõê#*<Ž7IÃÄ3Ä“ùuß÷I§ÓC/Çq¢0Ÿår™jµåz¢žâ%W©TŠÄ8Ã00 ƒR©„mÛQXÍÑ-Çc#ÄÅ[ÝÁ£±¹~f]ù<ì{_&ÿgÌ%'« ÊŠrŒÞ½_‹ÂuEðÿ"øè‹âT&P“~ö´8ÄfùÎ@ä‚8çžâ™Føj—Êa@„ºF£˜ú<—Pë ±ç¤ôð]uûËH0U÷^?ÿABÞ*ü&ÃÚ&GÉ\‘’Þ²¬šýͺ:Diº•ÌÚ»—77£&:EQEQEQ”±ñËÓ œÆiÓO Vün *0kŸà%¼j2–¢œ0܆L&ÃæÍ›¹ñÆÙ´iSM²Öîînº»»Ù¼y3‹/Õ+òhÃ'6J$1RÕû0IèÔzAñdD"Äã°Z­â8ΘÂFžŠŠ¢d¾ÑŠ–ÖøOîy£†WMæfÍf³‘ç«þ_å8aEâ³ü˜¯ !_‚‚¸ÎM«Ý-{R Ý£<Ï£¥¥…¶¶6<ÏÃó<¾óïð /ŒÛw£(Š¢(Š¢(‡ I; (Íc»>Í¿”/aë•[áéðY474^‘ëºäóyŠÅ"Åbñ¢(G/'Œµ`kkë1•Çq,H. zù°\.ãº.===‘Ð(뺺º4Ì¢¢e|çsÉÜöKH…qÙËeæìû>®ë’J¥¢É¶m“Ëi0DE9fñýx"‚<~\H0c)¤À;Œ“ãÝ’Ó’ùÑó¼šd•Ïçééé—¶Ô ‰Îf¸¾9Ncš&Õj±Þk0þÔ÷}J¥®ëFÑ*ÇÁ0 ,ËŠ„ÄL&ƒmÛQ¸}ÿŠÅb$Š×¤aäóyR©T$rV*,Ë"›Íây^Ôv˲èéé¡­­R©D.—‹r [–E¡PÀqŠÅ"®ëbš&Åb‘þþþhV­\Ã0Èårø¾O¹\¦\.3uê¨ó•ñÄ#˜¥à¸?»Ä3!!p…®'œ·å!Nê„uå€|bI"[&Nj†õyá:Ÿ «$>×ϧ²ÃmnÝ1“ä’‹BÐÑI»ëÛRL”É×Õ‘ Ûå?ˆÉlìW"Hš+uCì&n†û ï:î…å¼Dy9G#ü,ûK³n/<¾\K¯Áñ’u$m¥Òf™'×+y7¬7Ù&Ù'é>/í+'¾g/QŸ?L¤íŠ¢(Ê¥R©àû>™L&²) …HX“Éh¦iÖDÓ1h±XŒÆzRØ(]ׯ…–eEc[Æ–"ÜIº˜äk)cFdÿ}’Ÿ¥nI;CÇÔÓ%Gy²þäyHÛ¥œì#cÞ¤ý —ËaF4™NÆÙžçEuK›¤ÝR§iš¤R©è™AÚ$å’ch9ïúÉ„™LÇqjž‡äyAÚ¼Òis¡Pˆ&Ö_Ÿz¤®$ŽãDõË3‰aQ„=ù>¥N™$YÿL#ß]²Í¿þõ¯'úïqT°ü×»‡¿ óÃ|–eQ*•ÆGQŽÆ,</$Ÿ‡Ë«T.—£›³P­Vkn¶Š¢8ÀŽYûùùæÏëƒÜŽŽ„TlT>Ü™¦IGGƒƒƒ} Š¢Œ7® ò>®ßÅ¿‡\žÀþÛ`ŸØÚÅ6œÌ-¶ác%°J>Ÿ§««kLeå}¬”Ëe²ÙlMÛÈ!˜¦ dÿFÈ{WWW‡bKK ¶m“Éd¢ù]]]‘1"ŸÏG“L*• ÙlÛ¶1MÛ¶)•J˜¦I>Ÿêhoo§§§'z°±Q<3™ ÙlÓ4Éår8ŽCKK ½½½‘qCDÉÞÞÞȸ!F)ÏóÈf³T«ÕH ƒ’ä‹A³Z­R.—£ö ™L†;SN9åÈþxŽ\bñÇg¨—"È2aùä$g‹àa#):¥©Möjt("D剅®zKÊÈ>IÑÉ&œêÅMí—c× †R¦þüe»Gœ£‚D›e»[·,b—Uw+q­DÝIÌûÉ9ù‰ïC8+ü,‚+@?¦ã"€šá÷"©$äÍ‹w>P%ðz7ÂÏíuí!ÙI´£~’û 0%QG9ñQwìä¹Èù—.‚ߟ¨#;J;ÊÄb¦ô@ÊÕçXEQ”Ãçy”Ëe à\.S(j"¤%5£*• ¦iÒÒÒÕ#ã¶ú\ãårÏó¢|q¤sjoo¯»R©ù|>ÿJ^9Ïó¢úd»mÛ‘ØæºnÔ~Õê'ÝÙ¶µC&ÞÉXO!)ä%Ÿd"]*•Š&æ%Ó ˆˆ&×IDEI7 ã^™Ü'ã3ËKÉä9U*ŠÅbteRžeYQ=rÝd\E8lkk«;E8”ñ¾<·È¸¾~/)Læóù!é꣺$ÅÕT*Õ%m”ï´Qt—äÄHùÞå:&;oxÃ&úotTÐÂÏy˜õ,{â©ËU*•è™LQŽ'Tx¬Cž—e’mòY>ŸÏGŸzC›ÌFW”ÉÀz¡ÏøÀEœÈÒ™áÀÊ0 Zm—âYp¶mÓ;Œ8©(Ê1ÄÍå`æ¢<ì»Àg€/‹N2ŸÃZb»z†À¾l ÇŠ§£ 3£Çz¿©Ÿ­]xÊC}2÷…„´—‡µl6‹ã8är92™L$l&g)׋”ét:íÄ à8N$Š 3¨]×%›ÍÒÕÕEoo/ŽãÐÞÞN*•¢T*‘J¥èèèˆò-Š¢½½®®.ªÕjdÐv‹‘&Ù61–$.b #´)i\Cl7 #óù<ù|ž\.}?r‰èXáHÆP®ˆ9IOà µBŸˆ‚9b±*E<bá-©÷ô78v½ÙˆäúF3'Ç2ã¡:ÌçáhÔ–dG—Ÿ§P(Dëe\#‚[rÖpWWW$†V*•šû¬„«’F¥R)ò`oii¡T*ÑÓÓS3C]î³mmmtuuEb_2|kµZDLÉñ-F ˆ=“×LÖ%…BY®¿o×q’Æ‘‘Æ?™L&N5ø!P!ø#‹Ç ¸3W‰=á’—FC‚£ã‘áØ§ÑÐn´ïÆf]r½‘x?œ\õÇ ¡;Ò9Ö6~uʯã (Š¢Ûd³Y àX,F^„2•Hâ•&cÞFär¹Èëî`h4O®Í^v°Â—p ¢c£vŠ=¥þÜÔN;^ç>l2-ÃÁ0Ú¾£ýž†û=*cç­®ÇV¶r}°æ¯`ÎðvD ¥¬Êñ† uˆà(Š™¹t¤7rˆÐ&1¾'ƒP*Ƽ¹¹'Å6 “ û‹a0¹ Ãßü%¾¹Ô'a’qëŘçû>ííí‘G›„3KÊårf-ŸÏGyÿ¤­Ùl–žžžhö›´M ®‚Y•J…žž È„Ei£„Z“A™ü$_“„I¨V«5a2$܃\ ÷­o}k¢“‡9ð³÷1óô™c*.¡=’!1E9Fñ<˜6 oà$Ø®ë¶ÆE|ÀùPå±Qަ^¢þœP3ôÒxQÈ"ÉE#!˜lÛŽ„?É¥Ô̦–™àUò(Šh˜N§ÉårÑþär9:::Èd2T*z{{#ÏÇdˆ$™x“ñ|ß"Sttt±±¡··7$óʈ°™ ÷ÚhX?®9T#Æá öi2Œ:\b‘Ñ&w™bÜäxEQEQŽR$äi>Ÿò3Ї£Dè;›&Pêꊢ]CÝÜr¦I©Z%Oì@/ëÉTÌdAl–";Õ§†ÚèB2:z8:¹ìë%ê«O)¬CEÊkƒƒ œ8—/?Ÿhü/þ¡ôŠr43u¢0yù‡?â¡0’÷ÚxâºnHU©T†Ä÷®/ŸL-žuc%™ â˜é³¿ˆu‚ÄŠÅb$˜É±’å³Ù,íííQ]"-y^bè,‹äóùšúe (×¥££#:ŸJ¥B{{;Ùl62rvttDÆHle»x\H¨Ý¶¶6òù<år™t: åsJzU”Ëåè$ŽGGG«Ê”)‘è˜J¥(—ËtttD^µ’d;•JE!2êgËe2zzzèéé‰bÂg2Òét‰mÛtttP,yÏ{Þsh?Ìcÿ§0cÏŒgŒÉo b¡Zâñ+Šr ã88︶ä×ròfí„Ü–D1âÔZɨ‰-?É„‘¶'ïó’#D™™Bò>-v óù*9 …B$JBfÕ4ͨn¡^˜Ëår2æ’¡V•1R$ÈÛçÌ( ^‹Š¢(Šrœã8NdS*‹Q´ŒjµÊe_ÿ:©L† Á"O¾·-|o ×OI,片iâ hAæ?ùÄ‘ÞsÏÉgŒdÊß p˜ —!=âyT•° a¹lØNy¥Ãwi³”+†íÈ'α#ñ9¾WžŠ‰íÒ¶bØ–r¢¬î+Bi9Ñ®b¢ž6‚TÊõO6qzdA®Y¯Áº$r¼a¶ùw2̲W÷®ݼøâ‹ìÄgà-Ó¸oÞ'‡-'6|±-+ñýC¯C™œ¨ÇcŸà†²ùK_⹋. Ö…ÞhIO»1#S…F;®ïcøxànM˜…õA¡Ðþ%lb+—ËA¸1Ï+“&ÂTd8KN¯’“5†®Ïf³5á;ÅØ'³æÛÛÛ©V«QÂåJ¥BWWW”4[¼ü$át²c•„ÓbO<2¥¬(+• ¥R‰ŽŽ,ËŠÚ1eʺºº¢uííí J¥Rd¡²T*E±Í%~¹„~K¥Rd2:::"c¥–eE¹™¤¾R©D:ŽŒ©æM„>1|Š@%9§êãåËùš¦yQÈoK¼,ä%³b’û‹fr6xÞIø¹d¹$RŸÆkñN€—^fÖóÏÔ)Ðß„[M–©K.¿?EQŽqd¼ØÊΉ‹Èl`›øv:QáUë£"È}x8M¼æ(?bR¤ª_'yH|ßÇ÷} …Bh(^û2>û˜LŠì#" äÐÎår‘XÙÑÑAoo/]]]QY¡Z­Fí2³<܇%bÀXûmíßcÄÂU`l9EQE9¦›X:ŽlZ«7l ˜JEÞ‡îªU´…å3ÏU‚gŸØ+Ñ!ކb y.AzÞ‰”R?º«µ2OÒQ·‡mI¦Nš2ݰŒA0DJž£•(“<©;¾Ë4G#±Ý$ ÅëRŽ!m„àÑË—sáõëhpNP)*Šáº*±()ëìpE ZRw'ÅE3<¦Ô%©¼“ß¡ŸØ.ׄ°n‰¾n„uÛá~âÑš _n¸¿›Ø_DbIGU­º2’@ÚB¢¬è8fâ»që$B®—gZñ¶ýÙÛß>Æ_ÔñÉý}}¼ŽóyÓþ†Wži¶œïûd³ÙÈž­4ÆqÀ²@/ѱ‡ Z€…¯½Æ–Ç‹Ä1ñ€“p_cF¦êÔßý%VBxG}ø;ã9«šV ŽäJÁ­ÖÄää'OŽv¿è΋xáu/Dwîb¥H¹\¦ÇèaÛ‚mXŽÅÇ®ù8pç³w²ìK˨V«Ø?·!nGo>k²ã;8á/Nàñ=ÎEW\„k¸tù]lùß-,ì\ˆ‘3¢°gâ}— /)â£+• ¹\.Þ 0úIn¤L*C.“ã¹ÍÏÑžn'UHQ-U);QD¸OìÓ,\¸þþ~–ì[BSS ®Z€çy<ö±ÇXd."å¦À…þÞþèŽüÿöäÉGaGEÐ, ‡]§î"“ÉFÊp Yo¦7¸ËÁ9íúß]4ŸÛ Ä‚`OOø±“ 5VåHvcaO„ßF7–‘¼(D¬ù…u;‡ï2j‘SrdSÿ{3©YjG^Ë ð²s7ç^yzp§k>UŒï"P«QZQŽþ0«é.#îK-ð—€qjPDø&C¯ Qä^dFM%÷q¹É»L ‘{¼L¯A1¸¤R©Ès_ö•©ÉðâÉeñrL†>­WZ?±KÚ"çPÖú@Â\‹Å(²A£ 9ŠRƒC` RÑQQEQà¯ï½—[6ofJ>û‰OpÎ#йti$UˆC—†f¥’)€íÛ&"Óž•x/0tÒ¤YW¶—À4Õ¶÷@'Y&GúIÁRÄ0ݰìp#}ñÚ¬A+¦®"ñP®LàÙ)"[WX¿K,úµ§Çè¢Ö?CÂÚ¦Â㊙|æ+†×CLs€,árˉ¶”ˆÍ{2ÏMÎ)Eì™dE,1TÍ‹¶6±¸kÕ½;ÔzaŠXZ!f;ꮥ„éÝwÒIø-_t.\Èïs§YÂÿ¹¬Dô9ž„GñA’Svœà³,W*`Û±ùÕuƒÏÇÑ%:nPá1Dn¾ým:B‘AŒo½½½‘KîB£!½ºŒ@ Ž' ë{‚u/üó ¼Î},ê^þèr~õ«_EÓ¢žyö®Þru0ý§O<ñ²åOà{AUw]}ó¿7\h¾¸™O/ø43nŸ·Ão,ø æÌ'Ý›‚ê!gäxí]¯Á©0÷“sy|ÁãLûÎ4ø| zt®êäþùîßåk3¿Æ–-[¨¤+´Mi£à¹í*N…”âîw3ûwgãLqøÔW>EÓ½M¬éXÃ]—ÞÅÀcüŸ“ÿæ»MÚ6´qÇoÜÁ² ËÀ„6”~œÀÀ˜©f‚»~ þò[\çnÀ‚EÅEÁèâz0 3¸ãn ¯£ŸÞß—¹Çv"C¨é˜œB0ý©ÍF3©|*žr”£vv» ÍåæxDS$Îï“'œÎî'?œñGF`R.•øÞ}âiI2j)h¤.™JfÇzh!ñ[*ÕÕ-þ½D]yâQ„l¯ÀæGèŸ5ÉñÁ}+¼ÂÏ8©ûçÁ¯bä.‹šZQŽ'~Ž|¡&Š· žë!!‹&"0§xÊCL2,4ÄB£xB:Ž•—’—F¼ºå³¼÷ôôày^4.oß÷Éd2‘h˜Ì,ˆ²,ù…„Ã1Á#•J‘Ëåhkk;â9º•£™08Q³êŸÈ× Öy^à…mÁD)Á÷ƒ2B£:¤ŒeõÔÿ¿d»ì'e†ù}h=É:L3žºÜ¨é§Ž…\Ùž§VEQ”cJ¥‚g¼pÇ ôö²hþ|®¼¥KùC#­AúÇ2B–»œ¤•8’û‹© Æ>çK„ÆFë“"n£óªLóáºúsÊ4hO£ï·4Âv›Ø\ï"b¤Ëè³ø¤Ô!×°ÑòHø&fñ¦ìmpM×Ü}7¤&*ŽÏäFÒ¬ìÙô)È|jÄ‹îyÞMš­Ý·vˆÙÑ™Ìø}-•ÊÈuË£ÄpÛ|?6©Êc‹´ßuƒu’êR]äxòhq4 <Ésõ¼xÙq†>®M&å{>4ÇcˆÌ$q‡7ÍyS”Irñ””F; âé(™¢ÝÀ0ˆCì¿ïBŸ38‡K¿$ò×·*³öÎb°k,¸dÛ%|­ékìÞ½›ýÚÏG}”í/ogǪ<°â¾¿ùûÌØ=ƒ—=È–-[¸kÉ]lY½…{VÜÃ/^÷ vüÕÎÚu/þó‹<¸êA]þ(­¿l… x†ÇO>òfíÅ¿w'_yî+<~Éã¬Þ²šÏíúW?q5ßzý·xzÎÓXe‹~僞ÁßúC¬‹;çßÉ9wžCëûZ± ›‹¿1Kÿu)=ô0ïÄyüÕþ¿bêê©X)‹9]sXvï²à®šƒ©ŸJÓº¦à¼Ó x‚Ê@D·Á:Gp7”éH½n‰šX¶äv2=3Ž· É·Œp_88þ ±¡Iç‹ÝV¦¥ˆ§2õBäû”ze:›Œ†*Ä1$¸Ó%âŽI<=Nb>Â:Ká1{‰ã=TÃòýá¶þp9Gr®ÉŒ¾M¯îµ÷•¼ŸÉüšŠ¢Ûx/‡¦ƒÿâi Ôv÷É0«J2Oâh”ËeZZZ¢eÇq(—ËѲ„-—ˑ翈„xJØôt:]“WQB‹wuuEù—K¥R$(Š7¥ä ®T*5m¯).^—ÂDÌð”cöööi¢Ô ±Á4¿ˆçO—ŽåòÐ%ù|`%hk ^õ¹Ó'ó>eJ\®.ß:ù<´´@{;d³Cëð<(!Žë¨Ïí*Û¤žŽº@e®[ÛÎŽŽZ1‚cK[[Z†¶#Y‡œO}ñþ--CÛá8ÁþÉíêsèèh|=ä|åU_‡|/ííq{j~~P&›¯[ý5Íçƒ}åz5ºÉkÑÖüFµCö¯ßî8Á¹äóÁ{[[­UÆó‚¶É5K§·SÎeÊ”¡í,—ƒã§Ó,üõ¯QEQ2¹Ÿœ;—7õöÒåy<¶`Ad¢9ZEÆCe’ÚÑš‰œo–alÞ®Ã=A%é5\ |eÔ¡Ó§ ˜¿u+·Ü÷©Q/ºmÛ”J¥aSƒŒD6[ûX0ÒœÀ±0šÙ¡~{1¡øþÐG”$¾_;uœÚúê…Eï|?Þ6žÂcý{4ê‡Ëõ×)y-äQ0¹<ÒöúÇÅúë^¿½þºÔõç6Ú¹‹ÃosÝÚsòÉ“yöÙyvñêPÇqdp]—/-ü+Ý•qˆN¡QèT 2ÞCð[Bq†AÈ¿óï°ê‹«ƒ†Ì{„¥ÆRp`ϲ=Üáý,ߺœéÖtªß­r^÷y¼|ÚËøÛ|~±ð\òéKø£þ#>ü̇y~ðy®þÚÕä 9¦tL!—ËÑÿ—ý‹ ¦_8w,|†a°…Q3Ó2¼ýÿ½=òTøì/>Ëw+ßÅÎy¹†a°øÚÅ,²±÷c{Éüe|˜íÍί§Û§ƒ ó˜eXš_`âuÁÝS¼ñ’a=« Q•÷Fo$êñë–¥lÒn(uKðvƒÀkR< ‹Äá²2‰² Ó¼$©º2ÉãìŸfß‘î1£6êG¹a¶K’í2”Ï@凮@½å7zÁà  ÃNë¨T*d2ŠÅ¢zÍ(Êñ€ïÃõàµp¸çAá»D}®8¶Ë¼‘ƒ¥\.yBC24c–¤'a:Ž<]×¥££# ™.¹{zz¢ãJèSEœ«V«5³3MӬɥhšfT¢ȃÀp–DybL>¸n \ÉØÁ÷ƒÏɱ„î¹\ã§iÛ†j5žë7P>«Õ`_Ãhlm°¬ ÌHÈvñB¬?ŽmÃààÈud2ÁK¼/ëÇLRGý´ßúv$c)շò ¾?¬Ÿ´P(ÄÞ¡Ã]ÙDzâãÕGÚ7š‡h&Ó8öS*OX«T†n7Íø\ä<믉[~õ¿9GiK*U{9†œŸL±®?×|>8vW×ÐíçªRaÅ“O¢(Š¢ÀÇøC¾ým¦ìÜÉ Ï>{P¢¢Lf$¤ëñ*¢*sz{ƒ;¼Ñ÷}Òét”Vl4d¸–ô¤Ï:È¥á²w„£RÙ“m$¡Ðuo—úê…Æúúê—¥nB»nì Á¹&—ëýDŠÅàñj¸íù|íc[}}µßS°¿l¯ emíLnwœxª|_òžJŸ+•ZoÐr9ø,×N„DY.ãG®ä¹&—“ù0åw#Cül¶ö7â8ñµ‘ïQMDD•ú+•øü*ؾ}Û·¿CA…ǘ;0À½®Ë²¥Ë(•J8Ž0$|¥„Ä‘Qþ8⬼ɬÀx÷ôw‚Xö|e_úñ TcÎø×3(›eŸ¿˜{€íl§•V:ÿ¦“xóm&‹NZļsæqÁß]@__¬€b*–¨¿yʃ%™L&ð|Hù\á]y'Ô{̼y&3™‡0mäwŸ#ö¾K"ÞzÔm“0Ÿ4¨G<“è,)/!R³Ä›eœ6L?í´Ú»V’ãUEGE9Np¸«ËqÍ?ÜsÀ9'Î ñmîPL‚4•J‘N§£ˆ ’‹:ŸÏG“‹¤L&“¡¿¿?ò^4 #Ê} ÁƒP²žzê=ëó0*Ê1…$ªYzðÉ“YýÓªiBOÏÈOðcñ´M>7ùpy ˱fºtò’âåp$Ï¥Ññ’épÇ0MH¥¸}ÍÞŽ¢(Êñ|þ¢‹Xvï½üóÙgsî²eÝ$E9ìȈáXób=xÀÎ;gÔ1úH“uÓéÚa«s2œ¡KDµúùzõb[¹\;ÒîÌõ¡lÉ}åø¾+ŸæŠ(W.ÇB›iÖzÖÕ×gYAùä\Äry¨@–çL³VèLÎÇ+kÅ·¤x'B xWJ`™ÛéûXgYqåø" ‹Áü=Y–+ò=Éù&•NuÖÏO”ír.rÝeÞf¥œ‡œŸÆòh!âf¹˜±Ãùƒ‘x*"µlÏçã2ÉëW.ÇßCRඬà\^ÿúfÞõ®·Žö·‰ãZïß •J1¯2L* rEâÞØ —3ŒvM²ÿBf³?ó0?ùÅO¸fÛ5ðس'ʳ´èÊE<ýÓ§¹è3qã'o¤©Ü„ëºdªæŸ6ŸWÜyˆWB«ÙzPç˜L Ã8°ÜIæ®?† Ð~°È³¹:b(cá8mû‹£†ìèè ¿¿ÿ¸J­(Ç5® MÁ}ÒòÁ5‚¹FqJ`›CP“\Šc%ŸÏcÛ6¦iâû>íííär9<Ï‹ò6ær¹ šA2¾««‹r¹yn –et¾ E9æÈÒxì˜ËÕNIM2™“w(Š¢(ŠrP”é÷ßÏŸ pîÂ…ÝEd«OƒŽœõȾ`a„çéJ¥B¥R †«+!&J A<ãDd‚¡Û“Âãh¡T“!:¥Î¤P)^ŒrJÉôòòY<á¤Ýù|¼M=ȼöö@ “eë ò’Aeòù8]¼ˆ~IaRÄQ©O„W)/b¤\ÃŽ/rˆÔiÛñqÅ{ñÑóAÒ²‚¶&óTʹV«±Ð˜Jûe2Áõ,•âkš3K¥øZ:NíÜCñ^,kEEù~¥ étœã³R‰CÓŒ3~ˆ÷£‡qWêNz–Êw"bä;-•‚z2xúé—8ë¬géÿ¢9 l à…ûî fô‹g£P$Îæ+9ý’Á° Ôæ&”ð¡&4ý{_Øö¶_º,øÇWþò2ݵí.þô•?Å0 –ýÁ2r¹\nmÅ{W¨APQÆçí0åɇF,ãû>½½½úT”ã ÇÏÄ¿ Œiñê"µ¬Ç£WH ‘Åb‘–––(ÿ¢ä\,—ËQ8øB¡@WWW”Ç‚ÉF¹\.3™ÌžL&MjR”ãš0Ïú™–<©ª¸¨(Š¢(Ç ÿöÊ+¼òoÿ¦ãdå˜çpL¤=®£º/¿Æ'~´pÔâ¶m×D /A!m_–ëAÍ&}½—br9™J½QÞ@£¤~Èūd(QßÅ;ñ„“l"lÉq+•Ú¬ ®‡þÌåbϼJ%¨+Ù†\.¨¯R‰µl6(#YŠÅX0µ¬àE”•c‹· ¤FO„8i«œ§œŸˆ§íí5ApÝ8k†mÇ”,ÉlâݘÏŸ{zb¡3êmk‹^I/¿ Ï*ž˜ây(ï™L쵘¥E– )©T°.“ Ö‹Wd*”‘ë*¿·B!ö"^•ÕjPö3Ÿy’Y³öÒßfÒÜxãœþùœ}öÙØ¶Í¦M›†”[¿~}Tæºë® B¦¿ø"¿uñÅCˆ¦Ãu.q&Þ± D)xy½Y/ù­g³YìœÍìëgðÒ/EBÏóèééÁ²¬( ªzT)Ç3G´pÀ{–üìgüá–-Ãs²ÙìD_E9®˜Ð1ÄÇ …{ЬNFô>\¸®‹mÛ‘hèy^$2BZ5—ËEÚÚڢЬííí5Ñ êl,ËÕ`¢*”ÉÎXú‚Cî‚?v>_ZUQ”IÁDÛ E™‰¾Àú¦Ogá¬ãdå˜g¸ŒX“™‰µø'NÅô>Æko|çðE=öööšÉÁ"¨ ’PQO¼û dÂñŽDÐ.™‹PêOAË$¿¡¤5QÐ÷cÏÂŽŽØû/Ù-Š©A„¹R)Þ§T Ö‰è%f ñ¶ËdjS»‹x&áZ #Ç$k2ì©xŠ¢xF,扗d*‡)mo÷·í8ï¢\ßÛS*Åž "`ZV ØIý¶´¡>PŽœ§¬KæÅoHù3™ "ÂÊ+“© Ç*â`WWü=IúûcñRÚ#†‹¦†Ô-arE”¹ê‡óö7iB­^wÝu<úè£|æ3Ÿ¡©©‰îîn®»î:n¹åV®\ Ggg'ëÖ­£µµ•õë×sÝu×qÇwôqůà•?ýS>ò?Ž:Ê=p2·£¾çÜzÃr"DžëQ©T(ºEæ0‡\.‡ã8üßû¿˜Ä¢bi´|Šrr¤ûç]ðÇïë„SO²Í÷}ŠÅ"©TJs›)Êf¢Æ@8=¬^|Ï6 nó¢O.,ËŠr-¦R)\×Åó<|ßÇu]ŠÅ"–eá8Näµ(bb½°˜-g™¢…ŒÖ–~À¦'¦Ïª¡QQ&:&PeÒp$ú˜¿u+çŸyæDŸ®¢Œ;6G_¨Õ‰øÓÁÛ|6½wƒÕØN()QÞúÖ»)/’Î]ÂZ6 Z*ⓈC2'YÄ=ÅC/é»$"š¦ K"n‰¨)^qI!2™“QÖ%…MÉ?X­Vooœ±R <ü ?«ÕøØâ-(a=Å£Pò ÊñÅ‹R¼ %Ç¡ˆ¢…Bœ3QrJÛ::â§R·xÊõáÓ²báÒóâG@i£<Š 'ß¡Ô+íS¶×¯*Ur:Ê1dY¾CÓ¬m›˜v’y åDä„X\ìêjü+ë%—hRhM¹~òû<ì NvíÚ5øæ7¿yðž{î©Yÿ¾÷½oðOþäO¢åw½ë]ƒŸûÜç¢å_üâ ÷«çsŸûÜà~ðƒ†Ûªƒƒƒ‹^ziÌ 4Âw3ülöeúÃuƒƒƒƒ¥ÚúJ¥Ò mÛƒÕju°¿¿Ð4ÍÁžžžÁB¡0X­V«ÕêD_nE¼öÚk'º Cï~ þ¼{‹Á_ü!Ã|qãÆ!e … 0 öôôLôåQ”ÃÎ~ðƒšÿÒda"ǹÁÁA;x ?3ƒƒƒ½‡x~Éþ$—Ë f2™ÁÞÞ ÖÞÞÞAÛ¶ ôm{°T*EëªÕê a{XE–1ý'&€±ô‡eLðþÁAìêšèSV” åx|>˜¬c!E™(&ëâH=¤~íkƒ¹\n¢OYQ&”ãqL0ÚyWÝÀ†8g× ƒ¿˜ú»‘ ©TjжíÁë®Û3h'ÊØöà`&38X*/^¹\°‚208hšÁz)“|¥Rñþ©Ôà`ÿà`µ:8hñ>¹\PW*×kYA9ÙÁ:ÙnšµmÈå‚:e¹«+hg&¬äXÉåT*^.‚uÉíºØL&>®® Loopìj5¨³§'X.•‚íý‰Ç¸B!^Nšp #¨§«+ØÏ²‚í¦,›fm;ê ëeœƒ‘uºº‚¶ÕS*ÕÖ×;Œ±IömTÇXëQn£™ºǘ`Rx<öõõ±|ùr/^\³~É’%‘;ôæÍ›£rBkk+‹/æÑGf6(.p /áÊÊÄaVª>‚D~ø¢O®åRÉW†„7/…T*…eY5áÐEÊ‘î¼8cÛ+œëûpõÕC¶[–EµZÅ÷}ýÿ*Êd"Ç)‚|Í $Í¡D÷}ŸŽŽŽ(ol&“!›ÍR,)•Jd³ÙÈ“Ñu]*• ™L†T*…aê}­WŒÖ–~ÀÞ—H¢(ʤbRŒ E™pŽT_ðèîÝl¹õVR:æV”IÇD üé`öÁÛÿᙹÓh­³HXÕLèŽæ83#O2ñ¬“0šB?´´ÄË®{¨™fà™&ž‰â-)9Å{°¥%öÂ$ï¡DzϼdèÕ¤·žxúIXÎà<‚w *^’r.‚x' É:d¹¾|#’!C!ðЃøM®…´UÚ—JÅž“Ézñþ4Í8¦xJ¨Ô$õ„õÙk&ýïp™™ºßÐpÙ÷äÜÖ#Qα¾GÂÔ=)„ÇÅ‹³qãÆšuÜsÏ=¬^½€]»vÔtÍÍÍlÞ¼yÄú_xá*• }}}Q}ˆŽ>pbï³Aüv ©*!V3@…ØÒ˜ü$:ŠJ¥ Œb<4MÏóÔH¨L*º»»éîîfûöíÝ”!Œw?°}ûvÖ¯_ÏòåËñÞ»œ–[¹{öl®hÐ{KhCÍ»ª‹¬_¿ž­[·ÒÔÔ4ÑM‘tww³nݺ¡òáÔ àæâ¼‡#Īïûd2™hÜP.—k&'¥R)lÛÆ4MŠÅâܹäSŠ¢"}}}tvvòàƒù/MFë uL°sçN*Å —Ÿv9'oïŸèÓU” £³³“¾¾>vîÜ9ÑM‘x>xðÁY¿~=«W¯¦µµu¢OYQ& }>¨ðøòå\yå•c›x,†tŸÀVX$ˆ[)öÃÐðOŠÀ®˜$“Øn†ËÃÄ fâXVX¿“8¶IàQ ×—uH=6qJ)±kŠÓ í&ÊK»JÏEIsH²=fØ7±,ç›·õAlo•ó—|e⸟r®r#¼ÆÒ¾d[¥|òzø‰ïÄ Ž%*àFuPWFœQìDý6±ÍXhô€(¹9ä]ιŸIçTm†±Í°¾·ÌíðOÿw;÷~ä¢à·žÜ¦M)‹tuuEáCE˜ëê ¨JNÅj5Î;˜É¯b1Î¥(áJ}?ÚÛ‡.™çѶƒý3™8¼§–’P©ŠZ©Äy%“"©“¹\ðY¶‰ˆ˜ 'šÌ“(ˉԖXÖаÉíÉr²=Ùׇ?­ %¿£P/Ã$Ŷd¾E)§~&éììä8ä1ÁÔ‰>‘FlÚ´‰U«VÑÚÚÍ8f̘ÁâÅ‹Y²dIÍú"Áý£íÉVŸ ’’˱¾ä¦“HÉXL>ö}Ó4q]ß÷)•JضM&“QÑQ™t´¶¶²|ùrfÏž=ÑM•ÃÝÌž=›åË—ÓÚÚŠ÷?ðš?›ïþñ7,ëû~M"hE9–™‚3f̘覌Êx  -® Nº¨™`t(GMö#n8"/‹¸®‹išX–E¹\¦R©P.—£É¹\.Gd2lÛVïkå°ÒÜÜÌòåËY°`ÁD7eLî¾`æÌ™œ±ê ~ù¿œèSS” eÉ’%,_¾œ™3gNtSFe<ž,XÀòåËinnžèÓS” åx>xÓyçð±¤ÝÐÒ@ÐL ×MÚ³<ЮwlŠòÞÈœàÕ-‹hY& !¶EÊ>nÝ>²­œØ—DVÝ1Eä3l+&ö•—ÁÐP/õˈi&¶'Å×úòIQ¶žc%\–ºŠá5•kßN<1Ô%VEh•ï¡#,ã†ut„eŠa™)a=a™Žðå„ûOI|—‰:ÓázYç&~á÷î%Žá„uL ·O —óue¤=^Xÿ”ºWq„ýåõÿ·÷îqnœÕýÿǹø’-ã„æºä$ëd.ÑÚ-Kùæ[2›¶›j·´ ìR<¾ó{u‹¯Æ‡¦Þ_[7_¾tgyáJ›•Ú¤À/ØýJPšb…‹†[¼„4Ù!F8Ĺìd;7'™ß£3óhVZiW—™‘ÎûõòËZi.Ï3óÝçq^#Œ×MK·~ã0Þõ£wá'–fóí¶VC2@Á¶OýÁ’ß&'ñWÕ‡X,†p8l;ôÈ9HNFª];‘‹€Us0sêÒ÷äTSUËq¨iÖg1ò¢øh{ÚjÊ:EIº¡º‡Tw¨Œž$§H8\éÌ“¤¥‘{îÈ:Ñ1HµP”ÊßÝŽE÷¹Üí«Ø¢¡ÒõlÙ²¥%:/"‰R©„½{÷¢P(`÷îÝP¥%«­Ö®]‹«¯¾zI86-:šxøexÍé×8+ibpVž$ÊŸ…¬ªªuÏç‡aòù<âñ8æçyÕ4ãOúûûÑßßééi¯›R“vÉ8÷Üsmgà /¼€çî)ÔTP$IZÖÈO©VfÏ0^CóÀÑ D»u‚ªŽÇûÊÚ{ÌYЪ`ÉbÆ122‚\.À’+’$¡X,"›Í"›µRµG"„Ãáš –TUE>ŸÇÔÔÔJNÍ0Ë …0<<ŒB¡àuS–¥]²`ýúõØöÛÝßÐBI’ìE²,#›ÍÚßV:x]ׇ!I ð6ˆPÚGÓ4ÈeÅÅ0 d³Y„Ãá%ÛI«ÍãÓeäóyûzµºþb¦ Ã0:r/è¹WßÈñÈ0½N¯¿˜eÇ#ÇÉ¥ Ò©FŽ;ÓuŠnÍ ÕÌ ¤öo„esŒ ßa™cÉu~¯v ¹úß_¾ýËxÓýoÂFl´÷3†¥c M¶ôÒ9ìî–í š¦A.Êö³JÓ4À$E²ž¡º *E®ëˆD"X?¸ëŸY®{ä/€¤IVûË} ç¡a02V[EA>Ÿ·t™)kñ¦ªªIàÚk¯…±ô H$MÒIDGqt%Ò³²‰,RJ ÈÇþàοâ|Ü{é½s2’É$Eªªø½ÁßÃú«×CR$èºn=—3Öç‘èÎúÑYxbá <”{ÈnSª˜Âçþàsxó­o†ªªeëúHŠ„ûo»Çõã¸k×í¼ˆ¾éQ|ó/¿‰ëú¯ƒª©¸éÃ7AUU¼ÿÓïÇô§§ñÇÊ[ÇÉÉXüEœæù0¯5ñÔÞ§ðÚ­¯ÅñOÇNž/¥_Â=÷܃ßùßÁG?õQL|a_ý*”°‚»ßs7Þôž7áG?úÞñÓwàåúËøå~‰»ï¾CgáŽÄeßÿ—ïãWkÕܤj#²ºYœ çÿ ~½ª~öò—_‹ÇßMûtÝú]Q,ó‚èÔËçHHŠþK§­Ïîè<ñ3¥ ¥”«±˜õ&ã8$EG&¥P¥¯ÔäDÂú›"$c1'’pÎ#âN¼TÍØñ؃ƒƒXXXhZ'ðãqvvcccF>Ÿ¯¹º`vvv‰Ñý÷Jyká|¼öþ—9)VÅ÷*YÍt]·jô!ÃâÜܜח’aK'åÀÑÁ§ñÂs/TM¥ªë:òù<²YëœÏ[)TÕR  µèÅbkúN«¡"gU”ªZÿ'Îoüdz/t@ø°œ²d‚ ǰè¥X’$[–†‘‘[o0 Éd‘H†a ‘H@’$¨ªŠd2‰D"t:]ñh†}è[£{#² )9ð¨¼XM®+ŠZÖ4;–4iáÛD"|>o;i{EQ‰DÇkž'‘HTœ£âüXŽ\.‡h4  Ò1)Î{‚úAí¦(mš?4çi¼Ó| ¹AÇ 9LûŠcÄk&þFÇû½Ü¢0rÔÒùDg,-îpÏa:·ÛiKuvňu÷þt«]7:¿û·jmsCòÑ}_é_µóÓõÛ'¶ŸRx»Ç†x%IÂ¥—^ ?⥀aÿÐYÏC–dËñ¨ 2q9šY£R£®éÄétÚÖ%¬&æí2O²,Û‹dè!.VRU©T Éd™LÆ~ψF£ÈårøüŸï8þ@†…Ž],íloÑh¦ibÍš5ÈårA*•²uÒèÙmE{åí÷]×íc̬›Áè/Gñw¿ü;L¼8ɰó3;ñ›ÒoÚ}£g=“ÉdE›r¹œ¥‡ÅÂGd»M¹\Î~?¡ëÇmý…ž—š¦!K ýý4Ž^rÇ÷G6]òüæ¢gp }À~OÝi*3…l6k—Ñ˜šš²·™yr¯7^oßKr‚êët@/#¢#¬…‘}SÇ㊫¯À3³ÏØû¼Ô÷ž=Qá0}âUO ¶l÷^z/¾¤ ò32yË#¶Þñèü£8ó­gbàØ®þÝ«ñ‰/|püÂãxâÅ'pwánÜyÿ¸=w; —°î¢ux貇pÙ‹—ÙzD¦˜Áyç×Ä n^ê¥Çðê3‹À¶m¨¶šàÑGïÇ©S;pÞy£ÈfT¦€eÏË圴«CCNzUÀ²ý‰¯Ï”¾”^ãźÁ˜HXÇ’e+«X1‘pá°c·L&”®ÍHꥨæº×CsÀ³Z|ãxܳgvìØ}ûöUý "G­…BaUÅaéµë5ÚŒ¬^g¥SM£2€ËAbÈÑhÅb‘Ž Ó:)ž~f®X¨žJõk_û5<ðÀ½ˆÇ­‡öÜ\åê!Y¶¾Û´ÉI“°šf)´)dK››³™²l=àGF% •²öËç-%!qö'Ńþe³Nnv*&M+¨Ä¼ët<*Í0~£Ó:¨ Ï"õe[ÚU×Õåïx>ó™Ï`ll ?þñ±yóflܸ¡P§NÂÓO?Ûn»Í6"‹À2«ªZ”Ïç‹Å022MÓl§E#?!~G† ·Ó£Öödô§ØZŽŒp8Œd2ÙÐu©vœåŽ]«_Ë!ì%I‚,ËŽÇd2icÄ}È ²ÒvÔkŸèË]úL2ˆNYŽÑÉ):½Èð#öŽC¿G"9rïyÏ{¾Îd9YÐ9ðý<ðË$ð·Õõxrø‘s\-?\Å9D÷™ÞÜN·l6kæhÑIµ_E©püÖ˜%ƒ^.—k:ú.Úm¯u¼j?ê'] WÕêΊc °ÞèœCËêï‘NïδD%Ž=Ž÷\òh’I—lçàÐÐr¹œ­ÛmÚ´ ™LƶAŠ:(-N¤g =7há -r¤Ò óóóÖb¥½:Nÿéiìp?ÎÇùö3—?RÖ–bÙkAºeyCºŸåôel1M+Ltô룀ìÂ.¤£i|lôc¸lŠ¢T}®ÑJw›Èù855e÷Iüݽ¿»mÙlλü<\%_e·—ö'}z9Ý‹ôÚ7“É4t ]×ñË¿{/½_9þän¯ÜžúJ×®ZÖ›Zí¢ïÝ׋tÒp8Œ o€t@Â+o~%.\ºäX™LýèGáG¼Ô Œ3ÏÅà ‹À3b!R‡õë-Çñ›ßü>èzåã p‰†aý/¾ºîGˆø™ìxšf=%ié#¶Vå·pØyd×zÜÑv Ó |áx, (•JUÓ=õõõÙÂbtt333رcB¡¦§§ …°cÇŽŸS £ïÂócŸ¾üKÁ¨MDh4Šp8l?°†iŽN˧×{¿6ü?ﳿ3 +Ïú9çdðú×K¸çžíßÜyÌé=ŸÞÇé=U’¬÷RJg@ùÉÉAI©ç½Z’SH×Rm½§¸1 ç;³>Óû:}‡-e‡“xÜ:÷ÜœµÂ‰V;I’µ µ»š„a:…:àÛë¡ ~‘K_´Ó¬6jâ'çÄ%—\‚§Ÿ~{÷îÅOúS¤Ói\xá…€k®¹GŽÁOúS¤R)†a¯Ø,cr"‘€®ëÈf³vÔ#ÛI¡ë:æçç‘Ífa2™ŒmÅb¶cC44°%¢ÓÃ%C˜d,ù¸àŠŒíd@‰Åb¶¡]<¯Û˜N™"ȱBí¤kçŽ`éþ,F‰Û¨ÐDzÙì§h>ŸG.—«0â»Õ¢—èwñ{Ñ!án—¸B[Œx£ýÄmÝ×IÄmÄ¡cŠŽ j›èpKßѵEONN®nδ™FdAÓr ¤¯©nVUñxÜ6ÚÅãqû:¦R){,W3h´€æ…;r:¶Ó,W‹ä£4«¢C¹Ä9]Ë`Eã¢Úï+­Ÿ£ëº]Ó–œ««… ¦«e¹û$^7¢c²‘6ŠÛ-w<¢Þ}u_³Õ\ƒFÇΗ¾ô¥»Ýx¦¬JW²FÕSÆRG9é…R©–ÿD€%à  +YÆ *Ÿ®ð+ÀΈ•±‰ì 4Fè¸ÕÈärN[è&™tB)€Êœná°³½½8H’u÷˜§( åp·…žK²l—œâ8O¥¬óˆí¡—JS úÚë^D/O€õ’d•/g€SŒ‹©Tå½£ó—u7ÈråýÏç+4Y”ÝŽÚdÒ)FÇËø†åDqƒœÎäִʾ¸½äÜöy8K§dAôèÆ²±°ù6ÓQD"ˆF£H$PU±X óÏã™GžÁÐЊŢ½ˆinn®b‘ éïäÀ#g=–{ÆÒonÇž¦i},„mÛ¶-›j½žnEY>ʵÃzáToü½y¿Rèš®]×qüªã¸ëWwaÄYÕ1šÑKfžœÁÔÔ6›W}Œ•@‹Œ¨|ljœÀø-ã˜zÇÔ’k¨ªjC‹½:×:ÁY/—é€-Õ) ÃÀ¼€óxœÔªbýEIª¬ÏT:éo÷”ë-ŠÑŒôw#S!«ÜŽl’>0Æ7ŽGÀZ¹àfxxLLL`ll »víB(B©TÂÄÄĪr9®-šHÓˆÜWVÖ©Ðñ2ˆ«ˆü(ˆ&¨tTäM^‡çÖ®µ¿Òuë=îÌ3ñ®w…pûí7Ö=L"áDÖgzפ»ÕàµVÕƒÞ%ªíï~Ï w qqœèМ›«\ÈL‘ä@Ý´)ï @,ô½‰¦íF¼Ð Àx% ß¶ ‘ÍV™–ò;ñh2­R¦h&JqxÁàÌ3ÏD:†¢(رc:d;öÄ:Њ¢Ø/êôâ*¾@‹N ñÅV4,ˆ/úâ6âçZwqßZç ´=9²èsµ6ˆ/°¤7âoÕŒb:E÷çjF‰j߉©[ÅÈ#·Q¥–“ –¥Öõ®¶;â²Z{Ýש|:U—®4" š–êÀU•×NÓ4ŒŒŒ@×ud2{þT[m^ïžÑ˜Õ4m‰ÓQŒ¬e4#`[±Ð‘äT3À•@ÆÓj ¦¼Ò * àžw`º^éðÉø¡<àÿӫÀs š¾JÎÚVõ›` ,;„àNÈËVž÷måm¨ ÔŽ¬ì,–θ¥ü9 +ƒS6 èŠå¨¤:ujyÊð¤É@B¶l T›î #ÀÇSÖï€p#Öþ‰Yç‹”Sk{‚úKÆÓˆl5_3¥x3¶å =ŸR¯v2¨‚2)xUÃ>‰àôN㩾§:®£P¦ Ñ)Ýn(-/¥È]÷ÊuHåª/|S?ùÉO:zMÁkàÅ3 <½ö„ý ƒõøÃcX\|ɶՑS‘.o$R¹~Æm#¢5>âß"²\é\t;kE.º¡W{w`«éL»ð…ãqbbu· …B¸óÎ;ma³eË–U  ÀóëžG‘²‰êŸ]ˆ©q†i^È à,}Ó›îÇÓOÿ- ùHý´sîÅâwA «Œâu~ªc XÊH±X¹XYU­})‚“rÕ“ã2®Ì?_­@u·BY§ʼnŠê+s”ŠnŒ,Í®%BH¹¥z¤å /Å Yúc€ö*@“*íUÛÑ;´)‰Ø/êÔ†þçÆââ"n½õV¼æ5¯Á 7ÜK~¯dÈ!JQ‰bíM&4" š–ÏkÀõÖƒjQ#E56 Õ[­fØqGÚVûŽÑ dY¶S5wŠåúÏ0õðJ'°S‡H’å<ÒäãÀ<€Í1à7"ÀdÇY•ÅrìÇ‘8Ž;rÉp@€ §P•«ŸèÀãÌ›*&G£H¾|L:G •N –Í#ǹ§ø3ø¥‰¡òñåòñ¨ý–a):êd¡CåÿS¨t¾êÂ5 >kåïÈ'BýNÃqŽÝF¬ÃG÷‰"?36•·Ë”7Êç‘ÊûéB_H,’ã~œr<1i d§ )XNM­|ÿDG,EªR»Â¾'¹rGÉIKÑÉ0 øœ0ÈAªI–X+;aoA%9[¶&ǸÒü!@ ù”u­_]>v ÀNk“õÙõ¸àÀotBüÏ~¿ùí—¶±¡í Ã@<G,C2™´*Ñ3VÔûÅHE÷óð[³ßÂm—܆¯Œ|eIšÐv£ªª9Å‹÷Ñù–ZíêìUbþªï¯<{7 Ì7¼ît­Eª«HGÓö¸t_›¯~õ«ž\—åðL'(ó­7 cÛ= ößÙ¬e÷ŠÅ€ú§sñÜs¯´Ë#‰qJâßdëq«Ån{™Û‘è¶3º#"µCV«ç¸’ýf¥øÂñ¸R(gsS< ß³ÎúL¬Ê󆌌•°$¥…NÑ4·q×?r×p×%,K²x²0b”FÏC5#DÜ5Úu·Qï<”pR·´û<ê×çÑ4\öä“:ÍÈ­¬sœÜ°€“ÕF–ÿO?íäæïeR)'³‘˜©'›µ”‘ˆuÝHüårŽ£’†m:me%–ͦBÛ”iH,jtdÙê{>ïD’VS.g¥9 S)T(«étõ×lÖÅäü¥ûa•×2_Zꦛh‰N iÀé>h\nÐíJ&“väE-æóy(вd…î¡C‡ÐßßM›6ÙõFÄ—ÉNE1²,cdd¤¢Î Ó¬Z( PNFí:=­4~E"jÓ¯áÚk¯]¶íBCCëJ} ]ÃZÐ5¯W ×}ò'¹ùÕ+^áu—›¦i€”]Uµ0E±œJ1XoCpº¼=ENÁ™pô¨'“{BµÄLµG•{òKËì+î_Mí'µ!¯#ðÏá¥Ç«†¨þ”3ªTDg‹vìZÑc2]r F€\vÆišh@$q¢¥‹â-ÒìEE̺\Y_öìŸër×aá¼<ôÒCgÂ5#Ìü샸âƒW`áû 8:xÏ\ôLåvå>œñðXóÖ5ý¶cÀÖuÈ‹ÉQ5§žnŽ ûQÏ÷´QØÎ}>Î ‡Jç&ý/âº?/üû 8qé‰:áoV# Þ~Ç£xþÒŸØUwÛl6k÷H$‚¹¹9»F{#õwE¨þâ0ZðN³B¨œƒê¶!uªsí…Ó³^÷v“ËåN§‹Å:öŽH™w’ɤ]‚¢‘HoyË[<»6­¢%vÊ6DMŠÅyœ:u¹ý7Piª# )ݪ;µªH½F÷Yékn³û3L£ÒñØ ô5À%kž°ÎRʪ)þºŽsöíû3œs÷ÝŽÇ¥×\S© R BÓ–Ör¨G5‹t3x·ÕYèm§,…*‰ÛÐ1ª=„Ý¿W«‘à¾Uo€^û7:†ûw·$®w ÷6Õ”ê‡Øæv¬È®vMªõ§Öu_IŸÅ~U;¦aë÷¾€ ‹'qú†l_­YæÍJ??#®¼E9Gܸ˹í¶XØrÛÓº‹©)ÇY'*Z”¿–Xô[JÒhÔº64UÝ¥jDȱ˜N[×FQ¬éKevÜëO¨ü ­skqf2V”¤x¾|Þq3ËðÅ,´}iƒe«™ƒc—QUétÚ2jé:ŠÅ"âñ¸mTÈf³e’$áSŸú”ÉÑuÞ‹Å*‹±|g–PžÇÉx‘H¤bᑘقMDÛ­˜¡å¿«jhå‡aŽS0\þ¿o÷nœ>}º"@ÆÍ‰±1,nØ€ZKÆÜçÌWùÛv.^t ËøÅÔ<§èˆÔ\§QÛ‘'¶ƒ25Fûì³íÚ…¿úÆ7ð?FGqóg?[y F"£ê=@ÝiÕhD‰©w²j7sŒp¸þ6îü«9O$RßÛŠþD"õïa+îO#•~[q¹?Š‚ì½÷âmõÏÖµèß.»tˆDL:·xÓ¦LMMqTLƒ¬TYq§Ž¡÷`Ê“ŸHX߉E·M {ÈÔ”MIÄbÖ9Äàs*ìM•T“s… Q&ŸwŠs“íJ\ 22â¤`¥í)YÌ·¯ë•u7eÙê/9S)«º YÛÌÏ;Ѩb„ª¸N„©Á£€:,¢mt×4†a¯b¦4Ddx€‘‘d2D"‘ŠïïaYÎ4‚®ëPUÅb*,BŽ3Œf´øØ³.G€žÏÛ5u܍߸t]_ÖØ–ü‡°¢®/»¬%ý–S{u í¿@>Ÿ_qSr¦®ÔvT+øø7¿ ¼§~©®†Vk%c–çv¬ÈÅ*£ k<^È‘EÎ?úGÉjÂ)Š‚l6 Ã0ì’.ä¢L¢‹¾‹”#µÉù%Ö…£(A;°\kNt$R”ÉŸM?û®~äoºÉv¦ÑÿîETáp†aØ¿‹/úÎí¥EjC>Ÿ‡aH¥RË:< èXà%ÖÑ[ TóY–e addŠ¢ X,Úçîšç°îè:ÍbEÿ©Ž·¸ Œî¡»Ÿ¦i$ɾt}è{râf³Y;7ÕÂu_+ªKív°jš†Kλ˜””9RY|ddĉDº®#YN“BÇE­¸¢5éIDAT4 £æs`vv‹‹‹+¾ÆÝÀ#<‚7¼á K¾ë…«ªŠl6‹¹¹¹–·X,:Q¼F–e¤R©–.*X äpõBg7 Þß^d¥ÉårH&“ž,TÕ4Ívž3  i0Ž]¢#‘=*Ÿ4-„k¯µl:4œÝuEÜÓ¢ ¦ÛèYÇãƒO½ˆ÷j¯…$KV¡xwúP‡ñ÷å—ü‹ßýn¼¯Ã+p†iúÙÀYÿ *ƒ”3™ ; <‚t^RÒ ÃùN\ –Ë9ùìÉÁ&ËN¤d6kýî~wJ§­{=7ç|N¥œÔ¯€sÌfˆD,{•,[k(²3/— Ê:í §(AR4%ÉYCŽXM³’d—Öv„ÃÎÚ ZCCN\êÛÔ”slÑùÈ#ë½¾íþáAË((F´$“I†aG¸ë´Ö k±XD6›µk?ær9vx1L€Èçó¸êÆ1R~Ä`•k4˜©aY^6*¦žÞÑêˆN™¼ZÍß ¬vTðªy{瀈d9cåïX" òù¼1FÎ1ÑQGN)š¿nç¡\– Éd‰DÂãï]¥‰Z¬Ëé=ÕR7ª'¹«Õ¯DY›Ëåª:0× ¯n¬<7€Ê2;ej]'úÞíÄ ïëÕímäZɲlË—€°FXª”¯ä¼N¥Rö¾ñxªª64ÖÎ9ç».Z¯ñ|À®ËNd³YŒŒŒX‹ãqŒD£øã‰ gµ©û^ºKã4P^çÀ·¾…Ÿ<û¬=IÇ_WSþH\K+cÅ籦ág_ÿ:ÔD£££KË×ÊB&C\%,¶ED,OEý)Ÿ'ŸÏ#ŸÍ"ŸNCºöÚæÎ㎂vßWNžÄ={°þê«ÛzKÓ7é:R±xüq„^÷:Ǩ±ÜyÜפ‘ó¸¯}¹?‘HŠ¢XÏ¥zça]‡ö“Ÿ ÇÏ0R‘JwÜñ"¶lyG®³»Ó"òZ-wF†éVzÒñ¨8öŠ3qÙãO² E­yÇb8F,ãti ÓE;€û>ûehH`jÊzèkš†¡¡¡ªÅµ™ÎCïF„˜ªÂýø½Û6PMÑËåœH@MsÞËè7ªUIéRé½’ÎIј´½øÞ'FS&“V{r9+*qdÄ)«Kï3ŠâD&Vk+ENf³ÖqjmC†Õ^]wJ¥ÓN{Ói X´¶9xðJüÑõ¦aÁMþ*ëõ!Rþ§ªjCuZ²Ù,TUE.—³_ÞØéÈ0Áâk÷Þ‹Ÿ©*Þ +ƒb;4þXL ò2NIqÀU?­ )#Ê |Ù‘@Ñ/y—cAUU» ”º‘"£(ƒ Øù|ÞŽl¢ÈФ`Ÿ›¢“²Ù¬-)—EûG"{[UU«þŸÍfíÈ-1j‹RFÖÚ—êfѪþd2 EQL&‹Å*úJm¢'µÚÇ¡(ŠÅ–J¥L&+ÚE}¢sÒ6©T étÚ®%JûQô]'Ú>“É ÛiE±·£((Ц¢:Äâ¹èºöÔOñþÆãqär9D£QüáþaF€ÈÈJÀÛaÕ4`ÕâƒtÒR¤hžQ´"ÍKÊ|@ó³Ñô}±zY‚:Iè/5k>©,»–§ÉJQÖ“ìfuy iš;ñä]wA’$är9„Ãa¼í¾ûpùâ"BO<ᤧqGŽR Z ëvbU)ó±÷¿_9~Üy¾»·©æ¨n¤,‘Û¡äv^f³¸æÛ߯W֯dzßûžÕvw¦´+Qz,VyJÇ#âg´òVìOù<‰DÃO?Á/~±òZºÏ“ÍZ/×¢cÍ}w[ÝŽTêO¹ŽËºÀNž„.ËN°ªZÛˆEøÊumÈX8F 1‹š¦Un,}‘WU¤¿ÿ}ëó?hýï¶CE£•…‰J›u#çI&—ŽÓ„¦iö—%ÇpŸ‡±®õ ÀãYübÃæŠŸ¬êkg"ÒJm³Ç7’Ý L/ГŽÇ<€-÷=‡KÖœcI‰e+åÝö2ç9Ã0­Eÿîqü®q6ÒªY‡;šzŒññ¤Ú-u~±%à(‡ä0t#*˜‰[ï+Ù¬“FuÓ&'1­iI)VS©ÆìA±˜ã|t¿«QI_zßzá…õøÿ؆›oöúŽø€ÿ™Fxˆl.=qÂ6ÖµW¥“qš ”.‹a˜`ñå?ú#l;}S6´ý\¢sÒª‘#OtŽ% d³YÄb1Ûi$¦p¤h*Ñ©Gûf2D£Qd2$“ILMMÙ)¡éØä€œÈ-r:’“2Ûéß4MÃÈÈr¹œíˆ ‡Ãö j'97‰TU¤ÓiÄb1Ûéåv~U«Çæþ›Ò⵨µ µ'‰@UÕŠ”“$·éˆjË9‚Iî‹éÝmŸTCÚ!>'¢Ñ¨¾[L³HÎRÑ1 XTbÚE÷óFLIÿÓñi{zžQ?i-`EO3o݉7g×W¬% ¬[ù<°mÛÐ4k˜ñ†0{€ýû÷›GޱÿŽLóMþʼã}wTݾX,š¹\ÎTÅ,‹^7ŸaZÎØØ˜×Mð´ßá¹'Í䘲ìü‹ÅÌD"áu™ajÊ43ÓœŸ7ÍXÌ4çæjoÛìc¨X´Î‘JYŸé¼ŸÿüÌdRõúRt·N`fL3óo¦)?iš)Ó4ÿàã7eQ8Ta~~Þ”$É”$‰åx–̉allÌüâO~bÂ4͹Uc~~ÞÌd2¦išæÜÜœ977g¦R)3“ÉØï’$™SSS¦,Ëf±X4#‘ˆ™ËåLf&“1#‘ˆ955eoŸH$Ìùùy3‘H˜™LÆÌd2f.—³ÏQ,Íb±h¦ïÅ6ÍÏÏ/Ûî¹¹ÕöØB’$3û^þ)Šb†Ãá¦û[‹p8l0§¦¦V´_*•òåµëÅ÷ƒ#GŽ˜û÷ï·±ëæM3bšfÄ´ç¢$If*•òº™= É?Ó´ä[.—«qÅbÑœŸŸ¯‰âotŒjûv#¹\n‰›ÉdÌX,ÖÐþöœè1öïßoþâÆ­—&ÓzNNMMµíù!277gë^ (JGúY«ïŽÍvÀ³çq.—óT¨§¿ô¢NP«ßsüq¦i~B~ÚŒDœï ÓüË¿|ÜæÌxÜ0eÙ²³tùc†é!Z¡ôfÄãfà{ïÆ«w½zÉoš¦!Ú«yµ"Ãty@—7âµ/ "õiçkEQx¾3C\ª(Ë—QhEÝI1û o`à$ž|rÁëKá=* ý9€ÀÈSO!yë­ËF?StP# Ãø›Ã/¼€Ðw¿‹ð¶m+ÞWUU„ÃaŒŒŒØi-s¹²Ù,¦¦¦ìè¶©©©Šº^Åb†a`nn®"⌠ˆ”TÕ¿o¤§Ó˜[ò30§I†aº ½œIí?ŽÜ€íåTÉdù|ÅbÑëæ1=§âð˜çóÀÅ¿…Öc*•B$©Y‡êaPú<~Yc˜`óõñªo~¨ãxÔu½ÂpœH$N§‘Éd`š¦n4ÛºÉ)%ƒà´«G<ÇÜÜ\ój3í4äJ’d;[˜€£iÀGha ï‹¿SSSq8ÔƒR“#0/¤ëœÆb±ŠTË©TÊþ_UUÄb±%N=¶CŽRhšÃ0*êR Rw d’cbŠ_šo¤'QûÉAG6ZA‹¸R©TEÊc:o$YN%Xëÿj!¿Ö>©²¾G©¤ÉA Bû':bEýO¬çI¿‰)™éšSmI1ý1]s:]#ê;ýM‹T(Et$Á¦M›l§x&“,Ë(‹‡Ã¸ë®»‰DìëkÞøÆ7"BQ”Š´Á¥cÀ“O>éõÐ÷Žòø£ÚŽ9åÒ”ã„Æ¬Pêy¯¢(ž8ÿh~{…®ëKjƒ3Õ9òógqÑ/bÍ‹QD"V)PM4m=Âá4æææ iË/&g˜^¥çù²Ó῟x¢ê着ڊ"Ã0݇úŒ<õÜ%åzxV½61LbÀ=QÒž{ô)|EU1E…_íM*`²,{¶2•a˜ÖòŠo~ÃÇWý² LMMU8ËX$:ݺÁ‘¸DC/³ÜB&`hð˜Œø ‹uÄéHÆvrê…Ãa{a9‡††Ëål…)'":ÈÈ©–Ëå‰D*d—rÄ‘ƒ…þψ©2j@ºûÿj²ÎOóÅýw§¡÷¾T*e;V ðk©.׿åÚL¿‘3Á½oµqå¾ô­óÑöÅbÑ®eKÛPÛo¸á†%ûRÄ}<ÇÔÔTM>00€B¡àÉ}ñ -Ú©ÅápØó…^:>½„ä¥ÐB¯H$lk¹çL¬yôgXwÁVMG¸à‚S‚CŽvd˜jôœãј~ûþïá‘«¯ÆÍË`ÁÂ0AØÎ={ 6\x’t Òi+¥N§V42 ã#òyaäÏaÝß~Š¢,y‹Çãöjól6Û)׆±Xû7ƒë«ÌiŠúQÅ6 ‘¸ƒ|·ãõ*}¿àc1Ó<¯zðA`ƒ„ã箃®ë-' §a<‡¢(PUÕNÕI‹'ꈜ†ápØv 6âìr;ªèÿ^Z±Ä…#AZP¡išÂ¶Q²Ù¬ÙÈÔ†Ò¡7w k=ƒ$Y M³¾#ÂaëoÃÎ<ó ßW6]{?÷ö„$YßÓ6²Œ%Ç÷“$ëŸÛǘÉä iÖ¾ž§‘>šV»tˆ,Ëž.àñòîußYkœÿ~Õ ¸ê»?‚ö²-Ð4§lÎí·ç¡i¿&Œ³>øÁ%¿Ýzëøñw¸’dål¬³®¹œUþ!Ÿ ë³(«ÅÚÇ0²[–ÓæÛ¤RÎqé3=À ÃT‘ˆulÀ:g4ZyŒ\ˆÇ­6%ÎžŽ‰XǦýªƒÚN[çL$ªŸ‡¾K$`+#âJŽjý¯C$býíÞ&•²BÕ%ÉQ–Ä…?á°u~UµúœJYýwŸG×­þÄbÖqÜ×>“±ö3 眢Ò‰Xç¢ýèšÐÑpØÚ/›µÚG}£{N×…®‡îe½óÐotŒhÔ:ÝcU­}r9`d¤R¡“ek?º&Šâlñņ^E;xÞ<¯ÝòkÅ+¯ôb˜å_5èá?€ûöá‹UŒ’$!›Í.Y¥Ï0Lð©U߯ËÔ[A ×|‚ωK/~=…ožõM; åj  Tç¢)*þ-aC†`ޤí,”æ5HÄb1¨nA¨®'³<###øâ‚áa ù¼cË ‡;17gÙ˜ÄË궯™&04d}‡­d÷Òu  !Þ‚|¾2°A´%‘½K´“‘}¶‘奶'q?·ªÖy¨ÏËõgÍšÊcˆöB·M“˜Ÿ6n´>g2–}Ë}ÝêÙBÝç‰Å–öGÜO´ß‰×M¼¢=’Pçþ8v;űщŸ º×äЕå¥Û(ŠÕ²Óöd§¤k"ÚzÝA’¤ÆêúR'1p®u½È¼åŽÊo~^Ñ38uYkÝǃOá‡?ümÈrÈÞŽÝ ³”žs<þ7~‰Wéà‰=œ‡a¡„‡¾ýýÎ*QpD"ÖC,›ué´õ™·,[Ÿ2´ZˆŽCN4÷g:>=ÈdÙiƒi:+‡è¡".Àr?Å¶ŠŸi…“ø`¢ó„ÃÖ1ÝŽ¸¹9gûjç©ÕzèÑ‹®‘»Ïâoâßn ù®€£@Q;éÚQh%µA×­ßiÚFQœsKR¥óW¼†bÛȱIÇp/|û‰XŸé!;zñšT;O.ç´Gttºïµ¿Z;h,¹ÇÄßý]À_ W‘¾óc$§„122b׿`¦ÇxPCVùK\±¸ˆ'°Ô€¬ë:t]G$A2™ä:° Óe¸S+«ªŠl6‹L&Ã%†éÖ=}!pl7öb2WѬªª¢PUU‹E;íi±X´£vRû™X,8Çãjjr}òåùÕ¯ÎÂ5×<‡þþçqÓMg#•rì7ôÏms¡…â©ÔRgX†´ZIÒFιÅâ6l_-ÈOܯV`½þ¸©¶vk~ÞqlÕZûMÎE²_Ñ‚zª¡çŽàÿ¦{ Ú(EÙÅméïåÐuÇ(nKvJj_5(H¤šÓö'[§;CÓ*é”pàv€–m[Q¬ë52âü.IKƒ( †¨æôý¿ÿ·wƒDô»JÀÎ~¼ù¥—€˜sí~øs8vìÍ®ñº‰ ãkÖ˜f#Œ`399‰ááa ãµ?žÇïßöO¸`ë‡N[Bcdä)ÌÍ¥‹qº¦7ÇÁƒ½n†'ý^ûу˜þÊsø‡‹çqÓMÙéø%Œé5 … …&&&¼nJGuŒi»¥5÷¢ÿ3ŸY’BQ×u;%š»þ3½$¶re#­t¦aqÁO§Ò-ñyœUÔ¢! ÞyÄöÕ:¸_­Ë+9¸°ª‘óˆc•Æ–$_ûÚÿÆõ×_k͉BÔ… Ã@:F8†$Iœ éIzñý P(`ö«³Øúƒ­xçƒï¬›^‘œŒétº®#‹A×u$‰¶¦4Ÿ n¹ßl4Œ{?zÑgIr²‰Ïñ™LF}úN|Ñoä4 ÿ«½z‰ «_ÿåw_3:µzŠ Æ5m©^×ly1c”x±/µÎMí¤EÖÕÚ!ê)îßiܬä5·—ß~ô£wáÃ[Þò Üzëûê^·|Þræ¤R9Æ TÕ‰¦\ oû'ñ•¯ô^°‚[Ro¾éñuø\Âg>sb1àk_{úÐ=øîw_‡ü|¯›Ì0m£:AOE<~üšèyo‡µdÛ¶âÍo~=Öe˜áè£ÁÄå¸é¦‹Íf‘ÍfyÁÃô*{#ȆЛ?‰ÞúVÎJSÃ|ðAlÜø>ŒŒ\^3-9¥ ¬•»šV™F§Ué‰r9'={*ådk ƒ¥ŠÇ+³2ˆ¬&ÝR§Ò:µâ<’䜇 |t±‡˜â^’–ÞŸZéé)ãE­û#¦u¢q$<éþ@±èlOCE±¶%C©˜6žŒ¹bûr9ë{±-4~²Yë8ÅbeZq¼Ñu~öÙ>ô:ÿùŸgãèÑ  í‚,Ÿ¿l2ÓÊw2¤‹Îf1µ—¢8p‚æ(‡jéÄGÔ¾åæmÃçYýy¨\ÝãfÏCûD"ÕûC²£ÖyÂagL5ÒJgÀÔTõëÖ«,œ·€Ï¾ê³ˆ½Î¹šf]g*¢(ó8}ú4{ìÎ:ë,üŸÿ³ï~÷Eд3ì÷âw„Ér¥OÜ¥RªCÔ=O8ìÈ tÚú‹YÛˆÎBwI÷yÜí››«Þ’±˜ul÷³R|ö‰åcÊFDå`Äçf£×D–­4'ŠE'Í%!¦yl¤¬Éܰi“õ™œ{ô̦ë\­¿µî =#tÝ9Îr÷5“±Æé6ô»xÏt½RI’uýTÕÙVŒÊªVzÇÒ†¡(ÇÑ‹Üxãq¼÷½kñº×½³!g3é\lJ`üÌjÇçyç=ìuÓ½'¨»ÖáÊìÜ~ï¨ý¼¼óΟp6$†ižr$þÂá0/8`˜&«>ö,Þ¿uŠ·ëŽD"À¦MOáÔ©S¸üò¯#—»¼"ý¹2N™ÄŠ˜V»é‰Äw›Z+«Å`V¤[ªE«Ó:µê<Õ®K#Q©ÜñžT»?â~µîxÕ®›¸Ÿ,Wo‹ø]½wâÉÉ6ÕoL’NŸúÔiœ\xáqüõ_¿€uýþå_¬méúU‹P_é³¥Ú6<+Zqžfž•Ôw÷ø«÷¬¤l×îÈTª22Ò=‡ÄcÐvb4(•;qo/f2u rºMBôü ‡cŒ3Ð<¦þÒbô ˜Ÿ·œƒÉ¤“²³Vô§aT–½™›«”mõî9Ï3™¥ÛÑßbéðäÈM7ÍbqñDýÁÐ…<òÈ,ÞûÞ÷b%IᨤÃ0݇@{}ç]ž4nB8le<ؾýB¼ç=+KuÍ0½JO¥Zý×G¶â æ3ø»×áöÛ׆†† ( G<1=E/¦R¢~ß~ð úw~?¿ëZ ajjŠ0=I/§RÆð…Èç/áßqÖG£øØÇÎ(_¬ºŽÑh”&1=AEúáb||oxÃA<ÿü \pÁ=¼‰éyzñý P( “ÉàÀ7â²ËÞ‰ÑÑ3ÊNvÙlº®C’$$8"ÓB6m²œ®­L×ß*zùýàšk®ÁùçŸÏº?à7uw¿ÓÿðÌqŸG®‘P{†Y!Å"GÉù‘OúÓØºu+Û†è¯<ú8pÅù˜˜t]Àµàf%œáu:ÅúGÖãG¿q9^üöŶ’7TNö^i•]†aÉ}WYic~ëÕ¢Ñ(+ ÓèÏxú¥³qÝc¿°ScÑ‚$– Ó;¤R)~`˜fÓ¦58zt½ítB,c§#Ó6ØéèOn¼ñF΄Æ0ŒÍÝ›_Â=…Mؼys9¥º•a˜Æ œãqrr[·nÅÀÀöìÙƒR©ÔÐ~ÅŸÏpýe?…®ëH&“Èårl\d˜²Z90ÿk¿¤Í›×"‹±¡‘aÎjeÁ¹<€ÿ-/M½ˆ¿ø‹7Úß Á0 ~¡`˜±Z9Ñh”ç;Ãt ÍÈ‚pPUš¦¡X,ò;ØÕÊ‚žû Ó%4£€qàŽ_z^9ÿ¾úÕõÈçó0 ƒ'0Ì ”ãqrr333˜˜˜ÀÁƒQ*•°gÏž†ö9û"œ“ùÈ› it]ç @š‘§î;$UüË¿|áp˜ `š‘kî{÷Å®Aÿ=Y¼þõ—AUUÄãqär9®ãÄ0¢9Š¢@öc‘-†aVD³²@×u;’m \š• ßVÈýœèÀ_ÄžÇç?_‚®ë¼0aVA ‡Æèè(FGG1<<Œ`vv‡®»ï}W_Šð±_ NCÓ4d2¯»³" …ŠWhøR©„B¡àu3šfffÆë&ô4ÍÈ /|wÝõë®íØ ãåÓ š‘ŸxÙïá ÝÄG¢CUU@$ Œ\è–ñ× ò¬údš‘€åxì%#B·ÈŽ•Ò‹ó´×îu3²àÉ'ŸÄÐÐEé™lH<'z‡^»×Íê½F¯ ;l«¡—îu3ràĉ@>¿Ž¿ÛÔð®øo`çÎ×@`(wýî†yÚ zÇã?ŽãÇ7uŒÀ8gggQ*•0<•Vè½F·ÈŽ•Ò‹ó´—îu³²à¼óÎë¹Z¯<'z‡^º×¬¬œ^D7Ø"VC¯ÜëfåÀO<«~vž—ÖâƒÿuÉd™L&P¶‚n¸×Ý0O»Aïh…ãñ,¯;Ñ( P!< ¯¯³³³Ëî;??Ûæoó<‹·]ô6Ü{ï½^wgÅœ8qßùÎw0==íuSVÍÉ“'qêÔ©º÷Ëï;v ããã^7cUœ8qO<ñÖ­[çuSVE3rzè!¼ôÒKø·û·@Ê Øã`yæ=³³³xñÅñÖ·¾Õ리Šfu‚â¿¿º®ã‹o}+®¹æÜrË-^wiE}üÝ Ï‚Ü‡“'OâØ±cxþùç±cǯ›³bšÕ {ì1lÛ¶ çž{.^õªWyÝŽÐ-²c¥yž®–•ÜëcÇŽáäÉ“xÅ+^áu³WE3² ¯¯ÿøÿˆµk×"—ËáÜsÏõº;çDï°’{Ýëïò'‚3Ï<ƒƒƒ^w¥cô¢,è[Äjhô^÷ºÍðôéÓxòå!\ñ»Ãík¿ƒµ?X‹'NàK_ú’×]k˜n˜×Ý0Oƒ®w;v †a`óæÍM'0ŽÇf¸õÖ[që­·zÝ †a<æ¿þ뿼nÃ0Ã:Ã0p÷Ýw{݆a0Á¥Y¤ñWK¡­^÷ &­Ò ݦý ªNÔ—AèÓtRgðãn·lñ[Ÿ;%‹üÖofy:©3øul4# ‚6':e«ðSŸ™Æè¤MÑãƒu‚Þ¹×í&H}ÞµkW ß±»Á¸ˆ={ö```صkfggWÜF¿Œ·ŽØlLÆ3ÆÆÆÌ¡¡!óСCæ‘#GÌýû÷›W^y¥yèÐ!{›ýû÷›CCCæwÜa9rÄܹs§¹sçΆït®¼òJóÈ‘#ß7ÒF/ûqèÐ!óÊ+¯4UU59bÞ|óÍæ•W^iþüç?L˜`SOmüU“AèC+d×}`‚K+t‚F·éT‚¨˜f}Y„>0ÝK§t¿ŽávÊ¿õ¹S²ÈoýfêÓ)ÁÏccµ² hs¢S¶ ?õ™iœNÙý:>X'h½­ÂoýîA곪ª}Çî»'ïÈ‘#æ‘#GÌøÃæÐй°°Ðp½îƒûž´{<±ãÑ#–(¦i âøÃöß×_½¹ÿ~ûïŸÿüçûÕû½S¨ªjîܹ³ê€m¤^öcçÎç6MÓüð‡?lÞqÇé\‘AµdAúÐ Yàu˜`Ò* ÑmÚMuÓ¬/ ‚Ц;é¤ÎàÇ1ÜnÙâ·>wJù­ßÌòtRgðëØhFmNtÊVá§>3ÑI›¢Çëí±Uø­ß }¾ãŽ;Ì+¯¼Òþ´wìn°{=zÔ¼òÊ+Í£G.Û¯ È–NÙl8ÕªG”J% cpp°âû-[¶`qq0;;koGô÷÷cppG­û{§˜…ªª¸å–[ªþV¯^ö£T*avv¶âÜpàÀŒŽŽ¢L°©' ‚4þjÉ‚ ô¡²Àë>0Á¥:A£Û´› ë@}Y„>0ÝK§t?ŽávË¿õ¹S²ÈoýfêÓ)Á¯c£Y´9Ñ)[…ŸúÌ4N§lŠ~¬X´ÚVá·~w‚ ôyxxÄÁƒWÕ¯ûÙ vÏP(„Ý»w/éƒHPdK'm6gu¬WLƒƒƒKÆââ":d?8`ÉÃ¥¯¯¯â¡Së÷N°¸¸ˆ›o¾Š¢T|õúÐè6í‚ò÷÷÷cïÞ½(•JèïïÇèè¨Ý¿÷ 6õdAPÆßr² }h…,ðƒLf‚I+t‚F·i'A× €ú² }`º—Né ~Ã-~{†wJùí^3õé”Îà·9AýlF4Ò'?͉NÙ*üx¯™útʦè§9A}d =¶ ¿ÝëN”>÷÷÷£¿¿Õ}ðºŸÝ`÷ìïïÇÄÄËñ¶°°€™™ Úm ‚lé´Í†#}ÂáDZk×.ô÷÷CQ¯›Ó0ªª¢¯¯»wïöº)M±k×.„B! ¢T*allÌW¦w`Yà-, ?ÀrÀ{X0A ¨²b¥t“lY),‹˜zôŠzW°`¡WdA¯Ê€eÓ=]^MNNb||‡ÆŽ; …¼nRÃtZ†rģǔJ%ìÝ»…B»w(°…B333¸óÎ;½nJÓ(ŠR1édYÆÌÌ öíÛçuÓ˜e?`YÀx ËÿPKlß¾Ýë¦1L eÅJé6Ù²RX1µè%9ô¶,à÷f9zIô²X0Á§[äEo Œ# Ù‘æ~Æ Ê2;;k¯XÉç󘘘¨:᪭`ÃaëýÞ. …úúú°wï^Œc||€ãù_I¼ì€%bûöív:ƒ ô .È?¿FeŸû@´BxÝ&˜´J'ht›VÓM:P_¡LwÒIÁc¸Ó²Å}é”,ò[¿™åé¤Îà—±ÑJY´9Ñ)[…ŸúÌ4F'mŠ~¬tÆVá·~w‚nè³ßïmÐížTkUdxxÃÃÃ( +j£ßm·¶±‘mØñè!{öìÁŽ;pàÀª¹š)W®»0g¡P@ÝßÛÍèè(öíۇݻwÛÿ`ÇŽöçFÚèe?¶lÙRõÜâÃÛï}`‚Ïr² 㯞,BZ! ¼îlšÕ ݦ]tƒNÔ—AèÓÝtBgðÓî”lñSŸÎÉ"¿õ›iŒNè ~­A›²Uø©ÏÌÊè„MÑOãƒu‚öÚ*üÖïNÐ }ʽ ºÝóðáÿË/l6ìxôˆB¡€R©d{ÆÅ¢Çxtt333X\\LOO# aÇŽ ýÞNhÒˆÿTVm´^õ# axx“““ö¹ …>\‘ÂÈÏ}`‚M#²Àïã¯Yà÷>´J°`VC«t‚F·iÝ É¿÷é^:©3øe wR¶ø¥Ï@ge‘ŸúÍÔ§“:ƒŸÆF«dAæD'm~é3Ó8´)úe|°NÐ~[…ŸúÝ)º¡Ï~¿·Ý`÷ܾ};1==]ѯB¡Ðr=¤]xa³Ycš¦Ùöž1K˜œœ¬¬"ÃÃÃv¾àÅÅEŒaqq¡P¥R vˆ}½ß;ÍÀÀ´BxÝ&˜´J'ht›ND¨/ ‚Ц;é¤Îàç1Ü.Ùâ·>wJù­ßÌòtRgðûØX,ڜ蔭ÂO}f£“6E?Ö Zk«ð[¿;AÐúÄwìn±{ÎÌÌ`ïÞ½…BèëëC©T ¼Í°Ýã‰òoÙ²¥jÎöz¿ûFÚèe?èÜýýý5CœýÞ¦»é†ñ„>´Bxݦ» Â<ê†>Ô“AèÓ»´j|m ·¢O~ës§d‘ßúÍ´†nœ­èwÐæD§l~ê3ÓZºmN´¢Ï­º.^ô©Ý¶ ¿õ»tCŸ»áÞú½¥RÉNsÜí6ÃVÜ v<2 Ã0 Ã0 Ã0 Ã0 Ã0 Ã0 Ó4\ã‘a†a†a†a†a†a†a˜¦aÇ#Ã0 Ã0 Ã0 Ã0 Ã0 Ã0 Ã0MÃŽG†a†a†a†a†a†a†aš† Ã0 Ã0 Ã0 Ã0 Ã0 Ã0 Ã4 ;™ž¦P(`qqÑëf0 ã3X60A†Ç/Ã0 ËB†é5xÎ3½s†a˜ÖÁ2µ½°ã‘i³³³ÇÀÀ0>>îûÉ;>>Ž£GzÝ † 333¯ú[å@5X60AÆËñ;99‰¯/Ã0>f9=h.Á²a‚C+æ=Ïy¦è¦÷Ô Û:¥Ë0 Ó^ºI¦úv<2-¡T*all ¡PÄpôèQìÙ³Çë¦1 ÓB133Sõ7– ÓÛ LOO{Ý †a|ÌrzкËB†YAŸ÷<çfåyÞ÷‚.Ã0 Ó ÎòºLw0==¾¾>ÜrË-…Bö÷{öìÁìì,½n"Ã0M0;;‹ÉÉI Àððð’mX0Lﲸ¸ˆ={ö ¿¿¥RÉëæ0 ã3Ñ#€àë, fåyÞóœg˜ÕÄyß+º Ã0L«àˆÇ.arr333˜œœÄÖ­[100€={ö`qq±â»v…÷ÏÌÌ`ûöíÕíÛ·ã¨x¨RºåVQ_¦§§!Ë2°k×.ÌÎζý:6Ò>†ñ œ+¡PƒƒƒØ½{7úûû«nÓ9à•Lsò 2¿7ß|3¶lÙ‚íÛ·¯º ^Ï{/õ†YŽÕÎzóÎozи.±ü ¦•42‡•^êÜíš÷<ç™^À=΃ s­›÷½¦Ë0L'ðZF°_ {`Çc—@+oJ¥8€‰‰ >|×_}Åw…B“““-?7`­ö)•J˜žžÆôôtÕ ( Ë®œÅÌÌ …öíÛ‡ÆÆÆÚ~ ÇÆÆÐßßÑÑѶž‹aZA'çJ?&&&011QUÉn‡ðJ¦Uk Ë&¨tbüNOO£P(Ø2¨A˜÷^é SÕÎzóÎOzµhL—XÍ5ôƒ,d˜VÒÈnDxýìZ?ïyÎ3½@µqhͼï%]†a:…dûºNµÚEô÷÷Û“qxx‡ÂââbÅwõÕ°°°8|ø0fffÐßß……LNNbß¾}“uxx<ð@Ýc...âöÛo_’– P(ÔLgÐ $\vìØ}ûöµüø Ó.:=WjÑ9à•LaÙÀ™NŒßR©UU—¤r”yï™Ê0nV37™w~ó+Ñ%V‚Ÿd!ôšzs¸9àå³·óžç<Ó ÔçAй[=ï{A—a˜NÓkïålûkìxì"ܯ¯¯}}} ï_(0>>¾ì6Ë)0‡ÂwÞi§Ø»w/öîÝ‹áááeÓÔê‹(\–Sæ›m÷ìì,TUÅââ"&&&VÔN†ñšNΕFhµé´LcÙÀ™•ŒßfæÊž={°cÇŽ–¥ózÞ¯D¦2L'ivn,w\?é@ku‰ ÊB†i”V<·Z!_übKà9Ïô­xOí¦yßíº ÃxAÞËÙöç_ØñÈØlÙ²\õþŠ¢Tä+Ÿ˜˜ÀÌÌ fffV|“““¸óÎ;ÛÚf†ñ‚v¦ñZ´£¿,˜ ³’ñ»Ú¹211±d5àää$¦§§[’¢h5t*}Ãô"íž_íÐ%zU2L§ñ‹-ç<Ó øå=Õ/ó¾mn?ÚEÆ :ù^ζ?ÿÂŽGƦ™ÐäÑÑQÌÌÌØ«h`(ª(ž<;;‹ÉÉIlß¾½eE•[•*! aß¾}Çää$‡V3]G»ÓŠx)ÚÙ_– Lidüv"åPÐæ=Ãt­žw˜_ê3338|ø0&&&JièYÈ0&ÏßvÌ{žóL/PmœwjÎíŸ÷+}Ö·»Í­ìÃt;|ƲíÏ¿°ã‘±i&4ybb¥R©b…A(Âí·ß^‘R`aa…B¡¥5Z¾=<<ŒíÛ·cff£££\ô™é*ÚêÀK9Ðîþ²l`‚L½ñÛ‰4(Aœ÷ tZ=ï:1¿Õ%J¥ …>¶d!Ãtš <Û5ïyÎ3½€{œwjÎíŸ÷«yÖ·³Í­ìÃt;AJµ*¶¿Ö²Æ4MÓëF0ÝÃì쬭älÙ²¥êCµP( P(ðʆéRX0 S ž÷ Óy‚:ïÑ%&''¹ Ã4@PäÏ{†i A™ó@ýyä9߈Lc†éf8â‘i)ƒƒƒË®¬Z\\D¡Pà ÓŰ`Æ Ï{†é<ç†a¿À©V†a†a†a†a†a†a†iŽxd†a†a†a†a†a†a¦iØñÈ0 Ã0 Ã0 Ã0 Ã0 Ã0 Ã0LÓ°ã‘a†a†a†a†a†a†a˜¦aÇ#Ã0 Ã0 Ã0 Ã0 Ã0 Ã0 Ã0MÃŽG†a†a†a†a†a†a†aš† Ã0 Ã0 Ã0 Ã0 Ã0 Ã0 Ã4 ;†a†a†a†a†a†a†iv<2 Ã0 Ã0 Ã0 Ã0 Ã0 Ã0 Ó4ÿ?ÛÊ+ýo,î%tEXtdate:create2020-10-09T19:33:41+00:00þò`¸%tEXtdate:modify2020-10-09T19:33:41+00:00¯Ø!tEXtpdf:HiResBoundingBox1728x900+0+0×ì&ŒtEXtpdf:VersionPDF-1.7½8;í(tEXtxmp:CreateDate2020-10-09T14:31:46-05:00P276tEXtxmp:CreatorToolGL2PS 1.3.9, (C) 1999-2015 C. GeuzaineÛ©AJ(tEXtxmp:ModifyDate2020-10-09T14:31:46-05:00äÌ 6IEND®B`‚blis-0.9.0/docs/graphs/sup/sgemm_rrr_zen2_nt32.pdf000066400000000000000000005025351422157504600220100ustar00rootroot00000000000000%PDF-1.7 %Çì¢ %%Invocation: path/gs -dQUIET -dNOPAUSE -dBATCH -dSAFER -dAutoRotatePages=/None -sDEVICE=pdfwrite -dLanguageLevel=2 -dEmbedAllFonts=true -dOptimize=true -dDEVICEWIDTHPOINTS=1728 -dDEVICEHEIGHTPOINTS=900 -dNORANGEPAGESIZE -dFIXEDMEDIA -sOutputFile=? ? 5 0 obj <> stream xœÜ½M¯.;’7¯_±‡Uƒzůd2§l†Ûªž BCÖ×ÀUr« ÁߌXkE0÷9uï­v6„n©ÏŽ›ÉLæ›Iò‰ü/_åS¿Šýÿï¿ûËïê—ýÏ?þ§ßÙßõn«|=¥”¯ü¿û?µ]wù´¾¾æzêç¾¾þò»ý×ý©5,ŽcÖè}ÿù8$Oâ!?œq}ý_¿Û·9ž§´¯ÿñ¯þåOn$,Oy>µó§wÃ9þ¬ã³šRk_ŸrÞ\XކdcCùçÑÐ]®Ï}ÞQXΆhSCñg6ÔÚÝ?×u>.YކdcCùg6dÏk=m~ýøý“ÿ—ßU¾øþÝ_¾þ»¿ûÝ¿øW÷W_÷‡—¤~]ýSü¹Îû3çüú»¿üî_ÿ¾üáíiëSýáõúŒ¶–¶²ŸöÓ_ÿÚç?ïu}Zcï'ÚÝÿ,ßþ¹>m]ÿæïþÇßý÷÷»ÿõgoÂZŸ~?Ç+ù§Ÿ¾ƒs}žûu”ÚºÛlŸ6޶d9ÛÊ£ÔÖyT´5{ûܯ¶hyµGE[ÇQñâ–Ò÷?޶d9ÛÊ£ÔÖyT´Õ÷s·³-Z^mÅQÑÖqÔo}‡Fû”~Ù/Ò?s?k½Cø-§ý–\_ýþ”ñ´¯¿û÷û¿6½ óÛ…ÇM7~í8¶7帵pÜúkÇùËö¯¿ê´.ý›ýÿþýo „¾}ú…¡,ùÕôŠÝû1ì‡ø£ý"û»õ_ã®ës÷¿Æ¿Üý´ýÑþþøC›ŸkµõûÿiÅë3ê5~ÿ?Çþ_þP÷@0öÇø§ø×¿øÃnª]Ïúý¿ÛÇ=Ÿ±Êõûÿã}·SŸùûüÃ~ÁÚ¬×ïÿÃþøôO¿J~¿¸Ý_úk@ªŸ>ïùµöÈtÛÏf·ÿþaÈÃ.ñŸì®®¾Ú¾˜þõ—}WýcýÈý}ü×ÿÌÝÇ¿þ>þõh×§—õ“äAj¶_ûEû±µˆýïø£nô~r±?ÿáû7™O¿ÿ÷a̾åÿ5þõobûßöW틯Ǜ‹wvÙÔêOÒgÑgÿ0ƒïÕͱ`” ‹Ï#×sì+rËc–Yö滋n‡Û²ß±é'íý1C{ì¢ÅžÙûnoÁb£Ú܃ÂS ÞÈÕðǾ‘ý׬Ÿ²Ü²' ÿïû«¨sÁ²[2˳ߺËôcl(ë–ÇïÄn¿y;ãÓì˜Ûn¿ X¦sïÛ÷Ñé±/öÞ÷nï—ý¹{n–}ï÷åWž6ío˾ù5,ÝÊ}ÙÓ™°\ÖƒÛzPýÊv fÙ=(Ï€eÁò|ª7¼¿oxw áQ®ÏòÛÝÇö᫈‚±vF°øH¼¬uÂ2íÑ,ëÄ^*mËþíy¯Ý‰ýxhñc†?ëmh6°oÃîÃÂ:£ûo´¦Má ‡T{8˺°P·øÃYÖ…ý£»Åïxí>Ô§²ûñ­¿ —xAžÝŸž½êvñÇÆ©qÁRíþžÝ‡«ùYóã'Yj‡áöCvæãͬýŸÌ²ûp¯ ‹wüÙXóÆêÉà3÷2j<\OyË»{LÜ–ZщÇ:Ñ*,—·l(võýi {µìûh-Õ-Õ»³-ãóà˜Ý ûž:±v«ewÃÞÚg®8ÉzÑan°NøµÞÐZv'n¿Òƒ»Ù–çã?g+øj¹—}ŽÛR?×Þ(Ö+ÿݲ;áO°íaØÛ©Ö{Qö Öš[¬f˜øÞkݧû[Ðn<ä½þݶn¶ýãO·ì>ø«Ó ~óÝʾ ëæ^Ç,œ5ý}u ÏÇ«¾/€fvÖC‹ö<÷,Šwªî.ص_L|3µí.Ô‹¿Ùû‡»>þ–v{Ýb}°K=Ýn±>˜a?|ïfÛÿòmt»¤Yv.ëæ¸ø(Úî´nŽùYhf÷á¶K›Ï¯Y¬›Wùøì\›u†…»Ùƒ„¿¶ãñ7»öÝ…bWºö;ïçôÝÿ¤/~®uÔ¶¸Ü– oöþº>nÁÛÖ­ÖÍëÆ›]û>ßßuû–ýþúþ—fÏõØÏê–ÇÇïgYÚÙ}¸­ŸóÒÕwV‡¥Àòø ²-“?„ÏÏòë^9ءӾ7¼%cw¡Z7o[¸ew¡Ù…lÍËî‚nw³WÕ,Ö»Ð}ÙïlëB…oÅØ×ðñd߸uìùg¿>ælö¹?6°?«ñSÜËH{”~ ~™½4±ÿ¶-cë~/àà¶à‘^Ö 3p„Ùó~÷aüY}ëfÙ°ÙàÙS$^ÀËÖ-ÖÑ=«à͹¦*Ó^Ê:aµ9Ä Öû{p|¹vöˆpúÑÊ>vÿË-Þï¹{°‡°mØwéÍNŒ†Y8¹V›Ÿ÷ì°-•?ÍÏÆ!¥è·² ºÚ¥öˆánî.ì¡Æ[ư4wº_kÙïê–ÇŽÞg5{]̲û°_émyì÷0ËòqÄ[Æx2­<Ä&oËÙ´Þ¶7,ËoçÞcØsÑ⿃MÔÅ:ºÅËduµŽÖÅ_Æ&j3؈Kí>´|ö{fƒ¸[0ØÞ·Ÿ¾-“cÙ½ûp Xnœµû0­Ÿ½ò¹/ë„õs"ÌRýªûubíN¬…cüvÖŸ CõKÙ<]¬Ÿ£bQm¢®v©A¬«6S7ëÖ¸0mËî„ßÚµûÐí y0j]»Ãú¹¼€¾xñK5,¨ªÍÆs áÇϲ©í¶KíÑ ßžM&Ëúé+r·Ø˜oý´/×>wëçÕ8ÀÙÀV&®Ž“¦ù'`ðUVµ£uœ„‘Ê>ïî—º?¸?ëÃþÛÆ \hwa,´â‹ÓVv.ëæä 7{?æ…³ü%h{Mc?ѶتÔ-ÖëæöC›Åº`†¿o³'ðÐÒqˆ]Â.uO<õV0öm ͦéf·¼Ç· –݇n¿ù]µb°nÞ7†¶×6ŒßeT~ñ=ãÚ(î÷ç³}Û3šýhû=t¹Á<ÖÍ b–Ý…Õq7í^>-ìc.¼ÙÍ÷¶5JÁuvÊÂ+qÁrûÇ~ÛMúb³Ù$ÝìB¸[ïNÚmûºÙѰڎYZ«þyy;ø]ÚîÁåŸÇƒjš ¸–?â¶»°ñÛûï÷ÓlZõkÝxE·Åýdwõ•²[¬Õ,~Ã6EWüwܯÍÐ{ß–½(@ûŠm¢UþZ·¥êîe5üó+÷}î³1ùÂ1Ö~>ØíU†á;]_ã™awÀ†ð½ñ/¾mö¼ÚÒ çìû·!Ü®„CÌ÷b]Üc˃Cv çÀÍГ´göšSà_KÿÂÿÊqRàüí­xQ / t(<ÐNx`ÿ‘Ö^è´&Ä_'úXøbÀËÉ€_ßÐg—;FÝ»¹DÀá­(lLX08lœAà…ë€Àˆ¥^X%^xëœx‹Íâ+ù€@g+»x@à̉í€ëE€¤~ Ð`Ói Ð-~ˆpÙ´áÇí\JhÇôšÅ¿ž@@³ø7w `Áƒ8°`½s `Á8r0`Áˆp0`Á§p0`Å:à`À‚Ñç`À†‘.°Ðw— h°ëÇ–Æ•r0 ¡-K hNWЛp[®7Ú"íëdÀ2p; û¤þ†À28ƒ–ÁåM@`ÑÚ% °hQhÜìÚ€ !°L¼þ F*°í‡Ï ÷˜‰å`@à¶€ÞÄ€6XÓB,œWËÂ@›¸áíˆ _°¤ÀZà\I ÜÇ`X+—•¢@3€ùD6`¿)Ð\jhFˆ9ø¤@›`ÚZÃoYX9Ý%ÚÒÐ' ´;÷û ¬ôŠ$îvð›Úbˆ' ÜË^€u``«|M·ïW``#ŸÖE< ܇¢Ÿûaz@?÷±Ç@~/ß¶t~ÙD?¿Týö18Üç~â#¸Ï}0hñϟ=¼=}T êó[C€>´Êô¹+³¡ÏÝ47Ø Ðgnš¯$>(ËH|шžÿAˆ|~ šñmÃÄÝøüø @|ûÞÇ^Ÿ;h 0 ćÑWß´9Þ)ß¶Üxý|~Œ/X |Þ.þïmC!h÷¶eÀ©#Þóa1OÞókwòžýªxÅ{énïí…MÃ+%à›†à>wÄ@|û˜ (oCߣˆwHÄ+h„âó§wŸ»®€ˆà=7|É{î¹ò1T¼·-ŒMÞóv}i’¼'iC¼ç-ó,òž¹ª@Tâ=·€ÞÀ{îÚh™¼g-w´ìÈ·¡G8ÏpxæD>2þjò™ç ¬.ä3E½¼‘o¯Vð̉|Ö0 ›Èç?ÝEÂ+°Wç;+æ+{ùr }æ&[@<@Ÿ{y;†í¥õçeÐ7îšÿÿç¿{ÕUÔ·úçüòâ¾ïXpŸ >÷=…B—ÐÏ–Yþ{ûÙªÊW Á~¶8óÁ.ØÏŽú¤·W]íÅ~þßÝ"ö3‹¿¸Á~vÖõ‚?;¡àÏŽê þÌH#üùIŽ[¢??É~ž ¿z‚þ¼“Îq¢?; ¡èÏÎ*`=ÒŸãH+úó»qÐýy¯^ôÏ3%ÀÚp;)V†¤hp* °Bƒ °6|[©ÚzØå½kCRÔ§èë²Ôÿ¬ÞlèµaüMøS'þ¬.ÁüÙKáÇüéÇLø«P‘“ý¢™`?ÝN²ŸõÀ-©ÿ‘ëý“Õ¡ÿ5.ðRÿ“2õ¿&D ý¯Ñšú_ÜúÞCl÷Bl\'ûÙ³x €y–ØÏžÎ›ýâ˜`?»AoYìWéñKö«URžØÏŽy³_•lìgn~@›àO/Ÿ=Aà à/ºðg·üu²ŸÝ1¶`?5ìWÉ2‰~ŒHHôSNô#ú úé'OôÃGu_4,ò“‚”ä×DuA~í»hWŽùñJ ~íðÓûàWé‡KðÓg•àW?:>üôÒ÷Y»€¯øM õ‰ûtF`_ž!ì‹ß:°Ïî t&ìÓ¯Ôg†·ö§çÔçú¢Ë}:'˜/^¡`¾øÞÅ|v¸KÌ÷Ì æ‹+ ù4~&òÅ -ä‹-¯6Òo0_¼‰Á|eûj#&öÅïØo^`_ž%ì‹~öÅöåYâ>MR‰~š!ýâqúÅ¥ýâéý©ÜA{†ú‹wKôg_á›þbÈ üÓ‹ôÃeÐ_t3è/Ž ú«M 'ü‹q.ð/~ˆÀ¿x¤ñ¦Æ`OP] `%åê• Œ› Ô„˜?C `ZDúæãà Œa- 0¦¶ ÀlX˜gã] Ô÷¨©79p¿€àÀ´ˆm™ :#jÝ™ Xé¹N´Õ;-ÁZH)‚vÚÖB" Ü€•8ÐNž‰m) >n Â@;äë¤À¤@Ðp<ëåM4ÊÁ1‚@ÓþqŒ Ð>˯“ ƒ2’©ÃñÙ¾°•€nihè–ò@ C;@·LÈ„@[þCá:Ú@š ´Ät n™ ŽfpÐ=÷7àNòb`鿀ˆ£;U¿” ÝS €¥Â—@ŒÿMèûòé²Â úè|8Ä>jŸ‡Ø·ð¥Þ·š‚ßC„KÁX~~ c£à÷-Sð{€‡à÷0Ä3?‹Šß_ì¡ø=øÅÒr*~ôˆ’ªCò{°0?$¿çôå1}¥|½ô>2uê}”%½ï¡´˜zßWÄ¡÷=`ÝWЧ¤¯ Ïþ&¾RñaœAŸNPGÐ''—äGÀ É1ºØ½ïâ œzŸboRï Kè}W,)øMzÛSðS,K ~7ÿC𓞑‚ßúõiÃù7ÁoÑ{›‚ß’ 'Áà÷Cð{¸‚J諼Áü Ç‚ßÅEs ~“ÞòüB~ ÁOÁ„)øQ¼Nè³g…-?ÅÍõ™¸ø¢¾}A} ]NÔ§€áƒúŠâIƒú$@$öÕÏ›úÊO¨@‘ÔW–ÔÇØúƒú:¦©û8wØ'ý,±oð!'ö]\"'ö1¢áà>†ß&ö]Œ Nîc씸O±É}ú¡üñ?E'ø)2.ÁoqYz_á™ä÷PÑIô{øy¦àש¹ûÙgŠ Êü.¡žào[zIøË“m|‡¿% øk’oƒþš4ò ¿mÁ3ýµ›AПɘ¸Ñ_ÓÓ úk'è¯=ï¸OX Í‰þzaσþ¶å ût}Ÿ}À_büí†\Jðgâ'nGð·Û!hþ¬oøëMÒšàϦ#ø³<& ™ào7 8øëƒþ Á_Ï OÂ_—øð·›B þú%1Pðg'QŸ~Ì[ùÛ†öf¿mÁËìg2ð›ýúÅ:دO~öÁ~¶˜$é‘ý"\3ä?Ç$ûE|©Øo„‰%ü Eˆüí+á­ ø3 Mð7Þð7ôVýù²é뤿1èúAˆ¢?ӇϨOתNjþ†£ƒþ.Æ‘'ýYœ*ô;Ñß%Q(èÏÆXDãÆÔô7Éw¢¿ñ(VTôwU z¢?‹ë‰þ.ýμéïjä6Ñ_ôw1<éï¢/1ñïzÿ]“ÊVðß5^* åœqŸ~ÊF„€ûª~BÀ«ã÷MÜÆbŠ-GáÍ€×%µNx1¿*1p[ꩺ?U`àîøóÆÀëB€bàuahÀ!ÂÀ‰y;)pV¡™(Ð4ths¢ÀIu )ð ‹·¿]PàDÄsBà64ž p^„ê€À9±‚I´× mCÊ𯩀å'* §5½€KÓ,wFâÁž ãR‰9€ÑÅrUN ì<#É |G2hê‰çq!?€·’@H]üBÎ4R!~¡¯'_@è Þ+n9UÀœÊP ]Ë©2ïÈìTÕ2¯Ï„3Ö„Lf|‰€>* é‡ Øæ‡ Èõ#ðÁäHdÀÇ„ŠM!Ú!2­ü0v>ÚCœ¸ŸC¼°t8”@’Ú¡Næô¥Èq&©P "I…¶bóv‚ ·+¢ BO®þ:©°*†&•ÀGq¡¢ÂÖÄw!â!aãËžHh!çŒ U"àT䨰ÓCx$v¥%F" S2Pë¡ÈT‚­²¤9áÝð)"´rop[`¶%Ú6Fy€Œ8•€ŠÃÊD@æD‰€—ä:a×-‹;F’÷I„FaÁvz?“/Eòe" ¢s#P‹ö@Âë¦%°?ÊÅZÑ0˜ÐÖp7!ag”v"áÒf'Æú,p4ñžpté‡b¡¤bÂ1…|Xä-1Xd2:™pŠD‚ §r†‚ --Lj ÇŸd¡—)˜p0'™0ÏNN¡É„Z:$^“?D0¡-8jdÂýë­7ÚK‹˜ðŠ.^ôä%Nñ@0ážýÇ+ÐV)0ˆ §~¼`B[޾™ðb6y2¡=e@˜˜pR³ $œK)|B»©H8•ÌH8•H¸Oºßzà­PÊ@ÂÉx]¡cL¡',<è†çäÁ»4ºd3 °3L*yp2 ]88‡ˆQ8hQz¸’pÐVkhE<8•Uðt$úƒ“mºEŠ'?ûƒ ‘6xðpN߉ƒó–Þ(œR(Úª–™€e/èË[|‚õ",tH¼E~88ß)¼–´ÅàÁ%ý1xpÒ‰‘<ø`5zð ~ËàAe¼þ)K½5›¬úY^lÜ·óC-Ò1Qíû!yùá Õ›ùõRn?ÞPXÎzgçþrü™õÎúÕ𳡰 ÉÆ†òÏlh”#WöV–£!ÙØPþy4d³âœgC²œ Ѧ†âÏîRnÍîžëÏJ¹•û¯×\C-·vÖgû^”mÿó¹VËíÉvyÀùO[ßQ¤èg¯Âï(¨õ³—ÑGëu”Ú:ª´±­³J›ÚÊ£ÔÖ«â›ÚÊ*mjë¨ÒmÅQÑÖYñMonVic[g•¶ø¼â(µõªø¦¶²J›Ú:ª´E[qT´õO¨åÖÖ£lÁðÓZn×/Õrû¡€ß_©åöWûVËí¯÷½–ÛÏ ¾k¹ý–añ‡QèÛ ø§_Ëâ_Jÿô·—Dk Þ¸_)‰vGI´WŲãŸÿ“âeÿEÑþá'­ÕøK¦Íõ“òh3ZÜÿBy´=5/•GÛÆÊ£mÛýÛŸØ¢c[¾Ë|˜÷nKŒÎ²+ðƒ·TÏßr‹;RzižR'luKw¶GÒz‡åa@V>èVÜ£>ô|â,ø2—¼[ ùB'Ú¹]‰Gæ8ŽY¾&q·fÅý y! ¶žéÕzñå¡NýÖÊꦬ”Ók+Ðê bñ·áaœfBõºûPá$±N‹S4+<ôj}ø‚¬+M…\ÄÍÜ ¹˜jf)䂞پùƒšez+gï‹ÑÞjÆÙûlÜ÷ú”štƒm‹âì)Íí•âìéÍèmÈ¿Æ4õÞ.ù×X=§·)S\z»é`c¢go»NgmòÝi m-¬z/YhËq²÷ªB[LkÜ+MÚbd˶¨ÒÖäíô.ÛÄŠµ÷AÛ`Tcï=lVÀíLzØz¿é^³<÷1n‘™?ªqѹ6ÁÒǤsífyŽÝg:× ´Ñî¢sí¦3¦§Ìô#\…Î5K ôN]•εÅÄØ½°¤smî€Û:מÂ7{³‡ÎÈ~ :×Jjýºè\{.^¿¼Ê‹6áÏûB…–ÍNÕýZZ +smŒè¨ÐRõFÌâÜy—Êl¼>ßêÕ“ŽiZìµÆ1íAÆ^ÓÛ7ûB…åJ÷9ndìÙ×ï]˜×DÆ^§~¶_#w®m u>ï {]Õ´^ ì¾Íùt ™•Ò󼋋Æ^ oä]+2ö.æMö»¢#›¶åa‘–›¿Ãm@Í ŒA÷`-Óáü™Ú’ÉëlíÅ]=ýž,´uÓ3Úm"÷Œ= Á€e±ÐÖMq¶ß míWÇý}Úºà€ë«²ÎÖ^I/Xël=úXWc­‡¡N}uÖÙzpÊ@‘­Z˜}Ó×…"[æCõN® çšähâ¦sí¢§¥¯çšUÁÁàÚÝÀIxõ=è®™åæoé‰tvíÎÒ#ÝF/z³8¿™¯ßŠlÕÆ=ýé(²esÞóT[‘­º^ êÆéVdË pO3YdëaÔ\7OˆõÊäQï–Ww3‹ü¿Ý²j­ÈVµÊWvÒ°IÚŠlÕ‹«þa“´Ù²ú)Ë- E¶ê¤B8쇶»™tðÒÝ¿æýôïc”"[uÑ3 Êw½'†¥QàiÛÇ ÁvX%(«±Ug¼auŸ¬Æ–‰÷ÞÜÇ0,}ØOm5¶ª-ý,û‘¬ÆV}Л¢­ÈV v°Ù2qǧ‹Ñ.ÙòÉÛï¦M¢â86; ÊVfäѪlµëâcoÊlyïüê½ ÌVŒ#½¢Ì–µ7pL+ögÕˆÚrêÄÛftõšâ…/—MÐ6ˆ·›ZÇØSâ͈Þߊ>QfË\híÜ(³Õð˜e!íºíÐF<¿m³0”€ám¡œ?FEÚu3!úe¶zaưIÚq· î•¶¬ÿþ½›¤mßKLø›‡MÓ6ˆ·Nÿ1&²®»JŠìsà^³¥Îµ²®»¦”1¼Ž°|ÌWA¡-_ùµ¯ŠJ[ÝŠvÀ€¤ëÞôE_ I×}0%cØ]üJ“_žÍÑ6„w Gòk_S¹í÷ðe÷éò1|/Jøò_·9õ–}ö×òˆ‹Û~WŸdÆõxÖmn?w¢Y¼F¢Ÿ…dZ'¶Á5ÿLoSóð“O[-Ú1r‡Ù½Üζ°FÒ°YÚÆñ=“`1ý=aû0no¾éÛ^ëçºÂâî`o·|['ÌÀ„q[ÑÄ…Ç5Ðððxá}Œ ;6¬Ÿ{‰…OÄfiƇŠ&…›fÏx/~k¡´ÞÏw „ÏþB8lO ¬?¡/ „!xA6®Î’;^̃YÝ÷àAFÔ<Ø“qð Kâ$Á[d$xë=\•BPpÅBÁÅ’DÁ'nX(¸×#øB,gBÁ¹áI‚{97OueV½á Á›Û7% ÞÜ,$IЂÌp–HðfIªDA+™Š³ˆ‚‹uqof;' .bKuP…Ø“W{³ /™ÿbÁ‡ÊsˆƒV`W’8X¸nHq°°|e¢`è¸!ZôÁןm…|R¬Ò¸ƒb) Z}šF+R ³äCtù'QìK#ÅA[F€%Ö"¾¤8h².„g‰ƒ6 ^Ñ<Ý–‹¶Ù qЧv@ÅÁ24CJ,J¹ qÐPøä%úóÄ1Á‡[fI´u"\¯mAÀf(å–…8h—Âb$ÄAK§øJÄú ´mÐ |FmÐr¼°Ž•6XöØ×@‡ÔíQÀã.mÐîïAÃíQ`A%qÐ÷hÁýQ45¤EmÐ׉ 1jƒ¹ ’6èðP-ä<Pô­k`Ü~§^º ÅÄci']Ð6zÉ‚±+RÈ‚õD²`ÁÌè’=ÙŒ² ½"/Uжð8H,JÆ Y06 YÐ{pb âp eÁò\ßdÁr‡˜¸´ùC%Bô½€€g”¹âJô‚+8У öH´Œ#UÁ2YŠ3TA‹Ñ…Z&U°L–„I T¢q¨‚v/PÔ'w´J œŒ–I œüRC,‹QMÉŠŸ ¬…uľcÞz§ƒ'£„‚«¹µq)r íÚùSXµåCpà#f ´È R9ðYÄüàÀ›{ Ú2—g‰—.¸Ÿ;äEb }|øiÄÖs"10Â)+ŸZ7IbÂÀˆ>ôãÚ Ã§hº×K´ckÄÀZo'0pŠ«9‰«œ÷‘I |X÷o ¬H``íØTXUú))ðf>ÄAgX„ó.µ(ú•Bjú]ö>½ÐuøD~E5‚ü /›äW˜¯¸Ðºð­ÖGq—€‹›K.Å ë#Wh'A[ \¬5™¸¸RJÔvFÀúp[ÀÀªØº@‹f^/!°j“Î@¼Ô¢¿VXF/诸݂þìÅÅç-úkEz|àŸb_EvÈ|ÓŸ¶V ú³î›! NÎXNÑŸAî‹þ& >Š *è AÖKTõ˜$Á›!õ‰‚÷%ê Þ  ´cвPpSÞÀ@ÁE‘ ©‹LÁÂZõ©š.úÂA#Ï‹ôG5°1H?ÕÀ‡»¦ 82)¬ôÌ$j7´äA‹®Ç툭NÀê:Bó-q–ÂH& ,·,ÒoMamR÷„‘Å@h›³¿°±¨w¡öYO ,Ju Mð¹”`(Mð) ôV­îƒ7Z'ª´@acMŠ‚™]("”Ç)‘Ðôè7¶@!¡J¤(¸ßöò½‰„­Â$ >ŠDQ0Ð2‚CïPêú„J(&,ܽ0™°^ LUpè£ÎÕz÷•vˆ‚Làj=™LØ$cŽòMd¶ ­e~¤BsI¼s­š*TÁ¡k—'¶)ERª`‰LEqaEÔû! r}”¢ «¤glèÿ'ß6ˆõ¨d9š­äŸÿÜ¥Ó.ž¿Z:í‡g(ÖÏrhßk ý³”NûÙÏ? šGýªŸ½€{YZßG©­,Ц¶Î¢hj+R[çQÑVE‹¶Ž¢hÑVmGÅÛEÑÔÖY->©8JmGE[Q-Ú:Š¢E[qT´õO(fÈðòñ?+vÿRé´~ô¿R:í¯÷­tÚ_;î{é´Ÿ¿lïÒi¿e(üaäù6ðýéƯ8äW‡ÏBé4+ÿجlã/–N›K¥Óö¿~±tÚþïÿù'ÿÊÿúë¥ÓÞ—ø‡Ÿ´ö?+˜VÃXþ¿/¶ï\ÉÖîäç5ULíöÉîV²5ãG÷êIÉÖ ÆÜ%[Ówzuì8ˆÔxŸfGgÍyÓ§ÑQáY‹m%®½`gÕ=ñ^Ã7ìw¤%ºe¡Ý ž5Ï_G+ž5÷·úÝŒž5KEG¯¤D÷ÀœµàYóÄóæ–g±À(Ws×UàYóÝ«[*v;›:¤k·3¦TL’ç6`ØÊÆhQrT(¦Å JŽ¥Óf¹¹Û ¦‡%S² A›-|e³<Úíla¼™æG¹˜ÏƒÝZÍKu„ñ;ÓPíf>?®Y»¶;£¶;mÉ„íÎú7­Êv(aÜ*”m]tÖ­íΚ1ëÒvg®‡éõ±p;håÑngŒÝž­h»3¦íOÓ.±Ýƒ^§)•Úî Ûݶ®íΚÎÚîŒų]Úu{pËíÎð [}§ÂT0§¦•Ï­ >ĆF{õÁŠôÎÍöh»3µÜKlwæôì•éÖ£s£ÜÞ˜n=˜={gºµ½B~©>XÞ~0Æh¾ÚîŒÓàì“Û!¬aZÅ ‡lâk“´⃠y³/¦[[J>Ú}˜n=XbaŽÂtkÅ1ÌQgìPâßÞùÖvqœÕ™o=X­fÏÌ·ÞgMX.æ[0›c2ßzpWŸ9î;”Àà0j÷2ñ'ó­Óò0ßz ÿe^…éÖcb®˜Weºõ »bÚjrp÷8\øê*n€²yÛ“øD?¯‹µí͇ ËdmûÁ¨•yÝL·7ûhûv=§x8mŠ.¼žžÍÑ4à·)ÚÇðÁȾistc›öÔÊâöyVçfgqísÖ¶ù˜óBm{kÄ{`w¡ZÆ‚rÚÆ]7/„»³»£eÑKÛ¸ Õ2Ö>m‚.¼~m› + Œbǰ{7¡e?ëöE=޹pLö&Ÿ÷謖A÷ã²I®¾rš¶q—áC…¦mÜ¥d. á'¯iw©Z†‹ôÓvîz´Ÿ7lStg;6E£ZF…xÚÝtqogõÁjŒ5ktVË`òÀ\WcµŒª³fÅ ®í§mÝ5¥)ß°<Ä­z‡¬ø›[l?7†ðK÷êõL|á6I#Ö™™°¨,Ã+á ·Ù°±*HƒÅúƒ{Ýü`ÜŒm׎@ž¹‰qßb}/m<ˆc΃/Š)–7w_Â÷j‚Ûâf€¾¶“â‹ðìÛ-õÂnò,pg46²æüZø¦!íu|±„#¿H\d0`›pæë ¦Íì>\TòŽY‹‰®¯Q¿’íÛ…`g¾]pŽÃ€û5Oóým¼›¢±? Q ^ ufÍÂt˃³Hߦ£ @ýo«›ö†Áûô5Õ ¿^,È"v /,X@_Á‚kÒdAæs,H§r D5˜ƒ¹ÝéÁ‚ÜÌð`ÁŽÑÿ`AÖ§=X°³á@A0^pàÀqpàÀÂ@/´öuP Ð )0*¯‰—Ä•À@/³ 1Ð,¸Yaàzpa2àRÁ‘€@6u}ËD!зL¼—2}{yà!ÐáX(,”ÎMŽÎ  GÑ„ÀB}#!ФhÜ °pÚ„Àm+ °ðk n…šXX^+)°`gà„ÀÂŒô„@ÛŒÍ 7K,wX…‰¯ *Ë–X˜Ï›há‰o´ÂÈ~ËA¶©9Ú!‹Ã 4 ÖªcDµ’òƒk.$r§ñ ÀÚ¿S`ô¾Vê²IV‹h& ¬ (H ¬SÐ' ´/ í+5×ÄÀʯÄ@U}O ¬7Ç„À@%$V抶¢­T…•QUh%1°1¾<1°1Œ)1°2Ý'0ÐÊÆ¡a`ãx™ؘ.Ø´<4?øMظ+wr Á“åÏH´í Ákâ@Ûl ×6F%6ìš›ØXi80°é¶!¦6zq’Ã’›˜88PJbr V¬©Ë ¿’ ý$6Ü$6-æƒ{v‘sì’Íqâ6º¢’»°5°ë½ ´È1XÈ€¦¨¾!°kù˜ ;#³µá{B`g |B`Ç"ÀκÍI€â}`ç^¹I€=˜PØ9x$v†™;W~‰€!߉€Ó@2 6OìÌ]Iì uHdk2 âÑ’»^’`ÀÎ]Ñ’ÍB*$v¦$vmÁ€õ’;Ss“•$‘ ¤`ÀμЄÀÎÍÊ‚;wEK WPP`DŠ¢@í\šØ5úšk LÈ`‚¤@kQ ò§ diøUw` Ýω} …¡Æ‰£êRÂÀð^ä?0^áÄÀÁ$ÄÄÀÁg³†‡&‡ÀÀÁøòÄÀÁ"剣úDCKaà`©óÄÀÁ¡Ä@; ”% 4WÊ×Iƒ»Ô$îk8Xï!)p0¸<)0|+Aád TŒuR ¹Iü©1• ppúHÌW9 Á!Èt©¤ÀAwiR`S3A‹î¤À<)(°ÎY221Ð~–0ðâ†$‰Ú‰69ðb‚fràÅ]É«.$j£ã¿¡`Ú‚by  ×/öU”PЗªTµ+ô± ­¯ Úû·^,hkÁÌF´Ô1±`dˆ½d@² Ò_0hËp†`ðiœ<}yñu° ¯´¾Œ1,XÐ?í¯ƒíQ¿`Ð݉€?‰‚•)Ý) ÚògI¬·X¢`¥³8UÁ*U´’`cUJ‚¥SR¬ƒC¬ÜP$5ÁÆÒÀ© 6VO<4Aì=š’`»$å…$Èe‡$— ¶*b Úr-‹gÙ¤ÁvIb 6–S9$A~%’¯ï’ ëp& Z!ˆ{¢ÁúFÁv!ÐòÐo?õ@®ž=pðÕL=ð"“¤È\‹CäšàÐ¥k§  ‚¿m ‚Ü»ã@Á¥“qåP¹ø<8ðáO ÈáïA‰Æ ‚ô¿äÀõƒøæÀ~Q<Ô@·©†¨j w½=Ô@V¨M 4Ea er€Í„þç @–KL Ô>JIÉÔ‡Xˆ )MŠ·éH1Ú!Jé;Õ@*ˆ¡>"³C Û¦ø S)Òù±ØL1Jó!ò‹KìR†UÕ;)E*S ìß´ÀÞ9óvÖð9´@zÛ-ÞÂC „còµ$K)°‚û#Q«ÑÀÀ¾ ‰] Nb =c)r{ì—¸KØér;0… døÆúaB ”b—Z॓B œbÇÐYäêÐ'ûK ôv^Z à+´À®cB ¤ûçÐ µÔך©µZ`‘^1°H”(A6A‰¦‡Èw1P8Å@Lc‡8g!^?ˆ—Ä/J&)2Ö囘3ÄÀ&ÁPb`—¶b >‡éî;Ä@9ŒR ¤[þAIi!2=ç%~S)~¼ÔÀþƒÐ9Õ@¼mÉLv9ÔÀ‰™àP§¹à@¸Ô ìÔŠ%<b>1rF<0°ý 2m%1ðÒS?ÕÀþVCõL5µ~ |„Š ³H Ô(ŒO”38sôÁò$ÎÏ[ ´·ÿ­Tò?0yì)*!Å@ì)v°ã!ò˜õ…Ÿb ÞѹQÖ!²Jï!2iñàÀ&Á08µ"Œ³B d½à@ËóãX¡rj©7,âÀÉ*o9¸–r ¿]‡X°’;8ù0É·žNêô-ÈuϯTL;ØÏS˜_2 ½Jû5 ¬É~&›@*ûÖí=ØçûuEsû]Š öc~ÝÉ~ÀÌ“ý w¼Øï%º›|ìWuVÀ_#äý5u4è¯I$ ü«ty$ÿU)=ÉÌL>‚B‡Ä¿ í\GPèTÃzóyeT(SùŽ¨Ð›ËûŒ ½>—a¡â9úÀ7›X™e–¸ñ &Ì“„€Ñ…‡,!vɈ!ReJ={ z KÏzà”¸z Ä=p}´ê:_'Z¶Ö75P‚f @"°†È(Ô.É€µ«1`íŠaËVF?ÖÁß °r°C ”^j w¹;ÔÀE OœŠ> d‘òC Ô{”È ÚñÍ6n¶s@àTX¦ °Ñ—–¨Ê#‡¸¤*jà K¨ØäY†îå%J1ðQÜhˆ¡Çòvéz` KëÈò€‡Ø>o TBÞA olj]rahó;6&ο´@ÌЧH|;´ÀëÚÚéÐ/¢lj·"@C ¸¦Èšó‡È}*1pý(" -ÅÀõ Ø‹GC |¾…6­>ƒ;®I‚%s,\Z& rŸíCÄøq€ ÷v=@P^ IAÎC‰ˆ‚ô“ ²]€`%‹z iêZ žz bMC¬ºá›ïÛ›w3ãÚ%§"xqñ™Š p‡ Ø…p!²(ÕK¼˜Ð~é^Aðþ&ÒóýñÞ¤ È]*AP¯z ‚—Ô¾P…ã§"ˆ7éTŸwThçô{(‚8EP<Šà¢‡ãT¡À‚àz…vñî)–o‚  ô@–댕¸øDS ¡1ô@–:ôÀû»ØYÎæÐYãàÀòuB`˜*œ< °siø})TØa¡ °kÔzi_~KŒíö 01`G±C ”œ™XñK&r_Ńë÷xСPƒ$Àòy ÷b<1S¸™,Šþ ¬:&°I“XÅ„¡ré|(…sP*ˆS Ô`˜J ÃÅ%ᩇØ%ü…8DaBÀÁº\‰€ƒ›S$c‡È½D@.VµMù!Þ˜Å_Rà þ )°H± );ïŽ)JÊ‘w ³ÖD: JÿÑ[þ7”M;XÐ7Äz± 3]ŽÐƵ3?+ÛŒ Uî_Æ„*¥'cBY˜éˆ UÖTÆ„^ŸwHèžEH¨2Ã2&”¥`˜Ð‡è(XBä És‚(u¢`¡+"Q°°–H¢`á.ÞG~à’Ì(ÈŒÉx’C× )PéW‚¶-Ú+2Ô÷LQ +Ý”‡Èzó©Ni‚¬­v àù‰‡°#CðQê¡X°Uµ,lU¹~!*7åÀAÑ6å@&»r ¢S„+Y°ÑONlŠ l·H/2éÿIìÜŸ0iP‹Ë¤Á^.*Ôª0i°sˆ¤ÁÞ¥ÿ‰U“$qP;°$Z¸ä>á`$½ µíVâ`ŸJ**qÁPIƒ]p4¨EL¦*â5S?ûLÔ«”š >‡ÔâNQµtUuçGQò¡xÐ,¤¿‘EÏ;8T“Ô‘#(wðà¨Jå#Úì÷æÁÁ­L“µ)Yòà@æcòà`pòà`¦àÁÑ—* Å xptÝxpp¿’äA{@dâÁÁM “Ç(´ÛyóàÐ’8xp0[÷Èä¨}ä^D3G°s1#Œ¨¦LTVJ& R¼”îÂàÅN¤0xIN ePS© ^JŒ$Á‹â\& j…žI‚, u$ NÑh$ NeJd”aæÞô"Gðf»™#¨¶Ì¼¤èEŽ k ¦0ÈR²/ap½y0E ƒÜ•ü•$ø£0È@Îéå9„A忦0ˆP›Cć‡,(|IYe4UP2j¤ãÎA^7R/~f)  …GŽ ìȤåÐUº ׇ.ȸ™Cl?è‚ô‚º CÒ^¢ã…ƒ£)ø3tAåw¦.xI­ ]Pñµ© rÉrd *h8tAîzè‚…£G!£^¢h÷ˆERÔãJ]…€_º`}LJÚ7õõç_”ë÷$Áþ(%0ˆ0r E„È­?€P/Å Ñn¡&ˆP›)Á¡¨Ø~ˆ‚f¡’u“ë‘H¸°n`£’ålˆ65fCïÍx½•åhH66” Œ2GC²œ Ѧ†âÏîºi·åïÙs=ë¦õßP ÍX§ßý‡‚UõØqýþù Ç/Òúª±ö½ÆÖo)·öã+}ß¶9ò«äÕÏ^aóù¿K²±¥£ŒZ:«¨©¥<ˆ-½ ²©¥,¢Æ–ŽjÑR¤–Îrlú´²„Z:+¨Åç±¥W16µ”ÔØÒQ?-ZŠƒÔÒ?¡ÈÚ}™Êóü·Vdí·Œ¡z‰?Œ˜úékûEþÒ~kåo.²v[Íêÿ7K¬2ù_í_¿ZbÍú¡Äš³µÿšñ¯Š­™±üäPlm/w;‹­™ñ{±5³ý×ø×¿ý‰MÅÖÚóËÅÖö'¥<ífˆ¢Œíˆè±ïb1éÝW®÷=™ªÍì¶û¾•ª­¬’{)U›:Ú^Ë*U›Ñ÷*JÕæFL÷B–/ü­¾êX Þ8³À%½:¼qÊj¿×€3Î]²hfÀg.Y6sÁçNZ3áŒ[Úà÷^7¼qnñ5ÙZ“ù&þ×gœç½»ÅËž1ï< ù‚ÅÃnÛpþÂËNi|Žf,ó¿/ߘû^ÑògÜzX0û¶MêîI κáŒs·²|qfàí`'Z·¸/nÙþiŽgw’®Rá‹3ËÀ! ¾8³¸ƒgÙæîjÏ—•ðʲ¿ayrSKX.8ã  –íä5•v?ÜrÓWŠ.µèŒ³¿nxè‹+¬f²¬ôŕޗ`Ù¾=÷Mq2Zö ;ÈáÑØ&8••ü=_­ÃW›³Ú #®PNZ¶ãMg>\墮0PrµI?œé¸ÐM?œ*¬¶è‡KËC?\a`óê…~¸B¾Ú*ýp…¡Õýp*d°z§® XÒæPºá ƒÉ·n¸Âêg«_tñ¢àê“^¸‚÷ìO'7Ë]}ÑW¸ÏÑê}p…›îa„>8m±ºµôÁiŸš5}p…%ŽöÔF¤"³ úàò˜ñ„˜‚‡>.úà 5ð5&|p…\¼ÆM'\a*á²èÅH0¼Âã¡®0¸w]…N8©4ëª-âê ŽipÂUê~ËÖLÆ—„ë%Ê-âW¸Æåñn]׊r‹¸kÒ §*ëºé„«®¦=Ó ggù×r=tÂU:¨Ö,ôÂU–k[³Ò g;&ø=ÏF7\eË5;ýp•q#kŽ‚?Ùì ÎNA#ýpª¹ 7[ÇÍYö]Ë n¸Št¯Åêƒî…ÂçáAð<Ä{`â÷ó¾Î¤®2ynÙì\©jâù=‹n¸Êh²eÛÕ4•±vßm…Áо6x¸oÔÑÛ-n¸Ê¢=íåãCxe$êcÛ{ݼ–»YÛzC½Zn¸è‰«ð†?¶«ÌØaÿ`›ž C2/XÖ‰±¸™‡~8íÁõÔ?\å(úÔJW\åîšïžÀ,Gô©vºâ*ÊÛÜËÇpÞls¯›—òié1OËbHæ@Ë“¾¸Êúíî¥Øè‰³½qŠÞ~|@ Åþ&=­ÐW¹uõ~mè« ïú^êÁWJô´No\e:߶Ч€ÐÇv÷‚ ¾ðv=¶»×Ív¼Ÿ¶¹×bè)úi›{Qýž¸Ò¢7Ž‘§MÐEÕbüùÙ]•cé†ÚB o8¤Ñ‡þtDÿÍÈÊÝ–‡R8ÝîO‹£÷ƒ•õc{aôæjñ±½nF¸¢áûâàÍÂ5íëõ°âL…åçc²ÙRxá)6;«X.Þ›U,×WœÏè…ɱ àmy¢X®/Jž1“cÅôŒëfr,·Õxl[¯ÉàZ©zl_¯›Áîp &Ç¨ÏØ HׯeÓsQpŸeÓ3 ¸A›«:ê¿P¦er rËÃj¹ « ööcþ–kúù†€ˆè9% %Ò­t ×Î2(ý@@ªËrÍã‘¡{  ’k›Ø2Ñ 2 ë@ÀŽ^ÈÐçƒ!• ØÅwÁ€ÎþD@ªW†%Qv¼Nª C" Å´Y)é`@®ø<1 5ƒYñ`@E<eσý)õ¯ƒ£Àœpiâ`@‡õše€É€~î˜èÇÌŽø90܃Á¥‹ßÄtö%ÆØ%fO%Êe˜XX¿'00O–OEr Š–&¦EX¤• XR X˜“ X¸_‚`x8 ‚…1€ ‚yŒ@°°Àp‚`aˆi‚`BL Ý HU XP5)9°°bdr`p%j7ôàÀ4ˆ Ë’$–‹¼hÇ€éÄ….„ÁÂM€ •Š< •ôœ$(§k’ Ý 7(X¸‰z¢ 9oAq¢Á2ù^ Êå›4X˜4X £$ ù‚³aÑ`¡«„4XXù>iм·ÞHÐ`a‘ý¤Aº‰ ž„A%ì& jsš„A9ŠÁz ‚ÇN,,ê‘0X¸ÞJ,LF ”:a° 43Y°Èå,h‡E,¨>ü eÖÝc{8hƒ&¥¼KñùqHÄAwé½Áð–GÕºÄ<ÂAÏc~)‚ny)‚QÝ*p0òQƒ£8Wð Y„"|´vð`Ôº Œ =ð çpáOò ç;A`#FýžàAßÊÐ#Æ¿´",ŃVNo¾xЫҿ$AÏ–ÅY3wð©/ô,œµT±k0€J<è{ï€À +v±i5Á>t ‚1o)ö¦›“ ¸`)AP©”)ö ú{pžÁÎ Ð)vnŸ‚ •õÄIìL¾JAÐ2fвÁÞu?»¤½;7DNAÐ*»â$*g4ÁN?oj‚E;BDPíÁ‚žñ-bòë@A\/ôüZX$ ö©»‘(¨lÚUk+EA; ð%QÐ÷µ>HÐkÊ} èYÄ@8i‚έÐ;k‰§&¨,ÝU*7UÁÞt–dAKY°³”FÊ‚…´RìØ!UÁÞø»„*¨Ð¨T;}© v¦¶§*¨D™Pã5 U0>™Píâ¸c©‚e¨RìM UTm[‹TmR^ÏÒÍ”•©Í>RT¢Qj‚õ’;“§R´ßùÍ]ŠZp`çve‰‚©n‰‚;A$ vîR”(oPÐNA³BAe¨' ªvs²`W”BÀ u)ì\F' vDà`gàÄÁ®ˆˆÀA«s ‹pв°ÀzâÁzƒ{¥rHì܆%q°=$…ƒ½:m´7vÖNlÐ&‚›4é ÁNçyÒ`£˜’4¨âƒ‰ƒù†‰ƒv%´,lòÉ6&x'6Ê4Ƀ âCâ`[ÔûDƒD$ 6¦t 6yE‚Û#¨ jwõ¤Á†¼ë„Á&¡=`ÐFp§`0&߀A}f ƒÛÆ$ ¶GÐ&lÜð%i°1—%i°-*~„AÕ÷Ll¬ç0Ø–¸S0ØX^ÄúAE ìL4LìÜ’UN6I°ÓO˜$ØY‹ðW ­%ýO£;é¯pð>è¯(ØSôÇB5ýUÖOú£ðyÐó¬úcÐÌAUÔ&ú«i2AU5΃þ*ó\“þ*‹E$ý)J&é/ÏýUÕ&ü1:'Ù¯J— ö«R3ƒýTP+ÙÏV//1Ð-8FðwXžpBàaü),îЇ•b UƒC ätˆšÙŽ€Ðûê•| ø Ç}À_áçò …Âs„>?„¢á# ¼¡òlŸ¡ yD„BʈЦшHÎ#"t¾Ä@w #Ž4"Bq@„ƒrº#” À¯pP¬@"T1Q:ÔL„ƒÒ¥y„ƒ.£ŽpPʶ:$Ï)"t|åþšGD( Ç!¡tN¾BBçK4 •Ê ½Pï Ð#$×ÊPæ½½BB¯7ÿ‰—gL(ÏRL(=5GLèM© ƒBYððŠ˜a¡¡ FX(w&>ÂBYõè ]ßø¯°œÇ+*”áœÊ£WT(^”3*ÁϪ0Ì3*‰3*ôù!*jëŠKQ¡ŒͨÐþŽ ­œ[ó˜#*KòWT((ñˆ ÅïyF…R?Œ¨P¦Q¡XZù½žQ¡ˆR8£BŸ¢BiQTèCmð‰a† U¤æŠ—"ƒB¹;Ü+*a—gT(òÚ…{GT(‘0¢BYHè e²îÊ^q¡DÂŒ ÅGq¡»Î¸P|VÊ=Y^q¡øÌ3.tHqS\èø¼ °Ê‘a¡ ºÌ°Pùì2,T±zñ‘fX¨†ª eeÉ#,‚Ã+*ô~ ‚ŠŽ<¢B™<~D…2î2ÃBça¡ã­Ö)&Œ¸PFPq¡ŠDϸÐ[ê_Ä…Þ¼T„…ÂpD…r;’#*t)r4¢B™Û~D…r¿à#*”z‹¨P„Tža¡ˆP;ÃB!a¡×q¡`ˈ $<ãBA\ºˆµ*8ãBç·¸ÐGBcÄ…>bˈ eÄÂA€,¸tÄ…2ÎáJ.âBÉvA€Â¡€@nì{@`QèhP`QÃAE‘¢ARH 4Ë«*)Eì_¡Ï;0ÔüX%ìr¨Mlô¸Á¡tÈ%6Æ)ÈM…“UÉôà@îeõŠ]¸úÃۻߨºÉGt(°0BC™Öv„†²ˆýʉ#4´ #44Ú‰ÐÐÆûÏÐÐ&˜ŒÐÐ8& å4ÐPz§34”ëÓ#4”u1ŽÐÐÎKeh(·€?BCYáo¨¶öJ÷;:”u\èP2Êâ½tN‡²¼Óʲ4Gp(âÑØÐûó-;PIqº¤ØElè£`Ñ'‚Š.p`°Úƒ“,XX‹0Xøb$ j¿Ø¤Á¢ðÒ Aû/o%°Hð ´ˆƒ·¨rÕ/ìo)°\ •X¦"U%I !–û ú¢üE)0V¿IƒSzAƒts& Êá›0ø ²–`°2œ*X°²LE²`-\ Vi Á‚ªJ—,(âNŒµZ° h VnS™,Xù{&JöNŒü—ÀÁÊ¢Vƒu2…ƒJÍH¬!ô k`›p°*6p°^ÊÒ#¢ÒɃ5Â@Ń–ñNTÙíäA; ‹+ßœäÁªðÈàÁ §eâ js'Úio5°*d1p°>Ê4VÖI Ô|Ÿ8X¹åPâ æûÄÁV¾†ºí•ËpÈEÂÁÆj–Ƀ6é¼yÐr ì‰[3Š[ý®6! ›rOmy' 6–AMÔ”•8hí@6y>„ƒ6±|4غ€Q4Ø”24ØAƒ*”˜4¨+i° ºP‚›|AƒÜ/aÐn›‚AÛí÷"ØÄ!ƒí’Åa°]"=Á`“4Ø$Á ¶Ia/h°I´bˆhY4Øø4Ø.…uŠÛ-ÉP4¨@–¤Á&×GÐ`S„xРDg’³lSœôF 6}õƒmñ«l¬”ø’‘3z ð&hPú~ÊLKlë; 6¹sN9!¥‡ˆoꔥ’r b—S”ˆxê×;GPºÈ!Έ¥ ¨K‚`ã`c°õ©Žwthç þ—¸S4ع_Ï!Jý ìôÌ$vJ'vî=™<Ø‹dÄé ìE¤âÁ^É¢ÂÁNßMâ`/?ß8Ø«²ðR¡‰Ch ”ìž4¨ÊõIƒ]9WAƒÖIƒ•¬“­§hP;ú% v®G’U…þ­~0¨bûƒŠ~HTôHÂ`oŸwlhgÚo²`oClQÂ`§Ã'aP[o' Z°ÒîƒñÊ ƒ½+ P0عûë! 6 u! gRdië„ÁÞ%%†(È쯄ÁèhŠ‚](úðöÀ³) 2å¹ËÙ! ¾aЮ‚SBD×!vþL)‚{=ðÍý’<b c“û¥L¾¯ïb +&bà•6µ@nRuh ?¥@ÖÜŽ2kµTO5Q¹§Vìˆ0£Dމ¢ißÉ“xÈgüö2kµXµéWÛ²µÈdcÍ¢ü3k‘Õb%ýú«!Z^ Á éÏ£¡=®ÌO{õ––³!ÚÔPüy6´Ú»™Õ¾7²ÚÑÄúVðퟧ¼Úl=ÜàŸT^­^¿¹ºÚ^¡þæêj£_ÿO««ýäMÞ¼jñßó(võÓW·2å*b[Y:MmµÓÔÖqÛz¥¶¢xZ´uTO‹¶ò(µu¥ï*ʧ©­³~Z|ŒyÛz¥¶¢€Z´uTP‹¶ò(µõO¨³öxRâsuÖ~Ë ú§÷ øÃù§Ÿ¿Àç0úWÞÞw+sµZŠ;>~±ÒšUû?+ƒöC¥µwE´ŽJkó'­ýÃÿïë«íßÎ"ôðS­õŽæÈq½é·å¢¿Õå¿ý÷d<‹Ûr÷Sä;Yí£¢m7,ûŠ´\°4«ÌÅ4ú‹–çÃkÝ<¦2;›ËÁm±˜9æÑ/XÔ$/lƒºÀåÖ¶\#,,“ ðÝnwÿ0Ý}ðB«}èDv†Þu«Ì=g© ýsÓðȰpéîÁ!G·×<_–ÎÔlÄ¿oƒÕ½}Ô–ôݖɬúÁ6næÔó²«)ƒ~°‰‡IÙ\µÕ2 —"ôs˜…·pmÐݳ×¶H»ö©ôyvfب°àÂÃv*¥­Îþ¡÷o虦ñF3ç;ÿ~êG™óx+/ õažü¢…ÙØÜxy[lO;úôqsWÜý‡¸Ô–÷²UÛ%KÃÕ/Kq…óšýÃÔùÁcîöa†ûà.æÀw^[}`¨h-Ór‘i¡áQâ,ýR·ú@-`[îÞϪæÄ󗺟ò‘"ƒg±W ¯#–…·ðÜñR¸ß¶¨K½Z¾[Îb;VrŸyôèÕºˆKÏkÍþaê:)e©«¥>p‹émÙ}PIDåÍóõÛ+xæ¶ãaÁííõîÖc`nïQ½\^;›tÜò½Ø)Üݳ{pñy†+ÌȦà¼-»Lgço÷ ‘Žo–çÃä{ ¸{°dÁ0m ÿ¾ð·ùìx T8ŽÛøóaØ&ûÂÄÄ «}C²Ü´ÜíCnñfVUl >*{ÄêÔó\ÓÃY¸zUèÇÙ–ÊLÿ†sªrà1ÔU›•´+Û”L©¯H­¶e4,ø0kUj»-êB»p•eðZOQŸnY•ŠÄÐ\[a>67rÙ–Ê}p›úÐÏ)Êâ_°L&c3·ÞLû0#Тp‡‡mQ˜&o–G–O«—¥>áã­½ÞeÎãÙtËÃürÝ“}èêÃ`+Ù‡‡ç\C û§ëêÕ¤ånêÕÂ÷UÕ«Évž¢^ñ=êêC×eɂϥ/pæÚü°¦gA3¶ó;ÅŽE‹²ÛC]ú¹‡ºÀ-È·ån²Ü´¬úéï›yʇ¡ løy>¼ŸÖ¥ }Ì—z08LTÛ÷KQ§´ôKÕ.ž5ÆGió´D‘tÒ&gv ?Ý¥pu´Á©*ñOêzJTà…}hͰÔý…•õa(zA»³ÞêÒÄ;³²dp)Ûó‹©÷ü¾mÏ/ÆÄÞ¼”b[zhS3c[ùvÚÔÌÄ{tiªÌÏ5Ë# ÖˆõöQX`¨·ºÄoûvEw‡7Ïöüb\7–õV¦îæÎpŒµ=¿€_åVuÓÊ›YU}b/mbfŸžNK”ZåYK]`x j·,œV›EðânlÇ/ÅðßeFBÿ¶\]½â¯°²èæRxƪïžò¡eÊò G·>I/¹Êcp'OÞ¿,Çýã%"`û(mâ·S{óÞóÝýôÖù¸†ä+¼D¾òò•O–D¾BTKä«dµD¾úò‰Õù?|š’ùZ©i9KækZÄóQñ>˜ùó…¥g.Qà ƒ¨IC|2c»æÓä‘З–ì¢®« ú[uñ¸jìÓ$•اÉ%±ÚÍ}šn’ûºx!¸/:Ð/úi^Höëú¡‚ýºÖ†CÑ[䡨­Îû7u²m _Ôúuáp _@Ë!³@?M˜‰~"ü ¿±@¿!¾ ôú©ˆ~C”è>‘•}XÑïú]z)ýÂódèà ô»ôsú]úšƒý4‰‹ýÜ C`û¹…4˜}àų ¢6pS”A$úù)ä1 _º„Ä~nÁ¼Y² ‹Çd¸.%ûy1E¶ ròcˆ`?wÁôó†eyäâJºfðIýüB„­¦‚Œ= _Tq ôóTBÐ/}QB??†u€ýÜÅcNgËÏ#/žÉÏ d«zËÉuäçÎ(4Û:%5“ü¼¨ã‹üÜÂc@~éÒùù•IÙQhvàM~îN#k•¥.qEIò‹"“A~î#ªüÙú} ùíή^‘ÑI~~ Ïùyø0žÉÏ-¤NõAN8‘Ÿ;ËÈVõ×®EôsGzNôó³mãz·«>ÜŸù¹üx·ðܱÙU£â%‰ò)êOzõ‰Í\Ù¸òD~î¦#‘µùÝÒ/9îøK‘üÜH°SyP>a’_ºÿ„~Ú$Ð/½tb?÷=Š•»$R’ý<®ûÅ~~Ì‹ýüâ0=à!cÈÂO•ìç÷w°ßÂö´Nöó^õVUŸÈhS]Xò”þ¢¨gÀŸ»0É[õV§ø‘þ¢iП·C²SõêÎ>¨ÙdÉ©œ)}2¤?o…ç<\Õ±ÑìÜ•à˜»¤‘?–I~épù="ùÍþœàç Ç´äí/^ûV‘R6²xó|ÜD¿(~è‰Í~nÁÍ=yÿ|«žìÇéÐV±sÈßP:-àÏO§ÆŸáô‘ÄHø³¿©øþ1’ßÙ.ÈϳrhùwLò;¾¥>¼¿üåˆ}Ç€àØçwBªªK=â/Iìó;!œåýÓ@¹¬^! R.«B/Qß16Iñ«I†TüòÁHñËYãÉ.e¤øÙv3Áúz¡øE7Cò‹W8$?ëÉ>($ùqM%½¯&MRï‹6ô¾õBïK‹ô¾xÔû²Ðûªà<ô¾Z”ô¾Þ~é}úñCî«r/„ÜÃJÈ}ñó‡ÜwÜ å¾:½(÷Å€r_•€r_•#ƒr_•Ë$ä¾ÊPûÒ@±¯á¼Ä¾BBìSÅ€û”ÇŸb_\%öå/-±/ŸŒÄ>;‹ ¨„|®ºzöà"ÎQ)«¡ìHì«CÐ%±¯†Cb_b‰}ª3b_#±/féûâJìË·Fb_•·‹b_v{dØm‰}5$-‰}ù@%öÅ”bßq%ª}ùJHíËO[jßqL‹exŽbYÞ¡Ô>˧$À]çz+ľ:$ŸHíÓÎa)÷åï+½¯½IÒûòS–ÞWGÈrõ~OF¡÷U…?…Þ—ß¿XX†à—ï(¿:$ KðËO‚_Lr¡øå×,ÅÏÎ"E•X 1¼@’_íœ6BòËŸS’_ ‰òÎ>¬ôùµˆ“”Ëò†ä—?¯$¿ãJ~9\ÞGܰ² |¤øÕK)~y))~1Ó…â—•¿£u¡ë‡€äWGÉ/ï_’_ŽH’üòÅ—ä—ŸÔ“x+~Ñi ~•¢ö¯ÔI;t>Ï{{é|–¯¡ó=ZRç{B $êYa-Zˆz¥D°'Q¯‡X/-b½RäLë•êY¯©8b=_^þù@½R$Kõ2jH¨—‘E”ùÅ õJ´ õ¸¹F’^Þ]ÏŒ7éåý õJ m¨!LzfyÅvº…à–]નWJȇw?oW¤WŠ"gEz¥K‘ô²Ñ‘ úåý³‘žYˆh¥Räà陂^ÈyMÅstÿD4€^ž@HÊ‹ˆó"*8O{õ&çE3WÞ½NÊ»§HD*E"Œ(ï8‰”a]AyÚX”wÜ‹z@Ì"!ÅŸ àŸ¤;kŽÌEºSݹ¤»¼„èî°Ê›íŽf w‡…p§Sžã.…uòXWªHZX§SÈCù8CÍ“+Õ<ÅU¤š7#hTjž|ù©æÍ•vë…šw‹¤©æEØk¨y·ce0*]/+ƒQ‰.¡æÝߘ.ýë©æÝúvBÍ“ß;Õ¼[ãíÊ>®Bλõ²…œ·¤¼RÎ[Aq’óVžä¼Á”ŒJ€ 9o… '-L¾æ”ó–„9©yë5oÉ)j^“]àš,ä¼¥‰•r^¸ŒCÎ{´ 9ïÑÚ*ä¼ðކœ÷h­ržaSÎ{>/²ó™‘ÍHÎÓ\™rÞ£õCÈyüçU»’“·›(üÏRó­CÍ{´‰@΢>Ö¼^7o_¨'-ì aQQE UÄq­ˆ"޳hqqœyLã9í»®0΢g„qìEg éNaœtKeg‘Û»åý_²<²(fSQœ% MQœ%6Eq–7Ø•¢×,¢85ÒfgUŒYDqÖPÅYCTgÕÓŒ(Î*ÇDDqV=Šˆâ¬zó"Š3Ί0Έö0Î*ùaœU2²|éGöa¾Ä¼¨[z„qV©ãÆYC5TgX®ìÃúÇíDg•&â8›–ÎÇYù¢3Œ³‰o"ŒS`ÇY㜑œí;Ù•¦G‘œMŠHÎÀéˆäl¢¢™]x¾…r*)C9åüS(gŽS(§â›2”³K7T•¡œ]oR„rv9]"–3Q,g×±œ ¥ÊPÎl&{@ÏL„rÆí0”sèŠPÎb£B9#ŠøÎ.ðƒ^Ù~œÊ94üßܽͲî8Ò7÷Uœa÷@Ç ~‰°&а#ê_(¤QµÜëþÍÌ\k%øî]ÕU­Ž°üêl|IO®ü‘+§|åÊ™GÑ•³qa–+gêåîìÒùfu®_ÎÎ7U¾œôeJ_Îηnçॠ_NäË ÿå?‘ýìÀ¼ú»Ç½ÁáˉŠ|9jsørbÏ&_ÎO9Ͻç>Â÷¥ùrÒ…M®œr“+ggl‹\9;cdäÊ)‡+¹rJ›‘+§ Ù`<™÷åÊ9ˆr圦\9é¡“®œSZ=!'˜B®œôâHWNú¯¤+çú`<ß¾Ï÷‚gÒwbÝÂî¬|DðQÓOWΛ¹rÞ"­"× '°¿Dðmélt„Ô¦]žœ2È“sÊyIçÂ<Æùó€±ç1B/9o“üÄyŒ¾#ç]|fz·Ñ½ëÕÓSpCŠ#é]ô#%è)lU W¹•èU]ðÖR'õ®( ìFl’ «ˆ¯q_ãÃ(âkDx_ÿB|ôqÉLè“?¥ ¯ÓD ÐO=„~©©ýhOúSp(=óàzEï%=seÇAœÂÔ© †ÑÓ^z^ákI9¯ÌtÜ,ø›Ž›¥ëðãRÎ+‹ ¯?»@ +‹w“j^1¯ÐKb^ QÌ{Z8 '1†Œ£Ã“=ûªœ‚^ö  Wn>ÓôÊ­€= zEÞ  €C¸TôŽ(zeËד1|tÐÉ>­ Šá[ÔÌ÷åIALE¯¨½ Ç£¢Wè_#E¯Ù¨èѶ‘Š^¡–%Q¯|8rzË;ˆïº¤ARÔ»~BÁã.ªoþ?è«b€õ¡èqÁJE¯rc#E¯Š&yùt³II¯rÇ!IO[bIzŠ8“¤Wém'I¯‰ë(éUÉo”ôp}ô*÷ï’ô¯Ešž6ÚõʼnzšAÍtJx…>?”)ˆ1° E=®–)ê5 tõe–Æì˜÷;‚ÏÎ1ŽŠX“`—¢Ç¥¨Ç­á¡é-*x…š ]š^ kE®Mó~60°Ž¢^Wì]ŠzóCÔC˜§D½!¬KQº¯D=é_=1(Ôô&c¥éI=4=DqJÓ›|QM 1ùKÓ›Dhzr>D½û~פ¡D¢Þ$†HÔ›\$$êM kõä„-QOþ¿õ– ŽsXŠÈ£ 6i’¨G«!E½…ojŠz‹+…D=yòΜÃf`ßVVrÈhTÄÍ0õïŽD½%¿MŠz·0Žs¸ù.JÔãg5E½ûCÔã§-E½[1„õ–Äœ–f©z›×'Uïæ‚.UïæÒ,UO¾›õ6—Z‰z‹íS(‡7§2ºJÕÛ©êm HÕÛt!ü1YkŸeU^ÿæ}¬çã3çYey¡¼ë–|6Sïüª>™óì£KÄœgŸGü‰œg5ª÷c³åL†6æÒŸG†±fyõú9[ÎÐÆôç9кÛ;y[^E›âŸÇ@½RÐm«Ü/æ@hã@úó_žû¬®å9ÿå>ûúD×Qá*ž ¨¾{„Ë™l/³ëÈj†±^YÍ0ÖÑ c½zq¬ÌjƱάf+{q¬³߯Ìj†±^YÍøRf/Œõêű2«Ç:sŸq¬ìűþ‰ÜgÏ>Ïsîü{Ë}öÓ_Þ‹ã—¥ó—ïàs9ý§÷=ÊŸÏ}V»³Èÿ¯rŸeš³ù]´¿ÿ/û¬ŽKáÔeâõB8u@o áÔ÷ §F˸h+ WÝ:¦Â©'>¹3“€¡ÏR°å:îÅ–†–=i,Å8³(“VD@Õye*­Ø̪TZ}"cÇ[g‡ôŽ?‡²PáRæ,Œ1Ä´çÜ ]«Ñ²nÚEÃJ[''°t)œÀ‚ý¯®¢{pRx®wN«îæèÔ¼²ŽŠ‘wÃã#f_fˆ x—íËŒg ‡ŒÍImœšS@‡µø>…¬í{ò}j8Ï\bµê¥t)'w´\MëÁŠ^?Žzáõ7üÝqõ£Ž"ñ¤£eëÝ™Ñ2ï÷ŠÐKÎ]r·ߦ°\v+Äu.NÝêpaF]j¥g·:\˜ÑBÎ Î|ån4ìŸïóæ„pm×ZœÐÄiîI夠¯…bÍ¥ë%¤¡%è^kåÆn5¸(oá¨^¸ÄU5Êy_*gÀ`înßc´„ñ½› rPEŸ{rRaøØ}H⊋¥ç˜TË)°§pÅjú‡“ŸÀ÷¦½úA{ý íÅ"i:ØI{ñè´WѲ”<«ƒÿKÜ öV*YÚT²^ç^^¬ÇœLd½Nàë¡÷{Ì•˜°G¤„=Ô÷;`‘2 {¤Gu+I‘1IzŒLÒâ8’£“Hz‚Y‘ñU 7ðP%ëe aOÝÊ™ ÜJ™Œ_ñæxJÔ;@¨—)‰z™§†¨—É£ƒõÒň¬ç¨öb½LéCÖó<;Ñp/90¨çDþB½ƒÑzÞFË)€ÀZúÙc˜~qN°^õÒ*PϹñ·üìq¯ö’Ÿ=‘}ËϾà¨-?{ìfÀz>í’Ÿ=é¯ÊÏ»ŒÂ9ÐËŸ¬ç-à¶!?{lõÁzÞ‚qæ~Ÿ{ÝœUǹï¥,?è“sÀ¾èÊ9¿®Îì¿€zçA­ÊR ž…–œÂb‹¦@n›·Z¢aÑ îÅ9qÖ‘¡gQÏ[dœØ«6åüùµÊØú¥œ?/ÌóQ1ÌØÊƒ>SañÔæùßæ§ÙSÉqÀYeÐI´ÊË:¤8è«WÚ»Ë ô2/AÏZ6]é[³núSÄ»[€h =ÛIznZËéyÕsˆkµÉ†–†‹uZçñ¿Çõ1#€^:7ô¼ŽZ7g„.yùTóòûKÔó)þ(ŠÑ׌¨wŒÔó0§Ð_¢ž·¼D=?†ô§|ê×ýóugÀz>§ìY …³œÂ_åeÅt*éz<•d= ºÞ‚É9u=nëS×Ë–%·tÌRºžît=²Jêz ûˆÔõ²Ï1(}TÅô+HØ[|Y$ì-ìb(ìå¸S®õýE{ÇÌ÷1 ç–o=¶êRö’É.9×7ô¡²—}r'ç@*KUL-Ÿª”=DJe/¡²ÇY¥²§>WÎáCØãËœÂ^ rö²%…=°Å!ìqœc Ѻ^ýÐõ°ë>„=’ÂN}{/Øót¡*¦ŸEºžnt=®7©ë1Ô>u½lÉ)PUÔð÷½Þ×B]O“”®§IJ×Ó‘®7±›H]+uêzšt½<u½QoIƒ¨—jšþÞ²¼E½¼)õŠlõÊÜAÔ+ÌR,Q/'ÔËáž÷ÜAĨè èƒp eJz…æ!Izy U½üE¨ê器ê&U–ª§—k׸ÓõSº ¨Whg’¨w´@Ô+‹Òuˆz:ÑÌÀŠ0s¸WÔôŽA ‰)FšžÍ‰-[sÂQõò™9jŒTõh¦KU—LQ/ïDˆzy"ªzùC­œžÆuL!†öA× ÷|˜h˜ÚáfQÓ;ÎÍ èöQÓKjzùHPÔË7!D½üý)êåCCQO3¸€Ò†vr¸UÔôŽaVîäÞš^¼ÇdzGI¯ÐqJ’^Λ’^ÞÐôò餤§LEï8dì’^Þªzyƒ©ê³Çû‡’ª§yKÕÓ¤¤êé’¡êñÎ@Ô;åý+IÔ;†˜ÚÉY(êé¹’ªW˜'Fªž¦-Uß3©zy9Tõxƒ%êéÆ@Ô;ÚÉ‘!Šåœ¨ëÚ³¥ë在ë在ëébjN§¢¬—¿ e½£OËÉ·¬§§²ž¾¥ÒõŽÐõŽQÖz¯{ÒõôØK×ÓïOYOá™’õòÞ´c ¬iô{)ÎRÍs+è!èÑäAAvžôÈä)è•SГg ½-‰o)†ê–½lÙŠ¡¾>$=:!JÑË.TôH÷TôòïN?Æè){y zÙ…‚^¶PÐË–ôÞ¤ ˜×?iz_ñÔô²¥*w:[¨ée §Àq) ‡¼7³%³§ã¨ôàdKzpÒO4=8+ì˜pë˜Ã˃óìÓdbŸ.ƒ[Æõ>Ó1ô8æ€>ëþl¡(–Gm…èiYdbËÕ?~«}ÌHÖêÇ<%ìíγe–×°—=Ž9àL_æ ao8qž-WÏ*…½lùœC {ÙBU /Dêz¼@êzê°î×+”ª^qLXwL .ežb—ª:¨ØµIÕã{—ªMa©êià¼~4ïÏ–u¿OMU/{l%ÏÂÅHÕÛoÎ;’®§.M¹§lýú˜’t½<ÓPî,¶3@®ûý÷Í1[ɳ>…=*a/ûäØ'gðƼã'°—ãPØË£(ìe {ÙGs@MË3(ŽªØ–³&…=¹­JØË>ö¶Ü.5ƒøS—?÷Ûâ’^ŽII/¯’ÙLj‡šG0£¦ã5}RÎc å<ÍöÐó„|Òóö‡ž—çJ9 ޱôräô0Ž=œi~™ƒ=r(z…z˜î¥=pbÊy<$å<¶@ Õ°-º¤¦‹9ô<°¤ô<œ[‚þ<®-©æ‘S Û/¼;î®Ô<Ý)Éyyq)ç69#KÎÓ8‡œÇ>µ½{PÎË–”óÖ ðNaîË$ç½<6û}hy$ÀÔò0È!æÑ‡óPó@f”Â^ZÞËWóøA!oÓ{s<`§‡ë8”°—¿æÙry/Íìóò ¨BЭ½öËòøs¤'•+…<õ™}ƒQŽàê>gZžÔ=‰yÙB1zpŠyYbžFN5(—jF9Ô¼Ü-Tóò( zºŸ×1qÇ@OÃtÏkŠa@BêyyP/ïõzßÔó²Ç¼?&%=O7Tz^¶PÏÓ8ÒótÁ-§€³z^H÷?žåì·ý6!²ÑoW‡ß&ý-ÓošŠ0yGó2Ú˜WÉGLbqœÄ<¦LÌ« #ç±yr^öáÖËs³~z‡/ª@¯ÒÏQ W ¼=Æm͜Γ×3 ótmÂ<Ž"Ê« 4åiŠ‹`D^N1„¢¼ìCBbaö¤<§‰ò8A+¾'äiwΊ¤ a y þHÈS´' /GÉ)0*/§€€FA^ö! iR‚<,ÈÓõ ò˜¶2!¯ÚyzŽyzJyLmIÈÓ¼y9JΣ俇÷fýù’óòò’ñx+’ñƒSŽ)DCÎ>‹B¼˜Œ”ÃÌ}^]BžÂkDy9nÎ`PžÎ$Ì㳕˜Ç¢Ë‰yUñ~ļlù2‡ë˜Ã‡ó&_*rs;%çiÞâB¾†ÈWå{Iäcê±D¾ø˜B4˜êÏWœÞqû|š€¯Êg2'ðÁ{:±x/#îzÖǰã£þ{"Ÿž*aOoÒœÀü >D^Ò”|:€¯"ùW_“3Àï¶Ž¼âôŽ‹óUEÜMí…ÆKÓ;¯æ˜ΕsÀ¹Ä|:—˜Oo˜Oo¥˜OW#æã·0™OÚ}ÌgšÚ ±ÏZo”°/ϵÇǬö1`Û1´TmˆÀqPbÏýP4ŒÜÏ} ŸV£3`ËÊíððÖ~ˆ}¶öCÉJn‡>\8ëG¤ž®àÇ'‹à—í…îðËÓÌûµGHîã6'¹[ä>>É}\“û8éä>~Y’ûø ‘ûtyWNÇŒýÞ6$÷éN‰û¸ä&÷UÅæ ÏS€„wµÏ2S¶´ÜÍ¡¥—7Iûø$&÷é—÷iââ>]°¸/Ú¹‚bWr;Ê»>¶sÉ}xŸÎ g=®™¹r¦¥™Í;¿ªOf8ûè’1ÃÙç"ÃÙx>ï4`l9Ó€¡Y‚ôç‘OlÜåz'&cËk hÓ@üóh>èz¤¾ú[¶œ¡éÏyb²QýQ|%&ûT`–+·~Iüô¥Ãïä+ûÈ öõ‰é³<Ï$Nß< sŸ‰ë"OSŒtf³‘^yÁ0ÒÑ#½sŒa¤#/˜tfãHÙ‡#½2ŒáÉ=²‚ÙH¯œ`|سFzçÃHGN0éÌÆ‘²Gúgò†õ{ò_iÃþÀ õË{Åù²ýòíSûZ£¾h?FùóiÃúí¨þ—Mö÷oFûû¿4YØCŠH fÿú·oÚ˜,¬Í,¬Û7"~žÉ÷IŸŠØxêÏhÁ^fWl€˜s¾ï¦ P|¿wרb˜¡ R$ì©ý Ô{uF‡#)¾±êô,Ú»2^<ŒÏ£Å"‡Ù}” ‘Ç1…Qª ß…-2ÞwÓ”w*쯣tx5Ñ÷Àâdަ6F™ƒ‰" a”Õ™c ånÌM€ƒ6‹ #žb\É ˜ßu\Wx5Ùv5¦yUójªôjzþ¯¦vAà¦Ðÿý lÌài_8h„SSgåÇqÍpjz^§‰aVx5 úå믦€‰qáú焌=*®±.Á¨WøußM}®ðë¾7O]«ýmA®ñÔ^YŒ*µÛþmŽà¿| #üâŸθ®î ­Á„;êmv¬åyÔ1Œ³èÓŒ٣Yú±§eöpͯ~•5ø³6¿úgñbñѪـÖU˜æyóžclËŽG*vPOË€÷ø³<˜k™%mcÜif¬å–´øå[LášïÜCŠÞ²&¤€ÑÜB°ìw ß´gˆ/¸²îinÖ¥OK|÷+‹sx~þnÝæPÇÅ'³wË3ú\vl»Ÿ­ÝêUï—«O3d-+;RÐÇ?šOËKŒ3°b%Î3hòBà V¬¦¤dcxÖ›e.¼ØÃò(?-•žnãù}mN¶Cãæxn Í© ²×6‡6™±cŒa£Þ¬ðüiF ÕU¸|ŒeO²ÔåcxvÝÕC"ÆØfÈZ=_œ3x¾‚í3fÐoºA>-fZvÙøug5+ÐòéÇÙg3C–·+ŽÙ§Ïi14ò¹dŒ‚ac –L8¼2Æ\fZÏd!OÛÅTk©ºàm†¬e)ÆñP/+­õ´lvË2L| Å§`‚Ð@KLÁžŒü\ªµÌÎ |þ§ï-‰GÌò¹ß_.-Ûë9xYöõp4+¦àyzã©Y1›[HƲ/ÌÓrÓpÜX–s}J‹Ïc8üý™LL8KLà6Z0û2âD·ÓͳÅ×s>_å¸å!wLû&?Sºå=í›l}*Ÿ¬§eÇÏ‚Ç|^qýwßX&æÕl'´ì3¿Ê¼ºí„–WyÀ0ÃvBË>ŸñèO«^µ¬e©Ï2SÖ² À@KLa·Ž7ü¹ûÏåíN«ä|>Ëϵ,ížöQ¾lŒ‰mƬžb~y-øÝjµ­Ü²j*ñ¤ÍÊ,õÁ *W ¹÷™è3»Ï©p#9­x•ÍéZº¾»úœôNûŠ*ªÄl6ÛàGx>ÍÏÿ¯(™3í»l“”Ø´ƒMÉôê˜v³µËNLl¶>}JYGfÃ&7„³aV" #¯æ-mÃÞ=­x•MI[ÏiÅ«lJ“ù€f÷t¨Ëlœa`šÏ—ÙÆ¥ÇöÍÝÓ¾ËNÈŒ;›¶þVkA²ŸÙ»Ý‚ÛtÅXŒf¶zî sv>_“b%­Ù1…»ãM~V蘂Ùö0Žíýã䱤Îᵇo3|†©rZù*û=þçói~þîŒÓœS¸X˜lŸÂ2ˆÍÅ|öÞòܬØ(Lû\µx†qÅϷϪ›é#çóqñ”â‹ å¦-Uf*˜Hì7¦°X‹|Zù*kyzb•˜´8p74­|ÕŽ‡ «Íó„Úߌ ˜öe¾âñÃã8} ÏÄ™äùøaóéä-U·x®?Uå«é0{áiIÙÏç:|€çò9,[±[b^0éO¤ ;°oüì¯%öÁD,ìc-Ÿ“ûpPbz$õutY2Û‡mTÐG$¡btBQB_ã.OÐ׸Wôunw}ž lÖ“jawès½-S¨ö ú2K4¡Ï³âì;½ÞÔ§Ší¢>UþõY½Np!¨¯$®\žaŸÂÝ„}Ï¢>«e2õ)o ¨ÏD]œ*ÁuƒÐ®L($ðóOû¯÷Uf÷=Ëî ¹¯2¿ÀïW´û=- v˜Bë/ö›¦@E€,ØoÚj«Û’Ü™mì÷´lòaà FØa Ï‹‡­`Àßô•+áÏ‘¸ì`aŸý Ó^q<²O 3¢þ¦­v°9ü=-L» ø›æªcAÀŸ·à–ü=(Í’”€¿§å¢ ðgßZÀ”Ã_¹²‡S±è¦¸3€¿b»…hö+ÏöÏ+ØÏ^>PØÏ×:´û•ÆÂÈd¿ÒY8ìg/(ìg/èz±ŸNûÙ–ÄèS˜ºg?{]ñ@€ýL°™‚ýÊͼ§d?+¡6û™`G®Ã Ìã̆ìûƒýÌb€Gìw)”ìwUVË"û]Ï“O³9˜ ï;àïy2ø`þ[àÏ…?PfÀŸUhÚ ø»ªì:€¿k]?[˜Âs+m˜ÂÍTñd¿Kr#áÏ— ]Àß5™’:à¯^2qþl¡ÂÓ ø«i<ü™v‰7ðgkŒU€?»¾ë¦]âjV@n¾àÏŠÌá}ü™0‰•ðgåà0sÀ_zŸþÌ÷§ãú‚þêÖc ú3§£ö¢¿fùã_ô×.‚%ýÙrÖÀzAv[Ð_S²hÒŸ™X°ƒþÚ3+Ø @¶ºâC ú³Y`]pú3[Ã~ÑŸpýY 68 ?[ÎÀ/ ?s#Â&ôg»ó B ú3ÃGEK -Û¤È@3ÖŒ¶‡O7 1æ`¦$ì€Í~«h0xê…ú7ù¯©Äù¯WZÇÈý¢…‚Ø+òàÿlàëÅîõâ¿^Yƒü×ËEÿ¬êvØà¿Þéü×'ë‘ÿ=Û8ø¯O: ‘ÿlŒ‚c‚ÿ¼>í‹ÿÌ™ Û`ðŸ­Ú؃ÿºådEŸÀ'«j‹_ügb+Øügåõ@¹ÁnÃ?;ÿ´+ÿ-«Œ b>‹+¯8«Ç‡™11J õÁvhHÒ€{˜AãšD´–Ž>AOSI˜€¦¯>‹2AÒÐMø3¦ð@;øÏm± ÿ­±;rþ[ó¢'øoYY?øo^,ONþ³àJç 6gü÷´ô7ÿùÉÇÉOnÈÿìïø#®ßT`<š€¿éÕù~Möóc°Ÿ¹«ƒÁ~抆w'ØÏ2¾pÁ~ËÉñ+ \ÿà¾ð·žÙ“E'„ë)[ àÏF®ècð÷L…OkÀßzvð´·LÌA/ûÄÌù|èì·ìóKuö[»a£Mö³}P`#úYiE\¥÷)yü§#þU{}_ø‡_'éïéÏ b€Ûš2À'ôçÐÞ@~òù/+-’ÿ¼r&ÎŬ²¨Ðë(¹mûO½îrˆh0¼‚ÿÜlE"Œ)Tf‘èw%E‚TCT¢ß3\lj ú]Œ’è÷,àìCÑos¯'Õ`Dü«2'¢¤ˆ~ÌqŠ~Øÿ* ©ú1w·ðÏžS´$$â?™ €^ƒþ׃ÿl`\/øOûñŸ}-@e俎M¯ð¯£ðoˆ{ÿ«ÿÌûX üëŒþÙ@ –ŸtáßÓ?&ñ¯3s­ð¯KS"þu¦6þ=}ðtÌ¡3k¶ãŸ·ÜèϘÀ¶)©º4¦À?ÿõaÒ þ5M›ø×XQ9ñoðõ!þ5Öà}áÅ@àß%.ñ"ð¯±d1ð¯Ik üS}VáßÅìøÂ¿KÒ*ñï’]øg5¿NÄ?elþ=ûñB10²:)ñ+ðÏ%p¢]‹ÄT*%üs’‡‰Êðïù»Q üs²Çüs{"ðoîÍw0èïérK[+‘—êæGô7÷rô ?õ˜ 3°Ô"©ÓÝ%ãõIW€rJÓìþ°,8ýå©ý'øµ4Ñ*à¯Pþ ü]¶ÕŽ[Cø£Õ\ìÇ:2D?;Ì?@?[® ŒMemÞr Ÿµ¼u?‹ÇÁzïèWü…þ5ɯLäº'ø•gãŠGàW†TI€Ÿ¹*4¶84Y¡x4÷•ÎJÞä¾ÒY=‡ÜçoSüà>3R“ƒ™ì]Á/ õø8:÷¤wÁ}fþ¹!«÷Ù¶_ª_±*É/î³>åÅ}¦€À}f›j/ᯨD ¹Ï>\ØWƒûÌ\}¸Ï ÊS— jºm~æíŒ==ÀÏðŠ4àgPÆø¥9…à÷|$iäù]¶>½Èïj’¦@~lEÎ ò» Óƒ“üì"x…˜Ãóè“)me3?_Ÿ½O f_¹µKùÙóˆßäW4H~ÅKÃÿšàgó›Š4q‚Ÿ‹1&ÀÏ~/ž<ÀÏžë—ð÷´0è#À϶c;…¿eOAy)¥W¢+ÀÏ|l’~ö4]/ð«VÙP3¨…ËÁÏÌA¸¿ú,ïDÊÀ&ó·é/ð«—4E€Ÿµä~î#ÿRþjáŠäw=ë2Ô#ßµø‘%ú™ñŒza ß5¹ ý.íHˆ~Wš €~öœÂæô³]&´I Ÿ= 7aÐÑﺸ ú™­ÆÐŸ=ÂD;Ì¡0¨†øg,1ÐÉŒ¬ýEåfùÒŸí­q‹Af¬ßðçž[`²@'— Á[Nþ£%àÏ6ö„½zÇ3Œ% ð×1Aøó½¸ ¿f7è¯Uúˆ‘þZÕrúkfpAKà_Ãûök÷áràÆF÷¥;pïÃÉ3½*É{J‘&ÞãW$y‘<â=YðÄ{zQÄ{E9ºÅ{…IÝÈ{V LHÞÓμwqÍïÙß,ß%».ïy)ÝøäÍ$ໄ‰¾K&xŸ¾ÂÝ(Ï0ñ%ø™á âÃöžÄ×DA|±1I|È›'àË>oHW ð"ÇOÒ’vKró¬œ&Ïæÿ|S>›>9‡ ø´-ð5’ˆ¯zz>/Ìõ&>‹3ߪÄFLa è |ó~{{Nó›)§·ç´Poˆ‹$¾}©SØüR ùT×…îžöŠßr/ è{áîi;”áîéñá8S¸{š¶Nä[ö¨–—»§µ€kZ f° ÀÝÓv} ¹ðö´§›5x{–ÆtÿüºÝü†p(¿Î¬cüLÅy ø 9Eùzàa—Ô1"ßÅ<|B¾k"ß…Za"¾ŠÐQ_Õm ð=«)}9øÆÏ“÷Ò#޼÷¼MPzÈ{ ²xï¹q Á{Ï#>Þ¼×åÚKÞ›õÍ{OË&bA‰¡ö9¾Ծ2(.ö•|Q öÙ§ h¨ä¹^ZŸí†ñ8Cë³4Cë³'î?´>[Ç0ľr€&`~5/GÏr÷Ÿ/­Ïö¦Kh}V­0g´wuY¬H{•郅{;ZáÞÃöÔÒ€{]¶0â^ç’AÜkô ï -Ó”úƒŸxïùøÁ{¶ˆÎïÙQxÆ÷LƒÅà³]ýG1Ã^¦`¾ª³À%[fÇ‹ølÇŠ.A|–Ë+ˆ¯^CÚ¦ðìð4‚øjz|PéKÿ*}·A|0ø,„“ÄW­0$¾Úd£ñÕ$!Ÿ~BòñU3¡Â!3ˆ¯¶þóåéY2Ó÷ª½Í/ÏZ°MïY8Ì>xÏ7áà«à=»åoÞ«r²ïíÍQÀ{µÒ)€¼gÛý·§§ÝaŠŠÁ{öÍ„þBÞÛ´…ˆ÷,0çâÒ9ÕçPùÁÞ«õÐõœ÷L§§gðÞµù€’÷lpêq ÖûR ˆUF!Ÿüöô¼T}Àgw '€ï’k<Ï `áÀWU:€¯Êí3HéÙL‘ƒö,ÇvÛ =ÛJÌ—Ÿg5; ZH{›ÂiïªþH{y) =y_öTÉ^°§ÝqÀÞu„¿¿IçÅöR+(YtÓéçéw®~žvyñ'HOÕ$Ez–AÃòú ïIo3H¤gÁ—Èç«\8ôäxDÒóÕ 2`LÀ~VÀa`’ýLååãYë%< Ò«]÷¤WŸP^],ÅJÔ³G.Ü“¤„H+’ž9E€ÒAz­7Jvzm‘Ez&òÃd@Ð{ò~ƒžÝrˆz½» 2zö!ÙzKv%‚ÞÍb=óÿºÑSxÐÞß®?“aì¿ú¿†‡)Á¯+P^’¬zxF÷µ/á}ˆg—Ÿgæ)=1½<·—nžô+H7OJ7Oš:@}åú¤¾‚r₾"1A¡}7¿»‚>mI}ò¢òúä)è£f"滥ؘëýˆùž§½¡}]¦x2ß Ð7HÑ‚¾É굂¾…Ìb¾% óY<Ìg¿-øSô æ q-ˆ{…ö-ËzµSâsK1è)€Ïw¾ýÛ×iSxŸ©I§Ä瀂8ãû,ª˜ˆø¾u¿5>·ubÏÌø>{ÈOâ{ö¤ŠÿD€Ÿ»ÌÞ€K 1N~âà×Xý ð£\Ç?.Ï ð3vˆÄ÷={ÉþŽïËp.ß•¡<$¾9…€|Y ˜€Y!á9ïÝÈÔÜ3Pü¸ç{÷hÚ3Õ*hÏn½9qõrÈ"íùsþø®Kq… =Kg2_ŸµPŠ Þ³væà½«igî¼go龑%uŸ!Áx |† û|f+ÅîžþC… ùú÷.K•÷vï4 `¾‘]>Œtï”o’Ü;‡ 6Ü;ûýA|®¼bû.3½‘ÏL,àF ß õTÈg“zÅö·‚þMèNä»åÈ@ÿN3ø‚ÍÀ|LÂó …BóÍ*p¶îTÁ|K652ßb¹m1ß’°Mæ{9¼Ûòïl|´}Ïž•!ôï1ÐÇsúë× ú´ô=û·ùòïôÀÜ—ÌgW„:¦ðb¾Kâ,ï þóÙý{‰|v¹ ä -s›Ô*“ÏtjŽÈ+êò]ù=ò™`Fœ ä³Ûp½ïZL¢Cä³½" Èg Ó^"Ÿ#É˹Ó~ʇ`¾ÂÔ;‚>Û®舭ïlÓ¹Ó>Sí¥ñ™Xƒ=™ÏÌO/æ³+Ô1ßbô”˜¯É“Ì·Ed¾…í™Ïx¡…`¾Îâ^Òø}úƒùì'ã•+Þ0 z| äòYR6ôò­%ýÈ·2pÈ·hŒ!òÙžž„d¦Bæ òÕë#¸Ï~'ö ä»ää3ÃСñU $õ-‚/©¯5:'’ų́†P_•I‚ÔWo©‹˜AËsƒúªÔ0R_eÑa_KØ×™\Ÿi@€<Ì¡‰J‰}“^aß”¦Fì[ò¤Æ'‹ÈÏ\-@u$?ùRã{vsó ùÝoò3¹˜-;Þ¨þ"?£æ·‡§=bÄ:ßÕ¤ ýž¯5µC¢_ýªâçˆ~…ï.ÉO1Ÿ¿Æøx‚_•É–ägûÎ7ùÙÃŒ_ÓÑÏD4p€~uT![Î`¾<<ëHÎ@?CUž)ÐÏìT¼š@?{òéèg)Õp5@?ÿwü.×O¤äaޱç[þó™Ú¾|÷û·ÿíùÃÕA4üªÏ ÓãíÿoŸò¨ìôÝa<ÓØ—ËRƒ}·ýÿåË)þv´ÄÄ>S½ÂYEC©áŠm9T¶CYêçu\•ΡÐv ¥–ªÚ2÷¼çyÙp Ŷ*[r¨Mê2“Øü›_d¿”¡ªÚ†áúË@V¨ûV ²øg59|·¿\¿Õáüçº-îM}×Ö¸Ï?ËÇ? Õ†²}}"îç ô¬)zPùžßãèÃq†íœ÷>bË9RöâPg/5ªk ÇXhy¥^ëè¥±î°ØcÝ´ác©—Æ:zé5pì]ÇXl9ÇÊ^ëìõGŸsžiÃ~ߘ¿œÍ3Á1ÁÙ=?:FB²ñNoö½¾¤7û­~Ÿé;ôû&½Ù?^¿[„¾®…¿üözvvú«êïþö™{~û5þƒý,Ï‹ë?É(ëZî3ûMþã3éç³ZÖ_þ¿Zö†‡hþòŸž×ØœÄFÿËÿ©ÿýýÕýž·ñýëÿ«ùê<û¿ü—§ŸY`ÊøËÿý×f;Ém Ξ§¬Zz±ÿú×ÿ`–ÁQòþÓùÙ,íÎ| àÙå<{øö}~¶gg…ülö/&OëÇ¿þ³þïÇ¿Ö_þ[×~šýMÿ{ýãôlÖéHÏ6Õ˜ÿ]ÿú’žÍs¤gÛ­#=›5~IÏö´ýýëß¾iSz¶ë÷Ó³=üü2VÅŠÐËD‹­Ã\…Ÿ×É[|“âÁHüÞ9—>×fæ vÌ´³£ÁíÓãªýDFûïwõhñ­Ù³ç‹¿/§í^o´ÄY–‰M#l+ãCÀfÚ‚Öf´øYìêkßj.»úâER¯ei™vüí«Û²0¹5£Å1v™ûÌð3£V÷2)¡÷hñ»b…ìãú´À"²|ÿ]£Å·ÔËd€íGE üZnwö¿mßf=«ßɈâe¶ê~G‹Oà.æVfƒ<û67™ÜžXjF‹ï°-ÅJõÅ$³w3k…Óðîî®fÞàVÔû™Á훋êöƒÌ  á ß²Þ6ƒÚÐgzË3…²£%Ʊ°mÁÚH8ây â\ˆ3®ø.0v5BxF´8œ[´Ë¨~Ô?¯¹1=H-ŽýžÈcû8Øš[ŒÄº¯h‰>Ï,ž%ÃöPÅïº9íç¤O<¹Ã„=¢ÅwÇæ¸~Õ+ZÜøj¾:µ4k¡"hëêã °Ž¹7?ƒäÌyÙ^ÿÙ|on¡ öÔZæŸ0›éô‘iI7íu¡OŒ<ý÷ï÷E6ÇûE­%Ìàf¤Þv®‹Î%únÙƒ¬Ü#²EKœýŠkí–e*Œ–Q®EC¨+ZvʢŻÍÓÔ§‰+Õ»`”°wzŸà³+|v£¥E˶;÷´Pð7;н£%î…‹ÃvòºÂÄuE<ƒ7Ô™ãìÕ£åGMh±9˜EÂOnʳS)dÊ ßj ¹6ʶwíV,¼eª6ÏFSY}æ0mžÊäUŸ9¬-¬ é¢³·„ ©Ú¢…N·—P÷i¢V_qÊç¦1‹Ç¾0OäPæ`ëµ¥•B*ó‹¨q~îÖ=ñI·œQÑãÝsFEËt2…Õ×ü]é–Ò*R‹ˆ^>ÍB¦m:nŸåäåE~’~›A:\/ýWÌDeaËÅΣŒ<|ÙwÜ›»h?gfÄT7ÝÊæ¨ˆÛn#Ú‰f BïÓÙOƒ²‰OÏlÙ-e’~/·ê÷[Áû–%où$ù;õíÎéÝrÞêtvcc¨\#°Ðk!ýêÊÒOû{MO›”>-ÎDÝs>ÇÜôŠðQ?ŠöܹâÙ*òjºØmÕ¥ÚìÊÝ’ë#ïÆí±OËŤÈBÚ­8#†™ÔSF£Ë#»-Ì‹F8ûɞ˹äÊà*”_ ̰Ý3?õÛ?¡?ÂHck¬Ÿýf’#ûºW‘£áÁ,òݬÐù—ý|ˆ&¸ÝTõ´Èüc³°¸â  oÆ–¯ðqé¦ÃÆògE¶É ôþvØgÚ¾ìþIò+¶Ï´}ís7yùÏè·++§äkø¦$a唚ŸŠt˶gkø¾h۱Ͼ­ážØ,úl·”wKÞFà;2„usÇï{—ߊ0²Z=%_Ã7=¸±ÒtËM–CûPÜÒxÚíY´5Üeàh™ž£[àfØán¯jÕÍŽ^pVPéy¬\môD~ü¶hL¦•Û"n'õ¾×}K3¿e[Ľxƒßw‰½âöĹ̿ØqÉŒ£Bò'Åï }§ øùì;m‹øîŒìpoÝ?_,æfk‹øðÀÜ^ת»ïoŒ²=x¾oFTËÀek¸¹ñúÅTOÿfÓœH×PMZ¶5|3P¯Z ’­á¼ÅëZu þw]ÝD-æÏïgª<÷t ãi y¦Ú'ÚVp»˜ÃÞþ u›l‹a¶;HwËöãûÏê•ìT ¡ÅÕ *ÙnúŠ¿÷ÕB(l 7ÿŠ}š»Otó_1N÷$Ë>²?€Õ%H›æBäs5Ôíööè0]‰5\üվжˆ[^ÜûBÛ"næjœhû3ïÃúÖ·º½ÕN´¡”V³þ>1 #cªYÔm7©éŽ>Íst=}°­VOÉVqs)Ññ­~sâš­vÃóøºwÎ5½dWáZ½²ÕÓe‡}¤Ú'Ú–qÛùØv«3ZâÞXf[Æ-ÇZ.Ï¿ÔÍ#Ü)¥ZÀÆsŠa“Am^ØÊŠçÄÒ„LÀ@ߤø‡”hp èX€W` 5„:E 4üL ZŸØ0—¾ëä@ë{r c|Œ\ªv+,  8ðiÁõ ì½E X˜ N XX€ è&ƒà5€`¡·@°Ðu@ X˜H X˜KV X„†ÁÒU/3@°ÐQE XnTdòJwâÀÂDåâÀBéS xq/',üùD‚ª8 ¼˜ýT$x‘'„‚%Ò‚& ^*¬Ph†gM’àµXä—$hÑч$xÑ1@$xQÄ Zâô8Š(xQB Ê4!”7†Pðb¡à¥0¢`%qã#q°àsªÉ ­`Áš1P`AKÃBß´`ÁZ3½C°`fŽ! Ö)·¨`ÁªìtdÁªl™dAEÝ‹ÀJ(Xwºà 6%I& ¶¡h_ `…/ H0³“ÛMÇçA·“@Ú¸‹Aófˆ£‚o¢H°ñ' Ú™€g AsºŠWH$Ø™†$h%ðÂØCltÈ öò ‚>n\ @Ь±.ísS Þ¤C¼• EØé]%dB{b 5ÄSL ¼û‚×.1Ðæöb *Zoó9xa M!ta`çBA 4ãOxÍg ` Lk1Ь)qÄ@³ÓÄ‚# œÌ²)”#!9ÐÎ…†À@;è7Ñ‹hçÆÕ€=¼S9Ðn‰/mâÀ{!‰Š8Ðûžo: “-[ý A€ ¼WUK€ µ‘í¨à ’à=áü*t#QÀHÐJ0^/”MH$hÖ4»Ûx‘ åÆ ‘ ÙÝ|G$hFš@‚f«(/¼¹— Z`)HÐì+A6$A^ ôØí"A÷ˆ ~  B0HМ÷kŒ ô>uA‚~®8@Py§‚]ex‚fÏ[Ñt ŸD4ÓI :AÐÞ¯r‚  Ê t3—OA X`uK,ðÝÞ3¼¦ÉÝ ŸÁþ[Åý£flo^ Éþ§o;PpÚ#ÿBÁû˜DÁ !Qp##±PÞ–É‚IÞ’½žú‰‚Õ7¼•“wXaÕE(¸±9Jܨý‘(¸³‘(¸,#Ü ­DÁ¼L‰‚1¸‰‚É)7Ò¹% nä„N´Kö>DÁ-ß¡ Â9øPÃßþñB :„A8×ÂàsN¢ "SÄÂt  ¢Oä©’qG„©ë AÜÀƒïØÖ4¸ã•8hpǦà% ú | ƒqÔ) ÆQ‰ƒð2Aô3ÅQ ANU0V?ûþAF·ƒ}b/„ õw¼r"„( ~‰^è’ˆ¬5Bý¼q à—r0àþV"UçÁ€h4ðŠ/ÀÁ€Îr@x¢ˆ¨®Ù’È–@°ø€á*úã!¢?ž9é]’þÑN§ÐýVÍáÓŸd¿摃ýà0˜ì¶·—O¨ÿúÁ{çåêΗOhÿêê”™è“â~# t§Oè÷…5ç…}¾:Øw‡¸s`¬¸öÝñ¸ØÇ–“ûúî 2B™¤)BIP¡(P–þ L>Ÿþ LØþ  Ô”þ Œ9”?haŽSùƒÆvAΠe|:ƒ*7‘œA =wä ZX–„ΠÆRÁYt-L9 oÐÂB4ò-tô“7h¡Î oЄvò-ÌYœ* cŒSd¡ïT™?äTcRTI¹ƒZÆç`¯Tï·;h¡ˆûRCLÑB%°mÒ•ÀN·)™ñ¥v–î”øŒ³ßR`ƒÛ^Jy(v渒Ø‘z2¥À>è…I)°ÃÏ5¥ÀzØQNVJ 5°Q ìHw‘J ‹§Øñs¦ÈúA©ö›#S ì çT;*6§hBsp•ÀNÚ’Ø…uT‡<©Ú‹‘>¡ög&…ÀA½SB`G]¼-ïLô¡ÈL4)ÚÖ „6 ÌrŸB ­–d6û)9’R(‚”BàÀc’JàÀ+Löóˉ©Žˆ&K!pÀG*…ÀA‹„@¦½ûÝñ3QØQ ü¼%ŽøY N* ›Rœ¨Ñ—2à„gö!bCõ'²»è‹ôåþåêÜË#48K¡Ý¿Ì/ÐùVo|XPl^áŠD†‡KèDð`º„Î/.¡+~àÃ%®’‡Kè†\— ‡“ÄÀëç‚a_‚^R Š$ØcÍ>(™÷œ±IH\h8eÀö ´mty„:—8ç‘mo{½XÐ÷­v»Ä‚¶Q O°àͲš‚Aßñ9陼aF0h›>©ƒ¶é»_:à}¡t¼`PÑc‚Á›@ƒ=öâAûf:ômûáß¡ù.…êG Ô×<[äãÊAÖ ÌÁ6>¼Bícé/vò`£žx°#}±p°Ñ;R<¨’ÁâÁÎÔ<âAû2¾t@_¼^R /opDO$’‰„¶|½Cí§Ý •ù‰Hh«ÊK 4ï–0Ñ  Ɉ-´"B+= /P¡UWŽ$*+ˆðfa6á³:@?$Þ„XáÍHáÍz"ÂÉLT$Â-gR¡½ ÑB"4¢ÐA„îP´"´€"D’“‘oÕ=Â(è DhÅú+@ÐKÛ5‚­ÏG€àÍÜ5"Â{ÒéDh5´A– B/éö ´ð’¡'ôŒ¡Í‹ëní“ý²!ñíe¯/ÐnÕ~É€ñóô|›Ñ´Baô€ƒ[i™Éƒ¾â!xÐf ÀA b ÂÀA zã W Ñ8è1SÈNé8èÉÐÉ€ƒ–^s½¼B­La}á •`VõÀA‹òBöyààn,w´–Ž ´¢ZH ´ ßýŃ›IÕ‰ƒ^Ëðåº3ÓpÐ~©€¾“Gæ¤ÀÁÝ›ªZKcRÚùmñD¦c° …Å™³r PpxÝï¢èÀÎ*P@Aï@ ô„®Ø8/HÐJè…fVX ¾|B½ôEŒ(8¬RCZ1¼wp`gu) à°Òó‡ÕŠ “(h%4âì L§|ÆaÍD à°*u; V¶`(8¬¦Âuj€Ã¾4±¤“­ˆZÜR° ÷ ÃXp¹Ù*8Ðò†ä,8Jc&hÎJ¦ †Oa ! Z˜è0XpXúÖvª€£ès –ø/Ö“`Áa•à\Êð@KQ÷bA¶  þI Ð |Z¢Cà°t˜á<ÉØÀ c]>Ÿ²y’à(ÌñIô«ƒ¿gà°„ë”ýZ‚à@‚£°|IÐs ‡CeF¢ IЪ±¸ ˆGYò$ –lø _^{ù„zÐÜ)>CD zÂãömW_Î@Áa‰cRŠ\ã8¼†W´m! ¦ |Â~ùÄ Ì'$ø\àKfpà}Óû4HÐãËK´',(ޱÜògl “]¦KèhwÀà°$¹»ôÔÏW 08lgÖ-ˆØ@ËgxÈØÀ{FÁàF1 ¤7û‘ï­"Q9†º¥O­• ¿ªÇ™¸í£S•¾;ìç{ûrYj8Ó¡}œâoGK¦Ck£Žð÷ÀPj8†b[•-9T·$Ü÷>¦Í†c(¶åPÙr eßG†Kz'6œC¡íJ-ÿê|o–BsÙ þ.ß[Y¿˜-¾Õ3‰Ûgæ¶çŸ{}—ðmç¸èpþÓÜî—ò}óH,x@(ùÖ7Ï¥ ßgŽs¤rÃ@g*7Ž”½8Ô+-ÇÊTnëH妱ÔKciá8V¦rãXG*7¥^ëL Ç÷ S¹a¬3•›^ZõâXÿL·z[dW¿Iø6~/áÛ—ß&|û^_¾ýV¿Ï„oß§|'|ûÇ«ãw«Ð×Åð—ß^ÐÎN`YýåÏçM«Fú–nò÷ó¦-åM{e5;þùŸ¿IpÆÌiíúŸÈœö÷o¾ô/äU›÷79Ô¦F|þ9Ô¬8s¨=_r¨=mÿCÿú·oÚ”C­þ~µº£ÌcüZZ‘ÃäýÛkß{Åû7Ý6 îës£Ü`ó +Z|wÓ¬ ô=`'ÞRKøúXÂŽá-–%–QßI5Û G¶@Ø»šo~‘àÌw3­DæØHgV½eΟ´ŒÖ8»­#,£%Îu÷ðÖ´ 8WTwq[©;~4+ÂÅàn?•¥ä_0ú²Ô.ã/†FhÙr׌ ¼Ú†»æ ¤y¾zF‚øÍðÌÕpЈ'/ 15KìN§û8ÓMç `m³4ŶR·Í4K=0“²„Ñá|i¯Ye¤?~K9|Ã)Â? ÍR‡ÿÅA~ÏÛËd\¨êÓ,…ïciüèu2,i­.$ã O²VïªÝCF«¶6ËÇíçnƶŠЭ]LÆù¾yÑP(¾#˜‹ ¹ZkÌÅ…Üf)6Â1ËZ°µ5Þ®6akkØï7+mSù7¹Ý°µµ…Ç¢íöRíZ/°µu8†=;cØÚ:Ê‹´^á}Ñ^ð´Àû¢Ã‘±õ[Û@n«Ö{ØÚRE4Ûí¸xÀ:ØžVÈv㎭û3qx_LÈê­ßð¾H(ÖúnàC˜ó³u‡­Í~V?׸à}±P\ëÙbÂûb¡èÌÓï‹…Š£î°¶Yq¡8ùöRJÃd;o°’QflóŠ$>®•ŒºíLf‰nÅ),——L–ƶK@÷Ú]Ê–Ôhˆ Þâ‘}Ÿ«%YŸÈóÛ­p”Óûj±•êV8ªÛ™ m÷IÇE5±w¯Ü5¬`JLÛêF™±Íªú Эn”Û¼’ÙŠ_á†ÏðßÍJS˜­Íl–þAìöu.~¦†Ün_gO¿Q²¬Û×ùy†Õ¸ˆÇÑJG=ïßP“n¥£šjw^ÎíþªÃô˸âíùÆEOån¥£¦åÅ.ˆîèÓ+wyÈ¿Ý,Ní?îŒÄÞ-¶³ÅO`ßfK¼¨ßMû6ÛÒíX|Ööm®vâ«ðRŒSwôéqêÛK²>}à ÓgøHøkàÍŠ$m^ä­GËåµ?½Å¿ÝÊFÙÒmG/Ý5¬lüüV4ê¶–Š›nE£lå®L…f ›cƒ?o_ñ@ Û™ÇÛNÊïÞÿLµ7ö/è†ï“¼0™¥^X² ŒÏsb reˆ™óù¸glÀñ†ˆ4Nì„7R¢ o艉7òŸ&ZŸ@ÀÀé9„žý,Zˆ7‚ÅÖ; r ;›Æ^—øˆ‹­%8•˜¼K\ôZKl;ÈÎÄ? ô.˜“á×(iL ´†¸ä@£æ@ÇÍèk$â2šCèAGb•Á×ógpXeì5¼ÌE Ð*pN¨8~Q µà(R UšŽ‘I¹NE^1è„À‚"Ü e…K%à Ô'>€@,¨‚œXF|Î ¶N Qg ®„@¦M,H{hîõÁ]„À‚ Ð ªç%ZYÑ7^ð]N¼¢À;ð‚:œ xAhK¼à°— x‘„Ä€tغjíG‘mÞ>d@sêŠ÷E X_hF À&ÐÓ\½Ðb çØŠË»ásu sc‰ÍÚ¿7 Ðóm¿ °Þ5 yyªâ¡&šù¬92 W¼†@·Æ6‚ÝÃ<Žº™†‹†< ;‹a•LÃë5 ÐZæ‹ïFà ðfs µs=¹wŒ<ˆ _„€Ö7™èÜqr àM‘Yx³”$0üÝ7 º#?Öøq  ×UôiÝгNt'ä°X‚Ã8¨pÂt¬`@s·«¹™‰+ܾI€n.ŠÍÐÙAoÜïòˆýw¨ºEiÄ0 î÷Ù2ÖØð¿Ÿ$9á?‘¯šè'2ú¹ÖIît, 4[ÕDÀ0oùœ€€nºj|•y¸àPHô–ØÂzCƒFæáŠq'|ïŸz‹–ß{Ú1H€îO[K`´—•p¾_¨ÃLô.þ 'zŸ80æœï™>‹èÎyÁµ@@·µÅ¹'³p! ЧãÞp½·«ù‘ü烬ýÔq1@wJÜ"@7duü ×û;T} 7¸]œèɪ„€îǸ='Sp!·+0Ry$Þð¼7ï…h t Y;Ð-% ëb .\ 0æVáxóMôqýu'º“gÌ 詽^è÷sÅÀ þ…¯ði) É©˜ Jð‘³0Ü7ëÀ0núÅ€==X®ÁÛ‚1ˆ$@¿Å;˜0ð'Ð qÁ @w/DŸ ÀÈ`×èÅփ݂=~90͉D@·¬îh tI`c `7®xp@ÞÒN ôw–"º·óºÍ6ô†XÄž™<~_P [7ͻժ + Ð[}Nîì z Œ.Ñi܃ãjb˜ @¿š0&Q5›r=æÿHú´ÝÓùAÅñm[;^‚ í>k°HÐöSíE‚¦(è´–;Ø$hûÈ– A@‚îlÿãA/ht*4C€ íºu‚öMn†A÷£?AÐ5°z|jð8ÐÎzÄåK´ ä$ú†4¤½àÀû¢|*9qâ@O¼dH=ƈ”+¡Šj`åNMj vaR/X`R ¬‹ÚÕÀŠDJ©ÚÎñ­VrªÔ@í¥.žŠr`Jœd1Ê·€)¢†úK fJ=°™R0úK¤gBê¶õŽ£fç‰.ÁJV¸L Û é%åÀ8åÀÁÉð6>äÀ¨öš hæÑ8 ؉ ©ÂÿPQ×:AМ9ƒB¥V¼Á\§ ‚¶/}«£ðŠÁ_Ø ‡!Îû“'lÔÉ^^hEÑ É uÑ’â’×&õ‘o¼/ÂÀ ¥#1P¨0pÎO)p£D‚(@ž 8™Ž 8‘v%A¡*Á[j¡¤À›G¼Qf)APBiJ(_’$xK. .„C$ ÞÈE‘$hæÜ`:’à†n%dêŒA®O´Wâ ‚7y ÷T ‚ñï ‚±=Ap“Ť†K ,ø¢¦¨ÅXZ }ÐS ¬È“Z -bAÛJ„ñGZ`Á^V h™p“‘XÌ?A;*^E‚ ¡w¥I¼‘]Nb ÍÐ)Ä ̓}½PP²Pp×ÚÜb+ܬ .ôX›Ú 3:1Ð4‚‡ˆvP¸+múÄÀÍO¶0ÐJAÄnî;D‚~?ƒ½@‚¦þÆõM=ÝŒ$¸ÜŽH‚V™'0’ µ@wœt½‡@,t©7à(èµzâ’‚šPк„ÄI4Y¾@ûCižÞ!p­"PÐã6‚ó€‚!pH¤¡S,èñ§èaPñP­ P€ipODC‹7–@Á Éûqwíÿƒâƒv½å”-êàÇ‚vi@8  µà   V¢ ™œZ`ˆýqPÐ^Çà¡ Å”œj Ëë1i² O1x ,h^ô¡Wƒ7U ±àfP± ù'„ÖC´–°Å‚&&ÄåÝCõǃ‹zº`ðFþ’¤ÁIS4¸àŸ4¸R:ipö ÚëZÞ4x#Â%ip!#\Ò (¸Y‡$Q0^oàM{Ap-ŠvÁM1X ¨çW ?ò ‚7™I XPm*Að^” ‚Æo\(fš$X¯)IÞ;‰‚²ŠÅ^¢à@½L ‚æjÆŠDAÞ ¡àFª™DAÓ´$ zTÖþ©Óú[¶¿è¯"Ée@h.)Ú¢$%øC«þê€?¬üIÐ#ü13SÂ_ávRôW EHÒ_¡]^ôW.zŒ’þÊEÐ$ýÔ KúCzøÄ¿_bc%ü«ÈøøWaÅIüóÒÕ?Nü³ÒzArÀ¿&ßOâ_+Ô‰ϲŒâßÓ'"þµ eŽø×P©+ñ¯!íaâ_CúŸÄ?YÆ…üü$þ™?vpñ¯ÃÉ%ñ¯· èYJ~œô×7UIh“þ2o%ýõMô7H÷¢¿ :éϾèooÐR+I PLú-Lô7a”ôÇ⢿ÁÍ¢èol*z¤¿IßcÑŸY½£éÏ"iß: …DÆÈÀ?îÿfä\Jú›|óÒß̤¿)ŸRù‚VìÈÓ‘IÖ°WdFŽwQø7åDáòDøùZúãëü»>]AW‹'?é¯ã§Lú#:‰þß^áßó]¥ÿn ,ú»+ŒV¢¿\’þä((ü³5ó­ÚeEâß^ØÂÿ˜²TøgÖÝ€Qy‚”ÁNOÐB!þ?ôþÙ.9žz‚úïË4^ ¹^H\n –*ãÇÁ~f9•$Ý@áß•n i7PlóÓ ´ÂŠœn uÒU”n Üì¦(ê'úõ¨²+òë(}œäמä7h[ùÉœ"òcv£$¿.Ô"ù z©ŠüX±$Éo„s\‚óR$øMÚi~› p~ö_h‚¿I‡ߤ‰@àDzÀ ~sÚÈ}‹»u¡ß‚ëŒÐo]$4¢ßà^ôïû=ïX;A½O°–Øï†a.Ù¹4“ýü6ý@éh›~ …†pù^È¿˜~ ¡R~ ¶×ŒøAÆÀô½P24ý@™ž/ý@/D>¦è{mú^p’èÅ-±ü@/aKGÐڨʴҎ … .?ÐVè ?P/¶y’Ÿ·„êK?P; '‡¨õ©'ùÅÈWp5ïàP-èjî·¬WN'dz‚ZË<…@oÇÁÔ"ï1,ªlX¦a²}[Ã6\’Ç©Fô¹³Ø™ÛîÆÞ,vŸ„iœ6Wã¶»iv ŸêrNƒõ…ºjþNS‚oôq´™¥³Øj7NË,~rHà7-§Ò«ØÙ´ÜÞpœscÊ4q³²> ZXíL}6b­+"²¦'CbL÷1%.¥à>=oê¬8Ï«¡ÚY…çö´SJá>9·® Ÿ…áÖÉåæµ.JÅ=½n„[›•6"Úº¢Ú´„9 þ€þ&ÎZXí ñ׳^¬v†|ö³VD[Ûç:ú4V;»Bíšµ³ÚsÝ:Zˆ¹Æµ8’>‹Þˆþ7®r“Nû@ûÞ'dÚº¢6íæ¸qÝ"¬kZñ'‰ÝÁóÙBÀuCQËùì;bo|¡ŸÏz,àmá ¥Î‚çóUмÁrZá®ôqÇí]ÎôÓ>Ðg!Âißg_Ã2Ìy!âZ÷bVD\7–Ïš µÎrœŽZg IöæQîŒQ¢ÓŠwMøË^1ÌB¹³†d‘ÓŠwÝ8ʧ`µ»6ãÚç92f`1íû|AEaè+Ll>°Ÿ|Õ0±Ý,1W<†1²ÿ«#äº!Vs®Qê »iÕ»&Ü€wŒ¼ 3fàTk+cÆŒƒîpµ÷ê…1ð›*%N¯÷Šš‡q*¯`ŠTQ!Ûx–žÚÑÒ:¼!‹Ldvo3^Ì3šf ÜaÞáw㱆±°Þáã}â¾»Ûf4ćþ—&`ÛŸ¦ø„«3Ê:MwpqHLÒÝZ|T” ò£üÄá†Ç1£ªZeÜ<3·†«sŇÊdµÐøuQbÂ[â5ÛáÁÕ ãŠ÷мcÝX%*õªn×2o²ÒŠ=Zê@µJ,$Ë>Ѿ~÷ƒì*à­í ú²<ˆQ¬2v8«ØοWA”ë[¶eþIåzǦs•ˆ+÷ƒZ kåá0Œ¿ªËjvE˜ëe`™cŒûÀvYf ×ñµŽ0W|ðÁ¬ ~gìóa®x[Dß^’þ1$cÚ›ë' üœ$8Ã*z Ù$Øh9 ¶P"Ä6ì$Á/ äFXˆpµ‘wíÀ@î§;áQCÓð&>0p`#™ˆ¯‰7êJ'ÞHÚ˜xO\0ðFu›Ä@b`àkmRà}8I7² %ÞðœJ ´MKœ‰h›â€5PàM®I ,_(Ñ(¢@cÛØô“½cà%(pm1(бEPàÚ&D‹U¢@OªG½nã =„ÀñC¬Šøž1P #³Ÿ‡hë\)P…ëEÊ©& tŠ.ZŸ…–r• 2N'>-q.a`¡ý@X¢ìe‚`@.,9Äy‘’ r&¾CâÀŸ™ä@‚79°ŒXÌ’ Ê&–È¿“XIŒXP]31° H09°Ü<ŠXë.9~iÉFð?N ´†èB ¼Æšh.LÁfÀ@º$^ˆqI ¼ É%^¡˜}ˆæ%çŸdb óÕ&^·‘xõÃK ¼ É%^‹¬F ¼P3)ÐÎíãˆÍï#`xaIO ´¬÷чh‹^ŒC ¼nr!)ðBJ7aà…d‰7\ÂÀŠ ¦Ä@ÖjO ¼àx¡ub “Ÿ&V!'1°òVT†K ¬ð®J ¬|R„•;b S›$2ýIb`…»zb`x¨œX‘~"1°¢z«0°âë•X tÂ@!»0Þ-JP1fûäÀŠW69°Â—XF“XCO ¬È–X‘\'1P9V˜«+Êg%Vˆ@°.¼@Ðl ?N¬7QŒ Xá§ X‘wãA>£ÁŠE(A°"'Y‚ ùêøœ‚•O-A°bŸx€`!ö  y hö—è#$J+"Òz€ ¢Šä˜ H“L’ Ž ÂQë Áû©ƒá%v`ÅC‘$dJ$„$^¸É ‚5,Oâ@šV’6‰¨ëx` Ê¿ØPÎ:1^wÂ~` öš‰æò¸&$:r`ŸÈÜ“É ÞâÀ—ºäÀF› P°!%h¢`CéƒDA“£Q°Á­C,(»ƒX°!ßM²`CZñƒ‘0è`AD—,‡ÈƒÄ|°`< "¦ì`ADÑ,÷½Qnñ€Á† ƒ—?h_܃;ÙO4ØYÁ\4Á "º`°#Íóƒør& vØsGŽ8Xp“É‚¹oÿDÞ´m>ipÃ!8i©ˆ“74 —ïyÁàM?DÁ 6˜dÁÜM‚éÁhƒ7=­ï ½búK¼/JcÄAÏyZ"pðf¨pP«²pPf^á ~ØÅJ<øÅ„ƒžÒ8Zs0W°^g æ¾ Úv¹Iƒ0‡4ˆt·IƒW¤ ‡*?Mª‚”áR¼°©JUI!U°„»Å¡ ò1HŒ`ô‘–á AÂAÒà&BŠÜzÐ Ê!4ØÉ™o ’©¹¤('—C\`ÜÀ3EAÄÆª Tµ´’ù,¢`‰–C ™(EÁ‹l'QO tA¼ä‡.ˆùÀÁM‰8Ø#·ð! nü–© ÂŒzè‚‹ÃHDíŒ'æº GÉ‚°L²`˜ëU÷Jª Õ„ÁJf ’µRT˃qóN a°ò¢`ðÆ,Q¤ã€Al8ÜTƒ¿å) Æ08 `‚AÆ8`™7D˜þAƒdœ4Ø Ø ;»'[ă»Mì•" y°s©(’Ÿ£@mäÁŽä+/Y0¦.ìü¥.HrJܤHñàþ‘5ðÀAZ1o‚p‰~^8­ðÀAô¡4Ø¡§48(9J„KÒƒH+và R 8HSRâ X*iµ¿DJùîè#Œm÷Aƒ->Ó/ ˜ÖøÀ8(6VèsÂÁz‰ƒÖòãÄA5PÄ70ip‹i ÁAƒ-vé;_Òà~Ñ¿›<í@@÷'x1 7„É€Î|É€›},¡¸”ˆZ.rQàgQ EÒÄA¤À«‘ E‘z÷€ÀN–$^ºšcó)¼Pí4!Ðüã‚©>Ù ×M½xÝ_\Cƒõr ÅÈé r”kè¾¥k(晞¡ßÓ34î_z†Ò3Pž¡œfj‚“êž4A$MpÅîêБûùбg<4AÔa>4AÔ¾<4A„1š V—C„ÁìÐIì§&xŸšà¢K§DAQžDA$9;H™ó_¢`¨p"Á¢‹! Ê•U$X.žK¢`‡/kŠ‚:œDÁF/N‰‚|’S¤¹@ª ź”a9?dAØÉYˆž²àÆÔ“‘yï$Áý&Á ÙÚ]Ž1‰‚¬Âœ(x!Õ]¢ E…°I¼p9) ¢ìç! "Ú>Q°ÀÏ%QМ“㚥 J®# ÚÔƒÏR\o¼øñO¤1ø÷”A9‘ éOx(ƒ¿T?Di8¤ÁIwPIƒ}RD|k¢`AVÜDÁ‚`¢ w½¤Á˜ú) Æ^<¥ÁI8<¤ÁàG*ƒääT(x-Øà…‚ÌÇÿR?DŸ–0Œ i‘J´jáoQ·x)ƒ±E ^ 8”ÁÂë ¢t*ƒÈxx°`H~AdOJ¤º~€ 5—AxY§,HoÚ”‘›ã+–,ˆ:ž‡,ÈÇD XÞ¾¡¨ÙpH‚0=$AÚRÄîÐé*–š ŒZI…þ—+/M¢ œã D–áC¤ˆ”¢ B%î¯S¼© ŽOUù½UÞª© ¢.}r`¡DŸªàøÁÊ@ È¢ ‚5 œ„+Y,A¡>A3:„âG¬òô$2ÿk‚`…1>A°¢>P‚`¥{€@°"r%A°Ê” X‘‹%AвªÒ/Až@°ÒóôÁúö­ðÊ=uÁOÿPJÿ) ¢Þ! ~A'úÂà›[=dAä]8dAxP²`ƒ¾HÄÀ›}èJÓSº‡þ¿Ü½Ï²î8®å7÷SœaÝAoóH‘/àžt„‘à¸áð,Û®I¿¿`­êÛçfž,—#®«&u6’¢D}”ÄòÝ‘È<…ä@$ŸH7áÉä’Yœ² ¹>eA¸Û“;våHì )vÔ®Kì(R– h›èž;54`GöO‚ ½ b“ù$AV>I0>`‰i{€ *¿tÁ8‘dAT?8tÁ+Ôñî=Hp~#Á‰3‰¯ë3HTJf ƒ™»¿\Dí Bc¯W˜èH®3Lt½…ÁEýáLŒ Ë3ap$ b·²#LtF Á):±T¤(6Œ;"Eñ6:"E#A%EwÔjÉ8Ñ]‰–ŒÝ¨ŒÝR!ãDÔ”.È„­LP2]ykɄ̵J&Üï8Ñ„‘T±i`*ƒ¥)9»³â ŸÒ ÷A;¤A„$¼¤Á€9IƒØ2¥A ²) n†sJÄâ'ÕÁŠˆæT%BI¬ØcäP»01ÕÁ˜‚§:ØuêÕÁÚ:JE,´`Ƀ•É•’¹wÓ‘/x3.Tò ² …ŒþJ(l•ý [áå […&(lŒ½6Ô¢J(´NE(l7™PHù&¡°…Ã:™°]¤;2a£“DLØP1™° )˜…\ íóঔÁû &©*zTê ¶•>ÔÁE”“:uïqPKDüá!Ràöx5ƒÌw#öÂÜ?iƒ€lM³x!5ñ`GʨxÐq&ò â¦Äƒ¸Â`o4Â`—zG챤„A)h‚ÁÞ™QHìP_Íý;Þ. ƒ½Põ# vTt v©*]xé‚˵™3• =ð) r“Âà`šŸ„A”å;„ÁÉÄ? ƒLÓLa{¯ c´2]a´Rñí:Ò'C5•.ÈÀÌL¤:’é‚ÔT2]È-eI£© RE;Óo$fº`Äé¥28aR™R›ÊàdVß‘/`v(ƒ€Q­ê% Æb6…ÁÁU ƒüÍ! Ɔ‡.ˆåÑ‘/Èåeæ ÞÈJLaðÆ„LaðæQ ›ÂàMñP ½%§0ø™0H¯Ë© "ù‚@ÄÌŒ×B*ƒôW¤2ˆ:r¯|A ¢”Áý&ª A…‰b_œC¼xª#LtÂBeÖCä­He°} eÔô&G¥2xQ+<ÂDã ò`“¢Gl”uŃm±cð ¿/Œú <È8È îÄÁ7 6È F-„A»”ÑImQ0¨ìÁ#W°Ëì/”‚{Š‚Ð܃•º?DAÆ@$ v¦þ›Êû0xƒÁ‹j£`üš0×BäÖ3 "´=I°aCëƒQoíE‚ÁZ"A> âõ(ì•ÁžDÁù$QÐ&þ;aïµdÁŽ{É‚‚W² cw“;’…‚¶îþ@Á‰!P:Q°¢háQKí¾;Í¢”Ï~´c…ÂgQ´FyT6úÙa¿^KmYQé¾ó2eÇhËŠFiɲcËê÷=¢+ή`;º’%»ÚV¤9>lŽ®hË®Òrte_G¦Pz#ή`;º’åŸ]WÍóÙìŸuÕú/ÔJ3ðéwÿV×ê?l{¿í_h{YÉÃþªÁöYˆëWʱ}›à÷m;7åüþíg³ÙVùgör”Y‹nÎ*kì'¡£WÁ6ö”EÖÐÓQcM=©{:˵±§,±†žŽ kêIØÓY¬ÏjX‹žÎújzÄÕ=ý#EØîaÎ^{¾ÿuаýù«ô·ooÅŸ½9ûÙœý|™þtÖ~ïé/a»gûÿ¶ÿëUæŸ×_³FßꯙñÿÒ¿ªþ5õ¯o•ØÌXô¯ì;*±= àŽJlfü¬Äf¶ÿ¡ýûOl¬ÄÖöWb{ž*æp›*ÀÇ )ïÎy·= Yñîd»ï‰nTFx ­a›UD‹…h zUodJ_QÇÒ,ž —®wc±ŽœxÿÞÜ®²!'~E›Ž` ;A´¹¬±Bp[ðÑDNüˆS k,:êmOém4¹«aµÛÜ_½Ö„?7ŽØˆÕX\Å`ã¯HšKE÷‚õ¶Zý«Áͧo«({¡\¸Ó­¢¬'pûJÙ Èß^¨‘ôܼðÊÝáf1KlCW ¾ŽTûÛjôn¤ãÇ µzϵæÌ°¬"o ´;–U§®¨4w…%”Z· 7ôpÊÝ,Züü’á”;-^V¿¿«Œõ…N|H«Ì^Ö¯8䟜î°ÄVV‘ã—»Ã'gwq­ZÂ'ç–Ë-á²u—yŒ ¶†-N¨ûÌ´Š]NÔ&¢P³VÞcÙØå¤±ç±°Ë üSgÝØå%“ž­{弉_r]á•ó€#7ìpÊݱÅËci%œrEåWco¹ÂR¢M ¯œYb ­»WÎ i„WÎ,qîv…WîfÍö‡Ã1ç¥ Â2Ã1ç¡Ma¹'âíÔf ÅÛá’£ÇÐüî%sÞÆçI¯á˜ó6~…½…cÎ4Çø‡jÂ1g–m®pÌ©ÂcqǜǂũF8漸BXb‹x·àä÷„¶‚‡²Äìãù@Öqàô¼K:ÄdA< ÏqåÓÖÕ*Äl#õ°s…¸‚À×uˆ+wàôcÙW‚œÖ5´¼O`º#ÞuÖuOÄÛ¡zä²%hÄÛATzÞuîà+Y£tÜÁá¼Fm¸ƒ[æaûúÅhI¿9#<Ä¡ôø]¾#¸C ËcÙ¸ÛñæZc,Ü!˜}y#àn‡4°Æ=p‡òÏËx ànãA޹‚<—5KGÀÝÆÏ7+ÏQƒ#¶\öu®Œ ‹ƒn8å …e[E¤Ô·eüÐÏJ#Ëvø¼Pi$g«G[óýl›ALD/ºÛpí^¹‚Ðc€W® $êò(Ð&&¬mI¹YÔÄûBdQÆdó] 1Θ{Á3gåRܰá˜+X&mÛ ¢ãT¾Ù¥Â3WÀK»4xæËŒ6ž¹‚¶Û6þº¥é†+sõ†¶mý¼-C·mýÓó+.æžÊšõ×Ķotʼn☠·…Ü]K¸å ´„m{¸uH»¾Lz~¸å ”ƒg%·\™ñYÚµÃ-WÂï¹m㯕W£ß¿\Á2oÛÆ_ ’±{°¶müµ1ì¸yö.ˆDq¦})gÖ_>۾РcðÇî™5MI³qTká—³SùÉ[/Jšuÿc_® gÛÎ_“ènpËd¾oÛùk±BMts‡[δå8õ‚[®¬x‹mû>d”úÛ{Û÷¹"R6ÎÝ+ürQV»7øåÊ ^Û½äÍ"c÷±ìÌ›uõðò†sÛÞ_wÔ=³Û6ÿŠ—÷Æï`›-ž*,ëÂÛìÏc‡«sbÛǹ Ù–g,¤ëšÉ¾"¥:,>¦«Òõ×ÍcÙŠ´«a¹^ߨÅk_ãÆû{ašØÞ_“g6÷À _¶m{-œ+вÊaðj_ç‚Sy/öqFÊ®»B·}›+N?‚}œRYk6^ß;¼¹Bowö¯U`{à¼ßØ ”( o²“|`üwñ^Îÿ!Xâ@D_xÀxÕxî€Èî; À$Ô$@Ôô"ÝKD. B…DÅ̃‘þz j…Èb ‰€#¢sDQ î@ÀØþ À(Cv 6ó>†øn‰Êw&.$¦$rÑDÀ…ŠÁ‰€ ñbÀuÇk?;§&.l»œ h–7Ê"\ÈQM\È.H\~’önL\ ž¸V¨z‰€ ïÌD@n$\\Ç ‰üÉ€&ËøÕˆ­˜^ pq/\4.”TO4é0àB ¹dÀ…¨®d@s&9’W¼¦­É—èBÀ…ä•DÀ…Õ€Ø.<׎°D@ĸˆ­îŒLÛƒu!3¢ÒÑA€ÐD5ƒII€•\&DÑ¢ƒQ±ÿ@À(+“ˆXºƒQú ÀÊ+"Áä @†?¡úI€5\v6,i“‘kx`ô!ükuâôõÿÀ4Iˆ@ýÝÜÀó ¿F´ý¹{æÇA~nÿuIÞMX‚þPêQôçÉ`?øó#‚õf2‚þŽn@Ê2ý¹Ó' ø§¼3ñŸ· ¸ÿ¹c(üg°ÐÛ¼ÐëUúô&Ñ1ðÞ{=ÅíÇÁîƒ äÿ© øÏ7†øqàŸŸ'€øç7\x(‘+ü»ãõDö³õA<¥„??Ä/–ð—®.Ÿ@f‰iEøó•Gà àÏÏå=þ¼çÀÁ€?öü¹+ ðçÛþÜ‹§ü)Rðçýü8Ø/Ç@øón‚®aþù°‚öÿÌ17^øç^Á8ðÏ»ñ‘ÿÜÿÜüó“¿ðï8 ø'' ðÏ㄃íÀ÷4‚ÿ”Œ-þ“—Rüg–¸aä??*8rÃŒCþS‚­øOÛňÿ øO^KñŸû(øçÿ¼I ðωq9À¿£càŸ»Cã(ðŸÜ˜â??Êï(° ÚHhMú ¶‡ºõE€~”uüê® =Šÿ:!Pî5A ;™NP¾*A g9¾8Ðk]E7›úÐ ‚nq"ºoêÇÁFù0ä@„ºè[ÅÄQô™s0@?¢³…ª»! ô*‘Á},> F ôb'oÀ@/k° ô"ôÑèõñ€Y"‚è–à7` vd>0ÐSâ¨Éò]¨!H ôʾqÐbõ®/0q ß¬­‚ð|®–ÉžÞùãÀ@ßç¥z¦iÐäÅâ]¨.* ô€ýS ô­nâ Éø|~—Éž…-Æçªƒ›ñù(û&ô8ÿ€³Êø|8vĪO%´Ä„ýÒ=1øÇÁ~p#‹w…g™è “§Èôaàâ6¼Â@Oo6+Üч1Ð 0Ñ5îèƒ}ʉ6‚p…•* ôLÜ ºÁÚ]ÈÚ b™H ô |q g[ÄålÖîšr _OP_Í}Àbµ»ç(ôTëúfK¡^¨ÝUÁÑÄ@Ÿ’? ôò^q¢›ùÚÈËzzñƒ=ï$˜¯d!çX­“u&B x¾ Ы"G›‹uœ±÷œ PIÈ‚@O‡=u@vz“—èi¬q}›•»:–©¤@Õzz¡é@¯†„mä—‹·ÈzÂvts1aÛb ¢ãÉ:ΘJT¹;‘ Ÿ+ÚìLÚ¾^$è…áê¨ê–hÿÿíçû•óÑ”¨y-!ÐNTG!°16BJàó^W”À†ÍÕS l…¥ÀÆài Y-©Ƥ:XЧN(t+=D[ÃE1°a‹©› “b`C=›Yî.Å@Nvi [‡H l¨a‘b`C °= Y ÅÀºÀþ+5e©ë¡T+v I5°"p:Õ@ìï–b`Ýd=Š:•ÄÀ†ú|¢­S ¬P!R ´÷ò‹Uö ÅÀFÑSb`CwŠ¡¥J ´yó–mH\”­“hC)å€R äÝ)Ú<þqH•b‡¤@žL)°!ƒ*µ@³ÄQÔÒ(S |Ú\AWY°?Å@þº)VÔkI1°Â±˜b`Åæn©V.¬%rF¦h=ǹ(6l>’r`ƒƒ2åÀV¨®Qlظ-åÀŠš<’í÷øqª,ÏŸj`CYÂTuÅ’í¾å@ë?,¹[^Ê ÞÈ”â¦Rä +åÀ†(”[øîR ÔO.5°UBå@–ÓL9ïç”*צhŸàMÊ­÷ù¥hµZ_8èÝþ8Õ@û‚ý Z7àC¨ Ñ©6$@¦Èç9ÕÀ†°‹TùM5°!‘(å@ûÅCý£ØÚ[äj9å@ÍÑ`»HŒÔü{©òãÿ'e×RÜžQü"@|·Œ¬§@¬êÄgáÀÓÿJü×A'É’üW:µBò_Á.Éö­ ¸#ÿÙ›?PŽüÇW €ûŽ$ð°Df\ò_AÞQòã:’ÿX6+ùEŒ’ÿJc”'ù±2)ÒÏ”2 ‹ˆ¥ ¸ñ2JpWʉÔwcÐ)…@î–”¡ È̼¿‚mIÿø~Lü+ôÄÿ £•……ªŽð¯DÁŠÂÒIŒt;¢@è%Ã@qq„òú+ƒñ› E"ýŠÚVG(tŠ#©GèÄÄÊ8ÐH+8â@ïÏ8Лʠâ@oü,z‹Šˆª#¾ú ÅÊúEÕŠƒŽ@PºÌ2á\G è‚[H‘ ÁG (ã2tKd (ñ5AÙâ@÷×›ü,ê%ª¾Ëº¸Jò³Š/¡á)”G%úøa„~µ¼¥@ot(ôÃb<ѯò%ô«•0Hô«ŒóúÕJ­’èWÉ×¢?+?ùÒ½Ÿ°þ¬&d€œè¯b¡šôŸÞA¢4â_ ÿX62ñ¯b‘øgmâTÄ¿ wâ_EREâ–»I(%sÐêô•“øÃ«í€?¢”à¯v’§à{$üÕÎèPÂ_Å6¢ žü„¿Ú*øë`=°wÉKø«Q„?î‘ðgŃÂBø«¨zðWe,ø«Øw-á¯" á¯"ø-áï±Ì7üUHì õ¢`Hú«x?'ýUÔ™Jú«hJôW#Œ á¯6¶à¯6Fþ*Ñ)à¯6ÜÁŸæšà¯r鯢ÂfÒ_DFÒ_E*IÒ_e¸²èÏ,?Nø«ÅKø«7ƒC åHþ¸{aÂ_EýÄ EÖYÒ_…tƒbïÖ¤¿Š 줿Š@è¿PjíõY÷‘ø  BQÿâÅö!GL(ÂôŽ Pî$œA¡‹á Eèð Q5ƒB74Ô ÝUxÈΕº#ƒB÷;%pcá•¡EÀº;óJ²ÉˆP[EL&#B-¿êºgŸ¡Œ­ÈˆPâÆ‚3\8/DF¢PPr¡Pp±g¡àþÐUs:Qp3ïN(¸±Úh‹÷ 1Š…P‰›­¥ø,¡„‚ðõ¥XPŽ8ÅÀÒØ Å@¥¢H ,dU‰Øš6µ@ûa¡¨Õ®´@­[¥–A¡b` ø¤ˆ½ÄR ¤ê--)–ÉÐRŠ%‚wS D~CJ–…aš” ê_J ,CJ–aýR ÔJLR búS ,(^“J £óS ,¨^“J :–ÈÀúÄÀŠP†Ä@FÀJà'V*EäÀʘLq`eN–@°RÃZ)ÿ87A°R¸Vð¤8°bo‡äÀøâœ ȯQ²`¥{E0X©C +ƒ ƒ•@F´ŠÞÁ‹„ÁÊÔ(Á W: ƒµg¹ý@Â`¶ Vx`ëE 0Xé¦ Vf˜ ¹¯AÂ`%³ ëàå+*»& V楊ë¤ØF¬Ì0 Öu½h_GÐ`EÁÓ¤ÁŠ¢ZIƒ•Ñí¢A;õ)V‹C¼KÄ‚%‹+ãÔEƒ•I ¢Áz*¶CˆzRoƉ’ëbÈ'h0ON”Ø%”ö&¬ˆ°J¬$FÑ`%µŸ¿cÞˆ릦G¤~s(ŒS ×pÐÔéhs(‘›J _0âÁV œ¦X?yÑ“Y3ýàAl^{J 6ò uóãÄAÓG¢‰”@lS(R¥¶¯wV ¤òS Ù,µ@HÜo-0:Ò`ƒ›+i°!ø:iP²iКüxiÀ¯”[ÜáC D=ÈC ä"?¥ÀÆ0O° K©' 6dÜ' 6øý¹[Ò <Ø4ÈŠò‡ˆ­t“©÷R z–xñ’%v¦ÞI ìŒ% 6¸ÄS Œx“C ì¡¡~¦7 6”ç:¤ÀëëC DºT*‘Mz²÷R¤¾”BàÅ´; ƒ9 ´©"ÒûP‰¦©L­TÇG`¨‡EÏR‘eu(ˆ’J%0´ÌT™ÊšJà`ª ¤À_7¥ÀAf“¨6’ñ9¤@ì§zH•)‡’'fdJð8RàdH§¤À Wˆ´@|ï-p‚äS D…ÍC $¿¦ØY_IÕÖj©öfÿ¡š=µn+ŸGÃïjq–Mûh”Ge£ŸöëÕÖj±ÒÓç h8Š‘Ñ–¥‹Ò’ÅÈj± ýì †WWa;»¢åèêyÕ̯v†³+ØŽ®d9»ZíÕÑjŸÝ¬öîd}Ô~ûçTY{^Â^ùª²VÇ/Y{®¿\díêãÿm‘µïóúAØùµr^ÿöÓY\#+Û Ÿ¬ ÆŽÎjìéh…®^­Ø—j¨©¯£ˆšúÊVìëlžTEM}eÔÔW¶b_g+>ªª£Æ¾ÎBjzijúúGÊ­m÷kük•[ûówéoß^‹?{uþöÓÙûñ6ýùôýÖÓ_.·VÍ÷ó|¢þ°äš•û?Ví[ɵwi´Fɵù“~ÿþŸ¾ÐÚóZ Úø±fû|!ñ“y fÕ/X‹³íø{"[o•Çr÷/äÌ;ù=–Õ¾XÁm…ż aiÑo³l“°ô–ý¯¯#ùc©H×F9©Çâõ#÷¾‡…c€ªûX8dÔ=–qÑ‚Q´‰„x_Ù>?c@ú{…eµ/æâãŠ9, ŸÇ0‚¦Í²eia1¶ ˈëëV9,Ž™¥#_{ðwèÏèß¡s X>–º¸‘ú^ð÷jLªo¸ØLípîÕr¬Jf¸´Ì‚«ÇW½“‹ÕÐ…%NuÙ&·?27ÿ±Øf¦p¼£çq}!£Ã2û²áãú®Õð :YH¨¯¸\/ä–8ñ°"JðæX6÷@i1©F]_HÕǤê’<…Tl7hÁ©žë‡p€QÙ¿Q94îö…Äw a,¤ÆWüÍ!¬p|×2½–TÊfÙL¨ÇåMÛPãGæî?–†EBZ¬HzXnôÃ!@Æx,ã’%nÎ|Æp¿-ö5 ËŠQÍiÚ »?–]1¤–›cØø%o»ð> “KÇAíþBÊ=‹ÛŠÕÆ —Íçøæ6çÕÍlÎÏûn²Ä˜îU¿PO¿'À‡Xƒßa•-0;½2K´À(†°‚ûX0„]0n«« æZìØû:hUì‡eÍκ„x¥- % †`–øy—eõ³›€žãì»ð.jŠݶ³4ª0äð–yxó‹™üq¢çX#oîç3ý…ü<šûF¦6kEËKÅ1îž®öêFÐ`üÙ'GäÞ…jï`¡M`£Ó‰f1\m‚~! ¿¡Íª_¨à°^í!yß½fÙ_¨#·Æûb­+,••ðwC GØ a¹a±Ý¢dèäcׄ£¬9ö“#Xh³ê"%ã¹|Ök…cŠ—ÄcÙîM+HÔîS«7Ç„žÇOm*%þó3hèb\_Ð5crÖ6‘§ ”Ý—ÆÝ;ºÍà'hö5ËVdgXzY*ˆ×Ók¬„ýùXÌ{ëA›Ž^ þæ.Nû"Âëë³³ &-w¬„LÁQ iÚgÍËko !àW±ÁXà .øª±:,mrP–Ž4mìúX.œèÂß9„ølÔ+‡€yd€Äòq+® !ÖÙ|,;B,$`–X̱ÐÁ3es ±p¬ƒcÀ–Æ¥MŽj¡M…ÐFlMýXíÁ—Ä`õP3c1w´à&fäÈ!`FŽ]h¹q1{󗊯̓Z‹ƒÂ 5Ör{pP“C€´nOæçlG0XØóˆÕÉï1kçÄÕįڗƒÂc_fJö¸Ž;šE•K1ÿî²X& ;õ®± bé{sÄ‚ˆqÅ¥ŽŠGq ($÷Xr ˜€¶%Ø~÷£Š ø{ÅŠhcÇDz GµpÅÃH]9LÛ·‰5GÏž˜–øôVß-çG4<–ëâ¨ðâ²Á1,ŽuT +¶\ k>tœyŽ©Áë!‹¯ŽÓì²8¤XÚÈï“§Ù9€‚6 í]j~µÂÚýæ'úaát ßý~ü;Ñïèý¢²ðA~2šh÷!ðà¾Îe‰¸Ù ÷u®ÐZzp_ &÷¡› äSû.A±ï"7µ]^‰®€YaßÅõ­°QqöñãØ'àö¥%‡0”q’Q#~‘ßõÁ¡vùñ“ä‡líƒüøiHòW‹ü®Pžò»8ED~¨rwßÅ_è'¿Xí¿¬ÐOt.ôCØß~ƒ«I¡ßàÏ$ô¢~ ?A‰~CIöıßàO)öœ6ƒÑi¸ç#ÇÏ€ØopQ/öË6d¿!B#ûñã–ì—–Î.ö|êÄ~ƒ¿”ØoMÄ~(‡/öC8ãÁ~ˆH?à/-„?l´{À_Tl=Øop" þøMø›„ ÁߤCFð‡mRø› ²Ÿ`Á~t‹ýÒ Bô[“0Cô[“OÙÏ, 4°ßaû­ÉÇŽì·&nÄÊ\°äî7ú­É_ŽèÇz‰D¿5…‚@?;,@¿5yËÉ~æ‚0^ÚR/L²ßºù¬’ýÖ^‰ý?\b?b&û×Ã1н#ö[Zû-Ô@Jöc}ÇÄ¿u är oú“GHôwœìdû*  èÏ@±x ý­›«tÒŸYâä5‡@¾âr]ÈÜâ!áÏÚ¼áO¾(Áߺ¹ª9€û VYà vâæ  õkþÖâÚðg>¬04Rñ· XÈNÖ  ð·)–ðgN/P'àÏú……XŸð·9„ð—Gþ²KþÌå@üm:zÁ é9,Ï 6†0œìbpØo-®ÏÉ~kñŽ“ýÖâí"ü­M~ üY›0€›ÖâÒ›ìgî¿7ûÙA ¶ Î4 é•#À'û§7­ÅICö[›Lö³~À`¿µ‰àd?9Å~ µ¢’ýX%4ÙÏ,aúÅ~»¿ ýÖÆÛRèg-€‹Âæ9Ð!°é83ÐomÒ+Ñom:ˆ~kóžÏÁ|£j˜&ù­Íç’äwXæûbD~ˆNMòc½Ò$¿µ‰"¿"ª#5…È/- ¿ì™ä·6ß-"¿ÂÇWäWøóŠü¢ªÀ¯ð¹ø%Á¯ði¾spÓ¬>¿B‚À¯ð³!ð+B8‚_@ü oûÊ!Ào¸8 þZïüò’_áË[äWèËù!$ø ?õ#õ¯WVKøÛžvÂßFø\ÂßRì\Eã­û-Ü€%éÏ|oücÙÇä¿­5$ùowÊ8ä¿Ý¹6!ÿíIï1ù¹$ÿm-ÓÈò~Yù1pO=ä¿}qDþÛ“hDþ“[Cü'‡„øok Fþ“ Eüwô þÛZWöâàÕþÛ(ÖŸüg–·ò·'àÖ¢íÊ,€[Ž`£M“£h½¥¿¼À=‰CŽ¢û-ýåyq ÷ €;EGÀSÞM ·ÛIÜZÐånr›£À­Å4ð° ¹‰p*ð_þÜä¿üáÆÇÆ1ØiK7%ÿå©É[j+ù/où/ð™CÀA`§=…ˆ`§lúËŸ‰ô—c úÛRuïE¼cqƒIùC‘þP×5éïèô·…wŽà~Ó_vCÙLO;á/ï•”¿IßBП n sf}ÀÊàé‘ò§aKùãÕIøÓÝ“ð§9²rÄÊåBªfyU3a%„?½$ü顔𧙶!  …3 JÊŸw)z%Hù£W:•?ÝÀcÀ¨vŽKZ)œTþ0aSø“;WÚ/&µ?¹¤K*g|·¤ö'·°´¿›`$í/û¡ö'ÇuÍ!`Pµ¾~:jœG©ýaÖ¤ôÇß ¥¿ùMúCíCúË£¨œñå˜ÒßäZZÒŸn¨¤?þN)ýñ‰¢ôÇ·¥¿)´£nÆy•Úçgjº^iSh—#·c8…3ÝPiS(GíoÜ(ýé†vCê9„å/›P6ÓÕIù“F!åOwBÊßL-P#xÃ_žJÊߤ—AÊŸn¨”¿)‘¥cÊ›þò_9ˆ5Wªfx¥üñKÊŸ†)åOSdcøPþ4ÕFÊfóMy=Rþ²çq½žJ)’©¤ü]”Æ1´IÙl¾ùosŔҟ„4Iº;óÛæ1XR6Ûߤ?üz“µÓñÖ¢4ÈKúã19ÈR‡ôJ;”?°]*ÔçRùCx¡üQçË!`ÖÊ©1•?¼T€Œ^KD¹òG"a.é Ï忇ò—mZ®‡`Iå:_*„·¡5€ŒP$rñHÌ^wù˜~@>Ïâ?5Ù9œx·]*˜YRKí`¾b.˜óU.}Å|•ë0_åÒGÌ×û%æktË‹ù%41_ã™Ä|1mb>†Î$ó5 fb¾H;øäk߯a­âËCH|v!_æã:5b©qm)äË6D¾&#ò5‘¯ÑwßsŒå°®òåßD¾Æ5¡¯ ©ˆ|êõÊPÌ`¥&äSÏB¾†…­ˆ¯q¹)âËnH|äõ1_^q©%߉HEâS/">]Ë8TËÐB\Ês‘øã?I|y‰÷a|Œ`|€‡ˆ÷txOCïe7ä½l“@Ǥ%Kšâ=5!îɰßsêÎËÇÕÞÇõ¿=Õ‰`/›ö*ezi}‹<%­oQî—ÖGö艗“´¾E¸“ØGvz~ˆ} U]ªŠ7Æ:BUÃ@¡lÓú6åUi}›þi}[B^Žð$±o“{%ö–Í11D“qžˆý>â<Ë[ì‹ÏÁï'î)ÀU¸Wnd¥B]¸W®,Ü+tÞ ÷èóLÜËHÔŒUÅÇ_¸W€ ô$q‘÷ µˆ#ÖŽñ#Ö³ ßŒõd?Ä¥"J$.e?ä½*‘¼W;)Þ«Të¬ú⽪ØÏÆطܧ Ø¾*)À§hU_åâêˆõ„Æ&àkÔ`ŽXO(uG¬'µ;ŸŽ:b=qGëÉ0MnZÞßzßn Û$ð)ºVÀÇ}? |£l9¶!.5!¯q øÑz{–ñuzàE|²¯Syò)êUÈ×ÈIâë¼y"¾NxñÑûÈ×¹òuIuD¾þ-سS òuN­+‡@Läºà’¸Ä|ŸD¾.i‘ÈÇ0ªD¾ÎÇùödøgŽa ßEAWÈwñ …|ŠŸò]ŸŠß¾¸Ú?Ýf°gùì‰ù'â Ì`ÏþA|z¤€q6g¬'ù#Ö“Â!iip(Öc:c=qjßøTü°/×Á{Cè–°D 0Šš€Oѳðáç½sxÊîá-N¨>´Hà#f¤çÅØOñă÷ I¼GKâÒ7Ü£J˜¸×?='ßç+GÀÀN«2°“¸G…0qåé‰{wð|ï}zаOÜ‹lÛ_.žöŠõ\ïPÏKÌ–‘’Èà@¨'Cé© =Ez*˜N¡žœêë©2{*KÁžŠÙR°§œÞ ö”ãYÁžÒ쉲ÔG°çÍõ ¢=oFž2ØóVÄèRxI•CXâ³¢ðJ{Œ•\ÊÖ« hoò³U$úa°ç ’üJüIì+_g ç.Ê6¼¹<ÃßKq”I}ER©¸¹r òF䫟 ~¶ÞøPù„±ów˜'wÐ|1UG2ßz1_gd«˜) É|ŠAóÑŸ—ÌÇÏÈKåCŽ@Á¬b¾KìHæãW"¡/H }ü&úøfLêã‹ú”ùhO¨Sùà98T¾ë›Ê‘ìTù`!öÝÌ8÷ݼ¥‡Î‡GIàwS™ùÝʻ㔓(òcH{’ßú¦ó-é…D¿4 }ïϽ‰¼þ-æ¤F¶Õ5²ý}¾¡D¼RâïÊ¿7·¼Ã½“Ì·9=Á}*ý-ðóú‚/ð;Û U –ü¼â ÚÄTƒPà§ò?/åMËæ^ÌÄ+ûÕàç-Z~^BŽA!ÀÏKB hòž~§åFæ<{€ßbðh`SöÓðyõùÖa¨8d½ Ï+&Ä:ê\\–^?cU}^Cñ•àçœ:É7 |%øi@AŸï7H Ü1¨ÁNŽ`pÉZ+Š*öƒùü¿ãˆ`>oñù¬Í›ù¬ å:`puRso‘OåÁÅ|^ =óYŠoÁ|ny1Ÿyã±f7#8;z%™/Y ¬¦À|~fP`0Ÿ×DG›`>ÿõ_1ž*).æóúë8*€É«IB4 æósð‚ù¼8ÚóY¬Ž;Ç@ÁŽcP¸1˜ÏÞóäéwˆÌç#G›€>Ö[óy!ò—ÊçÝ É.xÉ«T†!pÉË­¿T>?,|f9B<ýÕö">/›^ÿæ/àóuö ø¼B;ÚðùÝÄ™øüTà§Á #¨ÌP&ðùÙ_ŸÞD?|~#€€,J àó3ᘣK9†ÍˆÏ+²¿4>³”ñù¿ÒûŽ«™ƒÍfŽþ Ÿ•%Ĺ€|~¿€xWƒÙäóRï/O¥B…|Ö†jâFR~HÈ|~Ô‹ùüó£óyuú—Èçïô“cÀ}óîVáRÌçwýåémÐ ÆP`ºr €]@ß1—}**/êóßó•Þwü >¿0Æ`3mnÌ¥zPŸÊ³Šú¼4,e¿cR *¨Ï‹‡¿T>·ò8ÍH`Ÿ?gŸUÒÚ(#‹G=XwYÕZèù]-^UÒÞò¨£JÚOû UÒšŽžÇ h8 ‰ÁvT’å¨GÖ­6ßutEÃÙlGW²œ]YgÁ5^]…í슖£««Q!àl\:fW°]ÉòO¯–Önÿ–ÿ«UKû6¿Ûhù¨·ùûl.G¾˜kÑÏQ ½ê ¡§£ºzµb_Y}uÐØW¶b_g+ö•uÐØ×Y}e+öu¶â#›uÐÐ׫Zõl…¾þ‘jiÏŠoDñ÷¡jiúNýíÛëñg¯Ðß~:{?Þª?Ÿ¾ßzúëÕÒZlÕýÿ«jiYmþ¬nÚßÿTKk£^ª„†GŒ¹ãñÙìÈ z|x'Ó®ña•.ÓX´1 ¤á$,ª6`¹Uq+^m,UÜ‚a«àV`~›E·‚‰Ú¬scíÓfË‚[=,i„øóBža,±ž·„ nÝètúK/6Ý¥м—2§pm¼ü¦k“×Oå¾ÝeÈ]ºÃR/iãqóîÖ•K#º{Sꎊ=,Jü12ŧ™JÐ oØcQ‚NÄE<Ÿ×E¹÷Á=Êp‘¢Ÿ­ iarš¶…lìwúXšb0bAßVW fÈóI§ÓW¸ÄÔ@¯¶f‘ ßù…ñ¼òݦ!w´µnU׉ŸníIm2šì2$âÅåíz) 'N¾9ì?b ¹F¯¡ÍU)Måµ=ŠD`7GÐq«îQd°l ½ÌpÅVz{ž‚›Žà†‹Ëà^Ý£kºïä‰~âŠ}#›ø¹+,ýÚWcŠ{ge )~·Å0ºå±lé èe.Z*,7q,ÔךîÕÚƒŠ,›#ˆ=JpaÒm;/XðKnî]7š}“!£à»cßäö>ÑØœh¸Á;‡€Y¿ï›–«Y“ƒÂܳͼ&~¿9—t†CíTQ*,ÂÀ¯p•I$Ü„W‰½[G̡˾Ç0 4›*J|%Ÿõþ¢â_è«ðú³ ¯Ÿ%®²-±N¾l#/H]ñµºl'¯—ªsUß›äJ9é²¼0¤ýp-r ñL^ö=†åF›¹8*œú¾) ÅËóªkrPè%Gßä«q3â2 šðïÖ°´Fe(Ö<—íäõò_¶•”¡˜Ô×óMÆã?ð·F°`™‹z×Ë Q2{Y“ƒª¸š=8¨øÐ×㛓Åõõæ@Ï1À7÷‹ÒNÜ»ï7ïÃ| x—À7Ðbd¡­XÅ øb;”ïUt«>4Ðâ=.Yø8uø8¹ø¸ôMàâ·ŽEõE|në$>JŠI|BJ"åÂD¾©£’XŽJd]€·¢ËT!ßMòÝÄK!ßM²¹I­Ø,©õÂ1 ¦$[RŸ >‹úTÞGÔ·¸|õ-æO‰ú…PQŸÅè€L†^몱\`õ)2 ÔgX÷Ô·(3ŠúŽ6@&³àú€L*d#ê[ ïYaßZœÆÄ>Úö­E÷±OÕn„}k ê€}ÖhèØgqSü{sT÷û, 9„ê3 Ĥ 4¢>•Õõ)£@Ôg^X.Eßã³Nê[›ËRŸ| >¿ôY,,€¾usÅAè[Î}*‡#è3 È Ð§>‚>³Ç}G?9„ˆDômMf‰aõ©ÎލOY?¹c~ª\#ð;Úü˜K!î[7W侕„î[Étà>ëøÍ}*€îSppßÚ"EpŸªõˆûTŠGÜ·6I çè‹#`QrŸYÐÀOÞ,‘Ÿr?H~YzGä·°-;ÈÏ nä^`¾‚ü¼hòË2@$¿,vNò;Û]±7žÐÏ-ªâ¹æbæ–¼`¿³ç5åXAŒ›½Ä1`?xñ~Y£Hà·n®µ~ÇÅü²ð:Á/KüΞsp´ü¼ úYS™•°ì¡Àͤ“Ÿjü²<ÁÏ öF n€_ÖL"ø)B”àw4¿HxrgŽï€ßq}›¨|€ûNKe0jÜ<€_fü²"=Á/¯àç1¬8hl –¹8&¼¯@~y½wàÂÕ#ˆðKç/ÁÏo 0®½/à—¹L$?ï… §!°—Âx¡ßÙÏ­B[pýrP ¿£É>†ðB?·ÚšŠTñ¨Î‚SÀ±+½àqÁ@¿LÐ"úi» ’Ÿ7 í2[ìeÉ>_à—7‚à—G‘ür$¿,väwör1Êÿ}È‹¡ñáÅ'ú¹% Ç‚BJMödU.}|Ÿn ¹/o&¹ï´póÅ}yëÈ}g›©í&îø7àçmâVÕc`- a%Èï´4í7±@_]ûMLÚ¥-3xÔ(?Ž3É/óóH~™iGò;¯o)ñF?[{fÄwP*޳çp®žc!¥þz…4Áßv¯[ÂßæþE€?f‰ý6Ë‹ý6K!‹ý̃êÉ~ÖMNªµ/ô3 p è·…D?ÕÚú)–ègÇÄŸdˆ V ½_h1U§™J0_ü¶ØuæØs As£V¦£H~›Þ‘߯6I~›ÎŠ}ô!¥ÞÇ›Rï;,ûë=ré}ynê}yÅÔû˜bz߀&»Ž!µ¨•© Õ>VÐKµOc‚Ú§ë]9‚òæ>›E8†R™~l©}ü¹%ö©‰Ô> [jŸfÚÎàäRûÒB¥ìPRíãÉ!öå©)ö òï>FšÌð¨ûˆk)öÑB±OîI‰}Ùæs)ö !]Š}XJìoìÓ§ØÇQ¥ØwqÑT¾¡cWQ,Ó¹%ö ®n%öñ5‘b_ö|ŒáÍ}Ú€#Õ¾<×½Þ½PíÓ¨$øéj$ø»Ž@ÿ£Ú§ÓHí»„ŠTût#¤ö}H}ºúv\ýKêÓÕCê»(’út„¤>µ‘Ô–ãµóqK¡¹q)ôéÚ%ôéR¤ôåQà½ãb¨ô1-¼ÇKÙóu!„=RIOý‘ôòœ"½—ÀwüTÂïÂr3/"âi”B<.ï’ñ4Ê} !úÙ9„õÁxº0ïƒj$âébˆxùnÙÇbP‚ †SrÐŽÀv•93r3l³|}´™*µÎ^ÈvhÀ˯Šëäå×Ï(ÎÃ’A8‘À.-;õ|kø›È~‰EÙ ±(Ûd '-È Ì89NÇÞ’Þa!¥…h§s íÒ2ÞcXÇhÉ1 _‚Q¶!¥eg=-pÙNwPl§ž÷·1ˆíê7¶ÓÝÛåQwÇß[£‚åÛö·1îªðŠ`TX„»lC¸ã,H¸Ë6Cýw‡e¿+Â]U<(á.[,y²ðQ.߯P1@F«×û·J¸Ë6„»´\õcTõÛê·1î@ˆ÷ë±K²Ëö|ÿPIviÑâOÒþ$ñÝ”X‡dº"ˆ#Ö•oX—\züH„?tÌHsoõ޾/V‡?ÉBoÅNß^QšÇí»ñ%KvÓ(¤ÕÁé.|ãn¼§V· ‘à²Mjuë›VÇ6©Õ±Ÿ”ºxTJ]<*µ:•ZÛìw¿ã,©uÝo¹îh“rÝú&×Ýßä:¶9ÆðM®ãQ)v±MÊu<{Êu7਼Ïtèuë›^wÓëØ&Õ®û›^wàœ®O8G¥åÐëxPÊ]øñÁ—svëC°ãß)Øñ˜ÂýŠÔ;•Š{NÅn}МÆpHvãç¨â$Îé\’ìÐË!ÙÑ’’ÝýŠÖ|Yr¹K ^dµ”ìxTJv¸;‡fGV;ÆÌ:ÆË§â•š¦Ò¡Ù±Ejvl3´bChÂ!ÚñL)zÑrˆ^ ÐTí Àªä CµÃBüT»7Òå)zñˆTíhIÕn} ]À娿›èUÑ+ )Û±Iêv7¨*u; [º[äp«ÝŽmR·#¦nw¡ÍR•¼AXoÝÎ, ªª¦h̦ ,Zº* ¾Îb¹^²+^ èòðÜbEñÜÑÉR Öõæ¹´(77-9‚ë­Ú™å×T»ò]µ[¾÷÷+d³Ÿp§=M3dS¢Ç‘£7>B6*›1›“êÏ‘£w¿…;m!˜1›Ü/c6ɀͥ,>l²Ö6¨Å€MFîœh×!ÀM½(>6`ÚqÐÝ2·J~Q9+ª1Œ„,Á]#W îúgŠžŠ|îX_2ᎻÊ&ÜÑõRíp¦[³ˆr©ÚñÜ;˨Co+¹µÏG–Þ 5#áîæ î¥(¸[ð"€ínæ*Ší¶:áX1%Ùn3=QlÇ6²§¦ b»ù–"Ûy®LZgu)Jr½1)j*ÐÎCÚÃ0 Ó"˜ý7 rA@ƒs3}…‘˜÷b^sÿÖýÎì Ùy~À+ZÓ9^²ç+ O®uÆ«®8ÉåRpú+V3£ÞÉu^E ’Üd]#œù^¬ùóÖô D/ÑΪr A¤rëC´³&  lr쮳£ª®ó:,/®ó+èc°ú#·¹T!ýܨi‚Ü. WKÁÚy˜—hçý¾‚5½¢ Ú É­²ª0Ï,ÎàÙJ¢[0žY¨íãùjî­iý`ñÒn´À‰ºX¯`M{\ë‹õVMÑ-pÏ,@,féUî§Lè[urHà>?ê%ÞyZ¢h–U4Ì!MÏ‹Æýžügˆ˜¯ÈÒ«úµ#KÏÊÀ¼øÏ»€:‡,=³@FC–^e5eéÕ¥<`Q]eš^Å—ÊÒk™·‡·Ê}2•¦×èþQšÞc¹Ï4½Æø(¥éµ‚1K¯)+n åè5fz1E¯e²Rô*JÑk,­=ë÷…~Öf¼SôìI„€ˆ=»¨ýübÞ9zK /Ž€Õö•£×X¥X9zv&ôƒ½ÆmÚ•¤×¦¢D‘¤×‹¢$½v M‘ãfGA#DŽÛsI Izr$é5¦Å(K¯1õ_Yz™ÊÒkz2M¯)%—izm}DkZ¤é=-(¸!O¯+<’‰z]¡¹LԳ˃YnMÑÚLÔkŠèf¢^ÛŠE¢Þ³àFõºâ_wŽÓ–™zMõ‘©÷ô1—™zåbpfá¨pnfêõ&ĬŸúY ‹ÈtëúÊ2S¯39R™zßo¥ê=ý”wª^gÁr¤ê=3ÈÓóÜú•™y‘çö´@¾sõ:‹e(W¯_Ê䦲÷8‚‹ÙfÌÕë¬> \½Ž©¥T=+= ¬Cª^çó¢T½ÎbÕHÕ{þî ÐÔö ý¬ßùB¿Õï/„T½®4G¦êõÁ«ã”¬T½ÎÒäJÕëØÈI™zÛt+S/ÉL½ÎÇ‘©×—49`I!D¦ÞU”ï‡L½«HÿC¦^gz‹2õ:3b”©×™@¤L½Îª ÊÔë¨UyÖ:³¢XYúé»iåfU^çwµxÕ:{7Ê£ŽZg?9ì/Ô:Ï7òU Œ†³lG½ YŽªb#æ®`xu¶³+ZŽ®æÃ°Yë¿§áì ¶£+YþéÊFó4ôW²?( ftÛ·:PßüAݲJbßfϵk͹óÛÏfÊÜG»(Ö½œ¬›W}0ôs´AGïZcè鍿=ÕÁØS¶aO¯Jcè鍿=µÁØS¶aO¯:cxŽÚ`ÖÓ«~Ÿlƒžþ¡úa×ZÌ¿Pù°?}Mýöíó³·Òo?›²Ÿ/ªŸÎÚï=ýõòaV¿ï1ý§-ö÷Ÿôû÷jѰ‡Q Ìþõï?±±hXŸR4ì²OEü@••¾ñÝۭȲ`A"ogòÊî‹8Ï÷…dd–Á¾ö@22›!™ž–kß“ı‚Ú«ÓŸü½³v#Üe”¢\äð‘Rá¿Ú(S)‹\Géª@Ë„Q® lêaÚöy¡Í„'Ÿ¥nF¹/Õ—AÏ«³êÇ…ëÙð Ý`úQ |C7|¸£ÖXÙ:$ú©­ãÇ ïù{“eÑo1Õ… ç¡ÛXÐ=M úXq‡ŸQg,‡ §ÐæŽåÐ…ÍäF]±ºè–C»iÂ$àŽVÃ74/øKø†î ì|>½ö÷âΦ}ÇŠn³6ñó9‰ý0q5-†°U–f´‚áK\^»Ý5´ÚƽiþºvÃ&&£ùVyÏDežöèŽ[6u;,1‚=P¯ú1øöä‚sôæŽ!ó,s> ">×\[ÂÏ[œ[>q1cØ~†ôLÜlã#x&êЙVwËÅDÔÑ}ÏÈgêøDž×…9ŸïgÀeUˤOä±ø÷֊LJ{}\>†gê’ôÇÕ­…|à㺬öh!0 [+ÙÚ¶À™§y·ž)ر|ñ}¦`Ð+F`G…«r\1ó=†t3†m1`–öƒ¹ ͰÀÕÅœ[OÇŽgͱ|Y3YKl<÷ÏC7ë’ŒaC°IŠu ëõ&1?škè™,61ÆmÞ­aðÂ^½Üî3%»®Å÷ú|æ[ŽpȈ1cMÅ%Ë SÜÇlæ^Nýtso=“²«çËñi£×Æ´1tãZ´ˆ1tçE7Ü—.–suÿLFB'VºÏnÀq{ý¬çv2dÜæ™ýñL/îYõX|}rçƒqÇl Æ ~ÜݼCÏ4¥¯å¹£æáò WqÔ°7û3án$î{Ú™âãŽ1<€È¹vÇšJà /Qø´¹X àñLËÊ9lÞågTæ$ÄÈÝ™h+V½HÌQôŒêò}ÜCh×¢á2¨}æ u¦±†×ÉmóÖ¹çå?ÔÍdô±îçÌÏÿ8×ê>¦Â=¡ÆŠØc×玴IÇÊØµ¸ÅÞ½hSÍ9äó2Dšg>.Ó"Xm·ÖÎÞáÞ;ÆÐMÓŠ1lŒáÖ½ÙÓœCϼd1÷±o¯þ;UH~<ççïNmjØ·¹Ú1Ü`Ú+î•-Ö&,1†Ù)Û<ܨ 1‹=ê¡r“·YÌÛ`ñå2Ëeïq¿¼6vwË P7K alNþçÒcÏ^ÑfêÜ(5ŸosŒ)þ´³ ɦÁ+n—[ã[󶨱ԬÀ˜lÒo7tnï2ëe«¡aûÔĤy–wÃG4éOš¶§F4pî»û2_žÁµÊ´7¦gqÏ‹çsá…¸½°K\ï°E%nå#ðʆ8—KêÃñXOÛÓÊuköÚžV6(•9šÏ7Ù®&†80+=…ÿÌp;»g ûH%ꦽmDʰ{_¹ØóÞ¶ˆó÷v܆ç?ú€.HÉsàê ?'Óv³2Ë`A¨9áp¨,4m;+sSL&ºÎg^Ú™§þvé0 ž×¸‹=ߦÀ2¯ø•6Ÿàé/šá:;,Ë—@!(ü~x?ž›ˆÇñŽ!ÜÏb÷>“É5å/— ;€ïxoÀ"Þƒgöà=äÒ‹÷øIIÞcM¿“÷*,ä½ ÒKòÞ…VRÙ“÷˜òAÞcÆgòÞà2¼gµÆ`ï™w8¾Àä½ÅmíÅ{ªº%Þ[܇¼çŽâôBÞËä=¯µ K-Ìè_€®V‚GI„MYÈXÂV2+‹ê’÷²¼¬x¯ˆÈ{¶¼@ð^á#/à+ÜšSÀWX·LÀW¸‡ €¯¢Ø¦x¯RYïU-È{•o-ñ^Óï™Èˆ ï¹ú†6|¦'ÑÀç¢Û‹øÌËE,ˆÏ,  á¢zDä3ö-À®@¾u!˜&ˆÏP˜Ø/ûÐú*ˆï² 8'ˆÏáxÄwYÜ Z psSgßÌ…Þ… ¾ÇÂÔ%ßcáÇÄw™ˆ³_ ÖôR\>†çµ„ymÄ÷üwñ]ÍSOâ»l 7¬{á25 ælŸƒ9ŠØÂ5t)ße!?(æÀtÙVp ’@¾Ë´FS ßcé¨|ä{Þ;,zéÈ÷üMÖ‘ï2-ï‰@¾ç½4±(ò9̓—ùž÷‘*ˆïiÂÓA|ŽüÀð‰lÍ=_É›â+æñ«Ð K_QÐ@Ÿ¹ bÎøJã‚ÄgáGðløl úñùÌÄWnù’@|vÁ¸<ŸmL‡sø WY¾òü˜Ô>³,|fÁ(øj¹…w1{#Žðùb¸d§Æ„ðU)о*ï•{ðËÞ«©”>;oYŸGUÁ´T; §“øìe‹÷®ŸõÂ~ƒøìU ÿˆÏV.ˆ¯ZuAò] 6× ñµ|Wƒøª¶" ñu𨃹;ÈnÃF<Ïü¸š€¥V4nç½6õNï>À{öï/Þk]Ë:ðž-ó+Ž ^2ZhÀ×<*ñ÷ä½v£6 qÏza¿ÀEÏ0q¯±A°’yon¦±R–@¸XО‰È4´×T“¸gžš†£âòÍëRÑ&hɾ÷‹÷šÅä=ûàî‚÷ŒDH€Á{/ÎcèWú7dÞëÚqž¼×;ë ’÷|ƒA[ðžŸLˆÜ·,1‚~³Â9yÏ¿d°2Ù— WÞë‹Eæ |æúàÙø®:tÅ#|ðumæJ໌þÁw|ÖÇÀ=ó°[àžqPÄw1¦‡ÀwUù|öE-8OðÒµY‚–Èw Æ)ù,¨ îÌg-Ê‹ù®EŽòY·,AL×¾tP ßóå!^ùž¥&' Ï÷Æ©1„›a"Ÿ}vqo€|C÷ùÌ‚iä È ä3O¦8¨Ï7vƆ…ۂךžþľQXý–ØgŸ|8i€}èx ì³Þ.Ð#†ÐY œÜ7:·B%÷ <€¾ç‚ÕÀ ÏösÄäôÙ¢Ø è³ |ö‚뿸C ¡o n—Jè³~ðfô=—Â1R=·0¼õ [ܰÄîÆˆ_/–à·>”¾[4–2"§H~ÚyDä§=DH~*÷Nðó°k4™(°®Ð€ŸC/$DªdÜâ‘àçžBm ò3€ŒWD?À&‰¸$†6É s ~¾g$Å1/M¨›Q‘›šB_Å^©ó1W#u¾AÝ„:_eTê|Üò‘:Ÿ6Ôù*o¹t¾ÊÒÒù*Ý”â¾:D‚„&¾–Ä}•[ˆû*îk ¯}qŸïùû}ÆTþ‚™ŒÆ ü9÷uDÙ û:k2 û,0ç¡RÉù/ìë¢Raß­Sû^aßýõÒùìTXö“ú:‡Dèë¬%'èëpõúzç 'ôõKˆ賈Æ7ôu¦Žúzû„¾Î­ }»Ù ú:]“‚>£]Hk€>‹=„ Ç!4ºúì–£— ÷¥½ Ï#'ÃÌg?,0Ÿ ¶íÅ|K‡É|ÆŸPÍ‚˜Ãeê‚|¶Ÿù€[ošGÌg 0˜T`¾u3†Ì·nÖÒó¹…z]‹ ð›Ùw`¾ká à»Öä.õ|î ~‡˜Ú„K¹#|2DÄ÷X&§bŸû@a%‚ØçXW#ˆý9è>Ï]¤.\ÿ¤¿ÄwÙ¦´xÅñ]¶‡<.9ˆÏ#pF|χƒAì ¾çã²yƒøø¡½ñ¹oiD Z¸1&ZßeûÃOZ<ˆ}?lÐe Ÿ;0gù ?½@¾Ë¶·Å“ÈwYáù ä 'z¾=ä`ñŽòùg/û…1Ø=‘ï²ÍvÉw% S”å¼ôXƒ$‚øü ~ßód0) À÷X¸³:€Ï£&ð6 âs >|¸züÝNä»,Íë%ñù“‹ER ŸGlôSâsK¬¬‚øüÕcŸ¿G Mò]+¦`¾g© ?xÁìù<%¾Çr‹.™ÜÒÐf{ôzľ¢-¬ˆ}¾àf9ö=çFÖ)¨ïÚžÅ÷» Ï}GXÿô¹…¨èÐ÷X8}îƒâÕ8ô=êú<êBŽAß3©YÂÒ¡Ï=_ØåÐ÷LiF¡ú|’CU èó)ý‚>·Ö0‚Ϋk i@ŸGÖ€'úËE% Ï\°3ße™`æîC¨Ì#sæsWbÒ93=Ʀƒù.K','öùƒq£—À¾ÒYµ‰Øg‚`p_¹uMî³Pª…MÖ¦¡Mp_¹ºBî³y»­Ï– ¸Áà>›ý -šÊóü~EYw?Kuh/­Ï&,îN€ß3É»4CÃc‘›%ÀÏý”gßñ´(h÷ùò|ÓO73™œû.Ë­¤¶çCðE>fMp_Ì`Уs“Ï`°kpŸÏažiFÌÖ`A2pß3g±U¸Ï ˜|#¸¸?¸ÏßïTê" ÕÐ¥žèç¢^ó.H~6{Þä×'·Š'ùõÁ9 ðëx @}沺_Ôg¹” ƒúÚó¶Ç€@}u3H1Û,VBì ½ý&=%‹¤ÇXÌ ˆ$uU«ëoosY!ÏöRÄQD½"†$êÖÁêñ¥¨×Åd@½"Ÿz°^¡Q¬§§ÄzeŠÉzŠèë5AåÐfTpk¬·_"Ÿ±^yÃ^• AØ«Üí)aï–°§t9À^cM>Á^gþ´`¯kÍEØ»øx ö.ùÇÔ9ðÍ ÎÄHFu*ŽŽ°×™Ï)ØÓgC´wõOÚ“ë´wñyî ­6‰{³© Æ0¹}‘pop;áÞÍü/áÞ-ç7qoiåHÞ[ò÷Tê@À·ù=R`gídÂPÈÑ‚qEá­>[Â%|Ö £C™ZyÜ©‘ .c|[ZŸ-¯3®ó±\\àøìËL|Ã.M>{j¯øl!ŽéH•ïRÔ1U¾KÑËTù”Ì'•¯\R©òñ%•ï7µ6ˆd–¬ýB>ëÊ¥oc%!•¯° T>¥|CåÃs@‰ÏœgT§¯Ó!ŽPâ{^(ãÅ{»swi|gIãKºïÙ·Ï xÏyÒ[ðžEÓÈg?J?ok]Aä³¥[?E¾Ë—ô OðÒdì ‘ÏäN´óÙ2qœ"ßóŠôsùö’Ú æ³> ¸4éI'òy 4,|¶ZÆLs‘¯X>/CÐ~\ù¬L~*Š|ZRäó~` ‘¯t!U¾|aBå+ùÂ\*‹*ßä.›TùÊÌ£Bå+ã:šÊwˆ›PùüX0†¡¨X¨|eéuI•¯¤‚YQ*E¾Âb!ù,¡C‘¯Ð£K‘¯l@ E¾ZHTù,ét$ò K0åß¡ò™FʈÍPùªTgª|õâ~TùêÅ=¨òU‰ÙTùjaMÊ|µoz†ÎWgb … ÆÐ—ôÃÉìŽÂwîÌgã^¯ÀN7Ŷ`¾jpˆv!õÙÀR_åΕTúÊÒãB'«Úa’J_Õ®¤TújÕ­€Òçš÷+²³>/6^ c«"¬Bé³>®ú\ÇÒJ_Ѿ^TúŠ"¨ôYª2Ô6(}åÖ*JŸ%8SC3©Ú•>»óõ¥ôe•>/YYÎÇP¤”¹Ògcê¤À?Óõ¡ôÙoľÚ$”€újꤾͱ¨NIAŸÅNáâ}ýŠïô¼nà o1VЧî}7w»ô-~ç}K!–„>«{|ôݬô@µÏ&_}©}fá¹0†%ÑjŸÅzLj{®öYm™úü÷¦”W}¯øN‹£ ßÅõÛIu0xÉ&t9‰ïy7òõD¥Ï¦8CMCé³lT {!õY.Â:‘Ï\(£“ÌÄ¥7¥>‹’ÀBí3ÒÂýtµ¯ÚfÜ8ÌWn ækÇ”Œ1XÞ9@_œFľÁ, aß³Î./±ÏÚoBžÁ:†cˆØÇþ¿Riì@Àû?¢<›Qž¬Ý•Qž—X.³ú®(OU9W”'}°åÉ X3ÊS{1)Ês3e‚až»žbŸ- ú;ÊSu¸2«ïV`a€ß€ûCìÇ‘þX +é2pÒ¿«%U²ò†¿v+ð—âOÀ_Ï€¿KHKøSú ÙÏÞì7YÖAìwW.¾É~+ƒ@Á~Ki6d?«o¶Š!˜¸¿<}9"CBÜøûÈè³É„!€ýl-½^ìg«bF…"£ïÊúCFßè_/ôÛSUÌè›ÜU)}ëú@?÷¿Sú¶V¢~Ãê†@Míȇ+ [ížW¸q$Øo…¦+§¯ëö1§ïê_§Öçóí¥õ [ã°c¤ôÝ WJ_תŽèg Úý¦ ˆè7oõÓ±D‡°èg!åñ'ÈoIB ùÙw’Ÿ»±z$ùÙÜA? ¿-M}E3¥¯Të"¥Ï~ƒrŠ}Ö‘¸ŸHé+M9SžÒgÁ‘ø%=¥Ï2&Á¿Hé³ß´€”>¿™#¥Ï»ó•ÒgDAÙ#°µìàé/ð åajô“£~½ÚØ÷ËJËF½„ß>O‘.ËDè¡oVûÊy©iÉ®hSW2œ]Ý¡]Ért[vEÃÑU³·Üór=n ,ÙmêJ†£«Ná²aVv/‹¼˜*RÕl½Pÿ6Pj- ‹6›Š»ÿ­þG κˠªí½ÕïóÏòñO«>5Trè'3âù’÷{õ·ŸÎË鑤g+öÕm9ý,¼²/Zξ²û:[©¯+œAG_ÝCG_j¥¾ŽVêËk†ö³/X^}©•ú:Zå£0ƒ~~Ürÿíù7/æp]ûoϳlÛ¸þö¿ê?ÿoVìùÔ¿ý¦ýÏÿfìõ¬íÿö<ížåÊ*ãoÿ÷¿Y¸sÝVâÌÞL×°¢iÿÅ<äÏZT·ö/Wh³ä¿ù|C/3^?¯Ðö¬¯P¡ÍþÅòi×ñ¯ÿ]ÿ•UÙZCIµçîê?ß^ ÍÚ¦ŒÙÛßõ¯oÚÞ'C¶Ý/h3ã·míè_ÿþ› ´Õ?.Ð6,mçyÕÄÔºñJ¸´u‹{†•×y'·8½L/‘‰YëÀ0­X8ò…Ô´” 7t+]Žc|âöªŸ{ã>K¿øË—·Vå¡‹°¸Àó¬ZžÕÊ ‹;¦ù—†÷ ŸöJë3,ÞÄ«µ0ø²ô¶Ë/~*„[¹I™Âlc¾-´ðžañˆ?üÔpÞ–"w]añ%mÜ`ŸØ6ÍjC´2¥Ú¹’¡¬ÈÅÃâa©aÙ¶òm¶ŒóoEâ7saîç mœò¼È÷nPb‰£Î°x|›—ã.~r»^ ²nŽÿ?€—à¸Ãà¾êõ `ùzcÁ{iÛ6쎃œ’,¶üY˜¿ŠÅÆÔ²Ãý˜Ób×èÇ#?–ÇÆ¹@`‘ÃñaX(™b*×ågßáÚ·ÏÑì(faZ݃ÅañÓ‚Kæ¶~6ÂŒ-û^mÌ`ÚÎôn°k§\8Èoèö@{_jE! xú‡oüáÈë¾ÅÏÍ\²R\¹sKøûÌ)ÕýT;ËîG›aßO±ºÐÏOg.3XÂvZ†“îca)&sØÊæV²›9?ì÷ô¥dœüöê9nq¢0ÏÆ3Y›Íø`#±ê§bÞµy)ìñ0"ÏNµ1<†Ê6âmÜÚåÀT£ç_n‰Ðžz¹€þXXÓÚJ€M§…šÇQÓ å7{Ü&,®?–ðª·O‡vkŸÛ¼aûÙé!¨Ûöv7Öò¶$b{•x]w¿­º›¶Ù“z4ÏŒö&q“›§x‹m—û2Ú­Bñíðqš£2,Óƒ¸›U! *~Z[a=–ÜŸÓK ¹{’Ø~øæ/ØÚæ™UÛ-Ú¡ømrK ¡WÏôz,Ú£ỷ[‚­8[·SÙŠ£l6NÛ$,Ï l²ßJLîÓ#Èü(í‡í/p+5TY¥Þ¦Õc¡`g‹ŽeŒaé6І6(˜n Ê€Õ7¸ H̲"kÕ©Döë@q jc_^¯Y囸Ükøãßn+š_ú6{ÁF¨¨e§Ø'+ÈyÖªjÞ˜´WTðt TJÿŒ4{)Ã]{¥øþ:ðZGÉħ #€­±=³Ýóf…þa¹üÍí›òܬ9aþ„gfèTÓ'µéV·7êÓFÞQC ½Ù߼Р:<Ÿ¦yd-<Ÿîüm¾’ªÇ5ûŒ4ײ©ê[!ø£{h¬woØåEÌšUˆ‚m5ýVôÃ\TwzEÏaض p\,¶3” ssWû(ÌçTÿ uÚÆ?5 Ú"[ã d;+-kR©IÙc¼ý†vøËì]ü×ìÐQmzÛ××wg‰6¾»U[Í‹rÙ¾Jöú¶M3Â/g¿»½¾}ˆ¸–Ûk¶7KGŒÇÉËõ\f¡§Î7TêfaB‚G ×hž9Wwí\ÛqX¤½¿s[ Ïä³suæ—z˜am¨eŸh{[o8øìmïïL \¾¿UóÚò~VmÖ[¼³<éÅÆÙ¹…ÓŠÏ\ó4F••b±÷wô·Lˆ»E›PQ,¿ÂÞßžÈGu¥4¯gãã´Œª½âWð+¶´½&,Ä7¼eö…¶×·U´ ŸÇÿÛ –RÕ£ÿìTÏ»&.9Rcl«)è@¶µ’½¿ÝòZ‰ÌXß}ÊŸ±f;+ÙëےźšWô;ákƒf¥MìííùdÑïnÕëG4‹ëÛnA€o³Ï³½½myäïŸæÚÄŒnvt|{¬ÍÓf„o±YTO·“›l§Ú;Ûlwc7wXï8ʧ~3/ž½½Mn÷¥h³ú¦sƬp@oˆ^{ŽB‚V3¦½½×BÀW³-ìímåqkô<Ô®f_g{}ûÞÑàö˜ëfÙX¾Xmöu¶÷·ÍŸ¸Å&cïïͨ«ÖBöhk#> ÙÖJöþ¶P\V›m­äLZ!'5ÛZiÞÑs‰6— º~TÜä¹yÍòxV´‰{~v»4û>ÛÜóxÂâ›\ùlóQµÈQ çiöy¶¸…ýúôk¶»’½Àwƒ‚Ølw%{{"ïÇvW²¸mj2Ãâ[\5‹†q¿ÙæJÓ‡¹q»,¿Ã^àÖ1º1uvÆ|ó—G8`læÌŽ)Ù£‚÷ì«S9 ¶U¼³6¿Z³íÍ€óÚu¿Ð=Ú/üsô¹üf@?èÅ€?þøôˆEî }ò¿Ð/ÿ`ÀÛ/?ðùí@@ˆFQ›È–xÃ÷žxC9M4pò~ˆ€Lí;ø€P8Ä^‡â5p J투ѤÀˆzP`‹ÛwP ÔʃyTR`È«B£; °Åæ€@R9 [R%2Ä0!p!¸6!ÐbSmò%2-)páC™hÑèŽx¢À…ÌÜÄÀ5â™N \Ü G¸ü' T”š8pQ²"N $Ú =ƒžÁf™/ôuU`)8ЄXG ­ãäàÀÉ|Sb ?<ÁfSI\Ä@k+Vb µh–XÎÍŠ1Ð,€G`àT2!1pjkYb !{}a {‚ñ€S剈†õ±ö%š¦‚M%ƒÍ;Ëwr Yüúˆfàf¥s#R›8s+MP Y@ŠAS¹Ã¢ÀR€È¤@+Ÿ¨œÜZ“ h†XÞ‰‹6ðšÓ»­‘U•Q X´a°°8¦P2»°4ZÈ€…"t0`a0“ °?D*O- ,Lס%)ô$®Y……áÑÂÀ¢=v‰•!šâÀªšqä@ã ÆAf©Ap`mª ¬#+ßš…•ƒ+sÄõH­ ¬w†/9¶¢È$p  ;ت¢[ëb%r •e8Fp`ݪA lEáàÀÖY øtsS" lª—Dl*ElŒÉ"Záeœ*80»!ÞŒÁ[¥ ;7Z¦šß.‚ ªœ hMÂEtKt¼µ!YðVº:YÐ,á« Z [{±`Ö­& š«'H•,h–ˆy! ZøÛõbÁûºÈ”€Aß©0¸0h°8 úÈ;ƒî®Š“Í?q„Á› bÁ ¸ïÁ,Âà=X30h•³ç í¨õ¢A;{<ú¤Á[Áz¤A+tNÒà=¸Ÿ hÐBÇ A;ÈŸjá ÝÁà us¤ï‰=|Ѿ óɃf ‚ÍAu‡ ºå¤AË(ˆcƒ7“pƒæ†‹J´s¿aÐw1Š6€A¿š ÞØDà/r;hÐ Ÿ4¸î›4è«ã' ®ý¡n¤,$n¼ºY_)qp#>0xpG=ÚÄA H´{ê¨'Ü7ûÄAKβ'ò(ñàŽºs‰ƒå(¹Ÿzòàñ&MÜHÚMܱDâà0€7ˆ#ipc‚¤A–\NÜXj$ nLþ¤Á *IÜŸš s’Ö™4¸QÎ3ieû’y?y'ÍÁãø%ä@¹ˆ>4AœëÐÇ7M0ŠÍ’`ÄK’ "¥IrÕ! b½th‚¨Ì{h‚\á¥&ÈÒH© R–“&8ñQ nn"ä©’ó(²àæžBbÁ-î$ n¦ÿ‹9ЄÁÍ+¢AÎ ÑàfÑ`DÔ©Dƒ6MƒÙHƒ›U Eƒ›.÷¤A&% rOò¤AŠŸIƒÎü¤A&5Ÿ48_ª _s@i“ò AÞåÄAnhuâàþàA.]O CiPc šK(ˆˆ01Ñ Ú1Á-`AIA,x…ó5AœªIÔ¼! æ¼' æd# êÓ.ÌÙFÌ[C<ÚóåBÌ÷3Q0§PÐ/'šó·# NU} ΘäÀüxór ú!s€À|õC’ó€óA º›.N ènº0€Ír½$A·tý¨@50 /3}åNô6!ÝÒE(ô]® ¼»©;}±  ­w× =ä;úše¼Ð,-@  õã @÷„ÆA @Š nN$D ýY À3ô‡)¸hô tÏmttKˆ† @óå Í? Ð,+h è[ý8Ð …h–òB@[ó_/=ÐQ%N4 Ô¾@@V‹Ž€¾ùXœ(×¼л xf?D@sÖ‡ 4C1 ìÄ€ Ëš%ÔR2 ï ý€Mݸƒ65¼°ùÄŸv;ÈoÚóôÒwÜòƒüj,†òƒGXä·2—ä·~›ä·0‘’ü,GÒ9ãÆ¡ìR¢ß‚§&Ñ;I%ú­v“üÌàW+òãÖRI~T²D~+¶Kò[Ø00ÉoACHò[(Ø|ƒÒ’Á ´d0(¤­ …ˆ{(Q¦©¢›W0èý Нé¡Î8Õ¡Þð¤brþa<(b %ᵇ/Ö!ÂÉòŠÌ”á~Ńºâs°_ ‡ÉÁ~Ø1÷`¿Ø{ÀÞ?ý•àÿƒþ°ÑêAÝ=è‘ý]p#ŸôW?èïú”7Ó/Oü›o)ÐNýÿnSâËÝ$þQÄKü£«9ñÒAâß"o ÿ6zfLhán"‰ NTL¨Ša(&ÔJmø÷Ž õé+&Ôh€B>ðÛm$ý1þ/é;6%ý±Ìè{i$ý}(ð¾èÇ’¡¥’)ZX{Œ¡Vû"’ÈR µƒÞ¡ÞÁ MNb`ÿ -”LR ¼ -¤Èú³)†J d}×Ii)rí1ðæö™Ô*1°RfI1õÊ$V•x¡Xx&1ÐÞ}/üËd‰•Ëø¯/TŠ¡È¢G©fÙjK;C ¤Ô›Zàdi{J¬I“R 7b”hâ[´¡Ø «C TF*JO%Û+K |Žâ²”[ff‡¹1ø4¥@ítH/ø³O$sX)ªR›¤ÀŠ FRk‘I d$Ÿ”@„s¤Ø™à/%°qã!)Ä“J u¬T)K ,˜6Rw úz ’%RäK!?]ꀆN[¥ X  IìL hý¢Qì¬*Ðö¿€%d@måž2 U\É€ÛdIì|»HìtÖIìÜÆK2`§ã”ë‹M%·”dÀΘÉ€ÚvW2`ç‡S2`çš”ó Ê€¤ÒDÊ€ª¦ x…$Úëô%^‘f’*à ǹåOŠ€×'Þ¬ž"àÕ)R¼>)^D*‰€ö³HðBI£YŒ&EÀkÅ„KðºãÐtß`ÿNðºJðB­Ý/œ§ x­XठxQØ” È]•S¼6ÂZ%‚#©^“r5Àk~„šežèû,îQÈO p`ž§È$ÿÔ>/©Žx H•a›Ôí5ôÖÇ[ر'ÀM]Rœ(q(€xKü…òn/ôß/œo¼¡@½Bç o8¦ˆPÔÀ<"BC˜y„®To1;"B‘=pD„bÍvD„"äòˆÝàÍA¼ÂÄ7AõÔDŒƒñé:HK»“¼0«¯ñ\&"5éÀ@¤Éˆ† D1âÔz` nè!BkO 0–D‡ßñ¡"ëPëg<èÆ9@èȇˆ­<žë—øxˆ_÷€@<ÑÞ %4‚y%ÚJt¼@³D )0W™d@³ O hKçþJ ¼Ê~¤„2-ûQeZà†ãTi••=•X™Ÿ¤´ÀÊ`,åV®<”X¹G‰ò+ ®y±ÌP^ ½HÉ€7*ŽIy¿â™È «™HŒÎ¼À‰PµÌ ¼¿^  ­ÃÁiÔi2-‘™È4årÈÌ T¾¡òYVKy ¹ÄÀ‹eþ„éˆ8¸+0P•£3/þŒ#/em3/Kja 6&vDüŠ;Ëžiq+DV®ùM{ ˆ3q‘Ø+œAVj4d8RàdTš(Ðj|½çÅ QRà,L$^ Ü^ª ðbuAà³¾p•) ¼(5‰ûÖ&æÿwï’¤9Ž,knŇ= Áû±Ž\Áô¬Z¤&wÿMƒ©ª¿{fEÖ­+}úÌÂ$Hð矩šؘF lE•öAMnOb`«Q›Ð§­kÅ-`àˆ`à`E1ràÐ"õäÀ1´Œ8°÷ÏÌ@U‡¶kIŸJt.ð,ŒmäÀ®½‚C«Ö;‹¥ O‘àЙ$ÁÁŒG’à`ôLÉVfþå µšzþè‘Ï:ˆ/´5À}$ÁIÖ" N, ,´"L¯ô@Ëýt›†Hpn& ’í­ëý’'ä¤@ÁYÖG|f=³BA+ÙüÊ´mü¾ .æe 7W nz‡‰‚Z¦G(ظ g `»’'‚äA‚ƒü(T6­HpÒ€!\¬?*\(A+dÂE€à3ïP‚“_à`š)Ap2Æ¥ìÀÒôÀ‚Çêòƒ"Ö ȵEgæ^ôƒâÕ$8+Ô,¡à„†(¸0÷¹ü Í#³‚\†üòƒvbQp¢0@  Uåuü" rEñ@Á˜ÈÇü@ÚŒü@³×{Ï÷¢Í”ù©1É,XÀBA] ¡àê°å îÈ@Alì2­^¢‹DÁZþAƒLˆ ´W÷LdÊh¹D‘¸P4A4xV3|Ñ ­dÓ^ŽP­™y9Bñ ãa Í´‘™~YB±Œ^áÆúA„[""‰p#*}•|+ÛÞÒwé±f7O)jù‡¶¹Š·}n»i£öúý’oßO+Z®ŠhïCÄFwE´ÚKwÛ»Š–èŠmêJ WWÍj®}Z-ÑÛÔ•î®ì+IDö®Ôru…¶èŠ ÿñ’oVDsÚõý©ä[š^›Ík¾•»ŽÛgñ¶çŸ{þTómG¿Øàþ§…‡¦ªýtKL¸!¢ôÖO7fn]¸*ᯫšúº«¹±¯ØŠ}½*ñ¯¨æÆ¾®jnêK[©¯»2ûŠjnìëªæ¦¾´•úº+ÃéYP57ôuWsÓc«­Ø×¿Só­XjéqýTó­ÿUÍ·o…þ~¬ùö'[}«ùögÛ}Ö|û¹¼à»æÛï¼"x}{!þñoµk£ßxµþñ÷K§ã~+;ù×¥Ó¦J§½ ›]ÿŒ:d,žVó¤xÚ?(ž–õ/”Vë‡2jC=>ÿò2j3•Å2jOã·2jOÛÿÒ¿þë‡6•Q+]F­ØbUÇúcéñ|È:ãþ!´ù6¢£çƒ¼=ÇÁãÖRSBäùïÕJدî-¾IInü™(GRSMnüaj{M¾Ì±g¥{‹gm€è™¡V«ì]PÎì<ÞÕŠAW&ûÁýÜOl3ù^«¹mseúV+þ{l› ±èz*ûºåhõ¬BÄ`¦oò b1;Ú¶Û62ÿjöâ%a䪧þ.²†«ïecp64_¿ZyÒ{‘Øï¢÷"ãÚäMï„÷j«º ÚÿòiÉY¾ÍƒÛµ”°ÞŸÈàÓÞ‹`¬¶2…{/¶Gôji¬Ç•¸Wg=.Õj¬Ç…uxj™ð^ n~-«9°%,ü[Ëf=.”ï©¶ÌŒ×ãBzo}~Ôã OÏä3ân÷)Œ»q µ"îÆÜÓjkSb£š\kgàÍ«Ù×:wCø®ÖɸJ‰<ý2î†2Oµn»Uuµ%ÄÝêÀOÞ2ânu:ßÖVX‹·Â¸Ì=µÕ%éÎôÖ<îÖ ×W[žÂµ;Èóµ ÄÝÚb7q·Ž…j[ˆ»=Àoöf‘슰ǹ=!î6éµgÞ†¶)¼ ,…ó´ ðfÛœ«Ó+oÌ髽!ð6!ý×Þx›(œTû@pÝNÞ¸Aí 7ª] ð†U{ëHˆ»-ÄæêȈ»m,‚YGAÜFÖ§·Œ½:ªÞl…ì-Ío¶~Îô–î·³€ê“-P±+ÊEÏ^˜)£o9Ë([ßõD'ªÍž±e¸h«=`åTâOnOÆ!¶ #x=_;TækÒn×~ F¾êѧ½dÔ¹8ç†95¤ªy=µÍUȾÍð¸Û¢U¡Ú·üt©|‚âçÇä-ÛãnV}Çï~»(y{Kö–ìq7ÛëLAêò:ô§ÖÓ‰ÉW;j™¢¥zÜÍBhÍûi¨É5`D¬g ¯œä߇5w³÷Ói˜»M@gµ*NØm"Ÿ±Úz§'ì6‘ëQmµŸÌ¢CçlÎR¥ÙéÚ?<§\Žs!a¯Úz?§.ׯÒ0uWÔåB2eµµ£:ÊIyµµ£Æ)„ d=kHÛ¡¬:£ŸŽ Â6A¼§ÚÒQö·u3üqÝ^#òiþ7ûNÛkÜÔªplöΧºÍ>Ôö·ê@çÝÚlõ(ÛÄô×i¨wÛ¬HØÎz/Ó«úœ¹Ù¢ ý”B`°Y!{D³Å|ì5nªWòƒ/¼Ù(Íû¡ÚrçÜl1{Ûš¯Ó[²GÞαÎù؇ÚÞãvùO¯E lÂG³¢èö߸[>‹x[0${C÷À›­¼í—ËV²×¸MòcO¼õ—üHë”q+¶Ê7Îf{àÍ&[ç¶hå¬áu&[ç%Ùl™ {oV·iö¡¶×¸iyçîoö¡¶×¸µø¡ìCm¯ñÍÅ¿š-!e¯ñ½ðyoŵõž½e8wš&ˆm¦Þ6Ë6[CÊÞÀ›I ­øB"ÏÌ>‚VÝ&Xm9¨MoÕe¹šX 㙯'Û¥øÒì3}4#•£U_|¼ÚBïgÓì3]ÎÔOäíévþò†qog–yB­Í–êVß<óúÙR݈¸xX³¤†» ŠI³¤NY® sQ³¤NY.Ss¦·œ¸[M\Ÿ¡Ùg:Ù¡ÌtÕÎJ^ÕVäñ«g_é|…5êš}¦‹ ³zžH³E¤áQ¡Ù"RÍŽÔ¼HS³5¤zñM²orÖñª¶ÜÅù4[BjØ 4ÓfKHM;Ѐ½¡ÙRËö²ð¶oSNÔ­j•fßèTpìsAí} Æ'TbiöÎv¬ŽÆÍ–‘*Ë…m\)8óíäg¸Î‡ìë„[÷7õ,¬i Ã]¡ÏÍã‰ömœu¼ž):Êã4[CjÚ ¤ ¯OXmíP?[§bÛ,ÿÍ>ÒÏ;¼fz:›}¤ŸwøÙËpûH;vqí¤ ¯hWÏêçúT;TÁ²çíLÓm”V|áüX]íŠöŽ÷ßѣ뗂7l»å«­Ÿs¦mž•¼ª­_^ØÍ&‡ËZR:F»fÓ¼ç ~Î×OæD7ú—³Éù¡¦¯RmI‘î{1î³+ƒl¿WPíEƒeâ ½/ôXõƒ>ID˜é…ƒ>I¸y09µ‰æfÁƒÃq+pÚÍ…ƒ¨p88ñΉ™Žpp≠œXRI88Qç6ppb¹®ÀÁéÊtàà„Ò8x_7¢f„hpb)— Á)=ppA \œÃJQ.è=ƒ ÂÀÁ…zAƒËWÇ \PBDƒJÐ Z‹OdIƒƒ‚iPy>¢ÁS³ìEƒƒ:ƒhðd|]0(g`p,þ¼„Á±™ 0h î |[ˆOI0o4âÃO!ÔiŒ ÈòZ‚ ¾Á„Ê·‚É×·& LþU L\ Lˆ%ZÔÁ±‹˜xa„ 7ˆ( O‹~yÇ|¸‘Dªðw)ÐZ< A <á ïyÁ„¹^hß ï˜x"Îs9\ø]!Z‹ïT„Ÿo´~—“c ¾¿H§—sá  ¦lQàäj‡¢@kñ·)ð„Rœð]øÇ"¿Í‹mj‘íkéÏ%)ÐZüeC œœÚ‘gÿMh›øƒJ œÅ‹‰9޽Æïw5)ð–^x,ëçç$š…i½(Ðb=Nx•>|ˆ¢ÀSqêE“K¶‰Ï¥¸)prYxQ Ùtº·lÖ㪘`“åÓš•Ç'–¤Àã¸ñmœOƒ“(ð8¾ëq!SW85S"ÎŽgFx|¾͊z\>¯$Îî /´Ž}ÎM´n| K”óY8¹¢  Ð\CŽ© @‹ƒ7¤(ð”&;gC ´1´ÚÈ‹Ÿ (Њxmßk³9xÌÏÎ|™å¸*”h§ãÓyR mãTO TI1Qà¨ó! ”ÇEh:ßiÒ}‘ÀÕ„@ó‡8νÒÖ Ç'á· Ð]CçPnêpä+pâ³H/!ð8„»§¥z·=Êq9'–ãÂê.„À6ô~̬dE<½´Zd1;weš/ @,Ó{QAP`ÀÓÿ΀çHNÙ`Às2~À€^¼Þ»¬Æ›!ÐC–—‹Þ äçƒg¢ßè…óϯ Œªø¤Àã½ðûx\'é¦@ßë+ ð„B_xvrøzå|oqôraœg?’3à±ä”‹yÎÚE'Xú¢Àcô©ŽfNg›gÏömœÏ^þþžÀ¬ïäXŽý+ ðØðÖ ÅV?÷ˆ ðT‡÷»x.±óœ3 —ñw4s<§çïL‡ÀÓ°¼‡Àö7(ðX= <'ìaP`1?ž#=uXÛFø›µÔ×¹°7.¯ï*´(ù[dæopàv‹œ0ðL-ÊÏZ‹Ï}„{ÁÇr~¾Âä@åoŠ'ì2eRh¿ ´)”O³ˆ¡ÀÀºvÂÀ89p&‡aà™â}]h ¦ùUÃVh6q×¢ˆ6 tEx’3ý|Gör5hFŸ¾mG¼B3~GǤÀ3Ÿ{‰‚'ƒÓ·¡(X8n‰‚yÓ—(ˆ:÷·(è/QÐ&å¥ê…(˜°Xuˆ‚ ù —(˜~ © V\ i‚C̘„&˜;‰Ž¢`†ê+M0£Ö\h‚éôCA,ƒ’5ÁçÚ¬·&X°,É¥ RV’&X3·¡&ÈB²¡ & ‰ÒQ“$4Aû½eÆ=~ŠËA‚­QËK±F«p$AÍ@E‚Ô,,÷H‚}€ò‚%gm1\o¡¬è³l‘àØŸŠàÀŠ7Á‚C°àDÙ`Á‰d©`A“K¿nìTGl‹ G´U>\}$ 2ÿ-X°aq•`A¦ŠM>u’,8=1 Ppb-í@AOÓ¸Qpb‘ë`A !ù6Ukô8ËÍ¢á¸Hœú³X+c ²î}° } œ”BÅ‚ër Î # v¬Ë(È2D!&¯z }‹ó &Æñ¤&š$òS‚`B媼Ò!¦Ni‚`Z?‚©à—‘ ˜ø 2s,XЂ{ÎydÁ…Õs‚IJ ÍüV" Ú,Æ?)dAk/´«,¸Û Ú¥A#ô…zh± éáûÅ‚ ¡à™Ay PÐTëå-@A›™-—‚vIÑ1PжñP;YжqÑP,h7ŒÃYp¢–XpUˆñbA[ÞÇ'g`Akðy?Yp ‹É‚vã½PÐÖz£ ­5ä³I¢ Ý¾‡@A¶}jK´‹ƒ  °³QP : Ïz:¾ Pð, å-DÁ…õÑ„‚«£˜XpIz" Úµp0! ÚJG牂ËÌ)~@Aëú_rÇÁrL"E‚'gäëAó-¼AÐnYgE€àqøa‚Ö‹IÐŽ´¼à¹TŽp A{4ý’“mˆí–Ï¥ŸWG†8QÐVÁÎ\³~  ­–äª6QÐV]ò‡Œ(¸ú‚úL´•¤’·8 ®Ó‰PÐ| ?GA³?øU' ÚOéª1QÐòH QÐÆyN´«Žn€‚k#Õ\(¸æd7@ÁÅ:CBÁ5QuK,hÆ ß†,hOƒ‹\dA®!,Ø¥ä‘un± èƒù… T¤D0Øè‘ v¤ª vää &”+ žìa'2à =üòÍÅá?:pðØ1¼ààÎ|³ '‚’ƒÕƒ“ªµp°C¨øEÕ.-pÛ½ÿB@ˆ!`ù”Y7)¤À-qRàæt?pa¶"-pc«Ð7Js…¸Aí¡n$"Bt ”Üœ2{‘O¡¯N ó…€¾0ád–ßì<̨~vAàœì†Àõ†@ûÆù +œŽ‚@[áË™Oˆå;‚ W/ Ü”þDH:¾(PÛÍéý+Þ8¢ÀŠzhA•·…(°¢äVP`ÅQȵÿ@io ¬ƒSR`Ã/.¬‹ "!°aEˆ€Àº!D–£¬ÈËÚ2ÎX„À†ú‘Í `6øÃÂÚ(ýÉ [Àm Ýßl¡Îµ·-ÔéHØðκl¡ "pQ×#öBÊ"6”Æ ì™6¤›^ ˆ‹;BwÁ€O‹Ã3 3;‚ÍyãTHì›U2àÀŠ)Á€ƒ¹p]0 ?7>œØ^¶Ð“Où'2…g¡ÒHœ§—ª® þ$. Å€‹âš¡ä`Àû_0 ŒçdÀM£¼p+Ä€U1ƒ²ºr0à¦ISh꟦PÉä MT'å µ¯êÛša ,‚B2`Á¤C X ñ“ X2eF2`¤M2 9.É€¥}ÈvZÿÈ€À Xé'VØ™Âjo?G50 Mj[É€f‡õßS®ÐÆH°òÞ69RÉ€šDо¤Á€¬• Ø+å?0 ­sê;‘¹Êr0`¼í}éÖRß8<: 8(ˆ'ãóbÀI•„ hs´þbÀ3Mrœ#.šÓÄ€+êI\œê‰ŸMÜö(ܰ@ZÇ~pB ñ \XáM¸±vg@࢟Rh u ¸×‡+ÔZœÃµ p±pg@ k‡‡+4ÁŸ¸+[;ÑF ´GÃçÏ¢À½éÍ4 Üt¹‰·«ã‚@뢼(𜊷t.Öº©;­Å/ 1Ж5õaÍ)ìb1Ъó8_Êša Whå%&šÙÁ‹h^æy+‚»¢Ž„0Ð6q]ŒhvçòÂ@ÛkܶЧ…^Wbà®Tå€Ö±{I‰ÖMaànHÚîð|OÍ!{&&8pû§÷âÀóîñ½À{!ËBh&d¿µÉ{"}T¸i5Z„rs ÊïZr íäo*rà9ona)9pOä‰Í ÆÒ@šKÚcHäÀ½?9Ð|Óþ* n©•54eT•–7Ô,ÏéâÀKóà M¬-*s¨½¾ý®$n.Õ)Ü eÅÖrèæoÔW»˜pÙy¾˜ö±Ûê¥Ã )ÿ•.¼“?tþz3ᄤ}ÙC7SøÈ„‹Jƒ˜pá&\á]é‚T•-Øß² Ö%½’±8hȂ٧l¡ †s(x w(ß¹áÝ‹-ÒÓ;YÐ q>H!a”‰„i}ØC>÷„„™jDè‚—XH˜Q5ûÝQq!ÊM_DX!-2 º §«A„‰ÞOa¥}õ"BŸT2Ù'ˆ¶]!aC­¥ “£DÂÍ!!ŠÈ6,ô}1á‚P$&´º_7Žö) TÒz£Å„CÖN2áØ˜ö 'o Qáä´WTh%í|PáäO.*œã“ ™eT8½}@á\ŸP¸d%Nš…{Jt(\,-(ðn…½R(v”&lpÖ6zHȄϘ˜9Á„ «06† Ä„ ò`Âæé,„ë±Ü Y)7ÐC¾‘p`ý@‰¥¥ 'L$B2O¡Õ.ó#‘}îyá€×N@8ñy»€ÉB¼ã‡´Eáà¼+€p¸e/x°2<Ø'[„VÆí•%¸Ö¦RG \0-_@¸% ¤“N@8½ TðàÄg@<8± ÁŃ05ŽIB$>ý+Ƀ3}òàDÝQñ ~ñà@ì7xpTà‹xp`qÇ‹±àóѰÓrv©$Á$%‘šàÒ¡ˆƒLÁMp!b¢à¤<&\ùö‡®…û1xp"µ!TÁEÀ‘,8QÐ!dÁÅC:´tAÔÈ¿tAZô¤ >“hÏ“.8;¹Mº âR¡ ¹vH]p2ÔA]p~¤ úÍï;Qlë¤ *ÕQº`T© rR&]ÐÏኺ`]l‘.(H£.8Ûº`l¡.Èš™! 6ºZ% .ð¼tAÆ»B¼û¥ d….8 Y\ºàR´ÛΩíÒ!e]¸k% Zìmµê|/Õh¹ºB[tņ««ÑVºúÁŸÑÉiPþ×µûL^Æôºhj‰Nئ~Ôð/§Öm»¦ÿ¢œÚ·²g^N­Þ%Ò>ë¢ýGÊ©ýtŒâUÏ£ªÕO7c«H!ÕVì+ ¥±¯»PûŠ­Ø×½•úR¡4õuJS_ÚJ}][©/JS_W¡4õ¥­Ô×µUÜÿ,”ƾîBizTµûúwÊ©Ù÷¤ó?•S›UNíÛþc9µ?Ùê[9µ?ÛÚÏ·Ú»œÚï¼xÿ|{ þño²k£ßxþåÔz±êŸû_”S‹åÔžýe9µçÿYN-W@{Õ5û×åÔÞLjÚhÑÛ?*¢–Õ˜þ¿/§öœ9’°ç™ñà),°6Ï×o" ÛâŽÞ²„=±LØÓ‚$lFQ{ÝÈÂfŠT0ȳ°'Êkõ–‘…=‘Ð[AöDAæÉ' {ÂpÜ[ÃzhÓµ–Ž,l¦¾÷6…mÐ㇚HÞÀçÞÓ°QoëiavòÉlo›iØÙµ¡Þó°1ÿî=3sýnw«¯°—`®³¦ê÷öÞ‡½÷ꞇ½°í3+E*öBð«÷‰Tlj{½/¤bÓ´õ´ ÛÜ’~Ê›©ØÉ'ö}$¤b'÷õ‘™Š ”{ŽÍTììs¯>*S±Qþ¸Æõ°‘òÌ›+ÖT…%¿Áõ°Oìcr=lHýT XWjx·“÷Ú¬ÓA­Ÿ”ð÷Ô¨Y—|QÕå‘«náX´ßróT€?+“±±ªHŸÙØHŠê')Iß~Z=1OdžǭKr_fôãRÏn°:ŒÓOµd¤üzïf-ÈüößêTÚÞâÏ‘ÍZw–H·XÓ±_$TqèF%Ç~‘nîãzýŠ¥2º#<¾˜nPR`?fÜn$Z±4Åô½ó±a2èFDKSø²¤¦Ño8ÁÁ¾ k·òM'Ø–±œÙF0`d8 ºU5ÚÈ;÷4Iñ0²Gûîðàg y·’EÙ0 kãÀƒŸQ¦›`W‘`tØ÷i ?£VßùØw×°B=BÂî†U :c@´h¤‚|ì Q¤Ê|lįGjHÈ6õ¡Ÿ–Ž„ì§åðÔ8•oŠ·4ïyz5üÏîH‹ë¢ù‚¼ÃJÄTœo±W8èΡs‚¿ rä >W°¹0ÛóDG®(†o®’3&›=-,ÀqnŠç«S”F•}±¡Q”F•}¯™•Fuèsä…tlŠ,O‹§c”e‡àÞ;Á¬QÒ±MK;?S†îÛœa–‚llõ[*²± ÔÜQ²± BÑ£tdcsu’çí†tìóÀ(“|4‡U×åš&ègm­iâ÷@ÙHÇ.(¼?jòtì‚ÊT£f¤cÔVµ »Àè4jE:¶Ís¼¥¡~A±Ñçõ‹tìÂ{´OÇ.“ÇžHÇ.ðÅûR¹¤àµ9êB:v­nÔtì‚€ÿh éØá¢a³ü£—d_VŽ]°¨âhùØÅÛŸïò±Í²yŽÞ:ò±‹gXŽ6ŽÍŠ}£M¤c7.:›^^ÈÆ®(Ý6ì+QÁ‡d_é§/ˆÕ3²± ìà Ž7(zç½ð|¼ŽÍÅGoÈÇ®É=§£wÃ/|Äû@>¶-.è{MäcWÔ ¶Ð׆}Ôo7ûL'\Ðíç¼=!»"­{ØW:¯ûà##!»ÂŸù|]‘ªMcTäc[Ò…ïÔ]aÔ£{>v4 äcW®5mk}MÉŸ›8-ì…³YÈÇ®X·h`1W?øÙ뤋ò’žŸ×ðÆ^¾MABvEÝÎa jűÎ\h·i÷m°YGFvÅR2ã&ϱ0A§2€o‚næÆâ–Õu«a)è ­¿%§¯d¢í8™;í+Öïö™Î¨?‹ö™öªž2ŽîuÆÙñž?é 8Ô i”…ôÅ"}›”ìÚqu–gÍ;°e–Oa}¯s½ÖÉq>®buÙz_ -ÞUPôå-1Çö™öå-±Ô°ÏtÆ¡N7Ûµ»«Á†ðuÔkÓöü_Üò\«"عé½ÎÉZá8aMö—¹X(yWßfOI޾ܛ-öEôyΦåÛ0'ûÞö‘vÉÉÄÓ>Òç%ÞP4`ÚGš>è ~ælÅ_â zÃ3ËôAŸ‡hZ”¨¡LIFË–úÈÓÖú¢:{7{zM V‡œ¶Ö¦:¯õik}mßÄÏÆÖúr'4r›§}¦Ý íš“Ç8†7øêxö•ö\Ø…µðÈágGëæw‹ª½™p~cBç½› ϤêfB§•› OÌübBOL¾ HˆTê ‘Hˆô‹ ±Úá…„^!á"ÂC fõÂ9Ù/)žÁƒ6µàÁ‰ ÀàA“MÎɈ'>¹Áƒ\%xp·.œÛããÁƒöü;V’çæNâA¸I.D•”àAӳΠ’áß\Èy \X *pÐ’f½…8¸°¾aà kª {…ƒ ´ÀÁ…<ÕÀÁÕýÑ\È€ ´up¾.´ÇÞYûã# Z‹ß|¤ÁS ýœ/iÐÎì4xv' ® #´ÇWÒàÑW|/ÐàÙëÜÖ¤ÁS Ýñ 4¨EÜEƒ§<›ó!hð ··8 Zƒß£¤ÁÓ 4ÄM´mŠoDƒvñ_4h˜>­@ƒ§åEƒªé4˜PñX4xVv÷Ò`J„6â Ó|S1’ì³Aƒ ªkÐ`½.LÈ Lx -}øëfÁä%™,(˜ð^L(Î(ÛSûõ&Á„?Á •Á¯b€`€-~EƒQÉ<0Ãv Xð¹ Ì"G2`É$>1 <ÄÁ€%у 2•‚‹§\˜?° "¨à‹°`a‹ £,H¸ ,ÈÔe ,®óÔª Œ~‰€VXÝ»!Ø"‹‹X¡h-¾ Š8ÏÈ ,(²,´3ö^H€“‹ À‚D— À‚¼á À‚Éb öT,pæ¯äÈBA€^¬ À‚+A€ xY…2‹~–ýI€Š½ˆ lØ€\N$0ƒ»ƒIýÁ€°µ_X0A R|B`eì1 Å!«ß¥Á€• x‹-}Í© Xñu´‡Ã°z†´0ö!V¬6XQ…2°ž0°ÂVÈT!`ÅJC€ïÈ@ÀŠJšÁ€ÿ‹¬ûwצWIµ ÏÔõÆÀûW` Õóÿº)p7H_¢ÀbJ¢À3·sò"2åDxªüú6……¹àè$ž¹K…À@Ûd¸¢×Y˜ ö\q Êä µ¬¸@pÒ‚%<ŸCÌÍÊ\Ô£H‚êr™”$x²Þ$¸ás ÜHj ²¢°@pãñaË÷ž)«ï ‹ 8Y»A x®—#œƒàL™L´—¸ÓIðT;—+„ÁI9$8¹¸HÐzF?ƒEš+[&‹4wîµX¤3‘àôÌ‹­%¿„Áóƒ:Yò‘Â`æŸDÁMuø% ¾QP Eï‘Vp ƒ¼8! R‰“0Èz‰! Ú,óœ„ANM/aqµ³Ï0BˆMHL [H„C1dÁPÈ‚©A5•,H”‘,(‰T²`Â< dÁ„—,èyä—*HÀ Upゆ,¸©@JDÑŒKœ C©‚E—(ˆ Û% B\¼DAÒ5A’—&ظA0ãÃri‚ ‘Ü}q ç®’+UCI‚È dù% –O´©¡#Û% úÔ&DAø¦3ƒ™[Á`FÙ‚€AU}/Á \ïƒ5­Eƒ«¿\4Ø11 DýàK¤~² ê¾]² V¡ºdÁFH”,Ø0Y™K¤b²`aÏ’‘(tÉ‚ÈîY™K,„BD&Á…‹à(Y0û2TAÎþÉ„¸`B+oâ”H&49 -T±ìÃKô)e¨‚BDÕKD|ïR±ÐÝ¥ 6ª‹RE>1!¯WÈ‚ÅgÔ¢ &,XZæbB$Ûj*&¬ç]LýQHx>w¢VÛŃ”TƒQ.ëâAØ¡.D–Ò„Œ  t" "âuÑ jk¿hÐ_IAƒ$Z)‚•Ú£ÁB¨¼Á¬™g'E™‹—"ˆnð/.ñK |ùBÏãà§G%pá%paA­K „Õ!”Àå>ŸKL4ŠJ¤¹Uø—&üK¸BÜÜFBàþÆ(pñ•^ñ ]üW¨¼]üWî$RÖ¦BùPB`eÏ—Ø?„@µH Ìl‘ˆwñ¥vb£¤Àð )ʤ@,Ð!<&hÇD0 µä—x4Zç9@àÙëå 5äH1Ž€[ Ä·6A6.A°c‚à$ÎIœ˜)ߊàüP=÷ý%~è¨LùÒl…€\”Qh/ÿz ‚gÁ‚— x"†ŽSB@”Ä»DA!×¥ ¶U°Pñ»TAè{RÕ"Uf¨‚˜·Ý¢àx©‚§Ú§ 86LÚ¡ bÁ‹K,nYÐ7¹TAÿ¥Bäd4TA.UpøN @;0¡TAªy¡ b¥K¬´fJìÔ ¥ v\ŠP)8˜«}©‚“N©‚°f@¾TAÝUAF BœxÌH€ç+áôFÌ“:¡TA¤¥ÚÅq“*HaS˜'µDPà©ÝêÛ3jc"0˜Q6 0cµ`A`BuÒ€@–½ Ì|ÆÅ™*´¯á›Sâ6Tñ̾æØKÌochFÀ@.Ñw©‚HÅ ÌT¬½¸JP Užÿ À„NP Êû_ˆ)vP §|á å _hÂk |¡ê˜(£H``¦STˆâÇ&ÜK¡ "ôx©‚|K¢òÚe õ"â/UpÁ)J Ÿª Vm¾0K \8¨ø QÀäÂÀùá -(Ö* ,(5X`û ,BGR`Aâ—(æ#_Æç‚@„Æ/DŒ ý›QÀäqK^¢`¢”(Q0QΣ*ˆÕ×.UµY/U°R[”*ˆžK¤º8ü•˜q~Áâ‹Ó7Ä| ¾—*˜w¡¥ôƒ*xî——9Ô'/o(³Ãê3Èð†¢ä•/èóë0‡"áá2‡N.aå\^æÐí´)o(W¢o(KÀ…9”eØÂº¹ÒQPôJldT¥ "«äJLTºàÇFº Ì,ns¢B[¶õeåÊ®A…»ÒèI*dE· Â%è‚ 7–ºÒ±öI¤ NH‘.ˆ…1¯tA¤E õq U0¡€Ç¥ ö,Us¶Kä°B¬°«RLt;¥—X3™Pˆxï%.¶3S‰€ ³_ˆ5f„€öj~Kå>®ÜÀL7é%¦·14£êV `†þzÕQ›gdwm¯ý Êh£`·¹*¢}n»i£öúý:jË :Õ}õ-QrŒmªc¤†«äزÚ}L)ô®Ôru…¶èŠ WWÛÊ›3ƒÑG­–èŠmêJ wWÍëF_]©åê mÑþã5ÕæYþ`¿kªÕߨ“fÐSgýVÎêO·mýÿÚ¿±m3¬®¯úkŸõ·~§Û÷|žU~®ûûog‹»¼6bOW‰5ïé®°Æžb#ôô*ÖÆž¢Àzºê«©'mÄžîRmì)Ê«¡§«ºšzÒFìé.ÔÆÇ5Š«yOwm5=äÚ=ý;Ø|Y${¢ÿ`û÷éŸïÆÞžüxã~¼Q¾q¿õô· °ÍQþ_kià¿í_ÿ²øšmô­øš5FoYÿú×·2lÖ˜~8/ÃöÌ„+ʰYãg6kû_ú×ýÐÆ2leÿu¶i~ Á ž`“ÂÊye®6„T#Z6ua«_?/»a뱬ž*„TGZ=+|è{É¿0ªóÆY½Ò¨Q=µžï„¬ñý´l¤[Á)»z_¨ÃèËÕÇDÆêl¹ú(ÃXý½ú¼Œ;Ê0BQX}Ó§Újk¤Š2ŒÕczkä‚2Œ`Ý5JFÆæà5\?=-gz»FK_auzþÜȶ‚­}NŸ†¶ÙVÈÿ]ç;ËÔ¹xa1«úùî·ìÝkú*+ž^w.ñ1íLßæ|sÖ‰åoñç¸Õ›ïu>2ë”!ª¾ÿ¾§®å{õõ ~Û:£®eò–é!ºs:§au¸íàÕYÓ‹ižG•b`™òWïÊ…e7üž8…ô1Ìs.Ë ä.ë¡Å#t¶“wÛ–V1öÛú,Yå¯ûÆÄ*ÆpW.û@gˆç ŸÕ‘ßé_.[;»âHþêØ¾Ô±áø=b%É;Fyt¾N=>§“×®é¼;þ†´ÅëÜj—Á²¥à¶A7}Âj‡Å–}¡¹fUö–9`µÛ<庣ž|oÐYËùl>È×iÈeÜá”Ü©x„NãܶØ€1ìø{¶-6q¨ó~Þ¶L™çõ¼m °ÃÔðC¡”Ù䇚QälûBŸWøFyÛº`œgµsò«ªìœ¢K(y÷ü0ÑÙjÒ¾MEˆ.ÁǼsEˆ.Ác³m° +‘Ÿ²áß‚mé|HwˆÑÑGºm°M?ê¹ö…NHÍÄùléªmûDä’žKZ2btft=;•â1º„s»TÄè|Y‰Ó‚]Ê.÷l[l 4Œ_.[l¢Ÿê-c(eö ÜVƒ:íWÔVÛûÕËFˆÎלzZìaF=Ó¢mßè‚#ðê®%‡6~Uk’6îǪuCG ¼]Û‚6^|¾m°ÔÌóÚ¶ ˜‹ãÅómË€-Ë{^ âxñ¯Ãóìáôü6¶OtZw'öfƬßöf)]ÿy[M*¥Û|­ÄçR´¶1ëëyíÖ'fQvb7_*Æ;ö¼\˜{|›ÕPI·ò”wEÂ,Ò«¶}£*ýœw×¶o4Ží[xá o8ýÚ'º ÕúLÓž–ŒY” ‚Ÿtì¿S{í‚­}’ ©ƒ;B¾"A¬$s‘ "L Â^|‘`÷px -H‚¨´v± Š ],ˆ/ÍÅ‚¨Íu± –­½X…‚‘ z± ô²àŸ‰'spÄ‚KÍ ²¨[°àDÉ`Á _u° ­GÁ‚&˜`Á )5XK Nxi‚'¼¥Á‚««‰­À¹YpBH ÄÜ‚ÓWÀ œ  £{ Hpò³,4;Õ× ‚s‘' ‚Kü>-Gb ´G1‚àDÚH€à„~ 8Q9@pnÿa£… h{yÏÁ‰Ï§@06!2® 8a» œøž^$˜Èl"AD#„‚e³.L˜¬ µwÁ`/ŠQ¿ûbAxV/L¤CÁ ª]0ˆB  "ä‚Á„I~À JÓ]4ˆhIÐ rƒüŠAƒ¶“oC\«‚¹|uÐàBɶ Áå9ÏAƒ …N‚—O ­‚¡oB\ø– .$Ï .|…ƒK¼H´¸sŸrŠ>˃ Vÿ€Á…UꃋL)äR°ƒŠ ªš .”# Œ~Hƒ ÙÕAƒ 6Ö Á…jºAƒË “ º.vàŽïDT@ÊapAŽŒÂàB1“€Á…4ˆ€A¨Dƒ ëb .|…ƒ—ÃQp]…‚«!†$´¸—$QÐlŸ¾ Qp¡t¸PPÁ2¡àÂÜ#P•0ƒ F|²àêÄ/²àB±à‚%Xpgƒ …Ì*É .˜vƒ­åMƒk|ÒàB˜:pp¡JRààrCOÐàBA× Aí$TP4¸@¸‚Á5H™„Á…DŽ€Á…:¹ƒk°_Âà‚k>`PQBÁàBêDÀ %¾:’ \îñ\¨û0È=ƒ'Øø†Á£š`ðló†Á5É„Á‡DÀàB aðD1_0x¢”¾ `ðD)ôƒÇ¾Œ–W8Ìa‚Á³õ ¯žƒ'Kó\  ËI€0xR.¿.< Nq`A…HƒŠmÏN΋€Á³ðpãŽ)Œ`p,¬4'<QFÀàu:NƒÇü¢Ae–ŠO¤õEƒÖ’œÇ@ƒ06_4xb¸`¿„w8„ÁÓ±#`ðìôu±`œYðDu}°àiñ³ žüÔsëæÉ?É‚c!³C,xBÃç@dÁ³Í9Yðy}/°àÙËé,h-~«OŠí ÏÑ}ÀàéÙ[ƒ L ­ÅoÂài9G ž¸ô׃ ] O¿¾`ðĥϑ¤ÇòÿEØ‚}íä›lpènÚl€ƒ‹In¼1 ÜX²1ppOŠsÄA&§ÛÓ/<Ù¦Žqv}Øè…ƒg'¹N¿>,²ÂÁã™vøž² ƒ§®Œw ”W8xªå¼p0*'Oá‰3Lâ Öžì!G=àà©Òà€Ø¹º\ÔÂÁS›÷ë¢Á“›û¢Á“ÑûRU‹4¨²¢Á“¡êWXÅ‹BqжÉ/<•Óœ![,î³}¯Ë~%2ZöË/GÓɵ}*r±ˆWæùm:öØâÁ“ùâÁS êëÂÁS«Ç[*‹x5 qðd/8µ5–ñò]¢ÁS–Ã5¿Á*^ƒT9QÆ ‹Ž‰íØ.µ’UXW4x27_ºàqÕ“Oâí- ž$Qðì³°ˆhð\-o žÓq†NGg² e@84‘OV¦ë˜;Šxy Yð¤_|](xî§±Â^ šQð¬îôBAeϺ°_ ªþžHðìã-“ùÛ ?IðüÜ/]Ðî,H‚g§ºU}RO’=ïêÊ dbäz]Û+5pkTqÎo;èFx3Hpg*‚$Aæ  nøË‚wùÏ”ÂO$¸•¯Ü ­‹í%èlHÜQ’à~cà¦4% Ü(¾, Ü(À¸QG)0PIÂÀ ‡H` ‹ÍnZF…© Á|îM)ú_JÌð£þ—(…JLÈô 0!š(kQ…hY~‚Ö´ Y¡ÿ±x]è‰Syêt®‡þg-/ÔB]¡ÿ±â]è©Í$&ί%&*X’SÃ¥˜¤ºQLDG 0ñV’t¤˜:a`¢è%ëÔ†˜PP&À؆ `Ÿ ` `bn‘ÀD·–ÀDÖ–˜¦ `¢"-ЫÔ]8Ó$BLX¦ À„Šù¡&s ‹„˜°ØN(€Ñ0ñ‘‘˜¶¡¦Ø•ˆ¢Ý—Hóq(€ wm(€´#‡¨½$&âœ$@ºCÄBã—HqH€YöÏäR¤H\¿%@p£$@&ƒ†˜y2’!3\ ÞØ—˜AC¡âë~©€®_Ü" n·Ð©ZÞ: _?逿Tè€(+té€ÔKCdè.t@$˼t@Id’i耈÷_: ‘>t@¾*B*JÄwý¥ΗT%(/?É€™©ž!vf„ H^J»T@ªü¡V²¤T@:BÄz¢— (&• بùId|4T@j¡2·(TÀNê’ Ø™Ä'ÊF¨€ý×[ì$>‰€ƒ:!EÀÜyl‰€ƒ{Iì´žJì”Ô(Â6" É 0ØCä²y—8ü]q‰€Hí¹T@|v.$.pPL” 8™v(px¼ûR Í¡ò‡ ˆ¤ÖKDÓ¥b ‚KìÌ)” 8èö” 8ß$(Ñ% Ži.!°ã—!ŽÚ'ô¤Nö#1ÛP“ ¥ 4Ô@8ø.5´—È_«Êñõ¡ªxR§Ãkˆ‹„QÉóP1á6—8?pÐú)ïô@ëùë¥r“Ð9Žb b¡œLhˆÏ_b Bä—ˆ\¨«øZNÙ p_Q½'çç7úÆþ¡m®2jŸÅnÚ臽~¿øZNV€úÕ¿Z¢6ÛTÃH Wm²œ¬ä_}uÅ–»+o»ºBÃÝÕóª¿ÊkÔl¹ºB[tņWW«¼;Zå³›U^¬Rpÿ™¢kÏKx¯á¿St-÷ß®¹öL]»æZ«ý·æÚ÷õC±ã׺îë?~¾³ /×Vè+ ª±¯»¢ûº¶B_¯­Ø—Jª©¯«¦šúŠ­Ø×½ûRQ5õuUUS_±ûº·âÓª²jì뮫¦‡<¶B_ÿNõµmë±ÍÿaÕ×~ç…úÇçËñ‡×ç?ßÂïWêŸÜÁŸ=ýíêkÙB@Ïô/+°YÁ±ÿû§êhß*°Ùÿ³[ÿ`?`ûçû²kÏïg…‘ýǪë󥄯fëÊ­/ÞÒY© [ ¤kÃò´ÌÊÏÒÂ6–Õé-'ìó´˜ØŒ°n;-ÅBVÞr¦¥Ö²!ô[¼ç’‘±·§Åjr{KC ‡€©×ÓÂ1 ¡§¥7¶,o8ôòA–Y!ÏÿDž³¯xŒ9{Gãúóéâ¦s›µl¶?Pµ™‘·4?T=eнÅ{®ùÚ“#¨­ÿBüÄ62Ož–#-¿žuÖ÷ßËÓy˜yÿ´l$kc^›SK˜›@Ò²Œ`ñ7hJn=-gaœH¬Zž I¿J³Bò~´Þ~¡dž_š6*£öOd¶'t»pº@3ÂWdÕ?®£›xý<4l­‡âW®Û¤R€7ðôQöúiáéožlo]-~.½7&ÕO{Ô_HªÇMÞgùÕaãX éò '#ÀÃJÑø6¸‰†…¼Ð‚mάý´à–‰ÚHÍzZêøÅ"€Ø cXÉ#OKolÁ6ž1@~Ç3¤Ð/쵩5Ÿ–üôäg<9†ÌGyr žKö4g Á»=yKïË.ò–nš]X‘ðiá°ÌÓÂ!dü¾s6à—š¦è c´˜´á-x\V:yÚ…·Í²ˆ¦oáƒ\LlOKŒÀ{]uü¢ÏÍZÿ+\ò“[Ý1‚ŠÒÓ2ê/¤îãÇ]üæO PøF[–è-ø¹—•=ò–íWo'þíæE‹78Uû½ÅOxsðõ>-­³›<#@Â}C˨¿úk“YXr±áHöcx î³Í\-ª;æg°Øâïiû²|¹OoúßV5Ý·ðçÉÞ‹¿`÷;îloŽ€-Ì8Ù¶œÀJ¶ûórð}˜vÐ7èo»Â¿àD7GcvåÏ[2‡€•Ož'“™Ï=ê`2ý Ì?-­ÿ‚­pb›Þ~!'&­š‹!åÀF?çñ½üg3—ù^þC=-^š‰èÏé¥Å1M¿%cÝÜîaã§¥p?R¡±ûq시_DZ/2²íý9Îe ?‰žva Ç´ÑÂD?Áø…S9ž·AzKM‹>H  fŸ-/ô4œu Î&¸zU9üØ‚#@x!Û þØ>¿›OƒÖàW§OƒìÈÞ°› yú»¥ן ÛÊ`~“_Ï–}Ä<ú§¥ø,È´b´T$gcÕÓ§¥1“ݯxã¼îÓÀLþ(m¶à)h++{mŸ-xr¬Å'r‹Ó ÜcþÚË=†€_ÅcÑP¿¶0Sä}P`Á 6¶é8ööKl_e jàØÃâåëÃríðiÙ‰ÆÎ„~÷f=Ü‘|"düÎÙ§rq~ƒcX¼AGŒý´Æ–å7- ëô3t½â§²¯2\¯xtýÓZ”iÿ´p ÑËÞlÁMák|ÕF}Z²Ï†l¿‚gmDoñÏp¶¥ÁàúF‡°9ÌÉ!l¾£li0´Tl3i¦õÓ³Ï2RúqvÛgskó±›; ·>Ê#Àkb!d²6ï›U|.D{íÓR}.´nu[ .]ÜÆ¶4Æ´Ñ#À“¸8¼«º¸!쫌|ÂÖÞÞa;ùd.ŽÌ˜ÏN|çî>5äl\«ß­°ö/˜ð ú0#ôulÐÇ–€¾ èc ‘©s’"èóõ¯.æëœˆùºèÌÇïM0j¾\Ì× b¾ÎY ¯sú#胉ó‚>¬wQä§‹ú ä_Ô-d¦Ái”¨o½D}CôHêÃ"‘õ!^Ôs¨¨/þŸÔÇ/WPßà+êƒ#´Aÿ >Qµ¨o’D}ƒÑQ>A}þ‰úy£±îû'õ þp¢>~û¢…Ø7øSöÀþà>?5Aß$x úø èS@Ð7ù«ušÓêôM25¡/b„¾99e&ô͉‡ •êƒùæ$vÂM˜æäDæ»:óM~3Å|n@Ï›Eû|ŸCX-›á…ô†¾9 d¾9ù£ùæâ³C曋(F曋Eæ»ö3E$ƒÐ7Ÿ/Bß\ÄT‡>Ö è‹X©ïÚ†cP¬ƒØwµ€ûl/ Üwõ î›Kcè~WŒ$l¢Õ1¸/örÏ2Áo®O𛋿Î1àýIð›XT8Èorâ"ò›œ„ý&'RB?kÁ^ÃFhäÇ‚…A~Ú ä77gl$¿¹ñcŠü,ôbkZÓ’ßÜüÔ’ü®~N™AA~¶Èä77^B¿¹ñ3ý&ÊVý&jýæþD?Å¡ý'úD¿k¯a0F€™ ÑÏŽí à&Û‰-›¡ Ú"ù%ÉonN(A~ðŠüà›ºÈá­ ¿„'*È®è‹ü4ÿù%NÐE~‰·„Ð/‘C…~šY ý'·b¿Dä -†€¹·ØÖá‹ýgìb¿Ä;Dð‡÷ þƒ5†@üéè‚?øÁ.ø‹mêð—9*Á_âÄTô—yÑE™l úË•è/sZ/úCÙ…‹þ úËb=’¼çýe>/¢?†I™t úËâÁFÞ¿Aô—ù¤Šþý ø+¼ÿÚ$F0?Ø/óyûéÚˆýPðAì—ÉÅb?ˆè§ž!o‹üÏ òc 4ȯ|#¿Ì—‚È/óÎúa]Œà$ô+ -œÃù•½¤è*º!€ê8†<ƒüŠ€ àÄŠ¡A~«ð«@ô[!#‘_%¯!‹#À+ÖÉo•Oò[•ÈOÛülÀŽc¸éE~Ù÷úõÔ‚þ¼jäM;ããKøÛp þ¶ˆŒð·cî„?X øÛ“|CøÛš’þö”ìúÛ“ÒŸ¯;ú‹þ,= J‡°H=¤¿­9éo/ŠNL% ú3—>Xôç«©ÿã¢?.üô··Èìd- ;°ÓÞRø@[’éooÄÌ {ó"þ˜iCøCRÙooi„`?æ5ûíÍi;ÙooáÏí[œ?²ß–löÓ" b?ç‚ú)EJìw·L$/¸3ˈ˜ŽNg ?9°¦ý¸,…ÐO+LýN–„7\§:trºÎð·…d„¿Íh”ào‡¸pv‡üíÍÉ7á/züc¿àO+WüÅÏ úSœèïºZ¤?.‰ôwô?.éïÚks ;Žaò—"ýÅoú;çstzZüO°óý˜Åèg·4°.ξÑoo©À¦xˆ~{ ÑÒ± QpóW¡ôÛ¨½ègGÄ›¶i¢fý,Õç~›\"ôcÊP ßÆý˜Dè{9úÙ~ýˆ~;@è·_ÂD¿½h- úíÍ€ÑïÚ èÇ…gýl/ èwc`8hÇdÀ&;àW^÷›\èÇÜõ@¿½8­"úmÙS a¿Ñ+åúíׂÐï:úÖ:={ý¶ÂìD?»hɼ!m}`’GôÛƒÇ!úéÇúé†úí%­#@†N WŸ öÛ’È~ ~{!0Oî‹ó/LÅurîÓ-.î³oö1I8°‰Æ}qÙˆ}¨ÛÔ·ù¤>Ýš¢>.BÔ·…뤾8”cŸ^"¾¸ƒˆ}qgûtË û˜„Øw°Ïözk~ñ‹û¶ ľ½(|û˜úØ=7.D…+AìÛ Sû¶„$b_ü0ľýf¾MwŒ˜ Sói2%æcy¦`¾$™/.:™o+Óûû1&ói&æÛƒÔBæÓíHäÛK'äÓ|PÌO)™o/Â.¡/ÞE„¾¸“}\m+ Éû„>ÛB" o/СoKN1ð©Oß=Qß^R õmúD}q¤¾-SÂŒ! ~@êÛ›çãØ·ªöÅkƒØ'öÅ£@î³l0P3ý0Rüô JñÓ]!ÉO¯F‚Ÿ½ßà·¥á/Ž$?ÝŸ’ütü6¹Å|r2Šù¶Zš^r€1ß7ioéióm:¿Å|[¤Hè£,æ“@Ê^Rò•=šÀBÙÓ#-e/óâHÙK¿ÞÈÇ:Ú—°GM{J=”°WøkKØË¼õ$ìeåØ%Ôo¶JØ+ôJØ+´õJØ £*F_K{ÂM {•o. {‘8Ha¯ÒÍ*a¯Òi e¯r..e¯r.žX×±¼™o+ÓMÊC-¡ì)h+e¯Iý£.Ödá¤.Ö9Ï–²×øÉ—²×i듲×lC'°enðöPÏùö"éŽÂ^çäHÂÞàtNÂ^—ƒ3€9´„=NÎ¥ë)õMºÞ9HÙSš˜¤½Á3†´7d½¬èSVI{Êî’¶7韓¶Ç7Vh{±Wh{з§,¨Ʀðâžö’¸·„b÷&Íz•ò$n‡K܃ v‰{ õÂñ➦Ô÷Ë¿Ä=ÜÂ÷øÊºÅ=ò[ˆ{ô}™œ0Y—¸'•@â®ñ%îQ" ±‚KÜoOgÈ×—¾÷ƾ½¿É{›¢°O•H_ò%ÀÐÆ°I¨{ôkvZwÞÔ·eTîßäIP_ø^H}V½”'ãÔwꙢœúl/°˜Cß)”Š–¢Ò©û¥îɯt¾s¨—ºwúA‹/-¼­A}ÖBp¡tjþ÷Î6/yÏZ¥ >Û«¼ä½3L0^‘Õéåé<ƒ'òå5½—o–J_“Ë¡¾pýW‰’Je6&ù±gä"ì3[|fú´(9g —¹¨ñO´¬Iå {P ÷ÈzYB">L«À¢ãsY%Ì>ÌUeÆðxEYMf Ü«C(Æ­·8„èyZ¶*è`Ÿ¹¤½ú0ךT)q =(RâwÙ©SÑí¶sSI´pŒß?D¶˜}YK- £NlӲ¨~už+èÇê›aÔ‚m8&Ö2±EÇÙø"iEÇÙƒAT÷7Ôšú;ˆZknÓÀ6áµrôþÔg*HÓ}B?=1ˆ:±Mß ¢ú;¨Ö±èGõ@A­SkÜ6}aŸ„¿÷xõÑR×|~œ–C¨ª­T†P=ÚTm2€©»ƒj‹àj5Ž€/¥§‘-F;k‹!TžÏœ ¡â¾nk0„Š»¤môâïøÚ9–F©ömÎØÆÏÆ&Àˆ¢z'½Q}à½e¥âøÉôžD]Ø‹C`¥–Ú9Ößz˜s²|_rÞãaè»3Œêî”:¸,n¤‘•E‰Glp¨JZG-Š£b§–GEKÿH¢|Z”Dé1è:†’(q…‡@›AuOÇiÁ/î+Ÿ8 ®úY=ûœÇÞø»(‰¿Ý¬J¢ôomMñE<‡³Ó¹Ž?•ˆtŽÅ!át眒Gë¼Û‰½b¸ùlI/:ïÑ’e[Ç /.£‡ l_çü:]û:sH~ÉWWåÀ6]Ù-c)ˆêg¼¦²(q‡®5E]8›Ýß)uÇð*ÙÊÕVõb~Žß»"õn¡—&ë=>döyæ6اG&%öJðÝs2·Òe±º—ÒqSØš^ÕÙ«YAçyGD›-êõJ:l©&‡úÍßÇ0üφè"þ·'†ýóÝìÓÌ*¶Ka`…çŸÙëRlÑ/xK»³Å¿²ÍVôB`ØÇc za<Þ­­çµîèr³õ¼ö} ÌÓw­å®Ð¢ÿ®Í>ËHvíØf,P 4'G„MÖð1¾å8o(<}†9›Ñxõ[œT¯jö1ÎÙl1/DOvêÉÿF¯<ÿ³Ù'£öû»YD #ÊhYCQmo8Úš_\oAØGk>-ëGµr`§óÛÒ^Ü÷ƾù}~!nîÃùâ>°˜¸æºÀ¾×Á}ì˜Ø7ñpöM‘±Oø(ì£Ç&°³_b++ûhC ì[x Ä}“š™¸ÏZpdpßäËTÜ7ió÷M$2 û&“‹„}“²š°o2ï^Ø7÷û&óð…}*ÿ#웜ˆ û&'âÂ>•ö©Ô¸/¶!÷Yi€UŽòÐ`C@“Šðˆû&³ñÅ}“IÝä>¦L÷]-*›„ÜgÌ6$4%Þ¡¿‘"À%¤ü’­¨<4®—Àë©]àÇÂÓ~::ÀOá_ÔüèŽ ðCÎ~p_â_ÜG“Up_úÆ}‰óîC“¤Âúà¾Ä醸/¶4oáØä>ÖÜ îKøa‚ûÔ‹¸/“]Å}øÒ ûVæTMØ—9ÁöeNÞˆ}*º#ì»¶2©7°oeN%‰}* $ì[t½û¢—CðQ’ú¬´fŠM}Ñæ[™Ó2Ÿêÿˆù¬\È “Å.pf@>•+ò­ü‰|‹5Æ…|*Û#ä»ö0-V/ò]Çò-|eE|+‹.A|± G0p.{ÜÿMÞ[˜÷¢´·²ø´g¢%NTÑâäùo«Å@J*â$ØSÉ&ÁÞ¢Ø Ø‹õkhÉ*¯EÞ**Mf íY شǪH‚½k§¦³=†Àn@J‹Ó2Á^t ÖS¬»õÌ® ¸âX H°·(F ö®~{ב{‹ÎÁž  ö®žÁJ×ù€•TüI°=;ì][ö¬Äc 2ÆÊö®½: ©:Ò'ïòÞuô{¾ÆàG'ïŵ ï) ¼§RYâ½Uœ#ïYùÍ{,ì/Ü“eV¸·Š q†­/Ùj1LâžbÕÂ=- Ü‹ž‰{×^\¦š@Øǰ{§—†ØjØ&ÆP_¸wŸÍR*Dbˆ{Ú†¸#î]-18EË÷q|'管EQ|€ €ï´ ×k/⻼•8^Äw ï::˜/rÉ|×ùä1äk lQFbEËÐB ï´8ú1 ¥ÄÆ ûÎ6~-€}gP^Í£÷]WçpßÙjìdh© gj¥ ²ã¿¸ïê†r¿*¾‘û®½ê5—Ë¿<šÐoÅ”ƒý,V¦'éýÖ¦¨AöSªˆØÏBð-[¡|ð!àomi‡”Ìb›­BìÑ’ ±¯·æÇ"ü-‘Èà@d § ü"û©t{h~ÑéPö‚m¨ù©Û8lq>r™NMŠ_´•a§W•«³ Þqü;Fð!ømåˆd´L%ëU%øéÒHñÓɬ‚O‹BñS?Rü˜Š_ôCÅ/x±óG@/1†ùA~ÑBj’~+ò㯠ðÓo)ðÓ ü¨øm¼)üXŸ.Àoãà{9ø±lP€_´Ä &ï§âÇœ© ?öä'µLä§ hŠ1à‹—b ì‡ØÄ5‚ü˜–ŠŠBð«à§–KðÃGüü¼à·q¹õ>vz6‰°!΄IjÒ&“Cq’ú´¡OÇô)]âô¡„Šú4DQ_ôCìÛÂIr_ôCî‹cŸ×üØb¡Lê~ÚCà§}~:ßz{ÅгÀ¥¤üX&ÀÁ© ¿è‡äÛp øY€~ºÄ~:²àïé ?õ*ú‹m®¼µ¾ÅRcA“ð/Zˆ“ðPâŸ$~RáIg#ü‹mˆ:?á_lCþ‹~®1|ðŸÎXügHþÓ8€úe€Úb\cð†oCÿÁ ø½ÿôÛ ÿö§Öwµ\#@ Ñ)ZˆNêYø-ù}=…ÑCà>×{š QCìš ±eh2„k.ü‹m®1¼å>]@ÑßþFûƒþâïZÞ?”àO ß°¾ @ð§ÛQð-k|à/¶YšÒACË× ¢]cÆeM‡¨¼M‡p,Á_´´ô~‚º6%Æq¤±>F%ü‹~×ø•ðOGþéX5ÆÀ–Ã9ú¿ª”Èwj]ÈWdЬ W[ˆ°EM Ás(ä‹–‰×ÈW¾!ŸZ„|Œ_ò1ªÈW¤Ãq ˜Az$¹Gx$Ûó]-B/Sñ¡þáóD,  O›úÔ ;‰ùÔ&OîÃ`ƒ84„Å“ ̅Ó®ˆ wĆ€aqú ·Ï³î•oO]Káž~Eà^lqyT±EŒ€ÛÌõÙ²â^[‘!VRd¨}8”>m#à+ŸψõŠøb/_´\c`Ë~GWƒùâXócBŸÆ)êÓÙˆú´Wù6Q_lCfŠR_ìEê‹mH}ÑráE}ñ÷šï^I}ÚBÔ§1‰úb›k ±o#õÅ6d¦«eŒIÔ-¤¾hÑp~ûõ¬õE ©OGõIæõ’l‹|R_ìEb*bNÖöè‹M}Úd¿{í1ìÒC0ã6!˜q2ŸÄ1_‘y“Ì{}AC0£ßt©zj~Á–Pý¸Å5oÕ›„ì&¾d¿OîÓ .ÙDyÉ~l‰!xÂíï×L» Ÿc½Ÿëdø•]†O85Ãð™É{2|r›p|R<¤ã“˵†ã3ö¢_’i áøò€f-ªZ>ŸC®På*ÞªŸI»$› ÇgôAÇgœ Ÿƒ¦Á#À˜FŒ ËçÀ–Ï!L¤å¥jÂñ9”ا!@Á‹!ô·î§õqÃñ¢ã3¶¡ãS—BŽO jÅê‡ãs0, ǧÎPŽOJ†OÜ90î£C(LýÓÊ[öÓÒÁâÀ¸×ÈqzäÀè‡Gß1n†Šó!Æ]AŒ»Í9Ðú¥¸5*lc€¢¼c ¸èä@SÈ\a NF(/¶0P^{¡4pa .)0PƒN–ê‚ uÂ9F@3'JO‡(P J‹¯½@¶Í;Ïo²ü“(P‹N‹­Œ7ß‚' Œ“!j“#Àü › âTˆ€1$"ൠ0~•` ÀC¯>€€qy‰€± 0n´À…ª× ê â÷'^Ç^=¯~€€ñ#TŽ¡Üw0ΎׅÈwPOœPï žvàupðS €'L¼ZöëM#Œ³!ÆÙ£2àÕŒó#Æ¥è1îuá­û]g¼¶êëŒ'nÄhϼƭü¤gƒo"àÕ 0î,"àÕCÀGŒû„Ã$Æ]ìÃ&F¿3†@OgŒ ÖÓû-AŒ“!^‡^Ç>lŸ¶Íi Ʊ €1JÀk‹ª)]~àµMŒ S Œ!`¯±>^çÀ«e÷gVýìk @®k ЋfDx×9Æù¯}º&uì·kR‡‹¾c Ľ3"ô¼4#¢Ê¸û{T@=Ò@þTâ? ü§§ü§‹ÿ®=ú~ÿPâ?œøïêçNw÷÷ĺ×ºz¿«›öz7 ÿô| ÿâdˆ1(â_\âßuzûcJ'ü»Z²æC-Eó¡·ì§Lú‹A9ýé‡,×°ÁXï{OôwËŠ ÝÛô?¯j<é§«×üjÕArÕ/ЧY•­«”ÔƒwÊØF­žh›»xÚÇF±[Oû¾×ß(žÖŸ¯ä»¶˜Z®Úbh‹ÒCl¸Ë”õ•ò»â™Zíê wWã!Ù«¢Öÿsµ\]¡-ºbþâY·_6¿+žýE1+É[¾Õ”ú¶Á_Bû(Möýîi;çëÞùãÇ[åÔ÷}o…žî’cÖÓ«àzº¶AOïâeèé*8vzºË±§Ø†=½J—¡§«ÜØéé.6Æžböô*\†gá*6f=½ ’ñŠmÐÓ¿U¬MŸ£ÿOªGöïª?>ß;?¼™þøñ¾ýx[ý|ã~ëéï×#³ª€OÓÛzdÿü¡Ù?ÿ£UÈ~DÅ1û×ýÐÆ*duü‹*d;þ >UúløÇo—ĤÙï‚—Ïi».~!¶i*¸é®ù¶{̈üû¶‡¦t(@°gc¶¹GÚ^•-ìg•;Gï))­Ùæ=e$ô¹ª§¢ˆ86 ÿwtRUÍÊÝSS)¨‰mú`y!t3:k ybO³±jg¯ô„X!–î-[µƒÎSxŠ“~jç) qŽflkä±Z'ò(@eÝzã¾â§Z—Bt܈p•R‹‚ku<#~˜jñ¿ž‚³z–ÇÛbäu[³:jÔÝ-ïã t4D¸Ö§.å“×õ诅ñå¼ü:ÐßpUÌ¢1 S(®fX'Oá­NS¯óFx¨”öøæðÐiJ [7$"\å}í©³ µÏ]xëä)¼5ð&Oá}ݧÎöruo7@=Š —5GèR¬7ógãOTµ[L§Q5¼–×I­µ©žŸõtÄ)DgG#<…âÒ0ízFŒT÷/oWéñK¡€†¶y[œTs‹ÊvÕ¿‹_ðíâ &À³vñ ÖÔ–_5È9è=¥mÖaLœaÛåŸx­x0x1㤦Wk®‚~S#:…ârmí.X •7ñµûmñK õœj¸éOë]óh“†ÅP¢2AµÅÓ¿FÖ={iB6ÝY³KœBóëÅü£ Oþ†×rœ’Û06¼–qJÍ…/ÚóŒø¦SÛ£@Ã^ñG'Ð\oF^ÖKH)ÚÓÞ8§uƒrVhè’…sºÝV¤a‚À9zlè’?ËPœ±œC廩­9ûG„ϧþœq>Å ¾ÞÈ8Ÿâºb ¿ÎÇᤆç÷åž´ _Ê[¡èس×óš“KŒ/Ûn7¼!…ö]MµàH}8˜çC}ݲ¾+‹ñûðR5 û®îN]Æ>Mü)b^{CøHìC¸Cd¨3ÀûZ#<ƒûÉ«¨#Þ1™é^O«Î;¨ïn‰ðÂ>ÀU®û‰(¾aìÃ{ññîîöˆÆ>¼‰„¾ûuF±-É…}7}¸oÆ[Ûèz.¦Å}hÁÜG,¬"÷¡å¡–mâ¾gÍvŒã˜ûÔ£-ò¢Å!ׇâ>Äâµ÷AÑ"]àm‰µ‚߃`¥>EðCèD_ÎSxÞ™‡ƒS€íM+ýà¾'îÉ¿oìÛ{õ=¯ÚMúžærƆ>¼Z †:úîz—†¾§º5§¡ïÉ|!C^¶ú•}hÉ((ô­›Oo Bß3]‰Ü>9ý?±©Gô ~hë¨ïø¡_r²‘ü ÖRÚϪÿ£mxpðù7úÁ·'úá+«Žè‡ÝúÅpÏ~¥YP0ú•|Ãý"œ¤½œ æѯLÇtŒ~%›¼ýÞË=4Œ~eêÑïrΰÑïÅ™ Òˆ~% ßšý°8Ñ­ð‡ÀÏÐg„¯O"¹á=ë8 pºŸüÁ q ‘Øï±pbø{ß×»!û!ĤgÛìWd'HöƒùÐ\'ö+ŠgnôkþÁ…~-ÍèWL¦F¿×²˜ÑÛˆ¤…~¯îD?7úÁ¾èm¤¢w·ô1ú½ÍÆ­½kFûgjmükÏÿ¼äIüsʤ?7ù %üMßÚ á@ÛeÚEƒb?¸:´ã¡BçYûMøÕÑùþu¬5rGÑïþ›YïJiL𢕴FDNÓ·hÒßt© ÓD9sfS©sm@ôë·ëšý¢£ãývëÍ­õ¹ïÁûjjpTûÜ}b«}Í+b«}pí}ÐÛè´­öA™–þgnºø§¤¾'OÀRßóXˆÔñ#$NÇÿ¸ævr_qUÙä>zE‚Á}e¤B'î+Óô`î+©âšûÊpˆÞÜwìGÔ‘F”'î+nÔÜ÷:º¹Ï͘7÷5…¯“ûJ"› éMö'÷•÷·Ð×1÷è#¾âÙ<¹¯$Y™ûJ®éÍ}Åßä¾â¼¿ä¾âªõÉ}Å¥»“ûÖ§.ém:…µØ…ÜW®/÷•'ÿ&÷!kä¾ hm#îC†ŠHPÜwÍäKsßkÕ+¹Ïy;›ûžd:ròcôíæ>œ„}·{ZûnÏËÂ>w0Hê»ònõõìAmêc^Îß7ô¡Ã¬¾EÐׇK¹úúÈ›^ÐׇZ˜ùz–<7ó­þIàƒ$®‡ €¯§çÖÀ‡ÝR>ê)ó­‘H|HO ø"¸ #ð¡C§$R_oÎÅ0ðAÂW¬MÀ™_X-àC_‰ø>„6tƒð¡5½"m¾±#m¾Ø¦h¿>lÃÝÊ…8†ëŠ÷Sß¾7É{AÙ–É{#×öâ½µã;Y.h)F•"ï=£eÀ޼÷ŒÚ-Dølhù0€ïoªhC§P~ð­‘Ÿ€/Œ Öð‚–¸õ¹¾5bŸŒ€/ž}ûÔ9Ü®ï%âãs*L Zzà_?/\€ïA×äy_˜-žø:u¾5r%rñ:Zù¹6bž-ÕÁÂ^ÒÙr^Àa¨“÷xʵV'ï…wáĽRh©NÜ[#.̸¡Žë”ùÖˆSA„{´DXø› ™ /qï™ë§ú÷t_Ö2œ¸-G‰{~å*U/poQKIü Ü‹,;- É{¬ýcë|rÒà½ÉRV |kä²PBâ‹[ø>‘/‚[Vy£¾^çùÖM¼µ@:vz«Ú&€i\©)ò­›xè5'ä‹^9u¾¸õ%Ρx–äãm¯?c„¸ ÈƒÄwýÐ6A|q׋iD|—;ùø®+Iße·•y÷qÕ¡‘•ð!Ëä=|HD*Þ‹m,í]tÀˆGÉ{kÒí@Þ‹X˜x”¼÷¸DSòÞƒZŒMÞ‹ø9ò^ÜŒºAÈ{ëfLö%ï=Xßûx‚–0À‰{q/ZÉ Ü[#—A¸·&Tk½˜t­ò0ÿ“÷ÖÝè—½xoäOGÞ ç”~ò']^.߃¹·bºñ'i/¢¾zH{²k!îÅ-­‡¸7ô¸÷ž1“"‰{ú—q€´Ї\DP|xœ-øîRS0$ð!ÑC‡'à9èplÛ†õ§ùgUÇþòzªu†¼l5·%R©Ƽµ 1Ô ó†£‰yYÕtsÞ{6ç=©'Úù¦ÏS2ßÌ5¤e¾|H曹±Ì‡¦wr_êf.Oô’!ôÒñ”¶N[W6è¹¥A²Þ•Ñúd½½³Þüí£òaa¥ºQïö=.Ô{,%™ôð ù’–îÚ­HS©>eRj^ÓšôÒŒ±}¹„5ìaw u©'íáÝ,3) /|M{oZgI{>IÚ{ßÔE{µþL{Õ‡¤½æ¶=I{-ERÓ^š’öº£I{=u Ó‚ÒÚt#£á6vf¤V¸—½Ó؉¨–<š2v®ÇM?¯·Zâ÷ÆSs·É\ãݸ‡’Ľu þ¾i/Øù¡½±®±‰PgP3€ñÒš*ô£<æ™(%>¼[4"‰¯¾þV‘fׯ·NÇŒéƒw£§MzäwÛâ“ ß“&¹$½ÍzO ÿD½µ…-›zïLŽë½o2¦¾7•œTøöÑIá{MþøZ‚>HX¡Àkƒ¸L_,.þ¾YoÔ|n…{£ÙÄCÜÃßF9V :£RªeͨT5ã÷0R>¸7¦;L÷ð’¾>ú^íVu #ÍÌÂ=è˜5é{@/A¢ô½õ’»Ü›=£WÖ÷J>ÇÂ=ø”«²¾÷ÞIwd%Œ”ïÍÃ|IÞÃÊÈæKé{` ‘›5Ê­’•fOo¥x/3Óyo¶žûïá3ï)ðQ‘ÔÖ(ÏLïQ±²Ô÷žŸm×í¦¶©ï]îšúÞÝsÇøž|ž%ðA´ÄJà»¶|,/$S!!>¼#D²À÷ZܶÀo_øÚoVüx 89+©¡†ÐHúÜà ºK߃‚jº£¾‡ ó^:…Çúm_{¥¾‡bF7ß|¶‹“À—M ø²ƒw_w犾î8bß0@'ðMŧ“÷²K¬yofsió^˜çµ›`ÖltHÞÃ>t9Å{3 áæ½™]Í{øÑoíÅ'P5Y›÷¸fûûƽ9¶zGÜ›k­&$îáð´îŲNŸ"îaé'ƒp(|È⇳s-ò ˆRøpÛ©ð]w^()|¸½¬ç‰÷ZÚ… |£nøÜiXÄ·Ž7|E´„Þõ²¡ñŽ×Oâ‹sÒRÄ·þN³'‰¯›°àÓfàËt‹>$O}¯¥ülàóGtüébHÚËîcI{ýþ;ã`ú©î­m.‡B÷b¿ú['n"«{AØRIKøåž¼‡ß@6_É{\²ÿ=i¯ÄŠýcí¼Þ‘ìIy/HHÔ%ZN¶¶¼–„µó¾fŽ@ßC%œùÑ÷à®[À‡ì]q’I …$¾xæõ)ß›SDŸ3ø“øŠÓÞL|QQçcïŒ:<ØæŸ)8vÐßþÜO|<»f“ Ù–ø0x91ߟ‹)}]r žÝ-”Òà9ôXoçüIäÛßžð7œ!¡Œ>/¥2¡¯§è30|%ùÙ?²Éïëîœ#‘ncŸ¾fSŸ¸ÊÔ‡YŠB¦»¦ìfê›^›úö"™ÔWl‘Iì+Eçkê{33ÊÔ÷þlíìÕ½³’úÖÜgPÔ×îüjQ_wà5© 5¿Ù|ø]¬è‘˜¦{P˜ú*¶+󉿛XÔ‡:eÖæH}ñi'Jæƒ åc패 0PÄôj¢Èd¾jYŹ|ë£×ù°Hîß\¾îÞ²™Ë—¶¤D¾mgc."[ß\¾YÓ JäCA•ëc휷ޠ™Ë÷xBÊ\¾çg䃳ÏNIçò‰Å| eÊÇÖ‰ ní#ïÁâ¨ÝøzšæÈ|Í¢’ùðœ èÄ|Ù:¡Ïœ)â«÷7‹/’"eš4/µw䥞†]_ß‚ €¨s&ñÅÑ l|;™ŽÀ‡Û]û°¥s |vxŠöð®ùH{84çÍéð1AqÀvNß¶ {9uö#)’íµi¯$FÒ‘ZSÊÓágâGÒ^MíÚ´÷¦QÁ´·ö#«¡Ýœ—2’ö𠉸tÕÉI{((N)-’3§™öºoÓÞã——h¿HNç0UðòÔö¬= ”î–FMÁÞ“kØÃ«úÌá ´Óì‘°×MA†½' ݆½+ƒ†=¬Õ$ önk‚½Û‘Ü„½+†½+ASâ.Ö {±›qš9Ió'ìÅM¯¯²¶—õdRÛ‹bUÿï¶´7Rßµ´7Ólm~@Û›þ^ { gš$ìAòršŽ­ ÍZ<þY$]o¢®ä zÊåÌß‹z‹fJž<}J ×Š ‹)ì¹Í÷ö<]KØË ”ä¼êêÉyÝMo“ózúÿÌyÙç;9±Éo¤wf*ž8o½ôÌ‚½êþœ zxYˆ2u—Ód%ìÍTmzEëä¼Ë}^’ó.''çm£9ïj©Z™t@;Aïʵ«A‹ö/èÝ)Nôª&ËÍy¯mp!ëGóO"’ƒC–õ€^óļ'J~ ê„yk¡üœ²^`µèL‡:Óˆ¥?¥nJòŽMI¯ývIyï7…ïp¹‹òzžÂ»OA `ÌÃå} óîžþKa<\‚CaÞSr?¼'=Å&½RÓ€N>¤3ƒo¸zl‚l\²d ôJZF zi›JÐ+ùÕÒõfIå\ºæ#}e=Däô\HÖÃ,"ø2è¡$ãôn;p,ëÍ9­z˜;íì$è=™¿+лŠU‚Øàý({ØB·}Ó)Ì ­ô0y‚Þu=¿}½œ’v®àjJ§ªÒ„‹si|1#<Q5%Z¥Å*–ªk‰µÖ‹ãÖ¿:Ö©5nSÿßš wõ¿¶ØÛï-~ï3½¢Ø÷hò/ã,÷ôóþ÷VÏ5¯¬œ²¹|”ù×±íýäȹØ%»'ÿ:÷£±c?9öó<\ êªù¯c?ÛûÉ‘c?ÿ9ÉÙ+æü—êNEòÎý·ªjOcda1þóA1ŒYþvÿÑç?áP{îܶÏÜïúçõÓ?QPªf¡Ÿî‚5§—>uOþÛ/w`‹¸ÿןń‚:Wûó9÷±·ò~έ¼/TEÆbuïË#ç¾öVÞ×¹Uî+J s_ùì+·Ê}[í;ž1«½¯'£X{_{+ïëÜê¯Þ31Õ®ÅBhƒßBeí,TæÒb.T6ÚOºYû–*ûÃí~*UöGÛý\ªì—í~§TÙ?šû~o¦ùu¶û·?˜±Î-þlÆü‡¿ÞÔg]2d­ýÜýxrQ 6Ãö·ÿóùZqÿíú—…ÿƒct]D¬:LÿíÌÁýßÿþ/ˆÞóÏwô¬¯Ö›?Áýã_qˆÏàM‚:/Ííþ—µí‚Þ«ÿíþ— õ¾û_÷üoùßÿ?T[ËŠú·Ëýù•ÿÿµÝzÁŽ«þíÿÌãü¿þŽ‹·¢Û¿ÂÀW¯=üÓUß*¢ šŸÙIå÷«¾­µœª¾á_.ÉöÿRý´Ñ³æÛóœÿÜÿÿ§Uß°ÑQõ­åà¿ç¿þkþë—ªoÜûQÕ·µ‚SÕ7 þRõmý·ü×ù±¬úvÿãªoU$*¬ÛÊ ç¨÷jˆÕ߂Řk1rGhÙZûÄÓÏѹcyެ²˜b­9ò†Æ³Öí¿-$‘ĻƿáñÀH¨ÇZgÆ_3^·-•AzDü?ÒôÚˆ‘—_Üѳñ‘'ÖÒ0$•Òb¤Fü  ÷á~z„ˆÄ­>µÈ)ÖlˆÙbÞD©®ørd9à.‹V±$€l1Òc^FøzN~`>¹â«P ¯yŒ”˜¡"Úº–¶Ñ—cë‰OÁQÛôp)TÛT:Òúq9¡Å› fÙòr“ˆ¬Dhµ`'ζœ/F*·Á)\øêµ’ˆE:ìëúÄH Â…!yA "cwyÄ€°êA°8Ž!µ‰¹ðPyi$-k¤ÆÏ‘u׺~(‹|güh5ê;ÄáÏâ»:Cû ÐxYAˆ—9Jœ½oMF¼FA)8 ô/‰kàÀQTWø^à"Õrü-‘¦Œû #OÜW`Bƈ¾ 5X^|ê&)A]³âàÇ y+(õÁnJü^kg°PfMŽ¿Ý Û]WtîÀH£È ­¾ôø¯è}´Z¬#+ :„u0P¦{zT¬BCA$|p k†âÀŒú" …®r…U<¶qÄpœ´ˆ+rä‰yƒ1®U)Q³ QéÁPÒEוmÈùw[‚2;>Ôô)DÉGl3)Áfƒ4$¸©=kŸàpÕo:Ã\¯°Ìˆ!5¸ˆ•1¸vò–rx‡ÊÕÂM}‰Ìë$Ñì…Á¤^®ß/Œ¡NML’XK“u«ðS5¤¯Eæ¸çfÕvßz6oTUZ“ ö|ÉZÚ#ºÙXù©R²~'>5-RB­o´tKø¿vg‰Á;”¤†º_®‰vðp™G<µ ÂkdD/öÛ%(Õ(©ÕPïÜUÂùž º8x³Ô'.WN}ù­Å&CG 0\Ý™ú˜À[Ø=ù¬ˆ(7(nÕJ„ÓâB¸@׋¨!82ížÀ‚·¡RV³=‚*ZDh"Cã¦õÇH³;:²ÿCßpl&Ü`í­ñBˆ¸FX•p-ELGø¦Ú{ù‰r3?~áì'8Çñu~m›F‘Êhh§ß­ë׌™_Ü/ÞÐëåÛ©Á˜^4jï³=Z¨€ EæøÈ#3jÍà-\€q): Ìb›‡?' ¨¬ûQ½"˜A× ŽE‹îQäŬ)¼µ|DºÍú.ijy8D׳Ôêë©í!&¾«Ä¢#o8]@¼¤×Þ{ç1ã%ýà¼àÍåwE-\|®n(Te}9Šû󂤒·Ço.E¹QkÂÂÏZƒFë¦5…ÇÅàíbæúªfÙ!Êól>DÇŒM4!\¾nûÖЧ1ŽoiLá¼³ àåÅx6ÞҘñ¤áM‰.æðÞä²™ÑA«EÝMîݧÖ7Ec|æApqMáÏJhÝ„)|ÈRþÀg‚!ÖÂý.ôÆ'üW8P ªó@z¤ñà\(?x;?ü–¢mf´!ÃCýÆ›ìAß&LàÓ“óƒÆM˜À×bÏóƒd LàÐkù „&p,~;?õ†í#5t›0ƒ£‡nô‡Xçø*áäÁ úÒwÅ¥z¢}LþWå~ûãGä:¿<šŽõ¨q+©§Ð3ˆëËe܃/¾éõ<…ÑúÁáøîí³ ¹òI}к S8jàð×.¬ …äòÇ#Q@¡‡‘€;¦G,gòËq#â«¥“ ¶9Ùc„kf¡``¼zßA¼œ´‚©Ú†(Xg®½…‚ âûƒ‚ØF|/9âùÚ,€>OÄ6•²XL£\@¡  *Ä÷4µv" ÆŽ©3aUÛ&¢`2°4£ ákŠ¡ð+µ‚,ˆOµr ¹Ýö1b)qMC ƒš›ÄÞÚ¯¼— ƒ*T×i<¶! ¹,ß–h.#ŸhðÎçÕ4ˆˆHO4ˆÁû¡AÔ[’£‚0x7?x†AT—ëB0xó­tÀàºFÝŽg ²É QûCÖÁ Öƒrïë'\GSøœïüÉ ƒkW™ÞeD2ÍýÁ;# ‚Á;)Ý0ˆÐoRÃàSc3 –ê–aðÉP“a…\„~‚ÁâÌ~³`Dö hbÁâWc² Öñ¼—Ì‚¥96b„LÌ«c,^ª™aãìkÄU#? Q’`eD5²ªQ°\޹_¯æ’AVœ*Ì‚/ΊT',6€& ºÆA’`I¹\¢N‘ ¬.|]ÑŽs’Q«™›È&|qUŸ(ß(· Ö¡×b¢`Uj‡Q.¯ûƒ‚(øñ…‚(Õvó„‚Õv‚‚š' ¾‰cFÁ&ßq’ \‰1›$ âzsD(Øn…e_ÔB Æ0 ¶þ â›9(ߣ?É‚XÞÕ' ÖÎpd²àë‡.YŽ=јX®âÁ± –^ñð& bÿ7GÄ‚UI®‰‚À±÷ƒ‚½'ø‘+`€ Âr6NĪ‘¿“X°… ϋǭÛ^™§&èjZI‚M|“Ü$˜êO’à±$øXhJ|¼ì1 >†Î$AßÛ›½ NÔrå A‰H JX * } I‚EBƒ`žU’àcXL| Ø$èûë@AAI¢ ­ÛI‚e$Aœ-ùQ$xIpˆ÷á‰÷Yšñ!®ðM‚ñ;ÄW™Çæ>‘`œ?‘ öì>ä$A|êK‚19h„$¸o“ྀ&Áœv’ãS) ò‹~ ¸÷aÜ÷A÷„h’$¸ò$Áã{D‚û«‚ÇdÌÛFx<¿âÀãN7î_Êxlȇ^¹_ųxÖàøíùürÂÀãJI#Jÿ <¿šx\>aàñã +! <;aà>baà£Æ•°ƒ;0ð¸g…Ç ÷E—Bx_Pà~êÒÕ›ç- Üo3Sà^r˜#æFúßM Üó¾)ðü*Rà1ÑŠyBxœ·(ðø5E¼~!{—Bx|—0ð¸s„ÇÅžÛž»!S‡8ð¸—ļeÀ©•÷f¿KzÙ–×Ó¶ƒÎ¯]¯( šý^ÍŠ›ýÐ~8vœì'ßßF¿êèl¢_*B‰~MVƒ~Mz÷F¿žÆN£ß°S1ѯë®<í rdšýfÔ6÷MG“û0¢ã÷Á!`÷MKN+(%Êà *£]ZA×6L¾N+h±^•Ü·ssŸí¢›û¯×t8Œ~èÒéýøÔW}ÀI}¯¥FSŸMC›úªMM‰}M¦Œ}i0L쳜| €rc_—/zcßPØhcl~„*cßô9$öôpûö6ƾiU:ÀËþ·//RSDñÝ/öu…w6ö­e»ì«Æ¾aÝ•Ø7|š)bEG Î Ö_pë}â>«Sz+€²T×§÷EÂ;wlpí­ž dNZü¡¢òu³š¥õ¿j]G܇-ÜP€Ü7³_•¸o¦EÍ܇%Q9å?¼\ÛüpœN.¸܇²ÙYt.Ö ÐOŸSþƒ`y?§#ZQ›û¦-,É}°CÝ'øáÍîé—û[[þû§¹ØRÈ(‹ú•ÿ.7Œ°ú‡¾å*ô%õïjÖä¤þ!;}|ä?W–gùÏ=õ¬þÝ·¬o©þÝöTmõïötcõï¶Teõu8×YýƒÍøþXAoW·ø·˜°øw§ülñÙÝ<)«·ã®©þÝ®¹`ñYdö$þE[Ò£Ä?Ô¦h'õ…嚦Ä?4ö˜#èsYä´úw£º?$õ’&Ÿf«ÏÜ%õÕ=©WZýCEC98¥þ=ö#¥ú«ÝøÈ¨Ü-ÍPúß“vëf9'YÿC&–¥Ôÿ°ÉÇ .ˆb’ÿÐùJœä¿â RÊņˆ”ÿЃ„$ý¯\:àÔÿŠU:ËåÀ@Ê呞Ÿò_±'6å¿xü>NÐu4òZÿ+¾ßRÿCGJ„’ÿ¢!ÈÇ T?NÐ(Èq¨ÅÙTÿPnd~Ô¿2¤¹§úå™Çoù•Çõ5’ÿÖˆ ‘–ÿŠ )ÿí¯¶ü‡,_²¸å¿”°Sÿ+©hZÿ‹o RÿKÓxê8fºo¥ÿá«øM’ÿPO]*ùïU¶TÿPÂø«þ¡LìõQÿЭžB£Ô¿×óOª(•ÿá>lcû¨Ô?|7¯–Õ?¼/Š‘RÿPPK´(ù¯^"²¢fÜ X4œnP´?Ž’‡”¡›Ó JWÄáÏ¥t譲ݠ˜¾nP“/Ý S¿ñvƒÎ€—/½7zU»9ð¶Ì˜ˆðâÇêðÉž6¾|Î6Vi•›‰ÎÏØØeÚØí5­D6N…ô7NI”[¼u}O/´­]ñ­v-iRÄŒûQQ åú¸A§ÕªÄÀ)×NR༔8•8íjO ÄZ)ÞþI¨âFåÎÛü8 k°/âG¥–gœ6Å$¦o,)0Zýá™#m+ T˜ËC`,{ø!Q`$iÓ Š…ÍEá{O Œd¯y €øÔ× {æ{QˆoWr(0ª’Õ“Ã&&ù‘$Ø¢*3ù’$+J="ÁØßî"A¬b¤r‘£Ò Wâ"Áp‘mD‚ñrç*F$ˆZE‚x¹K  b¥ÃóFiµv’`d€Q§ b-„‚Xɦ(Ä6QV Ê}X°E¥CŒt¹÷Ì ÄnG3 Ʋf* Y‘ýNUZ`´BãW‘±n8Q°E×Q0òÑHÎ |œ«YwŸ³±ŸÓ Š„/ývÎ ¼†…g–+g"þ=Iû©§´Eën¢¤Àu–ZÈ:)ðvH†Ixg*PYÅÉ™רs‚ —'i½§Ã:'U¯ON`É<$AÃmÈm”x7;tmÅãç&4‚ÞÃw“#ñ0æ¬Àjï´Œ ·õ*û@_g¥ô¾­¶Øzg>±} Ïã8} 5c ò¢¼]v›âB¡³ô" Oõ}å}’¾íEº•*ƒÑŠºû×Ï>PÝÔéut4Ap? Áµ‚ºÕáÉI¯éôV­kwR`Ï´E%:œ›$Ýû!Áw:;×(X{bžP¾6ž¹QðyÒåI„¡¯üˆ‚ïL•ÐYÅù}FÁçÒbA]HË(øfzn¢àpöh¢ ë"$ ¾™kD-vi‚6‚NgHšQ±êË‚¨–À—Œ —VfÁ7ƒ)fÁçõ%ͤÀÛ–ëL tÍl£ ü®üe2)ðñ­Iwâ¢Pp§…:¡`M“DZA›Óó²×™kŽ´ôvŠâFA­Ï‚8>ŠXFÁ¶uºí­J >]×8­ —æÌDÁö(‰7YÅ1E~bÁvÿ&©q' Œ‚øn}“P°ªª{’`uŠg’ zr(9O(X“¤Œ‚È8¥½Õ(ؽ:ÙVЮŸAVÐâÌ<Ãàë´†„Á'ñ6½ EéJ ƒ¯Íò ƒÛiD·úA´db²fÂàÎß ¾~o& ¢†Òø˜A‘ þaÁêȧY0Š»pÁ ª¡>/hÀê'/°N§š‹„A¤mS© båz}¬ 8‘ë ƒ…e€7 ÖL@ ¶ê[Ö,ˆžöÌ5 >MâQV޵æ\ðìEqÖÈ‘‹ï×ÿ%âÎ-öö{‹ßûÌ_/+÷=šüë,¿öÓþ÷VgùµRŸ¨&Èýä_Ç~<¶÷“#Ç~Þ‹5¯u¶þëØÇö~räÜO8~›÷ã¿ÎýhìØGþÓËÊ=‘ê[¿¬ÜÕÿ¸þëÊ=g­¸Ÿ Ä­Îþ{uåæÞ¯68ÿ‰ù«g¢ŸoƒN—ƒê}ý| Öh–UçôÙ£bœ>VŒó>öVÞϧúœöuTŒÓ¾ÎŠqÞ×ÞÊûúTŸó¾vÅ8ï먗ûÊ­r_gõ¹¼å³bœöuVŒË‡3·ò¾þ#uåx2 ñýZW®þ£ºr¿Tüƒºr¸ÝOuåþh»ŸëÊý~ÅÂo]¹4ùýÞTóët÷o0e[üÙ”ùÏÔ•Äaù÷©+÷×ËÁÝ»œÛŸ”˜ûëµê¾%æþcÝÐZ±Ã?)èÖ³ Û§ÚÚñÏ_Kº•ûü缤Ûý’nwþKßÚøân-÷¸þÅânýz†‹»­Á_Š»­±ÿ–ÿú/¿3–ÅÝž\Ü-ºØBVDŽÏ›3…òëeŠrÇŒÛÆ "ZVMeã•n¤k®'}yFeØ6&¥èå2¶%«•«D³Ù(ŸxÝ¢ÀâÔZ*š¹ÀMÚÕè`­¤z˜Iû-ý¨\-zÄFÎûÍa®«¹õá ¼4Ñ Gkñm·©m¹qü;måF[¾aYú ËýD;´Ý>Üæ™t“ºhSt€‰±Kg­•^´­Ã#iц®—ÊÝd qí±r÷,F*÷)äÖ:¸,\r‰0Ê´å¹ÒÂhQyî¬vs“'=! ƬåTi 8&—Ìä,Ï«|#iy*£—µŠò4ùBœŸZžN_H“ûíì 3éœÒË3å )þªrÉòGJ¹ ¼Ô&i-ŒU!¬) w¨BØzŒƒQK)Y!Œ1¥‚f@É˳R*£—Ý›¥4•k‚·RzÖcìoí˜Î”åâOS&£—Ïê½ ¼$·­•;ƒ—5Ö<­a—à5¢aÊy,oa,ð¶Û¾¼/K„5_s4ä˜,Fõ£¼-K„Uí¦g‰0F¦Ö©a¦ÂòâúE„c¤^Œ‚ b…²æoFok°kA¬aS°¶F tu›R à «øòú2ˆ+ͳªµ%9 ÔHLJÑ+ôÙEáÊ…™û1 SÁ ’DÍÞq­ß(éCyº„þŽl;Ì%ñE ¸™µàSÙI¦õ¦@=IŽWV€ IIF© †}ˆßÞœê¦W€ÎQ`¦ø´°Ç›euâ2´È”¢4´ŠÔˆyPõEM"KôªQ¾…E ZÁ¢¾Ìíºwk$‚¡ ´ ÷j‹Â5z ÑÂumÜ3©¹`݇ú2ˆ‚Gð£ôÁ@ìNÄ‚uÉšÀ{ùŸÑÀžA²‚Þë¨/ƒjd,èó¾ÎÇ@¿IA»Óõ¨£³,£ %š®ïJ vD4-¸Ö.h]ºžõ^íHXaDÑáHÏ*Ze®“ÀSÍ{ -~:¾ªùQì½×Ñ£”§ŽÎk ïÍ.¾M0Ö‰6ëýÖ­eƒÇ ºd­ÓA#YÆ; Ú¬9mcü+è׳J\7›ËŒ×øD™v]ÐzdM–hqB`/è’µN§£ö"ߓ蒵æp|´1”è ¸l‹+ÑRnÌ×o<ôçXsx‰øâ%½ j€#Fî"ÞÈý¼xI¯Û#ŒÂ¾(†¿6¹]îãE£¬5‡0èpÇo„ÑŒ•Gü¢WÖšÃÇÝe~}Ñ+k=sh¸Âsx¯¸,1—é{±8~é¦mHÊÑÔ5BÉ/Zt¬ßßEóÅkz}ë@½x¡½w° hJÓû‹×ôSâx¨I¼(¿þ…æ.?íÊ¢Yl¿k„qKñ§zÑ-kÍáèFÅûíE·¬5‡èó§€nY}íf-^ gè+C‘ÿ}¢Y>¤ãEŽ9ã¼™1ø>l¡³ô6O„ñ¤0±þÅKúÁO_|¶±éíU~ªF<Û0÷F¿¬õ]Uå_´ËZs8¾œ‹ˆý²Ö¼ft…\_4ÌZW}|ù¾xÑ0kMâˆ0Ófô¢aÖzRÑcGŸZoéh•S+?òD<ݦø=xC¯I} è¿zñ†^“8ºÛP¶zÑ.kMâè^Ôµ×á@<0 ì½è—µþÅ^JÜψp`t˜ŠiýE¿¬õ(ãé×mƒ~Y½Å/ÅUî‹–Y· r×¹ÍáÀi.” ïè5‹£'ךï]˦+}¾xE¯i!rÞÑëÿF”XáH‹p :Ñ—û¢iÖšÆÑlG7:úf­'xùÒ{ßh[ívãú¡mÖúQ¡™S„+Ýnh¤m³Ö,Ž`<=1/Út¬½†¸Œ|ñ†^³ø¼|ñŠ^“#‚ú ¨¿xE¯Y|Lù[^tÎZ“8ºÈp5ÿ† _å¬à7ŒÑõº¿DÐó /@‰ñ‘ÂÊkMáh¿zð÷c†OI¨t#L™z"Ú&Â^oDZסÓoLÆo¨ /?Åg¯èõ«¢cýb/^Ñ:¹À_¬ÖsŒžF\½¼-Öß±ÊIocØh{«Üݳê×÷ÛC"ýðüF÷õ]hØÀoïѾ S;ÝV/šg­)|Öᯭ5…£!H¬YçùxÍøâ-½~iì†~‰Œ[Ý>â¿ZâíK‚ågdÔ&AÂ׉‚ôôlT ø‚]Fï‚Ýë÷DÁ!£ÅFÁ¡ì°DAlû `³8QòOÿ  Têx7 ^ºÝ7 ^?¡ Z”m¼4Sm¼äÚ$èÊ ›ÕÃxƒ Ý¤AÔðÒ ׈V9Áþ$… ±ôàòÓ ˆÚ \Æ{Ñœ Ø=—% â=\ņ$Án]/I‹šö!ÁžK*‘`P1—Õ&AtðŽ™Ô$ˆòh\ò™»U²$ÁÒ&AhÙ„‘` 4OÔ(Ø\Œ‚C Æ“£ª7y•!`Û$$§J’$ˆ9Œw¤H0¼r?#s„†Ó)UÜwíaƒÄvgŠõU“ zÎ^&ÁèÂo †Kÿ=PSPWw0Þ’BÁ]ÉË(l͵¥P#”æ‚a¦æ]ªV4Éú|D‚Ûônd±¯“ÁÖtÂE6 FÑnÞ9µ5¼Í‚u¶$¿¡ Éè”Q0Ä^BÁ5QS[K¼ò·4 FgµûÇ‚€0¢‚Qð*œ“ñöo¼üjO„m7¤Q0ÚÄòˉ‚°Å뛦*„e L,­÷„AœŠ®°`„ÎשaŽq £‚A ðj‰[$÷RU ¬ŠØ…‚p°2€Q"“H0Üá'b€Š§A×Yñ+`˜ÃpA¹L6"ž („80ŒüÄáI!B‘ãC ŠˆÃsÖN„ŽË9^ˆx‡fLaàv9ñ!掱$aé"c`˜±ºÀPåÁzâd‘+dhMc „?[¿“0pÛ±± w®¤vR`TõÒ&SÕÁš"\¦À¨ÐÅ•¦(r½)#—Gh Á3Mæ+2…¸`²)Òs«'b-NDpj0iÍ›æS`”ñârJþ.ÂD1RN ÄI˳)0ôþªóôl ŒÇ˜ 5b`8Œ¸Ð†POº†'à99N ¾–ÌpPð-i„ïBû!bÂj‹1"F"x&ˆ†Yƒënq Œ":q äa¾bÌðP0wÑÈJ^'bºòÈØ%¸@b?^ Føð£Êo€`ìöÑŸ4†´Ä|‘`ëJµ6FqëÁMªj„9UÑ ˆ¨¡±¯«FØ#ÿšA0ÊzÇi‹1@c9ÕÂéƒ4¢F3ZÍ8^=aà.. Œð#ouq Fh2"üÈØ˜90„["“8ïÂŽ00JŠëCQž›L*Äg~6¢à5C¬æÀ¨rVNŒòddPq BŸÌ,0¢Ò˜ðLÖ˜bÅ‚xËijFƒC>œ"Áé ?6 ¢þ¶b$ÁksRIEÄ‘ b€Ie»¹Ä6 ¶™O¢Hu²‰ìA^u‚(·­»M Èâ½LIÉ ˆm¸œ7â?t q€zÊ‚8Ý'A\Qí…ˆoRD ˆoâ•¢8ׯæ@ž%õê¿\Þ-QPÚ‚aO¯”P=lhG3 fm¢ R]ù>2 ÂLUÆ,82ÜoÎ"JŒõ0AO,¸ÎŽ•iQ¾•kÃàtõGà Öo|íŠ[ô‘>YÒˆø‹,á+fà„Ax‚‡D@Âà,¿Õ*˜Íh’ç0bЧKö™A\m˜§³Ì‚íR‘£`HZíDÁXmòÂã“Jx+E Êèm éIà÷(E`¤H„°D7©Q0ÜþÔ\RœZ¢¤&hþ¡ ŠK ‚!žñ÷OIÐqê- æ/iŒÇ(ö“šà1 Ë¢L‚1Â35ÁÛÔ~h‚¼Õ‚¸ÆRR|½ÉP~€‹ Y„i›K>+‚H<à‚Ó’à-G~*‚°ýòZYÌ`wJ‚«ZDS[Šg–‘Æs$ÁÇžè”ín'†í—bIðÉÇ0%AG¨R„HÈKaIð±Q4%AØÁÅp’Óöžšà«$ê”ßêuuh‚8WíUš œéóä@¬6éáNMðuÒ`‚ FæGDãñš@ðu%þÁ’^ƒ –Õ\®›‘²¨ï BÔ"˜‹üÿ ‚Èz#| q4” ‚°ªŽÖœB ‚ˆ’ó ‚Í¥p«¸ ‚è<éÏ$ØÜA)Ivg>SFÁö*jž(ØÔN:Q°&ܘë°:j¬îá–,{ýsŠ‚ø=õU†Á˜´9"ìî¬08ÜnÊ0ˆ·©´EÁ Š—“Å‚x¡ñQ4 ‹g ƒÖ§N'I¸†Áé># ƒÓ+‹„Á‘Ã`ÏW™a°©'A²`­)Ša¶ã,S¡(³ Ò¸ø‚1 bjjD-±àpd6Yyþ„ ³ Vþ’òw ºEubÁYù7 BÎà"U,k,ÀÍ‚QB‚#bÁy ¯“³õL²`Ï@ºYpØž,ˆtvIwbA”š¯ÒÉ‚Óa8³ ’<ŸdÁ~§ Dþg_³`Ç‚¸Hì„LnBìaZç!›óy Bç—ª$ÄsLß¹QϺU9¢ ÌR"„‚ØÖº–áÒT÷„‚XR= B³ç‹Ý(ˆ3oãÔ‘ðÊšQ'aü" bD°P×KüÄnu0FA¼??¢`&÷d8²`˜ >¢ ®èüh‚xåÍSÄ}¬›T(z ™dAüàúÌ‚à‰÷ÔûëÞLfÁþ&Ýû›ò-aËv j‚AìFð/ÄœË÷­a¶ý2 ö,Ûnì%ñ†4Ø‹e¦AÎ÷ÒÙ;(^Mä1Ò ®d¦AÜR-Eƒý©~ˆLƒ0oIà# ⥠çA4ˆf=V¢Al#’0ñZ0ػӦLƒ0{\í Árý© âwàÍ&ÄõcÃ`GŒJ{! öwäa¿ƒœ¦ATó‰ŠË­Á¤Áââé¦Á–@’4ؼIìîLkìYU4ØQÀ×O4س¾Vâ Ôm¢pðuieó`›ÊÊ4öê4ù?©ó¶ðåâDÀªï5®·¯Êþ%æ’;ЩD[z<€N@:ð­_,( &&j&À¡>d €XSqAm5päšÂj`VõJ5p¯Œ€i¨2â…W?z š~|Ä€àšrʸµõMbÀ¨}C-ƒ 5uxùÄ€Ña“Ë«dÀ™æQC «|mœŽ‘o¿$o'»'Â$CŠ1ÞÝ8'¼Ý)6ï2.MÌ€÷4Á(MÐaþú¡ÀÇi~¦@ŽÐ›y)M|X °1ô±wÅCH5®±¸)°X—5â¦ë§ˆli®2’‹›Û&–W$k Ü1|Q`©ÉT¢@pS`–LI „aHª0ÇÍ¢1°¤KQˆ6\å‹Ã&"‘Kcc êˆ8…¯»'"ÅŒ71ðud31ðÍ»ËøÖŸ¡ðV¼_ ¬~ìexØè÷¦00/„1°:Ñ310ÒC?X‹Þ[‰k=-,1p¨(Gb s¬ \3¨l ¦@x8xߘ±Æâ4e l®ˆØúL „©bžÎÐhçÀo"ôc jøxCÁBz6M1sQ ð†ú¯(“gS`ô½¢¶' Œ¢vTEÃuE’ƒ~Èâ i œnF˜ÖЫQl ½\É2­¡ÛÎlk(Hå9)0FÄo²†Þ.Ýkkè]ìu°5ôvA•´†^#•EYCïT‰m ½“&m Í:Ti }¶r'k(–|\m }2ˆhkèÓäLkhV™JkhÙÈ)khIi^ÖÐb˰¡¯ë‡¦34úÛžسž‘90V¹÷ɱ`}Äj„—Ôˆó.5bÝ+û”9°^ ì˜;rÒ©Ó‰±Vyt8ä@øoµ¨öæî*æÀI)êÈðC uÄXžÚÂID5É æÀÞ)«Ë¶&Ž×äj „,Â#6â~?ˆNƒí”ûp"s jN–Sì#Ss šÃ‰ßÄCá‚ÄÀ™˜j „‚×Xˆ-"³§WTÖPÀ#À8Ýs'10ÈúƒX°rmlkè%·)àöq†^®xžÖÐëI3©¬¡—sIÒ ^OEp¶þØ6dÞlv†>Õè(c(BpÜä E¥¹çÔJ§–ì -®Æœ¾PÔó»(Â^*jµ1´4K46†–jB°1ý¾ù¼ØŠ2-d#Ca?Áp ød }]ÀÉ82–fÄH•HGïÈmˆ€1"ÙNÆÐ×µ«Ò êzNÄ„Ëb[FÀ`.e:1à@I}0 T<'Žš+žcÎ~f@œ„µ=B ìÍòð £b•F2 œÉ |šG}åî7ލvC³(ç9êÉ€°—54~=6É€¨|eYŽ ˆwÄo1 YW™ ˆŸÏ³G|}0~z-„€á”ç.Í]TÌ€¸ßâ`þ‰ŠoÛÊ$¢<Ì¡*„æP)­gž À)Í¡ÓúšiJ?_æÁmŠ4 ö’Nç ¾¥LlŽ:g¢ ‹NïDÁĶäÁˉ'Ƀ®Äð 2cRt3ëäA¬ÐΚ #z[ÌutŠ‚ŽÍ¥(Øû& bÚîŸDÁ9œ|–<ø$hš_ .) æ²*EA½ö6VÝÍgBšx…}xÕ”‘Ò<ø¸^ùæÁ‘„H,™Ïb,- Q<ˆH}“æÁ×µ1“ѨOMñ "#\PšQ2ˆKtó &þÀÂ7×YÂê P „u$4 ‘H4?º Î÷=uÁž¤i"DÑis"ÂîÞI„ë¾åŒšD-Kˆi"BôDcò¥ˆÊñŽô3šGŠÐ&‘y²&¡Ú÷ „P¾©‚°€ô.8“•„XÙky+ ìWzHɃˆÇZÀ#„ÂÂ~ù•@ˆIU•€0B×¼•„ØF•€;Ññ Ñ(½~ü¡èlXÎTA@†ÈX@ˆ˜¸‚TÂ~ç# „`A@áÏy!f}«ˆ#²9“o”ìëdÁ’¾]' –š {Ê,ÿ‘{õïâlÁÇ‚³è(§.Øsý“Ù‚e㨲±¸ù$ רÊdÁWÝ=2W.CF „¨;ô|€emÆi÷Ý'U0ò&N‹(Öýz:̃խ2UЭ¢’ëHЩ‚nv™<ˆEÊÇ#Š£‘ÜhÄ„qª‚ 6FLÄÝýœQ±|(ÆÁê—iâ ls|¥[ªÙÆÁæzhÆÁîâÔɃ- æA|ö´ˆF53¥ [æ¦× R¥ð£¹å‘ÂÅq°?^[*DÆÁæü‚ƒŽàm¼ÓŸ*¬ ƒÆÁ>sD8 a~p°¸gâ N‹þ@ã $ù~d FÉ8® S¬&Fá`UÁà¤A®¸Þ5 ¾÷O‰‚AÏï‘(ˆ¹X8mÄR±|h°¾ÖkmõgUpÍJÄ"Ó JBÎ3O»ÑgDñþ0›;Ž' VÔa°f6’aðu¿Ô«zÒ`uÃXÓà¡qYDYqn"Iðuý´”a èI¼ÓÌ(ÄTB%"%A°Ëý‘Çúq°—\§$8ÓHIðU×픣¦á‘&ဟ$A·‘Þ’àëe¾%Áæ®à) ¢Ü®¾Ü’ {]Y|]5 %ALDõL„l-¾¶$XmÃKI°V_dK‚¯ÝfæA޲Ø, ‘Á0‘%AÄ%eO•$ˆÛ¤ž<È”ð“q08œš BÜ•:j‚x’ºDBj‚¸ ÏTA¬ÆIƒx-)h`I°:³ÑŠàãr*‚o ŸVÝb$ÁêàfÚCKqDÀ‚`HA°Øó—‚àkWŽÁpeŸöИõ‰uÒG>ñÖY“ß-hK—³ý¡8ð¸œGÍ·Z^¦˜EA¢u—Ü‘ª´ÿï¬ßvn±·ß[üÞgþzÍ·ïÑä_Gm´Ÿ÷¿·:k£UäD>>ÊüëÜÆŽýxäØÏ‚K;á?=ÄÀþ8ÿ<>Ûñ dv$®”ÿ:öà±½“ùO¯óV!Š­«ôguÞ~©ÇÆ:oå¬ÝösÁ¶ÿ”:o?ÿô-œs®¿õómÅdóýÙ]ÁÍŸ?+¸y{+ïçÜÊûÚܼ¯³‚›÷µ·ò¾Î­r_YÁ-÷uTpË}åV¹¯c«}›»‚›÷uVpË2·ò¾þ#uÞð¦x‘ë÷k·þê¼ýò ÿA·?Üî§:o´ÝÏuÞ~ÿÎúÖyûGÞïM/¿NqÿöÓԹşM“ÿL·è€¸VTŸ:o¨´†ê Wýg ½]­ÐÛûþéNÿý_þÁzÕÿx¥7,;°TüÇ•ÞÚp¥·6þq¥·õÿ.ïv—óŸûÿÿ¼ÒÛ÷KvÙ¶Ïý×ß«ïvçàõÿ~¥·uäÌG~ÿ“sEcÆ?ë£×Ò™%Þ¬ò­5³Ä›µ×³Ä›¥£€Ìon"Yß‹YâÍzz}of‰gA¸ºƒUZQ×2þ7Ƙ¹Z÷ûÈ5W°®kÊ,qGsêÛ”%~‰×¢TYâ6ÇÖw(KüV §5Â,ñn…©¾“iâˆgªÔÊX(¢Ì:Àz3M ØÊm¦‰w—¥¯µ0M ò/G^¦‰÷ÎèR­5ÒÄ»K¬E3ÓÄÏ+éLÏfž5úV6-|4¢4ñKšIEx°aª®WÄs¹I¬w+2Ô@œ‰’îýëìç[£õ s{¨þÖöª“\•!¦"ZÊÑ£°¢œõ«þƒ…ßÕÕ@¼Ë]PެLž!M×0° —þºè$7¶ªPÿóá•*Àe2ž´~µv$ºWDÁ.6Ñ¥µ¨‘ ¬†.Ì®!Tå+,uÑHîÕš½"pò>;ѽR¬ ë‹tU(±u]C*ÄÐèÒIu\ê#×To Ž[}äºouI’Ñ»íæ6Eäl¶ª¡ßýàÌMªÒÄÝ^«F5#Œ®KM_|g¼œc0 x©î -ä²!¹¢’`øS΋¶«(ôµ.6m!rb˜m!—”ו¥+iE¹Yב¶ËM*J¢D9W[WI}ä^ÕXW É1º.A6’Ó}4‡ÉU?Bsf'9HZ'¬NrÖÖ ²“œ³†×¡ª“\S¤u1³®.–_Æìlñãõ¥Ì@¶”öÓ˜pɾ>í.7ŒXÿbnFîwÌ´ö±ÕÑ5™pMÝÆ y»ó»‚þÚ}37àòÔÑîGí, µ»°}@t‰á6¯:ÉY)Yof¬mÔ÷nOv€‰‰µÝÙ8döHº‡ZÉ]îô{È@˜\=ž&³¢-Gòs©•Ü-³ñzn˜)ŽÐ Oëy˜p»L{ ³n—pjÏËì€ð“Ç@erÀí"ôkjcrTFþTOgr^™<‡g09#1ñ·g09 {‚´g2Qüvgò†½3¼â«ÊÍDñÛEZy˜(~;αng&ŠßŽ-´ò²Àmüš{™(ŽóœÜs‹8àí,×V:Åq4?4˜(~;¡f‚D]‡8q¼¤!äDÌ'~ª÷bž8ÄÜÞ›Éh Å¿óÄow@joažømkßz70OÏRÄG֯ʼ ØÇk½Âئ¹Ÿs}˜(޼ºx›­W³Pÿ/óÄ!ܰQt­ìë+ïÈõæ oßm¡µE VÁà» …º ‡ZtZe *Õ Ó·úq¶ºŒMtVñu6b‰÷P‹~l¤Ç!Úýñ«hHha­d[GƶZ˜ y4»iLGðž9êõU§3UüvsäÖSųd‹Ä¶uÔWEIJáàŽñŠV¹ªžkOu¹÷e+Ì¿môj|½ì)©û¹ZT$„Û4¦Š»ƒJCs4ž7‚ü"€i(8ؼ’sd¸œ˜kɄ׆wôœ䋳á}«×M„ÞÑQíùª ¦ ¨öq+þÞÂuÓãœâ=Ù`ìx›º¹ÄñÂ’QùUt@µ¥MÙ8óÒÈt¾:ê¼ñ¤h(kh&9žoÎ%ÈÎ> /iÉñz|ñ’¾Ëg¤0ˆbƒƒŸÂ9Ä€îýYÚ³o™‰Û„­Döl>Cµ°*?Ås@k´°g—<@¬òžðÐÂÝÐ-ÚʳÕÑMÝ@5À:4qÑÙuïè‹Ubè!ìxGß,ÕÂwiÇ;úaö*+Uô ç ‚¶Ú3Îá8˜~E=Ù8)Þ³kd²‰×­UcG_4Láø÷2{”úxšæŽNµQð…JCG[4öÑbÑŽŽ¶hjÊEcÇ;ZÝ@©×3FÓ¢’ŒºÃß‘¥#´%9†€=Sfý«ÕÞ¾4ø ¬;,HÁÉ‚”PN,?±`×ͳYÐÝÌ7 v‰KÉ‚næ¹YÐ]U’›eòdA@&fA”‘ãòÒ,•ëu³`s¯˜dÁæ™3Y°9,Y°YØ,xIŠÙ,hÓÏfA'Ù& ÞJÝ0xkÁ¹aÐ}ö6 º•NÂ`·! a°çê[0Ø]À9ap.Uæ„ÁžËqà ”'~•aÌKú2 öš)ì’é“»ÖÉ‚½ÿ¦ý {—¼™(ØÝ 4Q½ÁâHÄȵY0ÞüˆX³¯žY$¬ b„7—YpÜ‚v£`ÖŠN CMýq°`Øg~(Š›˜á†xI‡bA˜ &yL,8œ°Ÿ,ˆŠìb6²à°ùÄ,´¦õÑ,&4ž¦Xp7–7 ˆ.ŒbÜ$X°—S3 ÆG\ ®)&™£K{œX\2˜£ûç8YØÉ‹dA0ºˆ\,Ö§ÚeŒò¼6bÁÝ¥Ý,dÏ5–XL®ž°dAlB›‹Y#Lz5 nÖ7 F ;®ñÅ‚Q¾‚oF±`Œp=BŒê%\Í Ã×ÇŰ`#\‘& ^þ&±`4nçŠT0XÓw•0xåZH0ˆ£idéŒ/ ^2N£n‡¾Ë0x{ek oáƒq€\¡ª ƒ— ƒY·Ã0Õý¹5 ^ÅËÃà%í7aðJ3 ^ª•,ˆHCý°àU”BAlÂå’Q%uùMBÁËïÉDÁè§ÈM„‚±@ã6BAâô)¡`vnM¼5 ^ÎL¼üJN¤ßẠ݈̈/O‰É‚˜^yW$ :t˜,x95YûáÝ•,xVÍ‚—kÇ% "ÔÀû-YðòAtÅÎdAd4ê«Å‚Y˜®É‚—ã=É‚®ºYÐÅË7 ºWC NÇ“0èžðo%1l¼ýÓ$ >ºÍ‚Ö|› ㉂ˆ0P“(X”Æ·Q°‚‹ùÛ(˜“›Qð¶£5Qƒñã$A5³N¼íbID0àú€ *0„`¼]Œ$I]j"Á¦h…AñBN¼ÝÁ1AðvÙ“ :®^ âF ”$ æ9$ vUDLŒJ<„8±àQ§r³ Š["›Xð¶ëâdAª ƒ›ì ƒ›ì ƒÙÙ8aðÆ„A] à ðUôµaI™½ÔÜ0xûäont•ŽÍ‚.¢´YðQ®ËfÁÇ‘ÌdÁ|Ì’‹¸YðÕCµaÐΪMƒ¯l}›ݬfÓ ýŸ››î”Mƒ]+ü¤Á¦_fÓ`‚]Ò ÛltÙšƒ®é·qp \ŒƒÀ¸JÔ3^šGw­MD3f^‹ wlôëõŸ(ú–Dˆgè*'®5;/v2ápÙÈdÂá ­É„P†È{f±e¼+û I1¢|1WÊfÂé²wfÂé<ÏdÂéi8™p:{?™pº•™+NçÉ„s*ÉL¯‘$™0‰ X1!®?ã$fÂ]26™0;2%¹E ÷[H÷ÖGÄ‹œŸbÙÙ>òàt}ï$B”¸‰·Ë–].)åÁn>5bQ.*¢Yu>«ƒ&N—âÜê ð[ôZ0‰pº²aø÷¸g!!Ú<óŒ„ÓæéDÂéRu§<È8‘0K ny0a$‘Ð;¶<ègé”ëWlÉ‘–]Xm˃]ë‚-¶Ôþ¬ºÖýÖ-1m}ð•h²õÁb-Íú ÝýÉ„I'É„ÓéÉ„´H%Á‰–BB¨©Ü/‘…šNu®M„ï{!¼¬X¾åÁ*Ûò Ë¥Ÿò n­CÔ ò`‘±r˃6Vny°hI¾åÁâ7fʃ. ŸòàãènʃñlyðR™á-º¹ý–Ý+m#¡û-YDyïr"a,gÑM–§>HµÍú`ÿUdjòFB'ñn}°ûh¬#F¦]ꃗ; o$|IN$t¥ëƒ(Qu}ôAüž÷ ]zëƒÃ9õÁnÍ)õÁéÅtêƒÝ‹ô“ŸR lŽl§@XuûoÐE¶@XŒ‡@Èy~ „?"Ìì¡-ºÇ/UÙâàe0OqÐÉ$&ÂÇÞî-&¬˜±|’ %º_a,LãSF†$B÷ÒØê`×Ûb«ƒÍì©òw9ÔA¾m·:èšÑ›«5«ƒ?R,è$º’cáóq „ÿ „#W „:N&BNÙYœrºl´É}ó`W6ÛæÁô#â`‘2) žSM"t¡úM„\H"ôåJ tóx!Vß„=KƒÎ¥ÞÒ ûƒ$>ÎÇÛÒ ;(niБé- ªåÔ) êxStm¤BðãI„.lvJƒ¢—$ÂôT˜SM"T™ „rg%¢8*'€Ô_O?© ¾~ÜS¬9bm°ju<ø8Ågó`ñ#•â ; mqð±°–<¨Ö‰ƒïµÄÁÛĘ8è¶š“*d>èÆÁT_̓–7‡„ߤA§>o´Üž0èN ][lÃ`3î$ ÖÄ:àң7 ªìÙFÁö‹0X•еQÐja7õFÁWÕÝ6 V³—Q°¸øb¢`ñC—(X\Ô*•AgLmlZ'oe°j¡²QÐI!‰‚xŽŸQÔŸ|;ññÜÿ^…áÿºý ÿœ­¼ñ¯ZÜKüKw£ñf<úËÿ,KoüS8*éÏM"7ý¹Pô¦¿ž>OÓßHf”"ˆåø ?ã©èïò{"é˼þ¡¿Ëö€¤?ä¼U×£ÚÑ•ÅÃ*ð=Ü¡t`¤"84KlEp¦ÉtÛCùÂLþÉχ=TÆ¿ä¿[+¿ä¿ÛkéÃú Ól½i¯Øüç@Ä,¸A¿¤NAP»± ØÓˆºÁ©ï¶"8¬Ã¦"8€HEÐkà­Î4J”¬x(‚ŠPŠ PäP%ï¦"˜zÕ! WIPpJ‚·Öß[¼Ñï7k‚ƒ© ªöû–…žRL JI°¨ÊÖ‹÷bE°$zZ,Z÷mEðýâß°Cmóßkm4ùï±5AÕøÞŠ`uä(Á׺g*‚®Y¼Áª·ÖV›ôT›ªlE°ù!KE°ùÍ›Š`W}*‚]!•­6/ãStöùVÕj ‚.Ïô7zò ÁáR¾)ßù)bDèIú 35ÃÝV‡:µoúSgÃŽN+í„¿´0%üÝ^7'üYr7ü=fŠCôž EÏjŸ+oø{´Kö{µ.úE£3FÕS tö­6—S TUò­¦°g1кN5PV¸TÝLaËΣ<å@^-6Ó¢à,!åÀjûYÊUÒ÷)rºÙr`žæ–¹–ÙràÔŒ´åÀ\Í þ"4Ãk‘r`Jš)V¥($ü]nÅvÊÄ:‹)3ý®ž‚!Ñ/‹\º¦è^w‰~×4€ú].̰ÅÀaüJch -b?D¤ˆZ‡È ~0[KŒø]vWm%ðòÊûP@ùዚ9Oäwm£h*²šüðí%0]à‡ T6࿌+%ø]Ih¿[î’M~·uRKŠ'l)ðv&¥ÀTŠR ¼,E§x+BnôÃÔÌÄÉ-^•Ô].vkÅnNK‰.ùɱZà4Äü\‘RàÅ•$1nðã]ŸàçÒ'›üÒtžJàc˜I%°XòN%°xN%°û§X}o¥-ÔY¦[ 춤h;Û‡üxæF¿t9¤-Ôç™ä—Ô™ä÷Z\5ù… ùã?Ð6]?p3_H&¿Ûý~ý¶Ú臙aì‡ÐÄýa?X­%]Šýnûc’ýì `b?`û‘GýÝÎiHú»Ý;éaÛ#¢?ÁuÂzÚÏXŠ–œ'üI<´ è0[tÊJÊ€®}’ì÷8`³Ÿ3’¶+´Êô³eÀò›ö+ôÃn*Kÿr¡·í eMåïßdÝÆPsá6†*+*¡n軡#-ž6†æÂ<¡Ó‹eS î#ûöRQ ŠÊ´Ø]Wvç¾^ÞgŽ`Íý8G°y©™9‚Ín¹ÌL©)sµÚK[hv›Ýà­Ê–ŸLå³X’ù¤Ú´5À¦ü—„@¬öš/[É2*¾!ÐyG§ȇÔ8íqÞ"ࣨÉÝ-)Ž:~yª€ošIEè+¼Îmµ ØUÈu«€Ý¹£©emÐÉ[ÌäQc °ž›(1Nß# ÄáHÈNYÜ„žä-mj%[í}Ò!öc3à^#šc)åpª“lsD #÷É€»M¬0‰ƒhV²•¬\B ~ÒvJ€¡öôSŒzñ”÷œ!8m&Î Áa8S'Ô΄Þ!xS† ^ä¢Beb„li ¾$Y5¥ÞOªyÒo×L 0²œ‰sÒowÑI 0]©Æ6§-4^Ý$[k€°Ê¹‘öô) ‡ê¡7tÀÿ•†ûG3å¿ý2ïýÞÜøo¿Ü¡?Ï•¿Þ¦¿î㯗†CG”ú- wÔpS‰·–uÛÖ¿þý_ ¢óS…·µ8éÇèQ6®íþ÷¿³Ï_kÑý•^ÿ äPLºþ?\?Îÿ½Þò^>ýR>ƒÿžÿºó_-ÿõK!9 ^ù¯½o’[Ëù¢Brü¹Æþ[þë¿üΘ É=ó’ë(ÓÛ˜ÐUŽçfësÝ1 &ô3ðߣ`-{p±„ÚÒ“#Œ]u´0º˜Ð¯•PŸŒ2¶©ºŽ.Bˆ2"YŸK!ôû)OŒÄRd<Œ16kA=zå0_Î1ôq «‰ëŒ¬YM.­ï6Éjr9ùh4YM¬ÒõÑe5q‹¤E•çBÇïcÊjb-½Ï‹VÄ«#dÜçM« R÷)̇V“Læ_ëKZMº‹´õùÒj‚zuü®µf« âÞq¼³ÒiÒ%Ûg£Ó¤1ßâ:Mº&ô9è4Y#Œ´¬…­&(„:󸮰št¼ÆÅ"Lµ»Ëñ¸ZMŽ‘B¯Iw?Ûõ[ÒkÒÝ”wL7%8¬ $Ì&èÔ¯nôš r_¸ßN¯Éaxk\ƒ^ŒLn3i6éj-8î‹^“îšbã¾é50¹ÍC¯ ~äPÖ­F¯ ÌZ7GÞËMe´ã—V TŽTZMºÓÆ9ÒjÒ;ÙbÜ=œ&ëåÍPǸ&ÝM…Ç=é4éî];ž‹N˜ÀâCx|á4IãÓzè4Á&¼äO §É˜úÐK§I÷#¶Fè4¦·ùâZ:MºÅ¶ñ4:M° ?Ô™zžþ³ñ ZM<ÓwO¦ž#AÆQ.¦ž×[j)‰//Sχ#÷£”2†ï*b ³/.õoÑð‰Ôs$ªi7u*nVÖAÆfn~¨Ëlr)\8Ê ÙŸâ­_Bß ã18pÍ%dŒþzïAÆðÕE|p¼O£VDX¼Æ[n EΖ_`Q(rC 52-Ñ'2Þ:(=búñâ,Žü»ñvÚM†Ê¢ ¬³+‹P0f·æº—:‘Žiòô•Ž!yŽÄ„¸ÞÚw˜Ý*w`¥8ϼ£¾Í‚E¾5B·I˜Åb –’|©èÐÙ‚W¿f<‚÷¹É¨,$ùænçËB’¯‚¿#ÌIü"†Âø0->#|ê̽ãL;N9Ɉlø0ÚË’ÞºûÐ{ô’ìÆ{6š„²h7ß&­;¶4ÖT×¢ú'?Åˉ:álrŒèyÇC#ÝLn‘È–ál zŽþÐo2šo›^.zÝTv FþdmNÆž^пK}¬Õ™ùÇÓÂûYõC8íhþ@Ç/zò#91ôùº|_TcD³žÃ”6ÎAN¶8˜5O±~H—ÿ=#ë »úÀ@ã¼Ao›~4;S—h†Œ^ÐêÍGïç›9†z€ð~¾Yª„}àÇ•]¢§â[cÌ—m¢ÝLiÌ«°Mô”Ÿ~  |´›žƒæs³-˜KmŒYÂq2œÕ»&Û‚¹éú¦Á¶`Sÿµ<ˆ8c솗 ¯hLâØ<¼¢oU; î3JªÓ?Í“˜óe‘KÊô¼®Â"WüuG"/oÈõ¦¼Y=äR”l¢ÏZS îÃmÊä>Õk‚ Y}¥ñ3µ³vÈ¥¥ÁD—µÉo¢`1ñ~¾˜aÈÈäÄûùf&/%ñ‰÷ó£b0ñB™7ŽŸé—!ßÍûŽ(cèÔqaÖrÓîmé­¤.Ú½]Ét¢ËZ¸e:Ñe­?ŸOÕˆ2bÏ ¯MôYRÀo~{(cÔ¦é<À(†Ë,H^œ;Œ«ÌœŒ{bâý(—2i붉8c¤[FD}‚Tø!ªøó)ý‚fÞ52™îëNN}ÖšŠ×¾Ü¦F¤±F î¸E¤1<¸ÁIð»µãñRéw_܉w´”~Nˆïè›)£¼Óg‰+ŽÄZ~–‡•ÍãÃüN‚Î]ŠékdRé5®©|Pé÷e¢ÏZ£«€*ÐDŸµÎ¼æ›ê•Bÿ+óÍD›µ©¶yá>Y}1ÕM¼Ÿ/~ ”‰÷óÍœæX0Î7òç”lÀ! ¢dߘ‹×Èd¶oÕÌ;_ÿMÛs,V×¢¡»pL@óŽÊZànÐ|‹>h.y&Z¬ ¡u«£ÇÚ¤q‚ZÍÄûù¢q‚h4ñ~æ//ÞÎÊõÕ‹×óó¤±cLæúVY 2î;õóÏ;)óú—eÛ:(ÙuI–Ä6fM…¤ÀngWR :mìºm7vY,7&&=ø‰ÍæˆÄÀæ.¨‰ÍÕÄÀæÞÛ‰@YAéàN8©'6—óN ÜÛ›ßL‰Írab ,S7·6·XN l®ö›ˆâu”%ÌÍKüäÀæ2=ÉÍ|r`ŒÄkÇh‰vs +“lÌEr ‹ ltêëæÀË´c¼¼Mtq½ ‚—5 ‚—|Ì//©“÷ˆIÐö×M‚öÕntîÇ&Áûgt×¾M‚.ä·IðöÕ(xk²Ú(x{ñ›(øøø]²s³ ›¦n|¼†1 >šI7 #bAw$Þ,ø˜’›H\#Ç£ö`\Ã`/RCшypàÛw& vÕODŒcÙÄ‚=1J,ØíRI\#\$ b„HnŒmH‡bÁîwn² ê'ö vûq“#œòã@A˜Ç_aHÃ(Ø]É:Q0“ñ»³eŒ‚ØäâW Q»ñáŽÅ‚;*cD &ódÁèHf b„(/ì.,‘,ˆÖ•¼Í‚øR,ØüŸ0ØÝ´2iûáÒÖ4ˆÁªpŸªìnV›8q#’œp0#I¦ÁîÄ¡¤A,1x_ ÆÒïCƒ܉h°»nPÒ îÞ8¦Aì–›c7DHÁ`wÚgÂ`w‡Å„ÁîšX ƒû« ƒ;ˆeìî;ž0Øm]1 bæ!ÅMƒÇnDƒtñš›QÑ““™i°{`ìN Ićø8˜»K¦$ vÛé’»k;$ b›Êá`÷*!qµBÉ~¢AlÂYÒ4Ø ½†Á‰3 vç|% "s‘Á`ï³piÂ`6ýHŒ€¿\0ØÝ‰8a°ÛF0ˆV!H8\g4‘0šñCBˆý}˜p8<™¡>–sF]Ûç”áù—ö&&Œ$U ˜0zß°z ™pº;©™0Üæ÷É„ÛLN¶‹ú"™0ò§9L¾¯˜@Ì„GÍ 1!k^ÓÈ„1B3–˜ùIÌ—0"‡‰Ó ™p'ðš ‘]À×®™pW¤5F^-aXLY³å`Âv»Ø•™0Êrr‰.&Œ«ÅÅ„˜0zFÂ}½Œ„±››#•9®dl$ 7-—“BBMÕÈPBÏÝÌÌAàäd$ Ãw£@w—5Ut\H%u„åv*# ù #—QÊß«„úâÛu¢bÂðCí¯3áu”]L˜A#as§[ax˜ÉÂ"Âa"ŒB¼üH„qµ´›W·WU"BÖ´ ÈX•‚àÆ&¸÷ûI„‘Ôû‘£<.#ß"BŒ°ˆ‰‰0j *D„Q$ë:åÁh€ÔOy0“kM„Q¿·k„‰è^˜cD’bë¶°ŽÆñ‰O‡R.M¨&ÂãS"ÂÈ“qÝJApƽ‘0®…T½¢$„Ë$"$ŒTÔðô #3š´.$ŒëÎ'‚HùàõTwme#á.¾l$ŒO‰Á.%£wÍ(FÂØ¦HW‹W!aÔ‹æ Y úÇ&ÂÈþ&Àˆ#©œDâŠWDÈJi?6FZ6aä+ó£–ž°íɪԊe‰3g<`0îzÂ`|‚ó†`p7Ñ2 ò¾'éã~åu Æ6:Ö™©è¬fä£JD»•Šî-Ó`Ü|êDƒq„¯ÄBe ¸Î›i·EÇ Áø­ûIƒñCJ=왋.é\4¹„ ò§=¥Á¨_@¨$ Æ7‘ãƒQe ÙƒÑ¢—K0¥ÊŸSŒ¿Nipg½£"oÁ`¤Ê}´ÁH¸ IdžÞ© Ƨ$á`ìGj!q0ê2H° äIðCÄÁ(Ë Î$ž"Æ%•ZHŒËóÑyÁ~lŒ«Ã'J4E5¹ î–v¦Á¨÷(D# F‡=nBŒÅ€”>Âà®b!Œoâ*_0?9÷BŒ³äêW,¸Ó ƒñÕÁ`|÷8`0Ö*óTãC7á‹0©š Á`\ôvÂ`Å7Á`”Ý °&ŒZúa0>¥Ã! FÅÿÁï" Æ)D0¸³7 ƒa8Ø0wà$0 ÆiS<®—`0vLÑL0»¡F&ŒCæa;æ7 ÆCtóðHƒ|³rÒ`üzÏ)Æ%}OŒË.b|”‡0Ræ#FNŒ#Æ}L 4ȹádžA¶Y8¥Áønò"Y0îý‹›÷Ì,¸'³`$Ãò> r^N,SÇ-)ðò.qS,׊7€Xð¸žbÁ=)™÷ÚÅ,¸sqÍ‚»Æ«Y0.M9a0«¾ ãNq0^÷É‚ñ‚œäE²`¼ŘdÁ½Àø“r›ÿ®˜ÐOL3a`5)­«nÌR €ÎŠÛØô²Û˜¬™ØÁžÝ£V.Ï’=j9o¤(8|“¤(˜.—À‘R§EAŒÈc*Qž›­ f{žÔ12?š`4ã9ù¦2™4Á(ÙM&“&ˆ£käHi‚Õ¬RÙ]ÌšàpK·í }Sï³7ôˆlohÜmohUŠhj‚U MJ‚*x¾Áæ×l*‚í·¯/´ù%–z`. ¬¦©2õÀn)-õÀn÷Tê]6“­ºëÖÝ©zëCúéÖ‡þ©CPêÓºE ‚ÓÑðÝVl ‚Ók" ‚ i³ïs ‚ˆ3J“ ˆ¡›Ç•$'A0naš”l'A0îžA„ÊÄŒÇFD ‚Ã%†¶;Ôõì¶;ÔñªíMCdºCM¼)ŽÇhgsh1à¤9´l+¨Ì¡®æÐbNshq˜ Í¡%}¨6‡å ns¨;wmsè«õÄ6‡¾6¦9T#¶7ôµx›ÞPWFßÞPw?ÙÞÐj$½¡én´7´rÒê"¥Ûê×õ6‡V»/í m‰dö†6EÄÒš²SzCÓݘÞP—¾ÜÞОš¡Í¡=©Òîнg»CSwJ{¨ Òl{h·Ögwh÷—§;´ÛÀ—îP×ÛîÐn?0Ý¡êɵ͡v”lsè°á0͡þÀ4‡:Ía›C‡ãMiusÏmu{×mžðÒ:USs›CgR¢Í¡îÞ–zàtÞ¿õÀ5 ™õ@lBΰ8UÚ+å@>Þ–§_8)ÎtCH „å*Ÿ”@8¥òI L‹]*°r'áHä¬a!0솑ˆ‘ùñ…NêS œ·ÞR£±NJ ìsõ¤Âa×NôƒíM¼/%=-úG Ĉ6‘8Óø`%pߊV§‹¥;B¥m¡î„·m¡ÅºKÚBhÝÎP—öÙÎТ—Òv†K q8ìä - amkhIî´5t­¡%ÒÖÐ׎ɴ†ºsZCßÔâl -^¡§5ôµ¶•ÖPOÖÛº÷ck¨ë›Ûê´õí m2^¦)´Ú-œ¦ÐnJSh3‘¥)´ÒÓÚ3HW¨ã)r…6ÿüi í‰l¶…v$}¡Ý쟾P×õ߾ОOûB‡VÉÛ:drØÆPómúB]ª|ûB;Ûj+ý¶…UÑH[è”ÑûB]?sûBUìoÛB§eË´…ºÕÃ?QBît†öòwwv»¾äHV¿Ÿ§8—]H³•þ¶/Aâ1¡š@h„ ( Áóãp¬µÂ¹÷™êS=…Ôt_t÷öÉ¿3#?lÿbE„_¡+ʸ|†.,Ì–~ç±™„@Ë®s #Zh\~Aà‰!ó@ ˆA™zŽŠ¹5Û—ÁF R ‚p$v&0*Ap 8$[2Aprë/%.þD ‚Êh>4Jø` LÀ¬›QÉð¢@l3F œÜÞMhéMó•!héCÐA¶~°9NËZÃK´¿¡ÂÀÉ­W‚“;ú 'ëÆ'Ê“ˆ#Ó†8å6%NÖŠš =^xö¹rZNÆìŠ'>Qaà”&@ œÌ”#F‚)pq# Qà\ð¦-½c¾ ðTÒõ@ -°Ê ÏÚè–ûà‹BàRª ÐòÒ+Cpa1 -{ý´äƒ~K€¾‚ñ_m믠P›Z %‚5‘‹· ÚbÄ-'.z%¶tðå)!pq#)Bà)þíb@›¢ó+(té}$Út‹\D0 ¶®`,0 MÁóÀ€6U>¯A›N‘Ç´ ýÏë€\Ü[]¸àu".úDÅ€§èÚ+ApMæ‹‘kã ϯœ±k‘éKɦ„ÀÅM2KI€—º„ÀÅbQ‚@Ía‚ÀSÓE ða8,!p)k•¸Ж¨…Cä~Ä’m뇪Á³™W}ë€VC| °„˜0JIäf†!&2+U@Æ… ˆÝ9CdŒOˆ€ò«HÌŸEÀ!\¡2ÚI w³ 0Q2§hû4û»' PáÚ‹èŒ"`áD°(h”" w× 03•X"`Õ¯(Êp‰€õ‡Pä¼ ·» °H'¤(«¤Ò© ÷y ;I,Ÿ@ðtìB¦4ÀÊÛ. °Bù °(”`c­DÀö /K"`…K=DÀ†®!bÞÞ[dÒ DÀ&" súCävì/ð•#x4ô* k¦RYj?TÀ&V¤ ôHþ·™õK/ñ€å‰€b“D@n " w= °“­%†æ'6HlŒí¤8…pÔ¤ƒ[Dœá%úð'PʰD@ijç›]§vÙ …ýÐY¦ô¥"L34@Ÿbnð…‚GkwÝ04À~§žnç ‚çÖxÔ£k€Ü´óÖñ~JäŽj¡ýŠ =Š¡r‹„[ôMdBäæ©·ˆÕKD®î¥>w8è ¶q²–81¼\ Bª%NDîR ù‘`z>цøyU‘KO²j’¨Z”Ò~< µ‘øowE¸ûˆ8>ŽøÞo~¼ŠÜžjÞù×UmmQ­I-WµµôX­Â¢~ð׫o»ûAËÝÏWúG–µøëîmW?lyõ3sô2óç>f~÷0?U³ûcªÇí¡Örþ²êq©ýpñ¸½<ýáâqµ´iñ¸O¯ð¦Ôþ1UÞëË ›ÎZšÿŠßFe8þþ. Ç>®£ÐÏë(ôµáØ×]Ž}]G¡¯×QìKÕáÔ×UN}ÅQìë>ŠŸ¤êñ¯»@œ>å8 }ý%eäˆço©ŒÜo •?ø¾78þüõ]ý4X~ç}ýÒÇ—‘Kæiٳ«\TŠû^¹«ÌÜŸ«ùöW[=.='pé·ëÇY¹´ú^m·/õãìߣhÜQ>®§|ܯõEãöÛš‡¬'Œé5Ö¼[jCuÿÝÒªÿ»·¢9—üosëúßËÌqé¾ç]˜CÌ[–w’˽2@mhYžãïQå»%¯¢ÕHø•í_êìŽXï\ÿ„ël·´Ê–ƒ»¥{Fç©--Ù[p€eya€3‰Àƒ=‰1kY(‹×pÌ)hï¥óüÞ”mŠéMSŽ[±3 z·l¦·Tü &,8¨wKG¡€†¿ÊÀ‚2ÑYÓf·¬ãSì,Þ¿—Ç×XÜÖÍZŽØô´¸ƒ¢ónɃ-8WÝ lßBÏÛà1Û¯Ià!»¥—×xëðúN¾ûøÓDéÓ0at³Dü<Ùö,lM›U? ÎÛpý xµ[pý ôg+Ò†ÚØöõ£$ν/ß+ð‘˜àáõ n^›^—5X°k@zŽ«ÌÅ6,Ö8´º[l/ oYþ6Xš*âzm«ZÏÈ/~-P8ß-ÛoáwÝ·^V âñwKé?-žz²[¦ç˜skݲ¼„€ûÓ3`AF²…µÐ„‰aØDq䟄»7¶ (0Ýð±MðlûŒç=ê™G•ü¿[`CÑk5`Cî“N ¿îa „Þ‚'5Ìcÿ-JìÉùyüï”ð÷úð aÂn&µ[dƒŽÙ6xÒ¾£Án© åô«vh·à¥Øðøá!Þ *8}·À„ª1bZµ§+PÐZÖÇBËiXå4ïv¥‰‚‘¯ÍÚ¸M‹¿‘ CÏžÑÒ1ðm…MU½[N¹×S à˜‘Q1’Ãܲh5oÁû·`sɬe¡¢žæ^ L´°aŒéœlìF¤£‡o'?¼~€ß{><^ÒK&û¾?¼Æ û‚>š§‚«v‹Lp7ëné-i¶[jðÜ3Á¨ŒïÌff쎎·x,‘¤ ’Ʊé>¡É]YÍwDv‹~UΊh&¾m¶KÛxÊöis£Ð- ¸N42LôwdNî(ø,mVvƒ@5Éfe„sãm\Ï„A˜áÒ²cð.]>8ìÜ‹%~¤FÜ úJù }X|]Ї…¡æ‚>|Ðö Å}j÷a]ØÇ5±ïjöQÔ ì¢,ð‹ûèľ˜_b߀2ØÇTà>nÿÜ-E&` ÷¬š‰}Ü)(°o ()°qn}ÀEäŠáØ7?Hé"Ûú4Ù‰ú& õM=}Pß©·çwÔ×% úT9^Ð×Y’GЧ’|‚¾Î=d}V¤/ár•‚;ÐgI™¬kTPŸ61õY¯ë…}Å*„}õ7YÀ•-°Ï ?½°¯ÏÀ °¯sc:aŸµL\ LàØg~kN‚ûTxPÜ×WÐ"Làw?ó8€8~}éÑüîcüúÓ𳿠c²Ár~[ÿ ü:w^øõxæàg[Àr€_g&¹ÀO…~—Gà×´VŸm9€àg-@Ó~×o~}鳜²aòÙ Ǧ¾è«÷unNÜǤï?–i ð{ô½L™€õ¬Àï Æ5=\A‚ü˜äwò»Z@~"I‚üžâ"°é¡¯ÜÇzÁ}@•Üw# iQ`a@ì{´°PÑÒ¥Öà>Ö»î{0 ‹ûäP÷=ÈW îKj îcäà>Ö¦ îKä]q_ÒBÜÇ}Ì ~"É~±"ùqã² ?–q òãNòA~I«5’ŸV:¿H pJˆÓ ð‹n~Œô ðK"2Z€•cFíM.Z~‰#µÀyj~éƒPîKºQY×Ï•xÖõß,ðC|dp_\ ¹/#§4¸ÅNÈ}™Ã ¸/ã•ö%ñ;±áœ}YÎbÃwû2]bÂ>ŠÔ—ù-‰ú2Š2õeD5õe~ý ¾¬wˆÔÇ2 A}9hÈ”¯Ô— ¤>” èË×&Œ"ôá.©/ó ôÅõú²Ö÷}Üo! ¹:}E¡…Xxú2/d¾¬æËô‘“ùF€ùÌ}+É|EÌ.P2ŸÝ‰æ÷ï0Ÿ97ßÌ7˜)æ³’¤<7L(4Èw*’‚Õœ—´»Œ˜o0‹RÌgÝ`üó FÓ‰ùN? 5™À; 泈Ïã0ß`t±˜Ï®ÏÌg~T`5˜OµXÅ|Öòf¾ãÕE‹CÓ@•r!Ÿýˆ¼æÌwâÈw]Í”tDM”—哎áó*טϼµ/ä ‡.‘ÏZðL€|£È±ä³/ù¬!~G8Qßð辋ú·)õY’V‡úT SÔ7bê›±hõMÖŸõ]-À>kYlYàÙDörì›Zn€úÌÁA%ÏM°CˆtnÂq‚ꜙ•âØ7YkIØg¿¡¸çØg¿)/¹o>RBŠL ·Øg-”Ø›NéoÈôõõÙãE}Ž}áéqè»ÿåÝÅ”oëeP_8uH}#´ÔªËçú½êòÛ[êôéúæóQ_JŸYˆe- ïº½€¾ëAVX¸DELâ>ÏZ 2ùÎãx }“' ùf,4|Ê¿òÍç â»Þßõ¾ùN‹ß ß|„K &ÀDä›>6*}CÏŽ©@5G¾ùˆ†|3ÖÓ@¾ëöRëãN)B¾Éõ4‰Ow¼þEòÞ}ê•n' yÏŒnl¡¸›À=ûà ¸§öâïJ·/dèÚ ÕC]<ÖmD=•ZêËõ'½zó!½sÛ(ù- /Ò‹N¦®žã @ïúh@z*S+Ò³_é]7w†¤ÁÏô†˜ õpÞõ €óìZÀ¡à€Þ¼èÐI/® wŸÊAo²Ú›@ïz”K …¤7¹eHÏæšƒ^ÜM‚žýÞèGÀ¡AÒÓõôæ£-@ÏZÖ ô&¼z÷õ:èÙ¯°¬La¤Ž”îéœwù¸ÁyÖEy)|ñi‘óîÓ„l‘\kôb\"èÍG| л.— 7¥ô®såÌ·Š_é÷ˆHÒ»Îҋפw÷꨷*Ë€7èÅwBлž5Ho>Zƒô®_ôæ#˜-°@Ð& x_€z“Å¥…z3Ä Þ}Ìdåè‚ ¨w_ŸlàÙÁz1 ’õæC ê]7¨w½6õìÔ¸ŸU&páYeù ¨g'/Ô»µ´~›láúçn2F5™@ø q ”Ö»ž Xïú^ëÙo:€±sýÆï¿… <µLà—Ð$ŽEË‚Kæì™áp*…ÀoÛ%ðqØè²·°·°õå-ðÑN |äCé{:µô=¾¡ïñI…¾Ç3>*~Ò÷rú¢ïázCߣ•C%ïVè{ùÍz“›—Qß“MD½Þ)ïÅÇAÔ›(ò^Øò¥»Ì5ߪ{aå=}?T÷âÍŸ2à!^߆‰ ô„×Ð÷8øPߋד°75‹,]?ü%øÜBßóp“?Sæ-ÏËÜ€W¹< ßµ†a6Ò)РˆwíÉicÁ ¸³ðàîÜœ°åüÀv Ú!Úœ¨uÎv£IiÛq¡Ý`eK¡Ýiñ†ŽS9t²‹¸’µ¼9-×LºÐdwƒ0ÈŽ·‰dwÿÈÑî5ÎÑÎZ¨ÆÁnI ¶Oè ]D!íîG»Ñ/ùîEŒ®«qý ¶Ôõ#Blwý aÜ7Â8¯„q^-ãdIR†qöç§ëEdWŒ&Â8£S†qF'ŒãìÆÇÙÂdW Œã¼~…8Nq)3 ` g×’¾Áõ" ¼ 3É¿b$g\1#9;êJF$gØÐö òêaqÅ å¼~…PΫe¥×ß#l`˜æÊyý a×1å¬tS+”3qBT(gx3”3 lÊ™éžW(§Õ åÌŒyA('óy#”ó:6d È åÌŠXg('K'D(gQ$4%½‚œÅôJ`ÂQuŒÂQrOÒ+ò²QÒ‹@W—ôŠ"”)éÑ!%=n’^¨RÒ+tPQÒ+[¤é]-Ðô £¤éUÝjzt¬JÒ«> A¬ Wžôv½RÓ«ò¾SÓ«Ad G…cE¢^eœ‡D½Ê§)Q¯Jˆ¢¨W鎑¨W%QÔkÈýQ¯JšH°j1D½¦EE½¦EE=Vµ Q¯‰)ê5…îQÔkÔ!еÀNˆbа•¨×´Š#ë5-·(ê5:ð ê5™èª^ûx£^„íJÔã®—!ê5†KÕcµ¨Põ4öIÕëZoQÕë Y/"€)ëõ/²^„'Ï·d=ÖÒõ:ã©¥ë±TbèzÈsY¯ó¡PÕc•¬Põº$YoHÕ¡¬7„Ó”õ"b–²ÞZ±Ã}ço` ®XÎO¨wEÐF,§t>¨zˆKYoŠz›âQ±¾¬7õè(ëM=^êzSúvsò5w]©!ëM”:Yo*d¹É„A®n†Aé1~‘²^„‘RֻމpT¨ŽÊ™)ô‰ô¨¶QÖS¢d=…ÖHÖ[R/)ë-©¸”õ×êÒõ–¢Ø©ë-úí¤ë-~«”õCœ$ë-IÞC&`q.Y{z…¬·1¸[dÇå¤î'ÔcÐí¤â@=©oB%:‚õp¦@=Q›P·øb=x'‚õðjõKÒcœq‘8HÉ;Šä|¤ûé!:L²+ߤ—,üÃeÝî`N[`¼ƒ9Ûø̉hqsN-ÐÌ9¥q0˜s’êË9µv`,gĈ1˜sEtçbàÎÄXΈ_"ù=J‰#ù…j@ô{¨í ýuƒý’–¡d?Eƈý}"öK"F²_Öœì S²_Vá/–”„¿‘š•!íÍië¨uÃ_ `X®1¡ôWÌGú«òÌ“þªVg¤¿& ýU%/’þ#*DM¤¿¦ë ú“'ú+A|r¤?Åw†’$‰Cjño0ÐŒô76Jú“ßHô§´Ñ§Á_Ü„¿+xð÷)œÓFâñ†¿©w‘ðI„¿Å<ŠKÛSȧ´=µHÛ£(Þ¥Oö/Ú†ÞKÜclqÈ{|Þ”÷X9*ä=¾Á”÷RhwC×>!}/£8pè{Ig¢Â§P'i|™QwÒø¸ïYh|YD¯èë¥ÆD‘ï§#ò¥vRä+Ê¥ÈWžK•¯JÊ¢ÊWôºQ勯Œ*_¥â!•¯J¦ÊW5ÞPåk ½üYù7ê~ e¼ËKækoô›-"5¡ò…ß‹*_C™¡Pùú§hÎÙéJ‘¯3êR*_W$U>VÞ •¯+Æw…X¼Påë s‘¯)š‡*‹…Ê7]H•o(ë*ß È+™/ò¢(óM9h)óM-É)óqëøù|-™o~¼T¾©P<—ùf$àAæ›”÷%ó-­f)ó-ÞMÉ|Ê—Ì·¸rùÙ:ë[Ÿ-Y°R¥Ê§Àf’Ÿ=,x:ù-Ê÷~+røÙ?ci ò[Ò ò³ß0À"ßÒò—"ß À„Ê·bK™/· ¿¥Ôn’ߊ`ŸM‰¤C'?«Lþ\2ߊðHßnù”È·’žÈÏ ifȇN~VªœtèègS ÒÙÏ k/¦ö¹ Yal`¿U>Þ*ŸU<ÇègE4ÈhŽ~+)ê ß*=X™ÆKô[…±Ð ?k`¡c“ÕEH*ÈoE4ÈÏ âA5ÀP9%üVâÒÜg•ß™¢çÜgµŸ‹ûN¡Bü Oñó?•¡øg¼$>{ÚóÏi—ËðH¿€Ÿª‹ ü옷ķjÀ¡SÓê¡Å95™QãŠç´òÝé¥ñY^©üì7˜ç64…;üNõøÝ-~VŽr“ߊØQŸÃt<ØP™yAò³­óE~V~•)zÿ ú_@~öm4‚Þƒï‡1’@?{õ¥òY©z- ›Ü'Kƒ5\œ`ëv1òxX ^“ÊðÙh_ ó2\j.Ôñîí%L‚w»T€2p¥6eàGA÷ËKíLà‹_‡pÈdÞ€®fQñÛÛdfÜbsò+QªØÚÒ1~+ÌÀ QZeÞ\—¥5æ $e·ÐDÍ–&øêÏí(2pL—ãv¿õ¡r6mûv6*ýñrCsK‡ ‰#lé°!1µô’ÑÂjßXOKéíAi#¼Ÿ½-T6Â"¡ô>Q˜ ™¥Ëĺì­£ÊD髱V“ûßÊx*Œâ£ÉO ¿Ø¼ìFÁ5TLÈœ.Ë€ ‰¾Ô2ÚÃzMjY¸ Ì}²^“»N÷—0 q!¡£Œ°ýÀ†L ³ØÖin⇊m¶¼¶œgýúmVN~%øJmVö‡Â™eâú3½™»eᡨ¥OX„ïrŽƒ0âÎÙam¶]Ó\²{ði,\}¡[–®ž¿²]ÓÖ뾬âO ãµ²y9Ýb±yÙmZøI[0 .Ç=¬È_#–5ÜÑT±]Öì!9#ØŽiý«í˜æ6ᳬ¶gÚÄÝÃ1²s}`æƒúT—¡ T›”aûh ïªÍí‡;!9bl¯ P¬k}`·LÞ-«¡w¼ÚŽin<ÕÕvL¯ë³Óü9AZ«¶eÚz]O‚ ê6ÊhÕfeoÁQmVΰÜÆ€QXsïgÞñT°æ®I&@;¯&ø1«±7`íYs¦8Œ ‚j;¦¹Mäªm™æâ0âUêž•ýbü%¯Y@Õ©6'{ ÞÎj:· ±ƒ5O‰Ã¸y5O?]Z“»'íÙW0 ÚÀï‡+º]Ð—ÏæŽôaý.è@ôAǽ dÐGzóaî󩥘ojÕÌG¾ æÃ|Hæ;¤ˆx¹%˜¯s£e0ß!I0acQ­Ì–ÎjÐ4’Ì÷h‰OæcJšïáªPÌ÷@âò)±\ȧâCB>ÍÕB¾çƒ h%úŒ€Vp‰/ •È—ÇD¾$!ò%*ÆB¾‡_¯˜;AóITó¥/0_"BùC­Á|I;et|1_Bx¦/Qˆò% ù4C ùËÐ ù’î(‘O•xÄ|™!V¢¾G¯©O·A}9p³3ƒ€¯©/G/“x±}1qú”à èÓ´KæË Ìó)WAЗùµ úXÆFÌS¨3_f-h1_$¬ÆE×# xê$ t&ik‚>–óóeŽFb¾¬UN’x'Ä|VhÜço2·€#óe=b¾Ì€%1Ÿæ 1_¦Œ,æÃfÜ|…ãˆû¬ñVAñINñiÆñq¬_aÞˆO+_aØ–ˆOY(">Cñ• 9  ŸfoŸê‰øp%âS‘v"ßP¨™#Ÿ u/\TD¾Áðß)a ñʼnI|…#ˆ¯èkª2€Fùîcœ—F!²‚øì:/Ê%9òE]&"_Tw"òËÎ9.E9"_œÄw58ð’Fl¡pkø®«ðEy{_šø¢(¾Ÿýý¾Q›¾Q„–¾S– -NKQŠÀwãÄw®Ç8ñ n›+⋺V$¾ ë ‹ñ´`ð^x-÷¢hyïúI€qpÈÞ<à^"îE}*âÞ©F…c÷†0ˆ{ò»’ö¬£hÏZprÐ^tÚ³#ðœ@|§ÅªJ‚áZ|§æÖ øì¦!ðE].ßÙ¿š¬ ÆWÈuÈ|‘ Fä 3!òY ¼ ›£Þ‘ï>‘ïz¸`¾S©g à0ó]6ú¢¡ÏÜÖpÍ¡/*oú"5Л48ôÅ;ôÝ}4z¿‘ LèSŽ™/»É|q;É|÷‰˜ÂOæ‹u#™/¶ ó™ÙDWä¿hÁŽìÿÉ|Ö‹¿Ÿd>;&è:øˆE"ôigwAß}Ųž7BŸµLpVâ¾:&s_ ò/¨ïèhqê;œ”÷|»Jh’ú¤[ú.}!ú®›è»Þ@_¤/úÎ ôÛUd‚¿§¦¹Áöâ>mdî‹d.r_$j‘ûlýZ^Üg\‘_b_lm@ð³_'ãï©rüb‹‚ŸµHnû¦H•b_ôÓaq¬úå¶¥õuÆ]‰û‚SÉ}׉Á}“îBßuŒ À\ òS\°Èo†—™AgŠÈorõ ô“c_è'QAè×Gô»Î4XXBýý®c€~Cá” ´jÊ^Ñï:è§Ç@ô‹KvôÓvB¿¸YS& ‚XìLöSÀ¶ØoÒã"ö»ZÀ~S ºdoÙO&,©eH¼ú]ô‹w‚èwµÈ,…~×1 'í«!öÓÇ!ö›Œ(üéj3P6èì‚?}@¢¿I¯èor ÑŸê²_Šß'ø›ÌBüÅ’Ô²BjüM1éOãÍ¥øÑð$¤Õ…âG}OŠ_7ý]‡âÇ~¥øaÔº?ž)?öŠ_ù¤ø -rBñÃlu)~HHÿ)ýVüZ'?1Çëî‘ÿâî‘ÿfHlà¿É½ÄaS‘f‰ sñß”:BþãNz¿ùABìó“E¤¿Á&Ðßäúô7ů¤¿°‘øwŽøÿâIV]?9¸êú‘-ü»ÎÕ¹ï ùï:øOf×O&´0lBü»ZOCkpâßÕOå^@|(ÀÉŽ0nN x®ÁÜk¾ŒÀ0“Èíµ €ÑKÐ P/ùï:¤2÷Z-à¿øQcö8¯…ø7¸¤þ]ÝÌþéA‘ÿ⊠€zPÎñ$Éq;GXÀY@d Æ© €1²¯cÆÐƒBËF˜€³“Ãpà lå¨ÛIþ‹^ €a÷ ðªMY _u.ˆt-c|²‰8¹þêrV€!ü‡d.‡øí:þÅõÿâZˆq_ˆCײ. ÐÏàrˆz*ño†þ¸šæ#kýi¸ýiØýér@ ýÍæÚóæDz…3H4 @ƒ®Ÿ|Cú“Õ¢¿ÁqOôw“ó{”ýÍOô§û’¾X@ø»:éó5BˆýTeXìw',hoö‹ÛGöÓì$ö‹ÛGö»~UŸ×«ôtÉ ýægôÓ»)ô #‰~×1‹+!Z@ô‹k)²@ÇÈ‚$½ï·*¼ ÷<›5pOÞà^ Q¯æ·ÏA¸'ÿ‡pOµÈ…{•sŒpO˜/Ü»Z@Kvá^å|&Ü»ŽÉENo(åõgͯk#íE "iOÙº¢½ÊÏ^´w7®Ÿ¿ŠëG i¯r°í]Çdz† Ã4 =CXƒöª¢W‡l(ŸhïnYo7Šh¯*üsõÖùä!ìÅ1ÛI£"¶“&Dlg¦F§ØÎòÜBßÕ¯LÐodoVwò1ö®~Vÿô¨H{q iïj‰øT°]ÉŸê'Ï`/®Ïa/, ì]-a.p¹«¿Më]-I{¾b:#ëéTb½«%Là¯Úó¥Ee¶ØÒïïK¨ S¾-¬:ŸËHvaÁ[æ»éÅ!½ªé˜ ‡Äå÷7ç…Ñä¼ë˜ñ6™œwýfõ×SæEC\?µ¸\Þ&òâ¾òâD„¼«@^t×]>Ðq¾î O>Mž!à]‡ÄÅùâêñ#ðÑuø(Ì!à]Ç€ð®Ö¼ëZ<œË@Gáq'à…Wž€Wé‰à…/¿Ê#}Ê Oj^ÓÁ0H¼è¸Þ½´°á“Àú /¬"á]Ç€ðâjHxºM&P.iaBJ[¯ˆÎ»_ðúu¼‹^» ` mðèÈwUñ{仉BߣFÀ»~À“ÛûÒ÷¨ºðâ5 o½:¯“;àŇÀÇpòPø‰²€šû<–¾ | ¿êóý˜Bßcê¼Å—ÀG±.Ô1â›Ô±ôâ;ç w—*W¹~{^ÑœCK<±]|:·¸ª”¸ÇgD¶»ŽY\¾±ç÷Ò›íâÕ m‡Pƒ—´Ç–öÚ›í 3hniÇ„2F±/¤= ‚’ö„eöûa‹¤=ô|K{í†;Ý+ÀÝõïÒÅ Ò^Ò¬¼µ=ž9ÄI‚æTjt»Ðöx®$]ŒBch{<{h{áMÚžŽ¡ ‰Ñ›²g’.Fí1´=ÚÚžŽß… ÒöÎ_¡ëR.]g]6†®§c¤ëé˜w!¸î$W_Ÿd{|N!ì©_ {<&„=ÂÞÈÏÌ:¯î ÿ=UÝ®€N‹Š½:çSá{Љlt.>t.-âѹ„zeña`éE€\S@$‚¦i÷*x»ÿp)~€/ê†:ðÅŽ$>Ký‚ â›ÚÝŒÈ7µé‘/¶ñ òMí’Fæ‹-:È|S›=‘ù®-0Ÿ¥!Z0Òø˜gÄ4>ä¯(Ï)Òø6‘Æ—y è‹ú©„¾™aAÒ7Fè[,¶¨<¾¤wŸy|‰™ÊãKÌ¿P"ßÕ²uƒ I =óø’ÄÌãS8¾òø’>ÌÈãSŽòøRäÊF³6™ÀôßÈãcbóø÷«¹òø¸pfܘÇÙ‰‘LJ¼¯<>†!21ûWŸâE•Ç7€oJã[:YÀhÁHã#yw¥ÀL"ÏÁÓørtJãS„¦Òøø¤"Uì¯4>Gbe”Æ—ƒ0•ÆGAûJã[ŸÓø(É3/‡i|z‘Æ'žŒT>¢"2ù²ò•#“cÍ HqH„KŠŠg*_}0rùØrùÊ;°óúUäòµW\çT„Rùøä˜Ê—"Oð·X>L¹|Z*—/±^¨rù²¢^"™oðÜJæÃ†W2ßx {Vv´¼„½xtÊåkwX§ýÝ^aÖ)BÉ~ ‹ÐoEZ¡®¾,¥òev+•ïJÁ‹T¾õB¿;¹©|V|-Jå#‚%˜Ð_ä7U‹B™|Ê›P&S”ɧ eò);D™|9ã. `HƒSòŠRù"9’©|JôP*_æT¾ÌáèJåC ŠRù®s#•/3‰X©|ñÎ0•O¥•Ê÷°` Rù´Yˆà¯#Iô®êf5ÁPüjƒ]·¢º“UÝðo¯ªn×qüUÕí;¿ùUÝÚž£úÿº«Ÿ¡í*šÄ–»ŠÚ¾)ª±ñ¯W?Þv÷ƒ–»ŸýÖ6ÿúïñ×ÝÚ®~ØòÇWcköÓ»ÛoÔ?³šÀùK¬/üF‘¶ù.›ö~WêJ)ŠY}z/úbu>/Q忼ˡٯ_ÅÐÐÃu zyVóžîbhÖÓ«zºŽAOï²jèé*…vzº ¡±§8†=½Šªá¿ ¡YO¯biüRâôôK«ã,Àÿ–j¥ýÆ@ôó—aå{CÏÏ_^ÐÏCÑ××ôk¿£VZ«]ü®•ö;Š¡ýxµ3+ÀV÷tÝÒ¿ Ä™ƾڿÚg¿~§ÄÙ¯ha³­(bfÿï?§…ÍJÿ3…ͪMXæµéß»Ï[òq¯ü°Å)u·œ•XJÉXeú,EM]ÕH™,PWë>m.õEÀêg)i ,/Ö8KIƒ4þj$µÃ¹ºçØŒÌb„µçAº´ÿ•Ü¡Åÿάïõ¨E*‚û-ÚS&vVÂâ¨mLb!¦_5n©úöt.Ä 5*«·âÒüò§BûÚ³²—m>¥'¡¼1ânZJg ¶´yKùùf;€höß¶³8Z:—o%—á:ÚHm—ß“Ÿm“ÖiQ]ç½0´ÀÊ2Ã…Ò’yTO Í[²}¾õü0™nçvý½h˜– ½TV+h{²–šé¸Ü-æ”êõáÒw/ìïªëËÅÖ‘†»X—·\mÙ{fÆGËnÃpn·aªŠÙ~ÛÌ)5žN‡mËV0âÛHª+в•ß-…›ó´ò˜císöj+džakd¥w‹Ù`Ä §nÛwé´LÖ÷ÙßþMíÌEÇ’ÎZk°™9Öl÷¬—ÛfümÕhŸA+nCTlÅJeìëSV^+VZ}÷¼G±‡ ›†íjÀÙm£YU ƒ»Åæ +%Í»S݆³c¥ŸË(s,…$í)`÷aË÷jËkVXD«Ýk3ËûÑ|^Ÿû-£ì9Æ,˜©3ó¦ÕcÁlq?÷·k-=ÁC»ï™y¥¦­/ÜQ°[̯¶—ÿL¨oûùÚjëQ¥›¶ïŸ­Ñ²6ºiæì±Q e¬6dúj RÆþÓœRSÉôíˆç4‰-§Ä±U£†O¥Y¥ëúÍ|ç|úݯ?¶Ólý`_ÒnYÇ$ù­ZÏæ“²ÖH¨Ý#—¹Õl(ÆÉ{5¯šmHA ì~¬ªmŽ÷]v ´«^³Ïd¯Lw;j£íaÕ\R«?úXºÕpÿ¶eü=ªšWm…ƒ±ïfOÊûb0|Žcíôᾤ6޶/ч{öh;NË~ܸ`û¦µX»·4óªÙþAnåèmÛTôBcm¢ón¸öô3:±zè~y`~lœwIµ™Ì«vN„Ïi¦uŒz¸ÛÕÄç1Êvr3'L(K=×îFY%.oi§TñÔs¯nÔþ¿û™ØoÖ‡Ïz{.(n•}­§&4«OpZÖ1Á¼:ØNlOÏ1j6^Þ²¿Ùî6¼Ã+ÏcTåÖ#Í^q3ªs³ß¶Ü„´Ÿ Føå&$›*pö^½ÅðÌ[Æ©¿œ6tàkÞÓ²ý½×íøÛvøf»_àjºMÊf•íS±¼6ØÐÒÐâ6Xùê-öŒì¦Ûà{Ê8F™ÿ7yKíǨƭ·÷ ÒÎs©ñÆýqžSzÉ[Ü„g%v<³Û4ágë{fþvö9&u³ÎL:û£œ†d>5Ûdyì–åOe¿)ÞkÂõÛ~8Æ ÏϳpŒÍv­²¡·4;©mÆçC·Ãì9•¥ž-Ë[:Z`A}üûÙ#‹]^³™ßþÜó²ý¹OæÇÛ¬|žQçý·Yùؼ/-Ùr¶%ɇϹ=ãúm2öûqýÅêwzËqØ&x«zîõXtv>8 V—À„'bÛ†MÿnƒmfiÛÔ^ܺB{±MæFÉmJN~ ø‹ƒžÁ#Vh½Çÿä=šgy±»!!ïÍzAÞÐvC¤¼(‰Bʳ#3øËIO ô"Ÿè€Þ©2Ðñ“¼ ÊÃbç¼£‚¾8ÏUtÒX6åœw¶ÃÊÕ9ÏZtÌt_ûbt8ï¬qqö V­T‡Ày¾[ Èê0Ò٨ЌólqŽ?óž@/`ÞÓY‡˜·ßPÒ80ÏyãÆ<ût!Uóö ¿:˜·g9†5ó¬²0϶Di5`^G¯Žx¶a „Óƒx½è½tÂÛƒ¿˜Ù Ϥ\Èö ¼=4ê=sÂ3ÚEÏ"±Úx=Šðú©w^âð¼~ŠŸy?xÝv:+àusðç6̶C"þ¼³à.÷à]_ð¼3X …9ÞÙ1x[œîŒÃ' êÐѸ¼ ŽwÆ$·Cw#7†zîÆ~ªúÑ¡;hÄXº3,§?ÈènE·€î†=`°ã$TàƒàÝ0Ûñ+Ç»[¶ïFDiïl°ª8æÀѯý%tº1ÜxðÎÔl8ËÞ¤s€w¢¯€w3sSXÐmæDW’ÓQ ?XÇ»#ã[s¼Ûh/WƒãÑ_VÇ;£c$#ï,b ãÓ5 ènÚ\ÁSu;‘¶†ÞMÛŒ½ºEñÉ ;ÛŠ×ât·lVÄêt·ŒhyÏèÎöH¢ÏéΔu\ÃÁ&Ív¸³«Áî €»U'µcÀÝ&c!ªÁÍ“œqîlËGÔüÝYàç-ÐN´2ZUÉ7 ;c3¾FNw+"QAwëËP÷÷3A‰Ôsè/‚;#hÜt°Ýc#²7ÚÙ®¼\G»'ƒâÀu'ðãa…`tÖ™Ö@E§ì¨·ë¬ä†·ëÌ}BÖÙºÇëìáùR˜Xg zv*²M,ÐϰȰ„Ø™â‚AvO§;@d×ö؉_ÁÛÔ2²xP´€ŒfÆ’ìŒyÎE²ãxdg»'z È®ýê ]fD,Ø®Ó5!¶ëܽ4Ø®Ãñ ¶³`ïl—®6‰vYñF; eíÄJd»E×ÙÎBüÊÙÎÖx,‡íìÔþ´ËöANü}Ð(ïEÝóB»œ…'@»ý1~´ÚÙ¢»áWn@~ ŸÐÎÎ…g º³càبU]Ó].Z«ƒîr³ào96ì#ê ïòQ¼x7èB"Þe[û¢_Ç»l1™@@Ç»=“P€w¶­60x·¿AA!l8ûx‹ã‘m½ (àå³Ëæ/Áwùìù ñΞ^zñÝYm¡· œ_þxg‹-¸u€wÅ\JèÆñ®q:ðÎb<0Ôïʆ!ÐøÎž;>ð]1/  šyy8lðl]î>€WjåkÀ+¶(6ìcج_€£^Ù/$[œðJÍ~^é™o1|‹ØöcM(¼D¼¼øñêeRôL‰»H/¶õ!ê É3D½+¨g1Âõ…zS{²õÌ'‰šo@½Øg—¬g©ãÅzö9! ¬·T¡°gé\éìF °g+2N™{{a}aÂží¡Œ€Ï䢷ªg»b}IUoŠP|¶š‚^@YoÐNßœ’Å(í*¥½ÌJŸN|KÛôøÖÐZÈg ynƒm” §=oÅúÒžÑGË|({Oax4•=SÎÒKÙKН¤²g[¿„½ÔDøL //âKÚ·šÄ—T˜Fħ²ã"¾§ñ-Vñ%ñížßÀg*8Öc>Sðè|IÂ4/5©§€¾BɾÔÐOê;zû­ëÙ1TzA}©3®ÔgYHRÇ&»>¬L}»dûö1¼]À¾¤„1bŸ-‚q.`_*T8*L\X½ x\È}¹Ü—Jðæá¾~xb `î0†ƒ_·¼F~,ýæ¾n‘›BŸŸýˆ~ ?Û¸—‹ƒŸƒ0ö~}ÄÙÀï^?kAa€_7…qܺ^·œoî3ç£uî3XGN/¸¯ÛØÑزÐBÊ;Ðd àǾ3‹@hqì³t, ¶6Žš›`RPtZŠßhê6¿T½=Æ´ûz¥šì³Ó=ÒöY7x®¯š)w;õÙ!õÝ¢½cŸ9?(x;öíU 7Æ:Ø7² nûì|™Òà±àˆïxLÎ}#ÙäÜ7Ja¦¸o”ó™\Ïݙ¿8×o¾zúÆþlh è³2¨Cß™’ñ úìVè> ¨G8; Ï‚îé_pè³ 9úPúú’3Ðwžî•C_?‚Á-é™7 €¾>§,wè³ ä¹€úìMáÇäØ×Ïþ0Þ°±Ï@Ô>°ï|£ÚÜ!¿¥v€~çSŸl9&Ø7šÁl‡›Ì!•_ì×£Ì?ØÏÜXìæ ß°T=ŠsÇ‚qbìø õž· gG á‟¥ \$ÀoLùf~ãdFóøäA¨‹~£«öÀol6œù76è{øð ™ƒß°/,ß’žy®àrø7ÝÀïì(~Ÿý!à72ÿZç»Iºo}#MzÇ}ö†ãQƒú,3aÞ ¾‘Ÿê³Ñ1ú,ÕíA}{Úb¨ÏZx_Œúl§õ.Ì{Ž×Ï̱Ͼœ UíPŸ­šÇ‹úì3ÁjÞ¡oæÌaÐg-¼6‡>ðú,w/3ß4¼\h9Ìg-pMƒù,Ò“Ûa¾¹×L|@Î|óQùq0Ÿ¥–"ÂÌ7&S€|öfêwùFìä³7³ç]¥žxL=1ȇ¯¸gct¡zw¨mlÎťY9îYRŸ ãžíitðž½µ|îÎ{ÇG‹oÏyÏfLïðžØ|×÷,É£1xÏf†„uÞ³Ô¤A–;°dó ¿jç=s4Ûc¸7R¼AÔóì{}á^š•Þ' ziÒ+Ü3_ûuÜ3†˜ ;ç=‹_€O¼÷s{?Î{˶—Ä›‡€q›Û”,ãy»Ä¼Åµ¼/¶¹"â5%åñü¯Ê}¼°pÞEÙtâ2|…wK‰;Ä»Ìê뤻¢0CHyWÐã‘òŒvYî\þRA^Jykq4ÝÙÚŒ!ZÄ0j5ŒÙ¬Z?‘îšÂï³9DX´‰÷YA›Úƒí¢;Iq Ü$£:ÝMr®7³Ð#7ë—ÀM„‚”„£ÀMÍŽWà&ƒô€wiú‰wI{® ïBvÞí׉ý€ï …nA/‡ ¾3· ƒ=ïÌ[Ù^|·ç-â ø®L&-’ïÊŒës¾«Y¸À«¡¾9ßYH#ÍyìiDµ‚ïZÄà‚(s¾Œ("ÞXeopº;®´;js¯{tˆ_ÿԖЄ»ò(‚6/õA›ö Æ w6ÓRó@ÐfÒþi Ú´¯„A™´™K`š&–µ{2ènìw†‚‡Ó­¨û‹îlÜd´%U½¢•$èÎþ»Ý²ž­QûMYïÑ6ÑÔõlš¬/]Ϭ7ÞÙ0pg׋}‰\Õ3œÅ€ª÷¨¼:U½ëí…ª—¦dx¨z”Ù\ѳªÄðÌsíU n ;›ÝÀd®çeU즠—ò²öæ2Òòh’* ²³yÔÁΖ‡ìl™© Ïvc³*RçAvv …¸v÷œìöl©{àdgë>';[MS1s²³žzö€¸GгçÏÈnÑTé¡èÙ˜ƒûEo¿ Cw²›)x'»icÌ®ië°]ËáΤB\‹³ÝÜw˜Ü Ao¹Œòu¶›{¢³ÅÙnÖ®ÀØnZ \ ÎvÓbŽðÎ8ÛY2Czí,ÿ—¡ÁÎvV­ƒŒèl7mÅ‚³Eì2:ÁÙÎ*z ØÎ‚…±.ÛÍU˜•¶³Pe†Q;Û-[T@6¸³²ü.îÎä«w¦«VŠm®ëÙˆ¥¡ÃÝ:Aè·°·žÁJ€;ë¡0€»Ã/èn… tg1Ü\A>°;ï¦M$Pm ïæ’»xg·æwfæC­íàÝ´" ùÆ;KùÆ‚xwb¶ÁŽwVH…·ËñÎ3b£€wv 0ðÎ"Æ‘¹¼;/P ¼;[€†wv;;#+ÞÍ(› ijׯ¼oƾÃ@¼9´âMê‰Îél¿xÇlNsŒ;hÓ>L@¼s×y=ñììDŠòø«Uƒðì¶`u³·>D žÉê•ÐwoÕà\g<ͱž!ãÅJŽŒ7BÆ;Øã‡¼®Ý yöÃ@Þ”kÜ!ohcMB^—o 7cÁ ȳõr(Ï&¼B ¼ÙÊ›±§(ïŒ.PWò¬A¯yömÐÙà 7k‘áz6bh;¤g%†HEŽzVê?@=~ø–;ê­§3÷¨w¼çF=Ëg@¤Pσðí¨g„PoumyÔ[#®ÇQo-mŸNiïy¸RsiÏÆ.ØMÖÛ— þëÙ(DÑYoÏTÆÅzÚ>Y¯T*·d½,Éz6BRÉ{<‰@º<´=c•á©×?^ÀìŸã>¹þÅyÉvà¾LÚ¼¢8•š§(Îõ–ö¬Bħ(NMî ã\\¢‘ýl[5R'’õTJCÉz2å {tø(_ohf¾ž^U){9˜ ìWãD`¿®Yì·XðBÊžv$û­, ö[R¸œýŒã°øpô3åL–'gor!úY#ãèg:#D¿É­b…~bv¡_ QÑÑÏœÚó…~YgLÙSé¥ì5Åš‚üмKJÙ‹@ROÙÓT¤”½X€üZÕêägC<Ï ¿–˜sðk5¢Hü¬b ðàgºÍ|){Mâ3ɯ©.ŠÈïáBàWWD„øuîx.ð묮#ò{t@~#â`~ÑÕî|=ãEŠ'ÐõN!¤ýlAÉ%¢ŸEvúí«âõýÌ!ó _Ü&Ýѯj‡v¢ß‰ØÇ™ýö½ã¢ègcí+ Ó~ÅäVDtZÜ3x ñêüfD ‚üld²€üæç|=ÃRÂa?óáë>ìgqøgÀSD`ý,@Ò™£ŸÅTŽ—°gU)‚ÿf¼ôÀ¿›¹€OK’':'kâ­T`¦Øç¸Räš Vaï €5D{`à°hûP  ¤ç˜•°ÍÎGÛþM<{‰{óÑÎà é|"Ô19r €9Pã  y_ú²7sdþ2¨S)ÑÐö„Àªê“ÀÅüG ê¬ G<™ù8Äá©õâìd¾¬õâ¿Òë|øÏ'nøï‰¨|ðŸÅ“Ò܀ܔwçø—µ›ðÏ^aºM€¶N#¶ü3ÁŠ~*Ç?ËÅe8ˆãŸ}”í\³ðíç¦?{ñùªýÍ“ª‚¿ýY(®PêПEfæ zåwø³õ"¸ÓÓqÃ߇Tø;KgBä¿Ó²îd=[«¾áïôó¼èϾBÒ¡¿«YПMñ•1œÏY€Kh&ýõÉ‹þ¬T#e:g§¦=#@³©¸èÏÎEMÓéošnü™ŸC€èÚÞLœ:ì—’Äc¿iùæ à<èg“3æý¬:£ŸEßýò-ý” ~ùF,„8''󜪾/¢ŸùS ¼ýlwãège@{ Ÿ¥?/rœqÓÒÖ`?‹çÆl@ö{Zôáì·¯N„æì÷dx}‰~“ éˆè÷0b^è÷pMKô[Ú×Eè§-è~Æ7(Ëêè·”V ô['ŽõÖ÷ìAù埓üÊä ŒäWTá™äg{€ ȯi×g’Ÿ•éª/ô;ÓÈiùmàDò«ÜxÝÁÏÖ_¸^‚ß`qE‚_cR5¸ïÐ"¥ÄÃLs*5Üw Òö÷=áè÷ÙèBÑÏ XKÜ—ä'÷í—šüèÜ·ÊÒ§`ÜgUkPì`Ÿ¡+œ\}€\U¥ÔgŽ)F&8õÙ1s§W-X’¬úìöÁ‰ ê³'‚úNÂÄü³õy^ÕylU±gØÃ{8õz7ÿæ§l “ÿôQ™èßýô÷û“ÙßxýÓÏüçoÑö¿þwú뫈‘iæ1ûÇø»üWQßÿåþd+ƒ5ןþGüèÿXKi8Ehö*ñ>Ë¿e7ÿí'öò_ã§ÿôî/.Õ¦¬èä?Æ%üúÏþØ¿gÕ¿fÛÏ?ý½Ëì]÷£žä?l3ü°ÿêãs¨€õ#ÒûÚË O´éfóú|ޝ\-?žº©¾ž3y÷…–ß#Ìîš¹™Ò}ilù³´º¶÷±åwy6ÔëÞݡźûO÷wŒnîendstream endobj 6 0 obj 162575 endobj 4 0 obj <> /Contents 5 0 R >> endobj 3 0 obj << /Type /Pages /Kids [ 4 0 R ] /Count 1 >> endobj 1 0 obj <> endobj 8 0 obj <> endobj 7 0 obj <> endobj 9 0 obj <>stream 2020-10-09T14:32:59-05:00 2020-10-09T14:32:59-05:00 GL2PS 1.3.9, (C) 1999-2015 C. Geuzaine gl2ps_renderer figureOctave endstream endobj 2 0 obj <>endobj xref 0 10 0000000000 65535 f 0000163125 00000 n 0000164638 00000 n 0000163066 00000 n 0000162933 00000 n 0000000266 00000 n 0000162911 00000 n 0000163218 00000 n 0000163189 00000 n 0000163282 00000 n trailer << /Size 10 /Root 1 0 R /Info 2 0 R /ID [<66467834E9B995A2614B94E602AC9336><66467834E9B995A2614B94E602AC9336>] >> startxref 164858 %%EOF blis-0.9.0/docs/graphs/sup/sgemm_rrr_zen2_nt32.png000066400000000000000000005611011422157504600220150ustar00rootroot00000000000000‰PNG  IHDR¬táÂgAMA± üa cHRMz&€„ú€èu0ê`:˜pœºQ<bKGDÿÿÿ ½§“ pHYsNNÆÊ/¥tIMEä !1µ˜¬ï>zTXtRaw profile type xmpH‰ÍVI’Û0 ¼ãy €ôY$o©Ê1ÏO”mylO2UsˆTÚHÝX)úýóýÀ‘yI$» [,iVÑ‹V+œ”µªéª][—Ëe°a|Õâ#Õ¤–&©4KE »èJe±Í°°Šm¥×¢xB¡±Éž6PÑáÜlÑl‰›*TïVÏd$@`ic.R¹ìE™¯*l‘ ­Íùjæäߺk7ñ9稙®8²Í‰›xsWƒ±K˜µ”Vû÷À¹ƒýêî aî²âÊÜ$‹ð† cs¨4x¿pÂ|…±“'ƒ€ÊþüH'’sÒ‰.Vp&ÙÀkXÜ BÜC±ñèê'ÞÈ 0£M%xŠ!Vnš-p&0m^ѵ.ÏpÂý“Ž4ÚxøG†IÉ=öhT)3Dø^݃„íÀ< ’A÷(âxŒQzm¾vzÇg.9ÉÃt¸Øa‡«F¹bÂW*ˆT˜PN„-h…ÝÁŸGpì׌‹¬ú’³Bxp·gz(ÚJsã@Bm·ìŒ*سâž”~‡Iµà½È&pîFú8j÷${@Ý”ÒYëT:+ìqÔ9s—xK_À}©ô KDPõ(Géðå.\‚–Ž4ðºDŒy)«…Ò(hft´(î‘óØ¡X€ùšÓ Ëл”ŸIñyYœ‡þ)s¥¡¹¾(kòÐß² ÛµÉÝ:·fÕ{–w‹‚žílj´ö-º5{Q –â­O–Å› |™aF\ãD«aÄ;‹‘˜ËÄ{àç5õ®¤èg $/ºe‚<ë~ï”.‡{%,¼Y ÇMß­?”mØt|Qó°Ïü¡ì`&‘ Án'Jr.õI\{”ÃÝÄì{ØyÄ•]í øÌH= §{§†OÀ"ÃýXèØu‘áà!uDJvMÑ/ßsÀÉ(lžù{™ÙúÌeúä#gsF‰¦^½‘æÆ =‡¼lõN^s¸«¸rx†;1†¡ô®¾NJc7½>ý ø ¶l´„o9¿IQÚþ7FP4ÿÇž~þ"é"Emþ·Ñ£ÅXqåkàÀcaNvPÏR¹7€IDATxÚìý}|wyïÿ¿rljœqI0"fœ`‚n2J ¢@³ÅiNIOÚ•8--1gK[ŽáWõìzHÛpÚî¶ê—ºw°cN)m‘\à”`Ø)nM ÁÊ ‰‡ä“„­Ü9 Ž~ÌÎì®´º¿YݼŸ‡¶öfvfvçÒgçšëúœ4>>>ŽˆˆˆˆˆˆˆˆˆˆˆˆˆÈœÜê‘ÕO‰GY0%EDDDDDDDDDDDDdÁ”x‘SâQDDDDDDDDDDDDDL‰GY0%EDDDDDDDDDDDDdÁ”x‘SâQDDDDDDDDDDDDDL‰GY0%eň¢ˆ uy¾ï/ɺú¾OE-y핼_DZaºÏóĸ²ÔŸÿébÃJ>öVòº‰ÌÇ\?ÓS=6Â0œÓkkŒ ²|æ2Hn›íg|ºÇ-vlXÉÇÞJ^7Y»óÜ@+ÇÉòtì‹ÌÝBãÀRŽæ³.«1¬†õY#œÚ¢¬ß¸H‹ŽŽŽg³Ùq`·,k|hhhÁË­T*ãKõÆ+•JK^{%ï‘åvøðᦟç©âÊRþ§‹ +ùØ[Éë&2sùL7‹#‡·,+!ÙlvÖ¯­1‚Èò˜ë`||öŸñ©–½T±a%{+yÝdíYŠs­ŒëØ™«ÅˆK9F˜ÕVÃú‰,„ÎNm1ÖOÒr…B0 e||Ó4)•J­^-YÁÂ0Äó<º»»›Þ¯¸""3™.Žär9LÓd||œÑÑQ‚  P(´z•E„¥Ì´lÅ‘¥Õª1¼Æ"+ÇRþ×y‘å³&QQ*•( ”J¥†’V×u) ¸®K†¸®Ûð\ß÷)  …†²ûB¡Ð°\Ïó–7ñÕ\?“d`[¿þ³¹o¶Ë-•JiùìÄÛš=f¦eÎvÛ£(Âu]Êå2†aP,1MsÆíKÞ¿(ŠÒ÷l¦V Éû:×çÎÆTïítŸÇÙ¼7 ß÷'½·Ék6[ÿ™ž¿˜Û¾Ì´Ÿuì7_n«Žý™ŽÁ™¶­ÙñPÿY˜)®Ô?¶þ=_ìØ0Ýû¾T±a½Ç……Ä‚©â@²ïZ f:3Ì&6Ì´¼ÅŠ3mÛ\Ž×‰Çzò~7ÛWaâû>ù|Ã0p'Ý–ùÐaé-Åø?ÙW³ýL/ç`6÷ÏfÙSû­Ì´m‹5H_ÿ¾O·ìÅŽ #,= Z;&˜ë¶ÏtüjL0ó{7Õö¬·c"VÏa!ç“÷k)Æká—5ÛÇϤT*‘ËåÒ9’7|¦ûf»\ÏóÒçO¼­ÙcfZæl·=¹Í²,‚ À÷} àX,θíÉÁ¿mÛ¶ôµ2™LÓmOî‹¢˲æôÜÙèììLŸëû~ÃçhªÏãlöc=ß÷>¯™L¦á1ÝÝÝ Áa¦ç/Ö¶¯3ígûS/·UÇþLÇàLÛæ8•J¥!V$fW’÷º>.Ìf½æbª¸¼öRĆõ ¦‹õ÷·"Ìt<,f,˜Ml˜iy‹fڶٯ͎u˜:Ž$¯UÿØdì0#,½¥ÿ×ß?›ÏôrŽfsÿl–=Õ±ßÊ1ÀLÛ¶c€äýž¦[öbÆ–žÆ­ÌuÛg:~5&˜~?×[ÏÇþD#¬®1ÂBÎÂÒVûy˜>Ìô\Xý± žÆ«oŒ°sˆ #èØ_à±ßê~±‹mbÿÙÑÑÑqÛ¶Ç¿üå/ã‡Nï3MsܶíñññZÿïú¾áåryÜ0Œñññ¸'o¹\Nï³,kÜqœô÷|>Ÿ.k>Ÿ 0žÏçÖ-yþt÷Íu¹Ínkö˜™–9ÛmÆmÛ7MsÜ4ÍqÃ0Þ‡©¶/y¯‹ÅbÃ}Àøèèhzÿèèè¤u˜é¹³ÙƤGsò9©ÿl%=ã§ú<Ö?vº×¨7ñ33q9ù|¾a¾‰©ž?ݶÏf½V¢éösrlëØŸ~¹Ín[Êc¦cp¶ÛÖ¬çøtqeº¸0›õšÍ>¨T*ÓÆ…fë½X±a½Ç…ùÆ‚™â@²ïZ f:3Ì&6Ì´¼ÅŠ3mÛtÏÿ×ý×iõz?7É2š=Fc„•i©Æÿɾšígz9dz¹.Ë^Ic€ÙnÛ\ÇõÏ™)64[öbÅ–‡ÆÍïŸË²:&˜ë¶Ïtü®Æ1A²Þ3û 9î“ר·žý‰4Fh~ÿ\–½ZÎN÷¾ÏfÙËq±Uc€ññécÁtÏ]+± žÆÍïŸË²—{Œ°sˆ #èØ_ر¿æ*“ù\.—^½R©Tøæ7¿‰mÛ %ôÙl6ý¿ïû˜¦IEø¾ßð{’i¯®aiiþLë2ÛÇÏĶí¦Ëžé¾¹,wªÛš=f1¶½þŠ£Ã‡søðaÇ™”ÕŸnû’¶'_ÝT¿\ ½Z¢þýžísg# ÃIŸ­dYS}çú5“,'¹Á÷ý9µci¶íó½r³Õ¦ÛÏžçéØŸÅr§ºm©ŽýÄtÇà|·m6qeº¸0ÓzÍÆtq¡~{;6¬÷¸0ßX0›8P¿|XþX0Óñ°˜±`6±a1·{¦ãm¦mköüïÿûÀÌÇz3Ó3s9ž@c„å²”ãÿúåÃÌŸéåÌæþÙ.{6¿Ïd¹ýffûÝ¢•±Ac„å¡1ÁÔ÷ÏvÙÍ~Ÿê¶ÅØöÙ¿ÌÝz;ö'Òaêûg»ìÙü>“åÕm‹¹í 9‡¸1‚ŽýÆuží±¿&•JˆKGO:é$r¹ÜŒ;4 ô—nýÏ\™›dÿÖ·6ÈçóiŸ‰Aʲ,òù<¹\nÎÏ0 § S}C¡PओNJ{g/tкÐç·ÒtûYÇþ겟ÃéâÊwÜÌ-.Ìg½¦‹ °t±a½Ç…ùÆÅ•e1?·s=Ö“çLe®–‡ÆÿkÃRê¿[´26hŒ°<4&X}–úÜ€ÆëãØŸHc„Õe)âÀ\—½”ç[5Å‚z#¬ ù.dŒ cvÖ\â1 C à\.3::ÊÐОçqß}÷M<,ËJ³ÉÉÏÀÀù|~ÚÁ¦,ÌtÖÙ~ëßפçp½r¹œfç›õožî¹³a𿤫’åLõyœË¾Í$Ë8|ø0•J…r¹<çÏéblûJ1Ý~6 CÇþ ¶ŸÃébÇ9çœLc½¦‹ °4±Aqaþ±@q µú¹›îù3ëÍ$_ê¯â›é‹ÂtËÒaéiü¿:-÷ þ¾VÆ–‡Æ«ÏRŸИ`}ûiŒ°º,FXè²—òb+Æ X0‘Æ«×B>‡ #èØŸß¶¯¹Äc2ék²LÓÄ0Œ†Éƒ“UÿæÙ¶=é¶dbRY:–eašfÃd¦…BÓ4g} Lœ(×0ŒIW›$F—J¥†/ ³yîL²ÙlÃä«ÉÕ/0õçq¶ê?¯õ“»FQ„aéž©®þšêù·=Ùç«õ*éös6›Õ±¿‚-Æ18ÑtqåÒK/Mo›*.,ÆzM`ibƒâÂücâ@k-ôxköü+®¸"½mºc½™äs_ÿyð.›Í’ÍfÉåréU ³}ît’rìîîn,Ë" CÇ!‚)?³ù¢â8NºÌ(ŠÒ?~ɶ¸®Ë¶mÛ0M3ý<'W28Ž3íó“u©ßöÕüYŸn?'WŒèØ_™ãlfª¸2ñÊœú¸Pÿž/t½¦‹ À’ÄÅ…ùÇÅÖZèñ6›çOu¬O¥X,’ÉdÒù Ãh˜Û`¶4FXÿ¯NË=h¦±Ac„å¡1Áê´çÖÚ˜tìÏ´o4FX]kÙKq±c€d[fŠS=7YïÕ &î+V§…ƒ #èØŸß±ÒøøøøÞï+ÉÖ&W2%½&;Ù4M\×% CÒçÕO›”PËÒ«ßï³Íšû¾O&“a||<}¿gûž-ä¹S Ã0-žxµÔÄÏãlA@E˜¦Ù´ËÄuO&6N;×ç¯vÍö³Žý•i)ŽÁ‰–;®43]\H^76(.Ì?(,¯…oKGæC¦¢1ÂòÐøuX©c€å^¶ÆËCc‚Õg%Œác¦²cб?V—•öw|-œ'¨_n³X0Ós›=µÓaõhU@Ç~óçÏÖšMXMe¾èÅ^öR®ë|Ôü‹ùÜåØÎ•¶/×2û _öR¬ëBŽß¥4Õz).¬~ë-,År{™ ­ˆ#Š«Ëz;î—jÙ+íØ_iVņ…/{¥}&5&б?WŠ‹³ìõòÕ9ÄõC±aáË^iç—â¹:îgg͵ZŠiši©tR´•h¥©zì×›ïÕ=‹½ì¥\וd9¶s½ìË•@Çþ—­Ï«âÂZ°ÞbÁR,WŸQÅ‚Õf½÷Kµl}&§§¸°ú(6,|ÙúLêØ_ígÙúŒ*¬5Š _özø¼ê¸ŸuSñ("""""""""""""KçäV¯€ˆˆˆˆˆˆˆˆˆˆˆˆˆ¬~J<ŠˆˆˆˆˆˆˆˆˆˆˆˆÈ‚)ñ(""""""""""""" ¦Ä£ˆˆˆˆˆˆˆˆˆˆˆˆˆ,˜"""""""""""""²`J<ŠˆˆˆˆˆˆˆˆˆˆˆˆÈ‚)ñ(""""""""""""" vj«W`9ìÞ½›‡zˆç=ïy­^•eõàƒrñÅ·z5–Õ#<ÂÆ9ûì³[½*Ëj®ïõO<ÁÀÀ@«W{Ù½îu¯ã’K.iõj,+ëÇ\ßëÇœ®®.Þóž÷´zÕ—•ÆëÇã?ÎO<Á\ÐêUYVs}¯yäþâ/þ‚ŽŽŽV¯ú²ºñÆ9qâD«WcÎVë±¼ZÇ#«u½çÿN9å>üá·zÕ—Õðð0¿ÿû¿¿*ÿN¬ÖX õ^Ùë½^¿|à`pppÕÅúõô7j%X­ë :g8[ÝÝÝlܸ±Õ«± «õïU½ÕÛê­æxQ¿ ¬‹Äã±cÇø¥_ú%n¼ñÆV¯Ê²Úµkû÷ïoõj,«¾¾>ºººèêêjõª,«¹¾×»víjõ*·ÄÓO?­cbPü›Ùàà ƒƒƒ­^íe§1Áú‘|Æ{{{[½*Ëj®ïu__ÇŽkõj/»'N¬ÊcbµË«u<²Z×{>ño=~?8vìo|ãWå߉Õ ´Þ+{½×ë÷ƒ'Nðž÷¼gÕÅúõô7j%X­ë :g8[7n\•±¾Þjý{UoµÆ¶z«9^L܆…X1­VÇÆÆ¸é¦›¸òÊ+Ù¾};»víbxxxÒãúúúÒÇìÙ³‡‘‘‘—½eË–uWÙ°sçÎV¯Â²ëêꢽ½½Õ«±ìÖÊ{½”qàüóÏoõ&.;ëÇZz¯5&X|ëñ˜hoo_Õ_Væk-½×³‰ó¬V«õý]­£Vëz¯¥ø·ÔßV«Õ ´ÞZïùR,˜L£´Þ³µVbâÀÌÖÂ{½Zc[½Õ/ÓŠI<öõõ188Èûßÿ~öïßO[[7ÜpCCpèë룿¿ŸÞÞ^öïßÏÈÈ{öì™qÙëõ$cOOO«WaÙ­…à4kå½^Ê8¬ê÷ùÒ1±~¬¥÷Zc‚Å·‰õ:Ø_KïõL±`!c‚Õjµ¾¿«õoÔj]ïµÿ–úûÁjµZcÖ[ë=_Š“éo”Ö{¶ÖJ,P˜ÙZx¯Wkl«·šãÅbZ1‰Çþþ~vïÞÍÎ;éêêbïÞ½Œ5”t D DDq@dµY1‰Ç‰ÆÆÆ~fdd¤![ÜÞÞNGG‡jõêŠÈPP,‘X},PYŸ4&P,Å‘•îÔV¯@âæ›o¦¯¯±±1ÚÛÛéïï§££ƒk®¹ˆ'~&•©nÚ´©i?çz=öžç122²&JŽEæ+™ö‘Giõª4µ”qà‘GY“‹,T__GŽ¡­­­Õ«ÒÔrŒ VûDß" 522B?·ß~ûŠý›8],HNÌwLpôèQúúúhoo×÷Y×úûûáèÑ£­^•¦–úûÁí·ßN__===«¾­—ÈBèû¾ˆèœ¡ÎŠ@üýà›ßüæ‚Ç+&ñ¸cÇŽtÃÚÚÚf÷îÝ‹2è9ãŒ3èèèH_Cd½JzLë[ßjõª4µ”q`ãÆk¢W¸ÈBuuuq×]wñãÿ¸Õ«ÒÔrŒ ^ö²—µz3EZjÓ¦MtuuqäÈ‘V¯Ê”–2œyæ™tuu±iÓ¦Vo¦HKíØ±ƒööv‚ hõªL¹~°tß¶lÙ¢X ‚¾èûˆÎ꜡HlÇŽ<öØc ¬ˆÄãÈÈ7Üp===éÕEÃÃÃÜpà ‹ròé§ŸÎË^ö2:::Z½©"-ÕÞÞN{{;ûöíkõªL²Ôqàì³ÏÖUK"Ô®\‰Õ Ë5&P,õ®­­®®®†9QV’™bÁBO$‰G‘õ.ù޼^¿$‰G‘õNßôý@Dç uÎPâïÇŽ[ð˜`EÌñxðàAÆÆÆZ$¥Ò'mV­„¢Èê§8 " X "±ÙÆÅ‘µKcÅQYVDâq6%ÑÉ'ƒT ´È 8 " X "±™bâ€ÈÚ§1ˆ€bˆ(ˆ¬F+"ñØÕÕE[[7ÝtSzÛàà ŸûÜçJœ{zzèïïgll ˆÛÁ´µµ¥“ÈŠÈê¥8 " X "±ÙÄÅ‘µMcÅQYVÄíííôööÒ××Çç>÷96mÚÄÈÈ===ìÞ½;}\oo/7Üp×_=mmmŒŒŒÐÛÛ»h“ÈŠHë(ˆ(ˆHl6±@q@dmÓ˜@D@±@DDV£‘x„øŠ„k®¹&-‡N&´­×ÖÖÆ`ÇŽ "kˆâ€ˆ€bˆÄfŠŠ"kŸÆ"Š"¢8 ²Ú¬˜Ä#ÄÁ¡¾úûûصk===ôöö.ëF‰ˆˆˆˆˆˆˆˆˆˆˆˆ¬7Q‘ÉdÈf³xž@†˜¦¹,¯¿(‰GˆŒ===iÅ#ÀŽ;Ò9EDDDDDDDDDDDDda2™ –e‘Ïç1 £á¾ ˆ¢×u —Ë-kâqQZ­222Äs9&?J:Šˆˆˆˆˆˆˆˆˆˆˆˆ,Ž0 ñ}Ïóèîînú˲(—Ëd³Y,Ë"Š¢ô¾¤"r©,JâqÏž=i‹Õ…8xð ¶m³}ûvlÛæàÁƒ“Ó××Ç•W^ÉöíÛÙ³gOšð‘µAq@D@±@Db3ÅÅ‘µOcÅQÕ-Š"|ß_´å%Õ‹CCCA0iÙA`Žã4Ü–p]ß÷uê-JâÑq<ÈØØØ¼—qðàAöìÙCOOû÷ï§««kRpHæìííeÿþýŒŒŒ°gÏž%Ù1"²üD D$6S,PYû4&P,ÅYý<Ï›w’/“ɤó4&|ßÇ4M ÃÀ¶íIËŽ¢¨¡ýªeY ÷»®‹iš Â0\ôí]”9ÛÚÚhkkãMoz×\sMÓ«½½½Ó.Ãu]vïÞÍîÝ»¸eë±cǤ§§ˆL2—$ÀÞ½{Ó«vîܹè;GD–— €bˆÄfŠŠ"kŸÆ"Š"¢8 «W˜¦™& çóü¤2±R©`Û6'“d¢mÛ¸®;é¹_/©xô<(ЍT* ¶mÛF>Ÿ§X,.Úv/JÅãÈÈ›6mbÇŽŒŒŒ0<<<ég¦çÓÕÕÕpûÞ½{Ó@1<<ÌÈÈHÃcÚÛÛéèèàСC‹¶CD¤5D D$6S,PYû4&P,ÅYÝ<Ï£T*MªXœ¨~þʼnÏÏf³Ø¶ÝÐ*5iµ ¤÷ÕW.Ö?6yLý}ɼ•J…J¥Rzÿ¿øEn½õÖm÷¢T<&ÕŒ###ýéOóä“O.h»¥âছn¶múúúØ·oûöíc×®]ض=«ƒàú믧­­ŽŽFFF¸á†fýÜéœqÆttt°cÇŽÅÚ\‘U©½½®®.6nÜØêU™ÒRÅ€7ÒÕÕ¥“ ²îuuuÑÑÑÁgœÑêU™ÒR ôEBÖ»M›6ÑÕÕÅ–-[Z½*ÓZªXpæ™gÒÕÕ¥ï²îíØ±ƒ®®.Î<óÌV¯Ê”–òûÁ–-[èêêbÓ¦M­ÞL‘–Ò÷}?Ñ9C3”ņ!a¦Õ†ÓÍ¥˜´TM¸®›¶C­O Bœ¤4M³!±hYVC•c ILÛ¶Éçótvv†aºÌ‰ÏO¾#Ÿþù ÚöE©x¬Ÿ¸µ§§'½Bjpp¾¾>öìÙ3«‰3ÇIû4';£¿¿Ÿ›o¾yAëwúé§ó²—½,½Bd½joo§½½}ûöµzU¦´Tqàì³ÏÖ— jW®Äê†ÄR  d½kkk£««‹ÁÁÁV¯Ê´¦Š £%I<ЬwÉwäõúý I<Ьwú~ ï":g¨s†²ø|ßDz,òùü¤ÄàDIâ1Iú¾ã8iÒÒ¶m<Ï£P(àºî¤ù-Ëj¨¨Œ¢¨!ñP,Éçó„a8é>˲ÃÇq8餓¸øâ‹´í‹RñxðàÁtr×ú¶ ]]]ìÝ»—‘‘‘YÔ˜ØæhçÎi)u¢ÙU J(ЬŠ"Š"›)(ˆ¬}ˆ(ˆˆâ€´V¡P “ÉÌé9A`Ûvú3‘ïûDQ”þÔÏ™Ìí˜0M“0 q]—|>?©b1y=¨UVNlµ `FÓÛMÓLŸÿío› 6,h-JâqâÄ­õ’òäéÊž“ò͉½ÖŽdù388¨h‘5@q@D@±@Db3ÅÅ‘µOcÅQÖ+•J”J¥i[¥63qÎʼn]AK¥®ë¦ ¿(Šèìì¤P(‰Ãd9ŽãLš âŠÈ0 Éd2i¥å\ضÎ p饗.hŸ-Jâ±½½}ÊŠÆ$á8Ý•I«§¾¾>ÆÆÆ€8(5¹-¹jŠÉüŠQ¥·M¬@L’ƒIòÑ4MŠÅ"a²mÛ¶¦‹S%!N<&ÉC×u*-gËqr¹o{ÛÛ¼Ï%ñØÛÛ ÄWLœ€6™çq&ííí8p ­œL&´­×ÖÖÖð˜;v(pˆ¬!Š"Š"›)(ˆ¬}ˆ(ˆˆâ€´FÒ5 Còùηêj²(ûöí£¯¯®®®†¾É===ô÷÷sèÐ!8Ðêm™V†8ŽCE“î3 ƒ ÒD#Ô”¶mŽãLz^ww7–e5½o-Y”ŠÇþþ~zzzØ¿䮽½½ÜrË- /x2J‘¥E–eQ.—'Ý—$›ÍåhYÅbqR«UÃ0Èçó ÍkÆÕdQ###ìܹ³é} -XEDDDDDDDDDDDDæÊó¼E_f ¿O5W#ÄIDÃ0š&óù|ÓŠÆr¹L±Xlá^[>‹’xlooŸ²¢qdd¨% EDDDDDDDDDDDDæÃuÝS(f½¼(Š&=> æIGˆ+'Îᘘê9Sݾ-JâqçÎìÛ·}ûö166–Þ~ðàAöìÙC{{;]]]­ÞVYÅ|ßÇ÷ý)ïÃR©ÔðøéxžG†éïɼŽS%§K< œº éíí ¯¯¾¾¾†û:::Ø»wo«·SDDDDDDDDDDDDV±$)èûþ¤ù“Ž™L†ñññ)—éû~CâqbÛÕ‰LÓL×C&›Wâqxx˜Ï}îs\sÍ5i ÕÞÞ^zzzLÛ«vuu©ÒQDDDDDDDDDDDDæ-Š" ÃH“‚ÓU1&­X듉͖—HæŒL’™AL™Ô¦œûQbóJ<¶··ÓÞÞŽëº ³sçNvìØÁÎ;éééiõ6‰ˆˆˆˆˆˆˆˆˆˆˆÈQ*•(‹A& “däTÂ0œ²21º»»1 #m›E¾ïS((—ËS.×4ÍVïŽm^s<¶µµÑÓÓÃÞ½{9pàííí bÛ67Ýtlõv‰ˆˆˆˆˆˆˆˆˆˆˆÈ*–´M ‚ M$:Žƒiši¥b½‰UŽI…äTíS-Ë¢R©¤ÉÌR©D>ŸÇqœVoúª5¯Äc½$ yóÍ7ãû>]]] rå•W²gÏúûûkõvŠˆˆˆˆˆˆˆˆˆˆˆÈ*’Ì¿˜$“¢ã8“ær„©Û«FQ4©úѲ,ÒªGÏó‚€|>ßêÍ^ÕœxœhçÎÜ|óÍ|ûÛ߯qFFF¸þúënõ¶ŠˆˆˆˆˆˆˆˆˆˆˆÈ*®ë¦mPÃ0ĶmÇ! Ã4á˜Édæ}Læh¬O6&s?6ca’Ïç5ãÍkŽÇ™ŒŒŒ0<öíÛGGG]]]@\éxÓM7ÑÑÑÁþýûÙ»w/### ‰I‘éø¾Ÿ&“Ö©É¿õÿŸXɘTC†a8)Á8Õ\¦i6MXÊÜÍ«ÕêØØûöí£··—Ý»w§·÷÷÷°wï^ÚÛÛÓÛ÷ìÙÃðð0­Þ^Yá’ù£("›ÍâºnÓä`ý<ŽŸß,ñXŸ¼”Å7¯ŠÇC‡ÐÓÓÓp{’\¬O:îܹˆ«!EDDDDDDDDDDDDf–eaÛv:ã|’†õÏI*eéÌ«âqpp€¶¶¶I·×W@ÖSâQDDDDDDDDDDDDfâº.QaÛ6†a`¶mÏ8¿c’X4 £¡2iÇZß–U­U—Ƽ*“9ÇÆÆÒÛ<ÀŽ;›$ÕfUDDDDDDDDDDDD¦E¥R ÇqÒ„#@>ŸŸôØú Æú¤¢iš mVÃ0T¢q™Ì+ñ˜$]×MoKæwLZ«N¼}bBRDDDDDDDDDDDD¤^©T&' ØöyÍæzL*$Ã0œñù²8æÕjµ­­Ý»w³oß¾´íêððpC›Õááaúûûéïïg÷îÝ“Ú²ŠˆˆˆˆˆˆˆˆˆˆˆˆÔ ‚€b±8ïDa};VÓ4'µg­¯„”Å7¯ŠG€ÞÞ^n¾ùf6mÚĦM›Ø½{7½½½éý}}}iÒ±þv‘f‚ ˜SÒqb"1ynÒz5ù½¾úQÉÇ¥3¯ŠÇDOO===MïëííÕ¼Ž""""""""""""2kÍZ¦6“ÌÙ8Uqârê“™³} ™»yW<&dxx¸áv%EDDDDDDDDDDD$Q(fUm8±=ê|M\N’¬”¥3ïÄãðð0¶m³k×.víÚÅõ×_ÏM7ÝÔêí‘( CJ¥ÒŒ›oâ1Ij&Õ[¶ÎwÞH™½y'ûúú8vì»wïfÿþýìܹ“þþ~úúúZ½M""""""""""""²ÂA€ëºi‚0Š"º»»Éd2A° ¹Ã0L[¨NWÙ˜¼†mÛ­ÞËÎu]:;;ø½ð}Ñ_c^‰Ç‘‘éíí¥··—®®.öîÝKGGǤ–«ó166Æ•W^Éààà¤ûúúú¸òÊ+Ù¾};{öìadddÑwŠˆ´žâ€ˆ€bˆÄ¦ŠŠ"ë‡Æ"Š"¢8°ÚEQD†X–…ëºär¹4aèyÞœA4,6’Ü\ílÛ&‚ Àó<2™ ¹\ˆ÷å;ÞñžzꩽƼííí ·wuu-ʆïÙ³‡±±±I·÷õõÑßßOoo/û÷ïgdd„={ö,ÊkŠÈÊ¢8 " X "±f±@q@d}ј@D@±@DV» 0M³¡Ò0Š"òù|C ÔÅl‡Z_ù¸^*ƒ  P(¤¿‡aH¡PHÅb1}*• ¦i²yóf|ßç±Çã¾ûî[ÐëŸÚê0Ѿ}û8vìXÓûÁh¶m§óJ&Ëžmuäj†aÚÎÖ¶í´j’øMîs]—ǧû+IN>ðÀ zýyÏñ¸†‡‡q]—÷¿ÿýMïi¨ªloo§££ƒC‡µzÕEd‘(ˆ(ˆHlªX 8 ²~hL " X "ŠkE†˜¦ LNüMuût’dcsNVÖ·h]K’y>œÞfš& P©T ›Í244”î÷|>Ïèè(/xÁ ¼+&ñ866ÆûÞ÷>Ç¡££cÒýÉ• Û¹nÚ´iÆy%Ÿyæîºë®E™Rd5Kæg}üñÇ[½*M-exüñÇTwY÷¹ë®»xæ™gZ½*M-ǘ Ù\"ëÉØØƒƒƒ9r¤Õ«2í:N :&8~ü8ƒƒƒú~ ëÞðð0ƒƒƒ?~¼Õ«ÒÔR?8r䃃ƒMÛµ‰¬'ú~ ï":g¨s†Ë¥>©˜Ì³˜Tã%æ’œOeäZäû>®ë’ÉdÃ0­ ÀqŠÅ"PKÔ†aHww÷¤}ÿ£ýhQÆ jµºk×®¦·oß¾}Òm÷Þ{ï´Ër]—M›6±{÷îîâÉž~úi†‡‡9çœsš&‘õ"D<ñÄ­^•¦–2<ñÄ ÒÕÕ5iŽZ‘õ$I6´µµµzUšZŽ1ÁÑ£Gmnj‘ÕèØ±c+>ñ¸”± I<&WA‹¬W‡bdddÅ&—úûA’xloo_±ã"‘å ïú~ ¢s†:g¸œLÓL“ŽEQ´àù“äfRÉgYÖ¤dæJ«v,•Jäóù)ïÃ(Šš&Zƒ “ÉpøðaLÓÄó¼i—•ì“|>ã8 ·:tˆááá æ•xloo_Ôƒ|ppþþ~8°hˬwÎ9çðæ7¿YY÷ºººèêêZ‘W÷/u¸à‚ èíímõ¦Š´\oo/ƒƒƒ+òª^ D–G{{;½½½ôõõµzUšZêXpî¹çjL éHëõûÁUW]¥X ‚¾èûˆÎêœáò2MÓ4’I’0 C,ËšW%£eYxž—&5MÓĶí†Dfò:SýÞ*QMÙ.¶T*Q*•0M“r¹Œiš“¶©R©¤·çr¹´Âq*¦i6MNöôôÐÞÞ¾à1Á¼‹y ²iÓ&nºé¦†ÛûúúØ´iû÷ïOožtU²®RYýD D$6S,H.‚TY»4&P,Åõb! Àú*ɉ•”•JeÒëÔW@®”ÄcضÝô¾0 À², …†a`Y¶mEÝÝÝiå¢a -¸jt¡Ôjµ^ý)sºR¨§§gÒã¹æškÒÀÜèС†`188ÈÎ;[·EdQ(ˆ(ˆHl¦X 8 ²öiL " X "Š«]ø¾ŸÎ;èû~Zi7±ÝiR9Uåßt¯1UÒ®™V'å¦âûþ¤í( ضÞ^.—èììÄu]Â0$ŸÏ7ÅÅQ‘˜bˆ€bˆ(¬D¥R©!1–T8†1cUÞ\çx ‚€b±H©TJ_£žiš óN¬¶l5Çqp]—l6‹ëº¸®›®o³Äb²}+1é H<öõõ122Âþýû›¶Uݹs';wîdÏž=ôõõqóÍ7Ïiù÷Þ{ï¤ÛÚÚÚ8pà@:±åŽ;8DÖ0ÅʼnMŒŠ"ëÆ"Š"¢8°Zxž—¶O­71©XŸ$ ‚Ó4gÝ.´Y•äLIËdù+¥ê1‚tÇdŸÙ¶M&“i¨Ò\Mæ•x¡¿¿ŸÝ»wO;—cWW===ìÛ·oQ¯.˜Ëü‘"²6)ˆ(ˆˆâ€ˆÄ D DDq`%ˆ¢ˆ0 Óù§«.Œ¢¨!QEÑœª›%§jYZÿœr¹Lww÷²î—\.‡eYضÝPõi–e±yóf à\.S,1MsÆmY©NžÏ“FFF€¸oòL’Ç:t¨ÕÛ*""""""""""""K¤T*ÑÙÙI6›M[ú¾ß0Ÿcbª$ã\[­Ö?'›ÍÎøØl6»ìÕ„I¥å¶mÛð}×uÓ}“ÌAY©TÒõ_­IG˜gÅcR®ÜlR׉’Ç êj‘U.iUÚ¬-ªã8³J†a˜þ¿>Ù8ÛV«‰¤Š0›ÍÎú¹õs>.µú ÐÑÑQ¢(¢³³³¡b3‚´úqµ›WÅc’@L*§“L¥RI·Ç4Í)[Ì®hK¼ÎJ<ŠˆˆˆˆˆˆˆˆˆˆˆÈ”\×Ų¬9ÏÁ8qÇ•¢¾ÅëL<Ïkz{>Ÿ_mVçtÍñ(""""""""""""MEQ„뺔Ëå¦÷OWù·“ŽaAÓÛ]×MÛ©Ú¶M¡P X,NYµ9±­ìІÐdÛÓ¼ƒƒƒìÚµ«%ûDDDD¦EѪè/""""""""+›çytwwcšæ”ÕŽ¦i¦Éº`‰“Z‹! C|ߟt{„aˆiši+Ö|>¿ú’‹Ó ‚•™xÜ´i]]]-Ù'"""2½R©D±Xœt{ÒB"ÞûÞ÷ÒÝÝÝêU‘Ìó<Ç™²Ú1‘$çVj’.I(&ëXî,<Ï#Š¢†êÆB¡ÀáÇ×Öþ¶ †¾ÿ ,¨Õjoo/-Ù7"""2Y†”J%²Ù,¾ïcYVú»a …ôq¯zÕ«Z½º""""""""²BEQ„çy Mû8Ã0Ò ÞWb’®T*¥IÄ(Š‚€B¡Vq&†a¤ë_,qgÊ««–a€eÅU¦ÿ,²“çó¤cÇŽ188ȱcÇnß¾};}}}­ÙY"""ëT©TJ‚Iˆ(Š( d2¢("—Ë¥­. Ãàºë®ãÎ;ïlõª‹ˆˆˆˆˆˆˆÈ åy¦iÎXŸ’sÅbÃ0p]Û¶)—ËévEQD¹\¦R©4$NWÃvÍ™øù8ù˜É@w7¸î¢¾Ä‚*EDDdù%­!|ßÇ÷ýôª­‰’«¶ŠÅ"'tžç¥¿288ØêM‘Ê÷ý)çu¬—$èÂ0L+W ß÷Ó*Ǥ¥j’€´,‹J¥‚ëºko.Ç©6˜@¹ ¥ärñ}޳(/1¯ŠGY~QEi5c©Tb``€b±H¥RIHÉiI¿z˲Ãp}  DDDDDDDDdA’îZ³I<:ŽÓ07âJ’$BÇÁ², ÃÀqÒ6«ù|~VÛ¹êù>ÜÐÿ?$žã±R©% Mßþ6W}éK z%EDDV¨B¡ŽÂ0¤³³·Úú T*Q.—%›Í’Ïç±m;í¹†aòVúß""""""""²r$s Îõ\ÒJ™ã±»»› ð}§ZÉçyQÑÝÝM†¸®K©TJÏ·­y¾›M°‰Žuóx;ï¼½Œ"""+P.—£T*‘ËåD¥R Çq8|ø0Žã4Ì%W—Õ “ÛVâ•g""""""""ÒzAq‚Îó<æôüb±8çç,Ó41 #m­št+—Ëd³YLÓĶãìÛJYç%çºð†l<ÏãÄY› \8vå•Üûò—/èe”xY!’6ª™LÏó(—Ëø¾ÏæÍ›xEQ:8šŠišM+“Á”ˆˆˆˆˆˆˆˆH=ß÷éîîNçCÌf³«¶s–ïû@|ŽlttÃ0Òÿ'IUÃ0Èf³ë«Ú1Šà=Yp€‰SqzÀ"íŠ%wíÚÅöíÛÓ€}ûö5ÜVŸˆˆˆÔtww“ÉdÒ]&“âd¥RÁqFGG©T* ‘ÍfÓ~ô3™˜x´m{ÕEDDDDDDDdiù¾O†är9|ß_uç‘’‹÷“ªÍ©Z¾ÖÏEiYù|~Å´‡]R†ù<”ˆ+ `ñ\Aüsö½g/ø¥NÏ“ÚÛÛÙ½{w«w“ˆˆÈª”Éd°, ß÷±m›îîn€)‹õ•ŠåryÖ¯3±*r]L’-""""""""sŽã¤€«-ñXß:59çÖŒçy„a˜ž7+‹­^õ¥†`YñO¸Ú±˜ÄÉÇ<`Å?ç}ñã8lÛ¶|>¿hä5&&WÛ€QDDDDDDDD–^ø¾ÏÐІaàºîŠ>†!a¦-T …A`YQ¥iÆq‚ XUŽñŽ€ÎN8|8®z„¸Ú±d‰!q›Õ 8¾à—\1s<ŽqÓM7qå•W²}ûvlÛæàÁƒ“×××—>fÏž=ŒŒŒ´zÕEd‘(ÈZE¹\ŽÎÎNJ¥AÐÝÝM6›M“ަi¦¿KL±@D`v±@q@dmÓ˜@D@±@D–RxžGgg'†a¤­GÇiõªM+“ÉÐÝÝëºAÎIEQšpœªâ1™ÃrÝÃ8áXŸh5‰çyLNõ6ÎÿÒù ~ÉyU<ÖëïïgÓ¦Mìܹ“þþþ¦<Àþýû§]Ξ={8tèïÿûikkcpp={ö°wï^vîÜ Ä£¿¿ŸÞÞ^ÚÛÛéëëcÏž=8p`qÞi)ÅY+’N&“IÛúúú¼,‘Õ¬¿¿Ÿ]»vñàƒ¶zUf´ØqàÁd×®]ô÷÷·zód…j6±tEi•c2ùôÀÀŽãP*•pÇq‚€(Šp§å‡¶m3>>>qãÒÿîÚµ‹¾¾>}ôÑ–®çl,Õ˜`×®]­Þ4‘–f×®]Üzë­­^•YYìXðÈ#¤±Pd=Kþ&>òÈ#­^•-Å÷ƒ[o½•]»v鄤¬{ú~ ï":g¸~Îú¾çy Ë·ú<Öt¢("“Éà8Ùl–l6›V>6“´cQBwwk6ÊóâÖ§SÌA¹h\·özÄÉÅBü;HwÝø'Ù}}}Ü~ûílþÁæ½ô¼æxL’ˆmmm ·÷ôôLºª yÌððð¤û&ᦛnJç‰tgÒkÌÇùçŸÏ[Þò–__d­Kúœ¯äõRÅ€‹/¾˜ýû÷·ze…ò<ß÷Ó$b†¸Õ?ÐQaÛ6žç¥í',ËJ¯žò}?m·º­Tç±qñÈb`,‹ýû÷sçþý|á'?iõšMIc‘¥•\5¼ÒoK .¸à D 6e½~?ø…_ø…ISLj¬Gû÷ïgpppNEËMßD––ήs†Éù«|>¿â[«&¢(bhh¨!9êºî´s4Î*!íºó.'Û^újG€l6þ©ng©TÍyÐù°ßßV¯··—Û/¿o|î\Â%ó~éy%»ººØ·o### %Îííí ¿C­:rb扆‡‡¹á†èêêÂ÷ýIË©ÜÄeÍ´lYd¹DÕþõIÂdbê(Šð}Ã0(—Ë„a˜¶tðiûÔd°Öò‰©72îŸÍÆÿ†!tvB¹ ¦É–} ®¹¦ÕkÙ”bˆÀìbâ€ÈÚ¦1ˆ€bˆ(,–¤Åê¬Ú®ÝÝÝd³Ù†DiR0•üÄJÂd.Åúóv®Ÿ#[fq¡¥‰ã˜LLºnœ,ã„ ã4®òœU°QÝ™x7T*`—À"nŽ6>>¹ãìOÏù)¼paQæÕjuÇŽ³*=N3U0HìÙ³‡k®¹†½{÷6}lråÑÄÉ`g\¶ˆ¬Š²\‚  T½¤Ç÷ý´7¼axžÇÀÀ‡NÛ7äóy‚ ‚¦IOüÑš"ŠâQJ©Tk©P,ÆÕŽIO÷R‰ó¾øEÎ|ê©V¯mSŠ"ÓÇÅ‘õAcÅQX ®ëâºnÓ ê[Íu]ü$98A¹\žTÁhYÖ´Ç ÃˆÏårq°L&m7 Ä·F|±þ”ë4¹0 g¿MQÔ8o"€ûž»é´Æ1ÍxY¹\œôÛ¶-^¥\.^¥L&~î\O3zlÞ//—«mj©Ÿ,k‰ÌâjE—–·Zâ-˜—yU<¶µµ±{÷nöíÛG{{û”s=ö÷÷³oß>zzz¦=À¡««kR[‡M›6¥W%ôôôÐßßÏ5×\C[[ûöí£­­kVhņˆÌžâ€,§dÞFÇq( „aˆiš8Žƒçy“*“ßÃ0œòŠª™=˰QµJÒ˜}h(þ7L%ªl–ãwÝÅK¾ûÝÖ­ï Df DÖ6 D DDq`¡‚j9[.—£X,®ˆn]a5ƒg¦-@K8Ž3iÝ|ß§»»›ÑÑцÛg]±™LbX.§Õ@œi«O: o¡ôä»°¬8)èyÛJo%óJœ¶_®j1IP6cYÖâU<&³=‹“{¾‡aóKž’Fí–ONÍ6Ž(ê9|ç;<ýøãK³Ó@±@D`v±@q@dmÓ˜@D@±@D"Š"2™ Žã¤]½V‚R©„išDQ„išd³YLÓ¤»»˲Èçó lÛf`ŠÄÞ$…Bã¹0È3nÍΣÕ%ƒr^ûG%|ñ“˜æYXVœðóÞÿî¿]Œs⃘¯¼šì_\v¶VúX(LZ0Œoö¼xò/ý4Æ7nÅÿØYXÏÎ.âU3sÿþ ÀºÊEL«¶nÓIfU2 0/>óÌßbÿÂC˜s«§ Ëå&ÉÄbü:õgêÓˆó1ïÄc[[û÷ïgß¾}ô÷÷388Ⱦ}ûÒûÛÛÛÙ½{÷¬&jïííÕãÚÚÚ8pà@lvìØ±®‡ÈZ¢8 ‹Åó¼´mD.—Ãu]Êå2¦iR*•Ò«¢lÛÆ4Mòù<†a¤ÕŠS%mÛÆ÷ýi æûñ¨"iÿPŸttÝø>×Gõ}è“þ†QÕÌ<<ò¶·qïà ¿¸ÔoÈ)ˆÌ.(ˆ¬mˆ(ˆˆâÀBxžGE çÃVß÷q'­t ‚ß÷ÓskaR*•èïÿoûÛ'UB6½&¿¾º±ÞçñJ¥ø®\,Ë î¡|wgKÅ Ö§^J>#°2¿MgfˆñqjçÝWWwNÐ0À8eŒ¡¡6<Ü[NÇ¿ÿÝX™“¨|ꥵÕò€! ~Æ‚/ºðË6ÁrÀ?'|É™+”þv#Ùÿý ‚§wà8`l8Nþ¶_À8 >VÃHfZjÞM¶ä ÉBaÊÎ9›wâ1±{÷nvïÞÍÈÈ###@œt\ÊÞÉIe¥ˆ¬_Š2Q†é\•JÏóð<|>O.—£\.§-LÓIJ¬9º¦K.ÎØª"Šâ&ëÉeS–Õ8ø ‚¸‰»eÅ—"5Kºn|ûÄKžL³:;tëÛe,7ÅQP,‘˜bˆ(Ôø¾Ÿ^H¿æv Ã0gÒu]òù|šp´,‹0 Ãÿö߯xíkŸ$àØ±–Eq•ßÀÛ?‹û‰Í”ï|M|ݾmÇSUû›&ª]×ïºñ5ÿÉ\†Åbœ§4ŒøT›SqâÿDQú¤dÙVÞ†RÃ]µ)ŽjÈæm&Cm¿„uý;±ŠYr¹k0·ƒ3ñ4_äŠq|m¡aA7öx;þá¿.®=¥3ƒwþ;‰Î~9Û®ÛAöõ0pÛ=î›ãóiaÅäìtL3Σú>=z&?ùɦ½× N<&–:Ù(""ÒLgg'¶mS*•°m›l6KwuŽÃJ¥’V:†a˜¶ Øs…b2šµ0llÆnñ_|ß/§Š¢Æó–E|ÙÔ'¾L©Ù<’ë0á(""""""""Í%U„•JeÚ^Ë¥T*Q*•0 ƒr5#†!QaY¹\Ž·¾õ½ ]Éèèؽû•¼àpäÈeé26o®þçøqºÿúg‰žÛ„TO‹%ç̪çÙ …ZÛÓl6~L2âÀ@Ý©´0`àO€ÀÛŠ«'*©49ýEÕåÞþqü?ùÆ)Œõáw¦¥†S&ÿ²ÄíN hxAÈWüÕ×Á×"ÈÜ•,¥¸æhÚA6ëù˜Ýµç4)`˜r~È&­V“™›º»á­o=M Ë;.^âQDDd¹$ó6ú¾OA@¹\Æq¢(¢P(ÏçÓA•a¸®›¶o‚ m­:³¤ù~méú¿òÙlüS.O=Wãtæ±Î""""""""²~„aHgg'Žã¤Õ„­äº.®ëR©TÒuÉård³Y¢(â‹_<™ë¯ÿ‚àwyî¹6>ô¡øôY2Q2•b¥Á û­^¢ßø-ü—þ.†qVí…Êe0M|?®n,ãåtvÖžŸî Ÿ¸¥)@ì?¨þ? 8@“]æyq¢±¾x´Pˆ_ ÞJñz“â›Û¦èo:ÁíN1 Â6MòùG>ôJrAøtm{ È/ aŠ×.ãeïß7ÞxlAïùÉ z¶ˆˆH tvvÒÙÙ™^uøðaœj‚/¹rª>IhYVúØd€3×+½’9!§åyñh&i™:]cô_i&""""""""kO.—òÊ‹sèµ9GQ_SßL0aŠ l6Ûtø£?úhš½ë®_äÎ;ŸOoïÇ9|¸–·³BèƒÇû«#d³ÕÙ‹~ó†[ÂüÐÿ€³Î"—‹“¾n”¥Pˆ×­XŒ+øL“t™“ò¯qòÍF«?'$›l[ÆÉÐ\.>ý—$8+•¸‰Yþ“WM]e8‘?Í}Õs†Ý~Á;À>‡7c/RMÂ4 ÝòyøÈGî\ðK¨âQDDV4ß÷‰¢Ïó‡Aàº.†a̘Lª#“«óm1ñÊ'âäâTW.ÙÕ€e©:QDDDDDDDD–•ïûÕ9 ¶m‹qåó‹sš*™ßÐu¡TŠqù||, ãÓe¾ï¦s5&Ër¹ çâþè^‹i‚eyâ ¸òÊ EžÝÝØ×}Œâžÿݶķד³í8 †ñÿ=¯v{}çÑdö£I,`âíEâÄcgõÿu‰Ä$qiqnÐuã×Yªl¸ Š!P’|îBkæ0“Ô|)ñ(""-— D¢(J'š6M“L&€ã8i U˲0 ƒ ÒJÇé$mUmÛž]›U¿î²£jÛ¶ãÛ|°6#Äžúy0Ú(•š¶d_„LÓ""""""""²6D¼ím§sÙe7ñoÿÿÞÙŸªZhr,©ôKZ &ó&æªíJ}?þ¹âŠq¾ûÝ«øô§OaãÆøÜÙïþîmœrÊÅé²J¥xÝ’„eÂë^÷T|î-‘ËA±H6ÿkS®Sœ¸Œ“Š–5Çm4‰‹Àà·$ÍÒ0£ëÆ”‹Ro0ùºº×I¢ÝÄÉÒÙVV¶ˆ"kHrÕÉäÛ# ÃÀ÷ýÆ.ÒaNª6ìîî¦\.cYÛ¶m P(¤“M§Ïõ<Ó4ªg’$*“ÿOÛÛ¾»;¾Dʶリ¾y»ï×.¡²,‚óߌe¿r‘öK<ðJJ®[ËgA“vSˆ¢xõÒ|¬OÎ6Mn¼ÿþxô4Ï)a|?_¡`ÕFPÕFîn[/¥»~‘ÜØ_à¸L“0¬%ü¢(~xÒrb6êŸëûñ¿¹\œ…øßd¹SI 0=/~nô%ð-âÒ2´P‘åEpÒIðï\Åßþí³|èCç¦÷ÆìÏOA|~) “‰“l¦YëÐÕPW'9ÿ?û³ÿÈi§ÝÆW¾ò½ô¾³Ï~9aÏŘ̓hÛ`^|‚ðŽ£Þt§_pAãŠÎcФEg' ½øÇ²¦ž}iNB 3Ïç& ÑmÔ’¢se¡Ä£ˆL–Ìy7Ñ~p”\®”öЂ€L&C¶Ú&Ò²¬I“ûŠ,·(ŠøÔ§nKÿ_*•°m;ý\'UŽÍæb¬¯nŒ‰ÙéçjÌå Tâþ/­&-ÁýxŸ?©š’~UaAd¦ÿoÈIú>þE¿NîΧtæâ~¼ ËŠdɄ҅Bíj° ¨õ–¯— ²êmÛVë?Ÿtq5ÍÚ$ÕI5daŠ…ïÇÂmÛjËö÷B÷wˆÛC AmàØÙ ÷Þ{v«? """"""""2OÉi^× ¹êªßÆqr¼ó—6o”´-ã6¦CCÓWù†A6›%ŸÏS©8Üzë³üýß·P©TøÄ'.ÁqâóW†'0MØ´ ï™ëÈmÿrüB‹’Õ›%‡æ­V'²ˆÏ«A\i¸Z `WLzÄ È¹Ö•Xø<‘3P«U‘.™.I®DQDwµ ª~n;˲¨T ®¸âWèì<š>.›Í¦‰×u)•J;v¬Õ›%ëP’,Ã}h÷Þ[¢T*aš&xž‡ã8 -Q¡qbiÛ¶ÓDe|ÿä¶­é(&)ÂwÏæ·~ëR(€ïŸÏM7ýÜÿü‚[Á6®Â ãçŃ«J%l›êZžFÆÏ_ÉÀµµn«…Bü¼l¶Öã>Ì5$ýøÇß'³YÀƒà!x]¼ºIáfô1«Ý](ý0Û *Å] ’¶I‚Ò±€|u’ì'!¼§ú’_ã\âD5꛵ɾ?øÁ‹ÓŠJY=2™ø¼POÏô÷›\qÅ9äó¹I+§Nz^:›¾Ÿ/šÜžµþÔ[EANçåû>ÝÝÝŒŽŽ¦ùð‡ ¿ÿFÞùÎø÷ÎÎx=‚ >]g_1 ÁŸWs_E8­­Ö:Ô%Nð9,mU^Rl0›V´6q…bÚ IÜ™@~ëoO«Tª®W²>ól­»ØTñ(²‚ÔW1ú¾çytwwÓÙÙI¡PHÛQ†A>Ÿ' C¢("Š"r¹>ÚÆ7ÞˆaDQD†äóµ(fÛ6arÎ9ç´zSeð}ŸB¡@©TJ[ýAÀ±cÇø³?ëÇq†††0M“|>ߤ¢±ö¯ëÒ¤º±ñJ¨à†¿Á˸dœã=ñ pø0!&Aýý[‰"…-[΢ðÁ‹‰.½Š\.®,j“cwvVÛ'¼".ŠÌå |õ¯Òí;Øv<`³í8‰—O’~Ä·%•Žõ!„àVâÛ2o„\7tÞ Þ7 x9PË€Ü_C8/×ÿYp}Èþ7(þaõB¬Û!¼¼mñz:Á»¬ Á/Ç?Æ™> áhõê7 ðkwçß ßþö¦V–tå*ªÀ;3Ï Y*•p]—0 Éår ÝË;w>oÒó²Ùø\™ïCö_®¯Ì¬³Àù:q"°›ZûÐmÔ’ƒKa®Õ‹Eâd¨ tÌ·rq±*'êz®®O'³k¿Z™ÅcH"+@2cEd«%å®ë¦óÛåóyJÕþAà8NCB \.³mœrJ\Þž<¾þŽišX–ÅöíÛ[½É²Ô·ú ‚ ½"*Š"îºkcc祟ã0œÜº=LÎ=÷Åi‹Ô\*(bÛv܇ž…=Oa>úrò|ëÊ“Éýàoðrñ )âS2xJ*!NÆ…aœlLÚ=“V pÇs%ºŸkǸ°v•˜iÆÍd`|¼v[2ßcÒB"„|™S |1XåjKÔ7ÀÀï€u˜cÄÌS€‡ï€m‡ ø¡êò¿…ßÿ©8¹h= î©= ùv°‹»+TÚãêFÿóÕ¹!«“aÛ§Ÿ‡Ÿkû)§|é*èmõ'EDDDDDDDDf#é€uøp„ivqÕU}Žã¤W=•J¥ôs?66Æùç_ärµv¦ù|m~Ãînhkû<ÆÀ)ýÓÃØ—½’à-þ°aü›¾8¯y çœOa¼-mcÿJœtœ8ùæõC¶§~#Œ|mrhÏ›0Ð Á<#þ;í?ö„Þï®Û¸L3nÓêyñ®t)ø£PØÆ Àò›À—'ì8è†Jž¸MÂ+Á¸̺«ÒÌ÷ÿéxì#Pø˜€ùg=¥³¡ô˜WÇëb%FgÁÿ¿`¾0Þî·¾bŒ‡¶?¼¾Õ'™AÆçËL3>϶yóI|ë[×Oûœ¤sÔ¦ *§Sœ)é˜tÜ+ ‹E ÃÀ÷}*•æ¥s†aðG]|ö³Àµ@|?ásðÆb|ÂjX?ö¯TŸX_”œßOÚˆFĉµÅœ›p¾­\“}WªþÌf®Èzþ"nC=»úS">ÏXª®kžÚ~[¬jË(ñ(kŠçÕ*ŽÌ%ž u¢0¬Í5—ü? C\×M“ŽI€Ž¢Û¶ñ}Ã0°,+M<&‚  \.7´›L–Ó,¡†q"¦þ…Ѥ·¹Ü;FV­©Ž£jnÚ¶³P(–eqôèf\×­~¾áÿñÝéóêçl C›³ÏþIÚÒ¡üÞ)ýs;ÿ7ôb¢“6cY0>~9?‹d3Gºéf€ Žgbš`n|ÿýßÀ¿ðm =´¸*}=Û®MVmnð°_]¿!ă °ãDᤜ~ßGì<ñÕPÉÕVÅxÙÆ#Ä­ ‚RØ?7?×CîTn^]·Ì‰²@™ÚÀªuÕ—Ô¤µÛÊÉc `Ú5ãe©'Fóùê2ŠìŒÛ¹’‡ýÿû4ÎúÎK[ý1‘ARpo~ówøå_v)gÎxEQ|~¨TŠ—ÑlÇ™ärñɰǧ·e³ÙiŸcš•\¬oˆòõ§o®Ý‘T å›f!Õsm@|¯›8É·Ðù¡–¤[ˆâs…âó}VuÝ–rnÊÙÈWª¸Ä‰G›ù·‡#Íñ(kJ€«]F,i:“\.Ggg'žç‘Édضm[ú¯ïûضÍÐÐCCC”ËeFGG©T*8Õ ëû~ZÍoGüo}‚Ñ4M‚ À0Œ¦ Å0¬Í)—LîkÍõ¯ˆHUÖ*ˆëù~üó‰O%âÏþÞ½ñì³gŸúÔ«q|ß*|æ3—¥Ï?W]õVÀgûöÓâÖ¦¯Ý‹ó§[9üÀ)8^û‚省QK¥Í˜›Éç![´(—᪫N!âõˆÆÏ¥DãEÍç-õ<Èü˜›«÷¼¯î΀x Ð T+9´\âc–ÚdÍEâ«…‚êO'ÇÀü4µ„äf°î€ò½Ä܇À}0NþÙvuõm#&J’ŽÉ•HÙÆ+Р1é˜J®^*×½’X·ƒùÙxû.}ùØ2}šDDDDDDDDd¾âspñ¹°|>â÷ÿF²Ùlzny:–Uk¥:::·¤c†lÛ¶|>ÏÀ„RFÒz¯0Ť‚wÜAðµ§ðç_ /}sóÇdÀj›aòÄçæÊÄsV ܪÔ`á B“tê$¬êÿ«Åx3¼örœ¶·‰“£É9ÍmÔ *–˜*eM‰¢ZÅãBø¾eYtww344„aiå¢eYDQDX}‘äÿ¶mÓÝÝmÛT*•´Uj}ò/é{Èçóéó’å…aH†“’†õ•ÍXVmN¹$éÐ,A)2É<…®ÿ?¹€êæ›ïæÙg À7¿ùcÎ<óe?¾‡Çûu~ðƒKˆ¢gxï{Äu/å²Ë>†m¿ÂeŸ¦xÃ=†Á‹NòøÑ·C¶n}”óÏ¥óÅ=AML'/¦ãDz²Vy NKñèÉ3°®nkÜ€mÛ \&ú‘M8Æi¼Ì»ˆÿø'WG•‰ÿð&W'ùㆀڕ@õ‰¿ú1–ö0øÝê2òP4ˆVc"¨%3§cT×m¶Ê&i[“8$û/™ÃÒ4 Áú àÀ9c?å‡?¼`>M""""""""2AO%”ÍÂø.:;oÅ0ŒYU;&žÐÕ,j?Åb­kU†ø¾išd³ÙÆóÑQT; Ÿ´ÜrœImӬ˟ÁýλpNœL4M{O{פ—ŸæÁuÿÏŸKæ6œ«q"s¡ÍóLnµZ¨.?ÉQ$ó-&²³XîbKºâÄEKL‰GYSl;Ž•³I<&ÕƒIÂ/Â0Äó<¢(¢\.E™L†(Š0 ƒl6›þ?™«1Š¢tÎEÇqÒjÃÙ0MÓ4ÓIy“ªÆäÿY–5e«ÔR)þI^>™Rd6|¿ZñgÅc߯UÑ–JE<²‘¯~õ2¶n½€­[-Î>û-¼ímp÷ݹãޏÙúÕWœþÄlÝú(Gœöj(í"?—ÿ7î0úÐòtx :°(ãIó@Fõc;Õ¡”\PE`žÑÓÏaœYWÀÿaºòÙ“Á1 O'“«%≔âÁ@µB¯¶.“®Nª9ò‡õ‡fÝ€cRç‰ÙŽ ÐîÁ0j­—=/~?‡† ôpõåmxÛYG0ÍA wþ/$""""""""‹.éìçºñùlÖ'“ù[ŠÅ"ŽãÌ®à$Š “Á ‚xŽ!ljÚÙY; ˜ÉÀÐaR*•xÁ†ðÿónxá „ï œÉã!>Ñ”œLÌåâ`u˜öÿz5Y#>/5åªVÀxñµ‰•íx=ŽÝdA]Uó‘8?èžz2ÙOˆÿhÿSõÊÃÂüjœÓ¬f“,×®Eâ?üÉ•RPë¾J$E„aÈ£ž.å ÿ(z;¯ý=ìÚðRž=ûYnã6*Ÿ®ð¼ç=¯Õ«-""""""""u’*Glj¯×7Mèî.á8NZ3+¹\|²¼>yhš0>ÿ?Šà× P€s+çÒ{/[ŸÛÊí;¯ÝóÚZÅžçÅËŠ¢øD`¥R[^6gG'œ³n: P=Ÿø¤Ýøð$O?ý7DÕl\RÕ˜T4f³Ù¦‰<Ïóp]ÇqæT¶>_IcrµJRÆÞìqS%7“9ñI2SÖ¯¤ínRØ]-£"#±:(†ÿ^(9bqäÈÃ\rÉ爢2ÿ÷ñÛ¿ýà ¼÷½ŸäOÿôQž{®öaKªêž|òZn=ï͘•ûᓟd³mcV_Ã$¼ÚÎ8ÁßÚÈá; ôp? åj‹R þ£Û Ùúö!µv¨f<ž1¿ ¹ÂWAðÍø9éïšðM:!ºøØùZ^¨M²œ0˜<ØpªËl±R©”*=Ï£T*¥×ù|ž(Š(•Jxž—VEÇ÷YÜ}w„ãì`xx/÷Þû·ù|ü3‹qÁ¿UýÉRë^æ'!!>¿×d·Í;é¹õLÖ£­V—™²ê$IDÃ0ð}?WñsŸ{– zÉdþÃÓ,òÇ<Ķm^š¬KªgJÊ%‰ÀåJÜ%ÉÓ4§MtN×j5ŠâP&ÇúÙThÊÚ“´aH.B‚8©84A’q@±KW]uŒr¹óÏ?|ˆüpõ~‹RÉ"Šàª«.Äq‚ àOþäbŽüËŸpîÃOsÑ–×Qºÿ—Á°,›±±óù_'¹ÆÛ ÷à™{3„¯‡ð‡ðÖ·Ÿ‚ë‚{E<Èg‰ÿ“T"B튥d.F—øsgüoô0dA~ÿJ›ÁüP²Ë„ZPãN0Þ/'?M?ù)ÍZý|´qYE»Èàà ƒƒƒK·""""""""2k¹\-W˜ÍB¡PH‹c&Ÿ«Ž¢ÚIÀä\Pý¹ãñÆÌZ¡P X,†!üùÏÿ9Ïõ?‡}Øæ×>þ6׿8Êfa` ¾Èÿ”³ñÿ fßÎt:‹ßi,™KÑ!®@ˆª?jíMË´¾Ð`uX›/%eÅ ‚ =™^(ð}?Mú¾Ÿ&DþËy3¯ýi\zi\tàÀ^ô¢Q(Tæœ@LZ”εuj6oí:Û×›‰mÛSnËi§ÝF< Ø ù¼A.—#ŸÏcš&›7o¦X,묬LaXë•^*ÅŸ¿b1þqœxÜ‘|dòù8Ùèû>Aàyccoåøñÿ…eÁ–-ß`ûöÓ‚¸õª½õ~üè,¯€mÛqÒÛ‡ïþãÇG9ï1ò/ÿ x6fÚÚNpö&¼qSü‚…l¸ßó qåax/˜Ã`?¯zÁÕÄI “^çÉ À¦¡ÿ¹BþMÀ™Õßë¹d9–&XFí¢®å*ÃÃ0ð<§îŠ3×u±m;­Lt]7íŸ_.—ñ}Ÿl6‹çyéþÎçóiÑqœIDQD†³Ž!ê¾,"""""""²ò$IÇJ%>×åû>¥R‰¡¡¡©ÏûF\‰X(Ä?ù|c[Õ:®ëâºnzž½X,rcxc|ÞÍÞùN8ÿü¸%Z2#Ôæ!L*ˆç+´ª÷Í÷|[°Ä;´þxXýÝ NDúóZ¢Ì²bø¾ïÇG}rÒ>¨öLZZ–ÅÐÐ^µæ¼\.§'â 8p ¾Åt¶Y{éYI‚¹9‡,bÆëÐdjÆy‰"ð}/m½šì“¤ò)ŸÏ“Ëå¨T*ÜpÃÍüô§ï оÁe—uẖå§I €J¥‚ïû 6nܸÈïž,§B!N2&§6³ãÔæu†Úç?9¶ …BZ-÷ßý¿s×ßíÁ=Üy#¥{âå–€R``Ÿúe¢ 7qmEƒ—œfðÀY'a¶ðÎKàù€ï|æŒ'7Áhü;â?æƒÿ0ØÆ's;˜¿ÜZ]¿fÝljEÄ“4Ö±ê‡PM‹{« ¿ÅN6&×Ir1 C‚ H«ÇI[£º®‹eYär9ŠÅ"žÏÉ2†††Ò6ªÉE•jKªŸ§‹CÉÜ´""""""""²:•Jµ¤£eÅçï’ Úg<ï“TØö´Wœ'çœ.–÷©UßFíäâDEj'ã"j…ÉÜŠÉË&IÌÙœR_ÎÚ˜‰ë4ÄÒ'>×9%eÙEQ”&>J¥¾ï†!a¦s&'à‹ÅbÓ¶¨SÜú› £6Ý\%'úç’xô¼ø§¾Âl:IÅ™aiÉ|E:t!wßývÚÛïeûv¿!Q‘TDe³Y,+ËÀ€Q÷Ñaß¾ †q?øÁ>gAà00àÐÝÝîïb±HüÅ_üžò˜¢(þ\Ùvœp ÃøÂ¥¤pµ>É8±˜µT*Q(ÒÏišX–ÅG~õ#œýågá}Jç|ûù/ÇøÿmÁøïñ²²…mX¯ü>þØ>é•RF·O=Ç)œì<Œ‹^Ï'#(Ö·[H&MöÀ9 NÝ1a`þ X£3Tà%s,Î0ÍjÓÄcݱ;›6óõ•ƒI ÔúcoóæÍ”Ëåt~Å$FY–E†d³Yòù<¶m“ÍfÓyZ·mÛ–“„âÄ6¨I|X¬«DDDDDDDDdÅó¼Z!K6 †‘Étù|¾¡“V*ŠâyëOx59ù•\4ŸLå“Ëå8|øpÚa ˆ“‡sMÖ·3¨%“$d¶úÿÚ\†!qâ/9_XŸ¨l]Ç¿¤”x”%EA†!®ë¦Œ Ã0p'm:—DßDÛœZVó 4‚ šø0kè_Y’Ï×·¥œ°ãÇG\wÝg¹é¦ ñ}Ÿ|>a<üðÝ\tÑVþûâ¼ó®ä¶ÛîäÃ>…R©D6›MÛž&Ëíîîæu¯{ /}éKy×»n¢¿+wÞù|.¾øó„¡Ç£~œý×O¦É$阴JÍå ›µ1 ¸öÚk9ãŒøj˜d’a·Ú¦2NLÚ sÈ}ãßhõGC¦W»Æÿ µÖêaX›Çy*žçáy^Zá˜TÛØqb¼'øp‘IþmòÖ¸Ö=> ƹçb½ó*¢ê:$º®;c#Á½`ý D?¬¾°ÁäaRÍ8!ŸÍÖŽÕ“ôC3ﯙ.üJ²A¤6$-M“Ø400@&“¡R©¤ýó“Ç$•Ö–e5´@MZ?'ÇÜÄÁ išé€NDdʼnXœy9DDDDDDdκ»ãëý-+>ÞÙÙ™žOj:Ý–ë’¶ø›âJû¤W&“!ŸÏ§ç³*•ÊäsTñ÷Âù&›„¸À¬.7™k±DÜÙÌ$žg1C|ÞP³‚­IJ<®Q™Lüo¸–R’àøÚ׆ù§ÚÈø?û³ÿ–Þ—Tÿ$åÜIB²Y²1‰Íª˜\7¾$I*ºnœ0Ìf« ’:IÅ£çÅ÷‡aü˜ÎÎøþ¡¡Æ*EËŠÿñÿ Ã!àä“ñ…/|ˆ .ø]J¥Üwß ¾úÕ·ñßþÛgž¹‘ññþú¯sâÄoÒÑñÖëãäa4ÝIk‡¦­’˜Tœ¡’q*ɈIõa’ÜOZ …t`†!¾ï§•‹Ùl6KIÂ1® ¶¯N¸=::šÎ-[Ÿ´‡Æ*èÙ$•t‘+DpîÏŸ ]­^‘õ!ŠâÓu¦ ‡Çÿ†aHww7†a¤³&éîŽ+&´CM }’=ÏÃ4M†††f>U_±¸˜œ)þ_o] »†)ñ¸mÞ'.’¤ZRÝ7I{GÓllß¾ï§IäbâàõÜsÊÿ…¼à8wÜñvÞþöãÜrË…uÏOÚF˜¦Þ–$Ò ÕIj“Ê®$fYµÄŒãÄ1âu³í$@OÞNËŠc²aÄÛ40'O>ùž{î'd³ßüæøË¿|÷ÞûwüÏÿ™áE/úOî½w¯|å+«IÊM@ž_ø…'¸ì²¯òÙϼë]Oóº×m!^ƒã¼†;îˆÈçÏÆ4ߌëŸü \}5DÑetwW4\~ùû9óÌ3øêW;øÒ—^ÄßÉþa|_ýº›aˆ}Õùärméöåóyn½u#·Üþgž¤üÿܳ1M2ÇsW[Äú.î^KôÏwÝv'îI9ÊýçâûT“©¯lõÇt}‹"¼B@pçið†7àûqÎ0À9ëc˜¿÷I*§=F¡E|P|åÓW>ð:¾þu>ûðÃtø>å"~íóWóîÿ|7m—µqÖSyØÀ»‰…¯²àVnfæþê&äï þ£€Bö³Ô*«¬wβ¥ð -jÉÓÜ@©ÿ?—«Ím›ÉÄ·•Jñï–Ü$˜ÍÆA·î|AoW6ÛØ¢âkIÕäĤc†AŽ/~ñ/èíýn¹å×¹ùæ°m› Ò`lš#¼ã/¢X,ò¡N[/nßnsíµ—ñÿøv‚ÀÀ06b[èììäÿøpCUf¥b¤o@ `WË(þæ:‚^@>QôkœuóÍ|èÚÃÕ>šf<%^}é—ïC&Cƒy¢À€w¿ŽRpAÿ}ÙvÁsïü?XÇ¿Î!¹¶Á4/­-òp¶|–Ümæ¯gàcÓ}Eð¡·iõGuõª?sÍ1EQüá­ËܼèãŸ'üÊ)œüçXçÆ8;ÂqŒôý¡pØ?Á²yþóùœëòÐ] Ïl¼˜ëý{†ÀîN!®V)þYñ‚ àLâfL“‰VücØÄ­V§zÜ,”J¥†ÖÅÉ1–T+‹E|ß§P(`Û6abšfš4 ‚ M–J¥´}i2Wb±zü$ÉÂä ®$Ù8Q2£È¼EÀ6â¹ Ê \–L’Œêç°MEÕŸº˜µ FFÇ0"ÚÚÚ8zô$®¾º­îpè¡#Üz×#üʯœ›Î9=[û·òÈëaó›ùñ7 ÀÈ žÏ¡3¾Êæ¶£Œž;ŠmÛ ¿Ä†ãø¹oýßzÅ·ø™ïþ ýôTž~úi¾ÿ“Ÿ2òÂOÅ|ØfÃ)ÇùÏä¡ ñì³góÔSa¯ýÑkyÍ_CHÈÿæïø‰YÝ §±NÞÁGù#¾pÚeܹáN~õƒï Ožt&<qÆYßçeOÿõ>ûô^Ý‹óÀÇØ}ép_øz«ßöÕ-"žËÄ"3¸ÕÿÏ¢]¸ˆˆˆˆˆ¬…B|ܹê;_ùq}Õ)Œa9N|® ÀõáŸ<ø^Òêî0µ/ÀeøMà¤ø·¯¼ï+ŒÇ©<[©Í¥h·4ˆ[˜šL>¯—|oIÎí©Õ©,%טZ›Ðø÷‰-9ãÇ WÄ'¿Ç‰Å8CiÛ…jëÏ×pÚi£«ë ×_-o}ëùd2ðÿP{$Ù™$“‹*ŠÅjWÈjò³R‰«'¶WŒ¯îh<¹'È" ›µª­Í4‘Ëå(‹é¿ÝÝÝ8Ž“ÎÇq”eY\|qÝݛٱã¬t¾»f=²l6íuùö×½Ž3O:‰sß½ £–;r}¸ôRÚº»keŠõYÝ(j,½,•È ²¿›­®“ ]]ñc¦ÊÜØ6Œc„!Å´äóB:3Õ|’Ù]gc]ðF²×ý,XåÏÁØQ· ˲°C0Íé͆ÿtlúv«?ª«GÚDË3%ï¾Àï—à>Ÿ`Ì$ ¼úRxøb¢g¡pÿUØmfà‹c_¼ Ó¼bÒ"¢|žÏüágxöÇÏò§å<ÛŽnãꋯ¦÷¡^N´ í[mµ ™M`|²þoÍb½§c0íHIѶm …Bz\–Ëe2™ Åb×uæ{Íçói¥´a¸®K©T¢R©¤Õñ…ACUaE …æ=ªjqÎW‰L”ÌIàdžì·T’¿Ï–ÕxAĦ|¿ÖÀ¶ãßë[u;N|ñÀµ×>É|î÷þàlÆOç¹SžcÇóžfç%ñgƒ›8sÙ¼ý7ïæ·ûªôù[·ÞÏÏÿü1î¼óqŽÜw¿x|ÇÏ<ÎG~ò¼†uùÅ—þ5ÿ÷žÿÀ;_t€þ¿ëîß¼ùÌÇ"†ž}_K‘™°­×ŸñA¾óì› Ÿ3y‡8»8À›óQâ7ØláÅyx7sßár®äè™Gy|Û~ž»ÿFügÚø_mÿȾ'vòÜésú‰ó¹ð™òpåëüÍèåÜ÷Ü&žwâû”n‡ž«Å¨Oÿżæœ{¹àé_àegŒpå³wrÆgðÇOà=õ?>ý"¶?ïTþÇЫ¸güLÞuÒ§ø§ç®æ?ú6Ÿ|œ‘pýùŸç´àf¬ã[±¹ƒ WpóQNð•KoàºûÿŽ'Çÿ•_ã6¶ýìéüàp¯€¾´éS¼ø¬€Qޱ­¯%zä{ú‡¼àŒïQ>‘ç/ØÎÎËŸá¼s~Žï¼j+g>x>û/¼óª³Zýa]mê¯ öˆÇ Ç‚,q[ód~dUF‹ˆˆˆˆ¬[QŸnv]¨|rŒü={hûÒ>ýà øÎ³Ïò‰;î`ëÖWÅ/ÞV‚/»°Ù†wWà]vü½ÂŒøœþÇþæcØï¶ùð‡?Ì-ÿõ?ú8¼…Ú<Љä;Krî"$ípÆñù΀ø ¶ÈXu‰Ç¾¾>úûûcçÎôööÒÞÞÞêÕZvÉú[t&‰ÇdN³¯ý.Âð±¬<6<ÄøR|ð|Î?ÿA}´— .¸€ nä©§.âoþæqÞõ® ËŠÏ¢ÆUz˽»ï†±±¸U)ÄAj]ù|óV§Éùý8á`aZ=™´Tô}˲ðÄžÙÄ%§cðæGøòØK8qÒ ~8öiÎå\¾Vú:G¸–x€gügø5ÞÇŽòš“Nç“Û?Œ}ÇÏsÁwŸæüs>Aç]Þ\UýÎrþE‡8õ)ƒ—ÿÃÙœùüóÙzzÄKùWžÙ8εNðÄyígþ,/|ä…9÷.ÿ]ß;ÄcO©€žÐ¡!¸Ì} ‡€—ßï³^Á÷Á~S¼^þ'€s€‹ º¬K!züÿ öïCômðïãUµ 9ò=PÚ Æeàü&ˆ€ûðàG`ð²W€IDAT »–`€ø$w‰ÉíV““ö~õ_p!ü;0ÿøwCp!d/ƒÒ}àpð,Xo‡Ò?Ä‹úû¿¿¼ÿ%œ~ôt.9ç.ýGƇvcö,æÐ†€Ç6>Æ\À“O<ɹç^7ð‘ÿ:ã±³Í7¬ö±ÈTꮩÆ0Ïû@­QS}ÇyÀ§Ÿ^ÝÇÄz9g(²ÔtÎpÉE}ɸÞ'Nê%U„!DÇÀ{÷£”†6>¹?½øûìúiÏþøYÎùé9|ÿßçÊ®ä¤ÜIñ 1éjVýt Kγ'Â|ßO§;Yj‹1N^U¤§§‡žžöîÝ‹mÛßm¾¬‚ñ]0%þÂíÿYüÅ=x8¾Ý×OÁodó7ÿç$ÞûÒ1.½èAN?ñþî|6:ØÌQöç¾Ë·ÙÄÜËŽs‰y2Ñ£o¦ë’8óOqcÛÛyþ«ŸÏYo)ßùpEÙ6jsÔ]Çï:Î]Ÿ¸ƒ+3Û¸äˆ _È·¾õ-NzÅ+x×ÈûøÍ¿É±cǸçõ÷ðæÊƒŒ?ãäˆÇx'ßt¹ÿ¾ž}lýÖVý7.ÿósúó>À ?¹“ÓŸ{‚÷¾ã½\~ßÕœ~Áétvu²©r'gý³ñ9ׄç_Ã5N¾vàšÎÿe¸Ð†k -¶¾Ìˆ÷}r¢Çq œpyFrutò~ ŒÖ?T¬½gÉÕÏV¶ñ$ÏÄåL¼B;‘œYHþxLew±É2’+Ñ“–[ÉO}ÁäúÌÎÙ¢Äd.&ÚÙ'“øj .ÜïÅW¬`UK ”%ºâ?(]þJüCÕyÅî€ì¯BÞ¢a†^5ј´ Mæ+¸Äº„¶«ÛèîîfSeØp¹yùÔ«[t$mH“¶¦Žã¤ó‰ÕW*&•Ä®ëR©TZ—FQ”Ròù|Ú’Ø0 LÓL+ë[œ:ªt“‰®íuš¸—•aÑÆÉ‡d„ä¬tguÒ„3,¸È€[µk±ºP¨•"^0@ø×Yx-„ƒ;ó à•ÆŸ¿ðǧp8¿rêstŽŸ„}â$Æ^ó%žôFž7Âɧcë‘û9úOñ¯ü oàåüã_ÿß~èeܽig6¼£[»ùrçS\ýÆïqÞ3Çø­îáÜo–Ÿ`ó±p|ó^þ²{‡?û0'm«.£š°ËçãÇû>اÇ'¦“yÚ- x!ð?ÀËgƒ}6„g@øD‡çÆà-m˜6ýÄQŽ= /:…g^vœŽŽÆ/r!½æ4ž~hç=´§7<Åó¶ÜÁõgÖ¾Šžzü8ÁëžæÆÍñÛÿvû·ø­KNâW.:'žx"Þ-ígó쫞£çKxŸ/¿úA6?Îæ£Gùp¦+S+ŽüÕW߯ïþà<ûì³Ü×ÖFé’K°ÑÑ+ø?þ— 6ßÏ££pGüœ¿ºè2>Ûw)•}>¾u+•€»kï×IÉÇá“Üçøóý‘êðu6ð³<ÿrü1ÀCp_mÕ wÇ?ÀŒj_’×á¶ø#S¶Õ}„ß¼Ø"|4Ä|¾‰kœÂ?¹ŸûÆÛ¸tcü@׸„ûÚÚ ú¼+^:Ê££lŽ'Ÿÿß‹¿È“O> ¬ÎÄ㢌 ê¿7&ßíêZ›Mú~—§ö‡Ê¡V œH²ÏÉ2"+ˆ!þ#–ÌÁT_ æB`O@á~à ½‚Çâu`{õbƒÀ?=~¼ó8¸u:ð°îˆŸ]ö 0FÀ…àYâ‹R Åsª¯sIuóî¯[Æ%` < þ8?…â(ü˜øxÜ<ÅçCçíÕݲ5^Oï‘ÆÝ_¹2ÕÕ좋üÖx_ú£`o«­v‘Fbàrèþ^my¥âǘ[À| ºŒWrâu^|Yôs†²¤’ó%s•\`=1ù2Óò’Ç'ϯ?Ÿ1Õ\íP›Â%˜Øñl•J.ØLöGr®©ÞO~²z»¡,zðnâ¿™e Âå<ÄqüòÞšÏ"x?‚ÎÇÇ81Æ/Ÿúº7ßÂѯåÓçžË+º^ÁK÷¿”«F«Ó“Xñç1Š"<Ï#*ÔŠÊårZ |_vfÛAOd…X5‰ÇááaFFF®@joo§££ƒC‡M<î¹ç¶lÙB×e]µ–DÉྛڕÇõ­Ìjæ¤%Qõ Hôl<…øŠÝRuÐ÷Âá{x´ÿöþçóÙzÚ´qœ ?¼›]ør>ùdNynŒm<ÎÏ\¶™×þ´låß3ÿNÏ¿cãÿûÿ5$Àþê™°ùœ+¸§rÎ߀ù‘8ùcçqlüÎxî·¿YüÜ9?Gù{eþâS§°õâ€|®~ï'yÑÁñÔSO±aë¶Üÿ/\ôÜsœrÊ)œ8ýbÎxâ§TÊð`ë%[áµ!lýœcA{üGëê·Yðyƒë¹r·Nþ’UŸôÍšpv‘´Ë×O€3ëÞ‡‰¯_†O­ÅðÈ­pöÙg³±´±Ö–ªþ‹ÚÄeÔ'”™ðšL¸-iNó˜äßúÏRÒ¶*9¹eSkÑWoœÚÙ…JõþúqOýól¾¸=øàƒ\|ñÅñë$_'&D“/6lýÉVV£…Äd?áÿÕ‡M<ãÁ?:0^7ñ¨i‚o¾ðõø Á_ û‰2åx·ÞxÅÙÜwß79ûìˆ×¾ö_x衯S*…¸nm› `-˶mòù<çw[·Æû=Ø CXY+­Dt]Ó4˾ï“Ïçéîî¦R©Ëåøÿ³wïámœç™ðoJ²¶zh9ò‰‘3´¬ÄTõÐŽ—mã$4TÒuµC¦i··%Ðt7aÜ_Rk»Înh˜´jºÙ`˜®²=¤!§Uâ$¶˜`’8ÞulŽØ¤áÄ2lYŠ%ŽIÖYøþ¾C‰ïßuá" Ì f˜‡ïÌ3ïóŽdÕ*z숢xD" ã¯ÿú¯ÑÞÞîk8ߨ‡dpp°nïÔ]¬ááalß¾íííÕ^•%W‘6ÁkÀ˜À+°Ö"‰‚<!D6SBïù ºãŸÂØÏÖãØgÝò>ôÓ$.?y9~$@ÏÞ¿œú©[Ýä—À#°ñØøâ¥êuÿ¿õº]8ðÚwð§ÇÖ Åw ¾ pߎ»pÙ;ÞÉ‘£ø;o…éÀGŸyÏø®Þò;÷Kì¿c#dYÆßš‹Ž–¤‡‡ÑÓÓƒ¾áaÄãqüz8ŒØhGô [ÚØqþ²üçøáßýÞüæ7cÓm·As(Š‚H$‚7( Ì[nñâG €(°ïïžù¹ë.÷çÌÍ ¿:“4¹ãŽü3Vá®Ì‰‰ Œ{'+ÅJ‰å¶ ÿ9 <œÑ »At=œ¡À­¢qrö)û‘·òleeu ÑÿÙ  ¸âmÀúõì¸ѯ¹Óh3ÓZþÙ ý’ä–Z Á¡{þ _ù‡kñôKn™öNã×üÇÏ?ïÃÖ­)ÿÞO0ýÔL=Š5kÖàüºuz'N¼ðè·ŠÛü¯;¿;®p5pádßùÎ&ôô\‡«¯~}ó0¬–ì Ê!Ë-É,®½½÷«O"‚Ã^;û¡ ÐÖvjvsî00ÑGÆnü•aà 9Ó4=0û»,˸ýâEÜzìV­Z…sçÎaòŠ+ðù§®Â† pîÜ9\}ëׯDZcÇ0qÍ58»j.omÅáDZþšk°zj 7Üp.»ìYœYužË[ðà+¯ ©© .\Àî¼W>ú(>øÁâäÉ“˜úÕ_Å'¿÷=ÜvÛm˜ššBKK ¢[·â•W^Á5×\ƒÇ{ ߸õV ?ú(>ò¾÷á‹÷݇P(„Ðð0V¯^×^{ ×\s þzíZ\zé¥e–e!6s#Y,C0D ñn,C3_4Ñ>”4Í+³%~šá0âñ¸W¡bĶqäÈ|Õ*´´´àræéÖutttxw΋¯úÿûÿoéØ%Tn,Xj½›4Ô1›dÌM¾å»‰$3é&vbæïâ|L$Cžr€&ËM “fî*˜™Gš™æÛ}œpÀVæ•îÿPùß8쩳H&“h=ßê–Ým¿Ö!Àüê¢÷.œÖ]œ»ªÀ €ù< PÛýÁ€³€}vœ?¼±[W#øãfàïí÷F*ëPÆ6õ‘s@ø_|ˆÜø¿ 8§g^ïB·h¢A@}“[Ù!˜y>Û|ñmÏà#?}#`±÷Æy·ä/à1àÊyüFÓ4>=|%®Ût_{û«øó±+½Eœù_g°sÃüÁz<ºþ"ÞÜ|Güø”Û»xð".½ˆn9Š?¹7=ŠƒW¬ÂOÖ\‚g§.GóÚ‹8ràŽ^~ç×_ă/]ŠmëOà©ÕGqìôY\²ÖíM|âÀq\·© ?_׆ÉãÇ`<ñ ¼år ¯¿ˆ.¬ÆÙ³gpjÃ)¼ºþ^·þf<{Ï5;›bõ…×/®zoH]ŽK¥·býêsXsÙq<—jÁ¿;s×_~ ˜ŽHGáœÞ„¿üwž»òU¼õåÐ~þit]æû¯6ÁUÓ›pôÐõø³w]‚/½/þÛYü}óSèÀ#x®É‡'/Y®ãMøßÀ-_ÁÿÜ-¯ÿTó×pæÌk>†ËÏ_ŽW½ ŸxðFúŽNÝ‚Ï\ò$þ¦ÙÍD>½êi¼é›ðÌñwàÑõG|`‰ÜÊ+7\ùƒ+ÿšódnB]Œë¬Î3M³]ꕜŸâz’ ÷:¤¸¶”Ù_޼ë.|÷ZkÁñ›Ü ç.?‡<€¿âÞxóôǞƛþúMpgΜÁ¦Þ€ÞþN­?…·<û¼|õËxióKxûÏÞžµ9ûïØÕTqêÔ)¼pë X}`5Z9[~òyßóøÑë~ä}‡~çâïà_Vý ¦ÄD 輺׺,ذ¡å xFØ>Æ€2”Œ éÀAQo?üˆç´.Ä|¿¶á×ðÒæ—0™ž„ê¨X³f ZÐøÊ³ß÷7?ˆkN]ƒîT÷¼Ûº%„èc³ –ã_8ޝûä™@<ßöøá/¸=,0æÝžK.¹ßø8Î<}·_r;]w¯lxï8üެ÷ÛsêÔ)ÜÙýx݉×á×/ýõ’·'s?lMmÅó¾ç½÷m#8pãøî÷¦¿áÔ hIµd½Ï _@=ªÈù ¸Ç>`D™í°ò%Ûí°ðF Îí0å÷CYõ:¨kÒøÅÓMw~üŒŽLà__/c•¦AÓT´9¶)Û‰F‡½6¡H0:ŽMÓ¼sìÅÜìßç‚pmk¥^‹ÈU7‰Çééi˜Sú ¹¹çM¥R8þ· ýÞÏð®uqlÁ£Xwz /~ûf$ÿ¼SSSxÓ£¯áÉÇcãÌ]6dlü·Ãx`óI¼üòG°þÑ üÚ¯=„ûÌ$8P`á-]»ñ…³ï £ãá ï_ó·xùµ×ðöÃkðÖ—Îá–[nÁC=†ŽÞ€¾ä0~õ”{ÿô¥—âùÍ[ðþ©!üY<¿ÿ¯1}ßðóßù¼þïÄCO=mÛ¶áèëñÝÎïB’$7‚ÿò+ÿe6‘*æËM’ÎôêÑ, õ¨œ8'Nœ@è=ßÄc/Ç¿ßr-N½åϰ¦õ x¦oÞŒ_üâ¸é¦ã¸÷^÷ÃY»f;®Þð¢muXãq®¼òJ¬]»Û¶méSW`rr¿õ[¿…ßû½ßÃþýû¡iŒ™ÒÀ¶m{c˜Š1Eò0"‰d%ÅC$UU…ªªU±Å¸¦¥&“ÉäŠÓ¢”ïC£YIŸu¹m‚“ÿtáû†¼ùkqî-QœþÁxàS8{ö,®¼òq<ýôu8|øz¼öÚÕ˜žv/x½ñ¿Ã‡?ŽãÇ#ý#ˆÕz¼îi<³y3Ö®]‹Û·mÃßÿ>nîî—}ÝÁ >ó§Šx<îÞh ðÔˆÎWâøu7á§7Ý„ÛÞó|wxö'‚ooø6ÝuÿðÂoà?|ô;xÐ4¡ª*.wfxb,T|ùË€øLyr1êHÎxÃÿôOÿ„ÿñéOg='Ndµ÷òôô4’ÉdµWcÙ­”øWn›î÷V<|ÃWðø‰ÛqâÄ ´´´àú=ûïŽ?Žw¿ø=üëƒßÄÙ³—yó\÷ôÓþù>ø ^èéAïßü þùK_ÂgþôO¡}ô£@4ê4oܸ<~‡Âí·ßî•~‚ßt:¦¦&(ñ8šü~¯ ²¢(x×#àĉx÷»ßh4Š+ãqÜê÷{‰¼ø¾}x,cž«ÿ‚Ù›µ¢Ñ(Æ~øCüóÌøï~¿ïþ‹¿@8†¦iÞøÓ·`v,jÃ0ðö™d[üë_wÇÿä'1ã–[nñ¦›p(cžÈ;߉£££ø­ßú-|êSŸÂú›oƉT ÓŠ‚Õ®”e\™ñ>SSSxë>€Ÿ¼ú*nþÍßÄ hnv{nþÑýLÓônˬP‘Yu"ó§¢(p'«´ø]L#˲7(¹%~:Žƒ‘‘¬Zµ ¿ó;¿ã·ù3gݰæ8~þóÌ®Zõ£ÜXpzÃi˜ºöpÁ–ðÈ®÷ã—olÅøOÖáOOÿÖžSYó]÷Â4~œþ;Ö„_Ñ"õ÷ñü+×fM³ê7~€W.ëÇ/ïý%Þ}ü{xõŸß œ™ÉïúÆwñêëÏc|ü}¸üý½oý¾øÐŸ#s¼†ÞàkÏ܃3g.ÅÛžý.nøùQ|óć b Öä <`á©kïÂéÓŽS§Naô™ÿƒ«Æ7k==þ]|ï²Ëpñâ 8?þ¹êgØôŒ{Á[¼Ó'ïÓ«?ŒóÎy¼rì[èHnÿKÀåâÄò CdN:²Í91~üa_ŸYªù´ çiSÈ®íÿ©øMEð»6â°³O­Ù{q_>ÜqŸ{Šì9ìærÿvæÏŸÀ==þqÎçºóÐFœÚºOá± ðw/¾ˆwòdÖ4W¶´àÆoÄ·žø9žºñFüäÐ#³/¾|¹¹º$aÃÉ HžLb³t=þîè3xæ²ËðÆcî²~÷µM8ûŽwà…ÇÃg7lÀ'R¿DûÌþ_yú<.½ôRüæºu¸ãŽ;ð£ýwÜqv?þqrófœ>}kN®Á7/¹ß»á4ŸkÆß¬›Æ»nöáÝßû®¹æsŽáŠ+®À|7þz~ò‹Ÿàák¯ÆN?©³gqíÚµØtâ,.kiÁ_BÏÛ{ðAóƒèééÁ•Ãß$ _;KÖ¯‡µæ)< ]ƒ­[·bŸµŸøÕ·à'û¾…w¾óxþçqÝ;¯ÃÝ?¹¿Ž¹&êA¹±àåäýHšÿ9ë¹W߆GOý:NŸ>µßy w>òlÄ™¬ÄÿGßFHŽŠÔt 'þÓðßóH­¹ >ÓýŽ<ýè9ì÷mÇ…S[4Ÿ€}ó–ñ×þgð >˜À«æOðߑƵXëõÄ€ÛgÐÖÔ#G`Íç†?û٠﵃^œþñÒk±yõ/qâ`o;ô6¿ðÕ¬í±NÅ“¯ßŒW_}«èyñIL½vÞ{ýÊ)à‘Õ@ËÛSxâ‰'ð‰?ù,¦îÎZå×^)þmË«¸äÆ?9îzÃuÀ?g'¿Ôö«ðòoÂOüdçF|å+_Áà§?‡©œ÷¹õêÕx`ófüR:‡_MãÏîú5¼ú?³·çjÆó¼£ß6]Š“©ÙíyÛºK93…çÿx ¾ò•¯àßxøÀ÷^?w¸ÜY±·Þ†_J¯áÅW?¿þxåéû²ÞçÅGžÁOþøãøÑà [pý·¾‰©©ïÌnï…Møç~‚7ÿñÇñ•¯|wÿ§?ÃÔ²?ŸË׮Ʒ7߆Í7øæ¼Ïk¯å¾Ïòî·æ“pôl}öx¬ÄùÁÈßÁ¡Ÿ¥ppú8,´áwÿîA<§Z¸xñW0ùÝ)¼ñ'ñwO~§O_‹éé+±~ýAà»Ý8}º›7?ˆø™Ë°å[°þð¯bdÏttt x7}Y–˲ iš×¦«¤F8l„k[+õZD®ºã1‘H ··Ï>ûlÖó½½½P°ó'>ñ ÒÏbÕÉ·á>¼Ç ã8¸ m8†¬^½—^zNŸþ\¼xÖ¬ùÒé4Ö­{gÎ܇M›nƒã8¸æšƒxõÕó¸öÚÓH§Óظq£Û3pÃ\y¥{QrÓ¦M8räˆ÷óÚk¯ÅÁƒ±iÓ&œ9s7n\¶}vøðalÞ¼¹ ŸVõ;v ëׯ÷îäY)Jý¬>Œ#GŽ`ãÆøþ÷¿_íÕ^°râÜ~ûí¸øè{ðüÅKq šš~K.y.+ÇB>뉉 \¼x¿û»¿‹O~ò“Õ^õ+·MðíLàúWÿ3þ o™™› Ö¬ù345qá¬^=ˆµk7ãÂ…-hiùÇñbÂöíÛñüóÏcëÖ­H¥R¸þúëqâ„{âùå—ãĉ¸æškðÜsÏáÍo~sV›`Ó¦MX;s'ýr[‰ÇÄéÓ§qúôi\!Æ™^!Jý¬Oœ8àüùó¸÷Þ{ëîä®Ü6Aww7¾õ­«qæÌ]ne °aÃS8uj.¿ü8}ú)\qEÓÓ7bݺuX¿~ëÖ¹WlÄÿøééi\}õÕ8tèÞò–·àÙgŸÅÖ­[ñüóÏ{ ÁÍk×¢ýôiür¦Wß«¯¾ŠÛo¿/¼ð‚WB]´'®¹æ¯!>£Ü6Çõ×_—^ziÎ<×\s Ξ= 8sæ Ž=êµK2ÏGrÛ)™Ûsüøñ¼ç0…æÏ‹yæS¯í‘z]ï…Ä¿àĉ¸á†æÜ´RʉÉdïÿûñøãâê~F=cØX½úƒ¸páš›ÿ'R©OcíÚµ8sæŒ+Ö­{ßÌõƒ°zõjœ=û455áüùóX·n.\ø \~ùH¥Rhnþ¹O.\¸€õë×cíÚ—pîÜ9¬Zu#Nž<éµ5Þð†7à¿ø…_š››çét§OŸö¦)4Oss³wÝâðáÃ^œRÏ?ÿ¼W6lØ€S§N¡¥¥²ãàÝGâÐ¥—âÉ“'±eË|óÄ oÞ믿[ž>+6¼¼nŽø|^Üú•nÀºññ¬y¾™L⪛nòâÛÖT kŽÇùa;¶_wF_}5+>¶<ölÝŠ'N`ëêÕ€ç/\È{N–S×­[ç]‡yå•W Î#z1‹éDL½òÊ+ñÊ+¯à†n˜Ó®??޵k×zóäÆÔ¥œçìٳظqcÞy.^¼ˆ 6ÌiŠsÔ£GâÊ+¯ÄÁƒñꫯâĉƒ+îüàóŸÿ<¾øàÀ”[Îì8Öü V}ÇÁ… °nÝ·Ðr®gÓ·àªU8`Íš5p»;FpæÌ\{íßàä¡á²µkqöâEœºä\vÙý€“'ß‹µkŸDkëÃxæ™]X·n.9u ë.¿ë¥(R©OÏ\H`zúJ¬>Ö†U«Wãâ… 8w饸l&½öÚk¸í¶}xä‘X»v-ššÜTý–ËîÇô%—àØ1?Ö¯ŸÀ¶mOàñÇ{°nÝ:œ;w—\r n¸áËxá…?Á… ÐÚú0R©M˜ž¾MMMH§ÓØàÚ¶!¼ðŸàܹs¸õÖÅ£þ6.¹äw\¼ˆ7\õ¦×®Å¡C¿ŸïyÜxããøÙÿ…K.¹'/^,ø>—^¸€U.àÜš5¸òú¿ÅáÃ÷Þç™Ä]X³f;¾|S®»úÿe½Ï›·<‚Çýmœ[¿—œ>5kÖàõ²Ž§^úÏÞûœ>Ö‚SGoð¶kÖ`óÖ¿ËÚžÌ÷9¹n®¾Úíퟹ=>úÛ¸lÕ*¤ÏžÅ¹ ¼í9wî^÷ºáò¯Ã‘ÔV455á̪UX½zõœýVêö¬Y³©t«Ö­›³ßV¿ºÉ×Þ„‹«WÃwþ<.45aÛ­ÿŠŸþôƒ8wî:;¿…'´çÖ¯ÇÚ3g°fÍHmáôéÓÞûÜvíC0Ÿü=l8MMMX³f 6Ýôð ‚‹/âúëÿ Ž6ãÈñ›piSΟ;‡×ΟÇëÛ?†Gyõ¦Üóƒ;ï¼—þà38ŠKq ¿Ä/ð4ÜŽý6.¹äC8þU¼îu_À‘#;qÕU/"•ú!®¹æ.^¼ˆ«®º W\q…÷ÿ-·-¾\Ἷ^Ûß™êýZÄJ¥Ê¾fX7=Ëñ…/|an½H¦2þ~×<¿V{õ‰¨B~øáœgdwæùÉO"ûºªàϽkž¹,2Ím9¿ÿQži¾žñû­ó¼Oæ4·çyýWæù=Óßfüþ֦ɷœÌçÞà·ù>Wä}:JxŸ/W`{Þ²Àí)eß.v{JÙoÅ>çR>Ÿ[æÙþLõ—t¬„¹4îÊ3ÕïT{5‰êƪj¯ÀBåë2\Ï5‰háˆ`, "Æ"r1ÀX@DŒDµ¢n¢>óøøxÖó‰D¢îJCÑâ0ÀX@DŒDäb, "€±€ˆˆjMÝ$ §§ÃÃÃH¥R€¡¡!ø|>ìØ±£Ú«FDË„q€ˆÆ"b "cŒDÄ8@TKšÒétºÚ+QªT*…]»v!•JÁçó!™Lb``===Õ^5"Z&ŒD0ã¹ ˆ`, "Æ¢ZRW‰G!‘pxÞ¾};|>_µW‡ˆª€q€ˆÆ"b "cŒDÄ8@T ê2ñHDDDDDDDDDDDDDµ¥®Æx$""""""""""""¢ÚÄÄ#•‰G"""""""""""""*DDDDDDDDDDDDDT6&‰ˆˆˆˆˆˆˆˆˆˆˆˆ¨l xÄ­·ÞŠmÛ¶¡¿¿Éd²Ú«T–ÑÑQôööÎyLLL,x»ëaßìܹ‰D"ïk•ØÆZÝómw)Ÿ£|ö•ÖhÛ\©XP/û¥œXPÏÇD¾í^iÿ*­‘¶y%~æ‹•ÚÆZÜl4žT*…þþ~lÛ¶ Û¶mÃÎ;ç·@í¶uGGG¡ª*¶mÛUU1::ZóëJ¥°{÷î¬e.U¬¬ÄºÏwÜçnG¾ý_©ýËØ°ô* ªñy‹µ¸Þ¥ÄJ­W¥Ö»œXPK1 +%Ôêç¹m‚J¯w½µ €ü± Rm‚R¦a¨¾åŒû˵=·Þzëœïu=lÃrµFºA}îsŸKwtt¤¿þõ¯§zè¡ô>ðô>ðj¯VÙÛtçw¦?÷¹Ïe=^|ñÅmw=ì]×Ó7ÝtSú¡‡Ê»ÊÝÆZÝŶ»Ðçß(Ÿ}¥5â6W"ÔË~)'Ôó11ßv¯¤ÿ•ÖhÛ¼Ò¾ …މJlc-î¶ “ØÏ=ôPú¡‡Jô£Mwtt¤§§§½ijµ­»ÿþôM7Ý”Öu=ýÐC¥ï¾ûîôM7ÝTÑïÝR¬·XÆþýû½}~çwVtWjÝ ÷»víJwttxÛñ¹Ï}.}ÓM7¥÷ïß_ÑýËØ°<* ªñy‹µºÞÅâ@¥Ö«Rë]N,¨¥˜FÅ‹µúy.G›`)Ö»žÚéôü± m‚R¦a¨ Ë÷—s{r¿×õ° ËÕj$ ›xc„_|qN®7wß}wúî»ï.{»kyß|ýë_OßtÓMÞ#_C»ÛXkû ”í.öù×ûg¿Tq›+ j}¿T"Ôã1Ql»WÂÿ¥ÒhÛ¼R¾ ÅŽ‰Jmc-í¶ ×øøxú¦›nJ{ÏMOO/Éwv)>ß|àYËL§Óé~ô£é¯ýë5»Þ=ôМ ÓÓÓÞ ¥Ö»Üu/vÜçûžˆÏä£ýhE÷/cÃÒ«T,¨ÆçY,Ôâz—*µ^å®w%bA-Ä4*M)± V?ÏåhTz½ë¥MNŽ•j”2 ã@õ-gÜ_º®§?ðÌù^×Ã6,W¨‘4d©Õ‰‰ $“Itvvzϵ¶¶¢½½ãããÕ^½EK&“ðù|emw­ï›ÎÎNìÝ»{÷î]²m¬Å}Pl»ÂŸ#|öK¡Q·¹ÜXPû¥ÜXP¯ÇD±í^ ÿ–B#nóJù.:&*µµ¶Ø&h\>Ÿ}}}hooŸwšZmë&“ILLLd-öìÙƒžžžš]oQ©µµ5ësؾ}»·MµGJùÿßÙÙ9绳}ûv¤R©Ší_ƆåQ‰XPϳX¨Õõ.J}Ïåˆa寂Z‰iTšb± V?Ïåh,Åz×K›( *Ñ&(eÆÚ°\q9LLL@×u|ö³Ÿó|­oÃrµÍšj¯ÀR˜žž€9_†æææ¼uüëÅøø8¦§§±mÛ6î?Èï ^Êv×ú¾immÍjäªÄ6ŠçkiÛn ðçߟýRhÔm.7Ôâ1«ÜXPÊ6Öâ÷£Øv¯„ÿK¡·y¥| •ÚÆZÛl4®ÖÖV pOL§§§1<<Œöövﳨն®¸8ßÚÚŠÝ»w#™L¢µµ===hoo¯ÙõÞ¾}»·þ™Ç•ØžJµÊ=¦Š÷ííís.>¦R)ìß¿¿¢í?ƆåQ‰XPϳX¨Õõ.J}Ïåˆa寂Fm5ªb±@\ˆ®µÏs9ÚK±ÞõÒ&ûv¾XP‰6A)ÓÔÃu£•`¹âþRK¥R¸ûî»æ$Qëa–« Ôh²Çc£J¥Rhmm…iš0M===ؽ{wÞÇ©ñðó'ß…•‹Ÿ= ü.¬lüüëßàà z{{1::Š;vìÁ\KvîÜ ŸÏ‡ööv$“IìÚµ«¦O”;;;áóù¼ ÉdÒû½žŽŽbçÎhmmE ¨öêPê10ÔÆ‚ÆÁX°ô50¬,õúy뺎ææfôõõU{UÊRoq¯Ú²Çc£zöÙg³þ@"‘Àðððœl95žBŸ¿¸«‰VÆ‚•‹Ÿ= ü.¬llÔ?qçr"‘@oo/|>_]|v@ 낪ªFWWWµW-/ŸÏ‡¯~õ«èïª€®®®‚%.k™¸HšH$Ð×ׇ@ P§i~õ æ‹÷ÜsOµW-¯F‹cA#Ê ŠUÀ¨6¶ ª‹q`e©çÏ[œ§îÛ·¯Ú«R¶zkU[C÷xÌ—q®×(óéììôjx/d»ë}ßTbë}s?ÿ•ðÙ/ÆJØæÅÄ‚FØ/•ØÆzß+õÿÀb4ú6¯ÔïB¥¶±Þ÷ÛµOŒ ’©³³sz«Öj[77!ÒÕÕ•ÕS ×»½½¦iâÙgŸÅ³Ï>‹={ö ¹¹yIÚ KyLMLLxwY›¦‰¼œØ6ª}•ŒÕø<‹ÅZ\ïRâ@¥Ök©ŸRbA=Ä4*=Ôêç¹m‚J¯7ÛµÓ¨¸åŒûK!‘H ¹¹»wïFoo/z{{Ìöô®‡m–« Ô(2ñ(îôϘ3‘HÔüCóÍ:…d2é›R¶»Þ÷M%¶±÷A±Ï%|ö‹ÑˆÛ\‰XÐû¥ÛXoûÿ¯Ñ¶™ßTtëm?°MP¿FGG±k×®‚ÓÔj[WŒ‹”»ÌÜq‘jm½S©³.¤R)$ lß¾½®âH?vìØ={öä]æJlÕ«JÄ‚j|žÅâ@­®w±8Pê{ÖÊ9V¡XPO1ŠÇ‚Zý<—£M°ëÍ6AmÆ4*n9âþRêééÁ=÷܃¾¾>ï;vì@___]lÃrµMC&÷K=<<ìÝù=44ŸÏ‡;vT{Õ¥½½‰DƒƒƒÞs‰D«ÿ¾í®÷}S‰m¬·}PÊç¿>ûÅh´m®T,h„ýR‰m¬§ýÀÿåi¤mæwaV¥¶±žöÛõ««« ©T CCCÞs‰D‰D"«Dr-¶uER{ppÐ[¦øÞ‰’jµºÞ£££Yû|pp>Ÿ¯¢ë½ëž)‘H ™Lz½`2™wM¯´¶Q½ªT,Xîϳ”8P«ë],Tj½–úø)%ÔCL#W)± ?Ïåj,Åz³MP[1Š[θ¿TDÒ-ó¸çµ•ŽuKe9Û@¤)N§«½K!•Ja×®]H¥Rðù|H&“¨ùñ ö.2577#™L¢¯¯ ÚîzÙ7Û¶mÃÞ½{çŒUU‰m¬å}0ßvûü鳯¤FÜæJÄ‚zÚ/‹õ~LäÛî•ö ’m›Wâw!ß1Q©m¬ÕýÀ6AãÆîÝ»áóù–ôØ]ŠÏ7™L¢¿¿hooÇÄÄDÅ¿wK±Þ‰DýýýhnnÆôô4š››±gϯ¤Q­Å‘|Çýàà`Ö…ÒLÞØ`Þ6j$•ˆÕø<‹ÅZ]ïbq RëUÉõ^l,¨µ˜F…‹µúy.G›`)Ö»ÞÚÀÜXP©6A)Ó0TßrÆýå”û½®‡mX®6P#iØÄ£ ê¢oß¾½n]-$•Jy]r[[[çíŠ[Êv×û¾©Ä6ÖÛ>(åó_ Ÿýb4Ú6W*4Â~©Ä6ÖÓ~àÿò4Ò6ó»Pùm¬§ýÀ6AýJ&“^Yž¥>v—âóË\Êï]¥×;óxÉMäWr½—bÝc¥µêU¥bA5>Ïbq ×»”8P©õª…ã§‘bZ£+%Ôêç¹m‚J¯7Û Ÿ¦¶ƒŠ«—ïd½oÃrµAÃ'‰ˆˆˆˆˆˆˆˆˆˆˆˆhé5ìDDDDDDDDDDDDD´|˜x$""""""""""""¢²1ñHDDDDDDDDDDDDDec⑈ˆˆˆˆˆˆˆˆˆˆˆˆÊÆÄ#•‰G"""""""""""""*DDDDDDDDDDDDDT6&‰ˆˆˆˆˆˆˆˆˆˆˆˆ¨lL<QÙ˜x$""""""""""""¢²1ñHDDDDDDDDDDDDDec⑈ˆˆˆˆˆˆˆˆˆˆˆˆÊÆÄ#•‰Gª:Çq`YVE—gšæ’­¯išp§*ï]Ëû…h¹ú>çÆÆ…ùÕúú-ÄB¿Ï…¦µ, ¶m/èýë5ÔòºÍg¾ïl¾s‹…|Çêgý¨ñTóÚýúY?j|寂¥j#,v]ê1ÔòºUÂR~Ç ÷KýÞ5µ_ÒÔ0b±Xzrr²Ú«Q²©©©´¦iiiiEQÒccce/7§—ò« Ç«òÞµ¼_¨zêíØ¯„ÉÉɼßçùâ ãÂüj}ý¨4+1ä³ïó|qdrr2­(ŠG4M+ùýë5ÔòºQa+õØÏwü:·(õ;θP_ëGó«·ØPík<öëký¨4õÒéÊÄ‚¥j#,V½Æ‚Z^7*O=Ɔ¥°”ßñBÇýR¿w-íöxl †a,ø.¼j ‡Ã°mSSSH§ÓeÑh´Ú«ETwêíØ/‡mÛ0 ÝÝÝy_g\¡•j%År‹#Á`²,#Ncjj –e!W{µ‰òZiÇ~¡ã·œ6ã5šz‹ ÕjÃóاFVoqXºÿå¼N@4«cÕ§†M<:Žƒh4Šp8Œh4:§{«®ë‡ÃÐu¶mC×uï5Ó4‡‡çtÁ‡ÃYË6 #ky¹ÿ¸:}!¢›¹î™Û#þÉ–ÚV,/zÛœùw¾iŠ-¯Ômuº®#‹A’$@$,ËE·W|^ŽãxŸS±’‹™ŸåBç/¦ÐgYì{Xì³LÓœóyÏ·îÅæ­Ôv×*û¥/o¾c!ÇýB·µ”ã¯Ðöæ~Ÿs?ûbq%sÚF‹ ™ï›»þ¥ÌÛh±¡Ð~.ÄþÉ ªÄòr×_ü]nÈ÷\5cA¡8°ã5÷XŸï|qĶm˜¦‰P($ @ÀÛ–…baùñØ/mY•jÿ/t{Ë9öÅg”ïø]H@LŸù97z\È|ß•ØFXЏ ö]©ßýåŠ â¹…Ä†j· ªym€Ç~áyëýØÏÝ–Å^'û‡m„¥m#‹Õh#Tú:A¡Ïz±q sßÌ·/VúùA!l#”¶¬Z½nPh{Ëi#Ôñ_N ”ù+±í ™xtmmmÞN1 ~¿ß{=óCwÈ/y4õîŽqY;]¼î8ÇAww7ü~¿`Äe±ÓF ½»ć¿XbyâN‡Ü¿óMSly¥n«xNQX–Ó4!I"‘HÑí[[›÷^~¿?ᆵ9ŽEQ`AóÓÑÑáÍgšfÖUž‡Åöe&Ó4½ï¨ßïÏz½»»{Îwt¾yTd»kýÒ;örÜ/t[K9þ mo @<ÏŠB)qE|¾€Â±¡Ø¼@cņBû¹Pûj¾XPÍ8 ¦¯T,(å~5cA¡m-õxÍw¬…ãˆx¿ÌéEYÔ¡l#,?û¥/«Ríÿ…no9Ç>0ÿñ[j@|¾¹±¡‘ã°²ÛK2_/å»_Oq!ßsKªym€Çþüóõ}ìg*ç:ØWl#,}¡X,¨F¡’× €ùcA9q@ì›LßH$’õ€ôÔÔ”÷úÔÔÔœuÈü~Ì7)ÛǽïFæwIÔŒÏ|!ó{XÊ{dÊÜw¹Ë…BYcMÌ7o¡ín”ÚÞ<öKSìØ_Èq¿Ðm-åø+¶½ù>ëtºp\iô¸NŽ …æmÄØ0ß~~àæétºh,¨fË›ïØ(7ä{®š± Ð¶š÷ßøFÁc=S¾8"–“oºzˆ+½ÀcáË*·ý¿Ðí-çØ/ôY;·(Ö˜o¹™ë—oºzˆ éôÊn#,U\û®ÔïþrÆ…tza±¡Úm‚j^xì7Þ±Ÿi±× Òi¶–³P,T£Pîu±ÞÅbA9q@¼G&ž”†m„…/+ßsµz ±œ6B¥®Šù–âØ/§ PhþJû ÙãQt—ƒÞ,ñx²,Ã0 ¨ªšÕ¥^Ó4nfW–e8ŽÓ4³þÎì29¯$I^WýbëSêô…¨ªšw¹•X^¾¿ç{®Ümͼãhrr“““s²ú…¶W”<Ü;›2— À»[B|¾¹ŠÍ_ŒmÛs¾Kb9™ë›ï{X± q'‚iš *Áo»¥¶7ýÅ-¯”¿KÝ÷¥nk±ão1Û[J\iÔ¸06dšo??üðÃóÆ ´XPÍ8T6”ò?¿š± Ø¶æ›÷¹çžPüXŸO¡cf!ÇÛÕÁcáËÊ÷÷|ÏUr{Ë9öó)õÜb1±¡Þã°²cÃRÆ…ÌåÅ¿ûõò=·Tq¡® äÃc¿¾ýL‹½N°°œm„RbAµÚå^' ÇÆê`aáËšï¹Z¾†XNÇ~öú.ôØoØÄc<àv#mjjB0P¸hÛ¶WW7ó±Ðƒ‡Šû4³´A(ò‚öbä)EQ …¼Ï~¡ócÛvÁ@Pè{XŽp8Œ¦¦&¯vv¹ÿŒÊ¿–ðد_•øŠ+=ö€Æ cC¦ùös±FcAõ•ó½Ëœw¡Çzæ|óYHãŸm„êà±_¿*uq¥Ø¹ÅbbC½Ç`eÇÆ…ÚW‹×Ä<óá±__{`,XNK ²Ü…ĉÅ …bã@u°P¿*uÝ౿ØýVІL<Ú¶ I’‹Å055…±±1†]×!IÒ¼DQ/³,###…B´p…¾¬¥~‘3?GQs8S,ó²óóÕo.41²,ϹË!s…¾‡‹%柜œD<G,[ðw³Üí®e<öëÇR| ÅŽ7h̸06äšo??ÿüó·‹±`ù•ó½+4o±c}>â„ óN¾b ç[ÛËÇ~ý¨ôw­Ôs‹ÅĆzŽ cãBí«…kùðدïc?Ób¯ŒË©± œåŠ•8 ÅÆê`¡~,Õu€ÇþRìs¡!bÐW±CdYöþ™hšæ & ¸;N|˜ªªfý ÌPZ/ê倢(e9k Óp8 Y–K>r’•$iÎÝ%bÀèh4:§;p)ó¢iZÖÀ«ân¡Ð÷°™ßÑÌ÷$É;Ù™ïί|óæÛn±Ïå®ûõ£Üã/ŸBqeëÖ­ÞsÄßÅbC¡¸»íõæÛÏŠ¢Ì€úõ€ò޹|óÞrË-Þs…Žõùˆï}æwÀ0Œ—le¡:xì×J·rn±ÐØPÏqAü½’Û+5.ˆmªµpm ûõ}ìgZìu þcA½Ä 2± ÜåÎ'*Ñn) Êσm„úQé륶jýØ/§ PhþÜm_챿fAS׉@ Ã0ÐÖÖæ EQ iš—EöûýPUÕ«³+>H$‚p8ìÛ¶½.¯µN’$„Ãa8Ž“5f@­ßï÷öµã8 Ú×¶m£­­Í›7‹åNÓ4hš†`0˜µüRçŸèŠÝÝÝ EQ`Û6€wC¡ïa1@À[®ã8^cXÓ4躎¶¶6Ȳì}Å @`ÞyÅ:[–•µÝõòý.ýú8öò¿ùÌWrUÄö‹ óÍ+Ö»‘bÃ|ûùÃþ06mÚ”7¨ëXPq(ï˜+eÞùŽõB"‘ü~¿7‚$IY㔂m„ê౿2Žýù,äÜb¡±¡^ã‚ØÖ•ÜFX‰qA¬=ņj_˜ýú=ös÷Ób®õ ê-åÇ‚J,73Nˆã½í–B± œ8ðü`±ØF¨ŸØ°Ô× €ú;öËm,DZߔN§Ó‹ûÈkŸÈÚŠ»x½Š.Ë2t]‡mÛÉš˜í>]2·­ƒ.ç:¥Dkš&ü~?Òé´÷/äs*wþ\¶m{]£óÝ…•ï{X ˲à8NÞÏ3w½Å@ÆbºBóæ›¿Ñðد]•>þ í`ùâJ®jÄ…Ìåæ‹ ÅæÍ7½ËÝϥĠ>cA=Å ¼c®VãH>l#TýÚµÔÇo¥ŽÝ¥\6ÛÕ±’âBæz×KlÈ\g zmøJ­W><ö«o±× 2§«§}Qq s½Êþ/¯•S(,6+±MPËÛMT •h¬ªöFÃÃÃèëëCWW:;;±gϤR©¬»°GGGÑÓÓƒžžoš‰‰ ŒŽŽV{õ‰¨ˆ`, "W±XÀ8@ÔøØ& "€±€ˆˆêMÍ$s¥R©¬¿'&&L&³î@jmmE{{;ÆÇÇ«½ºD´ˆ`, "Wf,` Z™Ø& "€±€ˆˆj]ÍŒñxÏ=÷`pp©T ­­­F{{;vìØ˜žž€9¥š››111QpÙgÏžÅSO=…æææ9uŸ‰V’d2‰d2‰'NT{UòZÊ8'Nœ@"‘@kkkIõ݉U"‘ÀSO=…³gÏV{UòZŽ6A¾ù‰V’T*…ññq¼üòËÕ^•yŠââÁbÛ§OŸF"‘àù­x˜žžÆéÓ§«½*y-õùÁË/¿ŒD"íÛ·ÃçóU{s‰ª†çŸ»wïöžK$Ø¿V©ƒžž #•J†††àóù¼Ad‰¨~1ÀX@D®RbãÀÂ9ŽÓ4aš&lÛ®öêÄ6ŒDÄ8@TjbŒÇÌ1föïßææf$“Iôôô ¯¯Ï›n``»víÂÎ;áóùL&100P³ƒ_Qéˆ`, "W)± Ñâ€ßï‡išsžWU###$É›âñxÞå„ÃaD£Q¤Óiï9Çq‡¡ëzÁeÕ¶ ˆ`, "Æ¢zT‰GÀ½#aÇŽ^wèÖÖÖ9Ý }>öíÛç l¹}ûv¢Â8@Dc¹ŠÅ‚FŒŠ¢ ‰x;Žƒ`0ˆ`0ˆ‘‘‘E/7Â0 Äãq¨ª 0M³"Ë&ZJlÀX@DŒDõ¦f€2»Gϧ”iˆ¨>1ÀX@D®RbA#ÅI’¼Ä `Y¢ÑhYËÕu@ kÙªª" ! ß4MȲ Y–õþŽãÀ²,(ŠÂÞ•´`lÀX@DŒDõ¤&Æx$"""""¢ü›ð$IÊ;¦£¦ió–lÜž’MMMðûýhkkCGGÇ455Í) ›ùœišhjj‚®ëhkkƒßïGKK Âápµw'-!&‰ˆˆˆˆˆj€ã80MÓ{ˆqC¡PYËÕ4 †a ­­ ápØKæëa)ضp8ŒX,†t:ÉÉI8޳àÞ—Ñhñxét‘HÑhtÎX“DDDDDDÔ8jªÔ*ÑJeYü~Ös²,—]ž4‰@UU†Ã0¼ä¡¦i…BPeÎ<¢‡¤xM–åE™¹üP(Û¶aÀòï`""""""ZrìñHDDDDDT@SSSÅù¨ªŠt:õÐ4 ÝÝÝyK¥.„ªªˆÅb˜œœÄØØ"‘LÓ„ßï÷ʧæN¯( :::ÐÝÝh4 I’ò&)‹½o&Y–ç”h%"""""¢ÆÁÄ#Q¹ÉÀJ¢mÛ°,+ëwÇq¼irÎ7ÏB”›°“$ ¶mÏy^Ó4Äãñyç³, mmmèèè@GGÚÚÚ¼u·,Ë{Þï÷£¥¥º®{ó655!zó‹Ò®Bww7º»»ç¼_SSÓ‚÷ÕŽŠ$S©z{{Ñßß¡¡! †††pçwbbb¢ÚÛIDDDDD´(Ñh¶mÃ0 ˜¦ Ã0²~·mÛ›&÷ç|óä#–⇡ë:B¡PYë¯i Ã@[[Âá0LÓ¿‡e¦îîn¨ªŠ©©)LMMAUU/Y(~NMM!N{½'3œº®cddétccc0MÓKNŠuÊcÒ0 (Š’·g%ՇДZÕuãããØ»w/:;;±mÛ6À=÷܃ÁÁAìÚµ ßÿþ÷áóùª½½DDDDDD "zJˆ‰ir.$‰fYVV¯@Àíí(IRYë‰D ªª—ü¥[5MC(Ê»Ž"¡‰D¼÷…B°mÿðÿÛ¶199™õšaÐu‘HÄ[¾X¶¢(PUÕKLjšI’`€÷žâw""""""ªOéñ8<<Œ@ €ÎÎάç[[[ñÙÏ~©T ãããÕÞV"""""¢š¥ª*ÒétÖCÓ4twwç-•ºÐeÇb1LNNbll ‘H¦iÂï÷gõ:,Ë‚¢(YIOY–ǽŠ6¹%`UUÍ*“Z¨7%à&EïKQ†–‰G"""""¢úV±R«íííy_½Yn•ˆˆˆˆˆhaDïÁÌñ¶m„Ãá¬çEA(ÂØØÇ™wÙåö´,FôÂë zAQýªHâ±½½£££y_K$0§7$&z#.6!ç8¢ÑhÞq% -S–e¯7bæ²ü~?¶lÙ’µn‚išszA’YnÕ0 hš¶<;•ˆˆˆˆˆˆ–LEÆx èïïtuupŽÉdƒƒƒèì윷G$¹‰¼Üd_4…$IY%HóMä/m*ÆVËÓ8Žƒp8ú¨WZ¶oßîñHDDDDDDùÅãñŠL‰Dæô:”$ ñx¶mömïùbIÂ@ MÓ`Y7 *’”Š¢`rrÒ{M–å¬2«ù’ ùÖ]Q”y¦DDDDDDT*2Æc¿×Ó±³³Ó{,4é8:: UU±mÛ6¨ªšwÜÈÁÁAÜzë­Ø¶múûû‘L&«½‰¨‚ˆ`, "W±XÀ8°0²,CUUïQ QžUUÕ9=#3_[ÈØŽD Á6ŒDÄ8@TO*’x E*•Zô2FGGÑßßžžìÝ»s‚ƒ(å:00€½{÷"™LzcKQýc "€±€ˆ\ÅbãQãc›€ˆÆ"b ª7)µêóùàóùpçwbÇŽy{:çQ×uôõõ¡¯¯€Ûsrzz‰D===ÜÓÓÓãý½gÏï®®jïK"*ãŒDä* -øý~o,Å|D9Ò¦¦&Äãñ¥HTØ& "€±€ˆˆêMEÉdÍÍÍhnn^T÷åd2‰‰‰‰9ÉÉ={öx¿OLL ™L¢³³Ó{®µµííígð ªsŒD0‘«X,hÄ8 IE™3>c®P(IJ¦´"°M@Dc1Õ£Š$‹õf,F$+[[[±{÷n$“I´¶¶¢§§ííí€ééiÈ ÐÜÜŒ‰‰‰eßqDTYŒD0‘«X,hÄ8à8Ž7fb!ù“–eA’¤‚ IÛ¶aÛö¼Ë/eDˉm" ˆˆq€¨UdŒG!™LbhhƒƒƒD"‘XÐü;wî„ÏçC{{;’É$víÚU‘ÀpäÈoˆV²ááaôööâÀÕ^•y-U€ ··ÃÃÃÕÞL¢ªêííÅàà Ž9RíU™×R· z{{«½‰DU511ÞÞ^ÜÿýÕ^•‚–*>|Ø‹…õ¦©©É+ÉjYÚÚÚÐÑѶ¶6„Ãá9%[ÇßïG[[ü~?ZZZ ëº·¬h4šµ ¿ß_íM¤e$þ'>|¸Ú«2¯¥ñ6_,(·TÒæÍ›k®M IlÛÎ;Σ(Ú+ BUU¯¤ßï‡mÛYÓtwwÃqLNNB–eD£QƒA¯g£®ë¢(°, Ðu@ Ú»„–¨^´RÏÞûÞ÷–]Á‰¨ðü€çD¼fÈk†´2ض]°ÊÍÀÀ@EÚéñ888ˆááa àÑGųÏ>‹gŸ}{÷î…ÏçCIË¿ ]]]sÆŒÌwC)IM"ªŒD0‘«X,X¶8àÏyè3?€0+Ï4VÎôáœ×s8Ž˲à÷ûç<Âáðœé-Ë‚eY…B$ ’$!‹Áqœ¬iLÓÄÈȈwr … iš×ëQÓ4/©©( TU“¼$ª&¶ ˆ`, "Æ¢rX–À½yu9T$ñ8::о¾>ôõõÁçóyÏwvvbÏž=H&“3¤Û·oŒg=Ÿ8ÄG¹Ó$ ´¶¶.ËÎ"¢¥Ã8@Dc¹ŠÅ‚e¡œ‡:óÐÈy¦‘s¦×r^ÏCUU¤Óé9x<>gZÃ0æŒÉ˜Û+R$u]G8öŽãx ÊbcJU ÛD0ãQ>†a,húp8ìݼº*’xL&“ó–$v¡zË>ŸD*•à…ÑÑѬ2J===ö¦‚ÏçÃŽ;–egÑÒa "€±€ˆ\¥Ä‚ejÎCžy¨Rži¤œé•œ×+@’¤‚¯gö~̤( 4M«ü~"ª ¶ ˆ`, "Æ¢|JM<ŠÊ:¦i²,ïï¥V‘1[[[‘H$ò&E±X—æ{î¹ýýý¸õÖ[ÑÞÞŽ‰‰ ôõõeu¡À®]»¼d“É$²zYQýb "€±€ˆ\ÅbÁJŠ¢ Âq/™["5³¼jf’R×õ¢IK¢ZÀ6ŒDÄ8@”˲¬¢ã5@ww·wÓ©nÃ4M†H$²dëW‘ÄcWW†††;vì@{{»W^uppíííEinmmž}û¼’¬­­­sºAû|¾¬i¶oßÎÀAÔ@ˆ`, "W±XÐhq@’$ض Ó4ó¾®(JV²PUUH’„p8ŒX,sÆ‚TU²,gMcY‚Á ÷7Q-c›€ˆÆ"b Êä8lÛ.šx4 ¦izÓX–I’¼Xó%Ãá0îºë®²×±"‰Çn÷e‘€Ä8¥*– ,u"ª_ŒD0‘«ØqÞ(q@”¼ñûýy_ÇãYã1J’„x<¿ßÓ4á8NÞò©###èîîFKK dY†eY…BƒÕÞl¢’°M@Dc1ðnVÍ­x“I×u¯«èé@ÑhtÞyLÓ¬Ä#à&ÆÇÇ111áÝuP¬Ä*ÑJÇKš.N{¿+Š‚ÉÉIïÎUY–³N*3§'§²,{w¼f.k¡ëADDDDDD••9”F>™UnæK<Š*7 i Ã@(B4E(‚mÛ0 –eAQo>1d%T,ñ8<<ŒÑÑQ  ¯¯pë­·bÇŽ¬¥LDDDDDTAŽã ¥¥%«'d4…$IY=#…|ÏQíˆF£ó޽hÛ¶×[Q’$8Ž3g‘˜Ô4 ‘HÄK2†B!˜¦ I’022‚¶¶¶¬ù-ËòzH>úè£eoGECCCDgggV‚±§§ÃÃÃǾ}û*µï‰ˆˆˆˆˆV4I’‹Åà÷û¡ªª7ÎÇn$"""""ªM†a@UUD£Q¯w£øiYÖœžˆ™óʲ Çq ª*lÛÎê!™™˜ŒÅb^µI’ IB¡·,Y–½¤¤,Ëèè耦ipÄUW]UÖvV$ñ8<<ŒžžÜsÏ=YÏ `ÇŽعs'‰ë+aÛ¶W6GQ”yKíشõDŒw d—†%"""""ªgâ<Ƕm˜¦ Çq (ŠW¡F'ILÓ„mÛPUš¦addÁ`°"‰ÇU•ØYÉd]]]y_cb]‹åa›šš¼1's_ƒhiiñ–)öÅ|ÛODDDDDT/DF˲`š¦7Ö¢ ÑhÔ;²mº®#@Ó4¯§¤mÛ°, º®#B×uhš†ÉÉɬsÃÌžŽ‚,Ë^‚SôzÏ?ûì³eogE­­­H$y_K&“fDDDDDD”M$ÇA<G:F:ÆÈÈLÓ¬ZòMQÄãqï122˲ ¼,Ã0à8dYöÆÉFaFÖöÇãqض½¨÷#"""""ªâ\N$úD™S˲²Œ¼žˆ"1iEA$ñŠ¢'¤$I^yUÑK²ÔR3ßWô¸T/¿ürÙÛ[‘ÄcWW†††044„T*å=?::Šþþ~´¶¶²Ì*Ñ<Âá0$IB<÷Nú·ÎØØlÛF8ž3Ÿã8^‰žùˆ“ÖùX–åäæ’$ÉëQ)Jð¼‰ÃbLÓ„¦iÐ4-ïüâ.ÞÌíWU¡PhQïGDDDDDT t]‡®ëp¶m{ BI’²Ê¯Šç„`0ˆh4šuŽ$ˆd¤ã8…BÞ¹[)Ät¢7¤ø[’$ÇfN$=ŠdžZ–;‘H'¡…îNÍ×Ã0 y'¶¡PÈ'$À²,˜¦é%Å4â@ÖÝ­âÎÚ܇bìÉÜuYÈ´€{Â-N²Å{G£Ñ¬»r#‘TUõÆ1c•hš–µ­DDDDDDÕ$†«I;1V£gQœ»ˆqEiÕÌbY–á8Ž×»1³Üj)c6ºu>â¦PsÛ¶m+{ÿ,*ñØÚÚŠÖÖV躎‰‰ tuuaûöíèêê*{…ˆˆˆˆˆˆjÊLÌ£i@æÉ™mÏ&q“‚ad''3â„ÓqœyO*ó• Íí(˲—TÓ‹¿…̱ KéE¨ªêœ2§ápÝÝÝYIÍBlÛ†eYeÙ»“W¬‡H”f¾ŸX/‘<=='''œð$"""""ª4Ó4³¶m{c4†Ãa¯2MfùT‘TU]ÑëÐï÷g%…q±óÝØéóùðüóÏ—µìE%}>zzzÐÓÓƒT*…ýû÷#‘H`ppÐ+¯Ê$$5„bã *Jñi ”&'|¹I¸L¢W¤ªª^éÓÜ$\æß™ ÆÜ÷eN+‰ –\rU”Ywg®¯iš°m{ÎòÄ]À𦡭­ º®# -z½‰ˆˆˆˆˆBÜD™Û«PŒY/n= ÷<¦££ªªÂqŒyÓå»Ù4‹yã4f&EÏÈåvíµ×"•J•µŒ²ÇxIHatt‰Dwß}·—„ܱc|>ß²ï """""¢Z'Æ÷È_Qp'ïk¹c$Ú¶=çÎØP(”ub+Æ)Gîx&ň2«±X,ëùp8Œh4ꕊF£^¢1{9Q5Ì—x7TŠs²Ì;ãñ8,ËBww·7Ÿ8§Éwn#žËí Y­ÄãÆqøðá²–Qvâ1WWWÚÛÛÑÙÙ‰©©)$“Iìܹ{öìÉ’ˆˆˆˆˆˆ\‘H~¿~¿±XÌKš¦‰p8 Çqæô.ŒF£ÞÉ©»Q$'E)Ÿp8ì%ü,ËB0œ“,Äqœ9½#£Ñ¨wGn¡é÷$Ú¶í¼e]¢Ñ¨×ÓSUUoÙbzÇq‡ç¼ÑR³m;ëôõõahh;wîÄÎ;ç”Y˜˜ÀîÝ»144„¾¾¾9eY‰ˆˆˆˆˆÈå÷ûÑÔÔ”·Ü„Ãa455!gÍ“ù· ë:ššš ëº7ßï¯ö&-¹îîn†Y–!Iâñ84Mƒ¢(0MÓ+½*Ë2 Àa0Mªª"‹AQȲŒH$â%(ia•x€ÜsÏ=hnnFss3úúú¼Þ088ˆááá9ÏQ~¢äO®ù’¹t]G0D,óîÖ%"""""Z)lÛF4E ÀØØEÁÈȈ—D¦iÐ4ÍÓE¨ªšõ …[T©U¡§§===y_ฎDDDDDD%'¾±X,ëy˲à8NÑ“^&‰ˆˆˆˆˆ\š¦y¥V7±¨ªª—tÌÇ1" pÇt¿‹Ÿ´0‹îñ($ $ LLLd=Ϥ#QéD) ÜÞ†a@Ó´‚ó2éHDDDDDäŠÅbsʤJ’„H$âý­( $IÊêé(°ÄjyÝãqbbýýýH&“Þs===¸çž{ª½MDDDDDD“;Œ¢85M@–Ý¿g†Sô³Ï©*`ÛîCÈ8ßÍ"z=f& Ã@$ñÆlÌ%’Ž@€IG"""""Z1¢Ñ( ÃðJ©Š²©ó‰$£ø]ôŠc>®¶m/éö.ºÇãàà ¦§§Ñ×ׇ½{÷¢«« ÃÃìʎ""""""ªw"ñ(Jþˆ2«óõxIGMÓ ëºw¢MDDDDDÔèÂá0,Ë‚išàG•B’$„B!¯k£'í™;amÛF0Ìz>œq·íñãÇqêÔ©²ÞkQ‰Çd2‰D"  ³³{öìA{{ûœ’«‹‘J¥pë­·"‘HÌympp·Þz+¶mÛ6§Ç%5Æ" ˆÈ5_,X®8‰d?TÕ}D"nÏFYž;MæsªêN—ùú|E,Ë^¹U]׋–YÃÈÈTUEww÷‚N¶‰êÛD0ãͼÄãBɲ EQ²zB6ŠÌ!@ Ú«_Qº®C’$o LQN6 add‘H±X Þ9g(B$ÁÆË~ÿšI<¦R)Ü}÷ÝhooŸóº¸“!·œksssEÆ•$¢êc "€±€ˆ\…bÁJˆš¦Á¶íE4Çb1î]­‚eYðûýsDµŒm" ˆˆq`¥•_òÉìÕhÛ¶÷»,ËÕ^íªÊnC”VššB0„®ëPš¦yCuˆŠ9KQfvM93÷ööæ}~Û¶msž{öÙg .K×u477£¯¯¯âyäÈ ¢³³_>Q½Æèè(8PíUÉk)ã8p½½½èêêBOOOµ7—¨jz{{1==›nº©Ú«’×r´ š››±wïÞjo*QÕLLL`pp¨Ø8í•¶”±àðáÃèííE{{{ÍœÄãñ¬¿#‘"‘HÁirÿÄ f±éˆ111ÇW{UòZêóƒûï¿È{“h¥àùψxÍ× k‰(š¯bfU—•–x=óí“p8Œ@ I’¼j7â†ÔH$’÷†VI’ …²žD"‘(»M°¨ÄckkkEòD"ááaìÛ·¯bËÌ´iÓ&Üu×]5{Q…h¹ˆ:çóÝ4PMK`Ë–-<‘ °wï^$ $‰j¯Êl-öövìÝ»ƒƒƒÕ^•¼–:lÞ¼™m"ÀK¼¯Ôóƒ÷¾÷½5sóQ5ñü€çD¼fÈk†µD `YdY.©WžmÛu›€Ôu½h¹×`0èÝTjEA8F$¦iÞs"9+öÙBªè T¤M°èÄc%ç‰DÍÍÍØ½{wÖóùî8š˜˜˜s'"ïL$ªŒD0‘«X,7A25.¶ ˆ`, "Æ•Æ4MH’Ó4aÛ6Âá0B¡PIÉ3Û¶—¤lèrm·ªªy§"¡ê8 À,ËÐu###PUÑh²,#BQض±±±ªnOY¥V3% ¯^r{{û‚îêéé™3}"‘ÀŽ;¼À ^Ï ‰D]]]ÕÛƒDTŒD0‘«X,` j|lÀX@DŒ+HÀÙ¶ Û¶ašfV9ÐÌòª¼Ò£"á˜9d=åQE¯G˲à÷û‹ÅÐÝÝP(äÛhš¦—X …BhiiÁØØØœ¡:ª©¬Äc*•‚®ëF*•ÊzÍçó¡§§@>Ÿ¯àrZ[[ÑÚÚ:çùÜfOO†‡‡±cÇø|> ÁçóaÇŽÕÞDT&Æ" ˆÈUJ,` jllÀX@DŒ+išÐ4 ŽãxIF˲¼™c<³ Çz-±*änà&5MÃØØÂá0TUõ’™&''k®§ç¢©T »víÂÄÄ„w×H0¦R)$ !‘Hà«_ýjÑäc)°k×.ìܹ>ŸÉdY6ÕÆ" ˆˆq€ˆ\ŒD0ã@#°m–eaddÄ+µ Ìöld–eÁ0 o\ËŽŽ¤ÓinRÕ²,„B!ȲìÛ·ÏØrûöí D Œq€ˆÆ"r寯¢•‡m" ˆˆq Qˆ1EâL×õyÇ9,…eY^éÕzâ8b± Ãà&3Çh”$©äq.kÅ¢ÉdÃÃÃèëë+8–cgg'zzz044TÑ» 2~$5&Æ" ˆˆq€ˆ\ŒD0ã@=‰F£P@Žã@×õ¢ãfŽñ˜;Þ£PoeW-ËB0ÄÈÈÂá°×ó13‰š[^µÖ­ZÌLÉd€[7¹1Íøøxµ·•ˆˆˆˆˆˆˆˆˆˆˆˆªÈ¶mèº˲¸IHI’¼2¢óõ\œ/ñ˜9}-–Í ½Žªª"{ ÓH$2§œj½YTGÑ]9ß ®¹Ä4‰D‚w­`áp’$Á0 Äb1o ÃBdYž·—c=$Ã0 I’—hŒF£0Mñx¼.KÅæ³¨"(z>"¦aÒ‘ˆˆˆˆˆˆˆˆˆˆˆhåˆF£Y‡Ãa/Ñæ8Ž×ë1·Djn’±X U±œZfÂá0"‘º»»aš&4M+Zb¶Þ,*ñ¸}ûvÀððpÑiÅ4b""""""""""""j|Žãd% Ã@$¢(PUÕ+9šK$sŠó•Xu§Ú›ZPww7ÇÁØØxåTEÇF²¨Ä£ÏçCOO†††0:::ït£££BOO|>_µ·•ˆˆˆˆˆˆˆˆˆˆˆˆ–‘H¬Y–Û¶¡iZÖëù’†™ ÆÌ×ó•[½!—3ù8_ÙWÁ²,´µµ!pÇrTUÕ+  … aÛvÔX5Æ# `||ýýýèêêBgg§7žc2™D"‘Àèè(ÚÛÛ100Píí$"""""""""""¢efÛ6Âá0,ËÊJ¾‰„[±2©™åXó%Eâq¹’x–ey=7çã84Mƒ®ëÞ:‹^ŽB<ÏZÿF±èÄ£ÏçÃW¿úU躎ááá9=}>úúúØÛ‘ˆˆˆˆˆˆˆˆˆˆˆh…¥VÇã8s’oùˆÄd.UU½qç{¯å`šfÁ÷ÒuÑh“““ˆD"Ðu=ït–pxÜäâÀÀH$²^ëìì¬ö¶Q•ضí•Zœœ,)Ù6_¯EUU½Ò¥ŽãÌIPŠ•KMQ”¬÷IHI’à8dYÎê YJ²µ‘”•xÌÄD#å’$)oÒQŒ•X¬Dª,ËPU¶m{cEfÎ#ËrÑq+E”O Åp8 I’ i ÀeY^Õ•hÕR¿Áàà ¶mÛVíí$"""""""""""¢%fÆœçæë‰˜Ù[°Øë’$AQ”‚ãŠ|V¥âDDDuʶmøý~D"¯æ½išY¥&ÇA0„ã8hkkà–—¸ë®»H$ª½ DDDDDDDDTà Ãð“““%Ï'’yÅz.¦§a¡dfww7E¦iˆÇãEK²fö€\þoð±8€Œý"è0V™^Ÿe%{{{ç<744„¡¡¡9Ï?ûì³K¹«ˆˆˆBæÝc¶m,!êÏwww€W›^’$ŒŒŒÀï÷pëäA×uضH$¤#eY,Ë*Xú´–¨ªêÝ _¬·åŠuUÎç(ÃÍCÄCe^7\Tâ±µµ}}}ÕÞ5DDD G”pˆD"Ð4 ápŠ¢x5êE¹ qç–®ë‡ÃÉJDÆãqoÙ¡P¨Ú›GDDDDDDDDuÀq†á‰DJžWô2´m{I×1f]ï ƒÜdi ¨Â^«q¢¤l*O9  X\_öÛ,:ñ800PÍÝCDDÔ0,Ë‚¢(^BÑ0 X–I’ ½¿u]G Ȫc/r@À»£ ˜𛈈ˆˆˆˆˆˆh¡ Ãðªm-6‰WJâ1‰,ªÜ*à&%IB €ã8Ð4 ’$¡»»».zg. ÇLÐ4`¦#C^2¸òWº¿—aUµ·YH¥Rؽ{7n½õVlÛ¶ ªªbtttÎtƒƒƒÞ4ýýýH&“Õ^u"ªÆZ©º»»aš&LÓèº]׋ÅÇá8âñ8b±b±TUõ™2TÅÊ´Ö2Æ"J‹ŒDm" ˆˆq ZLÓ„mÛ°m{Q%KKíí¨(Ê‚®aE£QoÌÉÌëc†axÃb±Xµw_í0 vWUà†c^F€£ï>Zö[–5Æ# £¹¹]]]Î{ÀÀÞ½{ .§¿¿ãããøìg? ŸÏ‡D"þþ~ìÙ³]]]ÜÀ1<<Œ´¶¶bppýýýØ·o_Ù;‚ˆªq€VQ.Õ¶m„Ãa¨ª EQ¼r¢á466%7òD©ÖÅÞ-VmŒDŒDm" ˆˆq D™UUUaÛö¢®1‰Äc%¯OÙ¶íU 3Mš¦Áï÷{7ê‹fîÍú+š®»½…÷Ì?­Üâáü».eT=]tÇT*…;wb÷îÝ$“I$ ´··{`zzºèx©T ‰DŸýìgÑÕÕ…ÎÎN  ½½û÷ï÷¦EOOzzzÐÙÙ‰={ö`bbbÞd'ÕÆZ),ËBKK ZZZÐÑÑ`0EQ`Û6¢Ñ($I*{$“I¤R©‚ËJ&“èììD{{{ÖóÛ·o÷昘ð¦Z[[ÑÞÞî%>‰¨~1P#², Žã@×u´´´ ©©Ék ŒŒ  Á²,¨ªŠ¯—€IDATÉÉIhšUU122RV£LÜI¶Ø†a51P<05>¶ ˆ`, "Æjã:ŠëS‘HdÁËPŽãÀqœŠ®›X'Y– … Ë2LÓô†,*™eÍ–­†pxyºî&3zš ü{îïbøÇÌUIýÊjœ_s¾¬·]Tâ1™Lbtt@ÀëÊœO{{;p÷Ýw\^{{;öîÝ‹ÖÖÖÙK¥°ÿ~/ LOO@Vð€ææfLLL\þ‘#G088ˆÁÁÁ²vQ½Foo/8PíU™c©ã8p½½½®öæR1 #«å8Âá0Âá0ü~?º»»  …N§‘N§½òbðlEQ I’×x*·„HZÎWÊ¢··ƒƒƒ8räHµwßËÕ&èíí­ö¦UÕÄÄz{{qÿý÷W{Uò* Êm>|Ø‹…D+™øŸxøðáj¯ÊËq~pÿý÷£···¤i‰Ïx~@Äk†+÷šaî8ŒâzqÍ À¢oŽ—e¹bc-F£Q„ÃaD£Qo½DBTUÕ…Wþ2M7ëVŠa¶í¾÷r”ƒÇH¶ín²iþÇý§nîÓ²¿6;88ˆd2‰M/¤ÊzÛEñ(eíéé):íŽ;°{÷n$‰9þ|FGG188ˆÖÖV’æ)dÓ¦M¸ë®»J~¢F%Ê ÔCƒºÒq¶lÙRt¼Y¢…², –e!‰x¥(·á¦ªªW¾Ò©¡PZfõ š/ñ¸wï^$ $‰jï¾¢Ø& Zâä½^o¹± Ü»–7oÞÌ6àU/Z©çï}ï{çTp"Z‰x~Àó"^3\™× -Ë‚ßïÇÔÔ”÷\4­ÈMñ€{Ík!Ÿ‘®ëy§F£ÞðDù®¡I’Çq– …ܬ›aËX1Ì4ù™g`nú44'«#¢×ë0ìaKåä,ÓqÜÄ¢$¹ËWU`ìûÐý÷=2;´ àÈèõhzòemç¢z<ІˆÏçËz¾§§gÎ*¦)å΂d2‰ÞÞ^ô÷÷£«« _ýêWç¼56ƪ¶m{IÇh4ж¶6´´´âñ8&''½rª…Æk,w,Ç|D‰Õz,µ*0ÀX@DŒDäb, "ÆÊ²m~¿ŽãÀ0 ïùù’ %Ëò‚—cLÓ€¬êbš¦y7üÏ÷^Žã̽mm³½E·?AU—§ÜiÖ6ú?]ýøï"zË0lÛ­†*VÕq×SlFK ºËÜ$&ŒŒ±˜ûþòWí%7¹inR2³ê¬ý_dÜÿ»×—µ‹J<Š»€DÏG¡µµuÎBbšÜ̹&&&°sçNø|>˜¦‰¼#_³Ø²‰¨>0P-°m{N™ ]×á÷ûFÑÑѦ¦&´µµy 3UU¡i¦¦¦Ç!IRVÙ‡JÜ%¶óõt¬ŒD” ˆÛD0ãÀR‡ÃP@º®{C¨Hâq±Ë‡Ã°mÛ»Áß²,ttt@Ó4X–5ï5/UU³_Óu÷¡(n—?ÀͲefØ7#W€ãÌ&ò2s–‹aš3,yxÑzÐÑᮦe¹‰AEqWi!—mèèp×3š)¡úᯠeã9X–»ýýýرcöìÙ“wZ‘ÐÌ-«”H$Š.›ˆêãU›ã8°mÛ»»Ê4MoŒFEQ ë:·Gc ð”¡PÈ«}_µ¤Ÿãx·1)Š‚x<>û\æÝ]u€±€ˆ€Â±€q€he`›€ˆÆ"b¨4Ó4ab±˜—ÐÜëI“““˺.¶m{×ãEªª°mÛ«"¸×Ý$IÂØØØ¼ÃÍItJ’›…qn]QÛÎî8Ãqão»×Ñ22ŒºîN.‹aY³o+Ë3/i4!2pccîPŒbdÙÍ•–z)϶g{-J/=‰tP‡û0r÷“˜œt——¹[êì0—Š2[mÖ¶ãÇ×ॗ6—õ¹.jŒGŸÏ‡¾¾> ¡µµuÞ±‡‡‡144„žžž‚x"‘@2™DggçœzòÍÍÍÞ] ===ÆŽ;àóù044ŸÏ‡;v”µˆiºf‘ã/ ƪљ„hô„Ãa„B!ŒAQoÐjÀ­ƒoš&LÓ\’r©‹Xy÷έP’¨Å º­”H$;:»»qâ·»Úk=c¥ÅÆ¢ÆÆ6ŒDÄ8PiŽã  " A–eȲŒÉÉɪÝH‡!I,ËB(B4õ’~¿¿ðu7Ë¢Q7!ÙÖæfðd9{€D1¿,»Ù½pØ}]’`Û€ Æ›¿ˆàk…Àuw!ðë×Á1Ý‚Î+§¹í~ÈÿMD_ùûÌŸ]^Öþu/ÇiÚL2Óp¯Í«¾G ýZ;b±ËÌ$ú pÛOÌíÞ¨Î$3«Ç†ÃÙã1ŠçLÚ®?ƒÀ?ݼ?æ.ãS·Ü÷âR¡¢¸ É™]‰Ë.Û‚Í›”õ¹.*ñ¸䉉 ìÞ½£££hoo÷î,ROLL ½½½è`í"`ô÷÷Ïy­³³Ó7r``»víòºU'“Éy»U‘Ø4Í v±Xí'ƪÓ4aÛ6dY†a°m‘HdÞÆ¢(^ÏÈŠ7Î,Ëmä«« ës5^Ë@4®xEâãñ¹ËQU<ñþž8z¿Q]c¥ÅÆ¢ÆÆ6ŒDÄ8PiÝÝÝ$)ëz×r%Åâý:::¼ÞŒ†axã8ʲ MÓ¼q"sÇnÔõÙ1 C·Ÿ€dÛ@w·{!¼ØðPÈY–½±UUF  bìÿ¼öÿ6¬×.CÐï^Rs¾÷(gþ œÀGÿæ^®“œ™kn17ÁgüíaXãëùò‡g‡’´þßkPoK!¶=¼þõïû"w5€Ê肘MQæ?)®õ†›€}b1w1“þ?ôàÌ„…jµjfr³–åΉ̖‚ýç>€'Ÿ¬RâÑçóaïÞ½Âðð0‰†††¼×[[[Ñ××W4é¸A¡”é|>öíÛç›íÛ·3pPUÌĦe#în˜ï€(Woü\ÑÛ±Ö1Pµ™¦ Çq¼FeY)Rç]$ç ^½XŽã6”LÓme6D=zÓtbÝlÛ}-Èž^””È×Ð$œØ¶ ȹS°0PZ,` jllÀX@DŒ•bY–÷¨VGÃ0Ì–EIEÛ¶½*d‘H†a`ß¾Û`ÛT5Iš½\¦(3¹ÃÄ!?zåhccî…ð*’9ÄTÝí¬¸Ë•B»ŠäöH—Ûd\LÆ!É2ðßÜÄœª‡Ýkxšç‡?Eð#[€&@½0 ùÆ3×éõtßD’€gKØz1óu_œÉ*Úˆ[ÚÕq¿Ö} ¶}›W²Õ²Ü÷3AR ‡ôͽ³¥bç)I›Iqg›ùlÜåÀÆçËþ¬xúúúÐ×ׇd2‰d2 ÀM:.eídѳ’¨ZLsn‡£Jõ˜s㾸‹cdÄM"Š;ÄïÑhÆÙb-Ë Ð"˜Ô;Æ*—ã8°,Ë«/_‚¢( díå…fôg PÕÙ†Pî ×¢LCnv`ö–¦XÌý9»"îs¹ q»Rƒc, "Æ" ˆÈÅX@DŒ³º»ÝëÉ–e¡££Ã+iºœIGq½-@×uoŒF˲ ë:dYF:öæù—iÙ37Ã盽”ænÇìpbj÷Í°ßø,ëz÷’Xk`"I¸×ÑmÛ]æØXîõôÙý jËcÿW@þ2* fÜäoûÞ†ØC×ÿWz0"‡¡„fÖ%˜½ˆ_lŸ·´ÌΣªPDµØŽ€qÏÓš;¯B$2ÓSóð?A2vg±`6ó9€<óÈQ¨£äB”x–:ÙHTK cq‰GÇq¹ùÇ™ vdÄ=À3c‘˜G<'ÊP‹Äbn·k!Òi7@‹÷Î7—¨á8ŽƒîînÄ‹dÙÃá0t]÷vÆTʘE¶=;B3à¬Àì-Dªš}'€ªº¤™ósˆ†ƒø=S w1ÑÊ`šî%(Ë‚wýK–eD–ù&uÑËQ$ ÃðÊ«j9׳Ä=ûßûÞ§¼|]&/)6S,pÏõ%¼ÿlÖ™NŠˆDŠW”¤™17d­Ÿi™‹÷á°{‰orr3F~pžHB~8çš^©×ìÄÅþ™ëˆ2ÜÏ.üë!пæ­¿@à7ŸCôÞ7ºCX^v?² ¼QËîéYJU6™9Vw_ÎäH5­2Ò*–x$Z L³xÖß²fë-s€eQÙʈ¢§c,¯»´ªÎó&–ÓÒLM¹‹çmÛ –¹ë•™Œï¿¹‚¨^9Žã•eȯ1—iš‡Ã°m¡PÈ+—šùz(*¹|ªš{ðƒîOq;ÕL½w„B³ q‹V¦<R-„®Ï^fzùåq躎x<>÷V……ÃîÏÌܦ¨(F!Ë2$I‚ã8Y×ãlÛ}ˆ_^Çq¯³9NöpB3éeÙMT†Bî$"y–¹.†1ûú¢.½e\LwwßF£2&'eXúl…Bîhî(Þ™!/qý0ƒ¦ÑèÕ¾¨|Ÿºx£û¼†“€¶wqï¥bNoGY.©Rmɘx$ZÃpcifwfr7˜Åb³ƒ°îOÑ¡I×݇F†á>dyvFUu§±¬Ù`+˜ªê¾—øÇ!†€ó†ÃÙ§2¢Bc)½º‰ê‘eYðûýYƒTëºî J-’Žã@×u„B!¯”àÞùe†×óQQ”’ÊNÌINŠ–’ûâüe*5&$Ñ QUOQ€÷½ï5ƒnOÃJ%göú¸ã¸×¬Åï™×²÷z[4…$IˆD"PUÑh---ˆÅbÞµ·`нn­(ÙÉCƒîu6Ñ{G˜É&Êòìe8Qh pŸ3M÷Z}(T¹ëáâú½a¸„ÆÆŠ÷œ,ÊFÞ’§ÀL‚ÑÛŸWȸÔXNõ3?€8Üäaâ‘V]/ýn]Ÿ vcc3ƒËJÙ=%iv€ÙXl6Y‹Í¾.’ˆ€›wWdÆ‘@fƒ"Xîï"¹©(nÒÚÚ²c­¢ÌΓIL#*;JRv&ªg™=ý~?4MC @0D ðz5ŠiEkrr²,g•IÈh4 Û¶K®u/IR©­³OÈr] ¤ªëÀöíÕ^ """"""""ªËr¯G"€e12òFüò—ÿ‘È]Y~w÷L©Ñ™á¿ÄupIr/‡išû¼i¯½6Žú§÷£µõ-¸úêqøý:¾øÅ7ãMoú}ÄãŠ{Nd Ÿ~Ú•AÕ~;»Ë¢iæÏîÞEöÌqƒÁÙñ ÊwÀÉLŠÎ@e±tÀ-{êÌ™UnõÉ'„ã¸+9û¡‘°qã«Õþب‰c ˜[8—ã¸ã3†`0˲à÷û!I‚Á Çñ’ŽŠ¢@’$1¯£›xyäKèîv“‡Ñ(üÝ”{àttx­e¹ 'sç—à|è?ÁžºΛßÀž¦‰$¼|ÕŸ¢»{ö·,7¡'Žã¶6÷˜$i6(ˆqUÝí›ÝâyÀ?ºî>×Ý=û¼»ïLhjr¯6M÷N31¶«XŽè+`ÍîsÇ®ûÇëðŽûßQí¯ -®Ï^R÷Úr(€¢(ÞpDÀlžùd^[wÙáÆ Íï8Âá0Âá0‚Á &''ðû¿ÿ¦¬D¥,ËÞµ¼Ù’@¨çX/\™÷ZÖòïPa¸= õ2—UŠ(ÜNó‘à& m3?+ÅÜâ‰ÇÄ#ÕÜÞŠ™Ïgöú±m7á§(Ù¯e–4ËÓÆÜ‹ü¢—£(}š`Åï™wŒäöVDðÎww‰˜G’²{i]vÙa\~ù9oš—_~Ù+/¹aÃ+xâ ÷Ž‘¯}í-ø¯ÿõeضÇŸüä9D£ÀŸüÉ1LMMazúñ¬÷»îº?D8ÌÄ#-­Ì2¿™¿çÒuÃÃ?‡mKèîtÝÂÐÐ÷á82ÆÆÆ¼»³lÛ†išfî èè˜M®)ŠÀÁïýÞ½˜šr³ø;> ýë>˜ÿv·ýÝvÄ‹ ¶ øÿt+ä€ gõ&د»ÒÕë ªncêÇ?þU8°šæ¾O8<[NY”Z…²ã‘ÏUŒÁÚÝí>lÛmœ…Bîï¢W¤¦¹Ë•$·Q'Ëî4¢¬³ÐÖ6¬›îßBýö£®–ßr##³c» ^oïÖÌòÅgrøúÃÕþºÑˆž‰³Åºƒ°,++éÌ­Ú—)t¯±‰k`Ž3{-«ÑQ # allÌ»vWŒ'7Ü ¬[IfŽA¸c*Z3¿›e,·¥,_0 ·ôª=³ž•L@.!&©fE£nð‰CQW:_#3™hš³µ§Åï€De9»ç£¢ÌŽó–»\Ñ‹I,ËqfÇjŒä©­ ¹3ŸM2hVÜ="–ë8t]ÇÆÿ ËêF8Æ%—ü¿øÅ¿@–eX–…S§~ŒC‡!1qîÜ/aÛîøu¯{Ý^üèG_ÀW¿úäL‚#‚|pfÿ8èéù ZZŽA’€+¯|¡Ú/5¸Ü›Ã0ðøãÓ3 ¤0^xá|ìcÿ ný€1ÄbŸ‚Ï7Ç‘022‚÷¾÷÷pï½kñ 7BQo¹¢·ò·¾õqìÚu÷ØT¿ð^„þðÌw7ŒçßÇ™-á ŽM1ض¢¸Ï‰Øpúô\uÕÄb3ƒd?ì&Msö„@À­/Œ¢|ªø)I³cÀîߦ ˜´-€ñ¿ÝX¦Œ»ÓG£@dæ&1V¬·Ïz`¼ˆ]DnT ^£Hy`%Üy´7²0¿<3¿ ÀXåÆ/ý €õw€v)pù³—WûkBDDDDDDDD †õIÇ@Àæý±±1¯ga¦ÜÊ}†á^+ ÜkÙ²ì–SÕ´Âï-†K2 Ã+¯ª(JVÆRhªE²Ýkr­ç“+]&€Ž™Ÿc3?C3ÿÌcCJ-X)åN¥Œurà&Er±ëVBb¹\L<Ò²sœ¹%ó1M÷ÏÖ©6͹óŠB"€jšûœH*ˆ»:Äø‹â¢¾¸C$sc£ø{6)˜=Mî ²¦™ÝK,[$,r麎¿ø‹ïbË–#ÞºƒAض3gîÇ>ô:ÀOúS´·o@,› î~_üâu£ÏªªŠo|ãó‘ñÌ3oA:-ãmo{¯¼òŠWºòâÅs¸æš‰j ¨ÁdöF7ض Çî»ïi¯a¢ë:þ¿ÿïxè¡Wà8®¸âN¬[÷>LMûØ}ÚpÛm?E[›{,­^}þ8þå_º1<üÇí‡ß_ù÷A<ýôu˜B[öUŠõ÷¯†ã¸¦X,»—s<îÆQžTÌ*bÉîÝorßG”«ž-/‘Yj^ÓÜùÅkb|×X,cº0 °þPÞd öa r ­"tšnôÿê®ŸÜ hß‚ßäm€öq¸eÄ]X: ? D›Ü²ä_Ìû ¸‰G°˜éñø¸û”ù ¿ ì÷ÃÏÞþ³juˆˆˆˆˆˆˆˆ¨âÚ¸¸1Þq´µµp{æëq Ív¢××»»³oÈ)ÜyÆ}ommmˆF£ƒP‘|½s ãuwá0Ð>tIÑ¡š–Œ`î…µÌ$`n™Sn‚Ï÷¢Z¥X‹œ/7A‚{}ÐÅ% ûþ ÀÄ#-»Ì…¦9[~0—(SÌ–IE!ówQU”0ÁÒqÜùDÏEÈ2Ëæ&Ù2«âwQÓZ$-Ýñàf§WU`ëÖÖ­{ÙK²8ððÃç Ë:LÓD0DGGÚÚÚ qèÐ!üä'?,ü†aÀ²,X–MÓ‰Dpðà × Ë2lÛÆW¤qêÔñòËÿÑècxÛÛ¾ EQ (Š7O$Á~°š&yãæ†ææfØ6ðÊ+íÕþPãfŽ{è&öt<óÌa|õ«¢­­mmLSŸßýîȲŒ––&ض;náG>ò&¶;hõ—rå øÍÉ|ù .Ü€^¸ÑïYèOßcÏAȾ#™)¹š½N¢-#J¥ŠÄ`4š}´ €=Û3QeÀþ™›,Tot§÷N(kö.°ØkÂ@ì=yî sùk€y 0R€ò¯T¸—80’ä?€Ûp°õ`Ü8ÿP·Ê& ô~ ƒ{×à6~bîO€ôz ~/¼††ú«> ¯ñd?È›í ]X3ñ÷²ç.«öW‡ˆˆˆˆˆˆˆˆJ :ÝD"³×¬u]‡$IËœZÖlg™Ž÷ÚרXiåTÓ4aÛ6ÆÆÆ …055U¼‡c8ì–ˤëîØB3]6ŰFÖ2$Âæ°QxœCîõ7ufºnÌ^¬„ÅV˜•fcp¯ý…1;d©ë¶Ôed¬Yú· Ê–9î¢ãd—Su¤…ÌøeYîk¢Þtf)Tq§‡ ÍŽÇ‹¹É†în÷gf¢S”GcBæeÅ]ŽXOY KÇ+ªiÞýîï#{º»£ƒÏ÷<Žý¢ÑoÁq¨ªŠP(Çq I‰íøò—¿Yî½÷TUõêc‹DŠø§!~^sÍ)\uÕVlÙò<>õ©[N¿jÆ’¡Œÿ@~¿¦D¥¿¿ ù—€¢œ¬ö×€j”PQfëöÿÏÞÝÇ·UÞ÷ÿ%„ÜÇŽB¸5ªØÜ*ÜÌÐÒ¹$´ƒB'»[ï’ïyëÖ†­Þ¤u?²~ׯµº´[;+l¡7ëp´Ñ–µàÕê ´¸Z”B Á§ J€ñ‰ø÷ÇÑu$ùÞ–lIöûùxøa[:çè:çè|téúœëº¬ì¹R-+ûz1×”ßïT^¢QçN©h4AggGŽÌÂçÛJ"a!Þxæ«ëE®¾ú#œ{nº'²×ëÅãñðg¿ü%§G"ÎF~?ðƒðíoS_¿Ë:ËZާf9±¸3Qµ=Ä'u ¾á€4ü xO‚–;£©ò‰YàuòƒæXˆí€øsÐs:·z"õtŽOgTàÛ¼'õ|·ã_å<–5G­)²ôUAgµ†¥`½¡e€š¾—zÞL*qVèëNB3ï%©eæ@â ð§z‡oûPw&Ø/¥‹ðhrËOé-ô[NDDDDDDDDFH8‰ÃPÈù±m›††âñø¨½ýþt¿| GÓIœ¶iŸo„±Aãq§ÑÐ f’¶í<æ÷;=Ìðaù¾± 9šo^Ì`‚£/·•ô0§Qœv¹Ð׊'‡u3·aò(±T9—e<îaèäæõ.UâQ&…&ÕĽXÌIvwg'1b1gÛvþ6ãS›dæp§Nb"ÝÛÐïO'H,ËYßëM'1L..M'3ƒA'¸&R½•Lb%óN‘L™Ã*x<'Ô‡×{93Gßï'‰DƒÝD£ÎîÙóoÔÔl§½½{ÈãäñÀ]wÝÅ‚/±{÷n¾úÕñxÇ3ä]*~¿ŸŠŠ“8xð(7ÝH•18ì-~¿¿ßOKK îr«V=LîÑM¦3ä°Þ¸½=„‹DÒ‰~g'±pûíÇ8zô¼ï}Ý<ñD=±ØRÀô~Œqå•÷bÛAÞõ®/ðÌ3+YÒûeOöñîc}üÑ}à;÷5¶þ÷rÀyÏÎÿ«¿‚+®pËöNÀÿòË|ä#Ëyè¡tEÉüD£C×NZZREˆ€w¥3ĨuxßÿÕà3I­@ø;‹{¾óÝÁ‹ úlêÿT/Cç€+À.X×fu×ïIðþé€'ÜLfßÖ»ÁnBÔçϯp*BAhè€Ä>§ÈÞ2ð÷ÁÑ#G§þ&""""""""c’H¤ÛêLÒÑLÕeÛ6[·nÍê2œîûêêœôQ–ÑhÔí<)[i¦Ñ4º··;uuNýɀhpw‹oã šÙÌ7™s?ŽÖãq “Ð â´Öá4¯oÀkÇSÛN`Ý¡˜fþîÔ¶ý8óWB:ÁêOý=E‰G µ*“ÂÄ3Qm4šN8é^U±˜ó¿þÔ$£Ñì¹3{Xµ´8ëÍšå,×Ô”Ý ËôF„ôÿæ1¯×Y·¡~ð§ëOg'$Q÷µlÛ&‰‡Ss;:=Á¹Ëã­·vaY/ÇI$øý~<±XÌ ö™Ï Çã•+OâÑG¿Å±c?p‡Lîî¯×ËE᣽‰`*H—t4ÚÛÛñz½455¹Û}íµs ý‘1מe¥'£ž5Ëê4sžwîœr®cÇù¿§Ç©¤˜¡‰‰Ñh‚ÿú¯'ø¯ÿúöî½wÀÐÎûmï®F, îºë³46–ñµ‹à³7<Æñ%—9ÛÙ³Üí5(ÏH:MMM<ö³ÅîS–åĈh”a+?n¢®iø/O<7eœå¥Jýsœ$^øŽ€ÿôÔ2™¹zÐu†W5“=‡q*L©í?ûeXGÁ»”A‰Æ¼7¤z§®J½ž©ß­Hýï…øÓàWê8ü¡“ ýNÜô {÷žŽˆˆˆˆˆˆˆˆ“ÓkiqÚÀ¶¸(>Ÿ–––Ñ“Ž©á=‰Œ!¾§QmÖ,çgÀð_–eÇ ‡Ã‘“Žàl˲œ^ ííÙs“™ù†KrÖÛ€Vœ„™i ¦þ_†ÓÆ6ɲÔTJãæÃé€ÐŸú½"µqÆ>Ôéd%ÿ¼8ÇÎ ÅL•7’Ú×0NÂs ¨Ç£LHæüi>_:aÑÞîþñ¯âóAm­H#‘ˆ;6¶eYøý~÷.3\)ØX–‡²2g.ÇX,F  FÝ^†‰DbÔîî>¼ç=oÑÞÞBuuõ¨]ÖÍóc¹“eðk9Ûíï‡õëŸ)Ø{G¦že¥¯W3ì°é= :×­Ïç\C™ |3¼qz¾Ô?ýéýÌ›w*±Xuuu,]z€ÖÖë°íwð¹Ïý ¶};^/¼š<Ì{~Їæ•C§â÷ÃW”sÅ÷}™ uNÒÿƒBí—Óe †î‰ëóúHÜí|NÆ? Þ¦®ÿ}à‰{ÒîæÖ$ý€b6x¼éáTãñg79Ÿ»ž(黃êÀ²q*9C+è|ŽºbC¤‡]˜ÀK´üøÂŒ©còÖ­©×K ¡‹A¢ÇYÕ>ÍIxúý«MË“œc÷õ¯ŸË‡?¬Ä£ˆˆˆˆˆˆˆH1 ‡öÓng˜é¾F^Õeæ8‹FFapÖÍßfØSœ7±XŒx<îÎãè2ÃÚvÆÜF)™Ê(f|^ð¿§G^f;X7N{WdÀ !Æ×Sq8^F½áLÛhO•ÓÂi‡„t›àpÍüùêé8α'Aj‘­}¢;%eDfxÓó»Õ¦°MïŦ¦ô¼°>_zŽÅXÌùmzR›žfXUÓ³Ú —jòio¤0½3™±©M92óæñÌüœÙ¦Ó ÑCCÃ?ß‚Çãq{9F"ZZZƒ¬^½šx<ŽmÛnRÑÌ¿ÃñãÎ- &AiY–;GÏç#‹>ö5N¢ÅY÷ŒÔ¾z±í¡oðûý£nOÄ$Á¹ÎLFHÏW;‰?“g¯>úÑ×Ü~ûË\ý{ù£?ú GŽ<€ÇãaÛ¶ûö=œ9ÿ¡PˆHdY*‰é'™¬à£}„6õ3{Ω\5ç7ÄO\—u}zw¤n^ø(pìG©ƒØ@çAäUð> <å<øðCœÊ‰¹lL¥¤ÛYx¾±ï§¹éaà뺗—ð7ü.ÃW†âÁ©@äPy „Rû` ÿÚ&æx½©ò& y8ÉŽ°oλ¹gÞb6ÜZÎw<ÍøW_ýNžÛó,Kùøìg×sË-¿ü;ðþ‰TDDDDDDDDòÆŒ ¤ÛÎmÛ¦®®ŽxMMMîÿ®º:çul;=Ÿš7׬NZð†N&I'éêH·“%R¿½Œ¯Í.ÓXçxËvL8Õ>Gg¨SSv+õZÔ~šÁǘ?΋ÌrN%eX–å “ÚÙéÄÛvþ¶m'Vuvf/ßÝÆÑLvkzT™ÞEf]:ñ8\Ïm“$‹P·+x"‘p‡$µ¬µµ ضíÏx<îþž£ÑYÞëõ‰DðûýƒAjSÙÖP(„mÛ$RAÙô†ôù|nbÒãñH$FïŠNzÆô¾úF\v(f¼í¡Ï£5øÃB¦s3€ÏçTJêêÒ×L žÑ0ó9|ËœwÞÛ|à/±ÿ·Y¿>ÌI'ýš·ÞZÀ]w}¯×™wÔé\Á|øSøÎ} o´‚A|>/¿üC¾ð…#\{íi¼ï£×sÓM§³zµ‚AÀï#ÐtÄïðîÊÞ´§ë¡ù 6ã»{Ÿ€å¾ ÞÏ8e¶¿žÏà|pf¾Í8‰»ÔDÏ>/xžJ?mö=ó5óƺ|à} ¬3ÿHùø O%?sœ¾ŽÍܲµµµlݺ•ºº:¾òɯð™øgøœçsÜt“ŸK_ïá¾W΢¡á gŸýKžyæ%ºœC}ßÅ»ÔÇšOVsÚiûyy(¨ˆˆˆˆˆˆˆˆä*u:)fæõlÛvÛ¥»»»·óÖÖ:½ ¶ûýéa͆`Ú·=ù{¿Ç¿_{-·ÞJ–Ùphþ·,§‘/_mÍÞÁÅVæ\ŠqÒC°zqÚÿRÓYCjÝñ,8âþd%4-œ¶ÍXêw˜tÒqŒS2•*%HßQ[ëüniqbˆéÔÓ㟺º:÷Žºº:¼^/‰DÛ¶ñûýÄãñ¬ídÞéá÷ûioow“‹‘H„D"AKK ápØMú™D£ßïw{NŽ—Ù·‘˜óÓÐÐà÷š>§‡Õ«W» ›aa¥´™æ÷p{»“Ô3=ŽÇrÓQæóñxœh4ÊîÝA¾úU?Á E("‘¸œòù/²þüOòÁ»î ¥¥…¯|åQþêði\ü‰4-®VAªço,vŸüd÷Þ{+VÀÞ½éa”iÀ©tƒ†xBHü 8T§–‰á|07á|ÛÎzžÔ(þßtóþ)ð:ƒ{qî„J ¿ÙC:óF†a{<â¼®ÿOÈ©‡ …BCÞ`âO,# ‰D…B„ÃašššXõ«8gÙ9´´´PWWG p·ãõzÝ!/ÚÛÛYuò*ølMçÚøñQˆþåR¼^'E" 5y·«:::8pà@Þ‘""""""""’‹†§/sÚ#çq§Á½½½}pû’iÔ7ó'uvŽØànYVj*1¨««s™ï|öY.Ú·/=Úe«áÿëN߈Ÿ¹Í|Ægð&°ÉTŽÁ´â!Ý#Ò Åê!Ý#r¸M“ÝWÇl?sÿ¤¦Ó˜8ä:Ô¦cU0˜}ÑûýNܱ¬ô<‰™ü~'0Ùù¦×ÕÀeþ?\¢Ä4Îû|><;ä©é]‹Åèîîv—Åb„B!¢Ñ¨;„ªé©eƒMMMn2Ò²,ššš°m;+Qhzšß&)iz9z<‚Á ›Ü¸N.C¢š¤ª™wÒ$AC¡ñxœX,æ&A­TÿûÌ˲¨««s'ŽÅbX–E8VïÇ—H8ó9ßÙ9¸GãHÌÝL€›DƒÜrËÙ|ÿû6/wtð§—]‡&ñ0|àwñ_ËCÏìćËO}šy/?=çÿÁÉ ðÛ  šÚýÐ žG0ø/Ï|Øê#}gO»)‡sƒßñZ𛂜ʃ…3·¢‡ôP™wAµƒwEêï¡î àL¢œ‘l42‡—Í4(7èÃ[˲ܡ–Mïh“DÌìuí ïìÌ›yš¡Í ΰ©^÷:¯‹:7Kº»»ÝÚ{>»ÿg<Üž€Ø¥ÙûiÂ[ðC¹½EDDDDDDD$êêœv÷öötVfxggçУݙB+V8 ?ôûZ–ÅêÕ«Ý6§­[·ÒÞÞŽ×ã…\tÆ?Á¤{ë}1átˆâ´­µ6àÉ1iÚ Á™r)5L-1ÒÌð¬Aœ$eæ\’…h&ÏgË"¦Äã4fÛN÷ì@ÀIšñ¡c1'Ó#Ѳҽ¥:;ç"gÝÌžÁ ³­+†nˆ÷zÓ Û%)âõâ&Ñ¢Ñ(‰DÂmØ7 òMMMnÂÑëõÒÙÙÉŠ+X½z5>Ÿ˲ÜáRM" ‘H¸ 8Ã$ Í¥Ÿ7Û‡ÁCŸú|¾¬Éu®7¶sc»û‹Åhjj"šš”ÏìGfL3%@mm­{7J p·UWWGOOuuuî~™»XL/Ê@ @8¦¼¼<ï0™lfÞfËr®½pعN2çv+“”ÇãnâÑãñÐìdŬ,ý×¥Ø6\rÉ-Ù¾óËËñ–Àºôrhïç.ÞÇÍçý¢à³½Ì;zs®›ƒ· Ø…“Pôƒïýàé,ýl/é9C¸èÃ^6&‰h*QœÊÀ ÄQ;器 L>ZÜçssyý®>ëjæ3p®Usì"‘ííí444ÐÙÙI4u‡Xv¶åÃëõÒÞÞN]]{³@"‘pohooÏJ"š‰ÁÍ\®ñxp±˜‡¿øÞ8xã@.\ÈŽßÝwÁºà*¾ZÁ??.$kŒuoÐ)+þÔg}¸™ïævŸš4Wbf²q¼wͺÎðÊ–å\?¦W±eY;¶€o~ón‚Á Ñh”{®¾‡/®þbÖÍ ---|>ÝÝݬX±‚P(D0tãSæü®Á`ÐIÆHó²‚smš,|4ñøGz‘)`YÎÔf~¿3º ‰D°,‹îîîì¶£pØiÌ7sÒ0fFÞ n{ù ²ç$ȇ“¸3½Mâ.Õ©‰ Ùs+ާ÷b4õúùN>äÉ(Wf;cç$¿î §Äã4buuNC¾‚1ËžóÍüöûÓóž™›$Ì0©fÝ¡Œµû³mÛnï*3t¨Ï磳³“††,ËrßM …BîШfBÀÖpçKËœëÌ$3™9GjÜ÷Òs`#Û¶±m›Õ«W»s>644¸eðù|n‚/ÒÞÞîî9‘H„@ àöšôûý,[¶ÌM\˜ž‰™afM’q 3¬£Iˆîœ–™sFƒAÞùÎwæçM'9³,çº5w8ÓÓ¸½}pOáA7/™‹>Uá0Iígÿìϸpî\<È{ÊÊ8©âwzS kðR®nñÃõ!HxœúyB½ø(4€ßËÆ¶ôºÄu@ªð½CïÏ ø!u§ÔðÇ`<72dn?L÷’ŽÇãîuc®ys½dö’ŽÅÒË›k-ó¯×ËÇ?þA·‡¡ÇãaWt—{S„¹ö2of­'âPqÆ“»7½ÐÀƒ•ÿ—‘éà /""""""S+vÚ¸B¡ô ù¦£J$aëÖ­Ùß×L¢¡ SL»µ™~ÌL6ât`céµè!»mÏ4ƒÅI' @˜t2Âà„_$õZ™IÌB¶]©ÝlR)ñX‚2‡_ŒÅœ;"êRÝ·nœ4i8ÂÌžF™Ý¹Ç;¶² jÇóÐçó¹ÉF“Hlhh ®®Îmôèîîv‘f®EÜ0?Þ!M›ššÆµ¼±bÅ w^5ÓÛ²®®Î¦ÔtKO$D"·—e]3›™oÒ j¼)Oww·›,1û¹uëV÷C `Æ|4'"ul2›;y°I>¥†¢uÅãxS mÓnÛî›áÌ3ϵǕL3 r<žÁLíãA¼öÜÔÞt7d#Mw‡L¹ge=ûö^Ä/Žþ€ïœ±’²Ceœ|ÎÉÌþý«¸z‡æz3z&H”ùq*>8ýŸNç]KÞåÞÍŒqð„<£&ꇔ1LêxeΡèìº3±I0ÖÖÖºwn™9LmÛv“íæ'dÝÕe…fHÕá˜ë# eõ`(4žn¨2}¤æ")z¦Êa§~Ž$xýóŸá;ϼΖþÔ]^FMMM¡K)"""""2#448múííévûh4J8Æçó¥Gè3m¿à4&65 ™tÌL6ÆãqB¡Ð£ñ )ÁÄp;p¾sš¿Áé NÂÑÇCzþÅḆ(SB‰Ç"gæbôz›¼^'ïNœ …œß™='j´œ‚IºÅãq7Éfð#‘ˆÛ³/ ºsɵ´´dõŠÇãÄb1ÚÛÛÝÞY¦Ÿ™- e%æòÉð††ÚÛÛ‰F£nïD“ 5å ‡ÃnâÑï÷ã÷ûÝ^ŽÛ¾þu,¯×M:˜„#Ñ($4Ù6ÿû'„¯3£ïv"7Î*W  ÐÞžÞï̱6þþtâǶÉ63…BÙýòãqçÊãq~g$n/¹ä%§˜éÙhw<‹õØ+Ä} ~O‚¦«Ç×þ5 5Gjt/Ô68dêš0çî_ïæËßš•þ.å?LÇËÜ\q3M¾—£åo–ý GeÁ78Øð(ƒ†,$u÷Ò"ÿ"®H\‘®tH7ZODˆ“3&¹h®?3,°™Ñ0sžZ–å&3‡6§¢e†o6Ï”,SLd8«q®«Ñæôö&ùÃ~Á27M˜! -ËâÜ]çR¹³’—_~™}ØGÅ+xsÉ›üìÐϰ<§ï=E‹ñÀöðÎñ`½e±xQ%÷üê#<´l'ÇUð‡ÿ€ù%gñ‡XO Wâr÷>÷´’¹°IQd“þ½5—ŠˆˆˆˆÈt‹9íû–å$}‰(Éëø—‡"‰8íèOº‡‘Çã4úÃ=‹LÂÑëõFéììt§û³#ŽR6.·f&53Û&'{xU)8%‹P"áæ®Ü9Ý¢ÑtÇ'sƒC¦\sHfPóp‡ÜnÞæo3¤hCC>Ÿ˲غu«ÛÉï÷‰D Ah†5ôûýø|¾¬!3‡:)@šòÅãq<;Ñn"‘p‡U4ûbñxÜ_ñÏ=—'Þÿ~ÎøÖ·X1k–[^ǵµl¸òJ½ñíÛ9xð +ZZÒó*ÆãZçêÔÏ i&Ùçñp£×˳ÇgdÓôT·g£»ßÁ`údÕýÔ|ð˜‰7‡2ÁŸ2€6`¬‡3%ÑqœØÃ§à»õøß!sNwðòC4Ýð¬OõVõÝ–½~êÜ[à&ç­º:±~üÜâ½…³/9›Ó’§qË-·°ôÿ-`góç·[ÞN#è8’#ƒ†`g~.»Cþ†#ᬡ‘3o*ˆD"tvvº½¥-Ë"‘HÐÞÞî&£Ñ(µµµøý~B¡;&½‰G™†JFŠLŠ0NR¡§=ÍsØñ¸óQ”ê\m;?æ#È\Öfó·¹9Ó²ÀN÷ç ˆý8ÏYÎëM NüüçwsÞyλwïæÊ+{è{|9'=¾œO.?ÎÁ7gñXù ^<ã(oÏ›ý»ñ®{•ÎÙýÌ=0—3Î9¿üï Ž?ÎI‹NrÊ3Ëf^ïE°Ê9cÁf/éå…×çðæ5³Ü^À[çíbçã7ÐÝ·”ÿ´µ½›9sæ0ï¤yœ·÷²Ÿ=³WR}¼šïî>Äy|Š pß…Ÿâó;>@‚2b\Àf,z¸€pG¹” 8Ìïsð"ˆ`ÄÃ}ìâ­<ÏÿwüN{;‰5ëT½u6»¯™ÍKodÛì·°ß®ä{³ë¹çízl<<2ë+›O{Å"þß[?äÒK/¡¿?Ìþç­ø«_&x¼ïêØ7oï>~Ïç´«[–3k0ú`©ßiÓ3M`;ëÉUIîûú}|üâóÖcoQ»¦–@( ðàIaš =ÜiæÍ’™= cä/ñ(’A‰Ç3x‘HúÃ&K÷fôùœçƒÁtÆñƒjdv»6ÿ›áCMÏ"Ó뜣IÄb17™ …Ü!=ÝĈeeÍKh‹™Él3_pžÔð¾³s'7~ä#n©m_ÿ:M^/çZ5Ürê©ìýÇ$‘H 9÷ÿ—eÁ_ÿµsß~›¿L/kÊú췾Ų3ÎpË;û¤“hÿ½ßKï‹Ï—Ë6s~½L~ <O:Q9Ò8¸£Ý¢ÞZS£çC:HvrÁÍ$:§mCìë¯AóbKÖãyó(Öñe$]‚ï!غ?µ¯†àÕƒ†8øÛƒ<üðüÚö*_{ükÔï®çŒ3ÎàÅ/rÇ;¸ âæÝ;oüÚ‡¼9!³ç>ØÄ’P(ä^Ÿ±X ¯×‹ßï'‘HàóùÜž‡>ŸÏÝŽ™ÇÔ QìKU®L/j³‡L¯ÅÌ›Ld‘‚°R?-¤{®‰D"ôzÿãqçc©¡!ý¤ƒæcÌë…o~ó(sæÌáСC|êSÏóéO_ @}ý=$ ðü¡r÷õ.=åV-+f?Ä…çŸÎ‹oÎæàoñëí‹8²dk{þ‹w,èå·GËyúôש«;ÈW¿ZÁî¥Ý|좟óÅ_×Ãɸl¾ÿ>ÏIx<7rãß¾Dbû<|«/+ÃçƒæTƒ† §çœ‘È•´\±OúÍ[Jb8u?Ùs—t’}7ï,œ»xGû¸²2~›á‡ÌMO¦ã¿ŸtRÓ“znàg»Yߟú;óùxªlñÔ2ãý.a¶üC<žÀ¹¹i¬ÕR›ì¹\ÌÜ.^F>V¦‘ÄìS Ëdbof iX„tìμyÃÈ|,óÆ×.ð}$uƒ‡n¸4ϱÒYÏãI7vYXÏ/Kƒj€Î+ô¡™4æóÒ7Hšþà4Ï™û›M¢/L:g>OÍç²ù8y"p¦¿2Õ ý]Ì$ ÍçÿÀû¨ÛÛ¡¶6ûïÌ>¦M8O—Ë”Á0¯a’ˆ¦Îa~›&Ó$éõf Œ¤ë&ñøë…>]Åo`v–«W;Ç7„ß ^Ä#^ÈjÀóÍt¶´¤G¥»Ë†@È©_¯Æ©ïn…ã/'ùp’9×Ìáù»ŸÇôð®Eï¢âå >ÿ‘Ï;uäpjy3tjz_љڞáÅù~#ýA$ÏJ.ñØÜÜLkk+}}}¬Y³†ÆÆF*++ ]¬11Á>³7£m;y,Hwrª£šw„á¸LpÊLšÞ&I™XÌLüÕÖÖâóùèéé4ôf,£®®¿ßO pç_Ì\n`ã"‘ Ü¡x笹æî»ï>>õ©OÑÚÚÊ›ov‡2 ‡Ãü¶¾ž¿ÿ}n¼ôR–=ÿ<Ç'üoÐÞÞN?ÄãSßÖ?¾p!óàS÷Ü3(é×·gso¸ùóçC Àé™èz<°råˆÉ¾‹>ö±¬ÿËÐ’ÙJ™@”)5©q Aöøã[qÞ«S7Ô:µ¹…ìón!þœ…g®—H+X,'Äß;£qz?ü!éÊHª‡Ô¾íû8åžSØ¿h?_;çk|¼ëãT¯æná¥/±ìÏ–±öáµ,¸~ŸôÒéUu/¿i”€&éozšk³®®ÎíœH$ܤbSS“{“‚~ØÜ¤àõzÝaŒ3—JfüغÕn¨e5$ª gÊê÷ÚðþÅëTÊ{p>Ôÿ< ßþ#8¶›AF™2ñmç·ïcéj3ĺI‚ó…¶öÝðvÿÛüÑÇfÓñØq~þ›yîvÎ8c7Üð?¼–ùórìØð£]È»^zžãgð“•÷ðÞ]Ÿàø]4áçfÞp·±ûœÝ<þ音uþI¼}Æó¼Õ±?òÏ,]@÷Ònöœ´‡yÍã=ŸËg.ÚÇ#§?Â_ÿ쯕Ì#ô_dõ/~ „ÙsÆž=ýYüïy<òò‚-ÿÈç“ç~ö8çMð7K9^_OÕ3?amÙµ,Úýç¼xîu\ºóO„¹ÿó-ÎÍR‘W†B]|&ï¼à,þ¬¥…pøÜ8ÂéÿôOøvìà›Tñ?Ÿû,A¯bq.ñ-â ›8zÝuülÎVýû¿³:ñKü~?víõ,Z´ˆ“–/çðÖ.Þ./gßö#üůþ‡Sþïç9~óí¯óº±_¤Êw8M¿ á'€§¡© "—ƒýHv~5ð1g½ønhÔ>’}zÛ¯„ȈoƒÐ| "ß°ÌíP{Wêïz¨mÍ~>¸<pÖóM©å=ôc㌰Ò~éa¢ý‹‰? Á¥¨èÃîoË=µ÷8§¢;‘Gz`úuÌ'ºr!ö.ç­f­~’Dç⬲X'Îg÷î«(e¥ÜN "ù£XPùoÿÆ¥ßù}}}œ?{6÷]~9vj.¶`0Èó¿÷{Üvî¹ìÙ³‡óÏ?ŸçŸžÙ?þ1±XŒ@ €eYø3kæÓx¢];eTëׯgË–-….Æ„L4 ¹ßæîyÓ8ç'=t¢©@t’nðlën"'n!±ðtâ;à]›!x=xÿ4µÔ]ø{þzGŽá3p‡1>ð«ìîÝͦ‹6qÎ9çpê©§Ry¢’“þø$*oE(sHaÓ›ÙÌjz%†ÃaÚÛÛihh  ÑÐЀßïw{›²Y–ESS“Ûs1‰¸ÃG£Q·§³LtttÐØØXè¢LHÞë™_À™«áåŒø !8ÜäTæ8ß>ïŒÂ7bÐo(Õ’ŽÓzê q3Ø×@âë`? ¡OBÝ6g“Á+!ºËi¸6üÀi5I¾ÓQɹž×¸å=òÄCµ\wôLÎ]² Ï1÷ø þ”-¼ÄKü˜àc|ÿ€;>}õ§ùÛ 80ëyŽ-{‰U/̼·jø¯¯¬¦§¿‡Å‹óÃþú«êiýQ+Ÿóý~òÀó‘[>ÏîŸìæðµ‡¹èƒ×NƒÃKNcÉ¡Whoo§¶¶ÖMù§bÑŸýííí¬[·ŽM›6põý÷ÓÛÛËæp²çdž¼|%ÞPˆX,F0¤ßïgÙ¬Y<Åœ½h¿øàÝÒ}{öpɇ>ÄI}}ƒç0†ì¹Ž;;³¿æ9¿ßÉÒºç8u«iæ<æñ+Ò£€S‰[½ÚÙFû8'ŸÈìZ:EryɆ†ŸüdEIÎñ˜×:zÈ Cdã\Ëaœ Óô¶8Âp¤ë[qB¤{.š×Lͱ ¤“›Cm? Ö`-L?4°7Ü †»côA´Ëù×ܵŸHà$¦z ð°N@b/ø®Ïh€;ñ‡õ2ïÂ…Ò½© ¿B·Aí§ÿûÛaVmvñCõ`Ÿ€ø“Nƒ–÷Õ=ÄKà¤ÔsæÐt[á­À}â?ÞMâµ2¼åGñzϬ üµç;̇àüG‰þøMȸ)ßóXgœ‰õ³ÔHØG¿Jl×¥Ðó2¾¹ÏáYy&þO~Šøi¿BÄBp˜ ¼Þ므Ï|ë1àø}ƒ_}k;'úN0÷ä“©x{ Þ_Ç Sé{̪ùì>Où³Ûñ¦NâÑÓ¯ãÙ?ÿ GÏˮΛëÉ ÿ9ðùÌkß\×–•^Æ4}fÌ„Tâñ¸Û‰ÄüvÎÓÎkn‡ì6âñ27ÛYÃ(¤}å+_á(ôᘼ~?ÈdFÛˆâÞhGØfÃý€ÏãÜ„çð_ì ºý<ô|ónn^1‹ž?ÈÅG/fÞ¼y«:ƲÈ2çû‚Ák÷½Æž÷`YVÖ¨ƒííí$‰¬QE¦B>êÉ%u{s[[õõõÔ××p÷Ýwã÷ûikkcÍš5îwèÐ!Ž9’ý  æCÖŒ{lÌðD™Ë˜L€uÐùñ… úSp«Áz ¢?„À…Î]»Þ=à9 [ß¾3`öî^þh·Øüý£<û¹޽õ ‰j+÷¬äàÁƒü|Ñ7øÃçßâxïËœÁ>ª=¥œ¥§màê7¯æÑòg÷ó;/dÀ0‡³[~Ì¿jáõsZ _¾–ÖÖ\sèüqÖÖ¨ö8Ç2¾ÿ¢pþµÎkœŸªl„ñ×OÐÕõ?Î&÷aÜŠ_<£oz› bæÆà$ Ë=åYà nEÓï÷gõnjjbõêÕn21³bÖ17!Ì›7Ï|æ3X–å¾f(Âëõ eßF³æGÌ|¾Ô’Ž]]]TUUºS*™LR^^NYYYî+y©$p¾ÑÆãpG ¬÷¤ã¥¯É‰çù‡N4x½ØÿÔDâ‡W`7ýšà?ñ¥ð«²·é}®—«ÎzýÆe,úÎ.\xœ%§¼‰ýSYº¤›ºC+˜“ü ñÃÈG¸‘m܇…ÅâÅâŒÝ~:¹ŠKzï£sW'>ë;t{ûùùY5xO»–÷^z‹~rä>À]XÝÝÔ®¨å?¿öŸÜ÷éûøÛ3o`qß+ôœ2—ŸÉžó÷Ò;{%?ÿ”P(ÄÜM›øàË/sÉž=œûlg-^ÌÂÆ2ß¶˜JO%öÇZxé™gxóœsðØ6‹o¸þTqï[[º”… ÎÍ“uuì5óCö-¹¤? ÝØòÛßBw7ç§–7Ï{ÌX±÷ÜãÔQ†Š?óxæØ¡™Ïƒ?~œW’ÉôÝ­Ç®Ï8—ƒÙ#"˜‘ÐP·Ž¢-™/9Þø·rå bÊËœ¹Ô øHZMWÔööì^}åË žÙ(3 »­kqüpæ™ø¾ö‡$®½"à­uxVCjùTµ;€pêï&OvÞe¥ßŽ‘ˆóV ú-ê²ß»¦1ÏãI5*ßÿ$‰=Ù–-ƒÏ.ÃþEªÑqû>xøy|@Ì{³‡S/8™·–¯dÙ¡9,Yò&×´µpê§õ§W›óçsøð-D"K8óÌ£üeûgáJXòÜsœ|ø0¾–‡öÜà^.ßñ0ý¦›bÊWŽü.ÇW¬ °ÒÙö{ÒJ0•@xþ¼óø’õ~X朋H;Džx‚ŒÑÊxäôÓ oK¿W[zzøÀ¾},>q‚]©Ï¾†Èng¤YsCf<î†o °^…ÚŽtƒz¤Õ©Ægvjµvµå÷Ýe†ªF¿øÓ_ðÌw^rÿ÷g-XÀÑ£Îÿ§–¿ÊÎÖ ,Y²„£GräÈì §ì³gÏæÌ3ÏdÁ‚$‡¾ðç,Y²„C‡9¿¯¼ÒýÁ‚,è{”¾_ö±|ùr^{í5î­¨`PQQAõË/sÎe—ñýïŸSN9…Å‹óì²¥|«¦†ƒ³f±páBÞxã Λ?Ÿçv~—]Æo~ó.»ì2~\vãìÞ½›¥K—rðÉ'9pàÀè×L‘Ê9ŒUæÅ|Ï2Ûdw3í C-oxIßè0pycà÷¿Tê¬ï©õìÃÀeðÖI°v€çBðVB¢ÝYÞ>ä´aC57H¬‡Ç]ó!¸"_roj†ð€v¨ÀÇW!Ö¾« p„ÿ.{™?úÓÝüë?Ÿ‡}‚Ÿ†Ø· þDÆî^ ¡?…ÚO8ÿ÷gôX2BÁê‚XÜ& ÒžÅà»Àù¿©¢©P?Ãé%m†Ä®Ô6> ‰ùøøV‚½Ï9&‰vg;ž%`ïøýÀ›ðþ wÃkçaý2uœÁÊø4`wê±^çoÃw øe`=ž¹Î9ÿéOûxÏEeøNI-Ø '¿x˜Ÿ?2›àÚ…üÍÇòÓ‡û8{™‡7Þxƒ3­=¼ôö,n;ïd8O=z”W]Êëßà‹ßzuï䵃ÛXµø}¼~p.ÖÏörúüÓ¹|A/»w¼Âå³™÷½>f-;ƒ³fŸÍñã)+;ħÀ®'S¹¤Ê%}tþ™ÍÛ/WãɾG¢¤LY,È“ÌzæD&±l–ñ¦šÌ¢Qçÿ–§ê1oÞ^}.sæÌq“˦Þ0Ôpžßüæ£|â×qæ™G¹ãާyøáÓØ»÷tNœ8Á›o¾É•Wöpð`Û·ŸÎâÅ'xæ™}œwÞéY#c$“{¨¨xŠsιŒîîgùÝß­¦¢â óæý€Ý»Ï'Þ­˜)¥2?~œûï?Ž×ûV*™fnH¸m éº×À$¹a¦ƒ*y6pß!}ƒvö9°Ýã†Û–¹Y{ ªÃÅpë•‚¡öÛï÷³ÿþ¶ZXyqœÏhS!m>‡“Ã@Âm×µó3¢—Þ@¼Î¹ÇðÕÏñÙSàc}oÑóæ¹Ü[¾››N}“yõóXxûB²h4Š·Éë´ÿESÓElwº¡`0è¶Ïg°éÐ6Ú¶úúúèííñ=îK&ñØÕÕE2™Ìº©²²’ªª*¶oß>bðxöÙg9ÿ”ó±¾µïûRõûA¸Å›NqCëà‹Xo‰Ý¿û´*¼7ßFü{ðØüŸYÏqwóžxk•»í?yô_8úv-³³};¹íà¿Ò·`Gúõÿèç+¸òÈ_^Âw‡ù!op:O°hö*ºç½ƒ]ûÊø¿Ãœƒsøø_}œ%÷ßTx*Øg×P~ú¼}ƸbÁT¼\Á s^ ï¼óéÚgV}œ'žx‚«¯¾šÿøç0—p o?ÿ6'õÄŽ7¿Ê…åФ›·g—óÖü÷pÖ±Yœ¾÷t®_p=Go8‡ñ÷²lå /=Šãt§†Y:ÿ†ó9qí ¾÷Séa'ÀM¿|n¨¾Þ ´¥ž< ' ¿ ,$ð‚Á_²Ì³¡–˜ö øÛü&ãñÔßvÜféҥ̻+5ä\göóî—Å_êÌc™Û3̤»™uSÑÀ×j;™ËŒô:vêÿ_ñ“¾{Þ ‰•€#Ïó!sx­vÒgF%:Qt.q`Ïž=$®¼ëÉŸð<ŸôÃ{¼Ø¾ôÝ®¯_ñ{ük¼–í=ïàiÛË’9‡¨ýð±öù8Íû þâ7_¡ïç}<þøåÌž=Ûéù“H°|ùr>̇>ô!ª««ùÀ>•DŒD"nÒpëÖ­nò°¶¶––––!ïj3̧&ih†8íÎìµ3€ÏçsïÞôz½nòp¸JK08ʘ¬%¤¹¹¹d{õNTkkë´¾S7S®u‚ËûÏÅZÿ°÷>¼ zaUn kè‘Äßù±mhoïaÏçkþ†^á«_­À¶áÆïçßø PÏÊg³ÿämüó¢/òúÁ¹|õ üÎ >4ÍžÍçœÆÆùó9ýâ‹ùÁž9£ì>¼;và³íÔK&øáí·óÁ»îâO¾û'ÔÖÖò™úzimåü‹ëÙqÒNΪªâèÙG9És1{N>Ìò|„÷ïç7:w¿z½t÷;1¡ç{ÒdžôÝ›ï!}­ûþꯜğÇCEêø¬!G} Lß–?ÞÛ‰{zF~>ùõ& 3…BüfÛ6IÝíêî&Ц¦Áeoi)Éù”gJü˵NÀ’Ô{à½ðzIì*Ãësž!Õh·Æi·^Z€}ødÎëz‰Åö,xJÉØîtÇ`€ºxzôuónoÜ”]%sN=•ç^}•eË–qæ™gòý?û.Ë–-ãèÑ£,X°€_:ÄñãÇaÙ2ìY³àèQÞ¼™+¯¼’'žx‚ÎóÎãî%K(¿â v¼ñåååì~î9æXgŸ}6;wîäånàa ¾¾žÖÖVn¸áþÑXµj½½½”——óù«®¢··×9¬/½Díu׿ç·îT‰pC(D}}=»víbåÊ•\uÍ5,MýÝÚÚêÎOÿÝï~—[o½•ï~÷»Do½•úúzöîÝËõ×_ïTÝSóSG"¾öµ¯ñéOšþþ~fÍšÅgﺋÛo¿P(äÎcíÎʘӺ©¥…ÚÚZº»»ihhàs©úž™ªb(~¿Ÿ††¢Ñ¨{cY8& fM›éË@Ö²>ÿy~šúßÜÇÙ·o .Äãñ Ý›Ë2w˲øÏÿüÏ)¿Žó!/±à¢0¼hC_êj¸Ö749ß©üÀÕ ø§0…xjHl_óï“h¼Ü9? vô~샘·{Ö‚Ÿ¬'ÚœÁ€è'²ÇÛõzO†y·{ªÏ<Îç>ΗË÷ãa‹Û›~X÷îý$ñ?~³8Ï]æÛïÞÏÇ~v:_ûÔ.>}Ïʬm|ì«?ãÊÙWñ/,bþéGùŒ'Î=;²o8ùîžÇá±?ÆÚÿ§=y&\šzvÇæãñ§–âùõ5ø€}¹ßNÏZ{Ip6'Ÿü(çíû(¡½çÒÕû ^ûù‹„žéËz­··êsŽÃ|í 4íªÂ¦‡Å³û¨žmqø©Ã´ýÅ»égŸ{÷çèçd2¿à2ÏãÌ=tŒçßt¶ãcOÏ9Ì#g?ÎÙ»ïÄÌŠÎ"ÄÏÜõýìâٸŹ|ˆv®fW|³ãÿMjØnãŸøýü^Z@äÓ?åox™‹HO×ð¯_àû_¥=õ«=°öxv]ü¡‡NðÇýu\sè~¹èd^Yòÿôrf’êyþ|ùþñµïð¿—ÿ/ïú•¯Ÿp—Ø?ÿ uê,þ=ùïüQÃñ¯-KÉ·>~ œ>ç£\²ÿž>ýiö/ù%þç³ïÌøÒ%½üÅÓÎè&OÔ>Ái}³¥§Žè)ë¡Õ|ÿð­o~‹¢+kž½oÕÿpf×™ìY¹‡}gÿœš§·g-ó/sNЉ3*ÊWÿ˜ Ÿ{„оã©KÐGOYíŸzõ÷8‰®x{mv¶ô©‹Ncå²?fÁ£ 8zÝQžèý/®Ûž]–ÿ œÉïÆ6p°á oü×?sÚÃîóv¹Í±¯þ-g~™:ã¯?ÿ×üýßöuðãÀuó³–ùÍßÎᲿ}7»¯ÚÍÂmÏrš}²ûü‹O¿Èg¯/ÍÞŽy©|Ë"±é‡$v"è}º·:¡ßvíj±(ÿñÐ ¬·Ïã™gðï}ƒÿyz gÎíâÿ¼ño°Üâïxso¼‘^ø ù—ICCMïlbõ¬Õ´´´¸ÉlÓÖçÏÓT^Óá»àthÛÚ¾}»FÕ „†Zíèè`ýúõìܹ3ëñõë׌xQÝtÓMTüä6î9þ)ÊéÅ;ëiŽžô&oÍùvsý¼yŸeùñ›Ù—úº~>q“àIw¢€õø¸xÑ~¿±ƒäÉ'ÓÞßíñ¸w³^ºx1 _~™Ë.»Œ˜móÉŠ ¾û ,_¹Û¶Y¹r%`áÂ…,X°€pÊ)§°wï^®½öZöîÝËÊ•+ÙµkgŸ}6{÷îeÙ²eœrÊ)Œ×ƒ>ÈM7ÝTèS7¥¶mÛFEE¥yçþDõ\ïÛ·}ûöñâ‹/ò‹_üb [..¹Ä€K.¹„·»þ‹ßr&Çx›þþ¥8·(Ù¤'X “ž¸)ŽÇcsâÄ –-[ÆÉ'ŸÌ±cǨ¬¬ä±ÇcãÆ<øàƒnÎM7Ýă>È¥—^ à^·`åÊ•=zÔ½ÞW®\ÉÞ½{9ûì³'õ˜éš˜9Æs®·mÛÆ¡C‡¸øâ‹ùò—¿\è¢[®u‚S;Ï㛯~ €“Nú)³f­`þü>üeÒã/›ñMWt ˆ²|ùÕ¼öÚkœwÞz{w³dÉŽ;ÆÉ'ŸLEEo¼ñ»è"îÛ¶ë>øA÷½øøãóîw¿›]»vQ¹x1gìÛç4Üû|,Ú¿Ÿ#]Ä‘#G&ôy?3ñš0ŸyW_}u¡‹2¥Æz®:ijÏ>ËK/½D$)¹/v¹Ö Þÿþ÷óÄ«9pà‹žYsw8u‚&²ï3ã)gÞ9çaåʓصkìÛ·ÇÃñãÇ™7osô(ýýœ?{6/=Ê‹_Ìžy†÷¼ç=üô§?å]—\ÂܧŸæ´ÓNãóç»Ã_:tˆsÏ=—'Ÿ|’Ûn»ÇœSO=•W_}•k®qF0ñz½no9s^—,YB2™ä–[nTOùéOʵ×^Ë®]»X–êFÔÓÓã~ÿ0Û5uó¿ù“Y·9å”SƼΎ;X¾|9Ë—/wëEfß{L‚pÿîééq—ê»ÒÀu2ëW™å¯R­G'þíØ±ƒ¾¾><È~ô£B}Ür‰„B!ÞøÅ]œ˜}‚çÞ¾ˆ×)çÜ“~Êþ“ŸâØ1§øÏŸð°ý/Yë–±š>ÌäºQ–e›ìèqcˆ „9oÀÄëýXìq'‹M°”8ÞÆZ$8èŽõláçzOêgöÛXÒßÉòå˹ïµ×Ü뢢¢‚‹öícñâÅœ8q‚“O>™ÞÙ³yüÍ7™7o¶msñ™grÖK/¹ñjùòåüïk¯AFÜúû·ÞâÂ×_göìÙœ8q‚ pýÑ£îë\~ùå|éÉ'Y°`o¾ù&'t_/+ã¡'X²d /¾ø"¯—Ëž{νVO;í4þï+¯0kÅ zzzX²d éëã¬cǘ;w.}}}œvÚiüŸW^áÚk¯å±ÇãòË/çcÛ·³|ùrz{{Y²d ?zûm~>o^¯—gŸ}–[.¹„•?ý)\p½ò —œ}6_{õUμî:,ËbÉ’%¼÷n*ŽçE‹xôØ1V¬XÁæßþ–w¾óüüç?çšk®aî#pá…òÒK/qÚi§ñëÞ^^++ãä“OfçÎÜüÎwrâ±Ç¸à‚ عs'^¯—­ÝÝÔÖÕñÔSO±lÙ2–ïÙÃ’7ßt{.¿ãïà®íÛÝøxÓM7±ô?;yã¶KxlçN–-[FOêF,ó÷5×\ã.ûßÿýßYëšØ·k—Óus`ìøûèÑ£TTTpÊ)§pàÀ½±ˆ+Þ¾‚]oí¢ìò²¬e,XÀO<Ám·ÝÆ¿üKöû½ä >÷¹ÏÑÝúÖ‹ÂÓý×¹ŸI-/¹)é©nÇ 2nz…/²|öÓóvóNÿî¿…ysçòæ›orÎIO²gÖürö)Ì™s*o¿}€÷žw€ëŸy†ÓN;W^y…ÊS+i~µþËßÁ+¯¼Â’%K¸õÕWñ‚Ûs}É’%Ü~ìXÖù}_{; .ää'SVVFûéýì:÷\^ýu:DÍgpÙã³bÅ º»»¹üòËù«ßþ–KRuƒK/½”šíÛYÝ·Œ×O~ƒdÁ‚|嬳¸ôÒKÝ÷ÜÅßü¦»+VÐöæ›üvÅ Ž=ÊÑ£GYyø$ÞÿÒn–ž±Ô]拯½æ¾ÎM7ÝÄ9mmxq>ŸæÏŸÏçgÏæ½ç½—=?ÝÃùt>ó›\~ùå<ùä“Y¯ÓÓÓòeË8ýõ×¹þ™gX°`¯¼òŠû:7ýΟÒÒÙ‡?üaæüû¿óîsÎá•W^qëß®®p¯­K¿óÎ:ë,^|ñEªUñ­ž—˜³~[o™ó ÜüòË@ºòÍùó9çÝï&óŽw¼ƒkŸzŠk–œÊ+O¿Â"ï"޼}„‡n¸Á9à”SNaíÃãñxxñÅ9묳øÁ±cÌY³Æ=¯Äãc‡ŽÐëéuë}íïxožsŽ[O:õ»ßÅ—±_|‘§þàصk½˜_ý¡ÔÍM¦¬qp_禛nâùÖV_{—_~™SN9…'Nðƒë¯gϓ˙µlýWö³öᇩ>~œ='˜3¯½þV]Íc=F©ÉõûÁõ×_ÏÊG?Ͻ8ߥÎêeÙÜï±ÿíœ8ñç8ßHOlž`á—™3ç»,]ÚϲeË8tè—_~9O=õ”ÛðáØ­ƒ8p`RÛ§Ã÷þR­g*õ¶ˆ;v°oß¾œÛ gDâqïÞ½|ó«ßæ‰înÊËßËk¯½ÆòåË™5ë úû¯¤¯¯‹.Úç½¶páBfÍšÅ7ÞXèÝÉ«W_}•W_}•ÓN;›o¾¹ÐÅ·\+<ð<ðsçžÎ¡CpìØ1Î8ão¿ýóçlæÏŸï~O0±á¹ŒDÚ)§œÂ‘#GX¸Ð™|Õü}àÀn¾ùf76˜ïã‰'×Êpë¼øâ‹¬Zµ ‘ñ˜éß6oþ/~ö³Cœþù¼öÚkTV.¦¿¿“‹.ºˆE‹±dÉÎ:ë¬Bï¦È¤R›áüêïºxÑ;‹Š‹ŽÐÓÓÏñã;ösç^ȬYOpÉ%N|ÌüŒ^²d‰ÚdZ1ßr­”ÌP«¹8ûì³ù|$<Ä3¿?îm‰Héºùæ›ÇTy*µ^"ã5“ßãgŸ}6ápx\똑tC’ÈôqõÕW)É2–ë^±AJÙL®€sãÅdÝ{abƒ9Æã‰'¹¬#23ùýsöÙgówwûϬ/tÑDd Þf˜GÐw™®òU'˜]诮®®A•ú¤©"2>Š"Š"¢8 "ÅÅQ)%“x4™ÖíÛ³'ùíèè ²²²ÐÅ‘) 8 " X "Š"âP,P,Å‘bS2‰G€úúzZ[[éëë`óæÍ”••±víÚBMD¦ˆâ€ˆ€bˆ(ˆˆC±@D@±@DDŠÉ¬þþþþBb¬úúúX·n}}}”••‘L&ill¤¾¾¾ÐE‘)¢8 " X "Š"âP,P,Å‘bRR‰G£££€êêjÊÊÊ ])ÅÅQ‡bˆ€bˆ(ˆƒ’L<ŠˆˆˆˆˆˆˆˆˆˆˆˆHq)©9EDDDDDDDDDDDD¤8)ñ("""""""""""""9SâQDDDDDDDDDDDDDr¦Ä£ˆˆˆˆˆˆˆˆˆˆˆˆˆälZ'›››¹êª«Xµj7n$™LºH9ikkcýúõƒ~ºººÆ½ß¥pln»í6:::†|.ûX¬Ç`¸ýËùŸ.ç>ߦÛ>ç+”ÊqÉ%”ò51Ô~Ï´Ï|›Nû<ß ÃÅ‚|íc1Õ ¦Ÿ¾¾>6nÜȪU«Xµj·Ýv۠늷®ÛÖÖ†ßïgÕªUøý~ÚÚÚŠ¾Ü}}}lÚ´)k›“+óQöá®ûû1ÔñÏ×ñUl˜|ùŠ…8Ÿ£Åb,÷Xâ@¾Ê•¯rç Š)¦ÉÈÆ Šõ|NE ßå.µ:  òU'Ë2Š…7•qªö窫®ô¾.…}˜ª:дÑ?M}éK_ê_½zuÿ}÷Ý×ÿè£ößzë­ý·Þzk¡‹•ó>½ï}ïëÿÒ—¾”õó /Œk¿KáØD£Ñþ .¸ ÿÑGò8äºÅz FÛï‘Îÿt9÷ù6÷9± TŽK.± ”¯‰áö{&}äÛtÛç™ö^éšÈÇ>ãqP`z2ÇùÑGíôÑGû?ûÙÏö¯^½º¿··×]¦Xëº=ôPÿ\ÐFû}ôÑþ;ÿ‚ .Èëûn2Êm¶ñÐC¹Çü}ï{_^w¾Ê>Òu¿nݺþÕ«W»ûñ¥/}©ÿ‚ .è衇òz|¦F>bA!Îçhq XË=ZÈW¹òUî\bA1Å4Ýh± XÏçTÔ &£Ü¥T'èï>ä£N0–eŠÃTÅý©ÜŸïëR؇©ªM'Ó6ñhcŒ^xaP.5wÜqGÿwÜ‘ó~ó±¹ï¾ûú/¸à÷g¨Šv>ö±ØŽÁXö{´ó_êç~²LÇ}ÎG,(öã’XPŠ×Ähû=>&ËtÛç™ò^íšÈ×>ÓqP`úÚ¾}{ÿ\п}ûv÷±ÞÞÞIyÏNÆù½õÖ[³¶ÙßßßÿÙÏ~¶ÿ¾ûî+Úr?ú裃z{{Ý/üù*w®eíºê}bÎÉg?ûÙ¼_ņɗ¯XPˆó9Z(Ær%ä«\¹–;± bšŒÍXbA±žÏ©¨ä»Ü¥R'èï9ä«N0–e o*ãþTˆF£ý·Þzë ÷u)ìÃTÕ¦“i9ÔjWWÉd’šš÷±ÊÊJªªªØ¾}{¡‹7aÉd’²²²œö»ØMMM [¶laË–-“¶Åx FÛoùüO‡s?¦ë>ç Já¸ä Jõšm¿gÂçÀd˜Žûÿkjj½wª««éëëËÛñUl˜ùˆ…8Ÿ£Åb-÷hq`¬¯91,×XP,1MÆf´XP¬çs*ê“QîR©Àȱ u‚±,£8P¦*îO…®®.¢Ñ(_øÂ=^ìû0Uu éfN¡ 0z{{½ÊˡÇ¿Tlß¾ÞÞ^V­Z8î|,û]ìǦ²²2«0P>öÑ<^LÇ`´ý†‘Ïÿt8÷“aºîs®± ¯rcÙÇb|Œ¶ß3ás`2LÇ}ž)ï…‘®‰|íc±Õ ¦¯ÊÊJç‹ioo/­­­TUU¹ç¢X뺦q¾²²’M›6‘L&©¬¬¤¾¾žªªª¢-wuuµ[þÌëÊìO¾ê ¹^S£]÷UUUƒûúúx衇òZÿSl˜ùˆ…8Ÿ£Åb-÷hq`¬¯91,×X0]ëFÓÕh±À4DÛùœŠ:Ád”»TêæØ òQ'Ë2¥Ðn4LUÜŸl}}}ÜqǃÁAIÔR؇©ªM7Ó²ÇãtÕ××Gee%ñxœx–ú1€Áç&œû‰˜ û<‘X0ŽK>ö±ÔÃLý˜ˆé¾Ï3õ½¯},õã :Añ3sƒdª©©¡¦¦fPoÕb­ëLˆ¬Y³&«§@1–»ªªŠx<ÎÎ;Ù¹s'wß}7ååå“R_˜Ìkª««Ë½Ë:ÓØØ8dƒ“êFÅ/Ÿ± çs´8PŒåKÈW¹&ûúK,(…˜&cÅz>§¢Nïr«NP|1MF7•q2tttP^^ΦM›X¿~=ëׯÒ=½KaŒ©ªMÓ2ñhîô81gGGGÑß14œ¶¶¶¬‹ÑH&“n°Ë~—ú±ÉÇ>–â1íüÏ„s?ÓqŸó ¦ÃqÉÇ>–ÚqÐçÀÄM·}Ö{¼îc©Õ JW[[ëÖ­q™b­ëšy‘nsà¼HÅVî¾¾>š››³úúúèèè ººº¤âÈÆY»v-wß}÷Ûœ‰u£R•XPˆó9Z(ÖrÆúšÅòk¤XPJ1MFÅz>§¢N0åV 8cšŒn*âþdª¯¯çÎ;ïdÆ îÀÚµkÙ°aCIìÃTÕ¦›i™xçMÝÚÚêÞù½yófÊÊÊX»vm¡‹6!UUUtttÐÜÜì>ÖÑÑáŽÿ>žý.õc“},µc0–ó?ÎýDL·}ÎW,˜Ç%ûXJÇAŸ¹™Nû¬÷BZ¾ö±”Žƒê¥kÍš5ôõõ±yóf÷±ŽŽ:::²†H.ƺ®Ij777»Û4ï;3¤Z±–»­­-ë˜777SVV–×rOFÙ3uttL&Ý^0™?™wMÏ´ºQ©ÊW,˜êó9–8P¬å-ä«\“}ýŒ%”BLÇXbA1žÏ©ªLF¹U'(®˜&£›Ê¸?YLÒ-óœïµùŽu“e*ë@ÓɬþþþþBb2ôõõ±nÝ:úúú(++#™LÒØØXôó%Œ¤µµÕmd*//'™L²aÃǵߥrlV­ZÅ–-[ÍU•},æc0Ü~vþ§Ó¹Ï§é¸Ïùˆ¥t\& Jýšj¿gÚç@>M·}ž‰ï…¡®‰|íc±Õ ¦ŸÖÖV6mÚDYYÙ¤^»“q~“É$7n¤««‹ªª*ºººòþ¾›Œrwtt°qãFÊËËéíí¥¼¼œ»ï¾ÛÒ¨ØâÈP×}sssVCi¦ššwn°é^7šNò q>G‹ÅZîÑâ@¾Ê•ÏrO4[L“‘ Šõ|NE`2Ê]ju òU'Ë2Š…7•q* |_—Â>LUh:™¶‰GÃŒ‹^]]]2“®Ž¤¯¯Ïí’[YY9lWܱìw©›|ìc©ƒ±œÿ™pî'bºís¾bÁt8.ùØÇR:úÈÍtÚg½ò¿¥tT'(]ÉdÒ–g²¯ÝÉ8¿f›“ù¾Ëw¹3¯—‰ü|–{2Ê>3­nTªò q>G‹ÅXî±Ä|•«®ŸéÓ¦»±Ä‚b=ŸSQ'Èw¹U'ÿ2Ű2ºRyO–ú>LUh:˜ö‰G™|ÓvŽG™:J<ŠˆˆˆˆˆˆˆˆˆˆˆˆHΔx‘œ)ñ("""""""""""""9SâQDDDDDDDDDDDDDr¦Ä£ˆˆˆˆˆˆˆˆˆˆˆˆˆäL‰GÉ™"""""""""""""’3%EDDDDDDDDDDDD$gJ<ŠˆˆˆˆˆˆˆˆˆˆˆˆHΔx‘œ)ñ("""""""""""""9SâQDDDDDDDDDDDDDr¦Ä£ˆˆˆˆˆˆˆˆˆˆˆˆˆäL‰G)8Û¶I$yÝ^<Ÿ´òÆãqlÛ.Èkóq™j#½ŸÆÅ…á{ùDÆc¼ïç‘–M$X–5®×/ÕXPÌeÎpïÙ¡¾[Œç=®¸P:å“é§mºöK§|2ýå &«Ž0Ѳ”b,(沉äÃd¾ÇGºî'ûµ‹ê¸ôKÉhiiéïîî.t1ò¦§§§?ôý@¿ÏçëïììÌy»íííý“ùÖúÛÛÛ òÚÅ|\dòL·k?º»»‡|?W†Wìå“4Å‚Ñçý<\éîîî÷ù|n c~ýRÅ\6ѵ?”¡®ß‘¾[Œõ=®¸PZå›É¦[\(tÛ€®ýÒ*Ÿ¤) 6Yu„‰*ÕXPÌe“‘M·¸0Y&ó=>Òu?Ù¯]LÇE=KH,÷]vÅ,cY===ô÷÷ãõz‰D"….–HÑ™n×~.,Ë"‹QWW7äóŠ+2)äÇhq¤¡¡¯×K?===$ Âáp¡‹-3˜®ý´‘®ß\êŠ Rj¦[\(T^×¾”:Å‚´Éª#ˆ”šé¤tMÛÄ£mÛD"Âá0‘HdP÷Öh4J8&bYÑhÔ}.‡ ‡Ãƒºà‡Ãá¬mÇb±¬í üàïòÃ1åŒÅbYÝ]M¥7sÆÊ¬‰DÜ}Îü¨eFÛÞX÷Õ¶m¢Ñ(---x<šššðz½£î›9_¶m»çi´!3Ïåx×˹î\Žö>íÜñx<ëܚת죭›¯ý.V3áÚÏåºÏ\¸k<×ýx÷u,×ßHû7ðý<ðÜW2—nq!óu–,ëN·Ø0Òq)˜ã3T,(T0ëä3Œå3¿±`¤}Ïõ:ðZ7çw¸ceYñxœP(€Çã! ºû2^ª#L=]û#Ëwý¼û›ËµoÎÑPû;ž:€Y>ó‰D‚x<ŽÇã¡©©iÔ}3ÿŠ+Üת­­r¿Ís¶mãóùƵþhV¯^í®dzî¬í}8Ú±ÌÇÝ÷hmmmÖóuuuƒÞ£Ã­ äe¿‹ÕL¹ös¹î3×îÚÏu?Þ}Ëõ7ÒþƒAÚÛÛ³b…1–¸bÎït‹ 0rlm]˜^±a¤ãŸ¯? ºÿ‡B¡~¿ß?áåGâ÷û ô‡B¡¬òŽu{×øÿp´½±îëÖ­[û~¿ßßïõzû½^o¿ÇãÉ:öÃí›9¿MMMYÏý===îó===ƒÊùþný±ìg{{»ûÞÈ|/™1ã3_ÇÈ|Žå52e»Û…BYsM ·îHû=]Æþž)×~.×ýPë%Œ¶½±îëX®¿±ìßPcŽW¦{\èï96Œ´îtŒ ÃçŸýìgÃÆþþþQcA!ã@~cÁX>ó  FÚ·‘Öýîw¿;ⵞi¨8b¶3Ôr¥ fzA×þèò]ÿïþærít®Gûn1Z=`¸íf–o¨åJ!.ô÷Ïì:ÂdÅsìÆúÞ/¥¸0Ôc“ Ù6`èÚŸ~×~¦‰¶ô÷«Ž0•u„ÑbA!ê¹¶˜r r‰æ52éûÁبŽ0ºB×riCÌ¥Ž¯6B³Þd\û¹ÔFZ?Ÿ×þ´ìñhºË744¸w²´··ãõz‰Åbøýþ¬.õ@p2»^¯Û¶‰ÇãYÿgv™Î\×ãñ¸]õG+ÏX—/¿ß?äkwÝ¡þî±\÷5óŽ£îînº»» ƒƒ²ú#í›òœ;›2· ¸wK˜ó;ÐhëÆ²¬Aï%³Ìòõ>Ì…Ù†¹!k†¡ö{ºŒý=“®ý\®ûëåÿ±û±îëh×ßDöo,qeºÆPlÈ4Üq~ì±Ç†0¶XPLqò[ê±BÆ‚Ñöm¨uŸ{î9`ôk}8#]3㹞TG( ]ûã_w¨ÿ@!K€IDAT‡{,Ÿû›Ëµ?”±~·˜Hl(õ¸3;6Lf\ÈÜ>ŒþÞ/¥¸0Ôc“Š¡m`(ºöKûÚÏ4ÑvPa*ëc‰…ª#äÚN#ÇÅÂPaüë÷X1·!æRGеŸ]Þñ^ûÓ6ñØÞÞ8ÝHgÍšECC0rѲ,w\ÝÌŸñ^<2:sL3‡6…BnОˆAÊçó …Üs?ÞõGcYÖˆ`¤÷a.Âá0³fÍrÇÎÎõÃ(ßf…¤k¿tåã}8R\yâ‰'€é@±!ÓpÇy´J–bAáåò¾Ë\w¼×zæzÃOå_u„Âе_ºr}¯õ»ÅDbC©Ç˜Ù±Aq¡øcÛ€Yg8ºöKËDÛ @±`*MF,ÏvÇ'&r-Œ  Cu„Ò•¯vе?Ñã6Ó2ñhY‡––zzzèìì$‹Fñx<ßÏçf–ÍÏÖ­[ …B#V:eüFz³Žõœy͘ÙZZZÜìüpã7´þh¼^ï »2·1Òûp¢ÌúÝÝÝ´··ÓÒÒ2î÷f®û]Ìtí—ŽÉxŽ;–,YLÏ¸Š  wœwíÚ5â~)L½\Þw#­;Úµ>ó… óN¾Ñ ‡ÛŽêSO×~éÈ÷{m¬ß-&J9.€bƒâBñ+†¶¡èÚ/ík?ÓDÛ @±`*å#ä²Ý‘âD>®…‘bâ@a¨ŽP:&«ÝtíOÆ17¦eâÑLújˆ×ëu?L€;™08ΜL¿ßŸõ?¤'(-Ó%Àû|>¼^oÖD¦áp¯×;æ aàD²gÐÝ%fÂèH$2¨;ðXÖI ÈšxÕÜíbŒô>‹Ì÷hækx<÷ËÎpw~ µîPûmŽùt¹+G×~éÈõúÊHqeåÊ•îcÓ-.˜ÿG‹ #Å…û^ê±a¸ãìóù† XP¹\sC­{å•Wºt­Ǽï3ß±XlÜC¶ªŽPºöKG¾ëãùn1ÞØPÊqÁü?“ëРŝÚ†¢k¿´¯ýLm'Å‚©”Xëv‡‹ù¨·Œ r ï¡:BéÈw»ÁXëÅ~íçRiýû>Ñkθ–.Á`X,ÆŠ+Ü`áóùn¹¶¶¿ßkNHSSápØ –e¹]^ Íãñ‡±m;kN€RµuëVjkkÝcmÛö¸ŽµeY¬X±Â]·¥¥eÈå@€†††¬íuýᘮØuuuø|>,Ë" ºw1Œô>M0t·kÛ¶[D£QV¬X×ëuß¿æN†`08캦̉D"k¿‹åýºöKG®×ßp†‹++]Ó).˜ý-6 ·®)÷tŠ Ãç?þã?fùòåCÆ@± r¹æÆ²îp×úHššš¨­­uç@ðx¶›'ÌõžzËH± —8ú~0Qª#”ŽÉn7€Ò»ös­Lŵ?«¿¿¿b§¼ø™¬­¹[p'z5ÝëõF±,‹­[·f-éîÓÅ ³ìù˜d´dë±fÍãñ8µµµô÷÷»çx<ç)×õ²,Ëí=Ô]XC½Ç"‘H`Ûöç{`¹ÍDÆf¹‘ÖjýéF×~ñÊ÷õ7”BÄ• 2·;TlmÝ¡Ö/uóXâ(L…\®¹b#CQ¡0tí¯É¾~óuíNæ¶UG( Å…âW uø|•k(ºö o¢í™ËÛ±P,˜ÜíNFŒ)L4€¾äBu„âU¨vƒR¹ös©LdýñšÖ‰Ç¡˜Lugg§›e®­­% ô.€Ì`5œ±žä|nk2·9Q™>ןŠ},¦ã8ÓèÚß¶&k›¹^¿“e¤r)6L3!”Âö ·XPˆ8¢8PÚfµ_ u(ÞzÀD)6”®™Ja{¹R@×}®fB,(•:B1R;ÁÌ4âB)l ×n k??¦åP«#ñz½î0 f¨ Ó½´†k7ÓXïÈÉç¶&s›Åf*öq&Çb¥k|ÛšÌm–ņéc&ÄRØ^)R(m3áÚW 0J×Lˆ ¥°½R¤ë~z™ ±@u„É¡X0}Í„¸P Û+VºöÇnÆõx‘ü›]興ˆˆˆˆˆˆˆˆˆˆˆHéSâQDDDDDDDDDDDDDr¦Ä£ˆˆˆˆˆˆˆˆˆˆˆˆˆäL‰GÉ™"""""""""""""’3%EDDDDDDDDDDDD$gs ]€©Ð××ÇöíÛ ] ‘¢Q^^NUUU¡‹1庺ºèíí-t1DŠFuu5eee….Æ”R@d°šššBaÊ%“I’Éd¡‹!R4*++©¬¬,t1¦\GGG¡‹ RTôý@DÔf("{`V¡wb²}èCbÉ’%\vÙe….Ê”zðÁ¹é¦› ]Œ)µmÛ6***¨¨¨(tQ¦ÔxÏõO~ò|ðÁB{Ê]~ùå|ìc+t1¦”®‰™c¼çzß¾}”••ñw÷w….ú”R`æØ·oûöíãꫯ.tQ¦ÔxÏõ¶mÛ¸ýöÛg\òñÖ[oåºë®+t1Æ­T¯åR­”j¹'ÿ}ôQ¾ûÝïºèSª££ƒ»îº«$?'J5¨ÜÅ]î™úýàoþæoèëë+¹X?“>£ŠA©–Ôf8V7Ýtï}ï{ ]Œœ”êçU¦Rm™J9^dîC®u‚ÑãqîܹÜpà |êSŸ*tQ¦TWW….Æ”jnn¦¦¦fÆ5ž÷\wuuºÈ1wî\]3„âßè:::fä]þªÌæ=>Óö{¼çº¹¹¹ÐE.ˆ¥K—–ä{£T¯åR­”j¹'ÿfê÷ƒ«¯¾º$¯©R*wq—{¦~?X²d 7ÞxcÉÅú™ôU JµÜ 6ñ:ýôÓKòüf*ÕÏ«L¥Û2•r¼¸¹(š9ûúúØ´iW]u«V­býúõCºææfw™7Žiˆ¤‹.ºˆóÎ;¯Ð»8åJùÍ=QõõõTWWºSnºœëÉŒçž{n¡wqÊ隘9¦Ó¹V ÿfâ5Q]]M}}}¡‹1å¦Ó¹K,˜h T•êù-ÕϨR-÷tŠ“ýý T•j,P¹Uî‰R,LŸQ*÷XM—X 80ºép®K5¶e*åx‘OE“xlnn¦££ƒ/|á lÙ²…²²2Ö­[—š››imm¥±±‘-[¶L&Ù¸qã¨Û^²d .,ô.N¹™8wee匛¦Ï¹žÌ8°xñâBïâ”Ó51sL§s­:AþÍÄk¢¬¬lFÎW6Îõh± —:A©*Õó[ªŸQ¥Zîéÿ&ûûA©*ÕX r«Ü¥X0˜>£T.±@q`tÓá\—jlËTÊñ"ŸŠ&ñØÚÚʆ X³f 555Ü}÷Ýôõõeuélkk£¾¾žúúzw™®®.ÚÚÚ ]|ÉÅÅqŒ D¦?Õ D DDq@¤ÔMâq ¾¾¾¬ÿ»ººH&“YãûVVVRUUÅöíÛ ]\™Š"Š"âÈŒŠ"3“ê"Š"¢8 RìæºÆwÞIss3}}}TVVÒÚÚJUUk×® ··`ÐÄ¢ååå£NzûÚk¯¹“N‡±ŽE&ªµµ•¶¶6öìÙSè¢ i2ãÀž={X¿~=kÖ¬ÑXÛ2£­_¿žÞÞ^.¸à‚BeHSQ'(//gË–-…ÞU‘‚éêꢹ¹™={ö º–ŠÅH±À4L´N°ÿ~Ö¯_OUU•¾ÈŒÖÜÜLWWû÷ï/tQ†4Ùß|ðAºººhllœÓ‰L”¾èûˆÚ Õf(éas­MâÑLÚÚÚJYY]]]lذ!/cú._¾œ›o¾¹hUD¦Šn`ýúõ….Ê&3œ{î¹ú"!lÙ²…ŽŽŽ¬!IЉê"“¯ªªŠ-[¶ÐÜÜ\è¢ k2cÁé§Ÿ®:¸‰÷™úýছnÒÍ"èû¾ˆ¨ÍPm†"ŽÆÆÆ¼Ô Š"ñ˜L&Y·nõõõn¥¿««‹uëÖQYY©» DfÅÅqŒ *++ ]D™dªˆ(ˆˆâ€H)*Š9ÛÚÚèëë˺ÓÐt•8ùëP]£5$ŠHéSP,ÇXcâ€Èô¥:ˆ€bˆ(ˆ”¢¢H<Ž¥K´ò`àd°ºãYdPP,Çh±@q@dúS@D@±@DDJQQ$kjj(++cÓ¦Mîc<ôÐCYc¬×××ÓÚÚJ__›7o¦¬¬ÌDVDJ— €bˆ8Æ D¦7Õ D DDq@¤Å•••466ÒÜÜÌC=Dyy9Éd’úúz6lØà.רØÈºuë¸í¶Û(++#™LÒØØ˜·IdE¤pD DÄ1–X 8 2½©N " X "Š"¥¨(àÜ‘°víZ·;teeå nÐeeeÜÿýtttP]]­À!2(ˆ(ˆˆc´X 8 2ý©N " X "Š"¥¦hà‡ÌîÑÃË2"RšD DÄ1–X 8 2½©N " X "Š"¥¤(æx‘ҦģˆˆˆˆˆˆˆˆˆˆˆˆˆäL‰GÉ™"""""""""""""’3%EDDDDDDDDDDDD$gJ<ŠˆˆˆˆˆˆˆˆˆˆˆˆHΔx‘œ)ñ("""""""""""""9SâQDDDDDDDDDDDDDr¦Ä£ˆˆˆˆˆˆˆˆˆˆˆˆˆäL‰GÉ™"""""""""""""’3%EDDDDDDDDDDDD$gJ<ŠˆˆˆˆˆˆˆˆˆˆˆˆHΔx‘œ)ñ("""""""""""""9SâQDDDDDDDDDDDDDr6'Ÿkkkcûöí466ÒÑÑAuu5eee…ÞO™DyI<öõõ±qãF:::ÜÇÙ¼y3Û·oçÞ{索ªªÐû*"""""""""""""“$/C­F£Q¶oßΖ-[عs§ûøwÞIMM ëÖ­£¯¯¯Ðû*"""""""""""""“$/‰ÇÖÖV‚Á 555YWVVò…/|¾¾>wV™~ò’xìëëv(U3¿cWWW¡÷UDDDDDDDDDDDDD&I^UUU´µµ ùœ™÷q`oH™>æäc#Á`7°fÍÀI8&“Iš››©©©¶G¤ˆˆˆˆˆˆˆˆˆˆˆˆˆ”¾¼$׬YÃwÞIss3­­­¬_¿€úúz ½Ÿ"""""""""""""2‰ò’xìèè ¦¦†_ýêWîЪÕÕÕî"""""""""""""2}å%ñ¸qãF·g£ær™yfçc#Á`¶¶6úúúrÚN[[~¿ŸU«Vá÷ûikk´Lss3W]u«V­bãÆ$“ÉÂ9™Š"Š"â-(ˆLªˆ(ˆˆâ€H)ÉKⱬ¬Œ²²2Þ÷¾÷±iÓ&š››ýŒ¦­­Íí9¹eËjjj3‡dcc#[¶l!™L²qãÆBCÉÅÅqŒ D¦?Õ D DDq@¤Ôäe¨Õd2Iyy9åå律 ²aÃ6lØ@MM ½½½tttP__8¦¾¾Þýÿî»ïvïnX³fM¡¥ˆäHq@D@±@D£ÅÅ‘éOuÅQ)5yI<666æ´~2™¤««kÐvî¾ûn÷ï®®.’ÉdÖ’•••TUU±}ûv‘§8 " X "ŽÑbâ€Èô§:ˆ€bˆ(ˆ”¢¼$d2I[[½½½€sçAæÅ>ÒzàƒM›6‘L&©¬¬¤¾¾žªª*€¬mf*//§««kÄí:tˆX,F2™tïx™‰:::èèè`ÿþý….Ê “öïßOssó˜c“ÈtÕÜÜ̾}û(+++tQ™ª:AGGGÎ7N‰”²d2Ikk+Û¶m+ÊÏÄÑbA®u‚ƒÒÜÜìnSd¦jmm%™LrðàÁBe©ø~°mÛ6š››©¯¯§²²²Ð»,R0ú~ ï"j3T›¡8ß{챜ëy™ã`Ó¦Møý~š››Ù¼y3›7ofýúõøýþ1]Ü·ÝveeeTUU‘L&Y·nݘ×ɼy󨪪¢ºº:_»+R’*++©©©aÑ¢E….ʰ&+,Z´ˆšš5*ÈŒWSSCUUóæÍ+tQ†5Ùu}‘™®¼¼œšš*** ]”MV,˜?>555ú~ 3^uu5555ÌŸ?¿ÐEÖd~?¨¨¨ ¦¦†òòòBï¦HAéû¾ˆ¨ÍPm†"à|?ÈG /=3'n­¯¯w³¡477³qãFâñø¨Û ƒî8Í~¿ŸÖÖVî¼óΜÊ7wî\.¾øb÷‘™ª²²’ÊÊJ6oÞ\è¢ k²âÀâÅ‹õeB„ô€ÅØ»Á˜ì:bÌteeeÔÔÔÐÑÑQ袌h¸XëPI&ñ(2Ó™ïÈ3õûI<ŠÌtú~ ï"j3T›¡àŽ0”k /=ÛÚÚÜÉ]3»`ÖÔÔp÷Ýw“L&ÇÔ¨1p˜£5kÖ¸]©¡îbPBQdúPP,Çh±@q@dúS@D@±@DDJI^'nÍdº'ÔíÙ q´}ûöAÛ5Ìö.ÓÑÑ¡.Ð"Ӏ €bˆ8F‹Š"ÓŸê"Š"¢8 RŠò’x¬¬¬¶G£I8Žtg꩹¹™¾¾>À mmmYÃ(Õ××ÓÚÚê.³yófÊÊÊX»vm¡£ˆäHq@D@±@Dc‰Š"Ó›ê"Š"¢8 RŠò2Çãš5kÜñŸ×®]ëNðjæxË$ÍwÞy'7n䪫®¢ªªŠ®®.6lØÕ…º±±‘uëÖ¹É&“I³†w‘Ò¥8 " X "ŽÑbâ€Èô§:ˆ€bˆ(ˆ”š¼$ç.‚КyGSYYÉý÷ßïöœ4Úf*++ËZ¦ººZCdQP,Çh±@q@dúS@D@±@DDJM^à$ƒÁ Û·o§««Ë½øÇ;yëh=#ǺŒˆ”.ÅÅqŒv+ˆLªˆ(ˆˆâ€H©È[âÒã-ëâ™YfçkC­­­¬_¿ž®®.÷±«®ºŠM›6¹ºŠˆˆˆˆˆˆˆˆˆˆˆˆÈô”—ÄãæÍ›Ù´i@Ö¸Éõõõ<ôÐC¬[·®Ðû)"""""""""""""“(/‰ÇÖÖVêëëÙ²eKÖ¤®Ü{ï½tuu¹“ºŠˆˆˆˆˆˆˆˆˆˆˆˆÈô“—Äc2™dÍš5C>WUU5«ˆˆˆˆˆˆˆˆˆˆˆˆˆL/yIߘױmÇSè¢O‰ÙùÞàš5k¸óÎ;ùÕ¯~E0$™LrÛm·ÑÕÕUè}™°h4J8óò–eÇ ]ì)“÷Ä#@2™¤­­ÞÞ^‰ÇãTUUz_EDDDDDDDDDDDD&,‘HŒkùX,6îuJYN‰Çææfü~?ÍÍÍîc­­­øý~6nÜÈúõëÕÛQDDDDDDDDDDDDŠ–eYc^Ö¶íq=7“’ŽCâ±¹¹™Í›7SUUEMM àôtÜ´iUUUlÙ²…»ï¾›d2™•˜)c 5‰Ã'ãñø çlÛ&‹z÷¦Ôœ‰¬Ô××ÇæÍ›illdÆ îã­­­Ü}÷ÝTVVºoܸ‘®®. ·*""""""""""""E%‹ G|>‘H¸=‡KTìñh–©—äPÛðxßÜÜì&3™,&á6¶m»ë˜¹3™^‹&qgz?Ú¶í¯j¶NB2 º Ë‘zH4ܰ¨±XŒ`0@ Àï÷» O¯×‹eYî>×ÕÕ Ýå‡Ú®¶Õôœôù|ø|>n¹å,XÓ±ŸPG£¾¾žúúú!ŸkllÔ¼Ž""""""""""""2¥Fš‹q “hÌLÎY–åijˆ€ûÛ$!Ͱ¨™ó8šÿ=Ï ÄcfÏC“¬ôx<444²æ’4¿Ír¡PˆX,–µ_¦§¥mÛî°¦·£ßï6éi™¤¥¥Å-2™äÀ9ûœ€;ÔjyyyV¢QIG™,C ! êµ8Òú€;4ªé=ljD"nâ1 ¹Ëeþ6I¿Ìä£ÙŽÏçËJü% 7qh†E5=#£Ñ¨;\ªÙN$!ãñxÜǶnÝêî¯I.& wNÉîîn²–‡ÃYûlö¯¥¥…X,FYY™;Dkuuµ›÷›¨ µÚÕÕ…ßïgýúõ¬_¿žÛn»M›6åT‘±nhÒáj93Œªºœäœ™;1sÈÔ‰Dó\æÜ™ÉÉ̤¨š5‹¹É@“tljjr“¥Á`ÐML†B!lÛv‰™¯ßÔÔ侎Ivz½^ÚÛÛ•%óx˜y"Íòëׯw¬ù0áÄcss3½½½lذ-[¶°fÍZ[[innÎKÁDDDDDDDDDDDDD†‰D=fhcI¤™áIap²23Ñhþ6‰ŸÏíu ݹw¨UÈî!iz7f“  ´´´àñxÜ!W›šš…BC;pÕ‘†–Í<™ûÜÐÐÀÇ?þqw>È;î¸#çs2¡Äc2™¤££ƒÆÆF©©©áî»ï¦ªªŠ®®®œ Õ××ÇUW]5dwÎææf®ºê*V­ZÅÆI&“9¿žˆÅÅq  DfÕ D DDq@F‹Å€ìùG“H$²†D5¿MÂÌy½^oVr/‘Hà÷û tvvºÏe&3焌ÇãnÏJ¿ßï&,MË­[·ºî簾¦!‡“5ÌrÃ%3“¥ñxœx°jÕªœÏÄ•••Y×ÔÔä\ €7Ò××7èñææfZ[[illdË–-$“I6nܘ—בâ¢8 " X "Ž¡bâ€ÈÌ¢:ˆ€bˆ(ˆcÖ¬Yî°¤f¸Spzïeöì3½Gêùhzÿ™ÄžIfÎý8°ga&“œ4É»ÌDefïG€h4ê&3×É\&ÓpW³¼mÛCöúüЇ>Äš5kðx<ìÙ³Çí嘹ÎÎNöîÝ›Óù™ðP«“eóæÍôööù\[[õõõÔ××»½,»ººhkk+t±E$D DÄ1\,P™9T'P,ÅÉ–™XK$î¥æ78‰ÇX,ÆŠ+†Ü†I^f&øÌ𨦷äp‰Çá’†&i¶5pŽG34«Ivz<ž!Œ‡uI$¡¥¥%ëÿÕ«W‡©­­åá‡æÿñùþ÷¿O(¢§§ÇÂu`OÊÕ«W³`Á‚œÎMQ%»ººˆF£|á _ò¹d2™Õ«²²²’ªª*¶oß^袋Hž(ˆ(ˆˆc¸X 8 2s¨N " X "Š’fz1&‰¬¡TM1g µZWW7bG“$4&Gëñ8Tâq(MMMô÷÷ ……BY‰Ë¡ÖkâѶmÂá°»¶mƒØ¶M(â½ï}/'Nœàºë®ãïÿþïGÜÞYgÅSO=•Ó9*šÄc__wÜqÁ`ªªªAÏ›;çZ^^>ê¼’‡"‹ÑÚÚZèÝ)¨ŽŽš››Ù¿¡‹2¤ÉŒû÷ï§¹¹yÈ1àEf’ææfb±‡*tQ†4u‚æææBï¦HA%“Iš››Ù¶m[¡‹2¬‘bA®u‚ƒºC1‰Ìd­­­477sðàÁBeH“ýý`Û¶m477kþ'™ñôý@ßDÔf¨6ÃRbÀ ž@ÀM@š9MòÎ<>œ ÈÌÇB¡Ð˜×ÎHé×ã13!™¹ß™L/J“pmhh  …hii!ðž÷¼€ë¯¿~Ä2¶¶¶ò³ŸýlØžÅc5'—•ׯ_?äãCM>¹sçηF)//gÆ 9íÐPæÍ›GUUÕÕÕyß¶H)©¬¬¤¦¦†Ç¼ÐEÒdÆ€E‹QSS3h~Z‘™¦¦¦†gžy†W^y¥ÐEÒTÔ .¾øâBï¦HA•——SSSþ}û ]”aMf,˜?>555”——z7E ªººšÊÊʬ;Å‹Éd?¨¨¨P,Aßôý@Dm†j3,M‰DÂ&Ô²,,Ë¢½½+Vd%ãÀ°=3“‘>ŸÎÎÎq•aŸÏ^6â÷ûÝäjKK‹{l†êÕãñŒšx¬ªª¢··7ç:Á„9P£££ƒòòr6mÚ”õxss3ååålÙ²Å}¬««kPQ E‘Ò§8 " X "ŽÑb¹ Rq@dúR@D@±@D$-cÛ¶›d´,ËMü% 7ièõzÝD]æp¥&ñhY^¯—p8ì.?ÐHs:ãf5¶m³bÅ šššˆÅbX–Egg'ñxœX,FSS“»ï#õtœªòBŽC­fêèèpÇK®ªª×õõõƒ–ïèè`íÚµn`0Ïoß¾=+Xttt°fÍš);`"29D DÄ1Z,P™þT'P,Åq˜¤¡Õ$Mb13 izz½^·×£IÌY–åöœŒD"„B¡!“u™ÛÎDzHŽW<§®®Žþþ~lÛfõêÕ´··cYuuuãJ(NvY3å”xìëë#ÒÚÚJ___ÖseeeÔ×× )++q;¦+÷@˜õõõ´¶¶²víZÊÊÊØ¼y3eee¬]»vʘˆLÅÅqŒ%(ˆLoªˆ(ˆˆâ€8“ˆD"X–åþÙãÑÈÆÔ²,¢Ñ(–eÑÐÐ8½ G.u¤ç&+‘gz5†B!|>---nYº»»Ýåúûûǵ]“„ N<öõõ±nÝ:ºººÜ»L‚±¯¯ŽŽ6oÞLGG÷Þ{ï¨ÉDZhlldݺuÜvÛm”••‘L&illÌ˶E¤4(ˆ(ˆˆâ€ˆ8 D DDq`ºËœ×1sXÕ¡‡&ñ˜™€ôxŸ¦¦¦¼îßêÕ«©««#‘H°zõj7iÛ6«W¯´---ÃöÜ,vJ<šîʦçãHÌ2êâ,"""""""""""23eöú3lÛ&‹ êÉhÛ6~¿ßfÕ$á†u´D$0(‘8•C©ú|>¶nÝJ  ÓÝÝM$!cYÁ`pPyJqˆUcBs,Ër“qf~G“œ˜d4=óÁï÷gÍ-™Ïýóù|ø|>‚Á`Ö0°“œgê‡TMu@Ëä½Ä„eeeÜ{ï½D£QZ[[õ|,++cÆ ƒAõv™ÁLBÑ$ÁI6šäœI<C%ÎçX ,Ër©fÞF³™å-Šò›Ž¤aÀ LBq&œx'¹ØØØHcc#YÏÕÔÔLÍA‘¢7p¨Upzþe&‡šóò;£ßï§¿¿?/ÛŠÇã„Ãaw®Æ–––¬y3_³à‰Gp’ Nñ%3 —hlnnfóæÍìܹsrˆˆˆˆˆˆˆˆˆˆˆˆ•X,F ÈzÌôôûýn/AÈN6•œŠ"igÛ6‰D˲ƒ„ÃazzzX±b¶m …†,k1”/Hýž¤Q^ó–x'8p^FÓ³Ñï÷»ÏužÃB'îb±ñxœD"mÛƒA<;$l   ´Œcæ€ÎüoZ‰GÉ;˲ܡT3‡5IG“˜4s#ùV5Ÿb±íííX–E]]^¯×íÕÙÔÔTèâÎb@H¤~ò|¨•x‘¼3æf¥jz8Z–•5kfâq¬½ '›mÛn¹hjj¢¡¡ŸÏ‡mÛƒ†’-zÒ‰ÆNR‰G)v™ÉDp†#5= -Ër‡)µ,«hz9Ú¶mÛx½^,ËbõêÕ´´´ÐÔÔ„×ëÅï÷—FïÆ¡˜9ü@4ÿ/¡Ä£ˆˆˆˆˆˆˆˆˆˆˆˆä•éí˜H$ܤ¢ÏçÃãñ‹Å²zAše0$„lØ8D£Qb±~¿ŸX,Fww7Çí…i’¥%) ÄvœžŽ“ëPâ±££ƒõë×òЈˆˆˆˆˆˆˆˆˆˆˆH‹Çãx<7  ±,ËM:úýþ¬¹ =Äjmm-@€­[·ºå˜h,éÄ£ñ·gèÕ<Ïó8¡Äcyy9555…<4""""""""""""R,Ë"‘H 9çáÀù©ê÷ûÝåLâ±î644¸Ã«–trq<8ï:ñXUUÅ–-[ }8DDDDDDDDDDDD¤ÀÂá0@Vâ13დ‰ÿÏç<™I̱òx<¢™krÒœ°qº:2)C­ÎžÈJ]]]¬_¿ž®®®)¤xx½^êêêðz½Äb1âñø Òiçá0ô%Ò‰G?`ã$ óD‰G‘ ó./€;wºH""""""""R"Ìp¤¡Pˆ`0HSS¡3N§Iò…B!º»»ñxND<w{OÖÕÕÑÐÐ@]]‘H¿ßïöÒ„ôMû3Êkœð‚ém —Z`a^ËÏK¨Ç£ˆˆÈ4`Û6µµµØ¶eYîa¦âçñxH$øý~b±/¾ø"G-t±EDDDDDDD¤ˆ™!V;;;Í»8\F“@Ì|,sXÕáäÒëжmâñ8uuu´´´ÎÈ_™Ã¼š633—äŒSßç 8΀§`täü9õx\¿~=«V­r6oÞœõXæs"""’›††÷ïD"=ë³éåhî<3•-¯×ëÞQljF£X–ÅYgÅ®]» ½;""""""""RÄLOÁá’t&¡7Ò0ªc•Kâ1‘HÐÐÐ@ww7ýýýX–E$qGØ+rÒµ$7Ì1q˜s(÷þŠÚBee%6l(ä¡™qLâÐL°][[KSS“›Œloow+y&)hjj"F±m›––Z[[Ù»wo¡wIDDDDDDDDŠT"‘ ‰ÐÞÞ>ì2^¯wÐ¥gPïÈÑ —3 éììt¡¦‡¥mÛî”·ŒÓ‚ µÛ^ æ?sNf²/“ÌLò~úÈ3™9ó9Û{>óyJKK …BýM™ölLt|zljG€Ì|e&,êßÛõkªÕDjlläÞ{ïåÒK/eþüùx<Ö¯_ßîy+W®tŸ³|ùrjkk“]t!D‚H¢c………˜¦I(¢¬¬ÌMB:ÿ_ZZÚn gÄclâ±¢¢Â­dÝqÇýªÐ $‰BèY,8 ÄÐ&u!H,BHlNGwÃ0¨®®îv:ÒÎ’‹º®wš”Ltyu]Çãñĵuy½^w4¦¦iÃs=GË‚Ü\ êä¹^˜úôT2šú7ê±ß‰Çòòr÷&///géÒ¥þtgùòå¬[·Žï}ï{¬Y³†ë¯¿žåË—Ç•+WR^^Ί+X³f µµµ,_¾»_oÙçÄccc#‹/æÞ{ïeóæÍÔÖÖRUUE^^™™™TUUÑÐÐÐízTUUñ½ï}믿ž‚‚V¬XA^^ëÖ­sŸ·~ýzŠ‹‹)..¦  €Õ«WSSSÓaï!Dz‘8 †ºp8Ün¾{€ÜÜ\%%%äçç“››ëV’lÛ& âóù°,+n®{§Wg=ÇÚŽxL „гX q@ˆ¡MêBX „80ØB¡‘H¤Ë5Ûê¬íi ¦6u–rÚ¾t]§¾¾¾Ý:Žƒ1Ú²ÏB!5úp0hTV‚a¨d)ÐÅ$h —6$/ñxÏ=÷P[[ËêÕ«Û­÷¸bÅ V¯^ÍÚµk©­­¥±±±ËmÕÖÖRPP@^^^Üã .t_[SSã>Ï‘““C^^ž›øB¤/‰b¨ …BnO,G$Á²,·¢ä,€ 5ŪÓÃÌYDZ'<‘hå%ÝF_¯Ú“4Mëðùº®÷«]ª¤¤Äý7‡Ýö.ŸÏ‡mÛB¡EEEN ÛéûƒyXÛ3ÍÁK<ªÕÕÑ}§ó©VºÛêøû ï×ÛîË‹jkkY¿~=+V¬àúë¯ïôyyyy¬X±‚{î¹§Ûç­Y³&î±ÆÆFÖ­[Gqq1 qÁ ++‹ššš.Ë{ìØ1¶lÙBVVV»%ÄpR[[Kmm-‡JvQÚè8pèÐ!ªªªÈÉÉ!'''Ù»,†‘H$B$q{Z…ÃaB¡¶mãóù(++sŸë÷û),,Äëõbš&õõõhš÷œîhš†Çãé´ÇYUU[¶láØ±cÉ>4í V £× 1œ466²yófêêê’]”u ú['hnn¦ªªJ¾ˆa¯¦¦†††š››“]”vãûA]]UUU,\¸ÌÌÌdï²I#ßäûÒf8¼Û º‚Á ¦iözZRÃ0:œåËYw±¯œéS#‘^¯˲âÚº¼^o\Ò³£Žvâ…Ô´£4*³[‘ˆJ$ÓT#;zŸNƒÖÔÔ°ñÀFGu=˜°;}ñè,ÊêÜØ]Y´h‘;º§Ö¯_ÏâÅ‹ÉÉÉéñ莮=z”ššéÝ †=g:äÇ'»(ÝJt8|ø0UUU²°´t¡P]׉D"„B!wnMÓâ¦OÜ„¡óš¾ô 3 ƒÊÊÊNÿ®ªª¢¦¦†£G&ûÐtk ê½©—1544PUU•²‰Ç¶ œÄ£|?ÃÝæÍ›©ªªJÉÄc[ñýÀI<:•B Wòý@¾!m†Ã·ÍÐ4Mòóó)**"‰PVVÖ§)J;K0öv  Ø¦ÓvVQQAii)–e‡Ý÷Ò4’’JJJ…¢CøB!˜2¥ã–Îö=žÁqØVeåÀ¾¿iBa!DgUSÇVýj‡ÀÓ¿lóæÍ ©ôiÄ£óaܶG 3r,ç9555Ýöª­­åÞ{索ªŠeË–áóùÒëpòäÉ\wÝuÒsI {ô¨§O² T˜6mZ»©¡…H4˲…Bî¼òNϬÊÊJòóó)))¡²²²Ë_‡`0Ø.)™(+V¬ ªª*¥¿\K@ˆ•““Ê+X¹re²‹Ò¥ŠÙÙÙR'‚ÖÎÄÃõûÁe—]&±@äû|?BÚ ‡s›¡išX–…eYTWW÷:Q˜H¹¹¹Ø¶ívʃ†®ënÒY®TbÒãñ´Ž¬ Tf­´ÔM0ú|>õÿ¡„Ã*áXZªÖ;LfâÑ0T9‚“tôzãÞ#P2ß…ðsàÿeûÁÅÅÅäääô»NЧÄcAA<ðµµµqC;Šìôèn £šš–,YBAA‘H¤Ó!Í555í¶%Ó# 14H©Ì™CÞI:½¬œQ‹š¦aÛ6ùùùîkœµËÊÊ0 Ã0ðz½ÝN3áTòRzì$±@=‹„Ú¤N „‰B‰ɲ,|>>Ÿ/©IGPS§z½^·½­²²hm‹‹›ÙkÊ|ÕÕäççóò~ ’‹••qÓ§ê¶ ¹¹jÊQ]¿_ýÁ0’»Î£¦A‚FìÆ±íÖ¤cYÁ Úe'ïZY úó ¿¡ž:P³½öiªÕ… P^^Þísçt77òòåËY´h«W¯îð¹NÏ£¶Ó!9s/ !ҟđʂÁ EEEƒA ÉÍÍ% Ý)) ÑuŸÏçöÀ2MÓM –––âw*8]p*zý™P5Š#ÔO2{qõ’Ä!t $1wÎ{Û¶ FçKw¦‚°m›p8Œe©šBo‰º®»ÓHô™e©ZEi©êå”&£'%! g±@â€C›Ô „ ±@!q` ™¦Ù£NòƒQ‡eYD"***:~r$—`,++SÿÓYÛWûgY*XmDT².T?†Ñ~;¶­ÞSÓZß×4ÕãµõÙ¶úq¶STä>×ΘA(¬ßÐ € &èÑ6À`ƒéSo×§æ<ŸË‚ü|µëÁ TT¨æA ÍQG"jW<õœDéSâQ•ÝGMM ÷Þ{/ëׯ'//ÏíYàÌ ï mîn~d'`,_¾¼Ýß X³f  æœ_²d ‹/&33“ÚÚZV¬X‘°¹œ…É#q@¤ŠP(äNjYEEEX–…×륬¬ ­Íš¦ÅOõîÜø±£{Ë™¾µÇ,+¾6 ©ZC T{Cbz $1´I@ „’išØ¶¼ÑŽ¦ †A   ÆM­êñx0M³ó²õc–0'Ùfš`݃~›®²p𦒄±## ¥m«!ƒŽ`P ,+k?ejI‰z}ôùfã<´Ÿü;¡u9„~ÝônЦ‚ÏkCI>”×¥@!^ÿú>ŽÀ²ÔûøýªxqÛ1À³֦̆ÃÂÂÄN½ÚçÄcff&k֬ᠼ¼œªª*xà÷ï999,[¶¬G‹²®X±¢GÏËÌÌdíÚµn°Y¸p¡!†‰"™œº®Ð4ÜÜ\7áØº®£i¡P¨Ï‰G¿ß¯>ñŠOg£-KÕ˜‚A5m„£³ªMòó)êb.ù~’X „€žÅ‰B mR'B€Ä!„ÄD ƒøý~"‘………ø|¾Þu|O€p8Œiš”ôQÂá0ÕÕÕqå‡Ã';kóêñû«½^°Ãu*ûæ´½E×}4Mõ¼R³DµÇ••µfåœ~¿J2êzk"4V³mðz D<7ÜúsEEô©…ሆç;«È¿ããøþûwx}Ú—nÀüƒjòk7Р#%%êýb†,F"êešÖA2QãF¨¸­õ!G½U¢rÐ}N<:–-[Ʋe˨­­¥¶¶PIÇœ;ÙY)„¾$ˆD ƒ·'•“h ƒØ¶Ýn4cO†išøú˜ÜÓ4Mu7rº(ªB[ž@ 51ÙÓ‘†--TUU±«Í%éHbBâ€$!‰B‰‹D"¼^¯›€ìk»Wo9Ë9K†Á믿΋{÷RVYÙ.ÉX__¯þ'P Á>Ï;Ú¶j’°êj`ÃÌ'®Ä0 –°ýe„‚ÑeOž¤t”©ž›½Ó4pÊçñľtÖXŒ©4 ÕÕ'ôÌí,‚²²åøþ­ŽÀÏ?Oà«êoþbðüæI(¹Q=PZªÞÇÙm·fGÃa5J³Í~všD,t ¦Ø>ŸzM¢ô;ñèèd£BÑSáp¯;qyÇ7MÓ3¾ººº]§¿óÛ—––RXXØ¿^c¥¥­µÓlßEÉçS…ÒnJU!„B!„B1x‚Á ………ضÝùŠ ~O]×±m›P(ä.g¤isÿñÞuWç/T›W´Üñ öœe©¾ýeejSNþ.d^Fðx‘I9 Ú(ðýРšÙQ˜÷¯Çè*áÙvÊWçwÛ&ôÐ8¡v9AÅ€J¯úW™‰~¥*—mCä¯úËÇ(õT€?:¬3Û™¦µN«ëê Ú´kêzïò´Î›ý˜Á6NÂB!D*…B”””°cÇŽ¸iNEª‹ŠŠÜùë5M£ºººÏÓ¡vÅ0 *++{ŸxŒB!¶ÒÐQ7%§чJ—B!„B!„ú,Ër—*++£¤¤„ŠŠŠA™b5 áñx0 ƒêêj÷ñÍ=Æø`úÓÎ_ìñÄ·yõqPg&RgÒ°²2Àï0ŸÂœ •g©AàgP?¨O5hÚe€JÌ…BñË:;.èÓ±vŒì׫…Bˆ …Ü5C¡ûx  ??Ÿüü|<;vì ²²’ŠŠŠI:: ÃPÛ‡Õ'¾iªÞZN7"P5§—Ò”)­½¸„B!„B!„è#Ë¿¿Þ]/±¥¥ŸÏGeee—3…%J$¡¬¬ MÓ°, hMn-ܳkáÍ­Md–‘ö«;)*ŠNuê Mt~ú PI¼ÊJÕw¿¢":¡˜ ÚÏ¡¬e&Õ»Áx|ë¡ì7€©²uܜצÙE±ƒ@S›XûPӡ殟ª‰±¤D5-†B¬íدW‚)SàÌ3›™7oWŸŽ·CF< !„H{¶mSXXèN×àõz)**r×W …Bøý~t]ïóš‹ý ÆÏY[a ‡U­À0bV˜B!„B!„¢ïÎ?ÿ(GŽL!;»Œ@ Ä}Ü3@mOÎúκ‘Îz’±ëHš¦Jù€À‰ïcüê-ŒKŸV™=Û¦hîÛØY­}ôû3¬iª&9g&Òv£;‹àõ¢0þ"Ä7ëõ”e©ŸNµNÌ4«í9³©b@ì§ x9­VgrÖdÌÍmŸŸÏç&Ó)T+zÐMɶUŽÐïïdT 3ßÇÓ>QhÛX¦Y¿óý:Œi/ «åIám»µ6× gúƒ~ÏbQ‚ªˆØ€€]ÖZër`¥}½'úX߇ГPú—Ä?!„B!„B‘ÎÊ?–+V<»ïþ”¿ü¥ÚMv•x3MõÚ¸Ñt=dY………îÚ‘Måªi@s3äl›ÊI`,þ÷ïê`ïóDušwš·KãG:k: 9ÈOª†Ã*è¬uØ—ýê”ô è&”~ì D÷;~\Bõw…AëhÇ"Z׬ôô൑—NŒø·Bt& ¹#»JJJÈÍÍ%77—P(„eYøý~***(++‹.Æ«/Îô‘~¿¯×‹eY4551cÆy¾aî´¬ƒ²Ö=‡ ‡Ãäçç»S2ضMuu5eeex<JKK±¬Þ Ïs¦8p+Ñ¡eA`ɬk—µvG1"þÅ>EÕwcßñ-*\AéÛÅøýj{¹ùùÓKaÄO‰]Ja¡ÚL[¦Ù:ÿ¼ó»3k‡:øÀ·,ÈÏ«•@,Â`=ú˜øŠUGÛ5‰þO™z€È=tÑÓM!„B!„B¤6ÛV#ïœÉ¹þë¿åÛßþ,¥¥¥qI@§}ÇxÓ„ü|Õ¦åô¯‰´®aè°,‹@tÞÔO~r)<²³g<„1ëëñK…Ã*óóâЯǂ¦¹ôß)<ôçÖLbJ/šÀó:jôž•D‹&!»jÊöùÔßóóÕqpÚ誫{0òРgI:‡†ZÒþŸC©MßxN’°¿4Ô,gÕÑ}‰2m~2âQˆfÛ6áp8n½E]×ÝQˆÎZŒ¦iR]]í&cœ‘^ Ö³ëŒ®ëÑ‘’S3æ~l»ý((Ã0Ü÷ðx<ìÝ»7Ù‡E cÎ} •@o»£iª ¨úJi©ª0„íó¸wÆ4ÕsC óŒZ¬M‡¹QMåpËŸxkâù1Õ*QÛMƬ,-U0ç==U ‡ÕïšÖ:—»¦µ.líÌÌZZMBÖƒ/J¿D|åÂB­Á臰¡¶¯i`†Ál„ðxð¯B% 0¥cÁz1Zù²¡è2¨ü&î´¬á0e3A³ZçÉ£ŠòaFæÅä|¥*Ù—ƒB!„B!„è!ÛV 6ÓTmPGŽÔ¡ë?çßQZZÚ®Y×ãˆØ6EE^¯ú[(¤Ú¹|¾Ö)OM·#¾iª¶¸¥KGcã5„B¶½†¼©`Ê–fJ–gàý|´AÚ)\´:RQO(02Ú0Æ[1e1A÷€ïjà$j™ gr2g‰¡Z§mÃ)¿®«·tÚ{Ĥw‰GhaX‰šæ´0ZΞ¾§#„Jöe¤dGŒè 䢒M¿:Ó¬‚$…H(Ó4 ‡Ã躎Çã!¸¿;‰ÇŠŠ wô¡ßï§$ÚÃëõº ŠÈN›ÚVl–‰·°Î4•N2ó7ÞHö¡À“¬svEEEhšF8Æ0 ª««;;ÿ»³(³3º“ðs•öxÀCD½‘aG×?,«$dâ¹heßRI:]K(t>‘ J.Z–ÚÆ”)­ïUQÓÌb’‰ŽØil[-t[Á)*RÛ)*R•³Š °¾%ƒÿC ¡*7^T¥À%&„Õ£ÇmÀ^–J¦vÌ7TýAû>xßUeˆ¼f @ó Ðs!ÿïà ¶Ž¶Œ¼¾[ ø(\Ò˜ÁÙ¿þ$¬Hö•"„B!„B!ºcÛ*¨iª=¬¦æ‹üüç¿ÅãñPVVæN{Ëiû²m0+ë1¶üã#_Äï×Ü\¡³ÝPHµc••©v´PHåúÓG™:u»w¿Â¨Qÿï’þ ƒÈœÛ …‹‰D@?¶ÿì‹Ð* –…eµvàDâ;öîò@¥þvÖGëè½|T"­ƒç†*¯Ö» ÓT®¯K$9˨$¢j¬ëéöì>¯·4`*)ªE›=nþ~l·$ñ(†”`PÄØ¹ŸͶmw´b0t“ƒ–e …0 #îq'¹â¬cçõzã>ŠŠŠâF7:# õ^,wÑE×ðÚkpõÕë0ŒÏwøœêêj,ËÂ0 ~÷»ß ÂÙÙ3ÚO×U2oíÚµlØÁ0JY¶ì KÜ{´í"ÓÁ`ûQ‡Þ‚:Œ›gbYjþùü|ð.x6ÿü'®„ÌLƲÔO4£gØ6Ü\®«DŸõÛÐóŸPeRöÛˆÔÍS QGoãŽË(›ôBëj±eUI  *EÑû¥³Š†š:ÁI<ê¨ÞC±OÑ€ïBpµÚ/gQéÒý[ ¾¯T¿ª*‰‚q;àö(»ô'!ÜÆS|*ºXõKê08)¿“¨ A$‘ÿÿgÀ;ø!˜_U»êÝž"`šJþƒê_'\u囼[UEÿkYB!„B!„b ­ä Cµé8bÊÊʺ¼bšá0PJéFâcøžUo1¯Ó4µ]‡3¸¦¤¤„ª«®â›…ÀI• uFv6™á`­ÃèŒÌô¡Ž¨¶QhØ·–Ä£R"Õè ¶µÔgJS¯×ëSP5‰àñxÈÍÍuŸï$c×i¬¬ì¸{€Ïç‹õØ•Ž’Œ=y]¬óÏ¿…_„k®Q@EE*ñÑë!æB´áLÑéíæÃܶm 1MõÉ_Lq¯åë®Ë㢋.r+†áÎŒŠ®C‰¯mÜÊžˆÇ}?gø eE‡ÆÏ  á ø‚º;뤤á õ?…´Nmêܶ60UÉGˆ>ÏI0: Ô‡´³PsUáN­ ýŒéPø57½ñõÜŠß‚Vк)Mk]òôëj×ÂUñÒ÷9 ŸP›÷„ˆ'þø;õBÂ;ÀÚ þï¨é^«f‚hg¨)]+ŒÖùúú¡B!„B!„Hmá°j? U"¯¬LÍžç ˜ñv×`«u ¡èP¸˜¶g]‡Êv¢isÜÇùå#è—éÔWVª)Ç:jPê áY×[Œ>_kSžÏ×ÚØ.OÚ›fpÕ~ç$÷"tàëJ ªí¯/¯íˆ“È4P ÕÂèãþÖÃNìÒNƒI£uªUg*Ö&‰G1äx½*À9lÛ&‰‡Ýÿ÷x*C´Ð- 〆î󀧬µîת"¨tñÓ7TFÿæEUŠÚ¼®>ú¯ø$¤•x$ºÝ`t[&øoÈë ;ÓøÁ¸-~³ÎÜö–ú‡ÛLí;¼WB© Ì€ÊUïVY™:¬^okÅ-²B÷AŵÀˆÖr{½Ì£/„B!„B!RV(ÔÚ<¦Ú¼K0MÓ]Ú PÑÍr‰¨â²2Ê|]¿‰ Be%;Fò“E?¡âkœ¶ò4ØW¢ñzÑÈì÷«öömPíŠØ×ä[ìZ6ªMOGµ×ùézêÖÁàL[†jw5p!ˆJJ:Ë9%k²Ø©X$ÅrÉ%~LsúÓ·°íL}ôQ¾ñ¥îÚŠ~¿ß]SÑãñ¸£;›Ú4vô¡Çã‰ÎŸn×£Ä颳Õ:LLvÄ0 ,Ëj÷Xo8#Çœÿw’ Bô•S±q.ãÇ«ã¿þkÓ¦½Áóω¼FfælÆŽý€¹s?ÇUW} `ªráæÎm»u¢ø¶½£JKÕcè½åÛNõmÑþƒ;‚úÐo{‹k´NËPêéää:„bާnðF·YŠJX–Õj½H/¨ E€?ÈQÙN' ÕY¡õ6Œh¥2Ÿ.+!NýÑ™‚Õ™¶VÓ@¡Ênûm"aµ¶¬SQµ, Û¶yúé§ÉÈÈèßqB!„B!„ eY¸Ëi9MÖEEEí–öŠþAM};Å4Õ¢ÓŠuÕÒ| °ŒÐoÉÈÍåÌŒ%ü¼ùó°ë4õÇgÊZ“|=Ôãñ4ýi»vÚøœ)N#´&öLZ‘Ý%!:ùç‰ù×-§Ik;æ&‰G‘öœ©O×®mdïÞ%8ðY~ø.êê2™0áY¾úU¥mFNÅ&}½èñxÐ4­]rÐãQ1¾¨¨ûi)c†®ë8+Õ‡‰ÑnJ'‘ØYðŽÍÛÈHGá0MuÍ„B­s«*iåܱ׎3²ñÊ+²{w)%%ïáóùøú׋Ðu yñÅ™,\x3÷Þ;M»Œ’xÿ}øÊWÚLqDG:ðÇjÈÒZç7t0üª¢‘‹ª,ttï„P‰=­ÊN¥ÂFU,ìèßMZG(†i]4¹»sø5uéäµ±!¥,úÜpÌs½1åê„Ç£ÎIÛ^`n~Ö¢Ë Ò®]k±íÅXVˆpXãÈ‘é45åsÕUkùâožâ7ü†p8L :tÕ¶m,ËÂ4M,Ëâºë®ãäÉ“½¼¢„B!„B!Ä@°mÕfç,Á¨ÚñX–E$aÇŽíÏhšjóû[Ž vìè2 ‰Dxñ{/òù×?n?Ï?"£a5üö+0•(s’ƒ‰[ÑaÕ ØŽŽj ôEË»œ’3ÁYë°­Á;ÂK—m†C$EZEç£öù|X–åN› ‡Ñ4óÎû:š¶€Å‹}„ßàÊ+Ÿæ‘G¦ã÷'6 gF‡ÉÊ¢"Ó-K}8ôt—®ëضšÕçSŸ¶­>+b·«ÏжŸ¦iòðà ™>}œû|§WLee¤Ý’¶ ž>ÀgL$›m«k2Q#âB!•¬¬lMFFkeeàõÚ|á G¨¬ÌæØ±ïAwàüü| Ãp×4-+ƒÍ›Ç©z›7ã½töÛÐÿø๻µÎE<Ê€k5•¬k[IÑhîTG­¹èA%ó4Ô‡pIôwg‘æüèß,TR²”Ö¤¤³æ¢3Ï»ó½­iÑíõ¤ Ñºndìcm§vá$¡óéOë/©ç€v€`I¯×K$A×uwÄ"@fæUX–…¦iÌæ„5kn`×kylýÄVwúH$‚eYx½^7~mܸ‘­[·öåòB!„B!„ dYª-Ô ¯W%C¡>ŸÊÊÊŽgì+-U|á°J6:ÏiÓˆlY%%%”••‡Ñu]Óɹ ‡Æï4’}ÍÝÀÝj¯/ – òк^¡Óiߤף ;ä,STÙß ÅЉXª}Ð)¿3XÁ&~PÁ`ÓHþ”°L"e…Ãa‚Á ;J  bYÇqè÷ûñz½˜¦†eÇã%0{ö‹L˜ps§S¨¶eš­kÚù|ZT#ÂJÛ%MSåYb–„ì1Ó$º/j›ÎZ‘к½pØùÀéÓ°sçHV­ÊàÎ;ÿ‡wÞù6_úÒL"‘¶m»ÓÀ~íkqóÍžxb+#F©¯?›Ïþ0Ï>{gòN¬N»¾>~ú]]o½nmž{î9n½õjJJ€‰a˜”––¢ë¾øµFmÛ݀߯’ìz(:¢1cZFú5õñ…Ð4õf%¨Äbg}b“ôÕ¨Q‘Zç<{Üb–ŽÄO|R±íbÍfïÑS^Z“—ÝÑT'MÓÜŸ¶•0˲Üõd}>/@Ã0ƒøý~ŠŠŠ¨¨¨ ¨¨ˆÊÊJvX;x;ôv´s‚­*„Ñÿ÷xMê$UœÆù¿ýíß¹é¦;s£ï§ÖSs’0†¡’yá°J4–”¨Çu½óõKJZ€1y,KýnÎCûÎ0yÛ&š,Pÿïl':˜ ]·ñû5"xì±Í|úÓs¸á†w1ÍÌž½×^;±c+Ù¹óã”—?Ä„ ?`Ï_ÿú«èúùîÐŒŒ¾ô¥ï¨ Ì 7FÓ~Ĉ‡¹é¦½Àšd_¢œé9¶Î̿ΔªÎñõ ‹@ äÞsš¦aY§¶“}û|”•µ™¦×É€;ó<ø|à+CÓ t7x¯óÁo|˜÷êpUé0Q=†œ) JQ‘žwºQO›Å€’Ä£H(ËR Ãh?bÐ4MlÛ&‰`š¦û;€×ëE×uš›Ç3räÇùã½ìߟÕáÔ¢qæ¾öx ¢¢‚ÂÂBþö·"òóUYB¡ÖX@ë´¦>ŸzšnRm«¤D=ßë…Ü\õ7ÓTIÇÊJµ€úqF9:ón;Û‡[×˳,õ·ë®kÄ4áá‡Ç1sæQ¶oÏÄ0,^{­‘ü Ǧ°°ÿýß?³rå~ ,ÍôéÓ™0á(kת…}úÓìÚõ4Û·Û<þ¸F Àã¹Çã&f›š‡Õuèõª^PNâÑ0Ôu´vnúâ›Ñ´¿bš:ápؽï¾pÅX:z)?úø˜qå ž×ÆQ¸ <—6Y­oèÌÉzh*ƒˆ!°?ÆàÓ:D@?ÚéÀ·P• 'Iôÿô<ñ­s¼;Iþöœr’:}š¾`uÍj.zî"ÖÖ*áçÄ-Ó4ñù|***0M“²²2¼^/š¦¹ÿ†AQ‘Z³²²]×Ý5gÊž3zÛ©HºëÇösÊ…IŸœDÙ'Ëú·!„B!„B1 œ2Ok›r0$PZZŠßÓ“Þ4Õ\¬š¦þ¿´´5ñ؆išnâ ¬¬“ö¡0ª®m2®‹Žøh´®™XŠJ:Ëi´¶ –D·ãG%)mâÛêB=x/‘¶$ñ(ÊI¶?~œÛoÉ 7Ü˾}Ü‘AÎpnÃ0ðz½nC»3"§¤ÊËáöÛÕÿÛvüÔÔÁ`k²E½®uÄ—iª!à®G÷ÔSÇhllM„¶íü;º+6N;ñÛãQ?á°Ú¶ß_…ϧ³gÏQ^yå/”–³iÓsØöèºÆ3ÏìâÝwwqèP ûØL,ë2*++)**âüó¯bêÔ%ìÞ‡Çà«_ý*·Ür=ôl{&>Ÿ[oý(М9øÃ²)*‚¯~ÊËO1uêHîºëKäçç»Sª–vÒ«ÅI´Æòz½ÌüùÏ“}©ˆÔýdÛP]­~÷xÔy­®nÝè$ç/½´ýû_!6ùÍo‚¬^­û†aðài¢_¦“ù‘Lõa¿øGr"˜Û=høÑ¿„¿Ä\KÑ‘z”ãqG‡ÁÚŠ[ÉЈޣN‚ЙÆÀY±/‰CƒÖéú:íØð¾À\ÑÉ1Vó+ÇŽVtbUóøfðƒq\gmÅØû͹$¢[ü˜€RVV&£…B!„B!Dœ@@µm{½6Á`ÐXVVÖ~Ö¿`°5CéL»×á6j&-Çe«Kým²Òˆo»sšÈÔªNгVd•p´£¯ëë`‘ò$ñ8Ù¶JšuºåLjšm¦^l#‰‰.BhYá°Æi§†mÿððÆ+¸é¦ëðûaF—ë-:£%++U ݱC_g¦Çp¸u¶GgDh¶´íèHÃ0â’‰ž^ £özDf=>ß"‘–åu×Ks¦L,(Pëµ]zi@ŸÏÇØ±7ðÃ^ÅÌ™ã¸í¶Uøý~¾üåJJJJÐu5kþ g(“¦•2b„zÏÇÿ.ºe¡›&ß}ieeó¹û³µøý9hØöH´ RÍ—çÎåbg¾Ö¶ÇuÄˆÖ •3 4&ÉûüìÙ‰¸ÔÄr’Ž­×îŽñÏ)-…Ægžaã_!bYø£ .]×yðŽ;X|ò$Ç_z‰1“æÃºOÁS;â{0•Ø`ø0N^ƒç·|¾rQú&*qWMüúŠ€cVëf:½·œS}­À8S4´éù䌔v¦‹õx<„B!w EÓ4Ñu9ås(ÞYÌ?Bÿ iFEEEn/ç9NBÐY7VÓ4LÓ$P]]„¡$…©È½½}ûv ’]!„B!„œ;º®Úïý9¹¹ßA×uü~¿;‹V;Î6^¯j·ŽM«Û„#¨¶¿j¶j»þ£Ó~è V0‘ÑŽC˜$‡ ÂB•4«¬TÿßnݶnL™¢rY~?üâÇÙºõ-n¼±Ó4£IFƒ¦¦÷ظ±„¦¦"<ƒ™3o,n¼ñ^ žç[ßjÔ¨Åßýî»O•ZG+–•©ä¡e©÷ …âòc€J¬ƒ* ;ó\;ÉÄÞ$Û²mÛ à¡×‰D0 Û¶ñûýûÛH^~yµµa7X‡Ãa¾{óÍxñEÐuvD³A>Ÿç>üaöì)Ç.¹ŽììlõfÑžœ±i“òó[ b  ãÆµ&' ùØ©Spè¿âG_BްÒ40ìjù×êjF8S¦VWÇÙ¬¯oÍÌvàÙsÎáK‰¹ÜD?™¦J¨{½­#wÙû°Ÿ²(»j;žÈë`·Î]쌾⦛ßÜL&p Ð|ú•T–Vâ zT¯¡Qx&ʱ‚ ~XÚ~Ú„hΘÑÿq’Ž:­Ó¦úÖ—µ½÷Œ®* ^zUq’‡.¿ºG}>………”––’ŸŸOii©{;IUuû|>öìÙ«À_áÇÒ-ÊÊÊÜõd5eéO¸c“’B‘LÎhkg]^ nºúΘ¦êZZ¼³˜#6rrûIÌèÎ\7'¾Avv6_ú’Ô „B!„b …Bª½Üï‡/ŒYÃ_æ±Ç*Ôò=jÌÏom@tLhÓ>ÖÔÖlþþèß¹ú¥«ywÁ»hš†®ë=K8:œéQSìT­bÈ’ÄããŒRܱCõšpÖìIâÑ4M~÷»c|üã5dg×cš•:äaÕ*O=µ™ñãë9rä¿xãó¹îº×˜2e:sçîÆðüóàó}•@ü3î6©I¡59áõªØéôêðz[GˆwÔÎï÷«Ÿ®X–…¦iŒzí52OžäÖïŸÿøÉO°mÃ0xàßÿ3·l¡jÏî¸ì2žüÝï°|>LÓÄãñ ë:ß9“iì}ã ´`¹Z‘?ùÉ" cD"”…Bño|Ï=q¿^~ùåìܹ³5é³Cº³¤3l$¶MÙÏŽBæ¸ÖìØAƒiò§å3ðÌ7?¬Ç†áÍÈ®ˆ¦uº¨°è%õ!ÜÛ8Nƒ°óoôZ0MÐkŸ£èËS°ŽÆýifÏžÍôéÓÉÎÎ&sIy9áp¿ßÏÿwá…üdþ|tÓ¤nútþ¼g;Gޤ¨¤„ÒÒR.ç.Þ³‡ Yðî»Ì¼äö^y%G|¾ÖµØ(*bŠa°qãFjû+þW cTk++‰˜&žN2¡«V± «»è¢3ô½ƒ§†ÁÅiŸÐ‘\H” > «éY‚Á¬|º»%›pc!æÿŠo‘NþC eBå­›ð^4Î=Ï'kѯ¾P—˜J´Y£S~Z–…†ÆÎŸ|›«?±”.€lਠBG œ‹ª,úÿ%ô}Îô²èþ·aš¦›,t’‡ |NG€p8Lii)EEETTTPXXHuu5ùùùTVVºk*jš†¦inbÑI :÷Wë'jšÖùÙN¯-I ‰D £î+P•ôŽÍN‡ÓŒ\Ÿ lŽ.…š¡âOÛ¾5yy/°jÕ¹\uÕ^Ž<3š=Œ:6Š#gáÜÆ#œkl&ôšÎø¦ñ|ã£ëXUu#‡G ¡a$YY¯ÐØ8QÇæqá¡É¨¼L¬»/ñó£êÑdl`Mó¼Å÷ïsx‹Ùìã9>Ào9Â×˜Í ÷9ó¸“ݬæcXZ? Ÿ‰À 2#°]‡×J±sX—Ì$и»eúÈ&<“Æ£}•—€±´k¾ª>ß#¬ã üBl´aööÙN)dþ9ó9î;ÎÕë®fÌ¡1 AæšÌøÑ—=é‘ä£Ç#.œéüt]wï='9X8¥0:q€ÊÊJŠŠŠâ¹6 ]×Ý×{<üÑ}}½š§µ¥¥%îßîî%µNk?º]yzxŒDÚ´Xà$±#¨^ƒ>Ôèà &¬²{¬CÑ×:#£6ªòŽéÛÒö3À·"ÿV èÓ€Ù~šh¢©© €Ûo‹Ÿÿ|&[·Î¤¸øAÊËo§`ü¶6Mà´ \qª‰7O#4ÖæØ©7(9…Èñ3hiiá8ÇÙÅ.JÃdÞäMîgÏÆ¾<òß gn`çWÉh:ÎucobæsÓxqÚ“|mç×ð”ßî¦ ÿOû?ŒZÀòÂô-œñn£ÎÚ͆sðíÃMü£©‰å ã=>—Q‡¶ñs¿AíøÏ1ê´1\^¿½±ŒGßfή9œz§OšÛ¿ýmšïº‹ËšfðÅ‘sùäÖ®¥0hâ¯Üοõoy·™iãš9ü1´73¸ü è''bèW±Ì­¢œ øñÛ ic€9|3fŠ^óâ“ ߪsÙœ ÚÍ`|teŸï\à\÷Ú²m¸àú½ü:ñwÍ ôïT,0P™fç˺ÓùÎ9W¡è㱄"¨Xâü8ëš8S›ƒ:ßAâ;ý”íØ}®…Š#NçB-úþN"t*ñI›m8eõÆ”è¾è´ŽÜ4¢?¡è¿fÌ6BÑ×ù¢ÇÂ&>áêÄ1X+z+é“À¾ì,ж€–Ö§Õß­à™–ì£¬‰êùlTSÂk9`…ðt`'øn„ P¿“ ž°À´@kOD¦ƒõ*؇Ô{•ÝÁ¿ûÀw„›Õk9æv0æç> ú)ð]Mj¬ÝÑCq;~4÷*°l0ßB}»ÔCiÖ¹*o‡¢¿‚½Œs€ãà=¬éúxf'Ýz6ØG¡òëPø ° ò.(\Z½ Ôç@ð90¦CéÕPXÿœÊâÖÇü³"Ñó¢e€>|ÓáÝS7ôûöH¦áÔN „èœÄ!Ä ÄªÞ ª~ܶC²V-¾Ï4bY™üþÃoÒ|å<ÉùÜ6:ÄÖÓuÆ1®u;FûíD"wÝÆH$âÎâ¥ë:÷¿|?šS©ïl=Ehý®ÒV_)Ñi•xt‡0V®\ÉòåËY»vm²‹–0¶ÝºF£¦©)Rm[ ÆÛ³gç÷ßûÞù:4†ÓNÛÅ©Sûy챿³uëB@#;»šüü?bšpI}=Ÿ¸é&/ÞÂÁƒ£9çœ1ix<Å=/PÌÔ‡jñ9<lÛVÓ'j/ýÿ°k×.tÛæ[—^ŠîõºÓ(~îÐ!š÷íC^ݹ“Y_L$Áãñ`š&³ËÊØ˜•Ena!¯ìßÇãaGt-#wZÄh‚Ãi‹ý×Il8¾ç:eíO²"†–Ä)²¼Þާžî,ÄŽpÿ¨^`jä@~t¢ÛQaýë°ýØ·@ðQ0¦AÅäs©¸ôŸ®«)ùìhÖàèrøƒÉüqÄÉnÉ&gR_?úu¦žÆÎ⌻g32f¨<§/‚jìÓè6‘欑èLuªë:!3D©·Ô] 1 º÷Ÿ®ënß™þ´¢¢"nAjgT¡ÇãÁ0 <›LLy’x²,8 «&ÍÀ?MÕ íóBȧÛý¨)Eê5¡2ðúÔ=jŸ@p’ Nl G?Zƒ`àCÀ|àe°'‚Vú(Y¥6ñ“ï<ǯ>ŸYG&2–ûËÿÉûsüpOUqìØ1 n¡–w¹ƒLf2ýùjþu‡ÙSêØ±ù9¾ý6¯-xììlf?YçžË[·ÞÊ9S§r×ÎLš>›ïº‹sト²O—¡RwÇÌœ0A~gªË‚Üï«ib¦Rö€ªtUV‚ÇÃyÎ5ù™úWÓ f¬~˜Û}>àvæ,‡£‘€“T÷UŸî˜Ç¼;æAa9§ý_‹³¸ûWwC8ÌÌè”ë±.Z?ç5<¥=¯tÄÕO|`øT®É¶£‹^s¥ÛAÿLÇõç± .ØLêß}“$þÝ ‚Jæ9õPõñ€:šÙv5Œú /ÁMȹÃ~Ïug}e-æ1g›Îåˆ>®©ç›³Aÿ˜•Àd5ŠÙ¾Ì7ÁúP Úð~1:šÙ_„îs+èÛU²Ï›V™ê8eœú(Õ‘Ç€&à-•Ì*y ÌühâêMˆÄ ]öÌÿ(|Bý^¿¦Æÿ‡Àü=DvªçÓ!R ÚþèÁ°!øwõ¾¥g@x¤J’±7z¨·ãÁœ lûmTå›*€þ° š }'úü·ÁxØ}¯/‚vÐÚÔå¿ x ŒlðžãSÀs c!ð¢ïs'x¯}诀=W%q’~“@_‹®ÙÄçÞÑ9ýÉVxö0ý¹épœÁœ]§˜Ñrˆs>~‚‹¶erâÍÜ·d§ýå4FÅèÑ£9{ýqîûÒûÌ\7“Kþ~œÿY|ˆ¹GGRûêÆŽˬǘqFÍÅ›¹t樂¿ZüK2_úWFŸùožÌ˜]6ÿñq›y'F1ûH&ל¾…Ë©¡yû‡i<9޳¦Nfü¸ ²2ÿðÑÄÜ;ƒl8´ˆ¡%¶C™a¨ªŠm·Ö Ú̧ýÿ;¢ý¼Ý×ézëLNÓˆÇÓú:5‹•z~ìcS¦d°V²OŸI,©ÎYFÆùZ—qÚqœÇc—¢Iç}ºsðàÁdª>ð8àtt–%²Qm…1uckåf‚›mBuWâõ,cý3?©_ÁägðÄͯðƒ5÷·ŽH´PÉÆ(Ó41CjÉ¡H$BYY†aàóùÜÎÿ¥²´–Hi•x\¿~=ÅÅÅ«ÄÙêÕ«ñx<¬_¿žë¯¿¾ws*rNwzíÆræ;v!c_ç W.Šh»ÂÁú˜ þÏ€¹´³A_¡"ˆÔƒ}BõÞ½ÿöíü8Ø8šüÜ·É=6†U§W‘qê9´ûmž9<ŸßŸšI‹˜‘ÕÄù§}ÿõOfÙJæ‘íà´ÿW¶@$:¯¢È¡Z4«¿ßéc×+û9ðÇ,vßMÎ[¿`Òã¿€‰:V;ö£’ ŸÞñi¿{˜š/ÔpÍ÷È”£o3bä>y'æâ_j‚Nƒ’ó>ÎûÆŠíQn€.ëu(!qÀI õ‰ýÜô/›ÙøIìßÿ‘hÒÏ,1Ý$=¨I̽€?r#çÞx.W4]¡Þ#z½ÎÑæ´/ªÇO´‚ˆN(Âï÷ ñÆ$øµè­Îˆâ²²2÷ýMS•Ç™ÚÔIì;ëœBk¦ºº:îwçïi·öaÖ·é)a± Œ¹øCÝï *þ™e@¶Å€ÏP‰§>àõBK œ€oD0Ã>´=`nsz4†…ð_ ¥¡…¿ÙªÃÂKå1®ÜÃ÷Ƨ¶Éæ¹ÍµŒÉ>Äž={¸´¬ÚIet.×ͯòÔ©3y`@SF55œ·`ÇŽcãÆœ{.‹W-G»ÜÏ?öžÇ‡ÿk.[VNáË£62v˯iijaÄÑmÔgŸC}v¾#ž¸ï>òŸ~šíûö1áÖ[Y·¿™¼åGy¾ªŠsžËkŸyù¯®aÁßppþ8ïŠ"wÔñyy¼\TÄ´Ï}Ž“]¤¦LŽv,òø£­[¼½ ~¶Š»¢_”œ/LÆúõ\ tz\©'Ū9шûÝép¤ë:TW3³£ ›iªíµšA×U2²m\‹ý½£ŽLm§[÷ûUë^ìãm§‹èÁú²‰ ÅŽ`Œ¬Ñû¡mµRpÚéwO˜ðº M–úùcik=Î \híñ {â¬eµŸ§Øç#’§ÃÎèȵFÏò£_¾/AÉÝê×2¢³7Û@ zÉFŸ,T—¤ß¯òä±*+¡(fIk—ŠA®Tâ1Ît•ôƒè@ÇhT‹ÞÖuÐÛNÍl@© 7ndÆŒ&®›u>ŸxjŽßBæøfšfÌ iÆ *ïRÏù­ý<üµ£œ;s»gŸ ¦éæk/{í554¸Çvÿü,Â]äþýoðáçžãšŒ 2ÎÉàÕ©S96kVv6`ë6ÕÕ\òœú"t±Zî•çÎ…“êÿÍ™pû[oq;@0vOáÑ£è'u˜ÿÙÔÄgþñ¯>ŒÌ?<†ÿïÀqU%HmÇÞ ÞâÉ€çcÎE›¿›‡ ð9à9õ»(Û¡N±³·NšDíÄù˜ÿ§¦¯ÿeV_ùÙθíz<°˜ ÷•k㿨ll˜Â²KÔ”ý5£aÓ˜z‚k7ß…÷Ôsü—\ÂÆSSxi$h9?|åæîÜ üB=áøýð*i+!u‚ñ#‹ÉΈ`gÝtçþØAë(ã2â§^†Ö™7œ†ÈÊžSFëÈatÛm¿‹Æ¾®í6œÑÇÎëÚ¾gGÛˆ}§S…'ú¸óœT§K‡ÝFnÌ6»ÌÑÇ.ýR°Ë¢_ÙïíÎ6_y‹ÁØæs`^ÆÙ`•GŸ]¯D¿<«¢_­—ƒouë×l>ž±ª­Å íy BcÁÖ€ãÀ¨ÜÝ”FâgŸc ¿á)`‚Š­Úc›3Ý7SuëêÐvtŠ=cÀ8ÞõeP?Ö €IDAT Ç€9|§€fõ|Ð.ÈFÕ¦˜æ¨œ…ÛÁ¥Ú˜ìCàÛ£:@÷€çøg‚y´½ÖA·@Ÿ Á™Ààml]Ú‹9ÑÑÏo@Ýœs™ð/U¤«„¶ŠvbÛ6 ÃpgLêØÄ›mÛnû‚ó{oÊ»D‹ÓÆÑvÍ÷¾ˆ-‹aîû@ß’š¦õú8õå= à ‰¸ÿßö8õf¿Ï<óÌ-ï@Jxp’ŒNýàa‡UÝlÕhm2ˆ‚‘ ù ¹iòSÝDAìÙ3ŠO.˜DÆÁ/ðæËo¡çêTUUQø…Bîõûùúù_§¼¼œi™Ó84ñG|,ó-ŽnUsé<¿.Ä®ÊQ|áŠ/ð­¿}‹ŸÞýUª_Éæ£ý(ÕÕÕ,8wð&#§Žä䨓äää0í;›Ø³u=p€9›Ce49·|ùrõEg¢:„çD÷i×£p¿e̘1ÃmTÈÈÈèýÉ팣uýœ 60sæLf†fªªIŒØvG½ußâ·‰OL;wjôVÌã±CòßÛ~y ÿÍÇýqê[ÿË–-œwÞy­Óo9_’Û&JJáÒ—&èÀ ®þÄçõ¬²á߃0"¬7û¡2¦·Ð—½˜/]ƒµ{<æ±ó±m¸ñH·D¿ñ~æÃÏ`gÚyçfÎ|†ººÇxðqxðqõw§’7sæLrss™:u*wÝunïµP(ÄŒ+f©ˆ%ѵHc“ˆ€[!wF):ID§2í¼W씤±S“ú|>V®\Éw¿û]w­Ä~M_š&–.]Êš5kRcm­A²råJ âî¡*!u‚ÿ;WRk Ã~\ ÕzëHã#ñ‰£H ÂÑiЯ»î5V¬8‹÷¾Í»‡'Cnš·…ƒä½í§¸®±’9ÿý"·œ˜Ìlþ€Íºœ¥\qÖ¸ý­·86nÅY|úäI&ßz+îÜÉÕWeíÚµ|óšý¼ó“Ÿð/“çòjÓÝ,Þ7‘»ÞÍc|^´ÀO<Á¯ëê¸;ú¿=3“ÿқo¢³ 8™ŽÂBðùð¶é„0'štÄ})ræ ÷û»ŸŽ¶“µ“{¥Í—ꪪ*ªªªX±bElj¿ØE±{û>±½L5Me€Rdš7þ qý­ðóx>s¢×çdT ðG§å¼̧çÙ5ãïS°-5èYÓÀÛ8ŠÊîÆ:Ð:‰eÞnJþSÅ ÿòfŽýw-U¯uÿ~rìXò ‹©SU}Õüó«Ì:q&gMÜË™{_dÑôüy`ÅÅSÈή§qåÓ<û¡vìØAnn.û³²ˆD.Â0Tåòµÿiäö·ÞrûOü}Ú4JJfº¿?ö‰:ŠöîåàÁƒ\]â`D›Vô¶³DEˆ_žÀ}Î5ÑßwŽIyVhÃÖñãÇ)Ó4>úþûì?žS§N1räHîÎÎf„ hšFSS|ð0fÌŽ?Nsv6/65qî¹çÒÜÜLæÁƒœsð §9r$WlÝÊ›^ÈŸãꫯfÓ¦M|eÒ$ô;ÈÈÈ`ë„ èÀ¨Q£ÜkaóæÍÌ»ì2Þ}ýu.¸à6mÚć>ô!^:rPßQÎ7Ž©cÆè“&MbïÞ½|û_ÿ•ÿy抋‹ùÿøn¼å^~ôQ>ò‘ÐðꫜuÖYø/ºÀ9böEñàƒrûí·óàƒ²äë_'òÐCnýîÜéÓyú¥—Ø3c»wïæ;%%|ó‡?¤ººš@ @ÞW¿Ê¿üeî¹çþgíZfΜ uuêº‹Ö #••Réü[^N$ú{0dDa!…S¦ÐÐÐÀ¤I“5j>Ÿ¹¯ñUV2/úš’’¾xÓM˜¦ÉÞ½{ñNœþÆ‚Œ¦ 8ËR ‡7#f¼zkGÖ©6ˆ~‘sn²”j­£”cÁîè—Áɨ6'fªl 2æ‹Ù! KÃú³u\Žäf8¾ÑÜÈÕ1+U‡Gæöam:Ä?_ø'νjÀW6ÇíÿàóA°j«ŠIcÆà}æ ”Í&޲þjÀèñpjjàQ£ÉGeðKƒ¹"Ñ„úÙû[Ⱦ¶…å_ÛÍ’ŸÍ„ ìüÖ.æìœÝZÐð¥¬7xcÞLÞÝ?–«#ï“{SÛ8‘ÇrjÌ8Z^>ÅÂÉ¿bÓ¼çäá“ÔOØÏÁsêØt0—ÑïŽæä„“ìýçø|&Ïn8ÜÚ¼óŸõXÿ»ß}›¦ú&¦ÏÜÏÛÖ¨f2Çî#óÂdï<ƒÓÎS1òýøß¿ÇèÚqàÐ~ÿÑ#œ÷þ‹œÖÁ»Ç§3wÔ˜0’ý7Ì?>Ž9còøi{¹®òÞQjNæCaOÍäÎãÌÑÛixw+Eç· ¿=‘q§ŽqŠSÔMœÈÚ³Çp÷‰É¼9ùM*žÃÏíWYx¤‘™GöðîıŒh™ÂN»•/d×0éø$¶4æÉG˜;æNŽ8ÉÉ‘'Ù–y—œv!3Æïfbã<ò^àMû ޼}„ “'ðÓé7pΔ°çM‚Û5žãuN?9šño§Ž:Þeá·æ&6OÕeòk¶²—½Ô[õä1ž'ênƪ{ÂXÜÎ[”²SÍì•¿ÓÀx7=¿+ö7L}z*|x)¢îO€?pk´~éþaÁ 1]HÚNu^ ä;½Í£ÓO”è°Cut®¿¤žÆyÌ)ŸCëT:ƒ¹Ä¯:‘¼qËŒþçhæîœë–í­9oñìåÏr{ùíüJƒÎ§µAÝ„ÇØpÚIÆžœÆu7²qÊFj²ÿÁ¬óˆíá~çek¹ƒšš±„¼Ñ954 ^à·ü'¿¡‚ LL )¤…·#ÙÉ3ü±3úŸ:4~,,´èþKü£ë·?4ý!Î?v>—Ô«ýóàaCæ¶NÞʯë~ A(ôR©`{æ>&Ž‘ÃGóiïqå‰/1wç\6\´½SÞধÏt÷gß”}¬½n¾?¨ïk¯[Ëœ7²¸äu§¼ïM«áÕÏNåÆU7®sí-LÙ7….¼#uÿèûŒ>rã6cÏÌ=ŒžuV#§O¥©©‰±'ðÊU¯pý7ДÑÄï.ý70m7œqÉï_ˆ=×â™Ë¹ù‰›q`MuMœÌßÀÔ½#iÝÄØ¦±¼ý±Ì:zã_Oãed~ø$¬69”;Ÿ–‘ÕŒ?ž¦ïÇ䟟húNã›ÇCŽ.<ʸÍã8~õq^¿áu÷Z±ëm¸ÆF;bqªîl0Ø}çFžÇéÿ<Ãc3îÒ#ŒûÕfÜ´…ÿüô;\øŸà@Éš››Ñ"ãì:NMÜÏñ›sðJÏÜ ù~àøOVFàÃ@©·µ÷ØuÀMì™ 1.%rèsä>{ß#“õ>£Çþx€šÓ5Îóz9>û2Væ3„ÃaöÍÞǧ ?Ei©š‘¬mûmÛýn¯ ߇BÛV\[Ä0–6‰Ç††€v]VV–J&táØ±cìüÖ r?¨ÃÃhѹ’öwÏù ä~íoLß|ï;Ÿ¯ ¥¥…C/汿àСƒ0\3ó.ž©û5“°9'ú[uS˜ç£ó"ÞþWNܡ[æòÅY°k×.ÎËËÃ_ó]®½öZþö·¿q0órΜõNMJÓÌ™øð£ªÜïíç±sÇQ=²†Ûn»˜7œÍ˜£9sþ™üsÁ?áb=s4¿¿lÙwÞ ÀäÉ“Y8y2 ¿õÔóÍ»¿É{ÀØko@õg»ŠMÀG8ƒ÷¢ÝcG0‚ªÜ*¸²õX:ãæè{bþŸ˜ÇÒÚ’I'Ïéjm_×Ã÷ _&//óî8¯ýëª:yŸÞ”µ£ç;ÏùRÌû|·“÷i»Çw£Ûx¡Íß;ÚÎ ñ^'ö`â'TÖ÷ùýÏ“5=‹M=i4ó28Ñr‚æšf²ë²Ý—ÿ8‘#œQ{é¨?qàøñã,þÆË<Óà’©s±²Æ0¹êöÏü.Ç’ƒ2{ö#lÛöߌSËñãjîƒP(ÄØ±Ó8óÌÝ<·ó(gu¼Ãç>÷9þú×sX³f W\q«V­â®»îbúôélÙ²…ùóçsøðaÞyç^ýuª««¹í¶ÛøÓŸþÄE]D]]7ndúôé¼ýöÛÌŸ?ŸÉ“'ó¹Ï}€ùóçss4ð³ŸýŒ£GòÝï~—£GróÍ7³gÏfΜɞ=­# ªªâ{¨ÖÕÕ±eË–dŸºA×ÐÐÐîX u½9×[¶la×®]Œ92ÙÅî“þÖ ëÈkÓÇ\ÍûãgsäôÓó©obÛ^<¬¬W8vl{÷^ʼngż:Õ‚h ªÅ5ÍdÊ”Œ÷<ïL8ƒÇOð圓ì}ã ÆÜ|3>æÎ;ï„ûïgÕªU<ô»‡˜ö|.µ,hnæPf&œ8Áرc3f §Ÿ~ºŠ!gžÉþÏ|†S994_u›Çç+W\Á‰É“ÝÒÔ<Èþ÷ÞãÐüùê¦&768ÿN˜0={ö0zôhöìÙ/zä»1D{ö¨ŸÞ¸2Z‰HÂý¸eËêêê/¤HÌéiü;rä;wîdÓ¦Miù¥®¿u‚††n9z.O{#sôèQ&žÀÄK–±s§J¨ëz ;wþˆŒŒZZZ=ú ÞAŽ¿šC‡j ‡ÿ›øžh…_lM˜«ãfOT?ÈeËÆqÁ°mÛ6ü}"_úàÆŒã&ê~Þ4‰'røðaêëëÉ;ë,vïÜÉØ±cÙ¼y3§æÌá7›6qÖYg±gÏFË«#GÒÜÜÌÔ©SY»kçÞp‘‡vë'·Ý†ÿᇹøâ‹ùõpúé§sí”)ÔÖÖ2wî\ž|òIjV­¢ð®»xá…ܺ wÝÅm·ÝƶmÛ˜>>_¶mÛÆüùóyøá‡YõïÀ]wñøãsÅWðÁ÷¿Ïe?ú·Ývï½§¾;äîÞ͘1c¸à‚ xæ™g8úÝïòÕ_þÒ-ÛwÜAÓ/IVV‡¦aî\~=w.ï½÷gžy&Ï<ó w,YÂÉ_þ’›o¾™§Ÿ~šcK–ðo¿ü%×\sû¼Egžé¾ç´iÓ°¼^;–Óð/É-7ÜÀ˜G%??Ÿêêjšòóy铟t__]]Í-³g£i¹¹¹œqÆÔ̘ÁW]Åü[ná•Y³xûÌ3™¼÷Þ{455qäÈþyúé¼wÞyXºÎä[o¥&#íߵ´´p`Ä2¯»€¦É“uð {ãŸøûöíãŸøuãÆaøýüóôÓ™ÿ¹Ï©:atª³É“'3þ|Nž<ɪU«:ü÷sÑ×äççsàÀªªª(..fòäɬZµŠ &ð êˆóïoû[víÚÅØiÓxöÙg“}[÷IcÁ†íÔàXx$ÆcÜ3ϱqÎ)lÛÀ¶m®Ÿ½m¯}†Ñ£GsòäIFŒÉäŸ-aÓñopôèfÌøç8@ÕûK©;5ÇÝöÌ™K¨«û5 â‰e•Ž÷Uã⟯ÐÐðeFÚÅUÓ¿Ã{ï}¬Qœ:uŠ#F0úÿ}š»––~úÓ§È=tǚΣ¥e‘º´´´|üZœqÒÁ`ˆb|LyŸ¿o4ù]tñúHž"ÌGñ²s0™„Íísz®B `q?~§×oƒú)üYkâtΉIG(ÁgÜÂü~-|bÆ ~»{7{&L`ÂÑ£\tò$‹Ffï¬?pôÐQ*žÇ7÷ïç³ÇŽ1räHNØ'xëõ,¾acΜ9<ÙÉkoÌâï½éÆG€uû'«:sœØ{‚óGæs‡? ##ƒCïb„ |íÿŽpêâ‹Ù±e»5³öî¥`äHFŒAóþfê¦O竬Úiÿ×^{-…ucâ¬Y8p€¬#›{6ìâÚk¯eË–-lŸ²êßeÄÉ“ìÈÈ ±~7cŒ'´)ÀwÞÉý÷ßÏm4½QŨs/f×®]Lž<™Š–­Ôz›-‡—?x™Ï\u~Š™7ßÌ‘Çã´ë®ã—Oý’;3ƒöA²s²Y³M%•O?}2|0•¾”H8ì¾ÏEÿú¯,ùŸ­Ì™3‡qãN§zÖ,ži´Ý0š9;¨­­¥®ðF ñ wÏþó˜¿û—´\’ìÛºOú <ÈŸø9Íø5àöÜùcÞšu¶m“ñ›pã'9Æé¸½»møí'gü¨åœG£Çí0œ¨͋ڋ½¹ýRFë|ðÿ9åó-sØA!ŸxåAþñéeŒ³Û¶¹ðÂxæ™?rêT*—Ìš5‹)SÈÌÌäÒk ©¨¨`ÆŒÜyçèºÎƒ>Ș1cÜú¡SosF—:ßÓûûÝu(´… …vÌAo‹H°]»v±eË–~·Žhiiié×IUUK—.eÛ¶mq/]º ËlþC=ÄŸ¾ÿG¬KØ2öÞ?>‰1cÆ0zô"Fú1G%;»‚––k9~<‡‰÷ÙÙ-ìßÿgž9ž¦¦÷8ÿüóyã7X°`Ñ/“MMMŒ¯ÖpkjjbêÔ©¼ûî»Ì›7/Ù‡Œ}ûöqÚi§%»ƒêàÁƒŒ7ޱcÇöci¤§çº®®Žºº:²²²x Í(•tП8ðÙÏ~–—ÿšÁûh?þIFŽ|•ñãwsüø6¦N½”¦¦òòvóþûï»÷û…^È¡C‡˜7oõõõìß¿ßýÿY³f¹÷ûöíÛ™5KNpbB*{bøè͹ްa'OždéÒ¥|âŸHvÑ{­¿u‚Ÿþô׌yýã¼1a6MM33f ãÆ} ðÒÒ’MFÆ?˜4é}:ƒ©S§2nÜó,X°€7Þxƒ‹.ºˆ]»vqùå—³}ûv¦NU½a§L™¢zª¦X]À1ï‰cÇŽqôèQ&Ç$k‡ƒžžëƒ²uëVŽ;Æo~ó233“]ô^éoà?ø?ýéa<Ñ£GsêÔ~Î:ë>øàÌŸ¿ˆwÞy–³Î:‹mÛ¶qƪÃÖܹjôAcc#™™™ÔÕÕ¹±á²Ë.cÆ \sÍ5¼øâ‹\pÁìß¿Ÿ©SUCŽóÿÛ·oçòË/çå—_æ†nàÉ'ŸtŸ7oãÇûn1~üø¸:‡3]—óû”)SÚ}é(9õ”#ÑÑ~Îóœò ´t­¤k¹{ÿÞxã ¹ð ùö·¿ì¢÷ZbAcc#_üâùë_¿æŽ–9²±cÿNKËNúÇçôÓÿÌþýŸbÚ´i¼ÿþûdggÓÔ´šìì³ijÊà´ÓinnæÐ¡3˜ûì¸X´‹u±¯é*Öž¦£÷ïßße|lûš)SÔoçïNÙvïÞ­F›G÷/ÕêyéMýo8?xüñÇñû+xã%Œ;–“'O2aÂÆÿ.MMßaĈ·™<ùMžÆ¨Q£8~ü&MÚÆˆ¹Lžüü6Gnå²Ë^ãůâŒ3Æ0qâD:ƒsÏUórïÞÇĉ{¹à‚÷yæ™yn¬8~<‡óÏÿ¯¿þyMAÁó|ðÁdÞy玟ĩS§˜={§Ÿþ,ÿüçginn榛^௽Âí 1zôhrs7pøð4Nœ8A~þÛ¼ôR“'Ofß¾“deeqæ™cÛÞyçtæÍ{‰'R_ŸÍÛoOaÔ¨QŒ9’nø;O>y7Üðw^~ùBöïÏbüøf&L8ÊÌè4ê›6ÍgÖ¬½\~ù?ÝçL˜p”#GÆqÍ5Üm\pÁ6êë³ijÊ`üøföïÏâðá±|ìcÿdzÏ^ÏÔ© |ô£/óòËòî»­ÉÖ .ØÆÔ© <óÌeÌ›·‹yóv±iÓü¸çÜpÃßÝÇÔšåP_ŸÝî9NY>õ©ÿãOú¸û·Y³ö2oÞ.šš2x÷ÝiL™r€Y³öºÏÝÆË/_ÈLæÜs7søð4öïÏbêÔöïÏ¢©)Ã}ÎøñÍ\~ù?yòÉ«hjR3¾MÚÀ¼y»8rd\Üqsž3kÖ^Þ}wZ\YýÙ´i~\y/¸`[Üùi[Ö .ØÆ„ Gyé¥ ÜçoÚ4Ÿ·ßžÂ˜è(ø¶ïS_Ÿíž¿÷ÞËàèÑ£ÜtÓφe›á²eËhúßr’“¼>î=Þ±—Q£FqìØL˜p3MMM\zéÓ¼þúX öïËm3t>ûœº|}}}R>'†Â÷þt­ÇJ÷¶ˆ7ÞxÛ¶û]'‰G!ÄÐ q@ „„ŠÄ!H,BH"Õ¤Ýk ÎËËKv±„ƒHâ€$!$!‰BX „8 DªH›Ä£3?óæÍ›ã¯ªª"''§/›B¤‰BX „8 „P$!@bB
&mÅÅÅ”——ÓØ¨V~àÈÌÌdÑ¢EÉ.šbHB€Ä!„Ä!„"±@ „„H%i³Æ#¨Ñ—,Yâ.Œ^[[ËŠ+(..NvÑ„ƒDâ€$!$!‰BX „8 D*I«Ä££ªª €… ’™™™ìâ!’@â€$!$!‰BX „8 D*HËÄ£B!„B!„B!„"µ¤ÕB!„B!„B!„BˆÔ$‰G!„B!„B!„B!D¿IâQ!„B!„B!„BÑo’xB!„B!„B!„BôÛN<®\¹’K/½”ùóç³|ùrjkk“]¤~Y¿~=K—.m÷SSSÓëýN‡c³xñbªªª:ü["ö1UAgûÝ“ó?TÎ}¢ µ}NT,H—ãÒŸXÎ÷DGû=Ü>m(íóp¼:‹‰ÚÇT<R'zY¾|9óçÏgþüù,^¼¸Ý} ©[×]¿~=‡ùóçãñxX¿~}Ê—»±±‘{ï½7n›+QöÎîû¶ûÑÑñOÔñ•Ø0ð ’q>»‹©XîžÄD•+QåîO,H¥˜&ºÖ“Xªçs0ê‰.wºÕ  ãX¨:AOž#q ù3îÖþ\zé¥í®ët؇Áª -CÔüã–üüü–Gy¤å…^h¹õÖ[[n½õÖd«ßûtíµ×¶üøÇ?ŽûyçwzµßéplB¡PË9çœÓò /txú»©z ºÛï®ÎÿP9÷‰6÷9± ]ŽKbA:ßí÷púH´¡¶ÏÃíZèêžHÄ>¦âq:ÁÐäç^x¡å…^hùÚ×¾Ö’ŸŸßÒÐÐà>'UëºëÖ­k9çœsZB¡PË /¼ÐrÏ=÷´œsÎ9 ½î¢ÜÎ6Ö­[çók¯½6¡Ç;Qeïê¾_²dIK~~¾»?þñ[Î9眖uëÖ%ôøJl‰ˆÉ8ŸÝÅT-wwq QåJT¹û R)¦‰îu Rõ|F` ÊNu‚––ÎcA"ê=yŽÄÔ0Xq0÷§íuû0Xu ¡dÈ&ÆÇ;ï¼Ó.§›{î¹§åž{îé÷~§ò±yä‘GZÎ9ç÷§£Šv"ö1ÕŽAOö»»óŸîç~  Å}ND,Hõã’ˆXŽ÷Dwû=>ÊPÛçár-twO$jSé8H`èÚ¼ysË9çœÓ²yóf÷±†††¹fâüÞzë­qÛliiiùÚ×¾ÖòÈ#¤l¹_xá…v  îþD•»¿eïî¾ïè:qÎÉ×¾öµ„_‰ /Q± ç³»8ŠåîIHT¹ú[îDÄ‚Tˆi¢gz Rõ|F ÑåN—:AKK×± Qu‚ž Vh(’S­ÖÔÔP[[KAAûXNNyyylÞ¼9ÙÅë³ÚÚZ233ûµß©~l X³f kÖ¬°}LÅcÐÝ~C×ç(œû0T÷¹¿± ŽKcAºÞÝí÷pøCqŸ‡ËµÐÕ=‘¨}Lµã u‚¡+33“eË–‘——×ésRµ®[[[KMMMÜ6V¯^MqqqÊ–Û™Â)'''î<,\¸ÐݧTˆ#=ùü/((hwí,\¸ÆÆÆ„_‰ ƒ#± ç³»8ªåî.ôô=#†õ7¤JL=Ó],HÕó9u‚(wºÔ  ëXˆ:AOž#q 5 VÜ 555„B!¾÷½ïµ{<Õ÷a°ê@CÍèd` 444´»²²²:œÇ?]lÞ¼™††æÏŸ¨È+V¸xOö;ÕMNNN\% ­Dì£óx*ƒîöº>ÿCáÜ„¡ºÏý©x´ÕßXГ}LÅ룻ýŸa(îóp¹ºº'µ©v¤N0tåää°bÅ @}1mhh ¼¼œ¼¼<÷\¤j]×iœÏÉÉáÞ{略¶–œœŠ‹‹ÉËËKÙr/\¸Ð-ì}åìO¢ê ý½§º»ïóòòÚ5>666²nݺ„Öÿ$6 ŽDÄ‚dœÏîâ@ª–»»8ÐÓ÷ŒÖßX0TëFCUw±ÀiˆNµó9u‚(wºÔ œcÛY,HD 'ÏI‡v£á`°âþ@klläž{îÁçóµK¢¦Ã> Vh¨’#‡ªÆÆFrrrˆD"D"Š‹‹¹÷Þ{;\p\ =rþ…C®…áKνpȵ0¼ÉùO+W®déÒ¥¬_¿žE‹u9‚9•,^¼˜ÌÌLòòò¨­­eÉ’%)ýE¹  €ÌÌL· ¶¶Öýÿt¶~ýz/^LNN>Ÿ/ÙÅýޱ@â@êX0tH,xC5H^Òõ|‡B!²²²X¶lY²‹Ò/é÷’mHŽxª¶mÛ÷ûŠ+¨ªª¢¼¼¼]¶\ =]§W“$ _rî…C®…áMêéÏé¹\UUÅÒ¥KÉÌÌL‹sçóùâ <ååå\ýõÉ.Z‡233ùõ¯ÍòåËñx<\ýõ]Nq™ÊœFÒªª*–-[†ÏçK‹ÆiѹtŒÅûî»/ÙEëÐP‹ ±`(ê(t7F²I ¹$ /é|¾ï©k×®MvQú-Ýê@É6¤G'" …ã’ˆ}L·ã Ÿ}7ÔöY®ºév¤N¾Ö¯_Ï’%Kº|NªÖuu‘Ún³íºH©VîÆÆFV®\× ÐØØHUU .L«8²|ùr-ZÄêÕ«;Üæp¬¥«DÄ‚dœÏîâ@ª–»»8ÐÓ÷L•ïX]Å‚tŠi¢ûXªçs0êQn©¤fLÝŒ¸?Š‹‹¹ï¾ûX¶l™û°hÑ"–-[–û0Xu ¡fH&A]ÔååånÏïx€ÌÌL-Z”ì¢õI^^UUU¬\¹Ò}¬ªªÊÿ½7ûîÇ&û˜nÇ 'ç8œû¾jûœ¨X0ŽK"ö1Žƒ|ôÏPÚg¹Z%jÓé8H }]ýõ466òÀ¸UUUQUU7Er*Öu¤öÊ•+Ým:×3¥Zª–{ýúõqÇ|åÊ•dff&´ÜQöXUUUÔÖÖº£`bb{M·ºQºJT,ìóÙ“8ªåî.$ª\}ÿô$¤CLJObA*žÏÁª D¹¥NZ1Mto0ãþ@q’n±? ¾×&:Ö ”Á¬ %#ZZZZ’]ˆÐØØÈ’%Khll$33“ÚÚZV¬X‘òë%t¥¼¼ÜmdÊÊÊ¢¶¶–eË–±bÅŠ^íwº›ùóç³fÍšvkU%bSùt¶ßÝÿ¡tîi(îs"bA:—¾Æ‚t¿':Úïáö9HCmŸ‡ãµÐÑ=‘¨}LÕã u‚¡§¼¼œ{ï½—ÌÌ̽wâüÖÖÖ²|ùrjjjÈËË£¦¦&á×Ý@”»ªªŠåË—“••ECCYYY¬^½ÚÒ(ÕâHG÷ýÊ•+ãJc¸kƒ õºÑP’ˆXŒóÙ]HÕrwU®D–»¯± ÕbšèZw± UÏç`Ô ¢ÜéV'€ö± Qu‚ž»‹©XîžÄD•+Ó†ºžÄ‚T=ŸƒQ'Ht¹¥NÐûç¤Â~ˆî¥Ë5™îû0Xu ¡`È'…B!„B!„B!„oÈ®ñ(„B!„B!„B!„<’xB!„B!„B!„Bô›$…B!„B!„B!„ý&‰G!„B!„B!„B!D¿IâQ!„B!„B!„BÑo’xB!„B!„B!„Bô›$…B!„B!„B!„ý&‰G!„B!„B!„B!D¿IâQ!„B!„B!„BÑo’xB!„B!„B!„Bô›$…B!„B!„B!„ý&‰G!„B!„B!„B!D¿IâQ!„B!„B!„BÑo’xB!„B!„B!„Bô›$ERÙ¶iš ÛV$°²F"lÛNÊ{÷Wª—OˆÞêìzî(¦HlèX*—Mˆ¾èÍ5ÝÕóLÓIJ¬^½wºÆt(Ÿmuu½¶­ôöúîì¹}‰ ÎöÒ16¤rÙÄДÈvg{ɺ÷»ºïûR¶Á”ÊeÃCcÁ@ÖúR–t¬¤Cù„è¹÷ñ¸´ˆ´SVVÖ²cÇŽNOõõõ-^¯·hZ Ãh©®®î×6+++[ò’Z*++“òÞý•êå=3îýDرcG»ë¹«˜"±¡c©\6ѹŽîûá Úêé5ÝQ q7 Ã#^¯·Çï®q Ê'¹÷•ÎîßÎê½¹¾;ÚvâBKKúƆT.›ˆ—îߢ] ¥¥w×p¢ïý®îûÞ–m°¥rÙDç†B!±` ë}‘®u€t(Ÿè™t¯# ¹÷ï¸ÈˆÇ4‡ãzݵý=,Ë¢¾¾ž––t]' &»XB¤´¡pï÷‡eY„ÃaŠŠŠÚýMbŠ.:ºï‡[,è«®b@II º®ÓÒÒB}}=¦i’]l!¹÷»»ûSèjÛDªK÷ïɬÃ˽/†Š¡PG¨Ïñþn[ˆt–îu‘þF'»ͶmB¡¶m£i>ŸMÓ…BX–…®ëx<"‘>ŸÏ}m$q‡˜z½^ Ãpÿðûýî¶ ÃÀëõºÛÔ4 ¿ßßëçvÇyM8Ôlìï§ÛmJKK ƒ†Çãi÷X$i÷œî¶ÙÓ}tÎIuuµ{.JKK …Bqå‹=?Îy±,‹H$‚×ëu+ §ÃòÙ¶M0tÏ]o^Û›s¡iZܵÑÝuדs{ Z–w]:ïÛ¶ü=y­sLú»ïé` îýÞÞË©~ïwtŸwºÛfO÷±»{°«{ß9/Îþvt®;‹)=߉ š¦%4.Äž«¶±!q¡«×ëºw<±ï©¦»cÞU,HT /ÏïLÛ8àñx:|¬;ÝÅ‚¬ô䳸³XÐÛÏñ¶õ€ÎbHl¹ª««Üë% ÅÝ?=%u„ä’{¿½d×ÿûsï;祳û·7õ€¶q¡«m':.ÄžK©#$‡|?h/ÑßÙ.[¾D× œs:ïýáV'hKêí%»ŽÐŸXàœ—¨# …6ľÔ†K,hKêí ×vƒázïDýHx´m›ÜÜ\÷æ‡Ãê ;ÑéûA ÝÞ2¶m“ŸŸ÷ÁäüݶmlÛ¦¨¨ˆÂÂBw¾ð`0èöˆëÍsC0¤¤¤$®§CÛÇ:zNwÛìé>:†išD"4Ms/zç½÷ îk-Ë" ‘››ë¾Waaa»ãç<î²Þ¼¶'òóóÝ×E"‘¸žU]]w=9ޱÚV  ãžSTTä^—ݽHȾ§ƒº÷{{/§ú½ß“XГmöt»»»º÷|>•••í¾ðwSÚ^±±!‘q: ÉŠ =yýP Ýó®bA"ë}yþ@ë.$3Ä–¯m,èÍýÚQ= ³â” ˆû"àĈޒ:Brɽ߱d×ÿûsïC×÷oOëÅ…®¶È¸RGH6ù~бD?Hd»@ì{'ºNÃ÷ÞNu‚¶¤ŽÐ±d×ú `àêéÞ†Øß: ÝXЖÔ:6\Û †û½ŸÐû>ÙóǤ¶sÓÖ××·x<ž–gŸ}¶ˆ›×X×õÇÓÒÒÒ:/xì|âeee-š¦¹¿-eeeîï†a´ø|>÷w¿ßïn¯7Ïí Ç7WpÛß»´øýþ.ëè9Ým³§ûXQQÑ´x<ž]×[t]oÑ4Í=Þmß»¬¬Ì}­sNKKKãþ´üùÏnZêëëÛ½w¯­¯¯ïÑ>VVVº×BìõãÌû>çºëÉ<Úmoɶ×FÛíøý~w½‰®^ÛÕ¾Åù½êÞïí½œê÷~ObAO¶ÙÓ}ìîìêÞïêüvSœçwúœcÐ]lHV\èêõC=.tuÌ{½£Xè:@_žß•ŽîûDÇ‚dÆŽÞ߉ݽ¶«{=VGk8ÛéèyRGH/rïw,ÙõÿþÜû]ß––®ë= m»¿qÁÙ'©#¤ù~бD?Hd»@Gïè:AKKâï}ç¾v¶•j÷þpª´%u„Ž%»ŽÐŸXÐÕùínÛÝʼntoCìk »} ± -©#tl¸¶ ×{ îû!=âÑ"ZRRâöj©¬¬ä¥—^Âãñ¸5Ú‰DÐuÛ¶ÝáÒÎïN>vû ¦ßèj(lož;:&Ûö±Þ¥íé>Æö8Ú±c;vìÀçóÅeõcß;v»ŽØ¡åÎ0â7ß|Àí-{N»{mìyíŽeYí®ŸØ!ö]wíGo9Ûqz#D"lÛîñë;Ú÷¡8¿÷@Þû½½—SýÞïI,èéñîé>vuvwïw¤'1ºŽ ý Ðul¸0øº:æáp¸ÓX0u€¾< u ’Ú¾Ûû¤»×vWèHW÷Loî'©#$ŸÜûKfýßÑŸ{¿3=©$3.€ÔR|?è\¢¿$²] í{§SäÞO5RGè\ª·¶}ÿÁ¬#¤kbã@gû>bA[RGèÜpn7®÷~"ïû!Ÿx¬¬¬Ô°Ò#FPRRÒíÁ¶,ËÏ6ög(Ïe=˜œã;µßïwu_Ä*Ã0ðûý”””ôúµ=;ïqG:»î!0bÄ‚Á ”ú#Ù`EîýôÒßë°§1¥7±¡/eê*6H\|]ó®bÄäèÏu×öµ½­8¯éLo*þRGH>¹÷ÓK"®³®ê7n’@ê©@¾¤žn¹÷åÞ'u„Ô4± 'Ûîk!]Úú²ïéBêé#™íÃõÞïÏë‡tâÑY¸³¬¬Œúúzª«« ‡Ãlß¾½Ëàa†›ev~***ðûý]VBEÏtuÁöôbŽ=μβ²27;ßÙüͽ¶'t]o×Ã!v]w-^ÝÎ6vìØAee%eee½¾û»ïéBîýÔ–èë°§1¥«Øˆ2u$. ¾®Ž¹¦iî§ÄÁÑŸë®»×vWèˆó… ¶'_w_:ÛŽÔ’KîýÔ6×YWõ€É“'É Î¶¤Ž\òý õ t»È½/÷~<©#¤¦DÄ‚¾¼¾§u„tlCLDHľ§ ©#¤®d¶ ×{?‘÷ýN<:‹¾:H×u4M‹[TÔAŒ=©§Ýc΂¥©¢íIO§àoº®Ç-fÐu½Ç7CÛÅd5Mã’K.qs‹ƒí†wôÚÞôFñz½q ¯:½[]w={]Æ.îjÛ6š¦¹_x:êýÕÙk;Úwç˜Åž8rï§¶þÞƒmõ&¦tQ¦®bC2ãBW¯o»ïC).tu̽^o§± ã@g¥²þÜs=ymWõ€Ž8×}ìy‡Ã½šš ¤Ž äÞOm‰®@×õ€yóæ¹%+.€ÔR|?H=Õ.*uHÝ{¸Ô Ú’:BjJD,è˶{ZGHÇ6ÄDÔÚîûPŠmI!u%³Ý`¸Þû‰¼ïG÷éUiÂçó‡ÉÍÍuƒ…aÜqÇœvÚiâñxÜ9wí\t@À –e¹Ã_“MÓ4¶mãóùÚýž***(,,t¯mÛ½:¾–e‘››ë¾¶¬¬¬Ýs¼^/^¯—’’’¸m÷äµ]q†ba–eáóùÜ^ ]w=ù¢âóùÜíÚ¶íV~ý …Bäææ¢ëº{Ý:½ºz­SnÓ4ãö=U®éD“{?µõ÷ìHobJllpz7%¢L]ņdÆ…®^?”ãBWÇÜéUÖQ,H·8ÐÙc©®?÷\O_ÛY= 3¥¥¥ºk hš·¾AOH!ùäÞOmQ€ÎëmW’@ê©@¾¤¦Áh¹÷‡k £ã&u„ÔÔßXЗm÷´ŽŽmˆý­8媱 £ã(u„Ô”Ìvƒáxï'ú¾ÑÒÒÒÒçW§ '‹ëôVpyuN€®ë„B!,Ë¢¢¢Â}]ìb°ÎðéT[þØEkßÓEìñíiæ<‰PXXHKK‹{^{znúóÚŽX–å‹î¨VÛë®§LÓĶíNÏgÛ²;‹;C¸»zmG¯ÊäÞO-‰¾;;>081¥3]ņdÄ…¾¼~(éè˜÷$¤Kèì±T•JŸãéKéˆÔ’OîýÔ’N÷ï@nWêÉ'ßROªÔáQ®Î¤Ú½?Üêí›ÔRË@}Ž÷uÛC¡ ±¿u€Ž¶1”I!u$³Ý@îýÄÝ÷Ã"ñØ–“±®®®v3Î………øýþ¤fücUgº;á‰ØÆ@n¯¿boþD¾v0ö3ÕŽåp4Tïý¸¶b›ý¹ŠÄ…áIbAòbÁ@}Ž$‰C‡ÜûÉ«ÿ§b ?$. ’ûý ¯¤N ÷~¢I,HÏ6ÂÔYœ‘80|H\žírï'Ξjµ3º®»S(8Ó&8CM“©³ywcu×3'ÛÈí¥ªÁØÏár,SÙP½÷âÚ’ëUâÂP&±`ðÊ4H,:äÞœò †‰ ƒW¦¡@îý¡KbÁà”g(80|H\¼2¥¹÷{oXŽxB!„B!„B!„B$ÖÈd@!„B!„B!„B‘þ$ñ(„B!„B!„B!„è7I< !„B!„B!„B!úMB!„B!„B!„Bˆ~“Ä£B!„B!„B!„¢ß$ñ(„B!„B!„B!„è7I< !„B!„B!„B!úmt² 0¾ÿýï³qãF²²²’]”Aµwï^¦M›–ìb ª‘‘AFFF²‹2¨z{®GŃ>˜ìbºO|âœ~úéÉ.Æ ’{bøèí¹nnnææ›o泟ýl²‹>¨¤N0|477ÓÜÜLvvv²‹2¨z{®X½z5999É.ú úæ7¿É¾}û’]Œ^K×{9]ë#éZî¾Ä¿ÓN;ÿøÇÉ.ú ª­­eùòåiY'H×X åNír×ïøÃxì±ÇÒ.֧ϨT®åi3ì©Ûo¿“'O&»ý’®ŸW±Ò5¶ÅJçx»ý­ ‹Äã¦M›¸á†¸ýöÛ“]”AµtéRÖ¬Y“ìb ª•+WRPP@AAA²‹2¨z{®—.]šì"'Åûï¿Ïã?žìb *¹'†Þžëªª*ªªª’]ìA'u‚áùÆW¬X‘ì¢ ªÞžë•+WR[[;ìûöíKË{"]ïåt­¤k¹ûÿ†ã÷ƒÚÚZ Òòs"]c”;µË=\¿ÔÕÕñÕ¯~5íbýpúŒJéZn6Þ:yòdZÆúXéúy+]c[¬tŽm÷¡?RfªÕÆÆFî½÷^.½ôRæÏŸÏÒ¥K©©©i÷¼•+WºÏY¾|9µµµÝn;33“‰'&{]^^^²‹0èrrrÒ²Çj •s=q`Ò¤IÉÞÅA'÷Äð1”ÎµÔ o8ÞYYYÃ.™Cë\÷$ôµN®Òõü¦ëgTº–{(Å¿þ~®Ò5H¹¥Ü}%± =ùŒ’r÷ÔP‰º7ÎuºÆ¶Xé/)e+W®¤ªªŠï}ï{¬Y³†ÌÌL–,YV®\Iyy9+V¬`Íš5îÔ(ÝY°`³gÏNö.ºtΪ÷Uqqñ²½5TÎõ@Æ`Xƹ'†¡t®¥NxÃñžÈËË£¸¸8ÙÅtCé\w úS'HWéz~Óõ3*]Ë=”âß@?HWé ¤ÜRî¾’XО|FI¹{j¨Ä‰Ý ç:]c[¬tމ”2‰Çòòr–-[Æõ×_OAA«W¯¦±±1nHçúõë)..¦¸¸Ø}NMM ëׯOvñ… q@ „Jw±@â€CŸÔ „ ±@!q@ˆt“2‰Ç¶ã~¯©©q×`päää——ÇæÍ›“]\!Ä8 „‰B%6Hbx’:$!$‘êF'»Žû+WÒØØHNNåååäåå±hÑ"Ú-,š••Õá|αŽ;Æ–-[ÈÊÊJû¡ºBôGmm-µµµ:t(ÙEéÐ@Æ€C‡QUUENNŽÌµ-†µªª*¶lÙ±cÇ’]” F £× 1œ466²yófêêê’]”Nu œÆƒ¾Ö š››©ªª’ïbØ«©©¡¡¡æææd¥Cýý ®®Žªª*.\Hfff²wWˆ¤‘ïòý@i3”6C!@}?HD e .Ô°éÌÌLjjjX¶lYB*ÿG¥¦¦†É“'KÂÖjkk©ªªâðáÃÉ.J‡2>|˜ªª* ¤!†µªª*êêêR¶m0ê†1¬544¸± U d,pN/h!†«Í›7S[[›²‰Çþ~à$srrR¶^$Ä`ïòý@i3”6C!@}?¨©©é÷½•‰ÇÚÚZ–,YBqq±»jMM K–,!''§ß‹qNž<™ë®»N*bØ+((    G=}Û@Ç€iÓ¦ ‰…–…è¯+VPUU·Bª:ƒ#''‡+V°råÊd¥CÝÅ‚þ6dggK@p?W‡ë÷ƒË.»LbÈ÷ù~ „´J›¡Jqq1999ý®¤Äëׯ§±±1îæv†J·]üµ£à'½”…H„ ±@¡ô4Hbè’:$!$‘ŽR"ñØ“a›NÏ£¶‹Á:Ó¢!Ò›Ä!H,B(ÝʼnB }R'B€Ä!„Ä!ÒQJ$ ÈÌÌäÞ{ïu«ªªbݺuqSS^^Ncc#<ð™™™î"²Bˆô%q@ „JObÄ!†6©!@bBâ€é(%ÖxŒ]cfݺudeeQ[[Kqq1Ë–-sŸ·bÅ –,YÂâÅ‹ÉÌ̤¶¶–+V¤ìâ×Bˆž“8 „‰B¥'±@â€C›Ô „ ±@!q@ˆt”‰GP=-Zä‡ÎÉÉi7 :33“µk׺ [.\¸P‡CˆÄ!H,B(ÝʼnB }R'B€Ä!„Ä!ÒMÊ$A‡ØáÑéÉs„éIâ€$!”žÄ‰B mR'B€Ä!„Ä!ÒIJ¬ñ(„B!„B!„B!„Ho’xB!„B!„B!„Bô›$…B!„B!„B!„ý&‰G!„B!„B!„B!D¿IâQ!„B!„B!„BÑo’xB!„B!„B!„Bô›$…B!„B!„B!„ý&‰G!„B!„B!„B!D¿IâQ!„B!„B!„BÑo’xB!„B!„B!„Bô›$…B!„B!„B!„ý&‰G!„B!„B!„B!D¿IâQ!„B!„B!„BÑo’xB!„B!„B!„Bô›$…B!„B!„B!„ý&‰G!„B!„B!„B!D¿IâQ!„B!„B!„BÑo£¹±õë׳yófV¬XAUU .$333Ùû)„B!„B!„B!„@ I<666²|ùrªªªÜÇV¬XÁ<ÀæÍ›ùõ¯M^^^²÷U!„B!„B!„B1@2Õj(bóæÍ¬Y³†mÛ¶¹ßwß}°dÉ“½¯B!„B!„B!„Bˆ’Äcyy9>Ÿ‚‚‚¸ÇsrrøÞ÷¾Gcc£;«B!„B!„B!„bèIHâ±±±±Ó©Tõkjj’½¯B!„B!„B!„Bˆ’Äc^^ëׯïðoκmGC !„B!„B!„B!†ŽÑ‰ØˆÏçcùòå\ýõ€J8ÖÖÖ²råJ :)„B!„B!„B!„H I<^ýõÜwß}¬\¹’òòr–.] @qq1+V¬Hö~ !„B!„B!„B!PB ŒÅÅÅîÔª .t×xB!„B!„B!„B ] Ißï“Knn®¬å(„B!„B!„B!Ä9(£?v²|ùr¿Äj_¬^½]×™={6º®³zõê.Û”––rùå—3{öl–/_N}}ýéÖ„§Œ´B¶@á:Q[ í€g?é!@Ú!„´BœIú%ð …X½z5MMM½ÞÇêÕ«Y¾|9ÅÅŬ\¹’ÂÂÂ.ƒ·†dII +W®¤¾¾žåË—ôs(„è'Ò!@Ú!„ëDm´Bœý¤O „i „Òq¦é—R«YYYdeeñÑ~”Å‹w»®cIIÉq÷aË–-cÙ²eÒØØHuu5ÅÅÅ€ÛÀxkI¬X±ÂŸÝ°hÑ¢~.…}$퀤-B¸NÔH; ÄÙOúB¶@!í€gš~Éx¬¯¯';;›yóæQ__Ommm—ˉî_[[Ûe}È+Vø Emm-õõõ¶ÉÍÍ%??ŸuëÖ ôó(„è#i„ mÂu¢¶@Ú!Î~Ò'B€´Bi„8õKÆ£—ÍX__ÏêÕ«illÜ™„îx)ѹ¹¹Üu×]Ô×ד››Kqq1ùùùö™.;;û„Ídz~ýz²³³ýý q.ª¯¯§¾¾žæææ>•nÏ N];ÐÜÜLuu5¹¹¹äææôCbÀTWW³~ýz><ЧÒÅéêtw!Î%MMM¬[·ŽmÛ¶ ô©tëDmA_û---TWWË÷qΫ­­¥±±‘–––>•.NÇ÷ƒmÛ¶Q]]ͼyóº­Ü$ĹB¾È÷!dÌPÆ …÷ûAô ú%ãà®»îB×uJKK)//§¼¼œ¥K—¢ëzÞÜ7ÝtYYYäççS__Ï’%Kz|ßã9tèµµµ2»Aœóêëë©®®fÿþý}*ÇtªÚ€ýû÷S]]- K‹s^uu5µµµ:th Oå˜NuŸ ººz ¢Ê+Kô~ ø µµµþ¢®B!„B!„B!„Bˆ³O¿ëëëY´hQ··åççt(Á*„B!„B!„B!„8»ôKà177÷˜õõõ@*)„B!„B!„B!„8û é,Z´ˆòòr²³³)..ö×y\½z5†a››Kaaá@?V!„B!„B!„B!Ä)Ò/Ç’’JKK)--íp[~~>+V¬èÇ)„B!„B!„B!„8…zx¬­­å‰'ž`ñâÅ~ Õ’’Š‹‹©®®öË«J¦£B!„B!„B!„ç€^sssÉÍÍÅ0 jkkY´hóæÍcÑ¢EôcB!„B!„B!„Bœf½ ï¿×¥¥¥466²lÙ2V®\É¢E‹¨¨¨ ´´t Ÿ3!„B!„B!„B!Îy¦iú¿‡Ãa H$þuÞïŽãððÃ÷ùx½ <Ö××S]]MII %%%²bÅ òóó»”\í¦¦&.¿ürª««»ÜVZZÊå—_ÎìÙ³»d\ !ÎÒ!@Ú!„ëXm´Bœ;¤O „i „Òq²lÛ&Ç TVV¢ªj‡mTU%‹qã7öù˜½<äææv¸¾°°°_žˆåË—ÓÔÔÔåúÒÒR***())aåÊ•Ô×׳|ùò~9¦âýEÚ!H[ „pu×H; ĹEúB¶@!í€=‘žÁh‘HUU1MUU)((À¶m‰Žã ±m›`0Øçã÷ºÔê©R^^Nccc··­^½šââbŠ‹‹ý,ËÚÚZV¯^=Ч-„èGÒ!@Ú!„ëXm´Bœ;¤O „i „ÒѦiRTT¸™Œ¦i¢ë:ñxœ²²2ªªªÐ4šš‰¦i¢( º®ó“Ÿü¤Ïçð¾ <ÖÖÖb÷ÜsO··Õ××wȪÌÍÍ%??ŸuëÖ ô© !ú‰´B¶@á:V[ í€çé!@Ú!„´Bô”¢(D"rrrH$TVV¢iš¦ø%V5Möm4Mó3"î»ï>6mÚÔ§s2ÐO‚§©©‰;3P(D~~~—Û½™ ˹fgg÷˺’Bˆ'퀤-B¸Ž×H; ĹAúB¶@!í€=á8¦i‡ihh@UUâñ8Á`UU©¬¬ìrŸ²²².×Ýxãddô-g±OÇ¥K—v{ýìÙ³»\·qãÆãîË0 ²³³Y¶lYŸPwvïÞMii)………”””ôûþ…8STTT°zõj¶nÝ:ЧҭSÙlݺ•¥K—²hÑ"Š‹‹úá 1`–.]Jcc#^xá@ŸJ·NGŸ ;;›•+WôCbÀÔÖÖRZZÊÖ­[ûmöþv*Û‚;w²téRòóóåû8§•––R[[ËÎ;úTºuª¿<þøãÔÖÖRRRÒí ¦ç ù~ ß„1C3ïo¶mû™Š¶mcº®£ë:àÃá0¶m‹Å…B„B!^9Õã)--¥ªªŠóÎ;¯OçÛ«Àcnnn¿¾É«««©¨¨`ÕªUý¶ÏtãÇ瓟üäûvPEˆÓÅ«s~¬IéT·Ó§O—/B+W®¤ººšêêê>•.¤O Ä鑟ŸÏÊ•+)--èSéÖ©n &Nœ(}!À¼Ÿ«ß®¿þz™| òý@¾!c†2f(ÞÏlÛ¦  €P(„iš„B! Ãð‘^ÐÑq*++ýë{£¤¤„÷Þ{ººº>s¯ýÙ9¯®®&;;›»îº«ÃõÝÍ8ª­­í2Qf& qæ“v@Ò!\'j ¼IÒqö’>¤-BH; ÎmŽãà8±XŒ`0ˆ¢(hšFMM †a`YñxÛ¶ûtôÜxã}žŒÔok¤-BH; Î –e¡išÿwQQº®£ª*UUUþõŠ¢PYY‰¦iTUUaÛ6Š¢ôhýÆãq§ÏûH×ëÀcSSK–,¡¶¶ÖŸuà›šš¨®®¦¼¼œêêj|ðÁ{¢¤¤„%K–pÓM7‘••E}}=%%%ý²o!Ä™AÚ!H[ „v@á’¶@Ò!¤g&Ã0ƒD£Qb±¦i ©©©éˆL§ëºÿ{e9Æãqb±X¿=®^KKK©¯¯gåʕݖU]´h‹-bùòå”––r÷ÝwŸÔþ7nÜØåº¬¬,V­Zå×—7ož4BœÅ¤B€´BWç¶@Ú!Î=Ò'B€´BiÄÙò,TUEUU ÃÀ4M Ãè’éxªÏÁ²¬~Ýg¯õõõTTT°lÙ²ã®åXXXHqq1åååý:»àdÖBœ¤B€´Bi„.i „ mBÚñþFÑ4`0ØázÛ¶ýuc±•••$‰.ÛJ¦ibšf¿î3£7wª¯¯ܺÉ'âm³nݺSýü!„B!„B!„Bñ¾aÛ6EEE˜¦ég:ŽC0Äq"‘†a`Y‰DÇqNÛ¹yçcÛ6?ü0ÿ÷ÿ×§}ö*ðè¥+w·¨kgÞ6Þ}„B!„B!„B!„8ÛÙ¶ªªTVV°mÇq°,‹p8Œa”•• …ˆÅbÇ]»±¿²½@£·?Û¶±m›ššÆ×§}÷*ðè¥+{™Çãm#)ÎB!„B!„B!„â\á•S ƒÔÕÕaY¨ªJMM Á`EQÐu€`0ˆªªD£Q?8˜.w{ýÉžS8Æ4MÇA×uÂá0@€—_~™‹/¾¸OûïUàqÞ¼yTTTœp[oï>B!„B!„B!„Bœ­¢Ñ(†aÇ©ªª@UUb±555‘H$°,«C†£ã88Žƒa]²ãñ8¶mŸTÖ£aD£Ñ×…ÃalÓÝ®ëhšægbŽ3†iÓ¦õé±÷*𘕕Eqq1ååå¬^½ú˜Û­^½šòòrŠ‹‹ÉÊÊêÓ‰ !„B!„B!„Bñ~RTTD^^žÿ·W¶TÓ4"‘H—íEñK«jš†¢(€t,((   À/Çê‰F£ÄãqTUíp½'=é•oõ‚Ž^ÀÜ £eYÜ•y‰DMÓPUEQ¨©©áÆoìóó1¤·w,))aݺu,_¾œE‹QXXè¯çX__Ouu5«W¯&??Ÿ’’’þ}…B!„B!„B!„`‘H„D"¸AGÃ0…B(ŠrÌõ5Mó®[·Ã0°, EQüò§^0Ñqâñ8•••€<,++ó—ôÔ4ÍßO<' ù™•†aH$xá¿^ çsXb/ñ^‰×Ûn»êêê>=½ üu½ëËÊʇÄÃáM]ש««Ã¶m€Ÿ!©i†a‰DÜÀ¦3ã3¹6ëÚÒþÒ«5»SXXØá"„B!„B!„B!ÄÙ"‡Y³f eee<üðüñÆóío›C‡ùeM½²©999D£Ñû±m›‚‚€cfÖÔÔ ý¬FO(¢¦¦†ÊÊJE! v¸ŸªªÔÕÕùAE]×QUÕ PZ@Ú.mãò™—Ÿ’ç¨ßÇRZZÊìÙ³Oõa„B!„B!„B!„8)–eQPP€ã8ÇÝÎ+Y:mÚ4Þzë-n¼ñF¾ûÝï²sçNî¿ÿ~þå_þ…ŠŠ TU%  …B„B! ÃÀ¶m_ápMÓ¨ªªêTì,‹¡ªª_‚Õ£iÁ`°C€ñXTU¥¬¬ÌÍjt Ìm³n;%ÏgŸJ­ !„B!„B!„Bq¦2M˲ˆF£”••u¹=càüE¡¦¦†_üâ=z”—^z EQø·û7¢Ñ¨Ÿaè•0µm›x÷¹“Êf<#¶`a2ø‚@¨/;ìªWÇüü|V®\9°OŽB!„B!„B!„8'yG˲ˆDº.V¨iš¿~£mÛÜÿý”——©µC¡ÑhÛ¶ýmu]'`YÖÙx|E…-ÉÀ£Ø}Ú[·zµÆcmm-K—.¥¶¶vŸ!„B!„B!„Bq&ŠÇãþïŽÓ³ÅÇñ·õJ©+@è]7uêTöîÝË<€ã8D£Q¢Ñ(S§NÜìÈP(D8ƶm?©ëú@?EýïÒÌHiUÜ5;찫^©®®¦±±±Ãõ³gϦ´´tž)!„B!„B!„Bq¦pÛvSÃî¶I0 ]×)**B×õn×aÔ4 UU),,ä /$ûË‘#Gò©O} ˲hšægF@·çsVh² p3 Ü¿»ïUàQ!„B!„B!„BˆÞò² =Fiš8ŽCQQQ‡à¤eY~02‹á8¡»Ha"‘èrŒH$‚mÛdggóä“O2þ| ÃàÀ|éK_" …Ð4ÍÏr,++£¡¡¡Û`æY!KË‚Lªèõ8ý¾ûXøÔS}Ú}¯ÖxB!„B!„B!„âdyAEÇq°, ]×±, Û¶ý@aQQ‘HÓ4‰ÇãD"âñ¸_>UÓ44M#‹ùë<†Ãa4MCQÍFoȱcÇ ( ßøÆ7¸è¢‹8xð ¿ŸÎçWTTD{{û@?Uý/Ç„4PƒðÍ0”U!ï3õᇩNr{KB!„B!„B!„â”ñ²E!£išx4MÓ(& ‰ŽãÇQ¥CiUp³#EÜŒFp×sô2MÓô˪z·_sÍ5üùÏF×uî½÷Þãžk0<;×wˆàÞ:…À4“?ÏÚ „ÙvË-l5«O‡R«B!„B!„B!„¢ß9Žƒaäåå‘——G8Æ4ݺž^ÐÑËz ƒ†išTVVâ8Á`H$‚aƒATUõ˳zlÛ&''Ç?–ªªÔÔÔPWWçgëÖ­444PYYyÂsöÎå¬ã­—Ù¤‚¦AYYòƒÐ Ûn¹¥Ï‡‘À£B!„B!„B!„èwápØ/•‹Åüu½u?Xè•LÕ4Í2êºN,£®®ŽP(„¢(~ö¤GQÊÊÊü5‹ŠŠ°,ËÏ¢Lφª×Ç’’’~}ÌMMM”––òÄOÐÔÔäcÑ¢E¶+--¥¢¢‚¦¦&-ZDII ¹¹¹ýz.Bˆ!퀧ÏÃ?Ì%—\2ЧÑ-i „г¶@Ú!ÎnÒ'B€´BiÎd¦iv:zEð…éº 6¦ó---ŽÓ9sÒ ÉÉÉA×õÔ¹8$Ïa@$nðýƆ¼?çñìâgû´›÷ÍË—/ç‰'žàž{îaåÊ•,Z´ˆåË—³zõj¯á())aåÊ•Ô×׳|ùò>u!D?‘v@ˆS'½n¾eYlß¾} O阤-BÀ‰Ûi„8ûIŸ@Ò!¤8Ó˜¦éC%‰n^P9ÉàŸeY|úÓŸ`Ë–-€[fÕqœn3!½ûhšÖ! ’diÖ|’ܬÇÓu¬žR!ûåì>²ÏÇŠŠ ÿ ^QQÁÒ¥K»½OSSÕÕÕÜsÏ=,Z´ˆÂÂBJJJÈÏÏç‰'žð·[½z5ÅÅÅSXXÈŠ+¨­­íÐÀ!ÎLÒqêD£Q üÚù–e±mÛ¶>­nI[ „€žµÒqv“>¤-BH;p&2M“‚‚¢Ñ¨_æôXN6ð¨ª*?øÁ·¼ªmÛX–E(êXL£ë:–e¥Žå8'Œëo¶íOG™ÕxŽAÎãÅ;ƒ°í–¾ö:ðØÔÔÄM7ÝÄ]wÝźu먯¯§ººšüü|²²²¨®®¦±±ñ„ëAÖ××SXXH~~~‡ëçÍ›GSSµµµþvžÜÜ\òóóýã !Î\Òqj†A<' ‡ýYg7nèSë–´B8q[ í€g?é!@Ú!„´goÜIÓ4 à  3¸¨iÚ1³%//~ðƒ|ÿûß'PVVvÌ £§ªª*õ‡e¾lÃîŸ$·Ìê©<†Ãnà±²²cY×:þ]¯~üê>º×Ç;3úúzV¬XÑe½Ç’’V¬XÁªU«¨¯¯÷€cÉÏÏgåÊ•ê-755ñÄOø Jcc#@‡Æ ;;›ÚÚÚ>= Bˆ'í€'ÏqÂá0¶mDZ,‹‚‚ÇÜÌÆp8LYY±XŒH$âÞyç~]H[ „€·Òqö“>¤-BH;ð~H$z¼iš8ŽC0¤¦¦†PèØ®žf;ÿ"‘ˆd,..&‰ôh?ʽzë;TÖ£ªB(Ô÷ýiºëHVUAZÆ©aQÀ8ö]›g7³7goŸß«Àc}}=«W¯& uYÀ5]~~>%%%Üyç'µÿÕ«WsÓM7‘››{Üÿ˜=µ{÷nJKK)--íó¾„8“yå·nÝ:ЧrBýÝlݺ•¥K—RQQ1ÐOˆ>‰F£D£Q†a——ç—Sµm›¢¢" µ€·÷ŠD"~ Š¡C‡úµðßÏNUŸàDeà…8ÛÕÖÖ²téRüñ>•éï¶`çÎ,]ºT¾ˆsž÷™¸sçÎ>•:ßüq–.]*’âœç}&îÞ½{ Oå„äû§†ŒʘawÇ¡  €x§õ½ ïàNz·’Ùƒ†a`Y–¿Þ¢ªªÝ®ï詪ª"‹u¹>cš&999D£QTU¥¨¨ˆ@ Ðá¾wÝuWïþƒnà@uýÔUb±™ŽÑ¨›Ý|컕––rç3wò×™íÓá{x7¢|"‹/öë0÷d¿K—.eùòå,Z´ˆ|¬¬¬>=@€ñãÇSRRÒ%3SˆsMqq1+W®dúôé}*ÇtªÚ€éÓ§³råʵ]B¼ßx3» Ãð×uºº:"‘uuuÄb1jjj0MÓïø¥—šPÅï]uÕU'¬H0NuŸ`åÊ•ý…PÞ¬á믿~ Oå¸NU[0qâDV®\)ßÄ9ÏûLœ8qâ@ŸÊ1Êï×_=+W®ìRºMˆs÷™8~üø>•c’ïBœZ2f(c†9ŽC ð'°{LÓ$û' -G/ÛÑêcS/€é­Û¨( uuu„B!?©ëúÉ­é8Ét¿¤ÊJ707 Ï-8oííx>ý­SVe"áÆ;ËÊ@ý8W¸×{/•÷Ó‹£õµOЫÀ£DìüÆö¨tÞ6'šAX[[ËM7ÝDVV¦iRRRÒmÃÑÝ~äK‚giÄÙ,}6XwÌc̲ò:nEEEÄãqâñ8‘H„X,F,CUUÿg$AUUB¡†aøét]G×u¦L™Âž={úié–´BèY[ í€g7é!@Ú!„´!ã8uuu@j\+v,Z–…iš (ŠÛ‰Ö\<–p8Lee¥¿/È©ª*Á`°çû5M7½ÏóÒý¼²±Ç Zv´íÞ?™¶ížGrì/€xÙX÷|NÓ„¢"÷B!ˆÿ Ìg¡ À]2/Ͻ½?õ*ðèÕJö2=¹¹¹]ê({Ûœè ¾|ùr/^ÌŠ+:Ôkî|Ì΋ÁVWWw»½âÌ#í€8›…ÃácÎøòf‘åååÇ)**²,lÛ&//p8Œ¦iD£Q4M;a‰`0ˆa8ŽÓ%ðèuÒ>ò‘píµ×ôÓÒ-i „pü¶@Ú!Î Ò'B€´BiN7Û¶1 Ã_?Ñ (z™ÞíÑhÓ4 ƒ~U.ÏIe#&y“ªª¢( š¦¡iÚq˵vË0Ü螢¤Œ±˜{ ‡»–XM*Æãî%]^ž{)(p÷{²¢QÈËÃYvá°{¸xlÔTªa’e¥–g<éÄQÇñ#ˆŽã>TÃp†B©¥µL—»Û”•¹×÷%®Ú!½¹Ó¼yó·öó‰Êyu‘÷¯®®¦¾¾žÂÂÂ.%Y³³³ý eqq1,^¼˜¬¬,ÊËËÉÊÊbñâÅýû¬!N;iÄÙʶmTUõ;O±XŒD"A"‘  ¡(Š¿M("‘H ( @Àï`TVVî ¯ñ:{Ç tÆb1ª««ß—Ò! gm´BœÝ¤O „i „ÒœnÑh”x<Ž®ëþÄwMÓüÊZUUUâñ8v2ZåYAïŽàNØ7 ƒöövÀ»RÅnö8øhn ¯¬¬ã:ŠŠ‘ˆm  ylÛ (ÖÔ¸÷5Œ®ë/VVº÷³mwß–åîÏ0zV®5‘ qãèŸ]€õ¨ªr¯vnœçgdF£n)ÔxÜݽ㤶ë±xÜß_<î0UÕ=íH$µ™:Ô,¨\í>ŒX,uÜ^&ªvÑ«ÀcVVË–-£¼¼œÜÜÜcÖ>®¨¨ ¼¼œâââÁ¹ÐYaa¡_¾µ¤¤„%K–øiÕõõõÇL«BœY¤g«h4J(Âq¿ôD0$ ú‹s{ÉH$B$ÙˆF£$ ªªªzlìÌ[ÄûL#mzÖH; ÄÙMúB¶@!íÀé”H$0 ƒªªª>UUý Ho’¼išþú‹éN¶ÄªeY~Vew“Á`ð„•¿:°íT_wb±ŽEUuƒu‰„H »ÓSú} ý­ó±LÓâ…Bà887.!üìÍ”ÝìÆ7½»Æî§Îþ£¿ü¤õT9BèF’øãpLÓ Föˆã¸Ñê*?{1sOMÓ܇éÑsÀx³ãu'ó÷D¯¨­­å®»îbõêÕäççû)ÍÕÕÕTWWS[[K~~þ ³"½+O$++‹U«Vùͼyó¤áâ,!í€8S9Žã—ð˜¦é—„pÇ/•êuмmcÉŽŒa;uR¼5ûxrngçX­÷!i „г¶@Ú!ÎnÒ'B€´BiN§ô²©éÒƒ€à-Ë¢ªª ³SÙRUUýLÈž„B! Ãè6Àx̱1/ó0ì5ëÁXšå¨D“S«ªHEæ°m(*pc—'Œ¡ƒÇݼq¸pØÝŸªB0Hâú•(¯wž … úÍ¿ZŠc¸™‡ŽeÊü¡AϪªñ^7 ‹ÿ„ PUŽNQÔÕ¥‹ƒ—z‚3º>o9ÌþÐëÀcVV+W®¤¼¼œŠŠ ª««)//÷oÏÍÍeÙ²e=jNVçu$…çiDoyeMûƒ·6£¦i”••ùû/**" ù1Çq…B]‚‹ž“š¹ÕѨÛc((pÿnh8þ¢Ùg0i „Ò!@Ú!„KÚ!„´½—H$üñ­t^–£—ͨiÁ`EQºŒuyñ»FÑu]×1 p— ò‚=¯K/‰ö(]ÏH÷‚A÷.Š’ZGÑümÌ;.&è¤Ö:,(‡š‡Ö£Þze÷; ݲ­‘ˆå3MwEMƒš, ,÷aú™ŽéªžÍÜ]„¾BðÐwQ_p0’ËLÆ0Ý“**rgzÍÔtªŠsë× ‡S§sLA(ët»iºÇ“]NóX2úºƒeË–aš&¦i²råJV®\éÿ}*‚ŽB!DoÙ¶í—7í /›±óï¶mF)((À¶m‰ŽãH$$™öf|yÙ'[j—숗i¦zF^iÇq{šÖ³}!„B!„Bˆs’7^ÖݤùÎFUU¹æâñÆ¿¼ÉúñxœD"áW +(( ÷üd½2¦±˜;Ùþ8lÛMŒFÝ!³DÂ*++s/–ñõŸ@›ÝL"án_Suá¢aþJÔP[ºî^,‹ä“ç¦&ƒ·ápêÒýså^ªª 4ãÏh_+tó’É–…ûkj܃{'à8îJnä8·tâ-Ëý5+ X¯òÖ‚4 øáóØ´izÏ_nô:ã±³ÜÜÜã®ã(„B ÇqˆF£hšF"‘ð¨>o¡ìÊÊJ¢Ñ¨_F"cY‘H„`0HAA‰D‚D"á/¾í]ø%VOȶÝ7{ɶÝÞ‰W¶BU;öòòÜNM<îþ¬¬tïïuFb1ü^“Ç4Á4ÉžÐ/™B!„B!„@¦iúé»Ó“Éûžô€¤7Iß« ¦iZ‡1»«¯þ)ÿò/Ÿ§ºúÛ¶} ÇIÝ%ùÓ2!À¾òV”?>D àÆûN|Tw;Eq‡Ûœd)Uï½ê¨Ý><]'dF UyÅM2ìÁ’Ä㩼‚Þ®ödÛîñjj¼|ÇJ­ªÜ– ô•£„Æe‹¥ªÏžÐq’D«ª ººŽêê½;ñ$ < !„8+˜¦é‰UUUX–…®ë~ÇëH†A0IJ,EAUUÂá0º®û¥S5MÃqb±˜´ …B„ÃaÇéRR²,,+5eè“W]E0gʈî^‰WÇq{ é3Ã"7@Ø]oDÓÜ2 ÝñVºN.jšÛ ên_ªêö@ ö|ä#\p]!„B!„Bœ[Çñ«}õz‰ N¼ e<' Y¶ìüã?sÁcTIÏx|"ŠãÇ?Âðáƒü ¢ªêþÔf5a=¾“`ë X½†3b>Zܽ¿ã¸ûM»Ûy‰œ^â G×Ýa²nï¯i¢xÞq¼€èñ$©J°'Ü>h@7Ãx–å>ÆhÔ½x9 ^NCtùÇ¡x±äe‚Žƒ€* ŸÖs쎅Bœ±¼’·¾¢¦iÔÔÔ‡ÉÉÉ ªª Ó4 …B~¦b<§2½§8,**²,¿³ ‰D"fcE£QTUí0ÛK×u¿¬ª®ë0hß›8‘7#â»ÉÛº­;ïõz«»^Åñ¦SÅb'î! !„B!„Bˆ³–ã8}Uç’¡½`š&Žãøû¬©©AÓ4LÓSÁîv(YmTNüáƒ?AQÆŽM [Ø„if }`Ê–íD_ú.ú47hîÏ@À ê©ê±‡Õ¼ÂcÇsŒê²®N•ÑÂaw{]O­Œäå „Ãn@Ô¦ó2#9Å üuº¾ÐRù ŽãÃ0ÜK²âjòôFôù5;U$ð(„âŒã8¦iúYŽŽãøÀ_“QQ€_/Þ«'ß9èø™à–^í\ôk‘m;}Ū*FÙ6wß}7s†w;*ý4s¬Ï¼U¦%ÛQ!„B!„âœFw<,v©ìÕÞ]ç²­ÞZ‡¶íf:Ô|â{(Ï¿H°f0Ñ>ƒóT6uÙ_B™s JìÇÉ{Ž„o\ƒHÍ£O$ÜÀ›W8Ì_±Ý­ZÔšæÁ ‚û·ã¸çUVæþ}Ìu*ÓY€ÔNò¢âf@FA©J'q/Þ1ÏxBqF°m›‚‚4Mò,œdÏ¢ªªªKçHUU*++ýÎŽw{è854M£¬¬ ˲(((À¶m÷~–åö tl›P(Dýk¯¹= ËÓDK(ýóHþœ“^ª¢·EÝ…B!„B!„è'ñxÜ_¦èdJ¬†XKŸÏoÛ6†¡ò裯óÓŸýDô18Çq‡Ð wx¬²”¢n¤ÎqP^}£e9FûZÚìzÜÎɘºî£Q7˜Ù9¿ÀqÜŒHoÅ¡þ¢ª©Ç‰¸ÇöÖ›¬©q¯ïQÐÑÓ]‰Õw/ú• }ȽZQÜcög õT’À£Bˆ÷½h4Úe¡ko=Fõ8=EQºÍP<&Çñ;\~}ûDÂíY%ƒjUj4êö´4ÍŸf¥¥j#$ÞÒ‹'ÓÛ8©Ó$p;5'˶%*„B!„Bq®q‡p8L"‘ ²²ÒK_b(µm*CÑ+jšîß¶í^Å"0mZ5uupàÀ "‘ˆ_ÌqR‰Þïª º“\’(9nÚö]ˆ57Úq <¶ô‹¼’§Ñh*0ºAN8AÕ^ˆDÜçÀ²Ü}Çãîq{ ,£ÛuQpË­Uqàß?„Sº¾#HàQ!ÄûP4%©£®ëÄb±åOtŒFS#_2C±Ã'u"á^¼Úºî—NU'C‰ÅÜU^žûÓÛqÚñUUõ;l^'<5åU“ØØN^0·SÔeû…B!„B!Ä"‘H`Y–euX®¨;–åÎÁWÕÔp™a¸6ËJeÚv€qãÖrÛm­|îs£‰ÇçqÕUøûöÊ’Ú¶»TéS­Ã eAô‡9t³2Réc}šæîÛîƒTveUÕqÖWìŽ;~¢û€ îþªªRÁÔ>ó€*ºzÇ/ÂÉóŠû¼NšÕOû9ŽŒS!„âøLÓ$FÉËËóË=TUU±yó*++)++ëvÍÅîX–`óøõÞM3ÕIßXUÝ©J55 ¥µÔ~TÕí]¨jê’&=jY©à£wüDâäžÇAƒÜKç})ŠÛ¹²:uL3Õùó¸ V@ü“'ÙéB!„B!„g³ÓØ—eYljD"ƒÑh*°hšn¡m»{½rrRÈ`0ì»÷ÞÕlÞ<ƒë®›…¢¸Û¤Çyãc¦™ÊžTUºÔ@õ2­ÄÒǵ¼lÃÊJ7 ¹Ã{ îy—ÔËÃ-mÆ ì…œäíÇ8~¿U;Ñ9qƒ“&P€»d0û¾‹‘À£BˆaY–_÷=à8Žãðµ¯ÝÅüùˆÇu,K'#c-†¡ù ‡@ªŒB<îþlsH”ï%8íEœ·öbÿ7}ºÕ½Ñ[:],æ^‚A¯>ªàômöyÇ© ( ŽÄqÜUz'¤¨È=g¯UTÔ)8ØDÔ,ê`ÞŽÛá)ëO©N^ç´½žaàvFò ìJ̃ îrŸÇ‡ž:Ðÿ„B!„B!D?r‡¢¢"¿Ü)¸cpš¦‰D…B8¸ãG†áÃaw\É0RãWšæòŇÒu(,\G0h2uêcü×@ÓRc`¡Plj÷Öóq¶6¡ëîýÍã¼z»vae¥{~±ØIN¶·ÃÍr¬Jû¸ùOÉ‹”üÙ“óÕ€: !yNƒp“ úâ4¬)G!„ýβ܀`QQjVS8 ‹­"p¸õÖç((˜aÂá8eee„Be<üðyçaƒn‡¡²2•¨XY‰=¤:‰Š£†€ÌËuÁXœ=G‰>Jâ{1ŸJâ®×Á²°æÜB8|üóWU]×ýŽSA»o¯óäÕ²O§iÛ¶Mò÷>Ã˶ÝΗ· ¤÷|tæ=_î9@¨ *CÀÜN…æRÇö¶õ¤^\Õ4I•M&ëϯƒÊŸB仺mÉôMÓú¿ŠB!„B!„è'ápÇqºu]'ŒQTäŽYyÙˆ±Xªd¨WàËK-%cÇ6`YÕÕã8&?þñ ¼ñÆüë(¦gCâ8X/´`ÿf ês¿ 6âßQ²ó¼{[¡«O•½4Ü £BÇ`\,y1q³!û;ÙÛR§eÉó7Y” B4AÝcðÂߟN(ä #7O$±re.¤f˜¿ÈÁ¹ôZÕSI$Ü@ ¢¤j¿'nÉ«ô°eK1‘HÇrñxª3fšneVÛv×Öv-3gŽfÅ ·“fÛŒuƒ‡êˆÛþ< Á>”Ú¯¦¥Ê±ƒÉ Γ}‰ cÁybA0šŒJžÇ]¾'U×¾¦&YÆ¢Ìùî>'­¶}¿ ÿ¹u8 7-èÿ.B!„B!„¢Ç!ú•»4M#‘H i¦iÇQUÓ4ùæ7ê×%îøVúz‰ÞظãRUU©Û·n]Åöíð—FwÛ²²´’¦ŽƒD" Ñ(hš‚˜èØ- 3 mNÆqËi^èxÁ?7 į@†…› ÙTÜ5O–F*h¨‘ ŠZÉýéYP1N*€yŠHàQ!D8Ž{I/!ê˼`Ÿm»ŽI“¶á8KPEÑÙ¹³ˆ²²2t=F<gúôL.ü\2¨7‹Y³Ü@ž¢¸¢ñÔB†‰ÔÕu<°·Òu(±!m:Lwÿtƒƒ3‰'ŽRpkuu`<6çòÿE×ÝN–WNBÓðK>„Ãîýu]§¬lŸYèu´,Ë=´¦¥îïec*ÊxV­rïïÍð ‡A ê» m‡È`< ±AüLû”=¼è>·šæÞ/r=¨ÉÎBìk`üÄç¹} Íûm°7BøMÐ&ùÿ@›å>‡‰„{nÊH°îyû ^‡@MÀÏjÇpãg^d:’õ(„B!„Bq&±,‹@ à¯×hÛ6ñxœP(„¢(ÉòXªªbÛ6oþ••îØS^^râ½iú3î½±=/ø§ªHÄ1M‡mÛ6pãáþûS‘·`°Ó %K…Åb1Zˆ¢¢ÔD{UÍŽXT”¬ËØŸ¼À≨@¯í;\˜IDAT ©ìG7;2˜¼­7ë=öÇZP™¶?7 RÁ *Z¸¥c;?ç'›ÙKxâ,aš&zo‹a Ñ / æÅø"·¨—è-2­ª°{÷oøÃ®â“ŸœÊ† ßäÝwÁ'?ò¯…B„’©„eé5’¼` Ï;h<î ²²ã4ÍzÕ‰—­èGkÖf`îß‘D£3H¼ìÆ0½ôѨXÔu7SÓq`Ó¦,öîÍ!x9n§"’:¬§¦Æ}~‰d9ØÇÀlÅ/1¸Ÿïe&þl#¯R pî{0¬ï¯€v¨ÐÁí0ìtïœÁ02ÜÇ¡Å@uܧÇ,ƒØ¹û¨š@ß ‰¡Ps+„ë:=U!ÜR¬z„ ô4!„B!„BÑc‰D‚h4J0ôÇÙÇ!‰D°, Çq…BD"eÜzkj\+Õ6ݾšPU,ËD‰xy EA×ub1Í/»Šm»kUU¥v»…‘8ÁdR@(äÞä8î¸[—À¢…;ffƒšü0wì*=»ïTðÖIìI柚<'7gâ–9wíÅ“eÑûr«ÝQ’—ÜqL’çè=ÆHòüABˆ“Çq‡`°'S5„èž—Ñç8nßC×SA;]wƒj^buõnºéwÌšÕÄw¾GQâqMÓ¨««óË<˜¦‰ªcúOzQùÊÊTDU» ,ž,UMe+†B`¯…Äÿ†ûyÑÜŠ†±«ÝÙU¦ «V-dÁ‚”Š÷;ˆûÓÂídè –Aü{îóÔ!m"î¸ ÚÔägzw¤ (A(K®ÉhÝöBФJx=õ¼ýyqY/&BÙ | ‚*õ³PÕy>‚¸»½oô©þ/%„B!„B!ú‰iš‰Dˆ¥ÕJU…šššÛ꺎ýZ3ª:ºCÐ/Ɉ`e1¼²¨ºž *¦øFªïPSãfvŽ^~ùþû¿ÿ×_”É“ç2~ü,˦²²’`0ˆišhšæ±mtÓtOOk´íTz¡W›TíMm‚“‡X;„¾„û«ÔÌÀÀ~´Q`=æ%Y渳—TÜB^½t’Û™  å܇ ±…Ç?¥`0¹&f…{L¿šl8y‰%©$Ï#­Sâ=]Þë¨'ƒ¡^ç,x¼L:d?w”WK7@!„B!„âýζm ÃÀ0Œ.AÇÎTUEUU‚ªJ´àP§~ëRõQ½Jci“þ×­û 𠮸b6·-\ÈõwÞÙ1‘ ‘pƒÁJà¸ÉªêîØj hÀµÉëë€îžƒ;FæÐóu O¤¬ï»@KžO7ÈçeILõ˜Oñ0(àuRã™áä¹öf}É“$#ŽBœlÛökuëºN"‘@UU‰¶m‡q+™oÛ6N²…·,‹iÓ¦ ôC§A4êÇýü/*JÕK…ÜÉH¶º844t¬åî±,‹p8ŒeÙ@“'—ðË_¶ríµYŽ©w,Úv÷µ¼hg(tò+G{e <&į̂îfNÙ¸C7‹° Ô pêöèGÁ9j9T>y¿€š\P"É}WÑuÆR2£0´-y>6h÷‚Z ìN;^(Š;)¬C²r·# uº.ýT¸ôÒ6LsÁ`oûÖ&Œ°Aù¸r&ŸÈuFÔ  á8Š¢ ( kv¯á ò¹7ïNB!„B!„ª  MÓˆÅbþrFNjŠF_ðQ´ÖߥnT¨©Á´m4M#a|ñ‹S‰…þÀ¼Ÿº%¶æw®ª§(ncŽÎ[ç±[ÞÊJJ71ºôìBo,0€;ÞVC߃E¸Á̾½àÉóÔpÇô ’û®$Œô¶3Óî{:•‘Jp8Å$ð(ı, ˲ƒ~™T]×1 ÇqËUz™Œªª  …Bù÷3MÓ¿oee%ñxœh4ŠišÄb1t]'wK`Æb1âñ8•••üò—¿è‡/N±pØ ,–•¥‚ee©à–|ô&8yë zŸäÞÿ½ô v0¤ªªŠ¼<رc×^;"u@Ûî©TU÷€šÖ1°è¥÷“Ñ6O÷Ã8H×?ïÃØûNàöª’¿‡q?¨½r î‡h2 Hî‡| ];*h7‚¹Ô[!Z Êë FHÕ<ï®#£& î ,%yꩲô¸Ñe’š­£[ªõ¯rB–iaÛî‰Y–EAÁG0Œüö$‹ Ù;k/•c+ù,ŸÅqlÛ& ( ¡Pˆycæñ﯌à™Ýýõ_N!„B!„Bœ†á.ÖWuËu #ï&rW&¨øI,¦iú”eeeD£Q6Ü}7ïºËM HÏLð轋’7ð˜ƒ?®v\ÞíU¤2 ½!-Ž%F{ìÏ5ÓÏ3˜¼xã’Þ¹‡qÇ'½¥œjµ´Ó‘i‰…8m¼ÁÛ¶ý išD£Q?)‘H …Ð4Í/Y‰Düï~÷Þ{/ßùÎw˜1c3gÎdÞ¼yƒA¶mÛÆ7¿ùM®¾újÇ!SVVÆW\ág:)'›]&Þ—¼,EpŒ¡lôvœŽK&B§Œº$Eï}¯•gžÊ‚âñ¢(ŠŸ!IC¡_ÂAÓ@Ùÿ–º;ñ¢—k³z/çÕ=÷Î)¼®÷ƒØ+ŸPFêÃ×InW‰ûÁX„ÛɈy¸Æöä¶Éò§ÉãÅ“·ë÷Ã\»´çS§¬x3ª‘Zœ¹Ë—ÜwZi:–QqÌŽSz²ªªù“"‘@€ßÍþ¿Šÿ UUý÷¾×躎¦iÉ’K{=´ä‹~éµ—ø‹Œ×ÔÔ¤Ú[áåÏä´õ6„B!„B!ÄIs‡x<Þ£,ÇôÄÛQ V‰‘¡¯¹û1 ï¢ …¨©©ñ^°m˜8Ñ@ôÆéN.¹ñ˜ºŽö';4¥“ZóQ!5è!ª¸c‡©Ò¬ÇŠ™žÊa1…Ô¡WÖÕ!5–xº³O3 < ‘&3þÝ|ík“hhh8n Îq?𬬌x<Ž®ë„B!,Ë"cY¡PˆD"á¼Y*uuuÄãqlÛ&//Acc±X–?ûÄ[¯±¨¨EQ0M“±cÇòóŸÿœK/½”©S§òÅ/~‘¢¢"æÌ™ÃÈ‘#ÉÉÉáüóÏ÷?H>ûÙÏòÈ#ðÒK/ñ™ÏÜ7ÐO±è%Çq/¦éö÷§ª¦>¼5ÍíƒÇ¯zà•áõá55W×sá…CˆÇ«°“eö?ú(Wßx£T´S j°w4ŒÕRÞÉtÇ['ÑÆ Öy‰ŽÞßé% ¢¤2ƒ¤‚–Þl!¯@ ·3Ñ])R/èè-N}‚X»÷œyÍÖ9~$æ>—8nö¡ªªØŽb)~¦¨™0Q-·ç8ŽÿÜ{Û' "‘Á`EQPUEQ¨««CAáWÑ_ù÷ó²{KKBkþÀ^r/O%½Þ§B!„B!„8u¢Ñ(Š¢øÉ]Äãþ¡ˆ“øâŸ°ÖebYð׿6qà ûP”CD£n%þñ¹èºÎ„ ())AÓ4?(ZWWG8FÓ4Š‹ÿÂ}÷]F,ó3(øC7‹-/ž|òÃäå è—YôP<îÆýB!7بin&cw޳¦4‰DÃ0ü`#àw4>ÿù}lÙ¿¾÷Ë©7L<÷Üã^¥Ã¢ÑŠÎcá³±Ô‡¸‚Û)ñUöxÁ¿ºvPº;ß©õ -ÜÒ é3€¼}è¸ÁÉîf…H•gµ8©šïŠâfmMáÐc‡X—XçO 0 ƒ`0H4%‹QPP@UUápØŸ` …üb,ömâñ¸¿°·WÜŒÒô…º;/ ^VÖ+]w¯ùKõðú)Û½B!„B!„èƒxûOdeµašE˜Éˆ[FÆ[=:çŸÿ3õõÃÈÌ,AQ2qX¶l0ûö}‡… ogÉ’%lݪã8:™™`ýúåüßÿíà7¿ù>cÆü?fÏÁk¯ý/Ÿø„A[ÛÓTU]Áu×}Ð9xp3÷ß¿€pXáºëš)/ÿ#GÂEÍå7æG?jbúôõddÌD×—sèжÿq/ ÐÚz ÿùŸ Í ºýêWqÛø§ýnqs,ö•OfÕäçq."ø×bfO®¥²Ò}-ÊÊ þ ÊÐf‚ùk°Þ;kÛ$”ö"‘%¨ýM&vA  EC‡þ©ÑD"PTK– ôÿ®s›´,÷½PSãþ]V–\spÖ+(—Nw¯„N5pßhék/ªj*[R3€¹kÞࢦëaðYÒ2cð}R F{k+&ƒÙ:üÌC/®Ø-/HèÕïi¦»ç)âUGň»‹^+ŠBQQQò)Ѱm]×ýu ಲ€ÖÜVF|ŠT¢Ñ¨_b¶/ë% !ÄãÿlxÃÍ ©« dïÉè3<»8¸_¾OvÂB!„âœöûß?Ãg?›M[›JfæZb±D"D*{'öOÍ~þ@[Û¶n]å'§xãb=ÒÓìÄÎÜñÅô¡µºNûµI•kUÒî©ìI™×Ö’ÀãYÈ¶ÝøDo²¤,Ë]GÎ[g±²Ò ŒƒnœÃ¶Ý`¢m§Êšjšû{0èÞ_ÓàŸx;FpÍ5S6l"¦ ¾Â÷¿ŸÅK/å2dÈ>rrr˜9³‘W^ù O>yyyyØ¶ÂøñßæèÑ47OàÅÏ'3s?‡ý”Ý»#"‘Ž£³dÉ!n¹e†ÑÈÔ©·òúëgúOŸùL6eeS¹ôÒŸñ¹Ï9D£&+W^®—ÚÚm46¾NCÃg <ûìh¾ùÍjÖ®ý-_ùÊ?rÇ×°fÍ Ÿ;îÈâþa9PÉç>7œ… ÝõUU%†D"‹ææŸ±|ùÄÿ½…†ƒ¿ ÚðSÌÌ…æùϯ¢(üϯíþQPàþŒD:.Χª(;È[ñmþ”÷-æêŸÜ ¢ª‚úÛŸA}=y¯ü-k‘«ß¤¨èÿ5sbã)ZôwÌ5YTUACÚàWM „Ã×ôÓs’i&ãˆÛ¶aü6‡à­T?:¶U»#7´,”$ÿ¨ªû†«ªê8Àûý« ¼£ù¥P~9ê nVÏšãoº‰ñŒOÝ?=¨&ÿ¶H•9µ“בªáÞe°eËf0£ÃÕŽãH$PUÇqüR§¶m'ß[aªªª444à8¦iF©¬¬L•‹M %g.xÁÄX,æÖm×`ò­“‰%{2Þ"ÚBôY÷=¡ÿXï?^éf“^;H­;ë•ñf…vþ’çÍÌJ—œ ²wí^޼w„ñ×gãèY}„1GÆ••ÅîÝ»©úh<‘—³_F ªüýO|ö²rÕÏ ŒŸ)\wèsl;8‡_ÅŸ`îð¹|¬ýr–º€êO ô|†sp'éè¤>7kèÝx!„B!Ä9å÷¿oæ _ØÇÁƒOpóÍdÙ²q\sÍ;n¤ëîwÅÊJÿ;c4õ—SUÕ;)&§&ø§Ÿàwo¬Q¾3µ$ðx**J%Iypªš^’Ó &z‰šæÞGUÝûƒîE×SåN½ £—¨(p啉FG‰@fæ6>ñ‰o±mÛ]45­¢¡!ÂÈ‘ë9p`" ÞΜ9Ÿç#y(CQLFšÇÇ>VÍs‡Ȱaw±vm/¿üg† ù?>ñ‰E|îs•Äã#:ô Î?ÿ/Œñ g¶mó§?§­Íá¼’©S¯CQ?‹)PVVFEEÔRP°„X,†aŒæé§Ÿæ«_mæk_»U…¥Ká±ÇÚݨÐ0 ^®`Ïðw¸qÚãn~’Ûn›ÅàÁº»ÎdÞ íaP/C„…þ Eû•Ãðe7@¤ÿ¾ûÇû»¾@ÞB}Žã^:0ê:Š®Üî>ÏsË*;ß úÔÙ`Û³H$fù¯µ÷ºk×fû™ûú¦“˜ËIòêŸlàͲ°ŸÜ„ñÇÉ0}:̘A<î¾·*%DFذ_…‰*,èô"i44¸o6ï´I•)0 ñä§uðKüÒ/=ñ>ú ÓvNãÒ5—R4¨ˆ±Ÿ{üóínñe¼cqÌÀŠ4ôÊ—ªªŠišƒA¢Ñ(‘ˆ;aÀ "VVVb†4tEQü§Žã ÑuUUý:ô^©S¯$j¤î{WÉ@ô¯ü°€:K’g§ã¤%ÇIõB¡T5·ö²WúÛÛ&t÷ãUCˆÇÁz bãÀÜæfÐrK@j6˜6Ø î} Æo¢½½3fø“Ÿœ ðФns°§ä3CòÖ‘AÔd´3eȲ‡î¡¦þ233adŽÎäW‡ÆpÛÑF®ÚyˆÅ£š©=4€? kaßè}\s¸•ì©{øÃ¾mä¾}1oz›Aûòp†9Œ>2šA{ ÿ>f=s÷Í¥ŒTì¹-g -‡FnÉcõ ßòúÑ™\ô žv ›˜@nÛ[,h|š›Û‡±„‘üfø.;8°ØÌÔ¡&ZÇQIf×áO±îÐ^al~˜òârŠÂEpíÉ?tÇq°‚y”Å˃„Ãab±EEEƒA¬ä,‡`0è—=7À‰DÐ4ÍVUU¡ªªŸ±ØïþǺý¤Ê£zƒµBô'·É÷Ê;}Û]O8Nê#ÊqܦÁ¶;|aÛ©IGà~¶†Û¨¬t×N÷<Ķ=™$°`A³f5QQ1£Ã6wÞù:=6•!CÞFQvÓø?3yn÷yŒÈlaoû Æ_´•yïäÏ;²Ù;j/;}’?¿ý¢Ñ©Œ±ƒ•ÿUÂÆí3wœÊ¦AÓyu_&­‡²eÛ$¬—þÊÇ™ŠÊ•làyÎc$®A6ÓÌKŒåKØ_ÀW)âÇ”óжýŒ:›Ã­³ø°ò/m·Ù5Hçò–ÉTMØÄ5;.fÞ°F·8Ì<’ Cš9rø|FeѼïiϸíÿûŒÔÈycÚÉzg/£‡ü•UöX7æ:²›ZYÖø'þÔ6ˆÃä21ó 6Œlàç?Èö¿Ï5løû_øúõßæ?ÿô.£³>É»[6“¿e;,Èz•On«ââ±<1ä3ÙùïeâbçW\OœYsäžaÄq~F[Ûµ\·÷ŒÁ aÃù‘ßRå\Ͳøqxë^z›’7¼}ðfÆf4rtâ³ìh»”~z Ï·åeZšÇ³ïüöÓÃùìß>ŒõîTB·bÎØAn£±1ƒÉ“oBQnâí8ügjæÀ­·Â‘ ìø È›é eaÜI:áäu © GoYT¤–v_Òîç©K^gã~é§í#žÜwNòºJܬÊtÞLáDÚï^ÉW'yNFòwo2‘ÕÍ>’ß%ˆ¥ýž~» õÎÍ •ÅÛù~AR¥ÛÓ+)¤—Z &_z7„„íœõö£$·1’ÛD’ÇÑÒn×Òö¡&÷cÐq¦µ×§"íùò^/ìp®mdrÌ‚:Ù½XÀÙêhpÓì}8ÍÉmFkÝëÌf÷vö%;Ù½Ÿõ6(- Í{ ð˜ë€Lˆý+DÿÚnÐǃ™Ê>°€šÎk çC`ÿB—‚¥ýKP†ƒµB—@¢ œ}ɧ`2˜;€­À^ B×AÆ"„B!zÀë÷0xæ5 ¾ýå79ðÎ~2îa-:3fì`É’Çù·£ù _° y â!(‚¦YMl›º×*^ãøSޞ¸ŒqœW|sæÌqûß^ÿØÂ¯þ寵èM’ô¾G¤axœ$(N3.ðXZZJEEMMM,Z´ˆ’’rssú´zͲR@oà0M­¯¨i©£dô²Óc^`1}à;3MMsG#&Mº‡nâ? '. vÿMÓ$£ª*Š¢ðéO[„B!lÛáÑGoIn`Ĉ穭ý+%%Ghj‚«®‰ã88ð®»îFŠ‹ÿƒ­[·òøã·ò…/|ûï_ˆ¢(üú×k×–ó÷¿oÁ¶¾ý¥«¾ù~ZÀs“2I$˜¦É¾0›O¿ö“¿>™åW.çæ‰7“·7#F°yóf~>þç<´ã!ž¸æ êµzJÂ_—ËúŒ…®ë†ágñyk†B!b±˜_vضm²ÈòË™z‹L›¦éÿô‚†¶m£( Ñh”ªª*¢Ñ(555~c0DQ?ˆØX2êÝ93±Ç™Šý帋QгÁ)ïx3€Öc€UºÛ‘¯Ãm ^ŠÂ#€ë¾Á?V’¿fª—-h>àþT‡‚úÅTiæHÄ$äÑfÁw>ó6¿}soÕäpÕGߥv×pl<ÀÁƒÛyþùضí† ÙÇg>ó+&OžÆ¯Zþç;—`ÿvÿ2žç!làéµÿÎ¥k§ò°et ÃÆÒ<´™ß<ù~³i>Ã×òÂÖ|®ß½ ÇW2yòdvíÚÅÓ-OÚß–ÁöÁÏ“·%‡Æv‹í¸%Ç·_Pìý¹öØ|« €£yyŒmiaÒŒüú¿ `ï^®œ<™Êí ÿºÁ†¿>€1>‡‰O?Àž1¯QÊ3›ÙÛØÈ§´¢Æ¿ˆnÛì6Œ7ª?aüŒ?G"üßý7¯Z…6j¿þu† Ì–GþÆÞþ;¶ÿÊàÛn£~öeÜû9Ã0øÇ}Œìüw…{ÿÆË.fè3Ï0úÓÿÎg"Pßs_[M>澎E¼ðe–« ÔÝLíøG·’ooà†Ê‹‹S/¶VÇz¿ÿp{òçÿnÞÀîä#•Ž]l kMTÇq'9)ÊW° ) ŽHÞÚñ¼Ò—ú¨«s«¾¿òJÂÂmý÷¾9ÍNyŸÀËp†ÔÚÜNâñújé¼*ÜY·ý‘úÂïýw¨£c@®ógX©YËU¤² ÓÏÕ4ðÎ[Kž¯ÚiŸ‚ŽNK²[ëI“Á:s{»v!Xk“§» ¸œ·’´f`„Fñ ào»¢åÀ«©cèÓÁÞöP÷[!ñ<° xÙ ’•]Eÿ4@èB°¶€µ?P§Mr3¤Ÿ6Cìþ X¯¤Ž™̆ø“œê÷½É€nÕ¬íú»·Mh*(¹ÿ!¨# 6Š^ïøœy÷S†C¨˜‰½`ïM>OC¡ê2oscU6Äó€-îãs2!8¬L7ˆ¨ïgênC3ÜçD{B< « ¬­ NKë•8|NFF2‰Ä[îs¢Oi"?»“'ÚÎá!8¹Yà&zc?eÁáf¬íSQ†DÍl®aø°ƒ=z[¼_mãâÜÕ]ÕõþÞ§7Ù:Îw=H[ „8-í@¸ß†¿¨n0Ï룧ñ¾Ûw^3·ß>˜a-;¸íèƒüµ1†3%È¡ë?ÉyÍMdí.†`1|Ô†ÏÕA¦ÃúóZXQ÷ZÌvÇå kW>Žl-ÛŸ¨?Çûy¢ñãô¡¸†nn—ñgqŠ j÷RQÎ^Ãá5¥¥¥¬Zµê„÷+,,¤°ðôÍç6ÍÔ aYYªT™7€˜^š¬¬Ìmˆ¼`czÆ¢ßìÔ\sß}ä¬]Ë}î7ñú¡CyljjpiûóÏó£×_gÕ¬YDmÛ8x¼2†^c»ßÄ‹‹‹¹á†ø§ú'~VR‚•H°hÑ"Z[[yýõ×™üñSYUÇìÙCùñÌÓ_ø?þÕüóÿÄ=÷ÜÿÞq?ß[û[b±@€n»¬ïŸùóçsðàAr ÂVUv—”`&Ÿ€˜{î‰y½ÞªN­u4šJíˆD}³téRV®\9ЧÑ+½mŽù¸mR3•:0:¤÷òpíª âÏšq1ÖV»}¡@;öXþ d­ÙÄ¡©‡Ü4˜CSqéµ—ljÇã|÷àw™Ò2…§f=EɦTTnŸu;Ø÷ZG·R±¹‚/^õE†,‚7˜~ítf̘ÁÁáý÷¬eYäää°lÙ2âñ¸?QÀ Z–…¢(Äãq¿Äi]]yyyTUUQTTD$ñ×*…T RÇq:´ gØ:Œ)³ÖóXÓ!F7æÃsWÓ²vß:ô8ÉEQF·/¼Ÿ­ù™ÿPÞ<ÿMž9ïÎ?r>ç¿w>“›ÿ‘û70¤íBþû»KX¿c=Ë–-£¨¨ˆ:/•2iOÁWøÑ–óÐ4ß7ÿžÝqçoû5õ™Í¼óÙbåÆgX¾b†aF©¿þzÆ\r >ú(7Ür «fÁg?‹eYƒA~þïð™Ë.cüžb|ÃVþþ­oqpòd}WíX#]EE©ÚïÅãn¿ ¦¦ëHYAûÚÔÕuœ äÍꪩé¸}8œZG×ã8î¶Ç˰¶m÷XeeÝoçõ»Þçm©mÃwü™þçѧµŸÜ_ú¥Oàez¼L8ï­QjÂÜËHnVºÖ$¶:Eò´dTÐËòë!o®¤ c¤¯Ýn·÷2›½¥:d>ïr öŸ©õÛ«ªÜß%uœH$UVY×»Nv€ÔýÒ·Oo:4-µ<$¿ûüp/ìÝ‹õ–›ªüü9ÒüÖFn ñ§© Nè®IþcÔu°KWqààA.×ÈáÖVvLšÄè«§ñØcîwžœó¶=½¯Ã¹ûø\vœÊ¾}C˜<ù ÿîY÷·#LÉØÂÎŒ™œ6W/ÏàÝw§2cÆfæ>øù™ë¨?r>GçfÍ¥—úû\øÊ+\¼q£ÿ÷ÁƒyzÑ"ÖefbÛ6š¦ñŇfζTmNÆ:,hh ¾vm‡s­˜1ƒfÎôÿþÊæÍoÙÒa›œd9zÿµ ãØ‘‰ÓNÿïÛ¹èIÚàîÿ’ÕºÒþ{€ùóçóÚk¯õü?ìûHoÛ‚3½/t&ñ*5tþØöʼ{c#ém¸mw›Ç«Þdš]˾{"‘ÔC(äÞîíÓ;FúýÒÛ0Oz»ªi—¯ñÄbn—ŶÝ.F8œš îÿ€ÛÆjZjÙo™ÛvÛL¯MooÓ ¸Çk§‹Š:–¿¯ªJ9uþ<ðÎß+gï8îD¤‚‚®ÇÙ¶mãÆý•ŸüäÖþ/Ó+gÒ˜¡ïg2fØ o¹„Çð , Ü‚±T•‘$~ ‰õ‡IlÆycš¹¾åY¶Ž(å‰_"óÈ:vϾ‰ñ¹ S•;xvس¼1í lÛÆ4M?™  =ãsâŒÒýä3*ãqõêÕS\\ ÀŠ+ÐuÕ«W³hÑ¢cÞoÛ¶m¼÷Þ{©+Ò×VñÊô„èZ2MMÛÞIÛÆ39C@ý.8«À|”+€æÝDÿ˜2äÚÈ&´aqªr "Ë”|” ÛD›½—»ÎoFk{š]÷·2þ¼î›q1l†¿~ó?˜õâ+pd*ÿ<|>ç·‰KÛ.å×G~Í?fü•œ£Y4gÌfÏÐ=œ?¸€õc_'>(Nss3UÍbwÍxBÖ£¿œöQ°åCß╦WXܼ˜mk·±ÀLõúc@“rÑ·àªÇ®âWc~…ZeqÃîLFÞ÷7Z‡´ò‘£dì^ÈÔÏÏãš'®á_ü+9CÈÕCÚtÏ=TMÕáoqÍU`AƒÖ/8pG˜ Ú\Ú¬ƒ¢¢“̹ֆoaMò|4ÜoÈÁ´×'K„LRß’½²RÉÑx[#™™™ ÿøðTi¥"Re™¼Aeoom®Î3ÒÓ鸖Wú1ÓŸ@¯T”žö,ýÿ’÷ÿÍÛ¾s «ôûy3Ú;}òSç;m¿aÃ7½Þ›Ñn¥mÓy*LØ73UoÛ€;wº¿DlxÈ€w-¸Bƒkb©×w¡­î lŽX€³t4ú3wR4Ê &Äf†Øu}+c¶¾m#þ¶Žã_Àtœ=fØñË*iƒEŠ¢‹ÅÐuÝ]T rß}÷1|ûp>¦}Œk®¹†D"ÁWÏû*»ví¶m>÷ŸÃ¶mæjs)**òƒˆUUUÄãq>úQ·$–,wR¦iþ¢Òï¾û.o¿ý6¹¹¹~ÉÓ††Îvîÿ‘s(èX]]Mnnî93£·Ï}ø®`'à§5ðhòƒß"ÉyY:Gyñ& ©DßQaÜ,¬ÿÝ9ð©Ñ­T5´ó(ÃøÀŸÖñÑL“ßû³wl$sìxfÿ‡­+™GˆGù1öÓ6#ùof°®T©=x&4FœÌ÷Ï»ˆÉÎi«k£nZ[f>ÍŸoúˆ¿.ªnëØö^xä¾wdkÈæâåK)þí[”FK¹ï[÷Q:÷óLÛûuF´îà‰+¾ÌÔì©Ì½r.ÛÍí~›äè:‰DÂ/¬ë:_NŽÌݤޔ|>¾Ã¬‚fýï÷¹¶¬ 4Í_wuì† ,O>7w$zÎ÷þú×îË–AQWÎÛ³iõ••Ǿ͹ën?iuåëë멯¯w‘¼Ò)J× MŠrü #¸û«¬ì¾Ö¹·â·= ªpůÁZlµ/}>‡g’{OM{ªÔi Ø€M@Eòºw"‹ùAB­ù5¬ODZQ±“_BÀ¨½Ò}Ž­®¥O4ЬN>H(Ê”~I¦à¼ XUq‡!C†0}øv^È?Ê–-S7öîm û/3÷O`¾b3hÖdêë'ñ±m`ûVó‹‰nÚ[Ö”&šÚ²Øñv6œ?Æ ½ó6Íx—);v0òÐ!6ϘÁmñ™þuË‚ªN#ü›gµR´—?º™X§Z`MÇ.i›V ÈûEêïx¼ã¤ñaÀ+€‘ÌW…é›.`Êúõ´´´0vìX^hÍgLj2¶¦ñp>?½$“Ìó°òÛû˜¸sÍÖQ F¶pËì¼þG‹ÿœs“‡$gíPþð‘u ~»•iCxù£Ù¿p¿ºlì?ýi5÷޽œÁcÜÔçy‰]ßÚÅèQŸç¨3ž¶_6p4k/_ú»MË¡C|)3“­_GåªÙ|áÀ§ þR¾k¾Â„=O³o”û"©ƒc>ŒRx¨gï™÷¡>·ÇšŒ©Š—YðJ}{cŒÝŒ¿t˜èìEqÇñ*tç©­­å¼óÎãí½Pæ »ÙÍÜ·ÿÖé0A°’cYêÀ©O• ohh eÐΛÞÌ[–;ihî ÛYÿØ”û8<î0ç:Âþ:‰k¯ØÍîám¼þôÄÛ|äK›ùëÿºý‚ùÞÉî7³Ø±}‡fذadÝÍ´ioðÊÚ…l?°_³š7_þ NjœböÅõiCÝ–±ŒÛÀèq»x§î¢Ç™~õ“Ô½ðQ†´ Ἃ^ãð»ÓØ»7Ç¿}ìØ¦ÏØÄ«¯¸mÎû=/ýùSþí-™-œÁ›þýÒã48Œ=š¡Ã†2jê/yï­/±cw ³/}†}Û.d×¾‹Ù{h/c†ŒaÔÐ7¸êƒïò̳³Ÿ=˜á“V`oŽqàÀ† ‘#GP&› Ú—Ç–I(9óæŒäÅWF1ºu4ïp'T]¶àþ¾Ömd/˜UFæîBÞpæ36³c6spðAšÚ³cׇhÔÆÌ™ðÖ¦Žõû/˜UFãŽÑÐ|“Ï{€»>Ä‘#G2dˆ¿ÍF{)ÃÚ†qÁ¬²û˜4rÙc6³ئ¿_Þ§ú¥Oàù½ŠßSÝ÷v°]ù:\ÂäÄD? Vtw ú>ñöo añžàš¿`÷¥¡Vþl01Ñ´YDãQT[%a'Ð4 e”Ž»Ô——(Лªa'ó]ðýêlÛê0q;cµµµ]^°ÜÜ\òóóY·nÝ 9€yçc¨oÖ¢ª‚ÀưÔpŽ€ZÎý?e‡³™·É¥®u•Vv\4›5¯_Jkk+_ù2·þ¤ã›þ†%Ó–9Ÿû¦0Â\Ïç>Ê´·p=ÏÒÚØÊ$¶q]d&7¶,áСCn4ø Ì`3[˜É{ƒ±µa÷ýýenžx3;wî$£pOú(³fÍ"RYYég Þ~ûí~±µµ;9Øïe"z¥O5M£¦¦¦Ãz‰^D;ξ¢(¬ZµŠÂÂÂ3ú»7¼Î湤ººúœy­ûÚ'8ú'ãs£´üàE@¬ þIżvìØ/ج=”ÃŽ#hþÉPÞøÇÃìÛ7„¹sâé§¿À‚!6oþ ™í5 nÝÇ»;ÿˆ¹3ÁøñM<~üx6m:Ÿø[o1!#ƒ!C†Ð²½…7§ñCs?3gÎdóæÍL>œü– >œw÷·Ð|Þy¼¼3—mo ;;›72|Þ<6¿õþÔ§xúé§™9o›×­cöìÙ466’Í· xwäH¦L™Âê7ßä+_ù <@<'‰ÐpÇ\øã³ ™ñ7yòdšª«¹pï^.»ì2Ö®]ËÞ¯|…@$B{{;ƒ ¢*}D"~©xüß½*F àß'ìS¥ßg °Ã²øÐ‡>Ä /¼À%ÿó?+?<ü0%îãMSU•p8LMM Ñh”ßüæ7¬ZµŠÙ‹ó«_ýŠà—¿ŒmÛŒPU.sÿ>‰D‚ù—!Z[KÕo~C à ÿïÿ±:åꫯfìØ±~–·ã8\}õÕL›6¹sçòÐCqÝu×ñÔSOù>œ9sæ ªªß7TU˲¸òÊ+©­­íòsîܹ<èVÇ9r$uuu¬_¿žÂÂB4Móg矪ªv8Ι¨_Ú‚ahFØ8œ™‡¥a?Ìmß3X?­€î÷j…¹ƒB”?ø!.Þ´‹}/>ÇŽïtØíÜAçv!GFáK£Þä×ñ÷:Ü~õØ72³˜o׌ãªñ‡øÊÌ*¾øÒÇ;lsû3wò³—îq·ÿÝ‹´mÍ ‡ç磿趘»§ÞºŽ£mG¹¢þ÷¬{rR‡}dýÃÓìSŒµGåÕ-›óç¿ÀúÖÛüè–—™úÞÓN;¿ûù¯¸e›Â‚£»A´·å½»ùÝ÷'qSã'ikkãß—ßÏšŽ0hß ¾6ØÝÇ«wh½ë³ÎãÏÛ_æü_ï`ïàGÉÈÈàèÑ£ ÊÄ7ËñÀ°™~x7ÑQ~ËL²Hpo†›wòn B ‹¢<‹ :öAîÿÎt@[d’Éã¬dè–æÔó¶`7áFW{X@iYÇ;!NŒÏ aaaÖØ”uŠ.ÿ2:+Ú¢­­ÄkUh,¾õ^Ç~CÉÆKøÔÑÿfðàÁüÓ=ÿÌ__LvÛËþí-¯àÁ1?ââA¼ðÒ Ì›t€o½ýmeL¥eІ¬ƒ/îçÒC222øíË'¼Ëì¦×ÅàöÁl}ã)æìÅ;GSÚæ zC‡±ëp.CÈewËÃìxã]&#²£¿éolôiJΰ·9oèVÆíÃßGë VÞÞñ Ú^wÚãKÍϳø§}‡2‘AÓ©§Õ¾ˆlgÙ‡³iÏûs6¼Æ°´NåÍ-¼3öR”w§s$§•Ië³÷5·g0xçÚ9ÊîõLi>Ÿ‰ýÎ>Qw›çý}LɰÙóú>ÒpÃvc2y;ÝÛp„öÁí´n…œÁ7²kßh¶ŽĈgÞæãûšý´f¼ÃУC÷v&³÷Í`ê¬kÉ\{ˆ73Ö°oßXìÝs˜7èu†Î™ŒÓ’øÖqìhCAóË nìŸË˜·Þ¤%{9­;r™¯eñ–õ$^fp[j›Ü̉Ôïuÿï ž6‡¬Ý¼ËQŽÒÞr” {Þáç£þç¿cO~éüÝÁüz5vÍ&¬–‘Dò^GÝüSLÞ}wû®Éâ™gŠÙ³î(›”-[‚\ôè×xoû§™Åžü‹´¯R3v,í·ßÎg~úb±ƒòÜþn8&‹ù}°ÊÊÊ~Íh<¾ ž c[Æ"ÎagL©Õêêj–.]ÊÆ´27à¦AÇMÿüç?ÏÈU«/c/Ùþõ£ ÐìÏ¥3 8œŒ( Åa8&[“éuC†ìCQ,.p4rG½HKK C‡eóÑ£¼7f #GŽäðáÃŒ1‚ÆÆFrrr8xð ]t›6mbÚ´i¼óÎ;¨ªJ[[cÆŒaذaþŒŸ}ûö1~üx:Ę1cúå9Ûºu+Ó§Oè—î´Ú¹s'£FbôèÑ}*§UO_ë;w²{÷n233yî¹çú´OZ_Ú€Ë.»ŒÜW¿Îsí—²—Ë’×&p‡öÜTщeçÎiŒ[Çë˜0a‡f„ ´¶¶räÈ&L˜À;#¦iX–ÅÇ>ö1,Ëâ /äÍ7ßdòäÉ4773y²û…Ã{Ÿ>|˜qãÆÖçLÞ玓y­kkkikkãºë®ãûßÿþ@ŸúIëkŸ`ÛŸw²»ágld"GýEÒ¸SÁ[èuðàY ¶?LXCSÓ*.¸àÞzë-.¸àÚÚÚ=z´ÿù?fÌöíÛç·Ο?Ÿ}ûöùípÚÚ„sñ=ÑÜÜÌþýû™8qbßwvéékÝÜÜÌÖ­[9|ø0¿üå/ÉÏÏïÁÞß?úÚ'¸á†0MÇ¿™¼Æ óye7`ôè_ÑÜ<›#Zü™âçÈ‘÷:t(ÍÍÍLœ8‘;w2þ|^ýu¿˜Ìn6lW:Dkk+£F¢¹¹™Ayy<ýöÛ~?bÖ¬YlÚ´‰‰'rðàAFŒpK¶µµ1nÜ8¶lÙâo;{öl6nÜÈ?øÁ}¯í÷~ß±c‡ßöx÷íÜOéé}vìØá·u^›Õù;ÌîÝ»™2e Û·o÷ÿ3fŒ¿ÝîÝ»2dcÇŽ=æ}¼ïA{öìaذaýö¨/ÎÔ~ÔÉ´[“’&Là±ÇèS?i}i jkk¹ùæ›yõÕW:\Ÿ…I^¸?‹†$‹ØÄÃÜà·`26™J$lÁ`ô覹¹™±c+µ7@Fæ6&·í&cð`Þ´—ú£{z”Q‡sÞyçñ›Ý»ÉÏÏ÷Û œ·ÞbF¶;î±}øp6=ê·-ï½÷\p³’ŸOìÚÅðÉ“iÙ±ƒö±cý÷ìÍû÷3íðaÌ¡C‡5jQ`Μ9lذٳgóùW_eÔ¨Qþ¹½8jÍÈ`Ĉìܹ“Ÿ>W¿ñ“&Mâ;Éœ4‰_îÜIÛôéþùä·´yà™™™8ŽÃÔ©SùÕ®]Ì;—õë×3kÖ,¦oÚÄ„ hjjBQ¶ef²±µ•1cưeËtM£mÍ.¼ðBÿ>lÙ‚¢ªìÛ·qãÆ1ñwÈjk#''‡––rrrøíÞ½újÖ­cÂ…²sçNÚÇŽ¥¹Ù dŽ=š­[·2oÞ¼nûwéídú}ÒÛÔžÞÇûéõ7nÜÈŒ3ztŸ={ö0eÊ^ýuÿ8£Fbøðá 6ŒÌÌL:Dss33fÌ`÷îÝ~{üÞ{ï±}ûv¾ð…/ð£ýh ßÚ'­/mÁ·¿ým½3ëŽ7Ü1C·ÈÈx„Ƀòh9zÐÞNÎÐ×x«½Œ!CnçСCdgW0voC‡MÞ'ƒ¶!O³{h=3ikÛÍôì= ß1…1£Gûï­W÷= c?Ê‘#GÈÊÚÍ”Æ †¶eqḿsøða²²²ø}s³?®8mÚ4¦oÚÄÈ‘#ÙµkãÆ£~èPödg“MKK “23·e‹ŸY³fñè;ï0iο/0õÝwÉjkcøðá´´´0|øpLðÿÏišÆÐgžñ÷1qâDÞ8|˜¦ñã÷³fÌ‘#\´?999þ¹ýyÏÿ8^x!Y›6qÞС~…‚ŒŒ ªÚÛ?~¼ßÇÉY»ÖïM›6—ví¢mút¿2ºµ•Ü]»>|8 L›6?nßÎ…øÛ·ogÊ”)´­YÃÜÉ“¾};­£GóÞ‘#¼œÝá}’³v-W…í8 =›ç¶mcdò½=yòd2àšä±ªGŽdøðá<ð ÿx¦M›FÖ¦MÌ<™õë×3cÆ ZZZØ\úÊ;ΜmÛ:t(ï¼ó\p[[iÍÍåõ×_gþüù8–Åš›Ù6i‡Fޤµµ•º±c9ÿ#žâr.ä Þã]¼ÔáîÔ¿0cĈõÝ«¦?èî}þàiÿÿöî¹q%]ãø³[‹åý‡Ä@![w†˜ìnM€'àšÆÀcâ .˜€8"¡1ÈÀƒ©Z}‚„}ë xAÊ>qâXŠÝ’º[ÿ_ÕTíf|2ýv«¿–lyÛ÷`}12F—‚ÿÏÈHŠÕµ·Lü;ÿ¿ãïþ·¦:`Õ4þóŸÿèïÿ»þñIú׳Güþ|þ·óî7€MZqáQ’~ûí7ýöÛoM@ÃþùÏ6= £'/ýûßÿnz€þzø¯¨Wš¦¯~æÚ­¡† ‘ÈOÈY€láÌ…ÇÕ—q><×Éɉz½žNNN4ŸÏ­wžçº¼¼ÜøUe¥‰±¿µï_Ö±mþMÍ/ÙP=SYÐÄzå€ã.“¦Æej܇dM™†ÝÊd­ëYGO`zÜ®õÒö,0Õ”y 9м:s¿®z>~üøê¸v¡†ºz o,=õí۷凖?~üXÞßß/?þ¼üüùsÓÃ:¸¦OŸ>-¿}û¶ñç?þxWÝ.ÌÍÍÍÍòèèhy¿u­ÑÖ9(ª{×úû²ö¦ùX³‰,pe^É—÷Ä[u·éyÀ4ßjnÛ±°kO˜¨ÑÆy 'ðÓjžïïï—÷÷÷Ë/_¾,?|ø°\,ëÇØÚëÞÝÝ-ŽŽ–777Ëûûûåׯ_—GGGF»*ƽúwwwë9ÿôé“Ñù65ö]ûþüü|ùáÇuß¾}[-ïîîŒÎ/ÙPYÐÄz倭ã.ÊSã25îC²À¦LC±¢,°u=ëè ª·K=Árùv˜è Ê<†°C]¹_g=/kj¨«ò‰·W'cVþøãW!욯_¿.¿~ýzpÝ6ÏÍ?–GGGë?Ûm5Ú6eê.Z××¾*>Öl" lŸYàâž(ª» ÏUñ­æ¶ E{ÂT6Í=¿–GGGˇ‡‡õÏ‹E%Çlëûùóçß¹\.—_¾|YþøñÃÚqßßß¿:!°X,Ö/øMûбíûmÇÉjM¾|ùbt~Ɇê™Ê‚&Ö³(lw™05®CÇm" lÈ4”S& l]Ï:zÓãv¥'X.wg©ž ÌcÈæÕ™ûu¸¹¹Y~þüùÕqíB uõ@>ñòV«iš*Ë2õûýõϺݮÂ0ÔÃÃCÓÃÛ[–e ‚à ºmŸ›~¿¯ÛÛ[ÝÞÞVV£sPT·´{ý}Xû*øZó¡Y༚®î‰¢ºÛðÀËÔmûÜt»Ý&à%5®~nÓÕ-í^Ö¾ ¾Ö|hظ^:4 ÊÔhãñQTwžªàcÍm9ví S5Ú6ôþêv»šN§’ž^˜. Åq¬0 ×kak¯»:9ßívuyy©,ËÔív5†¡µã>>>^ÿù¾ZÕcª_8tOíû0 _|Ìó\wwwFû?²¡&² ‰õ,Ê[Ç]”eÿÍ:2ìÐ,ðµ7òUQ¬NDÛ¶žuôUŒÛ•ž`5·oe‰ž Ìc\8oÔuå~Õò<×ׯ_uqqñê"ª 5ÔÕùÆËO<ú*Ïsu»]ýúõK¿~ýÒp8ÔåååÖ/‡X¬p,´kŽ…vcýÝE‘F£‘æó¹NOOw~‚Ù&ggg ‚@a*Ë2ŸŸ[ýB¹ßï+‚õ ‚,ËÖÿÛeóù\gggêv»º¸¸hz88€‹Y@؃,ðYP=_³€hW×ûææFNGãñ¸é¡ĵÜkš—ŸxôÕãããÆÿŸN§J’Dq¿ºZÿìZÿÕ»šÐdA{±öXáXh7z÷­Þ¹œ$‰F£‘‚ pbí...6Nœœœ(Žc ƒ¦‡¶Uúþý»&“‰NNN$IƒÁ`ç-.m¶:Iš$‰Æã±...œ89·¹˜oåÀÕÕUÓCÛÊ·ÈmË‚¢;`4ž Yä@»¸¼Þ«×©?þlz(s­jš×ŸxÜvÅÙÕ'”·ôûýõ=¼ßS·ësc¢F×ç@z½þmXû}´¡æ}²À‡y1Q£ëóÐÖç}ø^s[S5º>ôö[}7Èsý~_ý~ÿÕ§Umíu_^ Ÿ°qÜaêׯ_z||Ôã㣮¯¯Õét*éªÜSiš®ßeýë×/M§Ó­'œèìg2 šXÏ¢°qÜerÀÔ¸ªÞ?e²À…LCù,°u=ëè L›žÀ¾LC±:s¿ I’¨ÓéèòòR£ÑH£ÑHÒŸŸôv¡†•ºz _xyáqõNÿ—_Ì™$‰õïzË|>ߨŒ+Y–­Ã¦Lݮω]œƒ¢õoÃÚïÃÇšMdób¢F׿çýùV3Ç‚ŒÖèÚ<иk>Ÿëüü|çclíuWß‹ôòw¾ü^$ÛÆç¹¢(Ú8!ç¹’$Ñññ±S92™Ltzzªëëë­¿³½‘«LdAëY”¶Ž»(Êþ›¶¼ÆÚ•.eгÀÖõ¬£'¨bÜôvfŠÕ‘ûU‡ºººÒx<^ÿ‘¤ÓÓSÇc'j¨«ò—¥§ƒ:Žãõ;¿g³™‚ ÐééiÓCÛK†J’DQ­–$Éúþïï©Ûõ¹1Q£ksPfýÛ°öûð­fSYàü˜¨Ñ¥yàyà0>Õ̱ð'S5º4ôî Êó\³Ùlý³$I”$ÉÆ-’mìuWµ£(ZÿÎÕq·º¥š­ãžÏçsE‘‚ 0:î*Æþ\’$ʲlý)˜çž¿kºm½‘«LeAÝëY&lwQ˜WÕû§L¸ixR& l\Ϻz‚*ÆMO`W¦¡X¹_•ÕE·ç¤§×µ¦³®*uö@>ùËr¹\6=ˆ*äy®óósåy® ”e™¦Ó©õß—°KÇë“LNGY–i<k:¾«nWæ¦×ëéöööÕwU™¨Ñæ9x«î¢õ÷iíMò±fYàҼ웮ï‰mu·íyÀ$ßjnã±°mO˜ªÑÖy 'ðOǺ¼¼T•îÝ*Ö7Ë2M&¥iª0 •¦©ñ㮊q'I¢Éd¢N§£Åb¡N§£ëëëõ-lË‘mû>Š¢¥ÏõûýõwƒùÞùÄD4±žE9`븋rÀÔ¸LŽ{ß,°-Ó°[QغžuôUŒÛµž@z¦z‚2!šWgî×éåqíB uõ@>ñöÂãÊê¾èÇÇÇÎ|éê.yž¯?’Ûívßü(n™º]Ÿ5º6eÖ¿ k¿ßj6•>Ì‹‰]šžãSÍ æktiè Ü•eÙú¶ÚÖ¹ÊT4±žE9`ã¸Ë䀩qÙ°|Ê4ß•É[×³ŽžÀô¸é Þÿê@1WŽI×k¨«ò÷TÏÛïxP.<8Œ Æ…G´Z’$Êó¼éa° ÙWp¬Y´ {műæ©ÕâÂ#ŒIÓT£ÑH½^O½^O£ÑÈúÍ;ôððÐô0§Äq¬Ñh´õï\Ìmȸ¢©cuW¬þþääD½^O?~TEMN€ÕÑ7…€;Lìû&{õ]ûž=ªùô:ÕåsEÏÿ.×´‰O™j#.<ˆ,Ët~~® t{{«ëëk=<>n<©®n7°ëÝA«Zf³Ùú6%gggJÓ´òy,3>Àuî• †¡Æã±ºÝîÖÇT‘MeÚKd\Qå±Z&$i>Ÿ¿z!> ”çùú…z™±ÚMö$h§}û²û©®cÙdß°—²(£Ìv¡Ç®jßWÝ«—Ù÷ìy4áå±ïBHæ²À¶s"&kšÒtFp]À\xôÄê7Y–éúúZÓéTóù\Ÿ>}ÚøY’$Æoõ±Úøý~_Y–i6›i6›)˲W],J’dëß=ÿ}q+I]]]éúúZ’t~~^ùžŸŸ«Ûíj8Vúo&Ô¹WºÝ®¦Ó©¦ÓéÖ&»Šh*Ó¶…l€ ª>V‹r@Ò›ï^=þù¾/Êr ©žíµïq_f?Õy,›ìö™C—²(£Ì¶½Ç®jß×Ñ«í{ö<š°íØ·=Vÿ¾d& l:'bº6 )6d×üÀ­V=Òív×›±ßïëîîNyžoü¬¨ÙÇb±ôô¿8ŽÕívµX,E‘®®®66k¿ß×ããcáïÌó\ß¿u[‚$IÞ¼Á!Várzzº¾5 à‚º÷Ê[ªÈ¦2í9²®°ýXÝvâ­Lضä,ÚcŸã¾Ì~²éX~Oßð.f!PVѶ½Ç®bß³çÑVoû¶ç€d> ÚÐßukúu8×üÀ…G¼ÜxNGN§ôŸ$‰F£ÑÎÇìj`îîîôóçÏõ­.//×_®¾ë6oÕò<\žÿoÓãNÓT777Êóœï^€sêÜ+e˜ÎçêÎ4²®xϱZG˜th˜¨ù=9 ˜`â¸ë÷ÚÔ3HfûŸ³Ì=5Ýc›Ú÷ìy´•‰×©6ôئ²À÷þhBÓ½×üÀ…G¬ëöövïÿþââbã~åÓéTqïõeêïyu踣(Òx<Öl6ÓÍÍ !§Ô¹WÊ0™‡"Ðï9VëÈ]L\À—rÀç}ÏžG“\Êi÷~q9Šj€6økÓ@», u»]îk´9@" “|ÞOY–éêêªéaÖó)Ø÷À~È€-¸Õ*€ƒñ‰GãÂ#€ƒqáÀÁ¸ðà`\xp0.<8Œ ö_EU„ jâÕ%tEXtdate:create2020-10-09T19:33:41+00:00þò`¸%tEXtdate:modify2020-10-09T19:33:41+00:00¯Ø!tEXtpdf:HiResBoundingBox1728x900+0+0×ì&ŒtEXtpdf:VersionPDF-1.7½8;í(tEXtxmp:CreateDate2020-10-09T14:32:59-05:00çü{6tEXtxmp:CreatorToolGL2PS 1.3.9, (C) 1999-2015 C. GeuzaineÛ©AJ(tEXtxmp:ModifyDate2020-10-09T14:32:59-05:005ÀBIEND®B`‚blis-0.9.0/examples/000077500000000000000000000000001422157504600142755ustar00rootroot00000000000000blis-0.9.0/examples/oapi/000077500000000000000000000000001422157504600152255ustar00rootroot00000000000000blis-0.9.0/examples/oapi/00obj_basic.c000066400000000000000000000220161422157504600174450ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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 The University of Texas 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 COPYRIGHT HOLDER 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. */ #include #include "blis.h" int main( int argc, char** argv ) { obj_t a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11; obj_t v1, v2; num_t dt; dim_t m, n; inc_t rs, cs; // // This file demonstrates the basics of creating objects in BLIS, // inspecting their basic properties, and printing matrix objects. // // // Example 1: Create an object containing a 4x3 matrix of double- // precision real elements stored in column-major order. // // The matrix dimensions are m = 4 and n = 3. We choose to use column // storage (often called column-major storage) and thus we specify // that the row stride ("rs" for short) argument is 1 and the column // stride ("cs" for short) argument is equal to m = 4. In column // storage, cs is known as the leading dimension. dt = BLIS_DOUBLE; m = 4; n = 3; rs = 1; cs = 4; bli_obj_create( dt, m, n, rs, cs, &a1 ); // If cs is greater than m, then extra rows (in this case, two) will // be allocated beyond the lower edge of the matrix. Sometimes this // is desireable for alignment purposes. dt = BLIS_DOUBLE; m = 4; n = 3; rs = 1; cs = 6; bli_obj_create( dt, m, n, rs, cs, &a2 ); // // Example 2: Create an object containing a 4x3 matrix of double- // precision real elements stored in row-major order. // // Here, we choose to use row storage (often called row-major storage) // and thus we specify that the cs is 1 and rs is equal to n = 3. In // row storage, the leading dimension corresponds to rs. dt = BLIS_DOUBLE; m = 4; n = 3; rs = 3; cs = 1; bli_obj_create( dt, m, n, rs, cs, &a3 ); // As with the second example, we can cause extra columns (in this // case, five) to be allocated beyond the right edge of the matrix. dt = BLIS_DOUBLE; m = 4; n = 3; rs = 8; cs = 1; bli_obj_create( dt, m, n, rs, cs, &a4 ); // // Example 3: Create objects using other floating-point datatypes. // // Examples of using the other floating-point datatypes. m = 4; n = 3; rs = 1; cs = 4; bli_obj_create( BLIS_FLOAT, m, n, rs, cs, &a5 ); bli_obj_create( BLIS_SCOMPLEX, m, n, rs, cs, &a6 ); bli_obj_create( BLIS_DCOMPLEX, m, n, rs, cs, &a7 ); // // Example 4: Create objects using default (column) storage so that // we avoid having to specify rs and cs manually. // // Specifying the row and column strides as zero, as is done here, is // a shorthand request for the default storage scheme, which is // currently (and always has been) column storage. When requesting the // default storage scheme with rs = cs = 0, BLIS may insert additional // padding for alignment purposes. So, the 3x8 matrix object created // below may end up having a row stride that is greater than 3. When // in doubt, query the value! bli_obj_create( BLIS_FLOAT, 3, 5, 0, 0, &a8 ); // // Example 5: Inspect object fields after creation to expose // possible alignment/padding. // printf( "\n#\n# -- Example 5 --\n#\n\n" ); // Let's inspect the amount of padding inserted for alignment. Note // the difference between the m dimension and the column stride. printf( "datatype %s\n", bli_dt_string( bli_obj_dt( &a8 ) ) ); printf( "datatype size %d bytes\n", ( int )bli_dt_size( bli_obj_dt( &a8 ) ) ); printf( "m dim (# of rows): %d\n", ( int )bli_obj_length( &a8 ) ); printf( "n dim (# of cols): %d\n", ( int )bli_obj_width( &a8 ) ); printf( "row stride: %d\n", ( int )bli_obj_row_stride( &a8 ) ); printf( "col stride: %d\n", ( int )bli_obj_col_stride( &a8 ) ); // // Example 6: Inspect object fields after creation of other floating- // point datatypes. // printf( "\n#\n# -- Example 6 --\n#\n\n" ); bli_obj_create( BLIS_DOUBLE, 3, 5, 0, 0, &a9 ); bli_obj_create( BLIS_SCOMPLEX, 3, 5, 0, 0, &a10); bli_obj_create( BLIS_DCOMPLEX, 3, 5, 0, 0, &a11 ); printf( "datatype %s\n", bli_dt_string( bli_obj_dt( &a9 ) ) ); printf( "datatype size %d bytes\n", ( int )bli_dt_size( bli_obj_dt( &a9 ) ) ); printf( "m dim (# of rows): %d\n", ( int )bli_obj_length( &a9 ) ); printf( "n dim (# of cols): %d\n", ( int )bli_obj_width( &a9 ) ); printf( "row stride: %d\n", ( int )bli_obj_row_stride( &a9 ) ); printf( "col stride: %d\n", ( int )bli_obj_col_stride( &a9 ) ); printf( "\n" ); printf( "datatype %s\n", bli_dt_string( bli_obj_dt( &a10 ) ) ); printf( "datatype size %d bytes\n", ( int )bli_dt_size( bli_obj_dt( &a10 ) ) ); printf( "m dim (# of rows): %d\n", ( int )bli_obj_length( &a10 ) ); printf( "n dim (# of cols): %d\n", ( int )bli_obj_width( &a10 ) ); printf( "row stride: %d\n", ( int )bli_obj_row_stride( &a10 ) ); printf( "col stride: %d\n", ( int )bli_obj_col_stride( &a10 ) ); printf( "\n" ); printf( "datatype %s\n", bli_dt_string( bli_obj_dt( &a11 ) ) ); printf( "datatype size %d bytes\n", ( int )bli_dt_size( bli_obj_dt( &a11 ) ) ); printf( "m dim (# of rows): %d\n", ( int )bli_obj_length( &a11 ) ); printf( "n dim (# of cols): %d\n", ( int )bli_obj_width( &a11 ) ); printf( "row stride: %d\n", ( int )bli_obj_row_stride( &a11 ) ); printf( "col stride: %d\n", ( int )bli_obj_col_stride( &a11 ) ); // // Example 7: Initialize an object's elements to random values and then // print the matrix. // printf( "\n#\n# -- Example 7 --\n#\n\n" ); // We can set matrices to random values. The default behavior of // bli_randm() is to use random values on the internval [-1,1]. bli_randm( &a9 ); // And we can also print the matrices associated with matrix objects. // Notice that the third argument is a printf()-style format specifier. // Any valid printf() format specifier can be passed in here, but you // still need to make sure that the specifier makes sense for the data // being printed. For example, you shouldn't use "%d" when printing // elements of type 'float'. bli_printm( "matrix 'a9' contents:", &a9, "%4.1f", "" ); // // Example 8: Randomize and then print from an object containing a complex // matrix. // printf( "\n#\n# -- Example 8 --\n#\n\n" ); // When printing complex matrices, the same format specifier gets used // for both the real and imaginary parts. bli_randm( &a11 ); bli_printm( "matrix 'a11' contents (complex):", &a11, "%4.1f", "" ); // // Example 9: Create, randomize, and print vector objects. // printf( "\n#\n# -- Example 9 --\n#\n\n" ); // Now let's create two vector objects--a row vector and a column vector. // (A vector object is like a matrix object, except that it has at least // one unit dimension (equal to one). bli_obj_create( BLIS_DOUBLE, 4, 1, 0, 0, &v1 ); bli_obj_create( BLIS_DOUBLE, 1, 6, 0, 0, &v2 ); // If we know the object is a vector, we can use bli_randv(), though // bli_randm() would work just as well, since any vector is also a matrix. bli_randv( &v1 ); bli_randv( &v2 ); // We can print vectors, too. bli_printm( "vector 'v1' contents:", &v1, "%5.1f", "" ); bli_printm( "vector 'v2' contents:", &v2, "%5.1f", "" ); // Free all of the objects we created. bli_obj_free( &a1 ); bli_obj_free( &a2 ); bli_obj_free( &a3 ); bli_obj_free( &a4 ); bli_obj_free( &a5 ); bli_obj_free( &a6 ); bli_obj_free( &a7 ); bli_obj_free( &a8 ); bli_obj_free( &a9 ); bli_obj_free( &a10 ); bli_obj_free( &a11 ); bli_obj_free( &v1 ); bli_obj_free( &v2 ); return 0; } blis-0.9.0/examples/oapi/01obj_attach.c000066400000000000000000000133401422157504600176310ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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 The University of Texas 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 COPYRIGHT HOLDER 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. */ #include #include #include "blis.h" void init_dmatrix_by_rows( dim_t m, dim_t n, double* a, inc_t rs, inc_t cs ); void init_dmatrix_by_cols( dim_t m, dim_t n, double* a, inc_t rs, inc_t cs ); int main( int argc, char** argv ) { obj_t a1, a2; num_t dt; dim_t m, n; inc_t rs, cs; // // This file demonstrates interfacing external or existing buffers // with BLIS objects. // // // Example 1: Create a bufferless object and then attach an external // buffer to it, specifying column storage. // printf( "\n#\n# -- Example 1 --\n#\n\n" ); // We'll use these parameters for the following examples. dt = BLIS_DOUBLE; m = 4; n = 5; rs = 1; cs = m; // First we allocate and initialize a matrix by columns. double* p1 = malloc( m * n * sizeof( double ) ); init_dmatrix_by_cols( m, n, p1, rs, cs ); // bli_obj_create() automatically allocates an array large enough to hold // of the elements. We can also create a "bufferless" object and then // "attach" our own buffer to that object. This is useful when interfacing // BLIS objects to an existing application that produces its own matrix // arrays/buffers. bli_obj_create_without_buffer( dt, m, n, &a1 ); // Note that the fourth argument of bli_obj_attach_buffer() is the so-called // "imaginary stride". First of all, this stride only has meaning in the // complex domain. Secondly, it is a somewhat experimental property of the // obj_t, and one that is not fully recognized/utilized throughout BLIS. // Thus, the safe thing to do is to always pass in a 0, which is a request // for the default (which is actually 1). Please don't use any other value // unless you really know what you are doing. bli_obj_attach_buffer( p1, rs, cs, 0, &a1 ); // Now let's print the matrix so we can see how the element values were // assigned. bli_printm( "matrix 'a1', initialized by columns:", &a1, "%5.1f", "" ); // // Example 2: Create a bufferless object and then attach an external // buffer to it, specifying row storage. // printf( "\n#\n# -- Example 2 --\n#\n\n" ); // Now let's allocate another buffer, but this time we'll initialize it by // rows instead of by columns. We'll use the same values for m, n, rs, cs. double* p2 = malloc( m * n * sizeof( double ) ); init_dmatrix_by_rows( m, n, p2, rs, cs ); // Create a new bufferless object and attach the new buffer. This time, // instead of calling bli_obj_create_without_buffer() followed by // bli_obj_attach_buffer(), we call bli_obj_create_with_attached_buffer(), // which is just a convenience wrapper around the former two functions. // (Note that the wrapper function omits the imaginary stride argument.) #if 1 bli_obj_create_with_attached_buffer( dt, m, n, p2, rs, cs, &a2 ); #else bli_obj_create_without_buffer( dt, m, n, &a2 ); bli_obj_attach_buffer( p2, rs, cs, 0, &a2 ); #endif // Print the matrix so we can compare it to the first matrix output. bli_printm( "matrix 'a2', initialized by rows:", &a2, "%5.1f", "" ); // Please note that after creating an object via either of: // - bli_obj_create_without_buffer(), or // - bli_obj_create_with_attached_buffer() // we do NOT free it! That's because these functions merely initialize the // object and do not actually allocate any memory. // Free the memory arrays we allocated. free( p1 ); free( p2 ); return 0; } // ----------------------------------------------------------------------------- void init_dmatrix_by_rows( dim_t m, dim_t n, double* a, inc_t rs, inc_t cs ) { dim_t i, j; double alpha = 0.0; // Step through a matrix by rows, assigning each element a unique // value, starting at 0. for ( i = 0; i < m; ++i ) { for ( j = 0; j < n; ++j ) { double* a_ij = a + i*rs + j*cs; *a_ij = alpha; alpha += 1.0; } } } void init_dmatrix_by_cols( dim_t m, dim_t n, double* a, inc_t rs, inc_t cs ) { dim_t i, j; double alpha = 0.0; // Step through a matrix by columns, assigning each element a unique // value, starting at 0. for ( j = 0; j < n; ++j ) { for ( i = 0; i < m; ++i ) { double* a_ij = a + i*rs + j*cs; *a_ij = alpha; alpha += 1.0; } } } blis-0.9.0/examples/oapi/02obj_ij.c000066400000000000000000000170541422157504600167760ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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 The University of Texas 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 COPYRIGHT HOLDER 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. */ #include #include #include "blis.h" void init_dmatrix_by_rows( dim_t m, dim_t n, double* a, inc_t rs, inc_t cs ); void init_dmatrix_by_cols( dim_t m, dim_t n, double* a, inc_t rs, inc_t cs ); void init_dobj_by_cols( obj_t* a ); void init_zobj_by_cols( obj_t* a ); int main( int argc, char** argv ) { obj_t a1, a2, a3; num_t dt; dim_t m, n; inc_t rs, cs; dim_t i, j; // // This file demonstrates accessing and updating individual matrix elements // through the BLIS object API. // // // Example 1: Create an object and then individually access/view some of // its elements. // printf( "\n#\n# -- Example 1 --\n#\n\n" ); // We'll use these parameters for the following examples. dt = BLIS_DOUBLE; m = 4; n = 5; rs = 1; cs = m; // Create a object with known elements using the same approach as the // previous example file. double* p1 = malloc( m * n * sizeof( double ) ); init_dmatrix_by_cols( m, n, p1, rs, cs ); bli_obj_create_with_attached_buffer( dt, m, n, p1, rs, cs, &a1 ); bli_printm( "matrix 'a1' (initial state)", &a1, "%5.1f", "" ); // Regardless of how we create our object--whether via bli_obj_create() or // via attaching an existing buffer to a bufferless object--we can access // individual elements by specifying their offsets. The output value is // broken up by real and imaginary component. (When accessing real matrices, // the imaginary component will always be zero.) i = 1; j = 3; double alpha_r, alpha_i; bli_getijm( i, j, &a1, &alpha_r, &alpha_i ); // Here, we print out the element "returned" by bli_getijm(). printf( "element (%2d,%2d) of matrix 'a1' (real + imag): %5.1f + %5.1f\n", ( int )i, ( int )j, alpha_r, alpha_i ); // Let's query a few more elements. i = 0; j = 2; bli_getijm( i, j, &a1, &alpha_r, &alpha_i ); printf( "element (%2d,%2d) of matrix 'a1' (real + imag): %5.1f + %5.1f\n", ( int )i, ( int )j, alpha_r, alpha_i ); i = 3; j = 4; bli_getijm( i, j, &a1, &alpha_r, &alpha_i ); printf( "element (%2d,%2d) of matrix 'a1' (real + imag): %5.1f + %5.1f\n", ( int )i, ( int )j, alpha_r, alpha_i ); printf( "\n" ); // // Example 2: Modify individual elements of an existing matrix. // printf( "\n#\n# -- Example 2 --\n#\n\n" ); // Now let's change a few elements. Even if we set the imaginary // argument to a non-zero value, argument is ignored since we're // modifying a real matrix. If a1 were a complex object, those // values would be stored verbatim into the appropriate matrix // elements (see example for a3 below). alpha_r = -3.0; alpha_i = 0.0; i = 1; j = 3; bli_setijm( alpha_r, alpha_i, i, j, &a1 ); alpha_r = -9.0; alpha_i = -1.0; i = 0; j = 2; bli_setijm( alpha_r, alpha_i, i, j, &a1 ); alpha_r = -7.0; alpha_i = 2.0; i = 3; j = 4; bli_setijm( alpha_r, alpha_i, i, j, &a1 ); // Print the matrix again so we can see the update elements. bli_printm( "matrix 'a1' (modified state)", &a1, "%5.1f", "" ); // Next, let's create a regular object (with a buffer) and then // initialize its elements using bli_setijm(). bli_obj_create( dt, m, n, rs, cs, &a2 ); // See definition of init_dobj_by_cols() below. init_dobj_by_cols( &a2 ); // Because we initialized a2 in the same manner as a1 (by columns), // it should contain the same initial state as a1. bli_printm( "matrix 'a2'", &a2, "%5.1f", "" ); // // Example 3: Modify individual elements of an existing complex matrix. // printf( "\n#\n# -- Example 3 --\n#\n\n" ); // Create and initialize a complex object. dt = BLIS_DCOMPLEX; bli_obj_create( dt, m, n, rs, cs, &a3 ); // Initialize the matrix elements. (See definition of init_dobj_by_cols() // below). init_zobj_by_cols( &a3 ); // Print the complex matrix. bli_printm( "matrix 'a3' (initial state)", &a3, "%5.1f", "" ); i = 3; j = 0; bli_getijm( i, j, &a3, &alpha_r, &alpha_i ); alpha_r *= -1.0; alpha_i *= -1.0; bli_setijm( alpha_r, alpha_i, i, j, &a3 ); i = 3; j = 4; bli_getijm( i, j, &a3, &alpha_r, &alpha_i ); alpha_r *= -1.0; alpha_i *= -1.0; bli_setijm( alpha_r, alpha_i, i, j, &a3 ); i = 0; j = 4; bli_getijm( i, j, &a3, &alpha_r, &alpha_i ); alpha_r *= -1.0; alpha_i *= -1.0; bli_setijm( alpha_r, alpha_i, i, j, &a3 ); // Print the matrix again so we can see the update elements. bli_printm( "matrix 'a3' (modified state)", &a3, "%5.1f", "" ); // Free the memory arrays we allocated. free( p1 ); // Free the objects we created. bli_obj_free( &a2 ); bli_obj_free( &a3 ); return 0; } // ----------------------------------------------------------------------------- void init_dmatrix_by_rows( dim_t m, dim_t n, double* a, inc_t rs, inc_t cs ) { dim_t i, j; double alpha = 0.0; // Step through a matrix by rows, assigning each element a unique // value, starting at 0. for ( i = 0; i < m; ++i ) { for ( j = 0; j < n; ++j ) { double* a_ij = a + i*rs + j*cs; *a_ij = alpha; alpha += 1.0; } } } void init_dmatrix_by_cols( dim_t m, dim_t n, double* a, inc_t rs, inc_t cs ) { dim_t i, j; double alpha = 0.0; // Step through a matrix by columns, assigning each element a unique // value, starting at 0. for ( j = 0; j < n; ++j ) { for ( i = 0; i < m; ++i ) { double* a_ij = a + i*rs + j*cs; *a_ij = alpha; alpha += 1.0; } } } void init_dobj_by_cols( obj_t* a ) { dim_t m = bli_obj_length( a ); dim_t n = bli_obj_width( a ); dim_t i, j; double alpha = 0.0; // Step through a matrix by columns, assigning each element a unique // value, starting at 0. for ( j = 0; j < n; ++j ) { for ( i = 0; i < m; ++i ) { bli_setijm( alpha, 0.0, i, j, a ); alpha += 1.0; } } } void init_zobj_by_cols( obj_t* a ) { dim_t m = bli_obj_length( a ); dim_t n = bli_obj_width( a ); dim_t i, j; double alpha = 0.0; // Step through a matrix by columns, assigning each real and imaginary // element a unique value, starting at 0. for ( j = 0; j < n; ++j ) { for ( i = 0; i < m; ++i ) { bli_setijm( alpha, alpha + 1.0, i, j, a ); alpha += 2.0; } } } blis-0.9.0/examples/oapi/03obj_view.c000066400000000000000000000170711422157504600173460ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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 The University of Texas 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 COPYRIGHT HOLDER 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. */ #include #include #include "blis.h" void init_dmatrix_by_rows( dim_t m, dim_t n, double* a, inc_t rs, inc_t cs ); void init_dmatrix_by_cols( dim_t m, dim_t n, double* a, inc_t rs, inc_t cs ); void init_dobj_by_cols( obj_t* a ); void init_zobj_by_cols( obj_t* a ); int main( int argc, char** argv ) { obj_t a1, a2; obj_t v1, v2, v3, v4, v5; num_t dt; dim_t m, n; inc_t rs, cs; dim_t i, j; dim_t mv, nv; // // This file demonstrates creating and submatrix views into existing matrices. // // // Example 1: Create an object and then create a submatrix view. // printf( "\n#\n# -- Example 1 --\n#\n\n" ); // We'll use these parameters for the following examples. dt = BLIS_DOUBLE; m = 6; n = 7; rs = 1; cs = m; // Create an object a1 using bli_obj_create(). bli_obj_create( dt, m, n, rs, cs, &a1 ); // Initialize a1 to contain known values. init_dobj_by_cols( &a1 ); bli_printm( "matrix 'a1' (initial state)", &a1, "%5.1f", "" ); // Acquire a 4x3 submatrix view into a1 at (i,j) offsets (1,2). i = 1; j = 2; mv = 4; nv = 3; bli_acquire_mpart( i, j, mv, nv, &a1, &v1 ); bli_printm( "4x3 submatrix 'v1' at offsets (1,2)", &v1, "%5.1f", "" ); // NOTE: Submatrix views should never be passed to bli_obj_free(). It // will not cause an immediate error, but it is bad practice. Instead, // you should only release the objects that were created directy via // bli_obj_create(). In the above example, that means only object a1 // would be passed to bli_obj_free(). // // Example 2: Modify the contents of a submatrix view. // printf( "\n#\n# -- Example 2 --\n#\n\n" ); // Modify the first three elements of the first column. bli_setijm( -3.0, 0.0, 0, 0, &v1 ); bli_setijm( -4.0, 0.0, 1, 0, &v1 ); bli_setijm( -5.0, 0.0, 2, 0, &v1 ); // Modify the first three elements of the second column. bli_setijm( -6.0, 0.0, 0, 1, &v1 ); bli_setijm( -7.0, 0.0, 1, 1, &v1 ); bli_setijm( -8.0, 0.0, 2, 1, &v1 ); // Print the matrix again so we can see the update elements. bli_printm( "submatrix view 'v1' (modified state)", &v1, "%5.1f", "" ); bli_printm( "matrix 'a1' (indirectly modified due to changes to 'v1')", &a1, "%5.1f", "" ); // // Example 3: Create a submatrix view that is "too big". // printf( "\n#\n# -- Example 3 --\n#\n\n" ); // bli_acquire_mpart() will safely truncate your requested submatrix // view dimensions (or even the offsets) if they extend beyond the // bounds of the parent object. bli_printm( "matrix 'a1' (current state)", &a1, "%5.1f", "" ); // Acquire a 4x3 submatrix view into a1 at offsets (4,2). Notice how // the requested view contains four rows, but the view is created with // only two rows because the starting m offset of 4 leaves only two rows // left in the parent matrix. bli_acquire_mpart( 4, 2, 4, 3, &a1, &v2 ); bli_printm( "4x3 submatrix 'v2' at offsets (4,2) -- two rows truncated for safety", &v2, "%5.1f", "" ); // // Example 4: Create a bufferless object, attach an external buffer, and // then create a submatrix view. // printf( "\n#\n# -- Example 4 --\n#\n\n" ); // Create a object with known elements using the same approach as the // previous example file. double* p1 = malloc( m * n * sizeof( double ) ); init_dmatrix_by_cols( m, n, p1, rs, cs ); bli_obj_create_with_attached_buffer( dt, m, n, p1, rs, cs, &a2 ); bli_printm( "matrix 'a2' (initial state)", &a2, "%5.1f", "" ); // Acquire a 3x4 submatrix view at offset (2,3). bli_acquire_mpart( 2, 3, 3, 4, &a2, &v3 ); bli_printm( "3x4 submatrix view 'v3' at offsets (2,3)", &v3, "%5.1f", "" ); // // Example 5: Use a submatrix view to set a region of a larger matrix to // zero. // printf( "\n#\n# -- Example 5 --\n#\n\n" ); bli_printm( "3x4 submatrix view 'v3' at offsets (2,3)", &v3, "%5.1f", "" ); bli_setm( &BLIS_ZERO, &v3 ); bli_printm( "3x4 submatrix view 'v3' (zeroed out)", &v3, "%5.1f", "" ); bli_printm( "matrix 'a2' (modified state)", &a2, "%5.1f", "" ); // // Example 6: Obtain a submatrix view into a submatrix view. // printf( "\n#\n# -- Example 6 --\n#\n\n" ); bli_acquire_mpart( 1, 1, 5, 6, &a2, &v4 ); bli_printm( "5x6 submatrix view 'v4' at offsets (1,1) of 'a2'", &v4, "%5.1f", "" ); bli_acquire_mpart( 1, 0, 4, 5, &v4, &v5 ); bli_printm( "4x5 submatrix view 'v5' at offsets (1,0) of 'v4'", &v5, "%5.1f", "" ); // Free the memory arrays we allocated. free( p1 ); // Free the objects we created. bli_obj_free( &a1 ); return 0; } // ----------------------------------------------------------------------------- void init_dmatrix_by_rows( dim_t m, dim_t n, double* a, inc_t rs, inc_t cs ) { dim_t i, j; double alpha = 0.0; // Step through a matrix by rows, assigning each element a unique // value, starting at 0. for ( i = 0; i < m; ++i ) { for ( j = 0; j < n; ++j ) { double* a_ij = a + i*rs + j*cs; *a_ij = alpha; alpha += 1.0; } } } void init_dmatrix_by_cols( dim_t m, dim_t n, double* a, inc_t rs, inc_t cs ) { dim_t i, j; double alpha = 0.0; // Step through a matrix by columns, assigning each element a unique // value, starting at 0. for ( j = 0; j < n; ++j ) { for ( i = 0; i < m; ++i ) { double* a_ij = a + i*rs + j*cs; *a_ij = alpha; alpha += 1.0; } } } void init_dobj_by_cols( obj_t* a ) { dim_t m = bli_obj_length( a ); dim_t n = bli_obj_width( a ); dim_t i, j; double alpha = 0.0; // Step through a matrix by columns, assigning each element a unique // value, starting at 0. for ( j = 0; j < n; ++j ) { for ( i = 0; i < m; ++i ) { bli_setijm( alpha, 0.0, i, j, a ); alpha += 1.0; } } } void init_zobj_by_cols( obj_t* a ) { dim_t m = bli_obj_length( a ); dim_t n = bli_obj_width( a ); dim_t i, j; double alpha = 0.0; // Step through a matrix by columns, assigning each real and imaginary // element a unique value, starting at 0. for ( j = 0; j < n; ++j ) { for ( i = 0; i < m; ++i ) { bli_setijm( alpha, alpha + 1.0, i, j, a ); alpha += 2.0; } } } blis-0.9.0/examples/oapi/04level0.c000066400000000000000000000143071422157504600167310ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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 The University of Texas 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 COPYRIGHT HOLDER 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. */ #include #include "blis.h" int main( int argc, char** argv ) { obj_t alpha, beta, gamma, kappa, zeta; num_t dt; double gamma_d; // // This file demonstrates working with scalar objects. // // // Example 1: Create a scalar (1x1) object. // dt = BLIS_DOUBLE; // The easiest way to create a scalar object is with the following // convenience function. bli_obj_create_1x1( dt, &alpha ); // We could, of course, create an object using our more general-purpose // function, using m = n = 1. bli_obj_create( dt, 1, 1, 0, 0, &beta ); // We can even attach an external scalar. This function, unlike // bli_obj_create_1x1() and bli_obj_create(), does not result in any // memory allocation. bli_obj_create_1x1_with_attached_buffer( dt, &gamma_d, &gamma ); // There is one more way to create an object. Like the previous method, // it also avoids memory allocation by referencing a special "internal" // scalar that is invisibly part of every object. bli_obj_scalar_init_detached( dt, &kappa ); // Digression: In the most common cases, there is no need to create scalar // objects to begin with. That's because BLIS comes with three ready-to-use // globally-scoped scalar objects: // // obj_t BLIS_MINUS_ONE; // obj_t BLIS_ZERO; // obj_t BLIS ONE; // // Each of these special objects is provided by blis.h. They can be used // wherever a scalar object is expected as an input operand regardless of // the datatype of your other operands. Note that you should never try to // modify these global scalar objects directly, nor should you ever try to // perform an operation *on* the objects (that is, you should never try to // update their values, though you can always perform operations *with* // them--that's the whole point!). // // Example 2: Set the value of an existing scalar object. // printf( "\n#\n# -- Example 2 --\n#\n\n" ); // Once you've created an object, you can set its value via setsc. As with // setijm, setsc takes a real and imaginary value, but you can ignore the // imaginary argument if your object is real. And even if you pass in a // non-zero value, it is ignored for real objects. bli_setsc( -4.0, 0.0, &alpha ); bli_setsc( 3.0, 1.0, &beta ); bli_setsc( 0.5, 0.0, &kappa ); bli_setsc( 10.0, 0.0, &gamma ); // BLIS does not have a special print function for scalars, but since a // 1x1 is also a vector and a matrix, we can use printv or printm. bli_printm( "alpha:", &alpha, "%4.1f", "" ); bli_printm( "beta:", &beta, "%4.1f", "" ); bli_printm( "kappa:", &kappa, "%4.1f", "" ); bli_printm( "gamma:", &gamma, "%4.1f", "" ); // // Example 3: Create and set the value of a complex scalar object. // printf( "\n#\n# -- Example 3 --\n#\n\n" ); // Create one more scalar, this time a complex scalar, to show how it // can be used. bli_obj_create_1x1( BLIS_DCOMPLEX, &zeta ); bli_setsc( 3.3, -4.4, &zeta ); bli_printm( "zeta (complex):", &zeta, "%4.1f", "" ); // // Example 4: Copy scalar objects. // printf( "\n#\n# -- Example 4 --\n#\n\n" ); // We can copy scalars amongst one another, and we can use the global // scalar constants for input operands. bli_copysc( &beta, &gamma ); bli_printm( "gamma (overwritten with beta):", &gamma, "%4.1f", "" ); bli_copysc( &BLIS_ONE, &gamma ); bli_printm( "gamma (overwritten with BLIS_ONE):", &gamma, "%4.1f", "" ); // // Example 5: Perform other operations on scalar objects. // printf( "\n#\n# -- Example 5 --\n#\n\n" ); // BLIS defines a range of basic floating-point operations on scalars. bli_addsc( &beta, &gamma ); bli_printm( "gamma := gamma + beta", &gamma, "%4.1f", "" ); bli_subsc( &alpha, &gamma ); bli_printm( "gamma := gamma - alpha", &gamma, "%4.1f", "" ); bli_divsc( &kappa, &gamma ); bli_printm( "gamma := gamma / kappa", &gamma, "%4.1f", "" ); bli_sqrtsc( &gamma, &gamma ); bli_printm( "gamma := sqrt( gamma )", &gamma, "%4.1f", "" ); bli_normfsc( &alpha, &alpha ); bli_printm( "alpha := normf( alpha ) # normf() = abs() in real domain.", &alpha, "%4.1f", "" ); // Note that normfsc() allows complex input objects, but requires that the // output operand (the second operand) be a real object. bli_normfsc( &zeta, &alpha ); bli_printm( "alpha := normf( zeta ) # normf() = complex modulus in complex domain.", &alpha, "%4.1f", "" ); bli_invertsc( &gamma ); bli_printm( "gamma := 1.0 / gamma", &gamma, "%4.2f", "" ); // Only free the objects that resulted in actual allocation. bli_obj_free( &alpha ); bli_obj_free( &beta ); bli_obj_free( &zeta ); return 0; } // ----------------------------------------------------------------------------- blis-0.9.0/examples/oapi/05level1v.c000066400000000000000000000130501422157504600171130ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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 The University of Texas 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 COPYRIGHT HOLDER 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. */ #include #include "blis.h" int main( int argc, char** argv ) { obj_t alpha, beta, gamma; obj_t x, y, z, w, a; num_t dt; dim_t m, n; inc_t rs, cs; // // This file demonstrates working with vector objects and the level-1v // operations. // // // Example 1: Create vector objects and then broadcast (copy) scalar // values to all elements. // printf( "\n#\n# -- Example 1 --\n#\n\n" ); // Create a few vectors to work with. We make them all of the same length // so that we can perform operations between them. // NOTE: We've chosen to use row vectors here (1x4) instead of column // vectors (4x1) to allow for easier reading of standard output (less // scrolling). dt = BLIS_DOUBLE; m = 1; n = 4; rs = 0; cs = 0; bli_obj_create( dt, m, n, rs, cs, &x ); bli_obj_create( dt, m, n, rs, cs, &y ); bli_obj_create( dt, m, n, rs, cs, &z ); bli_obj_create( dt, m, n, rs, cs, &w ); bli_obj_create( dt, m, n, rs, cs, &a ); // Let's also create and initialize some scalar objects. bli_obj_create_1x1( dt, &alpha ); bli_obj_create_1x1( dt, &beta ); bli_obj_create_1x1( dt, &gamma ); bli_setsc( 2.0, 0.0, &alpha ); bli_setsc( 0.2, 0.0, &beta ); bli_setsc( 3.0, 0.0, &gamma ); bli_printm( "alpha:", &alpha, "%4.1f", "" ); bli_printm( "beta:", &beta, "%4.1f", "" ); bli_printm( "gamma:", &gamma, "%4.1f", "" ); // Vectors can set by "broadcasting" a constant to every element. bli_setv( &BLIS_ONE, &x ); bli_setv( &alpha, &y ); bli_setv( &BLIS_ZERO, &z ); // Note that we can use printv or printm to print vectors since vectors // are also matrices. We choose to use printm because it honors the // orientation of the vector (row or column) when printing, whereas // printv always prints vectors as column vectors regardless of their // they are 1 x n or n x 1. bli_printm( "x := 1.0", &x, "%4.1f", "" ); bli_printm( "y := alpha", &y, "%4.1f", "" ); bli_printm( "z := 0.0", &z, "%4.1f", "" ); // // Example 2: Randomize a vector object. // printf( "\n#\n# -- Example 2 --\n#\n\n" ); // Set a vector to random values. bli_randv( &w ); bli_printm( "w := randv()", &w, "%4.1f", "" ); // // Example 3: Perform various element-wise operations on vector objects. // printf( "\n#\n# -- Example 3 --\n#\n\n" ); // Copy a vector. bli_copyv( &w, &a ); bli_printm( "a := w", &a, "%4.1f", "" ); // Add and subtract vectors. bli_addv( &y, &a ); bli_printm( "a := a + y", &a, "%4.1f", "" ); bli_subv( &w, &a ); bli_printm( "a := a - w", &a, "%4.1f", "" ); // Scale a vector (destructive). bli_scalv( &beta, &a ); bli_printm( "a := beta * a", &a, "%4.1f", "" ); // Scale a vector (non-destructive). bli_scal2v( &gamma, &a, &z ); bli_printm( "z := gamma * a", &z, "%4.1f", "" ); // Scale and accumulate between vectors. bli_axpyv( &alpha, &w, &x ); bli_printm( "x := x + alpha * w", &x, "%4.1f", "" ); bli_xpbyv( &w, &BLIS_MINUS_ONE, &x ); bli_printm( "x := -1.0 * x + w", &x, "%4.1f", "" ); // Invert a vector element-wise. bli_invertv( &y ); bli_printm( "y := 1 / y", &y, "%4.1f", "" ); // Swap two vectors. bli_swapv( &x, &y ); bli_printm( "x (after swapping with y)", &x, "%4.1f", "" ); bli_printm( "y (after swapping with x)", &y, "%4.1f", "" ); // // Example 4: Perform contraction-like operations on vector objects. // printf( "\n#\n# -- Example 4 --\n#\n\n" ); // Perform a dot product. bli_dotv( &a, &z, &gamma ); bli_printm( "gamma := a * z (dot product)", &gamma, "%5.2f", "" ); // Perform an extended dot product. bli_dotxv( &alpha, &a, &z, &BLIS_ONE, &gamma ); bli_printm( "gamma := 1.0 * gamma + alpha * a * z (accumulate scaled dot product)", &gamma, "%5.2f", "" ); // Free the objects. bli_obj_free( &alpha ); bli_obj_free( &beta ); bli_obj_free( &gamma ); bli_obj_free( &x ); bli_obj_free( &y ); bli_obj_free( &z ); bli_obj_free( &w ); bli_obj_free( &a ); return 0; } // ----------------------------------------------------------------------------- blis-0.9.0/examples/oapi/06level1m.c000066400000000000000000000156151422157504600171140ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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 The University of Texas 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 COPYRIGHT HOLDER 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. */ #include #include "blis.h" int main( int argc, char** argv ) { obj_t alpha, beta, gamma; obj_t a, b, c, d, e, f, g, h; num_t dt; dim_t m, n; inc_t rs, cs; // // This file demonstrates working with matrix objects and the level-1m // operations. // // // Example 1: Create matrix objects and then broadcast (copy) scalar // values to all elements. // printf( "\n#\n# -- Example 1 --\n#\n\n" ); // Create a few matrices to work with. We make them all of the same // dimensions so that we can perform operations between them. dt = BLIS_DOUBLE; m = 2; n = 3; rs = 0; cs = 0; bli_obj_create( dt, m, n, rs, cs, &a ); bli_obj_create( dt, m, n, rs, cs, &b ); bli_obj_create( dt, m, n, rs, cs, &c ); bli_obj_create( dt, m, n, rs, cs, &d ); bli_obj_create( dt, m, n, rs, cs, &e ); // Let's also create and initialize some scalar objects. bli_obj_create_1x1( dt, &alpha ); bli_obj_create_1x1( dt, &beta ); bli_obj_create_1x1( dt, &gamma ); bli_setsc( 2.0, 0.0, &alpha ); bli_setsc( 0.2, 0.0, &beta ); bli_setsc( 3.0, 0.0, &gamma ); bli_printm( "alpha:", &alpha, "%4.1f", "" ); bli_printm( "beta:", &beta, "%4.1f", "" ); bli_printm( "gamma:", &gamma, "%4.1f", "" ); // Matrices, like vectors, can set by "broadcasting" a constant to every // element. bli_setm( &BLIS_ONE, &a ); bli_setm( &alpha, &b ); bli_setm( &BLIS_ZERO, &c ); bli_printm( "a := 1.0", &a, "%4.1f", "" ); bli_printm( "b := alpha", &b, "%4.1f", "" ); bli_printm( "c := 0.0", &c, "%4.1f", "" ); // // Example 2: Randomize a matrix object. // printf( "\n#\n# -- Example 2 --\n#\n\n" ); // Set a matrix to random values. bli_randm( &e ); bli_printm( "e (randomized):", &e, "%4.1f", "" ); // // Example 3: Perform element-wise operations on matrices. // printf( "\n#\n# -- Example 3 --\n#\n\n" ); // Copy a matrix. bli_copym( &e, &d ); bli_printm( "d := e", &d, "%4.1f", "" ); // Add and subtract vectors. bli_addm( &a, &d ); bli_printm( "d := d + a", &d, "%4.1f", "" ); bli_subm( &a, &e ); bli_printm( "e := e - a", &e, "%4.1f", "" ); // Scale a matrix (destructive). bli_scalm( &alpha, &e ); bli_printm( "e := alpha * e", &e, "%4.1f", "" ); // Scale a matrix (non-destructive). bli_scal2m( &beta, &e, &c ); bli_printm( "c := beta * e", &c, "%4.1f", "" ); // Scale and accumulate between matrices. bli_axpym( &alpha, &a, &c ); bli_printm( "c := c + alpha * a", &c, "%4.1f", "" ); // // Example 4: Copy and transpose a matrix. // printf( "\n#\n# -- Example 4 --\n#\n\n" ); // Create an n-by-m matrix into which we can copy-transpose an m-by-n // matrix. bli_obj_create( dt, n, m, rs, cs, &f ); // Initialize all of 'f' to -1.0 to simulate junk values. bli_setm( &BLIS_MINUS_ONE, &f ); bli_printm( "e:", &e, "%4.1f", "" ); bli_printm( "f (initial value):", &f, "%4.1f", "" ); // Since we are going to copy 'e' to 'f', we need to indicate a transpose // on 'e', the input operand. Transposition can be indicated by setting a // bit in the object. Since it always starts out as "no transpose", we can // simply toggle the bit. bli_obj_toggle_trans( &e ); // Another way to mark and object for transposition is to set it directly. //bli_obj_set_onlytrans( BLIS_TRANSPOSE, &e ); // A third way is to "apply" a transposition. This is equivalent to toggling // the transposition when the value being applied is BLIS_TRANSPOSE. If // the value applied is BLIS_NO_TRANSPOSE, the transposition bit in the // targeted object is unaffected. (Applying transposes is more useful in // practice when the 'trans' argument is a variable and not a constant // literal.) //bli_obj_apply_trans( BLIS_TRANSPOSE, &e ); //bli_obj_apply_trans( BLIS_NO_TRANSPOSE, &e ); //bli_obj_apply_trans( trans, &e ); // Copy 'e' to 'f', transposing 'e' in the process. Notice that we haven't // modified any properties of 'd'. It's the source operand that matters // when marking an operand for transposition, not the destination. bli_copym( &e, &f ); bli_printm( "f (copied value):", &f, "%4.1f", "" ); // // Example 5: Copy and Hermitian-transpose a matrix. // printf( "\n#\n# -- Example 5 --\n#\n\n" ); // Create an n-by-m complex matrix into which we can Hermitian-transpose // (or, conjugate-transpose) another complex (m-by-n) matrix. dt = BLIS_DCOMPLEX; bli_obj_create( dt, m, n, rs, cs, &g ); bli_obj_create( dt, n, m, rs, cs, &h ); // Randomize 'g', the input operand. bli_randm( &g ); // Initialize all of 'h' to -1.0 to simulate junk values. bli_setm( &BLIS_MINUS_ONE, &h ); bli_printm( "g:", &g, "%4.1f", "" ); bli_printm( "h (initial value):", &h, "%4.1f", "" ); // Set both the transpose and conjugation bits. bli_obj_toggle_trans( &g ); bli_obj_toggle_conj( &g ); // Copy 'g' to 'h', conjugating and transposing 'g' in the process. // Once again, notice that it's the source operand that we've marked for // conjugation. bli_copym( &g, &h ); bli_printm( "h (copied value):", &h, "%4.1f", "" ); // Free the objects. bli_obj_free( &alpha ); bli_obj_free( &beta ); bli_obj_free( &gamma ); bli_obj_free( &a ); bli_obj_free( &b ); bli_obj_free( &c ); bli_obj_free( &d ); bli_obj_free( &e ); bli_obj_free( &f ); bli_obj_free( &g ); bli_obj_free( &h ); return 0; } // ----------------------------------------------------------------------------- blis-0.9.0/examples/oapi/07level1m_diag.c000066400000000000000000000260361422157504600201000ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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 The University of Texas 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 COPYRIGHT HOLDER 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. */ #include #include "blis.h" int main( int argc, char** argv ) { num_t dt; dim_t m, n; inc_t rs, cs; // // This file demonstrates level-1m operations on structured matrices. // // // Example 1: Initialize the upper triangle of a matrix to random values. // printf( "\n#\n# -- Example 1 --\n#\n\n" ); obj_t a; // Create a matrix to work with. dt = BLIS_DOUBLE; m = 5; n = 5; rs = 0; cs = 0; bli_obj_create( dt, m, n, rs, cs, &a ); // First, we mark the matrix structure as triangular. bli_obj_set_struc( BLIS_TRIANGULAR, &a ); // Next, we specify whether the lower part or the upper part is to be // recognized as the "stored" region (which we call the uplo field). The // strictly opposite part (in this case, the strictly lower region) will // be *assumed* to be zero during computation. However, when printed out, // the strictly lower part may contain junk values. bli_obj_set_uplo( BLIS_UPPER, &a ); // Now set the upper triangle to random values. bli_randm( &a ); bli_printm( "a: randomize upper part (lower part may contain garbage)", &a, "%4.1f", "" ); // // Example 2: Initialize the upper triangle of a matrix to random values // but also explicitly set the strictly lower triangle to zero. // printf( "\n#\n# -- Example 2 --\n#\n\n" ); obj_t b, bl; // Create a matrix to work with. dt = BLIS_DOUBLE; m = 5; n = 5; rs = 0; cs = 0; bli_obj_create( dt, m, n, rs, cs, &b ); // Set structure and uplo. bli_obj_set_struc( BLIS_TRIANGULAR, &b ); bli_obj_set_uplo( BLIS_UPPER, &b ); // Create an alias, 'bl', of the original object 'b'. Both objects will // refer to the same underlying matrix elements, but now we will have two // different "views" into the matrix. Aliases are simply "shallow copies" // of the objects, meaning no additional memory allocation takes place. // Therefore it is up to the API user (you) to make sure that you only // free the original object (or exactly one of the aliases). bli_obj_alias_to( &b, &bl ); // Digression: Each object contains a diagonal offset (even vectors), // even if it is never needed. The diagonal offset for a newly-created // object (ie: objects created via bli_obj_create*()) defaults to 0, // meaning it intersects element (0,0), but it can be changed. When the // diagonal offset delta is positive, the diagonal intersects element // (0,delta). When the diagonal offset is negative, the diagonal // intersects element (-delta,0). In other words, think of element (0,0) // as the origin of a coordinate plane, with the diagonal being the // x-axis value. // Set the diagonal offset of 'bl' to -1. bli_obj_set_diag_offset( -1, &bl ); // Set the uplo field of 'bl' to "lower". bli_obj_set_uplo( BLIS_LOWER, &bl ); // Set the upper triangle of 'b' to random values. bli_randm( &b ); // Set the strictly lower triangle of 'b' to zero (by setting the lower // triangle of 'bl' to zero). bli_setm( &BLIS_ZERO, &bl ); bli_printm( "b: randomize upper part; set strictly lower part to 0.0", &b, "%4.1f", "" ); // You may not see the effect of setting the strictly lower part to zero, // since those values may already be zero (instead of random junk). So // let's set it to something you'll notice, like -1.0. bli_setm( &BLIS_MINUS_ONE, &bl ); bli_printm( "b: randomize upper part; set strictly lower part to -1.0", &b, "%4.1f", "" ); // // Example 3: Copy the lower triangle of an existing object to a newly // created (but otherwise uninitialized) object. // printf( "\n#\n# -- Example 3 --\n#\n\n" ); obj_t c; // Create a matrix to work with. dt = BLIS_DOUBLE; m = 5; n = 5; rs = 0; cs = 0; bli_obj_create( dt, m, n, rs, cs, &c ); // Reset the diagonal offset of 'bl' to 0. bli_obj_set_diag_offset( 0, &bl ); // Copy the lower triangle of matrix 'b' from Example 2 to object 'c'. // This should give us -1.0 in the strictly lower part and some non-zero // random values along the diagonal. Note that since 'c' is starting out // uninitialized, the strictly upper part could contain junk. bli_copym( &bl, &c ); bli_printm( "c: copy lower part of b (upper part may contain garbage)", &c, "%4.1f", "" ); // Notice that the structure and uplo properties of 'c' were set to their // default values, BLIS_GENERAL and BLIS_DENSE, respectively. Thus, it is // the structure and uplo of the *source* operand that controls what gets // copied, regardless of the structure/uplo of the destination. To // demonstrate this further, let's see what happens when we copy 'bl' // (which is lower triangular) to 'a' (which is upper triangular). bli_copym( &bl, &a ); // The result is that the lower part (diagonal and strictly lower part) is // copied into 'a', but the elements in the strictly upper part of 'a' are // unaffected. Note, however, that 'a' is still marked as upper triangular // and so in future computations where 'a' is an input operand, the -1.0 // values that were copied from 'bl' into the lower triangle will be // ignored. Generally speaking, level-1m operations on triangular matrices // ignore the "unstored" regions of input operands because they are assumed // to be zero). bli_printm( "a: copy lower triangular bl to upper triangular a", &a, "%4.1f", "" ); // // Example 4: Copy the lower triangle of an existing object into the // upper triangle of an existing object. // printf( "\n#\n# -- Example 4 --\n#\n\n" ); obj_t d; // Create a matrix to work with. dt = BLIS_DOUBLE; m = 5; n = 5; rs = 0; cs = 0; bli_obj_create( dt, m, n, rs, cs, &d ); // Let's start by setting entire destination matrix to zero. bli_setm( &BLIS_ZERO, &d ); bli_printm( "d: initial value (all zeros)", &d, "%4.1f", "" ); // Recall that 'bl' is marked as lower triangular with a diagonal offset // of 0. Also recall that 'bl' is an alias of 'b', which is now fully // initialized. But let's change a few values manually so we can later // see the full effect of the transposition. bli_setijm( 2.0, 0.0, 2, 0, &bl ); bli_setijm( 3.0, 0.0, 3, 0, &bl ); bli_setijm( 4.0, 0.0, 4, 0, &bl ); bli_setijm( 3.1, 0.0, 3, 1, &bl ); bli_setijm( 3.2, 0.0, 3, 2, &bl ); bli_printm( "bl: lower triangular bl is aliased to b", &bl, "%4.1f", "" ); // We want to pluck out the lower triangle and transpose it into the upper // triangle of 'd'. bli_obj_toggle_trans( &bl ); // Now we copy the transpose of the lower part of 'bl' into the upper // part of 'd'. (Again, notice that we haven't modified any properties of // 'd'. It's the source operand that matters, not the destination!) bli_copym( &bl, &d ); bli_printm( "d: transpose of lower triangular of bl copied to d", &d, "%4.1f", "" ); // // Example 5: Create a rectangular matrix (m > n) with a lower trapezoid // containing random values, then set the strictly upper // triangle to zeros. // printf( "\n#\n# -- Example 5 --\n#\n\n" ); obj_t e, el; // Create a matrix to work with. dt = BLIS_DOUBLE; m = 6; n = 4; rs = 0; cs = 0; bli_obj_create( dt, m, n, rs, cs, &e ); // Initialize the entire matrix to -1.0 to simulate junk values. bli_setm( &BLIS_MINUS_ONE, &e ); bli_printm( "e: initial value (all -1.0)", &e, "%4.1f", "" ); // Create an alias to work with. bli_obj_alias_to( &e, &el ); // Set structure and uplo of 'el'. bli_obj_set_struc( BLIS_TRIANGULAR, &el ); bli_obj_set_uplo( BLIS_LOWER, &el ); // Digression: Notice that "triangular" structure does not require that // the matrix be square. Rather, it simply means that either the part above // or below the diagonal will be assumed to be zero. // Randomize the lower trapezoid. bli_randm( &el ); bli_printm( "e: after lower trapezoid randomized", &e, "%4.1f", "" ); // Move the diagonal offset of 'el' to 1 and flip the uplo field to // "upper". bli_obj_set_diag_offset( 1, &el ); bli_obj_set_uplo( BLIS_UPPER, &el ); // Set the upper triangle to zero. bli_setm( &BLIS_ZERO, &el ); bli_printm( "e: after upper triangle set to zero", &e, "%4.1f", "" ); // // Example 6: Create an upper Hessenberg matrix of random values and then // set the "unstored" values to zero. // printf( "\n#\n# -- Example 6 --\n#\n\n" ); obj_t h, hl; // Create a matrix to work with. dt = BLIS_DOUBLE; m = 5; n = 5; rs = 0; cs = 0; bli_obj_create( dt, m, n, rs, cs, &h ); // Initialize the entire matrix to -1.0 to simulate junk values. bli_setm( &BLIS_MINUS_ONE, &h ); bli_printm( "h: initial value (all -1.0)", &h, "%4.1f", "" ); // Set the diagonal offset of 'h' to -1. bli_obj_set_diag_offset( -1, &h ); // Set the structure and uplo of 'h'. bli_obj_set_struc( BLIS_TRIANGULAR, &h ); bli_obj_set_uplo( BLIS_UPPER, &h ); // Randomize the elements on and above the first subdiagonal. bli_randm( &h ); bli_printm( "h: after randomizing above first subdiagonal", &h, "%4.1f", "" ); // Create an alias to work with. bli_obj_alias_to( &h, &hl ); // Flip the uplo of 'hl' and move the diagonal down by one. bli_obj_set_uplo( BLIS_LOWER, &hl ); bli_obj_set_diag_offset( -2, &hl ); // Set the region strictly below the first subdiagonal (on or below // the second subdiagonal) to zero. bli_setm( &BLIS_ZERO, &hl ); bli_printm( "h: after setting elements below first subdiagonal to zero", &h, "%4.1f", "" ); // Free the objects. bli_obj_free( &a ); bli_obj_free( &b ); bli_obj_free( &c ); bli_obj_free( &d ); bli_obj_free( &e ); bli_obj_free( &h ); return 0; } // ----------------------------------------------------------------------------- blis-0.9.0/examples/oapi/08level2.c000066400000000000000000000230261422157504600167350ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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 The University of Texas 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 COPYRIGHT HOLDER 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. */ #include #include "blis.h" int main( int argc, char** argv ) { num_t dt; dim_t m, n; inc_t rs, cs; obj_t a, x, y, b; obj_t* alpha; obj_t* beta; // // This file demonstrates level-2 operations. // // // Example 1: Perform a general rank-1 update (ger) operation. // printf( "\n#\n# -- Example 1 --\n#\n\n" ); // Create some matrix and vector operands to work with. dt = BLIS_DOUBLE; m = 4; n = 5; rs = 0; cs = 0; bli_obj_create( dt, m, n, rs, cs, &a ); bli_obj_create( dt, m, 1, rs, cs, &x ); bli_obj_create( dt, 1, n, rs, cs, &y ); // Set alpha. alpha = &BLIS_ONE; // Initialize vectors 'x' and 'y'. bli_randv( &x ); bli_setv( &BLIS_MINUS_ONE, &y ); // Initialize 'a' to 1.0. bli_setm( &BLIS_ONE, &a ); bli_printm( "x: set to random values", &x, "%4.1f", "" ); bli_printm( "y: set to -1.0", &y, "%4.1f", "" ); bli_printm( "a: initial value", &a, "%4.1f", "" ); // a := a + alpha * x * y, where 'a' is general. bli_ger( alpha, &x, &y, &a ); bli_printm( "a: after ger", &a, "%4.1f", "" ); // Free the objects. bli_obj_free( &a ); bli_obj_free( &x ); bli_obj_free( &y ); // // Example 2: Perform a general matrix-vector multiply (gemv) operation. // printf( "\n#\n# -- Example 2 --\n#\n\n" ); // Create some matrix and vector operands to work with. dt = BLIS_DOUBLE; m = 4; n = 5; rs = 0; cs = 0; bli_obj_create( dt, m, n, rs, cs, &a ); bli_obj_create( dt, 1, n, rs, cs, &x ); bli_obj_create( dt, 1, m, rs, cs, &y ); // Notice that we created vectors 'x' and 'y' as row vectors, even though // we often think of them as column vectors so that the overall problem // dimensions remain conformal. Note that this flexibility only comes // from the fact that the operation requires those operands to be vectors. // If we were instead looking at an operation where the operands were of // general shape (such as with the gemm operation), then typically the // dimensions matter, and column vectors would not be interchangeable with // row vectors and vice versa. // Set the scalars to use. alpha = &BLIS_ONE; beta = &BLIS_ONE; // Initialize vectors 'x' and 'y'. bli_setv( &BLIS_ONE, &x ); bli_setv( &BLIS_ZERO, &y ); // Randomize 'a'. bli_randm( &a ); bli_printm( "a: randomized", &a, "%4.1f", "" ); bli_printm( "x: set to 1.0", &x, "%4.1f", "" ); bli_printm( "y: initial value", &y, "%4.1f", "" ); // y := beta * y + alpha * a * x, where 'a' is general. bli_gemv( alpha, &a, &x, beta, &y ); bli_printm( "y: after gemv", &y, "%4.1f", "" ); // Free the objects. bli_obj_free( &a ); bli_obj_free( &x ); bli_obj_free( &y ); // // Example 3: Perform a symmetric rank-1 update (syr) operation. // printf( "\n#\n# -- Example 3 --\n#\n\n" ); // Create some matrix and vector operands to work with. dt = BLIS_DOUBLE; m = 5; rs = 0; cs = 0; bli_obj_create( dt, m, m, rs, cs, &a ); bli_obj_create( dt, 1, m, rs, cs, &x ); // Set alpha. alpha = &BLIS_ONE; // Initialize vector 'x'. bli_randv( &x ); // Zero out all of matrix 'a'. This is optional, but will avoid possibly // displaying junk values in the unstored triangle. bli_setm( &BLIS_ZERO, &a ); // Mark matrix 'a' as symmetric and stored in the lower triangle, and // then randomize that lower triangle. bli_obj_set_struc( BLIS_SYMMETRIC, &a ); bli_obj_set_uplo( BLIS_LOWER, &a ); bli_randm( &a ); bli_printm( "x: set to random values", &x, "%4.1f", "" ); bli_printm( "a: initial value (zeros in upper triangle)", &a, "%4.1f", "" ); // a := a + alpha * x * x^T, where 'a' is symmetric and lower-stored. bli_syr( alpha, &x, &a ); bli_printm( "a: after syr", &a, "%4.1f", "" ); // Free the objects. bli_obj_free( &a ); bli_obj_free( &x ); // // Example 4: Perform a symmetric matrix-vector multiply (symv) operation. // printf( "\n#\n# -- Example 4 --\n#\n\n" ); // Create some matrix and vector operands to work with. dt = BLIS_DOUBLE; m = 5; rs = 0; cs = 0; bli_obj_create( dt, m, m, rs, cs, &a ); bli_obj_create( dt, 1, m, rs, cs, &x ); bli_obj_create( dt, 1, m, rs, cs, &y ); // Set the scalars to use. alpha = &BLIS_ONE; beta = &BLIS_ONE; // Initialize vectors 'x' and 'y'. bli_setv( &BLIS_ONE, &x ); bli_setv( &BLIS_ZERO, &y ); // Zero out all of matrix 'a'. This is optional, but will avoid possibly // displaying junk values in the unstored triangle. bli_setm( &BLIS_ZERO, &a ); // Mark matrix 'a' as symmetric and stored in the upper triangle, and // then randomize that upper triangle. bli_obj_set_struc( BLIS_SYMMETRIC, &a ); bli_obj_set_uplo( BLIS_UPPER, &a ); bli_randm( &a ); bli_printm( "a: randomized (zeros in lower triangle)", &a, "%4.1f", "" ); bli_printm( "x: set to 1.0", &x, "%4.1f", "" ); bli_printm( "y: initial value", &y, "%4.1f", "" ); // y := beta * y + alpha * a * x, where 'a' is symmetric and upper-stored. bli_symv( alpha, &a, &x, beta, &y ); bli_printm( "y: after symv", &y, "%4.1f", "" ); // Free the objects. bli_obj_free( &a ); bli_obj_free( &x ); bli_obj_free( &y ); // // Example 5: Perform a triangular matrix-vector multiply (trmv) operation. // printf( "\n#\n# -- Example 5 --\n#\n\n" ); // Create some matrix and vector operands to work with. dt = BLIS_DOUBLE; m = 5; rs = 0; cs = 0; bli_obj_create( dt, m, m, rs, cs, &a ); bli_obj_create( dt, 1, m, rs, cs, &x ); // Set the scalars to use. alpha = &BLIS_ONE; // Initialize vector 'x'. bli_setv( &BLIS_ONE, &x ); // Zero out all of matrix 'a'. This is optional, but will avoid possibly // displaying junk values in the unstored triangle. bli_setm( &BLIS_ZERO, &a ); // Mark matrix 'a' as triangular, stored in the lower triangle, and // having a non-unit diagonal. Then randomize that lower triangle. bli_obj_set_struc( BLIS_TRIANGULAR, &a ); bli_obj_set_uplo( BLIS_LOWER, &a ); bli_obj_set_diag( BLIS_NONUNIT_DIAG, &a ); bli_randm( &a ); bli_printm( "a: randomized (zeros in upper triangle)", &a, "%4.1f", "" ); bli_printm( "x: initial value", &x, "%4.1f", "" ); // x := alpha * a * x, where 'a' is triangular and lower-stored. bli_trmv( alpha, &a, &x ); bli_printm( "x: after trmv", &x, "%4.1f", "" ); // Free the objects. bli_obj_free( &a ); bli_obj_free( &x ); // // Example 6: Perform a triangular solve (trsv) operation. // printf( "\n#\n# -- Example 6 --\n#\n\n" ); // Create some matrix and vector operands to work with. dt = BLIS_DOUBLE; m = 5; rs = 0; cs = 0; bli_obj_create( dt, m, m, rs, cs, &a ); bli_obj_create( dt, 1, m, rs, cs, &b ); bli_obj_create( dt, 1, m, rs, cs, &y ); // Set the scalars to use. alpha = &BLIS_ONE; // Initialize vector 'x'. bli_setv( &BLIS_ONE, &b ); // Zero out all of matrix 'a'. This is optional, but will avoid possibly // displaying junk values in the unstored triangle. bli_setm( &BLIS_ZERO, &a ); // Mark matrix 'a' as triangular, stored in the lower triangle, and // having a non-unit diagonal. Then randomize that lower triangle. bli_obj_set_struc( BLIS_TRIANGULAR, &a ); bli_obj_set_uplo( BLIS_LOWER, &a ); bli_obj_set_diag( BLIS_NONUNIT_DIAG, &a ); bli_randm( &a ); // Load the diagonal. By setting the diagonal to something of greater // absolute value than the off-diagonal elements, we increase the odds // that the matrix is not singular (singular matrices have no inverse). bli_shiftd( &BLIS_TWO, &a ); bli_printm( "a: randomized (zeros in upper triangle)", &a, "%4.1f", "" ); bli_printm( "b: initial value", &b, "%4.1f", "" ); // solve a * x = alpha * b, where 'a' is triangular and lower-stored, and // overwrite b with the solution vector x. bli_trsv( alpha, &a, &b ); bli_printm( "b: after trsv", &b, "%4.1f", "" ); // We can confirm the solution by comparing the product of a and x to the // original value of b. bli_copyv( &b, &y ); bli_trmv( alpha, &a, &y ); bli_printm( "y: should equal initial value of b", &y, "%4.1f", "" ); // Free the objects. bli_obj_free( &a ); bli_obj_free( &b ); return 0; } // ----------------------------------------------------------------------------- blis-0.9.0/examples/oapi/09level3.c000066400000000000000000000226171422157504600167440ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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 The University of Texas 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 COPYRIGHT HOLDER 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. */ #include #include "blis.h" int main( int argc, char** argv ) { num_t dt; dim_t m, n, k; inc_t rs, cs; side_t side; obj_t a, b, c; obj_t* alpha; obj_t* beta; // // This file demonstrates level-3 operations. // // // Example 1: Perform a general matrix-matrix multiply (gemm) operation. // printf( "\n#\n# -- Example 1 --\n#\n\n" ); // Create some matrix operands to work with. dt = BLIS_DOUBLE; m = 4; n = 5; k = 3; rs = 0; cs = 0; bli_obj_create( dt, m, n, rs, cs, &c ); bli_obj_create( dt, m, k, rs, cs, &a ); bli_obj_create( dt, k, n, rs, cs, &b ); // Set the scalars to use. alpha = &BLIS_ONE; beta = &BLIS_ONE; // Initialize the matrix operands. bli_randm( &a ); bli_setm( &BLIS_ONE, &b ); bli_setm( &BLIS_ZERO, &c ); bli_printm( "a: randomized", &a, "%4.1f", "" ); bli_printm( "b: set to 1.0", &b, "%4.1f", "" ); bli_printm( "c: initial value", &c, "%4.1f", "" ); // c := beta * c + alpha * a * b, where 'a', 'b', and 'c' are general. bli_gemm( alpha, &a, &b, beta, &c ); bli_printm( "c: after gemm", &c, "%4.1f", "" ); // Free the objects. bli_obj_free( &a ); bli_obj_free( &b ); bli_obj_free( &c ); // // Example 1b: Perform a general matrix-matrix multiply (gemm) operation // with the left input operand (matrix A) transposed. // printf( "\n#\n# -- Example 1b --\n#\n\n" ); // Create some matrix operands to work with. dt = BLIS_DOUBLE; m = 4; n = 5; k = 3; rs = 0; cs = 0; bli_obj_create( dt, m, n, rs, cs, &c ); bli_obj_create( dt, k, m, rs, cs, &a ); bli_obj_create( dt, k, n, rs, cs, &b ); // Set the scalars to use. alpha = &BLIS_ONE; beta = &BLIS_ONE; // Initialize the matrix operands. bli_randm( &a ); bli_setm( &BLIS_ONE, &b ); bli_setm( &BLIS_ZERO, &c ); // Set the transpose bit in 'a'. bli_obj_toggle_trans( &a ); bli_printm( "a: randomized", &a, "%4.1f", "" ); bli_printm( "b: set to 1.0", &b, "%4.1f", "" ); bli_printm( "c: initial value", &c, "%4.1f", "" ); // c := beta * c + alpha * a^T * b, where 'a', 'b', and 'c' are general. bli_gemm( alpha, &a, &b, beta, &c ); bli_printm( "c: after gemm", &c, "%4.1f", "" ); // Free the objects. bli_obj_free( &a ); bli_obj_free( &b ); bli_obj_free( &c ); // // Example 2: Perform a symmetric rank-k update (syrk) operation. // printf( "\n#\n# -- Example 2 --\n#\n\n" ); // Create some matrix and vector operands to work with. dt = BLIS_DOUBLE; m = 5; k = 3; rs = 0; cs = 0; bli_obj_create( dt, m, m, rs, cs, &c ); bli_obj_create( dt, m, k, rs, cs, &a ); // Set alpha. alpha = &BLIS_ONE; // Initialize matrix operands. bli_setm( &BLIS_ZERO, &c ); bli_randm( &a ); // Mark matrix 'c' as symmetric and stored in the lower triangle, and // then randomize that lower triangle. bli_obj_set_struc( BLIS_SYMMETRIC, &c ); bli_obj_set_uplo( BLIS_LOWER, &c ); bli_randm( &c ); bli_printm( "a: set to random values", &a, "%4.1f", "" ); bli_printm( "c: initial value (zeros in upper triangle)", &c, "%4.1f", "" ); // c := c + alpha * a * a^T, where 'c' is symmetric and lower-stored. bli_syrk( alpha, &a, beta, &c ); bli_printm( "c: after syrk", &c, "%4.1f", "" ); // Free the objects. bli_obj_free( &c ); bli_obj_free( &a ); // // Example 3: Perform a symmetric matrix-matrix multiply (symm) operation. // printf( "\n#\n# -- Example 3 --\n#\n\n" ); // Create some matrix and vector operands to work with. dt = BLIS_DOUBLE; m = 5; n = 6; rs = 0; cs = 0; bli_obj_create( dt, m, m, rs, cs, &a ); bli_obj_create( dt, m, n, rs, cs, &b ); bli_obj_create( dt, m, n, rs, cs, &c ); // Set the scalars to use. alpha = &BLIS_ONE; beta = &BLIS_ONE; // Set the side operand. side = BLIS_LEFT; // Initialize matrices 'b' and 'c'. bli_setm( &BLIS_ONE, &b ); bli_setm( &BLIS_ZERO, &c ); // Zero out all of matrix 'a'. This is optional, but will avoid possibly // displaying junk values in the unstored triangle. bli_setm( &BLIS_ZERO, &a ); // Mark matrix 'a' as symmetric and stored in the upper triangle, and // then randomize that upper triangle. bli_obj_set_struc( BLIS_SYMMETRIC, &a ); bli_obj_set_uplo( BLIS_UPPER, &a ); bli_randm( &a ); bli_printm( "a: randomized (zeros in lower triangle)", &a, "%4.1f", "" ); bli_printm( "b: set to 1.0", &b, "%4.1f", "" ); bli_printm( "c: initial value", &c, "%4.1f", "" ); // c := beta * c + alpha * a * b, where 'a' is symmetric and upper-stored. // Note that the first 'side' operand indicates the side from which matrix // 'a' is multiplied into 'b'. bli_symm( side, alpha, &a, &b, beta, &c ); bli_printm( "c: after symm", &c, "%4.1f", "" ); // Free the objects. bli_obj_free( &a ); bli_obj_free( &b ); bli_obj_free( &c ); // // Example 4: Perform a triangular matrix-matrix multiply (trmm) operation. // printf( "\n#\n# -- Example 4 --\n#\n\n" ); // Create some matrix and vector operands to work with. dt = BLIS_DOUBLE; m = 5; n = 4; rs = 0; cs = 0; bli_obj_create( dt, m, m, rs, cs, &a ); bli_obj_create( dt, m, n, rs, cs, &b ); // Set the scalars to use. alpha = &BLIS_ONE; // Set the side operand. side = BLIS_LEFT; // Initialize matrix 'b'. bli_setm( &BLIS_ONE, &b ); // Zero out all of matrix 'a'. This is optional, but will avoid possibly // displaying junk values in the unstored triangle. bli_setm( &BLIS_ZERO, &a ); // Mark matrix 'a' as triangular, stored in the lower triangle, and // having a non-unit diagonal. Then randomize that lower triangle. bli_obj_set_struc( BLIS_TRIANGULAR, &a ); bli_obj_set_uplo( BLIS_LOWER, &a ); bli_obj_set_diag( BLIS_NONUNIT_DIAG, &a ); bli_randm( &a ); bli_printm( "a: randomized (zeros in upper triangle)", &a, "%4.1f", "" ); bli_printm( "b: initial value", &b, "%4.1f", "" ); // b := alpha * a * b, where 'a' is triangular and lower-stored. bli_trmm( side, alpha, &a, &b ); bli_printm( "x: after trmm", &b, "%4.1f", "" ); // Free the objects. bli_obj_free( &a ); bli_obj_free( &b ); // // Example 5: Perform a triangular solve with multiple right-hand sides // (trsm) operation. // printf( "\n#\n# -- Example 5 --\n#\n\n" ); // Create some matrix and vector operands to work with. dt = BLIS_DOUBLE; m = 5; n = 4; rs = 0; cs = 0; bli_obj_create( dt, m, m, rs, cs, &a ); bli_obj_create( dt, m, n, rs, cs, &b ); bli_obj_create( dt, m, n, rs, cs, &c ); // Set the scalars to use. alpha = &BLIS_ONE; // Set the side operand. side = BLIS_LEFT; // Initialize matrix 'b'. bli_setm( &BLIS_ONE, &b ); // Zero out all of matrix 'a'. This is optional, but will avoid possibly // displaying junk values in the unstored triangle. bli_setm( &BLIS_ZERO, &a ); // Mark matrix 'a' as triangular, stored in the lower triangle, and // having a non-unit diagonal. Then randomize that lower triangle. bli_obj_set_struc( BLIS_TRIANGULAR, &a ); bli_obj_set_uplo( BLIS_LOWER, &a ); bli_obj_set_diag( BLIS_NONUNIT_DIAG, &a ); bli_randm( &a ); // Load the diagonal. By setting the diagonal to something of greater // absolute value than the off-diagonal elements, we increase the odds // that the matrix is not singular (singular matrices have no inverse). bli_shiftd( &BLIS_TWO, &a ); bli_printm( "a: randomized (zeros in upper triangle)", &a, "%4.1f", "" ); bli_printm( "b: initial value", &b, "%4.1f", "" ); // solve a * x = alpha * b, where 'a' is triangular and lower-stored, and // overwrite b with the solution matrix x. bli_trsm( side, alpha, &a, &b ); bli_printm( "b: after trsm", &b, "%4.1f", "" ); // We can confirm the solution by comparing the product of a and x to the // original value of b. bli_copym( &b, &c ); bli_trmm( side, alpha, &a, &c ); bli_printm( "c: should equal initial value of b", &c, "%4.1f", "" ); // Free the objects. bli_obj_free( &a ); bli_obj_free( &b ); bli_obj_free( &c ); return 0; } // ----------------------------------------------------------------------------- blis-0.9.0/examples/oapi/10util.c000066400000000000000000000210471422157504600165130ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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 The University of Texas 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 COPYRIGHT HOLDER 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. */ #include #include "blis.h" int main( int argc, char** argv ) { obj_t norm1, normi, normf; obj_t x, y, a, b, c, d, e, f, g; num_t dt; dim_t m, n; inc_t rs, cs; // // This file demonstrates working with vector and matrix objects in the // context of various utility operations. // // // Example 1: Compute various vector norms. // printf( "\n#\n# -- Example 1 --\n#\n\n" ); // Create a few matrices to work with. m = 1; n = 5; rs = 0; cs = 0; bli_obj_create( BLIS_DOUBLE, m, n, rs, cs, &x ); bli_obj_create( BLIS_DCOMPLEX, m, n, rs, cs, &y ); // Let's also create some scalar objects to hold the norms. Note that when // computing the norm alpha of a vector 'x', the datatype of alpha must be // equal to the real projection of the datatype of 'x'. dt = BLIS_DOUBLE; bli_obj_create_1x1( dt, &norm1 ); bli_obj_create_1x1( dt, &normi ); bli_obj_create_1x1( dt, &normf ); // Initialize the vectors to random values. bli_randv( &x ); bli_randv( &y ); bli_printm( "x:", &x, "%4.1f", "" ); // Compute the one, infinity, and frobenius norms of 'x'. bli_norm1v( &x, &norm1 ); bli_normiv( &x, &normi ); bli_normfv( &x, &normf ); bli_printm( "x: 1-norm:", &norm1, "%4.1f", "" ); bli_printm( "x: infinity norm:", &normi, "%4.1f", "" ); bli_printm( "x: frobenius norm:", &normf, "%4.1f", "" ); bli_printm( "y:", &y, "%4.1f", "" ); // Compute the one, infinity, and frobenius norms of 'y'. Note that we // can reuse the same scalars from before for computing norms of // dcomplex matrices, since the real projection of dcomplex is double. bli_norm1v( &y, &norm1 ); bli_normiv( &y, &normi ); bli_normfv( &y, &normf ); bli_printm( "y: 1-norm:", &norm1, "%4.1f", "" ); bli_printm( "y: infinity norm:", &normi, "%4.1f", "" ); bli_printm( "y: frobenius norm:", &normf, "%4.1f", "" ); // // Example 2: Compute various matrix norms. // printf( "\n#\n# -- Example 2 --\n#\n\n" ); // Create a few matrices to work with. m = 5; n = 6; rs = 0; cs = 0; bli_obj_create( BLIS_DOUBLE, m, n, rs, cs, &a ); bli_obj_create( BLIS_DCOMPLEX, m, n, rs, cs, &b ); // Initialize the matrices to random values. bli_randm( &a ); bli_randm( &b ); bli_printm( "a:", &a, "%4.1f", "" ); // Compute the one-norm of 'a'. bli_norm1m( &a, &norm1 ); bli_normim( &a, &normi ); bli_normfm( &a, &normf ); bli_printm( "a: 1-norm:", &norm1, "%4.1f", "" ); bli_printm( "a: infinity norm:", &normi, "%4.1f", "" ); bli_printm( "a: frobenius norm:", &normf, "%4.1f", "" ); bli_printm( "b:", &b, "%4.1f", "" ); // Compute the one-norm of 'b'. bli_norm1m( &b, &norm1 ); bli_normim( &b, &normi ); bli_normfm( &b, &normf ); bli_printm( "b: 1-norm:", &norm1, "%4.1f", "" ); bli_printm( "b: infinity norm:", &normi, "%4.1f", "" ); bli_printm( "b: frobenius norm:", &normf, "%4.1f", "" ); // // Example 3: Make a real matrix explicitly symmetric (or Hermitian). // printf( "\n#\n# -- Example 3 --\n#\n\n" ); // Create a few matrices to work with. m = 4; n = 4; rs = 0; cs = 0; bli_obj_create( BLIS_DOUBLE, m, n, rs, cs, &c ); bli_obj_create( BLIS_DOUBLE, m, n, rs, cs, &d ); // Initialize all of 'c' to -1.0 to simulate junk values. bli_setm( &BLIS_MINUS_ONE, &c ); // Set the structure and uplo of 'c'. bli_obj_set_struc( BLIS_SYMMETRIC, &c ); bli_obj_set_uplo( BLIS_LOWER, &c ); // Randomize the lower triangle of 'c'. bli_randm( &c ); bli_printm( "c (initial state):", &c, "%4.1f", "" ); // mksymm on a real matrix transposes the stored triangle into the // unstored triangle, making the matrix densely symmetric. bli_mksymm( &c ); bli_printm( "c (after mksymm on lower triangle):", &c, "%4.1f", "" ); // Digression: Most people think only of complex matrices as being able // to be complex. However, in BLIS, we define Hermitian operations on // real matrices, too--they are simply equivalent to the corresponding // symmetric operation. For example, when we make a real matrix explicitly // Hermitian, the result is indistinguishable from making it symmetric. // Initialize all of 'd' to -1.0 to simulate junk values. bli_setm( &BLIS_MINUS_ONE, &d ); bli_obj_set_struc( BLIS_HERMITIAN, &d ); bli_obj_set_uplo( BLIS_LOWER, &d ); // Randomize the lower triangle of 'd'. bli_randm( &d ); bli_printm( "d (initial state):", &d, "%4.1f", "" ); // mkherm on a real matrix behaves the same as mksymm, as there are no // imaginary elements to conjugate. bli_mkherm( &d ); bli_printm( "d (after mkherm on lower triangle):", &d, "%4.1f", "" ); // // Example 4: Make a complex matrix explicitly symmetric or Hermitian. // printf( "\n#\n# -- Example 4 --\n#\n\n" ); // Create a few matrices to work with. m = 4; n = 4; rs = 0; cs = 0; bli_obj_create( BLIS_DCOMPLEX, m, n, rs, cs, &e ); bli_obj_create( BLIS_DCOMPLEX, m, n, rs, cs, &f ); // Initialize all of 'e' to -1.0 to simulate junk values. bli_setm( &BLIS_MINUS_ONE, &e ); // Set the structure and uplo of 'e'. bli_obj_set_struc( BLIS_SYMMETRIC, &e ); bli_obj_set_uplo( BLIS_UPPER, &e ); // Randomize the upper triangle of 'e'. bli_randm( &e ); bli_printm( "e (initial state):", &e, "%4.1f", "" ); // mksymm on a complex matrix transposes the stored triangle into the // unstored triangle. bli_mksymm( &e ); bli_printm( "e (after mksymm):", &e, "%4.1f", "" ); // Initialize all of 'f' to -1.0 to simulate junk values. bli_setm( &BLIS_MINUS_ONE, &f ); // Set the structure and uplo of 'f'. bli_obj_set_struc( BLIS_HERMITIAN, &f ); bli_obj_set_uplo( BLIS_UPPER, &f ); // Randomize the upper triangle of 'f'. bli_randm( &f ); bli_printm( "f (initial state):", &f, "%4.1f", "" ); // mkherm on a complex matrix transposes and conjugates the stored // triangle into the unstored triangle. bli_mkherm( &f ); bli_printm( "f (after mkherm):", &f, "%4.1f", "" ); // // Example 5: Make a real matrix explicitly triangular. // printf( "\n#\n# -- Example 5 --\n#\n\n" ); // Create a few matrices to work with. m = 5; n = 5; rs = 0; cs = 0; bli_obj_create( BLIS_DOUBLE, m, n, rs, cs, &g ); // Initialize all of 'g' to -1.0 to simulate junk values. bli_setm( &BLIS_MINUS_ONE, &g ); // Set the structure and uplo of 'g'. bli_obj_set_struc( BLIS_TRIANGULAR, &g ); bli_obj_set_uplo( BLIS_LOWER, &g ); // Randomize the lower triangle of 'g'. bli_randm( &g ); bli_printm( "g (initial state):", &g, "%4.1f", "" ); // mktrim does not explicitly copy any data, since presumably the stored // triangle already contains the data of interest. However, mktrim does // explicitly writes zeros to the unstored region. bli_mktrim( &g ); bli_printm( "g (after mktrim):", &g, "%4.1f", "" ); // Free the objects. bli_obj_free( &norm1 ); bli_obj_free( &normi ); bli_obj_free( &normf ); bli_obj_free( &x ); bli_obj_free( &y ); bli_obj_free( &a ); bli_obj_free( &b ); bli_obj_free( &c ); bli_obj_free( &d ); bli_obj_free( &e ); bli_obj_free( &f ); bli_obj_free( &g ); return 0; } // ----------------------------------------------------------------------------- blis-0.9.0/examples/oapi/11gemm_md.c000066400000000000000000000210271422157504600171420ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas 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 The University of Texas 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 COPYRIGHT HOLDER 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. */ #include #include "blis.h" int main( int argc, char** argv ) { num_t dt_r, dt_c; num_t dt_s, dt_d; num_t dt_a, dt_b; dim_t m, n, k; inc_t rs, cs; obj_t a, b, c; obj_t* alpha; obj_t* beta; // // This file demonstrates mixing datatypes in gemm. // // NOTE: Please make sure that mixed datatype support is enabled in BLIS // before proceeding to build and run the example binaries. If you're not // sure whether mixed datatype support is enabled in BLIS, please refer // to './configure --help' for the relevant options. // // // Example 1: Perform a general matrix-matrix multiply (gemm) operation // with operands of different domains (but identical precisions). // printf( "\n#\n# -- Example 1 --\n#\n\n" ); // Create some matrix operands to work with. dt_r = BLIS_DOUBLE; dt_c = BLIS_DCOMPLEX; m = 4; n = 5; k = 1; rs = 0; cs = 0; bli_obj_create( dt_c, m, n, rs, cs, &c ); bli_obj_create( dt_r, m, k, rs, cs, &a ); bli_obj_create( dt_c, k, n, rs, cs, &b ); // Set the scalars to use. alpha = &BLIS_ONE; beta = &BLIS_ONE; // Initialize the matrix operands. bli_randm( &a ); bli_randm( &b ); bli_setm( &BLIS_ZERO, &c ); bli_printm( "a (double real): randomized", &a, "%4.1f", "" ); bli_printm( "b (double complex): randomized", &b, "%4.1f", "" ); bli_printm( "c (double complex): initial value", &c, "%4.1f", "" ); // c := beta * c + alpha * a * b, where 'a' is real, and 'b' and 'c' are // complex. bli_gemm( alpha, &a, &b, beta, &c ); bli_printm( "c (double complex): after gemm", &c, "%4.1f", "" ); // Free the objects. bli_obj_free( &a ); bli_obj_free( &b ); bli_obj_free( &c ); // // Example 2: Perform a general matrix-matrix multiply (gemm) operation // with operands of different precisions (but identical domains). // printf( "\n#\n# -- Example 2 --\n#\n\n" ); // Create some matrix operands to work with. dt_s = BLIS_FLOAT; dt_d = BLIS_DOUBLE; m = 4; n = 5; k = 1; rs = 0; cs = 0; bli_obj_create( dt_d, m, n, rs, cs, &c ); bli_obj_create( dt_s, m, k, rs, cs, &a ); bli_obj_create( dt_s, k, n, rs, cs, &b ); // Notice that we've chosen C to be double-precision real and A and B to be // single-precision real. // Since we are mixing precisions, we will also need to specify the // so-called "computation precision." That is, we need to signal to // bli_gemm() whether we want the A*B product to be computed in single // precision or double precision (prior to the result being accumulated // back to C). To specify the computation precision, we need to set the // corresponding bit in the C object. Here, we specify double-precision // computation. // NOTE: If you do not explicitly specify the computation precision, it // will default to the storage precision of the C object. bli_obj_set_comp_prec( BLIS_DOUBLE_PREC, &c ); // Initialize the matrix operands. bli_randm( &a ); bli_randm( &b ); bli_setm( &BLIS_ZERO, &c ); bli_printm( "a (single real): randomized", &a, "%4.1f", "" ); bli_printm( "b (single real): randomized", &b, "%4.1f", "" ); bli_printm( "c (double real): initial value", &c, "%4.1f", "" ); // c := beta * c + alpha * a * b, where 'a' and 'b' are single-precision // real, 'c' is double-precision real, and the matrix product is performed // in double-precision arithmetic. bli_gemm( alpha, &a, &b, beta, &c ); bli_printm( "c (double real): after gemm (exec prec = double precision)", &c, "%4.1f", "" ); // Free the objects. bli_obj_free( &a ); bli_obj_free( &b ); bli_obj_free( &c ); // // Example 3: Perform a general matrix-matrix multiply (gemm) operation // with operands of different domains AND precisions. // printf( "\n#\n# -- Example 3 --\n#\n\n" ); // Create some matrix operands to work with. dt_a = BLIS_FLOAT; dt_b = BLIS_DCOMPLEX; dt_c = BLIS_SCOMPLEX; m = 4; n = 5; k = 1; rs = 0; cs = 0; bli_obj_create( dt_c, m, n, rs, cs, &c ); bli_obj_create( dt_a, m, k, rs, cs, &a ); bli_obj_create( dt_b, k, n, rs, cs, &b ); // Notice that we've chosen C to be single-precision complex, and A to be // single-precision real, and B to be double-precision complex. // Set the computation precision to single precision this time. bli_obj_set_comp_prec( BLIS_SINGLE_PREC, &c ); // Initialize the matrix operands. bli_randm( &a ); bli_randm( &b ); bli_setm( &BLIS_ZERO, &c ); bli_printm( "a (single real): randomized", &a, "%4.1f", "" ); bli_printm( "b (double complex): randomized", &b, "%4.1f", "" ); bli_printm( "c (single complex): initial value", &c, "%4.1f", "" ); // c := beta * c + alpha * a * b, where 'a' is single-precision real, 'b' // is double-precision complex, 'c' is single-precision complex, and the // matrix product is performed in single-precision arithmetic. bli_gemm( alpha, &a, &b, beta, &c ); bli_printm( "c (single complex): after gemm (exec prec = single precision)", &c, "%4.1f", "" ); // Free the objects. bli_obj_free( &a ); bli_obj_free( &b ); bli_obj_free( &c ); // // Example 4: Project objects between the real and complex domains. // printf( "\n#\n# -- Example 4 --\n#\n\n" ); // Create some matrix operands to work with. dt_r = BLIS_DOUBLE; dt_c = BLIS_DCOMPLEX; m = 4; n = 5; rs = 0; cs = 0; bli_obj_create( dt_r, m, n, rs, cs, &a ); bli_obj_create( dt_c, m, n, rs, cs, &b ); // Initialize a real matrix A. bli_randm( &a ); bli_printm( "a (double real): randomized", &a, "%4.1f", "" ); // Project real matrix A to the complex domain (in B). bli_projm( &a, &b ); bli_printm( "b (double complex): projected from 'a'", &b, "%4.1f", "" ); // Notice how the imaginary components in B are zero since any real // matrix implicitly has imaginary values that are equal to zero. // Now let's project in the other direction. // Initialize the complex matrix B. bli_randm( &b ); bli_printm( "b (double complex): randomized", &b, "%4.1f", "" ); // Project complex matrix B to the real domain (in A). bli_projm( &b, &a ); bli_printm( "a (double real): projected from 'b'", &a, "%4.1f", "" ); // Notice how the imaginary components are lost in the projection from // the complex domain to the real domain. // Free the objects. bli_obj_free( &a ); bli_obj_free( &b ); // // Example 5: Typecast objects between the single and double precisions. // printf( "\n#\n# -- Example 5 --\n#\n\n" ); // Create some matrix operands to work with. dt_s = BLIS_FLOAT; dt_d = BLIS_DOUBLE; m = 4; n = 3; rs = 0; cs = 0; bli_obj_create( dt_d, m, n, rs, cs, &a ); bli_obj_create( dt_s, m, n, rs, cs, &b ); // Initialize a double-precision real matrix A. bli_randm( &a ); bli_printm( "a (double real): randomized", &a, "%23.16e", "" ); // Typecast A to single precision. bli_castm( &a, &b ); bli_printm( "b (single real): typecast from 'a'", &b, "%23.16e", "" ); // Notice how the values in B are only accurate to the 6th or 7th decimal // place relative to the true values in A. // Free the objects. bli_obj_free( &a ); bli_obj_free( &b ); return 0; } blis-0.9.0/examples/oapi/Makefile000066400000000000000000000122271422157504600166710ustar00rootroot00000000000000# # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2014, The University of Texas at Austin # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # # # Makefile # # Field G. Van Zee # # Makefile for BLIS object API example code. # # # --- Makefile PHONY target definitions ---------------------------------------- # .PHONY: all bin clean run # # --- Determine makefile fragment location ------------------------------------- # # Comments: # - DIST_PATH is assumed to not exist if BLIS_INSTALL_PATH is given. # - We must use recursively expanded assignment for LIB_PATH and INC_PATH in # the second case because CONFIG_NAME is not yet set. ifneq ($(strip $(BLIS_INSTALL_PATH)),) LIB_PATH := $(BLIS_INSTALL_PATH)/lib INC_PATH := $(BLIS_INSTALL_PATH)/include/blis SHARE_PATH := $(BLIS_INSTALL_PATH)/share/blis else DIST_PATH := ../.. LIB_PATH = ../../lib/$(CONFIG_NAME) INC_PATH = ../../include/$(CONFIG_NAME) SHARE_PATH := ../.. endif #ifneq ($(strip $(BLIS_LIB_PATH)),) #LIB_PATH := $(BLIS_LIB_PATH) #endif # #ifneq ($(strip $(BLIS_INC_PATH)),) #INC_PATH := $(BLIS_INC_PATH) #endif # #ifneq ($(strip $(BLIS_SHARE_PATH)),) #SHARE_PATH := $(BLIS_SHARE_PATH) #endif # # --- Include common makefile definitions -------------------------------------- # # Include the common makefile fragment. -include $(SHARE_PATH)/common.mk # # --- General build definitions ------------------------------------------------ # TEST_SRC_PATH := . TEST_OBJ_PATH := . # Gather all local object files. TEST_OBJS := $(sort $(patsubst $(TEST_SRC_PATH)/%.c, \ $(TEST_OBJ_PATH)/%.o, \ $(wildcard $(TEST_SRC_PATH)/*.c))) # Override the value of CINCFLAGS so that the value of CFLAGS returned by # get-user-cflags-for() is not cluttered up with include paths needed only # while building BLIS. CINCFLAGS := -I$(INC_PATH) # Use the "framework" CFLAGS for the configuration family. CFLAGS := $(call get-user-cflags-for,$(CONFIG_NAME)) # Add local header paths to CFLAGS CFLAGS += -I$(TEST_SRC_PATH) # Locate the libblis library to which we will link. #LIBBLIS_LINK := $(LIB_PATH)/$(LIBBLIS_L) # Binary executable name. TEST_BINS := 00obj_basic.x \ 01obj_attach.x \ 02obj_ij.x \ 03obj_view.x \ 04level0.x \ 05level1v.x \ 06level1m.x \ 07level1m_diag.x \ 08level2.x \ 09level3.x \ 10util.x \ 11gemm_md.x # # --- Targets/rules ------------------------------------------------------------ # # --- Primary targets --- all: bin bin: $(TEST_BINS) # --- Environment check rules --- check-env: check-env-make-defs check-env-fragments check-env-config-mk check-env-config-mk: ifeq ($(CONFIG_MK_PRESENT),no) $(error Cannot proceed: config.mk not detected! Run configure first) endif check-env-make-defs: check-env-fragments ifeq ($(MAKE_DEFS_MK_PRESENT),no) $(error Cannot proceed: make_defs.mk not detected! Invalid configuration) endif # --Object file rules -- $(TEST_OBJ_PATH)/%.o: $(TEST_SRC_PATH)/%.c $(LIBBLIS_LINK) ifeq ($(ENABLE_VERBOSE),yes) $(CC) $(CFLAGS) -c $< -o $@ else @echo "Compiling $@" @$(CC) $(CFLAGS) -c $< -o $@ endif # -- Executable file rules -- %.x: %.o $(LIBBLIS_LINK) ifeq ($(ENABLE_VERBOSE),yes) $(LINKER) $< $(LIBBLIS_LINK) $(LDFLAGS) -o $@ else @echo "Linking $@ against '$(LIBBLIS_LINK) $(LDFLAGS)'" @$(LINKER) $< $(LIBBLIS_LINK) $(LDFLAGS) -o $@ endif # -- Test run rules -- #run: $(TEST_BIN) # ./$(TEST_BIN) # -- Clean rules -- clean: - $(RM_F) $(TEST_OBJS) $(TEST_BINS) blis-0.9.0/examples/oapi/README000066400000000000000000000031241422157504600161050ustar00rootroot00000000000000 BLIS object API examples ------------------------ This directory contains several files, each containing various pieces of example code that demonstrate core functionality of the object API in BLIS. These example files should be thought of collectively like a tutorial, and therefore it is recommended to start from the beginning (the file that starts in '00'). You can build all of the examples by simply running 'make' from this directory. (You can also run 'make clean'.) The makefile assumes that you've already configured and built (but not necessarily installed) BLIS two directories up, in "../..". If you have already installed BLIS to some permanent directory, you may refer to that installation by setting the environment variable BLIS_INSTALL_PATH prior to running make: export BLIS_INSTALL_PATH=/usr/local; make or by setting the same variable as part of the make command: make BLIS_INSTALL_PATH=/usr/local Once the executable files have been built, we recommend reading the code in one terminal window alongside the executable output in another terminal. This will help you see the effects of each section of code. This tutorial is not exhaustive or complete; several object API functions were omitted (mostly for brevity's sake) and thus more examples could be written. If you've found object functionality in BLIS and are unsure how to use it, or if you are unsure of what additional functionality is present in BLIS, please feel free to join and then start a discussion on the blis-devel mailing list [1]. Thanks for your interest in BLIS! [1] https://groups.google.com/d/forum/blis-devel blis-0.9.0/examples/tapi/000077500000000000000000000000001422157504600152325ustar00rootroot00000000000000blis-0.9.0/examples/tapi/00level1v.c000066400000000000000000000134761422157504600171270ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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 The University of Texas 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 COPYRIGHT HOLDER 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. */ #include #include "blis.h" int main( int argc, char** argv ) { double* x; double* y; double* z; double* w; double* a; double alpha, beta, gamma; dim_t m, n; inc_t rs, cs; // Initialize some basic constants. double zero = 0.0; double one = 1.0; double minus_one = -1.0; // // This file demonstrates working with vectors and the level-1v // operations. // // // Example 1: Create vectors and then broadcast (copy) scalar // values to all elements. // printf( "\n#\n# -- Example 1 --\n#\n\n" ); // Create a few vectors to work with. We make them all of the same length // so that we can perform operations between them. // NOTE: We've chosen to use row vectors here (1x4) instead of column // vectors (4x1) to allow for easier reading of standard output (less // scrolling). m = 1; n = 4; rs = n; cs = 1; x = malloc( m * n * sizeof( double ) ); y = malloc( m * n * sizeof( double ) ); z = malloc( m * n * sizeof( double ) ); w = malloc( m * n * sizeof( double ) ); a = malloc( m * n * sizeof( double ) ); // Let's initialize some scalars. alpha = 2.0; beta = 0.2; gamma = 3.0; printf( "alpha:\n%4.1f\n\n", alpha ); printf( "beta:\n%4.1f\n\n", beta ); printf( "gamma:\n%4.1f\n\n", gamma ); printf( "\n" ); bli_dsetv( BLIS_NO_CONJUGATE, n, &one, x, 1 ); bli_dsetv( BLIS_NO_CONJUGATE, n, &alpha, y, 1 ); bli_dsetv( BLIS_NO_CONJUGATE, n, &zero, z, 1 ); // Note that we can use printv or printm to print vectors since vectors // are also matrices. We choose to use printm because it honors the // orientation of the vector (row or column) when printing, whereas // printv always prints vectors as column vectors regardless of their // they are 1 x n or n x 1. bli_dprintm( "x := 1.0", m, n, x, rs, cs, "%4.1f", "" ); bli_dprintm( "y := alpha", m, n, y, rs, cs, "%4.1f", "" ); bli_dprintm( "z := 0.0", m, n, z, rs, cs, "%4.1f", "" ); // // Example 2: Randomize a vector. // printf( "\n#\n# -- Example 2 --\n#\n\n" ); // Set a vector to random values. bli_drandv( n, w, 1 ); bli_dprintm( "x := randv()", m, n, w, rs, cs, "%4.1f", "" ); // // Example 3: Perform various element-wise operations on vectors. // printf( "\n#\n# -- Example 3 --\n#\n\n" ); // Copy a vector. bli_dcopyv( BLIS_NO_CONJUGATE, n, w, 1, a, 1 ); bli_dprintm( "a := w", m, n, a, rs, cs, "%4.1f", "" ); // Add and subtract vectors. bli_daddv( BLIS_NO_CONJUGATE, n, y, 1, a, 1 ); bli_dprintm( "a := a + y", m, n, a, rs, cs, "%4.1f", "" ); bli_dsubv( BLIS_NO_CONJUGATE, n, w, 1, a, 1 ); bli_dprintm( "a := a + w", m, n, a, rs, cs, "%4.1f", "" ); // Scale a vector (destructive). bli_dscalv( BLIS_NO_CONJUGATE, n, &beta, a, 1 ); bli_dprintm( "a := beta * a", m, n, a, rs, cs, "%4.1f", "" ); // Scale a vector (non-destructive). bli_dscal2v( BLIS_NO_CONJUGATE, n, &gamma, a, 1, z, 1 ); bli_dprintm( "z := gamma * a", m, n, z, rs, cs, "%4.1f", "" ); // Scale and accumulate between vectors. bli_daxpyv( BLIS_NO_CONJUGATE, n, &alpha, w, 1, x, 1 ); bli_dprintm( "x := x + alpha * w", m, n, x, rs, cs, "%4.1f", "" ); bli_dxpbyv( BLIS_NO_CONJUGATE, n, w, 1, &minus_one, x, 1 ); bli_dprintm( "x := -1.0 * x + w", m, n, x, rs, cs, "%4.1f", "" ); // Invert a vector element-wise. bli_dinvertv( n, y, 1 ); bli_dprintm( "y := 1 / y", m, n, y, rs, cs, "%4.1f", "" ); // Swap two vectors. bli_dswapv( n, x, 1, y, 1 ); bli_dprintm( "x (after swapping with y)", m, n, x, rs, cs, "%4.1f", "" ); bli_dprintm( "y (after swapping with x)", m, n, y, rs, cs, "%4.1f", "" ); // // Example 4: Perform contraction-like operations on vectors. // printf( "\n#\n# -- Example 4 --\n#\n\n" ); // Perform a dot product. bli_ddotv( BLIS_NO_CONJUGATE, BLIS_NO_CONJUGATE, n, a, 1, z, 1, &gamma ); printf( "gamma := a * z (dot product):\n%5.2f\n\n", gamma ); // Perform an extended dot product. bli_ddotxv( BLIS_NO_CONJUGATE, BLIS_NO_CONJUGATE, n, &alpha, a, 1, z, 1, &one, &gamma ); printf( "gamma := 1.0 * gamma + alpha * a * z (accumulate scaled dot product):\n%5.2f\n\n", gamma ); // Free the memory obtained via malloc(). free( x ); free( y ); free( z ); free( w ); free( a ); return 0; } // ----------------------------------------------------------------------------- blis-0.9.0/examples/tapi/01level1m.c000066400000000000000000000156131422157504600171120ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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 The University of Texas 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 COPYRIGHT HOLDER 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. */ #include #include "blis.h" int main( int argc, char** argv ) { double* a; double* b; double* c; double* d; double* e; double* f; dcomplex* g; dcomplex* h; double alpha, beta, gamma; dim_t m, n; inc_t rs, cs; // Initialize some basic constants. double zero = 0.0; double one = 1.0; double minus_one = -1.0; dcomplex minus_one_z = {-1.0, 0.0}; // // This file demonstrates working with matrices and the level-1m // operations. // // // Example 1: Create matrices and then broadcast (copy) scalar // values to all elements. // printf( "\n#\n# -- Example 1 --\n#\n\n" ); // Create a few matrices to work with. We make them all of the same // dimensions so that we can perform operations between them. m = 2; n = 3; rs = 1; cs = m; a = malloc( m * n * sizeof( double ) ); b = malloc( m * n * sizeof( double ) ); c = malloc( m * n * sizeof( double ) ); d = malloc( m * n * sizeof( double ) ); e = malloc( m * n * sizeof( double ) ); // Let's initialize some scalars. alpha = 2.0; beta = 0.2; gamma = 3.0; printf( "alpha:\n%4.1f\n\n", alpha ); printf( "beta:\n%4.1f\n\n", beta ); printf( "gamma:\n%4.1f\n\n", gamma ); printf( "\n" ); // Matrices, like vectors, can set by "broadcasting" a constant to every // element. Note that the second argument (0) is the diagonal offset. // The diagonal offset is only used when the uplo value is something other // than BLIS_DENSE (e.g. BLIS_LOWER or BLIS_UPPER). bli_dsetm( BLIS_NO_CONJUGATE, 0, BLIS_NONUNIT_DIAG, BLIS_DENSE, m, n, &one, a, rs, cs ); bli_dsetm( BLIS_NO_CONJUGATE, 0, BLIS_NONUNIT_DIAG, BLIS_DENSE, m, n, &alpha, b, rs, cs ); bli_dsetm( BLIS_NO_CONJUGATE, 0, BLIS_NONUNIT_DIAG, BLIS_DENSE, m, n, &zero, c, rs, cs ); bli_dprintm( "a := 1.0", m, n, a, rs, cs, "%4.1f", "" ); bli_dprintm( "b := alpha", m, n, b, rs, cs, "%4.1f", "" ); bli_dprintm( "c := 0.0", m, n, c, rs, cs, "%4.1f", "" ); // // Example 2: Randomize a matrix object. // printf( "\n#\n# -- Example 2 --\n#\n\n" ); bli_drandm( 0, BLIS_DENSE, m, n, e, rs, cs ); bli_dprintm( "e (randomized):", m, n, e, rs, cs, "%4.1f", "" ); // // Example 3: Perform element-wise operations on matrices. // printf( "\n#\n# -- Example 3 --\n#\n\n" ); // Copy a matrix. bli_dcopym( 0, BLIS_NONUNIT_DIAG, BLIS_DENSE, BLIS_NO_TRANSPOSE, m, n, e, rs, cs, d, rs, cs ); bli_dprintm( "d := e", m, n, d, rs, cs, "%4.1f", "" ); // Add and subtract vectors. bli_daddm( 0, BLIS_NONUNIT_DIAG, BLIS_DENSE, BLIS_NO_TRANSPOSE, m, n, a, rs, cs, d, rs, cs ); bli_dprintm( "d := d + a", m, n, d, rs, cs, "%4.1f", "" ); bli_dsubm( 0, BLIS_NONUNIT_DIAG, BLIS_DENSE, BLIS_NO_TRANSPOSE, m, n, a, rs, cs, e, rs, cs ); bli_dprintm( "e := e - a", m, n, e, rs, cs, "%4.1f", "" ); // Scale a matrix (destructive). bli_dscalm( BLIS_NO_CONJUGATE, 0, BLIS_NONUNIT_DIAG, BLIS_DENSE, m, n, &alpha, e, rs, cs ); bli_dprintm( "e := alpha * e", m, n, e, rs, cs, "%4.1f", "" ); // Scale a matrix (non-destructive). bli_dscal2m( 0, BLIS_NONUNIT_DIAG, BLIS_DENSE, BLIS_NO_TRANSPOSE, m, n, &beta, e, rs, cs, c, rs, cs ); bli_dprintm( "c := beta * e", m, n, c, rs, cs, "%4.1f", "" ); // Scale and accumulate between matrices. bli_daxpym( 0, BLIS_NONUNIT_DIAG, BLIS_DENSE, BLIS_NO_TRANSPOSE, m, n, &alpha, a, rs, cs, c, rs, cs ); bli_dprintm( "c := alpha * a", m, n, c, rs, cs, "%4.1f", "" ); // // Example 4: Copy and transpose a matrix. // printf( "\n#\n# -- Example 4 --\n#\n\n" ); // Create an n-by-m matrix into which we can copy-transpose an m-by-n // matrix. f = malloc( n * m * sizeof( double ) ); dim_t rsf = 1, csf = n; // Initialize all of 'f' to -1.0 to simulate junk values. bli_dsetm( BLIS_NO_CONJUGATE, 0, BLIS_NONUNIT_DIAG, BLIS_DENSE, n, m, &minus_one, f, rsf, csf ); bli_dprintm( "e:", m, n, e, rs, cs, "%4.1f", "" ); bli_dprintm( "f (initial value):", n, m, f, rsf, csf, "%4.1f", "" ); // Copy 'e' to 'f', transposing 'e' in the process. Notice that we haven't // modified any properties of 'd'. It's the source operand that matters // when marking an operand for transposition, not the destination. bli_dcopym( 0, BLIS_NONUNIT_DIAG, BLIS_DENSE, BLIS_TRANSPOSE, n, m, e, rs, cs, f, rsf, csf ); bli_dprintm( "f (copied value):", n, m, f, rsf, csf, "%4.1f", "" ); // // Example 5: Copy and Hermitian-transpose a matrix. // printf( "\n#\n# -- Example 5 --\n#\n\n" ); g = malloc( m * n * sizeof(dcomplex) ); h = malloc( n * m * sizeof(dcomplex) ); bli_zrandm( 0, BLIS_DENSE, m, n, g, rs, cs ); bli_zsetm( BLIS_NO_CONJUGATE, 0, BLIS_NONUNIT_DIAG, BLIS_DENSE, n, m, &minus_one_z, h, rsf, csf ); bli_zprintm( "g:", m, n, g, rs, cs, "%4.1f", "" ); bli_zprintm( "h (initial value):", n, m, h, rsf, csf, "%4.1f", "" ); bli_zcopym( 0, BLIS_NONUNIT_DIAG, BLIS_DENSE, BLIS_CONJ_TRANSPOSE, n, m, g, rs, cs, h, rsf, csf ); bli_zprintm( "h (copied value):", n, m, h, rsf, csf, "%4.1f", "" ); // Free the memory obtained via malloc(). free( a ); free( b ); free( c ); free( d ); free( e ); free( f ); free( g ); free( h ); return 0; } // ----------------------------------------------------------------------------- blis-0.9.0/examples/tapi/02level1m_diag.c000066400000000000000000000173311422157504600200760ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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 The University of Texas 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 COPYRIGHT HOLDER 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. */ #include #include "blis.h" int main( int argc, char** argv ) { double* a; double* b; double* c; double* d; double* e; double* h; dim_t m, n; inc_t rs, cs; // Initialize some basic constants. double zero = 0.0; double minus_one = -1.0; // // This file demonstrates level-1m operations on structured matrices. // // // Example 1: Initialize the upper triangle of a matrix to random values. // printf( "\n#\n# -- Example 1 --\n#\n\n" ); // Create a matrix to work with. m = 5; n = 5; rs = 1; cs = m; a = malloc( m * n * sizeof( double ) ); // Set the upper triangle to random values. bli_drandm( 0, BLIS_UPPER, m, n, a, rs, cs ); bli_dprintm( "a: randomize upper part (lower part may contain garbage)", m, n, a, rs, cs, "%4.1f", "" ); // // Example 2: Initialize the upper triangle of a matrix to random values // but also explicitly set the strictly lower triangle to zero. // printf( "\n#\n# -- Example 2 --\n#\n\n" ); // Create a matrix to work with. m = 5; n = 5; rs = 1; cs = m; b = malloc( m * n * sizeof( double ) ); // Set the upper triangle to random values. bli_drandm( 0, BLIS_UPPER, m, n, b, rs, cs ); // Set the strictly lower triangle of 'b' to zero (by setting the lower // triangle of 'bl' to zero). bli_dsetm( BLIS_NO_CONJUGATE, -1, BLIS_NONUNIT_DIAG, BLIS_LOWER, m, n, &zero, b, rs, cs ); bli_dprintm( "b: randomize upper part; set strictly lower part to 0.0)", m, n, b, rs, cs, "%4.1f", "" ); // You may not see the effect of setting the strictly lower part to zero, // since those values may already be zero (instead of random junk). So // let's set it to something you'll notice, like -1.0. bli_dsetm( BLIS_NO_CONJUGATE, -1, BLIS_NONUNIT_DIAG, BLIS_LOWER, m, n, &minus_one, b, rs, cs ); bli_dprintm( "b: randomize upper part; set strictly lower part to -1.0)", m, n, b, rs, cs, "%4.1f", "" ); // // Example 3: Copy the lower triangle of an existing matrix to a newly // created (but otherwise uninitialized) matrix. // printf( "\n#\n# -- Example 3 --\n#\n\n" ); // Create a matrix to work with. m = 5; n = 5; rs = 1; cs = m; c = malloc( m * n * sizeof( double ) ); bli_dcopym( 0, BLIS_NONUNIT_DIAG, BLIS_LOWER, BLIS_NO_TRANSPOSE, m, n, b, rs, cs, c, rs, cs ); bli_dprintm( "c: copy lower part of b (upper part may contain garbage)", m, n, c, rs, cs, "%4.1f", "" ); bli_dcopym( 0, BLIS_NONUNIT_DIAG, BLIS_LOWER, BLIS_NO_TRANSPOSE, m, n, b, rs, cs, a, rs, cs ); bli_dprintm( "a: copy lower triangle of b to upper triangular a", m, n, a, rs, cs, "%4.1f", "" ); // // Example 4: Copy the lower triangle of an existing object into the // upper triangle of an existing object. // printf( "\n#\n# -- Example 4 --\n#\n\n" ); // Create a matrix to work with. m = 5; n = 5; rs = 1; cs = m; d = malloc( m * n * sizeof( double ) ); // Let's start by setting entire destination matrix to zero. bli_dsetm( BLIS_NO_CONJUGATE, 0, BLIS_NONUNIT_DIAG, BLIS_DENSE, m, n, &zero, d, rs, cs ); bli_dprintm( "d: initial value (all zeros)", m, n, d, rs, cs, "%4.1f", "" ); // Let's change a few values of b manually so we can later see the full // effect of the transposition. bli_dsetijm( 2.0, 0.0, 2, 0, b, rs, cs ); bli_dsetijm( 3.0, 0.0, 3, 0, b, rs, cs ); bli_dsetijm( 4.0, 0.0, 4, 0, b, rs, cs ); bli_dsetijm( 3.1, 0.0, 2, 1, b, rs, cs ); bli_dsetijm( 3.2, 0.0, 3, 2, b, rs, cs ); bli_dprintm( "b:", m, n, b, rs, cs, "%4.1f", "" ); bli_dcopym( 0, BLIS_NONUNIT_DIAG, BLIS_LOWER, BLIS_TRANSPOSE, m, n, b, rs, cs, d, rs, cs ); bli_dprintm( "d: transpose of lower triangle of b copied to d", m, n, d, rs, cs, "%4.1f", "" ); // // Example 5: Create a rectangular matrix (m > n) with a lower trapezoid // containing random values, then set the strictly upper // triangle to zeros. // printf( "\n#\n# -- Example 5 --\n#\n\n" ); // Create a matrix to work with. m = 6; n = 4; rs = 1; cs = m; e = malloc( m * n * sizeof( double ) ); // Initialize the entire matrix to -1.0 to simulate junk values. bli_dsetm( BLIS_NO_CONJUGATE, 0, BLIS_NONUNIT_DIAG, BLIS_DENSE, m, n, &minus_one, e, rs, cs ); bli_dprintm( "e: initial value (all -1.0)", m, n, e, rs, cs, "%4.1f", "" ); // Randomize the lower trapezoid. bli_drandm( 0, BLIS_LOWER, m, n, e, rs, cs ); bli_dprintm( "e: after lower trapezoid randomized", m, n, e, rs, cs, "%4.1f", "" ); // Set the upper triangle to zero. bli_dsetm( BLIS_NO_CONJUGATE, 1, BLIS_NONUNIT_DIAG, BLIS_UPPER, m, n, &zero, e, rs, cs ); bli_dprintm( "e: after upper triangle set to zero", m, n, e, rs, cs, "%4.1f", "" ); // // Example 6: Create an upper Hessenberg matrix of random values and then // set the "unstored" values to zero. // printf( "\n#\n# -- Example 6 --\n#\n\n" ); // Create a matrix to work with. m = 5; n = 5; rs = 1; cs = m; h = malloc( m * n * sizeof( double ) ); // Initialize the entire matrix to -1.0 to simulate junk values. bli_dsetm( BLIS_NO_CONJUGATE, 0, BLIS_NONUNIT_DIAG, BLIS_DENSE, m, n, &minus_one, h, rs, cs ); bli_dprintm( "h: initial value (all -1.0)", m, n, h, rs, cs, "%4.1f", "" ); // Randomize the elements on and above the first subdiagonal. bli_drandm( -1, BLIS_UPPER, m, n, h, rs, cs ); bli_dprintm( "h: after randomizing above first subdiagonal", m, n, h, rs, cs, "%4.1f", "" ); // Set the region strictly below the first subdiagonal (on or below // the second subdiagonal) to zero. bli_dsetm( BLIS_NO_CONJUGATE, -2, BLIS_NONUNIT_DIAG, BLIS_LOWER, m, n, &zero, h, rs, cs ); bli_dprintm( "h: after setting elements below first subdiagonal to zero", m, n, h, rs, cs, "%4.1f", "" ); // Free the memory obtained via malloc(). free( a ); free( b ); free( c ); free( d ); free( e ); free( h ); return 0; } // ----------------------------------------------------------------------------- blis-0.9.0/examples/tapi/03level2.c000066400000000000000000000230641422157504600167370ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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 The University of Texas 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 COPYRIGHT HOLDER 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. */ #include #include "blis.h" int main( int argc, char** argv ) { double* a; double* x; double* y; double* b; double alpha, beta; dim_t m, n; inc_t rs, cs; // Initialize some basic constants. double zero = 0.0; double one = 1.0; double two = 2.0; double minus_one = -1.0; // // This file demonstrates level-2 operations. // // // Example 1: Perform a general rank-1 update (ger) operation. // printf( "\n#\n# -- Example 1 --\n#\n\n" ); // Create some matrix and vector operands to work with. m = 4; n = 5; rs = 1; cs = m; a = malloc( m * n * sizeof( double ) ); x = malloc( m * 1 * sizeof( double ) ); y = malloc( 1 * n * sizeof( double ) ); // Let's initialize some scalars. alpha = 1.0; // Initialize vectors 'x' and 'y'. bli_drandv( m, x, 1 ); bli_dsetv( BLIS_NO_CONJUGATE, n, &minus_one, y, 1 ); // Initialize 'a' to 1.0. bli_dsetm( BLIS_NO_CONJUGATE, 0, BLIS_NONUNIT_DIAG, BLIS_DENSE, m, n, &one, a, rs, cs ); bli_dprintm( "x: set to random values", m, 1, x, 1, m, "%4.1f", "" ); bli_dprintm( "y: set to -1.0", 1, n, y, n, 1, "%4.1f", "" ); bli_dprintm( "a: intial value", m, n, a, rs, cs, "%4.1f", "" ); // a := a + alpha * x * y, where 'a' is general. bli_dger( BLIS_NO_CONJUGATE, BLIS_NO_CONJUGATE, m, n, &alpha, x, 1, y, 1, a, rs, cs ); bli_dprintm( "a: after ger", m, n, a, rs, cs, "%4.1f", "" ); // Free the memory obtained via malloc(). free( a ); free( x ); free( y ); // // Example 2: Perform a general matrix-vector multiply (gemv) operation. // printf( "\n#\n# -- Example 2 --\n#\n\n" ); // Create some matrix and vector operands to work with. m = 4; n = 5; rs = 1; cs = m; a = malloc( m * n * sizeof( double ) ); x = malloc( 1 * n * sizeof( double ) ); y = malloc( 1 * m * sizeof( double ) ); // Set the scalars to use. alpha = 1.0; beta = 1.0; // Initialize vectors 'x' and 'y'. bli_dsetv( BLIS_NO_CONJUGATE, n, &one, x, 1 ); bli_dsetv( BLIS_NO_CONJUGATE, m, &zero, y, 1 ); // Randomize 'a'. bli_drandm( 0, BLIS_DENSE, m, n, a, rs, cs ); bli_dprintm( "a: randomized", m, n, a, rs, cs, "%4.1f", "" ); bli_dprintm( "x: set to 1.0", 1, n, x, n, 1, "%4.1f", "" ); bli_dprintm( "y: intial value", 1, m, y, m, 1, "%4.1f", "" ); // y := beta * y + alpha * a * x, where 'a' is general. bli_dgemv( BLIS_NO_TRANSPOSE, BLIS_NO_CONJUGATE, m, n, &alpha, a, rs, cs, x, 1, &beta, y, 1 ); bli_dprintm( "y: after gemv", 1, m, y, m, 1, "%4.1f", "" ); // Free the memory obtained via malloc(). free( a ); free( x ); free( y ); // // Example 3: Perform a symmetric rank-1 update (syr) operation. // printf( "\n#\n# -- Example 3 --\n#\n\n" ); // Create some matrix and vector operands to work with. m = 5; rs = 1; cs = 5; a = malloc( m * m * sizeof( double ) ); x = malloc( 1 * m * sizeof( double ) ); // Set alpha. alpha = 1.0; // Initialize vector 'x'. bli_drandv( m, x, 1 ); // Zero out all of matrix 'a'. This is optional, but will avoid possibly // displaying junk values in the unstored triangle. bli_dsetm( BLIS_NO_CONJUGATE, 0, BLIS_NONUNIT_DIAG, BLIS_DENSE, m, m, &zero, a, rs, cs ); // Randomize the lower triangle of 'a'. bli_drandm( 0, BLIS_LOWER, m, m, a, rs, cs ); bli_dprintm( "x: set to random values", 1, m, x, m, 1, "%4.1f", "" ); bli_dprintm( "a: initial value (zeros in upper triangle)", m, m, a, 1, m, "%4.1f", "" ); // a := a + alpha * x * x^T, where 'a' is symmetric and lower-stored. bli_dsyr( BLIS_LOWER, BLIS_NO_CONJUGATE, m, &alpha, x, 1, a, rs, cs ); bli_dprintm( "a: after syr", m, m, a, 1, m, "%4.1f", "" ); // Free the memory obtained via malloc(). free( a ); free( x ); // // Example 4: Perform a symmetric matrix-vector multiply (symv) operation. // printf( "\n#\n# -- Example 4 --\n#\n\n" ); // Create some matrix and vector operands to work with. m = 5;; rs = 1; cs = m; a = malloc( m * m * sizeof( double ) ); x = malloc( 1 * m * sizeof( double ) ); y = malloc( 1 * m * sizeof( double ) ); // Set the scalars to use. alpha = 1.0; beta = 1.0; // Initialize vectors 'x' and 'y'. bli_dsetv( BLIS_NO_CONJUGATE, m, &one, x, 1 ); bli_dsetv( BLIS_NO_CONJUGATE, m, &zero, y, 1 ); // Zero out all of matrix 'a'. This is optional, but will avoid possibly // displaying junk values in the unstored triangle. bli_dsetm( BLIS_NO_CONJUGATE, 0, BLIS_NONUNIT_DIAG, BLIS_DENSE, m, m, &zero, a, rs, cs ); // Randomize 'a'. bli_drandm( 0, BLIS_UPPER, m, m, a, rs, cs ); bli_dprintm( "a: randomized (zeros in lower triangle)", m, m, a, rs, cs, "%4.1f", "" ); bli_dprintm( "x: set to 1.0", 1, m, x, m, 1, "%4.1f", "" ); bli_dprintm( "y: intial value", 1, m, y, m, 1, "%4.1f", "" ); // y := beta * y + alpha * a * x, where 'a' is symmetric and upper-stored. bli_dsymv( BLIS_UPPER, BLIS_NO_TRANSPOSE, BLIS_NO_CONJUGATE, m, &alpha, a, rs, cs, x, 1, &beta, y, 1 ); bli_dprintm( "y: after symv", 1, m, y, m, 1, "%4.1f", "" ); // Free the memory obtained via malloc(). free( a ); free( x ); free( y ); // // Example 5: Perform a triangular matrix-vector multiply (trmv) operation. // printf( "\n#\n# -- Example 5 --\n#\n\n" ); // Create some matrix and vector operands to work with. m = 5;; rs = 1; cs = m; a = malloc( m * m * sizeof( double ) ); x = malloc( 1 * m * sizeof( double ) ); // Set the scalars to use. alpha = 1.0; // Initialize vector 'x'. bli_dsetv( BLIS_NO_CONJUGATE, m, &one, x, 1 ); // Zero out all of matrix 'a'. This is optional, but will avoid possibly // displaying junk values in the unstored triangle. bli_dsetm( BLIS_NO_CONJUGATE, 0, BLIS_NONUNIT_DIAG, BLIS_DENSE, m, m, &zero, a, rs, cs ); // Randomize 'a'. bli_drandm( 0, BLIS_LOWER, m, m, a, rs, cs ); bli_dprintm( "a: randomized (zeros in upper triangle)", m, m, a, rs, cs, "%4.1f", "" ); bli_dprintm( "x: intial value", 1, m, x, m, 1, "%4.1f", "" ); // x := alpha * a * x, where 'a' is triangular and lower-stored. bli_dtrmv( BLIS_LOWER, BLIS_NO_TRANSPOSE, BLIS_NONUNIT_DIAG, m, &alpha, a, rs, cs, x, 1 ); bli_dprintm( "x: after trmv", 1, m, x, m, 1, "%4.1f", "" ); // Free the memory obtained via malloc(). free( a ); free( x ); // // Example 6: Perform a triangular solve (trsv) operation. // printf( "\n#\n# -- Example 6 --\n#\n\n" ); // Create some matrix and vector operands to work with. m = 5;; rs = 1; cs = m; a = malloc( m * m * sizeof( double ) ); b = malloc( 1 * m * sizeof( double ) ); y = malloc( 1 * m * sizeof( double ) ); // Set the scalars to use. alpha = 1.0; // Initialize vector 'x'. bli_dsetv( BLIS_NO_CONJUGATE, m, &one, b, 1 ); // Zero out all of matrix 'a'. This is optional, but will avoid possibly // displaying junk values in the unstored triangle. bli_dsetm( BLIS_NO_CONJUGATE, 0, BLIS_NONUNIT_DIAG, BLIS_DENSE, m, m, &zero, a, rs, cs ); // Randomize 'a'. bli_drandm( 0, BLIS_LOWER, m, m, a, rs, cs ); // Load the diagonal. By setting the diagonal to something of greater // absolute value than the off-diagonal elements, we increase the odds // that the matrix is not singular (singular matrices have no inverse). bli_dshiftd( 0, m, m, &two, a, rs, cs ); bli_dprintm( "a: randomized (zeros in upper triangle)", m, m, a, rs, cs, "%4.1f", "" ); bli_dprintm( "b: intial value", 1, m, b, m, 1, "%4.1f", "" ); // x := alpha * a * x, where 'a' is triangular and lower-stored. bli_dtrsv( BLIS_LOWER, BLIS_NO_TRANSPOSE, BLIS_NONUNIT_DIAG, m, &alpha, a, rs, cs, x, 1 ); bli_dprintm( "b: after trsv", 1, m, b, m, 1, "%4.1f", "" ); // We can confirm the solution by comparing the product of a and x to the // original value of b. bli_dcopyv( BLIS_NO_TRANSPOSE, m, b, 1, y, 1 ); bli_dtrmv( BLIS_LOWER, BLIS_NO_TRANSPOSE, BLIS_NONUNIT_DIAG, m, &alpha, a, rs, cs, y, 1 ); bli_dprintm( "y: should equal initial value of b", 1, m, y, m, 1, "%4.1f", "" ); // Free the memory obtained via malloc(). free( a ); free( b ); free( y ); return 0; } blis-0.9.0/examples/tapi/04level3.c000066400000000000000000000255101422157504600167370ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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 The University of Texas 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 COPYRIGHT HOLDER 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. */ #include #include "blis.h" int main( int argc, char** argv ) { dim_t m, n, k; inc_t rsa, csa; inc_t rsb, csb; inc_t rsc, csc; double* a; double* b; double* c; double alpha, beta; // Initialize some basic constants. double zero = 0.0; double one = 1.0; double two = 2.0; // // This file demonstrates level-3 operations. // // // Example 1: Perform a general matrix-matrix multiply (gemm) operation. // printf( "\n#\n# -- Example 1 --\n#\n\n" ); // Create some matrix and vector operands to work with. m = 4; n = 5; k = 3; rsc = 1; csc = m; rsa = 1; csa = m; rsb = 1; csb = k; c = malloc( m * n * sizeof( double ) ); a = malloc( m * k * sizeof( double ) ); b = malloc( k * n * sizeof( double ) ); // Set the scalars to use. alpha = 1.0; beta = 1.0; // Initialize the matrix operands. bli_drandm( 0, BLIS_DENSE, m, k, a, rsa, csa ); bli_dsetm( BLIS_NO_CONJUGATE, 0, BLIS_NONUNIT_DIAG, BLIS_DENSE, k, n, &one, b, rsb, csb ); bli_dsetm( BLIS_NO_CONJUGATE, 0, BLIS_NONUNIT_DIAG, BLIS_DENSE, m, n, &zero, c, rsc, csc ); bli_dprintm( "a: randomized", m, k, a, rsa, csa, "%4.1f", "" ); bli_dprintm( "b: set to 1.0", k, n, b, rsb, csb, "%4.1f", "" ); bli_dprintm( "c: initial value", m, n, c, rsc, csc, "%4.1f", "" ); // c := beta * c + alpha * a * b, where 'a', 'b', and 'c' are general. bli_dgemm( BLIS_NO_TRANSPOSE, BLIS_NO_TRANSPOSE, m, n, k, &alpha, a, rsa, csa, b, rsb, csb, &beta, c, rsc, csc ); bli_dprintm( "c: after gemm", m, n, c, rsc, csc, "%4.1f", "" ); // Free the memory obtained via malloc(). free( a ); free( b ); free( c ); // // Example 1b: Perform a general matrix-matrix multiply (gemm) operation // with the left input operand (matrix A) transposed. // printf( "\n#\n# -- Example 1b --\n#\n\n" ); // Create some matrix and vector operands to work with. m = 4; n = 5; k = 3; rsc = 1; csc = m; rsa = 1; csa = k; rsb = 1; csb = k; c = malloc( m * n * sizeof( double ) ); a = malloc( k * m * sizeof( double ) ); b = malloc( k * n * sizeof( double ) ); // Set the scalars to use. alpha = 1.0; beta = 1.0; // Initialize the matrix operands. bli_drandm( 0, BLIS_DENSE, k, m, a, rsa, csa ); bli_dsetm( BLIS_NO_CONJUGATE, 0, BLIS_NONUNIT_DIAG, BLIS_DENSE, k, n, &one, b, rsb, csb ); bli_dsetm( BLIS_NO_CONJUGATE, 0, BLIS_NONUNIT_DIAG, BLIS_DENSE, m, n, &zero, c, rsc, csc ); bli_dprintm( "a: randomized", k, m, a, rsa, csa, "%4.1f", "" ); bli_dprintm( "b: set to 1.0", k, n, b, rsb, csb, "%4.1f", "" ); bli_dprintm( "c: initial value", m, n, c, rsc, csc, "%4.1f", "" ); // c := beta * c + alpha * a^T * b, where 'a', 'b', and 'c' are general. bli_dgemm( BLIS_TRANSPOSE, BLIS_NO_TRANSPOSE, m, n, k, &alpha, a, rsa, csa, b, rsb, csb, &beta, c, rsc, csc ); bli_dprintm( "c: after gemm", m, n, c, rsc, csc, "%4.1f", "" ); // Free the memory obtained via malloc(). free( a ); free( b ); free( c ); // // Example 2: Perform a symmetric rank-k update (syrk) operation. // printf( "\n#\n# -- Example 2 --\n#\n\n" ); // Create some matrix and vector operands to work with. m = 5; k = 3; rsc = 1; csc = m; rsa = 1; csa = m; c = malloc( m * m * sizeof( double ) ); a = malloc( m * k * sizeof( double ) ); // Set the scalars to use. alpha = 1.0; // Initialize the matrix operands. bli_dsetm( BLIS_NO_CONJUGATE, 0, BLIS_NONUNIT_DIAG, BLIS_DENSE, m, m, &zero, c, rsc, csc ); bli_drandm( 0, BLIS_DENSE, m, k, a, rsa, csa ); // Randomize the lower triangle of 'c'. bli_drandm( 0, BLIS_LOWER, m, n, c, rsc, csc ); bli_dprintm( "a: set to random values", m, k, a, rsa, csa, "%4.1f", "" ); bli_dprintm( "c: initial value (zeros in upper triangle)", m, m, c, rsc, csc, "%4.1f", "" ); // c := c + alpha * a * a^T, where 'c' is symmetric and lower-stored. bli_dsyrk( BLIS_LOWER, BLIS_NO_TRANSPOSE, m, k, &alpha, a, rsa, csa, &beta, c, rsc, csc ); bli_dprintm( "c: after syrk", m, m, c, rsc, csc, "%4.1f", "" ); // Free the memory obtained via malloc(). free( a ); free( c ); // // Example 3: Perform a symmetric matrix-matrix multiply (symm) operation. // printf( "\n#\n# -- Example 3 --\n#\n\n" ); // Create some matrix and vector operands to work with. m = 5; n = 6; rsc = 1; csc = m; rsa = 1; csa = m; rsb = 1; csb = m; c = malloc( m * n * sizeof( double ) ); a = malloc( m * m * sizeof( double ) ); b = malloc( m * n * sizeof( double ) ); // Set the scalars to use. alpha = 1.0; beta = 1.0; // Initialize matrices 'b' and 'c'. bli_dsetm( BLIS_NO_CONJUGATE, 0, BLIS_NONUNIT_DIAG, BLIS_DENSE, m, n, &one, b, rsb, csb ); bli_dsetm( BLIS_NO_CONJUGATE, 0, BLIS_NONUNIT_DIAG, BLIS_DENSE, m, n, &zero, c, rsc, csc ); // Zero out all of matrix 'a'. This is optional, but will avoid possibly // displaying junk values in the unstored triangle. bli_dsetm( BLIS_NO_CONJUGATE, 0, BLIS_NONUNIT_DIAG, BLIS_DENSE, m, m, &zero, a, rsa, csa ); // Randomize the upper triangle of 'a'. bli_drandm( 0, BLIS_UPPER, m, m, a, rsa, csa ); bli_dprintm( "a: randomized (zeros in lower triangle)", m, m, a, rsa, csa, "%4.1f", "" ); bli_dprintm( "b: set to 1.0", m, n, b, rsb, csb, "%4.1f", "" ); bli_dprintm( "c: initial value", m, n, c, rsc, csc, "%4.1f", "" ); // c := beta * c + alpha * a * b, where 'a' is symmetric and upper-stored. bli_dsymm( BLIS_LEFT, BLIS_UPPER, BLIS_NO_CONJUGATE, BLIS_NO_TRANSPOSE, m, n, &alpha, a, rsa, csa, b, rsb, csb, &beta, c, rsc, csc ); bli_dprintm( "c: after symm", m, n, c, rsc, csc, "%4.1f", "" ); // Free the memory obtained via malloc(). free( a ); free( b ); free( c ); // // Example 4: Perform a triangular matrix-matrix multiply (trmm) operation. // printf( "\n#\n# -- Example 4 --\n#\n\n" ); // Create some matrix and vector operands to work with. m = 5; n = 4; rsa = 1; csa = m; rsb = 1; csb = m; a = malloc( m * m * sizeof( double ) ); b = malloc( m * n * sizeof( double ) ); // Set the scalars to use. alpha = 1.0; // Initialize matrix 'b'. bli_dsetm( BLIS_NO_CONJUGATE, 0, BLIS_NONUNIT_DIAG, BLIS_DENSE, m, n, &one, b, rsb, csb ); // Zero out all of matrix 'a'. This is optional, but will avoid possibly // displaying junk values in the unstored triangle. bli_dsetm( BLIS_NO_CONJUGATE, 0, BLIS_NONUNIT_DIAG, BLIS_DENSE, m, m, &zero, a, rsa, csa ); // Randomize the lower triangle of 'a'. bli_drandm( 0, BLIS_LOWER, m, m, a, rsa, csa ); bli_dprintm( "a: randomized (zeros in upper triangle)", m, m, a, rsa, csa, "%4.1f", "" ); bli_dprintm( "b: initial value", m, n, b, rsb, csb, "%4.1f", "" ); // b := alpha * a * b, where 'a' is triangular and lower-stored. bli_dtrmm( BLIS_LEFT, BLIS_LOWER, BLIS_NONUNIT_DIAG, BLIS_NO_TRANSPOSE, m, n, &alpha, a, rsa, csa, b, rsb, csb ); bli_dprintm( "b: after trmm", m, n, b, rsb, csb, "%4.1f", "" ); // Free the memory obtained via malloc(). free( a ); free( b ); // // Example 5: Perform a triangular solve with multiple right-hand sides // (trsm) operation. // printf( "\n#\n# -- Example 5 --\n#\n\n" ); // Create some matrix and vector operands to work with. m = 5; n = 4; rsa = 1; csa = m; rsb = 1; csb = m; rsc = 1; csc = m; a = malloc( m * m * sizeof( double ) ); b = malloc( m * n * sizeof( double ) ); c = malloc( m * n * sizeof( double ) ); // Set the scalars to use. alpha = 1.0; // Initialize matrix 'b'. bli_dsetm( BLIS_NO_CONJUGATE, 0, BLIS_NONUNIT_DIAG, BLIS_DENSE, m, n, &one, b, rsb, csb ); // Zero out all of matrix 'a'. This is optional, but will avoid possibly // displaying junk values in the unstored triangle. bli_dsetm( BLIS_NO_CONJUGATE, 0, BLIS_NONUNIT_DIAG, BLIS_DENSE, m, m, &zero, a, rsa, csa ); // Randomize the lower triangle of 'a'. bli_drandm( 0, BLIS_LOWER, m, m, a, rsa, csa ); // Load the diagonal. By setting the diagonal to something of greater // absolute value than the off-diagonal elements, we increase the odds // that the matrix is not singular (singular matrices have no inverse). bli_dshiftd( 0, m, m, &two, a, rsa, csa ); bli_dprintm( "a: randomized (zeros in upper triangle)", m, m, a, rsa, csa, "%4.1f", "" ); bli_dprintm( "b: initial value", m, n, b, rsb, csb, "%4.1f", "" ); // solve a * x = alpha * b, where 'a' is triangular and lower-stored, and // overwrite b with the solution matrix x. bli_dtrsm( BLIS_LEFT, BLIS_LOWER, BLIS_NONUNIT_DIAG, BLIS_NO_TRANSPOSE, m, n, &alpha, a, rsa, csa, b, rsb, csb ); bli_dprintm( "b: after trmm", m, n, b, rsb, csb, "%4.1f", "" ); // We can confirm the solution by comparing the product of a and x to the // original value of b. bli_dcopym( 0, BLIS_NONUNIT_DIAG, BLIS_DENSE, BLIS_NO_TRANSPOSE, m, n, b, rsb, csb, c, rsc, csc ); bli_dtrmm( BLIS_LEFT, BLIS_LOWER, BLIS_NONUNIT_DIAG, BLIS_NO_TRANSPOSE, m, n, &alpha, a, rsa, csa, c, rsc, csc ); bli_dprintm( "c: should equal initial value of b", m, n, c, rsc, csc, "%4.1f", "" ); // Free the memory obtained via malloc(). free( a ); free( b ); free( c ); return 0; } // ----------------------------------------------------------------------------- blis-0.9.0/examples/tapi/05util.c000066400000000000000000000224101422157504600165170ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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 The University of Texas 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 COPYRIGHT HOLDER 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. */ #include #include "blis.h" int main( int argc, char** argv ) { double* x; dcomplex* y; double* a; dcomplex* b; double* c; double* d; dcomplex* e; dcomplex* f; double* g; double norm1, normi, normf; dim_t m, n; inc_t rs, cs; // Initialize some basic constants. double minus_one = -1.0; dcomplex minus_one_z = { -1.0, 0.0 }; // // This file demonstrates working with vector and matrices in the // context of various utility operations. // // // Example 1: Compute various vector norms. // printf( "\n#\n# -- Example 1 --\n#\n\n" ); // Create a few matrices to work with. m = 1; n = 5; rs = 5; cs = 1; x = malloc( m * n * sizeof( double ) ); y = malloc( m * n * sizeof( dcomplex ) ); // Initialize the vectors to random values. bli_drandv( n, x, 1 ); bli_zrandv( n, y, 1 ); bli_dprintm( "x", m, n, x, rs, cs, "%4.1f", "" ); // Compute the one, infinity, and frobenius norms of 'x'. Note that when // computing the norm alpha of a vector 'x', the datatype of alpha must be // equal to the real projection of the datatype of 'x'. bli_dnorm1v( n, x, 1, &norm1 ); bli_dnormiv( n, x, 1, &normi ); bli_dnormfv( n, x, 1, &normf ); bli_dprintm( "x: 1-norm:", 1, 1, &norm1, rs, cs, "%4.1f", "" ); bli_dprintm( "x: infinity norm:", 1, 1, &normi, rs, cs, "%4.1f", "" ); bli_dprintm( "x: frobenius norm:", 1, 1, &normf, rs, cs, "%4.1f", "" ); bli_zprintm( "y", m, n, y, rs, cs, "%4.1f", "" ); // Compute the one, infinity, and frobenius norms of 'y'. Note that we // can reuse the same scalars from before for computing norms of // dcomplex matrices, since the real projection of dcomplex is double. bli_znorm1v( n, y, 1, &norm1 ); bli_znormiv( n, y, 1, &normi ); bli_znormfv( n, y, 1, &normf ); bli_dprintm( "y: 1-norm:", 1, 1, &norm1, 1, 1, "%4.1f", "" ); bli_dprintm( "y: infinity norm:", 1, 1, &normi, 1, 1, "%4.1f", "" ); bli_dprintm( "y: frobenius norm:", 1, 1, &normf, 1, 1, "%4.1f", "" ); // // Example 2: Compute various matrix norms. // printf( "\n#\n# -- Example 2 --\n#\n\n" ); // Create a few matrices to work with. m = 5; n = 6; rs = 1; cs = m; a = malloc( m * n * sizeof( double ) ); b = malloc( m * n * sizeof( dcomplex ) ); // Initialize the matrices to random values. bli_drandm( 0, BLIS_DENSE, m, n, a, rs, cs ); bli_zrandm( 0, BLIS_DENSE, m, n, b, rs, cs ); bli_dprintm( "a:", m, n, a, rs, cs, "%4.1f", "" ); // Compute the one-norm of 'a'. bli_dnorm1m( 0, BLIS_NONUNIT_DIAG, BLIS_DENSE, m, n, a, rs, cs, &norm1 ); bli_dnormim( 0, BLIS_NONUNIT_DIAG, BLIS_DENSE, m, n, a, rs, cs, &normi ); bli_dnormfm( 0, BLIS_NONUNIT_DIAG, BLIS_DENSE, m, n, a, rs, cs, &normf ); bli_dprintm( "a: 1-norm:", 1, 1, &norm1, 1, 1, "%4.1f", "" ); bli_dprintm( "a: infinity norm:", 1, 1, &normi, 1, 1, "%4.1f", "" ); bli_dprintm( "a: frobenius norm:", 1, 1, &normf, 1, 1, "%4.1f", "" ); bli_zprintm( "b:", m, n, b, rs, cs, "%4.1f", "" ); // Compute the one-norm of 'b'. bli_znorm1m( 0, BLIS_NONUNIT_DIAG, BLIS_DENSE, m, n, b, rs, cs, &norm1 ); bli_znormim( 0, BLIS_NONUNIT_DIAG, BLIS_DENSE, m, n, b, rs, cs, &normi ); bli_znormfm( 0, BLIS_NONUNIT_DIAG, BLIS_DENSE, m, n, b, rs, cs, &normf ); bli_dprintm( "a: 1-norm:", 1, 1, &norm1, 1, 1, "%4.1f", "" ); bli_dprintm( "a: infinity norm:", 1, 1, &normi, 1, 1, "%4.1f", "" ); bli_dprintm( "a: frobenius norm:", 1, 1, &normf, 1, 1, "%4.1f", "" ); // // Example 3: Make a real matrix explicitly symmetric (or Hermitian). // printf( "\n#\n# -- Example 3 --\n#\n\n" ); // Create a few matrices to work with. m = 4; n = 4; rs = 1; cs = m; c = malloc( m * m * sizeof( double ) ); d = malloc( m * m * sizeof( double ) ); // Initialize all of 'c' to -1.0 to simulate junk values. bli_dsetm( BLIS_NO_CONJUGATE, 0, BLIS_NONUNIT_DIAG, BLIS_DENSE, m, m, &minus_one, c, rs, cs ); // Randomize the lower triangle of 'c'. bli_drandm( 0, BLIS_LOWER, m, m, c, rs, cs ); bli_dprintm( "c (initial state):", m, m, c, rs, cs, "%4.1f", "" ); // mksymm on a real matrix transposes the stored triangle into the // unstored triangle, making the matrix densely symmetric. bli_dmksymm( BLIS_LOWER, m, c, rs, cs ); bli_dprintm( "c (after mksymm on lower triangle):", m, m, c, rs, cs, "%4.1f", "" ); // Digression: Most people think only of complex matrices as being able // to be complex. However, in BLIS, we define Hermitian operations on // real matrices, too--they are simply equivalent to the corresponding // symmetric operation. For example, when we make a real matrix explicitly // Hermitian, the result is indistinguishable from making it symmetric. // Initialize all of 'd' to -1.0 to simulate junk values. bli_dsetm( BLIS_NO_CONJUGATE, 0, BLIS_NONUNIT_DIAG, BLIS_DENSE, m, m, &minus_one, d, rs, cs ); // Randomize the lower triangle of 'd'. bli_drandm( 0, BLIS_LOWER, m, m, d, rs, cs ); bli_dprintm( "d (initial state):", m, m, d, rs, cs, "%4.1f", "" ); // mkherm on a real matrix behaves the same as mksymm, as there are no // imaginary elements to conjugate. bli_dmkherm( BLIS_LOWER, m, d, rs, cs ); bli_dprintm( "c (after mkherm on lower triangle):", m, m, d, rs, cs, "%4.1f", "" ); // // Example 4: Make a complex matrix explicitly symmetric or Hermitian. // printf( "\n#\n# -- Example 4 --\n#\n\n" ); // Create a few matrices to work with. m = 4; n = 4; rs = 1; cs = m; e = malloc( m * m * sizeof( dcomplex ) ); f = malloc( m * m * sizeof( dcomplex ) ); // Initialize all of 'e' to -1.0 to simulate junk values. bli_zsetm( BLIS_NO_CONJUGATE, 0, BLIS_NONUNIT_DIAG, BLIS_DENSE, m, m, &minus_one_z, e, rs, cs ); // Randomize the upper triangle of 'e'. bli_zrandm( 0, BLIS_UPPER, m, m, e, rs, cs ); bli_zprintm( "e (initial state):", m, m, e, rs, cs, "%4.1f", "" ); // mksymm on a complex matrix transposes the stored triangle into the // unstored triangle. bli_zmksymm( BLIS_UPPER, m, e, rs, cs ); bli_zprintm( "e (after mksymm on lower triangle):", m, m, e, rs, cs, "%4.1f", "" ); // Initialize all of 'f' to -1.0 to simulate junk values. bli_zsetm( BLIS_NO_CONJUGATE, 0, BLIS_NONUNIT_DIAG, BLIS_DENSE, m, m, &minus_one_z, f, rs, cs ); // Randomize the upper triangle of 'd'. bli_zrandm( 0, BLIS_UPPER, m, m, f, rs, cs ); bli_zprintm( "f (initial state):", m, m, f, rs, cs, "%4.1f", "" ); // mkherm on a real matrix behaves the same as mksymm, as there are no // imaginary elements to conjugate. bli_zmkherm( BLIS_UPPER, m, f, rs, cs ); bli_zprintm( "f (after mkherm on lower triangle):", m, m, f, rs, cs, "%4.1f", "" ); // // Example 5: Make a real matrix explicitly triangular. // printf( "\n#\n# -- Example 5 --\n#\n\n" ); // Create a few matrices to work with. m = 5; n = 5; rs = 1; cs = m; g = malloc( m * m * sizeof( double ) ); // Initialize all of 'g' to -1.0 to simulate junk values. bli_dsetm( BLIS_NO_CONJUGATE, 0, BLIS_NONUNIT_DIAG, BLIS_DENSE, m, m, &minus_one, g, rs, cs ); // Randomize the lower triangle of 'g'. bli_drandm( 0, BLIS_LOWER, m, m, g, rs, cs ); bli_dprintm( "g (initial state):", m, m, g, rs, cs, "%4.1f", "" ); // mktrim does not explicitly copy any data, since presumably the stored // triangle already contains the data of interest. However, mktrim does // explicitly writes zeros to the unstored region. bli_dmktrim( BLIS_LOWER, m, g, rs, cs ); bli_dprintm( "g (after mktrim):", m, m, g, rs, cs, "%4.1f", "" ); // Free the memory obtained via malloc(). free( x ); free( y ); free( a ); free( b ); free( c ); free( d ); free( e ); free( f ); free( g ); return 0; } // ----------------------------------------------------------------------------- blis-0.9.0/examples/tapi/Makefile000066400000000000000000000113041422157504600166710ustar00rootroot00000000000000# # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2014, The University of Texas at Austin # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # # # Makefile # # Field G. Van Zee # # Makefile for BLIS typed API example code. # # # --- Makefile PHONY target definitions ---------------------------------------- # .PHONY: all bin clean run # # --- Determine makefile fragment location ------------------------------------- # # Comments: # - DIST_PATH is assumed to not exist if BLIS_INSTALL_PATH is given. # - We must use recursively expanded assignment for LIB_PATH and INC_PATH in # the second case because CONFIG_NAME is not yet set. ifneq ($(strip $(BLIS_INSTALL_PATH)),) LIB_PATH := $(BLIS_INSTALL_PATH)/lib INC_PATH := $(BLIS_INSTALL_PATH)/include/blis SHARE_PATH := $(BLIS_INSTALL_PATH)/share/blis else DIST_PATH := ../.. LIB_PATH = ../../lib/$(CONFIG_NAME) INC_PATH = ../../include/$(CONFIG_NAME) SHARE_PATH := ../.. endif # # --- Include common makefile definitions -------------------------------------- # # Include the common makefile fragment. -include $(SHARE_PATH)/common.mk # # --- General build definitions ------------------------------------------------ # TEST_SRC_PATH := . TEST_OBJ_PATH := . # Gather all local object files. TEST_OBJS := $(sort $(patsubst $(TEST_SRC_PATH)/%.c, \ $(TEST_OBJ_PATH)/%.o, \ $(wildcard $(TEST_SRC_PATH)/*.c))) # Override the value of CINCFLAGS so that the value of CFLAGS returned by # get-user-cflags-for() is not cluttered up with include paths needed only # while building BLIS. CINCFLAGS := -I$(INC_PATH) # Use the "framework" CFLAGS for the configuration family. CFLAGS := $(call get-user-cflags-for,$(CONFIG_NAME)) # Add local header paths to CFLAGS CFLAGS += -I$(TEST_SRC_PATH) # Locate the libblis library to which we will link. #LIBBLIS_LINK := $(LIB_PATH)/$(LIBBLIS_L) # Binary executable name. TEST_BINS := 00level1v.x \ 01level1m.x \ 02level1m_diag.x \ 03level2.x \ 04level3.x \ 05util.x # # --- Targets/rules ------------------------------------------------------------ # # --- Primary targets --- all: bin bin: $(TEST_BINS) # --- Environment check rules --- check-env: check-env-make-defs check-env-fragments check-env-config-mk check-env-config-mk: ifeq ($(CONFIG_MK_PRESENT),no) $(error Cannot proceed: config.mk not detected! Run configure first) endif check-env-make-defs: check-env-fragments ifeq ($(MAKE_DEFS_MK_PRESENT),no) $(error Cannot proceed: make_defs.mk not detected! Invalid configuration) endif # --Object file rules -- $(TEST_OBJ_PATH)/%.o: $(TEST_SRC_PATH)/%.c $(LIBBLIS_LINK) ifeq ($(ENABLE_VERBOSE),yes) $(CC) $(CFLAGS) -c $< -o $@ else @echo "Compiling $@" @$(CC) $(CFLAGS) -c $< -o $@ endif # -- Executable file rules -- %.x: %.o $(LIBBLIS_LINK) ifeq ($(ENABLE_VERBOSE),yes) $(LINKER) $< $(LIBBLIS_LINK) $(LDFLAGS) -o $@ else @echo "Linking $@ against '$(LIBBLIS_LINK) $(LDFLAGS)'" @$(LINKER) $< $(LIBBLIS_LINK) $(LDFLAGS) -o $@ endif # -- Test run rules -- #run: $(TEST_BIN) # ./$(TEST_BIN) # -- Clean rules -- clean: - $(RM_F) $(TEST_OBJS) $(TEST_BINS) blis-0.9.0/examples/tapi/README000066400000000000000000000031141422157504600161110ustar00rootroot00000000000000 BLIS typed API examples ----------------------- This directory contains several files, each containing various pieces of example code that demonstrate core functionality of the typed API in BLIS. These example files should be thought of collectively like a tutorial, and therefore it is recommended to start from the beginning (the file that starts in '00'). You can build all of the examples by simply running 'make' from this directory. (You can also run 'make clean'.) The makefile assumes that you've already configured and built (but not necessarily installed) BLIS two directories up, in "../..". If you have already installed BLIS to some permanent directory, you may refer to that installation by setting the environment variable BLIS_INSTALL_PATH prior to running make: export BLIS_INSTALL_PATH=/usr/local; make or by setting the same variable as part of the make command: make BLIS_INSTALL_PATH=/usr/local Once the executable files have been built, we recommend reading the code in one terminal window alongside the executable output in another terminal. This will help you see the effects of each section of code. This tutorial is not exhaustive or complete; many typed API functions were omitted (mostly for brevity's sake) and thus more examples could be written. If you've found typed functionality in BLIS and are unsure how to use it, or if you are unsure of what additional functionality is present in BLIS, please feel free to join and then start a discussion on the blis-devel mailing list [1]. Thanks for your interest in BLIS! [1] https://groups.google.com/d/forum/blis-devel blis-0.9.0/frame/000077500000000000000000000000001422157504600135515ustar00rootroot00000000000000blis-0.9.0/frame/0/000077500000000000000000000000001422157504600137105ustar00rootroot00000000000000blis-0.9.0/frame/0/bli_l0.h000066400000000000000000000035411422157504600152250ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "bli_l0_check.h" #include "bli_l0_oapi.h" #include "bli_l0_tapi.h" #include "bli_l0_ft.h" // Generate function pointer arrays for tapi functions. #include "bli_l0_fpa.h" // copysc #include "bli_copysc.h" blis-0.9.0/frame/0/bli_l0_check.c000066400000000000000000000210111422157504600163450ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // Define object-based check functions. // #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC(opname,_check) \ ( \ obj_t* chi, \ obj_t* psi \ ) \ { \ bli_l0_xxsc_check( chi, psi ); \ } GENFRONT( addsc ) GENFRONT( copysc ) GENFRONT( divsc ) GENFRONT( mulsc ) GENFRONT( sqrtsc ) GENFRONT( subsc ) #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC(opname,_check) \ ( \ obj_t* chi \ ) \ { \ bli_l0_xsc_check( chi ); \ } GENFRONT( invertsc ) #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC(opname,_check) \ ( \ obj_t* chi, \ obj_t* norm \ ) \ { \ bli_l0_xx2sc_check( chi, norm ); \ } GENFRONT( absqsc ) GENFRONT( normfsc ) // ----------------------------------------------------------------------------- void bli_getsc_check ( obj_t* chi, double* zeta_r, double* zeta_i ) { err_t e_val; // Check object datatypes. //e_val = bli_check_noninteger_object( chi ); //bli_check_error_code( e_val ); // Check object dimensions. e_val = bli_check_scalar_object( chi ); bli_check_error_code( e_val ); // Check object buffers (for non-NULLness). e_val = bli_check_object_buffer( chi ); bli_check_error_code( e_val ); } void bli_setsc_check ( double zeta_r, double zeta_i, obj_t* chi ) { err_t e_val; // Check object datatypes. //e_val = bli_check_floating_object( chi ); //bli_check_error_code( e_val ); // Check object dimensions. e_val = bli_check_scalar_object( chi ); bli_check_error_code( e_val ); // Check object buffers (for non-NULLness). e_val = bli_check_object_buffer( chi ); bli_check_error_code( e_val ); } void bli_unzipsc_check ( obj_t* chi, obj_t* zeta_r, obj_t* zeta_i ) { err_t e_val; // Check object datatypes. e_val = bli_check_noninteger_object( chi ); bli_check_error_code( e_val ); e_val = bli_check_real_object( zeta_r ); bli_check_error_code( e_val ); e_val = bli_check_real_object( zeta_i ); bli_check_error_code( e_val ); e_val = bli_check_nonconstant_object( zeta_r ); bli_check_error_code( e_val ); e_val = bli_check_nonconstant_object( zeta_i ); bli_check_error_code( e_val ); e_val = bli_check_object_real_proj_of( chi, zeta_r ); bli_check_error_code( e_val ); e_val = bli_check_object_real_proj_of( chi, zeta_i ); bli_check_error_code( e_val ); // Check object dimensions. e_val = bli_check_scalar_object( chi ); bli_check_error_code( e_val ); e_val = bli_check_scalar_object( zeta_r ); bli_check_error_code( e_val ); e_val = bli_check_scalar_object( zeta_i ); bli_check_error_code( e_val ); // Check object buffers (for non-NULLness). e_val = bli_check_object_buffer( chi ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( zeta_r ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( zeta_i ); bli_check_error_code( e_val ); } void bli_zipsc_check ( obj_t* zeta_r, obj_t* zeta_i, obj_t* chi ) { err_t e_val; // Check object datatypes. e_val = bli_check_real_object( zeta_r ); bli_check_error_code( e_val ); e_val = bli_check_real_object( zeta_i ); bli_check_error_code( e_val ); e_val = bli_check_noninteger_object( chi ); bli_check_error_code( e_val ); e_val = bli_check_nonconstant_object( chi ); bli_check_error_code( e_val ); e_val = bli_check_object_real_proj_of( chi, zeta_r ); bli_check_error_code( e_val ); e_val = bli_check_object_real_proj_of( chi, zeta_i ); bli_check_error_code( e_val ); // Check object dimensions. e_val = bli_check_scalar_object( zeta_r ); bli_check_error_code( e_val ); e_val = bli_check_scalar_object( zeta_i ); bli_check_error_code( e_val ); e_val = bli_check_scalar_object( chi ); bli_check_error_code( e_val ); // Check object buffers (for non-NULLness). e_val = bli_check_object_buffer( zeta_r ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( zeta_i ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( chi ); bli_check_error_code( e_val ); } // ----------------------------------------------------------------------------- void bli_l0_xsc_check ( obj_t* chi ) { err_t e_val; // Check object datatypes. e_val = bli_check_noninteger_object( chi ); bli_check_error_code( e_val ); e_val = bli_check_nonconstant_object( chi ); bli_check_error_code( e_val ); // Check object dimensions. e_val = bli_check_scalar_object( chi ); bli_check_error_code( e_val ); // Check object buffers (for non-NULLness). e_val = bli_check_object_buffer( chi ); bli_check_error_code( e_val ); } void bli_l0_xxsc_check ( obj_t* chi, obj_t* psi ) { err_t e_val; // Check object datatypes. e_val = bli_check_noninteger_object( chi ); bli_check_error_code( e_val ); e_val = bli_check_noninteger_object( psi ); bli_check_error_code( e_val ); e_val = bli_check_nonconstant_object( psi ); bli_check_error_code( e_val ); // Check object dimensions. e_val = bli_check_scalar_object( chi ); bli_check_error_code( e_val ); e_val = bli_check_scalar_object( psi ); bli_check_error_code( e_val ); // Check object buffers (for non-NULLness). e_val = bli_check_object_buffer( chi ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( psi ); bli_check_error_code( e_val ); } void bli_l0_xx2sc_check ( obj_t* chi, obj_t* absq ) { err_t e_val; // Check object datatypes. e_val = bli_check_noninteger_object( chi ); bli_check_error_code( e_val ); e_val = bli_check_nonconstant_object( absq ); bli_check_error_code( e_val ); e_val = bli_check_real_object( absq ); bli_check_error_code( e_val ); e_val = bli_check_object_real_proj_of( chi, absq ); bli_check_error_code( e_val ); // Check object dimensions. e_val = bli_check_scalar_object( chi ); bli_check_error_code( e_val ); e_val = bli_check_scalar_object( absq ); bli_check_error_code( e_val ); // Check object buffers (for non-NULLness). e_val = bli_check_object_buffer( chi ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( absq ); bli_check_error_code( e_val ); } void bli_l0_xxbsc_check ( obj_t* chi, obj_t* psi, bool* is_eq ) { err_t e_val; // Check object datatypes. e_val = bli_check_noninteger_object( chi ); bli_check_error_code( e_val ); e_val = bli_check_noninteger_object( psi ); bli_check_error_code( e_val ); // Check object dimensions. e_val = bli_check_scalar_object( chi ); bli_check_error_code( e_val ); e_val = bli_check_scalar_object( psi ); bli_check_error_code( e_val ); // Check object buffers (for non-NULLness). e_val = bli_check_object_buffer( chi ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( psi ); bli_check_error_code( e_val ); } blis-0.9.0/frame/0/bli_l0_check.h000066400000000000000000000066021422157504600163630ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype object-based check functions. // #undef GENTPROT #define GENTPROT( opname ) \ \ void PASTEMAC(opname,_check) \ ( \ obj_t* chi, \ obj_t* psi \ ); GENTPROT( addsc ) GENTPROT( copysc ) GENTPROT( divsc ) GENTPROT( mulsc ) GENTPROT( sqrtsc ) GENTPROT( subsc ) #undef GENTPROT #define GENTPROT( opname ) \ \ void PASTEMAC(opname,_check) \ ( \ obj_t* chi \ ); GENTPROT( invertsc ) #undef GENTPROT #define GENTPROT( opname ) \ \ void PASTEMAC(opname,_check) \ ( \ obj_t* chi, \ obj_t* absq \ ); GENTPROT( absqsc ) GENTPROT( normfsc ) #undef GENTPROT #define GENTPROT( opname ) \ \ void PASTEMAC(opname,_check) \ ( \ obj_t* chi, \ double* zeta_r, \ double* zeta_i \ ); GENTPROT( getsc ) #undef GENTPROT #define GENTPROT( opname ) \ \ void PASTEMAC(opname,_check) \ ( \ double zeta_r, \ double zeta_i, \ obj_t* chi \ ); GENTPROT( setsc ) #undef GENTPROT #define GENTPROT( opname ) \ \ void PASTEMAC(opname,_check) \ ( \ obj_t* chi, \ obj_t* zeta_r, \ obj_t* zeta_i \ ); GENTPROT( unzipsc ) #undef GENTPROT #define GENTPROT( opname ) \ \ void PASTEMAC(opname,_check) \ ( \ obj_t* zeta_r, \ obj_t* zeta_i, \ obj_t* chi \ ); GENTPROT( zipsc ) // ----------------------------------------------------------------------------- void bli_l0_xsc_check ( obj_t* chi ); void bli_l0_xxsc_check ( obj_t* chi, obj_t* psi ); void bli_l0_xx2sc_check ( obj_t* chi, obj_t* norm ); void bli_l0_xxbsc_check ( obj_t* chi, obj_t* psi, bool* is_eq ); blis-0.9.0/frame/0/bli_l0_fpa.c000066400000000000000000000045061422157504600160500ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // Define function pointer query interfaces. // #undef GENFRONT #define GENFRONT( opname ) \ \ GENARRAY_FPA( PASTECH(opname,_vft), opname ); \ \ PASTECH(opname,_vft) PASTEMAC(opname,_qfp)( num_t dt ) \ { \ return PASTECH(opname,_fpa)[ dt ]; \ } GENFRONT( absqsc ) GENFRONT( normfsc ) GENFRONT( addsc ) GENFRONT( divsc ) GENFRONT( mulsc ) GENFRONT( subsc ) GENFRONT( invertsc ) GENFRONT( sqrtsc ) GENFRONT( unzipsc ) GENFRONT( zipsc ) #undef GENFRONT #define GENFRONT( opname ) \ \ GENARRAY_FPA_I( PASTECH(opname,_vft), opname ); \ \ PASTECH(opname,_vft) PASTEMAC(opname,_qfp)( num_t dt ) \ { \ return PASTECH(opname,_fpa)[ dt ]; \ } GENFRONT( getsc ) GENFRONT( setsc ) blis-0.9.0/frame/0/bli_l0_fpa.h000066400000000000000000000037771422157504600160660ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype function pointer query interface. // #undef GENPROT #define GENPROT( opname ) \ \ PASTECH(opname,_vft) \ PASTEMAC(opname,_qfp)( num_t dt ); GENPROT( absqsc ) GENPROT( normfsc ) GENPROT( addsc ) GENPROT( divsc ) GENPROT( mulsc ) GENPROT( subsc ) GENPROT( invertsc ) GENPROT( sqrtsc ) GENPROT( unzipsc ) GENPROT( zipsc ) GENPROT( getsc ) GENPROT( setsc ) blis-0.9.0/frame/0/bli_l0_ft.h000066400000000000000000000100301422157504600157050ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // -- Level-0 function types --------------------------------------------------- // // addsc, divsc, subsc #undef GENTDEF #define GENTDEF( ctype, ch, opname, tsuf ) \ \ typedef void (*PASTECH2(ch,opname,tsuf)) \ ( \ conj_t conjchi, \ ctype* chi, \ ctype* psi \ ); INSERT_GENTDEF( addsc ) INSERT_GENTDEF( divsc ) INSERT_GENTDEF( subsc ) // invertsc #undef GENTDEF #define GENTDEF( ctype, ch, opname, tsuf ) \ \ typedef void (*PASTECH2(ch,opname,tsuf)) \ ( \ conj_t conjchi, \ ctype* chi \ ); INSERT_GENTDEF( invertsc ) // mulsc #undef GENTDEF #define GENTDEF( ctype, ch, opname, tsuf ) \ \ typedef void (*PASTECH2(ch,opname,tsuf)) \ ( \ conj_t conjchi, \ ctype* chi, \ ctype* psi \ ); INSERT_GENTDEF( mulsc ) // absqsc #undef GENTDEFR #define GENTDEFR( ctype, ctype_r, ch, chr, opname, tsuf ) \ \ typedef void (*PASTECH2(ch,opname,tsuf)) \ ( \ ctype* chi, \ ctype_r* absq \ ); INSERT_GENTDEFR( absqsc ) // normfsc #undef GENTDEFR #define GENTDEFR( ctype, ctype_r, ch, chr, opname, tsuf ) \ \ typedef void (*PASTECH2(ch,opname,tsuf)) \ ( \ ctype* chi, \ ctype_r* norm \ ); INSERT_GENTDEFR( normfsc ) // sqrtsc #undef GENTDEF #define GENTDEF( ctype, ch, opname, tsuf ) \ \ typedef void (*PASTECH2(ch,opname,tsuf)) \ ( \ ctype* chi, \ ctype* psi \ ); INSERT_GENTDEF( sqrtsc ) // getsc #undef GENTDEF #define GENTDEF( ctype, ch, opname, tsuf ) \ \ typedef void (*PASTECH2(ch,opname,tsuf)) \ ( \ ctype* chi, \ double* zeta_r, \ double* zeta_i \ ); INSERT_GENTDEF( getsc ) // setsc #undef GENTDEF #define GENTDEF( ctype, ch, opname, tsuf ) \ \ typedef void (*PASTECH2(ch,opname,tsuf)) \ ( \ double zeta_r, \ double zeta_i, \ ctype* chi \ ); INSERT_GENTDEF( setsc ) // unzipsc #undef GENTDEFR #define GENTDEFR( ctype, ctype_r, ch, chr, opname, tsuf ) \ \ typedef void (*PASTECH2(ch,opname,tsuf)) \ ( \ ctype* chi, \ ctype_r* zeta_r, \ ctype_r* zeta_i \ ); INSERT_GENTDEFR( unzipsc ) // zipsc #undef GENTDEFR #define GENTDEFR( ctype, ctype_r, ch, chr, opname, tsuf ) \ \ typedef void (*PASTECH2(ch,opname,tsuf)) \ ( \ ctype_r* zeta_r, \ ctype_r* zeta_i, \ ctype* chi \ ); INSERT_GENTDEFR( zipsc ) blis-0.9.0/frame/0/bli_l0_oapi.c000066400000000000000000000205741422157504600162350ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // Define object-based interfaces. // #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC0(opname) \ ( \ obj_t* chi, \ obj_t* absq \ ) \ { \ bli_init_once(); \ \ num_t dt_chi; \ num_t dt_absq_c = bli_obj_dt_proj_to_complex( absq ); \ \ void* buf_chi; \ void* buf_absq = bli_obj_buffer_at_off( absq ); \ \ if ( bli_error_checking_is_enabled() ) \ PASTEMAC(opname,_check)( chi, absq ); \ \ /* If chi is a scalar constant, use dt_absq_c to extract the address of the corresponding constant value; otherwise, use the datatype encoded within the chi object and extract the buffer at the chi offset. */ \ bli_obj_scalar_set_dt_buffer( chi, dt_absq_c, &dt_chi, &buf_chi ); \ \ /* Query a type-specific function pointer, except one that uses void* for function arguments instead of typed pointers. */ \ PASTECH(opname,_vft) f = PASTEMAC(opname,_qfp)( dt_chi ); \ \ f \ ( \ buf_chi, \ buf_absq \ ); \ } GENFRONT( absqsc ) GENFRONT( normfsc ) #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC0(opname) \ ( \ obj_t* chi, \ obj_t* psi \ ) \ { \ bli_init_once(); \ \ num_t dt = bli_obj_dt( psi ); \ \ conj_t conjchi = bli_obj_conj_status( chi ); \ \ void* buf_chi = bli_obj_buffer_for_1x1( dt, chi ); \ void* buf_psi = bli_obj_buffer_at_off( psi ); \ \ if ( bli_error_checking_is_enabled() ) \ PASTEMAC(opname,_check)( chi, psi ); \ \ /* Query a type-specific function pointer, except one that uses void* for function arguments instead of typed pointers. */ \ PASTECH(opname,_vft) f = PASTEMAC(opname,_qfp)( dt ); \ \ f \ ( \ conjchi, \ buf_chi, \ buf_psi \ ); \ } GENFRONT( addsc ) GENFRONT( divsc ) GENFRONT( mulsc ) GENFRONT( subsc ) #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC0(opname) \ ( \ obj_t* chi \ ) \ { \ bli_init_once(); \ \ num_t dt = bli_obj_dt( chi ); \ \ conj_t conjchi = bli_obj_conj_status( chi ); \ \ void* buf_chi = bli_obj_buffer_for_1x1( dt, chi ); \ \ if ( bli_error_checking_is_enabled() ) \ PASTEMAC(opname,_check)( chi ); \ \ /* Query a type-specific function pointer, except one that uses void* for function arguments instead of typed pointers. */ \ PASTECH(opname,_vft) f = PASTEMAC(opname,_qfp)( dt ); \ \ f \ ( \ conjchi, \ buf_chi \ ); \ } GENFRONT( invertsc ) #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC0(opname) \ ( \ obj_t* chi, \ obj_t* psi \ ) \ { \ bli_init_once(); \ \ num_t dt = bli_obj_dt( psi ); \ \ void* buf_chi = bli_obj_buffer_for_1x1( dt, chi ); \ void* buf_psi = bli_obj_buffer_at_off( psi ); \ \ if ( bli_error_checking_is_enabled() ) \ PASTEMAC(opname,_check)( chi, psi ); \ \ /* Query a type-specific function pointer, except one that uses void* for function arguments instead of typed pointers. */ \ PASTECH(opname,_vft) f = PASTEMAC(opname,_qfp)( dt ); \ \ f \ ( \ buf_chi, \ buf_psi \ ); \ } GENFRONT( sqrtsc ) #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC0(opname) \ ( \ obj_t* chi, \ double* zeta_r, \ double* zeta_i \ ) \ { \ bli_init_once(); \ \ num_t dt_chi = bli_obj_dt( chi ); \ num_t dt_def = BLIS_DCOMPLEX; \ num_t dt_use; \ \ /* If chi is a constant object, default to using the dcomplex value to maximize precision, and since we don't know if the caller needs just the real or the real and imaginary parts. */ \ void* buf_chi = bli_obj_buffer_for_1x1( dt_def, chi ); \ \ if ( bli_error_checking_is_enabled() ) \ PASTEMAC(opname,_check)( chi, zeta_r, zeta_i ); \ \ /* The _check() routine prevents integer types, so we know that chi is either a constant or an actual floating-point type. */ \ if ( bli_is_constant( dt_chi ) ) dt_use = dt_def; \ else dt_use = dt_chi; \ \ /* Query a type-specific function pointer, except one that uses void* for function arguments instead of typed pointers. */ \ PASTECH(opname,_vft) f = PASTEMAC(opname,_qfp)( dt_use ); \ \ f \ ( \ buf_chi, \ zeta_r, \ zeta_i \ ); \ } GENFRONT( getsc ) #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC0(opname) \ ( \ double zeta_r, \ double zeta_i, \ obj_t* chi \ ) \ { \ bli_init_once(); \ \ num_t dt_chi = bli_obj_dt( chi ); \ \ void* buf_chi = bli_obj_buffer_at_off( chi ); \ \ if ( bli_error_checking_is_enabled() ) \ PASTEMAC(opname,_check)( zeta_r, zeta_i, chi ); \ \ /* Query a type-specific function pointer, except one that uses void* for function arguments instead of typed pointers. */ \ PASTECH(opname,_vft) f = PASTEMAC(opname,_qfp)( dt_chi ); \ \ f \ ( \ zeta_r, \ zeta_i, \ buf_chi \ ); \ } GENFRONT( setsc ) #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC0(opname) \ ( \ obj_t* chi, \ obj_t* zeta_r, \ obj_t* zeta_i \ ) \ { \ bli_init_once(); \ \ num_t dt_chi; \ num_t dt_zeta_c = bli_obj_dt_proj_to_complex( zeta_r ); \ \ void* buf_chi; \ \ void* buf_zeta_r = bli_obj_buffer_at_off( zeta_r ); \ void* buf_zeta_i = bli_obj_buffer_at_off( zeta_i ); \ \ if ( bli_error_checking_is_enabled() ) \ PASTEMAC(opname,_check)( chi, zeta_r, zeta_i ); \ \ /* If chi is a scalar constant, use dt_zeta_c to extract the address of the corresponding constant value; otherwise, use the datatype encoded within the chi object and extract the buffer at the chi offset. */ \ bli_obj_scalar_set_dt_buffer( chi, dt_zeta_c, &dt_chi, &buf_chi ); \ \ /* Query a type-specific function pointer, except one that uses void* for function arguments instead of typed pointers. */ \ PASTECH(opname,_vft) f = PASTEMAC(opname,_qfp)( dt_chi ); \ \ f \ ( \ buf_chi, \ buf_zeta_r, \ buf_zeta_i \ ); \ } GENFRONT( unzipsc ) #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC0(opname) \ ( \ obj_t* zeta_r, \ obj_t* zeta_i, \ obj_t* chi \ ) \ { \ bli_init_once(); \ \ num_t dt_chi = bli_obj_dt( chi ); \ \ void* buf_zeta_r = bli_obj_buffer_for_1x1( dt_chi, zeta_r ); \ void* buf_zeta_i = bli_obj_buffer_for_1x1( dt_chi, zeta_i ); \ \ void* buf_chi = bli_obj_buffer_at_off( chi ); \ \ if ( bli_error_checking_is_enabled() ) \ PASTEMAC(opname,_check)( chi, zeta_r, zeta_i ); \ \ /* Query a type-specific function pointer, except one that uses void* for function arguments instead of typed pointers. */ \ PASTECH(opname,_vft) f = PASTEMAC(opname,_qfp)( dt_chi ); \ \ f \ ( \ buf_zeta_i, \ buf_zeta_r, \ buf_chi \ ); \ } GENFRONT( zipsc ) blis-0.9.0/frame/0/bli_l0_oapi.h000066400000000000000000000060161422157504600162350ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype object-based interfaces. // #undef GENPROT #define GENPROT( opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC0(opname) \ ( \ obj_t* chi, \ obj_t* absq \ ); GENPROT( absqsc ) GENPROT( normfsc ) #undef GENPROT #define GENPROT( opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC0(opname) \ ( \ obj_t* chi, \ obj_t* psi \ ); GENPROT( addsc ) GENPROT( divsc ) GENPROT( mulsc ) GENPROT( sqrtsc ) GENPROT( subsc ) #undef GENPROT #define GENPROT( opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC0(opname) \ ( \ obj_t* chi \ ); GENPROT( invertsc ) #undef GENPROT #define GENPROT( opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC0(opname) \ ( \ obj_t* chi, \ double* zeta_r, \ double* zeta_i \ ); GENPROT( getsc ) #undef GENPROT #define GENPROT( opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC0(opname) \ ( \ double zeta_r, \ double zeta_i, \ obj_t* chi \ ); GENPROT( setsc ) #undef GENPROT #define GENPROT( opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC0(opname) \ ( \ obj_t* chi, \ obj_t* zeta_r, \ obj_t* zeta_i \ ); GENPROT( unzipsc ) #undef GENPROT #define GENPROT( opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC0(opname) \ ( \ obj_t* zeta_r, \ obj_t* zeta_i, \ obj_t* chi \ ); GENPROT( zipsc ) blis-0.9.0/frame/0/bli_l0_tapi.c000066400000000000000000000134071422157504600162370ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // Define BLAS-like interfaces with typed operands. // #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, kername ) \ \ void PASTEMAC(ch,opname) \ ( \ conj_t conjchi, \ ctype* chi, \ ctype* psi \ ) \ { \ bli_init_once(); \ \ ctype chi_conj; \ \ PASTEMAC(ch,copycjs)( conjchi, *chi, chi_conj ); \ PASTEMAC(ch,kername)( chi_conj, *psi ); \ } INSERT_GENTFUNC_BASIC( addsc, adds ) INSERT_GENTFUNC_BASIC( divsc, invscals ) INSERT_GENTFUNC_BASIC( subsc, subs ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, kername ) \ \ void PASTEMAC(ch,opname) \ ( \ conj_t conjchi, \ ctype* chi \ ) \ { \ bli_init_once(); \ \ ctype chi_conj; \ \ PASTEMAC(ch,copycjs)( conjchi, *chi, chi_conj ); \ PASTEMAC(ch,kername)( chi_conj ); \ PASTEMAC(ch,copys)( chi_conj, *chi ); \ } INSERT_GENTFUNC_BASIC( invertsc, inverts ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, kername ) \ \ void PASTEMAC(ch,opname) \ ( \ conj_t conjchi, \ ctype* chi, \ ctype* psi \ ) \ { \ bli_init_once(); \ \ if ( PASTEMAC(ch,eq0)( *chi ) ) \ { \ /* Overwrite potential Infs and NaNs. */ \ PASTEMAC(ch,set0s)( *psi ); \ } \ else \ { \ ctype chi_conj; \ \ PASTEMAC(ch,copycjs)( conjchi, *chi, chi_conj ); \ PASTEMAC(ch,kername)( chi_conj, *psi ); \ } \ } INSERT_GENTFUNC_BASIC( mulsc, scals ) #undef GENTFUNCR #define GENTFUNCR( ctype, ctype_r, ch, chr, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ ctype* chi, \ ctype_r* absq \ ) \ { \ bli_init_once(); \ \ ctype_r chi_r; \ ctype_r chi_i; \ ctype_r absq_i; \ \ ( void )absq_i; \ \ PASTEMAC2(ch,chr,gets)( *chi, chi_r, chi_i ); \ \ /* absq = chi_r * chi_r + chi_i * chi_i; \ absq_r = 0.0; (thrown away) */ \ PASTEMAC(ch,absq2ris)( chi_r, chi_i, *absq, absq_i ); \ \ ( void )chi_i; \ } INSERT_GENTFUNCR_BASIC0( absqsc ) #undef GENTFUNCR #define GENTFUNCR( ctype, ctype_r, ch, chr, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ ctype* chi, \ ctype_r* norm \ ) \ { \ bli_init_once(); \ \ /* norm = sqrt( chi_r * chi_r + chi_i * chi_i ); */ \ PASTEMAC2(ch,chr,abval2s)( *chi, *norm ); \ } INSERT_GENTFUNCR_BASIC0( normfsc ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ ctype* chi, \ ctype* psi \ ) \ { \ bli_init_once(); \ \ /* NOTE: sqrtsc/sqrt2s differs from normfsc/abval2s in the complex domain. */ \ PASTEMAC(ch,sqrt2s)( *chi, *psi ); \ } INSERT_GENTFUNC_BASIC0( sqrtsc ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ ctype* chi, \ double* zeta_r, \ double* zeta_i \ ) \ { \ bli_init_once(); \ \ PASTEMAC2(ch,d,gets)( *chi, *zeta_r, *zeta_i ); \ } INSERT_GENTFUNC_BASIC0( getsc ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ double zeta_r, \ double zeta_i, \ ctype* chi \ ) \ { \ bli_init_once(); \ \ PASTEMAC2(d,ch,sets)( zeta_r, zeta_i, *chi ); \ } INSERT_GENTFUNC_BASIC0( setsc ) #undef GENTFUNCR #define GENTFUNCR( ctype, ctype_r, ch, chr, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ ctype* chi, \ ctype_r* zeta_r, \ ctype_r* zeta_i \ ) \ { \ bli_init_once(); \ \ PASTEMAC2(ch,chr,gets)( *chi, *zeta_r, *zeta_i ); \ } INSERT_GENTFUNCR_BASIC0( unzipsc ) #undef GENTFUNCR #define GENTFUNCR( ctype, ctype_r, ch, chr, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ ctype_r* zeta_r, \ ctype_r* zeta_i, \ ctype* chi \ ) \ { \ bli_init_once(); \ \ PASTEMAC2(chr,ch,sets)( *zeta_r, *zeta_i, *chi ); \ } INSERT_GENTFUNCR_BASIC0( zipsc ) // ----------------------------------------------------------------------------- void bli_igetsc ( dim_t* chi, double* zeta_r, double* zeta_i ) { bli_init_once(); PASTEMAC2(i,d,gets)( *chi, *zeta_r, *zeta_i ); } void bli_isetsc ( double zeta_r, double zeta_i, dim_t* chi ) { bli_init_once(); PASTEMAC2(d,i,sets)( zeta_r, zeta_i, *chi ); } blis-0.9.0/frame/0/bli_l0_tapi.h000066400000000000000000000076111422157504600162440ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype BLAS-like interfaces with typed operands. // #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC(ch,opname) \ ( \ conj_t conjchi, \ ctype* chi, \ ctype* psi \ ); INSERT_GENTPROT_BASIC0( addsc ) INSERT_GENTPROT_BASIC0( divsc ) INSERT_GENTPROT_BASIC0( mulsc ) INSERT_GENTPROT_BASIC0( subsc ) #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC(ch,opname) \ ( \ conj_t conjchi, \ ctype* chi \ ); INSERT_GENTPROT_BASIC0( invertsc ) #undef GENTPROTR #define GENTPROTR( ctype, ctype_r, ch, chr, opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC(ch,opname) \ ( \ ctype* chi, \ ctype_r* absq \ ); INSERT_GENTPROTR_BASIC0( absqsc ) INSERT_GENTPROTR_BASIC0( normfsc ) #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC(ch,opname) \ ( \ ctype* chi, \ ctype* psi \ ); INSERT_GENTPROT_BASIC0( sqrtsc ) #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC(ch,opname) \ ( \ ctype* chi, \ double* zeta_r, \ double* zeta_i \ ); INSERT_GENTPROT_BASIC0( getsc ) #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC(ch,opname) \ ( \ double zeta_r, \ double zeta_i, \ ctype* chi \ ); INSERT_GENTPROT_BASIC0( setsc ) #undef GENTPROTR #define GENTPROTR( ctype, ctype_r, ch, chr, opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC(ch,opname) \ ( \ ctype* chi, \ ctype_r* zeta_r, \ ctype_r* zeta_i \ ); INSERT_GENTPROTR_BASIC0( unzipsc ) #undef GENTPROTR #define GENTPROTR( ctype, ctype_r, ch, chr, opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC(ch,opname) \ ( \ ctype_r* zeta_r, \ ctype_r* zeta_i, \ ctype* chi \ ); INSERT_GENTPROTR_BASIC0( zipsc ) // ----------------------------------------------------------------------------- BLIS_EXPORT_BLIS void bli_igetsc ( dim_t* chi, double* zeta_r, double* zeta_i ); BLIS_EXPORT_BLIS void bli_isetsc ( double zeta_r, double zeta_i, dim_t* chi ); blis-0.9.0/frame/0/copysc/000077500000000000000000000000001422157504600152105ustar00rootroot00000000000000blis-0.9.0/frame/0/copysc/bli_copysc.c000066400000000000000000000072601422157504600175070ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // NOTE: This is one of the few functions in BLIS that is defined // with heterogeneous type support. This is done so that we have // an operation that can be used to typecast (copy-cast) a scalar // of one datatype to a scalar of another datatype. typedef void (*FUNCPTR_T) ( conj_t conjchi, void* chi, void* psi ); static FUNCPTR_T GENARRAY2_ALL(ftypes,copysc); // // Define object-based interfaces. // #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC0(opname) \ ( \ obj_t* chi, \ obj_t* psi \ ) \ { \ bli_init_once(); \ \ conj_t conjchi = bli_obj_conj_status( chi ); \ \ num_t dt_psi = bli_obj_dt( psi ); \ void* buf_psi = bli_obj_buffer_at_off( psi ); \ \ num_t dt_chi; \ void* buf_chi; \ \ FUNCPTR_T f; \ \ if ( bli_error_checking_is_enabled() ) \ PASTEMAC(opname,_check)( chi, psi ); \ \ /* If chi is a scalar constant, use dt_psi to extract the address of the corresponding constant value; otherwise, use the datatype encoded within the chi object and extract the buffer at the chi offset. */ \ bli_obj_scalar_set_dt_buffer( chi, dt_psi, &dt_chi, &buf_chi ); \ \ /* Index into the type combination array to extract the correct function pointer. */ \ f = ftypes[dt_chi][dt_psi]; \ \ /* Invoke the void pointer-based function. */ \ f( \ conjchi, \ buf_chi, \ buf_psi \ ); \ } GENFRONT( copysc ) // // Define BLAS-like interfaces with typed operands. // #undef GENTFUNC2 #define GENTFUNC2( ctype_x, ctype_y, chx, chy, varname ) \ \ void PASTEMAC2(chx,chy,varname) \ ( \ conj_t conjchi, \ void* chi, \ void* psi \ ) \ { \ bli_init_once(); \ \ ctype_x* chi_cast = chi; \ ctype_y* psi_cast = psi; \ \ if ( bli_is_conj( conjchi ) ) \ { \ PASTEMAC2(chx,chy,copyjs)( *chi_cast, *psi_cast ); \ } \ else \ { \ PASTEMAC2(chx,chy,copys)( *chi_cast, *psi_cast ); \ } \ } INSERT_GENTFUNC2_BASIC0( copysc ) INSERT_GENTFUNC2_MIX_D0( copysc ) INSERT_GENTFUNC2_MIX_P0( copysc ) blis-0.9.0/frame/0/copysc/bli_copysc.h000066400000000000000000000043541422157504600175150ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype object-based interfaces. // #undef GENFRONT #define GENFRONT( opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC0(opname) \ ( \ obj_t* chi, \ obj_t* psi \ ); GENFRONT( copysc ) // // Prototype BLAS-like interfaces with heterogeneous-typed operands. // #undef GENTPROT2 #define GENTPROT2( ctype_x, ctype_y, chx, chy, varname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC2(chx,chy,varname) \ ( \ conj_t conjchi, \ void* chi, \ void* psi \ ); INSERT_GENTPROT2_BASIC0( copysc ) INSERT_GENTPROT2_MIX_D0( copysc ) INSERT_GENTPROT2_MIX_P0( copysc ) blis-0.9.0/frame/1/000077500000000000000000000000001422157504600137115ustar00rootroot00000000000000blis-0.9.0/frame/1/bli_l1v.h000066400000000000000000000050541422157504600154160ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "bli_l1v_check.h" // Define kernel function types. //#include "bli_l1v_ft_ex.h" #include "bli_l1v_ft_ker.h" // Prototype object APIs (expert and non-expert). #include "bli_oapi_ex.h" #include "bli_l1v_oapi.h" #include "bli_xapi_undef.h" #include "bli_oapi_ba.h" #include "bli_l1v_oapi.h" #include "bli_xapi_undef.h" // Prototype typed APIs (expert and non-expert). #include "bli_tapi_ex.h" #include "bli_l1v_tapi.h" #include "bli_l1v_ft.h" #include "bli_xapi_undef.h" #include "bli_tapi_ba.h" #include "bli_l1v_tapi.h" #include "bli_l1v_ft.h" #include "bli_xapi_undef.h" // Generate function pointer arrays for tapi functions (expert only). #include "bli_l1v_fpa.h" // Pack-related // NOTE: packv and unpackv are temporarily disabled. //#include "bli_packv.h" //#include "bli_unpackv.h" // Other // NOTE: scalv control tree code is temporarily disabled. //#include "bli_scalv_cntl.h" //#include "bli_scalv_int.h" blis-0.9.0/frame/1/bli_l1v_check.c000066400000000000000000000267021422157504600165510ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // Define object-based check functions. // #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC(opname,_check) \ ( \ obj_t* x, \ obj_t* y \ ) \ { \ bli_l1v_xy_check( x, y ); \ } GENFRONT( addv ) GENFRONT( copyv ) GENFRONT( subv ) GENFRONT( swapv ) #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC(opname,_check) \ ( \ obj_t* x, \ obj_t* index \ ) \ { \ bli_l1v_xi_check( x, index ); \ } GENFRONT( amaxv ) #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC(opname,_check) \ ( \ obj_t* alpha, \ obj_t* x, \ obj_t* beta, \ obj_t* y \ ) \ { \ bli_l1v_axby_check( alpha, x, beta, y ); \ } GENFRONT( axpbyv ) #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC(opname,_check) \ ( \ obj_t* alpha, \ obj_t* x, \ obj_t* y \ ) \ { \ bli_l1v_axy_check( alpha, x, y ); \ } GENFRONT( axpyv ) GENFRONT( scal2v ) #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC(opname,_check) \ ( \ obj_t* x, \ obj_t* y, \ obj_t* rho \ ) \ { \ bli_l1v_dot_check( &BLIS_ONE, x, y, &BLIS_ONE, rho ); \ } GENFRONT( dotv ) #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC(opname,_check) \ ( \ obj_t* alpha, \ obj_t* x, \ obj_t* y, \ obj_t* beta, \ obj_t* rho \ ) \ { \ bli_l1v_dot_check( alpha, x, y, beta, rho ); \ } GENFRONT( dotxv ) #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC(opname,_check) \ ( \ obj_t* x \ ) \ { \ bli_l1v_x_check( x ); \ } GENFRONT( invertv ) #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC(opname,_check) \ ( \ obj_t* alpha, \ obj_t* x \ ) \ { \ bli_l1v_ax_check( alpha, x ); \ } GENFRONT( scalv ) GENFRONT( setv ) #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC(opname,_check) \ ( \ obj_t* x, \ obj_t* beta, \ obj_t* y \ ) \ { \ bli_l1v_xby_check( x, beta, y ); \ } GENFRONT( xpbyv ) // ----------------------------------------------------------------------------- void bli_l1v_xy_check ( obj_t* x, obj_t* y ) { err_t e_val; // Check object datatypes. e_val = bli_check_floating_object( x ); bli_check_error_code( e_val ); e_val = bli_check_floating_object( y ); bli_check_error_code( e_val ); // Check for consistent datatypes. e_val = bli_check_consistent_object_datatypes( x, y ); bli_check_error_code( e_val ); // Check object dimensions. e_val = bli_check_vector_object( x ); bli_check_error_code( e_val ); e_val = bli_check_vector_object( y ); bli_check_error_code( e_val ); e_val = bli_check_equal_vector_lengths( x, y ); bli_check_error_code( e_val ); // Check object buffers (for non-NULLness). e_val = bli_check_object_buffer( x ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( y ); bli_check_error_code( e_val ); } void bli_l1v_axy_check ( obj_t* alpha, obj_t* x, obj_t* y ) { err_t e_val; // Check object datatypes. e_val = bli_check_noninteger_object( alpha ); bli_check_error_code( e_val ); e_val = bli_check_floating_object( x ); bli_check_error_code( e_val ); e_val = bli_check_floating_object( y ); bli_check_error_code( e_val ); // Check for consistent datatypes. e_val = bli_check_consistent_object_datatypes( x, y ); bli_check_error_code( e_val ); // Check object dimensions. e_val = bli_check_scalar_object( alpha ); bli_check_error_code( e_val ); e_val = bli_check_vector_object( x ); bli_check_error_code( e_val ); e_val = bli_check_vector_object( y ); bli_check_error_code( e_val ); e_val = bli_check_equal_vector_lengths( x, y ); bli_check_error_code( e_val ); // Check object buffers (for non-NULLness). e_val = bli_check_object_buffer( alpha ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( x ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( y ); bli_check_error_code( e_val ); } void bli_l1v_xby_check ( obj_t* x, obj_t* beta, obj_t* y ) { err_t e_val; // Check object datatypes. e_val = bli_check_noninteger_object( beta ); bli_check_error_code( e_val ); e_val = bli_check_floating_object( x ); bli_check_error_code( e_val ); e_val = bli_check_floating_object( y ); bli_check_error_code( e_val ); // Check for consistent datatypes. e_val = bli_check_consistent_object_datatypes( x, y ); bli_check_error_code( e_val ); // Check object dimensions. e_val = bli_check_scalar_object( beta ); bli_check_error_code( e_val ); e_val = bli_check_vector_object( x ); bli_check_error_code( e_val ); e_val = bli_check_vector_object( y ); bli_check_error_code( e_val ); e_val = bli_check_equal_vector_lengths( x, y ); bli_check_error_code( e_val ); // Check object buffers (for non-NULLness). e_val = bli_check_object_buffer( beta ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( x ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( y ); bli_check_error_code( e_val ); } void bli_l1v_axby_check ( obj_t* alpha, obj_t* x, obj_t* beta, obj_t* y ) { err_t e_val; // Check object datatypes. e_val = bli_check_noninteger_object( alpha ); bli_check_error_code( e_val ); e_val = bli_check_noninteger_object( beta ); bli_check_error_code( e_val ); e_val = bli_check_floating_object( x ); bli_check_error_code( e_val ); e_val = bli_check_floating_object( y ); bli_check_error_code( e_val ); // Check for consistent datatypes. e_val = bli_check_consistent_object_datatypes( x, y ); bli_check_error_code( e_val ); // Check object dimensions. e_val = bli_check_scalar_object( alpha ); bli_check_error_code( e_val ); e_val = bli_check_scalar_object( beta ); bli_check_error_code( e_val ); e_val = bli_check_vector_object( x ); bli_check_error_code( e_val ); e_val = bli_check_vector_object( y ); bli_check_error_code( e_val ); e_val = bli_check_equal_vector_lengths( x, y ); bli_check_error_code( e_val ); // Check object buffers (for non-NULLness). e_val = bli_check_object_buffer( alpha ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( beta ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( x ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( y ); bli_check_error_code( e_val ); } void bli_l1v_dot_check ( obj_t* alpha, obj_t* x, obj_t* y, obj_t* beta, obj_t* rho ) { err_t e_val; // Check object datatypes. e_val = bli_check_noninteger_object( alpha ); bli_check_error_code( e_val ); e_val = bli_check_floating_object( x ); bli_check_error_code( e_val ); e_val = bli_check_floating_object( y ); bli_check_error_code( e_val ); e_val = bli_check_noninteger_object( beta ); bli_check_error_code( e_val ); e_val = bli_check_noninteger_object( rho ); bli_check_error_code( e_val ); e_val = bli_check_nonconstant_object( rho ); bli_check_error_code( e_val ); // Check for consistent datatypes. e_val = bli_check_consistent_object_datatypes( x, y ); bli_check_error_code( e_val ); // Check object dimensions. e_val = bli_check_scalar_object( alpha ); bli_check_error_code( e_val ); e_val = bli_check_vector_object( x ); bli_check_error_code( e_val ); e_val = bli_check_vector_object( y ); bli_check_error_code( e_val ); e_val = bli_check_scalar_object( beta ); bli_check_error_code( e_val ); e_val = bli_check_scalar_object( rho ); bli_check_error_code( e_val ); e_val = bli_check_equal_vector_lengths( x, y ); bli_check_error_code( e_val ); // Check object buffers (for non-NULLness). e_val = bli_check_object_buffer( alpha ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( x ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( y ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( beta ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( rho ); bli_check_error_code( e_val ); } void bli_l1v_x_check ( obj_t* x ) { err_t e_val; // Check object datatypes. e_val = bli_check_floating_object( x ); bli_check_error_code( e_val ); // Check object dimensions. e_val = bli_check_vector_object( x ); bli_check_error_code( e_val ); // Check object buffers (for non-NULLness). e_val = bli_check_object_buffer( x ); bli_check_error_code( e_val ); } void bli_l1v_ax_check ( obj_t* alpha, obj_t* x ) { err_t e_val; // Check object datatypes. e_val = bli_check_noninteger_object( alpha ); bli_check_error_code( e_val ); e_val = bli_check_floating_object( x ); bli_check_error_code( e_val ); // Check object dimensions. e_val = bli_check_scalar_object( alpha ); bli_check_error_code( e_val ); e_val = bli_check_vector_object( x ); bli_check_error_code( e_val ); // Check object buffers (for non-NULLness). e_val = bli_check_object_buffer( alpha ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( x ); bli_check_error_code( e_val ); } void bli_l1v_xi_check ( obj_t* x, obj_t* index ) { err_t e_val; // Check object datatypes. e_val = bli_check_floating_object( x ); bli_check_error_code( e_val ); e_val = bli_check_integer_object( index ); bli_check_error_code( e_val ); e_val = bli_check_nonconstant_object( index ); bli_check_error_code( e_val ); // Check object dimensions. e_val = bli_check_vector_object( x ); bli_check_error_code( e_val ); e_val = bli_check_scalar_object( index ); bli_check_error_code( e_val ); // Check object buffers (for non-NULLness). e_val = bli_check_object_buffer( x ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( index ); bli_check_error_code( e_val ); } blis-0.9.0/frame/1/bli_l1v_check.h000066400000000000000000000101671422157504600165540ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype object-based check functions. // #undef GENTPROT #define GENTPROT( opname ) \ \ void PASTEMAC(opname,_check) \ ( \ obj_t* x, \ obj_t* y \ ); GENTPROT( addv ) GENTPROT( copyv ) GENTPROT( subv ) GENTPROT( swapv ) #undef GENTPROT #define GENTPROT( opname ) \ \ void PASTEMAC(opname,_check) \ ( \ obj_t* x, \ obj_t* index \ ); GENTPROT( amaxv ) #undef GENTPROT #define GENTPROT( opname ) \ \ void PASTEMAC(opname,_check) \ ( \ obj_t* alpha, \ obj_t* x, \ obj_t* beta, \ obj_t* y \ ); GENTPROT( axpbyv ) #undef GENTPROT #define GENTPROT( opname ) \ \ void PASTEMAC(opname,_check) \ ( \ obj_t* alpha, \ obj_t* x, \ obj_t* y \ ); GENTPROT( axpyv ) GENTPROT( scal2v ) #undef GENTPROT #define GENTPROT( opname ) \ \ void PASTEMAC(opname,_check) \ ( \ obj_t* x, \ obj_t* y, \ obj_t* rho \ ); GENTPROT( dotv ) #undef GENTPROT #define GENTPROT( opname ) \ \ void PASTEMAC(opname,_check) \ ( \ obj_t* alpha, \ obj_t* x, \ obj_t* y, \ obj_t* beta, \ obj_t* rho \ ); GENTPROT( dotxv ) #undef GENTPROT #define GENTPROT( opname ) \ \ void PASTEMAC(opname,_check) \ ( \ obj_t* x \ ); GENTPROT( invertv ) #undef GENTPROT #define GENTPROT( opname ) \ \ void PASTEMAC(opname,_check) \ ( \ obj_t* alpha, \ obj_t* x \ ); GENTPROT( scalv ) GENTPROT( setv ) #undef GENTPROT #define GENTPROT( opname ) \ \ void PASTEMAC(opname,_check) \ ( \ obj_t* x, \ obj_t* beta, \ obj_t* y \ ); GENTPROT( xpbyv ) // ----------------------------------------------------------------------------- void bli_l1v_xy_check ( obj_t* x, obj_t* y ); void bli_l1v_axy_check ( obj_t* alpha, obj_t* x, obj_t* y ); void bli_l1v_xby_check ( obj_t* x, obj_t* beta, obj_t* y ); void bli_l1v_axby_check ( obj_t* alpha, obj_t* x, obj_t* beta, obj_t* y ); void bli_l1v_dot_check ( obj_t* alpha, obj_t* x, obj_t* y, obj_t* beta, obj_t* rho ); void bli_l1v_x_check ( obj_t* x ); void bli_l1v_ax_check ( obj_t* alpha, obj_t* x ); void bli_l1v_xi_check ( obj_t* x, obj_t* index ); blis-0.9.0/frame/1/bli_l1v_fpa.c000066400000000000000000000044121422157504600162340ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // Define function pointer query interfaces. // #undef GENFRONT #define GENFRONT( opname ) \ \ GENARRAY_FPA( PASTECH2(opname,BLIS_TAPI_EX_SUF,_vft), \ PASTECH(opname,BLIS_TAPI_EX_SUF) ); \ \ PASTECH2(opname,BLIS_TAPI_EX_SUF,_vft) \ PASTEMAC2(opname,BLIS_TAPI_EX_SUF,_qfp)( num_t dt ) \ { \ return PASTECH2(opname,BLIS_TAPI_EX_SUF,_fpa)[ dt ]; \ } GENFRONT( addv ) GENFRONT( copyv ) GENFRONT( subv ) GENFRONT( amaxv ) GENFRONT( axpbyv ) GENFRONT( axpyv ) GENFRONT( scal2v ) GENFRONT( dotv ) GENFRONT( dotxv ) GENFRONT( invertv ) GENFRONT( scalv ) GENFRONT( setv ) GENFRONT( swapv ) GENFRONT( xpbyv ) blis-0.9.0/frame/1/bli_l1v_fpa.h000066400000000000000000000040731422157504600162440ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype function pointer query interface. // #undef GENPROT #define GENPROT( opname ) \ \ PASTECH2(opname,BLIS_TAPI_EX_SUF,_vft) \ PASTEMAC2(opname,BLIS_TAPI_EX_SUF,_qfp)( num_t dt ); GENPROT( addv ) GENPROT( copyv ) GENPROT( subv ) GENPROT( amaxv ) GENPROT( axpbyv ) GENPROT( axpyv ) GENPROT( scal2v ) GENPROT( dotv ) GENPROT( dotxv ) GENPROT( invertv ) GENPROT( scalv ) GENPROT( setv ) GENPROT( swapv ) GENPROT( xpbyv ) blis-0.9.0/frame/1/bli_l1v_ft.h000066400000000000000000000116641422157504600161130ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // -- Level-1v function types -------------------------------------------------- // // addv, copyv, subv #undef GENTDEF #define GENTDEF( ctype, ch, opname, tsuf ) \ \ typedef void (*PASTECH3(ch,opname,EX_SUF,tsuf)) \ ( \ conj_t conjx, \ dim_t n, \ ctype* x, inc_t incx, \ ctype* y, inc_t incy \ BLIS_TAPI_EX_PARAMS \ ); INSERT_GENTDEF( addv ) INSERT_GENTDEF( copyv ) INSERT_GENTDEF( subv ) // amaxv #undef GENTDEF #define GENTDEF( ctype, ch, opname, tsuf ) \ \ typedef void (*PASTECH3(ch,opname,EX_SUF,tsuf)) \ ( \ dim_t n, \ ctype* x, inc_t incx, \ dim_t* index \ BLIS_TAPI_EX_PARAMS \ ); INSERT_GENTDEF( amaxv ) // axpbyv #undef GENTDEF #define GENTDEF( ctype, ch, opname, tsuf ) \ \ typedef void (*PASTECH3(ch,opname,EX_SUF,tsuf)) \ ( \ conj_t conjx, \ dim_t n, \ ctype* alpha, \ ctype* x, inc_t incx, \ ctype* beta, \ ctype* y, inc_t incy \ BLIS_TAPI_EX_PARAMS \ ); INSERT_GENTDEF( axpbyv ) // axpyv, scal2v #undef GENTDEF #define GENTDEF( ctype, ch, opname, tsuf ) \ \ typedef void (*PASTECH3(ch,opname,EX_SUF,tsuf)) \ ( \ conj_t conjx, \ dim_t n, \ ctype* alpha, \ ctype* x, inc_t incx, \ ctype* y, inc_t incy \ BLIS_TAPI_EX_PARAMS \ ); INSERT_GENTDEF( axpyv ) INSERT_GENTDEF( scal2v ) // dotv #undef GENTDEF #define GENTDEF( ctype, ch, opname, tsuf ) \ \ typedef void (*PASTECH3(ch,opname,EX_SUF,tsuf)) \ ( \ conj_t conjx, \ conj_t conjy, \ dim_t n, \ ctype* x, inc_t incx, \ ctype* y, inc_t incy, \ ctype* rho \ BLIS_TAPI_EX_PARAMS \ ); INSERT_GENTDEF( dotv ) // dotxv #undef GENTDEF #define GENTDEF( ctype, ch, opname, tsuf ) \ \ typedef void (*PASTECH3(ch,opname,EX_SUF,tsuf)) \ ( \ conj_t conjx, \ conj_t conjy, \ dim_t n, \ ctype* alpha, \ ctype* x, inc_t incx, \ ctype* y, inc_t incy, \ ctype* beta, \ ctype* rho \ BLIS_TAPI_EX_PARAMS \ ); INSERT_GENTDEF( dotxv ) // invertv #undef GENTDEF #define GENTDEF( ctype, ch, opname, tsuf ) \ \ typedef void (*PASTECH3(ch,opname,EX_SUF,tsuf)) \ ( \ dim_t n, \ ctype* x, inc_t incx \ BLIS_TAPI_EX_PARAMS \ ); INSERT_GENTDEF( invertv ) // scalv, setv #undef GENTDEF #define GENTDEF( ctype, ch, opname, tsuf ) \ \ typedef void (*PASTECH3(ch,opname,EX_SUF,tsuf)) \ ( \ conj_t conjalpha, \ dim_t n, \ ctype* alpha, \ ctype* x, inc_t incx \ BLIS_TAPI_EX_PARAMS \ ); INSERT_GENTDEF( scalv ) INSERT_GENTDEF( setv ) // swapv #undef GENTDEF #define GENTDEF( ctype, ch, opname, tsuf ) \ \ typedef void (*PASTECH3(ch,opname,EX_SUF,tsuf)) \ ( \ dim_t n, \ ctype* x, inc_t incx, \ ctype* y, inc_t incy \ BLIS_TAPI_EX_PARAMS \ ); INSERT_GENTDEF( swapv ) // xpybv #undef GENTDEF #define GENTDEF( ctype, ch, opname, tsuf ) \ \ typedef void (*PASTECH3(ch,opname,EX_SUF,tsuf)) \ ( \ conj_t conjx, \ dim_t n, \ ctype* x, inc_t incx, \ ctype* beta, \ ctype* y, inc_t incy \ BLIS_TAPI_EX_PARAMS \ ); INSERT_GENTDEF( xpbyv ) blis-0.9.0/frame/1/bli_l1v_ft_ker.h000066400000000000000000000125271422157504600167530ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_L1V_FT_KER_H #define BLIS_L1V_FT_KER_H // // -- Level-1v kernel function types ------------------------------------------- // // addv, copyv, subv #undef GENTDEF #define GENTDEF( ctype, ch, opname, tsuf ) \ \ typedef void (*PASTECH3(ch,opname,_ker,tsuf)) \ ( \ conj_t conjx, \ dim_t n, \ ctype* restrict x, inc_t incx, \ ctype* restrict y, inc_t incy, \ cntx_t* cntx \ ); INSERT_GENTDEF( addv ) INSERT_GENTDEF( copyv ) INSERT_GENTDEF( subv ) // amaxv #undef GENTDEF #define GENTDEF( ctype, ch, opname, tsuf ) \ \ typedef void (*PASTECH3(ch,opname,_ker,tsuf)) \ ( \ dim_t n, \ ctype* restrict x, inc_t incx, \ dim_t* restrict index, \ cntx_t* cntx \ ); INSERT_GENTDEF( amaxv ) // axpbyv #undef GENTDEF #define GENTDEF( ctype, ch, opname, tsuf ) \ \ typedef void (*PASTECH3(ch,opname,_ker,tsuf)) \ ( \ conj_t conjx, \ dim_t n, \ ctype* restrict alpha, \ ctype* restrict x, inc_t incx, \ ctype* restrict beta, \ ctype* restrict y, inc_t incy, \ cntx_t* cntx \ ); INSERT_GENTDEF( axpbyv ) // axpyv, scal2v #undef GENTDEF #define GENTDEF( ctype, ch, opname, tsuf ) \ \ typedef void (*PASTECH3(ch,opname,_ker,tsuf)) \ ( \ conj_t conjx, \ dim_t n, \ ctype* restrict alpha, \ ctype* restrict x, inc_t incx, \ ctype* restrict y, inc_t incy, \ cntx_t* cntx \ ); INSERT_GENTDEF( axpyv ) INSERT_GENTDEF( scal2v ) // dotv #undef GENTDEF #define GENTDEF( ctype, ch, opname, tsuf ) \ \ typedef void (*PASTECH3(ch,opname,_ker,tsuf)) \ ( \ conj_t conjx, \ conj_t conjy, \ dim_t n, \ ctype* restrict x, inc_t incx, \ ctype* restrict y, inc_t incy, \ ctype* restrict rho, \ cntx_t* cntx \ ); INSERT_GENTDEF( dotv ) // dotxv #undef GENTDEF #define GENTDEF( ctype, ch, opname, tsuf ) \ \ typedef void (*PASTECH3(ch,opname,_ker,tsuf)) \ ( \ conj_t conjx, \ conj_t conjy, \ dim_t n, \ ctype* restrict alpha, \ ctype* restrict x, inc_t incx, \ ctype* restrict y, inc_t incy, \ ctype* restrict beta, \ ctype* restrict rho, \ cntx_t* cntx \ ); INSERT_GENTDEF( dotxv ) // invertv #undef GENTDEF #define GENTDEF( ctype, ch, opname, tsuf ) \ \ typedef void (*PASTECH3(ch,opname,_ker,tsuf)) \ ( \ dim_t n, \ ctype* restrict x, inc_t incx, \ cntx_t* cntx \ ); INSERT_GENTDEF( invertv ) // scalv, setv #undef GENTDEF #define GENTDEF( ctype, ch, opname, tsuf ) \ \ typedef void (*PASTECH3(ch,opname,_ker,tsuf)) \ ( \ conj_t conjalpha, \ dim_t n, \ ctype* restrict alpha, \ ctype* restrict x, inc_t incx, \ cntx_t* cntx \ ); INSERT_GENTDEF( scalv ) INSERT_GENTDEF( setv ) // swapv #undef GENTDEF #define GENTDEF( ctype, ch, opname, tsuf ) \ \ typedef void (*PASTECH3(ch,opname,_ker,tsuf)) \ ( \ dim_t n, \ ctype* restrict x, inc_t incx, \ ctype* restrict y, inc_t incy, \ cntx_t* cntx \ ); INSERT_GENTDEF( swapv ) // xpybv #undef GENTDEF #define GENTDEF( ctype, ch, opname, tsuf ) \ \ typedef void (*PASTECH3(ch,opname,_ker,tsuf)) \ ( \ conj_t conjx, \ dim_t n, \ ctype* restrict x, inc_t incx, \ ctype* restrict beta, \ ctype* restrict y, inc_t incy, \ cntx_t* cntx \ ); INSERT_GENTDEF( xpbyv ) #endif blis-0.9.0/frame/1/bli_l1v_ker.h000066400000000000000000000063141422157504600162570ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Define template prototypes for level-1v kernels. // // Note: Instead of defining function prototype macro templates and then // instantiating those macros to define the individual function prototypes, // we simply alias the official operations' prototypes as defined in // bli_l1v_ker_prot.h. #undef GENTPROT #define GENTPROT ADDV_KER_PROT INSERT_GENTPROT_BASIC0( addv_ker_name ) #undef GENTPROT #define GENTPROT AMAXV_KER_PROT INSERT_GENTPROT_BASIC0( amaxv_ker_name ) #undef GENTPROT #define GENTPROT AXPBYV_KER_PROT INSERT_GENTPROT_BASIC0( axpbyv_ker_name ) #undef GENTPROT #define GENTPROT AXPYV_KER_PROT INSERT_GENTPROT_BASIC0( axpyv_ker_name ) #undef GENTPROT #define GENTPROT COPYV_KER_PROT INSERT_GENTPROT_BASIC0( copyv_ker_name ) #undef GENTPROT #define GENTPROT DOTV_KER_PROT INSERT_GENTPROT_BASIC0( dotv_ker_name ) #undef GENTPROT #define GENTPROT DOTXV_KER_PROT INSERT_GENTPROT_BASIC0( dotxv_ker_name ) #undef GENTPROT #define GENTPROT INVERTV_KER_PROT INSERT_GENTPROT_BASIC0( invertv_ker_name ) #undef GENTPROT #define GENTPROT SCALV_KER_PROT INSERT_GENTPROT_BASIC0( scalv_ker_name ) #undef GENTPROT #define GENTPROT SCAL2V_KER_PROT INSERT_GENTPROT_BASIC0( scal2v_ker_name ) #undef GENTPROT #define GENTPROT SETV_KER_PROT INSERT_GENTPROT_BASIC0( setv_ker_name ) #undef GENTPROT #define GENTPROT SUBV_KER_PROT INSERT_GENTPROT_BASIC0( subv_ker_name ) #undef GENTPROT #define GENTPROT SWAPV_KER_PROT INSERT_GENTPROT_BASIC0( swapv_ker_name ) #undef GENTPROT #define GENTPROT XPBYV_KER_PROT INSERT_GENTPROT_BASIC0( xpbyv_ker_name ) blis-0.9.0/frame/1/bli_l1v_ker_prot.h000066400000000000000000000131731422157504600173240ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Define template prototypes for level-1v kernels. // #define ADDV_KER_PROT( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ conj_t conjx, \ dim_t n, \ ctype* restrict x, inc_t incx, \ ctype* restrict y, inc_t incy, \ cntx_t* restrict cntx \ ); #define AMAXV_KER_PROT( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ dim_t n, \ ctype* restrict x, inc_t incx, \ dim_t* restrict index, \ cntx_t* restrict cntx \ ); \ #define AXPBYV_KER_PROT( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ conj_t conjx, \ dim_t n, \ ctype* restrict alpha, \ ctype* restrict x, inc_t incx, \ ctype* restrict beta, \ ctype* restrict y, inc_t incy, \ cntx_t* restrict cntx \ ); \ #define AXPYV_KER_PROT( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ conj_t conjx, \ dim_t n, \ ctype* restrict alpha, \ ctype* restrict x, inc_t incx, \ ctype* restrict y, inc_t incy, \ cntx_t* restrict cntx \ ); \ #define COPYV_KER_PROT( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ conj_t conjx, \ dim_t n, \ ctype* restrict x, inc_t incx, \ ctype* restrict y, inc_t incy, \ cntx_t* restrict cntx \ ); #define DOTV_KER_PROT( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ conj_t conjx, \ conj_t conjy, \ dim_t n, \ ctype* restrict x, inc_t incx, \ ctype* restrict y, inc_t incy, \ ctype* restrict rho, \ cntx_t* restrict cntx \ ); \ #define DOTXV_KER_PROT( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ conj_t conjx, \ conj_t conjy, \ dim_t n, \ ctype* restrict alpha, \ ctype* restrict x, inc_t incx, \ ctype* restrict y, inc_t incy, \ ctype* restrict beta, \ ctype* restrict rho, \ cntx_t* restrict cntx \ ); \ #define INVERTV_KER_PROT( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ dim_t n, \ ctype* restrict x, inc_t incx, \ cntx_t* restrict cntx \ ); \ #define SCALV_KER_PROT( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ conj_t conjalpha, \ dim_t n, \ ctype* restrict alpha, \ ctype* restrict x, inc_t incx, \ cntx_t* restrict cntx \ ); \ #define SCAL2V_KER_PROT( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ conj_t conjx, \ dim_t n, \ ctype* restrict alpha, \ ctype* restrict x, inc_t incx, \ ctype* restrict y, inc_t incy, \ cntx_t* restrict cntx \ ); \ #define SETV_KER_PROT( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ conj_t conjalpha, \ dim_t n, \ ctype* restrict alpha, \ ctype* restrict x, inc_t incx, \ cntx_t* restrict cntx \ ); \ #define SUBV_KER_PROT( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ conj_t conjx, \ dim_t n, \ ctype* restrict x, inc_t incx, \ ctype* restrict y, inc_t incy, \ cntx_t* restrict cntx \ ); #define SWAPV_KER_PROT( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ dim_t n, \ ctype* restrict x, inc_t incx, \ ctype* restrict y, inc_t incy, \ cntx_t* restrict cntx \ ); \ #define XPBYV_KER_PROT( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ conj_t conjx, \ dim_t n, \ ctype* restrict x, inc_t incx, \ ctype* restrict beta, \ ctype* restrict y, inc_t incy, \ cntx_t* restrict cntx \ ); \ blis-0.9.0/frame/1/bli_l1v_oapi.c000066400000000000000000000340111422157504600164140ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // Guard the function definitions so that they are only compiled when // #included from files that define the object API macros. #ifdef BLIS_ENABLE_OAPI // // Define object-based interfaces. // #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC(opname,EX_SUF) \ ( \ obj_t* x, \ obj_t* y \ BLIS_OAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_OAPI_EX_DECLS \ \ num_t dt = bli_obj_dt( x ); \ \ conj_t conjx = bli_obj_conj_status( x ); \ dim_t n = bli_obj_vector_dim( x ); \ void* buf_x = bli_obj_buffer_at_off( x ); \ inc_t inc_x = bli_obj_vector_inc( x ); \ void* buf_y = bli_obj_buffer_at_off( y ); \ inc_t inc_y = bli_obj_vector_inc( y ); \ \ if ( bli_error_checking_is_enabled() ) \ PASTEMAC(opname,_check)( x, y ); \ \ /* Query a type-specific function pointer, except one that uses void* for function arguments instead of typed pointers. */ \ PASTECH2(opname,BLIS_TAPI_EX_SUF,_vft) f = \ PASTEMAC2(opname,BLIS_TAPI_EX_SUF,_qfp)( dt ); \ \ f \ ( \ conjx, \ n, \ buf_x, inc_x, \ buf_y, inc_y, \ cntx, \ rntm \ ); \ } GENFRONT( addv ) GENFRONT( copyv ) GENFRONT( subv ) #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC(opname,EX_SUF) \ ( \ obj_t* x, \ obj_t* index \ BLIS_OAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_OAPI_EX_DECLS \ \ num_t dt = bli_obj_dt( x ); \ \ dim_t n = bli_obj_vector_dim( x ); \ void* buf_x = bli_obj_buffer_at_off( x ); \ inc_t incx = bli_obj_vector_inc( x ); \ \ void* buf_index = bli_obj_buffer_at_off( index ); \ \ if ( bli_error_checking_is_enabled() ) \ PASTEMAC(opname,_check)( x, index ); \ \ /* Query a type-specific function pointer, except one that uses void* for function arguments instead of typed pointers. */ \ PASTECH2(opname,BLIS_TAPI_EX_SUF,_vft) f = \ PASTEMAC2(opname,BLIS_TAPI_EX_SUF,_qfp)( dt ); \ \ f \ ( \ n, \ buf_x, incx, \ buf_index, \ cntx, \ rntm \ ); \ } GENFRONT( amaxv ) #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC(opname,EX_SUF) \ ( \ obj_t* alpha, \ obj_t* x, \ obj_t* beta, \ obj_t* y \ BLIS_OAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_OAPI_EX_DECLS \ \ num_t dt = bli_obj_dt( x ); \ \ conj_t conjx = bli_obj_conj_status( x ); \ dim_t n = bli_obj_vector_dim( x ); \ void* buf_x = bli_obj_buffer_at_off( x ); \ inc_t inc_x = bli_obj_vector_inc( x ); \ void* buf_y = bli_obj_buffer_at_off( y ); \ inc_t inc_y = bli_obj_vector_inc( y ); \ \ void* buf_alpha; \ void* buf_beta; \ \ obj_t alpha_local; \ obj_t beta_local; \ \ if ( bli_error_checking_is_enabled() ) \ PASTEMAC(opname,_check)( alpha, x, beta, y ); \ \ /* Create local copy-casts of scalars (and apply internal conjugation as needed). */ \ bli_obj_scalar_init_detached_copy_of( dt, BLIS_NO_CONJUGATE, \ alpha, &alpha_local ); \ bli_obj_scalar_init_detached_copy_of( dt, BLIS_NO_CONJUGATE, \ beta, &beta_local ); \ buf_alpha = bli_obj_buffer_for_1x1( dt, &alpha_local ); \ buf_beta = bli_obj_buffer_for_1x1( dt, &beta_local ); \ \ /* Query a type-specific function pointer, except one that uses void* for function arguments instead of typed pointers. */ \ PASTECH2(opname,BLIS_TAPI_EX_SUF,_vft) f = \ PASTEMAC2(opname,BLIS_TAPI_EX_SUF,_qfp)( dt ); \ \ f \ ( \ conjx, \ n, \ buf_alpha, \ buf_x, inc_x, \ buf_beta, \ buf_y, inc_y, \ cntx, \ rntm \ ); \ } GENFRONT( axpbyv ) #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC(opname,EX_SUF) \ ( \ obj_t* alpha, \ obj_t* x, \ obj_t* y \ BLIS_OAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_OAPI_EX_DECLS \ \ num_t dt = bli_obj_dt( x ); \ \ conj_t conjx = bli_obj_conj_status( x ); \ dim_t n = bli_obj_vector_dim( x ); \ void* buf_x = bli_obj_buffer_at_off( x ); \ inc_t inc_x = bli_obj_vector_inc( x ); \ void* buf_y = bli_obj_buffer_at_off( y ); \ inc_t inc_y = bli_obj_vector_inc( y ); \ \ void* buf_alpha; \ \ obj_t alpha_local; \ \ if ( bli_error_checking_is_enabled() ) \ PASTEMAC(opname,_check)( alpha, x, y ); \ \ /* Create local copy-casts of scalars (and apply internal conjugation as needed). */ \ bli_obj_scalar_init_detached_copy_of( dt, BLIS_NO_CONJUGATE, \ alpha, &alpha_local ); \ buf_alpha = bli_obj_buffer_for_1x1( dt, &alpha_local ); \ \ /* Query a type-specific function pointer, except one that uses void* for function arguments instead of typed pointers. */ \ PASTECH2(opname,BLIS_TAPI_EX_SUF,_vft) f = \ PASTEMAC2(opname,BLIS_TAPI_EX_SUF,_qfp)( dt ); \ \ f \ ( \ conjx, \ n, \ buf_alpha, \ buf_x, inc_x, \ buf_y, inc_y, \ cntx, \ rntm \ ); \ } GENFRONT( axpyv ) GENFRONT( scal2v ) #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC(opname,EX_SUF) \ ( \ obj_t* x, \ obj_t* y, \ obj_t* rho \ BLIS_OAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_OAPI_EX_DECLS \ \ num_t dt = bli_obj_dt( x ); \ \ conj_t conjx = bli_obj_conj_status( x ); \ conj_t conjy = bli_obj_conj_status( y ); \ dim_t n = bli_obj_vector_dim( x ); \ void* buf_x = bli_obj_buffer_at_off( x ); \ inc_t inc_x = bli_obj_vector_inc( x ); \ void* buf_y = bli_obj_buffer_at_off( y ); \ inc_t inc_y = bli_obj_vector_inc( y ); \ void* buf_rho = bli_obj_buffer_at_off( rho ); \ \ if ( bli_error_checking_is_enabled() ) \ PASTEMAC(opname,_check)( x, y, rho ); \ \ /* Query a type-specific function pointer, except one that uses void* for function arguments instead of typed pointers. */ \ PASTECH2(opname,BLIS_TAPI_EX_SUF,_vft) f = \ PASTEMAC2(opname,BLIS_TAPI_EX_SUF,_qfp)( dt ); \ \ f \ ( \ conjx, \ conjy, \ n, \ buf_x, inc_x, \ buf_y, inc_y, \ buf_rho, \ cntx, \ rntm \ ); \ } GENFRONT( dotv ) #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC(opname,EX_SUF) \ ( \ obj_t* alpha, \ obj_t* x, \ obj_t* y, \ obj_t* beta, \ obj_t* rho \ BLIS_OAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_OAPI_EX_DECLS \ \ num_t dt = bli_obj_dt( x ); \ \ conj_t conjx = bli_obj_conj_status( x ); \ conj_t conjy = bli_obj_conj_status( y ); \ dim_t n = bli_obj_vector_dim( x ); \ void* buf_x = bli_obj_buffer_at_off( x ); \ inc_t inc_x = bli_obj_vector_inc( x ); \ void* buf_y = bli_obj_buffer_at_off( y ); \ inc_t inc_y = bli_obj_vector_inc( y ); \ void* buf_rho = bli_obj_buffer_at_off( rho ); \ \ void* buf_alpha; \ void* buf_beta; \ \ obj_t alpha_local; \ obj_t beta_local; \ \ if ( bli_error_checking_is_enabled() ) \ PASTEMAC(opname,_check)( alpha, x, y, beta, rho ); \ \ /* Create local copy-casts of scalars (and apply internal conjugation as needed). */ \ bli_obj_scalar_init_detached_copy_of( dt, BLIS_NO_CONJUGATE, \ alpha, &alpha_local ); \ bli_obj_scalar_init_detached_copy_of( dt, BLIS_NO_CONJUGATE, \ beta, &beta_local ); \ buf_alpha = bli_obj_buffer_for_1x1( dt, &alpha_local ); \ buf_beta = bli_obj_buffer_for_1x1( dt, &beta_local ); \ \ /* Query a type-specific function pointer, except one that uses void* for function arguments instead of typed pointers. */ \ PASTECH2(opname,BLIS_TAPI_EX_SUF,_vft) f = \ PASTEMAC2(opname,BLIS_TAPI_EX_SUF,_qfp)( dt ); \ \ f \ ( \ conjx, \ conjy, \ n, \ buf_alpha, \ buf_x, inc_x, \ buf_y, inc_y, \ buf_beta, \ buf_rho, \ cntx, \ rntm \ ); \ } GENFRONT( dotxv ) #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC(opname,EX_SUF) \ ( \ obj_t* x \ BLIS_OAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_OAPI_EX_DECLS \ \ num_t dt = bli_obj_dt( x ); \ \ dim_t n = bli_obj_vector_dim( x ); \ void* buf_x = bli_obj_buffer_at_off( x ); \ inc_t inc_x = bli_obj_vector_inc( x ); \ \ if ( bli_error_checking_is_enabled() ) \ PASTEMAC(opname,_check)( x ); \ \ /* Query a type-specific function pointer, except one that uses void* for function arguments instead of typed pointers. */ \ PASTECH2(opname,BLIS_TAPI_EX_SUF,_vft) f = \ PASTEMAC2(opname,BLIS_TAPI_EX_SUF,_qfp)( dt ); \ \ f \ ( \ n, \ buf_x, inc_x, \ cntx, \ rntm \ ); \ } GENFRONT( invertv ) #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC(opname,EX_SUF) \ ( \ obj_t* alpha, \ obj_t* x \ BLIS_OAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_OAPI_EX_DECLS \ \ num_t dt = bli_obj_dt( x ); \ \ /* conj_t conjalpha = bli_obj_conj_status( alpha ); */ \ dim_t n = bli_obj_vector_dim( x ); \ void* buf_x = bli_obj_buffer_at_off( x ); \ inc_t inc_x = bli_obj_vector_inc( x ); \ \ void* buf_alpha; \ \ obj_t alpha_local; \ \ if ( bli_error_checking_is_enabled() ) \ PASTEMAC(opname,_check)( alpha, x ); \ \ /* Create local copy-casts of scalars (and apply internal conjugation as needed). */ \ bli_obj_scalar_init_detached_copy_of( dt, BLIS_NO_CONJUGATE, \ alpha, &alpha_local ); \ buf_alpha = bli_obj_buffer_for_1x1( dt, &alpha_local ); \ \ /* Query a type-specific function pointer, except one that uses void* for function arguments instead of typed pointers. */ \ PASTECH2(opname,BLIS_TAPI_EX_SUF,_vft) f = \ PASTEMAC2(opname,BLIS_TAPI_EX_SUF,_qfp)( dt ); \ \ f \ ( \ BLIS_NO_CONJUGATE, /* internal conjugation applied during copy-cast. */ \ n, \ buf_alpha, \ buf_x, inc_x, \ cntx, \ rntm \ ); \ } GENFRONT( scalv ) GENFRONT( setv ) #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC(opname,EX_SUF) \ ( \ obj_t* x, \ obj_t* y \ BLIS_OAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_OAPI_EX_DECLS \ \ num_t dt = bli_obj_dt( x ); \ \ dim_t n = bli_obj_vector_dim( x ); \ void* buf_x = bli_obj_buffer_at_off( x ); \ inc_t inc_x = bli_obj_vector_inc( x ); \ void* buf_y = bli_obj_buffer_at_off( y ); \ inc_t inc_y = bli_obj_vector_inc( y ); \ \ if ( bli_error_checking_is_enabled() ) \ PASTEMAC(opname,_check)( x, y ); \ \ /* Query a type-specific function pointer, except one that uses void* for function arguments instead of typed pointers. */ \ PASTECH2(opname,BLIS_TAPI_EX_SUF,_vft) f = \ PASTEMAC2(opname,BLIS_TAPI_EX_SUF,_qfp)( dt ); \ \ f \ ( \ n, \ buf_x, inc_x, \ buf_y, inc_y, \ cntx, \ rntm \ ); \ } GENFRONT( swapv ) #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC(opname,EX_SUF) \ ( \ obj_t* x, \ obj_t* beta, \ obj_t* y \ BLIS_OAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_OAPI_EX_DECLS \ \ num_t dt = bli_obj_dt( x ); \ \ conj_t conjx = bli_obj_conj_status( x ); \ dim_t n = bli_obj_vector_dim( x ); \ void* buf_x = bli_obj_buffer_at_off( x ); \ inc_t inc_x = bli_obj_vector_inc( x ); \ void* buf_y = bli_obj_buffer_at_off( y ); \ inc_t inc_y = bli_obj_vector_inc( y ); \ \ void* buf_beta; \ \ obj_t beta_local; \ \ if ( bli_error_checking_is_enabled() ) \ PASTEMAC(opname,_check)( x, beta, y ); \ \ /* Create local copy-casts of scalars (and apply internal conjugation as needed). */ \ bli_obj_scalar_init_detached_copy_of( dt, BLIS_NO_CONJUGATE, \ beta, &beta_local ); \ buf_beta = bli_obj_buffer_for_1x1( dt, &beta_local ); \ \ /* Query a type-specific function pointer, except one that uses void* for function arguments instead of typed pointers. */ \ PASTECH2(opname,BLIS_TAPI_EX_SUF,_vft) f = \ PASTEMAC2(opname,BLIS_TAPI_EX_SUF,_qfp)( dt ); \ \ f \ ( \ conjx, \ n, \ buf_x, inc_x, \ buf_beta, \ buf_y, inc_y, \ cntx, \ rntm \ ); \ } GENFRONT( xpbyv ) #endif blis-0.9.0/frame/1/bli_l1v_oapi.h000066400000000000000000000076521422157504600164340ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype object-based interfaces. // #undef GENTPROT #define GENTPROT( opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC(opname,EX_SUF) \ ( \ obj_t* x, \ obj_t* y \ BLIS_OAPI_EX_PARAMS \ ); GENTPROT( addv ) GENTPROT( copyv ) GENTPROT( subv ) #undef GENTPROT #define GENTPROT( opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC(opname,EX_SUF) \ ( \ obj_t* x, \ obj_t* index \ BLIS_OAPI_EX_PARAMS \ ); GENTPROT( amaxv ) #undef GENTPROT #define GENTPROT( opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC(opname,EX_SUF) \ ( \ obj_t* alpha, \ obj_t* x, \ obj_t* beta, \ obj_t* y \ BLIS_OAPI_EX_PARAMS \ ); GENTPROT( axpbyv ) #undef GENTPROT #define GENTPROT( opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC(opname,EX_SUF) \ ( \ obj_t* alpha, \ obj_t* x, \ obj_t* y \ BLIS_OAPI_EX_PARAMS \ ); GENTPROT( axpyv ) GENTPROT( scal2v ) #undef GENTPROT #define GENTPROT( opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC(opname,EX_SUF) \ ( \ obj_t* x, \ obj_t* y, \ obj_t* rho \ BLIS_OAPI_EX_PARAMS \ ); GENTPROT( dotv ) #undef GENTPROT #define GENTPROT( opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC(opname,EX_SUF) \ ( \ obj_t* alpha, \ obj_t* x, \ obj_t* y, \ obj_t* beta, \ obj_t* rho \ BLIS_OAPI_EX_PARAMS \ ); GENTPROT( dotxv ) #undef GENTPROT #define GENTPROT( opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC(opname,EX_SUF) \ ( \ obj_t* x \ BLIS_OAPI_EX_PARAMS \ ); GENTPROT( invertv ) #undef GENTPROT #define GENTPROT( opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC(opname,EX_SUF) \ ( \ obj_t* alpha, \ obj_t* x \ BLIS_OAPI_EX_PARAMS \ ); GENTPROT( scalv ) GENTPROT( setv ) #undef GENTPROT #define GENTPROT( opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC(opname,EX_SUF) \ ( \ obj_t* x, \ obj_t* y \ BLIS_OAPI_EX_PARAMS \ ); GENTPROT( swapv ) #undef GENTPROT #define GENTPROT( opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC(opname,EX_SUF) \ ( \ obj_t* x, \ obj_t* beta, \ obj_t* y \ BLIS_OAPI_EX_PARAMS \ ); GENTPROT( xpbyv ) blis-0.9.0/frame/1/bli_l1v_oapi_ba.c000066400000000000000000000036701422157504600170650ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // Include cpp macros that instantiate the API definition templates as // omitting expert parameters. #include "bli_oapi_ba.h" // Define the macro protecting the object API definitions. #define BLIS_ENABLE_OAPI // Include the object API definitions here. #include "bli_l1v_oapi.c" blis-0.9.0/frame/1/bli_l1v_oapi_ex.c000066400000000000000000000036661422157504600171240ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // Include cpp macros that instantiate the API definition templates as // having expert parameters. #include "bli_oapi_ex.h" // Define the macro protecting the object API definitions. #define BLIS_ENABLE_OAPI // Include the object API definitions here. #include "bli_l1v_oapi.c" blis-0.9.0/frame/1/bli_l1v_tapi.c000066400000000000000000000214661422157504600164330ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // Guard the function definitions so that they are only compiled when // #included from files that define the typed API macros. #ifdef BLIS_ENABLE_TAPI // // Define BLAS-like interfaces with typed operands. // #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, kerid ) \ \ void PASTEMAC2(ch,opname,EX_SUF) \ ( \ conj_t conjx, \ dim_t n, \ ctype* x, inc_t incx, \ ctype* y, inc_t incy \ BLIS_TAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_TAPI_EX_DECLS \ \ const num_t dt = PASTEMAC(ch,type); \ \ /* Obtain a valid context from the gks if necessary. */ \ if ( cntx == NULL ) cntx = bli_gks_query_cntx(); \ \ PASTECH2(ch,opname,_ker_ft) f = bli_cntx_get_l1v_ker_dt( dt, kerid, cntx ); \ \ f \ ( \ conjx, \ n, \ x, incx, \ y, incy, \ cntx \ ); \ } INSERT_GENTFUNC_BASIC( addv, BLIS_ADDV_KER ) INSERT_GENTFUNC_BASIC( copyv, BLIS_COPYV_KER ) INSERT_GENTFUNC_BASIC( subv, BLIS_SUBV_KER ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, kerid ) \ \ void PASTEMAC2(ch,opname,EX_SUF) \ ( \ dim_t n, \ ctype* x, inc_t incx, \ dim_t* index \ BLIS_TAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_TAPI_EX_DECLS \ \ const num_t dt = PASTEMAC(ch,type); \ \ /* Obtain a valid context from the gks if necessary. */ \ if ( cntx == NULL ) cntx = bli_gks_query_cntx(); \ \ PASTECH2(ch,opname,_ker_ft) f = bli_cntx_get_l1v_ker_dt( dt, kerid, cntx ); \ \ f \ ( \ n, \ x, incx, \ index, \ cntx \ ); \ } INSERT_GENTFUNC_BASIC( amaxv, BLIS_AMAXV_KER ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, kerid ) \ \ void PASTEMAC2(ch,opname,EX_SUF) \ ( \ conj_t conjx, \ dim_t n, \ ctype* alpha, \ ctype* x, inc_t incx, \ ctype* beta, \ ctype* y, inc_t incy \ BLIS_TAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_TAPI_EX_DECLS \ \ const num_t dt = PASTEMAC(ch,type); \ \ /* Obtain a valid context from the gks if necessary. */ \ if ( cntx == NULL ) cntx = bli_gks_query_cntx(); \ \ PASTECH2(ch,opname,_ker_ft) f = bli_cntx_get_l1v_ker_dt( dt, kerid, cntx ); \ \ f \ ( \ conjx, \ n, \ alpha, \ x, incx, \ beta, \ y, incy, \ cntx \ ); \ } INSERT_GENTFUNC_BASIC( axpbyv, BLIS_AXPBYV_KER ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, kerid ) \ \ void PASTEMAC2(ch,opname,EX_SUF) \ ( \ conj_t conjx, \ dim_t n, \ ctype* alpha, \ ctype* x, inc_t incx, \ ctype* y, inc_t incy \ BLIS_TAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_TAPI_EX_DECLS \ \ const num_t dt = PASTEMAC(ch,type); \ \ /* Obtain a valid context from the gks if necessary. */ \ if ( cntx == NULL ) \ cntx = bli_gks_query_cntx(); \ \ PASTECH2(ch,opname,_ker_ft) f = bli_cntx_get_l1v_ker_dt( dt, kerid, cntx ); \ \ f \ ( \ conjx, \ n, \ alpha, \ x, incx, \ y, incy, \ cntx \ ); \ } INSERT_GENTFUNC_BASIC( axpyv, BLIS_AXPYV_KER ) INSERT_GENTFUNC_BASIC( scal2v, BLIS_SCAL2V_KER ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, kerid ) \ \ void PASTEMAC2(ch,opname,EX_SUF) \ ( \ conj_t conjx, \ conj_t conjy, \ dim_t n, \ ctype* x, inc_t incx, \ ctype* y, inc_t incy, \ ctype* rho \ BLIS_TAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_TAPI_EX_DECLS \ \ const num_t dt = PASTEMAC(ch,type); \ \ /* Obtain a valid context from the gks if necessary. */ \ if ( cntx == NULL ) cntx = bli_gks_query_cntx(); \ \ PASTECH2(ch,opname,_ker_ft) f = bli_cntx_get_l1v_ker_dt( dt, kerid, cntx ); \ \ f \ ( \ conjx, \ conjy, \ n, \ x, incx, \ y, incy, \ rho, \ cntx \ ); \ } INSERT_GENTFUNC_BASIC( dotv, BLIS_DOTV_KER ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, kerid ) \ \ void PASTEMAC2(ch,opname,EX_SUF) \ ( \ conj_t conjx, \ conj_t conjy, \ dim_t n, \ ctype* alpha, \ ctype* x, inc_t incx, \ ctype* y, inc_t incy, \ ctype* beta, \ ctype* rho \ BLIS_TAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_TAPI_EX_DECLS \ \ const num_t dt = PASTEMAC(ch,type); \ \ /* Obtain a valid context from the gks if necessary. */ \ if ( cntx == NULL ) cntx = bli_gks_query_cntx(); \ \ PASTECH2(ch,opname,_ker_ft) f = bli_cntx_get_l1v_ker_dt( dt, kerid, cntx ); \ \ f \ ( \ conjx, \ conjy, \ n, \ alpha, \ x, incx, \ y, incy, \ beta, \ rho, \ cntx \ ); \ } INSERT_GENTFUNC_BASIC( dotxv, BLIS_DOTXV_KER ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, kerid ) \ \ void PASTEMAC2(ch,opname,EX_SUF) \ ( \ dim_t n, \ ctype* x, inc_t incx \ BLIS_TAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_TAPI_EX_DECLS \ \ const num_t dt = PASTEMAC(ch,type); \ \ /* Obtain a valid context from the gks if necessary. */ \ if ( cntx == NULL ) cntx = bli_gks_query_cntx(); \ \ PASTECH2(ch,opname,_ker_ft) f = bli_cntx_get_l1v_ker_dt( dt, kerid, cntx ); \ \ f \ ( \ n, \ x, incx, \ cntx \ ); \ } INSERT_GENTFUNC_BASIC( invertv, BLIS_INVERTV_KER ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, kerid ) \ \ void PASTEMAC2(ch,opname,EX_SUF) \ ( \ conj_t conjalpha, \ dim_t n, \ ctype* alpha, \ ctype* x, inc_t incx \ BLIS_TAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_TAPI_EX_DECLS \ \ const num_t dt = PASTEMAC(ch,type); \ \ /* Obtain a valid context from the gks if necessary. */ \ if ( cntx == NULL ) cntx = bli_gks_query_cntx(); \ \ PASTECH2(ch,opname,_ker_ft) f = bli_cntx_get_l1v_ker_dt( dt, kerid, cntx ); \ \ f \ ( \ conjalpha, \ n, \ alpha, \ x, incx, \ cntx \ ); \ } INSERT_GENTFUNC_BASIC( scalv, BLIS_SCALV_KER ) INSERT_GENTFUNC_BASIC( setv, BLIS_SETV_KER ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, kerid ) \ \ void PASTEMAC2(ch,opname,EX_SUF) \ ( \ dim_t n, \ ctype* x, inc_t incx, \ ctype* y, inc_t incy \ BLIS_TAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_TAPI_EX_DECLS \ \ const num_t dt = PASTEMAC(ch,type); \ \ /* Obtain a valid context from the gks if necessary. */ \ if ( cntx == NULL ) cntx = bli_gks_query_cntx(); \ \ PASTECH2(ch,opname,_ker_ft) f = bli_cntx_get_l1v_ker_dt( dt, kerid, cntx ); \ \ f \ ( \ n, \ x, incx, \ y, incy, \ cntx \ ); \ } INSERT_GENTFUNC_BASIC( swapv, BLIS_SWAPV_KER ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, kerid ) \ \ void PASTEMAC2(ch,opname,EX_SUF) \ ( \ conj_t conjx, \ dim_t n, \ ctype* x, inc_t incx, \ ctype* beta, \ ctype* y, inc_t incy \ BLIS_TAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_TAPI_EX_DECLS \ \ const num_t dt = PASTEMAC(ch,type); \ \ /* Obtain a valid context from the gks if necessary. */ \ if ( cntx == NULL ) cntx = bli_gks_query_cntx(); \ \ PASTECH2(ch,opname,_ker_ft) f = bli_cntx_get_l1v_ker_dt( dt, kerid, cntx ); \ \ f \ ( \ conjx, \ n, \ x, incx, \ beta, \ y, incy, \ cntx \ ); \ } INSERT_GENTFUNC_BASIC( xpbyv, BLIS_XPBYV_KER ) #endif blis-0.9.0/frame/1/bli_l1v_tapi.h000066400000000000000000000116261422157504600164350ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype BLAS-like interfaces with typed operands. // #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC2(ch,opname,EX_SUF) \ ( \ conj_t conjx, \ dim_t n, \ ctype* x, inc_t incx, \ ctype* y, inc_t incy \ BLIS_TAPI_EX_PARAMS \ ); INSERT_GENTPROT_BASIC0( addv ) INSERT_GENTPROT_BASIC0( copyv ) INSERT_GENTPROT_BASIC0( subv ) #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC2(ch,opname,EX_SUF) \ ( \ dim_t n, \ ctype* x, inc_t incx, \ dim_t* index \ BLIS_TAPI_EX_PARAMS \ ); \ INSERT_GENTPROT_BASIC0( amaxv ) #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC2(ch,opname,EX_SUF) \ ( \ conj_t conjx, \ dim_t n, \ ctype* alpha, \ ctype* x, inc_t incx, \ ctype* beta, \ ctype* y, inc_t incy \ BLIS_TAPI_EX_PARAMS \ ); \ INSERT_GENTPROT_BASIC0( axpbyv ) #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC2(ch,opname,EX_SUF) \ ( \ conj_t conjx, \ dim_t n, \ ctype* alpha, \ ctype* x, inc_t incx, \ ctype* y, inc_t incy \ BLIS_TAPI_EX_PARAMS \ ); \ INSERT_GENTPROT_BASIC0( axpyv ) INSERT_GENTPROT_BASIC0( scal2v ) #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC2(ch,opname,EX_SUF) \ ( \ conj_t conjx, \ conj_t conjy, \ dim_t n, \ ctype* x, inc_t incx, \ ctype* y, inc_t incy, \ ctype* rho \ BLIS_TAPI_EX_PARAMS \ ); \ INSERT_GENTPROT_BASIC0( dotv ) #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC2(ch,opname,EX_SUF) \ ( \ conj_t conjx, \ conj_t conjy, \ dim_t n, \ ctype* alpha, \ ctype* x, inc_t incx, \ ctype* y, inc_t incy, \ ctype* beta, \ ctype* rho \ BLIS_TAPI_EX_PARAMS \ ); \ INSERT_GENTPROT_BASIC0( dotxv ) #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC2(ch,opname,EX_SUF) \ ( \ dim_t n, \ ctype* x, inc_t incx \ BLIS_TAPI_EX_PARAMS \ ); \ INSERT_GENTPROT_BASIC0( invertv ) #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC2(ch,opname,EX_SUF) \ ( \ conj_t conjalpha, \ dim_t n, \ ctype* alpha, \ ctype* x, inc_t incx \ BLIS_TAPI_EX_PARAMS \ ); \ INSERT_GENTPROT_BASIC0( scalv ) INSERT_GENTPROT_BASIC0( setv ) #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC2(ch,opname,EX_SUF) \ ( \ dim_t n, \ ctype* x, inc_t incx, \ ctype* y, inc_t incy \ BLIS_TAPI_EX_PARAMS \ ); \ INSERT_GENTPROT_BASIC0( swapv ) #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC2(ch,opname,EX_SUF) \ ( \ conj_t conjx, \ dim_t n, \ ctype* x, inc_t incx, \ ctype* beta, \ ctype* y, inc_t incy \ BLIS_TAPI_EX_PARAMS \ ); \ INSERT_GENTPROT_BASIC0( xpbyv ) blis-0.9.0/frame/1/bli_l1v_tapi_ba.c000066400000000000000000000036661422157504600170770ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // Include cpp macros that instantiate the API definition templates as // omitting expert parameters. #include "bli_tapi_ba.h" // Define the macro protecting the typed API definitions. #define BLIS_ENABLE_TAPI // Include the typed API definitions here. #include "bli_l1v_tapi.c" blis-0.9.0/frame/1/bli_l1v_tapi_ex.c000066400000000000000000000036641422157504600171270ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // Include cpp macros that instantiate the API definition templates as // having expert parameters. #include "bli_tapi_ex.h" // Define the macro protecting the typed API definitions. #define BLIS_ENABLE_TAPI // Include the typed API definitions here. #include "bli_l1v_tapi.c" blis-0.9.0/frame/1/other/000077500000000000000000000000001422157504600150325ustar00rootroot00000000000000blis-0.9.0/frame/1/other/packv/000077500000000000000000000000001422157504600161365ustar00rootroot00000000000000blis-0.9.0/frame/1/other/packv/bli_packv.c000066400000000000000000000032341422157504600202360ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" blis-0.9.0/frame/1/other/packv/bli_packv.h000066400000000000000000000034331422157504600202440ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "bli_packv_cntl.h" #include "bli_packv_check.h" #include "bli_packv_init.h" #include "bli_packv_int.h" #include "bli_packv_unb_var1.h" blis-0.9.0/frame/1/other/packv/bli_packv_check.c000066400000000000000000000037711422157504600214010ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_packv_check ( obj_t* c, obj_t* p, cntx_t* cntx ) { err_t e_val; // Check object datatypes. e_val = bli_check_floating_object( c ); bli_check_error_code( e_val ); // Check object dimensions. // We don't check for conformal dimensions between c and p because // p has not yet been initialized. } blis-0.9.0/frame/1/other/packv/bli_packv_check.h000066400000000000000000000033451422157504600214030ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void bli_packv_check ( obj_t* c, obj_t* p, cntx_t* cntx ); blis-0.9.0/frame/1/other/packv/bli_packv_cntl.c000066400000000000000000000050561422157504600212620ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" cntl_t* bli_packv_cntl_obj_create ( void_fp var_func, void_fp packv_var_func, bszid_t bmid, pack_t pack_schema, cntl_t* sub_node ) { cntl_t* cntl; packv_params_t* params; // Allocate a packv_params_t struct. params = bli_malloc_intl( sizeof( packv_params_t ) ); // Initialize the packv_params_t struct. params->size = sizeof( packv_params_t ); params->packv_var_func = packv_var_func; params->bmid = bmid; params->pack_schema = pack_schema; // It's important that we set the bszid field to BLIS_NO_PART to indicate // that no blocksize partitioning is performed. bli_cntl_free() will rely // on this information to know how to step through the thrinfo_t tree in // sync with the cntl_t tree. cntl = bli_cntl_create_node ( BLIS_NO_PART, var_func, params, sub_node ); return cntl; } blis-0.9.0/frame/1/other/packv/bli_packv_cntl.h000066400000000000000000000045641422157504600212720ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ struct packv_params_s { uint64_t size packv_var_oft* var_func; bszid_t bmid; pack_t pack_schema; }; typedef struct packv_params_s packv_params_t; #define bli_cntl_packv_params_var_func( cntl ) \ \ ( (packv_params_t*)( cntl->params )->var_func ) #define bli_cntl_packv_params_bmid( cntl ) \ \ ( (packv_params_t*)( cntl->params )->bmid_m ) #define bli_cntl_packv_params_pack_schema( cntl ) \ \ ( (packv_params_t*)( cntl->params )->pack_schema ) // ----------------------------------------------------------------------------- cntl_t* bli_packv_cntl_obj_create ( void_fp var_func, void_fp packv_var_func, bszid_t bmid, pack_t pack_schema, cntl_t* sub_node ); blis-0.9.0/frame/1/other/packv/bli_packv_init.c000066400000000000000000000145371422157504600212710ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2016, Hewlett Packard Enterprise Development LP 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_packv_init ( obj_t* a, obj_t* p, cntx_t* cntx, packv_t* cntl ) { // The purpose of packm_init() is to initialize an object P so that // a source object A can be packed into P via one of the packv // implementations. This initialization includes acquiring a suitable // block of memory from the memory allocator, if such a block of memory // has not already been allocated previously. pack_t pack_schema; bszid_t bmult_id; // Check parameters. if ( bli_error_checking_is_enabled() ) bli_packv_check( a, p, cntx ); // First check if we are to skip this operation because the control tree // is NULL, and if so, simply alias the object to its packed counterpart. if ( bli_cntl_is_noop( cntl ) ) { bli_obj_alias_to( a, p ); return; } // At this point, we can be assured that cntl is not NULL. Let us now // check to see if the object has already been packed to the desired // schema (as encoded in the control tree). If so, we can alias and // return, as above. // Note that in most cases, bli_obj_pack_schema() will return // BLIS_NOT_PACKED and thus packing will be called for (but in some // cases packing has already taken place). Also, not all combinations // of current pack status and desired pack schema are valid. if ( bli_obj_pack_schema( a ) == cntl_pack_schema( cntl ) ) { bli_obj_alias_to( a, p ); return; } // Now, if we are not skipping the pack operation, then the only question // left is whether we are to typecast vector a before packing. if ( bli_obj_dt( a ) != bli_obj_target_dt( a ) ) bli_abort(); // Extract various fields from the control tree and pass them in // explicitly into _init_pack(). This allows external code generators // the option of bypassing usage of control trees altogether. pack_schema = cntl_pack_schema( cntl ); bmult_id = cntl_bmid( cntl ); // Initialize object p for the final packed vector. bli_packv_init_pack ( pack_schema, bmult_id, &a, p, cntx ); // Now p is ready to be packed. } siz_t bli_packv_init_pack ( pack_t schema, bszid_t bmult_id, obj_t* a, obj_t* p, cntx_t* cntx ) { num_t dt = bli_obj_dt( a ); dim_t dim_a = bli_obj_vector_dim( a ); dim_t bmult = bli_cntx_get_blksz_def_dt( dt, bmult_id, cntx ); pba_t* pba = bli_cntx_pba( cntx ); #if 0 mem_t* mem_p; #endif dim_t m_p_pad; siz_t size_p; inc_t rs_p, cs_p; void* buf; // We begin by copying the basic fields of c. bli_obj_alias_to( a, p ); // Update the dimensions. bli_obj_set_dims( dim_a, 1, p ); // Reset the view offsets to (0,0). bli_obj_set_offs( 0, 0, p ); // Set the pack schema in the p object to the value in the control tree // node. bli_obj_set_pack_schema( schema, p ); // Compute the dimensions padded by the dimension multiples. m_p_pad = bli_align_dim_to_mult( bli_obj_vector_dim( p ), bmult ); // Compute the size of the packed buffer. size_p = m_p_pad * 1 * bli_obj_elem_size( p ); #if 0 // Extract the address of the mem_t object within p that will track // properties of the packed buffer. mem_p = bli_obj_pack_mem( *p ); if ( bli_mem_is_unalloc( mem_p ) ) { // If the mem_t object of p has not yet been allocated, then acquire // a memory block suitable for a vector. bli_pba_acquire_v( pba, size_p, mem_p ); } else { // If the mem_t object has already been allocated, then release and // re-acquire the memory so there is sufficient space. if ( bli_mem_size( mem_p ) < size_p ) { bli_pba_release( mem_p ); bli_pba_acquire_v( pba, size_p, mem_p ); } } // Grab the buffer address from the mem_t object and copy it to the // main object buffer field. (Sometimes this buffer address will be // copied when the value is already up-to-date, because it persists // in the main object buffer field across loop iterations.) buf = bli_mem_buffer( mem_p ); bli_obj_set_buffer( buf, p ); #endif // Save the padded (packed) dimensions into the packed object. bli_obj_set_padded_dims( m_p_pad, 1, p ); // Set the row and column strides of p based on the pack schema. if ( schema == BLIS_PACKED_VECTOR ) { // Set the strides to reflect a column-stored vector. Note that the // column stride may never be used, and is only useful to determine // how much space beyond the vector would need to be zero-padded, if // zero-padding was needed. rs_p = 1; cs_p = bli_obj_padded_length( p ); bli_obj_set_strides( rs_p, cs_p, p ); } return size_p; } #if 0 void bli_packv_release ( obj_t* p, packv_t* cntl ) { if ( !bli_cntl_is_noop( cntl ) ) bli_obj_release_pack( p ); } #endif blis-0.9.0/frame/1/other/packv/bli_packv_init.h000066400000000000000000000036321422157504600212700ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void bli_packv_init ( obj_t* a, obj_t* p, cntx_t* cntx, packv_t* cntl ); siz_t bli_packv_init_pack ( pack_t pack_schema, bszid_t bmult_id, obj_t* a, obj_t* p, cntx_t* cntx ); blis-0.9.0/frame/1/other/packv/bli_packv_int.c000066400000000000000000000104341422157504600211100ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define FUNCPTR_T packv_fp typedef void (*FUNCPTR_T)( obj_t* a, obj_t* p, cntx_t* cntx, packv_t* cntl ); static FUNCPTR_T vars[1][3] = { // unblocked optimized unblocked blocked { bli_packv_unb_var1, NULL, NULL } }; void bli_packv_int ( obj_t* a, obj_t* p, cntx_t* cntx, cntl_t* cntl ) { #if 0 varnum_t n; impl_t i; #endif packv_var_oft f; // !!! // DEFINE packv_var_oft type. // !!! // Check parameters. if ( bli_error_checking_is_enabled() ) bli_packv_check( a, p, cntx ); // Sanity check; A should never have a zero dimension. If we must support // it, then we should fold it into the next alias-and-early-exit block. //if ( bli_obj_has_zero_dim( a ) ) bli_abort(); // First check if we are to skip this operation because the control tree // is NULL. We return without taking any action because a was already // aliased to p in packv_init(). if ( bli_cntl_is_noop( cntl ) ) { return; } // Let us now check to see if the object has already been packed. First // we check if it has been packed to an unspecified (row or column) // format, in which case we can return, since by now aliasing has already // taken place in packv_init(). // NOTE: The reason we don't need to even look at the control tree in // this case is as follows: an object's pack status is only set to // BLIS_PACKED_UNSPEC for situations when the actual format used is // not important, as long as its packed into contiguous rows or // contiguous columns. A good example of this is packing for matrix // operands in the level-2 operations. if ( bli_obj_pack_schema( a ) == BLIS_PACKED_UNSPEC ) { return; } // At this point, we can be assured that cntl is not NULL. Now we check // if the object has already been packed to the desired schema (as en- // coded in the control tree). If so, we can return, as above. // NOTE: In most cases, an object's pack status will be BLIS_NOT_PACKED // and thus packing will be called for (but in some cases packing has // already taken place, or does not need to take place, and so that will // be indicated by the pack status). Also, not all combinations of // current pack status and desired pack schema are valid. if ( bli_obj_pack_schema( a ) == cntl_pack_schema( cntl ) ) { return; } // Extract the variant number and implementation type. n = bli_cntl_var_num( cntl ); i = bli_cntl_impl_type( cntl ); // Index into the variant array to extract the correct function pointer. f = vars[n][i]; // Invoke the variant. f( a, p, cntx, cntl ); } blis-0.9.0/frame/1/other/packv/bli_packv_int.h000066400000000000000000000033751422157504600211230ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void bli_packv_int ( obj_t* c, obj_t* p, cntx_t* cntx, packv_t* cntl ); blis-0.9.0/frame/1/other/packv/bli_packv_unb_var1.c000066400000000000000000000061171422157504600220360ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define FUNCPTR_T packv_fp typedef void (*FUNCPTR_T)( dim_t m, void* c, inc_t incc, void* p, inc_t incp, cntx_t* cntx ); static FUNCPTR_T GENARRAY(ftypes,packv_unb_var1); void bli_packv_unb_var1( obj_t* c, obj_t* p, cntx_t* cntx, packv_t* cntl ) { num_t dt_cp = bli_obj_dt( c ); dim_t dim_p = bli_obj_vector_dim( p ); void* buf_c = bli_obj_buffer_at_off( c ); inc_t incc = bli_obj_vector_inc( c ); void* buf_p = bli_obj_buffer_at_off( p ); inc_t incp = bli_obj_vector_inc( p ); FUNCPTR_T f; // Index into the type combination array to extract the correct // function pointer. f = ftypes[dt_cp]; // Invoke the function. f ( dim_p, buf_c, incc, buf_p, incp, cntx ); } #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ dim_t m, \ void* c, inc_t incc, \ void* p, inc_t incp, \ cntx_t* cntx \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ PASTECH(ch,copyv_ft) copyv_p = bli_cntx_get_l1v_ker_dt( dt, BLIS_COPYV_KER, cntx ); \ \ copyv_p \ ( \ BLIS_NO_CONJUGATE, \ m, \ c, incc, \ p, incp, \ cntx \ ); \ } INSERT_GENTFUNC_BASIC0( packv_unb_var1 ) blis-0.9.0/frame/1/other/packv/bli_packv_unb_var1.h000066400000000000000000000040441422157504600220400ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void bli_packv_unb_var1( obj_t* c, obj_t* p, cntx_t* cntx, packv_t* cntl ); #undef GENTPROT #define GENTPROT( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ dim_t m, \ void* c, inc_t incc, \ void* p, inc_t incp, \ cntx_t* cntx \ ); INSERT_GENTPROT_BASIC( packv_unb_var1 ) blis-0.9.0/frame/1/other/scalv/000077500000000000000000000000001422157504600161425ustar00rootroot00000000000000blis-0.9.0/frame/1/other/scalv/bli_scalv_cntl.c000066400000000000000000000045651422157504600212760ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" scalv_t* scalv_cntl = NULL; void bli_scalv_cntl_init() { scalv_cntl = bli_scalv_cntl_obj_create( BLIS_UNBLOCKED, BLIS_VARIANT1 ); } void bli_scalv_cntl_finalize() { bli_cntl_free_node( scalv_cntl ); } scalv_t* bli_scalv_cntl_obj_create( impl_t impl_type, varnum_t var_num ) { scalv_t* cntl; cntl = ( scalv_t* ) bli_malloc_intl( sizeof(scalv_t) ); cntl->impl_type = impl_type; cntl->var_num = var_num; return cntl; } void bli_scalv_cntl_obj_init( scalv_t* cntl, impl_t impl_type, varnum_t var_num ) { cntl->impl_type = impl_type; cntl->var_num = var_num; } blis-0.9.0/frame/1/other/scalv/bli_scalv_cntl.h000066400000000000000000000042131422157504600212710ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ struct scalv_s { impl_t impl_type; varnum_t var_num; }; typedef struct scalv_s scalv_t; #define bli_cntl_sub_scalv( cntl ) cntl->sub_scalv void bli_scalv_cntl_init( void ); void bli_scalv_cntl_finalize( void ); scalv_t* bli_scalv_cntl_obj_create( impl_t impl_type, varnum_t var_num ); void bli_scalv_cntl_obj_init( scalv_t* cntl, impl_t impl_type, varnum_t var_num ); blis-0.9.0/frame/1/other/scalv/bli_scalv_int.c000066400000000000000000000053741422157504600211270ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" typedef void (*FUNCPTR_T)( obj_t* alpha, obj_t* x, cntx_t* cntx ); static FUNCPTR_T vars[1][3] = { // unblocked optimized unblocked blocked { bli_scalv_ex, bli_scalv_ex, NULL } }; void bli_scalv_int( obj_t* alpha, obj_t* x, cntx_t* cntx, scalv_t* cntl ) { varnum_t n; impl_t i; FUNCPTR_T f; // Return early if one of the matrix operands has a zero dimension. if ( bli_obj_has_zero_dim( x ) ) return; // Check parameters. if ( bli_error_checking_is_enabled() ) bli_scalv_check( alpha, x ); // First check if we are to skip this operation. if ( bli_cntl_is_noop( cntl ) ) return; // Return early if the alpha scalar equals one. if ( bli_obj_equals( alpha, &BLIS_ONE ) ) return; // Extract the variant number and implementation type. n = bli_cntl_var_num( cntl ); i = bli_cntl_impl_type( cntl ); // Index into the variant array to extract the correct function pointer. f = vars[n][i]; // Invoke the variant. f( alpha, x, cntx ); } blis-0.9.0/frame/1/other/scalv/bli_scalv_int.h000066400000000000000000000034261422157504600211300ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void bli_scalv_int( obj_t* alpha, obj_t* x, cntx_t* cntx, scalv_t* cntl ); blis-0.9.0/frame/1/other/unpackv/000077500000000000000000000000001422157504600165015ustar00rootroot00000000000000blis-0.9.0/frame/1/other/unpackv/bli_unpackv.c000066400000000000000000000032341422157504600211440ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" blis-0.9.0/frame/1/other/unpackv/bli_unpackv.h000066400000000000000000000034101422157504600211450ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "bli_unpackv_cntl.h" #include "bli_unpackv_check.h" #include "bli_unpackv_int.h" #include "bli_unpackv_unb_var1.h" blis-0.9.0/frame/1/other/unpackv/bli_unpackv_check.c000066400000000000000000000042271422157504600223040ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_unpackv_check ( obj_t* p, obj_t* a, cntx_t* cntx ) { err_t e_val; // Check object datatypes. e_val = bli_check_floating_object( p ); bli_check_error_code( e_val ); e_val = bli_check_floating_object( a ); bli_check_error_code( e_val ); // Check object dimensions. e_val = bli_check_equal_vector_lengths( p, a ); bli_check_error_code( e_val ); // Check pack status. e_val = bli_check_packv_schema_on_unpack( p ); bli_check_error_code( e_val ); } blis-0.9.0/frame/1/other/unpackv/bli_unpackv_check.h000066400000000000000000000033471422157504600223130ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void bli_unpackv_check ( obj_t* p, obj_t* a, cntx_t* cntx ); blis-0.9.0/frame/1/other/unpackv/bli_unpackv_cntl.c000066400000000000000000000046321422157504600221670ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" unpackv_t* unpackv_cntl = NULL; void bli_unpackv_cntl_init() { unpackv_cntl = bli_unpackv_cntl_obj_create( BLIS_UNBLOCKED, BLIS_VARIANT1 ); } void bli_unpackv_cntl_finalize() { bli_cntl_free_node( unpackv_cntl ); } unpackv_t* bli_unpackv_cntl_obj_create( impl_t impl_type, varnum_t var_num ) { unpackv_t* cntl; cntl = ( unpackv_t* ) bli_malloc_intl( sizeof(unpackv_t) ); cntl->impl_type = impl_type; cntl->var_num = var_num; return cntl; } void bli_unpackv_cntl_obj_init( unpackv_t* cntl, impl_t impl_type, varnum_t var_num ) { cntl->impl_type = impl_type; cntl->var_num = var_num; } blis-0.9.0/frame/1/other/unpackv/bli_unpackv_cntl.h000066400000000000000000000046371422157504600222010ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ struct unpackv_s { impl_t impl_type; varnum_t var_num; }; typedef struct unpackv_s unpackv_t; #define bli_cntl_sub_unpackv( cntl ) cntl->sub_unpackv #define bli_cntl_sub_unpackv_x( cntl ) cntl->sub_unpackv_x #define bli_cntl_sub_unpackv_x1( cntl ) cntl->sub_unpackv_x1 #define bli_cntl_sub_unpackv_y( cntl ) cntl->sub_unpackv_y #define bli_cntl_sub_unpackv_y1( cntl ) cntl->sub_unpackv_y1 void bli_unpackv_cntl_init( void ); void bli_unpackv_cntl_finalize( void ); unpackv_t* bli_unpackv_cntl_obj_create( impl_t impl_type, varnum_t var_num ); void bli_unpackv_cntl_obj_init( unpackv_t* cntl, impl_t impl_type, varnum_t var_num ); blis-0.9.0/frame/1/other/unpackv/bli_unpackv_int.c000066400000000000000000000174301422157504600220210ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define FUNCPTR_T unpackv_fp typedef void (*FUNCPTR_T)( obj_t* p, obj_t* a, cntx_t* cntx, unpackv_t* cntl ); static FUNCPTR_T vars[1][3] = { // unblocked optimized unblocked blocked { bli_unpackv_unb_var1, NULL, NULL } }; void bli_unpackv_int( obj_t* p, obj_t* a, cntx_t* cntx, unpackv_t* cntl ) { // The unpackv operation consists of an optional casting post-process. // (This post-process is analogous to the cast pre-process in packv.) // Here are the following possible ways unpackv can execute: // 1. unpack and cast: Unpack to a temporary vector c and then cast // c to a. // 2. unpack only: Unpack directly to vector a since typecasting is // not needed. // 3. cast only: Not yet supported / not used. // 4. no-op: The control tree directs us to skip the unpack operation // entirely. No action is taken. obj_t c; varnum_t n; impl_t i; FUNCPTR_T f; // Check parameters. if ( bli_error_checking_is_enabled() ) bli_unpackv_check( p, a, cntx ); // Sanity check; A should never have a zero dimension. If we must support // it, then we should fold it into the next alias-and-early-exit block. if ( bli_obj_has_zero_dim( a ) ) bli_abort(); // First check if we are to skip this operation because the control tree // is NULL, and if so, simply return. if ( bli_cntl_is_noop( cntl ) ) { return; } // If p was aliased to a during the pack stage (because it was already // in an acceptable packed/contiguous format), then no unpack is actually // necessary, so we return. if ( bli_obj_is_alias_of( p, a ) ) { return; } // Now, if we are not skipping the unpack operation, then the only // question left is whether we are to typecast vector a after unpacking. if ( bli_obj_dt( p ) != bli_obj_dt( a ) ) bli_abort(); /* if ( bli_obj_dt( p ) != bli_obj_dt( a ) ) { // Initialize an object c for the intermediate typecast vector. bli_unpackv_init_cast( p, a, &c ); } else */ { // If no cast is needed, then aliasing object c to the original // vector serves as a minor optimization. This causes the unpackv // implementation to unpack directly into vector a. bli_obj_alias_to( a, &c ); } // Now we are ready to proceed with the unpacking. // Extract the variant number and implementation type. n = bli_cntl_var_num( cntl ); i = bli_cntl_impl_type( cntl ); // Index into the variant array to extract the correct function pointer. f = vars[n][i]; // Invoke the variant. f( p, &c, cntx, cntl ); // Now, if necessary, we cast the contents of c to vector a. If casting // was not necessary, then we are done because the call to the unpackv // implementation would have unpacked directly to vector a. /* if ( bli_obj_dt( p ) != bli_obj_dt( a ) ) { // Copy/typecast vector c to vector a. // NOTE: Here, we use copynzv instead of copym because, in the cases // where we are unpacking/typecasting a real vector c to a complex // vector a, we want to touch only the real components of a, rather // than also set the imaginary components to zero. This comes about // because of the fact that, if we are unpacking real-to-complex, // then it is because all of the computation occurred in the real // domain, and so we would want to leave whatever imaginary values // there are in vector a untouched. Notice that for unpackings that // entail complex-to-complex data movements, the copynzv operation // behaves exactly as copym, so no use cases are lost (at least none // that I can think of). bli_copynzv( &c, a ); // NOTE: The above code/comment is outdated. What should happen is // as follows: // - If dt(a) is complex and dt(p) is real, then create an alias of // a and then tweak it so that it looks like a real domain object. // This will involve: // - projecting the datatype to real domain // - scaling both the row and column strides by 2 // ALL OF THIS should be done in the front-end, NOT here, as // unpackv() won't even be needed in that case. } */ } /* void bli_unpackv_init_cast( obj_t* p, obj_t* a, obj_t* c ) { // The idea here is that we want to create an object c that is identical // to object a, except that: // (1) the storage datatype of c is equal to the target datatype of a, // with the element size of c adjusted accordingly, // (2) object c is marked as being stored in a standard, contiguous // format (ie: a column vector), // (3) the view offset of c is reset to (0,0), and // (4) object c's main buffer is set to a new memory region acquired // from the memory manager, or extracted from p if a mem entry is // already available. (After acquring a mem entry from the memory // manager, it is cached within p for quick access later on.) num_t dt_targ_a = bli_obj_target_dt( a ); dim_t dim_a = bli_obj_vector_dim( a ); siz_t elem_size_c = bli_dt_size( dt_targ_a ); // We begin by copying the basic fields of a. bli_obj_alias_to( a, c ); // Update datatype and element size fields. bli_obj_set_dt( dt_targ_a, c ); bli_obj_set_elem_size( elem_size_c, c ); // Update the strides and dimensions. We set the increments to reflect a // column-stored vector. Note that the column stride is set to dim(a), // though it should never be used because there is no second column to // index into (and therefore it also does not need to be aligned). bli_obj_set_dims( dim_a, 1, c ); bli_obj_set_strides( 1, dim_a, c ); // Reset the view offsets to (0,0). bli_obj_set_offs( 0, 0, c ); // Check the mem_t entry of p associated with the cast buffer. If it is // NULL, then acquire memory sufficient to hold the object data and cache // it to p. (Otherwise, if it is non-NULL, then memory has already been // acquired from the memory manager and cached.) We then set the main // buffer of c to the cached address of the cast memory. bli_obj_set_buffer_with_cached_cast_mem( *p, *c ); } */ blis-0.9.0/frame/1/other/unpackv/bli_unpackv_int.h000066400000000000000000000036371422157504600220320ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void bli_unpackv_int( obj_t* p, obj_t* a, cntx_t* cntx, unpackv_t* cntl ); /* void bli_unpackv_init_cast( obj_t* p, obj_t* a, obj_t* c ); */ blis-0.9.0/frame/1/other/unpackv/bli_unpackv_unb_var1.c000066400000000000000000000061451422157504600227450ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define FUNCPTR_T unpackv_fp typedef void (*FUNCPTR_T)( dim_t m, void* p, inc_t incp, void* c, inc_t incc, cntx_t* cntx ); static FUNCPTR_T GENARRAY(ftypes,unpackv_unb_var1); void bli_unpackv_unb_var1( obj_t* p, obj_t* c, cntx_t* cntx, unpackv_t* cntl ) { num_t dt_pc = bli_obj_dt( p ); dim_t dim_c = bli_obj_vector_dim( c ); void* buf_p = bli_obj_buffer_at_off( p ); inc_t incp = bli_obj_vector_inc( p ); void* buf_c = bli_obj_buffer_at_off( c ); inc_t incc = bli_obj_vector_inc( c ); FUNCPTR_T f; // Index into the type combination array to extract the correct // function pointer. f = ftypes[dt_pc]; // Invoke the function. f ( dim_c, buf_p, incp, buf_c, incc, cntx ); } #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ dim_t m, \ void* p, inc_t incp, \ void* c, inc_t incc, \ cntx_t* cntx \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ PASTECH(ch,copyv_ft) copyv_p = bli_cntx_get_l1v_ker_dt( dt, BLIS_COPYV_KER, cntx ); \ \ copyv_p \ ( \ BLIS_NO_CONJUGATE, \ m, \ p, incp, \ c, incc, \ cntx \ ); \ } INSERT_GENTFUNC_BASIC0( unpackv_unb_var1 ) blis-0.9.0/frame/1/other/unpackv/bli_unpackv_unb_var1.h000066400000000000000000000040661422157504600227520ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void bli_unpackv_unb_var1( obj_t* p, obj_t* c, cntx_t* cntx, unpackv_t* cntl ); #undef GENTPROT #define GENTPROT( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ dim_t m, \ void* p, inc_t incp, \ void* c, inc_t incc, \ cntx_t* cntx \ ); INSERT_GENTPROT_BASIC( unpackv_unb_var1 ) blis-0.9.0/frame/1d/000077500000000000000000000000001422157504600140555ustar00rootroot00000000000000blis-0.9.0/frame/1d/bli_l1d.h000066400000000000000000000043301422157504600155340ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "bli_l1d_check.h" // Prototype object APIs (expert and non-expert). #include "bli_oapi_ex.h" #include "bli_l1d_oapi.h" #include "bli_xapi_undef.h" #include "bli_oapi_ba.h" #include "bli_l1d_oapi.h" #include "bli_xapi_undef.h" // Prototype typed APIs (expert and non-expert). #include "bli_tapi_ex.h" #include "bli_l1d_tapi.h" #include "bli_l1d_ft.h" #include "bli_xapi_undef.h" #include "bli_tapi_ba.h" #include "bli_l1d_tapi.h" #include "bli_l1d_ft.h" #include "bli_xapi_undef.h" // Generate function pointer arrays for tapi functions (expert only). #include "bli_l1d_fpa.h" blis-0.9.0/frame/1d/bli_l1d_check.c000066400000000000000000000134251422157504600166710ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // Define object-based check functions. // #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC(opname,_check) \ ( \ obj_t* x, \ obj_t* y \ ) \ { \ bli_l1d_xy_check( x, y ); \ } GENFRONT( addd ) GENFRONT( copyd ) GENFRONT( subd ) #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC(opname,_check) \ ( \ obj_t* alpha, \ obj_t* x, \ obj_t* y \ ) \ { \ bli_l1d_axy_check( alpha, x, y ); \ } GENFRONT( axpyd ) GENFRONT( scal2d ) #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC(opname,_check) \ ( \ obj_t* x \ ) \ { \ bli_l1d_x_check( x ); \ } GENFRONT( invertd ) #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC(opname,_check) \ ( \ obj_t* alpha, \ obj_t* x \ ) \ { \ bli_l1d_ax_check( alpha, x ); \ } GENFRONT( scald ) GENFRONT( setd ) GENFRONT( setid ) GENFRONT( shiftd ) #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC(opname,_check) \ ( \ obj_t* x, \ obj_t* beta, \ obj_t* y \ ) \ { \ bli_l1d_axy_check( beta, x, y ); \ } GENFRONT( xpbyd ) // ----------------------------------------------------------------------------- void bli_l1d_xy_check ( obj_t* x, obj_t* y ) { err_t e_val; // Check object datatypes. e_val = bli_check_floating_object( x ); bli_check_error_code( e_val ); e_val = bli_check_floating_object( y ); bli_check_error_code( e_val ); // Check for consistent datatypes. e_val = bli_check_consistent_object_datatypes( x, y ); bli_check_error_code( e_val ); // Check object dimensions. e_val = bli_check_matrix_object( x ); bli_check_error_code( e_val ); e_val = bli_check_matrix_object( y ); bli_check_error_code( e_val ); e_val = bli_check_conformal_dims( x, y ); bli_check_error_code( e_val ); // Check object buffers (for non-NULLness). e_val = bli_check_object_buffer( x ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( y ); bli_check_error_code( e_val ); } void bli_l1d_axy_check ( obj_t* alpha, obj_t* x, obj_t* y ) { err_t e_val; // Check object datatypes. e_val = bli_check_noninteger_object( alpha ); bli_check_error_code( e_val ); e_val = bli_check_floating_object( x ); bli_check_error_code( e_val ); e_val = bli_check_floating_object( y ); bli_check_error_code( e_val ); // Check for consistent datatypes. e_val = bli_check_consistent_object_datatypes( x, y ); bli_check_error_code( e_val ); // Check object dimensions. e_val = bli_check_scalar_object( alpha ); bli_check_error_code( e_val ); e_val = bli_check_matrix_object( x ); bli_check_error_code( e_val ); e_val = bli_check_matrix_object( y ); bli_check_error_code( e_val ); e_val = bli_check_conformal_dims( x, y ); bli_check_error_code( e_val ); // Check object buffers (for non-NULLness). e_val = bli_check_object_buffer( alpha ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( x ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( y ); bli_check_error_code( e_val ); } void bli_l1d_x_check ( obj_t* x ) { err_t e_val; // Check object datatypes. e_val = bli_check_floating_object( x ); bli_check_error_code( e_val ); // Check object dimensions. e_val = bli_check_matrix_object( x ); bli_check_error_code( e_val ); // Check object buffers (for non-NULLness). e_val = bli_check_object_buffer( x ); bli_check_error_code( e_val ); } void bli_l1d_ax_check ( obj_t* alpha, obj_t* x ) { err_t e_val; // Check object datatypes. e_val = bli_check_noninteger_object( alpha ); bli_check_error_code( e_val ); e_val = bli_check_floating_object( x ); bli_check_error_code( e_val ); // Check object dimensions. e_val = bli_check_scalar_object( alpha ); bli_check_error_code( e_val ); e_val = bli_check_matrix_object( x ); bli_check_error_code( e_val ); // Check object buffers (for non-NULLness). e_val = bli_check_object_buffer( alpha ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( x ); bli_check_error_code( e_val ); } blis-0.9.0/frame/1d/bli_l1d_check.h000066400000000000000000000057261422157504600167030ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype object-based check functions. // #undef GENTPROT #define GENTPROT( opname ) \ \ void PASTEMAC(opname,_check) \ ( \ obj_t* x, \ obj_t* y \ ); GENTPROT( addd ) GENTPROT( copyd ) GENTPROT( subd ) #undef GENTPROT #define GENTPROT( opname ) \ \ void PASTEMAC(opname,_check) \ ( \ obj_t* alpha, \ obj_t* x, \ obj_t* y \ ); GENTPROT( axpyd ) GENTPROT( scal2d ) #undef GENTPROT #define GENTPROT( opname ) \ \ void PASTEMAC(opname,_check) \ ( \ obj_t* x \ ); GENTPROT( invertd ) #undef GENTPROT #define GENTPROT( opname ) \ \ void PASTEMAC(opname,_check) \ ( \ obj_t* alpha, \ obj_t* x \ ); GENTPROT( scald ) GENTPROT( setd ) GENTPROT( setid ) GENTPROT( shiftd ) #undef GENTPROT #define GENTPROT( opname ) \ \ void PASTEMAC(opname,_check) \ ( \ obj_t* x, \ obj_t* beta, \ obj_t* y \ ); GENTPROT( xpbyd ) // ----------------------------------------------------------------------------- void bli_l1d_xy_check ( obj_t* x, obj_t* y ); void bli_l1d_axy_check ( obj_t* alpha, obj_t* x, obj_t* y ); void bli_l1d_x_check ( obj_t* x ); void bli_l1d_ax_check ( obj_t* alpha, obj_t* x ); blis-0.9.0/frame/1d/bli_l1d_fpa.c000066400000000000000000000043241422157504600163600ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // Define function pointer query interfaces. // #undef GENFRONT #define GENFRONT( opname ) \ \ GENARRAY_FPA( PASTECH2(opname,BLIS_TAPI_EX_SUF,_vft), \ PASTECH(opname,BLIS_TAPI_EX_SUF) ); \ \ PASTECH2(opname,BLIS_TAPI_EX_SUF,_vft) \ PASTEMAC2(opname,BLIS_TAPI_EX_SUF,_qfp)( num_t dt ) \ { \ return PASTECH2(opname,BLIS_TAPI_EX_SUF,_fpa)[ dt ]; \ } GENFRONT( addd ) GENFRONT( copyd ) GENFRONT( subd ) GENFRONT( axpyd ) GENFRONT( scal2d ) GENFRONT( invertd ) GENFRONT( scald ) GENFRONT( setd ) GENFRONT( setid ) GENFRONT( shiftd ) GENFRONT( xpbyd ) blis-0.9.0/frame/1d/bli_l1d_fpa.h000066400000000000000000000040111422157504600163560ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype function pointer query interface. // #undef GENPROT #define GENPROT( opname ) \ \ PASTECH2(opname,BLIS_TAPI_EX_SUF,_vft) \ PASTEMAC2(opname,BLIS_TAPI_EX_SUF,_qfp)( num_t dt ); GENPROT( addd ) GENPROT( copyd ) GENPROT( subd ) GENPROT( axpyd ) GENPROT( scal2d ) GENPROT( invertd ) GENPROT( scald ) GENPROT( setd ) GENPROT( setid ) GENPROT( shiftd ) GENPROT( xpbyd ) blis-0.9.0/frame/1d/bli_l1d_ft.h000066400000000000000000000106051422157504600162270ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // -- Level-1d function types -------------------------------------------------- // // addd, copyd, subd #undef GENTDEF #define GENTDEF( ctype, ch, opname, tsuf ) \ \ typedef void (*PASTECH3(ch,opname,EX_SUF,tsuf)) \ ( \ doff_t diagoffx, \ diag_t diagx, \ trans_t transx, \ dim_t m, \ dim_t n, \ ctype* x, inc_t rs_x, inc_t cs_x, \ ctype* y, inc_t rs_y, inc_t cs_y \ BLIS_TAPI_EX_PARAMS \ ); INSERT_GENTDEF( addd ) INSERT_GENTDEF( copyd ) INSERT_GENTDEF( subd ) // axpyd, scal2d #undef GENTDEF #define GENTDEF( ctype, ch, opname, tsuf ) \ \ typedef void (*PASTECH3(ch,opname,EX_SUF,tsuf)) \ ( \ doff_t diagoffx, \ diag_t diagx, \ trans_t transx, \ dim_t m, \ dim_t n, \ ctype* alpha, \ ctype* x, inc_t rs_x, inc_t cs_x, \ ctype* y, inc_t rs_y, inc_t cs_y \ BLIS_TAPI_EX_PARAMS \ ); INSERT_GENTDEF( axpyd ) INSERT_GENTDEF( scal2d ) // invertd #undef GENTDEF #define GENTDEF( ctype, ch, opname, tsuf ) \ \ typedef void (*PASTECH3(ch,opname,EX_SUF,tsuf)) \ ( \ doff_t diagoffx, \ dim_t m, \ dim_t n, \ ctype* x, inc_t rs_x, inc_t cs_x \ BLIS_TAPI_EX_PARAMS \ ); INSERT_GENTDEF( invertd ) // scald, setd #undef GENTDEF #define GENTDEF( ctype, ch, opname, tsuf ) \ \ typedef void (*PASTECH3(ch,opname,EX_SUF,tsuf)) \ ( \ conj_t conjalpha, \ doff_t diagoffx, \ dim_t m, \ dim_t n, \ ctype* alpha, \ ctype* x, inc_t rs_x, inc_t cs_x \ BLIS_TAPI_EX_PARAMS \ ); INSERT_GENTDEF( scald ) INSERT_GENTDEF( setd ) // setid #undef GENTDEFR #define GENTDEFR( ctype, ctype_r, ch, chr, opname, tsuf ) \ \ typedef void (*PASTECH3(ch,opname,EX_SUF,tsuf)) \ ( \ doff_t diagoffx, \ dim_t m, \ dim_t n, \ ctype_r* alpha, \ ctype* x, inc_t rs_x, inc_t cs_x \ BLIS_TAPI_EX_PARAMS \ ); INSERT_GENTDEFR( setid ) // shiftd #undef GENTDEF #define GENTDEF( ctype, ch, opname, tsuf ) \ \ typedef void (*PASTECH3(ch,opname,EX_SUF,tsuf)) \ ( \ doff_t diagoffx, \ dim_t m, \ dim_t n, \ ctype* alpha, \ ctype* x, inc_t rs_x, inc_t cs_x \ BLIS_TAPI_EX_PARAMS \ ); INSERT_GENTDEF( shiftd ) // xpbyd #undef GENTDEF #define GENTDEF( ctype, ch, opname, tsuf ) \ \ typedef void (*PASTECH3(ch,opname,EX_SUF,tsuf)) \ ( \ doff_t diagoffx, \ diag_t diagx, \ trans_t transx, \ dim_t m, \ dim_t n, \ ctype* x, inc_t rs_x, inc_t cs_x, \ ctype* beta, \ ctype* y, inc_t rs_y, inc_t cs_y \ BLIS_TAPI_EX_PARAMS \ ); INSERT_GENTDEF( xpbyd ) blis-0.9.0/frame/1d/bli_l1d_oapi.c000066400000000000000000000263431422157504600165470ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // Guard the function definitions so that they are only compiled when // #included from files that define the object API macros. #ifdef BLIS_ENABLE_OAPI // // Define object-based interfaces. // #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC(opname,EX_SUF) \ ( \ obj_t* x, \ obj_t* y \ BLIS_OAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_OAPI_EX_DECLS \ \ num_t dt = bli_obj_dt( x ); \ \ doff_t diagoffx = bli_obj_diag_offset( x ); \ diag_t diagx = bli_obj_diag( x ); \ trans_t transx = bli_obj_conjtrans_status( x ); \ dim_t m = bli_obj_length( y ); \ dim_t n = bli_obj_width( y ); \ void* buf_x = bli_obj_buffer_at_off( x ); \ inc_t rs_x = bli_obj_row_stride( x ); \ inc_t cs_x = bli_obj_col_stride( x ); \ void* buf_y = bli_obj_buffer_at_off( y ); \ inc_t rs_y = bli_obj_row_stride( y ); \ inc_t cs_y = bli_obj_col_stride( y ); \ \ if ( bli_error_checking_is_enabled() ) \ PASTEMAC(opname,_check)( x, y ); \ \ /* Query a type-specific function pointer, except one that uses void* for function arguments instead of typed pointers. */ \ PASTECH2(opname,BLIS_TAPI_EX_SUF,_vft) f = \ PASTEMAC2(opname,BLIS_TAPI_EX_SUF,_qfp)( dt ); \ \ f \ ( \ diagoffx, \ diagx, \ transx, \ m, \ n, \ buf_x, rs_x, cs_x, \ buf_y, rs_y, cs_y, \ cntx, \ rntm \ ); \ } GENFRONT( addd ) GENFRONT( copyd ) GENFRONT( subd ) #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC(opname,EX_SUF) \ ( \ obj_t* alpha, \ obj_t* x, \ obj_t* y \ BLIS_OAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_OAPI_EX_DECLS \ \ num_t dt = bli_obj_dt( x ); \ \ doff_t diagoffx = bli_obj_diag_offset( x ); \ diag_t diagx = bli_obj_diag( x ); \ trans_t transx = bli_obj_conjtrans_status( x ); \ dim_t m = bli_obj_length( y ); \ dim_t n = bli_obj_width( y ); \ void* buf_x = bli_obj_buffer_at_off( x ); \ inc_t rs_x = bli_obj_row_stride( x ); \ inc_t cs_x = bli_obj_col_stride( x ); \ void* buf_y = bli_obj_buffer_at_off( y ); \ inc_t rs_y = bli_obj_row_stride( y ); \ inc_t cs_y = bli_obj_col_stride( y ); \ \ void* buf_alpha; \ \ obj_t alpha_local; \ \ if ( bli_error_checking_is_enabled() ) \ PASTEMAC(opname,_check)( alpha, x, y ); \ \ /* Create local copy-casts of scalars (and apply internal conjugation as needed). */ \ bli_obj_scalar_init_detached_copy_of( dt, BLIS_NO_CONJUGATE, \ alpha, &alpha_local ); \ buf_alpha = bli_obj_buffer_for_1x1( dt, &alpha_local ); \ \ /* Query a type-specific function pointer, except one that uses void* for function arguments instead of typed pointers. */ \ PASTECH2(opname,BLIS_TAPI_EX_SUF,_vft) f = \ PASTEMAC2(opname,BLIS_TAPI_EX_SUF,_qfp)( dt ); \ \ f \ ( \ diagoffx, \ diagx, \ transx, \ m, \ n, \ buf_alpha, \ buf_x, rs_x, cs_x, \ buf_y, rs_y, cs_y, \ cntx, \ rntm \ ); \ } GENFRONT( axpyd ) GENFRONT( scal2d ) #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC(opname,EX_SUF) \ ( \ obj_t* x \ BLIS_OAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_OAPI_EX_DECLS \ \ num_t dt = bli_obj_dt( x ); \ \ doff_t diagoffx = bli_obj_diag_offset( x ); \ dim_t m = bli_obj_length( x ); \ dim_t n = bli_obj_width( x ); \ void* buf_x = bli_obj_buffer_at_off( x ); \ inc_t rs_x = bli_obj_row_stride( x ); \ inc_t cs_x = bli_obj_col_stride( x ); \ \ if ( bli_error_checking_is_enabled() ) \ PASTEMAC(opname,_check)( x ); \ \ /* Query a type-specific function pointer, except one that uses void* for function arguments instead of typed pointers. */ \ PASTECH2(opname,BLIS_TAPI_EX_SUF,_vft) f = \ PASTEMAC2(opname,BLIS_TAPI_EX_SUF,_qfp)( dt ); \ \ f \ ( \ diagoffx, \ m, \ n, \ buf_x, rs_x, cs_x, \ cntx, \ rntm \ ); \ } GENFRONT( invertd ) #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC(opname,EX_SUF) \ ( \ obj_t* alpha, \ obj_t* x \ BLIS_OAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_OAPI_EX_DECLS \ \ num_t dt = bli_obj_dt( x ); \ \ /* conj_t conjalpha = bli_obj_conj_status( alpha ); */ \ doff_t diagoffx = bli_obj_diag_offset( x ); \ dim_t m = bli_obj_length( x ); \ dim_t n = bli_obj_width( x ); \ void* buf_x = bli_obj_buffer_at_off( x ); \ inc_t rs_x = bli_obj_row_stride( x ); \ inc_t cs_x = bli_obj_col_stride( x ); \ \ void* buf_alpha; \ \ obj_t alpha_local; \ \ if ( bli_error_checking_is_enabled() ) \ PASTEMAC(opname,_check)( alpha, x ); \ \ /* Create local copy-casts of scalars (and apply internal conjugation as needed). */ \ bli_obj_scalar_init_detached_copy_of( dt, BLIS_NO_CONJUGATE, \ alpha, &alpha_local ); \ buf_alpha = bli_obj_buffer_for_1x1( dt, &alpha_local ); \ \ /* Query a type-specific function pointer, except one that uses void* for function arguments instead of typed pointers. */ \ PASTECH2(opname,BLIS_TAPI_EX_SUF,_vft) f = \ PASTEMAC2(opname,BLIS_TAPI_EX_SUF,_qfp)( dt ); \ \ f \ ( \ BLIS_NO_CONJUGATE, /* internal conjugation applied during copy-cast. */ \ diagoffx, \ m, \ n, \ buf_alpha, \ buf_x, rs_x, cs_x, \ cntx, \ rntm \ ); \ } GENFRONT( scald ) GENFRONT( setd ) #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC(opname,EX_SUF) \ ( \ obj_t* alpha, \ obj_t* x \ BLIS_OAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_OAPI_EX_DECLS \ \ num_t dt = bli_obj_dt( x ); \ \ doff_t diagoffx = bli_obj_diag_offset( x ); \ dim_t m = bli_obj_length( x ); \ dim_t n = bli_obj_width( x ); \ void* buf_x = bli_obj_buffer_at_off( x ); \ inc_t rs_x = bli_obj_row_stride( x ); \ inc_t cs_x = bli_obj_col_stride( x ); \ \ void* buf_alpha = bli_obj_buffer_for_1x1( dt, alpha ); \ \ if ( bli_error_checking_is_enabled() ) \ PASTEMAC(opname,_check)( alpha, x ); \ \ /* Query a type-specific function pointer, except one that uses void* for function arguments instead of typed pointers. */ \ PASTECH2(opname,BLIS_TAPI_EX_SUF,_vft) f = \ PASTEMAC2(opname,BLIS_TAPI_EX_SUF,_qfp)( dt ); \ \ f \ ( \ diagoffx, \ m, \ n, \ buf_alpha, \ buf_x, rs_x, cs_x, \ cntx, \ rntm \ ); \ } GENFRONT( setid ) #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC(opname,EX_SUF) \ ( \ obj_t* alpha, \ obj_t* x \ BLIS_OAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_OAPI_EX_DECLS \ \ num_t dt = bli_obj_dt( x ); \ \ doff_t diagoffx = bli_obj_diag_offset( x ); \ dim_t m = bli_obj_length( x ); \ dim_t n = bli_obj_width( x ); \ void* buf_x = bli_obj_buffer_at_off( x ); \ inc_t rs_x = bli_obj_row_stride( x ); \ inc_t cs_x = bli_obj_col_stride( x ); \ \ void* buf_alpha; \ \ obj_t alpha_local; \ \ if ( bli_error_checking_is_enabled() ) \ PASTEMAC(opname,_check)( alpha, x ); \ \ /* Create local copy-casts of scalars (and apply internal conjugation as needed). */ \ bli_obj_scalar_init_detached_copy_of( dt, BLIS_NO_CONJUGATE, \ alpha, &alpha_local ); \ buf_alpha = bli_obj_buffer_for_1x1( dt, &alpha_local ); \ \ /* Query a type-specific function pointer, except one that uses void* for function arguments instead of typed pointers. */ \ PASTECH2(opname,BLIS_TAPI_EX_SUF,_vft) f = \ PASTEMAC2(opname,BLIS_TAPI_EX_SUF,_qfp)( dt ); \ \ f \ ( \ diagoffx, \ m, \ n, \ buf_alpha, \ buf_x, rs_x, cs_x, \ cntx, \ rntm \ ); \ } GENFRONT( shiftd ) #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC(opname,EX_SUF) \ ( \ obj_t* x, \ obj_t* beta, \ obj_t* y \ BLIS_OAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_OAPI_EX_DECLS \ \ num_t dt = bli_obj_dt( x ); \ \ doff_t diagoffx = bli_obj_diag_offset( x ); \ diag_t diagx = bli_obj_diag( x ); \ trans_t transx = bli_obj_conjtrans_status( x ); \ dim_t m = bli_obj_length( y ); \ dim_t n = bli_obj_width( y ); \ void* buf_x = bli_obj_buffer_at_off( x ); \ inc_t rs_x = bli_obj_row_stride( x ); \ inc_t cs_x = bli_obj_col_stride( x ); \ void* buf_y = bli_obj_buffer_at_off( y ); \ inc_t rs_y = bli_obj_row_stride( y ); \ inc_t cs_y = bli_obj_col_stride( y ); \ \ void* buf_beta; \ \ obj_t beta_local; \ \ if ( bli_error_checking_is_enabled() ) \ PASTEMAC(opname,_check)( x, beta, y ); \ \ /* Create local copy-casts of scalars (and apply internal conjugation as needed). */ \ bli_obj_scalar_init_detached_copy_of( dt, BLIS_NO_CONJUGATE, \ beta, &beta_local ); \ buf_beta = bli_obj_buffer_for_1x1( dt, &beta_local ); \ \ /* Query a type-specific function pointer, except one that uses void* for function arguments instead of typed pointers. */ \ PASTECH2(opname,BLIS_TAPI_EX_SUF,_vft) f = \ PASTEMAC2(opname,BLIS_TAPI_EX_SUF,_qfp)( dt ); \ \ f \ ( \ diagoffx, \ diagx, \ transx, \ m, \ n, \ buf_x, rs_x, cs_x, \ buf_beta, \ buf_y, rs_y, cs_y, \ cntx, \ rntm \ ); \ } GENFRONT( xpbyd ) #endif blis-0.9.0/frame/1d/bli_l1d_oapi.h000066400000000000000000000055021422157504600165460ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype object-based interfaces. // #undef GENTPROT #define GENTPROT( opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC(opname,EX_SUF) \ ( \ obj_t* x, \ obj_t* y \ BLIS_OAPI_EX_PARAMS \ ); GENTPROT( addd ) GENTPROT( copyd ) GENTPROT( subd ) #undef GENTPROT #define GENTPROT( opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC(opname,EX_SUF) \ ( \ obj_t* alpha, \ obj_t* x, \ obj_t* y \ BLIS_OAPI_EX_PARAMS \ ); GENTPROT( axpyd ) GENTPROT( scal2d ) #undef GENTPROT #define GENTPROT( opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC(opname,EX_SUF) \ ( \ obj_t* x \ BLIS_OAPI_EX_PARAMS \ ); GENTPROT( invertd ) #undef GENTPROT #define GENTPROT( opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC(opname,EX_SUF) \ ( \ obj_t* alpha, \ obj_t* x \ BLIS_OAPI_EX_PARAMS \ ); GENTPROT( scald ) GENTPROT( setd ) GENTPROT( setid ) GENTPROT( shiftd ) #undef GENTPROT #define GENTPROT( opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC(opname,EX_SUF) \ ( \ obj_t* x, \ obj_t* beta, \ obj_t* y \ BLIS_OAPI_EX_PARAMS \ ); GENTPROT( xpbyd ) blis-0.9.0/frame/1d/bli_l1d_oapi_ba.c000066400000000000000000000036701422157504600172070ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // Include cpp macros that instantiate the API definition templates as // omitting expert parameters. #include "bli_oapi_ba.h" // Define the macro protecting the object API definitions. #define BLIS_ENABLE_OAPI // Include the object API definitions here. #include "bli_l1d_oapi.c" blis-0.9.0/frame/1d/bli_l1d_oapi_ex.c000066400000000000000000000036661422157504600172460ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // Include cpp macros that instantiate the API definition templates as // having expert parameters. #include "bli_oapi_ex.h" // Define the macro protecting the object API definitions. #define BLIS_ENABLE_OAPI // Include the object API definitions here. #include "bli_l1d_oapi.c" blis-0.9.0/frame/1d/bli_l1d_tapi.c000066400000000000000000000321051422157504600165450ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // Guard the function definitions so that they are only compiled when // #included from files that define the typed API macros. #ifdef BLIS_ENABLE_TAPI // // Define BLAS-like interfaces with typed operands. // #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, kername, kerid ) \ \ void PASTEMAC2(ch,opname,EX_SUF) \ ( \ doff_t diagoffx, \ diag_t diagx, \ trans_t transx, \ dim_t m, \ dim_t n, \ ctype* x, inc_t rs_x, inc_t cs_x, \ ctype* y, inc_t rs_y, inc_t cs_y \ BLIS_TAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_TAPI_EX_DECLS \ \ const num_t dt = PASTEMAC(ch,type); \ \ ctype* x1; \ ctype* y1; \ conj_t conjx; \ dim_t n_elem; \ dim_t offx, offy; \ inc_t incx, incy; \ \ if ( bli_zero_dim2( m, n ) ) return; \ \ if ( bli_is_outside_diag( diagoffx, transx, m, n ) ) return; \ \ /* Determine the distance to the diagonals, the number of diagonal elements, and the diagonal increments. */ \ bli_set_dims_incs_2d \ ( \ diagoffx, transx, \ m, n, rs_x, cs_x, rs_y, cs_y, \ &offx, &offy, &n_elem, &incx, &incy \ ); \ \ conjx = bli_extract_conj( transx ); \ \ if ( bli_is_nonunit_diag( diagx ) ) \ { \ x1 = x + offx; \ y1 = y + offy; \ } \ else /* if ( bli_is_unit_diag( diagx ) ) */ \ { \ /* Simulate a unit diagonal for x with a zero increment over a unit scalar. */ \ x1 = PASTEMAC(ch,1); \ incx = 0; \ y1 = y + offy; \ } \ \ /* Obtain a valid context from the gks if necessary. */ \ if ( cntx == NULL ) cntx = bli_gks_query_cntx(); \ \ /* Query the context for the operation's kernel address. */ \ PASTECH2(ch,kername,_ker_ft) f = bli_cntx_get_l1v_ker_dt( dt, kerid, cntx ); \ \ /* Invoke the kernel with the appropriate parameters. */ \ f( \ conjx, \ n_elem, \ x1, incx, \ y1, incy, \ cntx \ ); \ } INSERT_GENTFUNC_BASIC2( addd, addv, BLIS_ADDV_KER ) INSERT_GENTFUNC_BASIC2( copyd, copyv, BLIS_COPYV_KER ) INSERT_GENTFUNC_BASIC2( subd, subv, BLIS_SUBV_KER ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, kername, kerid ) \ \ void PASTEMAC2(ch,opname,EX_SUF) \ ( \ doff_t diagoffx, \ diag_t diagx, \ trans_t transx, \ dim_t m, \ dim_t n, \ ctype* alpha, \ ctype* x, inc_t rs_x, inc_t cs_x, \ ctype* y, inc_t rs_y, inc_t cs_y \ BLIS_TAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_TAPI_EX_DECLS \ \ const num_t dt = PASTEMAC(ch,type); \ \ ctype* x1; \ ctype* y1; \ conj_t conjx; \ dim_t n_elem; \ dim_t offx, offy; \ inc_t incx, incy; \ \ if ( bli_zero_dim2( m, n ) ) return; \ \ if ( bli_is_outside_diag( diagoffx, transx, m, n ) ) return; \ \ /* Determine the distance to the diagonals, the number of diagonal elements, and the diagonal increments. */ \ bli_set_dims_incs_2d \ ( \ diagoffx, transx, \ m, n, rs_x, cs_x, rs_y, cs_y, \ &offx, &offy, &n_elem, &incx, &incy \ ); \ \ conjx = bli_extract_conj( transx ); \ \ if ( bli_is_nonunit_diag( diagx ) ) \ { \ x1 = x + offx; \ y1 = y + offy; \ } \ else /* if ( bli_is_unit_diag( diagx ) ) */ \ { \ /* Simulate a unit diagonal for x with a zero increment over a unit scalar. */ \ x1 = PASTEMAC(ch,1); \ incx = 0; \ y1 = y + offy; \ } \ \ /* Obtain a valid context from the gks if necessary. */ \ if ( cntx == NULL ) cntx = bli_gks_query_cntx(); \ \ /* Query the context for the operation's kernel address. */ \ PASTECH2(ch,kername,_ker_ft) f = bli_cntx_get_l1v_ker_dt( dt, kerid, cntx ); \ \ /* Invoke the kernel with the appropriate parameters. */ \ f( \ conjx, \ n_elem, \ alpha, \ x1, incx, \ y1, incy, \ cntx \ ); \ } INSERT_GENTFUNC_BASIC2( axpyd, axpyv, BLIS_AXPYV_KER ) INSERT_GENTFUNC_BASIC2( scal2d, scal2v, BLIS_SCAL2V_KER ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, kername, kerid ) \ \ void PASTEMAC2(ch,opname,EX_SUF) \ ( \ doff_t diagoffx, \ dim_t m, \ dim_t n, \ ctype* x, inc_t rs_x, inc_t cs_x \ BLIS_TAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_TAPI_EX_DECLS \ \ const num_t dt = PASTEMAC(ch,type); \ \ ctype* x1; \ dim_t n_elem; \ dim_t offx; \ inc_t incx; \ \ if ( bli_zero_dim2( m, n ) ) return; \ \ if ( bli_is_outside_diag( diagoffx, BLIS_NO_TRANSPOSE, m, n ) ) return; \ \ /* Determine the distance to the diagonals, the number of diagonal elements, and the diagonal increments. */ \ bli_set_dims_incs_1d \ ( \ diagoffx, \ m, n, rs_x, cs_x, \ &offx, &n_elem, &incx \ ); \ \ x1 = x + offx; \ \ /* Obtain a valid context from the gks if necessary. */ \ if ( cntx == NULL ) cntx = bli_gks_query_cntx(); \ \ /* Query the context for the operation's kernel address. */ \ PASTECH2(ch,kername,_ker_ft) f = bli_cntx_get_l1v_ker_dt( dt, kerid, cntx ); \ \ /* Invoke the kernel with the appropriate parameters. */ \ f( \ n_elem, \ x1, incx, \ cntx \ ); \ } INSERT_GENTFUNC_BASIC2( invertd, invertv, BLIS_INVERTV_KER ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, kername, kerid ) \ \ void PASTEMAC2(ch,opname,EX_SUF) \ ( \ conj_t conjalpha, \ doff_t diagoffx, \ dim_t m, \ dim_t n, \ ctype* alpha, \ ctype* x, inc_t rs_x, inc_t cs_x \ BLIS_TAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_TAPI_EX_DECLS \ \ const num_t dt = PASTEMAC(ch,type); \ \ ctype* x1; \ dim_t n_elem; \ dim_t offx; \ inc_t incx; \ \ if ( bli_zero_dim2( m, n ) ) return; \ \ if ( bli_is_outside_diag( diagoffx, BLIS_NO_TRANSPOSE, m, n ) ) return; \ \ /* Determine the distance to the diagonals, the number of diagonal elements, and the diagonal increments. */ \ bli_set_dims_incs_1d \ ( \ diagoffx, \ m, n, rs_x, cs_x, \ &offx, &n_elem, &incx \ ); \ \ x1 = x + offx; \ \ /* Obtain a valid context from the gks if necessary. */ \ if ( cntx == NULL ) cntx = bli_gks_query_cntx(); \ \ /* Query the context for the operation's kernel address. */ \ PASTECH2(ch,kername,_ker_ft) f = bli_cntx_get_l1v_ker_dt( dt, kerid, cntx ); \ \ /* Invoke the kernel with the appropriate parameters. */ \ f( \ conjalpha, \ n_elem, \ alpha, \ x1, incx, \ cntx \ ); \ } INSERT_GENTFUNC_BASIC2( scald, scalv, BLIS_SCALV_KER ) INSERT_GENTFUNC_BASIC2( setd, setv, BLIS_SETV_KER ) #undef GENTFUNCR #define GENTFUNCR( ctype, ctype_r, ch, chr, opname, kername, kerid ) \ \ void PASTEMAC2(ch,opname,EX_SUF) \ ( \ doff_t diagoffx, \ dim_t m, \ dim_t n, \ ctype_r* alpha, \ ctype* x, inc_t rs_x, inc_t cs_x \ BLIS_TAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_TAPI_EX_DECLS \ \ const num_t dt = PASTEMAC(ch,type); \ const num_t dt_r = PASTEMAC(chr,type); \ \ ctype_r* x1; \ dim_t n_elem; \ dim_t offx; \ inc_t incx; \ \ /* If the datatype is real, the entire operation is a no-op. */ \ if ( bli_is_real( dt ) ) return; \ \ if ( bli_zero_dim2( m, n ) ) return; \ \ if ( bli_is_outside_diag( diagoffx, BLIS_NO_TRANSPOSE, m, n ) ) return; \ \ /* Determine the distance to the diagonals, the number of diagonal elements, and the diagonal increments. */ \ bli_set_dims_incs_1d \ ( \ diagoffx, \ m, n, rs_x, cs_x, \ &offx, &n_elem, &incx \ ); \ \ /* Alternate implementation. (Substitute for remainder of function). */ \ /* for ( i = 0; i < n_elem; ++i ) \ { \ ctype* chi11 = x1 + (i )*incx; \ \ PASTEMAC(ch,setis)( *alpha, *chi11 ); \ } */ \ \ /* Acquire the addres of the imaginary component of the first element, and scale the increment for use in the real domain. Note that the indexing into the imaginary field only needs to work for complex datatypes since we return early for real domain types. */ \ x1 = ( ctype_r* )( x + offx ) + 1; \ incx = 2*incx; \ \ /* Obtain a valid context from the gks if necessary. */ \ if ( cntx == NULL ) cntx = bli_gks_query_cntx(); \ \ /* Query the context for the operation's kernel address. */ \ PASTECH2(chr,kername,_ker_ft) f = bli_cntx_get_l1v_ker_dt( dt_r, kerid, cntx ); \ \ /* Invoke the kernel with the appropriate parameters. */ \ f( \ BLIS_NO_CONJUGATE, \ n_elem, \ alpha, \ x1, incx, \ cntx \ ); \ } INSERT_GENTFUNCR_BASIC2( setid, setv, BLIS_SETV_KER ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, kername, kerid ) \ \ void PASTEMAC2(ch,opname,EX_SUF) \ ( \ doff_t diagoffx, \ dim_t m, \ dim_t n, \ ctype* alpha, \ ctype* x, inc_t rs_x, inc_t cs_x \ BLIS_TAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_TAPI_EX_DECLS \ \ const num_t dt = PASTEMAC(ch,type); \ \ ctype* x1; \ dim_t n_elem; \ dim_t offx; \ inc_t incx; \ \ if ( bli_zero_dim2( m, n ) ) return; \ \ if ( bli_is_outside_diag( diagoffx, BLIS_NO_TRANSPOSE, m, n ) ) return; \ \ /* Determine the distance to the diagonals, the number of diagonal elements, and the diagonal increments. */ \ bli_set_dims_incs_1d \ ( \ diagoffx, \ m, n, rs_x, cs_x, \ &offx, &n_elem, &incx \ ); \ \ x1 = x + offx; \ \ /* Obtain a valid context from the gks if necessary. */ \ if ( cntx == NULL ) cntx = bli_gks_query_cntx(); \ \ /* Query the context for the operation's kernel address. */ \ PASTECH2(ch,kername,_ker_ft) f = bli_cntx_get_l1v_ker_dt( dt, kerid, cntx ); \ \ /* Invoke the kernel with the appropriate parameters. */ \ f( \ BLIS_NO_CONJUGATE, \ n_elem, \ alpha, 0, \ x1, incx, \ cntx \ ); \ } INSERT_GENTFUNC_BASIC2( shiftd, addv, BLIS_ADDV_KER ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, kername, kerid ) \ \ void PASTEMAC2(ch,opname,EX_SUF) \ ( \ doff_t diagoffx, \ diag_t diagx, \ trans_t transx, \ dim_t m, \ dim_t n, \ ctype* x, inc_t rs_x, inc_t cs_x, \ ctype* beta, \ ctype* y, inc_t rs_y, inc_t cs_y \ BLIS_TAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_TAPI_EX_DECLS \ \ const num_t dt = PASTEMAC(ch,type); \ \ ctype* x1; \ ctype* y1; \ conj_t conjx; \ dim_t n_elem; \ dim_t offx, offy; \ inc_t incx, incy; \ \ if ( bli_zero_dim2( m, n ) ) return; \ \ if ( bli_is_outside_diag( diagoffx, transx, m, n ) ) return; \ \ /* Determine the distance to the diagonals, the number of diagonal elements, and the diagonal increments. */ \ bli_set_dims_incs_2d \ ( \ diagoffx, transx, \ m, n, rs_x, cs_x, rs_y, cs_y, \ &offx, &offy, &n_elem, &incx, &incy \ ); \ \ conjx = bli_extract_conj( transx ); \ \ if ( bli_is_nonunit_diag( diagx ) ) \ { \ x1 = x + offx; \ y1 = y + offy; \ } \ else /* if ( bli_is_unit_diag( diagx ) ) */ \ { \ /* Simulate a unit diagonal for x with a zero increment over a unit scalar. */ \ x1 = PASTEMAC(ch,1); \ incx = 0; \ y1 = y + offy; \ } \ \ /* Obtain a valid context from the gks if necessary. */ \ if ( cntx == NULL ) cntx = bli_gks_query_cntx(); \ \ /* Query the context for the operation's kernel address. */ \ PASTECH2(ch,kername,_ker_ft) f = bli_cntx_get_l1v_ker_dt( dt, kerid, cntx ); \ \ /* Invoke the kernel with the appropriate parameters. */ \ f( \ conjx, \ n_elem, \ x1, incx, \ beta, \ y1, incy, \ cntx \ ); \ } INSERT_GENTFUNC_BASIC2( xpbyd, xpbyv, BLIS_XPBYV_KER ) #endif blis-0.9.0/frame/1d/bli_l1d_tapi.h000066400000000000000000000105301422157504600165500ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype BLAS-like interfaces with typed operands. // #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC2(ch,opname,EX_SUF) \ ( \ doff_t diagoffx, \ diag_t diagx, \ trans_t transx, \ dim_t m, \ dim_t n, \ ctype* x, inc_t rs_x, inc_t cs_x, \ ctype* y, inc_t rs_y, inc_t cs_y \ BLIS_TAPI_EX_PARAMS \ ); INSERT_GENTPROT_BASIC0( addd ) INSERT_GENTPROT_BASIC0( copyd ) INSERT_GENTPROT_BASIC0( subd ) #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC2(ch,opname,EX_SUF) \ ( \ doff_t diagoffx, \ diag_t diagx, \ trans_t transx, \ dim_t m, \ dim_t n, \ ctype* alpha, \ ctype* x, inc_t rs_x, inc_t cs_x, \ ctype* y, inc_t rs_y, inc_t cs_y \ BLIS_TAPI_EX_PARAMS \ ); INSERT_GENTPROT_BASIC0( axpyd ) INSERT_GENTPROT_BASIC0( scal2d ) #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC2(ch,opname,EX_SUF) \ ( \ doff_t diagoffx, \ dim_t m, \ dim_t n, \ ctype* x, inc_t rs_x, inc_t cs_x \ BLIS_TAPI_EX_PARAMS \ ); INSERT_GENTPROT_BASIC0( invertd ) #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC2(ch,opname,EX_SUF) \ ( \ conj_t conjalpha, \ doff_t diagoffx, \ dim_t m, \ dim_t n, \ ctype* alpha, \ ctype* x, inc_t rs_x, inc_t cs_x \ BLIS_TAPI_EX_PARAMS \ ); INSERT_GENTPROT_BASIC0( scald ) INSERT_GENTPROT_BASIC0( setd ) #undef GENTPROTR #define GENTPROTR( ctype, ctype_r, ch, chr, opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC2(ch,opname,EX_SUF) \ ( \ doff_t diagoffx, \ dim_t m, \ dim_t n, \ ctype_r* alpha, \ ctype* x, inc_t rs_x, inc_t cs_x \ BLIS_TAPI_EX_PARAMS \ ); INSERT_GENTPROTR_BASIC0( setid ) #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC2(ch,opname,EX_SUF) \ ( \ doff_t diagoffx, \ dim_t m, \ dim_t n, \ ctype* alpha, \ ctype* x, inc_t rs_x, inc_t cs_x \ BLIS_TAPI_EX_PARAMS \ ); INSERT_GENTPROT_BASIC0( shiftd ) #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC2(ch,opname,EX_SUF) \ ( \ doff_t diagoffx, \ diag_t diagx, \ trans_t transx, \ dim_t m, \ dim_t n, \ ctype* x, inc_t rs_x, inc_t cs_x, \ ctype* beta, \ ctype* y, inc_t rs_y, inc_t cs_y \ BLIS_TAPI_EX_PARAMS \ ); INSERT_GENTPROT_BASIC0( xpbyd ) blis-0.9.0/frame/1d/bli_l1d_tapi_ba.c000066400000000000000000000036661422157504600172210ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // Include cpp macros that instantiate the API definition templates as // omitting expert parameters. #include "bli_tapi_ba.h" // Define the macro protecting the typed API definitions. #define BLIS_ENABLE_TAPI // Include the typed API definitions here. #include "bli_l1d_tapi.c" blis-0.9.0/frame/1d/bli_l1d_tapi_ex.c000066400000000000000000000036641422157504600172510ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // Include cpp macros that instantiate the API definition templates as // having expert parameters. #include "bli_tapi_ex.h" // Define the macro protecting the typed API definitions. #define BLIS_ENABLE_TAPI // Include the typed API definitions here. #include "bli_l1d_tapi.c" blis-0.9.0/frame/1f/000077500000000000000000000000001422157504600140575ustar00rootroot00000000000000blis-0.9.0/frame/1f/bli_l1f.h000066400000000000000000000044261422157504600155460ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "bli_l1f_check.h" // Define kernel function types. #include "bli_l1f_ft_ker.h" // Prototype object APIs (expert and non-expert). #include "bli_oapi_ex.h" #include "bli_l1f_oapi.h" #include "bli_xapi_undef.h" #include "bli_oapi_ba.h" #include "bli_l1f_oapi.h" #include "bli_xapi_undef.h" // Prototype typed APIs (expert and non-expert). #include "bli_tapi_ex.h" #include "bli_l1f_tapi.h" #include "bli_l1f_ft.h" #include "bli_xapi_undef.h" #include "bli_tapi_ba.h" #include "bli_l1f_tapi.h" #include "bli_l1f_ft.h" #include "bli_xapi_undef.h" // Generate function pointer arrays for tapi functions (expert only). #include "bli_l1f_fpa.h" blis-0.9.0/frame/1f/bli_l1f_check.c000066400000000000000000000303741422157504600166770ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // Define object-based check functions. // void bli_axpy2v_check ( obj_t* alphax, obj_t* alphay, obj_t* x, obj_t* y, obj_t* z ) { err_t e_val; // Check object datatypes. e_val = bli_check_noninteger_object( alphax ); bli_check_error_code( e_val ); e_val = bli_check_noninteger_object( alphay ); bli_check_error_code( e_val ); e_val = bli_check_floating_object( x ); bli_check_error_code( e_val ); e_val = bli_check_floating_object( y ); bli_check_error_code( e_val ); e_val = bli_check_floating_object( z ); bli_check_error_code( e_val ); // Check for consistent datatypes. e_val = bli_check_consistent_object_datatypes( x, y ); bli_check_error_code( e_val ); e_val = bli_check_consistent_object_datatypes( x, z ); bli_check_error_code( e_val ); // Check object dimensions. e_val = bli_check_scalar_object( alphax ); bli_check_error_code( e_val ); e_val = bli_check_scalar_object( alphay ); bli_check_error_code( e_val ); e_val = bli_check_vector_object( x ); bli_check_error_code( e_val ); e_val = bli_check_vector_object( y ); bli_check_error_code( e_val ); e_val = bli_check_vector_object( z ); bli_check_error_code( e_val ); e_val = bli_check_equal_vector_lengths( x, y ); bli_check_error_code( e_val ); e_val = bli_check_equal_vector_lengths( x, z ); bli_check_error_code( e_val ); // Check object buffers (for non-NULLness). e_val = bli_check_object_buffer( alphax ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( alphay ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( x ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( y ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( z ); bli_check_error_code( e_val ); } void bli_axpyf_check ( obj_t* alpha, obj_t* a, obj_t* x, obj_t* y ) { err_t e_val; // Check object datatypes. e_val = bli_check_noninteger_object( alpha ); bli_check_error_code( e_val ); e_val = bli_check_floating_object( a ); bli_check_error_code( e_val ); e_val = bli_check_floating_object( x ); bli_check_error_code( e_val ); e_val = bli_check_floating_object( y ); bli_check_error_code( e_val ); // Check for consistent datatypes. e_val = bli_check_consistent_object_datatypes( a, x ); bli_check_error_code( e_val ); e_val = bli_check_consistent_object_datatypes( a, y ); bli_check_error_code( e_val ); // Check object dimensions. e_val = bli_check_scalar_object( alpha ); bli_check_error_code( e_val ); e_val = bli_check_matrix_object( a ); bli_check_error_code( e_val ); e_val = bli_check_vector_object( x ); bli_check_error_code( e_val ); e_val = bli_check_vector_object( y ); bli_check_error_code( e_val ); e_val = bli_check_vector_dim_equals( x, bli_obj_width_after_trans( a ) ); bli_check_error_code( e_val ); e_val = bli_check_vector_dim_equals( y, bli_obj_length_after_trans( a ) ); bli_check_error_code( e_val ); // Check object buffers (for non-NULLness). e_val = bli_check_object_buffer( alpha ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( a ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( x ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( y ); bli_check_error_code( e_val ); } void bli_dotaxpyv_check ( obj_t* alpha, obj_t* xt, obj_t* x, obj_t* y, obj_t* rho, obj_t* z ) { err_t e_val; // Check object datatypes. e_val = bli_check_noninteger_object( alpha ); bli_check_error_code( e_val ); e_val = bli_check_floating_object( xt ); bli_check_error_code( e_val ); e_val = bli_check_floating_object( x ); bli_check_error_code( e_val ); e_val = bli_check_floating_object( y ); bli_check_error_code( e_val ); e_val = bli_check_noninteger_object( rho ); bli_check_error_code( e_val ); e_val = bli_check_nonconstant_object( rho ); bli_check_error_code( e_val ); e_val = bli_check_floating_object( z ); bli_check_error_code( e_val ); // Check for consistent datatypes. e_val = bli_check_consistent_object_datatypes( x, xt ); bli_check_error_code( e_val ); e_val = bli_check_consistent_object_datatypes( x, y ); bli_check_error_code( e_val ); e_val = bli_check_consistent_object_datatypes( x, z ); bli_check_error_code( e_val ); // Check object dimensions. e_val = bli_check_scalar_object( alpha ); bli_check_error_code( e_val ); e_val = bli_check_vector_object( xt ); bli_check_error_code( e_val ); e_val = bli_check_vector_object( x ); bli_check_error_code( e_val ); e_val = bli_check_vector_object( y ); bli_check_error_code( e_val ); e_val = bli_check_scalar_object( rho ); bli_check_error_code( e_val ); e_val = bli_check_vector_object( z ); bli_check_error_code( e_val ); e_val = bli_check_equal_vector_lengths( x, xt ); bli_check_error_code( e_val ); e_val = bli_check_equal_vector_lengths( x, y ); bli_check_error_code( e_val ); e_val = bli_check_equal_vector_lengths( x, z ); bli_check_error_code( e_val ); // Check object aliases. e_val = bli_check_object_alias_of( xt, x ); bli_check_error_code( e_val ); // Check object buffers (for non-NULLness). e_val = bli_check_object_buffer( alpha ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( xt ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( x ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( y ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( rho ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( z ); bli_check_error_code( e_val ); } void bli_dotxaxpyf_check ( obj_t* alpha, obj_t* at, obj_t* a, obj_t* w, obj_t* x, obj_t* beta, obj_t* y, obj_t* z ) { err_t e_val; // Check object datatypes. e_val = bli_check_noninteger_object( alpha ); bli_check_error_code( e_val ); e_val = bli_check_floating_object( at ); bli_check_error_code( e_val ); e_val = bli_check_floating_object( a ); bli_check_error_code( e_val ); e_val = bli_check_floating_object( w ); bli_check_error_code( e_val ); e_val = bli_check_floating_object( x ); bli_check_error_code( e_val ); e_val = bli_check_noninteger_object( beta ); bli_check_error_code( e_val ); e_val = bli_check_floating_object( y ); bli_check_error_code( e_val ); e_val = bli_check_floating_object( z ); bli_check_error_code( e_val ); // Check for consistent datatypes. e_val = bli_check_consistent_object_datatypes( a, at ); bli_check_error_code( e_val ); e_val = bli_check_consistent_object_datatypes( a, w ); bli_check_error_code( e_val ); e_val = bli_check_consistent_object_datatypes( a, x ); bli_check_error_code( e_val ); e_val = bli_check_consistent_object_datatypes( a, y ); bli_check_error_code( e_val ); e_val = bli_check_consistent_object_datatypes( a, z ); bli_check_error_code( e_val ); // Check object dimensions. e_val = bli_check_scalar_object( alpha ); bli_check_error_code( e_val ); e_val = bli_check_matrix_object( at ); bli_check_error_code( e_val ); e_val = bli_check_matrix_object( a ); bli_check_error_code( e_val ); e_val = bli_check_vector_object( w ); bli_check_error_code( e_val ); e_val = bli_check_vector_object( x ); bli_check_error_code( e_val ); e_val = bli_check_scalar_object( beta ); bli_check_error_code( e_val ); e_val = bli_check_vector_object( y ); bli_check_error_code( e_val ); e_val = bli_check_vector_object( z ); bli_check_error_code( e_val ); e_val = bli_check_equal_vector_lengths( w, z ); bli_check_error_code( e_val ); e_val = bli_check_equal_vector_lengths( x, y ); bli_check_error_code( e_val ); e_val = bli_check_conformal_dims( at, a ); bli_check_error_code( e_val ); e_val = bli_check_object_length_equals( at, bli_obj_vector_dim( w ) ); bli_check_error_code( e_val ); e_val = bli_check_object_width_equals( at, bli_obj_vector_dim( y ) ); bli_check_error_code( e_val ); e_val = bli_check_object_length_equals( a, bli_obj_vector_dim( z ) ); bli_check_error_code( e_val ); e_val = bli_check_object_width_equals( a, bli_obj_vector_dim( x ) ); bli_check_error_code( e_val ); // Check object aliases. e_val = bli_check_object_alias_of( at, a ); bli_check_error_code( e_val ); // Check object buffers (for non-NULLness). e_val = bli_check_object_buffer( alpha ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( at ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( a ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( w ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( x ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( beta ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( y ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( z ); bli_check_error_code( e_val ); } void bli_dotxf_check ( obj_t* alpha, obj_t* a, obj_t* x, obj_t* beta, obj_t* y ) { err_t e_val; // Check object datatypes. e_val = bli_check_noninteger_object( alpha ); bli_check_error_code( e_val ); e_val = bli_check_floating_object( a ); bli_check_error_code( e_val ); e_val = bli_check_floating_object( x ); bli_check_error_code( e_val ); e_val = bli_check_noninteger_object( beta ); bli_check_error_code( e_val ); e_val = bli_check_floating_object( y ); bli_check_error_code( e_val ); // Check for consistent datatypes. e_val = bli_check_consistent_object_datatypes( a, x ); bli_check_error_code( e_val ); e_val = bli_check_consistent_object_datatypes( a, y ); bli_check_error_code( e_val ); // Check object dimensions. e_val = bli_check_scalar_object( alpha ); bli_check_error_code( e_val ); e_val = bli_check_matrix_object( a ); bli_check_error_code( e_val ); e_val = bli_check_vector_object( x ); bli_check_error_code( e_val ); e_val = bli_check_scalar_object( beta ); bli_check_error_code( e_val ); e_val = bli_check_vector_object( y ); bli_check_error_code( e_val ); e_val = bli_check_vector_dim_equals( x, bli_obj_length_after_trans( a ) ); bli_check_error_code( e_val ); e_val = bli_check_vector_dim_equals( y, bli_obj_width_after_trans( a ) ); bli_check_error_code( e_val ); // Check object buffers (for non-NULLness). e_val = bli_check_object_buffer( alpha ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( a ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( x ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( beta ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( y ); bli_check_error_code( e_val ); } blis-0.9.0/frame/1f/bli_l1f_check.h000066400000000000000000000055331422157504600167030ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype object-based check functions. // #undef GENTPROT #define GENTPROT( opname ) \ \ void PASTEMAC(opname,_check) \ ( \ obj_t* alphax, \ obj_t* alphay, \ obj_t* x, \ obj_t* y, \ obj_t* z \ ); GENTPROT( axpy2v ) #undef GENTPROT #define GENTPROT( opname ) \ \ void PASTEMAC(opname,_check) \ ( \ obj_t* alpha, \ obj_t* a, \ obj_t* x, \ obj_t* y \ ); GENTPROT( axpyf ) #undef GENTPROT #define GENTPROT( opname ) \ \ void PASTEMAC(opname,_check) \ ( \ obj_t* alpha, \ obj_t* xt, \ obj_t* x, \ obj_t* y, \ obj_t* rho, \ obj_t* z \ ); GENTPROT( dotaxpyv ) #undef GENTPROT #define GENTPROT( opname ) \ \ void PASTEMAC(opname,_check) \ ( \ obj_t* alpha, \ obj_t* at, \ obj_t* a, \ obj_t* w, \ obj_t* x, \ obj_t* beta, \ obj_t* y, \ obj_t* z \ ); GENTPROT( dotxaxpyf ) #undef GENTPROT #define GENTPROT( opname ) \ \ void PASTEMAC(opname,_check) \ ( \ obj_t* alpha, \ obj_t* a, \ obj_t* x, \ obj_t* beta, \ obj_t* y \ ); GENTPROT( dotxf ) blis-0.9.0/frame/1f/bli_l1f_fpa.c000066400000000000000000000041571422157504600163700ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // Define function pointer query interfaces. // #undef GENFRONT #define GENFRONT( opname ) \ \ GENARRAY_FPA( PASTECH2(opname,BLIS_TAPI_EX_SUF,_vft), \ PASTECH(opname,BLIS_TAPI_EX_SUF) ); \ \ PASTECH2(opname,BLIS_TAPI_EX_SUF,_vft) \ PASTEMAC2(opname,BLIS_TAPI_EX_SUF,_qfp)( num_t dt ) \ { \ return PASTECH2(opname,BLIS_TAPI_EX_SUF,_fpa)[ dt ]; \ } GENFRONT( axpy2v ) GENFRONT( axpyf ) GENFRONT( dotaxpyv ) GENFRONT( dotxaxpyf ) GENFRONT( dotxf ) blis-0.9.0/frame/1f/bli_l1f_fpa.h000066400000000000000000000036521422157504600163740ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype function pointer query interface. // #undef GENPROT #define GENPROT( opname ) \ \ PASTECH2(opname,BLIS_TAPI_EX_SUF,_vft) \ PASTEMAC2(opname,BLIS_TAPI_EX_SUF,_qfp)( num_t dt ); GENPROT( axpy2v ) GENPROT( axpyf ) GENPROT( dotaxpyv ) GENPROT( dotxaxpyf ) GENPROT( dotxf ) blis-0.9.0/frame/1f/bli_l1f_ft.h000066400000000000000000000076771422157504600162520ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // -- Level-1f function types -------------------------------------------------- // // axpy2v #undef GENTDEF #define GENTDEF( ctype, ch, opname, tsuf ) \ \ typedef void (*PASTECH3(ch,opname,EX_SUF,tsuf)) \ ( \ conj_t conjx, \ conj_t conjy, \ dim_t n, \ ctype* alpha1, \ ctype* alpha2, \ ctype* x, inc_t incx, \ ctype* y, inc_t incy, \ ctype* z, inc_t incz \ BLIS_TAPI_EX_PARAMS \ ); INSERT_GENTDEF( axpy2v ) // axpyf #undef GENTDEF #define GENTDEF( ctype, ch, opname, tsuf ) \ \ typedef void (*PASTECH3(ch,opname,EX_SUF,tsuf)) \ ( \ conj_t conja, \ conj_t conjx, \ dim_t m, \ dim_t b_n, \ ctype* alpha, \ ctype* a, inc_t inca, inc_t lda, \ ctype* x, inc_t incx, \ ctype* y, inc_t incy \ BLIS_TAPI_EX_PARAMS \ ); INSERT_GENTDEF( axpyf ) // dotaxpyv #undef GENTDEF #define GENTDEF( ctype, ch, opname, tsuf ) \ \ typedef void (*PASTECH3(ch,opname,EX_SUF,tsuf)) \ ( \ conj_t conjxt, \ conj_t conjx, \ conj_t conjy, \ dim_t m, \ ctype* alpha, \ ctype* x, inc_t incx, \ ctype* y, inc_t incy, \ ctype* rho, \ ctype* z, inc_t incz \ BLIS_TAPI_EX_PARAMS \ ); INSERT_GENTDEF( dotaxpyv ) // dotxf #undef GENTDEF #define GENTDEF( ctype, ch, opname, tsuf ) \ \ typedef void (*PASTECH3(ch,opname,EX_SUF,tsuf)) \ ( \ conj_t conjat, \ conj_t conjx, \ dim_t m, \ dim_t b_n, \ ctype* alpha, \ ctype* a, inc_t inca, inc_t lda, \ ctype* x, inc_t incx, \ ctype* beta, \ ctype* y, inc_t incy \ BLIS_TAPI_EX_PARAMS \ ); INSERT_GENTDEF( dotxf ) // dotxaxpyf #undef GENTDEF #define GENTDEF( ctype, ch, opname, tsuf ) \ \ typedef void (*PASTECH3(ch,opname,EX_SUF,tsuf)) \ ( \ conj_t conjat, \ conj_t conja, \ conj_t conjw, \ conj_t conjx, \ dim_t m, \ dim_t b_n, \ ctype* alpha, \ ctype* a, inc_t inca, inc_t lda, \ ctype* w, inc_t incw, \ ctype* x, inc_t incx, \ ctype* beta, \ ctype* y, inc_t incy, \ ctype* z, inc_t incz \ BLIS_TAPI_EX_PARAMS \ ); INSERT_GENTDEF( dotxaxpyf ) blis-0.9.0/frame/1f/bli_l1f_ft_ker.h000066400000000000000000000105601422157504600170740ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_L1F_FT_KER_H #define BLIS_L1F_FT_KER_H // // -- Level-1f kernel function types ------------------------------------------- // // axpy2v #undef GENTDEF #define GENTDEF( ctype, ch, opname, tsuf ) \ \ typedef void (*PASTECH3(ch,opname,_ker,tsuf)) \ ( \ conj_t conjx, \ conj_t conjy, \ dim_t n, \ ctype* restrict alpha1, \ ctype* restrict alpha2, \ ctype* restrict x, inc_t incx, \ ctype* restrict y, inc_t incy, \ ctype* restrict z, inc_t incz, \ cntx_t* cntx \ ); INSERT_GENTDEF( axpy2v ) // axpyf #undef GENTDEF #define GENTDEF( ctype, ch, opname, tsuf ) \ \ typedef void (*PASTECH3(ch,opname,_ker,tsuf)) \ ( \ conj_t conja, \ conj_t conjx, \ dim_t m, \ dim_t b_n, \ ctype* restrict alpha, \ ctype* restrict a, inc_t inca, inc_t lda, \ ctype* restrict x, inc_t incx, \ ctype* restrict y, inc_t incy, \ cntx_t* cntx \ ); INSERT_GENTDEF( axpyf ) // dotaxpyv #undef GENTDEF #define GENTDEF( ctype, ch, opname, tsuf ) \ \ typedef void (*PASTECH3(ch,opname,_ker,tsuf)) \ ( \ conj_t conjxt, \ conj_t conjx, \ conj_t conjy, \ dim_t m, \ ctype* restrict alpha, \ ctype* restrict x, inc_t incx, \ ctype* restrict y, inc_t incy, \ ctype* restrict rho, \ ctype* restrict z, inc_t incz, \ cntx_t* cntx \ ); INSERT_GENTDEF( dotaxpyv ) // dotxf #undef GENTDEF #define GENTDEF( ctype, ch, opname, tsuf ) \ \ typedef void (*PASTECH3(ch,opname,_ker,tsuf)) \ ( \ conj_t conjat, \ conj_t conjx, \ dim_t m, \ dim_t b_n, \ ctype* restrict alpha, \ ctype* restrict a, inc_t inca, inc_t lda, \ ctype* restrict x, inc_t incx, \ ctype* restrict beta, \ ctype* restrict y, inc_t incy, \ cntx_t* cntx \ ); INSERT_GENTDEF( dotxf ) // dotxaxpyf #undef GENTDEF #define GENTDEF( ctype, ch, opname, tsuf ) \ \ typedef void (*PASTECH3(ch,opname,_ker,tsuf)) \ ( \ conj_t conjat, \ conj_t conja, \ conj_t conjw, \ conj_t conjx, \ dim_t m, \ dim_t b_n, \ ctype* restrict alpha, \ ctype* restrict a, inc_t inca, inc_t lda, \ ctype* restrict w, inc_t incw, \ ctype* restrict x, inc_t incx, \ ctype* restrict beta, \ ctype* restrict y, inc_t incy, \ ctype* restrict z, inc_t incz, \ cntx_t* cntx \ ); INSERT_GENTDEF( dotxaxpyf ) #endif blis-0.9.0/frame/1f/bli_l1f_ker.h000066400000000000000000000046271422157504600164120ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Define template prototypes for level-1f kernels. // // Note: Instead of defining function prototype macro templates and then // instantiating those macros to define the individual function prototypes, // we simply alias the official operations' prototypes as defined in // bli_l1f_ker_prot.h. #undef GENTPROT #define GENTPROT AXPY2V_KER_PROT INSERT_GENTPROT_BASIC0( axpy2v_ker_name ) #undef GENTPROT #define GENTPROT AXPYF_KER_PROT INSERT_GENTPROT_BASIC0( axpyf_ker_name ) #undef GENTPROT #define GENTPROT DOTAXPYV_KER_PROT INSERT_GENTPROT_BASIC0( dotaxpyv_ker_name ) #undef GENTPROT #define GENTPROT DOTXAXPYF_KER_PROT INSERT_GENTPROT_BASIC0( dotxaxpyf_ker_name ) #undef GENTPROT #define GENTPROT DOTXF_KER_PROT INSERT_GENTPROT_BASIC0( dotxf_ker_name ) blis-0.9.0/frame/1f/bli_l1f_ker_prot.h000066400000000000000000000077411422157504600174560ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Define template prototypes for level-1f kernels. // #define AXPY2V_KER_PROT( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ conj_t conjx, \ conj_t conjy, \ dim_t n, \ ctype* restrict alphax, \ ctype* restrict alphay, \ ctype* restrict x, inc_t incx, \ ctype* restrict y, inc_t incy, \ ctype* restrict z, inc_t incz, \ cntx_t* restrict cntx \ ); #define AXPYF_KER_PROT( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ conj_t conja, \ conj_t conjx, \ dim_t m, \ dim_t b_n, \ ctype* restrict alpha, \ ctype* restrict a, inc_t inca, inc_t lda, \ ctype* restrict x, inc_t incx, \ ctype* restrict y, inc_t incy, \ cntx_t* restrict cntx \ ); #define DOTAXPYV_KER_PROT( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ conj_t conjxt, \ conj_t conjx, \ conj_t conjy, \ dim_t n, \ ctype* restrict alpha, \ ctype* restrict x, inc_t incx, \ ctype* restrict y, inc_t incy, \ ctype* restrict rho, \ ctype* restrict z, inc_t incz, \ cntx_t* restrict cntx \ ); #define DOTXAXPYF_KER_PROT( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ conj_t conjat, \ conj_t conja, \ conj_t conjw, \ conj_t conjx, \ dim_t m, \ dim_t b_n, \ ctype* restrict alpha, \ ctype* restrict a, inc_t inca, inc_t lda, \ ctype* restrict w, inc_t incw, \ ctype* restrict x, inc_t incx, \ ctype* restrict beta, \ ctype* restrict y, inc_t incy, \ ctype* restrict z, inc_t incz, \ cntx_t* restrict cntx \ ); #define DOTXF_KER_PROT( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ conj_t conjat, \ conj_t conjx, \ dim_t m, \ dim_t b_n, \ ctype* restrict alpha, \ ctype* restrict a, inc_t inca, inc_t lda, \ ctype* restrict x, inc_t incx, \ ctype* restrict beta, \ ctype* restrict y, inc_t incy, \ cntx_t* restrict cntx \ ); blis-0.9.0/frame/1f/bli_l1f_oapi.c000066400000000000000000000275511422157504600165550ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // Guard the function definitions so that they are only compiled when // #included from files that define the object API macros. #ifdef BLIS_ENABLE_OAPI // // Define object-based interfaces. // #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC(opname,EX_SUF) \ ( \ obj_t* alphax, \ obj_t* alphay, \ obj_t* x, \ obj_t* y, \ obj_t* z \ BLIS_OAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_OAPI_EX_DECLS \ \ num_t dt = bli_obj_dt( x ); \ \ conj_t conjx = bli_obj_conj_status( x ); \ conj_t conjy = bli_obj_conj_status( y ); \ dim_t n = bli_obj_vector_dim( x ); \ void* buf_x = bli_obj_buffer_at_off( x ); \ inc_t inc_x = bli_obj_vector_inc( x ); \ void* buf_y = bli_obj_buffer_at_off( y ); \ inc_t inc_y = bli_obj_vector_inc( y ); \ void* buf_z = bli_obj_buffer_at_off( z ); \ inc_t inc_z = bli_obj_vector_inc( z ); \ \ void* buf_alphax; \ void* buf_alphay; \ \ obj_t alphax_local; \ obj_t alphay_local; \ \ if ( bli_error_checking_is_enabled() ) \ PASTEMAC(opname,_check)( alphax, alphay, x, y, z ); \ \ /* Create local copy-casts of scalars (and apply internal conjugation as needed). */ \ bli_obj_scalar_init_detached_copy_of( dt, BLIS_NO_CONJUGATE, \ alphax, &alphax_local ); \ bli_obj_scalar_init_detached_copy_of( dt, BLIS_NO_CONJUGATE, \ alphay, &alphay_local ); \ buf_alphax = bli_obj_buffer_for_1x1( dt, &alphax_local ); \ buf_alphay = bli_obj_buffer_for_1x1( dt, &alphay_local ); \ \ /* Query a type-specific function pointer, except one that uses void* for function arguments instead of typed pointers. */ \ PASTECH2(opname,BLIS_TAPI_EX_SUF,_vft) f = \ PASTEMAC2(opname,BLIS_TAPI_EX_SUF,_qfp)( dt ); \ \ f \ ( \ conjx, \ conjy, \ n, \ buf_alphax, \ buf_alphay, \ buf_x, inc_x, \ buf_y, inc_y, \ buf_z, inc_z, \ cntx, \ rntm \ ); \ } GENFRONT( axpy2v ) #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC(opname,EX_SUF) \ ( \ obj_t* alpha, \ obj_t* a, \ obj_t* x, \ obj_t* y \ BLIS_OAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_OAPI_EX_DECLS \ \ num_t dt = bli_obj_dt( x ); \ \ conj_t conja = bli_obj_conj_status( a ); \ conj_t conjx = bli_obj_conj_status( x ); \ dim_t m = bli_obj_vector_dim( y ); \ dim_t b_n = bli_obj_vector_dim( x ); \ void* buf_a = bli_obj_buffer_at_off( a ); \ inc_t rs_a = bli_obj_row_stride( a ); \ inc_t cs_a = bli_obj_col_stride( a ); \ void* buf_x = bli_obj_buffer_at_off( x ); \ inc_t inc_x = bli_obj_vector_inc( x ); \ void* buf_y = bli_obj_buffer_at_off( y ); \ inc_t inc_y = bli_obj_vector_inc( y ); \ \ void* buf_alpha; \ \ obj_t alpha_local; \ \ if ( bli_error_checking_is_enabled() ) \ PASTEMAC(opname,_check)( alpha, a, x, y ); \ \ /* Create local copy-casts of scalars (and apply internal conjugation as needed). */ \ bli_obj_scalar_init_detached_copy_of( dt, BLIS_NO_CONJUGATE, \ alpha, &alpha_local ); \ buf_alpha = bli_obj_buffer_for_1x1( dt, &alpha_local ); \ \ /* Support cases where matrix A requires a transposition. */ \ if ( bli_obj_has_trans( a ) ) { bli_swap_incs( &rs_a, &cs_a ); } \ \ /* Query a type-specific function pointer, except one that uses void* for function arguments instead of typed pointers. */ \ PASTECH2(opname,BLIS_TAPI_EX_SUF,_vft) f = \ PASTEMAC2(opname,BLIS_TAPI_EX_SUF,_qfp)( dt ); \ \ f \ ( \ conja, \ conjx, \ m, \ b_n, \ buf_alpha, \ buf_a, rs_a, cs_a, \ buf_x, inc_x, \ buf_y, inc_y, \ cntx, \ rntm \ ); \ } GENFRONT( axpyf ) #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC(opname,EX_SUF) \ ( \ obj_t* alpha, \ obj_t* xt, \ obj_t* x, \ obj_t* y, \ obj_t* rho, \ obj_t* z \ BLIS_OAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_OAPI_EX_DECLS \ \ num_t dt = bli_obj_dt( x ); \ \ conj_t conjxt = bli_obj_conj_status( xt ); \ conj_t conjx = bli_obj_conj_status( x ); \ conj_t conjy = bli_obj_conj_status( y ); \ dim_t n = bli_obj_vector_dim( x ); \ void* buf_x = bli_obj_buffer_at_off( x ); \ inc_t inc_x = bli_obj_vector_inc( x ); \ void* buf_y = bli_obj_buffer_at_off( y ); \ inc_t inc_y = bli_obj_vector_inc( y ); \ void* buf_z = bli_obj_buffer_at_off( z ); \ inc_t inc_z = bli_obj_vector_inc( z ); \ void* buf_rho = bli_obj_buffer_at_off( rho ); \ \ void* buf_alpha; \ \ obj_t alpha_local; \ \ if ( bli_error_checking_is_enabled() ) \ PASTEMAC(opname,_check)( alpha, xt, x, y, rho, z ); \ \ /* Create local copy-casts of scalars (and apply internal conjugation as needed). */ \ bli_obj_scalar_init_detached_copy_of( dt, BLIS_NO_CONJUGATE, \ alpha, &alpha_local ); \ buf_alpha = bli_obj_buffer_for_1x1( dt, &alpha_local ); \ \ /* Query a type-specific function pointer, except one that uses void* for function arguments instead of typed pointers. */ \ PASTECH2(opname,BLIS_TAPI_EX_SUF,_vft) f = \ PASTEMAC2(opname,BLIS_TAPI_EX_SUF,_qfp)( dt ); \ \ f \ ( \ conjxt, \ conjx, \ conjy, \ n, \ buf_alpha, \ buf_x, inc_x, \ buf_y, inc_y, \ buf_rho, \ buf_z, inc_z, \ cntx, \ rntm \ ); \ } GENFRONT( dotaxpyv ) #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC(opname,EX_SUF) \ ( \ obj_t* alpha, \ obj_t* at, \ obj_t* a, \ obj_t* w, \ obj_t* x, \ obj_t* beta, \ obj_t* y, \ obj_t* z \ BLIS_OAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_OAPI_EX_DECLS \ \ num_t dt = bli_obj_dt( x ); \ \ conj_t conjat = bli_obj_conj_status( at ); \ conj_t conja = bli_obj_conj_status( a ); \ conj_t conjw = bli_obj_conj_status( w ); \ conj_t conjx = bli_obj_conj_status( x ); \ dim_t m = bli_obj_vector_dim( z ); \ dim_t b_n = bli_obj_vector_dim( y ); \ void* buf_a = bli_obj_buffer_at_off( a ); \ inc_t rs_a = bli_obj_row_stride( a ); \ inc_t cs_a = bli_obj_col_stride( a ); \ void* buf_w = bli_obj_buffer_at_off( w ); \ inc_t inc_w = bli_obj_vector_inc( w ); \ void* buf_x = bli_obj_buffer_at_off( x ); \ inc_t inc_x = bli_obj_vector_inc( x ); \ void* buf_y = bli_obj_buffer_at_off( y ); \ inc_t inc_y = bli_obj_vector_inc( y ); \ void* buf_z = bli_obj_buffer_at_off( z ); \ inc_t inc_z = bli_obj_vector_inc( z ); \ \ void* buf_alpha; \ void* buf_beta; \ \ obj_t alpha_local; \ obj_t beta_local; \ \ if ( bli_error_checking_is_enabled() ) \ PASTEMAC(opname,_check)( alpha, at, a, w, x, beta, y, z ); \ \ /* Create local copy-casts of scalars (and apply internal conjugation as needed). */ \ bli_obj_scalar_init_detached_copy_of( dt, BLIS_NO_CONJUGATE, \ alpha, &alpha_local ); \ bli_obj_scalar_init_detached_copy_of( dt, BLIS_NO_CONJUGATE, \ beta, &beta_local ); \ buf_alpha = bli_obj_buffer_for_1x1( dt, &alpha_local ); \ buf_beta = bli_obj_buffer_for_1x1( dt, &beta_local ); \ \ /* Support cases where matrix A requires a transposition. */ \ if ( bli_obj_has_trans( a ) ) { bli_swap_incs( &rs_a, &cs_a ); } \ \ /* Query a type-specific function pointer, except one that uses void* for function arguments instead of typed pointers. */ \ PASTECH2(opname,BLIS_TAPI_EX_SUF,_vft) f = \ PASTEMAC2(opname,BLIS_TAPI_EX_SUF,_qfp)( dt ); \ \ f \ ( \ conjat, \ conja, \ conjw, \ conjx, \ m, \ b_n, \ buf_alpha, \ buf_a, rs_a, cs_a, \ buf_w, inc_w, \ buf_x, inc_x, \ buf_beta, \ buf_y, inc_y, \ buf_z, inc_z, \ cntx, \ rntm \ ); \ } GENFRONT( dotxaxpyf ) #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC(opname,EX_SUF) \ ( \ obj_t* alpha, \ obj_t* a, \ obj_t* x, \ obj_t* beta, \ obj_t* y \ BLIS_OAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_OAPI_EX_DECLS \ \ num_t dt = bli_obj_dt( x ); \ \ conj_t conjat = bli_obj_conj_status( a ); \ conj_t conjx = bli_obj_conj_status( x ); \ dim_t m = bli_obj_vector_dim( x ); \ dim_t b_n = bli_obj_vector_dim( y ); \ void* buf_a = bli_obj_buffer_at_off( a ); \ inc_t rs_a = bli_obj_row_stride( a ); \ inc_t cs_a = bli_obj_col_stride( a ); \ void* buf_x = bli_obj_buffer_at_off( x ); \ inc_t inc_x = bli_obj_vector_inc( x ); \ void* buf_y = bli_obj_buffer_at_off( y ); \ inc_t inc_y = bli_obj_vector_inc( y ); \ \ void* buf_alpha; \ void* buf_beta; \ \ obj_t alpha_local; \ obj_t beta_local; \ \ if ( bli_error_checking_is_enabled() ) \ PASTEMAC(opname,_check)( alpha, a, x, beta, y ); \ \ /* Create local copy-casts of scalars (and apply internal conjugation as needed). */ \ bli_obj_scalar_init_detached_copy_of( dt, BLIS_NO_CONJUGATE, \ alpha, &alpha_local ); \ bli_obj_scalar_init_detached_copy_of( dt, BLIS_NO_CONJUGATE, \ beta, &beta_local ); \ buf_alpha = bli_obj_buffer_for_1x1( dt, &alpha_local ); \ buf_beta = bli_obj_buffer_for_1x1( dt, &beta_local ); \ \ /* Support cases where matrix A requires a transposition. */ \ if ( bli_obj_has_trans( a ) ) { bli_swap_incs( &rs_a, &cs_a ); } \ \ /* Query a type-specific function pointer, except one that uses void* for function arguments instead of typed pointers. */ \ PASTECH2(opname,BLIS_TAPI_EX_SUF,_vft) f = \ PASTEMAC2(opname,BLIS_TAPI_EX_SUF,_qfp)( dt ); \ \ f \ ( \ conjat, \ conjx, \ m, \ b_n, \ buf_alpha, \ buf_a, rs_a, cs_a, \ buf_x, inc_x, \ buf_beta, \ buf_y, inc_y, \ cntx, \ rntm \ ); \ } GENFRONT( dotxf ) #endif blis-0.9.0/frame/1f/bli_l1f_oapi.h000066400000000000000000000061061422157504600165530ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype object-based interfaces. // #undef GENTPROT #define GENTPROT( opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC(opname,EX_SUF) \ ( \ obj_t* alphax, \ obj_t* alphay, \ obj_t* x, \ obj_t* y, \ obj_t* z \ BLIS_OAPI_EX_PARAMS \ ); GENTPROT( axpy2v ) #undef GENTPROT #define GENTPROT( opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC(opname,EX_SUF) \ ( \ obj_t* alpha, \ obj_t* a, \ obj_t* x, \ obj_t* y \ BLIS_OAPI_EX_PARAMS \ ); GENTPROT( axpyf ) #undef GENTPROT #define GENTPROT( opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC(opname,EX_SUF) \ ( \ obj_t* alpha, \ obj_t* xt, \ obj_t* x, \ obj_t* y, \ obj_t* rho, \ obj_t* z \ BLIS_OAPI_EX_PARAMS \ ); GENTPROT( dotaxpyv ) #undef GENTPROT #define GENTPROT( opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC(opname,EX_SUF) \ ( \ obj_t* alpha, \ obj_t* at, \ obj_t* a, \ obj_t* w, \ obj_t* x, \ obj_t* beta, \ obj_t* y, \ obj_t* z \ BLIS_OAPI_EX_PARAMS \ ); GENTPROT( dotxaxpyf ) #undef GENTPROT #define GENTPROT( opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC(opname,EX_SUF) \ ( \ obj_t* alpha, \ obj_t* a, \ obj_t* x, \ obj_t* beta, \ obj_t* y \ BLIS_OAPI_EX_PARAMS \ ); GENTPROT( dotxf ) blis-0.9.0/frame/1f/bli_l1f_oapi_ba.c000066400000000000000000000036701422157504600172130ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // Include cpp macros that instantiate the API definition templates as // omitting expert parameters. #include "bli_oapi_ba.h" // Define the macro protecting the object API definitions. #define BLIS_ENABLE_OAPI // Include the object API definitions here. #include "bli_l1f_oapi.c" blis-0.9.0/frame/1f/bli_l1f_oapi_ex.c000066400000000000000000000036661422157504600172520ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // Include cpp macros that instantiate the API definition templates as // having expert parameters. #include "bli_oapi_ex.h" // Define the macro protecting the object API definitions. #define BLIS_ENABLE_OAPI // Include the object API definitions here. #include "bli_l1f_oapi.c" blis-0.9.0/frame/1f/bli_l1f_tapi.c000066400000000000000000000143621422157504600165560ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // Guard the function definitions so that they are only compiled when // #included from files that define the typed API macros. #ifdef BLIS_ENABLE_TAPI // // Define BLAS-like interfaces with typed operands. // #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, kerid ) \ \ void PASTEMAC2(ch,opname,EX_SUF) \ ( \ conj_t conjx, \ conj_t conjy, \ dim_t n, \ ctype* alphax, \ ctype* alphay, \ ctype* x, inc_t incx, \ ctype* y, inc_t incy, \ ctype* z, inc_t incz \ BLIS_TAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_TAPI_EX_DECLS \ \ const num_t dt = PASTEMAC(ch,type); \ \ /* Obtain a valid context from the gks if necessary. */ \ if ( cntx == NULL ) cntx = bli_gks_query_cntx(); \ \ PASTECH2(ch,opname,_ker_ft) f = bli_cntx_get_l1f_ker_dt( dt, kerid, cntx ); \ \ f \ ( \ conjx, \ conjy, \ n, \ alphax, \ alphay, \ x, incx, \ y, incy, \ z, incz, \ cntx \ ); \ } INSERT_GENTFUNC_BASIC( axpy2v, BLIS_AXPY2V_KER ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, kerid ) \ \ void PASTEMAC2(ch,opname,EX_SUF) \ ( \ conj_t conja, \ conj_t conjx, \ dim_t m, \ dim_t b_n, \ ctype* alpha, \ ctype* a, inc_t inca, inc_t lda, \ ctype* x, inc_t incx, \ ctype* y, inc_t incy \ BLIS_TAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_TAPI_EX_DECLS \ \ const num_t dt = PASTEMAC(ch,type); \ \ /* Obtain a valid context from the gks if necessary. */ \ if ( cntx == NULL ) cntx = bli_gks_query_cntx(); \ \ PASTECH2(ch,opname,_ker_ft) f = bli_cntx_get_l1f_ker_dt( dt, kerid, cntx ); \ \ f \ ( \ conja, \ conjx, \ m, \ b_n, \ alpha, \ a, inca, lda, \ x, incx, \ y, incy, \ cntx \ ); \ } INSERT_GENTFUNC_BASIC( axpyf, BLIS_AXPYF_KER ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, kerid ) \ \ void PASTEMAC2(ch,opname,EX_SUF) \ ( \ conj_t conjxt, \ conj_t conjx, \ conj_t conjy, \ dim_t n, \ ctype* alpha, \ ctype* x, inc_t incx, \ ctype* y, inc_t incy, \ ctype* rho, \ ctype* z, inc_t incz \ BLIS_TAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_TAPI_EX_DECLS \ \ const num_t dt = PASTEMAC(ch,type); \ \ /* Obtain a valid context from the gks if necessary. */ \ if ( cntx == NULL ) cntx = bli_gks_query_cntx(); \ \ PASTECH2(ch,opname,_ker_ft) f = bli_cntx_get_l1f_ker_dt( dt, kerid, cntx ); \ \ f \ ( \ conjxt, \ conjx, \ conjy, \ n, \ alpha, \ x, incx, \ y, incy, \ rho, \ z, incz, \ cntx \ ); \ } INSERT_GENTFUNC_BASIC( dotaxpyv, BLIS_DOTAXPYV_KER ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, kerid ) \ \ void PASTEMAC2(ch,opname,EX_SUF) \ ( \ conj_t conjat, \ conj_t conja, \ conj_t conjw, \ conj_t conjx, \ dim_t m, \ dim_t b_n, \ ctype* alpha, \ ctype* a, inc_t inca, inc_t lda, \ ctype* w, inc_t incw, \ ctype* x, inc_t incx, \ ctype* beta, \ ctype* y, inc_t incy, \ ctype* z, inc_t incz \ BLIS_TAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_TAPI_EX_DECLS \ \ const num_t dt = PASTEMAC(ch,type); \ \ /* Obtain a valid context from the gks if necessary. */ \ if ( cntx == NULL ) cntx = bli_gks_query_cntx(); \ \ PASTECH2(ch,opname,_ker_ft) f = bli_cntx_get_l1f_ker_dt( dt, kerid, cntx ); \ \ f \ ( \ conjat, \ conja, \ conjw, \ conjx, \ m, \ b_n, \ alpha, \ a, inca, lda, \ w, incw, \ x, incx, \ beta, \ y, incy, \ z, incz, \ cntx \ ); \ } INSERT_GENTFUNC_BASIC( dotxaxpyf, BLIS_DOTXAXPYF_KER ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, kerid ) \ \ void PASTEMAC2(ch,opname,EX_SUF) \ ( \ conj_t conjat, \ conj_t conjx, \ dim_t m, \ dim_t b_n, \ ctype* alpha, \ ctype* a, inc_t inca, inc_t lda, \ ctype* x, inc_t incx, \ ctype* beta, \ ctype* y, inc_t incy \ BLIS_TAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_TAPI_EX_DECLS \ \ const num_t dt = PASTEMAC(ch,type); \ \ /* Obtain a valid context from the gks if necessary. */ \ if ( cntx == NULL ) cntx = bli_gks_query_cntx(); \ \ PASTECH2(ch,opname,_ker_ft) f = bli_cntx_get_l1f_ker_dt( dt, kerid, cntx ); \ \ f \ ( \ conjat, \ conjx, \ m, \ b_n, \ alpha, \ a, inca, lda, \ x, incx, \ beta, \ y, incy, \ cntx \ ); \ } INSERT_GENTFUNC_BASIC( dotxf, BLIS_DOTXF_KER ) #endif blis-0.9.0/frame/1f/bli_l1f_tapi.h000066400000000000000000000076141422157504600165650ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype BLAS-like interfaces with typed operands. // #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC2(ch,opname,EX_SUF) \ ( \ conj_t conjx, \ conj_t conjy, \ dim_t n, \ ctype* alphax, \ ctype* alphay, \ ctype* x, inc_t incx, \ ctype* y, inc_t incy, \ ctype* z, inc_t incz \ BLIS_TAPI_EX_PARAMS \ ); INSERT_GENTPROT_BASIC0( axpy2v ) #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC2(ch,opname,EX_SUF) \ ( \ conj_t conja, \ conj_t conjx, \ dim_t m, \ dim_t b_n, \ ctype* alpha, \ ctype* a, inc_t inca, inc_t lda, \ ctype* x, inc_t incx, \ ctype* y, inc_t incy \ BLIS_TAPI_EX_PARAMS \ ); INSERT_GENTPROT_BASIC0( axpyf ) #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC2(ch,opname,EX_SUF) \ ( \ conj_t conjxt, \ conj_t conjx, \ conj_t conjy, \ dim_t n, \ ctype* alpha, \ ctype* x, inc_t incx, \ ctype* y, inc_t incy, \ ctype* rho, \ ctype* z, inc_t incz \ BLIS_TAPI_EX_PARAMS \ ); INSERT_GENTPROT_BASIC0( dotaxpyv ) #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC2(ch,opname,EX_SUF) \ ( \ conj_t conjat, \ conj_t conja, \ conj_t conjw, \ conj_t conjx, \ dim_t m, \ dim_t b_n, \ ctype* alpha, \ ctype* a, inc_t inca, inc_t lda, \ ctype* w, inc_t incw, \ ctype* x, inc_t incx, \ ctype* beta, \ ctype* y, inc_t incy, \ ctype* z, inc_t incz \ BLIS_TAPI_EX_PARAMS \ ); INSERT_GENTPROT_BASIC0( dotxaxpyf ) #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC2(ch,opname,EX_SUF) \ ( \ conj_t conjat, \ conj_t conjx, \ dim_t m, \ dim_t b_n, \ ctype* alpha, \ ctype* a, inc_t inca, inc_t lda, \ ctype* x, inc_t incx, \ ctype* beta, \ ctype* y, inc_t incy \ BLIS_TAPI_EX_PARAMS \ ); INSERT_GENTPROT_BASIC0( dotxf ) blis-0.9.0/frame/1f/bli_l1f_tapi_ba.c000066400000000000000000000036661422157504600172250ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // Include cpp macros that instantiate the API definition templates as // omitting expert parameters. #include "bli_tapi_ba.h" // Define the macro protecting the typed API definitions. #define BLIS_ENABLE_TAPI // Include the typed API definitions here. #include "bli_l1f_tapi.c" blis-0.9.0/frame/1f/bli_l1f_tapi_ex.c000066400000000000000000000036641422157504600172550ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // Include cpp macros that instantiate the API definition templates as // having expert parameters. #include "bli_tapi_ex.h" // Define the macro protecting the typed API definitions. #define BLIS_ENABLE_TAPI // Include the typed API definitions here. #include "bli_l1f_tapi.c" blis-0.9.0/frame/1m/000077500000000000000000000000001422157504600140665ustar00rootroot00000000000000blis-0.9.0/frame/1m/bli_l1m.h000066400000000000000000000047511422157504600155650ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "bli_l1m_check.h" // Define kernel function types. #include "bli_l1m_ft_ker.h" // Define object function types for variants. #include "bli_l1m_oft_var.h" // Prototype object APIs (expert and non-expert). #include "bli_oapi_ex.h" #include "bli_l1m_oapi.h" #include "bli_xapi_undef.h" #include "bli_oapi_ba.h" #include "bli_l1m_oapi.h" #include "bli_xapi_undef.h" // Prototype typed APIs (expert and non-expert). #include "bli_tapi_ex.h" #include "bli_l1m_tapi.h" #include "bli_l1m_ft.h" #include "bli_xapi_undef.h" #include "bli_tapi_ba.h" #include "bli_l1m_tapi.h" #include "bli_l1m_ft.h" #include "bli_xapi_undef.h" // Generate function pointer arrays for tapi functions (expert only). #include "bli_l1m_fpa.h" // Prototype level-1m implementations. #include "bli_l1m_unb_var1.h" // Pack-related #include "bli_packm.h" #include "bli_unpackm.h" blis-0.9.0/frame/1m/bli_l1m_check.c000066400000000000000000000124431422157504600167120ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // Define object-based check functions. // #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC(opname,_check) \ ( \ obj_t* x, \ obj_t* y \ ) \ { \ bli_l1m_xy_check( x, y ); \ } GENFRONT( addm ) GENFRONT( copym ) GENFRONT( subm ) #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC(opname,_check) \ ( \ obj_t* alpha, \ obj_t* x, \ obj_t* y \ ) \ { \ bli_l1m_axy_check( alpha, x, y ); \ } GENFRONT( axpym ) GENFRONT( scal2m ) #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC(opname,_check) \ ( \ obj_t* alpha, \ obj_t* x \ ) \ { \ bli_l1m_ax_check( alpha, x ); \ } GENFRONT( scalm ) GENFRONT( setm ) #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC(opname,_check) \ ( \ obj_t* x, \ obj_t* beta, \ obj_t* y \ ) \ { \ bli_l1m_axy_check( beta, x, y ); \ } GENFRONT( xpbym ) // ----------------------------------------------------------------------------- void bli_l1m_xy_check ( obj_t* x, obj_t* y ) { err_t e_val; // Check object datatypes. e_val = bli_check_floating_object( x ); bli_check_error_code( e_val ); e_val = bli_check_floating_object( y ); bli_check_error_code( e_val ); // Check for consistent datatypes. e_val = bli_check_consistent_object_datatypes( x, y ); bli_check_error_code( e_val ); // Check object dimensions. e_val = bli_check_matrix_object( x ); bli_check_error_code( e_val ); e_val = bli_check_matrix_object( y ); bli_check_error_code( e_val ); e_val = bli_check_conformal_dims( x, y ); bli_check_error_code( e_val ); // Check object buffers (for non-NULLness). e_val = bli_check_object_buffer( x ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( y ); bli_check_error_code( e_val ); } void bli_l1m_axy_check ( obj_t* alpha, obj_t* x, obj_t* y ) { err_t e_val; // Check object datatypes. e_val = bli_check_noninteger_object( alpha ); bli_check_error_code( e_val ); e_val = bli_check_floating_object( x ); bli_check_error_code( e_val ); e_val = bli_check_floating_object( y ); bli_check_error_code( e_val ); // Check for consistent datatypes. e_val = bli_check_consistent_object_datatypes( x, y ); bli_check_error_code( e_val ); // Check object dimensions. e_val = bli_check_scalar_object( alpha ); bli_check_error_code( e_val ); e_val = bli_check_matrix_object( x ); bli_check_error_code( e_val ); e_val = bli_check_matrix_object( y ); bli_check_error_code( e_val ); e_val = bli_check_conformal_dims( x, y ); bli_check_error_code( e_val ); // Check object buffers (for non-NULLness). e_val = bli_check_object_buffer( alpha ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( x ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( y ); bli_check_error_code( e_val ); } void bli_l1m_ax_check ( obj_t* alpha, obj_t* x ) { err_t e_val; // Check object datatypes. e_val = bli_check_noninteger_object( alpha ); bli_check_error_code( e_val ); e_val = bli_check_floating_object( x ); bli_check_error_code( e_val ); // Check object dimensions. e_val = bli_check_scalar_object( alpha ); bli_check_error_code( e_val ); e_val = bli_check_matrix_object( x ); bli_check_error_code( e_val ); // Check object properties. //e_val = bli_check_nonunit_diag( x ); //bli_check_error_code( e_val ); // Check object buffers (for non-NULLness). e_val = bli_check_object_buffer( alpha ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( x ); bli_check_error_code( e_val ); } blis-0.9.0/frame/1m/bli_l1m_check.h000066400000000000000000000053401422157504600167150ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype object-based check functions. // #undef GENPROT #define GENPROT( opname ) \ \ void PASTEMAC(opname,_check) \ ( \ obj_t* x, \ obj_t* y \ ); GENPROT( addm ) GENPROT( copym ) GENPROT( subm ) #undef GENPROT #define GENPROT( opname ) \ \ void PASTEMAC(opname,_check) \ ( \ obj_t* alpha, \ obj_t* x, \ obj_t* y \ ); GENPROT( axpym ) GENPROT( scal2m ) #undef GENPROT #define GENPROT( opname ) \ \ void PASTEMAC(opname,_check) \ ( \ obj_t* alpha, \ obj_t* x \ ); GENPROT( scalm ) GENPROT( setm ) #undef GENPROT #define GENPROT( opname ) \ \ void PASTEMAC(opname,_check) \ ( \ obj_t* x, \ obj_t* beta, \ obj_t* y \ ); GENPROT( xpbym ) // ----------------------------------------------------------------------------- void bli_l1m_xy_check ( obj_t* x, obj_t* y ); void bli_l1m_axy_check ( obj_t* alpha, obj_t* x, obj_t* y ); void bli_l1m_ax_check ( obj_t* alpha, obj_t* x ); blis-0.9.0/frame/1m/bli_l1m_fpa.c000066400000000000000000000051251422157504600164020ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // Define function pointer query interfaces. // #undef GENFRONT #define GENFRONT( opname ) \ \ GENARRAY_FPA( PASTECH2(opname,BLIS_TAPI_EX_SUF,_vft), \ PASTECH(opname,BLIS_TAPI_EX_SUF) ); \ \ PASTECH2(opname,BLIS_TAPI_EX_SUF,_vft) \ PASTEMAC2(opname,BLIS_TAPI_EX_SUF,_qfp)( num_t dt ) \ { \ return PASTECH2(opname,BLIS_TAPI_EX_SUF,_fpa)[ dt ]; \ } GENFRONT( addm ) GENFRONT( copym ) GENFRONT( subm ) GENFRONT( axpym ) GENFRONT( scal2m ) GENFRONT( scalm ) GENFRONT( setm ) GENFRONT( xpbym ) // // Define function pointer query interfaces for two-datatype operations. // #undef GENFRONT #define GENFRONT( opname ) \ \ GENARRAY_FPA2( PASTECH2(opname,BLIS_TAPI_EX_SUF,_vft), \ PASTECH(opname,BLIS_TAPI_EX_SUF) ); \ \ PASTECH2(opname,BLIS_TAPI_EX_SUF,_vft) \ PASTEMAC2(opname,BLIS_TAPI_EX_SUF,_qfp2)( num_t dtx, num_t dty ) \ { \ return PASTECH2(opname,BLIS_TAPI_EX_SUF,_fpa2)[ dtx ][ dty ]; \ } GENFRONT( xpbym_md ) blis-0.9.0/frame/1m/bli_l1m_fpa.h000066400000000000000000000042021422157504600164020ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype function pointer query interface. // #undef GENPROT #define GENPROT( opname ) \ \ PASTECH2(opname,BLIS_TAPI_EX_SUF,_vft) \ PASTEMAC2(opname,BLIS_TAPI_EX_SUF,_qfp)( num_t dt ); GENPROT( addm ) GENPROT( copym ) GENPROT( subm ) GENPROT( axpym ) GENPROT( scal2m ) GENPROT( scalm ) GENPROT( setm ) GENPROT( xpbym ) #undef GENPROT #define GENPROT( opname ) \ \ PASTECH2(opname,BLIS_TAPI_EX_SUF,_vft) \ PASTEMAC2(opname,BLIS_TAPI_EX_SUF,_qfp2)( num_t dtx, num_t dty ); GENPROT( xpbym_md ) blis-0.9.0/frame/1m/bli_l1m_ft.h000066400000000000000000000077151422157504600162610ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // -- Level-1v function types -------------------------------------------------- // // addm, subm #undef GENTDEF #define GENTDEF( ctype, ch, opname, tsuf ) \ \ typedef void (*PASTECH3(ch,opname,EX_SUF,tsuf)) \ ( \ doff_t diagoffx, \ diag_t diagx, \ uplo_t uplox, \ trans_t transx, \ dim_t m, \ dim_t n, \ ctype* x, inc_t rs_x, inc_t cs_x, \ ctype* y, inc_t rs_y, inc_t cs_y \ BLIS_TAPI_EX_PARAMS \ ); INSERT_GENTDEF( addm ) INSERT_GENTDEF( subm ) INSERT_GENTDEF( copym ) // axpym #undef GENTDEF #define GENTDEF( ctype, ch, opname, tsuf ) \ \ typedef void (*PASTECH3(ch,opname,EX_SUF,tsuf)) \ ( \ doff_t diagoffx, \ diag_t diagx, \ uplo_t uplox, \ trans_t transx, \ dim_t m, \ dim_t n, \ ctype* alpha, \ ctype* x, inc_t rs_x, inc_t cs_x, \ ctype* y, inc_t rs_y, inc_t cs_y \ BLIS_TAPI_EX_PARAMS \ ); INSERT_GENTDEF( axpym ) // scal2m #undef GENTDEF #define GENTDEF( ctype, ch, opname, tsuf ) \ \ typedef void (*PASTECH3(ch,opname,EX_SUF,tsuf)) \ ( \ doff_t diagoffx, \ diag_t diagx, \ uplo_t uplox, \ trans_t transx, \ dim_t m, \ dim_t n, \ ctype* alpha, \ ctype* x, inc_t rs_x, inc_t cs_x, \ ctype* y, inc_t rs_y, inc_t cs_y \ BLIS_TAPI_EX_PARAMS \ ); INSERT_GENTDEF( scal2m ) // scalm, setm #undef GENTDEF #define GENTDEF( ctype, ch, opname, tsuf ) \ \ typedef void (*PASTECH3(ch,opname,EX_SUF,tsuf)) \ ( \ conj_t conjalpha, \ doff_t diagoffx, \ diag_t diagx, \ uplo_t uplox, \ dim_t m, \ dim_t n, \ ctype* alpha, \ ctype* x, inc_t rs_x, inc_t cs_x \ BLIS_TAPI_EX_PARAMS \ ); INSERT_GENTDEF( scalm ) INSERT_GENTDEF( setm ) // xpbym #undef GENTDEF #define GENTDEF( ctype, ch, opname, tsuf ) \ \ typedef void (*PASTECH3(ch,opname,EX_SUF,tsuf)) \ ( \ doff_t diagoffx, \ diag_t diagx, \ uplo_t uplox, \ trans_t transx, \ dim_t m, \ dim_t n, \ ctype* x, inc_t rs_x, inc_t cs_x, \ ctype* beta, \ ctype* y, inc_t rs_y, inc_t cs_y \ BLIS_TAPI_EX_PARAMS \ ); INSERT_GENTDEF( xpbym ) INSERT_GENTDEF( xpbym_md ) blis-0.9.0/frame/1m/bli_l1m_ft_ker.h000066400000000000000000000103151422157504600171100ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_L1M_FT_KER_H #define BLIS_L1M_FT_KER_H // // -- Level-1m kernel function types ------------------------------------------- // // packm // NOTE: This is the function type for the structure-aware "kernel". #undef GENTDEF #define GENTDEF( ctype, ch, opname, tsuf ) \ \ typedef void (*PASTECH3(ch,opname,_ker,tsuf)) \ ( \ struc_t strucc, \ diag_t diagc, \ uplo_t uploc, \ conj_t conjc, \ pack_t schema, \ bool invdiag, \ dim_t panel_dim, \ dim_t panel_len, \ dim_t panel_dim_max, \ dim_t panel_len_max, \ dim_t panel_dim_off, \ dim_t panel_len_off, \ ctype* restrict kappa, \ ctype* restrict c, inc_t incc, inc_t ldc, \ ctype* restrict p, inc_t ldp, \ inc_t is_p, \ cntx_t* cntx, \ void* params \ ); INSERT_GENTDEF( packm ) // NOTE: the following macros generate packm kernel function type definitions // that are "ctyped" and void-typed, for each of the floating-point datatypes. // packm_ker #undef GENTDEF #define GENTDEF( ctype, ch, opname, tsuf ) \ \ typedef void (*PASTECH3(ch,opname,_ker,tsuf)) \ ( \ conj_t conja, \ pack_t schema, \ dim_t cdim, \ dim_t n, \ dim_t n_max, \ ctype* restrict kappa, \ ctype* restrict a, inc_t inca, inc_t lda, \ ctype* restrict p, inc_t ldp, \ cntx_t* restrict cntx \ ); INSERT_GENTDEF( packm_cxk ) // unpackm_ker #undef GENTDEF #define GENTDEF( ctype, ch, opname, tsuf ) \ \ typedef void (*PASTECH3(ch,opname,_ker,tsuf)) \ ( \ conj_t conjp, \ dim_t n, \ ctype* restrict kappa, \ ctype* restrict p, inc_t ldp, \ ctype* restrict a, inc_t inca, inc_t lda, \ cntx_t* restrict cntx \ ); INSERT_GENTDEF( unpackm_cxk ) // packm_1er_ker #undef GENTDEF #define GENTDEF( ctype, ch, opname, tsuf ) \ \ typedef void (*PASTECH3(ch,opname,_ker,tsuf)) \ ( \ conj_t conja, \ pack_t schema, \ dim_t cdim, \ dim_t n, \ dim_t n_max, \ ctype* restrict kappa, \ ctype* restrict a, inc_t inca, inc_t lda, \ ctype* restrict p, inc_t ldp, \ cntx_t* restrict cntx \ ); INSERT_GENTDEF( packm_cxk_1er ) #endif blis-0.9.0/frame/1m/bli_l1m_ker.h000066400000000000000000000065631422157504600164310ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Define template prototypes for level-1m kernels. // // Note: Instead of defining function prototype macro templates and then // instantiating those macros to define the individual function prototypes, // we simply alias the official operations' prototypes as defined in // bli_l1m_ker_prot.h. // native packm kernels #undef GENTPROT #define GENTPROT PACKM_KER_PROT INSERT_GENTPROT_BASIC0( packm_2xk_ker_name ) INSERT_GENTPROT_BASIC0( packm_3xk_ker_name ) INSERT_GENTPROT_BASIC0( packm_4xk_ker_name ) INSERT_GENTPROT_BASIC0( packm_6xk_ker_name ) INSERT_GENTPROT_BASIC0( packm_8xk_ker_name ) INSERT_GENTPROT_BASIC0( packm_10xk_ker_name ) INSERT_GENTPROT_BASIC0( packm_12xk_ker_name ) INSERT_GENTPROT_BASIC0( packm_14xk_ker_name ) INSERT_GENTPROT_BASIC0( packm_16xk_ker_name ) INSERT_GENTPROT_BASIC0( packm_24xk_ker_name ) // native unpackm kernels #undef GENTPROT #define GENTPROT UNPACKM_KER_PROT INSERT_GENTPROT_BASIC0( unpackm_2xk_ker_name ) INSERT_GENTPROT_BASIC0( unpackm_4xk_ker_name ) INSERT_GENTPROT_BASIC0( unpackm_6xk_ker_name ) INSERT_GENTPROT_BASIC0( unpackm_8xk_ker_name ) INSERT_GENTPROT_BASIC0( unpackm_10xk_ker_name ) INSERT_GENTPROT_BASIC0( unpackm_12xk_ker_name ) INSERT_GENTPROT_BASIC0( unpackm_14xk_ker_name ) INSERT_GENTPROT_BASIC0( unpackm_16xk_ker_name ) // 1e/1r packm kernels #undef GENTPROT #define GENTPROT PACKM_1ER_KER_PROT INSERT_GENTPROT_BASIC0( packm_2xk_1er_ker_name ) INSERT_GENTPROT_BASIC0( packm_4xk_1er_ker_name ) INSERT_GENTPROT_BASIC0( packm_6xk_1er_ker_name ) INSERT_GENTPROT_BASIC0( packm_8xk_1er_ker_name ) INSERT_GENTPROT_BASIC0( packm_10xk_1er_ker_name ) INSERT_GENTPROT_BASIC0( packm_12xk_1er_ker_name ) INSERT_GENTPROT_BASIC0( packm_14xk_1er_ker_name ) INSERT_GENTPROT_BASIC0( packm_16xk_1er_ker_name ) blis-0.9.0/frame/1m/bli_l1m_ker_prot.h000066400000000000000000000056611422157504600174730ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Define template prototypes for level-1m kernels. // // native packm kernels #define PACKM_KER_PROT( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ conj_t conja, \ pack_t schema, \ dim_t cdim, \ dim_t n, \ dim_t n_max, \ ctype* restrict kappa, \ ctype* restrict a, inc_t inca, inc_t lda, \ ctype* restrict p, inc_t ldp, \ cntx_t* restrict cntx \ ); // native unpackm kernels #define UNPACKM_KER_PROT( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ conj_t conja, \ dim_t n, \ ctype* restrict kappa, \ ctype* restrict p, inc_t ldp, \ ctype* restrict a, inc_t inca, inc_t lda, \ cntx_t* restrict cntx \ ); // 1e/1r packm kernels #define PACKM_1ER_KER_PROT( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ conj_t conja, \ pack_t schema, \ dim_t cdim, \ dim_t n, \ dim_t n_max, \ ctype* restrict kappa, \ ctype* restrict a, inc_t inca, inc_t lda, \ ctype* restrict p, inc_t ldp, \ cntx_t* restrict cntx \ ); blis-0.9.0/frame/1m/bli_l1m_oapi.c000066400000000000000000000274741422157504600165770ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // Guard the function definitions so that they are only compiled when // #included from files that define the object API macros. #ifdef BLIS_ENABLE_OAPI // // Define object-based interfaces. // #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC(opname,EX_SUF) \ ( \ obj_t* x, \ obj_t* y \ BLIS_OAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_OAPI_EX_DECLS \ \ num_t dt = bli_obj_dt( x ); \ \ doff_t diagoffx = bli_obj_diag_offset( x ); \ diag_t diagx = bli_obj_diag( x ); \ uplo_t uplox = bli_obj_uplo( x ); \ trans_t transx = bli_obj_conjtrans_status( x ); \ dim_t m = bli_obj_length( y ); \ dim_t n = bli_obj_width( y ); \ void* buf_x = bli_obj_buffer_at_off( x ); \ inc_t rs_x = bli_obj_row_stride( x ); \ inc_t cs_x = bli_obj_col_stride( x ); \ void* buf_y = bli_obj_buffer_at_off( y ); \ inc_t rs_y = bli_obj_row_stride( y ); \ inc_t cs_y = bli_obj_col_stride( y ); \ \ if ( bli_error_checking_is_enabled() ) \ PASTEMAC(opname,_check)( x, y ); \ \ /* Query a type-specific function pointer, except one that uses void* for function arguments instead of typed pointers. */ \ PASTECH2(opname,BLIS_TAPI_EX_SUF,_vft) f = \ PASTEMAC2(opname,BLIS_TAPI_EX_SUF,_qfp)( dt ); \ \ f \ ( \ diagoffx, \ diagx, \ uplox, \ transx, \ m, \ n, \ buf_x, rs_x, cs_x, \ buf_y, rs_y, cs_y, \ cntx, \ rntm \ ); \ } GENFRONT( addm ) GENFRONT( copym ) GENFRONT( subm ) #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC(opname,EX_SUF) \ ( \ obj_t* alpha, \ obj_t* x, \ obj_t* y \ BLIS_OAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_OAPI_EX_DECLS \ \ num_t dt = bli_obj_dt( x ); \ \ doff_t diagoffx = bli_obj_diag_offset( x ); \ diag_t diagx = bli_obj_diag( x ); \ uplo_t uplox = bli_obj_uplo( x ); \ trans_t transx = bli_obj_conjtrans_status( x ); \ dim_t m = bli_obj_length( y ); \ dim_t n = bli_obj_width( y ); \ void* buf_x = bli_obj_buffer_at_off( x ); \ inc_t rs_x = bli_obj_row_stride( x ); \ inc_t cs_x = bli_obj_col_stride( x ); \ void* buf_y = bli_obj_buffer_at_off( y ); \ inc_t rs_y = bli_obj_row_stride( y ); \ inc_t cs_y = bli_obj_col_stride( y ); \ \ void* buf_alpha; \ \ obj_t alpha_local; \ \ if ( bli_error_checking_is_enabled() ) \ PASTEMAC(opname,_check)( alpha, x, y ); \ \ /* Create local copy-casts of scalars (and apply internal conjugation as needed). */ \ bli_obj_scalar_init_detached_copy_of( dt, BLIS_NO_CONJUGATE, \ alpha, &alpha_local ); \ buf_alpha = bli_obj_buffer_for_1x1( dt, &alpha_local ); \ \ /* Query a type-specific function pointer, except one that uses void* for function arguments instead of typed pointers. */ \ PASTECH2(opname,BLIS_TAPI_EX_SUF,_vft) f = \ PASTEMAC2(opname,BLIS_TAPI_EX_SUF,_qfp)( dt ); \ \ f \ ( \ diagoffx, \ diagx, \ uplox, \ transx, \ m, \ n, \ buf_alpha, \ buf_x, rs_x, cs_x, \ buf_y, rs_y, cs_y, \ cntx, \ rntm \ ); \ } GENFRONT( axpym ) GENFRONT( scal2m ) #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC(opname,EX_SUF) \ ( \ obj_t* alpha, \ obj_t* x \ BLIS_OAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_OAPI_EX_DECLS \ \ num_t dt = bli_obj_dt( x ); \ \ /* conj_t conjalpha = bli_obj_conj_status( alpha ); */ \ doff_t diagoffx = bli_obj_diag_offset( x ); \ diag_t diagx = bli_obj_diag( x ); \ uplo_t uplox = bli_obj_uplo( x ); \ dim_t m = bli_obj_length( x ); \ dim_t n = bli_obj_width( x ); \ void* buf_x = bli_obj_buffer_at_off( x ); \ inc_t rs_x = bli_obj_row_stride( x ); \ inc_t cs_x = bli_obj_col_stride( x ); \ \ void* buf_alpha; \ \ obj_t alpha_local; \ obj_t x_local; \ \ if ( bli_error_checking_is_enabled() ) \ PASTEMAC(opname,_check)( alpha, x ); \ \ /* Alias x to x_local so we can apply alpha if it is non-unit. */ \ bli_obj_alias_to( x, &x_local ); \ \ /* If alpha is non-unit, apply it to the scalar attached to x. */ \ if ( !bli_obj_equals( alpha, &BLIS_ONE ) ) \ { \ /* Create a local copy-cast of alpha (and apply internal conjugation as needed). */ \ bli_obj_scalar_init_detached_copy_of( dt, BLIS_NO_CONJUGATE, \ alpha, &alpha_local ); \ \ bli_obj_scalar_apply_scalar( &alpha_local, &x_local ); \ } \ \ /* Grab the address of the internal scalar buffer for the scalar attached to x. */ \ buf_alpha = bli_obj_internal_scalar_buffer( &x_local ); \ \ /* Query a type-specific function pointer, except one that uses void* for function arguments instead of typed pointers. */ \ PASTECH2(opname,BLIS_TAPI_EX_SUF,_vft) f = \ PASTEMAC2(opname,BLIS_TAPI_EX_SUF,_qfp)( dt ); \ \ f \ ( \ BLIS_NO_CONJUGATE, /* internal conjugation applied during copy-cast. */ \ diagoffx, \ diagx, \ uplox, \ m, \ n, \ buf_alpha, \ buf_x, rs_x, cs_x, \ cntx, \ rntm \ ); \ } GENFRONT( scalm ) #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC(opname,EX_SUF) \ ( \ obj_t* alpha, \ obj_t* x \ BLIS_OAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_OAPI_EX_DECLS \ \ num_t dt = bli_obj_dt( x ); \ \ /* conj_t conjalpha = bli_obj_conj_status( alpha ); */ \ doff_t diagoffx = bli_obj_diag_offset( x ); \ diag_t diagx = bli_obj_diag( x ); \ uplo_t uplox = bli_obj_uplo( x ); \ dim_t m = bli_obj_length( x ); \ dim_t n = bli_obj_width( x ); \ void* buf_x = bli_obj_buffer_at_off( x ); \ inc_t rs_x = bli_obj_row_stride( x ); \ inc_t cs_x = bli_obj_col_stride( x ); \ \ void* buf_alpha; \ \ obj_t alpha_local; \ \ if ( bli_error_checking_is_enabled() ) \ PASTEMAC(opname,_check)( alpha, x ); \ \ /* Create local copy-casts of scalars (and apply internal conjugation as needed). */ \ bli_obj_scalar_init_detached_copy_of( dt, BLIS_NO_CONJUGATE, \ alpha, &alpha_local ); \ buf_alpha = bli_obj_buffer_for_1x1( dt, &alpha_local ); \ \ /* Query a type-specific function pointer, except one that uses void* for function arguments instead of typed pointers. */ \ PASTECH2(opname,BLIS_TAPI_EX_SUF,_vft) f = \ PASTEMAC2(opname,BLIS_TAPI_EX_SUF,_qfp)( dt ); \ \ f \ ( \ BLIS_NO_CONJUGATE, /* internal conjugation applied during copy-cast. */ \ diagoffx, \ diagx, \ uplox, \ m, \ n, \ buf_alpha, \ buf_x, rs_x, cs_x, \ cntx, \ rntm \ ); \ } GENFRONT( setm ) #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC(opname,EX_SUF) \ ( \ obj_t* x, \ obj_t* beta, \ obj_t* y \ BLIS_OAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_OAPI_EX_DECLS \ \ if ( bli_obj_dt( x ) != bli_obj_dt( y ) ) \ return bli_xpbym_md( x, beta, y ); \ \ num_t dt = bli_obj_dt( x ); \ \ doff_t diagoffx = bli_obj_diag_offset( x ); \ diag_t diagx = bli_obj_diag( x ); \ uplo_t uplox = bli_obj_uplo( x ); \ trans_t transx = bli_obj_conjtrans_status( x ); \ dim_t m = bli_obj_length( y ); \ dim_t n = bli_obj_width( y ); \ void* buf_x = bli_obj_buffer_at_off( x ); \ inc_t rs_x = bli_obj_row_stride( x ); \ inc_t cs_x = bli_obj_col_stride( x ); \ void* buf_y = bli_obj_buffer_at_off( y ); \ inc_t rs_y = bli_obj_row_stride( y ); \ inc_t cs_y = bli_obj_col_stride( y ); \ \ void* buf_beta; \ \ obj_t beta_local; \ \ if ( bli_error_checking_is_enabled() ) \ PASTEMAC(opname,_check)( x, beta, y ); \ \ /* Create local copy-casts of scalars (and apply internal conjugation as needed). */ \ bli_obj_scalar_init_detached_copy_of( dt, BLIS_NO_CONJUGATE, \ beta, &beta_local ); \ buf_beta = bli_obj_buffer_for_1x1( dt, &beta_local ); \ \ /* Query a type-specific function pointer, except one that uses void* for function arguments instead of typed pointers. */ \ PASTECH2(opname,BLIS_TAPI_EX_SUF,_vft) f = \ PASTEMAC2(opname,BLIS_TAPI_EX_SUF,_qfp)( dt ); \ \ f \ ( \ diagoffx, \ diagx, \ uplox, \ transx, \ m, \ n, \ buf_x, rs_x, cs_x, \ buf_beta, \ buf_y, rs_y, cs_y, \ cntx, \ rntm \ ); \ } GENFRONT( xpbym ) #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC(opname,EX_SUF) \ ( \ obj_t* x, \ obj_t* beta, \ obj_t* y \ BLIS_OAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_OAPI_EX_DECLS \ \ num_t dtx = bli_obj_dt( x ); \ num_t dty = bli_obj_dt( y ); \ \ doff_t diagoffx = bli_obj_diag_offset( x ); \ diag_t diagx = bli_obj_diag( x ); \ uplo_t uplox = bli_obj_uplo( x ); \ trans_t transx = bli_obj_conjtrans_status( x ); \ dim_t m = bli_obj_length( y ); \ dim_t n = bli_obj_width( y ); \ void* buf_x = bli_obj_buffer_at_off( x ); \ inc_t rs_x = bli_obj_row_stride( x ); \ inc_t cs_x = bli_obj_col_stride( x ); \ void* buf_y = bli_obj_buffer_at_off( y ); \ inc_t rs_y = bli_obj_row_stride( y ); \ inc_t cs_y = bli_obj_col_stride( y ); \ \ void* buf_beta; \ \ obj_t beta_local; \ \ /* Create local copy-casts of scalars (and apply internal conjugation as needed). */ \ bli_obj_scalar_init_detached_copy_of( dty, BLIS_NO_CONJUGATE, \ beta, &beta_local ); \ buf_beta = bli_obj_buffer_for_1x1( dty, &beta_local ); \ \ /* Query a (multi) type-specific function pointer, except one that uses void* for function arguments instead of typed pointers. */ \ PASTECH2(opname,BLIS_TAPI_EX_SUF,_vft) f = \ PASTEMAC2(opname,BLIS_TAPI_EX_SUF,_qfp2)( dtx, dty ); \ \ f \ ( \ diagoffx, \ diagx, \ uplox, \ transx, \ m, \ n, \ buf_x, rs_x, cs_x, \ buf_beta, \ buf_y, rs_y, cs_y, \ cntx, \ rntm \ ); \ } GENFRONT( xpbym_md ) #endif blis-0.9.0/frame/1m/bli_l1m_oapi.h000066400000000000000000000051431422157504600165710ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype object-based interfaces. // #undef GENPROT #define GENPROT( opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC(opname,EX_SUF) \ ( \ obj_t* x, \ obj_t* y \ BLIS_OAPI_EX_PARAMS \ ); GENPROT( addm ) GENPROT( copym ) GENPROT( subm ) #undef GENPROT #define GENPROT( opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC(opname,EX_SUF) \ ( \ obj_t* alpha, \ obj_t* x, \ obj_t* y \ BLIS_OAPI_EX_PARAMS \ ); GENPROT( axpym ) GENPROT( scal2m ) #undef GENPROT #define GENPROT( opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC(opname,EX_SUF) \ ( \ obj_t* alpha, \ obj_t* x \ BLIS_OAPI_EX_PARAMS \ ); GENPROT( scalm ) GENPROT( setm ) #undef GENPROT #define GENPROT( opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC(opname,EX_SUF) \ ( \ obj_t* x, \ obj_t* beta, \ obj_t* y \ BLIS_OAPI_EX_PARAMS \ ); GENPROT( xpbym ) GENPROT( xpbym_md ) blis-0.9.0/frame/1m/bli_l1m_oapi_ba.c000066400000000000000000000036701422157504600172310ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // Include cpp macros that instantiate the API definition templates as // omitting expert parameters. #include "bli_oapi_ba.h" // Define the macro protecting the object API definitions. #define BLIS_ENABLE_OAPI // Include the object API definitions here. #include "bli_l1m_oapi.c" blis-0.9.0/frame/1m/bli_l1m_oapi_ex.c000066400000000000000000000036661422157504600172700ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // Include cpp macros that instantiate the API definition templates as // having expert parameters. #include "bli_oapi_ex.h" // Define the macro protecting the object API definitions. #define BLIS_ENABLE_OAPI // Include the object API definitions here. #include "bli_l1m_oapi.c" blis-0.9.0/frame/1m/bli_l1m_oft_var.h000066400000000000000000000043201422157504600172750ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_L1M_OFT_VAR_H #define BLIS_L1M_OFT_VAR_H // // -- Level-3 variant function types ------------------------------------------- // #undef GENTDEF #define GENTDEF( opname ) \ \ typedef void (*PASTECH(opname,_var_oft)) \ ( \ obj_t* a, \ obj_t* p, \ cntx_t* cntx, \ rntm_t* rntm, \ cntl_t* cntl, \ thrinfo_t* thread \ ); GENTDEF( packm ) #undef GENTDEF #define GENTDEF( opname ) \ \ typedef void (*PASTECH(opname,_var_oft)) \ ( \ obj_t* p, \ obj_t* a, \ cntx_t* cntx, \ cntl_t* cntl, \ thrinfo_t* thread \ ); GENTDEF( unpackm ) #endif blis-0.9.0/frame/1m/bli_l1m_tapi.c000066400000000000000000000271371422157504600166000ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // Guard the function definitions so that they are only compiled when // #included from files that define the typed API macros. #ifdef BLIS_ENABLE_TAPI // // Define BLAS-like interfaces with typed operands. // #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, auxker ) \ \ void PASTEMAC2(ch,opname,EX_SUF) \ ( \ doff_t diagoffx, \ diag_t diagx, \ uplo_t uplox, \ trans_t transx, \ dim_t m, \ dim_t n, \ ctype* x, inc_t rs_x, inc_t cs_x, \ ctype* y, inc_t rs_y, inc_t cs_y \ BLIS_TAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_TAPI_EX_DECLS \ \ if ( bli_zero_dim2( m, n ) ) return; \ \ /* Obtain a valid context from the gks if necessary. */ \ if ( cntx == NULL ) cntx = bli_gks_query_cntx(); \ \ /* Invoke the helper variant, which loops over the appropriate kernel to implement the current operation. */ \ PASTEMAC2(ch,opname,_unb_var1) \ ( \ diagoffx, \ diagx, \ uplox, \ transx, \ m, \ n, \ x, rs_x, cs_x, \ y, rs_y, cs_y, \ cntx, \ rntm \ ); \ \ /* When the diagonal of an upper- or lower-stored matrix is unit, we handle it with a separate post-processing step. */ \ if ( bli_is_upper_or_lower( uplox ) && \ bli_is_unit_diag( diagx ) ) \ { \ PASTEMAC2(ch,auxker,BLIS_TAPI_EX_SUF) \ ( \ diagoffx, \ diagx, \ transx, \ m, \ n, \ x, rs_x, cs_x, \ y, rs_y, cs_y, \ cntx, \ rntm \ ); \ } \ } INSERT_GENTFUNC_BASIC( addm, addd ) INSERT_GENTFUNC_BASIC( subm, subd ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname ) \ \ void PASTEMAC2(ch,opname,EX_SUF) \ ( \ doff_t diagoffx, \ diag_t diagx, \ uplo_t uplox, \ trans_t transx, \ dim_t m, \ dim_t n, \ ctype* x, inc_t rs_x, inc_t cs_x, \ ctype* y, inc_t rs_y, inc_t cs_y \ BLIS_TAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_TAPI_EX_DECLS \ \ if ( bli_zero_dim2( m, n ) ) return; \ \ /* Obtain a valid context from the gks if necessary. */ \ if ( cntx == NULL ) cntx = bli_gks_query_cntx(); \ \ /* Invoke the helper variant, which loops over the appropriate kernel to implement the current operation. */ \ PASTEMAC2(ch,opname,_unb_var1) \ ( \ diagoffx, \ diagx, \ uplox, \ transx, \ m, \ n, \ x, rs_x, cs_x, \ y, rs_y, cs_y, \ cntx, \ rntm \ ); \ \ /* When the diagonal of an upper- or lower-stored matrix is unit, we handle it with a separate post-processing step. */ \ if ( bli_is_upper_or_lower( uplox ) && \ bli_is_unit_diag( diagx ) ) \ { \ doff_t diagoffy = diagoffx; \ ctype* one = PASTEMAC(ch,1); \ \ if ( bli_does_trans( transx ) ) \ bli_negate_diag_offset( &diagoffy ); \ \ PASTEMAC2(ch,setd,BLIS_TAPI_EX_SUF) \ ( \ BLIS_NO_CONJUGATE, \ diagoffy, \ m, \ n, \ one, \ y, rs_y, cs_y, \ cntx, \ rntm \ ); \ } \ } INSERT_GENTFUNC_BASIC0( copym ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname ) \ \ void PASTEMAC2(ch,opname,EX_SUF) \ ( \ doff_t diagoffx, \ diag_t diagx, \ uplo_t uplox, \ trans_t transx, \ dim_t m, \ dim_t n, \ ctype* alpha, \ ctype* x, inc_t rs_x, inc_t cs_x, \ ctype* y, inc_t rs_y, inc_t cs_y \ BLIS_TAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_TAPI_EX_DECLS \ \ if ( bli_zero_dim2( m, n ) ) return; \ \ /* If alpha is zero, then the entire operation is a no-op. */ \ if ( PASTEMAC(ch,eq0)( *alpha ) ) return; \ \ /* Obtain a valid context from the gks if necessary. */ \ if ( cntx == NULL ) cntx = bli_gks_query_cntx(); \ \ /* Invoke the helper variant, which loops over the appropriate kernel to implement the current operation. */ \ PASTEMAC2(ch,opname,_unb_var1) \ ( \ diagoffx, \ diagx, \ uplox, \ transx, \ m, \ n, \ alpha, \ x, rs_x, cs_x, \ y, rs_y, cs_y, \ cntx, \ rntm \ ); \ \ /* When the diagonal of an upper- or lower-stored matrix is unit, we handle it with a separate post-processing step. */ \ if ( bli_is_upper_or_lower( uplox ) && \ bli_is_unit_diag( diagx ) ) \ { \ PASTEMAC2(ch,axpyd,BLIS_TAPI_EX_SUF) \ ( \ diagoffx, \ diagx, \ transx, \ m, \ n, \ alpha, \ x, rs_x, cs_x, \ y, rs_y, cs_y, \ cntx, \ rntm \ ); \ } \ } INSERT_GENTFUNC_BASIC0( axpym ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname ) \ \ void PASTEMAC2(ch,opname,EX_SUF) \ ( \ doff_t diagoffx, \ diag_t diagx, \ uplo_t uplox, \ trans_t transx, \ dim_t m, \ dim_t n, \ ctype* alpha, \ ctype* x, inc_t rs_x, inc_t cs_x, \ ctype* y, inc_t rs_y, inc_t cs_y \ BLIS_TAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_TAPI_EX_DECLS \ \ if ( bli_zero_dim2( m, n ) ) return; \ \ /* Obtain a valid context from the gks if necessary. */ \ if ( cntx == NULL ) cntx = bli_gks_query_cntx(); \ \ /* If alpha is zero, then we set the output matrix to zero. This seemingly minor optimization is important because it will clear any NaNs and Infs in x that would otherwise propogate. */ \ if ( PASTEMAC(ch,eq0)( *alpha ) ) \ { \ \ PASTEMAC2(ch,setm,BLIS_TAPI_EX_SUF) \ ( \ BLIS_NO_CONJUGATE, \ diagoffx, \ diagx, \ uplox, \ m, \ n, \ alpha, \ y, rs_y, cs_y, \ cntx, \ rntm \ ); \ return; \ } \ \ /* Invoke the helper variant, which loops over the appropriate kernel to implement the current operation. */ \ PASTEMAC2(ch,opname,_unb_var1) \ ( \ diagoffx, \ diagx, \ uplox, \ transx, \ m, \ n, \ alpha, \ x, rs_x, cs_x, \ y, rs_y, cs_y, \ cntx, \ rntm \ ); \ \ /* When the diagonal of an upper- or lower-stored matrix is unit, we handle it with a separate post-processing step. */ \ if ( bli_is_upper_or_lower( uplox ) && \ bli_is_unit_diag( diagx ) ) \ { \ doff_t diagoffy = diagoffx; \ \ if ( bli_does_trans( transx ) ) \ bli_negate_diag_offset( &diagoffy ); \ \ PASTEMAC2(ch,setd,BLIS_TAPI_EX_SUF) \ ( \ BLIS_NO_CONJUGATE, \ diagoffy, \ m, \ n, \ alpha, \ y, rs_y, cs_y, \ cntx, \ rntm \ ); \ } \ } INSERT_GENTFUNC_BASIC0( scal2m ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname ) \ \ void PASTEMAC2(ch,opname,EX_SUF) \ ( \ conj_t conjalpha, \ doff_t diagoffx, \ diag_t diagx, \ uplo_t uplox, \ dim_t m, \ dim_t n, \ ctype* alpha, \ ctype* x, inc_t rs_x, inc_t cs_x \ BLIS_TAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_TAPI_EX_DECLS \ \ if ( bli_zero_dim2( m, n ) ) return; \ \ /* Obtain a valid context from the gks if necessary. */ \ if ( cntx == NULL ) cntx = bli_gks_query_cntx(); \ \ /* Invoke the helper variant, which loops over the appropriate kernel to implement the current operation. */ \ PASTEMAC2(ch,opname,_unb_var1) \ ( \ conjalpha, \ diagoffx, \ diagx, \ uplox, \ m, \ n, \ alpha, \ x, rs_x, cs_x, \ cntx, \ rntm \ ); \ } INSERT_GENTFUNC_BASIC0( scalm ) INSERT_GENTFUNC_BASIC0( setm ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname ) \ \ void PASTEMAC2(ch,opname,EX_SUF) \ ( \ doff_t diagoffx, \ diag_t diagx, \ uplo_t uplox, \ trans_t transx, \ dim_t m, \ dim_t n, \ ctype* x, inc_t rs_x, inc_t cs_x, \ ctype* beta, \ ctype* y, inc_t rs_y, inc_t cs_y \ BLIS_TAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_TAPI_EX_DECLS \ \ if ( bli_zero_dim2( m, n ) ) return; \ \ /* Obtain a valid context from the gks if necessary. */ \ if ( cntx == NULL ) cntx = bli_gks_query_cntx(); \ \ /* If beta is zero, then the operation reduces to copym. */ \ if ( PASTEMAC(ch,eq0)( *beta ) ) \ { \ PASTEMAC2(ch,copym,_unb_var1) \ ( \ diagoffx, \ diagx, \ uplox, \ transx, \ m, \ n, \ x, rs_x, cs_x, \ y, rs_y, cs_y, \ cntx, \ rntm \ ); \ \ return; \ } \ \ /* Invoke the helper variant, which loops over the appropriate kernel to implement the current operation. */ \ PASTEMAC2(ch,opname,_unb_var1) \ ( \ diagoffx, \ diagx, \ uplox, \ transx, \ m, \ n, \ x, rs_x, cs_x, \ beta, \ y, rs_y, cs_y, \ cntx, \ rntm \ ); \ \ /* When the diagonal of an upper- or lower-stored matrix is unit, we handle it with a separate post-processing step. */ \ if ( bli_is_upper_or_lower( uplox ) && \ bli_is_unit_diag( diagx ) ) \ { \ PASTEMAC2(ch,xpbyd,BLIS_TAPI_EX_SUF) \ ( \ diagoffx, \ diagx, \ transx, \ m, \ n, \ x, rs_x, cs_x, \ beta, \ y, rs_y, cs_y, \ cntx, \ rntm \ ); \ } \ } INSERT_GENTFUNC_BASIC0( xpbym ) #undef GENTFUNC2 #define GENTFUNC2( ctype_x, ctype_y, chx, chy, opname ) \ \ void PASTEMAC3(chx,chy,opname,EX_SUF) \ ( \ doff_t diagoffx, \ diag_t diagx, \ uplo_t uplox, \ trans_t transx, \ dim_t m, \ dim_t n, \ ctype_x* x, inc_t rs_x, inc_t cs_x, \ ctype_y* beta, \ ctype_y* y, inc_t rs_y, inc_t cs_y \ BLIS_TAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_TAPI_EX_DECLS \ \ if ( bli_zero_dim2( m, n ) ) return; \ \ /* Obtain a valid context from the gks if necessary. */ \ if ( cntx == NULL ) cntx = bli_gks_query_cntx(); \ \ /* If beta is zero, then the operation reduces to copym. */ \ if ( PASTEMAC(chy,eq0)( *beta ) ) \ { \ PASTEMAC2(chx,chy,castm) \ ( \ transx, \ m, \ n, \ x, rs_x, cs_x, \ y, rs_y, cs_y \ ); \ \ return; \ } \ \ /* Invoke the helper variant, which loops over the appropriate kernel to implement the current operation. */ \ PASTEMAC3(chx,chy,opname,_unb_var1) \ ( \ diagoffx, \ diagx, \ uplox, \ transx, \ m, \ n, \ x, rs_x, cs_x, \ beta, \ y, rs_y, cs_y, \ cntx, \ rntm \ ); \ } INSERT_GENTFUNC2_BASIC0( xpbym_md ) INSERT_GENTFUNC2_MIXDP0( xpbym_md ) #endif blis-0.9.0/frame/1m/bli_l1m_tapi.h000066400000000000000000000077741422157504600166120ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype BLAS-like interfaces with typed operands. // #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC2(ch,opname,EX_SUF) \ ( \ doff_t diagoffx, \ diag_t diagx, \ uplo_t uplox, \ trans_t transx, \ dim_t m, \ dim_t n, \ ctype* x, inc_t rs_x, inc_t cs_x, \ ctype* y, inc_t rs_y, inc_t cs_y \ BLIS_TAPI_EX_PARAMS \ ); INSERT_GENTPROT_BASIC0( addm ) INSERT_GENTPROT_BASIC0( copym ) INSERT_GENTPROT_BASIC0( subm ) #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC2(ch,opname,EX_SUF) \ ( \ doff_t diagoffx, \ diag_t diagx, \ uplo_t uplox, \ trans_t transx, \ dim_t m, \ dim_t n, \ ctype* alpha, \ ctype* x, inc_t rs_x, inc_t cs_x, \ ctype* y, inc_t rs_y, inc_t cs_y \ BLIS_TAPI_EX_PARAMS \ ); INSERT_GENTPROT_BASIC0( axpym ) INSERT_GENTPROT_BASIC0( scal2m ) #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC2(ch,opname,EX_SUF) \ ( \ conj_t conjalpha, \ doff_t diagoffx, \ diag_t diagx, \ uplo_t uplox, \ dim_t m, \ dim_t n, \ ctype* alpha, \ ctype* x, inc_t rs_x, inc_t cs_x \ BLIS_TAPI_EX_PARAMS \ ); INSERT_GENTPROT_BASIC0( scalm ) INSERT_GENTPROT_BASIC0( setm ) #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC2(ch,opname,EX_SUF) \ ( \ doff_t diagoffx, \ diag_t diagx, \ uplo_t uplox, \ trans_t transx, \ dim_t m, \ dim_t n, \ ctype* x, inc_t rs_x, inc_t cs_x, \ ctype* beta, \ ctype* y, inc_t rs_y, inc_t cs_y \ BLIS_TAPI_EX_PARAMS \ ); INSERT_GENTPROT_BASIC0( xpbym ) #undef GENTPROT2 #define GENTPROT2( ctype_x, ctype_y, chx, chy, opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC3(chx,chy,opname,EX_SUF) \ ( \ doff_t diagoffx, \ diag_t diagx, \ uplo_t uplox, \ trans_t transx, \ dim_t m, \ dim_t n, \ ctype_x* x, inc_t rs_x, inc_t cs_x, \ ctype_y* beta, \ ctype_y* y, inc_t rs_y, inc_t cs_y \ BLIS_TAPI_EX_PARAMS \ ); INSERT_GENTPROT2_BASIC0( xpbym_md ) INSERT_GENTPROT2_MIXDP0( xpbym_md ) blis-0.9.0/frame/1m/bli_l1m_tapi_ba.c000066400000000000000000000036661422157504600172430ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // Include cpp macros that instantiate the API definition templates as // omitting expert parameters. #include "bli_tapi_ba.h" // Define the macro protecting the typed API definitions. #define BLIS_ENABLE_TAPI // Include the typed API definitions here. #include "bli_l1m_tapi.c" blis-0.9.0/frame/1m/bli_l1m_tapi_ex.c000066400000000000000000000036641422157504600172730ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // Include cpp macros that instantiate the API definition templates as // having expert parameters. #include "bli_tapi_ex.h" // Define the macro protecting the typed API definitions. #define BLIS_ENABLE_TAPI // Include the typed API definitions here. #include "bli_l1m_tapi.c" blis-0.9.0/frame/1m/bli_l1m_unb_var1.c000066400000000000000000000354441422157504600173600ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // Define BLAS-like interfaces with typed operands. // #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, kername, kerid ) \ \ void PASTEMAC(ch,opname) \ ( \ doff_t diagoffx, \ diag_t diagx, \ uplo_t uplox, \ trans_t transx, \ dim_t m, \ dim_t n, \ ctype* x, inc_t rs_x, inc_t cs_x, \ ctype* y, inc_t rs_y, inc_t cs_y, \ cntx_t* cntx, \ rntm_t* rntm \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ uplo_t uplox_eff; \ conj_t conjx; \ dim_t n_iter; \ dim_t n_elem_max; \ inc_t ldx, incx; \ inc_t ldy, incy; \ dim_t ij0, n_shift; \ \ /* Set various loop parameters. */ \ bli_set_dims_incs_uplo_2m \ ( \ diagoffx, diagx, transx, \ uplox, m, n, rs_x, cs_x, rs_y, cs_y, \ &uplox_eff, &n_elem_max, &n_iter, &incx, &ldx, &incy, &ldy, \ &ij0, &n_shift \ ); \ \ if ( bli_is_zeros( uplox_eff ) ) return; \ \ /* Extract the conjugation component from the transx parameter. */ \ conjx = bli_extract_conj( transx ); \ \ /* Query the kernel needed for this operation. */ \ PASTECH2(ch,kername,_ker_ft) f = bli_cntx_get_l1v_ker_dt( dt, kerid, cntx ); \ \ /* Handle dense and upper/lower storage cases separately. */ \ if ( bli_is_dense( uplox_eff ) ) \ { \ for ( dim_t j = 0; j < n_iter; ++j ) \ { \ const dim_t n_elem = n_elem_max; \ \ ctype* x1 = x + (j )*ldx + (0 )*incx; \ ctype* y1 = y + (j )*ldy + (0 )*incy; \ \ /* Invoke the kernel with the appropriate parameters. */ \ f \ ( \ conjx, \ n_elem, \ x1, incx, \ y1, incy, \ cntx \ ); \ } \ } \ else \ { \ if ( bli_is_upper( uplox_eff ) ) \ { \ for ( dim_t j = 0; j < n_iter; ++j ) \ { \ const dim_t n_elem = bli_min( n_shift + j + 1, n_elem_max ); \ \ ctype* x1 = x + (ij0+j )*ldx + (0 )*incx; \ ctype* y1 = y + (ij0+j )*ldy + (0 )*incy; \ \ /* Invoke the kernel with the appropriate parameters. */ \ f \ ( \ conjx, \ n_elem, \ x1, incx, \ y1, incy, \ cntx \ ); \ } \ } \ else if ( bli_is_lower( uplox_eff ) ) \ { \ for ( dim_t j = 0; j < n_iter; ++j ) \ { \ const dim_t offi = bli_max( 0, ( doff_t )j - ( doff_t )n_shift ); \ const dim_t n_elem = n_elem_max - offi; \ \ ctype* x1 = x + (j )*ldx + (ij0+offi )*incx; \ ctype* y1 = y + (j )*ldy + (ij0+offi )*incy; \ \ /* Invoke the kernel with the appropriate parameters. */ \ f \ ( \ conjx, \ n_elem, \ x1, incx, \ y1, incy, \ cntx \ ); \ } \ } \ } \ } INSERT_GENTFUNC_BASIC2( addm_unb_var1, addv, BLIS_ADDV_KER ) INSERT_GENTFUNC_BASIC2( copym_unb_var1, copyv, BLIS_COPYV_KER ) INSERT_GENTFUNC_BASIC2( subm_unb_var1, subv, BLIS_SUBV_KER ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, kername, kerid ) \ \ void PASTEMAC(ch,opname) \ ( \ doff_t diagoffx, \ diag_t diagx, \ uplo_t uplox, \ trans_t transx, \ dim_t m, \ dim_t n, \ ctype* alpha, \ ctype* x, inc_t rs_x, inc_t cs_x, \ ctype* y, inc_t rs_y, inc_t cs_y, \ cntx_t* cntx, \ rntm_t* rntm \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ uplo_t uplox_eff; \ conj_t conjx; \ dim_t n_iter; \ dim_t n_elem_max; \ inc_t ldx, incx; \ inc_t ldy, incy; \ dim_t ij0, n_shift; \ \ /* Set various loop parameters. */ \ bli_set_dims_incs_uplo_2m \ ( \ diagoffx, diagx, transx, \ uplox, m, n, rs_x, cs_x, rs_y, cs_y, \ &uplox_eff, &n_elem_max, &n_iter, &incx, &ldx, &incy, &ldy, \ &ij0, &n_shift \ ); \ \ if ( bli_is_zeros( uplox_eff ) ) return; \ \ /* Extract the conjugation component from the transx parameter. */ \ conjx = bli_extract_conj( transx ); \ \ /* Query the kernel needed for this operation. */ \ PASTECH2(ch,kername,_ker_ft) f = bli_cntx_get_l1v_ker_dt( dt, kerid, cntx ); \ \ /* Handle dense and upper/lower storage cases separately. */ \ if ( bli_is_dense( uplox_eff ) ) \ { \ for ( dim_t j = 0; j < n_iter; ++j ) \ { \ const dim_t n_elem = n_elem_max; \ \ ctype* x1 = x + (j )*ldx + (0 )*incx; \ ctype* y1 = y + (j )*ldy + (0 )*incy; \ \ /* Invoke the kernel with the appropriate parameters. */ \ f \ ( \ conjx, \ n_elem, \ alpha, \ x1, incx, \ y1, incy, \ cntx \ ); \ } \ } \ else \ { \ if ( bli_is_upper( uplox_eff ) ) \ { \ for ( dim_t j = 0; j < n_iter; ++j ) \ { \ const dim_t n_elem = bli_min( n_shift + j + 1, n_elem_max ); \ \ ctype* x1 = x + (ij0+j )*ldx + (0 )*incx; \ ctype* y1 = y + (ij0+j )*ldy + (0 )*incy; \ \ /* Invoke the kernel with the appropriate parameters. */ \ f \ ( \ conjx, \ n_elem, \ alpha, \ x1, incx, \ y1, incy, \ cntx \ ); \ } \ } \ else if ( bli_is_lower( uplox_eff ) ) \ { \ for ( dim_t j = 0; j < n_iter; ++j ) \ { \ const dim_t offi = bli_max( 0, ( doff_t )j - ( doff_t )n_shift ); \ const dim_t n_elem = n_elem_max - offi; \ \ ctype* x1 = x + (j )*ldx + (ij0+offi )*incx; \ ctype* y1 = y + (j )*ldy + (ij0+offi )*incy; \ \ /* Invoke the kernel with the appropriate parameters. */ \ f \ ( \ conjx, \ n_elem, \ alpha, \ x1, incx, \ y1, incy, \ cntx \ ); \ } \ } \ } \ } INSERT_GENTFUNC_BASIC2( axpym_unb_var1, axpyv, BLIS_AXPYV_KER ) INSERT_GENTFUNC_BASIC2( scal2m_unb_var1, scal2v, BLIS_SCAL2V_KER ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, kername, kerid ) \ \ void PASTEMAC(ch,opname) \ ( \ conj_t conjalpha, \ doff_t diagoffx, \ diag_t diagx, \ uplo_t uplox, \ dim_t m, \ dim_t n, \ ctype* alpha, \ ctype* x, inc_t rs_x, inc_t cs_x, \ cntx_t* cntx, \ rntm_t* rntm \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ uplo_t uplox_eff; \ dim_t n_iter; \ dim_t n_elem_max; \ inc_t ldx, incx; \ dim_t ij0, n_shift; \ \ /* Set various loop parameters. */ \ bli_set_dims_incs_uplo_1m \ ( \ diagoffx, diagx, \ uplox, m, n, rs_x, cs_x, \ &uplox_eff, &n_elem_max, &n_iter, &incx, &ldx, \ &ij0, &n_shift \ ); \ \ if ( bli_is_zeros( uplox_eff ) ) return; \ \ /* Query the kernel needed for this operation. */ \ PASTECH2(ch,kername,_ker_ft) f = bli_cntx_get_l1v_ker_dt( dt, kerid, cntx ); \ \ /* Handle dense and upper/lower storage cases separately. */ \ if ( bli_is_dense( uplox_eff ) ) \ { \ for ( dim_t j = 0; j < n_iter; ++j ) \ { \ const dim_t n_elem = n_elem_max; \ \ ctype* x1 = x + (j )*ldx + (0 )*incx; \ \ /* Invoke the kernel with the appropriate parameters. */ \ f \ ( \ conjalpha, \ n_elem, \ alpha, \ x1, incx, \ cntx \ ); \ } \ } \ else \ { \ if ( bli_is_upper( uplox_eff ) ) \ { \ for ( dim_t j = 0; j < n_iter; ++j ) \ { \ const dim_t n_elem = bli_min( n_shift + j + 1, n_elem_max ); \ \ ctype* x1 = x + (ij0+j )*ldx + (0 )*incx; \ \ /* Invoke the kernel with the appropriate parameters. */ \ f \ ( \ conjalpha, \ n_elem, \ alpha, \ x1, incx, \ cntx \ ); \ } \ } \ else if ( bli_is_lower( uplox_eff ) ) \ { \ for ( dim_t j = 0; j < n_iter; ++j ) \ { \ const dim_t offi = bli_max( 0, ( doff_t )j - ( doff_t )n_shift ); \ const dim_t n_elem = n_elem_max - offi; \ \ ctype* x1 = x + (j )*ldx + (ij0+offi )*incx; \ \ /* Invoke the kernel with the appropriate parameters. */ \ f \ ( \ conjalpha, \ n_elem, \ alpha, \ x1, incx, \ cntx \ ); \ } \ } \ } \ } INSERT_GENTFUNC_BASIC2( scalm_unb_var1, scalv, BLIS_SCALV_KER ) INSERT_GENTFUNC_BASIC2( setm_unb_var1, setv, BLIS_SETV_KER ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, kername, kerid ) \ \ void PASTEMAC(ch,opname) \ ( \ doff_t diagoffx, \ diag_t diagx, \ uplo_t uplox, \ trans_t transx, \ dim_t m, \ dim_t n, \ ctype* x, inc_t rs_x, inc_t cs_x, \ ctype* beta, \ ctype* y, inc_t rs_y, inc_t cs_y, \ cntx_t* cntx, \ rntm_t* rntm \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ uplo_t uplox_eff; \ conj_t conjx; \ dim_t n_iter; \ dim_t n_elem_max; \ inc_t ldx, incx; \ inc_t ldy, incy; \ dim_t ij0, n_shift; \ \ /* Set various loop parameters. */ \ bli_set_dims_incs_uplo_2m \ ( \ diagoffx, diagx, transx, \ uplox, m, n, rs_x, cs_x, rs_y, cs_y, \ &uplox_eff, &n_elem_max, &n_iter, &incx, &ldx, &incy, &ldy, \ &ij0, &n_shift \ ); \ \ if ( bli_is_zeros( uplox_eff ) ) return; \ \ /* Extract the conjugation component from the transx parameter. */ \ conjx = bli_extract_conj( transx ); \ \ /* Query the kernel needed for this operation. */ \ PASTECH2(ch,kername,_ker_ft) f = bli_cntx_get_l1v_ker_dt( dt, kerid, cntx ); \ \ /* Handle dense and upper/lower storage cases separately. */ \ if ( bli_is_dense( uplox_eff ) ) \ { \ for ( dim_t j = 0; j < n_iter; ++j ) \ { \ const dim_t n_elem = n_elem_max; \ \ ctype* x1 = x + (j )*ldx + (0 )*incx; \ ctype* y1 = y + (j )*ldy + (0 )*incy; \ \ /* Invoke the kernel with the appropriate parameters. */ \ f \ ( \ conjx, \ n_elem, \ x1, incx, \ beta, \ y1, incy, \ cntx \ ); \ } \ } \ else \ { \ if ( bli_is_upper( uplox_eff ) ) \ { \ for ( dim_t j = 0; j < n_iter; ++j ) \ { \ const dim_t n_elem = bli_min( n_shift + j + 1, n_elem_max ); \ \ ctype* x1 = x + (ij0+j )*ldx + (0 )*incx; \ ctype* y1 = y + (ij0+j )*ldy + (0 )*incy; \ \ /* Invoke the kernel with the appropriate parameters. */ \ f \ ( \ conjx, \ n_elem, \ x1, incx, \ beta, \ y1, incy, \ cntx \ ); \ } \ } \ else if ( bli_is_lower( uplox_eff ) ) \ { \ for ( dim_t j = 0; j < n_iter; ++j ) \ { \ const dim_t offi = bli_max( 0, ( doff_t )j - ( doff_t )n_shift ); \ const dim_t n_elem = n_elem_max - offi; \ \ ctype* x1 = x + (j )*ldx + (ij0+offi )*incx; \ ctype* y1 = y + (j )*ldy + (ij0+offi )*incy; \ \ /* Invoke the kernel with the appropriate parameters. */ \ f \ ( \ conjx, \ n_elem, \ x1, incx, \ beta, \ y1, incy, \ cntx \ ); \ } \ } \ } \ } INSERT_GENTFUNC_BASIC2( xpbym_unb_var1, xpbyv, BLIS_XPBYV_KER ) #undef GENTFUNC2 #define GENTFUNC2( ctype_x, ctype_y, chx, chy, opname ) \ \ void PASTEMAC2(chx,chy,opname) \ ( \ doff_t diagoffx, \ diag_t diagx, \ uplo_t uplox, \ trans_t transx, \ dim_t m, \ dim_t n, \ ctype_x* x, inc_t rs_x, inc_t cs_x, \ ctype_y* beta, \ ctype_y* y, inc_t rs_y, inc_t cs_y, \ cntx_t* cntx, \ rntm_t* rntm \ ) \ { \ uplo_t uplox_eff; \ dim_t n_iter; \ dim_t n_elem_max; \ inc_t ldx, incx; \ inc_t ldy, incy; \ dim_t ij0, n_shift; \ \ /* Set various loop parameters. */ \ bli_set_dims_incs_uplo_2m \ ( \ diagoffx, diagx, transx, \ uplox, m, n, rs_x, cs_x, rs_y, cs_y, \ &uplox_eff, &n_elem_max, &n_iter, &incx, &ldx, &incy, &ldy, \ &ij0, &n_shift \ ); \ \ /* Extract the conjugation component from the transx parameter. */ \ /*conjx = bli_extract_conj( transx );*/ \ \ /* Handle dense and upper/lower storage cases separately. */ \ if ( PASTEMAC(chy,eq1)( *beta ) ) \ { \ if ( incx == 1 && incy == 1 ) \ { \ const dim_t n_elem = n_elem_max; \ \ for ( dim_t j = 0; j < n_iter; ++j ) \ { \ ctype_x* restrict x1 = x + (j )*ldx + (0 )*incx; \ ctype_y* restrict y1 = y + (j )*ldy + (0 )*incy; \ \ for ( dim_t i = 0; i < n_elem; ++i ) \ { \ PASTEMAC2(chx,chy,adds)( x1[i], y1[i] ); \ } \ } \ } \ else \ { \ const dim_t n_elem = n_elem_max; \ \ for ( dim_t j = 0; j < n_iter; ++j ) \ { \ ctype_x* restrict x1 = x + (j )*ldx + (0 )*incx; \ ctype_y* restrict y1 = y + (j )*ldy + (0 )*incy; \ \ ctype_x* restrict chi1 = x1; \ ctype_y* restrict psi1 = y1; \ \ for ( dim_t i = 0; i < n_elem; ++i ) \ { \ PASTEMAC2(chx,chy,adds)( *chi1, *psi1 ); \ \ chi1 += incx; \ psi1 += incy; \ } \ } \ } \ } \ else /* ( !PASTEMAC(chy,eq1)( *beta ) ) */ \ { \ if ( incx == 1 && incy == 1 ) \ { \ const dim_t n_elem = n_elem_max; \ \ for ( dim_t j = 0; j < n_iter; ++j ) \ { \ ctype_x* restrict x1 = x + (j )*ldx + (0 )*incx; \ ctype_y* restrict y1 = y + (j )*ldy + (0 )*incy; \ \ for ( dim_t i = 0; i < n_elem; ++i ) \ { \ PASTEMAC3(chx,chy,chy,xpbys)( x1[i], *beta, y1[i] ); \ } \ } \ } \ else \ { \ const dim_t n_elem = n_elem_max; \ \ for ( dim_t j = 0; j < n_iter; ++j ) \ { \ ctype_x* restrict x1 = x + (j )*ldx + (0 )*incx; \ ctype_y* restrict y1 = y + (j )*ldy + (0 )*incy; \ \ ctype_x* restrict chi1 = x1; \ ctype_y* restrict psi1 = y1; \ \ for ( dim_t i = 0; i < n_elem; ++i ) \ { \ PASTEMAC3(chx,chy,chy,xpbys)( *chi1, *beta, *psi1 ); \ \ chi1 += incx; \ psi1 += incy; \ } \ } \ } \ } \ } INSERT_GENTFUNC2_BASIC0( xpbym_md_unb_var1 ) INSERT_GENTFUNC2_MIXDP0( xpbym_md_unb_var1 ) blis-0.9.0/frame/1m/bli_l1m_unb_var1.h000066400000000000000000000100101422157504600173430ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype BLAS-like interfaces with typed operands. // #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ void PASTEMAC2(ch,opname,_unb_var1) \ ( \ doff_t diagoffx, \ diag_t diagx, \ uplo_t uplox, \ trans_t transx, \ dim_t m, \ dim_t n, \ ctype* x, inc_t rs_x, inc_t cs_x, \ ctype* y, inc_t rs_y, inc_t cs_y, \ cntx_t* cntx, \ rntm_t* rntm \ ); INSERT_GENTPROT_BASIC0( addm ) INSERT_GENTPROT_BASIC0( copym ) INSERT_GENTPROT_BASIC0( subm ) #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ void PASTEMAC2(ch,opname,_unb_var1) \ ( \ doff_t diagoffx, \ diag_t diagx, \ uplo_t uplox, \ trans_t transx, \ dim_t m, \ dim_t n, \ ctype* alpha, \ ctype* x, inc_t rs_x, inc_t cs_x, \ ctype* y, inc_t rs_y, inc_t cs_y, \ cntx_t* cntx, \ rntm_t* rntm \ ); INSERT_GENTPROT_BASIC0( axpym ) INSERT_GENTPROT_BASIC0( scal2m ) #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ void PASTEMAC2(ch,opname,_unb_var1) \ ( \ conj_t conjalpha, \ doff_t diagoffx, \ diag_t diagx, \ uplo_t uplox, \ dim_t m, \ dim_t n, \ ctype* alpha, \ ctype* x, inc_t rs_x, inc_t cs_x, \ cntx_t* cntx, \ rntm_t* rntm \ ); INSERT_GENTPROT_BASIC0( scalm ) INSERT_GENTPROT_BASIC0( setm ) #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ void PASTEMAC2(ch,opname,_unb_var1) \ ( \ doff_t diagoffx, \ diag_t diagx, \ uplo_t uplox, \ trans_t transx, \ dim_t m, \ dim_t n, \ ctype* x, inc_t rs_x, inc_t cs_x, \ ctype* beta, \ ctype* y, inc_t rs_y, inc_t cs_y, \ cntx_t* cntx, \ rntm_t* rntm \ ); INSERT_GENTPROT_BASIC0( xpbym ) #undef GENTPROT2 #define GENTPROT2( ctype_x, ctype_y, chx, chy, opname ) \ \ void PASTEMAC3(chx,chy,opname,_unb_var1) \ ( \ doff_t diagoffx, \ diag_t diagx, \ uplo_t uplox, \ trans_t transx, \ dim_t m, \ dim_t n, \ ctype_x* x, inc_t rs_x, inc_t cs_x, \ ctype_y* beta, \ ctype_y* y, inc_t rs_y, inc_t cs_y, \ cntx_t* cntx, \ rntm_t* rntm \ ); INSERT_GENTPROT2_BASIC0( xpbym_md ) INSERT_GENTPROT2_MIXDP0( xpbym_md ) blis-0.9.0/frame/1m/other/000077500000000000000000000000001422157504600152075ustar00rootroot00000000000000blis-0.9.0/frame/1m/other/bli_scalm.h000066400000000000000000000032461422157504600173120ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "bli_scalm_cntl.h" blis-0.9.0/frame/1m/other/bli_scalm_cntl.c000066400000000000000000000042051422157504600203210ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" cntl_t* bli_scalm_cntl_create_node ( void_fp var_func, cntl_t* sub_node ) { cntl_t* cntl; // It's important that we set the bszid field to BLIS_NO_PART to indicate // that no blocksize partitioning is performed. bli_cntl_free() will rely // on this information to know how to step through the thrinfo_t tree in // sync with the cntl_t tree. cntl = bli_cntl_create_node ( BLIS_NOID, BLIS_NO_PART, var_func, NULL, sub_node ); return cntl; } blis-0.9.0/frame/1m/other/bli_scalm_cntl.h000066400000000000000000000033551422157504600203330ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ cntl_t* bli_scalm_cntl_create_node ( void_fp var_func, cntl_t* sub_node ); blis-0.9.0/frame/1m/other/bli_scalm_int.c000066400000000000000000000064341422157504600201610ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define FUNCPTR_T scalm_fp typedef void (*FUNCPTR_T)( obj_t* alpha, obj_t* x, cntx_t* cntx ); static FUNCPTR_T vars[1][3] = { // unblocked optimized unblocked blocked { bli_scalm_ex, bli_scalm_ex, NULL } }; void bli_scalm_int( obj_t* alpha, obj_t* x, cntx_t* cntx, scalm_t* cntl ) { //obj_t x_local; varnum_t n; impl_t i; FUNCPTR_T f; // Return early if one of the matrix operands has a zero dimension. if ( bli_obj_has_zero_dim( x ) ) return; // Check parameters. if ( bli_error_checking_is_enabled() ) bli_scalm_check( alpha, x ); // First check if we are to skip this operation. if ( bli_cntl_is_noop( cntl ) ) return; // Return early if both alpha and the scalar attached to x are unit. if ( bli_obj_equals( alpha, &BLIS_ONE ) && bli_obj_scalar_equals( x, &BLIS_ONE ) ) return; // // This code has been disabled since we've now added the alpha // parameter back to the object interface to the underlying // scalm variant. // // Alias x to x_local so we can apply alpha if it is non-unit. //bli_obj_alias_to( *x, x_local ); // If alpha is non-unit, apply it to the scalar attached to x. //if ( !bli_obj_equals( alpha, &BLIS_ONE ) ) //{ // bli_obj_scalar_apply_scalar( alpha, &x_local ); //} // Extract the variant number and implementation type. n = bli_cntl_var_num( cntl ); i = bli_cntl_impl_type( cntl ); // Index into the variant array to extract the correct function pointer. f = vars[n][i]; // Invoke the variant. f( alpha, x, cntx ); } blis-0.9.0/frame/1m/other/bli_scalm_int.h000066400000000000000000000034261422157504600201640ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void bli_scalm_int( obj_t* alpha, obj_t* x, cntx_t* cntx, scalm_t* cntl ); blis-0.9.0/frame/1m/packm/000077500000000000000000000000001422157504600151615ustar00rootroot00000000000000blis-0.9.0/frame/1m/packm/bli_packm.h000066400000000000000000000042221422157504600172530ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "bli_packm_alloc.h" #include "bli_packm_cntl.h" #include "bli_packm_check.h" #include "bli_packm_init.h" #include "bli_packm_int.h" #include "bli_packm_scalar.h" #include "bli_packm_part.h" #include "bli_packm_struc_cxk.h" #include "bli_packm_struc_cxk_1er.h" #include "bli_packm_cxk.h" #include "bli_packm_cxk_1er.h" // Mixed datatype support. #ifdef BLIS_ENABLE_GEMM_MD #include "bli_packm_struc_cxk_md.h" #endif #include "bli_packm_blk_var1.h" blis-0.9.0/frame/1m/packm/bli_packm_alloc.c000066400000000000000000000067441422157504600204330ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2016, Hewlett Packard Enterprise Development LP 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void* bli_packm_alloc ( siz_t size_needed, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ) { // Query the pack buffer type from the control tree node. packbuf_t pack_buf_type = bli_cntl_packm_params_pack_buf_type( cntl ); return bli_packm_alloc_ex ( size_needed, pack_buf_type, rntm, cntl, thread ); } void* bli_packm_alloc_ex ( siz_t size_needed, packbuf_t pack_buf_type, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ) { // Query the address of the mem_t entry within the control tree node. mem_t* cntl_mem_p = bli_cntl_pack_mem( cntl ); mem_t* local_mem_p; mem_t local_mem_s; siz_t cntl_mem_size = 0; if ( bli_mem_is_alloc( cntl_mem_p ) ) cntl_mem_size = bli_mem_size( cntl_mem_p ); if ( cntl_mem_size < size_needed ) { if ( bli_thread_am_ochief( thread ) ) { // The chief thread releases the existing block associated with // the mem_t entry in the control tree, and then re-acquires a // new block, saving the associated mem_t entry to local_mem_s. if ( bli_mem_is_alloc( cntl_mem_p ) ) { bli_pba_release ( rntm, cntl_mem_p ); } bli_pba_acquire_m ( rntm, size_needed, pack_buf_type, &local_mem_s ); } // Broadcast the address of the chief thread's local mem_t entry to // all threads. local_mem_p = bli_thread_broadcast( thread, &local_mem_s ); // Save the chief thread's local mem_t entry to the mem_t field in // this thread's control tree node. *cntl_mem_p = *local_mem_p; // Barrier so that the master thread doesn't return from the function // before we are done reading. bli_thread_barrier( thread ); } return bli_mem_buffer( cntl_mem_p ); } blis-0.9.0/frame/1m/packm/bli_packm_alloc.h000066400000000000000000000037531422157504600204350ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ BLIS_EXPORT_BLIS void* bli_packm_alloc ( siz_t size_needed, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ); BLIS_EXPORT_BLIS void* bli_packm_alloc_ex ( siz_t size_needed, packbuf_t pack_buf_type, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ); blis-0.9.0/frame/1m/packm/bli_packm_blk_var1.c000066400000000000000000000263761422157504600210450ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" static func_t packm_struc_cxk_kers[BLIS_NUM_PACK_SCHEMA_TYPES] = { /* float (0) scomplex (1) double (2) dcomplex (3) */ // 0000 row/col panels { { bli_spackm_struc_cxk, bli_cpackm_struc_cxk, bli_dpackm_struc_cxk, bli_zpackm_struc_cxk, } }, // 0001 row/col panels: 1m-expanded (1e) { { NULL, bli_cpackm_struc_cxk_1er, NULL, bli_zpackm_struc_cxk_1er, } }, // 0010 row/col panels: 1m-reordered (1r) { { NULL, bli_cpackm_struc_cxk_1er, NULL, bli_zpackm_struc_cxk_1er, } }, }; static void_fp GENARRAY2_ALL(packm_struc_cxk_md,packm_struc_cxk_md); void bli_packm_blk_var1 ( obj_t* c, obj_t* p, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ) { // Extract various fields from the control tree. pack_t schema = bli_cntl_packm_params_pack_schema( cntl ); bool invdiag = bli_cntl_packm_params_does_invert_diag( cntl ); bool revifup = bli_cntl_packm_params_rev_iter_if_upper( cntl ); bool reviflo = bli_cntl_packm_params_rev_iter_if_lower( cntl ); // Every thread initializes p and determines the size of memory // block needed (which gets embedded into the otherwise "blank" mem_t // entry in the control tree node). Return early if no packing is required. if ( !bli_packm_init( c, p, cntx, rntm, cntl, thread ) ) return; // Check parameters. if ( bli_error_checking_is_enabled() ) bli_packm_int_check( c, p, cntx ); num_t dt_c = bli_obj_dt( c ); dim_t dt_c_size = bli_dt_size( dt_c ); num_t dt_p = bli_obj_dt( p ); dim_t dt_p_size = bli_dt_size( dt_p ); struc_t strucc = bli_obj_struc( c ); doff_t diagoffc = bli_obj_diag_offset( c ); diag_t diagc = bli_obj_diag( c ); uplo_t uploc = bli_obj_uplo( c ); conj_t conjc = bli_obj_conj_status( c ); dim_t iter_dim = bli_obj_length( p ); dim_t panel_len_full = bli_obj_width( p ); dim_t panel_len_max = bli_obj_padded_width( p ); char* c_cast = bli_obj_buffer_at_off( c ); inc_t incc = bli_obj_row_stride( c ); inc_t ldc = bli_obj_col_stride( c ); dim_t panel_dim_off = bli_obj_row_off( c ); dim_t panel_len_off = bli_obj_col_off( c ); char* p_cast = bli_obj_buffer( p ); inc_t ldp = bli_obj_col_stride( p ); inc_t is_p = bli_obj_imag_stride( p ); dim_t panel_dim_max = bli_obj_panel_dim( p ); inc_t ps_p = bli_obj_panel_stride( p ); doff_t diagoffc_inc = ( doff_t )panel_dim_max; obj_t kappa_local; char* kappa_cast = bli_packm_scalar( &kappa_local, p ); // we use the default lookup table to determine the right func_t // for the current schema. func_t* packm_kers = &packm_struc_cxk_kers[ bli_pack_schema_index( schema ) ]; // Query the datatype-specific function pointer from the func_t object. packm_ker_vft packm_ker_cast = bli_func_get_dt( dt_p, packm_kers ); // For mixed-precision gemm, select the proper kernel (only dense panels). if ( dt_c != dt_p ) { packm_ker_cast = packm_struc_cxk_md[ dt_c ][ dt_p ]; } // Query the address of the packm params field of the obj_t. The user might // have set this field in order to specify a custom packm kernel. packm_blk_var1_params_t* params = bli_obj_pack_params( c ); if ( params && params->ukr_fn[ dt_c ][ dt_p ] ) { // Query the user-provided packing kernel from the obj_t. If provided, // this overrides the kernel determined above. packm_ker_cast = params->ukr_fn[ dt_c ][ dt_p ]; } /* Compute the total number of iterations we'll need. */ dim_t n_iter = iter_dim / panel_dim_max + ( iter_dim % panel_dim_max ? 1 : 0 ); /* Set the initial values and increments for indices related to C and P based on whether reverse iteration was requested. */ dim_t ic0, ip0; doff_t ic_inc, ip_inc; if ( ( revifup && bli_is_upper( uploc ) && bli_is_triangular( strucc ) ) || ( reviflo && bli_is_lower( uploc ) && bli_is_triangular( strucc ) ) ) { ic0 = (n_iter - 1) * panel_dim_max; ic_inc = -panel_dim_max; ip0 = n_iter - 1; ip_inc = -1; } else { ic0 = 0; ic_inc = panel_dim_max; ip0 = 0; ip_inc = 1; } // Query the number of threads and thread ids from the current thread's // packm thrinfo_t node. const dim_t nt = bli_thread_n_way( thread ); const dim_t tid = bli_thread_work_id( thread ); // Determine the thread range and increment using the current thread's // packm thrinfo_t node. NOTE: The definition of bli_thread_range_jrir() // will depend on whether slab or round-robin partitioning was requested // at configure-time. dim_t it_start, it_end, it_inc; bli_thread_range_jrir( thread, n_iter, 1, FALSE, &it_start, &it_end, &it_inc ); char* p_begin = p_cast; // Iterate over every logical micropanel in the source matrix. for ( dim_t ic = ic0, ip = ip0, it = 0; it < n_iter; ic += ic_inc, ip += ip_inc, it += 1 ) { dim_t panel_dim_i = bli_min( panel_dim_max, iter_dim - ic ); dim_t panel_dim_off_i = panel_dim_off + ic; doff_t diagoffc_i = diagoffc + (ip )*diagoffc_inc; char* c_begin = c_cast + (ic )*incc*dt_c_size; inc_t p_inc = ps_p; // NOTE: We MUST use round-robin partitioning when packing // micropanels of a triangular matrix. Hermitian/symmetric // and general packing may use slab or round-robin, depending // on which was selected at configure-time. // The definition of bli_packm_my_iter() will depend on whether slab // or round-robin partitioning was requested at configure-time. bool my_iter = bli_is_triangular( strucc ) ? bli_packm_my_iter_rr( it, it_start, it_end, tid, nt ) : bli_packm_my_iter ( it, it_start, it_end, tid, nt ); if ( bli_is_triangular( strucc ) && bli_is_unstored_subpart_n( diagoffc_i, uploc, panel_dim_i, panel_len_full ) ) { // This case executes if the panel belongs to a triangular // matrix AND is completely unstored (ie: zero). If the panel // is unstored, we do nothing. (Notice that we don't even // increment p_begin.) continue; } else if ( bli_is_triangular( strucc ) && bli_intersects_diag_n( diagoffc_i, panel_dim_i, panel_len_full ) ) { // This case executes if the panel belongs to a triangular // matrix AND is diagonal-intersecting. Notice that we // cannot bury the following conditional logic into // packm_struc_cxk() because we need to know the value of // panel_len_max_i so we can properly increment p_inc. // Sanity check. Diagonals should not intersect the short end of // a micro-panel. If they do, then somehow the constraints on // cache blocksizes being a whole multiple of the register // blocksizes was somehow violated. if ( diagoffc_i < 0 ) bli_check_error_code( BLIS_NOT_YET_IMPLEMENTED ); dim_t panel_off_i; dim_t panel_len_i; dim_t panel_len_max_i; if ( bli_is_lower( uploc ) ) { panel_off_i = 0; panel_len_i = bli_abs( diagoffc_i ) + panel_dim_i; panel_len_max_i = bli_min( bli_abs( diagoffc_i ) + panel_dim_max, panel_len_max ); } else // if ( bli_is_upper( uploc ) ) { panel_off_i = bli_abs( diagoffc_i ); panel_len_i = panel_len_full - panel_off_i; panel_len_max_i = panel_len_max - panel_off_i; } dim_t panel_len_off_i = panel_off_i + panel_len_off; char* c_use = c_begin + (panel_off_i )*ldc*dt_c_size; char* p_use = p_begin; // We need to re-compute the imaginary stride as a function of // panel_len_max_i since triangular packed matrices have panels // of varying lengths. NOTE: This imaginary stride value is // only referenced by the packm kernels for induced methods. inc_t is_p_use = ldp * panel_len_max_i; // We nudge the imaginary stride up by one if it is odd. is_p_use += ( bli_is_odd( is_p_use ) ? 1 : 0 ); if ( my_iter ) { packm_ker_cast( strucc, diagc, uploc, conjc, schema, invdiag, panel_dim_i, panel_len_i, panel_dim_max, panel_len_max_i, panel_dim_off_i, panel_len_off_i, kappa_cast, c_use, incc, ldc, p_use, ldp, is_p_use, cntx, params ); } // NOTE: This value is usually LESS than ps_p because triangular // matrices usually have several micro-panels that are shorter // than a "full" micro-panel. p_inc = is_p_use; } else { // This case executes if the panel is either dense, or belongs // to a Hermitian or symmetric matrix, which includes stored, // unstored, and diagonal-intersecting panels. if ( my_iter ) { packm_ker_cast( bli_is_triangular( strucc ) ? BLIS_GENERAL : strucc, diagc, uploc, conjc, schema, invdiag, panel_dim_i, panel_len_full, panel_dim_max, panel_len_max, panel_dim_off_i, panel_len_off, kappa_cast, c_begin, incc, ldc, p_begin, ldp, is_p, cntx, params ); } } p_begin += p_inc*dt_p_size; } } blis-0.9.0/frame/1m/packm/bli_packm_blk_var1.h000066400000000000000000000041471422157504600210420ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // packm params types. // typedef struct { // Type of C Type of P packm_ker_vft ukr_fn[BLIS_NUM_FP_TYPES][BLIS_NUM_FP_TYPES]; } packm_blk_var1_params_t; // // Prototype object-based interfaces. // BLIS_EXPORT_BLIS void bli_packm_blk_var1 ( obj_t* c, obj_t* p, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl, thrinfo_t* t ); blis-0.9.0/frame/1m/packm/bli_packm_check.c000066400000000000000000000054021422157504600204040ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_packm_init_check ( obj_t* a, obj_t* p, cntx_t* cntx ) { err_t e_val; // Check object datatypes. e_val = bli_check_floating_object( a ); bli_check_error_code( e_val ); // Check control tree pointer. // NOTE: We can't check the control tree because we interpret a NULL // value (in bli_packm_int()) as a request to skip the operation. //e_val = bli_check_valid_cntl( ( void* )cntl ); //bli_check_error_code( e_val ); } void bli_packm_int_check ( obj_t* a, obj_t* p, cntx_t* cntx ) { err_t e_val; // Check object datatypes. e_val = bli_check_floating_object( a ); bli_check_error_code( e_val ); e_val = bli_check_floating_object( p ); bli_check_error_code( e_val ); // Check object dimensions. e_val = bli_check_conformal_dims( a, p ); bli_check_error_code( e_val ); // Check control tree pointer. // NOTE: We can't check the control tree because we interpret a NULL // value (in bli_packm_int()) as a request to skip the operation. //e_val = bli_check_valid_cntl( ( void* )cntl ); //bli_check_error_code( e_val ); } blis-0.9.0/frame/1m/packm/bli_packm_check.h000066400000000000000000000035141422157504600204130ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void bli_packm_init_check ( obj_t* a, obj_t* p, cntx_t* cntx ); void bli_packm_int_check ( obj_t* a, obj_t* p, cntx_t* cntx ); blis-0.9.0/frame/1m/packm/bli_packm_cntl.c000066400000000000000000000062251422157504600202730ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" BLIS_EXPORT_BLIS cntl_t* bli_packm_cntl_create_node ( rntm_t* rntm, void_fp var_func, bszid_t bmid_m, bszid_t bmid_n, bool does_invert_diag, bool rev_iter_if_upper, bool rev_iter_if_lower, pack_t pack_schema, packbuf_t pack_buf_type, cntl_t* sub_node ) { cntl_t* cntl; packm_params_t* params; #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_packm_cntl_create_node(): " ); #endif // Allocate a packm_params_t struct. params = bli_sba_acquire( rntm, sizeof( packm_params_t ) ); // Initialize the packm_params_t struct. params->size = sizeof( packm_params_t ); params->bmid_m = bmid_m; params->bmid_n = bmid_n; params->does_invert_diag = does_invert_diag; params->rev_iter_if_upper = rev_iter_if_upper; params->rev_iter_if_lower = rev_iter_if_lower; params->pack_schema = pack_schema; params->pack_buf_type = pack_buf_type; #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_packm_cntl_create_node(): " ); #endif // It's important that we set the bszid field to BLIS_NO_PART to indicate // that no blocksize partitioning is performed. bli_cntl_free() will rely // on this information to know how to step through the thrinfo_t tree in // sync with the cntl_t tree. cntl = bli_cntl_create_node ( rntm, BLIS_NOID, BLIS_NO_PART, var_func, params, sub_node ); return cntl; } blis-0.9.0/frame/1m/packm/bli_packm_cntl.h000066400000000000000000000070301422157504600202730ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ struct packm_params_s { uint64_t size; // size field must be present and come first. bszid_t bmid_m; bszid_t bmid_n; bool does_invert_diag; bool rev_iter_if_upper; bool rev_iter_if_lower; pack_t pack_schema; packbuf_t pack_buf_type; }; typedef struct packm_params_s packm_params_t; BLIS_INLINE bszid_t bli_cntl_packm_params_bmid_m( cntl_t* cntl ) { packm_params_t* ppp = ( packm_params_t* )cntl->params; return ppp->bmid_m; } BLIS_INLINE bszid_t bli_cntl_packm_params_bmid_n( cntl_t* cntl ) { packm_params_t* ppp = ( packm_params_t* )cntl->params; return ppp->bmid_n; } BLIS_INLINE bool bli_cntl_packm_params_does_invert_diag( cntl_t* cntl ) { packm_params_t* ppp = ( packm_params_t* )cntl->params; return ppp->does_invert_diag; } BLIS_INLINE bool bli_cntl_packm_params_rev_iter_if_upper( cntl_t* cntl ) { packm_params_t* ppp = ( packm_params_t* )cntl->params; return ppp->rev_iter_if_upper; } BLIS_INLINE bool bli_cntl_packm_params_rev_iter_if_lower( cntl_t* cntl ) { packm_params_t* ppp = ( packm_params_t* )cntl->params; return ppp->rev_iter_if_lower; } BLIS_INLINE pack_t bli_cntl_packm_params_pack_schema( cntl_t* cntl ) { packm_params_t* ppp = ( packm_params_t* )cntl->params; return ppp->pack_schema; } BLIS_INLINE packbuf_t bli_cntl_packm_params_pack_buf_type( cntl_t* cntl ) { packm_params_t* ppp = ( packm_params_t* )cntl->params; return ppp->pack_buf_type; } // ----------------------------------------------------------------------------- cntl_t* bli_packm_cntl_create_node ( rntm_t* rntm, void_fp var_func, bszid_t bmid_m, bszid_t bmid_n, bool does_invert_diag, bool rev_iter_if_upper, bool rev_iter_if_lower, pack_t pack_schema, packbuf_t pack_buf_type, cntl_t* sub_node ); blis-0.9.0/frame/1m/packm/bli_packm_cxk.c000066400000000000000000000155441422157504600201240ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENTFUNC #define GENTFUNC( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ conj_t conja, \ pack_t schema, \ dim_t panel_dim, \ dim_t panel_dim_max, \ dim_t panel_len, \ dim_t panel_len_max, \ ctype* kappa, \ ctype* a, inc_t inca, inc_t lda, \ ctype* p, inc_t ldp, \ cntx_t* cntx \ ) \ { \ /* Note that we use panel_dim_max, not panel_dim, to query the packm kernel function pointer. This means that we always use the same kernel, even for edge cases. */ \ num_t dt = PASTEMAC(ch,type); \ l1mkr_t ker_id = panel_dim_max; \ \ PASTECH2(ch,opname,_ker_ft) f; \ \ /* Query the context for the packm kernel corresponding to the current panel dimension, or kernel id. If the id is invalid, the function will return NULL. */ \ f = bli_cntx_get_packm_ker_dt( dt, ker_id, cntx ); \ \ /* If there exists a kernel implementation for the micro-panel dimension provided, we invoke the implementation. Otherwise, we use scal2m. */ \ if ( f != NULL ) \ { \ /* Under normal circumstances, the packm kernel will copy over a panel_dim x panel_len submatrix of A into P. However, the kernel now handles zero-filling at edge cases, which typically consist of the outer (panel_dim_max - panel_dim) rows or columns of the micropanel. (Note that these rows/columns correspond to values beyond the edge of matrix A.) The kernel intrinsically knows its own panel_dim_max, since that corresponds to the packm micropanel's normal width (corresponding to the gemm microkernel's register blocksize (mr or nr). However, we *do* need to pass in panel_len_max because the bottom-right edge case of trsm_lu will need all elements above the extended diagonal and beyond (to the right of) the bottom-right element to be initialized to zero so the trsm portion of the computational kernel will operate with zeros for those iterations. For example, if trsm_lu is executed on an 10x10 triangular matrix, and the gemmtrsm kernel uses MR = 6, the computation will begin with the edge case, which is the bottom-right 4x4 upper triangular matrix. Code in bli_packm_tri_cxk() will extend the diagonal as identity into the remaining portion of the micropanel. But before that happens, the packm kernel must have set the 0's added in step (3) below. packm kernel packm kernel packm kernel packm_tri_cxk step 1: step 2: step 3: step 4: x x x x . . x x x x . . x x x x 0 0 x x x x 0 0 ? x x x . . ? x x x . . ? x x x 0 0 ? x x x 0 0 ? ? x x . . -> ? ? x x . . -> ? ? x x 0 0 -> ? ? x x 0 0 ? ? ? x . . ? ? ? x . . ? ? ? x 0 0 ? ? ? x 0 0 . . . . . . 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 . . . . . . 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 x Copied from A; valid element. ? Copied from A, but value is unknown and unused. . Uninitialized. 0 Initialized to zero. 1 Initialized to one. NOTE: In step 5 (not shown), bli_packm_tri_cxk() sets the ?'s to zero. This is not needed to support trsm, but rather to support trmm. (Both use the same packing format and code.) In this case, panel_dim will be 4 because four rows of data are copied from A, panel_len will be 4 because those four rows span four columns of A, and panel_len_max will be 6 because there are a total of 6 columns that can be written to in the packed micropanel, 2 of which lie beyond the values copied from A. */ \ f \ ( \ conja, \ schema, \ panel_dim, \ panel_len, \ panel_len_max, \ kappa, \ a, inca, lda, \ p, ldp, \ cntx \ ); \ } \ else \ { \ /* Treat the micro-panel as panel_dim x panel_len and column-stored (unit row stride). */ \ PASTEMAC2(ch,scal2m,BLIS_TAPI_EX_SUF) \ ( \ 0, \ BLIS_NONUNIT_DIAG, \ BLIS_DENSE, \ ( trans_t )conja, \ panel_dim, \ panel_len, \ kappa, \ a, inca, lda, \ p, 1, ldp, \ cntx, \ /* The rntm_t* can safely be NULL as long as it's not used by scal2m_ex(). */ \ NULL \ ); \ \ /* If panel_dim < panel_dim_max, then we zero those unused rows. */ \ if ( panel_dim < panel_dim_max ) \ { \ const dim_t i = panel_dim; \ const dim_t m_edge = panel_dim_max - panel_dim; \ const dim_t n_edge = panel_len_max; \ ctype* restrict p_edge = p + (i )*1; \ \ PASTEMAC(ch,set0s_mxn) \ ( \ m_edge, \ n_edge, \ p_edge, 1, ldp \ ); \ } \ \ /* If panel_len < panel_len_max, then we zero those unused columns. */ \ if ( panel_len < panel_len_max ) \ { \ const dim_t j = panel_len; \ const dim_t m_edge = panel_dim_max; \ const dim_t n_edge = panel_len_max - panel_len; \ ctype* restrict p_edge = p + (j )*ldp; \ \ PASTEMAC(ch,set0s_mxn) \ ( \ m_edge, \ n_edge, \ p_edge, 1, ldp \ ); \ } \ } \ } INSERT_GENTFUNC_BASIC0( packm_cxk ) blis-0.9.0/frame/1m/packm/bli_packm_cxk.h000066400000000000000000000041071422157504600201220ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #undef GENTPROT #define GENTPROT( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ conj_t conja, \ pack_t schema, \ dim_t panel_dim, \ dim_t panel_dim_max, \ dim_t panel_len, \ dim_t panel_len_max, \ ctype* kappa, \ ctype* a, inc_t inca, inc_t lda, \ ctype* p, inc_t ldp, \ cntx_t* cntx \ ); INSERT_GENTPROT_BASIC0( packm_cxk ) blis-0.9.0/frame/1m/packm/bli_packm_cxk_1er.c000066400000000000000000000103241422157504600206620ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENTFUNCCO #define GENTFUNCCO( ctype, ctype_r, ch, chr, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ conj_t conja, \ pack_t schema, \ dim_t panel_dim, \ dim_t panel_dim_max, \ dim_t panel_len, \ dim_t panel_len_max, \ ctype* kappa, \ ctype* a, inc_t inca, inc_t lda, \ ctype* p, inc_t ldp, \ cntx_t* cntx \ ) \ { \ /* Note that we use panel_dim_max, not panel_dim, to query the packm kernel function pointer. This means that we always use the same kernel, even for edge cases. */ \ num_t dt = PASTEMAC(ch,type); \ l1mkr_t ker_id = panel_dim_max; \ \ PASTECH2(ch,opname,_ker_ft) f; \ \ /* Query the context for the packm kernel corresponding to the current panel dimension, or kernel id. If the id is invalid, the function will return NULL. */ \ f = bli_cntx_get_packm_ker_dt( dt, ker_id, cntx ); \ \ /* If there exists a kernel implementation for the micro-panel dimension provided, we invoke the implementation. Otherwise, we use scal2m. */ \ if ( f != NULL ) \ { \ f \ ( \ conja, \ schema, \ panel_dim, \ panel_len, \ panel_len_max, \ kappa, \ a, inca, lda, \ p, ldp, \ cntx \ ); \ } \ else \ { \ /* Treat the micro-panel as panel_dim x panel_len and column-stored (unit row stride). */ \ \ PASTEMAC(ch,scal21ms_mxn) \ ( \ schema, \ conja, \ panel_dim, \ panel_len, \ kappa, \ a, inca, lda, \ p, 1, ldp, ldp \ ); \ \ /* If panel_dim < panel_dim_max, then we zero those unused rows. */ \ if ( panel_dim < panel_dim_max ) \ { \ ctype* restrict zero = PASTEMAC(ch,0); \ const dim_t offm = panel_dim; \ const dim_t offn = 0; \ const dim_t m_edge = panel_dim_max - panel_dim; \ const dim_t n_edge = panel_len_max; \ \ PASTEMAC(ch,set1ms_mxn) \ ( \ schema, \ offm, \ offn, \ m_edge, \ n_edge, \ zero, \ p, 1, ldp, ldp \ ); \ } \ \ /* If panel_len < panel_len_max, then we zero those unused columns. */ \ if ( panel_len < panel_len_max ) \ { \ ctype* restrict zero = PASTEMAC(ch,0); \ const dim_t offm = 0; \ const dim_t offn = panel_len; \ const dim_t m_edge = panel_dim_max; \ const dim_t n_edge = panel_len_max - panel_len; \ \ PASTEMAC(ch,set1ms_mxn) \ ( \ schema, \ offm, \ offn, \ m_edge, \ n_edge, \ zero, \ p, 1, ldp, ldp \ ); \ } \ } \ } INSERT_GENTFUNCCO_BASIC0( packm_cxk_1er ) blis-0.9.0/frame/1m/packm/bli_packm_cxk_1er.h000066400000000000000000000041371422157504600206740ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #undef GENTPROTCO #define GENTPROTCO( ctype, ctype_r, ch, chr, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ conj_t conja, \ pack_t schema, \ dim_t panel_dim, \ dim_t panel_dim_max, \ dim_t panel_len, \ dim_t panel_len_max, \ ctype* kappa, \ ctype* a, inc_t inca, inc_t lda, \ ctype* p, inc_t ldp, \ cntx_t* cntx \ ); INSERT_GENTPROTCO_BASIC0( packm_cxk_1er ) blis-0.9.0/frame/1m/packm/bli_packm_init.c000066400000000000000000000170341422157504600202760ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2016, Hewlett Packard Enterprise Development LP 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" bool bli_packm_init ( obj_t* c, obj_t* p, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ) { bli_init_once(); // The purpose of packm_init() is to initialize an object P so that // a source object A can be packed into P via one of the packm // implementations. This initialization precedes the acquisition of a // suitable block of memory from the memory allocator (if such a block // of memory has not already been allocated previously). // Check parameters. if ( bli_error_checking_is_enabled() ) bli_packm_init_check( c, p, cntx ); // We begin by copying the fields of A. bli_obj_alias_to( c, p ); // If the object is marked as being filled with zeros, then we can skip // the packm operation entirely and alias. if ( bli_obj_is_zeros( c ) ) return false; // Extract various fields from the control tree. bszid_t bmult_id_m = bli_cntl_packm_params_bmid_m( cntl ); bszid_t bmult_id_n = bli_cntl_packm_params_bmid_n( cntl ); pack_t schema = bli_cntl_packm_params_pack_schema( cntl ); num_t dt_tar = bli_obj_target_dt( c ); num_t dt_scalar = bli_obj_scalar_dt( c ); dim_t bmult_m_def = bli_cntx_get_blksz_def_dt( dt_tar, bmult_id_m, cntx ); dim_t bmult_m_pack = bli_cntx_get_blksz_max_dt( dt_tar, bmult_id_m, cntx ); dim_t bmult_n_def = bli_cntx_get_blksz_def_dt( dt_tar, bmult_id_n, cntx ); // Typecast the internal scalar value to the target datatype. // Note that if the typecasting is needed, this must happen BEFORE we // change the datatype of P to reflect the target_dt. if ( dt_scalar != dt_tar ) { bli_obj_scalar_cast_to( dt_tar, p ); } // Update the storage datatype of P to be the target datatype of A. bli_obj_set_dt( dt_tar, p ); bli_obj_set_elem_size( bli_dt_size( dt_tar ), p ); // Store the pack schema to the object. bli_obj_set_pack_schema( schema, p ); // Clear the conjugation field from the object since matrix packing // in BLIS is deemed to take care of all conjugation necessary. bli_obj_set_conj( BLIS_NO_CONJUGATE, p ); // Since we are packing micropanels, mark P as dense. bli_obj_set_uplo( BLIS_DENSE, p ); // Reset the view offsets to (0,0). bli_obj_set_offs( 0, 0, p ); // Compute the dimensions padded by the dimension multiples. These // dimensions will be the dimensions of the packed matrices, including // zero-padding, and will be used by the macro- and micro-kernels. // We compute them by starting with the effective dimensions of A (now // in P) and aligning them to the dimension multiples (typically equal // to register blocksizes). This does waste a little bit of space for // level-2 operations, but that's okay with us. dim_t m_p = bli_obj_length( p ); dim_t n_p = bli_obj_width( p ); dim_t m_p_pad = bli_align_dim_to_mult( m_p, bmult_m_def ); dim_t n_p_pad = bli_align_dim_to_mult( n_p, bmult_n_def ); // Save the padded dimensions into the packed object. It is important // to save these dimensions since they represent the actual dimensions // of the zero-padded matrix. bli_obj_set_padded_dims( m_p_pad, n_p_pad, p ); // Now we prepare to compute strides, align them, and compute the // total number of bytes needed for the packed buffer. Then we use // that value to acquire an appropriate block of memory from the // memory allocator. // Extract the element size for the packed object. siz_t elem_size_p = bli_obj_elem_size( p ); // The panel dimension (for each datatype) should be equal to the // default (logical) blocksize multiple in the m dimension. dim_t m_panel = bmult_m_def; // The "column stride" of a row-micropanel packed object is interpreted // as the column stride WITHIN a micropanel. Thus, this is equal to the // packing (storage) blocksize multiple, which may be equal to the // default (logical) blocksize multiple). inc_t cs_p = bmult_m_pack; // The "row stride" of a row-micropanel packed object is interpreted // as the row stride WITHIN a micropanel. Thus, it is unit. inc_t rs_p = 1; // The "panel stride" of a micropanel packed object is interpreted as // the distance between the (0,0) element of panel k and the (0,0) // element of panel k+1. We use the padded width computed above to // allow for zero-padding (if necessary/desired) along the far end // of each micropanel (ie: the right edge of the matrix). Zero-padding // can also occur along the long edge of the last micropanel if the m // dimension of the matrix is not a whole multiple of MR. inc_t ps_p = cs_p * n_p_pad; // As a general rule, we don't want micropanel strides to be odd. There // are very few instances where this can happen, but we've seen it happen // more than zero times (such as for certain small problems), and so we // check for it here. if ( bli_is_odd( ps_p ) ) ps_p += 1; // Set the imaginary stride (in units of fundamental elements). // This is the number of real elements that must be traversed before // reaching the imaginary part of the packed micropanel. NOTE: the // imaginary stride is mostly vestigial and left over from the 3m // and 4m implementations. inc_t is_p = 1; // Store the strides and panel dimension in P. bli_obj_set_strides( rs_p, cs_p, p ); bli_obj_set_imag_stride( is_p, p ); bli_obj_set_panel_dim( m_panel, p ); bli_obj_set_panel_stride( ps_p, p ); bli_obj_set_panel_length( m_panel, p ); bli_obj_set_panel_width( n_p, p ); // Compute the size of the packed buffer. siz_t size_p = ps_p * ( m_p_pad / m_panel ) * elem_size_p; // If the requested size is zero, then we don't need to do any allocation. if ( size_p == 0 ) return false; // Update the buffer address in p to point to the buffer associated // with the mem_t entry acquired from the memory broker (now cached in // the control tree node). void* buffer = bli_packm_alloc( size_p, rntm, cntl, thread ); bli_obj_set_buffer( buffer, p ); return true; } blis-0.9.0/frame/1m/packm/bli_packm_init.h000066400000000000000000000034721422157504600203040ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ BLIS_EXPORT_BLIS bool bli_packm_init ( obj_t* a, obj_t* p, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ); blis-0.9.0/frame/1m/packm/bli_packm_int.c000066400000000000000000000044101422157504600201170ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_packm_int ( obj_t* a, obj_t* p, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ) { bli_init_once(); // Extract the function pointer from the object. packm_var_oft f = bli_obj_pack_fn( a ); // Barrier so that we know threads are done with previous computation // with the same packing buffer before starting to pack. bli_thread_barrier( thread ); // Invoke the variant with kappa_use. f ( a, p, cntx, rntm, cntl, thread ); // Barrier so that packing is done before computation. bli_thread_barrier( thread ); } blis-0.9.0/frame/1m/packm/bli_packm_int.h000066400000000000000000000034471422157504600201350ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void bli_packm_int ( obj_t* a, obj_t* p, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ); blis-0.9.0/frame/1m/packm/bli_packm_part.c000066400000000000000000000220411422157504600202730ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // -- Matrix partitioning ------------------------------------------------------ void bli_packm_acquire_mpart_t2b( subpart_t requested_part, dim_t i, dim_t b, obj_t* obj, obj_t* sub_obj ) { dim_t m, n; // For now, we only support acquiring the middle subpartition. if ( requested_part != BLIS_SUBPART1 ) { bli_check_error_code( BLIS_NOT_YET_IMPLEMENTED ); } // Partitioning top-to-bottom through packed column panels (which are // row-stored) is not yet supported. if ( bli_obj_is_col_packed( obj ) ) { bli_check_error_code( BLIS_NOT_YET_IMPLEMENTED ); } // Query the dimensions of the parent object. m = bli_obj_length( obj ); n = bli_obj_width( obj ); // Foolproofing: do not let b exceed what's left of the m dimension at // row offset i. if ( b > m - i ) b = m - i; // Begin by copying the info, elem size, buffer, row stride, and column // stride fields of the parent object. Note that this omits copying view // information because the new partition will have its own dimensions // and offsets. bli_obj_init_subpart_from( obj, sub_obj ); // Modify offsets and dimensions of requested partition. bli_obj_set_dims( b, n, sub_obj ); // Tweak the padded length of the subpartition to trick the underlying // implementation into only zero-padding for the narrow submatrix of // interest. Usually, the value we want is b (for non-edge cases), but // at the edges, we want the remainder of the mem_t region in the m // dimension. Edge cases are defined as occurring when i + b is exactly // equal to the inherited sub-object's length (which happens since the // determine_blocksize function would have returned a smaller value of // b for the edge iteration). In these cases, we arrive at the new // packed length by simply subtracting off i. { dim_t m_pack_max = bli_obj_padded_length( sub_obj ); dim_t m_pack_cur; if ( i + b == m ) m_pack_cur = m_pack_max - i; else m_pack_cur = b; bli_obj_set_padded_length( m_pack_cur, sub_obj ); } // Translate the desired offsets to a panel offset and adjust the // buffer pointer of the subpartition object. { char* buf_p = bli_obj_buffer( sub_obj ); siz_t elem_size = bli_obj_elem_size( sub_obj ); dim_t off_to_panel = bli_packm_offset_to_panel_for( i, sub_obj ); buf_p = buf_p + elem_size * off_to_panel; bli_obj_set_buffer( buf_p, sub_obj ); } } void bli_packm_acquire_mpart_l2r( subpart_t requested_part, dim_t j, dim_t b, obj_t* obj, obj_t* sub_obj ) { dim_t m, n; // Check parameters. //if ( bli_error_checking_is_enabled() ) // bli_packm_acquire_mpart_l2r_check( requested_part, j, b, obj, sub_obj ); // For now, we only support acquiring the middle subpartition. if ( requested_part != BLIS_SUBPART1 ) { bli_check_error_code( BLIS_NOT_YET_IMPLEMENTED ); } // Partitioning left-to-right through packed row panels (which are // column-stored) is not yet supported. if ( bli_obj_is_row_packed( obj ) ) { bli_check_error_code( BLIS_NOT_YET_IMPLEMENTED ); } // Query the dimensions of the parent object. m = bli_obj_length( obj ); n = bli_obj_width( obj ); // Foolproofing: do not let b exceed what's left of the n dimension at // column offset j. if ( b > n - j ) b = n - j; // Begin by copying the info, elem size, buffer, row stride, and column // stride fields of the parent object. Note that this omits copying view // information because the new partition will have its own dimensions // and offsets. bli_obj_init_subpart_from( obj, sub_obj ); // Modify offsets and dimensions of requested partition. bli_obj_set_dims( m, b, sub_obj ); // Tweak the padded width of the subpartition to trick the underlying // implementation into only zero-padding for the narrow submatrix of // interest. Usually, the value we want is b (for non-edge cases), but // at the edges, we want the remainder of the mem_t region in the n // dimension. Edge cases are defined as occurring when j + b is exactly // equal to the inherited sub-object's width (which happens since the // determine_blocksize function would have returned a smaller value of // b for the edge iteration). In these cases, we arrive at the new // packed width by simply subtracting off j. { dim_t n_pack_max = bli_obj_padded_width( sub_obj ); dim_t n_pack_cur; if ( j + b == n ) n_pack_cur = n_pack_max - j; else n_pack_cur = b; bli_obj_set_padded_width( n_pack_cur, sub_obj ); } // Translate the desired offsets to a panel offset and adjust the // buffer pointer of the subpartition object. { char* buf_p = bli_obj_buffer( sub_obj ); siz_t elem_size = bli_obj_elem_size( sub_obj ); dim_t off_to_panel = bli_packm_offset_to_panel_for( j, sub_obj ); buf_p = buf_p + elem_size * off_to_panel; bli_obj_set_buffer( buf_p, sub_obj ); } } void bli_packm_acquire_mpart_tl2br( subpart_t requested_part, dim_t ij, dim_t b, obj_t* obj, obj_t* sub_obj ) { bli_check_error_code( BLIS_NOT_YET_IMPLEMENTED ); } dim_t bli_packm_offset_to_panel_for( dim_t offmn, obj_t* p ) { dim_t panel_off; if ( bli_obj_pack_schema( p ) == BLIS_PACKED_ROWS ) { // For the "packed rows" schema, a single row is effectively one // row panel, and so we use the row offset as the panel offset. // Then we multiply this offset by the effective panel stride // (ie: the row stride) to arrive at the desired offset. panel_off = offmn * bli_obj_row_stride( p ); } else if ( bli_obj_pack_schema( p ) == BLIS_PACKED_COLUMNS ) { // For the "packed columns" schema, a single column is effectively one // column panel, and so we use the column offset as the panel offset. // Then we multiply this offset by the effective panel stride // (ie: the column stride) to arrive at the desired offset. panel_off = offmn * bli_obj_col_stride( p ); } else if ( bli_obj_pack_schema( p ) == BLIS_PACKED_ROW_PANELS ) { // For the "packed row panels" schema, the column stride is equal to // the panel dimension (length). So we can divide it into offmn // (interpreted as a row offset) to arrive at a panel offset. Then // we multiply this offset by the panel stride to arrive at the total // offset to the panel (in units of elements). panel_off = offmn / bli_obj_col_stride( p ); panel_off = panel_off * bli_obj_panel_stride( p ); // Sanity check. if ( offmn % bli_obj_col_stride( p ) > 0 ) bli_abort(); } else if ( bli_obj_pack_schema( p ) == BLIS_PACKED_COL_PANELS ) { // For the "packed column panels" schema, the row stride is equal to // the panel dimension (width). So we can divide it into offmn // (interpreted as a column offset) to arrive at a panel offset. Then // we multiply this offset by the panel stride to arrive at the total // offset to the panel (in units of elements). panel_off = offmn / bli_obj_row_stride( p ); panel_off = panel_off * bli_obj_panel_stride( p ); // Sanity check. if ( offmn % bli_obj_row_stride( p ) > 0 ) bli_abort(); } else { panel_off = 0; bli_check_error_code( BLIS_NOT_YET_IMPLEMENTED ); } return panel_off; } blis-0.9.0/frame/1m/packm/bli_packm_part.h000066400000000000000000000050561422157504600203070ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // -- Matrix partitioning ------------------------------------------------------ void bli_packm_acquire_mpart_t2b( subpart_t requested_part, dim_t i, dim_t b, obj_t* obj, obj_t* sub_obj ); void bli_packm_acquire_mpart_l2r( subpart_t requested_part, dim_t j, dim_t b, obj_t* obj, obj_t* sub_obj ); void bli_packm_acquire_mpart_tl2br( subpart_t requested_part, dim_t ij, dim_t b, obj_t* obj, obj_t* sub_obj ); dim_t bli_packm_offset_to_panel_for( dim_t offmn, obj_t* p ); blis-0.9.0/frame/1m/packm/bli_packm_scalar.c000066400000000000000000000062031422157504600205740ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2016, Hewlett Packard Enterprise Development LP 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void* bli_packm_scalar( obj_t* kappa, obj_t* p ) { num_t dt_p = bli_obj_dt( p ); pack_t schema = bli_obj_pack_schema( p ); // The value for kappa we use will depends on whether the scalar // attached to A has a nonzero imaginary component. If it does, // then we will apply the scalar during packing to facilitate // implementing induced complex domain algorithms in terms of // real domain micro-kernels. (In the aforementioned situation, // applying a real scalar is easy, but applying a complex one is // harder, so we avoid the need altogether with the code below.) if ( bli_obj_scalar_has_nonzero_imag( p ) && !bli_is_nat_packed( schema ) ) { //printf( "applying non-zero imag kappa\n_p" ); // Detach the scalar. bli_obj_scalar_detach( p, kappa ); // Reset the attached scalar (to 1.0). bli_obj_scalar_reset( p ); return bli_obj_buffer_for_1x1( dt_p, kappa ); } // This branch is also for native execution, where we assume that // the micro-kernel will always apply the alpha scalar of the // higher-level operation. Thus, we use BLIS_ONE for kappa so // that the underlying packm implementation does not perform // any scaling during packing. else { // If the internal scalar of A has only a real component, then // we will apply it later (in the micro-kernel), and so we will // use BLIS_ONE to indicate no scaling during packing. return bli_obj_buffer_for_1x1( dt_p, &BLIS_ONE ); } } blis-0.9.0/frame/1m/packm/bli_packm_scalar.h000066400000000000000000000033151422157504600206020ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ BLIS_EXPORT_BLIS void* bli_packm_scalar( obj_t* kappa, obj_t* p ); blis-0.9.0/frame/1m/packm/bli_packm_struc_cxk.c000066400000000000000000000334551422157504600213450ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENTFUNC #define GENTFUNC( ctype, ch, varname, kername ) \ \ void PASTEMAC(ch,varname) \ ( \ struc_t strucc, \ diag_t diagc, \ uplo_t uploc, \ conj_t conjc, \ pack_t schema, \ bool invdiag, \ dim_t panel_dim, \ dim_t panel_len, \ dim_t panel_dim_max, \ dim_t panel_len_max, \ dim_t panel_dim_off, \ dim_t panel_len_off, \ ctype* restrict kappa, \ ctype* restrict c, inc_t incc, inc_t ldc, \ ctype* restrict p, inc_t ldp, \ inc_t is_p, \ cntx_t* cntx \ ) \ { \ /* Handle micro-panel packing based on the structure of the matrix being packed. */ \ if ( bli_is_general( strucc ) ) \ { \ /* For micro-panels of general matrices, we can call the pack kernel front-end directly. */ \ PASTEMAC(ch,kername) \ ( \ conjc, \ schema, \ panel_dim, \ panel_dim_max, \ panel_len, \ panel_len_max, \ kappa, \ c, incc, ldc, \ p, ldp, \ cntx \ ); \ } \ else if ( bli_is_herm_or_symm( strucc ) ) \ { \ /* Call a helper function for micro-panels of Hermitian/symmetric matrices. */ \ PASTEMAC(ch,packm_herm_cxk) \ ( \ strucc, \ diagc, \ uploc, \ conjc, \ schema, \ invdiag, \ panel_dim, \ panel_len, \ panel_dim_max, \ panel_len_max, \ panel_dim_off, \ panel_len_off, \ kappa, \ c, incc, ldc, \ p, ldp, \ is_p, \ cntx \ ); \ } \ else /* ( bli_is_triangular( strucc ) ) */ \ { \ /* Call a helper function for micro-panels of triangular matrices. */ \ PASTEMAC(ch,packm_tri_cxk) \ ( \ strucc, \ diagc, \ uploc, \ conjc, \ schema, \ invdiag, \ panel_dim, \ panel_len, \ panel_dim_max, \ panel_len_max, \ panel_dim_off, \ panel_len_off, \ kappa, \ c, incc, ldc, \ p, ldp, \ is_p, \ cntx \ ); \ } \ } INSERT_GENTFUNC_BASIC( packm_struc_cxk, packm_cxk ) #undef GENTFUNC #define GENTFUNC( ctype, ch, varname, kername ) \ \ void PASTEMAC(ch,varname) \ ( \ struc_t strucc, \ diag_t diagc, \ uplo_t uploc, \ conj_t conjc, \ pack_t schema, \ bool invdiag, \ dim_t panel_dim, \ dim_t panel_len, \ dim_t panel_dim_max, \ dim_t panel_len_max, \ dim_t panel_dim_off, \ dim_t panel_len_off, \ ctype* restrict kappa, \ ctype* restrict c, inc_t incc, inc_t ldc, \ ctype* restrict p, inc_t ldp, \ inc_t is_p, \ cntx_t* cntx \ ) \ { \ doff_t diagoffc = panel_dim_off - panel_len_off; \ doff_t diagoffc_abs; \ dim_t i, j; \ \ /* Handle the case where the micro-panel does NOT intersect the diagonal separately from the case where it does intersect. */ \ if ( !bli_intersects_diag_n( diagoffc, panel_dim, panel_len ) ) \ { \ /* If the current panel is unstored, we need to make a few adjustments so we refer to the data where it is actually stored, also taking conjugation into account. (Note this implicitly assumes we are operating on a dense panel within a larger symmetric or Hermitian matrix, since a general matrix would not contain any unstored region.) */ \ if ( bli_is_unstored_subpart_n( diagoffc, uploc, panel_dim, panel_len ) ) \ { \ c = c + diagoffc * ( doff_t )ldc + \ -diagoffc * ( doff_t )incc; \ bli_swap_incs( &incc, &ldc ); \ \ if ( bli_is_hermitian( strucc ) ) \ bli_toggle_conj( &conjc ); \ } \ \ /* Pack the full panel. */ \ PASTEMAC(ch,kername) \ ( \ conjc, \ schema, \ panel_dim, \ panel_dim_max, \ panel_len, \ panel_len_max, \ kappa, \ c, incc, ldc, \ p, ldp, \ cntx \ ); \ } \ else /* if ( bli_intersects_diag_n( diagoffc, panel_dim, panel_len ) ) */ \ { \ ctype* restrict c10; \ ctype* restrict p10; \ dim_t p10_dim, p10_len; \ inc_t incc10, ldc10; \ doff_t diagoffc10; \ conj_t conjc10; \ \ ctype* restrict c12; \ ctype* restrict p12; \ dim_t p12_dim, p12_len; \ inc_t incc12, ldc12; \ doff_t diagoffc12; \ conj_t conjc12; \ \ /* Sanity check. Diagonals should not intersect the short end of a micro-panel. If they do, then somehow the constraints on cache blocksizes being a whole multiple of the register blocksizes was somehow violated. */ \ if ( diagoffc < 0 ) \ bli_check_error_code( BLIS_NOT_YET_IMPLEMENTED ); \ \ diagoffc_abs = bli_abs( diagoffc ); \ \ if ( bli_is_lower( uploc ) ) \ { \ p10_dim = panel_dim; \ p10_len = diagoffc_abs; \ p10 = p; \ c10 = c; \ incc10 = incc; \ ldc10 = ldc; \ conjc10 = conjc; \ \ p12_dim = panel_dim; \ p12_len = panel_len - p10_len; \ j = p10_len; \ diagoffc12 = diagoffc_abs - j; \ p12 = p + (j )*ldp; \ c12 = c + (j )*ldc; \ c12 = c12 + diagoffc12 * ( doff_t )ldc + \ -diagoffc12 * ( doff_t )incc; \ incc12 = ldc; \ ldc12 = incc; \ conjc12 = conjc; \ \ if ( bli_is_hermitian( strucc ) ) \ bli_toggle_conj( &conjc12 ); \ } \ else /* if ( bli_is_upper( uploc ) ) */ \ { \ p10_dim = panel_dim; \ p10_len = diagoffc_abs + panel_dim; \ diagoffc10 = diagoffc; \ p10 = p; \ c10 = c; \ c10 = c10 + diagoffc10 * ( doff_t )ldc + \ -diagoffc10 * ( doff_t )incc; \ incc10 = ldc; \ ldc10 = incc; \ conjc10 = conjc; \ \ p12_dim = panel_dim; \ p12_len = panel_len - p10_len; \ j = p10_len; \ p12 = p + (j )*ldp; \ c12 = c + (j )*ldc; \ incc12 = incc; \ ldc12 = ldc; \ conjc12 = conjc; \ \ if ( bli_is_hermitian( strucc ) ) \ bli_toggle_conj( &conjc10 ); \ } \ \ /* Pack to p10. For upper storage, this includes the unstored triangle of c11. */ \ /* NOTE: Since we're only packing partial panels here, we pass in p1x_len as panel_len_max; otherwise, the packm kernel will zero- fill the columns up to panel_len_max, which is not what we need or want to happen. */ \ PASTEMAC(ch,kername) \ ( \ conjc10, \ schema, \ p10_dim, \ panel_dim_max, \ p10_len, \ p10_len, \ kappa, \ c10, incc10, ldc10, \ p10, ldp, \ cntx \ ); \ \ /* Pack to p12. For lower storage, this includes the unstored triangle of c11. */ \ /* NOTE: Since we're only packing partial panels here, we pass in p1x_len as panel_len_max; otherwise, the packm kernel will zero- fill the columns up to panel_len_max, which is not what we need or want to happen. */ \ PASTEMAC(ch,kername) \ ( \ conjc12, \ schema, \ p12_dim, \ panel_dim_max, \ p12_len, \ p12_len, \ kappa, \ c12, incc12, ldc12, \ p12, ldp, \ cntx \ ); \ \ /* Pack the stored triangle of c11 to p11. */ \ { \ dim_t p11_m = panel_dim; \ dim_t p11_n = panel_dim; \ dim_t j2 = diagoffc_abs; \ ctype* restrict c11 = c + (j2 )*ldc; \ ctype* restrict p11 = p + (j2 )*ldp; \ trans_t transc = ( trans_t )conjc; \ \ PASTEMAC2(ch,copym,BLIS_TAPI_EX_SUF) \ ( \ 0, \ BLIS_NONUNIT_DIAG, \ uploc, \ transc, \ p11_m, \ p11_n, \ c11, incc, ldc, \ p11, 1, ldp, \ cntx, \ NULL \ ); \ \ /* If source matrix c is Hermitian, we have to zero out the imaginary components of the diagonal of p11 in case the corresponding elements in c11 were not already zero. */ \ if ( bli_is_hermitian( strucc ) ) \ { \ ctype* restrict pi11 = p11; \ \ for ( i = 0; i < p11_m; ++i ) \ { \ PASTEMAC(ch,seti0s)( *pi11 ); \ \ pi11 += 1 + ldp; \ } \ } \ \ /* Now that the diagonal has been made explicitly Hermitian (if applicable), we can now safely scale the stored triangle specified by uploc. */ \ PASTEMAC2(ch,scalm,BLIS_TAPI_EX_SUF) \ ( \ BLIS_NO_CONJUGATE, \ 0, \ BLIS_NONUNIT_DIAG, \ uploc, \ p11_m, \ p11_n, \ kappa, \ p11, 1, ldp, \ cntx, \ NULL \ ); \ } \ } \ } INSERT_GENTFUNC_BASIC( packm_herm_cxk, packm_cxk ) #undef GENTFUNC #define GENTFUNC( ctype, ch, varname, kername ) \ \ void PASTEMAC(ch,varname) \ ( \ struc_t strucc, \ diag_t diagc, \ uplo_t uploc, \ conj_t conjc, \ pack_t schema, \ bool invdiag, \ dim_t panel_dim, \ dim_t panel_len, \ dim_t panel_dim_max, \ dim_t panel_len_max, \ dim_t panel_dim_off, \ dim_t panel_len_off, \ ctype* restrict kappa, \ ctype* restrict c, inc_t incc, inc_t ldc, \ ctype* restrict p, inc_t ldp, \ inc_t is_p, \ cntx_t* cntx \ ) \ { \ doff_t diagoffc = panel_dim_off - panel_len_off; \ \ /* Pack the panel. */ \ PASTEMAC(ch,kername) \ ( \ conjc, \ schema, \ panel_dim, \ panel_dim_max, \ panel_len, \ panel_len_max, \ kappa, \ c, incc, ldc, \ p, ldp, \ cntx \ ); \ \ \ /* If the diagonal of c is implicitly unit, explicitly set the the diagonal of the packed panel to kappa. */ \ if ( bli_is_unit_diag( diagc ) ) \ { \ PASTEMAC2(ch,setd,BLIS_TAPI_EX_SUF) \ ( \ BLIS_NO_CONJUGATE, \ diagoffc, \ panel_dim, \ panel_len, \ kappa, \ p, 1, ldp, \ cntx, \ NULL \ ); \ } \ \ /* If requested, invert the diagonal of the packed panel. */ \ if ( invdiag == TRUE ) \ { \ PASTEMAC2(ch,invertd,BLIS_TAPI_EX_SUF) \ ( \ diagoffc, \ panel_dim, \ panel_len, \ p, 1, ldp, \ cntx, \ NULL \ ); \ } \ \ /* Set the region opposite the diagonal of p to zero. To do this, we need to reference the "unstored" region on the other side of the diagonal. This amounts to toggling uploc and then shifting the diagonal offset to shrink the newly referenced region (by one diagonal). Note that this zero-filling is not needed for trsm, since the unstored region is not referenced by the trsm micro-kernel; however, zero-filling is needed for trmm, which uses the gemm micro-kernel.*/ \ { \ ctype* restrict zero = PASTEMAC(ch,0); \ uplo_t uplop = uploc; \ \ bli_toggle_uplo( &uplop ); \ bli_shift_diag_offset_to_shrink_uplo( uplop, &diagoffc ); \ \ PASTEMAC2(ch,setm,BLIS_TAPI_EX_SUF) \ ( \ BLIS_NO_CONJUGATE, \ diagoffc, \ BLIS_NONUNIT_DIAG, \ uplop, \ panel_dim, \ panel_len, \ zero, \ p, 1, ldp, \ cntx, \ NULL \ ); \ } \ \ /* If this panel is an edge case in both panel dimension and length, then it must be a bottom-right corner case. Set the part of the diagonal that extends into the zero-padded region to identity. NOTE: This is actually only necessary when packing for trsm, as it helps prevent NaNs and Infs from creeping into the computation. However, we set the region to identity for trmm as well. Those 1.0's end up getting muliplied by the 0.0's in the zero-padded region of the other matrix, so there is no harm in this. */ \ if ( panel_dim != panel_dim_max && \ panel_len != panel_len_max ) \ { \ ctype* restrict one = PASTEMAC(ch,1); \ dim_t i = panel_dim; \ dim_t j = panel_len; \ dim_t m_br = panel_dim_max - i; \ dim_t n_br = panel_len_max - j; \ ctype* p_br = p + (i ) + (j )*ldp; \ \ PASTEMAC2(ch,setd,BLIS_TAPI_EX_SUF) \ ( \ BLIS_NO_CONJUGATE, \ 0, \ m_br, \ n_br, \ one, \ p_br, 1, ldp, \ cntx, \ NULL \ ); \ } \ } INSERT_GENTFUNC_BASIC( packm_tri_cxk, packm_cxk ) blis-0.9.0/frame/1m/packm/bli_packm_struc_cxk.h000066400000000000000000000047501422157504600213460ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #undef GENTPROT #define GENTPROT( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ struc_t strucc, \ diag_t diagc, \ uplo_t uploc, \ conj_t conjc, \ pack_t schema, \ bool invdiag, \ dim_t panel_dim, \ dim_t panel_len, \ dim_t panel_dim_max, \ dim_t panel_len_max, \ dim_t panel_dim_off, \ dim_t panel_len_off, \ ctype* restrict kappa, \ ctype* restrict c, inc_t incc, inc_t ldc, \ ctype* restrict p, inc_t ldp, \ inc_t is_p, \ cntx_t* cntx \ ); INSERT_GENTPROT_BASIC0( packm_struc_cxk ) INSERT_GENTPROT_BASIC0( packm_herm_cxk ) INSERT_GENTPROT_BASIC0( packm_tri_cxk ) blis-0.9.0/frame/1m/packm/bli_packm_struc_cxk_1er.c000066400000000000000000000354321422157504600221110ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENTFUNCCO #define GENTFUNCCO( ctype, ctype_r, ch, chr, varname, kername ) \ \ void PASTEMAC(ch,varname) \ ( \ struc_t strucc, \ diag_t diagc, \ uplo_t uploc, \ conj_t conjc, \ pack_t schema, \ bool invdiag, \ dim_t panel_dim, \ dim_t panel_len, \ dim_t panel_dim_max, \ dim_t panel_len_max, \ dim_t panel_dim_off, \ dim_t panel_len_off, \ ctype* restrict kappa, \ ctype* restrict c, inc_t incc, inc_t ldc, \ ctype* restrict p, inc_t ldp, \ inc_t is_p, \ cntx_t* cntx, \ void* params \ ) \ { \ /* Handle micro-panel packing based on the structure of the matrix being packed. */ \ if ( bli_is_general( strucc ) ) \ { \ /* For micro-panels of general matrices, we can call the pack kernel front-end directly. */ \ PASTEMAC(ch,kername) \ ( \ conjc, \ schema, \ panel_dim, \ panel_dim_max, \ panel_len, \ panel_len_max, \ kappa, \ c, incc, ldc, \ p, ldp, \ cntx \ ); \ } \ else if ( bli_is_herm_or_symm( strucc ) ) \ { \ /* Call a helper function for micro-panels of Hermitian/symmetric matrices. */ \ PASTEMAC(ch,packm_herm_cxk_1er) \ ( \ strucc, \ diagc, \ uploc, \ conjc, \ schema, \ invdiag, \ panel_dim, \ panel_len, \ panel_dim_max, \ panel_len_max, \ panel_dim_off, \ panel_len_off, \ kappa, \ c, incc, ldc, \ p, ldp, \ is_p, \ cntx, \ params \ ); \ } \ else /* ( bli_is_triangular( strucc ) ) */ \ { \ /* Call a helper function for micro-panels of triangular matrices. */ \ PASTEMAC(ch,packm_tri_cxk_1er) \ ( \ strucc, \ diagc, \ uploc, \ conjc, \ schema, \ invdiag, \ panel_dim, \ panel_len, \ panel_dim_max, \ panel_len_max, \ panel_dim_off, \ panel_len_off, \ kappa, \ c, incc, ldc, \ p, ldp, \ is_p, \ cntx, \ params \ ); \ } \ } INSERT_GENTFUNCCO_BASIC( packm_struc_cxk_1er, packm_cxk_1er ) #undef GENTFUNCCO #define GENTFUNCCO( ctype, ctype_r, ch, chr, varname, kername ) \ \ void PASTEMAC(ch,varname) \ ( \ struc_t strucc, \ diag_t diagc, \ uplo_t uploc, \ conj_t conjc, \ pack_t schema, \ bool invdiag, \ dim_t panel_dim, \ dim_t panel_len, \ dim_t panel_dim_max, \ dim_t panel_len_max, \ dim_t panel_dim_off, \ dim_t panel_len_off, \ ctype* restrict kappa, \ ctype* restrict c, inc_t incc, inc_t ldc, \ ctype* restrict p, inc_t ldp, \ inc_t is_p, \ cntx_t* cntx, \ void* params \ ) \ { \ doff_t diagoffc = panel_dim_off - panel_len_off; \ doff_t diagoffc_abs; \ dim_t j; \ \ /* Handle the case where the micro-panel does NOT intersect the diagonal separately from the case where it does intersect. */ \ if ( !bli_intersects_diag_n( diagoffc, panel_dim, panel_len ) ) \ { \ /* If the current panel is unstored, we need to make a few adjustments so we refer to the data where it is actually stored, also taking conjugation into account. (Note this implicitly assumes we are operating on a dense panel within a larger symmetric or Hermitian matrix, since a general matrix would not contain any unstored region.) */ \ if ( bli_is_unstored_subpart_n( diagoffc, uploc, panel_dim, panel_len ) ) \ { \ c = c + diagoffc * ( doff_t )ldc + \ -diagoffc * ( doff_t )incc; \ bli_swap_incs( &incc, &ldc ); \ \ if ( bli_is_hermitian( strucc ) ) \ bli_toggle_conj( &conjc ); \ } \ \ /* Pack the full panel. */ \ PASTEMAC(ch,kername) \ ( \ conjc, \ schema, \ panel_dim, \ panel_dim_max, \ panel_len, \ panel_len_max, \ kappa, \ c, incc, ldc, \ p, ldp, \ cntx \ ); \ } \ else /* if ( bli_intersects_diag_n( diagoffc, panel_dim, panel_len ) ) */ \ { \ ctype* restrict c10; \ ctype* restrict p10; \ dim_t p10_dim, p10_len; \ inc_t incc10, ldc10; \ doff_t diagoffc10; \ conj_t conjc10; \ \ ctype* restrict c12; \ ctype* restrict p12; \ dim_t p12_dim, p12_len; \ inc_t incc12, ldc12; \ doff_t diagoffc12; \ conj_t conjc12; \ \ \ /* Sanity check. Diagonals should not intersect the short end of a micro-panel. If they do, then somehow the constraints on cache blocksizes being a whole multiple of the register blocksizes was somehow violated. */ \ if ( diagoffc < 0 ) \ bli_check_error_code( BLIS_NOT_YET_IMPLEMENTED ); \ \ diagoffc_abs = bli_abs( diagoffc ); \ \ if ( bli_is_lower( uploc ) ) \ { \ p10_dim = panel_dim; \ p10_len = diagoffc_abs; \ p10 = p; \ c10 = c; \ incc10 = incc; \ ldc10 = ldc; \ conjc10 = conjc; \ \ p12_dim = panel_dim; \ p12_len = panel_len - p10_len; \ j = p10_len; \ diagoffc12 = diagoffc_abs - j; \ p12 = p + (j )*ldp; \ c12 = c + (j )*ldc; \ c12 = c12 + diagoffc12 * ( doff_t )ldc + \ -diagoffc12 * ( doff_t )incc; \ incc12 = ldc; \ ldc12 = incc; \ conjc12 = conjc; \ \ if ( bli_is_hermitian( strucc ) ) \ bli_toggle_conj( &conjc12 ); \ } \ else /* if ( bli_is_upper( uploc ) ) */ \ { \ p10_dim = panel_dim; \ p10_len = diagoffc_abs + panel_dim; \ diagoffc10 = diagoffc; \ p10 = p; \ c10 = c; \ c10 = c10 + diagoffc10 * ( doff_t )ldc + \ -diagoffc10 * ( doff_t )incc; \ incc10 = ldc; \ ldc10 = incc; \ conjc10 = conjc; \ \ p12_dim = panel_dim; \ p12_len = panel_len - p10_len; \ j = p10_len; \ p12 = p + (j )*ldp; \ c12 = c + (j )*ldc; \ incc12 = incc; \ ldc12 = ldc; \ conjc12 = conjc; \ \ if ( bli_is_hermitian( strucc ) ) \ bli_toggle_conj( &conjc10 ); \ } \ \ /* Pack to p10. For upper storage, this includes the unstored triangle of c11. */ \ /* NOTE: Since we're only packing partial panels here, we pass in p1x_len as panel_len_max; otherwise, the packm kernel will zero- fill the columns up to panel_len_max, which is not what we need or want to happen. */ \ PASTEMAC(ch,kername) \ ( \ conjc10, \ schema, \ p10_dim, \ panel_dim_max, \ p10_len, \ p10_len, \ kappa, \ c10, incc10, ldc10, \ p10, ldp, \ cntx \ ); \ \ /* Pack to p12. For lower storage, this includes the unstored triangle of c11. */ \ /* NOTE: Since we're only packing partial panels here, we pass in p1x_len as panel_len_max; otherwise, the packm kernel will zero- fill the columns up to panel_len_max, which is not what we need or want to happen. */ \ PASTEMAC(ch,kername) \ ( \ conjc12, \ schema, \ p12_dim, \ panel_dim_max, \ p12_len, \ p12_len, \ kappa, \ c12, incc12, ldc12, \ p12, ldp, \ cntx \ ); \ \ /* Pack the stored triangle of c11 to p11. */ \ { \ dim_t j = diagoffc_abs; \ ctype* restrict c11 = c + (j )*ldc; \ ctype* restrict p11 = p + (j )*ldp; \ \ PASTEMAC(ch,scal21ms_mxn_uplo) \ ( \ schema, \ uploc, \ conjc, \ panel_dim, \ kappa, \ c11, incc, ldc, \ p11, 1, ldp, ldp \ ); \ \ /* If we are packing a micro-panel with Hermitian structure, we must take special care of the diagonal. Now, if kappa were guaranteed to be unit, all we would need to do is explicitly zero out the imaginary part of the diagonal of p11, in case the diagonal of the source matrix contained garbage (non-zero) imaginary values. HOWEVER, since kappa can be non-unit, things become a little more complicated. In general, we must re-apply the kappa scalar to ONLY the real part of the diagonal of the source matrix and save the result to the diagonal of p11. */ \ if ( bli_is_hermitian( strucc ) ) \ { \ ctype_r* restrict c11_r = ( ctype_r* )c11; \ const dim_t incc2 = 2*incc; \ const dim_t ldc2 = 2*ldc; \ \ PASTEMAC3(ch,chr,ch,scal21ms_mxn_diag) \ ( \ schema, \ panel_dim, \ panel_dim, \ kappa, \ c11_r, incc2, ldc2, \ p11, 1, ldp, ldp \ ); \ } \ } \ } \ } INSERT_GENTFUNCCO_BASIC( packm_herm_cxk_1er, packm_cxk_1er ) #undef GENTFUNCCO #define GENTFUNCCO( ctype, ctype_r, ch, chr, varname, kername ) \ \ void PASTEMAC(ch,varname) \ ( \ struc_t strucc, \ diag_t diagc, \ uplo_t uploc, \ conj_t conjc, \ pack_t schema, \ bool invdiag, \ dim_t panel_dim, \ dim_t panel_len, \ dim_t panel_dim_max, \ dim_t panel_len_max, \ dim_t panel_dim_off, \ dim_t panel_len_off, \ ctype* restrict kappa, \ ctype* restrict c, inc_t incc, inc_t ldc, \ ctype* restrict p, inc_t ldp, \ inc_t is_p, \ cntx_t* cntx, \ void* params \ ) \ { \ doff_t diagoffc = panel_dim_off - panel_len_off; \ doff_t diagoffc_abs = bli_abs( diagoffc ); \ ctype* p11 = p + (diagoffc_abs )*ldp; \ \ \ /* Pack the panel. */ \ PASTEMAC(ch,kername) \ ( \ conjc, \ schema, \ panel_dim, \ panel_dim_max, \ panel_len, \ panel_len_max, \ kappa, \ c, incc, ldc, \ p, ldp, \ cntx \ ); \ \ \ /* Tweak the panel according to its triangular structure */ \ { \ /* If the diagonal of c is implicitly unit, explicitly set the the diagonal of the packed panel to kappa. */ \ if ( bli_is_unit_diag( diagc ) ) \ { \ PASTEMAC(ch,set1ms_mxn_diag) \ ( \ schema, \ 0, \ 0, \ panel_dim, \ panel_dim, \ kappa, \ p11, 1, ldp, ldp \ ); \ } \ \ \ /* If requested, invert the diagonal of the packed panel. */ \ if ( invdiag == TRUE ) \ { \ PASTEMAC(ch,invert1ms_mxn_diag) \ ( \ schema, \ 0, \ 0, \ panel_dim, \ panel_dim, \ p11, 1, ldp, ldp \ ); \ } \ \ \ /* Set the region opposite the diagonal of p to zero. To do this, we need to reference the "unstored" region on the other side of the diagonal. This amounts to toggling uploc and then shifting the diagonal offset to shrink the newly referenced region (by one diagonal). Note that this zero-filling is not needed for trsm, since the unstored region is not referenced by the trsm micro-kernel; however, zero-filling is needed for trmm, which uses the gemm micro-kernel.*/ \ { \ ctype* restrict zero = PASTEMAC(ch,0); \ uplo_t uplop = uploc; \ doff_t diagoffc11_0 = 0; \ dim_t p11_0_dim = panel_dim - 1; \ \ bli_toggle_uplo( &uplop ); \ bli_shift_diag_offset_to_shrink_uplo( uplop, &diagoffc11_0 ); \ \ /* Note that this macro works a little differently than the setm operation. Here, we pass in the dimensions of only p11, rather than the whole micro-panel, and furthermore we pass in the "shrunken" dimensions of p11, corresponding to the toggling and shrinking of the diagonal above. The macro will do the right thing, incrementing the pointer to p11 by the appropriate leading dimension (ldp or rs_p), and setting only the lower or upper triangle to zero. */ \ PASTEMAC(ch,set1ms_mxn_uplo) \ ( \ schema, \ diagoffc11_0, \ uplop, \ p11_0_dim, \ p11_0_dim, \ zero, \ p11, 1, ldp, ldp \ ); \ } \ } \ \ /* If this micro-panel is an edge case in both panel dimension and length, then it must be a bottom-right corner case, which typically only happens for micro-panels being packed for trsm. (It also happens for trmm if kr > 1.) Here, we set the part of the diagonal that extends into the zero-padded region to identity. This prevents NaNs and Infs from creeping into the computation. If this code does execute for trmm, it is okay, because those 1.0's that extend into the bottom-right region end up getting muliplied by the 0.0's in the zero-padded region of the other matrix. */ \ if ( panel_dim != panel_dim_max && \ panel_len != panel_len_max ) \ { \ ctype* restrict one = PASTEMAC(ch,1); \ dim_t offm = panel_dim; \ dim_t offn = panel_len; \ dim_t m_edge = panel_dim_max - panel_dim; \ dim_t n_edge = panel_len_max - panel_len; \ \ PASTEMAC(ch,set1ms_mxn_diag) \ ( \ schema, \ offm, \ offn, \ m_edge, \ n_edge, \ one, \ p, 1, ldp, ldp \ ); \ } \ } INSERT_GENTFUNCCO_BASIC( packm_tri_cxk_1er, packm_cxk_1er ) blis-0.9.0/frame/1m/packm/bli_packm_struc_cxk_1er.h000066400000000000000000000050541422157504600221130ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #undef GENTPROTCO #define GENTPROTCO( ctype, ctype_r, ch, chr, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ struc_t strucc, \ diag_t diagc, \ uplo_t uploc, \ conj_t conjc, \ pack_t schema, \ bool invdiag, \ dim_t panel_dim, \ dim_t panel_len, \ dim_t panel_dim_max, \ dim_t panel_len_max, \ dim_t panel_dim_off, \ dim_t panel_len_off, \ ctype* restrict kappa, \ ctype* restrict c, inc_t incc, inc_t ldc, \ ctype* restrict p, inc_t ldp, \ inc_t is_p, \ cntx_t* cntx, \ void* params \ ); INSERT_GENTPROTCO_BASIC0( packm_struc_cxk_1er ) INSERT_GENTPROTCO_BASIC0( packm_herm_cxk_1er ) INSERT_GENTPROTCO_BASIC0( packm_tri_cxk_1er ) blis-0.9.0/frame/1m/packm/bli_packm_struc_cxk_md.c000066400000000000000000000322431422157504600220170ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #ifdef BLIS_ENABLE_GEMM_MD #undef GENTFUNC2 #define GENTFUNC2( ctype_c, ctype_p, chc, chp, varname ) \ \ void PASTEMAC2(chc,chp,varname) \ ( \ struc_t strucc, \ diag_t diagc, \ uplo_t uploc, \ conj_t conjc, \ pack_t schema, \ bool invdiag, \ dim_t panel_dim, \ dim_t panel_len, \ dim_t panel_dim_max, \ dim_t panel_len_max, \ dim_t panel_dim_off, \ dim_t panel_len_off, \ ctype_p* restrict kappa, \ ctype_c* restrict c, inc_t incc, inc_t ldc, \ ctype_p* restrict p, inc_t ldp, \ inc_t is_p, \ cntx_t* cntx, \ void* params \ ) \ { \ if ( bli_is_nat_packed( schema ) ) \ { \ /* Sanity check: Make sure that kappa is 1.0. Mixed-datatype alpha values are never handled when packing for native execution; instead, they are passed along to the micro-kernel. */ \ if ( !PASTEMAC(chp,eq1)( *kappa ) ) \ bli_check_error_code( BLIS_NOT_YET_IMPLEMENTED ); \ \ /* Treat the micro-panel as panel_dim x panel_len and column-stored (unit row stride). */ \ \ /* NOTE: We ignore kappa for now, since it should be 1.0. */ \ PASTEMAC2(chc,chp,castm) \ ( \ ( trans_t )conjc, \ panel_dim, \ panel_len, \ c, incc, ldc, \ p, 1, ldp \ ); \ \ /* If panel_dim < panel_dim_max, then we zero those unused rows. */ \ if ( panel_dim < panel_dim_max ) \ { \ ctype_p* restrict zero = PASTEMAC(chp,0); \ const dim_t i = panel_dim; \ const dim_t m_edge = panel_dim_max - i; \ const dim_t n_edge = panel_len_max; \ ctype_p* p_edge = p + (i )*1; \ \ PASTEMAC2(chp,setm,BLIS_TAPI_EX_SUF) \ ( \ BLIS_NO_CONJUGATE, \ 0, \ BLIS_NONUNIT_DIAG, \ BLIS_DENSE, \ m_edge, \ n_edge, \ zero, \ p_edge, 1, ldp, \ cntx, \ NULL \ ); \ } \ \ /* If panel_len < panel_len_max, then we zero those unused columns. */ \ if ( panel_len < panel_len_max ) \ { \ ctype_p* restrict zero = PASTEMAC(chp,0); \ const dim_t j = panel_len; \ const dim_t m_edge = panel_dim_max; \ const dim_t n_edge = panel_len_max - j; \ ctype_p* p_edge = p + (j )*ldp; \ \ PASTEMAC2(chp,setm,BLIS_TAPI_EX_SUF) \ ( \ BLIS_NO_CONJUGATE, \ 0, \ BLIS_NONUNIT_DIAG, \ BLIS_DENSE, \ m_edge, \ n_edge, \ zero, \ p_edge, 1, ldp, \ cntx, \ NULL \ ); \ } \ } \ else if ( bli_is_1r_packed( schema ) ) \ { \ /* Treat the micro-panel as panel_dim x panel_len and column-stored (unit row stride). */ \ \ PASTEMAC2(chc,chp,packm_cxk_1r_md) \ ( \ conjc, \ panel_dim, \ panel_len, \ kappa, \ c, incc, ldc, \ p, ldp \ ); \ \ /* If panel_dim < panel_dim_max, then we zero those unused rows. */ \ if ( panel_dim < panel_dim_max ) \ { \ ctype_p* restrict zero = PASTEMAC(chp,0); \ const dim_t offm = panel_dim; \ const dim_t offn = 0; \ const dim_t m_edge = panel_dim_max - panel_dim; \ const dim_t n_edge = panel_len_max; \ \ ( void ) zero; \ ( void ) m_edge; ( void )offm; \ ( void ) n_edge; ( void )offn; \ \ PASTEMAC(chp,set1ms_mxn) \ ( \ schema, \ offm, \ offn, \ m_edge, \ n_edge, \ zero, \ p, 1, ldp, ldp \ ); \ } \ \ /* If panel_len < panel_len_max, then we zero those unused columns. */ \ if ( panel_len < panel_len_max ) \ { \ ctype_p* restrict zero = PASTEMAC(chp,0); \ const dim_t offm = 0; \ const dim_t offn = panel_len; \ const dim_t m_edge = panel_dim_max; \ const dim_t n_edge = panel_len_max - panel_len; \ \ ( void ) zero; \ ( void ) m_edge; ( void )offm; \ ( void ) n_edge; ( void )offn; \ \ PASTEMAC(chp,set1ms_mxn) \ ( \ schema, \ offm, \ offn, \ m_edge, \ n_edge, \ zero, \ p, 1, ldp, ldp \ ); \ } \ } \ else if ( bli_is_1e_packed( schema ) ) \ { \ /* Treat the micro-panel as panel_dim x panel_len and column-stored (unit row stride). */ \ \ PASTEMAC2(chc,chp,packm_cxk_1e_md) \ ( \ conjc, \ panel_dim, \ panel_len, \ kappa, \ c, incc, ldc, \ p, ldp \ ); \ \ /* If panel_dim < panel_dim_max, then we zero those unused rows. */ \ if ( panel_dim < panel_dim_max ) \ { \ ctype_p* restrict zero = PASTEMAC(chp,0); \ const dim_t offm = panel_dim; \ const dim_t offn = 0; \ const dim_t m_edge = panel_dim_max - panel_dim; \ const dim_t n_edge = panel_len_max; \ \ ( void ) zero; \ ( void ) m_edge; ( void )offm; \ ( void ) n_edge; ( void )offn; \ \ PASTEMAC(chp,set1ms_mxn) \ ( \ schema, \ offm, \ offn, \ m_edge, \ n_edge, \ zero, \ p, 1, ldp, ldp \ ); \ } \ \ /* If panel_len < panel_len_max, then we zero those unused columns. */ \ if ( panel_len < panel_len_max ) \ { \ ctype_p* restrict zero = PASTEMAC(chp,0); \ const dim_t offm = 0; \ const dim_t offn = panel_len; \ const dim_t m_edge = panel_dim_max; \ const dim_t n_edge = panel_len_max - panel_len; \ \ ( void ) zero; \ ( void ) m_edge; ( void )offm; \ ( void ) n_edge; ( void )offn; \ \ PASTEMAC(chp,set1ms_mxn) \ ( \ schema, \ offm, \ offn, \ m_edge, \ n_edge, \ zero, \ p, 1, ldp, ldp \ ); \ } \ } \ else \ { \ /* Mixed-datatype packing should not occur for any other schemas. */ \ bli_check_error_code( BLIS_NOT_YET_IMPLEMENTED ); \ } \ \ \ /* if ( bli_is_col_packed( schema ) ) \ PASTEMAC(ch,fprintm)( stdout, "packm_struc_cxk: bp copied", m_panel_max, n_panel_max, \ p, rs_p, cs_p, "%4.1f", "" ); \ else if ( bli_is_row_packed( schema ) ) \ PASTEMAC(ch,fprintm)( stdout, "packm_struc_cxk: ap copied", m_panel_max, n_panel_max, \ p, rs_p, cs_p, "%4.1f", "" ); \ */ \ } INSERT_GENTFUNC2_BASIC0( packm_struc_cxk_md ) INSERT_GENTFUNC2_MIXDP0( packm_struc_cxk_md ) // ----------------------------------------------------------------------------- #undef GENTFUNC2 #define GENTFUNC2( ctype_a, ctype_p, cha, chp, opname ) \ \ void PASTEMAC2(cha,chp,opname) \ ( \ conj_t conja, \ dim_t m, \ dim_t n, \ ctype_p* restrict kappa, \ ctype_a* restrict a, inc_t inca, inc_t lda, \ ctype_p* restrict p, inc_t ldp \ ) \ { \ const inc_t inca2 = 2 * inca; \ const inc_t lda2 = 2 * lda; \ const inc_t ldp2 = 2 * ldp; \ \ PASTEMAC(chp,ctyper)* restrict kappa_r = ( PASTEMAC(chp,ctyper)* )kappa; \ PASTEMAC(chp,ctyper)* restrict kappa_i = ( PASTEMAC(chp,ctyper)* )kappa + 1; \ PASTEMAC(cha,ctyper)* restrict alpha1_r = ( PASTEMAC(cha,ctyper)* )a; \ PASTEMAC(cha,ctyper)* restrict alpha1_i = ( PASTEMAC(cha,ctyper)* )a + 1; \ PASTEMAC(chp,ctyper)* restrict pi1_r = ( PASTEMAC(chp,ctyper)* )p; \ PASTEMAC(chp,ctyper)* restrict pi1_i = ( PASTEMAC(chp,ctyper)* )p + ldp; \ \ ( void )kappa_i; \ \ if ( PASTEMAC(chp,eq1)( *kappa ) ) \ { \ if ( bli_is_conj( conja ) ) \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ for ( dim_t i = 0; i < m; ++i ) \ { \ PASTEMAC2(cha,chp,copyjris) \ ( \ *(alpha1_r + i*inca2), \ *(alpha1_i + i*inca2), \ *(pi1_r + i* 1), \ *(pi1_i + i* 1) \ ); \ } \ \ alpha1_r += lda2; \ alpha1_i += lda2; \ pi1_r += ldp2; \ pi1_i += ldp2; \ } \ } \ else \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ for ( dim_t i = 0; i < m; ++i ) \ { \ PASTEMAC2(cha,chp,copyris) \ ( \ *(alpha1_r + i*inca2), \ *(alpha1_i + i*inca2), \ *(pi1_r + i* 1), \ *(pi1_i + i* 1) \ ); \ } \ \ alpha1_r += lda2; \ alpha1_i += lda2; \ pi1_r += ldp2; \ pi1_i += ldp2; \ } \ } \ } \ else \ { \ if ( bli_is_conj( conja ) ) \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ for ( dim_t i = 0; i < m; ++i ) \ { \ PASTEMAC3(chp,cha,chp,scal2jris) \ ( \ *kappa_r, \ *kappa_i, \ *(alpha1_r + i*inca2), \ *(alpha1_i + i*inca2), \ *(pi1_r + i* 1), \ *(pi1_i + i* 1) \ ); \ } \ \ alpha1_r += lda2; \ alpha1_i += lda2; \ pi1_r += ldp2; \ pi1_i += ldp2; \ } \ } \ else \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ for ( dim_t i = 0; i < m; ++i ) \ { \ PASTEMAC3(chp,cha,chp,scal2ris) \ ( \ *kappa_r, \ *kappa_i, \ *(alpha1_r + i*inca2), \ *(alpha1_i + i*inca2), \ *(pi1_r + i* 1), \ *(pi1_i + i* 1) \ ); \ } \ \ alpha1_r += lda2; \ alpha1_i += lda2; \ pi1_r += ldp2; \ pi1_i += ldp2; \ } \ } \ } \ } INSERT_GENTFUNC2_BASIC0( packm_cxk_1r_md ) INSERT_GENTFUNC2_MIXDP0( packm_cxk_1r_md ) // ----------------------------------------------------------------------------- #undef GENTFUNC2 #define GENTFUNC2( ctype_a, ctype_p, cha, chp, opname ) \ \ void PASTEMAC2(cha,chp,opname) \ ( \ conj_t conja, \ dim_t m, \ dim_t n, \ ctype_p* restrict kappa, \ ctype_a* restrict a, inc_t inca, inc_t lda, \ ctype_p* restrict p, inc_t ldp \ ) \ { \ const inc_t inca1 = inca; \ const inc_t lda1 = lda; \ const inc_t ldp1 = ldp; \ \ ctype_a* restrict alpha1_ri = ( ctype_a* )a; \ ctype_p* restrict pi1_ri = ( ctype_p* )p; \ ctype_p* restrict pi1_ir = ( ctype_p* )p + ldp1/2; \ \ ( void )inca1; \ \ if ( PASTEMAC(chp,eq1)( *kappa ) ) \ { \ if ( bli_is_conj( conja ) ) \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ for ( dim_t i = 0; i < m; ++i ) \ { \ PASTEMAC2(cha,chp,copyj1es) \ ( \ *(alpha1_ri + i*inca1), \ *(pi1_ri + i* 1), \ *(pi1_ir + i* 1) \ ); \ } \ \ alpha1_ri += lda1; \ pi1_ri += ldp1; \ pi1_ir += ldp1; \ } \ } \ else \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ for ( dim_t i = 0; i < m; ++i ) \ { \ PASTEMAC2(cha,chp,copy1es) \ ( \ *(alpha1_ri + i*inca1), \ *(pi1_ri + i* 1), \ *(pi1_ir + i* 1) \ ); \ } \ \ alpha1_ri += lda1; \ pi1_ri += ldp1; \ pi1_ir += ldp1; \ } \ } \ } \ else \ { \ if ( bli_is_conj( conja ) ) \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ for ( dim_t i = 0; i < m; ++i ) \ { \ PASTEMAC3(chp,cha,chp,scal2j1es) \ ( \ *kappa, \ *(alpha1_ri + i*inca1), \ *(pi1_ri + i* 1), \ *(pi1_ir + i* 1) \ ); \ } \ \ alpha1_ri += lda1; \ pi1_ri += ldp1; \ pi1_ir += ldp1; \ } \ } \ else \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ for ( dim_t i = 0; i < m; ++i ) \ { \ PASTEMAC3(chp,cha,chp,scal21es) \ ( \ *kappa, \ *(alpha1_ri + i*inca1), \ *(pi1_ri + i* 1), \ *(pi1_ir + i* 1) \ ); \ } \ \ alpha1_ri += lda1; \ pi1_ri += ldp1; \ pi1_ir += ldp1; \ } \ } \ } \ } INSERT_GENTFUNC2_BASIC0( packm_cxk_1e_md ) INSERT_GENTFUNC2_MIXDP0( packm_cxk_1e_md ) #endif blis-0.9.0/frame/1m/packm/bli_packm_struc_cxk_md.h000066400000000000000000000061001422157504600220150ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #undef GENTPROT2 #define GENTPROT2( ctype_c, ctype_p, chc, chp, varname ) \ \ void PASTEMAC2(chc,chp,varname) \ ( \ struc_t strucc, \ diag_t diagc, \ uplo_t uploc, \ conj_t conjc, \ pack_t schema, \ bool invdiag, \ dim_t panel_dim, \ dim_t panel_len, \ dim_t panel_dim_max, \ dim_t panel_len_max, \ dim_t panel_dim_off, \ dim_t panel_len_off, \ ctype_p* restrict kappa, \ ctype_c* restrict c, inc_t incc, inc_t ldc, \ ctype_p* restrict p, inc_t ldp, \ inc_t is_p, \ cntx_t* cntx, \ void* params \ ); INSERT_GENTPROT2_BASIC0( packm_struc_cxk_md ) INSERT_GENTPROT2_MIXDP0( packm_struc_cxk_md ) #undef GENTPROT2 #define GENTPROT2( ctype_a, ctype_p, cha, chp, opname ) \ \ void PASTEMAC2(cha,chp,opname) \ ( \ conj_t conja, \ dim_t m, \ dim_t n, \ ctype_p* restrict kappa, \ ctype_a* restrict a, inc_t inca, inc_t lda, \ ctype_p* restrict p, inc_t ldp \ ); INSERT_GENTPROT2_BASIC0( packm_cxk_1e_md ) INSERT_GENTPROT2_MIXDP0( packm_cxk_1e_md ) INSERT_GENTPROT2_BASIC0( packm_cxk_1r_md ) INSERT_GENTPROT2_MIXDP0( packm_cxk_1r_md ) blis-0.9.0/frame/1m/packm/bli_packm_thrinfo.c000066400000000000000000000043461422157504600210060ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_packm_thrinfo_init ( thrinfo_t* thread, thrcomm_t* ocomm, dim_t ocomm_id, dim_t n_way, dim_t work_id, bszid_t bszid, thrinfo_t* sub_node ) { bli_thrinfo_init ( thread, ocomm, ocomm_id, n_way, work_id, FALSE, BLIS_NO_PART, sub_node ); } void bli_packm_thrinfo_init_single ( thrinfo_t* thread ) { bli_packm_thrinfo_init ( thread, &BLIS_SINGLE_COMM, 0, 1, 0, BLIS_NO_PART, NULL ); } blis-0.9.0/frame/1m/packm/bli_packm_thrinfo.h000066400000000000000000000057621422157504600210160ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // thrinfo_t macros specific to packm. // /* #define bli_packm_thread_my_iter( index, thread ) \ \ ( index % thread->n_way == thread->work_id % thread->n_way ) */ #define bli_packm_my_iter_rr( i, start, end, work_id, n_way ) \ \ ( i % n_way == work_id % n_way ) #define bli_packm_my_iter_sl( i, start, end, work_id, n_way ) \ \ ( start <= i && i < end ) // Define a general-purpose version of bli_packm_my_iter() whose definition // depends on whether slab or round-robin partitioning was requested at // configure-time. #ifdef BLIS_ENABLE_JRIR_SLAB #define bli_packm_my_iter bli_packm_my_iter_sl #else // BLIS_ENABLE_JRIR_RR #define bli_packm_my_iter bli_packm_my_iter_rr #endif // // thrinfo_t APIs specific to packm. // #if 0 thrinfo_t* bli_packm_thrinfo_create ( thrcomm_t* ocomm, dim_t ocomm_id, dim_t n_way, dim_t work_id, thrinfo_t* sub_node ); #endif void bli_packm_thrinfo_init ( thrinfo_t* thread, thrcomm_t* ocomm, dim_t ocomm_id, dim_t n_way, dim_t work_id, bszid_t bszid, thrinfo_t* sub_node ); void bli_packm_thrinfo_init_single ( thrinfo_t* thread ); #if 0 void bli_packm_thrinfo_free ( thrinfo_t* thread ); #endif blis-0.9.0/frame/1m/unpackm/000077500000000000000000000000001422157504600155245ustar00rootroot00000000000000blis-0.9.0/frame/1m/unpackm/bli_unpackm.h000066400000000000000000000034441422157504600201660ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "bli_unpackm_cntl.h" #include "bli_unpackm_check.h" #include "bli_unpackm_int.h" #include "bli_unpackm_blk_var1.h" #include "bli_unpackm_cxk.h" blis-0.9.0/frame/1m/unpackm/bli_unpackm_blk_var1.c000066400000000000000000000206031422157504600217360ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define FUNCPTR_T unpackm_fp typedef void (*FUNCPTR_T)( struc_t strucc, doff_t diagoffc, diag_t diagc, uplo_t uploc, trans_t transc, dim_t m, dim_t n, dim_t m_panel, dim_t n_panel, void* p, inc_t rs_p, inc_t cs_p, dim_t pd_p, inc_t ps_p, void* c, inc_t rs_c, inc_t cs_c, cntx_t* cntx ); static FUNCPTR_T GENARRAY(ftypes,unpackm_blk_var1); void bli_unpackm_blk_var1 ( obj_t* p, obj_t* c, cntx_t* cntx, cntl_t* cntl, thrinfo_t* thread ) { num_t dt_cp = bli_obj_dt( c ); // Normally we take the parameters from the source argument. But here, // the packm/unpackm framework is not yet solidified enough for us to // assume that at this point struc(P) == struc(C), (ie: since // densification may have marked P's structure as dense when the root // is upper or lower). So, we take the struc field from C, not P. struc_t strucc = bli_obj_struc( c ); doff_t diagoffc = bli_obj_diag_offset( c ); diag_t diagc = bli_obj_diag( c ); uplo_t uploc = bli_obj_uplo( c ); // Again, normally the trans argument is on the source matrix. But we // know that the packed matrix is not transposed. If there is to be a // transposition, it is because C was originally transposed when packed. // Thus, we query C for the trans status, not P. Also, we only query // the trans status (not the conjugation status), since we probably // don't want to un-conjugate if the original matrix was conjugated // when packed. trans_t transc = bli_obj_onlytrans_status( c ); dim_t m_c = bli_obj_length( c ); dim_t n_c = bli_obj_width( c ); dim_t m_panel = bli_obj_panel_length( c ); dim_t n_panel = bli_obj_panel_width( c ); void* buf_p = bli_obj_buffer_at_off( p ); inc_t rs_p = bli_obj_row_stride( p ); inc_t cs_p = bli_obj_col_stride( p ); dim_t pd_p = bli_obj_panel_dim( p ); inc_t ps_p = bli_obj_panel_stride( p ); void* buf_c = bli_obj_buffer_at_off( c ); inc_t rs_c = bli_obj_row_stride( c ); inc_t cs_c = bli_obj_col_stride( c ); FUNCPTR_T f; // Index into the type combination array to extract the correct // function pointer. f = ftypes[dt_cp]; // Invoke the function. f( strucc, diagoffc, diagc, uploc, transc, m_c, n_c, m_panel, n_panel, buf_p, rs_p, cs_p, pd_p, ps_p, buf_c, rs_c, cs_c, cntx ); } #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ struc_t strucc, \ doff_t diagoffc, \ diag_t diagc, \ uplo_t uploc, \ trans_t transc, \ dim_t m, \ dim_t n, \ dim_t m_panel, \ dim_t n_panel, \ void* p, inc_t rs_p, inc_t cs_p, \ dim_t pd_p, inc_t ps_p, \ void* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx \ ) \ { \ ctype* restrict one = PASTEMAC(ch,1); \ ctype* restrict c_cast = c; \ ctype* restrict p_cast = p; \ ctype* restrict c_begin; \ ctype* restrict p_begin; \ \ dim_t iter_dim; \ dim_t num_iter; \ dim_t it, ic, ip; \ dim_t ic0, ip0; \ doff_t ic_inc, ip_inc; \ doff_t diagoffc_i; \ doff_t diagoffc_inc; \ dim_t panel_len; \ dim_t panel_dim_i; \ dim_t panel_dim_max; \ inc_t vs_c; \ inc_t incc, ldc; \ inc_t ldp; \ dim_t* m_panel_full; \ dim_t* n_panel_full; \ \ \ /* If c needs a transposition, induce it so that we can more simply express the remaining parameters and code. */ \ if ( bli_does_trans( transc ) ) \ { \ bli_swap_incs( &rs_c, &cs_c ); \ bli_negate_diag_offset( &diagoffc ); \ bli_toggle_uplo( &uploc ); \ bli_toggle_trans( &transc ); \ } \ \ /* If the strides of p indicate row storage, then we are packing to column panels; otherwise, if the strides indicate column storage, we are packing to row panels. */ \ if ( bli_is_row_stored_f( m_panel, n_panel, rs_p, cs_p ) ) \ { \ /* Prepare to unpack from column panels. */ \ iter_dim = n; \ panel_len = m; \ panel_dim_max = pd_p; \ incc = cs_c; \ ldc = rs_c; \ vs_c = cs_c; \ diagoffc_inc = -( doff_t)panel_dim_max; \ ldp = rs_p; \ m_panel_full = &m; \ n_panel_full = &panel_dim_i; \ } \ else /* if ( bli_is_col_stored_f( m_panel, n_panel, rs_p, cs_p ) ) */ \ { \ /* Prepare to unpack from row panels. */ \ iter_dim = m; \ panel_len = n; \ panel_dim_max = pd_p; \ incc = rs_c; \ ldc = cs_c; \ vs_c = rs_c; \ diagoffc_inc = ( doff_t )panel_dim_max; \ ldp = cs_p; \ m_panel_full = &panel_dim_i; \ n_panel_full = &n; \ } \ \ /* Compute the total number of iterations we'll need. */ \ num_iter = iter_dim / panel_dim_max + ( iter_dim % panel_dim_max ? 1 : 0 ); \ \ { \ ic0 = 0; \ ic_inc = panel_dim_max; \ ip0 = 0; \ ip_inc = 1; \ } \ \ for ( ic = ic0, ip = ip0, it = 0; it < num_iter; \ ic += ic_inc, ip += ip_inc, it += 1 ) \ { \ panel_dim_i = bli_min( panel_dim_max, iter_dim - ic ); \ \ diagoffc_i = diagoffc + (ip )*diagoffc_inc; \ \ p_begin = p_cast + ip * ps_p; \ c_begin = c_cast + ic * vs_c; \ \ /* If the current panel of C intersects the diagonal AND is upper or lower stored, then we must call scal2m. Otherwise, we can use a variant that is oblivious to structure and storage (and thus tends to be faster). */ \ if ( bli_intersects_diag_n( diagoffc_i, *m_panel_full, *n_panel_full ) && \ bli_is_upper_or_lower( uploc ) ) \ { \ PASTEMAC2(ch,scal2m,BLIS_TAPI_EX_SUF) \ ( \ diagoffc_i, \ diagc, \ uploc, \ transc, \ *m_panel_full, \ *n_panel_full, \ one, \ p_begin, rs_p, cs_p, \ c_begin, rs_c, cs_c, \ cntx, \ NULL \ ); \ } \ else \ { \ /* Pack the current panel. */ \ PASTEMAC(ch,unpackm_cxk) \ ( \ BLIS_NO_CONJUGATE, \ panel_dim_i, \ panel_len, \ one, \ p_begin, ldp, \ c_begin, incc, ldc, \ cntx \ ); \ } \ \ /*PASTEMAC(ch,fprintm)( stdout, "p copied", *m_panel_full, *n_panel_full, \ p_begin, rs_p, cs_p, "%4.1f", "" );*/ \ } \ \ } INSERT_GENTFUNC_BASIC0( unpackm_blk_var1 ) blis-0.9.0/frame/1m/unpackm/bli_unpackm_blk_var1.h000066400000000000000000000044451422157504600217510ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void bli_unpackm_blk_var1 ( obj_t* p, obj_t* c, cntx_t* cntx, cntl_t* cntl, thrinfo_t* thread ); #undef GENTPROT #define GENTPROT( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ struc_t strucc, \ doff_t diagoffc, \ diag_t diagc, \ uplo_t uploc, \ trans_t transc, \ dim_t m, \ dim_t n, \ dim_t m_panel, \ dim_t n_panel, \ void* p, inc_t rs_p, inc_t cs_p, \ dim_t pd_p, inc_t ps_p, \ void* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx \ ); INSERT_GENTPROT_BASIC0( unpackm_blk_var1 ) blis-0.9.0/frame/1m/unpackm/bli_unpackm_check.c000066400000000000000000000046321422157504600213160ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_unpackm_int_check ( obj_t* p, obj_t* a, cntx_t* cntx ) { err_t e_val; // Check object datatypes. e_val = bli_check_floating_object( p ); bli_check_error_code( e_val ); e_val = bli_check_floating_object( a ); bli_check_error_code( e_val ); // Check object dimensions. e_val = bli_check_conformal_dims( p, a ); bli_check_error_code( e_val ); // Check pack status. e_val = bli_check_packm_schema_on_unpack( p ); bli_check_error_code( e_val ); // Check control tree pointer // NOTE: We can't check the control tree until we stop interpreting a // NULL value (in bli_unpackm_int()) as a request to skip the operation. //e_val = bli_check_valid_cntl( ( void* )cntl ); //bli_check_error_code( e_val ); } blis-0.9.0/frame/1m/unpackm/bli_unpackm_check.h000066400000000000000000000033541422157504600213230ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void bli_unpackm_int_check ( obj_t* p, obj_t* a, cntx_t* cntx ); blis-0.9.0/frame/1m/unpackm/bli_unpackm_cntl.c000066400000000000000000000053221422157504600211760ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" cntl_t* bli_unpackm_cntl_create_node ( rntm_t* rntm, void_fp var_func, void_fp unpackm_var_func, cntl_t* sub_node ) { cntl_t* cntl; unpackm_params_t* params; err_t r_val; // NOTE: If this function is ever called, figure out whether the // bli_malloc_intl() below needs to be changed to bli_sba_acquire(). bli_abort(); // Allocate an unpackm_params_t struct. params = bli_malloc_intl( sizeof( unpackm_params_t ), &r_val ); // Initialize the unpackm_params_t struct. params->size = sizeof( unpackm_params_t ); params->var_func = unpackm_var_func; // It's important that we set the bszid field to BLIS_NO_PART to indicate // that no blocksize partitioning is performed. bli_cntl_free() will rely // on this information to know how to step through the thrinfo_t tree in // sync with the cntl_t tree. cntl = bli_cntl_create_node ( rntm, BLIS_NOID, BLIS_NO_PART, var_func, params, sub_node ); return cntl; } blis-0.9.0/frame/1m/unpackm/bli_unpackm_cntl.h000066400000000000000000000043251422157504600212050ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ struct unpackm_params_s { uint64_t size; // size field must be present and come first. unpackm_var_oft var_func; }; typedef struct unpackm_params_s unpackm_params_t; #define bli_cntl_unpackm_params_var_func( cntl ) \ \ ( ( (unpackm_params_t*)(cntl)->params )->var_func ) // ----------------------------------------------------------------------------- cntl_t* bli_unpackm_cntl_create_node ( rntm_t* rntm, void_fp var_func, void_fp unpackm_var_func, cntl_t* sub_node ); blis-0.9.0/frame/1m/unpackm/bli_unpackm_cxk.c000066400000000000000000000060071422157504600210240ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENTFUNC #define GENTFUNC( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ conj_t conjp, \ dim_t panel_dim, \ dim_t panel_len, \ ctype* kappa, \ ctype* p, inc_t ldp, \ ctype* a, inc_t inca, inc_t lda, \ cntx_t* cntx \ ) \ { \ num_t dt = PASTEMAC(ch,type); \ l1mkr_t ker_id = panel_dim; \ \ PASTECH2(ch,opname,_ker_ft) f; \ \ /* Query the context for the unpackm kernel corresponding to the current panel dimension, or kernel id. If the id is invalid, the function will return NULL. */ \ f = bli_cntx_get_unpackm_ker_dt( dt, ker_id, cntx ); \ \ /* If there exists a kernel implementation for the micro-panel dimension provided, we invoke the implementation. Otherwise, we use scal2m. */ \ if ( f != NULL ) \ { \ f \ ( \ conjp, \ panel_len, \ kappa, \ p, ldp, \ a, inca, lda, \ cntx \ ); \ } \ else \ { \ trans_t transp = ( trans_t )conjp; \ \ /* Treat the micro-panel as panel_dim x panel_len and column-stored (unit row stride). */ \ PASTEMAC2(ch,scal2m,BLIS_TAPI_EX_SUF) \ ( \ 0, \ BLIS_NONUNIT_DIAG, \ BLIS_DENSE, \ transp, \ panel_dim, \ panel_len, \ kappa, \ p, 1, ldp, \ a, inca, lda, \ cntx, \ NULL \ ); \ } \ } INSERT_GENTFUNC_BASIC0( unpackm_cxk ) blis-0.9.0/frame/1m/unpackm/bli_unpackm_cxk.h000066400000000000000000000037601422157504600210340ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #undef GENTPROT #define GENTPROT( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ conj_t conjp, \ dim_t panel_dim, \ dim_t panel_len, \ ctype* kappa, \ ctype* p, inc_t ldp, \ ctype* a, inc_t inca, inc_t lda, \ cntx_t* cntx \ ); INSERT_GENTPROT_BASIC0( unpackm_cxk ) blis-0.9.0/frame/1m/unpackm/bli_unpackm_int.c000066400000000000000000000047771422157504600210450ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_unpackm_int ( obj_t* p, obj_t* a, cntx_t* cntx, cntl_t* cntl, thrinfo_t* thread ) { bli_init_once(); unpackm_var_oft f; // Check parameters. if ( bli_error_checking_is_enabled() ) bli_unpackm_int_check( p, a, cntx ); // If p was aliased to a during the pack stage (because it was already // in an acceptable packed/contiguous format), then no unpack is actually // necessary, so we return. if ( bli_obj_is_alias_of( p, a ) ) return; // Extract the function pointer from the current control tree node. f = bli_cntl_unpackm_params_var_func( cntl ); // Invoke the variant. if ( bli_thread_am_ochief( thread ) ) { f ( p, a, cntx, cntl, thread ); } // Barrier so that unpacking is done before computation. bli_thread_barrier( thread ); } blis-0.9.0/frame/1m/unpackm/bli_unpackm_int.h000066400000000000000000000034251422157504600210370ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void bli_unpackm_int ( obj_t* p, obj_t* a, cntx_t* cntx, cntl_t* cntl, thrinfo_t* thread ); blis-0.9.0/frame/2/000077500000000000000000000000001422157504600137125ustar00rootroot00000000000000blis-0.9.0/frame/2/bli_l2.h000066400000000000000000000047761422157504600152440ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "bli_l2_check.h" // Define function types. #include "bli_l2_ft_unb.h" // Prototype object APIs (expert and non-expert). #include "bli_oapi_ex.h" #include "bli_l2_oapi.h" #include "bli_xapi_undef.h" #include "bli_oapi_ba.h" #include "bli_l2_oapi.h" #include "bli_xapi_undef.h" // Prototype typed APIs (expert and non-expert). #include "bli_tapi_ex.h" #include "bli_l2_tapi.h" #include "bli_l2_ft.h" #include "bli_xapi_undef.h" #include "bli_tapi_ba.h" #include "bli_l2_tapi.h" #include "bli_l2_ft.h" #include "bli_xapi_undef.h" // Generate function pointer arrays for tapi functions (expert only). #include "bli_l2_fpa.h" // Operation-specific headers #include "bli_gemv.h" #include "bli_ger.h" #include "bli_hemv.h" #include "bli_her.h" #include "bli_her2.h" #include "bli_symv.h" #include "bli_syr.h" #include "bli_syr2.h" #include "bli_trmv.h" #include "bli_trsv.h" blis-0.9.0/frame/2/bli_l2_check.c000066400000000000000000000244151422157504600163640ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_gemv_check ( obj_t* alpha, obj_t* a, obj_t* x, obj_t* beta, obj_t* y ) { err_t e_val; // Perform checks common to gemv/hemv/symv/trmv/trsv. bli_xxmv_check( alpha, a, x, beta, y ); // Check object structure. e_val = bli_check_general_object( a ); bli_check_error_code( e_val ); // Check for consistent datatypes. e_val = bli_check_consistent_object_datatypes( a, x ); bli_check_error_code( e_val ); e_val = bli_check_consistent_object_datatypes( a, y ); bli_check_error_code( e_val ); } void bli_hemv_check ( obj_t* alpha, obj_t* a, obj_t* x, obj_t* beta, obj_t* y ) { err_t e_val; // Perform checks common to gemv/hemv/symv/trmv/trsv. bli_xxmv_check( alpha, a, x, beta, y ); // Check squareness. e_val = bli_check_square_object( a ); bli_check_error_code( e_val ); // Check object structure. e_val = bli_check_hermitian_object( a ); bli_check_error_code( e_val ); // Check for consistent datatypes. e_val = bli_check_consistent_object_datatypes( a, x ); bli_check_error_code( e_val ); e_val = bli_check_consistent_object_datatypes( a, y ); bli_check_error_code( e_val ); } void bli_symv_check ( obj_t* alpha, obj_t* a, obj_t* x, obj_t* beta, obj_t* y ) { err_t e_val; // Perform checks common to gemv/hemv/symv/trmv/trsv. bli_xxmv_check( alpha, a, x, beta, y ); // Check squareness. e_val = bli_check_square_object( a ); bli_check_error_code( e_val ); // Check object structure. e_val = bli_check_symmetric_object( a ); bli_check_error_code( e_val ); // Check for consistent datatypes. e_val = bli_check_consistent_object_datatypes( a, x ); bli_check_error_code( e_val ); e_val = bli_check_consistent_object_datatypes( a, y ); bli_check_error_code( e_val ); } void bli_trmv_check ( obj_t* alpha, obj_t* a, obj_t* x ) { err_t e_val; // Perform checks common to gemv/hemv/symv/trmv/trsv. bli_xxmv_check( alpha, a, x, alpha, x ); // Check squareness. e_val = bli_check_square_object( a ); bli_check_error_code( e_val ); // Check object structure. e_val = bli_check_triangular_object( a ); bli_check_error_code( e_val ); // Check for consistent datatypes. e_val = bli_check_consistent_object_datatypes( a, x ); bli_check_error_code( e_val ); } void bli_trsv_check ( obj_t* alpha, obj_t* a, obj_t* x ) { err_t e_val; // Perform checks common to gemv/hemv/symv/trmv/trsv. bli_xxmv_check( alpha, a, x, alpha, x ); // Check squareness. e_val = bli_check_square_object( a ); bli_check_error_code( e_val ); // Check object structure. e_val = bli_check_triangular_object( a ); bli_check_error_code( e_val ); // Check for consistent datatypes. e_val = bli_check_consistent_object_datatypes( a, x ); bli_check_error_code( e_val ); } void bli_ger_check ( obj_t* alpha, obj_t* x, obj_t* y, obj_t* a ) { err_t e_val; // Perform checks common to ger/her/her2/syr/syr2. bli_xxr_check( alpha, x, y, a ); // Check object structure. e_val = bli_check_general_object( a ); bli_check_error_code( e_val ); // Check for consistent datatypes. e_val = bli_check_consistent_object_datatypes( a, x ); bli_check_error_code( e_val ); e_val = bli_check_consistent_object_datatypes( a, y ); bli_check_error_code( e_val ); } void bli_her_check ( obj_t* alpha, obj_t* x, obj_t* a ) { err_t e_val; // Perform checks common to ger/her/her2/syr/syr2. bli_xxr_check( alpha, x, x, a ); // Check squareness. e_val = bli_check_square_object( a ); bli_check_error_code( e_val ); // Check object structure. e_val = bli_check_hermitian_object( a ); bli_check_error_code( e_val ); // Check for consistent datatypes. e_val = bli_check_consistent_object_datatypes( a, x ); bli_check_error_code( e_val ); } void bli_her2_check ( obj_t* alpha, obj_t* x, obj_t* y, obj_t* a ) { err_t e_val; // Perform checks common to ger/her/her2/syr/syr2. bli_xxr_check( alpha, x, y, a ); // Check squareness. e_val = bli_check_square_object( a ); bli_check_error_code( e_val ); // Check object structure. e_val = bli_check_hermitian_object( a ); bli_check_error_code( e_val ); // Check for consistent datatypes. e_val = bli_check_consistent_object_datatypes( a, x ); bli_check_error_code( e_val ); e_val = bli_check_consistent_object_datatypes( a, y ); bli_check_error_code( e_val ); } void bli_syr_check ( obj_t* alpha, obj_t* x, obj_t* a ) { err_t e_val; // Perform checks common to ger/her/her2/syr/syr2. bli_xxr_check( alpha, x, x, a ); // Check squareness. e_val = bli_check_square_object( a ); bli_check_error_code( e_val ); // Check object structure. e_val = bli_check_symmetric_object( a ); bli_check_error_code( e_val ); // Check for consistent datatypes. e_val = bli_check_consistent_object_datatypes( a, x ); bli_check_error_code( e_val ); } void bli_syr2_check ( obj_t* alpha, obj_t* x, obj_t* y, obj_t* a ) { err_t e_val; // Perform checks common to ger/her/her2/syr/syr2. bli_xxr_check( alpha, x, y, a ); // Check squareness. e_val = bli_check_square_object( a ); bli_check_error_code( e_val ); // Check object structure. e_val = bli_check_symmetric_object( a ); bli_check_error_code( e_val ); // Check for consistent datatypes. e_val = bli_check_consistent_object_datatypes( a, x ); bli_check_error_code( e_val ); e_val = bli_check_consistent_object_datatypes( a, y ); bli_check_error_code( e_val ); } // ----------------------------------------------------------------------------- void bli_xxmv_check ( obj_t* alpha, obj_t* a, obj_t* x, obj_t* beta, obj_t* y ) { err_t e_val; // Check object datatypes. e_val = bli_check_noninteger_object( alpha ); bli_check_error_code( e_val ); e_val = bli_check_noninteger_object( beta ); bli_check_error_code( e_val ); e_val = bli_check_floating_object( a ); bli_check_error_code( e_val ); e_val = bli_check_floating_object( x ); bli_check_error_code( e_val ); e_val = bli_check_floating_object( y ); bli_check_error_code( e_val ); // Check object dimensions. e_val = bli_check_scalar_object( alpha ); bli_check_error_code( e_val ); e_val = bli_check_scalar_object( beta ); bli_check_error_code( e_val ); e_val = bli_check_matrix_object( a ); bli_check_error_code( e_val ); e_val = bli_check_vector_object( x ); bli_check_error_code( e_val ); e_val = bli_check_vector_object( y ); bli_check_error_code( e_val ); e_val = bli_check_vector_dim_equals( x, bli_obj_width_after_trans( a ) ); bli_check_error_code( e_val ); e_val = bli_check_vector_dim_equals( y, bli_obj_length_after_trans( a ) ); bli_check_error_code( e_val ); // Check object buffers (for non-NULLness). e_val = bli_check_object_buffer( alpha ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( a ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( x ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( beta ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( y ); bli_check_error_code( e_val ); } void bli_xxr_check ( obj_t* alpha, obj_t* x, obj_t* y, obj_t* a ) { err_t e_val; // Check object datatypes. e_val = bli_check_noninteger_object( alpha ); bli_check_error_code( e_val ); e_val = bli_check_floating_object( x ); bli_check_error_code( e_val ); e_val = bli_check_floating_object( y ); bli_check_error_code( e_val ); e_val = bli_check_floating_object( a ); bli_check_error_code( e_val ); // Check object dimensions. e_val = bli_check_scalar_object( alpha ); bli_check_error_code( e_val ); e_val = bli_check_vector_object( x ); bli_check_error_code( e_val ); e_val = bli_check_vector_object( y ); bli_check_error_code( e_val ); e_val = bli_check_matrix_object( a ); bli_check_error_code( e_val ); e_val = bli_check_vector_dim_equals( x, bli_obj_length_after_trans( a ) ); bli_check_error_code( e_val ); e_val = bli_check_vector_dim_equals( y, bli_obj_width_after_trans( a ) ); bli_check_error_code( e_val ); // Check object buffers (for non-NULLness). e_val = bli_check_object_buffer( alpha ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( x ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( y ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( a ); bli_check_error_code( e_val ); } blis-0.9.0/frame/2/bli_l2_check.h000066400000000000000000000055351422157504600163730ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype object-based check functions. // #undef GENPROT #define GENPROT( opname ) \ \ void PASTEMAC(opname,_check) \ ( \ obj_t* alpha, \ obj_t* a, \ obj_t* x, \ obj_t* beta, \ obj_t* y \ ); GENPROT( gemv ) GENPROT( hemv ) GENPROT( symv ) #undef GENPROT #define GENPROT( opname ) \ \ void PASTEMAC(opname,_check) \ ( \ obj_t* alpha, \ obj_t* x, \ obj_t* y, \ obj_t* a \ ); GENPROT( ger ) GENPROT( her2 ) GENPROT( syr2 ) #undef GENPROT #define GENPROT( opname ) \ \ void PASTEMAC(opname,_check) \ ( \ obj_t* alpha, \ obj_t* x, \ obj_t* a \ ); GENPROT( her ) GENPROT( syr ) #undef GENPROT #define GENPROT( opname ) \ \ void PASTEMAC(opname,_check) \ ( \ obj_t* alpha, \ obj_t* a, \ obj_t* x \ ); GENPROT( trmv ) GENPROT( trsv ) // ----------------------------------------------------------------------------- void bli_xxmv_check ( obj_t* alpha, obj_t* a, obj_t* x, obj_t* beta, obj_t* y ); void bli_xxr_check ( obj_t* alpha, obj_t* x, obj_t* y, obj_t* a ); blis-0.9.0/frame/2/bli_l2_fpa.c000066400000000000000000000066671422157504600160660ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // Define function pointer query interfaces. // #undef GENFRONT #define GENFRONT( opname ) \ \ GENARRAY_FPA( PASTECH2(opname,BLIS_TAPI_EX_SUF,_vft), \ PASTECH(opname,BLIS_TAPI_EX_SUF) ); \ \ PASTECH2(opname,BLIS_TAPI_EX_SUF,_vft) \ PASTEMAC2(opname,BLIS_TAPI_EX_SUF,_qfp)( num_t dt ) \ { \ return PASTECH2(opname,BLIS_TAPI_EX_SUF,_fpa)[ dt ]; \ } GENFRONT( gemv ) GENFRONT( ger ) GENFRONT( hemv ) GENFRONT( symv ) GENFRONT( her ) GENFRONT( syr ) GENFRONT( her2 ) GENFRONT( syr2 ) GENFRONT( trmv ) GENFRONT( trsv ) // // Define function pointer query interfaces for level-2 implementations. // #undef GENFRONT #define GENFRONT( opname, varname ) \ \ GENARRAY_FPA( PASTECH2(opname,_unb,_vft), \ varname ); \ \ PASTECH2(opname,_unb,_vft) \ PASTEMAC(varname,_qfp)( num_t dt ) \ { \ return PASTECH(varname,_fpa)[ dt ]; \ } GENFRONT( gemv, gemv_unb_var1 ) GENFRONT( gemv, gemv_unb_var2 ) GENFRONT( gemv, gemv_unf_var1 ) GENFRONT( gemv, gemv_unf_var2 ) GENFRONT( ger, ger_unb_var1 ) GENFRONT( ger, ger_unb_var2 ) GENFRONT( hemv, hemv_unb_var1 ) GENFRONT( hemv, hemv_unb_var2 ) GENFRONT( hemv, hemv_unb_var3 ) GENFRONT( hemv, hemv_unb_var4 ) GENFRONT( hemv, hemv_unf_var1 ) GENFRONT( hemv, hemv_unf_var3 ) GENFRONT( hemv, hemv_unf_var1a ) GENFRONT( hemv, hemv_unf_var3a ) GENFRONT( her, her_unb_var1 ) GENFRONT( her, her_unb_var2 ) GENFRONT( her2, her2_unb_var1 ) GENFRONT( her2, her2_unb_var2 ) GENFRONT( her2, her2_unb_var3 ) GENFRONT( her2, her2_unb_var4 ) GENFRONT( her2, her2_unf_var1 ) GENFRONT( her2, her2_unf_var4 ) GENFRONT( trmv, trmv_unb_var1 ) GENFRONT( trmv, trmv_unb_var2 ) GENFRONT( trmv, trmv_unf_var1 ) GENFRONT( trmv, trmv_unf_var2 ) GENFRONT( trsv, trsv_unb_var1 ) GENFRONT( trsv, trsv_unb_var2 ) GENFRONT( trsv, trsv_unf_var1 ) GENFRONT( trsv, trsv_unf_var2 ) blis-0.9.0/frame/2/bli_l2_fpa.h000066400000000000000000000061311422157504600160550ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype function pointer query interface. // #undef GENPROT #define GENPROT( opname ) \ \ PASTECH2(opname,BLIS_TAPI_EX_SUF,_vft) \ PASTEMAC2(opname,BLIS_TAPI_EX_SUF,_qfp)( num_t dt ); GENPROT( gemv ) GENPROT( ger ) GENPROT( hemv ) GENPROT( symv ) GENPROT( her ) GENPROT( syr ) GENPROT( her2 ) GENPROT( syr2 ) GENPROT( trmv ) GENPROT( trsv ) // // Prototype function pointer query interfaces for level-2 implementations. // #undef GENPROT #define GENPROT( opname, varname ) \ \ PASTECH2(opname,_unb,_vft) \ PASTEMAC(varname,_qfp)( num_t dt ); GENPROT( gemv, gemv_unb_var1 ) GENPROT( gemv, gemv_unb_var2 ) GENPROT( gemv, gemv_unf_var1 ) GENPROT( gemv, gemv_unf_var2 ) GENPROT( ger, ger_unb_var1 ) GENPROT( ger, ger_unb_var2 ) GENPROT( hemv, hemv_unb_var1 ) GENPROT( hemv, hemv_unb_var2 ) GENPROT( hemv, hemv_unb_var3 ) GENPROT( hemv, hemv_unb_var4 ) GENPROT( hemv, hemv_unf_var1 ) GENPROT( hemv, hemv_unf_var3 ) GENPROT( hemv, hemv_unf_var1a ) GENPROT( hemv, hemv_unf_var3a ) GENPROT( her, her_unb_var1 ) GENPROT( her, her_unb_var2 ) GENPROT( her2, her2_unb_var1 ) GENPROT( her2, her2_unb_var2 ) GENPROT( her2, her2_unb_var3 ) GENPROT( her2, her2_unb_var4 ) GENPROT( her2, her2_unf_var1 ) GENPROT( her2, her2_unf_var4 ) GENPROT( trmv, trmv_unb_var1 ) GENPROT( trmv, trmv_unb_var2 ) GENPROT( trmv, trmv_unf_var1 ) GENPROT( trmv, trmv_unf_var2 ) GENPROT( trsv, trsv_unb_var1 ) GENPROT( trsv, trsv_unb_var2 ) GENPROT( trsv, trsv_unf_var1 ) GENPROT( trsv, trsv_unf_var2 ) blis-0.9.0/frame/2/bli_l2_ft.h000066400000000000000000000111261422157504600157200ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // -- Level-2 function types --------------------------------------------------- // // gemv #undef GENTDEF #define GENTDEF( ctype, ch, opname, tsuf ) \ \ typedef void (*PASTECH3(ch,opname,EX_SUF,tsuf)) \ ( \ trans_t transa, \ conj_t conjx, \ dim_t m, \ dim_t n, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* x, inc_t incx, \ ctype* beta, \ ctype* y, inc_t incy \ BLIS_TAPI_EX_PARAMS \ ); INSERT_GENTDEF( gemv ) // ger #undef GENTDEF #define GENTDEF( ctype, ch, opname, tsuf ) \ \ typedef void (*PASTECH3(ch,opname,EX_SUF,tsuf)) \ ( \ conj_t conjx, \ conj_t conjy, \ dim_t m, \ dim_t n, \ ctype* alpha, \ ctype* x, inc_t incx, \ ctype* y, inc_t incy, \ ctype* a, inc_t rs_a, inc_t cs_a \ BLIS_TAPI_EX_PARAMS \ ); INSERT_GENTDEF( ger ) // hemv, symv #undef GENTDEF #define GENTDEF( ctype, ch, opname, tsuf ) \ \ typedef void (*PASTECH3(ch,opname,EX_SUF,tsuf)) \ ( \ uplo_t uploa, \ conj_t conja, \ conj_t conjx, \ dim_t m, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* x, inc_t incx, \ ctype* beta, \ ctype* y, inc_t incy \ BLIS_TAPI_EX_PARAMS \ ); INSERT_GENTDEF( hemv ) INSERT_GENTDEF( symv ) // her #undef GENTDEFR #define GENTDEFR( ctype, ctype_r, ch, chr, opname, tsuf ) \ \ typedef void (*PASTECH3(ch,opname,EX_SUF,tsuf)) \ ( \ uplo_t uploa, \ conj_t conjx, \ dim_t m, \ ctype_r* alpha, \ ctype* x, inc_t incx, \ ctype* a, inc_t rs_a, inc_t cs_a \ BLIS_TAPI_EX_PARAMS \ ); INSERT_GENTDEFR( her ) // syr #undef GENTDEF #define GENTDEF( ctype, ch, opname, tsuf ) \ \ typedef void (*PASTECH3(ch,opname,EX_SUF,tsuf)) \ ( \ uplo_t uploa, \ conj_t conjx, \ dim_t m, \ ctype* alpha, \ ctype* x, inc_t incx, \ ctype* a, inc_t rs_a, inc_t cs_a \ BLIS_TAPI_EX_PARAMS \ ); INSERT_GENTDEF( syr ) // her2, syr2 #undef GENTDEF #define GENTDEF( ctype, ch, opname, tsuf ) \ \ typedef void (*PASTECH3(ch,opname,EX_SUF,tsuf)) \ ( \ uplo_t uploa, \ conj_t conjx, \ conj_t conjy, \ dim_t m, \ ctype* alpha, \ ctype* x, inc_t incx, \ ctype* y, inc_t incy, \ ctype* a, inc_t rs_a, inc_t cs_a \ BLIS_TAPI_EX_PARAMS \ ); INSERT_GENTDEF( her2 ) INSERT_GENTDEF( syr2 ) // trmv, trsv #undef GENTDEF #define GENTDEF( ctype, ch, opname, tsuf ) \ \ typedef void (*PASTECH3(ch,opname,EX_SUF,tsuf)) \ ( \ uplo_t uploa, \ trans_t transa, \ diag_t diaga, \ dim_t m, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* x, inc_t incx \ BLIS_TAPI_EX_PARAMS \ ); INSERT_GENTDEF( trmv ) INSERT_GENTDEF( trsv ) blis-0.9.0/frame/2/bli_l2_ft_unb.h000066400000000000000000000105371422157504600165710ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_L2_FT_UNB_H #define BLIS_L2_FT_UNB_H // // -- Level-2 function types --------------------------------------------------- // // gemv #undef GENTDEF #define GENTDEF( ctype, ch, opname, tsuf ) \ \ typedef void (*PASTECH3(ch,opname,_unb,tsuf)) \ ( \ trans_t transa, \ conj_t conjx, \ dim_t m, \ dim_t n, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* x, inc_t incx, \ ctype* beta, \ ctype* y, inc_t incy, \ cntx_t* cntx \ ); INSERT_GENTDEF( gemv ) // ger #undef GENTDEF #define GENTDEF( ctype, ch, opname, tsuf ) \ \ typedef void (*PASTECH3(ch,opname,_unb,tsuf)) \ ( \ conj_t conjx, \ conj_t conjy, \ dim_t m, \ dim_t n, \ ctype* alpha, \ ctype* x, inc_t incx, \ ctype* y, inc_t incy, \ ctype* a, inc_t rs_a, inc_t cs_a, \ cntx_t* cntx \ ); INSERT_GENTDEF( ger ) // hemv (and symv) #undef GENTDEF #define GENTDEF( ctype, ch, opname, tsuf ) \ \ typedef void (*PASTECH3(ch,opname,_unb,tsuf)) \ ( \ uplo_t uploa, \ conj_t conja, \ conj_t conjx, \ conj_t conjh, \ dim_t m, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* x, inc_t incx, \ ctype* beta, \ ctype* y, inc_t incy, \ cntx_t* cntx \ ); INSERT_GENTDEF( hemv ) // her (and syr) #undef GENTDEFR #define GENTDEFR( ctype, ctype_r, ch, chr, opname, tsuf ) \ \ typedef void (*PASTECH3(ch,opname,_unb,tsuf)) \ ( \ uplo_t uploa, \ conj_t conjx, \ conj_t conjh, \ dim_t m, \ ctype* alpha, /* complex alpha allows her variants to also perform syr. */ \ ctype* x, inc_t incx, \ ctype* a, inc_t rs_a, inc_t cs_a, \ cntx_t* cntx \ ); INSERT_GENTDEFR( her ) // her2 (and syr2) #undef GENTDEF #define GENTDEF( ctype, ch, opname, tsuf ) \ \ typedef void (*PASTECH3(ch,opname,_unb,tsuf)) \ ( \ uplo_t uploa, \ conj_t conjx, \ conj_t conjy, \ conj_t conjh, \ dim_t m, \ ctype* alpha, \ ctype* x, inc_t incx, \ ctype* y, inc_t incy, \ ctype* a, inc_t rs_a, inc_t cs_a, \ cntx_t* cntx \ ); INSERT_GENTDEF( her2 ) // trmv (and trsv) #undef GENTDEF #define GENTDEF( ctype, ch, opname, tsuf ) \ \ typedef void (*PASTECH3(ch,opname,_unb,tsuf)) \ ( \ uplo_t uploa, \ trans_t transa, \ diag_t diaga, \ dim_t m, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* x, inc_t incx, \ cntx_t* cntx \ ); INSERT_GENTDEF( trmv ) INSERT_GENTDEF( trsv ) #endif blis-0.9.0/frame/2/bli_l2_oapi.c000066400000000000000000000301501422157504600162300ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // Guard the function definitions so that they are only compiled when // #included from files that define the object API macros. #ifdef BLIS_ENABLE_OAPI // // Define object-based interfaces. // #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC(opname,EX_SUF) \ ( \ obj_t* alpha, \ obj_t* a, \ obj_t* x, \ obj_t* beta, \ obj_t* y \ BLIS_OAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_OAPI_EX_DECLS \ \ num_t dt = bli_obj_dt( a ); \ \ trans_t transa = bli_obj_conjtrans_status( a ); \ conj_t conjx = bli_obj_conj_status( x ); \ dim_t m = bli_obj_length( a ); \ dim_t n = bli_obj_width( a ); \ void* buf_a = bli_obj_buffer_at_off( a ); \ inc_t rs_a = bli_obj_row_stride( a ); \ inc_t cs_a = bli_obj_col_stride( a ); \ void* buf_x = bli_obj_buffer_at_off( x ); \ inc_t incx = bli_obj_vector_inc( x ); \ void* buf_y = bli_obj_buffer_at_off( y ); \ inc_t incy = bli_obj_vector_inc( y ); \ \ void* buf_alpha; \ void* buf_beta; \ \ obj_t alpha_local; \ obj_t beta_local; \ \ if ( bli_error_checking_is_enabled() ) \ PASTEMAC(opname,_check)( alpha, a, x, beta, y ); \ \ /* Create local copy-casts of scalars (and apply internal conjugation as needed). */ \ bli_obj_scalar_init_detached_copy_of( dt, BLIS_NO_CONJUGATE, \ alpha, &alpha_local ); \ bli_obj_scalar_init_detached_copy_of( dt, BLIS_NO_CONJUGATE, \ beta, &beta_local ); \ buf_alpha = bli_obj_buffer_for_1x1( dt, &alpha_local ); \ buf_beta = bli_obj_buffer_for_1x1( dt, &beta_local ); \ \ /* Query a type-specific function pointer, except one that uses void* for function arguments instead of typed pointers. */ \ PASTECH2(opname,BLIS_TAPI_EX_SUF,_vft) f = \ PASTEMAC2(opname,BLIS_TAPI_EX_SUF,_qfp)( dt ); \ \ f \ ( \ transa, \ conjx, \ m, \ n, \ buf_alpha, \ buf_a, rs_a, cs_a, \ buf_x, incx, \ buf_beta, \ buf_y, incy, \ cntx, \ rntm \ ); \ } GENFRONT( gemv ) #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC(opname,EX_SUF) \ ( \ obj_t* alpha, \ obj_t* x, \ obj_t* y, \ obj_t* a \ BLIS_OAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_OAPI_EX_DECLS \ \ num_t dt = bli_obj_dt( a ); \ \ conj_t conjx = bli_obj_conj_status( x ); \ conj_t conjy = bli_obj_conj_status( y ); \ dim_t m = bli_obj_length( a ); \ dim_t n = bli_obj_width( a ); \ void* buf_x = bli_obj_buffer_at_off( x ); \ inc_t incx = bli_obj_vector_inc( x ); \ void* buf_y = bli_obj_buffer_at_off( y ); \ inc_t incy = bli_obj_vector_inc( y ); \ void* buf_a = bli_obj_buffer_at_off( a ); \ inc_t rs_a = bli_obj_row_stride( a ); \ inc_t cs_a = bli_obj_col_stride( a ); \ \ void* buf_alpha; \ \ obj_t alpha_local; \ \ if ( bli_error_checking_is_enabled() ) \ PASTEMAC(opname,_check)( alpha, x, y, a ); \ \ /* Create local copy-casts of scalars (and apply internal conjugation as needed). */ \ bli_obj_scalar_init_detached_copy_of( dt, BLIS_NO_CONJUGATE, \ alpha, &alpha_local ); \ buf_alpha = bli_obj_buffer_for_1x1( dt, &alpha_local ); \ \ /* Query a type-specific function pointer, except one that uses void* for function arguments instead of typed pointers. */ \ PASTECH2(opname,BLIS_TAPI_EX_SUF,_vft) f = \ PASTEMAC2(opname,BLIS_TAPI_EX_SUF,_qfp)( dt ); \ \ f \ ( \ conjx, \ conjy, \ m, \ n, \ buf_alpha, \ buf_x, incx, \ buf_y, incy, \ buf_a, rs_a, cs_a, \ cntx, \ rntm \ ); \ } GENFRONT( ger ) #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC(opname,EX_SUF) \ ( \ obj_t* alpha, \ obj_t* a, \ obj_t* x, \ obj_t* beta, \ obj_t* y \ BLIS_OAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_OAPI_EX_DECLS \ \ num_t dt = bli_obj_dt( a ); \ \ uplo_t uploa = bli_obj_uplo( a ); \ conj_t conja = bli_obj_conj_status( a ); \ conj_t conjx = bli_obj_conj_status( x ); \ dim_t m = bli_obj_length( a ); \ void* buf_a = bli_obj_buffer_at_off( a ); \ inc_t rs_a = bli_obj_row_stride( a ); \ inc_t cs_a = bli_obj_col_stride( a ); \ void* buf_x = bli_obj_buffer_at_off( x ); \ inc_t incx = bli_obj_vector_inc( x ); \ void* buf_y = bli_obj_buffer_at_off( y ); \ inc_t incy = bli_obj_vector_inc( y ); \ \ void* buf_alpha; \ void* buf_beta; \ \ obj_t alpha_local; \ obj_t beta_local; \ \ if ( bli_error_checking_is_enabled() ) \ PASTEMAC(opname,_check)( alpha, a, x, beta, y ); \ \ /* Create local copy-casts of scalars (and apply internal conjugation as needed). */ \ bli_obj_scalar_init_detached_copy_of( dt, BLIS_NO_CONJUGATE, \ alpha, &alpha_local ); \ bli_obj_scalar_init_detached_copy_of( dt, BLIS_NO_CONJUGATE, \ beta, &beta_local ); \ buf_alpha = bli_obj_buffer_for_1x1( dt, &alpha_local ); \ buf_beta = bli_obj_buffer_for_1x1( dt, &beta_local ); \ \ /* Query a type-specific function pointer, except one that uses void* for function arguments instead of typed pointers. */ \ PASTECH2(opname,BLIS_TAPI_EX_SUF,_vft) f = \ PASTEMAC2(opname,BLIS_TAPI_EX_SUF,_qfp)( dt ); \ \ f \ ( \ uploa, \ conja, \ conjx, \ m, \ buf_alpha, \ buf_a, rs_a, cs_a, \ buf_x, incx, \ buf_beta, \ buf_y, incy, \ cntx, \ rntm \ ); \ } GENFRONT( hemv ) GENFRONT( symv ) #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC(opname,EX_SUF) \ ( \ obj_t* alpha, \ obj_t* x, \ obj_t* a \ BLIS_OAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_OAPI_EX_DECLS \ \ num_t dt = bli_obj_dt( a ); \ \ uplo_t uploa = bli_obj_uplo( a ); \ conj_t conjx = bli_obj_conj_status( x ); \ dim_t m = bli_obj_length( a ); \ void* buf_x = bli_obj_buffer_at_off( x ); \ inc_t incx = bli_obj_vector_inc( x ); \ void* buf_a = bli_obj_buffer_at_off( a ); \ inc_t rs_a = bli_obj_row_stride( a ); \ inc_t cs_a = bli_obj_col_stride( a ); \ \ void* buf_alpha; \ \ obj_t alpha_local; \ \ if ( bli_error_checking_is_enabled() ) \ PASTEMAC(opname,_check)( alpha, x, a ); \ \ /* Create local copy-casts of scalars (and apply internal conjugation as needed). */ \ bli_obj_scalar_init_detached_copy_of( dt, BLIS_NO_CONJUGATE, \ alpha, &alpha_local ); \ buf_alpha = bli_obj_buffer_for_1x1( dt, &alpha_local ); \ \ /* Query a type-specific function pointer, except one that uses void* for function arguments instead of typed pointers. */ \ PASTECH2(opname,BLIS_TAPI_EX_SUF,_vft) f = \ PASTEMAC2(opname,BLIS_TAPI_EX_SUF,_qfp)( dt ); \ \ f \ ( \ uploa, \ conjx, \ m, \ buf_alpha, \ buf_x, incx, \ buf_a, rs_a, cs_a, \ cntx, \ rntm \ ); \ } GENFRONT( her ) GENFRONT( syr ) #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC(opname,EX_SUF) \ ( \ obj_t* alpha, \ obj_t* x, \ obj_t* y, \ obj_t* a \ BLIS_OAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_OAPI_EX_DECLS \ \ num_t dt = bli_obj_dt( a ); \ \ uplo_t uploa = bli_obj_uplo( a ); \ conj_t conjx = bli_obj_conj_status( x ); \ conj_t conjy = bli_obj_conj_status( y ); \ dim_t m = bli_obj_length( a ); \ void* buf_x = bli_obj_buffer_at_off( x ); \ inc_t incx = bli_obj_vector_inc( x ); \ void* buf_y = bli_obj_buffer_at_off( y ); \ inc_t incy = bli_obj_vector_inc( y ); \ void* buf_a = bli_obj_buffer_at_off( a ); \ inc_t rs_a = bli_obj_row_stride( a ); \ inc_t cs_a = bli_obj_col_stride( a ); \ \ void* buf_alpha; \ \ obj_t alpha_local; \ \ if ( bli_error_checking_is_enabled() ) \ PASTEMAC(opname,_check)( alpha, x, y, a ); \ \ /* Create local copy-casts of scalars (and apply internal conjugation as needed). */ \ bli_obj_scalar_init_detached_copy_of( dt, BLIS_NO_CONJUGATE, \ alpha, &alpha_local ); \ buf_alpha = bli_obj_buffer_for_1x1( dt, &alpha_local ); \ \ /* Query a type-specific function pointer, except one that uses void* for function arguments instead of typed pointers. */ \ PASTECH2(opname,BLIS_TAPI_EX_SUF,_vft) f = \ PASTEMAC2(opname,BLIS_TAPI_EX_SUF,_qfp)( dt ); \ \ f \ ( \ uploa, \ conjx, \ conjy, \ m, \ buf_alpha, \ buf_x, incx, \ buf_y, incy, \ buf_a, rs_a, cs_a, \ cntx, \ rntm \ ); \ } GENFRONT( her2 ) GENFRONT( syr2 ) #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC(opname,EX_SUF) \ ( \ obj_t* alpha, \ obj_t* a, \ obj_t* x \ BLIS_OAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_OAPI_EX_DECLS \ \ num_t dt = bli_obj_dt( a ); \ \ uplo_t uploa = bli_obj_uplo( a ); \ trans_t transa = bli_obj_conjtrans_status( a ); \ diag_t diaga = bli_obj_diag( a ); \ dim_t m = bli_obj_length( a ); \ void* buf_a = bli_obj_buffer_at_off( a ); \ inc_t rs_a = bli_obj_row_stride( a ); \ inc_t cs_a = bli_obj_col_stride( a ); \ void* buf_x = bli_obj_buffer_at_off( x ); \ inc_t incx = bli_obj_vector_inc( x ); \ \ void* buf_alpha; \ \ obj_t alpha_local; \ \ if ( bli_error_checking_is_enabled() ) \ PASTEMAC(opname,_check)( alpha, a, x ); \ \ /* Create local copy-casts of scalars (and apply internal conjugation as needed). */ \ bli_obj_scalar_init_detached_copy_of( dt, BLIS_NO_CONJUGATE, \ alpha, &alpha_local ); \ buf_alpha = bli_obj_buffer_for_1x1( dt, &alpha_local ); \ \ /* Query a type-specific function pointer, except one that uses void* for function arguments instead of typed pointers. */ \ PASTECH2(opname,BLIS_TAPI_EX_SUF,_vft) f = \ PASTEMAC2(opname,BLIS_TAPI_EX_SUF,_qfp)( dt ); \ \ f \ ( \ uploa, \ transa, \ diaga, \ m, \ buf_alpha, \ buf_a, rs_a, cs_a, \ buf_x, incx, \ cntx, \ rntm \ ); \ } GENFRONT( trmv ) GENFRONT( trsv ) #endif blis-0.9.0/frame/2/bli_l2_oapi.h000066400000000000000000000053221422157504600162400ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype object-based interfaces. // #undef GENPROT #define GENPROT( opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC(opname,EX_SUF) \ ( \ obj_t* alpha, \ obj_t* a, \ obj_t* x, \ obj_t* beta, \ obj_t* y \ BLIS_OAPI_EX_PARAMS \ ); GENPROT( gemv ) GENPROT( hemv ) GENPROT( symv ) #undef GENPROT #define GENPROT( opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC(opname,EX_SUF) \ ( \ obj_t* alpha, \ obj_t* x, \ obj_t* y, \ obj_t* a \ BLIS_OAPI_EX_PARAMS \ ); GENPROT( ger ) GENPROT( her2 ) GENPROT( syr2 ) #undef GENPROT #define GENPROT( opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC(opname,EX_SUF) \ ( \ obj_t* alpha, \ obj_t* x, \ obj_t* a \ BLIS_OAPI_EX_PARAMS \ ); GENPROT( her ) GENPROT( syr ) #undef GENPROT #define GENPROT( opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC(opname,EX_SUF) \ ( \ obj_t* alpha, \ obj_t* a, \ obj_t* x \ BLIS_OAPI_EX_PARAMS \ ); GENPROT( trmv ) GENPROT( trsv ) blis-0.9.0/frame/2/bli_l2_oapi_ba.c000066400000000000000000000036671422157504600167070ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // Include cpp macros that instantiate the API definition templates as // omitting expert parameters. #include "bli_oapi_ba.h" // Define the macro protecting the object API definitions. #define BLIS_ENABLE_OAPI // Include the object API definitions here. #include "bli_l2_oapi.c" blis-0.9.0/frame/2/bli_l2_oapi_ex.c000066400000000000000000000036651422157504600167370ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // Include cpp macros that instantiate the API definition templates as // having expert parameters. #include "bli_oapi_ex.h" // Define the macro protecting the object API definitions. #define BLIS_ENABLE_OAPI // Include the object API definitions here. #include "bli_l2_oapi.c" blis-0.9.0/frame/2/bli_l2_tapi.c000066400000000000000000000332531422157504600162440ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // Guard the function definitions so that they are only compiled when // #included from files that define the typed API macros. #ifdef BLIS_ENABLE_TAPI // // Define BLAS-like interfaces with typed operands. // #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, ftname, rvarname, cvarname ) \ \ void PASTEMAC2(ch,opname,EX_SUF) \ ( \ trans_t transa, \ conj_t conjx, \ dim_t m, \ dim_t n, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* x, inc_t incx, \ ctype* beta, \ ctype* y, inc_t incy \ BLIS_TAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_TAPI_EX_DECLS \ \ dim_t m_y, n_x; \ \ /* Determine the dimensions of y and x. */ \ bli_set_dims_with_trans( transa, m, n, &m_y, &n_x ); \ \ /* If y has zero elements, return early. */ \ if ( bli_zero_dim1( m_y ) ) return; \ \ /* Obtain a valid context from the gks if necessary. */ \ if ( cntx == NULL ) cntx = bli_gks_query_cntx(); \ \ /* If x has zero elements, or if alpha is zero, scale y by beta and return early. */ \ if ( bli_zero_dim1( n_x ) || PASTEMAC(ch,eq0)( *alpha ) ) \ { \ PASTEMAC2(ch,scalv,BLIS_TAPI_EX_SUF) \ ( \ BLIS_NO_CONJUGATE, \ m_y, \ beta, \ y, incy, \ cntx, \ NULL \ ); \ return; \ } \ \ /* Declare a void function pointer for the current operation. */ \ PASTECH2(ch,ftname,_unb_ft) f; \ \ /* Choose the underlying implementation. */ \ if ( bli_does_notrans( transa ) ) \ { \ if ( bli_is_row_stored( rs_a, cs_a ) ) f = PASTEMAC(ch,rvarname); \ else /* column or general stored */ f = PASTEMAC(ch,cvarname); \ } \ else /* if ( bli_does_trans( transa ) ) */ \ { \ if ( bli_is_row_stored( rs_a, cs_a ) ) f = PASTEMAC(ch,cvarname); \ else /* column or general stored */ f = PASTEMAC(ch,rvarname); \ } \ \ /* Invoke the variant chosen above, which loops over a level-1v or level-1f kernel to implement the current operation. */ \ f \ ( \ transa, \ conjx, \ m, \ n, \ alpha, \ a, rs_a, cs_a, \ x, incx, \ beta, \ y, incy, \ cntx \ ); \ } INSERT_GENTFUNC_BASIC3( gemv, gemv, gemv_unf_var1, gemv_unf_var2 ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, ftname, rvarname, cvarname ) \ \ void PASTEMAC2(ch,opname,EX_SUF) \ ( \ conj_t conjx, \ conj_t conjy, \ dim_t m, \ dim_t n, \ ctype* alpha, \ ctype* x, inc_t incx, \ ctype* y, inc_t incy, \ ctype* a, inc_t rs_a, inc_t cs_a \ BLIS_TAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_TAPI_EX_DECLS \ \ /* If x or y has zero elements, or if alpha is zero, return early. */ \ if ( bli_zero_dim2( m, n ) || PASTEMAC(ch,eq0)( *alpha ) ) return; \ \ /* Obtain a valid context from the gks if necessary. */ \ if ( cntx == NULL ) cntx = bli_gks_query_cntx(); \ \ /* Declare a void function pointer for the current operation. */ \ PASTECH2(ch,ftname,_unb_ft) f; \ \ /* Choose the underlying implementation. */ \ if ( bli_is_row_stored( rs_a, cs_a ) ) f = PASTEMAC(ch,rvarname); \ else /* column or general stored */ f = PASTEMAC(ch,cvarname); \ \ /* Invoke the variant chosen above, which loops over a level-1v or level-1f kernel to implement the current operation. */ \ f \ ( \ conjx, \ conjy, \ m, \ n, \ alpha, \ x, incx, \ y, incy, \ a, rs_a, cs_a, \ cntx \ ); \ } INSERT_GENTFUNC_BASIC3( ger, ger, ger_unb_var1, ger_unb_var2 ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, ftname, conjh, rvarname, cvarname ) \ \ void PASTEMAC2(ch,opname,EX_SUF) \ ( \ uplo_t uploa, \ conj_t conja, \ conj_t conjx, \ dim_t m, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* x, inc_t incx, \ ctype* beta, \ ctype* y, inc_t incy \ BLIS_TAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_TAPI_EX_DECLS \ \ /* Obtain a valid context from the gks if necessary. */ \ if ( cntx == NULL ) cntx = bli_gks_query_cntx(); \ \ /* If x has zero elements, or if alpha is zero, scale y by beta and return early. */ \ if ( bli_zero_dim1( m ) || PASTEMAC(ch,eq0)( *alpha ) ) \ { \ PASTEMAC2(ch,scalv,BLIS_TAPI_EX_SUF) \ ( \ BLIS_NO_CONJUGATE, \ m, \ beta, \ y, incy, \ cntx, \ NULL \ ); \ return; \ } \ \ /* Declare a void function pointer for the current operation. */ \ PASTECH2(ch,ftname,_unb_ft) f; \ \ /* Choose the underlying implementation. */ \ if ( bli_is_lower( uploa ) ) \ { \ if ( bli_is_row_stored( rs_a, cs_a ) ) f = PASTEMAC(ch,rvarname); \ else /* column or general stored */ f = PASTEMAC(ch,cvarname); \ } \ else /* if ( bli_is_upper( uploa ) ) */ \ { \ if ( bli_is_row_stored( rs_a, cs_a ) ) f = PASTEMAC(ch,cvarname); \ else /* column or general stored */ f = PASTEMAC(ch,rvarname); \ } \ \ /* Invoke the variant chosen above, which loops over a level-1v or level-1f kernel to implement the current operation. */ \ f \ ( \ uploa, \ conja, \ conjx, \ conjh, /* used by variants to distinguish hemv from symv */ \ m, \ alpha, \ a, rs_a, cs_a, \ x, incx, \ beta, \ y, incy, \ cntx \ ); \ } INSERT_GENTFUNC_BASIC4( hemv, hemv, BLIS_CONJUGATE, hemv_unf_var1, hemv_unf_var3 ) INSERT_GENTFUNC_BASIC4( symv, hemv, BLIS_NO_CONJUGATE, hemv_unf_var1, hemv_unf_var3 ) #undef GENTFUNCR #define GENTFUNCR( ctype, ctype_r, ch, chr, opname, ftname, conjh, rvarname, cvarname ) \ \ void PASTEMAC2(ch,opname,EX_SUF) \ ( \ uplo_t uploa, \ conj_t conjx, \ dim_t m, \ ctype_r* alpha, \ ctype* x, inc_t incx, \ ctype* a, inc_t rs_a, inc_t cs_a \ BLIS_TAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_TAPI_EX_DECLS \ \ ctype alpha_local; \ \ /* If x has zero elements, or if alpha is zero, return early. */ \ if ( bli_zero_dim1( m ) || PASTEMAC(chr,eq0)( *alpha ) ) return; \ \ /* Make a local copy of alpha, cast into the complex domain. This allows us to use the same underlying her variants to implement both her and syr operations. */ \ PASTEMAC2(chr,ch,copys)( *alpha, alpha_local ); \ \ /* Obtain a valid context from the gks if necessary. */ \ if ( cntx == NULL ) cntx = bli_gks_query_cntx(); \ \ /* Declare a void function pointer for the current operation. */ \ PASTECH2(ch,ftname,_unb_ft) f; \ \ /* Choose the underlying implementation. */ \ if ( bli_is_lower( uploa ) ) \ { \ if ( bli_is_row_stored( rs_a, cs_a ) ) f = PASTEMAC(ch,rvarname); \ else /* column or general stored */ f = PASTEMAC(ch,cvarname); \ } \ else /* if ( bli_is_upper( uploa ) ) */ \ { \ if ( bli_is_row_stored( rs_a, cs_a ) ) f = PASTEMAC(ch,cvarname); \ else /* column or general stored */ f = PASTEMAC(ch,rvarname); \ } \ \ /* Invoke the variant chosen above, which loops over a level-1v or level-1f kernel to implement the current operation. */ \ f \ ( \ uploa, \ conjx, \ conjh, /* used by variants to distinguish her from syr */ \ m, \ &alpha_local, \ x, incx, \ a, rs_a, cs_a, \ cntx \ ); \ } INSERT_GENTFUNCR_BASIC4( her, her, BLIS_CONJUGATE, her_unb_var1, her_unb_var2 ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, ftname, conjh, rvarname, cvarname ) \ \ void PASTEMAC2(ch,opname,EX_SUF) \ ( \ uplo_t uploa, \ conj_t conjx, \ dim_t m, \ ctype* alpha, \ ctype* x, inc_t incx, \ ctype* a, inc_t rs_a, inc_t cs_a \ BLIS_TAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_TAPI_EX_DECLS \ \ /* If x has zero elements, or if alpha is zero, return early. */ \ if ( bli_zero_dim1( m ) || PASTEMAC(ch,eq0)( *alpha ) ) return; \ \ /* Obtain a valid context from the gks if necessary. */ \ if ( cntx == NULL ) cntx = bli_gks_query_cntx(); \ \ /* Declare a void function pointer for the current operation. */ \ PASTECH2(ch,ftname,_unb_ft) f; \ \ /* Choose the underlying implementation. */ \ if ( bli_is_lower( uploa ) ) \ { \ if ( bli_is_row_stored( rs_a, cs_a ) ) f = PASTEMAC(ch,rvarname); \ else /* column or general stored */ f = PASTEMAC(ch,cvarname); \ } \ else /* if ( bli_is_upper( uploa ) ) */ \ { \ if ( bli_is_row_stored( rs_a, cs_a ) ) f = PASTEMAC(ch,cvarname); \ else /* column or general stored */ f = PASTEMAC(ch,rvarname); \ } \ \ /* Invoke the variant chosen above, which loops over a level-1v or level-1f kernel to implement the current operation. */ \ f \ ( \ uploa, \ conjx, \ conjh, /* used by variants to distinguish her2 from syr2 */ \ m, \ alpha, \ x, incx, \ a, rs_a, cs_a, \ cntx \ ); \ } INSERT_GENTFUNC_BASIC4( syr, her, BLIS_NO_CONJUGATE, her_unb_var1, her_unb_var2 ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, ftname, conjh, rvarname, cvarname ) \ \ void PASTEMAC2(ch,opname,EX_SUF) \ ( \ uplo_t uploa, \ conj_t conjx, \ conj_t conjy, \ dim_t m, \ ctype* alpha, \ ctype* x, inc_t incx, \ ctype* y, inc_t incy, \ ctype* a, inc_t rs_a, inc_t cs_a \ BLIS_TAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_TAPI_EX_DECLS \ \ /* If x has zero elements, or if alpha is zero, return early. */ \ if ( bli_zero_dim1( m ) || PASTEMAC(ch,eq0)( *alpha ) ) return; \ \ /* Obtain a valid context from the gks if necessary. */ \ if ( cntx == NULL ) cntx = bli_gks_query_cntx(); \ \ /* Declare a void function pointer for the current operation. */ \ PASTECH2(ch,ftname,_unb_ft) f; \ \ /* Choose the underlying implementation. */ \ if ( bli_is_lower( uploa ) ) \ { \ if ( bli_is_row_stored( rs_a, cs_a ) ) f = PASTEMAC(ch,rvarname); \ else /* column or general stored */ f = PASTEMAC(ch,cvarname); \ } \ else /* if ( bli_is_upper( uploa ) ) */ \ { \ if ( bli_is_row_stored( rs_a, cs_a ) ) f = PASTEMAC(ch,cvarname); \ else /* column or general stored */ f = PASTEMAC(ch,rvarname); \ } \ \ /* Invoke the variant chosen above, which loops over a level-1v or level-1f kernel to implement the current operation. */ \ f \ ( \ uploa, \ conjx, \ conjy, \ conjh, \ m, \ alpha, \ x, incx, \ y, incy, \ a, rs_a, cs_a, \ cntx \ ); \ } INSERT_GENTFUNC_BASIC4( her2, her2, BLIS_CONJUGATE, her2_unf_var1, her2_unf_var4 ) INSERT_GENTFUNC_BASIC4( syr2, her2, BLIS_NO_CONJUGATE, her2_unf_var1, her2_unf_var4 ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, ftname, rvarname, cvarname ) \ \ void PASTEMAC2(ch,opname,EX_SUF) \ ( \ uplo_t uploa, \ trans_t transa, \ diag_t diaga, \ dim_t m, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* x, inc_t incx \ BLIS_TAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_TAPI_EX_DECLS \ \ /* If x has zero elements, return early. */ \ if ( bli_zero_dim1( m ) ) return; \ \ /* Obtain a valid context from the gks if necessary. */ \ if ( cntx == NULL ) cntx = bli_gks_query_cntx(); \ \ /* If alpha is zero, set x to zero and return early. */ \ if ( PASTEMAC(ch,eq0)( *alpha ) ) \ { \ PASTEMAC2(ch,setv,BLIS_TAPI_EX_SUF) \ ( \ BLIS_NO_CONJUGATE, \ m, \ alpha, \ x, incx, \ cntx, \ NULL \ ); \ return; \ } \ \ /* Declare a void function pointer for the current operation. */ \ PASTECH2(ch,ftname,_unb_ft) f; \ \ /* Choose the underlying implementation. */ \ if ( bli_does_notrans( transa ) ) \ { \ if ( bli_is_row_stored( rs_a, cs_a ) ) f = PASTEMAC(ch,rvarname); \ else /* column or general stored */ f = PASTEMAC(ch,cvarname); \ } \ else /* if ( bli_does_trans( transa ) ) */ \ { \ if ( bli_is_row_stored( rs_a, cs_a ) ) f = PASTEMAC(ch,cvarname); \ else /* column or general stored */ f = PASTEMAC(ch,rvarname); \ } \ \ /* Invoke the variant chosen above, which loops over a level-1v or level-1f kernel to implement the current operation. */ \ f \ ( \ uploa, \ transa, \ diaga, \ m, \ alpha, \ a, rs_a, cs_a, \ x, incx, \ cntx \ ); \ } INSERT_GENTFUNC_BASIC3( trmv, trmv, trmv_unf_var1, trmv_unf_var2 ) INSERT_GENTFUNC_BASIC3( trsv, trmv, trsv_unf_var1, trsv_unf_var2 ) #endif blis-0.9.0/frame/2/bli_l2_tapi.h000066400000000000000000000110651422157504600162460ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype BLAS-like interfaces with typed operands. // #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC2(ch,opname,EX_SUF) \ ( \ trans_t transa, \ conj_t conjx, \ dim_t m, \ dim_t n, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* x, inc_t incx, \ ctype* beta, \ ctype* y, inc_t incy \ BLIS_TAPI_EX_PARAMS \ ); INSERT_GENTPROT_BASIC0( gemv ) #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC2(ch,opname,EX_SUF) \ ( \ conj_t conjx, \ conj_t conjy, \ dim_t m, \ dim_t n, \ ctype* alpha, \ ctype* x, inc_t incx, \ ctype* y, inc_t incy, \ ctype* a, inc_t rs_a, inc_t cs_a \ BLIS_TAPI_EX_PARAMS \ ); INSERT_GENTPROT_BASIC0( ger ) #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC2(ch,opname,EX_SUF) \ ( \ uplo_t uploa, \ conj_t conja, \ conj_t conjx, \ dim_t m, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* x, inc_t incx, \ ctype* beta, \ ctype* y, inc_t incy \ BLIS_TAPI_EX_PARAMS \ ); INSERT_GENTPROT_BASIC0( hemv ) INSERT_GENTPROT_BASIC0( symv ) #undef GENTPROTR #define GENTPROTR( ctype, ctype_r, ch, chr, opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC2(ch,opname,EX_SUF) \ ( \ uplo_t uploa, \ conj_t conjx, \ dim_t m, \ ctype_r* alpha, \ ctype* x, inc_t incx, \ ctype* a, inc_t rs_a, inc_t cs_a \ BLIS_TAPI_EX_PARAMS \ ); INSERT_GENTPROTR_BASIC0( her ) #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC2(ch,opname,EX_SUF) \ ( \ uplo_t uploa, \ conj_t conjx, \ dim_t m, \ ctype* alpha, \ ctype* x, inc_t incx, \ ctype* a, inc_t rs_a, inc_t cs_a \ BLIS_TAPI_EX_PARAMS \ ); INSERT_GENTPROT_BASIC0( syr ) #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC2(ch,opname,EX_SUF) \ ( \ uplo_t uploa, \ conj_t conjx, \ conj_t conjy, \ dim_t m, \ ctype* alpha, \ ctype* x, inc_t incx, \ ctype* y, inc_t incy, \ ctype* a, inc_t rs_a, inc_t cs_a \ BLIS_TAPI_EX_PARAMS \ ); INSERT_GENTPROT_BASIC0( her2 ) INSERT_GENTPROT_BASIC0( syr2 ) #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC2(ch,opname,EX_SUF) \ ( \ uplo_t uploa, \ trans_t transa, \ diag_t diaga, \ dim_t m, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* x, inc_t incx \ BLIS_TAPI_EX_PARAMS \ ); INSERT_GENTPROT_BASIC0( trmv ) INSERT_GENTPROT_BASIC0( trsv ) blis-0.9.0/frame/2/bli_l2_tapi_ba.c000066400000000000000000000036651422157504600167120ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // Include cpp macros that instantiate the API definition templates as // omitting expert parameters. #include "bli_tapi_ba.h" // Define the macro protecting the typed API definitions. #define BLIS_ENABLE_TAPI // Include the typed API definitions here. #include "bli_l2_tapi.c" blis-0.9.0/frame/2/bli_l2_tapi_ex.c000066400000000000000000000036631422157504600167420ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // Include cpp macros that instantiate the API definition templates as // having expert parameters. #include "bli_tapi_ex.h" // Define the macro protecting the typed API definitions. #define BLIS_ENABLE_TAPI // Include the typed API definitions here. #include "bli_l2_tapi.c" blis-0.9.0/frame/2/gemv/000077500000000000000000000000001422157504600146505ustar00rootroot00000000000000blis-0.9.0/frame/2/gemv/amd/000077500000000000000000000000001422157504600154115ustar00rootroot00000000000000blis-0.9.0/frame/2/gemv/amd/bli_gemv_unf_var2_amd.c000066400000000000000000000134651422157504600217750ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2022, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENTFUNC #define GENTFUNC( ctype, ch, varname, scalvsuf, axpyfsuf, fusefac ) \ \ void PASTEMAC(ch,varname) \ ( \ trans_t transa, \ conj_t conjx, \ dim_t m, \ dim_t n, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* x, inc_t incx, \ ctype* beta, \ ctype* y, inc_t incy, \ cntx_t* cntx \ ) \ { \ /*const num_t dt = PASTEMAC(ch,type);*/ \ \ ctype* A1; \ ctype* x1; \ ctype* y1; \ dim_t i; \ dim_t b_fuse, f; \ dim_t n_elem, n_iter; \ inc_t rs_at, cs_at; \ conj_t conja; \ \ bli_set_dims_incs_with_trans( transa, \ m, n, rs_a, cs_a, \ &n_elem, &n_iter, &rs_at, &cs_at ); \ \ conja = bli_extract_conj( transa ); \ \ /* y = beta * y; */ \ /* NOTE: We don't explicitly handle the case where beta == 0 here since that behavior is handled within the scalv kernel itself. */ \ PASTEMAC2(ch,scalv,scalvsuf) \ ( \ BLIS_NO_CONJUGATE, \ n_elem, \ beta, \ y, incy, \ cntx \ ); \ \ /* If alpha == 0, then we are done. */ \ if ( PASTEMAC(ch,eq0)( *alpha ) ) return; \ \ /*PASTECH(ch,axpyf_ker_ft) kfp_af;*/ \ \ /* Query the context for the kernel function pointer and fusing factor. */ \ /*kfp_af = bli_cntx_get_l1f_ker_dt( dt, BLIS_AXPYF_KER, cntx );*/ \ /*b_fuse = bli_cntx_get_blksz_def_dt( dt, BLIS_AF, cntx );*/ \ b_fuse = fusefac; \ \ for ( i = 0; i < n_iter; i += f ) \ { \ f = bli_determine_blocksize_dim_f( i, n_iter, b_fuse ); \ \ A1 = a + (0 )*rs_at + (i )*cs_at; \ x1 = x + (i )*incx; \ y1 = y + (0 )*incy; \ \ /* y = y + alpha * A1 * x1; */ \ /*kfp_af*/ \ PASTEMAC2(ch,axpyf,axpyfsuf) \ ( \ conja, \ conjx, \ n_elem, \ f, \ alpha, \ A1, rs_at, cs_at, \ x1, incx, \ y1, incy, \ cntx \ ); \ } \ } //INSERT_GENTFUNC_BASIC0( gemv_unf_var2 ) GENTFUNC( float, s, gemv_unf_var2, _zen_int10, _zen_int_5, 5 ) GENTFUNC( double, d, gemv_unf_var2, _zen_int10, _zen_int_16x4, 4 ) GENTFUNC( scomplex, c, gemv_unf_var2, _zen_int10, _zen_int_4, 4 ) //GENTFUNC( dcomplex, z, gemv_unf_var2, _zen_int10, _ex, 1 ) #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ trans_t transa, \ conj_t conjx, \ dim_t m, \ dim_t n, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* x, inc_t incx, \ ctype* beta, \ ctype* y, inc_t incy, \ cntx_t* cntx \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ ctype* zero = PASTEMAC(ch,0); \ ctype* A1; \ ctype* x1; \ ctype* y1; \ dim_t i; \ dim_t b_fuse, f; \ dim_t n_elem, n_iter; \ inc_t rs_at, cs_at; \ conj_t conja; \ \ bli_set_dims_incs_with_trans( transa, \ m, n, rs_a, cs_a, \ &n_elem, &n_iter, &rs_at, &cs_at ); \ \ conja = bli_extract_conj( transa ); \ \ /* If beta is zero, use setv. Otherwise, scale by beta. */ \ if ( PASTEMAC(ch,eq0)( *beta ) ) \ { \ /* y = 0; */ \ PASTEMAC2(ch,setv,BLIS_TAPI_EX_SUF) \ ( \ BLIS_NO_CONJUGATE, \ n_elem, \ zero, \ y, incy, \ cntx, \ NULL \ ); \ } \ else \ { \ /* y = beta * y; */ \ PASTEMAC2(ch,scalv,BLIS_TAPI_EX_SUF) \ ( \ BLIS_NO_CONJUGATE, \ n_elem, \ beta, \ y, incy, \ cntx, \ NULL \ ); \ } \ \ PASTECH(ch,axpyf_ker_ft) kfp_af; \ \ /* Query the context for the kernel function pointer and fusing factor. */ \ kfp_af = bli_cntx_get_l1f_ker_dt( dt, BLIS_AXPYF_KER, cntx ); \ b_fuse = bli_cntx_get_blksz_def_dt( dt, BLIS_AF, cntx ); \ \ for ( i = 0; i < n_iter; i += f ) \ { \ f = bli_determine_blocksize_dim_f( i, n_iter, b_fuse ); \ \ A1 = a + (0 )*rs_at + (i )*cs_at; \ x1 = x + (i )*incx; \ y1 = y + (0 )*incy; \ \ /* y = y + alpha * A1 * x1; */ \ kfp_af \ ( \ conja, \ conjx, \ n_elem, \ f, \ alpha, \ A1, rs_at, cs_at, \ x1, incx, \ y1, incy, \ cntx \ ); \ } \ } //INSERT_GENTFUNC_BASIC0( gemv_unf_var2 ) GENTFUNC( dcomplex, z, gemv_unf_var2 ) blis-0.9.0/frame/2/gemv/bli_gemv.h000066400000000000000000000034701422157504600166110ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // NOTE: level-2 control tree code is temporarily disabled. //#include "bli_gemv_cntl.h" //#include "bli_gemv_front.h" //#include "bli_gemv_int.h" #include "bli_gemv_var.h" blis-0.9.0/frame/2/gemv/bli_gemv_unb_var1.c000066400000000000000000000056641422157504600204100ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ trans_t transa, \ conj_t conjx, \ dim_t m, \ dim_t n, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* x, inc_t incx, \ ctype* beta, \ ctype* y, inc_t incy, \ cntx_t* cntx \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ ctype* a1t; \ ctype* x1; \ ctype* psi1; \ dim_t i; \ dim_t n_elem, n_iter; \ inc_t rs_at, cs_at; \ conj_t conja; \ \ bli_set_dims_incs_with_trans( transa, \ m, n, rs_a, cs_a, \ &n_iter, &n_elem, &rs_at, &cs_at ); \ \ conja = bli_extract_conj( transa ); \ \ PASTECH(ch,dotxv_ker_ft) kfp_dv; \ \ /* Query the context for the kernel function pointer. */ \ kfp_dv = bli_cntx_get_l1v_ker_dt( dt, BLIS_DOTXV_KER, cntx ); \ \ for ( i = 0; i < n_iter; ++i ) \ { \ a1t = a + (i )*rs_at + (0 )*cs_at; \ x1 = x + (0 )*incy; \ psi1 = y + (i )*incy; \ \ /* psi1 = beta * psi1 + alpha * a1t * x1; */ \ kfp_dv \ ( \ conja, \ conjx, \ n_elem, \ alpha, \ a1t, cs_at, \ x1, incx, \ beta, \ psi1, \ cntx \ ); \ } \ } INSERT_GENTFUNC_BASIC0( gemv_unb_var1 ) blis-0.9.0/frame/2/gemv/bli_gemv_unb_var2.c000066400000000000000000000067631422157504600204120ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ trans_t transa, \ conj_t conjx, \ dim_t m, \ dim_t n, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* x, inc_t incx, \ ctype* beta, \ ctype* y, inc_t incy, \ cntx_t* cntx \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ ctype* zero = PASTEMAC(ch,0); \ ctype* a1; \ ctype* chi1; \ ctype* y1; \ ctype alpha_chi1; \ dim_t i; \ dim_t n_elem, n_iter; \ inc_t rs_at, cs_at; \ conj_t conja; \ \ bli_set_dims_incs_with_trans( transa, \ m, n, rs_a, cs_a, \ &n_elem, &n_iter, &rs_at, &cs_at ); \ \ conja = bli_extract_conj( transa ); \ \ /* If beta is zero, use setv. Otherwise, scale by beta. */ \ if ( PASTEMAC(ch,eq0)( *beta ) ) \ { \ /* y = 0; */ \ PASTEMAC2(ch,setv,BLIS_TAPI_EX_SUF) \ ( \ BLIS_NO_CONJUGATE, \ n_elem, \ zero, \ y, incy, \ cntx, \ NULL \ ); \ } \ else \ { \ /* y = beta * y; */ \ PASTEMAC2(ch,scalv,BLIS_TAPI_EX_SUF) \ ( \ BLIS_NO_CONJUGATE, \ n_elem, \ beta, \ y, incy, \ cntx, \ NULL \ ); \ } \ \ PASTECH(ch,axpyv_ker_ft) kfp_av; \ \ /* Query the context for the kernel function pointer. */ \ kfp_av = bli_cntx_get_l1v_ker_dt( dt, BLIS_AXPYV_KER, cntx ); \ \ for ( i = 0; i < n_iter; ++i ) \ { \ a1 = a + (0 )*rs_at + (i )*cs_at; \ chi1 = x + (i )*incx; \ y1 = y + (0 )*incy; \ \ /* y = y + alpha * chi1 * a1; */ \ PASTEMAC(ch,copycjs)( conjx, *chi1, alpha_chi1 ); \ PASTEMAC(ch,scals)( *alpha, alpha_chi1 ); \ \ kfp_av \ ( \ conja, \ n_elem, \ &alpha_chi1, \ a1, rs_at, \ y1, incy, \ cntx \ ); \ } \ } INSERT_GENTFUNC_BASIC0( gemv_unb_var2 ) blis-0.9.0/frame/2/gemv/bli_gemv_unf_var1.c000066400000000000000000000061451422157504600204070ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ trans_t transa, \ conj_t conjx, \ dim_t m, \ dim_t n, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* x, inc_t incx, \ ctype* beta, \ ctype* y, inc_t incy, \ cntx_t* cntx \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ ctype* A1; \ ctype* x1; \ ctype* y1; \ dim_t i; \ dim_t b_fuse, f; \ dim_t n_elem, n_iter; \ inc_t rs_at, cs_at; \ conj_t conja; \ \ bli_set_dims_incs_with_trans( transa, \ m, n, rs_a, cs_a, \ &n_iter, &n_elem, &rs_at, &cs_at ); \ \ conja = bli_extract_conj( transa ); \ \ PASTECH(ch,dotxf_ker_ft) kfp_df; \ \ /* Query the context for the kernel function pointer and fusing factor. */ \ kfp_df = bli_cntx_get_l1f_ker_dt( dt, BLIS_DOTXF_KER, cntx ); \ b_fuse = bli_cntx_get_blksz_def_dt( dt, BLIS_DF, cntx ); \ \ for ( i = 0; i < n_iter; i += f ) \ { \ f = bli_determine_blocksize_dim_f( i, n_iter, b_fuse ); \ \ A1 = a + (i )*rs_at + (0 )*cs_at; \ x1 = x + (0 )*incy; \ y1 = y + (i )*incy; \ \ /* y1 = beta * y1 + alpha * A1 * x; */ \ kfp_df \ ( \ conja, \ conjx, \ n_elem, \ f, \ alpha, \ A1, cs_at, rs_at, \ x1, incx, \ beta, \ y1, incy, \ cntx \ ); \ \ } \ } INSERT_GENTFUNC_BASIC0( gemv_unf_var1 ) blis-0.9.0/frame/2/gemv/bli_gemv_unf_var2.c000066400000000000000000000070711422157504600204070ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ trans_t transa, \ conj_t conjx, \ dim_t m, \ dim_t n, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* x, inc_t incx, \ ctype* beta, \ ctype* y, inc_t incy, \ cntx_t* cntx \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ ctype* zero = PASTEMAC(ch,0); \ ctype* A1; \ ctype* x1; \ ctype* y1; \ dim_t i; \ dim_t b_fuse, f; \ dim_t n_elem, n_iter; \ inc_t rs_at, cs_at; \ conj_t conja; \ \ bli_set_dims_incs_with_trans( transa, \ m, n, rs_a, cs_a, \ &n_elem, &n_iter, &rs_at, &cs_at ); \ \ conja = bli_extract_conj( transa ); \ \ /* If beta is zero, use setv. Otherwise, scale by beta. */ \ if ( PASTEMAC(ch,eq0)( *beta ) ) \ { \ /* y = 0; */ \ PASTEMAC2(ch,setv,BLIS_TAPI_EX_SUF) \ ( \ BLIS_NO_CONJUGATE, \ n_elem, \ zero, \ y, incy, \ cntx, \ NULL \ ); \ } \ else \ { \ /* y = beta * y; */ \ PASTEMAC2(ch,scalv,BLIS_TAPI_EX_SUF) \ ( \ BLIS_NO_CONJUGATE, \ n_elem, \ beta, \ y, incy, \ cntx, \ NULL \ ); \ } \ \ PASTECH(ch,axpyf_ker_ft) kfp_af; \ \ /* Query the context for the kernel function pointer and fusing factor. */ \ kfp_af = bli_cntx_get_l1f_ker_dt( dt, BLIS_AXPYF_KER, cntx ); \ b_fuse = bli_cntx_get_blksz_def_dt( dt, BLIS_AF, cntx ); \ \ for ( i = 0; i < n_iter; i += f ) \ { \ f = bli_determine_blocksize_dim_f( i, n_iter, b_fuse ); \ \ A1 = a + (0 )*rs_at + (i )*cs_at; \ x1 = x + (i )*incx; \ y1 = y + (0 )*incy; \ \ /* y = y + alpha * A1 * x1; */ \ kfp_af \ ( \ conja, \ conjx, \ n_elem, \ f, \ alpha, \ A1, rs_at, cs_at, \ x1, incx, \ y1, incy, \ cntx \ ); \ } \ } INSERT_GENTFUNC_BASIC0( gemv_unf_var2 ) blis-0.9.0/frame/2/gemv/bli_gemv_var.h000066400000000000000000000052301422157504600174550ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype object-based interfaces. // #undef GENPROT #define GENPROT( opname ) \ \ void PASTEMAC0(opname) \ ( \ obj_t* alpha, \ obj_t* a, \ obj_t* x, \ obj_t* beta, \ obj_t* y, \ cntx_t* cntx, \ cntl_t* cntl \ ); GENPROT( gemv_blk_var1 ) GENPROT( gemv_blk_var2 ) GENPROT( gemv_unb_var1 ) GENPROT( gemv_unb_var2 ) GENPROT( gemv_unf_var1 ) GENPROT( gemv_unf_var2 ) // // Prototype BLAS-like interfaces with typed operands. // #undef GENTPROT #define GENTPROT( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ trans_t transa, \ conj_t conjx, \ dim_t m, \ dim_t n, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* x, inc_t incx, \ ctype* beta, \ ctype* y, inc_t incy, \ cntx_t* cntx \ ); INSERT_GENTPROT_BASIC0( gemv_unb_var1 ) INSERT_GENTPROT_BASIC0( gemv_unb_var2 ) INSERT_GENTPROT_BASIC0( gemv_unf_var1 ) INSERT_GENTPROT_BASIC0( gemv_unf_var2 ) blis-0.9.0/frame/2/gemv/bli_gemv_var_oapi.c000066400000000000000000000062001422157504600204560ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENFRONT #define GENFRONT( opname, varname ) \ \ void PASTEMAC0(varname) \ ( \ obj_t* alpha, \ obj_t* a, \ obj_t* x, \ obj_t* beta, \ obj_t* y, \ cntx_t* cntx, \ cntl_t* cntl \ ) \ { \ bli_init_once(); \ \ num_t dt = bli_obj_dt( a ); \ \ trans_t transa = bli_obj_conjtrans_status( a ); \ conj_t conjx = bli_obj_conj_status( x ); \ \ dim_t m = bli_obj_length( a ); \ dim_t n = bli_obj_width( a ); \ \ void* buf_a = bli_obj_buffer_at_off( a ); \ inc_t rs_a = bli_obj_row_stride( a ); \ inc_t cs_a = bli_obj_col_stride( a ); \ \ void* buf_x = bli_obj_buffer_at_off( x ); \ inc_t incx = bli_obj_vector_inc( x ); \ \ void* buf_y = bli_obj_buffer_at_off( y ); \ inc_t incy = bli_obj_vector_inc( y ); \ \ void* buf_alpha = bli_obj_buffer_for_1x1( dt, alpha ); \ void* buf_beta = bli_obj_buffer_for_1x1( dt, beta ); \ \ /* Query a type-specific function pointer, except one that uses void* for function arguments instead of typed pointers. */ \ PASTECH2(opname,_unb,_vft) f = \ PASTEMAC(varname,_qfp)( dt ); \ \ f \ ( \ transa, \ conjx, \ m, \ n, \ buf_alpha, \ buf_a, rs_a, cs_a, \ buf_x, incx, \ buf_beta, \ buf_y, incy, \ cntx \ ); \ } \ GENFRONT( gemv, gemv_unb_var1 ) GENFRONT( gemv, gemv_unb_var2 ) GENFRONT( gemv, gemv_unf_var1 ) GENFRONT( gemv, gemv_unf_var2 ) blis-0.9.0/frame/2/gemv/bli_gemv_var_oapi.c.prev000066400000000000000000000062061422157504600214370ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENFRONT #define GENFRONT( ftname, opname ) \ \ /*static gemv_vft GENARRAY(ftypes,gemv_unb_var1);*/ \ static GENARRAY_VFP(ftname,opname); \ \ void PASTEMAC0(opname) \ ( \ obj_t* alpha, \ obj_t* a, \ obj_t* x, \ obj_t* beta, \ obj_t* y, \ cntx_t* cntx, \ gemv_t* cntl \ ) \ { \ num_t dt = bli_obj_dt( a ); \ \ trans_t transa = bli_obj_conjtrans_status( a ); \ conj_t conjx = bli_obj_conj_status( x ); \ \ dim_t m = bli_obj_length( a ); \ dim_t n = bli_obj_width( a ); \ \ void* buf_a = bli_obj_buffer_at_off( a ); \ inc_t rs_a = bli_obj_row_stride( a ); \ inc_t cs_a = bli_obj_col_stride( a ); \ \ void* buf_x = bli_obj_buffer_at_off( x ); \ inc_t incx = bli_obj_vector_inc( x ); \ \ void* buf_y = bli_obj_buffer_at_off( y ); \ inc_t incy = bli_obj_vector_inc( y ); \ \ void* buf_alpha = bli_obj_buffer_for_1x1( dt, alpha ); \ void* buf_beta = bli_obj_buffer_for_1x1( dt, beta ); \ \ PASTECH(ftname,_vft) f = PASTECH(opname,_vfp)[dt]; \ \ /* Invoke the void pointer-based function for the given datatype. */ \ f( \ transa, \ conjx, \ m, \ n, \ buf_alpha, \ buf_a, rs_a, cs_a, \ buf_x, incx, \ buf_beta, \ buf_y, incy, \ cntx \ ); \ } \ GENFRONT( gemv, gemv_unb_var1 ) GENFRONT( gemv, gemv_unb_var2 ) GENFRONT( gemv, gemv_unf_var1 ) GENFRONT( gemv, gemv_unf_var2 ) blis-0.9.0/frame/2/gemv/other/000077500000000000000000000000001422157504600157715ustar00rootroot00000000000000blis-0.9.0/frame/2/gemv/other/bli_gemv_blk_var1.c000066400000000000000000000074061422157504600215110ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_gemv_blk_var1( obj_t* alpha, obj_t* a, obj_t* x, obj_t* beta, obj_t* y, cntx_t* cntx, gemv_t* cntl ) { obj_t a1, a1_pack; obj_t y1, y1_pack; dim_t m_trans; dim_t i; dim_t b_alg; // Initialize objects for packing. bli_obj_init_pack( &a1_pack ); bli_obj_init_pack( &y1_pack ); // Query dimension in partitioning direction. m_trans = bli_obj_length_after_trans( a ); // Partition along the m dimension. for ( i = 0; i < m_trans; i += b_alg ) { // Determine the current algorithmic blocksize. b_alg = bli_determine_blocksize_f( i, m_trans, a, bli_cntl_bszid( cntl ), cntx ); // Acquire partitions for A1 and y1. bli_acquire_mpart_t2b( BLIS_SUBPART1, i, b_alg, a, &a1 ); bli_acquire_vpart_f2b( BLIS_SUBPART1, i, b_alg, y, &y1 ); // Initialize objects for packing A1 and y1 (if needed). bli_packm_init( &a1, &a1_pack, cntx, bli_cntl_sub_packm_a( cntl ) ); bli_packv_init( &y1, &y1_pack, cntx, bli_cntl_sub_packv_y( cntl ) ); // Copy/pack A1, y1 (if needed). bli_packm_int( &a1, &a1_pack, cntx, bli_cntl_sub_packm_a( cntl ), &BLIS_PACKM_SINGLE_THREADED ); bli_packv_int( &y1, &y1_pack, cntx, bli_cntl_sub_packv_y( cntl ) ); // y1 = beta * y1 + alpha * A1 * x; bli_gemv_int( BLIS_NO_TRANSPOSE, BLIS_NO_CONJUGATE, alpha, &a1_pack, x, beta, &y1_pack, cntx, bli_cntl_sub_gemv( cntl ) ); // Copy/unpack y1 (if y1 was packed). bli_unpackv_int( &y1_pack, &y1, cntx, bli_cntl_sub_unpackv_y( cntl ) ); } // If any packing buffers were acquired within packm, release them back // to the memory manager. bli_packm_release( &a1_pack, bli_cntl_sub_packm_a( cntl ) ); bli_packv_release( &y1_pack, bli_cntl_sub_packv_y( cntl ) ); } blis-0.9.0/frame/2/gemv/other/bli_gemv_blk_var2.c000066400000000000000000000074011422157504600215050ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_gemv_blk_var2( obj_t* alpha, obj_t* a, obj_t* x, obj_t* beta, obj_t* y, cntx_t* cntx, gemv_t* cntl ) { obj_t a1, a1_pack; obj_t x1, x1_pack; dim_t n_trans; dim_t i; dim_t b_alg; // Initialize objects for packing. bli_obj_init_pack( &a1_pack ); bli_obj_init_pack( &x1_pack ); // Query dimension in partitioning direction. n_trans = bli_obj_width_after_trans( a ); // y = beta * y; bli_scalv_int( beta, y, cntx, bli_cntl_sub_scalv( cntl ) ); // Partition along the "k" dimension (n dimension of A). for ( i = 0; i < n_trans; i += b_alg ) { // Determine the current algorithmic blocksize. b_alg = bli_determine_blocksize_f( i, n_trans, a, bli_cntl_bszid( cntl ), cntx ); // Acquire partitions for A1 and x1. bli_acquire_mpart_l2r( BLIS_SUBPART1, i, b_alg, a, &a1 ); bli_acquire_vpart_f2b( BLIS_SUBPART1, i, b_alg, x, &x1 ); // Initialize objects for packing A1 and x1 (if needed). bli_packm_init( &a1, &a1_pack, cntx, bli_cntl_sub_packm_a( cntl ) ); bli_packv_init( &x1, &x1_pack, cntx, bli_cntl_sub_packv_x( cntl ) ); // Copy/pack A1, x1 (if needed). bli_packm_int( &a1, &a1_pack, cntx, bli_cntl_sub_packm_a( cntl ), &BLIS_PACKM_SINGLE_THREADED ); bli_packv_int( &x1, &x1_pack, cntx, bli_cntl_sub_packv_x( cntl ) ); // y = y + alpha * A1 * x1; bli_gemv_int( BLIS_NO_TRANSPOSE, BLIS_NO_CONJUGATE, alpha, &a1_pack, &x1_pack, &BLIS_ONE, y, cntx, bli_cntl_sub_gemv( cntl ) ); } // If any packing buffers were acquired within packm, release them back // to the memory manager. bli_packm_release( &a1_pack, bli_cntl_sub_packm_a( cntl ) ); bli_packv_release( &x1_pack, bli_cntl_sub_packv_x( cntl ) ); } blis-0.9.0/frame/2/gemv/other/bli_gemv_cntl.c000066400000000000000000000205241422157504600207440ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" extern scalv_t* scalv_cntl; extern packm_t* packm_cntl; extern packv_t* packv_cntl; extern unpackv_t* unpackv_cntl; gemv_t* gemv_cntl_bs_ke_dot = NULL; gemv_t* gemv_cntl_bs_ke_axpy = NULL; gemv_t* gemv_cntl_rp_bs_dot = NULL; gemv_t* gemv_cntl_rp_bs_axpy = NULL; gemv_t* gemv_cntl_cp_bs_dot = NULL; gemv_t* gemv_cntl_cp_bs_axpy = NULL; gemv_t* gemv_cntl_ge_dot = NULL; gemv_t* gemv_cntl_ge_axpy = NULL; void bli_gemv_cntl_init() { // Create control trees for the lowest-level kernels. These trees induce // operations on (persumably) relatively small block-subvector problems. gemv_cntl_bs_ke_dot = bli_gemv_cntl_obj_create( BLIS_UNB_FUSED, BLIS_VARIANT1, 0, NULL, NULL, NULL, NULL, NULL, NULL ); gemv_cntl_bs_ke_axpy = bli_gemv_cntl_obj_create( BLIS_UNB_FUSED, BLIS_VARIANT2, 0, NULL, NULL, NULL, NULL, NULL, NULL ); // Create control trees for problems with relatively small m dimension // (ie: where trans(A) is a row panel problem). gemv_cntl_rp_bs_dot = bli_gemv_cntl_obj_create( BLIS_BLOCKED, BLIS_VARIANT2, BLIS_N2, scalv_cntl, // scale y up-front packm_cntl, // pack A1 (if needed) packv_cntl, // pack x1 (if needed) NULL, // y is not partitioned in var2 gemv_cntl_bs_ke_dot, NULL ); // y is not partitioned in var2 gemv_cntl_rp_bs_axpy = bli_gemv_cntl_obj_create( BLIS_BLOCKED, BLIS_VARIANT2, BLIS_N2, scalv_cntl, // scale y up-front packm_cntl, // pack A1 (if needed) packv_cntl, // pack x1 (if needed) NULL, // y is not partitioned in var2 gemv_cntl_bs_ke_axpy, NULL ); // y is not partitioned in var2 // Create control trees for problems with relatively small n dimension // (ie: where trans(A) is a column panel problem). gemv_cntl_cp_bs_dot = bli_gemv_cntl_obj_create( BLIS_BLOCKED, BLIS_VARIANT1, BLIS_M2, NULL, // no scaling in blk_var1 packm_cntl, // pack A1 (if needed) NULL, // x is not partitioned in var1 packv_cntl, // pack y1 (if needed) gemv_cntl_bs_ke_dot, unpackv_cntl ); // unpack y1 (if packed) gemv_cntl_cp_bs_axpy = bli_gemv_cntl_obj_create( BLIS_BLOCKED, BLIS_VARIANT1, BLIS_M2, NULL, // no scaling in blk_var1 packm_cntl, // pack A1 (if needed) NULL, // x is not partitioned in var1 packv_cntl, // pack y1 (if needed) gemv_cntl_bs_ke_axpy, unpackv_cntl ); // unpack y1 (if packed) // Create control trees for generally large problems. Here, we choose a // variant that partitions subproblems into row panels. gemv_cntl_ge_dot = bli_gemv_cntl_obj_create( BLIS_BLOCKED, BLIS_VARIANT1, BLIS_M2, NULL, // no scaling in blk_var1 NULL, // do not pack A1 NULL, // x is not partitioned in var1 packv_cntl, // pack y1 (if needed) gemv_cntl_rp_bs_dot, unpackv_cntl ); // unpack y1 (if packed) gemv_cntl_ge_axpy = bli_gemv_cntl_obj_create( BLIS_BLOCKED, BLIS_VARIANT1, BLIS_M2, NULL, // no scaling in blk_var1 NULL, // do not pack A1 NULL, // x is not partitioned in var1 packv_cntl, // pack y1 (if needed) gemv_cntl_rp_bs_axpy, unpackv_cntl ); // unpack y1 (if packed) } void bli_gemv_cntl_finalize() { bli_cntl_free_node( gemv_cntl_bs_ke_dot ); bli_cntl_free_node( gemv_cntl_bs_ke_axpy ); bli_cntl_free_node( gemv_cntl_rp_bs_dot ); bli_cntl_free_node( gemv_cntl_rp_bs_axpy ); bli_cntl_free_node( gemv_cntl_cp_bs_dot ); bli_cntl_free_node( gemv_cntl_cp_bs_axpy ); bli_cntl_free_node( gemv_cntl_ge_dot ); bli_cntl_free_node( gemv_cntl_ge_axpy ); } gemv_t* bli_gemv_cntl_obj_create( impl_t impl_type, varnum_t var_num, bszid_t bszid, scalv_t* sub_scalv, packm_t* sub_packm_a, packv_t* sub_packv_x, packv_t* sub_packv_y, gemv_t* sub_gemv, unpackv_t* sub_unpackv_y ) { gemv_t* cntl; cntl = ( gemv_t* ) bli_malloc_intl( sizeof(gemv_t) ); cntl->impl_type = impl_type; cntl->var_num = var_num; cntl->bszid = bszid; cntl->sub_scalv = sub_scalv; cntl->sub_packm_a = sub_packm_a; cntl->sub_packv_x = sub_packv_x; cntl->sub_packv_y = sub_packv_y; cntl->sub_gemv = sub_gemv; cntl->sub_unpackv_y = sub_unpackv_y; return cntl; } void bli_gemv_cntl_obj_init( gemv_t* cntl, impl_t impl_type, varnum_t var_num, bszid_t bszid, scalv_t* sub_scalv, packm_t* sub_packm_a, packv_t* sub_packv_x, packv_t* sub_packv_y, gemv_t* sub_gemv, unpackv_t* sub_unpackv_y ) { cntl->impl_type = impl_type; cntl->var_num = var_num; cntl->bszid = bszid; cntl->sub_scalv = sub_scalv; cntl->sub_packm_a = sub_packm_a; cntl->sub_packv_x = sub_packv_x; cntl->sub_packv_y = sub_packv_y; cntl->sub_gemv = sub_gemv; cntl->sub_unpackv_y = sub_unpackv_y; } blis-0.9.0/frame/2/gemv/other/bli_gemv_cntl.h000066400000000000000000000066721422157504600207610ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ struct gemv_s { impl_t impl_type; varnum_t var_num; bszid_t bszid; struct scalv_s* sub_scalv; struct packm_s* sub_packm_a; struct packv_s* sub_packv_x; struct packv_s* sub_packv_y; struct gemv_s* sub_gemv; struct unpackv_s* sub_unpackv_y; }; typedef struct gemv_s gemv_t; #define bli_cntl_sub_gemv( cntl ) cntl->sub_gemv #define bli_cntl_sub_gemv_rp( cntl ) cntl->sub_gemv_rp #define bli_cntl_sub_gemv_cp( cntl ) cntl->sub_gemv_cp #define bli_cntl_sub_gemv_n_rp( cntl ) cntl->sub_gemv_n_rp #define bli_cntl_sub_gemv_n_cp( cntl ) cntl->sub_gemv_n_cp #define bli_cntl_sub_gemv_t_rp( cntl ) cntl->sub_gemv_t_rp #define bli_cntl_sub_gemv_t_cp( cntl ) cntl->sub_gemv_t_cp void bli_gemv_cntl_init( void ); void bli_gemv_cntl_finalize( void ); gemv_t* bli_gemv_cntl_obj_create( impl_t impl_type, varnum_t var_num, bszid_t bszid, scalv_t* sub_scalv, packm_t* sub_packm_a, packv_t* sub_packv_x, packv_t* sub_packv_y, gemv_t* sub_gemv, unpackv_t* sub_unpackv_y ); void bli_gemv_cntl_obj_init( gemv_t* cntl, impl_t impl_type, varnum_t var_num, bszid_t bszid, scalv_t* sub_scalv, packm_t* sub_packm_a, packv_t* sub_packv_x, packv_t* sub_packv_y, gemv_t* sub_gemv, unpackv_t* sub_unpackv_y ); blis-0.9.0/frame/2/gemv/other/bli_gemv_front.c000066400000000000000000000166721422157504600211450ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" extern gemv_t* gemv_cntl_bs_ke_axpy; extern gemv_t* gemv_cntl_bs_ke_dot; extern gemv_t* gemv_cntl_ge_axpy; extern gemv_t* gemv_cntl_ge_dot; void bli_gemv_front ( obj_t* alpha, obj_t* a, obj_t* x, obj_t* beta, obj_t* y, cntx_t* cntx ) { gemv_t* gemv_cntl; num_t dt_targ_a; num_t dt_targ_x; num_t dt_targ_y; bool a_has_unit_inc; bool x_has_unit_inc; bool y_has_unit_inc; obj_t alpha_local; obj_t beta_local; num_t dt_alpha; num_t dt_beta; // Check parameters. if ( bli_error_checking_is_enabled() ) bli_gemv_check( alpha, a, x, beta, y ); // Query the target datatypes of each object. dt_targ_a = bli_obj_target_dt( a ); dt_targ_x = bli_obj_target_dt( x ); dt_targ_y = bli_obj_target_dt( y ); // Determine whether each operand is stored with unit stride. a_has_unit_inc = ( bli_obj_is_row_stored( a ) || bli_obj_is_col_stored( a ) ); x_has_unit_inc = ( bli_obj_vector_inc( x ) == 1 ); y_has_unit_inc = ( bli_obj_vector_inc( y ) == 1 ); // Create an object to hold a copy-cast of alpha. Notice that we use // the type union of the target datatypes of a and x to prevent any // unnecessary loss of information during the computation. dt_alpha = bli_dt_union( dt_targ_a, dt_targ_x ); bli_obj_scalar_init_detached_copy_of( dt_alpha, BLIS_NO_CONJUGATE, alpha, &alpha_local ); // Create an object to hold a copy-cast of beta. Notice that we use // the datatype of y. Here's why: If y is real and beta is complex, // there is no reason to keep beta_local in the complex domain since // the complex part of beta*y will not be stored. If y is complex and // beta is real then beta is harmlessly promoted to complex. dt_beta = dt_targ_y; bli_obj_scalar_init_detached_copy_of( dt_beta, BLIS_NO_CONJUGATE, beta, &beta_local ); // If all operands have unit stride, we choose a control tree for calling // the unblocked implementation directly without any blocking. if ( a_has_unit_inc && x_has_unit_inc && y_has_unit_inc ) { // A row-major layout with no transpose is typically best served by // a dot-based implementation (and the same goes for a column-major // layout with a transposition) because it engenders unit stride // within matrix A. Similarly, an axpy-based code is better for // row-major cases with a transpose and column-major without a // transpose. For the general stride case, we mimic that of column- // major storage since that is the format into which we copy/pack. if ( bli_obj_has_notrans( a ) ) { if ( bli_obj_is_row_stored( a ) ) gemv_cntl = gemv_cntl_bs_ke_dot; else gemv_cntl = gemv_cntl_bs_ke_axpy; } else // if ( bli_obj_has_trans( a ) ) { if ( bli_obj_is_row_stored( a ) ) gemv_cntl = gemv_cntl_bs_ke_axpy; else gemv_cntl = gemv_cntl_bs_ke_dot; } } else { // Mark objects with unit stride as already being packed. This prevents // unnecessary packing from happening within the blocked algorithm. if ( a_has_unit_inc ) bli_obj_set_pack_schema( BLIS_PACKED_UNSPEC, a ); if ( x_has_unit_inc ) bli_obj_set_pack_schema( BLIS_PACKED_VECTOR, x ); if ( y_has_unit_inc ) bli_obj_set_pack_schema( BLIS_PACKED_VECTOR, y ); // Here, we make a similar choice as above, except that (1) we look // at storage tilt, and (2) we choose a tree that performs blocking. if ( bli_obj_has_notrans( a ) ) { if ( bli_obj_is_row_tilted( a ) ) gemv_cntl = gemv_cntl_ge_dot; else gemv_cntl = gemv_cntl_ge_axpy; } else // if ( bli_obj_has_trans( a ) ) { if ( bli_obj_is_row_tilted( a ) ) gemv_cntl = gemv_cntl_ge_axpy; else gemv_cntl = gemv_cntl_ge_dot; } } // Invoke the internal back-end with the copy-casts of scalars and the // chosen control tree. bli_gemv_int( BLIS_NO_TRANSPOSE, BLIS_NO_TRANSPOSE, &alpha_local, a, x, &beta_local, y, cntx, gemv_cntl ); } // // Define BLAS-like interfaces with homogeneous-typed operands. // #undef GENTFUNC #define GENTFUNC( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ trans_t transa, \ conj_t conjx, \ dim_t m, \ dim_t n, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* x, inc_t incx, \ ctype* beta, \ ctype* y, inc_t incy, \ cntx_t* cntx \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ obj_t alphao, ao, xo, betao, yo; \ \ dim_t m_a, n_a; \ dim_t m_x; \ dim_t m_y; \ inc_t rs_x, cs_x; \ inc_t rs_y, cs_y; \ \ bli_set_dims_with_trans( BLIS_NO_TRANSPOSE, m, n, &m_a, &n_a ); \ bli_set_dims_with_trans( transa, m, n, &m_y, &m_x ); \ \ rs_x = incx; cs_x = m_x * incx; \ rs_y = incy; cs_y = m_y * incy; \ \ bli_obj_create_1x1_with_attached_buffer( dt, alpha, &alphao ); \ bli_obj_create_1x1_with_attached_buffer( dt, beta, &betao ); \ \ bli_obj_create_with_attached_buffer( dt, m_a, n_a, a, rs_a, cs_a, &ao ); \ bli_obj_create_with_attached_buffer( dt, m_x, 1, x, rs_x, cs_x, &xo ); \ bli_obj_create_with_attached_buffer( dt, m_y, 1, y, rs_y, cs_y, &yo ); \ \ bli_obj_set_conjtrans( transa, &ao ); \ bli_obj_set_conj( conjx, &xo ); \ \ PASTEMAC0(opname)( &alphao, \ &ao, \ &xo, \ &betao, \ &yo, \ cntx ); \ } INSERT_GENTFUNC_BASIC0( gemv_front ) blis-0.9.0/frame/2/gemv/other/bli_gemv_front.h000066400000000000000000000042721422157504600211430ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void bli_gemv_front ( obj_t* alpha, obj_t* a, obj_t* x, obj_t* beta, obj_t* y, cntx_t* cntx ); #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ trans_t transa, \ conj_t conjx, \ dim_t m, \ dim_t n, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* x, inc_t incx, \ ctype* beta, \ ctype* y, inc_t incy, \ cntx_t* cntx \ ); INSERT_GENTPROT_BASIC( gemv_front ) blis-0.9.0/frame/2/gemv/other/bli_gemv_int.c000066400000000000000000000070331422157504600205760ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define FUNCPTR_T gemv_fp typedef void (*FUNCPTR_T)( obj_t* alpha, obj_t* a, obj_t* x, obj_t* beta, obj_t* y, cntx_t* cntx, gemv_t* cntl ); static FUNCPTR_T vars[3][3] = { // unblocked unblocked with fusing blocked { bli_gemv_unb_var1, bli_gemv_unf_var1, bli_gemv_blk_var1 }, { bli_gemv_unb_var2, bli_gemv_unf_var2, bli_gemv_blk_var2 }, { NULL, NULL, NULL }, }; void bli_gemv_int( trans_t transa, conj_t conjx, obj_t* alpha, obj_t* a, obj_t* x, obj_t* beta, obj_t* y, cntx_t* cntx, gemv_t* cntl ) { varnum_t n; impl_t i; FUNCPTR_T f; obj_t a_local; obj_t x_local; // Apply the trans and/or conj parameters to aliases of the objects. bli_obj_alias_with_trans( transa, a, &a_local ); bli_obj_alias_with_conj( conjx, x, &x_local ); // Check parameters. We use the aliased copy of A so the transa parameter // is taken into account for dimension checking. if ( bli_error_checking_is_enabled() ) bli_gemv_check( alpha, &a_local, &x_local, beta, y ); // If y has a zero dimension, return early. if ( bli_obj_has_zero_dim( y ) ) return; // If x has a zero dimension, scale y by beta and return early. if ( bli_obj_has_zero_dim( x ) ) { bli_scalm( beta, y ); return; } // Extract the variant number and implementation type. n = bli_cntl_var_num( cntl ); i = bli_cntl_impl_type( cntl ); // Index into the variant array to extract the correct function pointer. f = vars[n][i]; // Invoke the variant. f( alpha, &a_local, &x_local, beta, y, cntx, cntl ); } blis-0.9.0/frame/2/gemv/other/bli_gemv_int.h000066400000000000000000000035411422157504600206030ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void bli_gemv_int ( trans_t transa, conj_t conjx, obj_t* alpha, obj_t* a, obj_t* x, obj_t* beta, obj_t* y, cntx_t* cntx, gemv_t* cntl ); blis-0.9.0/frame/2/ger/000077500000000000000000000000001422157504600144675ustar00rootroot00000000000000blis-0.9.0/frame/2/ger/bli_ger.h000066400000000000000000000034631422157504600162510ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // NOTE: level-2 control tree code is temporarily disabled. //#include "bli_ger_cntl.h" //#include "bli_ger_front.h" //#include "bli_ger_int.h" #include "bli_ger_var.h" blis-0.9.0/frame/2/ger/bli_ger_unb_var1.c000066400000000000000000000053211422157504600200340ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ conj_t conjx, \ conj_t conjy, \ dim_t m, \ dim_t n, \ ctype* alpha, \ ctype* x, inc_t incx, \ ctype* y, inc_t incy, \ ctype* a, inc_t rs_a, inc_t cs_a, \ cntx_t* cntx \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ ctype* a1t; \ ctype* chi1; \ ctype* y1; \ ctype alpha_chi1; \ dim_t i; \ \ PASTECH(ch,axpyv_ker_ft) kfp_av; \ \ /* Query the context for the kernel function pointer. */ \ kfp_av = bli_cntx_get_l1v_ker_dt( dt, BLIS_AXPYV_KER, cntx ); \ \ for ( i = 0; i < m; ++i ) \ { \ a1t = a + (i )*rs_a + (0 )*cs_a; \ chi1 = x + (i )*incx; \ y1 = y + (0 )*incy; \ \ /* a1t = a1t + alpha * chi1 * y; */ \ PASTEMAC(ch,copycjs)( conjx, *chi1, alpha_chi1 ); \ PASTEMAC(ch,scals)( *alpha, alpha_chi1 ); \ \ kfp_av \ ( \ conjy, \ n, \ &alpha_chi1, \ y1, incy, \ a1t, cs_a, \ cntx \ ); \ } \ } INSERT_GENTFUNC_BASIC0( ger_unb_var1 ) blis-0.9.0/frame/2/ger/bli_ger_unb_var2.c000066400000000000000000000053141422157504600200370ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ conj_t conjx, \ conj_t conjy, \ dim_t m, \ dim_t n, \ ctype* alpha, \ ctype* x, inc_t incx, \ ctype* y, inc_t incy, \ ctype* a, inc_t rs_a, inc_t cs_a, \ cntx_t* cntx \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ ctype* a1; \ ctype* x1; \ ctype* psi1; \ ctype alpha_psi1; \ dim_t j; \ \ PASTECH(ch,axpyv_ker_ft) kfp_av; \ \ /* Query the context for the kernel function pointer. */ \ kfp_av = bli_cntx_get_l1v_ker_dt( dt, BLIS_AXPYV_KER, cntx ); \ \ for ( j = 0; j < n; ++j ) \ { \ a1 = a + (0 )*rs_a + (j )*cs_a; \ x1 = x + (0 )*incx; \ psi1 = y + (j )*incy; \ \ /* a1 = a1 + alpha * psi1 * x; */ \ PASTEMAC(ch,copycjs)( conjy, *psi1, alpha_psi1 ); \ PASTEMAC(ch,scals)( *alpha, alpha_psi1 ); \ \ kfp_av \ ( \ conjx, \ m, \ &alpha_psi1, \ x1, incx, \ a1, rs_a, \ cntx \ ); \ } \ } INSERT_GENTFUNC_BASIC0( ger_unb_var2 ) blis-0.9.0/frame/2/ger/bli_ger_var.h000066400000000000000000000047371422157504600171260ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype object-based interfaces. // #undef GENPROT #define GENPROT( opname ) \ \ void PASTEMAC0(opname) \ ( \ obj_t* alpha, \ obj_t* x, \ obj_t* y, \ obj_t* a, \ cntx_t* cntx, \ cntl_t* cntl \ ); GENPROT( ger_blk_var1 ) GENPROT( ger_blk_var2 ) GENPROT( ger_unb_var1 ) GENPROT( ger_unb_var2 ) // // Prototype BLAS-like interfaces with typed operands. // #undef GENTPROT #define GENTPROT( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ conj_t conjx, \ conj_t conjy, \ dim_t m, \ dim_t n, \ ctype* alpha, \ ctype* x, inc_t incx, \ ctype* y, inc_t incy, \ ctype* a, inc_t rs_a, inc_t cs_a, \ cntx_t* cntx \ ); INSERT_GENTPROT_BASIC0( ger_unb_var1 ) INSERT_GENTPROT_BASIC0( ger_unb_var2 ) blis-0.9.0/frame/2/ger/bli_ger_var_oapi.c000066400000000000000000000057221422157504600201240ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENFRONT #define GENFRONT( opname, varname ) \ \ void PASTEMAC0(varname) \ ( \ obj_t* alpha, \ obj_t* x, \ obj_t* y, \ obj_t* a, \ cntx_t* cntx, \ cntl_t* cntl \ ) \ { \ bli_init_once(); \ \ num_t dt = bli_obj_dt( a ); \ \ conj_t conjx = bli_obj_conj_status( x ); \ conj_t conjy = bli_obj_conj_status( y ); \ \ dim_t m = bli_obj_length( a ); \ dim_t n = bli_obj_width( a ); \ \ void* buf_x = bli_obj_buffer_at_off( x ); \ inc_t incx = bli_obj_vector_inc( x ); \ \ void* buf_y = bli_obj_buffer_at_off( y ); \ inc_t incy = bli_obj_vector_inc( y ); \ \ void* buf_a = bli_obj_buffer_at_off( a ); \ inc_t rs_a = bli_obj_row_stride( a ); \ inc_t cs_a = bli_obj_col_stride( a ); \ \ void* buf_alpha = bli_obj_buffer_for_1x1( dt, alpha ); \ \ /* Query a type-specific function pointer, except one that uses void* for function arguments instead of typed pointers. */ \ PASTECH2(opname,_unb,_vft) f = \ PASTEMAC(varname,_qfp)( dt ); \ \ f \ ( \ conjx, \ conjy, \ m, \ n, \ buf_alpha, \ buf_x, incx, \ buf_y, incy, \ buf_a, rs_a, cs_a, \ cntx \ ); \ } \ GENFRONT( ger, ger_unb_var1 ) GENFRONT( ger, ger_unb_var2 ) blis-0.9.0/frame/2/ger/other/000077500000000000000000000000001422157504600156105ustar00rootroot00000000000000blis-0.9.0/frame/2/ger/other/bli_ger_blk_var1.c000066400000000000000000000073451422157504600211510ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_ger_blk_var1( obj_t* alpha, obj_t* x, obj_t* y, obj_t* a, cntx_t* cntx, ger_t* cntl ) { obj_t a1, a1_pack; obj_t x1, x1_pack; dim_t i; dim_t b_alg; dim_t m_trans; // Initialize objects for packing. bli_obj_init_pack( &a1_pack ); bli_obj_init_pack( &x1_pack ); // Query dimension in partitioning direction. m_trans = bli_obj_length_after_trans( a ); // Partition along the m dimension. for ( i = 0; i < m_trans; i += b_alg ) { // Determine the current algorithmic blocksize. b_alg = bli_determine_blocksize_f( i, m_trans, a, bli_cntl_bszid( cntl ), cntx ); // Acquire partitions for A1 and x1. bli_acquire_mpart_t2b( BLIS_SUBPART1, i, b_alg, a, &a1 ); bli_acquire_vpart_f2b( BLIS_SUBPART1, i, b_alg, x, &x1 ); // Initialize objects for packing A1 and x1 (if needed). bli_packm_init( &a1, &a1_pack, cntx, bli_cntl_sub_packm_a( cntl ) ); bli_packv_init( &x1, &x1_pack, cntx, bli_cntl_sub_packv_x( cntl ) ); // Copy/pack A1, x1 (if needed). bli_packm_int( &a1, &a1_pack, cntx, bli_cntl_sub_packm_a( cntl ), &BLIS_PACKM_SINGLE_THREADED ); bli_packv_int( &x1, &x1_pack, cntx, bli_cntl_sub_packv_x( cntl ) ); // A1 = A1 + alpha * x1 * y; bli_ger_int( BLIS_NO_CONJUGATE, BLIS_NO_CONJUGATE, alpha, &x1_pack, y, &a1_pack, cntx, bli_cntl_sub_ger( cntl ) ); // Copy/unpack A1 (if A1 was packed). bli_unpackm_int( &a1_pack, &a1, cntx, bli_cntl_sub_unpackm_a( cntl ), &BLIS_PACKM_SINGLE_THREADED ); } // If any packing buffers were acquired within packm, release them back // to the memory manager. bli_packm_release( &a1_pack, bli_cntl_sub_packm_a( cntl ) ); bli_packv_release( &x1_pack, bli_cntl_sub_packv_x( cntl ) ); } blis-0.9.0/frame/2/ger/other/bli_ger_blk_var2.c000066400000000000000000000073441422157504600211510ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_ger_blk_var2( obj_t* alpha, obj_t* x, obj_t* y, obj_t* a, cntx_t* cntx, ger_t* cntl ) { obj_t a1, a1_pack; obj_t y1, y1_pack; dim_t i; dim_t b_alg; dim_t n_trans; // Initialize objects for packing. bli_obj_init_pack( &a1_pack ); bli_obj_init_pack( &y1_pack ); // Query dimension in partitioning direction. n_trans = bli_obj_width_after_trans( a ); // Partition along the n dimension. for ( i = 0; i < n_trans; i += b_alg ) { // Determine the current algorithmic blocksize. b_alg = bli_determine_blocksize_f( i, n_trans, a, bli_cntl_bszid( cntl ), cntx ); // Acquire partitions for A1 and y1. bli_acquire_mpart_l2r( BLIS_SUBPART1, i, b_alg, a, &a1 ); bli_acquire_vpart_f2b( BLIS_SUBPART1, i, b_alg, y, &y1 ); // Initialize objects for packing A1 and y1 (if needed). bli_packm_init( &a1, &a1_pack, cntx, bli_cntl_sub_packm_a( cntl ) ); bli_packv_init( &y1, &y1_pack, cntx, bli_cntl_sub_packv_y( cntl ) ); // Copy/pack A1, y1 (if needed). bli_packm_int( &a1, &a1_pack, cntx, bli_cntl_sub_packm_a( cntl ), &BLIS_PACKM_SINGLE_THREADED ); bli_packv_int( &y1, &y1_pack, cntx, bli_cntl_sub_packv_y( cntl ) ); // A1 = A1 + alpha * x * y1; bli_ger_int( BLIS_NO_CONJUGATE, BLIS_NO_CONJUGATE, alpha, x, &y1_pack, &a1_pack, cntx, bli_cntl_sub_ger( cntl ) ); // Copy/unpack A1 (if A1 was packed). bli_unpackm_int( &a1_pack, &a1, cntx, bli_cntl_sub_unpackm_a( cntl ), &BLIS_PACKM_SINGLE_THREADED ); } // If any packing buffers were acquired within packm, release them back // to the memory manager. bli_packm_release( &a1_pack, bli_cntl_sub_packm_a( cntl ) ); bli_packv_release( &y1_pack, bli_cntl_sub_packv_y( cntl ) ); } blis-0.9.0/frame/2/ger/other/bli_ger_cntl.c000066400000000000000000000171041422157504600204020ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" extern packm_t* packm_cntl; extern packv_t* packv_cntl; extern unpackm_t* unpackm_cntl; ger_t* ger_cntl_bs_ke_row = NULL; ger_t* ger_cntl_bs_ke_col = NULL; ger_t* ger_cntl_rp_bs_row = NULL; ger_t* ger_cntl_rp_bs_col = NULL; ger_t* ger_cntl_cp_bs_row = NULL; ger_t* ger_cntl_cp_bs_col = NULL; ger_t* ger_cntl_ge_row = NULL; ger_t* ger_cntl_ge_col = NULL; void bli_ger_cntl_init() { // Create control trees for the lowest-level kernels. These trees induce // operations on (persumably) relatively small block-subvector problems. ger_cntl_bs_ke_row = bli_ger_cntl_obj_create( BLIS_UNBLOCKED, BLIS_VARIANT1, 0, NULL, NULL, NULL, NULL, NULL ); ger_cntl_bs_ke_col = bli_ger_cntl_obj_create( BLIS_UNBLOCKED, BLIS_VARIANT2, 0, NULL, NULL, NULL, NULL, NULL ); // Create control trees for problems with relatively small m dimension // (ie: where A is a row panel problem). ger_cntl_rp_bs_row = bli_ger_cntl_obj_create( BLIS_BLOCKED, BLIS_VARIANT2, BLIS_N2, NULL, // x is not partitioned in var2 packv_cntl, // pack y1 (if needed) packm_cntl, // pack A1 (if needed) ger_cntl_bs_ke_row, unpackm_cntl ); // unpack A1 (if packed) ger_cntl_rp_bs_col = bli_ger_cntl_obj_create( BLIS_BLOCKED, BLIS_VARIANT2, BLIS_N2, NULL, // x is not partitioned in var2 packv_cntl, // pack y1 (if needed) packm_cntl, // pack A1 (if needed) ger_cntl_bs_ke_col, unpackm_cntl ); // unpack A1 (if packed) // Create control trees for problems with relatively small n dimension // (ie: where A is a column panel problem). ger_cntl_cp_bs_row = bli_ger_cntl_obj_create( BLIS_BLOCKED, BLIS_VARIANT1, BLIS_M2, packv_cntl, // pack x1 (if needed) NULL, // y is not partitioned in var1 packm_cntl, // pack A1 (if needed) ger_cntl_bs_ke_row, unpackm_cntl ); // unpack A1 (if packed) ger_cntl_cp_bs_col = bli_ger_cntl_obj_create( BLIS_BLOCKED, BLIS_VARIANT1, BLIS_M2, packv_cntl, // pack x1 (if needed) NULL, // y is not partitioned in var1 packm_cntl, // pack A1 (if needed) ger_cntl_bs_ke_col, unpackm_cntl ); // unpack A1 (if packed) // Create control trees for generally large problems. Here, we choose a // variant that partitions subproblems into column panels. ger_cntl_ge_row = bli_ger_cntl_obj_create( BLIS_BLOCKED, BLIS_VARIANT2, BLIS_N2, NULL, // x is not partitioned in var2 packv_cntl, // pack y1 (if needed) NULL, // do not pack A1 ger_cntl_cp_bs_row, NULL ); // do not unpack A1 ger_cntl_ge_col = bli_ger_cntl_obj_create( BLIS_BLOCKED, BLIS_VARIANT2, BLIS_N2, NULL, // x is not partitioned in var2 packv_cntl, // pack y1 (if needed) NULL, // do not pack A1 ger_cntl_cp_bs_col, NULL ); // do not unpack A1 } void bli_ger_cntl_finalize() { bli_cntl_free_node( ger_cntl_bs_ke_row ); bli_cntl_free_node( ger_cntl_bs_ke_col ); bli_cntl_free_node( ger_cntl_rp_bs_row ); bli_cntl_free_node( ger_cntl_rp_bs_col ); bli_cntl_free_node( ger_cntl_cp_bs_row ); bli_cntl_free_node( ger_cntl_cp_bs_col ); bli_cntl_free_node( ger_cntl_ge_row ); bli_cntl_free_node( ger_cntl_ge_col ); } ger_t* bli_ger_cntl_obj_create( impl_t impl_type, varnum_t var_num, bszid_t bszid, packv_t* sub_packv_x, packv_t* sub_packv_y, packm_t* sub_packm_a, ger_t* sub_ger, unpackm_t* sub_unpackm_a ) { ger_t* cntl; cntl = ( ger_t* ) bli_malloc_intl( sizeof(ger_t) ); cntl->impl_type = impl_type; cntl->var_num = var_num; cntl->bszid = bszid; cntl->sub_packv_x = sub_packv_x; cntl->sub_packv_y = sub_packv_y; cntl->sub_packm_a = sub_packm_a; cntl->sub_ger = sub_ger; cntl->sub_unpackm_a = sub_unpackm_a; return cntl; } void bli_ger_cntl_obj_init( ger_t* cntl, impl_t impl_type, varnum_t var_num, bszid_t bszid, packv_t* sub_packv_x, packv_t* sub_packv_y, packm_t* sub_packm_a, ger_t* sub_ger, unpackm_t* sub_unpackm_a ) { cntl->impl_type = impl_type; cntl->var_num = var_num; cntl->bszid = bszid; cntl->sub_packv_x = sub_packv_x; cntl->sub_packv_y = sub_packv_y; cntl->sub_packm_a = sub_packm_a; cntl->sub_ger = sub_ger; cntl->sub_unpackm_a = sub_unpackm_a; } blis-0.9.0/frame/2/ger/other/bli_ger_cntl.h000066400000000000000000000060251422157504600204070ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ struct ger_s { impl_t impl_type; varnum_t var_num; bszid_t bszid; struct packv_s* sub_packv_x; struct packv_s* sub_packv_y; struct packm_s* sub_packm_a; struct ger_s* sub_ger; struct unpackm_s* sub_unpackm_a; }; typedef struct ger_s ger_t; #define bli_cntl_sub_ger( cntl ) cntl->sub_ger #define bli_cntl_sub_ger_rp( cntl ) cntl->sub_ger_rp #define bli_cntl_sub_ger_cp( cntl ) cntl->sub_ger_cp void bli_ger_cntl_init( void ); void bli_ger_cntl_finalize( void ); ger_t* bli_ger_cntl_obj_create( impl_t impl_type, varnum_t var_num, bszid_t bszid, packv_t* sub_packv_x, packv_t* sub_packv_y, packm_t* sub_packm_a, ger_t* sub_ger, unpackm_t* sub_unpackm_a ); void bli_ger_cntl_obj_init( ger_t* cntl, impl_t impl_type, varnum_t var_num, bszid_t bszid, packv_t* sub_packv_x, packv_t* sub_packv_y, packm_t* sub_packm_a, ger_t* sub_ger, unpackm_t* sub_unpackm_a ); blis-0.9.0/frame/2/ger/other/bli_ger_front.c000066400000000000000000000132261422157504600205730ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" extern ger_t* ger_cntl_bs_ke_row; extern ger_t* ger_cntl_bs_ke_col; extern ger_t* ger_cntl_ge_row; extern ger_t* ger_cntl_ge_col; void bli_ger_front ( obj_t* alpha, obj_t* x, obj_t* y, obj_t* a, cntx_t* cntx ) { ger_t* ger_cntl; num_t dt_targ_x; num_t dt_targ_y; //num_t dt_targ_a; bool x_has_unit_inc; bool y_has_unit_inc; bool a_has_unit_inc; obj_t alpha_local; num_t dt_alpha; // Check parameters. if ( bli_error_checking_is_enabled() ) bli_ger_check( alpha, x, y, a ); // Query the target datatypes of each object. dt_targ_x = bli_obj_target_dt( x ); dt_targ_y = bli_obj_target_dt( y ); //dt_targ_a = bli_obj_target_dt( a ); // Determine whether each operand with unit stride. x_has_unit_inc = ( bli_obj_vector_inc( x ) == 1 ); y_has_unit_inc = ( bli_obj_vector_inc( y ) == 1 ); a_has_unit_inc = ( bli_obj_is_row_stored( a ) || bli_obj_is_col_stored( a ) ); // Create an object to hold a copy-cast of alpha. Notice that we use // the type union of the target datatypes of x and y to prevent any // unnecessary loss of information during the computation. dt_alpha = bli_dt_union( dt_targ_x, dt_targ_y ); bli_obj_scalar_init_detached_copy_of( dt_alpha, BLIS_NO_CONJUGATE, alpha, &alpha_local ); // If all operands have unit stride, we choose a control tree for calling // the unblocked implementation directly without any blocking. if ( x_has_unit_inc && y_has_unit_inc && a_has_unit_inc ) { // Use different control trees depending on storage of the matrix // operand. if ( bli_obj_is_row_stored( a ) ) ger_cntl = ger_cntl_bs_ke_row; else ger_cntl = ger_cntl_bs_ke_col; } else { // Mark objects with unit stride as already being packed. This prevents // unnecessary packing from happening within the blocked algorithm. if ( x_has_unit_inc ) bli_obj_set_pack_schema( BLIS_PACKED_VECTOR, x ); if ( y_has_unit_inc ) bli_obj_set_pack_schema( BLIS_PACKED_VECTOR, y ); if ( a_has_unit_inc ) bli_obj_set_pack_schema( BLIS_PACKED_UNSPEC, a ); // Here, we make a similar choice as above, except that (1) we look // at storage tilt, and (2) we choose a tree that performs blocking. if ( bli_obj_is_row_tilted( a ) ) ger_cntl = ger_cntl_ge_row; else ger_cntl = ger_cntl_ge_col; } // Invoke the internal back-end with the copy-cast scalar and the // chosen control tree. bli_ger_int( BLIS_NO_CONJUGATE, BLIS_NO_CONJUGATE, &alpha_local, x, y, a, cntx, ger_cntl ); } // // Define BLAS-like interfaces with homogeneous-typed operands. // #undef GENTFUNC #define GENTFUNC( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ conj_t conjx, \ conj_t conjy, \ dim_t m, \ dim_t n, \ ctype* alpha, \ ctype* x, inc_t incx, \ ctype* y, inc_t incy, \ ctype* a, inc_t rs_a, inc_t cs_a, \ cntx_t* cntx \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ obj_t alphao, xo, yo, ao; \ \ dim_t m_x; \ dim_t m_y; \ inc_t rs_x, cs_x; \ inc_t rs_y, cs_y; \ \ bli_set_dims_with_trans( BLIS_NO_TRANSPOSE, m, n, &m_x, &m_y ); \ \ rs_x = incx; cs_x = m_x * incx; \ rs_y = incy; cs_y = m_y * incy; \ \ bli_obj_create_1x1_with_attached_buffer( dt, alpha, &alphao ); \ \ bli_obj_create_with_attached_buffer( dt, m_x, 1, x, rs_x, cs_x, &xo ); \ bli_obj_create_with_attached_buffer( dt, m_y, 1, y, rs_y, cs_y, &yo ); \ bli_obj_create_with_attached_buffer( dt, m, n, a, rs_a, cs_a, &ao ); \ \ bli_obj_set_conj( conjx, &xo ); \ bli_obj_set_conj( conjy, &yo ); \ \ PASTEMAC0(opname)( &alphao, \ &xo, \ &yo, \ &ao, \ cntx ); \ } INSERT_GENTFUNC_BASIC0( ger_front ) blis-0.9.0/frame/2/ger/other/bli_ger_front.h000066400000000000000000000042131422157504600205740ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void bli_ger_front ( obj_t* alpha, obj_t* x, obj_t* y, obj_t* a, cntx_t* cntx ); #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ conj_t conjx, \ conj_t conjy, \ dim_t m, \ dim_t n, \ ctype* alpha, \ ctype* x, inc_t incx, \ ctype* y, inc_t incy, \ ctype* a, inc_t rs_a, inc_t cs_a, \ cntx_t* cntx \ ); INSERT_GENTPROT_BASIC( ger_front ) blis-0.9.0/frame/2/ger/other/bli_ger_int.c000066400000000000000000000105161422157504600202340ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define FUNCPTR_T ger_fp typedef void (*FUNCPTR_T)( obj_t* alpha, obj_t* x, obj_t* y, obj_t* a, cntx_t* cntx, ger_t* cntl ); static FUNCPTR_T vars[4][3] = { // unblocked unblocked with fusing blocked { bli_ger_unb_var1, NULL, bli_ger_blk_var1, }, { bli_ger_unb_var2, NULL, bli_ger_blk_var2, }, { NULL, NULL, NULL, }, { NULL, NULL, NULL, }, }; void bli_ger_int( conj_t conjx, conj_t conjy, obj_t* alpha, obj_t* x, obj_t* y, obj_t* a, cntx_t* cntx, ger_t* cntl ) { varnum_t n; impl_t i; FUNCPTR_T f; obj_t alpha_local; obj_t x_local; obj_t y_local; obj_t a_local; // Check parameters. if ( bli_error_checking_is_enabled() ) bli_ger_check( alpha, x, y, a ); // If A has a zero dimension, return early. if ( bli_obj_has_zero_dim( a ) ) return; // If x or y has a zero dimension, return early. if ( bli_obj_has_zero_dim( x ) || bli_obj_has_zero_dim( y ) ) return; // Alias the objects, applying conjx and conjy to x and y, respectively. bli_obj_alias_with_conj( conjx, x, &x_local ); bli_obj_alias_with_conj( conjy, y, &y_local ); bli_obj_alias_to( a, &a_local ); // If matrix A is marked for conjugation, we interpret this as a request // to apply a conjugation to the other operands. if ( bli_obj_has_conj( &a_local ) ) { bli_obj_toggle_conj( &a_local ); bli_obj_toggle_conj( &x_local ); bli_obj_toggle_conj( &y_local ); bli_obj_scalar_init_detached_copy_of( bli_obj_dt( alpha ), BLIS_CONJUGATE, alpha, &alpha_local ); } else { bli_obj_alias_to( *alpha, alpha_local ); } // If we are about the call a leaf-level implementation, and matrix A // still needs a transposition, then we must induce one by swapping the // strides and dimensions. if ( bli_cntl_is_leaf( cntl ) && bli_obj_has_trans( &a_local ) ) { bli_obj_induce_trans( &a_local ); bli_obj_set_onlytrans( BLIS_NO_TRANSPOSE, &a_local ); } // Extract the variant number and implementation type. n = bli_cntl_var_num( cntl ); i = bli_cntl_impl_type( cntl ); // Index into the variant array to extract the correct function pointer. f = vars[n][i]; // Invoke the variant. f( &alpha_local, &x_local, &y_local, &a_local, cntx, cntl ); } blis-0.9.0/frame/2/ger/other/bli_ger_int.h000066400000000000000000000036061422157504600202430ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void bli_ger_int( conj_t conjx, conj_t conjy, obj_t* alpha, obj_t* x, obj_t* y, obj_t* a, cntx_t* cntx, ger_t* cntl ); blis-0.9.0/frame/2/hemv/000077500000000000000000000000001422157504600146515ustar00rootroot00000000000000blis-0.9.0/frame/2/hemv/bli_hemv.h000066400000000000000000000034701422157504600166130ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // NOTE: level-2 control tree code is temporarily disabled. //#include "bli_hemv_cntl.h" //#include "bli_hemv_front.h" //#include "bli_hemv_int.h" #include "bli_hemv_var.h" blis-0.9.0/frame/2/hemv/bli_hemv_unb_var1.c000066400000000000000000000114111422157504600203750ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ uplo_t uplo, \ conj_t conja, \ conj_t conjx, \ conj_t conjh, \ dim_t m, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* x, inc_t incx, \ ctype* beta, \ ctype* y, inc_t incy, \ cntx_t* cntx \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ ctype* one = PASTEMAC(ch,1); \ ctype* zero = PASTEMAC(ch,0); \ ctype* a10t; \ ctype* alpha11; \ ctype* x0; \ ctype* chi1; \ ctype* y0; \ ctype* psi1; \ ctype conjx_chi1; \ ctype alpha_chi1; \ ctype alpha11_temp; \ dim_t i; \ dim_t n_behind; \ inc_t rs_at, cs_at; \ conj_t conj0, conj1; \ \ /* The algorithm will be expressed in terms of the lower triangular case; the upper triangular case is supported by swapping the row and column strides of A and toggling some conj parameters. */ \ if ( bli_is_lower( uplo ) ) \ { \ rs_at = rs_a; \ cs_at = cs_a; \ \ conj0 = bli_apply_conj( conjh, conja ); \ conj1 = conja; \ } \ else /* if ( bli_is_upper( uplo ) ) */ \ { \ rs_at = cs_a; \ cs_at = rs_a; \ \ conj0 = conja; \ conj1 = bli_apply_conj( conjh, conja ); \ } \ \ /* If beta is zero, use setv. Otherwise, scale by beta. */ \ if ( PASTEMAC(ch,eq0)( *beta ) ) \ { \ /* y = 0; */ \ PASTEMAC2(ch,setv,BLIS_TAPI_EX_SUF) \ ( \ BLIS_NO_CONJUGATE, \ m, \ zero, \ y, incy, \ cntx, \ NULL \ ); \ } \ else \ { \ /* y = beta * y; */ \ PASTEMAC2(ch,scalv,BLIS_TAPI_EX_SUF) \ ( \ BLIS_NO_CONJUGATE, \ m, \ beta, \ y, incy, \ cntx, \ NULL \ ); \ } \ \ PASTECH(ch,axpyv_ker_ft) kfp_av; \ PASTECH(ch,dotxv_ker_ft) kfp_dv; \ \ /* Query the context for the kernel function pointers. */ \ kfp_av = bli_cntx_get_l1v_ker_dt( dt, BLIS_AXPYV_KER, cntx ); \ kfp_dv = bli_cntx_get_l1v_ker_dt( dt, BLIS_DOTXV_KER, cntx ); \ \ for ( i = 0; i < m; ++i ) \ { \ n_behind = i; \ a10t = a + (i )*rs_at + (0 )*cs_at; \ alpha11 = a + (i )*rs_at + (i )*cs_at; \ x0 = x + (0 )*incx; \ chi1 = x + (i )*incx; \ y0 = y + (0 )*incy; \ psi1 = y + (i )*incy; \ \ /* Apply conjx to chi1 and and scale by alpha. */ \ PASTEMAC(ch,copycjs)( conjx, *chi1, conjx_chi1 ); \ PASTEMAC(ch,scal2s)( *alpha, conjx_chi1, alpha_chi1 ); \ \ /* y0 = y0 + alpha * a10t' * chi1; */ \ kfp_av \ ( \ conj0, \ n_behind, \ &alpha_chi1, \ a10t, cs_at, \ y0, incy, \ cntx \ ); \ \ /* psi1 = psi1 + alpha * a10t * x0; */ \ kfp_dv \ ( \ conj1, \ conjx, \ n_behind, \ alpha, \ a10t, cs_at, \ x0, incx, \ one, \ psi1, \ cntx \ ); \ \ /* For hemv, explicitly set the imaginary component of alpha11 to zero. */ \ PASTEMAC(ch,copycjs)( conja, *alpha11, alpha11_temp ); \ if ( bli_is_conj( conjh ) ) \ PASTEMAC(ch,seti0s)( alpha11_temp ); \ \ /* psi1 = psi1 + alpha * alpha11 * chi1; */ \ PASTEMAC(ch,axpys)( alpha_chi1, alpha11_temp, *psi1 ); \ \ } \ } INSERT_GENTFUNC_BASIC0( hemv_unb_var1 ) blis-0.9.0/frame/2/hemv/bli_hemv_unb_var2.c000066400000000000000000000114731422157504600204060ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ uplo_t uplo, \ conj_t conja, \ conj_t conjx, \ conj_t conjh, \ dim_t m, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* x, inc_t incx, \ ctype* beta, \ ctype* y, inc_t incy, \ cntx_t* cntx \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ ctype* one = PASTEMAC(ch,1); \ ctype* zero = PASTEMAC(ch,0); \ ctype* a10t; \ ctype* alpha11; \ ctype* a21; \ ctype* x0; \ ctype* chi1; \ ctype* x2; \ ctype* psi1; \ ctype conjx_chi1; \ ctype alpha_chi1; \ ctype alpha11_temp; \ dim_t i; \ dim_t n_behind; \ dim_t n_ahead; \ inc_t rs_at, cs_at; \ conj_t conj0, conj1; \ \ /* The algorithm will be expressed in terms of the lower triangular case; the upper triangular case is supported by swapping the row and column strides of A and toggling some conj parameters. */ \ if ( bli_is_lower( uplo ) ) \ { \ rs_at = rs_a; \ cs_at = cs_a; \ \ conj0 = conja; \ conj1 = bli_apply_conj( conjh, conja ); \ } \ else /* if ( bli_is_upper( uplo ) ) */ \ { \ rs_at = cs_a; \ cs_at = rs_a; \ \ conj0 = bli_apply_conj( conjh, conja ); \ conj1 = conja; \ } \ \ /* If beta is zero, use setv. Otherwise, scale by beta. */ \ if ( PASTEMAC(ch,eq0)( *beta ) ) \ { \ /* y = 0; */ \ PASTEMAC2(ch,setv,BLIS_TAPI_EX_SUF) \ ( \ BLIS_NO_CONJUGATE, \ m, \ zero, \ y, incy, \ cntx, \ NULL \ ); \ } \ else \ { \ /* y = beta * y; */ \ PASTEMAC2(ch,scalv,BLIS_TAPI_EX_SUF) \ ( \ BLIS_NO_CONJUGATE, \ m, \ beta, \ y, incy, \ cntx, \ NULL \ ); \ } \ \ PASTECH(ch,dotxv_ker_ft) kfp_dv; \ \ /* Query the context for the kernel function pointer. */ \ kfp_dv = bli_cntx_get_l1v_ker_dt( dt, BLIS_DOTXV_KER, cntx ); \ \ for ( i = 0; i < m; ++i ) \ { \ n_behind = i; \ n_ahead = m - i - 1; \ a10t = a + (i )*rs_at + (0 )*cs_at; \ alpha11 = a + (i )*rs_at + (i )*cs_at; \ a21 = a + (i+1)*rs_at + (i )*cs_at; \ x0 = x + (0 )*incx; \ chi1 = x + (i )*incx; \ x2 = x + (i+1)*incx; \ psi1 = y + (i )*incy; \ \ /* Apply conjx to chi1 and and scale by alpha. */ \ PASTEMAC(ch,copycjs)( conjx, *chi1, conjx_chi1 ); \ PASTEMAC(ch,scal2s)( *alpha, conjx_chi1, alpha_chi1 ); \ \ /* psi1 = psi1 + alpha * a10t * x0; */ \ kfp_dv \ ( \ conj0, \ conjx, \ n_behind, \ alpha, \ a10t, cs_at, \ x0, incx, \ one, \ psi1, \ cntx \ ); \ \ /* psi1 = psi1 + alpha * a21' * x2; */ \ kfp_dv \ ( \ conj1, \ conjx, \ n_ahead, \ alpha, \ a21, rs_at, \ x2, incx, \ one, \ psi1, \ cntx \ ); \ \ /* For hemv, explicitly set the imaginary component of alpha11 to zero. */ \ PASTEMAC(ch,copycjs)( conja, *alpha11, alpha11_temp ); \ if ( bli_is_conj( conjh ) ) \ PASTEMAC(ch,seti0s)( alpha11_temp ); \ \ /* psi1 = psi1 + alpha * alpha11 * chi1; */ \ PASTEMAC(ch,axpys)( alpha_chi1, alpha11_temp, *psi1 ); \ } \ } INSERT_GENTFUNC_BASIC0( hemv_unb_var2 ) blis-0.9.0/frame/2/hemv/bli_hemv_unb_var3.c000066400000000000000000000114051422157504600204020ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ uplo_t uplo, \ conj_t conja, \ conj_t conjx, \ conj_t conjh, \ dim_t m, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* x, inc_t incx, \ ctype* beta, \ ctype* y, inc_t incy, \ cntx_t* cntx \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ ctype* one = PASTEMAC(ch,1); \ ctype* zero = PASTEMAC(ch,0); \ ctype* alpha11; \ ctype* a21; \ ctype* chi1; \ ctype* x2; \ ctype* psi1; \ ctype* y2; \ ctype conjx_chi1; \ ctype alpha_chi1; \ ctype alpha11_temp; \ dim_t i; \ dim_t n_ahead; \ inc_t rs_at, cs_at; \ conj_t conj0, conj1; \ \ /* The algorithm will be expressed in terms of the lower triangular case; the upper triangular case is supported by swapping the row and column strides of A and toggling some conj parameters. */ \ if ( bli_is_lower( uplo ) ) \ { \ rs_at = rs_a; \ cs_at = cs_a; \ \ conj0 = bli_apply_conj( conjh, conja ); \ conj1 = conja; \ } \ else /* if ( bli_is_upper( uplo ) ) */ \ { \ rs_at = cs_a; \ cs_at = rs_a; \ \ conj0 = conja; \ conj1 = bli_apply_conj( conjh, conja ); \ } \ \ /* If beta is zero, use setv. Otherwise, scale by beta. */ \ if ( PASTEMAC(ch,eq0)( *beta ) ) \ { \ /* y = 0; */ \ PASTEMAC2(ch,setv,BLIS_TAPI_EX_SUF) \ ( \ BLIS_NO_CONJUGATE, \ m, \ zero, \ y, incy, \ cntx, \ NULL \ ); \ } \ else \ { \ /* y = beta * y; */ \ PASTEMAC2(ch,scalv,BLIS_TAPI_EX_SUF) \ ( \ BLIS_NO_CONJUGATE, \ m, \ beta, \ y, incy, \ cntx, \ NULL \ ); \ } \ \ PASTECH(ch,axpyv_ker_ft) kfp_av; \ PASTECH(ch,dotxv_ker_ft) kfp_dv; \ \ /* Query the context for the kernel function pointers. */ \ kfp_av = bli_cntx_get_l1v_ker_dt( dt, BLIS_AXPYV_KER, cntx ); \ kfp_dv = bli_cntx_get_l1v_ker_dt( dt, BLIS_DOTXV_KER, cntx ); \ \ for ( i = 0; i < m; ++i ) \ { \ n_ahead = m - i - 1; \ alpha11 = a + (i )*rs_at + (i )*cs_at; \ a21 = a + (i+1)*rs_at + (i )*cs_at; \ chi1 = x + (i )*incx; \ x2 = x + (i+1)*incx; \ psi1 = y + (i )*incy; \ y2 = y + (i+1)*incy; \ \ /* Apply conjx to chi1 and and scale by alpha. */ \ PASTEMAC(ch,copycjs)( conjx, *chi1, conjx_chi1 ); \ PASTEMAC(ch,scal2s)( *alpha, conjx_chi1, alpha_chi1 ); \ \ /* For hemv, explicitly set the imaginary component of alpha11 to zero. */ \ PASTEMAC(ch,copycjs)( conja, *alpha11, alpha11_temp ); \ if ( bli_is_conj( conjh ) ) \ PASTEMAC(ch,seti0s)( alpha11_temp ); \ \ /* psi1 = psi1 + alpha * alpha11 * chi1; */ \ PASTEMAC(ch,axpys)( alpha_chi1, alpha11_temp, *psi1 ); \ \ /* psi1 = psi1 + alpha * a21' * x2; */ \ kfp_dv \ ( \ conj0, \ conjx, \ n_ahead, \ alpha, \ a21, rs_at, \ x2, incx, \ one, \ psi1, \ cntx \ ); \ \ /* y2 = y2 + alpha * a21 * chi1; */ \ kfp_av \ ( \ conj1, \ n_ahead, \ &alpha_chi1, \ a21, rs_at, \ y2, incy, \ cntx \ ); \ } \ } INSERT_GENTFUNC_BASIC0( hemv_unb_var3 ) blis-0.9.0/frame/2/hemv/bli_hemv_unb_var4.c000066400000000000000000000113021422157504600203770ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ uplo_t uplo, \ conj_t conja, \ conj_t conjx, \ conj_t conjh, \ dim_t m, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* x, inc_t incx, \ ctype* beta, \ ctype* y, inc_t incy, \ cntx_t* cntx \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ ctype* zero = PASTEMAC(ch,0); \ ctype* a10t; \ ctype* alpha11; \ ctype* a21; \ ctype* chi1; \ ctype* y0; \ ctype* psi1; \ ctype* y2; \ ctype conjx_chi1; \ ctype alpha_chi1; \ ctype alpha11_temp; \ dim_t i; \ dim_t n_behind; \ dim_t n_ahead; \ inc_t rs_at, cs_at; \ conj_t conj0, conj1; \ \ /* The algorithm will be expressed in terms of the lower triangular case; the upper triangular case is supported by swapping the row and column strides of A and toggling some conj parameters. */ \ if ( bli_is_lower( uplo ) ) \ { \ rs_at = rs_a; \ cs_at = cs_a; \ \ conj0 = bli_apply_conj( conjh, conja ); \ conj1 = conja; \ } \ else /* if ( bli_is_upper( uplo ) ) */ \ { \ rs_at = cs_a; \ cs_at = rs_a; \ \ conj0 = conja; \ conj1 = bli_apply_conj( conjh, conja ); \ } \ \ /* If beta is zero, use setv. Otherwise, scale by beta. */ \ if ( PASTEMAC(ch,eq0)( *beta ) ) \ { \ /* y = 0; */ \ PASTEMAC2(ch,setv,BLIS_TAPI_EX_SUF) \ ( \ BLIS_NO_CONJUGATE, \ m, \ zero, \ y, incy, \ cntx, \ NULL \ ); \ } \ else \ { \ /* y = beta * y; */ \ PASTEMAC2(ch,scalv,BLIS_TAPI_EX_SUF) \ ( \ BLIS_NO_CONJUGATE, \ m, \ beta, \ y, incy, \ cntx, \ NULL \ ); \ } \ \ PASTECH(ch,axpyv_ker_ft) kfp_av; \ \ /* Query the context for the kernel function pointers. */ \ kfp_av = bli_cntx_get_l1v_ker_dt( dt, BLIS_AXPYV_KER, cntx ); \ \ for ( i = 0; i < m; ++i ) \ { \ n_behind = i; \ n_ahead = m - i - 1; \ a10t = a + (i )*rs_at + (0 )*cs_at; \ alpha11 = a + (i )*rs_at + (i )*cs_at; \ a21 = a + (i+1)*rs_at + (i )*cs_at; \ chi1 = x + (i )*incx; \ y0 = y + (0 )*incy; \ psi1 = y + (i )*incy; \ y2 = y + (i+1)*incy; \ \ /* Apply conjx to chi1 and and scale by alpha. */ \ PASTEMAC(ch,copycjs)( conjx, *chi1, conjx_chi1 ); \ PASTEMAC(ch,scal2s)( *alpha, conjx_chi1, alpha_chi1 ); \ \ /* y0 = y0 + alpha * a10t' * chi1; */ \ kfp_av \ ( \ conj0, \ n_behind, \ &alpha_chi1, \ a10t, cs_at, \ y0, incy, \ cntx \ ); \ \ /* For hemv, explicitly set the imaginary component of alpha11 to zero. */ \ PASTEMAC(ch,copycjs)( conja, *alpha11, alpha11_temp ); \ if ( bli_is_conj( conjh ) ) \ PASTEMAC(ch,seti0s)( alpha11_temp ); \ \ /* psi1 = psi1 + alpha * alpha11 * chi1; */ \ PASTEMAC(ch,axpys)( alpha_chi1, alpha11_temp, *psi1 ); \ \ /* y2 = y2 + alpha * a21 * chi1; */ \ kfp_av \ ( \ conj1, \ n_ahead, \ &alpha_chi1, \ a21, rs_at, \ y2, incy, \ cntx \ ); \ } \ } INSERT_GENTFUNC_BASIC0( hemv_unb_var4 ) blis-0.9.0/frame/2/hemv/bli_hemv_unf_var1.c000066400000000000000000000140031422157504600204010ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ uplo_t uplo, \ conj_t conja, \ conj_t conjx, \ conj_t conjh, \ dim_t m, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* x, inc_t incx, \ ctype* beta, \ ctype* y, inc_t incy, \ cntx_t* cntx \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ ctype* one = PASTEMAC(ch,1); \ ctype* zero = PASTEMAC(ch,0); \ ctype* A10; \ ctype* A11; \ ctype* a10t; \ ctype* alpha11; \ ctype* a21; \ ctype* x0; \ ctype* x1; \ ctype* chi11; \ ctype* y0; \ ctype* y1; \ ctype* y01; \ ctype* psi11; \ ctype* y21; \ ctype conjx_chi11; \ ctype alpha_chi11; \ ctype alpha11_temp; \ dim_t i, k, j; \ dim_t b_fuse, f; \ dim_t n_behind; \ dim_t f_ahead, f_behind; \ inc_t rs_at, cs_at; \ conj_t conj0, conj1; \ \ /* The algorithm will be expressed in terms of the lower triangular case; the upper triangular case is supported by swapping the row and column strides of A and toggling some conj parameters. */ \ if ( bli_is_lower( uplo ) ) \ { \ rs_at = rs_a; \ cs_at = cs_a; \ \ conj0 = conja; \ conj1 = bli_apply_conj( conjh, conja ); \ } \ else /* if ( bli_is_upper( uplo ) ) */ \ { \ rs_at = cs_a; \ cs_at = rs_a; \ \ conj0 = bli_apply_conj( conjh, conja ); \ conj1 = conja; \ } \ \ /* If beta is zero, use setv. Otherwise, scale by beta. */ \ if ( PASTEMAC(ch,eq0)( *beta ) ) \ { \ /* y = 0; */ \ PASTEMAC2(ch,setv,BLIS_TAPI_EX_SUF) \ ( \ BLIS_NO_CONJUGATE, \ m, \ zero, \ y, incy, \ cntx, \ NULL \ ); \ } \ else \ { \ /* y = beta * y; */ \ PASTEMAC2(ch,scalv,BLIS_TAPI_EX_SUF) \ ( \ BLIS_NO_CONJUGATE, \ m, \ beta, \ y, incy, \ cntx, \ NULL \ ); \ } \ \ PASTECH(ch,dotxaxpyf_ker_ft) kfp_xf; \ \ /* Query the context for the kernel function pointer and fusing factor. */ \ kfp_xf = bli_cntx_get_l1f_ker_dt( dt, BLIS_DOTXAXPYF_KER, cntx ); \ b_fuse = bli_cntx_get_blksz_def_dt( dt, BLIS_XF, cntx ); \ \ for ( i = 0; i < m; i += f ) \ { \ f = bli_determine_blocksize_dim_f( i, m, b_fuse ); \ n_behind = i; \ A10 = a + (i )*rs_at + (0 )*cs_at; \ A11 = a + (i )*rs_at + (i )*cs_at; \ x0 = x + (0 )*incx; \ x1 = x + (i )*incx; \ y0 = y + (0 )*incy; \ y1 = y + (i )*incy; \ \ /* y1 = y1 + alpha * A10 * x0; (dotxf) */ \ /* y0 = y0 + alpha * A10' * x1; (axpyf) */ \ kfp_xf \ ( \ conj0, \ conj1, \ conjx, \ conjx, \ n_behind, \ f, \ alpha, \ A10, cs_at, rs_at, \ x0, incx, \ x1, incx, \ one, \ y1, incy, \ y0, incy, \ cntx \ ); \ \ /* y1 = y1 + alpha * A11 * x1; (variant 4) */ \ for ( k = 0; k < f; ++k ) \ { \ f_behind = k; \ f_ahead = f - k - 1; \ a10t = A11 + (k )*rs_at + (0 )*cs_at; \ alpha11 = A11 + (k )*rs_at + (k )*cs_at; \ a21 = A11 + (k+1)*rs_at + (k )*cs_at; \ chi11 = x1 + (k )*incx; \ y01 = y1 + (0 )*incy; \ psi11 = y1 + (k )*incy; \ y21 = y1 + (k+1)*incy; \ \ /* y01 = y01 + alpha * a10t' * chi11; */ \ PASTEMAC(ch,copycjs)( conjx, *chi11, conjx_chi11 ); \ PASTEMAC(ch,scal2s)( *alpha, conjx_chi11, alpha_chi11 ); \ if ( bli_is_conj( conj1 ) ) \ { \ for ( j = 0; j < f_behind; ++j ) \ PASTEMAC(ch,axpyjs)( alpha_chi11, *(a10t + j*cs_at), *(y01 + j*incy) ); \ } \ else \ { \ for ( j = 0; j < f_behind; ++j ) \ PASTEMAC(ch,axpys)( alpha_chi11, *(a10t + j*cs_at), *(y01 + j*incy) ); \ } \ \ /* For hemv, explicitly set the imaginary component of alpha11 to zero. */ \ PASTEMAC(ch,copycjs)( conja, *alpha11, alpha11_temp ); \ if ( bli_is_conj( conjh ) ) \ PASTEMAC(ch,seti0s)( alpha11_temp ); \ \ /* psi11 = psi11 + alpha * alpha11 * chi11; */ \ PASTEMAC(ch,axpys)( alpha_chi11, alpha11_temp, *psi11 ); \ \ /* y21 = y21 + alpha * a21 * chi11; */ \ if ( bli_is_conj( conj0 ) ) \ { \ for ( j = 0; j < f_ahead; ++j ) \ PASTEMAC(ch,axpyjs)( alpha_chi11, *(a21 + j*rs_at), *(y21 + j*incy) ); \ } \ else \ { \ for ( j = 0; j < f_ahead; ++j ) \ PASTEMAC(ch,axpys)( alpha_chi11, *(a21 + j*rs_at), *(y21 + j*incy) ); \ } \ } \ } \ } INSERT_GENTFUNC_BASIC0( hemv_unf_var1 ) blis-0.9.0/frame/2/hemv/bli_hemv_unf_var1a.c000066400000000000000000000111671422157504600205520ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ uplo_t uplo, \ conj_t conja, \ conj_t conjx, \ conj_t conjh, \ dim_t m, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* x, inc_t incx, \ ctype* beta, \ ctype* y, inc_t incy, \ cntx_t* cntx \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ ctype* zero = PASTEMAC(ch,0); \ ctype* a10t; \ ctype* alpha11; \ ctype* x0; \ ctype* chi1; \ ctype* y0; \ ctype* psi1; \ ctype rho; \ ctype conjx_chi1; \ ctype alpha_chi1; \ ctype alpha11_temp; \ dim_t i; \ dim_t n_behind; \ inc_t rs_at, cs_at; \ conj_t conj0, conj1; \ \ /* The algorithm will be expressed in terms of the lower triangular case; the upper triangular case is supported by swapping the row and column strides of A and toggling some conj parameters. */ \ if ( bli_is_lower( uplo ) ) \ { \ rs_at = rs_a; \ cs_at = cs_a; \ \ conj0 = conja; \ conj1 = bli_apply_conj( conjh, conja ); \ } \ else /* if ( bli_is_upper( uplo ) ) */ \ { \ rs_at = cs_a; \ cs_at = rs_a; \ \ conj0 = bli_apply_conj( conjh, conja ); \ conj1 = conja; \ } \ \ /* If beta is zero, use setv. Otherwise, scale by beta. */ \ if ( PASTEMAC(ch,eq0)( *beta ) ) \ { \ /* y = 0; */ \ PASTEMAC2(ch,setv,BLIS_TAPI_EX_SUF) \ ( \ BLIS_NO_CONJUGATE, \ m, \ zero, \ y, incy, \ cntx, \ NULL \ ); \ } \ else \ { \ /* y = beta * y; */ \ PASTEMAC2(ch,scalv,BLIS_TAPI_EX_SUF) \ ( \ BLIS_NO_CONJUGATE, \ m, \ beta, \ y, incy, \ cntx, \ NULL \ ); \ } \ \ PASTECH(ch,dotaxpyv_ker_ft) kfp_vf; \ \ /* Query the context for the kernel function pointer. */ \ kfp_vf = bli_cntx_get_l1f_ker_dt( dt, BLIS_DOTAXPYV_KER, cntx ); \ \ for ( i = 0; i < m; ++i ) \ { \ n_behind = i; \ a10t = a + (i )*rs_at + (0 )*cs_at; \ alpha11 = a + (i )*rs_at + (i )*cs_at; \ x0 = x + (0 )*incx; \ chi1 = x + (i )*incx; \ y0 = y + (0 )*incy; \ psi1 = y + (i )*incy; \ \ /* Apply conjx to chi1 and and scale by alpha. */ \ PASTEMAC(ch,copycjs)( conjx, *chi1, conjx_chi1 ); \ PASTEMAC(ch,scal2s)( *alpha, conjx_chi1, alpha_chi1 ); \ \ /* psi1 = psi1 + alpha * a10t * x0; (dotv) */ \ /* y0 = y0 + alpha * a10t' * chi1; (axpyv) */ \ kfp_vf \ ( \ conj0, \ conj1, \ conjx, \ n_behind, \ &alpha_chi1, \ a10t, cs_at, \ x0, incx, \ &rho, \ y0, incy, \ cntx \ ); \ PASTEMAC(ch,axpys)( *alpha, rho, *psi1 ); \ \ /* For hemv, explicitly set the imaginary component of alpha11 to zero. */ \ PASTEMAC(ch,copycjs)( conja, *alpha11, alpha11_temp ); \ if ( bli_is_conj( conjh ) ) \ PASTEMAC(ch,seti0s)( alpha11_temp ); \ \ /* psi1 = psi1 + alpha * alpha11 * chi1; */ \ PASTEMAC(ch,axpys)( alpha_chi1, alpha11_temp, *psi1 ); \ \ } \ } INSERT_GENTFUNC_BASIC0( hemv_unf_var1a ) blis-0.9.0/frame/2/hemv/bli_hemv_unf_var3.c000066400000000000000000000140111422157504600204020ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ uplo_t uplo, \ conj_t conja, \ conj_t conjx, \ conj_t conjh, \ dim_t m, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* x, inc_t incx, \ ctype* beta, \ ctype* y, inc_t incy, \ cntx_t* cntx \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ ctype* one = PASTEMAC(ch,1); \ ctype* zero = PASTEMAC(ch,0); \ ctype* A11; \ ctype* A21; \ ctype* a10t; \ ctype* alpha11; \ ctype* a21; \ ctype* x1; \ ctype* x2; \ ctype* chi11; \ ctype* y1; \ ctype* y2; \ ctype* y01; \ ctype* psi11; \ ctype* y21; \ ctype conjx_chi11; \ ctype alpha_chi11; \ ctype alpha11_temp; \ dim_t i, k, j; \ dim_t b_fuse, f; \ dim_t n_ahead; \ dim_t f_ahead, f_behind; \ inc_t rs_at, cs_at; \ conj_t conj0, conj1; \ \ /* The algorithm will be expressed in terms of the lower triangular case; the upper triangular case is supported by swapping the row and column strides of A and toggling some conj parameters. */ \ if ( bli_is_lower( uplo ) ) \ { \ rs_at = rs_a; \ cs_at = cs_a; \ \ conj0 = bli_apply_conj( conjh, conja ); \ conj1 = conja; \ } \ else /* if ( bli_is_upper( uplo ) ) */ \ { \ rs_at = cs_a; \ cs_at = rs_a; \ \ conj0 = conja; \ conj1 = bli_apply_conj( conjh, conja ); \ } \ \ /* If beta is zero, use setv. Otherwise, scale by beta. */ \ if ( PASTEMAC(ch,eq0)( *beta ) ) \ { \ /* y = 0; */ \ PASTEMAC2(ch,setv,BLIS_TAPI_EX_SUF) \ ( \ BLIS_NO_CONJUGATE, \ m, \ zero, \ y, incy, \ cntx, \ NULL \ ); \ } \ else \ { \ /* y = beta * y; */ \ PASTEMAC2(ch,scalv,BLIS_TAPI_EX_SUF) \ ( \ BLIS_NO_CONJUGATE, \ m, \ beta, \ y, incy, \ cntx, \ NULL \ ); \ } \ \ PASTECH(ch,dotxaxpyf_ker_ft) kfp_xf; \ \ /* Query the context for the kernel function pointer and fusing factor. */ \ kfp_xf = bli_cntx_get_l1f_ker_dt( dt, BLIS_DOTXAXPYF_KER, cntx ); \ b_fuse = bli_cntx_get_blksz_def_dt( dt, BLIS_XF, cntx ); \ \ for ( i = 0; i < m; i += f ) \ { \ f = bli_determine_blocksize_dim_f( i, m, b_fuse ); \ n_ahead = m - i - f; \ A11 = a + (i )*rs_at + (i )*cs_at; \ A21 = a + (i+f)*rs_at + (i )*cs_at; \ x1 = x + (i )*incx; \ x2 = x + (i+f)*incx; \ y1 = y + (i )*incy; \ y2 = y + (i+f)*incy; \ \ /* y1 = y1 + alpha * A11 * x1; (variant 4) */ \ for ( k = 0; k < f; ++k ) \ { \ f_behind = k; \ f_ahead = f - k - 1; \ a10t = A11 + (k )*rs_at + (0 )*cs_at; \ alpha11 = A11 + (k )*rs_at + (k )*cs_at; \ a21 = A11 + (k+1)*rs_at + (k )*cs_at; \ chi11 = x1 + (k )*incx; \ y01 = y1 + (0 )*incy; \ psi11 = y1 + (k )*incy; \ y21 = y1 + (k+1)*incy; \ \ /* y01 = y01 + alpha * a10t' * chi11; */ \ PASTEMAC(ch,copycjs)( conjx, *chi11, conjx_chi11 ); \ PASTEMAC(ch,scal2s)( *alpha, conjx_chi11, alpha_chi11 ); \ if ( bli_is_conj( conj0 ) ) \ { \ for ( j = 0; j < f_behind; ++j ) \ PASTEMAC(ch,axpyjs)( alpha_chi11, *(a10t + j*cs_at), *(y01 + j*incy) ); \ } \ else \ { \ for ( j = 0; j < f_behind; ++j ) \ PASTEMAC(ch,axpys)( alpha_chi11, *(a10t + j*cs_at), *(y01 + j*incy) ); \ } \ \ /* For hemv, explicitly set the imaginary component of alpha11 to zero. */ \ PASTEMAC(ch,copycjs)( conja, *alpha11, alpha11_temp ); \ if ( bli_is_conj( conjh ) ) \ PASTEMAC(ch,seti0s)( alpha11_temp ); \ \ /* psi11 = psi11 + alpha * alpha11 * chi11; */ \ PASTEMAC(ch,axpys)( alpha_chi11, alpha11_temp, *psi11 ); \ \ /* y21 = y21 + alpha * a21 * chi11; */ \ if ( bli_is_conj( conj1 ) ) \ { \ for ( j = 0; j < f_ahead; ++j ) \ PASTEMAC(ch,axpyjs)( alpha_chi11, *(a21 + j*rs_at), *(y21 + j*incy) ); \ } \ else \ { \ for ( j = 0; j < f_ahead; ++j ) \ PASTEMAC(ch,axpys)( alpha_chi11, *(a21 + j*rs_at), *(y21 + j*incy) ); \ } \ } \ \ /* y1 = y1 + alpha * A21' * x2; (dotxf) */ \ /* y2 = y2 + alpha * A21 * x1; (axpyf) */ \ kfp_xf \ ( \ conj0, \ conj1, \ conjx, \ conjx, \ n_ahead, \ f, \ alpha, \ A21, rs_at, cs_at, \ x2, incx, \ x1, incx, \ one, \ y1, incy, \ y2, incy, \ cntx \ ); \ } \ } INSERT_GENTFUNC_BASIC0( hemv_unf_var3 ) blis-0.9.0/frame/2/hemv/bli_hemv_unf_var3a.c000066400000000000000000000111631422157504600205500ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ uplo_t uplo, \ conj_t conja, \ conj_t conjx, \ conj_t conjh, \ dim_t m, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* x, inc_t incx, \ ctype* beta, \ ctype* y, inc_t incy, \ cntx_t* cntx \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ ctype* zero = PASTEMAC(ch,0); \ ctype* alpha11; \ ctype* a21; \ ctype* chi1; \ ctype* x2; \ ctype* psi1; \ ctype* y2; \ ctype rho; \ ctype conjx_chi1; \ ctype alpha_chi1; \ ctype alpha11_temp; \ dim_t i; \ dim_t n_ahead; \ inc_t rs_at, cs_at; \ conj_t conj0, conj1; \ \ /* The algorithm will be expressed in terms of the lower triangular case; the upper triangular case is supported by swapping the row and column strides of A and toggling some conj parameters. */ \ if ( bli_is_lower( uplo ) ) \ { \ rs_at = rs_a; \ cs_at = cs_a; \ \ conj0 = bli_apply_conj( conjh, conja ); \ conj1 = conja; \ } \ else /* if ( bli_is_upper( uplo ) ) */ \ { \ rs_at = cs_a; \ cs_at = rs_a; \ \ conj0 = conja; \ conj1 = bli_apply_conj( conjh, conja ); \ } \ \ /* If beta is zero, use setv. Otherwise, scale by beta. */ \ if ( PASTEMAC(ch,eq0)( *beta ) ) \ { \ /* y = 0; */ \ PASTEMAC2(ch,setv,BLIS_TAPI_EX_SUF) \ ( \ BLIS_NO_CONJUGATE, \ m, \ zero, \ y, incy, \ cntx, \ NULL \ ); \ } \ else \ { \ /* y = beta * y; */ \ PASTEMAC2(ch,scalv,BLIS_TAPI_EX_SUF) \ ( \ BLIS_NO_CONJUGATE, \ m, \ beta, \ y, incy, \ cntx, \ NULL \ ); \ } \ \ PASTECH(ch,dotaxpyv_ker_ft) kfp_vf; \ \ /* Query the context for the kernel function pointer. */ \ kfp_vf = bli_cntx_get_l1f_ker_dt( dt, BLIS_DOTAXPYV_KER, cntx ); \ \ for ( i = 0; i < m; ++i ) \ { \ n_ahead = m - i - 1; \ alpha11 = a + (i )*rs_at + (i )*cs_at; \ a21 = a + (i+1)*rs_at + (i )*cs_at; \ chi1 = x + (i )*incx; \ x2 = x + (i+1)*incx; \ psi1 = y + (i )*incy; \ y2 = y + (i+1)*incy; \ \ /* For hemv, explicitly set the imaginary component of alpha11 to zero. */ \ PASTEMAC(ch,copycjs)( conja, *alpha11, alpha11_temp ); \ if ( bli_is_conj( conjh ) ) \ PASTEMAC(ch,seti0s)( alpha11_temp ); \ \ /* Apply conjx to chi1 and and scale by alpha. */ \ PASTEMAC(ch,copycjs)( conjx, *chi1, conjx_chi1 ); \ PASTEMAC(ch,scal2s)( *alpha, conjx_chi1, alpha_chi1 ); \ \ /* psi1 = psi1 + alpha * alpha11 * chi1; */ \ PASTEMAC(ch,axpys)( alpha_chi1, alpha11_temp, *psi1 ); \ \ /* psi1 = psi1 + alpha * a21' * x2; (dotv) */ \ /* y2 = y2 + alpha * a21 * chi1; (axpyv) */ \ kfp_vf \ ( \ conj0, \ conj1, \ conjx, \ n_ahead, \ &alpha_chi1, \ a21, rs_at, \ x2, incx, \ &rho, \ y2, incy, \ cntx \ ); \ PASTEMAC(ch,axpys)( *alpha, rho, *psi1 ); \ } \ } INSERT_GENTFUNC_BASIC0( hemv_unf_var3a ) blis-0.9.0/frame/2/hemv/bli_hemv_var.h000066400000000000000000000060041422157504600174570ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype object-based interfaces. // #undef GENPROT #define GENPROT( opname ) \ \ void PASTEMAC0(opname) \ ( \ conj_t conjh, \ obj_t* alpha, \ obj_t* a, \ obj_t* x, \ obj_t* beta, \ obj_t* y, \ cntx_t* cntx, \ cntl_t* cntl \ ); GENPROT( hemv_blk_var1 ) GENPROT( hemv_blk_var2 ) GENPROT( hemv_blk_var3 ) GENPROT( hemv_blk_var4 ) GENPROT( hemv_unb_var1 ) GENPROT( hemv_unb_var2 ) GENPROT( hemv_unb_var3 ) GENPROT( hemv_unb_var4 ) GENPROT( hemv_unf_var1 ) GENPROT( hemv_unf_var3 ) GENPROT( hemv_unf_var1a ) GENPROT( hemv_unf_var3a ) // // Prototype BLAS-like interfaces with typed operands. // #undef GENTPROT #define GENTPROT( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ uplo_t uplo, \ conj_t conja, \ conj_t conjx, \ conj_t conjh, \ dim_t m, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* x, inc_t incx, \ ctype* beta, \ ctype* y, inc_t incy, \ cntx_t* cntx \ ); INSERT_GENTPROT_BASIC0( hemv_unb_var1 ) INSERT_GENTPROT_BASIC0( hemv_unb_var2 ) INSERT_GENTPROT_BASIC0( hemv_unb_var3 ) INSERT_GENTPROT_BASIC0( hemv_unb_var4 ) INSERT_GENTPROT_BASIC0( hemv_unf_var1 ) INSERT_GENTPROT_BASIC0( hemv_unf_var3 ) INSERT_GENTPROT_BASIC0( hemv_unf_var1a ) INSERT_GENTPROT_BASIC0( hemv_unf_var3a ) blis-0.9.0/frame/2/hemv/bli_hemv_var_oapi.c000066400000000000000000000064421422157504600204700ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENFRONT #define GENFRONT( opname, varname ) \ \ void PASTEMAC0(varname) \ ( \ conj_t conjh, \ obj_t* alpha, \ obj_t* a, \ obj_t* x, \ obj_t* beta, \ obj_t* y, \ cntx_t* cntx, \ cntl_t* cntl \ ) \ { \ bli_init_once(); \ \ num_t dt = bli_obj_dt( a ); \ \ uplo_t uplo = bli_obj_uplo( a ); \ conj_t conja = bli_obj_conj_status( a ); \ conj_t conjx = bli_obj_conj_status( x ); \ \ dim_t m = bli_obj_length( a ); \ \ void* buf_a = bli_obj_buffer_at_off( a ); \ inc_t rs_a = bli_obj_row_stride( a ); \ inc_t cs_a = bli_obj_col_stride( a ); \ \ void* buf_x = bli_obj_buffer_at_off( x ); \ inc_t incx = bli_obj_vector_inc( x ); \ \ void* buf_y = bli_obj_buffer_at_off( y ); \ inc_t incy = bli_obj_vector_inc( y ); \ \ void* buf_alpha = bli_obj_buffer_for_1x1( dt, alpha ); \ void* buf_beta = bli_obj_buffer_for_1x1( dt, beta ); \ \ /* Query a type-specific function pointer, except one that uses void* for function arguments instead of typed pointers. */ \ PASTECH2(opname,_unb,_vft) f = \ PASTEMAC(varname,_qfp)( dt ); \ \ f \ ( \ uplo, \ conja, \ conjx, \ conjh, \ m, \ buf_alpha, \ buf_a, rs_a, cs_a, \ buf_x, incx, \ buf_beta, \ buf_y, incy, \ cntx \ ); \ } \ GENFRONT( hemv, hemv_unb_var1 ) GENFRONT( hemv, hemv_unb_var2 ) GENFRONT( hemv, hemv_unb_var3 ) GENFRONT( hemv, hemv_unb_var4 ) GENFRONT( hemv, hemv_unf_var1 ) GENFRONT( hemv, hemv_unf_var3 ) GENFRONT( hemv, hemv_unf_var1a ) GENFRONT( hemv, hemv_unf_var3a ) blis-0.9.0/frame/2/hemv/other/000077500000000000000000000000001422157504600157725ustar00rootroot00000000000000blis-0.9.0/frame/2/hemv/other/bli_hemv_blk_var1.c000066400000000000000000000133101422157504600215020ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_hemv_blk_var1( conj_t conjh, obj_t* alpha, obj_t* a, obj_t* x, obj_t* beta, obj_t* y, cntx_t* cntx, hemv_t* cntl ) { obj_t a11, a11_pack; obj_t a10; obj_t x1, x1_pack; obj_t x0; obj_t y1, y1_pack; obj_t y0; dim_t mn; dim_t ij; dim_t b_alg; // Even though this blocked algorithm is expressed only in terms of the // lower triangular case, the upper triangular case is still supported: // when bli_acquire_mpart_tl2br() is passed a matrix that is stored in // in the upper triangle, and the requested subpartition resides in the // lower triangle (as is the case for this algorithm), the routine fills // the request as if the caller had actually requested the corresponding // "mirror" subpartition in the upper triangle, except that it marks the // subpartition for transposition (and conjugation). // Initialize objects for packing. bli_obj_init_pack( &a11_pack ); bli_obj_init_pack( &x1_pack ); bli_obj_init_pack( &y1_pack ); // Query dimension. mn = bli_obj_length( a ); // y = beta * y; bli_scalv_int( beta, y, cntx, bli_cntl_sub_scalv( cntl ) ); // Partition diagonally. for ( ij = 0; ij < mn; ij += b_alg ) { // Determine the current algorithmic blocksize. b_alg = bli_determine_blocksize_f( ij, mn, a, bli_cntl_bszid( cntl ), cntx ); // Acquire partitions for A11, A10, x1, x0, y1, and y0. bli_acquire_mpart_tl2br( BLIS_SUBPART11, ij, b_alg, a, &a11 ); bli_acquire_mpart_tl2br( BLIS_SUBPART10, ij, b_alg, a, &a10 ); bli_acquire_vpart_f2b( BLIS_SUBPART1, ij, b_alg, x, &x1 ); bli_acquire_vpart_f2b( BLIS_SUBPART0, ij, b_alg, x, &x0 ); bli_acquire_vpart_f2b( BLIS_SUBPART1, ij, b_alg, y, &y1 ); bli_acquire_vpart_f2b( BLIS_SUBPART0, ij, b_alg, y, &y0 ); // Initialize objects for packing A11, x1, and y1 (if needed). bli_packm_init( &a11, &a11_pack, cntx, bli_cntl_sub_packm_a11( cntl ) ); bli_packv_init( &x1, &x1_pack, cntx, bli_cntl_sub_packv_x1( cntl ) ); bli_packv_init( &y1, &y1_pack, cntx, bli_cntl_sub_packv_y1( cntl ) ); // Copy/pack A11, x1, y1 (if needed). bli_packm_int( &a11, &a11_pack, cntx, bli_cntl_sub_packm_a11( cntl ), &BLIS_PACKM_SINGLE_THREADED ); bli_packv_int( &x1, &x1_pack, cntx, bli_cntl_sub_packv_x1( cntl ) ); bli_packv_int( &y1, &y1_pack, cntx, bli_cntl_sub_packv_y1( cntl ) ); // y0 = y0 + alpha * A10' * x1; bli_gemv_int( bli_apply_conj( conjh, BLIS_TRANSPOSE ), BLIS_NO_CONJUGATE, alpha, &a10, &x1_pack, &BLIS_ONE, &y0, cntx, bli_cntl_sub_gemv_t_rp( cntl ) ); // y1 = y1 + alpha * A11 * x1; bli_hemv_int( conjh, alpha, &a11_pack, &x1_pack, &BLIS_ONE, &y1_pack, cntx, bli_cntl_sub_hemv( cntl ) ); // y1 = y1 + alpha * A10 * x0; bli_gemv_int( BLIS_NO_TRANSPOSE, BLIS_NO_CONJUGATE, alpha, &a10, &x0, &BLIS_ONE, &y1_pack, cntx, bli_cntl_sub_gemv_n_rp( cntl ) ); // Copy/unpack y1 (if y1 was packed). bli_unpackv_int( &y1_pack, &y1, cntx, bli_cntl_sub_unpackv_y1( cntl ) ); } // If any packing buffers were acquired within packm, release them back // to the memory manager. bli_packm_release( &a11_pack, bli_cntl_sub_packm_a11( cntl ) ); bli_packv_release( &x1_pack, bli_cntl_sub_packv_x1( cntl ) ); bli_packv_release( &y1_pack, bli_cntl_sub_packv_y1( cntl ) ); } blis-0.9.0/frame/2/hemv/other/bli_hemv_blk_var2.c000066400000000000000000000134731422157504600215150ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_hemv_blk_var2( conj_t conjh, obj_t* alpha, obj_t* a, obj_t* x, obj_t* beta, obj_t* y, cntx_t* cntx, hemv_t* cntl ) { obj_t a11, a11_pack; obj_t a10; obj_t a21; obj_t x1, x1_pack; obj_t x0; obj_t x2; obj_t y1, y1_pack; dim_t mn; dim_t ij; dim_t b_alg; // Even though this blocked algorithm is expressed only in terms of the // lower triangular case, the upper triangular case is still supported: // when bli_acquire_mpart_tl2br() is passed a matrix that is stored in // in the upper triangle, and the requested subpartition resides in the // lower triangle (as is the case for this algorithm), the routine fills // the request as if the caller had actually requested the corresponding // "mirror" subpartition in the upper triangle, except that it marks the // subpartition for transposition (and conjugation). // Initialize objects for packing. bli_obj_init_pack( &a11_pack ); bli_obj_init_pack( &x1_pack ); bli_obj_init_pack( &y1_pack ); // Query dimension. mn = bli_obj_length( a ); // y = beta * y; bli_scalv_int( beta, y, cntx, bli_cntl_sub_scalv( cntl ) ); // Partition diagonally. for ( ij = 0; ij < mn; ij += b_alg ) { // Determine the current algorithmic blocksize. b_alg = bli_determine_blocksize_f( ij, mn, a, bli_cntl_bszid( cntl ), cntx ); // Acquire partitions for A11, A10, A21, x1, x0, x2, y1, and y0. bli_acquire_mpart_tl2br( BLIS_SUBPART11, ij, b_alg, a, &a11 ); bli_acquire_mpart_tl2br( BLIS_SUBPART10, ij, b_alg, a, &a10 ); bli_acquire_mpart_tl2br( BLIS_SUBPART21, ij, b_alg, a, &a21 ); bli_acquire_vpart_f2b( BLIS_SUBPART1, ij, b_alg, x, &x1 ); bli_acquire_vpart_f2b( BLIS_SUBPART0, ij, b_alg, x, &x0 ); bli_acquire_vpart_f2b( BLIS_SUBPART2, ij, b_alg, x, &x2 ); bli_acquire_vpart_f2b( BLIS_SUBPART1, ij, b_alg, y, &y1 ); // Initialize objects for packing A11, x1, and y1 (if needed). bli_packm_init( &a11, &a11_pack, cntx, bli_cntl_sub_packm_a11( cntl ) ); bli_packv_init( &x1, &x1_pack, cntx, bli_cntl_sub_packv_x1( cntl ) ); bli_packv_init( &y1, &y1_pack, cntx, bli_cntl_sub_packv_y1( cntl ) ); // Copy/pack A11, x1, y1 (if needed). bli_packm_int( &a11, &a11_pack, cntx, bli_cntl_sub_packm_a11( cntl ), &BLIS_PACKM_SINGLE_THREADED ); bli_packv_int( &x1, &x1_pack, cntx, bli_cntl_sub_packv_x1( cntl ) ); bli_packv_int( &y1, &y1_pack, cntx, bli_cntl_sub_packv_y1( cntl ) ); // y1 = y1 + alpha * A10 * x0; bli_gemv_int( BLIS_NO_TRANSPOSE, BLIS_NO_CONJUGATE, alpha, &a10, &x0, &BLIS_ONE, &y1_pack, cntx, bli_cntl_sub_gemv_n_rp( cntl ) ); // y1 = y1 + alpha * A11 * x1; bli_hemv_int( conjh, alpha, &a11_pack, &x1_pack, &BLIS_ONE, &y1_pack, cntx, bli_cntl_sub_hemv( cntl ) ); // y1 = y1 + alpha * A21' * x2; bli_gemv_int( bli_apply_conj( conjh, BLIS_TRANSPOSE ), BLIS_NO_CONJUGATE, alpha, &a21, &x2, &BLIS_ONE, &y1_pack, cntx, bli_cntl_sub_gemv_t_cp( cntl ) ); // Copy/unpack y1 (if y1 was packed). bli_unpackv_int( &y1_pack, &y1, cntx, bli_cntl_sub_unpackv_y1( cntl ) ); } // If any packing buffers were acquired within packm, release them back // to the memory manager. bli_packm_release( &a11_pack, bli_cntl_sub_packm_a11( cntl ) ); bli_packv_release( &x1_pack, bli_cntl_sub_packv_x1( cntl ) ); bli_packv_release( &y1_pack, bli_cntl_sub_packv_y1( cntl ) ); } blis-0.9.0/frame/2/hemv/other/bli_hemv_blk_var3.c000066400000000000000000000133101422157504600215040ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_hemv_blk_var3( conj_t conjh, obj_t* alpha, obj_t* a, obj_t* x, obj_t* beta, obj_t* y, cntx_t* cntx, hemv_t* cntl ) { obj_t a11, a11_pack; obj_t a21; obj_t x1, x1_pack; obj_t x2; obj_t y1, y1_pack; obj_t y2; dim_t mn; dim_t ij; dim_t b_alg; // Even though this blocked algorithm is expressed only in terms of the // lower triangular case, the upper triangular case is still supported: // when bli_acquire_mpart_tl2br() is passed a matrix that is stored in // in the upper triangle, and the requested subpartition resides in the // lower triangle (as is the case for this algorithm), the routine fills // the request as if the caller had actually requested the corresponding // "mirror" subpartition in the upper triangle, except that it marks the // subpartition for transposition (and conjugation). // Initialize objects for packing. bli_obj_init_pack( &a11_pack ); bli_obj_init_pack( &x1_pack ); bli_obj_init_pack( &y1_pack ); // Query dimension. mn = bli_obj_length( a ); // y = beta * y; bli_scalv_int( beta, y, cntx, bli_cntl_sub_scalv( cntl ) ); // Partition diagonally. for ( ij = 0; ij < mn; ij += b_alg ) { // Determine the current algorithmic blocksize. b_alg = bli_determine_blocksize_f( ij, mn, a, bli_cntl_bszid( cntl ), cntx ); // Acquire partitions for A11, A10, x1, x0, y1, and y0. bli_acquire_mpart_tl2br( BLIS_SUBPART11, ij, b_alg, a, &a11 ); bli_acquire_mpart_tl2br( BLIS_SUBPART21, ij, b_alg, a, &a21 ); bli_acquire_vpart_f2b( BLIS_SUBPART1, ij, b_alg, x, &x1 ); bli_acquire_vpart_f2b( BLIS_SUBPART2, ij, b_alg, x, &x2 ); bli_acquire_vpart_f2b( BLIS_SUBPART1, ij, b_alg, y, &y1 ); bli_acquire_vpart_f2b( BLIS_SUBPART2, ij, b_alg, y, &y2 ); // Initialize objects for packing A11, x1, and y1 (if needed). bli_packm_init( &a11, &a11_pack, cntx, bli_cntl_sub_packm_a11( cntl ) ); bli_packv_init( &x1, &x1_pack, cntx, bli_cntl_sub_packv_x1( cntl ) ); bli_packv_init( &y1, &y1_pack, cntx, bli_cntl_sub_packv_y1( cntl ) ); // Copy/pack A11, x1, y1 (if needed). bli_packm_int( &a11, &a11_pack, cntx, bli_cntl_sub_packm_a11( cntl ), &BLIS_PACKM_SINGLE_THREADED ); bli_packv_int( &x1, &x1_pack, cntx, bli_cntl_sub_packv_x1( cntl ) ); bli_packv_int( &y1, &y1_pack, cntx, bli_cntl_sub_packv_y1( cntl ) ); // y1 = y1 + alpha * A21' * x2; bli_gemv_int( bli_apply_conj( conjh, BLIS_TRANSPOSE ), BLIS_NO_CONJUGATE, alpha, &a21, &x2, &BLIS_ONE, &y1_pack, cntx, bli_cntl_sub_gemv_t_cp( cntl ) ); // y1 = y1 + alpha * A11 * x1; bli_hemv_int( conjh, alpha, &a11_pack, &x1_pack, &BLIS_ONE, &y1_pack, cntx, bli_cntl_sub_hemv( cntl ) ); // y2 = y2 + alpha * A21 * x1; bli_gemv_int( BLIS_NO_TRANSPOSE, BLIS_NO_CONJUGATE, alpha, &a21, &x1_pack, &BLIS_ONE, &y2, cntx, bli_cntl_sub_gemv_n_cp( cntl ) ); // Copy/unpack y1 (if y1 was packed). bli_unpackv_int( &y1_pack, &y1, cntx, bli_cntl_sub_unpackv_y1( cntl ) ); } // If any packing buffers were acquired within packm, release them back // to the memory manager. bli_packm_release( &a11_pack, bli_cntl_sub_packm_a11( cntl ) ); bli_packv_release( &x1_pack, bli_cntl_sub_packv_x1( cntl ) ); bli_packv_release( &y1_pack, bli_cntl_sub_packv_y1( cntl ) ); } blis-0.9.0/frame/2/hemv/other/bli_hemv_blk_var4.c000066400000000000000000000134671422157504600215220ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_hemv_blk_var4( conj_t conjh, obj_t* alpha, obj_t* a, obj_t* x, obj_t* beta, obj_t* y, cntx_t* cntx, hemv_t* cntl ) { obj_t a11, a11_pack; obj_t a10; obj_t a21; obj_t x1, x1_pack; obj_t y1, y1_pack; obj_t y0; obj_t y2; dim_t mn; dim_t ij; dim_t b_alg; // Even though this blocked algorithm is expressed only in terms of the // lower triangular case, the upper triangular case is still supported: // when bli_acquire_mpart_tl2br() is passed a matrix that is stored in // in the upper triangle, and the requested subpartition resides in the // lower triangle (as is the case for this algorithm), the routine fills // the request as if the caller had actually requested the corresponding // "mirror" subpartition in the upper triangle, except that it marks the // subpartition for transposition (and conjugation). // Initialize objects for packing. bli_obj_init_pack( &a11_pack ); bli_obj_init_pack( &x1_pack ); bli_obj_init_pack( &y1_pack ); // Query dimension. mn = bli_obj_length( a ); // y = beta * y; bli_scalv_int( beta, y, cntx, bli_cntl_sub_scalv( cntl ) ); // Partition diagonally. for ( ij = 0; ij < mn; ij += b_alg ) { // Determine the current algorithmic blocksize. b_alg = bli_determine_blocksize_f( ij, mn, a, bli_cntl_bszid( cntl ), cntx ); // Acquire partitions for A11, A10, A21, x1, y1, y0, and y2. bli_acquire_mpart_tl2br( BLIS_SUBPART11, ij, b_alg, a, &a11 ); bli_acquire_mpart_tl2br( BLIS_SUBPART10, ij, b_alg, a, &a10 ); bli_acquire_mpart_tl2br( BLIS_SUBPART21, ij, b_alg, a, &a21 ); bli_acquire_vpart_f2b( BLIS_SUBPART1, ij, b_alg, x, &x1 ); bli_acquire_vpart_f2b( BLIS_SUBPART1, ij, b_alg, y, &y1 ); bli_acquire_vpart_f2b( BLIS_SUBPART0, ij, b_alg, y, &y0 ); bli_acquire_vpart_f2b( BLIS_SUBPART2, ij, b_alg, y, &y2 ); // Initialize objects for packing A11, x1, and y1 (if needed). bli_packm_init( &a11, &a11_pack, cntx, bli_cntl_sub_packm_a11( cntl ) ); bli_packv_init( &x1, &x1_pack, cntx, bli_cntl_sub_packv_x1( cntl ) ); bli_packv_init( &y1, &y1_pack, cntx, bli_cntl_sub_packv_y1( cntl ) ); // Copy/pack A11, x1, y1 (if needed). bli_packm_int( &a11, &a11_pack, cntx, bli_cntl_sub_packm_a11( cntl ), &BLIS_PACKM_SINGLE_THREADED ); bli_packv_int( &x1, &x1_pack, cntx, bli_cntl_sub_packv_x1( cntl ) ); bli_packv_int( &y1, &y1_pack, cntx, bli_cntl_sub_packv_y1( cntl ) ); // y0 = y0 + alpha * A10' * x1; bli_gemv_int( bli_apply_conj( conjh, BLIS_TRANSPOSE ), BLIS_NO_CONJUGATE, alpha, &a10, &x1_pack, &BLIS_ONE, &y0, cntx, bli_cntl_sub_gemv_t_rp( cntl ) ); // y1 = y1 + alpha * A11 * x1; bli_hemv_int( conjh, alpha, &a11_pack, &x1_pack, &BLIS_ONE, &y1_pack, cntx, bli_cntl_sub_hemv( cntl ) ); // y2 = y2 + alpha * A21 * x1; bli_gemv_int( BLIS_NO_TRANSPOSE, BLIS_NO_CONJUGATE, alpha, &a21, &x1_pack, &BLIS_ONE, &y2, cntx, bli_cntl_sub_gemv_n_cp( cntl ) ); // Copy/unpack y1 (if y1 was packed). bli_unpackv_int( &y1_pack, &y1, cntx, bli_cntl_sub_unpackv_y1( cntl ) ); } // If any packing buffers were acquired within packm, release them back // to the memory manager. bli_packm_release( &a11_pack, bli_cntl_sub_packm_a11( cntl ) ); bli_packv_release( &x1_pack, bli_cntl_sub_packv_x1( cntl ) ); bli_packv_release( &y1_pack, bli_cntl_sub_packv_y1( cntl ) ); } blis-0.9.0/frame/2/hemv/other/bli_hemv_cntl.c000066400000000000000000000166441422157504600207560ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" extern scalv_t* scalv_cntl; extern packm_t* packm_cntl; extern packv_t* packv_cntl; extern unpackv_t* unpackv_cntl; extern gemv_t* gemv_cntl_rp_bs_dot; extern gemv_t* gemv_cntl_rp_bs_axpy; extern gemv_t* gemv_cntl_cp_bs_dot; extern gemv_t* gemv_cntl_cp_bs_axpy; hemv_t* hemv_cntl_bs_ke_lrow_ucol = NULL; hemv_t* hemv_cntl_bs_ke_lcol_urow = NULL; hemv_t* hemv_cntl_ge_lrow_ucol = NULL; hemv_t* hemv_cntl_ge_lcol_urow = NULL; void bli_hemv_cntl_init() { // Create control trees for the lowest-level kernels. These trees induce // operations on (presumably) relatively small block-subvector problems. hemv_cntl_bs_ke_lrow_ucol = bli_hemv_cntl_obj_create( BLIS_UNB_FUSED, BLIS_VARIANT1, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL ); hemv_cntl_bs_ke_lcol_urow = bli_hemv_cntl_obj_create( BLIS_UNB_FUSED, BLIS_VARIANT3, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL ); // Create control trees for generally large problems. Here, we choose a // variant that prioritizes keeping a subvector of y in cache. hemv_cntl_ge_lrow_ucol = bli_hemv_cntl_obj_create( BLIS_BLOCKED, BLIS_VARIANT2, BLIS_M2, scalv_cntl, // scale y up-front packm_cntl, // pack A11 (if needed) packv_cntl, // pack x1 (if needed) packv_cntl, // pack y1 (if needed) gemv_cntl_rp_bs_dot, // gemv_n_rp needed by var2 NULL, // gemv_n_cp not used by var2 NULL, // gemv_t_rp not used by var2 gemv_cntl_rp_bs_axpy, // gemv_t_cp needed by var2 hemv_cntl_bs_ke_lrow_ucol, unpackv_cntl ); // unpack y1 (if packed) hemv_cntl_ge_lcol_urow = bli_hemv_cntl_obj_create( BLIS_BLOCKED, BLIS_VARIANT2, BLIS_M2, scalv_cntl, // scale y up-front packm_cntl, // pack A11 (if needed) packv_cntl, // pack x1 (if needed) packv_cntl, // pack y1 (if needed) gemv_cntl_rp_bs_axpy, // gemv_n_rp needed by var2 NULL, // gemv_n_cp not used by var2 NULL, // gemv_t_rp not used by var2 gemv_cntl_rp_bs_dot, // gemv_t_cp needed by var2 hemv_cntl_bs_ke_lcol_urow, unpackv_cntl ); // unpack y1 (if packed) } void bli_hemv_cntl_finalize() { bli_cntl_free_node( hemv_cntl_bs_ke_lrow_ucol ); bli_cntl_free_node( hemv_cntl_bs_ke_lcol_urow ); bli_cntl_free_node( hemv_cntl_ge_lrow_ucol ); bli_cntl_free_node( hemv_cntl_ge_lcol_urow ); } hemv_t* bli_hemv_cntl_obj_create( impl_t impl_type, varnum_t var_num, bszid_t bszid, scalv_t* sub_scalv, packm_t* sub_packm_a11, packv_t* sub_packv_x1, packv_t* sub_packv_y1, gemv_t* sub_gemv_n_rp, gemv_t* sub_gemv_n_cp, gemv_t* sub_gemv_t_rp, gemv_t* sub_gemv_t_cp, hemv_t* sub_hemv, unpackv_t* sub_unpackv_y1 ) { hemv_t* cntl; cntl = ( hemv_t* ) bli_malloc_intl( sizeof(hemv_t) ); cntl->impl_type = impl_type; cntl->var_num = var_num; cntl->bszid = bszid; cntl->sub_scalv = sub_scalv; cntl->sub_packm_a11 = sub_packm_a11; cntl->sub_packv_x1 = sub_packv_x1; cntl->sub_packv_y1 = sub_packv_y1; cntl->sub_gemv_n_rp = sub_gemv_n_rp; cntl->sub_gemv_n_cp = sub_gemv_n_cp; cntl->sub_gemv_t_rp = sub_gemv_t_rp; cntl->sub_gemv_t_cp = sub_gemv_t_cp; cntl->sub_hemv = sub_hemv; cntl->sub_unpackv_y1 = sub_unpackv_y1; return cntl; } void bli_hemv_cntl_obj_init( hemv_t* cntl, impl_t impl_type, varnum_t var_num, bszid_t bszid, scalv_t* sub_scalv, packm_t* sub_packm_a11, packv_t* sub_packv_x1, packv_t* sub_packv_y1, gemv_t* sub_gemv_n_rp, gemv_t* sub_gemv_n_cp, gemv_t* sub_gemv_t_rp, gemv_t* sub_gemv_t_cp, hemv_t* sub_hemv, unpackv_t* sub_unpackv_y1 ) { cntl->impl_type = impl_type; cntl->var_num = var_num; cntl->bszid = bszid; cntl->sub_scalv = sub_scalv; cntl->sub_packm_a11 = sub_packm_a11; cntl->sub_packv_x1 = sub_packv_x1; cntl->sub_packv_y1 = sub_packv_y1; cntl->sub_gemv_n_rp = sub_gemv_n_rp; cntl->sub_gemv_n_cp = sub_gemv_n_cp; cntl->sub_gemv_t_rp = sub_gemv_t_rp; cntl->sub_gemv_t_cp = sub_gemv_t_cp; cntl->sub_hemv = sub_hemv; cntl->sub_unpackv_y1 = sub_unpackv_y1; } blis-0.9.0/frame/2/hemv/other/bli_hemv_cntl.h000066400000000000000000000072741422157504600207620ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ struct hemv_s { impl_t impl_type; varnum_t var_num; bszid_t bszid; struct scalv_s* sub_scalv; struct packm_s* sub_packm_a11; struct packv_s* sub_packv_x1; struct packv_s* sub_packv_y1; struct gemv_s* sub_gemv_n_rp; struct gemv_s* sub_gemv_n_cp; struct gemv_s* sub_gemv_t_rp; struct gemv_s* sub_gemv_t_cp; struct hemv_s* sub_hemv; struct unpackv_s* sub_unpackv_y1; }; typedef struct hemv_s hemv_t; #define bli_cntl_sub_hemv( cntl ) cntl->sub_hemv void bli_hemv_cntl_init( void ); void bli_hemv_cntl_finalize( void ); hemv_t* bli_hemv_cntl_obj_create( impl_t impl_type, varnum_t var_num, bszid_t bszid, scalv_t* sub_scalv, packm_t* sub_packm_a11, packv_t* sub_packv_x1, packv_t* sub_packv_y1, gemv_t* sub_gemv_n_rp, gemv_t* sub_gemv_n_cp, gemv_t* sub_gemv_t_rp, gemv_t* sub_gemv_t_cp, hemv_t* sub_hemv, unpackv_t* sub_unpackv_y1 ); void bli_hemv_cntl_obj_init( hemv_t* cntl, impl_t impl_type, varnum_t var_num, bszid_t bszid, scalv_t* sub_scalv, packm_t* sub_packm_a11, packv_t* sub_packv_x1, packv_t* sub_packv_y1, gemv_t* sub_gemv_n_rp, gemv_t* sub_gemv_n_cp, gemv_t* sub_gemv_t_rp, gemv_t* sub_gemv_t_cp, hemv_t* sub_hemv, unpackv_t* sub_unpackv_y1 ); blis-0.9.0/frame/2/hemv/other/bli_hemv_front.c000066400000000000000000000162551422157504600211440ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" extern hemv_t* hemv_cntl_bs_ke_lrow_ucol; extern hemv_t* hemv_cntl_bs_ke_lcol_urow; extern hemv_t* hemv_cntl_ge_lrow_ucol; extern hemv_t* hemv_cntl_ge_lcol_urow; void bli_hemv_front ( obj_t* alpha, obj_t* a, obj_t* x, obj_t* beta, obj_t* y, cntx_t* cntx ) { hemv_t* hemv_cntl; num_t dt_targ_a; num_t dt_targ_x; num_t dt_targ_y; bool a_has_unit_inc; bool x_has_unit_inc; bool y_has_unit_inc; obj_t alpha_local; obj_t beta_local; num_t dt_alpha; num_t dt_beta; // Check parameters. if ( bli_error_checking_is_enabled() ) bli_hemv_check( alpha, a, x, beta, y ); // Query the target datatypes of each object. dt_targ_a = bli_obj_target_dt( a ); dt_targ_x = bli_obj_target_dt( x ); dt_targ_y = bli_obj_target_dt( y ); // Determine whether each operand with unit stride. a_has_unit_inc = ( bli_obj_is_row_stored( a ) || bli_obj_is_col_stored( a ) ); x_has_unit_inc = ( bli_obj_vector_inc( x ) == 1 ); y_has_unit_inc = ( bli_obj_vector_inc( y ) == 1 ); // Create an object to hold a copy-cast of alpha. Notice that we use // the type union of the target datatypes of a and x to prevent any // unnecessary loss of information during the computation. dt_alpha = bli_dt_union( dt_targ_a, dt_targ_x ); bli_obj_scalar_init_detached_copy_of( dt_alpha, BLIS_NO_CONJUGATE, alpha, &alpha_local ); // Create an object to hold a copy-cast of beta. Notice that we use // the datatype of y. Here's why: If y is real and beta is complex, // there is no reason to keep beta_local in the complex domain since // the complex part of beta*y will not be stored. If y is complex and // beta is real then beta is harmlessly promoted to complex. dt_beta = dt_targ_y; bli_obj_scalar_init_detached_copy_of( dt_beta, BLIS_NO_CONJUGATE, beta, &beta_local ); // If all operands have unit stride, we choose a control tree for calling // the unblocked implementation directly without any blocking. if ( a_has_unit_inc && x_has_unit_inc && y_has_unit_inc ) { // We use two control trees to handle the four cases corresponding to // combinations of upper/lower triangular storage and row/column-storage. // The row-stored lower triangular and column-stored upper triangular // trees are identical. Same for the remaining two trees. if ( bli_obj_is_lower( a ) ) { if ( bli_obj_is_row_stored( a ) ) hemv_cntl = hemv_cntl_bs_ke_lrow_ucol; else hemv_cntl = hemv_cntl_bs_ke_lcol_urow; } else // if ( bli_obj_is_upper( a ) ) { if ( bli_obj_is_row_stored( a ) ) hemv_cntl = hemv_cntl_bs_ke_lcol_urow; else hemv_cntl = hemv_cntl_bs_ke_lrow_ucol; } } else { // Mark objects with unit stride as already being packed. This prevents // unnecessary packing from happening within the blocked algorithm. if ( a_has_unit_inc ) bli_obj_set_pack_schema( BLIS_PACKED_UNSPEC, a ); if ( x_has_unit_inc ) bli_obj_set_pack_schema( BLIS_PACKED_VECTOR, x ); if ( y_has_unit_inc ) bli_obj_set_pack_schema( BLIS_PACKED_VECTOR, y ); // Here, we make a similar choice as above, except that (1) we look // at storage tilt, and (2) we choose a tree that performs blocking. if ( bli_obj_is_lower( a ) ) { if ( bli_obj_is_row_tilted( a ) ) hemv_cntl = hemv_cntl_ge_lrow_ucol; else hemv_cntl = hemv_cntl_ge_lcol_urow; } else // if ( bli_obj_is_upper( a ) ) { if ( bli_obj_is_row_tilted( a ) ) hemv_cntl = hemv_cntl_ge_lcol_urow; else hemv_cntl = hemv_cntl_ge_lrow_ucol; } } // Invoke the internal back-end with the copy-casts of scalars and the // chosen control tree. Set conjh to BLIS_CONJUGATE to invoke the // Hermitian (and not symmetric) algorithms. bli_hemv_int( BLIS_CONJUGATE, &alpha_local, a, x, &beta_local, y, cntx, hemv_cntl ); } // // Define BLAS-like interfaces with homogeneous-typed operands. // #undef GENTFUNC #define GENTFUNC( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ uplo_t uploa, \ conj_t conja, \ conj_t conjx, \ dim_t m, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* x, inc_t incx, \ ctype* beta, \ ctype* y, inc_t incy, \ cntx_t* cntx \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ obj_t alphao, ao, xo, betao, yo; \ \ inc_t rs_x, cs_x; \ inc_t rs_y, cs_y; \ \ rs_x = incx; cs_x = m * incx; \ rs_y = incy; cs_y = m * incy; \ \ bli_obj_create_1x1_with_attached_buffer( dt, alpha, &alphao ); \ bli_obj_create_1x1_with_attached_buffer( dt, beta, &betao ); \ \ bli_obj_create_with_attached_buffer( dt, m, m, a, rs_a, cs_a, &ao ); \ bli_obj_create_with_attached_buffer( dt, m, 1, x, rs_x, cs_x, &xo ); \ bli_obj_create_with_attached_buffer( dt, m, 1, y, rs_y, cs_y, &yo ); \ \ bli_obj_set_uplo( uploa, &ao ); \ bli_obj_set_conj( conja, &ao ); \ bli_obj_set_conj( conjx, &xo ); \ \ bli_obj_set_struc( BLIS_HERMITIAN, &ao ); \ \ PASTEMAC0(opname)( &alphao, \ &ao, \ &xo, \ &betao, \ &yo, \ cntx ); \ } INSERT_GENTFUNC_BASIC0( hemv_front ) blis-0.9.0/frame/2/hemv/other/bli_hemv_front.h000066400000000000000000000044101422157504600211370ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void bli_hemv_front ( obj_t* alpha, obj_t* a, obj_t* x, obj_t* beta, obj_t* y, cntx_t* cntx ); // // Prototype BLAS-like interfaces with homogeneous-typed operands. // #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ uplo_t uploa, \ conj_t conja, \ conj_t conjx, \ dim_t m, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* x, inc_t incx, \ ctype* beta, \ ctype* y, inc_t incy, \ cntx_t* cntx \ ); INSERT_GENTPROT_BASIC( hemv_front ) blis-0.9.0/frame/2/hemv/other/bli_hemv_int.c000066400000000000000000000102441422157504600205760ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define FUNCPTR_T hemv_fp typedef void (*FUNCPTR_T)( conj_t conjh, obj_t* alpha, obj_t* a, obj_t* x, obj_t* beta, obj_t* y, cntx_t* cntx, hemv_t* cntl ); static FUNCPTR_T vars[4][3] = { // unblocked unblocked with fusing blocked { bli_hemv_unb_var1, bli_hemv_unf_var1, bli_hemv_blk_var1, }, { bli_hemv_unb_var2, NULL, bli_hemv_blk_var2, }, { bli_hemv_unb_var3, bli_hemv_unf_var3, bli_hemv_blk_var3, }, { bli_hemv_unb_var4, NULL, bli_hemv_blk_var4, }, }; void bli_hemv_int( conj_t conjh, obj_t* alpha, obj_t* a, obj_t* x, obj_t* beta, obj_t* y, cntx_t* cntx, hemv_t* cntl ) { varnum_t n; impl_t i; FUNCPTR_T f; obj_t a_local; // Check parameters. if ( bli_error_checking_is_enabled() ) { if ( bli_is_conj( conjh ) ) bli_hemv_check( alpha, a, x, beta, y ); else bli_symv_check( alpha, a, x, beta, y ); } // If y has a zero dimension, return early. if ( bli_obj_has_zero_dim( y ) ) return; // If x has a zero dimension, scale y by beta and return early. if ( bli_obj_has_zero_dim( x ) ) { bli_scalm( beta, y ); return; } // Alias A in case we need to induce the upper triangular case. bli_obj_alias_to( a, &a_local ); /* // Our blocked algorithms only [explicitly] implement the lower triangular // case, so if matrix A is stored as upper triangular, we must toggle the // transposition (and conjugation) bits so that the diagonal partitioning // routines grab the correct partitions corresponding to the upper // triangular case. But we only need to do this for blocked algorithms, // since unblocked algorithms are responsible for handling the upper case // explicitly (and they should not be inspecting the transposition bit anyway). if ( bli_cntl_is_blocked( cntl ) && bli_obj_is_upper( a ) ) { bli_obj_toggle_conj( &a_local ); bli_obj_toggle_trans( &a_local ); } */ // Extract the variant number and implementation type. n = bli_cntl_var_num( cntl ); i = bli_cntl_impl_type( cntl ); // Index into the variant array to extract the correct function pointer. f = vars[n][i]; // Invoke the variant. f( conjh, alpha, &a_local, x, beta, y, cntx, cntl ); } blis-0.9.0/frame/2/hemv/other/bli_hemv_int.h000066400000000000000000000036141422157504600206060ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void bli_hemv_int( conj_t conjh, obj_t* alpha, obj_t* a, obj_t* x, obj_t* beta, obj_t* y, cntx_t* cntx, hemv_t* cntl ); blis-0.9.0/frame/2/her/000077500000000000000000000000001422157504600144705ustar00rootroot00000000000000blis-0.9.0/frame/2/her/bli_her.h000066400000000000000000000034631422157504600162530ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // NOTE: level-2 control tree code is temporarily disabled. //#include "bli_her_cntl.h" //#include "bli_her_front.h" //#include "bli_her_int.h" #include "bli_her_var.h" blis-0.9.0/frame/2/her/bli_her_unb_var1.c000066400000000000000000000113531422157504600200400ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ uplo_t uplo, \ conj_t conjx, \ conj_t conjh, \ dim_t m, \ ctype* alpha, /* complex alpha allows her variants to also perform syr. */ \ ctype* x, inc_t incx, \ ctype* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ ctype* x0; \ ctype* chi1; \ ctype* c10t; \ ctype* gamma11; \ ctype alpha_local; \ ctype alpha_chi1; \ ctype alpha_chi1_chi1; \ ctype conjx0_chi1; \ ctype conjx1_chi1; \ dim_t i; \ dim_t n_behind; \ inc_t rs_ct, cs_ct; \ conj_t conj0, conj1; \ \ /* Eliminate unused variable warnings. */ \ ( void )conj0; \ \ /* Make a local copy of alpha and zero out the imaginary component if we are being invoked as her, since her requires alpha to be real. */ \ PASTEMAC(ch,copys)( *alpha, alpha_local ); \ if ( bli_is_conj( conjh ) ) \ { \ PASTEMAC(ch,seti0s)( alpha_local ); \ } \ \ /* The algorithm will be expressed in terms of the lower triangular case; the upper triangular case is supported by swapping the row and column strides of A and toggling some conj parameters. */ \ if ( bli_is_lower( uplo ) ) \ { \ rs_ct = rs_c; \ cs_ct = cs_c; \ } \ else /* if ( bli_is_upper( uplo ) ) */ \ { \ rs_ct = cs_c; \ cs_ct = rs_c; \ \ /* Toggle conjugation of conjx, but only if we are being invoked as her; for syr, conjx is unchanged. */ \ conjx = bli_apply_conj( conjh, conjx ); \ } \ \ /* Apply conjh (which carries the conjugation component of the Hermitian transpose, if applicable) to conjx as needed to arrive at the effective conjugation for the scalar and vector subproblems. */ \ conj0 = conjx; \ conj1 = bli_apply_conj( conjh, conjx ); \ \ PASTECH(ch,axpyv_ker_ft) kfp_av; \ \ /* Query the context for the kernel function pointer. */ \ kfp_av = bli_cntx_get_l1v_ker_dt( dt, BLIS_AXPYV_KER, cntx ); \ \ for ( i = 0; i < m; ++i ) \ { \ n_behind = i; \ x0 = x + (0 )*incx; \ chi1 = x + (i )*incx; \ c10t = c + (i )*rs_ct + (0 )*cs_ct; \ gamma11 = c + (i )*rs_ct + (i )*cs_ct; \ \ /* Apply conjx to chi1. */ \ PASTEMAC(ch,copycjs)( conj0, *chi1, conjx0_chi1 ); \ PASTEMAC(ch,copycjs)( conj1, *chi1, conjx1_chi1 ); \ \ /* Compute scalar for vector subproblem. */ \ PASTEMAC(ch,scal2s)( alpha_local, conjx0_chi1, alpha_chi1 ); \ \ /* Compute alpha * chi1 * conj(chi1) after chi1 has already been conjugated, if needed, by conjx. */ \ PASTEMAC(ch,scal2s)( alpha_chi1, conjx1_chi1, alpha_chi1_chi1 ); \ \ /* c10t = c10t + alpha * chi1 * x0'; */ \ kfp_av \ ( \ conj1, \ n_behind, \ &alpha_chi1, \ x0, incx, \ c10t, cs_ct, \ cntx \ ); \ \ /* gamma11 = gamma11 + alpha * chi1 * conj(chi1); */ \ PASTEMAC(ch,adds)( alpha_chi1_chi1, *gamma11 ); \ \ /* For her2, explicitly set the imaginary component of gamma11 to zero. */ \ if ( bli_is_conj( conjh ) ) \ PASTEMAC(ch,seti0s)( *gamma11 ); \ } \ } INSERT_GENTFUNC_BASIC0( her_unb_var1 ) blis-0.9.0/frame/2/her/bli_her_unb_var2.c000066400000000000000000000113551422157504600200430ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ uplo_t uplo, \ conj_t conjx, \ conj_t conjh, \ dim_t m, \ ctype* alpha, /* complex alpha allows her variants to also perform syr. */ \ ctype* x, inc_t incx, \ ctype* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ ctype* chi1; \ ctype* x2; \ ctype* gamma11; \ ctype* c21; \ ctype alpha_local; \ ctype alpha_chi1; \ ctype alpha_chi1_chi1; \ ctype conjx0_chi1; \ ctype conjx1_chi1; \ dim_t i; \ dim_t n_ahead; \ inc_t rs_ct, cs_ct; \ conj_t conj0, conj1; \ \ /* Eliminate unused variable warnings. */ \ ( void )conj0; \ \ /* Make a local copy of alpha and zero out the imaginary component if we are being invoked as her, since her requires alpha to be real. */ \ PASTEMAC(ch,copys)( *alpha, alpha_local ); \ if ( bli_is_conj( conjh ) ) \ { \ PASTEMAC(ch,seti0s)( alpha_local ); \ } \ \ /* The algorithm will be expressed in terms of the lower triangular case; the upper triangular case is supported by swapping the row and column strides of A and toggling some conj parameters. */ \ if ( bli_is_lower( uplo ) ) \ { \ rs_ct = rs_c; \ cs_ct = cs_c; \ } \ else /* if ( bli_is_upper( uplo ) ) */ \ { \ rs_ct = cs_c; \ cs_ct = rs_c; \ \ /* Toggle conjugation of conjx, but only if we are being invoked as her; for syr, conjx is unchanged. */ \ conjx = bli_apply_conj( conjh, conjx ); \ } \ \ /* Apply conjh (which carries the conjugation component of the Hermitian transpose, if applicable) to conjx as needed to arrive at the effective conjugation for the scalar and vector subproblems. */ \ conj0 = bli_apply_conj( conjh, conjx ); \ conj1 = conjx; \ \ PASTECH(ch,axpyv_ker_ft) kfp_av; \ \ /* Query the context for the kernel function pointer. */ \ kfp_av = bli_cntx_get_l1v_ker_dt( dt, BLIS_AXPYV_KER, cntx ); \ \ for ( i = 0; i < m; ++i ) \ { \ n_ahead = m - i - 1; \ chi1 = x + (i )*incx; \ x2 = x + (i+1)*incx; \ gamma11 = c + (i )*rs_ct + (i )*cs_ct; \ c21 = c + (i+1)*rs_ct + (i )*cs_ct; \ \ /* Apply conjx to chi1. */ \ PASTEMAC(ch,copycjs)( conj0, *chi1, conjx0_chi1 ); \ PASTEMAC(ch,copycjs)( conj1, *chi1, conjx1_chi1 ); \ \ /* Compute scalar for vector subproblem. */ \ PASTEMAC(ch,scal2s)( alpha_local, conjx0_chi1, alpha_chi1 ); \ \ /* Compute alpha * chi1 * conj(chi1) after chi1 has already been conjugated, if needed, by conjx. */ \ PASTEMAC(ch,scal2s)( alpha_chi1, conjx1_chi1, alpha_chi1_chi1 ); \ \ /* c21 = c21 + alpha * x2 * conj(chi1); */ \ kfp_av \ ( \ conj1, \ n_ahead, \ &alpha_chi1, \ x2, incx, \ c21, rs_ct, \ cntx \ ); \ \ /* gamma11 = gamma11 + alpha * chi1 * conj(chi1); */ \ PASTEMAC(ch,adds)( alpha_chi1_chi1, *gamma11 ); \ \ /* For her, explicitly set the imaginary component of gamma11 to zero. */ \ if ( bli_is_conj( conjh ) ) \ PASTEMAC(ch,seti0s)( *gamma11 ); \ } \ } INSERT_GENTFUNC_BASIC0( her_unb_var2 ) blis-0.9.0/frame/2/her/bli_her_var.h000066400000000000000000000050251422157504600171170ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype object-based interfaces. // #undef GENPROT #define GENPROT( opname ) \ \ void PASTEMAC0(opname) \ ( \ conj_t conjh, \ obj_t* alpha, \ obj_t* x, \ obj_t* c, \ cntx_t* cntx, \ cntl_t* cntl \ ); GENPROT( her_blk_var1 ) GENPROT( her_blk_var2 ) GENPROT( her_unb_var1 ) GENPROT( her_unb_var2 ) // // Prototype BLAS-like interfaces with typed operands. // #undef GENTPROTR #define GENTPROTR( ctype, ctype_r, ch, chr, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ uplo_t uplo, \ conj_t conjx, \ conj_t conjh, \ dim_t m, \ ctype* alpha, /* complex alpha allows her variants to also perform syr. */ \ ctype* x, inc_t incx, \ ctype* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx \ ); INSERT_GENTPROTR_BASIC0( her_unb_var1 ) INSERT_GENTPROTR_BASIC0( her_unb_var2 ) blis-0.9.0/frame/2/her/bli_her_var_oapi.c000066400000000000000000000054521422157504600201260ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENFRONT #define GENFRONT( opname, varname ) \ \ void PASTEMAC0(varname) \ ( \ conj_t conjh, \ obj_t* alpha, \ obj_t* x, \ obj_t* c, \ cntx_t* cntx, \ cntl_t* cntl \ ) \ { \ bli_init_once(); \ \ num_t dt = bli_obj_dt( c ); \ \ uplo_t uplo = bli_obj_uplo( c ); \ conj_t conjx = bli_obj_conj_status( x ); \ \ dim_t m = bli_obj_length( c ); \ \ void* buf_x = bli_obj_buffer_at_off( x ); \ inc_t incx = bli_obj_vector_inc( x ); \ \ void* buf_c = bli_obj_buffer_at_off( c ); \ inc_t rs_c = bli_obj_row_stride( c ); \ inc_t cs_c = bli_obj_col_stride( c ); \ \ void* buf_alpha = bli_obj_buffer_for_1x1( dt, alpha ); \ \ /* Query a type-specific function pointer, except one that uses void* for function arguments instead of typed pointers. */ \ PASTECH2(opname,_unb,_vft) f = \ PASTEMAC(varname,_qfp)( dt ); \ \ f \ ( \ uplo, \ conjx, \ conjh, \ m, \ buf_alpha, \ buf_x, incx, \ buf_c, rs_c, cs_c, \ cntx \ ); \ } \ GENFRONT( her, her_unb_var1 ) GENFRONT( her, her_unb_var2 ) blis-0.9.0/frame/2/her/other/000077500000000000000000000000001422157504600156115ustar00rootroot00000000000000blis-0.9.0/frame/2/her/other/bli_her_blk_var1.c000066400000000000000000000112451422157504600211450ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_her_blk_var1( conj_t conjh, obj_t* alpha, obj_t* x, obj_t* c, cntx_t* cntx, her_t* cntl ) { obj_t c11, c11_pack; obj_t c10; obj_t x1, x1_pack; obj_t x0; dim_t mn; dim_t ij; dim_t b_alg; // Even though this blocked algorithm is expressed only in terms of the // lower triangular case, the upper triangular case is still supported: // when bli_acquire_mpart_tl2br() is passed a matrix that is stored in // in the upper triangle, and the requested subpartition resides in the // lower triangle (as is the case for this algorithm), the routine fills // the request as if the caller had actually requested the corresponding // "mirror" subpartition in the upper triangle, except that it marks the // subpartition for transposition (and conjugation). // Initialize objects for packing. bli_obj_init_pack( &c11_pack ); bli_obj_init_pack( &x1_pack ); // Query dimension. mn = bli_obj_length( c ); // Partition diagonally. for ( ij = 0; ij < mn; ij += b_alg ) { // Determine the current algorithmic blocksize. b_alg = bli_determine_blocksize_f( ij, mn, c, bli_cntl_bszid( cntl ), cntx ); // Acquire partitions for C11, C10, x1, and x0. bli_acquire_mpart_tl2br( BLIS_SUBPART11, ij, b_alg, c, &c11 ); bli_acquire_mpart_tl2br( BLIS_SUBPART10, ij, b_alg, c, &c10 ); bli_acquire_vpart_f2b( BLIS_SUBPART1, ij, b_alg, x, &x1 ); bli_acquire_vpart_f2b( BLIS_SUBPART0, ij, b_alg, x, &x0 ); // Initialize objects for packing C11 and x1 (if needed). bli_packm_init( &c11, &c11_pack, cntx, bli_cntl_sub_packm_c11( cntl ) ); bli_packv_init( &x1, &x1_pack, cntx, bli_cntl_sub_packv_x1( cntl ) ); // Copy/pack C11, x1 (if needed). bli_packm_int( &c11, &c11_pack, cntx, bli_cntl_sub_packm_c11( cntl ), &BLIS_PACKM_SINGLE_THREADED ); bli_packv_int( &x1, &x1_pack, cntx, bli_cntl_sub_packv_x1( cntl ) ); // C10 = C10 + alpha * x1 * x0'; bli_ger_int( BLIS_NO_CONJUGATE, conjh, alpha, &x1_pack, &x0, &c10, cntx, bli_cntl_sub_ger( cntl ) ); // C11 = C11 + alpha * x1 * x1'; bli_her_int( conjh, alpha, &x1_pack, &c11_pack, cntx, bli_cntl_sub_her( cntl ) ); // Copy/unpack C11 (if C11 was packed). bli_unpackm_int( &c11_pack, &c11, cntx, bli_cntl_sub_unpackm_c11( cntl ), &BLIS_PACKM_SINGLE_THREADED ); } // If any packing buffers were acquired within packm, release them back // to the memory manager. bli_packm_release( &c11_pack, bli_cntl_sub_packm_c11( cntl ) ); bli_packv_release( &x1_pack, bli_cntl_sub_packv_x1( cntl ) ); } blis-0.9.0/frame/2/her/other/bli_her_blk_var2.c000066400000000000000000000112451422157504600211460ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_her_blk_var2( conj_t conjh, obj_t* alpha, obj_t* x, obj_t* c, cntx_t* cntx, her_t* cntl ) { obj_t c11, c11_pack; obj_t c21; obj_t x1, x1_pack; obj_t x2; dim_t mn; dim_t ij; dim_t b_alg; // Even though this blocked algorithm is expressed only in terms of the // lower triangular case, the upper triangular case is still supported: // when bli_acquire_mpart_tl2br() is passed a matrix that is stored in // in the upper triangle, and the requested subpartition resides in the // lower triangle (as is the case for this algorithm), the routine fills // the request as if the caller had actually requested the corresponding // "mirror" subpartition in the upper triangle, except that it marks the // subpartition for transposition (and conjugation). // Initialize objects for packing. bli_obj_init_pack( &c11_pack ); bli_obj_init_pack( &x1_pack ); // Query dimension. mn = bli_obj_length( c ); // Partition diagonally. for ( ij = 0; ij < mn; ij += b_alg ) { // Determine the current algorithmic blocksize. b_alg = bli_determine_blocksize_f( ij, mn, c, bli_cntl_bszid( cntl ), cntx ); // Acquire partitions for C11, C21, x1, and x2. bli_acquire_mpart_tl2br( BLIS_SUBPART11, ij, b_alg, c, &c11 ); bli_acquire_mpart_tl2br( BLIS_SUBPART21, ij, b_alg, c, &c21 ); bli_acquire_vpart_f2b( BLIS_SUBPART1, ij, b_alg, x, &x1 ); bli_acquire_vpart_f2b( BLIS_SUBPART2, ij, b_alg, x, &x2 ); // Initialize objects for packing C11 and x1 (if needed). bli_packm_init( &c11, &c11_pack, cntx, bli_cntl_sub_packm_c11( cntl ) ); bli_packv_init( &x1, &x1_pack, cntx, bli_cntl_sub_packv_x1( cntl ) ); // Copy/pack C11, x1 (if needed). bli_packm_int( &c11, &c11_pack, cntx, bli_cntl_sub_packm_c11( cntl ), &BLIS_PACKM_SINGLE_THREADED ); bli_packv_int( &x1, &x1_pack, cntx, bli_cntl_sub_packv_x1( cntl ) ); // C21 = C21 + alpha * x2 * x1'; bli_ger_int( BLIS_NO_CONJUGATE, conjh, alpha, &x2, &x1_pack, &c21, cntx, bli_cntl_sub_ger( cntl ) ); // C11 = C11 + alpha * x1 * x1'; bli_her_int( conjh, alpha, &x1_pack, &c11_pack, cntx, bli_cntl_sub_her( cntl ) ); // Copy/unpack C11 (if C11 was packed). bli_unpackm_int( &c11_pack, &c11, cntx, bli_cntl_sub_unpackm_c11( cntl ), &BLIS_PACKM_SINGLE_THREADED ); } // If any packing buffers were acquired within packm, release them back // to the memory manager. bli_packm_release( &c11_pack, bli_cntl_sub_packm_c11( cntl ) ); bli_packv_release( &x1_pack, bli_cntl_sub_packv_x1( cntl ) ); } blis-0.9.0/frame/2/her/other/bli_her_cntl.c000066400000000000000000000127371422157504600204130ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" extern packm_t* packm_cntl; extern packv_t* packv_cntl; extern unpackm_t* unpackm_cntl; extern ger_t* ger_cntl_rp_bs_row; extern ger_t* ger_cntl_cp_bs_col; extern ger_t* ger_cntl_bs_ke_row; extern ger_t* ger_cntl_bs_ke_col; her_t* her_cntl_bs_ke_lrow_ucol = NULL; her_t* her_cntl_bs_ke_lcol_urow = NULL; her_t* her_cntl_ge_lrow_ucol = NULL; her_t* her_cntl_ge_lcol_urow = NULL; void bli_her_cntl_init() { // Create control trees for the lowest-level kernels. These trees induce // operations on (persumably) relatively small block-subvector problems. her_cntl_bs_ke_lrow_ucol = bli_her_cntl_obj_create( BLIS_UNBLOCKED, BLIS_VARIANT1, 0, NULL, NULL, NULL, NULL, NULL ); her_cntl_bs_ke_lcol_urow = bli_her_cntl_obj_create( BLIS_UNBLOCKED, BLIS_VARIANT2, 0, NULL, NULL, NULL, NULL, NULL ); // Create control trees for generally large problems. Here, we choose // variants that partition for ger subproblems in the same direction // as the assumed storage. her_cntl_ge_lrow_ucol = bli_her_cntl_obj_create( BLIS_BLOCKED, BLIS_VARIANT1, BLIS_M2, packv_cntl, // pack x1 (if needed) NULL, // do NOT pack C11 ger_cntl_rp_bs_row, her_cntl_bs_ke_lrow_ucol, NULL ); // no unpacking needed her_cntl_ge_lcol_urow = bli_her_cntl_obj_create( BLIS_BLOCKED, BLIS_VARIANT2, BLIS_M2, packv_cntl, // pack x1 (if needed) NULL, // do NOT pack C11 ger_cntl_cp_bs_col, her_cntl_bs_ke_lcol_urow, NULL ); // no unpacking needed } void bli_her_cntl_finalize() { bli_cntl_free_node( her_cntl_bs_ke_lrow_ucol ); bli_cntl_free_node( her_cntl_bs_ke_lcol_urow ); bli_cntl_free_node( her_cntl_ge_lrow_ucol ); bli_cntl_free_node( her_cntl_ge_lcol_urow ); } her_t* bli_her_cntl_obj_create( impl_t impl_type, varnum_t var_num, bszid_t bszid, packv_t* sub_packv_x1, packm_t* sub_packm_c11, ger_t* sub_ger, her_t* sub_her, unpackm_t* sub_unpackm_c11 ) { her_t* cntl; cntl = ( her_t* ) bli_malloc_intl( sizeof(her_t) ); cntl->impl_type = impl_type; cntl->var_num = var_num; cntl->bszid = bszid; cntl->sub_packv_x1 = sub_packv_x1; cntl->sub_packm_c11 = sub_packm_c11; cntl->sub_ger = sub_ger; cntl->sub_her = sub_her; cntl->sub_unpackm_c11 = sub_unpackm_c11; return cntl; } void bli_her_cntl_obj_init( her_t* cntl, impl_t impl_type, varnum_t var_num, bszid_t bszid, packv_t* sub_packv_x1, packm_t* sub_packm_c11, ger_t* sub_ger, her_t* sub_her, unpackm_t* sub_unpackm_c11 ) { cntl->impl_type = impl_type; cntl->var_num = var_num; cntl->bszid = bszid; cntl->sub_packv_x1 = sub_packv_x1; cntl->sub_packm_c11 = sub_packm_c11; cntl->sub_ger = sub_ger; cntl->sub_her = sub_her; cntl->sub_unpackm_c11 = sub_unpackm_c11; } blis-0.9.0/frame/2/her/other/bli_her_cntl.h000066400000000000000000000056521422157504600204160ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ struct her_s { impl_t impl_type; varnum_t var_num; bszid_t bszid; struct packv_s* sub_packv_x1; struct packm_s* sub_packm_c11; struct ger_s* sub_ger; struct her_s* sub_her; struct unpackm_s* sub_unpackm_c11; }; typedef struct her_s her_t; #define bli_cntl_sub_her( cntl ) cntl->sub_her void bli_her_cntl_init( void ); void bli_her_cntl_finalize( void ); her_t* bli_her_cntl_obj_create( impl_t impl_type, varnum_t var_num, bszid_t bszid, packv_t* sub_packv_x1, packm_t* sub_packm_c11, ger_t* sub_ger, her_t* sub_her, unpackm_t* sub_unpackm_c11 ); void bli_her_cntl_obj_init( her_t* cntl, impl_t impl_type, varnum_t var_num, bszid_t bszid, packv_t* sub_packv_x1, packm_t* sub_packm_c11, ger_t* sub_ger, her_t* sub_her, unpackm_t* sub_unpackm_c11 ); blis-0.9.0/frame/2/her/other/bli_her_front.c000066400000000000000000000133731422157504600206000ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" extern her_t* her_cntl_bs_ke_lrow_ucol; extern her_t* her_cntl_bs_ke_lcol_urow; extern her_t* her_cntl_ge_lrow_ucol; extern her_t* her_cntl_ge_lcol_urow; void bli_her_front ( obj_t* alpha, obj_t* x, obj_t* c, cntx_t* cntx ) { her_t* her_cntl; num_t dt_targ_x; //num_t dt_targ_c; bool x_has_unit_inc; bool c_has_unit_inc; obj_t alpha_local; num_t dt_alpha; // Check parameters. if ( bli_error_checking_is_enabled() ) bli_her_check( alpha, x, c ); // Query the target datatypes of each object. dt_targ_x = bli_obj_target_dt( x ); //dt_targ_c = bli_obj_target_dt( c ); // Determine whether each operand with unit stride. x_has_unit_inc = ( bli_obj_vector_inc( x ) == 1 ); c_has_unit_inc = ( bli_obj_is_row_stored( c ) || bli_obj_is_col_stored( c ) ); // Create object to hold a copy-cast of alpha. dt_alpha = dt_targ_x; bli_obj_scalar_init_detached_copy_of( dt_alpha, BLIS_NO_CONJUGATE, alpha, &alpha_local ); // If all operands have unit stride, we choose a control tree for calling // the unblocked implementation directly without any blocking. if ( x_has_unit_inc && c_has_unit_inc ) { // We use two control trees to handle the four cases corresponding to // combinations of upper/lower triangular storage and row/column-storage. // The row-stored lower triangular and column-stored upper triangular // trees are identical. Same for the remaining two trees. if ( bli_obj_is_lower( c ) ) { if ( bli_obj_is_row_stored( c ) ) her_cntl = her_cntl_bs_ke_lrow_ucol; else her_cntl = her_cntl_bs_ke_lcol_urow; } else // if ( bli_obj_is_upper( c ) ) { if ( bli_obj_is_row_stored( c ) ) her_cntl = her_cntl_bs_ke_lcol_urow; else her_cntl = her_cntl_bs_ke_lrow_ucol; } } else { // Mark objects with unit stride as already being packed. This prevents // unnecessary packing from happening within the blocked algorithm. if ( x_has_unit_inc ) bli_obj_set_pack_schema( BLIS_PACKED_VECTOR, x ); if ( c_has_unit_inc ) bli_obj_set_pack_schema( BLIS_PACKED_UNSPEC, c ); // Here, we make a similar choice as above, except that (1) we look // at storage tilt, and (2) we choose a tree that performs blocking. if ( bli_obj_is_lower( c ) ) { if ( bli_obj_is_row_stored( c ) ) her_cntl = her_cntl_ge_lrow_ucol; else her_cntl = her_cntl_ge_lcol_urow; } else // if ( bli_obj_is_upper( c ) ) { if ( bli_obj_is_row_stored( c ) ) her_cntl = her_cntl_ge_lcol_urow; else her_cntl = her_cntl_ge_lrow_ucol; } } // Invoke the internal back-end with the copy-cast scalar and the // chosen control tree. Set conjh to BLIS_CONJUGATE to invoke the // Hermitian (and not symmetric) algorithms. bli_her_int( BLIS_CONJUGATE, &alpha_local, x, c, cntx, her_cntl ); } // // Define BLAS-like interfaces with homogeneous-typed operands. // #undef GENTFUNCR #define GENTFUNCR( ctype, ctype_r, ch, chr, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ uplo_t uploc, \ conj_t conjx, \ dim_t m, \ ctype_r* alpha, \ ctype* x, inc_t incx, \ ctype* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx \ ) \ { \ const num_t dt_r = PASTEMAC(chr,type); \ const num_t dt = PASTEMAC(ch,type); \ \ obj_t alphao, xo, co; \ \ inc_t rs_x, cs_x; \ \ rs_x = incx; cs_x = m * incx; \ \ bli_obj_create_1x1_with_attached_buffer( dt_r, alpha, &alphao ); \ \ bli_obj_create_with_attached_buffer( dt, m, 1, x, rs_x, cs_x, &xo ); \ bli_obj_create_with_attached_buffer( dt, m, m, c, rs_c, cs_c, &co ); \ \ bli_obj_set_conj( conjx, &xo ); \ bli_obj_set_uplo( uploc, &co ); \ \ bli_obj_set_struc( BLIS_HERMITIAN, &co ); \ \ PASTEMAC0(opname)( &alphao, \ &xo, \ &co, \ cntx ); \ } INSERT_GENTFUNCR_BASIC0( her_front ) blis-0.9.0/frame/2/her/other/bli_her_front.h000066400000000000000000000041351422157504600206010ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void bli_her_front ( obj_t* alpha, obj_t* x, obj_t* c, cntx_t* cntx ); #undef GENTPROTR #define GENTPROTR( ctype, ctype_r, ch, chr, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ uplo_t uploc, \ conj_t conjx, \ dim_t m, \ ctype_r* alpha, \ ctype* x, inc_t incx, \ ctype* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx \ ); INSERT_GENTPROTR_BASIC( her_front ) blis-0.9.0/frame/2/her/other/bli_her_int.c000066400000000000000000000071601422157504600202370ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define FUNCPTR_T her_fp typedef void (*FUNCPTR_T)( conj_t conjh, obj_t* alpha, obj_t* x, obj_t* c, cntx_t* cntx, her_t* cntl ); static FUNCPTR_T vars[4][3] = { // unblocked unblocked with fusing blocked { bli_her_unb_var1, NULL, bli_her_blk_var1, }, { bli_her_unb_var2, NULL, bli_her_blk_var2, }, { NULL, NULL, NULL, }, { NULL, NULL, NULL, }, }; void bli_her_int( conj_t conjh, obj_t* alpha, obj_t* x, obj_t* c, cntx_t* cntx, her_t* cntl ) { varnum_t n; impl_t i; FUNCPTR_T f; obj_t x_local; obj_t c_local; // Check parameters. if ( bli_error_checking_is_enabled() ) { if ( bli_is_conj( conjh ) ) bli_her_check( alpha, x, c ); else bli_syr_check( alpha, x, c ); } // If C or x has a zero dimension, return early. if ( bli_obj_has_zero_dim( c ) ) return; if ( bli_obj_has_zero_dim( x ) ) return; // Alias the operands in case we need to apply conjugations. bli_obj_alias_to( x, &x_local ); bli_obj_alias_to( c, &c_local ); // If matrix C is marked for conjugation, we interpret this as a request // to apply a conjugation to the other operands. if ( bli_obj_has_conj( &c_local ) ) { bli_obj_toggle_conj( &c_local ); // Notice that we don't need to conjugate alpha since it is guaranteed // to be real. bli_obj_toggle_conj( &x_local ); } // Extract the variant number and implementation type. n = bli_cntl_var_num( cntl ); i = bli_cntl_impl_type( cntl ); // Index into the variant array to extract the correct function pointer. f = vars[n][i]; // Invoke the variant. f( conjh, alpha, &x_local, &c_local, cntx, cntl ); } blis-0.9.0/frame/2/her/other/bli_her_int.h000066400000000000000000000035101422157504600202370ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void bli_her_int( conj_t conjh, obj_t* alpha, obj_t* x, obj_t* c, cntx_t* cntx, her_t* cntl ); blis-0.9.0/frame/2/her2/000077500000000000000000000000001422157504600145525ustar00rootroot00000000000000blis-0.9.0/frame/2/her2/bli_her2.h000066400000000000000000000034671422157504600164230ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // NOTE: level-2 control tree code is temporarily disabled. //#include "bli_her2_cntl.h" //#include "bli_her2_front.h" //#include "bli_her2_int.h" #include "bli_her2_var.h" blis-0.9.0/frame/2/her2/bli_her2_unb_var1.c000066400000000000000000000124511422157504600202040ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ uplo_t uplo, \ conj_t conjx, \ conj_t conjy, \ conj_t conjh, \ dim_t m, \ ctype* alpha, \ ctype* x, inc_t incx, \ ctype* y, inc_t incy, \ ctype* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ ctype* x0; \ ctype* chi1; \ ctype* y0; \ ctype* psi1; \ ctype* c10t; \ ctype* gamma11; \ ctype alpha0; \ ctype alpha1; \ ctype alpha0_chi1; \ ctype alpha1_psi1; \ ctype alpha0_chi1_psi1; \ ctype conjx0_chi1; \ ctype conjy1_psi1; \ ctype conjy0_psi1; \ dim_t i; \ dim_t n_behind; \ inc_t rs_ct, cs_ct; \ conj_t conj0, conj1; \ \ /* The algorithm will be expressed in terms of the lower triangular case; the upper triangular case is supported by swapping the row and column strides of A and toggling some conj parameters. */ \ if ( bli_is_lower( uplo ) ) \ { \ rs_ct = rs_c; \ cs_ct = cs_c; \ \ PASTEMAC(ch,copys)( *alpha, alpha0 ); \ PASTEMAC(ch,copycjs)( conjh, *alpha, alpha1 ); \ } \ else /* if ( bli_is_upper( uplo ) ) */ \ { \ rs_ct = cs_c; \ cs_ct = rs_c; \ \ /* Toggle conjugation of conjx/conjy, but only if we are being invoked as her2; for syr2, conjx/conjy are unchanged. */ \ conjx = bli_apply_conj( conjh, conjx ); \ conjy = bli_apply_conj( conjh, conjy ); \ \ PASTEMAC(ch,copycjs)( conjh, *alpha, alpha0 ); \ PASTEMAC(ch,copys)( *alpha, alpha1 ); \ } \ \ /* Apply conjh (which carries the conjugation component of the Hermitian transpose, if applicable) to conjx and/or conjy as needed to arrive at the effective conjugation for the vector subproblems. */ \ conj0 = bli_apply_conj( conjh, conjy ); \ conj1 = bli_apply_conj( conjh, conjx ); \ \ PASTECH(ch,axpyv_ker_ft) kfp_av; \ \ /* Query the context for the kernel function pointer. */ \ kfp_av = bli_cntx_get_l1v_ker_dt( dt, BLIS_AXPYV_KER, cntx ); \ \ for ( i = 0; i < m; ++i ) \ { \ n_behind = i; \ x0 = x + (0 )*incx; \ chi1 = x + (i )*incx; \ y0 = y + (0 )*incy; \ psi1 = y + (i )*incy; \ c10t = c + (i )*rs_ct + (0 )*cs_ct; \ gamma11 = c + (i )*rs_ct + (i )*cs_ct; \ \ /* Apply conjx and/or conjy to chi1 and/or psi1. */ \ PASTEMAC(ch,copycjs)( conjx, *chi1, conjx0_chi1 ); \ PASTEMAC(ch,copycjs)( conjy, *psi1, conjy1_psi1 ); \ PASTEMAC(ch,copycjs)( conj0, *psi1, conjy0_psi1 ); \ \ /* Compute scalars for vector subproblems. */ \ PASTEMAC(ch,scal2s)( alpha0, conjx0_chi1, alpha0_chi1 ); \ PASTEMAC(ch,scal2s)( alpha1, conjy1_psi1, alpha1_psi1 ); \ \ /* Compute alpha * chi1 * conj(psi1) after both chi1 and psi1 have already been conjugated, if needed, by conjx and conjy. */ \ PASTEMAC(ch,scal2s)( alpha0_chi1, conjy0_psi1, alpha0_chi1_psi1 ); \ \ /* c10t = c10t + alpha * chi1 * y0'; */ \ kfp_av \ ( \ conj0, \ n_behind, \ &alpha0_chi1, \ y0, incy, \ c10t, cs_ct, \ cntx \ ); \ \ /* c10t = c10t + conj(alpha) * psi1 * x0'; */ \ kfp_av \ ( \ conj1, \ n_behind, \ &alpha1_psi1, \ x0, incx, \ c10t, cs_ct, \ cntx \ ); \ \ /* gamma11 = gamma11 + alpha * chi1 * conj(psi1) \ + conj(alpha) * psi1 * conj(chi1); */ \ PASTEMAC(ch,adds)( alpha0_chi1_psi1, *gamma11 ); \ PASTEMAC(ch,adds)( alpha0_chi1_psi1, *gamma11 ); \ \ /* For her2, explicitly set the imaginary component of gamma11 to zero. */ \ if ( bli_is_conj( conjh ) ) \ PASTEMAC(ch,seti0s)( *gamma11 ); \ } \ } INSERT_GENTFUNC_BASIC0( her2_unb_var1 ) blis-0.9.0/frame/2/her2/bli_her2_unb_var2.c000066400000000000000000000130271422157504600202050ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ uplo_t uplo, \ conj_t conjx, \ conj_t conjy, \ conj_t conjh, \ dim_t m, \ ctype* alpha, \ ctype* x, inc_t incx, \ ctype* y, inc_t incy, \ ctype* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ ctype* x0; \ ctype* chi1; \ ctype* x2; \ ctype* psi1; \ ctype* c10t; \ ctype* gamma11; \ ctype* c21; \ ctype alpha0; \ ctype alpha1; \ ctype alpha0_psi1; \ ctype alpha1_psi1; \ ctype alpha0_chi1_psi1; \ ctype conjy0_psi1; \ ctype conjy1_psi1; \ ctype conjx0_chi1; \ dim_t i; \ dim_t n_behind; \ dim_t n_ahead; \ inc_t rs_ct, cs_ct; \ conj_t conj0, conj1; \ conj_t conjh_conjy; \ \ /* Eliminate unused variable warnings. */ \ ( void )conjh_conjy; \ \ /* The algorithm will be expressed in terms of the lower triangular case; the upper triangular case is supported by swapping the row and column strides of A and toggling some conj parameters. */ \ if ( bli_is_lower( uplo ) ) \ { \ rs_ct = rs_c; \ cs_ct = cs_c; \ \ PASTEMAC(ch,copys)( *alpha, alpha0 ); \ PASTEMAC(ch,copycjs)( conjh, *alpha, alpha1 ); \ } \ else /* if ( bli_is_upper( uplo ) ) */ \ { \ rs_ct = cs_c; \ cs_ct = rs_c; \ \ /* Toggle conjugation of conjx/conjy, but only if we are being invoked as her2; for syr2, conjx/conjy are unchanged. */ \ conjx = bli_apply_conj( conjh, conjx ); \ conjy = bli_apply_conj( conjh, conjy ); \ \ PASTEMAC(ch,copycjs)( conjh, *alpha, alpha0 ); \ PASTEMAC(ch,copys)( *alpha, alpha1 ); \ } \ \ /* Apply conjh (which carries the conjugation component of the Hermitian transpose, if applicable) to conjx and/or conjy as needed to arrive at the effective conjugation for the vector subproblems. */ \ conj0 = conjx; \ conj1 = bli_apply_conj( conjh, conjx ); \ conjh_conjy = bli_apply_conj( conjh, conjy ); \ \ PASTECH(ch,axpyv_ker_ft) kfp_av; \ \ /* Query the context for the kernel function pointer. */ \ kfp_av = bli_cntx_get_l1v_ker_dt( dt, BLIS_AXPYV_KER, cntx ); \ \ for ( i = 0; i < m; ++i ) \ { \ n_behind = i; \ n_ahead = m - i - 1; \ x0 = x + (0 )*incx; \ chi1 = x + (i )*incx; \ x2 = x + (i+1)*incx; \ psi1 = y + (i )*incy; \ c10t = c + (i )*rs_ct + (0 )*cs_ct; \ gamma11 = c + (i )*rs_ct + (i )*cs_ct; \ c21 = c + (i+1)*rs_ct + (i )*cs_ct; \ \ /* Apply conjx and/or conjy to chi1 and/or psi1. */ \ PASTEMAC(ch,copycjs)( conjh_conjy, *psi1, conjy0_psi1 ); \ PASTEMAC(ch,copycjs)( conjy, *psi1, conjy1_psi1 ); \ PASTEMAC(ch,copycjs)( conj0, *chi1, conjx0_chi1 ); \ \ /* Compute scalars for vector subproblems. */ \ PASTEMAC(ch,scal2s)( alpha0, conjy0_psi1, alpha0_psi1 ); \ PASTEMAC(ch,scal2s)( alpha1, conjy1_psi1, alpha1_psi1 ); \ \ /* Compute alpha * chi1 * conj(psi1) after both chi1 and psi1 have already been conjugated, if needed, by conjx and conjy. */ \ PASTEMAC(ch,scal2s)( alpha0_psi1, conjx0_chi1, alpha0_chi1_psi1 ); \ \ /* c21 = c21 + alpha * x2 * conj(psi1); */ \ kfp_av \ ( \ conj0, \ n_ahead, \ &alpha0_psi1, \ x2, incx, \ c21, rs_ct, \ cntx \ ); \ \ /* c10t = c10t + conj(alpha) * psi1 * x0'; */ \ kfp_av \ ( \ conj1, \ n_behind, \ &alpha1_psi1, \ x0, incx, \ c10t, cs_ct, \ cntx \ ); \ \ /* gamma11 = gamma11 + alpha * chi1 * conj(psi1) \ + conj(alpha) * psi1 * conj(chi1); */ \ PASTEMAC(ch,adds)( alpha0_chi1_psi1, *gamma11 ); \ PASTEMAC(ch,adds)( alpha0_chi1_psi1, *gamma11 ); \ \ /* For her2, explicitly set the imaginary component of gamma11 to zero. */ \ if ( bli_is_conj( conjh ) ) \ PASTEMAC(ch,seti0s)( *gamma11 ); \ } \ } INSERT_GENTFUNC_BASIC0( her2_unb_var2 ) blis-0.9.0/frame/2/her2/bli_her2_unb_var3.c000066400000000000000000000130251422157504600202040ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ uplo_t uplo, \ conj_t conjx, \ conj_t conjy, \ conj_t conjh, \ dim_t m, \ ctype* alpha, \ ctype* x, inc_t incx, \ ctype* y, inc_t incy, \ ctype* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ ctype* chi1; \ ctype* y0; \ ctype* psi1; \ ctype* y2; \ ctype* c10t; \ ctype* gamma11; \ ctype* c21; \ ctype alpha0; \ ctype alpha1; \ ctype alpha0_chi1; \ ctype alpha1_chi1; \ ctype alpha0_chi1_psi1; \ ctype conjx0_chi1; \ ctype conjx1_chi1; \ ctype conjy0_psi1; \ dim_t i; \ dim_t n_behind; \ dim_t n_ahead; \ inc_t rs_ct, cs_ct; \ conj_t conj0, conj1; \ conj_t conjh_conjx; \ \ /* Eliminate unused variable warnings. */ \ ( void )conjh_conjx; \ \ /* The algorithm will be expressed in terms of the lower triangular case; the upper triangular case is supported by swapping the row and column strides of A and toggling some conj parameters. */ \ if ( bli_is_lower( uplo ) ) \ { \ rs_ct = rs_c; \ cs_ct = cs_c; \ \ PASTEMAC(ch,copys)( *alpha, alpha0 ); \ PASTEMAC(ch,copycjs)( conjh, *alpha, alpha1 ); \ } \ else /* if ( bli_is_upper( uplo ) ) */ \ { \ rs_ct = cs_c; \ cs_ct = rs_c; \ \ /* Toggle conjugation of conjx/conjy, but only if we are being invoked as her2; for syr2, conjx/conjy are unchanged. */ \ conjx = bli_apply_conj( conjh, conjx ); \ conjy = bli_apply_conj( conjh, conjy ); \ \ PASTEMAC(ch,copycjs)( conjh, *alpha, alpha0 ); \ PASTEMAC(ch,copys)( *alpha, alpha1 ); \ } \ \ /* Apply conjh (which carries the conjugation component of the Hermitian transpose, if applicable) to conjx and/or conjy as needed to arrive at the effective conjugation for the vector subproblems. */ \ conj0 = bli_apply_conj( conjh, conjy ); \ conj1 = conjy; \ conjh_conjx = bli_apply_conj( conjh, conjx ); \ \ PASTECH(ch,axpyv_ker_ft) kfp_av; \ \ /* Query the context for the kernel function pointer. */ \ kfp_av = bli_cntx_get_l1v_ker_dt( dt, BLIS_AXPYV_KER, cntx ); \ \ for ( i = 0; i < m; ++i ) \ { \ n_behind = i; \ n_ahead = m - i - 1; \ chi1 = x + (i )*incx; \ y0 = y + (0 )*incy; \ psi1 = y + (i )*incy; \ y2 = y + (i+1)*incy; \ c10t = c + (i )*rs_ct + (0 )*cs_ct; \ gamma11 = c + (i )*rs_ct + (i )*cs_ct; \ c21 = c + (i+1)*rs_ct + (i )*cs_ct; \ \ /* Apply conjx and/or conjy to chi1 and/or psi1. */ \ PASTEMAC(ch,copycjs)( conjx, *chi1, conjx0_chi1 ); \ PASTEMAC(ch,copycjs)( conjh_conjx, *chi1, conjx1_chi1 ); \ PASTEMAC(ch,copycjs)( conj0, *psi1, conjy0_psi1 ); \ \ /* Compute scalars for vector subproblems. */ \ PASTEMAC(ch,scal2s)( alpha0, conjx0_chi1, alpha0_chi1 ); \ PASTEMAC(ch,scal2s)( alpha1, conjx1_chi1, alpha1_chi1 ); \ \ /* Compute alpha * chi1 * conj(psi1) after both chi1 and psi1 have already been conjugated, if needed, by conjx and conjy. */ \ PASTEMAC(ch,scal2s)( alpha0_chi1, conjy0_psi1, alpha0_chi1_psi1 ); \ \ /* c10t = c10t + alpha * chi1 * y0'; */ \ kfp_av \ ( \ conj0, \ n_behind, \ &alpha0_chi1, \ y0, incy, \ c10t, cs_ct, \ cntx \ ); \ \ /* c21 = c21 + conj(alpha) * y2 * conj(chi1); */ \ kfp_av \ ( \ conj1, \ n_ahead, \ &alpha1_chi1, \ y2, incy, \ c21, rs_ct, \ cntx \ ); \ \ /* gamma11 = gamma11 + alpha * chi1 * conj(psi1) \ + conj(alpha) * psi1 * conj(chi1); */ \ PASTEMAC(ch,adds)( alpha0_chi1_psi1, *gamma11 ); \ PASTEMAC(ch,adds)( alpha0_chi1_psi1, *gamma11 ); \ \ /* For her2, explicitly set the imaginary component of gamma11 to zero. */ \ if ( bli_is_conj( conjh ) ) \ PASTEMAC(ch,seti0s)( *gamma11 ); \ } \ } INSERT_GENTFUNC_BASIC0( her2_unb_var3 ) blis-0.9.0/frame/2/her2/bli_her2_unb_var4.c000066400000000000000000000127671422157504600202210ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ uplo_t uplo, \ conj_t conjx, \ conj_t conjy, \ conj_t conjh, \ dim_t m, \ ctype* alpha, \ ctype* x, inc_t incx, \ ctype* y, inc_t incy, \ ctype* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ ctype* chi1; \ ctype* x2; \ ctype* psi1; \ ctype* y2; \ ctype* gamma11; \ ctype* c21; \ ctype alpha0; \ ctype alpha1; \ ctype alpha0_psi1; \ ctype alpha1_chi1; \ ctype alpha0_chi1_psi1; \ ctype conjy0_psi1; \ ctype conjx1_chi1; \ ctype conjx0_chi1; \ dim_t i; \ dim_t n_ahead; \ inc_t rs_ct, cs_ct; \ conj_t conj0, conj1; \ conj_t conjh_conjx; \ conj_t conjh_conjy; \ \ /* Eliminate unused variable warnings. */ \ ( void )conjh_conjx; \ ( void )conjh_conjy; \ \ /* The algorithm will be expressed in terms of the lower triangular case; the upper triangular case is supported by swapping the row and column strides of A and toggling some conj parameters. */ \ if ( bli_is_lower( uplo ) ) \ { \ rs_ct = rs_c; \ cs_ct = cs_c; \ \ PASTEMAC(ch,copys)( *alpha, alpha0 ); \ PASTEMAC(ch,copycjs)( conjh, *alpha, alpha1 ); \ } \ else /* if ( bli_is_upper( uplo ) ) */ \ { \ rs_ct = cs_c; \ cs_ct = rs_c; \ \ /* Toggle conjugation of conjx/conjy, but only if we are being invoked as her2; for syr2, conjx/conjy are unchanged. */ \ conjx = bli_apply_conj( conjh, conjx ); \ conjy = bli_apply_conj( conjh, conjy ); \ \ PASTEMAC(ch,copycjs)( conjh, *alpha, alpha0 ); \ PASTEMAC(ch,copys)( *alpha, alpha1 ); \ } \ \ /* Apply conjh (which carries the conjugation component of the Hermitian transpose, if applicable) to conjx and/or conjy as needed to arrive at the effective conjugation for the vector subproblems. */ \ conj0 = conjx; \ conj1 = conjy; \ conjh_conjx = bli_apply_conj( conjh, conjx ); \ conjh_conjy = bli_apply_conj( conjh, conjy ); \ \ PASTECH(ch,axpyv_ker_ft) kfp_av; \ \ /* Query the context for the kernel function pointer. */ \ kfp_av = bli_cntx_get_l1v_ker_dt( dt, BLIS_AXPYV_KER, cntx ); \ \ for ( i = 0; i < m; ++i ) \ { \ n_ahead = m - i - 1; \ chi1 = x + (i )*incx; \ x2 = x + (i+1)*incx; \ psi1 = y + (i )*incy; \ y2 = y + (i+1)*incy; \ gamma11 = c + (i )*rs_ct + (i )*cs_ct; \ c21 = c + (i+1)*rs_ct + (i )*cs_ct; \ \ /* Apply conjx and/or conjy to chi1 and/or psi1. */ \ PASTEMAC(ch,copycjs)( conjh_conjy, *psi1, conjy0_psi1 ); \ PASTEMAC(ch,copycjs)( conjh_conjx, *chi1, conjx1_chi1 ); \ PASTEMAC(ch,copycjs)( conj0, *chi1, conjx0_chi1 ); \ \ /* Compute scalars for vector subproblems. */ \ PASTEMAC(ch,scal2s)( alpha0, conjy0_psi1, alpha0_psi1 ); \ PASTEMAC(ch,scal2s)( alpha1, conjx1_chi1, alpha1_chi1 ); \ \ /* Compute alpha * chi1 * conj(psi1) after both chi1 and psi1 have already been conjugated, if needed, by conjx and conjy. */ \ PASTEMAC(ch,scal2s)( alpha0_psi1, conjx0_chi1, alpha0_chi1_psi1 ); \ \ /* c21 = c21 + alpha * x2 * conj(psi1); */ \ kfp_av \ ( \ conj0, \ n_ahead, \ &alpha0_psi1, \ x2, incx, \ c21, rs_ct, \ cntx \ ); \ \ /* c21 = c21 + conj(alpha) * y2 * conj(chi1); */ \ kfp_av \ ( \ conj1, \ n_ahead, \ &alpha1_chi1, \ y2, incy, \ c21, rs_ct, \ cntx \ ); \ \ /* gamma11 = gamma11 + alpha * chi1 * conj(psi1) \ + conj(alpha) * psi1 * conj(chi1); */ \ PASTEMAC(ch,adds)( alpha0_chi1_psi1, *gamma11 ); \ PASTEMAC(ch,adds)( alpha0_chi1_psi1, *gamma11 ); \ \ /* For her2, explicitly set the imaginary component of gamma11 to zero. */ \ if ( bli_is_conj( conjh ) ) \ PASTEMAC(ch,seti0s)( *gamma11 ); \ } \ } INSERT_GENTFUNC_BASIC0( her2_unb_var4 ) blis-0.9.0/frame/2/her2/bli_her2_unf_var1.c000066400000000000000000000123501422157504600202060ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ uplo_t uplo, \ conj_t conjx, \ conj_t conjy, \ conj_t conjh, \ dim_t m, \ ctype* alpha, \ ctype* x, inc_t incx, \ ctype* y, inc_t incy, \ ctype* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ ctype* x0; \ ctype* chi1; \ ctype* y0; \ ctype* psi1; \ ctype* c10t; \ ctype* gamma11; \ ctype alpha0; \ ctype alpha1; \ ctype alpha0_chi1; \ ctype alpha1_psi1; \ ctype alpha0_chi1_psi1; \ ctype conjx0_chi1; \ ctype conjy1_psi1; \ ctype conjy0_psi1; \ dim_t i; \ dim_t n_behind; \ inc_t rs_ct, cs_ct; \ conj_t conj0, conj1; \ \ /* The algorithm will be expressed in terms of the lower triangular case; the upper triangular case is supported by swapping the row and column strides of A and toggling some conj parameters. */ \ if ( bli_is_lower( uplo ) ) \ { \ rs_ct = rs_c; \ cs_ct = cs_c; \ \ PASTEMAC(ch,copys)( *alpha, alpha0 ); \ PASTEMAC(ch,copycjs)( conjh, *alpha, alpha1 ); \ } \ else /* if ( bli_is_upper( uplo ) ) */ \ { \ rs_ct = cs_c; \ cs_ct = rs_c; \ \ /* Toggle conjugation of conjx/conjy, but only if we are being invoked as her2; for syr2, conjx/conjy are unchanged. */ \ conjx = bli_apply_conj( conjh, conjx ); \ conjy = bli_apply_conj( conjh, conjy ); \ \ PASTEMAC(ch,copycjs)( conjh, *alpha, alpha0 ); \ PASTEMAC(ch,copys)( *alpha, alpha1 ); \ } \ \ /* Apply conjh (which carries the conjugation component of the Hermitian transpose, if applicable) to conjx and/or conjy as needed to arrive at the effective conjugation for the vector subproblems. */ \ conj0 = bli_apply_conj( conjh, conjy ); \ conj1 = bli_apply_conj( conjh, conjx ); \ \ PASTECH(ch,axpy2v_ker_ft) kfp_2v; \ \ /* Query the context for the kernel function pointer. */ \ kfp_2v = bli_cntx_get_l1f_ker_dt( dt, BLIS_AXPY2V_KER, cntx ); \ \ for ( i = 0; i < m; ++i ) \ { \ n_behind = i; \ x0 = x + (0 )*incx; \ chi1 = x + (i )*incx; \ y0 = y + (0 )*incy; \ psi1 = y + (i )*incy; \ c10t = c + (i )*rs_ct + (0 )*cs_ct; \ gamma11 = c + (i )*rs_ct + (i )*cs_ct; \ \ /* Apply conjx and/or conjy to chi1 and/or psi1. */ \ PASTEMAC(ch,copycjs)( conjx, *chi1, conjx0_chi1 ); \ PASTEMAC(ch,copycjs)( conjy, *psi1, conjy1_psi1 ); \ PASTEMAC(ch,copycjs)( conj0, *psi1, conjy0_psi1 ); \ \ /* Compute scalars for vector subproblems. */ \ PASTEMAC(ch,scal2s)( alpha0, conjx0_chi1, alpha0_chi1 ); \ PASTEMAC(ch,scal2s)( alpha1, conjy1_psi1, alpha1_psi1 ); \ \ /* Compute alpha * chi1 * conj(psi1) after both chi1 and psi1 have already been conjugated, if needed, by conjx and conjy. */ \ PASTEMAC(ch,scal2s)( alpha0_chi1, conjy0_psi1, alpha0_chi1_psi1 ); \ \ /* c10t = c10t + alpha * chi1 * y0'; */ \ /* c10t = c10t + conj(alpha) * psi1 * x0'; */ \ kfp_2v \ ( \ conj0, \ conj1, \ n_behind, \ &alpha0_chi1, \ &alpha1_psi1, \ y0, incy, \ x0, incx, \ c10t, cs_ct, \ cntx \ ); \ \ /* gamma11 = gamma11 + alpha * chi1 * conj(psi1) \ + conj(alpha) * psi1 * conj(chi1); */ \ PASTEMAC(ch,adds)( alpha0_chi1_psi1, *gamma11 ); \ PASTEMAC(ch,adds)( alpha0_chi1_psi1, *gamma11 ); \ \ /* For her2, explicitly set the imaginary component of gamma11 to zero. */ \ if ( bli_is_conj( conjh ) ) \ PASTEMAC(ch,seti0s)( *gamma11 ); \ } \ } INSERT_GENTFUNC_BASIC0( her2_unf_var1 ) blis-0.9.0/frame/2/her2/bli_her2_unf_var4.c000066400000000000000000000126701422157504600202160ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ uplo_t uplo, \ conj_t conjx, \ conj_t conjy, \ conj_t conjh, \ dim_t m, \ ctype* alpha, \ ctype* x, inc_t incx, \ ctype* y, inc_t incy, \ ctype* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ ctype* chi1; \ ctype* x2; \ ctype* psi1; \ ctype* y2; \ ctype* gamma11; \ ctype* c21; \ ctype alpha0; \ ctype alpha1; \ ctype alpha0_psi1; \ ctype alpha1_chi1; \ ctype alpha0_chi1_psi1; \ ctype conjy0_psi1; \ ctype conjx1_chi1; \ ctype conjx0_chi1; \ dim_t i; \ dim_t n_ahead; \ inc_t rs_ct, cs_ct; \ conj_t conj0, conj1; \ conj_t conjh_conjx; \ conj_t conjh_conjy; \ \ /* Eliminate unused variable warnings. */ \ ( void )conjh_conjx; \ ( void )conjh_conjy; \ \ /* The algorithm will be expressed in terms of the lower triangular case; the upper triangular case is supported by swapping the row and column strides of A and toggling some conj parameters. */ \ if ( bli_is_lower( uplo ) ) \ { \ rs_ct = rs_c; \ cs_ct = cs_c; \ \ PASTEMAC(ch,copys)( *alpha, alpha0 ); \ PASTEMAC(ch,copycjs)( conjh, *alpha, alpha1 ); \ } \ else /* if ( bli_is_upper( uplo ) ) */ \ { \ rs_ct = cs_c; \ cs_ct = rs_c; \ \ /* Toggle conjugation of conjx/conjy, but only if we are being invoked as her2; for syr2, conjx/conjy are unchanged. */ \ conjx = bli_apply_conj( conjh, conjx ); \ conjy = bli_apply_conj( conjh, conjy ); \ \ PASTEMAC(ch,copycjs)( conjh, *alpha, alpha0 ); \ PASTEMAC(ch,copys)( *alpha, alpha1 ); \ } \ \ /* Apply conjh (which carries the conjugation component of the Hermitian transpose, if applicable) to conjx and/or conjy as needed to arrive at the effective conjugation for the vector subproblems. */ \ conj0 = conjx; \ conj1 = conjy; \ conjh_conjx = bli_apply_conj( conjh, conjx ); \ conjh_conjy = bli_apply_conj( conjh, conjy ); \ \ PASTECH(ch,axpy2v_ker_ft) kfp_2v; \ \ /* Query the context for the kernel function pointer. */ \ kfp_2v = bli_cntx_get_l1f_ker_dt( dt, BLIS_AXPY2V_KER, cntx ); \ \ for ( i = 0; i < m; ++i ) \ { \ n_ahead = m - i - 1; \ chi1 = x + (i )*incx; \ x2 = x + (i+1)*incx; \ psi1 = y + (i )*incy; \ y2 = y + (i+1)*incy; \ gamma11 = c + (i )*rs_ct + (i )*cs_ct; \ c21 = c + (i+1)*rs_ct + (i )*cs_ct; \ \ /* Apply conjx and/or conjy to chi1 and/or psi1. */ \ PASTEMAC(ch,copycjs)( conjh_conjy, *psi1, conjy0_psi1 ); \ PASTEMAC(ch,copycjs)( conjh_conjx, *chi1, conjx1_chi1 ); \ PASTEMAC(ch,copycjs)( conj0, *chi1, conjx0_chi1 ); \ \ /* Compute scalars for vector subproblems. */ \ PASTEMAC(ch,scal2s)( alpha0, conjy0_psi1, alpha0_psi1 ); \ PASTEMAC(ch,scal2s)( alpha1, conjx1_chi1, alpha1_chi1 ); \ \ /* Compute alpha * chi1 * conj(psi1) after both chi1 and psi1 have already been conjugated, if needed, by conjx and conjy. */ \ PASTEMAC(ch,scal2s)( alpha0_psi1, conjx0_chi1, alpha0_chi1_psi1 ); \ \ /* c21 = c21 + alpha * x2 * conj(psi1); */ \ /* c21 = c21 + conj(alpha) * y2 * conj(chi1); */ \ kfp_2v \ ( \ conj0, \ conj1, \ n_ahead, \ &alpha0_psi1, \ &alpha1_chi1, \ x2, incx, \ y2, incy, \ c21, rs_ct, \ cntx \ ); \ \ /* gamma11 = gamma11 + alpha * chi1 * conj(psi1) \ + conj(alpha) * psi1 * conj(chi1); */ \ PASTEMAC(ch,adds)( alpha0_chi1_psi1, *gamma11 ); \ PASTEMAC(ch,adds)( alpha0_chi1_psi1, *gamma11 ); \ \ /* For her2, explicitly set the imaginary component of gamma11 to zero. */ \ if ( bli_is_conj( conjh ) ) \ PASTEMAC(ch,seti0s)( *gamma11 ); \ } \ } INSERT_GENTFUNC_BASIC0( her2_unf_var4 ) blis-0.9.0/frame/2/her2/bli_her2_var.h000066400000000000000000000055551422157504600172730ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype object-based interfaces. // #undef GENPROT #define GENPROT( opname ) \ \ void PASTEMAC0(opname) \ ( \ conj_t conjh, \ obj_t* alpha, \ obj_t* alpha_conj, \ obj_t* x, \ obj_t* y, \ obj_t* c, \ cntx_t* cntx, \ cntl_t* cntl \ ); GENPROT( her2_blk_var1 ) GENPROT( her2_blk_var2 ) GENPROT( her2_blk_var3 ) GENPROT( her2_blk_var4 ) GENPROT( her2_unb_var1 ) GENPROT( her2_unb_var2 ) GENPROT( her2_unb_var3 ) GENPROT( her2_unb_var4 ) GENPROT( her2_unf_var1 ) GENPROT( her2_unf_var4 ) // // Prototype BLAS-like interfaces with typed operands. // #undef GENTPROT #define GENTPROT( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ uplo_t uplo, \ conj_t conjx, \ conj_t conjy, \ conj_t conjh, \ dim_t m, \ ctype* alpha, \ ctype* x, inc_t incx, \ ctype* y, inc_t incy, \ ctype* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx \ ); INSERT_GENTPROT_BASIC0( her2_unb_var1 ) INSERT_GENTPROT_BASIC0( her2_unb_var2 ) INSERT_GENTPROT_BASIC0( her2_unb_var3 ) INSERT_GENTPROT_BASIC0( her2_unb_var4 ) INSERT_GENTPROT_BASIC0( her2_unf_var1 ) INSERT_GENTPROT_BASIC0( her2_unf_var4 ) blis-0.9.0/frame/2/her2/bli_her2_var_oapi.c000066400000000000000000000062321422157504600202670ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENFRONT #define GENFRONT( opname, varname ) \ \ void PASTEMAC0(varname) \ ( \ conj_t conjh, \ obj_t* alpha, \ obj_t* alpha_conj, \ obj_t* x, \ obj_t* y, \ obj_t* c, \ cntx_t* cntx, \ cntl_t* cntl \ ) \ { \ bli_init_once(); \ \ num_t dt = bli_obj_dt( c ); \ \ uplo_t uplo = bli_obj_uplo( c ); \ conj_t conjx = bli_obj_conj_status( x ); \ conj_t conjy = bli_obj_conj_status( y ); \ \ dim_t m = bli_obj_length( c ); \ \ void* buf_x = bli_obj_buffer_at_off( x ); \ inc_t incx = bli_obj_vector_inc( x ); \ \ void* buf_y = bli_obj_buffer_at_off( y ); \ inc_t incy = bli_obj_vector_inc( y ); \ \ void* buf_c = bli_obj_buffer_at_off( c ); \ inc_t rs_c = bli_obj_row_stride( c ); \ inc_t cs_c = bli_obj_col_stride( c ); \ \ void* buf_alpha = bli_obj_buffer_for_1x1( dt, alpha ); \ \ /* Query a type-specific function pointer, except one that uses void* for function arguments instead of typed pointers. */ \ PASTECH2(opname,_unb,_vft) f = \ PASTEMAC(varname,_qfp)( dt ); \ \ f \ ( \ uplo, \ conjx, \ conjy, \ conjh, \ m, \ buf_alpha, \ buf_x, incx, \ buf_y, incy, \ buf_c, rs_c, cs_c, \ cntx \ ); \ } \ GENFRONT( her2, her2_unb_var1 ) GENFRONT( her2, her2_unb_var2 ) GENFRONT( her2, her2_unb_var3 ) GENFRONT( her2, her2_unb_var4 ) GENFRONT( her2, her2_unf_var1 ) GENFRONT( her2, her2_unf_var4 ) blis-0.9.0/frame/2/her2/other/000077500000000000000000000000001422157504600156735ustar00rootroot00000000000000blis-0.9.0/frame/2/her2/other/bli_her2_blk_var1.c000066400000000000000000000131031422157504600213040ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_her2_blk_var1( conj_t conjh, obj_t* alpha, obj_t* alpha_conj, obj_t* x, obj_t* y, obj_t* c, cntx_t* cntx, her2_t* cntl ) { obj_t c11, c11_pack; obj_t c10; obj_t x1, x1_pack; obj_t x0; obj_t y1, y1_pack; obj_t y0; dim_t mn; dim_t ij; dim_t b_alg; // Even though this blocked algorithm is expressed only in terms of the // lower triangular case, the upper triangular case is still supported: // when bli_acquire_mpart_tl2br() is passed a matrix that is stored in // in the upper triangle, and the requested subpartition resides in the // lower triangle (as is the case for this algorithm), the routine fills // the request as if the caller had actually requested the corresponding // "mirror" subpartition in the upper triangle, except that it marks the // subpartition for transposition (and conjugation). // Initialize objects for packing. bli_obj_init_pack( &c11_pack ); bli_obj_init_pack( &x1_pack ); bli_obj_init_pack( &y1_pack ); // Query dimension. mn = bli_obj_length( c ); // Partition diagonally. for ( ij = 0; ij < mn; ij += b_alg ) { // Determine the current algorithmic blocksize. b_alg = bli_determine_blocksize_f( ij, mn, c, bli_cntl_bszid( cntl ), cntx ); // Acquire partitions for C11, C10, x1, x0, y1, and y0. bli_acquire_mpart_tl2br( BLIS_SUBPART11, ij, b_alg, c, &c11 ); bli_acquire_mpart_tl2br( BLIS_SUBPART10, ij, b_alg, c, &c10 ); bli_acquire_vpart_f2b( BLIS_SUBPART1, ij, b_alg, x, &x1 ); bli_acquire_vpart_f2b( BLIS_SUBPART0, ij, b_alg, x, &x0 ); bli_acquire_vpart_f2b( BLIS_SUBPART1, ij, b_alg, y, &y1 ); bli_acquire_vpart_f2b( BLIS_SUBPART0, ij, b_alg, y, &y0 ); // Initialize objects for packing C11, x1, and y1 (if needed). bli_packm_init( &c11, &c11_pack, cntx, bli_cntl_sub_packm_c11( cntl ) ); bli_packv_init( &x1, &x1_pack, cntx, bli_cntl_sub_packv_x1( cntl ) ); bli_packv_init( &y1, &y1_pack, cntx, bli_cntl_sub_packv_y1( cntl ) ); // Copy/pack C11, x1, y1 (if needed). bli_packm_int( &c11, &c11_pack, cntx, bli_cntl_sub_packm_c11( cntl ), &BLIS_PACKM_SINGLE_THREADED ); bli_packv_int( &x1, &x1_pack, cntx, bli_cntl_sub_packv_x1( cntl ) ); bli_packv_int( &y1, &y1_pack, cntx, bli_cntl_sub_packv_y1( cntl ) ); // C10 = C10 + alpha * x1 * y0'; bli_ger_int( BLIS_NO_CONJUGATE, conjh, alpha, &x1_pack, &y0, &c10, cntx, bli_cntl_sub_ger_rp( cntl ) ); // C10 = C10 + conj(alpha) * y1 * x0'; bli_ger_int( BLIS_NO_CONJUGATE, conjh, alpha_conj, &y1_pack, &x0, &c10, cntx, bli_cntl_sub_ger_rp( cntl ) ); // C11 = C11 + alpha * x1 * y1' + conj(alpha) * y1 * x1'; bli_her2_int( conjh, alpha, alpha_conj, &x1_pack, &y1_pack, &c11_pack, cntx, bli_cntl_sub_her2( cntl ) ); // Copy/unpack C11 (if C11 was packed). bli_unpackm_int( &c11_pack, &c11, cntx, bli_cntl_sub_unpackm_c11( cntl ), &BLIS_PACKM_SINGLE_THREADED ); } // If any packing buffers were acquired within packm, release them back // to the memory manager. bli_packm_release( &c11_pack, bli_cntl_sub_packm_c11( cntl ) ); bli_packv_release( &x1_pack, bli_cntl_sub_packv_x1( cntl ) ); bli_packv_release( &y1_pack, bli_cntl_sub_packv_y1( cntl ) ); } blis-0.9.0/frame/2/her2/other/bli_her2_blk_var2.c000066400000000000000000000132621422157504600213130ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_her2_blk_var2( conj_t conjh, obj_t* alpha, obj_t* alpha_conj, obj_t* x, obj_t* y, obj_t* c, cntx_t* cntx, her2_t* cntl ) { obj_t c11, c11_pack; obj_t c10; obj_t c21; obj_t x1, x1_pack; obj_t x0; obj_t x2; obj_t y1, y1_pack; dim_t mn; dim_t ij; dim_t b_alg; // Even though this blocked algorithm is expressed only in terms of the // lower triangular case, the upper triangular case is still supported: // when bli_acquire_mpart_tl2br() is passed a matrix that is stored in // in the upper triangle, and the requested subpartition resides in the // lower triangle (as is the case for this algorithm), the routine fills // the request as if the caller had actually requested the corresponding // "mirror" subpartition in the upper triangle, except that it marks the // subpartition for transposition (and conjugation). // Initialize objects for packing. bli_obj_init_pack( &c11_pack ); bli_obj_init_pack( &x1_pack ); bli_obj_init_pack( &y1_pack ); // Query dimension. mn = bli_obj_length( c ); // Partition diagonally. for ( ij = 0; ij < mn; ij += b_alg ) { // Determine the current algorithmic blocksize. b_alg = bli_determine_blocksize_f( ij, mn, c, bli_cntl_bszid( cntl ), cntx ); // Acquire partitions for C11, C10, C21, x1, x0, x2, and y1. bli_acquire_mpart_tl2br( BLIS_SUBPART11, ij, b_alg, c, &c11 ); bli_acquire_mpart_tl2br( BLIS_SUBPART10, ij, b_alg, c, &c10 ); bli_acquire_mpart_tl2br( BLIS_SUBPART21, ij, b_alg, c, &c21 ); bli_acquire_vpart_f2b( BLIS_SUBPART1, ij, b_alg, x, &x1 ); bli_acquire_vpart_f2b( BLIS_SUBPART0, ij, b_alg, x, &x0 ); bli_acquire_vpart_f2b( BLIS_SUBPART2, ij, b_alg, x, &x2 ); bli_acquire_vpart_f2b( BLIS_SUBPART1, ij, b_alg, y, &y1 ); // Initialize objects for packing C11, x1, and y1 (if needed). bli_packm_init( &c11, &c11_pack, cntx, bli_cntl_sub_packm_c11( cntl ) ); bli_packv_init( &x1, &x1_pack, cntx, bli_cntl_sub_packv_x1( cntl ) ); bli_packv_init( &y1, &y1_pack, cntx, bli_cntl_sub_packv_y1( cntl ) ); // Copy/pack C11, x1, y1 (if needed). bli_packm_int( &c11, &c11_pack, cntx, bli_cntl_sub_packm_c11( cntl ), &BLIS_PACKM_SINGLE_THREADED ); bli_packv_int( &x1, &x1_pack, cntx, bli_cntl_sub_packv_x1( cntl ) ); bli_packv_int( &y1, &y1_pack, cntx, bli_cntl_sub_packv_y1( cntl ) ); // C10 = C10 + conj(alpha) * y1 * x0'; bli_ger_int( BLIS_NO_CONJUGATE, conjh, alpha_conj, &y1_pack, &x0, &c10, cntx, bli_cntl_sub_ger_rp( cntl ) ); // C21 = C21 + alpha * x2 * y1'; bli_ger_int( BLIS_NO_CONJUGATE, conjh, alpha, &x2, &y1_pack, &c21, cntx, bli_cntl_sub_ger_cp( cntl ) ); // C11 = C11 + alpha * x1 * y1' + conj(alpha) * y1 * x1'; bli_her2_int( conjh, alpha, alpha_conj, &x1_pack, &y1_pack, &c11_pack, cntx, bli_cntl_sub_her2( cntl ) ); // Copy/unpack C11 (if C11 was packed). bli_unpackm_int( &c11_pack, &c11, cntx, bli_cntl_sub_unpackm_c11( cntl ), &BLIS_PACKM_SINGLE_THREADED ); } // If any packing buffers were acquired within packm, release them back // to the memory manager. bli_packm_release( &c11_pack, bli_cntl_sub_packm_c11( cntl ) ); bli_packv_release( &x1_pack, bli_cntl_sub_packv_x1( cntl ) ); bli_packv_release( &y1_pack, bli_cntl_sub_packv_y1( cntl ) ); } blis-0.9.0/frame/2/her2/other/bli_her2_blk_var3.c000066400000000000000000000132621422157504600213140ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_her2_blk_var3( conj_t conjh, obj_t* alpha, obj_t* alpha_conj, obj_t* x, obj_t* y, obj_t* c, cntx_t* cntx, her2_t* cntl ) { obj_t c11, c11_pack; obj_t c10; obj_t c21; obj_t x1, x1_pack; obj_t y1, y1_pack; obj_t y0; obj_t y2; dim_t mn; dim_t ij; dim_t b_alg; // Even though this blocked algorithm is expressed only in terms of the // lower triangular case, the upper triangular case is still supported: // when bli_acquire_mpart_tl2br() is passed a matrix that is stored in // in the upper triangle, and the requested subpartition resides in the // lower triangle (as is the case for this algorithm), the routine fills // the request as if the caller had actually requested the corresponding // "mirror" subpartition in the upper triangle, except that it marks the // subpartition for transposition (and conjugation). // Initialize objects for packing. bli_obj_init_pack( &c11_pack ); bli_obj_init_pack( &x1_pack ); bli_obj_init_pack( &y1_pack ); // Query dimension. mn = bli_obj_length( c ); // Partition diagonally. for ( ij = 0; ij < mn; ij += b_alg ) { // Determine the current algorithmic blocksize. b_alg = bli_determine_blocksize_f( ij, mn, c, bli_cntl_bszid( cntl ), cntx ); // Acquire partitions for C11, C10, C21, x1, y1, y0, and y2. bli_acquire_mpart_tl2br( BLIS_SUBPART11, ij, b_alg, c, &c11 ); bli_acquire_mpart_tl2br( BLIS_SUBPART10, ij, b_alg, c, &c10 ); bli_acquire_mpart_tl2br( BLIS_SUBPART21, ij, b_alg, c, &c21 ); bli_acquire_vpart_f2b( BLIS_SUBPART1, ij, b_alg, x, &x1 ); bli_acquire_vpart_f2b( BLIS_SUBPART1, ij, b_alg, y, &y1 ); bli_acquire_vpart_f2b( BLIS_SUBPART0, ij, b_alg, y, &y0 ); bli_acquire_vpart_f2b( BLIS_SUBPART2, ij, b_alg, y, &y2 ); // Initialize objects for packing C11, x1, and y1 (if needed). bli_packm_init( &c11, &c11_pack, cntx, bli_cntl_sub_packm_c11( cntl ) ); bli_packv_init( &x1, &x1_pack, cntx, bli_cntl_sub_packv_x1( cntl ) ); bli_packv_init( &y1, &y1_pack, cntx, bli_cntl_sub_packv_y1( cntl ) ); // Copy/pack C11, x1, y1 (if needed). bli_packm_int( &c11, &c11_pack, cntx, bli_cntl_sub_packm_c11( cntl ), &BLIS_PACKM_SINGLE_THREADED ); bli_packv_int( &x1, &x1_pack, cntx, bli_cntl_sub_packv_x1( cntl ) ); bli_packv_int( &y1, &y1_pack, cntx, bli_cntl_sub_packv_y1( cntl ) ); // C10 = C10 + alpha * x1 * y0'; bli_ger_int( BLIS_NO_CONJUGATE, conjh, alpha, &x1_pack, &y0, &c10, cntx, bli_cntl_sub_ger_rp( cntl ) ); // C21 = C21 + conj(alpha) * y2 * x1'; bli_ger_int( BLIS_NO_CONJUGATE, conjh, alpha_conj, &y2, &x1_pack, &c21, cntx, bli_cntl_sub_ger_cp( cntl ) ); // C11 = C11 + alpha * x1 * y1' + conj(alpha) * y1 * x1'; bli_her2_int( conjh, alpha, alpha_conj, &x1_pack, &y1_pack, &c11_pack, cntx, bli_cntl_sub_her2( cntl ) ); // Copy/unpack C11 (if C11 was packed). bli_unpackm_int( &c11_pack, &c11, cntx, bli_cntl_sub_unpackm_c11( cntl ), &BLIS_PACKM_SINGLE_THREADED ); } // If any packing buffers were acquired within packm, release them back // to the memory manager. bli_packm_release( &c11_pack, bli_cntl_sub_packm_c11( cntl ) ); bli_packv_release( &x1_pack, bli_cntl_sub_packv_x1( cntl ) ); bli_packv_release( &y1_pack, bli_cntl_sub_packv_y1( cntl ) ); } blis-0.9.0/frame/2/her2/other/bli_her2_blk_var4.c000066400000000000000000000131031422157504600213070ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_her2_blk_var4( conj_t conjh, obj_t* alpha, obj_t* alpha_conj, obj_t* x, obj_t* y, obj_t* c, cntx_t* cntx, her2_t* cntl ) { obj_t c11, c11_pack; obj_t c21; obj_t x1, x1_pack; obj_t x2; obj_t y1, y1_pack; obj_t y2; dim_t mn; dim_t ij; dim_t b_alg; // Even though this blocked algorithm is expressed only in terms of the // lower triangular case, the upper triangular case is still supported: // when bli_acquire_mpart_tl2br() is passed a matrix that is stored in // in the upper triangle, and the requested subpartition resides in the // lower triangle (as is the case for this algorithm), the routine fills // the request as if the caller had actually requested the corresponding // "mirror" subpartition in the upper triangle, except that it marks the // subpartition for transposition (and conjugation). // Initialize objects for packing. bli_obj_init_pack( &c11_pack ); bli_obj_init_pack( &x1_pack ); bli_obj_init_pack( &y1_pack ); // Query dimension. mn = bli_obj_length( c ); // Partition diagonally. for ( ij = 0; ij < mn; ij += b_alg ) { // Determine the current algorithmic blocksize. b_alg = bli_determine_blocksize_f( ij, mn, c, bli_cntl_bszid( cntl ), cntx ); // Acquire partitions for C11, C21, x1, x2, y1, and y2. bli_acquire_mpart_tl2br( BLIS_SUBPART11, ij, b_alg, c, &c11 ); bli_acquire_mpart_tl2br( BLIS_SUBPART21, ij, b_alg, c, &c21 ); bli_acquire_vpart_f2b( BLIS_SUBPART1, ij, b_alg, x, &x1 ); bli_acquire_vpart_f2b( BLIS_SUBPART2, ij, b_alg, x, &x2 ); bli_acquire_vpart_f2b( BLIS_SUBPART1, ij, b_alg, y, &y1 ); bli_acquire_vpart_f2b( BLIS_SUBPART2, ij, b_alg, y, &y2 ); // Initialize objects for packing C11, x1, and y1 (if needed). bli_packm_init( &c11, &c11_pack, cntx, bli_cntl_sub_packm_c11( cntl ) ); bli_packv_init( &x1, &x1_pack, cntx, bli_cntl_sub_packv_x1( cntl ) ); bli_packv_init( &y1, &y1_pack, cntx, bli_cntl_sub_packv_y1( cntl ) ); // Copy/pack C11, x1, y1 (if needed). bli_packm_int( &c11, &c11_pack, cntx, bli_cntl_sub_packm_c11( cntl ), &BLIS_PACKM_SINGLE_THREADED ); bli_packv_int( &x1, &x1_pack, cntx, bli_cntl_sub_packv_x1( cntl ) ); bli_packv_int( &y1, &y1_pack, cntx, bli_cntl_sub_packv_y1( cntl ) ); // C21 = C21 + alpha * x2 * y1'; bli_ger_int( BLIS_NO_CONJUGATE, conjh, alpha, &x2, &y1_pack, &c21, cntx, bli_cntl_sub_ger_cp( cntl ) ); // C21 = C21 + conj(alpha) * y2 * x1'; bli_ger_int( BLIS_NO_CONJUGATE, conjh, alpha_conj, &y2, &x1_pack, &c21, cntx, bli_cntl_sub_ger_cp( cntl ) ); // C11 = C11 + alpha * x1 * y1' + conj(alpha) * y1 * x1'; bli_her2_int( conjh, alpha, alpha_conj, &x1_pack, &y1_pack, &c11_pack, cntx, bli_cntl_sub_her2( cntl ) ); // Copy/unpack C11 (if C11 was packed). bli_unpackm_int( &c11_pack, &c11, cntx, bli_cntl_sub_unpackm_c11( cntl ), &BLIS_PACKM_SINGLE_THREADED ); } // If any packing buffers were acquired within packm, release them back // to the memory manager. bli_packm_release( &c11_pack, bli_cntl_sub_packm_c11( cntl ) ); bli_packv_release( &x1_pack, bli_cntl_sub_packv_x1( cntl ) ); bli_packv_release( &y1_pack, bli_cntl_sub_packv_y1( cntl ) ); } blis-0.9.0/frame/2/her2/other/bli_her2_cntl.c000066400000000000000000000142261422157504600205520ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" extern packm_t* packm_cntl; extern packv_t* packv_cntl; extern unpackm_t* unpackm_cntl; extern ger_t* ger_cntl_rp_bs_row; extern ger_t* ger_cntl_cp_bs_col; her2_t* her2_cntl_bs_ke_lrow_ucol = NULL; her2_t* her2_cntl_bs_ke_lcol_urow = NULL; her2_t* her2_cntl_ge_lrow_ucol = NULL; her2_t* her2_cntl_ge_lcol_urow = NULL; void bli_her2_cntl_init() { // Create control trees for the lowest-level kernels. These trees induce // operations on (persumably) relatively small block-subvector problems. her2_cntl_bs_ke_lrow_ucol = bli_her2_cntl_obj_create( BLIS_UNB_FUSED, BLIS_VARIANT1, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL ); her2_cntl_bs_ke_lcol_urow = bli_her2_cntl_obj_create( BLIS_UNB_FUSED, BLIS_VARIANT4, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL ); // Create control trees for generally large problems. Here, we choose // variants that partition for ger subproblems in the same direction // as the assumed storage. her2_cntl_ge_lrow_ucol = bli_her2_cntl_obj_create( BLIS_BLOCKED, BLIS_VARIANT1, BLIS_M2, packv_cntl, // pack x1 (if needed) packv_cntl, // pack y1 (if needed) packm_cntl, // pack C11 (if needed) ger_cntl_rp_bs_row, ger_cntl_rp_bs_row, her2_cntl_bs_ke_lrow_ucol, unpackm_cntl ); // unpack C11 (if packed) her2_cntl_ge_lcol_urow = bli_her2_cntl_obj_create( BLIS_BLOCKED, BLIS_VARIANT4, BLIS_M2, packv_cntl, // pack x1 (if needed) packv_cntl, // pack y1 (if needed) packm_cntl, // pack C11 (if needed) ger_cntl_cp_bs_col, ger_cntl_cp_bs_col, her2_cntl_bs_ke_lcol_urow, unpackm_cntl ); // unpack C11 (if packed) } void bli_her2_cntl_finalize() { bli_cntl_free_node( her2_cntl_bs_ke_lrow_ucol ); bli_cntl_free_node( her2_cntl_bs_ke_lcol_urow ); bli_cntl_free_node( her2_cntl_ge_lrow_ucol ); bli_cntl_free_node( her2_cntl_ge_lcol_urow ); } her2_t* bli_her2_cntl_obj_create( impl_t impl_type, varnum_t var_num, bszid_t bszid, packv_t* sub_packv_x1, packv_t* sub_packv_y1, packm_t* sub_packm_c11, ger_t* sub_ger_rp, ger_t* sub_ger_cp, her2_t* sub_her2, unpackm_t* sub_unpackm_c11 ) { her2_t* cntl; cntl = ( her2_t* ) bli_malloc_intl( sizeof(her2_t) ); cntl->impl_type = impl_type; cntl->var_num = var_num; cntl->bszid = bszid; cntl->sub_packv_x1 = sub_packv_x1; cntl->sub_packv_y1 = sub_packv_y1; cntl->sub_packm_c11 = sub_packm_c11; cntl->sub_ger_rp = sub_ger_rp; cntl->sub_ger_cp = sub_ger_cp; cntl->sub_her2 = sub_her2; cntl->sub_unpackm_c11 = sub_unpackm_c11; return cntl; } void bli_her2_cntl_obj_init( her2_t* cntl, impl_t impl_type, varnum_t var_num, bszid_t bszid, packv_t* sub_packv_x1, packv_t* sub_packv_y1, packm_t* sub_packm_c11, ger_t* sub_ger_rp, ger_t* sub_ger_cp, her2_t* sub_her2, unpackm_t* sub_unpackm_c11 ) { cntl->impl_type = impl_type; cntl->var_num = var_num; cntl->bszid = bszid; cntl->sub_packv_x1 = sub_packv_x1; cntl->sub_packv_y1 = sub_packv_y1; cntl->sub_packm_c11 = sub_packm_c11; cntl->sub_ger_rp = sub_ger_rp; cntl->sub_ger_cp = sub_ger_cp; cntl->sub_her2 = sub_her2; cntl->sub_unpackm_c11 = sub_unpackm_c11; } blis-0.9.0/frame/2/her2/other/bli_her2_cntl.h000066400000000000000000000063701422157504600205600ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ struct her2_s { impl_t impl_type; varnum_t var_num; bszid_t bszid; struct packv_s* sub_packv_x1; struct packv_s* sub_packv_y1; struct packm_s* sub_packm_c11; struct ger_s* sub_ger_rp; struct ger_s* sub_ger_cp; struct her2_s* sub_her2; struct unpackm_s* sub_unpackm_c11; }; typedef struct her2_s her2_t; #define bli_cntl_sub_her2( cntl ) cntl->sub_her2 void bli_her2_cntl_init( void ); void bli_her2_cntl_finalize( void ); her2_t* bli_her2_cntl_obj_create( impl_t impl_type, varnum_t var_num, bszid_t bszid, packv_t* sub_packv_x1, packv_t* sub_packv_y1, packm_t* sub_packm_c11, ger_t* sub_ger_rp, ger_t* sub_ger_cp, her2_t* sub_her2, unpackm_t* sub_unpackm_c11 ); void bli_her2_cntl_obj_init( her2_t* cntl, impl_t impl_type, varnum_t var_num, bszid_t bszid, packv_t* sub_packv_x1, packv_t* sub_packv_y1, packm_t* sub_packm_c11, ger_t* sub_ger_rp, ger_t* sub_ger_cp, her2_t* sub_her2, unpackm_t* sub_unpackm_c11 ); blis-0.9.0/frame/2/her2/other/bli_her2_front.c000066400000000000000000000152131422157504600207370ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" extern her2_t* her2_cntl_bs_ke_lrow_ucol; extern her2_t* her2_cntl_bs_ke_lcol_urow; extern her2_t* her2_cntl_ge_lrow_ucol; extern her2_t* her2_cntl_ge_lcol_urow; void bli_her2_front ( obj_t* alpha, obj_t* x, obj_t* y, obj_t* c, cntx_t* cntx ) { her2_t* her2_cntl; num_t dt_targ_x; num_t dt_targ_y; //num_t dt_targ_c; bool x_has_unit_inc; bool y_has_unit_inc; bool c_has_unit_inc; obj_t alpha_local; obj_t alpha_conj_local; num_t dt_alpha; // Check parameters. if ( bli_error_checking_is_enabled() ) bli_her2_check( alpha, x, y, c ); // Query the target datatypes of each object. dt_targ_x = bli_obj_target_dt( x ); dt_targ_y = bli_obj_target_dt( y ); //dt_targ_c = bli_obj_target_dt( c ); // Determine whether each operand with unit stride. x_has_unit_inc = ( bli_obj_vector_inc( x ) == 1 ); y_has_unit_inc = ( bli_obj_vector_inc( y ) == 1 ); c_has_unit_inc = ( bli_obj_is_row_stored( c ) || bli_obj_is_col_stored( c ) ); // Create an object to hold a copy-cast of alpha. Notice that we use // the type union of the datatypes of x and y. dt_alpha = bli_dt_union( dt_targ_x, dt_targ_y ); bli_obj_scalar_init_detached_copy_of( dt_alpha, BLIS_NO_CONJUGATE, alpha, &alpha_local ); // Also create a conjugated copy of alpha. bli_obj_scalar_init_detached_copy_of( dt_alpha, BLIS_CONJUGATE, alpha, &alpha_conj_local ); // If all operands have unit stride, we choose a control tree for calling // the unblocked implementation directly without any blocking. if ( x_has_unit_inc && y_has_unit_inc && c_has_unit_inc ) { // We use two control trees to handle the four cases corresponding to // combinations of upper/lower triangular storage and row/column-storage. // The row-stored lower triangular and column-stored upper triangular // trees are identical. Same for the remaining two trees. if ( bli_obj_is_lower( c ) ) { if ( bli_obj_is_row_stored( c ) ) her2_cntl = her2_cntl_bs_ke_lrow_ucol; else her2_cntl = her2_cntl_bs_ke_lcol_urow; } else // if ( bli_obj_is_upper( c ) ) { if ( bli_obj_is_row_stored( c ) ) her2_cntl = her2_cntl_bs_ke_lcol_urow; else her2_cntl = her2_cntl_bs_ke_lrow_ucol; } } else { // Mark objects with unit stride as already being packed. This prevents // unnecessary packing from happening within the blocked algorithm. if ( x_has_unit_inc ) bli_obj_set_pack_schema( BLIS_PACKED_VECTOR, x ); if ( y_has_unit_inc ) bli_obj_set_pack_schema( BLIS_PACKED_VECTOR, y ); if ( c_has_unit_inc ) bli_obj_set_pack_schema( BLIS_PACKED_UNSPEC, c ); // Here, we make a similar choice as above, except that (1) we look // at storage tilt, and (2) we choose a tree that performs blocking. if ( bli_obj_is_lower( c ) ) { if ( bli_obj_is_row_stored( c ) ) her2_cntl = her2_cntl_ge_lrow_ucol; else her2_cntl = her2_cntl_ge_lcol_urow; } else // if ( bli_obj_is_upper( c ) ) { if ( bli_obj_is_row_stored( c ) ) her2_cntl = her2_cntl_ge_lcol_urow; else her2_cntl = her2_cntl_ge_lrow_ucol; } } // Invoke the internal back-end with the copy-cast scalar and the // chosen control tree. Set conjh to BLIS_CONJUGATE to invoke the // Hermitian (and not symmetric) algorithms. bli_her2_int( BLIS_CONJUGATE, &alpha_local, &alpha_conj_local, x, y, c, cntx, her2_cntl ); } // // Define BLAS-like interfaces with homogeneous-typed operands. // #undef GENTFUNC #define GENTFUNC( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ uplo_t uploc, \ conj_t conjx, \ conj_t conjy, \ dim_t m, \ ctype* alpha, \ ctype* x, inc_t incx, \ ctype* y, inc_t incy, \ ctype* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ obj_t alphao, xo, yo, co; \ \ inc_t rs_x, cs_x; \ inc_t rs_y, cs_y; \ \ rs_x = incx; cs_x = m * incx; \ rs_y = incy; cs_y = m * incy; \ \ bli_obj_create_1x1_with_attached_buffer( dt, alpha, &alphao ); \ \ bli_obj_create_with_attached_buffer( dt, m, 1, x, rs_x, cs_x, &xo ); \ bli_obj_create_with_attached_buffer( dt, m, 1, y, rs_y, cs_y, &yo ); \ bli_obj_create_with_attached_buffer( dt, m, m, c, rs_c, cs_c, &co ); \ \ bli_obj_set_conj( conjx, &xo ); \ bli_obj_set_conj( conjy, &yo ); \ bli_obj_set_uplo( uploc, &co ); \ \ bli_obj_set_struc( BLIS_HERMITIAN, &co ); \ \ PASTEMAC0(opname)( &alphao, \ &xo, \ &yo, \ &co, \ cntx ); \ } INSERT_GENTFUNC_BASIC0( her2_front ) blis-0.9.0/frame/2/her2/other/bli_her2_front.h000066400000000000000000000042321422157504600207430ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void bli_her2_front ( obj_t* alpha, obj_t* x, obj_t* y, obj_t* c, cntx_t* cntx ); #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ uplo_t uploc, \ conj_t conjx, \ conj_t conjy, \ dim_t m, \ ctype* alpha, \ ctype* x, inc_t incx, \ ctype* y, inc_t incy, \ ctype* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx \ ); INSERT_GENTPROT_BASIC( her2_front ) blis-0.9.0/frame/2/her2/other/bli_her2_int.c000066400000000000000000000107341422157504600204040ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define FUNCPTR_T her2_fp typedef void (*FUNCPTR_T)( conj_t conjh, obj_t* alpha, obj_t* alpha_conj, obj_t* x, obj_t* y, obj_t* c, cntx_t* cntx, her2_t* cntl ); static FUNCPTR_T vars[4][3] = { // unblocked unblocked with fusing blocked { bli_her2_unb_var1, bli_her2_unf_var1, bli_her2_blk_var1 }, { bli_her2_unb_var2, NULL, bli_her2_blk_var2 }, { bli_her2_unb_var3, NULL, bli_her2_blk_var3 }, { bli_her2_unb_var4, bli_her2_unf_var4, bli_her2_blk_var4 }, }; void bli_her2_int( conj_t conjh, obj_t* alpha, obj_t* alpha_conj, obj_t* x, obj_t* y, obj_t* c, cntx_t* cntx, her2_t* cntl ) { varnum_t n; impl_t i; FUNCPTR_T f; obj_t alpha_local; obj_t alpha_conj_local; obj_t x_local; obj_t y_local; obj_t c_local; // Check parameters. if ( bli_error_checking_is_enabled() ) { if ( bli_is_conj( conjh ) ) bli_her2_check( alpha, x, y, c ); else bli_syr2_check( alpha, x, y, c ); } // If C, x, or y has a zero dimension, return early. if ( bli_obj_has_zero_dim( c ) ) return; if ( bli_obj_has_zero_dim( x ) ) return; if ( bli_obj_has_zero_dim( y ) ) return; // Alias the operands in case we need to apply conjugations. bli_obj_alias_to( x, &x_local ); bli_obj_alias_to( y, &y_local ); bli_obj_alias_to( c, &c_local ); // If matrix C is marked for conjugation, we interpret this as a request // to apply a conjugation to the other operands. if ( bli_obj_has_conj( &c_local ) ) { bli_obj_toggle_conj( &c_local ); bli_obj_toggle_conj( &x_local ); bli_obj_toggle_conj( &y_local ); bli_obj_scalar_init_detached_copy_of( bli_obj_dt( alpha ), BLIS_CONJUGATE, alpha, &alpha_local ); bli_obj_scalar_init_detached_copy_of( bli_obj_dt( alpha_conj ), BLIS_CONJUGATE, alpha_conj, &alpha_conj_local ); } else { bli_obj_alias_to( *alpha, alpha_local ); bli_obj_alias_to( *alpha_conj, alpha_conj_local ); } // Extract the variant number and implementation type. n = bli_cntl_var_num( cntl ); i = bli_cntl_impl_type( cntl ); // Index into the variant array to extract the correct function pointer. f = vars[n][i]; // Invoke the variant. f( conjh, &alpha_local, &alpha_conj_local, &x_local, &y_local, &c_local, cntx, cntl ); } blis-0.9.0/frame/2/her2/other/bli_her2_int.h000066400000000000000000000036231422157504600204100ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void bli_her2_int( conj_t conjh, obj_t* alpha, obj_t* alpha_conj, obj_t* x, obj_t* y, obj_t* c, cntx_t* cntx, her2_t* cntl ); blis-0.9.0/frame/2/symv/000077500000000000000000000000001422157504600147105ustar00rootroot00000000000000blis-0.9.0/frame/2/symv/bli_symv.h000066400000000000000000000033441422157504600167110ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // NOTE: level-2 control tree code is temporarily disabled. //#include "bli_symv_front.h" blis-0.9.0/frame/2/symv/other/000077500000000000000000000000001422157504600160315ustar00rootroot00000000000000blis-0.9.0/frame/2/symv/other/bli_symv_front.c000066400000000000000000000162641422157504600212420ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" extern hemv_t* hemv_cntl_bs_ke_lrow_ucol; extern hemv_t* hemv_cntl_bs_ke_lcol_urow; extern hemv_t* hemv_cntl_ge_lrow_ucol; extern hemv_t* hemv_cntl_ge_lcol_urow; void bli_symv_front ( obj_t* alpha, obj_t* a, obj_t* x, obj_t* beta, obj_t* y, cntx_t* cntx ) { hemv_t* hemv_cntl; num_t dt_targ_a; num_t dt_targ_x; num_t dt_targ_y; bool a_has_unit_inc; bool x_has_unit_inc; bool y_has_unit_inc; obj_t alpha_local; obj_t beta_local; num_t dt_alpha; num_t dt_beta; // Check parameters. if ( bli_error_checking_is_enabled() ) bli_symv_check( alpha, a, x, beta, y ); // Query the target datatypes of each object. dt_targ_a = bli_obj_target_dt( a ); dt_targ_x = bli_obj_target_dt( x ); dt_targ_y = bli_obj_target_dt( y ); // Determine whether each operand with unit stride. a_has_unit_inc = ( bli_obj_is_row_stored( a ) || bli_obj_is_col_stored( a ) ); x_has_unit_inc = ( bli_obj_vector_inc( x ) == 1 ); y_has_unit_inc = ( bli_obj_vector_inc( y ) == 1 ); // Create an object to hold a copy-cast of alpha. Notice that we use // the type union of the target datatypes of a and x to prevent any // unnecessary loss of information during the computation. dt_alpha = bli_dt_union( dt_targ_a, dt_targ_x ); bli_obj_scalar_init_detached_copy_of( dt_alpha, BLIS_NO_CONJUGATE, alpha, &alpha_local ); // Create an object to hold a copy-cast of beta. Notice that we use // the datatype of y. Here's why: If y is real and beta is complex, // there is no reason to keep beta_local in the complex domain since // the complex part of beta*y will not be stored. If y is complex and // beta is real then beta is harmlessly promoted to complex. dt_beta = dt_targ_y; bli_obj_scalar_init_detached_copy_of( dt_beta, BLIS_NO_CONJUGATE, beta, &beta_local ); // If all operands have unit stride, we choose a control tree for calling // the unblocked implementation directly without any blocking. if ( a_has_unit_inc && x_has_unit_inc && y_has_unit_inc ) { // We use two control trees to handle the four cases corresponding to // combinations of upper/lower triangular storage and row/column-storage. // The row-stored lower triangular and column-stored upper triangular // trees are identical. Same for the remaining two trees. if ( bli_obj_is_lower( a ) ) { if ( bli_obj_is_row_stored( a ) ) hemv_cntl = hemv_cntl_bs_ke_lrow_ucol; else hemv_cntl = hemv_cntl_bs_ke_lcol_urow; } else // if ( bli_obj_is_upper( a ) ) { if ( bli_obj_is_row_stored( a ) ) hemv_cntl = hemv_cntl_bs_ke_lcol_urow; else hemv_cntl = hemv_cntl_bs_ke_lrow_ucol; } } else { // Mark objects with unit stride as already being packed. This prevents // unnecessary packing from happening within the blocked algorithm. if ( a_has_unit_inc ) bli_obj_set_pack_schema( BLIS_PACKED_UNSPEC, a ); if ( x_has_unit_inc ) bli_obj_set_pack_schema( BLIS_PACKED_VECTOR, x ); if ( y_has_unit_inc ) bli_obj_set_pack_schema( BLIS_PACKED_VECTOR, y ); // Here, we make a similar choice as above, except that (1) we look // at storage tilt, and (2) we choose a tree that performs blocking. if ( bli_obj_is_lower( a ) ) { if ( bli_obj_is_row_tilted( a ) ) hemv_cntl = hemv_cntl_ge_lrow_ucol; else hemv_cntl = hemv_cntl_ge_lcol_urow; } else // if ( bli_obj_is_upper( a ) ) { if ( bli_obj_is_row_tilted( a ) ) hemv_cntl = hemv_cntl_ge_lcol_urow; else hemv_cntl = hemv_cntl_ge_lrow_ucol; } } // Invoke the internal back-end with the copy-casts of scalars and the // chosen control tree. Set conjh to BLIS_NO_CONJUGATE to invoke the // symmetric (and not Hermitian) algorithms. bli_hemv_int( BLIS_NO_CONJUGATE, &alpha_local, a, x, &beta_local, y, cntx, hemv_cntl ); } // // Define BLAS-like interfaces with homogeneous-typed operands. // #undef GENTFUNC #define GENTFUNC( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ uplo_t uploa, \ conj_t conja, \ conj_t conjx, \ dim_t m, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* x, inc_t incx, \ ctype* beta, \ ctype* y, inc_t incy, \ cntx_t* cntx \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ obj_t alphao, ao, xo, betao, yo; \ \ inc_t rs_x, cs_x; \ inc_t rs_y, cs_y; \ \ rs_x = incx; cs_x = m * incx; \ rs_y = incy; cs_y = m * incy; \ \ bli_obj_create_1x1_with_attached_buffer( dt, alpha, &alphao ); \ bli_obj_create_1x1_with_attached_buffer( dt, beta, &betao ); \ \ bli_obj_create_with_attached_buffer( dt, m, m, a, rs_a, cs_a, &ao ); \ bli_obj_create_with_attached_buffer( dt, m, 1, x, rs_x, cs_x, &xo ); \ bli_obj_create_with_attached_buffer( dt, m, 1, y, rs_y, cs_y, &yo ); \ \ bli_obj_set_uplo( uploa, &ao ); \ bli_obj_set_conj( conja, &ao ); \ bli_obj_set_conj( conjx, &xo ); \ \ bli_obj_set_struc( BLIS_SYMMETRIC, &ao ); \ \ PASTEMAC0(opname)( &alphao, \ &ao, \ &xo, \ &betao, \ &yo, \ cntx ); \ } INSERT_GENTFUNC_BASIC0( symv_front ) blis-0.9.0/frame/2/symv/other/bli_symv_front.h000066400000000000000000000042761422157504600212470ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void bli_symv_front ( obj_t* alpha, obj_t* a, obj_t* x, obj_t* beta, obj_t* y, cntx_t* cntx ); #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ uplo_t uploa, \ conj_t conja, \ conj_t conjx, \ dim_t m, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* x, inc_t incx, \ ctype* beta, \ ctype* y, inc_t incy, \ cntx_t* cntx \ ); INSERT_GENTPROT_BASIC( symv_front ) blis-0.9.0/frame/2/syr/000077500000000000000000000000001422157504600145275ustar00rootroot00000000000000blis-0.9.0/frame/2/syr/bli_syr.h000066400000000000000000000033431422157504600163460ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // NOTE: level-2 control tree code is temporarily disabled. //#include "bli_syr_front.h" blis-0.9.0/frame/2/syr/other/000077500000000000000000000000001422157504600156505ustar00rootroot00000000000000blis-0.9.0/frame/2/syr/other/bli_syr_front.c000066400000000000000000000135601422157504600206740ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" extern her_t* her_cntl_bs_ke_lrow_ucol; extern her_t* her_cntl_bs_ke_lcol_urow; extern her_t* her_cntl_ge_lrow_ucol; extern her_t* her_cntl_ge_lcol_urow; void bli_syr_front ( obj_t* alpha, obj_t* x, obj_t* c, cntx_t* cntx ) { her_t* her_cntl; num_t dt_targ_x; num_t dt_targ_c; bool x_has_unit_inc; bool c_has_unit_inc; obj_t alpha_local; num_t dt_alpha; // Check parameters. if ( bli_error_checking_is_enabled() ) bli_syr_check( alpha, x, c ); // Query the target datatypes of each object. dt_targ_x = bli_obj_target_dt( x ); dt_targ_c = bli_obj_target_dt( c ); // Determine whether each operand with unit stride. x_has_unit_inc = ( bli_obj_vector_inc( x ) == 1 ); c_has_unit_inc = ( bli_obj_is_row_stored( c ) || bli_obj_is_col_stored( c ) ); // Create an object to hold a copy-cast of alpha. Notice that we use // the type union of the target datatypes of x and c to prevent any // unnecessary loss of information during the computation. dt_alpha = bli_dt_union( dt_targ_x, dt_targ_c ); bli_obj_scalar_init_detached_copy_of( dt_alpha, BLIS_NO_CONJUGATE, alpha, &alpha_local ); // If all operands have unit stride, we choose a control tree for calling // the unblocked implementation directly without any blocking. if ( x_has_unit_inc && c_has_unit_inc ) { // We use two control trees to handle the four cases corresponding to // combinations of upper/lower triangular storage and row/column-storage. // The row-stored lower triangular and column-stored upper triangular // trees are identical. Same for the remaining two trees. if ( bli_obj_is_lower( c ) ) { if ( bli_obj_is_row_stored( c ) ) her_cntl = her_cntl_bs_ke_lrow_ucol; else her_cntl = her_cntl_bs_ke_lcol_urow; } else // if ( bli_obj_is_upper( c ) ) { if ( bli_obj_is_row_stored( c ) ) her_cntl = her_cntl_bs_ke_lcol_urow; else her_cntl = her_cntl_bs_ke_lrow_ucol; } } else { // Mark objects with unit stride as already being packed. This prevents // unnecessary packing from happening within the blocked algorithm. if ( x_has_unit_inc ) bli_obj_set_pack_schema( BLIS_PACKED_VECTOR, x ); if ( c_has_unit_inc ) bli_obj_set_pack_schema( BLIS_PACKED_UNSPEC, c ); // Here, we make a similar choice as above, except that (1) we look // at storage tilt, and (2) we choose a tree that performs blocking. if ( bli_obj_is_lower( c ) ) { if ( bli_obj_is_row_stored( c ) ) her_cntl = her_cntl_ge_lrow_ucol; else her_cntl = her_cntl_ge_lcol_urow; } else // if ( bli_obj_is_upper( c ) ) { if ( bli_obj_is_row_stored( c ) ) her_cntl = her_cntl_ge_lcol_urow; else her_cntl = her_cntl_ge_lrow_ucol; } } // Invoke the internal back-end with the copy-cast scalar and the // chosen control tree. Set conjh to BLIS_NO_CONJUGATE to invoke the // symmetric (and not Hermitian) algorithms. bli_her_int( BLIS_NO_CONJUGATE, &alpha_local, x, c, cntx, her_cntl ); } // // Define BLAS-like interfaces with homogeneous-typed operands. // #undef GENTFUNC #define GENTFUNC( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ uplo_t uploc, \ conj_t conjx, \ dim_t m, \ ctype* alpha, \ ctype* x, inc_t incx, \ ctype* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ obj_t alphao, xo, co; \ \ inc_t rs_x, cs_x; \ \ rs_x = incx; cs_x = m * incx; \ \ bli_obj_create_1x1_with_attached_buffer( dt, alpha, &alphao ); \ \ bli_obj_create_with_attached_buffer( dt, m, 1, x, rs_x, cs_x, &xo ); \ bli_obj_create_with_attached_buffer( dt, m, m, c, rs_c, cs_c, &co ); \ \ bli_obj_set_conj( conjx, &xo ); \ bli_obj_set_uplo( uploc, &co ); \ \ bli_obj_set_struc( BLIS_SYMMETRIC, &co ); \ \ PASTEMAC0(opname)( &alphao, \ &xo, \ &co, \ cntx ); \ } INSERT_GENTFUNC_BASIC0( syr_front ) blis-0.9.0/frame/2/syr/other/bli_syr_front.h000066400000000000000000000041141422157504600206740ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void bli_syr_front ( obj_t* alpha, obj_t* x, obj_t* c, cntx_t* cntx ); #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ uplo_t uploc, \ conj_t conjx, \ dim_t m, \ ctype* alpha, \ ctype* x, inc_t incx, \ ctype* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx \ ); INSERT_GENTPROT_BASIC( syr_front ) blis-0.9.0/frame/2/syr2/000077500000000000000000000000001422157504600146115ustar00rootroot00000000000000blis-0.9.0/frame/2/syr2/bli_syr2.h000066400000000000000000000033441422157504600165130ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // NOTE: level-2 control tree code is temporarily disabled. //#include "bli_syr2_front.h" blis-0.9.0/frame/2/syr2/other/000077500000000000000000000000001422157504600157325ustar00rootroot00000000000000blis-0.9.0/frame/2/syr2/other/bli_syr2_front.c000066400000000000000000000145621422157504600210430ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" extern her2_t* her2_cntl_bs_ke_lrow_ucol; extern her2_t* her2_cntl_bs_ke_lcol_urow; extern her2_t* her2_cntl_ge_lrow_ucol; extern her2_t* her2_cntl_ge_lcol_urow; void bli_syr2_front ( obj_t* alpha, obj_t* x, obj_t* y, obj_t* c, cntx_t* cntx ) { her2_t* her2_cntl; num_t dt_targ_x; num_t dt_targ_y; //num_t dt_targ_c; bool x_has_unit_inc; bool y_has_unit_inc; bool c_has_unit_inc; obj_t alpha_local; num_t dt_alpha; // Check parameters. if ( bli_error_checking_is_enabled() ) bli_syr2_check( alpha, x, y, c ); // Query the target datatypes of each object. dt_targ_x = bli_obj_target_dt( x ); dt_targ_y = bli_obj_target_dt( y ); //dt_targ_c = bli_obj_target_dt( c ); // Determine whether each operand with unit stride. x_has_unit_inc = ( bli_obj_vector_inc( x ) == 1 ); y_has_unit_inc = ( bli_obj_vector_inc( y ) == 1 ); c_has_unit_inc = ( bli_obj_is_row_stored( c ) || bli_obj_is_col_stored( c ) ); // Create an object to hold a copy-cast of alpha. Notice that we use // the type union of the datatypes of x and y. dt_alpha = bli_dt_union( dt_targ_x, dt_targ_y ); bli_obj_scalar_init_detached_copy_of( dt_alpha, BLIS_NO_CONJUGATE, alpha, &alpha_local ); // If all operands have unit stride, we choose a control tree for calling // the unblocked implementation directly without any blocking. if ( x_has_unit_inc && y_has_unit_inc && c_has_unit_inc ) { // We use two control trees to handle the four cases corresponding to // combinations of upper/lower triangular storage and row/column-storage. // The row-stored lower triangular and column-stored upper triangular // trees are identical. Same for the remaining two trees. if ( bli_obj_is_lower( c ) ) { if ( bli_obj_is_row_stored( c ) ) her2_cntl = her2_cntl_bs_ke_lrow_ucol; else her2_cntl = her2_cntl_bs_ke_lcol_urow; } else // if ( bli_obj_is_upper( c ) ) { if ( bli_obj_is_row_stored( c ) ) her2_cntl = her2_cntl_bs_ke_lcol_urow; else her2_cntl = her2_cntl_bs_ke_lrow_ucol; } } else { // Mark objects with unit stride as already being packed. This prevents // unnecessary packing from happening within the blocked algorithm. if ( x_has_unit_inc ) bli_obj_set_pack_schema( BLIS_PACKED_VECTOR, x ); if ( y_has_unit_inc ) bli_obj_set_pack_schema( BLIS_PACKED_VECTOR, y ); if ( c_has_unit_inc ) bli_obj_set_pack_schema( BLIS_PACKED_UNSPEC, c ); // Here, we make a similar choice as above, except that (1) we look // at storage tilt, and (2) we choose a tree that performs blocking. if ( bli_obj_is_lower( c ) ) { if ( bli_obj_is_row_stored( c ) ) her2_cntl = her2_cntl_ge_lrow_ucol; else her2_cntl = her2_cntl_ge_lcol_urow; } else // if ( bli_obj_is_upper( c ) ) { if ( bli_obj_is_row_stored( c ) ) her2_cntl = her2_cntl_ge_lcol_urow; else her2_cntl = her2_cntl_ge_lrow_ucol; } } // Invoke the internal back-end with the copy-cast scalar and the // chosen control tree. Set conjh to BLIS_NO_CONJUGATE to invoke the // symmetric (and not Hermitian) algorithms. bli_her2_int( BLIS_NO_CONJUGATE, &alpha_local, &alpha_local, x, y, c, cntx, her2_cntl ); } // // Define BLAS-like interfaces with homogeneous-typed operands. // #undef GENTFUNC #define GENTFUNC( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ uplo_t uploc, \ conj_t conjx, \ conj_t conjy, \ dim_t m, \ ctype* alpha, \ ctype* x, inc_t incx, \ ctype* y, inc_t incy, \ ctype* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ obj_t alphao, xo, yo, co; \ \ inc_t rs_x, cs_x; \ inc_t rs_y, cs_y; \ \ rs_x = incx; cs_x = m * incx; \ rs_y = incy; cs_y = m * incy; \ \ bli_obj_create_1x1_with_attached_buffer( dt, alpha, &alphao ); \ \ bli_obj_create_with_attached_buffer( dt, m, 1, x, rs_x, cs_x, &xo ); \ bli_obj_create_with_attached_buffer( dt, m, 1, y, rs_y, cs_y, &yo ); \ bli_obj_create_with_attached_buffer( dt, m, m, c, rs_c, cs_c, &co ); \ \ bli_obj_set_conj( conjx, &xo ); \ bli_obj_set_conj( conjy, &yo ); \ bli_obj_set_uplo( uploc, &co ); \ \ bli_obj_set_struc( BLIS_SYMMETRIC, &co ); \ \ PASTEMAC0(opname)( &alphao, \ &xo, \ &yo, \ &co, \ cntx ); \ } INSERT_GENTFUNC_BASIC0( syr2_front ) blis-0.9.0/frame/2/syr2/other/bli_syr2_front.h000066400000000000000000000042321422157504600210410ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void bli_syr2_front ( obj_t* alpha, obj_t* x, obj_t* y, obj_t* c, cntx_t* cntx ); #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ uplo_t uploc, \ conj_t conjx, \ conj_t conjy, \ dim_t m, \ ctype* alpha, \ ctype* x, inc_t incx, \ ctype* y, inc_t incy, \ ctype* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx \ ); INSERT_GENTPROT_BASIC( syr2_front ) blis-0.9.0/frame/2/trmv/000077500000000000000000000000001422157504600147025ustar00rootroot00000000000000blis-0.9.0/frame/2/trmv/bli_trmv.h000066400000000000000000000034701422157504600166750ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // NOTE: level-2 control tree code is temporarily disabled. //#include "bli_trmv_cntl.h" //#include "bli_trmv_front.h" //#include "bli_trmv_int.h" #include "bli_trmv_var.h" blis-0.9.0/frame/2/trmv/bli_trmv_unb_var1.c000066400000000000000000000106521422157504600204650ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ uplo_t uploa, \ trans_t transa, \ diag_t diaga, \ dim_t m, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* x, inc_t incx, \ cntx_t* cntx \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ ctype* a10t; \ ctype* alpha11; \ ctype* a12t; \ ctype* x0; \ ctype* chi1; \ ctype* x2; \ ctype alpha_alpha11_conj; \ ctype rho; \ dim_t iter, i; \ dim_t n_ahead; \ inc_t rs_at, cs_at; \ uplo_t uploa_trans; \ conj_t conja; \ \ if ( bli_does_notrans( transa ) ) \ { \ rs_at = rs_a; \ cs_at = cs_a; \ uploa_trans = uploa; \ } \ else /* if ( bli_does_trans( transa ) ) */ \ { \ rs_at = cs_a; \ cs_at = rs_a; \ uploa_trans = bli_uplo_toggled( uploa ); \ } \ \ conja = bli_extract_conj( transa ); \ \ PASTECH(ch,dotv_ker_ft) kfp_dv; \ \ /* Query the context for the kernel function pointer. */ \ kfp_dv = bli_cntx_get_l1v_ker_dt( dt, BLIS_DOTV_KER, cntx ); \ \ /* We reduce all of the possible cases down to just lower/upper. */ \ if ( bli_is_upper( uploa_trans ) ) \ { \ for ( iter = 0; iter < m; ++iter ) \ { \ i = iter; \ n_ahead = m - iter - 1; \ alpha11 = a + (i )*rs_at + (i )*cs_at; \ a12t = a + (i )*rs_at + (i+1)*cs_at; \ chi1 = x + (i )*incx; \ x2 = x + (i+1)*incx; \ \ /* chi1 = alpha * alpha11 * chi1; */ \ PASTEMAC(ch,copys)( *alpha, alpha_alpha11_conj ); \ if ( bli_is_nonunit_diag( diaga ) ) \ PASTEMAC(ch,scalcjs)( conja, *alpha11, alpha_alpha11_conj ); \ PASTEMAC(ch,scals)( alpha_alpha11_conj, *chi1 ); \ \ /* chi1 = chi1 + alpha * a12t * x2; */ \ kfp_dv \ ( \ conja, \ BLIS_NO_CONJUGATE, \ n_ahead, \ a12t, cs_at, \ x2, incx, \ &rho, \ cntx \ ); \ PASTEMAC(ch,axpys)( *alpha, rho, *chi1 ); \ } \ } \ else /* if ( bli_is_lower( uploa_trans ) ) */ \ { \ for ( iter = 0; iter < m; ++iter ) \ { \ i = m - iter - 1; \ n_ahead = i; \ alpha11 = a + (i )*rs_at + (i )*cs_at; \ a10t = a + (i )*rs_at + (0 )*cs_at; \ chi1 = x + (i )*incx; \ x0 = x + (0 )*incx; \ \ /* chi1 = alpha * alpha11 * chi1; */ \ PASTEMAC(ch,copys)( *alpha, alpha_alpha11_conj ); \ if ( bli_is_nonunit_diag( diaga ) ) \ PASTEMAC(ch,scalcjs)( conja, *alpha11, alpha_alpha11_conj ); \ PASTEMAC(ch,scals)( alpha_alpha11_conj, *chi1 ); \ \ /* chi1 = chi1 + alpha * a10t * x0; */ \ kfp_dv \ ( \ conja, \ BLIS_NO_CONJUGATE, \ n_ahead, \ a10t, cs_at, \ x0, incx, \ &rho, \ cntx \ ); \ PASTEMAC(ch,axpys)( *alpha, rho, *chi1 ); \ } \ } \ } INSERT_GENTFUNC_BASIC0( trmv_unb_var1 ) blis-0.9.0/frame/2/trmv/bli_trmv_unb_var2.c000066400000000000000000000106141422157504600204640ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ uplo_t uploa, \ trans_t transa, \ diag_t diaga, \ dim_t m, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* x, inc_t incx, \ cntx_t* cntx \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ ctype* a01; \ ctype* alpha11; \ ctype* a21; \ ctype* x0; \ ctype* chi1; \ ctype* x2; \ ctype alpha_alpha11_conj; \ ctype alpha_chi1; \ dim_t iter, i; \ dim_t n_behind; \ inc_t rs_at, cs_at; \ uplo_t uploa_trans; \ conj_t conja; \ \ if ( bli_does_notrans( transa ) ) \ { \ rs_at = rs_a; \ cs_at = cs_a; \ uploa_trans = uploa; \ } \ else /* if ( bli_does_trans( transa ) ) */ \ { \ rs_at = cs_a; \ cs_at = rs_a; \ uploa_trans = bli_uplo_toggled( uploa ); \ } \ \ conja = bli_extract_conj( transa ); \ \ PASTECH(ch,axpyv_ker_ft) kfp_av; \ \ /* Query the context for the kernel function pointer. */ \ kfp_av = bli_cntx_get_l1v_ker_dt( dt, BLIS_AXPYV_KER, cntx ); \ \ /* We reduce all of the possible cases down to just lower/upper. */ \ if ( bli_is_upper( uploa_trans ) ) \ { \ for ( iter = 0; iter < m; ++iter ) \ { \ i = iter; \ n_behind = i; \ alpha11 = a + (i )*rs_at + (i )*cs_at; \ a01 = a + (0 )*rs_at + (i )*cs_at; \ chi1 = x + (i )*incx; \ x0 = x + (0 )*incx; \ \ /* x0 = x0 + alpha * chi1 * a01; */ \ PASTEMAC(ch,scal2s)( *alpha, *chi1, alpha_chi1 ); \ kfp_av \ ( \ conja, \ n_behind, \ &alpha_chi1, \ a01, rs_at, \ x0, incx, \ cntx \ ); \ \ /* chi1 = alpha * alpha11 * chi1; */ \ PASTEMAC(ch,copys)( *alpha, alpha_alpha11_conj ); \ if ( bli_is_nonunit_diag( diaga ) ) \ PASTEMAC(ch,scalcjs)( conja, *alpha11, alpha_alpha11_conj ); \ PASTEMAC(ch,scals)( alpha_alpha11_conj, *chi1 ); \ } \ } \ else /* if ( bli_is_lower( uploa_trans ) ) */ \ { \ for ( iter = 0; iter < m; ++iter ) \ { \ i = m - iter - 1; \ n_behind = iter; \ alpha11 = a + (i )*rs_at + (i )*cs_at; \ a21 = a + (i+1)*rs_at + (i )*cs_at; \ chi1 = x + (i )*incx; \ x2 = x + (i+1)*incx; \ \ /* x2 = x2 + alpha * chi1 * a21; */ \ PASTEMAC(ch,scal2s)( *alpha, *chi1, alpha_chi1 ); \ kfp_av \ ( \ conja, \ n_behind, \ &alpha_chi1, \ a21, rs_at, \ x2, incx, \ cntx \ ); \ \ /* chi1 = alpha * alpha11 * chi1; */ \ PASTEMAC(ch,copys)( *alpha, alpha_alpha11_conj ); \ if ( bli_is_nonunit_diag( diaga ) ) \ PASTEMAC(ch,scalcjs)( conja, *alpha11, alpha_alpha11_conj ); \ PASTEMAC(ch,scals)( alpha_alpha11_conj, *chi1 ); \ } \ } \ } INSERT_GENTFUNC_BASIC0( trmv_unb_var2 ) blis-0.9.0/frame/2/trmv/bli_trmv_unf_var1.c000066400000000000000000000143571422157504600204770ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ uplo_t uploa, \ trans_t transa, \ diag_t diaga, \ dim_t m, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* x, inc_t incx, \ cntx_t* cntx \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ ctype* one = PASTEMAC(ch,1); \ ctype* A10; \ ctype* A11; \ ctype* A12; \ ctype* a10t; \ ctype* alpha11; \ ctype* a12t; \ ctype* x0; \ ctype* x1; \ ctype* x2; \ ctype* x01; \ ctype* chi11; \ ctype* x21; \ ctype alpha_alpha11_conj; \ ctype rho1; \ dim_t iter, i, k, j, l; \ dim_t b_fuse, f; \ dim_t n_ahead, f_ahead; \ inc_t rs_at, cs_at; \ uplo_t uploa_trans; \ conj_t conja; \ \ if ( bli_does_notrans( transa ) ) \ { \ rs_at = rs_a; \ cs_at = cs_a; \ uploa_trans = uploa; \ } \ else /* if ( bli_does_trans( transa ) ) */ \ { \ rs_at = cs_a; \ cs_at = rs_a; \ uploa_trans = bli_uplo_toggled( uploa ); \ } \ \ conja = bli_extract_conj( transa ); \ \ PASTECH(ch,dotxf_ker_ft) kfp_df; \ \ /* Query the context for the kernel function pointer and fusing factor. */ \ kfp_df = bli_cntx_get_l1f_ker_dt( dt, BLIS_DOTXF_KER, cntx ); \ b_fuse = bli_cntx_get_blksz_def_dt( dt, BLIS_DF, cntx ); \ \ /* We reduce all of the possible cases down to just lower/upper. */ \ if ( bli_is_upper( uploa_trans ) ) \ { \ for ( iter = 0; iter < m; iter += f ) \ { \ f = bli_determine_blocksize_dim_f( iter, m, b_fuse ); \ i = iter; \ n_ahead = m - iter - f; \ A11 = a + (i )*rs_at + (i )*cs_at; \ A12 = a + (i )*rs_at + (i+f)*cs_at; \ x1 = x + (i )*incx; \ x2 = x + (i+f)*incx; \ \ /* x1 = alpha * A11 * x1; */ \ for ( k = 0; k < f; ++k ) \ { \ l = k; \ f_ahead = f - l - 1; \ alpha11 = A11 + (l )*rs_at + (l )*cs_at; \ a12t = A11 + (l )*rs_at + (l+1)*cs_at; \ chi11 = x1 + (l )*incx; \ x21 = x1 + (l+1)*incx; \ \ /* chi11 = alpha * alpha11 * chi11; */ \ PASTEMAC(ch,copys)( *alpha, alpha_alpha11_conj ); \ if ( bli_is_nonunit_diag( diaga ) ) \ PASTEMAC(ch,scalcjs)( conja, *alpha11, alpha_alpha11_conj ); \ PASTEMAC(ch,scals)( alpha_alpha11_conj, *chi11 ); \ \ /* chi11 = chi11 + alpha * a12t * x21; */ \ PASTEMAC(ch,set0s)( rho1 ); \ if ( bli_is_conj( conja ) ) \ { \ for ( j = 0; j < f_ahead; ++j ) \ PASTEMAC(ch,dotjs)( *(a12t + j*cs_at), *(x21 + j*incx), rho1 ); \ } \ else \ { \ for ( j = 0; j < f_ahead; ++j ) \ PASTEMAC(ch,dots)( *(a12t + j*cs_at), *(x21 + j*incx), rho1 ); \ } \ PASTEMAC(ch,axpys)( *alpha, rho1, *chi11 ); \ } \ \ /* x1 = x1 + alpha * A12 * x2; */ \ kfp_df \ ( \ conja, \ BLIS_NO_CONJUGATE, \ n_ahead, \ f, \ alpha, \ A12, cs_at, rs_at, \ x2, incx, \ one, \ x1, incx, \ cntx \ ); \ } \ } \ else /* if ( bli_is_lower( uploa_trans ) ) */ \ { \ for ( iter = 0; iter < m; iter += f ) \ { \ f = bli_determine_blocksize_dim_b( iter, m, b_fuse ); \ i = m - iter - f; \ n_ahead = i; \ A11 = a + (i )*rs_at + (i )*cs_at; \ A10 = a + (i )*rs_at + (0 )*cs_at; \ x1 = x + (i )*incx; \ x0 = x + (0 )*incx; \ \ /* x1 = alpha * A11 * x1; */ \ for ( k = 0; k < f; ++k ) \ { \ l = f - k - 1; \ f_ahead = l; \ alpha11 = A11 + (l )*rs_at + (l )*cs_at; \ a10t = A11 + (l )*rs_at + (0 )*cs_at; \ chi11 = x1 + (l )*incx; \ x01 = x1 + (0 )*incx; \ \ /* chi11 = alpha * alpha11 * chi11; */ \ PASTEMAC(ch,copys)( *alpha, alpha_alpha11_conj ); \ if ( bli_is_nonunit_diag( diaga ) ) \ PASTEMAC(ch,scalcjs)( conja, *alpha11, alpha_alpha11_conj ); \ PASTEMAC(ch,scals)( alpha_alpha11_conj, *chi11 ); \ \ /* chi11 = chi11 + alpha * a10t * x01; */ \ PASTEMAC(ch,set0s)( rho1 ); \ if ( bli_is_conj( conja ) ) \ { \ for ( j = 0; j < f_ahead; ++j ) \ PASTEMAC(ch,dotjs)( *(a10t + j*cs_at), *(x01 + j*incx), rho1 ); \ } \ else \ { \ for ( j = 0; j < f_ahead; ++j ) \ PASTEMAC(ch,dots)( *(a10t + j*cs_at), *(x01 + j*incx), rho1 ); \ } \ PASTEMAC(ch,axpys)( *alpha, rho1, *chi11 ); \ } \ \ /* x1 = x1 + alpha * A10 * x0; */ \ kfp_df \ ( \ conja, \ BLIS_NO_CONJUGATE, \ n_ahead, \ f, \ alpha, \ A10, cs_at, rs_at, \ x0, incx, \ one, \ x1, incx, \ cntx \ ); \ } \ } \ } INSERT_GENTFUNC_BASIC0( trmv_unf_var1 ) blis-0.9.0/frame/2/trmv/bli_trmv_unf_var2.c000066400000000000000000000142161422157504600204720ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ uplo_t uploa, \ trans_t transa, \ diag_t diaga, \ dim_t m, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* x, inc_t incx, \ cntx_t* cntx \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ ctype* A01; \ ctype* A11; \ ctype* A21; \ ctype* a01; \ ctype* alpha11; \ ctype* a21; \ ctype* x0; \ ctype* x1; \ ctype* x2; \ ctype* x01; \ ctype* chi11; \ ctype* x21; \ ctype alpha_alpha11_conj; \ ctype alpha_chi11; \ dim_t iter, i, k, j, l; \ dim_t b_fuse, f; \ dim_t n_behind, f_behind; \ inc_t rs_at, cs_at; \ uplo_t uploa_trans; \ conj_t conja; \ \ if ( bli_does_notrans( transa ) ) \ { \ rs_at = rs_a; \ cs_at = cs_a; \ uploa_trans = uploa; \ } \ else /* if ( bli_does_trans( transa ) ) */ \ { \ rs_at = cs_a; \ cs_at = rs_a; \ uploa_trans = bli_uplo_toggled( uploa ); \ } \ \ conja = bli_extract_conj( transa ); \ \ PASTECH(ch,axpyf_ker_ft) kfp_af; \ \ /* Query the context for the kernel function pointer and fusing factor. */ \ kfp_af = bli_cntx_get_l1f_ker_dt( dt, BLIS_AXPYF_KER, cntx ); \ b_fuse = bli_cntx_get_blksz_def_dt( dt, BLIS_AF, cntx ); \ \ /* We reduce all of the possible cases down to just lower/upper. */ \ if ( bli_is_upper( uploa_trans ) ) \ { \ for ( iter = 0; iter < m; iter += f ) \ { \ f = bli_determine_blocksize_dim_f( iter, m, b_fuse ); \ i = iter; \ n_behind = i; \ A11 = a + (i )*rs_at + (i )*cs_at; \ A01 = a + (0 )*rs_at + (i )*cs_at; \ x1 = x + (i )*incx; \ x0 = x + (0 )*incx; \ \ /* x0 = x0 + alpha * A01 * x1; */ \ kfp_af \ ( \ conja, \ BLIS_NO_CONJUGATE, \ n_behind, \ f, \ alpha, \ A01, rs_at, cs_at, \ x1, incx, \ x0, incx, \ cntx \ ); \ \ /* x1 = alpha * A11 * x1; */ \ for ( k = 0; k < f; ++k ) \ { \ l = k; \ f_behind = l; \ alpha11 = A11 + (l )*rs_at + (l )*cs_at; \ a01 = A11 + (0 )*rs_at + (l )*cs_at; \ chi11 = x1 + (l )*incx; \ x01 = x1 + (0 )*incx; \ \ /* x01 = x01 + alpha * chi11 * a01; */ \ PASTEMAC(ch,scal2s)( *alpha, *chi11, alpha_chi11 ); \ if ( bli_is_conj( conja ) ) \ { \ for ( j = 0; j < f_behind; ++j ) \ PASTEMAC(ch,axpyjs)( alpha_chi11, *(a01 + j*rs_at), *(x01 + j*incx) ); \ } \ else \ { \ for ( j = 0; j < f_behind; ++j ) \ PASTEMAC(ch,axpys)( alpha_chi11, *(a01 + j*rs_at), *(x01 + j*incx) ); \ } \ \ /* chi11 = alpha * alpha11 * chi11; */ \ PASTEMAC(ch,copys)( *alpha, alpha_alpha11_conj ); \ if ( bli_is_nonunit_diag( diaga ) ) \ PASTEMAC(ch,scalcjs)( conja, *alpha11, alpha_alpha11_conj ); \ PASTEMAC(ch,scals)( alpha_alpha11_conj, *chi11 ); \ } \ } \ } \ else /* if ( bli_is_lower( uploa_trans ) ) */ \ { \ for ( iter = 0; iter < m; iter += f ) \ { \ f = bli_determine_blocksize_dim_b( iter, m, b_fuse ); \ i = m - iter - f; \ n_behind = iter; \ A11 = a + (i )*rs_at + (i )*cs_at; \ A21 = a + (i+f)*rs_at + (i )*cs_at; \ x1 = x + (i )*incx; \ x2 = x + (i+f)*incx; \ \ /* x2 = x2 + alpha * A21 * x1; */ \ kfp_af \ ( \ conja, \ BLIS_NO_CONJUGATE, \ n_behind, \ f, \ alpha, \ A21, rs_at, cs_at, \ x1, incx, \ x2, incx, \ cntx \ ); \ \ /* x1 = alpha * A11 * x1; */ \ for ( k = 0; k < f; ++k ) \ { \ l = f - k - 1; \ f_behind = k; \ alpha11 = A11 + (l )*rs_at + (l )*cs_at; \ a21 = A11 + (l+1)*rs_at + (l )*cs_at; \ chi11 = x1 + (l )*incx; \ x21 = x1 + (l+1)*incx; \ \ /* x21 = x21 + alpha * chi11 * a21; */ \ PASTEMAC(ch,scal2s)( *alpha, *chi11, alpha_chi11 ); \ if ( bli_is_conj( conja ) ) \ { \ for ( j = 0; j < f_behind; ++j ) \ PASTEMAC(ch,axpyjs)( alpha_chi11, *(a21 + j*rs_at), *(x21 + j*incx) ); \ } \ else \ { \ for ( j = 0; j < f_behind; ++j ) \ PASTEMAC(ch,axpys)( alpha_chi11, *(a21 + j*rs_at), *(x21 + j*incx) ); \ } \ \ /* chi11 = alpha * alpha11 * chi11; */ \ PASTEMAC(ch,copys)( *alpha, alpha_alpha11_conj ); \ if ( bli_is_nonunit_diag( diaga ) ) \ PASTEMAC(ch,scalcjs)( conja, *alpha11, alpha_alpha11_conj ); \ PASTEMAC(ch,scals)( alpha_alpha11_conj, *chi11 ); \ } \ } \ } \ } INSERT_GENTFUNC_BASIC0( trmv_unf_var2 ) blis-0.9.0/frame/2/trmv/bli_trmv_var.h000066400000000000000000000051641422157504600175470ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype object-based interfaces. // #undef GENPROT #define GENPROT( opname ) \ \ void PASTEMAC0(opname) \ ( \ obj_t* alpha, \ obj_t* a, \ obj_t* x, \ cntx_t* cntx, \ cntl_t* cntl \ ); GENPROT( trmv_l_blk_var1 ) GENPROT( trmv_l_blk_var2 ) GENPROT( trmv_u_blk_var1 ) GENPROT( trmv_u_blk_var2 ) GENPROT( trmv_unb_var1 ) GENPROT( trmv_unb_var2 ) GENPROT( trmv_unf_var1 ) GENPROT( trmv_unf_var2 ) // // Prototype BLAS-like interfaces with typed operands. // #undef GENTPROT #define GENTPROT( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ uplo_t uploa, \ trans_t transa, \ diag_t diaga, \ dim_t m, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* x, inc_t incx, \ cntx_t* cntx \ ); INSERT_GENTPROT_BASIC0( trmv_unb_var1 ) INSERT_GENTPROT_BASIC0( trmv_unb_var2 ) INSERT_GENTPROT_BASIC0( trmv_unf_var1 ) INSERT_GENTPROT_BASIC0( trmv_unf_var2 ) blis-0.9.0/frame/2/trmv/bli_trmv_var_oapi.c000066400000000000000000000056121422157504600205500ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENFRONT #define GENFRONT( opname, varname ) \ \ void PASTEMAC0(varname) \ ( \ obj_t* alpha, \ obj_t* a, \ obj_t* x, \ cntx_t* cntx, \ cntl_t* cntl \ ) \ { \ bli_init_once(); \ \ num_t dt = bli_obj_dt( a ); \ \ uplo_t uploa = bli_obj_uplo( a ); \ trans_t transa = bli_obj_conjtrans_status( a ); \ diag_t diaga = bli_obj_diag( a ); \ \ dim_t m = bli_obj_length( a ); \ \ void* buf_a = bli_obj_buffer_at_off( a ); \ inc_t rs_a = bli_obj_row_stride( a ); \ inc_t cs_a = bli_obj_col_stride( a ); \ \ void* buf_x = bli_obj_buffer_at_off( x ); \ inc_t incx = bli_obj_vector_inc( x ); \ \ void* buf_alpha = bli_obj_buffer_for_1x1( dt, alpha ); \ \ /* Query a type-specific function pointer, except one that uses void* for function arguments instead of typed pointers. */ \ PASTECH2(opname,_unb,_vft) f = \ PASTEMAC(varname,_qfp)( dt ); \ \ f \ ( \ uploa, \ transa, \ diaga, \ m, \ buf_alpha, \ buf_a, rs_a, cs_a, \ buf_x, incx, \ cntx \ ); \ } \ GENFRONT( trmv, trmv_unb_var1 ) GENFRONT( trmv, trmv_unb_var2 ) GENFRONT( trmv, trmv_unf_var1 ) GENFRONT( trmv, trmv_unf_var2 ) blis-0.9.0/frame/2/trmv/other/000077500000000000000000000000001422157504600160235ustar00rootroot00000000000000blis-0.9.0/frame/2/trmv/other/bli_trmv_cntl.c000066400000000000000000000140401422157504600210240ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" extern packm_t* packm_cntl; extern packv_t* packv_cntl; extern unpackv_t* unpackv_cntl; extern gemv_t* gemv_cntl_rp_bs_dot; extern gemv_t* gemv_cntl_rp_bs_axpy; extern gemv_t* gemv_cntl_cp_bs_dot; extern gemv_t* gemv_cntl_cp_bs_axpy; trmv_t* trmv_cntl_bs_ke_nrow_tcol = NULL; trmv_t* trmv_cntl_bs_ke_ncol_trow = NULL; trmv_t* trmv_cntl_ge_nrow_tcol = NULL; trmv_t* trmv_cntl_ge_ncol_trow = NULL; void bli_trmv_cntl_init() { // Create control trees for the lowest-level kernels. These trees induce // operations on (presumably) relatively small block-subvector problems. trmv_cntl_bs_ke_nrow_tcol = bli_trmv_cntl_obj_create( BLIS_UNB_FUSED, BLIS_VARIANT1, 0, NULL, NULL, NULL, NULL, NULL, NULL ); trmv_cntl_bs_ke_ncol_trow = bli_trmv_cntl_obj_create( BLIS_UNB_FUSED, BLIS_VARIANT2, 0, NULL, NULL, NULL, NULL, NULL, NULL ); // Create control trees for generally large problems. Here we choose a // variant that prioritizes keeping a subvector of x in cache. trmv_cntl_ge_nrow_tcol = bli_trmv_cntl_obj_create( BLIS_BLOCKED, BLIS_VARIANT1, // use var1 to maximize x1 usage BLIS_M2, packm_cntl, // pack A11 (if needed) packv_cntl, // pack x1 (if needed) gemv_cntl_rp_bs_dot, // gemv_rp needed by var1 NULL, // gemv_cp not needed by var1 trmv_cntl_bs_ke_nrow_tcol, unpackv_cntl ); // unpack x1 (if packed) trmv_cntl_ge_ncol_trow = bli_trmv_cntl_obj_create( BLIS_BLOCKED, BLIS_VARIANT1, // use var1 to maximize x1 usage BLIS_M2, packm_cntl, // pack A11 (if needed) packv_cntl, // pack x1 (if needed) gemv_cntl_rp_bs_axpy, // gemv_rp needed by var1 NULL, // gemv_cp not needed by var1 trmv_cntl_bs_ke_ncol_trow, unpackv_cntl ); // unpack x1 (if packed) } void bli_trmv_cntl_finalize() { bli_cntl_free_node( trmv_cntl_bs_ke_nrow_tcol ); bli_cntl_free_node( trmv_cntl_bs_ke_ncol_trow ); bli_cntl_free_node( trmv_cntl_ge_nrow_tcol ); bli_cntl_free_node( trmv_cntl_ge_ncol_trow ); } trmv_t* bli_trmv_cntl_obj_create( impl_t impl_type, varnum_t var_num, bszid_t bszid, packm_t* sub_packm_a11, packv_t* sub_packv_x1, gemv_t* sub_gemv_rp, gemv_t* sub_gemv_cp, trmv_t* sub_trmv, unpackv_t* sub_unpackv_x1 ) { trmv_t* cntl; cntl = ( trmv_t* ) bli_malloc_intl( sizeof(trmv_t) ); cntl->impl_type = impl_type; cntl->var_num = var_num; cntl->bszid = bszid; cntl->sub_packm_a11 = sub_packm_a11; cntl->sub_packv_x1 = sub_packv_x1; cntl->sub_gemv_rp = sub_gemv_rp; cntl->sub_gemv_cp = sub_gemv_cp; cntl->sub_trmv = sub_trmv; cntl->sub_unpackv_x1 = sub_unpackv_x1; return cntl; } void bli_trmv_cntl_obj_init( trmv_t* cntl, impl_t impl_type, varnum_t var_num, bszid_t bszid, packm_t* sub_packm_a11, packv_t* sub_packv_x1, gemv_t* sub_gemv_rp, gemv_t* sub_gemv_cp, trmv_t* sub_trmv, unpackv_t* sub_unpackv_x1 ) { cntl->impl_type = impl_type; cntl->var_num = var_num; cntl->bszid = bszid; cntl->sub_packm_a11 = sub_packm_a11; cntl->sub_packv_x1 = sub_packv_x1; cntl->sub_gemv_rp = sub_gemv_rp; cntl->sub_gemv_cp = sub_gemv_cp; cntl->sub_trmv = sub_trmv; cntl->sub_unpackv_x1 = sub_unpackv_x1; } blis-0.9.0/frame/2/trmv/other/bli_trmv_cntl.h000066400000000000000000000061501422157504600210340ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ struct trmv_s { impl_t impl_type; varnum_t var_num; bszid_t bszid; struct packm_s* sub_packm_a11; struct packv_s* sub_packv_x1; struct gemv_s* sub_gemv_rp; struct gemv_s* sub_gemv_cp; struct trmv_s* sub_trmv; struct unpackv_s* sub_unpackv_x1; }; typedef struct trmv_s trmv_t; #define bli_cntl_sub_trmv( cntl ) cntl->sub_trmv void bli_trmv_cntl_init( void ); void bli_trmv_cntl_finalize( void ); trmv_t* bli_trmv_cntl_obj_create( impl_t impl_type, varnum_t var_num, bszid_t bszid, packm_t* sub_packm_a11, packv_t* sub_packv_x1, gemv_t* sub_gemv_rp, gemv_t* sub_gemv_cp, trmv_t* sub_trmv, unpackv_t* sub_unpackv_x1 ); void bli_trmv_cntl_obj_init( trmv_t* cntl, impl_t impl_type, varnum_t var_num, bszid_t bszid, packm_t* sub_packm_a11, packv_t* sub_packv_x1, gemv_t* sub_gemv_rp, gemv_t* sub_gemv_cp, trmv_t* sub_trmv, unpackv_t* sub_unpackv_x1 ); blis-0.9.0/frame/2/trmv/other/bli_trmv_front.c000066400000000000000000000135221422157504600212200ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" extern trmv_t* trmv_cntl_bs_ke_nrow_tcol; extern trmv_t* trmv_cntl_bs_ke_ncol_trow; extern trmv_t* trmv_cntl_ge_nrow_tcol; extern trmv_t* trmv_cntl_ge_ncol_trow; void bli_trmv_front ( obj_t* alpha, obj_t* a, obj_t* x, cntx_t* cntx ) { trmv_t* trmv_cntl; num_t dt_targ_a; num_t dt_targ_x; bool a_has_unit_inc; bool x_has_unit_inc; obj_t alpha_local; num_t dt_alpha; // Check parameters. if ( bli_error_checking_is_enabled() ) bli_trmv_check( alpha, a, x ); // Query the target datatypes of each object. dt_targ_a = bli_obj_target_dt( a ); dt_targ_x = bli_obj_target_dt( x ); // Determine whether each operand with unit stride. a_has_unit_inc = ( bli_obj_is_row_stored( a ) || bli_obj_is_col_stored( a ) ); x_has_unit_inc = ( bli_obj_vector_inc( x ) == 1 ); // Create an object to hold a copy-cast of alpha. Notice that we use // the type union of the target datatypes of a and x to prevent any // unnecessary loss of information during the computation. dt_alpha = bli_dt_union( dt_targ_a, dt_targ_x ); bli_obj_scalar_init_detached_copy_of( dt_alpha, BLIS_NO_CONJUGATE, alpha, &alpha_local ); // If all operands have unit stride, we choose a control tree for calling // the unblocked implementation directly without any blocking. if ( a_has_unit_inc && x_has_unit_inc ) { // We use two control trees to handle the four cases corresponding to // combinations of transposition and row/column-storage. // The row-stored without transpose and column-stored with transpose // trees are identical. Same for the remaining two trees. if ( bli_obj_has_notrans( a ) ) { if ( bli_obj_is_row_stored( a ) ) trmv_cntl = trmv_cntl_bs_ke_nrow_tcol; else trmv_cntl = trmv_cntl_bs_ke_ncol_trow; } else // if ( bli_obj_has_trans( a ) ) { if ( bli_obj_is_row_stored( a ) ) trmv_cntl = trmv_cntl_bs_ke_ncol_trow; else trmv_cntl = trmv_cntl_bs_ke_nrow_tcol; } } else { // Mark objects with unit stride as already being packed. This prevents // unnecessary packing from happening within the blocked algorithm. if ( a_has_unit_inc ) bli_obj_set_pack_schema( BLIS_PACKED_UNSPEC, a ); if ( x_has_unit_inc ) bli_obj_set_pack_schema( BLIS_PACKED_VECTOR, x ); // Here, we make a similar choice as above, except that (1) we look // at storage tilt, and (2) we choose a tree that performs blocking. if ( bli_obj_has_notrans( a ) ) { if ( bli_obj_is_row_tilted( a ) ) trmv_cntl = trmv_cntl_ge_nrow_tcol; else trmv_cntl = trmv_cntl_ge_ncol_trow; } else // if ( bli_obj_has_trans( a ) ) { if ( bli_obj_is_row_tilted( a ) ) trmv_cntl = trmv_cntl_ge_ncol_trow; else trmv_cntl = trmv_cntl_ge_nrow_tcol; } } // Invoke the internal back-end with the copy-cast of alpha and the // chosen control tree. bli_trmv_int( &alpha_local, a, x, cntx, trmv_cntl ); } // // Define BLAS-like interfaces with homogeneous-typed operands. // #undef GENTFUNC #define GENTFUNC( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ uplo_t uploa, \ trans_t transa, \ diag_t diaga, \ dim_t m, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* x, inc_t incx, \ cntx_t* cntx \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ obj_t alphao, ao, xo; \ \ inc_t rs_x, cs_x; \ \ rs_x = incx; cs_x = m * incx; \ \ bli_obj_create_1x1_with_attached_buffer( dt, alpha, &alphao ); \ \ bli_obj_create_with_attached_buffer( dt, m, m, a, rs_a, cs_a, &ao ); \ bli_obj_create_with_attached_buffer( dt, m, 1, x, rs_x, cs_x, &xo ); \ \ bli_obj_set_uplo( uploa, &ao ); \ bli_obj_set_conjtrans( transa, &ao ); \ bli_obj_set_diag( diaga, &ao ); \ \ bli_obj_set_struc( BLIS_TRIANGULAR, &ao ); \ \ PASTEMAC0(opname)( &alphao, \ &ao, \ &xo, \ cntx ); \ } INSERT_GENTFUNC_BASIC0( trmv_front ) blis-0.9.0/frame/2/trmv/other/bli_trmv_front.h000066400000000000000000000041501422157504600212220ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void bli_trmv_front ( obj_t* alpha, obj_t* a, obj_t* x, cntx_t* cntx ); #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ uplo_t uploa, \ trans_t transa, \ diag_t diaga, \ dim_t m, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* x, inc_t incx, \ cntx_t* cntx \ ); INSERT_GENTPROT_BASIC( trmv_front ) blis-0.9.0/frame/2/trmv/other/bli_trmv_int.c000066400000000000000000000120171422157504600206600ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define FUNCPTR_T trmv_fp typedef void (*FUNCPTR_T)( obj_t* alpha, obj_t* a, obj_t* x, cntx_t* cntx, trmv_t* cntl ); static FUNCPTR_T vars[2][3][3] = { // lower triangular { // unblocked unblocked with fusing blocked { bli_trmv_unb_var1, bli_trmv_unf_var1, bli_trmv_l_blk_var1 }, { bli_trmv_unb_var2, bli_trmv_unf_var2, bli_trmv_l_blk_var2 }, { NULL, NULL, NULL }, }, // upper triangular { // unblocked unblocked with fusing blocked { bli_trmv_unb_var1, bli_trmv_unf_var1, bli_trmv_u_blk_var1 }, { bli_trmv_unb_var2, bli_trmv_unf_var2, bli_trmv_u_blk_var2 }, { NULL, NULL, NULL }, } }; void bli_trmv_int( obj_t* alpha, obj_t* a, obj_t* x, cntx_t* cntx, trmv_t* cntl ) { varnum_t n; impl_t i; bool uplo; FUNCPTR_T f; obj_t a_local; // Check parameters. if ( bli_error_checking_is_enabled() ) bli_trmv_check( alpha, a, x ); // If A or x has a zero dimension, return early. if ( bli_obj_has_zero_dim( a ) ) return; if ( bli_obj_has_zero_dim( x ) ) return; // Alias A in case we need to induce a transformation (ie: transposition). bli_obj_alias_to( a, &a_local ); // NOTE: to support cases where B is complex and A is real, we will // need to have the default side case be BLIS_RIGHT and then express // the left case in terms of it, rather than the other way around. // Determine uplo (for indexing to the correct function pointer). if ( bli_obj_is_lower( &a_local ) ) uplo = 0; else uplo = 1; // We do not explicitly implement the cases where A is transposed. // However, we can still handle them. Specifically, if A is marked as // needing a transposition, we simply toggle the uplo value to cause the // correct algorithm to be induced. When that algorithm partitions into // A, it will grab the correct subpartitions, which will inherit A's // transposition bit and thus downstream subproblems will do the right // thing. Alternatively, we could accomplish the same end goal by // inducing a transposition, via bli_obj_induce_trans(), in the code // block below. That macro function swaps dimensions, strides, and // offsets. As an example, given a lower triangular, column-major matrix // that needs a transpose, we would induce that transposition by recasting // the object as an upper triangular, row-major matrix (with no transpose // needed). Note that how we choose to handle transposition here does NOT // affect the optimal choice of kernel (ie: a column-major column panel // matrix with transpose times a vector would use the same kernel as a // row-major row panel matrix with no transpose times a vector). if ( bli_obj_has_trans( &a_local ) ) { //bli_obj_induce_trans( &a_local ); //bli_obj_set_onlytrans( BLIS_NO_TRANSPOSE, &a_local ); if ( uplo == 1 ) uplo = 0; else uplo = 1; } // Extract the variant number and implementation type. n = bli_cntl_var_num( cntl ); i = bli_cntl_impl_type( cntl ); // Index into the variant array to extract the correct function pointer. f = vars[uplo][n][i]; // Invoke the variant. f( alpha, &a_local, x, cntx, cntl ); } blis-0.9.0/frame/2/trmv/other/bli_trmv_int.h000066400000000000000000000034541422157504600206720ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void bli_trmv_int( obj_t* alpha, obj_t* a, obj_t* x, cntx_t* cntx, trmv_t* cntl ); blis-0.9.0/frame/2/trmv/other/bli_trmv_l_blk_var1.c000066400000000000000000000100751422157504600221040ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_trmv_l_blk_var1( obj_t* alpha, obj_t* a, obj_t* x, cntx_t* cntx, trmv_t* cntl ) { obj_t a11, a11_pack; obj_t a10; obj_t x1, x1_pack; obj_t x0; dim_t mn; dim_t ij; dim_t b_alg; // Initialize objects for packing. bli_obj_init_pack( &a11_pack ); bli_obj_init_pack( &x1_pack ); // Query dimension. mn = bli_obj_length( a ); // Partition diagonally. for ( ij = 0; ij < mn; ij += b_alg ) { // Determine the current algorithmic blocksize. b_alg = bli_determine_blocksize_b( ij, mn, a, bli_cntl_bszid( cntl ), cntx ); // Acquire partitions for A11, A10, x1, and x0. bli_acquire_mpart_br2tl( BLIS_SUBPART11, ij, b_alg, a, &a11 ); bli_acquire_mpart_br2tl( BLIS_SUBPART10, ij, b_alg, a, &a10 ); bli_acquire_vpart_b2f( BLIS_SUBPART1, ij, b_alg, x, &x1 ); bli_acquire_vpart_b2f( BLIS_SUBPART0, ij, b_alg, x, &x0 ); // Initialize objects for packing A11 and x1 (if needed). bli_packm_init( &a11, &a11_pack, cntx, bli_cntl_sub_packm_a11( cntl ) ); bli_packv_init( &x1, &x1_pack, cntx, bli_cntl_sub_packv_x1( cntl ) ); // Copy/pack A11, x1 (if needed). bli_packm_int( &a11, &a11_pack, cntx, bli_cntl_sub_packm_a11( cntl ), &BLIS_PACKM_SINGLE_THREADED ); bli_packv_int( &x1, &x1_pack, cntx, bli_cntl_sub_packv_x1( cntl ) ); // x1 = alpha * tril( A11 ) * x1; bli_trmv_int( alpha, &a11_pack, &x1_pack, cntx, bli_cntl_sub_trmv( cntl ) ); // x1 = x1 + alpha * A10 * x0; bli_gemv_int( BLIS_NO_TRANSPOSE, BLIS_NO_CONJUGATE, alpha, &a10, &x0, &BLIS_ONE, &x1_pack, cntx, bli_cntl_sub_gemv_rp( cntl ) ); // Copy/unpack x1 (if x1 was packed). bli_unpackv_int( &x1_pack, &x1, cntx, bli_cntl_sub_unpackv_x1( cntl ) ); } // If any packing buffers were acquired within packm, release them back // to the memory manager. bli_packm_release( &a11_pack, bli_cntl_sub_packm_a11( cntl ) ); bli_packv_release( &x1_pack, bli_cntl_sub_packv_x1( cntl ) ); } blis-0.9.0/frame/2/trmv/other/bli_trmv_l_blk_var2.c000066400000000000000000000100751422157504600221050ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_trmv_l_blk_var2( obj_t* alpha, obj_t* a, obj_t* x, cntx_t* cntx, trmv_t* cntl ) { obj_t a11, a11_pack; obj_t a21; obj_t x1, x1_pack; obj_t x2; dim_t mn; dim_t ij; dim_t b_alg; // Initialize objects for packing. bli_obj_init_pack( &a11_pack ); bli_obj_init_pack( &x1_pack ); // Query dimension. mn = bli_obj_length( a ); // Partition diagonally. for ( ij = 0; ij < mn; ij += b_alg ) { // Determine the current algorithmic blocksize. b_alg = bli_determine_blocksize_b( ij, mn, a, bli_cntl_bszid( cntl ), cntx ); // Acquire partitions for A11, A21, x1, and x2. bli_acquire_mpart_br2tl( BLIS_SUBPART11, ij, b_alg, a, &a11 ); bli_acquire_mpart_br2tl( BLIS_SUBPART21, ij, b_alg, a, &a21 ); bli_acquire_vpart_b2f( BLIS_SUBPART1, ij, b_alg, x, &x1 ); bli_acquire_vpart_b2f( BLIS_SUBPART2, ij, b_alg, x, &x2 ); // Initialize objects for packing A11 and x1 (if needed). bli_packm_init( &a11, &a11_pack, cntx, bli_cntl_sub_packm_a11( cntl ) ); bli_packv_init( &x1, &x1_pack, cntx, bli_cntl_sub_packv_x1( cntl ) ); // Copy/pack A11, x1 (if needed). bli_packm_int( &a11, &a11_pack, cntx, bli_cntl_sub_packm_a11( cntl ), &BLIS_PACKM_SINGLE_THREADED ); bli_packv_int( &x1, &x1_pack, cntx, bli_cntl_sub_packv_x1( cntl ) ); // x2 = x2 + alpha * A21 * x1; bli_gemv_int( BLIS_NO_TRANSPOSE, BLIS_NO_CONJUGATE, alpha, &a21, &x1_pack, &BLIS_ONE, &x2, cntx, bli_cntl_sub_gemv_cp( cntl ) ); // x1 = alpha * tril( A11 ) * x1; bli_trmv_int( alpha, &a11_pack, &x1_pack, cntx, bli_cntl_sub_trmv( cntl ) ); // Copy/unpack x1 (if x1 was packed). bli_unpackv_int( &x1_pack, &x1, cntx, bli_cntl_sub_unpackv_x1( cntl ) ); } // If any packing buffers were acquired within packm, release them back // to the memory manager. bli_packm_release( &a11_pack, bli_cntl_sub_packm_a11( cntl ) ); bli_packv_release( &x1_pack, bli_cntl_sub_packv_x1( cntl ) ); } blis-0.9.0/frame/2/trmv/other/bli_trmv_u_blk_var1.c000066400000000000000000000100751422157504600221150ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_trmv_u_blk_var1( obj_t* alpha, obj_t* a, obj_t* x, cntx_t* cntx, trmv_t* cntl ) { obj_t a11, a11_pack; obj_t a12; obj_t x1, x1_pack; obj_t x2; dim_t mn; dim_t ij; dim_t b_alg; // Initialize objects for packing. bli_obj_init_pack( &a11_pack ); bli_obj_init_pack( &x1_pack ); // Query dimension. mn = bli_obj_length( a ); // Partition diagonally. for ( ij = 0; ij < mn; ij += b_alg ) { // Determine the current algorithmic blocksize. b_alg = bli_determine_blocksize_f( ij, mn, a, bli_cntl_bszid( cntl ), cntx ); // Acquire partitions for A11, A12, x1, and x2. bli_acquire_mpart_tl2br( BLIS_SUBPART11, ij, b_alg, a, &a11 ); bli_acquire_mpart_tl2br( BLIS_SUBPART12, ij, b_alg, a, &a12 ); bli_acquire_vpart_f2b( BLIS_SUBPART1, ij, b_alg, x, &x1 ); bli_acquire_vpart_f2b( BLIS_SUBPART2, ij, b_alg, x, &x2 ); // Initialize objects for packing A11 and x1 (if needed). bli_packm_init( &a11, &a11_pack, cntx, bli_cntl_sub_packm_a11( cntl ) ); bli_packv_init( &x1, &x1_pack, cntx, bli_cntl_sub_packv_x1( cntl ) ); // Copy/pack A11, x1 (if needed). bli_packm_int( &a11, &a11_pack, cntx, bli_cntl_sub_packm_a11( cntl ), &BLIS_PACKM_SINGLE_THREADED ); bli_packv_int( &x1, &x1_pack, cntx, bli_cntl_sub_packv_x1( cntl ) ); // x1 = alpha * triu( A11 ) * x1; bli_trmv_int( alpha, &a11_pack, &x1_pack, cntx, bli_cntl_sub_trmv( cntl ) ); // x1 = x1 + alpha * A12 * x2; bli_gemv_int( BLIS_NO_TRANSPOSE, BLIS_NO_CONJUGATE, alpha, &a12, &x2, &BLIS_ONE, &x1_pack, cntx, bli_cntl_sub_gemv_rp( cntl ) ); // Copy/unpack x1 (if x1 was packed). bli_unpackv_int( &x1_pack, &x1, cntx, bli_cntl_sub_unpackv_x1( cntl ) ); } // If any packing buffers were acquired within packm, release them back // to the memory manager. bli_packm_release( &a11_pack, bli_cntl_sub_packm_a11( cntl ) ); bli_packv_release( &x1_pack, bli_cntl_sub_packv_x1( cntl ) ); } blis-0.9.0/frame/2/trmv/other/bli_trmv_u_blk_var2.c000066400000000000000000000100751422157504600221160ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_trmv_u_blk_var2( obj_t* alpha, obj_t* a, obj_t* x, cntx_t* cntx, trmv_t* cntl ) { obj_t a11, a11_pack; obj_t a01; obj_t x1, x1_pack; obj_t x0; dim_t mn; dim_t ij; dim_t b_alg; // Initialize objects for packing. bli_obj_init_pack( &a11_pack ); bli_obj_init_pack( &x1_pack ); // Query dimension. mn = bli_obj_length( a ); // Partition diagonally. for ( ij = 0; ij < mn; ij += b_alg ) { // Determine the current algorithmic blocksize. b_alg = bli_determine_blocksize_b( ij, mn, a, bli_cntl_bszid( cntl ), cntx ); // Acquire partitions for A11, A21, x1, and x2. bli_acquire_mpart_br2tl( BLIS_SUBPART11, ij, b_alg, a, &a11 ); bli_acquire_mpart_br2tl( BLIS_SUBPART01, ij, b_alg, a, &a01 ); bli_acquire_vpart_b2f( BLIS_SUBPART1, ij, b_alg, x, &x1 ); bli_acquire_vpart_b2f( BLIS_SUBPART0, ij, b_alg, x, &x0 ); // Initialize objects for packing A11 and x1 (if needed). bli_packm_init( &a11, &a11_pack, cntx, bli_cntl_sub_packm_a11( cntl ) ); bli_packv_init( &x1, &x1_pack, cntx, bli_cntl_sub_packv_x1( cntl ) ); // Copy/pack A11, x1 (if needed). bli_packm_int( &a11, &a11_pack, cntx, bli_cntl_sub_packm_a11( cntl ), &BLIS_PACKM_SINGLE_THREADED ); bli_packv_int( &x1, &x1_pack, cntx, bli_cntl_sub_packv_x1( cntl ) ); // x0 = x0 + alpha * A01 * x1; bli_gemv_int( BLIS_NO_TRANSPOSE, BLIS_NO_CONJUGATE, alpha, &a01, &x1_pack, &BLIS_ONE, &x0, cntx, bli_cntl_sub_gemv_cp( cntl ) ); // x1 = alpha * triu( A11 ) * x1; bli_trmv_int( alpha, &a11_pack, &x1_pack, cntx, bli_cntl_sub_trmv( cntl ) ); // Copy/unpack x1 (if x1 was packed). bli_unpackv_int( &x1_pack, &x1, cntx, bli_cntl_sub_unpackv_x1( cntl ) ); } // If any packing buffers were acquired within packm, release them back // to the memory manager. bli_packm_release( &a11_pack, bli_cntl_sub_packm_a11( cntl ) ); bli_packv_release( &x1_pack, bli_cntl_sub_packv_x1( cntl ) ); } blis-0.9.0/frame/2/trsv/000077500000000000000000000000001422157504600147105ustar00rootroot00000000000000blis-0.9.0/frame/2/trsv/bli_trsv.h000066400000000000000000000034701422157504600167110ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // NOTE: level-2 control tree code is temporarily disabled. //#include "bli_trsv_cntl.h" //#include "bli_trsv_front.h" //#include "bli_trsv_int.h" #include "bli_trsv_var.h" blis-0.9.0/frame/2/trsv/bli_trsv_unb_var1.c000066400000000000000000000106501422157504600204770ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ uplo_t uploa, \ trans_t transa, \ diag_t diaga, \ dim_t m, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* x, inc_t incx, \ cntx_t* cntx \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ ctype* a10t; \ ctype* alpha11; \ ctype* a12t; \ ctype* x0; \ ctype* chi1; \ ctype* x2; \ ctype alpha11_conj; \ ctype rho; \ dim_t iter, i; \ dim_t n_behind; \ inc_t rs_at, cs_at; \ uplo_t uploa_trans; \ conj_t conja; \ \ if ( bli_does_notrans( transa ) ) \ { \ rs_at = rs_a; \ cs_at = cs_a; \ uploa_trans = uploa; \ } \ else /* if ( bli_does_trans( transa ) ) */ \ { \ rs_at = cs_a; \ cs_at = rs_a; \ uploa_trans = bli_uplo_toggled( uploa ); \ } \ \ conja = bli_extract_conj( transa ); \ \ /* x = alpha * x; */ \ PASTEMAC2(ch,scalv,BLIS_TAPI_EX_SUF) \ ( \ BLIS_NO_CONJUGATE, \ m, \ alpha, \ x, incx, \ cntx, \ NULL \ ); \ \ PASTECH(ch,dotv_ker_ft) kfp_tv; \ \ /* Query the context for the kernel function pointer. */ \ kfp_tv = bli_cntx_get_l1v_ker_dt( dt, BLIS_DOTV_KER, cntx ); \ \ /* We reduce all of the possible cases down to just lower/upper. */ \ if ( bli_is_upper( uploa_trans ) ) \ { \ for ( iter = 0; iter < m; ++iter ) \ { \ i = m - iter - 1; \ n_behind = iter; \ alpha11 = a + (i )*rs_at + (i )*cs_at; \ a12t = a + (i )*rs_at + (i+1)*cs_at; \ chi1 = x + (i )*incx; \ x2 = x + (i+1)*incx; \ \ /* chi1 = chi1 - a12t * x2; */ \ kfp_tv \ ( \ conja, \ BLIS_NO_CONJUGATE, \ n_behind, \ a12t, cs_at, \ x2, incx, \ &rho, \ cntx \ ); \ PASTEMAC(ch,subs)( rho, *chi1 ); \ \ /* chi1 = chi1 / alpha11; */ \ if ( bli_is_nonunit_diag( diaga ) ) \ { \ PASTEMAC(ch,copycjs)( conja, *alpha11, alpha11_conj ); \ PASTEMAC(ch,invscals)( alpha11_conj, *chi1 ); \ } \ } \ } \ else /* if ( bli_is_lower( uploa_trans ) ) */ \ { \ for ( iter = 0; iter < m; ++iter ) \ { \ i = iter; \ n_behind = i; \ alpha11 = a + (i )*rs_at + (i )*cs_at; \ a10t = a + (i )*rs_at + (0 )*cs_at; \ chi1 = x + (i )*incx; \ x0 = x + (0 )*incx; \ \ /* chi1 = chi1 - a10t * x0; */ \ kfp_tv \ ( \ conja, \ BLIS_NO_CONJUGATE, \ n_behind, \ a10t, cs_at, \ x0, incx, \ &rho, \ cntx \ ); \ PASTEMAC(ch,subs)( rho, *chi1 ); \ \ /* chi1 = chi1 / alpha11; */ \ if ( bli_is_nonunit_diag( diaga ) ) \ { \ PASTEMAC(ch,copycjs)( conja, *alpha11, alpha11_conj ); \ PASTEMAC(ch,invscals)( alpha11_conj, *chi1 ); \ } \ } \ } \ } INSERT_GENTFUNC_BASIC0( trsv_unb_var1 ) blis-0.9.0/frame/2/trsv/bli_trsv_unb_var2.c000066400000000000000000000106241422157504600205010ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ uplo_t uploa, \ trans_t transa, \ diag_t diaga, \ dim_t m, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* x, inc_t incx, \ cntx_t* cntx \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ ctype* a01; \ ctype* alpha11; \ ctype* a21; \ ctype* x0; \ ctype* chi1; \ ctype* x2; \ ctype alpha11_conj; \ ctype minus_chi1; \ dim_t iter, i; \ dim_t n_ahead; \ inc_t rs_at, cs_at; \ uplo_t uploa_trans; \ conj_t conja; \ \ if ( bli_does_notrans( transa ) ) \ { \ rs_at = rs_a; \ cs_at = cs_a; \ uploa_trans = uploa; \ } \ else /* if ( bli_does_trans( transa ) ) */ \ { \ rs_at = cs_a; \ cs_at = rs_a; \ uploa_trans = bli_uplo_toggled( uploa ); \ } \ \ conja = bli_extract_conj( transa ); \ \ /* x = alpha * x; */ \ PASTEMAC2(ch,scalv,BLIS_TAPI_EX_SUF) \ ( \ BLIS_NO_CONJUGATE, \ m, \ alpha, \ x, incx, \ cntx, \ NULL \ ); \ \ PASTECH(ch,axpyv_ker_ft) kfp_av; \ \ /* Query the context for the kernel function pointer. */ \ kfp_av = bli_cntx_get_l1v_ker_dt( dt, BLIS_AXPYV_KER, cntx ); \ \ /* We reduce all of the possible cases down to just lower/upper. */ \ if ( bli_is_upper( uploa_trans ) ) \ { \ for ( iter = 0; iter < m; ++iter ) \ { \ i = m - iter - 1; \ n_ahead = i; \ alpha11 = a + (i )*rs_at + (i )*cs_at; \ a01 = a + (0 )*rs_at + (i )*cs_at; \ chi1 = x + (i )*incx; \ x0 = x + (0 )*incx; \ \ /* chi1 = chi1 / alpha11; */ \ if ( bli_is_nonunit_diag( diaga ) ) \ { \ PASTEMAC(ch,copycjs)( conja, *alpha11, alpha11_conj ); \ PASTEMAC(ch,invscals)( alpha11_conj, *chi1 ); \ } \ \ /* x0 = x0 - chi1 * a01; */ \ PASTEMAC(ch,neg2s)( *chi1, minus_chi1 ); \ kfp_av \ ( \ conja, \ n_ahead, \ &minus_chi1, \ a01, rs_at, \ x0, incx, \ cntx \ ); \ } \ } \ else /* if ( bli_is_lower( uploa_trans ) ) */ \ { \ for ( iter = 0; iter < m; ++iter ) \ { \ i = iter; \ n_ahead = m - iter - 1; \ alpha11 = a + (i )*rs_at + (i )*cs_at; \ a21 = a + (i+1)*rs_at + (i )*cs_at; \ chi1 = x + (i )*incx; \ x2 = x + (i+1)*incx; \ \ /* chi1 = chi1 / alpha11; */ \ if ( bli_is_nonunit_diag( diaga ) ) \ { \ PASTEMAC(ch,copycjs)( conja, *alpha11, alpha11_conj ); \ PASTEMAC(ch,invscals)( alpha11_conj, *chi1 ); \ } \ \ /* x2 = x2 - chi1 * a21; */ \ PASTEMAC(ch,neg2s)( *chi1, minus_chi1 ); \ kfp_av \ ( \ conja, \ n_ahead, \ &minus_chi1, \ a21, rs_at, \ x2, incx, \ cntx \ ); \ } \ } \ } INSERT_GENTFUNC_BASIC0( trsv_unb_var2 ) blis-0.9.0/frame/2/trsv/bli_trsv_unf_var1.c000066400000000000000000000144151422157504600205060ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ uplo_t uploa, \ trans_t transa, \ diag_t diaga, \ dim_t m, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* x, inc_t incx, \ cntx_t* cntx \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ ctype* one = PASTEMAC(ch,1); \ ctype* minus_one = PASTEMAC(ch,m1); \ ctype* A10; \ ctype* A11; \ ctype* A12; \ ctype* a10t; \ ctype* alpha11; \ ctype* a12t; \ ctype* x0; \ ctype* x1; \ ctype* x2; \ ctype* x01; \ ctype* chi11; \ ctype* x21; \ ctype alpha11_conj; \ ctype rho1; \ dim_t iter, i, k, j, l; \ dim_t b_fuse, f; \ dim_t n_behind, f_behind; \ inc_t rs_at, cs_at; \ uplo_t uploa_trans; \ conj_t conja; \ \ /* x = alpha * x; */ \ PASTEMAC2(ch,scalv,BLIS_TAPI_EX_SUF) \ ( \ BLIS_NO_CONJUGATE, \ m, \ alpha, \ x, incx, \ cntx, \ NULL \ ); \ \ if ( bli_does_notrans( transa ) ) \ { \ rs_at = rs_a; \ cs_at = cs_a; \ uploa_trans = uploa; \ } \ else /* if ( bli_does_trans( transa ) ) */ \ { \ rs_at = cs_a; \ cs_at = rs_a; \ uploa_trans = bli_uplo_toggled( uploa ); \ } \ \ conja = bli_extract_conj( transa ); \ \ PASTECH(ch,dotxf_ker_ft) kfp_df; \ \ /* Query the context for the kernel function pointer and fusing factor. */ \ kfp_df = bli_cntx_get_l1f_ker_dt( dt, BLIS_DOTXF_KER, cntx ); \ b_fuse = bli_cntx_get_blksz_def_dt( dt, BLIS_DF, cntx ); \ \ /* We reduce all of the possible cases down to just lower/upper. */ \ if ( bli_is_upper( uploa_trans ) ) \ { \ for ( iter = 0; iter < m; iter += f ) \ { \ f = bli_determine_blocksize_dim_b( iter, m, b_fuse ); \ i = m - iter - f; \ n_behind = iter; \ A11 = a + (i )*rs_at + (i )*cs_at; \ A12 = a + (i )*rs_at + (i+f)*cs_at; \ x1 = x + (i )*incx; \ x2 = x + (i+f)*incx; \ \ /* x1 = x1 - A12 * x2; */ \ kfp_df \ ( \ conja, \ BLIS_NO_CONJUGATE, \ n_behind, \ f, \ minus_one, \ A12, cs_at, rs_at, \ x2, incx, \ one, \ x1, incx, \ cntx \ ); \ \ /* x1 = x1 / triu( A11 ); */ \ for ( k = 0; k < f; ++k ) \ { \ l = f - k - 1; \ f_behind = k; \ alpha11 = A11 + (l )*rs_at + (l )*cs_at; \ a12t = A11 + (l )*rs_at + (l+1)*cs_at; \ chi11 = x1 + (l )*incx; \ x21 = x1 + (l+1)*incx; \ \ /* chi11 = chi11 - a12t * x21; */ \ PASTEMAC(ch,set0s)( rho1 ); \ if ( bli_is_conj( conja ) ) \ { \ for ( j = 0; j < f_behind; ++j ) \ PASTEMAC(ch,dotjs)( *(a12t + j*cs_at), *(x21 + j*incx), rho1 ); \ } \ else \ { \ for ( j = 0; j < f_behind; ++j ) \ PASTEMAC(ch,dots)( *(a12t + j*cs_at), *(x21 + j*incx), rho1 ); \ } \ PASTEMAC(ch,subs)( rho1, *chi11 ); \ \ /* chi11 = chi11 / alpha11; */ \ if ( bli_is_nonunit_diag( diaga ) ) \ { \ PASTEMAC(ch,copycjs)( conja, *alpha11, alpha11_conj ); \ PASTEMAC(ch,invscals)( alpha11_conj, *chi11 ); \ } \ } \ } \ } \ else /* if ( bli_is_lower( uploa_trans ) ) */ \ { \ for ( iter = 0; iter < m; iter += f ) \ { \ f = bli_determine_blocksize_dim_f( iter, m, b_fuse ); \ i = iter; \ n_behind = i; \ A11 = a + (i )*rs_at + (i )*cs_at; \ A10 = a + (i )*rs_at + (0 )*cs_at; \ x1 = x + (i )*incx; \ x0 = x + (0 )*incx; \ \ /* x1 = x1 - A10 * x0; */ \ kfp_df \ ( \ conja, \ BLIS_NO_CONJUGATE, \ n_behind, \ f, \ minus_one, \ A10, cs_at, rs_at, \ x0, incx, \ one, \ x1, incx, \ cntx \ ); \ \ /* x1 = x1 / tril( A11 ); */ \ for ( k = 0; k < f; ++k ) \ { \ l = k; \ f_behind = l; \ alpha11 = A11 + (l )*rs_at + (l )*cs_at; \ a10t = A11 + (l )*rs_at + (0 )*cs_at; \ chi11 = x1 + (l )*incx; \ x01 = x1 + (0 )*incx; \ \ /* chi11 = chi11 - a10t * x01; */ \ PASTEMAC(ch,set0s)( rho1 ); \ if ( bli_is_conj( conja ) ) \ { \ for ( j = 0; j < f_behind; ++j ) \ PASTEMAC(ch,dotjs)( *(a10t + j*cs_at), *(x01 + j*incx), rho1 ); \ } \ else \ { \ for ( j = 0; j < f_behind; ++j ) \ PASTEMAC(ch,dots)( *(a10t + j*cs_at), *(x01 + j*incx), rho1 ); \ } \ PASTEMAC(ch,subs)( rho1, *chi11 ); \ \ /* chi11 = chi11 / alpha11; */ \ if ( bli_is_nonunit_diag( diaga ) ) \ { \ PASTEMAC(ch,copycjs)( conja, *alpha11, alpha11_conj ); \ PASTEMAC(ch,invscals)( alpha11_conj, *chi11 ); \ } \ } \ } \ } \ } INSERT_GENTFUNC_BASIC0( trsv_unf_var1 ) blis-0.9.0/frame/2/trsv/bli_trsv_unf_var2.c000066400000000000000000000142741422157504600205120ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ uplo_t uploa, \ trans_t transa, \ diag_t diaga, \ dim_t m, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* x, inc_t incx, \ cntx_t* cntx \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ ctype* minus_one = PASTEMAC(ch,m1); \ ctype* A01; \ ctype* A11; \ ctype* A21; \ ctype* a01; \ ctype* alpha11; \ ctype* a21; \ ctype* x0; \ ctype* x1; \ ctype* x2; \ ctype* x01; \ ctype* chi11; \ ctype* x21; \ ctype alpha11_conj; \ ctype minus_chi11; \ dim_t iter, i, k, j, l; \ dim_t b_fuse, f; \ dim_t n_ahead, f_ahead; \ inc_t rs_at, cs_at; \ uplo_t uploa_trans; \ conj_t conja; \ \ /* x = alpha * x; */ \ PASTEMAC2(ch,scalv,BLIS_TAPI_EX_SUF) \ ( \ BLIS_NO_CONJUGATE, \ m, \ alpha, \ x, incx, \ cntx, \ NULL \ ); \ \ if ( bli_does_notrans( transa ) ) \ { \ rs_at = rs_a; \ cs_at = cs_a; \ uploa_trans = uploa; \ } \ else /* if ( bli_does_trans( transa ) ) */ \ { \ rs_at = cs_a; \ cs_at = rs_a; \ uploa_trans = bli_uplo_toggled( uploa ); \ } \ \ conja = bli_extract_conj( transa ); \ \ PASTECH(ch,axpyf_ker_ft) kfp_af; \ \ /* Query the context for the kernel function pointer and fusing factor. */ \ kfp_af = bli_cntx_get_l1f_ker_dt( dt, BLIS_AXPYF_KER, cntx ); \ b_fuse = bli_cntx_get_blksz_def_dt( dt, BLIS_AF, cntx ); \ \ /* We reduce all of the possible cases down to just lower/upper. */ \ if ( bli_is_upper( uploa_trans ) ) \ { \ for ( iter = 0; iter < m; iter += f ) \ { \ f = bli_determine_blocksize_dim_b( iter, m, b_fuse ); \ i = m - iter - f; \ n_ahead = i; \ A11 = a + (i )*rs_at + (i )*cs_at; \ A01 = a + (0 )*rs_at + (i )*cs_at; \ x1 = x + (i )*incx; \ x0 = x + (0 )*incx; \ \ /* x1 = x1 / triu( A11 ); */ \ for ( k = 0; k < f; ++k ) \ { \ l = f - k - 1; \ f_ahead = l; \ alpha11 = A11 + (l )*rs_at + (l )*cs_at; \ a01 = A11 + (0 )*rs_at + (l )*cs_at; \ chi11 = x1 + (l )*incx; \ x01 = x1 + (0 )*incx; \ \ /* chi11 = chi11 / alpha11; */ \ if ( bli_is_nonunit_diag( diaga ) ) \ { \ PASTEMAC(ch,copycjs)( conja, *alpha11, alpha11_conj ); \ PASTEMAC(ch,invscals)( alpha11_conj, *chi11 ); \ } \ \ /* x01 = x01 - chi11 * a01; */ \ PASTEMAC(ch,neg2s)( *chi11, minus_chi11 ); \ if ( bli_is_conj( conja ) ) \ { \ for ( j = 0; j < f_ahead; ++j ) \ PASTEMAC(ch,axpyjs)( minus_chi11, *(a01 + j*rs_at), *(x01 + j*incx) ); \ } \ else \ { \ for ( j = 0; j < f_ahead; ++j ) \ PASTEMAC(ch,axpys)( minus_chi11, *(a01 + j*rs_at), *(x01 + j*incx) ); \ } \ } \ \ /* x0 = x0 - A01 * x1; */ \ kfp_af \ ( \ conja, \ BLIS_NO_CONJUGATE, \ n_ahead, \ f, \ minus_one, \ A01, rs_at, cs_at, \ x1, incx, \ x0, incx, \ cntx \ ); \ } \ } \ else /* if ( bli_is_lower( uploa_trans ) ) */ \ { \ for ( iter = 0; iter < m; iter += f ) \ { \ f = bli_determine_blocksize_dim_f( iter, m, b_fuse ); \ i = iter; \ n_ahead = m - iter - f; \ A11 = a + (i )*rs_at + (i )*cs_at; \ A21 = a + (i+f)*rs_at + (i )*cs_at; \ x1 = x + (i )*incx; \ x2 = x + (i+f)*incx; \ \ /* x1 = x1 / tril( A11 ); */ \ for ( k = 0; k < f; ++k ) \ { \ l = k; \ f_ahead = f - k - 1; \ alpha11 = A11 + (l )*rs_at + (l )*cs_at; \ a21 = A11 + (l+1)*rs_at + (l )*cs_at; \ chi11 = x1 + (l )*incx; \ x21 = x1 + (l+1)*incx; \ \ /* chi11 = chi11 / alpha11; */ \ if ( bli_is_nonunit_diag( diaga ) ) \ { \ PASTEMAC(ch,copycjs)( conja, *alpha11, alpha11_conj ); \ PASTEMAC(ch,invscals)( alpha11_conj, *chi11 ); \ } \ \ /* x21 = x21 - chi11 * a21; */ \ PASTEMAC(ch,neg2s)( *chi11, minus_chi11 ); \ if ( bli_is_conj( conja ) ) \ { \ for ( j = 0; j < f_ahead; ++j ) \ PASTEMAC(ch,axpyjs)( minus_chi11, *(a21 + j*rs_at), *(x21 + j*incx) ); \ } \ else \ { \ for ( j = 0; j < f_ahead; ++j ) \ PASTEMAC(ch,axpys)( minus_chi11, *(a21 + j*rs_at), *(x21 + j*incx) ); \ } \ } \ \ /* x2 = x2 - A21 * x1; */ \ kfp_af \ ( \ conja, \ BLIS_NO_CONJUGATE, \ n_ahead, \ f, \ minus_one, \ A21, rs_at, cs_at, \ x1, incx, \ x2, incx, \ cntx \ ); \ } \ } \ } INSERT_GENTFUNC_BASIC0( trsv_unf_var2 ) blis-0.9.0/frame/2/trsv/bli_trsv_var.h000066400000000000000000000051641422157504600175630ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype object-based interfaces. // #undef GENPROT #define GENPROT( opname ) \ \ void PASTEMAC0(opname) \ ( \ obj_t* alpha, \ obj_t* a, \ obj_t* x, \ cntx_t* cntx, \ cntl_t* cntl \ ); GENPROT( trsv_l_blk_var1 ) GENPROT( trsv_l_blk_var2 ) GENPROT( trsv_u_blk_var1 ) GENPROT( trsv_u_blk_var2 ) GENPROT( trsv_unb_var1 ) GENPROT( trsv_unb_var2 ) GENPROT( trsv_unf_var1 ) GENPROT( trsv_unf_var2 ) // // Prototype BLAS-like interfaces with typed operands. // #undef GENTPROT #define GENTPROT( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ uplo_t uploa, \ trans_t transa, \ diag_t diaga, \ dim_t m, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* x, inc_t incx, \ cntx_t* cntx \ ); INSERT_GENTPROT_BASIC0( trsv_unb_var1 ) INSERT_GENTPROT_BASIC0( trsv_unb_var2 ) INSERT_GENTPROT_BASIC0( trsv_unf_var1 ) INSERT_GENTPROT_BASIC0( trsv_unf_var2 ) blis-0.9.0/frame/2/trsv/bli_trsv_var_oapi.c000066400000000000000000000056121422157504600205640ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENFRONT #define GENFRONT( opname, varname ) \ \ void PASTEMAC0(varname) \ ( \ obj_t* alpha, \ obj_t* a, \ obj_t* x, \ cntx_t* cntx, \ cntl_t* cntl \ ) \ { \ bli_init_once(); \ \ num_t dt = bli_obj_dt( a ); \ \ uplo_t uploa = bli_obj_uplo( a ); \ trans_t transa = bli_obj_conjtrans_status( a ); \ diag_t diaga = bli_obj_diag( a ); \ \ dim_t m = bli_obj_length( a ); \ \ void* buf_a = bli_obj_buffer_at_off( a ); \ inc_t rs_a = bli_obj_row_stride( a ); \ inc_t cs_a = bli_obj_col_stride( a ); \ \ void* buf_x = bli_obj_buffer_at_off( x ); \ inc_t incx = bli_obj_vector_inc( x ); \ \ void* buf_alpha = bli_obj_buffer_for_1x1( dt, alpha ); \ \ /* Query a type-specific function pointer, except one that uses void* for function arguments instead of typed pointers. */ \ PASTECH2(opname,_unb,_vft) f = \ PASTEMAC(varname,_qfp)( dt ); \ \ f \ ( \ uploa, \ transa, \ diaga, \ m, \ buf_alpha, \ buf_a, rs_a, cs_a, \ buf_x, incx, \ cntx \ ); \ } \ GENFRONT( trsv, trsv_unb_var1 ) GENFRONT( trsv, trsv_unb_var2 ) GENFRONT( trsv, trsv_unf_var1 ) GENFRONT( trsv, trsv_unf_var2 ) blis-0.9.0/frame/2/trsv/other/000077500000000000000000000000001422157504600160315ustar00rootroot00000000000000blis-0.9.0/frame/2/trsv/other/bli_trsv_cntl.c000066400000000000000000000147571422157504600210570ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" extern scalv_t* scalv_cntl; extern packm_t* packm_cntl; extern packv_t* packv_cntl; extern unpackv_t* unpackv_cntl; extern gemv_t* gemv_cntl_rp_bs_dot; extern gemv_t* gemv_cntl_rp_bs_axpy; extern gemv_t* gemv_cntl_cp_bs_dot; extern gemv_t* gemv_cntl_cp_bs_axpy; trsv_t* trsv_cntl_bs_ke_nrow_tcol = NULL; trsv_t* trsv_cntl_bs_ke_ncol_trow = NULL; trsv_t* trsv_cntl_ge_nrow_tcol = NULL; trsv_t* trsv_cntl_ge_ncol_trow = NULL; void bli_trsv_cntl_init() { // Create control trees for the lowest-level kernels. These trees induce // operations on (presumably) relatively small block-subvector problems. trsv_cntl_bs_ke_nrow_tcol = bli_trsv_cntl_obj_create( BLIS_UNB_FUSED, BLIS_VARIANT1, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL ); trsv_cntl_bs_ke_ncol_trow = bli_trsv_cntl_obj_create( BLIS_UNB_FUSED, BLIS_VARIANT2, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL ); // Create control trees for generally large problems. Here we choose a // variant that prioritizes keeping a subvector of x in cache. trsv_cntl_ge_nrow_tcol = bli_trsv_cntl_obj_create( BLIS_BLOCKED, BLIS_VARIANT1, // use var1 to maximize x1 usage BLIS_M2, scalv_cntl, // scale x up-front packm_cntl, // pack A11 (if needed) packv_cntl, // pack x1 (if needed) gemv_cntl_rp_bs_dot, // gemv_rp needed by var1 NULL, // gemv_cp not needed by var1 trsv_cntl_bs_ke_nrow_tcol, unpackv_cntl ); // unpack x1 (if needed) trsv_cntl_ge_ncol_trow = bli_trsv_cntl_obj_create( BLIS_BLOCKED, BLIS_VARIANT1, // use var1 to maximize x1 usage BLIS_M2, scalv_cntl, // scale x up-front packm_cntl, // pack A11 (if needed) packv_cntl, // pack x1 (if needed) gemv_cntl_rp_bs_axpy, // gemv_rp needed by var1 NULL, // gemv_cp not needed by var1 trsv_cntl_bs_ke_ncol_trow, unpackv_cntl ); // unpack x1 (if needed) } void bli_trsv_cntl_finalize() { bli_cntl_free_node( trsv_cntl_bs_ke_nrow_tcol ); bli_cntl_free_node( trsv_cntl_bs_ke_ncol_trow ); bli_cntl_free_node( trsv_cntl_ge_nrow_tcol ); bli_cntl_free_node( trsv_cntl_ge_ncol_trow ); } trsv_t* bli_trsv_cntl_obj_create( impl_t impl_type, varnum_t var_num, bszid_t bszid, scalv_t* sub_scalv, packm_t* sub_packm_a11, packv_t* sub_packv_x1, gemv_t* sub_gemv_rp, gemv_t* sub_gemv_cp, trsv_t* sub_trsv, unpackv_t* sub_unpackv_x1 ) { trsv_t* cntl; cntl = ( trsv_t* ) bli_malloc_intl( sizeof(trsv_t) ); cntl->impl_type = impl_type; cntl->var_num = var_num; cntl->bszid = bszid; cntl->sub_scalv = sub_scalv; cntl->sub_packm_a11 = sub_packm_a11; cntl->sub_packv_x1 = sub_packv_x1; cntl->sub_gemv_rp = sub_gemv_rp; cntl->sub_gemv_cp = sub_gemv_cp; cntl->sub_trsv = sub_trsv; cntl->sub_unpackv_x1 = sub_unpackv_x1; return cntl; } void bli_trsv_cntl_obj_init( trsv_t* cntl, impl_t impl_type, varnum_t var_num, bszid_t bszid, scalv_t* sub_scalv, packm_t* sub_packm_a11, packv_t* sub_packv_x1, gemv_t* sub_gemv_rp, gemv_t* sub_gemv_cp, trsv_t* sub_trsv, unpackv_t* sub_unpackv_x1 ) { cntl->impl_type = impl_type; cntl->var_num = var_num; cntl->bszid = bszid; cntl->sub_scalv = sub_scalv; cntl->sub_packm_a11 = sub_packm_a11; cntl->sub_packv_x1 = sub_packv_x1; cntl->sub_gemv_rp = sub_gemv_rp; cntl->sub_gemv_cp = sub_gemv_cp; cntl->sub_trsv = sub_trsv; cntl->sub_unpackv_x1 = sub_unpackv_x1; } blis-0.9.0/frame/2/trsv/other/bli_trsv_cntl.h000066400000000000000000000063621422157504600210550ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ struct trsv_s { impl_t impl_type; varnum_t var_num; bszid_t bszid; struct scalv_s* sub_scalv; struct packm_s* sub_packm_a11; struct packv_s* sub_packv_x1; struct gemv_s* sub_gemv_rp; struct gemv_s* sub_gemv_cp; struct trsv_s* sub_trsv; struct unpackv_s* sub_unpackv_x1; }; typedef struct trsv_s trsv_t; #define bli_cntl_sub_trsv( cntl ) cntl->sub_trsv void bli_trsv_cntl_init( void ); void bli_trsv_cntl_finalize( void ); trsv_t* bli_trsv_cntl_obj_create( impl_t impl_type, varnum_t var_num, bszid_t bszid, scalv_t* sub_scalv, packm_t* sub_packm_a11, packv_t* sub_packv_x1, gemv_t* sub_gemv_rp, gemv_t* sub_gemv_cp, trsv_t* sub_trsv, unpackv_t* sub_unpackv_x1 ); void bli_trsv_cntl_obj_init( trsv_t* cntl, impl_t impl_type, varnum_t var_num, bszid_t bszid, scalv_t* sub_scalv, packm_t* sub_packm_a11, packv_t* sub_packv_x1, gemv_t* sub_gemv_rp, gemv_t* sub_gemv_cp, trsv_t* sub_trsv, unpackv_t* sub_unpackv_x1 ); blis-0.9.0/frame/2/trsv/other/bli_trsv_front.c000066400000000000000000000130761422157504600212400ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" extern trsv_t* trsv_cntl_bs_ke_nrow_tcol; extern trsv_t* trsv_cntl_bs_ke_ncol_trow; extern trsv_t* trsv_cntl_ge_nrow_tcol; extern trsv_t* trsv_cntl_ge_ncol_trow; void bli_trsv_front ( obj_t* alpha, obj_t* a, obj_t* x, cntx_t* cntx ) { trsv_t* trsv_cntl; num_t dt_targ_a; num_t dt_targ_x; bool a_has_unit_inc; bool x_has_unit_inc; obj_t alpha_local; num_t dt_alpha; // Check parameters. if ( bli_error_checking_is_enabled() ) bli_trsv_check( alpha, a, x ); // Query the target datatypes of each object. dt_targ_a = bli_obj_dt( a ); dt_targ_x = bli_obj_dt( x ); // Determine whether each operand with unit stride. a_has_unit_inc = ( bli_obj_is_row_stored( a ) || bli_obj_is_col_stored( a ) ); x_has_unit_inc = ( bli_obj_vector_inc( x ) == 1 ); // Create an object to hold a copy-cast of alpha. Notice that we use // the type union of the target datatypes of a and x to prevent any // unnecessary loss of information during the computation. dt_alpha = bli_dt_union( dt_targ_a, dt_targ_x ); bli_obj_scalar_init_detached_copy_of( dt_alpha, BLIS_NO_CONJUGATE, alpha, &alpha_local ); // If all operands have unit stride, we choose a control tree for calling // the unblocked implementation directly without any blocking. if ( a_has_unit_inc && x_has_unit_inc ) { if ( bli_obj_has_notrans( a ) ) { if ( bli_obj_is_row_stored( a ) ) trsv_cntl = trsv_cntl_bs_ke_nrow_tcol; else trsv_cntl = trsv_cntl_bs_ke_ncol_trow; } else // if ( bli_obj_has_trans( a ) ) { if ( bli_obj_is_row_stored( a ) ) trsv_cntl = trsv_cntl_bs_ke_ncol_trow; else trsv_cntl = trsv_cntl_bs_ke_nrow_tcol; } } else { // Mark objects with unit stride as already being packed. This prevents // unnecessary packing from happening within the blocked algorithm. if ( a_has_unit_inc ) bli_obj_set_pack_schema( BLIS_PACKED_UNSPEC, a ); if ( x_has_unit_inc ) bli_obj_set_pack_schema( BLIS_PACKED_VECTOR, x ); // Here, we make a similar choice as above, except that (1) we look // at storage tilt, and (2) we choose a tree that performs blocking. if ( bli_obj_has_notrans( a ) ) { if ( bli_obj_is_row_tilted( a ) ) trsv_cntl = trsv_cntl_ge_nrow_tcol; else trsv_cntl = trsv_cntl_ge_ncol_trow; } else // if ( bli_obj_has_trans( a ) ) { if ( bli_obj_is_row_tilted( a ) ) trsv_cntl = trsv_cntl_ge_ncol_trow; else trsv_cntl = trsv_cntl_ge_nrow_tcol; } } // Invoke the internal back-end with the copy-cast of alpha and the // chosen control tree. bli_trsv_int( &alpha_local, a, x, cntx, trsv_cntl ); } // // Define BLAS-like interfaces with homogeneous-typed operands. // #undef GENTFUNC #define GENTFUNC( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ uplo_t uploa, \ trans_t transa, \ diag_t diaga, \ dim_t m, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* x, inc_t incx, \ cntx_t* cntx \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ obj_t alphao, ao, xo; \ \ inc_t rs_x, cs_x; \ \ rs_x = incx; cs_x = m * incx; \ \ bli_obj_create_1x1_with_attached_buffer( dt, alpha, &alphao ); \ \ bli_obj_create_with_attached_buffer( dt, m, m, a, rs_a, cs_a, &ao ); \ bli_obj_create_with_attached_buffer( dt, m, 1, x, rs_x, cs_x, &xo ); \ \ bli_obj_set_uplo( uploa, &ao ); \ bli_obj_set_conjtrans( transa, &ao ); \ bli_obj_set_diag( diaga, &ao ); \ \ bli_obj_set_struc( BLIS_TRIANGULAR, &ao ); \ \ PASTEMAC0(opname)( &alphao, \ &ao, \ &xo, \ cntx ); \ } INSERT_GENTFUNC_BASIC0( trsv_front ) blis-0.9.0/frame/2/trsv/other/bli_trsv_front.h000066400000000000000000000041471422157504600212440ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void bli_trsv_front ( obj_t* alpha, obj_t* a, obj_t* x, cntx_t* cntx ); #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ uplo_t uploa, \ trans_t transa, \ diag_t diaga, \ dim_t m, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* x, inc_t incx, \ cntx_t* cntx \ ); INSERT_GENTPROT_BASIC( trsv_front ) blis-0.9.0/frame/2/trsv/other/bli_trsv_int.c000066400000000000000000000120201422157504600206660ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define FUNCPTR_T trsv_fp typedef void (*FUNCPTR_T)( obj_t* alpha, obj_t* a, obj_t* x, cntx_t* cntx, trsv_t* cntl ); static FUNCPTR_T vars[2][3][3] = { // lower triangular { // unblocked unblocked with fusing blocked { bli_trsv_unb_var1, bli_trsv_unf_var1, bli_trsv_l_blk_var1 }, { bli_trsv_unb_var2, bli_trsv_unf_var2, bli_trsv_l_blk_var2 }, { NULL, NULL, NULL }, }, // upper triangular { // unblocked unblocked with fusing blocked { bli_trsv_unb_var1, bli_trsv_unf_var1, bli_trsv_u_blk_var1 }, { bli_trsv_unb_var2, bli_trsv_unf_var2, bli_trsv_u_blk_var2 }, { NULL, NULL, NULL }, } }; void bli_trsv_int( obj_t* alpha, obj_t* a, obj_t* x, cntx_t* cntx, trsv_t* cntl ) { varnum_t n; impl_t i; bool uplo; FUNCPTR_T f; obj_t a_local; // Check parameters. if ( bli_error_checking_is_enabled() ) bli_trsv_check( alpha, a, x ); // If A or x has a zero dimension, return early. if ( bli_obj_has_zero_dim( a ) ) return; if ( bli_obj_has_zero_dim( x ) ) return; // Alias A in case we need to induce a transformation (ie: transposition). bli_obj_alias_to( a, &a_local ); // NOTE: to support cases where B is complex and A is real, we will // need to have the default side case be BLIS_RIGHT and then express // the left case in terms of it, rather than the other way around. // Determine uplo (for indexing to the correct function pointer). if ( bli_obj_is_lower( &a_local ) ) uplo = 0; else uplo = 1; // We do not explicitly implement the cases where A is transposed. // However, we can still handle them. Specifically, if A is marked as // needing a transposition, we simply toggle the uplo value to cause the // correct algorithm to be induced. When that algorithm partitions into // A, it will grab the correct subpartitions, which will inherit A's // transposition bit and thus downstream subproblems will do the right // thing. Alternatively, we could accomplish the same end goal by // inducing a transposition, via bli_obj_induce_trans(), in the code // block below. That macro function swaps dimensions, strides, and // offsets. As an example, given a lower triangular, column-major matrix // that needs a transpose, we would induce that transposition by recasting // the object as an upper triangular, row-major matrix (with no transpose // needed). Note that how we choose to handle transposition here does NOT // affect the optimal choice of kernel (ie: a column-major column panel // matrix with transpose times a vector would use the same kernel as a // row-major row panel matrix with no transpose times a vector). if ( bli_obj_has_trans( &a_local ) ) { //bli_obj_induce_trans( &a_local ); //bli_obj_set_onlytrans( BLIS_NO_TRANSPOSE, &a_local ); if ( uplo == 1 ) uplo = 0; else uplo = 1; } // Extract the variant number and implementation type. n = bli_cntl_var_num( cntl ); i = bli_cntl_impl_type( cntl ); // Index into the variant array to extract the correct function pointer. f = vars[uplo][n][i]; // Invoke the variant. f( alpha, &a_local, x, cntx, cntl ); } blis-0.9.0/frame/2/trsv/other/bli_trsv_int.h000066400000000000000000000034541422157504600207060ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void bli_trsv_int( obj_t* alpha, obj_t* a, obj_t* x, cntx_t* cntx, trsv_t* cntl ); blis-0.9.0/frame/2/trsv/other/bli_trsv_l_blk_var1.c000066400000000000000000000102551422157504600221200ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_trsv_l_blk_var1( obj_t* alpha, obj_t* a, obj_t* x, cntx_t* cntx, trsv_t* cntl ) { obj_t a11, a11_pack; obj_t a10; obj_t x1, x1_pack; obj_t x0; dim_t mn; dim_t ij; dim_t b_alg; // Initialize objects for packing. bli_obj_init_pack( &a11_pack ); bli_obj_init_pack( &x1_pack ); // Query dimension. mn = bli_obj_length( a ); // x = alpha * x; bli_scalv_int( alpha, x, cntx, bli_cntl_sub_scalv( cntl ) ); // Partition diagonally. for ( ij = 0; ij < mn; ij += b_alg ) { // Determine the current algorithmic blocksize. b_alg = bli_determine_blocksize_f( ij, mn, a, bli_cntl_bszid( cntl ), cntx ); // Acquire partitions for A11, A10, x1, and x0. bli_acquire_mpart_tl2br( BLIS_SUBPART11, ij, b_alg, a, &a11 ); bli_acquire_mpart_tl2br( BLIS_SUBPART10, ij, b_alg, a, &a10 ); bli_acquire_vpart_f2b( BLIS_SUBPART1, ij, b_alg, x, &x1 ); bli_acquire_vpart_f2b( BLIS_SUBPART0, ij, b_alg, x, &x0 ); // Initialize objects for packing A11 and x1 (if needed). bli_packm_init( &a11, &a11_pack, cntx, bli_cntl_sub_packm_a11( cntl ) ); bli_packv_init( &x1, &x1_pack, cntx, bli_cntl_sub_packv_x1( cntl ) ); // Copy/pack A11, x1 (if needed). bli_packm_int( &a11, &a11_pack, cntx, bli_cntl_sub_packm_a11( cntl ), &BLIS_PACKM_SINGLE_THREADED ); bli_packv_int( &x1, &x1_pack, cntx, bli_cntl_sub_packv_x1( cntl ) ); // x1 = x1 - A10 * x0; bli_gemv_int( BLIS_NO_TRANSPOSE, BLIS_NO_CONJUGATE, &BLIS_MINUS_ONE, &a10, &x0, &BLIS_ONE, &x1_pack, cntx, bli_cntl_sub_gemv_rp( cntl ) ); // x1 = x1 / tril( A11 ); bli_trsv_int( &BLIS_ONE, &a11_pack, &x1_pack, cntx, bli_cntl_sub_trsv( cntl ) ); // Copy/unpack x1 (if x1 was packed). bli_unpackv_int( &x1_pack, &x1, cntx, bli_cntl_sub_unpackv_x1( cntl ) ); } // If any packing buffers were acquired within packm, release them back // to the memory manager. bli_packm_release( &a11_pack, bli_cntl_sub_packm_a11( cntl ) ); bli_packv_release( &x1_pack, bli_cntl_sub_packv_x1( cntl ) ); } blis-0.9.0/frame/2/trsv/other/bli_trsv_l_blk_var2.c000066400000000000000000000102551422157504600221210ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_trsv_l_blk_var2( obj_t* alpha, obj_t* a, obj_t* x, cntx_t* cntx, trsv_t* cntl ) { obj_t a11, a11_pack; obj_t a21; obj_t x1, x1_pack; obj_t x2; dim_t mn; dim_t ij; dim_t b_alg; // Initialize objects for packing. bli_obj_init_pack( &a11_pack ); bli_obj_init_pack( &x1_pack ); // Query dimension. mn = bli_obj_length( a ); // x = alpha * x; bli_scalv_int( alpha, x, cntx, bli_cntl_sub_scalv( cntl ) ); // Partition diagonally. for ( ij = 0; ij < mn; ij += b_alg ) { // Determine the current algorithmic blocksize. b_alg = bli_determine_blocksize_f( ij, mn, a, bli_cntl_bszid( cntl ), cntx ); // Acquire partitions for A11, A21, x1, and x2. bli_acquire_mpart_tl2br( BLIS_SUBPART11, ij, b_alg, a, &a11 ); bli_acquire_mpart_tl2br( BLIS_SUBPART21, ij, b_alg, a, &a21 ); bli_acquire_vpart_f2b( BLIS_SUBPART1, ij, b_alg, x, &x1 ); bli_acquire_vpart_f2b( BLIS_SUBPART2, ij, b_alg, x, &x2 ); // Initialize objects for packing A11 and x1 (if needed). bli_packm_init( &a11, &a11_pack, cntx, bli_cntl_sub_packm_a11( cntl ) ); bli_packv_init( &x1, &x1_pack, cntx, bli_cntl_sub_packv_x1( cntl ) ); // Copy/pack A11, x1 (if needed). bli_packm_int( &a11, &a11_pack, cntx, bli_cntl_sub_packm_a11( cntl ), &BLIS_PACKM_SINGLE_THREADED ); bli_packv_int( &x1, &x1_pack, cntx, bli_cntl_sub_packv_x1( cntl ) ); // x1 = x1 / tril( A11 ); bli_trsv_int( &BLIS_ONE, &a11_pack, &x1_pack, cntx, bli_cntl_sub_trsv( cntl ) ); // x2 = x2 - A21 * x1; bli_gemv_int( BLIS_NO_TRANSPOSE, BLIS_NO_CONJUGATE, &BLIS_MINUS_ONE, &a21, &x1_pack, &BLIS_ONE, &x2, cntx, bli_cntl_sub_gemv_cp( cntl ) ); // Copy/unpack x1 (if x1 was packed). bli_unpackv_int( &x1_pack, &x1, cntx, bli_cntl_sub_unpackv_x1( cntl ) ); } // If any packing buffers were acquired within packm, release them back // to the memory manager. bli_packm_release( &a11_pack, bli_cntl_sub_packm_a11( cntl ) ); bli_packv_release( &x1_pack, bli_cntl_sub_packv_x1( cntl ) ); } blis-0.9.0/frame/2/trsv/other/bli_trsv_u_blk_var1.c000066400000000000000000000102551422157504600221310ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_trsv_u_blk_var1( obj_t* alpha, obj_t* a, obj_t* x, cntx_t* cntx, trsv_t* cntl ) { obj_t a11, a11_pack; obj_t a12; obj_t x1, x1_pack; obj_t x2; dim_t mn; dim_t ij; dim_t b_alg; // Initialize objects for packing. bli_obj_init_pack( &a11_pack ); bli_obj_init_pack( &x1_pack ); // Query dimension. mn = bli_obj_length( a ); // x = alpha * x; bli_scalv_int( alpha, x, cntx, bli_cntl_sub_scalv( cntl ) ); // Partition diagonally. for ( ij = 0; ij < mn; ij += b_alg ) { // Determine the current algorithmic blocksize. b_alg = bli_determine_blocksize_b( ij, mn, a, bli_cntl_bszid( cntl ), cntx ); // Acquire partitions for A11, A12, x1, and x2. bli_acquire_mpart_br2tl( BLIS_SUBPART11, ij, b_alg, a, &a11 ); bli_acquire_mpart_br2tl( BLIS_SUBPART12, ij, b_alg, a, &a12 ); bli_acquire_vpart_b2f( BLIS_SUBPART1, ij, b_alg, x, &x1 ); bli_acquire_vpart_b2f( BLIS_SUBPART2, ij, b_alg, x, &x2 ); // Initialize objects for packing A11 and x1 (if needed). bli_packm_init( &a11, &a11_pack, cntx, bli_cntl_sub_packm_a11( cntl ) ); bli_packv_init( &x1, &x1_pack, cntx, bli_cntl_sub_packv_x1( cntl ) ); // Copy/pack A11, x1 (if needed). bli_packm_int( &a11, &a11_pack, cntx, bli_cntl_sub_packm_a11( cntl ), &BLIS_PACKM_SINGLE_THREADED ); bli_packv_int( &x1, &x1_pack, cntx, bli_cntl_sub_packv_x1( cntl ) ); // x1 = x1 - A12 * x2; bli_gemv_int( BLIS_NO_TRANSPOSE, BLIS_NO_CONJUGATE, &BLIS_MINUS_ONE, &a12, &x2, &BLIS_ONE, &x1_pack, cntx, bli_cntl_sub_gemv_rp( cntl ) ); // x1 = x1 / tril( A11 ); bli_trsv_int( &BLIS_ONE, &a11_pack, &x1_pack, cntx, bli_cntl_sub_trsv( cntl ) ); // Copy/unpack x1 (if x1 was packed). bli_unpackv_int( &x1_pack, &x1, cntx, bli_cntl_sub_unpackv_x1( cntl ) ); } // If any packing buffers were acquired within packm, release them back // to the memory manager. bli_packm_release( &a11_pack, bli_cntl_sub_packm_a11( cntl ) ); bli_packv_release( &x1_pack, bli_cntl_sub_packv_x1( cntl ) ); } blis-0.9.0/frame/2/trsv/other/bli_trsv_u_blk_var2.c000066400000000000000000000102551422157504600221320ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_trsv_u_blk_var2( obj_t* alpha, obj_t* a, obj_t* x, cntx_t* cntx, trsv_t* cntl ) { obj_t a11, a11_pack; obj_t a01; obj_t x1, x1_pack; obj_t x0; dim_t mn; dim_t ij; dim_t b_alg; // Initialize objects for packing. bli_obj_init_pack( &a11_pack ); bli_obj_init_pack( &x1_pack ); // Query dimension. mn = bli_obj_length( a ); // x = alpha * x; bli_scalv_int( alpha, x, cntx, bli_cntl_sub_scalv( cntl ) ); // Partition diagonally. for ( ij = 0; ij < mn; ij += b_alg ) { // Determine the current algorithmic blocksize. b_alg = bli_determine_blocksize_b( ij, mn, a, bli_cntl_bszid( cntl ), cntx ); // Acquire partitions for A11, A01, x1, and x0. bli_acquire_mpart_br2tl( BLIS_SUBPART11, ij, b_alg, a, &a11 ); bli_acquire_mpart_br2tl( BLIS_SUBPART01, ij, b_alg, a, &a01 ); bli_acquire_vpart_b2f( BLIS_SUBPART1, ij, b_alg, x, &x1 ); bli_acquire_vpart_b2f( BLIS_SUBPART0, ij, b_alg, x, &x0 ); // Initialize objects for packing A11 and x1 (if needed). bli_packm_init( &a11, &a11_pack, cntx, bli_cntl_sub_packm_a11( cntl ) ); bli_packv_init( &x1, &x1_pack, cntx, bli_cntl_sub_packv_x1( cntl ) ); // Copy/pack A11, x1 (if needed). bli_packm_int( &a11, &a11_pack, cntx, bli_cntl_sub_packm_a11( cntl ), &BLIS_PACKM_SINGLE_THREADED ); bli_packv_int( &x1, &x1_pack, cntx, bli_cntl_sub_packv_x1( cntl ) ); // x1 = x1 / tril( A11 ); bli_trsv_int( &BLIS_ONE, &a11_pack, &x1_pack, cntx, bli_cntl_sub_trsv( cntl ) ); // x0 = x0 - A01 * x1; bli_gemv_int( BLIS_NO_TRANSPOSE, BLIS_NO_CONJUGATE, &BLIS_MINUS_ONE, &a01, &x1_pack, &BLIS_ONE, &x0, cntx, bli_cntl_sub_gemv_cp( cntl ) ); // Copy/unpack x1 (if x1 was packed). bli_unpackv_int( &x1_pack, &x1, cntx, bli_cntl_sub_unpackv_x1( cntl ) ); } // If any packing buffers were acquired within packm, release them back // to the memory manager. bli_packm_release( &a11_pack, bli_cntl_sub_packm_a11( cntl ) ); bli_packv_release( &x1_pack, bli_cntl_sub_packv_x1( cntl ) ); } blis-0.9.0/frame/3/000077500000000000000000000000001422157504600137135ustar00rootroot00000000000000blis-0.9.0/frame/3/bli_l3.h000066400000000000000000000062201422157504600152300ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "bli_l3_cntl.h" #include "bli_l3_check.h" #include "bli_l3_int.h" #include "bli_l3_packab.h" // Define function types. //#include "bli_l3_ft_ex.h" #include "bli_l3_ft_ukr.h" #include "bli_l3_oft.h" #include "bli_l3_oft_var.h" #include "bli_l3_blocksize.h" #include "bli_l3_direct.h" #include "bli_l3_prune.h" #include "bli_l3_schema.h" // Prototype object APIs (basic and expert). #include "bli_l3_oapi.h" #include "bli_l3_oapi_ex.h" // Prototype typed APIs (basic and expert). #include "bli_l3_tapi.h" #include "bli_l3_tapi_ex.h" // Define function types for small/unpacked handlers/kernels. #include "bli_l3_sup_oft.h" #include "bli_l3_sup_ft_ker.h" // Define static edge case logic for use in small/unpacked kernels. //#include "bli_l3_sup_edge.h" // Prototype object API to small/unpacked matrix dispatcher. #include "bli_l3_sup.h" // Prototype reference implementation of small/unpacked matrix handler. #include "bli_l3_sup_ref.h" #include "bli_l3_sup_int.h" #include "bli_l3_sup_vars.h" #include "bli_l3_sup_packm_a.h" #include "bli_l3_sup_packm_b.h" #include "bli_l3_sup_packm_var.h" // Prototype microkernel wrapper APIs. #include "bli_l3_ukr_oapi.h" #include "bli_l3_ukr_tapi.h" // Generate function pointer arrays for tapi microkernel functions. #include "bli_l3_ukr_fpa.h" // Operation-specific headers. #include "bli_gemm.h" #include "bli_hemm.h" #include "bli_symm.h" #include "bli_trmm.h" #include "bli_trmm3.h" #include "bli_trsm.h" #include "bli_gemmt.h" blis-0.9.0/frame/3/bli_l3_blocksize.c000066400000000000000000000246151422157504600173000ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" dim_t bli_l3_determine_kc ( dir_t direct, dim_t i, dim_t dim, obj_t* a, obj_t* b, bszid_t bszid, cntx_t* cntx, cntl_t* cntl ) { opid_t family = bli_cntl_family( cntl ); if ( family == BLIS_GEMM ) return bli_gemm_determine_kc( direct, i, dim, a, b, bszid, cntx ); else if ( family == BLIS_GEMMT ) return bli_gemmt_determine_kc( direct, i, dim, a, b, bszid, cntx ); else if ( family == BLIS_TRMM ) return bli_trmm_determine_kc( direct, i, dim, a, b, bszid, cntx ); else if ( family == BLIS_TRSM ) return bli_trsm_determine_kc( direct, i, dim, a, b, bszid, cntx ); // This should never execute. return bli_gemm_determine_kc( direct, i, dim, a, b, bszid, cntx ); } // ----------------------------------------------------------------------------- // // NOTE: We call a gemm/hemm/symm, trmm, or trsm-specific blocksize // function to determine the kc blocksize so that we can implement the // "nudging" of kc to be a multiple of mr or nr, as needed. // #undef GENFRONT #define GENFRONT( opname, l3op ) \ \ dim_t PASTEMAC0(opname) \ ( \ dir_t direct, \ dim_t i, \ dim_t dim, \ obj_t* a, \ obj_t* b, \ bszid_t bszid, \ cntx_t* cntx \ ) \ { \ if ( direct == BLIS_FWD ) \ return PASTEMAC(l3op,_determine_kc_f)( i, dim, a, b, bszid, cntx ); \ else \ return PASTEMAC(l3op,_determine_kc_b)( i, dim, a, b, bszid, cntx ); \ } GENFRONT( gemm_determine_kc, gemm ) GENFRONT( gemmt_determine_kc, gemmt ) GENFRONT( trmm_determine_kc, trmm ) GENFRONT( trsm_determine_kc, trsm ) // ----------------------------------------------------------------------------- #undef GENFRONT #define GENFRONT( opname, chdir ) \ \ dim_t PASTEMAC0(opname) \ ( \ dim_t i, \ dim_t dim, \ obj_t* a, \ obj_t* b, \ bszid_t bszid, \ cntx_t* cntx \ ) \ { \ num_t dt; \ blksz_t* bsize; \ dim_t mnr; \ dim_t b_alg, b_max; \ dim_t b_use; \ \ /* bli_*_determine_kc_f(): We assume that this function is being called from an algorithm that is moving "forward" (ie: top to bottom, left to right, top-left to bottom-right). */ \ \ /* bli_*_determine_kc_b(): We assume that this function is being called from an algorithm that is moving "backward" (ie: bottom to top, right to left, bottom-right to top-left). */ \ \ /* Extract the execution datatype and use it to query the corresponding blocksize and blocksize maximum values from the blksz_t object. */ \ dt = bli_obj_exec_dt( a ); \ bsize = bli_cntx_get_blksz( bszid, cntx ); \ b_alg = bli_blksz_get_def( dt, bsize ); \ b_max = bli_blksz_get_max( dt, bsize ); \ \ /* Nudge the default and maximum kc blocksizes up to the nearest multiple of MR if A is Hermitian or symmetric, or NR if B is Hermitian or symmetric. If neither case applies, then we leave the blocksizes unchanged. */ \ if ( bli_obj_root_is_herm_or_symm( a ) ) \ { \ mnr = bli_cntx_get_blksz_def_dt( dt, BLIS_MR, cntx ); \ b_alg = bli_align_dim_to_mult( b_alg, mnr ); \ b_max = bli_align_dim_to_mult( b_max, mnr ); \ } \ else if ( bli_obj_root_is_herm_or_symm( b ) ) \ { \ mnr = bli_cntx_get_blksz_def_dt( dt, BLIS_NR, cntx ); \ b_alg = bli_align_dim_to_mult( b_alg, mnr ); \ b_max = bli_align_dim_to_mult( b_max, mnr ); \ } \ \ /* Call the bli_determine_blocksize_[fb]_sub() helper routine defined in bli_blksz.c */ \ b_use = PASTEMAC2(determine_blocksize_,chdir,_sub)( i, dim, b_alg, b_max ); \ \ return b_use; \ } GENFRONT( gemm_determine_kc_f, f ) GENFRONT( gemm_determine_kc_b, b ) // ----------------------------------------------------------------------------- #undef GENFRONT #define GENFRONT( opname, chdir ) \ \ dim_t PASTEMAC0(opname) \ ( \ dim_t i, \ dim_t dim, \ obj_t* a, \ obj_t* b, \ bszid_t bszid, \ cntx_t* cntx \ ) \ { \ num_t dt; \ blksz_t* bsize; \ dim_t b_alg, b_max; \ dim_t b_use; \ \ /* bli_*_determine_kc_f(): We assume that this function is being called from an algorithm that is moving "forward" (ie: top to bottom, left to right, top-left to bottom-right). */ \ \ /* bli_*_determine_kc_b(): We assume that this function is being called from an algorithm that is moving "backward" (ie: bottom to top, right to left, bottom-right to top-left). */ \ \ /* Extract the execution datatype and use it to query the corresponding blocksize and blocksize maximum values from the blksz_t object. */ \ dt = bli_obj_exec_dt( a ); \ bsize = bli_cntx_get_blksz( bszid, cntx ); \ b_alg = bli_blksz_get_def( dt, bsize ); \ b_max = bli_blksz_get_max( dt, bsize ); \ \ /* Notice that for gemmt, we do not need to perform any special handling for the default and maximum kc blocksizes vis-a-vis MR or NR. */ \ \ /* Call the bli_determine_blocksize_[fb]_sub() helper routine defined in bli_blksz.c */ \ b_use = PASTEMAC2(determine_blocksize_,chdir,_sub)( i, dim, b_alg, b_max ); \ \ return b_use; \ } GENFRONT( gemmt_determine_kc_f, f ) GENFRONT( gemmt_determine_kc_b, b ) // ----------------------------------------------------------------------------- #undef GENFRONT #define GENFRONT( opname, chdir ) \ \ dim_t PASTEMAC0(opname) \ ( \ dim_t i, \ dim_t dim, \ obj_t* a, \ obj_t* b, \ bszid_t bszid, \ cntx_t* cntx \ ) \ { \ num_t dt; \ blksz_t* bsize; \ dim_t mnr; \ dim_t b_alg, b_max; \ dim_t b_use; \ \ /* bli_*_determine_kc_f(): We assume that this function is being called from an algorithm that is moving "forward" (ie: top to bottom, left to right, top-left to bottom-right). */ \ \ /* bli_*_determine_kc_b(): We assume that this function is being called from an algorithm that is moving "backward" (ie: bottom to top, right to left, bottom-right to top-left). */ \ \ /* Extract the execution datatype and use it to query the corresponding blocksize and blocksize maximum values from the blksz_t object. */ \ dt = bli_obj_exec_dt( a ); \ bsize = bli_cntx_get_blksz( bszid, cntx ); \ b_alg = bli_blksz_get_def( dt, bsize ); \ b_max = bli_blksz_get_max( dt, bsize ); \ \ /* Nudge the default and maximum kc blocksizes up to the nearest multiple of MR if the triangular matrix is on the left, or NR if the triangular matrix is one the right. */ \ if ( bli_obj_root_is_triangular( a ) ) \ mnr = bli_cntx_get_blksz_def_dt( dt, BLIS_MR, cntx ); \ else \ mnr = bli_cntx_get_blksz_def_dt( dt, BLIS_NR, cntx ); \ \ b_alg = bli_align_dim_to_mult( b_alg, mnr ); \ b_max = bli_align_dim_to_mult( b_max, mnr ); \ \ /* Call the bli_determine_blocksize_[fb]_sub() helper routine defined in bli_blksz.c */ \ b_use = PASTEMAC2(determine_blocksize_,chdir,_sub)( i, dim, b_alg, b_max ); \ \ return b_use; \ } GENFRONT( trmm_determine_kc_f, f ) GENFRONT( trmm_determine_kc_b, b ) // ----------------------------------------------------------------------------- #undef GENFRONT #define GENFRONT( opname, chdir ) \ \ dim_t PASTEMAC0(opname) \ ( \ dim_t i, \ dim_t dim, \ obj_t* a, \ obj_t* b, \ bszid_t bszid, \ cntx_t* cntx \ ) \ { \ num_t dt; \ blksz_t* bsize; \ dim_t mnr; \ dim_t b_alg, b_max; \ dim_t b_use; \ \ /* bli_*_determine_kc_f(): We assume that this function is being called from an algorithm that is moving "forward" (ie: top to bottom, left to right, top-left to bottom-right). */ \ \ /* bli_*_determine_kc_b(): We assume that this function is being called from an algorithm that is moving "backward" (ie: bottom to top, right to left, bottom-right to top-left). */ \ \ /* Extract the execution datatype and use it to query the corresponding blocksize and blocksize maximum values from the blksz_t object. */ \ dt = bli_obj_exec_dt( a ); \ bsize = bli_cntx_get_blksz( bszid, cntx ); \ b_alg = bli_blksz_get_def( dt, bsize ); \ b_max = bli_blksz_get_max( dt, bsize ); \ \ /* Nudge the default and maximum kc blocksizes up to the nearest multiple of MR. We always use MR (rather than sometimes using NR) because even when the triangle is on the right, packing of that matrix uses MR, since only left-side trsm micro-kernels are supported. */ \ mnr = bli_cntx_get_blksz_def_dt( dt, BLIS_MR, cntx ); \ b_alg = bli_align_dim_to_mult( b_alg, mnr ); \ b_max = bli_align_dim_to_mult( b_max, mnr ); \ \ /* Call the bli_determine_blocksize_[fb]_sub() helper routine defined in bli_blksz.c */ \ b_use = PASTEMAC2(determine_blocksize_,chdir,_sub)( i, dim, b_alg, b_max ); \ \ return b_use; \ } GENFRONT( trsm_determine_kc_f, f ) GENFRONT( trsm_determine_kc_b, b ) blis-0.9.0/frame/3/bli_l3_blocksize.h000066400000000000000000000053001422157504600172730ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ dim_t bli_l3_determine_kc ( dir_t direct, dim_t i, dim_t dim, obj_t* a, obj_t* b, bszid_t bszid, cntx_t* cntx, cntl_t* cntl ); #undef GENPROT #define GENPROT( opname ) \ \ dim_t PASTEMAC0(opname) \ ( \ dir_t direct, \ dim_t i, \ dim_t dim, \ obj_t* a, \ obj_t* b, \ bszid_t bszid, \ cntx_t* cntx \ ); GENPROT( gemm_determine_kc ) GENPROT( gemmt_determine_kc ) GENPROT( trmm_determine_kc ) GENPROT( trsm_determine_kc ) #undef GENPROT #define GENPROT( opname ) \ \ dim_t PASTEMAC0(opname) \ ( \ dim_t i, \ dim_t dim, \ obj_t* a, \ obj_t* b, \ bszid_t bszid, \ cntx_t* cntx \ ); GENPROT( gemm_determine_kc_f ) GENPROT( gemm_determine_kc_b ) GENPROT( gemmt_determine_kc_f ) GENPROT( gemmt_determine_kc_b ) GENPROT( trmm_determine_kc_f ) GENPROT( trmm_determine_kc_b ) GENPROT( trsm_determine_kc_f ) GENPROT( trsm_determine_kc_b ) blis-0.9.0/frame/3/bli_l3_check.c000066400000000000000000000320431422157504600163620ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_gemm_check ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx ) { //err_t e_val; // Check basic properties of the operation. bli_gemm_basic_check( alpha, a, b, beta, c, cntx ); // Check object structure. // NOTE: Can't perform these checks as long as bli_gemm_check() is called // from bli_l3_int(), which is in the execution path for structured // level-3 operations such as hemm. //e_val = bli_check_general_object( a ); //bli_check_error_code( e_val ); //e_val = bli_check_general_object( b ); //bli_check_error_code( e_val ); } void bli_gemmt_check ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx ) { err_t e_val; // Check basic properties of the operation. bli_gemmt_basic_check( alpha, a, b, beta, c, cntx ); // Check matrix squareness. e_val = bli_check_square_object( c ); bli_check_error_code( e_val ); } void bli_hemm_check ( side_t side, obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx ) { err_t e_val; // Perform checks common to hemm/symm/trmm/trsm. bli_hemm_basic_check( side, alpha, a, b, beta, c, cntx ); // Check object structure. e_val = bli_check_hermitian_object( a ); bli_check_error_code( e_val ); } void bli_herk_check ( obj_t* alpha, obj_t* a, obj_t* beta, obj_t* c, cntx_t* cntx ) { err_t e_val; obj_t ah; // Alias A to A^H so we can perform dimension checks. bli_obj_alias_with_trans( BLIS_CONJ_TRANSPOSE, a, &ah ); // Check basic properties of the operation. bli_herk_basic_check( alpha, a, &ah, beta, c, cntx ); // Check for real-valued alpha and beta. e_val = bli_check_real_valued_object( alpha ); bli_check_error_code( e_val ); e_val = bli_check_real_valued_object( beta ); bli_check_error_code( e_val ); // Check matrix structure. e_val = bli_check_hermitian_object( c ); bli_check_error_code( e_val ); } void bli_her2k_check ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx ) { err_t e_val; obj_t ah, bh; // Alias A and B to A^H and B^H so we can perform dimension checks. bli_obj_alias_with_trans( BLIS_CONJ_TRANSPOSE, a, &ah ); bli_obj_alias_with_trans( BLIS_CONJ_TRANSPOSE, b, &bh ); // Check basic properties of the operation. bli_her2k_basic_check( alpha, a, &bh, b, &ah, beta, c, cntx ); // Check for real-valued beta. e_val = bli_check_real_valued_object( beta ); bli_check_error_code( e_val ); // Check matrix structure. e_val = bli_check_hermitian_object( c ); bli_check_error_code( e_val ); } void bli_symm_check ( side_t side, obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx ) { err_t e_val; // Check basic properties of the operation. bli_hemm_basic_check( side, alpha, a, b, beta, c, cntx ); // Check object structure. e_val = bli_check_symmetric_object( a ); bli_check_error_code( e_val ); } void bli_syrk_check ( obj_t* alpha, obj_t* a, obj_t* beta, obj_t* c, cntx_t* cntx ) { err_t e_val; obj_t at; // Alias A to A^T so we can perform dimension checks. bli_obj_alias_with_trans( BLIS_TRANSPOSE, a, &at ); // Check basic properties of the operation. bli_herk_basic_check( alpha, a, &at, beta, c, cntx ); // Check matrix structure. e_val = bli_check_symmetric_object( c ); bli_check_error_code( e_val ); } void bli_syr2k_check ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx ) { err_t e_val; obj_t at, bt; // Alias A and B to A^T and B^T so we can perform dimension checks. bli_obj_alias_with_trans( BLIS_TRANSPOSE, a, &at ); bli_obj_alias_with_trans( BLIS_TRANSPOSE, b, &bt ); // Check basic properties of the operation. bli_her2k_basic_check( alpha, a, &bt, b, &at, beta, c, cntx ); // Check matrix structure. e_val = bli_check_symmetric_object( c ); bli_check_error_code( e_val ); } void bli_trmm3_check ( side_t side, obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx ) { err_t e_val; // Perform checks common to hemm/symm/trmm/trsm. bli_hemm_basic_check( side, alpha, a, b, beta, c, cntx ); // Check object structure. e_val = bli_check_triangular_object( a ); bli_check_error_code( e_val ); } void bli_trmm_check ( side_t side, obj_t* alpha, obj_t* a, obj_t* b, cntx_t* cntx ) { err_t e_val; // Perform checks common to hemm/symm/trmm/trsm. bli_hemm_basic_check( side, alpha, a, b, &BLIS_ZERO, b, cntx ); // Check object structure. e_val = bli_check_triangular_object( a ); bli_check_error_code( e_val ); } void bli_trsm_check ( side_t side, obj_t* alpha, obj_t* a, obj_t* b, cntx_t* cntx ) { err_t e_val; // Perform checks common to hemm/symm/trmm/trsm. bli_hemm_basic_check( side, alpha, a, b, &BLIS_ZERO, b, cntx ); // Check object structure. e_val = bli_check_triangular_object( a ); bli_check_error_code( e_val ); } // ----------------------------------------------------------------------------- void bli_gemm_basic_check ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx ) { err_t e_val; // Perform standard checks. bli_l3_basic_check( alpha, a, b, beta, c, cntx ); // Check object dimensions. e_val = bli_check_level3_dims( a, b, c ); bli_check_error_code( e_val ); #ifdef BLIS_ENABLE_GEMM_MD // Skip checking for consistent datatypes between A, B, and C since // that is totally valid for mixed-datatype gemm. // When mixing datatypes, make sure that alpha does not have a non-zero // imaginary component. if ( bli_obj_dt( c ) != bli_obj_dt( a ) || bli_obj_dt( c ) != bli_obj_dt( b ) || bli_obj_comp_prec( c ) != bli_obj_prec( c ) ) if ( !bli_obj_imag_is_zero( alpha ) ) { bli_print_msg( "Mixed-datatype gemm does not yet support alpha with a non-zero imaginary component. Please contact BLIS developers for further support.", __FILE__, __LINE__ ); bli_abort(); } #else // BLIS_DISABLE_GEMM_MD // Check for consistent datatypes. // NOTE: We only perform these tests when mixed datatype support is // disabled. e_val = bli_check_consistent_object_datatypes( c, a ); bli_check_error_code( e_val ); e_val = bli_check_consistent_object_datatypes( c, b ); bli_check_error_code( e_val ); #endif } void bli_gemmt_basic_check ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx ) { err_t e_val; // Perform standard checks. bli_l3_basic_check( alpha, a, b, beta, c, cntx ); // Check object dimensions. e_val = bli_check_level3_dims( a, b, c ); bli_check_error_code( e_val ); } void bli_hemm_basic_check ( side_t side, obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx ) { err_t e_val; // Perform standard checks. bli_l3_basic_check( alpha, a, b, beta, c, cntx ); // Check object dimensions. if ( bli_is_left( side ) ) { e_val = bli_check_level3_dims( a, b, c ); bli_check_error_code( e_val ); } else // if ( bli_is_right( side ) ) { e_val = bli_check_level3_dims( b, a, c ); bli_check_error_code( e_val ); } // Check matrix squareness. e_val = bli_check_square_object( a ); bli_check_error_code( e_val ); // Check for consistent datatypes. e_val = bli_check_consistent_object_datatypes( c, a ); bli_check_error_code( e_val ); e_val = bli_check_consistent_object_datatypes( c, b ); bli_check_error_code( e_val ); } void bli_herk_basic_check ( obj_t* alpha, obj_t* a, obj_t* ah, obj_t* beta, obj_t* c, cntx_t* cntx ) { err_t e_val; // Perform standard checks. bli_l3_basic_check( alpha, a, ah, beta, c, cntx ); // Check object dimensions. e_val = bli_check_level3_dims( a, ah, c ); bli_check_error_code( e_val ); // Check matrix squareness. e_val = bli_check_square_object( c ); bli_check_error_code( e_val ); // Check matrix structure. e_val = bli_check_general_object( a ); bli_check_error_code( e_val ); e_val = bli_check_general_object( ah ); bli_check_error_code( e_val ); // Check for consistent datatypes. e_val = bli_check_consistent_object_datatypes( c, a ); bli_check_error_code( e_val ); e_val = bli_check_consistent_object_datatypes( c, ah ); bli_check_error_code( e_val ); } void bli_her2k_basic_check ( obj_t* alpha, obj_t* a, obj_t* bh, obj_t* b, obj_t* ah, obj_t* beta, obj_t* c, cntx_t* cntx ) { err_t e_val; // Perform standard checks. bli_l3_basic_check( alpha, a, bh, beta, c, cntx ); bli_l3_basic_check( alpha, b, ah, beta, c, cntx ); // Check object dimensions. e_val = bli_check_level3_dims( a, bh, c ); bli_check_error_code( e_val ); e_val = bli_check_level3_dims( b, ah, c ); bli_check_error_code( e_val ); // Check matrix squareness. e_val = bli_check_square_object( c ); bli_check_error_code( e_val ); // Check matrix structure. e_val = bli_check_general_object( a ); bli_check_error_code( e_val ); e_val = bli_check_general_object( bh ); bli_check_error_code( e_val ); e_val = bli_check_general_object( b ); bli_check_error_code( e_val ); e_val = bli_check_general_object( ah ); bli_check_error_code( e_val ); // Check for consistent datatypes. e_val = bli_check_consistent_object_datatypes( c, a ); bli_check_error_code( e_val ); e_val = bli_check_consistent_object_datatypes( c, ah ); bli_check_error_code( e_val ); e_val = bli_check_consistent_object_datatypes( c, b ); bli_check_error_code( e_val ); e_val = bli_check_consistent_object_datatypes( c, bh ); bli_check_error_code( e_val ); } void bli_l3_basic_check ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx ) { err_t e_val; // Check object datatypes. e_val = bli_check_noninteger_object( alpha ); bli_check_error_code( e_val ); e_val = bli_check_noninteger_object( beta ); bli_check_error_code( e_val ); e_val = bli_check_floating_object( a ); bli_check_error_code( e_val ); e_val = bli_check_floating_object( b ); bli_check_error_code( e_val ); e_val = bli_check_floating_object( c ); bli_check_error_code( e_val ); // Check object dimensions. e_val = bli_check_scalar_object( alpha ); bli_check_error_code( e_val ); e_val = bli_check_scalar_object( beta ); bli_check_error_code( e_val ); e_val = bli_check_matrix_object( a ); bli_check_error_code( e_val ); e_val = bli_check_matrix_object( b ); bli_check_error_code( e_val ); e_val = bli_check_matrix_object( c ); bli_check_error_code( e_val ); // Check object buffers (for non-NULLness). e_val = bli_check_object_buffer( alpha ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( a ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( b ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( beta ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( c ); bli_check_error_code( e_val ); } blis-0.9.0/frame/3/bli_l3_check.h000066400000000000000000000074561422157504600164010ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype object-based check functions. // #undef GENPROT #define GENPROT( opname ) \ \ void PASTEMAC(opname,_check) \ ( \ obj_t* alpha, \ obj_t* a, \ obj_t* b, \ obj_t* beta, \ obj_t* c, \ cntx_t* cntx \ ); GENPROT( gemm ) GENPROT( gemmt ) GENPROT( her2k ) GENPROT( syr2k ) #undef GENPROT #define GENPROT( opname ) \ \ void PASTEMAC(opname,_check) \ ( \ side_t side, \ obj_t* alpha, \ obj_t* a, \ obj_t* b, \ obj_t* beta, \ obj_t* c, \ cntx_t* cntx \ ); GENPROT( hemm ) GENPROT( symm ) GENPROT( trmm3 ) #undef GENPROT #define GENPROT( opname ) \ \ void PASTEMAC(opname,_check) \ ( \ obj_t* alpha, \ obj_t* a, \ obj_t* beta, \ obj_t* c, \ cntx_t* cntx \ ); GENPROT( herk ) GENPROT( syrk ) #undef GENPROT #define GENPROT( opname ) \ \ void PASTEMAC(opname,_check) \ ( \ side_t side, \ obj_t* alpha, \ obj_t* a, \ obj_t* b, \ cntx_t* cntx \ ); GENPROT( trmm ) GENPROT( trsm ) // ----------------------------------------------------------------------------- void bli_gemm_basic_check ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx ); void bli_gemmt_basic_check ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx ); void bli_hemm_basic_check ( side_t side, obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx ); void bli_herk_basic_check ( obj_t* alpha, obj_t* a, obj_t* ah, obj_t* beta, obj_t* c, cntx_t* cntx ); void bli_her2k_basic_check ( obj_t* alpha, obj_t* a, obj_t* bh, obj_t* b, obj_t* ah, obj_t* beta, obj_t* c, cntx_t* cntx ); void bli_l3_basic_check ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx ); blis-0.9.0/frame/3/bli_l3_cntl.c000066400000000000000000000071311422157504600162450ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_l3_cntl_create_if ( opid_t family, pack_t schema_a, pack_t schema_b, obj_t* a, obj_t* b, obj_t* c, rntm_t* rntm, cntl_t* cntl_orig, cntl_t** cntl_use ) { // If the control tree pointer is NULL, we construct a default // tree as a function of the operation family. if ( cntl_orig == NULL ) { if ( family == BLIS_GEMM || family == BLIS_GEMMT || family == BLIS_TRMM ) { *cntl_use = bli_gemm_cntl_create ( rntm, family, schema_a, schema_b, bli_obj_ker_fn( c ) ); } else // if ( family == BLIS_TRSM ) { side_t side; if ( bli_obj_is_triangular( a ) ) side = BLIS_LEFT; else side = BLIS_RIGHT; *cntl_use = bli_trsm_cntl_create ( rntm, side, schema_a, schema_b, bli_obj_ker_fn( c ) ); } } else { // If the user provided a control tree, create a copy and use it // instead (so that threads can use its local tree as a place to // cache things like pack mem_t entries). *cntl_use = bli_cntl_copy( rntm, cntl_orig ); // Recursively set the family fields of the newly copied control tree // nodes. bli_cntl_mark_family( family, *cntl_use ); } } void bli_l3_cntl_free ( rntm_t* rntm, cntl_t* cntl_use, thrinfo_t* thread ) { // NOTE: We don't actually need to call separate _cntl_free() functions // for gemm and trsm; it is merely an unnecessary mirroring of behavior // from the _create() side (which must call different functions based // on the family). opid_t family = bli_cntl_family( cntl_use ); if ( family == BLIS_GEMM || family == BLIS_GEMMT || family == BLIS_TRMM ) { bli_gemm_cntl_free( rntm, cntl_use, thread ); } else // if ( family == BLIS_TRSM ) { bli_trsm_cntl_free( rntm, cntl_use, thread ); } } blis-0.9.0/frame/3/bli_l3_cntl.h000066400000000000000000000041631422157504600162540ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype conditional control tree creation functions. // void bli_l3_cntl_create_if ( opid_t family, pack_t schema_a, pack_t schema_b, obj_t* a, obj_t* b, obj_t* c, rntm_t* rntm, cntl_t* cntl_orig, cntl_t** cntl_use ); void bli_l3_cntl_free ( rntm_t* rntm, cntl_t* cntl_use, thrinfo_t* thread ); blis-0.9.0/frame/3/bli_l3_direct.c000066400000000000000000000074241422157504600165640ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" dir_t bli_l3_direct ( obj_t* a, obj_t* b, obj_t* c, cntl_t* cntl ) { // Query the operation family. opid_t family = bli_cntl_family( cntl ); if ( family == BLIS_GEMM ) return bli_gemm_direct( a, b, c ); else if ( family == BLIS_GEMMT ) return bli_gemmt_direct( a, b, c ); else if ( family == BLIS_TRMM ) return bli_trmm_direct( a, b, c ); else if ( family == BLIS_TRSM ) return bli_trsm_direct( a, b, c ); // This should never execute. return BLIS_FWD; } // ----------------------------------------------------------------------------- dir_t bli_gemm_direct ( obj_t* a, obj_t* b, obj_t* c ) { // For gemm, movement may be forwards (or backwards). return BLIS_FWD; } dir_t bli_gemmt_direct ( obj_t* a, obj_t* b, obj_t* c ) { // For gemmt, movement may be forwards (or backwards). return BLIS_FWD; } dir_t bli_trmm_direct ( obj_t* a, obj_t* b, obj_t* c ) { dir_t direct; // For trmm, movement for the parameter cases is as follows: // - left,lower: backwards // - left,upper: forwards // - right,lower: forwards // - right,upper: backwards if ( bli_obj_root_is_triangular( a ) ) { if ( bli_obj_root_is_lower( a ) ) direct = BLIS_BWD; else direct = BLIS_FWD; } else // if ( bli_obj_root_is_triangular( b ) ) { if ( bli_obj_root_is_lower( b ) ) direct = BLIS_FWD; else direct = BLIS_BWD; } return direct; } dir_t bli_trsm_direct ( obj_t* a, obj_t* b, obj_t* c ) { dir_t direct; // For trsm, movement for the parameter cases is as follows: // - left,lower: forwards // - left,upper: backwards // - right,lower: backwards // - right,upper: forwards if ( bli_obj_root_is_triangular( a ) ) { if ( bli_obj_root_is_lower( a ) ) direct = BLIS_FWD; else direct = BLIS_BWD; } else // if ( bli_obj_root_is_triangular( b ) ) { if ( bli_obj_root_is_lower( b ) ) direct = BLIS_BWD; else direct = BLIS_FWD; } return direct; } blis-0.9.0/frame/3/bli_l3_direct.h000066400000000000000000000041051422157504600165620ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ dir_t bli_l3_direct ( obj_t* a, obj_t* b, obj_t* c, cntl_t* cntl ); // ----------------------------------------------------------------------------- #undef GENPROT #define GENPROT( opname ) \ \ dir_t PASTEMAC0(opname) \ ( \ obj_t* a, \ obj_t* b, \ obj_t* c \ ); GENPROT( gemm_direct ) GENPROT( gemmt_direct ) GENPROT( trmm_direct ) GENPROT( trsm_direct ) blis-0.9.0/frame/3/bli_l3_ft_ukr.h000066400000000000000000000063071422157504600166100ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_L3_FT_UKR_H #define BLIS_L3_FT_UKR_H // // -- Level-3 micro-kernel function types -------------------------------------- // // gemm #undef GENTDEF #define GENTDEF( ctype, ch, opname, tsuf ) \ \ typedef void (*PASTECH3(ch,opname,_ukr,tsuf)) \ ( \ dim_t m, \ dim_t n, \ dim_t k, \ ctype* restrict alpha, \ ctype* restrict a, \ ctype* restrict b, \ ctype* restrict beta, \ ctype* restrict c, inc_t rs_c, inc_t cs_c, \ auxinfo_t* restrict data, \ cntx_t* restrict cntx \ ); INSERT_GENTDEF( gemm ) // gemmtrsm_[lu] #undef GENTDEF #define GENTDEF( ctype, ch, opname, tsuf ) \ \ typedef void (*PASTECH3(ch,opname,_ukr,tsuf)) \ ( \ dim_t m, \ dim_t n, \ dim_t k, \ ctype* restrict alpha, \ ctype* restrict a1x, \ ctype* restrict a11, \ ctype* restrict bx1, \ ctype* restrict b11, \ ctype* restrict c11, inc_t rs_c, inc_t cs_c, \ auxinfo_t* restrict data, \ cntx_t* restrict cntx \ ); INSERT_GENTDEF( gemmtrsm ) // trsm_[lu] #undef GENTDEF #define GENTDEF( ctype, ch, opname, tsuf ) \ \ typedef void (*PASTECH3(ch,opname,_ukr,tsuf)) \ ( \ ctype* restrict a, \ ctype* restrict b, \ ctype* restrict c, inc_t rs_c, inc_t cs_c, \ auxinfo_t* restrict data, \ cntx_t* restrict cntx \ ); INSERT_GENTDEF( trsm ) #endif blis-0.9.0/frame/3/bli_l3_ind.c000066400000000000000000000172431422157504600160640ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // This array tracks whether a particular operation is implemented for each of // the induced methods. static bool bli_l3_ind_oper_impl[BLIS_NUM_IND_METHODS][BLIS_NUM_LEVEL3_OPS] = { /* gemm gemmt hemm herk her2k symm syrk syr2k trmm3 trmm trsm */ /* 1m */ { TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE }, /* nat */ { TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE } }; // // NOTE: "2" is used instead of BLIS_NUM_FP_TYPES/2. // // BLIS provides APIs to modify this state during runtime. So, it's possible for one // application thread to modify the state before another starts the corresponding // BLIS operation. This is solved by making the induced method status array local to // threads. static BLIS_THREAD_LOCAL bool bli_l3_ind_oper_st[BLIS_NUM_IND_METHODS][BLIS_NUM_LEVEL3_OPS][2] = { /* gemm gemmt hemm herk her2k symm syrk syr2k trmm3 trmm trsm */ /* c z */ /* 1m */ { {FALSE,FALSE}, {FALSE,FALSE}, {FALSE,FALSE}, {FALSE,FALSE}, {FALSE,FALSE}, {FALSE,FALSE}, {FALSE,FALSE}, {FALSE,FALSE}, {FALSE,FALSE}, {FALSE,FALSE}, {FALSE,FALSE} }, /* nat */ { {TRUE,TRUE}, {TRUE,TRUE}, {TRUE,TRUE}, {TRUE,TRUE}, {TRUE,TRUE}, {TRUE,TRUE}, {TRUE,TRUE}, {TRUE,TRUE}, {TRUE,TRUE}, {TRUE,TRUE}, {TRUE,TRUE} }, }; // ----------------------------------------------------------------------------- #undef GENFUNC #define GENFUNC( opname, optype ) \ \ ind_t PASTEMAC(opname,ind_find_avail)( num_t dt ) \ { \ return bli_l3_ind_oper_find_avail( optype, dt ); \ } //bool PASTEMAC(opname,ind_has_avail)( num_t dt ) //{ // return bli_ind_oper_has_avail( optype, dt ); //} GENFUNC( gemm, BLIS_GEMM ) GENFUNC( gemmt, BLIS_GEMMT ) GENFUNC( hemm, BLIS_HEMM ) GENFUNC( symm, BLIS_SYMM ) GENFUNC( trmm3, BLIS_TRMM3 ) GENFUNC( trmm, BLIS_TRMM ) GENFUNC( trsm, BLIS_TRSM ) // ----------------------------------------------------------------------------- #if 0 bool bli_l3_ind_oper_is_avail( opid_t oper, ind_t method, num_t dt ) { bool enabled; bool stat; // If the datatype is real, it is never available. if ( !bli_is_complex( dt ) ) return FALSE; enabled = bli_l3_ind_oper_is_impl( oper, method ); stat = bli_l3_ind_oper_get_enable( oper, method, dt ); return ( enabled == TRUE && stat == TRUE ); } #endif // ----------------------------------------------------------------------------- ind_t bli_l3_ind_oper_find_avail( opid_t oper, num_t dt ) { bli_init_once(); ind_t im; // If the datatype is real, return native execution. if ( !bli_is_complex( dt ) ) return BLIS_NAT; // If the operation is not level-3, return native execution. if ( !bli_opid_is_level3( oper ) ) return BLIS_NAT; // Iterate over all induced methods and search for the first one // that is available (ie: both implemented and enabled) for the // current operation and datatype. for ( im = 0; im < BLIS_NUM_IND_METHODS; ++im ) { bool enabled = bli_l3_ind_oper_is_impl( oper, im ); bool stat = bli_l3_ind_oper_get_enable( oper, im, dt ); if ( enabled == TRUE && stat == TRUE ) return im; } // This return statement should never execute since the native index // should be found even if all induced methods are unavailable. We // include it simply to avoid a compiler warning. return BLIS_NAT; } // ----------------------------------------------------------------------------- void bli_l3_ind_set_enable_dt( ind_t method, num_t dt, bool status ) { opid_t iop; if ( !bli_is_complex( dt ) ) return; // Iterate over all level-3 operation ids. for ( iop = 0; iop < BLIS_NUM_LEVEL3_OPS; ++iop ) { bli_l3_ind_oper_set_enable( iop, method, dt, status ); } } // ----------------------------------------------------------------------------- void bli_l3_ind_oper_enable_only( opid_t oper, ind_t method, num_t dt ) { ind_t im; if ( !bli_is_complex( dt ) ) return; if ( !bli_opid_is_level3( oper ) ) return; for ( im = 0; im < BLIS_NUM_IND_METHODS; ++im ) { // Native execution should always stay enabled. if ( im == BLIS_NAT ) continue; // When we come upon the requested method, enable it for the given // operation and datatype. Otherwise, disable it. if ( im == method ) bli_l3_ind_oper_set_enable( oper, im, dt, TRUE ); else bli_l3_ind_oper_set_enable( oper, im, dt, FALSE ); } } void bli_l3_ind_oper_set_enable_all( opid_t oper, num_t dt, bool status ) { ind_t im; if ( !bli_is_complex( dt ) ) return; if ( !bli_opid_is_level3( oper ) ) return; for ( im = 0; im < BLIS_NUM_IND_METHODS; ++im ) { // Native execution should always stay enabled. if ( im != BLIS_NAT ) bli_l3_ind_oper_set_enable( oper, im, dt, status ); } } // ----------------------------------------------------------------------------- // A mutex to allow synchronous access to the bli_l3_ind_oper_st array. static bli_pthread_mutex_t oper_st_mutex = BLIS_PTHREAD_MUTEX_INITIALIZER; void bli_l3_ind_oper_set_enable( opid_t oper, ind_t method, num_t dt, bool status ) { num_t idt; if ( !bli_is_complex( dt ) ) return; if ( !bli_opid_is_level3( oper ) ) return; // Disallow changing status of native execution. if ( method == BLIS_NAT ) return; idt = bli_ind_map_cdt_to_index( dt ); // Acquire the mutex protecting bli_l3_ind_oper_st. bli_pthread_mutex_lock( &oper_st_mutex ); // BEGIN CRITICAL SECTION { bli_l3_ind_oper_st[ method ][ oper ][ idt ] = status; } // END CRITICAL SECTION // Release the mutex protecting bli_l3_ind_oper_st. bli_pthread_mutex_unlock( &oper_st_mutex ); } bool bli_l3_ind_oper_get_enable( opid_t oper, ind_t method, num_t dt ) { num_t idt = bli_ind_map_cdt_to_index( dt ); bool r_val; { r_val = bli_l3_ind_oper_st[ method ][ oper ][ idt ]; } return r_val; } // ----------------------------------------------------------------------------- bool bli_l3_ind_oper_is_impl( opid_t oper, ind_t method ) { return bli_l3_ind_oper_impl[ method ][ oper ]; } blis-0.9.0/frame/3/bli_l3_ind.h000066400000000000000000000053631422157504600160710ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_L3_IND_H #define BLIS_L3_IND_H // ----------------------------------------------------------------------------- #undef GENPROT #define GENPROT( opname ) \ \ ind_t PASTEMAC(opname,ind_find_avail)( num_t dt ); /*bool PASTEMAC(opname,ind_has_avail)( num_t dt ); */ GENPROT( gemm ) GENPROT( gemmt ) GENPROT( hemm ) GENPROT( symm ) GENPROT( trmm3 ) GENPROT( trmm ) GENPROT( trsm ) // ----------------------------------------------------------------------------- //bool bli_l3_ind_oper_is_avail( opid_t oper, ind_t method, num_t dt ); ind_t bli_l3_ind_oper_find_avail( opid_t oper, num_t dt ); void bli_l3_ind_set_enable_dt( ind_t method, num_t dt, bool status ); void bli_l3_ind_oper_enable_only( opid_t oper, ind_t method, num_t dt ); void bli_l3_ind_oper_set_enable_all( opid_t oper, num_t dt, bool status ); void bli_l3_ind_oper_set_enable( opid_t oper, ind_t method, num_t dt, bool status ); bool bli_l3_ind_oper_get_enable( opid_t oper, ind_t method, num_t dt ); bool bli_l3_ind_oper_is_impl( opid_t oper, ind_t method ); #endif blis-0.9.0/frame/3/bli_l3_ind_ukr.h000066400000000000000000000062551422157504600167530ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Define template prototypes for level-3 micro-kernels. // // 1m micro-kernels #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ dim_t m, \ dim_t n, \ dim_t k, \ ctype* restrict alpha, \ ctype* restrict a, \ ctype* restrict b, \ ctype* restrict beta, \ ctype* restrict c, inc_t rs_c, inc_t cs_c, \ auxinfo_t* restrict data, \ cntx_t* restrict cntx \ ); INSERT_GENTPROT_BASIC0( gemm1m_ukr_name ) #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ dim_t m, \ dim_t n, \ dim_t k, \ ctype* restrict alpha, \ ctype* restrict a1x, \ ctype* restrict a11, \ ctype* restrict bx1, \ ctype* restrict b11, \ ctype* restrict c11, inc_t rs_c, inc_t cs_c, \ auxinfo_t* restrict data, \ cntx_t* restrict cntx \ ); INSERT_GENTPROT_BASIC0( gemmtrsm1m_l_ukr_name ) INSERT_GENTPROT_BASIC0( gemmtrsm1m_u_ukr_name ) #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ ctype* restrict a, \ ctype* restrict b, \ ctype* restrict c, inc_t rs_c, inc_t cs_c, \ auxinfo_t* restrict data, \ cntx_t* restrict cntx \ ); INSERT_GENTPROT_BASIC0( trsm1m_l_ukr_name ) INSERT_GENTPROT_BASIC0( trsm1m_u_ukr_name ) blis-0.9.0/frame/3/bli_l3_int.c000066400000000000000000000111311422157504600160720ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_l3_int ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ) { obj_t a_local; obj_t b_local; obj_t c_local; // Return early if the current control tree node is NULL. if ( bli_cntl_is_null( cntl ) ) return; // Check parameters. if ( bli_error_checking_is_enabled() ) bli_gemm_basic_check( alpha, a, b, beta, c, cntx ); // If C has a zero dimension, return early. if ( bli_obj_has_zero_dim( c ) ) { return; } // If A or B has a zero dimension, scale C by beta and return early. if ( bli_obj_has_zero_dim( a ) || bli_obj_has_zero_dim( b ) ) { if ( bli_thread_am_ochief( thread ) ) bli_scalm( beta, c ); bli_thread_barrier( thread ); return; } // If A or B is marked as being filled with zeros, scale C by beta and // return early. if ( bli_obj_is_zeros( a ) || bli_obj_is_zeros( b ) ) { // This should never execute. bli_abort(); if ( bli_thread_am_ochief( thread ) ) bli_scalm( beta, c ); bli_thread_barrier( thread ); return; } // Alias A, B, and C in case we need to update attached scalars. bli_obj_alias_to( a, &a_local ); bli_obj_alias_to( b, &b_local ); bli_obj_alias_to( c, &c_local ); // Ensure that a valid packing function is set on A and B. if ( !bli_obj_pack_fn( &a_local ) ) bli_obj_set_pack_fn( bli_packm_blk_var1, &a_local ); if ( !bli_obj_pack_fn( &b_local ) ) bli_obj_set_pack_fn( bli_packm_blk_var1, &b_local ); // If we are about to call a leaf-level implementation, and matrix C // still needs a transposition, then we must induce one by swapping the // strides and dimensions. Note that this transposition would normally // be handled explicitly in the packing of C, but if C is not being // packed, this is our last chance to handle the transposition. //if ( bli_cntl_is_leaf( cntl ) && bli_obj_has_trans( c ) ) if ( bli_obj_has_trans( c ) ) { bli_obj_induce_trans( &c_local ); bli_obj_set_onlytrans( BLIS_NO_TRANSPOSE, &c_local ); } // If alpha is non-unit, typecast and apply it to the scalar attached // to B, unless it happens to be triangular. if ( bli_obj_root_is_triangular( b ) ) { if ( !bli_obj_equals( alpha, &BLIS_ONE ) ) bli_obj_scalar_apply_scalar( alpha, &a_local ); } else // if ( bli_obj_root_is_triangular( b ) ) { if ( !bli_obj_equals( alpha, &BLIS_ONE ) ) bli_obj_scalar_apply_scalar( alpha, &b_local ); } // If beta is non-unit, typecast and apply it to the scalar attached // to C. if ( !bli_obj_equals( beta, &BLIS_ONE ) ) bli_obj_scalar_apply_scalar( beta, &c_local ); // Create the next node in the thrinfo_t structure. bli_thrinfo_grow( rntm, cntl, thread ); // Extract the function pointer from the current control tree node. l3_var_oft f = bli_cntl_var_func( cntl ); // Invoke the variant. f ( &a_local, &b_local, &c_local, cntx, rntm, cntl, thread ); } blis-0.9.0/frame/3/bli_l3_int.h000066400000000000000000000035421422157504600161060ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void bli_l3_int ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ); blis-0.9.0/frame/3/bli_l3_oapi.c000066400000000000000000000064131422157504600162370ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2021, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // Define object-based interfaces (basic). // #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC0(opname) \ ( \ obj_t* alpha, \ obj_t* a, \ obj_t* b, \ obj_t* beta, \ obj_t* c \ ) \ { \ /* Invoke the expert interface and request default cntx_t and rntm_t objects. */ \ PASTEMAC(opname,_ex)( alpha, a, b, beta, c, NULL, NULL ); \ } GENFRONT( gemm ) GENFRONT( gemmt ) GENFRONT( her2k ) GENFRONT( syr2k ) #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC0(opname) \ ( \ side_t side, \ obj_t* alpha, \ obj_t* a, \ obj_t* b, \ obj_t* beta, \ obj_t* c \ ) \ { \ /* Invoke the expert interface and request default cntx_t and rntm_t objects. */ \ PASTEMAC(opname,_ex)( side, alpha, a, b, beta, c, NULL, NULL ); \ } GENFRONT( hemm ) GENFRONT( symm ) GENFRONT( trmm3 ) #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC0(opname) \ ( \ obj_t* alpha, \ obj_t* a, \ obj_t* beta, \ obj_t* c \ ) \ { \ /* Invoke the expert interface and request default cntx_t and rntm_t objects. */ \ PASTEMAC(opname,_ex)( alpha, a, beta, c, NULL, NULL ); \ } GENFRONT( herk ) GENFRONT( syrk ) #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC0(opname) \ ( \ side_t side, \ obj_t* alpha, \ obj_t* a, \ obj_t* b \ ) \ { \ /* Invoke the expert interface and request default cntx_t and rntm_t objects. */ \ PASTEMAC(opname,_ex)( side, alpha, a, b, NULL, NULL ); \ } GENFRONT( trmm ) GENFRONT( trsm ) blis-0.9.0/frame/3/bli_l3_oapi.h000066400000000000000000000053611422157504600162450ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype object-based interfaces (basic). // #undef GENPROT #define GENPROT( opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC0(opname) \ ( \ obj_t* alpha, \ obj_t* a, \ obj_t* b, \ obj_t* beta, \ obj_t* c \ ); GENPROT( gemm ) GENPROT( gemmt ) GENPROT( her2k ) GENPROT( syr2k ) #undef GENPROT #define GENPROT( opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC0(opname) \ ( \ side_t side, \ obj_t* alpha, \ obj_t* a, \ obj_t* b, \ obj_t* beta, \ obj_t* c \ ); GENPROT( hemm ) GENPROT( symm ) GENPROT( trmm3 ) #undef GENPROT #define GENPROT( opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC0(opname) \ ( \ obj_t* alpha, \ obj_t* a, \ obj_t* beta, \ obj_t* c \ ); GENPROT( herk ) GENPROT( syrk ) #undef GENPROT #define GENPROT( opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC0(opname) \ ( \ side_t side, \ obj_t* alpha, \ obj_t* a, \ obj_t* b \ ); GENPROT( trmm ) GENPROT( trsm ) blis-0.9.0/frame/3/bli_l3_oapi_ex.c000066400000000000000000000411611422157504600167320ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2021, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // Define object-based interfaces (expert). // // If a sandbox was enabled, we forgo defining bli_gemm_ex() since it will be // defined in the sandbox environment. #ifndef BLIS_ENABLE_SANDBOX void PASTEMAC(gemm,BLIS_OAPI_EX_SUF) ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, rntm_t* rntm ) { bli_init_once(); // If the rntm is non-NULL, it may indicate that we should forgo sup // handling altogether. bool enable_sup = TRUE; if ( rntm != NULL ) enable_sup = bli_rntm_l3_sup( rntm ); if ( enable_sup ) { // Execute the small/unpacked oapi handler. If it finds that the problem // does not fall within the thresholds that define "small", or for some // other reason decides not to use the small/unpacked implementation, // the function returns with BLIS_FAILURE, which causes execution to // proceed towards the conventional implementation. err_t result = bli_gemmsup( alpha, a, b, beta, c, cntx, rntm ); if ( result == BLIS_SUCCESS ) { return; } } // Initialize a local runtime with global settings if necessary. Note // that in the case that a runtime is passed in, we make a local copy. rntm_t rntm_l; if ( rntm == NULL ) { bli_rntm_init_from_global( &rntm_l ); rntm = &rntm_l; } else { rntm_l = *rntm; rntm = &rntm_l; } // Default to using native execution. num_t dt = bli_obj_dt( c ); ind_t im = BLIS_NAT; // If each matrix operand has a complex storage datatype, try to get an // induced method (if one is available and enabled). NOTE: Allowing // precisions to vary while using 1m, which is what we do here, is unique // to gemm; other level-3 operations use 1m only if all storage datatypes // are equal (and they ignore the computation precision). if ( bli_obj_is_complex( c ) && bli_obj_is_complex( a ) && bli_obj_is_complex( b ) ) { // Find the highest priority induced method that is both enabled and // available for the current operation. (If an induced method is // available but not enabled, or simply unavailable, BLIS_NAT will // be returned here.) im = bli_gemmind_find_avail( dt ); } // If necessary, obtain a valid context from the gks using the induced // method id determined above. if ( cntx == NULL ) cntx = bli_gks_query_ind_cntx( im, dt ); // Check the operands. if ( bli_error_checking_is_enabled() ) bli_gemm_check( alpha, a, b, beta, c, cntx ); // Invoke the operation's front-end and request the default control tree. bli_gemm_front( alpha, a, b, beta, c, cntx, rntm, NULL ); } #endif void PASTEMAC(gemmt,BLIS_OAPI_EX_SUF) ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, rntm_t* rntm ) { bli_init_once(); // Initialize a local runtime with global settings if necessary. Note // that in the case that a runtime is passed in, we make a local copy. rntm_t rntm_l; if ( rntm == NULL ) { bli_rntm_init_from_global( &rntm_l ); rntm = &rntm_l; } else { rntm_l = *rntm; rntm = &rntm_l; } // Default to using native execution. num_t dt = bli_obj_dt( c ); ind_t im = BLIS_NAT; // If all matrix operands are complex and of the same storage datatype, try // to get an induced method (if one is available and enabled). if ( bli_obj_dt( a ) == bli_obj_dt( c ) && bli_obj_dt( b ) == bli_obj_dt( c ) && bli_obj_is_complex( c ) ) { // Find the highest priority induced method that is both enabled and // available for the current operation. (If an induced method is // available but not enabled, or simply unavailable, BLIS_NAT will // be returned here.) im = bli_gemmtind_find_avail( dt ); } // If necessary, obtain a valid context from the gks using the induced // method id determined above. if ( cntx == NULL ) cntx = bli_gks_query_ind_cntx( im, dt ); // Check the operands. if ( bli_error_checking_is_enabled() ) bli_gemmt_check( alpha, a, b, beta, c, cntx ); // Invoke the operation's front-end and request the default control tree. bli_gemmt_front( alpha, a, b, beta, c, cntx, rntm, NULL ); } void PASTEMAC(her2k,BLIS_OAPI_EX_SUF) ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, rntm_t* rntm ) { bli_init_once(); obj_t ah; obj_t bh; obj_t alphah; // Check parameters. if ( bli_error_checking_is_enabled() ) bli_her2k_check( alpha, a, b, beta, c, cntx ); bli_obj_alias_to( alpha, &alphah ); bli_obj_toggle_conj( &alphah ); bli_obj_alias_to( a, &ah ); bli_obj_toggle_trans( &ah ); bli_obj_toggle_conj( &ah ); bli_obj_alias_to( b, &bh ); bli_obj_toggle_trans( &bh ); bli_obj_toggle_conj( &bh ); // Invoke gemmt twice, using beta only the first time. PASTEMAC(gemmt,BLIS_OAPI_EX_SUF)( alpha, a, &bh, beta, c, cntx, rntm ); PASTEMAC(gemmt,BLIS_OAPI_EX_SUF)( &alphah, b, &ah, &BLIS_ONE, c, cntx, rntm ); // The Hermitian rank-2k product was computed as alpha*A*B'+alpha'*B*A', even for // the diagonal elements. Mathematically, the imaginary components of // diagonal elements of a Hermitian rank-2k product should always be // zero. However, in practice, they sometimes accumulate meaningless // non-zero values. To prevent this, we explicitly set those values // to zero before returning. bli_setid( &BLIS_ZERO, c ); } void PASTEMAC(syr2k,BLIS_OAPI_EX_SUF) ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, rntm_t* rntm ) { bli_init_once(); obj_t at; obj_t bt; // Check parameters. if ( bli_error_checking_is_enabled() ) bli_syr2k_check( alpha, a, b, beta, c, cntx ); bli_obj_alias_to( b, &bt ); bli_obj_toggle_trans( &bt ); bli_obj_alias_to( a, &at ); bli_obj_toggle_trans( &at ); // Invoke gemmt twice, using beta only the first time. PASTEMAC(gemmt,BLIS_OAPI_EX_SUF)( alpha, a, &bt, beta, c, cntx, rntm ); PASTEMAC(gemmt,BLIS_OAPI_EX_SUF)( alpha, b, &at, &BLIS_ONE, c, cntx, rntm ); } void PASTEMAC(hemm,BLIS_OAPI_EX_SUF) ( side_t side, obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, rntm_t* rntm ) { bli_init_once(); // Initialize a local runtime with global settings if necessary. Note // that in the case that a runtime is passed in, we make a local copy. rntm_t rntm_l; if ( rntm == NULL ) { bli_rntm_init_from_global( &rntm_l ); rntm = &rntm_l; } else { rntm_l = *rntm; rntm = &rntm_l; } // Default to using native execution. num_t dt = bli_obj_dt( c ); ind_t im = BLIS_NAT; // If all matrix operands are complex and of the same storage datatype, try // to get an induced method (if one is available and enabled). if ( bli_obj_dt( a ) == bli_obj_dt( c ) && bli_obj_dt( b ) == bli_obj_dt( c ) && bli_obj_is_complex( c ) ) { // Find the highest priority induced method that is both enabled and // available for the current operation. (If an induced method is // available but not enabled, or simply unavailable, BLIS_NAT will // be returned here.) im = bli_hemmind_find_avail( dt ); } // If necessary, obtain a valid context from the gks using the induced // method id determined above. if ( cntx == NULL ) cntx = bli_gks_query_ind_cntx( im, dt ); // Check the operands. if ( bli_error_checking_is_enabled() ) bli_hemm_check( side, alpha, a, b, beta, c, cntx ); // Invoke the operation's front-end and request the default control tree. bli_hemm_front( side, alpha, a, b, beta, c, cntx, rntm, NULL ); } void PASTEMAC(symm,BLIS_OAPI_EX_SUF) ( side_t side, obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, rntm_t* rntm ) { bli_init_once(); // Initialize a local runtime with global settings if necessary. Note // that in the case that a runtime is passed in, we make a local copy. rntm_t rntm_l; if ( rntm == NULL ) { bli_rntm_init_from_global( &rntm_l ); rntm = &rntm_l; } else { rntm_l = *rntm; rntm = &rntm_l; } // Default to using native execution. num_t dt = bli_obj_dt( c ); ind_t im = BLIS_NAT; // If all matrix operands are complex and of the same storage datatype, try // to get an induced method (if one is available and enabled). if ( bli_obj_dt( a ) == bli_obj_dt( c ) && bli_obj_dt( b ) == bli_obj_dt( c ) && bli_obj_is_complex( c ) ) { // Find the highest priority induced method that is both enabled and // available for the current operation. (If an induced method is // available but not enabled, or simply unavailable, BLIS_NAT will // be returned here.) im = bli_symmind_find_avail( dt ); } // If necessary, obtain a valid context from the gks using the induced // method id determined above. if ( cntx == NULL ) cntx = bli_gks_query_ind_cntx( im, dt ); // Check the operands. if ( bli_error_checking_is_enabled() ) bli_symm_check( side, alpha, a, b, beta, c, cntx ); // Invoke the operation's front-end and request the default control tree. bli_symm_front( side, alpha, a, b, beta, c, cntx, rntm, NULL ); } void PASTEMAC(trmm3,BLIS_OAPI_EX_SUF) ( side_t side, obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, rntm_t* rntm ) { bli_init_once(); // Initialize a local runtime with global settings if necessary. Note // that in the case that a runtime is passed in, we make a local copy. rntm_t rntm_l; if ( rntm == NULL ) { bli_rntm_init_from_global( &rntm_l ); rntm = &rntm_l; } else { rntm_l = *rntm; rntm = &rntm_l; } // Default to using native execution. num_t dt = bli_obj_dt( c ); ind_t im = BLIS_NAT; // If all matrix operands are complex and of the same storage datatype, try // to get an induced method (if one is available and enabled). if ( bli_obj_dt( a ) == bli_obj_dt( c ) && bli_obj_dt( b ) == bli_obj_dt( c ) && bli_obj_is_complex( c ) ) { // Find the highest priority induced method that is both enabled and // available for the current operation. (If an induced method is // available but not enabled, or simply unavailable, BLIS_NAT will // be returned here.) im = bli_trmm3ind_find_avail( dt ); } // If necessary, obtain a valid context from the gks using the induced // method id determined above. if ( cntx == NULL ) cntx = bli_gks_query_ind_cntx( im, dt ); // Check the operands. if ( bli_error_checking_is_enabled() ) bli_trmm3_check( side, alpha, a, b, beta, c, cntx ); // Invoke the operation's front-end and request the default control tree. bli_trmm3_front( side, alpha, a, b, beta, c, cntx, rntm, NULL ); } void PASTEMAC(herk,BLIS_OAPI_EX_SUF) ( obj_t* alpha, obj_t* a, obj_t* beta, obj_t* c, cntx_t* cntx, rntm_t* rntm ) { bli_init_once(); obj_t ah; // Check parameters. if ( bli_error_checking_is_enabled() ) bli_herk_check( alpha, a, beta, c, cntx ); bli_obj_alias_to( a, &ah ); bli_obj_toggle_trans( &ah ); bli_obj_toggle_conj( &ah ); PASTEMAC(gemmt,BLIS_OAPI_EX_SUF)( alpha, a, &ah, beta, c, cntx, rntm ); // The Hermitian rank-k product was computed as Re(alpha)*A*A', even for the // diagonal elements. Mathematically, the imaginary components of // diagonal elements of a Hermitian rank-k product should always be // zero. However, in practice, they sometimes accumulate meaningless // non-zero values. To prevent this, we explicitly set those values // to zero before returning. bli_setid( &BLIS_ZERO, c ); } void PASTEMAC(syrk,BLIS_OAPI_EX_SUF) ( obj_t* alpha, obj_t* a, obj_t* beta, obj_t* c, cntx_t* cntx, rntm_t* rntm ) { bli_init_once(); obj_t at; // Check parameters. if ( bli_error_checking_is_enabled() ) bli_syrk_check( alpha, a, beta, c, cntx ); bli_obj_alias_to( a, &at ); bli_obj_toggle_trans( &at ); PASTEMAC(gemmt,BLIS_OAPI_EX_SUF)( alpha, a, &at, beta, c, cntx, rntm ); } void PASTEMAC(trmm,BLIS_OAPI_EX_SUF) ( side_t side, obj_t* alpha, obj_t* a, obj_t* b, cntx_t* cntx, rntm_t* rntm ) { bli_init_once(); // Initialize a local runtime with global settings if necessary. Note // that in the case that a runtime is passed in, we make a local copy. rntm_t rntm_l; if ( rntm == NULL ) { bli_rntm_init_from_global( &rntm_l ); rntm = &rntm_l; } else { rntm_l = *rntm; rntm = &rntm_l; } // Default to using native execution. num_t dt = bli_obj_dt( b ); ind_t im = BLIS_NAT; // If all matrix operands are complex and of the same storage datatype, try // to get an induced method (if one is available and enabled). if ( bli_obj_dt( a ) == bli_obj_dt( b ) && bli_obj_is_complex( b ) ) { // Find the highest priority induced method that is both enabled and // available for the current operation. (If an induced method is // available but not enabled, or simply unavailable, BLIS_NAT will // be returned here.) im = bli_trmmind_find_avail( dt ); } // If necessary, obtain a valid context from the gks using the induced // method id determined above. if ( cntx == NULL ) cntx = bli_gks_query_ind_cntx( im, dt ); // Check the operands. if ( bli_error_checking_is_enabled() ) bli_trmm_check( side, alpha, a, b, cntx ); // Invoke the operation's front-end and request the default control tree. bli_trmm_front( side, alpha, a, b, cntx, rntm, NULL ); } void PASTEMAC(trsm,BLIS_OAPI_EX_SUF) ( side_t side, obj_t* alpha, obj_t* a, obj_t* b, cntx_t* cntx, rntm_t* rntm ) { bli_init_once(); // Initialize a local runtime with global settings if necessary. Note // that in the case that a runtime is passed in, we make a local copy. rntm_t rntm_l; if ( rntm == NULL ) { bli_rntm_init_from_global( &rntm_l ); rntm = &rntm_l; } else { rntm_l = *rntm; rntm = &rntm_l; } // Default to using native execution. num_t dt = bli_obj_dt( b ); ind_t im = BLIS_NAT; // If all matrix operands are complex and of the same storage datatype, try // to get an induced method (if one is available and enabled). if ( bli_obj_dt( a ) == bli_obj_dt( b ) && bli_obj_is_complex( b ) ) { // Find the highest priority induced method that is both enabled and // available for the current operation. (If an induced method is // available but not enabled, or simply unavailable, BLIS_NAT will // be returned here.) im = bli_trsmind_find_avail( dt ); } // If necessary, obtain a valid context from the gks using the induced // method id determined above. if ( cntx == NULL ) cntx = bli_gks_query_ind_cntx( im, dt ); // Check the operands. if ( bli_error_checking_is_enabled() ) bli_trsm_check( side, alpha, a, b, cntx ); // Invoke the operation's front-end and request the default control tree. bli_trsm_front( side, alpha, a, b, cntx, rntm, NULL ); } blis-0.9.0/frame/3/bli_l3_oapi_ex.h000066400000000000000000000057521422157504600167450ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype object-based interfaces (expert). // #undef GENPROT #define GENPROT( opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC(opname,BLIS_OAPI_EX_SUF) \ ( \ obj_t* alpha, \ obj_t* a, \ obj_t* b, \ obj_t* beta, \ obj_t* c, \ cntx_t* cntx, \ rntm_t* rntm \ ); GENPROT( gemm ) GENPROT( gemmt ) GENPROT( her2k ) GENPROT( syr2k ) #undef GENPROT #define GENPROT( opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC(opname,BLIS_OAPI_EX_SUF) \ ( \ side_t side, \ obj_t* alpha, \ obj_t* a, \ obj_t* b, \ obj_t* beta, \ obj_t* c, \ cntx_t* cntx, \ rntm_t* rntm \ ); GENPROT( hemm ) GENPROT( symm ) GENPROT( trmm3 ) #undef GENPROT #define GENPROT( opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC(opname,BLIS_OAPI_EX_SUF) \ ( \ obj_t* alpha, \ obj_t* a, \ obj_t* beta, \ obj_t* c, \ cntx_t* cntx, \ rntm_t* rntm \ ); GENPROT( herk ) GENPROT( syrk ) #undef GENPROT #define GENPROT( opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC(opname,BLIS_OAPI_EX_SUF) \ ( \ side_t side, \ obj_t* alpha, \ obj_t* a, \ obj_t* b, \ cntx_t* cntx, \ rntm_t* rntm \ ); GENPROT( trmm ) GENPROT( trsm ) blis-0.9.0/frame/3/bli_l3_oft.h000066400000000000000000000056051422157504600161060ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_L3_OFT_H #define BLIS_L3_OFT_H // // -- Level-3 object function types -------------------------------------------- // // gemm #undef GENTDEF #define GENTDEF( opname ) \ \ typedef void (*PASTECH(opname,_oft)) \ ( \ obj_t* alpha, \ obj_t* a, \ obj_t* b, \ obj_t* beta, \ obj_t* c, \ cntx_t* cntx, \ rntm_t* rntm \ ); GENTDEF( gemm ) GENTDEF( gemmt ) GENTDEF( her2k ) GENTDEF( syr2k ) // hemm, symm, trmm3 #undef GENTDEF #define GENTDEF( opname ) \ \ typedef void (*PASTECH(opname,_oft)) \ ( \ side_t side, \ obj_t* alpha, \ obj_t* a, \ obj_t* b, \ obj_t* beta, \ obj_t* c, \ cntx_t* cntx, \ rntm_t* rntm \ ); GENTDEF( hemm ) GENTDEF( symm ) GENTDEF( trmm3 ) // herk, syrk #undef GENTDEF #define GENTDEF( opname ) \ \ typedef void (*PASTECH(opname,_oft)) \ ( \ obj_t* alpha, \ obj_t* a, \ obj_t* beta, \ obj_t* c, \ cntx_t* cntx, \ rntm_t* rntm \ ); GENTDEF( herk ) GENTDEF( syrk ) // trmm, trsm #undef GENTDEF #define GENTDEF( opname ) \ \ typedef void (*PASTECH(opname,_oft)) \ ( \ side_t side, \ obj_t* alpha, \ obj_t* a, \ obj_t* b, \ cntx_t* cntx, \ rntm_t* rntm \ ); GENTDEF( trmm ) GENTDEF( trsm ) #endif blis-0.9.0/frame/3/bli_l3_oft_var.h000066400000000000000000000040131422157504600167460ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_L3_OFT_VAR_H #define BLIS_L3_OFT_VAR_H // // -- Level-3 variant function types ------------------------------------------- // #undef GENTDEF #define GENTDEF( opname ) \ \ typedef void (*PASTECH(opname,_var_oft)) \ ( \ obj_t* a, \ obj_t* b, \ obj_t* c, \ cntx_t* cntx, \ rntm_t* rntm, \ cntl_t* cntl, \ thrinfo_t* thread \ ); GENTDEF( l3 ) #endif blis-0.9.0/frame/3/bli_l3_packab.c000066400000000000000000000064011422157504600165250ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_l3_packa ( obj_t* a, obj_t* b, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ) { obj_t a_local, a_pack; bli_obj_alias_to( a, &a_local ); if ( bli_obj_has_trans( a ) ) { bli_obj_induce_trans( &a_local ); bli_obj_set_onlytrans( BLIS_NO_TRANSPOSE, &a_local ); } // Pack matrix A according to the control tree node. bli_packm_int ( &a_local, &a_pack, cntx, rntm, cntl, thread ); // Proceed with execution using packed matrix A. bli_l3_int ( &BLIS_ONE, &a_pack, b, &BLIS_ONE, c, cntx, rntm, bli_cntl_sub_node( cntl ), bli_thrinfo_sub_node( thread ) ); } // ----------------------------------------------------------------------------- void bli_l3_packb ( obj_t* a, obj_t* b, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ) { obj_t bt_local, bt_pack; // We always pass B^T to bli_l3_packm. bli_obj_alias_to( b, &bt_local ); if ( bli_obj_has_trans( b ) ) { bli_obj_set_onlytrans( BLIS_NO_TRANSPOSE, &bt_local ); } else { bli_obj_induce_trans( &bt_local ); } // Pack matrix B according to the control tree node. bli_packm_int ( &bt_local, &bt_pack, cntx, rntm, cntl, thread ); // Transpose packed object back to B. bli_obj_induce_trans( &bt_pack ); // Proceed with execution using packed matrix B. bli_l3_int ( &BLIS_ONE, a, &bt_pack, &BLIS_ONE, c, cntx, rntm, bli_cntl_sub_node( cntl ), bli_thrinfo_sub_node( thread ) ); } blis-0.9.0/frame/3/bli_l3_packab.h000066400000000000000000000037511422157504600165370ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void bli_l3_packa ( obj_t* a, obj_t* b, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ); void bli_l3_packb ( obj_t* a, obj_t* b, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ); blis-0.9.0/frame/3/bli_l3_prune.c000066400000000000000000000140171422157504600164370ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" /* void bli_l3_prune_unref_mparts_m ( obj_t* a, obj_t* b, obj_t* c, cntl_t* cntl ) { // Query the operation family. opid_t family = bli_cntl_family( cntl ); if ( family == BLIS_GEMM ) return; // No pruning is necessary for gemm. else if ( family == BLIS_GEMMT ) bli_gemmt_prune_unref_mparts_m( a, b, c ); else if ( family == BLIS_TRMM ) bli_trmm_prune_unref_mparts_m( a, b, c ); else if ( family == BLIS_TRSM ) bli_trsm_prune_unref_mparts_m( a, b, c ); } */ #undef GENFRONT #define GENFRONT( dim ) \ \ void PASTEMAC(l3_prune_unref_mparts_,dim) \ ( \ obj_t* a, \ obj_t* b, \ obj_t* c, \ cntl_t* cntl \ ) \ { \ /* Query the operation family. */ \ opid_t family = bli_cntl_family( cntl ); \ \ if ( family == BLIS_GEMM ) return; /* No pruning is necessary for gemm. */ \ else if ( family == BLIS_GEMMT ) PASTEMAC(gemmt_prune_unref_mparts_,dim)( a, b, c ); \ else if ( family == BLIS_TRMM ) PASTEMAC(trmm_prune_unref_mparts_,dim)( a, b, c ); \ else if ( family == BLIS_TRSM ) PASTEMAC(trsm_prune_unref_mparts_,dim)( a, b, c ); \ } GENFRONT( m ) GENFRONT( n ) GENFRONT( k ) // ----------------------------------------------------------------------------- #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC(opname,_prune_unref_mparts_m) \ ( \ obj_t* a, \ obj_t* b, \ obj_t* c \ ) \ { \ /* No pruning is necessary for gemm. */ \ } \ void PASTEMAC(opname,_prune_unref_mparts_n) \ ( \ obj_t* a, \ obj_t* b, \ obj_t* c \ ) \ { \ /* No pruning is necessary for gemm. */ \ } \ void PASTEMAC(opname,_prune_unref_mparts_k) \ ( \ obj_t* a, \ obj_t* b, \ obj_t* c \ ) \ { \ /* No pruning is necessary for gemm. */ \ } GENFRONT( gemm ) // ----------------------------------------------------------------------------- #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC(opname,_prune_unref_mparts_m) \ ( \ obj_t* a, \ obj_t* ah, \ obj_t* c \ ) \ { \ /* Prune any unreferenced part from the subpartition of C (that would be encountered from partitioning in the m dimension) and adjust the subpartition of A accordingly. */ \ bli_prune_unref_mparts( c, BLIS_M, a, BLIS_M ); \ } \ void PASTEMAC(opname,_prune_unref_mparts_n) \ ( \ obj_t* a, \ obj_t* ah, \ obj_t* c \ ) \ { \ /* Prune any unreferenced part from the subpartition of C (that would be encountered from partitioning in the n dimension) and adjust the subpartition of Ah accordingly. */ \ bli_prune_unref_mparts( c, BLIS_N, ah, BLIS_N ); \ } \ void PASTEMAC(opname,_prune_unref_mparts_k) \ ( \ obj_t* a, \ obj_t* ah, \ obj_t* c \ ) \ { \ /* As long as A and Ah are general in structure, no pruning should be for the k dimension. */ \ } GENFRONT( gemmt ) // ----------------------------------------------------------------------------- #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC(opname,_prune_unref_mparts_m) \ ( \ obj_t* a, \ obj_t* b, \ obj_t* c \ ) \ { \ /* Prune any unreferenced part from the subpartition of A (that would be encountered from partitioning in the m dimension) and adjust the subpartition of C accordingly. */ \ bli_prune_unref_mparts( a, BLIS_M, c, BLIS_M ); \ } \ void PASTEMAC(opname,_prune_unref_mparts_n) \ ( \ obj_t* a, \ obj_t* b, \ obj_t* c \ ) \ { \ /* Prune any unreferenced part from the subpartition of B (that would be encountered from partitioning in the n dimension) and adjust the subpartition of C accordingly. */ \ bli_prune_unref_mparts( b, BLIS_N, c, BLIS_N ); \ } \ void PASTEMAC(opname,_prune_unref_mparts_k) \ ( \ obj_t* a, \ obj_t* b, \ obj_t* c \ ) \ { \ /* Prune any unreferenced part from the subpartition of A (that would be encountered from partitioning in the k dimension) and adjust the subpartition of B accordingly. */ \ bli_prune_unref_mparts( a, BLIS_N, b, BLIS_M ); \ \ /* Prune any unreferenced part from the subpartition of B (that would be encountered from partitioning in the k dimension) and adjust the subpartition of A accordingly. */ \ bli_prune_unref_mparts( b, BLIS_M, a, BLIS_N ); \ } GENFRONT( trmm ) GENFRONT( trsm ) blis-0.9.0/frame/3/bli_l3_prune.h000066400000000000000000000045361422157504600164510ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #undef GENPROT #define GENPROT( dim ) \ \ void PASTEMAC(l3_prune_unref_mparts_,dim) \ ( \ obj_t* a, \ obj_t* b, \ obj_t* c, \ cntl_t* cntl \ ); GENPROT( m ) GENPROT( n ) GENPROT( k ) // ----------------------------------------------------------------------------- #undef GENPROT #define GENPROT( opname, dim ) \ \ void PASTEMAC2(opname,_prune_unref_mparts_,dim) \ ( \ obj_t* a, \ obj_t* b, \ obj_t* c \ ); GENPROT( gemm, m ) GENPROT( gemm, n ) GENPROT( gemm, k ) GENPROT( gemmt, m ) GENPROT( gemmt, n ) GENPROT( gemmt, k ) GENPROT( trmm, m ) GENPROT( trmm, n ) GENPROT( trmm, k ) GENPROT( trsm, m ) GENPROT( trsm, n ) GENPROT( trsm, k ) blis-0.9.0/frame/3/bli_l3_schema.c000066400000000000000000000062071422157504600165500ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2021, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_l3_set_schemas ( obj_t* a, obj_t* b, obj_t* c, cntx_t* cntx ) { // Begin with pack schemas for native execution. pack_t schema_a = BLIS_PACKED_ROW_PANELS; pack_t schema_b = BLIS_PACKED_COL_PANELS; // When executing the 1m method, choose the appropriate pack schemas based // on the microkernel preference encoded within the current cntx_t (which // was presumably returned by the gks). if ( bli_cntx_method( cntx ) == BLIS_1M ) { num_t dt = bli_obj_domain( c ) | bli_obj_comp_prec( c ); // Note that bli_cntx_l3_vir_ukr_prefers_cols_dt() will use the real // projection of dt to query the preference of the corresponding native // real-domain microkernel. This is what ultimately determines which // variant of 1m is applicable. if ( bli_cntx_l3_vir_ukr_prefers_cols_dt( dt, BLIS_GEMM_UKR, cntx ) ) { schema_a = BLIS_PACKED_ROW_PANELS_1E; schema_b = BLIS_PACKED_COL_PANELS_1R; } else { schema_a = BLIS_PACKED_ROW_PANELS_1R; schema_b = BLIS_PACKED_COL_PANELS_1E; } } // Embed the schemas into the objects for A and B. This is a sort of hack // for communicating the desired pack schemas to bli_gemm_cntl_create() // (via bli_l3_thread_decorator() and bli_l3_cntl_create_if()). This allows // us to subsequently access the schemas from the control tree, which // hopefully reduces some confusion, particularly in bli_packm_init(). bli_obj_set_pack_schema( schema_a, a ); bli_obj_set_pack_schema( schema_b, b ); } blis-0.9.0/frame/3/bli_l3_schema.h000066400000000000000000000033721422157504600165550ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2021, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void bli_l3_set_schemas ( obj_t* a, obj_t* b, obj_t* c, cntx_t* cntx ); blis-0.9.0/frame/3/bli_l3_sup.c000066400000000000000000000157361422157504600161260ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" err_t bli_gemmsup ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, rntm_t* rntm ) { // Return early if small matrix handling is disabled at configure-time. #ifdef BLIS_DISABLE_SUP_HANDLING return BLIS_FAILURE; #endif // Return early if this is a mixed-datatype computation. if ( bli_obj_dt( c ) != bli_obj_dt( a ) || bli_obj_dt( c ) != bli_obj_dt( b ) || bli_obj_comp_prec( c ) != bli_obj_prec( c ) ) return BLIS_FAILURE; // Obtain a valid (native) context from the gks if necessary. // NOTE: This must be done before calling the _check() function, since // that function assumes the context pointer is valid. if ( cntx == NULL ) cntx = bli_gks_query_cntx(); // Return early if a microkernel preference-induced transposition would // have been performed and shifted the dimensions outside of the space // of sup-handled problems. if ( bli_cntx_l3_vir_ukr_dislikes_storage_of( c, BLIS_GEMM_UKR, cntx ) ) { const num_t dt = bli_obj_dt( c ); const dim_t m = bli_obj_length( c ); const dim_t n = bli_obj_width( c ); const dim_t k = bli_obj_width_after_trans( a ); // Pass in m and n reversed, which simulates a transposition of the // entire operation pursuant to the microkernel storage preference. if ( !bli_cntx_l3_sup_thresh_is_met( dt, n, m, k, cntx ) ) return BLIS_FAILURE; } else // ukr_prefers_storage_of( c, ... ) { const num_t dt = bli_obj_dt( c ); const dim_t m = bli_obj_length( c ); const dim_t n = bli_obj_width( c ); const dim_t k = bli_obj_width_after_trans( a ); if ( !bli_cntx_l3_sup_thresh_is_met( dt, m, n, k, cntx ) ) return BLIS_FAILURE; } // Initialize a local runtime with global settings if necessary. Note // that in the case that a runtime is passed in, we make a local copy. rntm_t rntm_l; if ( rntm == NULL ) { bli_rntm_init_from_global( &rntm_l ); rntm = &rntm_l; } else { rntm_l = *rntm; rntm = &rntm_l; } #if 0 const num_t dt = bli_obj_dt( c ); const dim_t m = bli_obj_length( c ); const dim_t n = bli_obj_width( c ); const dim_t k = bli_obj_width_after_trans( a ); const dim_t tm = bli_cntx_get_l3_sup_thresh_dt( dt, BLIS_MT, cntx ); const dim_t tn = bli_cntx_get_l3_sup_thresh_dt( dt, BLIS_NT, cntx ); const dim_t tk = bli_cntx_get_l3_sup_thresh_dt( dt, BLIS_KT, cntx ); printf( "dims: %d %d %d (threshs: %d %d %d)\n", (int)m, (int)n, (int)k, (int)tm, (int)tn, (int)tk ); #endif // We've now ruled out the following two possibilities: // - the ukernel prefers the operation as-is, and the sup thresholds are // unsatisfied. // - the ukernel prefers a transposed operation, and the sup thresholds are // unsatisfied after taking into account the transposition. // This implies that the sup thresholds (at least one of them) are met. // and the small/unpacked handler should be called. // NOTE: The sup handler is free to enforce a stricter threshold regime // if it so chooses, in which case it can/should return BLIS_FAILURE. // Query the small/unpacked handler from the context and invoke it. gemmsup_oft gemmsup_fp = bli_cntx_get_l3_sup_handler( BLIS_GEMM, cntx ); return gemmsup_fp ( alpha, a, b, beta, c, cntx, rntm ); } err_t bli_gemmtsup ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, rntm_t* rntm ) { // Return early if small matrix handling is disabled at configure-time. #ifdef BLIS_DISABLE_SUP_HANDLING return BLIS_FAILURE; #endif // Return early if this is a mixed-datatype computation. if ( bli_obj_dt( c ) != bli_obj_dt( a ) || bli_obj_dt( c ) != bli_obj_dt( b ) || bli_obj_comp_prec( c ) != bli_obj_prec( c ) ) return BLIS_FAILURE; // Obtain a valid (native) context from the gks if necessary. // NOTE: This must be done before calling the _check() function, since // that function assumes the context pointer is valid. if ( cntx == NULL ) cntx = bli_gks_query_cntx(); // Return early if the problem dimensions exceed their sup thresholds. // Notice that we do not bother to check whether the microkernel // prefers or dislikes the storage of C, since the same check is called // for either way. { const num_t dt = bli_obj_dt( c ); const dim_t m = bli_obj_length( c ); const dim_t k = bli_obj_width_after_trans( a ); if ( !bli_cntx_l3_sup_thresh_is_met( dt, m, m, k, cntx ) ) return BLIS_FAILURE; } // Initialize a local runtime with global settings if necessary. Note // that in the case that a runtime is passed in, we make a local copy. rntm_t rntm_l; if ( rntm == NULL ) { bli_rntm_init_from_global( &rntm_l ); rntm = &rntm_l; } else { rntm_l = *rntm; rntm = &rntm_l; } // We've now ruled out the possibility that the sup thresholds are // unsatisfied. // This implies that the sup thresholds (at least one of them) are met. // and the small/unpacked handler should be called. // NOTE: The sup handler is free to enforce a stricter threshold regime // if it so chooses, in which case it can/should return BLIS_FAILURE. // Query the small/unpacked handler from the context and invoke it. gemmtsup_oft gemmtsup_fp = bli_cntx_get_l3_sup_handler( BLIS_GEMMT, cntx ); return gemmtsup_fp ( alpha, a, b, beta, c, cntx, rntm ); } blis-0.9.0/frame/3/bli_l3_sup.h000066400000000000000000000037441422157504600161270ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2019 - 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ err_t bli_gemmsup ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, rntm_t* rntm ); err_t bli_gemmtsup ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, rntm_t* rntm ); blis-0.9.0/frame/3/bli_l3_sup_ft_ker.h000066400000000000000000000046461422157504600174630ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_L3_SUP_FT_KER_H #define BLIS_L3_SUP_FT_KER_H // // -- Level-3 small/unpacked kernel function types ----------------------------- // // gemmsup #undef GENTDEF #define GENTDEF( ctype, ch, opname, tsuf ) \ \ typedef void (*PASTECH3(ch,opname,_ker,tsuf)) \ ( \ conj_t conja, \ conj_t conjb, \ dim_t m, \ dim_t n, \ dim_t k, \ ctype* restrict alpha, \ ctype* restrict a, inc_t rs_a, inc_t cs_a, \ ctype* restrict b, inc_t rs_b, inc_t cs_b, \ ctype* restrict beta, \ ctype* restrict c, inc_t rs_c, inc_t cs_c, \ auxinfo_t* restrict data, \ cntx_t* restrict cntx \ ); INSERT_GENTDEF( gemmsup ) #endif blis-0.9.0/frame/3/bli_l3_sup_int.c000066400000000000000000000341301422157504600167650ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2019 - 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" err_t bli_gemmsup_int ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, rntm_t* rntm, thrinfo_t* thread ) { #if 0 //bli_gemmsup_ref_var2 //bli_gemmsup_ref_var1 #if 0 bli_gemmsup_ref_var1n #else #endif const stor3_t stor_id = bli_obj_stor3_from_strides( c, a, b ); const bool is_rrr_rrc_rcr_crr = ( stor_id == BLIS_RRR || stor_id == BLIS_RRC || stor_id == BLIS_RCR || stor_id == BLIS_CRR ); if ( is_rrr_rrc_rcr_crr ) { bli_gemmsup_ref_var2m ( BLIS_NO_TRANSPOSE, alpha, a, b, beta, c, stor_id, cntx, rntm ); } else { bli_gemmsup_ref_var2m ( BLIS_TRANSPOSE, alpha, a, b, beta, c, stor_id, cntx, rntm ); } return BLIS_SUCCESS; #endif const stor3_t stor_id = bli_obj_stor3_from_strides( c, a, b ); const bool is_rrr_rrc_rcr_crr = ( stor_id == BLIS_RRR || stor_id == BLIS_RRC || stor_id == BLIS_RCR || stor_id == BLIS_CRR ); const bool is_rcc_crc_ccr_ccc = !is_rrr_rrc_rcr_crr; const num_t dt = bli_obj_dt( c ); const bool row_pref = bli_cntx_l3_sup_ker_prefers_rows_dt( dt, stor_id, cntx ); const bool is_primary = ( row_pref ? is_rrr_rrc_rcr_crr : is_rcc_crc_ccr_ccc ); const dim_t m = bli_obj_length( c ); const dim_t n = bli_obj_width( c ); const dim_t MR = bli_cntx_get_blksz_def_dt( dt, BLIS_MR, cntx ); const dim_t NR = bli_cntx_get_blksz_def_dt( dt, BLIS_NR, cntx ); const bool auto_factor = bli_rntm_auto_factor( rntm ); const dim_t n_threads = bli_rntm_num_threads( rntm ); bool use_bp = TRUE; dim_t jc_new; dim_t ic_new; if ( is_primary ) { // This branch handles: // - rrr rrc rcr crr for row-preferential kernels // - rcc crc ccr ccc for column-preferential kernels const dim_t mu = m / MR; const dim_t nu = n / NR; // Decide which algorithm to use (block-panel var2m or panel-block // var1n) based on the number of micropanels in the m and n dimensions. // Also, recalculate the automatic thread factorization. if ( mu >= nu ) use_bp = TRUE; else /* if ( mu < nu ) */ use_bp = FALSE; // If the parallel thread factorization was automatic, we update it // with a new factorization based on the matrix dimensions in units // of micropanels. if ( auto_factor ) { if ( use_bp ) { // In the block-panel algorithm, the m dimension is parallelized // with ic_nt and the n dimension is parallelized with jc_nt. bli_thread_partition_2x2( n_threads, mu, nu, &ic_new, &jc_new ); } else // if ( !use_bp ) { // In the panel-block algorithm, the m dimension is parallelized // with jc_nt and the n dimension is parallelized with ic_nt. bli_thread_partition_2x2( n_threads, mu, nu, &jc_new, &ic_new ); } // Update the ways of parallelism for the jc and ic loops, and then // update the current thread's root thrinfo_t node according to the // new ways of parallelism value for the jc loop. bli_rntm_set_ways_only( jc_new, 1, ic_new, 1, 1, rntm ); bli_l3_sup_thrinfo_update_root( rntm, thread ); } if ( use_bp ) { #ifdef TRACEVAR if ( bli_thread_am_ochief( thread ) ) printf( "bli_l3_sup_int(): var2m primary\n" ); #endif // block-panel macrokernel; m -> mc, mr; n -> nc, nr: var2() bli_gemmsup_ref_var2m( BLIS_NO_TRANSPOSE, alpha, a, b, beta, c, stor_id, cntx, rntm, thread ); } else // use_pb { #ifdef TRACEVAR if ( bli_thread_am_ochief( thread ) ) printf( "bli_l3_sup_int(): var1n primary\n" ); #endif // panel-block macrokernel; m -> nc*,mr; n -> mc*,nr: var1() bli_gemmsup_ref_var1n( BLIS_NO_TRANSPOSE, alpha, a, b, beta, c, stor_id, cntx, rntm, thread ); // *requires nudging of nc up to be a multiple of mr. } } else { // This branch handles: // - rrr rrc rcr crr for column-preferential kernels // - rcc crc ccr ccc for row-preferential kernels const dim_t mu = n / MR; // the n becomes m after a transposition const dim_t nu = m / NR; // the m becomes n after a transposition // Decide which algorithm to use (block-panel var2m or panel-block // var1n) based on the number of micropanels in the m and n dimensions. // Also, recalculate the automatic thread factorization. if ( mu >= nu ) use_bp = TRUE; else /* if ( mu < nu ) */ use_bp = FALSE; // If the parallel thread factorization was automatic, we update it // with a new factorization based on the matrix dimensions in units // of micropanels. if ( auto_factor ) { if ( use_bp ) { // In the block-panel algorithm, the m dimension is parallelized // with ic_nt and the n dimension is parallelized with jc_nt. bli_thread_partition_2x2( n_threads, mu, nu, &ic_new, &jc_new ); } else // if ( !use_bp ) { // In the panel-block algorithm, the m dimension is parallelized // with jc_nt and the n dimension is parallelized with ic_nt. bli_thread_partition_2x2( n_threads, mu, nu, &jc_new, &ic_new ); } // Update the ways of parallelism for the jc and ic loops, and then // update the current thread's root thrinfo_t node according to the // new ways of parallelism value for the jc loop. bli_rntm_set_ways_only( jc_new, 1, ic_new, 1, 1, rntm ); bli_l3_sup_thrinfo_update_root( rntm, thread ); } if ( use_bp ) { #ifdef TRACEVAR if ( bli_thread_am_ochief( thread ) ) printf( "bli_l3_sup_int(): var2m non-primary\n" ); #endif // panel-block macrokernel; m -> nc, nr; n -> mc, mr: var2() + trans bli_gemmsup_ref_var2m( BLIS_TRANSPOSE, alpha, a, b, beta, c, stor_id, cntx, rntm, thread ); } else // use_pb { #ifdef TRACEVAR if ( bli_thread_am_ochief( thread ) ) printf( "bli_l3_sup_int(): var1n non-primary\n" ); #endif // block-panel macrokernel; m -> mc*,nr; n -> nc*,mr: var1() + trans bli_gemmsup_ref_var1n( BLIS_TRANSPOSE, alpha, a, b, beta, c, stor_id, cntx, rntm, thread ); // *requires nudging of mc up to be a multiple of nr. } } // Return success so that the caller knows that we computed the solution. return BLIS_SUCCESS; } // ----------------------------------------------------------------------------- err_t bli_gemmtsup_int ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, rntm_t* rntm, thrinfo_t* thread ) { const stor3_t stor_id = bli_obj_stor3_from_strides( c, a, b ); const bool is_rrr_rrc_rcr_crr = ( stor_id == BLIS_RRR || stor_id == BLIS_RRC || stor_id == BLIS_RCR || stor_id == BLIS_CRR ); const bool is_rcc_crc_ccr_ccc = !is_rrr_rrc_rcr_crr; const num_t dt = bli_obj_dt( c ); const bool row_pref = bli_cntx_l3_sup_ker_prefers_rows_dt( dt, stor_id, cntx ); const bool is_primary = ( row_pref ? is_rrr_rrc_rcr_crr : is_rcc_crc_ccr_ccc ); const dim_t m = bli_obj_length( c ); const dim_t n = m; const dim_t MR = bli_cntx_get_blksz_def_dt( dt, BLIS_MR, cntx ); const dim_t NR = bli_cntx_get_blksz_def_dt( dt, BLIS_NR, cntx ); const bool auto_factor = bli_rntm_auto_factor( rntm ); const dim_t n_threads = bli_rntm_num_threads( rntm ); bool use_bp = TRUE; dim_t jc_new; dim_t ic_new; if ( is_primary ) { // This branch handles: // - rrr rrc rcr crr for row-preferential kernels // - rcc crc ccr ccc for column-preferential kernels const dim_t mu = m / MR; const dim_t nu = n / NR; // Decide which algorithm to use (block-panel var2m or panel-block // var1n) based on the number of micropanels in the m and n dimensions. // Also, recalculate the automatic thread factorization. if ( mu >= nu ) use_bp = TRUE; else /* if ( mu < nu ) */ use_bp = FALSE; // If the parallel thread factorization was automatic, we update it // with a new factorization based on the matrix dimensions in units // of micropanels. if ( auto_factor ) { if ( use_bp ) { // In the block-panel algorithm, the m dimension is parallelized // with ic_nt and the n dimension is parallelized with jc_nt. bli_thread_partition_2x2( n_threads, mu, nu, &ic_new, &jc_new ); } else // if ( !use_bp ) { // In the panel-block algorithm, the m dimension is parallelized // with jc_nt and the n dimension is parallelized with ic_nt. bli_thread_partition_2x2( n_threads, mu, nu, &jc_new, &ic_new ); } // Update the ways of parallelism for the jc and ic loops, and then // update the current thread's root thrinfo_t node according to the // new ways of parallelism value for the jc loop. bli_rntm_set_ways_only( jc_new, 1, ic_new, 1, 1, rntm ); bli_l3_sup_thrinfo_update_root( rntm, thread ); } if ( use_bp ) { #ifdef TRACEVAR if ( bli_thread_am_ochief( thread ) ) printf( "bli_l3_sup_int(): var2m primary\n" ); #endif // block-panel macrokernel; m -> mc, mr; n -> nc, nr: var2() #if 0 bli_gemmtsup_ref_var2m( BLIS_NO_TRANSPOSE, alpha, a, b, beta, c, stor_id, cntx, rntm, thread ); #endif } else // use_pb { #ifdef TRACEVAR if ( bli_thread_am_ochief( thread ) ) printf( "bli_l3_sup_int(): var1n primary\n" ); #endif // panel-block macrokernel; m -> nc*,mr; n -> mc*,nr: var1() #if 0 bli_gemmtsup_ref_var1n( BLIS_NO_TRANSPOSE, alpha, a, b, beta, c, stor_id, cntx, rntm, thread ); #endif // *requires nudging of nc up to be a multiple of mr. } } else { // This branch handles: // - rrr rrc rcr crr for column-preferential kernels // - rcc crc ccr ccc for row-preferential kernels const dim_t mu = n / MR; // the n becomes m after a transposition const dim_t nu = m / NR; // the m becomes n after a transposition // Decide which algorithm to use (block-panel var2m or panel-block // var1n) based on the number of micropanels in the m and n dimensions. // Also, recalculate the automatic thread factorization. if ( mu >= nu ) use_bp = TRUE; else /* if ( mu < nu ) */ use_bp = FALSE; // If the parallel thread factorization was automatic, we update it // with a new factorization based on the matrix dimensions in units // of micropanels. if ( auto_factor ) { if ( use_bp ) { // In the block-panel algorithm, the m dimension is parallelized // with ic_nt and the n dimension is parallelized with jc_nt. bli_thread_partition_2x2( n_threads, mu, nu, &ic_new, &jc_new ); } else // if ( !use_bp ) { // In the panel-block algorithm, the m dimension is parallelized // with jc_nt and the n dimension is parallelized with ic_nt. bli_thread_partition_2x2( n_threads, mu, nu, &jc_new, &ic_new ); } // Update the ways of parallelism for the jc and ic loops, and then // update the current thread's root thrinfo_t node according to the // new ways of parallelism value for the jc loop. bli_rntm_set_ways_only( jc_new, 1, ic_new, 1, 1, rntm ); bli_l3_sup_thrinfo_update_root( rntm, thread ); } if ( use_bp ) { #ifdef TRACEVAR if ( bli_thread_am_ochief( thread ) ) printf( "bli_l3_sup_int(): var2m non-primary\n" ); #endif // panel-block macrokernel; m -> nc, nr; n -> mc, mr: var2() + trans #if 0 bli_gemmtsup_ref_var2m( BLIS_TRANSPOSE, alpha, a, b, beta, c, stor_id, cntx, rntm, thread ); #endif } else // use_pb { #ifdef TRACEVAR if ( bli_thread_am_ochief( thread ) ) printf( "bli_l3_sup_int(): var1n non-primary\n" ); #endif // block-panel macrokernel; m -> mc*,nr; n -> nc*,mr: var1() + trans #if 0 bli_gemmtsup_ref_var1n( BLIS_TRANSPOSE, alpha, a, b, beta, c, stor_id, cntx, rntm, thread ); #endif // *requires nudging of mc up to be a multiple of nr. } } // Return success so that the caller knows that we computed the solution. return BLIS_SUCCESS; } blis-0.9.0/frame/3/bli_l3_sup_int.h000066400000000000000000000040371422157504600167750ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2019 - 2000, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ err_t bli_gemmsup_int ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, rntm_t* rntm, thrinfo_t* thread ); err_t bli_gemmtsup_int ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, rntm_t* rntm, thrinfo_t* thread ); blis-0.9.0/frame/3/bli_l3_sup_ker.h000066400000000000000000000045031422157504600167620ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Define template prototypes for level-3 kernels on small/unpacked matrices. // // Note: Instead of defining function prototype macro templates and then // instantiating those macros to define the individual function prototypes, // we simply alias the official operations' prototypes as defined in // bli_l3_ker_prot.h. #undef GENTPROT #define GENTPROT GEMMSUP_KER_PROT INSERT_GENTPROT_BASIC0( gemmsup_rv_ukr_name ) INSERT_GENTPROT_BASIC0( gemmsup_rg_ukr_name ) INSERT_GENTPROT_BASIC0( gemmsup_cv_ukr_name ) INSERT_GENTPROT_BASIC0( gemmsup_cg_ukr_name ) INSERT_GENTPROT_BASIC0( gemmsup_rd_ukr_name ) INSERT_GENTPROT_BASIC0( gemmsup_cd_ukr_name ) INSERT_GENTPROT_BASIC0( gemmsup_gx_ukr_name ) blis-0.9.0/frame/3/bli_l3_sup_ker_prot.h000066400000000000000000000044251422157504600200310ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Define template prototypes for level-3 kernels on small/unpacked matrices. // #define GEMMSUP_KER_PROT( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ conj_t conja, \ conj_t conjb, \ dim_t m, \ dim_t n, \ dim_t k, \ ctype* restrict alpha, \ ctype* restrict a, inc_t rs_a, inc_t cs_a, \ ctype* restrict b, inc_t rs_b, inc_t cs_b, \ ctype* restrict beta, \ ctype* restrict c, inc_t rs_c, inc_t cs_c, \ auxinfo_t* restrict data, \ cntx_t* restrict cntx \ ); blis-0.9.0/frame/3/bli_l3_sup_oft.h000066400000000000000000000040411422157504600167660ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2019-20, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_L3_SUP_OFT_H #define BLIS_L3_SUP_OFT_H // // -- Level-3 small/unpacked object function types ----------------------------- // // gemm #undef GENTDEF #define GENTDEF( opname ) \ \ typedef err_t (*PASTECH(opname,_oft)) \ ( \ obj_t* alpha, \ obj_t* a, \ obj_t* b, \ obj_t* beta, \ obj_t* c, \ cntx_t* cntx, \ rntm_t* rntm \ ); GENTDEF( gemmsup ) GENTDEF( gemmtsup ) #endif blis-0.9.0/frame/3/bli_l3_sup_packm_a.c000066400000000000000000000305161422157504600175720ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENTFUNC #define GENTFUNC( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ bool will_pack, \ packbuf_t pack_buf_type, \ dim_t m, \ dim_t k, \ dim_t mr, \ cntx_t* restrict cntx, \ rntm_t* restrict rntm, \ mem_t* restrict mem, \ thrinfo_t* restrict thread \ ) \ { \ /* Inspect whether we are going to be packing matrix A. */ \ if ( will_pack == FALSE ) \ { \ } \ else /* if ( will_pack == TRUE ) */ \ { \ /* NOTE: This "rounding up" of the last upanel is actually optional for the rrc/crc cases, but absolutely necessary for the other cases since we NEED that last micropanel to have the same ldim (cs_p) as the other micropanels. Why? So that millikernels can use the same upanel ldim for all iterations of the ir loop. */ \ const dim_t m_pack = ( m / mr + ( m % mr ? 1 : 0 ) ) * mr; \ const dim_t k_pack = k; \ \ /* Barrier to make sure all threads are caught up and ready to begin the packm stage. */ \ bli_thread_barrier( thread ); \ \ /* Compute the size of the memory block eneded. */ \ siz_t size_needed = sizeof( ctype ) * m_pack * k_pack; \ \ /* Check the mem_t entry provided by the caller. If it is unallocated, then we need to acquire a block from the memory broker. */ \ if ( bli_mem_is_unalloc( mem ) ) \ { \ if ( bli_thread_am_ochief( thread ) ) \ { \ /* Acquire directly to the chief thread's mem_t that was passed in. It needs to be that mem_t struct, and not a local (temporary) mem_t, since there is no barrier until after packing is finished, which could allow a race condition whereby the chief thread exits the current function before the other threads have a chance to copy from it. (A barrier would fix that race condition, but then again, I prefer to keep barriers to a minimum.) */ \ bli_pba_acquire_m \ ( \ rntm, \ size_needed, \ pack_buf_type, \ mem \ ); \ } \ \ /* Broadcast the address of the chief thread's passed-in mem_t to all threads. */ \ mem_t* mem_p = bli_thread_broadcast( thread, mem ); \ \ /* Non-chief threads: Copy the contents of the chief thread's passed-in mem_t to the passed-in mem_t for this thread. (The chief thread already has the mem_t, so it does not need to perform any copy.) */ \ if ( !bli_thread_am_ochief( thread ) ) \ { \ *mem = *mem_p; \ } \ } \ else /* if ( bli_mem_is_alloc( mem ) ) */ \ { \ /* If the mem_t entry provided by the caller does NOT contain a NULL buffer, then a block has already been acquired from the memory broker and cached by the caller. */ \ \ /* As a sanity check, we should make sure that the mem_t object isn't associated with a block that is too small compared to the size of the packed matrix buffer that is needed, according to the value computed above. */ \ siz_t mem_size = bli_mem_size( mem ); \ \ if ( mem_size < size_needed ) \ { \ if ( bli_thread_am_ochief( thread ) ) \ { \ /* The chief thread releases the existing block associated with the mem_t, and then re-acquires a new block, saving the associated mem_t to its passed-in mem_t. (See coment above for why the acquisition needs to be directly to the chief thread's passed-in mem_t and not a local (temporary) mem_t. */ \ bli_pba_release \ ( \ rntm, \ mem \ ); \ bli_pba_acquire_m \ ( \ rntm, \ size_needed, \ pack_buf_type, \ mem \ ); \ } \ \ /* Broadcast the address of the chief thread's passed-in mem_t to all threads. */ \ mem_t* mem_p = bli_thread_broadcast( thread, mem ); \ \ /* Non-chief threads: Copy the contents of the chief thread's passed-in mem_t to the passed-in mem_t for this thread. (The chief thread already has the mem_t, so it does not need to perform any copy.) */ \ if ( !bli_thread_am_ochief( thread ) ) \ { \ *mem = *mem_p; \ } \ } \ else \ { \ /* If the mem_t entry is already allocated and sufficiently large, then we use it as-is. No action is needed. */ \ } \ } \ } \ } INSERT_GENTFUNC_BASIC0( packm_sup_init_mem_a ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ bool did_pack, \ rntm_t* restrict rntm, \ mem_t* restrict mem, \ thrinfo_t* restrict thread \ ) \ { \ /* Inspect whether we previously packed matrix A. */ \ if ( did_pack == FALSE ) \ { \ /* If we didn't pack matrix A, there's nothing to be done. */ \ } \ else /* if ( did_pack == TRUE ) */ \ { \ if ( thread != NULL ) \ if ( bli_thread_am_ochief( thread ) ) \ { \ /* Check the mem_t entry provided by the caller. Only proceed if it is allocated, which it should be. */ \ if ( bli_mem_is_alloc( mem ) ) \ { \ bli_pba_release \ ( \ rntm, \ mem \ ); \ } \ } \ } \ } INSERT_GENTFUNC_BASIC0( packm_sup_finalize_mem_a ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ bool will_pack, \ stor3_t stor_id, \ pack_t* restrict schema, \ dim_t m, \ dim_t k, \ dim_t mr, \ dim_t* restrict m_max, \ dim_t* restrict k_max, \ ctype* x, inc_t rs_x, inc_t cs_x, \ ctype** p, inc_t* restrict rs_p, inc_t* restrict cs_p, \ dim_t* restrict pd_p, inc_t* restrict ps_p, \ cntx_t* restrict cntx, \ mem_t* restrict mem, \ thrinfo_t* restrict thread \ ) \ { \ /* Inspect whether we are going to be packing matrix A. */ \ if ( will_pack == FALSE ) \ { \ *m_max = m; \ *k_max = k; \ \ /* Set the parameters for use with no packing of A (ie: using the source matrix A directly). */ \ { \ /* Use the strides of the source matrix as the final values. */ \ *rs_p = rs_x; \ *cs_p = cs_x; \ \ *pd_p = mr; \ *ps_p = mr * rs_x; \ \ /* Set the schema to "not packed" to indicate that packing will be skipped. */ \ *schema = BLIS_NOT_PACKED; \ } \ \ /* Since we won't be packing, simply update the buffer address provided by the caller to point to source matrix. */ \ *p = x; \ } \ else /* if ( will_pack == TRUE ) */ \ { \ /* NOTE: This is "rounding up" of the last upanel is actually optional for the rrc/crc cases, but absolutely necessary for the other cases since we NEED that last micropanel to have the same ldim (cs_p) as the other micropanels. Why? So that millikernels can use the same upanel ldim for all iterations of the ir loop. */ \ *m_max = ( m / mr + ( m % mr ? 1 : 0 ) ) * mr; \ *k_max = k; \ \ /* Determine the dimensions and strides for the packed matrix A. */ \ if ( stor_id == BLIS_RRC || \ stor_id == BLIS_CRC ) \ { \ /* stor3_t id values _RRC and _CRC: pack A to plain row storage. */ \ *rs_p = k; \ *cs_p = 1; \ \ *pd_p = mr; \ *ps_p = mr * k; \ \ /* Set the schema to "row packed" to indicate packing to plain row storage. */ \ *schema = BLIS_PACKED_ROWS; \ } \ else \ { \ /* All other stor3_t ids: pack A to column-stored row-panels. */ \ *rs_p = 1; \ *cs_p = mr; \ \ *pd_p = mr; \ *ps_p = mr * k; \ \ /* Set the schema to "packed row panels" to indicate packing to conventional column-stored row panels. */ \ *schema = BLIS_PACKED_ROW_PANELS; \ } \ \ /* Set the buffer address provided by the caller to point to the memory associated with the mem_t entry acquired from the memory broker. */ \ *p = bli_mem_buffer( mem ); \ } \ } INSERT_GENTFUNC_BASIC0( packm_sup_init_a ) // // Define BLAS-like interfaces to the variant chooser. // #undef GENTFUNC #define GENTFUNC( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ bool will_pack, \ packbuf_t pack_buf_type, \ stor3_t stor_id, \ trans_t transc, \ dim_t m_alloc, \ dim_t k_alloc, \ dim_t m, \ dim_t k, \ dim_t mr, \ ctype* restrict kappa, \ ctype* restrict a, inc_t rs_a, inc_t cs_a, \ ctype** restrict p, inc_t* restrict rs_p, inc_t* restrict cs_p, \ inc_t* restrict ps_p, \ cntx_t* restrict cntx, \ rntm_t* restrict rntm, \ mem_t* restrict mem, \ thrinfo_t* restrict thread \ ) \ { \ pack_t schema; \ dim_t m_max; \ dim_t k_max; \ dim_t pd_p; \ \ /* Prepare the packing destination buffer. If packing is not requested, this function will reduce to a no-op. */ \ PASTEMAC(ch,packm_sup_init_mem_a) \ ( \ will_pack, \ pack_buf_type, \ m_alloc, k_alloc, mr, \ cntx, \ rntm, \ mem, \ thread \ ); \ \ /* Determine the packing buffer and related parameters for matrix A. If A will not be packed, then a_use will be set to point to a and the _a_use strides will be set accordingly. */ \ PASTEMAC(ch,packm_sup_init_a) \ ( \ will_pack, \ stor_id, \ &schema, \ m, k, mr, \ &m_max, &k_max, \ a, rs_a, cs_a, \ p, rs_p, cs_p, \ &pd_p, ps_p, \ cntx, \ mem, \ thread \ ); \ \ /* Inspect whether we are going to be packing matrix A. */ \ if ( will_pack == FALSE ) \ { \ /* If we aren't going to pack matrix A, then there's nothing to do. */ \ \ /* printf( "blis_ packm_sup_a: not packing A.\n" ); \ */ \ } \ else /* if ( will_pack == TRUE ) */ \ { \ if ( schema == BLIS_PACKED_ROWS ) \ { \ /* printf( "blis_ packm_sup_a: packing A to rows.\n" ); \ */ \ \ /* For plain packing by rows, use var2. */ \ PASTEMAC(ch,packm_sup_var2) \ ( \ transc, \ schema, \ m, \ k, \ kappa, \ a, rs_a, cs_a, \ *p, *rs_p, *cs_p, \ cntx, \ thread \ ); \ } \ else /* if ( schema == BLIS_PACKED_ROW_PANELS ) */ \ { \ /* printf( "blis_ packm_sup_a: packing A to row panels.\n" ); \ */ \ \ /* For packing to column-stored row panels, use var1. */ \ PASTEMAC(ch,packm_sup_var1) \ ( \ transc, \ schema, \ m, \ k, \ m_max, \ k_max, \ kappa, \ a, rs_a, cs_a, \ *p, *rs_p, *cs_p, \ pd_p, *ps_p, \ cntx, \ thread \ ); \ } \ \ /* Barrier so that packing is done before computation. */ \ bli_thread_barrier( thread ); \ } \ } INSERT_GENTFUNC_BASIC0( packm_sup_a ) blis-0.9.0/frame/3/bli_l3_sup_packm_a.h000066400000000000000000000077051422157504600176030ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ bool will_pack, \ packbuf_t pack_buf_type, \ dim_t m, \ dim_t k, \ dim_t mr, \ cntx_t* restrict cntx, \ rntm_t* restrict rntm, \ mem_t* restrict mem, \ thrinfo_t* restrict thread \ ); \ INSERT_GENTPROT_BASIC0( packm_sup_init_mem_a ) #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ bool did_pack, \ rntm_t* restrict rntm, \ mem_t* restrict mem, \ thrinfo_t* restrict thread \ ); \ INSERT_GENTPROT_BASIC0( packm_sup_finalize_mem_a ) #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ bool will_pack, \ stor3_t stor_id, \ pack_t* restrict schema, \ dim_t m, \ dim_t k, \ dim_t mr, \ dim_t* restrict m_max, \ dim_t* restrict k_max, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype** p, inc_t* restrict rs_p, inc_t* restrict cs_p, \ dim_t* restrict pd_p, inc_t* restrict ps_p, \ cntx_t* restrict cntx, \ mem_t* restrict mem, \ thrinfo_t* restrict thread \ ); \ INSERT_GENTPROT_BASIC0( packm_sup_init_a ) #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ bool will_pack, \ packbuf_t pack_buf_type, \ stor3_t stor_id, \ trans_t transc, \ dim_t m_alloc, \ dim_t k_alloc, \ dim_t m, \ dim_t k, \ dim_t mr, \ ctype* restrict kappa, \ ctype* restrict a, inc_t rs_a, inc_t cs_a, \ ctype** restrict p, inc_t* restrict rs_p, inc_t* restrict cs_p, \ inc_t* restrict ps_p, \ cntx_t* restrict cntx, \ rntm_t* restrict rntm, \ mem_t* restrict mem, \ thrinfo_t* restrict thread \ ); \ INSERT_GENTPROT_BASIC0( packm_sup_a ) blis-0.9.0/frame/3/bli_l3_sup_packm_b.c000066400000000000000000000305431422157504600175730ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENTFUNC #define GENTFUNC( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ bool will_pack, \ packbuf_t pack_buf_type, \ dim_t k, \ dim_t n, \ dim_t nr, \ cntx_t* restrict cntx, \ rntm_t* restrict rntm, \ mem_t* restrict mem, \ thrinfo_t* restrict thread \ ) \ { \ /* Inspect whether we are going to be packing matrix B. */ \ if ( will_pack == FALSE ) \ { \ } \ else /* if ( will_pack == TRUE ) */ \ { \ /* NOTE: This "rounding up" of the last upanel is actually optional for the rrc/crc cases, but absolutely necessary for the other cases since we NEED that last micropanel to have the same ldim (cs_p) as the other micropanels. Why? So that millikernels can use the same upanel ldim for all iterations of the ir loop. */ \ const dim_t k_pack = k; \ const dim_t n_pack = ( n / nr + ( n % nr ? 1 : 0 ) ) * nr; \ \ /* Barrier to make sure all threads are caught up and ready to begin the packm stage. */ \ bli_thread_barrier( thread ); \ \ /* Compute the size of the memory block eneded. */ \ siz_t size_needed = sizeof( ctype ) * k_pack * n_pack; \ \ /* Check the mem_t entry provided by the caller. If it is unallocated, then we need to acquire a block from the memory broker. */ \ if ( bli_mem_is_unalloc( mem ) ) \ { \ if ( bli_thread_am_ochief( thread ) ) \ { \ /* Acquire directly to the chief thread's mem_t that was passed in. It needs to be that mem_t struct, and not a local (temporary) mem_t, since there is no barrier until after packing is finished, which could allow a race condition whereby the chief thread exits the current function before the other threads have a chance to copy from it. (A barrier would fix that race condition, but then again, I prefer to keep barriers to a minimum.) */ \ bli_pba_acquire_m \ ( \ rntm, \ size_needed, \ pack_buf_type, \ mem \ ); \ } \ \ /* Broadcast the address of the chief thread's passed-in mem_t to all threads. */ \ mem_t* mem_p = bli_thread_broadcast( thread, mem ); \ \ /* Non-chief threads: Copy the contents of the chief thread's passed-in mem_t to the passed-in mem_t for this thread. (The chief thread already has the mem_t, so it does not need to perform any copy.) */ \ if ( !bli_thread_am_ochief( thread ) ) \ { \ *mem = *mem_p; \ } \ } \ else /* if ( bli_mem_is_alloc( mem ) ) */ \ { \ /* If the mem_t entry provided by the caller does NOT contain a NULL buffer, then a block has already been acquired from the memory broker and cached by the caller. */ \ \ /* As a sanity check, we should make sure that the mem_t object isn't associated with a block that is too small compared to the size of the packed matrix buffer that is needed, according to the value computed above. */ \ siz_t mem_size = bli_mem_size( mem ); \ \ if ( mem_size < size_needed ) \ { \ if ( bli_thread_am_ochief( thread ) ) \ { \ /* The chief thread releases the existing block associated with the mem_t, and then re-acquires a new block, saving the associated mem_t to its passed-in mem_t. (See coment above for why the acquisition needs to be directly to the chief thread's passed-in mem_t and not a local (temporary) mem_t. */ \ bli_pba_release \ ( \ rntm, \ mem \ ); \ bli_pba_acquire_m \ ( \ rntm, \ size_needed, \ pack_buf_type, \ mem \ ); \ } \ \ /* Broadcast the address of the chief thread's passed-in mem_t to all threads. */ \ mem_t* mem_p = bli_thread_broadcast( thread, mem ); \ \ /* Non-chief threads: Copy the contents of the chief thread's passed-in mem_t to the passed-in mem_t for this thread. (The chief thread already has the mem_t, so it does not need to perform any copy.) */ \ if ( !bli_thread_am_ochief( thread ) ) \ { \ *mem = *mem_p; \ } \ } \ else \ { \ /* If the mem_t entry is already allocated and sufficiently large, then we use it as-is. No action is needed. */ \ } \ } \ } \ } INSERT_GENTFUNC_BASIC0( packm_sup_init_mem_b ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ bool did_pack, \ rntm_t* restrict rntm, \ mem_t* restrict mem, \ thrinfo_t* restrict thread \ ) \ { \ /* Inspect whether we previously packed matrix A. */ \ if ( did_pack == FALSE ) \ { \ /* If we didn't pack matrix A, there's nothing to be done. */ \ } \ else /* if ( did_pack == TRUE ) */ \ { \ if ( thread != NULL ) \ if ( bli_thread_am_ochief( thread ) ) \ { \ /* Check the mem_t entry provided by the caller. Only proceed if it is allocated, which it should be. */ \ if ( bli_mem_is_alloc( mem ) ) \ { \ bli_pba_release \ ( \ rntm, \ mem \ ); \ } \ } \ } \ } INSERT_GENTFUNC_BASIC0( packm_sup_finalize_mem_b ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ bool will_pack, \ stor3_t stor_id, \ pack_t* restrict schema, \ dim_t k, \ dim_t n, \ dim_t nr, \ dim_t* restrict k_max, \ dim_t* restrict n_max, \ ctype* x, inc_t rs_x, inc_t cs_x, \ ctype** p, inc_t* restrict rs_p, inc_t* restrict cs_p, \ dim_t* restrict pd_p, inc_t* restrict ps_p, \ cntx_t* restrict cntx, \ mem_t* restrict mem, \ thrinfo_t* restrict thread \ ) \ { \ /* Inspect whether we are going to be packing matrix B. */ \ if ( will_pack == FALSE ) \ { \ *k_max = k; \ *n_max = n; \ \ /* Set the parameters for use with no packing of B (ie: using the source matrix B directly). */ \ { \ /* Use the strides of the source matrix as the final values. */ \ *rs_p = rs_x; \ *cs_p = cs_x; \ \ *pd_p = nr; \ *ps_p = nr * cs_x; \ \ /* Set the schema to "not packed" to indicate that packing will be skipped. */ \ *schema = BLIS_NOT_PACKED; \ } \ \ /* Since we won't be packing, simply update the buffer address provided by the caller to point to source matrix. */ \ *p = x; \ } \ else /* if ( will_pack == TRUE ) */ \ { \ /* NOTE: This is "rounding up" of the last upanel is actually optional for the rrc/crc cases, but absolutely necessary for the other cases since we NEED that last micropanel to have the same ldim (cs_p) as the other micropanels. Why? So that millikernels can use the same upanel ldim for all iterations of the ir loop. */ \ *k_max = k; \ *n_max = ( n / nr + ( n % nr ? 1 : 0 ) ) * nr; \ \ /* Determine the dimensions and strides for the packed matrix B. */ \ if ( stor_id == BLIS_RRC || \ stor_id == BLIS_CRC ) \ { \ /* stor3_t id values _RRC and _CRC: pack B to plain row storage. */ \ *rs_p = 1; \ *cs_p = k; \ \ *pd_p = nr; \ *ps_p = k * nr; \ \ /* Set the schema to "column packed" to indicate packing to plain column storage. */ \ *schema = BLIS_PACKED_COLUMNS; \ } \ else \ { \ /* All other stor3_t ids: pack B to row-stored column-panels. */ \ *rs_p = nr; \ *cs_p = 1; \ \ *pd_p = nr; \ *ps_p = k * nr; \ \ /* Set the schema to "packed column panels" to indicate packing to conventional row-stored column panels. */ \ *schema = BLIS_PACKED_COL_PANELS; \ } \ \ /* Set the buffer address provided by the caller to point to the memory associated with the mem_t entry acquired from the memory broker. */ \ *p = bli_mem_buffer( mem ); \ } \ } INSERT_GENTFUNC_BASIC0( packm_sup_init_b ) // // Define BLAS-like interfaces to the variant chooser. // #undef GENTFUNC #define GENTFUNC( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ bool will_pack, \ packbuf_t pack_buf_type, \ stor3_t stor_id, \ trans_t transc, \ dim_t k_alloc, \ dim_t n_alloc, \ dim_t k, \ dim_t n, \ dim_t nr, \ ctype* restrict kappa, \ ctype* restrict b, inc_t rs_b, inc_t cs_b, \ ctype** restrict p, inc_t* restrict rs_p, inc_t* restrict cs_p, \ inc_t* restrict ps_p, \ cntx_t* restrict cntx, \ rntm_t* restrict rntm, \ mem_t* restrict mem, \ thrinfo_t* restrict thread \ ) \ { \ pack_t schema; \ dim_t k_max; \ dim_t n_max; \ dim_t pd_p; \ \ /* Prepare the packing destination buffer. If packing is not requested, this function will reduce to a no-op. */ \ PASTEMAC(ch,packm_sup_init_mem_b) \ ( \ will_pack, \ pack_buf_type, \ k_alloc, n_alloc, nr, \ cntx, \ rntm, \ mem, \ thread \ ); \ \ /* Determine the packing buffer and related parameters for matrix B. If B will not be packed, then b_use will be set to point to b and the _b_use strides will be set accordingly. */ \ PASTEMAC(ch,packm_sup_init_b) \ ( \ will_pack, \ stor_id, \ &schema, \ k, n, nr, \ &k_max, &n_max, \ b, rs_b, cs_b, \ p, rs_p, cs_p, \ &pd_p, ps_p, \ cntx, \ mem, \ thread \ ); \ \ /* Inspect whether we are going to be packing matrix B. */ \ if ( will_pack == FALSE ) \ { \ /* If we aren't going to pack matrix B, then there's nothing to do. */ \ \ /* printf( "blis_ packm_sup_b: not packing B.\n" ); \ */ \ } \ else /* if ( will_pack == TRUE ) */ \ { \ if ( schema == BLIS_PACKED_COLUMNS ) \ { \ /* printf( "blis_ packm_sup_b: packing B to columns.\n" ); \ */ \ \ /* For plain packing by columns, use var2. */ \ PASTEMAC(ch,packm_sup_var2) \ ( \ transc, \ schema, \ k, \ n, \ kappa, \ b, rs_b, cs_b, \ *p, *rs_p, *cs_p, \ cntx, \ thread \ ); \ } \ else /* if ( schema == BLIS_PACKED_COL_PANELS ) */ \ { \ /* printf( "blis_ packm_sup_b: packing B to col panels.\n" ); \ */ \ \ /* For packing to row-stored column panels, use var1. */ \ PASTEMAC(ch,packm_sup_var1) \ ( \ transc, \ schema, \ k, \ n, \ k_max, \ n_max, \ kappa, \ b, rs_b, cs_b, \ *p, *rs_p, *cs_p, \ pd_p, *ps_p, \ cntx, \ thread \ ); \ } \ \ /* Barrier so that packing is done before computation. */ \ bli_thread_barrier( thread ); \ } \ } INSERT_GENTFUNC_BASIC0( packm_sup_b ) blis-0.9.0/frame/3/bli_l3_sup_packm_b.h000066400000000000000000000077051422157504600176040ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ bool will_pack, \ packbuf_t pack_buf_type, \ dim_t k, \ dim_t n, \ dim_t nr, \ cntx_t* restrict cntx, \ rntm_t* restrict rntm, \ mem_t* restrict mem, \ thrinfo_t* restrict thread \ ); \ INSERT_GENTPROT_BASIC0( packm_sup_init_mem_b ) #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ bool did_pack, \ rntm_t* restrict rntm, \ mem_t* restrict mem, \ thrinfo_t* restrict thread \ ); \ INSERT_GENTPROT_BASIC0( packm_sup_finalize_mem_b ) #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ bool will_pack, \ stor3_t stor_id, \ pack_t* restrict schema, \ dim_t k, \ dim_t n, \ dim_t nr, \ dim_t* restrict k_max, \ dim_t* restrict n_max, \ ctype* b, inc_t rs_b, inc_t cs_b, \ ctype** p, inc_t* restrict rs_p, inc_t* restrict cs_p, \ dim_t* restrict pd_p, inc_t* restrict ps_p, \ cntx_t* restrict cntx, \ mem_t* restrict mem, \ thrinfo_t* restrict thread \ ); \ INSERT_GENTPROT_BASIC0( packm_sup_init_b ) #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ bool will_pack, \ packbuf_t pack_buf_type, \ stor3_t stor_id, \ trans_t transc, \ dim_t k_alloc, \ dim_t n_alloc, \ dim_t k, \ dim_t n, \ dim_t nr, \ ctype* restrict kappa, \ ctype* restrict b, inc_t rs_b, inc_t cs_b, \ ctype** restrict p, inc_t* restrict rs_p, inc_t* restrict cs_p, \ inc_t* restrict ps_p, \ cntx_t* restrict cntx, \ rntm_t* restrict rntm, \ mem_t* restrict mem, \ thrinfo_t* restrict thread \ ); \ INSERT_GENTPROT_BASIC0( packm_sup_b ) blis-0.9.0/frame/3/bli_l3_sup_packm_var.c000066400000000000000000000356261422157504600201510ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // Define BLAS-like interfaces to the variants. // #undef GENTFUNCR #define GENTFUNCR( ctype, ctype_r, ch, chr, opname, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ trans_t transc, \ pack_t schema, \ dim_t m, \ dim_t n, \ dim_t m_max, \ dim_t n_max, \ ctype* restrict kappa, \ ctype* restrict c, inc_t rs_c, inc_t cs_c, \ ctype* restrict p, inc_t rs_p, inc_t cs_p, \ dim_t pd_p, inc_t ps_p, \ cntx_t* restrict cntx, \ thrinfo_t* restrict thread \ ) \ { \ ctype* restrict kappa_cast = kappa; \ ctype* restrict c_cast = c; \ ctype* restrict p_cast = p; \ \ dim_t iter_dim; \ dim_t n_iter; \ dim_t it, ic; \ dim_t ic0; \ doff_t ic_inc; \ dim_t panel_len_full; \ dim_t panel_len_i; \ dim_t panel_len_max; \ dim_t panel_len_max_i; \ dim_t panel_dim_i; \ dim_t panel_dim_max; \ inc_t vs_c; \ inc_t ldc; \ inc_t ldp, p_inc; \ conj_t conjc; \ \ \ /* Extract the conjugation bit from the transposition argument. */ \ conjc = bli_extract_conj( transc ); \ \ /* If c needs a transposition, induce it so that we can more simply express the remaining parameters and code. */ \ if ( bli_does_trans( transc ) ) \ { \ bli_swap_incs( &rs_c, &cs_c ); \ bli_toggle_trans( &transc ); \ } \ \ /* Create flags to incidate row or column storage. Note that the schema bit that encodes row or column is describing the form of micro-panel, not the storage in the micro-panel. Hence the mismatch in "row" and "column" semantics. */ \ bool row_stored = bli_is_col_packed( schema ); \ /*bool col_stored = bli_is_row_packed( schema );*/ \ \ /* If the row storage flag indicates row storage, then we are packing to column panels; otherwise, if the strides indicate column storage, we are packing to row panels. */ \ if ( row_stored ) \ { \ /* Prepare to pack to row-stored column panels. */ \ iter_dim = n; \ panel_len_full = m; \ panel_len_max = m_max; \ panel_dim_max = pd_p; \ vs_c = cs_c; \ ldc = rs_c; \ ldp = rs_p; \ } \ else /* if ( col_stored ) */ \ { \ /* Prepare to pack to column-stored row panels. */ \ iter_dim = m; \ panel_len_full = n; \ panel_len_max = n_max; \ panel_dim_max = pd_p; \ vs_c = rs_c; \ ldc = cs_c; \ ldp = cs_p; \ } \ \ /* Compute the total number of iterations we'll need. */ \ n_iter = iter_dim / panel_dim_max + ( iter_dim % panel_dim_max ? 1 : 0 ); \ \ /* Set the initial values and increments for indices related to C and P based on whether reverse iteration was requested. */ \ { \ ic0 = 0; \ ic_inc = panel_dim_max; \ } \ \ ctype* restrict p_begin = p_cast; \ \ /* Query the number of threads and thread ids from the current thread's packm thrinfo_t node. */ \ const dim_t nt = bli_thread_n_way( thread ); \ const dim_t tid = bli_thread_work_id( thread ); \ \ /* Suppress warnings in case tid isn't used (ie: as in slab partitioning). */ \ ( void )nt; \ ( void )tid; \ \ dim_t it_start, it_end, it_inc; \ \ /* Determine the thread range and increment using the current thread's packm thrinfo_t node. NOTE: The definition of bli_thread_range_jrir() will depend on whether slab or round-robin partitioning was requested at configure-time. */ \ bli_thread_range_jrir( thread, n_iter, 1, FALSE, &it_start, &it_end, &it_inc ); \ \ /* Iterate over every logical micropanel in the source matrix. */ \ for ( ic = ic0, it = 0; it < n_iter; \ ic += ic_inc, it += 1 ) \ { \ panel_dim_i = bli_min( panel_dim_max, iter_dim - ic ); \ \ ctype* restrict c_begin = c_cast + (ic )*vs_c; \ \ ctype* restrict c_use = c_begin; \ ctype* restrict p_use = p_begin; \ \ { \ panel_len_i = panel_len_full; \ panel_len_max_i = panel_len_max; \ \ /* The definition of bli_packm_my_iter() will depend on whether slab or round-robin partitioning was requested at configure-time. */ \ if ( bli_packm_my_iter( it, it_start, it_end, tid, nt ) ) \ { \ PASTEMAC(ch,packm_cxk) \ ( \ conjc, \ schema, \ panel_dim_i, \ panel_dim_max, \ panel_len_i, \ panel_len_max_i, \ kappa_cast, \ c_use, vs_c, ldc, \ p_use, ldp, \ cntx \ ); \ } \ \ /* NOTE: This value is equivalent to ps_p. */ \ p_inc = ps_p; \ } \ \ p_begin += p_inc; \ \ /* if ( row_stored ) \ PASTEMAC(ch,fprintm)( stdout, "packm_sup_var1: b packed", panel_len_max, panel_dim_max, \ p_use, rs_p, cs_p, "%5.2f", "" ); \ if ( !row_stored ) \ PASTEMAC(ch,fprintm)( stdout, "packm_sup_var1: a packed", panel_dim_max, panel_len_max, \ p_use, rs_p, cs_p, "%5.2f", "" ); \ */ \ } \ \ } INSERT_GENTFUNCR_BASIC( packm, packm_sup_var1 ) /* if ( row_stored ) \ PASTEMAC(ch,fprintm)( stdout, "packm_var2: b", m, n, \ c_cast, rs_c, cs_c, "%4.1f", "" ); \ if ( col_stored ) \ PASTEMAC(ch,fprintm)( stdout, "packm_var2: a", m, n, \ c_cast, rs_c, cs_c, "%4.1f", "" ); \ */ /* if ( row_stored ) \ PASTEMAC(ch,fprintm)( stdout, "packm_blk_var1: b packed", *m_panel_max, *n_panel_max, \ p_use, rs_p, cs_p, "%5.2f", "" ); \ else \ PASTEMAC(ch,fprintm)( stdout, "packm_blk_var1: a packed", *m_panel_max, *n_panel_max, \ p_use, rs_p, cs_p, "%5.2f", "" ); \ */ \ \ /* if ( col_stored ) { \ if ( bli_thread_work_id( thread ) == 0 ) \ { \ printf( "packm_blk_var1: thread %lu (a = %p, ap = %p)\n", bli_thread_work_id( thread ), c_use, p_use ); \ fflush( stdout ); \ PASTEMAC(ch,fprintm)( stdout, "packm_blk_var1: a", *m_panel_use, *n_panel_use, \ ( ctype* )c_use, rs_c, cs_c, "%4.1f", "" ); \ PASTEMAC(ch,fprintm)( stdout, "packm_blk_var1: ap", *m_panel_max, *n_panel_max, \ ( ctype* )p_use, rs_p, cs_p, "%4.1f", "" ); \ fflush( stdout ); \ } \ bli_thread_barrier( thread ); \ if ( bli_thread_work_id( thread ) == 1 ) \ { \ printf( "packm_blk_var1: thread %lu (a = %p, ap = %p)\n", bli_thread_work_id( thread ), c_use, p_use ); \ fflush( stdout ); \ PASTEMAC(ch,fprintm)( stdout, "packm_blk_var1: a", *m_panel_use, *n_panel_use, \ ( ctype* )c_use, rs_c, cs_c, "%4.1f", "" ); \ PASTEMAC(ch,fprintm)( stdout, "packm_blk_var1: ap", *m_panel_max, *n_panel_max, \ ( ctype* )p_use, rs_p, cs_p, "%4.1f", "" ); \ fflush( stdout ); \ } \ bli_thread_barrier( thread ); \ } \ else { \ if ( bli_thread_work_id( thread ) == 0 ) \ { \ printf( "packm_blk_var1: thread %lu (b = %p, bp = %p)\n", bli_thread_work_id( thread ), c_use, p_use ); \ fflush( stdout ); \ PASTEMAC(ch,fprintm)( stdout, "packm_blk_var1: b", *m_panel_use, *n_panel_use, \ ( ctype* )c_use, rs_c, cs_c, "%4.1f", "" ); \ PASTEMAC(ch,fprintm)( stdout, "packm_blk_var1: bp", *m_panel_max, *n_panel_max, \ ( ctype* )p_use, rs_p, cs_p, "%4.1f", "" ); \ fflush( stdout ); \ } \ bli_thread_barrier( thread ); \ if ( bli_thread_work_id( thread ) == 1 ) \ { \ printf( "packm_blk_var1: thread %lu (b = %p, bp = %p)\n", bli_thread_work_id( thread ), c_use, p_use ); \ fflush( stdout ); \ PASTEMAC(ch,fprintm)( stdout, "packm_blk_var1: b", *m_panel_use, *n_panel_use, \ ( ctype* )c_use, rs_c, cs_c, "%4.1f", "" ); \ PASTEMAC(ch,fprintm)( stdout, "packm_blk_var1: bp", *m_panel_max, *n_panel_max, \ ( ctype* )p_use, rs_p, cs_p, "%4.1f", "" ); \ fflush( stdout ); \ } \ bli_thread_barrier( thread ); \ } \ */ /* PASTEMAC(chr,fprintm)( stdout, "packm_var2: bp_rpi", *m_panel_max, *n_panel_max, \ ( ctype_r* )p_use, rs_p, cs_p, "%4.1f", "" ); \ */ /* if ( row_stored ) { \ PASTEMAC(chr,fprintm)( stdout, "packm_var2: b_r", *m_panel_max, *n_panel_max, \ ( ctype_r* )c_use, 2*rs_c, 2*cs_c, "%4.1f", "" ); \ PASTEMAC(chr,fprintm)( stdout, "packm_var2: b_i", *m_panel_max, *n_panel_max, \ (( ctype_r* )c_use)+rs_c, 2*rs_c, 2*cs_c, "%4.1f", "" ); \ PASTEMAC(chr,fprintm)( stdout, "packm_var2: bp_r", *m_panel_max, *n_panel_max, \ ( ctype_r* )p_use, rs_p, cs_p, "%4.1f", "" ); \ inc_t is_b = rs_p * *m_panel_max; \ PASTEMAC(chr,fprintm)( stdout, "packm_var2: bp_i", *m_panel_max, *n_panel_max, \ ( ctype_r* )p_use + is_b, rs_p, cs_p, "%4.1f", "" ); \ } \ */ /* if ( col_stored ) { \ PASTEMAC(chr,fprintm)( stdout, "packm_var2: a_r", *m_panel_max, *n_panel_max, \ ( ctype_r* )c_use, 2*rs_c, 2*cs_c, "%4.1f", "" ); \ PASTEMAC(chr,fprintm)( stdout, "packm_var2: a_i", *m_panel_max, *n_panel_max, \ (( ctype_r* )c_use)+rs_c, 2*rs_c, 2*cs_c, "%4.1f", "" ); \ PASTEMAC(chr,fprintm)( stdout, "packm_var2: ap_r", *m_panel_max, *n_panel_max, \ ( ctype_r* )p_use, rs_p, cs_p, "%4.1f", "" ); \ PASTEMAC(chr,fprintm)( stdout, "packm_var2: ap_i", *m_panel_max, *n_panel_max, \ ( ctype_r* )p_use + p_inc, rs_p, cs_p, "%4.1f", "" ); \ } \ */ #undef GENTFUNCR #define GENTFUNCR( ctype, ctype_r, ch, chr, opname, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ trans_t transc, \ pack_t schema, \ dim_t m, \ dim_t n, \ ctype* restrict kappa, \ ctype* restrict c, inc_t rs_c, inc_t cs_c, \ ctype* restrict p, inc_t rs_p, inc_t cs_p, \ cntx_t* restrict cntx, \ thrinfo_t* restrict thread \ ) \ { \ ctype* restrict kappa_cast = kappa; \ ctype* restrict c_cast = c; \ ctype* restrict p_cast = p; \ \ dim_t iter_dim; \ dim_t n_iter; \ dim_t it; \ dim_t vector_len; \ inc_t incc, ldc; \ inc_t incp, ldp; \ conj_t conjc; \ \ \ /* Extract the conjugation bit from the transposition argument. */ \ conjc = bli_extract_conj( transc ); \ \ /* If c needs a transposition, induce it so that we can more simply express the remaining parameters and code. */ \ if ( bli_does_trans( transc ) ) \ { \ bli_swap_incs( &rs_c, &cs_c ); \ bli_toggle_trans( &transc ); \ } \ \ /* Create flags to incidate row or column storage. Note that the schema bit that encodes row or column is describing the form of micro-panel, not the storage in the micro-panel. Hence the mismatch in "row" and "column" semantics. */ \ bool col_stored = bli_is_col_packed( schema ); \ /*bool row_stored = bli_is_row_packed( schema );*/ \ \ if ( col_stored ) \ { \ /* Prepare to pack to a column-stored matrix. */ \ iter_dim = n; \ vector_len = m; \ incc = rs_c; \ ldc = cs_c; \ incp = 1; \ ldp = cs_p; \ } \ else /* if ( row_stored ) */ \ { \ /* Prepare to pack to a row-stored matrix. */ \ iter_dim = m; \ vector_len = n; \ incc = cs_c; \ ldc = rs_c; \ incp = 1; \ ldp = rs_p; \ } \ \ /* Compute the total number of iterations we'll need. */ \ n_iter = iter_dim; \ \ \ ctype* restrict p_begin = p_cast; \ \ /* Query the number of threads and thread ids from the current thread's packm thrinfo_t node. */ \ const dim_t nt = bli_thread_n_way( thread ); \ const dim_t tid = bli_thread_work_id( thread ); \ \ /* Suppress warnings in case tid isn't used (ie: as in slab partitioning). */ \ ( void )nt; \ ( void )tid; \ \ dim_t it_start, it_end, it_inc; \ \ /* Determine the thread range and increment using the current thread's packm thrinfo_t node. NOTE: The definition of bli_thread_range_jrir() will depend on whether slab or round-robin partitioning was requested at configure-time. */ \ bli_thread_range_jrir( thread, n_iter, 1, FALSE, &it_start, &it_end, &it_inc ); \ \ /* Iterate over every logical micropanel in the source matrix. */ \ for ( it = 0; it < n_iter; it += 1 ) \ { \ ctype* restrict c_begin = c_cast + (it )*ldc; \ \ ctype* restrict c_use = c_begin; \ ctype* restrict p_use = p_begin; \ \ { \ /* The definition of bli_packm_my_iter() will depend on whether slab or round-robin partitioning was requested at configure-time. */ \ if ( bli_packm_my_iter( it, it_start, it_end, tid, nt ) ) \ { \ PASTEMAC2(ch,scal2v,BLIS_TAPI_EX_SUF) \ ( \ conjc, \ vector_len, \ kappa_cast, \ c_use, incc, \ p_use, incp, \ cntx, \ NULL \ ); \ } \ \ } \ \ p_begin += ldp; \ \ /* if ( row_stored ) \ PASTEMAC(ch,fprintm)( stdout, "packm_sup_var1: b packed", panel_len_max, panel_dim_max, \ p_use, rs_p, cs_p, "%5.2f", "" ); \ if ( !row_stored ) \ PASTEMAC(ch,fprintm)( stdout, "packm_sup_var1: a packed", panel_dim_max, panel_len_max, \ p_use, rs_p, cs_p, "%5.2f", "" ); \ */ \ } \ } INSERT_GENTFUNCR_BASIC( packm, packm_sup_var2 ) blis-0.9.0/frame/3/bli_l3_sup_packm_var.h000066400000000000000000000054621422157504600201510ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype BLAS-like interfaces to the variants. // #undef GENTPROT #define GENTPROT( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ trans_t transc, \ pack_t schema, \ dim_t m, \ dim_t n, \ dim_t m_max, \ dim_t n_max, \ ctype* restrict kappa, \ ctype* restrict c, inc_t rs_c, inc_t cs_c, \ ctype* restrict p, inc_t rs_p, inc_t cs_p, \ dim_t pd_p, inc_t ps_p, \ cntx_t* restrict cntx, \ thrinfo_t* restrict thread \ ); INSERT_GENTPROT_BASIC0( packm_sup_var1 ) #undef GENTPROT #define GENTPROT( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ trans_t transc, \ pack_t schema, \ dim_t m, \ dim_t n, \ ctype* restrict kappa, \ ctype* restrict c, inc_t rs_c, inc_t cs_c, \ ctype* restrict p, inc_t rs_p, inc_t cs_p, \ cntx_t* restrict cntx, \ thrinfo_t* restrict thread \ ); INSERT_GENTPROT_BASIC0( packm_sup_var2 ) blis-0.9.0/frame/3/bli_l3_sup_ref.c000066400000000000000000000126101422157504600167460ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2019 - 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" err_t bli_gemmsup_ref ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, rntm_t* rntm ) { // This function implements the default gemmsup handler. If you are a // BLIS developer and wish to use a different gemmsup handler, please // register a different function pointer in the context in your // sub-configuration's bli_cntx_init_*() function. // Check parameters. if ( bli_error_checking_is_enabled() ) bli_gemm_check( alpha, a, b, beta, c, cntx ); #if 0 // NOTE: This special case handling is done within the variants. // If alpha is zero, scale by beta and return. if ( bli_obj_equals( alpha, &BLIS_ZERO ) ) { bli_scalm( beta, c ); return; } // If A or B has a zero dimension, scale C by beta and return early. if ( bli_obj_has_zero_dim( a ) || bli_obj_has_zero_dim( b ) ) { bli_scalm( beta, c ); return BLIS_SUCCESS; } #endif const stor3_t stor_id = bli_obj_stor3_from_strides( c, a, b ); // Don't use the small/unpacked implementation if one of the matrices // uses general stride. NOTE: We check for this here, in bli_gemmsup_ref() // (and not in the calling function, bli_gemmsup()), because we consider // this way of handling general stride to be part of the implementation // and not necessarily a general-purpose solution that would apply to all // possible gemmsup handlers. Similarly, we check for it here (and not in // the internal thread entry point, bli_gemmsup_int()) because we don't // want to have to manage the multiple return values from the threads, // which we would have to process into a single return value and then // return from the parallel/threaded region. if ( stor_id == BLIS_XXX ) return BLIS_FAILURE; // Parse and interpret the contents of the rntm_t object to properly // set the ways of parallelism for each loop. bli_rntm_set_ways_from_rntm_sup ( bli_obj_length( c ), bli_obj_width( c ), bli_obj_width( a ), rntm ); #if 0 printf( "rntm.pack_a = %d\n", ( int )bli_rntm_pack_a( rntm ) ); printf( "rntm.pack_b = %d\n", ( int )bli_rntm_pack_b( rntm ) ); //bli_rntm_set_pack_a( 0, rntm ); //bli_rntm_set_pack_b( 0, rntm ); #endif return bli_l3_sup_thread_decorator ( bli_gemmsup_int, BLIS_GEMM, // operation family id alpha, a, b, beta, c, cntx, rntm ); } // ----------------------------------------------------------------------------- err_t bli_gemmtsup_ref ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, rntm_t* rntm ) { // This function implements the default gemmtsup handler. If you are a // BLIS developer and wish to use a different gemmtsup handler, please // register a different function pointer in the context in your // sub-configuration's bli_cntx_init_*() function. // Check parameters. if ( bli_error_checking_is_enabled() ) bli_gemmt_check( alpha, a, b, beta, c, cntx ); #if 0 // NOTE: This special case handling is done within the variants. // If alpha is zero, scale by beta and return. if ( bli_obj_equals( alpha, &BLIS_ZERO ) ) { bli_scalm( beta, c ); return; } // If A or B has a zero dimension, scale C by beta and return early. if ( bli_obj_has_zero_dim( a ) || bli_obj_has_zero_dim( b ) ) { bli_scalm( beta, c ); return BLIS_SUCCESS; } #endif // Parse and interpret the contents of the rntm_t object to properly // set the ways of parallelism for each loop. bli_rntm_set_ways_from_rntm_sup ( bli_obj_length( c ), bli_obj_width( c ), bli_obj_width( a ), rntm ); return bli_l3_sup_thread_decorator ( bli_gemmtsup_int, BLIS_GEMMT, // operation family id alpha, a, b, beta, c, cntx, rntm ); } blis-0.9.0/frame/3/bli_l3_sup_ref.h000066400000000000000000000037541422157504600167640ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2019 - 2000, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ err_t bli_gemmsup_ref ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, rntm_t* rntm ); err_t bli_gemmtsup_ref ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, rntm_t* rntm ); blis-0.9.0/frame/3/bli_l3_sup_var12.c000066400000000000000000000536001422157504600171310ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define FUNCPTR_T gemmsup_fp typedef void (*FUNCPTR_T) ( conj_t conja, conj_t conjb, dim_t m, dim_t n, dim_t k, void* restrict alpha, void* restrict a, inc_t rs_a, inc_t cs_a, void* restrict b, inc_t rs_b, inc_t cs_b, void* restrict beta, void* restrict c, inc_t rs_c, inc_t cs_c, stor3_t eff_id, cntx_t* restrict cntx, rntm_t* restrict rntm ); #if 0 // // -- var2 --------------------------------------------------------------------- // static FUNCPTR_T GENARRAY(ftypes_var2,gemmsup_ref_var2); void bli_gemmsup_ref_var2 ( trans_t trans, obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, stor3_t eff_id, cntx_t* cntx, rntm_t* rntm ) { #if 0 obj_t at, bt; bli_obj_alias_to( a, &at ); bli_obj_alias_to( b, &bt ); // Induce transpositions on A and/or B if either object is marked for // transposition. We can induce "fast" transpositions since they objects // are guaranteed to not have structure or be packed. if ( bli_obj_has_trans( &at ) ) { bli_obj_induce_fast_trans( &at ); } if ( bli_obj_has_trans( &bt ) ) { bli_obj_induce_fast_trans( &bt ); } const num_t dt_exec = bli_obj_dt( c ); const conj_t conja = bli_obj_conj_status( a ); const conj_t conjb = bli_obj_conj_status( b ); const dim_t m = bli_obj_length( c ); const dim_t n = bli_obj_width( c ); const dim_t k = bli_obj_width( &at ); void* restrict buf_a = bli_obj_buffer_at_off( &at ); const inc_t rs_a = bli_obj_row_stride( &at ); const inc_t cs_a = bli_obj_col_stride( &at ); void* restrict buf_b = bli_obj_buffer_at_off( &bt ); const inc_t rs_b = bli_obj_row_stride( &bt ); const inc_t cs_b = bli_obj_col_stride( &bt ); void* restrict buf_c = bli_obj_buffer_at_off( c ); const inc_t rs_c = bli_obj_row_stride( c ); const inc_t cs_c = bli_obj_col_stride( c ); void* restrict buf_alpha = bli_obj_buffer_for_1x1( dt_exec, alpha ); void* restrict buf_beta = bli_obj_buffer_for_1x1( dt_exec, beta ); #else const num_t dt_exec = bli_obj_dt( c ); const conj_t conja = bli_obj_conj_status( a ); const conj_t conjb = bli_obj_conj_status( b ); const dim_t m = bli_obj_length( c ); const dim_t n = bli_obj_width( c ); dim_t k; void* restrict buf_a = bli_obj_buffer_at_off( a ); inc_t rs_a; inc_t cs_a; void* restrict buf_b = bli_obj_buffer_at_off( b ); inc_t rs_b; inc_t cs_b; if ( bli_obj_has_notrans( a ) ) { k = bli_obj_width( a ); rs_a = bli_obj_row_stride( a ); cs_a = bli_obj_col_stride( a ); } else // if ( bli_obj_has_trans( a ) ) { // Assign the variables with an implicit transposition. k = bli_obj_length( a ); rs_a = bli_obj_col_stride( a ); cs_a = bli_obj_row_stride( a ); } if ( bli_obj_has_notrans( b ) ) { rs_b = bli_obj_row_stride( b ); cs_b = bli_obj_col_stride( b ); } else // if ( bli_obj_has_trans( b ) ) { // Assign the variables with an implicit transposition. rs_b = bli_obj_col_stride( b ); cs_b = bli_obj_row_stride( b ); } void* restrict buf_c = bli_obj_buffer_at_off( c ); const inc_t rs_c = bli_obj_row_stride( c ); const inc_t cs_c = bli_obj_col_stride( c ); void* restrict buf_alpha = bli_obj_buffer_for_1x1( dt_exec, alpha ); void* restrict buf_beta = bli_obj_buffer_for_1x1( dt_exec, beta ); #endif // Index into the type combination array to extract the correct // function pointer. FUNCPTR_T f = ftypes_var2[dt_exec]; // Invoke the function. f ( conja, conjb, m, n, k, buf_alpha, buf_a, rs_a, cs_a, buf_b, rs_b, cs_b, buf_beta, buf_c, rs_c, cs_c, eff_id, cntx, rntm ); } #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ conj_t conja, \ conj_t conjb, \ dim_t m, \ dim_t n, \ dim_t k, \ void* restrict alpha, \ void* restrict a, inc_t rs_a, inc_t cs_a, \ void* restrict b, inc_t rs_b, inc_t cs_b, \ void* restrict beta, \ void* restrict c, inc_t rs_c, inc_t cs_c, \ stor3_t eff_id, \ cntx_t* restrict cntx, \ rntm_t* restrict rntm \ ) \ { \ /* If any dimension is zero, return immediately. */ \ if ( bli_zero_dim3( m, n, k ) ) return; \ \ /* If alpha is zero, scale by beta and return. */ \ if ( PASTEMAC(ch,eq0)( *(( ctype* )alpha) ) ) \ { \ PASTEMAC(ch,scalm) \ ( \ BLIS_NO_CONJUGATE, \ 0, \ BLIS_NONUNIT_DIAG, \ BLIS_DENSE, \ m, n, \ beta, \ c, rs_c, cs_c \ ); \ return; \ } \ \ const num_t dt = PASTEMAC(ch,type); \ \ /* Query the context for various blocksizes. */ \ const dim_t NC = bli_cntx_get_l3_sup_blksz_def_dt( dt, BLIS_NC, cntx ); \ const dim_t KC = bli_cntx_get_l3_sup_blksz_def_dt( dt, BLIS_KC, cntx ); \ const dim_t MC = bli_cntx_get_l3_sup_blksz_def_dt( dt, BLIS_MC, cntx ); \ const dim_t NR = bli_cntx_get_l3_sup_blksz_def_dt( dt, BLIS_NR, cntx ); \ const dim_t MR = bli_cntx_get_l3_sup_blksz_def_dt( dt, BLIS_MR, cntx ); \ \ /* Compute partitioning step values for each matrix of each loop. */ \ const inc_t jcstep_c = cs_c * NC; \ const inc_t jcstep_b = cs_b * NC; \ \ const inc_t pcstep_a = cs_a * KC; \ const inc_t pcstep_b = rs_b * KC; \ \ const inc_t icstep_c = rs_c * MC; \ const inc_t icstep_a = rs_a * MC; \ \ const inc_t jrstep_c = cs_c * NR; \ const inc_t jrstep_b = cs_b * NR; \ \ const inc_t irstep_c = rs_c * MR; \ const inc_t irstep_a = rs_a * MR; \ \ /* Query a stor3_t enum value to characterize the problem. Examples: BLIS_RRR, BLIS_RRC, BLIS_RCR, BLIS_RCC, etc. NOTE: If any matrix is general-stored, we use the all-purpose sup microkernel corresponding to the stor3_t enum value BLIS_XXX. */ \ const stor3_t stor_id = bli_stor3_from_strides( rs_c, cs_c, \ rs_a, cs_a, rs_b, cs_b ); \ \ /* Query the context for the sup microkernel address and cast it to its function pointer type. */ \ PASTECH(ch,gemmsup_ker_ft) \ gemmsup_ker = bli_cntx_get_l3_sup_ker_dt( dt, stor_id, cntx ); \ \ ctype* restrict a_00 = a; \ ctype* restrict b_00 = b; \ ctype* restrict c_00 = c; \ ctype* restrict alpha_cast = alpha; \ ctype* restrict beta_cast = beta; \ \ ctype* restrict one = PASTEMAC(ch,1); \ \ auxinfo_t aux; \ \ /* Compute number of primary and leftover components of the outer dimensions. NOTE: Functionally speaking, we compute jc_iter as: jc_iter = n / NC; if ( jc_left ) ++jc_iter; However, this is implemented as: jc_iter = ( n + NC - 1 ) / NC; This avoids a branch at the cost of two additional integer instructions. The pc_iter, mc_iter, nr_iter, and mr_iter variables are computed in similar manner. */ \ const dim_t jc_iter = ( n + NC - 1 ) / NC; \ const dim_t jc_left = n % NC; \ \ const dim_t pc_iter = ( k + KC - 1 ) / KC; \ const dim_t pc_left = k % KC; \ \ const dim_t ic_iter = ( m + MC - 1 ) / MC; \ const dim_t ic_left = m % MC; \ \ const dim_t jc_inc = 1; \ const dim_t pc_inc = 1; \ const dim_t ic_inc = 1; \ const dim_t jr_inc = 1; \ const dim_t ir_inc = 1; \ \ /* Loop over the n dimension (NC rows/columns at a time). */ \ for ( dim_t jj = 0; jj < jc_iter; jj += jc_inc ) \ { \ const dim_t nc_cur = ( bli_is_not_edge_f( jj, jc_iter, jc_left ) ? NC : jc_left ); \ \ ctype* restrict b_jc = b_00 + jj * jcstep_b; \ ctype* restrict c_jc = c_00 + jj * jcstep_c; \ \ const dim_t jr_iter = ( nc_cur + NR - 1 ) / NR; \ const dim_t jr_left = nc_cur % NR; \ \ /* Loop over the k dimension (KC rows/columns at a time). */ \ for ( dim_t pp = 0; pp < pc_iter; pp += pc_inc ) \ { \ const dim_t kc_cur = ( bli_is_not_edge_f( pp, pc_iter, pc_left ) ? KC : pc_left ); \ \ ctype* restrict a_pc = a_00 + pp * pcstep_a; \ ctype* restrict b_pc = b_jc + pp * pcstep_b; \ \ /* Only apply beta to the first iteration of the pc loop. */ \ ctype* restrict beta_use = ( pp == 0 ? beta_cast : one ); \ \ /* Loop over the m dimension (MC rows at a time). */ \ for ( dim_t ii = 0; ii < ic_iter; ii += ic_inc ) \ { \ const dim_t mc_cur = ( bli_is_not_edge_f( ii, ic_iter, ic_left ) ? MC : ic_left ); \ \ ctype* restrict a_ic = a_pc + ii * icstep_a; \ ctype* restrict c_ic = c_jc + ii * icstep_c; \ \ const dim_t ir_iter = ( mc_cur + MR - 1 ) / MR; \ const dim_t ir_left = mc_cur % MR; \ \ /* Loop over the n dimension (NR columns at a time). */ \ for ( dim_t j = 0; j < jr_iter; j += jr_inc ) \ { \ const dim_t nr_cur = ( bli_is_not_edge_f( j, jr_iter, jr_left ) ? NR : jr_left ); \ \ ctype* restrict b_jr = b_pc + j * jrstep_b; \ ctype* restrict c_jr = c_ic + j * jrstep_c; \ \ /* ctype* restrict b2 = b_jr; \ */ \ \ /* Loop over the m dimension (MR rows at a time). */ \ for ( dim_t i = 0; i < ir_iter; i += ir_inc ) \ { \ const dim_t mr_cur = ( bli_is_not_edge_f( i, ir_iter, ir_left ) ? MR : ir_left ); \ \ ctype* restrict a_ir = a_ic + i * irstep_a; \ ctype* restrict c_ir = c_jr + i * irstep_c; \ \ /* Save addresses of next panels of A and B to the auxinfo_t object. */ \ /* ctype* restrict a2 = bli_gemm_get_next_a_upanel( a_ir, irstep_a, ir_inc ); \ if ( bli_is_last_iter( i, ir_iter, 0, 1 ) ) \ { \ a2 = a_00; \ b2 = bli_gemm_get_next_b_upanel( b_jr, jrstep_b, jr_inc ); \ if ( bli_is_last_iter( j, jr_iter, 0, 1 ) ) \ b2 = b_00; \ } \ \ bli_auxinfo_set_next_a( a2, &aux ); \ bli_auxinfo_set_next_b( b2, &aux ); \ */ \ \ /* Invoke the gemmsup micro-kernel. */ \ gemmsup_ker \ ( \ conja, \ conjb, \ mr_cur, \ nr_cur, \ kc_cur, \ alpha_cast, \ a_ir, rs_a, cs_a, \ b_jr, rs_b, cs_b, \ beta_use, \ c_ir, rs_c, cs_c, \ &aux, \ cntx \ ); \ } \ } \ } \ } \ } \ \ /* PASTEMAC(ch,fprintm)( stdout, "gemmsup_ref_var2: b1", kc_cur, nr_cur, b_jr, rs_b, cs_b, "%4.1f", "" ); \ PASTEMAC(ch,fprintm)( stdout, "gemmsup_ref_var2: a1", mr_cur, kc_cur, a_ir, rs_a, cs_a, "%4.1f", "" ); \ PASTEMAC(ch,fprintm)( stdout, "gemmsup_ref_var2: c ", mr_cur, nr_cur, c_ir, rs_c, cs_c, "%4.1f", "" ); \ */ \ } INSERT_GENTFUNC_BASIC0( gemmsup_ref_var2 ) // // -- var1 --------------------------------------------------------------------- // static FUNCPTR_T GENARRAY(ftypes_var1,gemmsup_ref_var1); void bli_gemmsup_ref_var1 ( trans_t trans, obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, stor3_t eff_id, cntx_t* cntx, rntm_t* rntm ) { #if 0 obj_t at, bt; bli_obj_alias_to( a, &at ); bli_obj_alias_to( b, &bt ); // Induce transpositions on A and/or B if either object is marked for // transposition. We can induce "fast" transpositions since they objects // are guaranteed to not have structure or be packed. if ( bli_obj_has_trans( &at ) ) { bli_obj_induce_fast_trans( &at ); } if ( bli_obj_has_trans( &bt ) ) { bli_obj_induce_fast_trans( &bt ); } const num_t dt_exec = bli_obj_dt( c ); const conj_t conja = bli_obj_conj_status( a ); const conj_t conjb = bli_obj_conj_status( b ); const dim_t m = bli_obj_length( c ); const dim_t n = bli_obj_width( c ); const dim_t k = bli_obj_width( &at ); void* restrict buf_a = bli_obj_buffer_at_off( &at ); const inc_t rs_a = bli_obj_row_stride( &at ); const inc_t cs_a = bli_obj_col_stride( &at ); void* restrict buf_b = bli_obj_buffer_at_off( &bt ); const inc_t rs_b = bli_obj_row_stride( &bt ); const inc_t cs_b = bli_obj_col_stride( &bt ); void* restrict buf_c = bli_obj_buffer_at_off( c ); const inc_t rs_c = bli_obj_row_stride( c ); const inc_t cs_c = bli_obj_col_stride( c ); void* restrict buf_alpha = bli_obj_buffer_for_1x1( dt_exec, alpha ); void* restrict buf_beta = bli_obj_buffer_for_1x1( dt_exec, beta ); #else const num_t dt_exec = bli_obj_dt( c ); const conj_t conja = bli_obj_conj_status( a ); const conj_t conjb = bli_obj_conj_status( b ); const dim_t m = bli_obj_length( c ); const dim_t n = bli_obj_width( c ); dim_t k; void* restrict buf_a = bli_obj_buffer_at_off( a ); inc_t rs_a; inc_t cs_a; void* restrict buf_b = bli_obj_buffer_at_off( b ); inc_t rs_b; inc_t cs_b; if ( bli_obj_has_notrans( a ) ) { k = bli_obj_width( a ); rs_a = bli_obj_row_stride( a ); cs_a = bli_obj_col_stride( a ); } else // if ( bli_obj_has_trans( a ) ) { // Assign the variables with an implicit transposition. k = bli_obj_length( a ); rs_a = bli_obj_col_stride( a ); cs_a = bli_obj_row_stride( a ); } if ( bli_obj_has_notrans( b ) ) { rs_b = bli_obj_row_stride( b ); cs_b = bli_obj_col_stride( b ); } else // if ( bli_obj_has_trans( b ) ) { // Assign the variables with an implicit transposition. rs_b = bli_obj_col_stride( b ); cs_b = bli_obj_row_stride( b ); } void* restrict buf_c = bli_obj_buffer_at_off( c ); const inc_t rs_c = bli_obj_row_stride( c ); const inc_t cs_c = bli_obj_col_stride( c ); void* restrict buf_alpha = bli_obj_buffer_for_1x1( dt_exec, alpha ); void* restrict buf_beta = bli_obj_buffer_for_1x1( dt_exec, beta ); #endif // Index into the type combination array to extract the correct // function pointer. FUNCPTR_T f = ftypes_var1[dt_exec]; // Invoke the function. f ( conja, conjb, m, n, k, buf_alpha, buf_a, rs_a, cs_a, buf_b, rs_b, cs_b, buf_beta, buf_c, rs_c, cs_c, eff_id, cntx, rntm ); } #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ conj_t conja, \ conj_t conjb, \ dim_t m, \ dim_t n, \ dim_t k, \ void* restrict alpha, \ void* restrict a, inc_t rs_a, inc_t cs_a, \ void* restrict b, inc_t rs_b, inc_t cs_b, \ void* restrict beta, \ void* restrict c, inc_t rs_c, inc_t cs_c, \ stor3_t eff_id, \ cntx_t* restrict cntx, \ rntm_t* restrict rntm \ ) \ { \ /* If any dimension is zero, return immediately. */ \ if ( bli_zero_dim3( m, n, k ) ) return; \ \ /* If alpha is zero, scale by beta and return. */ \ if ( PASTEMAC(ch,eq0)( *(( ctype* )alpha) ) ) \ { \ PASTEMAC(ch,scalm) \ ( \ BLIS_NO_CONJUGATE, \ 0, \ BLIS_NONUNIT_DIAG, \ BLIS_DENSE, \ m, n, \ beta, \ c, rs_c, cs_c \ ); \ return; \ } \ \ const num_t dt = PASTEMAC(ch,type); \ \ /* Query the context for various blocksizes. */ \ const dim_t NC0 = bli_cntx_get_l3_sup_blksz_def_dt( dt, BLIS_NC, cntx ); \ const dim_t KC = bli_cntx_get_l3_sup_blksz_def_dt( dt, BLIS_KC, cntx ); \ const dim_t MC0 = bli_cntx_get_l3_sup_blksz_def_dt( dt, BLIS_MC, cntx ); \ const dim_t NR = bli_cntx_get_l3_sup_blksz_def_dt( dt, BLIS_NR, cntx ); \ const dim_t MR = bli_cntx_get_l3_sup_blksz_def_dt( dt, BLIS_MR, cntx ); \ \ /* Nudge NC up to a multiple of MR and MC up to a multiple of NR. */ \ const dim_t NC = bli_align_dim_to_mult( NC0, MR ); \ const dim_t MC = bli_align_dim_to_mult( MC0, NR ); \ \ /* Compute partitioning step values for each matrix of each loop. */ \ const inc_t jcstep_c = rs_c * NC; \ const inc_t jcstep_a = rs_a * NC; \ \ const inc_t pcstep_a = cs_a * KC; \ const inc_t pcstep_b = rs_b * KC; \ \ const inc_t icstep_c = cs_c * MC; \ const inc_t icstep_b = cs_b * MC; \ \ const inc_t jrstep_c = rs_c * MR; \ const inc_t jrstep_a = rs_a * MR; \ \ const inc_t irstep_c = cs_c * NR; \ const inc_t irstep_b = cs_b * NR; \ \ /* Query a stor3_t enum value to characterize the problem. Examples: BLIS_RRR, BLIS_RRC, BLIS_RCR, BLIS_RCC, etc. NOTE: If any matrix is general-stored, we use the all-purpose sup microkernel corresponding to the stor3_t enum value BLIS_XXX. */ \ const stor3_t stor_id = bli_stor3_from_strides( rs_c, cs_c, \ rs_a, cs_a, rs_b, cs_b ); \ \ /* Query the context for the sup microkernel address and cast it to its function pointer type. */ \ PASTECH(ch,gemmsup_ker_ft) \ gemmsup_ker = bli_cntx_get_l3_sup_ker_dt( dt, stor_id, cntx ); \ \ ctype* restrict a_00 = a; \ ctype* restrict b_00 = b; \ ctype* restrict c_00 = c; \ ctype* restrict alpha_cast = alpha; \ ctype* restrict beta_cast = beta; \ \ ctype* restrict one = PASTEMAC(ch,1); \ \ auxinfo_t aux; \ \ /* Compute number of primary and leftover components of the outer dimensions. NOTE: Functionally speaking, we compute jc_iter as: jc_iter = m / NC; if ( jc_left ) ++jc_iter; However, this is implemented as: jc_iter = ( m + NC - 1 ) / NC; This avoids a branch at the cost of two additional integer instructions. The pc_iter, mc_iter, nr_iter, and mr_iter variables are computed in similar manner. */ \ const dim_t jc_iter = ( m + NC - 1 ) / NC; \ const dim_t jc_left = m % NC; \ \ const dim_t pc_iter = ( k + KC - 1 ) / KC; \ const dim_t pc_left = k % KC; \ \ const dim_t ic_iter = ( n + MC - 1 ) / MC; \ const dim_t ic_left = n % MC; \ \ const dim_t jc_inc = 1; \ const dim_t pc_inc = 1; \ const dim_t ic_inc = 1; \ const dim_t jr_inc = 1; \ const dim_t ir_inc = 1; \ \ /* Loop over the m dimension (NC rows/columns at a time). */ \ for ( dim_t jj = 0; jj < jc_iter; jj += jc_inc ) \ { \ const dim_t nc_cur = ( bli_is_not_edge_f( jj, jc_iter, jc_left ) ? NC : jc_left ); \ \ ctype* restrict a_jc = a_00 + jj * jcstep_a; \ ctype* restrict c_jc = c_00 + jj * jcstep_c; \ \ const dim_t jr_iter = ( nc_cur + MR - 1 ) / MR; \ const dim_t jr_left = nc_cur % MR; \ \ /* Loop over the k dimension (KC rows/columns at a time). */ \ for ( dim_t pp = 0; pp < pc_iter; pp += pc_inc ) \ { \ const dim_t kc_cur = ( bli_is_not_edge_f( pp, pc_iter, pc_left ) ? KC : pc_left ); \ \ ctype* restrict a_pc = a_jc + pp * pcstep_a; \ ctype* restrict b_pc = b_00 + pp * pcstep_b; \ \ /* Only apply beta to the first iteration of the pc loop. */ \ ctype* restrict beta_use = ( pp == 0 ? beta_cast : one ); \ \ /* Loop over the n dimension (MC rows at a time). */ \ for ( dim_t ii = 0; ii < ic_iter; ii += ic_inc ) \ { \ const dim_t mc_cur = ( bli_is_not_edge_f( ii, ic_iter, ic_left ) ? MC : ic_left ); \ \ ctype* restrict b_ic = b_pc + ii * icstep_b; \ ctype* restrict c_ic = c_jc + ii * icstep_c; \ \ const dim_t ir_iter = ( mc_cur + NR - 1 ) / NR; \ const dim_t ir_left = mc_cur % NR; \ \ /* Loop over the m dimension (NR columns at a time). */ \ for ( dim_t j = 0; j < jr_iter; j += jr_inc ) \ { \ const dim_t nr_cur = ( bli_is_not_edge_f( j, jr_iter, jr_left ) ? NR : jr_left ); \ \ ctype* restrict a_jr = a_pc + j * jrstep_a; \ ctype* restrict c_jr = c_ic + j * jrstep_c; \ \ /* Loop over the n dimension (MR rows at a time). */ \ for ( dim_t i = 0; i < ir_iter; i += ir_inc ) \ { \ const dim_t mr_cur = ( bli_is_not_edge_f( i, ir_iter, ir_left ) ? MR : ir_left ); \ \ ctype* restrict b_ir = b_ic + i * irstep_b; \ ctype* restrict c_ir = c_jr + i * irstep_c; \ \ /* Invoke the gemmsup micro-kernel. */ \ gemmsup_ker \ ( \ conja, \ conjb, \ mr_cur, \ nr_cur, \ kc_cur, \ alpha_cast, \ a_jr, rs_a, cs_a, \ b_ir, rs_b, cs_b, \ beta_use, \ c_ir, rs_c, cs_c, \ &aux, \ cntx \ ); \ } \ } \ } \ } \ } \ \ /* PASTEMAC(ch,fprintm)( stdout, "gemmsup_ref_var2: b1", kc_cur, nr_cur, b_jr, rs_b, cs_b, "%4.1f", "" ); \ PASTEMAC(ch,fprintm)( stdout, "gemmsup_ref_var2: a1", mr_cur, kc_cur, a_ir, rs_a, cs_a, "%4.1f", "" ); \ PASTEMAC(ch,fprintm)( stdout, "gemmsup_ref_var2: c ", mr_cur, nr_cur, c_ir, rs_c, cs_c, "%4.1f", "" ); \ */ \ } INSERT_GENTFUNC_BASIC0( gemmsup_ref_var1 ) #endif blis-0.9.0/frame/3/bli_l3_sup_var1n2m.c000066400000000000000000001317601422157504600174700ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define FUNCPTR_T gemmsup_fp typedef void (*FUNCPTR_T) ( bool packa, bool packb, conj_t conja, conj_t conjb, dim_t m, dim_t n, dim_t k, void* restrict alpha, void* restrict a, inc_t rs_a, inc_t cs_a, void* restrict b, inc_t rs_b, inc_t cs_b, void* restrict beta, void* restrict c, inc_t rs_c, inc_t cs_c, stor3_t eff_id, cntx_t* restrict cntx, rntm_t* restrict rntm, thrinfo_t* restrict thread ); // // -- var1n -------------------------------------------------------------------- // static FUNCPTR_T GENARRAY(ftypes_var1n,gemmsup_ref_var1n); void bli_gemmsup_ref_var1n ( trans_t trans, obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, stor3_t eff_id, cntx_t* cntx, rntm_t* rntm, thrinfo_t* thread ) { #if 0 obj_t at, bt; bli_obj_alias_to( a, &at ); bli_obj_alias_to( b, &bt ); // Induce transpositions on A and/or B if either object is marked for // transposition. We can induce "fast" transpositions since they objects // are guaranteed to not have structure or be packed. if ( bli_obj_has_trans( &at ) ) { bli_obj_induce_fast_trans( &at ); } if ( bli_obj_has_trans( &bt ) ) { bli_obj_induce_fast_trans( &bt ); } const num_t dt = bli_obj_dt( c ); const conj_t conja = bli_obj_conj_status( a ); const conj_t conjb = bli_obj_conj_status( b ); const dim_t m = bli_obj_length( c ); const dim_t n = bli_obj_width( c ); const dim_t k = bli_obj_width( &at ); void* restrict buf_a = bli_obj_buffer_at_off( &at ); const inc_t rs_a = bli_obj_row_stride( &at ); const inc_t cs_a = bli_obj_col_stride( &at ); void* restrict buf_b = bli_obj_buffer_at_off( &bt ); const inc_t rs_b = bli_obj_row_stride( &bt ); const inc_t cs_b = bli_obj_col_stride( &bt ); void* restrict buf_c = bli_obj_buffer_at_off( c ); const inc_t rs_c = bli_obj_row_stride( c ); const inc_t cs_c = bli_obj_col_stride( c ); void* restrict buf_alpha = bli_obj_buffer_for_1x1( dt, alpha ); void* restrict buf_beta = bli_obj_buffer_for_1x1( dt, beta ); #else const num_t dt = bli_obj_dt( c ); const bool packa = bli_rntm_pack_a( rntm ); const bool packb = bli_rntm_pack_b( rntm ); const conj_t conja = bli_obj_conj_status( a ); const conj_t conjb = bli_obj_conj_status( b ); const dim_t m = bli_obj_length( c ); const dim_t n = bli_obj_width( c ); dim_t k; void* restrict buf_a = bli_obj_buffer_at_off( a ); inc_t rs_a; inc_t cs_a; void* restrict buf_b = bli_obj_buffer_at_off( b ); inc_t rs_b; inc_t cs_b; if ( bli_obj_has_notrans( a ) ) { k = bli_obj_width( a ); rs_a = bli_obj_row_stride( a ); cs_a = bli_obj_col_stride( a ); } else // if ( bli_obj_has_trans( a ) ) { // Assign the variables with an implicit transposition. k = bli_obj_length( a ); rs_a = bli_obj_col_stride( a ); cs_a = bli_obj_row_stride( a ); } if ( bli_obj_has_notrans( b ) ) { rs_b = bli_obj_row_stride( b ); cs_b = bli_obj_col_stride( b ); } else // if ( bli_obj_has_trans( b ) ) { // Assign the variables with an implicit transposition. rs_b = bli_obj_col_stride( b ); cs_b = bli_obj_row_stride( b ); } void* restrict buf_c = bli_obj_buffer_at_off( c ); const inc_t rs_c = bli_obj_row_stride( c ); const inc_t cs_c = bli_obj_col_stride( c ); void* restrict buf_alpha = bli_obj_buffer_for_1x1( dt, alpha ); void* restrict buf_beta = bli_obj_buffer_for_1x1( dt, beta ); #endif // Index into the type combination array to extract the correct // function pointer. FUNCPTR_T f = ftypes_var1n[dt]; #if 1 // Optimize some storage/packing cases by transforming them into others. // These optimizations are expressed by changing trans and/or eff_id. bli_gemmsup_ref_var1n2m_opt_cases( dt, &trans, packa, packb, &eff_id, cntx ); #endif if ( bli_is_notrans( trans ) ) { // Invoke the function. f ( packa, packb, conja, conjb, m, n, k, buf_alpha, buf_a, rs_a, cs_a, buf_b, rs_b, cs_b, buf_beta, buf_c, rs_c, cs_c, eff_id, cntx, rntm, thread ); } else { // Invoke the function (transposing the operation). f ( packb, packa, conjb, // swap the conj values. conja, n, // swap the m and n dimensions. m, k, buf_alpha, buf_b, cs_b, rs_b, // swap the positions of A and B. buf_a, cs_a, rs_a, // swap the strides of A and B. buf_beta, buf_c, cs_c, rs_c, // swap the strides of C. bli_stor3_trans( eff_id ), // transpose the stor3_t id. cntx, rntm, thread ); } } #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ bool packa, \ bool packb, \ conj_t conja, \ conj_t conjb, \ dim_t m, \ dim_t n, \ dim_t k, \ void* restrict alpha, \ void* restrict a, inc_t rs_a, inc_t cs_a, \ void* restrict b, inc_t rs_b, inc_t cs_b, \ void* restrict beta, \ void* restrict c, inc_t rs_c, inc_t cs_c, \ stor3_t stor_id, \ cntx_t* restrict cntx, \ rntm_t* restrict rntm, \ thrinfo_t* restrict thread \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ /* If m or n is zero, return immediately. */ \ if ( bli_zero_dim2( m, n ) ) return; \ \ /* If k < 1 or alpha is zero, scale by beta and return. */ \ if ( k < 1 || PASTEMAC(ch,eq0)( *(( ctype* )alpha) ) ) \ { \ if ( bli_thread_am_ochief( thread ) ) \ { \ PASTEMAC(ch,scalm) \ ( \ BLIS_NO_CONJUGATE, \ 0, \ BLIS_NONUNIT_DIAG, \ BLIS_DENSE, \ m, n, \ beta, \ c, rs_c, cs_c \ ); \ } \ return; \ } \ \ /* This transposition of the stor3_t id value is inherent to variant 1. The reason: we assume that variant 2 is the "main" variant. The consequence of this is that we assume that the millikernels that iterate over m are registered to the "primary" kernel group associated with the kernel IO preference; similarly, mkernels that iterate over n are assumed to be registered to the "non-primary" group associated with the ("non-primary") anti-preference. Note that this pattern holds regardless of whether the mkernel set has a row or column preference.) See bli_l3_sup_int.c for a higher-level view of how this choice is made. */ \ stor_id = bli_stor3_trans( stor_id ); \ \ /* Query the context for various blocksizes. */ \ const dim_t NR = bli_cntx_get_l3_sup_blksz_def_dt( dt, BLIS_NR, cntx ); \ const dim_t MR = bli_cntx_get_l3_sup_blksz_def_dt( dt, BLIS_MR, cntx ); \ const dim_t NC0 = bli_cntx_get_l3_sup_blksz_def_dt( dt, BLIS_NC, cntx ); \ const dim_t MC0 = bli_cntx_get_l3_sup_blksz_def_dt( dt, BLIS_MC, cntx ); \ const dim_t KC0 = bli_cntx_get_l3_sup_blksz_def_dt( dt, BLIS_KC, cntx ); \ \ dim_t KC; \ if ( packa && packb ) \ { \ KC = KC0; \ } \ else if ( packb ) \ { \ if ( stor_id == BLIS_RRR || \ stor_id == BLIS_CCC ) KC = KC0; \ else if ( stor_id == BLIS_RRC || \ stor_id == BLIS_CRC ) KC = KC0; \ else if ( stor_id == BLIS_RCR || \ stor_id == BLIS_CCR ) KC = (( KC0 / 4 ) / 4 ) * 4; \ else KC = KC0; \ } \ else if ( packa ) \ { \ if ( stor_id == BLIS_RRR || \ stor_id == BLIS_CCC ) KC = (( KC0 / 2 ) / 2 ) * 2; \ else if ( stor_id == BLIS_RRC || \ stor_id == BLIS_CRC ) KC = KC0; \ else if ( stor_id == BLIS_RCR || \ stor_id == BLIS_CCR ) KC = (( KC0 / 4 ) / 4 ) * 4; \ else KC = KC0; \ } \ else /* if ( !packa && !packb ) */ \ { \ if ( FALSE ) KC = KC0; \ else if ( stor_id == BLIS_RRC || \ stor_id == BLIS_CRC ) KC = KC0; \ else if ( m <= MR && n <= NR ) KC = KC0; \ else if ( m <= 2*MR && n <= 2*NR ) KC = KC0 / 2; \ else if ( m <= 3*MR && n <= 3*NR ) KC = (( KC0 / 3 ) / 4 ) * 4; \ else if ( m <= 4*MR && n <= 4*NR ) KC = KC0 / 4; \ else KC = (( KC0 / 5 ) / 4 ) * 4; \ } \ \ /* Nudge NC up to a multiple of MR and MC up to a multiple of NR. NOTE: This is unique to variant 1 (ie: not performed in variant 2) because MC % MR == 0 and NC % NR == 0 is already enforced at runtime. */ \ const dim_t NC = bli_align_dim_to_mult( NC0, MR ); \ const dim_t MC = bli_align_dim_to_mult( MC0, NR ); \ \ /* Query the maximum blocksize for MR, which implies a maximum blocksize extension for the final iteration. */ \ const dim_t MRM = bli_cntx_get_l3_sup_blksz_max_dt( dt, BLIS_MR, cntx ); \ const dim_t MRE = MRM - MR; \ \ /* Compute partitioning step values for each matrix of each loop. */ \ const inc_t jcstep_c = rs_c; \ const inc_t jcstep_a = rs_a; \ \ const inc_t pcstep_a = cs_a; \ const inc_t pcstep_b = rs_b; \ \ const inc_t icstep_c = cs_c; \ const inc_t icstep_b = cs_b; \ \ const inc_t jrstep_c = rs_c * MR; \ \ /* const inc_t jrstep_a = rs_a * MR; \ \ const inc_t irstep_c = cs_c * NR; \ const inc_t irstep_b = cs_b * NR; \ */ \ \ /* Query the context for the sup microkernel address and cast it to its function pointer type. */ \ PASTECH(ch,gemmsup_ker_ft) \ gemmsup_ker = bli_cntx_get_l3_sup_ker_dt( dt, stor_id, cntx ); \ \ ctype* restrict a_00 = a; \ ctype* restrict b_00 = b; \ ctype* restrict c_00 = c; \ ctype* restrict alpha_cast = alpha; \ ctype* restrict beta_cast = beta; \ \ /* Make local copies of beta and one scalars to prevent any unnecessary sharing of cache lines between the cores' caches. */ \ ctype beta_local = *beta_cast; \ ctype one_local = *PASTEMAC(ch,1); \ \ auxinfo_t aux; \ \ /* Parse and interpret the contents of the rntm_t object to properly set the ways of parallelism for each loop. */ \ /*bli_rntm_set_ways_from_rntm_sup( m, n, k, rntm );*/ \ \ /* Initialize a mem_t entry for A and B. Strictly speaking, this is only needed for the matrix we will be packing (if any), but we do it unconditionally to be safe. An alternative way of initializing the mem_t entries is: bli_mem_clear( &mem_a ); \ bli_mem_clear( &mem_b ); \ */ \ mem_t mem_a = BLIS_MEM_INITIALIZER; \ mem_t mem_b = BLIS_MEM_INITIALIZER; \ \ /* Define an array of bszid_t ids, which will act as our substitute for the cntl_t tree. NOTE: These bszid_t values, and their order, match that of the bp algorithm (variant 2) because they are not used to query actual blocksizes but rather query the ways of parallelism for the various loops. For example, the 2nd loop in variant 1 partitions in the m dimension (in increments of MR), but parallelizes that m dimension with BLIS_JR_NT. The only difference is that the _packa and _packb arrays have been adjusted for the semantic difference in order in which packa and packb nodes are encountered in the thrinfo tree. That is, this panel-block algorithm partitions an NC x KC submatrix of A to be packed in the 4th loop, and a KC x MC submatrix of B to be packed in the 3rd loop. */ \ /* 5thloop 4thloop packa 3rdloop packb 2ndloop 1stloop ukrloop */ \ bszid_t bszids_nopack[6] = { BLIS_NC, BLIS_KC, BLIS_MC, BLIS_NR, BLIS_MR, BLIS_KR }; \ bszid_t bszids_packa [7] = { BLIS_NC, BLIS_KC, BLIS_NO_PART, BLIS_MC, BLIS_NR, BLIS_MR, BLIS_KR }; \ bszid_t bszids_packb [7] = { BLIS_NC, BLIS_KC, BLIS_MC, BLIS_NO_PART, BLIS_NR, BLIS_MR, BLIS_KR }; \ bszid_t bszids_packab[8] = { BLIS_NC, BLIS_KC, BLIS_NO_PART, BLIS_MC, BLIS_NO_PART, BLIS_NR, BLIS_MR, BLIS_KR }; \ bszid_t* restrict bszids; \ \ /* Set the bszids pointer to the correct bszids array above based on which matrices (if any) are being packed. */ \ if ( packa ) { if ( packb ) bszids = bszids_packab; \ else bszids = bszids_packa; } \ else { if ( packb ) bszids = bszids_packb; \ else bszids = bszids_nopack; } \ \ /* Determine whether we are using more than one thread. */ \ const bool is_mt = ( bli_rntm_calc_num_threads( rntm ) > 1 ); \ \ thrinfo_t* restrict thread_jc = NULL; \ thrinfo_t* restrict thread_pc = NULL; \ thrinfo_t* restrict thread_pa = NULL; \ thrinfo_t* restrict thread_ic = NULL; \ thrinfo_t* restrict thread_pb = NULL; \ thrinfo_t* restrict thread_jr = NULL; \ \ /* Grow the thrinfo_t tree. */ \ bszid_t* restrict bszids_jc = bszids; \ thread_jc = thread; \ bli_thrinfo_sup_grow( rntm, bszids_jc, thread_jc ); \ \ /* Compute the JC loop thread range for the current thread. */ \ dim_t jc_start, jc_end; \ bli_thread_range_sub( thread_jc, m, MR, FALSE, &jc_start, &jc_end ); \ const dim_t m_local = jc_end - jc_start; \ \ /* Compute number of primary and leftover components of the JC loop. */ \ /*const dim_t jc_iter = ( m_local + NC - 1 ) / NC;*/ \ const dim_t jc_left = m_local % NC; \ \ /* Loop over the m dimension (NC rows/columns at a time). */ \ /*for ( dim_t jj = 0; jj < jc_iter; jj += 1 )*/ \ for ( dim_t jj = jc_start; jj < jc_end; jj += NC ) \ { \ /* Calculate the thread's current JC block dimension. */ \ const dim_t nc_cur = ( NC <= jc_end - jj ? NC : jc_left ); \ \ ctype* restrict a_jc = a_00 + jj * jcstep_a; \ ctype* restrict c_jc = c_00 + jj * jcstep_c; \ \ /* Grow the thrinfo_t tree. */ \ bszid_t* restrict bszids_pc = &bszids_jc[1]; \ thread_pc = bli_thrinfo_sub_node( thread_jc ); \ bli_thrinfo_sup_grow( rntm, bszids_pc, thread_pc ); \ \ /* Compute the PC loop thread range for the current thread. */ \ const dim_t pc_start = 0, pc_end = k; \ const dim_t k_local = k; \ \ /* Compute number of primary and leftover components of the PC loop. */ \ /*const dim_t pc_iter = ( k_local + KC - 1 ) / KC;*/ \ const dim_t pc_left = k_local % KC; \ \ /* Loop over the k dimension (KC rows/columns at a time). */ \ /*for ( dim_t pp = 0; pp < pc_iter; pp += 1 )*/ \ for ( dim_t pp = pc_start; pp < pc_end; pp += KC ) \ { \ /* Calculate the thread's current PC block dimension. */ \ const dim_t kc_cur = ( KC <= pc_end - pp ? KC : pc_left ); \ \ ctype* restrict a_pc = a_jc + pp * pcstep_a; \ ctype* restrict b_pc = b_00 + pp * pcstep_b; \ \ /* Only apply beta to the first iteration of the pc loop. */ \ ctype* restrict beta_use = ( pp == 0 ? &beta_local : &one_local ); \ \ ctype* a_use; \ inc_t rs_a_use, cs_a_use, ps_a_use; \ \ /* Set the bszid_t array and thrinfo_t pointer based on whether we will be packing A. If we won't be packing A, we alias to the _pc variables so that code further down can unconditionally reference the _pa variables. Note that *if* we will be packing A, the thrinfo_t node will have already been created by a previous call to bli_thrinfo_grow(), since bszid values of BLIS_NO_PART cause the tree to grow by two (e.g. to the next bszid that is a normal bszid_t value). */ \ bszid_t* restrict bszids_pa; \ if ( packa ) { bszids_pa = &bszids_pc[1]; \ thread_pa = bli_thrinfo_sub_node( thread_pc ); } \ else { bszids_pa = &bszids_pc[0]; \ thread_pa = thread_pc; } \ \ /* Determine the packing buffer and related parameters for matrix A. (If A will not be packed, then a_use will be set to point to a and the _a_use strides will be set accordingly.) Then call the packm sup variant chooser, which will call the appropriate implementation based on the schema deduced from the stor_id. NOTE: packing matrix A in this panel-block algorithm corresponds to packing matrix B in the block-panel algorithm. */ \ PASTEMAC(ch,packm_sup_a) \ ( \ packa, \ BLIS_BUFFER_FOR_B_PANEL, /* This algorithm packs matrix A to */ \ stor_id, /* a "panel of B". */ \ BLIS_NO_TRANSPOSE, \ NC, KC, /* This "panel of B" is (at most) NC x KC. */ \ nc_cur, kc_cur, MR, \ &one_local, \ a_pc, rs_a, cs_a, \ &a_use, &rs_a_use, &cs_a_use, \ &ps_a_use, \ cntx, \ rntm, \ &mem_a, \ thread_pa \ ); \ \ /* Alias a_use so that it's clear this is our current block of matrix A. */ \ ctype* restrict a_pc_use = a_use; \ \ /* We don't need to embed the panel stride of A within the auxinfo_t object because this variant iterates through A in the jr loop, which occurs here, within the macrokernel, not within the millikernel. */ \ /*bli_auxinfo_set_ps_a( ps_a_use, &aux );*/ \ \ /* Grow the thrinfo_t tree. */ \ bszid_t* restrict bszids_ic = &bszids_pa[1]; \ thread_ic = bli_thrinfo_sub_node( thread_pa ); \ bli_thrinfo_sup_grow( rntm, bszids_ic, thread_ic ); \ \ /* Compute the IC loop thread range for the current thread. */ \ dim_t ic_start, ic_end; \ bli_thread_range_sub( thread_ic, n, NR, FALSE, &ic_start, &ic_end ); \ const dim_t n_local = ic_end - ic_start; \ \ /* Compute number of primary and leftover components of the IC loop. */ \ /*const dim_t ic_iter = ( n_local + MC - 1 ) / MC;*/ \ const dim_t ic_left = n_local % MC; \ \ /* Loop over the n dimension (MC rows at a time). */ \ /*for ( dim_t ii = 0; ii < ic_iter; ii += 1 )*/ \ for ( dim_t ii = ic_start; ii < ic_end; ii += MC ) \ { \ /* Calculate the thread's current IC block dimension. */ \ const dim_t mc_cur = ( MC <= ic_end - ii ? MC : ic_left ); \ \ ctype* restrict b_ic = b_pc + ii * icstep_b; \ ctype* restrict c_ic = c_jc + ii * icstep_c; \ \ ctype* b_use; \ inc_t rs_b_use, cs_b_use, ps_b_use; \ \ /* Set the bszid_t array and thrinfo_t pointer based on whether we will be packing A. If we won't be packing A, we alias to the _pc variables so that code further down can unconditionally reference the _pa variables. Note that *if* we will be packing A, the thrinfo_t node will have already been created by a previous call to bli_thrinfo_grow(), since bszid values of BLIS_NO_PART cause the tree to grow by two (e.g. to the next bszid that is a normal bszid_t value). */ \ bszid_t* restrict bszids_pb; \ if ( packb ) { bszids_pb = &bszids_ic[1]; \ thread_pb = bli_thrinfo_sub_node( thread_ic ); } \ else { bszids_pb = &bszids_ic[0]; \ thread_pb = thread_ic; } \ \ /* Determine the packing buffer and related parameters for matrix B. (If B will not be packed, then b_use will be set to point to b and the _b_use strides will be set accordingly.) Then call the packm sup variant chooser, which will call the appropriate implementation based on the schema deduced from the stor_id. NOTE: packing matrix B in this panel-block algorithm corresponds to packing matrix A in the block-panel algorithm. */ \ PASTEMAC(ch,packm_sup_b) \ ( \ packb, \ BLIS_BUFFER_FOR_A_BLOCK, /* This algorithm packs matrix B to */ \ stor_id, /* a "block of A". */ \ BLIS_NO_TRANSPOSE, \ KC, MC, /* This "block of A" is (at most) KC x MC. */ \ kc_cur, mc_cur, NR, \ &one_local, \ b_ic, rs_b, cs_b, \ &b_use, &rs_b_use, &cs_b_use, \ &ps_b_use, \ cntx, \ rntm, \ &mem_b, \ thread_pb \ ); \ \ /* Alias b_use so that it's clear this is our current block of matrix B. */ \ ctype* restrict b_ic_use = b_use; \ \ /* Embed the panel stride of B within the auxinfo_t object. The millikernel will query and use this to iterate through micropanels of B. */ \ bli_auxinfo_set_ps_b( ps_b_use, &aux ); \ \ /* Grow the thrinfo_t tree. */ \ bszid_t* restrict bszids_jr = &bszids_pb[1]; \ thread_jr = bli_thrinfo_sub_node( thread_pb ); \ bli_thrinfo_sup_grow( rntm, bszids_jr, thread_jr ); \ \ /* Compute number of primary and leftover components of the JR loop. */ \ dim_t jr_iter = ( nc_cur + MR - 1 ) / MR; \ dim_t jr_left = nc_cur % MR; \ \ /* An optimization: allow the last jr iteration to contain up to MRE rows of C and A. (If MRE > MR, the mkernel has agreed to handle these cases.) Note that this prevents us from declaring jr_iter and jr_left as const. NOTE: We forgo this optimization when packing A since packing an extended edge case is not yet supported. */ \ if ( !packa && !is_mt ) \ if ( MRE != 0 && 1 < jr_iter && jr_left != 0 && jr_left <= MRE ) \ { \ jr_iter--; jr_left += MR; \ } \ \ /* Compute the JR loop thread range for the current thread. */ \ dim_t jr_start, jr_end; \ bli_thread_range_sub( thread_jr, jr_iter, 1, FALSE, &jr_start, &jr_end ); \ \ /* Loop over the m dimension (NR columns at a time). */ \ /*for ( dim_t j = 0; j < jr_iter; j += 1 )*/ \ for ( dim_t j = jr_start; j < jr_end; j += 1 ) \ { \ const dim_t nr_cur = ( bli_is_not_edge_f( j, jr_iter, jr_left ) ? MR : jr_left ); \ \ /* ctype* restrict a_jr = a_pc + j * jrstep_a; \ */ \ ctype* restrict a_jr = a_pc_use + j * ps_a_use; \ ctype* restrict c_jr = c_ic + j * jrstep_c; \ \ /* const dim_t ir_iter = ( mc_cur + NR - 1 ) / NR; \ const dim_t ir_left = mc_cur % NR; \ */ \ \ /* Loop over the n dimension (MR rows at a time). */ \ { \ /* Invoke the gemmsup millikernel. */ \ gemmsup_ker \ ( \ conja, \ conjb, \ nr_cur, /* Notice: nr_cur <= MR. */ \ mc_cur, /* Recall: mc_cur partitions the n dimension! */ \ kc_cur, \ alpha_cast, \ a_jr, rs_a_use, cs_a_use, \ b_ic_use, rs_b_use, cs_b_use, \ beta_use, \ c_jr, rs_c, cs_c, \ &aux, \ cntx \ ); \ } \ } \ } \ \ /* NOTE: This barrier is only needed if we are packing A (since that matrix is packed within the pc loop of this variant). */ \ if ( packa ) bli_thread_barrier( thread_pa ); \ } \ } \ \ /* Release any memory that was acquired for packing matrices A and B. */ \ PASTEMAC(ch,packm_sup_finalize_mem_a) \ ( \ packa, \ rntm, \ &mem_a, \ thread_pa \ ); \ PASTEMAC(ch,packm_sup_finalize_mem_b) \ ( \ packb, \ rntm, \ &mem_b, \ thread_pb \ ); \ \ /* PASTEMAC(ch,fprintm)( stdout, "gemmsup_ref_var2: b1", kc_cur, nr_cur, b_jr, rs_b, cs_b, "%4.1f", "" ); \ PASTEMAC(ch,fprintm)( stdout, "gemmsup_ref_var2: a1", mr_cur, kc_cur, a_ir, rs_a, cs_a, "%4.1f", "" ); \ PASTEMAC(ch,fprintm)( stdout, "gemmsup_ref_var2: c ", mr_cur, nr_cur, c_ir, rs_c, cs_c, "%4.1f", "" ); \ */ \ } INSERT_GENTFUNC_BASIC0( gemmsup_ref_var1n ) // // -- var2m -------------------------------------------------------------------- // static FUNCPTR_T GENARRAY(ftypes_var2m,gemmsup_ref_var2m); void bli_gemmsup_ref_var2m ( trans_t trans, obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, stor3_t eff_id, cntx_t* cntx, rntm_t* rntm, thrinfo_t* thread ) { #if 0 obj_t at, bt; bli_obj_alias_to( a, &at ); bli_obj_alias_to( b, &bt ); // Induce transpositions on A and/or B if either object is marked for // transposition. We can induce "fast" transpositions since they objects // are guaranteed to not have structure or be packed. if ( bli_obj_has_trans( &at ) ) { bli_obj_induce_fast_trans( &at ); } if ( bli_obj_has_trans( &bt ) ) { bli_obj_induce_fast_trans( &bt ); } const num_t dt = bli_obj_dt( c ); const conj_t conja = bli_obj_conj_status( a ); const conj_t conjb = bli_obj_conj_status( b ); const dim_t m = bli_obj_length( c ); const dim_t n = bli_obj_width( c ); const dim_t k = bli_obj_width( &at ); void* restrict buf_a = bli_obj_buffer_at_off( &at ); const inc_t rs_a = bli_obj_row_stride( &at ); const inc_t cs_a = bli_obj_col_stride( &at ); void* restrict buf_b = bli_obj_buffer_at_off( &bt ); const inc_t rs_b = bli_obj_row_stride( &bt ); const inc_t cs_b = bli_obj_col_stride( &bt ); void* restrict buf_c = bli_obj_buffer_at_off( c ); const inc_t rs_c = bli_obj_row_stride( c ); const inc_t cs_c = bli_obj_col_stride( c ); void* restrict buf_alpha = bli_obj_buffer_for_1x1( dt, alpha ); void* restrict buf_beta = bli_obj_buffer_for_1x1( dt, beta ); #else const num_t dt = bli_obj_dt( c ); const bool packa = bli_rntm_pack_a( rntm ); const bool packb = bli_rntm_pack_b( rntm ); const conj_t conja = bli_obj_conj_status( a ); const conj_t conjb = bli_obj_conj_status( b ); const dim_t m = bli_obj_length( c ); const dim_t n = bli_obj_width( c ); dim_t k; void* restrict buf_a = bli_obj_buffer_at_off( a ); inc_t rs_a; inc_t cs_a; void* restrict buf_b = bli_obj_buffer_at_off( b ); inc_t rs_b; inc_t cs_b; if ( bli_obj_has_notrans( a ) ) { k = bli_obj_width( a ); rs_a = bli_obj_row_stride( a ); cs_a = bli_obj_col_stride( a ); } else // if ( bli_obj_has_trans( a ) ) { // Assign the variables with an implicit transposition. k = bli_obj_length( a ); rs_a = bli_obj_col_stride( a ); cs_a = bli_obj_row_stride( a ); } if ( bli_obj_has_notrans( b ) ) { rs_b = bli_obj_row_stride( b ); cs_b = bli_obj_col_stride( b ); } else // if ( bli_obj_has_trans( b ) ) { // Assign the variables with an implicit transposition. rs_b = bli_obj_col_stride( b ); cs_b = bli_obj_row_stride( b ); } void* restrict buf_c = bli_obj_buffer_at_off( c ); const inc_t rs_c = bli_obj_row_stride( c ); const inc_t cs_c = bli_obj_col_stride( c ); void* restrict buf_alpha = bli_obj_buffer_for_1x1( dt, alpha ); void* restrict buf_beta = bli_obj_buffer_for_1x1( dt, beta ); #endif // Index into the type combination array to extract the correct // function pointer. FUNCPTR_T f = ftypes_var2m[dt]; #if 1 // Optimize some storage/packing cases by transforming them into others. // These optimizations are expressed by changing trans and/or eff_id. bli_gemmsup_ref_var1n2m_opt_cases( dt, &trans, packa, packb, &eff_id, cntx ); #endif if ( bli_is_notrans( trans ) ) { // Invoke the function. f ( packa, packb, conja, conjb, m, n, k, buf_alpha, buf_a, rs_a, cs_a, buf_b, rs_b, cs_b, buf_beta, buf_c, rs_c, cs_c, eff_id, cntx, rntm, thread ); } else { // Invoke the function (transposing the operation). f ( packb, // swap the pack values. packa, conjb, // swap the conj values. conja, n, // swap the m and n dimensions. m, k, buf_alpha, buf_b, cs_b, rs_b, // swap the positions of A and B. buf_a, cs_a, rs_a, // swap the strides of A and B. buf_beta, buf_c, cs_c, rs_c, // swap the strides of C. bli_stor3_trans( eff_id ), // transpose the stor3_t id. cntx, rntm, thread ); } } #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ bool packa, \ bool packb, \ conj_t conja, \ conj_t conjb, \ dim_t m, \ dim_t n, \ dim_t k, \ void* restrict alpha, \ void* restrict a, inc_t rs_a, inc_t cs_a, \ void* restrict b, inc_t rs_b, inc_t cs_b, \ void* restrict beta, \ void* restrict c, inc_t rs_c, inc_t cs_c, \ stor3_t stor_id, \ cntx_t* restrict cntx, \ rntm_t* restrict rntm, \ thrinfo_t* restrict thread \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ /* If m or n is zero, return immediately. */ \ if ( bli_zero_dim2( m, n ) ) return; \ \ /* If k < 1 or alpha is zero, scale by beta and return. */ \ if ( k < 1 || PASTEMAC(ch,eq0)( *(( ctype* )alpha) ) ) \ { \ if ( bli_thread_am_ochief( thread ) ) \ { \ PASTEMAC(ch,scalm) \ ( \ BLIS_NO_CONJUGATE, \ 0, \ BLIS_NONUNIT_DIAG, \ BLIS_DENSE, \ m, n, \ beta, \ c, rs_c, cs_c \ ); \ } \ return; \ } \ \ /* Query the context for various blocksizes. */ \ const dim_t NR = bli_cntx_get_l3_sup_blksz_def_dt( dt, BLIS_NR, cntx ); \ const dim_t MR = bli_cntx_get_l3_sup_blksz_def_dt( dt, BLIS_MR, cntx ); \ const dim_t NC = bli_cntx_get_l3_sup_blksz_def_dt( dt, BLIS_NC, cntx ); \ const dim_t MC = bli_cntx_get_l3_sup_blksz_def_dt( dt, BLIS_MC, cntx ); \ const dim_t KC0 = bli_cntx_get_l3_sup_blksz_def_dt( dt, BLIS_KC, cntx ); \ \ dim_t KC; \ if ( packa && packb ) \ { \ KC = KC0; \ } \ else if ( packb ) \ { \ if ( stor_id == BLIS_RRR || \ stor_id == BLIS_CCC ) KC = KC0; \ else if ( stor_id == BLIS_RRC || \ stor_id == BLIS_CRC ) KC = KC0; \ else if ( stor_id == BLIS_RCR || \ stor_id == BLIS_CCR ) KC = (( KC0 / 4 ) / 4 ) * 4; \ else KC = KC0; \ } \ else if ( packa ) \ { \ if ( stor_id == BLIS_RRR || \ stor_id == BLIS_CCC ) KC = (( KC0 / 2 ) / 2 ) * 2; \ else if ( stor_id == BLIS_RRC || \ stor_id == BLIS_CRC ) KC = KC0; \ else if ( stor_id == BLIS_RCR || \ stor_id == BLIS_CCR ) KC = (( KC0 / 4 ) / 4 ) * 4; \ else KC = KC0; \ } \ else /* if ( !packa && !packb ) */ \ { \ if ( stor_id == BLIS_RRR || \ stor_id == BLIS_CCC ) KC = KC0; \ else if ( stor_id == BLIS_RRC || \ stor_id == BLIS_CRC ) KC = KC0; \ else if ( m <= MR && n <= NR ) KC = KC0; \ else if ( m <= 2*MR && n <= 2*NR ) KC = KC0 / 2; \ else if ( m <= 3*MR && n <= 3*NR ) KC = (( KC0 / 3 ) / 4 ) * 4; \ else if ( m <= 4*MR && n <= 4*NR ) KC = KC0 / 4; \ else KC = (( KC0 / 5 ) / 4 ) * 4; \ } \ \ /* Query the maximum blocksize for NR, which implies a maximum blocksize extension for the final iteration. */ \ const dim_t NRM = bli_cntx_get_l3_sup_blksz_max_dt( dt, BLIS_NR, cntx ); \ const dim_t NRE = NRM - NR; \ \ /* Compute partitioning step values for each matrix of each loop. */ \ const inc_t jcstep_c = cs_c; \ const inc_t jcstep_b = cs_b; \ \ const inc_t pcstep_a = cs_a; \ const inc_t pcstep_b = rs_b; \ \ const inc_t icstep_c = rs_c; \ const inc_t icstep_a = rs_a; \ \ const inc_t jrstep_c = cs_c * NR; \ \ /* const inc_t jrstep_b = cs_b * NR; \ ( void )jrstep_b; \ \ const inc_t irstep_c = rs_c * MR; \ const inc_t irstep_a = rs_a * MR; \ */ \ \ /* Query the context for the sup microkernel address and cast it to its function pointer type. */ \ PASTECH(ch,gemmsup_ker_ft) \ gemmsup_ker = bli_cntx_get_l3_sup_ker_dt( dt, stor_id, cntx ); \ \ ctype* restrict a_00 = a; \ ctype* restrict b_00 = b; \ ctype* restrict c_00 = c; \ ctype* restrict alpha_cast = alpha; \ ctype* restrict beta_cast = beta; \ \ /* Make local copies of beta and one scalars to prevent any unnecessary sharing of cache lines between the cores' caches. */ \ ctype beta_local = *beta_cast; \ ctype one_local = *PASTEMAC(ch,1); \ \ auxinfo_t aux; \ \ /* Parse and interpret the contents of the rntm_t object to properly set the ways of parallelism for each loop. */ \ /*bli_rntm_set_ways_from_rntm_sup( m, n, k, rntm );*/ \ \ /* Initialize a mem_t entry for A and B. Strictly speaking, this is only needed for the matrix we will be packing (if any), but we do it unconditionally to be safe. An alternative way of initializing the mem_t entries is: bli_mem_clear( &mem_a ); \ bli_mem_clear( &mem_b ); \ */ \ mem_t mem_a = BLIS_MEM_INITIALIZER; \ mem_t mem_b = BLIS_MEM_INITIALIZER; \ \ /* Define an array of bszid_t ids, which will act as our substitute for the cntl_t tree. */ \ /* 5thloop 4thloop packb 3rdloop packa 2ndloop 1stloop ukrloop */ \ bszid_t bszids_nopack[6] = { BLIS_NC, BLIS_KC, BLIS_MC, BLIS_NR, BLIS_MR, BLIS_KR }; \ bszid_t bszids_packa [7] = { BLIS_NC, BLIS_KC, BLIS_MC, BLIS_NO_PART, BLIS_NR, BLIS_MR, BLIS_KR }; \ bszid_t bszids_packb [7] = { BLIS_NC, BLIS_KC, BLIS_NO_PART, BLIS_MC, BLIS_NR, BLIS_MR, BLIS_KR }; \ bszid_t bszids_packab[8] = { BLIS_NC, BLIS_KC, BLIS_NO_PART, BLIS_MC, BLIS_NO_PART, BLIS_NR, BLIS_MR, BLIS_KR }; \ bszid_t* restrict bszids; \ \ /* Set the bszids pointer to the correct bszids array above based on which matrices (if any) are being packed. */ \ if ( packa ) { if ( packb ) bszids = bszids_packab; \ else bszids = bszids_packa; } \ else { if ( packb ) bszids = bszids_packb; \ else bszids = bszids_nopack; } \ \ /* Determine whether we are using more than one thread. */ \ const bool is_mt = ( bli_rntm_calc_num_threads( rntm ) > 1 ); \ \ thrinfo_t* restrict thread_jc = NULL; \ thrinfo_t* restrict thread_pc = NULL; \ thrinfo_t* restrict thread_pb = NULL; \ thrinfo_t* restrict thread_ic = NULL; \ thrinfo_t* restrict thread_pa = NULL; \ thrinfo_t* restrict thread_jr = NULL; \ \ /* Grow the thrinfo_t tree. */ \ bszid_t* restrict bszids_jc = bszids; \ thread_jc = thread; \ bli_thrinfo_sup_grow( rntm, bszids_jc, thread_jc ); \ \ /* Compute the JC loop thread range for the current thread. */ \ dim_t jc_start, jc_end; \ bli_thread_range_sub( thread_jc, n, NR, FALSE, &jc_start, &jc_end ); \ const dim_t n_local = jc_end - jc_start; \ \ /* Compute number of primary and leftover components of the JC loop. */ \ /*const dim_t jc_iter = ( n_local + NC - 1 ) / NC;*/ \ const dim_t jc_left = n_local % NC; \ \ /* Loop over the n dimension (NC rows/columns at a time). */ \ /*for ( dim_t jj = 0; jj < jc_iter; jj += 1 )*/ \ for ( dim_t jj = jc_start; jj < jc_end; jj += NC ) \ { \ /* Calculate the thread's current JC block dimension. */ \ const dim_t nc_cur = ( NC <= jc_end - jj ? NC : jc_left ); \ \ ctype* restrict b_jc = b_00 + jj * jcstep_b; \ ctype* restrict c_jc = c_00 + jj * jcstep_c; \ \ /* Grow the thrinfo_t tree. */ \ bszid_t* restrict bszids_pc = &bszids_jc[1]; \ thread_pc = bli_thrinfo_sub_node( thread_jc ); \ bli_thrinfo_sup_grow( rntm, bszids_pc, thread_pc ); \ \ /* Compute the PC loop thread range for the current thread. */ \ const dim_t pc_start = 0, pc_end = k; \ const dim_t k_local = k; \ \ /* Compute number of primary and leftover components of the PC loop. */ \ /*const dim_t pc_iter = ( k_local + KC - 1 ) / KC;*/ \ const dim_t pc_left = k_local % KC; \ \ /* Loop over the k dimension (KC rows/columns at a time). */ \ /*for ( dim_t pp = 0; pp < pc_iter; pp += 1 )*/ \ for ( dim_t pp = pc_start; pp < pc_end; pp += KC ) \ { \ /* Calculate the thread's current PC block dimension. */ \ const dim_t kc_cur = ( KC <= pc_end - pp ? KC : pc_left ); \ \ ctype* restrict a_pc = a_00 + pp * pcstep_a; \ ctype* restrict b_pc = b_jc + pp * pcstep_b; \ \ /* Only apply beta to the first iteration of the pc loop. */ \ ctype* restrict beta_use = ( pp == 0 ? &beta_local : &one_local ); \ \ ctype* b_use; \ inc_t rs_b_use, cs_b_use, ps_b_use; \ \ /* Set the bszid_t array and thrinfo_t pointer based on whether we will be packing B. If we won't be packing B, we alias to the _pc variables so that code further down can unconditionally reference the _pb variables. Note that *if* we will be packing B, the thrinfo_t node will have already been created by a previous call to bli_thrinfo_grow(), since bszid values of BLIS_NO_PART cause the tree to grow by two (e.g. to the next bszid that is a normal bszid_t value). */ \ bszid_t* restrict bszids_pb; \ if ( packb ) { bszids_pb = &bszids_pc[1]; \ thread_pb = bli_thrinfo_sub_node( thread_pc ); } \ else { bszids_pb = &bszids_pc[0]; \ thread_pb = thread_pc; } \ \ /* Determine the packing buffer and related parameters for matrix B. (If B will not be packed, then a_use will be set to point to b and the _b_use strides will be set accordingly.) Then call the packm sup variant chooser, which will call the appropriate implementation based on the schema deduced from the stor_id. */ \ PASTEMAC(ch,packm_sup_b) \ ( \ packb, \ BLIS_BUFFER_FOR_B_PANEL, /* This algorithm packs matrix B to */ \ stor_id, /* a "panel of B." */ \ BLIS_NO_TRANSPOSE, \ KC, NC, /* This "panel of B" is (at most) KC x NC. */ \ kc_cur, nc_cur, NR, \ &one_local, \ b_pc, rs_b, cs_b, \ &b_use, &rs_b_use, &cs_b_use, \ &ps_b_use, \ cntx, \ rntm, \ &mem_b, \ thread_pb \ ); \ \ /* Alias b_use so that it's clear this is our current block of matrix B. */ \ ctype* restrict b_pc_use = b_use; \ \ /* We don't need to embed the panel stride of B within the auxinfo_t object because this variant iterates through B in the jr loop, which occurs here, within the macrokernel, not within the millikernel. */ \ /*bli_auxinfo_set_ps_b( ps_b_use, &aux );*/ \ \ /* Grow the thrinfo_t tree. */ \ bszid_t* restrict bszids_ic = &bszids_pb[1]; \ thread_ic = bli_thrinfo_sub_node( thread_pb ); \ bli_thrinfo_sup_grow( rntm, bszids_ic, thread_ic ); \ \ /* Compute the IC loop thread range for the current thread. */ \ dim_t ic_start, ic_end; \ bli_thread_range_sub( thread_ic, m, MR, FALSE, &ic_start, &ic_end ); \ const dim_t m_local = ic_end - ic_start; \ \ /* Compute number of primary and leftover components of the IC loop. */ \ /*const dim_t ic_iter = ( m_local + MC - 1 ) / MC;*/ \ const dim_t ic_left = m_local % MC; \ \ /* Loop over the m dimension (MC rows at a time). */ \ /*for ( dim_t ii = 0; ii < ic_iter; ii += 1 )*/ \ for ( dim_t ii = ic_start; ii < ic_end; ii += MC ) \ { \ /* Calculate the thread's current IC block dimension. */ \ const dim_t mc_cur = ( MC <= ic_end - ii ? MC : ic_left ); \ \ ctype* restrict a_ic = a_pc + ii * icstep_a; \ ctype* restrict c_ic = c_jc + ii * icstep_c; \ \ ctype* a_use; \ inc_t rs_a_use, cs_a_use, ps_a_use; \ \ /* Set the bszid_t array and thrinfo_t pointer based on whether we will be packing B. If we won't be packing A, we alias to the _ic variables so that code further down can unconditionally reference the _pa variables. Note that *if* we will be packing A, the thrinfo_t node will have already been created by a previous call to bli_thrinfo_grow(), since bszid values of BLIS_NO_PART cause the tree to grow by two (e.g. to the next bszid that is a normal bszid_t value). */ \ bszid_t* restrict bszids_pa; \ if ( packa ) { bszids_pa = &bszids_ic[1]; \ thread_pa = bli_thrinfo_sub_node( thread_ic ); } \ else { bszids_pa = &bszids_ic[0]; \ thread_pa = thread_ic; } \ \ /* Determine the packing buffer and related parameters for matrix A. (If A will not be packed, then a_use will be set to point to a and the _a_use strides will be set accordingly.) Then call the packm sup variant chooser, which will call the appropriate implementation based on the schema deduced from the stor_id. */ \ PASTEMAC(ch,packm_sup_a) \ ( \ packa, \ BLIS_BUFFER_FOR_A_BLOCK, /* This algorithm packs matrix A to */ \ stor_id, /* a "block of A." */ \ BLIS_NO_TRANSPOSE, \ MC, KC, /* This "block of A" is (at most) MC x KC. */ \ mc_cur, kc_cur, MR, \ &one_local, \ a_ic, rs_a, cs_a, \ &a_use, &rs_a_use, &cs_a_use, \ &ps_a_use, \ cntx, \ rntm, \ &mem_a, \ thread_pa \ ); \ \ /* Alias a_use so that it's clear this is our current block of matrix A. */ \ ctype* restrict a_ic_use = a_use; \ \ /* Embed the panel stride of A within the auxinfo_t object. The millikernel will query and use this to iterate through micropanels of A (if needed). */ \ bli_auxinfo_set_ps_a( ps_a_use, &aux ); \ \ /* Grow the thrinfo_t tree. */ \ bszid_t* restrict bszids_jr = &bszids_pa[1]; \ thread_jr = bli_thrinfo_sub_node( thread_pa ); \ bli_thrinfo_sup_grow( rntm, bszids_jr, thread_jr ); \ \ /* Compute number of primary and leftover components of the JR loop. */ \ dim_t jr_iter = ( nc_cur + NR - 1 ) / NR; \ dim_t jr_left = nc_cur % NR; \ \ /* An optimization: allow the last jr iteration to contain up to NRE columns of C and B. (If NRE > NR, the mkernel has agreed to handle these cases.) Note that this prevents us from declaring jr_iter and jr_left as const. NOTE: We forgo this optimization when packing B since packing an extended edge case is not yet supported. */ \ if ( !packb && !is_mt ) \ if ( NRE != 0 && 1 < jr_iter && jr_left != 0 && jr_left <= NRE ) \ { \ jr_iter--; jr_left += NR; \ } \ \ /* Compute the JR loop thread range for the current thread. */ \ dim_t jr_start, jr_end; \ bli_thread_range_sub( thread_jr, jr_iter, 1, FALSE, &jr_start, &jr_end ); \ \ /* Loop over the n dimension (NR columns at a time). */ \ /*for ( dim_t j = 0; j < jr_iter; j += 1 )*/ \ for ( dim_t j = jr_start; j < jr_end; j += 1 ) \ { \ const dim_t nr_cur = ( bli_is_not_edge_f( j, jr_iter, jr_left ) ? NR : jr_left ); \ \ /* ctype* restrict b_jr = b_pc_use + j * jrstep_b; \ */ \ ctype* restrict b_jr = b_pc_use + j * ps_b_use; \ ctype* restrict c_jr = c_ic + j * jrstep_c; \ \ /* const dim_t ir_iter = ( mc_cur + MR - 1 ) / MR; \ const dim_t ir_left = mc_cur % MR; \ */ \ \ /* Loop over the m dimension (MR rows at a time). */ \ { \ /* Invoke the gemmsup millikernel. */ \ gemmsup_ker \ ( \ conja, \ conjb, \ mc_cur, \ nr_cur, \ kc_cur, \ alpha_cast, \ a_ic_use, rs_a_use, cs_a_use, \ b_jr, rs_b_use, cs_b_use, \ beta_use, \ c_jr, rs_c, cs_c, \ &aux, \ cntx \ ); \ } \ } \ } \ \ /* NOTE: This barrier is only needed if we are packing B (since that matrix is packed within the pc loop of this variant). */ \ if ( packb ) bli_thread_barrier( thread_pb ); \ } \ } \ \ /* Release any memory that was acquired for packing matrices A and B. */ \ PASTEMAC(ch,packm_sup_finalize_mem_a) \ ( \ packa, \ rntm, \ &mem_a, \ thread_pa \ ); \ PASTEMAC(ch,packm_sup_finalize_mem_b) \ ( \ packb, \ rntm, \ &mem_b, \ thread_pb \ ); \ \ /* PASTEMAC(ch,fprintm)( stdout, "gemmsup_ref_var2: b1", kc_cur, nr_cur, b_jr, rs_b, cs_b, "%4.1f", "" ); \ PASTEMAC(ch,fprintm)( stdout, "gemmsup_ref_var2: a1", mr_cur, kc_cur, a_ir, rs_a, cs_a, "%4.1f", "" ); \ PASTEMAC(ch,fprintm)( stdout, "gemmsup_ref_var2: c ", mr_cur, nr_cur, c_ir, rs_c, cs_c, "%4.1f", "" ); \ */ \ } INSERT_GENTFUNC_BASIC0( gemmsup_ref_var2m ) blis-0.9.0/frame/3/bli_l3_sup_vars.h000066400000000000000000000142141422157504600171540ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype object-based interfaces. // #undef GENPROT #define GENPROT( opname ) \ \ void PASTEMAC0(opname) \ ( \ trans_t trans, \ obj_t* alpha, \ obj_t* a, \ obj_t* b, \ obj_t* beta, \ obj_t* c, \ stor3_t eff_id, \ cntx_t* cntx, \ rntm_t* rntm, \ thrinfo_t* thread \ ); GENPROT( gemmsup_ref_var1 ) GENPROT( gemmsup_ref_var2 ) GENPROT( gemmsup_ref_var1n ) GENPROT( gemmsup_ref_var2m ) // // Prototype BLAS-like interfaces with void pointer operands. // #undef GENTPROT #define GENTPROT( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ conj_t conja, \ conj_t conjb, \ dim_t m, \ dim_t n, \ dim_t k, \ void* restrict alpha, \ void* restrict a, inc_t rs_a, inc_t cs_a, \ void* restrict b, inc_t rs_b, inc_t cs_b, \ void* restrict beta, \ void* restrict c, inc_t rs_c, inc_t cs_c, \ stor3_t eff_id, \ cntx_t* restrict cntx, \ rntm_t* restrict rntm, \ thrinfo_t* restrict thread \ ); INSERT_GENTPROT_BASIC0( gemmsup_ref_var1 ) INSERT_GENTPROT_BASIC0( gemmsup_ref_var2 ) #undef GENTPROT #define GENTPROT( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ bool packa, \ bool packb, \ conj_t conja, \ conj_t conjb, \ dim_t m, \ dim_t n, \ dim_t k, \ void* restrict alpha, \ void* restrict a, inc_t rs_a, inc_t cs_a, \ void* restrict b, inc_t rs_b, inc_t cs_b, \ void* restrict beta, \ void* restrict c, inc_t rs_c, inc_t cs_c, \ stor3_t eff_id, \ cntx_t* restrict cntx, \ rntm_t* restrict rntm, \ thrinfo_t* restrict thread \ ); INSERT_GENTPROT_BASIC0( gemmsup_ref_var1n ) INSERT_GENTPROT_BASIC0( gemmsup_ref_var2m ) // ----------------------------------------------------------------------------- BLIS_INLINE void bli_gemmsup_ref_var1n2m_opt_cases ( num_t dt, trans_t* trans, bool packa, bool packb, stor3_t* eff_id, cntx_t* cntx ) { const bool row_pref = bli_cntx_l3_sup_ker_prefers_rows_dt( dt, *eff_id, cntx ); // Handle row- and column-preferrential kernels separately. if ( row_pref ) { if ( packa && packb ) { if ( *eff_id == BLIS_RRC ) { // Since C is already row-stored, we can use BLIS_RRR kernel instead. *eff_id = BLIS_RRR; } else if ( *eff_id == BLIS_CRC ) { // BLIS_RRC when transposed below (both matrices still packed). // This allows us to use the BLIS_RRR kernel instead. *eff_id = BLIS_CCC; // BLIS_RRR when transposed below. } else if ( *eff_id == BLIS_CRR ) { // Induce a transpose to make C row-stored. // BLIS_RCC when transposed below (both matrices still packed). // This allows us to use the BLIS_RRR kernel instead. *trans = bli_trans_toggled( *trans ); *eff_id = BLIS_CCC; // BLIS_RRR when transposed below. } } else if ( packb ) { if ( *eff_id == BLIS_RRC ) { // Since C is already row-stored, we can use BLIS_RRR kernel instead. *eff_id = BLIS_RRR; } else if ( *eff_id == BLIS_CRC ) { // BLIS_RRC when transposed below (with packa instead of packb). // No transformation is beneficial here. } else if ( *eff_id == BLIS_RCC ) { // C is already row-stored; cancel transposition and use BLIS_RCR // kernel instead. *trans = bli_trans_toggled( *trans ); *eff_id = BLIS_RCR; } #if 0 // This transformation performs poorly. Theory: packing A (formerly B) // when eff_id == BLIS_RCC (formerly BLIS_CRR) to row storage is slow // and kills the performance? else if ( eff_id == BLIS_CRR ) { trans = bli_trans_toggled( trans ); eff_id = BLIS_CRC; // BLIS_RRC when transposed below. } #endif } else if ( packa ) { if ( *eff_id == BLIS_CRR ) { // Induce a transpose to make C row-stored. // BLIS_RCC when transposed below (both matrices still packed). // This allows us to use the BLIS_RRR kernel instead. *trans = bli_trans_toggled( *trans ); *eff_id = BLIS_CCR; // BLIS_RCR when transposed below. } } } else { //bli_check_error_code( BLIS_NOT_YET_IMPLEMENTED ); printf( "libblis: sup var1n2m_opt_cases not yet implemented for column-preferential kernels.\n" ); bli_abort(); } } blis-0.9.0/frame/3/bli_l3_tapi.c000066400000000000000000000201701422157504600162400ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2021, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // Define BLAS-like interfaces with typed operands (basic). // #undef GENTFUNC #define GENTFUNC( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ trans_t transa, \ trans_t transb, \ dim_t m, \ dim_t n, \ dim_t k, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* b, inc_t rs_b, inc_t cs_b, \ ctype* beta, \ ctype* c, inc_t rs_c, inc_t cs_c \ ) \ { \ /* Invoke the expert interface and request default cntx_t and rntm_t objects. */ \ PASTEMAC2(ch,opname,BLIS_TAPI_EX_SUF) \ ( \ transa, \ transb, \ m, n, k, \ alpha, \ a, rs_a, cs_a, \ b, rs_b, cs_b, \ beta, \ c, rs_c, cs_c, \ NULL, \ NULL \ ); \ } INSERT_GENTFUNC_BASIC0( gemm ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ uplo_t uploc, \ trans_t transa, \ trans_t transb, \ dim_t m, \ dim_t k, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* b, inc_t rs_b, inc_t cs_b, \ ctype* beta, \ ctype* c, inc_t rs_c, inc_t cs_c \ ) \ { \ /* Invoke the expert interface and request default cntx_t and rntm_t objects. */ \ PASTEMAC2(ch,opname,BLIS_TAPI_EX_SUF) \ ( \ uploc, \ transa, \ transb, \ m, k, \ alpha, \ a, rs_a, cs_a, \ b, rs_b, cs_b, \ beta, \ c, rs_c, cs_c, \ NULL, \ NULL \ ); \ } INSERT_GENTFUNC_BASIC0( gemmt ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, struca ) \ \ void PASTEMAC(ch,opname) \ ( \ side_t side, \ uplo_t uploa, \ conj_t conja, \ trans_t transb, \ dim_t m, \ dim_t n, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* b, inc_t rs_b, inc_t cs_b, \ ctype* beta, \ ctype* c, inc_t rs_c, inc_t cs_c \ ) \ { \ /* Invoke the expert interface and request default cntx_t and rntm_t objects. */ \ PASTEMAC2(ch,opname,BLIS_TAPI_EX_SUF) \ ( \ side, \ uploa, \ conja, \ transb, \ m, n, \ alpha, \ a, rs_a, cs_a, \ b, rs_b, cs_b, \ beta, \ c, rs_c, cs_c, \ NULL, \ NULL \ ); \ } INSERT_GENTFUNC_BASIC( hemm, BLIS_HERMITIAN ) INSERT_GENTFUNC_BASIC( symm, BLIS_SYMMETRIC ) #undef GENTFUNCR #define GENTFUNCR( ctype, ctype_r, ch, chr, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ uplo_t uploc, \ trans_t transa, \ dim_t m, \ dim_t k, \ ctype_r* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype_r* beta, \ ctype* c, inc_t rs_c, inc_t cs_c \ ) \ { \ /* Invoke the expert interface and request default cntx_t and rntm_t objects. */ \ PASTEMAC2(ch,opname,BLIS_TAPI_EX_SUF) \ ( \ uploc, \ transa, \ m, k, \ alpha, \ a, rs_a, cs_a, \ beta, \ c, rs_c, cs_c, \ NULL, \ NULL \ ); \ } INSERT_GENTFUNCR_BASIC0( herk ) #undef GENTFUNCR #define GENTFUNCR( ctype, ctype_r, ch, chr, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ uplo_t uploc, \ trans_t transa, \ trans_t transb, \ dim_t m, \ dim_t k, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* b, inc_t rs_b, inc_t cs_b, \ ctype_r* beta, \ ctype* c, inc_t rs_c, inc_t cs_c \ ) \ { \ /* Invoke the expert interface and request default cntx_t and rntm_t objects. */ \ PASTEMAC2(ch,opname,BLIS_TAPI_EX_SUF) \ ( \ uploc, \ transa, \ transb, \ m, k, \ alpha, \ a, rs_a, cs_a, \ b, rs_b, cs_b, \ beta, \ c, rs_c, cs_c, \ NULL, \ NULL \ ); \ } INSERT_GENTFUNCR_BASIC0( her2k ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ uplo_t uploc, \ trans_t transa, \ dim_t m, \ dim_t k, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* beta, \ ctype* c, inc_t rs_c, inc_t cs_c \ ) \ { \ /* Invoke the expert interface and request default cntx_t and rntm_t objects. */ \ PASTEMAC2(ch,opname,BLIS_TAPI_EX_SUF) \ ( \ uploc, \ transa, \ m, k, \ alpha, \ a, rs_a, cs_a, \ beta, \ c, rs_c, cs_c, \ NULL, \ NULL \ ); \ } INSERT_GENTFUNC_BASIC0( syrk ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ uplo_t uploc, \ trans_t transa, \ trans_t transb, \ dim_t m, \ dim_t k, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* b, inc_t rs_b, inc_t cs_b, \ ctype* beta, \ ctype* c, inc_t rs_c, inc_t cs_c \ ) \ { \ /* Invoke the expert interface and request default cntx_t and rntm_t objects. */ \ PASTEMAC2(ch,opname,BLIS_TAPI_EX_SUF) \ ( \ uploc, \ transa, \ transb, \ m, k, \ alpha, \ a, rs_a, cs_a, \ b, rs_b, cs_b, \ beta, \ c, rs_c, cs_c, \ NULL, \ NULL \ ); \ } INSERT_GENTFUNC_BASIC0( syr2k ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ side_t side, \ uplo_t uploa, \ trans_t transa, \ diag_t diaga, \ trans_t transb, \ dim_t m, \ dim_t n, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* b, inc_t rs_b, inc_t cs_b, \ ctype* beta, \ ctype* c, inc_t rs_c, inc_t cs_c \ ) \ { \ /* Invoke the expert interface and request default cntx_t and rntm_t objects. */ \ PASTEMAC2(ch,opname,BLIS_TAPI_EX_SUF) \ ( \ side, \ uploa, \ transa, \ diaga, \ transb, \ m, n, \ alpha, \ a, rs_a, cs_a, \ b, rs_b, cs_b, \ beta, \ c, rs_c, cs_c, \ NULL, \ NULL \ ); \ } INSERT_GENTFUNC_BASIC0( trmm3 ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ side_t side, \ uplo_t uploa, \ trans_t transa, \ diag_t diaga, \ dim_t m, \ dim_t n, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* b, inc_t rs_b, inc_t cs_b \ ) \ { \ /* Invoke the expert interface and request default cntx_t and rntm_t objects. */ \ PASTEMAC2(ch,opname,BLIS_TAPI_EX_SUF) \ ( \ side, \ uploa, \ transa, \ diaga, \ m, n, \ alpha, \ a, rs_a, cs_a, \ b, rs_b, cs_b, \ NULL, \ NULL \ ); \ } INSERT_GENTFUNC_BASIC0( trmm ) INSERT_GENTFUNC_BASIC0( trsm ) blis-0.9.0/frame/3/bli_l3_tapi.h000066400000000000000000000124311422157504600162460ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype BLAS-like interfaces with typed operands (basic). // #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC(ch,opname) \ ( \ trans_t transa, \ trans_t transb, \ dim_t m, \ dim_t n, \ dim_t k, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* b, inc_t rs_b, inc_t cs_b, \ ctype* beta, \ ctype* c, inc_t rs_c, inc_t cs_c \ ); INSERT_GENTPROT_BASIC0( gemm ) #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC(ch,opname) \ ( \ side_t side, \ uplo_t uploa, \ conj_t conja, \ trans_t transb, \ dim_t m, \ dim_t n, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* b, inc_t rs_b, inc_t cs_b, \ ctype* beta, \ ctype* c, inc_t rs_c, inc_t cs_c \ ); INSERT_GENTPROT_BASIC0( hemm ) INSERT_GENTPROT_BASIC0( symm ) #undef GENTPROTR #define GENTPROTR( ctype, ctype_r, ch, chr, opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC(ch,opname) \ ( \ uplo_t uploc, \ trans_t transa, \ dim_t m, \ dim_t k, \ ctype_r* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype_r* beta, \ ctype* c, inc_t rs_c, inc_t cs_c \ ); INSERT_GENTPROTR_BASIC0( herk ) #undef GENTPROTR #define GENTPROTR( ctype, ctype_r, ch, chr, opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC(ch,opname) \ ( \ uplo_t uploc, \ trans_t transa, \ trans_t transb, \ dim_t m, \ dim_t k, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* b, inc_t rs_b, inc_t cs_b, \ ctype_r* beta, \ ctype* c, inc_t rs_c, inc_t cs_c \ ); INSERT_GENTPROTR_BASIC0( her2k ) #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC(ch,opname) \ ( \ uplo_t uploc, \ trans_t transa, \ dim_t m, \ dim_t k, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* beta, \ ctype* c, inc_t rs_c, inc_t cs_c \ ); INSERT_GENTPROT_BASIC0( syrk ) #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC(ch,opname) \ ( \ uplo_t uploc, \ trans_t transa, \ trans_t transb, \ dim_t m, \ dim_t k, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* b, inc_t rs_b, inc_t cs_b, \ ctype* beta, \ ctype* c, inc_t rs_c, inc_t cs_c \ ); INSERT_GENTPROT_BASIC0( gemmt ) INSERT_GENTPROT_BASIC0( syr2k ) #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC(ch,opname) \ ( \ side_t side, \ uplo_t uploa, \ trans_t transa, \ diag_t diaga, \ trans_t transb, \ dim_t m, \ dim_t n, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* b, inc_t rs_b, inc_t cs_b, \ ctype* beta, \ ctype* c, inc_t rs_c, inc_t cs_c \ ); INSERT_GENTPROT_BASIC0( trmm3 ) #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC(ch,opname) \ ( \ side_t side, \ uplo_t uploa, \ trans_t transa, \ diag_t diaga, \ dim_t m, \ dim_t n, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* b, inc_t rs_b, inc_t cs_b \ ); INSERT_GENTPROT_BASIC0( trmm ) INSERT_GENTPROT_BASIC0( trsm ) blis-0.9.0/frame/3/bli_l3_tapi_ex.c000066400000000000000000000354121422157504600167410ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // Define BLAS-like interfaces with typed operands (expert). // #undef GENTFUNC #define GENTFUNC( ctype, ch, opname ) \ \ void PASTEMAC2(ch,opname,BLIS_OAPI_EX_SUF) \ ( \ trans_t transa, \ trans_t transb, \ dim_t m, \ dim_t n, \ dim_t k, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* b, inc_t rs_b, inc_t cs_b, \ ctype* beta, \ ctype* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx, \ rntm_t* rntm \ ) \ { \ bli_init_once(); \ \ const num_t dt = PASTEMAC(ch,type); \ \ obj_t alphao = BLIS_OBJECT_INITIALIZER_1X1; \ obj_t ao = BLIS_OBJECT_INITIALIZER; \ obj_t bo = BLIS_OBJECT_INITIALIZER; \ obj_t betao = BLIS_OBJECT_INITIALIZER_1X1; \ obj_t co = BLIS_OBJECT_INITIALIZER; \ \ dim_t m_a, n_a; \ dim_t m_b, n_b; \ \ bli_set_dims_with_trans( transa, m, k, &m_a, &n_a ); \ bli_set_dims_with_trans( transb, k, n, &m_b, &n_b ); \ \ bli_obj_init_finish_1x1( dt, alpha, &alphao ); \ bli_obj_init_finish_1x1( dt, beta, &betao ); \ \ bli_obj_init_finish( dt, m_a, n_a, a, rs_a, cs_a, &ao ); \ bli_obj_init_finish( dt, m_b, n_b, b, rs_b, cs_b, &bo ); \ bli_obj_init_finish( dt, m, n, c, rs_c, cs_c, &co ); \ \ bli_obj_set_conjtrans( transa, &ao ); \ bli_obj_set_conjtrans( transb, &bo ); \ \ PASTEMAC(opname,BLIS_OAPI_EX_SUF) \ ( \ &alphao, \ &ao, \ &bo, \ &betao, \ &co, \ cntx, \ rntm \ ); \ } INSERT_GENTFUNC_BASIC0( gemm ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, struca ) \ \ void PASTEMAC2(ch,opname,BLIS_OAPI_EX_SUF) \ ( \ side_t side, \ uplo_t uploa, \ conj_t conja, \ trans_t transb, \ dim_t m, \ dim_t n, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* b, inc_t rs_b, inc_t cs_b, \ ctype* beta, \ ctype* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx, \ rntm_t* rntm \ ) \ { \ bli_init_once(); \ \ const num_t dt = PASTEMAC(ch,type); \ \ obj_t alphao = BLIS_OBJECT_INITIALIZER_1X1; \ obj_t ao = BLIS_OBJECT_INITIALIZER; \ obj_t bo = BLIS_OBJECT_INITIALIZER; \ obj_t betao = BLIS_OBJECT_INITIALIZER_1X1; \ obj_t co = BLIS_OBJECT_INITIALIZER; \ \ dim_t mn_a; \ dim_t m_b, n_b; \ \ bli_set_dim_with_side( side, m, n, &mn_a ); \ bli_set_dims_with_trans( transb, m, n, &m_b, &n_b ); \ \ bli_obj_init_finish_1x1( dt, alpha, &alphao ); \ bli_obj_init_finish_1x1( dt, beta, &betao ); \ \ bli_obj_init_finish( dt, mn_a, mn_a, a, rs_a, cs_a, &ao ); \ bli_obj_init_finish( dt, m_b, n_b, b, rs_b, cs_b, &bo ); \ bli_obj_init_finish( dt, m, n, c, rs_c, cs_c, &co ); \ \ bli_obj_set_uplo( uploa, &ao ); \ bli_obj_set_conj( conja, &ao ); \ bli_obj_set_conjtrans( transb, &bo ); \ \ bli_obj_set_struc( struca, &ao ); \ \ PASTEMAC(opname,BLIS_OAPI_EX_SUF) \ ( \ side, \ &alphao, \ &ao, \ &bo, \ &betao, \ &co, \ cntx, \ rntm \ ); \ } INSERT_GENTFUNC_BASIC( hemm, BLIS_HERMITIAN ) INSERT_GENTFUNC_BASIC( symm, BLIS_SYMMETRIC ) #undef GENTFUNCR #define GENTFUNCR( ctype, ctype_r, ch, chr, opname ) \ \ void PASTEMAC2(ch,opname,BLIS_OAPI_EX_SUF) \ ( \ uplo_t uploc, \ trans_t transa, \ dim_t m, \ dim_t k, \ ctype_r* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype_r* beta, \ ctype* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx, \ rntm_t* rntm \ ) \ { \ bli_init_once(); \ \ const num_t dt_r = PASTEMAC(chr,type); \ const num_t dt = PASTEMAC(ch,type); \ \ obj_t alphao = BLIS_OBJECT_INITIALIZER_1X1; \ obj_t ao = BLIS_OBJECT_INITIALIZER; \ obj_t betao = BLIS_OBJECT_INITIALIZER_1X1; \ obj_t co = BLIS_OBJECT_INITIALIZER; \ \ dim_t m_a, n_a; \ \ bli_set_dims_with_trans( transa, m, k, &m_a, &n_a ); \ \ bli_obj_init_finish_1x1( dt_r, alpha, &alphao ); \ bli_obj_init_finish_1x1( dt_r, beta, &betao ); \ \ bli_obj_init_finish( dt, m_a, n_a, a, rs_a, cs_a, &ao ); \ bli_obj_init_finish( dt, m, m, c, rs_c, cs_c, &co ); \ \ bli_obj_set_uplo( uploc, &co ); \ bli_obj_set_conjtrans( transa, &ao ); \ \ bli_obj_set_struc( BLIS_HERMITIAN, &co ); \ \ PASTEMAC(opname,BLIS_OAPI_EX_SUF) \ ( \ &alphao, \ &ao, \ &betao, \ &co, \ cntx, \ rntm \ ); \ } INSERT_GENTFUNCR_BASIC0( herk ) #undef GENTFUNCR #define GENTFUNCR( ctype, ctype_r, ch, chr, opname ) \ \ void PASTEMAC2(ch,opname,BLIS_OAPI_EX_SUF) \ ( \ uplo_t uploc, \ trans_t transa, \ trans_t transb, \ dim_t m, \ dim_t k, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* b, inc_t rs_b, inc_t cs_b, \ ctype_r* beta, \ ctype* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx, \ rntm_t* rntm \ ) \ { \ bli_init_once(); \ \ const num_t dt_r = PASTEMAC(chr,type); \ const num_t dt = PASTEMAC(ch,type); \ \ obj_t alphao = BLIS_OBJECT_INITIALIZER_1X1; \ obj_t ao = BLIS_OBJECT_INITIALIZER; \ obj_t bo = BLIS_OBJECT_INITIALIZER; \ obj_t betao = BLIS_OBJECT_INITIALIZER_1X1; \ obj_t co = BLIS_OBJECT_INITIALIZER; \ \ dim_t m_a, n_a; \ dim_t m_b, n_b; \ \ bli_set_dims_with_trans( transa, m, k, &m_a, &n_a ); \ bli_set_dims_with_trans( transb, m, k, &m_b, &n_b ); \ \ bli_obj_init_finish_1x1( dt, alpha, &alphao ); \ bli_obj_init_finish_1x1( dt_r, beta, &betao ); \ \ bli_obj_init_finish( dt, m_a, n_a, a, rs_a, cs_a, &ao ); \ bli_obj_init_finish( dt, m_b, n_b, b, rs_b, cs_b, &bo ); \ bli_obj_init_finish( dt, m, m, c, rs_c, cs_c, &co ); \ \ bli_obj_set_uplo( uploc, &co ); \ bli_obj_set_conjtrans( transa, &ao ); \ bli_obj_set_conjtrans( transb, &bo ); \ \ bli_obj_set_struc( BLIS_HERMITIAN, &co ); \ \ PASTEMAC(opname,BLIS_OAPI_EX_SUF) \ ( \ &alphao, \ &ao, \ &bo, \ &betao, \ &co, \ cntx, \ rntm \ ); \ } INSERT_GENTFUNCR_BASIC0( her2k ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname ) \ \ void PASTEMAC2(ch,opname,BLIS_OAPI_EX_SUF) \ ( \ uplo_t uploc, \ trans_t transa, \ dim_t m, \ dim_t k, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* beta, \ ctype* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx, \ rntm_t* rntm \ ) \ { \ bli_init_once(); \ \ const num_t dt = PASTEMAC(ch,type); \ \ obj_t alphao = BLIS_OBJECT_INITIALIZER_1X1; \ obj_t ao = BLIS_OBJECT_INITIALIZER; \ obj_t betao = BLIS_OBJECT_INITIALIZER_1X1; \ obj_t co = BLIS_OBJECT_INITIALIZER; \ \ dim_t m_a, n_a; \ \ bli_set_dims_with_trans( transa, m, k, &m_a, &n_a ); \ \ bli_obj_init_finish_1x1( dt, alpha, &alphao ); \ bli_obj_init_finish_1x1( dt, beta, &betao ); \ \ bli_obj_init_finish( dt, m_a, n_a, a, rs_a, cs_a, &ao ); \ bli_obj_init_finish( dt, m, m, c, rs_c, cs_c, &co ); \ \ bli_obj_set_uplo( uploc, &co ); \ bli_obj_set_conjtrans( transa, &ao ); \ \ bli_obj_set_struc( BLIS_SYMMETRIC, &co ); \ \ PASTEMAC(opname,BLIS_OAPI_EX_SUF) \ ( \ &alphao, \ &ao, \ &betao, \ &co, \ cntx, \ rntm \ ); \ } INSERT_GENTFUNC_BASIC0( syrk ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname ) \ \ void PASTEMAC2(ch,opname,BLIS_OAPI_EX_SUF) \ ( \ uplo_t uploc, \ trans_t transa, \ trans_t transb, \ dim_t m, \ dim_t k, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* b, inc_t rs_b, inc_t cs_b, \ ctype* beta, \ ctype* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx, \ rntm_t* rntm \ ) \ { \ bli_init_once(); \ \ const num_t dt = PASTEMAC(ch,type); \ \ obj_t alphao = BLIS_OBJECT_INITIALIZER_1X1; \ obj_t ao = BLIS_OBJECT_INITIALIZER; \ obj_t bo = BLIS_OBJECT_INITIALIZER; \ obj_t betao = BLIS_OBJECT_INITIALIZER_1X1; \ obj_t co = BLIS_OBJECT_INITIALIZER; \ \ dim_t m_a, n_a; \ dim_t m_b, n_b; \ \ bli_set_dims_with_trans( transa, m, k, &m_a, &n_a ); \ bli_set_dims_with_trans( transb, m, k, &m_b, &n_b ); \ \ bli_obj_init_finish_1x1( dt, alpha, &alphao ); \ bli_obj_init_finish_1x1( dt, beta, &betao ); \ \ bli_obj_init_finish( dt, m_a, n_a, a, rs_a, cs_a, &ao ); \ bli_obj_init_finish( dt, m_b, n_b, b, rs_b, cs_b, &bo ); \ bli_obj_init_finish( dt, m, m, c, rs_c, cs_c, &co ); \ \ bli_obj_set_uplo( uploc, &co ); \ bli_obj_set_conjtrans( transa, &ao ); \ bli_obj_set_conjtrans( transb, &bo ); \ \ bli_obj_set_struc( BLIS_SYMMETRIC, &co ); \ \ PASTEMAC(opname,BLIS_OAPI_EX_SUF) \ ( \ &alphao, \ &ao, \ &bo, \ &betao, \ &co, \ cntx, \ rntm \ ); \ } INSERT_GENTFUNC_BASIC0( syr2k ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname ) \ \ void PASTEMAC2(ch,opname,BLIS_OAPI_EX_SUF) \ ( \ uplo_t uploc, \ trans_t transa, \ trans_t transb, \ dim_t m, \ dim_t k, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* b, inc_t rs_b, inc_t cs_b, \ ctype* beta, \ ctype* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx, \ rntm_t* rntm \ ) \ { \ bli_init_once(); \ \ const num_t dt = PASTEMAC(ch,type); \ \ obj_t alphao = BLIS_OBJECT_INITIALIZER_1X1; \ obj_t ao = BLIS_OBJECT_INITIALIZER; \ obj_t bo = BLIS_OBJECT_INITIALIZER; \ obj_t betao = BLIS_OBJECT_INITIALIZER_1X1; \ obj_t co = BLIS_OBJECT_INITIALIZER; \ \ dim_t m_a, n_a; \ dim_t m_b, n_b; \ \ bli_set_dims_with_trans( transa, m, k, &m_a, &n_a ); \ bli_set_dims_with_trans( transb, k, m, &m_b, &n_b ); \ \ bli_obj_init_finish_1x1( dt, alpha, &alphao ); \ bli_obj_init_finish_1x1( dt, beta, &betao ); \ \ bli_obj_init_finish( dt, m_a, n_a, a, rs_a, cs_a, &ao ); \ bli_obj_init_finish( dt, m_b, n_b, b, rs_b, cs_b, &bo ); \ bli_obj_init_finish( dt, m, m, c, rs_c, cs_c, &co ); \ \ bli_obj_set_uplo( uploc, &co ); \ bli_obj_set_conjtrans( transa, &ao ); \ bli_obj_set_conjtrans( transb, &bo ); \ \ PASTEMAC(opname,BLIS_OAPI_EX_SUF) \ ( \ &alphao, \ &ao, \ &bo, \ &betao, \ &co, \ cntx, \ rntm \ ); \ } INSERT_GENTFUNC_BASIC0( gemmt ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname ) \ \ void PASTEMAC2(ch,opname,BLIS_OAPI_EX_SUF) \ ( \ side_t side, \ uplo_t uploa, \ trans_t transa, \ diag_t diaga, \ trans_t transb, \ dim_t m, \ dim_t n, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* b, inc_t rs_b, inc_t cs_b, \ ctype* beta, \ ctype* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx, \ rntm_t* rntm \ ) \ { \ bli_init_once(); \ \ const num_t dt = PASTEMAC(ch,type); \ \ obj_t alphao = BLIS_OBJECT_INITIALIZER_1X1; \ obj_t ao = BLIS_OBJECT_INITIALIZER; \ obj_t bo = BLIS_OBJECT_INITIALIZER; \ obj_t betao = BLIS_OBJECT_INITIALIZER_1X1; \ obj_t co = BLIS_OBJECT_INITIALIZER; \ \ dim_t mn_a; \ dim_t m_b, n_b; \ \ bli_set_dim_with_side( side, m, n, &mn_a ); \ bli_set_dims_with_trans( transb, m, n, &m_b, &n_b ); \ \ bli_obj_init_finish_1x1( dt, alpha, &alphao ); \ bli_obj_init_finish_1x1( dt, beta, &betao ); \ \ bli_obj_init_finish( dt, mn_a, mn_a, a, rs_a, cs_a, &ao ); \ bli_obj_init_finish( dt, m_b, n_b, b, rs_b, cs_b, &bo ); \ bli_obj_init_finish( dt, m, n, c, rs_c, cs_c, &co ); \ \ bli_obj_set_uplo( uploa, &ao ); \ bli_obj_set_diag( diaga, &ao ); \ bli_obj_set_conjtrans( transa, &ao ); \ bli_obj_set_conjtrans( transb, &bo ); \ \ bli_obj_set_struc( BLIS_TRIANGULAR, &ao ); \ \ PASTEMAC(opname,BLIS_OAPI_EX_SUF) \ ( \ side, \ &alphao, \ &ao, \ &bo, \ &betao, \ &co, \ cntx, \ rntm \ ); \ } INSERT_GENTFUNC_BASIC0( trmm3 ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname ) \ \ void PASTEMAC2(ch,opname,BLIS_OAPI_EX_SUF) \ ( \ side_t side, \ uplo_t uploa, \ trans_t transa, \ diag_t diaga, \ dim_t m, \ dim_t n, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* b, inc_t rs_b, inc_t cs_b, \ cntx_t* cntx, \ rntm_t* rntm \ ) \ { \ bli_init_once(); \ \ const num_t dt = PASTEMAC(ch,type); \ \ obj_t alphao = BLIS_OBJECT_INITIALIZER_1X1; \ obj_t ao = BLIS_OBJECT_INITIALIZER; \ obj_t bo = BLIS_OBJECT_INITIALIZER; \ \ dim_t mn_a; \ \ bli_set_dim_with_side( side, m, n, &mn_a ); \ \ bli_obj_init_finish_1x1( dt, alpha, &alphao ); \ \ bli_obj_init_finish( dt, mn_a, mn_a, a, rs_a, cs_a, &ao ); \ bli_obj_init_finish( dt, m, n, b, rs_b, cs_b, &bo ); \ \ bli_obj_set_uplo( uploa, &ao ); \ bli_obj_set_diag( diaga, &ao ); \ bli_obj_set_conjtrans( transa, &ao ); \ \ bli_obj_set_struc( BLIS_TRIANGULAR, &ao ); \ \ PASTEMAC(opname,BLIS_OAPI_EX_SUF) \ ( \ side, \ &alphao, \ &ao, \ &bo, \ cntx, \ rntm \ ); \ } INSERT_GENTFUNC_BASIC0( trmm ) INSERT_GENTFUNC_BASIC0( trsm ) blis-0.9.0/frame/3/bli_l3_tapi_ex.h000066400000000000000000000134361422157504600167500ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype BLAS-like interfaces with typed operands (expert). // #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC2(ch,opname,BLIS_TAPI_EX_SUF) \ ( \ trans_t transa, \ trans_t transb, \ dim_t m, \ dim_t n, \ dim_t k, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* b, inc_t rs_b, inc_t cs_b, \ ctype* beta, \ ctype* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx, \ rntm_t* rntm \ ); INSERT_GENTPROT_BASIC0( gemm ) #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC2(ch,opname,BLIS_TAPI_EX_SUF) \ ( \ side_t side, \ uplo_t uploa, \ conj_t conja, \ trans_t transb, \ dim_t m, \ dim_t n, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* b, inc_t rs_b, inc_t cs_b, \ ctype* beta, \ ctype* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx, \ rntm_t* rntm \ ); INSERT_GENTPROT_BASIC0( hemm ) INSERT_GENTPROT_BASIC0( symm ) #undef GENTPROTR #define GENTPROTR( ctype, ctype_r, ch, chr, opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC2(ch,opname,BLIS_TAPI_EX_SUF) \ ( \ uplo_t uploc, \ trans_t transa, \ dim_t m, \ dim_t k, \ ctype_r* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype_r* beta, \ ctype* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx, \ rntm_t* rntm \ ); INSERT_GENTPROTR_BASIC0( herk ) #undef GENTPROTR #define GENTPROTR( ctype, ctype_r, ch, chr, opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC2(ch,opname,BLIS_TAPI_EX_SUF) \ ( \ uplo_t uploc, \ trans_t transa, \ trans_t transb, \ dim_t m, \ dim_t k, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* b, inc_t rs_b, inc_t cs_b, \ ctype_r* beta, \ ctype* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx, \ rntm_t* rntm \ ); INSERT_GENTPROTR_BASIC0( her2k ) #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC2(ch,opname,BLIS_TAPI_EX_SUF) \ ( \ uplo_t uploc, \ trans_t transa, \ dim_t m, \ dim_t k, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* beta, \ ctype* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx, \ rntm_t* rntm \ ); INSERT_GENTPROT_BASIC0( syrk ) #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC2(ch,opname,BLIS_TAPI_EX_SUF) \ ( \ uplo_t uploc, \ trans_t transa, \ trans_t transb, \ dim_t m, \ dim_t k, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* b, inc_t rs_b, inc_t cs_b, \ ctype* beta, \ ctype* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx, \ rntm_t* rntm \ ); INSERT_GENTPROT_BASIC0( gemmt ) INSERT_GENTPROT_BASIC0( syr2k ) #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC2(ch,opname,BLIS_TAPI_EX_SUF) \ ( \ side_t side, \ uplo_t uploa, \ trans_t transa, \ diag_t diaga, \ trans_t transb, \ dim_t m, \ dim_t n, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* b, inc_t rs_b, inc_t cs_b, \ ctype* beta, \ ctype* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx, \ rntm_t* rntm \ ); INSERT_GENTPROT_BASIC0( trmm3 ) #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC2(ch,opname,BLIS_TAPI_EX_SUF) \ ( \ side_t side, \ uplo_t uploa, \ trans_t transa, \ diag_t diaga, \ dim_t m, \ dim_t n, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* b, inc_t rs_b, inc_t cs_b, \ cntx_t* cntx, \ rntm_t* rntm \ ); INSERT_GENTPROT_BASIC0( trmm ) INSERT_GENTPROT_BASIC0( trsm ) blis-0.9.0/frame/3/bli_l3_thrinfo.c000066400000000000000000000546211422157504600167640ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "assert.h" void bli_l3_thrinfo_init_single ( thrinfo_t* thread ) { bli_thrinfo_init_single( thread ); } void bli_l3_thrinfo_free ( rntm_t* rntm, thrinfo_t* thread ) { bli_thrinfo_free( rntm, thread ); } void bli_l3_sup_thrinfo_free ( rntm_t* rntm, thrinfo_t* thread ) { bli_thrinfo_free( rntm, thread ); } // ----------------------------------------------------------------------------- void bli_l3_thrinfo_create_root ( dim_t id, thrcomm_t* gl_comm, rntm_t* rntm, cntl_t* cntl, thrinfo_t** thread ) { // Query the global communicator for the total number of threads to use. dim_t n_threads = bli_thrcomm_num_threads( gl_comm ); // Use the thread id passed in as the global communicator id. dim_t gl_comm_id = id; // Use the blocksize id of the current (root) control tree node to // query the top-most ways of parallelism to obtain. bszid_t bszid = bli_cntl_bszid( cntl ); dim_t xx_way = bli_rntm_ways_for( bszid, rntm ); // Determine the work id for this thrinfo_t node. dim_t work_id = gl_comm_id / ( n_threads / xx_way ); // Create the root thrinfo_t node. *thread = bli_thrinfo_create ( rntm, gl_comm, gl_comm_id, xx_way, work_id, TRUE, bszid, NULL ); } // ----------------------------------------------------------------------------- void bli_l3_sup_thrinfo_create_root ( dim_t id, thrcomm_t* gl_comm, rntm_t* rntm, thrinfo_t** thread ) { // Query the global communicator for the total number of threads to use. dim_t n_threads = bli_thrcomm_num_threads( gl_comm ); // Use the thread id passed in as the global communicator id. dim_t gl_comm_id = id; // Use the BLIS_NC blocksize id to query the top-most ways of parallelism // to obtain. Note that hard-coding BLIS_NC like this is a little bit of a // hack, but it works fine since both of the sup algorithms (bp and pb) use // the cache blocksizes down to the 3rd loop. (See the definitions of // bli_rntm_calc_num_threads_bp() and bli_rntm_calc_num_threads_pb() for // a concise enumeration of these bszid_t ids.) const bszid_t bszid = BLIS_NC; dim_t xx_way = bli_rntm_ways_for( BLIS_NC, rntm ); // Determine the work id for this thrinfo_t node. dim_t work_id = gl_comm_id / ( n_threads / xx_way ); // Create the root thrinfo_t node. *thread = bli_thrinfo_create ( rntm, gl_comm, gl_comm_id, xx_way, work_id, TRUE, bszid, NULL ); } // ----------------------------------------------------------------------------- void bli_l3_sup_thrinfo_update_root ( rntm_t* rntm, thrinfo_t* thread ) { // Query the current root for the total number of threads to use. const dim_t n_threads = bli_thread_num_threads( thread ); // Query the current root for the (global) comm id. const dim_t gl_comm_id = bli_thread_ocomm_id( thread ); // Query the rntm_t for the updated number of ways of parallelism. const dim_t xx_way = bli_rntm_ways_for( BLIS_NC, rntm ); // Recompute the work id for this thrinfo_t node using the updated // number of ways of parallelism. dim_t work_id = gl_comm_id / ( n_threads / xx_way ); // Save the updated ways of parallelism and work id to the thrinfo_t node. bli_thrinfo_set_n_way( xx_way, thread ); bli_thrinfo_set_work_id( work_id, thread ); } // ----------------------------------------------------------------------------- void bli_l3_thrinfo_print_gemm_paths ( thrinfo_t** threads ) { // In order to query the number of threads, we query the only thread we // know exists: thread 0. dim_t n_threads = bli_thread_num_threads( threads[0] ); // For the purposes of printing the "header" information that is common // to the various instances of a thrinfo_t (ie: across all threads), we // choose the last thread in case the problem is so small that there is // only an "edge" case, which will always be assigned to the last thread // (at least for higher levels of partitioning). thrinfo_t* jc_info = threads[n_threads-1]; thrinfo_t* pc_info = NULL; thrinfo_t* pb_info = NULL; thrinfo_t* ic_info = NULL; thrinfo_t* pa_info = NULL; thrinfo_t* jr_info = NULL; thrinfo_t* ir_info = NULL; // Initialize the n_ways and n_threads fields of each thrinfo_t "level" // to -1. More than likely, these will all be overwritten with meaningful // values, but in case some thrinfo_t trees are not fully built (see // next commnet), these will be the placeholder values. dim_t jc_way = -1, pc_way = -1, pb_way = -1, ic_way = -1, pa_way = -1, jr_way = -1, ir_way = -1; dim_t jc_nt = -1, pc_nt = -1, pb_nt = -1, ic_nt = -1, pa_nt = -1, jr_nt = -1, ir_nt = -1; // NOTE: We must check each thrinfo_t pointer for NULLness. Certain threads // may not fully build their thrinfo_t structures--specifically when the // dimension being parallelized is not large enough for each thread to have // even one unit of work (where as unit is usually a single micropanel's // width, MR or NR). if ( !jc_info ) goto print_header; jc_way = bli_thread_n_way( jc_info ); jc_nt = bli_thread_num_threads( jc_info ); pc_info = bli_thrinfo_sub_node( jc_info ); if ( !pc_info ) goto print_header; pc_way = bli_thread_n_way( pc_info ); pc_nt = bli_thread_num_threads( pc_info ); pb_info = bli_thrinfo_sub_node( pc_info ); if ( !pb_info ) goto print_header; pb_way = bli_thread_n_way( pb_info ); pb_nt = bli_thread_num_threads( pb_info ); ic_info = bli_thrinfo_sub_node( pb_info ); if ( !ic_info ) goto print_header; ic_way = bli_thread_n_way( ic_info ); ic_nt = bli_thread_num_threads( ic_info ); pa_info = bli_thrinfo_sub_node( ic_info ); if ( !pa_info ) goto print_header; pa_way = bli_thread_n_way( pa_info ); pa_nt = bli_thread_num_threads( pa_info ); jr_info = bli_thrinfo_sub_node( pa_info ); if ( !jr_info ) goto print_header; jr_way = bli_thread_n_way( jr_info ); jr_nt = bli_thread_num_threads( jr_info ); ir_info = bli_thrinfo_sub_node( jr_info ); if ( !ir_info ) goto print_header; ir_way = bli_thread_n_way( ir_info ); ir_nt = bli_thread_num_threads( ir_info ); print_header: printf( " jc kc pb ic pa jr ir\n" ); printf( "xx_nt: %4ld %4ld %4ld %4ld %4ld %4ld %4ld\n", ( unsigned long )jc_nt, ( unsigned long )pc_nt, ( unsigned long )pb_nt, ( unsigned long )ic_nt, ( unsigned long )pa_nt, ( unsigned long )jr_nt, ( unsigned long )ir_nt ); printf( "xx_way: %4ld %4ld %4ld %4ld %4ld %4ld %4ld\n", ( unsigned long )jc_way, ( unsigned long )pc_way, ( unsigned long )pb_way, ( unsigned long )ic_way, ( unsigned long )pa_way, ( unsigned long )jr_way, ( unsigned long )ir_way ); printf( "============================================\n" ); for ( dim_t gl_id = 0; gl_id < n_threads; ++gl_id ) { jc_info = threads[gl_id]; dim_t jc_comm_id = -1, pc_comm_id = -1, pb_comm_id = -1, ic_comm_id = -1, pa_comm_id = -1, jr_comm_id = -1, ir_comm_id = -1; dim_t jc_work_id = -1, pc_work_id = -1, pb_work_id = -1, ic_work_id = -1, pa_work_id = -1, jr_work_id = -1, ir_work_id = -1; if ( !jc_info ) goto print_thrinfo; jc_comm_id = bli_thread_ocomm_id( jc_info ); jc_work_id = bli_thread_work_id( jc_info ); pc_info = bli_thrinfo_sub_node( jc_info ); if ( !pc_info ) goto print_thrinfo; pc_comm_id = bli_thread_ocomm_id( pc_info ); pc_work_id = bli_thread_work_id( pc_info ); pb_info = bli_thrinfo_sub_node( pc_info ); if ( !pb_info ) goto print_thrinfo; pb_comm_id = bli_thread_ocomm_id( pb_info ); pb_work_id = bli_thread_work_id( pb_info ); ic_info = bli_thrinfo_sub_node( pb_info ); if ( !ic_info ) goto print_thrinfo; ic_comm_id = bli_thread_ocomm_id( ic_info ); ic_work_id = bli_thread_work_id( ic_info ); pa_info = bli_thrinfo_sub_node( ic_info ); if ( !pa_info ) goto print_thrinfo; pa_comm_id = bli_thread_ocomm_id( pa_info ); pa_work_id = bli_thread_work_id( pa_info ); jr_info = bli_thrinfo_sub_node( pa_info ); if ( !jr_info ) goto print_thrinfo; jr_comm_id = bli_thread_ocomm_id( jr_info ); jr_work_id = bli_thread_work_id( jr_info ); ir_info = bli_thrinfo_sub_node( jr_info ); if ( !ir_info ) goto print_thrinfo; ir_comm_id = bli_thread_ocomm_id( ir_info ); ir_work_id = bli_thread_work_id( ir_info ); print_thrinfo: printf( "comm ids: %4ld %4ld %4ld %4ld %4ld %4ld %4ld\n", ( long )jc_comm_id, ( long )pc_comm_id, ( long )pb_comm_id, ( long )ic_comm_id, ( long )pa_comm_id, ( long )jr_comm_id, ( long )ir_comm_id ); printf( "work ids: %4ld %4ld %4ld %4ld %4ld %4ld %4ld\n", ( long )jc_work_id, ( long )pc_work_id, ( long )pb_work_id, ( long )ic_work_id, ( long )pa_work_id, ( long )jr_work_id, ( long )ir_work_id ); printf( "--------------------------------------------\n" ); } } // ----------------------------------------------------------------------------- // ----------------------------------------------------------------------------- // ----------------------------------------------------------------------------- void bli_l3_thrinfo_print_trsm_paths ( thrinfo_t** threads ) { // In order to query the number of threads, we query the only thread we // know exists: thread 0. dim_t n_threads = bli_thread_num_threads( threads[0] ); // For the purposes of printing the "header" information that is common // to the various instances of a thrinfo_t (ie: across all threads), we // choose the last thread in case the problem is so small that there is // only an "edge" case, which will always be assigned to the last thread // (at least for higher levels of partitioning). thrinfo_t* jc_info = threads[n_threads-1]; thrinfo_t* pc_info = NULL; thrinfo_t* pb_info = NULL; thrinfo_t* ic_info = NULL; thrinfo_t* pa_info = NULL; thrinfo_t* pa_info0 = NULL; thrinfo_t* jr_info = NULL; thrinfo_t* jr_info0 = NULL; thrinfo_t* ir_info = NULL; thrinfo_t* ir_info0 = NULL; // Initialize the n_ways and n_threads fields of each thrinfo_t "level" // to -1. More than likely, these will all be overwritten with meaningful // values, but in case some thrinfo_t trees are not fully built (see // next commnet), these will be the placeholder values. dim_t jc_way = -1, pc_way = -1, pb_way = -1, ic_way = -1, pa_way = -1, jr_way = -1, ir_way = -1, pa_way0 = -1, jr_way0 = -1, ir_way0 = -1; dim_t jc_nt = -1, pc_nt = -1, pb_nt = -1, ic_nt = -1, pa_nt = -1, jr_nt = -1, ir_nt = -1, pa_nt0 = -1, jr_nt0 = -1, ir_nt0 = -1; // NOTE: We must check each thrinfo_t pointer for NULLness. Certain threads // may not fully build their thrinfo_t structures--specifically when the // dimension being parallelized is not large enough for each thread to have // even one unit of work (where as unit is usually a single micropanel's // width, MR or NR). if ( !jc_info ) goto print_header; jc_way = bli_thread_n_way( jc_info ); jc_nt = bli_thread_num_threads( jc_info ); pc_info = bli_thrinfo_sub_node( jc_info ); if ( !pc_info ) goto print_header; pc_way = bli_thread_n_way( pc_info ); pc_nt = bli_thread_num_threads( pc_info ); pb_info = bli_thrinfo_sub_node( pc_info ); if ( !pb_info ) goto print_header; pb_way = bli_thread_n_way( pb_info ); pb_nt = bli_thread_num_threads( pb_info ); ic_info = bli_thrinfo_sub_node( pb_info ); if ( !ic_info ) goto print_header; ic_way = bli_thread_n_way( ic_info ); ic_nt = bli_thread_num_threads( ic_info ); pa_info = bli_thrinfo_sub_node( ic_info ); pa_info0 = bli_thrinfo_sub_prenode( ic_info ); // check_header_prenode: if ( !pa_info0 ) goto check_header_node; pa_way0 = bli_thread_n_way( pa_info0 ); pa_nt0 = bli_thread_num_threads( pa_info0 ); jr_info0 = bli_thrinfo_sub_node( pa_info0 ); if ( !jr_info0 ) goto check_header_node; jr_way0 = bli_thread_n_way( jr_info0 ); jr_nt0 = bli_thread_num_threads( jr_info0 ); ir_info0 = bli_thrinfo_sub_node( jr_info0 ); if ( !ir_info0 ) goto check_header_node; ir_way0 = bli_thread_n_way( ir_info0 ); ir_nt0 = bli_thread_num_threads( ir_info0 ); check_header_node: if ( !pa_info ) goto print_header; pa_way = bli_thread_n_way( pa_info ); pa_nt = bli_thread_num_threads( pa_info ); jr_info = bli_thrinfo_sub_node( pa_info ); if ( !jr_info ) goto print_header; jr_way = bli_thread_n_way( jr_info ); jr_nt = bli_thread_num_threads( jr_info ); ir_info = bli_thrinfo_sub_node( jr_info ); if ( !ir_info ) goto print_header; ir_way = bli_thread_n_way( ir_info ); ir_nt = bli_thread_num_threads( ir_info ); print_header: printf( " jc kc pb ic pa jr ir\n" ); printf( "xx_nt: %4ld %4ld %4ld %4ld %2ld|%2ld %2ld|%2ld %2ld|%2ld\n", ( long )jc_nt, ( long )pc_nt, ( long )pb_nt, ( long )ic_nt, ( long )pa_nt0, ( long )pa_nt, ( long )jr_nt0, ( long )jr_nt, ( long )ir_nt0, ( long )ir_nt ); printf( "xx_way: %4ld %4ld %4ld %4ld %2ld|%2ld %2ld|%2ld %2ld|%2ld\n", ( long )jc_way, ( long )pc_way, ( long )pb_way, ( long )ic_way, ( long )pa_way0, ( long )pa_way, ( long )jr_way0, ( long )jr_way, ( long )ir_way0, ( long )ir_way ); printf( "==================================================\n" ); for ( dim_t gl_id = 0; gl_id < n_threads; ++gl_id ) { jc_info = threads[gl_id]; #if 1 // NOTE: This cpp branch contains code that is safe to execute // for small problems that are parallelized enough that one or // more threads gets no work. dim_t jc_comm_id = -1, pc_comm_id = -1, pb_comm_id = -1, ic_comm_id = -1, pa_comm_id = -1, jr_comm_id = -1, ir_comm_id = -1, pa_comm_id0 = -1, jr_comm_id0 = -1, ir_comm_id0 = -1; dim_t jc_work_id = -1, pc_work_id = -1, pb_work_id = -1, ic_work_id = -1, pa_work_id = -1, jr_work_id = -1, ir_work_id = -1, pa_work_id0 = -1, jr_work_id0 = -1, ir_work_id0 = -1; if ( !jc_info ) goto print_thrinfo; jc_comm_id = bli_thread_ocomm_id( jc_info ); jc_work_id = bli_thread_work_id( jc_info ); pc_info = bli_thrinfo_sub_node( jc_info ); if ( !pc_info ) goto print_thrinfo; pc_comm_id = bli_thread_ocomm_id( pc_info ); pc_work_id = bli_thread_work_id( pc_info ); pb_info = bli_thrinfo_sub_node( pc_info ); if ( !pb_info ) goto print_thrinfo; pb_comm_id = bli_thread_ocomm_id( pb_info ); pb_work_id = bli_thread_work_id( pb_info ); ic_info = bli_thrinfo_sub_node( pb_info ); if ( !ic_info ) goto print_thrinfo; ic_comm_id = bli_thread_ocomm_id( ic_info ); ic_work_id = bli_thread_work_id( ic_info ); pa_info = bli_thrinfo_sub_node( ic_info ); pa_info0 = bli_thrinfo_sub_prenode( ic_info ); // check_thrinfo_prenode: if ( !pa_info0 ) goto check_thrinfo_node; pa_comm_id0 = bli_thread_ocomm_id( pa_info0 ); pa_work_id0 = bli_thread_work_id( pa_info0 ); jr_info0 = bli_thrinfo_sub_node( pa_info0 ); if ( !jr_info0 ) goto check_thrinfo_node; jr_comm_id0 = bli_thread_ocomm_id( jr_info0 ); jr_work_id0 = bli_thread_work_id( jr_info0 ); ir_info0 = bli_thrinfo_sub_node( jr_info0 ); if ( !ir_info0 ) goto check_thrinfo_node; ir_comm_id0 = bli_thread_ocomm_id( ir_info0 ); ir_work_id0 = bli_thread_work_id( ir_info0 ); check_thrinfo_node: if ( !pa_info ) goto print_thrinfo; pa_comm_id = bli_thread_ocomm_id( pa_info ); pa_work_id = bli_thread_work_id( pa_info ); jr_info = bli_thrinfo_sub_node( pa_info ); if ( !jr_info ) goto print_thrinfo; jr_comm_id = bli_thread_ocomm_id( jr_info ); jr_work_id = bli_thread_work_id( jr_info ); ir_info = bli_thrinfo_sub_node( jr_info ); if ( !ir_info ) goto print_thrinfo; ir_comm_id = bli_thread_ocomm_id( ir_info ); ir_work_id = bli_thread_work_id( ir_info ); print_thrinfo: #else dim_t jc_comm_id; dim_t pc_comm_id; dim_t pb_comm_id; dim_t ic_comm_id; dim_t pa_comm_id0, pa_comm_id; dim_t jr_comm_id0, jr_comm_id; dim_t ir_comm_id0, ir_comm_id; dim_t jc_work_id; dim_t pc_work_id; dim_t pb_work_id; dim_t ic_work_id; dim_t pa_work_id0, pa_work_id; dim_t jr_work_id0, jr_work_id; dim_t ir_work_id0, ir_work_id; // NOTE: We must check each thrinfo_t pointer for NULLness. Certain threads // may not fully build their thrinfo_t structures--specifically when the // dimension being parallelized is not large enough for each thread to have // even one unit of work (where as unit is usually a single micropanel's // width, MR or NR). if ( !jc_info ) { jc_comm_id = pc_comm_id = pb_comm_id = ic_comm_id = pa_comm_id = jr_comm_id = ir_comm_id = -1; jc_work_id = pc_work_id = pb_work_id = ic_work_id = pa_work_id = jr_work_id = ir_work_id = -1; } else { jc_comm_id = bli_thread_ocomm_id( jc_info ); jc_work_id = bli_thread_work_id( jc_info ); pc_info = bli_thrinfo_sub_node( jc_info ); if ( !pc_info ) { pc_comm_id = pb_comm_id = ic_comm_id = pa_comm_id = jr_comm_id = ir_comm_id = -1; pc_work_id = pb_work_id = ic_work_id = pa_work_id = jr_work_id = ir_work_id = -1; } else { pc_comm_id = bli_thread_ocomm_id( pc_info ); pc_work_id = bli_thread_work_id( pc_info ); pb_info = bli_thrinfo_sub_node( pc_info ); if ( !pb_info ) { pb_comm_id = ic_comm_id = pa_comm_id = jr_comm_id = ir_comm_id = -1; pb_work_id = ic_work_id = pa_work_id = jr_work_id = ir_work_id = -1; } else { pb_comm_id = bli_thread_ocomm_id( pb_info ); pb_work_id = bli_thread_work_id( pb_info ); ic_info = bli_thrinfo_sub_node( pb_info ); if ( !ic_info ) { ic_comm_id = pa_comm_id = jr_comm_id = ir_comm_id = -1; ic_work_id = pa_work_id = jr_work_id = ir_work_id = -1; } else { ic_comm_id = bli_thread_ocomm_id( ic_info ); ic_work_id = bli_thread_work_id( ic_info ); pa_info0 = bli_thrinfo_sub_prenode( ic_info ); pa_info = bli_thrinfo_sub_node( ic_info ); // Prenode if ( !pa_info0 ) { pa_comm_id0 = jr_comm_id0 = ir_comm_id0 = -1; pa_work_id0 = jr_work_id0 = ir_work_id0 = -1; } else { pa_comm_id0 = bli_thread_ocomm_id( pa_info0 ); pa_work_id0 = bli_thread_work_id( pa_info0 ); jr_info0 = bli_thrinfo_sub_node( pa_info0 ); if ( !jr_info0 ) { jr_comm_id0 = ir_comm_id0 = -1; jr_work_id0 = ir_work_id0 = -1; } else { jr_comm_id0 = bli_thread_ocomm_id( jr_info0 ); jr_work_id0 = bli_thread_work_id( jr_info0 ); ir_info0 = bli_thrinfo_sub_node( jr_info0 ); if ( !ir_info0 ) { ir_comm_id0 = -1; ir_work_id0 = -1; } else { ir_comm_id0 = bli_thread_ocomm_id( ir_info0 ); ir_work_id0 = bli_thread_work_id( ir_info0 ); } } } // Main node if ( !pa_info ) { pa_comm_id = jr_comm_id = ir_comm_id = -1; pa_work_id = jr_work_id = ir_work_id = -1; } else { pa_comm_id = bli_thread_ocomm_id( pa_info ); pa_work_id = bli_thread_work_id( pa_info ); jr_info = bli_thrinfo_sub_node( pa_info ); if ( !jr_info ) { jr_comm_id = ir_comm_id = -1; jr_work_id = ir_work_id = -1; } else { jr_comm_id = bli_thread_ocomm_id( jr_info ); jr_work_id = bli_thread_work_id( jr_info ); ir_info = bli_thrinfo_sub_node( jr_info ); if ( !ir_info ) { ir_comm_id = -1; ir_work_id = -1; } else { ir_comm_id = bli_thread_ocomm_id( ir_info ); ir_work_id = bli_thread_work_id( ir_info ); } } } } } } } #endif printf( "comm ids: %4ld %4ld %4ld %4ld %2ld|%2ld %2ld|%2ld %2ld|%2ld\n", ( long )jc_comm_id, ( long )pc_comm_id, ( long )pb_comm_id, ( long )ic_comm_id, ( long )pa_comm_id0, ( long )pa_comm_id, ( long )jr_comm_id0, ( long )jr_comm_id, ( long )ir_comm_id0, ( long )ir_comm_id ); printf( "work ids: %4ld %4ld %4ld %4ld %2ld|%2ld %2ld|%2ld %2ld|%2ld\n", ( long )jc_work_id, ( long )pc_work_id, ( long )pb_work_id, ( long )ic_work_id, ( long )pa_work_id0, ( long )pa_work_id, ( long )jr_work_id0, ( long )jr_work_id, ( long )ir_work_id0, ( long )ir_work_id ); printf( "--------------------------------------------------\n" ); } } // ----------------------------------------------------------------------------- void bli_l3_thrinfo_free_paths ( rntm_t* rntm, thrinfo_t** threads ) { dim_t n_threads = bli_thread_num_threads( threads[0] ); dim_t i; for ( i = 0; i < n_threads; ++i ) bli_l3_thrinfo_free( rntm, threads[i] ); bli_free_intl( threads ); } blis-0.9.0/frame/3/bli_l3_thrinfo.h000066400000000000000000000102771422157504600167700ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // thrinfo_t macros specific to various level-3 operations. // // gemm // NOTE: The definition of bli_gemm_get_next_?_upanel() does not need to // change depending on BLIS_ENABLE_JRIR_SLAB / BLIS_ENABLE_JRIR_RR. #define bli_gemm_get_next_a_upanel( a1, step, inc ) ( a1 + step * inc ) #define bli_gemm_get_next_b_upanel( b1, step, inc ) ( b1 + step * inc ) // gemmt // NOTE: The definition of bli_gemmt_get_next_?_upanel() does not need to // change depending on BLIS_ENABLE_JRIR_SLAB / BLIS_ENABLE_JRIR_RR. #define bli_gemmt_get_next_a_upanel( a1, step, inc ) ( a1 + step * inc ) #define bli_gemmt_get_next_b_upanel( b1, step, inc ) ( b1 + step * inc ) // trmm // NOTE: The definition of bli_trmm_get_next_?_upanel() does not need to // change depending on BLIS_ENABLE_JRIR_SLAB / BLIS_ENABLE_JRIR_RR. #define bli_trmm_get_next_a_upanel( a1, step, inc ) ( a1 + step * inc ) #define bli_trmm_get_next_b_upanel( b1, step, inc ) ( b1 + step * inc ) #define bli_trmm_my_iter_rr( index, thread ) \ \ ( index % thread->n_way == thread->work_id % thread->n_way ) // trsm #define bli_trsm_my_iter_rr( index, thread ) \ \ ( index % thread->n_way == thread->work_id % thread->n_way ) // // thrinfo_t APIs specific to level-3 operations. // void bli_l3_thrinfo_init ( thrinfo_t* thread, thrcomm_t* ocomm, dim_t ocomm_id, dim_t n_way, dim_t work_id, thrinfo_t* sub_node ); void bli_l3_thrinfo_init_single ( thrinfo_t* thread ); void bli_l3_thrinfo_free ( rntm_t* rntm, thrinfo_t* thread ); void bli_l3_sup_thrinfo_free ( rntm_t* rntm, thrinfo_t* thread ); // ----------------------------------------------------------------------------- void bli_l3_thrinfo_create_root ( dim_t id, thrcomm_t* gl_comm, rntm_t* rntm, cntl_t* cntl, thrinfo_t** thread ); void bli_l3_sup_thrinfo_create_root ( dim_t id, thrcomm_t* gl_comm, rntm_t* rntm, thrinfo_t** thread ); void bli_l3_sup_thrinfo_update_root ( rntm_t* rntm, thrinfo_t* thread ); void bli_l3_thrinfo_print_gemm_paths ( thrinfo_t** threads ); void bli_l3_thrinfo_print_trsm_paths ( thrinfo_t** threads ); // ----------------------------------------------------------------------------- void bli_l3_thrinfo_free_paths ( rntm_t* rntm, thrinfo_t** threads ); blis-0.9.0/frame/3/bli_l3_ukr.h000066400000000000000000000044561422157504600161220ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Define template prototypes for level-3 micro-kernels. // // Note: Instead of defining function prototype macro templates and then // instantiating those macros to define the individual function prototypes, // we simply alias the official operations' prototypes as defined in // bli_l3_ukr_prot.h. #undef GENTPROT #define GENTPROT GEMM_UKR_PROT INSERT_GENTPROT_BASIC0( gemm_ukr_name ) #undef GENTPROT #define GENTPROT GEMMTRSM_UKR_PROT INSERT_GENTPROT_BASIC0( gemmtrsm_l_ukr_name ) INSERT_GENTPROT_BASIC0( gemmtrsm_u_ukr_name ) #undef GENTPROT #define GENTPROT TRSM_UKR_PROT INSERT_GENTPROT_BASIC0( trsm_l_ukr_name ) INSERT_GENTPROT_BASIC0( trsm_u_ukr_name ) blis-0.9.0/frame/3/bli_l3_ukr_fpa.c000066400000000000000000000041731422157504600167370ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // Define function pointer query interfaces. // #undef GENFRONT #define GENFRONT( tname, opname ) \ \ GENARRAY_FPA( PASTECH2(tname,_ukr,_vft), \ opname ); \ \ PASTECH2(tname,_ukr,_vft) \ PASTEMAC(opname,_qfp)( num_t dt ) \ { \ return PASTECH(opname,_fpa)[ dt ]; \ } GENFRONT( gemm, gemm_ukernel ) GENFRONT( gemmtrsm, gemmtrsm_l_ukernel ) GENFRONT( gemmtrsm, gemmtrsm_u_ukernel ) GENFRONT( trsm, trsm_l_ukernel ) GENFRONT( trsm, trsm_u_ukernel ) blis-0.9.0/frame/3/bli_l3_ukr_fpa.h000066400000000000000000000037571422157504600167530ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype function pointer query interface. // #undef GENPROT #define GENPROT( tname, opname ) \ \ PASTECH2(tname,_ukr,_vft) \ PASTEMAC(opname,_qfp)( num_t dt ); GENPROT( gemm, gemm_ukernel ) GENPROT( gemmtrsm, gemmtrsm_l_ukernel ) GENPROT( gemmtrsm, gemmtrsm_u_ukernel ) GENPROT( trsm, trsm_l_ukernel ) GENPROT( trsm, trsm_u_ukernel ) blis-0.9.0/frame/3/bli_l3_ukr_oapi.c000066400000000000000000000155361422157504600171260ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENFRONT #define GENFRONT( tname, opname ) \ \ void PASTEMAC0(opname) \ ( \ obj_t* alpha, \ obj_t* a, \ obj_t* b, \ obj_t* beta, \ obj_t* c, \ cntx_t* cntx \ ) \ { \ bli_init_once(); \ \ num_t dt = bli_obj_dt( c ); \ \ dim_t m = bli_obj_length( c ); \ dim_t n = bli_obj_width( c ); \ dim_t k = bli_obj_width( a ); \ void* buf_a = bli_obj_buffer_at_off( a ); \ void* buf_b = bli_obj_buffer_at_off( b ); \ void* buf_c = bli_obj_buffer_at_off( c ); \ inc_t rs_c = bli_obj_row_stride( c ); \ inc_t cs_c = bli_obj_col_stride( c ); \ void* buf_alpha = bli_obj_buffer_for_1x1( dt, alpha ); \ void* buf_beta = bli_obj_buffer_for_1x1( dt, beta ); \ \ auxinfo_t data; \ \ /* Fill the auxinfo_t struct in case the micro-kernel uses it. */ \ bli_auxinfo_set_next_a( buf_a, &data ); \ bli_auxinfo_set_next_b( buf_b, &data ); \ bli_auxinfo_set_is_a( 1, &data ); \ bli_auxinfo_set_is_b( 1, &data ); \ \ /* Query a type-specific function pointer, except one that uses void* for function arguments instead of typed pointers. */ \ PASTECH2(tname,_ukr,_vft) f = \ PASTEMAC(opname,_qfp)( dt ); \ \ f \ ( \ m, \ n, \ k, \ buf_alpha, \ buf_a, \ buf_b, \ buf_beta, \ buf_c, rs_c, cs_c, \ &data, \ cntx \ ); \ } \ GENFRONT( gemm, gemm_ukernel ) #undef GENFRONT #define GENFRONT( tname, opname, opnamel, opnameu ) \ \ void PASTEMAC0(opname) \ ( \ obj_t* alpha, \ obj_t* a1x, \ obj_t* a11, \ obj_t* bx1, \ obj_t* b11, \ obj_t* c11, \ cntx_t* cntx \ ) \ { \ bli_init_once(); \ \ num_t dt = bli_obj_dt( c11 ); \ \ dim_t m = bli_obj_length( c11 ); \ dim_t n = bli_obj_width( c11 ); \ dim_t k = bli_obj_width( a1x ); \ void* buf_a1x = bli_obj_buffer_at_off( a1x ); \ void* buf_a11 = bli_obj_buffer_at_off( a11 ); \ void* buf_bx1 = bli_obj_buffer_at_off( bx1 ); \ void* buf_b11 = bli_obj_buffer_at_off( b11 ); \ void* buf_c11 = bli_obj_buffer_at_off( c11 ); \ inc_t rs_c = bli_obj_row_stride( c11 ); \ inc_t cs_c = bli_obj_col_stride( c11 ); \ void* buf_alpha = bli_obj_buffer_for_1x1( dt, alpha ); \ \ auxinfo_t data; \ \ /* Fill the auxinfo_t struct in case the micro-kernel uses it. */ \ if ( bli_obj_is_lower( a11 ) ) \ { bli_auxinfo_set_next_a( buf_a1x, &data ); } \ else /* if ( bli_obj_is_upper( a11 ) ) */ \ { bli_auxinfo_set_next_a( buf_a11, &data ); } \ bli_auxinfo_set_next_b( buf_bx1, &data ); \ \ /* Invoke the void pointer-based function for the given datatype. */ \ if ( bli_obj_is_lower( a11 ) ) \ { \ /* Query a type-specific function pointer, except one that uses void* for function arguments instead of typed pointers. */ \ PASTECH2(tname,_ukr,_vft) f = \ PASTEMAC(opnamel,_qfp)( dt ); \ \ f \ ( \ m, \ n, \ k, \ buf_alpha, \ buf_a1x, \ buf_a11, \ buf_bx1, \ buf_b11, \ buf_c11, rs_c, cs_c, \ &data, \ cntx \ ); \ } \ else /* if ( bli_obj_is_upper( a11 ) ) */ \ { \ /* Query a type-specific function pointer, except one that uses void* for function arguments instead of typed pointers. */ \ PASTECH2(tname,_ukr,_vft) f = \ PASTEMAC(opnameu,_qfp)( dt ); \ \ f \ ( \ m, \ n, \ k, \ buf_alpha, \ buf_a1x, \ buf_a11, \ buf_bx1, \ buf_b11, \ buf_c11, rs_c, cs_c, \ &data, \ cntx \ ); \ } \ } \ GENFRONT( gemmtrsm, gemmtrsm_ukernel, gemmtrsm_l_ukernel, gemmtrsm_u_ukernel ) #undef GENFRONT #define GENFRONT( tname, opname, opnamel, opnameu ) \ \ void PASTEMAC0(opname) \ ( \ obj_t* a, \ obj_t* b, \ obj_t* c, \ cntx_t* cntx \ ) \ { \ bli_init_once(); \ \ num_t dt = bli_obj_dt( c ); \ \ void* buf_a = bli_obj_buffer_at_off( a ); \ void* buf_b = bli_obj_buffer_at_off( b ); \ void* buf_c = bli_obj_buffer_at_off( c ); \ inc_t rs_c = bli_obj_row_stride( c ); \ inc_t cs_c = bli_obj_col_stride( c ); \ \ auxinfo_t data; \ \ /* Fill the auxinfo_t struct in case the micro-kernel uses it. */ \ bli_auxinfo_set_next_a( buf_a, &data ); \ bli_auxinfo_set_next_b( buf_b, &data ); \ bli_auxinfo_set_is_a( 1, &data ); \ bli_auxinfo_set_is_b( 1, &data ); \ \ /* Invoke the void pointer-based function for the given datatype. */ \ if ( bli_obj_is_lower( a ) ) \ { \ /* Query a type-specific function pointer, except one that uses void* for function arguments instead of typed pointers. */ \ PASTECH2(tname,_ukr,_vft) f = \ PASTEMAC(opnamel,_qfp)( dt ); \ \ f \ ( \ buf_a, \ buf_b, \ buf_c, rs_c, cs_c, \ &data, \ cntx \ ); \ } \ else /* if ( bli_obj_is_upper( a ) ) */ \ { \ /* Query a type-specific function pointer, except one that uses void* for function arguments instead of typed pointers. */ \ PASTECH2(tname,_ukr,_vft) f = \ PASTEMAC(opnameu,_qfp)( dt ); \ \ f \ ( \ buf_a, \ buf_b, \ buf_c, rs_c, cs_c, \ &data, \ cntx \ ); \ } \ } \ GENFRONT( trsm, trsm_ukernel, trsm_l_ukernel, trsm_u_ukernel ) blis-0.9.0/frame/3/bli_l3_ukr_oapi.h000066400000000000000000000046701422157504600171300ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype object-based interfaces. // #undef GENPROT #define GENPROT( opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC0(opname) \ ( \ obj_t* alpha, \ obj_t* a, \ obj_t* b, \ obj_t* beta, \ obj_t* c, \ cntx_t* cntx \ ); GENPROT( gemm_ukernel ) #undef GENPROT #define GENPROT( opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC0(opname) \ ( \ obj_t* alpha, \ obj_t* a1x, \ obj_t* a11, \ obj_t* bx1, \ obj_t* b11, \ obj_t* c11, \ cntx_t* cntx \ ); GENPROT( gemmtrsm_ukernel ) #undef GENPROT #define GENPROT( opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC0(opname) \ ( \ obj_t* a, \ obj_t* b, \ obj_t* c, \ cntx_t* cntx \ ); GENPROT( trsm_ukernel ) blis-0.9.0/frame/3/bli_l3_ukr_prot.h000066400000000000000000000057661422157504600171730ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Define template prototypes for level-3 micro-kernels. // #define GEMM_UKR_PROT( ctype, ch, opname ) GEMM_UKR_PROT2(ctype, ctype, ch, opname) #define GEMM_UKR_PROT2( ctype_in, ctype_out, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ dim_t m, \ dim_t n, \ dim_t k, \ ctype_out* restrict alpha, \ ctype_in* restrict a, \ ctype_in* restrict b, \ ctype_out* restrict beta, \ ctype_out* restrict c, inc_t rs_c, inc_t cs_c, \ auxinfo_t* restrict data, \ cntx_t* restrict cntx \ ); #define GEMMTRSM_UKR_PROT( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ dim_t m, \ dim_t n, \ dim_t k, \ ctype* restrict alpha, \ ctype* restrict a1x, \ ctype* restrict a11, \ ctype* restrict bx1, \ ctype* restrict b11, \ ctype* restrict c11, inc_t rs_c, inc_t cs_c, \ auxinfo_t* restrict data, \ cntx_t* restrict cntx \ ); #define TRSM_UKR_PROT( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ ctype* restrict a, \ ctype* restrict b, \ ctype* restrict c, inc_t rs_c, inc_t cs_c, \ auxinfo_t* restrict data, \ cntx_t* restrict cntx \ ); blis-0.9.0/frame/3/bli_l3_ukr_tapi.c000066400000000000000000000107631422157504600171300ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, tname, kerid ) \ \ void PASTEMAC(ch,opname) \ ( \ dim_t m, \ dim_t n, \ dim_t k, \ ctype* restrict alpha, \ ctype* restrict a, \ ctype* restrict b, \ ctype* restrict beta, \ ctype* restrict c, inc_t rs_c, inc_t cs_c, \ auxinfo_t* restrict data, \ cntx_t* restrict cntx \ ) \ { \ bli_init_once(); \ \ const num_t dt = PASTEMAC(ch,type); \ \ /* Query the context for the function address of the current datatype's micro-kernel. */ \ PASTECH2(ch,tname,_ukr_ft) f = bli_cntx_get_l3_vir_ukr_dt( dt, kerid, cntx ); \ \ /* Invoke the typed function for the given datatype. */ \ f \ ( \ m, \ n, \ k, \ alpha, \ a, \ b, \ beta, \ c, rs_c, cs_c, \ data, \ cntx \ ); \ } \ INSERT_GENTFUNC_BASIC2( gemm_ukernel, gemm, BLIS_GEMM_UKR ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, tname, kerid ) \ \ void PASTEMAC(ch,opname) \ ( \ dim_t m, \ dim_t n, \ dim_t k, \ ctype* restrict alpha, \ ctype* restrict a1x, \ ctype* restrict a11, \ ctype* restrict bx1, \ ctype* restrict b11, \ ctype* restrict c11, inc_t rs_c, inc_t cs_c, \ auxinfo_t* restrict data, \ cntx_t* restrict cntx \ ) \ { \ bli_init_once(); \ \ const num_t dt = PASTEMAC(ch,type); \ \ /* Query the context for the function address of the current datatype's micro-kernel. */ \ PASTECH2(ch,tname,_ukr_ft) f = bli_cntx_get_l3_vir_ukr_dt( dt, kerid, cntx ); \ \ /* Invoke the typed function for the given datatype. */ \ f \ ( \ m, \ n, \ k, \ alpha, \ a1x, \ a11, \ bx1, \ b11, \ c11, rs_c, cs_c, \ data, \ cntx \ ); \ } \ INSERT_GENTFUNC_BASIC2( gemmtrsm_l_ukernel, gemmtrsm, BLIS_GEMMTRSM_L_UKR ) INSERT_GENTFUNC_BASIC2( gemmtrsm_u_ukernel, gemmtrsm, BLIS_GEMMTRSM_U_UKR ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, tname, kerid ) \ \ void PASTEMAC(ch,opname) \ ( \ ctype* restrict a, \ ctype* restrict b, \ ctype* restrict c, inc_t rs_c, inc_t cs_c, \ auxinfo_t* restrict data, \ cntx_t* restrict cntx \ ) \ { \ bli_init_once(); \ \ const num_t dt = PASTEMAC(ch,type); \ \ /* Query the context for the function address of the current datatype's micro-kernel. */ \ PASTECH2(ch,tname,_ukr_ft) f = bli_cntx_get_l3_vir_ukr_dt( dt, kerid, cntx ); \ \ /* Invoke the typed function for the given datatype. */ \ f \ ( \ a, \ b, \ c, rs_c, cs_c, \ data, \ cntx \ ); \ } \ INSERT_GENTFUNC_BASIC2( trsm_l_ukernel, trsm, BLIS_TRSM_L_UKR ) INSERT_GENTFUNC_BASIC2( trsm_u_ukernel, trsm, BLIS_TRSM_U_UKR ) blis-0.9.0/frame/3/bli_l3_ukr_tapi.h000066400000000000000000000041651422157504600171340ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Generate prototypes for level-3 micro-kernel wrappers. // #undef gemm_ukr_name #define gemm_ukr_name gemm_ukernel #undef gemmtrsm_l_ukr_name #define gemmtrsm_l_ukr_name gemmtrsm_l_ukernel #undef gemmtrsm_u_ukr_name #define gemmtrsm_u_ukr_name gemmtrsm_u_ukernel #undef trsm_l_ukr_name #define trsm_l_ukr_name trsm_l_ukernel #undef trsm_u_ukr_name #define trsm_u_ukr_name trsm_u_ukernel // Include the level-3 micro-kernel API template. #include "bli_l3_ukr.h" blis-0.9.0/frame/3/gemm/000077500000000000000000000000001422157504600146405ustar00rootroot00000000000000blis-0.9.0/frame/3/gemm/bli_gemm.h000066400000000000000000000035211422157504600165650ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "bli_gemm_cntl.h" #include "bli_gemm_front.h" #include "bli_gemm_var.h" #include "bli_gemm_ind_opt.h" // Mixed datatype support. #ifdef BLIS_ENABLE_GEMM_MD #include "bli_gemm_md.h" #endif blis-0.9.0/frame/3/gemm/bli_gemm_blk_var1.c000066400000000000000000000060031422157504600203370ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_gemm_blk_var1 ( obj_t* a, obj_t* b, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ) { obj_t a1, c1; dim_t my_start, my_end; dim_t b_alg; // Determine the direction in which to partition (forwards or backwards). dir_t direct = bli_l3_direct( a, b, c, cntl ); // Prune any zero region that exists along the partitioning dimension. bli_l3_prune_unref_mparts_m( a, b, c, cntl ); // Determine the current thread's subpartition range. bli_thread_range_mdim ( direct, thread, a, b, c, cntl, cntx, &my_start, &my_end ); // Partition along the m dimension. for ( dim_t i = my_start; i < my_end; i += b_alg ) { // Determine the current algorithmic blocksize. b_alg = bli_determine_blocksize( direct, i, my_end, a, bli_cntl_bszid( cntl ), cntx ); // Acquire partitions for A1 and C1. bli_acquire_mpart_mdim( direct, BLIS_SUBPART1, i, b_alg, a, &a1 ); bli_acquire_mpart_mdim( direct, BLIS_SUBPART1, i, b_alg, c, &c1 ); // Perform gemm subproblem. bli_l3_int ( &BLIS_ONE, &a1, b, &BLIS_ONE, &c1, cntx, rntm, bli_cntl_sub_node( cntl ), bli_thrinfo_sub_node( thread ) ); } } blis-0.9.0/frame/3/gemm/bli_gemm_blk_var2.c000066400000000000000000000060031422157504600203400ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_gemm_blk_var2 ( obj_t* a, obj_t* b, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ) { obj_t b1, c1; dim_t my_start, my_end; dim_t b_alg; // Determine the direction in which to partition (forwards or backwards). dir_t direct = bli_l3_direct( a, b, c, cntl ); // Prune any zero region that exists along the partitioning dimension. bli_l3_prune_unref_mparts_n( a, b, c, cntl ); // Determine the current thread's subpartition range. bli_thread_range_ndim ( direct, thread, a, b, c, cntl, cntx, &my_start, &my_end ); // Partition along the n dimension. for ( dim_t i = my_start; i < my_end; i += b_alg ) { // Determine the current algorithmic blocksize. b_alg = bli_determine_blocksize( direct, i, my_end, b, bli_cntl_bszid( cntl ), cntx ); // Acquire partitions for B1 and C1. bli_acquire_mpart_ndim( direct, BLIS_SUBPART1, i, b_alg, b, &b1 ); bli_acquire_mpart_ndim( direct, BLIS_SUBPART1, i, b_alg, c, &c1 ); // Perform gemm subproblem. bli_l3_int ( &BLIS_ONE, a, &b1, &BLIS_ONE, &c1, cntx, rntm, bli_cntl_sub_node( cntl ), bli_thrinfo_sub_node( thread ) ); } } blis-0.9.0/frame/3/gemm/bli_gemm_blk_var3.c000066400000000000000000000104421422157504600203430ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_gemm_blk_var3 ( obj_t* a, obj_t* b, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ) { obj_t a1, b1; dim_t b_alg; // Determine the direction in which to partition (forwards or backwards). dir_t direct = bli_l3_direct( a, b, c, cntl ); // Prune any zero region that exists along the partitioning dimension. bli_l3_prune_unref_mparts_k( a, b, c, cntl ); // Query dimension in partitioning direction. dim_t k_trans = bli_obj_width_after_trans( a ); // Partition along the k dimension. for ( dim_t i = 0; i < k_trans; i += b_alg ) { // Determine the current algorithmic blocksize. b_alg = bli_l3_determine_kc( direct, i, k_trans, a, b, bli_cntl_bszid( cntl ), cntx, cntl ); // Acquire partitions for A1 and B1. bli_acquire_mpart_ndim( direct, BLIS_SUBPART1, i, b_alg, a, &a1 ); bli_acquire_mpart_mdim( direct, BLIS_SUBPART1, i, b_alg, b, &b1 ); // Perform gemm subproblem. bli_l3_int ( &BLIS_ONE, &a1, &b1, &BLIS_ONE, c, cntx, rntm, bli_cntl_sub_node( cntl ), bli_thrinfo_sub_node( thread ) ); bli_thread_barrier( bli_thrinfo_sub_node( thread ) ); // This variant executes multiple rank-k updates. Therefore, if the // internal beta scalar on matrix C is non-zero, we must use it // only for the first iteration (and then BLIS_ONE for all others). // And since c is a locally aliased obj_t (see _int() function), we // can simply overwrite the internal beta scalar with BLIS_ONE once // it has been used in the first iteration. However... // Unlike variant 3 of gemm and gemmt, which reset the internal scalar // on C at the end of the first iteration so that subsequent iterations // do not erroneously apply beta more than once, it is important that // this behavior not be applied to trmm. That is because the order of // computation is always such that the beta that is passed into the // macro-kernel must be zero, since the macro-kernel only applies that // beta to (and thus overwrites) the row-panel of C that corresponds to // the current block intersecting the diagonal. It turns out that this // same pattern holds for trmm3 as well--except there, the beta scalar // is potentially non-zero, but is still applied only to the current // row-panel of C, and thus beta is applied to all of C exactly once. // Thus, for neither trmm nor trmm3 should we reset the scalar on C // after the first iteration. if ( bli_cntl_family( cntl ) != BLIS_TRMM ) if ( i == 0 ) bli_obj_scalar_reset( c ); } } blis-0.9.0/frame/3/gemm/bli_gemm_cntl.c000066400000000000000000000172701422157504600176060ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" cntl_t* bli_gemm_cntl_create ( rntm_t* rntm, opid_t family, pack_t schema_a, pack_t schema_b, void_fp ker ) { return bli_gemmbp_cntl_create( rntm, family, schema_a, schema_b, ker ); } // ----------------------------------------------------------------------------- cntl_t* bli_gemmbp_cntl_create ( rntm_t* rntm, opid_t family, pack_t schema_a, pack_t schema_b, void_fp ker ) { void_fp macro_kernel_fp; // Choose the default macrokernel based on the operation family... if ( family == BLIS_GEMM ) macro_kernel_fp = bli_gemm_ker_var2; else if ( family == BLIS_GEMMT ) macro_kernel_fp = bli_gemmt_x_ker_var2; else if ( family == BLIS_TRMM ) macro_kernel_fp = bli_trmm_xx_ker_var2; else /* should never execute */ macro_kernel_fp = NULL; // ...unless a non-NULL kernel function pointer is passed in, in which // case we use that instead. if ( ker ) macro_kernel_fp = ker; // Create two nodes for the macro-kernel. cntl_t* gemm_cntl_bu_ke = bli_gemm_cntl_create_node ( rntm, // the thread's runtime structure family, // the operation family BLIS_MR, // needed for bli_thrinfo_rgrow() NULL, // variant function pointer not used NULL // no sub-node; this is the leaf of the tree. ); cntl_t* gemm_cntl_bp_bu = bli_gemm_cntl_create_node ( rntm, // the thread's runtime structure family, BLIS_NR, // not used by macro-kernel, but needed for bli_thrinfo_rgrow() macro_kernel_fp, gemm_cntl_bu_ke ); // Create a node for packing matrix A. cntl_t* gemm_cntl_packa = bli_packm_cntl_create_node ( rntm, bli_l3_packa, // pack the left-hand operand BLIS_MR, BLIS_KR, FALSE, // do NOT invert diagonal FALSE, // reverse iteration if upper? FALSE, // reverse iteration if lower? schema_a, // normally BLIS_PACKED_ROW_PANELS BLIS_BUFFER_FOR_A_BLOCK, gemm_cntl_bp_bu ); // Create a node for partitioning the m dimension by MC. cntl_t* gemm_cntl_op_bp = bli_gemm_cntl_create_node ( rntm, family, BLIS_MC, bli_gemm_blk_var1, gemm_cntl_packa ); // Create a node for packing matrix B. cntl_t* gemm_cntl_packb = bli_packm_cntl_create_node ( rntm, bli_l3_packb, // pack the right-hand operand BLIS_NR, BLIS_KR, FALSE, // do NOT invert diagonal FALSE, // reverse iteration if upper? FALSE, // reverse iteration if lower? schema_b, // normally BLIS_PACKED_COL_PANELS BLIS_BUFFER_FOR_B_PANEL, gemm_cntl_op_bp ); // Create a node for partitioning the k dimension by KC. cntl_t* gemm_cntl_mm_op = bli_gemm_cntl_create_node ( rntm, family, BLIS_KC, bli_gemm_blk_var3, gemm_cntl_packb ); // Create a node for partitioning the n dimension by NC. cntl_t* gemm_cntl_vl_mm = bli_gemm_cntl_create_node ( rntm, family, BLIS_NC, bli_gemm_blk_var2, gemm_cntl_mm_op ); return gemm_cntl_vl_mm; } // ----------------------------------------------------------------------------- // This control tree creation function is disabled because it is no longer used. // (It was originally created in the run up to publishing the 1m journal article, // but was disabled to reduce complexity.) #if 0 cntl_t* bli_gemmpb_cntl_create ( opid_t family ) { void_fp macro_kernel_p = bli_gemm_ker_var1; // Change the macro-kernel if the operation family is gemmt or trmm. //if ( family == BLIS_GEMMT ) macro_kernel_p = bli_gemmt_x_ker_var2; //else if ( family == BLIS_TRMM ) macro_kernel_p = bli_trmm_xx_ker_var2; // Create two nodes for the macro-kernel. cntl_t* gemm_cntl_ub_ke = bli_gemm_cntl_create_node ( family, // the operation family BLIS_MR, // needed for bli_thrinfo_rgrow() NULL, // variant function pointer not used NULL // no sub-node; this is the leaf of the tree. ); cntl_t* gemm_cntl_pb_ub = bli_gemm_cntl_create_node ( family, BLIS_NR, // not used by macro-kernel, but needed for bli_thrinfo_rgrow() macro_kernel_p, gemm_cntl_ub_ke ); // Create a node for packing matrix A (which is really the right-hand // operand "B"). cntl_t* gemm_cntl_packb = bli_packm_cntl_create_node ( bli_gemm_packb, // pack the right-hand operand bli_packm_blk_var1, BLIS_MR, BLIS_KR, FALSE, // do NOT invert diagonal FALSE, // reverse iteration if upper? FALSE, // reverse iteration if lower? BLIS_PACKED_COL_PANELS, BLIS_BUFFER_FOR_A_BLOCK, gemm_cntl_pb_ub ); // Create a node for partitioning the n dimension by MC. cntl_t* gemm_cntl_op_pb = bli_gemm_cntl_create_node ( family, BLIS_MC, bli_gemm_blk_var2, gemm_cntl_packb ); // Create a node for packing matrix B (which is really the left-hand // operand "A"). cntl_t* gemm_cntl_packa = bli_packm_cntl_create_node ( bli_gemm_packa, // pack the left-hand operand bli_packm_blk_var1, BLIS_NR, BLIS_KR, FALSE, // do NOT invert diagonal FALSE, // reverse iteration if upper? FALSE, // reverse iteration if lower? BLIS_PACKED_ROW_PANELS, BLIS_BUFFER_FOR_B_PANEL, gemm_cntl_op_pb ); // Create a node for partitioning the k dimension by KC. cntl_t* gemm_cntl_mm_op = bli_gemm_cntl_create_node ( family, BLIS_KC, bli_gemm_blk_var3, gemm_cntl_packa ); // Create a node for partitioning the m dimension by NC. cntl_t* gemm_cntl_vl_mm = bli_gemm_cntl_create_node ( family, BLIS_NC, bli_gemm_blk_var1, gemm_cntl_mm_op ); return gemm_cntl_vl_mm; } #endif // ----------------------------------------------------------------------------- void bli_gemm_cntl_free ( rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ) { bli_cntl_free( rntm, cntl, thread ); } // ----------------------------------------------------------------------------- cntl_t* bli_gemm_cntl_create_node ( rntm_t* rntm, opid_t family, bszid_t bszid, void_fp var_func, cntl_t* sub_node ) { return bli_cntl_create_node( rntm, family, bszid, var_func, NULL, sub_node ); } blis-0.9.0/frame/3/gemm/bli_gemm_cntl.h000066400000000000000000000051401422157504600176040ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ cntl_t* bli_gemm_cntl_create ( rntm_t* rntm, opid_t family, pack_t schema_a, pack_t schema_b, void_fp ker ); // ----------------------------------------------------------------------------- cntl_t* bli_gemmbp_cntl_create ( rntm_t* rntm, opid_t family, pack_t schema_a, pack_t schema_b, void_fp ker ); #if 0 cntl_t* bli_gemmpb_cntl_create ( opid_t family, ); #endif // ----------------------------------------------------------------------------- void bli_gemm_cntl_free ( rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ); // ----------------------------------------------------------------------------- cntl_t* bli_gemm_cntl_create_node ( rntm_t* rntm, opid_t family, bszid_t bszid, void_fp var_func, cntl_t* sub_node ); blis-0.9.0/frame/3/gemm/bli_gemm_front.c000066400000000000000000000231521422157504600177720ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_gemm_front ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl ) { bli_init_once(); obj_t a_local; obj_t b_local; obj_t c_local; // If C has a zero dimension, return early. if ( bli_obj_has_zero_dim( c ) ) { return; } // If alpha is zero, or if A or B has a zero dimension, scale C by beta // and return early. if ( bli_obj_equals( alpha, &BLIS_ZERO ) || bli_obj_has_zero_dim( a ) || bli_obj_has_zero_dim( b ) ) { bli_scalm( beta, c ); return; } #if 0 #ifdef BLIS_ENABLE_SMALL_MATRIX // Only handle small problems separately for homogeneous datatypes. if ( bli_obj_dt( a ) == bli_obj_dt( b ) && bli_obj_dt( a ) == bli_obj_dt( c ) && bli_obj_comp_prec( c ) == bli_obj_prec( c ) ) { err_t status = bli_gemm_small( alpha, a, b, beta, c, cntx, cntl ); if ( status == BLIS_SUCCESS ) return; } #endif #endif // Alias A, B, and C in case we need to apply transformations. bli_obj_alias_to( a, &a_local ); bli_obj_alias_to( b, &b_local ); bli_obj_alias_to( c, &c_local ); // Set the obj_t buffer field to the location currently implied by the row // and column offsets and then zero the offsets. If any of the original // obj_t's were views into larger matrices, this step effectively makes // those obj_t's "forget" their lineage. bli_obj_reset_origin( &a_local ); bli_obj_reset_origin( &b_local ); bli_obj_reset_origin( &c_local ); // An optimization: If C is stored by rows and the micro-kernel prefers // contiguous columns, or if C is stored by columns and the micro-kernel // prefers contiguous rows, transpose the entire operation to allow the // micro-kernel to access elements of C in its preferred manner. if ( bli_cntx_l3_vir_ukr_dislikes_storage_of( &c_local, BLIS_GEMM_UKR, cntx ) ) { bli_obj_swap( &a_local, &b_local ); bli_obj_induce_trans( &a_local ); bli_obj_induce_trans( &b_local ); bli_obj_induce_trans( &c_local ); } // Set the pack schemas within the objects. bli_l3_set_schemas( &a_local, &b_local, &c_local, cntx ); #ifdef BLIS_ENABLE_GEMM_MD cntx_t cntx_local; // If any of the storage datatypes differ, or if the computation precision // differs from the storage precision of C, utilize the mixed datatype // code path. // NOTE: If we ever want to support the caller setting the computation // domain explicitly, we will need to check the computation dt against the // storage dt of C (instead of the computation precision against the // storage precision of C). if ( bli_obj_dt( &c_local ) != bli_obj_dt( &a_local ) || bli_obj_dt( &c_local ) != bli_obj_dt( &b_local ) || bli_obj_comp_prec( &c_local ) != bli_obj_prec( &c_local ) ) { // Handle mixed datatype cases in bli_gemm_md(), which may modify // the objects or the context. (If the context is modified, cntx // is adjusted to point to cntx_local.) bli_gemm_md( &a_local, &b_local, beta, &c_local, &cntx_local, &cntx ); } #endif // Next, we handle the possibility of needing to typecast alpha to the // computation datatype and/or beta to the storage datatype of C. // Attach alpha to B, and in the process typecast alpha to the target // datatype of the matrix (which in this case is equal to the computation // datatype). bli_obj_scalar_attach( BLIS_NO_CONJUGATE, alpha, &b_local ); // Attach beta to C, and in the process typecast beta to the target // datatype of the matrix (which in this case is equal to the storage // datatype of C). bli_obj_scalar_attach( BLIS_NO_CONJUGATE, beta, &c_local ); // Change the alpha and beta pointers to BLIS_ONE since the values have // now been typecast and attached to the matrices above. alpha = &BLIS_ONE; beta = &BLIS_ONE; // Parse and interpret the contents of the rntm_t object to properly // set the ways of parallelism for each loop, and then make any // additional modifications necessary for the current operation. bli_rntm_set_ways_for_op ( BLIS_GEMM, BLIS_LEFT, // ignored for gemm/hemm/symm bli_obj_length( &c_local ), bli_obj_width( &c_local ), bli_obj_width( &a_local ), rntm ); obj_t* cp = &c_local; obj_t* betap = beta; #ifdef BLIS_ENABLE_GEMM_MD #ifdef BLIS_ENABLE_GEMM_MD_EXTRA_MEM // If any of the following conditions are met, create a temporary matrix // conformal to C into which we will accumulate the matrix product: // - the storage precision of C differs from the computation precision; // - the domains are mixed as crr; // - the storage format of C does not match the preferred orientation // of the ccr or crc cases. // Then, after the computation is complete, this matrix will be copied // or accumulated back to C. const bool is_ccr_mismatch = ( bli_gemm_md_is_ccr( &a_local, &b_local, &c_local ) && !bli_obj_is_col_stored( &c_local ) ); const bool is_crc_mismatch = ( bli_gemm_md_is_crc( &a_local, &b_local, &c_local ) && !bli_obj_is_row_stored( &c_local ) ); obj_t ct; bool use_ct = FALSE; // FGVZ: Consider adding another guard here that only creates and uses a // temporary matrix for accumulation if k < c * kc, where c is some small // constant like 2. And don't forget to use the same conditional for the // castm() and free() at the end. if ( bli_obj_prec( &c_local ) != bli_obj_comp_prec( &c_local ) || bli_gemm_md_is_crr( &a_local, &b_local, &c_local ) || is_ccr_mismatch || is_crc_mismatch ) { use_ct = TRUE; } // If we need a temporary matrix conformal to C for whatever reason, // we create it and prepare to use it now. if ( use_ct ) { const dim_t m = bli_obj_length( &c_local ); const dim_t n = bli_obj_width( &c_local ); inc_t rs = bli_obj_row_stride( &c_local ); inc_t cs = bli_obj_col_stride( &c_local ); num_t dt_ct = bli_obj_domain( &c_local ) | bli_obj_comp_prec( &c_local ); // When performing the crr case, accumulate to a contiguously-stored // real matrix so we do not have to repeatedly update C with general // stride. if ( bli_gemm_md_is_crr( &a_local, &b_local, &c_local ) ) dt_ct = BLIS_REAL | bli_obj_comp_prec( &c_local ); // When performing the mismatched ccr or crc cases, now is the time // to specify the appropriate storage so the gemm_md_c2r_ref() virtual // microkernel can output directly to C (instead of using a temporary // microtile). if ( is_ccr_mismatch ) { rs = 1; cs = m; } else if ( is_crc_mismatch ) { rs = n; cs = 1; } bli_obj_create( dt_ct, m, n, rs, cs, &ct ); const num_t dt_exec = bli_obj_exec_dt( &c_local ); const num_t dt_comp = bli_obj_comp_dt( &c_local ); bli_obj_set_target_dt( dt_ct, &ct ); bli_obj_set_exec_dt( dt_exec, &ct ); bli_obj_set_comp_dt( dt_comp, &ct ); // A naive approach would cast C to the comptuation datatype, // compute with beta, and then cast the result back to the // user-provided output matrix. However, we employ a different // approach that halves the number of memops on C (or its // typecast temporary) by writing the A*B product directly to // temporary storage, and then using xpbym to scale the // output matrix by beta and accumulate/cast the A*B product. //bli_castm( &c_local, &ct ); betap = &BLIS_ZERO; cp = &ct; } #endif #endif // Invoke the internal back-end via the thread handler. bli_l3_thread_decorator ( bli_l3_int, BLIS_GEMM, // operation family id alpha, &a_local, &b_local, betap, cp, cntx, rntm, cntl ); #ifdef BLIS_ENABLE_GEMM_MD #ifdef BLIS_ENABLE_GEMM_MD_EXTRA_MEM // If we created a temporary matrix conformal to C for whatever reason, // we copy/accumulate the result back to C and then release the object. if ( use_ct ) { obj_t beta_local; bli_obj_scalar_detach( &c_local, &beta_local ); //bli_castnzm( &ct, &c_local ); bli_xpbym( &ct, &beta_local, &c_local ); bli_obj_free( &ct ); } #endif #endif } blis-0.9.0/frame/3/gemm/bli_gemm_front.h000066400000000000000000000040421422157504600177740ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void bli_gemm_front ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl ); #ifdef BLIS_ENABLE_SMALL_MATRIX err_t bli_gemm_small ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, cntl_t* cntl ); #endif blis-0.9.0/frame/3/gemm/bli_gemm_ker_var1.c000066400000000000000000000042621422157504600203550ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #if 0 #include "blis.h" void bli_gemm_ker_var1 ( obj_t* a, obj_t* b, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ) { // Implement _ker_var1() in terms of _ker_var2() by transposing the // entire suboperation (which also requires swapping A and B). bli_obj_induce_trans( a ); bli_obj_induce_trans( b ); bli_obj_induce_trans( c ); bli_gemm_ker_var2( b, a, c, cntx, rntm, cntl, thread ); } #endif blis-0.9.0/frame/3/gemm/bli_gemm_ker_var2.c000066400000000000000000000261531422157504600203610ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" typedef void (*xpbys_mxn_vft) ( dim_t m, dim_t n, void* x, inc_t rs_x, inc_t cs_x, void* b, void* y, inc_t rs_y, inc_t cs_y ); #undef GENTFUNC2 #define GENTFUNC2(ctypex,ctypey,chx,chy,op) \ \ void PASTEMAC2(chx,chy,op) \ ( \ dim_t m, \ dim_t n, \ void* x, inc_t rs_x, inc_t cs_x, \ void* b, \ void* y, inc_t rs_y, inc_t cs_y \ ) \ { \ ctypex* restrict x_cast = x; \ ctypey* restrict b_cast = b; \ ctypey* restrict y_cast = y; \ \ PASTEMAC3(chx,chy,chy,xpbys_mxn) \ ( \ m, n, \ x_cast, rs_x, cs_x, \ b_cast, \ y_cast, rs_y, cs_y \ ); \ } INSERT_GENTFUNC2_BASIC0(xbpys_mxn_fn); INSERT_GENTFUNC2_MIXDP0(xbpys_mxn_fn); static xpbys_mxn_vft GENARRAY2_ALL(xbpys_mxn, xbpys_mxn_fn); void bli_gemm_ker_var2 ( obj_t* a, obj_t* b, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ) { num_t dt_exec = bli_obj_exec_dt( c ); num_t dt_c = bli_obj_dt( c ); pack_t schema_a = bli_obj_pack_schema( a ); pack_t schema_b = bli_obj_pack_schema( b ); dim_t m = bli_obj_length( c ); dim_t n = bli_obj_width( c ); dim_t k = bli_obj_width( a ); char* a_cast = bli_obj_buffer_at_off( a ); inc_t is_a = bli_obj_imag_stride( a ); dim_t pd_a = bli_obj_panel_dim( a ); inc_t ps_a = bli_obj_panel_stride( a ); char* b_cast = bli_obj_buffer_at_off( b ); inc_t is_b = bli_obj_imag_stride( b ); dim_t pd_b = bli_obj_panel_dim( b ); inc_t ps_b = bli_obj_panel_stride( b ); char* c_cast = bli_obj_buffer_at_off( c ); inc_t rs_c = bli_obj_row_stride( c ); inc_t cs_c = bli_obj_col_stride( c ); // If any dimension is zero, return immediately. if ( bli_zero_dim3( m, n, k ) ) return; // Detach and multiply the scalars attached to A and B. // NOTE: We know that the internal scalars of A and B are already of the // target datatypes because the necessary typecasting would have already // taken place during bli_packm_init(). obj_t scalar_a; obj_t scalar_b; bli_obj_scalar_detach( a, &scalar_a ); bli_obj_scalar_detach( b, &scalar_b ); bli_mulsc( &scalar_a, &scalar_b ); // Grab the addresses of the internal scalar buffers for the scalar // merged above and the scalar attached to C. // NOTE: We know that scalar_b is of type dt_exec due to the above code // that casts the scalars of A and B to dt_exec via scalar_a and scalar_b, // and we know that the internal scalar in C is already of the type dt_c // due to the casting in the implementation of bli_obj_scalar_attach(). char* alpha_cast = bli_obj_internal_scalar_buffer( &scalar_b ); char* beta_cast = bli_obj_internal_scalar_buffer( c ); // If 1m is being employed on a column- or row-stored matrix with a // real-valued beta, we can use the real domain macro-kernel, which // eliminates a little overhead associated with the 1m virtual // micro-kernel. // Only employ this optimization if the storage datatype of C is // equal to the execution/computation datatype. #if 1 if ( bli_cntx_method( cntx ) == BLIS_1M ) { bli_gemm_ind_recast_1m_params ( &dt_exec, &dt_c, schema_a, c, &m, &n, &k, &pd_a, &ps_a, &pd_b, &ps_b, &rs_c, &cs_c ); } #endif #ifdef BLIS_ENABLE_GEMM_MD // Tweak parameters in select mixed domain cases (rcc, crc, ccr). if ( bli_cntx_method( cntx ) == BLIS_NAT ) { bli_gemm_md_ker_var2_recast ( &dt_exec, bli_obj_dt( a ), bli_obj_dt( b ), &dt_c, &m, &n, &k, &pd_a, &ps_a, &pd_b, &ps_b, c, &rs_c, &cs_c ); } #endif siz_t dt_size = bli_dt_size( dt_exec ); siz_t dt_c_size = bli_dt_size( dt_c ); // Alias some constants to simpler names. const dim_t MR = pd_a; const dim_t NR = pd_b; //const dim_t PACKMR = cs_a; //const dim_t PACKNR = rs_b; // Query the context for the micro-kernel address and cast it to its // function pointer type. gemm_ukr_vft gemm_ukr = bli_cntx_get_l3_vir_ukr_dt( dt_exec, BLIS_GEMM_UKR, cntx ); // Query the params field from the obj_t. If it is non-NULL, grab the ukr // field of the params struct. If that function pointer is non-NULL, use it // as our microkernel instead of the default microkernel queried from the // cntx above. gemm_ker_params_t* params = bli_obj_ker_params( c ); gemm_ukr_vft user_ukr = params ? params->ukr : NULL; if ( user_ukr ) gemm_ukr = user_ukr; // Temporary C buffer for edge cases. Note that the strides of this // temporary buffer are set so that they match the storage of the // original C matrix. For example, if C is column-stored, ct will be // column-stored as well. char ct[ BLIS_STACK_BUF_MAX_SIZE ] __attribute__((aligned(BLIS_STACK_BUF_ALIGN_SIZE))); const bool col_pref = bli_cntx_l3_vir_ukr_prefers_cols_dt( dt_exec, BLIS_GEMM_UKR, cntx ); const inc_t rs_ct = ( col_pref ? 1 : NR ); const inc_t cs_ct = ( col_pref ? MR : 1 ); char* zero = bli_obj_buffer_for_const( dt_exec, &BLIS_ZERO ); // // Assumptions/assertions: // rs_a == 1 // cs_a == PACKMR // pd_a == MR // ps_a == stride to next micro-panel of A // rs_b == PACKNR // cs_b == 1 // pd_b == NR // ps_b == stride to next micro-panel of B // rs_c == (no assumptions) // cs_c == (no assumptions) // // Compute number of primary and leftover components of the m and n // dimensions. dim_t n_iter = n / NR; dim_t n_left = n % NR; dim_t m_iter = m / MR; dim_t m_left = m % MR; if ( n_left ) ++n_iter; if ( m_left ) ++m_iter; // Determine some increments used to step through A, B, and C. inc_t rstep_a = ps_a * dt_size; inc_t cstep_b = ps_b * dt_size; inc_t rstep_c = rs_c * MR * dt_c_size; inc_t cstep_c = cs_c * NR * dt_c_size; auxinfo_t aux; // Save the pack schemas of A and B to the auxinfo_t object. bli_auxinfo_set_schema_a( schema_a, &aux ); bli_auxinfo_set_schema_b( schema_b, &aux ); // Save the imaginary stride of A and B to the auxinfo_t object. bli_auxinfo_set_is_a( is_a, &aux ); bli_auxinfo_set_is_b( is_b, &aux ); // Save the virtual microkernel address and the params. bli_auxinfo_set_ukr( gemm_ukr, &aux ); bli_auxinfo_set_params( params, &aux ); // The 'thread' argument points to the thrinfo_t node for the 2nd (jr) // loop around the microkernel. Here we query the thrinfo_t node for the // 1st (ir) loop around the microkernel. thrinfo_t* caucus = bli_thrinfo_sub_node( thread ); // Query the number of threads and thread ids for each loop. dim_t jr_nt = bli_thread_n_way( thread ); dim_t jr_tid = bli_thread_work_id( thread ); dim_t ir_nt = bli_thread_n_way( caucus ); dim_t ir_tid = bli_thread_work_id( caucus ); dim_t jr_start, jr_end; dim_t ir_start, ir_end; dim_t jr_inc, ir_inc; // Determine the thread range and increment for the 2nd and 1st loops. // NOTE: The definition of bli_thread_range_jrir() will depend on whether // slab or round-robin partitioning was requested at configure-time. bli_thread_range_jrir( thread, n_iter, 1, FALSE, &jr_start, &jr_end, &jr_inc ); bli_thread_range_jrir( caucus, m_iter, 1, FALSE, &ir_start, &ir_end, &ir_inc ); // Loop over the n dimension (NR columns at a time). for ( dim_t j = jr_start; j < jr_end; j += jr_inc ) { char* b1 = b_cast + j * cstep_b; char* c1 = c_cast + j * cstep_c; dim_t n_cur = ( bli_is_not_edge_f( j, n_iter, n_left ) ? NR : n_left ); // Initialize our next panel of B to be the current panel of B. char* b2 = b1; // Loop over the m dimension (MR rows at a time). for ( dim_t i = ir_start; i < ir_end; i += ir_inc ) { char* a1 = a_cast + i * rstep_a; char* c11 = c1 + i * rstep_c; dim_t m_cur = ( bli_is_not_edge_f( i, m_iter, m_left ) ? MR : m_left ); // Compute the addresses of the next panels of A and B. char* a2 = bli_gemm_get_next_a_upanel( a1, rstep_a, ir_inc ); if ( bli_is_last_iter( i, ir_end, ir_tid, ir_nt ) ) { a2 = a_cast; b2 = bli_gemm_get_next_b_upanel( b1, cstep_b, jr_inc ); if ( bli_is_last_iter( j, jr_end, jr_tid, jr_nt ) ) b2 = b_cast; } // Save addresses of next panels of A and B to the auxinfo_t // object. bli_auxinfo_set_next_a( a2, &aux ); bli_auxinfo_set_next_b( b2, &aux ); // Edge case handling now occurs within the microkernel itself, but // we must still explicitly accumulate to a temporary microtile in // situations where a virtual microkernel is being used, such as // during the 1m method or some cases of mixed datatypes. if ( dt_exec == dt_c ) { // Invoke the gemm micro-kernel. gemm_ukr ( m_cur, n_cur, k, alpha_cast, a1, b1, beta_cast, c11, rs_c, cs_c, &aux, cntx ); } else { // Invoke the gemm micro-kernel. gemm_ukr ( MR, NR, k, alpha_cast, a1, b1, zero, &ct, rs_ct, cs_ct, &aux, cntx ); // Accumulate to C with type-casting. xbpys_mxn[ dt_exec ][ dt_c ] ( m_cur, n_cur, &ct, rs_ct, cs_ct, beta_cast, c11, rs_c, cs_c ); } } } /* PASTEMAC(ch,fprintm)( stdout, "gemm_ker_var2: b1", k, NR, b1, NR, 1, "%4.1f", "" ); PASTEMAC(ch,fprintm)( stdout, "gemm_ker_var2: a1", MR, k, a1, 1, MR, "%4.1f", "" ); PASTEMAC(ch,fprintm)( stdout, "gemm_ker_var2: c after", m_cur, n_cur, c11, rs_c, cs_c, "%4.1f", "" ); */ } blis-0.9.0/frame/3/gemm/bli_gemm_md.c000066400000000000000000000517431422157504600172510ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2017 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #ifdef BLIS_ENABLE_GEMM_MD void bli_gemm_md ( obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx_local, cntx_t** cntx ) { mddm_t doms; const bool a_is_real = bli_obj_is_real( a ); const bool a_is_comp = bli_obj_is_complex( a ); const bool b_is_real = bli_obj_is_real( b ); const bool b_is_comp = bli_obj_is_complex( b ); const bool c_is_real = bli_obj_is_real( c ); const bool c_is_comp = bli_obj_is_complex( c ); if ( c_is_real && a_is_real && b_is_real ) { // C_real += A_real * B_real doms = bli_gemm_md_rrr( a, b, beta, c, cntx_local, cntx ); } else if ( c_is_comp && a_is_comp && b_is_comp ) { // C_complex += A_complex * B_complex doms = bli_gemm_md_ccc( a, b, beta, c, cntx_local, cntx ); } else if ( c_is_comp && a_is_comp && b_is_real ) { // C_complex += A_complex * B_real doms = bli_gemm_md_ccr( a, b, beta, c, cntx_local, cntx ); } else if ( c_is_comp && a_is_real && b_is_comp ) { // C_complex += A_real * B_complex doms = bli_gemm_md_crc( a, b, beta, c, cntx_local, cntx ); } else if ( c_is_real && a_is_comp && b_is_comp ) { // C_real += A_complex * B_complex doms = bli_gemm_md_rcc( a, b, beta, c, cntx_local, cntx ); } else if ( c_is_comp && a_is_real && b_is_real ) { // C_complex += A_real * B_real doms = bli_gemm_md_crr( a, b, beta, c, cntx_local, cntx ); } else if ( c_is_real && a_is_comp && b_is_real ) { // C_real += A_complex * B_real doms = bli_gemm_md_rcr( a, b, beta, c, cntx_local, cntx ); } else if ( c_is_real && a_is_real && b_is_comp ) { // C_real += A_real * B_complex doms = bli_gemm_md_rrc( a, b, beta, c, cntx_local, cntx ); } else { doms.comp = BLIS_REAL; doms.exec = BLIS_REAL; // This should never execute. bli_abort(); } // Extract the computation and execution domains from the struct // returned above. dom_t dom_comp = doms.comp; dom_t dom_exec = doms.exec; // Inspect the computation precision of C. (The user may have set // this explicitly to request the precision in which the computation // should take place.) prec_t prec_comp = bli_obj_comp_prec( c ); // The computation precision tells us the target precision of A and B. // NOTE: We don't set the target domain here. The target domain would // either be unchanged, or would have been changed in one of the eight // domain cases above. bli_obj_set_target_prec( prec_comp, a ); bli_obj_set_target_prec( prec_comp, b ); // Combine the execution domain with the computation precision to form // the execution datatype. (The computation precision and execution // precision are always equal.) num_t dt_exec = dom_exec | prec_comp; // Set the execution datatypes of A, B, and C. bli_obj_set_exec_dt( dt_exec, a ); bli_obj_set_exec_dt( dt_exec, b ); bli_obj_set_exec_dt( dt_exec, c ); // Combine the computation precision and computation domain to form the // computation datatype. num_t dt_comp = dom_comp | prec_comp; // Set the computation datatypes of A, B, and C. bli_obj_set_comp_dt( dt_comp, a ); bli_obj_set_comp_dt( dt_comp, b ); bli_obj_set_comp_dt( dt_comp, c ); } // ----------------------------------------------------------------------------- // cab mddm_t bli_gemm_md_ccr ( obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx_local, cntx_t** cntx ) { mddm_t doms; // We assume that the requested computation domain is complex. //dom_t dom_comp_in = bli_obj_comp_domain( c ); //dom_t dom_comp_in = BLIS_COMPLEX; // For ccr, the computation (ukernel) will be real, but the execution // will appear complex to other parts of the implementation. doms.comp = BLIS_REAL; doms.exec = BLIS_COMPLEX; // Here we construct the computation datatype, which for the ccr case // is equal to the real projection of the execution datatype, and use // that computation datatype to query the corresponding ukernel output // preference. const num_t dt = BLIS_REAL | bli_obj_comp_prec( c ); const bool row_pref = bli_cntx_l3_nat_ukr_prefers_rows_dt( dt, BLIS_GEMM_UKR, *cntx ); // We can only perform this case of mixed-domain gemm, C += A*B where // B is real, if the microkernel prefers column output. If it prefers // row output, we must induce a transposition and perform C += A*B // where A (formerly B) is real. if ( row_pref ) { bli_obj_swap( a, b ); bli_obj_induce_trans( a ); bli_obj_induce_trans( b ); bli_obj_induce_trans( c ); // We must swap the pack schemas because the schemas were set before // the objects were swapped. bli_obj_swap_pack_schemas( a, b ); return bli_gemm_md_crc( a, b, beta, c, cntx_local, cntx ); } // Create a local copy of the context and then prepare to use this // context instead of the one passed in. *cntx_local = **cntx; *cntx = cntx_local; // Copy the real domain blocksizes into the slots of their complex // counterparts. blksz_t* blksz_mr = bli_cntx_get_blksz( BLIS_MR, *cntx ); blksz_t* blksz_nr = bli_cntx_get_blksz( BLIS_NR, *cntx ); blksz_t* blksz_mc = bli_cntx_get_blksz( BLIS_MC, *cntx ); blksz_t* blksz_nc = bli_cntx_get_blksz( BLIS_NC, *cntx ); blksz_t* blksz_kc = bli_cntx_get_blksz( BLIS_KC, *cntx ); bli_blksz_copy_dt( BLIS_FLOAT, blksz_mr, BLIS_SCOMPLEX, blksz_mr ); bli_blksz_copy_dt( BLIS_DOUBLE, blksz_mr, BLIS_DCOMPLEX, blksz_mr ); bli_blksz_copy_dt( BLIS_FLOAT, blksz_nr, BLIS_SCOMPLEX, blksz_nr ); bli_blksz_copy_dt( BLIS_DOUBLE, blksz_nr, BLIS_DCOMPLEX, blksz_nr ); bli_blksz_copy_dt( BLIS_FLOAT, blksz_mc, BLIS_SCOMPLEX, blksz_mc ); bli_blksz_copy_dt( BLIS_DOUBLE, blksz_mc, BLIS_DCOMPLEX, blksz_mc ); bli_blksz_copy_dt( BLIS_FLOAT, blksz_nc, BLIS_SCOMPLEX, blksz_nc ); bli_blksz_copy_dt( BLIS_DOUBLE, blksz_nc, BLIS_DCOMPLEX, blksz_nc ); bli_blksz_copy_dt( BLIS_FLOAT, blksz_kc, BLIS_SCOMPLEX, blksz_kc ); bli_blksz_copy_dt( BLIS_DOUBLE, blksz_kc, BLIS_DCOMPLEX, blksz_kc ); // Halve both the real and complex MR's (which are both real MR's). bli_blksz_scale_def_max( 1, 2, BLIS_FLOAT, blksz_mr ); bli_blksz_scale_def_max( 1, 2, BLIS_DOUBLE, blksz_mr ); bli_blksz_scale_def_max( 1, 2, BLIS_SCOMPLEX, blksz_mr ); bli_blksz_scale_def_max( 1, 2, BLIS_DCOMPLEX, blksz_mr ); // Halve both the real and complex MC's (which are both real MC's). bli_blksz_scale_def_max( 1, 2, BLIS_FLOAT, blksz_mc ); bli_blksz_scale_def_max( 1, 2, BLIS_DOUBLE, blksz_mc ); bli_blksz_scale_def_max( 1, 2, BLIS_SCOMPLEX, blksz_mc ); bli_blksz_scale_def_max( 1, 2, BLIS_DCOMPLEX, blksz_mc ); // Use the default pack schemas in the objects. // static func_t* bli_cntx_get_l3_vir_ukrs( l3ukr_t ukr_id, cntx_t* cntx ) func_t* l3_vir_ukrs = bli_cntx_get_l3_vir_ukrs( BLIS_GEMM_UKR, *cntx ); // Rather than check which complex datatype dt_comp refers to, we set // the mixed-domain virtual microkernel for both types. bli_func_set_dt( bli_cgemm_md_c2r_ref, BLIS_SCOMPLEX, l3_vir_ukrs ); bli_func_set_dt( bli_zgemm_md_c2r_ref, BLIS_DCOMPLEX, l3_vir_ukrs ); // Return the computation and execution domains. return doms; } // ----------------------------------------------------------------------------- // cab mddm_t bli_gemm_md_crc ( obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx_local, cntx_t** cntx ) { mddm_t doms; // We assume that the requested computation domain is complex. //dom_t dom_comp_in = bli_obj_comp_domain( c ); //dom_t dom_comp_in = BLIS_COMPLEX; // For crc, the computation (ukernel) will be real, but the execution // will appear complex to other parts of the implementation. doms.comp = BLIS_REAL; doms.exec = BLIS_COMPLEX; // Here we construct the computation datatype, which for the crc case // is equal to the real projection of the execution datatype, and use // that computation datatype to query the corresponding ukernel output // preference. const num_t dt = BLIS_REAL | bli_obj_comp_prec( c ); const bool col_pref = bli_cntx_l3_nat_ukr_prefers_cols_dt( dt, BLIS_GEMM_UKR, *cntx ); // We can only perform this case of mixed-domain gemm, C += A*B where // A is real, if the microkernel prefers row output. If it prefers // column output, we must induce a transposition and perform C += A*B // where B (formerly A) is real. if ( col_pref ) { bli_obj_swap( a, b ); bli_obj_induce_trans( a ); bli_obj_induce_trans( b ); bli_obj_induce_trans( c ); // We must swap the pack schemas because the schemas were set before // the objects were swapped. bli_obj_swap_pack_schemas( a, b ); return bli_gemm_md_ccr( a, b, beta, c, cntx_local, cntx ); } // Create a local copy of the context and then prepare to use this // context instead of the one passed in. *cntx_local = **cntx; *cntx = cntx_local; // Copy the real domain blocksizes into the slots of their complex // counterparts. blksz_t* blksz_mr = bli_cntx_get_blksz( BLIS_MR, *cntx ); blksz_t* blksz_nr = bli_cntx_get_blksz( BLIS_NR, *cntx ); blksz_t* blksz_mc = bli_cntx_get_blksz( BLIS_MC, *cntx ); blksz_t* blksz_nc = bli_cntx_get_blksz( BLIS_NC, *cntx ); blksz_t* blksz_kc = bli_cntx_get_blksz( BLIS_KC, *cntx ); bli_blksz_copy_dt( BLIS_FLOAT, blksz_mr, BLIS_SCOMPLEX, blksz_mr ); bli_blksz_copy_dt( BLIS_DOUBLE, blksz_mr, BLIS_DCOMPLEX, blksz_mr ); bli_blksz_copy_dt( BLIS_FLOAT, blksz_nr, BLIS_SCOMPLEX, blksz_nr ); bli_blksz_copy_dt( BLIS_DOUBLE, blksz_nr, BLIS_DCOMPLEX, blksz_nr ); bli_blksz_copy_dt( BLIS_FLOAT, blksz_mc, BLIS_SCOMPLEX, blksz_mc ); bli_blksz_copy_dt( BLIS_DOUBLE, blksz_mc, BLIS_DCOMPLEX, blksz_mc ); bli_blksz_copy_dt( BLIS_FLOAT, blksz_nc, BLIS_SCOMPLEX, blksz_nc ); bli_blksz_copy_dt( BLIS_DOUBLE, blksz_nc, BLIS_DCOMPLEX, blksz_nc ); bli_blksz_copy_dt( BLIS_FLOAT, blksz_kc, BLIS_SCOMPLEX, blksz_kc ); bli_blksz_copy_dt( BLIS_DOUBLE, blksz_kc, BLIS_DCOMPLEX, blksz_kc ); // Halve both the real and complex NR's (which are both real NR's). bli_blksz_scale_def_max( 1, 2, BLIS_FLOAT, blksz_nr ); bli_blksz_scale_def_max( 1, 2, BLIS_DOUBLE, blksz_nr ); bli_blksz_scale_def_max( 1, 2, BLIS_SCOMPLEX, blksz_nr ); bli_blksz_scale_def_max( 1, 2, BLIS_DCOMPLEX, blksz_nr ); // Halve both the real and complex NC's (which are both real NC's). bli_blksz_scale_def_max( 1, 2, BLIS_FLOAT, blksz_nc ); bli_blksz_scale_def_max( 1, 2, BLIS_DOUBLE, blksz_nc ); bli_blksz_scale_def_max( 1, 2, BLIS_SCOMPLEX, blksz_nc ); bli_blksz_scale_def_max( 1, 2, BLIS_DCOMPLEX, blksz_nc ); // Use the default pack schemas in the objects. // static func_t* bli_cntx_get_l3_vir_ukrs( l3ukr_t ukr_id, cntx_t* cntx ) func_t* l3_vir_ukrs = bli_cntx_get_l3_vir_ukrs( BLIS_GEMM_UKR, *cntx ); // Rather than check which complex datatype dt_comp refers to, we set // the mixed-domain virtual microkernel for both types. bli_func_set_dt( bli_cgemm_md_c2r_ref, BLIS_SCOMPLEX, l3_vir_ukrs ); bli_func_set_dt( bli_zgemm_md_c2r_ref, BLIS_DCOMPLEX, l3_vir_ukrs ); // Return the computation and execution domains. return doms; } // ----------------------------------------------------------------------------- // cab mddm_t bli_gemm_md_rcc ( obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx_local, cntx_t** cntx ) { mddm_t doms; // We assume that the requested computation domain is complex. //dom_t dom_comp_in = bli_obj_comp_domain( c ); //dom_t dom_comp_in = BLIS_COMPLEX; // For rcc, the computation (ukernel) will be real, and since the output // matrix C is also real, so must be the execution domain. doms.comp = BLIS_REAL; doms.exec = BLIS_REAL; // Create a local copy of the context and then prepare to use this // context instead of the one passed in. *cntx_local = **cntx; *cntx = cntx_local; // Copy the real domain blocksizes into the slots of their complex // counterparts. blksz_t* blksz_mr = bli_cntx_get_blksz( BLIS_MR, *cntx ); blksz_t* blksz_nr = bli_cntx_get_blksz( BLIS_NR, *cntx ); blksz_t* blksz_mc = bli_cntx_get_blksz( BLIS_MC, *cntx ); blksz_t* blksz_nc = bli_cntx_get_blksz( BLIS_NC, *cntx ); blksz_t* blksz_kc = bli_cntx_get_blksz( BLIS_KC, *cntx ); bli_blksz_copy_dt( BLIS_FLOAT, blksz_mr, BLIS_SCOMPLEX, blksz_mr ); bli_blksz_copy_dt( BLIS_DOUBLE, blksz_mr, BLIS_DCOMPLEX, blksz_mr ); bli_blksz_copy_dt( BLIS_FLOAT, blksz_nr, BLIS_SCOMPLEX, blksz_nr ); bli_blksz_copy_dt( BLIS_DOUBLE, blksz_nr, BLIS_DCOMPLEX, blksz_nr ); bli_blksz_copy_dt( BLIS_FLOAT, blksz_mc, BLIS_SCOMPLEX, blksz_mc ); bli_blksz_copy_dt( BLIS_DOUBLE, blksz_mc, BLIS_DCOMPLEX, blksz_mc ); bli_blksz_copy_dt( BLIS_FLOAT, blksz_nc, BLIS_SCOMPLEX, blksz_nc ); bli_blksz_copy_dt( BLIS_DOUBLE, blksz_nc, BLIS_DCOMPLEX, blksz_nc ); bli_blksz_copy_dt( BLIS_FLOAT, blksz_kc, BLIS_SCOMPLEX, blksz_kc ); bli_blksz_copy_dt( BLIS_DOUBLE, blksz_kc, BLIS_DCOMPLEX, blksz_kc ); // Halve both the real and complex KC's (which are both real KC's). bli_blksz_scale_def_max( 1, 2, BLIS_FLOAT, blksz_kc ); bli_blksz_scale_def_max( 1, 2, BLIS_DOUBLE, blksz_kc ); bli_blksz_scale_def_max( 1, 2, BLIS_SCOMPLEX, blksz_kc ); bli_blksz_scale_def_max( 1, 2, BLIS_DCOMPLEX, blksz_kc ); // Use the 1r pack schema for both A and B with the conjugation // of A or B toggled (to produce ar * br - ai * bi). bli_obj_set_pack_schema( BLIS_PACKED_ROW_PANELS_1R, a ); bli_obj_set_pack_schema( BLIS_PACKED_COL_PANELS_1R, b ); bli_obj_toggle_conj( b ); // We also need to copy over the packm kernels from the 1m // context. We query the address of that context here. // NOTE: This is needed for situations where the rcc case does not // involve any casting to different precisions, since currently // bli_packm_blk_var1() is coded to hand off control to // bli_packm_blk_var1_md() only when the storage datatype differs from // the target datatype. (The packm_blk_var1_md() function has "built-in" // support for packing to 1r (and 1e) schemas, whereas the // packm_blk_var1() function relies on packm kernels for packing to 1r. const num_t dt_complex = bli_obj_dt( a ); cntx_t* cntx_1m = bli_gks_query_ind_cntx( BLIS_1M, dt_complex ); func_t* cntx_funcs = bli_cntx_packm_kers_buf( *cntx ); func_t* cntx_1m_funcs = bli_cntx_packm_kers_buf( cntx_1m ); for ( dim_t i = 0; i <= BLIS_PACKM_31XK_KER; ++i ) { cntx_funcs[ i ] = cntx_1m_funcs[ i ]; } // Return the computation and execution domains. return doms; } // ----------------------------------------------------------------------------- // cab mddm_t bli_gemm_md_crr ( obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx_local, cntx_t** cntx ) { mddm_t doms; #ifndef BLIS_ENABLE_GEMM_MD_EXTRA_MEM obj_t c_real; #endif // We assume that the requested computation domain is real. //dom_t dom_comp_in = bli_obj_comp_domain( c ); //dom_t dom_comp_in = BLIS_REAL; // For crr, the computation (ukernel) will be real, and since we will // be updating only the real part of the output matrix C, the exectuion // domain is also real. doms.comp = BLIS_REAL; doms.exec = BLIS_REAL; // Since the A*B product is real, we can update only the real part of // C. Thus, we convert the obj_t for the complex matrix to one that // represents only the real part. HOWEVER, there are two situations in // which we forgo this trick: // - If extra memory optimizations are enabled, we should leave C alone // since we'll be computing A*B to a temporary matrix and accumulating // that result back to C, and in order for that to work, we need to // allow that code to continue accessing C as a complex matrix. // - Even if extra memory optimizations are diabled, logically projecting // C as a real matrix can still cause problems if beta is non-unit. In // that situation, the implementation won't get a chance to scale the // imaginary components of C by beta, and thus it would compute the // wrong answer. Thus, if beta is non-unit, we must leave C alone. #ifndef BLIS_ENABLE_GEMM_MD_EXTRA_MEM if ( bli_obj_equals( beta, &BLIS_ONE ) ) { bli_obj_real_part( c, &c_real ); // Overwrite the complex obj_t with its real-only alias. *c = c_real; } #endif // Use the default pack schemas in the objects. // Return the computation and execution domains. return doms; } // ----------------------------------------------------------------------------- // cab mddm_t bli_gemm_md_rcr ( obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx_local, cntx_t** cntx ) { mddm_t doms; obj_t a_real; // We assume that the requested computation domain is real. //dom_t dom_comp_in = bli_obj_comp_domain( c ); //dom_t dom_comp_in = BLIS_REAL; // For rcr, the computation (ukernel) will be real, and since the output // matrix C is also real, so must be the execution domain. doms.comp = BLIS_REAL; doms.exec = BLIS_REAL; // Convert the obj_t for the complex matrix to one that represents only // the real part. bli_obj_real_part( a, &a_real ); // Overwrite the complex obj_t with its real-only alias. *a = a_real; // Use the default pack schemas in the objects. // Return the computation and execution domains. return doms; } // ----------------------------------------------------------------------------- // cab mddm_t bli_gemm_md_rrc ( obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx_local, cntx_t** cntx ) { mddm_t doms; obj_t b_real; // We assume that the requested computation domain is real. //dom_t dom_comp_in = bli_obj_comp_domain( c ); //dom_t dom_comp_in = BLIS_REAL; // For rcr, the computation (ukernel) will be real, and since the output // matrix C is also real, so must be the execution domain. doms.comp = BLIS_REAL; doms.exec = BLIS_REAL; // Convert the obj_t for the complex matrix to one that represents only // the real part. bli_obj_real_part( b, &b_real ); // Overwrite the complex obj_t with its real-only alias. *b = b_real; // Use the default pack schemas in the objects. // Return the computation and execution domains. return doms; } // ----------------------------------------------------------------------------- // cab mddm_t bli_gemm_md_rrr ( obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx_local, cntx_t** cntx ) { mddm_t doms; // We assume that the requested computation domain is real. //dom_t dom_comp_in = bli_obj_comp_domain( c ); //dom_t dom_comp_in = BLIS_REAL; // For rrr, the computation (ukernel) and execution domains are both // real. doms.comp = BLIS_REAL; doms.exec = BLIS_REAL; // Use the default pack schemas in the objects. // Return the computation and execution domains. return doms; } // ----------------------------------------------------------------------------- // cab mddm_t bli_gemm_md_ccc ( obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx_local, cntx_t** cntx ) { mddm_t doms; // We assume that the requested computation domain is complex. //dom_t dom_comp_in = bli_obj_comp_domain( c ); //dom_t dom_comp_in = BLIS_COMPLEX; // For ccc, the computation (ukernel) and execution domains are both // complex. doms.comp = BLIS_COMPLEX; doms.exec = BLIS_COMPLEX; // Use the default pack schemas in the objects. // Return the computation and execution domains. return doms; } #endif blis-0.9.0/frame/3/gemm/bli_gemm_md.h000066400000000000000000000221301422157504600172420ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "bli_gemm_md_c2r_ref.h" // Define a local struct type that makes returning two values easier. typedef struct mddm_s { dom_t comp; dom_t exec; } mddm_t; void bli_gemm_md ( obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx_local, cntx_t** cntx ); mddm_t bli_gemm_md_ccc( obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx_l, cntx_t** cntx ); mddm_t bli_gemm_md_ccr( obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx_l, cntx_t** cntx ); mddm_t bli_gemm_md_crc( obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx_l, cntx_t** cntx ); mddm_t bli_gemm_md_rcc( obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx_l, cntx_t** cntx ); mddm_t bli_gemm_md_rrc( obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx_l, cntx_t** cntx ); mddm_t bli_gemm_md_rcr( obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx_l, cntx_t** cntx ); mddm_t bli_gemm_md_crr( obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx_l, cntx_t** cntx ); mddm_t bli_gemm_md_rrr( obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx_l, cntx_t** cntx ); // ----------------------------------------------------------------------------- void bli_gemm_md_front ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl ); void bli_gemm_md_zgemm ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl ); // ----------------------------------------------------------------------------- BLIS_INLINE bool bli_gemm_md_is_crr( obj_t* a, obj_t* b, obj_t* c ) { bool r_val = FALSE; // NOTE: The last conditional subexpression is necessary if/when we // allow the user to specify the computation domain. (The computation // domain is currently ignored, but once it is honored as a user- // settable value, it will affect the execution domain, which is what // is checked below. Until then, the last expression is not actually // necessary since crr is already unconditionally associated with an // execution domain of BLIS_REAL.) if ( bli_obj_is_complex( c ) && bli_obj_is_real( a ) && bli_obj_is_real( b ) && bli_obj_exec_domain( c ) == BLIS_REAL ) r_val = TRUE; return r_val; } BLIS_INLINE bool bli_gemm_md_is_ccr( obj_t* a, obj_t* b, obj_t* c ) { bool r_val = FALSE; // NOTE: The last conditional subexpression is necessary if/when we // allow the user to specify the computation domain. (The computation // domain is currently ignored, but once it is honored as a user- // settable value, it will affect the execution domain, which is what // is checked below. Until then, the last expression is not actually // necessary since ccr is already unconditionally associated with an // execution domain of BLIS_COMPLEX.) if ( bli_obj_is_complex( c ) && bli_obj_is_complex( a ) && bli_obj_is_real( b ) && bli_obj_exec_domain( c ) == BLIS_COMPLEX ) r_val = TRUE; return r_val; } BLIS_INLINE bool bli_gemm_md_is_crc( obj_t* a, obj_t* b, obj_t* c ) { bool r_val = FALSE; // NOTE: The last conditional subexpression is necessary if/when we // allow the user to specify the computation domain. (The computation // domain is currently ignored, but once it is honored as a user- // settable value, it will affect the execution domain, which is what // is checked below. Until then, the last expression is not actually // necessary since crc is already unconditionally associated with an // execution domain of BLIS_COMPLEX.) if ( bli_obj_is_complex( c ) && bli_obj_is_real( a ) && bli_obj_is_complex( b ) && bli_obj_exec_domain( c ) == BLIS_COMPLEX ) r_val = TRUE; return r_val; } // ----------------------------------------------------------------------------- BLIS_INLINE void bli_gemm_md_ker_var2_recast ( num_t* dt_comp, num_t dt_a, num_t dt_b, num_t* dt_c, dim_t* m, dim_t* n, dim_t* k, inc_t* pd_a, inc_t* ps_a, inc_t* pd_b, inc_t* ps_b, obj_t* c, inc_t* rs_c, inc_t* cs_c ) { if ( bli_is_real( *dt_c ) && bli_is_complex( dt_a ) && bli_is_complex( dt_b ) ) { // The rcc case is executed with a real macrokernel, so we need to // double the k dimension (because both A and B are packed to the 1r // schema), and also the panel strides of A and B since they were // packed as complex matrices and we now need to convert them to // units of real elements. *k *= 2; *ps_a *= 2; *ps_b *= 2; } else if ( bli_is_complex( *dt_c ) && bli_is_real( dt_a ) && bli_is_complex( dt_b ) ) { #if 1 obj_t beta; bli_obj_scalar_detach( c, &beta ); if ( //bli_obj_imag_equals( &beta, &BLIS_ZERO ) && bli_obj_imag_is_zero( &beta ) && bli_is_row_stored( *rs_c, *cs_c ) && bli_obj_prec( c ) == bli_obj_comp_prec( c ) ) { // If beta is real, and C is not general-stored, and the computation // precision is equal to the storage precision of C, we can use the // real macrokernel (and real microkernel, which is already stored // to the real virtual microkernel slots of the context) instead of // the complex macrokernel and c2r virtual microkernel. *dt_comp = bli_dt_proj_to_real( *dt_comp ); *dt_c = bli_dt_proj_to_real( *dt_c ); *n *= 2; *pd_b *= 2; *ps_b *= 2; *rs_c *= 2; } else #endif { // Generally speaking, the crc case is executed with a complex // macrokernel, so we need to halve the panel stride of A (which // is real) since the macrokernel will perform the pointer // arithmetic in units of complex elements. *ps_a /= 2; } } else if ( bli_is_complex( *dt_c ) && bli_is_complex( dt_a ) && bli_is_real( dt_b ) ) { #if 1 obj_t beta; bli_obj_scalar_detach( c, &beta ); if ( //bli_obj_imag_equals( &beta, &BLIS_ZERO ) && bli_obj_imag_is_zero( &beta ) && bli_is_col_stored( *rs_c, *cs_c ) && bli_obj_prec( c ) == bli_obj_comp_prec( c ) ) { // If beta is real, and C is not general-stored, and the computation // precision is equal to the storage precision of C, we can use the // real macrokernel (and real microkernel, which is already stored // to the real virtual microkernel slots of the context) instead of // the complex macrokernel and c2r virtual microkernel. *dt_comp = bli_dt_proj_to_real( *dt_comp ); *dt_c = bli_dt_proj_to_real( *dt_c ); *m *= 2; *pd_a *= 2; *ps_a *= 2; *cs_c *= 2; } else #endif { // Generally speaking, the ccr case is executed with a complex // macrokernel, so we need to halve the panel stride of B (which // is real) since the macrokernel will perform the pointer // arithmetic in units of complex elements. *ps_b /= 2; } } #if 0 else if ( bli_is_real( dt_c ) && bli_is_real( dt_a ) && bli_is_real( dt_b ) ) { // No action needed. //printf( "gemm_md.h: rrr: m n k are now %d %d %d\n", (int)*m, (int)*n, (int)*k ); } else if ( bli_is_complex( dt_c ) && bli_is_real( dt_a ) && bli_is_real( dt_b ) ) { // No action needed. } else if ( bli_is_real( dt_c ) && bli_is_complex( dt_a ) && bli_is_real( dt_b ) ) { // No action needed. } else if ( bli_is_real( dt_c ) && bli_is_real( dt_a ) && bli_is_complex( dt_b ) ) { // No action needed. } #endif } blis-0.9.0/frame/3/gemm/bli_gemm_md_c2r_ref.c000066400000000000000000000205241422157504600206440ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #ifdef BLIS_ENABLE_GEMM_MD #undef GENTFUNCCO #define GENTFUNCCO( ctype, ctype_r, ch, chr, opname, suf ) \ \ void PASTEMAC2(ch,opname,suf) \ ( \ dim_t m, \ dim_t n, \ dim_t k, \ ctype* restrict alpha, \ ctype* restrict a, \ ctype* restrict b, \ ctype* restrict beta, \ ctype* restrict c, inc_t rs_c, inc_t cs_c, \ auxinfo_t* restrict data, \ cntx_t* restrict cntx \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ const num_t dt_r = PASTEMAC(chr,type); \ \ PASTECH(chr,gemm_ukr_ft) \ rgemm_ukr = bli_cntx_get_l3_nat_ukr_dt( dt_r, BLIS_GEMM_UKR, cntx ); \ const bool col_pref = bli_cntx_l3_nat_ukr_prefers_cols_dt( dt_r, BLIS_GEMM_UKR, cntx ); \ const bool row_pref = !col_pref; \ \ const dim_t mr = bli_cntx_get_blksz_def_dt( dt, BLIS_MR, cntx ); \ const dim_t nr = bli_cntx_get_blksz_def_dt( dt, BLIS_NR, cntx ); \ \ dim_t mr_r = mr; \ dim_t nr_r = nr; \ \ ctype ct[ BLIS_STACK_BUF_MAX_SIZE \ / sizeof( ctype_r ) ] \ __attribute__((aligned(BLIS_STACK_BUF_ALIGN_SIZE))); \ inc_t rs_ct; \ inc_t cs_ct; \ \ ctype_r* restrict a_r = ( ctype_r* )a; \ \ ctype_r* restrict b_r = ( ctype_r* )b; \ \ ctype_r* restrict zero_r = PASTEMAC(chr,0); \ \ ctype_r* restrict alpha_r = &PASTEMAC(ch,real)( *alpha ); \ /* ctype_r* restrict alpha_i = &PASTEMAC(ch,imag)( *alpha ); \ */ \ \ ctype_r* restrict beta_r = &PASTEMAC(ch,real)( *beta ); \ ctype_r* restrict beta_i = &PASTEMAC(ch,imag)( *beta ); \ \ dim_t m_use; \ dim_t n_use; \ \ ctype_r* c_use; \ inc_t rs_c_use; \ inc_t cs_c_use; \ \ bool using_ct; \ \ /* This virtual microkernel is used by ccr and crc mixed-domain cases when any of the following conditions are met: - beta is complex (ie: has a non-zero imaginary component) - C is general-stored - the computation precision differs from the storage of C If, however, none of the above conditions are met, then the real domain macrokernel can be (and will be) called instead of calling the complex macrokernel (and this virtual microkernel). */ \ \ /* PASTEMAC(chr,fprintm)( stdout, "gemm_ukr: a", mr, k, \ a_r, 1, mr, "%5.2f", "" ); \ PASTEMAC(chr,fprintm)( stdout, "gemm_ukr: b", k, nr, \ b_r, nr, 1, "%5.2f", "" ); \ PASTEMAC(chr,fprintm)( stdout, "gemm_ukr: c before", mr, nr, \ c_use, rs_c_use, cs_c_use, "%5.2f", "" ); \ */ \ \ /* SAFETY CHECK: The higher level implementation should never allow an alpha with non-zero imaginary component to be passed in, because it can't be applied properly using the 1m method. If alpha is not real, then something is very wrong. */ \ /* if ( !PASTEMAC(chr,eq0)( *alpha_i ) ) \ bli_check_error_code( BLIS_NOT_YET_IMPLEMENTED ); \ */ \ \ /* If beta has a non-zero imaginary component OR if c is stored with general stride, then we compute the alpha*a*b product into temporary storage and then accumulate that result into c afterwards. Note that the other two cases concerning disagreement between the storage of C and the output preference of the micro-kernel, should ONLY occur in the context of trsm, whereby this virtual micro-kernel is called directly from the trsm macro-kernel to update the micro-tile b11 that exists within the packed row-panel of B. Indeed that is the reason those cases MUST be explicitly handled. */ \ if ( !PASTEMAC(chr,eq0)( *beta_i ) ) using_ct = TRUE; \ else if ( bli_is_col_stored( rs_c, cs_c ) && row_pref ) using_ct = TRUE; \ else if ( bli_is_row_stored( rs_c, cs_c ) && col_pref ) using_ct = TRUE; \ else if ( bli_is_gen_stored( rs_c, cs_c ) ) using_ct = TRUE; \ else using_ct = FALSE; \ \ \ if ( using_ct ) \ { \ /* In the atypical cases, we compute the result into temporary workspace ct and then accumulate it back to c at the end. */ \ \ /* Set the strides of ct based on the preference of the underlying native real domain gemm micro-kernel. Note that we set the ct strides in units of complex elements. */ \ if ( col_pref ) { rs_ct = 1; cs_ct = mr; } \ else { rs_ct = nr; cs_ct = 1; } \ \ c_use = ( ctype_r* )ct; \ rs_c_use = rs_ct; \ cs_c_use = cs_ct; \ \ /* Convert the strides and corresponding microtile dimension from being in units of complex elements to be in units of real elements. */ \ if ( bli_is_col_stored( rs_c_use, cs_c_use ) ) { cs_c_use *= 2; mr_r *= 2; } \ else { rs_c_use *= 2; nr_r *= 2; }\ \ /* c = beta * c + alpha_r * a * b; */ \ rgemm_ukr \ ( \ mr_r, \ nr_r, \ k, \ alpha_r, \ a_r, \ b_r, \ zero_r, \ c_use, rs_c_use, cs_c_use, \ data, \ cntx \ ); \ \ /* Accumulate the final result in ct back to c. */ \ if ( PASTEMAC(ch,eq1)( *beta ) ) \ { \ for ( dim_t j = 0; j < n; ++j ) \ for ( dim_t i = 0; i < m; ++i ) \ { \ PASTEMAC(ch,adds)( *(ct + i*rs_ct + j*cs_ct), \ *(c + i*rs_c + j*cs_c ) ); \ } \ } \ else if ( PASTEMAC(ch,eq0)( *beta ) ) \ { \ for ( dim_t j = 0; j < n; ++j ) \ for ( dim_t i = 0; i < m; ++i ) \ { \ PASTEMAC(ch,copys)( *(ct + i*rs_ct + j*cs_ct), \ *(c + i*rs_c + j*cs_c ) ); \ } \ } \ else \ { \ for ( dim_t j = 0; j < n; ++j ) \ for ( dim_t i = 0; i < m; ++i ) \ { \ PASTEMAC(ch,xpbys)( *(ct + i*rs_ct + j*cs_ct), \ *beta, \ *(c + i*rs_c + j*cs_c ) ); \ } \ } \ } \ else \ { \ /* In the typical cases, we use the real part of beta and accumulate directly into the output matrix c. */ \ \ c_use = ( ctype_r* )c; \ rs_c_use = rs_c; \ cs_c_use = cs_c; \ m_use = m; \ n_use = n; \ \ /* Convert the strides and corresponding microtile dimension from being in units of complex elements to be in units of real elements. */ \ if ( bli_is_col_stored( rs_c_use, cs_c_use ) ) { cs_c_use *= 2; m_use *= 2; } \ else { rs_c_use *= 2; n_use *= 2; } \ \ /* c = beta * c + alpha_r * a * b; */ \ rgemm_ukr \ ( \ m_use, \ n_use, \ k, \ alpha_r, \ a_r, \ b_r, \ beta_r, \ c_use, rs_c_use, cs_c_use, \ data, \ cntx \ ); \ } \ } INSERT_GENTFUNCCO_BASIC( gemm_md_c2r, BLIS_REF_SUFFIX ) #endif blis-0.9.0/frame/3/gemm/bli_gemm_md_c2r_ref.h000066400000000000000000000035431422157504600206530ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // -- Level-3 native micro-kernel prototype redefinitions ---------------------- #undef gemm_ukr_name #define gemm_ukr_name gemm_md_c2r_ref // Include the native micro-kernel API template. #include "bli_l3_ukr.h" blis-0.9.0/frame/3/gemm/bli_gemm_var.h000066400000000000000000000043121422157504600174340ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // gemm kernel parameter struct. // typedef struct { gemm_ukr_vft ukr; } gemm_ker_params_t; // // Prototype object-based interfaces. // #undef GENPROT #define GENPROT( opname ) \ \ void PASTEMAC0(opname) \ ( \ obj_t* a, \ obj_t* b, \ obj_t* c, \ cntx_t* cntx, \ rntm_t* rntm, \ cntl_t* cntl, \ thrinfo_t* thread \ ); GENPROT( gemm_blk_var1 ) GENPROT( gemm_blk_var2 ) GENPROT( gemm_blk_var3 ) GENPROT( gemm_ker_var1 ) GENPROT( gemm_ker_var2 ) blis-0.9.0/frame/3/gemm/ind/000077500000000000000000000000001422157504600154125ustar00rootroot00000000000000blis-0.9.0/frame/3/gemm/ind/bli_gemm_ind_opt.h000066400000000000000000000053071422157504600210570ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ BLIS_INLINE void bli_gemm_ind_recast_1m_params ( num_t* dt_exec, num_t* dt_c, pack_t schema_a, obj_t* c, dim_t* m, dim_t* n, dim_t* k, inc_t* pd_a, inc_t* ps_a, inc_t* pd_b, inc_t* ps_b, inc_t* rs_c, inc_t* cs_c ) { obj_t beta; /* Detach the beta scalar from c so that we can test its imaginary component. */ bli_obj_scalar_detach( c, &beta ); /* If beta is in the real domain, and c is row- or column-stored, then we may proceed with the optimization. */ if ( bli_obj_imag_is_zero( &beta ) && !bli_is_gen_stored( *rs_c, *cs_c ) ) { *dt_exec = bli_dt_proj_to_real( *dt_exec ); *dt_c = bli_dt_proj_to_real( *dt_c ); if ( bli_is_1e_packed( schema_a ) ) { *m *= 2; *n *= 1; *k *= 2; *pd_a *= 2; *ps_a *= 2; *pd_b *= 1; *ps_b *= 2; *rs_c *= 1; *cs_c *= 2; } else /* if ( bli_is_1r_packed( schema_a ) ) */ { *m *= 1; *n *= 2; *k *= 2; *pd_a *= 1; *ps_a *= 2; *pd_b *= 2; *ps_b *= 2; *rs_c *= 2; *cs_c *= 1; } } } blis-0.9.0/frame/3/gemm/other/000077500000000000000000000000001422157504600157615ustar00rootroot00000000000000blis-0.9.0/frame/3/gemm/other/bli_gemm_ker_var2.c000066400000000000000000000251011422157504600214720ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define FUNCPTR_T gemm_fp typedef void (*FUNCPTR_T) ( pack_t schema_a, pack_t schema_b, dim_t m, dim_t n, dim_t k, void* alpha, void* a, inc_t cs_a, inc_t is_a, dim_t pd_a, inc_t ps_a, void* b, inc_t rs_b, inc_t is_b, dim_t pd_b, inc_t ps_b, void* beta, void* c, inc_t rs_c, inc_t cs_c, cntx_t* cntx, rntm_t* rntm, thrinfo_t* thread ); static FUNCPTR_T GENARRAY(ftypes,gemm_ker_var2); void bli_gemm_ker_var2 ( obj_t* a, obj_t* b, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ) { num_t dt_exec = bli_obj_exec_dt( c ); pack_t schema_a = bli_obj_pack_schema( a ); pack_t schema_b = bli_obj_pack_schema( b ); dim_t m = bli_obj_length( c ); dim_t n = bli_obj_width( c ); dim_t k = bli_obj_width( a ); void* buf_a = bli_obj_buffer_at_off( a ); inc_t cs_a = bli_obj_col_stride( a ); inc_t is_a = bli_obj_imag_stride( a ); dim_t pd_a = bli_obj_panel_dim( a ); inc_t ps_a = bli_obj_panel_stride( a ); void* buf_b = bli_obj_buffer_at_off( b ); inc_t rs_b = bli_obj_row_stride( b ); inc_t is_b = bli_obj_imag_stride( b ); dim_t pd_b = bli_obj_panel_dim( b ); inc_t ps_b = bli_obj_panel_stride( b ); void* buf_c = bli_obj_buffer_at_off( c ); inc_t rs_c = bli_obj_row_stride( c ); inc_t cs_c = bli_obj_col_stride( c ); obj_t scalar_a; obj_t scalar_b; void* buf_alpha; void* buf_beta; FUNCPTR_T f; // Detach and multiply the scalars attached to A and B. bli_obj_scalar_detach( a, &scalar_a ); bli_obj_scalar_detach( b, &scalar_b ); bli_mulsc( &scalar_a, &scalar_b ); // Grab the addresses of the internal scalar buffers for the scalar // merged above and the scalar attached to C. buf_alpha = bli_obj_internal_scalar_buffer( &scalar_b ); buf_beta = bli_obj_internal_scalar_buffer( c ); // If 1m is being employed on a column- or row-stored matrix with a // real-valued beta, we can use the real domain macro-kernel, which // eliminates a little overhead associated with the 1m virtual // micro-kernel. #if 1 if ( bli_is_1m_packed( schema_a ) ) { bli_l3_ind_recast_1m_params ( dt_exec, schema_a, c, m, n, k, pd_a, ps_a, pd_b, ps_b, rs_c, cs_c ); } #endif // Index into the type combination array to extract the correct // function pointer. f = ftypes[dt_exec]; // Invoke the function. f( schema_a, schema_b, m, n, k, buf_alpha, buf_a, cs_a, is_a, pd_a, ps_a, buf_b, rs_b, is_b, pd_b, ps_b, buf_beta, buf_c, rs_c, cs_c, cntx, rntm, thread ); } #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ pack_t schema_a, \ pack_t schema_b, \ dim_t m, \ dim_t n, \ dim_t k, \ void* alpha, \ void* a, inc_t cs_a, inc_t is_a, \ dim_t pd_a, inc_t ps_a, \ void* b, inc_t rs_b, inc_t is_b, \ dim_t pd_b, inc_t ps_b, \ void* beta, \ void* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx, \ rntm_t* rntm, \ thrinfo_t* thread \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ /* Alias some constants to simpler names. */ \ const dim_t MR = pd_a; \ const dim_t NR = pd_b; \ /*const dim_t PACKMR = cs_a;*/ \ /*const dim_t PACKNR = rs_b;*/ \ \ /* Query the context for the micro-kernel address and cast it to its function pointer type. */ \ PASTECH(ch,gemm_ukr_ft) \ gemm_ukr = bli_cntx_get_l3_vir_ukr_dt( dt, BLIS_GEMM_UKR, cntx ); \ \ /* Temporary C buffer for edge cases. Note that the strides of this temporary buffer are set so that they match the storage of the original C matrix. For example, if C is column-stored, ct will be column-stored as well. */ \ ctype ct[ BLIS_STACK_BUF_MAX_SIZE \ / sizeof( ctype ) ] \ __attribute__((aligned(BLIS_STACK_BUF_ALIGN_SIZE))); \ const bool col_pref = bli_cntx_l3_vir_ukr_prefers_cols_dt( dt, BLIS_GEMM_UKR, cntx ); \ const inc_t rs_ct = ( col_pref ? 1 : NR ); \ const inc_t cs_ct = ( col_pref ? MR : 1 ); \ \ ctype* restrict zero = PASTEMAC(ch,0); \ ctype* restrict a_cast = a; \ ctype* restrict b_cast = b; \ ctype* restrict c_cast = c; \ ctype* restrict alpha_cast = alpha; \ ctype* restrict beta_cast = beta; \ ctype* restrict b1; \ ctype* restrict c1; \ \ dim_t m_iter, m_left; \ dim_t n_iter, n_left; \ dim_t i, j; \ dim_t m_cur; \ dim_t n_cur; \ inc_t rstep_a; \ inc_t cstep_b; \ inc_t rstep_c, cstep_c; \ auxinfo_t aux; \ \ /* Assumptions/assertions: rs_a == 1 cs_a == PACKMR pd_a == MR ps_a == stride to next micro-panel of A rs_b == PACKNR cs_b == 1 pd_b == NR ps_b == stride to next micro-panel of B rs_c == (no assumptions) cs_c == (no assumptions) */ \ \ /* If any dimension is zero, return immediately. */ \ if ( bli_zero_dim3( m, n, k ) ) return; \ \ /* Clear the temporary C buffer in case it has any infs or NaNs. */ \ PASTEMAC(ch,set0s_mxn)( MR, NR, \ ct, rs_ct, cs_ct ); \ \ /* Compute number of primary and leftover components of the m and n dimensions. */ \ n_iter = n / NR; \ n_left = n % NR; \ \ m_iter = m / MR; \ m_left = m % MR; \ \ if ( n_left ) ++n_iter; \ if ( m_left ) ++m_iter; \ \ /* Determine some increments used to step through A, B, and C. */ \ rstep_a = ps_a; \ \ cstep_b = ps_b; \ \ rstep_c = rs_c * MR; \ cstep_c = cs_c * NR; \ \ /* Save the pack schemas of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_schema_a( schema_a, &aux ); \ bli_auxinfo_set_schema_b( schema_b, &aux ); \ \ /* Save the imaginary stride of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_is_a( is_a, &aux ); \ bli_auxinfo_set_is_b( is_b, &aux ); \ \ thrinfo_t* caucus = bli_thrinfo_sub_node( thread ); \ dim_t jr_num_threads = bli_thread_n_way( thread ); \ dim_t jr_thread_id = bli_thread_work_id( thread ); \ dim_t ir_num_threads = bli_thread_n_way( caucus ); \ dim_t ir_thread_id = bli_thread_work_id( caucus ); \ \ /* Loop over the n dimension (NR columns at a time). */ \ for ( j = jr_thread_id; j < n_iter; j += jr_num_threads ) \ { \ ctype* restrict a1; \ ctype* restrict c11; \ ctype* restrict b2; \ \ b1 = b_cast + j * cstep_b; \ c1 = c_cast + j * cstep_c; \ \ n_cur = ( bli_is_not_edge_f( j, n_iter, n_left ) ? NR : n_left ); \ \ /* Initialize our next panel of B to be the current panel of B. */ \ b2 = b1; \ \ /* Loop over the m dimension (MR rows at a time). */ \ for ( i = ir_thread_id; i < m_iter; i += ir_num_threads ) \ { \ ctype* restrict a2; \ \ a1 = a_cast + i * rstep_a; \ c11 = c1 + i * rstep_c; \ \ m_cur = ( bli_is_not_edge_f( i, m_iter, m_left ) ? MR : m_left ); \ \ /* Compute the addresses of the next panels of A and B. */ \ a2 = bli_gemm_get_next_a_upanel( caucus, a1, rstep_a ); \ if ( bli_is_last_iter( i, m_iter, ir_thread_id, ir_num_threads ) ) \ { \ a2 = a_cast; \ b2 = bli_gemm_get_next_b_upanel( thread, b1, cstep_b ); \ if ( bli_is_last_iter( j, n_iter, jr_thread_id, jr_num_threads ) ) \ b2 = b_cast; \ } \ \ /* Save addresses of next panels of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_next_a( a2, &aux ); \ bli_auxinfo_set_next_b( b2, &aux ); \ \ /* Handle interior and edge cases separately. */ \ if ( m_cur == MR && n_cur == NR ) \ { \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k, \ alpha_cast, \ a1, \ b1, \ beta_cast, \ c11, rs_c, cs_c, \ &aux, \ cntx \ ); \ } \ else \ { \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k, \ alpha_cast, \ a1, \ b1, \ zero, \ ct, rs_ct, cs_ct, \ &aux, \ cntx \ ); \ \ /* Scale the bottom edge of C and add the result from above. */ \ PASTEMAC(ch,xpbys_mxn)( m_cur, n_cur, \ ct, rs_ct, cs_ct, \ beta_cast, \ c11, rs_c, cs_c ); \ } \ } \ } \ \ /* PASTEMAC(ch,fprintm)( stdout, "gemm_ker_var2: b1", k, NR, b1, NR, 1, "%4.1f", "" ); \ PASTEMAC(ch,fprintm)( stdout, "gemm_ker_var2: a1", MR, k, a1, 1, MR, "%4.1f", "" ); \ PASTEMAC(ch,fprintm)( stdout, "gemm_ker_var2: c after", m_cur, n_cur, c11, rs_c, cs_c, "%4.1f", "" ); \ */ \ } INSERT_GENTFUNC_BASIC0( gemm_ker_var2 ) blis-0.9.0/frame/3/gemm/other/bli_gemm_ker_var2rr.c000066400000000000000000000262261422157504600220470ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define FUNCPTR_T gemm_fp typedef void (*FUNCPTR_T) ( pack_t schema_a, pack_t schema_b, dim_t m, dim_t n, dim_t k, void* alpha, void* a, inc_t cs_a, inc_t is_a, dim_t pd_a, inc_t ps_a, void* b, inc_t rs_b, inc_t is_b, dim_t pd_b, inc_t ps_b, void* beta, void* c, inc_t rs_c, inc_t cs_c, cntx_t* cntx, rntm_t* rntm, thrinfo_t* thread ); static FUNCPTR_T GENARRAY(ftypes,gemm_ker_var2rr); // // -- Macrokernel functions for round-robin partitioning ----------------------- // void bli_gemm_ker_var2rr ( obj_t* a, obj_t* b, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ) { num_t dt_exec = bli_obj_exec_dt( c ); pack_t schema_a = bli_obj_pack_schema( a ); pack_t schema_b = bli_obj_pack_schema( b ); dim_t m = bli_obj_length( c ); dim_t n = bli_obj_width( c ); dim_t k = bli_obj_width( a ); void* buf_a = bli_obj_buffer_at_off( a ); inc_t cs_a = bli_obj_col_stride( a ); inc_t is_a = bli_obj_imag_stride( a ); dim_t pd_a = bli_obj_panel_dim( a ); inc_t ps_a = bli_obj_panel_stride( a ); void* buf_b = bli_obj_buffer_at_off( b ); inc_t rs_b = bli_obj_row_stride( b ); inc_t is_b = bli_obj_imag_stride( b ); dim_t pd_b = bli_obj_panel_dim( b ); inc_t ps_b = bli_obj_panel_stride( b ); void* buf_c = bli_obj_buffer_at_off( c ); inc_t rs_c = bli_obj_row_stride( c ); inc_t cs_c = bli_obj_col_stride( c ); obj_t scalar_a; obj_t scalar_b; void* buf_alpha; void* buf_beta; FUNCPTR_T f; // Detach and multiply the scalars attached to A and B. bli_obj_scalar_detach( a, &scalar_a ); bli_obj_scalar_detach( b, &scalar_b ); bli_mulsc( &scalar_a, &scalar_b ); // Grab the addresses of the internal scalar buffers for the scalar // merged above and the scalar attached to C. buf_alpha = bli_obj_internal_scalar_buffer( &scalar_b ); buf_beta = bli_obj_internal_scalar_buffer( c ); // If 1m is being employed on a column- or row-stored matrix with a // real-valued beta, we can use the real domain macro-kernel, which // eliminates a little overhead associated with the 1m virtual // micro-kernel. if ( bli_is_1m_packed( schema_a ) ) { bli_l3_ind_recast_1m_params ( dt_exec, schema_a, c, m, n, k, pd_a, ps_a, pd_b, ps_b, rs_c, cs_c ); } // Index into the type combination array to extract the correct // function pointer. f = ftypes[dt_exec]; // Invoke the function. f( schema_a, schema_b, m, n, k, buf_alpha, buf_a, cs_a, is_a, pd_a, ps_a, buf_b, rs_b, is_b, pd_b, ps_b, buf_beta, buf_c, rs_c, cs_c, cntx, rntm, thread ); } #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ pack_t schema_a, \ pack_t schema_b, \ dim_t m, \ dim_t n, \ dim_t k, \ void* alpha, \ void* a, inc_t cs_a, inc_t is_a, \ dim_t pd_a, inc_t ps_a, \ void* b, inc_t rs_b, inc_t is_b, \ dim_t pd_b, inc_t ps_b, \ void* beta, \ void* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx, \ rntm_t* rntm, \ thrinfo_t* thread \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ /* Alias some constants to simpler names. */ \ const dim_t MR = pd_a; \ const dim_t NR = pd_b; \ /*const dim_t PACKMR = cs_a;*/ \ /*const dim_t PACKNR = rs_b;*/ \ \ /* Query the context for the micro-kernel address and cast it to its function pointer type. */ \ PASTECH(ch,gemm_ukr_ft) \ gemm_ukr = bli_cntx_get_l3_vir_ukr_dt( dt, BLIS_GEMM_UKR, cntx ); \ \ /* Temporary C buffer for edge cases. Note that the strides of this temporary buffer are set so that they match the storage of the original C matrix. For example, if C is column-stored, ct will be column-stored as well. */ \ ctype ct[ BLIS_STACK_BUF_MAX_SIZE \ / sizeof( ctype ) ] \ __attribute__((aligned(BLIS_STACK_BUF_ALIGN_SIZE))); \ const bool col_pref = bli_cntx_l3_vir_ukr_prefers_cols_dt( dt, BLIS_GEMM_UKR, cntx ); \ const inc_t rs_ct = ( col_pref ? 1 : NR ); \ const inc_t cs_ct = ( col_pref ? MR : 1 ); \ \ ctype* restrict zero = PASTEMAC(ch,0); \ ctype* restrict a_cast = a; \ ctype* restrict b_cast = b; \ ctype* restrict c_cast = c; \ ctype* restrict alpha_cast = alpha; \ ctype* restrict beta_cast = beta; \ ctype* restrict b1; \ ctype* restrict c1; \ \ dim_t m_iter, m_left; \ dim_t n_iter, n_left; \ dim_t i, j; \ dim_t m_cur; \ dim_t n_cur; \ inc_t rstep_a; \ inc_t cstep_b; \ inc_t rstep_c, cstep_c; \ auxinfo_t aux; \ \ /* Assumptions/assertions: rs_a == 1 cs_a == PACKMR pd_a == MR ps_a == stride to next micro-panel of A rs_b == PACKNR cs_b == 1 pd_b == NR ps_b == stride to next micro-panel of B rs_c == (no assumptions) cs_c == (no assumptions) */ \ \ /* If any dimension is zero, return immediately. */ \ if ( bli_zero_dim3( m, n, k ) ) return; \ \ /* Clear the temporary C buffer in case it has any infs or NaNs. */ \ PASTEMAC(ch,set0s_mxn)( MR, NR, \ ct, rs_ct, cs_ct ); \ \ /* Compute number of primary and leftover components of the m and n dimensions. */ \ n_iter = n / NR; \ n_left = n % NR; \ \ m_iter = m / MR; \ m_left = m % MR; \ \ if ( n_left ) ++n_iter; \ if ( m_left ) ++m_iter; \ \ /* Determine some increments used to step through A, B, and C. */ \ rstep_a = ps_a; \ \ cstep_b = ps_b; \ \ rstep_c = rs_c * MR; \ cstep_c = cs_c * NR; \ \ /* Save the pack schemas of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_schema_a( schema_a, &aux ); \ bli_auxinfo_set_schema_b( schema_b, &aux ); \ \ /* Save the imaginary stride of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_is_a( is_a, &aux ); \ bli_auxinfo_set_is_b( is_b, &aux ); \ \ /* The 'thread' argument points to the thrinfo_t node for the 2nd (jr) loop around the microkernel. Here we query the thrinfo_t node for the 1st (ir) loop around the microkernel. */ \ thrinfo_t* caucus = bli_thrinfo_sub_node( thread ); \ \ /* Query the number of threads and thread ids for each loop. */ \ dim_t jr_nt = bli_thread_n_way( thread ); \ dim_t jr_tid = bli_thread_work_id( thread ); \ dim_t ir_nt = bli_thread_n_way( caucus ); \ dim_t ir_tid = bli_thread_work_id( caucus ); \ \ dim_t jr_start, jr_end; \ dim_t ir_start, ir_end; \ dim_t jr_inc, ir_inc; \ \ /* Determine the thread range and increment for each thrinfo_t node. */ \ bli_thread_range_jrir_rr( thread, n_iter, 1, FALSE, &jr_start, &jr_end, &jr_inc ); \ bli_thread_range_jrir_rr( caucus, m_iter, 1, FALSE, &ir_start, &ir_end, &ir_inc ); \ \ /* Loop over the n dimension (NR columns at a time). */ \ for ( j = jr_start; j < jr_end; j += jr_inc ) \ { \ ctype* restrict a1; \ ctype* restrict c11; \ ctype* restrict b2; \ \ b1 = b_cast + j * cstep_b; \ c1 = c_cast + j * cstep_c; \ \ n_cur = ( bli_is_not_edge_f( j, n_iter, n_left ) ? NR : n_left ); \ \ /* Initialize our next panel of B to be the current panel of B. */ \ b2 = b1; \ \ /* Loop over the m dimension (MR rows at a time). */ \ for ( i = ir_start; i < ir_end; i += ir_inc ) \ { \ ctype* restrict a2; \ \ a1 = a_cast + i * rstep_a; \ c11 = c1 + i * rstep_c; \ \ m_cur = ( bli_is_not_edge_f( i, m_iter, m_left ) ? MR : m_left ); \ \ /* Compute the addresses of the next panels of A and B. */ \ a2 = bli_gemm_get_next_a_upanel( a1, rstep_a, ir_inc ); \ if ( bli_is_last_iter_rr( i, ir_end, ir_tid, ir_nt ) ) \ { \ a2 = a_cast; \ b2 = bli_gemm_get_next_b_upanel( b1, cstep_b, jr_inc ); \ if ( bli_is_last_iter_rr( j, jr_end, jr_tid, jr_nt ) ) \ b2 = b_cast; \ } \ \ /* Save addresses of next panels of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_next_a( a2, &aux ); \ bli_auxinfo_set_next_b( b2, &aux ); \ \ /* Handle interior and edge cases separately. */ \ if ( m_cur == MR && n_cur == NR ) \ { \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k, \ alpha_cast, \ a1, \ b1, \ beta_cast, \ c11, rs_c, cs_c, \ &aux, \ cntx \ ); \ } \ else \ { \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k, \ alpha_cast, \ a1, \ b1, \ zero, \ ct, rs_ct, cs_ct, \ &aux, \ cntx \ ); \ \ /* Scale the bottom edge of C and add the result from above. */ \ PASTEMAC(ch,xpbys_mxn)( m_cur, n_cur, \ ct, rs_ct, cs_ct, \ beta_cast, \ c11, rs_c, cs_c ); \ } \ } \ } \ \ /* PASTEMAC(ch,fprintm)( stdout, "gemm_ker_var2rr: b1", k, NR, b1, NR, 1, "%4.1f", "" ); \ PASTEMAC(ch,fprintm)( stdout, "gemm_ker_var2rr: a1", MR, k, a1, 1, MR, "%4.1f", "" ); \ PASTEMAC(ch,fprintm)( stdout, "gemm_ker_var2rr: c after", m_cur, n_cur, c11, rs_c, cs_c, "%4.1f", "" ); \ */ \ } INSERT_GENTFUNC_BASIC0( gemm_ker_var2rr ) blis-0.9.0/frame/3/gemm/other/bli_gemm_ker_var2sl.c000066400000000000000000000262201422157504600220340ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define FUNCPTR_T gemm_fp typedef void (*FUNCPTR_T) ( pack_t schema_a, pack_t schema_b, dim_t m, dim_t n, dim_t k, void* alpha, void* a, inc_t cs_a, inc_t is_a, dim_t pd_a, inc_t ps_a, void* b, inc_t rs_b, inc_t is_b, dim_t pd_b, inc_t ps_b, void* beta, void* c, inc_t rs_c, inc_t cs_c, cntx_t* cntx, rntm_t* rntm, thrinfo_t* thread ); static FUNCPTR_T GENARRAY(ftypes,gemm_ker_var2sl); // // -- Macrokernel functions for slab partitioning ------------------------------ // void bli_gemm_ker_var2sl ( obj_t* a, obj_t* b, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ) { num_t dt_exec = bli_obj_exec_dt( c ); pack_t schema_a = bli_obj_pack_schema( a ); pack_t schema_b = bli_obj_pack_schema( b ); dim_t m = bli_obj_length( c ); dim_t n = bli_obj_width( c ); dim_t k = bli_obj_width( a ); void* buf_a = bli_obj_buffer_at_off( a ); inc_t cs_a = bli_obj_col_stride( a ); inc_t is_a = bli_obj_imag_stride( a ); dim_t pd_a = bli_obj_panel_dim( a ); inc_t ps_a = bli_obj_panel_stride( a ); void* buf_b = bli_obj_buffer_at_off( b ); inc_t rs_b = bli_obj_row_stride( b ); inc_t is_b = bli_obj_imag_stride( b ); dim_t pd_b = bli_obj_panel_dim( b ); inc_t ps_b = bli_obj_panel_stride( b ); void* buf_c = bli_obj_buffer_at_off( c ); inc_t rs_c = bli_obj_row_stride( c ); inc_t cs_c = bli_obj_col_stride( c ); obj_t scalar_a; obj_t scalar_b; void* buf_alpha; void* buf_beta; FUNCPTR_T f; // Detach and multiply the scalars attached to A and B. bli_obj_scalar_detach( a, &scalar_a ); bli_obj_scalar_detach( b, &scalar_b ); bli_mulsc( &scalar_a, &scalar_b ); // Grab the addresses of the internal scalar buffers for the scalar // merged above and the scalar attached to C. buf_alpha = bli_obj_internal_scalar_buffer( &scalar_b ); buf_beta = bli_obj_internal_scalar_buffer( c ); // If 1m is being employed on a column- or row-stored matrix with a // real-valued beta, we can use the real domain macro-kernel, which // eliminates a little overhead associated with the 1m virtual // micro-kernel. if ( bli_is_1m_packed( schema_a ) ) { bli_l3_ind_recast_1m_params ( dt_exec, schema_a, c, m, n, k, pd_a, ps_a, pd_b, ps_b, rs_c, cs_c ); } // Index into the type combination array to extract the correct // function pointer. f = ftypes[dt_exec]; // Invoke the function. f( schema_a, schema_b, m, n, k, buf_alpha, buf_a, cs_a, is_a, pd_a, ps_a, buf_b, rs_b, is_b, pd_b, ps_b, buf_beta, buf_c, rs_c, cs_c, cntx, rntm, thread ); } #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ pack_t schema_a, \ pack_t schema_b, \ dim_t m, \ dim_t n, \ dim_t k, \ void* alpha, \ void* a, inc_t cs_a, inc_t is_a, \ dim_t pd_a, inc_t ps_a, \ void* b, inc_t rs_b, inc_t is_b, \ dim_t pd_b, inc_t ps_b, \ void* beta, \ void* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx, \ rntm_t* rntm, \ thrinfo_t* thread \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ /* Alias some constants to simpler names. */ \ const dim_t MR = pd_a; \ const dim_t NR = pd_b; \ /*const dim_t PACKMR = cs_a;*/ \ /*const dim_t PACKNR = rs_b;*/ \ \ /* Query the context for the micro-kernel address and cast it to its function pointer type. */ \ PASTECH(ch,gemm_ukr_ft) \ gemm_ukr = bli_cntx_get_l3_vir_ukr_dt( dt, BLIS_GEMM_UKR, cntx ); \ \ /* Temporary C buffer for edge cases. Note that the strides of this temporary buffer are set so that they match the storage of the original C matrix. For example, if C is column-stored, ct will be column-stored as well. */ \ ctype ct[ BLIS_STACK_BUF_MAX_SIZE \ / sizeof( ctype ) ] \ __attribute__((aligned(BLIS_STACK_BUF_ALIGN_SIZE))); \ const bool col_pref = bli_cntx_l3_vir_ukr_prefers_cols_dt( dt, BLIS_GEMM_UKR, cntx ); \ const inc_t rs_ct = ( col_pref ? 1 : NR ); \ const inc_t cs_ct = ( col_pref ? MR : 1 ); \ \ ctype* restrict zero = PASTEMAC(ch,0); \ ctype* restrict a_cast = a; \ ctype* restrict b_cast = b; \ ctype* restrict c_cast = c; \ ctype* restrict alpha_cast = alpha; \ ctype* restrict beta_cast = beta; \ ctype* restrict b1; \ ctype* restrict c1; \ \ dim_t m_iter, m_left; \ dim_t n_iter, n_left; \ dim_t i, j; \ dim_t m_cur; \ dim_t n_cur; \ inc_t rstep_a; \ inc_t cstep_b; \ inc_t rstep_c, cstep_c; \ auxinfo_t aux; \ \ /* Assumptions/assertions: rs_a == 1 cs_a == PACKMR pd_a == MR ps_a == stride to next micro-panel of A rs_b == PACKNR cs_b == 1 pd_b == NR ps_b == stride to next micro-panel of B rs_c == (no assumptions) cs_c == (no assumptions) */ \ \ /* If any dimension is zero, return immediately. */ \ if ( bli_zero_dim3( m, n, k ) ) return; \ \ /* Clear the temporary C buffer in case it has any infs or NaNs. */ \ PASTEMAC(ch,set0s_mxn)( MR, NR, \ ct, rs_ct, cs_ct ); \ \ /* Compute number of primary and leftover components of the m and n dimensions. */ \ n_iter = n / NR; \ n_left = n % NR; \ \ m_iter = m / MR; \ m_left = m % MR; \ \ if ( n_left ) ++n_iter; \ if ( m_left ) ++m_iter; \ \ /* Determine some increments used to step through A, B, and C. */ \ rstep_a = ps_a; \ \ cstep_b = ps_b; \ \ rstep_c = rs_c * MR; \ cstep_c = cs_c * NR; \ \ /* Save the pack schemas of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_schema_a( schema_a, &aux ); \ bli_auxinfo_set_schema_b( schema_b, &aux ); \ \ /* Save the imaginary stride of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_is_a( is_a, &aux ); \ bli_auxinfo_set_is_b( is_b, &aux ); \ \ /* The 'thread' argument points to the thrinfo_t node for the 2nd (jr) loop around the microkernel. Here we query the thrinfo_t node for the 1st (ir) loop around the microkernel. */ \ thrinfo_t* caucus = bli_thrinfo_sub_node( thread ); \ \ /* Query the number of threads and thread ids for each loop. */ \ dim_t jr_nt = bli_thread_n_way( thread ); \ dim_t jr_tid = bli_thread_work_id( thread ); \ dim_t ir_nt = bli_thread_n_way( caucus ); \ dim_t ir_tid = bli_thread_work_id( caucus ); \ \ dim_t jr_start, jr_end; \ dim_t ir_start, ir_end; \ dim_t jr_inc, ir_inc; \ \ /* Determine the thread range and increment for each thrinfo_t node. */ \ bli_thread_range_jrir_sl( thread, n_iter, 1, FALSE, &jr_start, &jr_end, &jr_inc ); \ bli_thread_range_jrir_sl( caucus, m_iter, 1, FALSE, &ir_start, &ir_end, &ir_inc ); \ \ /* Loop over the n dimension (NR columns at a time). */ \ for ( j = jr_start; j < jr_end; j += jr_inc ) \ { \ ctype* restrict a1; \ ctype* restrict c11; \ ctype* restrict b2; \ \ b1 = b_cast + j * cstep_b; \ c1 = c_cast + j * cstep_c; \ \ n_cur = ( bli_is_not_edge_f( j, n_iter, n_left ) ? NR : n_left ); \ \ /* Initialize our next panel of B to be the current panel of B. */ \ b2 = b1; \ \ /* Loop over the m dimension (MR rows at a time). */ \ for ( i = ir_start; i < ir_end; i += ir_inc ) \ { \ ctype* restrict a2; \ \ a1 = a_cast + i * rstep_a; \ c11 = c1 + i * rstep_c; \ \ m_cur = ( bli_is_not_edge_f( i, m_iter, m_left ) ? MR : m_left ); \ \ /* Compute the addresses of the next panels of A and B. */ \ a2 = bli_gemm_get_next_a_upanel( a1, rstep_a, ir_inc ); \ if ( bli_is_last_iter_sl( i, ir_end, ir_tid, ir_nt ) ) \ { \ a2 = a_cast; \ b2 = bli_gemm_get_next_b_upanel( b1, cstep_b, jr_inc ); \ if ( bli_is_last_iter_sl( j, jr_end, jr_tid, jr_nt ) ) \ b2 = b_cast; \ } \ \ /* Save addresses of next panels of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_next_a( a2, &aux ); \ bli_auxinfo_set_next_b( b2, &aux ); \ \ /* Handle interior and edge cases separately. */ \ if ( m_cur == MR && n_cur == NR ) \ { \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k, \ alpha_cast, \ a1, \ b1, \ beta_cast, \ c11, rs_c, cs_c, \ &aux, \ cntx \ ); \ } \ else \ { \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k, \ alpha_cast, \ a1, \ b1, \ zero, \ ct, rs_ct, cs_ct, \ &aux, \ cntx \ ); \ \ /* Scale the bottom edge of C and add the result from above. */ \ PASTEMAC(ch,xpbys_mxn)( m_cur, n_cur, \ ct, rs_ct, cs_ct, \ beta_cast, \ c11, rs_c, cs_c ); \ } \ } \ } \ \ /* PASTEMAC(ch,fprintm)( stdout, "gemm_ker_var2sl: b1", k, NR, b1, NR, 1, "%4.1f", "" ); \ PASTEMAC(ch,fprintm)( stdout, "gemm_ker_var2sl: a1", MR, k, a1, 1, MR, "%4.1f", "" ); \ PASTEMAC(ch,fprintm)( stdout, "gemm_ker_var2sl: c after", m_cur, n_cur, c11, rs_c, cs_c, "%4.1f", "" ); \ */ \ } INSERT_GENTFUNC_BASIC0( gemm_ker_var2sl ) blis-0.9.0/frame/3/gemm/other/bli_gemm_ker_var5.c000066400000000000000000000237361422157504600215110ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define FUNCPTR_T gemm_fp typedef void (*FUNCPTR_T)( dim_t m, dim_t n, dim_t k, void* alpha, void* a, inc_t cs_a, dim_t pd_a, inc_t ps_a, void* b, inc_t rs_b, dim_t pd_b, inc_t ps_b, void* beta, void* c, inc_t rs_c, inc_t cs_c, void_fp gemm_ukr ); static FUNCPTR_T GENARRAY(ftypes,gemm_ker_var5); void bli_gemm_ker_var5( obj_t* a, obj_t* b, obj_t* c, cntx_t* cntx, gemm_t* cntl, gemm_thrinfo_t* thread ) { num_t dt_exec = bli_obj_exec_dt( c ); dim_t m = bli_obj_length( c ); dim_t n = bli_obj_width( c ); dim_t k = bli_obj_width( a ); void* buf_a = bli_obj_buffer_at_off( a ); inc_t cs_a = bli_obj_col_stride( a ); dim_t pd_a = bli_obj_panel_dim( a ); inc_t ps_a = bli_obj_panel_stride( a ); void* buf_b = bli_obj_buffer_at_off( b ); inc_t rs_b = bli_obj_row_stride( b ); dim_t pd_b = bli_obj_panel_dim( b ); inc_t ps_b = bli_obj_panel_stride( b ); void* buf_c = bli_obj_buffer_at_off( c ); inc_t rs_c = bli_obj_row_stride( c ); inc_t cs_c = bli_obj_col_stride( c ); obj_t scalar_a; obj_t scalar_b; void* buf_alpha; void* buf_beta; FUNCPTR_T f; func_t* gemm_ukrs; void_fp gemm_ukr; // Detach and multiply the scalars attached to A and B. bli_obj_scalar_detach( a, &scalar_a ); bli_obj_scalar_detach( b, &scalar_b ); bli_mulsc( &scalar_a, &scalar_b ); // Grab the addresses of the internal scalar buffers for the scalar // merged above and the scalar attached to C. buf_alpha = bli_obj_internal_scalar_buffer( &scalar_b ); buf_beta = bli_obj_internal_scalar_buffer( c ); // Index into the type combination array to extract the correct // function pointer. f = ftypes[dt_exec]; // Extract from the context the func_t object containing // the gemm micro-kernel function addresses, and then query the // function address corresponding to the current datatype. gemm_ukrs = bli_cntx_get_l3_ukr( BLIS_GEMM_UKR, cntx ); gemm_ukr = bli_func_get_dt( dt_exec, gemm_ukrs ); // Invoke the function. f( m, n, k, buf_alpha, buf_a, cs_a, pd_a, ps_a, buf_b, rs_b, pd_b, ps_b, buf_beta, buf_c, rs_c, cs_c, gemm_ukr ); } #undef GENTFUNC #define GENTFUNC( ctype, ch, varname, ukrtype ) \ \ void PASTEMAC(ch,varname)( \ dim_t m, \ dim_t n, \ dim_t k, \ void* alpha, \ void* a, inc_t cs_a, dim_t pd_a, inc_t ps_a, \ void* b, inc_t rs_b, dim_t pd_b, inc_t ps_b, \ void* beta, \ void* c, inc_t rs_c, inc_t cs_c, \ void_fp gemm_ukr \ ) \ { \ /* Cast the micro-kernel address to its function pointer type. */ \ PASTECH(ch,ukrtype) gemm_ukr_cast = gemm_ukr; \ \ /* Temporary buffer for incremental packing of B. */ \ ctype bp[ PASTEMAC(ch,maxkc) * \ /* !!!! NOTE: This packnr actually needs to be something like maxpacknr if it is to be guaranteed to work in all situations !!!! The right place to define maxpackmr/nr would be in bli_kernel_post_macro_defs.h */ \ PASTEMAC(ch,packnr) ] \ __attribute__((aligned(BLIS_STACK_BUF_ALIGN_SIZE))); \ \ /* Temporary C buffer for edge cases. */ \ ctype ct[ PASTEMAC(ch,maxmr) * \ PASTEMAC(ch,maxnr) ] \ __attribute__((aligned(BLIS_STACK_BUF_ALIGN_SIZE))); \ const inc_t rs_ct = 1; \ const inc_t cs_ct = PASTEMAC(ch,maxmr); \ \ /* Alias some constants to simpler names. */ \ const dim_t MR = pd_a; \ const dim_t NR = pd_b; \ const dim_t PACKNR = rs_b; \ \ ctype* restrict one = PASTEMAC(ch,1); \ ctype* restrict zero = PASTEMAC(ch,0); \ ctype* restrict a_cast = a; \ ctype* restrict b_cast = b; \ ctype* restrict c_cast = c; \ ctype* restrict alpha_cast = alpha; \ ctype* restrict beta_cast = beta; \ ctype* restrict b1; \ ctype* restrict c1; \ ctype* restrict b2; \ \ dim_t m_iter, m_left; \ dim_t n_iter, n_left; \ dim_t i, j; \ dim_t m_cur; \ dim_t n_cur; \ inc_t rstep_a; \ inc_t cstep_b; \ inc_t rstep_c, cstep_c; \ auxinfo_t aux; \ \ /* Assumptions/assertions: rs_a == 1 cs_a == PACKMR pd_a == MR ps_a == stride to next micro-panel of A rs_b == PACKNR cs_b == 1 pd_b == NR ps_b == stride to next micro-panel of B rs_c == (no assumptions) cs_c == (no assumptions) */ \ \ /* If any dimension is zero, return immediately. */ \ if ( bli_zero_dim3( m, n, k ) ) return; \ \ /* Clear the temporary C buffer in case it has any infs or NaNs. */ \ PASTEMAC(ch,set0s_mxn)( MR, NR, \ ct, rs_ct, cs_ct ); \ \ /* Compute number of primary and leftover components of the m and n dimensions. */ \ n_iter = n / NR; \ n_left = n % NR; \ \ m_iter = m / MR; \ m_left = m % MR; \ \ if ( n_left ) ++n_iter; \ if ( m_left ) ++m_iter; \ \ /* Determine some increments used to step through A, B, and C. */ \ rstep_a = ps_a; \ \ cstep_b = ps_b; \ \ rstep_c = rs_c * MR; \ cstep_c = cs_c * NR; \ \ /* Save the panel strides of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_ps_a( ps_a, &aux ); \ bli_auxinfo_set_ps_b( ps_b, &aux ); \ \ b1 = b_cast; \ c1 = c_cast; \ \ /* Since we pack micro-panels of B incrementaly, one at a time, the address of the next micro-panel of B remains constant. */ \ b2 = bp; \ \ /* Save address of next panel of B to the auxinfo_t object. */ \ bli_auxinfo_set_next_b( b2, &aux ); \ \ /* Loop over the n dimension (NR columns at a time). */ \ for ( j = 0; j < n_iter; ++j ) \ { \ ctype* restrict a1; \ ctype* restrict c11; \ \ a1 = a_cast; \ c11 = c1; \ \ n_cur = ( bli_is_not_edge_f( j, n_iter, n_left ) ? NR : n_left ); \ \ /* Incrementally pack a single micro-panel of B. */ \ PASTEMAC(ch,packm_cxk)( BLIS_NO_CONJUGATE, \ n_cur, \ k, \ one, \ b1, 1, rs_b, \ bp, PACKNR ); \ \ /* Loop over the m dimension (MR rows at a time). */ \ for ( i = 0; i < m_iter; ++i ) \ { \ ctype* restrict a2; \ \ m_cur = ( bli_is_not_edge_f( i, m_iter, m_left ) ? MR : m_left ); \ \ /* Compute the addresses of the next panels of A and B. */ \ a2 = a1 + rstep_a; \ if ( bli_is_last_iter( i, m_iter ) ) \ { \ a2 = a_cast; \ } \ \ /* Save address of next panel of A to the auxinfo_t object. */ \ bli_auxinfo_set_next_a( a2, &aux ); \ \ /* Handle interior and edge cases separately. */ \ if ( m_cur == MR && n_cur == NR ) \ { \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr_cast( k, \ alpha_cast, \ a1, \ bp, \ beta_cast, \ c11, rs_c, cs_c, \ &aux ); \ } \ else \ { \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr_cast( k, \ alpha_cast, \ a1, \ bp, \ zero, \ ct, rs_ct, cs_ct, \ &aux ); \ \ /* Scale the bottom edge of C and add the result from above. */ \ PASTEMAC(ch,xpbys_mxn)( m_cur, n_cur, \ ct, rs_ct, cs_ct, \ beta_cast, \ c11, rs_c, cs_c ); \ } \ \ a1 += rstep_a; \ c11 += rstep_c; \ } \ \ b1 += cstep_b; \ c1 += cstep_c; \ } \ \ /*PASTEMAC(ch,fprintm)( stdout, "gemm_ker_var5: b1", k, NR, b1, NR, 1, "%4.1f", "" ); \ PASTEMAC(ch,fprintm)( stdout, "gemm_ker_var5: a1", MR, k, a1, 1, MR, "%4.1f", "" );*/ \ } INSERT_GENTFUNC_BASIC( gemm_ker_var5, gemm_ukr_t ) blis-0.9.0/frame/3/gemm/other/bli_gemm_ker_var5.h000066400000000000000000000050731422157504600215100ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype object-based interface. // void bli_gemm_ker_var5( obj_t* a, obj_t* b, obj_t* c, cntx_t* cntx, gemm_t* cntl, gemm_thrinfo_t* thread ); // // Prototype BLAS-like interfaces. // #undef GENTPROT #define GENTPROT( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname)( \ dim_t m, \ dim_t n, \ dim_t k, \ void* alpha, \ void* a, inc_t cs_a, dim_t pd_a, inc_t ps_a, \ void* b, inc_t rs_b, dim_t pd_b, inc_t ps_b, \ void* beta, \ void* c, inc_t rs_c, inc_t cs_c, \ void_fp gemm_ukr \ ); INSERT_GENTPROT_BASIC( gemm_ker_var5 ) blis-0.9.0/frame/3/gemmt/000077500000000000000000000000001422157504600150245ustar00rootroot00000000000000blis-0.9.0/frame/3/gemmt/bli_gemmt.h000066400000000000000000000032761422157504600171440ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "bli_gemmt_front.h" #include "bli_gemmt_var.h" blis-0.9.0/frame/3/gemmt/bli_gemmt_front.c000066400000000000000000000101151422157504600203350ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_gemmt_front ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl ) { bli_init_once(); obj_t a_local; obj_t b_local; obj_t c_local; // If C has a zero dimension, return early. if ( bli_obj_has_zero_dim( c ) ) { return; } // If alpha is zero, or if A or B has a zero dimension, scale C by beta // and return early. if ( bli_obj_equals( alpha, &BLIS_ZERO ) || bli_obj_has_zero_dim( a ) || bli_obj_has_zero_dim( b ) ) { bli_scalm( beta, c ); return; } // Alias A, B, and C in case we need to apply transformations. bli_obj_alias_to( a, &a_local ); bli_obj_alias_to( b, &b_local ); bli_obj_alias_to( c, &c_local ); // Set the obj_t buffer field to the location currently implied by the row // and column offsets and then zero the offsets. If any of the original // obj_t's were views into larger matrices, this step effectively makes // those obj_t's "forget" their lineage. bli_obj_reset_origin( &a_local ); bli_obj_reset_origin( &b_local ); bli_obj_reset_origin( &c_local ); // An optimization: If C is stored by rows and the micro-kernel prefers // contiguous columns, or if C is stored by columns and the micro-kernel // prefers contiguous rows, transpose the entire operation to allow the // micro-kernel to access elements of C in its preferred manner. if ( bli_cntx_l3_vir_ukr_dislikes_storage_of( &c_local, BLIS_GEMM_UKR, cntx ) ) { bli_obj_swap( &a_local, &b_local ); bli_obj_induce_trans( &a_local ); bli_obj_induce_trans( &b_local ); bli_obj_induce_trans( &c_local ); } // Set the pack schemas within the objects, as appropriate. bli_l3_set_schemas( &a_local, &b_local, &c_local, cntx ); // Parse and interpret the contents of the rntm_t object to properly // set the ways of parallelism for each loop, and then make any // additional modifications necessary for the current operation. bli_rntm_set_ways_for_op ( BLIS_GEMM, BLIS_LEFT, // ignored for gemm/hemm/symm/gemmt bli_obj_length( &c_local ), bli_obj_width( &c_local ), bli_obj_width( &a_local ), rntm ); // Invoke the internal back-end via the thread handler. bli_l3_thread_decorator ( bli_l3_int, BLIS_GEMMT, // operation family id alpha, &a_local, &b_local, beta, &c_local, cntx, rntm, cntl ); } blis-0.9.0/frame/3/gemmt/bli_gemmt_front.h000066400000000000000000000036001422157504600203430ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void bli_gemmt_front ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl ); blis-0.9.0/frame/3/gemmt/bli_gemmt_l_ker_var2.c000066400000000000000000000376101422157504600212440ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define FUNCPTR_T gemmt_fp typedef void (*FUNCPTR_T) ( doff_t diagoffc, pack_t schema_a, pack_t schema_b, dim_t m, dim_t n, dim_t k, void* alpha, void* a, inc_t cs_a, inc_t is_a, dim_t pd_a, inc_t ps_a, void* b, inc_t rs_b, inc_t is_b, dim_t pd_b, inc_t ps_b, void* beta, void* c, inc_t rs_c, inc_t cs_c, cntx_t* cntx, rntm_t* rntm, thrinfo_t* thread ); static FUNCPTR_T GENARRAY(ftypes,gemmt_l_ker_var2); void bli_gemmt_l_ker_var2 ( obj_t* a, obj_t* b, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ) { num_t dt_exec = bli_obj_exec_dt( c ); doff_t diagoffc = bli_obj_diag_offset( c ); pack_t schema_a = bli_obj_pack_schema( a ); pack_t schema_b = bli_obj_pack_schema( b ); dim_t m = bli_obj_length( c ); dim_t n = bli_obj_width( c ); dim_t k = bli_obj_width( a ); void* buf_a = bli_obj_buffer_at_off( a ); inc_t cs_a = bli_obj_col_stride( a ); inc_t is_a = bli_obj_imag_stride( a ); dim_t pd_a = bli_obj_panel_dim( a ); inc_t ps_a = bli_obj_panel_stride( a ); void* buf_b = bli_obj_buffer_at_off( b ); inc_t rs_b = bli_obj_row_stride( b ); inc_t is_b = bli_obj_imag_stride( b ); dim_t pd_b = bli_obj_panel_dim( b ); inc_t ps_b = bli_obj_panel_stride( b ); void* buf_c = bli_obj_buffer_at_off( c ); inc_t rs_c = bli_obj_row_stride( c ); inc_t cs_c = bli_obj_col_stride( c ); obj_t scalar_a; obj_t scalar_b; void* buf_alpha; void* buf_beta; FUNCPTR_T f; // Detach and multiply the scalars attached to A and B. bli_obj_scalar_detach( a, &scalar_a ); bli_obj_scalar_detach( b, &scalar_b ); bli_mulsc( &scalar_a, &scalar_b ); // Grab the addresses of the internal scalar buffers for the scalar // merged above and the scalar attached to C. buf_alpha = bli_obj_internal_scalar_buffer( &scalar_b ); buf_beta = bli_obj_internal_scalar_buffer( c ); // Index into the type combination array to extract the correct // function pointer. f = ftypes[dt_exec]; // Invoke the function. f( diagoffc, schema_a, schema_b, m, n, k, buf_alpha, buf_a, cs_a, is_a, pd_a, ps_a, buf_b, rs_b, is_b, pd_b, ps_b, buf_beta, buf_c, rs_c, cs_c, cntx, rntm, thread ); } #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ doff_t diagoffc, \ pack_t schema_a, \ pack_t schema_b, \ dim_t m, \ dim_t n, \ dim_t k, \ void* alpha, \ void* a, inc_t cs_a, inc_t is_a, \ dim_t pd_a, inc_t ps_a, \ void* b, inc_t rs_b, inc_t is_b, \ dim_t pd_b, inc_t ps_b, \ void* beta, \ void* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx, \ rntm_t* rntm, \ thrinfo_t* thread \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ /* Alias some constants to simpler names. */ \ const dim_t MR = pd_a; \ const dim_t NR = pd_b; \ /*const dim_t PACKMR = cs_a;*/ \ /*const dim_t PACKNR = rs_b;*/ \ \ /* Query the context for the micro-kernel address and cast it to its function pointer type. */ \ PASTECH(ch,gemm_ukr_ft) \ gemm_ukr = bli_cntx_get_l3_vir_ukr_dt( dt, BLIS_GEMM_UKR, cntx ); \ \ /* Temporary C buffer for edge cases. Note that the strides of this temporary buffer are set so that they match the storage of the original C matrix. For example, if C is column-stored, ct will be column-stored as well. */ \ ctype ct[ BLIS_STACK_BUF_MAX_SIZE \ / sizeof( ctype ) ] \ __attribute__((aligned(BLIS_STACK_BUF_ALIGN_SIZE))); \ const bool col_pref = bli_cntx_l3_vir_ukr_prefers_cols_dt( dt, BLIS_GEMM_UKR, cntx ); \ const inc_t rs_ct = ( col_pref ? 1 : NR ); \ const inc_t cs_ct = ( col_pref ? MR : 1 ); \ \ ctype* restrict zero = PASTEMAC(ch,0); \ ctype* restrict a_cast = a; \ ctype* restrict b_cast = b; \ ctype* restrict c_cast = c; \ ctype* restrict alpha_cast = alpha; \ ctype* restrict beta_cast = beta; \ ctype* restrict b1; \ ctype* restrict c1; \ \ doff_t diagoffc_ij; \ dim_t m_iter, m_left; \ dim_t n_iter, n_left; \ dim_t m_cur; \ dim_t n_cur; \ dim_t i, j, ip; \ inc_t rstep_a; \ inc_t cstep_b; \ inc_t rstep_c, cstep_c; \ auxinfo_t aux; \ \ /* Assumptions/assertions: rs_a == 1 cs_a == PACKMR pd_a == MR ps_a == stride to next micro-panel of A rs_b == PACKNR cs_b == 1 pd_b == NR ps_b == stride to next micro-panel of B rs_c == (no assumptions) cs_c == (no assumptions) */ \ \ /* If any dimension is zero, return immediately. */ \ if ( bli_zero_dim3( m, n, k ) ) return; \ \ /* Safeguard: If the current panel of C is entirely above the diagonal, it is not stored. So we do nothing. */ \ if ( bli_is_strictly_above_diag_n( diagoffc, m, n ) ) return; \ \ /* If there is a zero region above where the diagonal of C intersects the left edge of the panel, adjust the pointer to C and A and treat this case as if the diagonal offset were zero. */ \ if ( diagoffc < 0 ) \ { \ ip = -diagoffc / MR; \ i = ip * MR; \ m = m - i; \ diagoffc = -diagoffc % MR; \ c_cast = c_cast + (i )*rs_c; \ a_cast = a_cast + (ip )*ps_a; \ } \ \ /* If there is a zero region to the right of where the diagonal of C intersects the bottom of the panel, shrink it to prevent "no-op" iterations from executing. */ \ if ( diagoffc + m < n ) \ { \ n = diagoffc + m; \ } \ \ /* Clear the temporary C buffer in case it has any infs or NaNs. */ \ PASTEMAC(ch,set0s_mxn)( MR, NR, \ ct, rs_ct, cs_ct ); \ \ /* Compute number of primary and leftover components of the m and n dimensions. */ \ n_iter = n / NR; \ n_left = n % NR; \ \ m_iter = m / MR; \ m_left = m % MR; \ \ if ( n_left ) ++n_iter; \ if ( m_left ) ++m_iter; \ \ /* Determine some increments used to step through A, B, and C. */ \ rstep_a = ps_a; \ \ cstep_b = ps_b; \ \ rstep_c = rs_c * MR; \ cstep_c = cs_c * NR; \ \ /* Save the pack schemas of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_schema_a( schema_a, &aux ); \ bli_auxinfo_set_schema_b( schema_b, &aux ); \ \ /* Save the imaginary stride of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_is_a( is_a, &aux ); \ bli_auxinfo_set_is_b( is_b, &aux ); \ \ /* Save the desired output datatype (indicating no typecasting). */ \ /*bli_auxinfo_set_dt_on_output( dt, &aux );*/ \ \ /* The 'thread' argument points to the thrinfo_t node for the 2nd (jr) loop around the microkernel. Here we query the thrinfo_t node for the 1st (ir) loop around the microkernel. */ \ thrinfo_t* caucus = bli_thrinfo_sub_node( thread ); \ \ /* Query the number of threads and thread ids for each loop. */ \ dim_t jr_nt = bli_thread_n_way( thread ); \ dim_t jr_tid = bli_thread_work_id( thread ); \ dim_t ir_nt = bli_thread_n_way( caucus ); \ dim_t ir_tid = bli_thread_work_id( caucus ); \ \ dim_t jr_start, jr_end; \ dim_t ir_start, ir_end; \ dim_t jr_inc, ir_inc; \ \ /* Note that we partition the 2nd loop into two regions: the rectangular part of C, and the triangular portion. */ \ dim_t n_iter_rct; \ dim_t n_iter_tri; \ \ if ( bli_is_strictly_below_diag_n( diagoffc, m, n ) ) \ { \ /* If the entire panel of C does not intersect the diagonal, there is no triangular region, and therefore we can skip the second set of loops. */ \ n_iter_rct = n_iter; \ n_iter_tri = 0; \ } \ else \ { \ /* If the panel of C does intersect the diagonal, compute the number of iterations in the rectangular region by dividing NR into the diagonal offset. Any remainder from this integer division is discarded, which is what we want. That is, we want the rectangular region to contain as many columns of whole microtiles as possible without including any microtiles that intersect the diagonal. The number of iterations in the triangular (or trapezoidal) region is computed as the remaining number of iterations in the n dimension. */ \ n_iter_rct = diagoffc / NR; \ n_iter_tri = n_iter - n_iter_rct; \ } \ \ /* Determine the thread range and increment for the 2nd and 1st loops for the initial rectangular region of C (if it exists). NOTE: The definition of bli_thread_range_jrir() will depend on whether slab or round-robin partitioning was requested at configure-time. */ \ bli_thread_range_jrir( thread, n_iter_rct, 1, FALSE, &jr_start, &jr_end, &jr_inc ); \ bli_thread_range_jrir( caucus, m_iter, 1, FALSE, &ir_start, &ir_end, &ir_inc ); \ \ /* Loop over the n dimension (NR columns at a time). */ \ for ( j = jr_start; j < jr_end; j += jr_inc ) \ { \ ctype* restrict a1; \ ctype* restrict c11; \ ctype* restrict b2; \ \ b1 = b_cast + j * cstep_b; \ c1 = c_cast + j * cstep_c; \ \ n_cur = ( bli_is_not_edge_f( j, n_iter, n_left ) ? NR : n_left ); \ \ /* Initialize our next panel of B to be the current panel of B. */ \ b2 = b1; \ \ /* Interior loop over the m dimension (MR rows at a time). */ \ for ( i = ir_start; i < ir_end; i += ir_inc ) \ { \ ctype* restrict a2; \ \ a1 = a_cast + i * rstep_a; \ c11 = c1 + i * rstep_c; \ \ /* No need to compute the diagonal offset for the rectangular region. */ \ /*diagoffc_ij = diagoffc - (doff_t)j*NR + (doff_t)i*MR;*/ \ \ m_cur = ( bli_is_not_edge_f( i, m_iter, m_left ) ? MR : m_left ); \ \ /* Compute the addresses of the next panels of A and B. */ \ a2 = bli_gemmt_get_next_a_upanel( a1, rstep_a, ir_inc ); \ if ( bli_is_last_iter( i, m_iter, ir_tid, ir_nt ) ) \ { \ a2 = a_cast; \ b2 = bli_gemmt_get_next_b_upanel( b1, cstep_b, jr_inc ); \ if ( bli_is_last_iter( j, n_iter, jr_tid, jr_nt ) ) \ b2 = b_cast; \ } \ \ /* Save addresses of next panels of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_next_a( a2, &aux ); \ bli_auxinfo_set_next_b( b2, &aux ); \ \ /* If the diagonal intersects the current MR x NR submatrix, we compute it the temporary buffer and then add in the elements on or below the diagonal. Otherwise, if the submatrix is strictly below the diagonal, we compute and store as we normally would. And if we're strictly above the diagonal, we do nothing and continue. */ \ { \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ m_cur, \ n_cur, \ k, \ alpha_cast, \ a1, \ b1, \ beta_cast, \ c11, rs_c, cs_c, \ &aux, \ cntx \ ); \ } \ } \ } \ \ /* If there is no triangular region, then we're done. */ \ if ( n_iter_tri == 0 ) return; \ \ /* Use round-robin assignment of micropanels to threads in the 2nd loop and the default (slab or rr) partitioning in the 1st loop for the remaining triangular region of C. */ \ bli_thread_range_jrir_rr( thread, n_iter_tri, 1, FALSE, &jr_start, &jr_end, &jr_inc ); \ \ /* Advance the start and end iteration offsets for the triangular region by the number of iterations used for the rectangular region. */ \ jr_start += n_iter_rct; \ jr_end += n_iter_rct; \ \ /* Loop over the n dimension (NR columns at a time). */ \ for ( j = jr_start; j < jr_end; j += jr_inc ) \ { \ ctype* restrict a1; \ ctype* restrict c11; \ ctype* restrict b2; \ \ b1 = b_cast + j * cstep_b; \ c1 = c_cast + j * cstep_c; \ \ n_cur = ( bli_is_not_edge_f( j, n_iter, n_left ) ? NR : n_left ); \ \ /* Initialize our next panel of B to be the current panel of B. */ \ b2 = b1; \ \ /* Interior loop over the m dimension (MR rows at a time). */ \ for ( i = ir_start; i < ir_end; i += ir_inc ) \ { \ ctype* restrict a2; \ \ a1 = a_cast + i * rstep_a; \ c11 = c1 + i * rstep_c; \ \ /* Compute the diagonal offset for the submatrix at (i,j). */ \ diagoffc_ij = diagoffc - (doff_t)j*NR + (doff_t)i*MR; \ \ m_cur = ( bli_is_not_edge_f( i, m_iter, m_left ) ? MR : m_left ); \ \ /* Compute the addresses of the next panels of A and B. */ \ a2 = bli_gemmt_get_next_a_upanel( a1, rstep_a, ir_inc ); \ if ( bli_is_last_iter( i, m_iter, ir_tid, ir_nt ) ) \ { \ a2 = a_cast; \ b2 = bli_gemmt_get_next_b_upanel( b1, cstep_b, jr_inc ); \ if ( bli_is_last_iter_rr( j, n_iter, jr_tid, jr_nt ) ) \ b2 = b_cast; \ } \ \ /* Save addresses of next panels of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_next_a( a2, &aux ); \ bli_auxinfo_set_next_b( b2, &aux ); \ \ /* If the diagonal intersects the current MR x NR submatrix, we compute it the temporary buffer and then add in the elements on or below the diagonal. Otherwise, if the submatrix is strictly below the diagonal, we compute and store as we normally would. And if we're strictly above the diagonal, we do nothing and continue. */ \ if ( bli_intersects_diag_n( diagoffc_ij, m_cur, n_cur ) ) \ { \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ MR, \ NR, \ k, \ alpha_cast, \ a1, \ b1, \ zero, \ ct, rs_ct, cs_ct, \ &aux, \ cntx \ ); \ \ /* Scale C and add the result to only the stored part. */ \ PASTEMAC(ch,xpbys_mxn_l)( diagoffc_ij, \ m_cur, n_cur, \ ct, rs_ct, cs_ct, \ beta_cast, \ c11, rs_c, cs_c ); \ } \ else if ( bli_is_strictly_below_diag_n( diagoffc_ij, m_cur, n_cur ) ) \ { \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ m_cur, \ n_cur, \ k, \ alpha_cast, \ a1, \ b1, \ beta_cast, \ c11, rs_c, cs_c, \ &aux, \ cntx \ ); \ } \ } \ } \ } INSERT_GENTFUNC_BASIC0( gemmt_l_ker_var2 ) blis-0.9.0/frame/3/gemmt/bli_gemmt_u_ker_var2.c000066400000000000000000000401641422157504600212530ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define FUNCPTR_T gemmt_fp typedef void (*FUNCPTR_T) ( doff_t diagoffc, pack_t schema_a, pack_t schema_b, dim_t m, dim_t n, dim_t k, void* alpha, void* a, inc_t cs_a, inc_t is_a, dim_t pd_a, inc_t ps_a, void* b, inc_t rs_b, inc_t is_b, dim_t pd_b, inc_t ps_b, void* beta, void* c, inc_t rs_c, inc_t cs_c, cntx_t* cntx, rntm_t* rntm, thrinfo_t* thread ); static FUNCPTR_T GENARRAY(ftypes,gemmt_u_ker_var2); void bli_gemmt_u_ker_var2 ( obj_t* a, obj_t* b, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ) { num_t dt_exec = bli_obj_exec_dt( c ); doff_t diagoffc = bli_obj_diag_offset( c ); pack_t schema_a = bli_obj_pack_schema( a ); pack_t schema_b = bli_obj_pack_schema( b ); dim_t m = bli_obj_length( c ); dim_t n = bli_obj_width( c ); dim_t k = bli_obj_width( a ); void* buf_a = bli_obj_buffer_at_off( a ); inc_t cs_a = bli_obj_col_stride( a ); inc_t is_a = bli_obj_imag_stride( a ); dim_t pd_a = bli_obj_panel_dim( a ); inc_t ps_a = bli_obj_panel_stride( a ); void* buf_b = bli_obj_buffer_at_off( b ); inc_t rs_b = bli_obj_row_stride( b ); inc_t is_b = bli_obj_imag_stride( b ); dim_t pd_b = bli_obj_panel_dim( b ); inc_t ps_b = bli_obj_panel_stride( b ); void* buf_c = bli_obj_buffer_at_off( c ); inc_t rs_c = bli_obj_row_stride( c ); inc_t cs_c = bli_obj_col_stride( c ); obj_t scalar_a; obj_t scalar_b; void* buf_alpha; void* buf_beta; FUNCPTR_T f; // Detach and multiply the scalars attached to A and B. bli_obj_scalar_detach( a, &scalar_a ); bli_obj_scalar_detach( b, &scalar_b ); bli_mulsc( &scalar_a, &scalar_b ); // Grab the addresses of the internal scalar buffers for the scalar // merged above and the scalar attached to C. buf_alpha = bli_obj_internal_scalar_buffer( &scalar_b ); buf_beta = bli_obj_internal_scalar_buffer( c ); // Index into the type combination array to extract the correct // function pointer. f = ftypes[dt_exec]; // Invoke the function. f( diagoffc, schema_a, schema_b, m, n, k, buf_alpha, buf_a, cs_a, is_a, pd_a, ps_a, buf_b, rs_b, is_b, pd_b, ps_b, buf_beta, buf_c, rs_c, cs_c, cntx, rntm, thread ); } #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ doff_t diagoffc, \ pack_t schema_a, \ pack_t schema_b, \ dim_t m, \ dim_t n, \ dim_t k, \ void* alpha, \ void* a, inc_t cs_a, inc_t is_a, \ dim_t pd_a, inc_t ps_a, \ void* b, inc_t rs_b, inc_t is_b, \ dim_t pd_b, inc_t ps_b, \ void* beta, \ void* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx, \ rntm_t* rntm, \ thrinfo_t* thread \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ /* Alias some constants to simpler names. */ \ const dim_t MR = pd_a; \ const dim_t NR = pd_b; \ /*const dim_t PACKMR = cs_a;*/ \ /*const dim_t PACKNR = rs_b;*/ \ \ /* Query the context for the micro-kernel address and cast it to its function pointer type. */ \ PASTECH(ch,gemm_ukr_ft) \ gemm_ukr = bli_cntx_get_l3_vir_ukr_dt( dt, BLIS_GEMM_UKR, cntx ); \ \ /* Temporary C buffer for edge cases. Note that the strides of this temporary buffer are set so that they match the storage of the original C matrix. For example, if C is column-stored, ct will be column-stored as well. */ \ ctype ct[ BLIS_STACK_BUF_MAX_SIZE \ / sizeof( ctype ) ] \ __attribute__((aligned(BLIS_STACK_BUF_ALIGN_SIZE))); \ const bool col_pref = bli_cntx_l3_vir_ukr_prefers_cols_dt( dt, BLIS_GEMM_UKR, cntx ); \ const inc_t rs_ct = ( col_pref ? 1 : NR ); \ const inc_t cs_ct = ( col_pref ? MR : 1 ); \ \ ctype* restrict zero = PASTEMAC(ch,0); \ ctype* restrict a_cast = a; \ ctype* restrict b_cast = b; \ ctype* restrict c_cast = c; \ ctype* restrict alpha_cast = alpha; \ ctype* restrict beta_cast = beta; \ ctype* restrict b1; \ ctype* restrict c1; \ \ doff_t diagoffc_ij; \ dim_t m_iter, m_left; \ dim_t n_iter, n_left; \ dim_t m_cur; \ dim_t n_cur; \ dim_t i, j, jp; \ inc_t rstep_a; \ inc_t cstep_b; \ inc_t rstep_c, cstep_c; \ auxinfo_t aux; \ \ /* Assumptions/assertions: rs_a == 1 cs_a == PACKMR pd_a == MR ps_a == stride to next micro-panel of A rs_b == PACKNR cs_b == 1 pd_b == NR ps_b == stride to next micro-panel of B rs_c == (no assumptions) cs_c == (no assumptions) */ \ \ /* If any dimension is zero, return immediately. */ \ if ( bli_zero_dim3( m, n, k ) ) return; \ \ /* Safeguard: If the current panel of C is entirely below the diagonal, it is not stored. So we do nothing. */ \ if ( bli_is_strictly_below_diag_n( diagoffc, m, n ) ) return; \ \ /* If there is a zero region to the left of where the diagonal of C intersects the top edge of the panel, adjust the pointer to C and B and treat this case as if the diagonal offset were zero. NOTE: It's possible that after this pruning that the diagonal offset is still positive (though it is guaranteed to be less than NR). */ \ if ( diagoffc > 0 ) \ { \ jp = diagoffc / NR; \ j = jp * NR; \ n = n - j; \ diagoffc = diagoffc % NR; \ c_cast = c_cast + (j )*cs_c; \ b_cast = b_cast + (jp )*ps_b; \ } \ \ /* If there is a zero region below where the diagonal of C intersects the right edge of the panel, shrink it to prevent "no-op" iterations from executing. */ \ if ( -diagoffc + n < m ) \ { \ m = -diagoffc + n; \ } \ \ /* Clear the temporary C buffer in case it has any infs or NaNs. */ \ PASTEMAC(ch,set0s_mxn)( MR, NR, \ ct, rs_ct, cs_ct ); \ \ /* Compute number of primary and leftover components of the m and n dimensions. */ \ n_iter = n / NR; \ n_left = n % NR; \ \ m_iter = m / MR; \ m_left = m % MR; \ \ if ( n_left ) ++n_iter; \ if ( m_left ) ++m_iter; \ \ /* Determine some increments used to step through A, B, and C. */ \ rstep_a = ps_a; \ \ cstep_b = ps_b; \ \ rstep_c = rs_c * MR; \ cstep_c = cs_c * NR; \ \ /* Save the pack schemas of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_schema_a( schema_a, &aux ); \ bli_auxinfo_set_schema_b( schema_b, &aux ); \ \ /* Save the imaginary stride of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_is_a( is_a, &aux ); \ bli_auxinfo_set_is_b( is_b, &aux ); \ \ /* Save the desired output datatype (indicating no typecasting). */ \ /*bli_auxinfo_set_dt_on_output( dt, &aux );*/ \ \ /* The 'thread' argument points to the thrinfo_t node for the 2nd (jr) loop around the microkernel. Here we query the thrinfo_t node for the 1st (ir) loop around the microkernel. */ \ thrinfo_t* caucus = bli_thrinfo_sub_node( thread ); \ \ /* Query the number of threads and thread ids for each loop. */ \ dim_t jr_nt = bli_thread_n_way( thread ); \ dim_t jr_tid = bli_thread_work_id( thread ); \ dim_t ir_nt = bli_thread_n_way( caucus ); \ dim_t ir_tid = bli_thread_work_id( caucus ); \ \ dim_t jr_start, jr_end; \ dim_t ir_start, ir_end; \ dim_t jr_inc, ir_inc; \ \ /* Note that we partition the 2nd loop into two regions: the triangular part of C, and the rectangular portion. */ \ dim_t n_iter_tri; \ dim_t n_iter_rct; \ \ if ( bli_is_strictly_above_diag_n( diagoffc, m, n ) ) \ { \ /* If the entire panel of C does not intersect the diagonal, there is no triangular region, and therefore we can skip the first set of loops. */ \ n_iter_tri = 0; \ n_iter_rct = n_iter; \ } \ else \ { \ /* If the panel of C does intersect the diagonal, compute the number of iterations in the triangular (or trapezoidal) region by dividing NR into the number of rows in C. A non-zero remainder means we need to add one additional iteration. That is, we want the triangular region to contain as few columns of whole microtiles as possible while still including all microtiles that intersect the diagonal. The number of iterations in the rectangular region is computed as the remaining number of iterations in the n dimension. */ \ n_iter_tri = ( m + diagoffc ) / NR + ( ( m + diagoffc ) % NR ? 1 : 0 ); \ n_iter_rct = n_iter - n_iter_tri; \ } \ \ /* Use round-robin assignment of micropanels to threads in the 2nd loop and the default (slab or rr) partitioning in the 1st loop for the initial triangular region of C (if it exists). */ \ bli_thread_range_jrir_rr( thread, n_iter_tri, 1, FALSE, &jr_start, &jr_end, &jr_inc ); \ bli_thread_range_jrir ( caucus, m_iter, 1, FALSE, &ir_start, &ir_end, &ir_inc ); \ \ /* Loop over the n dimension (NR columns at a time). */ \ for ( j = jr_start; j < jr_end; j += jr_inc ) \ { \ ctype* restrict a1; \ ctype* restrict c11; \ ctype* restrict b2; \ \ b1 = b_cast + j * cstep_b; \ c1 = c_cast + j * cstep_c; \ \ n_cur = ( bli_is_not_edge_f( j, n_iter, n_left ) ? NR : n_left ); \ \ /* Initialize our next panel of B to be the current panel of B. */ \ b2 = b1; \ \ /* Interior loop over the m dimension (MR rows at a time). */ \ for ( i = ir_start; i < ir_end; i += ir_inc ) \ { \ ctype* restrict a2; \ \ a1 = a_cast + i * rstep_a; \ c11 = c1 + i * rstep_c; \ \ /* Compute the diagonal offset for the submatrix at (i,j). */ \ diagoffc_ij = diagoffc - (doff_t)j*NR + (doff_t)i*MR; \ \ m_cur = ( bli_is_not_edge_f( i, m_iter, m_left ) ? MR : m_left ); \ \ /* Compute the addresses of the next panels of A and B. */ \ a2 = bli_gemmt_get_next_a_upanel( a1, rstep_a, ir_inc ); \ if ( bli_is_last_iter( i, m_iter, ir_tid, ir_nt ) ) \ { \ a2 = a_cast; \ b2 = bli_gemmt_get_next_b_upanel( b1, cstep_b, jr_inc ); \ if ( bli_is_last_iter_rr( j, n_iter, jr_tid, jr_nt ) ) \ b2 = b_cast; \ } \ \ /* Save addresses of next panels of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_next_a( a2, &aux ); \ bli_auxinfo_set_next_b( b2, &aux ); \ \ /* If the diagonal intersects the current MR x NR submatrix, we compute it the temporary buffer and then add in the elements on or below the diagonal. Otherwise, if the submatrix is strictly above the diagonal, we compute and store as we normally would. And if we're strictly below the diagonal, we do nothing and continue. */ \ if ( bli_intersects_diag_n( diagoffc_ij, m_cur, n_cur ) ) \ { \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ MR, \ NR, \ k, \ alpha_cast, \ a1, \ b1, \ zero, \ ct, rs_ct, cs_ct, \ &aux, \ cntx \ ); \ \ /* Scale C and add the result to only the stored part. */ \ PASTEMAC(ch,xpbys_mxn_u)( diagoffc_ij, \ m_cur, n_cur, \ ct, rs_ct, cs_ct, \ beta_cast, \ c11, rs_c, cs_c ); \ } \ else if ( bli_is_strictly_above_diag_n( diagoffc_ij, m_cur, n_cur ) ) \ { \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ m_cur, \ n_cur, \ k, \ alpha_cast, \ a1, \ b1, \ beta_cast, \ c11, rs_c, cs_c, \ &aux, \ cntx \ ); \ } \ } \ } \ \ /* If there is no rectangular region, then we're done. */ \ if ( n_iter_rct == 0 ) return; \ \ /* Determine the thread range and increment for the 2nd loop of the remaining rectangular region of C (and also use default partitioning for the 1st loop). NOTE: The definition of bli_thread_range_jrir() will depend on whether slab or round-robin partitioning was requested at configure-time. */ \ bli_thread_range_jrir( thread, n_iter_rct, 1, FALSE, &jr_start, &jr_end, &jr_inc ); \ \ /* Advance the start and end iteration offsets for the rectangular region by the number of iterations used for the triangular region. */ \ jr_start += n_iter_tri; \ jr_end += n_iter_tri; \ \ /* Loop over the n dimension (NR columns at a time). */ \ for ( j = jr_start; j < jr_end; j += jr_inc ) \ { \ ctype* restrict a1; \ ctype* restrict c11; \ ctype* restrict b2; \ \ b1 = b_cast + j * cstep_b; \ c1 = c_cast + j * cstep_c; \ \ n_cur = ( bli_is_not_edge_f( j, n_iter, n_left ) ? NR : n_left ); \ \ /* Initialize our next panel of B to be the current panel of B. */ \ b2 = b1; \ \ /* Interior loop over the m dimension (MR rows at a time). */ \ for ( i = ir_start; i < ir_end; i += ir_inc ) \ { \ ctype* restrict a2; \ \ a1 = a_cast + i * rstep_a; \ c11 = c1 + i * rstep_c; \ \ /* No need to compute the diagonal offset for the rectangular region. */ \ /*diagoffc_ij = diagoffc - (doff_t)j*NR + (doff_t)i*MR;*/ \ \ m_cur = ( bli_is_not_edge_f( i, m_iter, m_left ) ? MR : m_left ); \ \ /* Compute the addresses of the next panels of A and B. */ \ a2 = bli_gemmt_get_next_a_upanel( a1, rstep_a, ir_inc ); \ if ( bli_is_last_iter( i, m_iter, ir_tid, ir_nt ) ) \ { \ a2 = a_cast; \ b2 = bli_gemmt_get_next_b_upanel( b1, cstep_b, jr_inc ); \ if ( bli_is_last_iter( j, n_iter, jr_tid, jr_nt ) ) \ b2 = b_cast; \ } \ \ /* Save addresses of next panels of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_next_a( a2, &aux ); \ bli_auxinfo_set_next_b( b2, &aux ); \ \ /* If the diagonal intersects the current MR x NR submatrix, we compute it the temporary buffer and then add in the elements on or below the diagonal. Otherwise, if the submatrix is strictly above the diagonal, we compute and store as we normally would. And if we're strictly below the diagonal, we do nothing and continue. */ \ { \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ m_cur, \ n_cur, \ k, \ alpha_cast, \ a1, \ b1, \ beta_cast, \ c11, rs_c, cs_c, \ &aux, \ cntx \ ); \ } \ } \ } \ } INSERT_GENTFUNC_BASIC0( gemmt_u_ker_var2 ) blis-0.9.0/frame/3/gemmt/bli_gemmt_var.h000066400000000000000000000054501422157504600200100ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype object-based interfaces. // #undef GENPROT #define GENPROT( opname ) \ \ void PASTEMAC0(opname) \ ( \ obj_t* a, \ obj_t* ah, \ obj_t* c, \ cntx_t* cntx, \ rntm_t* rntm, \ cntl_t* cntl, \ thrinfo_t* thread \ ); GENPROT( gemmt_x_ker_var2 ) GENPROT( gemmt_l_ker_var2 ) GENPROT( gemmt_u_ker_var2 ) // // Prototype BLAS-like interfaces with void pointer operands. // #undef GENTPROT #define GENTPROT( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ doff_t diagoffc, \ pack_t schema_a, \ pack_t schema_b, \ dim_t m, \ dim_t n, \ dim_t k, \ void* alpha, \ void* a, inc_t cs_a, inc_t is_a, \ dim_t pd_a, inc_t ps_a, \ void* b, inc_t rs_b, inc_t is_b, \ dim_t pd_b, inc_t ps_b, \ void* beta, \ void* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx, \ rntm_t* rntm, \ thrinfo_t* thread \ ); INSERT_GENTPROT_BASIC0( gemmt_l_ker_var2 ) INSERT_GENTPROT_BASIC0( gemmt_u_ker_var2 ) blis-0.9.0/frame/3/gemmt/bli_gemmt_x_ker_var2.c000066400000000000000000000045221422157504600212540ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" static l3_var_oft vars[2] = { bli_gemmt_l_ker_var2, bli_gemmt_u_ker_var2, }; void bli_gemmt_x_ker_var2 ( obj_t* a, obj_t* ah, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ) { dim_t uplo; l3_var_oft f; // Set a bool based on the uplo field of C's root object. if ( bli_obj_root_is_lower( c ) ) uplo = 0; else uplo = 1; // Index into the variant array to extract the correct function pointer. f = vars[uplo]; // Call the macrokernel. f ( a, ah, c, cntx, rntm, cntl, thread ); } blis-0.9.0/frame/3/gemmt/other/000077500000000000000000000000001422157504600161455ustar00rootroot00000000000000blis-0.9.0/frame/3/gemmt/other/bli_gemmt_l_ker_var2.c000066400000000000000000000300611422157504600223560ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define FUNCPTR_T gemmt_fp typedef void (*FUNCPTR_T) ( doff_t diagoffc, pack_t schema_a, pack_t schema_b, dim_t m, dim_t n, dim_t k, void* alpha, void* a, inc_t cs_a, inc_t is_a, dim_t pd_a, inc_t ps_a, void* b, inc_t rs_b, inc_t is_b, dim_t pd_b, inc_t ps_b, void* beta, void* c, inc_t rs_c, inc_t cs_c, cntx_t* cntx, rntm_t* rntm, thrinfo_t* thread ); static FUNCPTR_T GENARRAY(ftypes,gemmt_l_ker_var2); void bli_gemmt_l_ker_var2 ( obj_t* a, obj_t* b, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ) { num_t dt_exec = bli_obj_exec_dt( c ); doff_t diagoffc = bli_obj_diag_offset( c ); pack_t schema_a = bli_obj_pack_schema( a ); pack_t schema_b = bli_obj_pack_schema( b ); dim_t m = bli_obj_length( c ); dim_t n = bli_obj_width( c ); dim_t k = bli_obj_width( a ); void* buf_a = bli_obj_buffer_at_off( a ); inc_t cs_a = bli_obj_col_stride( a ); inc_t is_a = bli_obj_imag_stride( a ); dim_t pd_a = bli_obj_panel_dim( a ); inc_t ps_a = bli_obj_panel_stride( a ); void* buf_b = bli_obj_buffer_at_off( b ); inc_t rs_b = bli_obj_row_stride( b ); inc_t is_b = bli_obj_imag_stride( b ); dim_t pd_b = bli_obj_panel_dim( b ); inc_t ps_b = bli_obj_panel_stride( b ); void* buf_c = bli_obj_buffer_at_off( c ); inc_t rs_c = bli_obj_row_stride( c ); inc_t cs_c = bli_obj_col_stride( c ); obj_t scalar_a; obj_t scalar_b; void* buf_alpha; void* buf_beta; FUNCPTR_T f; // Detach and multiply the scalars attached to A and B. bli_obj_scalar_detach( a, &scalar_a ); bli_obj_scalar_detach( b, &scalar_b ); bli_mulsc( &scalar_a, &scalar_b ); // Grab the addresses of the internal scalar buffers for the scalar // merged above and the scalar attached to C. buf_alpha = bli_obj_internal_scalar_buffer( &scalar_b ); buf_beta = bli_obj_internal_scalar_buffer( c ); // Index into the type combination array to extract the correct // function pointer. f = ftypes[dt_exec]; // Invoke the function. f( diagoffc, schema_a, schema_b, m, n, k, buf_alpha, buf_a, cs_a, is_a, pd_a, ps_a, buf_b, rs_b, is_b, pd_b, ps_b, buf_beta, buf_c, rs_c, cs_c, cntx, rntm, thread ); } #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ doff_t diagoffc, \ pack_t schema_a, \ pack_t schema_b, \ dim_t m, \ dim_t n, \ dim_t k, \ void* alpha, \ void* a, inc_t cs_a, inc_t is_a, \ dim_t pd_a, inc_t ps_a, \ void* b, inc_t rs_b, inc_t is_b, \ dim_t pd_b, inc_t ps_b, \ void* beta, \ void* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx, \ rntm_t* rntm, \ thrinfo_t* thread \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ /* Alias some constants to simpler names. */ \ const dim_t MR = pd_a; \ const dim_t NR = pd_b; \ /*const dim_t PACKMR = cs_a;*/ \ /*const dim_t PACKNR = rs_b;*/ \ \ /* Query the context for the micro-kernel address and cast it to its function pointer type. */ \ PASTECH(ch,gemm_ukr_ft) \ gemm_ukr = bli_cntx_get_l3_vir_ukr_dt( dt, BLIS_GEMM_UKR, cntx ); \ \ /* Temporary C buffer for edge cases. Note that the strides of this temporary buffer are set so that they match the storage of the original C matrix. For example, if C is column-stored, ct will be column-stored as well. */ \ ctype ct[ BLIS_STACK_BUF_MAX_SIZE \ / sizeof( ctype ) ] \ __attribute__((aligned(BLIS_STACK_BUF_ALIGN_SIZE))); \ const bool col_pref = bli_cntx_l3_vir_ukr_prefers_cols_dt( dt, BLIS_GEMM_UKR, cntx ); \ const inc_t rs_ct = ( col_pref ? 1 : NR ); \ const inc_t cs_ct = ( col_pref ? MR : 1 ); \ \ ctype* restrict zero = PASTEMAC(ch,0); \ ctype* restrict a_cast = a; \ ctype* restrict b_cast = b; \ ctype* restrict c_cast = c; \ ctype* restrict alpha_cast = alpha; \ ctype* restrict beta_cast = beta; \ ctype* restrict b1; \ ctype* restrict c1; \ \ doff_t diagoffc_ij; \ dim_t m_iter, m_left; \ dim_t n_iter, n_left; \ dim_t m_cur; \ dim_t n_cur; \ dim_t i, j, ip; \ inc_t rstep_a; \ inc_t cstep_b; \ inc_t rstep_c, cstep_c; \ auxinfo_t aux; \ \ /* Assumptions/assertions: rs_a == 1 cs_a == PACKMR pd_a == MR ps_a == stride to next micro-panel of A rs_b == PACKNR cs_b == 1 pd_b == NR ps_b == stride to next micro-panel of B rs_c == (no assumptions) cs_c == (no assumptions) */ \ \ /* If any dimension is zero, return immediately. */ \ if ( bli_zero_dim3( m, n, k ) ) return; \ \ /* Safeguard: If the current panel of C is entirely above the diagonal, it is not stored. So we do nothing. */ \ if ( bli_is_strictly_above_diag_n( diagoffc, m, n ) ) return; \ \ /* If there is a zero region above where the diagonal of C intersects the left edge of the panel, adjust the pointer to C and A and treat this case as if the diagonal offset were zero. */ \ if ( diagoffc < 0 ) \ { \ ip = -diagoffc / MR; \ i = ip * MR; \ m = m - i; \ diagoffc = -diagoffc % MR; \ c_cast = c_cast + (i )*rs_c; \ a_cast = a_cast + (ip )*ps_a; \ } \ \ /* If there is a zero region to the right of where the diagonal of C intersects the bottom of the panel, shrink it to prevent "no-op" iterations from executing. */ \ if ( diagoffc + m < n ) \ { \ n = diagoffc + m; \ } \ \ /* Clear the temporary C buffer in case it has any infs or NaNs. */ \ PASTEMAC(ch,set0s_mxn)( MR, NR, \ ct, rs_ct, cs_ct ); \ \ /* Compute number of primary and leftover components of the m and n dimensions. */ \ n_iter = n / NR; \ n_left = n % NR; \ \ m_iter = m / MR; \ m_left = m % MR; \ \ if ( n_left ) ++n_iter; \ if ( m_left ) ++m_iter; \ \ /* Determine some increments used to step through A, B, and C. */ \ rstep_a = ps_a; \ \ cstep_b = ps_b; \ \ rstep_c = rs_c * MR; \ cstep_c = cs_c * NR; \ \ /* Save the pack schemas of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_schema_a( schema_a, &aux ); \ bli_auxinfo_set_schema_b( schema_b, &aux ); \ \ /* Save the imaginary stride of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_is_a( is_a, &aux ); \ bli_auxinfo_set_is_b( is_b, &aux ); \ \ b1 = b_cast; \ c1 = c_cast; \ \ thrinfo_t* caucus = bli_thrinfo_sub_node( thread ); \ dim_t jr_num_threads = bli_thread_n_way( thread ); \ dim_t jr_thread_id = bli_thread_work_id( thread ); \ dim_t ir_num_threads = bli_thread_n_way( caucus ); \ dim_t ir_thread_id = bli_thread_work_id( caucus ); \ \ /* Loop over the n dimension (NR columns at a time). */ \ for ( j = jr_thread_id; j < n_iter; j += jr_num_threads ) \ { \ ctype* restrict a1; \ ctype* restrict c11; \ ctype* restrict b2; \ \ b1 = b_cast + j * cstep_b; \ c1 = c_cast + j * cstep_c; \ \ n_cur = ( bli_is_not_edge_f( j, n_iter, n_left ) ? NR : n_left ); \ \ /* Initialize our next panel of B to be the current panel of B. */ \ b2 = b1; \ \ /* Interior loop over the m dimension (MR rows at a time). */ \ for ( i = ir_thread_id; i < m_iter; i += ir_num_threads ) \ { \ ctype* restrict a2; \ \ a1 = a_cast + i * rstep_a; \ c11 = c1 + i * rstep_c; \ \ /* Compute the diagonal offset for the submatrix at (i,j). */ \ diagoffc_ij = diagoffc - (doff_t)j*NR + (doff_t)i*MR; \ \ m_cur = ( bli_is_not_edge_f( i, m_iter, m_left ) ? MR : m_left ); \ \ /* Compute the addresses of the next panels of A and B. */ \ a2 = bli_gemmt_get_next_a_upanel( caucus, a1, rstep_a ); \ if ( bli_is_last_iter( i, m_iter, ir_thread_id, ir_num_threads ) ) \ { \ a2 = a_cast; \ b2 = bli_gemmt_get_next_b_upanel( thread, b1, cstep_b ); \ if ( bli_is_last_iter( j, n_iter, jr_thread_id, jr_num_threads ) ) \ b2 = b_cast; \ } \ \ /* Save addresses of next panels of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_next_a( a2, &aux ); \ bli_auxinfo_set_next_b( b2, &aux ); \ \ /* If the diagonal intersects the current MR x NR submatrix, we compute it the temporary buffer and then add in the elements on or below the diagonal. Otherwise, if the submatrix is strictly below the diagonal, we compute and store as we normally would. And if we're strictly above the diagonal, we do nothing and continue. */ \ if ( bli_intersects_diag_n( diagoffc_ij, m_cur, n_cur ) ) \ { \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k, \ alpha_cast, \ a1, \ b1, \ zero, \ ct, rs_ct, cs_ct, \ &aux, \ cntx \ ); \ \ /* Scale C and add the result to only the stored part. */ \ PASTEMAC(ch,xpbys_mxn_l)( diagoffc_ij, \ m_cur, n_cur, \ ct, rs_ct, cs_ct, \ beta_cast, \ c11, rs_c, cs_c ); \ } \ else if ( bli_is_strictly_below_diag_n( diagoffc_ij, m_cur, n_cur ) ) \ { \ /* Handle interior and edge cases separately. */ \ if ( m_cur == MR && n_cur == NR ) \ { \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k, \ alpha_cast, \ a1, \ b1, \ beta_cast, \ c11, rs_c, cs_c, \ &aux, \ cntx \ ); \ } \ else \ { \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k, \ alpha_cast, \ a1, \ b1, \ zero, \ ct, rs_ct, cs_ct, \ &aux, \ cntx \ ); \ \ /* Scale the edge of C and add the result. */ \ PASTEMAC(ch,xpbys_mxn)( m_cur, n_cur, \ ct, rs_ct, cs_ct, \ beta_cast, \ c11, rs_c, cs_c ); \ } \ } \ } \ } \ } INSERT_GENTFUNC_BASIC0( gemmt_l_ker_var2 ) blis-0.9.0/frame/3/gemmt/other/bli_gemmt_u_ker_var2.c000066400000000000000000000300631422157504600223710ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define FUNCPTR_T gemmt_fp typedef void (*FUNCPTR_T) ( doff_t diagoffc, pack_t schema_a, pack_t schema_b, dim_t m, dim_t n, dim_t k, void* alpha, void* a, inc_t cs_a, inc_t is_a, dim_t pd_a, inc_t ps_a, void* b, inc_t rs_b, inc_t is_b, dim_t pd_b, inc_t ps_b, void* beta, void* c, inc_t rs_c, inc_t cs_c, cntx_t* cntx, rntm_t* rntm, thrinfo_t* thread ); static FUNCPTR_T GENARRAY(ftypes,gemmt_u_ker_var2); void bli_gemmt_u_ker_var2 ( obj_t* a, obj_t* b, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ) { num_t dt_exec = bli_obj_exec_dt( c ); doff_t diagoffc = bli_obj_diag_offset( c ); pack_t schema_a = bli_obj_pack_schema( a ); pack_t schema_b = bli_obj_pack_schema( b ); dim_t m = bli_obj_length( c ); dim_t n = bli_obj_width( c ); dim_t k = bli_obj_width( a ); void* buf_a = bli_obj_buffer_at_off( a ); inc_t cs_a = bli_obj_col_stride( a ); inc_t is_a = bli_obj_imag_stride( a ); dim_t pd_a = bli_obj_panel_dim( a ); inc_t ps_a = bli_obj_panel_stride( a ); void* buf_b = bli_obj_buffer_at_off( b ); inc_t rs_b = bli_obj_row_stride( b ); inc_t is_b = bli_obj_imag_stride( b ); dim_t pd_b = bli_obj_panel_dim( b ); inc_t ps_b = bli_obj_panel_stride( b ); void* buf_c = bli_obj_buffer_at_off( c ); inc_t rs_c = bli_obj_row_stride( c ); inc_t cs_c = bli_obj_col_stride( c ); obj_t scalar_a; obj_t scalar_b; void* buf_alpha; void* buf_beta; FUNCPTR_T f; // Detach and multiply the scalars attached to A and B. bli_obj_scalar_detach( a, &scalar_a ); bli_obj_scalar_detach( b, &scalar_b ); bli_mulsc( &scalar_a, &scalar_b ); // Grab the addresses of the internal scalar buffers for the scalar // merged above and the scalar attached to C. buf_alpha = bli_obj_internal_scalar_buffer( &scalar_b ); buf_beta = bli_obj_internal_scalar_buffer( c ); // Index into the type combination array to extract the correct // function pointer. f = ftypes[dt_exec]; // Invoke the function. f( diagoffc, schema_a, schema_b, m, n, k, buf_alpha, buf_a, cs_a, is_a, pd_a, ps_a, buf_b, rs_b, is_b, pd_b, ps_b, buf_beta, buf_c, rs_c, cs_c, cntx, rntm, thread ); } #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ doff_t diagoffc, \ pack_t schema_a, \ pack_t schema_b, \ dim_t m, \ dim_t n, \ dim_t k, \ void* alpha, \ void* a, inc_t cs_a, inc_t is_a, \ dim_t pd_a, inc_t ps_a, \ void* b, inc_t rs_b, inc_t is_b, \ dim_t pd_b, inc_t ps_b, \ void* beta, \ void* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx, \ rntm_t* rntm, \ thrinfo_t* thread \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ /* Alias some constants to simpler names. */ \ const dim_t MR = pd_a; \ const dim_t NR = pd_b; \ /*const dim_t PACKMR = cs_a;*/ \ /*const dim_t PACKNR = rs_b;*/ \ \ /* Query the context for the micro-kernel address and cast it to its function pointer type. */ \ PASTECH(ch,gemm_ukr_ft) \ gemm_ukr = bli_cntx_get_l3_vir_ukr_dt( dt, BLIS_GEMM_UKR, cntx ); \ \ /* Temporary C buffer for edge cases. Note that the strides of this temporary buffer are set so that they match the storage of the original C matrix. For example, if C is column-stored, ct will be column-stored as well. */ \ ctype ct[ BLIS_STACK_BUF_MAX_SIZE \ / sizeof( ctype ) ] \ __attribute__((aligned(BLIS_STACK_BUF_ALIGN_SIZE))); \ const bool col_pref = bli_cntx_l3_vir_ukr_prefers_cols_dt( dt, BLIS_GEMM_UKR, cntx ); \ const inc_t rs_ct = ( col_pref ? 1 : NR ); \ const inc_t cs_ct = ( col_pref ? MR : 1 ); \ \ ctype* restrict zero = PASTEMAC(ch,0); \ ctype* restrict a_cast = a; \ ctype* restrict b_cast = b; \ ctype* restrict c_cast = c; \ ctype* restrict alpha_cast = alpha; \ ctype* restrict beta_cast = beta; \ ctype* restrict b1; \ ctype* restrict c1; \ \ doff_t diagoffc_ij; \ dim_t m_iter, m_left; \ dim_t n_iter, n_left; \ dim_t m_cur; \ dim_t n_cur; \ dim_t i, j, jp; \ inc_t rstep_a; \ inc_t cstep_b; \ inc_t rstep_c, cstep_c; \ auxinfo_t aux; \ \ /* Assumptions/assertions: rs_a == 1 cs_a == PACKMR pd_a == MR ps_a == stride to next micro-panel of A rs_b == PACKNR cs_b == 1 pd_b == NR ps_b == stride to next micro-panel of B rs_c == (no assumptions) cs_c == (no assumptions) */ \ \ /* If any dimension is zero, return immediately. */ \ if ( bli_zero_dim3( m, n, k ) ) return; \ \ /* Safeguard: If the current panel of C is entirely below the diagonal, it is not stored. So we do nothing. */ \ if ( bli_is_strictly_below_diag_n( diagoffc, m, n ) ) return; \ \ /* If there is a zero region to the left of where the diagonal of C intersects the top edge of the panel, adjust the pointer to C and B and treat this case as if the diagonal offset were zero. */ \ if ( diagoffc > 0 ) \ { \ jp = diagoffc / NR; \ j = jp * NR; \ n = n - j; \ diagoffc = diagoffc % NR; \ c_cast = c_cast + (j )*cs_c; \ b_cast = b_cast + (jp )*ps_b; \ } \ \ /* If there is a zero region below where the diagonal of C intersects the right edge of the panel, shrink it to prevent "no-op" iterations from executing. */ \ if ( -diagoffc + n < m ) \ { \ m = -diagoffc + n; \ } \ \ /* Clear the temporary C buffer in case it has any infs or NaNs. */ \ PASTEMAC(ch,set0s_mxn)( MR, NR, \ ct, rs_ct, cs_ct ); \ \ /* Compute number of primary and leftover components of the m and n dimensions. */ \ n_iter = n / NR; \ n_left = n % NR; \ \ m_iter = m / MR; \ m_left = m % MR; \ \ if ( n_left ) ++n_iter; \ if ( m_left ) ++m_iter; \ \ /* Determine some increments used to step through A, B, and C. */ \ rstep_a = ps_a; \ \ cstep_b = ps_b; \ \ rstep_c = rs_c * MR; \ cstep_c = cs_c * NR; \ \ /* Save the pack schemas of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_schema_a( schema_a, &aux ); \ bli_auxinfo_set_schema_b( schema_b, &aux ); \ \ /* Save the imaginary stride of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_is_a( is_a, &aux ); \ bli_auxinfo_set_is_b( is_b, &aux ); \ \ b1 = b_cast; \ c1 = c_cast; \ \ thrinfo_t* caucus = bli_thrinfo_sub_node( thread ); \ dim_t jr_num_threads = bli_thread_n_way( thread ); \ dim_t jr_thread_id = bli_thread_work_id( thread ); \ dim_t ir_num_threads = bli_thread_n_way( caucus ); \ dim_t ir_thread_id = bli_thread_work_id( caucus ); \ \ /* Loop over the n dimension (NR columns at a time). */ \ for ( j = jr_thread_id; j < n_iter; j += jr_num_threads ) \ { \ ctype* restrict a1; \ ctype* restrict c11; \ ctype* restrict b2; \ \ b1 = b_cast + j * cstep_b; \ c1 = c_cast + j * cstep_c; \ \ n_cur = ( bli_is_not_edge_f( j, n_iter, n_left ) ? NR : n_left ); \ \ /* Initialize our next panel of B to be the current panel of B. */ \ b2 = b1; \ \ /* Interior loop over the m dimension (MR rows at a time). */ \ for ( i = ir_thread_id; i < m_iter; i += ir_num_threads ) \ { \ ctype* restrict a2; \ \ a1 = a_cast + i * rstep_a; \ c11 = c1 + i * rstep_c; \ \ /* Compute the diagonal offset for the submatrix at (i,j). */ \ diagoffc_ij = diagoffc - (doff_t)j*NR + (doff_t)i*MR; \ \ m_cur = ( bli_is_not_edge_f( i, m_iter, m_left ) ? MR : m_left ); \ \ /* Compute the addresses of the next panels of A and B. */ \ a2 = bli_gemmt_get_next_a_upanel( caucus, a1, rstep_a ); \ if ( bli_is_last_iter( i, m_iter, ir_thread_id, ir_num_threads ) ) \ { \ a2 = a_cast; \ b2 = bli_gemmt_get_next_b_upanel( thread, b1, cstep_b ); \ if ( bli_is_last_iter( j, n_iter, jr_thread_id, jr_num_threads ) ) \ b2 = b_cast; \ } \ \ /* Save addresses of next panels of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_next_a( a2, &aux ); \ bli_auxinfo_set_next_b( b2, &aux ); \ \ /* If the diagonal intersects the current MR x NR submatrix, we compute it the temporary buffer and then add in the elements on or below the diagonal. Otherwise, if the submatrix is strictly above the diagonal, we compute and store as we normally would. And if we're strictly below the diagonal, we do nothing and continue. */ \ if ( bli_intersects_diag_n( diagoffc_ij, m_cur, n_cur ) ) \ { \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k, \ alpha_cast, \ a1, \ b1, \ zero, \ ct, rs_ct, cs_ct, \ &aux, \ cntx \ ); \ \ /* Scale C and add the result to only the stored part. */ \ PASTEMAC(ch,xpbys_mxn_u)( diagoffc_ij, \ m_cur, n_cur, \ ct, rs_ct, cs_ct, \ beta_cast, \ c11, rs_c, cs_c ); \ } \ else if ( bli_is_strictly_above_diag_n( diagoffc_ij, m_cur, n_cur ) ) \ { \ /* Handle interior and edge cases separately. */ \ if ( m_cur == MR && n_cur == NR ) \ { \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k, \ alpha_cast, \ a1, \ b1, \ beta_cast, \ c11, rs_c, cs_c, \ &aux, \ cntx \ ); \ } \ else \ { \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k, \ alpha_cast, \ a1, \ b1, \ zero, \ ct, rs_ct, cs_ct, \ &aux, \ cntx \ ); \ \ /* Scale the edge of C and add the result. */ \ PASTEMAC(ch,xpbys_mxn)( m_cur, n_cur, \ ct, rs_ct, cs_ct, \ beta_cast, \ c11, rs_c, cs_c ); \ } \ } \ } \ } \ } INSERT_GENTFUNC_BASIC0( gemmt_u_ker_var2 ) blis-0.9.0/frame/3/hemm/000077500000000000000000000000001422157504600146415ustar00rootroot00000000000000blis-0.9.0/frame/3/hemm/bli_hemm.h000066400000000000000000000032461422157504600165730ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "bli_hemm_front.h" blis-0.9.0/frame/3/hemm/bli_hemm_front.c000066400000000000000000000137661422157504600200060ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_hemm_front ( side_t side, obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl ) { bli_init_once(); obj_t a_local; obj_t b_local; obj_t c_local; // If alpha is zero, scale by beta and return. if ( bli_obj_equals( alpha, &BLIS_ZERO ) ) { bli_scalm( beta, c ); return; } // Alias A, B, and C in case we need to apply transformations. bli_obj_alias_to( a, &a_local ); bli_obj_alias_to( b, &b_local ); bli_obj_alias_to( c, &c_local ); // Set the obj_t buffer field to the location currently implied by the row // and column offsets and then zero the offsets. If any of the original // obj_t's were views into larger matrices, this step effectively makes // those obj_t's "forget" their lineage. bli_obj_reset_origin( &a_local ); bli_obj_reset_origin( &b_local ); bli_obj_reset_origin( &c_local ); #ifdef BLIS_DISABLE_HEMM_RIGHT // NOTE: This case casts right-side hemm in terms of left side. This is // necessary when the current subconfiguration uses a gemm microkernel // that assumes that the packing kernel will have already duplicated // (broadcast) element of B in the packed copy of B. Supporting // duplication within the logic that packs micropanels from Hermitian/ // matrices would be ugly, and so we simply don't support it. As a // consequence, those subconfigurations need a way to force the Hermitian // matrix to be on the left (and thus the general matrix to the on the // right). So our solution is that in those cases, the subconfigurations // simply #define BLIS_DISABLE_HEMM_RIGHT. // NOTE: This case casts right-side hemm in terms of left side. This can // lead to the microkernel being executed on an output matrix with the // microkernel's general stride IO case (unless the microkernel supports // both both row and column IO cases as well). // If A is being multiplied from the right, transpose all operands // so that we can perform the computation as if A were being multiplied // from the left. if ( bli_is_right( side ) ) { bli_toggle_side( &side ); bli_obj_induce_trans( &a_local ); bli_obj_induce_trans( &b_local ); bli_obj_induce_trans( &c_local ); } #else // NOTE: This case computes right-side hemm/symm natively by packing // elements of the Hermitian/symmetric matrix A to micropanels of the // right-hand packed matrix operand "B", and elements of the general // matrix B to micropanels of the left-hand packed matrix operand "A". // This code path always gives us the opportunity to transpose the // entire operation so that the effective storage format of the output // matrix matches the microkernel's output preference. Thus, from a // performance perspective, this case is preferred. // An optimization: If C is stored by rows and the micro-kernel prefers // contiguous columns, or if C is stored by columns and the micro-kernel // prefers contiguous rows, transpose the entire operation to allow the // micro-kernel to access elements of C in its preferred manner. //if ( !bli_obj_is_1x1( &c_local ) ) // NOTE: This conditional should NOT // be enabled. See issue #342 comments. if ( bli_cntx_l3_vir_ukr_dislikes_storage_of( &c_local, BLIS_GEMM_UKR, cntx ) ) { bli_toggle_side( &side ); bli_obj_toggle_conj( &a_local ); bli_obj_induce_trans( &b_local ); bli_obj_induce_trans( &c_local ); } // If the Hermitian/symmetric matrix A is being multiplied from the right, // swap A and B so that the Hermitian/symmetric matrix will actually be on // the right. if ( bli_is_right( side ) ) { bli_obj_swap( &a_local, &b_local ); } #endif // Set the pack schemas within the objects. bli_l3_set_schemas( &a_local, &b_local, &c_local, cntx ); // Parse and interpret the contents of the rntm_t object to properly // set the ways of parallelism for each loop, and then make any // additional modifications necessary for the current operation. bli_rntm_set_ways_for_op ( BLIS_HEMM, BLIS_LEFT, // ignored for gemm/hemm/symm bli_obj_length( &c_local ), bli_obj_width( &c_local ), bli_obj_width( &a_local ), rntm ); // Invoke the internal back-end. bli_l3_thread_decorator ( bli_l3_int, BLIS_GEMM, // operation family id alpha, &a_local, &b_local, beta, &c_local, cntx, rntm, cntl ); } blis-0.9.0/frame/3/hemm/bli_hemm_front.h000066400000000000000000000035401422157504600200000ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void bli_hemm_front ( side_t side, obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl ); blis-0.9.0/frame/3/old/000077500000000000000000000000001422157504600144715ustar00rootroot00000000000000blis-0.9.0/frame/3/old/bli_l3_ft_ex.h000066400000000000000000000134701422157504600172000ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_L3_FT_EX_H #define BLIS_L3_FT_EX_H // // -- Level-3 expert function types -------------------------------------------- // // gemm #undef GENTDEF #define GENTDEF( ctype, ch, opname, tsuf ) \ \ typedef void (*PASTECH3(ch,opname,BLIS_TAPI_EX_SUF,tsuf)) \ ( \ trans_t transa, \ trans_t transb, \ dim_t m, \ dim_t n, \ dim_t k, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* b, inc_t rs_b, inc_t cs_b, \ ctype* beta, \ ctype* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx, \ rntm_t* rntm \ ); INSERT_GENTDEF( gemm ) // hemm, symm #undef GENTDEF #define GENTDEF( ctype, ch, opname, tsuf ) \ \ typedef void (*PASTECH3(ch,opname,BLIS_TAPI_EX_SUF,tsuf)) \ ( \ side_t side, \ uplo_t uploa, \ conj_t conja, \ trans_t transb, \ dim_t m, \ dim_t n, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* b, inc_t rs_b, inc_t cs_b, \ ctype* beta, \ ctype* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx, \ rntm_t* rntm \ ); INSERT_GENTDEF( hemm ) INSERT_GENTDEF( symm ) // herk #undef GENTDEFR #define GENTDEFR( ctype, ctype_r, ch, chr, opname, tsuf ) \ \ typedef void (*PASTECH3(ch,opname,BLIS_TAPI_EX_SUF,tsuf)) \ ( \ uplo_t uploc, \ trans_t transa, \ dim_t m, \ dim_t k, \ ctype_r* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype_r* beta, \ ctype* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx, \ rntm_t* rntm \ ); INSERT_GENTDEFR( herk ) // her2k #undef GENTDEFR #define GENTDEFR( ctype, ctype_r, ch, chr, opname, tsuf ) \ \ typedef void (*PASTECH3(ch,opname,BLIS_TAPI_EX_SUF,tsuf)) \ ( \ uplo_t uploc, \ trans_t transa, \ trans_t transb, \ dim_t m, \ dim_t k, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* b, inc_t rs_b, inc_t cs_b, \ ctype_r* beta, \ ctype* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx, \ rntm_t* rntm \ ); INSERT_GENTDEFR( her2k ) // syrk #undef GENTDEFR #define GENTDEFR( ctype, ctype_r, ch, chr, opname, tsuf ) \ \ typedef void (*PASTECH3(ch,opname,BLIS_TAPI_EX_SUF,tsuf)) \ ( \ uplo_t uploc, \ trans_t transa, \ dim_t m, \ dim_t k, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* beta, \ ctype* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx, \ rntm_t* rntm \ ); INSERT_GENTDEFR( syrk ) // syr2k #undef GENTDEF #define GENTDEF( ctype, ch, opname, tsuf ) \ \ typedef void (*PASTECH3(ch,opname,BLIS_TAPI_EX_SUF,tsuf)) \ ( \ uplo_t uploc, \ trans_t transa, \ trans_t transb, \ dim_t m, \ dim_t k, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* b, inc_t rs_b, inc_t cs_b, \ ctype* beta, \ ctype* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx, \ rntm_t* rntm \ ); INSERT_GENTDEF( syr2k ) // trmm3 #undef GENTDEF #define GENTDEF( ctype, ch, opname, tsuf ) \ \ typedef void (*PASTECH3(ch,opname,BLIS_TAPI_EX_SUF,tsuf)) \ ( \ side_t side, \ uplo_t uploa, \ trans_t transa, \ diag_t diaga, \ trans_t transb, \ dim_t m, \ dim_t n, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* b, inc_t rs_b, inc_t cs_b, \ ctype* beta, \ ctype* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx, \ rntm_t* rntm \ ); INSERT_GENTDEF( trmm3 ) // trmm #undef GENTDEF #define GENTDEF( ctype, ch, opname, tsuf ) \ \ typedef void (*PASTECH3(ch,opname,BLIS_TAPI_EX_SUF,tsuf)) \ ( \ side_t side, \ uplo_t uploa, \ trans_t transa, \ diag_t diaga, \ dim_t m, \ dim_t n, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* b, inc_t rs_b, inc_t cs_b, \ cntx_t* cntx, \ rntm_t* rntm \ ); INSERT_GENTDEF( trmm ) INSERT_GENTDEF( trsm ) #endif blis-0.9.0/frame/3/old/bli_l3_sup_edge.h000066400000000000000000000076521422157504600176730ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ static void bli_dgemmsup_ker_edge_dispatcher ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx, const dim_t num_mr, const dim_t num_nr, dim_t* restrict mrs, dim_t* restrict nrs, dgemmsup_ker_ft* kmap ) { #if 1 // outer loop = mr; inner loop = nr dim_t n_left = n0; double* restrict cj = c; double* restrict bj = b; for ( dim_t j = 0; n_left != 0; ++j ) { const dim_t nr_cur = nrs[ j ]; if ( nr_cur <= n_left ) { dim_t m_left = m0; double* restrict cij = cj; double* restrict ai = a; for ( dim_t i = 0; m_left != 0; ++i ) { const dim_t mr_cur = mrs[ i ]; if ( mr_cur <= m_left ) { dgemmsup_ker_ft ker_fp = kmap[ i*num_nr + j*1 ]; ker_fp ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += mr_cur*rs_c0; ai += mr_cur*rs_a0; m_left -= mr_cur; } } cj += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } } #else // outer loop = nr; inner loop = mr dim_t m_left = m0; double* restrict ci = c; double* restrict ai = a; for ( dim_t i = 0; m_left != 0; ++i ) { const dim_t mr_cur = mrs[ i ]; if ( mr_cur <= m_left ) { dim_t n_left = n0; double* restrict cij = ci; double* restrict bj = b; for ( dim_t j = 0; n_left != 0; ++j ) { const dim_t nr_cur = nrs[ j ]; if ( nr_cur <= n_left ) { dgemmsup_ker_ft ker_fp = kmap[ i*num_nr + j*1 ]; ker_fp ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } } ci += mr_cur*rs_c0; ai += mr_cur*rs_a0; m_left -= mr_cur; } } #endif } blis-0.9.0/frame/3/old/bli_l3_sup_var1n2m.c000066400000000000000000000602601422157504600202420ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define FUNCPTR_T gemmsup_fp typedef void (*FUNCPTR_T) ( conj_t conja, conj_t conjb, dim_t m, dim_t n, dim_t k, void* restrict alpha, void* restrict a, inc_t rs_a, inc_t cs_a, void* restrict b, inc_t rs_b, inc_t cs_b, void* restrict beta, void* restrict c, inc_t rs_c, inc_t cs_c, stor3_t eff_id, cntx_t* restrict cntx, rntm_t* restrict rntm, cntl_t* restrict cntl, thrinfo_t* restrict thread ); // // -- var1n -------------------------------------------------------------------- // static FUNCPTR_T GENARRAY(ftypes_var1n,gemmsup_ref_var1n); void bli_gemmsup_ref_var1n ( trans_t trans, obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, stor3_t eff_id, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ) { #if 0 obj_t at, bt; bli_obj_alias_to( a, &at ); bli_obj_alias_to( b, &bt ); // Induce transpositions on A and/or B if either object is marked for // transposition. We can induce "fast" transpositions since they objects // are guaranteed to not have structure or be packed. if ( bli_obj_has_trans( &at ) ) { bli_obj_induce_fast_trans( &at ); } if ( bli_obj_has_trans( &bt ) ) { bli_obj_induce_fast_trans( &bt ); } const num_t dt_exec = bli_obj_dt( c ); const conj_t conja = bli_obj_conj_status( a ); const conj_t conjb = bli_obj_conj_status( b ); const dim_t m = bli_obj_length( c ); const dim_t n = bli_obj_width( c ); const dim_t k = bli_obj_width( &at ); void* restrict buf_a = bli_obj_buffer_at_off( &at ); const inc_t rs_a = bli_obj_row_stride( &at ); const inc_t cs_a = bli_obj_col_stride( &at ); void* restrict buf_b = bli_obj_buffer_at_off( &bt ); const inc_t rs_b = bli_obj_row_stride( &bt ); const inc_t cs_b = bli_obj_col_stride( &bt ); void* restrict buf_c = bli_obj_buffer_at_off( c ); const inc_t rs_c = bli_obj_row_stride( c ); const inc_t cs_c = bli_obj_col_stride( c ); void* restrict buf_alpha = bli_obj_buffer_for_1x1( dt_exec, alpha ); void* restrict buf_beta = bli_obj_buffer_for_1x1( dt_exec, beta ); #else const num_t dt_exec = bli_obj_dt( c ); const conj_t conja = bli_obj_conj_status( a ); const conj_t conjb = bli_obj_conj_status( b ); const dim_t m = bli_obj_length( c ); const dim_t n = bli_obj_width( c ); dim_t k; void* restrict buf_a = bli_obj_buffer_at_off( a ); inc_t rs_a; inc_t cs_a; void* restrict buf_b = bli_obj_buffer_at_off( b ); inc_t rs_b; inc_t cs_b; if ( bli_obj_has_notrans( a ) ) { k = bli_obj_width( a ); rs_a = bli_obj_row_stride( a ); cs_a = bli_obj_col_stride( a ); } else // if ( bli_obj_has_trans( a ) ) { // Assign the variables with an implicit transposition. k = bli_obj_length( a ); rs_a = bli_obj_col_stride( a ); cs_a = bli_obj_row_stride( a ); } if ( bli_obj_has_notrans( b ) ) { rs_b = bli_obj_row_stride( b ); cs_b = bli_obj_col_stride( b ); } else // if ( bli_obj_has_trans( b ) ) { // Assign the variables with an implicit transposition. rs_b = bli_obj_col_stride( b ); cs_b = bli_obj_row_stride( b ); } void* restrict buf_c = bli_obj_buffer_at_off( c ); const inc_t rs_c = bli_obj_row_stride( c ); const inc_t cs_c = bli_obj_col_stride( c ); void* restrict buf_alpha = bli_obj_buffer_for_1x1( dt_exec, alpha ); void* restrict buf_beta = bli_obj_buffer_for_1x1( dt_exec, beta ); #endif // Index into the type combination array to extract the correct // function pointer. FUNCPTR_T f = ftypes_var1n[dt_exec]; if ( bli_is_notrans( trans ) ) { // Invoke the function. f ( conja, conjb, m, n, k, buf_alpha, buf_a, rs_a, cs_a, buf_b, rs_b, cs_b, buf_beta, buf_c, rs_c, cs_c, eff_id, cntx, rntm, cntl, thread ); } else { // Invoke the function (transposing the operation). f ( conjb, // swap the conj values. conja, n, // swap the m and n dimensions. m, k, buf_alpha, buf_b, cs_b, rs_b, // swap the positions of A and B. buf_a, cs_a, rs_a, // swap the strides of A and B. buf_beta, buf_c, cs_c, rs_c, // swap the strides of C. bli_stor3_trans( eff_id ), // transpose the stor3_t id. cntx, rntm, cntl, thread ); } } #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ conj_t conja, \ conj_t conjb, \ dim_t m, \ dim_t n, \ dim_t k, \ void* restrict alpha, \ void* restrict a, inc_t rs_a, inc_t cs_a, \ void* restrict b, inc_t rs_b, inc_t cs_b, \ void* restrict beta, \ void* restrict c, inc_t rs_c, inc_t cs_c, \ stor3_t stor_id, \ cntx_t* restrict cntx, \ rntm_t* restrict rntm, \ cntl_t* restrict cntl, \ thrinfo_t* restrict thread \ ) \ { \ /* If m or n is zero, return immediately. */ \ if ( bli_zero_dim2( m, n ) ) return; \ \ /* If k < 1 or alpha is zero, scale by beta and return. */ \ if ( k < 1 || PASTEMAC(ch,eq0)( *(( ctype* )alpha) ) ) \ { \ PASTEMAC(ch,scalm) \ ( \ BLIS_NO_CONJUGATE, \ 0, \ BLIS_NONUNIT_DIAG, \ BLIS_DENSE, \ m, n, \ beta, \ c, rs_c, cs_c \ ); \ return; \ } \ \ const num_t dt = PASTEMAC(ch,type); \ \ /* This transposition of the stor3_t id value is inherent to variant 1. The reason: we assume that variant 2 is the "main" variant. The consequence of this is that we assume that the millikernels that iterate over m are registered to the kernel group associated with the kernel preference. So, regardless of whether the mkernels are row- or column-preferential, millikernels that iterate over n are always placed in the slots for the opposite kernel group. */ \ stor_id = bli_stor3_trans( stor_id ); \ \ /* Query the context for various blocksizes. */ \ const dim_t NR = bli_cntx_get_l3_sup_blksz_def_dt( dt, BLIS_NR, cntx ); \ const dim_t MR = bli_cntx_get_l3_sup_blksz_def_dt( dt, BLIS_MR, cntx ); \ const dim_t NC0 = bli_cntx_get_l3_sup_blksz_def_dt( dt, BLIS_NC, cntx ); \ const dim_t MC0 = bli_cntx_get_l3_sup_blksz_def_dt( dt, BLIS_MC, cntx ); \ const dim_t KC0 = bli_cntx_get_l3_sup_blksz_def_dt( dt, BLIS_KC, cntx ); \ \ dim_t KC; \ if ( FALSE ) KC = KC0; \ else if ( stor_id == BLIS_RRC || \ stor_id == BLIS_CRC ) KC = KC0; \ else if ( m <= MR && n <= NR ) KC = KC0; \ else if ( m <= 2*MR && n <= 2*NR ) KC = KC0 / 2; \ else if ( m <= 3*MR && n <= 3*NR ) KC = (( KC0 / 3 ) / 4 ) * 4; \ else if ( m <= 4*MR && n <= 4*NR ) KC = KC0 / 4; \ else KC = (( KC0 / 5 ) / 4 ) * 4; \ \ /* Nudge NC up to a multiple of MR and MC up to a multiple of NR. */ \ const dim_t NC = bli_align_dim_to_mult( NC0, MR ); \ const dim_t MC = bli_align_dim_to_mult( MC0, NR ); \ \ /* Query the maximum blocksize for MR, which implies a maximum blocksize extension for the final iteration. */ \ const dim_t MRM = bli_cntx_get_l3_sup_blksz_max_dt( dt, BLIS_MR, cntx ); \ const dim_t MRE = MRM - MR; \ \ /* Compute partitioning step values for each matrix of each loop. */ \ const inc_t jcstep_c = rs_c * NC; \ const inc_t jcstep_a = rs_a * NC; \ \ const inc_t pcstep_a = cs_a * KC; \ const inc_t pcstep_b = rs_b * KC; \ \ const inc_t icstep_c = cs_c * MC; \ const inc_t icstep_b = cs_b * MC; \ \ const inc_t jrstep_c = rs_c * MR; \ const inc_t jrstep_a = rs_a * MR; \ \ /* const inc_t irstep_c = cs_c * NR; \ const inc_t irstep_b = cs_b * NR; \ */ \ \ /* Query the context for the sup microkernel address and cast it to its function pointer type. */ \ PASTECH(ch,gemmsup_ker_ft) \ gemmsup_ker = bli_cntx_get_l3_sup_ker_dt( dt, stor_id, cntx ); \ \ ctype* restrict a_00 = a; \ ctype* restrict b_00 = b; \ ctype* restrict c_00 = c; \ ctype* restrict alpha_cast = alpha; \ ctype* restrict beta_cast = beta; \ \ ctype* restrict one = PASTEMAC(ch,1); \ \ auxinfo_t aux; \ \ /* Compute number of primary and leftover components of the outer dimensions. NOTE: Functionally speaking, we compute jc_iter as: jc_iter = m / NC; if ( jc_left ) ++jc_iter; However, this is implemented as: jc_iter = ( m + NC - 1 ) / NC; This avoids a branch at the cost of two additional integer instructions. The pc_iter, mc_iter, nr_iter, and mr_iter variables are computed in similar manner. */ \ const dim_t jc_iter = ( m + NC - 1 ) / NC; \ const dim_t jc_left = m % NC; \ \ const dim_t pc_iter = ( k + KC - 1 ) / KC; \ const dim_t pc_left = k % KC; \ \ const dim_t ic_iter = ( n + MC - 1 ) / MC; \ const dim_t ic_left = n % MC; \ \ const dim_t jc_inc = 1; \ const dim_t pc_inc = 1; \ const dim_t ic_inc = 1; \ const dim_t jr_inc = 1; \ /* const dim_t ir_inc = 1; \ */ \ \ /* Loop over the m dimension (NC rows/columns at a time). */ \ for ( dim_t jj = 0; jj < jc_iter; jj += jc_inc ) \ { \ const dim_t nc_cur = ( bli_is_not_edge_f( jj, jc_iter, jc_left ) ? NC : jc_left ); \ \ ctype* restrict a_jc = a_00 + jj * jcstep_a; \ ctype* restrict c_jc = c_00 + jj * jcstep_c; \ \ dim_t jr_iter = ( nc_cur + MR - 1 ) / MR; \ dim_t jr_left = nc_cur % MR; \ \ /* An optimization: allow the last jr iteration to contain up to MRE rows of C and A. (If MRE > MR, the mkernel has agreed to handle these cases.) Note that this prevents us from declaring jr_iter and jr_left as const. */ \ if ( 1 ) \ if ( MRE != 0 && 1 < jr_iter && jr_left != 0 && jr_left <= MRE ) \ { \ jr_iter--; jr_left += MR; \ } \ \ /* Loop over the k dimension (KC rows/columns at a time). */ \ for ( dim_t pp = 0; pp < pc_iter; pp += pc_inc ) \ { \ const dim_t kc_cur = ( bli_is_not_edge_f( pp, pc_iter, pc_left ) ? KC : pc_left ); \ \ ctype* restrict a_pc = a_jc + pp * pcstep_a; \ ctype* restrict b_pc = b_00 + pp * pcstep_b; \ \ /* Only apply beta to the first iteration of the pc loop. */ \ ctype* restrict beta_use = ( pp == 0 ? beta_cast : one ); \ \ /* Loop over the n dimension (MC rows at a time). */ \ for ( dim_t ii = 0; ii < ic_iter; ii += ic_inc ) \ { \ const dim_t mc_cur = ( bli_is_not_edge_f( ii, ic_iter, ic_left ) ? MC : ic_left ); \ \ ctype* restrict b_ic = b_pc + ii * icstep_b; \ ctype* restrict c_ic = c_jc + ii * icstep_c; \ \ /* const dim_t ir_iter = ( mc_cur + NR - 1 ) / NR; \ const dim_t ir_left = mc_cur % NR; \ */ \ \ /* Loop over the m dimension (NR columns at a time). */ \ for ( dim_t j = 0; j < jr_iter; j += jr_inc ) \ { \ const dim_t nr_cur = ( bli_is_not_edge_f( j, jr_iter, jr_left ) ? MR : jr_left ); \ \ ctype* restrict a_jr = a_pc + j * jrstep_a; \ ctype* restrict c_jr = c_ic + j * jrstep_c; \ \ /* Loop over the n dimension (MR rows at a time). */ \ { \ /* Invoke the gemmsup millikernel. */ \ gemmsup_ker \ ( \ conja, \ conjb, \ nr_cur, /* Notice: nr_cur <= MR. */ \ mc_cur, /* Recall: mc_cur partitions the n dimension! */ \ kc_cur, \ alpha_cast, \ a_jr, rs_a, cs_a, \ b_ic, rs_b, cs_b, \ beta_use, \ c_jr, rs_c, cs_c, \ &aux, \ cntx \ ); \ } \ } \ } \ } \ } \ \ /* PASTEMAC(ch,fprintm)( stdout, "gemmsup_ref_var2: b1", kc_cur, nr_cur, b_jr, rs_b, cs_b, "%4.1f", "" ); \ PASTEMAC(ch,fprintm)( stdout, "gemmsup_ref_var2: a1", mr_cur, kc_cur, a_ir, rs_a, cs_a, "%4.1f", "" ); \ PASTEMAC(ch,fprintm)( stdout, "gemmsup_ref_var2: c ", mr_cur, nr_cur, c_ir, rs_c, cs_c, "%4.1f", "" ); \ */ \ } INSERT_GENTFUNC_BASIC0( gemmsup_ref_var1n ) // // -- var2m -------------------------------------------------------------------- // static FUNCPTR_T GENARRAY(ftypes_var2m,gemmsup_ref_var2m); void bli_gemmsup_ref_var2m ( trans_t trans, obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, stor3_t eff_id, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ) { #if 0 obj_t at, bt; bli_obj_alias_to( a, &at ); bli_obj_alias_to( b, &bt ); // Induce transpositions on A and/or B if either object is marked for // transposition. We can induce "fast" transpositions since they objects // are guaranteed to not have structure or be packed. if ( bli_obj_has_trans( &at ) ) { bli_obj_induce_fast_trans( &at ); } if ( bli_obj_has_trans( &bt ) ) { bli_obj_induce_fast_trans( &bt ); } const num_t dt_exec = bli_obj_dt( c ); const conj_t conja = bli_obj_conj_status( a ); const conj_t conjb = bli_obj_conj_status( b ); const dim_t m = bli_obj_length( c ); const dim_t n = bli_obj_width( c ); const dim_t k = bli_obj_width( &at ); void* restrict buf_a = bli_obj_buffer_at_off( &at ); const inc_t rs_a = bli_obj_row_stride( &at ); const inc_t cs_a = bli_obj_col_stride( &at ); void* restrict buf_b = bli_obj_buffer_at_off( &bt ); const inc_t rs_b = bli_obj_row_stride( &bt ); const inc_t cs_b = bli_obj_col_stride( &bt ); void* restrict buf_c = bli_obj_buffer_at_off( c ); const inc_t rs_c = bli_obj_row_stride( c ); const inc_t cs_c = bli_obj_col_stride( c ); void* restrict buf_alpha = bli_obj_buffer_for_1x1( dt_exec, alpha ); void* restrict buf_beta = bli_obj_buffer_for_1x1( dt_exec, beta ); #else const num_t dt_exec = bli_obj_dt( c ); const conj_t conja = bli_obj_conj_status( a ); const conj_t conjb = bli_obj_conj_status( b ); const dim_t m = bli_obj_length( c ); const dim_t n = bli_obj_width( c ); dim_t k; void* restrict buf_a = bli_obj_buffer_at_off( a ); inc_t rs_a; inc_t cs_a; void* restrict buf_b = bli_obj_buffer_at_off( b ); inc_t rs_b; inc_t cs_b; if ( bli_obj_has_notrans( a ) ) { k = bli_obj_width( a ); rs_a = bli_obj_row_stride( a ); cs_a = bli_obj_col_stride( a ); } else // if ( bli_obj_has_trans( a ) ) { // Assign the variables with an implicit transposition. k = bli_obj_length( a ); rs_a = bli_obj_col_stride( a ); cs_a = bli_obj_row_stride( a ); } if ( bli_obj_has_notrans( b ) ) { rs_b = bli_obj_row_stride( b ); cs_b = bli_obj_col_stride( b ); } else // if ( bli_obj_has_trans( b ) ) { // Assign the variables with an implicit transposition. rs_b = bli_obj_col_stride( b ); cs_b = bli_obj_row_stride( b ); } void* restrict buf_c = bli_obj_buffer_at_off( c ); const inc_t rs_c = bli_obj_row_stride( c ); const inc_t cs_c = bli_obj_col_stride( c ); void* restrict buf_alpha = bli_obj_buffer_for_1x1( dt_exec, alpha ); void* restrict buf_beta = bli_obj_buffer_for_1x1( dt_exec, beta ); #endif // Index into the type combination array to extract the correct // function pointer. FUNCPTR_T f = ftypes_var2m[dt_exec]; if ( bli_is_notrans( trans ) ) { // Invoke the function. f ( conja, conjb, m, n, k, buf_alpha, buf_a, rs_a, cs_a, buf_b, rs_b, cs_b, buf_beta, buf_c, rs_c, cs_c, eff_id, cntx, rntm, cntl, thread ); } else { // Invoke the function (transposing the operation). f ( conjb, // swap the conj values. conja, n, // swap the m and n dimensions. m, k, buf_alpha, buf_b, cs_b, rs_b, // swap the positions of A and B. buf_a, cs_a, rs_a, // swap the strides of A and B. buf_beta, buf_c, cs_c, rs_c, // swap the strides of C. bli_stor3_trans( eff_id ), // transpose the stor3_t id. cntx, rntm, cntl, thread ); } } #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ conj_t conja, \ conj_t conjb, \ dim_t m, \ dim_t n, \ dim_t k, \ void* restrict alpha, \ void* restrict a, inc_t rs_a, inc_t cs_a, \ void* restrict b, inc_t rs_b, inc_t cs_b, \ void* restrict beta, \ void* restrict c, inc_t rs_c, inc_t cs_c, \ stor3_t stor_id, \ cntx_t* restrict cntx, \ rntm_t* restrict rntm, \ cntl_t* restrict cntl, \ thrinfo_t* restrict thread \ ) \ { \ /* If m or n is zero, return immediately. */ \ if ( bli_zero_dim2( m, n ) ) return; \ \ /* If k < 1 or alpha is zero, scale by beta and return. */ \ if ( k < 1 || PASTEMAC(ch,eq0)( *(( ctype* )alpha) ) ) \ { \ PASTEMAC(ch,scalm) \ ( \ BLIS_NO_CONJUGATE, \ 0, \ BLIS_NONUNIT_DIAG, \ BLIS_DENSE, \ m, n, \ beta, \ c, rs_c, cs_c \ ); \ return; \ } \ \ const num_t dt = PASTEMAC(ch,type); \ \ /* Query the context for various blocksizes. */ \ const dim_t NR = bli_cntx_get_l3_sup_blksz_def_dt( dt, BLIS_NR, cntx ); \ const dim_t MR = bli_cntx_get_l3_sup_blksz_def_dt( dt, BLIS_MR, cntx ); \ const dim_t NC = bli_cntx_get_l3_sup_blksz_def_dt( dt, BLIS_NC, cntx ); \ const dim_t MC = bli_cntx_get_l3_sup_blksz_def_dt( dt, BLIS_MC, cntx ); \ const dim_t KC0 = bli_cntx_get_l3_sup_blksz_def_dt( dt, BLIS_KC, cntx ); \ \ dim_t KC; \ if ( stor_id == BLIS_RRR || \ stor_id == BLIS_CCC ) KC = KC0; \ else if ( stor_id == BLIS_RRC || \ stor_id == BLIS_CRC ) KC = KC0; \ else if ( m <= MR && n <= NR ) KC = KC0; \ else if ( m <= 2*MR && n <= 2*NR ) KC = KC0 / 2; \ else if ( m <= 3*MR && n <= 3*NR ) KC = (( KC0 / 3 ) / 4 ) * 4; \ else if ( m <= 4*MR && n <= 4*NR ) KC = KC0 / 4; \ else KC = (( KC0 / 5 ) / 4 ) * 4; \ \ /* Query the maximum blocksize for NR, which implies a maximum blocksize extension for the final iteration. */ \ const dim_t NRM = bli_cntx_get_l3_sup_blksz_max_dt( dt, BLIS_NR, cntx ); \ const dim_t NRE = NRM - NR; \ \ /* Compute partitioning step values for each matrix of each loop. */ \ const inc_t jcstep_c = cs_c * NC; \ const inc_t jcstep_b = cs_b * NC; \ \ const inc_t pcstep_a = cs_a * KC; \ const inc_t pcstep_b = rs_b * KC; \ \ const inc_t icstep_c = rs_c * MC; \ const inc_t icstep_a = rs_a * MC; \ \ const inc_t jrstep_c = cs_c * NR; \ const inc_t jrstep_b = cs_b * NR; \ \ /* const inc_t irstep_c = rs_c * MR; \ const inc_t irstep_a = rs_a * MR; \ */ \ \ /* Query the context for the sup microkernel address and cast it to its function pointer type. */ \ PASTECH(ch,gemmsup_ker_ft) \ gemmsup_ker = bli_cntx_get_l3_sup_ker_dt( dt, stor_id, cntx ); \ \ ctype* restrict a_00 = a; \ ctype* restrict b_00 = b; \ ctype* restrict c_00 = c; \ ctype* restrict alpha_cast = alpha; \ ctype* restrict beta_cast = beta; \ \ ctype* restrict one = PASTEMAC(ch,1); \ \ auxinfo_t aux; \ \ /* Compute number of primary and leftover components of the outer dimensions. NOTE: Functionally speaking, we compute jc_iter as: jc_iter = n / NC; if ( jc_left ) ++jc_iter; However, this is implemented as: jc_iter = ( n + NC - 1 ) / NC; This avoids a branch at the cost of two additional integer instructions. The pc_iter, mc_iter, nr_iter, and mr_iter variables are computed in similar manner. */ \ const dim_t jc_iter = ( n + NC - 1 ) / NC; \ const dim_t jc_left = n % NC; \ \ const dim_t pc_iter = ( k + KC - 1 ) / KC; \ const dim_t pc_left = k % KC; \ \ const dim_t ic_iter = ( m + MC - 1 ) / MC; \ const dim_t ic_left = m % MC; \ \ const dim_t jc_inc = 1; \ const dim_t pc_inc = 1; \ const dim_t ic_inc = 1; \ const dim_t jr_inc = 1; \ /* const dim_t ir_inc = 1; \ */ \ \ /* Loop over the n dimension (NC rows/columns at a time). */ \ for ( dim_t jj = 0; jj < jc_iter; jj += jc_inc ) \ { \ const dim_t nc_cur = ( bli_is_not_edge_f( jj, jc_iter, jc_left ) ? NC : jc_left ); \ \ ctype* restrict b_jc = b_00 + jj * jcstep_b; \ ctype* restrict c_jc = c_00 + jj * jcstep_c; \ \ dim_t jr_iter = ( nc_cur + NR - 1 ) / NR; \ dim_t jr_left = nc_cur % NR; \ \ /* An optimization: allow the last jr iteration to contain up to NRE columns of C and B. (If NRE > NR, the mkernel has agreed to handle these cases.) Note that this prevents us from declaring jr_iter and jr_left as const. */ \ if ( 1 ) \ if ( NRE != 0 && 1 < jr_iter && jr_left != 0 && jr_left <= NRE ) \ { \ jr_iter--; jr_left += NR; \ } \ \ /* Loop over the k dimension (KC rows/columns at a time). */ \ for ( dim_t pp = 0; pp < pc_iter; pp += pc_inc ) \ { \ const dim_t kc_cur = ( bli_is_not_edge_f( pp, pc_iter, pc_left ) ? KC : pc_left ); \ \ ctype* restrict a_pc = a_00 + pp * pcstep_a; \ ctype* restrict b_pc = b_jc + pp * pcstep_b; \ \ /* Only apply beta to the first iteration of the pc loop. */ \ ctype* restrict beta_use = ( pp == 0 ? beta_cast : one ); \ \ /* Loop over the m dimension (MC rows at a time). */ \ for ( dim_t ii = 0; ii < ic_iter; ii += ic_inc ) \ { \ const dim_t mc_cur = ( bli_is_not_edge_f( ii, ic_iter, ic_left ) ? MC : ic_left ); \ \ ctype* restrict a_ic = a_pc + ii * icstep_a; \ ctype* restrict c_ic = c_jc + ii * icstep_c; \ \ /* const dim_t ir_iter = ( mc_cur + MR - 1 ) / MR; \ const dim_t ir_left = mc_cur % MR; \ */ \ \ /* Loop over the n dimension (NR columns at a time). */ \ for ( dim_t j = 0; j < jr_iter; j += jr_inc ) \ { \ const dim_t nr_cur = ( bli_is_not_edge_f( j, jr_iter, jr_left ) ? NR : jr_left ); \ \ ctype* restrict b_jr = b_pc + j * jrstep_b; \ ctype* restrict c_jr = c_ic + j * jrstep_c; \ \ /* Loop over the m dimension (MR rows at a time). */ \ { \ /* Invoke the gemmsup millikernel. */ \ gemmsup_ker \ ( \ conja, \ conjb, \ mc_cur, \ nr_cur, \ kc_cur, \ alpha_cast, \ a_ic, rs_a, cs_a, \ b_jr, rs_b, cs_b, \ beta_use, \ c_jr, rs_c, cs_c, \ &aux, \ cntx \ ); \ } \ } \ } \ } \ } \ \ /* PASTEMAC(ch,fprintm)( stdout, "gemmsup_ref_var2: b1", kc_cur, nr_cur, b_jr, rs_b, cs_b, "%4.1f", "" ); \ PASTEMAC(ch,fprintm)( stdout, "gemmsup_ref_var2: a1", mr_cur, kc_cur, a_ir, rs_a, cs_a, "%4.1f", "" ); \ PASTEMAC(ch,fprintm)( stdout, "gemmsup_ref_var2: c ", mr_cur, nr_cur, c_ir, rs_c, cs_c, "%4.1f", "" ); \ */ \ } INSERT_GENTFUNC_BASIC0( gemmsup_ref_var2m ) blis-0.9.0/frame/3/symm/000077500000000000000000000000001422157504600147005ustar00rootroot00000000000000blis-0.9.0/frame/3/symm/bli_symm.h000066400000000000000000000032461422157504600166710ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "bli_symm_front.h" blis-0.9.0/frame/3/symm/bli_symm_front.c000066400000000000000000000137221422157504600200740ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_symm_front ( side_t side, obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl ) { bli_init_once(); obj_t a_local; obj_t b_local; obj_t c_local; // If alpha is zero, scale by beta and return. if ( bli_obj_equals( alpha, &BLIS_ZERO ) ) { bli_scalm( beta, c ); return; } // Alias A, B, and C in case we need to apply transformations. bli_obj_alias_to( a, &a_local ); bli_obj_alias_to( b, &b_local ); bli_obj_alias_to( c, &c_local ); // Set the obj_t buffer field to the location currently implied by the row // and column offsets and then zero the offsets. If any of the original // obj_t's were views into larger matrices, this step effectively makes // those obj_t's "forget" their lineage. bli_obj_reset_origin( &a_local ); bli_obj_reset_origin( &b_local ); bli_obj_reset_origin( &c_local ); #ifdef BLIS_DISABLE_SYMM_RIGHT // NOTE: This case casts right-side symm in terms of left side. This is // necessary when the current subconfiguration uses a gemm microkernel // that assumes that the packing kernel will have already duplicated // (broadcast) element of B in the packed copy of B. Supporting // duplication within the logic that packs micropanels from symmetric // matrices would be ugly, and so we simply don't support it. As a // consequence, those subconfigurations need a way to force the symmetric // matrix to be on the left (and thus the general matrix to the on the // right). So our solution is that in those cases, the subconfigurations // simply #define BLIS_DISABLE_SYMM_RIGHT. // NOTE: This case casts right-side symm in terms of left side. This can // lead to the microkernel being executed on an output matrix with the // microkernel's general stride IO case (unless the microkernel supports // both both row and column IO cases as well). // If A is being multiplied from the right, transpose all operands // so that we can perform the computation as if A were being multiplied // from the left. if ( bli_is_right( side ) ) { bli_toggle_side( &side ); bli_obj_induce_trans( &a_local ); bli_obj_induce_trans( &b_local ); bli_obj_induce_trans( &c_local ); } #else // NOTE: This case computes right-side hemm/symm natively by packing // elements of the Hermitian/symmetric matrix A to micropanels of the // right-hand packed matrix operand "B", and elements of the general // matrix B to micropanels of the left-hand packed matrix operand "A". // This code path always gives us the opportunity to transpose the // entire operation so that the effective storage format of the output // matrix matches the microkernel's output preference. Thus, from a // performance perspective, this case is preferred. // An optimization: If C is stored by rows and the micro-kernel prefers // contiguous columns, or if C is stored by columns and the micro-kernel // prefers contiguous rows, transpose the entire operation to allow the // micro-kernel to access elements of C in its preferred manner. //if ( !bli_obj_is_1x1( &c_local ) ) // NOTE: This conditional should NOT // be enabled. See issue #342 comments. if ( bli_cntx_l3_vir_ukr_dislikes_storage_of( &c_local, BLIS_GEMM_UKR, cntx ) ) { bli_toggle_side( &side ); bli_obj_induce_trans( &b_local ); bli_obj_induce_trans( &c_local ); } // If the Hermitian/symmetric matrix A is being multiplied from the right, // swap A and B so that the Hermitian/symmetric matrix will actually be on // the right. if ( bli_is_right( side ) ) { bli_obj_swap( &a_local, &b_local ); } #endif // Set the pack schemas within the objects. bli_l3_set_schemas( &a_local, &b_local, &c_local, cntx ); // Parse and interpret the contents of the rntm_t object to properly // set the ways of parallelism for each loop, and then make any // additional modifications necessary for the current operation. bli_rntm_set_ways_for_op ( BLIS_SYMM, BLIS_LEFT, // ignored for gemm/hemm/symm bli_obj_length( &c_local ), bli_obj_width( &c_local ), bli_obj_width( &a_local ), rntm ); // Invoke the internal back-end. bli_l3_thread_decorator ( bli_l3_int, BLIS_GEMM, // operation family id alpha, &a_local, &b_local, beta, &c_local, cntx, rntm, cntl ); } blis-0.9.0/frame/3/symm/bli_symm_front.h000066400000000000000000000035401422157504600200760ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void bli_symm_front ( side_t side, obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl ); blis-0.9.0/frame/3/trmm/000077500000000000000000000000001422157504600146725ustar00rootroot00000000000000blis-0.9.0/frame/3/trmm/bli_trmm.h000066400000000000000000000033011422157504600166450ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "bli_trmm_front.h" #include "bli_trmm_var.h" blis-0.9.0/frame/3/trmm/bli_trmm_front.c000066400000000000000000000155531422157504600200640ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_trmm_front ( side_t side, obj_t* alpha, obj_t* a, obj_t* b, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl ) { bli_init_once(); obj_t a_local; obj_t b_local; obj_t c_local; // If alpha is zero, scale by beta and return. if ( bli_obj_equals( alpha, &BLIS_ZERO ) ) { bli_scalm( alpha, b ); return; } // Alias A and B so we can tweak the objects if necessary. bli_obj_alias_to( a, &a_local ); bli_obj_alias_to( b, &b_local ); bli_obj_alias_to( b, &c_local ); // Set the obj_t buffer field to the location currently implied by the row // and column offsets and then zero the offsets. If any of the original // obj_t's were views into larger matrices, this step effectively makes // those obj_t's "forget" their lineage. bli_obj_reset_origin( &a_local ); bli_obj_reset_origin( &b_local ); bli_obj_reset_origin( &c_local ); // We do not explicitly implement the cases where A is transposed. // However, we can still handle them. Specifically, if A is marked as // needing a transposition, we simply induce a transposition. This // allows us to only explicitly implement the no-transpose cases. Once // the transposition is induced, the correct algorithm will be called, // since, for example, an algorithm over a transposed lower triangular // matrix A moves in the same direction (forwards) as a non-transposed // upper triangular matrix. And with the transposition induced, the // matrix now appears to be upper triangular, so the upper triangular // algorithm will grab the correct partitions, as if it were upper // triangular (with no transpose) all along. if ( bli_obj_has_trans( &a_local ) ) { bli_obj_induce_trans( &a_local ); bli_obj_set_onlytrans( BLIS_NO_TRANSPOSE, &a_local ); } #ifdef BLIS_DISABLE_TRMM_RIGHT // NOTE: This case casts right-side trmm in terms of left side. This is // necessary when the current subconfiguration uses a gemm microkernel // that assumes that the packing kernel will have already duplicated // (broadcast) element of B in the packed copy of B. Supporting // duplication within the logic that packs micropanels from triangular // matrices would be ugly, and so we simply don't support it. As a // consequence, those subconfigurations need a way to force the triangular // matrix to be on the left (and thus the general matrix to the on the // right). So our solution is that in those cases, the subconfigurations // simply #define BLIS_DISABLE_TRMM_RIGHT. // NOTE: This case casts right-side trmm in terms of left side. This can // lead to the microkernel being executed on an output matrix with the // microkernel's general stride IO case (unless the microkernel supports // both both row and column IO cases as well). // NOTE: Casting right-side trmm in terms of left side reduces the number // of macrokernels exercised to two (trmm_ll and trmm_lu). // If A is being multiplied from the right, transpose all operands // so that we can perform the computation as if A were being multiplied // from the left. if ( bli_is_right( side ) ) { bli_toggle_side( &side ); bli_obj_induce_trans( &a_local ); bli_obj_induce_trans( &b_local ); bli_obj_induce_trans( &c_local ); } #else // NOTE: This case computes right-side trmm natively with trmm_rl and // trmm_ru macrokernels. This code path always gives us the opportunity // to transpose the entire operation so that the effective storage format // of the output matrix matches the microkernel's output preference. // Thus, from a performance perspective, this case is preferred. // An optimization: If C is stored by rows and the micro-kernel prefers // contiguous columns, or if C is stored by columns and the micro-kernel // prefers contiguous rows, transpose the entire operation to allow the // micro-kernel to access elements of C in its preferred manner. // NOTE: We disable the optimization for 1x1 matrices since the concept // of row- vs. column storage breaks down. //if ( !bli_obj_is_1x1( &c_local ) ) // NOTE: This conditional should NOT // be enabled. See issue #342 comments. if ( bli_cntx_l3_vir_ukr_dislikes_storage_of( &c_local, BLIS_GEMM_UKR, cntx ) ) { bli_toggle_side( &side ); bli_obj_induce_trans( &a_local ); bli_obj_induce_trans( &b_local ); bli_obj_induce_trans( &c_local ); } // If A is being multiplied from the right, swap A and B so that // the matrix will actually be on the right. if ( bli_is_right( side ) ) { bli_obj_swap( &a_local, &b_local ); } #endif // Set the pack schemas within the objects. bli_l3_set_schemas( &a_local, &b_local, &c_local, cntx ); // Parse and interpret the contents of the rntm_t object to properly // set the ways of parallelism for each loop, and then make any // additional modifications necessary for the current operation. bli_rntm_set_ways_for_op ( BLIS_TRMM, side, bli_obj_length( &c_local ), bli_obj_width( &c_local ), bli_obj_width( &a_local ), rntm ); // Invoke the internal back-end. bli_l3_thread_decorator ( bli_l3_int, BLIS_TRMM, // operation family id alpha, &a_local, &b_local, &BLIS_ZERO, &c_local, cntx, rntm, cntl ); } blis-0.9.0/frame/3/trmm/bli_trmm_front.h000066400000000000000000000034711422157504600200650ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void bli_trmm_front ( side_t side, obj_t* alpha, obj_t* a, obj_t* b, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl ); blis-0.9.0/frame/3/trmm/bli_trmm_ll_ker_var2.c000066400000000000000000000313701422157504600211310ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define FUNCPTR_T gemm_fp typedef void (*FUNCPTR_T) ( doff_t diagoffa, pack_t schema_a, pack_t schema_b, dim_t m, dim_t n, dim_t k, void* alpha, void* a, inc_t cs_a, dim_t pd_a, inc_t ps_a, void* b, inc_t rs_b, dim_t pd_b, inc_t ps_b, void* beta, void* c, inc_t rs_c, inc_t cs_c, cntx_t* cntx, rntm_t* rntm, thrinfo_t* thread ); static FUNCPTR_T GENARRAY(ftypes,trmm_ll_ker_var2); void bli_trmm_ll_ker_var2 ( obj_t* a, obj_t* b, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ) { num_t dt_exec = bli_obj_exec_dt( c ); doff_t diagoffa = bli_obj_diag_offset( a ); pack_t schema_a = bli_obj_pack_schema( a ); pack_t schema_b = bli_obj_pack_schema( b ); dim_t m = bli_obj_length( c ); dim_t n = bli_obj_width( c ); dim_t k = bli_obj_width( a ); void* buf_a = bli_obj_buffer_at_off( a ); inc_t cs_a = bli_obj_col_stride( a ); dim_t pd_a = bli_obj_panel_dim( a ); inc_t ps_a = bli_obj_panel_stride( a ); void* buf_b = bli_obj_buffer_at_off( b ); inc_t rs_b = bli_obj_row_stride( b ); dim_t pd_b = bli_obj_panel_dim( b ); inc_t ps_b = bli_obj_panel_stride( b ); void* buf_c = bli_obj_buffer_at_off( c ); inc_t rs_c = bli_obj_row_stride( c ); inc_t cs_c = bli_obj_col_stride( c ); obj_t scalar_a; obj_t scalar_b; void* buf_alpha; void* buf_beta; FUNCPTR_T f; // Detach and multiply the scalars attached to A and B. bli_obj_scalar_detach( a, &scalar_a ); bli_obj_scalar_detach( b, &scalar_b ); bli_mulsc( &scalar_a, &scalar_b ); // Grab the addresses of the internal scalar buffers for the scalar // merged above and the scalar attached to C. buf_alpha = bli_obj_internal_scalar_buffer( &scalar_b ); buf_beta = bli_obj_internal_scalar_buffer( c ); // Index into the type combination array to extract the correct // function pointer. f = ftypes[dt_exec]; // Invoke the function. f( diagoffa, schema_a, schema_b, m, n, k, buf_alpha, buf_a, cs_a, pd_a, ps_a, buf_b, rs_b, pd_b, ps_b, buf_beta, buf_c, rs_c, cs_c, cntx, rntm, thread ); } #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ doff_t diagoffa, \ pack_t schema_a, \ pack_t schema_b, \ dim_t m, \ dim_t n, \ dim_t k, \ void* alpha, \ void* a, inc_t cs_a, dim_t pd_a, inc_t ps_a, \ void* b, inc_t rs_b, dim_t pd_b, inc_t ps_b, \ void* beta, \ void* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx, \ rntm_t* rntm, \ thrinfo_t* thread \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ /* Alias some constants to simpler names. */ \ const dim_t MR = pd_a; \ const dim_t NR = pd_b; \ const dim_t PACKMR = cs_a; \ const dim_t PACKNR = rs_b; \ \ /* Query the context for the micro-kernel address and cast it to its function pointer type. */ \ PASTECH(ch,gemm_ukr_ft) \ gemm_ukr = bli_cntx_get_l3_vir_ukr_dt( dt, BLIS_GEMM_UKR, cntx ); \ \ ctype* restrict one = PASTEMAC(ch,1); \ ctype* restrict a_cast = a; \ ctype* restrict b_cast = b; \ ctype* restrict c_cast = c; \ ctype* restrict alpha_cast = alpha; \ ctype* restrict beta_cast = beta; \ ctype* restrict b1; \ ctype* restrict c1; \ \ doff_t diagoffa_i; \ dim_t k_full; \ dim_t m_iter, m_left; \ dim_t n_iter, n_left; \ dim_t m_cur; \ dim_t n_cur; \ dim_t k_a1011; \ dim_t off_a1011; \ dim_t i, j; \ inc_t rstep_a; \ inc_t cstep_b; \ inc_t rstep_c, cstep_c; \ inc_t istep_a; \ inc_t istep_b; \ inc_t ps_a_cur; \ inc_t is_a_cur; \ auxinfo_t aux; \ \ /* Assumptions/assertions: rs_a == 1 cs_a == PACKMR pd_a == MR ps_a == stride to next micro-panel of A rs_b == PACKNR cs_b == 1 pd_b == NR ps_b == stride to next micro-panel of B rs_c == (no assumptions) cs_c == (no assumptions) */ \ \ /* Safety trap: Certain indexing within this macro-kernel does not work as intended if both MR and NR are odd. */ \ if ( ( bli_is_odd( PACKMR ) && bli_is_odd( NR ) ) || \ ( bli_is_odd( PACKNR ) && bli_is_odd( MR ) ) ) bli_abort(); \ \ /* If any dimension is zero, return immediately. */ \ if ( bli_zero_dim3( m, n, k ) ) return; \ \ /* Safeguard: If the current block of A is entirely above the diagonal, it is implicitly zero. So we do nothing. */ \ if ( bli_is_strictly_above_diag_n( diagoffa, m, k ) ) return; \ \ /* Compute k_full. For all trmm, k_full is simply k. This is needed because some parameter combinations of trmm reduce k to advance past zero regions in the triangular matrix, and when computing the imaginary stride of B (the non-triangular matrix), which is used by 4m1/3m1 implementations, we need this unreduced value of k. */ \ k_full = k; \ \ /* If there is a zero region above where the diagonal of A intersects the left edge of the block, adjust the pointer to C and treat this case as if the diagonal offset were zero. This skips over the region that was not packed. (Note we assume the diagonal offset is a multiple of MR; this assumption will hold as long as the cache blocksizes are each a multiple of MR and NR.) */ \ if ( diagoffa < 0 ) \ { \ i = -diagoffa; \ m = m - i; \ diagoffa = 0; \ c_cast = c_cast + (i )*rs_c; \ } \ \ /* Compute number of primary and leftover components of the m and n dimensions. */ \ n_iter = n / NR; \ n_left = n % NR; \ \ m_iter = m / MR; \ m_left = m % MR; \ \ if ( n_left ) ++n_iter; \ if ( m_left ) ++m_iter; \ \ /* Determine some increments used to step through A, B, and C. */ \ rstep_a = ps_a; \ \ cstep_b = ps_b; \ \ rstep_c = rs_c * MR; \ cstep_c = cs_c * NR; \ \ istep_a = PACKMR * k; \ istep_b = PACKNR * k_full; \ \ if ( bli_is_odd( istep_a ) ) istep_a += 1; \ if ( bli_is_odd( istep_b ) ) istep_b += 1; \ \ /* Save the pack schemas of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_schema_a( schema_a, &aux ); \ bli_auxinfo_set_schema_b( schema_b, &aux ); \ \ /* Save the imaginary stride of B to the auxinfo_t object. */ \ bli_auxinfo_set_is_b( istep_b, &aux ); \ \ /* The 'thread' argument points to the thrinfo_t node for the 2nd (jr) loop around the microkernel. Here we query the thrinfo_t node for the 1st (ir) loop around the microkernel. */ \ /*thrinfo_t* ir_thread = bli_thrinfo_sub_node( thread );*/ \ \ /* Query the number of threads and thread ids for each loop. */ \ dim_t jr_nt = bli_thread_n_way( thread ); \ dim_t jr_tid = bli_thread_work_id( thread ); \ /*dim_t ir_nt = bli_thread_n_way( ir_thread ); \ dim_t ir_tid = bli_thread_work_id( ir_thread );*/ \ \ dim_t jr_start, jr_end; \ /*dim_t ir_start, ir_end;*/ \ dim_t jr_inc; \ \ /* Determine the thread range and increment for the 2nd loop. NOTE: The definition of bli_thread_range_jrir() will depend on whether slab or round-robin partitioning was requested at configure-time. \ NOTE: Parallelism in the 1st loop is disabled for now. */ \ bli_thread_range_jrir( thread, n_iter, 1, FALSE, &jr_start, &jr_end, &jr_inc ); \ /*bli_thread_range_jrir_rr( caucus, m_iter, 1, FALSE, &ir_start, &ir_end, &ir_inc );*/ \ \ /* Loop over the n dimension (NR columns at a time). */ \ for ( j = jr_start; j < jr_end; j += jr_inc ) \ { \ ctype* restrict a1; \ ctype* restrict c11; \ ctype* restrict b2; \ \ b1 = b_cast + j * cstep_b; \ c1 = c_cast + j * cstep_c; \ \ n_cur = ( bli_is_not_edge_f( j, n_iter, n_left ) ? NR : n_left ); \ \ /* Initialize our next panel of B to be the current panel of B. */ \ b2 = b1; \ \ a1 = a_cast; \ c11 = c1; \ \ /* Loop over the m dimension (MR rows at a time). */ \ for ( i = 0; i < m_iter; ++i ) \ { \ diagoffa_i = diagoffa + ( doff_t )i*MR; \ \ m_cur = ( bli_is_not_edge_f( i, m_iter, m_left ) ? MR : m_left ); \ \ /* If the current panel of A intersects the diagonal, scale C by beta. If it is strictly below the diagonal, scale by one. This allows the current macro-kernel to work for both trmm and trmm3. */ \ if ( bli_intersects_diag_n( diagoffa_i, MR, k ) ) \ { \ ctype* restrict b1_i; \ ctype* restrict a2; \ \ /* Determine the offset to and length of the panel that was packed so we can index into the corresponding location in b1. */ \ off_a1011 = 0; \ k_a1011 = bli_min( diagoffa_i + MR, k ); \ \ /* Compute the panel stride for the current diagonal- intersecting micro-panel. */ \ is_a_cur = k_a1011 * PACKMR; \ is_a_cur += ( bli_is_odd( is_a_cur ) ? 1 : 0 ); \ ps_a_cur = is_a_cur; \ \ /* NOTE: ir loop parallelism disabled for now. */ \ /*if ( bli_trmm_my_iter( i, ir_thread ) ) {*/ \ \ b1_i = b1 + off_a1011 * PACKNR; \ \ /* Compute the addresses of the next panels of A and B. */ \ a2 = a1; \ if ( bli_is_last_iter_rr( i, m_iter, 0, 1 ) ) \ { \ a2 = a_cast; \ b2 = b1; \ if ( bli_is_last_iter( j, n_iter, jr_tid, jr_nt ) ) \ b2 = b_cast; \ } \ \ /* Save addresses of next panels of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_next_a( a2, &aux ); \ bli_auxinfo_set_next_b( b2, &aux ); \ \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ m_cur, \ n_cur, \ k_a1011, \ alpha_cast, \ a1, \ b1_i, \ beta_cast, \ c11, rs_c, cs_c, \ &aux, \ cntx \ ); \ /*}*/ \ \ a1 += ps_a_cur; \ } \ else if ( bli_is_strictly_below_diag_n( diagoffa_i, MR, k ) ) \ { \ /* NOTE: ir loop parallelism disabled for now. */ \ /*if ( bli_trmm_my_iter( i, ir_thread ) ) {*/ \ \ ctype* restrict a2; \ \ /* Compute the addresses of the next panels of A and B. */ \ a2 = a1; \ if ( bli_is_last_iter_rr( i, m_iter, 0, 1 ) ) \ { \ a2 = a_cast; \ b2 = b1; \ if ( bli_is_last_iter( j, n_iter, jr_tid, jr_nt ) ) \ b2 = b_cast; \ } \ \ /* Save addresses of next panels of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_next_a( a2, &aux ); \ bli_auxinfo_set_next_b( b2, &aux ); \ \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ m_cur, \ n_cur, \ k, \ alpha_cast, \ a1, \ b1, \ one, \ c11, rs_c, cs_c, \ &aux, \ cntx \ ); \ /*}*/ \ \ a1 += rstep_a; \ } \ \ c11 += rstep_c; \ } \ } \ /*PASTEMAC(ch,fprintm)( stdout, "trmm_ll_ker_var2: a1", MR, k_a1011, a1, 1, MR, "%4.1f", "" );*/ \ /*PASTEMAC(ch,fprintm)( stdout, "trmm_ll_ker_var2: b1", k_a1011, NR, b1_i, NR, 1, "%4.1f", "" );*/ \ } INSERT_GENTFUNC_BASIC0( trmm_ll_ker_var2 ) blis-0.9.0/frame/3/trmm/bli_trmm_lu_ker_var2.c000066400000000000000000000316261422157504600211460ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define FUNCPTR_T gemm_fp typedef void (*FUNCPTR_T) ( doff_t diagoffa, pack_t schema_a, pack_t schema_b, dim_t m, dim_t n, dim_t k, void* alpha, void* a, inc_t cs_a, dim_t pd_a, inc_t ps_a, void* b, inc_t rs_b, dim_t pd_b, inc_t ps_b, void* beta, void* c, inc_t rs_c, inc_t cs_c, cntx_t* cntx, rntm_t* rntm, thrinfo_t* thread ); static FUNCPTR_T GENARRAY(ftypes,trmm_lu_ker_var2); void bli_trmm_lu_ker_var2 ( obj_t* a, obj_t* b, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ) { num_t dt_exec = bli_obj_exec_dt( c ); doff_t diagoffa = bli_obj_diag_offset( a ); pack_t schema_a = bli_obj_pack_schema( a ); pack_t schema_b = bli_obj_pack_schema( b ); dim_t m = bli_obj_length( c ); dim_t n = bli_obj_width( c ); dim_t k = bli_obj_width( a ); void* buf_a = bli_obj_buffer_at_off( a ); inc_t cs_a = bli_obj_col_stride( a ); dim_t pd_a = bli_obj_panel_dim( a ); inc_t ps_a = bli_obj_panel_stride( a ); void* buf_b = bli_obj_buffer_at_off( b ); inc_t rs_b = bli_obj_row_stride( b ); dim_t pd_b = bli_obj_panel_dim( b ); inc_t ps_b = bli_obj_panel_stride( b ); void* buf_c = bli_obj_buffer_at_off( c ); inc_t rs_c = bli_obj_row_stride( c ); inc_t cs_c = bli_obj_col_stride( c ); obj_t scalar_a; obj_t scalar_b; void* buf_alpha; void* buf_beta; FUNCPTR_T f; // Detach and multiply the scalars attached to A and B. bli_obj_scalar_detach( a, &scalar_a ); bli_obj_scalar_detach( b, &scalar_b ); bli_mulsc( &scalar_a, &scalar_b ); // Grab the addresses of the internal scalar buffers for the scalar // merged above and the scalar attached to C. buf_alpha = bli_obj_internal_scalar_buffer( &scalar_b ); buf_beta = bli_obj_internal_scalar_buffer( c ); // Index into the type combination array to extract the correct // function pointer. f = ftypes[dt_exec]; // Invoke the function. f( diagoffa, schema_a, schema_b, m, n, k, buf_alpha, buf_a, cs_a, pd_a, ps_a, buf_b, rs_b, pd_b, ps_b, buf_beta, buf_c, rs_c, cs_c, cntx, rntm, thread ); } #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ doff_t diagoffa, \ pack_t schema_a, \ pack_t schema_b, \ dim_t m, \ dim_t n, \ dim_t k, \ void* alpha, \ void* a, inc_t cs_a, dim_t pd_a, inc_t ps_a, \ void* b, inc_t rs_b, dim_t pd_b, inc_t ps_b, \ void* beta, \ void* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx, \ rntm_t* rntm, \ thrinfo_t* thread \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ /* Alias some constants to simpler names. */ \ const dim_t MR = pd_a; \ const dim_t NR = pd_b; \ const dim_t PACKMR = cs_a; \ const dim_t PACKNR = rs_b; \ \ /* Query the context for the micro-kernel address and cast it to its function pointer type. */ \ PASTECH(ch,gemm_ukr_ft) \ gemm_ukr = bli_cntx_get_l3_vir_ukr_dt( dt, BLIS_GEMM_UKR, cntx ); \ \ ctype* restrict one = PASTEMAC(ch,1); \ ctype* restrict a_cast = a; \ ctype* restrict b_cast = b; \ ctype* restrict c_cast = c; \ ctype* restrict alpha_cast = alpha; \ ctype* restrict beta_cast = beta; \ ctype* restrict b1; \ ctype* restrict c1; \ \ doff_t diagoffa_i; \ dim_t k_full; \ dim_t m_iter, m_left; \ dim_t n_iter, n_left; \ dim_t m_cur; \ dim_t n_cur; \ dim_t k_a1112; \ dim_t off_a1112; \ dim_t i, j; \ inc_t rstep_a; \ inc_t cstep_b; \ inc_t rstep_c, cstep_c; \ inc_t istep_a; \ inc_t istep_b; \ inc_t ps_a_cur; \ inc_t is_a_cur; \ auxinfo_t aux; \ \ /* Assumptions/assertions: rs_a == 1 cs_a == PACKMR pd_a == MR ps_a == stride to next micro-panel of A rs_b == PACKNR cs_b == 1 pd_b == NR ps_b == stride to next micro-panel of B rs_c == (no assumptions) cs_c == (no assumptions) */ \ \ /* Safety trap: Certain indexing within this macro-kernel does not work as intended if both MR and NR are odd. */ \ if ( ( bli_is_odd( PACKMR ) && bli_is_odd( NR ) ) || \ ( bli_is_odd( PACKNR ) && bli_is_odd( MR ) ) ) bli_abort(); \ \ /* If any dimension is zero, return immediately. */ \ if ( bli_zero_dim3( m, n, k ) ) return; \ \ /* Safeguard: If the current block of A is entirely below the diagonal, it is implicitly zero. So we do nothing. */ \ if ( bli_is_strictly_below_diag_n( diagoffa, m, k ) ) return; \ \ /* Compute k_full. For all trmm, k_full is simply k. This is needed because some parameter combinations of trmm reduce k to advance past zero regions in the triangular matrix, and when computing the imaginary stride of B (the non-triangular matrix), which is used by 4m1/3m1 implementations, we need this unreduced value of k. */ \ k_full = k; \ \ /* If there is a zero region to the left of where the diagonal of A intersects the top edge of the block, adjust the pointer to B and treat this case as if the diagonal offset were zero. Note that we don't need to adjust the pointer to A since packm would have simply skipped over the region that was not stored. */ \ if ( diagoffa > 0 ) \ { \ i = diagoffa; \ k = k - i; \ diagoffa = 0; \ b_cast = b_cast + i * PACKNR; \ } \ \ /* If there is a zero region below where the diagonal of A intersects the right side of the block, shrink it to prevent "no-op" iterations from executing. */ \ if ( -diagoffa + k < m ) \ { \ m = -diagoffa + k; \ } \ \ /* Compute number of primary and leftover components of the m and n dimensions. */ \ n_iter = n / NR; \ n_left = n % NR; \ \ m_iter = m / MR; \ m_left = m % MR; \ \ if ( n_left ) ++n_iter; \ if ( m_left ) ++m_iter; \ \ /* Determine some increments used to step through A, B, and C. */ \ rstep_a = ps_a; \ \ cstep_b = ps_b; \ \ rstep_c = rs_c * MR; \ cstep_c = cs_c * NR; \ \ istep_a = PACKMR * k; \ istep_b = PACKNR * k_full; \ \ if ( bli_is_odd( istep_a ) ) istep_a += 1; \ if ( bli_is_odd( istep_b ) ) istep_b += 1; \ \ /* Save the pack schemas of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_schema_a( schema_a, &aux ); \ bli_auxinfo_set_schema_b( schema_b, &aux ); \ \ /* Save the imaginary stride of B to the auxinfo_t object. */ \ bli_auxinfo_set_is_b( istep_b, &aux ); \ \ /* The 'thread' argument points to the thrinfo_t node for the 2nd (jr) loop around the microkernel. Here we query the thrinfo_t node for the 1st (ir) loop around the microkernel. */ \ /*thrinfo_t* ir_thread = bli_thrinfo_sub_node( thread );*/ \ \ /* Query the number of threads and thread ids for each loop. */ \ dim_t jr_nt = bli_thread_n_way( thread ); \ dim_t jr_tid = bli_thread_work_id( thread ); \ /*dim_t ir_nt = bli_thread_n_way( ir_thread ); \ dim_t ir_tid = bli_thread_work_id( ir_thread );*/ \ \ dim_t jr_start, jr_end; \ /*dim_t ir_start, ir_end;*/ \ dim_t jr_inc; \ \ /* Determine the thread range and increment for the 2nd loop. NOTE: The definition of bli_thread_range_jrir() will depend on whether slab or round-robin partitioning was requested at configure-time. \ NOTE: Parallelism in the 1st loop is disabled for now. */ \ bli_thread_range_jrir( thread, n_iter, 1, FALSE, &jr_start, &jr_end, &jr_inc ); \ /*bli_thread_range_jrir_rr( caucus, m_iter, 1, FALSE, &ir_start, &ir_end, &ir_inc );*/ \ \ /* Loop over the n dimension (NR columns at a time). */ \ for ( j = jr_start; j < jr_end; j += jr_inc ) \ { \ ctype* restrict a1; \ ctype* restrict c11; \ ctype* restrict b2; \ \ b1 = b_cast + j * cstep_b; \ c1 = c_cast + j * cstep_c; \ \ n_cur = ( bli_is_not_edge_f( j, n_iter, n_left ) ? NR : n_left ); \ \ /* Initialize our next panel of B to be the current panel of B. */ \ b2 = b1; \ \ a1 = a_cast; \ c11 = c1; \ \ /* Loop over the m dimension (MR rows at a time). */ \ for ( i = 0; i < m_iter; ++i ) \ { \ diagoffa_i = diagoffa + ( doff_t )i*MR; \ \ m_cur = ( bli_is_not_edge_f( i, m_iter, m_left ) ? MR : m_left ); \ \ /* If the current panel of A intersects the diagonal, scale C by beta. If it is strictly above the diagonal, scale by one. This allows the current macro-kernel to work for both trmm and trmm3. */ \ if ( bli_intersects_diag_n( diagoffa_i, MR, k ) ) \ { \ ctype* restrict b1_i; \ ctype* restrict a2; \ \ /* Determine the offset to and length of the panel that was packed so we can index into the corresponding location in b1. */ \ off_a1112 = diagoffa_i; \ k_a1112 = k - off_a1112; \ \ /* Compute the panel stride for the current diagonal- intersecting micro-panel. */ \ is_a_cur = k_a1112 * PACKMR; \ is_a_cur += ( bli_is_odd( is_a_cur ) ? 1 : 0 ); \ ps_a_cur = is_a_cur; \ \ /* NOTE: ir loop parallelism disabled for now. */ \ /*if ( bli_trmm_my_iter( i, ir_thread ) ) {*/ \ \ b1_i = b1 + off_a1112 * PACKNR; \ \ /* Compute the addresses of the next panels of A and B. */ \ a2 = a1; \ if ( bli_is_last_iter_rr( i, m_iter, 0, 1 ) ) \ { \ a2 = a_cast; \ b2 = b1; \ if ( bli_is_last_iter( j, n_iter, jr_tid, jr_nt ) ) \ b2 = b_cast; \ } \ \ /* Save addresses of next panels of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_next_a( a2, &aux ); \ bli_auxinfo_set_next_b( b2, &aux ); \ \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ m_cur, \ n_cur, \ k_a1112, \ alpha_cast, \ a1, \ b1_i, \ beta_cast, \ c11, rs_c, cs_c, \ &aux, \ cntx \ ); \ /*}*/ \ \ a1 += ps_a_cur; \ } \ else if ( bli_is_strictly_above_diag_n( diagoffa_i, MR, k ) ) \ { \ /* NOTE: ir loop parallelism disabled for now. */ \ /*if ( bli_trmm_my_iter( i, ir_thread ) ) {*/ \ \ ctype* restrict a2; \ \ /* Compute the addresses of the next panels of A and B. */ \ a2 = a1; \ if ( bli_is_last_iter_rr( i, m_iter, 0, 1 ) ) \ { \ a2 = a_cast; \ b2 = b1; \ if ( bli_is_last_iter( j, n_iter, jr_tid, jr_nt ) ) \ b2 = b_cast; \ } \ \ /* Save addresses of next panels of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_next_a( a2, &aux ); \ bli_auxinfo_set_next_b( b2, &aux ); \ \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ m_cur, \ n_cur, \ k, \ alpha_cast, \ a1, \ b1, \ one, \ c11, rs_c, cs_c, \ &aux, \ cntx \ ); \ /*}*/ \ \ a1 += rstep_a; \ } \ \ c11 += rstep_c; \ } \ } \ \ /*PASTEMAC(ch,fprintm)( stdout, "trmm_lu_ker_var2: a1", MR, k_a1112, a1, 1, MR, "%4.1f", "" );*/ \ /*PASTEMAC(ch,fprintm)( stdout, "trmm_lu_ker_var2: b1", k_a1112, NR, b1_i, NR, 1, "%4.1f", "" );*/ \ } INSERT_GENTFUNC_BASIC0( trmm_lu_ker_var2 ) blis-0.9.0/frame/3/trmm/bli_trmm_rl_ker_var2.c000066400000000000000000000354621422157504600211450ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define FUNCPTR_T gemm_fp typedef void (*FUNCPTR_T) ( doff_t diagoffb, pack_t schema_a, pack_t schema_b, dim_t m, dim_t n, dim_t k, void* alpha, void* a, inc_t cs_a, dim_t pd_a, inc_t ps_a, void* b, inc_t rs_b, dim_t pd_b, inc_t ps_b, void* beta, void* c, inc_t rs_c, inc_t cs_c, cntx_t* cntx, rntm_t* rntm, thrinfo_t* thread ); static FUNCPTR_T GENARRAY(ftypes,trmm_rl_ker_var2); void bli_trmm_rl_ker_var2 ( obj_t* a, obj_t* b, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ) { num_t dt_exec = bli_obj_exec_dt( c ); doff_t diagoffb = bli_obj_diag_offset( b ); pack_t schema_a = bli_obj_pack_schema( a ); pack_t schema_b = bli_obj_pack_schema( b ); dim_t m = bli_obj_length( c ); dim_t n = bli_obj_width( c ); dim_t k = bli_obj_width( a ); void* buf_a = bli_obj_buffer_at_off( a ); inc_t cs_a = bli_obj_col_stride( a ); dim_t pd_a = bli_obj_panel_dim( a ); inc_t ps_a = bli_obj_panel_stride( a ); void* buf_b = bli_obj_buffer_at_off( b ); inc_t rs_b = bli_obj_row_stride( b ); dim_t pd_b = bli_obj_panel_dim( b ); inc_t ps_b = bli_obj_panel_stride( b ); void* buf_c = bli_obj_buffer_at_off( c ); inc_t rs_c = bli_obj_row_stride( c ); inc_t cs_c = bli_obj_col_stride( c ); obj_t scalar_a; obj_t scalar_b; void* buf_alpha; void* buf_beta; FUNCPTR_T f; // Detach and multiply the scalars attached to A and B. bli_obj_scalar_detach( a, &scalar_a ); bli_obj_scalar_detach( b, &scalar_b ); bli_mulsc( &scalar_a, &scalar_b ); // Grab the addresses of the internal scalar buffers for the scalar // merged above and the scalar attached to C. buf_alpha = bli_obj_internal_scalar_buffer( &scalar_b ); buf_beta = bli_obj_internal_scalar_buffer( c ); // Index into the type combination array to extract the correct // function pointer. f = ftypes[dt_exec]; // Invoke the function. f( diagoffb, schema_a, schema_b, m, n, k, buf_alpha, buf_a, cs_a, pd_a, ps_a, buf_b, rs_b, pd_b, ps_b, buf_beta, buf_c, rs_c, cs_c, cntx, rntm, thread ); } #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ doff_t diagoffb, \ pack_t schema_a, \ pack_t schema_b, \ dim_t m, \ dim_t n, \ dim_t k, \ void* alpha, \ void* a, inc_t cs_a, dim_t pd_a, inc_t ps_a, \ void* b, inc_t rs_b, dim_t pd_b, inc_t ps_b, \ void* beta, \ void* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx, \ rntm_t* rntm, \ thrinfo_t* thread \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ /* Alias some constants to simpler names. */ \ const dim_t MR = pd_a; \ const dim_t NR = pd_b; \ const dim_t PACKMR = cs_a; \ const dim_t PACKNR = rs_b; \ \ /* Query the context for the micro-kernel address and cast it to its function pointer type. */ \ PASTECH(ch,gemm_ukr_ft) \ gemm_ukr = bli_cntx_get_l3_vir_ukr_dt( dt, BLIS_GEMM_UKR, cntx ); \ \ ctype* restrict one = PASTEMAC(ch,1); \ ctype* restrict a_cast = a; \ ctype* restrict b_cast = b; \ ctype* restrict c_cast = c; \ ctype* restrict alpha_cast = alpha; \ ctype* restrict beta_cast = beta; \ ctype* restrict b1; \ ctype* restrict c1; \ \ doff_t diagoffb_j; \ dim_t k_full; \ dim_t m_iter, m_left; \ dim_t n_iter, n_left; \ dim_t m_cur; \ dim_t n_cur; \ dim_t k_b1121; \ dim_t off_b1121; \ dim_t i, j; \ inc_t rstep_a; \ inc_t cstep_b; \ inc_t rstep_c, cstep_c; \ inc_t istep_a; \ inc_t istep_b; \ inc_t ps_b_cur; \ inc_t is_b_cur; \ auxinfo_t aux; \ \ /* Assumptions/assertions: rs_a == 1 cs_a == PACKMR pd_a == MR ps_a == stride to next micro-panel of A rs_b == PACKNR cs_b == 1 pd_b == NR ps_b == stride to next micro-panel of B rs_c == (no assumptions) cs_c == (no assumptions) */ \ \ /* Safety trap: Certain indexing within this macro-kernel does not work as intended if both MR and NR are odd. */ \ if ( ( bli_is_odd( PACKMR ) && bli_is_odd( NR ) ) || \ ( bli_is_odd( PACKNR ) && bli_is_odd( MR ) ) ) bli_abort(); \ \ /* If any dimension is zero, return immediately. */ \ if ( bli_zero_dim3( m, n, k ) ) return; \ \ /* Safeguard: If the current panel of B is entirely above the diagonal, it is implicitly zero. So we do nothing. */ \ if ( bli_is_strictly_above_diag_n( diagoffb, k, n ) ) return; \ \ /* Compute k_full. For all trmm, k_full is simply k. This is needed because some parameter combinations of trmm reduce k to advance past zero regions in the triangular matrix, and when computing the imaginary stride of A (the non-triangular matrix), which is used by 4m1/3m1 implementations, we need this unreduced value of k. */ \ k_full = k; \ \ /* If there is a zero region above where the diagonal of B intersects the left edge of the panel, adjust the pointer to A and treat this case as if the diagonal offset were zero. Note that we don't need to adjust the pointer to B since packm would have simply skipped over the region that was not stored. */ \ if ( diagoffb < 0 ) \ { \ j = -diagoffb; \ k = k - j; \ diagoffb = 0; \ a_cast = a_cast + j * PACKMR; \ } \ \ /* If there is a zero region to the right of where the diagonal of B intersects the bottom of the panel, shrink it to prevent "no-op" iterations from executing. */ \ if ( diagoffb + k < n ) \ { \ n = diagoffb + k; \ } \ \ /* Compute number of primary and leftover components of the m and n dimensions. */ \ n_iter = n / NR; \ n_left = n % NR; \ \ m_iter = m / MR; \ m_left = m % MR; \ \ if ( n_left ) ++n_iter; \ if ( m_left ) ++m_iter; \ \ /* Determine some increments used to step through A, B, and C. */ \ rstep_a = ps_a; \ \ cstep_b = ps_b; \ \ rstep_c = rs_c * MR; \ cstep_c = cs_c * NR; \ \ istep_a = PACKMR * k_full; \ istep_b = PACKNR * k; \ \ if ( bli_is_odd( istep_a ) ) istep_a += 1; \ if ( bli_is_odd( istep_b ) ) istep_b += 1; \ \ /* Save the pack schemas of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_schema_a( schema_a, &aux ); \ bli_auxinfo_set_schema_b( schema_b, &aux ); \ \ /* Save the imaginary stride of A to the auxinfo_t object. */ \ bli_auxinfo_set_is_a( istep_a, &aux ); \ \ thrinfo_t* caucus = bli_thrinfo_sub_node( thread ); \ \ dim_t jr_nt = bli_thread_n_way( thread ); \ dim_t jr_tid = bli_thread_work_id( thread ); \ dim_t ir_nt = bli_thread_n_way( caucus ); \ dim_t ir_tid = bli_thread_work_id( caucus ); \ \ dim_t jr_start, jr_end; \ dim_t ir_start, ir_end; \ dim_t jr_inc, ir_inc; \ \ /* Note that we partition the 2nd loop into two regions: the rectangular part of B, and the triangular portion. */ \ dim_t n_iter_rct; \ dim_t n_iter_tri; \ \ if ( bli_is_strictly_below_diag_n( diagoffb, m, n ) ) \ { \ /* If the entire panel of B does not intersect the diagonal, there is no triangular region, and therefore we can skip the second set of loops. */ \ n_iter_rct = n_iter; \ n_iter_tri = 0; \ } \ else \ { \ /* If the panel of B does intersect the diagonal, compute the number of iterations in the rectangular region by dividing NR into the diagonal offset. (There should never be any remainder in this division.) The number of iterations in the triangular (or trapezoidal) region is computed as the remaining number of iterations in the n dimension. */ \ n_iter_rct = diagoffb / NR; \ n_iter_tri = n_iter - n_iter_rct; \ } \ \ /* Determine the thread range and increment for the 2nd and 1st loops for the initial rectangular region of B (if it exists). NOTE: The definition of bli_thread_range_jrir() will depend on whether slab or round-robin partitioning was requested at configure-time. \ NOTE: Parallelism in the 1st loop is disabled for now. */ \ bli_thread_range_jrir( thread, n_iter_rct, 1, FALSE, &jr_start, &jr_end, &jr_inc ); \ bli_thread_range_jrir( caucus, m_iter, 1, FALSE, &ir_start, &ir_end, &ir_inc ); \ \ /* Loop over the n dimension (NR columns at a time). */ \ for ( j = jr_start; j < jr_end; j += jr_inc ) \ { \ ctype* restrict a1; \ ctype* restrict c11; \ ctype* restrict b2; \ \ b1 = b_cast + j * cstep_b; \ c1 = c_cast + j * cstep_c; \ \ n_cur = ( bli_is_not_edge_f( j, n_iter, n_left ) ? NR : n_left ); \ \ /* Initialize our next panel of B to be the current panel of B. */ \ b2 = b1; \ \ { \ /* Loop over the m dimension (MR rows at a time). */ \ for ( i = ir_start; i < ir_end; i += ir_inc ) \ { \ ctype* restrict a2; \ \ a1 = a_cast + i * rstep_a; \ c11 = c1 + i * rstep_c; \ \ m_cur = ( bli_is_not_edge_f( i, m_iter, m_left ) ? MR : m_left ); \ \ /* Compute the addresses of the next panels of A and B. */ \ a2 = bli_trmm_get_next_a_upanel( a1, rstep_a, ir_inc ); \ if ( bli_is_last_iter( i, m_iter, ir_tid, ir_nt ) ) \ { \ a2 = a_cast; \ b2 = bli_trmm_get_next_b_upanel( b1, cstep_b, jr_inc ); \ if ( bli_is_last_iter( j, n_iter, jr_tid, jr_nt ) ) \ b2 = b_cast; \ } \ \ /* Save addresses of next panels of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_next_a( a2, &aux ); \ bli_auxinfo_set_next_b( b2, &aux ); \ \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ m_cur, \ n_cur, \ k, \ alpha_cast, \ a1, \ b1, \ one, \ c11, rs_c, cs_c, \ &aux, \ cntx \ ); \ } \ } \ } \ \ /* If there is no triangular region, then we're done. */ \ if ( n_iter_tri == 0 ) return; \ \ /* Use round-robin assignment of micropanels to threads in the 2nd and 1st loops for the remaining triangular region of B (if it exists). NOTE: We don't need to call bli_thread_range_jrir_rr() here since we employ a hack that calls for each thread to execute every iteration of the jr and ir loops but skip all but the pointer increment for iterations that are not assigned to it. */ \ \ /* Advance the starting b1 and c1 pointers to the positions corresponding to the start of the triangular region of B. */ \ jr_start = n_iter_rct; \ b1 = b_cast + jr_start * cstep_b; \ c1 = c_cast + jr_start * cstep_c; \ \ /* Loop over the n dimension (NR columns at a time). */ \ for ( j = jr_start; j < n_iter; ++j ) \ { \ ctype* restrict a1; \ ctype* restrict c11; \ ctype* restrict b2; \ \ diagoffb_j = diagoffb - ( doff_t )j*NR; \ \ /* Determine the offset to the beginning of the panel that was packed so we can index into the corresponding location in A. Then compute the length of that panel. */ \ off_b1121 = bli_max( -diagoffb_j, 0 ); \ k_b1121 = k - off_b1121; \ \ a1 = a_cast; \ c11 = c1; \ \ n_cur = ( bli_is_not_edge_f( j, n_iter, n_left ) ? NR : n_left ); \ \ /* Initialize our next panel of B to be the current panel of B. */ \ b2 = b1; \ \ /* If the current panel of B intersects the diagonal, scale C by beta. If it is strictly below the diagonal, scale by one. This allows the current macro-kernel to work for both trmm and trmm3. */ \ { \ /* Compute the panel stride for the current diagonal- intersecting micro-panel. */ \ is_b_cur = k_b1121 * PACKNR; \ is_b_cur += ( bli_is_odd( is_b_cur ) ? 1 : 0 ); \ ps_b_cur = is_b_cur; \ \ if ( bli_trmm_my_iter_rr( j, thread ) ) { \ \ /* Loop over the m dimension (MR rows at a time). */ \ for ( i = 0; i < m_iter; ++i ) \ { \ if ( bli_trmm_my_iter_rr( i, caucus ) ) { \ \ ctype* restrict a1_i; \ ctype* restrict a2; \ \ m_cur = ( bli_is_not_edge_f( i, m_iter, m_left ) ? MR : m_left ); \ \ a1_i = a1 + off_b1121 * PACKMR; \ \ /* Compute the addresses of the next panels of A and B. */ \ a2 = a1; \ if ( bli_is_last_iter_rr( i, m_iter, 0, 1 ) ) \ { \ a2 = a_cast; \ b2 = b1; \ if ( bli_is_last_iter_rr( j, n_iter, jr_tid, jr_nt ) ) \ b2 = b_cast; \ } \ \ /* Save addresses of next panels of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_next_a( a2, &aux ); \ bli_auxinfo_set_next_b( b2, &aux ); \ \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ m_cur, \ n_cur, \ k_b1121, \ alpha_cast, \ a1_i, \ b1, \ beta_cast, \ c11, rs_c, cs_c, \ &aux, \ cntx \ ); \ } \ \ a1 += rstep_a; \ c11 += rstep_c; \ } \ } \ \ b1 += ps_b_cur; \ } \ \ c1 += cstep_c; \ } \ \ /*PASTEMAC(ch,fprintm)( stdout, "trmm_rl_ker_var2: a1", MR, k_b1121, a1, 1, MR, "%4.1f", "" );*/ \ /*PASTEMAC(ch,fprintm)( stdout, "trmm_rl_ker_var2: b1", k_b1121, NR, b1_i, NR, 1, "%4.1f", "" );*/ \ } INSERT_GENTFUNC_BASIC0( trmm_rl_ker_var2 ) blis-0.9.0/frame/3/trmm/bli_trmm_ru_ker_var2.c000066400000000000000000000373201422157504600211510ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define FUNCPTR_T gemm_fp typedef void (*FUNCPTR_T) ( doff_t diagoffb, pack_t schema_a, pack_t schema_b, dim_t m, dim_t n, dim_t k, void* alpha, void* a, inc_t cs_a, dim_t pd_a, inc_t ps_a, void* b, inc_t rs_b, dim_t pd_b, inc_t ps_b, void* beta, void* c, inc_t rs_c, inc_t cs_c, cntx_t* cntx, rntm_t* rntm, thrinfo_t* thread ); static FUNCPTR_T GENARRAY(ftypes,trmm_ru_ker_var2); void bli_trmm_ru_ker_var2 ( obj_t* a, obj_t* b, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ) { num_t dt_exec = bli_obj_exec_dt( c ); doff_t diagoffb = bli_obj_diag_offset( b ); pack_t schema_a = bli_obj_pack_schema( a ); pack_t schema_b = bli_obj_pack_schema( b ); dim_t m = bli_obj_length( c ); dim_t n = bli_obj_width( c ); dim_t k = bli_obj_width( a ); void* buf_a = bli_obj_buffer_at_off( a ); inc_t cs_a = bli_obj_col_stride( a ); dim_t pd_a = bli_obj_panel_dim( a ); inc_t ps_a = bli_obj_panel_stride( a ); void* buf_b = bli_obj_buffer_at_off( b ); inc_t rs_b = bli_obj_row_stride( b ); dim_t pd_b = bli_obj_panel_dim( b ); inc_t ps_b = bli_obj_panel_stride( b ); void* buf_c = bli_obj_buffer_at_off( c ); inc_t rs_c = bli_obj_row_stride( c ); inc_t cs_c = bli_obj_col_stride( c ); obj_t scalar_a; obj_t scalar_b; void* buf_alpha; void* buf_beta; FUNCPTR_T f; // Detach and multiply the scalars attached to A and B. bli_obj_scalar_detach( a, &scalar_a ); bli_obj_scalar_detach( b, &scalar_b ); bli_mulsc( &scalar_a, &scalar_b ); // Grab the addresses of the internal scalar buffers for the scalar // merged above and the scalar attached to C. buf_alpha = bli_obj_internal_scalar_buffer( &scalar_b ); buf_beta = bli_obj_internal_scalar_buffer( c ); // Index into the type combination array to extract the correct // function pointer. f = ftypes[dt_exec]; // Invoke the function. f( diagoffb, schema_a, schema_b, m, n, k, buf_alpha, buf_a, cs_a, pd_a, ps_a, buf_b, rs_b, pd_b, ps_b, buf_beta, buf_c, rs_c, cs_c, cntx, rntm, thread ); } #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ doff_t diagoffb, \ pack_t schema_a, \ pack_t schema_b, \ dim_t m, \ dim_t n, \ dim_t k, \ void* alpha, \ void* a, inc_t cs_a, dim_t pd_a, inc_t ps_a, \ void* b, inc_t rs_b, dim_t pd_b, inc_t ps_b, \ void* beta, \ void* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx, \ rntm_t* rntm, \ thrinfo_t* thread \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ /* Alias some constants to simpler names. */ \ const dim_t MR = pd_a; \ const dim_t NR = pd_b; \ const dim_t PACKMR = cs_a; \ const dim_t PACKNR = rs_b; \ \ /* Query the context for the micro-kernel address and cast it to its function pointer type. */ \ PASTECH(ch,gemm_ukr_ft) \ gemm_ukr = bli_cntx_get_l3_vir_ukr_dt( dt, BLIS_GEMM_UKR, cntx ); \ \ ctype* restrict one = PASTEMAC(ch,1); \ ctype* restrict a_cast = a; \ ctype* restrict b_cast = b; \ ctype* restrict c_cast = c; \ ctype* restrict alpha_cast = alpha; \ ctype* restrict beta_cast = beta; \ ctype* restrict b1; \ ctype* restrict c1; \ \ doff_t diagoffb_j; \ dim_t k_full; \ dim_t m_iter, m_left; \ dim_t n_iter, n_left; \ dim_t m_cur; \ dim_t n_cur; \ dim_t k_b0111; \ dim_t off_b0111; \ dim_t i, j, jb0; \ inc_t rstep_a; \ inc_t cstep_b; \ inc_t rstep_c, cstep_c; \ inc_t istep_a; \ inc_t istep_b; \ inc_t ps_b_cur; \ inc_t is_b_cur; \ auxinfo_t aux; \ \ /* Assumptions/assertions: rs_a == 1 cs_a == PACKMR pd_a == MR ps_a == stride to next micro-panel of A rs_b == PACKNR cs_b == 1 pd_b == NR ps_b == stride to next micro-panel of B rs_c == (no assumptions) cs_c == (no assumptions) */ \ \ /* Safety trap: Certain indexing within this macro-kernel does not work as intended if both MR and NR are odd. */ \ if ( ( bli_is_odd( PACKMR ) && bli_is_odd( NR ) ) || \ ( bli_is_odd( PACKNR ) && bli_is_odd( MR ) ) ) bli_abort(); \ \ /* If any dimension is zero, return immediately. */ \ if ( bli_zero_dim3( m, n, k ) ) return; \ \ /* Safeguard: If the current panel of B is entirely below its diagonal, it is implicitly zero. So we do nothing. */ \ if ( bli_is_strictly_below_diag_n( diagoffb, k, n ) ) return; \ \ /* Compute k_full. For all trmm, k_full is simply k. This is needed because some parameter combinations of trmm reduce k to advance past zero regions in the triangular matrix, and when computing the imaginary stride of A (the non-triangular matrix), which is used by 4m1/3m1 implementations, we need this unreduced value of k. */ \ k_full = k; \ \ /* If there is a zero region to the left of where the diagonal of B intersects the top edge of the panel, adjust the pointer to C and treat this case as if the diagonal offset were zero. This skips over the region that was not packed. (Note we assume the diagonal offset is a multiple of MR; this assumption will hold as long as the cache blocksizes are each a multiple of MR and NR.) */ \ if ( diagoffb > 0 ) \ { \ j = diagoffb; \ n = n - j; \ diagoffb = 0; \ c_cast = c_cast + (j )*cs_c; \ } \ \ /* If there is a zero region below where the diagonal of B intersects the right side of the block, shrink it to prevent "no-op" iterations from executing. */ \ if ( -diagoffb + n < k ) \ { \ k = -diagoffb + n; \ } \ \ /* Compute number of primary and leftover components of the m and n dimensions. */ \ n_iter = n / NR; \ n_left = n % NR; \ \ m_iter = m / MR; \ m_left = m % MR; \ \ if ( n_left ) ++n_iter; \ if ( m_left ) ++m_iter; \ \ /* Determine some increments used to step through A, B, and C. */ \ rstep_a = ps_a; \ \ cstep_b = ps_b; \ \ rstep_c = rs_c * MR; \ cstep_c = cs_c * NR; \ \ istep_a = PACKMR * k_full; \ istep_b = PACKNR * k; \ \ if ( bli_is_odd( istep_a ) ) istep_a += 1; \ if ( bli_is_odd( istep_b ) ) istep_b += 1; \ \ /* Save the pack schemas of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_schema_a( schema_a, &aux ); \ bli_auxinfo_set_schema_b( schema_b, &aux ); \ \ /* Save the imaginary stride of A to the auxinfo_t object. */ \ bli_auxinfo_set_is_a( istep_a, &aux ); \ \ /* The 'thread' argument points to the thrinfo_t node for the 2nd (jr) loop around the microkernel. Here we query the thrinfo_t node for the 1st (ir) loop around the microkernel. */ \ thrinfo_t* caucus = bli_thrinfo_sub_node( thread ); \ \ /* Query the number of threads and thread ids for each loop. */ \ dim_t jr_nt = bli_thread_n_way( thread ); \ dim_t jr_tid = bli_thread_work_id( thread ); \ dim_t ir_nt = bli_thread_n_way( caucus ); \ dim_t ir_tid = bli_thread_work_id( caucus ); \ \ dim_t jr_start, jr_end; \ dim_t ir_start, ir_end; \ dim_t jr_inc, ir_inc; \ \ /* Note that we partition the 2nd loop into two regions: the triangular part of C, and the rectangular portion. */ \ dim_t n_iter_tri; \ dim_t n_iter_rct; \ \ if ( bli_is_strictly_above_diag_n( diagoffb, k, n ) ) \ { \ /* If the entire panel of B does not intersect the diagonal, there is no triangular region, and therefore we can skip the first set of loops. */ \ n_iter_tri = 0; \ n_iter_rct = n_iter; \ } \ else \ { \ /* If the panel of B does intersect the diagonal, compute the number of iterations in the triangular (or trapezoidal) region by dividing NR into the number of rows in B. (There should never be any remainder in this division.) The number of iterations in the rectangular region is computed as the remaining number of iterations in the n dimension. */ \ n_iter_tri = ( k + diagoffb ) / NR + ( ( k + diagoffb ) % NR ? 1 : 0 ); \ n_iter_rct = n_iter - n_iter_tri; \ } \ \ /* Use round-robin assignment of micropanels to threads in the 2nd and 1st loops for the initial triangular region of B (if it exists). NOTE: We don't need to call bli_thread_range_jrir_rr() here since we employ a hack that calls for each thread to execute every iteration of the jr and ir loops but skip all but the pointer increment for iterations that are not assigned to it. */ \ \ b1 = b_cast; \ c1 = c_cast; \ \ /* Loop over the n dimension (NR columns at a time). */ \ for ( j = 0; j < n_iter_tri; ++j ) \ { \ ctype* restrict a1; \ ctype* restrict c11; \ ctype* restrict b2; \ \ diagoffb_j = diagoffb - ( doff_t )j*NR; \ \ /* Determine the offset to and length of the panel that was packed so we can index into the corresponding location in A. */ \ off_b0111 = 0; \ k_b0111 = bli_min( k, -diagoffb_j + NR ); \ \ a1 = a_cast; \ c11 = c1; \ \ n_cur = ( bli_is_not_edge_f( j, n_iter, n_left ) ? NR : n_left ); \ \ /* Initialize our next panel of B to be the current panel of B. */ \ b2 = b1; \ \ /* If the current panel of B intersects the diagonal, scale C by beta. If it is strictly below the diagonal, scale by one. This allows the current macro-kernel to work for both trmm and trmm3. */ \ { \ /* Compute the panel stride for the current diagonal- intersecting micro-panel. */ \ is_b_cur = k_b0111 * PACKNR; \ is_b_cur += ( bli_is_odd( is_b_cur ) ? 1 : 0 ); \ ps_b_cur = is_b_cur; \ \ if ( bli_trmm_my_iter_rr( j, thread ) ) { \ \ /* Loop over the m dimension (MR rows at a time). */ \ for ( i = 0; i < m_iter; ++i ) \ { \ if ( bli_trmm_my_iter_rr( i, caucus ) ) { \ \ ctype* restrict a1_i; \ ctype* restrict a2; \ \ m_cur = ( bli_is_not_edge_f( i, m_iter, m_left ) ? MR : m_left ); \ \ a1_i = a1 + off_b0111 * PACKMR; \ \ /* Compute the addresses of the next panels of A and B. */ \ a2 = a1; \ if ( bli_is_last_iter_rr( i, m_iter, 0, 1 ) ) \ { \ a2 = a_cast; \ b2 = b1; \ if ( bli_is_last_iter_rr( j, n_iter, jr_tid, jr_nt ) ) \ b2 = b_cast; \ } \ \ /* Save addresses of next panels of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_next_a( a2, &aux ); \ bli_auxinfo_set_next_b( b2, &aux ); \ \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ m_cur, \ n_cur, \ k_b0111, \ alpha_cast, \ a1_i, \ b1, \ beta_cast, \ c11, rs_c, cs_c, \ &aux, \ cntx \ ); \ } \ \ a1 += rstep_a; \ c11 += rstep_c; \ } \ } \ \ b1 += ps_b_cur; \ } \ \ c1 += cstep_c; \ } \ \ /* If there is no rectangular region, then we're done. */ \ if ( n_iter_rct == 0 ) return; \ \ /* Determine the thread range and increment for the 2nd and 1st loops for the remaining rectangular region of B. NOTE: The definition of bli_thread_range_jrir() will depend on whether slab or round-robin partitioning was requested at configure-time. \ NOTE: Parallelism in the 1st loop is disabled for now. */ \ bli_thread_range_jrir( thread, n_iter_rct, 1, FALSE, &jr_start, &jr_end, &jr_inc ); \ bli_thread_range_jrir( caucus, m_iter, 1, FALSE, &ir_start, &ir_end, &ir_inc ); \ \ /* Advance the start and end iteration offsets for the rectangular region by the number of iterations used for the triangular region. */ \ jr_start += n_iter_tri; \ jr_end += n_iter_tri; \ jb0 = n_iter_tri; \ \ /* Save the resulting value of b1 from the previous loop since it represents the starting point for the rectangular region. */ \ b_cast = b1; \ \ /* Loop over the n dimension (NR columns at a time). */ \ for ( j = jr_start; j < jr_end; j += jr_inc ) \ { \ ctype* restrict a1; \ ctype* restrict c11; \ ctype* restrict b2; \ \ /* NOTE: We must index through b_cast differently since it contains the starting address of the rectangular region (which is already n_iter_tri logical iterations through B). */ \ b1 = b_cast + (j-jb0) * cstep_b; \ c1 = c_cast + j * cstep_c; \ \ n_cur = ( bli_is_not_edge_f( j, n_iter, n_left ) ? NR : n_left ); \ \ /* Initialize our next panel of B to be the current panel of B. */ \ b2 = b1; \ \ /* If the current panel of B intersects the diagonal, scale C by beta. If it is strictly below the diagonal, scale by one. This allows the current macro-kernel to work for both trmm and trmm3. */ \ { \ /* Loop over the m dimension (MR rows at a time). */ \ for ( i = ir_start; i < ir_end; i += ir_inc ) \ { \ ctype* restrict a2; \ \ a1 = a_cast + i * rstep_a; \ c11 = c1 + i * rstep_c; \ \ m_cur = ( bli_is_not_edge_f( i, m_iter, m_left ) ? MR : m_left ); \ \ /* Compute the addresses of the next panels of A and B. */ \ a2 = bli_trmm_get_next_a_upanel( a1, rstep_a, ir_inc ); \ if ( bli_is_last_iter( i, m_iter, ir_tid, ir_nt ) ) \ { \ a2 = a_cast; \ b2 = bli_trmm_get_next_b_upanel( b1, cstep_b, jr_inc ); \ if ( bli_is_last_iter( j, n_iter, jr_tid, jr_nt ) ) \ b2 = b_cast; \ } \ \ /* Save addresses of next panels of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_next_a( a2, &aux ); \ bli_auxinfo_set_next_b( b2, &aux ); \ \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ m_cur, \ n_cur, \ k, \ alpha_cast, \ a1, \ b1, \ one, \ c11, rs_c, cs_c, \ &aux, \ cntx \ ); \ } \ } \ } \ \ \ \ /*PASTEMAC(ch,fprintm)( stdout, "trmm_ru_ker_var2: a1", MR, k_b0111, a1, 1, MR, "%4.1f", "" );*/ \ /*PASTEMAC(ch,fprintm)( stdout, "trmm_ru_ker_var2: b1", k_b0111, NR, b1_i, NR, 1, "%4.1f", "" );*/ \ } INSERT_GENTFUNC_BASIC0( trmm_ru_ker_var2 ) blis-0.9.0/frame/3/trmm/bli_trmm_var.h000066400000000000000000000057561422157504600175350ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype object-based interfaces. // #undef GENPROT #define GENPROT( opname ) \ \ void PASTEMAC0(opname) \ ( \ obj_t* a, \ obj_t* b, \ obj_t* c, \ cntx_t* cntx, \ rntm_t* rntm, \ cntl_t* cntl, \ thrinfo_t* thread \ ); //GENPROT( trmm_blk_var1 ) //GENPROT( trmm_blk_var2 ) //GENPROT( trmm_blk_var3 ) GENPROT( trmm_xx_ker_var2 ) GENPROT( trmm_ll_ker_var2 ) GENPROT( trmm_lu_ker_var2 ) GENPROT( trmm_rl_ker_var2 ) GENPROT( trmm_ru_ker_var2 ) // // Prototype BLAS-like interfaces with void pointer operands. // #undef GENTPROT #define GENTPROT( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ doff_t diagoff, \ pack_t schema_a, \ pack_t schema_b, \ dim_t m, \ dim_t n, \ dim_t k, \ void* alpha, \ void* a, inc_t cs_a, \ dim_t pd_a, inc_t ps_a, \ void* b, inc_t rs_b, \ dim_t pd_b, inc_t ps_b, \ void* beta, \ void* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx, \ rntm_t* rntm, \ thrinfo_t* thread \ ); INSERT_GENTPROT_BASIC0( trmm_ll_ker_var2 ) INSERT_GENTPROT_BASIC0( trmm_lu_ker_var2 ) INSERT_GENTPROT_BASIC0( trmm_rl_ker_var2 ) INSERT_GENTPROT_BASIC0( trmm_ru_ker_var2 ) blis-0.9.0/frame/3/trmm/bli_trmm_xx_ker_var2.c000066400000000000000000000054231422157504600211610ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" static l3_var_oft vars[2][2] = { { bli_trmm_ll_ker_var2, bli_trmm_lu_ker_var2 }, { bli_trmm_rl_ker_var2, bli_trmm_ru_ker_var2 } }; void bli_trmm_xx_ker_var2 ( obj_t* a, obj_t* b, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ) { dim_t side; dim_t uplo; l3_var_oft f; // Set two bools: one based on the implied side parameter (the structure // of the root object) and one based on the uplo field of the triangular // matrix's root object (whether that is matrix A or matrix B). if ( bli_obj_root_is_triangular( a ) ) { side = 0; if ( bli_obj_root_is_lower( a ) ) uplo = 0; else uplo = 1; } else // if ( bli_obj_root_is_triangular( b ) ) { side = 1; if ( bli_obj_root_is_lower( b ) ) uplo = 0; else uplo = 1; } // Index into the variant array to extract the correct function pointer. f = vars[side][uplo]; // Call the macrokernel. f ( a, b, c, cntx, rntm, cntl, thread ); } blis-0.9.0/frame/3/trmm/other/000077500000000000000000000000001422157504600160135ustar00rootroot00000000000000blis-0.9.0/frame/3/trmm/other/bli_trmm_ll_ker_var2.c000066400000000000000000000372031422157504600222530ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define FUNCPTR_T gemm_fp typedef void (*FUNCPTR_T) ( doff_t diagoffa, pack_t schema_a, pack_t schema_b, dim_t m, dim_t n, dim_t k, void* alpha, void* a, inc_t cs_a, dim_t pd_a, inc_t ps_a, void* b, inc_t rs_b, dim_t pd_b, inc_t ps_b, void* beta, void* c, inc_t rs_c, inc_t cs_c, cntx_t* cntx, rntm_t* rntm, thrinfo_t* thread ); static FUNCPTR_T GENARRAY(ftypes,trmm_ll_ker_var2); void bli_trmm_ll_ker_var2 ( obj_t* a, obj_t* b, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ) { num_t dt_exec = bli_obj_exec_dt( c ); doff_t diagoffa = bli_obj_diag_offset( a ); pack_t schema_a = bli_obj_pack_schema( a ); pack_t schema_b = bli_obj_pack_schema( b ); dim_t m = bli_obj_length( c ); dim_t n = bli_obj_width( c ); dim_t k = bli_obj_width( a ); void* buf_a = bli_obj_buffer_at_off( a ); inc_t cs_a = bli_obj_col_stride( a ); dim_t pd_a = bli_obj_panel_dim( a ); inc_t ps_a = bli_obj_panel_stride( a ); void* buf_b = bli_obj_buffer_at_off( b ); inc_t rs_b = bli_obj_row_stride( b ); dim_t pd_b = bli_obj_panel_dim( b ); inc_t ps_b = bli_obj_panel_stride( b ); void* buf_c = bli_obj_buffer_at_off( c ); inc_t rs_c = bli_obj_row_stride( c ); inc_t cs_c = bli_obj_col_stride( c ); obj_t scalar_a; obj_t scalar_b; void* buf_alpha; void* buf_beta; FUNCPTR_T f; // Detach and multiply the scalars attached to A and B. bli_obj_scalar_detach( a, &scalar_a ); bli_obj_scalar_detach( b, &scalar_b ); bli_mulsc( &scalar_a, &scalar_b ); // Grab the addresses of the internal scalar buffers for the scalar // merged above and the scalar attached to C. buf_alpha = bli_obj_internal_scalar_buffer( &scalar_b ); buf_beta = bli_obj_internal_scalar_buffer( c ); // Index into the type combination array to extract the correct // function pointer. f = ftypes[dt_exec]; // Invoke the function. f( diagoffa, schema_a, schema_b, m, n, k, buf_alpha, buf_a, cs_a, pd_a, ps_a, buf_b, rs_b, pd_b, ps_b, buf_beta, buf_c, rs_c, cs_c, cntx, rntm, thread ); } #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ doff_t diagoffa, \ pack_t schema_a, \ pack_t schema_b, \ dim_t m, \ dim_t n, \ dim_t k, \ void* alpha, \ void* a, inc_t cs_a, dim_t pd_a, inc_t ps_a, \ void* b, inc_t rs_b, dim_t pd_b, inc_t ps_b, \ void* beta, \ void* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx, \ rntm_t* rntm, \ thrinfo_t* jr_thread \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ /* Alias some constants to simpler names. */ \ const dim_t MR = pd_a; \ const dim_t NR = pd_b; \ const dim_t PACKMR = cs_a; \ const dim_t PACKNR = rs_b; \ \ /* Query the context for the micro-kernel address and cast it to its function pointer type. */ \ PASTECH(ch,gemm_ukr_ft) \ gemm_ukr = bli_cntx_get_l3_vir_ukr_dt( dt, BLIS_GEMM_UKR, cntx ); \ \ /* Temporary C buffer for edge cases. Note that the strides of this temporary buffer are set so that they match the storage of the original C matrix. For example, if C is column-stored, ct will be column-stored as well. */ \ ctype ct[ BLIS_STACK_BUF_MAX_SIZE \ / sizeof( ctype ) ] \ __attribute__((aligned(BLIS_STACK_BUF_ALIGN_SIZE))); \ const bool col_pref = bli_cntx_l3_vir_ukr_prefers_cols_dt( dt, BLIS_GEMM_UKR, cntx ); \ const inc_t rs_ct = ( col_pref ? 1 : NR ); \ const inc_t cs_ct = ( col_pref ? MR : 1 ); \ \ ctype* restrict one = PASTEMAC(ch,1); \ ctype* restrict zero = PASTEMAC(ch,0); \ ctype* restrict a_cast = a; \ ctype* restrict b_cast = b; \ ctype* restrict c_cast = c; \ ctype* restrict alpha_cast = alpha; \ ctype* restrict beta_cast = beta; \ ctype* restrict b1; \ ctype* restrict c1; \ \ doff_t diagoffa_i; \ dim_t k_full; \ dim_t m_iter, m_left; \ dim_t n_iter, n_left; \ dim_t m_cur; \ dim_t n_cur; \ dim_t k_a1011; \ dim_t off_a1011; \ dim_t i, j; \ inc_t rstep_a; \ inc_t cstep_b; \ inc_t rstep_c, cstep_c; \ inc_t istep_a; \ inc_t istep_b; \ inc_t off_scl; \ inc_t ss_a_num; \ inc_t ss_a_den; \ inc_t ps_a_cur; \ inc_t is_a_cur; \ auxinfo_t aux; \ \ /* Assumptions/assertions: rs_a == 1 cs_a == PACKMR pd_a == MR ps_a == stride to next micro-panel of A rs_b == PACKNR cs_b == 1 pd_b == NR ps_b == stride to next micro-panel of B rs_c == (no assumptions) cs_c == (no assumptions) */ \ \ /* Safety trap: Certain indexing within this macro-kernel does not work as intended if both MR and NR are odd. */ \ if ( ( bli_is_odd( PACKMR ) && bli_is_odd( NR ) ) || \ ( bli_is_odd( PACKNR ) && bli_is_odd( MR ) ) ) bli_abort(); \ \ /* If any dimension is zero, return immediately. */ \ if ( bli_zero_dim3( m, n, k ) ) return; \ \ /* Safeguard: If the current block of A is entirely above the diagonal, it is implicitly zero. So we do nothing. */ \ if ( bli_is_strictly_above_diag_n( diagoffa, m, k ) ) return; \ \ /* Compute k_full. For all trmm, k_full is simply k. This is needed because some parameter combinations of trmm reduce k to advance past zero regions in the triangular matrix, and when computing the imaginary stride of B (the non-triangular matrix), which is used by 4m1/3m1 implementations, we need this unreduced value of k. */ \ k_full = k; \ \ /* Compute indexing scaling factor for for 4m or 3m. This is needed because one of the packing register blocksizes (PACKMR or PACKNR) is used to index into the micro-panels of the non- triangular matrix when computing with a diagonal-intersecting micro-panel of the triangular matrix. In the case of 4m or 3m, real values are stored in both sub-panels, and so the indexing needs to occur in units of real values. The value computed here is divided into the complex pointer offset to cause the pointer to be advanced by the correct value. */ \ if ( bli_is_4mi_packed( schema_a ) || \ bli_is_3mi_packed( schema_a ) || \ bli_is_rih_packed( schema_a ) ) off_scl = 2; \ else off_scl = 1; \ \ /* Compute the storage stride scaling. Usually this is just 1. However, in the case of interleaved 3m, we need to scale the offset by 3/2. And if we are packing real-only, imag-only, or summed-only, we need to scale the computed panel sizes by 1/2 to compensate for the fact that the pointer arithmetic occurs in terms of complex elements rather than real elements. */ \ if ( bli_is_3mi_packed( schema_a ) ) { ss_a_num = 3; ss_a_den = 2; } \ else if ( bli_is_rih_packed( schema_a ) ) { ss_a_num = 1; ss_a_den = 2; } \ else { ss_a_num = 1; ss_a_den = 1; } \ \ /* If there is a zero region above where the diagonal of A intersects the left edge of the block, adjust the pointer to C and treat this case as if the diagonal offset were zero. This skips over the region that was not packed. (Note we assume the diagonal offset is a multiple of MR; this assumption will hold as long as the cache blocksizes are each a multiple of MR and NR.) */ \ if ( diagoffa < 0 ) \ { \ i = -diagoffa; \ m = m - i; \ diagoffa = 0; \ c_cast = c_cast + (i )*rs_c; \ } \ \ /* Clear the temporary C buffer in case it has any infs or NaNs. */ \ PASTEMAC(ch,set0s_mxn)( MR, NR, \ ct, rs_ct, cs_ct ); \ \ /* Compute number of primary and leftover components of the m and n dimensions. */ \ n_iter = n / NR; \ n_left = n % NR; \ \ m_iter = m / MR; \ m_left = m % MR; \ \ if ( n_left ) ++n_iter; \ if ( m_left ) ++m_iter; \ \ /* Determine some increments used to step through A, B, and C. */ \ rstep_a = ps_a; \ \ cstep_b = ps_b; \ \ rstep_c = rs_c * MR; \ cstep_c = cs_c * NR; \ \ istep_a = PACKMR * k; \ istep_b = PACKNR * k_full; \ \ if ( bli_is_odd( istep_a ) ) istep_a += 1; \ if ( bli_is_odd( istep_b ) ) istep_b += 1; \ \ /* Save the pack schemas of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_schema_a( schema_a, &aux ); \ bli_auxinfo_set_schema_b( schema_b, &aux ); \ \ /* Save the imaginary stride of B to the auxinfo_t object. */ \ bli_auxinfo_set_is_b( istep_b, &aux ); \ \ b1 = b_cast; \ c1 = c_cast; \ \ thrinfo_t* ir_thread = bli_thrinfo_sub_node( jr_thread ); \ dim_t jr_num_threads = bli_thread_n_way( jr_thread ); \ dim_t jr_thread_id = bli_thread_work_id( jr_thread ); \ \ /* Loop over the n dimension (NR columns at a time). */ \ for ( j = 0; j < n_iter; ++j ) \ { \ if ( bli_trmm_my_iter( j, jr_thread ) ) { \ \ ctype* restrict a1; \ ctype* restrict c11; \ ctype* restrict b2; \ \ a1 = a_cast; \ c11 = c1; \ \ n_cur = ( bli_is_not_edge_f( j, n_iter, n_left ) ? NR : n_left ); \ \ /* Initialize our next panel of B to be the current panel of B. */ \ b2 = b1; \ \ /* Loop over the m dimension (MR rows at a time). */ \ for ( i = 0; i < m_iter; ++i ) \ { \ diagoffa_i = diagoffa + ( doff_t )i*MR; \ \ m_cur = ( bli_is_not_edge_f( i, m_iter, m_left ) ? MR : m_left ); \ \ /* If the current panel of A intersects the diagonal, scale C by beta. If it is strictly below the diagonal, scale by one. This allows the current macro-kernel to work for both trmm and trmm3. */ \ if ( bli_intersects_diag_n( diagoffa_i, MR, k ) ) \ { \ ctype* restrict b1_i; \ ctype* restrict a2; \ \ /* Determine the offset to and length of the panel that was packed so we can index into the corresponding location in b1. */ \ off_a1011 = 0; \ k_a1011 = bli_min( diagoffa_i + MR, k ); \ \ /* Compute the panel stride for the current diagonal- intersecting micro-panel. */ \ is_a_cur = k_a1011 * PACKMR; \ is_a_cur += ( bli_is_odd( is_a_cur ) ? 1 : 0 ); \ ps_a_cur = ( is_a_cur * ss_a_num ) / ss_a_den; \ \ if ( bli_trmm_my_iter( i, ir_thread ) ) { \ \ b1_i = b1 + ( off_a1011 * PACKNR ) / off_scl; \ \ /* Compute the addresses of the next panels of A and B. */ \ a2 = a1; \ if ( bli_is_last_iter( i, m_iter, 0, 1 ) ) \ { \ a2 = a_cast; \ b2 = b1; \ if ( bli_is_last_iter( j, n_iter, jr_thread_id, jr_num_threads ) ) \ b2 = b_cast; \ } \ \ /* Save addresses of next panels of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_next_a( a2, &aux ); \ bli_auxinfo_set_next_b( b2, &aux ); \ \ /* Save the 4m1/3m1 imaginary stride of A to the auxinfo_t object. */ \ bli_auxinfo_set_is_a( is_a_cur, &aux ); \ \ /* Handle interior and edge cases separately. */ \ if ( m_cur == MR && n_cur == NR ) \ { \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k_a1011, \ alpha_cast, \ a1, \ b1_i, \ beta_cast, \ c11, rs_c, cs_c, \ &aux, \ cntx \ ); \ } \ else \ { \ /* Copy edge elements of C to the temporary buffer. */ \ PASTEMAC(ch,copys_mxn)( m_cur, n_cur, \ c11, rs_c, cs_c, \ ct, rs_ct, cs_ct ); \ \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k_a1011, \ alpha_cast, \ a1, \ b1_i, \ beta_cast, \ ct, rs_ct, cs_ct, \ &aux, \ cntx \ ); \ \ /* Copy the result to the edge of C. */ \ PASTEMAC(ch,copys_mxn)( m_cur, n_cur, \ ct, rs_ct, cs_ct, \ c11, rs_c, cs_c ); \ } \ } \ \ a1 += ps_a_cur; \ } \ else if ( bli_is_strictly_below_diag_n( diagoffa_i, MR, k ) ) \ { \ if ( bli_trmm_my_iter( i, ir_thread ) ) { \ \ ctype* restrict a2; \ \ /* Compute the addresses of the next panels of A and B. */ \ a2 = a1; \ if ( bli_is_last_iter( i, m_iter, 0, 1 ) ) \ { \ a2 = a_cast; \ b2 = b1; \ if ( bli_is_last_iter( j, n_iter, jr_thread_id, jr_num_threads ) ) \ b2 = b_cast; \ } \ \ /* Save addresses of next panels of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_next_a( a2, &aux ); \ bli_auxinfo_set_next_b( b2, &aux ); \ \ /* Save the 4m1/3m1 imaginary stride of A to the auxinfo_t object. */ \ bli_auxinfo_set_is_a( istep_a, &aux ); \ \ /* Handle interior and edge cases separately. */ \ if ( m_cur == MR && n_cur == NR ) \ { \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k, \ alpha_cast, \ a1, \ b1, \ one, \ c11, rs_c, cs_c, \ &aux, \ cntx \ ); \ } \ else \ { \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k, \ alpha_cast, \ a1, \ b1, \ zero, \ ct, rs_ct, cs_ct, \ &aux, \ cntx \ ); \ \ /* Add the result to the edge of C. */ \ PASTEMAC(ch,adds_mxn)( m_cur, n_cur, \ ct, rs_ct, cs_ct, \ c11, rs_c, cs_c ); \ } \ } \ \ a1 += rstep_a; \ } \ \ c11 += rstep_c; \ } \ } \ \ b1 += cstep_b; \ c1 += cstep_c; \ } \ /*PASTEMAC(ch,fprintm)( stdout, "trmm_ll_ker_var2: a1", MR, k_a1011, a1, 1, MR, "%4.1f", "" );*/ \ /*PASTEMAC(ch,fprintm)( stdout, "trmm_ll_ker_var2: b1", k_a1011, NR, b1_i, NR, 1, "%4.1f", "" );*/ \ } INSERT_GENTFUNC_BASIC0( trmm_ll_ker_var2 ) blis-0.9.0/frame/3/trmm/other/bli_trmm_ll_ker_var2rr.c000066400000000000000000000410551422157504600226170ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define FUNCPTR_T gemm_fp typedef void (*FUNCPTR_T) ( doff_t diagoffa, pack_t schema_a, pack_t schema_b, dim_t m, dim_t n, dim_t k, void* alpha, void* a, inc_t cs_a, dim_t pd_a, inc_t ps_a, void* b, inc_t rs_b, dim_t pd_b, inc_t ps_b, void* beta, void* c, inc_t rs_c, inc_t cs_c, cntx_t* cntx, rntm_t* rntm, thrinfo_t* thread ); static FUNCPTR_T GENARRAY(ftypes,trmm_ll_ker_var2rr); // // -- Macrokernel functions for round-robin partitioning ----------------------- // void bli_trmm_ll_ker_var2rr ( obj_t* a, obj_t* b, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ) { num_t dt_exec = bli_obj_exec_dt( c ); doff_t diagoffa = bli_obj_diag_offset( a ); pack_t schema_a = bli_obj_pack_schema( a ); pack_t schema_b = bli_obj_pack_schema( b ); dim_t m = bli_obj_length( c ); dim_t n = bli_obj_width( c ); dim_t k = bli_obj_width( a ); void* buf_a = bli_obj_buffer_at_off( a ); inc_t cs_a = bli_obj_col_stride( a ); dim_t pd_a = bli_obj_panel_dim( a ); inc_t ps_a = bli_obj_panel_stride( a ); void* buf_b = bli_obj_buffer_at_off( b ); inc_t rs_b = bli_obj_row_stride( b ); dim_t pd_b = bli_obj_panel_dim( b ); inc_t ps_b = bli_obj_panel_stride( b ); void* buf_c = bli_obj_buffer_at_off( c ); inc_t rs_c = bli_obj_row_stride( c ); inc_t cs_c = bli_obj_col_stride( c ); obj_t scalar_a; obj_t scalar_b; void* buf_alpha; void* buf_beta; FUNCPTR_T f; // Detach and multiply the scalars attached to A and B. bli_obj_scalar_detach( a, &scalar_a ); bli_obj_scalar_detach( b, &scalar_b ); bli_mulsc( &scalar_a, &scalar_b ); // Grab the addresses of the internal scalar buffers for the scalar // merged above and the scalar attached to C. buf_alpha = bli_obj_internal_scalar_buffer( &scalar_b ); buf_beta = bli_obj_internal_scalar_buffer( c ); // Index into the type combination array to extract the correct // function pointer. f = ftypes[dt_exec]; // Invoke the function. f( diagoffa, schema_a, schema_b, m, n, k, buf_alpha, buf_a, cs_a, pd_a, ps_a, buf_b, rs_b, pd_b, ps_b, buf_beta, buf_c, rs_c, cs_c, cntx, rntm, thread ); } #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ doff_t diagoffa, \ pack_t schema_a, \ pack_t schema_b, \ dim_t m, \ dim_t n, \ dim_t k, \ void* alpha, \ void* a, inc_t cs_a, dim_t pd_a, inc_t ps_a, \ void* b, inc_t rs_b, dim_t pd_b, inc_t ps_b, \ void* beta, \ void* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx, \ rntm_t* rntm, \ thrinfo_t* thread \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ /* Alias some constants to simpler names. */ \ const dim_t MR = pd_a; \ const dim_t NR = pd_b; \ const dim_t PACKMR = cs_a; \ const dim_t PACKNR = rs_b; \ \ /* Query the context for the micro-kernel address and cast it to its function pointer type. */ \ PASTECH(ch,gemm_ukr_ft) \ gemm_ukr = bli_cntx_get_l3_vir_ukr_dt( dt, BLIS_GEMM_UKR, cntx ); \ \ /* Temporary C buffer for edge cases. Note that the strides of this temporary buffer are set so that they match the storage of the original C matrix. For example, if C is column-stored, ct will be column-stored as well. */ \ ctype ct[ BLIS_STACK_BUF_MAX_SIZE \ / sizeof( ctype ) ] \ __attribute__((aligned(BLIS_STACK_BUF_ALIGN_SIZE))); \ const bool col_pref = bli_cntx_l3_vir_ukr_prefers_cols_dt( dt, BLIS_GEMM_UKR, cntx ); \ const inc_t rs_ct = ( col_pref ? 1 : NR ); \ const inc_t cs_ct = ( col_pref ? MR : 1 ); \ \ ctype* restrict one = PASTEMAC(ch,1); \ ctype* restrict zero = PASTEMAC(ch,0); \ ctype* restrict a_cast = a; \ ctype* restrict b_cast = b; \ ctype* restrict c_cast = c; \ ctype* restrict alpha_cast = alpha; \ ctype* restrict beta_cast = beta; \ ctype* restrict b1; \ ctype* restrict c1; \ \ doff_t diagoffa_i; \ dim_t k_full; \ dim_t m_iter, m_left; \ dim_t n_iter, n_left; \ dim_t m_cur; \ dim_t n_cur; \ dim_t k_a1011; \ dim_t off_a1011; \ dim_t i, j; \ inc_t rstep_a; \ inc_t cstep_b; \ inc_t rstep_c, cstep_c; \ inc_t istep_a; \ inc_t istep_b; \ inc_t off_scl; \ inc_t ss_a_num; \ inc_t ss_a_den; \ inc_t ps_a_cur; \ inc_t is_a_cur; \ auxinfo_t aux; \ \ /* Assumptions/assertions: rs_a == 1 cs_a == PACKMR pd_a == MR ps_a == stride to next micro-panel of A rs_b == PACKNR cs_b == 1 pd_b == NR ps_b == stride to next micro-panel of B rs_c == (no assumptions) cs_c == (no assumptions) */ \ \ /* Safety trap: Certain indexing within this macro-kernel does not work as intended if both MR and NR are odd. */ \ if ( ( bli_is_odd( PACKMR ) && bli_is_odd( NR ) ) || \ ( bli_is_odd( PACKNR ) && bli_is_odd( MR ) ) ) bli_abort(); \ \ /* If any dimension is zero, return immediately. */ \ if ( bli_zero_dim3( m, n, k ) ) return; \ \ /* Safeguard: If the current block of A is entirely above the diagonal, it is implicitly zero. So we do nothing. */ \ if ( bli_is_strictly_above_diag_n( diagoffa, m, k ) ) return; \ \ /* Compute k_full. For all trmm, k_full is simply k. This is needed because some parameter combinations of trmm reduce k to advance past zero regions in the triangular matrix, and when computing the imaginary stride of B (the non-triangular matrix), which is used by 4m1/3m1 implementations, we need this unreduced value of k. */ \ k_full = k; \ \ /* Compute indexing scaling factor for for 4m or 3m. This is needed because one of the packing register blocksizes (PACKMR or PACKNR) is used to index into the micro-panels of the non- triangular matrix when computing with a diagonal-intersecting micro-panel of the triangular matrix. In the case of 4m or 3m, real values are stored in both sub-panels, and so the indexing needs to occur in units of real values. The value computed here is divided into the complex pointer offset to cause the pointer to be advanced by the correct value. */ \ if ( bli_is_4mi_packed( schema_a ) || \ bli_is_3mi_packed( schema_a ) || \ bli_is_rih_packed( schema_a ) ) off_scl = 2; \ else off_scl = 1; \ \ /* Compute the storage stride scaling. Usually this is just 1. However, in the case of interleaved 3m, we need to scale the offset by 3/2. And if we are packing real-only, imag-only, or summed-only, we need to scale the computed panel sizes by 1/2 to compensate for the fact that the pointer arithmetic occurs in terms of complex elements rather than real elements. */ \ if ( bli_is_3mi_packed( schema_a ) ) { ss_a_num = 3; ss_a_den = 2; } \ else if ( bli_is_rih_packed( schema_a ) ) { ss_a_num = 1; ss_a_den = 2; } \ else { ss_a_num = 1; ss_a_den = 1; } \ \ /* If there is a zero region above where the diagonal of A intersects the left edge of the block, adjust the pointer to C and treat this case as if the diagonal offset were zero. This skips over the region that was not packed. (Note we assume the diagonal offset is a multiple of MR; this assumption will hold as long as the cache blocksizes are each a multiple of MR and NR.) */ \ if ( diagoffa < 0 ) \ { \ i = -diagoffa; \ m = m - i; \ diagoffa = 0; \ c_cast = c_cast + (i )*rs_c; \ } \ \ /* Clear the temporary C buffer in case it has any infs or NaNs. */ \ PASTEMAC(ch,set0s_mxn)( MR, NR, \ ct, rs_ct, cs_ct ); \ \ /* Compute number of primary and leftover components of the m and n dimensions. */ \ n_iter = n / NR; \ n_left = n % NR; \ \ m_iter = m / MR; \ m_left = m % MR; \ \ if ( n_left ) ++n_iter; \ if ( m_left ) ++m_iter; \ \ /* Determine some increments used to step through A, B, and C. */ \ rstep_a = ps_a; \ \ cstep_b = ps_b; \ \ rstep_c = rs_c * MR; \ cstep_c = cs_c * NR; \ \ istep_a = PACKMR * k; \ istep_b = PACKNR * k_full; \ \ if ( bli_is_odd( istep_a ) ) istep_a += 1; \ if ( bli_is_odd( istep_b ) ) istep_b += 1; \ \ /* Save the pack schemas of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_schema_a( schema_a, &aux ); \ bli_auxinfo_set_schema_b( schema_b, &aux ); \ \ /* Save the imaginary stride of B to the auxinfo_t object. */ \ bli_auxinfo_set_is_b( istep_b, &aux ); \ \ /* The 'thread' argument points to the thrinfo_t node for the 2nd (jr) loop around the microkernel. Here we query the thrinfo_t node for the 1st (ir) loop around the microkernel. */ \ /*thrinfo_t* ir_thread = bli_thrinfo_sub_node( thread );*/ \ \ /* Query the number of threads and thread ids for each loop. */ \ dim_t jr_nt = bli_thread_n_way( thread ); \ dim_t jr_tid = bli_thread_work_id( thread ); \ /*dim_t ir_nt = bli_thread_n_way( ir_thread ); \ dim_t ir_tid = bli_thread_work_id( ir_thread );*/ \ \ dim_t jr_start, jr_end; \ /*dim_t ir_start, ir_end;*/ \ dim_t jr_inc; \ \ /* Use round-robin assignment of micropanels to threads in the 2nd loop for the initial rectangular region of C (if it exists). NOTE: Parallelism in the 1st loop is disabled for now. */ \ bli_thread_range_jrir_rr( thread, n_iter, 1, FALSE, &jr_start, &jr_end, &jr_inc ); \ /*bli_thread_range_jrir_rr( caucus, m_iter, 1, FALSE, &ir_start, &ir_end, &ir_inc );*/ \ \ /* Loop over the n dimension (NR columns at a time). */ \ for ( j = jr_start; j < jr_end; j += jr_inc ) \ { \ ctype* restrict a1; \ ctype* restrict c11; \ ctype* restrict b2; \ \ b1 = b_cast + j * cstep_b; \ c1 = c_cast + j * cstep_c; \ \ n_cur = ( bli_is_not_edge_f( j, n_iter, n_left ) ? NR : n_left ); \ \ /* Initialize our next panel of B to be the current panel of B. */ \ b2 = b1; \ \ a1 = a_cast; \ c11 = c1; \ \ /* Loop over the m dimension (MR rows at a time). */ \ for ( i = 0; i < m_iter; ++i ) \ { \ diagoffa_i = diagoffa + ( doff_t )i*MR; \ \ m_cur = ( bli_is_not_edge_f( i, m_iter, m_left ) ? MR : m_left ); \ \ /* If the current panel of A intersects the diagonal, scale C by beta. If it is strictly below the diagonal, scale by one. This allows the current macro-kernel to work for both trmm and trmm3. */ \ if ( bli_intersects_diag_n( diagoffa_i, MR, k ) ) \ { \ ctype* restrict b1_i; \ ctype* restrict a2; \ \ /* Determine the offset to and length of the panel that was packed so we can index into the corresponding location in b1. */ \ off_a1011 = 0; \ k_a1011 = bli_min( diagoffa_i + MR, k ); \ \ /* Compute the panel stride for the current diagonal- intersecting micro-panel. */ \ is_a_cur = k_a1011 * PACKMR; \ is_a_cur += ( bli_is_odd( is_a_cur ) ? 1 : 0 ); \ ps_a_cur = ( is_a_cur * ss_a_num ) / ss_a_den; \ \ /* NOTE: ir loop parallelism disabled for now. */ \ /*if ( bli_trmm_my_iter( i, ir_thread ) ) {*/ \ \ b1_i = b1 + ( off_a1011 * PACKNR ) / off_scl; \ \ /* Compute the addresses of the next panels of A and B. */ \ a2 = a1; \ if ( bli_is_last_iter_rr( i, m_iter, 0, 1 ) ) \ { \ a2 = a_cast; \ b2 = b1; \ if ( bli_is_last_iter_rr( j, n_iter, jr_tid, jr_nt ) ) \ b2 = b_cast; \ } \ \ /* Save addresses of next panels of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_next_a( a2, &aux ); \ bli_auxinfo_set_next_b( b2, &aux ); \ \ /* Save the 4m1/3m1 imaginary stride of A to the auxinfo_t object. */ \ bli_auxinfo_set_is_a( is_a_cur, &aux ); \ \ /* Handle interior and edge cases separately. */ \ if ( m_cur == MR && n_cur == NR ) \ { \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k_a1011, \ alpha_cast, \ a1, \ b1_i, \ beta_cast, \ c11, rs_c, cs_c, \ &aux, \ cntx \ ); \ } \ else \ { \ /* Copy edge elements of C to the temporary buffer. */ \ PASTEMAC(ch,copys_mxn)( m_cur, n_cur, \ c11, rs_c, cs_c, \ ct, rs_ct, cs_ct ); \ \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k_a1011, \ alpha_cast, \ a1, \ b1_i, \ beta_cast, \ ct, rs_ct, cs_ct, \ &aux, \ cntx \ ); \ \ /* Copy the result to the edge of C. */ \ PASTEMAC(ch,copys_mxn)( m_cur, n_cur, \ ct, rs_ct, cs_ct, \ c11, rs_c, cs_c ); \ } \ /*}*/ \ \ a1 += ps_a_cur; \ } \ else if ( bli_is_strictly_below_diag_n( diagoffa_i, MR, k ) ) \ { \ /* NOTE: ir loop parallelism disabled for now. */ \ /*if ( bli_trmm_my_iter( i, ir_thread ) ) {*/ \ \ ctype* restrict a2; \ \ /* Compute the addresses of the next panels of A and B. */ \ a2 = a1; \ if ( bli_is_last_iter_rr( i, m_iter, 0, 1 ) ) \ { \ a2 = a_cast; \ b2 = b1; \ if ( bli_is_last_iter_rr( j, n_iter, jr_tid, jr_nt ) ) \ b2 = b_cast; \ } \ \ /* Save addresses of next panels of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_next_a( a2, &aux ); \ bli_auxinfo_set_next_b( b2, &aux ); \ \ /* Save the 4m1/3m1 imaginary stride of A to the auxinfo_t object. */ \ bli_auxinfo_set_is_a( istep_a, &aux ); \ \ /* Handle interior and edge cases separately. */ \ if ( m_cur == MR && n_cur == NR ) \ { \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k, \ alpha_cast, \ a1, \ b1, \ one, \ c11, rs_c, cs_c, \ &aux, \ cntx \ ); \ } \ else \ { \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k, \ alpha_cast, \ a1, \ b1, \ zero, \ ct, rs_ct, cs_ct, \ &aux, \ cntx \ ); \ \ /* Add the result to the edge of C. */ \ PASTEMAC(ch,adds_mxn)( m_cur, n_cur, \ ct, rs_ct, cs_ct, \ c11, rs_c, cs_c ); \ } \ /*}*/ \ \ a1 += rstep_a; \ } \ \ c11 += rstep_c; \ } \ } \ /*PASTEMAC(ch,fprintm)( stdout, "trmm_ll_ker_var2rr: a1", MR, k_a1011, a1, 1, MR, "%4.1f", "" );*/ \ /*PASTEMAC(ch,fprintm)( stdout, "trmm_ll_ker_var2rr: b1", k_a1011, NR, b1_i, NR, 1, "%4.1f", "" );*/ \ } INSERT_GENTFUNC_BASIC0( trmm_ll_ker_var2rr ) blis-0.9.0/frame/3/trmm/other/bli_trmm_ll_ker_var2sl.c000066400000000000000000000410451422157504600226110ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define FUNCPTR_T gemm_fp typedef void (*FUNCPTR_T) ( doff_t diagoffa, pack_t schema_a, pack_t schema_b, dim_t m, dim_t n, dim_t k, void* alpha, void* a, inc_t cs_a, dim_t pd_a, inc_t ps_a, void* b, inc_t rs_b, dim_t pd_b, inc_t ps_b, void* beta, void* c, inc_t rs_c, inc_t cs_c, cntx_t* cntx, rntm_t* rntm, thrinfo_t* thread ); static FUNCPTR_T GENARRAY(ftypes,trmm_ll_ker_var2sl); // // -- Macrokernel functions for slab partitioning ------------------------------ // void bli_trmm_ll_ker_var2sl ( obj_t* a, obj_t* b, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ) { num_t dt_exec = bli_obj_exec_dt( c ); doff_t diagoffa = bli_obj_diag_offset( a ); pack_t schema_a = bli_obj_pack_schema( a ); pack_t schema_b = bli_obj_pack_schema( b ); dim_t m = bli_obj_length( c ); dim_t n = bli_obj_width( c ); dim_t k = bli_obj_width( a ); void* buf_a = bli_obj_buffer_at_off( a ); inc_t cs_a = bli_obj_col_stride( a ); dim_t pd_a = bli_obj_panel_dim( a ); inc_t ps_a = bli_obj_panel_stride( a ); void* buf_b = bli_obj_buffer_at_off( b ); inc_t rs_b = bli_obj_row_stride( b ); dim_t pd_b = bli_obj_panel_dim( b ); inc_t ps_b = bli_obj_panel_stride( b ); void* buf_c = bli_obj_buffer_at_off( c ); inc_t rs_c = bli_obj_row_stride( c ); inc_t cs_c = bli_obj_col_stride( c ); obj_t scalar_a; obj_t scalar_b; void* buf_alpha; void* buf_beta; FUNCPTR_T f; // Detach and multiply the scalars attached to A and B. bli_obj_scalar_detach( a, &scalar_a ); bli_obj_scalar_detach( b, &scalar_b ); bli_mulsc( &scalar_a, &scalar_b ); // Grab the addresses of the internal scalar buffers for the scalar // merged above and the scalar attached to C. buf_alpha = bli_obj_internal_scalar_buffer( &scalar_b ); buf_beta = bli_obj_internal_scalar_buffer( c ); // Index into the type combination array to extract the correct // function pointer. f = ftypes[dt_exec]; // Invoke the function. f( diagoffa, schema_a, schema_b, m, n, k, buf_alpha, buf_a, cs_a, pd_a, ps_a, buf_b, rs_b, pd_b, ps_b, buf_beta, buf_c, rs_c, cs_c, cntx, rntm, thread ); } #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ doff_t diagoffa, \ pack_t schema_a, \ pack_t schema_b, \ dim_t m, \ dim_t n, \ dim_t k, \ void* alpha, \ void* a, inc_t cs_a, dim_t pd_a, inc_t ps_a, \ void* b, inc_t rs_b, dim_t pd_b, inc_t ps_b, \ void* beta, \ void* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx, \ rntm_t* rntm, \ thrinfo_t* thread \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ /* Alias some constants to simpler names. */ \ const dim_t MR = pd_a; \ const dim_t NR = pd_b; \ const dim_t PACKMR = cs_a; \ const dim_t PACKNR = rs_b; \ \ /* Query the context for the micro-kernel address and cast it to its function pointer type. */ \ PASTECH(ch,gemm_ukr_ft) \ gemm_ukr = bli_cntx_get_l3_vir_ukr_dt( dt, BLIS_GEMM_UKR, cntx ); \ \ /* Temporary C buffer for edge cases. Note that the strides of this temporary buffer are set so that they match the storage of the original C matrix. For example, if C is column-stored, ct will be column-stored as well. */ \ ctype ct[ BLIS_STACK_BUF_MAX_SIZE \ / sizeof( ctype ) ] \ __attribute__((aligned(BLIS_STACK_BUF_ALIGN_SIZE))); \ const bool col_pref = bli_cntx_l3_vir_ukr_prefers_cols_dt( dt, BLIS_GEMM_UKR, cntx ); \ const inc_t rs_ct = ( col_pref ? 1 : NR ); \ const inc_t cs_ct = ( col_pref ? MR : 1 ); \ \ ctype* restrict one = PASTEMAC(ch,1); \ ctype* restrict zero = PASTEMAC(ch,0); \ ctype* restrict a_cast = a; \ ctype* restrict b_cast = b; \ ctype* restrict c_cast = c; \ ctype* restrict alpha_cast = alpha; \ ctype* restrict beta_cast = beta; \ ctype* restrict b1; \ ctype* restrict c1; \ \ doff_t diagoffa_i; \ dim_t k_full; \ dim_t m_iter, m_left; \ dim_t n_iter, n_left; \ dim_t m_cur; \ dim_t n_cur; \ dim_t k_a1011; \ dim_t off_a1011; \ dim_t i, j; \ inc_t rstep_a; \ inc_t cstep_b; \ inc_t rstep_c, cstep_c; \ inc_t istep_a; \ inc_t istep_b; \ inc_t off_scl; \ inc_t ss_a_num; \ inc_t ss_a_den; \ inc_t ps_a_cur; \ inc_t is_a_cur; \ auxinfo_t aux; \ \ /* Assumptions/assertions: rs_a == 1 cs_a == PACKMR pd_a == MR ps_a == stride to next micro-panel of A rs_b == PACKNR cs_b == 1 pd_b == NR ps_b == stride to next micro-panel of B rs_c == (no assumptions) cs_c == (no assumptions) */ \ \ /* Safety trap: Certain indexing within this macro-kernel does not work as intended if both MR and NR are odd. */ \ if ( ( bli_is_odd( PACKMR ) && bli_is_odd( NR ) ) || \ ( bli_is_odd( PACKNR ) && bli_is_odd( MR ) ) ) bli_abort(); \ \ /* If any dimension is zero, return immediately. */ \ if ( bli_zero_dim3( m, n, k ) ) return; \ \ /* Safeguard: If the current block of A is entirely above the diagonal, it is implicitly zero. So we do nothing. */ \ if ( bli_is_strictly_above_diag_n( diagoffa, m, k ) ) return; \ \ /* Compute k_full. For all trmm, k_full is simply k. This is needed because some parameter combinations of trmm reduce k to advance past zero regions in the triangular matrix, and when computing the imaginary stride of B (the non-triangular matrix), which is used by 4m1/3m1 implementations, we need this unreduced value of k. */ \ k_full = k; \ \ /* Compute indexing scaling factor for for 4m or 3m. This is needed because one of the packing register blocksizes (PACKMR or PACKNR) is used to index into the micro-panels of the non- triangular matrix when computing with a diagonal-intersecting micro-panel of the triangular matrix. In the case of 4m or 3m, real values are stored in both sub-panels, and so the indexing needs to occur in units of real values. The value computed here is divided into the complex pointer offset to cause the pointer to be advanced by the correct value. */ \ if ( bli_is_4mi_packed( schema_a ) || \ bli_is_3mi_packed( schema_a ) || \ bli_is_rih_packed( schema_a ) ) off_scl = 2; \ else off_scl = 1; \ \ /* Compute the storage stride scaling. Usually this is just 1. However, in the case of interleaved 3m, we need to scale the offset by 3/2. And if we are packing real-only, imag-only, or summed-only, we need to scale the computed panel sizes by 1/2 to compensate for the fact that the pointer arithmetic occurs in terms of complex elements rather than real elements. */ \ if ( bli_is_3mi_packed( schema_a ) ) { ss_a_num = 3; ss_a_den = 2; } \ else if ( bli_is_rih_packed( schema_a ) ) { ss_a_num = 1; ss_a_den = 2; } \ else { ss_a_num = 1; ss_a_den = 1; } \ \ /* If there is a zero region above where the diagonal of A intersects the left edge of the block, adjust the pointer to C and treat this case as if the diagonal offset were zero. This skips over the region that was not packed. (Note we assume the diagonal offset is a multiple of MR; this assumption will hold as long as the cache blocksizes are each a multiple of MR and NR.) */ \ if ( diagoffa < 0 ) \ { \ i = -diagoffa; \ m = m - i; \ diagoffa = 0; \ c_cast = c_cast + (i )*rs_c; \ } \ \ /* Clear the temporary C buffer in case it has any infs or NaNs. */ \ PASTEMAC(ch,set0s_mxn)( MR, NR, \ ct, rs_ct, cs_ct ); \ \ /* Compute number of primary and leftover components of the m and n dimensions. */ \ n_iter = n / NR; \ n_left = n % NR; \ \ m_iter = m / MR; \ m_left = m % MR; \ \ if ( n_left ) ++n_iter; \ if ( m_left ) ++m_iter; \ \ /* Determine some increments used to step through A, B, and C. */ \ rstep_a = ps_a; \ \ cstep_b = ps_b; \ \ rstep_c = rs_c * MR; \ cstep_c = cs_c * NR; \ \ istep_a = PACKMR * k; \ istep_b = PACKNR * k_full; \ \ if ( bli_is_odd( istep_a ) ) istep_a += 1; \ if ( bli_is_odd( istep_b ) ) istep_b += 1; \ \ /* Save the pack schemas of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_schema_a( schema_a, &aux ); \ bli_auxinfo_set_schema_b( schema_b, &aux ); \ \ /* Save the imaginary stride of B to the auxinfo_t object. */ \ bli_auxinfo_set_is_b( istep_b, &aux ); \ \ /* The 'thread' argument points to the thrinfo_t node for the 2nd (jr) loop around the microkernel. Here we query the thrinfo_t node for the 1st (ir) loop around the microkernel. */ \ /*thrinfo_t* ir_thread = bli_thrinfo_sub_node( thread );*/ \ \ /* Query the number of threads and thread ids for each loop. */ \ dim_t jr_nt = bli_thread_n_way( thread ); \ dim_t jr_tid = bli_thread_work_id( thread ); \ /*dim_t ir_nt = bli_thread_n_way( ir_thread ); \ dim_t ir_tid = bli_thread_work_id( ir_thread );*/ \ \ dim_t jr_start, jr_end; \ /*dim_t ir_start, ir_end;*/ \ dim_t jr_inc; \ \ /* Use slab assignment of micropanels to threads in the 2nd loop for the initial rectangular region of C (if it exists). NOTE: Parallelism in the 1st loop is disabled for now. */ \ bli_thread_range_jrir_sl( thread, n_iter, 1, FALSE, &jr_start, &jr_end, &jr_inc ); \ /*bli_thread_range_jrir_rr( caucus, m_iter, 1, FALSE, &ir_start, &ir_end, &ir_inc );*/ \ \ /* Loop over the n dimension (NR columns at a time). */ \ for ( j = jr_start; j < jr_end; j += jr_inc ) \ { \ ctype* restrict a1; \ ctype* restrict c11; \ ctype* restrict b2; \ \ b1 = b_cast + j * cstep_b; \ c1 = c_cast + j * cstep_c; \ \ n_cur = ( bli_is_not_edge_f( j, n_iter, n_left ) ? NR : n_left ); \ \ /* Initialize our next panel of B to be the current panel of B. */ \ b2 = b1; \ \ a1 = a_cast; \ c11 = c1; \ \ /* Loop over the m dimension (MR rows at a time). */ \ for ( i = 0; i < m_iter; ++i ) \ { \ diagoffa_i = diagoffa + ( doff_t )i*MR; \ \ m_cur = ( bli_is_not_edge_f( i, m_iter, m_left ) ? MR : m_left ); \ \ /* If the current panel of A intersects the diagonal, scale C by beta. If it is strictly below the diagonal, scale by one. This allows the current macro-kernel to work for both trmm and trmm3. */ \ if ( bli_intersects_diag_n( diagoffa_i, MR, k ) ) \ { \ ctype* restrict b1_i; \ ctype* restrict a2; \ \ /* Determine the offset to and length of the panel that was packed so we can index into the corresponding location in b1. */ \ off_a1011 = 0; \ k_a1011 = bli_min( diagoffa_i + MR, k ); \ \ /* Compute the panel stride for the current diagonal- intersecting micro-panel. */ \ is_a_cur = k_a1011 * PACKMR; \ is_a_cur += ( bli_is_odd( is_a_cur ) ? 1 : 0 ); \ ps_a_cur = ( is_a_cur * ss_a_num ) / ss_a_den; \ \ /* NOTE: ir loop parallelism disabled for now. */ \ /*if ( bli_trmm_my_iter( i, ir_thread ) ) {*/ \ \ b1_i = b1 + ( off_a1011 * PACKNR ) / off_scl; \ \ /* Compute the addresses of the next panels of A and B. */ \ a2 = a1; \ if ( bli_is_last_iter_rr( i, m_iter, 0, 1 ) ) \ { \ a2 = a_cast; \ b2 = b1; \ if ( bli_is_last_iter_sl( j, n_iter, jr_tid, jr_nt ) ) \ b2 = b_cast; \ } \ \ /* Save addresses of next panels of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_next_a( a2, &aux ); \ bli_auxinfo_set_next_b( b2, &aux ); \ \ /* Save the 4m1/3m1 imaginary stride of A to the auxinfo_t object. */ \ bli_auxinfo_set_is_a( is_a_cur, &aux ); \ \ /* Handle interior and edge cases separately. */ \ if ( m_cur == MR && n_cur == NR ) \ { \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k_a1011, \ alpha_cast, \ a1, \ b1_i, \ beta_cast, \ c11, rs_c, cs_c, \ &aux, \ cntx \ ); \ } \ else \ { \ /* Copy edge elements of C to the temporary buffer. */ \ PASTEMAC(ch,copys_mxn)( m_cur, n_cur, \ c11, rs_c, cs_c, \ ct, rs_ct, cs_ct ); \ \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k_a1011, \ alpha_cast, \ a1, \ b1_i, \ beta_cast, \ ct, rs_ct, cs_ct, \ &aux, \ cntx \ ); \ \ /* Copy the result to the edge of C. */ \ PASTEMAC(ch,copys_mxn)( m_cur, n_cur, \ ct, rs_ct, cs_ct, \ c11, rs_c, cs_c ); \ } \ /*}*/ \ \ a1 += ps_a_cur; \ } \ else if ( bli_is_strictly_below_diag_n( diagoffa_i, MR, k ) ) \ { \ /* NOTE: ir loop parallelism disabled for now. */ \ /*if ( bli_trmm_my_iter( i, ir_thread ) ) {*/ \ \ ctype* restrict a2; \ \ /* Compute the addresses of the next panels of A and B. */ \ a2 = a1; \ if ( bli_is_last_iter_rr( i, m_iter, 0, 1 ) ) \ { \ a2 = a_cast; \ b2 = b1; \ if ( bli_is_last_iter_sl( j, n_iter, jr_tid, jr_nt ) ) \ b2 = b_cast; \ } \ \ /* Save addresses of next panels of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_next_a( a2, &aux ); \ bli_auxinfo_set_next_b( b2, &aux ); \ \ /* Save the 4m1/3m1 imaginary stride of A to the auxinfo_t object. */ \ bli_auxinfo_set_is_a( istep_a, &aux ); \ \ /* Handle interior and edge cases separately. */ \ if ( m_cur == MR && n_cur == NR ) \ { \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k, \ alpha_cast, \ a1, \ b1, \ one, \ c11, rs_c, cs_c, \ &aux, \ cntx \ ); \ } \ else \ { \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k, \ alpha_cast, \ a1, \ b1, \ zero, \ ct, rs_ct, cs_ct, \ &aux, \ cntx \ ); \ \ /* Add the result to the edge of C. */ \ PASTEMAC(ch,adds_mxn)( m_cur, n_cur, \ ct, rs_ct, cs_ct, \ c11, rs_c, cs_c ); \ } \ /*}*/ \ \ a1 += rstep_a; \ } \ \ c11 += rstep_c; \ } \ } \ /*PASTEMAC(ch,fprintm)( stdout, "trmm_ll_ker_var2sl: a1", MR, k_a1011, a1, 1, MR, "%4.1f", "" );*/ \ /*PASTEMAC(ch,fprintm)( stdout, "trmm_ll_ker_var2sl: b1", k_a1011, NR, b1_i, NR, 1, "%4.1f", "" );*/ \ } INSERT_GENTFUNC_BASIC0( trmm_ll_ker_var2sl ) blis-0.9.0/frame/3/trmm/other/bli_trmm_lu_ker_var2.c000066400000000000000000000374571422157504600222770ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define FUNCPTR_T gemm_fp typedef void (*FUNCPTR_T) ( doff_t diagoffa, pack_t schema_a, pack_t schema_b, dim_t m, dim_t n, dim_t k, void* alpha, void* a, inc_t cs_a, dim_t pd_a, inc_t ps_a, void* b, inc_t rs_b, dim_t pd_b, inc_t ps_b, void* beta, void* c, inc_t rs_c, inc_t cs_c, cntx_t* cntx, rntm_t* rntm, thrinfo_t* thread ); static FUNCPTR_T GENARRAY(ftypes,trmm_lu_ker_var2); void bli_trmm_lu_ker_var2 ( obj_t* a, obj_t* b, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ) { num_t dt_exec = bli_obj_exec_dt( c ); doff_t diagoffa = bli_obj_diag_offset( a ); pack_t schema_a = bli_obj_pack_schema( a ); pack_t schema_b = bli_obj_pack_schema( b ); dim_t m = bli_obj_length( c ); dim_t n = bli_obj_width( c ); dim_t k = bli_obj_width( a ); void* buf_a = bli_obj_buffer_at_off( a ); inc_t cs_a = bli_obj_col_stride( a ); dim_t pd_a = bli_obj_panel_dim( a ); inc_t ps_a = bli_obj_panel_stride( a ); void* buf_b = bli_obj_buffer_at_off( b ); inc_t rs_b = bli_obj_row_stride( b ); dim_t pd_b = bli_obj_panel_dim( b ); inc_t ps_b = bli_obj_panel_stride( b ); void* buf_c = bli_obj_buffer_at_off( c ); inc_t rs_c = bli_obj_row_stride( c ); inc_t cs_c = bli_obj_col_stride( c ); obj_t scalar_a; obj_t scalar_b; void* buf_alpha; void* buf_beta; FUNCPTR_T f; // Detach and multiply the scalars attached to A and B. bli_obj_scalar_detach( a, &scalar_a ); bli_obj_scalar_detach( b, &scalar_b ); bli_mulsc( &scalar_a, &scalar_b ); // Grab the addresses of the internal scalar buffers for the scalar // merged above and the scalar attached to C. buf_alpha = bli_obj_internal_scalar_buffer( &scalar_b ); buf_beta = bli_obj_internal_scalar_buffer( c ); // Index into the type combination array to extract the correct // function pointer. f = ftypes[dt_exec]; // Invoke the function. f( diagoffa, schema_a, schema_b, m, n, k, buf_alpha, buf_a, cs_a, pd_a, ps_a, buf_b, rs_b, pd_b, ps_b, buf_beta, buf_c, rs_c, cs_c, cntx, rntm, thread ); } #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ doff_t diagoffa, \ pack_t schema_a, \ pack_t schema_b, \ dim_t m, \ dim_t n, \ dim_t k, \ void* alpha, \ void* a, inc_t cs_a, dim_t pd_a, inc_t ps_a, \ void* b, inc_t rs_b, dim_t pd_b, inc_t ps_b, \ void* beta, \ void* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx, \ rntm_t* rntm, \ thrinfo_t* jr_thread \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ /* Alias some constants to simpler names. */ \ const dim_t MR = pd_a; \ const dim_t NR = pd_b; \ const dim_t PACKMR = cs_a; \ const dim_t PACKNR = rs_b; \ \ /* Query the context for the micro-kernel address and cast it to its function pointer type. */ \ PASTECH(ch,gemm_ukr_ft) \ gemm_ukr = bli_cntx_get_l3_vir_ukr_dt( dt, BLIS_GEMM_UKR, cntx ); \ \ /* Temporary C buffer for edge cases. Note that the strides of this temporary buffer are set so that they match the storage of the original C matrix. For example, if C is column-stored, ct will be column-stored as well. */ \ ctype ct[ BLIS_STACK_BUF_MAX_SIZE \ / sizeof( ctype ) ] \ __attribute__((aligned(BLIS_STACK_BUF_ALIGN_SIZE))); \ const bool col_pref = bli_cntx_l3_vir_ukr_prefers_cols_dt( dt, BLIS_GEMM_UKR, cntx ); \ const inc_t rs_ct = ( col_pref ? 1 : NR ); \ const inc_t cs_ct = ( col_pref ? MR : 1 ); \ \ ctype* restrict one = PASTEMAC(ch,1); \ ctype* restrict zero = PASTEMAC(ch,0); \ ctype* restrict a_cast = a; \ ctype* restrict b_cast = b; \ ctype* restrict c_cast = c; \ ctype* restrict alpha_cast = alpha; \ ctype* restrict beta_cast = beta; \ ctype* restrict b1; \ ctype* restrict c1; \ \ doff_t diagoffa_i; \ dim_t k_full; \ dim_t m_iter, m_left; \ dim_t n_iter, n_left; \ dim_t m_cur; \ dim_t n_cur; \ dim_t k_a1112; \ dim_t off_a1112; \ dim_t i, j; \ inc_t rstep_a; \ inc_t cstep_b; \ inc_t rstep_c, cstep_c; \ inc_t istep_a; \ inc_t istep_b; \ inc_t off_scl; \ inc_t ss_a_num; \ inc_t ss_a_den; \ inc_t ps_a_cur; \ inc_t is_a_cur; \ auxinfo_t aux; \ \ /* Assumptions/assertions: rs_a == 1 cs_a == PACKMR pd_a == MR ps_a == stride to next micro-panel of A rs_b == PACKNR cs_b == 1 pd_b == NR ps_b == stride to next micro-panel of B rs_c == (no assumptions) cs_c == (no assumptions) */ \ \ /* Safety trap: Certain indexing within this macro-kernel does not work as intended if both MR and NR are odd. */ \ if ( ( bli_is_odd( PACKMR ) && bli_is_odd( NR ) ) || \ ( bli_is_odd( PACKNR ) && bli_is_odd( MR ) ) ) bli_abort(); \ \ /* If any dimension is zero, return immediately. */ \ if ( bli_zero_dim3( m, n, k ) ) return; \ \ /* Safeguard: If the current block of A is entirely below the diagonal, it is implicitly zero. So we do nothing. */ \ if ( bli_is_strictly_below_diag_n( diagoffa, m, k ) ) return; \ \ /* Compute k_full. For all trmm, k_full is simply k. This is needed because some parameter combinations of trmm reduce k to advance past zero regions in the triangular matrix, and when computing the imaginary stride of B (the non-triangular matrix), which is used by 4m1/3m1 implementations, we need this unreduced value of k. */ \ k_full = k; \ \ /* Compute indexing scaling factor for for 4m or 3m. This is needed because one of the packing register blocksizes (PACKMR or PACKNR) is used to index into the micro-panels of the non- triangular matrix when computing with a diagonal-intersecting micro-panel of the triangular matrix. In the case of 4m or 3m, real values are stored in both sub-panels, and so the indexing needs to occur in units of real values. The value computed here is divided into the complex pointer offset to cause the pointer to be advanced by the correct value. */ \ if ( bli_is_4mi_packed( schema_a ) || \ bli_is_3mi_packed( schema_a ) || \ bli_is_rih_packed( schema_a ) ) off_scl = 2; \ else off_scl = 1; \ \ /* Compute the storage stride scaling. Usually this is just 1. However, in the case of interleaved 3m, we need to scale the offset by 3/2. And if we are packing real-only, imag-only, or summed-only, we need to scale the computed panel sizes by 1/2 to compensate for the fact that the pointer arithmetic occurs in terms of complex elements rather than real elements. */ \ if ( bli_is_3mi_packed( schema_a ) ) { ss_a_num = 3; ss_a_den = 2; } \ else if ( bli_is_rih_packed( schema_a ) ) { ss_a_num = 1; ss_a_den = 2; } \ else { ss_a_num = 1; ss_a_den = 1; } \ \ /* If there is a zero region to the left of where the diagonal of A intersects the top edge of the block, adjust the pointer to B and treat this case as if the diagonal offset were zero. Note that we don't need to adjust the pointer to A since packm would have simply skipped over the region that was not stored. */ \ if ( diagoffa > 0 ) \ { \ i = diagoffa; \ k = k - i; \ diagoffa = 0; \ b_cast = b_cast + ( i * PACKNR ) / off_scl; \ } \ \ /* If there is a zero region below where the diagonal of A intersects the right side of the block, shrink it to prevent "no-op" iterations from executing. */ \ if ( -diagoffa + k < m ) \ { \ m = -diagoffa + k; \ } \ \ /* Clear the temporary C buffer in case it has any infs or NaNs. */ \ PASTEMAC(ch,set0s_mxn)( MR, NR, \ ct, rs_ct, cs_ct ); \ \ /* Compute number of primary and leftover components of the m and n dimensions. */ \ n_iter = n / NR; \ n_left = n % NR; \ \ m_iter = m / MR; \ m_left = m % MR; \ \ if ( n_left ) ++n_iter; \ if ( m_left ) ++m_iter; \ \ /* Determine some increments used to step through A, B, and C. */ \ rstep_a = ps_a; \ \ cstep_b = ps_b; \ \ rstep_c = rs_c * MR; \ cstep_c = cs_c * NR; \ \ istep_a = PACKMR * k; \ istep_b = PACKNR * k_full; \ \ if ( bli_is_odd( istep_a ) ) istep_a += 1; \ if ( bli_is_odd( istep_b ) ) istep_b += 1; \ \ /* Save the pack schemas of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_schema_a( schema_a, &aux ); \ bli_auxinfo_set_schema_b( schema_b, &aux ); \ \ /* Save the imaginary stride of B to the auxinfo_t object. */ \ bli_auxinfo_set_is_b( istep_b, &aux ); \ \ b1 = b_cast; \ c1 = c_cast; \ \ thrinfo_t* ir_thread = bli_thrinfo_sub_node( jr_thread ); \ dim_t jr_num_threads = bli_thread_n_way( jr_thread ); \ dim_t jr_thread_id = bli_thread_work_id( jr_thread ); \ \ /* Loop over the n dimension (NR columns at a time). */ \ for ( j = 0; j < n_iter; ++j ) \ { \ if ( bli_trmm_my_iter( j, jr_thread ) ) { \ \ ctype* restrict a1; \ ctype* restrict c11; \ ctype* restrict b2; \ \ a1 = a_cast; \ c11 = c1; \ \ n_cur = ( bli_is_not_edge_f( j, n_iter, n_left ) ? NR : n_left ); \ \ /* Initialize our next panel of B to be the current panel of B. */ \ b2 = b1; \ \ /* Loop over the m dimension (MR rows at a time). */ \ for ( i = 0; i < m_iter; ++i ) \ { \ diagoffa_i = diagoffa + ( doff_t )i*MR; \ \ m_cur = ( bli_is_not_edge_f( i, m_iter, m_left ) ? MR : m_left ); \ \ /* If the current panel of A intersects the diagonal, scale C by beta. If it is strictly above the diagonal, scale by one. This allows the current macro-kernel to work for both trmm and trmm3. */ \ if ( bli_intersects_diag_n( diagoffa_i, MR, k ) ) \ { \ ctype* restrict b1_i; \ ctype* restrict a2; \ \ /* Determine the offset to and length of the panel that was packed so we can index into the corresponding location in b1. */ \ off_a1112 = diagoffa_i; \ k_a1112 = k - off_a1112; \ \ /* Compute the panel stride for the current diagonal- intersecting micro-panel. */ \ is_a_cur = k_a1112 * PACKMR; \ is_a_cur += ( bli_is_odd( is_a_cur ) ? 1 : 0 ); \ ps_a_cur = ( is_a_cur * ss_a_num ) / ss_a_den; \ \ if ( bli_trmm_my_iter( i, ir_thread ) ) { \ \ b1_i = b1 + ( off_a1112 * PACKNR ) / off_scl; \ \ /* Compute the addresses of the next panels of A and B. */ \ a2 = a1; \ if ( bli_is_last_iter( i, m_iter, 0, 1 ) ) \ { \ a2 = a_cast; \ b2 = b1; \ if ( bli_is_last_iter( j, n_iter, jr_thread_id, jr_num_threads ) ) \ b2 = b_cast; \ } \ \ /* Save addresses of next panels of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_next_a( a2, &aux ); \ bli_auxinfo_set_next_b( b2, &aux ); \ \ /* Save the 4m1/3m1 imaginary stride of A to the auxinfo_t object. */ \ bli_auxinfo_set_is_a( is_a_cur, &aux ); \ \ /* Handle interior and edge cases separately. */ \ if ( m_cur == MR && n_cur == NR ) \ { \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k_a1112, \ alpha_cast, \ a1, \ b1_i, \ beta_cast, \ c11, rs_c, cs_c, \ &aux, \ cntx \ ); \ } \ else \ { \ /* Copy edge elements of C to the temporary buffer. */ \ PASTEMAC(ch,copys_mxn)( m_cur, n_cur, \ c11, rs_c, cs_c, \ ct, rs_ct, cs_ct ); \ \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k_a1112, \ alpha_cast, \ a1, \ b1_i, \ beta_cast, \ ct, rs_ct, cs_ct, \ &aux, \ cntx \ ); \ \ /* Copy the result to the edge of C. */ \ PASTEMAC(ch,copys_mxn)( m_cur, n_cur, \ ct, rs_ct, cs_ct, \ c11, rs_c, cs_c ); \ } \ } \ \ a1 += ps_a_cur; \ } \ else if ( bli_is_strictly_above_diag_n( diagoffa_i, MR, k ) ) \ { \ if ( bli_trmm_my_iter( i, ir_thread ) ) { \ \ ctype* restrict a2; \ \ /* Compute the addresses of the next panels of A and B. */ \ a2 = a1; \ if ( bli_is_last_iter( i, m_iter, 0, 1 ) ) \ { \ a2 = a_cast; \ b2 = b1; \ if ( bli_is_last_iter( j, n_iter, jr_thread_id, jr_num_threads ) ) \ b2 = b_cast; \ } \ \ /* Save addresses of next panels of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_next_a( a2, &aux ); \ bli_auxinfo_set_next_b( b2, &aux ); \ \ /* Save the 4m1/3m1 imaginary stride of A to the auxinfo_t object. */ \ bli_auxinfo_set_is_a( istep_a, &aux ); \ \ /* Handle interior and edge cases separately. */ \ if ( m_cur == MR && n_cur == NR ) \ { \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k, \ alpha_cast, \ a1, \ b1, \ one, \ c11, rs_c, cs_c, \ &aux, \ cntx \ ); \ } \ else \ { \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k, \ alpha_cast, \ a1, \ b1, \ zero, \ ct, rs_ct, cs_ct, \ &aux, \ cntx \ ); \ \ /* Add the result to the edge of C. */ \ PASTEMAC(ch,adds_mxn)( m_cur, n_cur, \ ct, rs_ct, cs_ct, \ c11, rs_c, cs_c ); \ } \ } \ \ a1 += rstep_a; \ } \ \ c11 += rstep_c; \ } \ } \ \ b1 += cstep_b; \ c1 += cstep_c; \ } \ \ /*PASTEMAC(ch,fprintm)( stdout, "trmm_lu_ker_var2: a1", MR, k_a1112, a1, 1, MR, "%4.1f", "" );*/ \ /*PASTEMAC(ch,fprintm)( stdout, "trmm_lu_ker_var2: b1", k_a1112, NR, b1_i, NR, 1, "%4.1f", "" );*/ \ } INSERT_GENTFUNC_BASIC0( trmm_lu_ker_var2 ) blis-0.9.0/frame/3/trmm/other/bli_trmm_lu_ker_var2rr.c000066400000000000000000000412351422157504600226300ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define FUNCPTR_T gemm_fp typedef void (*FUNCPTR_T) ( doff_t diagoffa, pack_t schema_a, pack_t schema_b, dim_t m, dim_t n, dim_t k, void* alpha, void* a, inc_t cs_a, dim_t pd_a, inc_t ps_a, void* b, inc_t rs_b, dim_t pd_b, inc_t ps_b, void* beta, void* c, inc_t rs_c, inc_t cs_c, cntx_t* cntx, rntm_t* rntm, thrinfo_t* thread ); static FUNCPTR_T GENARRAY(ftypes,trmm_lu_ker_var2rr); // // -- Macrokernel functions for round-robin partitioning ----------------------- // void bli_trmm_lu_ker_var2rr ( obj_t* a, obj_t* b, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ) { num_t dt_exec = bli_obj_exec_dt( c ); doff_t diagoffa = bli_obj_diag_offset( a ); pack_t schema_a = bli_obj_pack_schema( a ); pack_t schema_b = bli_obj_pack_schema( b ); dim_t m = bli_obj_length( c ); dim_t n = bli_obj_width( c ); dim_t k = bli_obj_width( a ); void* buf_a = bli_obj_buffer_at_off( a ); inc_t cs_a = bli_obj_col_stride( a ); dim_t pd_a = bli_obj_panel_dim( a ); inc_t ps_a = bli_obj_panel_stride( a ); void* buf_b = bli_obj_buffer_at_off( b ); inc_t rs_b = bli_obj_row_stride( b ); dim_t pd_b = bli_obj_panel_dim( b ); inc_t ps_b = bli_obj_panel_stride( b ); void* buf_c = bli_obj_buffer_at_off( c ); inc_t rs_c = bli_obj_row_stride( c ); inc_t cs_c = bli_obj_col_stride( c ); obj_t scalar_a; obj_t scalar_b; void* buf_alpha; void* buf_beta; FUNCPTR_T f; // Detach and multiply the scalars attached to A and B. bli_obj_scalar_detach( a, &scalar_a ); bli_obj_scalar_detach( b, &scalar_b ); bli_mulsc( &scalar_a, &scalar_b ); // Grab the addresses of the internal scalar buffers for the scalar // merged above and the scalar attached to C. buf_alpha = bli_obj_internal_scalar_buffer( &scalar_b ); buf_beta = bli_obj_internal_scalar_buffer( c ); // Index into the type combination array to extract the correct // function pointer. f = ftypes[dt_exec]; // Invoke the function. f( diagoffa, schema_a, schema_b, m, n, k, buf_alpha, buf_a, cs_a, pd_a, ps_a, buf_b, rs_b, pd_b, ps_b, buf_beta, buf_c, rs_c, cs_c, cntx, rntm, thread ); } #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ doff_t diagoffa, \ pack_t schema_a, \ pack_t schema_b, \ dim_t m, \ dim_t n, \ dim_t k, \ void* alpha, \ void* a, inc_t cs_a, dim_t pd_a, inc_t ps_a, \ void* b, inc_t rs_b, dim_t pd_b, inc_t ps_b, \ void* beta, \ void* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx, \ rntm_t* rntm, \ thrinfo_t* thread \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ /* Alias some constants to simpler names. */ \ const dim_t MR = pd_a; \ const dim_t NR = pd_b; \ const dim_t PACKMR = cs_a; \ const dim_t PACKNR = rs_b; \ \ /* Query the context for the micro-kernel address and cast it to its function pointer type. */ \ PASTECH(ch,gemm_ukr_ft) \ gemm_ukr = bli_cntx_get_l3_vir_ukr_dt( dt, BLIS_GEMM_UKR, cntx ); \ \ /* Temporary C buffer for edge cases. Note that the strides of this temporary buffer are set so that they match the storage of the original C matrix. For example, if C is column-stored, ct will be column-stored as well. */ \ ctype ct[ BLIS_STACK_BUF_MAX_SIZE \ / sizeof( ctype ) ] \ __attribute__((aligned(BLIS_STACK_BUF_ALIGN_SIZE))); \ const bool col_pref = bli_cntx_l3_vir_ukr_prefers_cols_dt( dt, BLIS_GEMM_UKR, cntx ); \ const inc_t rs_ct = ( col_pref ? 1 : NR ); \ const inc_t cs_ct = ( col_pref ? MR : 1 ); \ \ ctype* restrict one = PASTEMAC(ch,1); \ ctype* restrict zero = PASTEMAC(ch,0); \ ctype* restrict a_cast = a; \ ctype* restrict b_cast = b; \ ctype* restrict c_cast = c; \ ctype* restrict alpha_cast = alpha; \ ctype* restrict beta_cast = beta; \ ctype* restrict b1; \ ctype* restrict c1; \ \ doff_t diagoffa_i; \ dim_t k_full; \ dim_t m_iter, m_left; \ dim_t n_iter, n_left; \ dim_t m_cur; \ dim_t n_cur; \ dim_t k_a1112; \ dim_t off_a1112; \ dim_t i, j; \ inc_t rstep_a; \ inc_t cstep_b; \ inc_t rstep_c, cstep_c; \ inc_t istep_a; \ inc_t istep_b; \ inc_t off_scl; \ inc_t ss_a_num; \ inc_t ss_a_den; \ inc_t ps_a_cur; \ inc_t is_a_cur; \ auxinfo_t aux; \ \ /* Assumptions/assertions: rs_a == 1 cs_a == PACKMR pd_a == MR ps_a == stride to next micro-panel of A rs_b == PACKNR cs_b == 1 pd_b == NR ps_b == stride to next micro-panel of B rs_c == (no assumptions) cs_c == (no assumptions) */ \ \ /* Safety trap: Certain indexing within this macro-kernel does not work as intended if both MR and NR are odd. */ \ if ( ( bli_is_odd( PACKMR ) && bli_is_odd( NR ) ) || \ ( bli_is_odd( PACKNR ) && bli_is_odd( MR ) ) ) bli_abort(); \ \ /* If any dimension is zero, return immediately. */ \ if ( bli_zero_dim3( m, n, k ) ) return; \ \ /* Safeguard: If the current block of A is entirely below the diagonal, it is implicitly zero. So we do nothing. */ \ if ( bli_is_strictly_below_diag_n( diagoffa, m, k ) ) return; \ \ /* Compute k_full. For all trmm, k_full is simply k. This is needed because some parameter combinations of trmm reduce k to advance past zero regions in the triangular matrix, and when computing the imaginary stride of B (the non-triangular matrix), which is used by 4m1/3m1 implementations, we need this unreduced value of k. */ \ k_full = k; \ \ /* Compute indexing scaling factor for for 4m or 3m. This is needed because one of the packing register blocksizes (PACKMR or PACKNR) is used to index into the micro-panels of the non- triangular matrix when computing with a diagonal-intersecting micro-panel of the triangular matrix. In the case of 4m or 3m, real values are stored in both sub-panels, and so the indexing needs to occur in units of real values. The value computed here is divided into the complex pointer offset to cause the pointer to be advanced by the correct value. */ \ if ( bli_is_4mi_packed( schema_a ) || \ bli_is_3mi_packed( schema_a ) || \ bli_is_rih_packed( schema_a ) ) off_scl = 2; \ else off_scl = 1; \ \ /* Compute the storage stride scaling. Usually this is just 1. However, in the case of interleaved 3m, we need to scale the offset by 3/2. And if we are packing real-only, imag-only, or summed-only, we need to scale the computed panel sizes by 1/2 to compensate for the fact that the pointer arithmetic occurs in terms of complex elements rather than real elements. */ \ if ( bli_is_3mi_packed( schema_a ) ) { ss_a_num = 3; ss_a_den = 2; } \ else if ( bli_is_rih_packed( schema_a ) ) { ss_a_num = 1; ss_a_den = 2; } \ else { ss_a_num = 1; ss_a_den = 1; } \ \ /* If there is a zero region to the left of where the diagonal of A intersects the top edge of the block, adjust the pointer to B and treat this case as if the diagonal offset were zero. Note that we don't need to adjust the pointer to A since packm would have simply skipped over the region that was not stored. */ \ if ( diagoffa > 0 ) \ { \ i = diagoffa; \ k = k - i; \ diagoffa = 0; \ b_cast = b_cast + ( i * PACKNR ) / off_scl; \ } \ \ /* If there is a zero region below where the diagonal of A intersects the right side of the block, shrink it to prevent "no-op" iterations from executing. */ \ if ( -diagoffa + k < m ) \ { \ m = -diagoffa + k; \ } \ \ /* Clear the temporary C buffer in case it has any infs or NaNs. */ \ PASTEMAC(ch,set0s_mxn)( MR, NR, \ ct, rs_ct, cs_ct ); \ \ /* Compute number of primary and leftover components of the m and n dimensions. */ \ n_iter = n / NR; \ n_left = n % NR; \ \ m_iter = m / MR; \ m_left = m % MR; \ \ if ( n_left ) ++n_iter; \ if ( m_left ) ++m_iter; \ \ /* Determine some increments used to step through A, B, and C. */ \ rstep_a = ps_a; \ \ cstep_b = ps_b; \ \ rstep_c = rs_c * MR; \ cstep_c = cs_c * NR; \ \ istep_a = PACKMR * k; \ istep_b = PACKNR * k_full; \ \ if ( bli_is_odd( istep_a ) ) istep_a += 1; \ if ( bli_is_odd( istep_b ) ) istep_b += 1; \ \ /* Save the pack schemas of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_schema_a( schema_a, &aux ); \ bli_auxinfo_set_schema_b( schema_b, &aux ); \ \ /* Save the imaginary stride of B to the auxinfo_t object. */ \ bli_auxinfo_set_is_b( istep_b, &aux ); \ \ /* The 'thread' argument points to the thrinfo_t node for the 2nd (jr) loop around the microkernel. Here we query the thrinfo_t node for the 1st (ir) loop around the microkernel. */ \ /*thrinfo_t* ir_thread = bli_thrinfo_sub_node( thread );*/ \ \ /* Query the number of threads and thread ids for each loop. */ \ dim_t jr_nt = bli_thread_n_way( thread ); \ dim_t jr_tid = bli_thread_work_id( thread ); \ /*dim_t ir_nt = bli_thread_n_way( ir_thread ); \ dim_t ir_tid = bli_thread_work_id( ir_thread );*/ \ \ dim_t jr_start, jr_end; \ /*dim_t ir_start, ir_end;*/ \ dim_t jr_inc; \ \ /* Use round-robin assignment of micropanels to threads in the 2nd loop for the initial rectangular region of C (if it exists). */ \ bli_thread_range_jrir_rr( thread, n_iter, 1, FALSE, &jr_start, &jr_end, &jr_inc ); \ /*bli_thread_range_jrir_rr( caucus, m_iter, 1, FALSE, &ir_start, &ir_end, &ir_inc );*/ \ \ /* Loop over the n dimension (NR columns at a time). */ \ for ( j = jr_start; j < jr_end; j += jr_inc ) \ { \ ctype* restrict a1; \ ctype* restrict c11; \ ctype* restrict b2; \ \ b1 = b_cast + j * cstep_b; \ c1 = c_cast + j * cstep_c; \ \ n_cur = ( bli_is_not_edge_f( j, n_iter, n_left ) ? NR : n_left ); \ \ /* Initialize our next panel of B to be the current panel of B. */ \ b2 = b1; \ \ a1 = a_cast; \ c11 = c1; \ \ /* Loop over the m dimension (MR rows at a time). */ \ for ( i = 0; i < m_iter; ++i ) \ { \ diagoffa_i = diagoffa + ( doff_t )i*MR; \ \ m_cur = ( bli_is_not_edge_f( i, m_iter, m_left ) ? MR : m_left ); \ \ /* If the current panel of A intersects the diagonal, scale C by beta. If it is strictly above the diagonal, scale by one. This allows the current macro-kernel to work for both trmm and trmm3. */ \ if ( bli_intersects_diag_n( diagoffa_i, MR, k ) ) \ { \ ctype* restrict b1_i; \ ctype* restrict a2; \ \ /* Determine the offset to and length of the panel that was packed so we can index into the corresponding location in b1. */ \ off_a1112 = diagoffa_i; \ k_a1112 = k - off_a1112; \ \ /* Compute the panel stride for the current diagonal- intersecting micro-panel. */ \ is_a_cur = k_a1112 * PACKMR; \ is_a_cur += ( bli_is_odd( is_a_cur ) ? 1 : 0 ); \ ps_a_cur = ( is_a_cur * ss_a_num ) / ss_a_den; \ \ /* NOTE: ir loop parallelism disabled for now. */ \ /*if ( bli_trmm_my_iter( i, ir_thread ) ) {*/ \ \ b1_i = b1 + ( off_a1112 * PACKNR ) / off_scl; \ \ /* Compute the addresses of the next panels of A and B. */ \ a2 = a1; \ if ( bli_is_last_iter_rr( i, m_iter, 0, 1 ) ) \ { \ a2 = a_cast; \ b2 = b1; \ if ( bli_is_last_iter_rr( j, n_iter, jr_tid, jr_nt ) ) \ b2 = b_cast; \ } \ \ /* Save addresses of next panels of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_next_a( a2, &aux ); \ bli_auxinfo_set_next_b( b2, &aux ); \ \ /* Save the 4m1/3m1 imaginary stride of A to the auxinfo_t object. */ \ bli_auxinfo_set_is_a( is_a_cur, &aux ); \ \ /* Handle interior and edge cases separately. */ \ if ( m_cur == MR && n_cur == NR ) \ { \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k_a1112, \ alpha_cast, \ a1, \ b1_i, \ beta_cast, \ c11, rs_c, cs_c, \ &aux, \ cntx \ ); \ } \ else \ { \ /* Copy edge elements of C to the temporary buffer. */ \ PASTEMAC(ch,copys_mxn)( m_cur, n_cur, \ c11, rs_c, cs_c, \ ct, rs_ct, cs_ct ); \ \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k_a1112, \ alpha_cast, \ a1, \ b1_i, \ beta_cast, \ ct, rs_ct, cs_ct, \ &aux, \ cntx \ ); \ \ /* Copy the result to the edge of C. */ \ PASTEMAC(ch,copys_mxn)( m_cur, n_cur, \ ct, rs_ct, cs_ct, \ c11, rs_c, cs_c ); \ } \ /*}*/ \ \ a1 += ps_a_cur; \ } \ else if ( bli_is_strictly_above_diag_n( diagoffa_i, MR, k ) ) \ { \ /* NOTE: ir loop parallelism disabled for now. */ \ /*if ( bli_trmm_my_iter( i, ir_thread ) ) {*/ \ \ ctype* restrict a2; \ \ /* Compute the addresses of the next panels of A and B. */ \ a2 = a1; \ if ( bli_is_last_iter_rr( i, m_iter, 0, 1 ) ) \ { \ a2 = a_cast; \ b2 = b1; \ if ( bli_is_last_iter_rr( j, n_iter, jr_tid, jr_nt ) ) \ b2 = b_cast; \ } \ \ /* Save addresses of next panels of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_next_a( a2, &aux ); \ bli_auxinfo_set_next_b( b2, &aux ); \ \ /* Save the 4m1/3m1 imaginary stride of A to the auxinfo_t object. */ \ bli_auxinfo_set_is_a( istep_a, &aux ); \ \ /* Handle interior and edge cases separately. */ \ if ( m_cur == MR && n_cur == NR ) \ { \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k, \ alpha_cast, \ a1, \ b1, \ one, \ c11, rs_c, cs_c, \ &aux, \ cntx \ ); \ } \ else \ { \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k, \ alpha_cast, \ a1, \ b1, \ zero, \ ct, rs_ct, cs_ct, \ &aux, \ cntx \ ); \ \ /* Add the result to the edge of C. */ \ PASTEMAC(ch,adds_mxn)( m_cur, n_cur, \ ct, rs_ct, cs_ct, \ c11, rs_c, cs_c ); \ } \ /*}*/ \ \ a1 += rstep_a; \ } \ \ c11 += rstep_c; \ } \ } \ \ /*PASTEMAC(ch,fprintm)( stdout, "trmm_lu_ker_var2rr: a1", MR, k_a1112, a1, 1, MR, "%4.1f", "" );*/ \ /*PASTEMAC(ch,fprintm)( stdout, "trmm_lu_ker_var2rr: b1", k_a1112, NR, b1_i, NR, 1, "%4.1f", "" );*/ \ } INSERT_GENTFUNC_BASIC0( trmm_lu_ker_var2rr ) blis-0.9.0/frame/3/trmm/other/bli_trmm_lu_ker_var2sl.c000066400000000000000000000412261422157504600226230ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define FUNCPTR_T gemm_fp typedef void (*FUNCPTR_T) ( doff_t diagoffa, pack_t schema_a, pack_t schema_b, dim_t m, dim_t n, dim_t k, void* alpha, void* a, inc_t cs_a, dim_t pd_a, inc_t ps_a, void* b, inc_t rs_b, dim_t pd_b, inc_t ps_b, void* beta, void* c, inc_t rs_c, inc_t cs_c, cntx_t* cntx, rntm_t* rntm, thrinfo_t* thread ); static FUNCPTR_T GENARRAY(ftypes,trmm_lu_ker_var2sl); // // -- Macrokernel functions for slab partitioning ------------------------------ // void bli_trmm_lu_ker_var2sl ( obj_t* a, obj_t* b, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ) { num_t dt_exec = bli_obj_exec_dt( c ); doff_t diagoffa = bli_obj_diag_offset( a ); pack_t schema_a = bli_obj_pack_schema( a ); pack_t schema_b = bli_obj_pack_schema( b ); dim_t m = bli_obj_length( c ); dim_t n = bli_obj_width( c ); dim_t k = bli_obj_width( a ); void* buf_a = bli_obj_buffer_at_off( a ); inc_t cs_a = bli_obj_col_stride( a ); dim_t pd_a = bli_obj_panel_dim( a ); inc_t ps_a = bli_obj_panel_stride( a ); void* buf_b = bli_obj_buffer_at_off( b ); inc_t rs_b = bli_obj_row_stride( b ); dim_t pd_b = bli_obj_panel_dim( b ); inc_t ps_b = bli_obj_panel_stride( b ); void* buf_c = bli_obj_buffer_at_off( c ); inc_t rs_c = bli_obj_row_stride( c ); inc_t cs_c = bli_obj_col_stride( c ); obj_t scalar_a; obj_t scalar_b; void* buf_alpha; void* buf_beta; FUNCPTR_T f; // Detach and multiply the scalars attached to A and B. bli_obj_scalar_detach( a, &scalar_a ); bli_obj_scalar_detach( b, &scalar_b ); bli_mulsc( &scalar_a, &scalar_b ); // Grab the addresses of the internal scalar buffers for the scalar // merged above and the scalar attached to C. buf_alpha = bli_obj_internal_scalar_buffer( &scalar_b ); buf_beta = bli_obj_internal_scalar_buffer( c ); // Index into the type combination array to extract the correct // function pointer. f = ftypes[dt_exec]; // Invoke the function. f( diagoffa, schema_a, schema_b, m, n, k, buf_alpha, buf_a, cs_a, pd_a, ps_a, buf_b, rs_b, pd_b, ps_b, buf_beta, buf_c, rs_c, cs_c, cntx, rntm, thread ); } #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ doff_t diagoffa, \ pack_t schema_a, \ pack_t schema_b, \ dim_t m, \ dim_t n, \ dim_t k, \ void* alpha, \ void* a, inc_t cs_a, dim_t pd_a, inc_t ps_a, \ void* b, inc_t rs_b, dim_t pd_b, inc_t ps_b, \ void* beta, \ void* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx, \ rntm_t* rntm, \ thrinfo_t* thread \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ /* Alias some constants to simpler names. */ \ const dim_t MR = pd_a; \ const dim_t NR = pd_b; \ const dim_t PACKMR = cs_a; \ const dim_t PACKNR = rs_b; \ \ /* Query the context for the micro-kernel address and cast it to its function pointer type. */ \ PASTECH(ch,gemm_ukr_ft) \ gemm_ukr = bli_cntx_get_l3_vir_ukr_dt( dt, BLIS_GEMM_UKR, cntx ); \ \ /* Temporary C buffer for edge cases. Note that the strides of this temporary buffer are set so that they match the storage of the original C matrix. For example, if C is column-stored, ct will be column-stored as well. */ \ ctype ct[ BLIS_STACK_BUF_MAX_SIZE \ / sizeof( ctype ) ] \ __attribute__((aligned(BLIS_STACK_BUF_ALIGN_SIZE))); \ const bool col_pref = bli_cntx_l3_vir_ukr_prefers_cols_dt( dt, BLIS_GEMM_UKR, cntx ); \ const inc_t rs_ct = ( col_pref ? 1 : NR ); \ const inc_t cs_ct = ( col_pref ? MR : 1 ); \ \ ctype* restrict one = PASTEMAC(ch,1); \ ctype* restrict zero = PASTEMAC(ch,0); \ ctype* restrict a_cast = a; \ ctype* restrict b_cast = b; \ ctype* restrict c_cast = c; \ ctype* restrict alpha_cast = alpha; \ ctype* restrict beta_cast = beta; \ ctype* restrict b1; \ ctype* restrict c1; \ \ doff_t diagoffa_i; \ dim_t k_full; \ dim_t m_iter, m_left; \ dim_t n_iter, n_left; \ dim_t m_cur; \ dim_t n_cur; \ dim_t k_a1112; \ dim_t off_a1112; \ dim_t i, j; \ inc_t rstep_a; \ inc_t cstep_b; \ inc_t rstep_c, cstep_c; \ inc_t istep_a; \ inc_t istep_b; \ inc_t off_scl; \ inc_t ss_a_num; \ inc_t ss_a_den; \ inc_t ps_a_cur; \ inc_t is_a_cur; \ auxinfo_t aux; \ \ /* Assumptions/assertions: rs_a == 1 cs_a == PACKMR pd_a == MR ps_a == stride to next micro-panel of A rs_b == PACKNR cs_b == 1 pd_b == NR ps_b == stride to next micro-panel of B rs_c == (no assumptions) cs_c == (no assumptions) */ \ \ /* Safety trap: Certain indexing within this macro-kernel does not work as intended if both MR and NR are odd. */ \ if ( ( bli_is_odd( PACKMR ) && bli_is_odd( NR ) ) || \ ( bli_is_odd( PACKNR ) && bli_is_odd( MR ) ) ) bli_abort(); \ \ /* If any dimension is zero, return immediately. */ \ if ( bli_zero_dim3( m, n, k ) ) return; \ \ /* Safeguard: If the current block of A is entirely below the diagonal, it is implicitly zero. So we do nothing. */ \ if ( bli_is_strictly_below_diag_n( diagoffa, m, k ) ) return; \ \ /* Compute k_full. For all trmm, k_full is simply k. This is needed because some parameter combinations of trmm reduce k to advance past zero regions in the triangular matrix, and when computing the imaginary stride of B (the non-triangular matrix), which is used by 4m1/3m1 implementations, we need this unreduced value of k. */ \ k_full = k; \ \ /* Compute indexing scaling factor for for 4m or 3m. This is needed because one of the packing register blocksizes (PACKMR or PACKNR) is used to index into the micro-panels of the non- triangular matrix when computing with a diagonal-intersecting micro-panel of the triangular matrix. In the case of 4m or 3m, real values are stored in both sub-panels, and so the indexing needs to occur in units of real values. The value computed here is divided into the complex pointer offset to cause the pointer to be advanced by the correct value. */ \ if ( bli_is_4mi_packed( schema_a ) || \ bli_is_3mi_packed( schema_a ) || \ bli_is_rih_packed( schema_a ) ) off_scl = 2; \ else off_scl = 1; \ \ /* Compute the storage stride scaling. Usually this is just 1. However, in the case of interleaved 3m, we need to scale the offset by 3/2. And if we are packing real-only, imag-only, or summed-only, we need to scale the computed panel sizes by 1/2 to compensate for the fact that the pointer arithmetic occurs in terms of complex elements rather than real elements. */ \ if ( bli_is_3mi_packed( schema_a ) ) { ss_a_num = 3; ss_a_den = 2; } \ else if ( bli_is_rih_packed( schema_a ) ) { ss_a_num = 1; ss_a_den = 2; } \ else { ss_a_num = 1; ss_a_den = 1; } \ \ /* If there is a zero region to the left of where the diagonal of A intersects the top edge of the block, adjust the pointer to B and treat this case as if the diagonal offset were zero. Note that we don't need to adjust the pointer to A since packm would have simply skipped over the region that was not stored. */ \ if ( diagoffa > 0 ) \ { \ i = diagoffa; \ k = k - i; \ diagoffa = 0; \ b_cast = b_cast + ( i * PACKNR ) / off_scl; \ } \ \ /* If there is a zero region below where the diagonal of A intersects the right side of the block, shrink it to prevent "no-op" iterations from executing. */ \ if ( -diagoffa + k < m ) \ { \ m = -diagoffa + k; \ } \ \ /* Clear the temporary C buffer in case it has any infs or NaNs. */ \ PASTEMAC(ch,set0s_mxn)( MR, NR, \ ct, rs_ct, cs_ct ); \ \ /* Compute number of primary and leftover components of the m and n dimensions. */ \ n_iter = n / NR; \ n_left = n % NR; \ \ m_iter = m / MR; \ m_left = m % MR; \ \ if ( n_left ) ++n_iter; \ if ( m_left ) ++m_iter; \ \ /* Determine some increments used to step through A, B, and C. */ \ rstep_a = ps_a; \ \ cstep_b = ps_b; \ \ rstep_c = rs_c * MR; \ cstep_c = cs_c * NR; \ \ istep_a = PACKMR * k; \ istep_b = PACKNR * k_full; \ \ if ( bli_is_odd( istep_a ) ) istep_a += 1; \ if ( bli_is_odd( istep_b ) ) istep_b += 1; \ \ /* Save the pack schemas of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_schema_a( schema_a, &aux ); \ bli_auxinfo_set_schema_b( schema_b, &aux ); \ \ /* Save the imaginary stride of B to the auxinfo_t object. */ \ bli_auxinfo_set_is_b( istep_b, &aux ); \ \ /* The 'thread' argument points to the thrinfo_t node for the 2nd (jr) loop around the microkernel. Here we query the thrinfo_t node for the 1st (ir) loop around the microkernel. */ \ /*thrinfo_t* ir_thread = bli_thrinfo_sub_node( thread );*/ \ \ /* Query the number of threads and thread ids for each loop. */ \ dim_t jr_nt = bli_thread_n_way( thread ); \ dim_t jr_tid = bli_thread_work_id( thread ); \ /*dim_t ir_nt = bli_thread_n_way( ir_thread ); \ dim_t ir_tid = bli_thread_work_id( ir_thread );*/ \ \ dim_t jr_start, jr_end; \ /*dim_t ir_start, ir_end;*/ \ dim_t jr_inc; \ \ /* Use slab assignment of micropanels to threads in the 2nd loop for the initial rectangular region of C (if it exists). */ \ bli_thread_range_jrir_sl( thread, n_iter, 1, FALSE, &jr_start, &jr_end, &jr_inc ); \ /*bli_thread_range_jrir_rr( caucus, m_iter, 1, FALSE, &ir_start, &ir_end, &ir_inc );*/ \ \ /* Loop over the n dimension (NR columns at a time). */ \ for ( j = jr_start; j < jr_end; j += jr_inc ) \ { \ ctype* restrict a1; \ ctype* restrict c11; \ ctype* restrict b2; \ \ b1 = b_cast + j * cstep_b; \ c1 = c_cast + j * cstep_c; \ \ n_cur = ( bli_is_not_edge_f( j, n_iter, n_left ) ? NR : n_left ); \ \ /* Initialize our next panel of B to be the current panel of B. */ \ b2 = b1; \ \ a1 = a_cast; \ c11 = c1; \ \ /* Loop over the m dimension (MR rows at a time). */ \ for ( i = 0; i < m_iter; ++i ) \ { \ diagoffa_i = diagoffa + ( doff_t )i*MR; \ \ m_cur = ( bli_is_not_edge_f( i, m_iter, m_left ) ? MR : m_left ); \ \ /* If the current panel of A intersects the diagonal, scale C by beta. If it is strictly above the diagonal, scale by one. This allows the current macro-kernel to work for both trmm and trmm3. */ \ if ( bli_intersects_diag_n( diagoffa_i, MR, k ) ) \ { \ ctype* restrict b1_i; \ ctype* restrict a2; \ \ /* Determine the offset to and length of the panel that was packed so we can index into the corresponding location in b1. */ \ off_a1112 = diagoffa_i; \ k_a1112 = k - off_a1112; \ \ /* Compute the panel stride for the current diagonal- intersecting micro-panel. */ \ is_a_cur = k_a1112 * PACKMR; \ is_a_cur += ( bli_is_odd( is_a_cur ) ? 1 : 0 ); \ ps_a_cur = ( is_a_cur * ss_a_num ) / ss_a_den; \ \ /* NOTE: ir loop parallelism disabled for now. */ \ /*if ( bli_trmm_my_iter( i, ir_thread ) ) {*/ \ \ b1_i = b1 + ( off_a1112 * PACKNR ) / off_scl; \ \ /* Compute the addresses of the next panels of A and B. */ \ a2 = a1; \ if ( bli_is_last_iter_rr( i, m_iter, 0, 1 ) ) \ { \ a2 = a_cast; \ b2 = b1; \ if ( bli_is_last_iter_sl( j, n_iter, jr_tid, jr_nt ) ) \ b2 = b_cast; \ } \ \ /* Save addresses of next panels of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_next_a( a2, &aux ); \ bli_auxinfo_set_next_b( b2, &aux ); \ \ /* Save the 4m1/3m1 imaginary stride of A to the auxinfo_t object. */ \ bli_auxinfo_set_is_a( is_a_cur, &aux ); \ \ /* Handle interior and edge cases separately. */ \ if ( m_cur == MR && n_cur == NR ) \ { \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k_a1112, \ alpha_cast, \ a1, \ b1_i, \ beta_cast, \ c11, rs_c, cs_c, \ &aux, \ cntx \ ); \ } \ else \ { \ /* Copy edge elements of C to the temporary buffer. */ \ PASTEMAC(ch,copys_mxn)( m_cur, n_cur, \ c11, rs_c, cs_c, \ ct, rs_ct, cs_ct ); \ \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k_a1112, \ alpha_cast, \ a1, \ b1_i, \ beta_cast, \ ct, rs_ct, cs_ct, \ &aux, \ cntx \ ); \ \ /* Copy the result to the edge of C. */ \ PASTEMAC(ch,copys_mxn)( m_cur, n_cur, \ ct, rs_ct, cs_ct, \ c11, rs_c, cs_c ); \ } \ /*}*/ \ \ a1 += ps_a_cur; \ } \ else if ( bli_is_strictly_above_diag_n( diagoffa_i, MR, k ) ) \ { \ /* NOTE: ir loop parallelism disabled for now. */ \ /*if ( bli_trmm_my_iter( i, ir_thread ) ) {*/ \ \ ctype* restrict a2; \ \ /* Compute the addresses of the next panels of A and B. */ \ a2 = a1; \ if ( bli_is_last_iter_rr( i, m_iter, 0, 1 ) ) \ { \ a2 = a_cast; \ b2 = b1; \ if ( bli_is_last_iter_sl( j, n_iter, jr_tid, jr_nt ) ) \ b2 = b_cast; \ } \ \ /* Save addresses of next panels of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_next_a( a2, &aux ); \ bli_auxinfo_set_next_b( b2, &aux ); \ \ /* Save the 4m1/3m1 imaginary stride of A to the auxinfo_t object. */ \ bli_auxinfo_set_is_a( istep_a, &aux ); \ \ /* Handle interior and edge cases separately. */ \ if ( m_cur == MR && n_cur == NR ) \ { \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k, \ alpha_cast, \ a1, \ b1, \ one, \ c11, rs_c, cs_c, \ &aux, \ cntx \ ); \ } \ else \ { \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k, \ alpha_cast, \ a1, \ b1, \ zero, \ ct, rs_ct, cs_ct, \ &aux, \ cntx \ ); \ \ /* Add the result to the edge of C. */ \ PASTEMAC(ch,adds_mxn)( m_cur, n_cur, \ ct, rs_ct, cs_ct, \ c11, rs_c, cs_c ); \ } \ /*}*/ \ \ a1 += rstep_a; \ } \ \ c11 += rstep_c; \ } \ } \ \ /*PASTEMAC(ch,fprintm)( stdout, "trmm_lu_ker_var2sl: a1", MR, k_a1112, a1, 1, MR, "%4.1f", "" );*/ \ /*PASTEMAC(ch,fprintm)( stdout, "trmm_lu_ker_var2sl: b1", k_a1112, NR, b1_i, NR, 1, "%4.1f", "" );*/ \ } INSERT_GENTFUNC_BASIC0( trmm_lu_ker_var2sl ) blis-0.9.0/frame/3/trmm/other/bli_trmm_rl_ker_var2.c000066400000000000000000000401511422157504600222550ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define FUNCPTR_T gemm_fp typedef void (*FUNCPTR_T) ( doff_t diagoffb, pack_t schema_a, pack_t schema_b, dim_t m, dim_t n, dim_t k, void* alpha, void* a, inc_t cs_a, dim_t pd_a, inc_t ps_a, void* b, inc_t rs_b, dim_t pd_b, inc_t ps_b, void* beta, void* c, inc_t rs_c, inc_t cs_c, cntx_t* cntx, rntm_t* rntm, thrinfo_t* thread ); static FUNCPTR_T GENARRAY(ftypes,trmm_rl_ker_var2); void bli_trmm_rl_ker_var2 ( obj_t* a, obj_t* b, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ) { num_t dt_exec = bli_obj_exec_dt( c ); doff_t diagoffb = bli_obj_diag_offset( b ); pack_t schema_a = bli_obj_pack_schema( a ); pack_t schema_b = bli_obj_pack_schema( b ); dim_t m = bli_obj_length( c ); dim_t n = bli_obj_width( c ); dim_t k = bli_obj_width( a ); void* buf_a = bli_obj_buffer_at_off( a ); inc_t cs_a = bli_obj_col_stride( a ); dim_t pd_a = bli_obj_panel_dim( a ); inc_t ps_a = bli_obj_panel_stride( a ); void* buf_b = bli_obj_buffer_at_off( b ); inc_t rs_b = bli_obj_row_stride( b ); dim_t pd_b = bli_obj_panel_dim( b ); inc_t ps_b = bli_obj_panel_stride( b ); void* buf_c = bli_obj_buffer_at_off( c ); inc_t rs_c = bli_obj_row_stride( c ); inc_t cs_c = bli_obj_col_stride( c ); obj_t scalar_a; obj_t scalar_b; void* buf_alpha; void* buf_beta; FUNCPTR_T f; // Detach and multiply the scalars attached to A and B. bli_obj_scalar_detach( a, &scalar_a ); bli_obj_scalar_detach( b, &scalar_b ); bli_mulsc( &scalar_a, &scalar_b ); // Grab the addresses of the internal scalar buffers for the scalar // merged above and the scalar attached to C. buf_alpha = bli_obj_internal_scalar_buffer( &scalar_b ); buf_beta = bli_obj_internal_scalar_buffer( c ); // Index into the type combination array to extract the correct // function pointer. f = ftypes[dt_exec]; // Invoke the function. f( diagoffb, schema_a, schema_b, m, n, k, buf_alpha, buf_a, cs_a, pd_a, ps_a, buf_b, rs_b, pd_b, ps_b, buf_beta, buf_c, rs_c, cs_c, cntx, rntm, thread ); } #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ doff_t diagoffb, \ pack_t schema_a, \ pack_t schema_b, \ dim_t m, \ dim_t n, \ dim_t k, \ void* alpha, \ void* a, inc_t cs_a, dim_t pd_a, inc_t ps_a, \ void* b, inc_t rs_b, dim_t pd_b, inc_t ps_b, \ void* beta, \ void* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx, \ rntm_t* rntm, \ thrinfo_t* jr_thread \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ /* Alias some constants to simpler names. */ \ const dim_t MR = pd_a; \ const dim_t NR = pd_b; \ const dim_t PACKMR = cs_a; \ const dim_t PACKNR = rs_b; \ \ /* Query the context for the micro-kernel address and cast it to its function pointer type. */ \ PASTECH(ch,gemm_ukr_ft) \ gemm_ukr = bli_cntx_get_l3_vir_ukr_dt( dt, BLIS_GEMM_UKR, cntx ); \ \ /* Temporary C buffer for edge cases. Note that the strides of this temporary buffer are set so that they match the storage of the original C matrix. For example, if C is column-stored, ct will be column-stored as well. */ \ ctype ct[ BLIS_STACK_BUF_MAX_SIZE \ / sizeof( ctype ) ] \ __attribute__((aligned(BLIS_STACK_BUF_ALIGN_SIZE))); \ const bool col_pref = bli_cntx_l3_vir_ukr_prefers_cols_dt( dt, BLIS_GEMM_UKR, cntx ); \ const inc_t rs_ct = ( col_pref ? 1 : NR ); \ const inc_t cs_ct = ( col_pref ? MR : 1 ); \ \ ctype* restrict one = PASTEMAC(ch,1); \ ctype* restrict zero = PASTEMAC(ch,0); \ ctype* restrict a_cast = a; \ ctype* restrict b_cast = b; \ ctype* restrict c_cast = c; \ ctype* restrict alpha_cast = alpha; \ ctype* restrict beta_cast = beta; \ ctype* restrict b1; \ ctype* restrict c1; \ \ doff_t diagoffb_j; \ dim_t k_full; \ dim_t m_iter, m_left; \ dim_t n_iter, n_left; \ dim_t m_cur; \ dim_t n_cur; \ dim_t k_b1121; \ dim_t off_b1121; \ dim_t i, j; \ inc_t rstep_a; \ inc_t cstep_b; \ inc_t rstep_c, cstep_c; \ inc_t istep_a; \ inc_t istep_b; \ inc_t off_scl; \ inc_t ss_b_num; \ inc_t ss_b_den; \ inc_t ps_b_cur; \ inc_t is_b_cur; \ auxinfo_t aux; \ \ /* Assumptions/assertions: rs_a == 1 cs_a == PACKMR pd_a == MR ps_a == stride to next micro-panel of A rs_b == PACKNR cs_b == 1 pd_b == NR ps_b == stride to next micro-panel of B rs_c == (no assumptions) cs_c == (no assumptions) */ \ \ /* Safety trap: Certain indexing within this macro-kernel does not work as intended if both MR and NR are odd. */ \ if ( ( bli_is_odd( PACKMR ) && bli_is_odd( NR ) ) || \ ( bli_is_odd( PACKNR ) && bli_is_odd( MR ) ) ) bli_abort(); \ \ /* If any dimension is zero, return immediately. */ \ if ( bli_zero_dim3( m, n, k ) ) return; \ \ /* Safeguard: If the current panel of B is entirely above the diagonal, it is implicitly zero. So we do nothing. */ \ if ( bli_is_strictly_above_diag_n( diagoffb, k, n ) ) return; \ \ /* Compute k_full. For all trmm, k_full is simply k. This is needed because some parameter combinations of trmm reduce k to advance past zero regions in the triangular matrix, and when computing the imaginary stride of A (the non-triangular matrix), which is used by 4m1/3m1 implementations, we need this unreduced value of k. */ \ k_full = k; \ \ /* Compute indexing scaling factor for for 4m or 3m. This is needed because one of the packing register blocksizes (PACKMR or PACKNR) is used to index into the micro-panels of the non- triangular matrix when computing with a diagonal-intersecting micro-panel of the triangular matrix. In the case of 4m or 3m, real values are stored in both sub-panels, and so the indexing needs to occur in units of real values. The value computed here is divided into the complex pointer offset to cause the pointer to be advanced by the correct value. */ \ if ( bli_is_4mi_packed( schema_b ) || \ bli_is_3mi_packed( schema_b ) || \ bli_is_rih_packed( schema_b ) ) off_scl = 2; \ else off_scl = 1; \ \ /* Compute the storage stride scaling. Usually this is just 1. However, in the case of interleaved 3m, we need to scale the offset by 3/2. And if we are packing real-only, imag-only, or summed-only, we need to scale the computed panel sizes by 1/2 to compensate for the fact that the pointer arithmetic occurs in terms of complex elements rather than real elements. */ \ if ( bli_is_3mi_packed( schema_b ) ) { ss_b_num = 3; ss_b_den = 2; } \ else if ( bli_is_rih_packed( schema_b ) ) { ss_b_num = 1; ss_b_den = 2; } \ else { ss_b_num = 1; ss_b_den = 1; } \ \ /* If there is a zero region above where the diagonal of B intersects the left edge of the panel, adjust the pointer to A and treat this case as if the diagonal offset were zero. Note that we don't need to adjust the pointer to B since packm would have simply skipped over the region that was not stored. */ \ if ( diagoffb < 0 ) \ { \ j = -diagoffb; \ k = k - j; \ diagoffb = 0; \ a_cast = a_cast + ( j * PACKMR ) / off_scl; \ } \ \ /* If there is a zero region to the right of where the diagonal of B intersects the bottom of the panel, shrink it to prevent "no-op" iterations from executing. */ \ if ( diagoffb + k < n ) \ { \ n = diagoffb + k; \ } \ \ /* Clear the temporary C buffer in case it has any infs or NaNs. */ \ PASTEMAC(ch,set0s_mxn)( MR, NR, \ ct, rs_ct, cs_ct ); \ \ /* Compute number of primary and leftover components of the m and n dimensions. */ \ n_iter = n / NR; \ n_left = n % NR; \ \ m_iter = m / MR; \ m_left = m % MR; \ \ if ( n_left ) ++n_iter; \ if ( m_left ) ++m_iter; \ \ /* Determine some increments used to step through A, B, and C. */ \ rstep_a = ps_a; \ \ cstep_b = ps_b; \ \ rstep_c = rs_c * MR; \ cstep_c = cs_c * NR; \ \ istep_a = PACKMR * k_full; \ istep_b = PACKNR * k; \ \ if ( bli_is_odd( istep_a ) ) istep_a += 1; \ if ( bli_is_odd( istep_b ) ) istep_b += 1; \ \ /* Save the pack schemas of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_schema_a( schema_a, &aux ); \ bli_auxinfo_set_schema_b( schema_b, &aux ); \ \ /* Save the imaginary stride of A to the auxinfo_t object. */ \ bli_auxinfo_set_is_a( istep_a, &aux ); \ \ b1 = b_cast; \ c1 = c_cast; \ \ thrinfo_t* ir_thread = bli_thrinfo_sub_node( jr_thread ); \ dim_t jr_num_threads = bli_thread_n_way( jr_thread ); \ dim_t jr_thread_id = bli_thread_work_id( jr_thread ); \ \ /* Loop over the n dimension (NR columns at a time). */ \ for ( j = 0; j < n_iter; ++j ) \ { \ ctype* restrict a1; \ ctype* restrict c11; \ ctype* restrict b2; \ \ diagoffb_j = diagoffb - ( doff_t )j*NR; \ \ /* Determine the offset to the beginning of the panel that was packed so we can index into the corresponding location in A. Then compute the length of that panel. */ \ off_b1121 = bli_max( -diagoffb_j, 0 ); \ k_b1121 = k - off_b1121; \ \ a1 = a_cast; \ c11 = c1; \ \ n_cur = ( bli_is_not_edge_f( j, n_iter, n_left ) ? NR : n_left ); \ \ /* Initialize our next panel of B to be the current panel of B. */ \ b2 = b1; \ \ /* If the current panel of B intersects the diagonal, scale C by beta. If it is strictly below the diagonal, scale by one. This allows the current macro-kernel to work for both trmm and trmm3. */ \ if ( bli_intersects_diag_n( diagoffb_j, k, NR ) ) \ { \ /* Compute the panel stride for the current diagonal- intersecting micro-panel. */ \ is_b_cur = k_b1121 * PACKNR; \ is_b_cur += ( bli_is_odd( is_b_cur ) ? 1 : 0 ); \ ps_b_cur = ( is_b_cur * ss_b_num ) / ss_b_den; \ \ if ( bli_trmm_my_iter( j, jr_thread ) ) { \ \ /* Save the 4m1/3m1 imaginary stride of B to the auxinfo_t object. */ \ bli_auxinfo_set_is_b( is_b_cur, &aux ); \ \ /* Loop over the m dimension (MR rows at a time). */ \ for ( i = 0; i < m_iter; ++i ) \ { \ if ( bli_trmm_my_iter( i, ir_thread ) ) { \ \ ctype* restrict a1_i; \ ctype* restrict a2; \ \ m_cur = ( bli_is_not_edge_f( i, m_iter, m_left ) ? MR : m_left ); \ \ a1_i = a1 + ( off_b1121 * PACKMR ) / off_scl; \ \ /* Compute the addresses of the next panels of A and B. */ \ a2 = a1; \ if ( bli_is_last_iter( i, m_iter, 0, 1 ) ) \ { \ a2 = a_cast; \ b2 = b1; \ if ( bli_is_last_iter( j, n_iter, jr_thread_id, jr_num_threads ) ) \ b2 = b_cast; \ } \ \ /* Save addresses of next panels of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_next_a( a2, &aux ); \ bli_auxinfo_set_next_b( b2, &aux ); \ \ /* Handle interior and edge cases separately. */ \ if ( m_cur == MR && n_cur == NR ) \ { \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k_b1121, \ alpha_cast, \ a1_i, \ b1, \ beta_cast, \ c11, rs_c, cs_c, \ &aux, \ cntx \ ); \ } \ else \ { \ /* Copy edge elements of C to the temporary buffer. */ \ PASTEMAC(ch,copys_mxn)( m_cur, n_cur, \ c11, rs_c, cs_c, \ ct, rs_ct, cs_ct ); \ \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k_b1121, \ alpha_cast, \ a1_i, \ b1, \ beta_cast, \ ct, rs_ct, cs_ct, \ &aux, \ cntx \ ); \ \ /* Copy the result to the edge of C. */ \ PASTEMAC(ch,copys_mxn)( m_cur, n_cur, \ ct, rs_ct, cs_ct, \ c11, rs_c, cs_c ); \ } \ } \ \ a1 += rstep_a; \ c11 += rstep_c; \ } \ } \ \ b1 += ps_b_cur; \ } \ else if ( bli_is_strictly_below_diag_n( diagoffb_j, k, NR ) ) \ { \ if ( bli_trmm_my_iter( j, jr_thread ) ) { \ \ /* Save the 4m1/3m1 imaginary stride of B to the auxinfo_t object. */ \ bli_auxinfo_set_is_b( istep_b, &aux ); \ \ /* Loop over the m dimension (MR rows at a time). */ \ for ( i = 0; i < m_iter; ++i ) \ { \ if ( bli_trmm_my_iter( i, ir_thread ) ) { \ \ ctype* restrict a2; \ \ m_cur = ( bli_is_not_edge_f( i, m_iter, m_left ) ? MR : m_left ); \ \ /* Compute the addresses of the next panels of A and B. */ \ a2 = a1; \ if ( bli_is_last_iter( i, m_iter, 0, 1 ) ) \ { \ a2 = a_cast; \ b2 = b1; \ if ( bli_is_last_iter( j, n_iter, jr_thread_id, jr_num_threads ) ) \ b2 = b_cast; \ } \ \ /* Save addresses of next panels of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_next_a( a2, &aux ); \ bli_auxinfo_set_next_b( b2, &aux ); \ \ /* Handle interior and edge cases separately. */ \ if ( m_cur == MR && n_cur == NR ) \ { \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k, \ alpha_cast, \ a1, \ b1, \ one, \ c11, rs_c, cs_c, \ &aux, \ cntx \ ); \ } \ else \ { \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k, \ alpha_cast, \ a1, \ b1, \ zero, \ ct, rs_ct, cs_ct, \ &aux, \ cntx \ ); \ \ /* Add the result to the edge of C. */ \ PASTEMAC(ch,adds_mxn)( m_cur, n_cur, \ ct, rs_ct, cs_ct, \ c11, rs_c, cs_c ); \ } \ } \ \ a1 += rstep_a; \ c11 += rstep_c; \ } \ } \ \ b1 += cstep_b; \ } \ \ c1 += cstep_c; \ } \ \ /*PASTEMAC(ch,fprintm)( stdout, "trmm_rl_ker_var2: a1", MR, k_b1121, a1, 1, MR, "%4.1f", "" );*/ \ /*PASTEMAC(ch,fprintm)( stdout, "trmm_rl_ker_var2: b1", k_b1121, NR, b1_i, NR, 1, "%4.1f", "" );*/ \ } INSERT_GENTFUNC_BASIC0( trmm_rl_ker_var2 ) blis-0.9.0/frame/3/trmm/other/bli_trmm_rl_ker_var2rr.c000066400000000000000000000447521422157504600226340ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define FUNCPTR_T gemm_fp typedef void (*FUNCPTR_T) ( doff_t diagoffb, pack_t schema_a, pack_t schema_b, dim_t m, dim_t n, dim_t k, void* alpha, void* a, inc_t cs_a, dim_t pd_a, inc_t ps_a, void* b, inc_t rs_b, dim_t pd_b, inc_t ps_b, void* beta, void* c, inc_t rs_c, inc_t cs_c, cntx_t* cntx, rntm_t* rntm, thrinfo_t* thread ); static FUNCPTR_T GENARRAY(ftypes,trmm_rl_ker_var2rr); // // -- Macrokernel functions for round-robin partitioning ----------------------- // void bli_trmm_rl_ker_var2rr ( obj_t* a, obj_t* b, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ) { num_t dt_exec = bli_obj_exec_dt( c ); doff_t diagoffb = bli_obj_diag_offset( b ); pack_t schema_a = bli_obj_pack_schema( a ); pack_t schema_b = bli_obj_pack_schema( b ); dim_t m = bli_obj_length( c ); dim_t n = bli_obj_width( c ); dim_t k = bli_obj_width( a ); void* buf_a = bli_obj_buffer_at_off( a ); inc_t cs_a = bli_obj_col_stride( a ); dim_t pd_a = bli_obj_panel_dim( a ); inc_t ps_a = bli_obj_panel_stride( a ); void* buf_b = bli_obj_buffer_at_off( b ); inc_t rs_b = bli_obj_row_stride( b ); dim_t pd_b = bli_obj_panel_dim( b ); inc_t ps_b = bli_obj_panel_stride( b ); void* buf_c = bli_obj_buffer_at_off( c ); inc_t rs_c = bli_obj_row_stride( c ); inc_t cs_c = bli_obj_col_stride( c ); obj_t scalar_a; obj_t scalar_b; void* buf_alpha; void* buf_beta; FUNCPTR_T f; // Detach and multiply the scalars attached to A and B. bli_obj_scalar_detach( a, &scalar_a ); bli_obj_scalar_detach( b, &scalar_b ); bli_mulsc( &scalar_a, &scalar_b ); // Grab the addresses of the internal scalar buffers for the scalar // merged above and the scalar attached to C. buf_alpha = bli_obj_internal_scalar_buffer( &scalar_b ); buf_beta = bli_obj_internal_scalar_buffer( c ); // Index into the type combination array to extract the correct // function pointer. f = ftypes[dt_exec]; // Invoke the function. f( diagoffb, schema_a, schema_b, m, n, k, buf_alpha, buf_a, cs_a, pd_a, ps_a, buf_b, rs_b, pd_b, ps_b, buf_beta, buf_c, rs_c, cs_c, cntx, rntm, thread ); } #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ doff_t diagoffb, \ pack_t schema_a, \ pack_t schema_b, \ dim_t m, \ dim_t n, \ dim_t k, \ void* alpha, \ void* a, inc_t cs_a, dim_t pd_a, inc_t ps_a, \ void* b, inc_t rs_b, dim_t pd_b, inc_t ps_b, \ void* beta, \ void* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx, \ rntm_t* rntm, \ thrinfo_t* thread \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ /* Alias some constants to simpler names. */ \ const dim_t MR = pd_a; \ const dim_t NR = pd_b; \ const dim_t PACKMR = cs_a; \ const dim_t PACKNR = rs_b; \ \ /* Query the context for the micro-kernel address and cast it to its function pointer type. */ \ PASTECH(ch,gemm_ukr_ft) \ gemm_ukr = bli_cntx_get_l3_vir_ukr_dt( dt, BLIS_GEMM_UKR, cntx ); \ \ /* Temporary C buffer for edge cases. Note that the strides of this temporary buffer are set so that they match the storage of the original C matrix. For example, if C is column-stored, ct will be column-stored as well. */ \ ctype ct[ BLIS_STACK_BUF_MAX_SIZE \ / sizeof( ctype ) ] \ __attribute__((aligned(BLIS_STACK_BUF_ALIGN_SIZE))); \ const bool col_pref = bli_cntx_l3_vir_ukr_prefers_cols_dt( dt, BLIS_GEMM_UKR, cntx ); \ const inc_t rs_ct = ( col_pref ? 1 : NR ); \ const inc_t cs_ct = ( col_pref ? MR : 1 ); \ \ ctype* restrict one = PASTEMAC(ch,1); \ ctype* restrict zero = PASTEMAC(ch,0); \ ctype* restrict a_cast = a; \ ctype* restrict b_cast = b; \ ctype* restrict c_cast = c; \ ctype* restrict alpha_cast = alpha; \ ctype* restrict beta_cast = beta; \ ctype* restrict b1; \ ctype* restrict c1; \ \ doff_t diagoffb_j; \ dim_t k_full; \ dim_t m_iter, m_left; \ dim_t n_iter, n_left; \ dim_t m_cur; \ dim_t n_cur; \ dim_t k_b1121; \ dim_t off_b1121; \ dim_t i, j; \ inc_t rstep_a; \ inc_t cstep_b; \ inc_t rstep_c, cstep_c; \ inc_t istep_a; \ inc_t istep_b; \ inc_t off_scl; \ inc_t ss_b_num; \ inc_t ss_b_den; \ inc_t ps_b_cur; \ inc_t is_b_cur; \ auxinfo_t aux; \ \ /* Assumptions/assertions: rs_a == 1 cs_a == PACKMR pd_a == MR ps_a == stride to next micro-panel of A rs_b == PACKNR cs_b == 1 pd_b == NR ps_b == stride to next micro-panel of B rs_c == (no assumptions) cs_c == (no assumptions) */ \ \ /* Safety trap: Certain indexing within this macro-kernel does not work as intended if both MR and NR are odd. */ \ if ( ( bli_is_odd( PACKMR ) && bli_is_odd( NR ) ) || \ ( bli_is_odd( PACKNR ) && bli_is_odd( MR ) ) ) bli_abort(); \ \ /* If any dimension is zero, return immediately. */ \ if ( bli_zero_dim3( m, n, k ) ) return; \ \ /* Safeguard: If the current panel of B is entirely above the diagonal, it is implicitly zero. So we do nothing. */ \ if ( bli_is_strictly_above_diag_n( diagoffb, k, n ) ) return; \ \ /* Compute k_full. For all trmm, k_full is simply k. This is needed because some parameter combinations of trmm reduce k to advance past zero regions in the triangular matrix, and when computing the imaginary stride of A (the non-triangular matrix), which is used by 4m1/3m1 implementations, we need this unreduced value of k. */ \ k_full = k; \ \ /* Compute indexing scaling factor for for 4m or 3m. This is needed because one of the packing register blocksizes (PACKMR or PACKNR) is used to index into the micro-panels of the non- triangular matrix when computing with a diagonal-intersecting micro-panel of the triangular matrix. In the case of 4m or 3m, real values are stored in both sub-panels, and so the indexing needs to occur in units of real values. The value computed here is divided into the complex pointer offset to cause the pointer to be advanced by the correct value. */ \ if ( bli_is_4mi_packed( schema_b ) || \ bli_is_3mi_packed( schema_b ) || \ bli_is_rih_packed( schema_b ) ) off_scl = 2; \ else off_scl = 1; \ \ /* Compute the storage stride scaling. Usually this is just 1. However, in the case of interleaved 3m, we need to scale the offset by 3/2. And if we are packing real-only, imag-only, or summed-only, we need to scale the computed panel sizes by 1/2 to compensate for the fact that the pointer arithmetic occurs in terms of complex elements rather than real elements. */ \ if ( bli_is_3mi_packed( schema_b ) ) { ss_b_num = 3; ss_b_den = 2; } \ else if ( bli_is_rih_packed( schema_b ) ) { ss_b_num = 1; ss_b_den = 2; } \ else { ss_b_num = 1; ss_b_den = 1; } \ \ /* If there is a zero region above where the diagonal of B intersects the left edge of the panel, adjust the pointer to A and treat this case as if the diagonal offset were zero. Note that we don't need to adjust the pointer to B since packm would have simply skipped over the region that was not stored. */ \ if ( diagoffb < 0 ) \ { \ j = -diagoffb; \ k = k - j; \ diagoffb = 0; \ a_cast = a_cast + ( j * PACKMR ) / off_scl; \ } \ \ /* If there is a zero region to the right of where the diagonal of B intersects the bottom of the panel, shrink it to prevent "no-op" iterations from executing. */ \ if ( diagoffb + k < n ) \ { \ n = diagoffb + k; \ } \ \ /* Clear the temporary C buffer in case it has any infs or NaNs. */ \ PASTEMAC(ch,set0s_mxn)( MR, NR, \ ct, rs_ct, cs_ct ); \ \ /* Compute number of primary and leftover components of the m and n dimensions. */ \ n_iter = n / NR; \ n_left = n % NR; \ \ m_iter = m / MR; \ m_left = m % MR; \ \ if ( n_left ) ++n_iter; \ if ( m_left ) ++m_iter; \ \ /* Determine some increments used to step through A, B, and C. */ \ rstep_a = ps_a; \ \ cstep_b = ps_b; \ \ rstep_c = rs_c * MR; \ cstep_c = cs_c * NR; \ \ istep_a = PACKMR * k_full; \ istep_b = PACKNR * k; \ \ if ( bli_is_odd( istep_a ) ) istep_a += 1; \ if ( bli_is_odd( istep_b ) ) istep_b += 1; \ \ /* Save the pack schemas of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_schema_a( schema_a, &aux ); \ bli_auxinfo_set_schema_b( schema_b, &aux ); \ \ /* Save the imaginary stride of A to the auxinfo_t object. */ \ bli_auxinfo_set_is_a( istep_a, &aux ); \ \ thrinfo_t* caucus = bli_thrinfo_sub_node( thread ); \ \ dim_t jr_nt = bli_thread_n_way( thread ); \ dim_t jr_tid = bli_thread_work_id( thread ); \ dim_t ir_nt = bli_thread_n_way( caucus ); \ dim_t ir_tid = bli_thread_work_id( caucus ); \ \ dim_t jr_start, jr_end; \ dim_t ir_start, ir_end; \ dim_t jr_inc, ir_inc; \ \ /* Note that we partition the 2nd loop into two regions: the rectangular part of B, and the triangular portion. */ \ dim_t n_iter_rct; \ dim_t n_iter_tri; \ \ if ( bli_is_strictly_below_diag_n( diagoffb, m, n ) ) \ { \ /* If the entire panel of B does not intersect the diagonal, there is no triangular region, and therefore we can skip the second set of loops. */ \ n_iter_rct = n_iter; \ n_iter_tri = 0; \ } \ else \ { \ /* If the panel of B does intersect the diagonal, compute the number of iterations in the rectangular region by dividing NR into the diagonal offset. (There should never be any remainder in this division.) The number of iterations in the triangular (or trapezoidal) region is computed as the remaining number of iterations in the n dimension. */ \ n_iter_rct = diagoffb / NR; \ n_iter_tri = n_iter - n_iter_rct; \ } \ \ /* Use round-robin assignment of micropanels to threads in the 2nd and 1st loops for the initial rectangular region of B (if it exists). */ \ bli_thread_range_jrir_rr( thread, n_iter_rct, 1, FALSE, &jr_start, &jr_end, &jr_inc ); \ bli_thread_range_jrir_rr( caucus, m_iter, 1, FALSE, &ir_start, &ir_end, &ir_inc ); \ \ /* Loop over the n dimension (NR columns at a time). */ \ for ( j = jr_start; j < jr_end; j += jr_inc ) \ { \ ctype* restrict a1; \ ctype* restrict c11; \ ctype* restrict b2; \ \ b1 = b_cast + j * cstep_b; \ c1 = c_cast + j * cstep_c; \ \ n_cur = ( bli_is_not_edge_f( j, n_iter, n_left ) ? NR : n_left ); \ \ /* Initialize our next panel of B to be the current panel of B. */ \ b2 = b1; \ \ { \ /* Save the 4m1/3m1 imaginary stride of B to the auxinfo_t object. */ \ bli_auxinfo_set_is_b( istep_b, &aux ); \ \ /* Loop over the m dimension (MR rows at a time). */ \ for ( i = ir_start; i < ir_end; i += ir_inc ) \ { \ ctype* restrict a2; \ \ a1 = a_cast + i * rstep_a; \ c11 = c1 + i * rstep_c; \ \ m_cur = ( bli_is_not_edge_f( i, m_iter, m_left ) ? MR : m_left ); \ \ /* Compute the addresses of the next panels of A and B. */ \ a2 = bli_trmm_get_next_a_upanel( a1, rstep_a, ir_inc ); \ if ( bli_is_last_iter_rr( i, m_iter, ir_tid, ir_nt ) ) \ { \ a2 = a_cast; \ b2 = bli_trmm_get_next_b_upanel( b1, cstep_b, jr_inc ); \ if ( bli_is_last_iter_rr( j, n_iter, jr_tid, jr_nt ) ) \ b2 = b_cast; \ } \ \ /* Save addresses of next panels of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_next_a( a2, &aux ); \ bli_auxinfo_set_next_b( b2, &aux ); \ \ /* Handle interior and edge cases separately. */ \ if ( m_cur == MR && n_cur == NR ) \ { \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k, \ alpha_cast, \ a1, \ b1, \ one, \ c11, rs_c, cs_c, \ &aux, \ cntx \ ); \ } \ else \ { \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k, \ alpha_cast, \ a1, \ b1, \ zero, \ ct, rs_ct, cs_ct, \ &aux, \ cntx \ ); \ \ /* Add the result to the edge of C. */ \ PASTEMAC(ch,adds_mxn)( m_cur, n_cur, \ ct, rs_ct, cs_ct, \ c11, rs_c, cs_c ); \ } \ } \ } \ } \ \ /* If there is no triangular region, then we're done. */ \ if ( n_iter_tri == 0 ) return; \ \ /* Use round-robin assignment of micropanels to threads in the 2nd loop for the remaining triangular region of B (if it exists). NOTE: We don't need to call bli_thread_range_jrir*() here since we employ a hack that calls for each thread to execute every iteration of the jr and ir loops but skip all but the pointer increment for iterations that are not assigned to it. */ \ \ /* Advance the starting b1 and c1 pointers to the positions corresponding to the start of the triangular region of B. */ \ jr_start = n_iter_rct; \ b1 = b_cast + jr_start * cstep_b; \ c1 = c_cast + jr_start * cstep_c; \ \ /* Loop over the n dimension (NR columns at a time). */ \ for ( j = jr_start; j < n_iter; ++j ) \ { \ ctype* restrict a1; \ ctype* restrict c11; \ ctype* restrict b2; \ \ diagoffb_j = diagoffb - ( doff_t )j*NR; \ \ /* Determine the offset to the beginning of the panel that was packed so we can index into the corresponding location in A. Then compute the length of that panel. */ \ off_b1121 = bli_max( -diagoffb_j, 0 ); \ k_b1121 = k - off_b1121; \ \ a1 = a_cast; \ c11 = c1; \ \ n_cur = ( bli_is_not_edge_f( j, n_iter, n_left ) ? NR : n_left ); \ \ /* Initialize our next panel of B to be the current panel of B. */ \ b2 = b1; \ \ /* If the current panel of B intersects the diagonal, scale C by beta. If it is strictly below the diagonal, scale by one. This allows the current macro-kernel to work for both trmm and trmm3. */ \ { \ /* Compute the panel stride for the current diagonal- intersecting micro-panel. */ \ is_b_cur = k_b1121 * PACKNR; \ is_b_cur += ( bli_is_odd( is_b_cur ) ? 1 : 0 ); \ ps_b_cur = ( is_b_cur * ss_b_num ) / ss_b_den; \ \ if ( bli_trmm_my_iter( j, thread ) ) { \ \ /* Save the 4m1/3m1 imaginary stride of B to the auxinfo_t object. */ \ bli_auxinfo_set_is_b( is_b_cur, &aux ); \ \ /* Loop over the m dimension (MR rows at a time). */ \ for ( i = 0; i < m_iter; ++i ) \ { \ if ( bli_trmm_my_iter( i, caucus ) ) { \ \ ctype* restrict a1_i; \ ctype* restrict a2; \ \ m_cur = ( bli_is_not_edge_f( i, m_iter, m_left ) ? MR : m_left ); \ \ a1_i = a1 + ( off_b1121 * PACKMR ) / off_scl; \ \ /* Compute the addresses of the next panels of A and B. */ \ a2 = a1; \ if ( bli_is_last_iter_rr( i, m_iter, 0, 1 ) ) \ { \ a2 = a_cast; \ b2 = b1; \ if ( bli_is_last_iter_rr( j, n_iter, jr_tid, jr_nt ) ) \ b2 = b_cast; \ } \ \ /* Save addresses of next panels of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_next_a( a2, &aux ); \ bli_auxinfo_set_next_b( b2, &aux ); \ \ /* Handle interior and edge cases separately. */ \ if ( m_cur == MR && n_cur == NR ) \ { \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k_b1121, \ alpha_cast, \ a1_i, \ b1, \ beta_cast, \ c11, rs_c, cs_c, \ &aux, \ cntx \ ); \ } \ else \ { \ /* Copy edge elements of C to the temporary buffer. */ \ PASTEMAC(ch,copys_mxn)( m_cur, n_cur, \ c11, rs_c, cs_c, \ ct, rs_ct, cs_ct ); \ \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k_b1121, \ alpha_cast, \ a1_i, \ b1, \ beta_cast, \ ct, rs_ct, cs_ct, \ &aux, \ cntx \ ); \ \ /* Copy the result to the edge of C. */ \ PASTEMAC(ch,copys_mxn)( m_cur, n_cur, \ ct, rs_ct, cs_ct, \ c11, rs_c, cs_c ); \ } \ } \ \ a1 += rstep_a; \ c11 += rstep_c; \ } \ } \ \ b1 += ps_b_cur; \ } \ \ c1 += cstep_c; \ } \ \ /*PASTEMAC(ch,fprintm)( stdout, "trmm_rl_ker_var2rr: a1", MR, k_b1121, a1, 1, MR, "%4.1f", "" );*/ \ /*PASTEMAC(ch,fprintm)( stdout, "trmm_rl_ker_var2rr: b1", k_b1121, NR, b1_i, NR, 1, "%4.1f", "" );*/ \ } INSERT_GENTFUNC_BASIC0( trmm_rl_ker_var2rr ) blis-0.9.0/frame/3/trmm/other/bli_trmm_rl_ker_var2sl.c000066400000000000000000000447431422157504600226270ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define FUNCPTR_T gemm_fp typedef void (*FUNCPTR_T) ( doff_t diagoffb, pack_t schema_a, pack_t schema_b, dim_t m, dim_t n, dim_t k, void* alpha, void* a, inc_t cs_a, dim_t pd_a, inc_t ps_a, void* b, inc_t rs_b, dim_t pd_b, inc_t ps_b, void* beta, void* c, inc_t rs_c, inc_t cs_c, cntx_t* cntx, rntm_t* rntm, thrinfo_t* thread ); static FUNCPTR_T GENARRAY(ftypes,trmm_rl_ker_var2sl); // // -- Macrokernel functions for slab partitioning ------------------------------ // void bli_trmm_rl_ker_var2sl ( obj_t* a, obj_t* b, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ) { num_t dt_exec = bli_obj_exec_dt( c ); doff_t diagoffb = bli_obj_diag_offset( b ); pack_t schema_a = bli_obj_pack_schema( a ); pack_t schema_b = bli_obj_pack_schema( b ); dim_t m = bli_obj_length( c ); dim_t n = bli_obj_width( c ); dim_t k = bli_obj_width( a ); void* buf_a = bli_obj_buffer_at_off( a ); inc_t cs_a = bli_obj_col_stride( a ); dim_t pd_a = bli_obj_panel_dim( a ); inc_t ps_a = bli_obj_panel_stride( a ); void* buf_b = bli_obj_buffer_at_off( b ); inc_t rs_b = bli_obj_row_stride( b ); dim_t pd_b = bli_obj_panel_dim( b ); inc_t ps_b = bli_obj_panel_stride( b ); void* buf_c = bli_obj_buffer_at_off( c ); inc_t rs_c = bli_obj_row_stride( c ); inc_t cs_c = bli_obj_col_stride( c ); obj_t scalar_a; obj_t scalar_b; void* buf_alpha; void* buf_beta; FUNCPTR_T f; // Detach and multiply the scalars attached to A and B. bli_obj_scalar_detach( a, &scalar_a ); bli_obj_scalar_detach( b, &scalar_b ); bli_mulsc( &scalar_a, &scalar_b ); // Grab the addresses of the internal scalar buffers for the scalar // merged above and the scalar attached to C. buf_alpha = bli_obj_internal_scalar_buffer( &scalar_b ); buf_beta = bli_obj_internal_scalar_buffer( c ); // Index into the type combination array to extract the correct // function pointer. f = ftypes[dt_exec]; // Invoke the function. f( diagoffb, schema_a, schema_b, m, n, k, buf_alpha, buf_a, cs_a, pd_a, ps_a, buf_b, rs_b, pd_b, ps_b, buf_beta, buf_c, rs_c, cs_c, cntx, rntm, thread ); } #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ doff_t diagoffb, \ pack_t schema_a, \ pack_t schema_b, \ dim_t m, \ dim_t n, \ dim_t k, \ void* alpha, \ void* a, inc_t cs_a, dim_t pd_a, inc_t ps_a, \ void* b, inc_t rs_b, dim_t pd_b, inc_t ps_b, \ void* beta, \ void* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx, \ rntm_t* rntm, \ thrinfo_t* thread \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ /* Alias some constants to simpler names. */ \ const dim_t MR = pd_a; \ const dim_t NR = pd_b; \ const dim_t PACKMR = cs_a; \ const dim_t PACKNR = rs_b; \ \ /* Query the context for the micro-kernel address and cast it to its function pointer type. */ \ PASTECH(ch,gemm_ukr_ft) \ gemm_ukr = bli_cntx_get_l3_vir_ukr_dt( dt, BLIS_GEMM_UKR, cntx ); \ \ /* Temporary C buffer for edge cases. Note that the strides of this temporary buffer are set so that they match the storage of the original C matrix. For example, if C is column-stored, ct will be column-stored as well. */ \ ctype ct[ BLIS_STACK_BUF_MAX_SIZE \ / sizeof( ctype ) ] \ __attribute__((aligned(BLIS_STACK_BUF_ALIGN_SIZE))); \ const bool col_pref = bli_cntx_l3_vir_ukr_prefers_cols_dt( dt, BLIS_GEMM_UKR, cntx ); \ const inc_t rs_ct = ( col_pref ? 1 : NR ); \ const inc_t cs_ct = ( col_pref ? MR : 1 ); \ \ ctype* restrict one = PASTEMAC(ch,1); \ ctype* restrict zero = PASTEMAC(ch,0); \ ctype* restrict a_cast = a; \ ctype* restrict b_cast = b; \ ctype* restrict c_cast = c; \ ctype* restrict alpha_cast = alpha; \ ctype* restrict beta_cast = beta; \ ctype* restrict b1; \ ctype* restrict c1; \ \ doff_t diagoffb_j; \ dim_t k_full; \ dim_t m_iter, m_left; \ dim_t n_iter, n_left; \ dim_t m_cur; \ dim_t n_cur; \ dim_t k_b1121; \ dim_t off_b1121; \ dim_t i, j; \ inc_t rstep_a; \ inc_t cstep_b; \ inc_t rstep_c, cstep_c; \ inc_t istep_a; \ inc_t istep_b; \ inc_t off_scl; \ inc_t ss_b_num; \ inc_t ss_b_den; \ inc_t ps_b_cur; \ inc_t is_b_cur; \ auxinfo_t aux; \ \ /* Assumptions/assertions: rs_a == 1 cs_a == PACKMR pd_a == MR ps_a == stride to next micro-panel of A rs_b == PACKNR cs_b == 1 pd_b == NR ps_b == stride to next micro-panel of B rs_c == (no assumptions) cs_c == (no assumptions) */ \ \ /* Safety trap: Certain indexing within this macro-kernel does not work as intended if both MR and NR are odd. */ \ if ( ( bli_is_odd( PACKMR ) && bli_is_odd( NR ) ) || \ ( bli_is_odd( PACKNR ) && bli_is_odd( MR ) ) ) bli_abort(); \ \ /* If any dimension is zero, return immediately. */ \ if ( bli_zero_dim3( m, n, k ) ) return; \ \ /* Safeguard: If the current panel of B is entirely above the diagonal, it is implicitly zero. So we do nothing. */ \ if ( bli_is_strictly_above_diag_n( diagoffb, k, n ) ) return; \ \ /* Compute k_full. For all trmm, k_full is simply k. This is needed because some parameter combinations of trmm reduce k to advance past zero regions in the triangular matrix, and when computing the imaginary stride of A (the non-triangular matrix), which is used by 4m1/3m1 implementations, we need this unreduced value of k. */ \ k_full = k; \ \ /* Compute indexing scaling factor for for 4m or 3m. This is needed because one of the packing register blocksizes (PACKMR or PACKNR) is used to index into the micro-panels of the non- triangular matrix when computing with a diagonal-intersecting micro-panel of the triangular matrix. In the case of 4m or 3m, real values are stored in both sub-panels, and so the indexing needs to occur in units of real values. The value computed here is divided into the complex pointer offset to cause the pointer to be advanced by the correct value. */ \ if ( bli_is_4mi_packed( schema_b ) || \ bli_is_3mi_packed( schema_b ) || \ bli_is_rih_packed( schema_b ) ) off_scl = 2; \ else off_scl = 1; \ \ /* Compute the storage stride scaling. Usually this is just 1. However, in the case of interleaved 3m, we need to scale the offset by 3/2. And if we are packing real-only, imag-only, or summed-only, we need to scale the computed panel sizes by 1/2 to compensate for the fact that the pointer arithmetic occurs in terms of complex elements rather than real elements. */ \ if ( bli_is_3mi_packed( schema_b ) ) { ss_b_num = 3; ss_b_den = 2; } \ else if ( bli_is_rih_packed( schema_b ) ) { ss_b_num = 1; ss_b_den = 2; } \ else { ss_b_num = 1; ss_b_den = 1; } \ \ /* If there is a zero region above where the diagonal of B intersects the left edge of the panel, adjust the pointer to A and treat this case as if the diagonal offset were zero. Note that we don't need to adjust the pointer to B since packm would have simply skipped over the region that was not stored. */ \ if ( diagoffb < 0 ) \ { \ j = -diagoffb; \ k = k - j; \ diagoffb = 0; \ a_cast = a_cast + ( j * PACKMR ) / off_scl; \ } \ \ /* If there is a zero region to the right of where the diagonal of B intersects the bottom of the panel, shrink it to prevent "no-op" iterations from executing. */ \ if ( diagoffb + k < n ) \ { \ n = diagoffb + k; \ } \ \ /* Clear the temporary C buffer in case it has any infs or NaNs. */ \ PASTEMAC(ch,set0s_mxn)( MR, NR, \ ct, rs_ct, cs_ct ); \ \ /* Compute number of primary and leftover components of the m and n dimensions. */ \ n_iter = n / NR; \ n_left = n % NR; \ \ m_iter = m / MR; \ m_left = m % MR; \ \ if ( n_left ) ++n_iter; \ if ( m_left ) ++m_iter; \ \ /* Determine some increments used to step through A, B, and C. */ \ rstep_a = ps_a; \ \ cstep_b = ps_b; \ \ rstep_c = rs_c * MR; \ cstep_c = cs_c * NR; \ \ istep_a = PACKMR * k_full; \ istep_b = PACKNR * k; \ \ if ( bli_is_odd( istep_a ) ) istep_a += 1; \ if ( bli_is_odd( istep_b ) ) istep_b += 1; \ \ /* Save the pack schemas of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_schema_a( schema_a, &aux ); \ bli_auxinfo_set_schema_b( schema_b, &aux ); \ \ /* Save the imaginary stride of A to the auxinfo_t object. */ \ bli_auxinfo_set_is_a( istep_a, &aux ); \ \ thrinfo_t* caucus = bli_thrinfo_sub_node( thread ); \ \ dim_t jr_nt = bli_thread_n_way( thread ); \ dim_t jr_tid = bli_thread_work_id( thread ); \ dim_t ir_nt = bli_thread_n_way( caucus ); \ dim_t ir_tid = bli_thread_work_id( caucus ); \ \ dim_t jr_start, jr_end; \ dim_t ir_start, ir_end; \ dim_t jr_inc, ir_inc; \ \ /* Note that we partition the 2nd loop into two regions: the rectangular part of B, and the triangular portion. */ \ dim_t n_iter_rct; \ dim_t n_iter_tri; \ \ if ( bli_is_strictly_below_diag_n( diagoffb, m, n ) ) \ { \ /* If the entire panel of B does not intersect the diagonal, there is no triangular region, and therefore we can skip the second set of loops. */ \ n_iter_rct = n_iter; \ n_iter_tri = 0; \ } \ else \ { \ /* If the panel of B does intersect the diagonal, compute the number of iterations in the rectangular region by dividing NR into the diagonal offset. (There should never be any remainder in this division.) The number of iterations in the triangular (or trapezoidal) region is computed as the remaining number of iterations in the n dimension. */ \ n_iter_rct = diagoffb / NR; \ n_iter_tri = n_iter - n_iter_rct; \ } \ \ /* Use slab assignment of micropanels to threads in the 2nd and 1st loops for the initial rectangular region of B (if it exists). */ \ bli_thread_range_jrir_sl( thread, n_iter_rct, 1, FALSE, &jr_start, &jr_end, &jr_inc ); \ bli_thread_range_jrir_sl( caucus, m_iter, 1, FALSE, &ir_start, &ir_end, &ir_inc ); \ \ /* Loop over the n dimension (NR columns at a time). */ \ for ( j = jr_start; j < jr_end; j += jr_inc ) \ { \ ctype* restrict a1; \ ctype* restrict c11; \ ctype* restrict b2; \ \ b1 = b_cast + j * cstep_b; \ c1 = c_cast + j * cstep_c; \ \ n_cur = ( bli_is_not_edge_f( j, n_iter, n_left ) ? NR : n_left ); \ \ /* Initialize our next panel of B to be the current panel of B. */ \ b2 = b1; \ \ { \ /* Save the 4m1/3m1 imaginary stride of B to the auxinfo_t object. */ \ bli_auxinfo_set_is_b( istep_b, &aux ); \ \ /* Loop over the m dimension (MR rows at a time). */ \ for ( i = ir_start; i < ir_end; i += ir_inc ) \ { \ ctype* restrict a2; \ \ a1 = a_cast + i * rstep_a; \ c11 = c1 + i * rstep_c; \ \ m_cur = ( bli_is_not_edge_f( i, m_iter, m_left ) ? MR : m_left ); \ \ /* Compute the addresses of the next panels of A and B. */ \ a2 = bli_trmm_get_next_a_upanel( a1, rstep_a, ir_inc ); \ if ( bli_is_last_iter_sl( i, m_iter, ir_tid, ir_nt ) ) \ { \ a2 = a_cast; \ b2 = bli_trmm_get_next_b_upanel( b1, cstep_b, jr_inc ); \ if ( bli_is_last_iter_sl( j, n_iter, jr_tid, jr_nt ) ) \ b2 = b_cast; \ } \ \ /* Save addresses of next panels of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_next_a( a2, &aux ); \ bli_auxinfo_set_next_b( b2, &aux ); \ \ /* Handle interior and edge cases separately. */ \ if ( m_cur == MR && n_cur == NR ) \ { \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k, \ alpha_cast, \ a1, \ b1, \ one, \ c11, rs_c, cs_c, \ &aux, \ cntx \ ); \ } \ else \ { \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k, \ alpha_cast, \ a1, \ b1, \ zero, \ ct, rs_ct, cs_ct, \ &aux, \ cntx \ ); \ \ /* Add the result to the edge of C. */ \ PASTEMAC(ch,adds_mxn)( m_cur, n_cur, \ ct, rs_ct, cs_ct, \ c11, rs_c, cs_c ); \ } \ } \ } \ } \ \ /* If there is no triangular region, then we're done. */ \ if ( n_iter_tri == 0 ) return; \ \ /* Use round-robin assignment of micropanels to threads in the 2nd loop for the remaining triangular region of B (if it exists). NOTE: We don't need to call bli_thread_range_jrir*() here since we employ a hack that calls for each thread to execute every iteration of the jr and ir loops but skip all but the pointer increment for iterations that are not assigned to it. */ \ \ /* Advance the starting b1 and c1 pointers to the positions corresponding to the start of the triangular region of B. */ \ jr_start = n_iter_rct; \ b1 = b_cast + jr_start * cstep_b; \ c1 = c_cast + jr_start * cstep_c; \ \ /* Loop over the n dimension (NR columns at a time). */ \ for ( j = jr_start; j < n_iter; ++j ) \ { \ ctype* restrict a1; \ ctype* restrict c11; \ ctype* restrict b2; \ \ diagoffb_j = diagoffb - ( doff_t )j*NR; \ \ /* Determine the offset to the beginning of the panel that was packed so we can index into the corresponding location in A. Then compute the length of that panel. */ \ off_b1121 = bli_max( -diagoffb_j, 0 ); \ k_b1121 = k - off_b1121; \ \ a1 = a_cast; \ c11 = c1; \ \ n_cur = ( bli_is_not_edge_f( j, n_iter, n_left ) ? NR : n_left ); \ \ /* Initialize our next panel of B to be the current panel of B. */ \ b2 = b1; \ \ /* If the current panel of B intersects the diagonal, scale C by beta. If it is strictly below the diagonal, scale by one. This allows the current macro-kernel to work for both trmm and trmm3. */ \ { \ /* Compute the panel stride for the current diagonal- intersecting micro-panel. */ \ is_b_cur = k_b1121 * PACKNR; \ is_b_cur += ( bli_is_odd( is_b_cur ) ? 1 : 0 ); \ ps_b_cur = ( is_b_cur * ss_b_num ) / ss_b_den; \ \ if ( bli_trmm_my_iter( j, thread ) ) { \ \ /* Save the 4m1/3m1 imaginary stride of B to the auxinfo_t object. */ \ bli_auxinfo_set_is_b( is_b_cur, &aux ); \ \ /* Loop over the m dimension (MR rows at a time). */ \ for ( i = 0; i < m_iter; ++i ) \ { \ if ( bli_trmm_my_iter( i, caucus ) ) { \ \ ctype* restrict a1_i; \ ctype* restrict a2; \ \ m_cur = ( bli_is_not_edge_f( i, m_iter, m_left ) ? MR : m_left ); \ \ a1_i = a1 + ( off_b1121 * PACKMR ) / off_scl; \ \ /* Compute the addresses of the next panels of A and B. */ \ a2 = a1; \ if ( bli_is_last_iter_rr( i, m_iter, 0, 1 ) ) \ { \ a2 = a_cast; \ b2 = b1; \ if ( bli_is_last_iter_rr( j, n_iter, jr_tid, jr_nt ) ) \ b2 = b_cast; \ } \ \ /* Save addresses of next panels of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_next_a( a2, &aux ); \ bli_auxinfo_set_next_b( b2, &aux ); \ \ /* Handle interior and edge cases separately. */ \ if ( m_cur == MR && n_cur == NR ) \ { \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k_b1121, \ alpha_cast, \ a1_i, \ b1, \ beta_cast, \ c11, rs_c, cs_c, \ &aux, \ cntx \ ); \ } \ else \ { \ /* Copy edge elements of C to the temporary buffer. */ \ PASTEMAC(ch,copys_mxn)( m_cur, n_cur, \ c11, rs_c, cs_c, \ ct, rs_ct, cs_ct ); \ \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k_b1121, \ alpha_cast, \ a1_i, \ b1, \ beta_cast, \ ct, rs_ct, cs_ct, \ &aux, \ cntx \ ); \ \ /* Copy the result to the edge of C. */ \ PASTEMAC(ch,copys_mxn)( m_cur, n_cur, \ ct, rs_ct, cs_ct, \ c11, rs_c, cs_c ); \ } \ } \ \ a1 += rstep_a; \ c11 += rstep_c; \ } \ } \ \ b1 += ps_b_cur; \ } \ \ c1 += cstep_c; \ } \ \ /*PASTEMAC(ch,fprintm)( stdout, "trmm_rl_ker_var2sl: a1", MR, k_b1121, a1, 1, MR, "%4.1f", "" );*/ \ /*PASTEMAC(ch,fprintm)( stdout, "trmm_rl_ker_var2sl: b1", k_b1121, NR, b1_i, NR, 1, "%4.1f", "" );*/ \ } INSERT_GENTFUNC_BASIC0( trmm_rl_ker_var2sl ) blis-0.9.0/frame/3/trmm/other/bli_trmm_ru_ker_var2.c000066400000000000000000000401641422157504600222720ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define FUNCPTR_T gemm_fp typedef void (*FUNCPTR_T) ( doff_t diagoffb, pack_t schema_a, pack_t schema_b, dim_t m, dim_t n, dim_t k, void* alpha, void* a, inc_t cs_a, dim_t pd_a, inc_t ps_a, void* b, inc_t rs_b, dim_t pd_b, inc_t ps_b, void* beta, void* c, inc_t rs_c, inc_t cs_c, cntx_t* cntx, rntm_t* rntm, thrinfo_t* thread ); static FUNCPTR_T GENARRAY(ftypes,trmm_ru_ker_var2); void bli_trmm_ru_ker_var2 ( obj_t* a, obj_t* b, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ) { num_t dt_exec = bli_obj_exec_dt( c ); doff_t diagoffb = bli_obj_diag_offset( b ); pack_t schema_a = bli_obj_pack_schema( a ); pack_t schema_b = bli_obj_pack_schema( b ); dim_t m = bli_obj_length( c ); dim_t n = bli_obj_width( c ); dim_t k = bli_obj_width( a ); void* buf_a = bli_obj_buffer_at_off( a ); inc_t cs_a = bli_obj_col_stride( a ); dim_t pd_a = bli_obj_panel_dim( a ); inc_t ps_a = bli_obj_panel_stride( a ); void* buf_b = bli_obj_buffer_at_off( b ); inc_t rs_b = bli_obj_row_stride( b ); dim_t pd_b = bli_obj_panel_dim( b ); inc_t ps_b = bli_obj_panel_stride( b ); void* buf_c = bli_obj_buffer_at_off( c ); inc_t rs_c = bli_obj_row_stride( c ); inc_t cs_c = bli_obj_col_stride( c ); obj_t scalar_a; obj_t scalar_b; void* buf_alpha; void* buf_beta; FUNCPTR_T f; // Detach and multiply the scalars attached to A and B. bli_obj_scalar_detach( a, &scalar_a ); bli_obj_scalar_detach( b, &scalar_b ); bli_mulsc( &scalar_a, &scalar_b ); // Grab the addresses of the internal scalar buffers for the scalar // merged above and the scalar attached to C. buf_alpha = bli_obj_internal_scalar_buffer( &scalar_b ); buf_beta = bli_obj_internal_scalar_buffer( c ); // Index into the type combination array to extract the correct // function pointer. f = ftypes[dt_exec]; // Invoke the function. f( diagoffb, schema_a, schema_b, m, n, k, buf_alpha, buf_a, cs_a, pd_a, ps_a, buf_b, rs_b, pd_b, ps_b, buf_beta, buf_c, rs_c, cs_c, cntx, rntm, thread ); } #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ doff_t diagoffb, \ pack_t schema_a, \ pack_t schema_b, \ dim_t m, \ dim_t n, \ dim_t k, \ void* alpha, \ void* a, inc_t cs_a, dim_t pd_a, inc_t ps_a, \ void* b, inc_t rs_b, dim_t pd_b, inc_t ps_b, \ void* beta, \ void* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx, \ rntm_t* rntm, \ thrinfo_t* jr_thread \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ /* Alias some constants to simpler names. */ \ const dim_t MR = pd_a; \ const dim_t NR = pd_b; \ const dim_t PACKMR = cs_a; \ const dim_t PACKNR = rs_b; \ \ /* Query the context for the micro-kernel address and cast it to its function pointer type. */ \ PASTECH(ch,gemm_ukr_ft) \ gemm_ukr = bli_cntx_get_l3_vir_ukr_dt( dt, BLIS_GEMM_UKR, cntx ); \ \ /* Temporary C buffer for edge cases. Note that the strides of this temporary buffer are set so that they match the storage of the original C matrix. For example, if C is column-stored, ct will be column-stored as well. */ \ ctype ct[ BLIS_STACK_BUF_MAX_SIZE \ / sizeof( ctype ) ] \ __attribute__((aligned(BLIS_STACK_BUF_ALIGN_SIZE))); \ const bool col_pref = bli_cntx_l3_vir_ukr_prefers_cols_dt( dt, BLIS_GEMM_UKR, cntx ); \ const inc_t rs_ct = ( col_pref ? 1 : NR ); \ const inc_t cs_ct = ( col_pref ? MR : 1 ); \ \ ctype* restrict one = PASTEMAC(ch,1); \ ctype* restrict zero = PASTEMAC(ch,0); \ ctype* restrict a_cast = a; \ ctype* restrict b_cast = b; \ ctype* restrict c_cast = c; \ ctype* restrict alpha_cast = alpha; \ ctype* restrict beta_cast = beta; \ ctype* restrict b1; \ ctype* restrict c1; \ \ doff_t diagoffb_j; \ dim_t k_full; \ dim_t m_iter, m_left; \ dim_t n_iter, n_left; \ dim_t m_cur; \ dim_t n_cur; \ dim_t k_b0111; \ dim_t off_b0111; \ dim_t i, j; \ inc_t rstep_a; \ inc_t cstep_b; \ inc_t rstep_c, cstep_c; \ inc_t istep_a; \ inc_t istep_b; \ inc_t off_scl; \ inc_t ss_b_num; \ inc_t ss_b_den; \ inc_t ps_b_cur; \ inc_t is_b_cur; \ auxinfo_t aux; \ \ /* Assumptions/assertions: rs_a == 1 cs_a == PACKMR pd_a == MR ps_a == stride to next micro-panel of A rs_b == PACKNR cs_b == 1 pd_b == NR ps_b == stride to next micro-panel of B rs_c == (no assumptions) cs_c == (no assumptions) */ \ \ /* Safety trap: Certain indexing within this macro-kernel does not work as intended if both MR and NR are odd. */ \ if ( ( bli_is_odd( PACKMR ) && bli_is_odd( NR ) ) || \ ( bli_is_odd( PACKNR ) && bli_is_odd( MR ) ) ) bli_abort(); \ \ /* If any dimension is zero, return immediately. */ \ if ( bli_zero_dim3( m, n, k ) ) return; \ \ /* Safeguard: If the current panel of B is entirely below its diagonal, it is implicitly zero. So we do nothing. */ \ if ( bli_is_strictly_below_diag_n( diagoffb, k, n ) ) return; \ \ /* Compute k_full. For all trmm, k_full is simply k. This is needed because some parameter combinations of trmm reduce k to advance past zero regions in the triangular matrix, and when computing the imaginary stride of A (the non-triangular matrix), which is used by 4m1/3m1 implementations, we need this unreduced value of k. */ \ k_full = k; \ \ /* Compute indexing scaling factor for for 4m or 3m. This is needed because one of the packing register blocksizes (PACKMR or PACKNR) is used to index into the micro-panels of the non- triangular matrix when computing with a diagonal-intersecting micro-panel of the triangular matrix. In the case of 4m or 3m, real values are stored in both sub-panels, and so the indexing needs to occur in units of real values. The value computed here is divided into the complex pointer offset to cause the pointer to be advanced by the correct value. */ \ if ( bli_is_4mi_packed( schema_b ) || \ bli_is_3mi_packed( schema_b ) || \ bli_is_rih_packed( schema_b ) ) off_scl = 2; \ else off_scl = 1; \ \ /* Compute the storage stride scaling. Usually this is just 1. However, in the case of interleaved 3m, we need to scale the offset by 3/2. And if we are packing real-only, imag-only, or summed-only, we need to scale the computed panel sizes by 1/2 to compensate for the fact that the pointer arithmetic occurs in terms of complex elements rather than real elements. */ \ if ( bli_is_3mi_packed( schema_b ) ) { ss_b_num = 3; ss_b_den = 2; } \ else if ( bli_is_rih_packed( schema_b ) ) { ss_b_num = 1; ss_b_den = 2; } \ else { ss_b_num = 1; ss_b_den = 1; } \ \ /* If there is a zero region to the left of where the diagonal of B intersects the top edge of the panel, adjust the pointer to C and treat this case as if the diagonal offset were zero. This skips over the region that was not packed. (Note we assume the diagonal offset is a multiple of MR; this assumption will hold as long as the cache blocksizes are each a multiple of MR and NR.) */ \ if ( diagoffb > 0 ) \ { \ j = diagoffb; \ n = n - j; \ diagoffb = 0; \ c_cast = c_cast + (j )*cs_c; \ } \ \ /* If there is a zero region below where the diagonal of B intersects the right side of the block, shrink it to prevent "no-op" iterations from executing. */ \ if ( -diagoffb + n < k ) \ { \ k = -diagoffb + n; \ } \ \ /* Clear the temporary C buffer in case it has any infs or NaNs. */ \ PASTEMAC(ch,set0s_mxn)( MR, NR, \ ct, rs_ct, cs_ct ); \ \ /* Compute number of primary and leftover components of the m and n dimensions. */ \ n_iter = n / NR; \ n_left = n % NR; \ \ m_iter = m / MR; \ m_left = m % MR; \ \ if ( n_left ) ++n_iter; \ if ( m_left ) ++m_iter; \ \ /* Determine some increments used to step through A, B, and C. */ \ rstep_a = ps_a; \ \ cstep_b = ps_b; \ \ rstep_c = rs_c * MR; \ cstep_c = cs_c * NR; \ \ istep_a = PACKMR * k_full; \ istep_b = PACKNR * k; \ \ if ( bli_is_odd( istep_a ) ) istep_a += 1; \ if ( bli_is_odd( istep_b ) ) istep_b += 1; \ \ /* Save the pack schemas of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_schema_a( schema_a, &aux ); \ bli_auxinfo_set_schema_b( schema_b, &aux ); \ \ /* Save the imaginary stride of A to the auxinfo_t object. */ \ bli_auxinfo_set_is_a( istep_a, &aux ); \ \ b1 = b_cast; \ c1 = c_cast; \ \ thrinfo_t* ir_thread = bli_thrinfo_sub_node( jr_thread ); \ dim_t jr_num_threads = bli_thread_n_way( jr_thread ); \ dim_t jr_thread_id = bli_thread_work_id( jr_thread ); \ \ /* Loop over the n dimension (NR columns at a time). */ \ for ( j = 0; j < n_iter; ++j ) \ { \ ctype* restrict a1; \ ctype* restrict c11; \ ctype* restrict b2; \ \ diagoffb_j = diagoffb - ( doff_t )j*NR; \ \ /* Determine the offset to and length of the panel that was packed so we can index into the corresponding location in A. */ \ off_b0111 = 0; \ k_b0111 = bli_min( k, -diagoffb_j + NR ); \ \ a1 = a_cast; \ c11 = c1; \ \ n_cur = ( bli_is_not_edge_f( j, n_iter, n_left ) ? NR : n_left ); \ \ /* Initialize our next panel of B to be the current panel of B. */ \ b2 = b1; \ \ /* If the current panel of B intersects the diagonal, scale C by beta. If it is strictly below the diagonal, scale by one. This allows the current macro-kernel to work for both trmm and trmm3. */ \ if ( bli_intersects_diag_n( diagoffb_j, k, NR ) ) \ { \ /* Compute the panel stride for the current diagonal- intersecting micro-panel. */ \ is_b_cur = k_b0111 * PACKNR; \ is_b_cur += ( bli_is_odd( is_b_cur ) ? 1 : 0 ); \ ps_b_cur = ( is_b_cur * ss_b_num ) / ss_b_den; \ \ if ( bli_trmm_my_iter( j, jr_thread ) ) { \ \ /* Save the 4m1/3m1 imaginary stride of B to the auxinfo_t object. */ \ bli_auxinfo_set_is_b( is_b_cur, &aux ); \ \ /* Loop over the m dimension (MR rows at a time). */ \ for ( i = 0; i < m_iter; ++i ) \ { \ if ( bli_trmm_my_iter( i, ir_thread ) ) { \ \ ctype* restrict a1_i; \ ctype* restrict a2; \ \ m_cur = ( bli_is_not_edge_f( i, m_iter, m_left ) ? MR : m_left ); \ \ a1_i = a1 + ( off_b0111 * PACKMR ) / off_scl; \ \ /* Compute the addresses of the next panels of A and B. */ \ a2 = a1; \ if ( bli_is_last_iter( i, m_iter, 0, 1 ) ) \ { \ a2 = a_cast; \ b2 = b1; \ if ( bli_is_last_iter( j, n_iter, jr_thread_id, jr_num_threads ) ) \ b2 = b_cast; \ } \ \ /* Save addresses of next panels of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_next_a( a2, &aux ); \ bli_auxinfo_set_next_b( b2, &aux ); \ \ /* Handle interior and edge cases separately. */ \ if ( m_cur == MR && n_cur == NR ) \ { \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k_b0111, \ alpha_cast, \ a1_i, \ b1, \ beta_cast, \ c11, rs_c, cs_c, \ &aux, \ cntx \ ); \ } \ else \ { \ /* Copy edge elements of C to the temporary buffer. */ \ PASTEMAC(ch,copys_mxn)( m_cur, n_cur, \ c11, rs_c, cs_c, \ ct, rs_ct, cs_ct ); \ \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k_b0111, \ alpha_cast, \ a1_i, \ b1, \ beta_cast, \ ct, rs_ct, cs_ct, \ &aux, \ cntx \ ); \ \ /* Copy the result to the edge of C. */ \ PASTEMAC(ch,copys_mxn)( m_cur, n_cur, \ ct, rs_ct, cs_ct, \ c11, rs_c, cs_c ); \ } \ } \ \ a1 += rstep_a; \ c11 += rstep_c; \ } \ } \ \ b1 += ps_b_cur; \ } \ else if ( bli_is_strictly_above_diag_n( diagoffb_j, k, NR ) ) \ { \ if ( bli_trmm_my_iter( j, jr_thread ) ) { \ \ /* Save the 4m1/3m1 imaginary stride of B to the auxinfo_t object. */ \ bli_auxinfo_set_is_b( istep_b, &aux ); \ \ /* Loop over the m dimension (MR rows at a time). */ \ for ( i = 0; i < m_iter; ++i ) \ { \ if ( bli_trmm_my_iter( i, ir_thread ) ) { \ \ ctype* restrict a2; \ \ m_cur = ( bli_is_not_edge_f( i, m_iter, m_left ) ? MR : m_left ); \ \ /* Compute the addresses of the next panels of A and B. */ \ a2 = a1; \ if ( bli_is_last_iter( i, m_iter, 0, 1 ) ) \ { \ a2 = a_cast; \ b2 = b1; \ if ( bli_is_last_iter( j, n_iter, jr_thread_id, jr_num_threads ) ) \ b2 = b_cast; \ } \ \ /* Save addresses of next panels of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_next_a( a2, &aux ); \ bli_auxinfo_set_next_b( b2, &aux ); \ \ /* Handle interior and edge cases separately. */ \ if ( m_cur == MR && n_cur == NR ) \ { \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k, \ alpha_cast, \ a1, \ b1, \ one, \ c11, rs_c, cs_c, \ &aux, \ cntx \ ); \ } \ else \ { \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k, \ alpha_cast, \ a1, \ b1, \ zero, \ ct, rs_ct, cs_ct, \ &aux, \ cntx \ ); \ \ /* Add the result to the edge of C. */ \ PASTEMAC(ch,adds_mxn)( m_cur, n_cur, \ ct, rs_ct, cs_ct, \ c11, rs_c, cs_c ); \ } \ } \ \ a1 += rstep_a; \ c11 += rstep_c; \ } \ } \ \ b1 += cstep_b; \ } \ \ c1 += cstep_c; \ } \ \ /*PASTEMAC(ch,fprintm)( stdout, "trmm_ru_ker_var2: a1", MR, k_b0111, a1, 1, MR, "%4.1f", "" );*/ \ /*PASTEMAC(ch,fprintm)( stdout, "trmm_ru_ker_var2: b1", k_b0111, NR, b1_i, NR, 1, "%4.1f", "" );*/ \ } INSERT_GENTFUNC_BASIC0( trmm_ru_ker_var2 ) blis-0.9.0/frame/3/trmm/other/bli_trmm_ru_ker_var2rr.c000066400000000000000000000466041422157504600226430ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define FUNCPTR_T gemm_fp typedef void (*FUNCPTR_T) ( doff_t diagoffb, pack_t schema_a, pack_t schema_b, dim_t m, dim_t n, dim_t k, void* alpha, void* a, inc_t cs_a, dim_t pd_a, inc_t ps_a, void* b, inc_t rs_b, dim_t pd_b, inc_t ps_b, void* beta, void* c, inc_t rs_c, inc_t cs_c, cntx_t* cntx, rntm_t* rntm, thrinfo_t* thread ); static FUNCPTR_T GENARRAY(ftypes,trmm_ru_ker_var2rr); // // -- Macrokernel functions for round-robin partitioning ----------------------- // void bli_trmm_ru_ker_var2rr ( obj_t* a, obj_t* b, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ) { num_t dt_exec = bli_obj_exec_dt( c ); doff_t diagoffb = bli_obj_diag_offset( b ); pack_t schema_a = bli_obj_pack_schema( a ); pack_t schema_b = bli_obj_pack_schema( b ); dim_t m = bli_obj_length( c ); dim_t n = bli_obj_width( c ); dim_t k = bli_obj_width( a ); void* buf_a = bli_obj_buffer_at_off( a ); inc_t cs_a = bli_obj_col_stride( a ); dim_t pd_a = bli_obj_panel_dim( a ); inc_t ps_a = bli_obj_panel_stride( a ); void* buf_b = bli_obj_buffer_at_off( b ); inc_t rs_b = bli_obj_row_stride( b ); dim_t pd_b = bli_obj_panel_dim( b ); inc_t ps_b = bli_obj_panel_stride( b ); void* buf_c = bli_obj_buffer_at_off( c ); inc_t rs_c = bli_obj_row_stride( c ); inc_t cs_c = bli_obj_col_stride( c ); obj_t scalar_a; obj_t scalar_b; void* buf_alpha; void* buf_beta; FUNCPTR_T f; // Detach and multiply the scalars attached to A and B. bli_obj_scalar_detach( a, &scalar_a ); bli_obj_scalar_detach( b, &scalar_b ); bli_mulsc( &scalar_a, &scalar_b ); // Grab the addresses of the internal scalar buffers for the scalar // merged above and the scalar attached to C. buf_alpha = bli_obj_internal_scalar_buffer( &scalar_b ); buf_beta = bli_obj_internal_scalar_buffer( c ); // Index into the type combination array to extract the correct // function pointer. f = ftypes[dt_exec]; // Invoke the function. f( diagoffb, schema_a, schema_b, m, n, k, buf_alpha, buf_a, cs_a, pd_a, ps_a, buf_b, rs_b, pd_b, ps_b, buf_beta, buf_c, rs_c, cs_c, cntx, rntm, thread ); } #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ doff_t diagoffb, \ pack_t schema_a, \ pack_t schema_b, \ dim_t m, \ dim_t n, \ dim_t k, \ void* alpha, \ void* a, inc_t cs_a, dim_t pd_a, inc_t ps_a, \ void* b, inc_t rs_b, dim_t pd_b, inc_t ps_b, \ void* beta, \ void* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx, \ rntm_t* rntm, \ thrinfo_t* thread \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ /* Alias some constants to simpler names. */ \ const dim_t MR = pd_a; \ const dim_t NR = pd_b; \ const dim_t PACKMR = cs_a; \ const dim_t PACKNR = rs_b; \ \ /* Query the context for the micro-kernel address and cast it to its function pointer type. */ \ PASTECH(ch,gemm_ukr_ft) \ gemm_ukr = bli_cntx_get_l3_vir_ukr_dt( dt, BLIS_GEMM_UKR, cntx ); \ \ /* Temporary C buffer for edge cases. Note that the strides of this temporary buffer are set so that they match the storage of the original C matrix. For example, if C is column-stored, ct will be column-stored as well. */ \ ctype ct[ BLIS_STACK_BUF_MAX_SIZE \ / sizeof( ctype ) ] \ __attribute__((aligned(BLIS_STACK_BUF_ALIGN_SIZE))); \ const bool col_pref = bli_cntx_l3_vir_ukr_prefers_cols_dt( dt, BLIS_GEMM_UKR, cntx ); \ const inc_t rs_ct = ( col_pref ? 1 : NR ); \ const inc_t cs_ct = ( col_pref ? MR : 1 ); \ \ ctype* restrict one = PASTEMAC(ch,1); \ ctype* restrict zero = PASTEMAC(ch,0); \ ctype* restrict a_cast = a; \ ctype* restrict b_cast = b; \ ctype* restrict c_cast = c; \ ctype* restrict alpha_cast = alpha; \ ctype* restrict beta_cast = beta; \ ctype* restrict b1; \ ctype* restrict c1; \ \ doff_t diagoffb_j; \ dim_t k_full; \ dim_t m_iter, m_left; \ dim_t n_iter, n_left; \ dim_t m_cur; \ dim_t n_cur; \ dim_t k_b0111; \ dim_t off_b0111; \ dim_t i, j, jb0; \ inc_t rstep_a; \ inc_t cstep_b; \ inc_t rstep_c, cstep_c; \ inc_t istep_a; \ inc_t istep_b; \ inc_t off_scl; \ inc_t ss_b_num; \ inc_t ss_b_den; \ inc_t ps_b_cur; \ inc_t is_b_cur; \ auxinfo_t aux; \ \ /* Assumptions/assertions: rs_a == 1 cs_a == PACKMR pd_a == MR ps_a == stride to next micro-panel of A rs_b == PACKNR cs_b == 1 pd_b == NR ps_b == stride to next micro-panel of B rs_c == (no assumptions) cs_c == (no assumptions) */ \ \ /* Safety trap: Certain indexing within this macro-kernel does not work as intended if both MR and NR are odd. */ \ if ( ( bli_is_odd( PACKMR ) && bli_is_odd( NR ) ) || \ ( bli_is_odd( PACKNR ) && bli_is_odd( MR ) ) ) bli_abort(); \ \ /* If any dimension is zero, return immediately. */ \ if ( bli_zero_dim3( m, n, k ) ) return; \ \ /* Safeguard: If the current panel of B is entirely below its diagonal, it is implicitly zero. So we do nothing. */ \ if ( bli_is_strictly_below_diag_n( diagoffb, k, n ) ) return; \ \ /* Compute k_full. For all trmm, k_full is simply k. This is needed because some parameter combinations of trmm reduce k to advance past zero regions in the triangular matrix, and when computing the imaginary stride of A (the non-triangular matrix), which is used by 4m1/3m1 implementations, we need this unreduced value of k. */ \ k_full = k; \ \ /* Compute indexing scaling factor for for 4m or 3m. This is needed because one of the packing register blocksizes (PACKMR or PACKNR) is used to index into the micro-panels of the non- triangular matrix when computing with a diagonal-intersecting micro-panel of the triangular matrix. In the case of 4m or 3m, real values are stored in both sub-panels, and so the indexing needs to occur in units of real values. The value computed here is divided into the complex pointer offset to cause the pointer to be advanced by the correct value. */ \ if ( bli_is_4mi_packed( schema_b ) || \ bli_is_3mi_packed( schema_b ) || \ bli_is_rih_packed( schema_b ) ) off_scl = 2; \ else off_scl = 1; \ \ /* Compute the storage stride scaling. Usually this is just 1. However, in the case of interleaved 3m, we need to scale the offset by 3/2. And if we are packing real-only, imag-only, or summed-only, we need to scale the computed panel sizes by 1/2 to compensate for the fact that the pointer arithmetic occurs in terms of complex elements rather than real elements. */ \ if ( bli_is_3mi_packed( schema_b ) ) { ss_b_num = 3; ss_b_den = 2; } \ else if ( bli_is_rih_packed( schema_b ) ) { ss_b_num = 1; ss_b_den = 2; } \ else { ss_b_num = 1; ss_b_den = 1; } \ \ /* If there is a zero region to the left of where the diagonal of B intersects the top edge of the panel, adjust the pointer to C and treat this case as if the diagonal offset were zero. This skips over the region that was not packed. (Note we assume the diagonal offset is a multiple of MR; this assumption will hold as long as the cache blocksizes are each a multiple of MR and NR.) */ \ if ( diagoffb > 0 ) \ { \ j = diagoffb; \ n = n - j; \ diagoffb = 0; \ c_cast = c_cast + (j )*cs_c; \ } \ \ /* If there is a zero region below where the diagonal of B intersects the right side of the block, shrink it to prevent "no-op" iterations from executing. */ \ if ( -diagoffb + n < k ) \ { \ k = -diagoffb + n; \ } \ \ /* Clear the temporary C buffer in case it has any infs or NaNs. */ \ PASTEMAC(ch,set0s_mxn)( MR, NR, \ ct, rs_ct, cs_ct ); \ \ /* Compute number of primary and leftover components of the m and n dimensions. */ \ n_iter = n / NR; \ n_left = n % NR; \ \ m_iter = m / MR; \ m_left = m % MR; \ \ if ( n_left ) ++n_iter; \ if ( m_left ) ++m_iter; \ \ /* Determine some increments used to step through A, B, and C. */ \ rstep_a = ps_a; \ \ cstep_b = ps_b; \ \ rstep_c = rs_c * MR; \ cstep_c = cs_c * NR; \ \ istep_a = PACKMR * k_full; \ istep_b = PACKNR * k; \ \ if ( bli_is_odd( istep_a ) ) istep_a += 1; \ if ( bli_is_odd( istep_b ) ) istep_b += 1; \ \ /* Save the pack schemas of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_schema_a( schema_a, &aux ); \ bli_auxinfo_set_schema_b( schema_b, &aux ); \ \ /* Save the imaginary stride of A to the auxinfo_t object. */ \ bli_auxinfo_set_is_a( istep_a, &aux ); \ \ /* The 'thread' argument points to the thrinfo_t node for the 2nd (jr) loop around the microkernel. Here we query the thrinfo_t node for the 1st (ir) loop around the microkernel. */ \ thrinfo_t* caucus = bli_thrinfo_sub_node( thread ); \ \ /* Query the number of threads and thread ids for each loop. */ \ dim_t jr_nt = bli_thread_n_way( thread ); \ dim_t jr_tid = bli_thread_work_id( thread ); \ dim_t ir_nt = bli_thread_n_way( caucus ); \ dim_t ir_tid = bli_thread_work_id( caucus ); \ \ dim_t jr_start, jr_end; \ dim_t ir_start, ir_end; \ dim_t jr_inc, ir_inc; \ \ /* Note that we partition the 2nd loop into two regions: the triangular part of C, and the rectangular portion. */ \ dim_t n_iter_tri; \ dim_t n_iter_rct; \ \ if ( bli_is_strictly_above_diag_n( diagoffb, k, n ) ) \ { \ /* If the entire panel of B does not intersect the diagonal, there is no triangular region, and therefore we can skip the first set of loops. */ \ n_iter_tri = 0; \ n_iter_rct = n_iter; \ } \ else \ { \ /* If the panel of B does intersect the diagonal, compute the number of iterations in the triangular (or trapezoidal) region by dividing NR into the number of rows in B. (There should never be any remainder in this division.) The number of iterations in the rectangular region is computed as the remaining number of iterations in the n dimension. */ \ n_iter_tri = ( k + diagoffb ) / NR + ( ( k + diagoffb ) % NR ? 1 : 0 ); \ n_iter_rct = n_iter - n_iter_tri; \ } \ \ /* Use round-robin assignment of micropanels to threads in the 2nd loop for the initial triangular region of B (if it exists). NOTE: We don't need to call bli_thread_range_jrir*() here since we employ a hack that calls for each thread to execute every iteration of the jr and ir loops but skip all but the pointer increment for iterations that are not assigned to it. */ \ \ b1 = b_cast; \ c1 = c_cast; \ \ /* Loop over the n dimension (NR columns at a time). */ \ for ( j = 0; j < n_iter_tri; ++j ) \ { \ ctype* restrict a1; \ ctype* restrict c11; \ ctype* restrict b2; \ \ diagoffb_j = diagoffb - ( doff_t )j*NR; \ \ /* Determine the offset to and length of the panel that was packed so we can index into the corresponding location in A. */ \ off_b0111 = 0; \ k_b0111 = bli_min( k, -diagoffb_j + NR ); \ \ a1 = a_cast; \ c11 = c1; \ \ n_cur = ( bli_is_not_edge_f( j, n_iter, n_left ) ? NR : n_left ); \ \ /* Initialize our next panel of B to be the current panel of B. */ \ b2 = b1; \ \ /* If the current panel of B intersects the diagonal, scale C by beta. If it is strictly below the diagonal, scale by one. This allows the current macro-kernel to work for both trmm and trmm3. */ \ { \ /* Compute the panel stride for the current diagonal- intersecting micro-panel. */ \ is_b_cur = k_b0111 * PACKNR; \ is_b_cur += ( bli_is_odd( is_b_cur ) ? 1 : 0 ); \ ps_b_cur = ( is_b_cur * ss_b_num ) / ss_b_den; \ \ if ( bli_trmm_my_iter( j, thread ) ) { \ \ /* Save the 4m1/3m1 imaginary stride of B to the auxinfo_t object. */ \ bli_auxinfo_set_is_b( is_b_cur, &aux ); \ \ /* Loop over the m dimension (MR rows at a time). */ \ for ( i = 0; i < m_iter; ++i ) \ { \ if ( bli_trmm_my_iter( i, caucus ) ) { \ \ ctype* restrict a1_i; \ ctype* restrict a2; \ \ m_cur = ( bli_is_not_edge_f( i, m_iter, m_left ) ? MR : m_left ); \ \ a1_i = a1 + ( off_b0111 * PACKMR ) / off_scl; \ \ /* Compute the addresses of the next panels of A and B. */ \ a2 = a1; \ if ( bli_is_last_iter_rr( i, m_iter, 0, 1 ) ) \ { \ a2 = a_cast; \ b2 = b1; \ if ( bli_is_last_iter_rr( j, n_iter, jr_tid, jr_nt ) ) \ b2 = b_cast; \ } \ \ /* Save addresses of next panels of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_next_a( a2, &aux ); \ bli_auxinfo_set_next_b( b2, &aux ); \ \ /* Handle interior and edge cases separately. */ \ if ( m_cur == MR && n_cur == NR ) \ { \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k_b0111, \ alpha_cast, \ a1_i, \ b1, \ beta_cast, \ c11, rs_c, cs_c, \ &aux, \ cntx \ ); \ } \ else \ { \ /* Copy edge elements of C to the temporary buffer. */ \ PASTEMAC(ch,copys_mxn)( m_cur, n_cur, \ c11, rs_c, cs_c, \ ct, rs_ct, cs_ct ); \ \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k_b0111, \ alpha_cast, \ a1_i, \ b1, \ beta_cast, \ ct, rs_ct, cs_ct, \ &aux, \ cntx \ ); \ \ /* Copy the result to the edge of C. */ \ PASTEMAC(ch,copys_mxn)( m_cur, n_cur, \ ct, rs_ct, cs_ct, \ c11, rs_c, cs_c ); \ } \ } \ \ a1 += rstep_a; \ c11 += rstep_c; \ } \ } \ \ b1 += ps_b_cur; \ } \ \ c1 += cstep_c; \ } \ \ /* If there is no rectangular region, then we're done. */ \ if ( n_iter_rct == 0 ) return; \ \ /* Use round-robin assignment of micropanels to threads in the 2nd and 1st loops the remaining triangular region of B. */ \ bli_thread_range_jrir_rr( thread, n_iter_rct, 1, FALSE, &jr_start, &jr_end, &jr_inc ); \ bli_thread_range_jrir_rr( caucus, m_iter, 1, FALSE, &ir_start, &ir_end, &ir_inc ); \ \ /* Advance the start and end iteration offsets for the rectangular region by the number of iterations used for the triangular region. */ \ jr_start += n_iter_tri; \ jr_end += n_iter_tri; \ jb0 = n_iter_tri; \ \ /* Save the resulting value of b1 from the previous loop since it represents the starting point for the rectangular region. */ \ b_cast = b1; \ \ /* Loop over the n dimension (NR columns at a time). */ \ for ( j = jr_start; j < jr_end; j += jr_inc ) \ { \ ctype* restrict a1; \ ctype* restrict c11; \ ctype* restrict b2; \ \ /* NOTE: We must index through b_cast differently since it contains the starting address of the rectangular region (which is already n_iter_tri logical iterations through B). */ \ b1 = b_cast + (j-jb0) * cstep_b; \ c1 = c_cast + j * cstep_c; \ \ n_cur = ( bli_is_not_edge_f( j, n_iter, n_left ) ? NR : n_left ); \ \ /* Initialize our next panel of B to be the current panel of B. */ \ b2 = b1; \ \ /* If the current panel of B intersects the diagonal, scale C by beta. If it is strictly below the diagonal, scale by one. This allows the current macro-kernel to work for both trmm and trmm3. */ \ { \ /* Save the 4m1/3m1 imaginary stride of B to the auxinfo_t object. */ \ bli_auxinfo_set_is_b( istep_b, &aux ); \ \ /* Loop over the m dimension (MR rows at a time). */ \ for ( i = ir_start; i < ir_end; i += ir_inc ) \ { \ ctype* restrict a2; \ \ a1 = a_cast + i * rstep_a; \ c11 = c1 + i * rstep_c; \ \ m_cur = ( bli_is_not_edge_f( i, m_iter, m_left ) ? MR : m_left ); \ \ /* Compute the addresses of the next panels of A and B. */ \ a2 = bli_trmm_get_next_a_upanel( a1, rstep_a, ir_inc ); \ if ( bli_is_last_iter_rr( i, m_iter, ir_tid, ir_nt ) ) \ { \ a2 = a_cast; \ b2 = bli_trmm_get_next_b_upanel( b1, cstep_b, jr_inc ); \ if ( bli_is_last_iter_rr( j, n_iter, jr_tid, jr_nt ) ) \ b2 = b_cast; \ } \ \ /* Save addresses of next panels of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_next_a( a2, &aux ); \ bli_auxinfo_set_next_b( b2, &aux ); \ \ /* Handle interior and edge cases separately. */ \ if ( m_cur == MR && n_cur == NR ) \ { \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k, \ alpha_cast, \ a1, \ b1, \ one, \ c11, rs_c, cs_c, \ &aux, \ cntx \ ); \ } \ else \ { \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k, \ alpha_cast, \ a1, \ b1, \ zero, \ ct, rs_ct, cs_ct, \ &aux, \ cntx \ ); \ \ /* Add the result to the edge of C. */ \ PASTEMAC(ch,adds_mxn)( m_cur, n_cur, \ ct, rs_ct, cs_ct, \ c11, rs_c, cs_c ); \ } \ } \ } \ } \ \ \ \ /*PASTEMAC(ch,fprintm)( stdout, "trmm_ru_ker_var2rr: a1", MR, k_b0111, a1, 1, MR, "%4.1f", "" );*/ \ /*PASTEMAC(ch,fprintm)( stdout, "trmm_ru_ker_var2rr: b1", k_b0111, NR, b1_i, NR, 1, "%4.1f", "" );*/ \ } INSERT_GENTFUNC_BASIC0( trmm_ru_ker_var2rr ) blis-0.9.0/frame/3/trmm/other/bli_trmm_ru_ker_var2sl.c000066400000000000000000000465751422157504600226450ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define FUNCPTR_T gemm_fp typedef void (*FUNCPTR_T) ( doff_t diagoffb, pack_t schema_a, pack_t schema_b, dim_t m, dim_t n, dim_t k, void* alpha, void* a, inc_t cs_a, dim_t pd_a, inc_t ps_a, void* b, inc_t rs_b, dim_t pd_b, inc_t ps_b, void* beta, void* c, inc_t rs_c, inc_t cs_c, cntx_t* cntx, rntm_t* rntm, thrinfo_t* thread ); static FUNCPTR_T GENARRAY(ftypes,trmm_ru_ker_var2sl); // // -- Macrokernel functions for slab partitioning ------------------------------ // void bli_trmm_ru_ker_var2sl ( obj_t* a, obj_t* b, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ) { num_t dt_exec = bli_obj_exec_dt( c ); doff_t diagoffb = bli_obj_diag_offset( b ); pack_t schema_a = bli_obj_pack_schema( a ); pack_t schema_b = bli_obj_pack_schema( b ); dim_t m = bli_obj_length( c ); dim_t n = bli_obj_width( c ); dim_t k = bli_obj_width( a ); void* buf_a = bli_obj_buffer_at_off( a ); inc_t cs_a = bli_obj_col_stride( a ); dim_t pd_a = bli_obj_panel_dim( a ); inc_t ps_a = bli_obj_panel_stride( a ); void* buf_b = bli_obj_buffer_at_off( b ); inc_t rs_b = bli_obj_row_stride( b ); dim_t pd_b = bli_obj_panel_dim( b ); inc_t ps_b = bli_obj_panel_stride( b ); void* buf_c = bli_obj_buffer_at_off( c ); inc_t rs_c = bli_obj_row_stride( c ); inc_t cs_c = bli_obj_col_stride( c ); obj_t scalar_a; obj_t scalar_b; void* buf_alpha; void* buf_beta; FUNCPTR_T f; // Detach and multiply the scalars attached to A and B. bli_obj_scalar_detach( a, &scalar_a ); bli_obj_scalar_detach( b, &scalar_b ); bli_mulsc( &scalar_a, &scalar_b ); // Grab the addresses of the internal scalar buffers for the scalar // merged above and the scalar attached to C. buf_alpha = bli_obj_internal_scalar_buffer( &scalar_b ); buf_beta = bli_obj_internal_scalar_buffer( c ); // Index into the type combination array to extract the correct // function pointer. f = ftypes[dt_exec]; // Invoke the function. f( diagoffb, schema_a, schema_b, m, n, k, buf_alpha, buf_a, cs_a, pd_a, ps_a, buf_b, rs_b, pd_b, ps_b, buf_beta, buf_c, rs_c, cs_c, cntx, rntm, thread ); } #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ doff_t diagoffb, \ pack_t schema_a, \ pack_t schema_b, \ dim_t m, \ dim_t n, \ dim_t k, \ void* alpha, \ void* a, inc_t cs_a, dim_t pd_a, inc_t ps_a, \ void* b, inc_t rs_b, dim_t pd_b, inc_t ps_b, \ void* beta, \ void* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx, \ rntm_t* rntm, \ thrinfo_t* thread \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ /* Alias some constants to simpler names. */ \ const dim_t MR = pd_a; \ const dim_t NR = pd_b; \ const dim_t PACKMR = cs_a; \ const dim_t PACKNR = rs_b; \ \ /* Query the context for the micro-kernel address and cast it to its function pointer type. */ \ PASTECH(ch,gemm_ukr_ft) \ gemm_ukr = bli_cntx_get_l3_vir_ukr_dt( dt, BLIS_GEMM_UKR, cntx ); \ \ /* Temporary C buffer for edge cases. Note that the strides of this temporary buffer are set so that they match the storage of the original C matrix. For example, if C is column-stored, ct will be column-stored as well. */ \ ctype ct[ BLIS_STACK_BUF_MAX_SIZE \ / sizeof( ctype ) ] \ __attribute__((aligned(BLIS_STACK_BUF_ALIGN_SIZE))); \ const bool col_pref = bli_cntx_l3_vir_ukr_prefers_cols_dt( dt, BLIS_GEMM_UKR, cntx ); \ const inc_t rs_ct = ( col_pref ? 1 : NR ); \ const inc_t cs_ct = ( col_pref ? MR : 1 ); \ \ ctype* restrict one = PASTEMAC(ch,1); \ ctype* restrict zero = PASTEMAC(ch,0); \ ctype* restrict a_cast = a; \ ctype* restrict b_cast = b; \ ctype* restrict c_cast = c; \ ctype* restrict alpha_cast = alpha; \ ctype* restrict beta_cast = beta; \ ctype* restrict b1; \ ctype* restrict c1; \ \ doff_t diagoffb_j; \ dim_t k_full; \ dim_t m_iter, m_left; \ dim_t n_iter, n_left; \ dim_t m_cur; \ dim_t n_cur; \ dim_t k_b0111; \ dim_t off_b0111; \ dim_t i, j, jb0; \ inc_t rstep_a; \ inc_t cstep_b; \ inc_t rstep_c, cstep_c; \ inc_t istep_a; \ inc_t istep_b; \ inc_t off_scl; \ inc_t ss_b_num; \ inc_t ss_b_den; \ inc_t ps_b_cur; \ inc_t is_b_cur; \ auxinfo_t aux; \ \ /* Assumptions/assertions: rs_a == 1 cs_a == PACKMR pd_a == MR ps_a == stride to next micro-panel of A rs_b == PACKNR cs_b == 1 pd_b == NR ps_b == stride to next micro-panel of B rs_c == (no assumptions) cs_c == (no assumptions) */ \ \ /* Safety trap: Certain indexing within this macro-kernel does not work as intended if both MR and NR are odd. */ \ if ( ( bli_is_odd( PACKMR ) && bli_is_odd( NR ) ) || \ ( bli_is_odd( PACKNR ) && bli_is_odd( MR ) ) ) bli_abort(); \ \ /* If any dimension is zero, return immediately. */ \ if ( bli_zero_dim3( m, n, k ) ) return; \ \ /* Safeguard: If the current panel of B is entirely below its diagonal, it is implicitly zero. So we do nothing. */ \ if ( bli_is_strictly_below_diag_n( diagoffb, k, n ) ) return; \ \ /* Compute k_full. For all trmm, k_full is simply k. This is needed because some parameter combinations of trmm reduce k to advance past zero regions in the triangular matrix, and when computing the imaginary stride of A (the non-triangular matrix), which is used by 4m1/3m1 implementations, we need this unreduced value of k. */ \ k_full = k; \ \ /* Compute indexing scaling factor for for 4m or 3m. This is needed because one of the packing register blocksizes (PACKMR or PACKNR) is used to index into the micro-panels of the non- triangular matrix when computing with a diagonal-intersecting micro-panel of the triangular matrix. In the case of 4m or 3m, real values are stored in both sub-panels, and so the indexing needs to occur in units of real values. The value computed here is divided into the complex pointer offset to cause the pointer to be advanced by the correct value. */ \ if ( bli_is_4mi_packed( schema_b ) || \ bli_is_3mi_packed( schema_b ) || \ bli_is_rih_packed( schema_b ) ) off_scl = 2; \ else off_scl = 1; \ \ /* Compute the storage stride scaling. Usually this is just 1. However, in the case of interleaved 3m, we need to scale the offset by 3/2. And if we are packing real-only, imag-only, or summed-only, we need to scale the computed panel sizes by 1/2 to compensate for the fact that the pointer arithmetic occurs in terms of complex elements rather than real elements. */ \ if ( bli_is_3mi_packed( schema_b ) ) { ss_b_num = 3; ss_b_den = 2; } \ else if ( bli_is_rih_packed( schema_b ) ) { ss_b_num = 1; ss_b_den = 2; } \ else { ss_b_num = 1; ss_b_den = 1; } \ \ /* If there is a zero region to the left of where the diagonal of B intersects the top edge of the panel, adjust the pointer to C and treat this case as if the diagonal offset were zero. This skips over the region that was not packed. (Note we assume the diagonal offset is a multiple of MR; this assumption will hold as long as the cache blocksizes are each a multiple of MR and NR.) */ \ if ( diagoffb > 0 ) \ { \ j = diagoffb; \ n = n - j; \ diagoffb = 0; \ c_cast = c_cast + (j )*cs_c; \ } \ \ /* If there is a zero region below where the diagonal of B intersects the right side of the block, shrink it to prevent "no-op" iterations from executing. */ \ if ( -diagoffb + n < k ) \ { \ k = -diagoffb + n; \ } \ \ /* Clear the temporary C buffer in case it has any infs or NaNs. */ \ PASTEMAC(ch,set0s_mxn)( MR, NR, \ ct, rs_ct, cs_ct ); \ \ /* Compute number of primary and leftover components of the m and n dimensions. */ \ n_iter = n / NR; \ n_left = n % NR; \ \ m_iter = m / MR; \ m_left = m % MR; \ \ if ( n_left ) ++n_iter; \ if ( m_left ) ++m_iter; \ \ /* Determine some increments used to step through A, B, and C. */ \ rstep_a = ps_a; \ \ cstep_b = ps_b; \ \ rstep_c = rs_c * MR; \ cstep_c = cs_c * NR; \ \ istep_a = PACKMR * k_full; \ istep_b = PACKNR * k; \ \ if ( bli_is_odd( istep_a ) ) istep_a += 1; \ if ( bli_is_odd( istep_b ) ) istep_b += 1; \ \ /* Save the pack schemas of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_schema_a( schema_a, &aux ); \ bli_auxinfo_set_schema_b( schema_b, &aux ); \ \ /* Save the imaginary stride of A to the auxinfo_t object. */ \ bli_auxinfo_set_is_a( istep_a, &aux ); \ \ /* The 'thread' argument points to the thrinfo_t node for the 2nd (jr) loop around the microkernel. Here we query the thrinfo_t node for the 1st (ir) loop around the microkernel. */ \ thrinfo_t* caucus = bli_thrinfo_sub_node( thread ); \ \ /* Query the number of threads and thread ids for each loop. */ \ dim_t jr_nt = bli_thread_n_way( thread ); \ dim_t jr_tid = bli_thread_work_id( thread ); \ dim_t ir_nt = bli_thread_n_way( caucus ); \ dim_t ir_tid = bli_thread_work_id( caucus ); \ \ dim_t jr_start, jr_end; \ dim_t ir_start, ir_end; \ dim_t jr_inc, ir_inc; \ \ /* Note that we partition the 2nd loop into two regions: the triangular part of C, and the rectangular portion. */ \ dim_t n_iter_tri; \ dim_t n_iter_rct; \ \ if ( bli_is_strictly_above_diag_n( diagoffb, k, n ) ) \ { \ /* If the entire panel of B does not intersect the diagonal, there is no triangular region, and therefore we can skip the first set of loops. */ \ n_iter_tri = 0; \ n_iter_rct = n_iter; \ } \ else \ { \ /* If the panel of B does intersect the diagonal, compute the number of iterations in the triangular (or trapezoidal) region by dividing NR into the number of rows in B. (There should never be any remainder in this division.) The number of iterations in the rectangular region is computed as the remaining number of iterations in the n dimension. */ \ n_iter_tri = ( k + diagoffb ) / NR + ( ( k + diagoffb ) % NR ? 1 : 0 ); \ n_iter_rct = n_iter - n_iter_tri; \ } \ \ /* Use round-robin assignment of micropanels to threads in the 2nd loop for the initial triangular region of B (if it exists). NOTE: We don't need to call bli_thread_range_jrir*() here since we employ a hack that calls for each thread to execute every iteration of the jr and ir loops but skip all but the pointer increment for iterations that are not assigned to it. */ \ \ b1 = b_cast; \ c1 = c_cast; \ \ /* Loop over the n dimension (NR columns at a time). */ \ for ( j = 0; j < n_iter_tri; ++j ) \ { \ ctype* restrict a1; \ ctype* restrict c11; \ ctype* restrict b2; \ \ diagoffb_j = diagoffb - ( doff_t )j*NR; \ \ /* Determine the offset to and length of the panel that was packed so we can index into the corresponding location in A. */ \ off_b0111 = 0; \ k_b0111 = bli_min( k, -diagoffb_j + NR ); \ \ a1 = a_cast; \ c11 = c1; \ \ n_cur = ( bli_is_not_edge_f( j, n_iter, n_left ) ? NR : n_left ); \ \ /* Initialize our next panel of B to be the current panel of B. */ \ b2 = b1; \ \ /* If the current panel of B intersects the diagonal, scale C by beta. If it is strictly below the diagonal, scale by one. This allows the current macro-kernel to work for both trmm and trmm3. */ \ { \ /* Compute the panel stride for the current diagonal- intersecting micro-panel. */ \ is_b_cur = k_b0111 * PACKNR; \ is_b_cur += ( bli_is_odd( is_b_cur ) ? 1 : 0 ); \ ps_b_cur = ( is_b_cur * ss_b_num ) / ss_b_den; \ \ if ( bli_trmm_my_iter( j, thread ) ) { \ \ /* Save the 4m1/3m1 imaginary stride of B to the auxinfo_t object. */ \ bli_auxinfo_set_is_b( is_b_cur, &aux ); \ \ /* Loop over the m dimension (MR rows at a time). */ \ for ( i = 0; i < m_iter; ++i ) \ { \ if ( bli_trmm_my_iter( i, caucus ) ) { \ \ ctype* restrict a1_i; \ ctype* restrict a2; \ \ m_cur = ( bli_is_not_edge_f( i, m_iter, m_left ) ? MR : m_left ); \ \ a1_i = a1 + ( off_b0111 * PACKMR ) / off_scl; \ \ /* Compute the addresses of the next panels of A and B. */ \ a2 = a1; \ if ( bli_is_last_iter_rr( i, m_iter, 0, 1 ) ) \ { \ a2 = a_cast; \ b2 = b1; \ if ( bli_is_last_iter_rr( j, n_iter, jr_tid, jr_nt ) ) \ b2 = b_cast; \ } \ \ /* Save addresses of next panels of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_next_a( a2, &aux ); \ bli_auxinfo_set_next_b( b2, &aux ); \ \ /* Handle interior and edge cases separately. */ \ if ( m_cur == MR && n_cur == NR ) \ { \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k_b0111, \ alpha_cast, \ a1_i, \ b1, \ beta_cast, \ c11, rs_c, cs_c, \ &aux, \ cntx \ ); \ } \ else \ { \ /* Copy edge elements of C to the temporary buffer. */ \ PASTEMAC(ch,copys_mxn)( m_cur, n_cur, \ c11, rs_c, cs_c, \ ct, rs_ct, cs_ct ); \ \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k_b0111, \ alpha_cast, \ a1_i, \ b1, \ beta_cast, \ ct, rs_ct, cs_ct, \ &aux, \ cntx \ ); \ \ /* Copy the result to the edge of C. */ \ PASTEMAC(ch,copys_mxn)( m_cur, n_cur, \ ct, rs_ct, cs_ct, \ c11, rs_c, cs_c ); \ } \ } \ \ a1 += rstep_a; \ c11 += rstep_c; \ } \ } \ \ b1 += ps_b_cur; \ } \ \ c1 += cstep_c; \ } \ \ /* If there is no rectangular region, then we're done. */ \ if ( n_iter_rct == 0 ) return; \ \ /* Use slab assignment of micropanels to threads in the 2nd and 1st loops the remaining triangular region of B. */ \ bli_thread_range_jrir_sl( thread, n_iter_rct, 1, FALSE, &jr_start, &jr_end, &jr_inc ); \ bli_thread_range_jrir_sl( caucus, m_iter, 1, FALSE, &ir_start, &ir_end, &ir_inc ); \ \ /* Advance the start and end iteration offsets for the rectangular region by the number of iterations used for the triangular region. */ \ jr_start += n_iter_tri; \ jr_end += n_iter_tri; \ jb0 = n_iter_tri; \ \ /* Save the resulting value of b1 from the previous loop since it represents the starting point for the rectangular region. */ \ b_cast = b1; \ \ /* Loop over the n dimension (NR columns at a time). */ \ for ( j = jr_start; j < jr_end; j += jr_inc ) \ { \ ctype* restrict a1; \ ctype* restrict c11; \ ctype* restrict b2; \ \ /* NOTE: We must index through b_cast differently since it contains the starting address of the rectangular region (which is already n_iter_tri logical iterations through B). */ \ b1 = b_cast + (j-jb0) * cstep_b; \ c1 = c_cast + j * cstep_c; \ \ n_cur = ( bli_is_not_edge_f( j, n_iter, n_left ) ? NR : n_left ); \ \ /* Initialize our next panel of B to be the current panel of B. */ \ b2 = b1; \ \ /* If the current panel of B intersects the diagonal, scale C by beta. If it is strictly below the diagonal, scale by one. This allows the current macro-kernel to work for both trmm and trmm3. */ \ { \ /* Save the 4m1/3m1 imaginary stride of B to the auxinfo_t object. */ \ bli_auxinfo_set_is_b( istep_b, &aux ); \ \ /* Loop over the m dimension (MR rows at a time). */ \ for ( i = ir_start; i < ir_end; i += ir_inc ) \ { \ ctype* restrict a2; \ \ a1 = a_cast + i * rstep_a; \ c11 = c1 + i * rstep_c; \ \ m_cur = ( bli_is_not_edge_f( i, m_iter, m_left ) ? MR : m_left ); \ \ /* Compute the addresses of the next panels of A and B. */ \ a2 = bli_trmm_get_next_a_upanel( a1, rstep_a, ir_inc ); \ if ( bli_is_last_iter_sl( i, m_iter, ir_tid, ir_nt ) ) \ { \ a2 = a_cast; \ b2 = bli_trmm_get_next_b_upanel( b1, cstep_b, jr_inc ); \ if ( bli_is_last_iter_sl( j, n_iter, jr_tid, jr_nt ) ) \ b2 = b_cast; \ } \ \ /* Save addresses of next panels of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_next_a( a2, &aux ); \ bli_auxinfo_set_next_b( b2, &aux ); \ \ /* Handle interior and edge cases separately. */ \ if ( m_cur == MR && n_cur == NR ) \ { \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k, \ alpha_cast, \ a1, \ b1, \ one, \ c11, rs_c, cs_c, \ &aux, \ cntx \ ); \ } \ else \ { \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k, \ alpha_cast, \ a1, \ b1, \ zero, \ ct, rs_ct, cs_ct, \ &aux, \ cntx \ ); \ \ /* Add the result to the edge of C. */ \ PASTEMAC(ch,adds_mxn)( m_cur, n_cur, \ ct, rs_ct, cs_ct, \ c11, rs_c, cs_c ); \ } \ } \ } \ } \ \ \ \ /*PASTEMAC(ch,fprintm)( stdout, "trmm_ru_ker_var2sl: a1", MR, k_b0111, a1, 1, MR, "%4.1f", "" );*/ \ /*PASTEMAC(ch,fprintm)( stdout, "trmm_ru_ker_var2sl: b1", k_b0111, NR, b1_i, NR, 1, "%4.1f", "" );*/ \ } INSERT_GENTFUNC_BASIC0( trmm_ru_ker_var2sl ) blis-0.9.0/frame/3/trmm3/000077500000000000000000000000001422157504600147555ustar00rootroot00000000000000blis-0.9.0/frame/3/trmm3/bli_trmm3.h000066400000000000000000000032471422157504600170240ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "bli_trmm3_front.h" blis-0.9.0/frame/3/trmm3/bli_trmm3_front.c000066400000000000000000000143521422157504600202260ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_trmm3_front ( side_t side, obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl ) { bli_init_once(); obj_t a_local; obj_t b_local; obj_t c_local; // If alpha is zero, scale by beta and return. if ( bli_obj_equals( alpha, &BLIS_ZERO ) ) { bli_scalm( beta, c ); return; } // Alias A, B, and C so we can tweak the objects if necessary. bli_obj_alias_to( a, &a_local ); bli_obj_alias_to( b, &b_local ); bli_obj_alias_to( c, &c_local ); // Set the obj_t buffer field to the location currently implied by the row // and column offsets and then zero the offsets. If any of the original // obj_t's were views into larger matrices, this step effectively makes // those obj_t's "forget" their lineage. bli_obj_reset_origin( &a_local ); bli_obj_reset_origin( &b_local ); bli_obj_reset_origin( &c_local ); // We do not explicitly implement the cases where A is transposed. // However, we can still handle them. Specifically, if A is marked as // needing a transposition, we simply induce a transposition. This // allows us to only explicitly implement the no-transpose cases. Once // the transposition is induced, the correct algorithm will be called, // since, for example, an algorithm over a transposed lower triangular // matrix A moves in the same direction (forwards) as a non-transposed // upper triangular matrix. And with the transposition induced, the // matrix now appears to be upper triangular, so the upper triangular // algorithm will grab the correct partitions, as if it were upper // triangular (with no transpose) all along. if ( bli_obj_has_trans( &a_local ) ) { bli_obj_induce_trans( &a_local ); bli_obj_set_onlytrans( BLIS_NO_TRANSPOSE, &a_local ); } #ifdef BLIS_DISABLE_TRMM3_RIGHT // NOTE: This case casts right-side trmm3 in terms of left side. This is // necessary when the current subconfiguration uses a gemm microkernel // that assumes that the packing kernel will have already duplicated // (broadcast) element of B in the packed copy of B. Supporting // duplication within the logic that packs micropanels from triangular // matrices would be ugly, and so we simply don't support it. As a // consequence, those subconfigurations need a way to force the triangular // matrix to be on the left (and thus the general matrix to the on the // right). So our solution is that in those cases, the subconfigurations // simply #define BLIS_DISABLE_TRMM3_RIGHT. // NOTE: This case casts right-side trmm3 in terms of left side. This can // lead to the microkernel being executed on an output matrix with the // microkernel's general stride IO case (unless the microkernel supports // both both row and column IO cases as well). // NOTE: Casting right-side trmm3 in terms of left side reduces the number // of macrokernels exercised to two (trmm_ll and trmm_lu). // If A is being multiplied from the right, transpose all operands // so that we can perform the computation as if A were being multiplied // from the left. if ( bli_is_right( side ) ) { bli_toggle_side( &side ); bli_obj_induce_trans( &a_local ); bli_obj_induce_trans( &b_local ); bli_obj_induce_trans( &c_local ); } #else // An optimization: If C is stored by rows and the micro-kernel prefers // contiguous columns, or if C is stored by columns and the micro-kernel // prefers contiguous rows, transpose the entire operation to allow the // micro-kernel to access elements of C in its preferred manner. if ( bli_cntx_l3_vir_ukr_dislikes_storage_of( &c_local, BLIS_GEMM_UKR, cntx ) ) { bli_toggle_side( &side ); bli_obj_induce_trans( &a_local ); bli_obj_induce_trans( &b_local ); bli_obj_induce_trans( &c_local ); } // If A is being multiplied from the right, swap A and B so that // the matrix will actually be on the right. if ( bli_is_right( side ) ) { bli_obj_swap( &a_local, &b_local ); } #endif // Set the pack schemas within the objects. bli_l3_set_schemas( &a_local, &b_local, &c_local, cntx ); // Parse and interpret the contents of the rntm_t object to properly // set the ways of parallelism for each loop, and then make any // additional modifications necessary for the current operation. bli_rntm_set_ways_for_op ( BLIS_TRMM3, side, bli_obj_length( &c_local ), bli_obj_width( &c_local ), bli_obj_width( &a_local ), rntm ); // Invoke the internal back-end. bli_l3_thread_decorator ( bli_l3_int, BLIS_TRMM, // operation family id alpha, &a_local, &b_local, beta, &c_local, cntx, rntm, cntl ); } blis-0.9.0/frame/3/trmm3/bli_trmm3_front.h000066400000000000000000000035411422157504600202310ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void bli_trmm3_front ( side_t side, obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl ); blis-0.9.0/frame/3/trsm/000077500000000000000000000000001422157504600147005ustar00rootroot00000000000000blis-0.9.0/frame/3/trsm/bli_trsm.h000066400000000000000000000033331422157504600166660ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "bli_trsm_cntl.h" #include "bli_trsm_front.h" #include "bli_trsm_var.h" blis-0.9.0/frame/3/trsm/bli_trsm_blk_var1.c000066400000000000000000000142561422157504600204500ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" //#define PRINT void bli_trsm_blk_var1 ( obj_t* a, obj_t* b, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ) { dim_t my_start, my_end; dim_t b_alg; // Determine the direction in which to partition (forwards or backwards). dir_t direct = bli_l3_direct( a, b, c, cntl ); // Prune any zero region that exists along the partitioning dimension. bli_l3_prune_unref_mparts_m( a, b, c, cntl ); // Isolate the diagonal block A11 and its corresponding row panel C1. const dim_t kc = bli_obj_width_after_trans( a ); obj_t a11, c1; bli_acquire_mpart_mdim( direct, BLIS_SUBPART1, 0, kc, a, &a11 ); bli_acquire_mpart_mdim( direct, BLIS_SUBPART1, 0, kc, c, &c1 ); // All threads iterate over the entire diagonal block A11. my_start = 0; my_end = kc; #ifdef PRINT printf( "bli_trsm_blk_var1(): a11 is %d x %d at offsets (%3d, %3d)\n", (int)bli_obj_length( &a11 ), (int)bli_obj_width( &a11 ), (int)bli_obj_row_off( &a11 ), (int)bli_obj_col_off( &a11 ) ); printf( "bli_trsm_blk_var1(): entering trsm subproblem loop.\n" ); #endif // Partition along the m dimension for the trsm subproblem. for ( dim_t i = my_start; i < my_end; i += b_alg ) { obj_t a11_1, c1_1; b_alg = bli_determine_blocksize( direct, i, my_end, &a11, bli_cntl_bszid( cntl ), cntx ); // Acquire partitions for A1 and C1. bli_acquire_mpart_mdim( direct, BLIS_SUBPART1, i, b_alg, &a11, &a11_1 ); bli_acquire_mpart_mdim( direct, BLIS_SUBPART1, i, b_alg, &c1, &c1_1 ); #ifdef PRINT printf( "bli_trsm_blk_var1(): a11_1 is %d x %d at offsets (%3d, %3d)\n", (int)bli_obj_length( &a11_1 ), (int)bli_obj_width( &a11_1 ), (int)bli_obj_row_off( &a11_1 ), (int)bli_obj_col_off( &a11_1 ) ); #endif // Perform trsm subproblem. bli_l3_int ( &BLIS_ONE, &a11_1, b, &BLIS_ONE, &c1_1, cntx, rntm, bli_cntl_sub_prenode( cntl ), bli_thrinfo_sub_prenode( thread ) ); } #ifdef PRINT printf( "bli_trsm_blk_var1(): finishing trsm subproblem loop.\n" ); #endif // We must execute a barrier here because the upcoming rank-k update // requires the packed matrix B to be fully updated by the trsm // subproblem. bli_thread_barrier( thread ); // Isolate the remaining part of the column panel matrix A, which we do by // acquiring the subpartition ahead of A11 (that is, A21 or A01, depending // on whether we are moving forwards or backwards, respectively). obj_t ax1, cx1; bli_acquire_mpart_mdim( direct, BLIS_SUBPART1A, 0, kc, a, &ax1 ); bli_acquire_mpart_mdim( direct, BLIS_SUBPART1A, 0, kc, c, &cx1 ); #ifdef PRINT printf( "bli_trsm_blk_var1(): ax1 is %d x %d at offsets (%3d, %3d)\n", (int)bli_obj_length( &ax1 ), (int)bli_obj_width( &ax1 ), (int)bli_obj_row_off( &ax1 ), (int)bli_obj_col_off( &ax1 ) ); #endif // Determine the current thread's subpartition range for the gemm // subproblem over Ax1. bli_thread_range_mdim ( direct, thread, &ax1, b, &cx1, cntl, cntx, &my_start, &my_end ); #ifdef PRINT printf( "bli_trsm_blk_var1(): entering gemm subproblem loop (%d->%d).\n", (int)my_start, (int)my_end ); #endif // Partition along the m dimension for the gemm subproblem. for ( dim_t i = my_start; i < my_end; i += b_alg ) { obj_t a11, c1; // Determine the current algorithmic blocksize. b_alg = bli_determine_blocksize( direct, i, my_end, &ax1, bli_cntl_bszid( cntl ), cntx ); // Acquire partitions for A1 and C1. bli_acquire_mpart_mdim( direct, BLIS_SUBPART1, i, b_alg, &ax1, &a11 ); bli_acquire_mpart_mdim( direct, BLIS_SUBPART1, i, b_alg, &cx1, &c1 ); #ifdef PRINT printf( "bli_trsm_blk_var1(): a11 is %d x %d at offsets (%3d, %3d)\n", (int)bli_obj_length( &a11 ), (int)bli_obj_width( &a11 ), (int)bli_obj_row_off( &a11 ), (int)bli_obj_col_off( &a11 ) ); #endif // Perform gemm subproblem. (Note that we use the same backend // function as before, since we're calling the same macrokernel.) bli_l3_int ( &BLIS_ONE, &a11, b, &BLIS_ONE, &c1, cntx, rntm, bli_cntl_sub_node( cntl ), bli_thrinfo_sub_node( thread ) ); } #ifdef PRINT printf( "bli_trsm_blk_var1(): finishing gemm subproblem loop.\n" ); #endif } blis-0.9.0/frame/3/trsm/bli_trsm_blk_var2.c000066400000000000000000000060031422157504600204400ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_trsm_blk_var2 ( obj_t* a, obj_t* b, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ) { obj_t b1, c1; dim_t my_start, my_end; dim_t b_alg; // Determine the direction in which to partition (forwards or backwards). dir_t direct = bli_l3_direct( a, b, c, cntl ); // Prune any zero region that exists along the partitioning dimension. bli_l3_prune_unref_mparts_n( a, b, c, cntl ); // Determine the current thread's subpartition range. bli_thread_range_ndim ( direct, thread, a, b, c, cntl, cntx, &my_start, &my_end ); // Partition along the n dimension. for ( dim_t i = my_start; i < my_end; i += b_alg ) { // Determine the current algorithmic blocksize. b_alg = bli_determine_blocksize( direct, i, my_end, b, bli_cntl_bszid( cntl ), cntx ); // Acquire partitions for B1 and C1. bli_acquire_mpart_ndim( direct, BLIS_SUBPART1, i, b_alg, b, &b1 ); bli_acquire_mpart_ndim( direct, BLIS_SUBPART1, i, b_alg, c, &c1 ); // Perform trsm subproblem. bli_l3_int ( &BLIS_ONE, a, &b1, &BLIS_ONE, &c1, cntx, rntm, bli_cntl_sub_node( cntl ), bli_thrinfo_sub_node( thread ) ); } } blis-0.9.0/frame/3/trsm/bli_trsm_blk_var3.c000066400000000000000000000064031422157504600204450ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_trsm_blk_var3 ( obj_t* a, obj_t* b, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ) { obj_t a1, b1; dim_t b_alg; // Determine the direction in which to partition (forwards or backwards). dir_t direct = bli_l3_direct( a, b, c, cntl ); // Prune any zero region that exists along the partitioning dimension. bli_l3_prune_unref_mparts_k( a, b, c, cntl ); // Query dimension in partitioning direction. dim_t k_trans = bli_obj_width_after_trans( a ); // Partition along the k dimension. for ( dim_t i = 0; i < k_trans; i += b_alg ) { // Determine the current algorithmic blocksize. b_alg = bli_trsm_determine_kc( direct, i, k_trans, a, b, bli_cntl_bszid( cntl ), cntx ); // Acquire partitions for A1 and B1. bli_acquire_mpart_ndim( direct, BLIS_SUBPART1, i, b_alg, a, &a1 ); bli_acquire_mpart_mdim( direct, BLIS_SUBPART1, i, b_alg, b, &b1 ); // Perform trsm subproblem. bli_l3_int ( &BLIS_ONE, &a1, &b1, &BLIS_ONE, c, cntx, rntm, bli_cntl_sub_node( cntl ), bli_thrinfo_sub_node( thread ) ); //bli_thread_ibarrier( thread ); bli_thread_barrier( bli_thrinfo_sub_node( thread ) ); // This variant executes multiple rank-k updates. Therefore, if the // internal alpha scalars on A/B and C are non-zero, we must ensure // that they are only used in the first iteration. if ( i == 0 ) { bli_obj_scalar_reset( a ); bli_obj_scalar_reset( b ); bli_obj_scalar_reset( c ); } } } blis-0.9.0/frame/3/trsm/bli_trsm_cntl.c000066400000000000000000000205621422157504600177040ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" cntl_t* bli_trsm_cntl_create ( rntm_t* rntm, side_t side, pack_t schema_a, pack_t schema_b, void_fp ker ) { if ( bli_is_left( side ) ) return bli_trsm_l_cntl_create( rntm, schema_a, schema_b, ker ); else return bli_trsm_r_cntl_create( rntm, schema_a, schema_b, ker ); } cntl_t* bli_trsm_l_cntl_create ( rntm_t* rntm, pack_t schema_a, pack_t schema_b, void_fp ker ) { void_fp macro_kernel_p; // Set the default macrokernel. If a non-NULL kernel function pointer is // passed in, we use that instead. macro_kernel_p = bli_trsm_xx_ker_var2; if ( ker ) macro_kernel_p = ker; const opid_t family = BLIS_TRSM; // // Create nodes for packing A and the macro-kernel (gemm branch). // cntl_t* gemm_cntl_bu_ke = bli_trsm_cntl_create_node ( rntm, // the thread's runtime structure family, // the operation family BLIS_MR, // needed for bli_thrinfo_rgrow() NULL, // variant function pointer not used NULL // no sub-node; this is the leaf of the tree. ); cntl_t* gemm_cntl_bp_bu = bli_trsm_cntl_create_node ( rntm, family, BLIS_NR, // not used by macro-kernel, but needed for bli_thrinfo_rgrow() macro_kernel_p, gemm_cntl_bu_ke ); // Create a node for packing matrix A. cntl_t* gemm_cntl_packa = bli_packm_cntl_create_node ( rntm, bli_l3_packa, // trsm operation's packm function for A. BLIS_MR, BLIS_MR, FALSE, // do NOT invert diagonal TRUE, // reverse iteration if upper? FALSE, // reverse iteration if lower? schema_a, // normally BLIS_PACKED_ROW_PANELS BLIS_BUFFER_FOR_A_BLOCK, gemm_cntl_bp_bu ); // // Create nodes for packing A and the macro-kernel (trsm branch). // cntl_t* trsm_cntl_bu_ke = bli_trsm_cntl_create_node ( rntm, // the thread's runtime structure family, // the operation family BLIS_MR, // needed for bli_thrinfo_rgrow() NULL, // variant function pointer not used NULL // no sub-node; this is the leaf of the tree. ); cntl_t* trsm_cntl_bp_bu = bli_trsm_cntl_create_node ( rntm, family, BLIS_NR, // not used by macro-kernel, but needed for bli_thrinfo_rgrow() macro_kernel_p, trsm_cntl_bu_ke ); // Create a node for packing matrix A. cntl_t* trsm_cntl_packa = bli_packm_cntl_create_node ( rntm, bli_l3_packa, // trsm operation's packm function for A. BLIS_MR, BLIS_MR, #ifdef BLIS_ENABLE_TRSM_PREINVERSION TRUE, // invert diagonal #else FALSE, // do NOT invert diagonal #endif TRUE, // reverse iteration if upper? FALSE, // reverse iteration if lower? schema_a, // normally BLIS_PACKED_ROW_PANELS BLIS_BUFFER_FOR_A_BLOCK, trsm_cntl_bp_bu ); // ------------------------------------------------------------------------- // Create a node for partitioning the m dimension by MC. // NOTE: We attach the gemm sub-tree as the main branch. cntl_t* trsm_cntl_op_bp = bli_trsm_cntl_create_node ( rntm, family, BLIS_MC, bli_trsm_blk_var1, gemm_cntl_packa ); // Attach the trsm sub-tree as the auxiliary "prenode" branch. bli_cntl_set_sub_prenode( trsm_cntl_packa, trsm_cntl_op_bp ); // ------------------------------------------------------------------------- // Create a node for packing matrix B. cntl_t* trsm_cntl_packb = bli_packm_cntl_create_node ( rntm, bli_l3_packb, BLIS_NR, BLIS_MR, FALSE, // do NOT invert diagonal FALSE, // reverse iteration if upper? FALSE, // reverse iteration if lower? schema_b, // normally BLIS_PACKED_COL_PANELS BLIS_BUFFER_FOR_B_PANEL, trsm_cntl_op_bp ); // Create a node for partitioning the k dimension by KC. cntl_t* trsm_cntl_mm_op = bli_trsm_cntl_create_node ( rntm, family, BLIS_KC, bli_trsm_blk_var3, trsm_cntl_packb ); // Create a node for partitioning the n dimension by NC. cntl_t* trsm_cntl_vl_mm = bli_trsm_cntl_create_node ( rntm, family, BLIS_NC, bli_trsm_blk_var2, trsm_cntl_mm_op ); return trsm_cntl_vl_mm; } cntl_t* bli_trsm_r_cntl_create ( rntm_t* rntm, pack_t schema_a, pack_t schema_b, void_fp ker ) { // NOTE: trsm macrokernels are presently disabled for right-side execution. // Set the default macrokernel. If a non-NULL kernel function pointer is // passed in, we use that instead. void_fp macro_kernel_p = bli_trsm_xx_ker_var2; if ( ker ) macro_kernel_p = ker; const opid_t family = BLIS_TRSM; // Create two nodes for the macro-kernel. cntl_t* trsm_cntl_bu_ke = bli_trsm_cntl_create_node ( rntm, family, BLIS_MR, // needed for bli_thrinfo_rgrow() NULL, // variant function pointer not used NULL // no sub-node; this is the leaf of the tree. ); cntl_t* trsm_cntl_bp_bu = bli_trsm_cntl_create_node ( rntm, family, BLIS_NR, // not used by macro-kernel, but needed for bli_thrinfo_rgrow() macro_kernel_p, trsm_cntl_bu_ke ); // Create a node for packing matrix A. cntl_t* trsm_cntl_packa = bli_packm_cntl_create_node ( rntm, bli_l3_packa, BLIS_NR, BLIS_MR, FALSE, // do NOT invert diagonal FALSE, // reverse iteration if upper? FALSE, // reverse iteration if lower? schema_a, // normally BLIS_PACKED_ROW_PANELS BLIS_BUFFER_FOR_A_BLOCK, trsm_cntl_bp_bu ); // Create a node for partitioning the m dimension by MC. cntl_t* trsm_cntl_op_bp = bli_trsm_cntl_create_node ( rntm, family, BLIS_MC, bli_trsm_blk_var1, trsm_cntl_packa ); // Create a node for packing matrix B. cntl_t* trsm_cntl_packb = bli_packm_cntl_create_node ( rntm, bli_l3_packb, BLIS_MR, BLIS_MR, TRUE, // do NOT invert diagonal FALSE, // reverse iteration if upper? TRUE, // reverse iteration if lower? schema_b, // normally BLIS_PACKED_COL_PANELS BLIS_BUFFER_FOR_B_PANEL, trsm_cntl_op_bp ); // Create a node for partitioning the k dimension by KC. cntl_t* trsm_cntl_mm_op = bli_trsm_cntl_create_node ( rntm, family, BLIS_KC, bli_trsm_blk_var3, trsm_cntl_packb ); // Create a node for partitioning the n dimension by NC. cntl_t* trsm_cntl_vl_mm = bli_trsm_cntl_create_node ( rntm, family, BLIS_NC, bli_trsm_blk_var2, trsm_cntl_mm_op ); return trsm_cntl_vl_mm; } void bli_trsm_cntl_free ( rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ) { bli_cntl_free( rntm, cntl, thread ); } // ----------------------------------------------------------------------------- cntl_t* bli_trsm_cntl_create_node ( rntm_t* rntm, opid_t family, bszid_t bszid, void_fp var_func, cntl_t* sub_node ) { return bli_cntl_create_node( rntm, family, bszid, var_func, NULL, sub_node ); } blis-0.9.0/frame/3/trsm/bli_trsm_cntl.h000066400000000000000000000047321422157504600177120ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ cntl_t* bli_trsm_cntl_create ( rntm_t* rntm, side_t side, pack_t schema_a, pack_t schema_b, void_fp ker ); cntl_t* bli_trsm_l_cntl_create ( rntm_t* rntm, pack_t schema_a, pack_t schema_b, void_fp ker ); cntl_t* bli_trsm_r_cntl_create ( rntm_t* rntm, pack_t schema_a, pack_t schema_b, void_fp ker ); void bli_trsm_cntl_free ( rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ); // ----------------------------------------------------------------------------- cntl_t* bli_trsm_cntl_create_node ( rntm_t* rntm, opid_t family, bszid_t bszid, void_fp var_func, cntl_t* sub_node ); blis-0.9.0/frame/3/trsm/bli_trsm_front.c000066400000000000000000000121241422157504600200670ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_trsm_front ( side_t side, obj_t* alpha, obj_t* a, obj_t* b, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl ) { bli_init_once(); obj_t a_local; obj_t b_local; obj_t c_local; #if 0 #ifdef BLIS_ENABLE_SMALL_MATRIX_TRSM gint_t status = bli_trsm_small( side, alpha, a, b, cntx, cntl ); if ( status == BLIS_SUCCESS ) return; #endif #endif // If alpha is zero, scale by beta and return. if ( bli_obj_equals( alpha, &BLIS_ZERO ) ) { bli_scalm( alpha, b ); return; } // Alias A and B so we can tweak the objects if necessary. bli_obj_alias_to( a, &a_local ); bli_obj_alias_to( b, &b_local ); bli_obj_alias_to( b, &c_local ); // Set the obj_t buffer field to the location currently implied by the row // and column offsets and then zero the offsets. If any of the original // obj_t's were views into larger matrices, this step effectively makes // those obj_t's "forget" their lineage. bli_obj_reset_origin( &a_local ); bli_obj_reset_origin( &b_local ); bli_obj_reset_origin( &c_local ); // We do not explicitly implement the cases where A is transposed. // However, we can still handle them. Specifically, if A is marked as // needing a transposition, we simply induce a transposition. This // allows us to only explicitly implement the no-transpose cases. Once // the transposition is induced, the correct algorithm will be called, // since, for example, an algorithm over a transposed lower triangular // matrix A moves in the same direction (forwards) as a non-transposed // upper triangular matrix. And with the transposition induced, the // matrix now appears to be upper triangular, so the upper triangular // algorithm will grab the correct partitions, as if it were upper // triangular (with no transpose) all along. if ( bli_obj_has_trans( &a_local ) ) { bli_obj_induce_trans( &a_local ); bli_obj_set_onlytrans( BLIS_NO_TRANSPOSE, &a_local ); } #if 1 // If A is being solved against from the right, transpose all operands // so that we can perform the computation as if A were being solved // from the left. if ( bli_is_right( side ) ) { bli_toggle_side( &side ); bli_obj_induce_trans( &a_local ); bli_obj_induce_trans( &b_local ); bli_obj_induce_trans( &c_local ); } #else // NOTE: Enabling this code requires that BLIS NOT be configured with // BLIS_RELAX_MCNR_NCMR_CONSTRAINTS defined. #ifdef BLIS_RELAX_MCNR_NCMR_CONSTRAINTS #error "BLIS_RELAX_MCNR_NCMR_CONSTRAINTS must not be defined for current trsm_r implementation." #endif // If A is being solved against from the right, swap A and B so that // the triangular matrix will actually be on the right. if ( bli_is_right( side ) ) { bli_obj_swap( &a_local, &b_local ); } #endif // Set the pack schemas within the objects. bli_l3_set_schemas( &a_local, &b_local, &c_local, cntx ); // Parse and interpret the contents of the rntm_t object to properly // set the ways of parallelism for each loop, and then make any // additional modifications necessary for the current operation. bli_rntm_set_ways_for_op ( BLIS_TRSM, side, bli_obj_length( &c_local ), bli_obj_width( &c_local ), bli_obj_width( &a_local ), rntm ); // Invoke the internal back-end. bli_l3_thread_decorator ( bli_l3_int, BLIS_TRSM, // operation family id alpha, &a_local, &b_local, alpha, &c_local, cntx, rntm, cntl ); } blis-0.9.0/frame/3/trsm/bli_trsm_front.h000066400000000000000000000040711422157504600200760ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void bli_trsm_front ( side_t side, obj_t* alpha, obj_t* a, obj_t* b, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl ); #ifdef BLIS_ENABLE_SMALL_MATRIX err_t bli_trsm_small ( side_t side, obj_t* alpha, obj_t* a, obj_t* b, cntx_t* cntx, cntl_t* cntl ); #endif blis-0.9.0/frame/3/trsm/bli_trsm_ll_ker_var2.c000066400000000000000000000370641422157504600211530ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define FUNCPTR_T gemm_fp typedef void (*FUNCPTR_T) ( doff_t diagoffa, pack_t schema_a, pack_t schema_b, dim_t m, dim_t n, dim_t k, void* alpha1, void* a, inc_t cs_a, dim_t pd_a, inc_t ps_a, void* b, inc_t rs_b, dim_t pd_b, inc_t ps_b, void* alpha2, void* c, inc_t rs_c, inc_t cs_c, cntx_t* cntx, rntm_t* rntm, thrinfo_t* thread ); static FUNCPTR_T GENARRAY(ftypes,trsm_ll_ker_var2); void bli_trsm_ll_ker_var2 ( obj_t* a, obj_t* b, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ) { num_t dt_exec = bli_obj_exec_dt( c ); doff_t diagoffa = bli_obj_diag_offset( a ); pack_t schema_a = bli_obj_pack_schema( a ); pack_t schema_b = bli_obj_pack_schema( b ); dim_t m = bli_obj_length( c ); dim_t n = bli_obj_width( c ); dim_t k = bli_obj_width( a ); void* buf_a = bli_obj_buffer_at_off( a ); inc_t cs_a = bli_obj_col_stride( a ); dim_t pd_a = bli_obj_panel_dim( a ); inc_t ps_a = bli_obj_panel_stride( a ); void* buf_b = bli_obj_buffer_at_off( b ); inc_t rs_b = bli_obj_row_stride( b ); dim_t pd_b = bli_obj_panel_dim( b ); inc_t ps_b = bli_obj_panel_stride( b ); void* buf_c = bli_obj_buffer_at_off( c ); inc_t rs_c = bli_obj_row_stride( c ); inc_t cs_c = bli_obj_col_stride( c ); void* buf_alpha1; void* buf_alpha2; FUNCPTR_T f; // Grab the address of the internal scalar buffer for the scalar // attached to B (the non-triangular matrix). This will be the alpha // scalar used in the gemmtrsm subproblems (ie: the scalar that would // be applied to the packed copy of B prior to it being updated by // the trsm subproblem). This scalar may be unit, if for example it // was applied during packing. buf_alpha1 = bli_obj_internal_scalar_buffer( b ); // Grab the address of the internal scalar buffer for the scalar // attached to C. This will be the "beta" scalar used in the gemm-only // subproblems that correspond to micro-panels that do not intersect // the diagonal. We need this separate scalar because it's possible // that the alpha attached to B was reset, if it was applied during // packing. buf_alpha2 = bli_obj_internal_scalar_buffer( c ); // Index into the type combination array to extract the correct // function pointer. f = ftypes[dt_exec]; // Invoke the function. f( diagoffa, schema_a, schema_b, m, n, k, buf_alpha1, buf_a, cs_a, pd_a, ps_a, buf_b, rs_b, pd_b, ps_b, buf_alpha2, buf_c, rs_c, cs_c, cntx, rntm, thread ); } #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ doff_t diagoffa, \ pack_t schema_a, \ pack_t schema_b, \ dim_t m, \ dim_t n, \ dim_t k, \ void* alpha1, \ void* a, inc_t cs_a, dim_t pd_a, inc_t ps_a, \ void* b, inc_t rs_b, dim_t pd_b, inc_t ps_b, \ void* alpha2, \ void* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx, \ rntm_t* rntm, \ thrinfo_t* thread \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ /* Alias some constants to simpler names. */ \ const dim_t MR = pd_a; \ const dim_t NR = pd_b; \ const dim_t PACKMR = cs_a; \ const dim_t PACKNR = rs_b; \ \ /* Cast the micro-kernel address to its function pointer type. */ \ PASTECH(ch,gemmtrsm_ukr_ft) \ gemmtrsm_ukr = bli_cntx_get_l3_vir_ukr_dt( dt, BLIS_GEMMTRSM_L_UKR, cntx ); \ PASTECH(ch,gemm_ukr_ft) \ gemm_ukr = bli_cntx_get_l3_vir_ukr_dt( dt, BLIS_GEMM_UKR, cntx ); \ \ /* Temporary C buffer for edge cases. Note that the strides of this temporary buffer are set so that they match the storage of the original C matrix. For example, if C is column-stored, ct will be column-stored as well. */ \ /* ctype ct[ BLIS_STACK_BUF_MAX_SIZE \ / sizeof( ctype ) ] \ __attribute__((aligned(BLIS_STACK_BUF_ALIGN_SIZE))); \ const bool col_pref = bli_cntx_l3_vir_ukr_prefers_cols_dt( dt, BLIS_GEMM_UKR, cntx ); \ const inc_t rs_ct = ( col_pref ? 1 : NR ); \ const inc_t cs_ct = ( col_pref ? MR : 1 ); \ */ \ \ ctype* restrict minus_one = PASTEMAC(ch,m1); \ ctype* restrict a_cast = a; \ ctype* restrict b_cast = b; \ ctype* restrict c_cast = c; \ ctype* restrict alpha1_cast = alpha1; \ ctype* restrict alpha2_cast = alpha2; \ ctype* restrict b1; \ ctype* restrict c1; \ \ doff_t diagoffa_i; \ dim_t k_full; \ dim_t m_iter, m_left; \ dim_t n_iter, n_left; \ dim_t m_cur; \ dim_t n_cur; \ dim_t k_a1011; \ dim_t k_a10; \ dim_t off_a10; \ dim_t off_a11; \ dim_t i, j; \ inc_t rstep_a; \ inc_t cstep_b; \ inc_t rstep_c, cstep_c; \ inc_t istep_a; \ inc_t istep_b; \ inc_t ps_a_cur; \ inc_t is_a_cur; \ auxinfo_t aux; \ \ /* Assumptions/assertions: rs_a == 1 cs_a == PACKMR pd_a == MR ps_a == stride to next micro-panel of A rs_b == PACKNR cs_b == 1 pd_b == NR ps_b == stride to next micro-panel of B rs_c == (no assumptions) cs_c == (no assumptions) */ \ \ /* Safety trap: Certain indexing within this macro-kernel does not work as intended if both MR and NR are odd. */ \ if ( ( bli_is_odd( PACKMR ) && bli_is_odd( NR ) ) || \ ( bli_is_odd( PACKNR ) && bli_is_odd( MR ) ) ) bli_abort(); \ \ /* If any dimension is zero, return immediately. */ \ if ( bli_zero_dim3( m, n, k ) ) return; \ \ /* Safeguard: If matrix A is above the diagonal, it is implicitly zero. So we do nothing. */ \ if ( bli_is_strictly_above_diag_n( diagoffa, m, k ) ) return; \ \ /* Compute k_full as k inflated up to a multiple of MR. This is needed because some parameter combinations of trsm reduce k to advance past zero regions in the triangular matrix, and when computing the imaginary stride of B (the non-triangular matrix), which is used by 4m1/3m1 implementations, we need this unreduced value of k. */ \ k_full = ( k % MR != 0 ? k + MR - ( k % MR ) : k ); \ \ /* If there is a zero region above where the diagonal of A intersects the left edge of the block, adjust the pointer to C and treat this case as if the diagonal offset were zero. This skips over the region that was not packed. (Note we assume the diagonal offset is a multiple of MR; this assumption will hold as long as the cache blocksizes are each a multiple of MR and NR.) */ \ if ( diagoffa < 0 ) \ { \ i = -diagoffa; \ m = m - i; \ diagoffa = 0; \ c_cast = c_cast + (i )*rs_c; \ } \ \ /* Check the k dimension, which needs to be a multiple of MR. If k isn't a multiple of MR, we adjust it higher to satisfy the micro- kernel, which is expecting to perform an MR x MR triangular solve. This adjustment of k is consistent with what happened when A was packed: all of its bottom/right edges were zero-padded, and furthermore, the panel that stores the bottom-right corner of the matrix has its diagonal extended into the zero-padded region (as identity). This allows the trsm of that bottom-right panel to proceed without producing any infs or NaNs that would infect the "good" values of the corresponding block of B. */ \ if ( k % MR != 0 ) k += MR - ( k % MR ); \ \ /* NOTE: We don't need to check that m is a multiple of PACKMR since we know that the underlying buffer was already allocated to have an m dimension that is a multiple of PACKMR, with the region between the last row and the next multiple of MR zero-padded accordingly. */ \ \ /* Compute number of primary and leftover components of the m and n dimensions. */ \ n_iter = n / NR; \ n_left = n % NR; \ \ m_iter = m / MR; \ m_left = m % MR; \ \ if ( n_left ) ++n_iter; \ if ( m_left ) ++m_iter; \ \ /* Determine some increments used to step through A, B, and C. */ \ rstep_a = ps_a; \ \ cstep_b = ps_b; \ \ rstep_c = rs_c * MR; \ cstep_c = cs_c * NR; \ \ istep_a = PACKMR * k; \ istep_b = PACKNR * k_full; \ \ if ( bli_is_odd( istep_a ) ) istep_a += 1; \ if ( bli_is_odd( istep_b ) ) istep_b += 1; \ \ /* Save the pack schemas of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_schema_a( schema_a, &aux ); \ bli_auxinfo_set_schema_b( schema_b, &aux ); \ \ /* Save the imaginary stride of B to the auxinfo_t object. */ \ bli_auxinfo_set_is_b( istep_b, &aux ); \ \ /* We don't bother querying the thrinfo_t node for the 1st loop because we can't parallelize that loop in trsm due to the inter-iteration dependencies that exist. */ \ /*thrinfo_t* caucus = bli_thrinfo_sub_node( thread );*/ \ \ /* Query the number of threads and thread ids for each loop. */ \ dim_t jr_nt = bli_thread_n_way( thread ); \ dim_t jr_tid = bli_thread_work_id( thread ); \ \ dim_t jr_start, jr_end; \ dim_t jr_inc; \ \ /* Determine the thread range and increment for the 2nd loop. NOTE: The definition of bli_thread_range_jrir() will depend on whether slab or round-robin partitioning was requested at configure-time. NOTE: Parallelism in the 1st loop is unattainable due to the inter-iteration dependencies present in trsm. */ \ bli_thread_range_jrir( thread, n_iter, 1, FALSE, &jr_start, &jr_end, &jr_inc ); \ \ /* Loop over the n dimension (NR columns at a time). */ \ for ( j = jr_start; j < jr_end; j += jr_inc ) \ { \ ctype* restrict a1; \ ctype* restrict c11; \ ctype* restrict b2; \ \ b1 = b_cast + j * cstep_b; \ c1 = c_cast + j * cstep_c; \ \ n_cur = ( bli_is_not_edge_f( j, n_iter, n_left ) ? NR : n_left ); \ \ /* Initialize our next panel of B to be the current panel of B. */ \ b2 = b1; \ \ a1 = a_cast; \ c11 = c1 + (0 )*rstep_c; \ \ /* Loop over the m dimension (MR rows at a time). */ \ for ( i = 0; i < m_iter; ++i ) \ { \ diagoffa_i = diagoffa + ( doff_t )i*MR; \ \ m_cur = ( bli_is_not_edge_f( i, m_iter, m_left ) ? MR : m_left ); \ \ /* If the current panel of A intersects the diagonal, use a special micro-kernel that performs a fused gemm and trsm. If the current panel of A resides below the diagonal, use a a regular gemm micro-kernel. Otherwise, if it is above the diagonal, it was not packed (because it is implicitly zero) and so we do nothing. */ \ if ( bli_intersects_diag_n( diagoffa_i, MR, k ) ) \ { \ ctype* restrict a10; \ ctype* restrict a11; \ ctype* restrict b01; \ ctype* restrict b11; \ ctype* restrict a2; \ \ /* Compute various offsets into and lengths of parts of A. */ \ off_a10 = 0; \ k_a1011 = diagoffa_i + MR; \ k_a10 = k_a1011 - MR; \ off_a11 = k_a10; \ \ /* Compute the panel stride for the current diagonal- intersecting micro-panel. */ \ is_a_cur = k_a1011 * PACKMR; \ is_a_cur += ( bli_is_odd( is_a_cur ) ? 1 : 0 ); \ ps_a_cur = is_a_cur; \ \ /* Compute the addresses of the panel A10 and the triangular block A11. */ \ a10 = a1; \ a11 = a1 + k_a10 * PACKMR; \ /*a11 = bli_ptr_inc_by_frac( a1, sizeof( ctype ), k_a10 * PACKMR, 1 );*/ \ \ /* Compute the addresses of the panel B01 and the block B11. */ \ b01 = b1 + off_a10 * PACKNR; \ b11 = b1 + off_a11 * PACKNR; \ \ /* Compute the addresses of the next panels of A and B. */ \ a2 = a1 + ps_a_cur; \ if ( bli_is_last_iter_rr( i, m_iter, 0, 1 ) ) \ { \ a2 = a_cast; \ b2 = b1; \ if ( bli_is_last_iter( j, n_iter, jr_tid, jr_nt ) ) \ b2 = b_cast; \ } \ \ /* Save addresses of next panels of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_next_a( a2, &aux ); \ bli_auxinfo_set_next_b( b2, &aux ); \ \ gemmtrsm_ukr \ ( \ m_cur, \ n_cur, \ k_a10, \ alpha1_cast, \ a10, \ a11, \ b01, \ b11, \ c11, rs_c, cs_c, \ &aux, \ cntx \ ); \ \ a1 += ps_a_cur; \ } \ else if ( bli_is_strictly_below_diag_n( diagoffa_i, MR, k ) ) \ { \ ctype* restrict a2; \ \ /* Compute the addresses of the next panels of A and B. */ \ a2 = a1 + rstep_a; \ if ( bli_is_last_iter_rr( i, m_iter, 0, 1 ) ) \ { \ a2 = a_cast; \ b2 = b1; \ if ( bli_is_last_iter( j, n_iter, jr_tid, jr_nt ) ) \ b2 = b_cast; \ } \ \ /* Save addresses of next panels of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_next_a( a2, &aux ); \ bli_auxinfo_set_next_b( b2, &aux ); \ \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ m_cur, \ n_cur, \ k, \ minus_one, \ a1, \ b1, \ alpha2_cast, \ c11, rs_c, cs_c, \ &aux, \ cntx \ ); \ \ a1 += rstep_a; \ } \ \ c11 += rstep_c; \ } \ } \ \ /* PASTEMAC(d,fprintm)( stdout, "trsm_ll_ker_var2: a11p_r computed", MR, MR, \ ( double* )a11, 1, PACKMR, "%4.1f", "" ); \ */ \ \ /* PASTEMAC(ch,fprintm)( stdout, "trsm_ll_ker_var2: a1 (diag)", MR, k_a1011, a1, 1, MR, "%5.2f", "" ); \ PASTEMAC(ch,fprintm)( stdout, "trsm_ll_ker_var2: a11 (diag)", MR, MR, a11, 1, MR, "%5.2f", "" ); \ PASTEMAC(ch,fprintm)( stdout, "trsm_ll_ker_var2: b1 (diag)", k_a1011, NR, bp_i, NR, 1, "%5.2f", "" ); \ PASTEMAC(ch,fprintm)( stdout, "trsm_ll_ker_var2: bp11 (diag)", MR, NR, bp11, NR, 1, "%5.2f", "" ); \ */ \ \ /* PASTEMAC(ch,fprintm)( stdout, "trsm_ll_ker_var2: a1 (ndiag)", MR, k, a1, 1, MR, "%5.2f", "" ); \ PASTEMAC(ch,fprintm)( stdout, "trsm_ll_ker_var2: b1 (ndiag)", k, NR, bp, NR, 1, "%5.2f", "" ); \ */ \ } INSERT_GENTFUNC_BASIC0( trsm_ll_ker_var2 ) blis-0.9.0/frame/3/trsm/bli_trsm_lu_ker_var2.c000066400000000000000000000400331422157504600211520ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define FUNCPTR_T gemm_fp typedef void (*FUNCPTR_T) ( doff_t diagoffa, pack_t schema_a, pack_t schema_b, dim_t m, dim_t n, dim_t k, void* alpha1, void* a, inc_t cs_a, dim_t pd_a, inc_t ps_a, void* b, inc_t rs_b, dim_t pd_b, inc_t ps_b, void* alpha2, void* c, inc_t rs_c, inc_t cs_c, cntx_t* cntx, rntm_t* rntm, thrinfo_t* thread ); static FUNCPTR_T GENARRAY(ftypes,trsm_lu_ker_var2); void bli_trsm_lu_ker_var2 ( obj_t* a, obj_t* b, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ) { num_t dt_exec = bli_obj_exec_dt( c ); doff_t diagoffa = bli_obj_diag_offset( a ); pack_t schema_a = bli_obj_pack_schema( a ); pack_t schema_b = bli_obj_pack_schema( b ); dim_t m = bli_obj_length( c ); dim_t n = bli_obj_width( c ); dim_t k = bli_obj_width( a ); void* buf_a = bli_obj_buffer_at_off( a ); inc_t cs_a = bli_obj_col_stride( a ); dim_t pd_a = bli_obj_panel_dim( a ); inc_t ps_a = bli_obj_panel_stride( a ); void* buf_b = bli_obj_buffer_at_off( b ); inc_t rs_b = bli_obj_row_stride( b ); dim_t pd_b = bli_obj_panel_dim( b ); inc_t ps_b = bli_obj_panel_stride( b ); void* buf_c = bli_obj_buffer_at_off( c ); inc_t rs_c = bli_obj_row_stride( c ); inc_t cs_c = bli_obj_col_stride( c ); void* buf_alpha1; void* buf_alpha2; FUNCPTR_T f; // Grab the address of the internal scalar buffer for the scalar // attached to B (the non-triangular matrix). This will be the alpha // scalar used in the gemmtrsm subproblems (ie: the scalar that would // be applied to the packed copy of B prior to it being updated by // the trsm subproblem). This scalar may be unit, if for example it // was applied during packing. buf_alpha1 = bli_obj_internal_scalar_buffer( b ); // Grab the address of the internal scalar buffer for the scalar // attached to C. This will be the "beta" scalar used in the gemm-only // subproblems that correspond to micro-panels that do not intersect // the diagonal. We need this separate scalar because it's possible // that the alpha attached to B was reset, if it was applied during // packing. buf_alpha2 = bli_obj_internal_scalar_buffer( c ); // Index into the type combination array to extract the correct // function pointer. f = ftypes[dt_exec]; // Invoke the function. f( diagoffa, schema_a, schema_b, m, n, k, buf_alpha1, buf_a, cs_a, pd_a, ps_a, buf_b, rs_b, pd_b, ps_b, buf_alpha2, buf_c, rs_c, cs_c, cntx, rntm, thread ); } #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ doff_t diagoffa, \ pack_t schema_a, \ pack_t schema_b, \ dim_t m, \ dim_t n, \ dim_t k, \ void* alpha1, \ void* a, inc_t cs_a, dim_t pd_a, inc_t ps_a, \ void* b, inc_t rs_b, dim_t pd_b, inc_t ps_b, \ void* alpha2, \ void* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx, \ rntm_t* rntm, \ thrinfo_t* thread \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ /* Alias some constants to simpler names. */ \ const dim_t MR = pd_a; \ const dim_t NR = pd_b; \ const dim_t PACKMR = cs_a; \ const dim_t PACKNR = rs_b; \ \ /* Cast the micro-kernel address to its function pointer type. */ \ PASTECH(ch,gemmtrsm_ukr_ft) \ gemmtrsm_ukr = bli_cntx_get_l3_vir_ukr_dt( dt, BLIS_GEMMTRSM_U_UKR, cntx ); \ PASTECH(ch,gemm_ukr_ft) \ gemm_ukr = bli_cntx_get_l3_vir_ukr_dt( dt, BLIS_GEMM_UKR, cntx ); \ \ /* Temporary C buffer for edge cases. Note that the strides of this temporary buffer are set so that they match the storage of the original C matrix. For example, if C is column-stored, ct will be column-stored as well. */ \ /* ctype ct[ BLIS_STACK_BUF_MAX_SIZE \ / sizeof( ctype ) ] \ __attribute__((aligned(BLIS_STACK_BUF_ALIGN_SIZE))); \ const bool col_pref = bli_cntx_l3_vir_ukr_prefers_cols_dt( dt, BLIS_GEMM_UKR, cntx ); \ const inc_t rs_ct = ( col_pref ? 1 : NR ); \ const inc_t cs_ct = ( col_pref ? MR : 1 ); \ */ \ \ ctype* restrict minus_one = PASTEMAC(ch,m1); \ ctype* restrict a_cast = a; \ ctype* restrict b_cast = b; \ ctype* restrict c_cast = c; \ ctype* restrict alpha1_cast = alpha1; \ ctype* restrict alpha2_cast = alpha2; \ ctype* restrict b1; \ ctype* restrict c1; \ \ doff_t diagoffa_i; \ dim_t k_full; \ dim_t m_iter, m_left; \ dim_t n_iter, n_left; \ dim_t m_cur; \ dim_t n_cur; \ dim_t k_a1112; \ dim_t k_a11; \ dim_t k_a12; \ dim_t off_a11; \ dim_t off_a12; \ dim_t i, j, ib; \ inc_t rstep_a; \ inc_t cstep_b; \ inc_t rstep_c, cstep_c; \ inc_t istep_a; \ inc_t istep_b; \ inc_t ps_a_cur; \ inc_t is_a_cur; \ auxinfo_t aux; \ \ /* Assumptions/assertions: rs_a == 1 cs_a == PACKMR pd_a == MR ps_a == stride to next micro-panel of A rs_b == PACKNR cs_b == 1 pd_b == NR ps_b == stride to next micro-panel of B rs_c == (no assumptions) cs_c == (no assumptions) */ \ \ /* Safety trap: Certain indexing within this macro-kernel does not work as intended if both MR and NR are odd. */ \ if ( ( bli_is_odd( PACKMR ) && bli_is_odd( NR ) ) || \ ( bli_is_odd( PACKNR ) && bli_is_odd( MR ) ) ) bli_abort(); \ \ /* If any dimension is zero, return immediately. */ \ if ( bli_zero_dim3( m, n, k ) ) return; \ \ /* Safeguard: If matrix A is below the diagonal, it is implicitly zero. So we do nothing. */ \ if ( bli_is_strictly_below_diag_n( diagoffa, m, k ) ) return; \ \ /* Compute k_full as k inflated up to a multiple of MR. This is needed because some parameter combinations of trsm reduce k to advance past zero regions in the triangular matrix, and when computing the imaginary stride of B (the non-triangular matrix), which is used by 4m1/3m1 implementations, we need this unreduced value of k. */ \ k_full = ( k % MR != 0 ? k + MR - ( k % MR ) : k ); \ \ /* If there is a zero region to the left of where the diagonal of A intersects the top edge of the block, adjust the pointer to B and treat this case as if the diagonal offset were zero. Note that we don't need to adjust the pointer to A since packm would have simply skipped over the region that was not stored. */ \ if ( diagoffa > 0 ) \ { \ i = diagoffa; \ k = k - i; \ diagoffa = 0; \ b_cast = b_cast + i * PACKNR; \ } \ \ /* If there is a zero region below where the diagonal of A intersects the right side of the block, shrink it to prevent "no-op" iterations from executing. */ \ if ( -diagoffa + k < m ) \ { \ m = -diagoffa + k; \ } \ \ /* Check the k dimension, which needs to be a multiple of MR. If k isn't a multiple of MR, we adjust it higher to satisfy the micro- kernel, which is expecting to perform an MR x MR triangular solve. This adjustment of k is consistent with what happened when A was packed: all of its bottom/right edges were zero-padded, and furthermore, the panel that stores the bottom-right corner of the matrix has its diagonal extended into the zero-padded region (as identity). This allows the trsm of that bottom-right panel to proceed without producing any infs or NaNs that would infect the "good" values of the corresponding block of B. */ \ if ( k % MR != 0 ) k += MR - ( k % MR ); \ \ /* NOTE: We don't need to check that m is a multiple of PACKMR since we know that the underlying buffer was already allocated to have an m dimension that is a multiple of PACKMR, with the region between the last row and the next multiple of MR zero-padded accordingly. */ \ \ /* Compute number of primary and leftover components of the m and n dimensions. */ \ n_iter = n / NR; \ n_left = n % NR; \ \ m_iter = m / MR; \ m_left = m % MR; \ \ if ( n_left ) ++n_iter; \ if ( m_left ) ++m_iter; \ \ /* Determine some increments used to step through A, B, and C. */ \ rstep_a = ps_a; \ \ cstep_b = ps_b; \ \ rstep_c = rs_c * MR; \ cstep_c = cs_c * NR; \ \ istep_a = PACKMR * k; \ istep_b = PACKNR * k_full; \ \ if ( bli_is_odd( istep_a ) ) istep_a += 1; \ if ( bli_is_odd( istep_b ) ) istep_b += 1; \ \ /* Save the pack schemas of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_schema_a( schema_a, &aux ); \ bli_auxinfo_set_schema_b( schema_b, &aux ); \ \ /* Save the imaginary stride of B to the auxinfo_t object. */ \ bli_auxinfo_set_is_b( istep_b, &aux ); \ \ /* We don't bother querying the thrinfo_t node for the 1st loop because we can't parallelize that loop in trsm due to the inter-iteration dependencies that exist. */ \ /*thrinfo_t* caucus = bli_thrinfo_sub_node( thread );*/ \ \ /* Query the number of threads and thread ids for each loop. */ \ dim_t jr_nt = bli_thread_n_way( thread ); \ dim_t jr_tid = bli_thread_work_id( thread ); \ \ dim_t jr_start, jr_end; \ dim_t jr_inc; \ \ /* Determine the thread range and increment for the 2nd loop. NOTE: The definition of bli_thread_range_jrir() will depend on whether slab or round-robin partitioning was requested at configure-time. NOTE: Parallelism in the 1st loop is unattainable due to the inter-iteration dependencies present in trsm. */ \ bli_thread_range_jrir( thread, n_iter, 1, FALSE, &jr_start, &jr_end, &jr_inc ); \ \ /* Loop over the n dimension (NR columns at a time). */ \ for ( j = jr_start; j < jr_end; j += jr_inc ) \ { \ ctype* restrict a1; \ ctype* restrict c11; \ ctype* restrict b2; \ \ b1 = b_cast + j * cstep_b; \ c1 = c_cast + j * cstep_c; \ \ n_cur = ( bli_is_not_edge_f( j, n_iter, n_left ) ? NR : n_left ); \ \ /* Initialize our next panel of B to be the current panel of B. */ \ b2 = b1; \ \ a1 = a_cast; \ c11 = c1 + (m_iter-1)*rstep_c; \ \ /* Loop over the m dimension (MR rows at a time). */ \ for ( ib = 0; ib < m_iter; ++ib ) \ { \ i = m_iter - 1 - ib; \ diagoffa_i = diagoffa + ( doff_t )i*MR; \ \ m_cur = ( bli_is_not_edge_b( ib, m_iter, m_left ) ? MR : m_left ); \ \ /* If the current panel of A intersects the diagonal, use a special micro-kernel that performs a fused gemm and trsm. If the current panel of A resides above the diagonal, use a a regular gemm micro-kernel. Otherwise, if it is below the diagonal, it was not packed (because it is implicitly zero) and so we do nothing. */ \ if ( bli_intersects_diag_n( diagoffa_i, MR, k ) ) \ { \ ctype* restrict a11; \ ctype* restrict a12; \ ctype* restrict b11; \ ctype* restrict b21; \ ctype* restrict a2; \ \ /* Compute various offsets into and lengths of parts of A. */ \ off_a11 = diagoffa_i; \ k_a1112 = k - off_a11;; \ k_a11 = MR; \ k_a12 = k_a1112 - MR; \ off_a12 = off_a11 + k_a11; \ \ /* Compute the panel stride for the current diagonal- intersecting micro-panel. */ \ is_a_cur = k_a1112 * PACKMR; \ is_a_cur += ( bli_is_odd( is_a_cur ) ? 1 : 0 ); \ ps_a_cur = is_a_cur; \ \ /* Compute the addresses of the triangular block A11 and the panel A12. */ \ a11 = a1; \ a12 = a1 + k_a11 * PACKMR; \ /*a12 = bli_ptr_inc_by_frac( a1, sizeof( ctype ), k_a11 * PACKMR, 1 );*/ \ \ /* Compute the addresses of the panel B01 and the block B11. */ \ b11 = b1 + off_a11 * PACKNR; \ b21 = b1 + off_a12 * PACKNR; \ \ /* Compute the addresses of the next panels of A and B. */ \ a2 = a1 + ps_a_cur; \ if ( bli_is_last_iter_rr( ib, m_iter, 0, 1 ) ) \ { \ a2 = a_cast; \ b2 = b1; \ if ( bli_is_last_iter( j, n_iter, jr_tid, jr_nt ) ) \ b2 = b_cast; \ } \ \ /* Save addresses of next panels of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_next_a( a2, &aux ); \ bli_auxinfo_set_next_b( b2, &aux ); \ \ gemmtrsm_ukr \ ( \ m_cur, \ n_cur, \ k_a12, \ alpha1_cast, \ a12, \ a11, \ b21, \ b11, \ c11, rs_c, cs_c, \ &aux, \ cntx \ ); \ \ a1 += ps_a_cur; \ } \ else if ( bli_is_strictly_above_diag_n( diagoffa_i, MR, k ) ) \ { \ ctype* restrict a2; \ \ /* Compute the addresses of the next panels of A and B. */ \ a2 = a1 + rstep_a; \ if ( bli_is_last_iter_rr( ib, m_iter, 0, 1 ) ) \ { \ a2 = a_cast; \ b2 = b1; \ if ( bli_is_last_iter( j, n_iter, jr_tid, jr_nt ) ) \ b2 = b_cast; \ } \ \ /* Save addresses of next panels of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_next_a( a2, &aux ); \ bli_auxinfo_set_next_b( b2, &aux ); \ \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ m_cur, \ n_cur, \ k, \ minus_one, \ a1, \ b1, \ alpha2_cast, \ c11, rs_c, cs_c, \ &aux, \ cntx \ ); \ \ a1 += rstep_a; \ } \ \ c11 -= rstep_c; \ } \ } \ \ /* PASTEMAC(ch,fprintm)( stdout, "trsm_lu_ker_var2: a1 (diag)", MR, k_a1112, a1, 1, MR, "%5.2f", "" ); \ PASTEMAC(ch,fprintm)( stdout, "trsm_lu_ker_var2: b11 (diag)", MR, NR, b11, NR, 1, "%6.3f", "" ); \ printf( "m_iter = %lu\n", m_iter ); \ printf( "m_cur = %lu\n", m_cur ); \ printf( "k = %lu\n", k ); \ printf( "diagoffa_i = %lu\n", diagoffa_i ); \ printf( "off_a1112 = %lu\n", off_a1112 ); \ printf( "k_a1112 = %lu\n", k_a1112 ); \ printf( "k_a12 = %lu\n", k_a12 ); \ printf( "k_a11 = %lu\n", k_a11 ); \ printf( "rs_c,cs_c = %lu %lu\n", rs_c, cs_c ); \ printf( "rs_ct,cs_ct= %lu %lu\n", rs_ct, cs_ct ); \ */ \ \ /* PASTEMAC(ch,fprintm)( stdout, "trsm_lu_ker_var2: b11 after (diag)", MR, NR, b11, NR, 1, "%5.2f", "" ); \ PASTEMAC(ch,fprintm)( stdout, "trsm_lu_ker_var2: b11 after (diag)", MR, NR, b11, NR, 1, "%5.2f", "" ); \ PASTEMAC(ch,fprintm)( stdout, "trsm_lu_ker_var2: ct after (diag)", m_cur, n_cur, ct, rs_ct, cs_ct, "%5.2f", "" ); \ */ \ } INSERT_GENTFUNC_BASIC0( trsm_lu_ker_var2 ) blis-0.9.0/frame/3/trsm/bli_trsm_rl_ker_var2.c000066400000000000000000000404001422157504600211450ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define FUNCPTR_T gemm_fp typedef void (*FUNCPTR_T) ( doff_t diagoffb, pack_t schema_a, pack_t schema_b, dim_t m, dim_t n, dim_t k, void* alpha1, void* a, inc_t cs_a, dim_t pd_a, inc_t ps_a, void* b, inc_t rs_b, dim_t pd_b, inc_t ps_b, void* alpha2, void* c, inc_t rs_c, inc_t cs_c, cntx_t* cntx, rntm_t* rntm, thrinfo_t* thread ); static FUNCPTR_T GENARRAY(ftypes,trsm_rl_ker_var2); void bli_trsm_rl_ker_var2 ( obj_t* a, obj_t* b, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ) { num_t dt_exec = bli_obj_exec_dt( c ); doff_t diagoffb = bli_obj_diag_offset( b ); pack_t schema_a = bli_obj_pack_schema( a ); pack_t schema_b = bli_obj_pack_schema( b ); dim_t m = bli_obj_length( c ); dim_t n = bli_obj_width( c ); dim_t k = bli_obj_width( a ); void* buf_a = bli_obj_buffer_at_off( a ); inc_t cs_a = bli_obj_col_stride( a ); dim_t pd_a = bli_obj_panel_dim( a ); inc_t ps_a = bli_obj_panel_stride( a ); void* buf_b = bli_obj_buffer_at_off( b ); inc_t rs_b = bli_obj_row_stride( b ); dim_t pd_b = bli_obj_panel_dim( b ); inc_t ps_b = bli_obj_panel_stride( b ); void* buf_c = bli_obj_buffer_at_off( c ); inc_t rs_c = bli_obj_row_stride( c ); inc_t cs_c = bli_obj_col_stride( c ); void* buf_alpha1; void* buf_alpha2; FUNCPTR_T f; // Grab the address of the internal scalar buffer for the scalar // attached to A (the non-triangular matrix). This will be the alpha // scalar used in the gemmtrsm subproblems (ie: the scalar that would // be applied to the packed copy of A prior to it being updated by // the trsm subproblem). This scalar may be unit, if for example it // was applied during packing. buf_alpha1 = bli_obj_internal_scalar_buffer( a ); // Grab the address of the internal scalar buffer for the scalar // attached to C. This will be the "beta" scalar used in the gemm-only // subproblems that correspond to micro-panels that do not intersect // the diagonal. We need this separate scalar because it's possible // that the alpha attached to B was reset, if it was applied during // packing. buf_alpha2 = bli_obj_internal_scalar_buffer( c ); // Index into the type combination array to extract the correct // function pointer. f = ftypes[dt_exec]; // Invoke the function. f( diagoffb, schema_a, schema_b, m, n, k, buf_alpha1, buf_a, cs_a, pd_a, ps_a, buf_b, rs_b, pd_b, ps_b, buf_alpha2, buf_c, rs_c, cs_c, cntx, rntm, thread ); } #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ doff_t diagoffb, \ pack_t schema_a, \ pack_t schema_b, \ dim_t m, \ dim_t n, \ dim_t k, \ void* alpha1, \ void* a, inc_t cs_a, dim_t pd_a, inc_t ps_a, \ void* b, inc_t rs_b, dim_t pd_b, inc_t ps_b, \ void* alpha2, \ void* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx, \ rntm_t* rntm, \ thrinfo_t* thread \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ /* Alias some constants to simpler names. */ \ const dim_t MR = pd_a; \ const dim_t NR = pd_b; \ const dim_t PACKMR = cs_a; \ const dim_t PACKNR = rs_b; \ \ /* Cast the micro-kernel address to its function pointer type. */ \ /* NOTE: We use the upper-triangular gemmtrsm ukernel because, while the current macro-kernel targets the "rl" case (right-side/lower- triangular), it becomes upper-triangular after the kernel operation is transposed so that all kernel instances are of the "left" variety (since those are the only trsm ukernels that exist). */ \ PASTECH(ch,gemmtrsm_ukr_ft) \ gemmtrsm_ukr = bli_cntx_get_l3_vir_ukr_dt( dt, BLIS_GEMMTRSM_U_UKR, cntx ); \ PASTECH(ch,gemm_ukr_ft) \ gemm_ukr = bli_cntx_get_l3_vir_ukr_dt( dt, BLIS_GEMM_UKR, cntx ); \ \ /* Temporary C buffer for edge cases. Note that the strides of this temporary buffer are set so that they match the storage of the original C matrix. For example, if C is column-stored, ct will be column-stored as well. */ \ /* ctype ct[ BLIS_STACK_BUF_MAX_SIZE \ / sizeof( ctype ) ] \ __attribute__((aligned(BLIS_STACK_BUF_ALIGN_SIZE))); \ const bool col_pref = bli_cntx_l3_vir_ukr_prefers_cols_dt( dt, BLIS_GEMM_UKR, cntx ); \ const inc_t rs_ct = ( col_pref ? 1 : NR ); \ const inc_t cs_ct = ( col_pref ? MR : 1 ); \ */ \ \ ctype* restrict minus_one = PASTEMAC(ch,m1); \ ctype* restrict a_cast = a; \ ctype* restrict b_cast = b; \ ctype* restrict c_cast = c; \ ctype* restrict alpha1_cast = alpha1; \ ctype* restrict alpha2_cast = alpha2; \ ctype* restrict b1; \ ctype* restrict c1; \ \ doff_t diagoffb_j; \ dim_t k_full; \ dim_t m_iter, m_left; \ dim_t n_iter, n_left; \ dim_t m_cur; \ dim_t n_cur; \ dim_t k_b1121; \ dim_t k_b11; \ dim_t k_b21; \ dim_t off_b11; \ dim_t off_b21; \ dim_t i, j, jb; \ inc_t rstep_a; \ inc_t cstep_b; \ inc_t rstep_c, cstep_c; \ inc_t istep_a; \ inc_t istep_b; \ inc_t ps_b_cur; \ inc_t is_b_cur; \ auxinfo_t aux; \ \ /* Assumptions/assertions: rs_a == 1 cs_a == PACKNR pd_a == NR ps_a == stride to next micro-panel of A rs_b == PACKMR cs_b == 1 pd_b == MR ps_b == stride to next micro-panel of B rs_c == (no assumptions) cs_c == (no assumptions) Note that MR/NR and PACKMR/PACKNR have been swapped to reflect the swapping of values in the control tree (ie: those values used when packing). This swapping is needed since we cast right-hand trsm in terms of transposed left-hand trsm. So, if we're going to be transposing the operation, then A needs to be packed with NR and B needs to be packed with MR (remember: B is the triangular matrix in the right-hand side parameter case). */ \ \ /* Safety trap: Certain indexing within this macro-kernel does not work as intended if both MR and NR are odd. */ \ if ( ( bli_is_odd( PACKMR ) && bli_is_odd( NR ) ) || \ ( bli_is_odd( PACKNR ) && bli_is_odd( MR ) ) ) bli_abort(); \ \ /* If any dimension is zero, return immediately. */ \ if ( bli_zero_dim3( m, n, k ) ) return; \ \ /* Safeguard: If the current panel of B is entirely above its diagonal, it is implicitly zero. So we do nothing. */ \ if ( bli_is_strictly_above_diag_n( diagoffb, k, n ) ) return; \ \ /* Compute k_full as k inflated up to a multiple of NR. This is needed because some parameter combinations of trsm reduce k to advance past zero regions in the triangular matrix, and when computing the imaginary stride of B (the non-triangular matrix), which is used by 4m1/3m1 implementations, we need this unreduced value of k. */ \ k_full = ( k % NR != 0 ? k + NR - ( k % NR ) : k ); \ \ /* If there is a zero region above where the diagonal of B intersects the left edge of the panel, adjust the pointer to A and treat this case as if the diagonal offset were zero. Note that we don't need to adjust the pointer to B since packm would have simply skipped over the region that was not stored. */ \ if ( diagoffb < 0 ) \ { \ j = -diagoffb; \ k = k - j; \ diagoffb = 0; \ a_cast = a_cast + j * PACKMR; \ } \ \ /* If there is a zero region to the right of where the diagonal of B intersects the bottom of the panel, shrink it so that we can index to the correct place in C (corresponding to the part of the panel of B that was packed). NOTE: This is NOT being done to skip over "no-op" iterations, as with the trsm_lu macro-kernel. This MUST be done for correct execution because we use n (via n_iter) to compute diagonal and index offsets for backwards movement through B. */ \ if ( diagoffb + k < n ) \ { \ n = diagoffb + k; \ } \ \ /* Check the k dimension, which needs to be a multiple of NR. If k isn't a multiple of NR, we adjust it higher to satisfy the micro- kernel, which is expecting to perform an NR x NR triangular solve. This adjustment of k is consistent with what happened when B was packed: all of its bottom/right edges were zero-padded, and furthermore, the panel that stores the bottom-right corner of the matrix has its diagonal extended into the zero-padded region (as identity). This allows the trsm of that bottom-right panel to proceed without producing any infs or NaNs that would infect the "good" values of the corresponding block of A. */ \ if ( k % NR != 0 ) k += NR - ( k % NR ); \ \ /* NOTE: We don't need to check that n is a multiple of PACKNR since we know that the underlying buffer was already allocated to have an n dimension that is a multiple of PACKNR, with the region between the last column and the next multiple of NR zero-padded accordingly. */ \ \ /* Compute number of primary and leftover components of the m and n dimensions. */ \ n_iter = n / NR; \ n_left = n % NR; \ \ m_iter = m / MR; \ m_left = m % MR; \ \ if ( n_left ) ++n_iter; \ if ( m_left ) ++m_iter; \ \ /* Determine some increments used to step through A, B, and C. */ \ rstep_a = ps_a; \ \ cstep_b = ps_b; \ \ rstep_c = rs_c * MR; \ cstep_c = cs_c * NR; \ \ istep_a = PACKMR * k_full; \ istep_b = PACKNR * k; \ \ if ( bli_is_odd( istep_a ) ) istep_a += 1; \ if ( bli_is_odd( istep_b ) ) istep_b += 1; \ \ /* Save the pack schemas of A and B to the auxinfo_t object. NOTE: We swap the values for A and B since the triangular "A" matrix is actually contained within B. */ \ bli_auxinfo_set_schema_a( schema_b, &aux ); \ bli_auxinfo_set_schema_b( schema_a, &aux ); \ \ /* Save the imaginary stride of A to the auxinfo_t object. NOTE: We swap the values for A and B since the triangular "A" matrix is actually contained within B. */ \ bli_auxinfo_set_is_b( istep_a, &aux ); \ \ b1 = b_cast; \ c1 = c_cast; \ \ /* Loop over the n dimension (NR columns at a time). */ \ for ( jb = 0; jb < n_iter; ++jb ) \ { \ ctype* restrict a1; \ ctype* restrict c11; \ ctype* restrict b11; \ ctype* restrict b21; \ ctype* restrict b2; \ \ j = n_iter - 1 - jb; \ diagoffb_j = diagoffb - ( doff_t )j*NR; \ a1 = a_cast; \ c11 = c1 + (n_iter-1)*cstep_c; \ \ n_cur = ( bli_is_not_edge_b( jb, n_iter, n_left ) ? NR : n_left ); \ \ /* Initialize our next panel of B to be the current panel of B. */ \ b2 = b1; \ \ /* If the current panel of B intersects the diagonal, use a special micro-kernel that performs a fused gemm and trsm. If the current panel of B resides below the diagonal, use a a regular gemm micro-kernel. Otherwise, if it is above the diagonal, it was not packed (because it is implicitly zero) and so we do nothing. */ \ if ( bli_intersects_diag_n( diagoffb_j, k, NR ) ) \ { \ /* Determine the offset to and length of the panel that was packed so we can index into the corresponding location in A. */ \ off_b11 = bli_max( -diagoffb_j, 0 ); \ k_b1121 = k - off_b11; \ k_b11 = NR; \ k_b21 = k_b1121 - NR; \ off_b21 = off_b11 + k_b11; \ \ /* Compute the addresses of the triangular block B11 and the panel B21. */ \ b11 = b1; \ b21 = b1 + k_b11 * PACKNR; \ /*b21 = bli_ptr_inc_by_frac( b1, sizeof( ctype ), k_b11 * PACKNR, 1 );*/ \ \ /* Compute the panel stride for the current micro-panel. */ \ is_b_cur = k_b1121 * PACKNR; \ is_b_cur += ( bli_is_odd( is_b_cur ) ? 1 : 0 ); \ ps_b_cur = is_b_cur; \ \ /* Loop over the m dimension (MR rows at a time). */ \ for ( i = 0; i < m_iter; ++i ) \ { \ if ( bli_trsm_my_iter_rr( i, thread ) ){ \ \ ctype* restrict a11; \ ctype* restrict a12; \ ctype* restrict a2; \ \ m_cur = ( bli_is_not_edge_f( i, m_iter, m_left ) ? MR : m_left ); \ \ /* Compute the addresses of the A11 block and A12 panel. */ \ a11 = a1 + off_b11 * PACKMR; \ a12 = a1 + off_b21 * PACKMR; \ \ /* Compute the addresses of the next panels of A and B. */ \ a2 = a1; \ /*if ( bli_is_last_iter_rr( i, m_iter, 0, 1 ) ) */\ if ( i + bli_thread_num_threads(thread) >= m_iter ) \ { \ a2 = a_cast; \ b2 = b1 + ps_b_cur; \ if ( bli_is_last_iter_rr( jb, n_iter, 0, 1 ) ) \ b2 = b_cast; \ } \ \ /* Save addresses of next panels of A and B to the auxinfo_t object. NOTE: We swap the values for A and B since the triangular "A" matrix is actually contained within B. */ \ bli_auxinfo_set_next_a( b2, &aux ); \ bli_auxinfo_set_next_b( a2, &aux ); \ \ gemmtrsm_ukr \ ( \ m_cur, \ n_cur, \ k_b21, \ alpha1_cast, \ b21, \ b11, \ a12, \ a11, \ c11, cs_c, rs_c, \ &aux, \ cntx \ ); \ \ } \ \ a1 += rstep_a; \ c11 += rstep_c; \ } \ \ b1 += ps_b_cur; \ } \ else if ( bli_is_strictly_below_diag_n( diagoffb_j, k, NR ) ) \ { \ /* Loop over the m dimension (MR rows at a time). */ \ for ( i = 0; i < m_iter; ++i ) \ { \ if ( bli_trsm_my_iter_rr( i, thread ) ){ \ \ ctype* restrict a2; \ \ m_cur = ( bli_is_not_edge_f( i, m_iter, m_left ) ? MR : m_left ); \ \ /* Compute the addresses of the next panels of A and B. */ \ a2 = a1; \ /*if ( bli_is_last_iter_rr( i, m_iter, 0, 1 ) ) */\ if ( i + bli_thread_num_threads(thread) >= m_iter ) \ { \ a2 = a_cast; \ b2 = b1 + cstep_b; \ if ( bli_is_last_iter_rr( jb, n_iter, 0, 1 ) ) \ b2 = b_cast; \ } \ \ /* Save addresses of next panels of A and B to the auxinfo_t object. NOTE: We swap the values for A and B since the triangular "A" matrix is actually contained within B. */ \ bli_auxinfo_set_next_a( b2, &aux ); \ bli_auxinfo_set_next_b( a2, &aux ); \ \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ m_cur, \ n_cur, \ k, \ minus_one, \ b1, \ a1, \ alpha2_cast, \ c11, cs_c, rs_c, \ &aux, \ cntx \ ); \ \ } \ \ a1 += rstep_a; \ c11 += rstep_c; \ } \ \ b1 += cstep_b; \ } \ \ c1 -= cstep_c; \ } \ } INSERT_GENTFUNC_BASIC0( trsm_rl_ker_var2 ) blis-0.9.0/frame/3/trsm/bli_trsm_ru_ker_var2.c000066400000000000000000000376161422157504600211750ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define FUNCPTR_T gemm_fp typedef void (*FUNCPTR_T) ( doff_t diagoffb, pack_t schema_a, pack_t schema_b, dim_t m, dim_t n, dim_t k, void* alpha1, void* a, inc_t cs_a, dim_t pd_a, inc_t ps_a, void* b, inc_t rs_b, dim_t pd_b, inc_t ps_b, void* alpha2, void* c, inc_t rs_c, inc_t cs_c, cntx_t* cntx, rntm_t* rntm, thrinfo_t* thread ); static FUNCPTR_T GENARRAY(ftypes,trsm_ru_ker_var2); void bli_trsm_ru_ker_var2 ( obj_t* a, obj_t* b, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ) { num_t dt_exec = bli_obj_exec_dt( c ); doff_t diagoffb = bli_obj_diag_offset( b ); pack_t schema_a = bli_obj_pack_schema( a ); pack_t schema_b = bli_obj_pack_schema( b ); dim_t m = bli_obj_length( c ); dim_t n = bli_obj_width( c ); dim_t k = bli_obj_width( a ); void* buf_a = bli_obj_buffer_at_off( a ); inc_t cs_a = bli_obj_col_stride( a ); dim_t pd_a = bli_obj_panel_dim( a ); inc_t ps_a = bli_obj_panel_stride( a ); void* buf_b = bli_obj_buffer_at_off( b ); inc_t rs_b = bli_obj_row_stride( b ); dim_t pd_b = bli_obj_panel_dim( b ); inc_t ps_b = bli_obj_panel_stride( b ); void* buf_c = bli_obj_buffer_at_off( c ); inc_t rs_c = bli_obj_row_stride( c ); inc_t cs_c = bli_obj_col_stride( c ); void* buf_alpha1; void* buf_alpha2; FUNCPTR_T f; // Grab the address of the internal scalar buffer for the scalar // attached to A (the non-triangular matrix). This will be the alpha // scalar used in the gemmtrsm subproblems (ie: the scalar that would // be applied to the packed copy of A prior to it being updated by // the trsm subproblem). This scalar may be unit, if for example it // was applied during packing. buf_alpha1 = bli_obj_internal_scalar_buffer( a ); // Grab the address of the internal scalar buffer for the scalar // attached to C. This will be the "beta" scalar used in the gemm-only // subproblems that correspond to micro-panels that do not intersect // the diagonal. We need this separate scalar because it's possible // that the alpha attached to B was reset, if it was applied during // packing. buf_alpha2 = bli_obj_internal_scalar_buffer( c ); // Index into the type combination array to extract the correct // function pointer. f = ftypes[dt_exec]; // Invoke the function. f( diagoffb, schema_a, schema_b, m, n, k, buf_alpha1, buf_a, cs_a, pd_a, ps_a, buf_b, rs_b, pd_b, ps_b, buf_alpha2, buf_c, rs_c, cs_c, cntx, rntm, thread ); } #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ doff_t diagoffb, \ pack_t schema_a, \ pack_t schema_b, \ dim_t m, \ dim_t n, \ dim_t k, \ void* alpha1, \ void* a, inc_t cs_a, dim_t pd_a, inc_t ps_a, \ void* b, inc_t rs_b, dim_t pd_b, inc_t ps_b, \ void* alpha2, \ void* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx, \ rntm_t* rntm, \ thrinfo_t* thread \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ /* Alias some constants to simpler names. */ \ const dim_t MR = pd_a; \ const dim_t NR = pd_b; \ const dim_t PACKMR = cs_a; \ const dim_t PACKNR = rs_b; \ \ /* Cast the micro-kernel address to its function pointer type. */ \ /* NOTE: We use the lower-triangular gemmtrsm ukernel because, while the current macro-kernel targets the "ru" case (right-side/upper- triangular), it becomes lower-triangular after the kernel operation is transposed so that all kernel instances are of the "left" variety (since those are the only trsm ukernels that exist). */ \ PASTECH(ch,gemmtrsm_ukr_ft) \ gemmtrsm_ukr = bli_cntx_get_l3_vir_ukr_dt( dt, BLIS_GEMMTRSM_L_UKR, cntx ); \ PASTECH(ch,gemm_ukr_ft) \ gemm_ukr = bli_cntx_get_l3_vir_ukr_dt( dt, BLIS_GEMM_UKR, cntx ); \ \ /* Temporary C buffer for edge cases. Note that the strides of this temporary buffer are set so that they match the storage of the original C matrix. For example, if C is column-stored, ct will be column-stored as well. */ \ /* ctype ct[ BLIS_STACK_BUF_MAX_SIZE \ / sizeof( ctype ) ] \ __attribute__((aligned(BLIS_STACK_BUF_ALIGN_SIZE))); \ const bool col_pref = bli_cntx_l3_vir_ukr_prefers_cols_dt( dt, BLIS_GEMM_UKR, cntx ); \ const inc_t rs_ct = ( col_pref ? 1 : NR ); \ const inc_t cs_ct = ( col_pref ? MR : 1 ); \ */ \ \ ctype* restrict minus_one = PASTEMAC(ch,m1); \ ctype* restrict a_cast = a; \ ctype* restrict b_cast = b; \ ctype* restrict c_cast = c; \ ctype* restrict alpha1_cast = alpha1; \ ctype* restrict alpha2_cast = alpha2; \ ctype* restrict b1; \ ctype* restrict c1; \ \ doff_t diagoffb_j; \ dim_t k_full; \ dim_t m_iter, m_left; \ dim_t n_iter, n_left; \ dim_t m_cur; \ dim_t n_cur; \ dim_t k_b0111; \ dim_t k_b01; \ dim_t off_b01; \ dim_t off_b11; \ dim_t i, j; \ inc_t rstep_a; \ inc_t cstep_b; \ inc_t rstep_c, cstep_c; \ inc_t istep_a; \ inc_t istep_b; \ inc_t ps_b_cur; \ inc_t is_b_cur; \ auxinfo_t aux; \ \ /* Assumptions/assertions: rs_a == 1 cs_a == PACKNR pd_a == NR ps_a == stride to next micro-panel of A rs_b == PACKMR cs_b == 1 pd_b == MR ps_b == stride to next micro-panel of B rs_c == (no assumptions) cs_c == (no assumptions) Note that MR/NR and PACKMR/PACKNR have been swapped to reflect the swapping of values in the control tree (ie: those values used when packing). This swapping is needed since we cast right-hand trsm in terms of transposed left-hand trsm. So, if we're going to be transposing the operation, then A needs to be packed with NR and B needs to be packed with MR (remember: B is the triangular matrix in the right-hand side parameter case). */ \ \ /* Safety trap: Certain indexing within this macro-kernel does not work as intended if both MR and NR are odd. */ \ if ( ( bli_is_odd( PACKMR ) && bli_is_odd( NR ) ) || \ ( bli_is_odd( PACKNR ) && bli_is_odd( MR ) ) ) bli_abort(); \ \ /* If any dimension is zero, return immediately. */ \ if ( bli_zero_dim3( m, n, k ) ) return; \ \ /* Safeguard: If the current panel of B is entirely below its diagonal, it is implicitly zero. So we do nothing. */ \ if ( bli_is_strictly_below_diag_n( diagoffb, k, n ) ) return; \ \ /* Compute k_full as k inflated up to a multiple of NR. This is needed because some parameter combinations of trsm reduce k to advance past zero regions in the triangular matrix, and when computing the imaginary stride of B (the non-triangular matrix), which is used by 4m1/3m1 implementations, we need this unreduced value of k. */ \ k_full = ( k % NR != 0 ? k + NR - ( k % NR ) : k ); \ \ /* If there is a zero region to the left of where the diagonal of B intersects the top edge of the panel, adjust the pointer to C and treat this case as if the diagonal offset were zero. This skips over the region that was not packed. (Note we assume the diagonal offset is a multiple of MR; this assumption will hold as long as the cache blocksizes are each a multiple of MR and NR.) */ \ if ( diagoffb > 0 ) \ { \ j = diagoffb; \ n = n - j; \ diagoffb = 0; \ c_cast = c_cast + (j )*cs_c; \ } \ \ /* If there is a zero region below where the diagonal of B intersects the right side of the block, shrink it to prevent "no-op" iterations from executing. */ \ if ( -diagoffb + n < k ) \ { \ k = -diagoffb + n; \ } \ \ /* Check the k dimension, which needs to be a multiple of NR. If k isn't a multiple of NR, we adjust it higher to satisfy the micro- kernel, which is expecting to perform an NR x NR triangular solve. This adjustment of k is consistent with what happened when B was packed: all of its bottom/right edges were zero-padded, and furthermore, the panel that stores the bottom-right corner of the matrix has its diagonal extended into the zero-padded region (as identity). This allows the trsm of that bottom-right panel to proceed without producing any infs or NaNs that would infect the "good" values of the corresponding block of A. */ \ if ( k % NR != 0 ) k += NR - ( k % NR ); \ \ /* NOTE: We don't need to check that n is a multiple of PACKNR since we know that the underlying buffer was already allocated to have an n dimension that is a multiple of PACKNR, with the region between the last column and the next multiple of NR zero-padded accordingly. */ \ \ /* Compute number of primary and leftover components of the m and n dimensions. */ \ n_iter = n / NR; \ n_left = n % NR; \ \ m_iter = m / MR; \ m_left = m % MR; \ \ if ( n_left ) ++n_iter; \ if ( m_left ) ++m_iter; \ \ /* Determine some increments used to step through A, B, and C. */ \ rstep_a = ps_a; \ \ cstep_b = ps_b; \ \ rstep_c = rs_c * MR; \ cstep_c = cs_c * NR; \ \ istep_a = PACKMR * k_full; \ istep_b = PACKNR * k; \ \ if ( bli_is_odd( istep_a ) ) istep_a += 1; \ if ( bli_is_odd( istep_b ) ) istep_b += 1; \ \ /* Save the pack schemas of A and B to the auxinfo_t object. NOTE: We swap the values for A and B since the triangular "A" matrix is actually contained within B. */ \ bli_auxinfo_set_schema_a( schema_b, &aux ); \ bli_auxinfo_set_schema_b( schema_a, &aux ); \ \ /* Save the imaginary stride of A to the auxinfo_t object. NOTE: We swap the values for A and B since the triangular "A" matrix is actually contained within B. */ \ bli_auxinfo_set_is_b( istep_a, &aux ); \ \ b1 = b_cast; \ c1 = c_cast; \ \ /* Loop over the n dimension (NR columns at a time). */ \ for ( j = 0; j < n_iter; ++j ) \ { \ ctype* restrict a1; \ ctype* restrict c11; \ ctype* restrict b01; \ ctype* restrict b11; \ ctype* restrict b2; \ \ diagoffb_j = diagoffb - ( doff_t )j*NR; \ a1 = a_cast; \ c11 = c1; \ \ n_cur = ( bli_is_not_edge_f( j, n_iter, n_left ) ? NR : n_left ); \ \ /* Initialize our next panel of B to be the current panel of B. */ \ b2 = b1; \ \ /* If the current panel of B intersects the diagonal, use a special micro-kernel that performs a fused gemm and trsm. If the current panel of B resides above the diagonal, use a a regular gemm micro-kernel. Otherwise, if it is below the diagonal, it was not packed (because it is implicitly zero) and so we do nothing. */ \ if ( bli_intersects_diag_n( diagoffb_j, k, NR ) ) \ { \ /* Determine the offset to and length of the panel that was packed so we can index into the corresponding location in A. */ \ off_b01 = 0; \ k_b0111 = bli_min( k, -diagoffb_j + NR ); \ k_b01 = k_b0111 - NR; \ off_b11 = k_b01; \ \ /* Compute the addresses of the panel B10 and the triangular block B11. */ \ b01 = b1; \ b11 = b1 + k_b01 * PACKNR; \ /*b11 = bli_ptr_inc_by_frac( b1, sizeof( ctype ), k_b01 * PACKNR, 1 );*/ \ \ /* Compute the panel stride for the current micro-panel. */ \ is_b_cur = k_b0111 * PACKNR; \ is_b_cur += ( bli_is_odd( is_b_cur ) ? 1 : 0 ); \ ps_b_cur = is_b_cur; \ \ /* Loop over the m dimension (MR rows at a time). */ \ for ( i = 0; i < m_iter; ++i ) \ { \ if ( bli_trsm_my_iter_rr( i, thread ) ){ \ \ ctype* restrict a10; \ ctype* restrict a11; \ ctype* restrict a2; \ \ m_cur = ( bli_is_not_edge_f( i, m_iter, m_left ) ? MR : m_left ); \ \ /* Compute the addresses of the A10 panel and A11 block. */ \ a10 = a1 + off_b01 * PACKMR; \ a11 = a1 + off_b11 * PACKMR; \ \ /* Compute the addresses of the next panels of A and B. */ \ a2 = a1; \ /*if ( bli_is_last_iter_rr( i, m_iter, 0, 1 ) ) */\ if ( i + bli_thread_num_threads(thread) >= m_iter ) \ { \ a2 = a_cast; \ b2 = b1 + ps_b_cur; \ if ( bli_is_last_iter_rr( j, n_iter, 0, 1 ) ) \ b2 = b_cast; \ } \ \ /* Save addresses of next panels of A and B to the auxinfo_t object. NOTE: We swap the values for A and B since the triangular "A" matrix is actually contained within B. */ \ bli_auxinfo_set_next_a( b2, &aux ); \ bli_auxinfo_set_next_b( a2, &aux ); \ \ gemmtrsm_ukr \ ( \ m_cur, \ n_cur, \ k_b01, \ alpha1_cast, \ b01, \ b11, \ a10, \ a11, \ c11, cs_c, rs_c, \ &aux, \ cntx \ ); \ \ } \ \ a1 += rstep_a; \ c11 += rstep_c; \ } \ \ b1 += ps_b_cur; \ } \ else if ( bli_is_strictly_above_diag_n( diagoffb_j, k, NR ) ) \ { \ /* Loop over the m dimension (MR rows at a time). */ \ for ( i = 0; i < m_iter; ++i ) \ { \ if ( bli_trsm_my_iter_rr( i, thread ) ){ \ \ ctype* restrict a2; \ \ m_cur = ( bli_is_not_edge_f( i, m_iter, m_left ) ? MR : m_left ); \ \ /* Compute the addresses of the next panels of A and B. */ \ a2 = a1; \ /*if ( bli_is_last_iter_rr( i, m_iter, 0, 1 ) ) */\ if ( i + bli_thread_num_threads(thread) >= m_iter ) \ { \ a2 = a_cast; \ b2 = b1 + cstep_b; \ if ( bli_is_last_iter_rr( j, n_iter, 0, 1 ) ) \ b2 = b_cast; \ } \ \ /* Save addresses of next panels of A and B to the auxinfo_t object. NOTE: We swap the values for A and B since the triangular "A" matrix is actually contained within B. */ \ bli_auxinfo_set_next_a( b2, &aux ); \ bli_auxinfo_set_next_b( a2, &aux ); \ \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ m_cur, \ n_cur, \ k, \ minus_one, \ b1, \ a1, \ alpha2_cast, \ c11, cs_c, rs_c, \ &aux, \ cntx \ ); \ \ } \ \ a1 += rstep_a; \ c11 += rstep_c; \ } \ \ b1 += cstep_b; \ } \ \ c1 += cstep_c; \ } \ } INSERT_GENTFUNC_BASIC0( trsm_ru_ker_var2 ) blis-0.9.0/frame/3/trsm/bli_trsm_var.h000066400000000000000000000057531422157504600175460ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype object-based interfaces. // #undef GENPROT #define GENPROT( opname ) \ \ void PASTEMAC0(opname) \ ( \ obj_t* a, \ obj_t* b, \ obj_t* c, \ cntx_t* cntx, \ rntm_t* rntm, \ cntl_t* cntl, \ thrinfo_t* thread \ ); GENPROT( trsm_blk_var1 ) GENPROT( trsm_blk_var2 ) GENPROT( trsm_blk_var3 ) GENPROT( trsm_xx_ker_var2 ) GENPROT( trsm_ll_ker_var2 ) GENPROT( trsm_lu_ker_var2 ) GENPROT( trsm_rl_ker_var2 ) GENPROT( trsm_ru_ker_var2 ) // // Prototype BLAS-like interfaces with void pointer operands. // #undef GENTPROT #define GENTPROT( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ doff_t diagoff, \ pack_t schema_a, \ pack_t schema_b, \ dim_t m, \ dim_t n, \ dim_t k, \ void* alpha1, \ void* a, inc_t cs_a, \ dim_t pd_a, inc_t ps_a, \ void* b, inc_t rs_b, \ dim_t pd_b, inc_t ps_b, \ void* alpha2, \ void* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx, \ rntm_t* rntm, \ thrinfo_t* thread \ ); INSERT_GENTPROT_BASIC0( trsm_ll_ker_var2 ) INSERT_GENTPROT_BASIC0( trsm_lu_ker_var2 ) INSERT_GENTPROT_BASIC0( trsm_rl_ker_var2 ) INSERT_GENTPROT_BASIC0( trsm_ru_ker_var2 ) blis-0.9.0/frame/3/trsm/bli_trsm_xx_ker_var2.c000066400000000000000000000054231422157504600211750ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" static l3_var_oft vars[2][2] = { { bli_trsm_ll_ker_var2, bli_trsm_lu_ker_var2 }, { bli_trsm_rl_ker_var2, bli_trsm_ru_ker_var2 } }; void bli_trsm_xx_ker_var2 ( obj_t* a, obj_t* b, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ) { dim_t side; dim_t uplo; l3_var_oft f; // Set two bools: one based on the implied side parameter (the structure // of the root object) and one based on the uplo field of the triangular // matrix's root object (whether that is matrix A or matrix B). if ( bli_obj_root_is_triangular( a ) ) { side = 0; if ( bli_obj_root_is_lower( a ) ) uplo = 0; else uplo = 1; } else // if ( bli_obj_root_is_triangular( b ) ) { side = 1; if ( bli_obj_root_is_lower( b ) ) uplo = 0; else uplo = 1; } // Index into the variant array to extract the correct function pointer. f = vars[side][uplo]; // Call the macrokernel. f ( a, b, c, cntx, rntm, cntl, thread ); } blis-0.9.0/frame/3/trsm/other/000077500000000000000000000000001422157504600160215ustar00rootroot00000000000000blis-0.9.0/frame/3/trsm/other/bli_trsm_ll_ker_var2.c000066400000000000000000000464421422157504600222740ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define FUNCPTR_T gemm_fp typedef void (*FUNCPTR_T) ( doff_t diagoffa, pack_t schema_a, pack_t schema_b, dim_t m, dim_t n, dim_t k, void* alpha1, void* a, inc_t cs_a, dim_t pd_a, inc_t ps_a, void* b, inc_t rs_b, dim_t pd_b, inc_t ps_b, void* alpha2, void* c, inc_t rs_c, inc_t cs_c, cntx_t* cntx, rntm_t* rntm, thrinfo_t* thread ); static FUNCPTR_T GENARRAY(ftypes,trsm_ll_ker_var2); void bli_trsm_ll_ker_var2 ( obj_t* a, obj_t* b, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ) { num_t dt_exec = bli_obj_exec_dt( c ); doff_t diagoffa = bli_obj_diag_offset( a ); pack_t schema_a = bli_obj_pack_schema( a ); pack_t schema_b = bli_obj_pack_schema( b ); dim_t m = bli_obj_length( c ); dim_t n = bli_obj_width( c ); dim_t k = bli_obj_width( a ); void* buf_a = bli_obj_buffer_at_off( a ); inc_t cs_a = bli_obj_col_stride( a ); dim_t pd_a = bli_obj_panel_dim( a ); inc_t ps_a = bli_obj_panel_stride( a ); void* buf_b = bli_obj_buffer_at_off( b ); inc_t rs_b = bli_obj_row_stride( b ); dim_t pd_b = bli_obj_panel_dim( b ); inc_t ps_b = bli_obj_panel_stride( b ); void* buf_c = bli_obj_buffer_at_off( c ); inc_t rs_c = bli_obj_row_stride( c ); inc_t cs_c = bli_obj_col_stride( c ); void* buf_alpha1; void* buf_alpha2; FUNCPTR_T f; // Grab the address of the internal scalar buffer for the scalar // attached to B (the non-triangular matrix). This will be the alpha // scalar used in the gemmtrsm subproblems (ie: the scalar that would // be applied to the packed copy of B prior to it being updated by // the trsm subproblem). This scalar may be unit, if for example it // was applied during packing. buf_alpha1 = bli_obj_internal_scalar_buffer( b ); // Grab the address of the internal scalar buffer for the scalar // attached to C. This will be the "beta" scalar used in the gemm-only // subproblems that correspond to micro-panels that do not intersect // the diagonal. We need this separate scalar because it's possible // that the alpha attached to B was reset, if it was applied during // packing. buf_alpha2 = bli_obj_internal_scalar_buffer( c ); // Index into the type combination array to extract the correct // function pointer. f = ftypes[dt_exec]; // Invoke the function. f( diagoffa, schema_a, schema_b, m, n, k, buf_alpha1, buf_a, cs_a, pd_a, ps_a, buf_b, rs_b, pd_b, ps_b, buf_alpha2, buf_c, rs_c, cs_c, cntx, rntm, thread ); } #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ doff_t diagoffa, \ pack_t schema_a, \ pack_t schema_b, \ dim_t m, \ dim_t n, \ dim_t k, \ void* alpha1, \ void* a, inc_t cs_a, dim_t pd_a, inc_t ps_a, \ void* b, inc_t rs_b, dim_t pd_b, inc_t ps_b, \ void* alpha2, \ void* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx, \ rntm_t* rntm, \ thrinfo_t* thread \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ /* Alias some constants to simpler names. */ \ const dim_t MR = pd_a; \ const dim_t NR = pd_b; \ const dim_t PACKMR = cs_a; \ const dim_t PACKNR = rs_b; \ \ /* Cast the micro-kernel address to its function pointer type. */ \ PASTECH(ch,gemmtrsm_ukr_ft) \ gemmtrsm_ukr = bli_cntx_get_l3_vir_ukr_dt( dt, BLIS_GEMMTRSM_L_UKR, cntx ); \ PASTECH(ch,gemm_ukr_ft) \ gemm_ukr = bli_cntx_get_l3_vir_ukr_dt( dt, BLIS_GEMM_UKR, cntx ); \ \ /* Temporary C buffer for edge cases. Note that the strides of this temporary buffer are set so that they match the storage of the original C matrix. For example, if C is column-stored, ct will be column-stored as well. */ \ ctype ct[ BLIS_STACK_BUF_MAX_SIZE \ / sizeof( ctype ) ] \ __attribute__((aligned(BLIS_STACK_BUF_ALIGN_SIZE))); \ const bool col_pref = bli_cntx_l3_vir_ukr_prefers_cols_dt( dt, BLIS_GEMM_UKR, cntx ); \ const inc_t rs_ct = ( col_pref ? 1 : NR ); \ const inc_t cs_ct = ( col_pref ? MR : 1 ); \ \ ctype* restrict zero = PASTEMAC(ch,0); \ ctype* restrict minus_one = PASTEMAC(ch,m1); \ ctype* restrict a_cast = a; \ ctype* restrict b_cast = b; \ ctype* restrict c_cast = c; \ ctype* restrict alpha1_cast = alpha1; \ ctype* restrict alpha2_cast = alpha2; \ ctype* restrict b1; \ ctype* restrict c1; \ \ doff_t diagoffa_i; \ dim_t k_full; \ dim_t m_iter, m_left; \ dim_t n_iter, n_left; \ dim_t m_cur; \ dim_t n_cur; \ dim_t k_a1011; \ dim_t k_a10; \ dim_t off_a10; \ dim_t off_a11; \ dim_t i, j; \ inc_t rstep_a; \ inc_t cstep_b; \ inc_t rstep_c, cstep_c; \ inc_t istep_a; \ inc_t istep_b; \ inc_t off_scl; \ inc_t ss_a_num; \ inc_t ss_a_den; \ inc_t ps_a_cur; \ inc_t is_a_cur; \ auxinfo_t aux; \ \ /* Assumptions/assertions: rs_a == 1 cs_a == PACKMR pd_a == MR ps_a == stride to next micro-panel of A rs_b == PACKNR cs_b == 1 pd_b == NR ps_b == stride to next micro-panel of B rs_c == (no assumptions) cs_c == (no assumptions) */ \ \ /* Safety trap: Certain indexing within this macro-kernel does not work as intended if both MR and NR are odd. */ \ if ( ( bli_is_odd( PACKMR ) && bli_is_odd( NR ) ) || \ ( bli_is_odd( PACKNR ) && bli_is_odd( MR ) ) ) bli_abort(); \ \ /* If any dimension is zero, return immediately. */ \ if ( bli_zero_dim3( m, n, k ) ) return; \ \ /* Safeguard: If matrix A is above the diagonal, it is implicitly zero. So we do nothing. */ \ if ( bli_is_strictly_above_diag_n( diagoffa, m, k ) ) return; \ \ /* Compute k_full as k inflated up to a multiple of MR. This is needed because some parameter combinations of trsm reduce k to advance past zero regions in the triangular matrix, and when computing the imaginary stride of B (the non-triangular matrix), which is used by 4m1/3m1 implementations, we need this unreduced value of k. */ \ k_full = ( k % MR != 0 ? k + MR - ( k % MR ) : k ); \ \ /* Compute indexing scaling factor for for 4m or 3m. This is needed because one of the packing register blocksizes (PACKMR or PACKNR) is used to index into the micro-panels of the non- triangular matrix when computing with a diagonal-intersecting micro-panel of the triangular matrix. In the case of 4m or 3m, real values are stored in both sub-panels, and so the indexing needs to occur in units of real values. The value computed here is divided into the complex pointer offset to cause the pointer to be advanced by the correct value. */ \ if ( bli_is_4mi_packed( schema_a ) || \ bli_is_3mi_packed( schema_a ) || \ bli_is_rih_packed( schema_a ) ) off_scl = 2; \ else off_scl = 1; \ \ /* Compute the storage stride scaling. Usually this is just 1. However, in the case of interleaved 3m, we need to scale the offset by 3/2. Note that real-only, imag-only, and summed-only packing formats are not applicable here since trsm is a two- operand operation only (unlike trmm, which is capable of three- operand). */ \ if ( bli_is_3mi_packed( schema_a ) ) { ss_a_num = 3; ss_a_den = 2; } \ else { ss_a_num = 1; ss_a_den = 1; } \ \ /* If there is a zero region above where the diagonal of A intersects the left edge of the block, adjust the pointer to C and treat this case as if the diagonal offset were zero. This skips over the region that was not packed. (Note we assume the diagonal offset is a multiple of MR; this assumption will hold as long as the cache blocksizes are each a multiple of MR and NR.) */ \ if ( diagoffa < 0 ) \ { \ i = -diagoffa; \ m = m - i; \ diagoffa = 0; \ c_cast = c_cast + (i )*rs_c; \ } \ \ /* Check the k dimension, which needs to be a multiple of MR. If k isn't a multiple of MR, we adjust it higher to satisfy the micro- kernel, which is expecting to perform an MR x MR triangular solve. This adjustment of k is consistent with what happened when A was packed: all of its bottom/right edges were zero-padded, and furthermore, the panel that stores the bottom-right corner of the matrix has its diagonal extended into the zero-padded region (as identity). This allows the trsm of that bottom-right panel to proceed without producing any infs or NaNs that would infect the "good" values of the corresponding block of B. */ \ if ( k % MR != 0 ) k += MR - ( k % MR ); \ \ /* NOTE: We don't need to check that m is a multiple of PACKMR since we know that the underlying buffer was already allocated to have an m dimension that is a multiple of PACKMR, with the region between the last row and the next multiple of MR zero-padded accordingly. */ \ \ /* Clear the temporary C buffer in case it has any infs or NaNs. */ \ PASTEMAC(ch,set0s_mxn)( MR, NR, \ ct, rs_ct, cs_ct ); \ \ /* Compute number of primary and leftover components of the m and n dimensions. */ \ n_iter = n / NR; \ n_left = n % NR; \ \ m_iter = m / MR; \ m_left = m % MR; \ \ if ( n_left ) ++n_iter; \ if ( m_left ) ++m_iter; \ \ /* Determine some increments used to step through A, B, and C. */ \ rstep_a = ps_a; \ \ cstep_b = ps_b; \ \ rstep_c = rs_c * MR; \ cstep_c = cs_c * NR; \ \ istep_a = PACKMR * k; \ istep_b = PACKNR * k_full; \ \ if ( bli_is_odd( istep_a ) ) istep_a += 1; \ if ( bli_is_odd( istep_b ) ) istep_b += 1; \ \ /* Save the pack schemas of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_schema_a( schema_a, &aux ); \ bli_auxinfo_set_schema_b( schema_b, &aux ); \ \ /* Save the imaginary stride of B to the auxinfo_t object. */ \ bli_auxinfo_set_is_b( istep_b, &aux ); \ \ b1 = b_cast; \ c1 = c_cast; \ \ /* Loop over the n dimension (NR columns at a time). */ \ for ( j = 0; j < n_iter; ++j ) \ { \ if( bli_trsm_my_iter( j, thread ) ) { \ \ ctype* restrict a1; \ ctype* restrict c11; \ ctype* restrict b2; \ \ a1 = a_cast; \ c11 = c1 + (0 )*rstep_c; \ \ n_cur = ( bli_is_not_edge_f( j, n_iter, n_left ) ? NR : n_left ); \ \ /* Initialize our next panel of B to be the current panel of B. */ \ b2 = b1; \ \ /* Loop over the m dimension (MR rows at a time). */ \ for ( i = 0; i < m_iter; ++i ) \ { \ diagoffa_i = diagoffa + ( doff_t )i*MR; \ \ m_cur = ( bli_is_not_edge_f( i, m_iter, m_left ) ? MR : m_left ); \ \ /* If the current panel of A intersects the diagonal, use a special micro-kernel that performs a fused gemm and trsm. If the current panel of A resides below the diagonal, use a a regular gemm micro-kernel. Otherwise, if it is above the diagonal, it was not packed (because it is implicitly zero) and so we do nothing. */ \ if ( bli_intersects_diag_n( diagoffa_i, MR, k ) ) \ { \ ctype* restrict a10; \ ctype* restrict a11; \ ctype* restrict b01; \ ctype* restrict b11; \ ctype* restrict a2; \ \ /* Compute various offsets into and lengths of parts of A. */ \ off_a10 = 0; \ k_a1011 = diagoffa_i + MR; \ k_a10 = k_a1011 - MR; \ off_a11 = k_a10; \ \ /* Compute the panel stride for the current diagonal- intersecting micro-panel. */ \ is_a_cur = k_a1011 * PACKMR; \ is_a_cur += ( bli_is_odd( is_a_cur ) ? 1 : 0 ); \ ps_a_cur = ( is_a_cur * ss_a_num ) / ss_a_den; \ \ /* Compute the addresses of the panel A10 and the triangular block A11. */ \ a10 = a1; \ /* a11 = a1 + ( k_a10 * PACKMR ) / off_scl; */ \ a11 = bli_ptr_inc_by_frac( a1, sizeof( ctype ), k_a10 * PACKMR, off_scl ); \ \ /* Compute the addresses of the panel B01 and the block B11. */ \ b01 = b1 + ( off_a10 * PACKNR ) / off_scl; \ b11 = b1 + ( off_a11 * PACKNR ) / off_scl; \ \ /* Compute the addresses of the next panels of A and B. */ \ a2 = a1 + ps_a_cur; \ if ( bli_is_last_iter( i, m_iter, 0, 1 ) ) \ { \ a2 = a_cast; \ b2 = b1; \ /*if ( bli_is_last_iter( j, n_iter, 0, 1 ) ) */\ if ( j + bli_thread_num_threads(thread) >= n_iter ) \ b2 = b_cast; \ } \ \ /* Save addresses of next panels of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_next_a( a2, &aux ); \ bli_auxinfo_set_next_b( b2, &aux ); \ \ /* Save the 4m1/3m1 imaginary stride of A to the auxinfo_t object. */ \ bli_auxinfo_set_is_a( is_a_cur, &aux ); \ \ /* Handle interior and edge cases separately. */ \ if ( m_cur == MR && n_cur == NR ) \ { \ /* Invoke the fused gemm/trsm micro-kernel. */ \ gemmtrsm_ukr \ ( \ k_a10, \ alpha1_cast, \ a10, \ a11, \ b01, \ b11, \ c11, rs_c, cs_c, \ &aux, \ cntx \ ); \ } \ else \ { \ /* Invoke the fused gemm/trsm micro-kernel. */ \ gemmtrsm_ukr \ ( \ k_a10, \ alpha1_cast, \ a10, \ a11, \ b01, \ b11, \ ct, rs_ct, cs_ct, \ &aux, \ cntx \ ); \ \ /* Copy the result to the bottom edge of C. */ \ PASTEMAC(ch,copys_mxn)( m_cur, n_cur, \ ct, rs_ct, cs_ct, \ c11, rs_c, cs_c ); \ } \ \ a1 += ps_a_cur; \ } \ else if ( bli_is_strictly_below_diag_n( diagoffa_i, MR, k ) ) \ { \ ctype* restrict a2; \ \ /* Compute the addresses of the next panels of A and B. */ \ a2 = a1 + rstep_a; \ if ( bli_is_last_iter( i, m_iter, 0, 1 ) ) \ { \ a2 = a_cast; \ b2 = b1; \ /*if ( bli_is_last_iter( j, n_iter, 0, 1 ) ) */\ if ( j + bli_thread_num_threads(thread) >= n_iter ) \ b2 = b_cast; \ } \ \ /* Save addresses of next panels of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_next_a( a2, &aux ); \ bli_auxinfo_set_next_b( b2, &aux ); \ \ /* Save the 4m1/3m1 imaginary stride of A to the auxinfo_t object. */ \ bli_auxinfo_set_is_a( istep_a, &aux ); \ \ /* Handle interior and edge cases separately. */ \ if ( m_cur == MR && n_cur == NR ) \ { \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k, \ minus_one, \ a1, \ b1, \ alpha2_cast, \ c11, rs_c, cs_c, \ &aux, \ cntx \ ); \ } \ else \ { \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k, \ minus_one, \ a1, \ b1, \ zero, \ ct, rs_ct, cs_ct, \ &aux, \ cntx \ ); \ \ /* Add the result to the edge of C. */ \ PASTEMAC(ch,xpbys_mxn)( m_cur, n_cur, \ ct, rs_ct, cs_ct, \ alpha2_cast, \ c11, rs_c, cs_c ); \ } \ \ a1 += rstep_a; \ } \ \ c11 += rstep_c; \ } \ } \ \ b1 += cstep_b; \ c1 += cstep_c; \ } \ \ /* if ( bli_is_4mi_packed( schema_a ) ){ \ PASTEMAC(d,fprintm)( stdout, "trsm4m1_ll_ker_var2: b_r before", k, n, \ ( double* )b, rs_b, 1, "%4.1f", "" ); \ PASTEMAC(d,fprintm)( stdout, "trsm4m1_ll_ker_var2: b_i before", k, n, \ ( double* )b+72, rs_b, 1, "%4.1f", "" ); \ }else{ \ PASTEMAC(d,fprintm)( stdout, "trsmnat_ll_ker_var2: b_r before", k, n, \ ( double* )b, 2*rs_b, 2, "%4.1f", "" ); \ PASTEMAC(d,fprintm)( stdout, "trsmnat_ll_ker_var2: b_i before", k, n, \ ( double* )b+1, 2*rs_b, 2, "%4.1f", "" ); \ } \ */ \ \ /* PASTEMAC(d,fprintm)( stdout, "trsm_ll_ker_var2: a11p_r computed", MR, MR, \ ( double* )a11, 1, PACKMR, "%4.1f", "" ); \ */ \ \ /* if ( bli_is_4mi_packed( schema_a ) ){ \ PASTEMAC(d,fprintm)( stdout, "trsm4m1_ll_ker_var2: b_r after", k, n, \ ( double* )b, rs_b, 1, "%4.1f", "" ); \ PASTEMAC(d,fprintm)( stdout, "trsm4m1_ll_ker_var2: b_i after", k, n, \ ( double* )b+72, rs_b, 1, "%4.1f", "" ); \ }else{ \ PASTEMAC(d,fprintm)( stdout, "trsmnat_ll_ker_var2: b_r after", k, n, \ ( double* )b, 2*rs_b, 2, "%4.1f", "" ); \ PASTEMAC(d,fprintm)( stdout, "trsmnat_ll_ker_var2: b_i after", k, n, \ ( double* )b+1, 2*rs_b, 2, "%4.1f", "" ); \ } \ PASTEMAC(d,fprintm)( stdout, "trsm_ll_ker_var2: b_r", m, n, \ ( double* )c, 1, cs_c, "%4.1f", "" ); \ PASTEMAC(d,fprintm)( stdout, "trsm_ll_ker_var2: b_i", m, n, \ ( double* )c + 8*9, 1, cs_c, "%4.1f", "" ); \ */ \ \ /* PASTEMAC(ch,fprintm)( stdout, "trsm_ll_ker_var2: a1 (diag)", MR, k_a1011, a1, 1, MR, "%5.2f", "" ); \ PASTEMAC(ch,fprintm)( stdout, "trsm_ll_ker_var2: a11 (diag)", MR, MR, a11, 1, MR, "%5.2f", "" ); \ PASTEMAC(ch,fprintm)( stdout, "trsm_ll_ker_var2: b1 (diag)", k_a1011, NR, bp_i, NR, 1, "%5.2f", "" ); \ PASTEMAC(ch,fprintm)( stdout, "trsm_ll_ker_var2: bp11 (diag)", MR, NR, bp11, NR, 1, "%5.2f", "" ); \ */ \ \ /* PASTEMAC(ch,fprintm)( stdout, "trsm_ll_ker_var2: a1 (ndiag)", MR, k, a1, 1, MR, "%5.2f", "" ); \ PASTEMAC(ch,fprintm)( stdout, "trsm_ll_ker_var2: b1 (ndiag)", k, NR, bp, NR, 1, "%5.2f", "" ); \ */ \ } INSERT_GENTFUNC_BASIC0( trsm_ll_ker_var2 ) blis-0.9.0/frame/3/trsm/other/bli_trsm_ll_ker_var2rr.c000066400000000000000000000477131422157504600226420ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define FUNCPTR_T gemm_fp typedef void (*FUNCPTR_T) ( doff_t diagoffa, pack_t schema_a, pack_t schema_b, dim_t m, dim_t n, dim_t k, void* alpha1, void* a, inc_t cs_a, dim_t pd_a, inc_t ps_a, void* b, inc_t rs_b, dim_t pd_b, inc_t ps_b, void* alpha2, void* c, inc_t rs_c, inc_t cs_c, cntx_t* cntx, rntm_t* rntm, thrinfo_t* thread ); static FUNCPTR_T GENARRAY(ftypes,trsm_ll_ker_var2rr); // // -- Macrokernel functions for round-robin partitioning ----------------------- // void bli_trsm_ll_ker_var2rr ( obj_t* a, obj_t* b, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ) { num_t dt_exec = bli_obj_exec_dt( c ); doff_t diagoffa = bli_obj_diag_offset( a ); pack_t schema_a = bli_obj_pack_schema( a ); pack_t schema_b = bli_obj_pack_schema( b ); dim_t m = bli_obj_length( c ); dim_t n = bli_obj_width( c ); dim_t k = bli_obj_width( a ); void* buf_a = bli_obj_buffer_at_off( a ); inc_t cs_a = bli_obj_col_stride( a ); dim_t pd_a = bli_obj_panel_dim( a ); inc_t ps_a = bli_obj_panel_stride( a ); void* buf_b = bli_obj_buffer_at_off( b ); inc_t rs_b = bli_obj_row_stride( b ); dim_t pd_b = bli_obj_panel_dim( b ); inc_t ps_b = bli_obj_panel_stride( b ); void* buf_c = bli_obj_buffer_at_off( c ); inc_t rs_c = bli_obj_row_stride( c ); inc_t cs_c = bli_obj_col_stride( c ); void* buf_alpha1; void* buf_alpha2; FUNCPTR_T f; // Grab the address of the internal scalar buffer for the scalar // attached to B (the non-triangular matrix). This will be the alpha // scalar used in the gemmtrsm subproblems (ie: the scalar that would // be applied to the packed copy of B prior to it being updated by // the trsm subproblem). This scalar may be unit, if for example it // was applied during packing. buf_alpha1 = bli_obj_internal_scalar_buffer( b ); // Grab the address of the internal scalar buffer for the scalar // attached to C. This will be the "beta" scalar used in the gemm-only // subproblems that correspond to micro-panels that do not intersect // the diagonal. We need this separate scalar because it's possible // that the alpha attached to B was reset, if it was applied during // packing. buf_alpha2 = bli_obj_internal_scalar_buffer( c ); // Index into the type combination array to extract the correct // function pointer. f = ftypes[dt_exec]; // Invoke the function. f( diagoffa, schema_a, schema_b, m, n, k, buf_alpha1, buf_a, cs_a, pd_a, ps_a, buf_b, rs_b, pd_b, ps_b, buf_alpha2, buf_c, rs_c, cs_c, cntx, rntm, thread ); } #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ doff_t diagoffa, \ pack_t schema_a, \ pack_t schema_b, \ dim_t m, \ dim_t n, \ dim_t k, \ void* alpha1, \ void* a, inc_t cs_a, dim_t pd_a, inc_t ps_a, \ void* b, inc_t rs_b, dim_t pd_b, inc_t ps_b, \ void* alpha2, \ void* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx, \ rntm_t* rntm, \ thrinfo_t* thread \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ /* Alias some constants to simpler names. */ \ const dim_t MR = pd_a; \ const dim_t NR = pd_b; \ const dim_t PACKMR = cs_a; \ const dim_t PACKNR = rs_b; \ \ /* Cast the micro-kernel address to its function pointer type. */ \ PASTECH(ch,gemmtrsm_ukr_ft) \ gemmtrsm_ukr = bli_cntx_get_l3_vir_ukr_dt( dt, BLIS_GEMMTRSM_L_UKR, cntx ); \ PASTECH(ch,gemm_ukr_ft) \ gemm_ukr = bli_cntx_get_l3_vir_ukr_dt( dt, BLIS_GEMM_UKR, cntx ); \ \ /* Temporary C buffer for edge cases. Note that the strides of this temporary buffer are set so that they match the storage of the original C matrix. For example, if C is column-stored, ct will be column-stored as well. */ \ ctype ct[ BLIS_STACK_BUF_MAX_SIZE \ / sizeof( ctype ) ] \ __attribute__((aligned(BLIS_STACK_BUF_ALIGN_SIZE))); \ const bool col_pref = bli_cntx_l3_vir_ukr_prefers_cols_dt( dt, BLIS_GEMM_UKR, cntx ); \ const inc_t rs_ct = ( col_pref ? 1 : NR ); \ const inc_t cs_ct = ( col_pref ? MR : 1 ); \ \ ctype* restrict zero = PASTEMAC(ch,0); \ ctype* restrict minus_one = PASTEMAC(ch,m1); \ ctype* restrict a_cast = a; \ ctype* restrict b_cast = b; \ ctype* restrict c_cast = c; \ ctype* restrict alpha1_cast = alpha1; \ ctype* restrict alpha2_cast = alpha2; \ ctype* restrict b1; \ ctype* restrict c1; \ \ doff_t diagoffa_i; \ dim_t k_full; \ dim_t m_iter, m_left; \ dim_t n_iter, n_left; \ dim_t m_cur; \ dim_t n_cur; \ dim_t k_a1011; \ dim_t k_a10; \ dim_t off_a10; \ dim_t off_a11; \ dim_t i, j; \ inc_t rstep_a; \ inc_t cstep_b; \ inc_t rstep_c, cstep_c; \ inc_t istep_a; \ inc_t istep_b; \ inc_t off_scl; \ inc_t ss_a_num; \ inc_t ss_a_den; \ inc_t ps_a_cur; \ inc_t is_a_cur; \ auxinfo_t aux; \ \ /* Assumptions/assertions: rs_a == 1 cs_a == PACKMR pd_a == MR ps_a == stride to next micro-panel of A rs_b == PACKNR cs_b == 1 pd_b == NR ps_b == stride to next micro-panel of B rs_c == (no assumptions) cs_c == (no assumptions) */ \ \ /* Safety trap: Certain indexing within this macro-kernel does not work as intended if both MR and NR are odd. */ \ if ( ( bli_is_odd( PACKMR ) && bli_is_odd( NR ) ) || \ ( bli_is_odd( PACKNR ) && bli_is_odd( MR ) ) ) bli_abort(); \ \ /* If any dimension is zero, return immediately. */ \ if ( bli_zero_dim3( m, n, k ) ) return; \ \ /* Safeguard: If matrix A is above the diagonal, it is implicitly zero. So we do nothing. */ \ if ( bli_is_strictly_above_diag_n( diagoffa, m, k ) ) return; \ \ /* Compute k_full as k inflated up to a multiple of MR. This is needed because some parameter combinations of trsm reduce k to advance past zero regions in the triangular matrix, and when computing the imaginary stride of B (the non-triangular matrix), which is used by 4m1/3m1 implementations, we need this unreduced value of k. */ \ k_full = ( k % MR != 0 ? k + MR - ( k % MR ) : k ); \ \ /* Compute indexing scaling factor for for 4m or 3m. This is needed because one of the packing register blocksizes (PACKMR or PACKNR) is used to index into the micro-panels of the non- triangular matrix when computing with a diagonal-intersecting micro-panel of the triangular matrix. In the case of 4m or 3m, real values are stored in both sub-panels, and so the indexing needs to occur in units of real values. The value computed here is divided into the complex pointer offset to cause the pointer to be advanced by the correct value. */ \ if ( bli_is_4mi_packed( schema_a ) || \ bli_is_3mi_packed( schema_a ) || \ bli_is_rih_packed( schema_a ) ) off_scl = 2; \ else off_scl = 1; \ \ /* Compute the storage stride scaling. Usually this is just 1. However, in the case of interleaved 3m, we need to scale the offset by 3/2. Note that real-only, imag-only, and summed-only packing formats are not applicable here since trsm is a two- operand operation only (unlike trmm, which is capable of three- operand). */ \ if ( bli_is_3mi_packed( schema_a ) ) { ss_a_num = 3; ss_a_den = 2; } \ else { ss_a_num = 1; ss_a_den = 1; } \ \ /* If there is a zero region above where the diagonal of A intersects the left edge of the block, adjust the pointer to C and treat this case as if the diagonal offset were zero. This skips over the region that was not packed. (Note we assume the diagonal offset is a multiple of MR; this assumption will hold as long as the cache blocksizes are each a multiple of MR and NR.) */ \ if ( diagoffa < 0 ) \ { \ i = -diagoffa; \ m = m - i; \ diagoffa = 0; \ c_cast = c_cast + (i )*rs_c; \ } \ \ /* Check the k dimension, which needs to be a multiple of MR. If k isn't a multiple of MR, we adjust it higher to satisfy the micro- kernel, which is expecting to perform an MR x MR triangular solve. This adjustment of k is consistent with what happened when A was packed: all of its bottom/right edges were zero-padded, and furthermore, the panel that stores the bottom-right corner of the matrix has its diagonal extended into the zero-padded region (as identity). This allows the trsm of that bottom-right panel to proceed without producing any infs or NaNs that would infect the "good" values of the corresponding block of B. */ \ if ( k % MR != 0 ) k += MR - ( k % MR ); \ \ /* NOTE: We don't need to check that m is a multiple of PACKMR since we know that the underlying buffer was already allocated to have an m dimension that is a multiple of PACKMR, with the region between the last row and the next multiple of MR zero-padded accordingly. */ \ \ /* Clear the temporary C buffer in case it has any infs or NaNs. */ \ PASTEMAC(ch,set0s_mxn)( MR, NR, \ ct, rs_ct, cs_ct ); \ \ /* Compute number of primary and leftover components of the m and n dimensions. */ \ n_iter = n / NR; \ n_left = n % NR; \ \ m_iter = m / MR; \ m_left = m % MR; \ \ if ( n_left ) ++n_iter; \ if ( m_left ) ++m_iter; \ \ /* Determine some increments used to step through A, B, and C. */ \ rstep_a = ps_a; \ \ cstep_b = ps_b; \ \ rstep_c = rs_c * MR; \ cstep_c = cs_c * NR; \ \ istep_a = PACKMR * k; \ istep_b = PACKNR * k_full; \ \ if ( bli_is_odd( istep_a ) ) istep_a += 1; \ if ( bli_is_odd( istep_b ) ) istep_b += 1; \ \ /* Save the pack schemas of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_schema_a( schema_a, &aux ); \ bli_auxinfo_set_schema_b( schema_b, &aux ); \ \ /* Save the imaginary stride of B to the auxinfo_t object. */ \ bli_auxinfo_set_is_b( istep_b, &aux ); \ \ /* We don't bother querying the thrinfo_t node for the 1st loop because we can't parallelize that loop in trsm due to the inter-iteration dependencies that exist. */ \ /*thrinfo_t* caucus = bli_thrinfo_sub_node( thread );*/ \ \ /* Query the number of threads and thread ids for each loop. */ \ dim_t jr_nt = bli_thread_n_way( thread ); \ dim_t jr_tid = bli_thread_work_id( thread ); \ \ dim_t jr_start, jr_end; \ dim_t jr_inc; \ \ /* Use round-robin assignment of micropanels to threads in the 2nd loop. NOTE: Parallelism in the 1st loop is unattainable due to the inter-iteration dependencies present in trsm. */ \ bli_thread_range_jrir_rr( thread, n_iter, 1, FALSE, &jr_start, &jr_end, &jr_inc ); \ \ /* Loop over the n dimension (NR columns at a time). */ \ for ( j = jr_start; j < jr_end; j += jr_inc ) \ { \ ctype* restrict a1; \ ctype* restrict c11; \ ctype* restrict b2; \ \ b1 = b_cast + j * cstep_b; \ c1 = c_cast + j * cstep_c; \ \ n_cur = ( bli_is_not_edge_f( j, n_iter, n_left ) ? NR : n_left ); \ \ /* Initialize our next panel of B to be the current panel of B. */ \ b2 = b1; \ \ a1 = a_cast; \ c11 = c1 + (0 )*rstep_c; \ \ /* Loop over the m dimension (MR rows at a time). */ \ for ( i = 0; i < m_iter; ++i ) \ { \ diagoffa_i = diagoffa + ( doff_t )i*MR; \ \ m_cur = ( bli_is_not_edge_f( i, m_iter, m_left ) ? MR : m_left ); \ \ /* If the current panel of A intersects the diagonal, use a special micro-kernel that performs a fused gemm and trsm. If the current panel of A resides below the diagonal, use a a regular gemm micro-kernel. Otherwise, if it is above the diagonal, it was not packed (because it is implicitly zero) and so we do nothing. */ \ if ( bli_intersects_diag_n( diagoffa_i, MR, k ) ) \ { \ ctype* restrict a10; \ ctype* restrict a11; \ ctype* restrict b01; \ ctype* restrict b11; \ ctype* restrict a2; \ \ /* Compute various offsets into and lengths of parts of A. */ \ off_a10 = 0; \ k_a1011 = diagoffa_i + MR; \ k_a10 = k_a1011 - MR; \ off_a11 = k_a10; \ \ /* Compute the panel stride for the current diagonal- intersecting micro-panel. */ \ is_a_cur = k_a1011 * PACKMR; \ is_a_cur += ( bli_is_odd( is_a_cur ) ? 1 : 0 ); \ ps_a_cur = ( is_a_cur * ss_a_num ) / ss_a_den; \ \ /* Compute the addresses of the panel A10 and the triangular block A11. */ \ a10 = a1; \ /* a11 = a1 + ( k_a10 * PACKMR ) / off_scl; */ \ a11 = bli_ptr_inc_by_frac( a1, sizeof( ctype ), k_a10 * PACKMR, off_scl ); \ \ /* Compute the addresses of the panel B01 and the block B11. */ \ b01 = b1 + ( off_a10 * PACKNR ) / off_scl; \ b11 = b1 + ( off_a11 * PACKNR ) / off_scl; \ \ /* Compute the addresses of the next panels of A and B. */ \ a2 = a1 + ps_a_cur; \ if ( bli_is_last_iter_rr( i, m_iter, 0, 1 ) ) \ { \ a2 = a_cast; \ b2 = b1; \ if ( bli_is_last_iter_rr( j, n_iter, jr_tid, jr_nt ) ) \ b2 = b_cast; \ } \ \ /* Save addresses of next panels of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_next_a( a2, &aux ); \ bli_auxinfo_set_next_b( b2, &aux ); \ \ /* Save the 4m1/3m1 imaginary stride of A to the auxinfo_t object. */ \ bli_auxinfo_set_is_a( is_a_cur, &aux ); \ \ /* Handle interior and edge cases separately. */ \ if ( m_cur == MR && n_cur == NR ) \ { \ /* Invoke the fused gemm/trsm micro-kernel. */ \ gemmtrsm_ukr \ ( \ k_a10, \ alpha1_cast, \ a10, \ a11, \ b01, \ b11, \ c11, rs_c, cs_c, \ &aux, \ cntx \ ); \ } \ else \ { \ /* Invoke the fused gemm/trsm micro-kernel. */ \ gemmtrsm_ukr \ ( \ k_a10, \ alpha1_cast, \ a10, \ a11, \ b01, \ b11, \ ct, rs_ct, cs_ct, \ &aux, \ cntx \ ); \ \ /* Copy the result to the bottom edge of C. */ \ PASTEMAC(ch,copys_mxn)( m_cur, n_cur, \ ct, rs_ct, cs_ct, \ c11, rs_c, cs_c ); \ } \ \ a1 += ps_a_cur; \ } \ else if ( bli_is_strictly_below_diag_n( diagoffa_i, MR, k ) ) \ { \ ctype* restrict a2; \ \ /* Compute the addresses of the next panels of A and B. */ \ a2 = a1 + rstep_a; \ if ( bli_is_last_iter_rr( i, m_iter, 0, 1 ) ) \ { \ a2 = a_cast; \ b2 = b1; \ if ( bli_is_last_iter_rr( j, n_iter, jr_tid, jr_nt ) ) \ b2 = b_cast; \ } \ \ /* Save addresses of next panels of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_next_a( a2, &aux ); \ bli_auxinfo_set_next_b( b2, &aux ); \ \ /* Save the 4m1/3m1 imaginary stride of A to the auxinfo_t object. */ \ bli_auxinfo_set_is_a( istep_a, &aux ); \ \ /* Handle interior and edge cases separately. */ \ if ( m_cur == MR && n_cur == NR ) \ { \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k, \ minus_one, \ a1, \ b1, \ alpha2_cast, \ c11, rs_c, cs_c, \ &aux, \ cntx \ ); \ } \ else \ { \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k, \ minus_one, \ a1, \ b1, \ zero, \ ct, rs_ct, cs_ct, \ &aux, \ cntx \ ); \ \ /* Add the result to the edge of C. */ \ PASTEMAC(ch,xpbys_mxn)( m_cur, n_cur, \ ct, rs_ct, cs_ct, \ alpha2_cast, \ c11, rs_c, cs_c ); \ } \ \ a1 += rstep_a; \ } \ \ c11 += rstep_c; \ } \ } \ \ /* if ( bli_is_4mi_packed( schema_a ) ){ \ PASTEMAC(d,fprintm)( stdout, "trsm4m1_ll_ker_var2: b_r before", k, n, \ ( double* )b, rs_b, 1, "%4.1f", "" ); \ PASTEMAC(d,fprintm)( stdout, "trsm4m1_ll_ker_var2: b_i before", k, n, \ ( double* )b+72, rs_b, 1, "%4.1f", "" ); \ }else{ \ PASTEMAC(d,fprintm)( stdout, "trsmnat_ll_ker_var2: b_r before", k, n, \ ( double* )b, 2*rs_b, 2, "%4.1f", "" ); \ PASTEMAC(d,fprintm)( stdout, "trsmnat_ll_ker_var2: b_i before", k, n, \ ( double* )b+1, 2*rs_b, 2, "%4.1f", "" ); \ } \ */ \ \ /* PASTEMAC(d,fprintm)( stdout, "trsm_ll_ker_var2: a11p_r computed", MR, MR, \ ( double* )a11, 1, PACKMR, "%4.1f", "" ); \ */ \ \ /* if ( bli_is_4mi_packed( schema_a ) ){ \ PASTEMAC(d,fprintm)( stdout, "trsm4m1_ll_ker_var2: b_r after", k, n, \ ( double* )b, rs_b, 1, "%4.1f", "" ); \ PASTEMAC(d,fprintm)( stdout, "trsm4m1_ll_ker_var2: b_i after", k, n, \ ( double* )b+72, rs_b, 1, "%4.1f", "" ); \ }else{ \ PASTEMAC(d,fprintm)( stdout, "trsmnat_ll_ker_var2: b_r after", k, n, \ ( double* )b, 2*rs_b, 2, "%4.1f", "" ); \ PASTEMAC(d,fprintm)( stdout, "trsmnat_ll_ker_var2: b_i after", k, n, \ ( double* )b+1, 2*rs_b, 2, "%4.1f", "" ); \ } \ PASTEMAC(d,fprintm)( stdout, "trsm_ll_ker_var2: b_r", m, n, \ ( double* )c, 1, cs_c, "%4.1f", "" ); \ PASTEMAC(d,fprintm)( stdout, "trsm_ll_ker_var2: b_i", m, n, \ ( double* )c + 8*9, 1, cs_c, "%4.1f", "" ); \ */ \ \ /* PASTEMAC(ch,fprintm)( stdout, "trsm_ll_ker_var2: a1 (diag)", MR, k_a1011, a1, 1, MR, "%5.2f", "" ); \ PASTEMAC(ch,fprintm)( stdout, "trsm_ll_ker_var2: a11 (diag)", MR, MR, a11, 1, MR, "%5.2f", "" ); \ PASTEMAC(ch,fprintm)( stdout, "trsm_ll_ker_var2: b1 (diag)", k_a1011, NR, bp_i, NR, 1, "%5.2f", "" ); \ PASTEMAC(ch,fprintm)( stdout, "trsm_ll_ker_var2: bp11 (diag)", MR, NR, bp11, NR, 1, "%5.2f", "" ); \ */ \ \ /* PASTEMAC(ch,fprintm)( stdout, "trsm_ll_ker_var2: a1 (ndiag)", MR, k, a1, 1, MR, "%5.2f", "" ); \ PASTEMAC(ch,fprintm)( stdout, "trsm_ll_ker_var2: b1 (ndiag)", k, NR, bp, NR, 1, "%5.2f", "" ); \ */ \ } INSERT_GENTFUNC_BASIC0( trsm_ll_ker_var2rr ) blis-0.9.0/frame/3/trsm/other/bli_trsm_ll_ker_var2sl.c000066400000000000000000000477041422157504600226350ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define FUNCPTR_T gemm_fp typedef void (*FUNCPTR_T) ( doff_t diagoffa, pack_t schema_a, pack_t schema_b, dim_t m, dim_t n, dim_t k, void* alpha1, void* a, inc_t cs_a, dim_t pd_a, inc_t ps_a, void* b, inc_t rs_b, dim_t pd_b, inc_t ps_b, void* alpha2, void* c, inc_t rs_c, inc_t cs_c, cntx_t* cntx, rntm_t* rntm, thrinfo_t* thread ); static FUNCPTR_T GENARRAY(ftypes,trsm_ll_ker_var2sl); // // -- Macrokernel functions for slab partitioning ------------------------------ // void bli_trsm_ll_ker_var2sl ( obj_t* a, obj_t* b, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ) { num_t dt_exec = bli_obj_exec_dt( c ); doff_t diagoffa = bli_obj_diag_offset( a ); pack_t schema_a = bli_obj_pack_schema( a ); pack_t schema_b = bli_obj_pack_schema( b ); dim_t m = bli_obj_length( c ); dim_t n = bli_obj_width( c ); dim_t k = bli_obj_width( a ); void* buf_a = bli_obj_buffer_at_off( a ); inc_t cs_a = bli_obj_col_stride( a ); dim_t pd_a = bli_obj_panel_dim( a ); inc_t ps_a = bli_obj_panel_stride( a ); void* buf_b = bli_obj_buffer_at_off( b ); inc_t rs_b = bli_obj_row_stride( b ); dim_t pd_b = bli_obj_panel_dim( b ); inc_t ps_b = bli_obj_panel_stride( b ); void* buf_c = bli_obj_buffer_at_off( c ); inc_t rs_c = bli_obj_row_stride( c ); inc_t cs_c = bli_obj_col_stride( c ); void* buf_alpha1; void* buf_alpha2; FUNCPTR_T f; // Grab the address of the internal scalar buffer for the scalar // attached to B (the non-triangular matrix). This will be the alpha // scalar used in the gemmtrsm subproblems (ie: the scalar that would // be applied to the packed copy of B prior to it being updated by // the trsm subproblem). This scalar may be unit, if for example it // was applied during packing. buf_alpha1 = bli_obj_internal_scalar_buffer( b ); // Grab the address of the internal scalar buffer for the scalar // attached to C. This will be the "beta" scalar used in the gemm-only // subproblems that correspond to micro-panels that do not intersect // the diagonal. We need this separate scalar because it's possible // that the alpha attached to B was reset, if it was applied during // packing. buf_alpha2 = bli_obj_internal_scalar_buffer( c ); // Index into the type combination array to extract the correct // function pointer. f = ftypes[dt_exec]; // Invoke the function. f( diagoffa, schema_a, schema_b, m, n, k, buf_alpha1, buf_a, cs_a, pd_a, ps_a, buf_b, rs_b, pd_b, ps_b, buf_alpha2, buf_c, rs_c, cs_c, cntx, rntm, thread ); } #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ doff_t diagoffa, \ pack_t schema_a, \ pack_t schema_b, \ dim_t m, \ dim_t n, \ dim_t k, \ void* alpha1, \ void* a, inc_t cs_a, dim_t pd_a, inc_t ps_a, \ void* b, inc_t rs_b, dim_t pd_b, inc_t ps_b, \ void* alpha2, \ void* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx, \ rntm_t* rntm, \ thrinfo_t* thread \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ /* Alias some constants to simpler names. */ \ const dim_t MR = pd_a; \ const dim_t NR = pd_b; \ const dim_t PACKMR = cs_a; \ const dim_t PACKNR = rs_b; \ \ /* Cast the micro-kernel address to its function pointer type. */ \ PASTECH(ch,gemmtrsm_ukr_ft) \ gemmtrsm_ukr = bli_cntx_get_l3_vir_ukr_dt( dt, BLIS_GEMMTRSM_L_UKR, cntx ); \ PASTECH(ch,gemm_ukr_ft) \ gemm_ukr = bli_cntx_get_l3_vir_ukr_dt( dt, BLIS_GEMM_UKR, cntx ); \ \ /* Temporary C buffer for edge cases. Note that the strides of this temporary buffer are set so that they match the storage of the original C matrix. For example, if C is column-stored, ct will be column-stored as well. */ \ ctype ct[ BLIS_STACK_BUF_MAX_SIZE \ / sizeof( ctype ) ] \ __attribute__((aligned(BLIS_STACK_BUF_ALIGN_SIZE))); \ const bool col_pref = bli_cntx_l3_vir_ukr_prefers_cols_dt( dt, BLIS_GEMM_UKR, cntx ); \ const inc_t rs_ct = ( col_pref ? 1 : NR ); \ const inc_t cs_ct = ( col_pref ? MR : 1 ); \ \ ctype* restrict zero = PASTEMAC(ch,0); \ ctype* restrict minus_one = PASTEMAC(ch,m1); \ ctype* restrict a_cast = a; \ ctype* restrict b_cast = b; \ ctype* restrict c_cast = c; \ ctype* restrict alpha1_cast = alpha1; \ ctype* restrict alpha2_cast = alpha2; \ ctype* restrict b1; \ ctype* restrict c1; \ \ doff_t diagoffa_i; \ dim_t k_full; \ dim_t m_iter, m_left; \ dim_t n_iter, n_left; \ dim_t m_cur; \ dim_t n_cur; \ dim_t k_a1011; \ dim_t k_a10; \ dim_t off_a10; \ dim_t off_a11; \ dim_t i, j; \ inc_t rstep_a; \ inc_t cstep_b; \ inc_t rstep_c, cstep_c; \ inc_t istep_a; \ inc_t istep_b; \ inc_t off_scl; \ inc_t ss_a_num; \ inc_t ss_a_den; \ inc_t ps_a_cur; \ inc_t is_a_cur; \ auxinfo_t aux; \ \ /* Assumptions/assertions: rs_a == 1 cs_a == PACKMR pd_a == MR ps_a == stride to next micro-panel of A rs_b == PACKNR cs_b == 1 pd_b == NR ps_b == stride to next micro-panel of B rs_c == (no assumptions) cs_c == (no assumptions) */ \ \ /* Safety trap: Certain indexing within this macro-kernel does not work as intended if both MR and NR are odd. */ \ if ( ( bli_is_odd( PACKMR ) && bli_is_odd( NR ) ) || \ ( bli_is_odd( PACKNR ) && bli_is_odd( MR ) ) ) bli_abort(); \ \ /* If any dimension is zero, return immediately. */ \ if ( bli_zero_dim3( m, n, k ) ) return; \ \ /* Safeguard: If matrix A is above the diagonal, it is implicitly zero. So we do nothing. */ \ if ( bli_is_strictly_above_diag_n( diagoffa, m, k ) ) return; \ \ /* Compute k_full as k inflated up to a multiple of MR. This is needed because some parameter combinations of trsm reduce k to advance past zero regions in the triangular matrix, and when computing the imaginary stride of B (the non-triangular matrix), which is used by 4m1/3m1 implementations, we need this unreduced value of k. */ \ k_full = ( k % MR != 0 ? k + MR - ( k % MR ) : k ); \ \ /* Compute indexing scaling factor for for 4m or 3m. This is needed because one of the packing register blocksizes (PACKMR or PACKNR) is used to index into the micro-panels of the non- triangular matrix when computing with a diagonal-intersecting micro-panel of the triangular matrix. In the case of 4m or 3m, real values are stored in both sub-panels, and so the indexing needs to occur in units of real values. The value computed here is divided into the complex pointer offset to cause the pointer to be advanced by the correct value. */ \ if ( bli_is_4mi_packed( schema_a ) || \ bli_is_3mi_packed( schema_a ) || \ bli_is_rih_packed( schema_a ) ) off_scl = 2; \ else off_scl = 1; \ \ /* Compute the storage stride scaling. Usually this is just 1. However, in the case of interleaved 3m, we need to scale the offset by 3/2. Note that real-only, imag-only, and summed-only packing formats are not applicable here since trsm is a two- operand operation only (unlike trmm, which is capable of three- operand). */ \ if ( bli_is_3mi_packed( schema_a ) ) { ss_a_num = 3; ss_a_den = 2; } \ else { ss_a_num = 1; ss_a_den = 1; } \ \ /* If there is a zero region above where the diagonal of A intersects the left edge of the block, adjust the pointer to C and treat this case as if the diagonal offset were zero. This skips over the region that was not packed. (Note we assume the diagonal offset is a multiple of MR; this assumption will hold as long as the cache blocksizes are each a multiple of MR and NR.) */ \ if ( diagoffa < 0 ) \ { \ i = -diagoffa; \ m = m - i; \ diagoffa = 0; \ c_cast = c_cast + (i )*rs_c; \ } \ \ /* Check the k dimension, which needs to be a multiple of MR. If k isn't a multiple of MR, we adjust it higher to satisfy the micro- kernel, which is expecting to perform an MR x MR triangular solve. This adjustment of k is consistent with what happened when A was packed: all of its bottom/right edges were zero-padded, and furthermore, the panel that stores the bottom-right corner of the matrix has its diagonal extended into the zero-padded region (as identity). This allows the trsm of that bottom-right panel to proceed without producing any infs or NaNs that would infect the "good" values of the corresponding block of B. */ \ if ( k % MR != 0 ) k += MR - ( k % MR ); \ \ /* NOTE: We don't need to check that m is a multiple of PACKMR since we know that the underlying buffer was already allocated to have an m dimension that is a multiple of PACKMR, with the region between the last row and the next multiple of MR zero-padded accordingly. */ \ \ /* Clear the temporary C buffer in case it has any infs or NaNs. */ \ PASTEMAC(ch,set0s_mxn)( MR, NR, \ ct, rs_ct, cs_ct ); \ \ /* Compute number of primary and leftover components of the m and n dimensions. */ \ n_iter = n / NR; \ n_left = n % NR; \ \ m_iter = m / MR; \ m_left = m % MR; \ \ if ( n_left ) ++n_iter; \ if ( m_left ) ++m_iter; \ \ /* Determine some increments used to step through A, B, and C. */ \ rstep_a = ps_a; \ \ cstep_b = ps_b; \ \ rstep_c = rs_c * MR; \ cstep_c = cs_c * NR; \ \ istep_a = PACKMR * k; \ istep_b = PACKNR * k_full; \ \ if ( bli_is_odd( istep_a ) ) istep_a += 1; \ if ( bli_is_odd( istep_b ) ) istep_b += 1; \ \ /* Save the pack schemas of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_schema_a( schema_a, &aux ); \ bli_auxinfo_set_schema_b( schema_b, &aux ); \ \ /* Save the imaginary stride of B to the auxinfo_t object. */ \ bli_auxinfo_set_is_b( istep_b, &aux ); \ \ /* We don't bother querying the thrinfo_t node for the 1st loop because we can't parallelize that loop in trsm due to the inter-iteration dependencies that exist. */ \ /*thrinfo_t* caucus = bli_thrinfo_sub_node( thread );*/ \ \ /* Query the number of threads and thread ids for each loop. */ \ dim_t jr_nt = bli_thread_n_way( thread ); \ dim_t jr_tid = bli_thread_work_id( thread ); \ \ dim_t jr_start, jr_end; \ dim_t jr_inc; \ \ /* Use slab assignment of micropanels to threads in the 2nd loop. NOTE: Parallelism in the 1st loop is unattainable due to the inter-iteration dependencies present in trsm. */ \ bli_thread_range_jrir_sl( thread, n_iter, 1, FALSE, &jr_start, &jr_end, &jr_inc ); \ \ /* Loop over the n dimension (NR columns at a time). */ \ for ( j = jr_start; j < jr_end; j += jr_inc ) \ { \ ctype* restrict a1; \ ctype* restrict c11; \ ctype* restrict b2; \ \ b1 = b_cast + j * cstep_b; \ c1 = c_cast + j * cstep_c; \ \ n_cur = ( bli_is_not_edge_f( j, n_iter, n_left ) ? NR : n_left ); \ \ /* Initialize our next panel of B to be the current panel of B. */ \ b2 = b1; \ \ a1 = a_cast; \ c11 = c1 + (0 )*rstep_c; \ \ /* Loop over the m dimension (MR rows at a time). */ \ for ( i = 0; i < m_iter; ++i ) \ { \ diagoffa_i = diagoffa + ( doff_t )i*MR; \ \ m_cur = ( bli_is_not_edge_f( i, m_iter, m_left ) ? MR : m_left ); \ \ /* If the current panel of A intersects the diagonal, use a special micro-kernel that performs a fused gemm and trsm. If the current panel of A resides below the diagonal, use a a regular gemm micro-kernel. Otherwise, if it is above the diagonal, it was not packed (because it is implicitly zero) and so we do nothing. */ \ if ( bli_intersects_diag_n( diagoffa_i, MR, k ) ) \ { \ ctype* restrict a10; \ ctype* restrict a11; \ ctype* restrict b01; \ ctype* restrict b11; \ ctype* restrict a2; \ \ /* Compute various offsets into and lengths of parts of A. */ \ off_a10 = 0; \ k_a1011 = diagoffa_i + MR; \ k_a10 = k_a1011 - MR; \ off_a11 = k_a10; \ \ /* Compute the panel stride for the current diagonal- intersecting micro-panel. */ \ is_a_cur = k_a1011 * PACKMR; \ is_a_cur += ( bli_is_odd( is_a_cur ) ? 1 : 0 ); \ ps_a_cur = ( is_a_cur * ss_a_num ) / ss_a_den; \ \ /* Compute the addresses of the panel A10 and the triangular block A11. */ \ a10 = a1; \ /* a11 = a1 + ( k_a10 * PACKMR ) / off_scl; */ \ a11 = bli_ptr_inc_by_frac( a1, sizeof( ctype ), k_a10 * PACKMR, off_scl ); \ \ /* Compute the addresses of the panel B01 and the block B11. */ \ b01 = b1 + ( off_a10 * PACKNR ) / off_scl; \ b11 = b1 + ( off_a11 * PACKNR ) / off_scl; \ \ /* Compute the addresses of the next panels of A and B. */ \ a2 = a1 + ps_a_cur; \ if ( bli_is_last_iter_rr( i, m_iter, 0, 1 ) ) \ { \ a2 = a_cast; \ b2 = b1; \ if ( bli_is_last_iter_sl( j, n_iter, jr_tid, jr_nt ) ) \ b2 = b_cast; \ } \ \ /* Save addresses of next panels of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_next_a( a2, &aux ); \ bli_auxinfo_set_next_b( b2, &aux ); \ \ /* Save the 4m1/3m1 imaginary stride of A to the auxinfo_t object. */ \ bli_auxinfo_set_is_a( is_a_cur, &aux ); \ \ /* Handle interior and edge cases separately. */ \ if ( m_cur == MR && n_cur == NR ) \ { \ /* Invoke the fused gemm/trsm micro-kernel. */ \ gemmtrsm_ukr \ ( \ k_a10, \ alpha1_cast, \ a10, \ a11, \ b01, \ b11, \ c11, rs_c, cs_c, \ &aux, \ cntx \ ); \ } \ else \ { \ /* Invoke the fused gemm/trsm micro-kernel. */ \ gemmtrsm_ukr \ ( \ k_a10, \ alpha1_cast, \ a10, \ a11, \ b01, \ b11, \ ct, rs_ct, cs_ct, \ &aux, \ cntx \ ); \ \ /* Copy the result to the bottom edge of C. */ \ PASTEMAC(ch,copys_mxn)( m_cur, n_cur, \ ct, rs_ct, cs_ct, \ c11, rs_c, cs_c ); \ } \ \ a1 += ps_a_cur; \ } \ else if ( bli_is_strictly_below_diag_n( diagoffa_i, MR, k ) ) \ { \ ctype* restrict a2; \ \ /* Compute the addresses of the next panels of A and B. */ \ a2 = a1 + rstep_a; \ if ( bli_is_last_iter_rr( i, m_iter, 0, 1 ) ) \ { \ a2 = a_cast; \ b2 = b1; \ if ( bli_is_last_iter_sl( j, n_iter, jr_tid, jr_nt ) ) \ b2 = b_cast; \ } \ \ /* Save addresses of next panels of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_next_a( a2, &aux ); \ bli_auxinfo_set_next_b( b2, &aux ); \ \ /* Save the 4m1/3m1 imaginary stride of A to the auxinfo_t object. */ \ bli_auxinfo_set_is_a( istep_a, &aux ); \ \ /* Handle interior and edge cases separately. */ \ if ( m_cur == MR && n_cur == NR ) \ { \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k, \ minus_one, \ a1, \ b1, \ alpha2_cast, \ c11, rs_c, cs_c, \ &aux, \ cntx \ ); \ } \ else \ { \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k, \ minus_one, \ a1, \ b1, \ zero, \ ct, rs_ct, cs_ct, \ &aux, \ cntx \ ); \ \ /* Add the result to the edge of C. */ \ PASTEMAC(ch,xpbys_mxn)( m_cur, n_cur, \ ct, rs_ct, cs_ct, \ alpha2_cast, \ c11, rs_c, cs_c ); \ } \ \ a1 += rstep_a; \ } \ \ c11 += rstep_c; \ } \ } \ \ /* if ( bli_is_4mi_packed( schema_a ) ){ \ PASTEMAC(d,fprintm)( stdout, "trsm4m1_ll_ker_var2: b_r before", k, n, \ ( double* )b, rs_b, 1, "%4.1f", "" ); \ PASTEMAC(d,fprintm)( stdout, "trsm4m1_ll_ker_var2: b_i before", k, n, \ ( double* )b+72, rs_b, 1, "%4.1f", "" ); \ }else{ \ PASTEMAC(d,fprintm)( stdout, "trsmnat_ll_ker_var2: b_r before", k, n, \ ( double* )b, 2*rs_b, 2, "%4.1f", "" ); \ PASTEMAC(d,fprintm)( stdout, "trsmnat_ll_ker_var2: b_i before", k, n, \ ( double* )b+1, 2*rs_b, 2, "%4.1f", "" ); \ } \ */ \ \ /* PASTEMAC(d,fprintm)( stdout, "trsm_ll_ker_var2: a11p_r computed", MR, MR, \ ( double* )a11, 1, PACKMR, "%4.1f", "" ); \ */ \ \ /* if ( bli_is_4mi_packed( schema_a ) ){ \ PASTEMAC(d,fprintm)( stdout, "trsm4m1_ll_ker_var2: b_r after", k, n, \ ( double* )b, rs_b, 1, "%4.1f", "" ); \ PASTEMAC(d,fprintm)( stdout, "trsm4m1_ll_ker_var2: b_i after", k, n, \ ( double* )b+72, rs_b, 1, "%4.1f", "" ); \ }else{ \ PASTEMAC(d,fprintm)( stdout, "trsmnat_ll_ker_var2: b_r after", k, n, \ ( double* )b, 2*rs_b, 2, "%4.1f", "" ); \ PASTEMAC(d,fprintm)( stdout, "trsmnat_ll_ker_var2: b_i after", k, n, \ ( double* )b+1, 2*rs_b, 2, "%4.1f", "" ); \ } \ PASTEMAC(d,fprintm)( stdout, "trsm_ll_ker_var2: b_r", m, n, \ ( double* )c, 1, cs_c, "%4.1f", "" ); \ PASTEMAC(d,fprintm)( stdout, "trsm_ll_ker_var2: b_i", m, n, \ ( double* )c + 8*9, 1, cs_c, "%4.1f", "" ); \ */ \ \ /* PASTEMAC(ch,fprintm)( stdout, "trsm_ll_ker_var2: a1 (diag)", MR, k_a1011, a1, 1, MR, "%5.2f", "" ); \ PASTEMAC(ch,fprintm)( stdout, "trsm_ll_ker_var2: a11 (diag)", MR, MR, a11, 1, MR, "%5.2f", "" ); \ PASTEMAC(ch,fprintm)( stdout, "trsm_ll_ker_var2: b1 (diag)", k_a1011, NR, bp_i, NR, 1, "%5.2f", "" ); \ PASTEMAC(ch,fprintm)( stdout, "trsm_ll_ker_var2: bp11 (diag)", MR, NR, bp11, NR, 1, "%5.2f", "" ); \ */ \ \ /* PASTEMAC(ch,fprintm)( stdout, "trsm_ll_ker_var2: a1 (ndiag)", MR, k, a1, 1, MR, "%5.2f", "" ); \ PASTEMAC(ch,fprintm)( stdout, "trsm_ll_ker_var2: b1 (ndiag)", k, NR, bp, NR, 1, "%5.2f", "" ); \ */ \ } INSERT_GENTFUNC_BASIC0( trsm_ll_ker_var2sl ) blis-0.9.0/frame/3/trsm/other/bli_trsm_lu_ker_var2.c000066400000000000000000000445311422157504600223020ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define FUNCPTR_T gemm_fp typedef void (*FUNCPTR_T) ( doff_t diagoffa, pack_t schema_a, pack_t schema_b, dim_t m, dim_t n, dim_t k, void* alpha1, void* a, inc_t cs_a, dim_t pd_a, inc_t ps_a, void* b, inc_t rs_b, dim_t pd_b, inc_t ps_b, void* alpha2, void* c, inc_t rs_c, inc_t cs_c, cntx_t* cntx, rntm_t* rntm, thrinfo_t* thread ); static FUNCPTR_T GENARRAY(ftypes,trsm_lu_ker_var2); void bli_trsm_lu_ker_var2 ( obj_t* a, obj_t* b, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ) { num_t dt_exec = bli_obj_exec_dt( c ); doff_t diagoffa = bli_obj_diag_offset( a ); pack_t schema_a = bli_obj_pack_schema( a ); pack_t schema_b = bli_obj_pack_schema( b ); dim_t m = bli_obj_length( c ); dim_t n = bli_obj_width( c ); dim_t k = bli_obj_width( a ); void* buf_a = bli_obj_buffer_at_off( a ); inc_t cs_a = bli_obj_col_stride( a ); dim_t pd_a = bli_obj_panel_dim( a ); inc_t ps_a = bli_obj_panel_stride( a ); void* buf_b = bli_obj_buffer_at_off( b ); inc_t rs_b = bli_obj_row_stride( b ); dim_t pd_b = bli_obj_panel_dim( b ); inc_t ps_b = bli_obj_panel_stride( b ); void* buf_c = bli_obj_buffer_at_off( c ); inc_t rs_c = bli_obj_row_stride( c ); inc_t cs_c = bli_obj_col_stride( c ); void* buf_alpha1; void* buf_alpha2; FUNCPTR_T f; // Grab the address of the internal scalar buffer for the scalar // attached to B (the non-triangular matrix). This will be the alpha // scalar used in the gemmtrsm subproblems (ie: the scalar that would // be applied to the packed copy of B prior to it being updated by // the trsm subproblem). This scalar may be unit, if for example it // was applied during packing. buf_alpha1 = bli_obj_internal_scalar_buffer( b ); // Grab the address of the internal scalar buffer for the scalar // attached to C. This will be the "beta" scalar used in the gemm-only // subproblems that correspond to micro-panels that do not intersect // the diagonal. We need this separate scalar because it's possible // that the alpha attached to B was reset, if it was applied during // packing. buf_alpha2 = bli_obj_internal_scalar_buffer( c ); // Index into the type combination array to extract the correct // function pointer. f = ftypes[dt_exec]; // Invoke the function. f( diagoffa, schema_a, schema_b, m, n, k, buf_alpha1, buf_a, cs_a, pd_a, ps_a, buf_b, rs_b, pd_b, ps_b, buf_alpha2, buf_c, rs_c, cs_c, cntx, rntm, thread ); } #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ doff_t diagoffa, \ pack_t schema_a, \ pack_t schema_b, \ dim_t m, \ dim_t n, \ dim_t k, \ void* alpha1, \ void* a, inc_t cs_a, dim_t pd_a, inc_t ps_a, \ void* b, inc_t rs_b, dim_t pd_b, inc_t ps_b, \ void* alpha2, \ void* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx, \ rntm_t* rntm, \ thrinfo_t* thread \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ /* Alias some constants to simpler names. */ \ const dim_t MR = pd_a; \ const dim_t NR = pd_b; \ const dim_t PACKMR = cs_a; \ const dim_t PACKNR = rs_b; \ \ /* Cast the micro-kernel address to its function pointer type. */ \ PASTECH(ch,gemmtrsm_ukr_ft) \ gemmtrsm_ukr = bli_cntx_get_l3_vir_ukr_dt( dt, BLIS_GEMMTRSM_U_UKR, cntx ); \ PASTECH(ch,gemm_ukr_ft) \ gemm_ukr = bli_cntx_get_l3_vir_ukr_dt( dt, BLIS_GEMM_UKR, cntx ); \ \ /* Temporary C buffer for edge cases. Note that the strides of this temporary buffer are set so that they match the storage of the original C matrix. For example, if C is column-stored, ct will be column-stored as well. */ \ ctype ct[ BLIS_STACK_BUF_MAX_SIZE \ / sizeof( ctype ) ] \ __attribute__((aligned(BLIS_STACK_BUF_ALIGN_SIZE))); \ const bool col_pref = bli_cntx_l3_vir_ukr_prefers_cols_dt( dt, BLIS_GEMM_UKR, cntx ); \ const inc_t rs_ct = ( col_pref ? 1 : NR ); \ const inc_t cs_ct = ( col_pref ? MR : 1 ); \ \ ctype* restrict zero = PASTEMAC(ch,0); \ ctype* restrict minus_one = PASTEMAC(ch,m1); \ ctype* restrict a_cast = a; \ ctype* restrict b_cast = b; \ ctype* restrict c_cast = c; \ ctype* restrict alpha1_cast = alpha1; \ ctype* restrict alpha2_cast = alpha2; \ ctype* restrict b1; \ ctype* restrict c1; \ \ doff_t diagoffa_i; \ dim_t k_full; \ dim_t m_iter, m_left; \ dim_t n_iter, n_left; \ dim_t m_cur; \ dim_t n_cur; \ dim_t k_a1112; \ dim_t k_a11; \ dim_t k_a12; \ dim_t off_a11; \ dim_t off_a12; \ dim_t i, j, ib; \ inc_t rstep_a; \ inc_t cstep_b; \ inc_t rstep_c, cstep_c; \ inc_t istep_a; \ inc_t istep_b; \ inc_t off_scl; \ inc_t ss_a_num; \ inc_t ss_a_den; \ inc_t ps_a_cur; \ inc_t is_a_cur; \ auxinfo_t aux; \ \ /* Assumptions/assertions: rs_a == 1 cs_a == PACKMR pd_a == MR ps_a == stride to next micro-panel of A rs_b == PACKNR cs_b == 1 pd_b == NR ps_b == stride to next micro-panel of B rs_c == (no assumptions) cs_c == (no assumptions) */ \ \ /* Safety trap: Certain indexing within this macro-kernel does not work as intended if both MR and NR are odd. */ \ if ( ( bli_is_odd( PACKMR ) && bli_is_odd( NR ) ) || \ ( bli_is_odd( PACKNR ) && bli_is_odd( MR ) ) ) bli_abort(); \ \ /* If any dimension is zero, return immediately. */ \ if ( bli_zero_dim3( m, n, k ) ) return; \ \ /* Safeguard: If matrix A is below the diagonal, it is implicitly zero. So we do nothing. */ \ if ( bli_is_strictly_below_diag_n( diagoffa, m, k ) ) return; \ \ /* Compute k_full as k inflated up to a multiple of MR. This is needed because some parameter combinations of trsm reduce k to advance past zero regions in the triangular matrix, and when computing the imaginary stride of B (the non-triangular matrix), which is used by 4m1/3m1 implementations, we need this unreduced value of k. */ \ k_full = ( k % MR != 0 ? k + MR - ( k % MR ) : k ); \ \ /* Compute indexing scaling factor for for 4m or 3m. This is needed because one of the packing register blocksizes (PACKMR or PACKNR) is used to index into the micro-panels of the non- triangular matrix when computing with a diagonal-intersecting micro-panel of the triangular matrix. In the case of 4m or 3m, real values are stored in both sub-panels, and so the indexing needs to occur in units of real values. The value computed here is divided into the complex pointer offset to cause the pointer to be advanced by the correct value. */ \ if ( bli_is_4mi_packed( schema_a ) || \ bli_is_3mi_packed( schema_a ) || \ bli_is_rih_packed( schema_a ) ) off_scl = 2; \ else off_scl = 1; \ \ /* Compute the storage stride scaling. Usually this is just 1. However, in the case of interleaved 3m, we need to scale the offset by 3/2. Note that real-only, imag-only, and summed-only packing formats are not applicable here since trsm is a two- operand operation only (unlike trmm, which is capable of three- operand). */ \ if ( bli_is_3mi_packed( schema_a ) ) { ss_a_num = 3; ss_a_den = 2; } \ else { ss_a_num = 1; ss_a_den = 1; } \ \ /* If there is a zero region to the left of where the diagonal of A intersects the top edge of the block, adjust the pointer to B and treat this case as if the diagonal offset were zero. Note that we don't need to adjust the pointer to A since packm would have simply skipped over the region that was not stored. */ \ if ( diagoffa > 0 ) \ { \ i = diagoffa; \ k = k - i; \ diagoffa = 0; \ b_cast = b_cast + ( i * PACKNR ) / off_scl; \ } \ \ /* If there is a zero region below where the diagonal of A intersects the right side of the block, shrink it to prevent "no-op" iterations from executing. */ \ if ( -diagoffa + k < m ) \ { \ m = -diagoffa + k; \ } \ \ /* Check the k dimension, which needs to be a multiple of MR. If k isn't a multiple of MR, we adjust it higher to satisfy the micro- kernel, which is expecting to perform an MR x MR triangular solve. This adjustment of k is consistent with what happened when A was packed: all of its bottom/right edges were zero-padded, and furthermore, the panel that stores the bottom-right corner of the matrix has its diagonal extended into the zero-padded region (as identity). This allows the trsm of that bottom-right panel to proceed without producing any infs or NaNs that would infect the "good" values of the corresponding block of B. */ \ if ( k % MR != 0 ) k += MR - ( k % MR ); \ \ /* NOTE: We don't need to check that m is a multiple of PACKMR since we know that the underlying buffer was already allocated to have an m dimension that is a multiple of PACKMR, with the region between the last row and the next multiple of MR zero-padded accordingly. */ \ \ /* Clear the temporary C buffer in case it has any infs or NaNs. */ \ PASTEMAC(ch,set0s_mxn)( MR, NR, \ ct, rs_ct, cs_ct ); \ \ /* Compute number of primary and leftover components of the m and n dimensions. */ \ n_iter = n / NR; \ n_left = n % NR; \ \ m_iter = m / MR; \ m_left = m % MR; \ \ if ( n_left ) ++n_iter; \ if ( m_left ) ++m_iter; \ \ /* Determine some increments used to step through A, B, and C. */ \ rstep_a = ps_a; \ \ cstep_b = ps_b; \ \ rstep_c = rs_c * MR; \ cstep_c = cs_c * NR; \ \ istep_a = PACKMR * k; \ istep_b = PACKNR * k_full; \ \ if ( bli_is_odd( istep_a ) ) istep_a += 1; \ if ( bli_is_odd( istep_b ) ) istep_b += 1; \ \ /* Save the pack schemas of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_schema_a( schema_a, &aux ); \ bli_auxinfo_set_schema_b( schema_b, &aux ); \ \ /* Save the imaginary stride of B to the auxinfo_t object. */ \ bli_auxinfo_set_is_b( istep_b, &aux ); \ \ b1 = b_cast; \ c1 = c_cast; \ \ /* Loop over the n dimension (NR columns at a time). */ \ for ( j = 0; j < n_iter; ++j ) \ { \ if( bli_trsm_my_iter( j, thread ) ) { \ \ ctype* restrict a1; \ ctype* restrict c11; \ ctype* restrict b2; \ \ a1 = a_cast; \ c11 = c1 + (m_iter-1)*rstep_c; \ \ n_cur = ( bli_is_not_edge_f( j, n_iter, n_left ) ? NR : n_left ); \ \ /* Initialize our next panel of B to be the current panel of B. */ \ b2 = b1; \ \ /* Loop over the m dimension (MR rows at a time). */ \ for ( ib = 0; ib < m_iter; ++ib ) \ { \ i = m_iter - 1 - ib; \ diagoffa_i = diagoffa + ( doff_t )i*MR; \ \ m_cur = ( bli_is_not_edge_b( ib, m_iter, m_left ) ? MR : m_left ); \ \ /* If the current panel of A intersects the diagonal, use a special micro-kernel that performs a fused gemm and trsm. If the current panel of A resides above the diagonal, use a a regular gemm micro-kernel. Otherwise, if it is below the diagonal, it was not packed (because it is implicitly zero) and so we do nothing. */ \ if ( bli_intersects_diag_n( diagoffa_i, MR, k ) ) \ { \ ctype* restrict a11; \ ctype* restrict a12; \ ctype* restrict b11; \ ctype* restrict b21; \ ctype* restrict a2; \ \ /* Compute various offsets into and lengths of parts of A. */ \ off_a11 = diagoffa_i; \ k_a1112 = k - off_a11;; \ k_a11 = MR; \ k_a12 = k_a1112 - MR; \ off_a12 = off_a11 + k_a11; \ \ /* Compute the panel stride for the current diagonal- intersecting micro-panel. */ \ is_a_cur = k_a1112 * PACKMR; \ is_a_cur += ( bli_is_odd( is_a_cur ) ? 1 : 0 ); \ ps_a_cur = ( is_a_cur * ss_a_num ) / ss_a_den; \ \ /* Compute the addresses of the triangular block A11 and the panel A12. */ \ a11 = a1; \ /* a12 = a1 + ( k_a11 * PACKMR ) / off_scl; */ \ a12 = bli_ptr_inc_by_frac( a1, sizeof( ctype ), k_a11 * PACKMR, off_scl ); \ \ /* Compute the addresses of the panel B01 and the block B11. */ \ b11 = b1 + ( off_a11 * PACKNR ) / off_scl; \ b21 = b1 + ( off_a12 * PACKNR ) / off_scl; \ \ /* Compute the addresses of the next panels of A and B. */ \ a2 = a1 + ps_a_cur; \ if ( bli_is_last_iter( ib, m_iter, 0, 1 ) ) \ { \ a2 = a_cast; \ b2 = b1; \ /*if ( bli_is_last_iter( j, n_iter, 0, 1 ) ) */\ if ( j + bli_thread_num_threads(thread) >= n_iter ) \ b2 = b_cast; \ } \ \ /* Save addresses of next panels of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_next_a( a2, &aux ); \ bli_auxinfo_set_next_b( b2, &aux ); \ \ /* Save the 4m1/3m1 imaginary stride of A to the auxinfo_t object. */ \ bli_auxinfo_set_is_a( is_a_cur, &aux ); \ \ /* Handle interior and edge cases separately. */ \ if ( m_cur == MR && n_cur == NR ) \ { \ /* Invoke the fused gemm/trsm micro-kernel. */ \ gemmtrsm_ukr \ ( \ k_a12, \ alpha1_cast, \ a12, \ a11, \ b21, \ b11, \ c11, rs_c, cs_c, \ &aux, \ cntx \ ); \ } \ else \ { \ /* Invoke the fused gemm/trsm micro-kernel. */ \ gemmtrsm_ukr \ ( \ k_a12, \ alpha1_cast, \ a12, \ a11, \ b21, \ b11, \ ct, rs_ct, cs_ct, \ &aux, \ cntx \ ); \ \ /* Copy the result to the bottom edge of C. */ \ PASTEMAC(ch,copys_mxn)( m_cur, n_cur, \ ct, rs_ct, cs_ct, \ c11, rs_c, cs_c ); \ } \ \ a1 += ps_a_cur; \ } \ else if ( bli_is_strictly_above_diag_n( diagoffa_i, MR, k ) ) \ { \ ctype* restrict a2; \ \ /* Compute the addresses of the next panels of A and B. */ \ a2 = a1 + rstep_a; \ if ( bli_is_last_iter( ib, m_iter, 0, 1 ) ) \ { \ a2 = a_cast; \ b2 = b1; \ /*if ( bli_is_last_iter( j, n_iter, 0, 1 ) ) */\ if ( j + bli_thread_num_threads(thread) >= n_iter ) \ b2 = b_cast; \ } \ \ /* Save addresses of next panels of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_next_a( a2, &aux ); \ bli_auxinfo_set_next_b( b2, &aux ); \ \ /* Save the 4m1/3m1 imaginary stride of A to the auxinfo_t object. */ \ bli_auxinfo_set_is_a( istep_a, &aux ); \ \ /* Handle interior and edge cases separately. */ \ if ( m_cur == MR && n_cur == NR ) \ { \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k, \ minus_one, \ a1, \ b1, \ alpha2_cast, \ c11, rs_c, cs_c, \ &aux, \ cntx \ ); \ } \ else \ { \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k, \ minus_one, \ a1, \ b1, \ zero, \ ct, rs_ct, cs_ct, \ &aux, \ cntx \ ); \ \ /* Add the result to the edge of C. */ \ PASTEMAC(ch,xpbys_mxn)( m_cur, n_cur, \ ct, rs_ct, cs_ct, \ alpha2_cast, \ c11, rs_c, cs_c ); \ } \ \ a1 += rstep_a; \ } \ \ c11 -= rstep_c; \ } \ } \ \ b1 += cstep_b; \ c1 += cstep_c; \ } \ \ /* PASTEMAC(ch,fprintm)( stdout, "trsm_lu_ker_var2: a1 (diag)", MR, k_a1112, a1, 1, MR, "%5.2f", "" ); \ PASTEMAC(ch,fprintm)( stdout, "trsm_lu_ker_var2: b11 (diag)", MR, NR, b11, NR, 1, "%6.3f", "" ); \ printf( "m_iter = %lu\n", m_iter ); \ printf( "m_cur = %lu\n", m_cur ); \ printf( "k = %lu\n", k ); \ printf( "diagoffa_i = %lu\n", diagoffa_i ); \ printf( "off_a1112 = %lu\n", off_a1112 ); \ printf( "k_a1112 = %lu\n", k_a1112 ); \ printf( "k_a12 = %lu\n", k_a12 ); \ printf( "k_a11 = %lu\n", k_a11 ); \ printf( "rs_c,cs_c = %lu %lu\n", rs_c, cs_c ); \ printf( "rs_ct,cs_ct= %lu %lu\n", rs_ct, cs_ct ); \ */ \ \ /* PASTEMAC(ch,fprintm)( stdout, "trsm_lu_ker_var2: b11 after (diag)", MR, NR, b11, NR, 1, "%5.2f", "" ); \ PASTEMAC(ch,fprintm)( stdout, "trsm_lu_ker_var2: b11 after (diag)", MR, NR, b11, NR, 1, "%5.2f", "" ); \ PASTEMAC(ch,fprintm)( stdout, "trsm_lu_ker_var2: ct after (diag)", m_cur, n_cur, ct, rs_ct, cs_ct, "%5.2f", "" ); \ */ \ } INSERT_GENTFUNC_BASIC0( trsm_lu_ker_var2 ) blis-0.9.0/frame/3/trsm/other/bli_trsm_lu_ker_var2rr.c000066400000000000000000000460021422157504600226410ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define FUNCPTR_T gemm_fp typedef void (*FUNCPTR_T) ( doff_t diagoffa, pack_t schema_a, pack_t schema_b, dim_t m, dim_t n, dim_t k, void* alpha1, void* a, inc_t cs_a, dim_t pd_a, inc_t ps_a, void* b, inc_t rs_b, dim_t pd_b, inc_t ps_b, void* alpha2, void* c, inc_t rs_c, inc_t cs_c, cntx_t* cntx, rntm_t* rntm, thrinfo_t* thread ); static FUNCPTR_T GENARRAY(ftypes,trsm_lu_ker_var2rr); // // -- Macrokernel functions for round-robin partitioning ----------------------- // void bli_trsm_lu_ker_var2rr ( obj_t* a, obj_t* b, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ) { num_t dt_exec = bli_obj_exec_dt( c ); doff_t diagoffa = bli_obj_diag_offset( a ); pack_t schema_a = bli_obj_pack_schema( a ); pack_t schema_b = bli_obj_pack_schema( b ); dim_t m = bli_obj_length( c ); dim_t n = bli_obj_width( c ); dim_t k = bli_obj_width( a ); void* buf_a = bli_obj_buffer_at_off( a ); inc_t cs_a = bli_obj_col_stride( a ); dim_t pd_a = bli_obj_panel_dim( a ); inc_t ps_a = bli_obj_panel_stride( a ); void* buf_b = bli_obj_buffer_at_off( b ); inc_t rs_b = bli_obj_row_stride( b ); dim_t pd_b = bli_obj_panel_dim( b ); inc_t ps_b = bli_obj_panel_stride( b ); void* buf_c = bli_obj_buffer_at_off( c ); inc_t rs_c = bli_obj_row_stride( c ); inc_t cs_c = bli_obj_col_stride( c ); void* buf_alpha1; void* buf_alpha2; FUNCPTR_T f; // Grab the address of the internal scalar buffer for the scalar // attached to B (the non-triangular matrix). This will be the alpha // scalar used in the gemmtrsm subproblems (ie: the scalar that would // be applied to the packed copy of B prior to it being updated by // the trsm subproblem). This scalar may be unit, if for example it // was applied during packing. buf_alpha1 = bli_obj_internal_scalar_buffer( b ); // Grab the address of the internal scalar buffer for the scalar // attached to C. This will be the "beta" scalar used in the gemm-only // subproblems that correspond to micro-panels that do not intersect // the diagonal. We need this separate scalar because it's possible // that the alpha attached to B was reset, if it was applied during // packing. buf_alpha2 = bli_obj_internal_scalar_buffer( c ); // Index into the type combination array to extract the correct // function pointer. f = ftypes[dt_exec]; // Invoke the function. f( diagoffa, schema_a, schema_b, m, n, k, buf_alpha1, buf_a, cs_a, pd_a, ps_a, buf_b, rs_b, pd_b, ps_b, buf_alpha2, buf_c, rs_c, cs_c, cntx, rntm, thread ); } #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ doff_t diagoffa, \ pack_t schema_a, \ pack_t schema_b, \ dim_t m, \ dim_t n, \ dim_t k, \ void* alpha1, \ void* a, inc_t cs_a, dim_t pd_a, inc_t ps_a, \ void* b, inc_t rs_b, dim_t pd_b, inc_t ps_b, \ void* alpha2, \ void* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx, \ rntm_t* rntm, \ thrinfo_t* thread \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ /* Alias some constants to simpler names. */ \ const dim_t MR = pd_a; \ const dim_t NR = pd_b; \ const dim_t PACKMR = cs_a; \ const dim_t PACKNR = rs_b; \ \ /* Cast the micro-kernel address to its function pointer type. */ \ PASTECH(ch,gemmtrsm_ukr_ft) \ gemmtrsm_ukr = bli_cntx_get_l3_vir_ukr_dt( dt, BLIS_GEMMTRSM_U_UKR, cntx ); \ PASTECH(ch,gemm_ukr_ft) \ gemm_ukr = bli_cntx_get_l3_vir_ukr_dt( dt, BLIS_GEMM_UKR, cntx ); \ \ /* Temporary C buffer for edge cases. Note that the strides of this temporary buffer are set so that they match the storage of the original C matrix. For example, if C is column-stored, ct will be column-stored as well. */ \ ctype ct[ BLIS_STACK_BUF_MAX_SIZE \ / sizeof( ctype ) ] \ __attribute__((aligned(BLIS_STACK_BUF_ALIGN_SIZE))); \ const bool col_pref = bli_cntx_l3_vir_ukr_prefers_cols_dt( dt, BLIS_GEMM_UKR, cntx ); \ const inc_t rs_ct = ( col_pref ? 1 : NR ); \ const inc_t cs_ct = ( col_pref ? MR : 1 ); \ \ ctype* restrict zero = PASTEMAC(ch,0); \ ctype* restrict minus_one = PASTEMAC(ch,m1); \ ctype* restrict a_cast = a; \ ctype* restrict b_cast = b; \ ctype* restrict c_cast = c; \ ctype* restrict alpha1_cast = alpha1; \ ctype* restrict alpha2_cast = alpha2; \ ctype* restrict b1; \ ctype* restrict c1; \ \ doff_t diagoffa_i; \ dim_t k_full; \ dim_t m_iter, m_left; \ dim_t n_iter, n_left; \ dim_t m_cur; \ dim_t n_cur; \ dim_t k_a1112; \ dim_t k_a11; \ dim_t k_a12; \ dim_t off_a11; \ dim_t off_a12; \ dim_t i, j, ib; \ inc_t rstep_a; \ inc_t cstep_b; \ inc_t rstep_c, cstep_c; \ inc_t istep_a; \ inc_t istep_b; \ inc_t off_scl; \ inc_t ss_a_num; \ inc_t ss_a_den; \ inc_t ps_a_cur; \ inc_t is_a_cur; \ auxinfo_t aux; \ \ /* Assumptions/assertions: rs_a == 1 cs_a == PACKMR pd_a == MR ps_a == stride to next micro-panel of A rs_b == PACKNR cs_b == 1 pd_b == NR ps_b == stride to next micro-panel of B rs_c == (no assumptions) cs_c == (no assumptions) */ \ \ /* Safety trap: Certain indexing within this macro-kernel does not work as intended if both MR and NR are odd. */ \ if ( ( bli_is_odd( PACKMR ) && bli_is_odd( NR ) ) || \ ( bli_is_odd( PACKNR ) && bli_is_odd( MR ) ) ) bli_abort(); \ \ /* If any dimension is zero, return immediately. */ \ if ( bli_zero_dim3( m, n, k ) ) return; \ \ /* Safeguard: If matrix A is below the diagonal, it is implicitly zero. So we do nothing. */ \ if ( bli_is_strictly_below_diag_n( diagoffa, m, k ) ) return; \ \ /* Compute k_full as k inflated up to a multiple of MR. This is needed because some parameter combinations of trsm reduce k to advance past zero regions in the triangular matrix, and when computing the imaginary stride of B (the non-triangular matrix), which is used by 4m1/3m1 implementations, we need this unreduced value of k. */ \ k_full = ( k % MR != 0 ? k + MR - ( k % MR ) : k ); \ \ /* Compute indexing scaling factor for for 4m or 3m. This is needed because one of the packing register blocksizes (PACKMR or PACKNR) is used to index into the micro-panels of the non- triangular matrix when computing with a diagonal-intersecting micro-panel of the triangular matrix. In the case of 4m or 3m, real values are stored in both sub-panels, and so the indexing needs to occur in units of real values. The value computed here is divided into the complex pointer offset to cause the pointer to be advanced by the correct value. */ \ if ( bli_is_4mi_packed( schema_a ) || \ bli_is_3mi_packed( schema_a ) || \ bli_is_rih_packed( schema_a ) ) off_scl = 2; \ else off_scl = 1; \ \ /* Compute the storage stride scaling. Usually this is just 1. However, in the case of interleaved 3m, we need to scale the offset by 3/2. Note that real-only, imag-only, and summed-only packing formats are not applicable here since trsm is a two- operand operation only (unlike trmm, which is capable of three- operand). */ \ if ( bli_is_3mi_packed( schema_a ) ) { ss_a_num = 3; ss_a_den = 2; } \ else { ss_a_num = 1; ss_a_den = 1; } \ \ /* If there is a zero region to the left of where the diagonal of A intersects the top edge of the block, adjust the pointer to B and treat this case as if the diagonal offset were zero. Note that we don't need to adjust the pointer to A since packm would have simply skipped over the region that was not stored. */ \ if ( diagoffa > 0 ) \ { \ i = diagoffa; \ k = k - i; \ diagoffa = 0; \ b_cast = b_cast + ( i * PACKNR ) / off_scl; \ } \ \ /* If there is a zero region below where the diagonal of A intersects the right side of the block, shrink it to prevent "no-op" iterations from executing. */ \ if ( -diagoffa + k < m ) \ { \ m = -diagoffa + k; \ } \ \ /* Check the k dimension, which needs to be a multiple of MR. If k isn't a multiple of MR, we adjust it higher to satisfy the micro- kernel, which is expecting to perform an MR x MR triangular solve. This adjustment of k is consistent with what happened when A was packed: all of its bottom/right edges were zero-padded, and furthermore, the panel that stores the bottom-right corner of the matrix has its diagonal extended into the zero-padded region (as identity). This allows the trsm of that bottom-right panel to proceed without producing any infs or NaNs that would infect the "good" values of the corresponding block of B. */ \ if ( k % MR != 0 ) k += MR - ( k % MR ); \ \ /* NOTE: We don't need to check that m is a multiple of PACKMR since we know that the underlying buffer was already allocated to have an m dimension that is a multiple of PACKMR, with the region between the last row and the next multiple of MR zero-padded accordingly. */ \ \ /* Clear the temporary C buffer in case it has any infs or NaNs. */ \ PASTEMAC(ch,set0s_mxn)( MR, NR, \ ct, rs_ct, cs_ct ); \ \ /* Compute number of primary and leftover components of the m and n dimensions. */ \ n_iter = n / NR; \ n_left = n % NR; \ \ m_iter = m / MR; \ m_left = m % MR; \ \ if ( n_left ) ++n_iter; \ if ( m_left ) ++m_iter; \ \ /* Determine some increments used to step through A, B, and C. */ \ rstep_a = ps_a; \ \ cstep_b = ps_b; \ \ rstep_c = rs_c * MR; \ cstep_c = cs_c * NR; \ \ istep_a = PACKMR * k; \ istep_b = PACKNR * k_full; \ \ if ( bli_is_odd( istep_a ) ) istep_a += 1; \ if ( bli_is_odd( istep_b ) ) istep_b += 1; \ \ /* Save the pack schemas of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_schema_a( schema_a, &aux ); \ bli_auxinfo_set_schema_b( schema_b, &aux ); \ \ /* Save the imaginary stride of B to the auxinfo_t object. */ \ bli_auxinfo_set_is_b( istep_b, &aux ); \ \ /* We don't bother querying the thrinfo_t node for the 1st loop because we can't parallelize that loop in trsm due to the inter-iteration dependencies that exist. */ \ /*thrinfo_t* caucus = bli_thrinfo_sub_node( thread );*/ \ \ /* Query the number of threads and thread ids for each loop. */ \ dim_t jr_nt = bli_thread_n_way( thread ); \ dim_t jr_tid = bli_thread_work_id( thread ); \ \ dim_t jr_start, jr_end; \ dim_t jr_inc; \ \ /* Use round-robin assignment of micropanels to threads in the 2nd loop. NOTE: Parallelism in the 1st loop is unattainable due to the inter-iteration dependencies present in trsm. */ \ bli_thread_range_jrir_rr( thread, n_iter, 1, FALSE, &jr_start, &jr_end, &jr_inc ); \ \ /* Loop over the n dimension (NR columns at a time). */ \ for ( j = jr_start; j < jr_end; j += jr_inc ) \ { \ ctype* restrict a1; \ ctype* restrict c11; \ ctype* restrict b2; \ \ b1 = b_cast + j * cstep_b; \ c1 = c_cast + j * cstep_c; \ \ n_cur = ( bli_is_not_edge_f( j, n_iter, n_left ) ? NR : n_left ); \ \ /* Initialize our next panel of B to be the current panel of B. */ \ b2 = b1; \ \ a1 = a_cast; \ c11 = c1 + (m_iter-1)*rstep_c; \ \ /* Loop over the m dimension (MR rows at a time). */ \ for ( ib = 0; ib < m_iter; ++ib ) \ { \ i = m_iter - 1 - ib; \ diagoffa_i = diagoffa + ( doff_t )i*MR; \ \ m_cur = ( bli_is_not_edge_b( ib, m_iter, m_left ) ? MR : m_left ); \ \ /* If the current panel of A intersects the diagonal, use a special micro-kernel that performs a fused gemm and trsm. If the current panel of A resides above the diagonal, use a a regular gemm micro-kernel. Otherwise, if it is below the diagonal, it was not packed (because it is implicitly zero) and so we do nothing. */ \ if ( bli_intersects_diag_n( diagoffa_i, MR, k ) ) \ { \ ctype* restrict a11; \ ctype* restrict a12; \ ctype* restrict b11; \ ctype* restrict b21; \ ctype* restrict a2; \ \ /* Compute various offsets into and lengths of parts of A. */ \ off_a11 = diagoffa_i; \ k_a1112 = k - off_a11;; \ k_a11 = MR; \ k_a12 = k_a1112 - MR; \ off_a12 = off_a11 + k_a11; \ \ /* Compute the panel stride for the current diagonal- intersecting micro-panel. */ \ is_a_cur = k_a1112 * PACKMR; \ is_a_cur += ( bli_is_odd( is_a_cur ) ? 1 : 0 ); \ ps_a_cur = ( is_a_cur * ss_a_num ) / ss_a_den; \ \ /* Compute the addresses of the triangular block A11 and the panel A12. */ \ a11 = a1; \ /* a12 = a1 + ( k_a11 * PACKMR ) / off_scl; */ \ a12 = bli_ptr_inc_by_frac( a1, sizeof( ctype ), k_a11 * PACKMR, off_scl ); \ \ /* Compute the addresses of the panel B01 and the block B11. */ \ b11 = b1 + ( off_a11 * PACKNR ) / off_scl; \ b21 = b1 + ( off_a12 * PACKNR ) / off_scl; \ \ /* Compute the addresses of the next panels of A and B. */ \ a2 = a1 + ps_a_cur; \ if ( bli_is_last_iter_rr( ib, m_iter, 0, 1 ) ) \ { \ a2 = a_cast; \ b2 = b1; \ if ( bli_is_last_iter_rr( j, n_iter, jr_tid, jr_nt ) ) \ b2 = b_cast; \ } \ \ /* Save addresses of next panels of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_next_a( a2, &aux ); \ bli_auxinfo_set_next_b( b2, &aux ); \ \ /* Save the 4m1/3m1 imaginary stride of A to the auxinfo_t object. */ \ bli_auxinfo_set_is_a( is_a_cur, &aux ); \ \ /* Handle interior and edge cases separately. */ \ if ( m_cur == MR && n_cur == NR ) \ { \ /* Invoke the fused gemm/trsm micro-kernel. */ \ gemmtrsm_ukr \ ( \ k_a12, \ alpha1_cast, \ a12, \ a11, \ b21, \ b11, \ c11, rs_c, cs_c, \ &aux, \ cntx \ ); \ } \ else \ { \ /* Invoke the fused gemm/trsm micro-kernel. */ \ gemmtrsm_ukr \ ( \ k_a12, \ alpha1_cast, \ a12, \ a11, \ b21, \ b11, \ ct, rs_ct, cs_ct, \ &aux, \ cntx \ ); \ \ /* Copy the result to the bottom edge of C. */ \ PASTEMAC(ch,copys_mxn)( m_cur, n_cur, \ ct, rs_ct, cs_ct, \ c11, rs_c, cs_c ); \ } \ \ a1 += ps_a_cur; \ } \ else if ( bli_is_strictly_above_diag_n( diagoffa_i, MR, k ) ) \ { \ ctype* restrict a2; \ \ /* Compute the addresses of the next panels of A and B. */ \ a2 = a1 + rstep_a; \ if ( bli_is_last_iter_rr( ib, m_iter, 0, 1 ) ) \ { \ a2 = a_cast; \ b2 = b1; \ if ( bli_is_last_iter_rr( j, n_iter, jr_tid, jr_nt ) ) \ b2 = b_cast; \ } \ \ /* Save addresses of next panels of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_next_a( a2, &aux ); \ bli_auxinfo_set_next_b( b2, &aux ); \ \ /* Save the 4m1/3m1 imaginary stride of A to the auxinfo_t object. */ \ bli_auxinfo_set_is_a( istep_a, &aux ); \ \ /* Handle interior and edge cases separately. */ \ if ( m_cur == MR && n_cur == NR ) \ { \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k, \ minus_one, \ a1, \ b1, \ alpha2_cast, \ c11, rs_c, cs_c, \ &aux, \ cntx \ ); \ } \ else \ { \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k, \ minus_one, \ a1, \ b1, \ zero, \ ct, rs_ct, cs_ct, \ &aux, \ cntx \ ); \ \ /* Add the result to the edge of C. */ \ PASTEMAC(ch,xpbys_mxn)( m_cur, n_cur, \ ct, rs_ct, cs_ct, \ alpha2_cast, \ c11, rs_c, cs_c ); \ } \ \ a1 += rstep_a; \ } \ \ c11 -= rstep_c; \ } \ } \ \ /* PASTEMAC(ch,fprintm)( stdout, "trsm_lu_ker_var2: a1 (diag)", MR, k_a1112, a1, 1, MR, "%5.2f", "" ); \ PASTEMAC(ch,fprintm)( stdout, "trsm_lu_ker_var2: b11 (diag)", MR, NR, b11, NR, 1, "%6.3f", "" ); \ printf( "m_iter = %lu\n", m_iter ); \ printf( "m_cur = %lu\n", m_cur ); \ printf( "k = %lu\n", k ); \ printf( "diagoffa_i = %lu\n", diagoffa_i ); \ printf( "off_a1112 = %lu\n", off_a1112 ); \ printf( "k_a1112 = %lu\n", k_a1112 ); \ printf( "k_a12 = %lu\n", k_a12 ); \ printf( "k_a11 = %lu\n", k_a11 ); \ printf( "rs_c,cs_c = %lu %lu\n", rs_c, cs_c ); \ printf( "rs_ct,cs_ct= %lu %lu\n", rs_ct, cs_ct ); \ */ \ \ /* PASTEMAC(ch,fprintm)( stdout, "trsm_lu_ker_var2: b11 after (diag)", MR, NR, b11, NR, 1, "%5.2f", "" ); \ PASTEMAC(ch,fprintm)( stdout, "trsm_lu_ker_var2: b11 after (diag)", MR, NR, b11, NR, 1, "%5.2f", "" ); \ PASTEMAC(ch,fprintm)( stdout, "trsm_lu_ker_var2: ct after (diag)", m_cur, n_cur, ct, rs_ct, cs_ct, "%5.2f", "" ); \ */ \ } INSERT_GENTFUNC_BASIC0( trsm_lu_ker_var2rr ) blis-0.9.0/frame/3/trsm/other/bli_trsm_lu_ker_var2sl.c000066400000000000000000000457731422157504600226520ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define FUNCPTR_T gemm_fp typedef void (*FUNCPTR_T) ( doff_t diagoffa, pack_t schema_a, pack_t schema_b, dim_t m, dim_t n, dim_t k, void* alpha1, void* a, inc_t cs_a, dim_t pd_a, inc_t ps_a, void* b, inc_t rs_b, dim_t pd_b, inc_t ps_b, void* alpha2, void* c, inc_t rs_c, inc_t cs_c, cntx_t* cntx, rntm_t* rntm, thrinfo_t* thread ); static FUNCPTR_T GENARRAY(ftypes,trsm_lu_ker_var2sl); // // -- Macrokernel functions for slab partitioning ------------------------------ // void bli_trsm_lu_ker_var2sl ( obj_t* a, obj_t* b, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ) { num_t dt_exec = bli_obj_exec_dt( c ); doff_t diagoffa = bli_obj_diag_offset( a ); pack_t schema_a = bli_obj_pack_schema( a ); pack_t schema_b = bli_obj_pack_schema( b ); dim_t m = bli_obj_length( c ); dim_t n = bli_obj_width( c ); dim_t k = bli_obj_width( a ); void* buf_a = bli_obj_buffer_at_off( a ); inc_t cs_a = bli_obj_col_stride( a ); dim_t pd_a = bli_obj_panel_dim( a ); inc_t ps_a = bli_obj_panel_stride( a ); void* buf_b = bli_obj_buffer_at_off( b ); inc_t rs_b = bli_obj_row_stride( b ); dim_t pd_b = bli_obj_panel_dim( b ); inc_t ps_b = bli_obj_panel_stride( b ); void* buf_c = bli_obj_buffer_at_off( c ); inc_t rs_c = bli_obj_row_stride( c ); inc_t cs_c = bli_obj_col_stride( c ); void* buf_alpha1; void* buf_alpha2; FUNCPTR_T f; // Grab the address of the internal scalar buffer for the scalar // attached to B (the non-triangular matrix). This will be the alpha // scalar used in the gemmtrsm subproblems (ie: the scalar that would // be applied to the packed copy of B prior to it being updated by // the trsm subproblem). This scalar may be unit, if for example it // was applied during packing. buf_alpha1 = bli_obj_internal_scalar_buffer( b ); // Grab the address of the internal scalar buffer for the scalar // attached to C. This will be the "beta" scalar used in the gemm-only // subproblems that correspond to micro-panels that do not intersect // the diagonal. We need this separate scalar because it's possible // that the alpha attached to B was reset, if it was applied during // packing. buf_alpha2 = bli_obj_internal_scalar_buffer( c ); // Index into the type combination array to extract the correct // function pointer. f = ftypes[dt_exec]; // Invoke the function. f( diagoffa, schema_a, schema_b, m, n, k, buf_alpha1, buf_a, cs_a, pd_a, ps_a, buf_b, rs_b, pd_b, ps_b, buf_alpha2, buf_c, rs_c, cs_c, cntx, rntm, thread ); } #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ doff_t diagoffa, \ pack_t schema_a, \ pack_t schema_b, \ dim_t m, \ dim_t n, \ dim_t k, \ void* alpha1, \ void* a, inc_t cs_a, dim_t pd_a, inc_t ps_a, \ void* b, inc_t rs_b, dim_t pd_b, inc_t ps_b, \ void* alpha2, \ void* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx, \ rntm_t* rntm, \ thrinfo_t* thread \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ /* Alias some constants to simpler names. */ \ const dim_t MR = pd_a; \ const dim_t NR = pd_b; \ const dim_t PACKMR = cs_a; \ const dim_t PACKNR = rs_b; \ \ /* Cast the micro-kernel address to its function pointer type. */ \ PASTECH(ch,gemmtrsm_ukr_ft) \ gemmtrsm_ukr = bli_cntx_get_l3_vir_ukr_dt( dt, BLIS_GEMMTRSM_U_UKR, cntx ); \ PASTECH(ch,gemm_ukr_ft) \ gemm_ukr = bli_cntx_get_l3_vir_ukr_dt( dt, BLIS_GEMM_UKR, cntx ); \ \ /* Temporary C buffer for edge cases. Note that the strides of this temporary buffer are set so that they match the storage of the original C matrix. For example, if C is column-stored, ct will be column-stored as well. */ \ ctype ct[ BLIS_STACK_BUF_MAX_SIZE \ / sizeof( ctype ) ] \ __attribute__((aligned(BLIS_STACK_BUF_ALIGN_SIZE))); \ const bool col_pref = bli_cntx_l3_vir_ukr_prefers_cols_dt( dt, BLIS_GEMM_UKR, cntx ); \ const inc_t rs_ct = ( col_pref ? 1 : NR ); \ const inc_t cs_ct = ( col_pref ? MR : 1 ); \ \ ctype* restrict zero = PASTEMAC(ch,0); \ ctype* restrict minus_one = PASTEMAC(ch,m1); \ ctype* restrict a_cast = a; \ ctype* restrict b_cast = b; \ ctype* restrict c_cast = c; \ ctype* restrict alpha1_cast = alpha1; \ ctype* restrict alpha2_cast = alpha2; \ ctype* restrict b1; \ ctype* restrict c1; \ \ doff_t diagoffa_i; \ dim_t k_full; \ dim_t m_iter, m_left; \ dim_t n_iter, n_left; \ dim_t m_cur; \ dim_t n_cur; \ dim_t k_a1112; \ dim_t k_a11; \ dim_t k_a12; \ dim_t off_a11; \ dim_t off_a12; \ dim_t i, j, ib; \ inc_t rstep_a; \ inc_t cstep_b; \ inc_t rstep_c, cstep_c; \ inc_t istep_a; \ inc_t istep_b; \ inc_t off_scl; \ inc_t ss_a_num; \ inc_t ss_a_den; \ inc_t ps_a_cur; \ inc_t is_a_cur; \ auxinfo_t aux; \ \ /* Assumptions/assertions: rs_a == 1 cs_a == PACKMR pd_a == MR ps_a == stride to next micro-panel of A rs_b == PACKNR cs_b == 1 pd_b == NR ps_b == stride to next micro-panel of B rs_c == (no assumptions) cs_c == (no assumptions) */ \ \ /* Safety trap: Certain indexing within this macro-kernel does not work as intended if both MR and NR are odd. */ \ if ( ( bli_is_odd( PACKMR ) && bli_is_odd( NR ) ) || \ ( bli_is_odd( PACKNR ) && bli_is_odd( MR ) ) ) bli_abort(); \ \ /* If any dimension is zero, return immediately. */ \ if ( bli_zero_dim3( m, n, k ) ) return; \ \ /* Safeguard: If matrix A is below the diagonal, it is implicitly zero. So we do nothing. */ \ if ( bli_is_strictly_below_diag_n( diagoffa, m, k ) ) return; \ \ /* Compute k_full as k inflated up to a multiple of MR. This is needed because some parameter combinations of trsm reduce k to advance past zero regions in the triangular matrix, and when computing the imaginary stride of B (the non-triangular matrix), which is used by 4m1/3m1 implementations, we need this unreduced value of k. */ \ k_full = ( k % MR != 0 ? k + MR - ( k % MR ) : k ); \ \ /* Compute indexing scaling factor for for 4m or 3m. This is needed because one of the packing register blocksizes (PACKMR or PACKNR) is used to index into the micro-panels of the non- triangular matrix when computing with a diagonal-intersecting micro-panel of the triangular matrix. In the case of 4m or 3m, real values are stored in both sub-panels, and so the indexing needs to occur in units of real values. The value computed here is divided into the complex pointer offset to cause the pointer to be advanced by the correct value. */ \ if ( bli_is_4mi_packed( schema_a ) || \ bli_is_3mi_packed( schema_a ) || \ bli_is_rih_packed( schema_a ) ) off_scl = 2; \ else off_scl = 1; \ \ /* Compute the storage stride scaling. Usually this is just 1. However, in the case of interleaved 3m, we need to scale the offset by 3/2. Note that real-only, imag-only, and summed-only packing formats are not applicable here since trsm is a two- operand operation only (unlike trmm, which is capable of three- operand). */ \ if ( bli_is_3mi_packed( schema_a ) ) { ss_a_num = 3; ss_a_den = 2; } \ else { ss_a_num = 1; ss_a_den = 1; } \ \ /* If there is a zero region to the left of where the diagonal of A intersects the top edge of the block, adjust the pointer to B and treat this case as if the diagonal offset were zero. Note that we don't need to adjust the pointer to A since packm would have simply skipped over the region that was not stored. */ \ if ( diagoffa > 0 ) \ { \ i = diagoffa; \ k = k - i; \ diagoffa = 0; \ b_cast = b_cast + ( i * PACKNR ) / off_scl; \ } \ \ /* If there is a zero region below where the diagonal of A intersects the right side of the block, shrink it to prevent "no-op" iterations from executing. */ \ if ( -diagoffa + k < m ) \ { \ m = -diagoffa + k; \ } \ \ /* Check the k dimension, which needs to be a multiple of MR. If k isn't a multiple of MR, we adjust it higher to satisfy the micro- kernel, which is expecting to perform an MR x MR triangular solve. This adjustment of k is consistent with what happened when A was packed: all of its bottom/right edges were zero-padded, and furthermore, the panel that stores the bottom-right corner of the matrix has its diagonal extended into the zero-padded region (as identity). This allows the trsm of that bottom-right panel to proceed without producing any infs or NaNs that would infect the "good" values of the corresponding block of B. */ \ if ( k % MR != 0 ) k += MR - ( k % MR ); \ \ /* NOTE: We don't need to check that m is a multiple of PACKMR since we know that the underlying buffer was already allocated to have an m dimension that is a multiple of PACKMR, with the region between the last row and the next multiple of MR zero-padded accordingly. */ \ \ /* Clear the temporary C buffer in case it has any infs or NaNs. */ \ PASTEMAC(ch,set0s_mxn)( MR, NR, \ ct, rs_ct, cs_ct ); \ \ /* Compute number of primary and leftover components of the m and n dimensions. */ \ n_iter = n / NR; \ n_left = n % NR; \ \ m_iter = m / MR; \ m_left = m % MR; \ \ if ( n_left ) ++n_iter; \ if ( m_left ) ++m_iter; \ \ /* Determine some increments used to step through A, B, and C. */ \ rstep_a = ps_a; \ \ cstep_b = ps_b; \ \ rstep_c = rs_c * MR; \ cstep_c = cs_c * NR; \ \ istep_a = PACKMR * k; \ istep_b = PACKNR * k_full; \ \ if ( bli_is_odd( istep_a ) ) istep_a += 1; \ if ( bli_is_odd( istep_b ) ) istep_b += 1; \ \ /* Save the pack schemas of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_schema_a( schema_a, &aux ); \ bli_auxinfo_set_schema_b( schema_b, &aux ); \ \ /* Save the imaginary stride of B to the auxinfo_t object. */ \ bli_auxinfo_set_is_b( istep_b, &aux ); \ \ /* We don't bother querying the thrinfo_t node for the 1st loop because we can't parallelize that loop in trsm due to the inter-iteration dependencies that exist. */ \ /*thrinfo_t* caucus = bli_thrinfo_sub_node( thread );*/ \ \ /* Query the number of threads and thread ids for each loop. */ \ dim_t jr_nt = bli_thread_n_way( thread ); \ dim_t jr_tid = bli_thread_work_id( thread ); \ \ dim_t jr_start, jr_end; \ dim_t jr_inc; \ \ /* Use slab assignment of micropanels to threads in the 2nd loop. NOTE: Parallelism in the 1st loop is unattainable due to the inter-iteration dependencies present in trsm. */ \ bli_thread_range_jrir_sl( thread, n_iter, 1, FALSE, &jr_start, &jr_end, &jr_inc ); \ \ /* Loop over the n dimension (NR columns at a time). */ \ for ( j = jr_start; j < jr_end; j += jr_inc ) \ { \ ctype* restrict a1; \ ctype* restrict c11; \ ctype* restrict b2; \ \ b1 = b_cast + j * cstep_b; \ c1 = c_cast + j * cstep_c; \ \ n_cur = ( bli_is_not_edge_f( j, n_iter, n_left ) ? NR : n_left ); \ \ /* Initialize our next panel of B to be the current panel of B. */ \ b2 = b1; \ \ a1 = a_cast; \ c11 = c1 + (m_iter-1)*rstep_c; \ \ /* Loop over the m dimension (MR rows at a time). */ \ for ( ib = 0; ib < m_iter; ++ib ) \ { \ i = m_iter - 1 - ib; \ diagoffa_i = diagoffa + ( doff_t )i*MR; \ \ m_cur = ( bli_is_not_edge_b( ib, m_iter, m_left ) ? MR : m_left ); \ \ /* If the current panel of A intersects the diagonal, use a special micro-kernel that performs a fused gemm and trsm. If the current panel of A resides above the diagonal, use a a regular gemm micro-kernel. Otherwise, if it is below the diagonal, it was not packed (because it is implicitly zero) and so we do nothing. */ \ if ( bli_intersects_diag_n( diagoffa_i, MR, k ) ) \ { \ ctype* restrict a11; \ ctype* restrict a12; \ ctype* restrict b11; \ ctype* restrict b21; \ ctype* restrict a2; \ \ /* Compute various offsets into and lengths of parts of A. */ \ off_a11 = diagoffa_i; \ k_a1112 = k - off_a11;; \ k_a11 = MR; \ k_a12 = k_a1112 - MR; \ off_a12 = off_a11 + k_a11; \ \ /* Compute the panel stride for the current diagonal- intersecting micro-panel. */ \ is_a_cur = k_a1112 * PACKMR; \ is_a_cur += ( bli_is_odd( is_a_cur ) ? 1 : 0 ); \ ps_a_cur = ( is_a_cur * ss_a_num ) / ss_a_den; \ \ /* Compute the addresses of the triangular block A11 and the panel A12. */ \ a11 = a1; \ /* a12 = a1 + ( k_a11 * PACKMR ) / off_scl; */ \ a12 = bli_ptr_inc_by_frac( a1, sizeof( ctype ), k_a11 * PACKMR, off_scl ); \ \ /* Compute the addresses of the panel B01 and the block B11. */ \ b11 = b1 + ( off_a11 * PACKNR ) / off_scl; \ b21 = b1 + ( off_a12 * PACKNR ) / off_scl; \ \ /* Compute the addresses of the next panels of A and B. */ \ a2 = a1 + ps_a_cur; \ if ( bli_is_last_iter_rr( ib, m_iter, 0, 1 ) ) \ { \ a2 = a_cast; \ b2 = b1; \ if ( bli_is_last_iter_sl( j, n_iter, jr_tid, jr_nt ) ) \ b2 = b_cast; \ } \ \ /* Save addresses of next panels of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_next_a( a2, &aux ); \ bli_auxinfo_set_next_b( b2, &aux ); \ \ /* Save the 4m1/3m1 imaginary stride of A to the auxinfo_t object. */ \ bli_auxinfo_set_is_a( is_a_cur, &aux ); \ \ /* Handle interior and edge cases separately. */ \ if ( m_cur == MR && n_cur == NR ) \ { \ /* Invoke the fused gemm/trsm micro-kernel. */ \ gemmtrsm_ukr \ ( \ k_a12, \ alpha1_cast, \ a12, \ a11, \ b21, \ b11, \ c11, rs_c, cs_c, \ &aux, \ cntx \ ); \ } \ else \ { \ /* Invoke the fused gemm/trsm micro-kernel. */ \ gemmtrsm_ukr \ ( \ k_a12, \ alpha1_cast, \ a12, \ a11, \ b21, \ b11, \ ct, rs_ct, cs_ct, \ &aux, \ cntx \ ); \ \ /* Copy the result to the bottom edge of C. */ \ PASTEMAC(ch,copys_mxn)( m_cur, n_cur, \ ct, rs_ct, cs_ct, \ c11, rs_c, cs_c ); \ } \ \ a1 += ps_a_cur; \ } \ else if ( bli_is_strictly_above_diag_n( diagoffa_i, MR, k ) ) \ { \ ctype* restrict a2; \ \ /* Compute the addresses of the next panels of A and B. */ \ a2 = a1 + rstep_a; \ if ( bli_is_last_iter_rr( ib, m_iter, 0, 1 ) ) \ { \ a2 = a_cast; \ b2 = b1; \ if ( bli_is_last_iter_sl( j, n_iter, jr_tid, jr_nt ) ) \ b2 = b_cast; \ } \ \ /* Save addresses of next panels of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_next_a( a2, &aux ); \ bli_auxinfo_set_next_b( b2, &aux ); \ \ /* Save the 4m1/3m1 imaginary stride of A to the auxinfo_t object. */ \ bli_auxinfo_set_is_a( istep_a, &aux ); \ \ /* Handle interior and edge cases separately. */ \ if ( m_cur == MR && n_cur == NR ) \ { \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k, \ minus_one, \ a1, \ b1, \ alpha2_cast, \ c11, rs_c, cs_c, \ &aux, \ cntx \ ); \ } \ else \ { \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k, \ minus_one, \ a1, \ b1, \ zero, \ ct, rs_ct, cs_ct, \ &aux, \ cntx \ ); \ \ /* Add the result to the edge of C. */ \ PASTEMAC(ch,xpbys_mxn)( m_cur, n_cur, \ ct, rs_ct, cs_ct, \ alpha2_cast, \ c11, rs_c, cs_c ); \ } \ \ a1 += rstep_a; \ } \ \ c11 -= rstep_c; \ } \ } \ \ /* PASTEMAC(ch,fprintm)( stdout, "trsm_lu_ker_var2: a1 (diag)", MR, k_a1112, a1, 1, MR, "%5.2f", "" ); \ PASTEMAC(ch,fprintm)( stdout, "trsm_lu_ker_var2: b11 (diag)", MR, NR, b11, NR, 1, "%6.3f", "" ); \ printf( "m_iter = %lu\n", m_iter ); \ printf( "m_cur = %lu\n", m_cur ); \ printf( "k = %lu\n", k ); \ printf( "diagoffa_i = %lu\n", diagoffa_i ); \ printf( "off_a1112 = %lu\n", off_a1112 ); \ printf( "k_a1112 = %lu\n", k_a1112 ); \ printf( "k_a12 = %lu\n", k_a12 ); \ printf( "k_a11 = %lu\n", k_a11 ); \ printf( "rs_c,cs_c = %lu %lu\n", rs_c, cs_c ); \ printf( "rs_ct,cs_ct= %lu %lu\n", rs_ct, cs_ct ); \ */ \ \ /* PASTEMAC(ch,fprintm)( stdout, "trsm_lu_ker_var2: b11 after (diag)", MR, NR, b11, NR, 1, "%5.2f", "" ); \ PASTEMAC(ch,fprintm)( stdout, "trsm_lu_ker_var2: b11 after (diag)", MR, NR, b11, NR, 1, "%5.2f", "" ); \ PASTEMAC(ch,fprintm)( stdout, "trsm_lu_ker_var2: ct after (diag)", m_cur, n_cur, ct, rs_ct, cs_ct, "%5.2f", "" ); \ */ \ } INSERT_GENTFUNC_BASIC0( trsm_lu_ker_var2sl ) blis-0.9.0/frame/3/trsm/other/bli_trsm_rl_ker_var2.c000066400000000000000000000467211422157504600223020ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define FUNCPTR_T gemm_fp typedef void (*FUNCPTR_T) ( doff_t diagoffb, pack_t schema_a, pack_t schema_b, dim_t m, dim_t n, dim_t k, void* alpha1, void* a, inc_t cs_a, dim_t pd_a, inc_t ps_a, void* b, inc_t rs_b, dim_t pd_b, inc_t ps_b, void* alpha2, void* c, inc_t rs_c, inc_t cs_c, cntx_t* cntx, rntm_t* rntm, thrinfo_t* thread ); static FUNCPTR_T GENARRAY(ftypes,trsm_rl_ker_var2); void bli_trsm_rl_ker_var2 ( obj_t* a, obj_t* b, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ) { num_t dt_exec = bli_obj_exec_dt( c ); doff_t diagoffb = bli_obj_diag_offset( b ); pack_t schema_a = bli_obj_pack_schema( a ); pack_t schema_b = bli_obj_pack_schema( b ); dim_t m = bli_obj_length( c ); dim_t n = bli_obj_width( c ); dim_t k = bli_obj_width( a ); void* buf_a = bli_obj_buffer_at_off( a ); inc_t cs_a = bli_obj_col_stride( a ); dim_t pd_a = bli_obj_panel_dim( a ); inc_t ps_a = bli_obj_panel_stride( a ); void* buf_b = bli_obj_buffer_at_off( b ); inc_t rs_b = bli_obj_row_stride( b ); dim_t pd_b = bli_obj_panel_dim( b ); inc_t ps_b = bli_obj_panel_stride( b ); void* buf_c = bli_obj_buffer_at_off( c ); inc_t rs_c = bli_obj_row_stride( c ); inc_t cs_c = bli_obj_col_stride( c ); void* buf_alpha1; void* buf_alpha2; FUNCPTR_T f; // Grab the address of the internal scalar buffer for the scalar // attached to A (the non-triangular matrix). This will be the alpha // scalar used in the gemmtrsm subproblems (ie: the scalar that would // be applied to the packed copy of A prior to it being updated by // the trsm subproblem). This scalar may be unit, if for example it // was applied during packing. buf_alpha1 = bli_obj_internal_scalar_buffer( a ); // Grab the address of the internal scalar buffer for the scalar // attached to C. This will be the "beta" scalar used in the gemm-only // subproblems that correspond to micro-panels that do not intersect // the diagonal. We need this separate scalar because it's possible // that the alpha attached to B was reset, if it was applied during // packing. buf_alpha2 = bli_obj_internal_scalar_buffer( c ); // Index into the type combination array to extract the correct // function pointer. f = ftypes[dt_exec]; // Invoke the function. f( diagoffb, schema_a, schema_b, m, n, k, buf_alpha1, buf_a, cs_a, pd_a, ps_a, buf_b, rs_b, pd_b, ps_b, buf_alpha2, buf_c, rs_c, cs_c, cntx, rntm, thread ); } #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ doff_t diagoffb, \ pack_t schema_a, \ pack_t schema_b, \ dim_t m, \ dim_t n, \ dim_t k, \ void* alpha1, \ void* a, inc_t cs_a, dim_t pd_a, inc_t ps_a, \ void* b, inc_t rs_b, dim_t pd_b, inc_t ps_b, \ void* alpha2, \ void* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx, \ rntm_t* rntm, \ thrinfo_t* thread \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ /* Alias some constants to simpler names. */ \ const dim_t MR = pd_a; \ const dim_t NR = pd_b; \ const dim_t PACKMR = cs_a; \ const dim_t PACKNR = rs_b; \ \ /* Cast the micro-kernel address to its function pointer type. */ \ /* NOTE: We use the upper-triangular gemmtrsm ukernel because, while the current macro-kernel targets the "rl" case (right-side/lower- triangular), it becomes upper-triangular after the kernel operation is transposed so that all kernel instances are of the "left" variety (since those are the only trsm ukernels that exist). */ \ PASTECH(ch,gemmtrsm_ukr_ft) \ gemmtrsm_ukr = bli_cntx_get_l3_vir_ukr_dt( dt, BLIS_GEMMTRSM_U_UKR, cntx ); \ PASTECH(ch,gemm_ukr_ft) \ gemm_ukr = bli_cntx_get_l3_vir_ukr_dt( dt, BLIS_GEMM_UKR, cntx ); \ \ /* Temporary C buffer for edge cases. Note that the strides of this temporary buffer are set so that they match the storage of the original C matrix. For example, if C is column-stored, ct will be column-stored as well. */ \ ctype ct[ BLIS_STACK_BUF_MAX_SIZE \ / sizeof( ctype ) ] \ __attribute__((aligned(BLIS_STACK_BUF_ALIGN_SIZE))); \ const bool col_pref = bli_cntx_l3_vir_ukr_prefers_cols_dt( dt, BLIS_GEMM_UKR, cntx ); \ const inc_t rs_ct = ( col_pref ? 1 : NR ); \ const inc_t cs_ct = ( col_pref ? MR : 1 ); \ \ ctype* restrict zero = PASTEMAC(ch,0); \ ctype* restrict minus_one = PASTEMAC(ch,m1); \ ctype* restrict a_cast = a; \ ctype* restrict b_cast = b; \ ctype* restrict c_cast = c; \ ctype* restrict alpha1_cast = alpha1; \ ctype* restrict alpha2_cast = alpha2; \ ctype* restrict b1; \ ctype* restrict c1; \ \ doff_t diagoffb_j; \ dim_t k_full; \ dim_t m_iter, m_left; \ dim_t n_iter, n_left; \ dim_t m_cur; \ dim_t n_cur; \ dim_t k_b1121; \ dim_t k_b11; \ dim_t k_b21; \ dim_t off_b11; \ dim_t off_b21; \ dim_t i, j, jb; \ inc_t rstep_a; \ inc_t cstep_b; \ inc_t rstep_c, cstep_c; \ inc_t istep_a; \ inc_t istep_b; \ inc_t off_scl; \ inc_t ss_b_num; \ inc_t ss_b_den; \ inc_t ps_b_cur; \ inc_t is_b_cur; \ auxinfo_t aux; \ \ /* Assumptions/assertions: rs_a == 1 cs_a == PACKNR pd_a == NR ps_a == stride to next micro-panel of A rs_b == PACKMR cs_b == 1 pd_b == MR ps_b == stride to next micro-panel of B rs_c == (no assumptions) cs_c == (no assumptions) Note that MR/NR and PACKMR/PACKNR have been swapped to reflect the swapping of values in the control tree (ie: those values used when packing). This swapping is needed since we cast right-hand trsm in terms of transposed left-hand trsm. So, if we're going to be transposing the operation, then A needs to be packed with NR and B needs to be packed with MR (remember: B is the triangular matrix in the right-hand side parameter case). */ \ \ /* Safety trap: Certain indexing within this macro-kernel does not work as intended if both MR and NR are odd. */ \ if ( ( bli_is_odd( PACKMR ) && bli_is_odd( NR ) ) || \ ( bli_is_odd( PACKNR ) && bli_is_odd( MR ) ) ) bli_abort(); \ \ /* If any dimension is zero, return immediately. */ \ if ( bli_zero_dim3( m, n, k ) ) return; \ \ /* Safeguard: If the current panel of B is entirely above its diagonal, it is implicitly zero. So we do nothing. */ \ if ( bli_is_strictly_above_diag_n( diagoffb, k, n ) ) return; \ \ /* Compute k_full as k inflated up to a multiple of NR. This is needed because some parameter combinations of trsm reduce k to advance past zero regions in the triangular matrix, and when computing the imaginary stride of B (the non-triangular matrix), which is used by 4m1/3m1 implementations, we need this unreduced value of k. */ \ k_full = ( k % NR != 0 ? k + NR - ( k % NR ) : k ); \ \ /* Compute indexing scaling factor for for 4m or 3m. This is needed because one of the packing register blocksizes (PACKMR or PACKNR) is used to index into the micro-panels of the non- triangular matrix when computing with a diagonal-intersecting micro-panel of the triangular matrix. In the case of 4m or 3m, real values are stored in both sub-panels, and so the indexing needs to occur in units of real values. The value computed here is divided into the complex pointer offset to cause the pointer to be advanced by the correct value. */ \ if ( bli_is_4mi_packed( schema_b ) || \ bli_is_3mi_packed( schema_b ) || \ bli_is_rih_packed( schema_b ) ) off_scl = 2; \ else off_scl = 1; \ \ /* Compute the storage stride scaling. Usually this is just 1. However, in the case of interleaved 3m, we need to scale the offset by 3/2. Note that real-only, imag-only, and summed-only packing formats are not applicable here since trsm is a two- operand operation only (unlike trmm, which is capable of three- operand). */ \ if ( bli_is_3mi_packed( schema_b ) ) { ss_b_num = 3; ss_b_den = 2; } \ else { ss_b_num = 1; ss_b_den = 1; } \ \ /* If there is a zero region above where the diagonal of B intersects the left edge of the panel, adjust the pointer to A and treat this case as if the diagonal offset were zero. Note that we don't need to adjust the pointer to B since packm would have simply skipped over the region that was not stored. */ \ if ( diagoffb < 0 ) \ { \ j = -diagoffb; \ k = k - j; \ diagoffb = 0; \ a_cast = a_cast + ( j * PACKMR ) / off_scl; \ } \ \ /* If there is a zero region to the right of where the diagonal of B intersects the bottom of the panel, shrink it so that we can index to the correct place in C (corresponding to the part of the panel of B that was packed). NOTE: This is NOT being done to skip over "no-op" iterations, as with the trsm_lu macro-kernel. This MUST be done for correct execution because we use n (via n_iter) to compute diagonal and index offsets for backwards movement through B. */ \ if ( diagoffb + k < n ) \ { \ n = diagoffb + k; \ } \ \ /* Check the k dimension, which needs to be a multiple of NR. If k isn't a multiple of NR, we adjust it higher to satisfy the micro- kernel, which is expecting to perform an NR x NR triangular solve. This adjustment of k is consistent with what happened when B was packed: all of its bottom/right edges were zero-padded, and furthermore, the panel that stores the bottom-right corner of the matrix has its diagonal extended into the zero-padded region (as identity). This allows the trsm of that bottom-right panel to proceed without producing any infs or NaNs that would infect the "good" values of the corresponding block of A. */ \ if ( k % NR != 0 ) k += NR - ( k % NR ); \ \ /* NOTE: We don't need to check that n is a multiple of PACKNR since we know that the underlying buffer was already allocated to have an n dimension that is a multiple of PACKNR, with the region between the last column and the next multiple of NR zero-padded accordingly. */ \ \ /* Clear the temporary C buffer in case it has any infs or NaNs. */ \ PASTEMAC(ch,set0s_mxn)( MR, NR, \ ct, rs_ct, cs_ct ); \ \ /* Compute number of primary and leftover components of the m and n dimensions. */ \ n_iter = n / NR; \ n_left = n % NR; \ \ m_iter = m / MR; \ m_left = m % MR; \ \ if ( n_left ) ++n_iter; \ if ( m_left ) ++m_iter; \ \ /* Determine some increments used to step through A, B, and C. */ \ rstep_a = ps_a; \ \ cstep_b = ps_b; \ \ rstep_c = rs_c * MR; \ cstep_c = cs_c * NR; \ \ istep_a = PACKMR * k_full; \ istep_b = PACKNR * k; \ \ if ( bli_is_odd( istep_a ) ) istep_a += 1; \ if ( bli_is_odd( istep_b ) ) istep_b += 1; \ \ /* Save the pack schemas of A and B to the auxinfo_t object. NOTE: We swap the values for A and B since the triangular "A" matrix is actually contained within B. */ \ bli_auxinfo_set_schema_a( schema_b, &aux ); \ bli_auxinfo_set_schema_b( schema_a, &aux ); \ \ /* Save the imaginary stride of A to the auxinfo_t object. NOTE: We swap the values for A and B since the triangular "A" matrix is actually contained within B. */ \ bli_auxinfo_set_is_b( istep_a, &aux ); \ \ b1 = b_cast; \ c1 = c_cast; \ \ /* Loop over the n dimension (NR columns at a time). */ \ for ( jb = 0; jb < n_iter; ++jb ) \ { \ ctype* restrict a1; \ ctype* restrict c11; \ ctype* restrict b11; \ ctype* restrict b21; \ ctype* restrict b2; \ \ j = n_iter - 1 - jb; \ diagoffb_j = diagoffb - ( doff_t )j*NR; \ a1 = a_cast; \ c11 = c1 + (n_iter-1)*cstep_c; \ \ n_cur = ( bli_is_not_edge_b( jb, n_iter, n_left ) ? NR : n_left ); \ \ /* Initialize our next panel of B to be the current panel of B. */ \ b2 = b1; \ \ /* If the current panel of B intersects the diagonal, use a special micro-kernel that performs a fused gemm and trsm. If the current panel of B resides below the diagonal, use a a regular gemm micro-kernel. Otherwise, if it is above the diagonal, it was not packed (because it is implicitly zero) and so we do nothing. */ \ if ( bli_intersects_diag_n( diagoffb_j, k, NR ) ) \ { \ /* Determine the offset to and length of the panel that was packed so we can index into the corresponding location in A. */ \ off_b11 = bli_max( -diagoffb_j, 0 ); \ k_b1121 = k - off_b11; \ k_b11 = NR; \ k_b21 = k_b1121 - NR; \ off_b21 = off_b11 + k_b11; \ \ /* Compute the addresses of the triangular block B11 and the panel B21. */ \ b11 = b1; \ /* b21 = b1 + ( k_b11 * PACKNR ) / off_scl; */ \ b21 = bli_ptr_inc_by_frac( b1, sizeof( ctype ), k_b11 * PACKNR, off_scl ); \ \ /* Compute the panel stride for the current micro-panel. */ \ is_b_cur = k_b1121 * PACKNR; \ is_b_cur += ( bli_is_odd( is_b_cur ) ? 1 : 0 ); \ ps_b_cur = ( is_b_cur * ss_b_num ) / ss_b_den; \ \ /* Save the 4m1/3m1 imaginary stride of B to the auxinfo_t object. NOTE: We swap the values for A and B since the triangular "A" matrix is actually contained within B. */ \ bli_auxinfo_set_is_a( is_b_cur, &aux ); \ \ /* Loop over the m dimension (MR rows at a time). */ \ for ( i = 0; i < m_iter; ++i ) \ { \ if( bli_trsm_my_iter( i, thread ) ){ \ \ ctype* restrict a11; \ ctype* restrict a12; \ ctype* restrict a2; \ \ m_cur = ( bli_is_not_edge_f( i, m_iter, m_left ) ? MR : m_left ); \ \ /* Compute the addresses of the A11 block and A12 panel. */ \ a11 = a1 + ( off_b11 * PACKMR ) / off_scl; \ a12 = a1 + ( off_b21 * PACKMR ) / off_scl; \ \ /* Compute the addresses of the next panels of A and B. */ \ a2 = a1; \ /*if ( bli_is_last_iter( i, m_iter, 0, 1 ) ) */\ if ( i + bli_thread_num_threads(thread) >= m_iter ) \ { \ a2 = a_cast; \ b2 = b1 + ps_b_cur; \ if ( bli_is_last_iter( jb, n_iter, 0, 1 ) ) \ b2 = b_cast; \ } \ \ /* Save addresses of next panels of A and B to the auxinfo_t object. NOTE: We swap the values for A and B since the triangular "A" matrix is actually contained within B. */ \ bli_auxinfo_set_next_a( b2, &aux ); \ bli_auxinfo_set_next_b( a2, &aux ); \ \ /* Handle interior and edge cases separately. */ \ if ( m_cur == MR && n_cur == NR ) \ { \ /* Invoke the fused gemm/trsm micro-kernel. */ \ gemmtrsm_ukr \ ( \ k_b21, \ alpha1_cast, \ b21, \ b11, \ a12, \ a11, \ c11, cs_c, rs_c, \ &aux, \ cntx \ ); \ } \ else \ { \ /* Invoke the fused gemm/trsm micro-kernel. */ \ gemmtrsm_ukr \ ( \ k_b21, \ alpha1_cast, \ b21, \ b11, \ a12, \ a11, \ ct, cs_ct, rs_ct, \ &aux, \ cntx \ ); \ \ /* Copy the result to the bottom edge of C. */ \ PASTEMAC(ch,copys_mxn)( m_cur, n_cur, \ ct, rs_ct, cs_ct, \ c11, rs_c, cs_c ); \ } \ } \ \ a1 += rstep_a; \ c11 += rstep_c; \ } \ \ b1 += ps_b_cur; \ } \ else if ( bli_is_strictly_below_diag_n( diagoffb_j, k, NR ) ) \ { \ /* Save the 4m1/3m1 imaginary stride of B to the auxinfo_t object. NOTE: We swap the values for A and B since the triangular "A" matrix is actually contained within B. */ \ bli_auxinfo_set_is_a( istep_b, &aux ); \ \ /* Loop over the m dimension (MR rows at a time). */ \ for ( i = 0; i < m_iter; ++i ) \ { \ if( bli_trsm_my_iter( i, thread ) ){ \ \ ctype* restrict a2; \ \ m_cur = ( bli_is_not_edge_f( i, m_iter, m_left ) ? MR : m_left ); \ \ /* Compute the addresses of the next panels of A and B. */ \ a2 = a1; \ /*if ( bli_is_last_iter( i, m_iter, 0, 1 ) ) */\ if ( i + bli_thread_num_threads(thread) >= m_iter ) \ { \ a2 = a_cast; \ b2 = b1 + cstep_b; \ if ( bli_is_last_iter( jb, n_iter, 0, 1 ) ) \ b2 = b_cast; \ } \ \ /* Save addresses of next panels of A and B to the auxinfo_t object. NOTE: We swap the values for A and B since the triangular "A" matrix is actually contained within B. */ \ bli_auxinfo_set_next_a( b2, &aux ); \ bli_auxinfo_set_next_b( a2, &aux ); \ \ /* Handle interior and edge cases separately. */ \ if ( m_cur == MR && n_cur == NR ) \ { \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k, \ minus_one, \ b1, \ a1, \ alpha2_cast, \ c11, cs_c, rs_c, \ &aux, \ cntx \ ); \ } \ else \ { \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k, \ minus_one, \ b1, \ a1, \ zero, \ ct, cs_ct, rs_ct, \ &aux, \ cntx \ ); \ \ /* Add the result to the edge of C. */ \ PASTEMAC(ch,xpbys_mxn)( m_cur, n_cur, \ ct, rs_ct, cs_ct, \ alpha2_cast, \ c11, rs_c, cs_c ); \ } \ } \ \ a1 += rstep_a; \ c11 += rstep_c; \ } \ \ b1 += cstep_b; \ } \ \ c1 -= cstep_c; \ } \ } INSERT_GENTFUNC_BASIC0( trsm_rl_ker_var2 ) blis-0.9.0/frame/3/trsm/other/bli_trsm_ru_ker_var2.c000066400000000000000000000461211422157504600223050ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define FUNCPTR_T gemm_fp typedef void (*FUNCPTR_T) ( doff_t diagoffb, pack_t schema_a, pack_t schema_b, dim_t m, dim_t n, dim_t k, void* alpha1, void* a, inc_t cs_a, dim_t pd_a, inc_t ps_a, void* b, inc_t rs_b, dim_t pd_b, inc_t ps_b, void* alpha2, void* c, inc_t rs_c, inc_t cs_c, cntx_t* cntx, rntm_t* rntm, thrinfo_t* thread ); static FUNCPTR_T GENARRAY(ftypes,trsm_ru_ker_var2); void bli_trsm_ru_ker_var2 ( obj_t* a, obj_t* b, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ) { num_t dt_exec = bli_obj_exec_dt( c ); doff_t diagoffb = bli_obj_diag_offset( b ); pack_t schema_a = bli_obj_pack_schema( a ); pack_t schema_b = bli_obj_pack_schema( b ); dim_t m = bli_obj_length( c ); dim_t n = bli_obj_width( c ); dim_t k = bli_obj_width( a ); void* buf_a = bli_obj_buffer_at_off( a ); inc_t cs_a = bli_obj_col_stride( a ); dim_t pd_a = bli_obj_panel_dim( a ); inc_t ps_a = bli_obj_panel_stride( a ); void* buf_b = bli_obj_buffer_at_off( b ); inc_t rs_b = bli_obj_row_stride( b ); dim_t pd_b = bli_obj_panel_dim( b ); inc_t ps_b = bli_obj_panel_stride( b ); void* buf_c = bli_obj_buffer_at_off( c ); inc_t rs_c = bli_obj_row_stride( c ); inc_t cs_c = bli_obj_col_stride( c ); void* buf_alpha1; void* buf_alpha2; FUNCPTR_T f; // Grab the address of the internal scalar buffer for the scalar // attached to A (the non-triangular matrix). This will be the alpha // scalar used in the gemmtrsm subproblems (ie: the scalar that would // be applied to the packed copy of A prior to it being updated by // the trsm subproblem). This scalar may be unit, if for example it // was applied during packing. buf_alpha1 = bli_obj_internal_scalar_buffer( a ); // Grab the address of the internal scalar buffer for the scalar // attached to C. This will be the "beta" scalar used in the gemm-only // subproblems that correspond to micro-panels that do not intersect // the diagonal. We need this separate scalar because it's possible // that the alpha attached to B was reset, if it was applied during // packing. buf_alpha2 = bli_obj_internal_scalar_buffer( c ); // Index into the type combination array to extract the correct // function pointer. f = ftypes[dt_exec]; // Invoke the function. f( diagoffb, schema_a, schema_b, m, n, k, buf_alpha1, buf_a, cs_a, pd_a, ps_a, buf_b, rs_b, pd_b, ps_b, buf_alpha2, buf_c, rs_c, cs_c, cntx, rntm, thread ); } #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ doff_t diagoffb, \ pack_t schema_a, \ pack_t schema_b, \ dim_t m, \ dim_t n, \ dim_t k, \ void* alpha1, \ void* a, inc_t cs_a, dim_t pd_a, inc_t ps_a, \ void* b, inc_t rs_b, dim_t pd_b, inc_t ps_b, \ void* alpha2, \ void* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx, \ rntm_t* rntm, \ thrinfo_t* thread \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ /* Alias some constants to simpler names. */ \ const dim_t MR = pd_a; \ const dim_t NR = pd_b; \ const dim_t PACKMR = cs_a; \ const dim_t PACKNR = rs_b; \ \ /* Cast the micro-kernel address to its function pointer type. */ \ /* NOTE: We use the lower-triangular gemmtrsm ukernel because, while the current macro-kernel targets the "ru" case (right-side/upper- triangular), it becomes lower-triangular after the kernel operation is transposed so that all kernel instances are of the "left" variety (since those are the only trsm ukernels that exist). */ \ PASTECH(ch,gemmtrsm_ukr_ft) \ gemmtrsm_ukr = bli_cntx_get_l3_vir_ukr_dt( dt, BLIS_GEMMTRSM_L_UKR, cntx ); \ PASTECH(ch,gemm_ukr_ft) \ gemm_ukr = bli_cntx_get_l3_vir_ukr_dt( dt, BLIS_GEMM_UKR, cntx ); \ \ /* Temporary C buffer for edge cases. Note that the strides of this temporary buffer are set so that they match the storage of the original C matrix. For example, if C is column-stored, ct will be column-stored as well. */ \ ctype ct[ BLIS_STACK_BUF_MAX_SIZE \ / sizeof( ctype ) ] \ __attribute__((aligned(BLIS_STACK_BUF_ALIGN_SIZE))); \ const bool col_pref = bli_cntx_l3_vir_ukr_prefers_cols_dt( dt, BLIS_GEMM_UKR, cntx ); \ const inc_t rs_ct = ( col_pref ? 1 : NR ); \ const inc_t cs_ct = ( col_pref ? MR : 1 ); \ \ ctype* restrict zero = PASTEMAC(ch,0); \ ctype* restrict minus_one = PASTEMAC(ch,m1); \ ctype* restrict a_cast = a; \ ctype* restrict b_cast = b; \ ctype* restrict c_cast = c; \ ctype* restrict alpha1_cast = alpha1; \ ctype* restrict alpha2_cast = alpha2; \ ctype* restrict b1; \ ctype* restrict c1; \ \ doff_t diagoffb_j; \ dim_t k_full; \ dim_t m_iter, m_left; \ dim_t n_iter, n_left; \ dim_t m_cur; \ dim_t n_cur; \ dim_t k_b0111; \ dim_t k_b01; \ dim_t off_b01; \ dim_t off_b11; \ dim_t i, j; \ inc_t rstep_a; \ inc_t cstep_b; \ inc_t rstep_c, cstep_c; \ inc_t istep_a; \ inc_t istep_b; \ inc_t off_scl; \ inc_t ss_b_num; \ inc_t ss_b_den; \ inc_t ps_b_cur; \ inc_t is_b_cur; \ auxinfo_t aux; \ \ /* Assumptions/assertions: rs_a == 1 cs_a == PACKNR pd_a == NR ps_a == stride to next micro-panel of A rs_b == PACKMR cs_b == 1 pd_b == MR ps_b == stride to next micro-panel of B rs_c == (no assumptions) cs_c == (no assumptions) Note that MR/NR and PACKMR/PACKNR have been swapped to reflect the swapping of values in the control tree (ie: those values used when packing). This swapping is needed since we cast right-hand trsm in terms of transposed left-hand trsm. So, if we're going to be transposing the operation, then A needs to be packed with NR and B needs to be packed with MR (remember: B is the triangular matrix in the right-hand side parameter case). */ \ \ /* Safety trap: Certain indexing within this macro-kernel does not work as intended if both MR and NR are odd. */ \ if ( ( bli_is_odd( PACKMR ) && bli_is_odd( NR ) ) || \ ( bli_is_odd( PACKNR ) && bli_is_odd( MR ) ) ) bli_abort(); \ \ /* If any dimension is zero, return immediately. */ \ if ( bli_zero_dim3( m, n, k ) ) return; \ \ /* Safeguard: If the current panel of B is entirely below its diagonal, it is implicitly zero. So we do nothing. */ \ if ( bli_is_strictly_below_diag_n( diagoffb, k, n ) ) return; \ \ /* Compute k_full as k inflated up to a multiple of NR. This is needed because some parameter combinations of trsm reduce k to advance past zero regions in the triangular matrix, and when computing the imaginary stride of B (the non-triangular matrix), which is used by 4m1/3m1 implementations, we need this unreduced value of k. */ \ k_full = ( k % NR != 0 ? k + NR - ( k % NR ) : k ); \ \ /* Compute indexing scaling factor for for 4m or 3m. This is needed because one of the packing register blocksizes (PACKMR or PACKNR) is used to index into the micro-panels of the non- triangular matrix when computing with a diagonal-intersecting micro-panel of the triangular matrix. In the case of 4m or 3m, real values are stored in both sub-panels, and so the indexing needs to occur in units of real values. The value computed here is divided into the complex pointer offset to cause the pointer to be advanced by the correct value. */ \ if ( bli_is_4mi_packed( schema_b ) || \ bli_is_3mi_packed( schema_b ) || \ bli_is_rih_packed( schema_b ) ) off_scl = 2; \ else off_scl = 1; \ \ /* Compute the storage stride scaling. Usually this is just 1. However, in the case of interleaved 3m, we need to scale the offset by 3/2. Note that real-only, imag-only, and summed-only packing formats are not applicable here since trsm is a two- operand operation only (unlike trmm, which is capable of three- operand). */ \ if ( bli_is_3mi_packed( schema_b ) ) { ss_b_num = 3; ss_b_den = 2; } \ else { ss_b_num = 1; ss_b_den = 1; } \ \ /* If there is a zero region to the left of where the diagonal of B intersects the top edge of the panel, adjust the pointer to C and treat this case as if the diagonal offset were zero. This skips over the region that was not packed. (Note we assume the diagonal offset is a multiple of MR; this assumption will hold as long as the cache blocksizes are each a multiple of MR and NR.) */ \ if ( diagoffb > 0 ) \ { \ j = diagoffb; \ n = n - j; \ diagoffb = 0; \ c_cast = c_cast + (j )*cs_c; \ } \ \ /* If there is a zero region below where the diagonal of B intersects the right side of the block, shrink it to prevent "no-op" iterations from executing. */ \ if ( -diagoffb + n < k ) \ { \ k = -diagoffb + n; \ } \ \ /* Check the k dimension, which needs to be a multiple of NR. If k isn't a multiple of NR, we adjust it higher to satisfy the micro- kernel, which is expecting to perform an NR x NR triangular solve. This adjustment of k is consistent with what happened when B was packed: all of its bottom/right edges were zero-padded, and furthermore, the panel that stores the bottom-right corner of the matrix has its diagonal extended into the zero-padded region (as identity). This allows the trsm of that bottom-right panel to proceed without producing any infs or NaNs that would infect the "good" values of the corresponding block of A. */ \ if ( k % NR != 0 ) k += NR - ( k % NR ); \ \ /* NOTE: We don't need to check that n is a multiple of PACKNR since we know that the underlying buffer was already allocated to have an n dimension that is a multiple of PACKNR, with the region between the last column and the next multiple of NR zero-padded accordingly. */ \ \ /* Clear the temporary C buffer in case it has any infs or NaNs. */ \ PASTEMAC(ch,set0s_mxn)( MR, NR, \ ct, rs_ct, cs_ct ); \ \ /* Compute number of primary and leftover components of the m and n dimensions. */ \ n_iter = n / NR; \ n_left = n % NR; \ \ m_iter = m / MR; \ m_left = m % MR; \ \ if ( n_left ) ++n_iter; \ if ( m_left ) ++m_iter; \ \ /* Determine some increments used to step through A, B, and C. */ \ rstep_a = ps_a; \ \ cstep_b = ps_b; \ \ rstep_c = rs_c * MR; \ cstep_c = cs_c * NR; \ \ istep_a = PACKMR * k_full; \ istep_b = PACKNR * k; \ \ if ( bli_is_odd( istep_a ) ) istep_a += 1; \ if ( bli_is_odd( istep_b ) ) istep_b += 1; \ \ /* Save the pack schemas of A and B to the auxinfo_t object. NOTE: We swap the values for A and B since the triangular "A" matrix is actually contained within B. */ \ bli_auxinfo_set_schema_a( schema_b, &aux ); \ bli_auxinfo_set_schema_b( schema_a, &aux ); \ \ /* Save the imaginary stride of A to the auxinfo_t object. NOTE: We swap the values for A and B since the triangular "A" matrix is actually contained within B. */ \ bli_auxinfo_set_is_b( istep_a, &aux ); \ \ b1 = b_cast; \ c1 = c_cast; \ \ /* Loop over the n dimension (NR columns at a time). */ \ for ( j = 0; j < n_iter; ++j ) \ { \ ctype* restrict a1; \ ctype* restrict c11; \ ctype* restrict b01; \ ctype* restrict b11; \ ctype* restrict b2; \ \ diagoffb_j = diagoffb - ( doff_t )j*NR; \ a1 = a_cast; \ c11 = c1; \ \ n_cur = ( bli_is_not_edge_f( j, n_iter, n_left ) ? NR : n_left ); \ \ /* Initialize our next panel of B to be the current panel of B. */ \ b2 = b1; \ \ /* If the current panel of B intersects the diagonal, use a special micro-kernel that performs a fused gemm and trsm. If the current panel of B resides above the diagonal, use a a regular gemm micro-kernel. Otherwise, if it is below the diagonal, it was not packed (because it is implicitly zero) and so we do nothing. */ \ if ( bli_intersects_diag_n( diagoffb_j, k, NR ) ) \ { \ /* Determine the offset to and length of the panel that was packed so we can index into the corresponding location in A. */ \ off_b01 = 0; \ k_b0111 = bli_min( k, -diagoffb_j + NR ); \ k_b01 = k_b0111 - NR; \ off_b11 = k_b01; \ \ /* Compute the addresses of the panel B10 and the triangular block B11. */ \ b01 = b1; \ /* b11 = b1 + ( k_b01 * PACKNR ) / off_scl; */ \ b11 = bli_ptr_inc_by_frac( b1, sizeof( ctype ), k_b01 * PACKNR, off_scl ); \ \ /* Compute the panel stride for the current micro-panel. */ \ is_b_cur = k_b0111 * PACKNR; \ is_b_cur += ( bli_is_odd( is_b_cur ) ? 1 : 0 ); \ ps_b_cur = ( is_b_cur * ss_b_num ) / ss_b_den; \ \ /* Save the 4m1/3m1 imaginary stride of B to the auxinfo_t object. NOTE: We swap the values for A and B since the triangular "A" matrix is actually contained within B. */ \ bli_auxinfo_set_is_a( is_b_cur, &aux ); \ \ /* Loop over the m dimension (MR rows at a time). */ \ for ( i = 0; i < m_iter; ++i ) \ { \ if( bli_trsm_my_iter( i, thread ) ){ \ \ ctype* restrict a10; \ ctype* restrict a11; \ ctype* restrict a2; \ \ m_cur = ( bli_is_not_edge_f( i, m_iter, m_left ) ? MR : m_left ); \ \ /* Compute the addresses of the A10 panel and A11 block. */ \ a10 = a1 + ( off_b01 * PACKMR ) / off_scl; \ a11 = a1 + ( off_b11 * PACKMR ) / off_scl; \ \ /* Compute the addresses of the next panels of A and B. */ \ a2 = a1; \ /*if ( bli_is_last_iter( i, m_iter, 0, 1 ) ) */\ if ( i + bli_thread_num_threads(thread) >= m_iter ) \ { \ a2 = a_cast; \ b2 = b1 + ps_b_cur; \ if ( bli_is_last_iter( j, n_iter, 0, 1 ) ) \ b2 = b_cast; \ } \ \ /* Save addresses of next panels of A and B to the auxinfo_t object. NOTE: We swap the values for A and B since the triangular "A" matrix is actually contained within B. */ \ bli_auxinfo_set_next_a( b2, &aux ); \ bli_auxinfo_set_next_b( a2, &aux ); \ \ /* Handle interior and edge cases separately. */ \ if ( m_cur == MR && n_cur == NR ) \ { \ /* Invoke the fused gemm/trsm micro-kernel. */ \ gemmtrsm_ukr \ ( \ k_b01, \ alpha1_cast, \ b01, \ b11, \ a10, \ a11, \ c11, cs_c, rs_c, \ &aux, \ cntx \ ); \ } \ else \ { \ /* Invoke the fused gemm/trsm micro-kernel. */ \ gemmtrsm_ukr \ ( \ k_b01, \ alpha1_cast, \ b01, \ b11, \ a10, \ a11, \ ct, cs_ct, rs_ct, \ &aux, \ cntx \ ); \ \ /* Copy the result to the bottom edge of C. */ \ PASTEMAC(ch,copys_mxn)( m_cur, n_cur, \ ct, rs_ct, cs_ct, \ c11, rs_c, cs_c ); \ } \ } \ \ a1 += rstep_a; \ c11 += rstep_c; \ } \ \ b1 += ps_b_cur; \ } \ else if ( bli_is_strictly_above_diag_n( diagoffb_j, k, NR ) ) \ { \ /* Save the 4m1/3m1 imaginary stride of B to the auxinfo_t object. NOTE: We swap the values for A and B since the triangular "A" matrix is actually contained within B. */ \ bli_auxinfo_set_is_a( istep_b, &aux ); \ \ /* Loop over the m dimension (MR rows at a time). */ \ for ( i = 0; i < m_iter; ++i ) \ { \ if( bli_trsm_my_iter( i, thread ) ){ \ \ ctype* restrict a2; \ \ m_cur = ( bli_is_not_edge_f( i, m_iter, m_left ) ? MR : m_left ); \ \ /* Compute the addresses of the next panels of A and B. */ \ a2 = a1; \ /*if ( bli_is_last_iter( i, m_iter, 0, 1 ) ) */\ if ( i + bli_thread_num_threads(thread) >= m_iter ) \ { \ a2 = a_cast; \ b2 = b1 + cstep_b; \ if ( bli_is_last_iter( j, n_iter, 0, 1 ) ) \ b2 = b_cast; \ } \ \ /* Save addresses of next panels of A and B to the auxinfo_t object. NOTE: We swap the values for A and B since the triangular "A" matrix is actually contained within B. */ \ bli_auxinfo_set_next_a( b2, &aux ); \ bli_auxinfo_set_next_b( a2, &aux ); \ \ /* Handle interior and edge cases separately. */ \ if ( m_cur == MR && n_cur == NR ) \ { \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k, \ minus_one, \ b1, \ a1, \ alpha2_cast, \ c11, cs_c, rs_c, \ &aux, \ cntx \ ); \ } \ else \ { \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k, \ minus_one, \ b1, \ a1, \ zero, \ ct, cs_ct, rs_ct, \ &aux, \ cntx \ ); \ \ /* Add the result to the edge of C. */ \ PASTEMAC(ch,xpbys_mxn)( m_cur, n_cur, \ ct, rs_ct, cs_ct, \ alpha2_cast, \ c11, rs_c, cs_c ); \ } \ } \ \ a1 += rstep_a; \ c11 += rstep_c; \ } \ \ b1 += cstep_b; \ } \ \ c1 += cstep_c; \ } \ } INSERT_GENTFUNC_BASIC0( trsm_ru_ker_var2 ) blis-0.9.0/frame/base/000077500000000000000000000000001422157504600144635ustar00rootroot00000000000000blis-0.9.0/frame/base/bli_apool.c000066400000000000000000000436421422157504600166000ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_apool_init ( apool_t* restrict apool ) { err_t r_val; // NOTE: The apool_t is only used in one place; it is the type used to // define the sba. We've switched to static initialization of the mutex // field to remove one more thing that could possibly go wrong during // library initialization. // Query the mutex from the apool_t. //bli_pthread_mutex_t* restrict mutex = bli_apool_mutex( apool ); // Initialize the mutex. //*mutex = BLIS_PTHREAD_MUTEX_INITIALIZER; //bli_pthread_mutex_init( mutex, NULL ); // We choose to start with: // - an empty pool // - an initial block_ptrs_len of 8 // - a single element in each initial array_t (though this is moot with // num_blocks = 0). const siz_t num_blocks = 0; siz_t block_ptrs_len = 8; const siz_t num_elem = 1; // NOTE: Unlike in the bli_pool API, apool_t allocates block_ptrs as an // array of array_t* instead of an array of pblk_t. Why? We don't need to // track the size of each block, thus we don't need the block_size field // of pblk_t. That leaves only the void* field, and since we know apool_t // will always contain "blocks" that are really array_t structs, we can // make block_ptrs an array of array_t*. // We formally set the block_size and align_size fields of the underlying // pool, even though they won't be queried. (They are used from hard-coded // values in bli_apool_alloc_block().) const siz_t block_size = sizeof( array_t ); const siz_t align_size = 64; // Query the underlying pool_t from the apool_t. pool_t* restrict pool = bli_apool_pool( apool ); // Set the default array_t length of the apool_t. bli_apool_set_def_array_len( num_elem, apool ); // ------------------------------------------------------------------------- // Make sure that block_ptrs_len is at least num_blocks. block_ptrs_len = bli_max( block_ptrs_len, num_blocks ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_apool_init(): allocating block_ptrs (length %d): ", ( int )block_ptrs_len ); #endif // Allocate the block_ptrs array. array_t** restrict block_ptrs = bli_malloc_intl( block_ptrs_len * sizeof( array_t* ), &r_val ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_apool_init(): allocating %d array_t.\n", ( int )num_blocks ); fflush( stdout ); #endif // Allocate and initialize each entry in the block_ptrs array. for ( dim_t i = 0; i < num_blocks; ++i ) { // Pass in num_elem so the function knows how many elements to // initially have in each array_t. bli_apool_alloc_block ( num_elem, &(block_ptrs[i]) ); } // NOTE: The semantics of top_index approximate a stack, where a "full" // stack (no blocks checked out) is one where top_index == 0 and an empty // stack (all blocks checked out) one where top_index == num_blocks. // (Here, num_blocks tracks the number of blocks currently allocated as // part of the pool.) This "orientation" of the stack was chosen // intentionally, in contrast to one where top_index == -1 means the // stack is empty and top_index = num_blocks - 1 means the stack is // full. The chosen scheme allows one to conceptualize the stack as a // number line in which blocks are checked out from lowest to highest, // and additional blocks are added at the higher end. // Initialize the pool_t structure. // NOTE: We don't use the malloc_fp and free_fp fields at the apool_t // level. Nevertheless, we set them to NULL. bli_pool_set_block_ptrs( block_ptrs, pool ); bli_pool_set_block_ptrs_len( block_ptrs_len, pool ); bli_pool_set_top_index( 0, pool ); bli_pool_set_num_blocks( num_blocks, pool ); bli_pool_set_block_size( block_size, pool ); bli_pool_set_align_size( align_size, pool ); bli_pool_set_malloc_fp( NULL, pool ); bli_pool_set_free_fp( NULL, pool ); } void bli_apool_alloc_block ( siz_t num_elem, array_t** restrict array_p ) { err_t r_val; // Since the apool_t is defined as a pool of array_t, we can hard-code // the block_size parameter. const siz_t block_size = sizeof( array_t ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_apool_alloc_block(): allocating array_t: " ); #endif // Allocate the array_t via the bli_fmalloc_align() wrapper, which performs // alignment logic and opaquely saves the original pointer so that it can // be recovered when it's time to free the block. array_t* restrict array = bli_malloc_intl( block_size, &r_val ); // Initialize an array_t struct within the newly allocated memory region. bli_array_init( num_elem, sizeof( pool_t* ), array ); // Save the pointer in the caller's array_t*. *array_p = array; } void bli_apool_free_block ( array_t* restrict array ) { const siz_t num_elem = bli_array_num_elem( array ); pool_t** restrict buf = bli_array_buf( array ); // Step through the array and finalize each pool_t. for ( dim_t i = 0; i < num_elem; ++i ) { pool_t* restrict pool = buf[ i ]; #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_apool_free_block(): freeing pool_t %d within array_t.\n", ( int )i ); fflush( stdout ); #endif // Finalize and free the current pool_t, if it was created/allocated. if ( pool != NULL ) { // Finalize the pool. bli_pool_finalize( pool ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_apool_free_block(): pool_t %d: ", ( int )i ); #endif // Free the pool_t struct. bli_free_intl( pool ); } } #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_apool_free_block(): " ); #endif // Free the array buffer. bli_array_finalize( array ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_apool_free_block(): freeing array_t: " ); #endif // Free the array. bli_free_intl( array ); } void bli_apool_finalize ( apool_t* restrict apool ) { // NOTE: Since the apool_t's mutex is now initialized statically, we no // longer need to explicitly destroy it. // Query the mutex from the apool_t. //bli_pthread_mutex_t* restrict mutex = bli_apool_mutex( apool ); // Destroy the mutex. //bli_pthread_mutex_destroy( mutex ); // Query the underlying pool_t and mutex from the apool_t. pool_t* restrict pool = bli_apool_pool( apool ); // ---------------------------------------------------------------- // Query the block_ptrs array. array_t** restrict block_ptrs = bli_pool_block_ptrs( pool ); // Query the total number of blocks currently allocated. siz_t num_blocks = bli_pool_num_blocks( pool ); // Query the top_index of the pool. siz_t top_index = bli_pool_top_index( pool ); // Sanity check: The top_index should be zero. if ( top_index != 0 ) bli_abort(); // Free the individual blocks (each an array_t) currently in the pool. for ( dim_t i = 0; i < num_blocks; ++i ) { #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_apool_finalize(): freeing array_t %d within apool_t.\n", ( int )i ); fflush( stdout ); #endif bli_apool_free_block( block_ptrs[i] ); } #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_apool_finalize(): freeing block_ptrs (length %d): ", ( int )( bli_pool_block_ptrs_len( pool ) ) ); #endif // Free the block_ptrs array. bli_free_intl( block_ptrs ); } array_t* bli_apool_checkout_array ( siz_t n_threads, apool_t* restrict apool ) { // Acquire the apool_t's mutex. bli_apool_lock( apool ); // ---------------------------------------------------------------------------- // NOTE: Unlike with the bli_pool API, we do not need to handle potential // reinitialization since the apool_t's block_size (corresponding to the // size of an array_t struct) will never grow. // If the apool_t is exhausted, add a block (e.g. an array_t). if ( bli_apool_is_exhausted( apool ) ) { #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_apool_checkout_block(): apool_t is exhausted; " "growing by 1 array_t.\n" ); fflush( stdout ); #endif bli_apool_grow( 1, apool ); } // At this point, at least one array_t is guaranteed to be available. // Query the underlying pool_t from the apool_t. pool_t* restrict pool = bli_apool_pool( apool ); // Query the block_ptrs array. array_t** restrict block_ptrs = bli_pool_block_ptrs( pool ); // Query the top_index of the pool. const siz_t top_index = bli_pool_top_index( pool ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_apool_checkout_array(): checking out array_t %d.\n", ( int )top_index ); fflush( stdout ); #endif // Select the array_t* at top_index to return to the caller. array_t* restrict array = block_ptrs[ top_index ]; // Increment the pool's top_index. bli_pool_set_top_index( top_index + 1, pool ); // ---------------------------------------------------------------------------- // Release the apool_t's mutex. bli_apool_unlock( apool ); // Resize the array_t according to the number of threads specified by the // caller. (We need one element in the array_t per thread.) bli_array_resize( n_threads, array ); // Return the selected array_t*. return array; } void bli_apool_checkin_array ( array_t* restrict array, apool_t* restrict apool ) { // Acquire the apool_t's mutex. bli_apool_lock( apool ); // Query the underlying pool_t from the apool_t. pool_t* restrict pool = bli_apool_pool( apool ); // ---------------------------------------------------------------------------- // NOTE: Unlike with the bli_pool API, we do not need to handle potential // freeing of the blocks upon checkin due to the block_size having since // changed due to reinitialization since the apool's block_size will never // change. // Query the block_ptrs array. array_t** restrict block_ptrs = bli_pool_block_ptrs( pool ); // Query the top_index of the pool. const siz_t top_index = bli_pool_top_index( pool ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_apool_checkin_block(): checking in array_t %d.\n", ( int )top_index - 1 ); fflush( stdout ); #endif // Copy the caller's array_t address to the element at top_index - 1. block_ptrs[ top_index - 1 ] = array; // Decrement the pool's top_index. bli_pool_set_top_index( top_index - 1, pool ); // ---------------------------------------------------------------------------- // Release the apool_t's mutex. bli_apool_unlock( apool ); } pool_t* bli_apool_array_elem ( siz_t index, array_t* restrict array ) { err_t r_val; // Query the array element corresponding to index. // NOTE: If we knew that the array_t contained elements of size // sizeof( void* ) or sizeof( whatever ), we could return the *value* // stored in the array. But since array_t is general-purpose, it can't // return the element itself. So instead, bli_array_elem() returns the // address of the element in the array. Since the elements that apool_t // stores in the array_t are pool_t*, that means that the function is // actually returning the address of a pool_t*, or pool_t**, hence the // dereferencing below. pool_t** restrict pool_p = bli_array_elem( index, array ); pool_t* pool = *pool_p; // If the element is NULL, then it means a pool_t has not yet been created // and allocated for the given index (thread id). if ( pool == NULL ) { // Settle on the parameters to use when initializing the pool_t for // the current index within the array_t. const siz_t num_blocks = 1; const siz_t block_ptrs_len = 25; const siz_t align_size = 16; const siz_t offset_size = 0; malloc_ft malloc_fp = BLIS_MALLOC_POOL; free_ft free_fp = BLIS_FREE_POOL; // Each small block pool should contain blocks large enough to // accommodate any of the data structures for which they will be // used. const siz_t n_sizes = 4; siz_t sizes[4] = { sizeof( cntl_t ), sizeof( packm_params_t ), sizeof( thrcomm_t ), sizeof( thrinfo_t ) }; siz_t block_size = 0; // Find the largest of the sizes above and use that as the block_size // for the pool. for ( dim_t i = 0; i < n_sizes; ++i ) { if ( block_size < sizes[i] ) block_size = sizes[i]; } #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_apool_array_elem(): pool_t for tid %d is NULL; allocating pool_t.\n", ( int )index ); printf( "bli_apool_array_elem(): allocating pool_t: " ); #endif // Allocate the pool_t. pool = bli_malloc_intl( sizeof( pool_t ), &r_val ); // Initialize the pool_t. bli_pool_init ( num_blocks, block_ptrs_len, block_size, align_size, offset_size, malloc_fp, free_fp, pool ); // Update the array element with the address to the new pool_t. // NOTE: We pass in the address of the pool_t* since the bli_array // API is generalized for arbitrarily-sized elements, and therefore // it must always take the address of the data, rather than the // value (which it can only do if the elem size were fixed). bli_array_set_elem( &pool, index, array ); } // The array element is now guaranteed to refer to an allocated and // initialized pool_t. // Return the array element. return pool; } void bli_apool_grow ( siz_t num_blocks_add, apool_t* restrict apool ) { err_t r_val; // If the requested increase is zero, return early. if ( num_blocks_add == 0 ) return; // Query the underlying pool_t from the apool_t. pool_t* restrict pool = bli_apool_pool( apool ); // Query the default initial array length from the apool_t. const siz_t num_elem = bli_apool_def_array_len( apool ); // ---------------------------------------------------------------------------- // Query the allocated length of the block_ptrs array and also the // total number of blocks currently allocated. const siz_t block_ptrs_len_cur = bli_pool_block_ptrs_len( pool ); const siz_t num_blocks_cur = bli_pool_num_blocks( pool ); // Compute the total number of allocated blocks that will exist // after we grow the pool. const siz_t num_blocks_new = num_blocks_cur + num_blocks_add; // If adding num_blocks_add new blocks will exceed the current capacity // of the block_ptrs array, we need to first put in place a new (larger) // array. if ( block_ptrs_len_cur < num_blocks_new ) { // To prevent this from happening often, we double the current // length of the block_ptrs array. const siz_t block_ptrs_len_new = 2 * block_ptrs_len_cur; // Query the current block_ptrs array. array_t** restrict block_ptrs_cur = bli_pool_block_ptrs( pool ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_apool_grow(): growing block_ptrs_len (%d -> %d): ", ( int )block_ptrs_len_cur, ( int )block_ptrs_len_new ); #endif // Allocate a new block_ptrs array. array_t** restrict block_ptrs_new = bli_malloc_intl( block_ptrs_len_new * sizeof( array_t* ), &r_val ); // Query the top_index of the pool. const siz_t top_index = bli_pool_top_index( pool ); // Copy the contents of the old block_ptrs array to the new/resized // array. Notice that we can begin with top_index since all entries // from 0 to top_index-1 have been (and are currently) checked out // to threads. for ( dim_t i = top_index; i < num_blocks_cur; ++i ) { block_ptrs_new[i] = block_ptrs_cur[i]; } #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_apool_grow(): freeing prev block_ptrs: " ); #endif // Free the old block_ptrs array. bli_free_intl( block_ptrs_cur ); // Update the pool_t struct with the new block_ptrs array and // record its allocated length. bli_pool_set_block_ptrs( block_ptrs_new, pool ); bli_pool_set_block_ptrs_len( block_ptrs_len_new, pool ); } // At this point, we are guaranteed to have enough unused elements // in the block_ptrs array to accommodate an additional num_blocks_add // blocks. // Query the current block_ptrs array (which was maybe just resized). array_t** restrict block_ptrs = bli_pool_block_ptrs( pool ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_apool_grow(): growing apool_t (%d -> %d).\n", ( int )num_blocks_cur, ( int )num_blocks_new ); fflush( stdout ); #endif // Allocate the requested additional blocks in the resized array. for ( dim_t i = num_blocks_cur; i < num_blocks_new; ++i ) { bli_apool_alloc_block ( num_elem, &(block_ptrs[i]) ); } // Update the pool_t struct with the new number of allocated blocks. // Notice that top_index remains unchanged, as do the block_size and // align_size fields. bli_pool_set_num_blocks( num_blocks_new, pool ); } blis-0.9.0/frame/base/bli_apool.h000066400000000000000000000067731422157504600166110ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_APOOL_H #define BLIS_APOOL_H // -- Locked pool-of-arrays type -- /* typedef struct { bli_pthread_mutex_t mutex; pool_t pool; siz_t def_array_len; } apool_t; */ // apool entry query BLIS_INLINE pool_t* bli_apool_pool( apool_t* apool ) { return &(apool->pool); } BLIS_INLINE bli_pthread_mutex_t* bli_apool_mutex( apool_t* apool ) { return &(apool->mutex); } BLIS_INLINE siz_t bli_apool_def_array_len( apool_t* pool ) { return pool->def_array_len; } BLIS_INLINE bool bli_apool_is_exhausted( apool_t* apool ) { pool_t* restrict pool = bli_apool_pool( apool ); return bli_pool_is_exhausted( pool ); } // apool action BLIS_INLINE void bli_apool_lock( apool_t* apool ) { bli_pthread_mutex_lock( bli_apool_mutex( apool ) ); } BLIS_INLINE void bli_apool_unlock( apool_t* apool ) { bli_pthread_mutex_unlock( bli_apool_mutex( apool ) ); } // apool entry modification BLIS_INLINE void bli_apool_set_def_array_len( siz_t def_array_len, apool_t* pool ) \ { pool->def_array_len = def_array_len; } // ----------------------------------------------------------------------------- void bli_apool_init ( apool_t* restrict apool ); void bli_apool_finalize ( apool_t* restrict apool ); array_t* bli_apool_checkout_array ( siz_t n_threads, apool_t* restrict apool ); void bli_apool_checkin_array ( array_t* restrict array, apool_t* restrict apool ); pool_t* bli_apool_array_elem ( siz_t index, array_t* restrict array ); void bli_apool_grow ( siz_t num_blocks_add, apool_t* restrict apool ); void bli_apool_alloc_block ( siz_t num_elem, array_t** restrict array_p ); void bli_apool_free_block ( array_t* restrict array ); #endif blis-0.9.0/frame/base/bli_arch.c000066400000000000000000000217121422157504600163750ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018-2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifdef BLIS_CONFIGURETIME_CPUID // NOTE: If you need to make any changes to this cpp branch, it's probably // the case that you also need to modify bli_arch.c, bli_cpuid.c, and // bli_env.c. Don't forget to update these other files as needed! // The BLIS_ENABLE_SYSTEM macro must be defined so that the correct cpp // branch in bli_system.h is processed. (This macro is normally defined in // bli_config.h.) #define BLIS_ENABLE_SYSTEM // Use C-style static inline functions for any static inline functions that // happen to be defined by the headers below. (This macro is normally defined // in bli_config_macro_defs.h.) #define BLIS_INLINE static // Since we're not building a shared library, we can forgo the use of the // BLIS_EXPORT_BLIS annotations by #defining them to be nothing. (This macro // is normally defined in bli_config_macro_defs.h.) #define BLIS_EXPORT_BLIS #include "bli_system.h" #include "bli_type_defs.h" #include "bli_arch.h" #include "bli_cpuid.h" #include "bli_env.h" #else #include "blis.h" #endif // ----------------------------------------------------------------------------- // The arch_t id for the currently running hardware. We initialize to -1, // which will be overwritten upon calling bli_arch_set_id(). static arch_t id = -1; arch_t bli_arch_query_id( void ) { bli_arch_set_id_once(); // Simply return the id that was previously cached. return id; } // ----------------------------------------------------------------------------- // A pthread structure used in pthread_once(). pthread_once() is guaranteed to // execute exactly once among all threads that pass in this control object. static bli_pthread_once_t once_id = BLIS_PTHREAD_ONCE_INIT; void bli_arch_set_id_once( void ) { #ifndef BLIS_CONFIGURETIME_CPUID bli_pthread_once( &once_id, bli_arch_set_id ); #endif } // ----------------------------------------------------------------------------- void bli_arch_set_id( void ) { // Check the environment variable BLIS_ARCH_DEBUG to see if the user // requested that we echo the result of the subconfiguration selection. bool do_logging = bli_env_get_var( "BLIS_ARCH_DEBUG", 0 ); bli_arch_set_logging( do_logging ); // Check the environment variable BLIS_ARCH_TYPE to see if the user // requested that we use a specific subconfiguration. dim_t req_id = bli_env_get_var( "BLIS_ARCH_TYPE", -1 ); #ifndef BLIS_CONFIGURETIME_CPUID if ( req_id != -1 ) { // BLIS_ARCH_TYPE was set. Cautiously check whether its value is usable. // If req_id was set to an invalid arch_t value (ie: outside the range // [0,BLIS_NUM_ARCHS-1]), output an error message and abort. if ( bli_error_checking_is_enabled() ) { err_t e_val = bli_check_valid_arch_id( req_id ); bli_check_error_code( e_val ); } // At this point, we know that req_id is in the valid range, but we // don't yet know if it refers to a context that was actually // initialized. Query the address of an internal context data structure // corresponding to req_id. This pointer will be NULL if the associated // subconfig is not available. cntx_t** req_cntx = bli_gks_lookup_id( req_id ); // This function checks the context pointer and aborts with a useful // error message if the pointer is found to be NULL. if ( bli_error_checking_is_enabled() ) { err_t e_val = bli_check_initialized_gks_cntx( req_cntx ); bli_check_error_code( e_val ); } // Finally, we can be confident that req_id (1) is in range and (2) // refers to a context that has been initialized. id = req_id; } else #endif { // BLIS_ARCH_TYPE was unset. Proceed with normal subconfiguration // selection behavior. // Architecture families. #if defined BLIS_FAMILY_INTEL64 || \ defined BLIS_FAMILY_AMD64 || \ defined BLIS_FAMILY_X86_64 || \ defined BLIS_FAMILY_ARM64 || \ defined BLIS_FAMILY_ARM32 id = bli_cpuid_query_id(); #endif // Intel microarchitectures. #ifdef BLIS_FAMILY_SKX id = BLIS_ARCH_SKX; #endif #ifdef BLIS_FAMILY_KNL id = BLIS_ARCH_KNL; #endif #ifdef BLIS_FAMILY_KNC id = BLIS_ARCH_KNC; #endif #ifdef BLIS_FAMILY_HASWELL id = BLIS_ARCH_HASWELL; #endif #ifdef BLIS_FAMILY_SANDYBRIDGE id = BLIS_ARCH_SANDYBRIDGE; #endif #ifdef BLIS_FAMILY_PENRYN id = BLIS_ARCH_PENRYN; #endif // AMD microarchitectures. #ifdef BLIS_FAMILY_ZEN3 id = BLIS_ARCH_ZEN3; #endif #ifdef BLIS_FAMILY_ZEN2 id = BLIS_ARCH_ZEN2; #endif #ifdef BLIS_FAMILY_ZEN id = BLIS_ARCH_ZEN; #endif #ifdef BLIS_FAMILY_EXCAVATOR id = BLIS_ARCH_EXCAVATOR; #endif #ifdef BLIS_FAMILY_STEAMROLLER id = BLIS_ARCH_STEAMROLLER; #endif #ifdef BLIS_FAMILY_PILEDRIVER id = BLIS_ARCH_PILEDRIVER; #endif #ifdef BLIS_FAMILY_BULLDOZER id = BLIS_ARCH_BULLDOZER; #endif // ARM microarchitectures. #ifdef BLIS_FAMILY_ARMSVE id = BLIS_ARCH_ARMSVE; #endif #ifdef BLIS_FAMILY_A64FX id = BLIS_ARCH_A64FX; #endif #ifdef BLIS_FAMILY_FIRESTORM id = BLIS_ARCH_FIRESTORM; #endif #ifdef BLIS_FAMILY_THUNDERX2 id = BLIS_ARCH_THUNDERX2; #endif #ifdef BLIS_FAMILY_CORTEXA57 id = BLIS_ARCH_CORTEXA57; #endif #ifdef BLIS_FAMILY_CORTEXA53 id = BLIS_ARCH_CORTEXA53; #endif #ifdef BLIS_FAMILY_CORTEXA15 id = BLIS_ARCH_CORTEXA15; #endif #ifdef BLIS_FAMILY_CORTEXA9 id = BLIS_ARCH_CORTEXA9; #endif // IBM microarchitectures. #ifdef BLIS_FAMILY_POWER10 id = BLIS_ARCH_POWER10; #endif #ifdef BLIS_FAMILY_POWER9 id = BLIS_ARCH_POWER9; #endif #ifdef BLIS_FAMILY_POWER7 id = BLIS_ARCH_POWER7; #endif #ifdef BLIS_FAMILY_BGQ id = BLIS_ARCH_BGQ; #endif // Generic microarchitecture. #ifdef BLIS_FAMILY_GENERIC id = BLIS_ARCH_GENERIC; #endif } if ( bli_arch_get_logging() ) fprintf( stderr, "libblis: selecting sub-configuration '%s'.\n", bli_arch_string( id ) ); //printf( "blis_arch_query_id(): id = %u\n", id ); //exit(1); } // ----------------------------------------------------------------------------- // NOTE: This string array must be kept up-to-date with the arch_t // enumeration that is typedef'ed in bli_type_defs.h. That is, the // index order of each string should correspond to the implied/assigned // enum value given to the corresponding BLIS_ARCH_ value. static char* config_name[ BLIS_NUM_ARCHS ] = { "skx", "knl", "knc", "haswell", "sandybridge", "penryn", "zen3", "zen2", "zen", "excavator", "steamroller", "piledriver", "bulldozer", "armsve", "a64fx", "firestorm", "thunderx2", "cortexa57", "cortexa53", "cortexa15", "cortexa9", "power10", "power9", "power7", "bgq", "generic" }; char* bli_arch_string( arch_t id ) { return config_name[ id ]; } // ----------------------------------------------------------------------------- static bool arch_dolog = 0; void bli_arch_set_logging( bool dolog ) { arch_dolog = dolog; } bool bli_arch_get_logging( void ) { return arch_dolog; } void bli_arch_log( char* fmt, ... ) { char prefix[] = "libblis: "; int n_chars = strlen( prefix ) + strlen( fmt ) + 1; if ( bli_arch_get_logging() && fmt ) { char* prefix_fmt = malloc( n_chars ); snprintf( prefix_fmt, n_chars, "%s%s", prefix, fmt ); va_list ap; va_start( ap, fmt ); vfprintf( stderr, prefix_fmt, ap ); va_end( ap ); free( prefix_fmt ); } } blis-0.9.0/frame/base/bli_arch.h000066400000000000000000000037251422157504600164060ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_ARCH_H #define BLIS_ARCH_H BLIS_EXPORT_BLIS arch_t bli_arch_query_id( void ); void bli_arch_set_id_once( void ); void bli_arch_set_id( void ); BLIS_EXPORT_BLIS char* bli_arch_string( arch_t id ); void bli_arch_set_logging( bool dolog ); bool bli_arch_get_logging( void ); void bli_arch_log( char*, ... ); #endif blis-0.9.0/frame/base/bli_array.c000066400000000000000000000151141422157504600165750ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" //#define BLIS_ENABLE_MEM_TRACING void bli_array_init ( const siz_t num_elem, const siz_t elem_size, array_t* restrict array ) { err_t r_val; #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_array_init(): allocating array [%d * %d]: ", ( int )num_elem, ( int )elem_size ); #endif // Compute the total size (in bytes) of the array. const size_t array_size = num_elem * elem_size; // Allocate the array buffer. void* restrict buf = bli_malloc_intl( array_size, &r_val ); // Initialize the array elements to zero. THIS IS IMPORANT because // consumer threads will use the NULL-ness of the array elements to // determine if the corresponding block (data structure) needs to be // created/allocated and initialized. memset( buf, 0, array_size ); // Initialize the array_t structure. bli_array_set_buf( buf, array ); bli_array_set_num_elem( num_elem, array ); bli_array_set_elem_size( elem_size, array ); } void bli_array_resize ( const siz_t num_elem_new, array_t* restrict array ) { err_t r_val; // Query the number of elements in the array. const siz_t num_elem_prev = bli_array_num_elem( array ); // If the new requested size (number of elements) is less than or equal to // the current size, no action is needed; return early. if ( num_elem_new <= num_elem_prev ) return; // At this point, we know that num_elem_prev < num_elem_new, which means // we need to proceed with the resizing. // Query the size of each element in the array. const siz_t elem_size = bli_array_elem_size( array ); // Compute the total size (in bytes) of the array before and after resizing. const size_t array_size_prev = num_elem_prev * elem_size; const size_t array_size_new = num_elem_new * elem_size; // Query the previous array buffer. void* restrict buf_prev = bli_array_buf( array ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_array_resize(): allocating array [%d * %d]: ", ( int )num_elem_new, ( int )elem_size ); #endif // Allocate a new array buffer. char* restrict buf_new = bli_malloc_intl( array_size_new, &r_val ); // Copy the previous array contents to the new array. memcpy( buf_new, buf_prev, array_size_prev ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_array_resize(): freeing array [%d * %d]: ", ( int )num_elem_prev, ( int )elem_size ); #endif // Now that the elements have been copied over to the new buffer, we can // free the previous array buffer. bli_free_intl( buf_prev ); // Initialize the new elements' contents to zero. (Note that we advance // the new buffer address by the size of the previous array so that we // arrive at the first byte of the new segment.) memset( &buf_new[ array_size_prev ], 0, array_size_new - array_size_prev ); // Update the array_t structure. // NOTE: The array elem_size field does not need updating. bli_array_set_buf( buf_new, array ); bli_array_set_num_elem( num_elem_new, array ); } void bli_array_finalize ( array_t* restrict array ) { #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_array_finalize(): freeing buf (length %d): ", ( int )bli_array_num_elem( array ) ); #endif // Query the buffer from the array. void* restrict buf = bli_array_buf( array ); // Free the buffer. bli_free_intl( buf ); } void* bli_array_elem ( const siz_t index, array_t* restrict array ) { // Query the number of elements in the array. const siz_t num_elem = bli_array_num_elem( array ); // Sanity check: disallow access beyond the bounds of the array. if ( num_elem <= index ) bli_abort(); // Query the size of each element in the array. const siz_t elem_size = bli_array_elem_size( array ); // Query the buffer from the array, but store it as a char* so we can use // it to easily perform byte pointer arithmetic. char* restrict buf = bli_array_buf( array ); // Advance the pointer by (index * elem_size) bytes. buf += index * elem_size; // Return the address of the element computed above. return ( void* )buf; } void bli_array_set_elem ( void* restrict elem, const siz_t index, array_t* restrict array ) { // Query the size of each element in the array. const siz_t elem_size = bli_array_elem_size( array ); // Query the buffer from the array as a char*. char* restrict buf = bli_array_buf( array ); if ( elem_size == sizeof( void* ) ) { #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_array_set_elem(): elem_size is %d; setting index %d.\n", ( int )elem_size, ( int )index ); fflush( stdout ); #endif // Special case: Handle elem_size = sizeof( void* ) without calling // memcpy(). void** restrict buf_vvp = ( void** )buf; void** restrict elem_vvp = ( void** )elem; buf_vvp[ index ] = *elem_vvp; } else { // General case: Copy the elem_size bytes from elem to buf at the // element index specified by index. memcpy( &buf[ index * elem_size ], elem, ( size_t )elem_size ); } } blis-0.9.0/frame/base/bli_array.h000066400000000000000000000060161422157504600166030ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_ARRAY_H #define BLIS_ARRAY_H // -- Array type -- /* typedef struct { void* buf; siz_t num_elem; siz_t elem_size; } array_t; */ // Array entry query BLIS_INLINE void* bli_array_buf( array_t* array ) { return array->buf; } BLIS_INLINE siz_t bli_array_num_elem( array_t* array ) { return array->num_elem; } BLIS_INLINE siz_t bli_array_elem_size( array_t* array ) { return array->elem_size; } // Array entry modification BLIS_INLINE void bli_array_set_buf( void* buf, array_t* array ) \ { array->buf = buf; } BLIS_INLINE void bli_array_set_num_elem( siz_t num_elem, array_t* array ) \ { array->num_elem = num_elem; } BLIS_INLINE void bli_array_set_elem_size( siz_t elem_size, array_t* array ) \ { array->elem_size = elem_size; } // ----------------------------------------------------------------------------- void bli_array_init ( const siz_t num_elem, const siz_t elem_size, array_t* restrict array ); void bli_array_resize ( const siz_t num_elem_new, array_t* restrict array ); void bli_array_finalize ( array_t* restrict array ); void* bli_array_elem ( const siz_t index, array_t* restrict array ); void bli_array_set_elem ( void* restrict elem, const siz_t index, array_t* restrict array ); #endif blis-0.9.0/frame/base/bli_auxinfo.h000066400000000000000000000070471422157504600171430ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_AUXINFO_MACRO_DEFS_H #define BLIS_AUXINFO_MACRO_DEFS_H // auxinfo_t field query BLIS_INLINE pack_t bli_auxinfo_schema_a( auxinfo_t* ai ) { return ai->schema_a; } BLIS_INLINE pack_t bli_auxinfo_schema_b( auxinfo_t* ai ) { return ai->schema_b; } BLIS_INLINE void* bli_auxinfo_next_a( auxinfo_t* ai ) { return ai->a_next; } BLIS_INLINE void* bli_auxinfo_next_b( auxinfo_t* ai ) { return ai->b_next; } BLIS_INLINE inc_t bli_auxinfo_is_a( auxinfo_t* ai ) { return ai->is_a; } BLIS_INLINE inc_t bli_auxinfo_is_b( auxinfo_t* ai ) { return ai->is_b; } BLIS_INLINE inc_t bli_auxinfo_ps_a( auxinfo_t* ai ) { return ai->ps_a; } BLIS_INLINE inc_t bli_auxinfo_ps_b( auxinfo_t* ai ) { return ai->ps_b; } BLIS_INLINE void_fp bli_auxinfo_ukr( auxinfo_t* ai ) { return ai->ukr; } BLIS_INLINE void* bli_auxinfo_params( auxinfo_t* ai ) { return ai->params; } // auxinfo_t field modification BLIS_INLINE void bli_auxinfo_set_schema_a( pack_t schema, auxinfo_t* ai ) { ai->schema_a = schema; } BLIS_INLINE void bli_auxinfo_set_schema_b( pack_t schema, auxinfo_t* ai ) { ai->schema_b = schema; } BLIS_INLINE void bli_auxinfo_set_next_a( void* p, auxinfo_t* ai ) { ai->a_next = p; } BLIS_INLINE void bli_auxinfo_set_next_b( void* p, auxinfo_t* ai ) { ai->b_next = p; } BLIS_INLINE void bli_auxinfo_set_next_ab( void* ap, void* bp, auxinfo_t* ai ) { ai->a_next = ap; ai->b_next = bp; } BLIS_INLINE void bli_auxinfo_set_is_a( inc_t is, auxinfo_t* ai ) { ai->is_a = is; } BLIS_INLINE void bli_auxinfo_set_is_b( inc_t is, auxinfo_t* ai ) { ai->is_b = is; } BLIS_INLINE void bli_auxinfo_set_ps_a( inc_t ps, auxinfo_t* ai ) { ai->ps_a = ps; } BLIS_INLINE void bli_auxinfo_set_ps_b( inc_t ps, auxinfo_t* ai ) { ai->ps_b = ps; } BLIS_INLINE void bli_auxinfo_set_ukr( void_fp ukr, auxinfo_t* ai ) { ai->ukr = ukr; } BLIS_INLINE void bli_auxinfo_set_params( void* params, auxinfo_t* ai ) { ai->params = params; } #endif blis-0.9.0/frame/base/bli_blksz.c000066400000000000000000000245131422157504600166070ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" blksz_t* bli_blksz_create_ed ( dim_t b_s, dim_t be_s, dim_t b_d, dim_t be_d, dim_t b_c, dim_t be_c, dim_t b_z, dim_t be_z ) { err_t r_val; blksz_t* b = bli_malloc_intl( sizeof( blksz_t ), &r_val ); bli_blksz_init_ed ( b, b_s, be_s, b_d, be_d, b_c, be_c, b_z, be_z ); return b; } blksz_t* bli_blksz_create ( dim_t b_s, dim_t b_d, dim_t b_c, dim_t b_z, dim_t be_s, dim_t be_d, dim_t be_c, dim_t be_z ) { err_t r_val; blksz_t* b = bli_malloc_intl( sizeof( blksz_t ), &r_val ); bli_blksz_init ( b, b_s, b_d, b_c, b_z, be_s, be_d, be_c, be_z ); return b; } void bli_blksz_init_ed ( blksz_t* b, dim_t b_s, dim_t be_s, dim_t b_d, dim_t be_d, dim_t b_c, dim_t be_c, dim_t b_z, dim_t be_z ) { b->v[BLIS_FLOAT] = b_s; b->v[BLIS_DOUBLE] = b_d; b->v[BLIS_SCOMPLEX] = b_c; b->v[BLIS_DCOMPLEX] = b_z; b->e[BLIS_FLOAT] = be_s; b->e[BLIS_DOUBLE] = be_d; b->e[BLIS_SCOMPLEX] = be_c; b->e[BLIS_DCOMPLEX] = be_z; } void bli_blksz_init ( blksz_t* b, dim_t b_s, dim_t b_d, dim_t b_c, dim_t b_z, dim_t be_s, dim_t be_d, dim_t be_c, dim_t be_z ) { b->v[BLIS_FLOAT] = b_s; b->v[BLIS_DOUBLE] = b_d; b->v[BLIS_SCOMPLEX] = b_c; b->v[BLIS_DCOMPLEX] = b_z; b->e[BLIS_FLOAT] = be_s; b->e[BLIS_DOUBLE] = be_d; b->e[BLIS_SCOMPLEX] = be_c; b->e[BLIS_DCOMPLEX] = be_z; } void bli_blksz_init_easy ( blksz_t* b, dim_t b_s, dim_t b_d, dim_t b_c, dim_t b_z ) { b->v[BLIS_FLOAT] = b->e[BLIS_FLOAT] = b_s; b->v[BLIS_DOUBLE] = b->e[BLIS_DOUBLE] = b_d; b->v[BLIS_SCOMPLEX] = b->e[BLIS_SCOMPLEX] = b_c; b->v[BLIS_DCOMPLEX] = b->e[BLIS_DCOMPLEX] = b_z; } void bli_blksz_free ( blksz_t* b ) { bli_free_intl( b ); } // ----------------------------------------------------------------------------- #if 0 void bli_blksz_reduce_dt_to ( num_t dt_bm, blksz_t* bmult, num_t dt_bs, blksz_t* blksz ) { dim_t blksz_def = bli_blksz_get_def( dt_bs, blksz ); dim_t blksz_max = bli_blksz_get_max( dt_bs, blksz ); dim_t bmult_val = bli_blksz_get_def( dt_bm, bmult ); // If the blocksize multiple is zero, we do nothing. if ( bmult_val == 0 ) return; // Round the default and maximum blocksize values down to their // respective nearest multiples of bmult_val. (Notice that we // ignore the "max" entry in the bmult object since that would // correspond to the packing dimension, which plays no role // as a blocksize multiple.) blksz_def = ( blksz_def / bmult_val ) * bmult_val; blksz_max = ( blksz_max / bmult_val ) * bmult_val; // Make sure the new blocksize values are at least the blocksize // multiple. if ( blksz_def == 0 ) blksz_def = bmult_val; if ( blksz_max == 0 ) blksz_max = bmult_val; // Store the new blocksizes back to the object. bli_blksz_set_def( blksz_def, dt_bs, blksz ); bli_blksz_set_max( blksz_max, dt_bs, blksz ); } #endif // ----------------------------------------------------------------------------- void bli_blksz_reduce_def_to ( num_t dt_bm, blksz_t* bmult, num_t dt_bs, blksz_t* blksz ) { dim_t blksz_def = bli_blksz_get_def( dt_bs, blksz ); dim_t bmult_val = bli_blksz_get_def( dt_bm, bmult ); // If the blocksize multiple is zero, we do nothing. if ( bmult_val == 0 ) return; // Round the default and maximum blocksize values down to their // respective nearest multiples of bmult_val. (Notice that we // ignore the "max" entry in the bmult object since that would // correspond to the packing dimension, which plays no role // as a blocksize multiple.) blksz_def = ( blksz_def / bmult_val ) * bmult_val; // Make sure the new blocksize values are at least the blocksize // multiple. if ( blksz_def == 0 ) blksz_def = bmult_val; // Store the new blocksizes back to the object. bli_blksz_set_def( blksz_def, dt_bs, blksz ); } // ----------------------------------------------------------------------------- void bli_blksz_reduce_max_to ( num_t dt_bm, blksz_t* bmult, num_t dt_bs, blksz_t* blksz ) { dim_t blksz_max = bli_blksz_get_max( dt_bs, blksz ); dim_t bmult_val = bli_blksz_get_def( dt_bm, bmult ); // If the blocksize multiple is zero, we do nothing. if ( bmult_val == 0 ) return; // Round the blocksize values down to its nearest multiple of // of bmult_val. (Notice that we ignore the "max" entry in the // bmult object since that would correspond to the packing // dimension, which plays no role as a blocksize multiple.) blksz_max = ( blksz_max / bmult_val ) * bmult_val; // Make sure the new blocksize value is at least the blocksize // multiple. if ( blksz_max == 0 ) blksz_max = bmult_val; // Store the new blocksize back to the object. bli_blksz_set_max( blksz_max, dt_bs, blksz ); } // ----------------------------------------------------------------------------- dim_t bli_determine_blocksize ( dir_t direct, dim_t i, dim_t dim, obj_t* obj, bszid_t bszid, cntx_t* cntx ) { if ( direct == BLIS_FWD ) return bli_determine_blocksize_f( i, dim, obj, bszid, cntx ); else return bli_determine_blocksize_b( i, dim, obj, bszid, cntx ); } dim_t bli_determine_blocksize_f ( dim_t i, dim_t dim, obj_t* obj, bszid_t bszid, cntx_t* cntx ) { num_t dt; blksz_t* bsize; dim_t b_alg, b_max; dim_t b_use; // Extract the execution datatype and use it to query the corresponding // blocksize and blocksize maximum values from the blksz_t object. dt = bli_obj_exec_dt( obj ); bsize = bli_cntx_get_blksz( bszid, cntx ); b_alg = bli_blksz_get_def( dt, bsize ); b_max = bli_blksz_get_max( dt, bsize ); b_use = bli_determine_blocksize_f_sub( i, dim, b_alg, b_max ); return b_use; } dim_t bli_determine_blocksize_b ( dim_t i, dim_t dim, obj_t* obj, bszid_t bszid, cntx_t* cntx ) { num_t dt; blksz_t* bsize; dim_t b_alg, b_max; dim_t b_use; // Extract the execution datatype and use it to query the corresponding // blocksize and blocksize maximum values from the blksz_t object. dt = bli_obj_exec_dt( obj ); bsize = bli_cntx_get_blksz( bszid, cntx ); b_alg = bli_blksz_get_def( dt, bsize ); b_max = bli_blksz_get_max( dt, bsize ); b_use = bli_determine_blocksize_b_sub( i, dim, b_alg, b_max ); return b_use; } dim_t bli_determine_blocksize_f_sub ( dim_t i, dim_t dim, dim_t b_alg, dim_t b_max ) { dim_t b_now; dim_t dim_left_now; // We assume that this function is being called from an algorithm that // is moving "forward" (ie: top to bottom, left to right, top-left // to bottom-right). // Compute how much of the matrix dimension is left, including the // chunk that will correspond to the blocksize we are computing now. dim_left_now = dim - i; // If the dimension currently remaining is less than the maximum // blocksize, use it instead of the default blocksize b_alg. // Otherwise, use b_alg. if ( dim_left_now <= b_max ) { b_now = dim_left_now; } else { b_now = b_alg; } return b_now; } dim_t bli_determine_blocksize_b_sub ( dim_t i, dim_t dim, dim_t b_alg, dim_t b_max ) { dim_t b_now; dim_t dim_left_now; dim_t dim_at_edge; // We assume that this function is being called from an algorithm that // is moving "backward" (ie: bottom to top, right to left, bottom-right // to top-left). // Compute how much of the matrix dimension is left, including the // chunk that will correspond to the blocksize we are computing now. dim_left_now = dim - i; // Sanity check: if dim_left_now is zero, then we can return zero // without going any further. if ( dim_left_now == 0 ) return 0; dim_at_edge = dim_left_now % b_alg; // If dim_left_now is a multiple of b_alg, we can safely return b_alg // without going any further. if ( dim_at_edge == 0 ) return b_alg; // If the dimension currently remaining is less than the maximum // blocksize, use it as the chosen blocksize. If this is not the case, // then we know dim_left_now is greater than the maximum blocksize. // To determine how much of it we should use for the current blocksize, // we inspect dim_at_edge; if it is smaller than (or equal to) b_max - // b_alg, then we use b_alg + dim_at_edge. Otherwise, dim_at_edge is // greater than b_max - b_alg, in which case we use dim_at_edge. if ( dim_left_now <= b_max ) { b_now = dim_left_now; } else // if ( dim_left_now > b_max ) { if ( dim_at_edge <= b_max - b_alg ) { b_now = b_alg + dim_at_edge; } else // if ( dim_at_edge > b_max - b_alg ) { b_now = dim_at_edge; } } return b_now; } blis-0.9.0/frame/base/bli_blksz.h000066400000000000000000000160561422157504600166170ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // blksz_t query BLIS_INLINE dim_t bli_blksz_get_def ( num_t dt, blksz_t* b ) { return b->v[ dt ]; } BLIS_INLINE dim_t bli_blksz_get_max ( num_t dt, blksz_t* b ) { return b->e[ dt ]; } // blksz_t modification BLIS_INLINE void bli_blksz_set_def ( dim_t val, num_t dt, blksz_t* b ) { b->v[ dt ] = val; } BLIS_INLINE void bli_blksz_set_max ( dim_t val, num_t dt, blksz_t* b ) { b->e[ dt ] = val; } BLIS_INLINE void bli_blksz_copy ( blksz_t* b_src, blksz_t* b_dst ) { *b_dst = *b_src; } BLIS_INLINE void bli_blksz_copy_if_pos ( blksz_t* b_src, blksz_t* b_dst ) { // Copy the blocksize values over to b_dst one-by-one so that // we can skip the ones that are non-positive. const dim_t v_s = bli_blksz_get_def( BLIS_FLOAT, b_src ); const dim_t v_d = bli_blksz_get_def( BLIS_DOUBLE, b_src ); const dim_t v_c = bli_blksz_get_def( BLIS_SCOMPLEX, b_src ); const dim_t v_z = bli_blksz_get_def( BLIS_DCOMPLEX, b_src ); const dim_t e_s = bli_blksz_get_max( BLIS_FLOAT, b_src ); const dim_t e_d = bli_blksz_get_max( BLIS_DOUBLE, b_src ); const dim_t e_c = bli_blksz_get_max( BLIS_SCOMPLEX, b_src ); const dim_t e_z = bli_blksz_get_max( BLIS_DCOMPLEX, b_src ); if ( v_s > 0 ) bli_blksz_set_def( v_s, BLIS_FLOAT, b_dst ); if ( v_d > 0 ) bli_blksz_set_def( v_d, BLIS_DOUBLE, b_dst ); if ( v_c > 0 ) bli_blksz_set_def( v_c, BLIS_SCOMPLEX, b_dst ); if ( v_z > 0 ) bli_blksz_set_def( v_z, BLIS_DCOMPLEX, b_dst ); if ( e_s > 0 ) bli_blksz_set_max( e_s, BLIS_FLOAT, b_dst ); if ( e_d > 0 ) bli_blksz_set_max( e_d, BLIS_DOUBLE, b_dst ); if ( e_c > 0 ) bli_blksz_set_max( e_c, BLIS_SCOMPLEX, b_dst ); if ( e_z > 0 ) bli_blksz_set_max( e_z, BLIS_DCOMPLEX, b_dst ); } BLIS_INLINE void bli_blksz_copy_def_dt ( num_t dt_src, blksz_t* b_src, num_t dt_dst, blksz_t* b_dst ) { const dim_t val = bli_blksz_get_def( dt_src, b_src ); bli_blksz_set_def( val, dt_dst, b_dst ); } BLIS_INLINE void bli_blksz_copy_max_dt ( num_t dt_src, blksz_t* b_src, num_t dt_dst, blksz_t* b_dst ) { const dim_t val = bli_blksz_get_max( dt_src, b_src ); bli_blksz_set_max( val, dt_dst, b_dst ); } BLIS_INLINE void bli_blksz_copy_dt ( num_t dt_src, blksz_t* b_src, num_t dt_dst, blksz_t* b_dst ) { bli_blksz_copy_def_dt( dt_src, b_src, dt_dst, b_dst ); bli_blksz_copy_max_dt( dt_src, b_src, dt_dst, b_dst ); } BLIS_INLINE void bli_blksz_scale_def ( dim_t num, dim_t den, num_t dt, blksz_t* b ) { const dim_t val = bli_blksz_get_def( dt, b ); bli_blksz_set_def( ( val * num ) / den, dt, b ); } BLIS_INLINE void bli_blksz_scale_max ( dim_t num, dim_t den, num_t dt, blksz_t* b ) { const dim_t val = bli_blksz_get_max( dt, b ); bli_blksz_set_max( ( val * num ) / den, dt, b ); } BLIS_INLINE void bli_blksz_scale_def_max ( dim_t num, dim_t den, num_t dt, blksz_t* b ) { bli_blksz_scale_def( num, den, dt, b ); bli_blksz_scale_max( num, den, dt, b ); } // ----------------------------------------------------------------------------- BLIS_EXPORT_BLIS blksz_t* bli_blksz_create_ed ( dim_t b_s, dim_t be_s, dim_t b_d, dim_t be_d, dim_t b_c, dim_t be_c, dim_t b_z, dim_t be_z ); BLIS_EXPORT_BLIS blksz_t* bli_blksz_create ( dim_t b_s, dim_t b_d, dim_t b_c, dim_t b_z, dim_t be_s, dim_t be_d, dim_t be_c, dim_t be_z ); BLIS_EXPORT_BLIS void bli_blksz_init_ed ( blksz_t* b, dim_t b_s, dim_t be_s, dim_t b_d, dim_t be_d, dim_t b_c, dim_t be_c, dim_t b_z, dim_t be_z ); BLIS_EXPORT_BLIS void bli_blksz_init ( blksz_t* b, dim_t b_s, dim_t b_d, dim_t b_c, dim_t b_z, dim_t be_s, dim_t be_d, dim_t be_c, dim_t be_z ); BLIS_EXPORT_BLIS void bli_blksz_init_easy ( blksz_t* b, dim_t b_s, dim_t b_d, dim_t b_c, dim_t b_z ); BLIS_EXPORT_BLIS void bli_blksz_free ( blksz_t* b ); // ----------------------------------------------------------------------------- #if 0 BLIS_EXPORT_BLIS void bli_blksz_reduce_dt_to ( num_t dt_bm, blksz_t* bmult, num_t dt_bs, blksz_t* blksz ); #endif void bli_blksz_reduce_def_to ( num_t dt_bm, blksz_t* bmult, num_t dt_bs, blksz_t* blksz ); void bli_blksz_reduce_max_to ( num_t dt_bm, blksz_t* bmult, num_t dt_bs, blksz_t* blksz ); // ----------------------------------------------------------------------------- dim_t bli_determine_blocksize ( dir_t direct, dim_t i, dim_t dim, obj_t* obj, bszid_t bszid, cntx_t* cntx ); dim_t bli_determine_blocksize_f ( dim_t i, dim_t dim, obj_t* obj, bszid_t bszid, cntx_t* cntx ); dim_t bli_determine_blocksize_b ( dim_t i, dim_t dim, obj_t* obj, bszid_t bszid, cntx_t* cntx ); dim_t bli_determine_blocksize_f_sub ( dim_t i, dim_t dim, dim_t b_alg, dim_t b_max ); dim_t bli_determine_blocksize_b_sub ( dim_t i, dim_t dim, dim_t b_alg, dim_t b_max ); blis-0.9.0/frame/base/bli_check.c000066400000000000000000000532121422157504600165350ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // -- General stuff ------------------------------------------------------------ err_t bli_check_error_code_helper( gint_t code, char* file, guint_t line ) { if ( code == BLIS_SUCCESS ) return code; if ( BLIS_ERROR_CODE_MAX < code && code < BLIS_ERROR_CODE_MIN ) { bli_print_msg( bli_error_string_for_code( code ), file, line ); bli_abort(); } else { bli_print_msg( bli_error_string_for_code( BLIS_UNDEFINED_ERROR_CODE ), file, line ); bli_abort(); } return code; } err_t bli_check_valid_error_level( errlev_t level ) { err_t e_val = BLIS_SUCCESS; if ( level != BLIS_NO_ERROR_CHECKING && level != BLIS_FULL_ERROR_CHECKING ) e_val = BLIS_INVALID_ERROR_CHECKING_LEVEL; return e_val; } err_t bli_check_null_pointer( void* ptr ) { err_t e_val = BLIS_SUCCESS; if ( ptr == NULL ) e_val = BLIS_NULL_POINTER; return e_val; } // -- Parameter-related checks ------------------------------------------------- err_t bli_check_valid_side( side_t side ) { err_t e_val = BLIS_SUCCESS; if ( side != BLIS_LEFT && side != BLIS_RIGHT /*&& side != BLIS_TOP && side != BLIS_BOTTOM*/ ) e_val = BLIS_INVALID_SIDE; return e_val; } err_t bli_check_valid_uplo( uplo_t uplo ) { err_t e_val = BLIS_SUCCESS; if ( !bli_is_lower( uplo ) && !bli_is_upper( uplo ) ) e_val = BLIS_INVALID_UPLO; return e_val; } err_t bli_check_valid_trans( trans_t trans ) { err_t e_val = BLIS_SUCCESS; if ( trans != BLIS_NO_TRANSPOSE && trans != BLIS_TRANSPOSE && trans != BLIS_CONJ_NO_TRANSPOSE && trans != BLIS_CONJ_TRANSPOSE ) e_val = BLIS_INVALID_TRANS; return e_val; } err_t bli_check_valid_diag( diag_t diag ) { err_t e_val = BLIS_SUCCESS; if ( diag != BLIS_NONUNIT_DIAG && diag != BLIS_UNIT_DIAG ) e_val = BLIS_INVALID_DIAG; return e_val; } err_t bli_check_nonunit_diag( obj_t* a ) { err_t e_val = BLIS_SUCCESS; if ( !bli_obj_has_nonunit_diag( a ) ) e_val = BLIS_EXPECTED_NONUNIT_DIAG; return e_val; } // -- Datatype-related checks -------------------------------------------------- err_t bli_check_valid_datatype( num_t dt ) { err_t e_val = BLIS_SUCCESS; if ( dt != BLIS_FLOAT && dt != BLIS_DOUBLE && dt != BLIS_SCOMPLEX && dt != BLIS_DCOMPLEX && dt != BLIS_INT && dt != BLIS_CONSTANT ) e_val = BLIS_INVALID_DATATYPE; return e_val; } err_t bli_check_object_valid_datatype( obj_t* a ) { err_t e_val; num_t dt; dt = bli_obj_dt( a ); e_val = bli_check_valid_datatype( dt ); return e_val; } err_t bli_check_noninteger_datatype( num_t dt ) { err_t e_val = BLIS_SUCCESS; if ( dt == BLIS_INT ) e_val = BLIS_EXPECTED_NONINTEGER_DATATYPE; return e_val; } err_t bli_check_noninteger_object( obj_t* a ) { err_t e_val; num_t dt; dt = bli_obj_dt( a ); e_val = bli_check_noninteger_datatype( dt ); return e_val; } err_t bli_check_nonconstant_datatype( num_t dt ) { err_t e_val = BLIS_SUCCESS; if ( dt == BLIS_CONSTANT ) e_val = BLIS_EXPECTED_NONCONSTANT_DATATYPE; return e_val; } err_t bli_check_nonconstant_object( obj_t* a ) { err_t e_val; num_t dt; dt = bli_obj_dt( a ); e_val = bli_check_nonconstant_datatype( dt ); return e_val; } err_t bli_check_floating_datatype( num_t dt ) { err_t e_val = BLIS_SUCCESS; if ( dt != BLIS_FLOAT && dt != BLIS_DOUBLE && dt != BLIS_SCOMPLEX && dt != BLIS_DCOMPLEX ) e_val = BLIS_EXPECTED_FLOATING_POINT_DATATYPE; return e_val; } err_t bli_check_floating_object( obj_t* a ) { err_t e_val; num_t dt; dt = bli_obj_dt( a ); e_val = bli_check_floating_datatype( dt ); return e_val; } err_t bli_check_real_datatype( num_t dt ) { err_t e_val = BLIS_SUCCESS; if ( dt != BLIS_FLOAT && dt != BLIS_DOUBLE ) e_val = BLIS_EXPECTED_REAL_DATATYPE; return e_val; } err_t bli_check_real_object( obj_t* a ) { err_t e_val; num_t dt; dt = bli_obj_dt( a ); e_val = bli_check_real_datatype( dt ); return e_val; } err_t bli_check_integer_datatype( num_t dt ) { err_t e_val = BLIS_SUCCESS; if ( dt != BLIS_INT ) e_val = BLIS_EXPECTED_INTEGER_DATATYPE; return e_val; } err_t bli_check_integer_object( obj_t* a ) { err_t e_val; num_t dt; dt = bli_obj_dt( a ); e_val = bli_check_integer_datatype( dt ); return e_val; } err_t bli_check_consistent_datatypes( num_t dt_a, num_t dt_b ) { err_t e_val = BLIS_SUCCESS; if ( dt_a != BLIS_CONSTANT && dt_b != BLIS_CONSTANT ) if ( dt_a != dt_b ) e_val = BLIS_INCONSISTENT_DATATYPES; return e_val; } err_t bli_check_consistent_object_datatypes( obj_t* a, obj_t* b ) { err_t e_val; num_t dt_a; num_t dt_b; dt_a = bli_obj_dt( a ); dt_b = bli_obj_dt( b ); e_val = bli_check_consistent_datatypes( dt_a, dt_b ); return e_val; } err_t bli_check_datatype_real_proj_of( num_t dt_c, num_t dt_r ) { err_t e_val = BLIS_SUCCESS; if ( ( dt_c == BLIS_CONSTANT && bli_is_complex( dt_r ) ) || ( dt_c == BLIS_FLOAT && dt_r != BLIS_FLOAT ) || ( dt_c == BLIS_DOUBLE && dt_r != BLIS_DOUBLE ) || ( dt_c == BLIS_SCOMPLEX && dt_r != BLIS_FLOAT ) || ( dt_c == BLIS_DCOMPLEX && dt_r != BLIS_DOUBLE ) ) e_val = BLIS_EXPECTED_REAL_PROJ_OF; return e_val; } err_t bli_check_object_real_proj_of( obj_t* c, obj_t* r ) { err_t e_val; num_t dt_c; num_t dt_r; dt_c = bli_obj_dt( c ); dt_r = bli_obj_dt( r ); e_val = bli_check_datatype_real_proj_of( dt_c, dt_r ); return e_val; } err_t bli_check_real_valued_object( obj_t* a ) { err_t e_val = BLIS_SUCCESS; double a_real; double a_imag; bli_getsc( a, &a_real, &a_imag ); if ( a_imag != 0.0 ) e_val = BLIS_EXPECTED_REAL_VALUED_OBJECT; return e_val; } err_t bli_check_consistent_precisions( num_t dt_a, num_t dt_b ) { err_t e_val = BLIS_SUCCESS; if ( dt_a == BLIS_FLOAT ) { if ( dt_b != BLIS_FLOAT && dt_b != BLIS_SCOMPLEX ) e_val = BLIS_INCONSISTENT_PRECISIONS; } else if ( dt_a == BLIS_DOUBLE ) { if ( dt_b != BLIS_DOUBLE && dt_b != BLIS_DCOMPLEX ) e_val = BLIS_INCONSISTENT_PRECISIONS; } return e_val; } err_t bli_check_consistent_object_precisions( obj_t* a, obj_t* b ) { err_t e_val; num_t dt_a; num_t dt_b; dt_a = bli_obj_dt( a ); dt_b = bli_obj_dt( b ); e_val = bli_check_consistent_precisions( dt_a, dt_b ); return e_val; } // -- Dimension-related checks ------------------------------------------------- err_t bli_check_conformal_dims( obj_t* a, obj_t* b ) { err_t e_val = BLIS_SUCCESS; dim_t m_a, n_a; dim_t m_b, n_b; m_a = bli_obj_length_after_trans( a ); n_a = bli_obj_width_after_trans( a ); m_b = bli_obj_length_after_trans( b ); n_b = bli_obj_width_after_trans( b ); if ( m_a != m_b || n_a != n_b ) e_val = BLIS_NONCONFORMAL_DIMENSIONS; return e_val; } err_t bli_check_level3_dims( obj_t* a, obj_t* b, obj_t* c ) { err_t e_val = BLIS_SUCCESS; dim_t m_c, n_c; dim_t m_a, k_a; dim_t k_b, n_b; m_c = bli_obj_length_after_trans( c ); n_c = bli_obj_width_after_trans( c ); m_a = bli_obj_length_after_trans( a ); k_a = bli_obj_width_after_trans( a ); k_b = bli_obj_length_after_trans( b ); n_b = bli_obj_width_after_trans( b ); if ( m_c != m_a || n_c != n_b || k_a != k_b ) e_val = BLIS_NONCONFORMAL_DIMENSIONS; return e_val; } err_t bli_check_scalar_object( obj_t* a ) { err_t e_val = BLIS_SUCCESS; if ( bli_obj_length( a ) < 0 || bli_obj_width( a ) < 0 ) return BLIS_NEGATIVE_DIMENSION; if ( bli_obj_length( a ) != 1 || bli_obj_width( a ) != 1 ) return BLIS_EXPECTED_SCALAR_OBJECT; return e_val; } err_t bli_check_vector_object( obj_t* a ) { err_t e_val = BLIS_SUCCESS; if ( bli_obj_length( a ) < 0 || bli_obj_width( a ) < 0 ) return BLIS_NEGATIVE_DIMENSION; if ( !bli_obj_is_vector( a ) ) return BLIS_EXPECTED_VECTOR_OBJECT; return e_val; } err_t bli_check_matrix_object( obj_t* a ) { err_t e_val = BLIS_SUCCESS; if ( bli_obj_length( a ) < 0 || bli_obj_width( a ) < 0 ) e_val = BLIS_NEGATIVE_DIMENSION; return e_val; } err_t bli_check_equal_vector_lengths( obj_t* x, obj_t* y ) { err_t e_val = BLIS_SUCCESS; dim_t dim_x; dim_t dim_y; dim_x = bli_obj_vector_dim( x ); dim_y = bli_obj_vector_dim( y ); if ( dim_x != dim_y ) e_val = BLIS_UNEQUAL_VECTOR_LENGTHS; return e_val; } err_t bli_check_square_object( obj_t* a ) { err_t e_val = BLIS_SUCCESS; if ( bli_obj_length( a ) != bli_obj_width( a ) ) e_val = BLIS_EXPECTED_SQUARE_OBJECT; return e_val; } err_t bli_check_object_length_equals( obj_t* a, dim_t m ) { err_t e_val = BLIS_SUCCESS; if ( bli_obj_length( a ) != m ) e_val = BLIS_UNEXPECTED_OBJECT_LENGTH; return e_val; } err_t bli_check_object_width_equals( obj_t* a, dim_t n ) { err_t e_val = BLIS_SUCCESS; if ( bli_obj_width( a ) != n ) e_val = BLIS_UNEXPECTED_OBJECT_WIDTH; return e_val; } err_t bli_check_vector_dim_equals( obj_t* a, dim_t n ) { err_t e_val = BLIS_SUCCESS; if ( bli_obj_vector_dim( a ) != n ) e_val = BLIS_UNEXPECTED_VECTOR_DIM; return e_val; } err_t bli_check_object_diag_offset_equals( obj_t* a, doff_t offset ) { err_t e_val = BLIS_SUCCESS; if ( offset != bli_obj_diag_offset( a ) ) e_val = BLIS_UNEXPECTED_DIAG_OFFSET; return e_val; } // -- Stride-related checks ---------------------------------------------------- err_t bli_check_matrix_strides( dim_t m, dim_t n, inc_t rs, inc_t cs, inc_t is ) { err_t e_val = BLIS_SUCCESS; // Note: A lot of thought went into designing these checks. Do NOT change // them unless you absolutely know what you are doing! Particularly, do // not try to merge the general and row-/column-major sections. It might // be possible, but it would be a lot less readable. // Prohibit negative dimensions. if ( m < 0 || n < 0 ) return BLIS_NEGATIVE_DIMENSION; // Overwrite rs and cs with the absolute value of each. We can do this // since the checks below are not dependent on the sign of the strides. rs = bli_abs( rs ); cs = bli_abs( cs ); is = bli_abs( is ); // The default case (whereby we interpret rs == cs == 0 as a request for // column-major order) is handled prior to calling this function, so the // only time we should see zero strides here is if the matrix is empty. if ( m == 0 || n == 0 ) return e_val; // Disallow row, column, or imaginary strides of zero. if ( ( rs == 0 || cs == 0 || is == 0 ) ) return BLIS_INVALID_DIM_STRIDE_COMBINATION; // Check stride consistency in cases of general stride. if ( rs != 1 && cs != 1 ) { // We apply different tests depending on which way the strides // "tilt". if ( rs == cs ) { // If rs == cs, then we must be dealing with an m-by-1 or a // 1-by-n matrix and thus at least one of the dimensions, m // or n, must be unit (even if the other is zero). if ( m != 1 && n != 1 ) return BLIS_INVALID_DIM_STRIDE_COMBINATION; } else if ( rs < cs ) { // For column-major tilt, cs must be equal or larger than m * rs. if ( m * rs > cs ) return BLIS_INVALID_DIM_STRIDE_COMBINATION; } else if ( cs < rs ) { // For row-major tilt, rs must be equal or larger than n * cs. if ( n * cs > rs ) return BLIS_INVALID_DIM_STRIDE_COMBINATION; } } else // check stride consistency of row-/column-storage cases. { if ( rs == 1 && cs == 1 ) { // If rs == cs == 1, then we must be dealing with an m-by-1, a // 1-by-n, or a 1-by-1 matrix and thus at least one of the // dimensions, m or n, must be unit (even if the other is zero). if ( m != 1 && n != 1 ) return BLIS_INVALID_DIM_STRIDE_COMBINATION; } else if ( rs == 1 ) { // For column-major storage, don't allow the column stride to be // less than the m dimension. if ( cs < m ) return BLIS_INVALID_COL_STRIDE; } else if ( cs == 1 ) { // For row-major storage, don't allow the row stride to be less // than the n dimension. if ( rs < n ) return BLIS_INVALID_ROW_STRIDE; } } return e_val; } // -- Structure-related checks ------------------------------------------------- err_t bli_check_general_object( obj_t* a ) { err_t e_val = BLIS_SUCCESS; if ( !bli_obj_is_general( a ) ) e_val = BLIS_EXPECTED_GENERAL_OBJECT; return e_val; } err_t bli_check_hermitian_object( obj_t* a ) { err_t e_val = BLIS_SUCCESS; if ( !bli_obj_is_hermitian( a ) ) e_val = BLIS_EXPECTED_HERMITIAN_OBJECT; return e_val; } err_t bli_check_symmetric_object( obj_t* a ) { err_t e_val = BLIS_SUCCESS; if ( !bli_obj_is_symmetric( a ) ) e_val = BLIS_EXPECTED_SYMMETRIC_OBJECT; return e_val; } err_t bli_check_triangular_object( obj_t* a ) { err_t e_val = BLIS_SUCCESS; if ( !bli_obj_is_triangular( a ) ) e_val = BLIS_EXPECTED_TRIANGULAR_OBJECT; return e_val; } err_t bli_check_object_struc( obj_t* a, struc_t struc ) { err_t e_val = BLIS_SUCCESS; if ( bli_is_general( struc ) ) e_val = bli_check_general_object( a ); else if ( bli_is_hermitian( struc ) ) e_val = bli_check_hermitian_object( a ); else if ( bli_is_symmetric( struc ) ) e_val = bli_check_symmetric_object( a ); else if ( bli_is_triangular( struc ) ) e_val = bli_check_triangular_object( a ); return e_val; } // -- Storage-related checks --------------------------------------------------- err_t bli_check_upper_or_lower_object( obj_t* a ) { err_t e_val = BLIS_SUCCESS; if ( !bli_obj_is_lower( a ) && !bli_obj_is_upper( a ) ) e_val = BLIS_EXPECTED_UPPER_OR_LOWER_OBJECT; return e_val; } // -- Partitioning-related checks ---------------------------------------------- err_t bli_check_valid_3x1_subpart( subpart_t part ) { err_t e_val = BLIS_SUCCESS; if ( part != BLIS_SUBPART0 && part != BLIS_SUBPART1AND0 && part != BLIS_SUBPART1 && part != BLIS_SUBPART1AND2 && part != BLIS_SUBPART2 && part != BLIS_SUBPART1A && part != BLIS_SUBPART1B ) e_val = BLIS_INVALID_3x1_SUBPART; return e_val; } err_t bli_check_valid_1x3_subpart( subpart_t part ) { err_t e_val = BLIS_SUCCESS; if ( part != BLIS_SUBPART0 && part != BLIS_SUBPART1AND0 && part != BLIS_SUBPART1 && part != BLIS_SUBPART1AND2 && part != BLIS_SUBPART2 && part != BLIS_SUBPART1A && part != BLIS_SUBPART1B ) e_val = BLIS_INVALID_1x3_SUBPART; return e_val; } err_t bli_check_valid_3x3_subpart( subpart_t part ) { err_t e_val = BLIS_SUCCESS; if ( part != BLIS_SUBPART00 && part != BLIS_SUBPART10 && part != BLIS_SUBPART20 && part != BLIS_SUBPART01 && part != BLIS_SUBPART11 && part != BLIS_SUBPART21 && part != BLIS_SUBPART02 && part != BLIS_SUBPART12 && part != BLIS_SUBPART22 ) e_val = BLIS_INVALID_3x3_SUBPART; return e_val; } // -- Control tree-related checks ---------------------------------------------- err_t bli_check_valid_cntl( void* cntl ) { err_t e_val = BLIS_SUCCESS; if ( cntl == NULL ) e_val = BLIS_UNEXPECTED_NULL_CONTROL_TREE; return e_val; } // -- Packing-related checks --------------------------------------------------- err_t bli_check_packm_schema_on_unpack( obj_t* a ) { err_t e_val = BLIS_SUCCESS; if ( bli_obj_pack_schema( a ) != BLIS_PACKED_ROWS && bli_obj_pack_schema( a ) != BLIS_PACKED_COLUMNS && bli_obj_pack_schema( a ) != BLIS_PACKED_ROW_PANELS && bli_obj_pack_schema( a ) != BLIS_PACKED_COL_PANELS ) e_val = BLIS_PACK_SCHEMA_NOT_SUPPORTED_FOR_UNPACK; return e_val; } err_t bli_check_packv_schema_on_unpack( obj_t* a ) { err_t e_val = BLIS_SUCCESS; if ( bli_obj_pack_schema( a ) != BLIS_PACKED_VECTOR ) e_val = BLIS_PACK_SCHEMA_NOT_SUPPORTED_FOR_UNPACK; return e_val; } // -- Buffer-related checks ---------------------------------------------------- err_t bli_check_object_buffer( obj_t* a ) { err_t e_val = BLIS_SUCCESS; // We are only concerned with NULL buffers in objects where BOTH // dimensions are non-zero. if ( bli_obj_buffer( a ) == NULL ) if ( bli_obj_length( a ) > 0 && bli_obj_width( a ) > 0 ) e_val = BLIS_EXPECTED_NONNULL_OBJECT_BUFFER; return e_val; } // -- Memory checks ------------------------------------------------------------ err_t bli_check_valid_malloc_buf( void* ptr ) { err_t e_val = BLIS_SUCCESS; if ( ptr == NULL ) e_val = BLIS_MALLOC_RETURNED_NULL; return e_val; } // -- Internal memory pool checks ---------------------------------------------- err_t bli_check_valid_packbuf( packbuf_t buf_type ) { err_t e_val = BLIS_SUCCESS; if ( buf_type != BLIS_BUFFER_FOR_A_BLOCK && buf_type != BLIS_BUFFER_FOR_B_PANEL && buf_type != BLIS_BUFFER_FOR_C_PANEL && buf_type != BLIS_BUFFER_FOR_GEN_USE ) e_val = BLIS_INVALID_PACKBUF; return e_val; } err_t bli_check_if_exhausted_pool( pool_t* pool ) { err_t e_val = BLIS_SUCCESS; if ( bli_pool_is_exhausted( pool ) ) e_val = BLIS_EXHAUSTED_CONTIG_MEMORY_POOL; return e_val; } err_t bli_check_sufficient_stack_buf_size( cntx_t* cntx ) { err_t e_val = BLIS_SUCCESS; num_t dt; for ( dt = BLIS_DT_LO; dt <= BLIS_DT_HI; ++dt ) { dim_t mr = bli_cntx_get_blksz_def_dt( dt, BLIS_MR, cntx ); dim_t nr = bli_cntx_get_blksz_def_dt( dt, BLIS_NR, cntx ); siz_t dt_size = bli_dt_size( dt ); // NOTE: For induced methods, we use the size of the complex datatypes // (rather than the size of the native micro-kernels' datatype) because // the macro-kernel needs this larger micro-tile footprint, even if the // virtual micro-kernel implementation will only ever be writing to half // of it (real or imaginary part) at a time. if ( mr * nr * dt_size > BLIS_STACK_BUF_MAX_SIZE ) e_val = BLIS_INSUFFICIENT_STACK_BUF_SIZE; } return e_val; } err_t bli_check_alignment_is_power_of_two( size_t align_size ) { err_t e_val = BLIS_SUCCESS; // This function returns an error code if align_size is zero or not // a power of two. if ( align_size == 0 ) e_val = BLIS_ALIGNMENT_NOT_POWER_OF_TWO; else if ( ( align_size & ( align_size - 1 ) ) ) e_val = BLIS_ALIGNMENT_NOT_POWER_OF_TWO; return e_val; } err_t bli_check_alignment_is_mult_of_ptr_size( size_t align_size ) { err_t e_val = BLIS_SUCCESS; // This function returns an error code if align_size is not a whole // multiple of the size of a pointer. if ( align_size % sizeof( void* ) != 0 ) e_val = BLIS_ALIGNMENT_NOT_MULT_OF_PTR_SIZE; return e_val; } // -- Object-related errors ---------------------------------------------------- err_t bli_check_object_alias_of( obj_t* a, obj_t* b ) { err_t e_val = BLIS_SUCCESS; if ( !bli_obj_is_alias_of( a, b ) ) e_val = BLIS_EXPECTED_OBJECT_ALIAS; return e_val; } // -- Architecture-related errors ---------------------------------------------- err_t bli_check_valid_arch_id( arch_t id ) { err_t e_val = BLIS_SUCCESS; if ( ( gint_t )id < 0 || BLIS_NUM_ARCHS <= ( gint_t )id ) e_val = BLIS_INVALID_ARCH_ID; return e_val; } err_t bli_check_initialized_gks_cntx( cntx_t** cntx ) { err_t e_val = BLIS_SUCCESS; if ( cntx == NULL ) e_val = BLIS_UNINITIALIZED_GKS_CNTX; return e_val; } // -- Architecture-related errors ---------------------------------------------- err_t bli_check_valid_mc_mod_mult( blksz_t* mc, blksz_t* mr ) { num_t dt; for ( dt = BLIS_DT_LO; dt <= BLIS_DT_HI; ++dt ) { dim_t mc_def_dt = bli_blksz_get_def( dt, mc ); dim_t mc_max_dt = bli_blksz_get_max( dt, mc ); dim_t mr_dt = bli_blksz_get_def( dt, mr ); if ( mc_def_dt % mr_dt != 0 ) return BLIS_MC_DEF_NONMULTIPLE_OF_MR; else if ( mc_max_dt % mr_dt != 0 ) return BLIS_MC_MAX_NONMULTIPLE_OF_MR; } return BLIS_SUCCESS; } err_t bli_check_valid_nc_mod_mult( blksz_t* nc, blksz_t* nr ) { num_t dt; for ( dt = BLIS_DT_LO; dt <= BLIS_DT_HI; ++dt ) { dim_t nc_def_dt = bli_blksz_get_def( dt, nc ); dim_t nc_max_dt = bli_blksz_get_max( dt, nc ); dim_t nr_dt = bli_blksz_get_def( dt, nr ); if ( nc_def_dt % nr_dt != 0 ) return BLIS_NC_DEF_NONMULTIPLE_OF_NR; else if ( nc_max_dt % nr_dt != 0 ) return BLIS_NC_MAX_NONMULTIPLE_OF_NR; } return BLIS_SUCCESS; } err_t bli_check_valid_kc_mod_mult( blksz_t* kc, blksz_t* kr ) { num_t dt; for ( dt = BLIS_DT_LO; dt <= BLIS_DT_HI; ++dt ) { dim_t kc_def_dt = bli_blksz_get_def( dt, kc ); dim_t kc_max_dt = bli_blksz_get_max( dt, kc ); dim_t kr_dt = bli_blksz_get_def( dt, kr ); if ( kc_def_dt % kr_dt != 0 ) return BLIS_KC_DEF_NONMULTIPLE_OF_KR; else if ( kc_max_dt % kr_dt != 0 ) return BLIS_KC_MAX_NONMULTIPLE_OF_KR; } return BLIS_SUCCESS; } blis-0.9.0/frame/base/bli_check.h000066400000000000000000000120301422157504600165330ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ BLIS_EXPORT_BLIS err_t bli_check_error_code_helper( gint_t code, char* file, guint_t line ); err_t bli_check_valid_error_level( errlev_t level ); err_t bli_check_null_pointer( void* ptr ); err_t bli_check_valid_side( side_t side ); err_t bli_check_valid_uplo( uplo_t uplo ); err_t bli_check_valid_trans( trans_t trans ); err_t bli_check_valid_diag( diag_t diag ); err_t bli_check_nonunit_diag( obj_t* a ); err_t bli_check_valid_datatype( num_t dt ); err_t bli_check_object_valid_datatype( obj_t* a ); err_t bli_check_noninteger_datatype( num_t dt ); err_t bli_check_noninteger_object( obj_t* a ); err_t bli_check_nonconstant_datatype( num_t dt ); err_t bli_check_nonconstant_object( obj_t* a ); err_t bli_check_floating_datatype( num_t dt ); err_t bli_check_floating_object( obj_t* a ); err_t bli_check_real_datatype( num_t dt ); err_t bli_check_real_object( obj_t* a ); err_t bli_check_integer_datatype( num_t dt ); err_t bli_check_integer_object( obj_t* a ); err_t bli_check_consistent_datatypes( num_t dt_a, num_t dt_b ); err_t bli_check_consistent_object_datatypes( obj_t* a, obj_t* b ); err_t bli_check_datatype_real_proj_of( num_t dt_c, num_t dt_r ); err_t bli_check_object_real_proj_of( obj_t* c, obj_t* r ); err_t bli_check_real_valued_object( obj_t* a ); err_t bli_check_consistent_precisions( num_t dt_a, num_t dt_b ); err_t bli_check_consistent_object_precisions( obj_t* a, obj_t* b ); err_t bli_check_conformal_dims( obj_t* a, obj_t* b ); err_t bli_check_level3_dims( obj_t* a, obj_t* b, obj_t* c ); err_t bli_check_scalar_object( obj_t* a ); err_t bli_check_vector_object( obj_t* a ); err_t bli_check_matrix_object( obj_t* a ); err_t bli_check_equal_vector_lengths( obj_t* x, obj_t* y ); err_t bli_check_square_object( obj_t* a ); err_t bli_check_object_length_equals( obj_t* a, dim_t m ); err_t bli_check_object_width_equals( obj_t* a, dim_t n ); err_t bli_check_vector_dim_equals( obj_t* a, dim_t n ); err_t bli_check_object_diag_offset_equals( obj_t* a, doff_t offset ); err_t bli_check_matrix_strides( dim_t m, dim_t n, inc_t rs, inc_t cs, inc_t is ); err_t bli_check_general_object( obj_t* a ); err_t bli_check_hermitian_object( obj_t* a ); err_t bli_check_symmetric_object( obj_t* a ); err_t bli_check_triangular_object( obj_t* a ); err_t bli_check_object_struc( obj_t* a, struc_t struc ); err_t bli_check_upper_or_lower_object( obj_t* a ); err_t bli_check_valid_3x1_subpart( subpart_t part ); err_t bli_check_valid_1x3_subpart( subpart_t part ); err_t bli_check_valid_3x3_subpart( subpart_t part ); err_t bli_check_valid_cntl( void* cntl ); err_t bli_check_packm_schema_on_unpack( obj_t* a ); err_t bli_check_packv_schema_on_unpack( obj_t* a ); err_t bli_check_object_buffer( obj_t* a ); err_t bli_check_valid_malloc_buf( void* ptr ); err_t bli_check_valid_packbuf( packbuf_t buf_type ); err_t bli_check_if_exhausted_pool( pool_t* pool ); err_t bli_check_sufficient_stack_buf_size( cntx_t* cntx ); err_t bli_check_alignment_is_power_of_two( size_t align_size ); err_t bli_check_alignment_is_mult_of_ptr_size( size_t align_size ); err_t bli_check_object_alias_of( obj_t* a, obj_t* b ); err_t bli_check_valid_arch_id( arch_t id ); err_t bli_check_initialized_gks_cntx( cntx_t** cntx ); err_t bli_check_valid_mc_mod_mult( blksz_t* mc, blksz_t* mr ); err_t bli_check_valid_nc_mod_mult( blksz_t* nc, blksz_t* nr ); err_t bli_check_valid_kc_mod_mult( blksz_t* kc, blksz_t* kr ); blis-0.9.0/frame/base/bli_clock.c000066400000000000000000000110121422157504600165430ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" static double gtod_ref_time_sec = 0.0; double bli_clock( void ) { return bli_clock_helper(); } double bli_clock_min_diff( double time_min, double time_start ) { double time_min_prev; double time_diff; // Save the old value. time_min_prev = time_min; time_diff = bli_clock() - time_start; time_min = bli_fmin( time_min, time_diff ); // Assume that anything: // - under or equal to zero, // - under a nanosecond // is actually garbled due to the clocks being taken too closely together. if ( time_min <= 0.0 ) time_min = time_min_prev; else if ( time_min < 1.0e-9 ) time_min = time_min_prev; return time_min; } #ifdef BLIS_DISABLE_SYSTEM // --- Begin systemless definitions -------------------------------------------- double bli_clock_helper() { return 0.0; } // --- End systemless definitions ---------------------------------------------- #else // --- Begin system definitions ------------------------------------------------ #if BLIS_OS_WINDOWS // --- Begin Windows build definitions ----------------------------------------- double bli_clock_helper() { LARGE_INTEGER clock_freq = {0}; LARGE_INTEGER clock_val; BOOL r_val; r_val = QueryPerformanceFrequency( &clock_freq ); if ( r_val == 0 ) { bli_print_msg( "QueryPerformanceFrequency() failed", __FILE__, __LINE__ ); bli_abort(); } r_val = QueryPerformanceCounter( &clock_val ); if ( r_val == 0 ) { bli_print_msg( "QueryPerformanceCounter() failed", __FILE__, __LINE__ ); bli_abort(); } return ( ( double) clock_val.QuadPart / ( double) clock_freq.QuadPart ); } // --- End Windows build definitions ------------------------------------------- #elif BLIS_OS_OSX // --- Begin OSX build definitions ------------------------------------------- double bli_clock_helper() { mach_timebase_info_data_t timebase; mach_timebase_info( &timebase ); uint64_t nsec = mach_absolute_time(); double the_time = (double) nsec * 1.0e-9 * timebase.numer / timebase.denom; if ( gtod_ref_time_sec == 0.0 ) gtod_ref_time_sec = the_time; return the_time - gtod_ref_time_sec; } // --- End OSX build definitions --------------------------------------------- #else // --- Begin Linux build definitions ------------------------------------------- double bli_clock_helper() { double the_time, norm_sec; struct timespec ts; clock_gettime( CLOCK_MONOTONIC, &ts ); if ( gtod_ref_time_sec == 0.0 ) gtod_ref_time_sec = ( double ) ts.tv_sec; norm_sec = ( double ) ts.tv_sec - gtod_ref_time_sec; the_time = norm_sec + ts.tv_nsec * 1.0e-9; return the_time; } // --- End Linux build definitions --------------------------------------------- #endif // --- End system definitions -------------------------------------------------- #endif blis-0.9.0/frame/base/bli_clock.h000066400000000000000000000034511422157504600165600ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ BLIS_EXPORT_BLIS double bli_clock( void ); BLIS_EXPORT_BLIS double bli_clock_min_diff( double time_min, double time_start ); double bli_clock_helper( void ); blis-0.9.0/frame/base/bli_cntl.c000066400000000000000000000256001422157504600164200ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" cntl_t* bli_cntl_create_node ( rntm_t* rntm, opid_t family, bszid_t bszid, void_fp var_func, void* params, cntl_t* sub_node ) { cntl_t* cntl; mem_t* pack_mem; #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_cntl_create_node(): " ); #endif // Allocate the cntl_t struct. cntl = bli_sba_acquire( rntm, sizeof( cntl_t ) ); bli_cntl_set_family( family, cntl ); bli_cntl_set_bszid( bszid, cntl ); bli_cntl_set_var_func( var_func, cntl ); bli_cntl_set_params( params, cntl ); bli_cntl_set_sub_prenode( NULL, cntl ); bli_cntl_set_sub_node( sub_node, cntl ); // Query the address of the node's packed mem_t entry so we can initialize // key fields (to NULL or 0). // NOTE: This initialization is important, since it allows threads to // discern whether blocks have been acquired from the memory allocator. pack_mem = bli_cntl_pack_mem( cntl ); bli_mem_clear( pack_mem ); return cntl; } void bli_cntl_free_node ( rntm_t* rntm, cntl_t* cntl ) { #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_cntl_free_node(): " ); #endif bli_sba_release( rntm, cntl ); } void bli_cntl_clear_node ( cntl_t* cntl ) { mem_t* pack_mem; // Clear various fields in the control tree. Clearing these fields // actually is not needed, but we do it for debugging/completeness. bli_cntl_set_var_func( NULL, cntl ); bli_cntl_set_params( NULL, cntl ); bli_cntl_set_sub_prenode( NULL, cntl ); bli_cntl_set_sub_node( NULL, cntl ); // Clearing these fields is potentially more important if the control // tree is cached somewhere and reused. pack_mem = bli_cntl_pack_mem( cntl ); bli_mem_clear( pack_mem ); } // ----------------------------------------------------------------------------- void bli_cntl_free ( rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ) { if ( thread != NULL ) bli_cntl_free_w_thrinfo( rntm, cntl, thread ); else bli_cntl_free_wo_thrinfo( rntm, cntl ); } void bli_cntl_free_w_thrinfo ( rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ) { // Base case: simply return when asked to free NULL nodes. if ( cntl == NULL ) return; cntl_t* cntl_sub_prenode = bli_cntl_sub_prenode( cntl ); cntl_t* cntl_sub_node = bli_cntl_sub_node( cntl ); void* cntl_params = bli_cntl_params( cntl ); mem_t* cntl_pack_mem = bli_cntl_pack_mem( cntl ); // Don't immediately dereference the prenode and subnode of the thrinfo_t // node. In some cases, the thrinfo_t tree is not built out all the way, // perhaps because there are more ways of parallelization than micropanels // of data in this dimension, or because the problem is small enough that // there is no gemm subproblem in bli_trsm_blk_var1(). Thus, we start with // NULL values for these variables and only dereference the fields of the // thrinfo_t struct if the thrinfo_t exists (ie: is non-NULL). We will also // have to check the thrinfo_t pointer for NULLness before using it below, // when checking if we need to free the pack_mem field of the cntl_t node // (see below). thrinfo_t* thread_sub_prenode = NULL; thrinfo_t* thread_sub_node = NULL; if ( thread != NULL ) { thread_sub_prenode = bli_thrinfo_sub_prenode( thread ); thread_sub_node = bli_thrinfo_sub_node( thread ); } // Only recurse into prenode branch if it exists. if ( cntl_sub_prenode != NULL ) { // Recursively free all memory associated with the sub-prenode and its // children. bli_cntl_free_w_thrinfo( rntm, cntl_sub_prenode, thread_sub_prenode ); } // Only recurse into the child node if it exists. if ( cntl_sub_node != NULL ) { // Recursively free all memory associated with the sub-node and its // children. bli_cntl_free_w_thrinfo( rntm, cntl_sub_node, thread_sub_node ); } // Free the current node's params field, if it is non-NULL. if ( cntl_params != NULL ) { #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_cntl_free_w_thrinfo(): " ); #endif bli_sba_release( rntm, cntl_params ); } // Release the current node's pack mem_t entry back to the memory // broker from which it originated, but only if the mem_t entry is // allocated, and only if the current thread is chief for its group. // Also note that we don't proceed with either of the above tests if // the thrinfo_t pointer is NULL. (See above for background on when // this can happen.) if ( thread != NULL ) if ( bli_thread_am_ochief( thread ) ) if ( bli_mem_is_alloc( cntl_pack_mem ) ) { #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_cntl_free_w_thrinfo(): releasing mem pool block.\n" ); #endif bli_pba_release( rntm, cntl_pack_mem ); } // Free the current node. bli_cntl_free_node( rntm, cntl ); } void bli_cntl_free_wo_thrinfo ( rntm_t* rntm, cntl_t* cntl ) { // Base case: simply return when asked to free NULL nodes. if ( cntl == NULL ) return; cntl_t* cntl_sub_prenode = bli_cntl_sub_prenode( cntl ); cntl_t* cntl_sub_node = bli_cntl_sub_node( cntl ); void* cntl_params = bli_cntl_params( cntl ); mem_t* cntl_pack_mem = bli_cntl_pack_mem( cntl ); { // Recursively free all memory associated with the sub-prenode and its // children. bli_cntl_free_wo_thrinfo( rntm, cntl_sub_prenode ); } { // Recursively free all memory associated with the sub-node and its // children. bli_cntl_free_wo_thrinfo( rntm, cntl_sub_node ); } // Free the current node's params field, if it is non-NULL. if ( cntl_params != NULL ) { bli_sba_release( rntm, cntl_params ); } // Release the current node's pack mem_t entry back to the memory // broker from which it originated, but only if the mem_t entry is // allocated. if ( bli_mem_is_alloc( cntl_pack_mem ) ) { bli_pba_release( rntm, cntl_pack_mem ); } // Free the current node. bli_cntl_free_node( rntm, cntl ); } // ----------------------------------------------------------------------------- cntl_t* bli_cntl_copy ( rntm_t* rntm, cntl_t* cntl ) { // Make a copy of the current node. Notice that the source node // should NOT have any allocated/cached mem_t entries, and that // bli_cntl_create_node() creates a node with a cleared mem_t // field. cntl_t* cntl_copy = bli_cntl_create_node ( rntm, bli_cntl_family( cntl ), bli_cntl_bszid( cntl ), bli_cntl_var_func( cntl ), NULL, NULL ); // Check the params field of the existing control tree; if it's non-NULL, // copy it. if ( bli_cntl_params( cntl ) != NULL ) { // Detect the size of the params struct by reading the first field // as a uint64_t, and then allocate this many bytes for a new params // struct. uint64_t params_size = bli_cntl_params_size( cntl ); void* params_orig = bli_cntl_params( cntl ); void* params_copy = bli_sba_acquire( rntm, ( size_t )params_size ); // Copy the original params struct to the new memory region. memcpy( params_copy, params_orig, params_size ); // Save the address of the new params struct into the new control // tree node. bli_cntl_set_params( params_copy, cntl_copy ); } // If the sub-prenode exists, copy it recursively. if ( bli_cntl_sub_prenode( cntl ) != NULL ) { cntl_t* sub_prenode_copy = bli_cntl_copy ( rntm, bli_cntl_sub_prenode( cntl ) ); // Save the address of the new sub-node (sub-tree) to the existing // node. bli_cntl_set_sub_prenode( sub_prenode_copy, cntl_copy ); } // If the sub-node exists, copy it recursively. if ( bli_cntl_sub_node( cntl ) != NULL ) { cntl_t* sub_node_copy = bli_cntl_copy ( rntm, bli_cntl_sub_node( cntl ) ); // Save the address of the new sub-node (sub-tree) to the existing // node. bli_cntl_set_sub_node( sub_node_copy, cntl_copy ); } // Return the address of the newly created node. return cntl_copy; } void bli_cntl_mark_family ( opid_t family, cntl_t* cntl ) { // This function sets the family field of all cntl tree nodes that are // children of cntl. It's used by bli_l3_cntl_create_if() after making // a copy of a user-given cntl tree, if the user provided one, to mark // the operation family, which is used to determine appropriate behavior // by various functions when executing the blocked variants. // Set the family of the root node. bli_cntl_set_family( family, cntl ); // Recursively set the family field of the sub-tree rooted at the sub-node, // if it exists. if ( bli_cntl_sub_prenode( cntl ) != NULL ) { bli_cntl_mark_family( family, bli_cntl_sub_prenode( cntl ) ); } // Recursively set the family field of the sub-tree rooted at the prenode, // if it exists. if ( bli_cntl_sub_node( cntl ) != NULL ) { bli_cntl_mark_family( family, bli_cntl_sub_node( cntl ) ); } } // ----------------------------------------------------------------------------- dim_t bli_cntl_calc_num_threads_in ( rntm_t* rntm, cntl_t* cntl ) { dim_t n_threads_in = 1; for ( ; cntl != NULL; cntl = bli_cntl_sub_node( cntl ) ) { bszid_t bszid = bli_cntl_bszid( cntl ); dim_t cur_way; // We assume bszid is in {NC,KC,MC,NR,MR,KR} if it is not // BLIS_NO_PART. if ( bszid != BLIS_NO_PART ) cur_way = bli_rntm_ways_for( bszid, rntm ); else cur_way = 1; n_threads_in *= cur_way; } return n_threads_in; } blis-0.9.0/frame/base/bli_cntl.h000066400000000000000000000125221422157504600164240ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ /* // -- Control tree node definition -- struct cntl_s { // Basic fields (usually required). opid_t family; bszid_t bszid; void_fp var_func; struct cntl_s* sub_prenode; struct cntl_s* sub_node; // Optional fields (needed only by some operations such as packm). // NOTE: first field of params must be a uint64_t containing the size // of the struct. void* params; // Internal fields that track "cached" data. mem_t pack_mem; }; typedef struct cntl_s cntl_t; */ // -- Control tree prototypes -- BLIS_EXPORT_BLIS cntl_t* bli_cntl_create_node ( rntm_t* rntm, opid_t family, bszid_t bszid, void_fp var_func, void* params, cntl_t* sub_node ); BLIS_EXPORT_BLIS void bli_cntl_free_node ( rntm_t* rntm, cntl_t* cntl ); BLIS_EXPORT_BLIS void bli_cntl_clear_node ( cntl_t* cntl ); // ----------------------------------------------------------------------------- BLIS_EXPORT_BLIS void bli_cntl_free ( rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ); BLIS_EXPORT_BLIS void bli_cntl_free_w_thrinfo ( rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ); BLIS_EXPORT_BLIS void bli_cntl_free_wo_thrinfo ( rntm_t* rntm, cntl_t* cntl ); BLIS_EXPORT_BLIS cntl_t* bli_cntl_copy ( rntm_t* rntm, cntl_t* cntl ); BLIS_EXPORT_BLIS void bli_cntl_mark_family ( opid_t family, cntl_t* cntl ); // ----------------------------------------------------------------------------- dim_t bli_cntl_calc_num_threads_in ( rntm_t* rntm, cntl_t* cntl ); // ----------------------------------------------------------------------------- // cntl_t query (fields only) BLIS_INLINE opid_t bli_cntl_family( cntl_t* cntl ) { return cntl->family; } BLIS_INLINE bszid_t bli_cntl_bszid( cntl_t* cntl ) { return cntl->bszid; } BLIS_INLINE void_fp bli_cntl_var_func( cntl_t* cntl ) { return cntl->var_func; } BLIS_INLINE cntl_t* bli_cntl_sub_prenode( cntl_t* cntl ) { return cntl->sub_prenode; } BLIS_INLINE cntl_t* bli_cntl_sub_node( cntl_t* cntl ) { return cntl->sub_node; } BLIS_INLINE void* bli_cntl_params( cntl_t* cntl ) { return cntl->params; } BLIS_INLINE uint64_t bli_cntl_params_size( cntl_t* cntl ) { // The first 64 bytes is always the size of the params structure. return *( ( uint64_t* )(cntl->params) ); } BLIS_INLINE mem_t* bli_cntl_pack_mem( cntl_t* cntl ) { return &(cntl->pack_mem); } // cntl_t query (complex) BLIS_INLINE bool bli_cntl_is_null( cntl_t* cntl ) { return ( bool ) ( cntl == NULL ); } BLIS_INLINE bool bli_cntl_is_leaf( cntl_t* cntl ) { return ( bool ) ( bli_cntl_sub_node( cntl ) == NULL ); } BLIS_INLINE bool bli_cntl_does_part( cntl_t* cntl ) { return ( bool ) ( bli_cntl_bszid( cntl ) != BLIS_NO_PART ); } // cntl_t modification BLIS_INLINE void bli_cntl_set_family( opid_t family, cntl_t* cntl ) { cntl->family = family; } BLIS_INLINE void bli_cntl_set_bszid( bszid_t bszid, cntl_t* cntl ) { cntl->bszid = bszid; } BLIS_INLINE void bli_cntl_set_var_func( void_fp var_func, cntl_t* cntl ) { cntl->var_func = var_func; } BLIS_INLINE void bli_cntl_set_sub_prenode( cntl_t* sub_prenode, cntl_t* cntl ) { cntl->sub_prenode = sub_prenode; } BLIS_INLINE void bli_cntl_set_sub_node( cntl_t* sub_node, cntl_t* cntl ) { cntl->sub_node = sub_node; } BLIS_INLINE void bli_cntl_set_params( void* params, cntl_t* cntl ) { cntl->params = params; } BLIS_INLINE void bli_cntl_set_pack_mem( mem_t* pack_mem, cntl_t* cntl ) { cntl->pack_mem = *pack_mem; } blis-0.9.0/frame/base/bli_cntx.c000066400000000000000000001447071422157504600164460ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_cntx_clear( cntx_t* cntx ) { // Fill the entire cntx_t structure with zeros. memset( ( void* )cntx, 0, sizeof( cntx_t ) ); } // ----------------------------------------------------------------------------- void bli_cntx_set_blkszs( ind_t method, dim_t n_bs, ... ) { // This function can be called from the bli_cntx_init_*() function for // a particular architecture if the kernel developer wishes to use // non-default blocksizes. It should be called after // bli_cntx_init_defaults() so that the context begins with default // blocksizes across all datatypes. /* Example prototypes: void bli_cntx_set_blkszs ( ind_t method = BLIS_NAT, dim_t n_bs, bszid_t bs0_id, blksz_t* blksz0, bszid_t bm0_id, bszid_t bs1_id, blksz_t* blksz1, bszid_t bm1_id, bszid_t bs2_id, blksz_t* blksz2, bszid_t bm2_id, ... cntx_t* cntx ); void bli_cntx_set_blkszs ( ind_t method != BLIS_NAT, dim_t n_bs, bszid_t bs0_id, blksz_t* blksz0, bszid_t bm0_id, dim_t def_scalr0, dim_t max_scalr0, bszid_t bs1_id, blksz_t* blksz1, bszid_t bm1_id, dim_t def_scalr1, dim_t max_scalr1, bszid_t bs2_id, blksz_t* blksz2, bszid_t bm2_id, dim_t def_scalr2, dim_t max_scalr2, ... cntx_t* cntx ); */ va_list args; dim_t i; err_t r_val; // Allocate some temporary local arrays. #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_cntx_set_blkszs(): " ); #endif bszid_t* bszids = bli_malloc_intl( n_bs * sizeof( bszid_t ), &r_val ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_cntx_set_blkszs(): " ); #endif blksz_t** blkszs = bli_malloc_intl( n_bs * sizeof( blksz_t* ), &r_val ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_cntx_set_blkszs(): " ); #endif bszid_t* bmults = bli_malloc_intl( n_bs * sizeof( bszid_t ), &r_val ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_cntx_set_blkszs(): " ); #endif double* dsclrs = bli_malloc_intl( n_bs * sizeof( double ), &r_val ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_cntx_set_blkszs(): " ); #endif double* msclrs = bli_malloc_intl( n_bs * sizeof( double ), &r_val ); // -- Begin variable argument section -- // Initialize variable argument environment. va_start( args, n_bs ); // Handle native and induced method cases separately. if ( method == BLIS_NAT ) { // Process n_bs tuples. for ( i = 0; i < n_bs; ++i ) { // Here, we query the variable argument list for: // - the bszid_t of the blocksize we're about to process, // - the address of the blksz_t object, // - the bszid_t of the multiple we need to associate with // the blksz_t object. bszid_t bs_id = ( bszid_t )va_arg( args, bszid_t ); blksz_t* blksz = ( blksz_t* )va_arg( args, blksz_t* ); bszid_t bm_id = ( bszid_t )va_arg( args, bszid_t ); // Store the values in our temporary arrays. bszids[ i ] = bs_id; blkszs[ i ] = blksz; bmults[ i ] = bm_id; } } else // if induced method execution was indicated { // Process n_bs tuples. for ( i = 0; i < n_bs; ++i ) { // Here, we query the variable argument list for: // - the bszid_t of the blocksize we're about to process, // - the address of the blksz_t object, // - the bszid_t of the multiple we need to associate with // the blksz_t object, // - the scalars we wish to apply to the real blocksizes to // come up with the induced complex blocksizes (for default // and maximum blocksizes). bszid_t bs_id = ( bszid_t )va_arg( args, bszid_t ); blksz_t* blksz = ( blksz_t* )va_arg( args, blksz_t* ); bszid_t bm_id = ( bszid_t )va_arg( args, bszid_t ); double dsclr = ( double )va_arg( args, double ); double msclr = ( double )va_arg( args, double ); // Store the values in our temporary arrays. bszids[ i ] = bs_id; blkszs[ i ] = blksz; bmults[ i ] = bm_id; dsclrs[ i ] = dsclr; msclrs[ i ] = msclr; } } // The last argument should be the context pointer. cntx_t* cntx = ( cntx_t* )va_arg( args, cntx_t* ); // Shutdown variable argument environment and clean up stack. va_end( args ); // -- End variable argument section -- // Save the execution type into the context. bli_cntx_set_method( method, cntx ); // Query the context for the addresses of: // - the blocksize object array // - the blocksize multiple array blksz_t* cntx_blkszs = bli_cntx_blkszs_buf( cntx ); bszid_t* cntx_bmults = bli_cntx_bmults_buf( cntx ); // Now that we have the context address, we want to copy the values // from the temporary buffers into the corresponding buffers in the // context. Notice that the blksz_t* pointers were saved, rather than // the objects themselves, but we copy the contents of the objects // when copying into the context. // Handle native and induced method cases separately. if ( method == BLIS_NAT ) { // Process each blocksize id tuple provided. for ( i = 0; i < n_bs; ++i ) { // Read the current blocksize id, blksz_t* pointer, blocksize // multiple id, and blocksize scalar. bszid_t bs_id = bszids[ i ]; bszid_t bm_id = bmults[ i ]; blksz_t* blksz = blkszs[ i ]; blksz_t* cntx_blksz = &cntx_blkszs[ bs_id ]; // Copy the blksz_t object contents into the appropriate // location within the context's blksz_t array. Do the same // for the blocksize multiple id. //cntx_blkszs[ bs_id ] = *blksz; //bli_blksz_copy( blksz, cntx_blksz ); bli_blksz_copy_if_pos( blksz, cntx_blksz ); // Copy the blocksize multiple id into the context. cntx_bmults[ bs_id ] = bm_id; } } else { // Process each blocksize id tuple provided. for ( i = 0; i < n_bs; ++i ) { // Read the current blocksize id, blksz_t pointer, blocksize // multiple id, and blocksize scalar. bszid_t bs_id = bszids[ i ]; bszid_t bm_id = bmults[ i ]; double dsclr = dsclrs[ i ]; double msclr = msclrs[ i ]; blksz_t* blksz = blkszs[ i ]; blksz_t* cntx_blksz = &cntx_blkszs[ bs_id ]; // Copy the real domain values of the source blksz_t object into // the context, duplicating into the complex domain fields. bli_blksz_copy_dt( BLIS_FLOAT, blksz, BLIS_FLOAT, cntx_blksz ); bli_blksz_copy_dt( BLIS_DOUBLE, blksz, BLIS_DOUBLE, cntx_blksz ); bli_blksz_copy_dt( BLIS_FLOAT, blksz, BLIS_SCOMPLEX, cntx_blksz ); bli_blksz_copy_dt( BLIS_DOUBLE, blksz, BLIS_DCOMPLEX, cntx_blksz ); // If the default blocksize scalar is non-unit, we need to scale // the complex domain default blocksizes. if ( dsclr != 1.0 ) { // Scale the complex domain default blocksize values in the // blocksize object. bli_blksz_scale_def( 1, ( dim_t )dsclr, BLIS_SCOMPLEX, cntx_blksz ); bli_blksz_scale_def( 1, ( dim_t )dsclr, BLIS_DCOMPLEX, cntx_blksz ); } // Similarly, if the maximum blocksize scalar is non-unit, we need // to scale the complex domain maximum blocksizes. if ( msclr != 1.0 ) { // Scale the complex domain maximum blocksize values in the // blocksize object. bli_blksz_scale_max( 1, ( dim_t )msclr, BLIS_SCOMPLEX, cntx_blksz ); bli_blksz_scale_max( 1, ( dim_t )msclr, BLIS_DCOMPLEX, cntx_blksz ); } // Copy the blocksize multiple id into the context. cntx_bmults[ bs_id ] = bm_id; } } // Free the temporary local arrays. #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_cntx_set_blkszs(): " ); #endif bli_free_intl( blkszs ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_cntx_set_blkszs(): " ); #endif bli_free_intl( bszids ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_cntx_set_blkszs(): " ); #endif bli_free_intl( bmults ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_cntx_set_blkszs(): " ); #endif bli_free_intl( dsclrs ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_cntx_set_blkszs(): " ); #endif bli_free_intl( msclrs ); } // ----------------------------------------------------------------------------- void bli_cntx_set_ind_blkszs( ind_t method, num_t dt, dim_t n_bs, ... ) { /* Example prototypes: void bli_gks_cntx_set_ind_blkszs ( ind_t method != BLIS_NAT, num_t dt, dim_t n_bs, bszid_t bs0_id, dim_t def_scalr0, dim_t max_scalr0, bszid_t bs1_id, dim_t def_scalr1, dim_t max_scalr1, bszid_t bs2_id, dim_t def_scalr2, dim_t max_scalr2, ... cntx_t* cntx ); NOTE: This function modifies an existing context that is presumed to have been initialized for native execution. */ va_list args; dim_t i; err_t r_val; // Project the given datatype to the real domain. This will be used later on. num_t dt_real = bli_dt_proj_to_real( dt ); // Return early if called with BLIS_NAT. if ( method == BLIS_NAT ) return; // Allocate some temporary local arrays. #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_cntx_set_ind_blkszs(): " ); #endif bszid_t* bszids = bli_malloc_intl( n_bs * sizeof( bszid_t ), &r_val ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_cntx_set_ind_blkszs(): " ); #endif double* dsclrs = bli_malloc_intl( n_bs * sizeof( double ), &r_val ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_cntx_set_ind_blkszs(): " ); #endif double* msclrs = bli_malloc_intl( n_bs * sizeof( double ), &r_val ); // -- Begin variable argument section -- // Initialize variable argument environment. va_start( args, n_bs ); { // Process n_bs tuples. for ( i = 0; i < n_bs; ++i ) { // Here, we query the variable argument list for: // - the bszid_t of the blocksize we're about to process, // - the scalars we wish to apply to the real blocksizes to // come up with the induced complex blocksizes (for default // and maximum blocksizes). bszid_t bs_id = ( bszid_t )va_arg( args, bszid_t ); double dsclr = ( double )va_arg( args, double ); double msclr = ( double )va_arg( args, double ); // Store the values in our temporary arrays. bszids[ i ] = bs_id; dsclrs[ i ] = dsclr; msclrs[ i ] = msclr; } } // The last argument should be the context pointer. cntx_t* cntx = ( cntx_t* )va_arg( args, cntx_t* ); // Shutdown variable argument environment and clean up stack. va_end( args ); // -- End variable argument section -- // Save the execution type into the context. bli_cntx_set_method( method, cntx ); // Now that we have the context address, we want to copy the values // from the temporary buffers into the corresponding buffers in the // context. { // Process each blocksize id tuple provided. for ( i = 0; i < n_bs; ++i ) { // Read the current blocksize id, blocksize multiple id, // and blocksize scalar. bszid_t bs_id = bszids[ i ]; double dsclr = dsclrs[ i ]; double msclr = msclrs[ i ]; //blksz_t* cntx_blksz = &cntx_blkszs[ bs_id ]; // Query the context for the blksz_t object assoicated with the // current blocksize id, and also query the object corresponding // to the blocksize multiple. blksz_t* cntx_blksz = bli_cntx_get_blksz( bs_id, cntx ); // Copy the real domain value of the blksz_t object into the // corresponding complex domain slot of the same object. bli_blksz_copy_dt( dt_real, cntx_blksz, dt, cntx_blksz ); // If the default blocksize scalar is non-unit, we need to scale // the complex domain default blocksizes. if ( dsclr != 1.0 ) { // Scale the default blocksize value corresponding to the given // datatype. bli_blksz_scale_def( 1, ( dim_t )dsclr, dt, cntx_blksz ); } // Similarly, if the maximum blocksize scalar is non-unit, we need // to scale the complex domain maximum blocksizes. if ( msclr != 1.0 ) { // Scale the maximum blocksize value corresponding to the given // datatype. bli_blksz_scale_max( 1, ( dim_t )msclr, dt, cntx_blksz ); } } } // Free the temporary local arrays. #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_cntx_set_ind_blkszs(): " ); #endif bli_free_intl( bszids ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_cntx_set_ind_blkszs(): " ); #endif bli_free_intl( dsclrs ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_cntx_set_ind_blkszs(): " ); #endif bli_free_intl( msclrs ); } // ----------------------------------------------------------------------------- void bli_cntx_set_l3_nat_ukrs( dim_t n_ukrs, ... ) { // This function can be called from the bli_cntx_init_*() function for // a particular architecture if the kernel developer wishes to use // non-default level-3 microkernels. It should be called after // bli_cntx_init_defaults() so that the context begins with default // microkernels across all datatypes. /* Example prototypes: void bli_cntx_set_l3_nat_ukrs ( dim_t n_ukrs, l3ukr_t ukr0_id, num_t dt0, void_fp ukr0_fp, bool pref0, l3ukr_t ukr1_id, num_t dt1, void_fp ukr1_fp, bool pref1, l3ukr_t ukr2_id, num_t dt2, void_fp ukr2_fp, bool pref2, ... cntx_t* cntx ); */ va_list args; dim_t i; err_t r_val; // Allocate some temporary local arrays. #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_cntx_set_l3_nat_ukrs(): " ); #endif l3ukr_t* ukr_ids = bli_malloc_intl( n_ukrs * sizeof( l3ukr_t ), &r_val ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_cntx_set_l3_nat_ukrs(): " ); #endif num_t* ukr_dts = bli_malloc_intl( n_ukrs * sizeof( num_t ), &r_val ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_cntx_set_l3_nat_ukrs(): " ); #endif void_fp* ukr_fps = bli_malloc_intl( n_ukrs * sizeof( void_fp ), &r_val ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_cntx_set_l3_nat_ukrs(): " ); #endif bool* ukr_prefs = bli_malloc_intl( n_ukrs * sizeof( bool ), &r_val ); // -- Begin variable argument section -- // Initialize variable argument environment. va_start( args, n_ukrs ); // Process n_ukrs tuples. for ( i = 0; i < n_ukrs; ++i ) { // Here, we query the variable argument list for: // - the l3ukr_t of the kernel we're about to process, // - the datatype of the kernel, // - the kernel function pointer, and // - the kernel function storage preference // that we need to store to the context. // NOTE: Though bool_t is no longer used, the following comment is // being kept for historical reasons. // The type that we pass into the va_arg() macro for the ukr // preference matters. Using 'bool_t' may cause breakage on 64-bit // systems that define int as 32 bits and long int and pointers as // 64 bits. The problem is that TRUE or FALSE are defined as 1 and // 0, respectively, and when "passed" into the variadic function // they come with no contextual typecast. Thus, default rules of // argument promotion kick in to treat these integer literals as // being of type int. Thus, we need to let va_arg() treat the TRUE // or FALSE value as an int, even if we cast it to and store it // within a bool_t afterwards. const l3ukr_t ukr_id = ( l3ukr_t )va_arg( args, l3ukr_t ); const num_t ukr_dt = ( num_t )va_arg( args, num_t ); void_fp ukr_fp = ( void_fp )va_arg( args, void_fp ); const bool ukr_pref = ( bool )va_arg( args, int ); // Store the values in our temporary arrays. ukr_ids[ i ] = ukr_id; ukr_dts[ i ] = ukr_dt; ukr_fps[ i ] = ukr_fp; ukr_prefs[ i ] = ukr_pref; } // The last argument should be the context pointer. cntx_t* cntx = ( cntx_t* )va_arg( args, cntx_t* ); // Shutdown variable argument environment and clean up stack. va_end( args ); // -- End variable argument section -- // Query the context for the addresses of: // - the l3 virtual ukernel func_t array // - the l3 native ukernel func_t array // - the l3 native ukernel preferences array func_t* cntx_l3_vir_ukrs = bli_cntx_l3_vir_ukrs_buf( cntx ); func_t* cntx_l3_nat_ukrs = bli_cntx_l3_nat_ukrs_buf( cntx ); mbool_t* cntx_l3_nat_ukrs_prefs = bli_cntx_l3_nat_ukrs_prefs_buf( cntx ); // Now that we have the context address, we want to copy the values // from the temporary buffers into the corresponding buffers in the // context. // Process each blocksize id tuple provided. for ( i = 0; i < n_ukrs; ++i ) { // Read the current ukernel id, ukernel datatype, ukernel function // pointer, and ukernel preference. const l3ukr_t ukr_id = ukr_ids[ i ]; const num_t ukr_dt = ukr_dts[ i ]; void_fp ukr_fp = ukr_fps[ i ]; const bool ukr_pref = ukr_prefs[ i ]; // Index into the func_t and mbool_t for the current kernel id // being processed. func_t* vukrs = &cntx_l3_vir_ukrs[ ukr_id ]; func_t* ukrs = &cntx_l3_nat_ukrs[ ukr_id ]; mbool_t* prefs = &cntx_l3_nat_ukrs_prefs[ ukr_id ]; // Store the ukernel function pointer and preference values into // the context. Notice that we redundantly store the native // ukernel address in both the native and virtual ukernel slots // in the context. This is standard practice when creating a // native context. (Induced method contexts will overwrite the // virtual function pointer with the address of the appropriate // virtual ukernel.) bli_func_set_dt( ukr_fp, ukr_dt, vukrs ); bli_func_set_dt( ukr_fp, ukr_dt, ukrs ); bli_mbool_set_dt( ukr_pref, ukr_dt, prefs ); } // Free the temporary local arrays. #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_cntx_set_l3_nat_ukrs(): " ); #endif bli_free_intl( ukr_ids ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_cntx_set_l3_nat_ukrs(): " ); #endif bli_free_intl( ukr_dts ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_cntx_set_l3_nat_ukrs(): " ); #endif bli_free_intl( ukr_fps ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_cntx_set_l3_nat_ukrs(): " ); #endif bli_free_intl( ukr_prefs ); } // ----------------------------------------------------------------------------- void bli_cntx_set_l3_vir_ukrs( dim_t n_ukrs, ... ) { // This function can be called from the bli_cntx_init_*() function for // a particular architecture if the kernel developer wishes to use // non-default level-3 virtual microkernels. It should be called after // bli_cntx_init_defaults() so that the context begins with default // microkernels across all datatypes. /* Example prototypes: void bli_cntx_set_l3_vir_ukrs ( dim_t n_ukrs, l3ukr_t ukr0_id, num_t dt0, void_fp ukr0_fp, l3ukr_t ukr1_id, num_t dt1, void_fp ukr1_fp, l3ukr_t ukr2_id, num_t dt2, void_fp ukr2_fp, ... cntx_t* cntx ); */ va_list args; dim_t i; err_t r_val; // Allocate some temporary local arrays. #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_cntx_set_l3_vir_ukrs(): " ); #endif l3ukr_t* ukr_ids = bli_malloc_intl( n_ukrs * sizeof( l3ukr_t ), &r_val ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_cntx_set_l3_vir_ukrs(): " ); #endif num_t* ukr_dts = bli_malloc_intl( n_ukrs * sizeof( num_t ), &r_val ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_cntx_set_l3_vir_ukrs(): " ); #endif void_fp* ukr_fps = bli_malloc_intl( n_ukrs * sizeof( void_fp ), &r_val ); // -- Begin variable argument section -- // Initialize variable argument environment. va_start( args, n_ukrs ); // Process n_ukrs tuples. for ( i = 0; i < n_ukrs; ++i ) { // Here, we query the variable argument list for: // - the l3ukr_t of the kernel we're about to process, // - the datatype of the kernel, and // - the kernel function pointer. // that we need to store to the context. const l3ukr_t ukr_id = ( l3ukr_t )va_arg( args, l3ukr_t ); const num_t ukr_dt = ( num_t )va_arg( args, num_t ); void_fp ukr_fp = ( void_fp )va_arg( args, void_fp ); // Store the values in our temporary arrays. ukr_ids[ i ] = ukr_id; ukr_dts[ i ] = ukr_dt; ukr_fps[ i ] = ukr_fp; } // The last argument should be the context pointer. cntx_t* cntx = ( cntx_t* )va_arg( args, cntx_t* ); // Shutdown variable argument environment and clean up stack. va_end( args ); // -- End variable argument section -- // Query the context for the addresses of: // - the l3 virtual ukernel func_t array func_t* cntx_l3_vir_ukrs = bli_cntx_l3_vir_ukrs_buf( cntx ); // Now that we have the context address, we want to copy the values // from the temporary buffers into the corresponding buffers in the // context. // Process each blocksize id tuple provided. for ( i = 0; i < n_ukrs; ++i ) { // Read the current ukernel id, ukernel datatype, ukernel function // pointer, and ukernel preference. const l3ukr_t ukr_id = ukr_ids[ i ]; const num_t ukr_dt = ukr_dts[ i ]; void_fp ukr_fp = ukr_fps[ i ]; // Index into the func_t and mbool_t for the current kernel id // being processed. func_t* vukrs = &cntx_l3_vir_ukrs[ ukr_id ]; // Store the ukernel function pointer and preference values into // the context. Notice that we redundantly store the native // ukernel address in both the native and virtual ukernel slots // in the context. This is standard practice when creating a // native context. (Induced method contexts will overwrite the // virtual function pointer with the address of the appropriate // virtual ukernel.) bli_func_set_dt( ukr_fp, ukr_dt, vukrs ); } // Free the temporary local arrays. #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_cntx_set_l3_vir_ukrs(): " ); #endif bli_free_intl( ukr_ids ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_cntx_set_l3_vir_ukrs(): " ); #endif bli_free_intl( ukr_dts ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_cntx_set_l3_vir_ukrs(): " ); #endif bli_free_intl( ukr_fps ); } // ----------------------------------------------------------------------------- void bli_cntx_set_l3_sup_thresh( dim_t n_thresh, ... ) { // This function can be called from the bli_cntx_init_*() function for // a particular architecture if the kernel developer wishes to use // non-default thresholds for small/unpacked matrix handling. It should // be called after bli_cntx_init_defaults() so that the context begins // with default thresholds. /* Example prototypes: void bli_cntx_set_l3_sup_thresh ( dim_t n_thresh, threshid_t th0_id, blksz_t* blksz0, threshid_t th1_id, blksz_t* blksz1, ... cntx_t* cntx ); */ va_list args; dim_t i; err_t r_val; // Allocate some temporary local arrays. #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_cntx_set_l3_sup_thresh(): " ); #endif threshid_t* threshids = bli_malloc_intl( n_thresh * sizeof( threshid_t ), &r_val ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_cntx_set_l3_sup_thresh(): " ); #endif blksz_t** threshs = bli_malloc_intl( n_thresh * sizeof( blksz_t* ), &r_val ); // -- Begin variable argument section -- // Initialize variable argument environment. va_start( args, n_thresh ); // Process n_thresh tuples. for ( i = 0; i < n_thresh; ++i ) { // Here, we query the variable argument list for: // - the threshid_t of the threshold we're about to process, // - the address of the blksz_t object, threshid_t th_id = ( threshid_t )va_arg( args, threshid_t ); blksz_t* thresh = ( blksz_t* )va_arg( args, blksz_t* ); // Store the values in our temporary arrays. threshids[ i ] = th_id; threshs[ i ] = thresh; } // The last argument should be the context pointer. cntx_t* cntx = ( cntx_t* )va_arg( args, cntx_t* ); // Shutdown variable argument environment and clean up stack. va_end( args ); // -- End variable argument section -- // Query the context for the addresses of: // - the threshold array blksz_t* cntx_threshs = bli_cntx_l3_sup_thresh_buf( cntx ); // Now that we have the context address, we want to copy the values // from the temporary buffers into the corresponding buffers in the // context. Notice that the blksz_t* pointers were saved, rather than // the objects themselves, but we copy the contents of the objects // when copying into the context. // Process each blocksize id tuple provided. for ( i = 0; i < n_thresh; ++i ) { // Read the current blocksize id, blksz_t* pointer, blocksize // multiple id, and blocksize scalar. threshid_t th_id = threshids[ i ]; blksz_t* thresh = threshs[ i ]; blksz_t* cntx_thresh = &cntx_threshs[ th_id ]; // Copy the blksz_t object contents into the appropriate // location within the context's blksz_t array. //cntx_threshs[ th_id ] = *thresh; //bli_blksz_copy( thresh, cntx_thresh ); bli_blksz_copy_if_pos( thresh, cntx_thresh ); } // Free the temporary local arrays. #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_cntx_set_l3_sup_thresh(): " ); #endif bli_free_intl( threshs ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_cntx_set_l3_sup_thresh(): " ); #endif bli_free_intl( threshids ); } // ----------------------------------------------------------------------------- void bli_cntx_set_l3_sup_handlers( dim_t n_ops, ... ) { // This function can be called from the bli_cntx_init_*() function for // a particular architecture if the kernel developer wishes to use // non-default level-3 operation handler for small/unpacked matrices. It // should be called after bli_cntx_init_defaults() so that the context // begins with default sup handlers across all datatypes. /* Example prototypes: void bli_cntx_set_l3_sup_handlers ( dim_t n_ops, opid_t op0_id, void* handler0_fp, opid_t op1_id, void* handler1_fp, opid_t op2_id, void* handler2_fp, ... cntx_t* cntx ); */ va_list args; dim_t i; err_t r_val; // Allocate some temporary local arrays. #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_cntx_set_l3_sup_handlers(): " ); #endif opid_t* op_ids = bli_malloc_intl( n_ops * sizeof( opid_t ), &r_val ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_cntx_set_l3_sup_handlers(): " ); #endif void** op_fps = bli_malloc_intl( n_ops * sizeof( void* ), &r_val ); // -- Begin variable argument section -- // Initialize variable argument environment. va_start( args, n_ops ); // Process n_ukrs tuples. for ( i = 0; i < n_ops; ++i ) { // Here, we query the variable argument list for: // - the opid_t of the operation we're about to process, // - the sup handler function pointer // that we need to store to the context. const opid_t op_id = ( opid_t )va_arg( args, opid_t ); void* op_fp = ( void* )va_arg( args, void* ); // Store the values in our temporary arrays. op_ids[ i ] = op_id; op_fps[ i ] = op_fp; } // The last argument should be the context pointer. cntx_t* cntx = ( cntx_t* )va_arg( args, cntx_t* ); // Shutdown variable argument environment and clean up stack. va_end( args ); // -- End variable argument section -- // Query the context for the addresses of: // - the l3 small/unpacked handlers array void** cntx_l3_sup_handlers = bli_cntx_l3_sup_handlers_buf( cntx ); // Now that we have the context address, we want to copy the values // from the temporary buffers into the corresponding buffers in the // context. // Process each operation id tuple provided. for ( i = 0; i < n_ops; ++i ) { // Read the current operation id and handler function pointer. const opid_t op_id = op_ids[ i ]; void* op_fp = op_fps[ i ]; // Store the sup handler function pointer into the slot for the // specified operation id. cntx_l3_sup_handlers[ op_id ] = op_fp; } // Free the temporary local arrays. #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_cntx_set_l3_sup_handlers(): " ); #endif bli_free_intl( op_ids ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_cntx_set_l3_sup_handlers(): " ); #endif bli_free_intl( op_fps ); } // ----------------------------------------------------------------------------- void bli_cntx_set_l3_sup_blkszs( dim_t n_bs, ... ) { // This function can be called from the bli_cntx_init_*() function for // a particular architecture if the kernel developer wishes to use // non-default l3 sup blocksizes. It should be called after // bli_cntx_init_defaults() so that the context begins with default // blocksizes across all datatypes. /* Example prototypes: void bli_cntx_set_blkszs ( dim_t n_bs, bszid_t bs0_id, blksz_t* blksz0, bszid_t bs1_id, blksz_t* blksz1, bszid_t bs2_id, blksz_t* blksz2, ... cntx_t* cntx ); */ va_list args; dim_t i; err_t r_val; // Allocate some temporary local arrays. #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_cntx_set_blkszs(): " ); #endif bszid_t* bszids = bli_malloc_intl( n_bs * sizeof( bszid_t ), &r_val ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_cntx_set_blkszs(): " ); #endif blksz_t** blkszs = bli_malloc_intl( n_bs * sizeof( blksz_t* ), &r_val ); // -- Begin variable argument section -- // Initialize variable argument environment. va_start( args, n_bs ); // Process n_bs tuples. for ( i = 0; i < n_bs; ++i ) { // Here, we query the variable argument list for: // - the bszid_t of the blocksize we're about to process, // - the address of the blksz_t object. bszid_t bs_id = ( bszid_t )va_arg( args, bszid_t ); blksz_t* blksz = ( blksz_t* )va_arg( args, blksz_t* ); // Store the values in our temporary arrays. bszids[ i ] = bs_id; blkszs[ i ] = blksz; } // The last argument should be the context pointer. cntx_t* cntx = ( cntx_t* )va_arg( args, cntx_t* ); // Shutdown variable argument environment and clean up stack. va_end( args ); // -- End variable argument section -- // Query the context for the addresses of: // - the blocksize object array blksz_t* cntx_l3_sup_blkszs = bli_cntx_l3_sup_blkszs_buf( cntx ); // Now that we have the context address, we want to copy the values // from the temporary buffers into the corresponding buffers in the // context. Notice that the blksz_t* pointers were saved, rather than // the objects themselves, but we copy the contents of the objects // when copying into the context. // Process each blocksize id tuple provided. for ( i = 0; i < n_bs; ++i ) { // Read the current blocksize id, blksz_t* pointer, blocksize // multiple id, and blocksize scalar. bszid_t bs_id = bszids[ i ]; blksz_t* blksz = blkszs[ i ]; blksz_t* cntx_l3_sup_blksz = &cntx_l3_sup_blkszs[ bs_id ]; // Copy the blksz_t object contents into the appropriate // location within the context's blksz_t array. //cntx_l3_sup_blkszs[ bs_id ] = *blksz; //bli_blksz_copy( blksz, cntx_l3_sup_blksz ); bli_blksz_copy_if_pos( blksz, cntx_l3_sup_blksz ); } // Free the temporary local arrays. #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_cntx_set_blkszs(): " ); #endif bli_free_intl( blkszs ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_cntx_set_blkszs(): " ); #endif bli_free_intl( bszids ); } // ----------------------------------------------------------------------------- void bli_cntx_set_l3_sup_kers( dim_t n_ukrs, ... ) { // This function can be called from the bli_cntx_init_*() function for // a particular architecture if the kernel developer wishes to use // non-default level-3 microkernels for small/unpacked matrices. It // should be called after bli_cntx_init_defaults() so that the context // begins with default sup micro/millikernels across all datatypes. /* Example prototypes: void bli_cntx_set_l3_sup_kers ( dim_t n_ukrs, stor3_t stor_id0, num_t dt0, void* ukr0_fp, bool pref0, stor3_t stor_id1, num_t dt1, void* ukr1_fp, bool pref1, stor3_t stor_id2, num_t dt2, void* ukr2_fp, bool pref2, ... cntx_t* cntx ); */ va_list args; dim_t i; err_t r_val; // Allocate some temporary local arrays. #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_cntx_set_l3_sup_kers(): " ); #endif stor3_t* st3_ids = bli_malloc_intl( n_ukrs * sizeof( stor3_t ), &r_val ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_cntx_set_l3_sup_kers(): " ); #endif num_t* ukr_dts = bli_malloc_intl( n_ukrs * sizeof( num_t ), &r_val ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_cntx_set_l3_sup_kers(): " ); #endif void** ukr_fps = bli_malloc_intl( n_ukrs * sizeof( void* ), &r_val ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_cntx_set_l3_sup_kers(): " ); #endif bool* ukr_prefs = bli_malloc_intl( n_ukrs * sizeof( bool ), &r_val ); // -- Begin variable argument section -- // Initialize variable argument environment. va_start( args, n_ukrs ); // Process n_ukrs tuples. for ( i = 0; i < n_ukrs; ++i ) { // Here, we query the variable argument list for: // - the stor3_t storage case being assigned to the kernel we're // about to process, // - the datatype of the kernel, // - the kernel function pointer, and // - the kernel function storage preference // that we need to store to the context. const stor3_t st3_id = ( stor3_t )va_arg( args, stor3_t ); const num_t ukr_dt = ( num_t )va_arg( args, num_t ); void* ukr_fp = ( void* )va_arg( args, void* ); const bool ukr_pref = ( bool )va_arg( args, int ); // Store the values in our temporary arrays. st3_ids[ i ] = st3_id; ukr_dts[ i ] = ukr_dt; ukr_fps[ i ] = ukr_fp; ukr_prefs[ i ] = ukr_pref; } // The last argument should be the context pointer. cntx_t* cntx = ( cntx_t* )va_arg( args, cntx_t* ); // Shutdown variable argument environment and clean up stack. va_end( args ); // -- End variable argument section -- // Query the context for the addresses of: // - the l3 small/unpacked ukernel func_t array // - the l3 small/unpacked ukernel preferences array func_t* cntx_l3_sup_kers = bli_cntx_l3_sup_kers_buf( cntx ); mbool_t* cntx_l3_sup_kers_prefs = bli_cntx_l3_sup_kers_prefs_buf( cntx ); // Now that we have the context address, we want to copy the values // from the temporary buffers into the corresponding buffers in the // context. #if 0 dim_t sup_map[ BLIS_NUM_LEVEL3_SUP_UKRS ][2]; // Create the small/unpacked ukernel mappings: // - rv -> rrr 0, rcr 2 // - rg -> rrc 1, rcc 3 // - cv -> ccr 6, ccc 7 // - cg -> crr 4, crc 5 // - rd -> rrc 1 // - cd -> crc 5 // - rc -> rcc 3 // - cr -> crr 4 // - gx -> xxx 8 // NOTE: We only need to set one slot in the context l3_sup_kers array // for the general-stride/generic ukernel type, but since the loop below // needs to be set up to set two slots to accommodate the RV, RG, CV, and // CG, ukernel types, we will just be okay with the GX ukernel being set // redundantly. (The RD, CD, CR, and RC ukernel types are set redundantly // for the same reason.) sup_map[ BLIS_GEMMSUP_RV_UKR ][0] = BLIS_RRR; sup_map[ BLIS_GEMMSUP_RV_UKR ][1] = BLIS_RCR; sup_map[ BLIS_GEMMSUP_RG_UKR ][0] = BLIS_RRC; sup_map[ BLIS_GEMMSUP_RG_UKR ][1] = BLIS_RCC; sup_map[ BLIS_GEMMSUP_CV_UKR ][0] = BLIS_CCR; sup_map[ BLIS_GEMMSUP_CV_UKR ][1] = BLIS_CCC; sup_map[ BLIS_GEMMSUP_CG_UKR ][0] = BLIS_CRR; sup_map[ BLIS_GEMMSUP_CG_UKR ][1] = BLIS_CRC; sup_map[ BLIS_GEMMSUP_RD_UKR ][0] = BLIS_RRC; sup_map[ BLIS_GEMMSUP_RD_UKR ][1] = BLIS_RRC; sup_map[ BLIS_GEMMSUP_CD_UKR ][0] = BLIS_CRC; sup_map[ BLIS_GEMMSUP_CD_UKR ][1] = BLIS_CRC; sup_map[ BLIS_GEMMSUP_RC_UKR ][0] = BLIS_RCC; sup_map[ BLIS_GEMMSUP_RC_UKR ][1] = BLIS_RCC; sup_map[ BLIS_GEMMSUP_CR_UKR ][0] = BLIS_CRR; sup_map[ BLIS_GEMMSUP_CR_UKR ][1] = BLIS_CRR; sup_map[ BLIS_GEMMSUP_GX_UKR ][0] = BLIS_XXX; sup_map[ BLIS_GEMMSUP_GX_UKR ][1] = BLIS_XXX; #endif // Process each blocksize id tuple provided. for ( i = 0; i < n_ukrs; ++i ) { // Read the current stor3_t id, ukernel datatype, ukernel function // pointer, and ukernel preference. const stor3_t st3_id = st3_ids[ i ]; const num_t ukr_dt = ukr_dts[ i ]; void* ukr_fp = ukr_fps[ i ]; const bool ukr_pref = ukr_prefs[ i ]; // Index to the func_t and mbool_t for the current stor3_t id // being processed. func_t* ukrs = &cntx_l3_sup_kers[ st3_id ]; mbool_t* prefs = &cntx_l3_sup_kers_prefs[ st3_id ]; // Store the ukernel function pointer and preference values into // the stor3_t location in the context. bli_func_set_dt( ukr_fp, ukr_dt, ukrs ); bli_mbool_set_dt( ukr_pref, ukr_dt, prefs ); } // Free the temporary local arrays. #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_cntx_set_l3_sup_kers(): " ); #endif bli_free_intl( st3_ids ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_cntx_set_l3_sup_kers(): " ); #endif bli_free_intl( ukr_dts ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_cntx_set_l3_sup_kers(): " ); #endif bli_free_intl( ukr_fps ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_cntx_set_l3_sup_kers(): " ); #endif bli_free_intl( ukr_prefs ); } // ----------------------------------------------------------------------------- void bli_cntx_set_l1f_kers( dim_t n_kers, ... ) { // This function can be called from the bli_cntx_init_*() function for // a particular architecture if the kernel developer wishes to use // non-default level-1f kernels. It should be called after // bli_cntx_init_defaults() so that the context begins with default l1f // kernels across all datatypes. /* Example prototypes: void bli_cntx_set_l1f_kers ( dim_t n_ukrs, l1fkr_t ker0_id, num_t ker0_dt, void_fp ker0_fp, l1fkr_t ker1_id, num_t ker1_dt, void_fp ker1_fp, l1fkr_t ker2_id, num_t ker2_dt, void_fp ker2_fp, ... cntx_t* cntx ); */ va_list args; dim_t i; err_t r_val; // Allocate some temporary local arrays. #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_cntx_set_l1f_kers(): " ); #endif l1fkr_t* ker_ids = bli_malloc_intl( n_kers * sizeof( l1fkr_t ), &r_val ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_cntx_set_l1f_kers(): " ); #endif num_t* ker_dts = bli_malloc_intl( n_kers * sizeof( num_t ), &r_val ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_cntx_set_l1f_kers(): " ); #endif void_fp* ker_fps = bli_malloc_intl( n_kers * sizeof( void_fp ), &r_val ); // -- Begin variable argument section -- // Initialize variable argument environment. va_start( args, n_kers ); // Process n_kers tuples. for ( i = 0; i < n_kers; ++i ) { // Here, we query the variable argument list for: // - the l1fkr_t of the kernel we're about to process, // - the datatype of the kernel, and // - the kernel function pointer // that we need to store to the context. const l1fkr_t ker_id = ( l1fkr_t )va_arg( args, l1fkr_t ); const num_t ker_dt = ( num_t )va_arg( args, num_t ); void_fp ker_fp = ( void_fp )va_arg( args, void_fp ); // Store the values in our temporary arrays. ker_ids[ i ] = ker_id; ker_dts[ i ] = ker_dt; ker_fps[ i ] = ker_fp; } // The last argument should be the context pointer. cntx_t* cntx = ( cntx_t* )va_arg( args, cntx_t* ); // Shutdown variable argument environment and clean up stack. va_end( args ); // -- End variable argument section -- // Query the context for the address of: // - the level-1f kernels func_t array func_t* cntx_l1f_kers = bli_cntx_l1f_kers_buf( cntx ); // Now that we have the context address, we want to copy the values // from the temporary buffers into the corresponding buffers in the // context. // Process each blocksize id tuple provided. for ( i = 0; i < n_kers; ++i ) { // Read the current kernel id, kernel datatype, and kernel function // pointer. const l1fkr_t ker_id = ker_ids[ i ]; const num_t ker_dt = ker_dts[ i ]; void_fp ker_fp = ker_fps[ i ]; // Index into the func_t and mbool_t for the current kernel id // being processed. func_t* kers = &cntx_l1f_kers[ ker_id ]; // Store the ukernel function pointer and preference values into // the context. bli_func_set_dt( ker_fp, ker_dt, kers ); } // Free the temporary local arrays. #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_cntx_set_l1f_kers(): " ); #endif bli_free_intl( ker_ids ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_cntx_set_l1f_kers(): " ); #endif bli_free_intl( ker_dts ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_cntx_set_l1f_kers(): " ); #endif bli_free_intl( ker_fps ); } // ----------------------------------------------------------------------------- void bli_cntx_set_l1v_kers( dim_t n_kers, ... ) { // This function can be called from the bli_cntx_init_*() function for // a particular architecture if the kernel developer wishes to use // non-default level-1v kernels. It should be called after // bli_cntx_init_defaults() so that the context begins with default l1v // kernels across all datatypes. /* Example prototypes: void bli_cntx_set_l1v_kers ( dim_t n_ukrs, l1vkr_t ker0_id, num_t ker0_dt, void_fp ker0_fp, l1vkr_t ker1_id, num_t ker1_dt, void_fp ker1_fp, l1vkr_t ker2_id, num_t ker2_dt, void_fp ker2_fp, ... cntx_t* cntx ); */ va_list args; dim_t i; err_t r_val; // Allocate some temporary local arrays. #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_cntx_set_l1v_kers(): " ); #endif l1vkr_t* ker_ids = bli_malloc_intl( n_kers * sizeof( l1vkr_t ), &r_val ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_cntx_set_l1v_kers(): " ); #endif num_t* ker_dts = bli_malloc_intl( n_kers * sizeof( num_t ), &r_val ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_cntx_set_l1v_kers(): " ); #endif void_fp* ker_fps = bli_malloc_intl( n_kers * sizeof( void_fp ), &r_val ); // -- Begin variable argument section -- // Initialize variable argument environment. va_start( args, n_kers ); // Process n_kers tuples. for ( i = 0; i < n_kers; ++i ) { // Here, we query the variable argument list for: // - the l1vkr_t of the kernel we're about to process, // - the datatype of the kernel, and // - the kernel function pointer // that we need to store to the context. const l1vkr_t ker_id = ( l1vkr_t )va_arg( args, l1vkr_t ); const num_t ker_dt = ( num_t )va_arg( args, num_t ); void_fp ker_fp = ( void_fp )va_arg( args, void_fp ); // Store the values in our temporary arrays. ker_ids[ i ] = ker_id; ker_dts[ i ] = ker_dt; ker_fps[ i ] = ker_fp; } // The last argument should be the context pointer. cntx_t* cntx = ( cntx_t* )va_arg( args, cntx_t* ); // Shutdown variable argument environment and clean up stack. va_end( args ); // -- End variable argument section -- // Query the context for the address of: // - the level-1v kernels func_t array func_t* cntx_l1v_kers = bli_cntx_l1v_kers_buf( cntx ); // Now that we have the context address, we want to copy the values // from the temporary buffers into the corresponding buffers in the // context. // Process each blocksize id tuple provided. for ( i = 0; i < n_kers; ++i ) { // Read the current kernel id, kernel datatype, and kernel function // pointer. const l1vkr_t ker_id = ker_ids[ i ]; const num_t ker_dt = ker_dts[ i ]; void_fp ker_fp = ker_fps[ i ]; // Index into the func_t and mbool_t for the current kernel id // being processed. func_t* kers = &cntx_l1v_kers[ ker_id ]; // Store the ukernel function pointer and preference values into // the context. bli_func_set_dt( ker_fp, ker_dt, kers ); } // Free the temporary local arrays. #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_cntx_set_l1v_kers(): " ); #endif bli_free_intl( ker_ids ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_cntx_set_l1v_kers(): " ); #endif bli_free_intl( ker_dts ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_cntx_set_l1v_kers(): " ); #endif bli_free_intl( ker_fps ); } // ----------------------------------------------------------------------------- void bli_cntx_set_packm_kers( dim_t n_kers, ... ) { // This function can be called from the bli_cntx_init_*() function for // a particular architecture if the kernel developer wishes to use // non-default packing kernels. It should be called after // bli_cntx_init_defaults() so that the context begins with default packm // kernels across all datatypes. /* Example prototypes: void bli_cntx_set_packm_kers ( dim_t n_ukrs, l1mkr_t ker0_id, num_t ker0_dt, void_fp ker0_fp, l1mkr_t ker1_id, num_t ker1_dt, void_fp ker1_fp, l1mkr_t ker2_id, num_t ker2_dt, void_fp ker2_fp, ... cntx_t* cntx ); */ va_list args; dim_t i; err_t r_val; // Allocate some temporary local arrays. #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_cntx_set_packm_kers(): " ); #endif l1mkr_t* ker_ids = bli_malloc_intl( n_kers * sizeof( l1mkr_t ), &r_val ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_cntx_set_packm_kers(): " ); #endif num_t* ker_dts = bli_malloc_intl( n_kers * sizeof( num_t ), &r_val ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_cntx_set_packm_kers(): " ); #endif void_fp* ker_fps = bli_malloc_intl( n_kers * sizeof( void_fp ), &r_val ); // -- Begin variable argument section -- // Initialize variable argument environment. va_start( args, n_kers ); // Process n_kers tuples. for ( i = 0; i < n_kers; ++i ) { // Here, we query the variable argument list for: // - the l1mkr_t of the kernel we're about to process, // - the datatype of the kernel, and // - the kernel function pointer // that we need to store to the context. const l1mkr_t ker_id = ( l1mkr_t )va_arg( args, l1mkr_t ); const num_t ker_dt = ( num_t )va_arg( args, num_t ); void_fp ker_fp = ( void_fp )va_arg( args, void_fp ); // Store the values in our temporary arrays. ker_ids[ i ] = ker_id; ker_dts[ i ] = ker_dt; ker_fps[ i ] = ker_fp; } // The last argument should be the context pointer. cntx_t* cntx = ( cntx_t* )va_arg( args, cntx_t* ); // Shutdown variable argument environment and clean up stack. va_end( args ); // -- End variable argument section -- // Query the context for the address of: // - the packm kernels func_t array func_t* cntx_packm_kers = bli_cntx_packm_kers_buf( cntx ); // Now that we have the context address, we want to copy the values // from the temporary buffers into the corresponding buffers in the // context. // Process each blocksize id tuple provided. for ( i = 0; i < n_kers; ++i ) { // Read the current kernel id, kernel datatype, and kernel function // pointer. const l1mkr_t ker_id = ker_ids[ i ]; const num_t ker_dt = ker_dts[ i ]; void_fp ker_fp = ker_fps[ i ]; // Index into the func_t and mbool_t for the current kernel id // being processed. func_t* kers = &cntx_packm_kers[ ker_id ]; // Store the ukernel function pointer and preference values into // the context. bli_func_set_dt( ker_fp, ker_dt, kers ); } // Free the temporary local arrays. #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_cntx_set_packm_kers(): " ); #endif bli_free_intl( ker_ids ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_cntx_set_packm_kers(): " ); #endif bli_free_intl( ker_dts ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_cntx_set_packm_kers(): " ); #endif bli_free_intl( ker_fps ); } // ----------------------------------------------------------------------------- void bli_cntx_print( cntx_t* cntx ) { dim_t i; // Print the values stored in the blksz_t objects. printf( " s d c z\n" ); for ( i = 0; i < BLIS_NUM_BLKSZS; ++i ) { printf( "blksz/mult %2lu: %13lu/%2lu %13lu/%2lu %13lu/%2lu %13lu/%2lu\n", ( unsigned long )i, ( unsigned long )bli_cntx_get_blksz_def_dt( BLIS_FLOAT, i, cntx ), ( unsigned long )bli_cntx_get_bmult_dt ( BLIS_FLOAT, i, cntx ), ( unsigned long )bli_cntx_get_blksz_def_dt( BLIS_DOUBLE, i, cntx ), ( unsigned long )bli_cntx_get_bmult_dt ( BLIS_DOUBLE, i, cntx ), ( unsigned long )bli_cntx_get_blksz_def_dt( BLIS_SCOMPLEX, i, cntx ), ( unsigned long )bli_cntx_get_bmult_dt ( BLIS_SCOMPLEX, i, cntx ), ( unsigned long )bli_cntx_get_blksz_def_dt( BLIS_DCOMPLEX, i, cntx ), ( unsigned long )bli_cntx_get_bmult_dt ( BLIS_DCOMPLEX, i, cntx ) ); } for ( i = 0; i < BLIS_NUM_LEVEL3_UKRS; ++i ) { func_t* ukr = bli_cntx_get_l3_vir_ukrs( i, cntx ); printf( "l3 vir ukr %2lu: %16p %16p %16p %16p\n", ( unsigned long )i, bli_func_get_dt( BLIS_FLOAT, ukr ), bli_func_get_dt( BLIS_DOUBLE, ukr ), bli_func_get_dt( BLIS_SCOMPLEX, ukr ), bli_func_get_dt( BLIS_DCOMPLEX, ukr ) ); } for ( i = 0; i < BLIS_NUM_3OP_RC_COMBOS; ++i ) { func_t* ukr = bli_cntx_get_l3_sup_kers( i, cntx ); printf( "l3 sup ukr %2lu: %16p %16p %16p %16p\n", ( unsigned long )i, bli_func_get_dt( BLIS_FLOAT, ukr ), bli_func_get_dt( BLIS_DOUBLE, ukr ), bli_func_get_dt( BLIS_SCOMPLEX, ukr ), bli_func_get_dt( BLIS_DCOMPLEX, ukr ) ); } for ( i = 0; i < BLIS_NUM_LEVEL1F_KERS; ++i ) { func_t* ker = bli_cntx_get_l1f_kers( i, cntx ); printf( "l1f ker %2lu: %16p %16p %16p %16p\n", ( unsigned long )i, bli_func_get_dt( BLIS_FLOAT, ker ), bli_func_get_dt( BLIS_DOUBLE, ker ), bli_func_get_dt( BLIS_SCOMPLEX, ker ), bli_func_get_dt( BLIS_DCOMPLEX, ker ) ); } for ( i = 0; i < BLIS_NUM_LEVEL1V_KERS; ++i ) { func_t* ker = bli_cntx_get_l1v_kers( i, cntx ); printf( "l1v ker %2lu: %16p %16p %16p %16p\n", ( unsigned long )i, bli_func_get_dt( BLIS_FLOAT, ker ), bli_func_get_dt( BLIS_DOUBLE, ker ), bli_func_get_dt( BLIS_SCOMPLEX, ker ), bli_func_get_dt( BLIS_DCOMPLEX, ker ) ); } { ind_t method = bli_cntx_method( cntx ); printf( "ind method : %lu\n", ( unsigned long )method ); } } blis-0.9.0/frame/base/bli_cntx.h000066400000000000000000000522751422157504600164510ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2016, Hewlett Packard Enterprise Development LP Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_CNTX_H #define BLIS_CNTX_H // Context object type (defined in bli_type_defs.h) /* typedef struct cntx_s { blksz_t* blkszs; bszid_t* bmults; func_t* l3_vir_ukrs; func_t* l3_nat_ukrs; mbool_t* l3_nat_ukrs_prefs; blksz_t* l3_sup_thresh; void** l3_sup_handlers; blksz_t* l3_sup_blkszs; func_t* l3_sup_kers; mbool_t* l3_sup_kers_prefs; func_t* l1f_kers; func_t* l1v_kers; func_t* packm_kers; func_t* unpackm_kers; ind_t method; } cntx_t; */ // ----------------------------------------------------------------------------- // // -- cntx_t query (fields only) ----------------------------------------------- // BLIS_INLINE blksz_t* bli_cntx_blkszs_buf( cntx_t* cntx ) { return cntx->blkszs; } BLIS_INLINE bszid_t* bli_cntx_bmults_buf( cntx_t* cntx ) { return cntx->bmults; } BLIS_INLINE func_t* bli_cntx_l3_vir_ukrs_buf( cntx_t* cntx ) { return cntx->l3_vir_ukrs; } BLIS_INLINE func_t* bli_cntx_l3_nat_ukrs_buf( cntx_t* cntx ) { return cntx->l3_nat_ukrs; } BLIS_INLINE mbool_t* bli_cntx_l3_nat_ukrs_prefs_buf( cntx_t* cntx ) { return cntx->l3_nat_ukrs_prefs; } BLIS_INLINE blksz_t* bli_cntx_l3_sup_thresh_buf( cntx_t* cntx ) { return cntx->l3_sup_thresh; } BLIS_INLINE void** bli_cntx_l3_sup_handlers_buf( cntx_t* cntx ) { return cntx->l3_sup_handlers; } BLIS_INLINE blksz_t* bli_cntx_l3_sup_blkszs_buf( cntx_t* cntx ) { return cntx->l3_sup_blkszs; } BLIS_INLINE func_t* bli_cntx_l3_sup_kers_buf( cntx_t* cntx ) { return cntx->l3_sup_kers; } BLIS_INLINE mbool_t* bli_cntx_l3_sup_kers_prefs_buf( cntx_t* cntx ) { return cntx->l3_sup_kers_prefs; } BLIS_INLINE func_t* bli_cntx_l1f_kers_buf( cntx_t* cntx ) { return cntx->l1f_kers; } BLIS_INLINE func_t* bli_cntx_l1v_kers_buf( cntx_t* cntx ) { return cntx->l1v_kers; } BLIS_INLINE func_t* bli_cntx_packm_kers_buf( cntx_t* cntx ) { return cntx->packm_kers; } BLIS_INLINE func_t* bli_cntx_unpackm_kers_buf( cntx_t* cntx ) { return cntx->unpackm_kers; } BLIS_INLINE ind_t bli_cntx_method( cntx_t* cntx ) { return cntx->method; } // ----------------------------------------------------------------------------- // // -- cntx_t modification (fields only) ---------------------------------------- // BLIS_INLINE void bli_cntx_set_method( ind_t method, cntx_t* cntx ) { cntx->method = method; } // ----------------------------------------------------------------------------- // // -- cntx_t query (complex) --------------------------------------------------- // BLIS_INLINE blksz_t* bli_cntx_get_blksz( bszid_t bs_id, cntx_t* cntx ) { blksz_t* blkszs = bli_cntx_blkszs_buf( cntx ); blksz_t* blksz = &blkszs[ bs_id ]; // Return the address of the blksz_t identified by bs_id. return blksz; } BLIS_INLINE dim_t bli_cntx_get_blksz_def_dt( num_t dt, bszid_t bs_id, cntx_t* cntx ) { blksz_t* blksz = bli_cntx_get_blksz( bs_id, cntx ); dim_t bs_dt = bli_blksz_get_def( dt, blksz ); // Return the main (default) blocksize value for the datatype given. return bs_dt; } BLIS_INLINE dim_t bli_cntx_get_blksz_max_dt( num_t dt, bszid_t bs_id, cntx_t* cntx ) { blksz_t* blksz = bli_cntx_get_blksz( bs_id, cntx ); dim_t bs_dt = bli_blksz_get_max( dt, blksz ); // Return the auxiliary (maximum) blocksize value for the datatype given. return bs_dt; } BLIS_INLINE bszid_t bli_cntx_get_bmult_id( bszid_t bs_id, cntx_t* cntx ) { bszid_t* restrict bmults = bli_cntx_bmults_buf( cntx ); bszid_t bm_id = bmults[ bs_id ]; return bm_id; } BLIS_INLINE blksz_t* bli_cntx_get_bmult( bszid_t bs_id, cntx_t* cntx ) { bszid_t bm_id = bli_cntx_get_bmult_id( bs_id, cntx ); blksz_t* restrict bmult = bli_cntx_get_blksz( bm_id, cntx ); return bmult; } BLIS_INLINE dim_t bli_cntx_get_bmult_dt( num_t dt, bszid_t bs_id, cntx_t* cntx ) { blksz_t* bmult = bli_cntx_get_bmult( bs_id, cntx ); dim_t bm_dt = bli_blksz_get_def( dt, bmult ); return bm_dt; } // ----------------------------------------------------------------------------- BLIS_INLINE func_t* bli_cntx_get_l3_vir_ukrs( l3ukr_t ukr_id, cntx_t* cntx ) { func_t* funcs = bli_cntx_l3_vir_ukrs_buf( cntx ); func_t* func = &funcs[ ukr_id ]; return func; } BLIS_INLINE void_fp bli_cntx_get_l3_vir_ukr_dt( num_t dt, l3ukr_t ukr_id, cntx_t* cntx ) { func_t* func = bli_cntx_get_l3_vir_ukrs( ukr_id, cntx ); return bli_func_get_dt( dt, func ); } BLIS_INLINE func_t* bli_cntx_get_l3_nat_ukrs( l3ukr_t ukr_id, cntx_t* cntx ) { func_t* funcs = bli_cntx_l3_nat_ukrs_buf( cntx ); func_t* func = &funcs[ ukr_id ]; return func; } BLIS_INLINE void_fp bli_cntx_get_l3_nat_ukr_dt( num_t dt, l3ukr_t ukr_id, cntx_t* cntx ) { func_t* func = bli_cntx_get_l3_nat_ukrs( ukr_id, cntx ); return bli_func_get_dt( dt, func ); } // ----------------------------------------------------------------------------- BLIS_INLINE mbool_t* bli_cntx_get_l3_nat_ukr_prefs( l3ukr_t ukr_id, cntx_t* cntx ) { mbool_t* mbools = bli_cntx_l3_nat_ukrs_prefs_buf( cntx ); mbool_t* mbool = &mbools[ ukr_id ]; return mbool; } BLIS_INLINE bool bli_cntx_get_l3_nat_ukr_prefs_dt( num_t dt, l3ukr_t ukr_id, cntx_t* cntx ) { mbool_t* mbool = bli_cntx_get_l3_nat_ukr_prefs( ukr_id, cntx ); return ( bool )bli_mbool_get_dt( dt, mbool ); } // ----------------------------------------------------------------------------- BLIS_INLINE blksz_t* bli_cntx_get_l3_sup_thresh( threshid_t thresh_id, cntx_t* cntx ) { blksz_t* threshs = bli_cntx_l3_sup_thresh_buf( cntx ); blksz_t* thresh = &threshs[ thresh_id ]; // Return the address of the blksz_t identified by thresh_id. return thresh; } BLIS_INLINE dim_t bli_cntx_get_l3_sup_thresh_dt( num_t dt, threshid_t thresh_id, cntx_t* cntx ) { blksz_t* threshs = bli_cntx_get_l3_sup_thresh( thresh_id, cntx ); dim_t thresh_dt = bli_blksz_get_def( dt, threshs ); // Return the main (default) threshold value for the datatype given. return thresh_dt; } BLIS_INLINE bool bli_cntx_l3_sup_thresh_is_met( num_t dt, dim_t m, dim_t n, dim_t k, cntx_t* cntx ) { if ( m < bli_cntx_get_l3_sup_thresh_dt( dt, BLIS_MT, cntx ) ) return TRUE; if ( n < bli_cntx_get_l3_sup_thresh_dt( dt, BLIS_NT, cntx ) ) return TRUE; if ( k < bli_cntx_get_l3_sup_thresh_dt( dt, BLIS_KT, cntx ) ) return TRUE; return FALSE; } // ----------------------------------------------------------------------------- BLIS_INLINE void* bli_cntx_get_l3_sup_handler( opid_t op, cntx_t* cntx ) { void** funcs = bli_cntx_l3_sup_handlers_buf( cntx ); void* func = funcs[ op ]; return func; } // ----------------------------------------------------------------------------- BLIS_INLINE blksz_t* bli_cntx_get_l3_sup_blksz( bszid_t bs_id, cntx_t* cntx ) { blksz_t* blkszs = bli_cntx_l3_sup_blkszs_buf( cntx ); blksz_t* blksz = &blkszs[ bs_id ]; // Return the address of the blksz_t identified by bs_id. return blksz; } BLIS_INLINE dim_t bli_cntx_get_l3_sup_blksz_def_dt( num_t dt, bszid_t bs_id, cntx_t* cntx ) { blksz_t* blksz = bli_cntx_get_l3_sup_blksz( bs_id, cntx ); dim_t bs_dt = bli_blksz_get_def( dt, blksz ); // Return the main (default) blocksize value for the datatype given. return bs_dt; } BLIS_INLINE dim_t bli_cntx_get_l3_sup_blksz_max_dt( num_t dt, bszid_t bs_id, cntx_t* cntx ) { blksz_t* blksz = bli_cntx_get_l3_sup_blksz( bs_id, cntx ); dim_t bs_dt = bli_blksz_get_max( dt, blksz ); // Return the auxiliary (maximum) blocksize value for the datatype given. return bs_dt; } // ----------------------------------------------------------------------------- BLIS_INLINE func_t* bli_cntx_get_l3_sup_kers( stor3_t stor_id, cntx_t* cntx ) { func_t* funcs = bli_cntx_l3_sup_kers_buf( cntx ); func_t* func = &funcs[ stor_id ]; return func; } BLIS_INLINE void* bli_cntx_get_l3_sup_ker_dt( num_t dt, stor3_t stor_id, cntx_t* cntx ) { func_t* func = bli_cntx_get_l3_sup_kers( stor_id, cntx ); return bli_func_get_dt( dt, func ); } // ----------------------------------------------------------------------------- BLIS_INLINE mbool_t* bli_cntx_get_l3_sup_ker_prefs( stor3_t stor_id, cntx_t* cntx ) { mbool_t* mbools = bli_cntx_l3_sup_kers_prefs_buf( cntx ); mbool_t* mbool = &mbools[ stor_id ]; return mbool; } BLIS_INLINE bool bli_cntx_get_l3_sup_ker_prefs_dt( num_t dt, stor3_t stor_id, cntx_t* cntx ) { mbool_t* mbool = bli_cntx_get_l3_sup_ker_prefs( stor_id, cntx ); return ( bool )bli_mbool_get_dt( dt, mbool ); } // ----------------------------------------------------------------------------- BLIS_INLINE func_t* bli_cntx_get_l1f_kers( l1fkr_t ker_id, cntx_t* cntx ) { func_t* funcs = bli_cntx_l1f_kers_buf( cntx ); func_t* func = &funcs[ ker_id ]; return func; } BLIS_INLINE void_fp bli_cntx_get_l1f_ker_dt( num_t dt, l1fkr_t ker_id, cntx_t* cntx ) { func_t* func = bli_cntx_get_l1f_kers( ker_id, cntx ); return bli_func_get_dt( dt, func ); } // ----------------------------------------------------------------------------- BLIS_INLINE func_t* bli_cntx_get_l1v_kers( l1vkr_t ker_id, cntx_t* cntx ) { func_t* funcs = bli_cntx_l1v_kers_buf( cntx ); func_t* func = &funcs[ ker_id ]; return func; } BLIS_INLINE void_fp bli_cntx_get_l1v_ker_dt( num_t dt, l1vkr_t ker_id, cntx_t* cntx ) { func_t* func = bli_cntx_get_l1v_kers( ker_id, cntx ); return bli_func_get_dt( dt, func ); } // ----------------------------------------------------------------------------- BLIS_INLINE func_t* bli_cntx_get_packm_kers( l1mkr_t ker_id, cntx_t* cntx ) { func_t* func = NULL; // Only index to the requested packm func_t if the packm kernel being // requested is one that is explicitly supported. if ( 0 <= ( gint_t )ker_id && ( gint_t )ker_id < BLIS_NUM_PACKM_KERS ) { func_t* funcs = bli_cntx_packm_kers_buf( cntx ); func = &funcs[ ker_id ]; } return func; } BLIS_INLINE void_fp bli_cntx_get_packm_ker_dt( num_t dt, l1mkr_t ker_id, cntx_t* cntx ) { void_fp fp = NULL; // Only query the context for the packm func_t (and then extract the // datatype-specific function pointer) if the packm kernel being // requested is one that is explicitly supported. if ( 0 <= ( gint_t )ker_id && ( gint_t )ker_id < BLIS_NUM_PACKM_KERS ) { func_t* func = bli_cntx_get_packm_kers( ker_id, cntx ); fp = bli_func_get_dt( dt, func ); } return fp; } BLIS_INLINE func_t* bli_cntx_get_unpackm_kers( l1mkr_t ker_id, cntx_t* cntx ) { func_t* func = NULL; // Only index to the requested unpackm func_t if the unpackm kernel being // requested is one that is explicitly supported. if ( 0 <= ( gint_t )ker_id && ( gint_t )ker_id < BLIS_NUM_UNPACKM_KERS ) { func_t* funcs = bli_cntx_unpackm_kers_buf( cntx ); func = &funcs[ ker_id ]; } return func; } BLIS_INLINE void_fp bli_cntx_get_unpackm_ker_dt( num_t dt, l1mkr_t ker_id, cntx_t* cntx ) { void_fp fp = NULL; // Only query the context for the unpackm func_t (and then extract the // datatype-specific function pointer) if the unpackm kernel being // requested is one that is explicitly supported. if ( 0 <= ( gint_t )ker_id && ( gint_t )ker_id < BLIS_NUM_UNPACKM_KERS ) { func_t* func = bli_cntx_get_unpackm_kers( ker_id, cntx ); fp = bli_func_get_dt( dt, func ); } return fp; } // ----------------------------------------------------------------------------- BLIS_INLINE bool bli_cntx_l3_nat_ukr_prefers_rows_dt( num_t dt, l3ukr_t ukr_id, cntx_t* cntx ) { const bool prefs = bli_cntx_get_l3_nat_ukr_prefs_dt( dt, ukr_id, cntx ); // A ukernel preference of TRUE means the ukernel prefers row storage. return ( bool ) ( prefs == TRUE ); } BLIS_INLINE bool bli_cntx_l3_nat_ukr_prefers_cols_dt( num_t dt, l3ukr_t ukr_id, cntx_t* cntx ) { const bool prefs = bli_cntx_get_l3_nat_ukr_prefs_dt( dt, ukr_id, cntx ); // A ukernel preference of FALSE means the ukernel prefers column storage. return ( bool ) ( prefs == FALSE ); } BLIS_INLINE bool bli_cntx_l3_nat_ukr_prefers_storage_of( obj_t* obj, l3ukr_t ukr_id, cntx_t* cntx ) { // Note that we use the computation datatype, which may differ from the // storage datatype of C (when performing a mixed datatype operation). const num_t dt = bli_obj_comp_dt( obj ); const bool ukr_prefers_rows = bli_cntx_l3_nat_ukr_prefers_rows_dt( dt, ukr_id, cntx ); const bool ukr_prefers_cols = bli_cntx_l3_nat_ukr_prefers_cols_dt( dt, ukr_id, cntx ); bool r_val = FALSE; if ( bli_obj_is_row_stored( obj ) && ukr_prefers_rows ) r_val = TRUE; else if ( bli_obj_is_col_stored( obj ) && ukr_prefers_cols ) r_val = TRUE; return r_val; } BLIS_INLINE bool bli_cntx_l3_nat_ukr_dislikes_storage_of( obj_t* obj, l3ukr_t ukr_id, cntx_t* cntx ) { return ( bool ) !bli_cntx_l3_nat_ukr_prefers_storage_of( obj, ukr_id, cntx ); } // ----------------------------------------------------------------------------- BLIS_INLINE bool bli_cntx_l3_vir_ukr_prefers_rows_dt( num_t dt, l3ukr_t ukr_id, cntx_t* cntx ) { // For induced methods, return the ukernel storage preferences of the // corresponding real micro-kernel. // NOTE: This projection to real domain becomes unnecessary if you // set the exec_dt for 1m to the real projection of the storage // datatype. if ( bli_cntx_method( cntx ) != BLIS_NAT ) dt = bli_dt_proj_to_real( dt ); return bli_cntx_l3_nat_ukr_prefers_rows_dt( dt, ukr_id, cntx ); } BLIS_INLINE bool bli_cntx_l3_vir_ukr_prefers_cols_dt( num_t dt, l3ukr_t ukr_id, cntx_t* cntx ) { // For induced methods, return the ukernel storage preferences of the // corresponding real micro-kernel. // NOTE: This projection to real domain becomes unnecessary if you // set the exec_dt for 1m to the real projection of the storage // datatype. if ( bli_cntx_method( cntx ) != BLIS_NAT ) dt = bli_dt_proj_to_real( dt ); return bli_cntx_l3_nat_ukr_prefers_cols_dt( dt, ukr_id, cntx ); } BLIS_INLINE bool bli_cntx_l3_vir_ukr_prefers_storage_of( obj_t* obj, l3ukr_t ukr_id, cntx_t* cntx ) { // Note that we use the computation datatype, which may differ from the // storage datatype of C (when performing a mixed datatype operation). const num_t dt = bli_obj_comp_dt( obj ); const bool ukr_prefers_rows = bli_cntx_l3_vir_ukr_prefers_rows_dt( dt, ukr_id, cntx ); const bool ukr_prefers_cols = bli_cntx_l3_vir_ukr_prefers_cols_dt( dt, ukr_id, cntx ); bool r_val = FALSE; if ( bli_obj_is_row_stored( obj ) && ukr_prefers_rows ) r_val = TRUE; else if ( bli_obj_is_col_stored( obj ) && ukr_prefers_cols ) r_val = TRUE; return r_val; } BLIS_INLINE bool bli_cntx_l3_vir_ukr_dislikes_storage_of( obj_t* obj, l3ukr_t ukr_id, cntx_t* cntx ) { return ( bool ) !bli_cntx_l3_vir_ukr_prefers_storage_of( obj, ukr_id, cntx ); } // ----------------------------------------------------------------------------- BLIS_INLINE bool bli_cntx_l3_sup_ker_prefers_rows_dt( num_t dt, stor3_t stor_id, cntx_t* cntx ) { const bool prefs = bli_cntx_get_l3_sup_ker_prefs_dt( dt, stor_id, cntx ); // A ukernel preference of TRUE means the ukernel prefers row storage. return ( bool ) ( prefs == TRUE ); } BLIS_INLINE bool bli_cntx_l3_sup_ker_prefers_cols_dt( num_t dt, stor3_t stor_id, cntx_t* cntx ) { const bool prefs = bli_cntx_get_l3_sup_ker_prefs_dt( dt, stor_id, cntx ); // A ukernel preference of FALSE means the ukernel prefers column storage. return ( bool ) ( prefs == FALSE ); } #if 0 // NOTE: These static functions aren't needed yet. BLIS_INLINE bool bli_cntx_l3_sup_ker_prefers_storage_of( obj_t* obj, stor3_t stor_id, cntx_t* cntx ) { const num_t dt = bli_obj_dt( obj ); const bool ukr_prefers_rows = bli_cntx_l3_sup_ker_prefers_rows_dt( dt, stor_id, cntx ); const bool ukr_prefers_cols = bli_cntx_l3_sup_ker_prefers_cols_dt( dt, stor_id, cntx ); bool r_val = FALSE; if ( bli_obj_is_row_stored( obj ) && ukr_prefers_rows ) r_val = TRUE; else if ( bli_obj_is_col_stored( obj ) && ukr_prefers_cols ) r_val = TRUE; return r_val; } BLIS_INLINE bool bli_cntx_l3_sup_ker_dislikes_storage_of( obj_t* obj, stor3_t stor_id, cntx_t* cntx ) { return ( bool ) !bli_cntx_l3_sup_ker_prefers_storage_of( obj, stor_id, cntx ); } #endif // ----------------------------------------------------------------------------- // // -- cntx_t modification (complex) -------------------------------------------- // // NOTE: The framework does not use any of the following functions. We provide // them in order to facilitate creating/modifying custom contexts. BLIS_INLINE void bli_cntx_set_blksz( bszid_t bs_id, blksz_t* blksz, bszid_t mult_id, cntx_t* cntx ) { blksz_t* blkszs = bli_cntx_blkszs_buf( cntx ); bszid_t* bmults = bli_cntx_bmults_buf( cntx ); blkszs[ bs_id ] = *blksz; bmults[ bs_id ] = mult_id; } BLIS_INLINE void bli_cntx_set_blksz_def_dt( num_t dt, bszid_t bs_id, dim_t bs, cntx_t* cntx ) { blksz_t* blkszs = bli_cntx_blkszs_buf( cntx ); blksz_t* blksz = &blkszs[ bs_id ]; bli_blksz_set_def( bs, dt, blksz ); } BLIS_INLINE void bli_cntx_set_blksz_max_dt( num_t dt, bszid_t bs_id, dim_t bs, cntx_t* cntx ) { blksz_t* blkszs = bli_cntx_blkszs_buf( cntx ); blksz_t* blksz = &blkszs[ bs_id ]; bli_blksz_set_max( bs, dt, blksz ); } BLIS_INLINE void bli_cntx_set_l3_vir_ukr( l3ukr_t ukr_id, func_t* func, cntx_t* cntx ) { func_t* funcs = bli_cntx_l3_vir_ukrs_buf( cntx ); funcs[ ukr_id ] = *func; } BLIS_INLINE void bli_cntx_set_l3_nat_ukr( l3ukr_t ukr_id, func_t* func, cntx_t* cntx ) { func_t* funcs = bli_cntx_l3_nat_ukrs_buf( cntx ); funcs[ ukr_id ] = *func; } BLIS_INLINE void bli_cntx_set_l3_nat_ukr_prefs( l3ukr_t ukr_id, mbool_t* prefs, cntx_t* cntx ) { mbool_t* mbools = bli_cntx_l3_nat_ukrs_prefs_buf( cntx ); mbools[ ukr_id ] = *prefs; } BLIS_INLINE void bli_cntx_set_l1f_ker( l1fkr_t ker_id, func_t* func, cntx_t* cntx ) { func_t* funcs = bli_cntx_l1f_kers_buf( cntx ); funcs[ ker_id ] = *func; } BLIS_INLINE void bli_cntx_set_l1v_ker( l1vkr_t ker_id, func_t* func, cntx_t* cntx ) { func_t* funcs = bli_cntx_l1v_kers_buf( cntx ); funcs[ ker_id ] = *func; } BLIS_INLINE void bli_cntx_set_packm_ker( l1mkr_t ker_id, func_t* func, cntx_t* cntx ) { func_t* funcs = bli_cntx_get_packm_kers( ker_id, cntx ); funcs[ ker_id ] = *func; } BLIS_INLINE void bli_cntx_set_packm_ker_dt( void_fp fp, num_t dt, l1mkr_t ker_id, cntx_t* cntx ) { func_t* func = ( func_t* )bli_cntx_get_packm_kers( ker_id, cntx ); bli_func_set_dt( fp, dt, func ); } BLIS_INLINE void bli_cntx_set_unpackm_ker( l1mkr_t ker_id, func_t* func, cntx_t* cntx ) { func_t* funcs = bli_cntx_get_unpackm_kers( ker_id, cntx ); funcs[ ker_id ] = *func; } BLIS_INLINE void bli_cntx_set_unpackm_ker_dt( void_fp fp, num_t dt, l1mkr_t ker_id, cntx_t* cntx ) { func_t* func = ( func_t* )bli_cntx_get_unpackm_kers( ker_id, cntx ); bli_func_set_dt( fp, dt, func ); } // ----------------------------------------------------------------------------- // Function prototypes BLIS_EXPORT_BLIS void bli_cntx_clear( cntx_t* cntx ); BLIS_EXPORT_BLIS void bli_cntx_set_blkszs( ind_t method, dim_t n_bs, ... ); BLIS_EXPORT_BLIS void bli_cntx_set_ind_blkszs( ind_t method, num_t dt, dim_t n_bs, ... ); BLIS_EXPORT_BLIS void bli_cntx_set_l3_nat_ukrs( dim_t n_ukrs, ... ); BLIS_EXPORT_BLIS void bli_cntx_set_l3_vir_ukrs( dim_t n_ukrs, ... ); BLIS_EXPORT_BLIS void bli_cntx_set_l3_sup_thresh( dim_t n_thresh, ... ); BLIS_EXPORT_BLIS void bli_cntx_set_l3_sup_handlers( dim_t n_ops, ... ); BLIS_EXPORT_BLIS void bli_cntx_set_l3_sup_blkszs( dim_t n_bs, ... ); BLIS_EXPORT_BLIS void bli_cntx_set_l3_sup_kers( dim_t n_ukrs, ... ); BLIS_EXPORT_BLIS void bli_cntx_set_l1f_kers( dim_t n_kers, ... ); BLIS_EXPORT_BLIS void bli_cntx_set_l1v_kers( dim_t n_kers, ... ); BLIS_EXPORT_BLIS void bli_cntx_set_packm_kers( dim_t n_kers, ... ); BLIS_EXPORT_BLIS void bli_cntx_print( cntx_t* cntx ); #endif blis-0.9.0/frame/base/bli_const.c000066400000000000000000000064101422157504600166040ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // Statically initialize structs containing representations of various // constants for each datatype supported in BLIS. static constdata_t bli_two_buffer = bli_obj_init_constdata( 2.0 ); static constdata_t bli_one_buffer = bli_obj_init_constdata( 1.0 ); static constdata_t bli_zero_buffer = bli_obj_init_constdata( 0.0 ); static constdata_t bli_mone_buffer = bli_obj_init_constdata( -1.0 ); static constdata_t bli_mtwo_buffer = bli_obj_init_constdata( -2.0 ); // Statically initialize global scalar constants, attaching the addresses // of the corresponding structs above. obj_t BLIS_TWO = bli_obj_init_const( &bli_two_buffer ); obj_t BLIS_ONE = bli_obj_init_const( &bli_one_buffer ); obj_t BLIS_ZERO = bli_obj_init_const( &bli_zero_buffer ); obj_t BLIS_MINUS_ONE = bli_obj_init_const( &bli_mone_buffer ); obj_t BLIS_MINUS_TWO = bli_obj_init_const( &bli_mtwo_buffer ); #if 0 obj_t BLIS_TWO = {}; obj_t BLIS_ONE = {}; obj_t BLIS_ZERO = {}; obj_t BLIS_MINUS_ONE = {}; obj_t BLIS_MINUS_TWO = {}; void bli_const_init( void ) { bli_obj_create_const( 2.0, &BLIS_TWO ); bli_obj_create_const( 1.0, &BLIS_ONE ); bli_obj_create_const( 0.5, &BLIS_ONE_HALF ); bli_obj_create_const( 0.0, &BLIS_ZERO ); bli_obj_create_const( -0.5, &BLIS_MINUS_ONE_HALF ); bli_obj_create_const( -1.0, &BLIS_MINUS_ONE ); bli_obj_create_const( -2.0, &BLIS_MINUS_TWO ); } void bli_const_finalize( void ) { bli_obj_free( &BLIS_TWO ); bli_obj_free( &BLIS_ONE ); bli_obj_free( &BLIS_ONE_HALF ); bli_obj_free( &BLIS_ZERO ); bli_obj_free( &BLIS_MINUS_ONE_HALF ); bli_obj_free( &BLIS_MINUS_ONE ); bli_obj_free( &BLIS_MINUS_TWO ); } #endif blis-0.9.0/frame/base/bli_const.h000066400000000000000000000033101422157504600166050ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void bli_const_init( void ); void bli_const_finalize( void ); blis-0.9.0/frame/base/bli_cpuid.c000066400000000000000000001163551422157504600165740ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018-2020, Advanced Micro Devices, Inc. Copyright (C) 2019, Dave Love, University of Manchester 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #if 0 // Used only during standalone testing of ARM support. #include "bli_system.h" #include "bli_type_defs.h" #include "bli_cpuid.h" #undef __x86_64__ #undef _M_X64 #undef __i386 #undef _M_IX86 #define __arm__ #endif #ifdef BLIS_CONFIGURETIME_CPUID // NOTE: If you need to make any changes to this cpp branch, it's probably // the case that you also need to modify bli_arch.c, bli_cpuid.c, and // bli_env.c. Don't forget to update these other files as needed! // The BLIS_ENABLE_SYSTEM macro must be defined so that the correct cpp // branch in bli_system.h is processed. (This macro is normally defined in // bli_config.h.) #define BLIS_ENABLE_SYSTEM // Use C-style static inline functions for any static inline functions that // happen to be defined by the headers below. (This macro is normally defined // in bli_config_macro_defs.h.) #define BLIS_INLINE static // Since we're not building a shared library, we can forgo the use of the // BLIS_EXPORT_BLIS annotations by #defining them to be nothing. (This macro // is normally defined in bli_config_macro_defs.h.) #define BLIS_EXPORT_BLIS #include "bli_system.h" #include "bli_type_defs.h" #include "bli_arch.h" #include "bli_cpuid.h" //#include "bli_env.h" #else #include "blis.h" #endif // ----------------------------------------------------------------------------- #if defined(__x86_64__) || defined(_M_X64) || defined(__i386) || defined(_M_IX86) #include "cpuid.h" arch_t bli_cpuid_query_id( void ) { uint32_t vendor, family, model, features; // Call the CPUID instruction and parse its results into a family id, // model id, and a feature bit field. The return value encodes the // vendor. vendor = bli_cpuid_query( &family, &model, &features ); #if 0 printf( "vendor = %s\n", vendor==1 ? "AMD": "INTEL" ); printf("family = %x\n", family ); printf( "model = %x\n", model ); printf( "features = %x\n", features ); #endif if ( vendor == VENDOR_INTEL ) { // Check for each Intel configuration that is enabled, check for that // microarchitecture. We check from most recent to most dated. #ifdef BLIS_CONFIG_SKX if ( bli_cpuid_is_skx( family, model, features ) ) return BLIS_ARCH_SKX; #endif #ifdef BLIS_CONFIG_KNL if ( bli_cpuid_is_knl( family, model, features ) ) return BLIS_ARCH_KNL; #endif #ifdef BLIS_CONFIG_HASWELL if ( bli_cpuid_is_haswell( family, model, features ) ) return BLIS_ARCH_HASWELL; #endif #ifdef BLIS_CONFIG_SANDYBRIDGE if ( bli_cpuid_is_sandybridge( family, model, features ) ) return BLIS_ARCH_SANDYBRIDGE; #endif #ifdef BLIS_CONFIG_PENRYN if ( bli_cpuid_is_penryn( family, model, features ) ) return BLIS_ARCH_PENRYN; #endif // If none of the other sub-configurations were detected, return // the 'generic' arch_t id value. return BLIS_ARCH_GENERIC; } else if ( vendor == VENDOR_AMD ) { // Check for each AMD configuration that is enabled, check for that // microarchitecture. We check from most recent to most dated. #ifdef BLIS_CONFIG_ZEN3 if ( bli_cpuid_is_zen3( family, model, features ) ) return BLIS_ARCH_ZEN3; #endif #ifdef BLIS_CONFIG_ZEN2 if ( bli_cpuid_is_zen2( family, model, features ) ) return BLIS_ARCH_ZEN2; #endif #ifdef BLIS_CONFIG_ZEN if ( bli_cpuid_is_zen( family, model, features ) ) return BLIS_ARCH_ZEN; #endif #ifdef BLIS_CONFIG_EXCAVATOR if ( bli_cpuid_is_excavator( family, model, features ) ) return BLIS_ARCH_EXCAVATOR; #endif #ifdef BLIS_CONFIG_STEAMROLLER if ( bli_cpuid_is_steamroller( family, model, features ) ) return BLIS_ARCH_STEAMROLLER; #endif #ifdef BLIS_CONFIG_PILEDRIVER if ( bli_cpuid_is_piledriver( family, model, features ) ) return BLIS_ARCH_PILEDRIVER; #endif #ifdef BLIS_CONFIG_BULLDOZER if ( bli_cpuid_is_bulldozer( family, model, features ) ) return BLIS_ARCH_BULLDOZER; #endif // If none of the other sub-configurations were detected, return // the 'generic' arch_t id value. return BLIS_ARCH_GENERIC; } else if ( vendor == VENDOR_UNKNOWN ) { return BLIS_ARCH_GENERIC; } return BLIS_ARCH_GENERIC; } // ----------------------------------------------------------------------------- bool bli_cpuid_is_skx ( uint32_t family, uint32_t model, uint32_t features ) { // Check for expected CPU features. const uint32_t expected = FEATURE_AVX | FEATURE_FMA3 | FEATURE_AVX2 | FEATURE_AVX512F | FEATURE_AVX512DQ | FEATURE_AVX512BW | FEATURE_AVX512VL ; int nvpu = vpu_count(); if ( bli_cpuid_has_features( features, expected ) ) { switch ( nvpu ) { case 1: bli_arch_log( "Hardware has 1 FMA unit; using 'haswell' (not 'skx') sub-config.\n" ); return FALSE; case 2: bli_arch_log( "Hardware has 2 FMA units; using 'skx' sub-config.\n" ); return TRUE; default: bli_arch_log( "Number of FMA units unknown; using 'haswell' (not 'skx') config.\n" ); return FALSE; } } else return FALSE; return TRUE; } bool bli_cpuid_is_knl ( uint32_t family, uint32_t model, uint32_t features ) { // Check for expected CPU features. const uint32_t expected = FEATURE_AVX | FEATURE_FMA3 | FEATURE_AVX2 | FEATURE_AVX512F | FEATURE_AVX512PF; if ( !bli_cpuid_has_features( features, expected ) ) return FALSE; return TRUE; } bool bli_cpuid_is_haswell ( uint32_t family, uint32_t model, uint32_t features ) { // Check for expected CPU features. const uint32_t expected = FEATURE_AVX | FEATURE_FMA3 | FEATURE_AVX2; if ( !bli_cpuid_has_features( features, expected ) ) return FALSE; return TRUE; } bool bli_cpuid_is_sandybridge ( uint32_t family, uint32_t model, uint32_t features ) { // Check for expected CPU features. const uint32_t expected = FEATURE_AVX; if ( !bli_cpuid_has_features( features, expected ) ) return FALSE; return TRUE; } bool bli_cpuid_is_penryn ( uint32_t family, uint32_t model, uint32_t features ) { // Check for expected CPU features. const uint32_t expected = FEATURE_SSE3 | FEATURE_SSSE3; if ( !bli_cpuid_has_features( features, expected ) ) return FALSE; return TRUE; } // ----------------------------------------------------------------------------- bool bli_cpuid_is_zen3 ( uint32_t family, uint32_t model, uint32_t features ) { // Check for expected CPU features. const uint32_t expected = FEATURE_AVX | FEATURE_FMA3 | FEATURE_AVX2; if ( !bli_cpuid_has_features( features, expected ) ) return FALSE; // All Zen3 cores have a family of 0x19. if ( family != 0x19 ) return FALSE; // Finally, check for specific models: // - 0x00 ~ 0xff // NOTE: We accept any model because the family 25 (0x19) is unique. const bool is_arch = ( 0x00 <= model && model <= 0xff ); if ( !is_arch ) return FALSE; return TRUE; } bool bli_cpuid_is_zen2 ( uint32_t family, uint32_t model, uint32_t features ) { // Check for expected CPU features. const uint32_t expected = FEATURE_AVX | FEATURE_FMA3 | FEATURE_AVX2; if ( !bli_cpuid_has_features( features, expected ) ) return FALSE; // All Zen2 cores have a family of 0x17. if ( family != 0x17 ) return FALSE; // Finally, check for specific models: // - 0x30 ~ 0xff // NOTE: We must check model because the family 23 (0x17) is shared with // zen. const bool is_arch = ( 0x30 <= model && model <= 0xff ); if ( !is_arch ) return FALSE; return TRUE; } bool bli_cpuid_is_zen ( uint32_t family, uint32_t model, uint32_t features ) { // Check for expected CPU features. const uint32_t expected = FEATURE_AVX | FEATURE_FMA3 | FEATURE_AVX2; if ( !bli_cpuid_has_features( features, expected ) ) return FALSE; // All Zen cores have a family of 0x17. if ( family != 0x17 ) return FALSE; // Finally, check for specific models: // - 0x00 ~ 0x2f // NOTE: We must check model because the family 23 (0x17) is shared with // zen2. const bool is_arch = ( 0x00 <= model && model <= 0x2f ); if ( !is_arch ) return FALSE; return TRUE; } bool bli_cpuid_is_excavator ( uint32_t family, uint32_t model, uint32_t features ) { // Check for expected CPU features. const uint32_t expected = FEATURE_AVX | FEATURE_FMA3 | FEATURE_AVX2; if ( !bli_cpuid_has_features( features, expected ) ) return FALSE; // All Excavator cores have a family of 0x15. if ( family != 0x15 ) return FALSE; // Finally, check for specific models: // - 0x60 ~ 0x7f const bool is_arch = ( 0x60 <= model && model <= 0x7f ); if ( !is_arch ) return FALSE; return TRUE; } bool bli_cpuid_is_steamroller ( uint32_t family, uint32_t model, uint32_t features ) { // Check for expected CPU features. const uint32_t expected = FEATURE_AVX | FEATURE_FMA3 | FEATURE_FMA4; if ( !bli_cpuid_has_features( features, expected ) ) return FALSE; // All Steamroller cores have a family of 0x15. if ( family != 0x15 ) return FALSE; // Finally, check for specific models: // - 0x30 ~ 0x3f const bool is_arch = ( 0x30 <= model && model <= 0x3f ); if ( !is_arch ) return FALSE; return TRUE; } bool bli_cpuid_is_piledriver ( uint32_t family, uint32_t model, uint32_t features ) { // Check for expected CPU features. const uint32_t expected = FEATURE_AVX | FEATURE_FMA3 | FEATURE_FMA4; if ( !bli_cpuid_has_features( features, expected ) ) return FALSE; // All Piledriver cores have a family of 0x15. if ( family != 0x15 ) return FALSE; // Finally, check for specific models: // - 0x02 // - 0x10 ~ 0x1f const bool is_arch = model == 0x02 || ( 0x10 <= model && model <= 0x1f ); if ( !is_arch ) return FALSE; return TRUE; } bool bli_cpuid_is_bulldozer ( uint32_t family, uint32_t model, uint32_t features ) { // Check for expected CPU features. const uint32_t expected = FEATURE_AVX | FEATURE_FMA4; if ( !bli_cpuid_has_features( features, expected ) ) return FALSE; // All Bulldozer cores have a family of 0x15. if ( family != 0x15 ) return FALSE; // Finally, check for specific models: // - 0x00 // - 0x01 const bool is_arch = ( model == 0x00 || model == 0x01 ); if ( !is_arch ) return FALSE; return TRUE; } #elif defined(__aarch64__) || defined(__arm__) || defined(_M_ARM) arch_t bli_cpuid_query_id( void ) { uint32_t vendor, model, part, features; vendor = bli_cpuid_query( &model, &part, &features ); #if 0 printf( "vendor = %u\n", vendor ); printf( "model = %u\n", model ); printf( "part = 0x%x\n", part ); printf( "features = %u\n", features ); #endif if ( vendor == VENDOR_ARM ) { if ( model == MODEL_ARMV8 ) { return part; // Check for each ARMv8 configuration that is enabled, check for that // microarchitecture. We check from most recent to most dated. // If none of the other sub-configurations were detected, return // the 'generic' arch_t id value. return BLIS_ARCH_GENERIC; } else if ( model == MODEL_ARMV7 ) { // Check for each ARMv7 configuration that is enabled, check for that // microarchitecture. We check from most recent to most dated. #ifdef BLIS_CONFIG_CORTEXA15 if ( bli_cpuid_is_cortexa15( model, part, features ) ) return BLIS_ARCH_CORTEXA15; #endif #ifdef BLIS_CONFIG_CORTEXA9 if ( bli_cpuid_is_cortexa9( model, part, features ) ) return BLIS_ARCH_CORTEXA9; #endif // If none of the other sub-configurations were detected, return // the 'generic' arch_t id value. return BLIS_ARCH_GENERIC; } } else if ( vendor == VENDOR_UNKNOWN ) { return BLIS_ARCH_GENERIC; } return BLIS_ARCH_GENERIC; } bool bli_cpuid_is_cortexa15 ( uint32_t family, uint32_t model, uint32_t features ) { // Check for expected CPU features. const uint32_t expected = FEATURE_NEON; return bli_cpuid_has_features( features, expected ) && model == 0xc0f; } bool bli_cpuid_is_cortexa9 ( uint32_t family, uint32_t model, uint32_t features ) { // Check for expected CPU features. const uint32_t expected = FEATURE_NEON; return bli_cpuid_has_features( features, expected ) && model == 0xc09; } #endif // ----------------------------------------------------------------------------- // // This section of the file was based off of cpuid.cxx from TBLIS [1]. // // [1] https://github.com/devinamatthews/tblis // /* Copyright (C) 2017, The University of Texas at Austin Copyright (C) 2017, Devin Matthews Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #if defined(__x86_64__) || defined(_M_X64) || defined(__i386) || defined(_M_IX86) enum { // input register(s) output register FEATURE_MASK_SSE3 = (1u<< 0), // cpuid[eax=1] :ecx[0] FEATURE_MASK_SSSE3 = (1u<< 9), // cpuid[eax=1] :ecx[9] FEATURE_MASK_SSE41 = (1u<<19), // cpuid[eax=1] :ecx[19] FEATURE_MASK_SSE42 = (1u<<20), // cpuid[eax=1] :ecx[20] FEATURE_MASK_AVX = (1u<<28), // cpuid[eax=1] :ecx[28] FEATURE_MASK_AVX2 = (1u<< 5), // cpuid[eax=7,ecx=0] :ebx[5] FEATURE_MASK_FMA3 = (1u<<12), // cpuid[eax=1] :ecx[12] FEATURE_MASK_FMA4 = (1u<<16), // cpuid[eax=0x80000001]:ecx[16] FEATURE_MASK_AVX512F = (1u<<16), // cpuid[eax=7,ecx=0] :ebx[16] FEATURE_MASK_AVX512DQ = (1u<<17), // cpuid[eax=7,ecx=0] :ebx[17] FEATURE_MASK_AVX512PF = (1u<<26), // cpuid[eax=7,ecx=0] :ebx[26] FEATURE_MASK_AVX512ER = (1u<<27), // cpuid[eax=7,ecx=0] :ebx[27] FEATURE_MASK_AVX512CD = (1u<<28), // cpuid[eax=7,ecx=0] :ebx[28] FEATURE_MASK_AVX512BW = (1u<<30), // cpuid[eax=7,ecx=0] :ebx[30] FEATURE_MASK_AVX512VL = (1u<<31), // cpuid[eax=7,ecx=0] :ebx[31] FEATURE_MASK_XGETBV = (1u<<26)| (1u<<27), // cpuid[eax=1] :ecx[27:26] XGETBV_MASK_XMM = 0x02u, // xcr0[1] XGETBV_MASK_YMM = 0x04u, // xcr0[2] XGETBV_MASK_ZMM = 0xe0u // xcr0[7:5] }; uint32_t bli_cpuid_query ( uint32_t* family, uint32_t* model, uint32_t* features ) { uint32_t eax, ebx, ecx, edx; uint32_t old_model = 0; uint32_t old_family = 0; uint32_t ext_model = 0; uint32_t ext_family = 0; *family = 0; *model = 0; *features = 0; //fprintf( stderr, "checking cpuid\n" ); uint32_t cpuid_max = __get_cpuid_max( 0, 0 ); uint32_t cpuid_max_ext = __get_cpuid_max( 0x80000000u, 0 ); //fprintf( stderr, "max cpuid leaf: %d\n", cpuid_max ); //fprintf( stderr, "max extended cpuid leaf: %08x\n", cpuid_max_ext ); if ( cpuid_max < 1 ) return VENDOR_UNKNOWN; // The fourth '0' serves as the NULL-terminator for the vendor string. uint32_t vendor_string[4] = { 0, 0, 0, 0 }; // This is actually a macro that modifies the last four operands, // hence why they are not passed by address. __cpuid( 0, eax, vendor_string[0], vendor_string[2], vendor_string[1] ); // Check extended feature bits for post-AVX2 features. if ( cpuid_max >= 7 ) { // This is actually a macro that modifies the last four operands, // hence why they are not passed by address. __cpuid_count( 7, 0, eax, ebx, ecx, edx ); //fprintf( stderr, "cpuid leaf 7:\n" ); //print_binary( eax ); //print_binary( ebx ); //print_binary( ecx ); //print_binary( edx ); if ( bli_cpuid_has_features( ebx, FEATURE_MASK_AVX2 ) ) *features |= FEATURE_AVX2; if ( bli_cpuid_has_features( ebx, FEATURE_MASK_AVX512F ) ) *features |= FEATURE_AVX512F; if ( bli_cpuid_has_features( ebx, FEATURE_MASK_AVX512DQ ) ) *features |= FEATURE_AVX512DQ; if ( bli_cpuid_has_features( ebx, FEATURE_MASK_AVX512PF ) ) *features |= FEATURE_AVX512PF; if ( bli_cpuid_has_features( ebx, FEATURE_MASK_AVX512ER ) ) *features |= FEATURE_AVX512ER; if ( bli_cpuid_has_features( ebx, FEATURE_MASK_AVX512CD ) ) *features |= FEATURE_AVX512CD; if ( bli_cpuid_has_features( ebx, FEATURE_MASK_AVX512BW ) ) *features |= FEATURE_AVX512BW; if ( bli_cpuid_has_features( ebx, FEATURE_MASK_AVX512VL ) ) *features |= FEATURE_AVX512VL; } // Check extended processor info / features bits for AMD-specific features. if ( cpuid_max_ext >= 0x80000001u ) { // This is actually a macro that modifies the last four operands, // hence why they are not passed by address. __cpuid( 0x80000001u, eax, ebx, ecx, edx ); //fprintf(stderr, "extended cpuid leaf 0x80000001:\n"); //print_binary(eax); //print_binary(ebx); //print_binary(ecx); //print_binary(edx); if ( bli_cpuid_has_features( ecx, FEATURE_MASK_FMA4 ) ) *features |= FEATURE_FMA4; } // Unconditionally check processor info / features bits. { // This is actually a macro that modifies the last four operands, // hence why they are not passed by address. __cpuid( 1, eax, ebx, ecx, edx ); //fprintf(stderr, "cpuid leaf 1:\n"); //print_binary(eax); //print_binary(ebx); //print_binary(ecx); //print_binary(edx); /* cpuid(eax=1): eax[27:0] 3: 0 - Stepping 7: 4 - Model 11: 8 - Family 13:12 - Processor Type 19:16 - Extended Model 27:20 - Extended Family Intel and AMD have suggested applications to display the family of a CPU as the sum of the "Family" and the "Extended Family" fields shown above, and the model as the sum of the "Model" and the 4-bit left-shifted "Extended Model" fields. If "Family" is different than 6 or 15, only the "Family" and "Model" fields should be used while the "Extended Family" and "Extended Model" bits are reserved. If "Family" is set to 15, then "Extended Family" and the 4-bit left-shifted "Extended Model" should be added to the respective base values, and if "Family" is set to 6, then only the 4-bit left-shifted "Extended Model" should be added to "Model". */ old_model = ( eax >> 4 ) & ( 0xF ); // bits 7:4 old_family = ( eax >> 8 ) & ( 0xF ); // bits 11:8 ext_model = ( eax >> 16 ) & ( 0xF ); // bits 19:16 ext_family = ( eax >> 20 ) & ( 0xFF ); // bits 27:20 // Set the display model and family values based on the original family // value. See explanation above. if ( old_family == 6 ) { *model = ( ext_model << 4 ) + old_model; *family = old_family; } else if ( old_family == 15 ) { *model = ( ext_model << 4 ) + old_model; *family = ( ext_family ) + old_family; } else { *model = old_model; *family = old_family; } // Check for SSE, AVX, and FMA3 features. if ( bli_cpuid_has_features( ecx, FEATURE_MASK_SSE3 ) ) *features |= FEATURE_SSE3; if ( bli_cpuid_has_features( ecx, FEATURE_MASK_SSSE3 ) ) *features |= FEATURE_SSSE3; if ( bli_cpuid_has_features( ecx, FEATURE_MASK_SSE41 ) ) *features |= FEATURE_SSE41; if ( bli_cpuid_has_features( ecx, FEATURE_MASK_SSE42 ) ) *features |= FEATURE_SSE42; if ( bli_cpuid_has_features( ecx, FEATURE_MASK_AVX ) ) *features |= FEATURE_AVX; if ( bli_cpuid_has_features( ecx, FEATURE_MASK_FMA3 ) ) *features |= FEATURE_FMA3; // Check whether the hardware supports xsave/xrestor/xsetbv/xgetbv AND // support for these is enabled by the OS. If so, then we proceed with // checking that various register-state saving features are available. if ( bli_cpuid_has_features( ecx, FEATURE_MASK_XGETBV ) ) { uint32_t xcr = 0; // Call xgetbv to get xcr0 (the extended control register) copied // to [edx:eax]. This encodes whether software supports various // register state-saving features. __asm__ __volatile__ ( ".byte 0x0F, 0x01, 0xD0" : "=a" (eax), "=d" (edx) : "c" (xcr) : "cc" ); //fprintf(stderr, "xcr0:\n"); //print_binary(eax); //print_binary(edx); //fprintf(stderr, "xgetbv: xmm: %d\n", bli_cpuid_has_features(eax, XGETBV_MASK_XMM)); //fprintf(stderr, "xgetbv: ymm: %d\n", bli_cpuid_has_features(eax, XGETBV_MASK_XMM| // XGETBV_MASK_YMM)); //fprintf(stderr, "xgetbv: zmm: %d\n", bli_cpuid_has_features(eax, XGETBV_MASK_XMM| // XGETBV_MASK_YMM| // XGETBV_MASK_ZMM)); // The OS can manage the state of 512-bit zmm (AVX-512) registers // only if the xcr[7:5] bits are set. If they are not set, then // clear all feature bits related to AVX-512. if ( !bli_cpuid_has_features( eax, XGETBV_MASK_XMM | XGETBV_MASK_YMM | XGETBV_MASK_ZMM ) ) { *features &= ~( FEATURE_AVX512F | FEATURE_AVX512DQ | FEATURE_AVX512PF | FEATURE_AVX512ER | FEATURE_AVX512CD | FEATURE_AVX512BW | FEATURE_AVX512VL ); } // The OS can manage the state of 256-bit ymm (AVX) registers // only if the xcr[2] bit is set. If it is not set, then // clear all feature bits related to AVX. if ( !bli_cpuid_has_features( eax, XGETBV_MASK_XMM | XGETBV_MASK_YMM ) ) { *features &= ~( FEATURE_AVX | FEATURE_AVX2 | FEATURE_FMA3 | FEATURE_FMA4 ); } // The OS can manage the state of 128-bit xmm (SSE) registers // only if the xcr[1] bit is set. If it is not set, then // clear all feature bits related to SSE (which means the // entire bitfield is clear). if ( !bli_cpuid_has_features( eax, XGETBV_MASK_XMM ) ) { *features = 0; } } else { // If the hardware does not support xsave/xrestor/xsetbv/xgetbv, // OR these features are not enabled by the OS, then we clear // the bitfield, because it means that not even xmm support is // present. //fprintf(stderr, "xgetbv: no\n"); features = 0; } } //fprintf(stderr, "vendor: %12s\n", vendor_string); //fprintf(stderr, "family: %d\n", family); //fprintf(stderr, "model: %d\n", model); //fprintf(stderr, "sse3: %d\n", bli_cpuid_has_features(features, FEATURE_SSE3)); //fprintf(stderr, "ssse3: %d\n", bli_cpuid_has_features(features, FEATURE_SSSE3)); //fprintf(stderr, "sse4.1: %d\n", bli_cpuid_has_features(features, FEATURE_SSE41)); //fprintf(stderr, "sse4.2: %d\n", bli_cpuid_has_features(features, FEATURE_SSE42)); //fprintf(stderr, "avx: %d\n", bli_cpuid_has_features(features, FEATURE_AVX)); //fprintf(stderr, "avx2: %d\n", bli_cpuid_has_features(features, FEATURE_AVX2)); //fprintf(stderr, "fma3: %d\n", bli_cpuid_has_features(features, FEATURE_FMA3)); //fprintf(stderr, "fma4: %d\n", bli_cpuid_has_features(features, FEATURE_FMA4)); //fprintf(stderr, "avx512f: %d\n", bli_cpuid_has_features(features, FEATURE_AVX512F)); //fprintf(stderr, "avx512pf: %d\n", bli_cpuid_has_features(features, FEATURE_AVX512PF)); //fprintf(stderr, "avx512dq: %d\n", bli_cpuid_has_features(features, FEATURE_AVX512DQ)); // Check the vendor string and return a value to indicate Intel or AMD. if ( strcmp( ( char* )vendor_string, "AuthenticAMD" ) == 0 ) return VENDOR_AMD; else if ( strcmp( ( char* )vendor_string, "GenuineIntel" ) == 0 ) return VENDOR_INTEL; else return VENDOR_UNKNOWN; } void get_cpu_name( char *cpu_name ) { uint32_t eax, ebx, ecx, edx; __cpuid( 0x80000002u, eax, ebx, ecx, edx ); //printf("%x %x %x %x\n", eax, ebx, ecx, edx); *( uint32_t* )&cpu_name[0 + 0] = eax; *( uint32_t* )&cpu_name[0 + 4] = ebx; *( uint32_t* )&cpu_name[0 + 8] = ecx; *( uint32_t* )&cpu_name[0 +12] = edx; __cpuid( 0x80000003u, eax, ebx, ecx, edx ); //printf("%x %x %x %x\n", eax, ebx, ecx, edx); *( uint32_t* )&cpu_name[16+ 0] = eax; *( uint32_t* )&cpu_name[16+ 4] = ebx; *( uint32_t* )&cpu_name[16+ 8] = ecx; *( uint32_t* )&cpu_name[16+12] = edx; __cpuid( 0x80000004u, eax, ebx, ecx, edx ); //printf("%x %x %x %x\n", eax, ebx, ecx, edx); *( uint32_t* )&cpu_name[32+ 0] = eax; *( uint32_t* )&cpu_name[32+ 4] = ebx; *( uint32_t* )&cpu_name[32+ 8] = ecx; *( uint32_t* )&cpu_name[32+12] = edx; } // Return the number of FMA units _assuming avx512 is supported_. // This needs updating for new processor types, sigh. // See https://ark.intel.com/content/www/us/en/ark.html#@Processors // and also https://github.com/jeffhammond/vpu-count int vpu_count( void ) { char cpu_name[48] = {}; char* loc; char model_num[5]; int sku; get_cpu_name( cpu_name ); if ( strstr( cpu_name, "Intel(R) Xeon(R)" ) != NULL ) { if (( loc = strstr( cpu_name, "Platinum" ) )) return 2; if ( loc == NULL ) loc = strstr( cpu_name, "Gold" ); // 1 or 2, tested below if ( loc == NULL ) if (( loc = strstr( cpu_name, "Silver" ) )) return 1; if ( loc == NULL ) if (( loc = strstr( cpu_name, "Bronze" ) )) return 1; if ( loc == NULL ) loc = strstr( cpu_name, "W" ); if ( loc == NULL ) if (( loc = strstr( cpu_name, "D" ) )) // Fixme: May be wrong // return 1; if ( loc == NULL ) return -1; // We may have W-nnnn rather than, say, Gold nnnn if ( 'W' == *loc && '-' == *(loc+1) ) loc++; else loc = strstr( loc+1, " " ); if ( loc == NULL ) return -1; strncpy( model_num, loc+1, 4 ); model_num[4] = '\0'; // Things like i9-10900X matched above sku = atoi( model_num ); // These were derived from ARK listings as of 2019-10-09, but // may not be complete, especially as the ARK Skylake listing // seems to be limited. if ( 8199 >= sku && sku >= 8100 ) return 2; else if ( 6199 >= sku && sku >= 6100 ) return 2; else if ( sku == 5122 ) return 2; else if ( 6299 >= sku && sku >= 6200 ) return 2; // Cascade Lake Gold else if ( 5299 >= sku && sku >= 5200 ) return 1; // Cascade Lake Gold else if ( 5199 >= sku && sku >= 5100 ) return 1; else if ( 4199 >= sku && sku >= 4100 ) return 1; else if ( 3199 >= sku && sku >= 3100 ) return 1; else if ( 3299 >= sku && sku >= 3200 ) return 2; // Cascade Lake W else if ( 2299 >= sku && sku >= 2200 ) return 2; // Cascade Lake W else if ( 2199 >= sku && sku >= 2120 ) return 2; else if ( 2102 == sku || sku == 2104 ) return 2; // Gold exceptions else if ( 2119 >= sku && sku >= 2100 ) return 1; else return -1; } else if ( strstr( cpu_name, "Intel(R) Core(TM)" ) != NULL ) return 2; // All i7/i9 with avx512? else { return -1; } } #elif defined(__aarch64__) #ifdef __linux__ // This is adapted from OpenBLAS. See // https://www.kernel.org/doc/html/latest/arm64/cpu-feature-registers.html // for the mechanism, but not the magic numbers. // Fixme: Could these be missing in older Linux? #include #include #ifndef HWCAP_CPUID #define HWCAP_CPUID (1 << 11) #endif /* From https://www.kernel.org/doc/html/latest/arm64/sve.html and the aarch64 hwcap.h */ #ifndef HWCAP_SVE #define HWCAP_SVE (1 << 22) #endif /* Maybe also for AT_HWCAP2 #define HWCAP2_SVE2(1 << 1) et al ) */ #endif //__linux__ #ifdef __APPLE__ #include // #include #endif static uint32_t get_coretype ( uint32_t* features ) { int implementer = 0x00, part = 0x000; *features = FEATURE_NEON; #ifdef __linux__ if ( getauxval( AT_HWCAP ) & HWCAP_CPUID ) { // Also available from // /sys/devices/system/cpu/cpu0/regs/identification/midr_el1 // and split out in /proc/cpuinfo (with a tab before the colon): // CPU part : 0x0a1 uint64_t midr_el1; __asm("mrs %0, MIDR_EL1" : "=r" (midr_el1)); /* * MIDR_EL1 * * 31 24 23 20 19 16 15 4 3 0 * ----------------------------------------------------------------- * | Implementer | Variant | Architecture | Part Number | Revision | * ----------------------------------------------------------------- */ implementer = (midr_el1 >> 24) & 0xFF; part = (midr_el1 >> 4) & 0xFFF; } bool has_sve = getauxval( AT_HWCAP ) & HWCAP_SVE; if (has_sve) *features |= FEATURE_SVE; #endif //__linux__ #ifdef __APPLE__ // Better values could be obtained from sysctlbyname() implementer = 0x61; //Apple part = 0x023; //Firestorm #endif //__APPLE__ // From Linux arch/arm64/include/asm/cputype.h // ARM_CPU_IMP_ARM 0x41 // ARM_CPU_IMP_APM 0x50 // ARM_CPU_IMP_CAVIUM 0x43 // ARM_CPU_IMP_BRCM 0x42 // ARM_CPU_IMP_QCOM 0x51 // ARM_CPU_IMP_NVIDIA 0x4E // ARM_CPU_IMP_FUJITSU 0x46 // ARM_CPU_IMP_HISI 0x48 // ARM_CPU_IMP_APPLE 0x61 // // ARM_CPU_PART_AEM_V8 0xD0F // ARM_CPU_PART_FOUNDATION 0xD00 // ARM_CPU_PART_CORTEX_A57 0xD07 // ARM_CPU_PART_CORTEX_A72 0xD08 // ARM_CPU_PART_CORTEX_A53 0xD03 // ARM_CPU_PART_CORTEX_A73 0xD09 // ARM_CPU_PART_CORTEX_A75 0xD0A // ARM_CPU_PART_CORTEX_A35 0xD04 // ARM_CPU_PART_CORTEX_A55 0xD05 // ARM_CPU_PART_CORTEX_A76 0xD0B // ARM_CPU_PART_NEOVERSE_N1 0xD0C // ARM_CPU_PART_CORTEX_A77 0xD0D // from GCC: // ARM_CPU_PART_CORTEX_A78 0xd41 // ARM_CPU_PART_CORTEX_X1 0xd44 // ARM_CPU_PART_CORTEX_V1 0xd40 // ARM_CPU_PART_CORTEX_N2 0xd49 // ARM_CPU_PART_CORTEX_R82 0xd15 // // APM_CPU_PART_POTENZA 0x000 // // CAVIUM_CPU_PART_THUNDERX 0x0A1 // CAVIUM_CPU_PART_THUNDERX_81XX 0x0A2 // CAVIUM_CPU_PART_THUNDERX_83XX 0x0A3 // CAVIUM_CPU_PART_THUNDERX2 0x0AF // CAVIUM_CPU_PART_THUNDERX3 0x0B8 // taken from OpenBLAS // // BRCM_CPU_PART_BRAHMA_B53 0x100 // BRCM_CPU_PART_VULCAN 0x516 // // QCOM_CPU_PART_FALKOR_V1 0x800 // QCOM_CPU_PART_FALKOR 0xC00 // QCOM_CPU_PART_KRYO 0x200 // QCOM_CPU_PART_KRYO_3XX_SILVER 0x803 // QCOM_CPU_PART_KRYO_4XX_GOLD 0x804 // QCOM_CPU_PART_KRYO_4XX_SILVER 0x805 // // NVIDIA_CPU_PART_DENVER 0x003 // NVIDIA_CPU_PART_CARMEL 0x004 // // FUJITSU_CPU_PART_A64FX 0x001 // // HISI_CPU_PART_TSV110 0xD01 // APPLE_CPU_PART_M1_ICESTORM 0x022 // APPLE_CPU_PART_M1_FIRESTORM 0x023 // Fixme: After merging the vpu_count branch we could report the // part here with bli_dolog. switch(implementer) { case 0x41: // ARM switch (part) { #ifdef BLIS_CONFIG_CORTEXA57 case 0xd07: // Cortex A57 return BLIS_ARCH_CORTEXA57; #endif #ifdef BLIS_CONFIG_CORTEXA53 case 0xd03: // Cortex A53 return BLIS_ARCH_CORTEXA53; #endif #ifdef BLIS_CONFIG_THUNDERX2 case 0xd0c: // Neoverse N1 (and Graviton G2?) return BLIS_ARCH_THUNDERX2; //placeholder for N1 #endif } break; case 0x42: // Broadcom switch (part) { #ifdef BLIS_CONFIG_THUNDERX2 case 0x516: // Vulcan return BLIS_ARCH_THUNDERX2; #endif } break; case 0x43: // Cavium switch (part) { #ifdef BLIS_CONFIG_THUNDERX2 case 0x0af: // ThunderX2 case 0x0b8: // ThunderX3 return BLIS_ARCH_THUNDERX2; #endif } break; case 0x46: // Fujitsu switch (part) { #ifdef BLIS_CONFIG_A64FX case 0x001: // A64FX return BLIS_ARCH_A64FX; #endif } break; case 0x61: // Apple switch (part) { #ifdef BLIS_CONFIG_FIRESTORM case 0x022: // Icestorm (M1.LITTLE) case 0x023: // Firestorm (M1.big) return BLIS_ARCH_FIRESTORM; #endif } break; } #ifdef BLIS_CONFIG_ARMSVE if (has_sve) return BLIS_ARCH_ARMSVE; #endif // Can't use #if defined(...) here because of parsing done for autoconfiguration #ifdef BLIS_CONFIG_CORTEXA57 return BLIS_ARCH_CORTEXA57; #else #ifdef BLIS_CONFIG_CORTEXA53 return BLIS_ARCH_CORTEXA53; #else return BLIS_ARCH_GENERIC; #endif #endif } uint32_t bli_cpuid_query ( uint32_t* model, uint32_t* part, uint32_t* features ) { *model = MODEL_ARMV8; *part = get_coretype(features); return VENDOR_ARM; } #elif defined(__arm__) || defined(_M_ARM) /* I can't easily find documentation to do this as for aarch64, though it presumably could be unearthed from Linux code. However, on Linux 5.2 (and Androids's 3.4), /proc/cpuinfo has this sort of thing, used below: CPU implementer : 0x41 CPU architecture: 7 CPU variant : 0x3 CPU part : 0xc09 The complication for family selection is that Neon is optional for CortexA9, for instance. That's tested in bli_cpuid_is_cortexa9. */ #define TEMP_BUFFER_SIZE 200 uint32_t bli_cpuid_query ( uint32_t* model, uint32_t* part, uint32_t* features ) { *model = MODEL_UNKNOWN; *part = 0; *features = 0; char* pci_str = "/proc/cpuinfo"; char proc_str[ TEMP_BUFFER_SIZE ]; char ptno_str[ TEMP_BUFFER_SIZE ]; char feat_str[ TEMP_BUFFER_SIZE ]; char* r_val; //printf( "bli_cpuid_query(): beginning search\n" ); // Search /proc/cpuinfo for the 'Processor' entry. r_val = find_string_in( "Processor", proc_str, TEMP_BUFFER_SIZE, pci_str ); if ( r_val == NULL ) return VENDOR_ARM; // Search /proc/cpuinfo for the 'CPU part' entry. r_val = find_string_in( "CPU part", ptno_str, TEMP_BUFFER_SIZE, pci_str ); if ( r_val == NULL ) return VENDOR_ARM; // Search /proc/cpuinfo for the 'Features' entry. r_val = find_string_in( "Features", feat_str, TEMP_BUFFER_SIZE, pci_str ); if ( r_val == NULL ) return VENDOR_ARM; #if 0 printf( "bli_cpuid_query(): full processor string: %s\n", proc_str ); printf( "bli_cpuid_query(): full part num string: %s\n", ptno_str ); printf( "bli_cpuid_query(): full features string: %s\n", feat_str ); #endif // Parse the feature string to check for SIMD features. if ( strstr( feat_str, "neon" ) != NULL || strstr( feat_str, "asimd" ) != NULL ) *features |= FEATURE_NEON; // Parse the feature string to check for SVE features. if ( strstr( feat_str, "sve" ) != NULL ) *features |= FEATURE_SVE; //printf( "bli_cpuid_query(): features var: %u\n", *features ); // Parse the processor string to uncover the model. if ( strstr( proc_str, "ARMv7" ) != NULL ) *model = MODEL_ARMV7; else if ( strstr( proc_str, "AArch64" ) != NULL || strstr( proc_str, "ARMv8" ) ) *model = MODEL_ARMV8; //printf( "bli_cpuid_query(): model: %u\n", *model ); // Parse the part number string. r_val = strstr( ptno_str, "0x" ); if ( r_val != NULL) { *part = strtol( r_val, NULL, 16 ); } //printf( "bli_cpuid_query(): part#: %x\n", *part ); return VENDOR_ARM; } char* find_string_in( char* target, char* buffer, size_t buf_len, char* filepath ) { // This function searches for the first line of the file located at // 'filepath' that contains the string 'target' and then copies that // line (actually, the substring of the line starting with 'target') // to 'buffer', which is 'buf_len' bytes long. char* r_val = NULL; // Allocate a temporary local buffer equal to the size of buffer. char* buf_local = malloc( buf_len * sizeof( char ) ); // Open the file stream. FILE* stream = fopen( filepath, "r" ); // Repeatedly read in a line from the stream, storing the contents of // the stream into buf_local. while ( !feof( stream ) ) { // Read in the current line, up to buf_len-1 bytes. r_val = fgets( buf_local, buf_len-1, stream ); //printf( "read line: %s", buf_local ); // fgets() returns the pointer specified by the first argument (in // this case, buf_local) on success and NULL on error. if ( r_val == NULL ) break; // Since fgets() was successful, we can search for the target string // within the current line, as captured in buf_local. r_val = strstr( buf_local, target ); // If the target string was found in buf_local, we save it to buffer. if ( r_val != NULL ) { //printf( " found match to '%s'\n", target ); // Copy the string read by fgets() to the caller's buffer. strncpy( buffer, buf_local, buf_len ); // Make sure that we have a terminating null character by the // end of the buffer. if ( buf_len > 0 ) buffer[ buf_len - 1 ] = '\0'; // Leave the loop since we found the target string. break; } } // Close the file stream. fclose( stream ); // Free the temporary local buffer. free( buf_local ); // Return r_val so the caller knows if we failed. return r_val; } #endif blis-0.9.0/frame/base/bli_cpuid.h000066400000000000000000000153231422157504600165720ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018-2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #if 0 // Used only during standalone testing of ARM support. #define FALSE 0 #define TRUE 1 typedef enum { BLIS_ARCH_CORTEXA57 = 10, BLIS_ARCH_CORTEXA15 = 11, BLIS_ARCH_CORTEXA9 = 12, BLIS_ARCH_GENERIC = 13 } arch_t; typedef uint64_t bool; #define bli_abort abort #endif #ifndef BLIS_CPUID_H #define BLIS_CPUID_H arch_t bli_cpuid_query_id( void ); // Intel bool bli_cpuid_is_skx( uint32_t family, uint32_t model, uint32_t features ); bool bli_cpuid_is_knl( uint32_t family, uint32_t model, uint32_t features ); bool bli_cpuid_is_haswell( uint32_t family, uint32_t model, uint32_t features ); bool bli_cpuid_is_sandybridge( uint32_t family, uint32_t model, uint32_t features ); bool bli_cpuid_is_penryn( uint32_t family, uint32_t model, uint32_t features ); // AMD bool bli_cpuid_is_zen3( uint32_t family, uint32_t model, uint32_t features ); bool bli_cpuid_is_zen2( uint32_t family, uint32_t model, uint32_t features ); bool bli_cpuid_is_zen( uint32_t family, uint32_t model, uint32_t features ); bool bli_cpuid_is_excavator( uint32_t family, uint32_t model, uint32_t features ); bool bli_cpuid_is_steamroller( uint32_t family, uint32_t model, uint32_t features ); bool bli_cpuid_is_piledriver( uint32_t family, uint32_t model, uint32_t features ); bool bli_cpuid_is_bulldozer( uint32_t family, uint32_t model, uint32_t features ); // ARM bool bli_cpuid_is_thunderx2( uint32_t model, uint32_t part, uint32_t features ); bool bli_cpuid_is_cortexa57( uint32_t model, uint32_t part, uint32_t features ); bool bli_cpuid_is_cortexa53( uint32_t model, uint32_t part, uint32_t features ); bool bli_cpuid_is_armsve( uint32_t model, uint32_t part, uint32_t features ); bool bli_cpuid_is_a64fx( uint32_t model, uint32_t part, uint32_t features ); bool bli_cpuid_is_cortexa15( uint32_t model, uint32_t part, uint32_t features ); bool bli_cpuid_is_cortexa9( uint32_t model, uint32_t part, uint32_t features ); uint32_t bli_cpuid_query( uint32_t* family, uint32_t* model, uint32_t* features ); // ----------------------------------------------------------------------------- // // This section of the file was based off of cpuid.hpp from TBLIS [1]. // // [1] https://github.com/devinamatthews/tblis // /* Copyright (C) 2017, The University of Texas at Austin Copyright (C) 2017, Devin Matthews 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ BLIS_INLINE bool bli_cpuid_has_features( uint32_t have, uint32_t want ) { return ( have & want ) == want; } // ----------------------------------------------------------------------------- #if defined(__x86_64__) || defined(_M_X64) || defined(__i386) || defined(_M_IX86) // cpuid.h is now #included in bli_cpuid.c instead of here. See issue #393 // for more information why this move was made. //#include "cpuid.h" void get_cpu_name( char *cpu_name ); int vpu_count( void ); enum { VENDOR_INTEL = 0, VENDOR_AMD, VENDOR_UNKNOWN }; enum { FEATURE_SSE3 = 0x0001, FEATURE_SSSE3 = 0x0002, FEATURE_SSE41 = 0x0004, FEATURE_SSE42 = 0x0008, FEATURE_AVX = 0x0010, FEATURE_AVX2 = 0x0020, FEATURE_FMA3 = 0x0040, FEATURE_FMA4 = 0x0080, FEATURE_AVX512F = 0x0100, FEATURE_AVX512DQ = 0x0200, FEATURE_AVX512PF = 0x0400, FEATURE_AVX512ER = 0x0800, FEATURE_AVX512CD = 0x1000, FEATURE_AVX512BW = 0x2000, FEATURE_AVX512VL = 0x4000 }; #elif defined(__aarch64__) || defined(__arm__) || defined(_M_ARM) char* find_string_in( char* target, char* buffer, size_t buf_len, char* filepath ); enum { VENDOR_ARM = 0, VENDOR_UNKNOWN }; enum { MODEL_ARMV7 = 0, MODEL_ARMV8, MODEL_UNKNOWN }; enum { FEATURE_NEON = 0x01, FEATURE_SVE = 0x02 }; #endif #endif blis-0.9.0/frame/base/bli_env.c000066400000000000000000000106131422157504600162460ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifdef BLIS_CONFIGURETIME_CPUID // NOTE: If you need to make any changes to this cpp branch, it's probably // the case that you also need to modify bli_arch.c, bli_cpuid.c, and // bli_env.c. Don't forget to update these other files as needed! // The BLIS_ENABLE_SYSTEM macro must be defined so that the correct cpp // branch in bli_system.h is processed. (This macro is normally defined in // bli_config.h.) #define BLIS_ENABLE_SYSTEM // Use C-style static inline functions for any static inline functions that // happen to be defined by the headers below. (This macro is normally defined // in bli_config_macro_defs.h.) #define BLIS_INLINE static // Since we're not building a shared library, we can forgo the use of the // BLIS_EXPORT_BLIS annotations by #defining them to be nothing. (This macro // is normally defined in bli_config_macro_defs.h.) #define BLIS_EXPORT_BLIS #include "bli_system.h" #include "bli_type_defs.h" //#include "bli_arch.h" //#include "bli_cpuid.h" #include "bli_env.h" #else #include "blis.h" #endif // ----------------------------------------------------------------------------- gint_t bli_env_get_var( const char* env, gint_t fallback ) { gint_t r_val; char* str; // Query the environment variable and store the result in str. str = getenv( env ); // Set the return value based on the string obtained from getenv(). if ( str != NULL ) { // If there was no error, convert the string to an integer and // prepare to return that integer. r_val = ( gint_t )strtol( str, NULL, 10 ); } else { // If there was an error, use the "fallback" as the return value. r_val = fallback; } return r_val; } #if 0 #ifdef _MSC_VER #define strerror_r(errno,buf,len) strerror_s(buf,len,errno) #endif void bli_env_set_var( const char* env, dim_t value ) { dim_t r_val; char value_str[32]; const char* fs_32 = "%u"; const char* fs_64 = "%lu"; // Convert the string to an integer, but vary the format specifier // depending on the integer type size. if ( bli_info_get_int_type_size() == 32 ) sprintf( value_str, fs_32, value ); else sprintf( value_str, fs_64, value ); // Set the environment variable using the string we just wrote to via // sprintf(). (The 'TRUE' argument means we want to overwrite the current // value if the environment variable already exists.) r_val = bli_setenv( env, value_str, TRUE ); // Check the return value in case something went horribly wrong. if ( r_val == -1 ) { char err_str[128]; // Query the human-readable error string corresponding to errno. strerror_r( errno, err_str, 128 ); // Print the error message. bli_print_msg( err_str, __FILE__, __LINE__ ); } } #endif blis-0.9.0/frame/base/bli_env.h000066400000000000000000000036431422157504600162600ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2016, Hewlett Packard Enterprise Development LP Copyright (C) 2018, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_ENV_H #define BLIS_ENV_H gint_t bli_env_get_var( const char* env, gint_t fallback ); //void bli_env_set_var( const char* env, dim_t value ); #endif blis-0.9.0/frame/base/bli_error.c000066400000000000000000000206771422157504600166220ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // Internal array to hold error strings. static char *bli_error_string[-BLIS_ERROR_CODE_MAX] = { [-BLIS_INVALID_ERROR_CHECKING_LEVEL] = "Invalid error checking level.", [-BLIS_UNDEFINED_ERROR_CODE] = "Undefined error code.", [-BLIS_NULL_POINTER] = "Encountered unexpected null pointer.", [-BLIS_NOT_YET_IMPLEMENTED] = "Requested functionality not yet implemented.", [-BLIS_INVALID_SIDE] = "Invalid side parameter value.", [-BLIS_INVALID_UPLO] = "Invalid uplo_t parameter value.", [-BLIS_INVALID_TRANS] = "Invalid trans_t parameter value.", [-BLIS_INVALID_CONJ] = "Invalid conj_t parameter value.", [-BLIS_INVALID_DIAG] = "Invalid diag_t parameter value.", [-BLIS_EXPECTED_NONUNIT_DIAG] = "Expected object with non-unit diagonal.", [-BLIS_INVALID_DATATYPE] = "Invalid datatype value.", [-BLIS_EXPECTED_FLOATING_POINT_DATATYPE] = "Expected floating-point datatype value.", [-BLIS_EXPECTED_NONINTEGER_DATATYPE] = "Expected non-integer datatype value.", [-BLIS_EXPECTED_NONCONSTANT_DATATYPE] = "Expected non-constant datatype value.", [-BLIS_EXPECTED_REAL_DATATYPE] = "Expected real datatype value.", [-BLIS_EXPECTED_INTEGER_DATATYPE] = "Expected integer datatype value.", [-BLIS_INCONSISTENT_DATATYPES] = "Expected consistent datatypes (equal, or one being constant).", [-BLIS_EXPECTED_REAL_PROJ_OF] = "Expected second datatype to be real projection of first.", [-BLIS_EXPECTED_REAL_VALUED_OBJECT] = "Expected real-valued object (ie: if complex, imaginary component equals zero).", [-BLIS_INCONSISTENT_PRECISIONS] = "Expected consistent precisions (both single or both double).", [-BLIS_NONCONFORMAL_DIMENSIONS] = "Encountered non-conformal dimensions between objects.", [-BLIS_EXPECTED_SCALAR_OBJECT] = "Expected scalar object.", [-BLIS_EXPECTED_VECTOR_OBJECT] = "Expected vector object.", [-BLIS_UNEQUAL_VECTOR_LENGTHS] = "Encountered unequal vector lengths.", [-BLIS_EXPECTED_SQUARE_OBJECT] = "Expected square object.", [-BLIS_UNEXPECTED_OBJECT_LENGTH] = "Unexpected object length.", [-BLIS_UNEXPECTED_OBJECT_WIDTH] = "Unexpected object width.", [-BLIS_UNEXPECTED_VECTOR_DIM] = "Unexpected vector dimension.", [-BLIS_UNEXPECTED_DIAG_OFFSET] = "Unexpected object diagonal offset.", [-BLIS_NEGATIVE_DIMENSION] = "Encountered negative dimension.", [-BLIS_INVALID_ROW_STRIDE] = "Encountered invalid row stride relative to n dimension.", [-BLIS_INVALID_COL_STRIDE] = "Encountered invalid col stride relative to m dimension.", [-BLIS_INVALID_DIM_STRIDE_COMBINATION] = "Encountered invalid stride/dimension combination.", [-BLIS_EXPECTED_GENERAL_OBJECT] = "Expected general object.", [-BLIS_EXPECTED_HERMITIAN_OBJECT] = "Expected Hermitian object.", [-BLIS_EXPECTED_SYMMETRIC_OBJECT] = "Expected symmetric object.", [-BLIS_EXPECTED_TRIANGULAR_OBJECT] = "Expected triangular object.", [-BLIS_EXPECTED_UPPER_OR_LOWER_OBJECT] = "Expected upper or lower triangular object.", [-BLIS_INVALID_3x1_SUBPART] = "Encountered invalid 3x1 (vertical) subpartition label.", [-BLIS_INVALID_1x3_SUBPART] = "Encountered invalid 1x3 (horizontal) subpartition label.", [-BLIS_INVALID_3x3_SUBPART] = "Encountered invalid 3x3 (diagonal) subpartition label.", [-BLIS_UNEXPECTED_NULL_CONTROL_TREE] = "Encountered unexpected null control tree node.", [-BLIS_PACK_SCHEMA_NOT_SUPPORTED_FOR_UNPACK] = "Pack schema not yet supported/implemented for use with unpacking.", [-BLIS_EXPECTED_NONNULL_OBJECT_BUFFER] = "Encountered object with non-zero dimensions containing null buffer.", [-BLIS_MALLOC_RETURNED_NULL] = "malloc() returned NULL; heap memory is likely exhausted.", [-BLIS_INVALID_PACKBUF] = "Invalid packbuf_t value.", [-BLIS_EXHAUSTED_CONTIG_MEMORY_POOL] = "Attempted to allocate more memory from contiguous pool than is available.", [-BLIS_INSUFFICIENT_STACK_BUF_SIZE] = "Configured maximum stack buffer size is insufficient for register blocksizes currently in use.", [-BLIS_ALIGNMENT_NOT_POWER_OF_TWO] = "Encountered memory alignment value that is either zero or not a power of two.", [-BLIS_ALIGNMENT_NOT_MULT_OF_PTR_SIZE] = "Encountered memory alignment value that is not a multiple of sizeof(void*).", [-BLIS_EXPECTED_OBJECT_ALIAS] = "Expected object to be alias.", [-BLIS_INVALID_ARCH_ID] = "Invalid architecture id value.", [-BLIS_UNINITIALIZED_GKS_CNTX] = "Accessed uninitialized context in gks; BLIS_ARCH_TYPE is probably set to an invalid architecture id.", [-BLIS_MC_DEF_NONMULTIPLE_OF_MR] = "Default MC is non-multiple of MR for one or more datatypes.", [-BLIS_MC_MAX_NONMULTIPLE_OF_MR] = "Maximum MC is non-multiple of MR for one or more datatypes.", [-BLIS_NC_DEF_NONMULTIPLE_OF_NR] = "Default NC is non-multiple of NR for one or more datatypes.", [-BLIS_NC_MAX_NONMULTIPLE_OF_NR] = "Maximum NC is non-multiple of NR for one or more datatypes.", [-BLIS_KC_DEF_NONMULTIPLE_OF_KR] = "Default KC is non-multiple of KR for one or more datatypes.", [-BLIS_KC_MAX_NONMULTIPLE_OF_KR] = "Maximum KC is non-multiple of KR for one or more datatypes.", }; // ----------------------------------------------------------------------------- void bli_print_msg( char* str, char* file, guint_t line ) { fprintf( stderr, "\n" ); fprintf( stderr, "libblis: %s (line %lu):\n", file, ( long unsigned int )line ); fprintf( stderr, "libblis: %s\n", str ); fflush( stderr ); } void bli_abort( void ) { fprintf( stderr, "libblis: Aborting.\n" ); //raise( SIGABRT ); abort(); } // ----------------------------------------------------------------------------- // Current error checking level. static BLIS_THREAD_LOCAL errlev_t bli_err_chk_level = BLIS_FULL_ERROR_CHECKING; errlev_t bli_error_checking_level( void ) { return bli_err_chk_level; } void bli_error_checking_level_set( errlev_t new_level ) { err_t e_val; e_val = bli_check_valid_error_level( new_level ); bli_check_error_code( e_val ); bli_err_chk_level = new_level; } bool bli_error_checking_is_enabled( void ) { return bli_error_checking_level() != BLIS_NO_ERROR_CHECKING; } char* bli_error_string_for_code( gint_t code ) { return bli_error_string[-code]; } blis-0.9.0/frame/base/bli_error.h000066400000000000000000000041161422157504600166150ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ BLIS_EXPORT_BLIS errlev_t bli_error_checking_level( void ); BLIS_EXPORT_BLIS void bli_error_checking_level_set( errlev_t new_level ); BLIS_EXPORT_BLIS bool bli_error_checking_is_enabled( void ); void bli_print_msg( char* str, char* file, guint_t line ); BLIS_EXPORT_BLIS void bli_abort( void ); char* bli_error_string_for_code( gint_t code ); blis-0.9.0/frame/base/bli_func.c000066400000000000000000000061421422157504600164130ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" func_t* bli_func_create ( void_fp ptr_s, void_fp ptr_d, void_fp ptr_c, void_fp ptr_z ) { func_t* f; err_t r_val; f = ( func_t* )bli_malloc_intl( sizeof( func_t ), &r_val ); bli_func_init ( f, ptr_s, ptr_d, ptr_c, ptr_z ); return f; } void bli_func_init ( func_t* f, void_fp ptr_s, void_fp ptr_d, void_fp ptr_c, void_fp ptr_z ) { bli_func_set_dt( ptr_s, BLIS_FLOAT, f ); bli_func_set_dt( ptr_d, BLIS_DOUBLE, f ); bli_func_set_dt( ptr_c, BLIS_SCOMPLEX, f ); bli_func_set_dt( ptr_z, BLIS_DCOMPLEX, f ); } void bli_func_init_null ( func_t* f ) { bli_func_set_dt( NULL, BLIS_FLOAT, f ); bli_func_set_dt( NULL, BLIS_DOUBLE, f ); bli_func_set_dt( NULL, BLIS_SCOMPLEX, f ); bli_func_set_dt( NULL, BLIS_DCOMPLEX, f ); } void bli_func_free( func_t* f ) { bli_free_intl( f ); } // ----------------------------------------------------------------------------- bool bli_func_is_null_dt( num_t dt, func_t* f ) { return ( bli_func_get_dt( dt, f ) == NULL ); } bool bli_func_is_null( func_t* f ) { bool r_val = TRUE; num_t dt; // Iterate over all floating-point datatypes. If any is non-null, // return FALSE. Otherwise, if they are all null, return TRUE. for ( dt = BLIS_DT_LO; dt <= BLIS_DT_HI; ++dt ) { if ( bli_func_get_dt( dt, f ) != NULL ) { r_val = FALSE; break; } } return r_val; } blis-0.9.0/frame/base/bli_func.h000066400000000000000000000055421422157504600164230ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // ----------------------------------------------------------------------------- // func_t query BLIS_INLINE void_fp bli_func_get_dt ( num_t dt, func_t* func ) { return func->ptr[ dt ]; } // func_t modification BLIS_INLINE void bli_func_set_dt ( void_fp fp, num_t dt, func_t* func ) { func->ptr[ dt ] = fp; } BLIS_INLINE void bli_func_copy_dt ( num_t dt_src, func_t* func_src, num_t dt_dst, func_t* func_dst ) { void_fp fp = bli_func_get_dt( dt_src, func_src ); bli_func_set_dt( fp, dt_dst, func_dst ); } // ----------------------------------------------------------------------------- func_t* bli_func_create ( void_fp ptr_s, void_fp ptr_d, void_fp ptr_c, void_fp ptr_z ); void bli_func_init ( func_t* f, void_fp ptr_s, void_fp ptr_d, void_fp ptr_c, void_fp ptr_z ); void bli_func_init_null ( func_t* f ); void bli_func_free( func_t* f ); // ----------------------------------------------------------------------------- bool bli_func_is_null_dt( num_t dt, func_t* f ); bool bli_func_is_null( func_t* f ); blis-0.9.0/frame/base/bli_getopt.c000066400000000000000000000141141422157504600167600ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" static const char OPT_MARKER = '-'; void bli_getopt_init_state( int opterr, getopt_t* state ) { state->optarg = NULL; state->optind = 1; state->opterr = opterr; state->optopt = 0; } int bli_getopt( int argc, char** const argv, const char* optstring, getopt_t* state ) { static char* nextchar = NULL; char* elem_str; char* optstr_char; // If argv contains no more arguments to process, return. if ( state->optind == argc ) return -1; // Get a pointer to the current argv element string to process. If // nextchar is non-NULL, then it means the previous call processed // an element of argv with more than one option character, in which // case we need to pick up where we left off (which is the address // contained in nextchar). if ( nextchar == NULL ) { elem_str = argv[ state->optind ]; // elem_str[0] should be an OPT_MARKER if it is an option. In the // event that it is not an option, argv should be permuted so that // the non-option argument moves back toward the end of the list. // This functionality is not supported/implemented here. Therefore, // we require all of the program's option arguments to precede all of // its non-option arguments. if ( elem_str[0] != OPT_MARKER ) { state->optarg = NULL; //state->optind += 1; return -1; } // Skip over the OPT_MARKER. elem_str++; } else { // Note we don't need to skip the OPT_MARKER here since we are // continuing processing of a string with more than one option // character. // Use the nextchar pointer as our element string. elem_str = nextchar; // Reset nextchar to NULL. nextchar = NULL; } // Find the first occurrence of elem_str[0] in optstring. optstr_char = strchr( optstring, elem_str[0] ); // If the option character in elem_str[0] is absent from the option // string, store it and return '?'. if ( optstr_char == NULL ) { if ( state->opterr == 1 ) fprintf( stderr, "bli_getopt(): **error**: option character '%c' missing from option string \"%s\"\n", elem_str[0], optstring ); // We can't dereference optstr_char since it is NULL, so we use // elem_str[0] instead. state->optopt = elem_str[0]; state->optind += 1; return '?'; } // We can now safely assume that an option characer was found in the // option string. Now we need to check if the option takes an argument. if ( optstr_char[1] == ':' ) { // If the current element string ends after the option character, // then the companion argument must be stored in the next element // of argv. Otherwise, the argument begins immediately after the // option character. if ( elem_str[1] == '\0' ) { // If there are no more elements in argv, the argument was // omitted. Store the corresponding option character and // return '?'. if ( state->optind + 1 >= argc ) { if ( state->opterr == 1 ) fprintf( stderr, "bli_getopt(): **error**: option character '%c' is missing an argument (end of argv)\n", elem_str[0] ); state->optopt = *optstr_char; state->optind += 1; return '?'; } // If there are still more elements in argv yet to process AND // the next one is an option, then the argument was omitted. else if ( argv[ state->optind + 1 ][0] == OPT_MARKER ) { if ( state->opterr == 1 ) fprintf( stderr, "bli_getopt(): **error**: option character '%c' is missing an argument (next element of argv is option '%c')\n", elem_str[0], argv[ state->optind + 1 ][1] ); state->optopt = *optstr_char; state->optind += 1; return '?'; } // If no error was deteced above, we can safely assign optarg // to be the next element in argv and increment optind by two. state->optarg = argv[ state->optind + 1 ]; state->optind += 2; } else { // We don't need to check for missing arguments since we know // that because the char after the option character is not NULL, // the character(s) after it must constitute the argument. state->optarg = &elem_str[1]; state->optind += 1; } return *optstr_char; } // The current option character does NOT take an argument. However, we // still need to check if the next char is an option argument (such as // occurs when the user runs "program -rv" instead of "program -r -v"). if ( elem_str[1] != '\0' ) { if ( strchr( optstring, elem_str[1] ) != NULL ) { nextchar = &elem_str[1]; return *optstr_char; } } state->optarg = NULL; state->optind += 1; return *optstr_char; } blis-0.9.0/frame/base/bli_getopt.h000066400000000000000000000036421422157504600167710ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ typedef struct getopt_s { char* optarg; int optind; int opterr; int optopt; } getopt_t; BLIS_EXPORT_BLIS void bli_getopt_init_state( int opterr, getopt_t* state ); BLIS_EXPORT_BLIS int bli_getopt( int argc, char** const argv, const char* optstring, getopt_t* state ); blis-0.9.0/frame/base/bli_gks.c000066400000000000000000000673671422157504600162640ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018-2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // The array of cntx_t* pointers to cache modified contexts used by // induced methods. static cntx_t** gks[ BLIS_NUM_ARCHS ]; // The array of function pointers holding the registered context initialization // functions for induced methods. static void_fp cntx_ind_init[ BLIS_NUM_ARCHS ]; // The array of function pointers holding the registered context initialization // functions for reference kernels. static void_fp cntx_ref_init[ BLIS_NUM_ARCHS ]; // Define a function pointer type for context initialization functions. typedef void (*nat_cntx_init_ft)( cntx_t* cntx ); typedef void (*ref_cntx_init_ft)( cntx_t* cntx ); typedef void (*ind_cntx_init_ft)( ind_t method, cntx_t* cntx ); // ----------------------------------------------------------------------------- void bli_gks_init( void ) { { // Initialize the internal data structure we use to track registered // contexts. bli_gks_init_index(); // Register a context for each architecture that was #define'd in // bli_config.h. // Intel architectures #ifdef BLIS_CONFIG_SKX bli_gks_register_cntx( BLIS_ARCH_SKX, bli_cntx_init_skx, bli_cntx_init_skx_ref, bli_cntx_init_skx_ind ); #endif #ifdef BLIS_CONFIG_KNL bli_gks_register_cntx( BLIS_ARCH_KNL, bli_cntx_init_knl, bli_cntx_init_knl_ref, bli_cntx_init_knl_ind ); #endif #ifdef BLIS_CONFIG_KNC bli_gks_register_cntx( BLIS_ARCH_KNC, bli_cntx_init_knc, bli_cntx_init_knc_ref, bli_cntx_init_knc_ind ); #endif #ifdef BLIS_CONFIG_HASWELL bli_gks_register_cntx( BLIS_ARCH_HASWELL, bli_cntx_init_haswell, bli_cntx_init_haswell_ref, bli_cntx_init_haswell_ind ); #endif #ifdef BLIS_CONFIG_SANDYBRIDGE bli_gks_register_cntx( BLIS_ARCH_SANDYBRIDGE, bli_cntx_init_sandybridge, bli_cntx_init_sandybridge_ref, bli_cntx_init_sandybridge_ind ); #endif #ifdef BLIS_CONFIG_PENRYN bli_gks_register_cntx( BLIS_ARCH_PENRYN, bli_cntx_init_penryn, bli_cntx_init_penryn_ref, bli_cntx_init_penryn_ind ); #endif // AMD architectures #ifdef BLIS_CONFIG_ZEN3 bli_gks_register_cntx( BLIS_ARCH_ZEN3, bli_cntx_init_zen3, bli_cntx_init_zen3_ref, bli_cntx_init_zen3_ind ); #endif #ifdef BLIS_CONFIG_ZEN2 bli_gks_register_cntx( BLIS_ARCH_ZEN2, bli_cntx_init_zen2, bli_cntx_init_zen2_ref, bli_cntx_init_zen2_ind ); #endif #ifdef BLIS_CONFIG_ZEN bli_gks_register_cntx( BLIS_ARCH_ZEN, bli_cntx_init_zen, bli_cntx_init_zen_ref, bli_cntx_init_zen_ind ); #endif #ifdef BLIS_CONFIG_EXCAVATOR bli_gks_register_cntx( BLIS_ARCH_EXCAVATOR, bli_cntx_init_excavator, bli_cntx_init_excavator_ref, bli_cntx_init_excavator_ind ); #endif #ifdef BLIS_CONFIG_STEAMROLLER bli_gks_register_cntx( BLIS_ARCH_STEAMROLLER, bli_cntx_init_steamroller, bli_cntx_init_steamroller_ref, bli_cntx_init_steamroller_ind ); #endif #ifdef BLIS_CONFIG_PILEDRIVER bli_gks_register_cntx( BLIS_ARCH_PILEDRIVER, bli_cntx_init_piledriver, bli_cntx_init_piledriver_ref, bli_cntx_init_piledriver_ind ); #endif #ifdef BLIS_CONFIG_BULLDOZER bli_gks_register_cntx( BLIS_ARCH_BULLDOZER, bli_cntx_init_bulldozer, bli_cntx_init_bulldozer_ref, bli_cntx_init_bulldozer_ind ); #endif // ARM architectures #ifdef BLIS_CONFIG_A64FX bli_gks_register_cntx( BLIS_ARCH_A64FX, bli_cntx_init_a64fx, bli_cntx_init_a64fx_ref, bli_cntx_init_a64fx_ind ); #endif #ifdef BLIS_CONFIG_THUNDERX2 bli_gks_register_cntx( BLIS_ARCH_THUNDERX2, bli_cntx_init_thunderx2, bli_cntx_init_thunderx2_ref, bli_cntx_init_thunderx2_ind ); #endif #ifdef BLIS_CONFIG_CORTEXA57 bli_gks_register_cntx( BLIS_ARCH_CORTEXA57, bli_cntx_init_cortexa57, bli_cntx_init_cortexa57_ref, bli_cntx_init_cortexa57_ind ); #endif #ifdef BLIS_CONFIG_CORTEXA53 bli_gks_register_cntx( BLIS_ARCH_CORTEXA53, bli_cntx_init_cortexa53, bli_cntx_init_cortexa53_ref, bli_cntx_init_cortexa53_ind ); #endif #ifdef BLIS_CONFIG_ARMSVE bli_gks_register_cntx( BLIS_ARCH_ARMSVE, bli_cntx_init_armsve, bli_cntx_init_armsve_ref, bli_cntx_init_armsve_ind ); #endif #ifdef BLIS_CONFIG_A64FX bli_gks_register_cntx( BLIS_ARCH_A64FX, bli_cntx_init_a64fx, bli_cntx_init_a64fx_ref, bli_cntx_init_a64fx_ind ); #endif #ifdef BLIS_CONFIG_FIRESTORM bli_gks_register_cntx( BLIS_ARCH_FIRESTORM, bli_cntx_init_firestorm, bli_cntx_init_firestorm_ref, bli_cntx_init_firestorm_ind ); #endif #ifdef BLIS_CONFIG_CORTEXA15 bli_gks_register_cntx( BLIS_ARCH_CORTEXA15, bli_cntx_init_cortexa15, bli_cntx_init_cortexa15_ref, bli_cntx_init_cortexa15_ind ); #endif #ifdef BLIS_CONFIG_CORTEXA9 bli_gks_register_cntx( BLIS_ARCH_CORTEXA9, bli_cntx_init_cortexa9, bli_cntx_init_cortexa9_ref, bli_cntx_init_cortexa9_ind ); #endif // IBM architectures #ifdef BLIS_CONFIG_POWER10 bli_gks_register_cntx( BLIS_ARCH_POWER10, bli_cntx_init_power10, bli_cntx_init_power10_ref, bli_cntx_init_power10_ind ); #endif #ifdef BLIS_CONFIG_POWER9 bli_gks_register_cntx( BLIS_ARCH_POWER9, bli_cntx_init_power9, bli_cntx_init_power9_ref, bli_cntx_init_power9_ind ); #endif #ifdef BLIS_CONFIG_POWER7 bli_gks_register_cntx( BLIS_ARCH_POWER7, bli_cntx_init_power7, bli_cntx_init_power7_ref, bli_cntx_init_power7_ind ); #endif #ifdef BLIS_CONFIG_BGQ bli_gks_register_cntx( BLIS_ARCH_BGQ, bli_cntx_init_bgq, bli_cntx_init_bgq_ref, bli_cntx_init_bgq_ind ); #endif // Generic architectures #ifdef BLIS_CONFIG_GENERIC bli_gks_register_cntx( BLIS_ARCH_GENERIC, bli_cntx_init_generic, bli_cntx_init_generic_ref, bli_cntx_init_generic_ind ); #endif } } // ----------------------------------------------------------------------------- void bli_gks_finalize( void ) { arch_t id; ind_t ind; // BEGIN CRITICAL SECTION // NOTE: This critical section is implicit. We assume this function is only // called from within the critical section within bli_finalize(). { // Iterate over the architectures in the gks array. for ( id = 0; id < BLIS_NUM_ARCHS; ++id ) { cntx_t** restrict gks_id = gks[ id ]; // Only consider context arrays for architectures that were allocated // in the first place. if ( gks_id != NULL ) { // Iterate over the induced methods in the current sub-array // referenced by cntx_pp. for ( ind = 0; ind < BLIS_NUM_IND_METHODS; ++ind ) { cntx_t* restrict gks_id_ind = gks_id[ ind ]; // If the current context was allocated, free it. if ( gks_id_ind != NULL ) { #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_gks_finalize(): cntx for ind_t %d: ", ( int )ind ); #endif bli_free_intl( gks_id_ind ); } } #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_gks_finalize(): gks for arch_t %d: ", ( int )id ); #endif // Free the array of BLIS_NUM_IND_METHODS cntx* elements. bli_free_intl( gks_id ); } } } // END CRITICAL SECTION } // ----------------------------------------------------------------------------- void bli_gks_init_index( void ) { // This function is called by bli_gks_init(). It simply initializes all // architecture id elements of the internal arrays to NULL. const size_t gks_size = sizeof( cntx_t* ) * BLIS_NUM_ARCHS; const size_t fpa_size = sizeof( void_fp ) * BLIS_NUM_ARCHS; // Set every entry in gks and context init function pointer arrays to // zero/NULL. This is done so that later on we know which ones were // allocated. memset( gks, 0, gks_size ); memset( cntx_ref_init, 0, fpa_size ); memset( cntx_ind_init, 0, fpa_size ); } // ----------------------------------------------------------------------------- cntx_t* bli_gks_lookup_nat_cntx ( arch_t id ) { // Return the address of the (native) context for a given architecture id. // This function assumes the architecture has already been registered. return bli_gks_lookup_ind_cntx( id, BLIS_NAT ); } // ----------------------------------------------------------------------------- cntx_t* bli_gks_lookup_ind_cntx ( arch_t id, ind_t ind ) { // Return the address of the context for a given architecture id and // induced method. This function assumes the architecture has already // been registered. Note that this function returns NULL if the induced // method hasn't yet been called (and thus its context pointer is still // NULL). // Sanity check: verify that the arch_t id is valid. if ( bli_error_checking_is_enabled() ) { err_t e_val = bli_check_valid_arch_id( id ); bli_check_error_code( e_val ); } // Index into the array of context pointers for the given architecture id, // and then index into the subarray for the given induced method. cntx_t** restrict gks_id = gks[ id ]; cntx_t* restrict gks_id_ind = gks_id[ ind ]; // Return the context pointer at gks_id_ind. return gks_id_ind; } // ----------------------------------------------------------------------------- cntx_t** bli_gks_lookup_id ( arch_t id ) { // Return the address of the array of context pointers for a given // architecture id. This function is only used for sanity check purposes // to ensure that the underlying data structures for a particular id are // initialized. // Index into the array of context pointers for the given architecture id. cntx_t** restrict gks_id = gks[ id ]; // Return the context pointer at gks_id_ind. return gks_id; } // ----------------------------------------------------------------------------- void bli_gks_register_cntx ( arch_t id, void_fp nat_fp, void_fp ref_fp, void_fp ind_fp ) { err_t r_val; // This function is called by bli_gks_init() for each architecture that // will be supported by BLIS. It takes an architecture id and three // function pointers, one to a function that initializes a native context // (supplied by the kernel developer), one to a function that initializes // a reference context (with function pointers specific to the architecture // associated with id), and one to a function that initializes a // context for use with induced methods (again, with function pointers // to the architecture). The latter two functions are automatically // generated by the framework. Unlike with native contexts, we don't // actually store the induced contexts until that induced method is // called, and we don't ever store reference contexts. For this reason, we // can get away with only storing the pointers to the initialization // functions for those latter two types of contexts, which we can then // call at a later time when those contexts are needed. // Sanity check: verify that the arch_t id is valid. if ( bli_error_checking_is_enabled() ) { err_t e_val = bli_check_valid_arch_id( id ); bli_check_error_code( e_val ); } nat_cntx_init_ft f = nat_fp; // First, store the function pointers to the context initialization // functions for reference kernels and induced method execution. The // former will be used whenever we need to obtain reference kernels and // latter will be used later on if the user calls a level-3 function // with induced execution enabled. cntx_ref_init[ id ] = ref_fp; cntx_ind_init[ id ] = ind_fp; // If the the context array pointer isn't NULL, then it means the given // architecture id has already registered (and the underlying memory // allocations and context initializations have already been performed). // This is really just a safety feature to prevent memory leaks; this // early return should never occur, because the caller should never try // to register with an architecture id that has already been registered. if ( gks[ id ] != NULL ) return; #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_gks_register_cntx(): " ); #endif // At this point, we know the pointer to the array of cntx_t* is NULL and // needs to be allocated. Allocate the memory and initialize it to // zeros/NULL, storing the address of the alloacted memory at the element // for the current architecture id. gks[ id ] = bli_calloc_intl( sizeof( cntx_t* ) * BLIS_NUM_IND_METHODS, &r_val ); // Alias the allocated array for readability. cntx_t** restrict gks_id = gks[ id ]; #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_gks_register_cntx(): " ); #endif // Allocate memory for a single context and store the address at // the element in the gks[ id ] array that is reserved for native // execution. gks_id[ BLIS_NAT ] = bli_calloc_intl( sizeof( cntx_t ), &r_val ); // Alias the allocated context address for readability. cntx_t* restrict gks_id_nat = gks_id[ BLIS_NAT ]; // Call the context initialization function on the element of the newly // allocated array corresponding to native execution. f( gks_id_nat ); // Verify that cache blocksizes are whole multiples of register blocksizes. // Specifically, verify that: // - MC is a whole multiple of MR. // - NC is a whole multiple of NR. // - KC is a whole multiple of KR. // These constraints are enforced because it makes it easier to handle diagonals // in the macro-kernel implementations. Additionally, we optionally verify that: // - MC is a whole multiple of NR. // - NC is a whole multiple of MR. // These latter constraints, guarded by #ifndef BLIS_RELAX_MCNR_NCMR_CONSTRAINTS // below, are only enforced when we wish to be able to handle the trsm right- // side case handling that swaps A and B, so that B is the triangular matrix, // with NR blocking used to pack A and MR blocking used to pack B, with the // arguments to the gemmtrsm microkernel swapped at the last minute, as the // kernel is called. err_t e_val; blksz_t* restrict mc = bli_cntx_get_blksz( BLIS_MC, gks_id_nat ); blksz_t* restrict nc = bli_cntx_get_blksz( BLIS_NC, gks_id_nat ); blksz_t* restrict kc = bli_cntx_get_blksz( BLIS_KC, gks_id_nat ); blksz_t* restrict mr = bli_cntx_get_blksz( BLIS_MR, gks_id_nat ); blksz_t* restrict nr = bli_cntx_get_blksz( BLIS_NR, gks_id_nat ); blksz_t* restrict kr = bli_cntx_get_blksz( BLIS_KR, gks_id_nat ); e_val = bli_check_valid_mc_mod_mult( mc, mr ); bli_check_error_code( e_val ); e_val = bli_check_valid_nc_mod_mult( nc, nr ); bli_check_error_code( e_val ); e_val = bli_check_valid_kc_mod_mult( kc, kr ); bli_check_error_code( e_val ); #ifndef BLIS_RELAX_MCNR_NCMR_CONSTRAINTS e_val = bli_check_valid_mc_mod_mult( mc, nr ); bli_check_error_code( e_val ); e_val = bli_check_valid_nc_mod_mult( nc, mr ); bli_check_error_code( e_val ); #endif // Verify that the register blocksizes in the context are sufficiently large // relative to the maximum stack buffer size defined at configure-time. e_val = bli_check_sufficient_stack_buf_size( gks_id_nat ); bli_check_error_code( e_val ); } // ----------------------------------------------------------------------------- cntx_t* bli_gks_query_cntx( void ) { return bli_gks_query_nat_cntx(); } cntx_t* bli_gks_query_nat_cntx( void ) { bli_init_once(); // Return the address of the native context for the architecture id // corresponding to the current hardware, as determined by // bli_arch_query_id(). // Query the architecture id. arch_t id = bli_arch_query_id(); // Use the architecture id to look up a pointer to its context. cntx_t* cntx = bli_gks_lookup_nat_cntx( id ); return cntx; } // ----------------------------------------------------------------------------- cntx_t* bli_gks_query_cntx_noinit( void ) { // This function is identical to bli_gks_query_cntx(), except that it // does not call bli_init_once(). // Query the architecture id. arch_t id = bli_arch_query_id(); // Use the architecture id to look up a pointer to its context. cntx_t* cntx = bli_gks_lookup_nat_cntx( id ); return cntx; } // ----------------------------------------------------------------------------- // A mutex to allow synchronous access to the gks when it needs to be updated // with a new entry corresponding to a context for an ind_t value. static bli_pthread_mutex_t gks_mutex = BLIS_PTHREAD_MUTEX_INITIALIZER; cntx_t* bli_gks_query_ind_cntx ( ind_t ind, num_t dt ) { bli_init_once(); cntx_t* gks_id_ind; err_t r_val; // Return the address of a context that will be suited for executing a // level-3 operation via the requested induced method (and datatype) for // the architecture id corresponding to the current hardware, as // determined by bli_arch_query_id(). // This function is called when a level-3 operation via induced method is // called, e.g. bli_gemm1m(). If this is the first time that induced method // is being executed since bli_gks_init(), the necessary context structure // is allocated and initialized. If this is not the first time, then the // address of a previously-allocated and initialized (cached) context is // returned. Note that much of this must be done with mutual exclusion to // ensure thread safety and deterministic behavior. // Query the architecture id. arch_t id = bli_arch_query_id(); // Sanity check: verify that the arch_t id is valid. if ( bli_error_checking_is_enabled() ) { err_t e_val = bli_check_valid_arch_id( id ); bli_check_error_code( e_val ); } // NOTE: These initial statements can reside outside of the critical section // because gks[ id ] should have already been allocated, and the native // context in that array should have already been allocated/initialized. // Query the gks for the array of context pointers corresponding to the // given architecture id. cntx_t** restrict gks_id = gks[ id ]; cntx_t* restrict gks_id_nat = gks_id[ BLIS_NAT ]; // If for some reason the native context was requested, we can return // its address early. if ( ind == BLIS_NAT ) return gks_id_nat; // This function assumes that the architecture idenified by id has // already been registered with the gks (which guarantees that // gks[ id ] is non-NULL and gks[ id ][ BLIS_NAT ] is also non-NULL // and refers to a context initialized with valid data). // Acquire the mutex protecting the gks. bli_pthread_mutex_lock( &gks_mutex ); // BEGIN CRITICAL SECTION { // Alias for readability the element of gks_id associated with the // requested induced method. gks_id_ind = gks_id[ ind ]; // If the context pointer is NULL, then we know we must allocate and // then initialize the context before returning its address. if ( gks_id_ind == NULL ) { // If gks_id_ind is NULL, then we know we must allocate and then // initialize the context, storing its address back to // gks_id[ ind ]. gks_id_ind = bli_calloc_intl( sizeof( cntx_t ), &r_val ); gks_id[ ind ] = gks_id_ind; // Before we can call the induced method context initialization // function on the newly allocated structure, we must first copy // over the contents of the native context. *gks_id_ind = *gks_id_nat; // Use the architecture id to look up the function pointer to the // context initialization function for induced methods. ind_cntx_init_ft f = cntx_ind_init[ id ]; // Now we modify the context (so that it contains the proper values // for its induced method) by calling the context initialization // function for the current induced method. (That function assumes // that the context is pre- initialized with values for native // execution.) f( ind, gks_id_ind ); } } // END CRITICAL SECTION // Release the mutex protecting the gks. bli_pthread_mutex_unlock( &gks_mutex ); // Return the address of the newly-allocated/initialized context. return gks_id_ind; } // ----------------------------------------------------------------------------- void bli_gks_init_ref_cntx ( cntx_t* cntx ) { // Query the architecture id. arch_t id = bli_arch_query_id(); // Sanity check: verify that the arch_t id is valid. if ( bli_error_checking_is_enabled() ) { err_t e_val = bli_check_valid_arch_id( id ); bli_check_error_code( e_val ); } // Obtain the function pointer to the context initialization function for // reference kernels. ref_cntx_init_ft f = cntx_ref_init[ id ]; // Initialize the caller's context with reference kernels and related values. f( cntx ); } // ----------------------------------------------------------------------------- bool bli_gks_cntx_l3_nat_ukr_is_ref ( num_t dt, l3ukr_t ukr_id, cntx_t* cntx ) { cntx_t ref_cntx; // Initialize a context with reference kernels for the arch_t id queried // via bli_arch_query_id(). bli_gks_init_ref_cntx( &ref_cntx ); // Query each context for the micro-kernel function pointer for the // specified datatype. void_fp ref_fp = bli_cntx_get_l3_nat_ukr_dt( dt, ukr_id, &ref_cntx ); void_fp fp = bli_cntx_get_l3_nat_ukr_dt( dt, ukr_id, cntx ); // Return the result. return fp == ref_fp; } // // -- level-3 micro-kernel implementation strings ------------------------------ // static char* bli_gks_l3_ukr_impl_str[BLIS_NUM_UKR_IMPL_TYPES] = { "refrnce", "virtual", "optimzd", "notappl", }; // ----------------------------------------------------------------------------- char* bli_gks_l3_ukr_impl_string( l3ukr_t ukr, ind_t method, num_t dt ) { kimpl_t ki; // Query the context for the current induced method and datatype, and // then query the ukernel function pointer for the given datatype from // that context. cntx_t* cntx = bli_gks_query_ind_cntx( method, dt ); void_fp fp = bli_cntx_get_l3_vir_ukr_dt( dt, ukr, cntx ); // Check whether the ukernel function pointer is NULL for the given // datatype. If it is NULL, return the string for not applicable. // Otherwise, query the ukernel implementation type using the method // provided and return the associated string. if ( fp == NULL ) ki = BLIS_NOTAPPLIC_UKERNEL; else ki = bli_gks_l3_ukr_impl_type( ukr, method, dt ); return bli_gks_l3_ukr_impl_str[ ki ]; } #if 0 char* bli_gks_l3_ukr_avail_impl_string( l3ukr_t ukr, num_t dt ) { opid_t oper; ind_t method; kimpl_t ki; // We need to decide which operation we will use to query the // current available induced method. If the ukr type given is // BLIS_GEMM_UKR, we use gemm. Otherwise, we use trsm (since // the four other defined ukr types are trsm-related). if ( ukr == BLIS_GEMM_UKR ) oper = BLIS_GEMM; else oper = BLIS_TRSM; // Query the current available induced method using the // chosen operation id type. method = bli_l3_ind_oper_find_avail( oper, dt ); // Query the ukernel implementation type using the current // available method. ki = bli_gks_l3_ukr_impl_type( ukr, method, dt ); return bli_ukr_impl_str[ ki ]; } #endif kimpl_t bli_gks_l3_ukr_impl_type( l3ukr_t ukr, ind_t method, num_t dt ) { // If the current available induced method is not native, it // must be virtual. if ( method != BLIS_NAT ) return BLIS_VIRTUAL_UKERNEL; else { // If the current available induced method for the gemm // operation is native, then it might be reference or // optimized. To determine which, we compare the // datatype-specific function pointer within the ukrs // object corresponding to the current available induced // method to the typed function pointer within the known // reference ukrs object. cntx_t ref_cntx_l; // Query the architecture id. arch_t id = bli_arch_query_id(); // Sanity check: verify that the arch_t id is valid. if ( bli_error_checking_is_enabled() ) { err_t e_val = bli_check_valid_arch_id( id ); bli_check_error_code( e_val ); } // Obtain the function pointer to the context initialization function // for reference kernels. ref_cntx_init_ft f = cntx_ref_init[ id ]; // Initialize a local context with reference kernels and related values. f( &ref_cntx_l ); // Query the native context from the gks. cntx_t* nat_cntx = bli_gks_lookup_nat_cntx( id ); // Query the native ukernel func_t from both the native and reference // contexts. void_fp nat_fp = bli_cntx_get_l3_nat_ukr_dt( dt, ukr, nat_cntx ); void_fp ref_fp = bli_cntx_get_l3_nat_ukr_dt( dt, ukr, &ref_cntx_l ); if ( nat_fp == ref_fp ) return BLIS_REFERENCE_UKERNEL; else return BLIS_OPTIMIZED_UKERNEL; } } blis-0.9.0/frame/base/bli_gks.h000066400000000000000000000052011422157504600162440ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_GKS_H #define BLIS_GKS_H void bli_gks_init( void ); void bli_gks_finalize( void ); void bli_gks_init_index( void ); cntx_t* bli_gks_lookup_nat_cntx( arch_t id ); cntx_t* bli_gks_lookup_ind_cntx( arch_t id, ind_t ind ); cntx_t** bli_gks_lookup_id( arch_t id ); void bli_gks_register_cntx( arch_t id, void_fp nat_fp, void_fp ref_fp, void_fp ind_fp ); BLIS_EXPORT_BLIS cntx_t* bli_gks_query_cntx( void ); BLIS_EXPORT_BLIS cntx_t* bli_gks_query_nat_cntx( void ); cntx_t* bli_gks_query_cntx_noinit( void ); BLIS_EXPORT_BLIS cntx_t* bli_gks_query_ind_cntx( ind_t ind, num_t dt ); BLIS_EXPORT_BLIS void bli_gks_init_ref_cntx( cntx_t* cntx ); bool bli_gks_cntx_l3_nat_ukr_is_ref( num_t dt, l3ukr_t ukr_id, cntx_t* cntx ); BLIS_EXPORT_BLIS char* bli_gks_l3_ukr_impl_string( l3ukr_t ukr, ind_t method, num_t dt ); BLIS_EXPORT_BLIS kimpl_t bli_gks_l3_ukr_impl_type( l3ukr_t ukr, ind_t method, num_t dt ); //char* bli_gks_l3_ukr_avail_impl_string( l3ukr_t ukr, num_t dt ); #endif blis-0.9.0/frame/base/bli_ind.c000066400000000000000000000136541422157504600162400ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" static char* bli_ind_impl_str[BLIS_NUM_IND_METHODS] = { /* 1m */ "1m", /* nat */ "native", }; // ----------------------------------------------------------------------------- void bli_ind_init( void ) { // NOTE: Instead of calling bli_gks_query_cntx(), we call // bli_gks_query_cntx_noinit() to avoid the call to bli_init_once(). cntx_t* cntx = bli_gks_query_cntx_noinit(); // For each precision, enable the default induced method (1m) if both of // the following conditions are met: // - the complex domain kernel is the (unoptimized) reference kernel // - the real domain kernel is NOT the (unoptimized) reference kernel // The second condition means that BLIS will not bother to use an induced // method if both the real and complex domain kernels are reference. bool s_is_ref = bli_gks_cntx_l3_nat_ukr_is_ref( BLIS_FLOAT, BLIS_GEMM_UKR, cntx ); bool d_is_ref = bli_gks_cntx_l3_nat_ukr_is_ref( BLIS_DOUBLE, BLIS_GEMM_UKR, cntx ); bool c_is_ref = bli_gks_cntx_l3_nat_ukr_is_ref( BLIS_SCOMPLEX, BLIS_GEMM_UKR, cntx ); bool z_is_ref = bli_gks_cntx_l3_nat_ukr_is_ref( BLIS_DCOMPLEX, BLIS_GEMM_UKR, cntx ); if ( c_is_ref && !s_is_ref ) bli_ind_enable_dt( BLIS_1M, BLIS_SCOMPLEX ); if ( z_is_ref && !d_is_ref ) bli_ind_enable_dt( BLIS_1M, BLIS_DCOMPLEX ); } void bli_ind_finalize( void ) { } // ----------------------------------------------------------------------------- void bli_ind_enable( ind_t method ) { bli_ind_enable_dt( method, BLIS_SCOMPLEX ); bli_ind_enable_dt( method, BLIS_DCOMPLEX ); } void bli_ind_disable( ind_t method ) { bli_ind_disable_dt( method, BLIS_SCOMPLEX ); bli_ind_disable_dt( method, BLIS_DCOMPLEX ); } void bli_ind_disable_all( void ) { bli_ind_disable_all_dt( BLIS_SCOMPLEX ); bli_ind_disable_all_dt( BLIS_DCOMPLEX ); } // ----------------------------------------------------------------------------- void bli_ind_enable_dt( ind_t method, num_t dt ) { if ( !bli_is_complex( dt ) ) return; bli_l3_ind_set_enable_dt( method, dt, TRUE ); } void bli_ind_disable_dt( ind_t method, num_t dt ) { if ( !bli_is_complex( dt ) ) return; bli_l3_ind_set_enable_dt( method, dt, FALSE ); } void bli_ind_disable_all_dt( num_t dt ) { ind_t im; for ( im = 0; im < BLIS_NUM_IND_METHODS; ++im ) { // Never disable native execution. if ( im != BLIS_NAT ) bli_ind_disable_dt( im, dt ); } } // ----------------------------------------------------------------------------- void bli_ind_oper_enable_only( opid_t oper, ind_t method, num_t dt ) { if ( !bli_is_complex( dt ) ) return; if ( bli_opid_is_level3( oper ) ) { bli_l3_ind_oper_enable_only( oper, method, dt ); } else { // Other operations are not implemented, so requests to enable // them for any given induced method are currently no-ops. ; } } // ----------------------------------------------------------------------------- bool bli_ind_oper_is_impl( opid_t oper, ind_t method ) { bool is_impl = FALSE; if ( bli_opid_is_level3( oper ) ) { // Look up whether the operation is implemented for the given induced // method id. is_impl = bli_l3_ind_oper_is_impl( oper, method ); } else { // All other operations should be reported as not implemented, // unless the requested check was for BLIS_NAT, in which case // all operations are implemented. if ( method == BLIS_NAT ) is_impl = TRUE; else is_impl = FALSE; } return is_impl; } ind_t bli_ind_oper_find_avail( opid_t oper, num_t dt ) { ind_t method; if ( bli_opid_is_level3( oper ) ) { method = bli_l3_ind_oper_find_avail( oper, dt ); } else { // Currently, any operation that is not level-3 is guaranteed // to be native. method = BLIS_NAT; } return method; } char* bli_ind_oper_get_avail_impl_string( opid_t oper, num_t dt ) { ind_t method = bli_ind_oper_find_avail( oper, dt ); return bli_ind_get_impl_string( method ); } // ----------------------------------------------------------------------------- char* bli_ind_get_impl_string( ind_t method ) { return bli_ind_impl_str[ method ]; } num_t bli_ind_map_cdt_to_index( num_t dt ) { // A non-complex datatype should never be passed in. if ( !bli_is_complex( dt ) ) bli_abort(); // Map the complex datatype to a zero-based index. if ( bli_is_scomplex( dt ) ) return 0; else /* if ( bli_is_dcomplex( dt ) ) */ return 1; } blis-0.9.0/frame/base/bli_ind.h000066400000000000000000000051221422157504600162340ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_IND_H #define BLIS_IND_H // level-3 induced method management #include "bli_l3_ind.h" void bli_ind_init( void ); void bli_ind_finalize( void ); BLIS_EXPORT_BLIS void bli_ind_enable( ind_t method ); BLIS_EXPORT_BLIS void bli_ind_disable( ind_t method ); BLIS_EXPORT_BLIS void bli_ind_disable_all( void ); BLIS_EXPORT_BLIS void bli_ind_enable_dt( ind_t method, num_t dt ); BLIS_EXPORT_BLIS void bli_ind_disable_dt( ind_t method, num_t dt ); BLIS_EXPORT_BLIS void bli_ind_disable_all_dt( num_t dt ); BLIS_EXPORT_BLIS void bli_ind_oper_enable_only( opid_t oper, ind_t method, num_t dt ); BLIS_EXPORT_BLIS bool bli_ind_oper_is_impl( opid_t oper, ind_t method ); BLIS_EXPORT_BLIS ind_t bli_ind_oper_find_avail( opid_t oper, num_t dt ); BLIS_EXPORT_BLIS char* bli_ind_oper_get_avail_impl_string( opid_t oper, num_t dt ); char* bli_ind_get_impl_string( ind_t method ); num_t bli_ind_map_cdt_to_index( num_t dt ); #endif blis-0.9.0/frame/base/bli_info.c000066400000000000000000000170501422157504600164130ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // -- General library information ---------------------------------------------- // This string gets defined via -D on the command line when BLIS is compiled. // This string is (or rather, should be) only used here. static char* bli_version_str = BLIS_VERSION_STRING; static char* bli_int_type_size_str = STRINGIFY_INT( BLIS_INT_TYPE_SIZE ); char* bli_info_get_version_str( void ) { return bli_version_str; } char* bli_info_get_int_type_size_str( void ) { return bli_int_type_size_str; } // -- General configuration-related -------------------------------------------- gint_t bli_info_get_int_type_size( void ) { return BLIS_INT_TYPE_SIZE; } gint_t bli_info_get_num_fp_types( void ) { return BLIS_NUM_FP_TYPES; } gint_t bli_info_get_max_type_size( void ) { return BLIS_MAX_TYPE_SIZE; } gint_t bli_info_get_page_size( void ) { return BLIS_PAGE_SIZE; } gint_t bli_info_get_simd_num_registers( void ) { return BLIS_SIMD_MAX_NUM_REGISTERS; } gint_t bli_info_get_simd_size( void ) { return BLIS_SIMD_MAX_SIZE; } gint_t bli_info_get_simd_align_size( void ) { return BLIS_SIMD_ALIGN_SIZE; } gint_t bli_info_get_stack_buf_max_size( void ) { return BLIS_STACK_BUF_MAX_SIZE; } gint_t bli_info_get_stack_buf_align_size( void ) { return BLIS_STACK_BUF_ALIGN_SIZE; } gint_t bli_info_get_heap_addr_align_size( void ) { return BLIS_HEAP_ADDR_ALIGN_SIZE; } gint_t bli_info_get_heap_stride_align_size( void ) { return BLIS_HEAP_STRIDE_ALIGN_SIZE; } gint_t bli_info_get_pool_addr_align_size_a( void ) { return BLIS_POOL_ADDR_ALIGN_SIZE_A; } gint_t bli_info_get_pool_addr_align_size_b( void ) { return BLIS_POOL_ADDR_ALIGN_SIZE_B; } gint_t bli_info_get_pool_addr_align_size_c( void ) { return BLIS_POOL_ADDR_ALIGN_SIZE_C; } gint_t bli_info_get_pool_addr_align_size_gen( void ) { return BLIS_POOL_ADDR_ALIGN_SIZE_GEN; } gint_t bli_info_get_pool_addr_offset_size_a( void ) { return BLIS_POOL_ADDR_OFFSET_SIZE_A; } gint_t bli_info_get_pool_addr_offset_size_b( void ) { return BLIS_POOL_ADDR_OFFSET_SIZE_B; } gint_t bli_info_get_pool_addr_offset_size_c( void ) { return BLIS_POOL_ADDR_OFFSET_SIZE_C; } gint_t bli_info_get_pool_addr_offset_size_gen( void ) { return BLIS_POOL_ADDR_OFFSET_SIZE_GEN; } gint_t bli_info_get_enable_blas( void ) { #ifdef BLIS_ENABLE_BLAS return 1; #else return 0; #endif } gint_t bli_info_get_enable_cblas( void ) { #ifdef BLIS_ENABLE_CBLAS return 1; #else return 0; #endif } gint_t bli_info_get_blas_int_type_size( void ) { return BLIS_BLAS_INT_TYPE_SIZE; } gint_t bli_info_get_enable_pba_pools( void ) { #ifdef BLIS_ENABLE_PBA_POOLS return 1; #else return 0; #endif } gint_t bli_info_get_enable_sba_pools( void ) { #ifdef BLIS_ENABLE_SBA_POOLS return 1; #else return 0; #endif } gint_t bli_info_get_enable_threading( void ) { if ( bli_info_get_enable_openmp() || bli_info_get_enable_pthreads() ) return 1; else return 0; } gint_t bli_info_get_enable_openmp( void ) { #ifdef BLIS_ENABLE_OPENMP return 1; #else return 0; #endif } gint_t bli_info_get_enable_pthreads( void ) { #ifdef BLIS_ENABLE_PTHREADS return 1; #else return 0; #endif } gint_t bli_info_get_thread_part_jrir_slab( void ) { #ifdef BLIS_ENABLE_JRIR_SLAB return 1; #else return 0; #endif } gint_t bli_info_get_thread_part_jrir_rr( void ) { #ifdef BLIS_ENABLE_JRIR_RR return 1; #else return 0; #endif } gint_t bli_info_get_enable_memkind( void ) { #ifdef BLIS_ENABLE_MEMKIND return 1; #else return 0; #endif } gint_t bli_info_get_enable_sandbox( void ) { #ifdef BLIS_ENABLE_SANDBOX return 1; #else return 0; #endif } // -- Kernel implementation-related -------------------------------------------- // -- Level-3 kernel definitions -- char* bli_info_get_gemm_ukr_impl_string( ind_t method, num_t dt ) { bli_init_once(); return bli_gks_l3_ukr_impl_string( BLIS_GEMM_UKR, method, dt ); } char* bli_info_get_gemmtrsm_l_ukr_impl_string( ind_t method, num_t dt ) { bli_init_once(); return bli_gks_l3_ukr_impl_string( BLIS_GEMMTRSM_L_UKR, method, dt ); } char* bli_info_get_gemmtrsm_u_ukr_impl_string( ind_t method, num_t dt ) { bli_init_once(); return bli_gks_l3_ukr_impl_string( BLIS_GEMMTRSM_U_UKR, method, dt ); } char* bli_info_get_trsm_l_ukr_impl_string( ind_t method, num_t dt ) { bli_init_once(); return bli_gks_l3_ukr_impl_string( BLIS_TRSM_L_UKR, method, dt ); } char* bli_info_get_trsm_u_ukr_impl_string( ind_t method, num_t dt ) { bli_init_once(); return bli_gks_l3_ukr_impl_string( BLIS_TRSM_U_UKR, method, dt ); } // -- BLIS implementation query (level-3) -------------------------------------- char* bli_info_get_gemm_impl_string( num_t dt ) { return bli_ind_oper_get_avail_impl_string( BLIS_GEMM, dt ); } char* bli_info_get_gemmt_impl_string( num_t dt ) { return bli_ind_oper_get_avail_impl_string( BLIS_GEMMT, dt ); } char* bli_info_get_hemm_impl_string( num_t dt ) { return bli_ind_oper_get_avail_impl_string( BLIS_HEMM, dt ); } char* bli_info_get_herk_impl_string( num_t dt ) { return bli_ind_oper_get_avail_impl_string( BLIS_GEMMT, dt ); } char* bli_info_get_her2k_impl_string( num_t dt ) { return bli_ind_oper_get_avail_impl_string( BLIS_GEMMT, dt ); } char* bli_info_get_symm_impl_string( num_t dt ) { return bli_ind_oper_get_avail_impl_string( BLIS_SYMM, dt ); } char* bli_info_get_syrk_impl_string( num_t dt ) { return bli_ind_oper_get_avail_impl_string( BLIS_GEMMT, dt ); } char* bli_info_get_syr2k_impl_string( num_t dt ) { return bli_ind_oper_get_avail_impl_string( BLIS_GEMMT, dt ); } char* bli_info_get_trmm_impl_string( num_t dt ) { return bli_ind_oper_get_avail_impl_string( BLIS_TRMM, dt ); } char* bli_info_get_trmm3_impl_string( num_t dt ) { return bli_ind_oper_get_avail_impl_string( BLIS_TRMM3, dt ); } char* bli_info_get_trsm_impl_string( num_t dt ) { return bli_ind_oper_get_avail_impl_string( BLIS_TRSM, dt ); } blis-0.9.0/frame/base/bli_info.h000066400000000000000000000125171422157504600164230ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // -- General library information ---------------------------------------------- BLIS_EXPORT_BLIS char* bli_info_get_version_str( void ); BLIS_EXPORT_BLIS char* bli_info_get_int_type_size_str( void ); // -- General configuration-related -------------------------------------------- BLIS_EXPORT_BLIS gint_t bli_info_get_int_type_size( void ); BLIS_EXPORT_BLIS gint_t bli_info_get_num_fp_types( void ); BLIS_EXPORT_BLIS gint_t bli_info_get_max_type_size( void ); BLIS_EXPORT_BLIS gint_t bli_info_get_page_size( void ); BLIS_EXPORT_BLIS gint_t bli_info_get_simd_num_registers( void ); BLIS_EXPORT_BLIS gint_t bli_info_get_simd_size( void ); BLIS_EXPORT_BLIS gint_t bli_info_get_simd_align_size( void ); BLIS_EXPORT_BLIS gint_t bli_info_get_stack_buf_max_size( void ); BLIS_EXPORT_BLIS gint_t bli_info_get_stack_buf_align_size( void ); BLIS_EXPORT_BLIS gint_t bli_info_get_heap_addr_align_size( void ); BLIS_EXPORT_BLIS gint_t bli_info_get_heap_stride_align_size( void ); BLIS_EXPORT_BLIS gint_t bli_info_get_pool_addr_align_size_a( void ); BLIS_EXPORT_BLIS gint_t bli_info_get_pool_addr_align_size_b( void ); BLIS_EXPORT_BLIS gint_t bli_info_get_pool_addr_align_size_c( void ); BLIS_EXPORT_BLIS gint_t bli_info_get_pool_addr_align_size_gen( void ); BLIS_EXPORT_BLIS gint_t bli_info_get_pool_addr_offset_size_a( void ); BLIS_EXPORT_BLIS gint_t bli_info_get_pool_addr_offset_size_b( void ); BLIS_EXPORT_BLIS gint_t bli_info_get_pool_addr_offset_size_c( void ); BLIS_EXPORT_BLIS gint_t bli_info_get_pool_addr_offset_size_gen( void ); BLIS_EXPORT_BLIS gint_t bli_info_get_enable_stay_auto_init( void ); BLIS_EXPORT_BLIS gint_t bli_info_get_enable_blas( void ); BLIS_EXPORT_BLIS gint_t bli_info_get_enable_cblas( void ); BLIS_EXPORT_BLIS gint_t bli_info_get_blas_int_type_size( void ); BLIS_EXPORT_BLIS gint_t bli_info_get_enable_pba_pools( void ); BLIS_EXPORT_BLIS gint_t bli_info_get_enable_sba_pools( void ); BLIS_EXPORT_BLIS gint_t bli_info_get_enable_threading( void ); BLIS_EXPORT_BLIS gint_t bli_info_get_enable_openmp( void ); BLIS_EXPORT_BLIS gint_t bli_info_get_enable_pthreads( void ); BLIS_EXPORT_BLIS gint_t bli_info_get_thread_part_jrir_slab( void ); BLIS_EXPORT_BLIS gint_t bli_info_get_thread_part_jrir_rr( void ); BLIS_EXPORT_BLIS gint_t bli_info_get_enable_memkind( void ); BLIS_EXPORT_BLIS gint_t bli_info_get_enable_sandbox( void ); // -- Kernel implementation-related -------------------------------------------- // -- Level-3 kernel definitions -- BLIS_EXPORT_BLIS char* bli_info_get_gemm_ukr_impl_string( ind_t method, num_t dt ); BLIS_EXPORT_BLIS char* bli_info_get_gemmtrsm_l_ukr_impl_string( ind_t method, num_t dt ); BLIS_EXPORT_BLIS char* bli_info_get_gemmtrsm_u_ukr_impl_string( ind_t method, num_t dt ); BLIS_EXPORT_BLIS char* bli_info_get_trsm_l_ukr_impl_string( ind_t method, num_t dt ); BLIS_EXPORT_BLIS char* bli_info_get_trsm_u_ukr_impl_string( ind_t method, num_t dt ); // -- BLIS implementation query (level-3) -------------------------------------- BLIS_EXPORT_BLIS char* bli_info_get_gemm_impl_string( num_t dt ); BLIS_EXPORT_BLIS char* bli_info_get_gemmt_impl_string( num_t dt ); BLIS_EXPORT_BLIS char* bli_info_get_hemm_impl_string( num_t dt ); BLIS_EXPORT_BLIS char* bli_info_get_herk_impl_string( num_t dt ); BLIS_EXPORT_BLIS char* bli_info_get_her2k_impl_string( num_t dt ); BLIS_EXPORT_BLIS char* bli_info_get_symm_impl_string( num_t dt ); BLIS_EXPORT_BLIS char* bli_info_get_syrk_impl_string( num_t dt ); BLIS_EXPORT_BLIS char* bli_info_get_syr2k_impl_string( num_t dt ); BLIS_EXPORT_BLIS char* bli_info_get_trmm_impl_string( num_t dt ); BLIS_EXPORT_BLIS char* bli_info_get_trmm3_impl_string( num_t dt ); BLIS_EXPORT_BLIS char* bli_info_get_trsm_impl_string( num_t dt ); blis-0.9.0/frame/base/bli_init.c000066400000000000000000000105341422157504600164230ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // ----------------------------------------------------------------------------- void bli_init( void ) { bli_init_once(); } void bli_finalize( void ) { bli_finalize_once(); } // ----------------------------------------------------------------------------- void bli_init_auto( void ) { bli_init_once(); } void bli_finalize_auto( void ) { // The _auto() functions are used when initializing the BLAS compatibility // layer. It would not make much sense to automatically initialize and // finalize for every BLAS routine call; therefore, we remain initialized // unless and until the application explicitly calls bli_finalize(). } // ----------------------------------------------------------------------------- // A pthread_once_t variable is a pthread structure used in pthread_once(). // pthread_once() is guaranteed to execute exactly once among all threads that // pass in this control object (until/unless the variable is reset). static bli_pthread_once_t once_init = BLIS_PTHREAD_ONCE_INIT; static bli_pthread_once_t once_finalize = BLIS_PTHREAD_ONCE_INIT; void bli_init_once( void ) { bli_pthread_once( &once_init, bli_init_apis ); } void bli_finalize_once( void ) { bli_pthread_once( &once_finalize, bli_finalize_apis ); } // ----------------------------------------------------------------------------- void bli_init_apis( void ) { // Initialize various sub-APIs. bli_gks_init(); bli_ind_init(); bli_thread_init(); bli_pack_init(); bli_memsys_init(); // Reset the control variable that will allow finalization. // NOTE: We must initialize a fresh pthread_once_t object and THEN copy the // contents to the static control variable because some implementations of // pthreads define pthread_once_t as a struct and BLIS_PTHREAD_ONCE_INIT as // a struct initializer expression (i.e. { ... }), which cannot be used in // post-declaration struct assignment in strict C99. const bli_pthread_once_t once_new = BLIS_PTHREAD_ONCE_INIT; once_finalize = once_new; } void bli_finalize_apis( void ) { // Finalize various sub-APIs. bli_memsys_finalize(); bli_pack_finalize(); bli_thread_finalize(); bli_ind_finalize(); bli_gks_finalize(); // Reset the control variable that will allow (re-)initialization. // NOTE: We must initialize a fresh pthread_once_t object and THEN copy the // contents to the static control variable because some implementations of // pthreads define pthread_once_t as a struct and BLIS_PTHREAD_ONCE_INIT as // a struct initializer expression (i.e. { ... }), which cannot be used in // post-declaration struct assignment in strict C99. const bli_pthread_once_t once_new = BLIS_PTHREAD_ONCE_INIT; once_init = once_new; } blis-0.9.0/frame/base/bli_init.h000066400000000000000000000036251422157504600164330ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ BLIS_EXPORT_BLIS void bli_init( void ); BLIS_EXPORT_BLIS void bli_finalize( void ); void bli_init_auto( void ); void bli_finalize_auto( void ); void bli_init_apis( void ); void bli_finalize_apis( void ); void bli_init_once( void ); void bli_finalize_once( void ); blis-0.9.0/frame/base/bli_machval.c000066400000000000000000000067351422157504600171030ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define FUNCPTR_T machval_fp typedef void (*FUNCPTR_T)( machval_t mval, void* v ); static FUNCPTR_T GENARRAY(ftypes,machval); // // Define object-based interface. // void bli_machval( machval_t mval, obj_t* v ) { num_t dt_v = bli_obj_dt( v ); void* buf_v = bli_obj_buffer_at_off( v ); FUNCPTR_T f; // Index into the function pointer array. f = ftypes[dt_v]; // Invoke the function. f( mval, buf_v ); } // // Define BLAS-like interfaces. // #undef GENTFUNCR #define GENTFUNCR( ctype_v, ctype_vr, chv, chvr, opname, varname ) \ \ void PASTEMAC(chv,opname) \ ( \ machval_t mval, \ void* v \ ) \ { \ static ctype_vr pvals[ BLIS_NUM_MACH_PARAMS ]; \ \ static bool first_time = TRUE; \ \ dim_t val_i = mval - BLIS_MACH_PARAM_FIRST; \ ctype_v* v_cast = v; \ \ /* If this is the first time through, call the underlying code to discover each machine parameter. */ \ if ( first_time ) \ { \ char lapack_mval; \ dim_t m, i; \ \ for( i = 0, m = BLIS_MACH_PARAM_FIRST; \ i < BLIS_NUM_MACH_PARAMS - 1; \ ++i, ++m ) \ { \ bli_param_map_blis_to_netlib_machval( m, &lapack_mval ); \ \ /*printf( "bli_machval: querying %u %c\n", m, lapack_mval );*/ \ \ pvals[i] = PASTEMAC(chvr,varname)( &lapack_mval, 1 ); \ \ /*printf( "bli_machval: got back %34.29e\n", pvals[i] ); */ \ } \ \ /* Store epsilon^2 in the last element. */ \ pvals[i] = pvals[0] * pvals[0]; \ \ first_time = FALSE; \ } \ \ /* Copy the requested parameter value to the output buffer, which may involve a demotion from the complex to real domain. */ \ PASTEMAC2(chvr,chv,copys)( pvals[ val_i ], *v_cast ); \ } INSERT_GENTFUNCR_BASIC( machval, lamch ) blis-0.9.0/frame/base/bli_machval.h000066400000000000000000000041131422157504600170740ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "bli_lsame.h" #include "bli_slamch.h" #include "bli_dlamch.h" // // Prototype object-based interface. // BLIS_EXPORT_BLIS void bli_machval( machval_t mval, obj_t* v ); // // Prototype BLAS-like interfaces. // #undef GENTPROTR #define GENTPROTR( ctype_v, ctype_vr, chv, chvr, opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC(chv,opname) \ ( \ machval_t mval, \ void* v \ ); INSERT_GENTPROTR_BASIC0( machval ) blis-0.9.0/frame/base/bli_malloc.c000066400000000000000000000167611422157504600167370ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" //#define BLIS_ENABLE_MEM_TRACING // ----------------------------------------------------------------------------- // NOTE: These functions are no longer used. Instead, the relevant sections // of code call bli_fmalloc_align() and pass in the desired malloc()-like // function, such as BLIS_MALLOC_POOL. #if 0 void* bli_malloc_pool( size_t size ) { const malloc_ft malloc_fp = BLIS_MALLOC_POOL; const size_t align_size = BLIS_POOL_ADDR_ALIGN_SIZE; #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_malloc_pool(): size %ld, align size %ld\n", ( long )size, ( long )align_size ); fflush( stdout ); #endif return bli_fmalloc_align( malloc_fp, size, align_size ); } void bli_free_pool( void* p ) { #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_free_pool(): freeing block\n" ); fflush( stdout ); #endif bli_ffree_align( BLIS_FREE_POOL, p ); } #endif // ----------------------------------------------------------------------------- void* bli_malloc_user( size_t size, err_t* r_val ) { const malloc_ft malloc_fp = BLIS_MALLOC_USER; const size_t align_size = BLIS_HEAP_ADDR_ALIGN_SIZE; #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_malloc_user(): size %ld, align size %ld\n", ( long )size, ( long )align_size ); fflush( stdout ); #endif void* p = bli_fmalloc_align( malloc_fp, size, align_size, r_val ); return p; } void bli_free_user( void* p ) { #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_free_user(): freeing block\n" ); fflush( stdout ); #endif bli_ffree_align( BLIS_FREE_USER, p ); } // ----------------------------------------------------------------------------- void* bli_malloc_intl( size_t size, err_t* r_val ) { const malloc_ft malloc_fp = BLIS_MALLOC_INTL; #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_malloc_intl(): size %ld\n", ( long )size ); fflush( stdout ); #endif void* p = bli_fmalloc_noalign( malloc_fp, size, r_val ); return p; } void* bli_calloc_intl( size_t size, err_t* r_val ) { #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_calloc_intl(): " ); #endif void* p = bli_malloc_intl( size, r_val ); if ( bli_is_success( *r_val ) ) memset( p, 0, size ); return p; } void bli_free_intl( void* p ) { #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_free_intl(): freeing block\n" ); fflush( stdout ); #endif bli_ffree_noalign( BLIS_FREE_INTL, p ); } // ----------------------------------------------------------------------------- void* bli_fmalloc_align ( malloc_ft f, size_t size, size_t align_size, err_t* r_val ) { const size_t ptr_size = sizeof( void* ); size_t align_offset = 0; void* p_orig; int8_t* p_byte; void** p_addr; // Check parameters. if ( bli_error_checking_is_enabled() ) bli_fmalloc_align_check( f, size, align_size ); // Return early if zero bytes were requested. if ( size == 0 ) return NULL; // Add the alignment size and the size of a pointer to the number // of bytes to allocate. size += align_size + ptr_size; // Call the allocation function. p_orig = f( size ); // Check the pointer returned by malloc(). if ( bli_error_checking_is_enabled() ) bli_fmalloc_post_check( p_orig ); // The pseudo-return value isn't used yet. *r_val = BLIS_SUCCESS; // Advance the pointer by one pointer element. p_byte = p_orig; p_byte += ptr_size; // Compute the offset to the desired alignment. if ( bli_is_unaligned_to( ( siz_t )p_byte, ( siz_t )align_size ) ) { align_offset = align_size - bli_offset_past_alignment( ( siz_t )p_byte, ( siz_t )align_size ); } // Advance the pointer using the difference between the alignment // size and the alignment offset. p_byte += align_offset; // Compute the address of the pointer element just before the start // of the aligned address, and store the original address there. p_addr = ( void** )(p_byte - ptr_size); *p_addr = p_orig; // Return the aligned pointer. return p_byte; } void bli_ffree_align ( free_ft f, void* p ) { const size_t ptr_size = sizeof( void* ); void* p_orig; int8_t* p_byte; void** p_addr; // If the pointer to free is NULL, it was obviously not aligned and // does not need to be freed. if ( p == NULL ) return; // Since the bli_fmalloc_align() function returned the aligned pointer, // we have to first recover the original pointer before we can free the // memory. // Start by casting the pointer to a byte pointer. p_byte = p; // Compute the address of the pointer element just before the start // of the aligned address, and recover the original address. p_addr = ( void** )( p_byte - ptr_size ); p_orig = *p_addr; // Free the original pointer. f( p_orig ); } // ----------------------------------------------------------------------------- void* bli_fmalloc_noalign ( malloc_ft f, size_t size, err_t* r_val ) { void* p = f( size ); // Check the pointer returned by malloc(). if ( bli_error_checking_is_enabled() ) bli_fmalloc_post_check( p ); // The pseudo-return value isn't used yet. *r_val = BLIS_SUCCESS; return p; } void bli_ffree_noalign ( free_ft f, void* p ) { f( p ); } // ----------------------------------------------------------------------------- void bli_fmalloc_align_check ( malloc_ft f, size_t size, size_t align_size ) { err_t e_val; // Check for valid alignment. e_val = bli_check_alignment_is_power_of_two( align_size ); bli_check_error_code( e_val ); e_val = bli_check_alignment_is_mult_of_ptr_size( align_size ); bli_check_error_code( e_val ); } void bli_fmalloc_post_check ( void* p ) { err_t e_val; // Check for valid values from malloc(). e_val = bli_check_valid_malloc_buf( p ); bli_check_error_code( e_val ); } blis-0.9.0/frame/base/bli_malloc.h000066400000000000000000000053641422157504600167410ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // Typedef function pointer types for malloc() and free() substitutes. //typedef void* (*malloc_ft) ( size_t size ); //typedef void (*free_ft) ( void* p ); // ----------------------------------------------------------------------------- #if 0 BLIS_EXPORT_BLIS void* bli_malloc_pool( size_t size ); BLIS_EXPORT_BLIS void bli_free_pool( void* p ); #endif void* bli_malloc_intl( size_t size, err_t* r_val ); void* bli_calloc_intl( size_t size, err_t* r_val ); void bli_free_intl( void* p ); BLIS_EXPORT_BLIS void* bli_malloc_user( size_t size, err_t* r_val ); BLIS_EXPORT_BLIS void bli_free_user( void* p ); // ----------------------------------------------------------------------------- void* bli_fmalloc_align( malloc_ft f, size_t size, size_t align_size, err_t* r_val ); void bli_ffree_align( free_ft f, void* p ); void* bli_fmalloc_noalign( malloc_ft f, size_t size, err_t* r_val ); void bli_ffree_noalign( free_ft f, void* p ); void bli_fmalloc_align_check( malloc_ft f, size_t size, size_t align_size ); void bli_fmalloc_post_check( void* p ); blis-0.9.0/frame/base/bli_mbool.c000066400000000000000000000044531422157504600165730ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" mbool_t* bli_mbool_create ( bool b_s, bool b_d, bool b_c, bool b_z ) { mbool_t* b; err_t r_val; b = ( mbool_t* ) bli_malloc_intl( sizeof( mbool_t ), &r_val ); bli_mbool_init ( b, b_s, b_d, b_c, b_z ); return b; } void bli_mbool_init ( mbool_t* b, bool b_s, bool b_d, bool b_c, bool b_z ) { bli_mbool_set_dt( b_s, BLIS_FLOAT, b ); bli_mbool_set_dt( b_d, BLIS_DOUBLE, b ); bli_mbool_set_dt( b_c, BLIS_SCOMPLEX, b ); bli_mbool_set_dt( b_z, BLIS_DCOMPLEX, b ); } void bli_mbool_free( mbool_t* b ) { bli_free_intl( b ); } blis-0.9.0/frame/base/bli_mbool.h000066400000000000000000000044621422157504600166000ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // ----------------------------------------------------------------------------- // mbool_t query BLIS_INLINE bool bli_mbool_get_dt( num_t dt, mbool_t* mb ) { return ( bool )( mb->v[ dt ] ); } // mbool_t modification BLIS_INLINE void bli_mbool_set_dt( bool val, num_t dt, mbool_t* mb ) { mb->v[ dt ] = val; } // ----------------------------------------------------------------------------- mbool_t* bli_mbool_create ( bool b_s, bool b_d, bool b_c, bool b_z ); void bli_mbool_init ( mbool_t* b, bool b_s, bool b_d, bool b_c, bool b_z ); void bli_mbool_free( mbool_t* b ); blis-0.9.0/frame/base/bli_mem.h000066400000000000000000000102521422157504600162400ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2016, Hewlett Packard Enterprise Development LP Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_MEM_H #define BLIS_MEM_H // mem_t object type (defined in bli_type_defs.h) /* typedef struct mem_s { pblk_t pblk; packbuf_t buf_type; pool_t* pool; siz_t size; } mem_t; typedef struct { void* buf; siz_t block_size; } pblk_t; */ // // -- mem_t query -------------------------------------------------------------- // BLIS_INLINE pblk_t* bli_mem_pblk( mem_t* mem ) { return &(mem->pblk); } BLIS_INLINE void* bli_mem_buffer( mem_t* mem ) { return bli_pblk_buf( bli_mem_pblk( mem ) ); } BLIS_INLINE packbuf_t bli_mem_buf_type( mem_t* mem ) { return mem->buf_type; } BLIS_INLINE pool_t* bli_mem_pool( mem_t* mem ) { return mem->pool; } BLIS_INLINE siz_t bli_mem_size( mem_t* mem ) { return mem->size; } BLIS_INLINE bool bli_mem_is_alloc( mem_t* mem ) { return ( bool ) ( bli_mem_buffer( mem ) != NULL ); } BLIS_INLINE bool bli_mem_is_unalloc( mem_t* mem ) { return ( bool ) ( bli_mem_buffer( mem ) == NULL ); } // // -- mem_t modification ------------------------------------------------------- // BLIS_INLINE void bli_mem_set_pblk( pblk_t* pblk, mem_t* mem ) { mem->pblk = *pblk; } BLIS_INLINE void bli_mem_set_buffer( void* buf, mem_t* mem ) { bli_pblk_set_buf( buf, &(mem->pblk) ); } BLIS_INLINE void bli_mem_set_buf_type( packbuf_t buf_type, mem_t* mem ) { mem->buf_type = buf_type; } BLIS_INLINE void bli_mem_set_pool( pool_t* pool, mem_t* mem ) { mem->pool = pool; } BLIS_INLINE void bli_mem_set_size( siz_t size, mem_t* mem ) { mem->size = size; } // // -- mem_t initialization ----------------------------------------------------- // // NOTE: This initializer macro must be updated whenever fields are added or // removed from the mem_t type definition. An alternative to the initializer is // calling bli_mem_clear() at runtime. #define BLIS_MEM_INITIALIZER \ { \ .pblk = BLIS_PBLK_INITIALIZER, \ .buf_type = -1, \ .pool = NULL, \ .size = 0, \ } \ BLIS_INLINE void bli_mem_clear( mem_t* mem ) { bli_mem_set_buffer( NULL, mem ); #ifdef __cplusplus const packbuf_t pb = BLIS_BUFFER_FOR_GEN_USE; // When using C++, which is strongly typed, we avoid use of -1 as a // packbuf_t value since it will result in a compile-time error. bli_mem_set_buf_type( pb, mem ); #else bli_mem_set_buf_type( ( packbuf_t )-1, mem ); #endif bli_mem_set_pool( NULL, mem ); bli_mem_set_size( 0, mem ); } #endif blis-0.9.0/frame/base/bli_memsys.c000066400000000000000000000051151422157504600167740ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2016, Hewlett Packard Enterprise Development LP Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_memsys_init( void ) { // Query a native context so we have something to pass into // bli_pba_init_pools(). We use BLIS_DOUBLE for the datatype, // but the dt argument is actually only used when initializing // contexts for induced methods. // NOTE: Instead of calling bli_gks_query_cntx(), we call // bli_gks_query_cntx_noinit() to avoid the call to bli_init_once(). cntx_t* cntx_p = bli_gks_query_cntx_noinit(); // Initialize the packing block allocator and its data structures. bli_pba_init( cntx_p ); // Initialize the small block allocator and its data structures. bli_sba_init(); } void bli_memsys_finalize( void ) { // Finalize the small block allocator and its data structures. bli_sba_finalize(); // Finalize the packing block allocator and its data structures. bli_pba_finalize(); } blis-0.9.0/frame/base/bli_memsys.h000066400000000000000000000037161422157504600170060ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2016, Hewlett Packard Enterprise Development LP Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_MEMSYS_H #define BLIS_MEMSYS_H // ----------------------------------------------------------------------------- void bli_memsys_init( void ); void bli_memsys_finalize( void ); #endif blis-0.9.0/frame/base/bli_obj.c000066400000000000000000000470621422157504600162400ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_obj_create ( num_t dt, dim_t m, dim_t n, inc_t rs, inc_t cs, obj_t* obj ) { bli_init_once(); bli_obj_create_without_buffer( dt, m, n, obj ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_obj_create(): " ); #endif bli_obj_alloc_buffer( rs, cs, 1, obj ); } void bli_obj_create_with_attached_buffer ( num_t dt, dim_t m, dim_t n, void* p, inc_t rs, inc_t cs, obj_t* obj ) { bli_init_once(); bli_obj_create_without_buffer( dt, m, n, obj ); bli_obj_attach_buffer( p, rs, cs, 1, obj ); } void bli_obj_create_without_buffer ( num_t dt, dim_t m, dim_t n, obj_t* obj ) { siz_t elem_size; void* s; bli_init_once(); if ( bli_error_checking_is_enabled() ) bli_obj_create_without_buffer_check( dt, m, n, obj ); // Query the size of one element of the object's pre-set datatype. elem_size = bli_dt_size( dt ); // Set any default properties that are appropriate. bli_obj_set_defaults( obj ); // Set the object root to itself, since obj is not presumed to be a view // into a larger matrix. This is typically the only time this field is // ever set; henceforth, subpartitions and aliases to this object will // get copies of this field, and thus always have access to its // "greatest-grand" parent (ie: the original parent, or "root", object). // However, there ARE a few places where it is convenient to reset the // root field explicitly via bli_obj_set_as_root(). (We do not list // those places here. Just grep for bli_obj_set_as_root within the // top-level 'frame' directory to see them. bli_obj_set_as_root( obj ); // Set individual fields. bli_obj_set_buffer( NULL, obj ); bli_obj_set_dt( dt, obj ); bli_obj_set_elem_size( elem_size, obj ); bli_obj_set_target_dt( dt, obj ); bli_obj_set_exec_dt( dt, obj ); bli_obj_set_comp_dt( dt, obj ); bli_obj_set_dims( m, n, obj ); bli_obj_set_offs( 0, 0, obj ); bli_obj_set_diag_offset( 0, obj ); bli_obj_set_pack_fn( NULL, obj ); bli_obj_set_pack_params( NULL, obj ); bli_obj_set_ker_fn( NULL, obj ); bli_obj_set_ker_params( NULL, obj ); // Set the internal scalar to 1.0. bli_obj_set_scalar_dt( dt, obj ); s = bli_obj_internal_scalar_buffer( obj ); // Always writing the imaginary component is needed in mixed-domain // scenarios. Failing to do this can lead to reading uninitialized // memory just before calling the macrokernel (as the internal scalars // for A and B are merged). //if ( bli_is_float( dt ) ) { bli_sset1s( *(( float* )s) ); } //else if ( bli_is_double( dt ) ) { bli_dset1s( *(( double* )s) ); } if ( bli_is_float( dt ) ) { bli_cset1s( *(( scomplex* )s) ); } else if ( bli_is_double( dt ) ) { bli_zset1s( *(( dcomplex* )s) ); } else if ( bli_is_scomplex( dt ) ) { bli_cset1s( *(( scomplex* )s) ); } else if ( bli_is_dcomplex( dt ) ) { bli_zset1s( *(( dcomplex* )s) ); } } void bli_obj_alloc_buffer ( inc_t rs, inc_t cs, inc_t is, obj_t* obj ) { dim_t n_elem = 0; dim_t m, n; siz_t elem_size; siz_t buffer_size; void* p; err_t r_val; bli_init_once(); // Query the dimensions of the object we are allocating. m = bli_obj_length( obj ); n = bli_obj_width( obj ); // Query the size of one element. elem_size = bli_obj_elem_size( obj ); // Adjust the strides, if needed, before doing anything else // (particularly, before doing any error checking). bli_adjust_strides( m, n, elem_size, &rs, &cs, &is ); if ( bli_error_checking_is_enabled() ) bli_obj_alloc_buffer_check( rs, cs, is, obj ); // Determine how much object to allocate. if ( m == 0 || n == 0 ) { // For empty objects, set n_elem to zero. Row and column strides // should remain unchanged (because alignment is not needed). n_elem = 0; } else { // The number of elements to allocate is given by the distance from // the element with the lowest address (usually {0, 0}) to the element // with the highest address (usually {m-1, n-1}), plus one for the // highest element itself. n_elem = (m-1) * bli_abs( rs ) + (n-1) * bli_abs( cs ) + 1; } // Handle the special case where imaginary stride is larger than // normal. if ( bli_obj_is_complex( obj ) ) { // Notice that adding is/2 works regardless of whether the // imaginary stride is unit, something between unit and // 2*n_elem, or something bigger than 2*n_elem. n_elem = bli_abs( is ) / 2 + n_elem; } // Compute the size of the total buffer to be allocated, which includes // padding if the leading dimension was increased for alignment purposes. buffer_size = ( siz_t )n_elem * elem_size; // Allocate the buffer. p = bli_malloc_user( buffer_size, &r_val ); // Set individual fields. bli_obj_set_buffer( p, obj ); bli_obj_set_strides( rs, cs, obj ); bli_obj_set_imag_stride( is, obj ); } void bli_obj_attach_buffer ( void* p, inc_t rs, inc_t cs, inc_t is, obj_t* obj ) { bli_init_once(); // Interpret is = 0 as a request for the default, which is is = 1; if ( is == 0 ) is = 1; // Check that the strides and lengths are compatible. Note that the // user *must* specify valid row and column strides when attaching an // external buffer. if ( bli_error_checking_is_enabled() ) bli_obj_attach_buffer_check( p, rs, cs, is, obj ); // Update the object. bli_obj_set_buffer( p, obj ); bli_obj_set_strides( rs, cs, obj ); bli_obj_set_imag_stride( is, obj ); } void bli_obj_create_1x1 ( num_t dt, obj_t* obj ) { bli_obj_create_without_buffer( dt, 1, 1, obj ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_obj_create_1x1(): " ); #endif bli_obj_alloc_buffer( 1, 1, 1, obj ); } void bli_obj_create_1x1_with_attached_buffer ( num_t dt, void* p, obj_t* obj ) { bli_obj_create_without_buffer( dt, 1, 1, obj ); bli_obj_attach_buffer( p, 1, 1, 1, obj ); } void bli_obj_create_conf_to ( obj_t* s, obj_t* d ) { const num_t dt = bli_obj_dt( s ); const dim_t m = bli_obj_length( s ); const dim_t n = bli_obj_width( s ); const inc_t rs = bli_obj_row_stride( s ); const inc_t cs = bli_obj_col_stride( s ); bli_obj_create( dt, m, n, rs, cs, d ); } void bli_obj_free ( obj_t* obj ) { if ( bli_error_checking_is_enabled() ) bli_obj_free_check( obj ); // Don't dereference obj if it is NULL. if ( obj != NULL ) { // Idiot safety: Don't try to free the buffer field if the object // is a detached scalar (ie: if the buffer pointer refers to the // address of the internal scalar buffer). if ( bli_obj_buffer( obj ) != bli_obj_internal_scalar_buffer( obj ) ) { #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_obj_free(): " ); #endif bli_free_user( bli_obj_buffer( obj ) ); } } } #if 0 //void bli_obj_create_const ( double value, obj_t* obj ) { gint_t* temp_i; float* temp_s; double* temp_d; scomplex* temp_c; dcomplex* temp_z; if ( bli_error_checking_is_enabled() ) bli_obj_create_const_check( value, obj ); bli_obj_create( BLIS_CONSTANT, 1, 1, 1, 1, obj ); //temp_s = bli_obj_buffer_for_const( BLIS_FLOAT, obj ); //temp_d = bli_obj_buffer_for_const( BLIS_DOUBLE, obj ); //temp_c = bli_obj_buffer_for_const( BLIS_SCOMPLEX, obj ); //temp_z = bli_obj_buffer_for_const( BLIS_DCOMPLEX, obj ); //temp_i = bli_obj_buffer_for_const( BLIS_INT, obj ); bli_dssets( value, 0.0, *temp_s ); bli_ddsets( value, 0.0, *temp_d ); bli_dcsets( value, 0.0, *temp_c ); bli_dzsets( value, 0.0, *temp_z ); *temp_i = ( gint_t ) value; } //void bli_obj_create_const_copy_of ( obj_t* a, obj_t* b ) { gint_t* temp_i; float* temp_s; double* temp_d; scomplex* temp_c; dcomplex* temp_z; void* buf_a; dcomplex value; if ( bli_error_checking_is_enabled() ) bli_obj_create_const_copy_of_check( a, b ); bli_obj_create( BLIS_CONSTANT, 1, 1, 1, 1, b ); //temp_s = bli_obj_buffer_for_const( BLIS_FLOAT, b ); //temp_d = bli_obj_buffer_for_const( BLIS_DOUBLE, b ); //temp_c = bli_obj_buffer_for_const( BLIS_SCOMPLEX, b ); //temp_z = bli_obj_buffer_for_const( BLIS_DCOMPLEX, b ); //temp_i = bli_obj_buffer_for_const( BLIS_INT, b ); buf_a = bli_obj_buffer_at_off( a ); bli_zzsets( 0.0, 0.0, value ); if ( bli_obj_is_float( a ) ) { bli_szcopys( *(( float* )buf_a), value ); } else if ( bli_obj_is_double( a ) ) { bli_dzcopys( *(( double* )buf_a), value ); } else if ( bli_obj_is_scomplex( a ) ) { bli_czcopys( *(( scomplex* )buf_a), value ); } else if ( bli_obj_is_dcomplex( a ) ) { bli_zzcopys( *(( dcomplex* )buf_a), value ); } else { bli_check_error_code( BLIS_NOT_YET_IMPLEMENTED ); } bli_zscopys( value, *temp_s ); bli_zdcopys( value, *temp_d ); bli_zccopys( value, *temp_c ); bli_zzcopys( value, *temp_z ); *temp_i = ( gint_t ) bli_zreal( value ); } #endif void bli_adjust_strides ( dim_t m, dim_t n, siz_t elem_size, inc_t* rs, inc_t* cs, inc_t* is ) { // Here, we check the strides that were input from the user and modify // them if needed. // Handle the special "empty" case first. If either dimension is zero, // do nothing (this could represent a zero-length "slice" of another // matrix). if ( m == 0 || n == 0 ) return; // Interpret rs = cs = 0 as request for column storage and -1 as a request // for row storage. if ( *rs == 0 && *cs == 0 && ( *is == 0 || *is == 1 ) ) { // First we handle the 1x1 scalar case explicitly. if ( m == 1 && n == 1 ) { *rs = 1; *cs = 1; } // We use column-major storage, except when m == 1, in which case we // use what amounts to row-major storage because we don't want both // strides to be unit. else if ( m == 1 && n > 1 ) { *rs = n; *cs = 1; } else { *rs = 1; *cs = m; } // Use default complex storage. *is = 1; // Align the strides depending on the tilt of the matrix. Note that // scalars are neither row nor column tilted. Also note that alignment // is only done for rs = cs = 0, and any user-supplied row and column // strides are preserved. if ( bli_is_col_tilted( m, n, *rs, *cs ) ) { *cs = bli_align_dim_to_size( *cs, elem_size, BLIS_HEAP_STRIDE_ALIGN_SIZE ); } else if ( bli_is_row_tilted( m, n, *rs, *cs ) ) { *rs = bli_align_dim_to_size( *rs, elem_size, BLIS_HEAP_STRIDE_ALIGN_SIZE ); } } else if ( *rs == -1 && *cs == -1 && ( *is == 0 || *is == 1 ) ) { // First we handle the 1x1 scalar case explicitly. if ( m == 1 && n == 1 ) { *rs = 1; *cs = 1; } // We use row-major storage, except when n == 1, in which case we // use what amounts to column-major storage because we don't want both // strides to be unit. else if ( n == 1 && m > 1 ) { *rs = 1; *cs = m; } else { *rs = n; *cs = 1; } // Use default complex storage. *is = 1; // Align the strides depending on the tilt of the matrix. Note that // scalars are neither row nor column tilted. Also note that alignment // is only done for rs = cs = -1, and any user-supplied row and column // strides are preserved. if ( bli_is_col_tilted( m, n, *rs, *cs ) ) { *cs = bli_align_dim_to_size( *cs, elem_size, BLIS_HEAP_STRIDE_ALIGN_SIZE ); } else if ( bli_is_row_tilted( m, n, *rs, *cs ) ) { *rs = bli_align_dim_to_size( *rs, elem_size, BLIS_HEAP_STRIDE_ALIGN_SIZE ); } } else if ( *rs == 1 && *cs == 1 ) { // If both strides are unit, this is probably a "lazy" request for a // single vector (but could also be a request for a 1xn matrix in // column-major order or an mx1 matrix in row-major order). In BLIS, // we have decided to "reserve" the case where rs = cs = 1 for // 1x1 scalars only. if ( m > 1 && n == 1 ) { // Set the column stride to indicate that this is a column vector // stored in column-major order. This is done for legacy reasons, // because we at one time we had to satisify the error checking // in the underlying BLAS library, which expects the leading // dimension to be set to at least m, even if it will never be // used for indexing since it is a vector and thus only has one // column of data. *cs = m; } else if ( m == 1 && n > 1 ) { // Set the row stride to indicate that this is a row vector stored // in row-major order. *rs = n; } // Nothing needs to be done for the 1x1 scalar case where m == n == 1. } } static siz_t dt_sizes[6] = { sizeof( float ), sizeof( scomplex ), sizeof( double ), sizeof( dcomplex ), sizeof( gint_t ), sizeof( constdata_t ) }; siz_t bli_dt_size ( num_t dt ) { if ( bli_error_checking_is_enabled() ) bli_dt_size_check( dt ); return dt_sizes[dt]; } static char* dt_names[ BLIS_NUM_FP_TYPES+1 ] = { "float", "scomplex", "double", "dcomplex", "int" }; char* bli_dt_string ( num_t dt ) { if ( bli_error_checking_is_enabled() ) bli_dt_string_check( dt ); return dt_names[dt]; } dim_t bli_align_dim_to_mult ( dim_t dim, dim_t dim_mult ) { // We return the dimension unmodified if the multiple is zero // (to avoid division by zero). if ( dim_mult == 0 ) return dim; dim = ( ( dim + dim_mult - 1 ) / dim_mult ) * dim_mult; return dim; } dim_t bli_align_dim_to_size ( dim_t dim, siz_t elem_size, siz_t align_size ) { dim = ( ( dim * ( dim_t )elem_size + ( dim_t )align_size - 1 ) / ( dim_t )align_size ) * ( dim_t )align_size / ( dim_t )elem_size; return dim; } dim_t bli_align_ptr_to_size ( void* p, size_t align_size ) { dim_t dim; dim = ( ( ( uintptr_t )p + align_size - 1 ) / align_size ) * align_size; return dim; } #if 0 static num_t type_union[BLIS_NUM_FP_TYPES][BLIS_NUM_FP_TYPES] = { // s c d z /* s */ { BLIS_FLOAT, BLIS_SCOMPLEX, BLIS_DOUBLE, BLIS_DCOMPLEX }, /* c */ { BLIS_SCOMPLEX, BLIS_SCOMPLEX, BLIS_DCOMPLEX, BLIS_DCOMPLEX }, /* d */ { BLIS_DOUBLE, BLIS_DCOMPLEX, BLIS_DOUBLE, BLIS_DCOMPLEX }, /* z */ { BLIS_DCOMPLEX, BLIS_DCOMPLEX, BLIS_DCOMPLEX, BLIS_DCOMPLEX } }; num_t bli_dt_union( num_t dt1, num_t dt2 ) { if ( bli_error_checking_is_enabled() ) bli_dt_union_check( dt1, dt2 ); return type_union[dt1][dt2]; } #endif void bli_obj_print ( char* label, obj_t* obj ) { bli_init_once(); FILE* file = stdout; if ( bli_error_checking_is_enabled() ) bli_obj_print_check( label, obj ); fprintf( file, "\n" ); fprintf( file, "%s\n", label ); fprintf( file, "\n" ); fprintf( file, " m x n %lu x %lu\n", ( unsigned long )bli_obj_length( obj ), ( unsigned long )bli_obj_width( obj ) ); fprintf( file, "\n" ); fprintf( file, " offm, offn %lu, %lu\n", ( unsigned long )bli_obj_row_off( obj ), ( unsigned long )bli_obj_col_off( obj ) ); fprintf( file, " diagoff %ld\n", ( signed long int )bli_obj_diag_offset( obj ) ); fprintf( file, "\n" ); fprintf( file, " buf %p\n", ( void* )bli_obj_buffer( obj ) ); fprintf( file, " elem size %lu\n", ( unsigned long )bli_obj_elem_size( obj ) ); fprintf( file, " rs, cs %ld, %ld\n", ( signed long int )bli_obj_row_stride( obj ), ( signed long int )bli_obj_col_stride( obj ) ); fprintf( file, " is %ld\n", ( signed long int )bli_obj_imag_stride( obj ) ); fprintf( file, " m_padded %lu\n", ( unsigned long )bli_obj_padded_length( obj ) ); fprintf( file, " n_padded %lu\n", ( unsigned long )bli_obj_padded_width( obj ) ); fprintf( file, " pd %lu\n", ( unsigned long )bli_obj_panel_dim( obj ) ); fprintf( file, " ps %lu\n", ( unsigned long )bli_obj_panel_stride( obj ) ); fprintf( file, "\n" ); fprintf( file, " info %lX\n", ( unsigned long )(*obj).info ); fprintf( file, " - is complex %lu\n", ( unsigned long )bli_obj_is_complex( obj ) ); fprintf( file, " - is d. prec %lu\n", ( unsigned long )bli_obj_is_double_prec( obj ) ); fprintf( file, " - datatype %lu\n", ( unsigned long )bli_obj_dt( obj ) ); fprintf( file, " - target dt %lu\n", ( unsigned long )bli_obj_target_dt( obj ) ); fprintf( file, " - exec dt %lu\n", ( unsigned long )bli_obj_exec_dt( obj ) ); fprintf( file, " - comp dt %lu\n", ( unsigned long )bli_obj_comp_dt( obj ) ); fprintf( file, " - scalar dt %lu\n", ( unsigned long )bli_obj_scalar_dt( obj ) ); fprintf( file, " - has trans %lu\n", ( unsigned long )bli_obj_has_trans( obj ) ); fprintf( file, " - has conj %lu\n", ( unsigned long )bli_obj_has_conj( obj ) ); fprintf( file, " - unit diag? %lu\n", ( unsigned long )bli_obj_has_unit_diag( obj ) ); fprintf( file, " - struc type %lu\n", ( unsigned long )bli_obj_struc( obj ) >> BLIS_STRUC_SHIFT ); fprintf( file, " - uplo type %lu\n", ( unsigned long )bli_obj_uplo( obj ) >> BLIS_UPLO_SHIFT ); fprintf( file, " - is upper %lu\n", ( unsigned long )bli_obj_is_upper( obj ) ); fprintf( file, " - is lower %lu\n", ( unsigned long )bli_obj_is_lower( obj ) ); fprintf( file, " - is dense %lu\n", ( unsigned long )bli_obj_is_dense( obj ) ); fprintf( file, " - pack schema %lu\n", ( unsigned long )bli_obj_pack_schema( obj ) >> BLIS_PACK_SCHEMA_SHIFT ); fprintf( file, " - packinv diag? %lu\n", ( unsigned long )bli_obj_has_inverted_diag( obj ) ); fprintf( file, " - pack ordifup %lu\n", ( unsigned long )bli_obj_is_pack_rev_if_upper( obj ) ); fprintf( file, " - pack ordiflo %lu\n", ( unsigned long )bli_obj_is_pack_rev_if_lower( obj ) ); fprintf( file, " - packbuf type %lu\n", ( unsigned long )bli_obj_pack_buffer_type( obj ) >> BLIS_PACK_BUFFER_SHIFT ); fprintf( file, "\n" ); } blis-0.9.0/frame/base/bli_obj.h000066400000000000000000000067641422157504600162510ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "bli_obj_check.h" BLIS_EXPORT_BLIS void bli_obj_create ( num_t dt, dim_t m, dim_t n, inc_t rs, inc_t cs, obj_t* obj ); BLIS_EXPORT_BLIS void bli_obj_create_with_attached_buffer ( num_t dt, dim_t m, dim_t n, void* p, inc_t rs, inc_t cs, obj_t* obj ); BLIS_EXPORT_BLIS void bli_obj_create_without_buffer ( num_t dt, dim_t m, dim_t n, obj_t* obj ); BLIS_EXPORT_BLIS void bli_obj_alloc_buffer ( inc_t rs, inc_t cs, inc_t is, obj_t* obj ); BLIS_EXPORT_BLIS void bli_obj_attach_buffer ( void* p, inc_t rs, inc_t cs, inc_t is, obj_t* obj ); BLIS_EXPORT_BLIS void bli_obj_create_1x1 ( num_t dt, obj_t* obj ); BLIS_EXPORT_BLIS void bli_obj_create_1x1_with_attached_buffer ( num_t dt, void* p, obj_t* obj ); BLIS_EXPORT_BLIS void bli_obj_create_conf_to ( obj_t* s, obj_t* d ); BLIS_EXPORT_BLIS void bli_obj_free ( obj_t* obj ); void bli_adjust_strides ( dim_t m, dim_t n, siz_t elem_size, inc_t* rs, inc_t* cs, inc_t* is ); BLIS_EXPORT_BLIS siz_t bli_dt_size ( num_t dt ); BLIS_EXPORT_BLIS char* bli_dt_string ( num_t dt ); BLIS_EXPORT_BLIS dim_t bli_align_dim_to_mult ( dim_t dim, dim_t dim_mult ); BLIS_EXPORT_BLIS dim_t bli_align_dim_to_size ( dim_t dim, siz_t elem_size, siz_t align_size ); BLIS_EXPORT_BLIS dim_t bli_align_ptr_to_size ( void* p, size_t align_size ); BLIS_EXPORT_BLIS void bli_obj_print ( char* label, obj_t* obj ); blis-0.9.0/frame/base/bli_obj_scalar.c000066400000000000000000000166271422157504600175700ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_obj_scalar_init_detached ( num_t dt, obj_t* beta ) { void* p; // Initialize beta without a buffer and then attach its internal buffer. // NOTE: This initializes both the storage datatype and scalar datatype // bitfields within beta to dt. bli_obj_create_without_buffer( dt, 1, 1, beta ); // Query the address of the object's internal scalar buffer. p = bli_obj_internal_scalar_buffer( beta ); // Update the object. bli_obj_set_buffer( p, beta ); bli_obj_set_strides( 1, 1, beta ); bli_obj_set_imag_stride( 1, beta ); } void bli_obj_scalar_init_detached_copy_of ( num_t dt, conj_t conj, obj_t* alpha, obj_t* beta ) { obj_t alpha_local; // Make a local copy of alpha so we can apply the conj parameter. bli_obj_alias_to( alpha, &alpha_local ); bli_obj_apply_conj( conj, &alpha_local ); // Initialize beta without a buffer and then attach its internal buffer. bli_obj_scalar_init_detached( dt, beta ); // Copy the scalar value in a to object b, conjugating and/or // typecasting if needed. bli_copysc( &alpha_local, beta ); } void bli_obj_scalar_detach ( obj_t* a, obj_t* alpha ) { // Use the scalar datatype of A as the storage datatype of the detached // object alpha. num_t dt_a = bli_obj_scalar_dt( a ); // Initialize alpha to be a bufferless internal scalar of the same // datatype as the scalar attached to A. bli_obj_scalar_init_detached( dt_a, alpha ); // Copy the internal scalar in A to alpha. // NOTE: This is simply a field-to-field copy with no typecasting. But // that's okay since bli_obj_scalar_init_detached() initializes the // storage datatype of alpha to be the same as the datatype of the // scalar queried from bli_obj_scalar_dt() above. bli_obj_copy_internal_scalar( a, alpha ); } void bli_obj_scalar_attach ( conj_t conj, obj_t* alpha, obj_t* a ) { obj_t alpha_cast; // Use the target datatype of A as the datatype to which we cast // alpha locally. const num_t dt_targ = bli_obj_target_dt( a ); // Make a copy-cast of alpha to the target datatype of A, queried // above. This step gives us the opportunity to conjugate and/or // typecast alpha. bli_obj_scalar_init_detached_copy_of( dt_targ, conj, alpha, &alpha_cast ); // Copy the internal scalar in alpha_cast to A. bli_obj_copy_internal_scalar( &alpha_cast, a ); // Update the scalar datatype of A. bli_obj_set_scalar_dt( dt_targ, a ); } void bli_obj_scalar_cast_to ( num_t dt, obj_t* a ) { obj_t alpha; obj_t alpha_cast; // Initialize an object alpha to be a bufferless scalar whose // storage datatype is equal to the scalar datatype of A. bli_obj_scalar_init_detached( bli_obj_scalar_dt( a ), &alpha ); // Copy the internal scalar in A to alpha. // NOTE: Since alpha was initialized with the scalar datatype of A, // a simple field-to-field copy is sufficient (no casting is needed // here). bli_obj_copy_internal_scalar( a, &alpha ); // Make a copy-cast of alpha, alpha_cast, with the datatype given by // the caller. (This is where the typecasting happens.) bli_obj_scalar_init_detached_copy_of( dt, BLIS_NO_CONJUGATE, &alpha, &alpha_cast ); // Copy the newly-typecasted value in alpha_cast back to A. bli_obj_copy_internal_scalar( &alpha_cast, a ); // Update the scalar datatype of A to reflect to new datatype used // in the typecast. bli_obj_set_scalar_dt( dt, a ); } void bli_obj_scalar_apply_scalar ( obj_t* alpha, obj_t* a ) { obj_t alpha_cast; obj_t scalar_a; // Make a copy of alpha, alpha_cast, with the same datatype as the // scalar datatype of A. (This is where the typecasting happens.) bli_obj_scalar_init_detached_copy_of( bli_obj_scalar_dt( a ), BLIS_NO_CONJUGATE, alpha, &alpha_cast ); // Detach the scalar from A. bli_obj_scalar_detach( a, &scalar_a ); // Scale the detached scalar by alpha. bli_mulsc( &alpha_cast, &scalar_a ); // Copy the internal scalar in scalar_a to A. bli_obj_copy_internal_scalar( &scalar_a, a ); } void bli_obj_scalar_reset ( obj_t* a ) { num_t dt = bli_obj_scalar_dt( a ); void* scalar_a = bli_obj_internal_scalar_buffer( a ); void* one = bli_obj_buffer_for_const( dt, &BLIS_ONE ); if ( bli_is_float( dt ) ) *(( float* )scalar_a) = *(( float* )one); else if ( bli_is_double( dt ) ) *(( double* )scalar_a) = *(( double* )one); else if ( bli_is_scomplex( dt ) ) *(( scomplex* )scalar_a) = *(( scomplex* )one); else if ( bli_is_dcomplex( dt ) ) *(( dcomplex* )scalar_a) = *(( dcomplex* )one); // Alternate implementation: //bli_obj_scalar_attach( BLIS_NO_CONJUGATE, &BLIS_ONE, a ); } bool bli_obj_scalar_has_nonzero_imag ( obj_t* a ) { bool r_val = FALSE; num_t dt = bli_obj_scalar_dt( a ); void* scalar_a = bli_obj_internal_scalar_buffer( a ); // FGVZ: Reimplement by using bli_obj_imag_part() and then // bli_obj_equals( &BLIS_ZERO, ... ). if ( bli_is_real( dt ) ) { r_val = FALSE; } else if ( bli_is_scomplex( dt ) ) { r_val = ( bli_cimag( *(( scomplex* )scalar_a) ) != 0.0F ); } else if ( bli_is_dcomplex( dt ) ) { r_val = ( bli_zimag( *(( dcomplex* )scalar_a) ) != 0.0 ); } return r_val; } bool bli_obj_scalar_equals ( obj_t* a, obj_t* beta ) { obj_t scalar_a; bool r_val; bli_obj_scalar_detach( a, &scalar_a ); r_val = bli_obj_equals( &scalar_a, beta ); return r_val; } blis-0.9.0/frame/base/bli_obj_scalar.h000066400000000000000000000050471422157504600175670ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ BLIS_EXPORT_BLIS void bli_obj_scalar_init_detached ( num_t dt, obj_t* beta ); BLIS_EXPORT_BLIS void bli_obj_scalar_init_detached_copy_of ( num_t dt, conj_t conj, obj_t* alpha, obj_t* beta ); BLIS_EXPORT_BLIS void bli_obj_scalar_detach ( obj_t* a, obj_t* alpha ); BLIS_EXPORT_BLIS void bli_obj_scalar_attach ( conj_t conj, obj_t* alpha, obj_t* a ); BLIS_EXPORT_BLIS void bli_obj_scalar_cast_to ( num_t dt, obj_t* a ); BLIS_EXPORT_BLIS void bli_obj_scalar_apply_scalar ( obj_t* alpha, obj_t* a ); BLIS_EXPORT_BLIS void bli_obj_scalar_reset ( obj_t* a ); BLIS_EXPORT_BLIS bool bli_obj_scalar_has_nonzero_imag ( obj_t* a ); BLIS_EXPORT_BLIS bool bli_obj_scalar_equals ( obj_t* a, obj_t* beta ); blis-0.9.0/frame/base/bli_opid.h000066400000000000000000000034061422157504600164200ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ BLIS_INLINE bool bli_opid_is_level3( opid_t opid ) { return ( bool ) ( BLIS_GEMM <= opid && opid <= BLIS_TRSM ); } blis-0.9.0/frame/base/bli_pack.c000066400000000000000000000116671422157504600164060ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // The global rntm_t structure. (The definition resides in bli_rntm.c.) extern rntm_t global_rntm; // A mutex to allow synchronous access to global_rntm. (The definition // resides in bli_rntm.c.) extern bli_pthread_mutex_t global_rntm_mutex; // ----------------------------------------------------------------------------- void bli_pack_init( void ) { // Read the environment variables and use them to initialize the // global runtime object. bli_pack_init_rntm_from_env( &global_rntm ); } void bli_pack_finalize( void ) { } // ----------------------------------------------------------------------------- void bli_pack_get_pack_a( bool* pack_a ) { // We must ensure that global_rntm has been initialized. bli_init_once(); *pack_a = bli_rntm_pack_a( &global_rntm ); } // ----------------------------------------------------------------------------- void bli_pack_get_pack_b( bool* pack_b ) { // We must ensure that global_rntm has been initialized. bli_init_once(); *pack_b = bli_rntm_pack_b( &global_rntm ); } // ---------------------------------------------------------------------------- void bli_pack_set_pack_a( bool pack_a ) { // We must ensure that global_rntm has been initialized. bli_init_once(); // Acquire the mutex protecting global_rntm. bli_pthread_mutex_lock( &global_rntm_mutex ); bli_rntm_set_pack_a( pack_a, &global_rntm ); // Release the mutex protecting global_rntm. bli_pthread_mutex_unlock( &global_rntm_mutex ); } // ---------------------------------------------------------------------------- void bli_pack_set_pack_b( bool pack_b ) { // We must ensure that global_rntm has been initialized. bli_init_once(); // Acquire the mutex protecting global_rntm. bli_pthread_mutex_lock( &global_rntm_mutex ); bli_rntm_set_pack_b( pack_b, &global_rntm ); // Release the mutex protecting global_rntm. bli_pthread_mutex_unlock( &global_rntm_mutex ); } // ---------------------------------------------------------------------------- void bli_pack_init_rntm_from_env ( rntm_t* rntm ) { // NOTE: We don't need to acquire the global_rntm_mutex here because this // function is only called from bli_pack_init(), which is only called // by bli_init_once(). bool pack_a; bool pack_b; #if 1 //def BLIS_ENABLE_SELECTIVE_PACKING // Try to read BLIS_PACK_A and BLIS_PACK_B. For each variable, default to // -1 if it is unset. gint_t pack_a_env = bli_env_get_var( "BLIS_PACK_A", -1 ); gint_t pack_b_env = bli_env_get_var( "BLIS_PACK_B", -1 ); // Enforce the default behavior first, then check for affirmative FALSE, and // finally assume anything else is TRUE. if ( pack_a_env == -1 ) pack_a = FALSE; // default behavior else if ( pack_a_env == 0 ) pack_a = FALSE; // zero is FALSE else pack_a = TRUE; // anything else is TRUE if ( pack_b_env == -1 ) pack_b = FALSE; // default behavior else if ( pack_b_env == 0 ) pack_b = FALSE; // zero is FALSE else pack_b = TRUE; // anything else is TRUE #else pack_a = TRUE; pack_b = TRUE; #endif // Save the results back in the runtime object. bli_rntm_set_pack_a( pack_a, rntm ); bli_rntm_set_pack_b( pack_b, rntm ); #if 0 printf( "bli_pack_init_rntm_from_env()\n" ); bli_rntm_print( rntm ); #endif } blis-0.9.0/frame/base/bli_pack.h000066400000000000000000000040301422157504600163750ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_PACK_H #define BLIS_PACK_H void bli_pack_init( void ); void bli_pack_finalize( void ); BLIS_EXPORT_BLIS void bli_pack_get_pack_a( bool* pack_a ); BLIS_EXPORT_BLIS void bli_pack_get_pack_b( bool* pack_b ); BLIS_EXPORT_BLIS void bli_pack_set_pack_a( bool pack_a ); BLIS_EXPORT_BLIS void bli_pack_set_pack_b( bool pack_b ); void bli_pack_init_rntm_from_env( rntm_t* rntm ); #endif blis-0.9.0/frame/base/bli_param_map.c000066400000000000000000000170011422157504600174110ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // --- BLIS to BLAS/LAPACK mappings -------------------------------------------- void bli_param_map_blis_to_netlib_side( side_t side, char* blas_side ) { if ( side == BLIS_LEFT ) *blas_side = 'L'; else if ( side == BLIS_RIGHT ) *blas_side = 'R'; else { bli_check_error_code( BLIS_INVALID_SIDE ); } } void bli_param_map_blis_to_netlib_uplo( uplo_t uplo, char* blas_uplo ) { if ( uplo == BLIS_LOWER ) *blas_uplo = 'L'; else if ( uplo == BLIS_UPPER ) *blas_uplo = 'U'; else { bli_check_error_code( BLIS_INVALID_UPLO ); } } void bli_param_map_blis_to_netlib_trans( trans_t trans, char* blas_trans ) { if ( trans == BLIS_NO_TRANSPOSE ) *blas_trans = 'N'; else if ( trans == BLIS_TRANSPOSE ) *blas_trans = 'T'; else if ( trans == BLIS_CONJ_TRANSPOSE ) *blas_trans = 'C'; else { bli_check_error_code( BLIS_INVALID_TRANS ); } } void bli_param_map_blis_to_netlib_diag( diag_t diag, char* blas_diag ) { if ( diag == BLIS_NONUNIT_DIAG ) *blas_diag = 'N'; else if ( diag == BLIS_UNIT_DIAG ) *blas_diag = 'U'; else { bli_check_error_code( BLIS_INVALID_DIAG ); } } void bli_param_map_blis_to_netlib_machval( machval_t machval, char* blas_machval ) { if ( machval == BLIS_MACH_EPS ) *blas_machval = 'E'; else if ( machval == BLIS_MACH_SFMIN ) *blas_machval = 'S'; else if ( machval == BLIS_MACH_BASE ) *blas_machval = 'B'; else if ( machval == BLIS_MACH_PREC ) *blas_machval = 'P'; else if ( machval == BLIS_MACH_NDIGMANT ) *blas_machval = 'N'; else if ( machval == BLIS_MACH_RND ) *blas_machval = 'R'; else if ( machval == BLIS_MACH_EMIN ) *blas_machval = 'M'; else if ( machval == BLIS_MACH_RMIN ) *blas_machval = 'U'; else if ( machval == BLIS_MACH_EMAX ) *blas_machval = 'L'; else if ( machval == BLIS_MACH_RMAX ) *blas_machval = 'O'; else { bli_check_error_code( BLIS_INVALID_MACHVAL ); } } // --- BLAS/LAPACK to BLIS mappings -------------------------------------------- // NOTE: These functions were converted into static functions. Please see this // file's corresponding header for those definitions. // --- BLIS char to BLIS mappings ---------------------------------------------- void bli_param_map_char_to_blis_side( char side, side_t* blis_side ) { if ( side == 'l' || side == 'L' ) *blis_side = BLIS_LEFT; else if ( side == 'r' || side == 'R' ) *blis_side = BLIS_RIGHT; else { bli_check_error_code( BLIS_INVALID_SIDE ); } } void bli_param_map_char_to_blis_uplo( char uplo, uplo_t* blis_uplo ) { if ( uplo == 'l' || uplo == 'L' ) *blis_uplo = BLIS_LOWER; else if ( uplo == 'u' || uplo == 'U' ) *blis_uplo = BLIS_UPPER; else if ( uplo == 'e' || uplo == 'E' ) *blis_uplo = BLIS_DENSE; else { bli_check_error_code( BLIS_INVALID_UPLO ); } } void bli_param_map_char_to_blis_trans( char trans, trans_t* blis_trans ) { if ( trans == 'n' || trans == 'N' ) *blis_trans = BLIS_NO_TRANSPOSE; else if ( trans == 't' || trans == 'T' ) *blis_trans = BLIS_TRANSPOSE; else if ( trans == 'c' || trans == 'C' ) *blis_trans = BLIS_CONJ_NO_TRANSPOSE; else if ( trans == 'h' || trans == 'H' ) *blis_trans = BLIS_CONJ_TRANSPOSE; else { bli_check_error_code( BLIS_INVALID_TRANS ); } } void bli_param_map_char_to_blis_conj( char conj, conj_t* blis_conj ) { if ( conj == 'n' || conj == 'N' ) *blis_conj = BLIS_NO_CONJUGATE; else if ( conj == 'c' || conj == 'C' ) *blis_conj = BLIS_CONJUGATE; else { bli_check_error_code( BLIS_INVALID_CONJ ); } } void bli_param_map_char_to_blis_diag( char diag, diag_t* blis_diag ) { if ( diag == 'n' || diag == 'N' ) *blis_diag = BLIS_NONUNIT_DIAG; else if ( diag == 'u' || diag == 'U' ) *blis_diag = BLIS_UNIT_DIAG; else { bli_check_error_code( BLIS_INVALID_DIAG ); } } void bli_param_map_char_to_blis_dt( char dt, num_t* blis_dt ) { if ( dt == 's' ) *blis_dt = BLIS_FLOAT; else if ( dt == 'd' ) *blis_dt = BLIS_DOUBLE; else if ( dt == 'c' ) *blis_dt = BLIS_SCOMPLEX; else if ( dt == 'z' ) *blis_dt = BLIS_DCOMPLEX; else if ( dt == 'i' ) *blis_dt = BLIS_INT; else { bli_check_error_code( BLIS_INVALID_DATATYPE ); } } // --- BLIS to BLIS char mappings ---------------------------------------------- void bli_param_map_blis_to_char_side( side_t blis_side, char* side ) { if ( blis_side == BLIS_LEFT ) *side = 'l'; else if ( blis_side == BLIS_RIGHT ) *side = 'r'; else { bli_check_error_code( BLIS_INVALID_SIDE ); } } void bli_param_map_blis_to_char_uplo( uplo_t blis_uplo, char* uplo ) { if ( blis_uplo == BLIS_LOWER ) *uplo = 'l'; else if ( blis_uplo == BLIS_UPPER ) *uplo = 'u'; else { bli_check_error_code( BLIS_INVALID_UPLO ); } } void bli_param_map_blis_to_char_trans( trans_t blis_trans, char* trans ) { if ( blis_trans == BLIS_NO_TRANSPOSE ) *trans = 'n'; else if ( blis_trans == BLIS_TRANSPOSE ) *trans = 't'; else if ( blis_trans == BLIS_CONJ_NO_TRANSPOSE ) *trans = 'c'; else if ( blis_trans == BLIS_CONJ_TRANSPOSE ) *trans = 'h'; else { bli_check_error_code( BLIS_INVALID_TRANS ); } } void bli_param_map_blis_to_char_conj( conj_t blis_conj, char* conj ) { if ( blis_conj == BLIS_NO_CONJUGATE ) *conj = 'n'; else if ( blis_conj == BLIS_CONJUGATE ) *conj = 'c'; else { bli_check_error_code( BLIS_INVALID_CONJ ); } } void bli_param_map_blis_to_char_diag( diag_t blis_diag, char* diag ) { if ( blis_diag == BLIS_NONUNIT_DIAG ) *diag = 'n'; else if ( blis_diag == BLIS_UNIT_DIAG ) *diag = 'u'; else { bli_check_error_code( BLIS_INVALID_DIAG ); } } void bli_param_map_blis_to_char_dt( num_t blis_dt, char* dt ) { if ( blis_dt == BLIS_FLOAT ) *dt = 's'; else if ( blis_dt == BLIS_DOUBLE ) *dt = 'd'; else if ( blis_dt == BLIS_SCOMPLEX ) *dt = 'c'; else if ( blis_dt == BLIS_DCOMPLEX ) *dt = 'z'; else if ( blis_dt == BLIS_INT ) *dt = 'i'; else { bli_check_error_code( BLIS_INVALID_DATATYPE ); } } blis-0.9.0/frame/base/bli_param_map.h000066400000000000000000000131051422157504600174170ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // --- BLIS to BLAS/LAPACK mappings -------------------------------------------- BLIS_EXPORT_BLIS void bli_param_map_blis_to_netlib_side( side_t side, char* blas_side ); BLIS_EXPORT_BLIS void bli_param_map_blis_to_netlib_uplo( uplo_t uplo, char* blas_uplo ); BLIS_EXPORT_BLIS void bli_param_map_blis_to_netlib_trans( trans_t trans, char* blas_trans ); BLIS_EXPORT_BLIS void bli_param_map_blis_to_netlib_diag( diag_t diag, char* blas_diag ); BLIS_EXPORT_BLIS void bli_param_map_blis_to_netlib_machval( machval_t machval, char* blas_machval ); // --- BLAS/LAPACK to BLIS mappings -------------------------------------------- // NOTE: These static functions were converted from regular functions in order // to reduce function call overhead within the BLAS compatibility layer. BLIS_INLINE void bli_param_map_netlib_to_blis_side( char side, side_t* blis_side ) { if ( side == 'l' || side == 'L' ) *blis_side = BLIS_LEFT; else if ( side == 'r' || side == 'R' ) *blis_side = BLIS_RIGHT; else { // Instead of reporting an error to the framework, default to // an arbitrary value. This is needed because this function is // called by the BLAS compatibility layer AFTER it has already // checked errors and called xerbla(). If the application wants // to override the BLAS compatibility layer's xerbla--which // responds to errors with abort()--we need to also NOT call // abort() here, since either way it has already been dealt // with. //bli_check_error_code( BLIS_INVALID_SIDE ); *blis_side = BLIS_LEFT; } } BLIS_INLINE void bli_param_map_netlib_to_blis_uplo( char uplo, uplo_t* blis_uplo ) { if ( uplo == 'l' || uplo == 'L' ) *blis_uplo = BLIS_LOWER; else if ( uplo == 'u' || uplo == 'U' ) *blis_uplo = BLIS_UPPER; else { // See comment for bli_param_map_netlib_to_blis_side() above. //bli_check_error_code( BLIS_INVALID_UPLO ); *blis_uplo = BLIS_LOWER; } } BLIS_INLINE void bli_param_map_netlib_to_blis_trans( char trans, trans_t* blis_trans ) { if ( trans == 'n' || trans == 'N' ) *blis_trans = BLIS_NO_TRANSPOSE; else if ( trans == 't' || trans == 'T' ) *blis_trans = BLIS_TRANSPOSE; else if ( trans == 'c' || trans == 'C' ) *blis_trans = BLIS_CONJ_TRANSPOSE; else { // See comment for bli_param_map_netlib_to_blis_side() above. //bli_check_error_code( BLIS_INVALID_TRANS ); *blis_trans = BLIS_NO_TRANSPOSE; } } BLIS_INLINE void bli_param_map_netlib_to_blis_diag( char diag, diag_t* blis_diag ) { if ( diag == 'n' || diag == 'N' ) *blis_diag = BLIS_NONUNIT_DIAG; else if ( diag == 'u' || diag == 'U' ) *blis_diag = BLIS_UNIT_DIAG; else { // See comment for bli_param_map_netlib_to_blis_side() above. //bli_check_error_code( BLIS_INVALID_DIAG ); *blis_diag = BLIS_NONUNIT_DIAG; } } // --- BLIS char to BLIS mappings ---------------------------------------------- BLIS_EXPORT_BLIS void bli_param_map_char_to_blis_side( char side, side_t* blis_side ); BLIS_EXPORT_BLIS void bli_param_map_char_to_blis_uplo( char uplo, uplo_t* blis_uplo ); BLIS_EXPORT_BLIS void bli_param_map_char_to_blis_trans( char trans, trans_t* blis_trans ); BLIS_EXPORT_BLIS void bli_param_map_char_to_blis_conj( char conj, conj_t* blis_conj ); BLIS_EXPORT_BLIS void bli_param_map_char_to_blis_diag( char diag, diag_t* blis_diag ); BLIS_EXPORT_BLIS void bli_param_map_char_to_blis_dt( char dt, num_t* blis_dt ); // --- BLIS to BLIS char mappings ---------------------------------------------- BLIS_EXPORT_BLIS void bli_param_map_blis_to_char_side( side_t blis_side, char* side ); BLIS_EXPORT_BLIS void bli_param_map_blis_to_char_uplo( uplo_t blis_uplo, char* uplo ); BLIS_EXPORT_BLIS void bli_param_map_blis_to_char_trans( trans_t blis_trans, char* trans ); BLIS_EXPORT_BLIS void bli_param_map_blis_to_char_conj( conj_t blis_conj, char* conj ); BLIS_EXPORT_BLIS void bli_param_map_blis_to_char_diag( diag_t blis_diag, char* diag ); BLIS_EXPORT_BLIS void bli_param_map_blis_to_char_dt( num_t blis_dt, char* dt ); blis-0.9.0/frame/base/bli_part.c000066400000000000000000000603121422157504600164250ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // -- Matrix partitioning ------------------------------------------------------ void bli_acquire_mpart ( dim_t i, dim_t j, dim_t bm, dim_t bn, obj_t* parent, obj_t* child ) { // Query the dimensions of the parent object. const dim_t m_par = bli_obj_length( parent ); const dim_t n_par = bli_obj_width( parent ); // If either i or j is already beyond what exists of the parent matrix, // slide them back to the outer dimensions. (What will happen in this // scenario is that bm and bn and/or will be reduced to zero so that the // child matrix does not refer to anything beyond the bounds of the // parent. (Note: This is a safety measure and generally should never // be needed if the caller is passing in sane arguments.) if ( i > m_par ) i = m_par; if ( j > n_par ) j = n_par; // If either bm or bn spills out over the edge of the parent matrix, // reduce them so that the child matrix fits within the bounds of the // parent. (Note: This is a safety measure and generally should never // be needed if the caller is passing in sane arguments, though this // code is somewhat more likely to be needed than the code above.) if ( bm > m_par - i ) bm = m_par - i; if ( bn > n_par - j ) bn = n_par - j; // Alias the parent object's contents into the child object. bli_obj_alias_to( parent, child ); // Set the offsets and dimensions of the child object. Note that we // increment, rather than overwrite, the offsets of the child object // in case the parent object already had non-zero offsets (usually // because the parent was itself a child a larger grandparent object). bli_obj_inc_offs( i, j, child ); bli_obj_set_dims( bm, bn, child ); } void bli_acquire_mpart_t2b ( subpart_t req_part, dim_t i, dim_t b, obj_t* obj, obj_t* sub_obj ) { bli_acquire_mpart_mdim( BLIS_FWD, req_part, i, b, obj, sub_obj ); } void bli_acquire_mpart_b2t ( subpart_t req_part, dim_t i, dim_t b, obj_t* obj, obj_t* sub_obj ) { bli_acquire_mpart_mdim( BLIS_BWD, req_part, i, b, obj, sub_obj ); } void bli_acquire_mpart_mdim ( dir_t direct, subpart_t req_part, dim_t i, dim_t b, obj_t* obj, obj_t* sub_obj ) { dim_t m; dim_t n; dim_t m_part = 0; dim_t n_part = 0; inc_t offm_inc = 0; inc_t offn_inc = 0; doff_t diag_off_inc; // Call a special function for partitioning packed objects. (By only // catching those objects packed to panels, we omit cases where the // object is packed to row or column storage, as such objects can be // partitioned through normally.) Note that the function called below // assumes forward partitioning. if ( bli_obj_is_panel_packed( obj ) ) { bli_packm_acquire_mpart_t2b( req_part, i, b, obj, sub_obj ); return; } // Check parameters. if ( bli_error_checking_is_enabled() ) bli_acquire_mpart_t2b_check( req_part, i, b, obj, sub_obj ); // Query the m and n dimensions of the object (accounting for // transposition, if indicated). if ( bli_obj_has_notrans( obj ) ) { m = bli_obj_length( obj ); n = bli_obj_width( obj ); } else // if ( bli_obj_has_trans( obj ) ) { m = bli_obj_width( obj ); n = bli_obj_length( obj ); } // Foolproofing: do not let b exceed what's left of the m dimension at // row offset i. if ( b > m - i ) b = m - i; // NOTE: Most of this function implicitly assumes moving forward. // When moving backward, we have to relocate i. if ( direct == BLIS_BWD ) { // Modify i to account for the fact that we are moving backwards. i = m - i - b; } // Support SUBPART1B (behind SUBPART1) and SUBPART1A (ahead of SUBPART1), // to refer to subpartitions 0 and 2 when moving forward, and 2 and 0 when // moving backward. subpart_t subpart0_alias; subpart_t subpart2_alias; if ( direct == BLIS_FWD ) { subpart0_alias = BLIS_SUBPART1B; subpart2_alias = BLIS_SUBPART1A; } else { subpart0_alias = BLIS_SUBPART1A; subpart2_alias = BLIS_SUBPART1B; } // Compute offset increments and dimensions based on which // subpartition is being requested, assuming no transposition. if ( req_part == BLIS_SUBPART0 || req_part == subpart0_alias ) { // A0 (offm,offn) unchanged. // A0 is i x n. offm_inc = 0; offn_inc = 0; m_part = i; n_part = n; } else if ( req_part == BLIS_SUBPART1AND0 ) { // A1+A0 (offm,offn) unchanged. // A1+A0 is (i+b) x n. offm_inc = 0; offn_inc = 0; m_part = i + b; n_part = n; } else if ( req_part == BLIS_SUBPART1 ) { // A1 (offm,offn) += (i,0). // A1 is b x n. offm_inc = i; offn_inc = 0; m_part = b; n_part = n; } else if ( req_part == BLIS_SUBPART1AND2 ) { // A1+A2 (offm,offn) += (i,0). // A1+A2 is (m-i) x n. offm_inc = i; offn_inc = 0; m_part = m - i; n_part = n; } else if ( req_part == BLIS_SUBPART2 || req_part == subpart2_alias ) { // A2 (offm,offn) += (i+b,0). // A2 is (m-i-b) x n. offm_inc = i + b; offn_inc = 0; m_part = m - i - b; n_part = n; } // Compute the diagonal offset based on the m and n offsets. diag_off_inc = ( doff_t )offm_inc - ( doff_t )offn_inc; // Begin by copying the info, elem size, buffer, row stride, and column // stride fields of the parent object. Note that this omits copying view // information because the new partition will have its own dimensions // and offsets. bli_obj_init_subpart_from( obj, sub_obj ); // Modify offsets and dimensions of requested partition based on // whether it needs to be transposed. if ( bli_obj_has_notrans( obj ) ) { bli_obj_set_dims( m_part, n_part, sub_obj ); bli_obj_inc_offs( offm_inc, offn_inc, sub_obj ); bli_obj_inc_diag_offset( diag_off_inc, sub_obj ); } else // if ( bli_obj_has_trans( obj ) ) { bli_obj_set_dims( n_part, m_part, sub_obj ); bli_obj_inc_offs( offn_inc, offm_inc, sub_obj ); bli_obj_inc_diag_offset( -diag_off_inc, sub_obj ); } // If the root matrix is not general (ie: has structure defined by the // diagonal), and the subpartition does not intersect the root matrix's // diagonal, then set the subpartition structure to "general"; otherwise // we let the subpartition inherit the storage structure of its immediate // parent. if ( !bli_obj_root_is_general( sub_obj ) && bli_obj_is_outside_diag( sub_obj ) ) { // NOTE: This comment may be out-of-date since we now distinguish // between uplo properties for the current and root objects... // Note that we cannot mark the subpartition object as general/dense // here since it makes sense to preserve the existing uplo information // a while longer so that the correct kernels are invoked. (Example: // incremental packing/computing in gemmt produces subpartitions that // appear general/dense, but their uplo fields are needed to be either // lower or upper, to determine which macro-kernel gets called in the // gemmt_int() back-end.) // If the subpartition lies entirely in an "unstored" triangle of the // root matrix, then we need to tweak the subpartition. If the root // matrix is Hermitian or symmetric, then we reflect the partition to // the other side of the diagonal, toggling the transposition bit (and // conjugation bit if the root matrix is Hermitian). Or, if the root // matrix is triangular, the subpartition should be marked as zero. if ( bli_obj_is_unstored_subpart( sub_obj ) ) { if ( bli_obj_root_is_hermitian( sub_obj ) ) { bli_obj_reflect_about_diag( sub_obj ); bli_obj_toggle_conj( sub_obj ); } else if ( bli_obj_root_is_symmetric( sub_obj ) ) { bli_obj_reflect_about_diag( sub_obj ); } else if ( bli_obj_root_is_triangular( sub_obj ) ) { bli_obj_set_uplo( BLIS_ZEROS, sub_obj ); } } } } void bli_acquire_mpart_l2r ( subpart_t req_part, dim_t i, dim_t b, obj_t* obj, obj_t* sub_obj ) { bli_acquire_mpart_ndim( BLIS_FWD, req_part, i, b, obj, sub_obj ); } void bli_acquire_mpart_r2l ( subpart_t req_part, dim_t j, dim_t b, obj_t* obj, obj_t* sub_obj ) { bli_acquire_mpart_ndim( BLIS_BWD, req_part, j, b, obj, sub_obj ); } void bli_acquire_mpart_ndim ( dir_t direct, subpart_t req_part, dim_t j, dim_t b, obj_t* obj, obj_t* sub_obj ) { dim_t m; dim_t n; dim_t m_part = 0; dim_t n_part = 0; inc_t offm_inc = 0; inc_t offn_inc = 0; doff_t diag_off_inc; // Call a special function for partitioning packed objects. (By only // catching those objects packed to panels, we omit cases where the // object is packed to row or column storage, as such objects can be // partitioned through normally.) Note that the function called below // assumes forward partitioning. if ( bli_obj_is_panel_packed( obj ) ) { bli_packm_acquire_mpart_l2r( req_part, j, b, obj, sub_obj ); return; } // Check parameters. if ( bli_error_checking_is_enabled() ) bli_acquire_mpart_l2r_check( req_part, j, b, obj, sub_obj ); // Query the m and n dimensions of the object (accounting for // transposition, if indicated). if ( bli_obj_has_notrans( obj ) ) { m = bli_obj_length( obj ); n = bli_obj_width( obj ); } else // if ( bli_obj_has_trans( obj ) ) { m = bli_obj_width( obj ); n = bli_obj_length( obj ); } // Foolproofing: do not let b exceed what's left of the n dimension at // column offset j. if ( b > n - j ) b = n - j; // NOTE: Most of this function implicitly assumes moving forward. // When moving backward, we have to relocate j. if ( direct == BLIS_BWD ) { // Modify j to account for the fact that we are moving backwards. j = n - j - b; } // Support SUBPART1B (behind SUBPART1) and SUBPART1A (ahead of SUBPART1), // to refer to subpartitions 0 and 2 when moving forward, and 2 and 0 when // moving backward. subpart_t subpart0_alias; subpart_t subpart2_alias; if ( direct == BLIS_FWD ) { subpart0_alias = BLIS_SUBPART1B; subpart2_alias = BLIS_SUBPART1A; } else { subpart0_alias = BLIS_SUBPART1A; subpart2_alias = BLIS_SUBPART1B; } // Compute offset increments and dimensions based on which // subpartition is being requested, assuming no transposition. if ( req_part == BLIS_SUBPART0 || req_part == subpart0_alias ) { // A0 (offm,offn) unchanged. // A0 is m x j. offm_inc = 0; offn_inc = 0; m_part = m; n_part = j; } else if ( req_part == BLIS_SUBPART1AND0 ) { // A1+A0 (offm,offn) unchanged. // A1+A0 is m x (j+b). offm_inc = 0; offn_inc = 0; m_part = m; n_part = j + b; } else if ( req_part == BLIS_SUBPART1 ) { // A1 (offm,offn) += (0,j). // A1 is m x b. offm_inc = 0; offn_inc = j; m_part = m; n_part = b; } else if ( req_part == BLIS_SUBPART1AND2 ) { // A1+A2 (offm,offn) += (0,j). // A1+A2 is m x (n-j). offm_inc = 0; offn_inc = j; m_part = m; n_part = n - j; } else if ( req_part == BLIS_SUBPART2 || req_part == subpart2_alias ) { // A2 (offm,offn) += (0,j+b). // A2 is m x (n-j-b). offm_inc = 0; offn_inc = j + b; m_part = m; n_part = n - j - b; } // Compute the diagonal offset based on the m and n offsets. diag_off_inc = ( doff_t )offm_inc - ( doff_t )offn_inc; // Begin by copying the info, elem size, buffer, row stride, and column // stride fields of the parent object. Note that this omits copying view // information because the new partition will have its own dimensions // and offsets. bli_obj_init_subpart_from( obj, sub_obj ); // Modify offsets and dimensions of requested partition based on // whether it needs to be transposed. if ( bli_obj_has_notrans( obj ) ) { bli_obj_set_dims( m_part, n_part, sub_obj ); bli_obj_inc_offs( offm_inc, offn_inc, sub_obj ); bli_obj_inc_diag_offset( diag_off_inc, sub_obj ); } else // if ( bli_obj_has_trans( obj ) ) { bli_obj_set_dims( n_part, m_part, sub_obj ); bli_obj_inc_offs( offn_inc, offm_inc, sub_obj ); bli_obj_inc_diag_offset( -diag_off_inc, sub_obj ); } // If the root matrix is not general (ie: has structure defined by the // diagonal), and the subpartition does not intersect the root matrix's // diagonal, then we might need to modify some of the subpartition's // properties, depending on its structure type. if ( !bli_obj_root_is_general( sub_obj ) && bli_obj_is_outside_diag( sub_obj ) ) { // NOTE: This comment may be out-of-date since we now distinguish // between uplo properties for the current and root objects... // Note that we cannot mark the subpartition object as general/dense // here since it makes sense to preserve the existing uplo information // a while longer so that the correct kernels are invoked. (Example: // incremental packing/computing in gemmt produces subpartitions that // appear general/dense, but their uplo fields are needed to be either // lower or upper, to determine which macro-kernel gets called in the // gemmt_int() back-end.) // If the subpartition lies entirely in an "unstored" triangle of the // root matrix, then we need to tweak the subpartition. If the root // matrix is Hermitian or symmetric, then we reflect the partition to // the other side of the diagonal, toggling the transposition bit (and // conjugation bit if the root matrix is Hermitian). Or, if the root // matrix is triangular, the subpartition should be marked as zero. if ( bli_obj_is_unstored_subpart( sub_obj ) ) { if ( bli_obj_root_is_hermitian( sub_obj ) ) { bli_obj_reflect_about_diag( sub_obj ); bli_obj_toggle_conj( sub_obj ); } else if ( bli_obj_root_is_symmetric( sub_obj ) ) { bli_obj_reflect_about_diag( sub_obj ); } else if ( bli_obj_root_is_triangular( sub_obj ) ) { bli_obj_set_uplo( BLIS_ZEROS, sub_obj ); } } } } void bli_acquire_mpart_tl2br ( subpart_t req_part, dim_t i, dim_t b, obj_t* obj, obj_t* sub_obj ) { bli_acquire_mpart_mndim( BLIS_FWD, req_part, i, b, obj, sub_obj ); } void bli_acquire_mpart_br2tl ( subpart_t req_part, dim_t j, dim_t b, obj_t* obj, obj_t* sub_obj ) { bli_acquire_mpart_mndim( BLIS_BWD, req_part, j, b, obj, sub_obj ); } void bli_acquire_mpart_mndim ( dir_t direct, subpart_t req_part, dim_t ij, dim_t b, obj_t* obj, obj_t* sub_obj ) { dim_t m; dim_t n; dim_t min_m_n; dim_t m_part = 0; dim_t n_part = 0; inc_t offm_inc = 0; inc_t offn_inc = 0; doff_t diag_off_inc; // Call a special function for partitioning packed objects. (By only // catching those objects packed to panels, we omit cases where the // object is packed to row or column storage, as such objects can be // partitioned through normally.) Note that the function called below // assumes forward partitioning. if ( bli_obj_is_panel_packed( obj ) ) { bli_packm_acquire_mpart_tl2br( req_part, ij, b, obj, sub_obj ); return; } // Check parameters. if ( bli_error_checking_is_enabled() ) bli_acquire_mpart_tl2br_check( req_part, ij, b, obj, sub_obj ); // Query the m and n dimensions of the object (accounting for // transposition, if indicated). if ( bli_obj_has_notrans( obj ) ) { m = bli_obj_length( obj ); n = bli_obj_width( obj ); } else // if ( bli_obj_has_trans( obj ) ) { m = bli_obj_width( obj ); n = bli_obj_length( obj ); } // Foolproofing: do not let b exceed what's left of min(m,n) at // row/column offset ij. min_m_n = bli_min( m, n ); if ( b > min_m_n - ij ) b = min_m_n - ij; // NOTE: Most of this function implicitly assumes moving forward. // When moving backward, we have to relocate ij. if ( direct == BLIS_BWD ) { // Modify ij to account for the fact that we are moving backwards. ij = min_m_n - ij - b; } // Compute offset increments and dimensions based on which // subpartition is being requested, assuming no transposition. // Left column of subpartitions if ( req_part == BLIS_SUBPART00 ) { // A00 (offm,offn) unchanged. // A00 is ij x ij. offm_inc = 0; offn_inc = 0; m_part = ij; n_part = ij; } else if ( req_part == BLIS_SUBPART10 ) { // A10 (offm,offn) += (ij,0). // A10 is b x ij. offm_inc = ij; offn_inc = 0; m_part = b; n_part = ij; } else if ( req_part == BLIS_SUBPART20 ) { // A20 (offm,offn) += (ij+b,0). // A20 is (m-ij-b) x ij. offm_inc = ij + b; offn_inc = 0; m_part = m - ij - b; n_part = ij; } // Middle column of subpartitions. else if ( req_part == BLIS_SUBPART01 ) { // A01 (offm,offn) += (0,ij). // A01 is ij x b. offm_inc = 0; offn_inc = ij; m_part = ij; n_part = b; } else if ( req_part == BLIS_SUBPART11 ) { // A11 (offm,offn) += (ij,ij). // A11 is b x b. offm_inc = ij; offn_inc = ij; m_part = b; n_part = b; } else if ( req_part == BLIS_SUBPART21 ) { // A21 (offm,offn) += (ij+b,ij). // A21 is (m-ij-b) x b. offm_inc = ij + b; offn_inc = ij; m_part = m - ij - b; n_part = b; } // Right column of subpartitions. else if ( req_part == BLIS_SUBPART02 ) { // A02 (offm,offn) += (0,ij+b). // A02 is ij x (n-ij-b). offm_inc = 0; offn_inc = ij + b; m_part = ij; n_part = n - ij - b; } else if ( req_part == BLIS_SUBPART12 ) { // A12 (offm,offn) += (ij,ij+b). // A12 is b x (n-ij-b). offm_inc = ij; offn_inc = ij + b; m_part = b; n_part = n - ij - b; } else // if ( req_part == BLIS_SUBPART22 ) { // A22 (offm,offn) += (ij+b,ij+b). // A22 is (m-ij-b) x (n-ij-b). offm_inc = ij + b; offn_inc = ij + b; m_part = m - ij - b; n_part = n - ij - b; } // Compute the diagonal offset based on the m and n offsets. diag_off_inc = ( doff_t )offm_inc - ( doff_t )offn_inc; // Begin by copying the info, elem size, buffer, row stride, and column // stride fields of the parent object. Note that this omits copying view // information because the new partition will have its own dimensions // and offsets. bli_obj_init_subpart_from( obj, sub_obj ); // Modify offsets and dimensions of requested partition based on // whether it needs to be transposed. if ( bli_obj_has_notrans( obj ) ) { bli_obj_set_dims( m_part, n_part, sub_obj ); bli_obj_inc_offs( offm_inc, offn_inc, sub_obj ); bli_obj_inc_diag_offset( diag_off_inc, sub_obj ); } else // if ( bli_obj_has_trans( obj ) ) { bli_obj_set_dims( n_part, m_part, sub_obj ); bli_obj_inc_offs( offn_inc, offm_inc, sub_obj ); bli_obj_inc_diag_offset( -diag_off_inc, sub_obj ); } // If the root matrix is not general (ie: has structure defined by the // diagonal), and the subpartition does not intersect the root matrix's // diagonal, then set the subpartition structure to "general"; otherwise // we let the subpartition inherit the storage structure of its immediate // parent. if ( !bli_obj_root_is_general( sub_obj ) && req_part != BLIS_SUBPART00 && req_part != BLIS_SUBPART11 && req_part != BLIS_SUBPART22 ) { // FGVZ: Fix me. This needs to be cleaned up. Either non-diagonal // intersecting subpartitions should inherit their root object's // uplo field, or it should not. Right now, they DO inherit the // uplo (because they are not set to BLIS_DENSE when the diagonal // does not intersect). But the whole point of being able to query // the root object's properties (e.g. uplo field) was so that we // COULD mark such subpartitions as dense, to make it easier for // certain subproblems on those subpartitions--subproblems that // are agnostic to where the subpartition came from. // NOTE: This comment may be out-of-date since we now distinguish // between uplo properties for the current and root objects... // Note that we cannot mark the subpartition object as general/dense // here since it makes sense to preserve the existing uplo information // a while longer so that the correct kernels are invoked. (Example: // incremental packing/computing in gemmt produces subpartitions that // appear general/dense, but their uplo fields are needed to be either // lower or upper, to determine which macro-kernel gets called in the // gemmt_int() back-end.) // If the subpartition lies entirely in an "unstored" triangle of the // root matrix, then we need to tweak the subpartition. If the root // matrix is Hermitian or symmetric, then we reflect the partition to // the other side of the diagonal, toggling the transposition bit (and // conjugation bit if the root matrix is Hermitian). Or, if the root // matrix is triangular, the subpartition should be marked as zero. if ( bli_obj_is_unstored_subpart( sub_obj ) ) { if ( bli_obj_root_is_hermitian( sub_obj ) ) { bli_obj_reflect_about_diag( sub_obj ); bli_obj_toggle_conj( sub_obj ); } else if ( bli_obj_root_is_symmetric( sub_obj ) ) { bli_obj_reflect_about_diag( sub_obj ); } else if ( bli_obj_root_is_triangular( sub_obj ) ) { bli_obj_set_uplo( BLIS_ZEROS, sub_obj ); } } } } // -- Vector partitioning ------------------------------------------------------ void bli_acquire_vpart_f2b ( subpart_t req_part, dim_t i, dim_t b, obj_t* obj, obj_t* sub_obj ) { if ( bli_obj_is_col_vector( obj ) ) bli_acquire_mpart_mdim( BLIS_FWD, req_part, i, b, obj, sub_obj ); else // if ( bli_obj_is_row_vector( obj ) ) bli_acquire_mpart_ndim( BLIS_FWD, req_part, i, b, obj, sub_obj ); } void bli_acquire_vpart_b2f ( subpart_t req_part, dim_t i, dim_t b, obj_t* obj, obj_t* sub_obj ) { if ( bli_obj_is_col_vector( obj ) ) bli_acquire_mpart_mdim( BLIS_BWD, req_part, i, b, obj, sub_obj ); else // if ( bli_obj_is_row_vector( obj ) ) bli_acquire_mpart_ndim( BLIS_BWD, req_part, i, b, obj, sub_obj ); } // -- Scalar acquisition ------------------------------------------------------- void bli_acquire_mij ( dim_t i, dim_t j, obj_t* obj, obj_t* sub_obj ) { obj_t tmp_obj; bli_acquire_mpart_ndim( BLIS_FWD, BLIS_SUBPART1, j, 1, obj, &tmp_obj ); bli_acquire_mpart_mdim( BLIS_FWD, BLIS_SUBPART1, i, 1, &tmp_obj, sub_obj ); } void bli_acquire_vi ( dim_t i, obj_t* obj, obj_t* sub_obj ) { if ( bli_obj_is_col_vector( obj ) ) bli_acquire_mpart_mdim( BLIS_FWD, BLIS_SUBPART1, i, 1, obj, sub_obj ); else // if ( bli_obj_is_row_vector( obj ) ) bli_acquire_mpart_ndim( BLIS_FWD, BLIS_SUBPART1, i, 1, obj, sub_obj ); } blis-0.9.0/frame/base/bli_part.h000066400000000000000000000065671422157504600164460ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "bli_part_check.h" // -- Matrix partitioning ------------------------------------------------------ BLIS_EXPORT_BLIS void bli_acquire_mpart ( dim_t i, dim_t j, dim_t m, dim_t n, obj_t* obj, obj_t* sub_obj ); #undef GENPROT #define GENPROT( opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC0( opname ) \ ( \ subpart_t req_part, \ dim_t i, \ dim_t b, \ obj_t* obj, \ obj_t* sub_obj \ ); GENPROT( acquire_mpart_t2b ) GENPROT( acquire_mpart_b2t ) GENPROT( acquire_mpart_l2r ) GENPROT( acquire_mpart_r2l ) GENPROT( acquire_mpart_tl2br ) GENPROT( acquire_mpart_br2tl ) #undef GENPROT #define GENPROT( opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC0( opname ) \ ( \ dir_t direct, \ subpart_t req_part, \ dim_t i, \ dim_t b, \ obj_t* obj, \ obj_t* sub_obj \ ); GENPROT( acquire_mpart_mdim ) GENPROT( acquire_mpart_ndim ) GENPROT( acquire_mpart_mndim ) // -- Vector partitioning ------------------------------------------------------ #undef GENPROT #define GENPROT( opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC0( opname ) \ ( \ subpart_t req_part, \ dim_t i, \ dim_t b, \ obj_t* obj, \ obj_t* sub_obj \ ); GENPROT( acquire_vpart_f2b ) GENPROT( acquire_vpart_b2f ) // -- Scalar acquisition ------------------------------------------------------- BLIS_EXPORT_BLIS void bli_acquire_mij ( dim_t i, dim_t j, obj_t* obj, obj_t* sub_obj ); BLIS_EXPORT_BLIS void bli_acquire_vi ( dim_t i, obj_t* obj, obj_t* sub_obj ); blis-0.9.0/frame/base/bli_pba.c000066400000000000000000000422461422157504600162270ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2016, Hewlett Packard Enterprise Development LP Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // Statically initialize the mutex within the packing block allocator object. static pba_t pba = { .mutex = BLIS_PTHREAD_MUTEX_INITIALIZER }; // ----------------------------------------------------------------------------- pba_t* bli_pba_query( void ) { return &pba; } void bli_pba_init ( cntx_t* restrict cntx ) { pba_t* restrict pba = bli_pba_query(); const siz_t align_size = BLIS_POOL_ADDR_ALIGN_SIZE_GEN; malloc_ft malloc_fp = BLIS_MALLOC_POOL; free_ft free_fp = BLIS_FREE_POOL; // These fields are used for general-purpose allocation (ie: buf_type // equal to BLIS_BUFFER_FOR_GEN_USE) within bli_pba_acquire_m(). bli_pba_set_align_size( align_size, pba ); bli_pba_set_malloc_fp( malloc_fp, pba ); bli_pba_set_free_fp( free_fp, pba ); // The mutex field of pba is initialized statically above. This // keeps bli_pba_init() simpler and removes the possibility of // something going wrong during mutex initialization. #ifdef BLIS_ENABLE_PBA_POOLS bli_pba_init_pools( cntx, pba ); #endif } void bli_pba_finalize ( void ) { pba_t* restrict pba = bli_pba_query(); #ifdef BLIS_ENABLE_PBA_POOLS bli_pba_finalize_pools( pba ); #endif // The mutex field of pba is initialized statically above, and // therefore never destroyed. bli_pba_set_malloc_fp( NULL, pba ); bli_pba_set_free_fp( NULL, pba ); } void bli_pba_acquire_m ( rntm_t* rntm, siz_t req_size, packbuf_t buf_type, mem_t* mem ) { pool_t* pool; pblk_t* pblk; dim_t pi; err_t r_val; // If the internal memory pools for packing block allocator are disabled, // we spoof the buffer type as BLIS_BUFFER_FOR_GEN_USE to induce the // immediate usage of bli_pba_malloc(). #ifndef BLIS_ENABLE_PBA_POOLS buf_type = BLIS_BUFFER_FOR_GEN_USE; #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_pba_acquire_m(): bli_fmalloc_align(): size %ld\n", ( long )req_size ); #endif #endif // Query the memory broker from the runtime. pba_t* pba = bli_rntm_pba( rntm ); if ( buf_type == BLIS_BUFFER_FOR_GEN_USE ) { malloc_ft malloc_fp = bli_pba_malloc_fp( pba ); siz_t align_size = bli_pba_align_size( pba ); // For general-use buffer requests, dynamically allocating memory // is assumed to be sufficient. void* buf = bli_fmalloc_align( malloc_fp, req_size, align_size, &r_val ); // Initialize the mem_t object with: // - the address of the memory block, // - the buffer type (a packbuf_t value), // - the size of the requested region, // - the pba_t from which the mem_t entry was acquired. // NOTE: We initialize the pool field to NULL since this block did not // come from a memory pool. bli_mem_set_buffer( buf, mem ); bli_mem_set_buf_type( buf_type, mem ); bli_mem_set_pool( NULL, mem ); bli_mem_set_size( req_size, mem ); } else { // This branch handles cases where the memory block needs to come // from an internal memory pool, in which blocks are allocated once // and then recycled. // Map the requested packed buffer type to a zero-based index, which // we then use to select the corresponding memory pool. pi = bli_packbuf_index( buf_type ); pool = bli_pba_pool( pi, pba ); // Extract the address of the pblk_t struct within the mem_t. pblk = bli_mem_pblk( mem ); // Acquire the mutex associated with the pba object. bli_pba_lock( pba ); // BEGIN CRITICAL SECTION { // Checkout a block from the pool. If the pool's blocks are too // small, it will be reinitialized with blocks large enough to // accommodate the requested block size. If the pool is exhausted, // either because it is still empty or because all blocks have // been checked out already, additional blocks will be allocated // automatically, as-needed. Note that the addresses are stored // directly into the mem_t struct since pblk is the address of // the struct's pblk_t field. bli_pool_checkout_block( req_size, pblk, pool ); } // END CRITICAL SECTION // Release the mutex associated with the pba object. bli_pba_unlock( pba ); // Query the block_size from the pblk_t. This will be at least // req_size, perhaps larger. siz_t block_size = bli_pblk_block_size( pblk ); // Initialize the mem_t object with: // - the buffer type (a packbuf_t value), // - the address of the memory pool to which it belongs, // - the size of the contiguous memory block (NOT the size of the // requested region), // - the pba_t from which the mem_t entry was acquired. // The actual (aligned) address is already stored in the mem_t // struct's pblk_t field. bli_mem_set_buf_type( buf_type, mem ); bli_mem_set_pool( pool, mem ); bli_mem_set_size( block_size, mem ); } } void bli_pba_release ( rntm_t* rntm, mem_t* mem ) { packbuf_t buf_type; pool_t* pool; pblk_t* pblk; // Query the memory broker from the runtime. pba_t* pba = bli_rntm_pba( rntm ); // Extract the buffer type so we know what kind of memory was allocated. buf_type = bli_mem_buf_type( mem ); #ifndef BLIS_ENABLE_PBA_POOLS #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_pba_release(): bli_ffree_align(): size %ld\n", ( long )bli_mem_size( mem ) ); #endif #endif if ( buf_type == BLIS_BUFFER_FOR_GEN_USE ) { free_ft free_fp = bli_pba_free_fp( pba ); void* buf = bli_mem_buffer( mem ); // For general-use buffers, we dynamically allocate memory, and so // here we need to free it. bli_ffree_align( free_fp, buf ); } else { // Extract the address of the pool from which the memory was // allocated. pool = bli_mem_pool( mem ); // Extract the address of the pblk_t struct within the mem_t struct. pblk = bli_mem_pblk( mem ); // Acquire the mutex associated with the pba object. bli_pba_lock( pba ); // BEGIN CRITICAL SECTION { // Check the block back into the pool. bli_pool_checkin_block( pblk, pool ); } // END CRITICAL SECTION // Release the mutex associated with the pba object. bli_pba_unlock( pba ); } // Clear the mem_t object so that it appears unallocated. This clears: // - the pblk_t struct's fields (ie: the buffer addresses) // - the pool field // - the size field // - the pba field // NOTE: We do not clear the buf_type field since there is no // "uninitialized" value for packbuf_t. bli_mem_clear( mem ); } #if 0 void bli_pba_acquire_v ( pba_t* pba, siz_t req_size, mem_t* mem ) { bli_pba_acquire_m ( pba, req_size, BLIS_BUFFER_FOR_GEN_USE, mem ); } #endif siz_t bli_pba_pool_size ( pba_t* pba, packbuf_t buf_type ) { siz_t r_val; if ( buf_type == BLIS_BUFFER_FOR_GEN_USE ) { // We don't (yet) track the amount of general-purpose // memory that is currently allocated. r_val = 0; } else { dim_t pool_index; pool_t* pool; // Acquire the pointer to the pool corresponding to the buf_type // provided. pool_index = bli_packbuf_index( buf_type ); pool = bli_pba_pool( pool_index, pba ); // Compute the pool "size" as the product of the block size // and the number of blocks in the pool. r_val = bli_pool_block_size( pool ) * bli_pool_num_blocks( pool ); } return r_val; } // ----------------------------------------------------------------------------- void bli_pba_init_pools ( cntx_t* cntx, pba_t* pba ) { // Map each of the packbuf_t values to an index starting at zero. const dim_t index_a = bli_packbuf_index( BLIS_BUFFER_FOR_A_BLOCK ); const dim_t index_b = bli_packbuf_index( BLIS_BUFFER_FOR_B_PANEL ); const dim_t index_c = bli_packbuf_index( BLIS_BUFFER_FOR_C_PANEL ); // Alias the pool addresses to convenient identifiers. pool_t* pool_a = bli_pba_pool( index_a, pba ); pool_t* pool_b = bli_pba_pool( index_b, pba ); pool_t* pool_c = bli_pba_pool( index_c, pba ); // Start with empty pools. const dim_t num_blocks_a = 0; const dim_t num_blocks_b = 0; const dim_t num_blocks_c = 0; siz_t block_size_a = 0; siz_t block_size_b = 0; siz_t block_size_c = 0; // For blocks of A and panels of B, start off with block_ptrs arrays that // are of a decent length. For C, we can start off with an empty array. const dim_t block_ptrs_len_a = 80; const dim_t block_ptrs_len_b = 80; const dim_t block_ptrs_len_c = 0; // Use the address alignment sizes designated (at configure-time) for pools. const siz_t align_size_a = BLIS_POOL_ADDR_ALIGN_SIZE_A; const siz_t align_size_b = BLIS_POOL_ADDR_ALIGN_SIZE_B; const siz_t align_size_c = BLIS_POOL_ADDR_ALIGN_SIZE_C; // Use the offsets from the above alignments. const siz_t offset_size_a = BLIS_POOL_ADDR_OFFSET_SIZE_A; const siz_t offset_size_b = BLIS_POOL_ADDR_OFFSET_SIZE_B; const siz_t offset_size_c = BLIS_POOL_ADDR_OFFSET_SIZE_C; // Use the malloc() and free() designated (at configure-time) for pools. malloc_ft malloc_fp = BLIS_MALLOC_POOL; free_ft free_fp = BLIS_FREE_POOL; // Determine the block size for each memory pool. bli_pba_compute_pool_block_sizes( &block_size_a, &block_size_b, &block_size_c, cntx ); // Initialize the memory pools for A, B, and C. bli_pool_init( num_blocks_a, block_ptrs_len_a, block_size_a, align_size_a, offset_size_a, malloc_fp, free_fp, pool_a ); bli_pool_init( num_blocks_b, block_ptrs_len_b, block_size_b, align_size_b, offset_size_b, malloc_fp, free_fp, pool_b ); bli_pool_init( num_blocks_c, block_ptrs_len_c, block_size_c, align_size_c, offset_size_c, malloc_fp, free_fp, pool_c ); } void bli_pba_finalize_pools ( pba_t* pba ) { // Map each of the packbuf_t values to an index starting at zero. dim_t index_a = bli_packbuf_index( BLIS_BUFFER_FOR_A_BLOCK ); dim_t index_b = bli_packbuf_index( BLIS_BUFFER_FOR_B_PANEL ); dim_t index_c = bli_packbuf_index( BLIS_BUFFER_FOR_C_PANEL ); // Alias the pool addresses to convenient identifiers. pool_t* pool_a = bli_pba_pool( index_a, pba ); pool_t* pool_b = bli_pba_pool( index_b, pba ); pool_t* pool_c = bli_pba_pool( index_c, pba ); // Finalize the memory pools for A, B, and C. bli_pool_finalize( pool_a ); bli_pool_finalize( pool_b ); bli_pool_finalize( pool_c ); } // ----------------------------------------------------------------------------- void bli_pba_compute_pool_block_sizes ( siz_t* bs_a, siz_t* bs_b, siz_t* bs_c, cntx_t* cntx ) { const ind_t im = bli_cntx_method( cntx ); siz_t bs_cand_a = 0; siz_t bs_cand_b = 0; siz_t bs_cand_c = 0; num_t dt; // Compute pool block sizes for each datatype and find the maximum // size for each pool. This is done so that new pools do not need // to be allocated if the user switches datatypes. for ( dt = BLIS_DT_LO; dt <= BLIS_DT_HI; ++dt ) { siz_t bs_dt_a; siz_t bs_dt_b; siz_t bs_dt_c; // Avoid considering induced methods for real datatypes. if ( bli_is_real( dt ) && im != BLIS_NAT ) continue; bli_pba_compute_pool_block_sizes_dt( dt, &bs_dt_a, &bs_dt_b, &bs_dt_c, cntx ); bs_cand_a = bli_max( bs_dt_a, bs_cand_a ); bs_cand_b = bli_max( bs_dt_b, bs_cand_b ); bs_cand_c = bli_max( bs_dt_c, bs_cand_c ); } // Save the results. *bs_a = bs_cand_a; *bs_b = bs_cand_b; *bs_c = bs_cand_c; } // ----------------------------------------------------------------------------- void bli_pba_compute_pool_block_sizes_dt ( num_t dt, siz_t* bs_a, siz_t* bs_b, siz_t* bs_c, cntx_t* cntx ) { siz_t size_dt = bli_dt_size( dt ); blksz_t* mr; blksz_t* nr; blksz_t* mc; blksz_t* kc; blksz_t* nc; dim_t mr_dt; dim_t nr_dt; dim_t max_mnr_dt; dim_t mc_max_dt; dim_t kc_max_dt; dim_t nc_max_dt; dim_t packmr_dt; dim_t packnr_dt; dim_t max_packmnr_dt; dim_t scale_num_dt; dim_t scale_den_dt; dim_t pool_mc_dt, left_mc_dt; dim_t pool_nc_dt, left_nc_dt; dim_t pool_kc_dt; // // Find the larger of the two register blocksizes. // // Query the mr and nr blksz_t objects for the given method of // execution. mr = bli_cntx_get_blksz( BLIS_MR, cntx ); nr = bli_cntx_get_blksz( BLIS_NR, cntx ); // Extract the mr and nr values specific to the current datatype. mr_dt = bli_blksz_get_def( dt, mr ); nr_dt = bli_blksz_get_def( dt, nr ); // Find the maximum of mr and nr. max_mnr_dt = bli_max( mr_dt, nr_dt ); // // Define local maximum cache blocksizes. // // Query the mc, kc, and nc blksz_t objects for native execution. mc = bli_cntx_get_blksz( BLIS_MC, cntx ); kc = bli_cntx_get_blksz( BLIS_KC, cntx ); nc = bli_cntx_get_blksz( BLIS_NC, cntx ); // Extract the maximum mc, kc, and nc values specific to the current // datatype. mc_max_dt = bli_blksz_get_max( dt, mc ); kc_max_dt = bli_blksz_get_max( dt, kc ); nc_max_dt = bli_blksz_get_max( dt, nc ); // Add max(mr,nr) to kc to make room for the nudging of kc at // runtime to be a multiple of mr or nr for triangular operations // trmm, trmm3, and trsm. kc_max_dt += max_mnr_dt; // // Compute scaling factors. // // Compute integer scaling factors (numerator and denominator) used // to account for situations when the packing register blocksizes are // larger than the regular register blocksizes. // In order to compute the scaling factors, we first have to determine // whether ( packmr / mr ) is greater than ( packnr / nr ). This is // needed ONLY because the amount of space allocated for a block of A // and a panel of B needs to be such that MR and NR can be swapped (ie: // A is packed with NR and B is packed with MR). This transformation is // needed for right-side trsm when inducing an algorithm that (a) has // favorable access patterns for column-stored C and (b) allows the // macro-kernel to reuse the existing left-side fused gemmtrsm micro- // kernels. We avoid integer division by cross-multiplying: // // ( packmr / mr ) >= ( packnr / nr ) // ( packmr / mr ) * nr >= packnr // packmr * nr >= packnr * mr // // So, if packmr * nr >= packnr * mr, then we will use packmr and mr as // our scaling factors. Otherwise, we'll use packnr and nr. packmr_dt = bli_blksz_get_max( dt, mr ); packnr_dt = bli_blksz_get_max( dt, nr ); if ( packmr_dt * nr_dt >= packnr_dt * mr_dt ) { scale_num_dt = packmr_dt; scale_den_dt = mr_dt; } else { scale_num_dt = packnr_dt; scale_den_dt = nr_dt; } // // Compute pool block dimensions. // pool_mc_dt = ( mc_max_dt * scale_num_dt ) / scale_den_dt; left_mc_dt = ( mc_max_dt * scale_num_dt ) % scale_den_dt; pool_nc_dt = ( nc_max_dt * scale_num_dt ) / scale_den_dt; left_nc_dt = ( nc_max_dt * scale_num_dt ) % scale_den_dt; pool_kc_dt = ( kc_max_dt ); if ( left_mc_dt > 0 ) pool_mc_dt += 1; if ( left_nc_dt > 0 ) pool_nc_dt += 1; // // Compute pool block sizes // // We add an extra micro-panel of space to the block sizes for A and B // just to be sure any pre-loading performed by the micro-kernel does // not cause a segmentation fault. max_packmnr_dt = bli_max( packmr_dt, packnr_dt ); *bs_a = ( pool_mc_dt + max_packmnr_dt ) * pool_kc_dt * size_dt; *bs_b = ( pool_nc_dt + max_packmnr_dt ) * pool_kc_dt * size_dt; *bs_c = ( pool_mc_dt ) * pool_nc_dt * size_dt; } blis-0.9.0/frame/base/bli_pba.h000066400000000000000000000106061422157504600162270ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2016, Hewlett Packard Enterprise Development LP Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_MEMBRK_H #define BLIS_MEMBRK_H // Packing block allocator (formerly memory broker) /* typedef struct pba_s { pool_t pools[3]; bli_pthread_mutex_t mutex; // These fields are used for general-purpose allocation. siz_t align_size; malloc_ft malloc_fp; free_ft free_fp; } pba_t; */ // pba init //BLIS_INLINE void bli_pba_init_mutex( pba_t* pba ) //{ // bli_pthread_mutex_init( &(pba->mutex), NULL ); //} //BLIS_INLINE void bli_pba_finalize_mutex( pba_t* pba ) //{ // bli_pthread_mutex_destroy( &(pba->mutex) ); //} // pba query BLIS_INLINE pool_t* bli_pba_pool( dim_t pool_index, pba_t* pba ) { return &(pba->pools[ pool_index ]); } BLIS_INLINE siz_t bli_pba_align_size( pba_t* pba ) { return pba->align_size; } BLIS_INLINE malloc_ft bli_pba_malloc_fp( pba_t* pba ) { return pba->malloc_fp; } BLIS_INLINE free_ft bli_pba_free_fp( pba_t* pba ) { return pba->free_fp; } // pba modification BLIS_INLINE void bli_pba_set_align_size( siz_t align_size, pba_t* pba ) { pba->align_size = align_size; } BLIS_INLINE void bli_pba_set_malloc_fp( malloc_ft malloc_fp, pba_t* pba ) { pba->malloc_fp = malloc_fp; } BLIS_INLINE void bli_pba_set_free_fp( free_ft free_fp, pba_t* pba ) { pba->free_fp = free_fp; } // pba action BLIS_INLINE void bli_pba_lock( pba_t* pba ) { bli_pthread_mutex_lock( &(pba->mutex) ); } BLIS_INLINE void bli_pba_unlock( pba_t* pba ) { bli_pthread_mutex_unlock( &(pba->mutex) ); } // ----------------------------------------------------------------------------- BLIS_EXPORT_BLIS pba_t* bli_pba_query( void ); void bli_pba_init ( cntx_t* cntx ); void bli_pba_finalize ( void ); void bli_pba_acquire_m ( rntm_t* rntm, siz_t req_size, packbuf_t buf_type, mem_t* mem ); void bli_pba_release ( rntm_t* rntm, mem_t* mem ); BLIS_INLINE void bli_pba_rntm_set_pba ( rntm_t* rntm ) { pba_t* pba = bli_pba_query(); bli_rntm_set_pba( pba, rntm ); } siz_t bli_pba_pool_size ( pba_t* pba, packbuf_t buf_type ); // ---------------------------------------------------------------------------- void bli_pba_init_pools ( cntx_t* cntx, pba_t* pba ); void bli_pba_finalize_pools ( pba_t* pba ); void bli_pba_compute_pool_block_sizes ( siz_t* bs_a, siz_t* bs_b, siz_t* bs_c, cntx_t* cntx ); void bli_pba_compute_pool_block_sizes_dt ( num_t dt, siz_t* bs_a, siz_t* bs_b, siz_t* bs_c, cntx_t* cntx ); #endif blis-0.9.0/frame/base/bli_pool.c000066400000000000000000000530411422157504600164310ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" //#define BLIS_ENABLE_MEM_TRACING void bli_pool_init ( siz_t num_blocks, siz_t block_ptrs_len, siz_t block_size, siz_t align_size, siz_t offset_size, malloc_ft malloc_fp, free_ft free_fp, pool_t* restrict pool ) { err_t r_val; // Make sure that block_ptrs_len is at least num_blocks. block_ptrs_len = bli_max( block_ptrs_len, num_blocks ); // Handle the case where block_ptrs_len is zero, we explicitly set it to 1, // to avoid any malloc() with zero size, whose behavior is not fixed, and // also to prevent from falling into any further memory corruption bug. block_ptrs_len = ( block_ptrs_len == 0 ) ? 1 : block_ptrs_len; #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_pool_init(): allocating block_ptrs (length %d): ", ( int )block_ptrs_len ); #endif // Allocate the block_ptrs array. // FGVZ: Do we want to call malloc_fp() for internal data structures as // well as pool blocks? If so, don't forget to s/bli_free_intl/free_fp/g. pblk_t* restrict block_ptrs = bli_malloc_intl( block_ptrs_len * sizeof( pblk_t ), &r_val ); // Allocate and initialize each entry in the block_ptrs array. for ( dim_t i = 0; i < num_blocks; ++i ) { #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_pool_init(): allocating block %d of size %d (align %d, offset %d).\n", ( int )i, ( int )block_size, ( int )align_size, ( int )offset_size ); fflush( stdout ); #endif bli_pool_alloc_block ( block_size, align_size, offset_size, malloc_fp, &(block_ptrs[i]) ); } // NOTE: The semantics of top_index approximate a stack, where a "full" // stack (no blocks checked out) is one where top_index == 0 and an empty // stack (all blocks checked out) one where top_index == num_blocks. // (Here, num_blocks tracks the number of blocks currently allocated as // part of the pool.) This "orientation" of the stack was chosen // intentionally, in contrast to one where top_index == -1 means the // stack is empty and top_index = num_blocks - 1 means the stack is // full. The chosen scheme allows one to conceptualize the stack as a // number line in which blocks are checked out from lowest to highest, // and additional blocks are added at the higher end. // Initialize the pool_t structure. bli_pool_set_block_ptrs( block_ptrs, pool ); bli_pool_set_block_ptrs_len( block_ptrs_len, pool ); bli_pool_set_top_index( 0, pool ); bli_pool_set_num_blocks( num_blocks, pool ); bli_pool_set_block_size( block_size, pool ); bli_pool_set_align_size( align_size, pool ); bli_pool_set_offset_size( offset_size, pool ); bli_pool_set_malloc_fp( malloc_fp, pool ); bli_pool_set_free_fp( free_fp, pool ); } void bli_pool_finalize ( pool_t* restrict pool ) { // NOTE: This implementation assumes that either: // - all blocks have been checked in by all threads, or // - some subset of blocks have been checked in and the caller // is bli_pool_reinit(). // Query the block_ptrs array. pblk_t* restrict block_ptrs = bli_pool_block_ptrs( pool ); // Query the total number of blocks currently allocated. const siz_t num_blocks = bli_pool_num_blocks( pool ); // NOTE: This sanity check has been disabled because bli_pool_reinit() // is currently implemented in terms of bli_pool_finalize() followed by // bli_pool_init(). If that _reinit() takes place when some blocks are // checked out, then we would expect top_index != 0, and therefore this // check is not universally appropriate. #if 0 // Query the top_index of the pool. const siz_t top_index = bli_pool_top_index( pool ); // Sanity check: The top_index should be zero. if ( top_index != 0 ) { printf( "bli_pool_finalize(): final top_index == %d (expected 0); block_size: %d.\n", ( int )top_index, ( int )bli_pool_block_size( pool ) ); printf( "bli_pool_finalize(): Implication: not all blocks were checked back in!\n" ); bli_abort(); } #endif // Query the free() function pointer for the pool. free_ft free_fp = bli_pool_free_fp( pool ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_pool_finalize(): freeing %d blocks of size %d (align %d, offset %d).\n", ( int )num_blocks, ( int )bli_pool_block_size( pool ), ( int )bli_pool_align_size( pool ), ( int )bli_pool_offset_size( pool ) ); fflush( stdout ); #endif // Query the offset size of the pool. const siz_t offset_size = bli_pool_offset_size( pool ); // Free the individual blocks currently in the pool. for ( dim_t i = 0; i < num_blocks; ++i ) { #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_pool_finalize(): block %d: ", ( int )i ); #endif bli_pool_free_block( offset_size, free_fp, &(block_ptrs[i]) ); } #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_pool_finalize(): freeing block_ptrs (length %d): ", ( int )( bli_pool_block_ptrs_len( pool ) ) ); #endif // Free the block_ptrs array. bli_free_intl( block_ptrs ); // This explicit clearing of the pool_t struct is not strictly // necessary and so it has been commented out. #if 0 // Clear the contents of the pool_t struct. bli_pool_set_block_ptrs( NULL, pool ); bli_pool_set_block_ptrs_len( 0, pool ); bli_pool_set_num_blocks( 0, pool ); bli_pool_set_top_index( 0, pool ); bli_pool_set_block_size( 0, pool ); bli_pool_set_align_size( 0, pool ); bli_pool_set_offset_size( 0, pool ); #endif } void bli_pool_reinit ( siz_t num_blocks_new, siz_t block_ptrs_len_new, siz_t block_size_new, siz_t align_size_new, siz_t offset_size_new, pool_t* restrict pool ) { // Preserve the pointers to malloc() and free() provided when the pool // was first initialized. malloc_ft malloc_fp = bli_pool_malloc_fp( pool ); free_ft free_fp = bli_pool_free_fp( pool ); // Finalize the pool as it is currently configured. If some blocks // are still checked out to threads, those blocks are not freed // here, and instead will be freed when the threads attempt to check // those blocks back into the pool. (This condition can be detected // since the block size is encoded into each pblk, which is copied // upon checkout.) bli_pool_finalize( pool ); // Reinitialize the pool with the new parameters, in particular, // the new block size. bli_pool_init ( num_blocks_new, block_ptrs_len_new, block_size_new, align_size_new, offset_size_new, malloc_fp, free_fp, pool ); } void bli_pool_checkout_block ( siz_t req_size, pblk_t* restrict block, pool_t* restrict pool ) { // If the requested block size is smaller than what the pool was // initialized with, reinitialize the pool to contain blocks of the // requested size. if ( bli_pool_block_size( pool ) < req_size ) { const siz_t num_blocks_new = bli_pool_num_blocks( pool ); const siz_t block_ptrs_len_new = bli_pool_block_ptrs_len( pool ); const siz_t align_size_new = bli_pool_align_size( pool ); const siz_t offset_size_new = bli_pool_offset_size( pool ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_pool_checkout_block(): old block size %d < req size %d; " "reiniting.\n", ( int )bli_pool_block_size( pool ), ( int )req_size ); fflush( stdout ); #endif bli_pool_reinit ( num_blocks_new, block_ptrs_len_new, req_size, align_size_new, offset_size_new, pool ); } // If the pool is exhausted, add a block. if ( bli_pool_is_exhausted( pool ) ) { #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_pool_checkout_block(): pool is exhausted (block size %d); " "growing by 1.\n", ( int )bli_pool_block_size( pool ) ); fflush( stdout ); #endif bli_pool_grow( 1, pool ); } // At this point, at least one block is guaranteed to be available. // Query the block_ptrs array. pblk_t* restrict block_ptrs = bli_pool_block_ptrs( pool ); // Query the top_index of the pool. const siz_t top_index = bli_pool_top_index( pool ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_pool_checkout_block(): checking out block %d of size %d " "(align %d).\n", ( int )top_index, ( int )bli_pool_block_size( pool ), ( int )bli_pool_align_size( pool ) ); fflush( stdout ); #endif // Copy the pblk_t at top_index to the caller's pblk_t struct. *block = block_ptrs[ top_index ]; // Notice that we don't actually need to clear the contents of // block_ptrs[top_index]. It will get overwritten eventually when // the block is checked back in. bli_pblk_clear( &block_ptrs[top_index] ); // Increment the pool's top_index. bli_pool_set_top_index( top_index + 1, pool ); } void bli_pool_checkin_block ( pblk_t* restrict block, pool_t* restrict pool ) { // If the pblk_t being checked in was allocated with a different block // size than is currently in use in the pool, we simply free it and // return. These "orphaned" blocks are no longer of use because the pool // has since been reinitialized to a different (larger) block size. if ( bli_pblk_block_size( block ) != bli_pool_block_size( pool ) ) { // Query the offset size of the pool. const siz_t offset_size = bli_pool_offset_size( pool ); // Query the free() function pointer for the pool. free_ft free_fp = bli_pool_free_fp( pool ); bli_pool_free_block( offset_size, free_fp, block ); return; } // Query the block_ptrs array. pblk_t* restrict block_ptrs = bli_pool_block_ptrs( pool ); // Query the top_index of the pool. const siz_t top_index = bli_pool_top_index( pool ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_pool_checkin_block(): checking in block %d of size %d " "(align %d, offset %d).\n", ( int )top_index - 1, ( int )bli_pool_block_size( pool ), ( int )bli_pool_align_size( pool ), ( int )bli_pool_offset_size( pool ) ); fflush( stdout ); #endif // Copy the caller's pblk_t struct to the block at top_index - 1. block_ptrs[ top_index - 1 ] = *block; // Decrement the pool's top_index. bli_pool_set_top_index( top_index - 1, pool ); } void bli_pool_grow ( siz_t num_blocks_add, pool_t* restrict pool ) { err_t r_val; // If the requested increase is zero, return early. if ( num_blocks_add == 0 ) return; // Query the allocated length of the block_ptrs array and also the // total number of blocks currently allocated. const siz_t block_ptrs_len_cur = bli_pool_block_ptrs_len( pool ); const siz_t num_blocks_cur = bli_pool_num_blocks( pool ); // Compute the total number of allocated blocks that will exist // after we grow the pool. const siz_t num_blocks_new = num_blocks_cur + num_blocks_add; // If adding num_blocks_add new blocks will exceed the current capacity // of the block_ptrs array, we need to first put in place a new (larger) // array. if ( block_ptrs_len_cur < num_blocks_new ) { // To prevent this from happening often, we double the current // length of the block_ptrs array. // Sanity: make sure that the block_ptrs_len_new will be at least // num_blocks_new, in case doubling the block_ptrs_len_cur is not enough. // Example 1: // - block_ptrs_len_cur == num_blocks_cur == 0 and num_blocks_add = 1 // - So doubling: 2 * block_ptrs_len_cur = 0, whereas 1 is expected // Example 2: // - block_ptrs_len_cur == num_blocks_cur == 10 and num_blocks_add = 30 // - So doubling: 2 * block_ptrs_len_cur = 20, whereas 40 is expected const siz_t block_ptrs_len_new = bli_max( (2 * block_ptrs_len_cur), num_blocks_new ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_pool_grow(): growing block_ptrs_len (%d -> %d): ", ( int )block_ptrs_len_cur, ( int )block_ptrs_len_new ); #endif // Query the current block_ptrs array. pblk_t* restrict block_ptrs_cur = bli_pool_block_ptrs( pool ); // Allocate a new block_ptrs array. // FGVZ: Do we want to call malloc_fp() for internal data structures as // well as pool blocks? If so, don't forget to s/bli_free_intl/free_fp/g. pblk_t* restrict block_ptrs_new = bli_malloc_intl( block_ptrs_len_new * sizeof( pblk_t ), &r_val ); // Query the top_index of the pool. const siz_t top_index = bli_pool_top_index( pool ); // Copy the contents of the old block_ptrs array to the new/resized // array. Notice that we can begin with top_index since all entries // from 0 to top_index-1 have been (and are currently) checked out // to threads. for ( dim_t i = top_index; i < num_blocks_cur; ++i ) { block_ptrs_new[i] = block_ptrs_cur[i]; } #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_pool_grow(): freeing prev block_ptrs: " ); #endif // Free the old block_ptrs array. bli_free_intl( block_ptrs_cur ); // Update the pool_t struct with the new block_ptrs array and // record its allocated length. bli_pool_set_block_ptrs( block_ptrs_new, pool ); bli_pool_set_block_ptrs_len( block_ptrs_len_new, pool ); } // At this point, we are guaranteed to have enough unused elements // in the block_ptrs array to accommodate an additional num_blocks_add // blocks. // Query the current block_ptrs array (which was mabye just resized). pblk_t* restrict block_ptrs = bli_pool_block_ptrs( pool ); // Query the block size and alignment size of the pool. const siz_t block_size = bli_pool_block_size( pool ); const siz_t align_size = bli_pool_align_size( pool ); const siz_t offset_size = bli_pool_offset_size( pool ); // Query the malloc() function pointer for the pool. malloc_ft malloc_fp = bli_pool_malloc_fp( pool ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_pool_grow(): growing pool from (%d -> %d).\n", ( int )num_blocks_cur, ( int )num_blocks_new ); fflush( stdout ); #endif // Allocate the requested additional blocks in the resized array. for ( dim_t i = num_blocks_cur; i < num_blocks_new; ++i ) { bli_pool_alloc_block ( block_size, align_size, offset_size, malloc_fp, &(block_ptrs[i]) ); } // Update the pool_t struct with the new number of allocated blocks. // Notice that top_index remains unchanged, as do the block_size and // align_size fields. bli_pool_set_num_blocks( num_blocks_new, pool ); } void bli_pool_shrink ( siz_t num_blocks_sub, pool_t* restrict pool ) { // If the requested decrease is zero, return early. if ( num_blocks_sub == 0 ) return; // Query the total number of blocks currently allocated. const siz_t num_blocks = bli_pool_num_blocks( pool ); // Query the top_index of the pool. const siz_t top_index = bli_pool_top_index( pool ); // Compute the number of blocks available to be checked out // (and thus available for removal). const siz_t num_blocks_avail = num_blocks - top_index; // If the requested decrease is more than the number of available // blocks in the pool, only remove the number of blocks actually // available. num_blocks_sub = bli_min( num_blocks_sub, num_blocks_avail ); // Query the block_ptrs array. pblk_t* restrict block_ptrs = bli_pool_block_ptrs( pool ); // Compute the new total number of blocks. const siz_t num_blocks_new = num_blocks - num_blocks_sub; // Query the offset size of the pool. const siz_t offset_size = bli_pool_offset_size( pool ); // Query the free() function pointer for the pool. free_ft free_fp = bli_pool_free_fp( pool ); // Free the individual blocks. for ( dim_t i = num_blocks_new; i < num_blocks; ++i ) { bli_pool_free_block( offset_size, free_fp, &(block_ptrs[i]) ); } // Update the pool_t struct. bli_pool_set_num_blocks( num_blocks_new, pool ); // Note that after shrinking the pool, num_blocks < block_ptrs_len. // This means the pool can grow again by num_blocks_sub before // a re-allocation of block_ptrs is triggered. } void bli_pool_alloc_block ( siz_t block_size, siz_t align_size, siz_t offset_size, malloc_ft malloc_fp, pblk_t* restrict block ) { err_t r_val; #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_pool_alloc_block(): calling fmalloc_align(): size %d (align %d, offset %d)\n", ( int )block_size, ( int )align_size, ( int )offset_size ); fflush( stdout ); #endif // Allocate the block via the bli_fmalloc_align() wrapper, which performs // alignment logic and opaquely saves the original pointer so that it can // be recovered when it's time to free the block. Note that we have to // add offset_size to the number of bytes requested since we will skip // that many bytes at the beginning of the allocated memory. void* restrict buf = bli_fmalloc_align( malloc_fp, block_size + offset_size, align_size, &r_val ); #if 0 // NOTE: This code is disabled because it is not needed, since // bli_fmalloc_align() is guaranteed to return an aligned address. // Advance the pointer to achieve the necessary alignment, if it is not // already aligned. if ( bli_is_unaligned_to( ( siz_t )buf_sys, ( siz_t )align_size ) ) { // C99's stdint.h guarantees that a void* can be safely cast to a // uintptr_t and then back to a void*, hence the casting of buf_sys // and align_size to uintptr_t. buf_align is initially cast to char* // to allow pointer arithmetic in units of bytes, and then advanced // to the next nearest alignment boundary, and finally cast back to // void* before being stored. Notice that the arithmetic works even // if the alignment value is not a power of two. buf_align = ( void* )( ( char* )buf_align + ( ( uintptr_t )align_size - ( uintptr_t )buf_sys % ( uintptr_t )align_size ) ); } #endif // Advance the pointer by offset_size bytes. buf = ( void* )( ( char* )buf + offset_size ); // Save the results in the pblk_t structure. bli_pblk_set_buf( buf, block ); bli_pblk_set_block_size( block_size, block ); } void bli_pool_free_block ( siz_t offset_size, free_ft free_fp, pblk_t* restrict block ) { #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_pool_free_block(): calling ffree_align(): size %d.\n", ( int )bli_pblk_block_size( block ) ); fflush( stdout ); #endif // Extract the pblk_t buffer, which is the aligned address returned from // bli_fmalloc_align() when the block was allocated. void* restrict buf = bli_pblk_buf( block ); // Undo the pointer advancement by offset_size bytes performed previously // by bli_pool_alloc_block(). buf = ( void* )( ( char* )buf - offset_size ); // Free the block via the bli_ffree_align() wrapper, which recovers the // original pointer that was returned by the pool's malloc() function when // the block was allocated. bli_ffree_align( free_fp, buf ); } void bli_pool_print ( pool_t* restrict pool ) { pblk_t* block_ptrs = bli_pool_block_ptrs( pool ); siz_t block_ptrs_len = bli_pool_block_ptrs_len( pool ); siz_t top_index = bli_pool_top_index( pool ); siz_t num_blocks = bli_pool_num_blocks( pool ); siz_t block_size = bli_pool_block_size( pool ); siz_t align_size = bli_pool_align_size( pool ); siz_t offset_size = bli_pool_offset_size( pool ); printf( "pool struct ---------------\n" ); printf( " block_ptrs: %p\n", block_ptrs ); printf( " block_ptrs_len: %d\n", ( int )block_ptrs_len ); printf( " top_index: %d\n", ( int )top_index ); printf( " num_blocks: %d\n", ( int )num_blocks ); printf( " block_size: %d\n", ( int )block_size ); printf( " align_size: %d\n", ( int )align_size ); printf( " offset_size: %d\n", ( int )offset_size ); printf( " pblks sys align\n" ); for ( dim_t i = 0; i < num_blocks; ++i ) { printf( " %d: %p\n", ( int )i, bli_pblk_buf( &block_ptrs[i] ) ); } } void bli_pblk_print ( pblk_t* restrict pblk ) { void* buf = bli_pblk_buf( pblk ); printf( "pblk struct ---------------\n" ); printf( " block address (aligned): %p\n", buf ); } blis-0.9.0/frame/base/bli_pool.h000066400000000000000000000151061422157504600164360ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_POOL_H #define BLIS_POOL_H // -- Pool block type -- /* typedef struct { void* buf; siz_t block_size; } pblk_t; */ // -- Pool type -- /* typedef struct { void* block_ptrs; siz_t block_ptrs_len; siz_t top_index; siz_t num_blocks; siz_t block_size; siz_t align_size; malloc_ft malloc_fp; free_ft free_fp; } pool_t; */ // Pool block query BLIS_INLINE void* bli_pblk_buf( pblk_t* pblk ) { return pblk->buf; } BLIS_INLINE siz_t bli_pblk_block_size( pblk_t* pblk ) { return pblk->block_size; } // Pool block modification BLIS_INLINE void bli_pblk_set_buf( void* buf, pblk_t* pblk ) { pblk->buf = buf; } BLIS_INLINE void bli_pblk_set_block_size( siz_t block_size, pblk_t* pblk ) { pblk->block_size = block_size; } // // -- pool block initialization ------------------------------------------------ // // NOTE: This initializer macro must be updated whenever fields are added or // removed from the pblk_t type definition. An alternative to the initializer is // calling bli_pblk_clear() at runtime. #define BLIS_PBLK_INITIALIZER \ { \ .buf = NULL, \ .block_size = 0, \ } \ BLIS_INLINE void bli_pblk_clear( pblk_t* pblk ) { bli_pblk_set_buf( NULL, pblk ); bli_pblk_set_block_size( 0, pblk ); } // Pool entry query BLIS_INLINE void* bli_pool_block_ptrs( pool_t* pool ) { return pool->block_ptrs; } BLIS_INLINE siz_t bli_pool_block_ptrs_len( pool_t* pool ) { return pool->block_ptrs_len; } BLIS_INLINE siz_t bli_pool_num_blocks( pool_t* pool ) { return pool->num_blocks; } BLIS_INLINE siz_t bli_pool_block_size( pool_t* pool ) { return pool->block_size; } BLIS_INLINE siz_t bli_pool_align_size( pool_t* pool ) { return pool->align_size; } BLIS_INLINE siz_t bli_pool_offset_size( pool_t* pool ) { return pool->offset_size; } BLIS_INLINE malloc_ft bli_pool_malloc_fp( pool_t* pool ) { return pool->malloc_fp; } BLIS_INLINE free_ft bli_pool_free_fp( pool_t* pool ) { return pool->free_fp; } BLIS_INLINE siz_t bli_pool_top_index( pool_t* pool ) { return pool->top_index; } BLIS_INLINE bool bli_pool_is_exhausted( pool_t* pool ) { return ( bool ) ( bli_pool_top_index( pool ) == bli_pool_num_blocks( pool ) ); } // Pool entry modification BLIS_INLINE void bli_pool_set_block_ptrs( void* block_ptrs, pool_t* pool ) \ { pool->block_ptrs = block_ptrs; } BLIS_INLINE void bli_pool_set_block_ptrs_len( siz_t block_ptrs_len, pool_t* pool ) \ { pool->block_ptrs_len = block_ptrs_len; } BLIS_INLINE void bli_pool_set_num_blocks( siz_t num_blocks, pool_t* pool ) \ { pool->num_blocks = num_blocks; } BLIS_INLINE void bli_pool_set_block_size( siz_t block_size, pool_t* pool ) \ { pool->block_size = block_size; } BLIS_INLINE void bli_pool_set_align_size( siz_t align_size, pool_t* pool ) \ { pool->align_size = align_size; } BLIS_INLINE void bli_pool_set_offset_size( siz_t offset_size, pool_t* pool ) \ { pool->offset_size = offset_size; } BLIS_INLINE void bli_pool_set_malloc_fp( malloc_ft malloc_fp, pool_t* pool ) \ { pool->malloc_fp = malloc_fp; } BLIS_INLINE void bli_pool_set_free_fp( free_ft free_fp, pool_t* pool ) \ { pool->free_fp = free_fp; } BLIS_INLINE void bli_pool_set_top_index( siz_t top_index, pool_t* pool ) \ { pool->top_index = top_index; } // ----------------------------------------------------------------------------- void bli_pool_init ( siz_t num_blocks, siz_t block_ptrs_len, siz_t block_size, siz_t align_size, siz_t offset_size, malloc_ft malloc_fp, free_ft free_fp, pool_t* restrict pool ); void bli_pool_finalize ( pool_t* restrict pool ); void bli_pool_reinit ( siz_t num_blocks_new, siz_t block_ptrs_len_new, siz_t block_size_new, siz_t align_size_new, siz_t offset_size_new, pool_t* restrict pool ); void bli_pool_checkout_block ( siz_t req_size, pblk_t* restrict block, pool_t* restrict pool ); void bli_pool_checkin_block ( pblk_t* restrict block, pool_t* restrict pool ); void bli_pool_grow ( siz_t num_blocks_add, pool_t* restrict pool ); void bli_pool_shrink ( siz_t num_blocks_sub, pool_t* restrict pool ); void bli_pool_alloc_block ( siz_t block_size, siz_t align_size, siz_t offset_size, malloc_ft malloc_fp, pblk_t* restrict block ); void bli_pool_free_block ( siz_t offset_size, free_ft free_fp, pblk_t* restrict block ); void bli_pool_print ( pool_t* restrict pool ); void bli_pblk_print ( pblk_t* restrict pblk ); #endif blis-0.9.0/frame/base/bli_prune.c000066400000000000000000000131041422157504600166050ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_prune_unref_mparts( obj_t* p, mdim_t mdim_p, obj_t* s, mdim_t mdim_s ) { // If the primary object is general, it has no structure, and // therefore, no unreferenced parts. if ( bli_obj_is_general( p ) ) return; // If the primary object is BLIS_ZEROS, set the dimensions so that the // matrix is empty. This is not strictly needed but rather a minor // optimization, as it would prevent threads that would otherwise get // subproblems on BLIS_ZEROS operands from calling the macro-kernel, // because bli_thread_range*() would return empty ranges, which would // cause the variant's for loop from executing any iterations. // NOTE: this should only ever execute if the primary object is // triangular because that is the only structure type with subpartitions // that can be marked as BLIS_ZEROS. if ( bli_obj_is_triangular( p ) && bli_obj_is_zeros( p ) ) { bli_obj_set_dim( mdim_p, 0, p ); bli_obj_set_dim( mdim_s, 0, s ); return; } // If the primary object is hermitian, symmetric, or triangular, we // assume that the unstored region will be unreferenced (otherwise, // the caller should not be invoking this function on that object). //if ( bli_obj_is_herm_or_symm( p ) || // bli_obj_is_triangular( p ) ) { doff_t diagoff_p = bli_obj_diag_offset( p ); dim_t m = bli_obj_length( p ); dim_t n = bli_obj_width( p ); uplo_t uplo = bli_obj_uplo( p ); dim_t off_inc = 0; dim_t q; // Support implicit transposition on p and s. if ( bli_obj_has_trans( p ) ) { bli_reflect_about_diag( &diagoff_p, &uplo, &m, &n ); bli_toggle_dim( &mdim_p ); } if ( bli_obj_has_trans( s ) ) { bli_toggle_dim( &mdim_s ); } // Prune away any zero region of the matrix depending on the // dimension of the primary object being partitioned and the // triangle in which it is stored. if ( bli_obj_is_lower( p ) ) { if ( bli_is_m_dim( mdim_p ) ) { bli_prune_unstored_region_top_l( &diagoff_p, &m, &n, &off_inc ); } else // if ( bli_is_n_dim( mdim_p ) ) { bli_prune_unstored_region_right_l( &diagoff_p, &m, &n, &off_inc ); } } else if ( bli_obj_is_upper( p ) ) { if ( bli_is_m_dim( mdim_p ) ) { bli_prune_unstored_region_bottom_u( &diagoff_p, &m, &n, &off_inc ); } else // if ( bli_is_n_dim( mdim_p ) ) { bli_prune_unstored_region_left_u( &diagoff_p, &m, &n, &off_inc ); } } else if ( bli_obj_is_dense( p ) ) { // Hermitian, symmetric, and triangular matrices are almost // never dense, but if one were found to be dense, it would // have no unreferenced regions to prune. return; } else // if ( bli_obj_is_zeros( p ) ) { // Sanity check. Hermitian/symmetric matrices should never have // zero subpartitions. bli_check_error_code( BLIS_NOT_YET_IMPLEMENTED ); } // Select the (potentially modified) dimension along which we are // partitioning. if ( bli_is_m_dim( mdim_p ) ) q = m; else /* if ( bli_is_n_dim( mdim_p ) ) */ q = n; // Update the affected objects in case anything changed. Notice that // it is okay to update the dimension and diagonal offset fields of // packed primary objects, as long as we do so in tandem with the // secondary object to maintain conformality. This just means that // the "ignore-able" zero region is skipped over here, rather than // within the macro-kernel. bli_obj_set_diag_offset( diagoff_p, p ); bli_obj_set_dim( mdim_p, q, p ); bli_obj_set_dim( mdim_s, q, s ); // Only update the affected offset fields if the object in question // is NOT a packed object. Otherwise, bli_obj_buffer_at_off() will // compute the wrong address within the macro-kernel object wrapper. if ( !bli_obj_is_packed( p ) ) { bli_obj_inc_off( mdim_p, off_inc, p ); } if ( !bli_obj_is_packed( s ) ) { bli_obj_inc_off( mdim_s, off_inc, s ); } } } blis-0.9.0/frame/base/bli_prune.h000066400000000000000000000033671422157504600166240ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void bli_prune_unref_mparts( obj_t* p, mdim_t mdim_p, obj_t* s, mdim_t mdim_s ); blis-0.9.0/frame/base/bli_query.c000066400000000000000000000134501422157504600166250ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" bool bli_obj_equals( obj_t* a, obj_t* b ) { #if 0 bool r_val = FALSE; num_t dt_a; num_t dt_b; num_t dt; // The function is not yet implemented for vectors and matrices. if ( !bli_obj_is_1x1( a ) || !bli_obj_is_1x1( b ) ) bli_check_error_code( BLIS_NOT_YET_IMPLEMENTED ); dt_a = bli_obj_dt( a ); dt_b = bli_obj_dt( b ); // If B is BLIS_CONSTANT, then we need to test equality based on the // datatype of A--this works even if A is also BLIS_CONSTANT. If B // is a regular non-constant type, then we should use its datatype // to test equality. if ( dt_b == BLIS_CONSTANT ) dt = dt_a; else dt = dt_b; // Now test equality based on the chosen datatype. if ( dt == BLIS_CONSTANT ) { dcomplex* ap_z = bli_obj_buffer_for_const( BLIS_DCOMPLEX, a ); dcomplex* bp_z = bli_obj_buffer_for_const( BLIS_DCOMPLEX, b ); // We only test equality for one datatype (double complex) since // we expect either all fields within the constant to be equal or // none to be equal. Therefore, we can just test one of them. r_val = bli_zeqa( ap_z, bp_z ); } else { void* buf_a = bli_obj_buffer_for_1x1( dt, a ); void* buf_b = bli_obj_buffer_for_1x1( dt, b ); if ( dt == BLIS_FLOAT ) r_val = bli_seqa( buf_a, buf_b ); else if ( dt == BLIS_DOUBLE ) r_val = bli_deqa( buf_a, buf_b ); else if ( dt == BLIS_SCOMPLEX ) r_val = bli_ceqa( buf_a, buf_b ); else if ( dt == BLIS_DCOMPLEX ) r_val = bli_zeqa( buf_a, buf_b ); else if ( dt == BLIS_INT ) r_val = bli_ieqa( buf_a, buf_b ); } return r_val; #else bool r_val; if ( bli_obj_is_1x1( a ) && bli_obj_is_1x1( b ) ) bli_eqsc( a, b, &r_val ); else if ( bli_obj_is_vector( a ) && bli_obj_is_vector( b ) ) bli_eqv( a, b, &r_val ); else bli_eqm( a, b, &r_val ); return r_val; #endif } bool bli_obj_imag_equals( obj_t* a, obj_t* b ) { #if 0 bool r_val = FALSE; num_t dt_a; num_t dt_b; dt_a = bli_obj_dt( a ); dt_b = bli_obj_dt( b ); // The function is not yet implemented for vectors and matrices. if ( !bli_obj_is_1x1( a ) || !bli_obj_is_1x1( b ) || bli_is_constant( dt_a ) || bli_is_complex( dt_b ) ) bli_check_error_code( BLIS_NOT_YET_IMPLEMENTED ); // Handle the special (trivial) case where a is real, in which // case all we have to do is test whether b is zero. if ( bli_is_real( dt_a ) ) { r_val = bli_obj_equals( &BLIS_ZERO, b ); } else // if ( bli_is_complex( dt_a ) ) { num_t dt_a_real = bli_dt_proj_to_real( dt_a ); // Now we compare the imaginary part of a to b. Notice that since // we are using bli_obj_buffer_for_1x1() to acquire the buffer for // b, this works regardless of whether b is BLIS_CONSTANT. if ( dt_a == BLIS_SCOMPLEX ) { scomplex* ap_c = bli_obj_buffer_at_off( a ); float* bp_c = bli_obj_buffer_for_1x1( dt_a_real, b ); r_val = bli_seq( bli_cimag( *ap_c ), *bp_c ); } else if ( dt_a == BLIS_DCOMPLEX ) { dcomplex* ap_z = bli_obj_buffer_at_off( a ); double* bp_z = bli_obj_buffer_for_1x1( dt_a_real, b ); r_val = bli_deq( bli_zimag( *ap_z ), *bp_z ); } } #endif bool r_val = FALSE; // The function is not yet implemented for vectors and matrices. if ( !bli_obj_is_1x1( a ) || !bli_obj_is_1x1( b ) || bli_obj_is_complex( b ) ) bli_check_error_code( BLIS_NOT_YET_IMPLEMENTED ); double a_r, a_i; double b_r, b_i; // Get the real and imaginary parts of a and cast them to local doubles. bli_getsc( a, &a_r, &a_i ); // Get the value of b and cast to a local double. (Note: the imaginary part // of b is ignored since we know b is real.) bli_getsc( b, &b_r, &b_i ); // Compare the imaginary part of a to the real part of b. if ( a_i == b_r ) r_val = TRUE; return r_val; } bool bli_obj_imag_is_zero( obj_t* a ) { bool r_val = TRUE; // The function is not yet implemented for vectors and matrices. if ( !bli_obj_is_1x1( a ) ) bli_check_error_code( BLIS_NOT_YET_IMPLEMENTED ); if ( bli_obj_is_complex( a ) ) { double a_r, a_i; // Get the real and imaginary parts and cast them to local doubles. bli_getsc( a, &a_r, &a_i ); // Compare the imaginary part of a to double-precision zero. if ( !bli_deq0( a_i ) ) r_val = FALSE; } return r_val; } blis-0.9.0/frame/base/bli_query.h000066400000000000000000000035001422157504600166250ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ BLIS_EXPORT_BLIS bool bli_obj_equals( obj_t* a, obj_t* b ); BLIS_EXPORT_BLIS bool bli_obj_imag_equals( obj_t* a, obj_t* b ); BLIS_EXPORT_BLIS bool bli_obj_imag_is_zero( obj_t* a ); blis-0.9.0/frame/base/bli_rntm.c000066400000000000000000000346001422157504600164400ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // The global rntm_t structure, which holds the global thread settings // along with a few other key parameters. rntm_t global_rntm; // A mutex to allow synchronous access to global_rntm. bli_pthread_mutex_t global_rntm_mutex = BLIS_PTHREAD_MUTEX_INITIALIZER; // ---------------------------------------------------------------------------- void bli_rntm_init_from_global( rntm_t* rntm ) { // We must ensure that global_rntm has been initialized. bli_init_once(); // Acquire the mutex protecting global_rntm. bli_pthread_mutex_lock( &global_rntm_mutex ); *rntm = global_rntm; // Release the mutex protecting global_rntm. bli_pthread_mutex_unlock( &global_rntm_mutex ); } // ----------------------------------------------------------------------------- void bli_rntm_set_ways_for_op ( opid_t l3_op, side_t side, dim_t m, dim_t n, dim_t k, rntm_t* rntm ) { // Set the number of ways for each loop, if needed, depending on what // kind of information is already stored in the rntm_t object. bli_rntm_set_ways_from_rntm( m, n, k, rntm ); #if 0 printf( "bli_rntm_set_ways_for_op()\n" ); bli_rntm_print( rntm ); #endif // Now modify the number of ways, if necessary, based on the operation. if ( l3_op == BLIS_TRMM || l3_op == BLIS_TRSM ) { dim_t jc = bli_rntm_jc_ways( rntm ); dim_t pc = bli_rntm_pc_ways( rntm ); dim_t ic = bli_rntm_ic_ways( rntm ); dim_t jr = bli_rntm_jr_ways( rntm ); dim_t ir = bli_rntm_ir_ways( rntm ); // Notice that, if we do need to update the ways, we don't need to // update the num_threads field since we only reshuffle where the // parallelism is extracted, not the total amount of parallelism. if ( l3_op == BLIS_TRMM ) { // We reconfigure the parallelism extracted from trmm_r due to a // dependency in the jc loop. (NOTE: This dependency does not exist // for trmm3.) if ( bli_is_left( side ) ) { bli_rntm_set_ways_only ( jc, pc, ic, jr, ir, rntm ); } else // if ( bli_is_right( side ) ) { bli_rntm_set_ways_only ( 1, pc, ic, jr * jc, ir, rntm ); } } else if ( l3_op == BLIS_TRSM ) { //printf( "bli_rntm_set_ways_for_op(): jc%d ic%d jr%d\n", (int)jc, (int)ic, (int)jr ); if ( bli_is_left( side ) ) { bli_rntm_set_ways_only ( jc, 1, ic * pc, jr * ir, 1, rntm ); } else // if ( bli_is_right( side ) ) { bli_rntm_set_ways_only ( 1, 1, ic * pc * jc * ir * jr, 1, 1, rntm ); } } } } void bli_rntm_set_ways_from_rntm ( dim_t m, dim_t n, dim_t k, rntm_t* rntm ) { dim_t nt = bli_rntm_num_threads( rntm ); dim_t jc = bli_rntm_jc_ways( rntm ); dim_t pc = bli_rntm_pc_ways( rntm ); dim_t ic = bli_rntm_ic_ways( rntm ); dim_t jr = bli_rntm_jr_ways( rntm ); dim_t ir = bli_rntm_ir_ways( rntm ); bool auto_factor = FALSE; #ifdef BLIS_ENABLE_MULTITHREADING bool nt_set = FALSE; bool ways_set = FALSE; // If the rntm was fed in as a copy of the global runtime via // bli_rntm_init_from_global(), we know that either: // - the num_threads field is -1 and all of the ways are -1; // - the num_threads field is -1 and all of the ways are set; // - the num_threads field is set and all of the ways are -1. // However, we can't be sure that a user-provided rntm_t isn't // initialized uncleanly. So here we have to enforce some rules // to get the rntm_t into a predictable state. // First, we establish whether or not the number of threads is set. if ( nt > 0 ) nt_set = TRUE; // Take this opportunity to set the auto_factor field. if ( nt_set ) auto_factor = TRUE; // Next, we establish whether or not any of the ways of parallelism // for each loop were set. If any of the ways are set (positive), we // then we assume the user wanted to use those positive values and // default the non-positive values to 1. if ( jc > 0 || pc > 0 || ic > 0 || jr > 0 || ir > 0 ) { ways_set = TRUE; if ( jc < 1 ) jc = 1; if ( pc < 1 ) pc = 1; if ( ic < 1 ) ic = 1; if ( jr < 1 ) jr = 1; if ( ir < 1 ) ir = 1; } // Now we use the values of nt_set and ways_set to determine how to // interpret the original values we found in the rntm_t object. if ( ways_set == TRUE ) { // If the ways were set, then we use the values that were given // and interpreted above (we set any non-positive value to 1). // The only thing left to do is calculate the correct number of // threads. nt = jc * pc * ic * jr * ir; } else if ( ways_set == FALSE && nt_set == TRUE ) { // If the ways were not set but the number of thread was set, then // we attempt to automatically generate a thread factorization that // will work given the problem size. #ifdef BLIS_DISABLE_AUTO_PRIME_NUM_THREADS // If use of prime numbers is disallowed for automatic thread // factorizations, we first check if the number of threads requested // is prime. If it is prime, and it exceeds a minimum threshold, then // we reduce the number of threads by one so that the number is not // prime. This will allow for automatic thread factorizations to span // two dimensions (loops), which tends to be more efficient. if ( bli_is_prime( nt ) && BLIS_NT_MAX_PRIME < nt ) nt -= 1; #endif pc = 1; //printf( "m n = %d %d BLIS_THREAD_RATIO_M _N = %d %d\n", (int)m, (int)n, (int)BLIS_THREAD_RATIO_M, (int)BLIS_THREAD_RATIO_N ); bli_thread_partition_2x2( nt, m*BLIS_THREAD_RATIO_M, n*BLIS_THREAD_RATIO_N, &ic, &jc ); //printf( "jc ic = %d %d\n", (int)jc, (int)ic ); for ( ir = BLIS_THREAD_MAX_IR ; ir > 1 ; ir-- ) { if ( ic % ir == 0 ) { ic /= ir; break; } } for ( jr = BLIS_THREAD_MAX_JR ; jr > 1 ; jr-- ) { if ( jc % jr == 0 ) { jc /= jr; break; } } } else // if ( ways_set == FALSE && nt_set == FALSE ) { // If neither the ways nor the number of threads were set, then // the rntm was not meaningfully changed since initialization, // and thus we'll default to single-threaded execution. nt = 1; jc = pc = ic = jr = ir = 1; } #else // When multithreading is disabled, always set the rntm_t ways // values to 1. nt = 1; jc = pc = ic = jr = ir = 1; #endif // Save the results back in the runtime object. bli_rntm_set_auto_factor_only( auto_factor, rntm ); bli_rntm_set_num_threads_only( nt, rntm ); bli_rntm_set_ways_only( jc, pc, ic, jr, ir, rntm ); } void bli_rntm_set_ways_from_rntm_sup ( dim_t m, dim_t n, dim_t k, rntm_t* rntm ) { dim_t nt = bli_rntm_num_threads( rntm ); dim_t jc = bli_rntm_jc_ways( rntm ); dim_t pc = bli_rntm_pc_ways( rntm ); dim_t ic = bli_rntm_ic_ways( rntm ); dim_t jr = bli_rntm_jr_ways( rntm ); dim_t ir = bli_rntm_ir_ways( rntm ); bool auto_factor = FALSE; #ifdef BLIS_ENABLE_MULTITHREADING bool nt_set = FALSE; bool ways_set = FALSE; // If the rntm was fed in as a copy of the global runtime via // bli_rntm_init_from_global(), we know that either: // - the num_threads field is -1 and all of the ways are -1; // - the num_threads field is -1 and all of the ways are set; // - the num_threads field is set and all of the ways are -1. // However, we can't be sure that a user-provided rntm_t isn't // initialized uncleanly. So here we have to enforce some rules // to get the rntm_t into a predictable state. // First, we establish whether or not the number of threads is set. if ( nt > 0 ) nt_set = TRUE; // Take this opportunity to set the auto_factor field. if ( nt_set ) auto_factor = TRUE; // Next, we establish whether or not any of the ways of parallelism // for each loop were set. If any of the ways are set (positive), we // then we assume the user wanted to use those positive values and // default the non-positive values to 1. if ( jc > 0 || pc > 0 || ic > 0 || jr > 0 || ir > 0 ) { ways_set = TRUE; if ( jc < 1 ) jc = 1; if ( pc < 1 ) pc = 1; if ( ic < 1 ) ic = 1; if ( jr < 1 ) jr = 1; if ( ir < 1 ) ir = 1; } // Now we use the values of nt_set and ways_set to determine how to // interpret the original values we found in the rntm_t object. if ( ways_set == TRUE ) { // If the ways were set, then we use the values that were given // and interpreted above (we set any non-positive value to 1). // The only thing left to do is calculate the correct number of // threads. nt = jc * pc * ic * jr * ir; } else if ( ways_set == FALSE && nt_set == TRUE ) { // If the ways were not set but the number of thread was set, then // we attempt to automatically generate a thread factorization that // will work given the problem size. #ifdef BLIS_DISABLE_AUTO_PRIME_NUM_THREADS // If use of prime numbers is disallowed for automatic thread // factorizations, we first check if the number of threads requested // is prime. If it is prime, and it exceeds a minimum threshold, then // we reduce the number of threads by one so that the number is not // prime. This will allow for automatic thread factorizations to span // two dimensions (loops), which tends to be more efficient. if ( bli_is_prime( nt ) && BLIS_NT_MAX_PRIME < nt ) nt -= 1; #endif pc = 1; //bli_thread_partition_2x2( nt, m*BLIS_THREAD_SUP_RATIO_M, // n*BLIS_THREAD_SUP_RATIO_N, &ic, &jc ); bli_thread_partition_2x2( nt, m, n, &ic, &jc ); //printf( "bli_rntm_set_ways_from_rntm_sup(): jc = %d ic = %d\n", (int)jc, (int)ic ); #if 0 for ( ir = BLIS_THREAD_SUP_MAX_IR ; ir > 1 ; ir-- ) { if ( ic % ir == 0 ) { ic /= ir; break; } } for ( jr = BLIS_THREAD_SUP_MAX_JR ; jr > 1 ; jr-- ) { if ( jc % jr == 0 ) { jc /= jr; break; } } #else ir = 1; jr = 1; #endif } else // if ( ways_set == FALSE && nt_set == FALSE ) { // If neither the ways nor the number of threads were set, then // the rntm was not meaningfully changed since initialization, // and thus we'll default to single-threaded execution. nt = 1; jc = pc = ic = jr = ir = 1; } #else // When multithreading is disabled, always set the rntm_t ways // values to 1. nt = 1; jc = pc = ic = jr = ir = 1; #endif // Save the results back in the runtime object. bli_rntm_set_auto_factor_only( auto_factor, rntm ); bli_rntm_set_num_threads_only( nt, rntm ); bli_rntm_set_ways_only( jc, pc, ic, jr, ir, rntm ); } void bli_rntm_print ( rntm_t* rntm ) { dim_t af = bli_rntm_auto_factor( rntm ); dim_t nt = bli_rntm_num_threads( rntm ); dim_t jc = bli_rntm_jc_ways( rntm ); dim_t pc = bli_rntm_pc_ways( rntm ); dim_t ic = bli_rntm_ic_ways( rntm ); dim_t jr = bli_rntm_jr_ways( rntm ); dim_t ir = bli_rntm_ir_ways( rntm ); printf( "rntm contents nt jc pc ic jr ir\n" ); printf( "autofac? %1d | %4d%4d%4d%4d%4d%4d\n", (int)af, (int)nt, (int)jc, (int)pc, (int)ic, (int)jr, (int)ir ); } // ----------------------------------------------------------------------------- dim_t bli_rntm_calc_num_threads_in ( bszid_t* restrict bszid_cur, rntm_t* restrict rntm ) { /* // bp algorithm: bszid_t bszids[7] = { BLIS_NC, // level 0: 5th loop BLIS_KC, // level 1: 4th loop BLIS_NO_PART, // level 2: pack B BLIS_MC, // level 3: 3rd loop BLIS_NO_PART, // level 4: pack A BLIS_NR, // level 5: 2nd loop BLIS_MR, // level 6: 1st loop BLIS_KR // level 7: ukr loop ... // pb algorithm: BLIS_NR, // level 5: 2nd loop BLIS_MR, // level 6: 1st loop BLIS_KR // level 7: ukr loop }; */ dim_t n_threads_in = 1; // Starting with the current element of the bszids array (pointed // to by bszid_cur), multiply all of the corresponding ways of // parallelism. for ( ; *bszid_cur != BLIS_KR; bszid_cur++ ) { const bszid_t bszid = *bszid_cur; //if ( bszid == BLIS_KR ) break; // We assume bszid is in {NC,KC,MC,NR,MR,KR} if it is not // BLIS_NO_PART. if ( bszid != BLIS_NO_PART ) { const dim_t cur_way = bli_rntm_ways_for( bszid, rntm ); n_threads_in *= cur_way; } } return n_threads_in; } #if 0 for ( ; *bszid_cur != BLIS_KR; bszid_cur++ ) { const bszid_t bszid = *bszid_cur; dim_t cur_way = 1; // We assume bszid is in {NC,KC,MC,NR,MR,KR} if it is not // BLIS_NO_PART. if ( bszid != BLIS_NO_PART ) cur_way = bli_rntm_ways_for( bszid, rntm ); else cur_way = 1; n_threads_in *= cur_way; } #endif blis-0.9.0/frame/base/bli_rntm.h000066400000000000000000000245401422157504600164470ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2016, Hewlett Packard Enterprise Development LP Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_RNTM_H #define BLIS_RNTM_H // Runtime object type (defined in bli_type_defs.h) /* typedef struct rntm_s { bool auto_factor; dim_t num_threads; dim_t* thrloop; bool pack_a; bool pack_b; bool l3_sup; pool_t* sba_pool; pba_t* pba; } rntm_t; */ // // -- rntm_t query (public API) ------------------------------------------------ // BLIS_INLINE bool bli_rntm_auto_factor( rntm_t* rntm ) { return rntm->auto_factor; } BLIS_INLINE dim_t bli_rntm_num_threads( rntm_t* rntm ) { return rntm->num_threads; } BLIS_INLINE dim_t bli_rntm_ways_for( bszid_t bszid, rntm_t* rntm ) { return rntm->thrloop[ bszid ]; } BLIS_INLINE dim_t bli_rntm_jc_ways( rntm_t* rntm ) { return bli_rntm_ways_for( BLIS_NC, rntm ); } BLIS_INLINE dim_t bli_rntm_pc_ways( rntm_t* rntm ) { return bli_rntm_ways_for( BLIS_KC, rntm ); } BLIS_INLINE dim_t bli_rntm_ic_ways( rntm_t* rntm ) { return bli_rntm_ways_for( BLIS_MC, rntm ); } BLIS_INLINE dim_t bli_rntm_jr_ways( rntm_t* rntm ) { return bli_rntm_ways_for( BLIS_NR, rntm ); } BLIS_INLINE dim_t bli_rntm_ir_ways( rntm_t* rntm ) { return bli_rntm_ways_for( BLIS_MR, rntm ); } BLIS_INLINE dim_t bli_rntm_pr_ways( rntm_t* rntm ) { return bli_rntm_ways_for( BLIS_KR, rntm ); } BLIS_INLINE bool bli_rntm_pack_a( rntm_t* rntm ) { return ( bool )( rntm->pack_a ); } BLIS_INLINE bool bli_rntm_pack_b( rntm_t* rntm ) { return ( bool )( rntm->pack_b ); } BLIS_INLINE bool bli_rntm_l3_sup( rntm_t* rntm ) { return rntm->l3_sup; } // // -- rntm_t query (internal use only) ----------------------------------------- // BLIS_INLINE pool_t* bli_rntm_sba_pool( rntm_t* rntm ) { return rntm->sba_pool; } BLIS_INLINE pba_t* bli_rntm_pba( rntm_t* rntm ) { return rntm->pba; } #if 0 BLIS_INLINE dim_t bli_rntm_equals( rntm_t* rntm1, rntm_t* rntm2 ) { const bool nt = bli_rntm_num_threads( rntm1 ) == bli_rntm_num_threads( rntm2 ); const bool jc = bli_rntm_jc_ways( rntm1 ) == bli_rntm_jc_ways( rntm2 ); const bool pc = bli_rntm_pc_ways( rntm1 ) == bli_rntm_pc_ways( rntm2 ); const bool ic = bli_rntm_ic_ways( rntm1 ) == bli_rntm_ic_ways( rntm2 ); const bool jr = bli_rntm_jr_ways( rntm1 ) == bli_rntm_jr_ways( rntm2 ); const bool ir = bli_rntm_ir_ways( rntm1 ) == bli_rntm_ir_ways( rntm2 ); const bool pr = bli_rntm_pr_ways( rntm1 ) == bli_rntm_pr_ways( rntm2 ); if ( nt && jc && pc && ic && jr && ir && pr ) return TRUE; else return FALSE; } #endif // // -- rntm_t modification (internal use only) ---------------------------------- // BLIS_INLINE void bli_rntm_set_auto_factor_only( bool auto_factor, rntm_t* rntm ) { rntm->auto_factor = auto_factor; } BLIS_INLINE void bli_rntm_set_num_threads_only( dim_t nt, rntm_t* rntm ) { rntm->num_threads = nt; } BLIS_INLINE void bli_rntm_set_ways_for_only( bszid_t loop, dim_t n_ways, rntm_t* rntm ) { rntm->thrloop[ loop ] = n_ways; } BLIS_INLINE void bli_rntm_set_jc_ways_only( dim_t ways, rntm_t* rntm ) { bli_rntm_set_ways_for_only( BLIS_NC, ways, rntm ); } BLIS_INLINE void bli_rntm_set_pc_ways_only( dim_t ways, rntm_t* rntm ) { bli_rntm_set_ways_for_only( BLIS_KC, ways, rntm ); } BLIS_INLINE void bli_rntm_set_ic_ways_only( dim_t ways, rntm_t* rntm ) { bli_rntm_set_ways_for_only( BLIS_MC, ways, rntm ); } BLIS_INLINE void bli_rntm_set_jr_ways_only( dim_t ways, rntm_t* rntm ) { bli_rntm_set_ways_for_only( BLIS_NR, ways, rntm ); } BLIS_INLINE void bli_rntm_set_ir_ways_only( dim_t ways, rntm_t* rntm ) { bli_rntm_set_ways_for_only( BLIS_MR, ways, rntm ); } BLIS_INLINE void bli_rntm_set_pr_ways_only( dim_t ways, rntm_t* rntm ) { bli_rntm_set_ways_for_only( BLIS_KR, ways, rntm ); } BLIS_INLINE void bli_rntm_set_ways_only( dim_t jc, dim_t pc, dim_t ic, dim_t jr, dim_t ir, rntm_t* rntm ) { // Record the number of ways of parallelism per loop. bli_rntm_set_jc_ways_only( jc, rntm ); bli_rntm_set_pc_ways_only( pc, rntm ); bli_rntm_set_ic_ways_only( ic, rntm ); bli_rntm_set_jr_ways_only( jr, rntm ); bli_rntm_set_ir_ways_only( ir, rntm ); bli_rntm_set_pr_ways_only( 1, rntm ); } BLIS_INLINE void bli_rntm_set_sba_pool( pool_t* sba_pool, rntm_t* rntm ) { rntm->sba_pool = sba_pool; } BLIS_INLINE void bli_rntm_set_pba( pba_t* pba, rntm_t* rntm ) { rntm->pba = pba; } BLIS_INLINE void bli_rntm_clear_num_threads_only( rntm_t* rntm ) { bli_rntm_set_num_threads_only( -1, rntm ); } BLIS_INLINE void bli_rntm_clear_ways_only( rntm_t* rntm ) { bli_rntm_set_ways_only( -1, -1, -1, -1, -1, rntm ); } BLIS_INLINE void bli_rntm_clear_sba_pool( rntm_t* rntm ) { bli_rntm_set_sba_pool( NULL, rntm ); } BLIS_INLINE void bli_rntm_clear_pba( rntm_t* rntm ) { bli_rntm_set_pba( NULL, rntm ); } // // -- rntm_t modification (public API) ----------------------------------------- // BLIS_INLINE void bli_rntm_set_num_threads( dim_t nt, rntm_t* rntm ) { // Record the total number of threads to use. bli_rntm_set_num_threads_only( nt, rntm ); // Set the individual ways of parallelism to default states. bli_rntm_clear_ways_only( rntm ); } BLIS_INLINE void bli_rntm_set_ways( dim_t jc, dim_t pc, dim_t ic, dim_t jr, dim_t ir, rntm_t* rntm ) { // Record the number of ways of parallelism per loop. bli_rntm_set_jc_ways_only( jc, rntm ); bli_rntm_set_pc_ways_only( pc, rntm ); bli_rntm_set_ic_ways_only( ic, rntm ); bli_rntm_set_jr_ways_only( jr, rntm ); bli_rntm_set_ir_ways_only( ir, rntm ); bli_rntm_set_pr_ways_only( 1, rntm ); // Set the num_threads field to a default state. bli_rntm_clear_num_threads_only( rntm ); } BLIS_INLINE void bli_rntm_set_pack_a( bool pack_a, rntm_t* rntm ) { // Set the bool indicating whether matrix A should be packed. rntm->pack_a = pack_a; } BLIS_INLINE void bli_rntm_set_pack_b( bool pack_b, rntm_t* rntm ) { // Set the bool indicating whether matrix B should be packed. rntm->pack_b = pack_b; } BLIS_INLINE void bli_rntm_set_l3_sup( bool l3_sup, rntm_t* rntm ) { // Set the bool indicating whether level-3 sup handling is enabled. rntm->l3_sup = l3_sup; } BLIS_INLINE void bli_rntm_enable_l3_sup( rntm_t* rntm ) { bli_rntm_set_l3_sup( TRUE, rntm ); } BLIS_INLINE void bli_rntm_disable_l3_sup( rntm_t* rntm ) { bli_rntm_set_l3_sup( FALSE, rntm ); } // // -- rntm_t modification (internal use only) ---------------------------------- // BLIS_INLINE void bli_rntm_clear_pack_a( rntm_t* rntm ) { bli_rntm_set_pack_a( FALSE, rntm ); } BLIS_INLINE void bli_rntm_clear_pack_b( rntm_t* rntm ) { bli_rntm_set_pack_b( FALSE, rntm ); } BLIS_INLINE void bli_rntm_clear_l3_sup( rntm_t* rntm ) { bli_rntm_set_l3_sup( TRUE, rntm ); } // // -- rntm_t initialization ---------------------------------------------------- // // NOTE: Initialization is not necessary as long the user calls at least ONE // of the public "set" accessors, each of which guarantees that the rntm_t // will be in a good state upon return. #define BLIS_RNTM_INITIALIZER \ { \ .auto_factor = TRUE, \ .num_threads = -1, \ .thrloop = { -1, -1, -1, -1, -1, -1 }, \ .pack_a = FALSE, \ .pack_b = FALSE, \ .l3_sup = TRUE, \ .sba_pool = NULL, \ .pba = NULL, \ } \ BLIS_INLINE void bli_rntm_init( rntm_t* rntm ) { bli_rntm_set_auto_factor_only( TRUE, rntm ); bli_rntm_clear_num_threads_only( rntm ); bli_rntm_clear_ways_only( rntm ); bli_rntm_clear_pack_a( rntm ); bli_rntm_clear_pack_b( rntm ); bli_rntm_clear_l3_sup( rntm ); bli_rntm_clear_sba_pool( rntm ); bli_rntm_clear_pba( rntm ); } // -- rntm_t total thread calculation ------------------------------------------ BLIS_INLINE dim_t bli_rntm_calc_num_threads ( rntm_t* restrict rntm ) { dim_t n_threads; n_threads = bli_rntm_ways_for( BLIS_NC, rntm ); n_threads *= bli_rntm_ways_for( BLIS_KC, rntm ); n_threads *= bli_rntm_ways_for( BLIS_MC, rntm ); n_threads *= bli_rntm_ways_for( BLIS_NR, rntm ); n_threads *= bli_rntm_ways_for( BLIS_MR, rntm ); return n_threads; } // ----------------------------------------------------------------------------- // Function prototypes BLIS_EXPORT_BLIS void bli_rntm_init_from_global( rntm_t* rntm ); BLIS_EXPORT_BLIS void bli_rntm_set_ways_for_op ( opid_t l3_op, side_t side, dim_t m, dim_t n, dim_t k, rntm_t* rntm ); void bli_rntm_set_ways_from_rntm ( dim_t m, dim_t n, dim_t k, rntm_t* rntm ); void bli_rntm_set_ways_from_rntm_sup ( dim_t m, dim_t n, dim_t k, rntm_t* rntm ); void bli_rntm_print ( rntm_t* rntm ); dim_t bli_rntm_calc_num_threads_in ( bszid_t* restrict bszid_cur, rntm_t* restrict rntm ); #endif blis-0.9.0/frame/base/bli_sba.c000066400000000000000000000134321422157504600162250ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // Statically initialize the mutex within the small block allocator. // Note that the sba is an apool_t of array_t of pool_t. static apool_t sba = { .mutex = BLIS_PTHREAD_MUTEX_INITIALIZER }; apool_t* bli_sba_query( void ) { return &sba; } // ----------------------------------------------------------------------------- void bli_sba_init( void ) { bli_apool_init( &sba ); } void bli_sba_finalize( void ) { bli_apool_finalize( &sba ); } void* bli_sba_acquire ( rntm_t* restrict rntm, siz_t req_size ) { void* block; err_t r_val; #ifdef BLIS_ENABLE_SBA_POOLS if ( rntm == NULL ) { block = bli_malloc_intl( req_size, &r_val ); } else { pblk_t pblk; // Query the small block pool from the rntm. pool_t* restrict pool = bli_rntm_sba_pool( rntm ); // We don't expect NULL sba_pool pointers in the normal course of BLIS // operation. However, there are rare instances where it is convenient // to support use of bli_sba_acquire() without having to pass in a valid // sba pool data structure. The case that inspired this branch was the // gemm_ukr and related test modules in the BLIS testsuite. (There, it // is convenient to not have to checkout an array_t from the sba, and it // does no harm since the malloc() happens outside of the region that // would be timed.) if ( pool == NULL ) { block = bli_malloc_intl( req_size, &r_val ); } else { // Query the block_size of the pool_t so that we can request the exact // size present. const siz_t block_size = bli_pool_block_size( pool ); // Sanity check: Make sure the requested size is no larger than the // block_size field of the pool. if ( block_size < req_size ) { printf( "bli_sba_acquire(): ** pool block_size is %d but req_size is %d.\n", ( int )block_size, ( int )req_size ); bli_abort(); } // Check out a block using the block_size queried above. bli_pool_checkout_block( block_size, &pblk, pool ); // The block address is stored within the pblk_t. block = bli_pblk_buf( &pblk ); } } #else block = bli_malloc_intl( req_size, &r_val ); #endif // Return the address obtained from the pblk_t. return block; } void bli_sba_release ( rntm_t* restrict rntm, void* restrict block ) { #ifdef BLIS_ENABLE_SBA_POOLS if ( rntm == NULL ) { bli_free_intl( block ); } else { pblk_t pblk; // Query the small block pool from the rntm. pool_t* restrict pool = bli_rntm_sba_pool( rntm ); if ( pool == NULL ) { bli_free_intl( block ); } else { // Query the block_size field from the pool. This is not super-important // for this particular application of the pool_t (that is, the "leaf" // component of the sba), but it seems like good housekeeping to maintain // the block_size field of the pblk_t in case its ever needed/read. const siz_t block_size = bli_pool_block_size( pool ); // Embed the block's memory address into a pblk_t, along with the // block_size queried from the pool. bli_pblk_set_buf( block, &pblk ); bli_pblk_set_block_size( block_size, &pblk ); // Check the pblk_t back into the pool_t. (It's okay that the pblk_t is // a local variable since its contents are copied into the pool's internal // data structure--an array of pblk_t.) bli_pool_checkin_block( &pblk, pool ); } } #else bli_free_intl( block ); #endif } array_t* bli_sba_checkout_array ( const siz_t n_threads ) { #ifndef BLIS_ENABLE_SBA_POOLS return NULL; #endif return bli_apool_checkout_array( n_threads, &sba ); } void bli_sba_checkin_array ( array_t* restrict array ) { #ifndef BLIS_ENABLE_SBA_POOLS return; #endif bli_apool_checkin_array( array, &sba ); } void bli_sba_rntm_set_pool ( siz_t index, array_t* restrict array, rntm_t* restrict rntm ) { #ifndef BLIS_ENABLE_SBA_POOLS bli_rntm_set_sba_pool( NULL, rntm ); return; #endif // Query the pool_t* in the array_t corresponding to index. pool_t* restrict pool = bli_apool_array_elem( index, array ); // Embed the pool_t* into the rntm_t. bli_rntm_set_sba_pool( pool, rntm ); } blis-0.9.0/frame/base/bli_sba.h000066400000000000000000000045161422157504600162350ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_SBA_H #define BLIS_SBA_H apool_t* bli_sba_query( void ); // ----------------------------------------------------------------------------- void bli_sba_init( void ); void bli_sba_finalize( void ); array_t* bli_sba_checkout_array ( const siz_t n_threads ); void bli_sba_checkin_array ( array_t* restrict array ); void bli_sba_rntm_set_pool ( siz_t index, array_t* restrict array, rntm_t* restrict rntm ); void* bli_sba_acquire ( rntm_t* restrict rntm, siz_t req_size ); void bli_sba_release ( rntm_t* restrict rntm, void* restrict block ); #endif blis-0.9.0/frame/base/bli_setgetijm.c000066400000000000000000000113271422157504600174540ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" typedef void (*setijm_fp) ( double ar, double ai, dim_t i, dim_t j, void* restrict b, inc_t rs, inc_t cs ); static setijm_fp GENARRAY(ftypes_setijm,setijm); err_t bli_setijm ( double ar, double ai, dim_t i, dim_t j, obj_t* b ) { dim_t m = bli_obj_length( b ); dim_t n = bli_obj_width( b ); dim_t rs = bli_obj_row_stride( b ); dim_t cs = bli_obj_col_stride( b ); num_t dt = bli_obj_dt( b ); // Return error if i or j is beyond bounds of the matrix/vector. if ( i < 0 || m <= i ) return BLIS_FAILURE; if ( j < 0 || n <= j ) return BLIS_FAILURE; // Don't modify scalar constants. if ( dt == BLIS_CONSTANT ) return BLIS_FAILURE; // Query the pointer to the buffer at the adjusted offsets. void* b_p = bli_obj_buffer_at_off( b ); // Index into the function pointer array. setijm_fp f = ftypes_setijm[ dt ]; // Invoke the type-specific function. f ( ar, ai, i, j, b_p, rs, cs ); return BLIS_SUCCESS; } #undef GENTFUNC #define GENTFUNC( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ double ar, \ double ai, \ dim_t i, \ dim_t j, \ void* restrict b, inc_t rs, inc_t cs \ ) \ { \ ctype* restrict b_cast = ( ctype* )b; \ \ ctype* restrict b_ij = b_cast + (i )*rs + (j )*cs; \ \ PASTEMAC2(z,ch,sets)( ar, ai, *b_ij ); \ } INSERT_GENTFUNC_BASIC0( setijm ) // ----------------------------------------------------------------------------- typedef void (*getijm_fp) ( dim_t i, dim_t j, void* restrict b, inc_t rs, inc_t cs, double* ar, double* ai ); static getijm_fp GENARRAY(ftypes_getijm,getijm); err_t bli_getijm ( dim_t i, dim_t j, obj_t* b, double* ar, double* ai ) { dim_t m = bli_obj_length( b ); dim_t n = bli_obj_width( b ); dim_t rs = bli_obj_row_stride( b ); dim_t cs = bli_obj_col_stride( b ); num_t dt = bli_obj_dt( b ); // Return error if i or j is beyond bounds of the matrix/vector. if ( i < 0 || m <= i ) return BLIS_FAILURE; if ( j < 0 || n <= j ) return BLIS_FAILURE; // Disallow access into scalar constants. if ( dt == BLIS_CONSTANT ) return BLIS_FAILURE; // Query the pointer to the buffer at the adjusted offsets. void* b_p = bli_obj_buffer_at_off( b ); // Index into the function pointer array. getijm_fp f = ftypes_getijm[ dt ]; // Invoke the type-specific function. f ( i, j, b_p, rs, cs, ar, ai ); return BLIS_SUCCESS; } #undef GENTFUNC #define GENTFUNC( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ dim_t i, \ dim_t j, \ void* restrict b, inc_t rs, inc_t cs, \ double* ar, \ double* ai \ ) \ { \ ctype* restrict b_cast = ( ctype* )b; \ \ ctype* restrict b_ij = b_cast + (i )*rs + (j )*cs; \ \ PASTEMAC2(ch,z,gets)( *b_ij, *ar, *ai ); \ } INSERT_GENTFUNC_BASIC0( getijm ) blis-0.9.0/frame/base/bli_setgetijm.h000066400000000000000000000051541422157504600174620ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ BLIS_EXPORT_BLIS err_t bli_setijm ( double ar, double ai, dim_t i, dim_t j, obj_t* b ); #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC(ch,opname) \ ( \ double ar, \ double ai, \ dim_t i, \ dim_t j, \ void* restrict b, inc_t rs, inc_t cs \ ); INSERT_GENTPROT_BASIC0( setijm ) // ----------------------------------------------------------------------------- BLIS_EXPORT_BLIS err_t bli_getijm ( dim_t i, dim_t j, obj_t* b, double* ar, double* ai ); #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC(ch,opname) \ ( \ dim_t i, \ dim_t j, \ void* restrict b, inc_t rs, inc_t cs, \ double* ar, \ double* ai \ ); INSERT_GENTPROT_BASIC0( getijm ) blis-0.9.0/frame/base/bli_setgetijv.c000066400000000000000000000104341422157504600174630ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" typedef void (*setijv_fp) ( double ar, double ai, dim_t i, void* restrict x, inc_t incx ); static setijv_fp GENARRAY(ftypes_setijv,setijv); err_t bli_setijv ( double ar, double ai, dim_t i, obj_t* x ) { dim_t n = bli_obj_vector_dim( x ); dim_t incx = bli_obj_vector_inc( x ); num_t dt = bli_obj_dt( x ); // Return error if i is beyond bounds of the vector. if ( i < 0 || n <= i ) return BLIS_FAILURE; // Don't modify scalar constants. if ( dt == BLIS_CONSTANT ) return BLIS_FAILURE; // Query the pointer to the buffer at the adjusted offsets. void* x_p = bli_obj_buffer_at_off( x ); // Index into the function pointer array. setijv_fp f = ftypes_setijv[ dt ]; // Invoke the type-specific function. f ( ar, ai, i, x_p, incx ); return BLIS_SUCCESS; } #undef GENTFUNC #define GENTFUNC( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ double ar, \ double ai, \ dim_t i, \ void* restrict x, inc_t incx \ ) \ { \ ctype* restrict x_cast = ( ctype* )x; \ \ ctype* restrict x_i = x_cast + (i )*incx; \ \ PASTEMAC2(z,ch,sets)( ar, ai, *x_i ); \ } INSERT_GENTFUNC_BASIC0( setijv ) // ----------------------------------------------------------------------------- typedef void (*getijv_fp) ( dim_t i, void* restrict x, inc_t incx, double* ar, double* ai ); static getijv_fp GENARRAY(ftypes_getijv,getijv); err_t bli_getijv ( dim_t i, obj_t* x, double* ar, double* ai ) { dim_t n = bli_obj_vector_dim( x ); dim_t incx = bli_obj_vector_inc( x ); num_t dt = bli_obj_dt( x ); // Return error if i is beyond bounds of the vector. if ( i < 0 || n <= i ) return BLIS_FAILURE; // Disallow access into scalar constants. if ( dt == BLIS_CONSTANT ) return BLIS_FAILURE; // Query the pointer to the buffer at the adjusted offsets. void* x_p = bli_obj_buffer_at_off( x ); // Index into the function pointer array. getijv_fp f = ftypes_getijv[ dt ]; // Invoke the type-specific function. f ( i, x_p, incx, ar, ai ); return BLIS_SUCCESS; } #undef GENTFUNC #define GENTFUNC( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ dim_t i, \ void* restrict x, inc_t incx, \ double* ar, \ double* ai \ ) \ { \ ctype* restrict x_cast = ( ctype* )x; \ \ ctype* restrict x_i = x_cast + (i )*incx; \ \ PASTEMAC2(ch,z,gets)( *x_i, *ar, *ai ); \ } INSERT_GENTFUNC_BASIC0( getijv ) blis-0.9.0/frame/base/bli_setgetijv.h000066400000000000000000000050011422157504600174620ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ BLIS_EXPORT_BLIS err_t bli_setijv ( double ar, double ai, dim_t i, obj_t* x ); #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC(ch,opname) \ ( \ double ar, \ double ai, \ dim_t i, \ void* restrict x, inc_t incx \ ); INSERT_GENTPROT_BASIC0( setijv ) // ----------------------------------------------------------------------------- BLIS_EXPORT_BLIS err_t bli_getijv ( dim_t i, obj_t* x, double* ar, double* ai ); #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC(ch,opname) \ ( \ dim_t i, \ void* restrict b, inc_t incx, \ double* ar, \ double* ai \ ); INSERT_GENTPROT_BASIC0( getijv ) blis-0.9.0/frame/base/bli_setri.c000066400000000000000000000113361422157504600166070ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // -- setr --------------------------------------------------------------------- void bli_setrm ( obj_t* alpha, obj_t* b ) { obj_t alpha_real; obj_t br; // Check parameters. if ( bli_error_checking_is_enabled() ) bli_setm_check( alpha, b ); // Initialize a local scalar, alpha_real, using the real projection // of the datatype of b. bli_obj_scalar_init_detached( bli_obj_dt_proj_to_real( b ), &alpha_real ); // Copy/typecast alpha to alpha_real. This discards the imaginary // part of alpha (if it is complex). bli_copysc( alpha, &alpha_real ); // Acquire an alias to the real part of b. bli_obj_real_part( b, &br ); // Use setm to set the real part of b to alpha_real. bli_setm( &alpha_real, &br ); } void bli_setrv ( obj_t* alpha, obj_t* x ) { obj_t alpha_real; obj_t xr; // Check parameters. if ( bli_error_checking_is_enabled() ) bli_setv_check( alpha, x ); // Initialize a local scalar, alpha_real, using the real projection // of the datatype of x. bli_obj_scalar_init_detached( bli_obj_dt_proj_to_real( x ), &alpha_real ); // Copy/typecast alpha to alpha_real. This discards the imaginary // part of alpha (if it is complex). bli_copysc( alpha, &alpha_real ); // Acquire an alias to the real part of x. bli_obj_real_part( x, &xr ); // Use setv to set the real part of x to alpha_real. bli_setv( &alpha_real, &xr ); } // -- seti --------------------------------------------------------------------- void bli_setim ( obj_t* alpha, obj_t* b ) { obj_t alpha_real; obj_t bi; // Check parameters. if ( bli_error_checking_is_enabled() ) bli_setm_check( alpha, b ); // If the object is real, return early. if ( bli_obj_is_real( b ) ) return; // Initialize a local scalar, alpha_real, using the real projection // of the datatype of b. bli_obj_scalar_init_detached( bli_obj_dt_proj_to_real( b ), &alpha_real ); // Copy/typecast alpha to alpha_real. This discards the imaginary // part of alpha (if it is complex). bli_copysc( alpha, &alpha_real ); // Acquire an alias to the imaginary part of b. bli_obj_imag_part( b, &bi ); // Use setm to set the imaginary part of b to alpha_real. bli_setm( &alpha_real, &bi ); } void bli_setiv ( obj_t* alpha, obj_t* x ) { obj_t alpha_real; obj_t xi; // Check parameters. if ( bli_error_checking_is_enabled() ) bli_setv_check( alpha, x ); // If the object is real, return early. if ( bli_obj_is_real( x ) ) return; // Initialize a local scalar, alpha_real, using the real projection // of the datatype of x. bli_obj_scalar_init_detached( bli_obj_dt_proj_to_real( x ), &alpha_real ); // Copy/typecast alpha to alpha_real. This discards the imaginary // part of alpha (if it is complex). bli_copysc( alpha, &alpha_real ); // Acquire an alias to the imaginary part of x. bli_obj_imag_part( x, &xi ); // Use setm to set the imaginary part of x to alpha_real. bli_setm( &alpha_real, &xi ); } blis-0.9.0/frame/base/bli_setri.h000066400000000000000000000042011422157504600166050ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // -- setr --------------------------------------------------------------------- BLIS_EXPORT_BLIS void bli_setrm ( obj_t* alpha, obj_t* b ); BLIS_EXPORT_BLIS void bli_setrv ( obj_t* alpha, obj_t* x ); // -- seti --------------------------------------------------------------------- BLIS_EXPORT_BLIS void bli_setim ( obj_t* alpha, obj_t* b ); BLIS_EXPORT_BLIS void bli_setiv ( obj_t* alpha, obj_t* x ); blis-0.9.0/frame/base/bli_string.c000066400000000000000000000035621422157504600167710ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_string_mkupper( char* s ) { // Convert the string to uppercase. for ( ; *s != '\0'; s++ ) { // Convert to unsigned in case one of the chars is negative. *s = toupper( ( unsigned char ) *s ); } } blis-0.9.0/frame/base/bli_string.h000066400000000000000000000032551422157504600167750ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void bli_string_mkupper( char* s ); blis-0.9.0/frame/base/bli_winsys.c000066400000000000000000000045111422157504600170120ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #ifdef _MSC_VER #include #else #include #endif #if 0 // NOTE: This function is no longer needed by BLIS since BLIS no longer // makes any attempt to change environment variables; rather, it only // reads them. We can keep it here for some time before removing it, // though. int bli_setenv( const char *name, const char *value, int overwrite ) { #ifdef _MSC_VER // Windows. _putenv_s( name, value ); #else // Everything else: Linux, OS X, etc. setenv( name, value, overwrite ); #endif } #endif void bli_sleep( unsigned int secs ) { #ifdef _MSC_VER // Windows. Sleep( secs * 1000 ); #else // Everything else: Linux, OS X, etc. sleep( secs ); #endif } blis-0.9.0/frame/base/bli_winsys.h000066400000000000000000000034111422157504600170150ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ //int bli_setenv( const char *name, const char *value, int overwrite ); BLIS_EXPORT_BLIS void bli_sleep( unsigned int secs ); blis-0.9.0/frame/base/cast/000077500000000000000000000000001422157504600154155ustar00rootroot00000000000000blis-0.9.0/frame/base/cast/bli_castm.c000066400000000000000000000153071422157504600175240ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // NOTE: This is one of the few functions in BLIS that is defined // with heterogeneous type support. This is done so that we have // an operation that can be used to typecast (copy-cast) a matrix // of one datatype to a scalar of another datatype. typedef void (*FUNCPTR_T) ( trans_t transa, dim_t m, dim_t n, void* restrict a, inc_t rs_a, inc_t cs_a, void* restrict b, inc_t rs_b, inc_t cs_b ); static FUNCPTR_T GENARRAY2_ALL(ftypes,castm); // // Define object-based interface. // void bli_castm ( obj_t* a, obj_t* b ) { num_t dt_a = bli_obj_dt( a ); num_t dt_b = bli_obj_dt( b ); trans_t transa = bli_obj_conjtrans_status( a ); dim_t m = bli_obj_length( b ); dim_t n = bli_obj_width( b ); void* buf_a = bli_obj_buffer_at_off( a ); inc_t rs_a = bli_obj_row_stride( a ); inc_t cs_a = bli_obj_col_stride( a ); void* buf_b = bli_obj_buffer_at_off( b ); inc_t rs_b = bli_obj_row_stride( b ); inc_t cs_b = bli_obj_col_stride( b ); FUNCPTR_T f; // Check parameters. if ( bli_error_checking_is_enabled() ) bli_castm_check( a, b ); #if 0 if ( bli_obj_dt( a ) == bli_obj_dt( b ) ) { // If a and b share the same datatype, we can simply use copym. bli_copym( a, b ); return; } #endif // Index into the type combination array to extract the correct // function pointer. f = ftypes[dt_a][dt_b]; // Invoke the void pointer-based function. f ( transa, m, n, buf_a, rs_a, cs_a, buf_b, rs_b, cs_b ); } // ----------------------------------------------------------------------------- // // Define BLAS-like interfaces with typed operands. // #undef GENTFUNC2 #define GENTFUNC2( ctype_a, ctype_b, cha, chb, opname ) \ \ void PASTEMAC2(cha,chb,opname) \ ( \ trans_t transa, \ dim_t m, \ dim_t n, \ void* restrict a, inc_t rs_a, inc_t cs_a, \ void* restrict b, inc_t rs_b, inc_t cs_b \ ) \ { \ ctype_a* restrict a_cast = a; \ ctype_b* restrict b_cast = b; \ conj_t conja; \ dim_t n_iter; \ dim_t n_elem; \ inc_t lda, inca; \ inc_t ldb, incb; \ dim_t j, i; \ \ /* Set various loop parameters. */ \ bli_set_dims_incs_2m \ ( \ transa, \ m, n, rs_a, cs_a, rs_b, cs_b, \ &n_elem, &n_iter, &inca, &lda, &incb, &ldb \ ); \ \ /* Extract the conjugation component from the transa parameter. */ \ conja = bli_extract_conj( transa ); \ \ if ( bli_is_conj( conja ) ) \ { \ if ( inca == 1 && incb == 1 ) \ { \ for ( j = 0; j < n_iter; ++j ) \ { \ ctype_a* restrict a1 = a_cast + (j )*lda + (0 )*inca; \ ctype_b* restrict b1 = b_cast + (j )*ldb + (0 )*incb; \ \ for ( i = 0; i < n_elem; ++i ) \ { \ PASTEMAC2(cha,chb,copyjs)( a1[i], b1[i] ); \ } \ } \ } \ else \ { \ for ( j = 0; j < n_iter; ++j ) \ { \ ctype_a* restrict a1 = a_cast + (j )*lda + (0 )*inca; \ ctype_b* restrict b1 = b_cast + (j )*ldb + (0 )*incb; \ \ for ( i = 0; i < n_elem; ++i ) \ { \ PASTEMAC2(cha,chb,copyjs)( *a1, *b1 ); \ \ a1 += inca; \ b1 += incb; \ } \ } \ } \ } \ else \ { \ if ( inca == 1 && incb == 1 ) \ { \ for ( j = 0; j < n_iter; ++j ) \ { \ ctype_a* restrict a1 = a_cast + (j )*lda + (0 )*inca; \ ctype_b* restrict b1 = b_cast + (j )*ldb + (0 )*incb; \ \ for ( i = 0; i < n_elem; ++i ) \ { \ PASTEMAC2(cha,chb,copys)( a1[i], b1[i] ); \ } \ } \ } \ else \ { \ for ( j = 0; j < n_iter; ++j ) \ { \ ctype_a* restrict a1 = a_cast + (j )*lda + (0 )*inca; \ ctype_b* restrict b1 = b_cast + (j )*ldb + (0 )*incb; \ \ for ( i = 0; i < n_elem; ++i ) \ { \ PASTEMAC2(cha,chb,copys)( *a1, *b1 ); \ \ a1 += inca; \ b1 += incb; \ } \ } \ } \ } \ } INSERT_GENTFUNC2_BASIC0( castm ) INSERT_GENTFUNC2_MIXDP0( castm ) // ----------------------------------------------------------------------------- // // Define object-based _check() function. // void bli_castm_check ( obj_t* a, obj_t* b ) { err_t e_val; // Check object datatypes. e_val = bli_check_floating_object( a ); bli_check_error_code( e_val ); e_val = bli_check_floating_object( b ); bli_check_error_code( e_val ); // Check structure. // NOTE: We enforce general structure for now in order to simplify the // implementation. bli_check_general_object( a ); bli_check_error_code( e_val ); bli_check_general_object( b ); bli_check_error_code( e_val ); // Check object dimensions. e_val = bli_check_matrix_object( a ); bli_check_error_code( e_val ); e_val = bli_check_matrix_object( b ); bli_check_error_code( e_val ); e_val = bli_check_conformal_dims( a, b ); bli_check_error_code( e_val ); // Check object buffers (for non-NULLness). e_val = bli_check_object_buffer( a ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( b ); bli_check_error_code( e_val ); } blis-0.9.0/frame/base/cast/bli_castm.h000066400000000000000000000044721422157504600175320ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype object-based interface. // BLIS_EXPORT_BLIS void bli_castm ( obj_t* a, obj_t* b ); // // Prototype BLAS-like interfaces with heterogeneous-typed operands. // #undef GENTPROT2 #define GENTPROT2( ctype_a, ctype_b, cha, chb, opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC2(cha,chb,opname) \ ( \ trans_t transa, \ dim_t m, \ dim_t n, \ void* a, inc_t rs_a, inc_t cs_a, \ void* b, inc_t rs_b, inc_t cs_b \ ); INSERT_GENTPROT2_BASIC0( castm ) INSERT_GENTPROT2_MIXDP0( castm ) // // Prototype object-based _check() function. // void bli_castm_check ( obj_t* a, obj_t* b ); blis-0.9.0/frame/base/cast/bli_castnzm.c000066400000000000000000000153331422157504600200730ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // NOTE: This is one of the few functions in BLIS that is defined // with heterogeneous type support. This is done so that we have // an operation that can be used to typecast (copy-cast) a matrix // of one datatype to a scalar of another datatype. typedef void (*FUNCPTR_T) ( trans_t transa, dim_t m, dim_t n, void* restrict a, inc_t rs_a, inc_t cs_a, void* restrict b, inc_t rs_b, inc_t cs_b ); static FUNCPTR_T GENARRAY2_ALL(ftypes,castnzm); // // Define object-based interface. // void bli_castnzm ( obj_t* a, obj_t* b ) { num_t dt_a = bli_obj_dt( a ); num_t dt_b = bli_obj_dt( b ); trans_t transa = bli_obj_conjtrans_status( a ); dim_t m = bli_obj_length( b ); dim_t n = bli_obj_width( b ); void* buf_a = bli_obj_buffer_at_off( a ); inc_t rs_a = bli_obj_row_stride( a ); inc_t cs_a = bli_obj_col_stride( a ); void* buf_b = bli_obj_buffer_at_off( b ); inc_t rs_b = bli_obj_row_stride( b ); inc_t cs_b = bli_obj_col_stride( b ); FUNCPTR_T f; // Check parameters. if ( bli_error_checking_is_enabled() ) bli_castnzm_check( a, b ); #if 0 if ( bli_obj_dt( a ) == bli_obj_dt( b ) ) { // If a and b share the same datatype, we can simply use copym. bli_copym( a, b ); return; } #endif // Index into the type combination array to extract the correct // function pointer. f = ftypes[dt_a][dt_b]; // Invoke the void pointer-based function. f ( transa, m, n, buf_a, rs_a, cs_a, buf_b, rs_b, cs_b ); } // ----------------------------------------------------------------------------- // // Define BLAS-like interfaces with typed operands. // #undef GENTFUNC2 #define GENTFUNC2( ctype_a, ctype_b, cha, chb, opname ) \ \ void PASTEMAC2(cha,chb,opname) \ ( \ trans_t transa, \ dim_t m, \ dim_t n, \ void* restrict a, inc_t rs_a, inc_t cs_a, \ void* restrict b, inc_t rs_b, inc_t cs_b \ ) \ { \ ctype_a* restrict a_cast = a; \ ctype_b* restrict b_cast = b; \ conj_t conja; \ dim_t n_iter; \ dim_t n_elem; \ inc_t lda, inca; \ inc_t ldb, incb; \ dim_t j, i; \ \ /* Set various loop parameters. */ \ bli_set_dims_incs_2m \ ( \ transa, \ m, n, rs_a, cs_a, rs_b, cs_b, \ &n_elem, &n_iter, &inca, &lda, &incb, &ldb \ ); \ \ /* Extract the conjugation component from the transa parameter. */ \ conja = bli_extract_conj( transa ); \ \ if ( bli_is_conj( conja ) ) \ { \ if ( inca == 1 && incb == 1 ) \ { \ for ( j = 0; j < n_iter; ++j ) \ { \ ctype_a* restrict a1 = a_cast + (j )*lda + (0 )*inca; \ ctype_b* restrict b1 = b_cast + (j )*ldb + (0 )*incb; \ \ for ( i = 0; i < n_elem; ++i ) \ { \ PASTEMAC2(cha,chb,copyjnzs)( a1[i], b1[i] ); \ } \ } \ } \ else \ { \ for ( j = 0; j < n_iter; ++j ) \ { \ ctype_a* restrict a1 = a_cast + (j )*lda + (0 )*inca; \ ctype_b* restrict b1 = b_cast + (j )*ldb + (0 )*incb; \ \ for ( i = 0; i < n_elem; ++i ) \ { \ PASTEMAC2(cha,chb,copyjnzs)( *a1, *b1 ); \ \ a1 += inca; \ b1 += incb; \ } \ } \ } \ } \ else \ { \ if ( inca == 1 && incb == 1 ) \ { \ for ( j = 0; j < n_iter; ++j ) \ { \ ctype_a* restrict a1 = a_cast + (j )*lda + (0 )*inca; \ ctype_b* restrict b1 = b_cast + (j )*ldb + (0 )*incb; \ \ for ( i = 0; i < n_elem; ++i ) \ { \ PASTEMAC2(cha,chb,copynzs)( a1[i], b1[i] ); \ } \ } \ } \ else \ { \ for ( j = 0; j < n_iter; ++j ) \ { \ ctype_a* restrict a1 = a_cast + (j )*lda + (0 )*inca; \ ctype_b* restrict b1 = b_cast + (j )*ldb + (0 )*incb; \ \ for ( i = 0; i < n_elem; ++i ) \ { \ PASTEMAC2(cha,chb,copynzs)( *a1, *b1 ); \ \ a1 += inca; \ b1 += incb; \ } \ } \ } \ } \ } INSERT_GENTFUNC2_BASIC0( castnzm ) INSERT_GENTFUNC2_MIXDP0( castnzm ) // ----------------------------------------------------------------------------- // // Define object-based _check() function. // void bli_castnzm_check ( obj_t* a, obj_t* b ) { err_t e_val; // Check object datatypes. e_val = bli_check_floating_object( a ); bli_check_error_code( e_val ); e_val = bli_check_floating_object( b ); bli_check_error_code( e_val ); // Check structure. // NOTE: We enforce general structure for now in order to simplify the // implementation. bli_check_general_object( a ); bli_check_error_code( e_val ); bli_check_general_object( b ); bli_check_error_code( e_val ); // Check object dimensions. e_val = bli_check_matrix_object( a ); bli_check_error_code( e_val ); e_val = bli_check_matrix_object( b ); bli_check_error_code( e_val ); e_val = bli_check_conformal_dims( a, b ); bli_check_error_code( e_val ); // Check object buffers (for non-NULLness). e_val = bli_check_object_buffer( a ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( b ); bli_check_error_code( e_val ); } blis-0.9.0/frame/base/cast/bli_castnzm.h000066400000000000000000000045021422157504600200740ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype object-based interface. // BLIS_EXPORT_BLIS void bli_castnzm ( obj_t* a, obj_t* b ); // // Prototype BLAS-like interfaces with heterogeneous-typed operands. // #undef GENTPROT2 #define GENTPROT2( ctype_a, ctype_b, cha, chb, opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC2(cha,chb,opname) \ ( \ trans_t transa, \ dim_t m, \ dim_t n, \ void* a, inc_t rs_a, inc_t cs_a, \ void* b, inc_t rs_b, inc_t cs_b \ ); INSERT_GENTPROT2_BASIC0( castnzm ) INSERT_GENTPROT2_MIXDP0( castnzm ) // // Prototype object-based _check() function. // void bli_castnzm_check ( obj_t* a, obj_t* b ); blis-0.9.0/frame/base/cast/bli_castv.c000066400000000000000000000120511422157504600175260ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // NOTE: This is one of the few functions in BLIS that is defined // with heterogeneous type support. This is done so that we have // an operation that can be used to typecast (copy-cast) a matrix // of one datatype to a scalar of another datatype. typedef void (*FUNCPTR_T) ( conj_t conjx, dim_t n, void* restrict x, inc_t inc_x, void* restrict y, inc_t inc_y ); static FUNCPTR_T GENARRAY2_ALL(ftypes,castv); // // Define object-based interface. // void bli_castv ( obj_t* x, obj_t* y ) { num_t dt_x = bli_obj_dt( x ); num_t dt_y = bli_obj_dt( y ); conj_t conjx = bli_obj_conj_status( x ); dim_t n = bli_obj_vector_dim( x ); void* buf_x = bli_obj_buffer_at_off( x ); inc_t inc_x = bli_obj_vector_inc( x ); void* buf_y = bli_obj_buffer_at_off( y ); inc_t inc_y = bli_obj_vector_inc( y ); FUNCPTR_T f; // Check parameters. if ( bli_error_checking_is_enabled() ) bli_castv_check( x, y ); #if 0 if ( bli_obj_dt( x ) == bli_obj_dt( y ) ) { // If x and y share the same datatype, we can simply use copyv. bli_copyv( x, y ); return; } #endif // Index into the type combination array to extract the correct // function pointer. f = ftypes[dt_x][dt_y]; // Invoke the void pointer-based function. f ( conjx, n, buf_x, inc_x, buf_y, inc_y ); } // ----------------------------------------------------------------------------- // // Define BLAS-like interfaces with typed operands. // #undef GENTFUNC2 #define GENTFUNC2( ctype_x, ctype_y, chx, chy, opname ) \ \ void PASTEMAC2(chx,chy,opname) \ ( \ conj_t conjx, \ dim_t n, \ void* restrict x, inc_t incx, \ void* restrict y, inc_t incy \ ) \ { \ ctype_x* restrict x1 = x; \ ctype_y* restrict y1 = y; \ dim_t i; \ \ if ( bli_is_conj( conjx ) ) \ { \ if ( incx == 1 && incy == 1 ) \ { \ for ( i = 0; i < n; ++i ) \ { \ PASTEMAC2(chx,chy,copyjs)( x1[i], y1[i] ); \ } \ } \ else \ { \ for ( i = 0; i < n; ++i ) \ { \ PASTEMAC2(chx,chy,copyjs)( *x1, *y1 ); \ \ x1 += incx; \ y1 += incy; \ } \ } \ } \ else \ { \ if ( incx == 1 && incy == 1 ) \ { \ for ( i = 0; i < n; ++i ) \ { \ PASTEMAC2(chx,chy,copys)( x1[i], y1[i] ); \ } \ } \ else \ { \ for ( i = 0; i < n; ++i ) \ { \ PASTEMAC2(chx,chy,copys)( *x1, *y1 ); \ \ x1 += incx; \ y1 += incy; \ } \ } \ } \ } INSERT_GENTFUNC2_BASIC0( castv ) INSERT_GENTFUNC2_MIXDP0( castv ) // ----------------------------------------------------------------------------- // // Define object-based _check() function. // void bli_castv_check ( obj_t* x, obj_t* y ) { err_t e_val; // Check object datatypes. e_val = bli_check_floating_object( x ); bli_check_error_code( e_val ); e_val = bli_check_floating_object( y ); bli_check_error_code( e_val ); // Check object dimensions. e_val = bli_check_vector_object( x ); bli_check_error_code( e_val ); e_val = bli_check_vector_object( y ); bli_check_error_code( e_val ); e_val = bli_check_equal_vector_lengths( x, y ); bli_check_error_code( e_val ); // Check object buffers (for non-NULLness). e_val = bli_check_object_buffer( x ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( y ); bli_check_error_code( e_val ); } blis-0.9.0/frame/base/cast/bli_castv.h000066400000000000000000000044151422157504600175400ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype object-based interface. // BLIS_EXPORT_BLIS void bli_castv ( obj_t* x, obj_t* y ); // // Prototype BLAS-like interfaces with heterogeneous-typed operands. // #undef GENTPROT2 #define GENTPROT2( ctype_x, ctype_y, chx, chy, opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC2(chx,chy,opname) \ ( \ conj_t conjx, \ dim_t n, \ void* x, inc_t incx, \ void* y, inc_t incy \ ); INSERT_GENTPROT2_BASIC0( castv ) INSERT_GENTPROT2_MIXDP0( castv ) // // Prototype object-based _check() function. // void bli_castv_check ( obj_t* x, obj_t* y ); blis-0.9.0/frame/base/cast/old/000077500000000000000000000000001422157504600161735ustar00rootroot00000000000000blis-0.9.0/frame/base/cast/old/bli_cast_check.c000066400000000000000000000064261422157504600212640ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_castm_check ( obj_t* a, obj_t* b ) { err_t e_val; // Check object datatypes. e_val = bli_check_floating_object( a ); bli_check_error_code( e_val ); e_val = bli_check_floating_object( b ); bli_check_error_code( e_val ); // Check structure. // NOTE: We enforce general structure for now in order to simplify the // implementation. bli_check_general_object( a ); bli_check_error_code( e_val ); bli_check_general_object( b ); bli_check_error_code( e_val ); // Check object dimensions. e_val = bli_check_matrix_object( a ); bli_check_error_code( e_val ); e_val = bli_check_matrix_object( b ); bli_check_error_code( e_val ); e_val = bli_check_conformal_dims( a, b ); bli_check_error_code( e_val ); // Check object buffers (for non-NULLness). e_val = bli_check_object_buffer( a ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( b ); bli_check_error_code( e_val ); } void bli_castv_check ( obj_t* x, obj_t* y ) { err_t e_val; // Check object datatypes. e_val = bli_check_floating_object( x ); bli_check_error_code( e_val ); e_val = bli_check_floating_object( y ); bli_check_error_code( e_val ); // Check object dimensions. e_val = bli_check_vector_object( x ); bli_check_error_code( e_val ); e_val = bli_check_vector_object( y ); bli_check_error_code( e_val ); e_val = bli_check_equal_vector_lengths( x, y ); bli_check_error_code( e_val ); // Check object buffers (for non-NULLness). e_val = bli_check_object_buffer( x ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( y ); bli_check_error_code( e_val ); } blis-0.9.0/frame/base/cast/old/bli_cast_check.h000066400000000000000000000034241422157504600212640ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void bli_castm_check ( obj_t* a, obj_t* b ); void bli_castv_check ( obj_t* x, obj_t* y ); blis-0.9.0/frame/base/check/000077500000000000000000000000001422157504600155405ustar00rootroot00000000000000blis-0.9.0/frame/base/check/bli_obj_check.c000066400000000000000000000131441422157504600204440ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_obj_create_check( num_t dt, dim_t m, dim_t n, inc_t rs, inc_t cs, obj_t* obj ) { err_t e_val; e_val = bli_check_valid_datatype( dt ); bli_check_error_code( e_val ); e_val = bli_check_matrix_strides( m, n, rs, cs, 1 ); bli_check_error_code( e_val ); e_val = bli_check_null_pointer( obj ); bli_check_error_code( e_val ); } void bli_obj_create_without_buffer_check( num_t dt, dim_t m, dim_t n, obj_t* obj ) { err_t e_val; e_val = bli_check_valid_datatype( dt ); bli_check_error_code( e_val ); e_val = bli_check_null_pointer( obj ); bli_check_error_code( e_val ); } void bli_obj_alloc_buffer_check( inc_t rs, inc_t cs, inc_t is, obj_t* obj ) { err_t e_val; e_val = bli_check_matrix_strides( bli_obj_length( obj ), bli_obj_width( obj ), rs, cs, is ); bli_check_error_code( e_val ); e_val = bli_check_null_pointer( obj ); bli_check_error_code( e_val ); } void bli_obj_attach_buffer_check( void* p, inc_t rs, inc_t cs, inc_t is, obj_t* obj ) { err_t e_val; // NOTE: We allow the caller to attach NULL to an object because // the buffer contains NULL after _create_wihout_buffer() anyway. // Thus, we're not opening a window for undefined behavior because // that window is already open. Instead of checking for NULL here, // we check the object buffers for all objects in all of the // computational operations' _check()/_int_check() functions. //e_val = bli_check_null_pointer( p ); //bli_check_error_code( e_val ); e_val = bli_check_matrix_strides( bli_obj_length( obj ), bli_obj_width( obj ), rs, cs, is ); bli_check_error_code( e_val ); e_val = bli_check_null_pointer( obj ); bli_check_error_code( e_val ); } void bli_obj_create_scalar_check( num_t dt, obj_t* obj ) { err_t e_val; e_val = bli_check_valid_datatype( dt ); bli_check_error_code( e_val ); e_val = bli_check_null_pointer( obj ); bli_check_error_code( e_val ); } void bli_obj_free_check( obj_t* obj ) { //err_t e_val; // We don't bother checking for null-ness since bli_obj_free() // handles null pointers safely. //e_val = bli_check_null_pointer( obj ); //bli_check_error_code( e_val ); } void bli_obj_create_const_check( double value, obj_t* obj ) { err_t e_val; e_val = bli_check_null_pointer( obj ); bli_check_error_code( e_val ); } #if 0 void bli_obj_create_const_copy_of_check( obj_t* a, obj_t* b ) { err_t e_val; e_val = bli_check_null_pointer( a ); bli_check_error_code( e_val ); e_val = bli_check_null_pointer( b ); bli_check_error_code( e_val ); e_val = bli_check_scalar_object( a ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( a ); bli_check_error_code( e_val ); } #endif void bli_dt_size_check( num_t dt ) { err_t e_val; e_val = bli_check_valid_datatype( dt ); bli_check_error_code( e_val ); } void bli_dt_string_check( num_t dt ) { err_t e_val; e_val = bli_check_nonconstant_datatype( dt ); bli_check_error_code( e_val ); } void bli_dt_union_check( num_t dt1, num_t dt2 ) { err_t e_val; e_val = bli_check_floating_datatype( dt1 ); bli_check_error_code( e_val ); e_val = bli_check_floating_datatype( dt2 ); bli_check_error_code( e_val ); } void bli_obj_print_check( char* label, obj_t* obj ) { err_t e_val; e_val = bli_check_null_pointer( label ); bli_check_error_code( e_val ); e_val = bli_check_null_pointer( obj ); bli_check_error_code( e_val ); } blis-0.9.0/frame/base/check/bli_obj_check.h000066400000000000000000000056251422157504600204560ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void bli_obj_create_check( num_t dt, dim_t m, dim_t n, inc_t rs, inc_t cs, obj_t* obj ); void bli_obj_create_without_buffer_check( num_t dt, dim_t m, dim_t n, obj_t* obj ); void bli_obj_alloc_buffer_check( inc_t rs, inc_t cs, inc_t is, obj_t* obj ); void bli_obj_attach_buffer_check( void* p, inc_t rs, inc_t cs, inc_t is, obj_t* obj ); void bli_obj_create_scalar_check( num_t dt, obj_t* obj ); void bli_obj_free_check( obj_t* obj ); void bli_obj_create_const_check( double value, obj_t* obj ); void bli_obj_create_const_copy_of_check( obj_t* a, obj_t* b ); void bli_dt_size_check( num_t dt ); void bli_dt_string_check( num_t dt ); void bli_dt_union_check( num_t dt1, num_t dt2 ); void bli_obj_print_check( char* label, obj_t* obj ); blis-0.9.0/frame/base/check/bli_part_check.c000066400000000000000000000062771422157504600206510ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_acquire_mpart_t2b_check( subpart_t requested_part, dim_t i, dim_t b, obj_t* obj, obj_t* sub_obj ) { err_t e_val; e_val = bli_check_valid_3x1_subpart( requested_part ); bli_check_error_code( e_val ); e_val = bli_check_null_pointer( obj ); bli_check_error_code( e_val ); e_val = bli_check_null_pointer( sub_obj ); bli_check_error_code( e_val ); } void bli_acquire_mpart_l2r_check( subpart_t requested_part, dim_t j, dim_t b, obj_t* obj, obj_t* sub_obj ) { err_t e_val; e_val = bli_check_valid_1x3_subpart( requested_part ); bli_check_error_code( e_val ); e_val = bli_check_null_pointer( obj ); bli_check_error_code( e_val ); e_val = bli_check_null_pointer( sub_obj ); bli_check_error_code( e_val ); } void bli_acquire_mpart_tl2br_check( subpart_t requested_part, dim_t ij, dim_t b, obj_t* obj, obj_t* sub_obj ) { err_t e_val; e_val = bli_check_valid_3x3_subpart( requested_part ); bli_check_error_code( e_val ); e_val = bli_check_null_pointer( obj ); bli_check_error_code( e_val ); e_val = bli_check_null_pointer( sub_obj ); bli_check_error_code( e_val ); } blis-0.9.0/frame/base/check/bli_part_check.h000066400000000000000000000046541422157504600206530ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void bli_acquire_mpart_t2b_check( subpart_t requested_part, dim_t i, dim_t b, obj_t* obj, obj_t* sub_obj ); void bli_acquire_mpart_l2r_check( subpart_t requested_part, dim_t j, dim_t b, obj_t* obj, obj_t* sub_obj ); void bli_acquire_mpart_tl2br_check( subpart_t requested_part, dim_t ij, dim_t b, obj_t* obj, obj_t* sub_obj ); blis-0.9.0/frame/base/noopt/000077500000000000000000000000001422157504600156225ustar00rootroot00000000000000blis-0.9.0/frame/base/noopt/bli_dlamch.c000066400000000000000000000711621422157504600200530ustar00rootroot00000000000000#include "blis.h" #include #include #include #ifdef __cplusplus extern "C" { #endif #ifdef BLIS_ENABLE_LEGACY_LAMCH double bli_pow_di( bla_double* a, bla_integer* n ); /* Table of constant values */ //static bla_integer c__1 = 1; static bla_double c_b32 = 0.; double bli_pow_di(bla_double *ap, bla_integer *bp) { double pow, x; bla_integer n; unsigned long u; pow = 1; x = *ap; n = *bp; if( n != 0 ) { if( n < 0 ) { n = -n; x = 1/x; } for( u = n; ; ) { if( u & 01 ) pow *= x; if( u >>= 1 ) x *= x; else break; } } return pow; } bla_double bli_dlamch(bla_character *cmach, ftnlen cmach_len) { /* Initialized data */ static bla_logical first = TRUE_; /* System generated locals */ bla_integer i__1; bla_double ret_val; /* Builtin functions */ double bli_pow_di(bla_double *, bla_integer *); /* Local variables */ static bla_double base; static bla_integer beta; static bla_double emin, prec, emax; static bla_integer imin, imax; static bla_logical lrnd; static bla_double rmin, rmax, t, rmach; extern bla_logical bli_lsame(bla_character *, bla_character *, ftnlen, ftnlen); static bla_double smnum, sfmin; extern /* Subroutine */ int bli_dlamc2(bla_integer *, bla_integer *, bla_logical *, bla_double *, bla_integer *, bla_double *, bla_integer *, bla_double *); static bla_integer it; static bla_double rnd, eps; /* -- LAPACK auxiliary routine (version 3.2) -- */ /* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */ /* November 2006 */ /* .. Scalar Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* DLAMCH determines double precision machine parameters. */ /* Arguments */ /* ========= */ /* CMACH (input) CHARACTER*1 */ /* Specifies the value to be returned by DLAMCH: */ /* = 'E' or 'e', DLAMCH := eps */ /* = 'S' or 's , DLAMCH := sfmin */ /* = 'B' or 'b', DLAMCH := base */ /* = 'P' or 'p', DLAMCH := eps*base */ /* = 'N' or 'n', DLAMCH := t */ /* = 'R' or 'r', DLAMCH := rnd */ /* = 'M' or 'm', DLAMCH := emin */ /* = 'U' or 'u', DLAMCH := rmin */ /* = 'L' or 'l', DLAMCH := emax */ /* = 'O' or 'o', DLAMCH := rmax */ /* where */ /* eps = relative machine precision */ /* sfmin = safe minimum, such that 1/sfmin does not overflow */ /* base = base of the machine */ /* prec = eps*base */ /* t = number of (base) digits in the mantissa */ /* rnd = 1.0 when rounding occurs in addition, 0.0 otherwise */ /* emin = minimum exponent before (gradual) underflow */ /* rmin = underflow threshold - base**(emin-1) */ /* emax = largest exponent before overflow */ /* rmax = overflow threshold - (base**emax)*(1-eps) */ /* ===================================================================== */ /* .. Parameters .. */ /* .. */ /* .. Local Scalars .. */ /* .. */ /* .. External Functions .. */ /* .. */ /* .. External Subroutines .. */ /* .. */ /* .. Save statement .. */ /* .. */ /* .. Data statements .. */ /* .. */ /* .. Executable Statements .. */ if (first) { bli_dlamc2(&beta, &it, &lrnd, &eps, &imin, &rmin, &imax, &rmax); base = (bla_double) beta; t = (bla_double) it; if (lrnd) { rnd = 1.; i__1 = 1 - it; eps = bli_pow_di(&base, &i__1) / 2; } else { rnd = 0.; i__1 = 1 - it; eps = bli_pow_di(&base, &i__1); } prec = eps * base; emin = (bla_double) imin; emax = (bla_double) imax; sfmin = rmin; smnum = 1. / rmax; if (smnum >= sfmin) { /* Use SMALL plus a bit, to avoid the possibility of rounding */ /* causing overflow when computing 1/sfmin. */ sfmin = smnum * (eps + 1.); } } if (bli_lsame(cmach, "E", (ftnlen)1, (ftnlen)1)) { rmach = eps; } else if (bli_lsame(cmach, "S", (ftnlen)1, (ftnlen)1)) { rmach = sfmin; } else if (bli_lsame(cmach, "B", (ftnlen)1, (ftnlen)1)) { rmach = base; } else if (bli_lsame(cmach, "P", (ftnlen)1, (ftnlen)1)) { rmach = prec; } else if (bli_lsame(cmach, "N", (ftnlen)1, (ftnlen)1)) { rmach = t; } else if (bli_lsame(cmach, "R", (ftnlen)1, (ftnlen)1)) { rmach = rnd; } else if (bli_lsame(cmach, "M", (ftnlen)1, (ftnlen)1)) { rmach = emin; } else if (bli_lsame(cmach, "U", (ftnlen)1, (ftnlen)1)) { rmach = rmin; } else if (bli_lsame(cmach, "L", (ftnlen)1, (ftnlen)1)) { rmach = emax; } else if (bli_lsame(cmach, "O", (ftnlen)1, (ftnlen)1)) { rmach = rmax; } ret_val = rmach; first = FALSE_; return ret_val; /* End of DLAMCH */ } /* bli_dlamch_ */ /* *********************************************************************** */ /* Subroutine */ int bli_dlamc1(bla_integer *beta, bla_integer *t, bla_logical *rnd, bla_logical *ieee1) { /* Initialized data */ static bla_logical first = TRUE_; /* System generated locals */ bla_double d__1, d__2; /* Local variables */ static bla_logical lrnd; static bla_double a, b, c__, f; static bla_integer lbeta; static bla_double savec; extern bla_double bli_dlamc3(bla_double *, bla_double *); static bla_logical lieee1; static bla_double t1, t2; static bla_integer lt; static bla_double one, qtr; /* -- LAPACK auxiliary routine (version 3.2) -- */ /* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */ /* November 2006 */ /* .. Scalar Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* DLAMC1 determines the machine parameters given by BETA, T, RND, and */ /* IEEE1. */ /* Arguments */ /* ========= */ /* BETA (output) INTEGER */ /* The base of the machine. */ /* T (output) INTEGER */ /* The number of ( BETA ) digits in the mantissa. */ /* RND (output) LOGICAL */ /* Specifies whether proper rounding ( RND = .TRUE. ) or */ /* chopping ( RND = .FALSE. ) occurs in addition. This may not */ /* be a reliable guide to the way in which the machine performs */ /* its arithmetic. */ /* IEEE1 (output) LOGICAL */ /* Specifies whether rounding appears to be done in the IEEE */ /* 'round to nearest' style. */ /* Further Details */ /* =============== */ /* The routine is based on the routine ENVRON by Malcolm and */ /* incorporates suggestions by Gentleman and Marovich. See */ /* Malcolm M. A. (1972) Algorithms to reveal properties of */ /* floating-point arithmetic. Comms. of the ACM, 15, 949-951. */ /* Gentleman W. M. and Marovich S. B. (1974) More on algorithms */ /* that reveal properties of floating point arithmetic units. */ /* Comms. of the ACM, 17, 276-277. */ /* ===================================================================== */ /* .. Local Scalars .. */ /* .. */ /* .. External Functions .. */ /* .. */ /* .. Save statement .. */ /* .. */ /* .. Data statements .. */ /* .. */ /* .. Executable Statements .. */ if (first) { one = 1.; /* LBETA, LIEEE1, LT and LRND are the local values of BETA, */ /* IEEE1, T and RND. */ /* Throughout this routine we use the function DLAMC3 to ensure */ /* that relevant values are stored and not held in registers, or */ /* are not affected by optimizers. */ /* Compute a = 2.0**m with the smallest positive bla_integer m such */ /* that */ /* fl( a + 1.0 ) = a. */ a = 1.; c__ = 1.; /* + WHILE( C.EQ.ONE )LOOP */ L10: if (c__ == one) { a *= 2; c__ = bli_dlamc3(&a, &one); d__1 = -a; c__ = bli_dlamc3(&c__, &d__1); goto L10; } /* + END WHILE */ /* Now compute b = 2.0**m with the smallest positive bla_integer m */ /* such that */ /* fl( a + b ) .gt. a. */ b = 1.; c__ = bli_dlamc3(&a, &b); /* + WHILE( C.EQ.A )LOOP */ L20: if (c__ == a) { b *= 2; c__ = bli_dlamc3(&a, &b); goto L20; } /* + END WHILE */ /* Now compute the base. a and c are neighbouring floating point */ /* numbers in the interval ( beta**t, beta**( t + 1 ) ) and so */ /* their difference is beta. Adding 0.25 to c is to ensure that it */ /* is truncated to beta and not ( beta - 1 ). */ qtr = one / 4; savec = c__; d__1 = -a; c__ = bli_dlamc3(&c__, &d__1); lbeta = (bla_integer) (c__ + qtr); /* Now determine whether rounding or chopping occurs, by adding a */ /* bit less than beta/2 and a bit more than beta/2 to a. */ b = (bla_double) lbeta; d__1 = b / 2; d__2 = -b / 100; f = bli_dlamc3(&d__1, &d__2); c__ = bli_dlamc3(&f, &a); if (c__ == a) { lrnd = TRUE_; } else { lrnd = FALSE_; } d__1 = b / 2; d__2 = b / 100; f = bli_dlamc3(&d__1, &d__2); c__ = bli_dlamc3(&f, &a); if (lrnd && c__ == a) { lrnd = FALSE_; } /* Try and decide whether rounding is done in the IEEE 'round to */ /* nearest' style. B/2 is half a unit in the last place of the two */ /* numbers A and SAVEC. Furthermore, A is even, i.e. has last bit */ /* zero, and SAVEC is odd. Thus adding B/2 to A should not change */ /* A, but adding B/2 to SAVEC should change SAVEC. */ d__1 = b / 2; t1 = bli_dlamc3(&d__1, &a); d__1 = b / 2; t2 = bli_dlamc3(&d__1, &savec); lieee1 = t1 == a && t2 > savec && lrnd; /* Now find the mantissa, t. It should be the bla_integer part of */ /* log to the base beta of a, however it is safer to determine t */ /* by powering. So we find t as the smallest positive bla_integer for */ /* which */ /* fl( beta**t + 1.0 ) = 1.0. */ lt = 0; a = 1.; c__ = 1.; /* + WHILE( C.EQ.ONE )LOOP */ L30: if (c__ == one) { ++lt; a *= lbeta; c__ = bli_dlamc3(&a, &one); d__1 = -a; c__ = bli_dlamc3(&c__, &d__1); goto L30; } /* + END WHILE */ } *beta = lbeta; *t = lt; *rnd = lrnd; *ieee1 = lieee1; first = FALSE_; return 0; /* End of DLAMC1 */ } /* bli_dlamc1_ */ /* *********************************************************************** */ /* Subroutine */ int bli_dlamc2(bla_integer *beta, bla_integer *t, bla_logical *rnd, bla_double *eps, bla_integer *emin, bla_double *rmin, bla_integer *emax, bla_double *rmax) { /* Initialized data */ static bla_logical first = TRUE_; static bla_logical iwarn = FALSE_; /* Format strings */ static bla_character fmt_9999[] = "(//\002 WARNING. The value EMIN may be incorre\ ct:-\002,\002 EMIN = \002,i8,/\002 If, after inspection, the value EMIN loo\ ks\002,\002 acceptable please comment out \002,/\002 the IF block as marked \ within the code of routine\002,\002 DLAMC2,\002,/\002 otherwise supply EMIN \ explicitly.\002,/)"; /* System generated locals */ bla_integer i__1; bla_double d__1, d__2, d__3, d__4, d__5; /* Builtin functions */ double bli_pow_di(bla_double *, bla_integer *); //bla_integer s_wsfe(cilist *), do_fio(bla_integer *, bla_character *, ftnlen), e_wsfe(); /* Local variables */ static bla_logical ieee; static bla_double half; static bla_logical lrnd; static bla_double leps, zero, a, b, c__; static bla_integer i__, lbeta; static bla_double rbase; static bla_integer lemin, lemax, gnmin; static bla_double smnum; static bla_integer gpmin; static bla_double third, lrmin, lrmax, sixth; extern /* Subroutine */ int bli_dlamc1(bla_integer *, bla_integer *, bla_logical *, bla_logical *); extern bla_double bli_dlamc3(bla_double *, bla_double *); static bla_logical lieee1; extern /* Subroutine */ int bli_dlamc4(bla_integer *, bla_double *, bla_integer *), bli_dlamc5(bla_integer *, bla_integer *, bla_integer *, bla_logical *, bla_integer *, bla_double *); static bla_integer lt, ngnmin, ngpmin; static bla_double one, two; /* Fortran I/O blocks */ //static cilist io___58 = { 0, 6, 0, fmt_9999, 0 }; /* -- LAPACK auxiliary routine (version 3.2) -- */ /* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */ /* November 2006 */ /* .. Scalar Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* DLAMC2 determines the machine parameters specified in its argument */ /* list. */ /* Arguments */ /* ========= */ /* BETA (output) INTEGER */ /* The base of the machine. */ /* T (output) INTEGER */ /* The number of ( BETA ) digits in the mantissa. */ /* RND (output) LOGICAL */ /* Specifies whether proper rounding ( RND = .TRUE. ) or */ /* chopping ( RND = .FALSE. ) occurs in addition. This may not */ /* be a reliable guide to the way in which the machine performs */ /* its arithmetic. */ /* EPS (output) DOUBLE PRECISION */ /* The smallest positive number such that */ /* fl( 1.0 - EPS ) .LT. 1.0, */ /* where fl denotes the computed value. */ /* EMIN (output) INTEGER */ /* The minimum exponent before (gradual) underflow occurs. */ /* RMIN (output) DOUBLE PRECISION */ /* The smallest normalized number for the machine, given by */ /* BASE**( EMIN - 1 ), where BASE is the floating point value */ /* of BETA. */ /* EMAX (output) INTEGER */ /* The maximum exponent before overflow occurs. */ /* RMAX (output) DOUBLE PRECISION */ /* The largest positive number for the machine, given by */ /* BASE**EMAX * ( 1 - EPS ), where BASE is the floating point */ /* value of BETA. */ /* Further Details */ /* =============== */ /* The computation of EPS is based on a routine PARANOIA by */ /* W. Kahan of the University of California at Berkeley. */ /* ===================================================================== */ /* .. Local Scalars .. */ /* .. */ /* .. External Functions .. */ /* .. */ /* .. External Subroutines .. */ /* .. */ /* .. Intrinsic Functions .. */ /* .. */ /* .. Save statement .. */ /* .. */ /* .. Data statements .. */ /* .. */ /* .. Executable Statements .. */ if (first) { zero = 0.; one = 1.; two = 2.; /* LBETA, LT, LRND, LEPS, LEMIN and LRMIN are the local values of */ /* BETA, T, RND, EPS, EMIN and RMIN. */ /* Throughout this routine we use the function DLAMC3 to ensure */ /* that relevant values are stored and not held in registers, or */ /* are not affected by optimizers. */ /* DLAMC1 returns the parameters LBETA, LT, LRND and LIEEE1. */ bli_dlamc1(&lbeta, <, &lrnd, &lieee1); /* Start to find EPS. */ b = (bla_double) lbeta; i__1 = -lt; a = bli_pow_di(&b, &i__1); leps = a; /* Try some tricks to see whether or not this is the correct EPS. */ b = two / 3; half = one / 2; d__1 = -half; sixth = bli_dlamc3(&b, &d__1); third = bli_dlamc3(&sixth, &sixth); d__1 = -half; b = bli_dlamc3(&third, &d__1); b = bli_dlamc3(&b, &sixth); b = f2c_abs(b); if (b < leps) { b = leps; } leps = 1.; /* + WHILE( ( LEPS.GT.B ).AND.( B.GT.ZERO ) )LOOP */ L10: if (leps > b && b > zero) { leps = b; d__1 = half * leps; /* Computing 5th power */ d__3 = two, d__4 = d__3, d__3 *= d__3; /* Computing 2nd power */ d__5 = leps; d__2 = d__4 * (d__3 * d__3) * (d__5 * d__5); c__ = bli_dlamc3(&d__1, &d__2); d__1 = -c__; c__ = bli_dlamc3(&half, &d__1); b = bli_dlamc3(&half, &c__); d__1 = -b; c__ = bli_dlamc3(&half, &d__1); b = bli_dlamc3(&half, &c__); goto L10; } /* + END WHILE */ if (a < leps) { leps = a; } /* Computation of EPS complete. */ /* Now find EMIN. Let A = + or - 1, and + or - (1 + BASE**(-3)). */ /* Keep dividing A by BETA until (gradual) underflow occurs. This */ /* is detected when we cannot recover the previous A. */ rbase = one / lbeta; smnum = one; for (i__ = 1; i__ <= 3; ++i__) { d__1 = smnum * rbase; smnum = bli_dlamc3(&d__1, &zero); /* L20: */ } a = bli_dlamc3(&one, &smnum); bli_dlamc4(&ngpmin, &one, &lbeta); d__1 = -one; bli_dlamc4(&ngnmin, &d__1, &lbeta); bli_dlamc4(&gpmin, &a, &lbeta); d__1 = -a; bli_dlamc4(&gnmin, &d__1, &lbeta); ieee = FALSE_; if (ngpmin == ngnmin && gpmin == gnmin) { if (ngpmin == gpmin) { lemin = ngpmin; /* ( Non twos-complement machines, no gradual underflow; */ /* e.g., VAX ) */ } else if (gpmin - ngpmin == 3) { lemin = ngpmin - 1 + lt; ieee = TRUE_; /* ( Non twos-complement machines, with gradual underflow; */ /* e.g., IEEE standard followers ) */ } else { lemin = f2c_min(ngpmin,gpmin); /* ( A guess; no known machine ) */ iwarn = TRUE_; } } else if (ngpmin == gpmin && ngnmin == gnmin) { if ((i__1 = ngpmin - ngnmin, f2c_abs(i__1)) == 1) { lemin = f2c_max(ngpmin,ngnmin); /* ( Twos-complement machines, no gradual underflow; */ /* e.g., CYBER 205 ) */ } else { lemin = f2c_min(ngpmin,ngnmin); /* ( A guess; no known machine ) */ iwarn = TRUE_; } } else if ((i__1 = ngpmin - ngnmin, f2c_abs(i__1)) == 1 && gpmin == gnmin) { if (gpmin - f2c_min(ngpmin,ngnmin) == 3) { lemin = f2c_max(ngpmin,ngnmin) - 1 + lt; /* ( Twos-complement machines with gradual underflow; */ /* no known machine ) */ } else { lemin = f2c_min(ngpmin,ngnmin); /* ( A guess; no known machine ) */ iwarn = TRUE_; } } else { /* Computing MIN */ i__1 = f2c_min(ngpmin,ngnmin), i__1 = f2c_min(i__1,gpmin); lemin = f2c_min(i__1,gnmin); /* ( A guess; no known machine ) */ iwarn = TRUE_; } first = FALSE_; /* ** */ /* Comment out this if block if EMIN is ok */ if (iwarn) { first = TRUE_; /* s_wsfe(&io___58); do_fio(&c__1, (bla_character *)&lemin, (ftnlen)sizeof(bla_integer)); e_wsfe(); */ printf( "%s", fmt_9999 ); } /* ** */ /* Assume IEEE arithmetic if we found denormalised numbers above, */ /* or if arithmetic seems to round in the IEEE style, determined */ /* in routine DLAMC1. A true IEEE machine should have both things */ /* true; however, faulty machines may have one or the other. */ ieee = ieee || lieee1; /* Compute RMIN by successive division by BETA. We could compute */ /* RMIN as BASE**( EMIN - 1 ), but some machines underflow during */ /* this computation. */ lrmin = 1.; i__1 = 1 - lemin; for (i__ = 1; i__ <= i__1; ++i__) { d__1 = lrmin * rbase; lrmin = bli_dlamc3(&d__1, &zero); /* L30: */ } /* Finally, call DLAMC5 to compute EMAX and RMAX. */ bli_dlamc5(&lbeta, <, &lemin, &ieee, &lemax, &lrmax); } *beta = lbeta; *t = lt; *rnd = lrnd; *eps = leps; *emin = lemin; *rmin = lrmin; *emax = lemax; *rmax = lrmax; return 0; /* End of DLAMC2 */ } /* bli_dlamc2_ */ /* *********************************************************************** */ bla_double bli_dlamc3(bla_double *a, bla_double *b) { /* System generated locals */ bla_double ret_val; /* -- LAPACK auxiliary routine (version 3.2) -- */ /* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */ /* November 2006 */ /* .. Scalar Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* DLAMC3 is intended to force A and B to be stored prior to doing */ /* the addition of A and B , for use in situations where optimizers */ /* might hold one of these in a register. */ /* Arguments */ /* ========= */ /* A (input) DOUBLE PRECISION */ /* B (input) DOUBLE PRECISION */ /* The values A and B. */ /* ===================================================================== */ /* .. Executable Statements .. */ ret_val = *a + *b; return ret_val; /* End of DLAMC3 */ } /* bli_dlamc3_ */ /* *********************************************************************** */ /* Subroutine */ int bli_dlamc4(bla_integer *emin, bla_double *start, bla_integer *base) { /* System generated locals */ bla_integer i__1; bla_double d__1; /* Local variables */ static bla_double zero, a; static bla_integer i__; static bla_double rbase, b1, b2, c1, c2, d1, d2; extern bla_double bli_dlamc3(bla_double *, bla_double *); static bla_double one; /* -- LAPACK auxiliary routine (version 3.2) -- */ /* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */ /* November 2006 */ /* .. Scalar Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* DLAMC4 is a service routine for DLAMC2. */ /* Arguments */ /* ========= */ /* EMIN (output) INTEGER */ /* The minimum exponent before (gradual) underflow, computed by */ /* setting A = START and dividing by BASE until the previous A */ /* can not be recovered. */ /* START (input) DOUBLE PRECISION */ /* The starting point for determining EMIN. */ /* BASE (input) INTEGER */ /* The base of the machine. */ /* ===================================================================== */ /* .. Local Scalars .. */ /* .. */ /* .. External Functions .. */ /* .. */ /* .. Executable Statements .. */ a = *start; one = 1.; rbase = one / *base; zero = 0.; *emin = 1; d__1 = a * rbase; b1 = bli_dlamc3(&d__1, &zero); c1 = a; c2 = a; d1 = a; d2 = a; /* + WHILE( ( C1.EQ.A ).AND.( C2.EQ.A ).AND. */ /* $ ( D1.EQ.A ).AND.( D2.EQ.A ) )LOOP */ L10: if (c1 == a && c2 == a && d1 == a && d2 == a) { --(*emin); a = b1; d__1 = a / *base; b1 = bli_dlamc3(&d__1, &zero); d__1 = b1 * *base; c1 = bli_dlamc3(&d__1, &zero); d1 = zero; i__1 = *base; for (i__ = 1; i__ <= i__1; ++i__) { d1 += b1; /* L20: */ } d__1 = a * rbase; b2 = bli_dlamc3(&d__1, &zero); d__1 = b2 / rbase; c2 = bli_dlamc3(&d__1, &zero); d2 = zero; i__1 = *base; for (i__ = 1; i__ <= i__1; ++i__) { d2 += b2; /* L30: */ } goto L10; } /* + END WHILE */ return 0; /* End of DLAMC4 */ } /* bli_dlamc4_ */ /* *********************************************************************** */ /* Subroutine */ int bli_dlamc5(bla_integer *beta, bla_integer *p, bla_integer *emin, bla_logical *ieee, bla_integer *emax, bla_double *rmax) { /* System generated locals */ bla_integer i__1; bla_double d__1; /* Local variables */ static bla_integer lexp; static bla_double oldy; static bla_integer uexp, i__; static bla_double y, z__; static bla_integer nbits; extern bla_double bli_dlamc3(bla_double *, bla_double *); static bla_double recbas; static bla_integer exbits, expsum, try__; /* -- LAPACK auxiliary routine (version 3.2) -- */ /* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */ /* November 2006 */ /* .. Scalar Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* DLAMC5 attempts to compute RMAX, the largest machine floating-point */ /* number, without overflow. It assumes that EMAX + f2c_abs(EMIN) sum */ /* approximately to a power of 2. It will fail on machines where this */ /* assumption does not hold, for example, the Cyber 205 (EMIN = -28625, */ /* EMAX = 28718). It will also fail if the value supplied for EMIN is */ /* too large (i.e. too close to zero), probably with overflow. */ /* Arguments */ /* ========= */ /* BETA (input) INTEGER */ /* The base of floating-point arithmetic. */ /* P (input) INTEGER */ /* The number of base BETA digits in the mantissa of a */ /* floating-point value. */ /* EMIN (input) INTEGER */ /* The minimum exponent before (gradual) underflow. */ /* IEEE (input) LOGICAL */ /* A bla_logical flag specifying whether or not the arithmetic */ /* system is thought to comply with the IEEE standard. */ /* EMAX (output) INTEGER */ /* The largest exponent before overflow */ /* RMAX (output) DOUBLE PRECISION */ /* The largest machine floating-point number. */ /* ===================================================================== */ /* .. Parameters .. */ /* .. */ /* .. Local Scalars .. */ /* .. */ /* .. External Functions .. */ /* .. */ /* .. Intrinsic Functions .. */ /* .. */ /* .. Executable Statements .. */ /* First compute LEXP and UEXP, two powers of 2 that bound */ /* f2c_abs(EMIN). We then assume that EMAX + f2c_abs(EMIN) will sum */ /* approximately to the bound that is closest to f2c_abs(EMIN). */ /* (EMAX is the exponent of the required number RMAX). */ lexp = 1; exbits = 1; L10: try__ = lexp << 1; if (try__ <= -(*emin)) { lexp = try__; ++exbits; goto L10; } if (lexp == -(*emin)) { uexp = lexp; } else { uexp = try__; ++exbits; } /* Now -LEXP is less than or equal to EMIN, and -UEXP is greater */ /* than or equal to EMIN. EXBITS is the number of bits needed to */ /* store the exponent. */ if (uexp + *emin > -lexp - *emin) { expsum = lexp << 1; } else { expsum = uexp << 1; } /* EXPSUM is the exponent range, approximately equal to */ /* EMAX - EMIN + 1 . */ *emax = expsum + *emin - 1; nbits = exbits + 1 + *p; /* NBITS is the total number of bits needed to store a */ /* floating-point number. */ if (nbits % 2 == 1 && *beta == 2) { /* Either there are an odd number of bits used to store a */ /* floating-point number, which is unlikely, or some bits are */ /* not used in the representation of numbers, which is possible, */ /* (e.g. Cray machines) or the mantissa has an implicit bit, */ /* (e.g. IEEE machines, Dec Vax machines), which is perhaps the */ /* most likely. We have to assume the last alternative. */ /* If this is true, then we need to reduce EMAX by one because */ /* there must be some way of representing zero in an implicit-bit */ /* system. On machines like Cray, we are reducing EMAX by one */ /* unnecessarily. */ --(*emax); } if (*ieee) { /* Assume we are on an IEEE machine which reserves one exponent */ /* for infinity and NaN. */ --(*emax); } /* Now create RMAX, the largest machine number, which should */ /* be equal to (1.0 - BETA**(-P)) * BETA**EMAX . */ /* First compute 1.0 - BETA**(-P), being careful that the */ /* result is less than 1.0 . */ recbas = 1. / *beta; z__ = *beta - 1.; y = 0.; i__1 = *p; for (i__ = 1; i__ <= i__1; ++i__) { z__ *= recbas; if (y < 1.) { oldy = y; } y = bli_dlamc3(&y, &z__); /* L20: */ } if (y >= 1.) { y = oldy; } /* Now multiply by BETA**EMAX to get RMAX. */ i__1 = *emax; for (i__ = 1; i__ <= i__1; ++i__) { d__1 = y * *beta; y = bli_dlamc3(&d__1, &c_b32); /* L30: */ } *rmax = y; return 0; /* End of DLAMC5 */ } /* bli_dlamc5_ */ #else bla_double bli_dlamch(bla_character *cmach, ftnlen cmach_len) { /* = 'E' or 'e', DLAMCH := eps */ /* = 'S' or 's , DLAMCH := sfmin */ /* = 'B' or 'b', DLAMCH := base */ /* = 'P' or 'p', DLAMCH := eps*base */ /* = 'N' or 'n', DLAMCH := t */ /* = 'R' or 'r', DLAMCH := rnd */ /* = 'M' or 'm', DLAMCH := emin */ /* = 'U' or 'u', DLAMCH := rmin */ /* = 'L' or 'l', DLAMCH := emax */ /* = 'O' or 'o', DLAMCH := rmax */ /* where */ /* eps = relative machine precision */ /* sfmin = safe minimum, such that 1/sfmin does not overflow */ /* base = base of the machine */ /* prec = eps*base */ /* t = number of (base) digits in the mantissa */ /* rnd = 1.0 when rounding occurs in addition, 0.0 otherwise */ /* emin = minimum exponent before (gradual) underflow */ /* rmin = underflow threshold - base**(emin-1) */ /* emax = largest exponent before overflow */ /* rmax = overflow threshold - (base**emax)*(1-eps) */ double safe_min = DBL_MIN; double small = 1.0f / DBL_MAX; if ( small >= safe_min ) safe_min = small * ( 1.0 + DBL_EPSILON ); switch ( toupper( *cmach ) ) { case 'E': return DBL_EPSILON; case 'S': return safe_min; case 'B': return FLT_RADIX; case 'P': return FLT_RADIX*DBL_EPSILON; case 'N': return DBL_MANT_DIG; case 'R': return FLT_ROUNDS == FE_TONEAREST ? 1.0 : 0.0; case 'M': return DBL_MIN_EXP; case 'U': return DBL_MIN; case 'L': return DBL_MAX_EXP; case 'O': return DBL_MAX; } return 0.0; } #endif #ifdef __cplusplus } #endif blis-0.9.0/frame/base/noopt/bli_dlamch.h000066400000000000000000000033121422157504600200500ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ bla_double bli_dlamch( bla_character* cmach, ftnlen cmach_len ); blis-0.9.0/frame/base/noopt/bli_lsame.c000066400000000000000000000053551422157504600177250ustar00rootroot00000000000000/* lsame.f -- translated by f2c (version 19991025). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ #ifdef __cplusplus extern "C" { #endif #include "blis.h" bla_logical bli_lsame(bla_character *ca, bla_character *cb, ftnlen ca_len, ftnlen cb_len) { /* System generated locals */ bla_logical ret_val; /* Local variables */ static bla_integer inta, intb, zcode; /* -- LAPACK auxiliary routine (version 3.2) -- */ /* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */ /* November 2006 */ /* .. Scalar Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* LSAME returns .TRUE. if CA is the same letter as CB regardless of */ /* case. */ /* Arguments */ /* ========= */ /* CA (input) CHARACTER*1 */ /* CB (input) CHARACTER*1 */ /* CA and CB specify the single bla_characters to be compared. */ /* ===================================================================== */ /* .. Intrinsic Functions .. */ /* .. */ /* .. Local Scalars .. */ /* .. */ /* .. Executable Statements .. */ /* Test if the bla_characters are equal */ ret_val = *(unsigned char *)ca == *(unsigned char *)cb; if (ret_val) { return ret_val; } /* Now test for equivalence if both bla_characters are alphabetic. */ zcode = 'Z'; /* Use 'Z' rather than 'A' so that ASCII can be detected on Prime */ /* machines, on which ICHAR returns a value with bit 8 set. */ /* ICHAR('A') on Prime machines returns 193 which is the same as */ /* ICHAR('A') on an EBCDIC machine. */ inta = *(unsigned char *)ca; intb = *(unsigned char *)cb; if (zcode == 90 || zcode == 122) { /* ASCII is assumed - ZCODE is the ASCII code of either lower or */ /* upper case 'Z'. */ if (inta >= 97 && inta <= 122) { inta += -32; } if (intb >= 97 && intb <= 122) { intb += -32; } } else if (zcode == 233 || zcode == 169) { /* EBCDIC is assumed - ZCODE is the EBCDIC code of either lower or */ /* upper case 'Z'. */ if ((inta >= 129 && inta <= 137) || (inta >= 145 && inta <= 153) || (inta >= 162 && inta <= 169)) { inta += 64; } if ((intb >= 129 && intb <= 137) || (intb >= 145 && intb <= 153) || (intb >= 162 && intb <= 169)) { intb += 64; } } else if (zcode == 218 || zcode == 250) { /* ASCII is assumed, on Prime machines - ZCODE is the ASCII code */ /* plus 128 of either lower or upper case 'Z'. */ if (inta >= 225 && inta <= 250) { inta += -32; } if (intb >= 225 && intb <= 250) { intb += -32; } } ret_val = inta == intb; /* RETURN */ /* End of LSAME */ return ret_val; } /* bli_lsame */ #ifdef __cplusplus } #endif blis-0.9.0/frame/base/noopt/bli_lsame.h000066400000000000000000000033461422157504600177300ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ bla_logical bli_lsame( bla_character* ca, bla_character* cb, ftnlen ca_len, ftnlen cb_len ); blis-0.9.0/frame/base/noopt/bli_slamch.c000066400000000000000000000710531422157504600200710ustar00rootroot00000000000000#include "blis.h" #include #include #include #ifdef __cplusplus extern "C" { #endif #ifdef BLIS_ENABLE_LEGACY_LAMCH double bli_pow_ri( bla_real* a, bla_integer* n ); /* Table of constant values */ //static bla_integer c__1 = 1; static bla_real c_b32 = (float)0.; double bli_pow_ri(bla_real *ap, bla_integer *bp) { double pow, x; bla_integer n; unsigned long u; pow = 1; x = *ap; n = *bp; if( n != 0 ) { if( n < 0 ) { n = -n; x = 1/x; } for( u = n; ; ) { if( u & 01 ) pow *= x; if( u >>= 1 ) x *= x; else break; } } return pow; } bla_real bli_slamch(bla_character *cmach, ftnlen cmach_len) { /* Initialized data */ static bla_logical first = TRUE_; /* System generated locals */ bla_integer i__1; bla_real ret_val; /* Builtin functions */ double bli_pow_ri(bla_real *, bla_integer *); /* Local variables */ static bla_real base; static bla_integer beta; static bla_real emin, prec, emax; static bla_integer imin, imax; static bla_logical lrnd; static bla_real rmin, rmax, t, rmach; extern bla_logical bli_lsame(bla_character *, bla_character *, ftnlen, ftnlen); static bla_real smnum, sfmin; extern /* Subroutine */ int bli_slamc2(bla_integer *, bla_integer *, bla_logical *, bla_real *, bla_integer *, bla_real *, bla_integer *, bla_real *); static bla_integer it; static bla_real rnd, eps; /* -- LAPACK auxiliary routine (version 3.2) -- */ /* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */ /* November 2006 */ /* .. Scalar Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* SLAMCH determines single precision machine parameters. */ /* Arguments */ /* ========= */ /* CMACH (input) CHARACTER*1 */ /* Specifies the value to be returned by SLAMCH: */ /* = 'E' or 'e', SLAMCH := eps */ /* = 'S' or 's , SLAMCH := sfmin */ /* = 'B' or 'b', SLAMCH := base */ /* = 'P' or 'p', SLAMCH := eps*base */ /* = 'N' or 'n', SLAMCH := t */ /* = 'R' or 'r', SLAMCH := rnd */ /* = 'M' or 'm', SLAMCH := emin */ /* = 'U' or 'u', SLAMCH := rmin */ /* = 'L' or 'l', SLAMCH := emax */ /* = 'O' or 'o', SLAMCH := rmax */ /* where */ /* eps = relative machine precision */ /* sfmin = safe minimum, such that 1/sfmin does not overflow */ /* base = base of the machine */ /* prec = eps*base */ /* t = number of (base) digits in the mantissa */ /* rnd = 1.0 when rounding occurs in addition, 0.0 otherwise */ /* emin = minimum exponent before (gradual) underflow */ /* rmin = underflow threshold - base**(emin-1) */ /* emax = largest exponent before overflow */ /* rmax = overflow threshold - (base**emax)*(1-eps) */ /* ===================================================================== */ /* .. Parameters .. */ /* .. */ /* .. Local Scalars .. */ /* .. */ /* .. External Functions .. */ /* .. */ /* .. External Subroutines .. */ /* .. */ /* .. Save statement .. */ /* .. */ /* .. Data statements .. */ /* .. */ /* .. Executable Statements .. */ if (first) { bli_slamc2(&beta, &it, &lrnd, &eps, &imin, &rmin, &imax, &rmax); base = (bla_real) beta; t = (bla_real) it; if (lrnd) { rnd = (float)1.; i__1 = 1 - it; eps = bli_pow_ri(&base, &i__1) / 2; } else { rnd = (float)0.; i__1 = 1 - it; eps = bli_pow_ri(&base, &i__1); } prec = eps * base; emin = (bla_real) imin; emax = (bla_real) imax; sfmin = rmin; smnum = (float)1. / rmax; if (smnum >= sfmin) { /* Use SMALL plus a bit, to avoid the possibility of rounding */ /* causing overflow when computing 1/sfmin. */ sfmin = smnum * (eps + (float)1.); } } if (bli_lsame(cmach, "E", (ftnlen)1, (ftnlen)1)) { rmach = eps; } else if (bli_lsame(cmach, "S", (ftnlen)1, (ftnlen)1)) { rmach = sfmin; } else if (bli_lsame(cmach, "B", (ftnlen)1, (ftnlen)1)) { rmach = base; } else if (bli_lsame(cmach, "P", (ftnlen)1, (ftnlen)1)) { rmach = prec; } else if (bli_lsame(cmach, "N", (ftnlen)1, (ftnlen)1)) { rmach = t; } else if (bli_lsame(cmach, "R", (ftnlen)1, (ftnlen)1)) { rmach = rnd; } else if (bli_lsame(cmach, "M", (ftnlen)1, (ftnlen)1)) { rmach = emin; } else if (bli_lsame(cmach, "U", (ftnlen)1, (ftnlen)1)) { rmach = rmin; } else if (bli_lsame(cmach, "L", (ftnlen)1, (ftnlen)1)) { rmach = emax; } else if (bli_lsame(cmach, "O", (ftnlen)1, (ftnlen)1)) { rmach = rmax; } ret_val = rmach; first = FALSE_; return ret_val; /* End of SLAMCH */ } /* bli_slamch_ */ /* *********************************************************************** */ /* Subroutine */ int bli_slamc1(bla_integer *beta, bla_integer *t, bla_logical *rnd, bla_logical *ieee1) { /* Initialized data */ static bla_logical first = TRUE_; /* System generated locals */ bla_real r__1, r__2; /* Local variables */ static bla_logical lrnd; static bla_real a, b, c__, f; static bla_integer lbeta; static bla_real savec; static bla_logical lieee1; static bla_real t1, t2; extern bla_real bli_slamc3(bla_real *, bla_real *); static bla_integer lt; static bla_real one, qtr; /* -- LAPACK auxiliary routine (version 3.2) -- */ /* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */ /* November 2006 */ /* .. Scalar Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* SLAMC1 determines the machine parameters given by BETA, T, RND, and */ /* IEEE1. */ /* Arguments */ /* ========= */ /* BETA (output) INTEGER */ /* The base of the machine. */ /* T (output) INTEGER */ /* The number of ( BETA ) digits in the mantissa. */ /* RND (output) LOGICAL */ /* Specifies whether proper rounding ( RND = .TRUE. ) or */ /* chopping ( RND = .FALSE. ) occurs in addition. This may not */ /* be a reliable guide to the way in which the machine performs */ /* its arithmetic. */ /* IEEE1 (output) LOGICAL */ /* Specifies whether rounding appears to be done in the IEEE */ /* 'round to nearest' style. */ /* Further Details */ /* =============== */ /* The routine is based on the routine ENVRON by Malcolm and */ /* incorporates suggestions by Gentleman and Marovich. See */ /* Malcolm M. A. (1972) Algorithms to reveal properties of */ /* floating-point arithmetic. Comms. of the ACM, 15, 949-951. */ /* Gentleman W. M. and Marovich S. B. (1974) More on algorithms */ /* that reveal properties of floating point arithmetic units. */ /* Comms. of the ACM, 17, 276-277. */ /* ===================================================================== */ /* .. Local Scalars .. */ /* .. */ /* .. External Functions .. */ /* .. */ /* .. Save statement .. */ /* .. */ /* .. Data statements .. */ /* .. */ /* .. Executable Statements .. */ if (first) { one = (float)1.; /* LBETA, LIEEE1, LT and LRND are the local values of BETA, */ /* IEEE1, T and RND. */ /* Throughout this routine we use the function SLAMC3 to ensure */ /* that relevant values are stored and not held in registers, or */ /* are not affected by optimizers. */ /* Compute a = 2.0**m with the smallest positive bla_integer m such */ /* that */ /* fl( a + 1.0 ) = a. */ a = (float)1.; c__ = (float)1.; /* + WHILE( C.EQ.ONE )LOOP */ L10: if (c__ == one) { a *= 2; c__ = bli_slamc3(&a, &one); r__1 = -a; c__ = bli_slamc3(&c__, &r__1); goto L10; } /* + END WHILE */ /* Now compute b = 2.0**m with the smallest positive bla_integer m */ /* such that */ /* fl( a + b ) .gt. a. */ b = (float)1.; c__ = bli_slamc3(&a, &b); /* + WHILE( C.EQ.A )LOOP */ L20: if (c__ == a) { b *= 2; c__ = bli_slamc3(&a, &b); goto L20; } /* + END WHILE */ /* Now compute the base. a and c are neighbouring floating point */ /* numbers in the interval ( beta**t, beta**( t + 1 ) ) and so */ /* their difference is beta. Adding 0.25 to c is to ensure that it */ /* is truncated to beta and not ( beta - 1 ). */ qtr = one / 4; savec = c__; r__1 = -a; c__ = bli_slamc3(&c__, &r__1); lbeta = c__ + qtr; /* Now determine whether rounding or chopping occurs, by adding a */ /* bit less than beta/2 and a bit more than beta/2 to a. */ b = (bla_real) lbeta; r__1 = b / 2; r__2 = -b / 100; f = bli_slamc3(&r__1, &r__2); c__ = bli_slamc3(&f, &a); if (c__ == a) { lrnd = TRUE_; } else { lrnd = FALSE_; } r__1 = b / 2; r__2 = b / 100; f = bli_slamc3(&r__1, &r__2); c__ = bli_slamc3(&f, &a); if (lrnd && c__ == a) { lrnd = FALSE_; } /* Try and decide whether rounding is done in the IEEE 'round to */ /* nearest' style. B/2 is half a unit in the last place of the two */ /* numbers A and SAVEC. Furthermore, A is even, i.e. has last bit */ /* zero, and SAVEC is odd. Thus adding B/2 to A should not change */ /* A, but adding B/2 to SAVEC should change SAVEC. */ r__1 = b / 2; t1 = bli_slamc3(&r__1, &a); r__1 = b / 2; t2 = bli_slamc3(&r__1, &savec); lieee1 = t1 == a && t2 > savec && lrnd; /* Now find the mantissa, t. It should be the bla_integer part of */ /* log to the base beta of a, however it is safer to determine t */ /* by powering. So we find t as the smallest positive bla_integer for */ /* which */ /* fl( beta**t + 1.0 ) = 1.0. */ lt = 0; a = (float)1.; c__ = (float)1.; /* + WHILE( C.EQ.ONE )LOOP */ L30: if (c__ == one) { ++lt; a *= lbeta; c__ = bli_slamc3(&a, &one); r__1 = -a; c__ = bli_slamc3(&c__, &r__1); goto L30; } /* + END WHILE */ } *beta = lbeta; *t = lt; *rnd = lrnd; *ieee1 = lieee1; first = FALSE_; return 0; /* End of SLAMC1 */ } /* bli_slamc1_ */ /* *********************************************************************** */ /* Subroutine */ int bli_slamc2(bla_integer *beta, bla_integer *t, bla_logical *rnd, bla_real * eps, bla_integer *emin, bla_real *rmin, bla_integer *emax, bla_real *rmax) { /* Initialized data */ static bla_logical first = TRUE_; static bla_logical iwarn = FALSE_; /* Format strings */ static bla_character fmt_9999[] = "(//\002 WARNING. The value EMIN may be incorre\ ct:-\002,\002 EMIN = \002,i8,/\002 If, after inspection, the value EMIN loo\ ks\002,\002 acceptable please comment out \002,/\002 the IF block as marked \ within the code of routine\002,\002 SLAMC2,\002,/\002 otherwise supply EMIN \ explicitly.\002,/)"; /* System generated locals */ bla_integer i__1; bla_real r__1, r__2, r__3, r__4, r__5; /* Builtin functions */ double bli_pow_ri(bla_real *, bla_integer *); //bla_integer s_wsfe(cilist *), do_fio(bla_integer *, bla_character *, ftnlen), e_wsfe(); /* Local variables */ static bla_logical ieee; static bla_real half; static bla_logical lrnd; static bla_real leps, zero, a, b, c__; static bla_integer i__, lbeta; static bla_real rbase; static bla_integer lemin, lemax, gnmin; static bla_real smnum; static bla_integer gpmin; static bla_real third, lrmin, lrmax, sixth; static bla_logical lieee1; extern /* Subroutine */ int bli_slamc1(bla_integer *, bla_integer *, bla_logical *, bla_logical *); extern bla_real bli_slamc3(bla_real *, bla_real *); extern /* Subroutine */ int bli_slamc4(bla_integer *, bla_real *, bla_integer *), bli_slamc5(bla_integer *, bla_integer *, bla_integer *, bla_logical *, bla_integer *, bla_real *); static bla_integer lt, ngnmin, ngpmin; static bla_real one, two; /* Fortran I/O blocks */ //static cilist io___58 = { 0, 6, 0, fmt_9999, 0 }; /* -- LAPACK auxiliary routine (version 3.2) -- */ /* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */ /* November 2006 */ /* .. Scalar Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* SLAMC2 determines the machine parameters specified in its argument */ /* list. */ /* Arguments */ /* ========= */ /* BETA (output) INTEGER */ /* The base of the machine. */ /* T (output) INTEGER */ /* The number of ( BETA ) digits in the mantissa. */ /* RND (output) LOGICAL */ /* Specifies whether proper rounding ( RND = .TRUE. ) or */ /* chopping ( RND = .FALSE. ) occurs in addition. This may not */ /* be a reliable guide to the way in which the machine performs */ /* its arithmetic. */ /* EPS (output) REAL */ /* The smallest positive number such that */ /* fl( 1.0 - EPS ) .LT. 1.0, */ /* where fl denotes the computed value. */ /* EMIN (output) INTEGER */ /* The minimum exponent before (gradual) underflow occurs. */ /* RMIN (output) REAL */ /* The smallest normalized number for the machine, given by */ /* BASE**( EMIN - 1 ), where BASE is the floating point value */ /* of BETA. */ /* EMAX (output) INTEGER */ /* The maximum exponent before overflow occurs. */ /* RMAX (output) REAL */ /* The largest positive number for the machine, given by */ /* BASE**EMAX * ( 1 - EPS ), where BASE is the floating point */ /* value of BETA. */ /* Further Details */ /* =============== */ /* The computation of EPS is based on a routine PARANOIA by */ /* W. Kahan of the University of California at Berkeley. */ /* ===================================================================== */ /* .. Local Scalars .. */ /* .. */ /* .. External Functions .. */ /* .. */ /* .. External Subroutines .. */ /* .. */ /* .. Intrinsic Functions .. */ /* .. */ /* .. Save statement .. */ /* .. */ /* .. Data statements .. */ /* .. */ /* .. Executable Statements .. */ if (first) { zero = (float)0.; one = (float)1.; two = (float)2.; /* LBETA, LT, LRND, LEPS, LEMIN and LRMIN are the local values of */ /* BETA, T, RND, EPS, EMIN and RMIN. */ /* Throughout this routine we use the function SLAMC3 to ensure */ /* that relevant values are stored and not held in registers, or */ /* are not affected by optimizers. */ /* SLAMC1 returns the parameters LBETA, LT, LRND and LIEEE1. */ bli_slamc1(&lbeta, <, &lrnd, &lieee1); /* Start to find EPS. */ b = (bla_real) lbeta; i__1 = -lt; a = bli_pow_ri(&b, &i__1); leps = a; /* Try some tricks to see whether or not this is the correct EPS. */ b = two / 3; half = one / 2; r__1 = -half; sixth = bli_slamc3(&b, &r__1); third = bli_slamc3(&sixth, &sixth); r__1 = -half; b = bli_slamc3(&third, &r__1); b = bli_slamc3(&b, &sixth); b = f2c_abs(b); if (b < leps) { b = leps; } leps = (float)1.; /* + WHILE( ( LEPS.GT.B ).AND.( B.GT.ZERO ) )LOOP */ L10: if (leps > b && b > zero) { leps = b; r__1 = half * leps; /* Computing 5th power */ r__3 = two, r__4 = r__3, r__3 *= r__3; /* Computing 2nd power */ r__5 = leps; r__2 = r__4 * (r__3 * r__3) * (r__5 * r__5); c__ = bli_slamc3(&r__1, &r__2); r__1 = -c__; c__ = bli_slamc3(&half, &r__1); b = bli_slamc3(&half, &c__); r__1 = -b; c__ = bli_slamc3(&half, &r__1); b = bli_slamc3(&half, &c__); goto L10; } /* + END WHILE */ if (a < leps) { leps = a; } /* Computation of EPS complete. */ /* Now find EMIN. Let A = + or - 1, and + or - (1 + BASE**(-3)). */ /* Keep dividing A by BETA until (gradual) underflow occurs. This */ /* is detected when we cannot recover the previous A. */ rbase = one / lbeta; smnum = one; for (i__ = 1; i__ <= 3; ++i__) { r__1 = smnum * rbase; smnum = bli_slamc3(&r__1, &zero); /* L20: */ } a = bli_slamc3(&one, &smnum); bli_slamc4(&ngpmin, &one, &lbeta); r__1 = -one; bli_slamc4(&ngnmin, &r__1, &lbeta); bli_slamc4(&gpmin, &a, &lbeta); r__1 = -a; bli_slamc4(&gnmin, &r__1, &lbeta); ieee = FALSE_; if (ngpmin == ngnmin && gpmin == gnmin) { if (ngpmin == gpmin) { lemin = ngpmin; /* ( Non twos-complement machines, no gradual underflow; */ /* e.g., VAX ) */ } else if (gpmin - ngpmin == 3) { lemin = ngpmin - 1 + lt; ieee = TRUE_; /* ( Non twos-complement machines, with gradual underflow; */ /* e.g., IEEE standard followers ) */ } else { lemin = f2c_min(ngpmin,gpmin); /* ( A guess; no known machine ) */ iwarn = TRUE_; } } else if (ngpmin == gpmin && ngnmin == gnmin) { if ((i__1 = ngpmin - ngnmin, f2c_abs(i__1)) == 1) { lemin = f2c_max(ngpmin,ngnmin); /* ( Twos-complement machines, no gradual underflow; */ /* e.g., CYBER 205 ) */ } else { lemin = f2c_min(ngpmin,ngnmin); /* ( A guess; no known machine ) */ iwarn = TRUE_; } } else if ((i__1 = ngpmin - ngnmin, f2c_abs(i__1)) == 1 && gpmin == gnmin) { if (gpmin - f2c_min(ngpmin,ngnmin) == 3) { lemin = f2c_max(ngpmin,ngnmin) - 1 + lt; /* ( Twos-complement machines with gradual underflow; */ /* no known machine ) */ } else { lemin = f2c_min(ngpmin,ngnmin); /* ( A guess; no known machine ) */ iwarn = TRUE_; } } else { /* Computing MIN */ i__1 = f2c_min(ngpmin,ngnmin), i__1 = f2c_min(i__1,gpmin); lemin = f2c_min(i__1,gnmin); /* ( A guess; no known machine ) */ iwarn = TRUE_; } first = FALSE_; /* ** */ /* Comment out this if block if EMIN is ok */ if (iwarn) { first = TRUE_; /* s_wsfe(&io___58); do_fio(&c__1, (bla_character *)&lemin, (ftnlen)sizeof(bla_integer)); e_wsfe(); */ printf( "%s", fmt_9999 ); } /* ** */ /* Assume IEEE arithmetic if we found denormalised numbers above, */ /* or if arithmetic seems to round in the IEEE style, determined */ /* in routine SLAMC1. A true IEEE machine should have both things */ /* true; however, faulty machines may have one or the other. */ ieee = ieee || lieee1; /* Compute RMIN by successive division by BETA. We could compute */ /* RMIN as BASE**( EMIN - 1 ), but some machines underflow during */ /* this computation. */ lrmin = (float)1.; i__1 = 1 - lemin; for (i__ = 1; i__ <= i__1; ++i__) { r__1 = lrmin * rbase; lrmin = bli_slamc3(&r__1, &zero); /* L30: */ } /* Finally, call SLAMC5 to compute EMAX and RMAX. */ bli_slamc5(&lbeta, <, &lemin, &ieee, &lemax, &lrmax); } *beta = lbeta; *t = lt; *rnd = lrnd; *eps = leps; *emin = lemin; *rmin = lrmin; *emax = lemax; *rmax = lrmax; return 0; /* End of SLAMC2 */ } /* bli_slamc2_ */ /* *********************************************************************** */ bla_real bli_slamc3(bla_real *a, bla_real *b) { /* System generated locals */ bla_real ret_val; /* -- LAPACK auxiliary routine (version 3.2) -- */ /* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */ /* November 2006 */ /* .. Scalar Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* SLAMC3 is intended to force A and B to be stored prior to doing */ /* the addition of A and B , for use in situations where optimizers */ /* might hold one of these in a register. */ /* Arguments */ /* ========= */ /* A (input) REAL */ /* B (input) REAL */ /* The values A and B. */ /* ===================================================================== */ /* .. Executable Statements .. */ ret_val = *a + *b; return ret_val; /* End of SLAMC3 */ } /* bli_slamc3_ */ /* *********************************************************************** */ /* Subroutine */ int bli_slamc4(bla_integer *emin, bla_real *start, bla_integer *base) { /* System generated locals */ bla_integer i__1; bla_real r__1; /* Local variables */ static bla_real zero, a; static bla_integer i__; static bla_real rbase, b1, b2, c1, c2, d1, d2; extern bla_real bli_slamc3(bla_real *, bla_real *); static bla_real one; /* -- LAPACK auxiliary routine (version 3.2) -- */ /* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */ /* November 2006 */ /* .. Scalar Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* SLAMC4 is a service routine for SLAMC2. */ /* Arguments */ /* ========= */ /* EMIN (output) INTEGER */ /* The minimum exponent before (gradual) underflow, computed by */ /* setting A = START and dividing by BASE until the previous A */ /* can not be recovered. */ /* START (input) REAL */ /* The starting point for determining EMIN. */ /* BASE (input) INTEGER */ /* The base of the machine. */ /* ===================================================================== */ /* .. Local Scalars .. */ /* .. */ /* .. External Functions .. */ /* .. */ /* .. Executable Statements .. */ a = *start; one = (float)1.; rbase = one / *base; zero = (float)0.; *emin = 1; r__1 = a * rbase; b1 = bli_slamc3(&r__1, &zero); c1 = a; c2 = a; d1 = a; d2 = a; /* + WHILE( ( C1.EQ.A ).AND.( C2.EQ.A ).AND. */ /* $ ( D1.EQ.A ).AND.( D2.EQ.A ) )LOOP */ L10: if (c1 == a && c2 == a && d1 == a && d2 == a) { --(*emin); a = b1; r__1 = a / *base; b1 = bli_slamc3(&r__1, &zero); r__1 = b1 * *base; c1 = bli_slamc3(&r__1, &zero); d1 = zero; i__1 = *base; for (i__ = 1; i__ <= i__1; ++i__) { d1 += b1; /* L20: */ } r__1 = a * rbase; b2 = bli_slamc3(&r__1, &zero); r__1 = b2 / rbase; c2 = bli_slamc3(&r__1, &zero); d2 = zero; i__1 = *base; for (i__ = 1; i__ <= i__1; ++i__) { d2 += b2; /* L30: */ } goto L10; } /* + END WHILE */ return 0; /* End of SLAMC4 */ } /* bli_slamc4_ */ /* *********************************************************************** */ /* Subroutine */ int bli_slamc5(bla_integer *beta, bla_integer *p, bla_integer *emin, bla_logical *ieee, bla_integer *emax, bla_real *rmax) { /* System generated locals */ bla_integer i__1; bla_real r__1; /* Local variables */ static bla_integer lexp; static bla_real oldy; static bla_integer uexp, i__; static bla_real y, z__; static bla_integer nbits; extern bla_real bli_slamc3(bla_real *, bla_real *); static bla_real recbas; static bla_integer exbits, expsum, try__; /* -- LAPACK auxiliary routine (version 3.2) -- */ /* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */ /* November 2006 */ /* .. Scalar Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* SLAMC5 attempts to compute RMAX, the largest machine floating-point */ /* number, without overflow. It assumes that EMAX + f2c_abs(EMIN) sum */ /* approximately to a power of 2. It will fail on machines where this */ /* assumption does not hold, for example, the Cyber 205 (EMIN = -28625, */ /* EMAX = 28718). It will also fail if the value supplied for EMIN is */ /* too large (i.e. too close to zero), probably with overflow. */ /* Arguments */ /* ========= */ /* BETA (input) INTEGER */ /* The base of floating-point arithmetic. */ /* P (input) INTEGER */ /* The number of base BETA digits in the mantissa of a */ /* floating-point value. */ /* EMIN (input) INTEGER */ /* The minimum exponent before (gradual) underflow. */ /* IEEE (input) LOGICAL */ /* A bla_logical flag specifying whether or not the arithmetic */ /* system is thought to comply with the IEEE standard. */ /* EMAX (output) INTEGER */ /* The largest exponent before overflow */ /* RMAX (output) REAL */ /* The largest machine floating-point number. */ /* ===================================================================== */ /* .. Parameters .. */ /* .. */ /* .. Local Scalars .. */ /* .. */ /* .. External Functions .. */ /* .. */ /* .. Intrinsic Functions .. */ /* .. */ /* .. Executable Statements .. */ /* First compute LEXP and UEXP, two powers of 2 that bound */ /* f2c_abs(EMIN). We then assume that EMAX + f2c_abs(EMIN) will sum */ /* approximately to the bound that is closest to f2c_abs(EMIN). */ /* (EMAX is the exponent of the required number RMAX). */ lexp = 1; exbits = 1; L10: try__ = lexp << 1; if (try__ <= -(*emin)) { lexp = try__; ++exbits; goto L10; } if (lexp == -(*emin)) { uexp = lexp; } else { uexp = try__; ++exbits; } /* Now -LEXP is less than or equal to EMIN, and -UEXP is greater */ /* than or equal to EMIN. EXBITS is the number of bits needed to */ /* store the exponent. */ if (uexp + *emin > -lexp - *emin) { expsum = lexp << 1; } else { expsum = uexp << 1; } /* EXPSUM is the exponent range, approximately equal to */ /* EMAX - EMIN + 1 . */ *emax = expsum + *emin - 1; nbits = exbits + 1 + *p; /* NBITS is the total number of bits needed to store a */ /* floating-point number. */ if (nbits % 2 == 1 && *beta == 2) { /* Either there are an odd number of bits used to store a */ /* floating-point number, which is unlikely, or some bits are */ /* not used in the representation of numbers, which is possible, */ /* (e.g. Cray machines) or the mantissa has an implicit bit, */ /* (e.g. IEEE machines, Dec Vax machines), which is perhaps the */ /* most likely. We have to assume the last alternative. */ /* If this is true, then we need to reduce EMAX by one because */ /* there must be some way of representing zero in an implicit-bit */ /* system. On machines like Cray, we are reducing EMAX by one */ /* unnecessarily. */ --(*emax); } if (*ieee) { /* Assume we are on an IEEE machine which reserves one exponent */ /* for infinity and NaN. */ --(*emax); } /* Now create RMAX, the largest machine number, which should */ /* be equal to (1.0 - BETA**(-P)) * BETA**EMAX . */ /* First compute 1.0 - BETA**(-P), being careful that the */ /* result is less than 1.0 . */ recbas = (float)1. / *beta; z__ = *beta - (float)1.; y = (float)0.; i__1 = *p; for (i__ = 1; i__ <= i__1; ++i__) { z__ *= recbas; if (y < (float)1.) { oldy = y; } y = bli_slamc3(&y, &z__); /* L20: */ } if (y >= (float)1.) { y = oldy; } /* Now multiply by BETA**EMAX to get RMAX. */ i__1 = *emax; for (i__ = 1; i__ <= i__1; ++i__) { r__1 = y * *beta; y = bli_slamc3(&r__1, &c_b32); /* L30: */ } *rmax = y; return 0; /* End of SLAMC5 */ } /* bli_slamc5_ */ #else bla_real bli_slamch(bla_character *cmach, ftnlen cmach_len) { /* = 'E' or 'e', SLAMCH := eps */ /* = 'S' or 's , SLAMCH := sfmin */ /* = 'B' or 'b', SLAMCH := base */ /* = 'P' or 'p', SLAMCH := eps*base */ /* = 'N' or 'n', SLAMCH := t */ /* = 'R' or 'r', SLAMCH := rnd */ /* = 'M' or 'm', SLAMCH := emin */ /* = 'U' or 'u', SLAMCH := rmin */ /* = 'L' or 'l', SLAMCH := emax */ /* = 'O' or 'o', SLAMCH := rmax */ /* where */ /* eps = relative machine precision */ /* sfmin = safe minimum, such that 1/sfmin does not overflow */ /* base = base of the machine */ /* prec = eps*base */ /* t = number of (base) digits in the mantissa */ /* rnd = 1.0 when rounding occurs in addition, 0.0 otherwise */ /* emin = minimum exponent before (gradual) underflow */ /* rmin = underflow threshold - base**(emin-1) */ /* emax = largest exponent before overflow */ /* rmax = overflow threshold - (base**emax)*(1-eps) */ float safe_min = FLT_MIN; float small = 1.0f / FLT_MAX; if ( small >= safe_min ) safe_min = small * ( 1.0f + FLT_EPSILON ); switch ( toupper( *cmach ) ) { case 'E': return FLT_EPSILON; case 'S': return safe_min; case 'B': return FLT_RADIX; case 'P': return FLT_RADIX*FLT_EPSILON; case 'N': return FLT_MANT_DIG; case 'R': return FLT_ROUNDS == FE_TONEAREST ? 1.0f : 0.0f; case 'M': return FLT_MIN_EXP; case 'U': return FLT_MIN; case 'L': return FLT_MAX_EXP; case 'O': return FLT_MAX; } return 0.0f; } #endif #ifdef __cplusplus } #endif blis-0.9.0/frame/base/noopt/bli_slamch.h000066400000000000000000000033101422157504600200650ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ bla_real bli_slamch( bla_character* cmach, ftnlen cmach_len ); blis-0.9.0/frame/base/proj/000077500000000000000000000000001422157504600154355ustar00rootroot00000000000000blis-0.9.0/frame/base/proj/bli_projm.c000066400000000000000000000071161422157504600175630ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_projm ( obj_t* a, obj_t* b ) { // Check parameters. if ( bli_error_checking_is_enabled() ) bli_projm_check( a, b ); if ( ( bli_obj_is_real( a ) && bli_obj_is_real( b ) ) || ( bli_obj_is_complex( a ) && bli_obj_is_complex( b ) ) ) { // If a and b are both real or both complex, we can simply use // copym. bli_copym( a, b ); } else { // This branch handles the case where one operand is real and // the other is complex. if ( bli_obj_is_real( a ) /* && bli_obj_is_complex( b ) */ ) { // If a is real and b is complex, we must obtain the real part // of b so that we can copy a into the real part (after // initializing all of b, including imaginary components, to // zero). obj_t br; bli_obj_real_part( b, &br ); bli_setm( &BLIS_ZERO, b ); bli_copym( a, &br ); } else // bli_obj_is_complex( a ) && bli_obj_is_real( b ) { // If a is complex and b is real, we can simply copy the // real part of a into b. obj_t ar; bli_obj_real_part( a, &ar ); bli_copym( &ar, b ); } } } // ----------------------------------------------------------------------------- void bli_projm_check ( obj_t* a, obj_t* b ) { err_t e_val; // Check object datatypes. e_val = bli_check_floating_object( a ); bli_check_error_code( e_val ); e_val = bli_check_floating_object( b ); bli_check_error_code( e_val ); e_val = bli_check_consistent_object_precisions( a, b ); bli_check_error_code( e_val ); // Check object dimensions. e_val = bli_check_matrix_object( a ); bli_check_error_code( e_val ); e_val = bli_check_matrix_object( b ); bli_check_error_code( e_val ); e_val = bli_check_conformal_dims( a, b ); bli_check_error_code( e_val ); // Check object buffers (for non-NULLness). e_val = bli_check_object_buffer( a ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( b ); bli_check_error_code( e_val ); } blis-0.9.0/frame/base/proj/bli_projm.h000066400000000000000000000034401422157504600175640ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ BLIS_EXPORT_BLIS void bli_projm ( obj_t* a, obj_t* b ); void bli_projm_check ( obj_t* a, obj_t* b ); blis-0.9.0/frame/base/proj/bli_projv.c000066400000000000000000000071241422157504600175730ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_projv ( obj_t* x, obj_t* y ) { // Check parameters. if ( bli_error_checking_is_enabled() ) bli_projv_check( x, y ); if ( ( bli_obj_is_real( x ) && bli_obj_is_real( y ) ) || ( bli_obj_is_complex( x ) && bli_obj_is_complex( y ) ) ) { // If x and y are both real or both complex, we can simply use // copyv. bli_copyv( x, y ); } else { // This branch handles the case where one operand is real and // the other is complex. if ( bli_obj_is_real( x ) /* && bli_obj_is_complex( y ) */ ) { // If x is real and y is complex, we must obtain the real part // of y so that we can copy x into the real part (after // initializing all of y, including imaginary components, to // zero). obj_t yr; bli_obj_real_part( y, &yr ); bli_setv( &BLIS_ZERO, y ); bli_copyv( x, &yr ); } else // bli_obj_is_complex( x ) && bli_obj_is_real( y ) { // If x is complex and y is real, we can simply copy the // real part of x into y. obj_t xr; bli_obj_real_part( x, &xr ); bli_copyv( &xr, y ); } } } // ----------------------------------------------------------------------------- void bli_projv_check ( obj_t* x, obj_t* y ) { err_t e_val; // Check object datatypes. e_val = bli_check_floating_object( x ); bli_check_error_code( e_val ); e_val = bli_check_floating_object( y ); bli_check_error_code( e_val ); e_val = bli_check_consistent_object_precisions( x, y ); bli_check_error_code( e_val ); // Check object dimensions. e_val = bli_check_vector_object( x ); bli_check_error_code( e_val ); e_val = bli_check_vector_object( y ); bli_check_error_code( e_val ); e_val = bli_check_equal_vector_lengths( x, y ); bli_check_error_code( e_val ); // Check object buffers (for non-NULLness). e_val = bli_check_object_buffer( x ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( y ); bli_check_error_code( e_val ); } blis-0.9.0/frame/base/proj/bli_projv.h000066400000000000000000000034401422157504600175750ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ BLIS_EXPORT_BLIS void bli_projv ( obj_t* x, obj_t* y ); void bli_projv_check ( obj_t* x, obj_t* y ); blis-0.9.0/frame/base/proj/old/000077500000000000000000000000001422157504600162135ustar00rootroot00000000000000blis-0.9.0/frame/base/proj/old/bli_proj_check.c000066400000000000000000000063261422157504600213230ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_projm_check ( obj_t* a, obj_t* b ) { err_t e_val; // Check object datatypes. e_val = bli_check_floating_object( a ); bli_check_error_code( e_val ); e_val = bli_check_floating_object( b ); bli_check_error_code( e_val ); e_val = bli_check_consistent_object_precisions( a, b ); bli_check_error_code( e_val ); // Check object dimensions. e_val = bli_check_matrix_object( a ); bli_check_error_code( e_val ); e_val = bli_check_matrix_object( b ); bli_check_error_code( e_val ); e_val = bli_check_conformal_dims( a, b ); bli_check_error_code( e_val ); // Check object buffers (for non-NULLness). e_val = bli_check_object_buffer( a ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( b ); bli_check_error_code( e_val ); } void bli_projv_check ( obj_t* x, obj_t* y ) { err_t e_val; // Check object datatypes. e_val = bli_check_floating_object( x ); bli_check_error_code( e_val ); e_val = bli_check_floating_object( y ); bli_check_error_code( e_val ); e_val = bli_check_consistent_object_precisions( x, y ); bli_check_error_code( e_val ); // Check object dimensions. e_val = bli_check_vector_object( x ); bli_check_error_code( e_val ); e_val = bli_check_vector_object( y ); bli_check_error_code( e_val ); e_val = bli_check_equal_vector_lengths( x, y ); bli_check_error_code( e_val ); // Check object buffers (for non-NULLness). e_val = bli_check_object_buffer( x ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( y ); bli_check_error_code( e_val ); } blis-0.9.0/frame/base/proj/old/bli_proj_check.h000066400000000000000000000034241422157504600213240ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void bli_projm_check ( obj_t* a, obj_t* b ); void bli_projv_check ( obj_t* x, obj_t* y ); blis-0.9.0/frame/compat/000077500000000000000000000000001422157504600150345ustar00rootroot00000000000000blis-0.9.0/frame/compat/amd/000077500000000000000000000000001422157504600155755ustar00rootroot00000000000000blis-0.9.0/frame/compat/amd/bla_copy_amd.c000066400000000000000000000111161422157504600203520ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2022, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // Define BLAS-to-BLIS interfaces. // #undef GENTFUNC #define GENTFUNC( ftype, ch, blasname, blisname, isuf ) \ \ void PASTEF77(ch,blasname) \ ( \ const f77_int* n, \ const ftype* x, const f77_int* incx, \ ftype* y, const f77_int* incy \ ) \ { \ dim_t n0; \ ftype* x0; \ ftype* y0; \ inc_t incx0; \ inc_t incy0; \ \ /* Initialize BLIS. */ \ /*bli_init_auto()*/; \ \ /* Convert/typecast negative values of n to zero. */ \ bli_convert_blas_dim1( *n, n0 ); \ \ /* If the input increments are negative, adjust the pointers so we can use positive increments instead. */ \ bli_convert_blas_incv( n0, (ftype*)x, *incx, x0, incx0 ); \ bli_convert_blas_incv( n0, (ftype*)y, *incy, y0, incy0 ); \ \ /* Call BLIS interface. */ \ /* NOTE: While we skip explicit initialization for real domain instances since we call the microkernel directly, the complex domain instances still need initialization so that they can query valid contexts from gks. However, the expert API will self-initialize before attempting to query a context, so the complex domain cases should work fine. */ \ PASTEMAC2(ch,blisname,isuf) \ ( \ BLIS_NO_CONJUGATE, \ n0, \ x0, incx0, \ y0, incy0, \ NULL \ ); \ \ /* Finalize BLIS. */ \ /*bli_finalize_auto();*/ \ } #ifdef BLIS_ENABLE_BLAS //INSERT_GENTFUNC_BLAS( copy, copyv ) GENTFUNC( float, s, copy, copyv, _zen_int ) GENTFUNC( double, d, copy, copyv, _zen_int ) #endif #undef GENTFUNC #define GENTFUNC( ftype, ch, blasname, blisname, isuf ) \ \ void PASTEF77(ch,blasname) \ ( \ const f77_int* n, \ const ftype* x, const f77_int* incx, \ ftype* y, const f77_int* incy \ ) \ { \ dim_t n0; \ ftype* x0; \ ftype* y0; \ inc_t incx0; \ inc_t incy0; \ \ /* Initialize BLIS. */ \ /*bli_init_auto()*/; \ \ /* Convert/typecast negative values of n to zero. */ \ bli_convert_blas_dim1( *n, n0 ); \ \ /* If the input increments are negative, adjust the pointers so we can use positive increments instead. */ \ bli_convert_blas_incv( n0, (ftype*)x, *incx, x0, incx0 ); \ bli_convert_blas_incv( n0, (ftype*)y, *incy, y0, incy0 ); \ \ /* Call BLIS interface. */ \ /* NOTE: While we skip explicit initialization for real domain instances since we call the microkernel directly, the complex domain instances still need initialization so that they can query valid contexts from gks. However, the expert API will self-initialize before attempting to query a context, so the complex domain cases should work fine. */ \ PASTEMAC2(ch,blisname,isuf) \ ( \ BLIS_NO_CONJUGATE, \ n0, \ x0, incx0, \ y0, incy0, \ NULL, \ NULL \ ); \ \ /* Finalize BLIS. */ \ /*bli_finalize_auto();*/ \ } #ifdef BLIS_ENABLE_BLAS //INSERT_GENTFUNC_BLAS( copy, copyv ) GENTFUNC( scomplex, c, copy, copyv, _ex ) GENTFUNC( dcomplex, z, copy, copyv, _ex ) #endif blis-0.9.0/frame/compat/amd/bla_gemv_amd.c000066400000000000000000000130661422157504600203440ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2022, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // Define BLAS-to-BLIS interfaces. // #undef GENTFUNC #define GENTFUNC( ftype, ch, blasname, blisname ) \ \ void PASTEF77(ch,blasname) \ ( \ const f77_char* transa, \ const f77_int* m, \ const f77_int* n, \ const ftype* alpha, \ const ftype* a, const f77_int* lda, \ const ftype* x, const f77_int* incx, \ const ftype* beta, \ ftype* y, const f77_int* incy \ ) \ { \ trans_t blis_transa; \ dim_t m0, n0; \ dim_t m_y, n_x; \ ftype* x0; \ ftype* y0; \ inc_t incx0; \ inc_t incy0; \ \ /* Initialize BLIS. */ \ /*bli_init_auto();*/ \ \ /* Perform BLAS parameter checking. */ \ PASTEBLACHK(blasname) \ ( \ MKSTR(ch), \ MKSTR(blasname), \ transa, \ m, \ n, \ lda, \ incx, \ incy \ ); \ \ /* BLAS handles cases where y has no elements as well as those where x has no elements. In the case of the former, it cannot do any work since the output vector is empty; but in the latter case, BLAS has peculiar semantics. When x has no elements (and transa(A) has no columns), BLAS returns immediately without performing any computation even if the number of elements of y (and rows of transa(A)) is non-zero, in which case any sane interpretations of gemv would have the the operation reduce to y := beta * y. Here, we emulate the BLAS exactly so as to provide "bug-for-bug" compatibility. Note that this extreme level of compatibility would not be contemplated if it weren't for the fact that some BLAS unit tests actually check for this behavior. Also, it should be emphasized that BLIS, when called natively, does NOT exhibit this quirky behavior; it will scale y by beta as one would expect. */ \ if ( *m == 0 || *n == 0 ) \ { \ /* Finalize BLIS. */ \ /*bli_finalize_auto();*/ \ \ return; \ } \ \ /* Map BLAS chars to their corresponding BLIS enumerated type value. */ \ bli_param_map_netlib_to_blis_trans( *transa, &blis_transa ); \ \ /* Convert/typecast negative values of m and n to zero. */ \ bli_convert_blas_dim1( *m, m0 ); \ bli_convert_blas_dim1( *n, n0 ); \ \ /* Determine the dimensions of x and y so we can adjust the increments, if necessary.*/ \ bli_set_dims_with_trans( blis_transa, m0, n0, &m_y, &n_x ); \ \ /* If the input increments are negative, adjust the pointers so we can use positive increments instead. */ \ bli_convert_blas_incv( n_x, (ftype*)x, *incx, x0, incx0 ); \ bli_convert_blas_incv( m_y, (ftype*)y, *incy, y0, incy0 ); \ \ /* If alpha is zero, scale y by beta and return early. */ \ if ( PASTEMAC(ch,eq0)( *alpha ) ) \ { \ PASTEMAC2(ch,scalv,BLIS_TAPI_EX_SUF) \ ( \ BLIS_NO_CONJUGATE, \ m_y, \ ( ftype* )beta, \ ( ftype* )y0, incy0, \ NULL, \ NULL \ ); \ return; \ } \ \ /* Set the row and column strides of A. */ \ const inc_t rs_a = 1; \ const inc_t cs_a = *lda; \ \ /* Declare a void function pointer for the current operation. */ \ PASTECH2(ch,blisname,_unb_ft) f; \ \ /* Choose the underlying implementation. */ \ if ( bli_does_notrans( blis_transa ) ) f = PASTEMAC(ch,gemv_unf_var2); \ else /* if ( bli_does_trans( blis_transa ) ) */ f = PASTEMAC(ch,gemv_unf_var1); \ \ /* Obtain a valid context from the gks. This is needed because these implementations of ?gemv_() skip calling gemv_ex() and instead call the unblocked fused variants directly. */ \ cntx_t* cntx = bli_gks_query_cntx(); \ \ /* Invoke the variant chosen above, which loops over a level-1v or level-1f kernel to implement the current operation. */ \ f \ ( \ blis_transa, \ BLIS_NO_CONJUGATE, \ m0, \ n0, \ (ftype*)alpha, \ (ftype*)a, rs_a, cs_a, \ x0, incx0, \ (ftype*)beta, \ y0, incy0, \ cntx \ ); \ \ /* Finalize BLIS. */ \ /*bli_finalize_auto();*/ \ } #ifdef BLIS_ENABLE_BLAS INSERT_GENTFUNC_BLAS( gemv, gemv ) #endif blis-0.9.0/frame/compat/attic/000077500000000000000000000000001422157504600161405ustar00rootroot00000000000000blis-0.9.0/frame/compat/attic/bla_gbmv.c000066400000000000000000000063111422157504600200560ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // Define BLAS-to-BLIS interfaces. // #undef GENTFUNC #define GENTFUNC( ftype, ch, blasname, blisname ) \ \ void PASTEF77(ch,blasname)( \ f77_char* transa, \ f77_int* m, \ f77_int* n, \ f77_int* kl, \ f77_int* ku, \ ftype* alpha, \ ftype* a, f77_int* lda, \ ftype* x, f77_int* incx, \ ftype* beta, \ ftype* y, f77_int* incy \ ) \ { \ trans_t blis_transa; \ dim_t m0, n0; \ dim_t m_y, n_x; \ ftype* x0; \ ftype* y0; \ inc_t incx0; \ inc_t incy0; \ \ /* Map BLAS chars to their corresponding BLIS enumerated type value. */ \ bli_param_map_netlib_to_blis_trans( *transa, &blis_transa ); \ \ /* Convert/typecast negative values of m and n to zero. */ \ bli_convert_blas_dim1( *m, m0 ); \ bli_convert_blas_dim1( *n, n0 ); \ \ /* Determine the dimensions of x and y so we can adjust the increments, if necessary.*/ \ bli_set_dims_with_trans( blis_transa, m0, n0, &m_y, &n_x ); \ \ /* If the input increments are negative, adjust the pointers so we can use positive increments instead. */ \ bli_convert_blas_incv( n_x, x, *incx, x0, incx0 ); \ bli_convert_blas_incv( m_y, y, *incy, y0, incy0 ); \ \ bli_check_error_code( BLIS_NOT_YET_IMPLEMENTED ); \ } #ifdef BLIS_ENABLE_BLAS INSERT_GENTFUNC_BLAS( gbmv, gbmv ) #endif blis-0.9.0/frame/compat/attic/bla_gbmv.h000066400000000000000000000045451422157504600200720ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype BLAS-to-BLIS interfaces. // #undef GENTPROT #define GENTPROT( ftype, ch, blasname ) \ \ BLIS_EXPORT_BLAS void PASTEF77(ch,blasname)( \ f77_char* transa, \ f77_int* m, \ f77_int* n, \ f77_int* kl, \ f77_int* ku, \ ftype* alpha, \ ftype* a, f77_int* lda, \ ftype* x, f77_int* incx, \ ftype* beta, \ ftype* y, f77_int* incy \ ); #ifdef BLIS_ENABLE_BLAS INSERT_GENTPROT_BLAS( gbmv ) #endif blis-0.9.0/frame/compat/attic/bla_hbmv.c000066400000000000000000000056331422157504600200650ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // Define BLAS-to-BLIS interfaces. // #undef GENTFUNCCO #define GENTFUNCCO( ftype, ftype_r, ch, chr, blasname, blisname ) \ \ void PASTEF77(ch,blasname)( \ f77_char* uploa, \ f77_int* m, \ f77_int* k, \ ftype* alpha, \ ftype* a, f77_int* lda, \ ftype* x, f77_int* incx, \ ftype* beta, \ ftype* y, f77_int* incy \ ) \ { \ uplo_t blis_uploa; \ dim_t m0; \ ftype* x0; \ ftype* y0; \ inc_t incx0; \ inc_t incy0; \ \ /* Map BLAS chars to their corresponding BLIS enumerated type value. */ \ bli_param_map_netlib_to_blis_uplo( *uploa, &blis_uploa ); \ \ /* Convert/typecast negative values of m to zero. */ \ bli_convert_blas_dim1( *m, m0 ); \ \ /* If the input increments are negative, adjust the pointers so we can use positive increments instead. */ \ bli_convert_blas_incv( m0, x, *incx, x0, incx0 ); \ bli_convert_blas_incv( m0, y, *incy, y0, incy0 ); \ \ bli_check_error_code( BLIS_NOT_YET_IMPLEMENTED ); \ } #ifdef BLIS_ENABLE_BLAS INSERT_GENTFUNCCO_BLAS( hbmv, hbmv ) #endif blis-0.9.0/frame/compat/attic/bla_hbmv.h000066400000000000000000000044401422157504600200650ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype BLAS-to-BLIS interfaces. // #undef GENTPROTCO #define GENTPROTCO( ftype, ftype_r, ch, chr, blasname ) \ \ BLIS_EXPORT_BLAS void PASTEF77(ch,blasname)( \ f77_char* uploa, \ f77_int* m, \ f77_int* k, \ ftype* alpha, \ ftype* a, f77_int* lda, \ ftype* x, f77_int* incx, \ ftype* beta, \ ftype* y, f77_int* incy \ ); #ifdef BLIS_ENABLE_BLAS INSERT_GENTPROTCO_BLAS( hbmv ) #endif blis-0.9.0/frame/compat/attic/bla_hpmv.c000066400000000000000000000055421422157504600201020ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // Define BLAS-to-BLIS interfaces. // #undef GENTFUNCCO #define GENTFUNCCO( ftype, ftype_r, ch, chr, blasname, blisname ) \ \ void PASTEF77(ch,blasname)( \ f77_char* uploa, \ f77_int* m, \ ftype* alpha, \ ftype* a, \ ftype* x, f77_int* incx, \ ftype* beta, \ ftype* y, f77_int* incy \ ) \ { \ uplo_t blis_uploa; \ dim_t m0; \ ftype* x0; \ ftype* y0; \ inc_t incx0; \ inc_t incy0; \ \ /* Map BLAS chars to their corresponding BLIS enumerated type value. */ \ bli_param_map_netlib_to_blis_uplo( *uploa, &blis_uploa ); \ \ /* Convert/typecast negative values of m to zero. */ \ bli_convert_blas_dim1( *m, m0 ); \ \ /* If the input increments are negative, adjust the pointers so we can use positive increments instead. */ \ bli_convert_blas_incv( m0, x, *incx, x0, incx0 ); \ bli_convert_blas_incv( m0, y, *incy, y0, incy0 ); \ \ bli_check_error_code( BLIS_NOT_YET_IMPLEMENTED ); \ } #ifdef BLIS_ENABLE_BLAS INSERT_GENTFUNCCO_BLAS( hpmv, hpmv ) #endif blis-0.9.0/frame/compat/attic/bla_hpmv.h000066400000000000000000000043471422157504600201110ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype BLAS-to-BLIS interfaces. // #undef GENTPROTCO #define GENTPROTCO( ftype, ftype_r, ch, chr, blasname ) \ \ BLIS_EXPORT_BLAS void PASTEF77(ch,blasname)( \ f77_char* uploa, \ f77_int* m, \ ftype* alpha, \ ftype* a, \ ftype* x, f77_int* incx, \ ftype* beta, \ ftype* y, f77_int* incy \ ); #ifdef BLIS_ENABLE_BLAS INSERT_GENTPROTCO_BLAS( hpmv ) #endif blis-0.9.0/frame/compat/attic/bla_hpr.c000066400000000000000000000052421422157504600177160ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // Define BLAS-to-BLIS interfaces. // #undef GENTFUNCCO #define GENTFUNCCO( ftype, ftype_r, ch, chr, blasname, blisname ) \ \ void PASTEF77(ch,blasname)( \ f77_char* uploa, \ f77_int* m, \ ftype_r* alpha, \ ftype* x, f77_int* incx, \ ftype* a \ ) \ { \ uplo_t blis_uploa; \ dim_t m0; \ ftype* x0; \ inc_t incx0; \ \ /* Map BLAS chars to their corresponding BLIS enumerated type value. */ \ bli_param_map_netlib_to_blis_uplo( *uploa, &blis_uploa ); \ \ /* Convert/typecast negative values of m to zero. */ \ bli_convert_blas_dim1( *m, m0 ); \ \ /* If the input increments are negative, adjust the pointers so we can use positive increments instead. */ \ bli_convert_blas_incv( m0, x, *incx, x0, incx0 ); \ \ bli_check_error_code( BLIS_NOT_YET_IMPLEMENTED ); \ } #ifdef BLIS_ENABLE_BLAS INSERT_GENTFUNCCO_BLAS( hpr, hpr ) #endif blis-0.9.0/frame/compat/attic/bla_hpr.h000066400000000000000000000041761422157504600177300ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype BLAS-to-BLIS interfaces. // #undef GENTPROTCO #define GENTPROTCO( ftype, ftype_r, ch, chr, blasname ) \ \ BLIS_EXPORT_BLAS void PASTEF77(ch,blasname)( \ f77_char* uploa, \ f77_int* m, \ ftype_r* alpha, \ ftype* x, f77_int* incx, \ ftype* a \ ); #ifdef BLIS_ENABLE_BLAS INSERT_GENTPROTCO_BLAS( hpr ) #endif blis-0.9.0/frame/compat/attic/bla_hpr2.c000066400000000000000000000054641422157504600200060ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // Define BLAS-to-BLIS interfaces. // #undef GENTFUNCCO #define GENTFUNCCO( ftype, ftype_r, ch, chr, blasname, blisname ) \ \ void PASTEF77(ch,blasname)( \ f77_char* uploa, \ f77_int* m, \ ftype* alpha, \ ftype* x, f77_int* incx, \ ftype* y, f77_int* incy, \ ftype* a \ ) \ { \ uplo_t blis_uploa; \ dim_t m0; \ ftype* x0; \ ftype* y0; \ inc_t incx0; \ inc_t incy0; \ \ /* Map BLAS chars to their corresponding BLIS enumerated type value. */ \ bli_param_map_netlib_to_blis_uplo( *uploa, &blis_uploa ); \ \ /* Convert/typecast negative values of m to zero. */ \ bli_convert_blas_dim1( *m, m0 ); \ \ /* If the input increments are negative, adjust the pointers so we can use positive increments instead. */ \ bli_convert_blas_incv( m0, x, *incx, x0, incx0 ); \ bli_convert_blas_incv( m0, y, *incy, y0, incy0 ); \ \ bli_check_error_code( BLIS_NOT_YET_IMPLEMENTED ); \ } #ifdef BLIS_ENABLE_BLAS INSERT_GENTFUNCCO_BLAS( hpr2, hpr2 ) #endif blis-0.9.0/frame/compat/attic/bla_hpr2.h000066400000000000000000000042711422157504600200060ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype BLAS-to-BLIS interfaces. // #undef GENTPROTCO #define GENTPROTCO( ftype, ftype_r, ch, chr, blasname ) \ \ BLIS_EXPORT_BLAS void PASTEF77(ch,blasname)( \ f77_char* uploa, \ f77_int* m, \ ftype* alpha, \ ftype* x, f77_int* incx, \ ftype* y, f77_int* incy, \ ftype* a \ ); #ifdef BLIS_ENABLE_BLAS INSERT_GENTPROTCO_BLAS( hpr2 ) #endif blis-0.9.0/frame/compat/attic/bla_rot.c000066400000000000000000000052451422157504600177340ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // Define BLAS-to-BLIS interfaces. // #undef GENTFUNCR2 #define GENTFUNCR2( ftype_xy, ftype_r, chxy, chr, blasname, blisname ) \ \ void PASTEF772(chxy,chr,blasname)( \ f77_int* n, \ ftype_xy* x, f77_int* incx, \ ftype_xy* y, f77_int* incy, \ ftype_r* c, \ ftype_r* s \ ) \ { \ dim_t n0; \ ftype_xy* x0; \ ftype_xy* y0; \ inc_t incx0; \ inc_t incy0; \ \ /* Convert/typecast negative values of n to zero. */ \ bli_convert_blas_dim1( *n, n0 ); \ \ /* If the input increments are negative, adjust the pointers so we can use positive increments instead. */ \ bli_convert_blas_incv( n0, x, *incx, x0, incx0 ); \ bli_convert_blas_incv( n0, y, *incy, y0, incy0 ); \ \ bli_check_error_code( BLIS_NOT_YET_IMPLEMENTED ); \ } #ifdef BLIS_ENABLE_BLAS INSERT_GENTFUNCR2_BLAS( rot, ROT_KERNEL ) #endif blis-0.9.0/frame/compat/attic/bla_rot.h000066400000000000000000000042731422157504600177410ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype BLAS-to-BLIS interfaces. // #undef GENTPROTR2 #define GENTPROTR2( ftype_xy, ftype_r, chxy, chr, blasname ) \ \ BLIS_EXPORT_BLAS void PASTEF772(chxy,chr,blasname)( \ f77_int* n, \ ftype_xy* x, f77_int* incx, \ ftype_xy* y, f77_int* incy, \ ftype_r* c, \ ftype_r* s \ ); #ifdef BLIS_ENABLE_BLAS INSERT_GENTPROTR2_BLAS( rot ) #endif blis-0.9.0/frame/compat/attic/bla_rotg.c000066400000000000000000000042471422157504600201040ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // Define BLAS-to-BLIS interfaces. // #undef GENTFUNCR #define GENTFUNCR( ftype_xy, ftype_r, chxy, chr, blasname, blisname ) \ \ void PASTEF77(chxy,blasname)( \ ftype_xy* x, \ ftype_xy* y, \ ftype_r* c, \ ftype_r* s \ ) \ { \ bli_check_error_code( BLIS_NOT_YET_IMPLEMENTED ); \ } #ifdef BLIS_ENABLE_BLAS INSERT_GENTFUNCR_BLAS( rotg, rotg, ROTG_KERNEL ) #endif blis-0.9.0/frame/compat/attic/bla_rotg.h000066400000000000000000000041251422157504600201040ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype BLAS-to-BLIS interfaces. // #undef GENTPROTR #define GENTPROTR( ftype_xy, ftype_r, chxy, chr, blasname ) \ \ BLIS_EXPORT_BLAS void PASTEF77(chxy,blasname)( \ ftype_xy* x, \ ftype_xy* y, \ ftype_r* c, \ ftype_r* s \ ); #ifdef BLIS_ENABLE_BLAS INSERT_GENTPROTR_BLAS( rotg, rotg ) #endif blis-0.9.0/frame/compat/attic/bla_rotm.c000066400000000000000000000050521422157504600201050ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // Define BLAS-to-BLIS interfaces. // #undef GENTFUNCRO #define GENTFUNCRO( ftype, ch, blasname, blisname ) \ \ void PASTEF77(ch,blasname)( \ f77_int* n, \ ftype* x, f77_int* incx, \ ftype* y, f77_int* incy, \ ftype* dparam \ ) \ { \ dim_t n0; \ ftype* x0; \ ftype* y0; \ inc_t incx0; \ inc_t incy0; \ \ /* Convert/typecast negative values of n to zero. */ \ bli_convert_blas_dim1( *n, n0 ); \ \ /* If the input increments are negative, adjust the pointers so we can use positive increments instead. */ \ bli_convert_blas_incv( n0, x, *incx, x0, incx0 ); \ bli_convert_blas_incv( n0, y, *incy, y0, incy0 ); \ \ bli_check_error_code( BLIS_NOT_YET_IMPLEMENTED ); \ } #ifdef BLIS_ENABLE_BLAS INSERT_GENTFUNCRO_BLAS( rotm, ROTM_KERNEL ) #endif blis-0.9.0/frame/compat/attic/bla_rotm.h000066400000000000000000000041161422157504600201120ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype BLAS-to-BLIS interfaces. // #undef GENTPROTRO #define GENTPROTRO( ftype, ch, blasname ) \ \ BLIS_EXPORT_BLAS void PASTEF77(ch,blasname)( \ f77_int* n, \ ftype* x, f77_int* incx, \ ftype* y, f77_int* incy, \ ftype* dparam \ ); #ifdef BLIS_ENABLE_BLAS INSERT_GENTPROTRO_BLAS( rotm ) #endif blis-0.9.0/frame/compat/attic/bla_rotmg.c000066400000000000000000000042531422157504600202560ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // Define BLAS-to-BLIS interfaces. // #undef GENTFUNCRO #define GENTFUNCRO( ftype, ch, blasname, blisname ) \ \ void PASTEF77(ch,blasname)( \ ftype* d1, \ ftype* d2, \ ftype* x, \ ftype* y, \ ftype* dparam \ ) \ { \ bli_check_error_code( BLIS_NOT_YET_IMPLEMENTED ); \ } #ifdef BLIS_ENABLE_BLAS INSERT_GENTFUNCRO_BLAS( rotmg, ROTMG_KERNEL ) #endif blis-0.9.0/frame/compat/attic/bla_rotmg.h000066400000000000000000000041301422157504600202550ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype BLAS-to-BLIS interfaces. // #undef GENTPROTRO #define GENTPROTRO( ftype, ch, blasname ) \ \ BLIS_EXPORT_BLAS void PASTEF77(ch,blasname)( \ ftype* d1, \ ftype* d2, \ ftype* x, \ ftype* y, \ ftype* dparam \ ); #ifdef BLIS_ENABLE_BLAS INSERT_GENTPROTRO_BLAS( rotmg ) #endif blis-0.9.0/frame/compat/attic/bla_sbmv.c000066400000000000000000000056151422157504600201000ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // Define BLAS-to-BLIS interfaces. // #undef GENTFUNCRO #define GENTFUNCRO( ftype, ch, blasname, blisname ) \ \ void PASTEF77(ch,blasname)( \ f77_char* uploa, \ f77_int* m, \ f77_int* k, \ ftype* alpha, \ ftype* a, f77_int* lda, \ ftype* x, f77_int* incx, \ ftype* beta, \ ftype* y, f77_int* incy \ ) \ { \ uplo_t blis_uploa; \ dim_t m0; \ ftype* x0; \ ftype* y0; \ inc_t incx0; \ inc_t incy0; \ \ /* Map BLAS chars to their corresponding BLIS enumerated type value. */ \ bli_param_map_netlib_to_blis_uplo( *uploa, &blis_uploa ); \ \ /* Convert/typecast negative values of m to zero. */ \ bli_convert_blas_dim1( *m, m0 ); \ \ /* If the input increments are negative, adjust the pointers so we can use positive increments instead. */ \ bli_convert_blas_incv( m0, x, *incx, x0, incx0 ); \ bli_convert_blas_incv( m0, y, *incy, y0, incy0 ); \ \ bli_check_error_code( BLIS_NOT_YET_IMPLEMENTED ); \ } #ifdef BLIS_ENABLE_BLAS INSERT_GENTFUNCRO_BLAS( sbmv, sbmv ) #endif blis-0.9.0/frame/compat/attic/bla_sbmv.h000066400000000000000000000044221422157504600201000ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype BLAS-to-BLIS interfaces. // #undef GENTPROTRO #define GENTPROTRO( ftype, ch, blasname ) \ \ BLIS_EXPORT_BLAS void PASTEF77(ch,blasname)( \ f77_char* uploa, \ f77_int* m, \ f77_int* k, \ ftype* alpha, \ ftype* a, f77_int* lda, \ ftype* x, f77_int* incx, \ ftype* beta, \ ftype* y, f77_int* incy \ ); #ifdef BLIS_ENABLE_BLAS INSERT_GENTPROTRO_BLAS( sbmv ) #endif blis-0.9.0/frame/compat/attic/bla_spmv.c000066400000000000000000000055241422157504600201150ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // Define BLAS-to-BLIS interfaces. // #undef GENTFUNCRO #define GENTFUNCRO( ftype, ch, blasname, blisname ) \ \ void PASTEF77(ch,blasname)( \ f77_char* uploa, \ f77_int* m, \ ftype* alpha, \ ftype* a, \ ftype* x, f77_int* incx, \ ftype* beta, \ ftype* y, f77_int* incy \ ) \ { \ uplo_t blis_uploa; \ dim_t m0; \ ftype* x0; \ ftype* y0; \ inc_t incx0; \ inc_t incy0; \ \ /* Map BLAS chars to their corresponding BLIS enumerated type value. */ \ bli_param_map_netlib_to_blis_uplo( *uploa, &blis_uploa ); \ \ /* Convert/typecast negative values of m to zero. */ \ bli_convert_blas_dim1( *m, m0 ); \ \ /* If the input increments are negative, adjust the pointers so we can use positive increments instead. */ \ bli_convert_blas_incv( m0, x, *incx, x0, incx0 ); \ bli_convert_blas_incv( m0, y, *incy, y0, incy0 ); \ \ bli_check_error_code( BLIS_NOT_YET_IMPLEMENTED ); \ } #ifdef BLIS_ENABLE_BLAS INSERT_GENTFUNCRO_BLAS( spmv, spmv ) #endif blis-0.9.0/frame/compat/attic/bla_spmv.h000066400000000000000000000043311422157504600201150ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype BLAS-to-BLIS interfaces. // #undef GENTPROTRO #define GENTPROTRO( ftype, ch, blasname ) \ \ BLIS_EXPORT_BLAS void PASTEF77(ch,blasname)( \ f77_char* uploa, \ f77_int* m, \ ftype* alpha, \ ftype* a, \ ftype* x, f77_int* incx, \ ftype* beta, \ ftype* y, f77_int* incy \ ); #ifdef BLIS_ENABLE_BLAS INSERT_GENTPROTRO_BLAS( spmv ) #endif blis-0.9.0/frame/compat/attic/bla_spr.c000066400000000000000000000052241422157504600177310ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // Define BLAS-to-BLIS interfaces. // #undef GENTFUNCRO #define GENTFUNCRO( ftype, ch, blasname, blisname ) \ \ void PASTEF77(ch,blasname)( \ f77_char* uploa, \ f77_int* m, \ ftype* alpha, \ ftype* x, f77_int* incx, \ ftype* a \ ) \ { \ uplo_t blis_uploa; \ dim_t m0; \ ftype* x0; \ inc_t incx0; \ \ /* Map BLAS chars to their corresponding BLIS enumerated type value. */ \ bli_param_map_netlib_to_blis_uplo( *uploa, &blis_uploa ); \ \ /* Convert/typecast negative values of m to zero. */ \ bli_convert_blas_dim1( *m, m0 ); \ \ /* If the input increments are negative, adjust the pointers so we can use positive increments instead. */ \ bli_convert_blas_incv( m0, x, *incx, x0, incx0 ); \ \ bli_check_error_code( BLIS_NOT_YET_IMPLEMENTED ); \ } #ifdef BLIS_ENABLE_BLAS INSERT_GENTFUNCRO_BLAS( spr, spr ) #endif blis-0.9.0/frame/compat/attic/bla_spr.h000066400000000000000000000041601422157504600177340ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype BLAS-to-BLIS interfaces. // #undef GENTPROTRO #define GENTPROTRO( ftype, ch, blasname ) \ \ BLIS_EXPORT_BLAS void PASTEF77(ch,blasname)( \ f77_char* uploa, \ f77_int* m, \ ftype* alpha, \ ftype* x, f77_int* incx, \ ftype* a \ ); #ifdef BLIS_ENABLE_BLAS INSERT_GENTPROTRO_BLAS( spr ) #endif blis-0.9.0/frame/compat/attic/bla_spr2.c000066400000000000000000000054461422157504600200210ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // Define BLAS-to-BLIS interfaces. // #undef GENTFUNCRO #define GENTFUNCRO( ftype, ch, blasname, blisname ) \ \ void PASTEF77(ch,blasname)( \ f77_char* uploa, \ f77_int* m, \ ftype* alpha, \ ftype* x, f77_int* incx, \ ftype* y, f77_int* incy, \ ftype* a \ ) \ { \ uplo_t blis_uploa; \ dim_t m0; \ ftype* x0; \ ftype* y0; \ inc_t incx0; \ inc_t incy0; \ \ /* Map BLAS chars to their corresponding BLIS enumerated type value. */ \ bli_param_map_netlib_to_blis_uplo( *uploa, &blis_uploa ); \ \ /* Convert/typecast negative values of m to zero. */ \ bli_convert_blas_dim1( *m, m0 ); \ \ /* If the input increments are negative, adjust the pointers so we can use positive increments instead. */ \ bli_convert_blas_incv( m0, x, *incx, x0, incx0 ); \ bli_convert_blas_incv( m0, y, *incy, y0, incy0 ); \ \ bli_check_error_code( BLIS_NOT_YET_IMPLEMENTED ); \ } #ifdef BLIS_ENABLE_BLAS INSERT_GENTFUNCRO_BLAS( spr2, spr2 ) #endif blis-0.9.0/frame/compat/attic/bla_spr2.h000066400000000000000000000042531422157504600200210ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype BLAS-to-BLIS interfaces. // #undef GENTPROTRO #define GENTPROTRO( ftype, ch, blasname ) \ \ BLIS_EXPORT_BLAS void PASTEF77(ch,blasname)( \ f77_char* uploa, \ f77_int* m, \ ftype* alpha, \ ftype* x, f77_int* incx, \ ftype* y, f77_int* incy, \ ftype* a \ ); #ifdef BLIS_ENABLE_BLAS INSERT_GENTPROTRO_BLAS( spr2 ) #endif blis-0.9.0/frame/compat/attic/bla_tbmv.c000066400000000000000000000056451422157504600201040ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // Define BLAS-to-BLIS interfaces. // #undef GENTFUNC #define GENTFUNC( ftype, ch, blasname, blisname ) \ \ void PASTEF77(ch,blasname)( \ f77_char* uploa, \ f77_char* transa, \ f77_char* diaga, \ f77_int* m, \ f77_int* k, \ ftype* a, f77_int* lda, \ ftype* x, f77_int* incx \ ) \ { \ uplo_t blis_uploa; \ trans_t blis_transa; \ diag_t blis_diaga; \ dim_t m0; \ ftype* x0; \ inc_t incx0; \ \ /* Map BLAS chars to their corresponding BLIS enumerated type value. */ \ bli_param_map_netlib_to_blis_uplo( *uploa, &blis_uploa ); \ bli_param_map_netlib_to_blis_trans( *transa, &blis_transa ); \ bli_param_map_netlib_to_blis_diag( *diaga, &blis_diaga ); \ \ /* Convert/typecast negative values of m to zero. */ \ bli_convert_blas_dim1( *m, m0 ); \ \ /* If the input increments are negative, adjust the pointers so we can use positive increments instead. */ \ bli_convert_blas_incv( m0, x, *incx, x0, incx0 ); \ \ bli_check_error_code( BLIS_NOT_YET_IMPLEMENTED ); \ } #ifdef BLIS_ENABLE_BLAS INSERT_GENTFUNC_BLAS( tbmv, tbmv ) #endif blis-0.9.0/frame/compat/attic/bla_tbmv.h000066400000000000000000000043241422157504600201020ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype BLAS-to-BLIS interfaces. // #undef GENTPROT #define GENTPROT( ftype, ch, blasname ) \ \ BLIS_EXPORT_BLAS void PASTEF77(ch,blasname)( \ f77_char* uploa, \ f77_char* transa, \ f77_char* diaga, \ f77_int* m, \ f77_int* k, \ ftype* a, f77_int* lda, \ ftype* x, f77_int* incx \ ); #ifdef BLIS_ENABLE_BLAS INSERT_GENTPROT_BLAS( tbmv ) #endif blis-0.9.0/frame/compat/attic/bla_tbsv.c000066400000000000000000000056451422157504600201120ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // Define BLAS-to-BLIS interfaces. // #undef GENTFUNC #define GENTFUNC( ftype, ch, blasname, blisname ) \ \ void PASTEF77(ch,blasname)( \ f77_char* uploa, \ f77_char* transa, \ f77_char* diaga, \ f77_int* m, \ f77_int* k, \ ftype* a, f77_int* lda, \ ftype* x, f77_int* incx \ ) \ { \ uplo_t blis_uploa; \ trans_t blis_transa; \ diag_t blis_diaga; \ dim_t m0; \ ftype* x0; \ inc_t incx0; \ \ /* Map BLAS chars to their corresponding BLIS enumerated type value. */ \ bli_param_map_netlib_to_blis_uplo( *uploa, &blis_uploa ); \ bli_param_map_netlib_to_blis_trans( *transa, &blis_transa ); \ bli_param_map_netlib_to_blis_diag( *diaga, &blis_diaga ); \ \ /* Convert/typecast negative values of m to zero. */ \ bli_convert_blas_dim1( *m, m0 ); \ \ /* If the input increments are negative, adjust the pointers so we can use positive increments instead. */ \ bli_convert_blas_incv( m0, x, *incx, x0, incx0 ); \ \ bli_check_error_code( BLIS_NOT_YET_IMPLEMENTED ); \ } #ifdef BLIS_ENABLE_BLAS INSERT_GENTFUNC_BLAS( tbsv, tbsv ) #endif blis-0.9.0/frame/compat/attic/bla_tbsv.h000066400000000000000000000043241422157504600201100ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype BLAS-to-BLIS interfaces. // #undef GENTPROT #define GENTPROT( ftype, ch, blasname ) \ \ BLIS_EXPORT_BLAS void PASTEF77(ch,blasname)( \ f77_char* uploa, \ f77_char* transa, \ f77_char* diaga, \ f77_int* m, \ f77_int* k, \ ftype* a, f77_int* lda, \ ftype* x, f77_int* incx \ ); #ifdef BLIS_ENABLE_BLAS INSERT_GENTPROT_BLAS( tbsv ) #endif blis-0.9.0/frame/compat/attic/bla_tpmv.c000066400000000000000000000055541422157504600201210ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // Define BLAS-to-BLIS interfaces. // #undef GENTFUNC #define GENTFUNC( ftype, ch, blasname, blisname ) \ \ void PASTEF77(ch,blasname)( \ f77_char* uploa, \ f77_char* transa, \ f77_char* diaga, \ f77_int* m, \ ftype* a, \ ftype* x, f77_int* incx \ ) \ { \ uplo_t blis_uploa; \ trans_t blis_transa; \ diag_t blis_diaga; \ dim_t m0; \ ftype* x0; \ inc_t incx0; \ \ /* Map BLAS chars to their corresponding BLIS enumerated type value. */ \ bli_param_map_netlib_to_blis_uplo( *uploa, &blis_uploa ); \ bli_param_map_netlib_to_blis_trans( *transa, &blis_transa ); \ bli_param_map_netlib_to_blis_diag( *diaga, &blis_diaga ); \ \ /* Convert/typecast negative values of m to zero. */ \ bli_convert_blas_dim1( *m, m0 ); \ \ /* If the input increments are negative, adjust the pointers so we can use positive increments instead. */ \ bli_convert_blas_incv( m0, x, *incx, x0, incx0 ); \ \ bli_check_error_code( BLIS_NOT_YET_IMPLEMENTED ); \ } #ifdef BLIS_ENABLE_BLAS INSERT_GENTFUNC_BLAS( tpmv, tpmv ) #endif blis-0.9.0/frame/compat/attic/bla_tpmv.h000066400000000000000000000042331422157504600201170ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype BLAS-to-BLIS interfaces. // #undef GENTPROT #define GENTPROT( ftype, ch, blasname ) \ \ BLIS_EXPORT_BLAS void PASTEF77(ch,blasname)( \ f77_char* uploa, \ f77_char* transa, \ f77_char* diaga, \ f77_int* m, \ ftype* a, \ ftype* x, f77_int* incx \ ); #ifdef BLIS_ENABLE_BLAS INSERT_GENTPROT_BLAS( tpmv ) #endif blis-0.9.0/frame/compat/attic/bla_tpsv.c000066400000000000000000000055541422157504600201270ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // Define BLAS-to-BLIS interfaces. // #undef GENTFUNC #define GENTFUNC( ftype, ch, blasname, blisname ) \ \ void PASTEF77(ch,blasname)( \ f77_char* uploa, \ f77_char* transa, \ f77_char* diaga, \ f77_int* m, \ ftype* a, \ ftype* x, f77_int* incx \ ) \ { \ uplo_t blis_uploa; \ trans_t blis_transa; \ diag_t blis_diaga; \ dim_t m0; \ ftype* x0; \ inc_t incx0; \ \ /* Map BLAS chars to their corresponding BLIS enumerated type value. */ \ bli_param_map_netlib_to_blis_uplo( *uploa, &blis_uploa ); \ bli_param_map_netlib_to_blis_trans( *transa, &blis_transa ); \ bli_param_map_netlib_to_blis_diag( *diaga, &blis_diaga ); \ \ /* Convert/typecast negative values of m to zero. */ \ bli_convert_blas_dim1( *m, m0 ); \ \ /* If the input increments are negative, adjust the pointers so we can use positive increments instead. */ \ bli_convert_blas_incv( m0, x, *incx, x0, incx0 ); \ \ bli_check_error_code( BLIS_NOT_YET_IMPLEMENTED ); \ } #ifdef BLIS_ENABLE_BLAS INSERT_GENTFUNC_BLAS( tpsv, tpsv ) #endif blis-0.9.0/frame/compat/attic/bla_tpsv.h000066400000000000000000000042331422157504600201250ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype BLAS-to-BLIS interfaces. // #undef GENTPROT #define GENTPROT( ftype, ch, blasname ) \ \ BLIS_EXPORT_BLAS void PASTEF77(ch,blasname)( \ f77_char* uploa, \ f77_char* transa, \ f77_char* diaga, \ f77_int* m, \ ftype* a, \ ftype* x, f77_int* incx \ ); #ifdef BLIS_ENABLE_BLAS INSERT_GENTPROT_BLAS( tpsv ) #endif blis-0.9.0/frame/compat/bla_amax.c000066400000000000000000000061371422157504600167530ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // Define BLAS-to-BLIS interfaces. // #undef GENTFUNC #define GENTFUNC( ftype_x, chx, blasname, blisname ) \ \ f77_int PASTEF772(i,chx,blasname) \ ( \ const f77_int* n, \ const ftype_x* x, const f77_int* incx \ ) \ { \ dim_t n0; \ ftype_x* x0; \ inc_t incx0; \ gint_t bli_index; \ f77_int f77_index; \ \ /* If the vector is empty, return an index of zero. This early check is needed to emulate netlib BLAS. Without it, bli_?amaxv() will return 0, which ends up getting incremented to 1 (below) before being returned, which is not what we want. */ \ if ( *n < 1 || *incx <= 0 ) return 0; \ \ /* Initialize BLIS. */ \ bli_init_auto(); \ \ /* Convert/typecast negative values of n to zero. */ \ bli_convert_blas_dim1( *n, n0 ); \ \ /* If the input increments are negative, adjust the pointers so we can use positive increments instead. */ \ bli_convert_blas_incv( n0, (ftype_x*)x, *incx, x0, incx0 ); \ \ /* Call BLIS interface. */ \ PASTEMAC2(chx,blisname,BLIS_TAPI_EX_SUF) \ ( \ n0, \ x0, incx0, \ &bli_index, \ NULL, \ NULL \ ); \ \ /* Convert zero-based BLIS (C) index to one-based BLAS (Fortran) index. Also, if the BLAS integer size differs from the BLIS integer size, that typecast occurs here. */ \ f77_index = bli_index + 1; \ \ /* Finalize BLIS. */ \ bli_finalize_auto(); \ \ return f77_index; \ } #ifdef BLIS_ENABLE_BLAS INSERT_GENTFUNC_BLAS( amax, amaxv ) #endif blis-0.9.0/frame/compat/bla_amax.h000066400000000000000000000037051422157504600167560ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype BLAS-to-BLIS interfaces. // #undef GENTPROT #define GENTPROT( ftype_x, chx, blasname ) \ \ BLIS_EXPORT_BLAS f77_int PASTEF772(i,chx,blasname) \ ( \ const f77_int* n, \ const ftype_x* x, const f77_int* incx \ ); #ifdef BLIS_ENABLE_BLAS INSERT_GENTPROT_BLAS( amax ) #endif blis-0.9.0/frame/compat/bla_asum.c000066400000000000000000000051161422157504600167660ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // Define BLAS-to-BLIS interfaces. // #undef GENTFUNCR2 #define GENTFUNCR2( ftype_x, ftype_r, chx, chr, blasname, blisname ) \ \ ftype_r PASTEF772(chr,chx,blasname) \ ( \ const f77_int* n, \ const ftype_x* x, const f77_int* incx \ ) \ { \ dim_t n0; \ ftype_x* x0; \ inc_t incx0; \ ftype_r asum; \ \ /* Initialize BLIS. */ \ bli_init_auto(); \ \ /* Convert/typecast negative values of n to zero. */ \ bli_convert_blas_dim1( *n, n0 ); \ \ /* If the input increments are negative, adjust the pointers so we can use positive increments instead. */ \ bli_convert_blas_incv( n0, (ftype_x*)x, *incx, x0, incx0 ); \ \ /* Call BLIS interface. */ \ PASTEMAC2(chx,blisname,BLIS_TAPI_EX_SUF) \ ( \ n0, \ x0, incx0, \ &asum, \ NULL, \ NULL \ ); \ \ /* Finalize BLIS. */ \ bli_finalize_auto(); \ \ return asum; \ } #ifdef BLIS_ENABLE_BLAS INSERT_GENTFUNCR2_BLAS( asum, asumv ) #endif blis-0.9.0/frame/compat/bla_asum.h000066400000000000000000000037331422157504600167760ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype BLAS-to-BLIS interfaces. // #undef GENTPROTR2 #define GENTPROTR2( ftype_x, ftype_r, chx, chr, blasname ) \ \ BLIS_EXPORT_BLAS ftype_r PASTEF772(chr,chx,blasname) \ ( \ const f77_int* n, \ const ftype_x* x, const f77_int* incx \ ); #ifdef BLIS_ENABLE_BLAS INSERT_GENTPROTR2_BLAS( asum ) #endif blis-0.9.0/frame/compat/bla_axpy.c000066400000000000000000000053341422157504600170040ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // Define BLAS-to-BLIS interfaces. // #undef GENTFUNC #define GENTFUNC( ftype, ch, blasname, blisname ) \ \ void PASTEF77(ch,blasname) \ ( \ const f77_int* n, \ const ftype* alpha, \ const ftype* x, const f77_int* incx, \ ftype* y, const f77_int* incy \ ) \ { \ dim_t n0; \ ftype* x0; \ ftype* y0; \ inc_t incx0; \ inc_t incy0; \ \ /* Initialize BLIS. */ \ bli_init_auto(); \ \ /* Convert/typecast negative values of n to zero. */ \ bli_convert_blas_dim1( *n, n0 ); \ \ /* If the input increments are negative, adjust the pointers so we can use positive increments instead. */ \ bli_convert_blas_incv( n0, (ftype*)x, *incx, x0, incx0 ); \ bli_convert_blas_incv( n0, (ftype*)y, *incy, y0, incy0 ); \ \ /* Call BLIS interface. */ \ PASTEMAC2(ch,blisname,BLIS_TAPI_EX_SUF) \ ( \ BLIS_NO_CONJUGATE, \ n0, \ (ftype*)alpha, \ x0, incx0, \ y0, incy0, \ NULL, \ NULL \ ); \ \ /* Finalize BLIS. */ \ bli_finalize_auto(); \ } #ifdef BLIS_ENABLE_BLAS INSERT_GENTFUNC_BLAS( axpy, axpyv ) #endif blis-0.9.0/frame/compat/bla_axpy.h000066400000000000000000000040111422157504600170000ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype BLAS-to-BLIS interfaces. // #undef GENTPROT #define GENTPROT( ftype, ch, blasname ) \ \ BLIS_EXPORT_BLAS void PASTEF77(ch,blasname) \ ( \ const f77_int* n, \ const ftype* alpha, \ const ftype* x, const f77_int* incx, \ ftype* y, const f77_int* incy \ ); #ifdef BLIS_ENABLE_BLAS INSERT_GENTPROT_BLAS( axpy ) #endif blis-0.9.0/frame/compat/bla_copy.c000066400000000000000000000052511422157504600167730ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // Define BLAS-to-BLIS interfaces. // #undef GENTFUNC #define GENTFUNC( ftype, ch, blasname, blisname ) \ \ void PASTEF77(ch,blasname) \ ( \ const f77_int* n, \ const ftype* x, const f77_int* incx, \ ftype* y, const f77_int* incy \ ) \ { \ dim_t n0; \ ftype* x0; \ ftype* y0; \ inc_t incx0; \ inc_t incy0; \ \ /* Initialize BLIS. */ \ bli_init_auto(); \ \ /* Convert/typecast negative values of n to zero. */ \ bli_convert_blas_dim1( *n, n0 ); \ \ /* If the input increments are negative, adjust the pointers so we can use positive increments instead. */ \ bli_convert_blas_incv( n0, (ftype*)x, *incx, x0, incx0 ); \ bli_convert_blas_incv( n0, (ftype*)y, *incy, y0, incy0 ); \ \ /* Call BLIS interface. */ \ PASTEMAC2(ch,blisname,BLIS_TAPI_EX_SUF) \ ( \ BLIS_NO_CONJUGATE, \ n0, \ x0, incx0, \ y0, incy0, \ NULL, \ NULL \ ); \ \ /* Finalize BLIS. */ \ bli_finalize_auto(); \ } #ifdef BLIS_ENABLE_BLAS INSERT_GENTFUNC_BLAS( copy, copyv ) #endif blis-0.9.0/frame/compat/bla_copy.h000066400000000000000000000037521422157504600170040ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype BLAS-to-BLIS interfaces. // #undef GENTPROT #define GENTPROT( ftype, ch, blasname ) \ \ BLIS_EXPORT_BLAS void PASTEF77(ch,blasname) \ ( \ const f77_int* n, \ const ftype* x, const f77_int* incx, \ ftype* y, const f77_int* incy \ ); #ifdef BLIS_ENABLE_BLAS INSERT_GENTPROT_BLAS( copy ) #endif blis-0.9.0/frame/compat/bla_dot.c000066400000000000000000000131741422157504600166120ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #ifdef BLIS_ENABLE_BLAS // // Define BLAS-to-BLIS interfaces. // #undef GENTFUNCDOT #define GENTFUNCDOT( ftype, ch, chc, blis_conjx, blasname, blisname ) \ \ ftype PASTEF772(ch,blasname,chc) \ ( \ const f77_int* n, \ const ftype* x, const f77_int* incx, \ const ftype* y, const f77_int* incy \ ) \ { \ dim_t n0; \ ftype* x0; \ ftype* y0; \ inc_t incx0; \ inc_t incy0; \ ftype rho; \ \ /* Initialize BLIS. */ \ bli_init_auto(); \ \ /* Convert/typecast negative values of n to zero. */ \ bli_convert_blas_dim1( *n, n0 ); \ \ /* If the input increments are negative, adjust the pointers so we can use positive increments instead. */ \ bli_convert_blas_incv( n0, (ftype*)x, *incx, x0, incx0 ); \ bli_convert_blas_incv( n0, (ftype*)y, *incy, y0, incy0 ); \ \ /* Call BLIS interface. */ \ PASTEMAC2(ch,blisname,BLIS_TAPI_EX_SUF) \ ( \ blis_conjx, \ BLIS_NO_CONJUGATE, \ n0, \ x0, incx0, \ y0, incy0, \ &rho, \ NULL, \ NULL \ ); \ \ /* Finalize BLIS. */ \ bli_finalize_auto(); \ \ return rho; \ } INSERT_GENTFUNCDOTR_BLAS( dot, dotv ) #ifdef BLIS_DISABLE_COMPLEX_RETURN_INTEL INSERT_GENTFUNCDOTC_BLAS( dot, dotv ) #else // #ifdef BLIS_ENABLE_COMPLEX_RETURN_INTEL // For the "intel" complex return type, use a hidden preceding parameter to // return the result rather than an actual return value. #undef GENTFUNCDOT #define GENTFUNCDOT( ftype, ch, chc, blis_conjx, blasname, blisname ) \ \ void PASTEF772(ch,blasname,chc) \ ( \ ftype* rhop, \ const f77_int* n, \ const ftype* x, const f77_int* incx, \ const ftype* y, const f77_int* incy \ ) \ { \ dim_t n0; \ ftype* x0; \ ftype* y0; \ inc_t incx0; \ inc_t incy0; \ ftype rho; \ \ /* Initialize BLIS. */ \ bli_init_auto(); \ \ /* Convert/typecast negative values of n to zero. */ \ bli_convert_blas_dim1( *n, n0 ); \ \ /* If the input increments are negative, adjust the pointers so we can use positive increments instead. */ \ bli_convert_blas_incv( n0, (ftype*)x, *incx, x0, incx0 ); \ bli_convert_blas_incv( n0, (ftype*)y, *incy, y0, incy0 ); \ \ /* Call BLIS interface. */ \ PASTEMAC2(ch,blisname,BLIS_TAPI_EX_SUF) \ ( \ blis_conjx, \ BLIS_NO_CONJUGATE, \ n0, \ x0, incx0, \ y0, incy0, \ &rho, \ NULL, \ NULL \ ); \ \ /* Finalize BLIS. */ \ bli_finalize_auto(); \ \ *rhop = rho; \ } INSERT_GENTFUNCDOTC_BLAS( dot, dotv ) #endif // -- "Black sheep" dot product function definitions -- // Input vectors stored in single precision, computed in double precision, // with result returned in single precision. float PASTEF77(sd,sdot) ( const f77_int* n, const float* sb, const float* x, const f77_int* incx, const float* y, const f77_int* incy ) { return ( float ) ( ( double )(*sb) + PASTEF77(d,sdot) ( n, x, incx, y, incy ) ); } // Input vectors stored in single precision, computed in double precision, // with result returned in double precision. double PASTEF77(d,sdot) ( const f77_int* n, const float* x, const f77_int* incx, const float* y, const f77_int* incy ) { dim_t n0; float* x0; float* y0; inc_t incx0; inc_t incy0; double rho; dim_t i; /* Initialization of BLIS is not required. */ /* Convert/typecast negative values of n to zero. */ bli_convert_blas_dim1( *n, n0 ); /* If the input increments are negative, adjust the pointers so we can use positive increments instead. */ bli_convert_blas_incv( n0, (float*)x, *incx, x0, incx0 ); bli_convert_blas_incv( n0, (float*)y, *incy, y0, incy0 ); rho = 0.0; for ( i = 0; i < n0; i++ ) { float* chi1 = x0 + (i )*incx0; float* psi1 = y0 + (i )*incy0; bli_ddots( (( double )(*chi1)), (( double )(*psi1)), rho ); } /* Finalization of BLIS is not required, because initialization was not required. */ return rho; } #endif blis-0.9.0/frame/compat/bla_dot.h000066400000000000000000000057021422157504600166150ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifdef BLIS_ENABLE_BLAS // // Prototype BLAS-to-BLIS interfaces. // #undef GENTPROTDOT #define GENTPROTDOT( ftype, ch, chc, blasname ) \ \ BLIS_EXPORT_BLAS ftype PASTEF772(ch,blasname,chc) \ ( \ const f77_int* n, \ const ftype* x, const f77_int* incx, \ const ftype* y, const f77_int* incy \ ); INSERT_GENTPROTDOTR_BLAS( dot ) #ifdef BLIS_DISABLE_COMPLEX_RETURN_INTEL INSERT_GENTPROTDOTC_BLAS( dot ) #else // For the "intel" complex return type, we use a hidden parameter (passed by // address) to return the result. #undef GENTPROTDOT #define GENTPROTDOT( ftype, ch, chc, blasname ) \ \ BLIS_EXPORT_BLAS void PASTEF772(ch,blasname,chc) \ ( \ ftype* rhop, \ const f77_int* n, \ const ftype* x, const f77_int* incx, \ const ftype* y, const f77_int* incy \ ); INSERT_GENTPROTDOTC_BLAS( dot ) #endif // -- "Black sheep" dot product function prototypes -- BLIS_EXPORT_BLAS float PASTEF77(sd,sdot) ( const f77_int* n, const float* sb, const float* x, const f77_int* incx, const float* y, const f77_int* incy ); BLIS_EXPORT_BLAS double PASTEF77(d,sdot) ( const f77_int* n, const float* x, const f77_int* incx, const float* y, const f77_int* incy ); #endif blis-0.9.0/frame/compat/bla_gemm.c000066400000000000000000000156771422157504600167630ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2019-2022, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // Define BLAS-to-BLIS interfaces. // #ifdef BLIS_BLAS3_CALLS_TAPI #undef GENTFUNC #define GENTFUNC( ftype, ch, blasname, blisname ) \ \ void PASTEF77(ch,blasname) \ ( \ const f77_char* transa, \ const f77_char* transb, \ const f77_int* m, \ const f77_int* n, \ const f77_int* k, \ const ftype* alpha, \ const ftype* a, const f77_int* lda, \ const ftype* b, const f77_int* ldb, \ const ftype* beta, \ ftype* c, const f77_int* ldc \ ) \ { \ trans_t blis_transa; \ trans_t blis_transb; \ dim_t m0, n0, k0; \ \ /* Initialize BLIS. */ \ bli_init_auto(); \ \ /* Perform BLAS parameter checking. */ \ PASTEBLACHK(blasname) \ ( \ MKSTR(ch), \ MKSTR(blasname), \ transa, \ transb, \ m, \ n, \ k, \ lda, \ ldb, \ ldc \ ); \ \ /* Map BLAS chars to their corresponding BLIS enumerated type value. */ \ bli_param_map_netlib_to_blis_trans( *transa, &blis_transa ); \ bli_param_map_netlib_to_blis_trans( *transb, &blis_transb ); \ \ /* Typecast BLAS integers to BLIS integers. */ \ bli_convert_blas_dim1( *m, m0 ); \ bli_convert_blas_dim1( *n, n0 ); \ bli_convert_blas_dim1( *k, k0 ); \ \ /* Set the row and column strides of the matrix operands. */ \ const inc_t rs_a = 1; \ const inc_t cs_a = *lda; \ const inc_t rs_b = 1; \ const inc_t cs_b = *ldb; \ const inc_t rs_c = 1; \ const inc_t cs_c = *ldc; \ \ /* Call BLIS interface. */ \ PASTEMAC2(ch,blisname,BLIS_TAPI_EX_SUF) \ ( \ blis_transa, \ blis_transb, \ m0, \ n0, \ k0, \ (ftype*)alpha, \ (ftype*)a, rs_a, cs_a, \ (ftype*)b, rs_b, cs_b, \ (ftype*)beta, \ (ftype*)c, rs_c, cs_c, \ NULL, \ NULL \ ); \ \ /* Finalize BLIS. */ \ bli_finalize_auto(); \ } #else #undef GENTFUNC #define GENTFUNC( ftype, ch, blasname, blisname ) \ \ void PASTEF77(ch,blasname) \ ( \ const f77_char* transa, \ const f77_char* transb, \ const f77_int* m, \ const f77_int* n, \ const f77_int* k, \ const ftype* alpha, \ const ftype* a, const f77_int* lda, \ const ftype* b, const f77_int* ldb, \ const ftype* beta, \ ftype* c, const f77_int* ldc \ ) \ { \ trans_t blis_transa; \ trans_t blis_transb; \ dim_t m0, n0, k0; \ \ /* Initialize BLIS. */ \ bli_init_auto(); \ \ /* Perform BLAS parameter checking. */ \ PASTEBLACHK(blasname) \ ( \ MKSTR(ch), \ MKSTR(blasname), \ transa, \ transb, \ m, \ n, \ k, \ lda, \ ldb, \ ldc \ ); \ \ /* Map BLAS chars to their corresponding BLIS enumerated type value. */ \ bli_param_map_netlib_to_blis_trans( *transa, &blis_transa ); \ bli_param_map_netlib_to_blis_trans( *transb, &blis_transb ); \ \ /* Typecast BLAS integers to BLIS integers. */ \ bli_convert_blas_dim1( *m, m0 ); \ bli_convert_blas_dim1( *n, n0 ); \ bli_convert_blas_dim1( *k, k0 ); \ \ /* Set the row and column strides of the matrix operands. */ \ const inc_t rs_a = 1; \ const inc_t cs_a = *lda; \ const inc_t rs_b = 1; \ const inc_t cs_b = *ldb; \ const inc_t rs_c = 1; \ const inc_t cs_c = *ldc; \ \ /* Handle special cases of m == 1 or n == 1 via gemv. */ \ if ( n0 == 1 ) \ { \ dim_t m0t, k0t; \ bli_set_dims_with_trans( blis_transa, m0, k0, &m0t, &k0t ); \ \ PASTEMAC2(ch,gemv,BLIS_TAPI_EX_SUF) \ ( \ blis_transa, \ bli_extract_conj( blis_transb ), \ m0t, k0t, \ ( ftype* )alpha, \ ( ftype* )a, rs_a, cs_a, \ ( ftype* )b, ( bli_does_notrans( blis_transb ) ? rs_b : cs_b ), \ ( ftype* )beta, \ c, rs_c, \ NULL, \ NULL \ ); \ return; \ } \ else if ( m0 == 1 ) \ { \ dim_t n0t, k0t; \ bli_set_dims_with_trans( blis_transb, n0, k0, &n0t, &k0t ); \ \ PASTEMAC2(ch,gemv,BLIS_TAPI_EX_SUF) \ ( \ blis_transb, \ bli_extract_conj( blis_transa ), \ n0t, k0t, \ ( ftype* )alpha, \ ( ftype* )b, cs_b, rs_b, \ ( ftype* )a, ( bli_does_notrans( blis_transa ) ? cs_a : rs_a ), \ ( ftype* )beta, \ c, cs_c, \ NULL, \ NULL \ ); \ return; \ } \ \ const num_t dt = PASTEMAC(ch,type); \ \ obj_t alphao = BLIS_OBJECT_INITIALIZER_1X1; \ obj_t ao = BLIS_OBJECT_INITIALIZER; \ obj_t bo = BLIS_OBJECT_INITIALIZER; \ obj_t betao = BLIS_OBJECT_INITIALIZER_1X1; \ obj_t co = BLIS_OBJECT_INITIALIZER; \ \ dim_t m0_a, n0_a; \ dim_t m0_b, n0_b; \ \ bli_set_dims_with_trans( blis_transa, m0, k0, &m0_a, &n0_a ); \ bli_set_dims_with_trans( blis_transb, k0, n0, &m0_b, &n0_b ); \ \ bli_obj_init_finish_1x1( dt, (ftype*)alpha, &alphao ); \ bli_obj_init_finish_1x1( dt, (ftype*)beta, &betao ); \ \ bli_obj_init_finish( dt, m0_a, n0_a, (ftype*)a, rs_a, cs_a, &ao ); \ bli_obj_init_finish( dt, m0_b, n0_b, (ftype*)b, rs_b, cs_b, &bo ); \ bli_obj_init_finish( dt, m0, n0, (ftype*)c, rs_c, cs_c, &co ); \ \ bli_obj_set_conjtrans( blis_transa, &ao ); \ bli_obj_set_conjtrans( blis_transb, &bo ); \ \ PASTEMAC(blisname,BLIS_OAPI_EX_SUF) \ ( \ &alphao, \ &ao, \ &bo, \ &betao, \ &co, \ NULL, \ NULL \ ); \ \ /* Finalize BLIS. */ \ bli_finalize_auto(); \ } #endif #ifdef BLIS_ENABLE_BLAS INSERT_GENTFUNC_BLAS( gemm, gemm ) #endif blis-0.9.0/frame/compat/bla_gemm.h000066400000000000000000000043251422157504600167540ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype BLAS-to-BLIS interfaces. // #undef GENTPROT #define GENTPROT( ftype, ch, blasname ) \ \ BLIS_EXPORT_BLAS void PASTEF77(ch,blasname) \ ( \ const f77_char* transa, \ const f77_char* transb, \ const f77_int* m, \ const f77_int* n, \ const f77_int* k, \ const ftype* alpha, \ const ftype* a, const f77_int* lda, \ const ftype* b, const f77_int* ldb, \ const ftype* beta, \ ftype* c, const f77_int* ldc \ ); #ifdef BLIS_ENABLE_BLAS INSERT_GENTPROT_BLAS( gemm ) #endif blis-0.9.0/frame/compat/bla_gemv.c000066400000000000000000000112641422157504600167600ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2022, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // Define BLAS-to-BLIS interfaces. // #undef GENTFUNC #define GENTFUNC( ftype, ch, blasname, blisname ) \ \ void PASTEF77(ch,blasname) \ ( \ const f77_char* transa, \ const f77_int* m, \ const f77_int* n, \ const ftype* alpha, \ const ftype* a, const f77_int* lda, \ const ftype* x, const f77_int* incx, \ const ftype* beta, \ ftype* y, const f77_int* incy \ ) \ { \ trans_t blis_transa; \ dim_t m0, n0; \ dim_t m_y, n_x; \ ftype* x0; \ ftype* y0; \ inc_t incx0; \ inc_t incy0; \ \ /* Initialize BLIS. */ \ bli_init_auto(); \ \ /* Perform BLAS parameter checking. */ \ PASTEBLACHK(blasname) \ ( \ MKSTR(ch), \ MKSTR(blasname), \ transa, \ m, \ n, \ lda, \ incx, \ incy \ ); \ \ /* Map BLAS chars to their corresponding BLIS enumerated type value. */ \ bli_param_map_netlib_to_blis_trans( *transa, &blis_transa ); \ \ /* Convert/typecast negative values of m and n to zero. */ \ bli_convert_blas_dim1( *m, m0 ); \ bli_convert_blas_dim1( *n, n0 ); \ \ /* Determine the dimensions of x and y so we can adjust the increments, if necessary.*/ \ bli_set_dims_with_trans( blis_transa, m0, n0, &m_y, &n_x ); \ \ /* BLAS handles cases where y has no elements as well as those where x has no elements. In the case of the former, it cannot do any work since the output vector is empty; but in the latter case, BLAS has peculiar semantics. When x has no elements (and transa(A) has no columns), BLAS returns immediately without performing any computation even if the number of elements of y (and rows of transa(A)) is non-zero, in which case any sane interpretations of gemv would have the the operation reduce to y := beta * y. Here, we emulate the BLAS exactly so as to provide "bug-for-bug" compatibility. Note that this extreme level of compatibility would not be contemplated if it weren't for the fact that some BLAS unit tests actually check for this behavior. Also, it should be emphasized that BLIS, when called natively, does NOT exhibit this quirky behavior; it will scale y by beta as one would expect. */ \ if ( m_y > 0 && n_x == 0 ) \ { \ /* Finalize BLIS. */ \ bli_finalize_auto(); \ \ return; \ } \ \ /* If the input increments are negative, adjust the pointers so we can use positive increments instead. */ \ bli_convert_blas_incv( n_x, (ftype*)x, *incx, x0, incx0 ); \ bli_convert_blas_incv( m_y, (ftype*)y, *incy, y0, incy0 ); \ \ /* Set the row and column strides of A. */ \ const inc_t rs_a = 1; \ const inc_t cs_a = *lda; \ \ /* Call BLIS interface. */ \ PASTEMAC2(ch,blisname,BLIS_TAPI_EX_SUF) \ ( \ blis_transa, \ BLIS_NO_CONJUGATE, \ m0, \ n0, \ (ftype*)alpha, \ (ftype*)a, rs_a, cs_a, \ x0, incx0, \ (ftype*)beta, \ y0, incy0, \ NULL, \ NULL \ ); \ \ /* Finalize BLIS. */ \ bli_finalize_auto(); \ } #ifdef BLIS_ENABLE_BLAS INSERT_GENTFUNC_BLAS( gemv, gemv ) #endif blis-0.9.0/frame/compat/bla_gemv.h000066400000000000000000000042321422157504600167620ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype BLAS-to-BLIS interfaces. // #undef GENTPROT #define GENTPROT( ftype, ch, blasname ) \ \ BLIS_EXPORT_BLAS void PASTEF77(ch,blasname) \ ( \ const f77_char* transa, \ const f77_int* m, \ const f77_int* n, \ const ftype* alpha, \ const ftype* a, const f77_int* lda, \ const ftype* x, const f77_int* incx, \ const ftype* beta, \ ftype* y, const f77_int* incy \ ); #ifdef BLIS_ENABLE_BLAS INSERT_GENTPROT_BLAS( gemv ) #endif blis-0.9.0/frame/compat/bla_ger.c000066400000000000000000000063101422157504600165730ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // Define BLAS-to-BLIS interfaces. // #undef GENTFUNCDOT #define GENTFUNCDOT( ftype, ch, chc, blis_conjy, blasname, blisname ) \ \ void PASTEF772(ch,blasname,chc) \ ( \ const f77_int* m, \ const f77_int* n, \ const ftype* alpha, \ const ftype* x, const f77_int* incx, \ const ftype* y, const f77_int* incy, \ ftype* a, const f77_int* lda \ ) \ { \ dim_t m0, n0; \ ftype* x0; \ ftype* y0; \ inc_t incx0; \ inc_t incy0; \ \ /* Initialize BLIS. */ \ bli_init_auto(); \ \ /* Perform BLAS parameter checking. */ \ PASTEBLACHK(blasname) \ ( \ MKSTR(ch), \ MKSTR(blasname), \ MKSTR(chc), \ m, \ n, \ incx, \ incy, \ lda \ ); \ \ /* Convert/typecast negative values of m and n to zero. */ \ bli_convert_blas_dim1( *m, m0 ); \ bli_convert_blas_dim1( *n, n0 ); \ \ /* If the input increments are negative, adjust the pointers so we can use positive increments instead. */ \ bli_convert_blas_incv( m0, (ftype*)x, *incx, x0, incx0 ); \ bli_convert_blas_incv( n0, (ftype*)y, *incy, y0, incy0 ); \ \ /* Set the row and column strides of A. */ \ const inc_t rs_a = 1; \ const inc_t cs_a = *lda; \ \ /* Call BLIS interface. */ \ PASTEMAC2(ch,blisname,BLIS_TAPI_EX_SUF) \ ( \ BLIS_NO_CONJUGATE, \ blis_conjy, \ m0, \ n0, \ (ftype*)alpha, \ x0, incx0, \ y0, incy0, \ (ftype*)a, rs_a, cs_a, \ NULL, \ NULL \ ); \ \ /* Finalize BLIS. */ \ bli_finalize_auto(); \ } #ifdef BLIS_ENABLE_BLAS INSERT_GENTFUNCDOT_BLAS( ger, ger ) #endif blis-0.9.0/frame/compat/bla_ger.h000066400000000000000000000041521422157504600166020ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype BLAS-to-BLIS interfaces. // #undef GENTPROTDOT #define GENTPROTDOT( ftype, chxy, chc, blasname ) \ \ BLIS_EXPORT_BLAS void PASTEF772(chxy,blasname,chc) \ ( \ const f77_int* m, \ const f77_int* n, \ const ftype* alpha, \ const ftype* x, const f77_int* incx, \ const ftype* y, const f77_int* incy, \ ftype* a, const f77_int* lda \ ); #ifdef BLIS_ENABLE_BLAS INSERT_GENTPROTDOT_BLAS( ger ) #endif blis-0.9.0/frame/compat/bla_hemm.c000066400000000000000000000140761422157504600167540ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // Define BLAS-to-BLIS interfaces. // #ifdef BLIS_BLAS3_CALLS_TAPI #undef GENTFUNCCO #define GENTFUNCCO( ftype, ftype_r, ch, chr, blasname, blisname ) \ \ void PASTEF77(ch,blasname) \ ( \ const f77_char* side, \ const f77_char* uploa, \ const f77_int* m, \ const f77_int* n, \ const ftype* alpha, \ const ftype* a, const f77_int* lda, \ const ftype* b, const f77_int* ldb, \ const ftype* beta, \ ftype* c, const f77_int* ldc \ ) \ { \ side_t blis_side; \ uplo_t blis_uploa; \ dim_t m0, n0; \ \ /* Initialize BLIS. */ \ bli_init_auto(); \ \ /* Perform BLAS parameter checking. */ \ PASTEBLACHK(blasname) \ ( \ MKSTR(ch), \ MKSTR(blasname), \ side, \ uploa, \ m, \ n, \ lda, \ ldb, \ ldc \ ); \ \ /* Map BLAS chars to their corresponding BLIS enumerated type value. */ \ bli_param_map_netlib_to_blis_side( *side, &blis_side ); \ bli_param_map_netlib_to_blis_uplo( *uploa, &blis_uploa ); \ \ /* Typecast BLAS integers to BLIS integers. */ \ bli_convert_blas_dim1( *m, m0 ); \ bli_convert_blas_dim1( *n, n0 ); \ \ /* Set the row and column strides of the matrix operands. */ \ const inc_t rs_a = 1; \ const inc_t cs_a = *lda; \ const inc_t rs_b = 1; \ const inc_t cs_b = *ldb; \ const inc_t rs_c = 1; \ const inc_t cs_c = *ldc; \ \ /* Call BLIS interface. */ \ PASTEMAC2(ch,blisname,BLIS_TAPI_EX_SUF) \ ( \ blis_side, \ blis_uploa, \ BLIS_NO_CONJUGATE, \ BLIS_NO_TRANSPOSE, \ m0, \ n0, \ (ftype*)alpha, \ (ftype*)a, rs_a, cs_a, \ (ftype*)b, rs_b, cs_b, \ (ftype*)beta, \ (ftype*)c, rs_c, cs_c, \ NULL, \ NULL \ ); \ \ /* Finalize BLIS. */ \ bli_finalize_auto(); \ } #else #undef GENTFUNCCO #define GENTFUNCCO( ftype, ftype_r, ch, chr, blasname, blisname ) \ \ void PASTEF77(ch,blasname) \ ( \ const f77_char* side, \ const f77_char* uploa, \ const f77_int* m, \ const f77_int* n, \ const ftype* alpha, \ const ftype* a, const f77_int* lda, \ const ftype* b, const f77_int* ldb, \ const ftype* beta, \ ftype* c, const f77_int* ldc \ ) \ { \ side_t blis_side; \ uplo_t blis_uploa; \ dim_t m0, n0; \ \ /* Initialize BLIS. */ \ bli_init_auto(); \ \ /* Perform BLAS parameter checking. */ \ PASTEBLACHK(blasname) \ ( \ MKSTR(ch), \ MKSTR(blasname), \ side, \ uploa, \ m, \ n, \ lda, \ ldb, \ ldc \ ); \ \ /* Map BLAS chars to their corresponding BLIS enumerated type value. */ \ bli_param_map_netlib_to_blis_side( *side, &blis_side ); \ bli_param_map_netlib_to_blis_uplo( *uploa, &blis_uploa ); \ \ /* Typecast BLAS integers to BLIS integers. */ \ bli_convert_blas_dim1( *m, m0 ); \ bli_convert_blas_dim1( *n, n0 ); \ \ /* Set the row and column strides of the matrix operands. */ \ const inc_t rs_a = 1; \ const inc_t cs_a = *lda; \ const inc_t rs_b = 1; \ const inc_t cs_b = *ldb; \ const inc_t rs_c = 1; \ const inc_t cs_c = *ldc; \ \ const num_t dt = PASTEMAC(ch,type); \ \ const conj_t conja = BLIS_NO_CONJUGATE; \ const trans_t transb = BLIS_NO_TRANSPOSE; \ const struc_t struca = BLIS_HERMITIAN; \ \ obj_t alphao = BLIS_OBJECT_INITIALIZER_1X1; \ obj_t ao = BLIS_OBJECT_INITIALIZER; \ obj_t bo = BLIS_OBJECT_INITIALIZER; \ obj_t betao = BLIS_OBJECT_INITIALIZER_1X1; \ obj_t co = BLIS_OBJECT_INITIALIZER; \ \ dim_t mn0_a; \ dim_t m0_b, n0_b; \ \ bli_set_dim_with_side( blis_side, m0, n0, &mn0_a ); \ bli_set_dims_with_trans( transb, m0, n0, &m0_b, &n0_b ); \ \ bli_obj_init_finish_1x1( dt, (ftype*)alpha, &alphao ); \ bli_obj_init_finish_1x1( dt, (ftype*)beta, &betao ); \ \ bli_obj_init_finish( dt, mn0_a, mn0_a, (ftype*)a, rs_a, cs_a, &ao ); \ bli_obj_init_finish( dt, m0_b, n0_b, (ftype*)b, rs_b, cs_b, &bo ); \ bli_obj_init_finish( dt, m0, n0, (ftype*)c, rs_c, cs_c, &co ); \ \ bli_obj_set_uplo( blis_uploa, &ao ); \ bli_obj_set_conj( conja, &ao ); \ bli_obj_set_conjtrans( transb, &bo ); \ \ bli_obj_set_struc( struca, &ao ); \ \ PASTEMAC(blisname,BLIS_OAPI_EX_SUF) \ ( \ blis_side, \ &alphao, \ &ao, \ &bo, \ &betao, \ &co, \ NULL, \ NULL \ ); \ \ /* Finalize BLIS. */ \ bli_finalize_auto(); \ } #endif #ifdef BLIS_ENABLE_BLAS INSERT_GENTFUNCCO_BLAS( hemm, hemm ) #endif blis-0.9.0/frame/compat/bla_hemm.h000066400000000000000000000043121422157504600167510ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype BLAS-to-BLIS interfaces. // #undef GENTPROTCO #define GENTPROTCO( ftype, ftype_r, ch, chr, blasname ) \ \ BLIS_EXPORT_BLAS void PASTEF77(ch,blasname) \ ( \ const f77_char* side, \ const f77_char* uploa, \ const f77_int* m, \ const f77_int* n, \ const ftype* alpha, \ const ftype* a, const f77_int* lda, \ const ftype* b, const f77_int* ldb, \ const ftype* beta, \ ftype* c, const f77_int* ldc \ ); #ifdef BLIS_ENABLE_BLAS INSERT_GENTPROTCO_BLAS( hemm ) #endif blis-0.9.0/frame/compat/bla_hemv.c000066400000000000000000000065601422157504600167640ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // Define BLAS-to-BLIS interfaces. // #undef GENTFUNCCO #define GENTFUNCCO( ftype, ftype_r, ch, chr, blasname, blisname ) \ \ void PASTEF77(ch,blasname) \ ( \ const f77_char* uploa, \ const f77_int* m, \ const ftype* alpha, \ const ftype* a, const f77_int* lda, \ const ftype* x, const f77_int* incx, \ const ftype* beta, \ ftype* y, const f77_int* incy \ ) \ { \ uplo_t blis_uploa; \ dim_t m0; \ ftype* x0; \ ftype* y0; \ inc_t incx0; \ inc_t incy0; \ \ /* Initialize BLIS. */ \ bli_init_auto(); \ \ /* Perform BLAS parameter checking. */ \ PASTEBLACHK(blasname) \ ( \ MKSTR(ch), \ MKSTR(blasname), \ uploa, \ m, \ lda, \ incx, \ incy \ ); \ \ /* Map BLAS chars to their corresponding BLIS enumerated type value. */ \ bli_param_map_netlib_to_blis_uplo( *uploa, &blis_uploa ); \ \ /* Convert/typecast negative values of m to zero. */ \ bli_convert_blas_dim1( *m, m0 ); \ \ /* If the input increments are negative, adjust the pointers so we can use positive increments instead. */ \ bli_convert_blas_incv( m0, (ftype*)x, *incx, x0, incx0 ); \ bli_convert_blas_incv( m0, (ftype*)y, *incy, y0, incy0 ); \ \ /* Set the row and column strides of A. */ \ const inc_t rs_a = 1; \ const inc_t cs_a = *lda; \ \ /* Call BLIS interface. */ \ PASTEMAC2(ch,blisname,BLIS_TAPI_EX_SUF) \ ( \ blis_uploa, \ BLIS_NO_CONJUGATE, \ BLIS_NO_CONJUGATE, \ m0, \ (ftype*)alpha, \ (ftype*)a, rs_a, cs_a, \ x0, incx0, \ (ftype*)beta, \ y0, incy0, \ NULL, \ NULL \ ); \ \ /* Finalize BLIS. */ \ bli_finalize_auto(); \ } #ifdef BLIS_ENABLE_BLAS INSERT_GENTFUNCCO_BLAS( hemv, hemv ) #endif blis-0.9.0/frame/compat/bla_hemv.h000066400000000000000000000042211422157504600167610ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype BLAS-to-BLIS interfaces. // #undef GENTPROTCO #define GENTPROTCO( ftype, ftype_r, ch, chr, blasname ) \ \ BLIS_EXPORT_BLAS void PASTEF77(ch,blasname) \ ( \ const f77_char* uploa, \ const f77_int* m, \ const ftype* alpha, \ const ftype* a, const f77_int* lda, \ const ftype* x, const f77_int* incx, \ const ftype* beta, \ ftype* y, const f77_int* incy \ ); #ifdef BLIS_ENABLE_BLAS INSERT_GENTPROTCO_BLAS( hemv ) #endif blis-0.9.0/frame/compat/bla_her.c000066400000000000000000000061741422157504600166040ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // Define BLAS-to-BLIS interfaces. // #undef GENTFUNCCO #define GENTFUNCCO( ftype, ftype_r, ch, chr, blasname, blisname ) \ \ void PASTEF77(ch,blasname) \ ( \ const f77_char* uploa, \ const f77_int* m, \ const ftype_r* alpha, \ const ftype* x, const f77_int* incx, \ ftype* a, const f77_int* lda \ ) \ { \ uplo_t blis_uploa; \ dim_t m0; \ ftype* x0; \ inc_t incx0; \ \ /* Initialize BLIS. */ \ bli_init_auto(); \ \ /* Perform BLAS parameter checking. */ \ PASTEBLACHK(blasname) \ ( \ MKSTR(ch), \ MKSTR(blasname), \ uploa, \ m, \ incx, \ lda \ ); \ \ /* Map BLAS chars to their corresponding BLIS enumerated type value. */ \ bli_param_map_netlib_to_blis_uplo( *uploa, &blis_uploa ); \ \ /* Convert/typecast negative values of m to zero. */ \ bli_convert_blas_dim1( *m, m0 ); \ \ /* If the input increments are negative, adjust the pointers so we can use positive increments instead. */ \ bli_convert_blas_incv( m0, (ftype*)x, *incx, x0, incx0 ); \ \ /* Set the row and column strides of A. */ \ const inc_t rs_a = 1; \ const inc_t cs_a = *lda; \ \ /* Call BLIS interface. */ \ PASTEMAC2(ch,blisname,BLIS_TAPI_EX_SUF) \ ( \ blis_uploa, \ BLIS_NO_CONJUGATE, \ m0, \ (ftype_r*)alpha, \ x0, incx0, \ (ftype*)a, rs_a, cs_a, \ NULL, \ NULL \ ); \ \ /* Finalize BLIS. */ \ bli_finalize_auto(); \ } #ifdef BLIS_ENABLE_BLAS INSERT_GENTFUNCCO_BLAS( her, her ) #endif blis-0.9.0/frame/compat/bla_her.h000066400000000000000000000041001422157504600165740ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype BLAS-to-BLIS interfaces. // #undef GENTPROTCO #define GENTPROTCO( ftype, ftype_r, ch, chr, blasname ) \ \ BLIS_EXPORT_BLAS void PASTEF77(ch,blasname) \ ( \ const f77_char* uploa, \ const f77_int* m, \ const ftype_r* alpha, \ const ftype* x, const f77_int* incx, \ ftype* a, const f77_int* lda \ ); #ifdef BLIS_ENABLE_BLAS INSERT_GENTPROTCO_BLAS( her ) #endif blis-0.9.0/frame/compat/bla_her2.c000066400000000000000000000064761422157504600166730ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // Define BLAS-to-BLIS interfaces. // #undef GENTFUNCCO #define GENTFUNCCO( ftype, ftype_r, ch, chr, blasname, blisname ) \ \ void PASTEF77(ch,blasname) \ ( \ const f77_char* uploa, \ const f77_int* m, \ const ftype* alpha, \ const ftype* x, const f77_int* incx, \ const ftype* y, const f77_int* incy, \ ftype* a, const f77_int* lda \ ) \ { \ uplo_t blis_uploa; \ dim_t m0; \ ftype* x0; \ ftype* y0; \ inc_t incx0; \ inc_t incy0; \ \ /* Initialize BLIS. */ \ bli_init_auto(); \ \ /* Perform BLAS parameter checking. */ \ PASTEBLACHK(blasname) \ ( \ MKSTR(ch), \ MKSTR(blasname), \ uploa, \ m, \ incx, \ incy, \ lda \ ); \ \ /* Map BLAS chars to their corresponding BLIS enumerated type value. */ \ bli_param_map_netlib_to_blis_uplo( *uploa, &blis_uploa ); \ \ /* Convert/typecast negative values of m to zero. */ \ bli_convert_blas_dim1( *m, m0 ); \ \ /* If the input increments are negative, adjust the pointers so we can use positive increments instead. */ \ bli_convert_blas_incv( m0, (ftype*)x, *incx, x0, incx0 ); \ bli_convert_blas_incv( m0, (ftype*)y, *incy, y0, incy0 ); \ \ /* Set the row and column strides of A. */ \ const inc_t rs_a = 1; \ const inc_t cs_a = *lda; \ \ /* Call BLIS interface. */ \ PASTEMAC2(ch,blisname,BLIS_TAPI_EX_SUF) \ ( \ blis_uploa, \ BLIS_NO_CONJUGATE, \ BLIS_NO_CONJUGATE, \ m0, \ (ftype*)alpha, \ x0, incx0, \ y0, incy0, \ (ftype*)a, rs_a, cs_a, \ NULL, \ NULL \ ); \ \ /* Finalize BLIS. */ \ bli_finalize_auto(); \ } #ifdef BLIS_ENABLE_BLAS INSERT_GENTFUNCCO_BLAS( her2, her2 ) #endif blis-0.9.0/frame/compat/bla_her2.h000066400000000000000000000041621422157504600166660ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype BLAS-to-BLIS interfaces. // #undef GENTPROTCO #define GENTPROTCO( ftype, ftype_r, ch, chr, blasname ) \ \ BLIS_EXPORT_BLAS void PASTEF77(ch,blasname) \ ( \ const f77_char* uploa, \ const f77_int* m, \ const ftype* alpha, \ const ftype* x, const f77_int* incx, \ const ftype* y, const f77_int* incy, \ ftype* a, const f77_int* lda \ ); #ifdef BLIS_ENABLE_BLAS INSERT_GENTPROTCO_BLAS( her2 ) #endif blis-0.9.0/frame/compat/bla_her2k.c000066400000000000000000000160031422157504600170310ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // Define BLAS-to-BLIS interfaces. // #ifdef BLIS_BLAS3_CALLS_TAPI #undef GENTFUNCCO #define GENTFUNCCO( ftype, ftype_r, ch, chr, blasname, blisname ) \ \ void PASTEF77(ch,blasname) \ ( \ const f77_char* uploc, \ const f77_char* transa, \ const f77_int* m, \ const f77_int* k, \ const ftype* alpha, \ const ftype* a, const f77_int* lda, \ const ftype* b, const f77_int* ldb, \ const ftype_r* beta, \ ftype* c, const f77_int* ldc \ ) \ { \ uplo_t blis_uploc; \ trans_t blis_transa; \ dim_t m0, k0; \ \ /* Initialize BLIS. */ \ bli_init_auto(); \ \ /* Perform BLAS parameter checking. */ \ PASTEBLACHK(blasname) \ ( \ MKSTR(ch), \ MKSTR(blasname), \ uploc, \ transa, \ m, \ k, \ lda, \ ldb, \ ldc \ ); \ \ /* Map BLAS chars to their corresponding BLIS enumerated type value. */ \ bli_param_map_netlib_to_blis_uplo( *uploc, &blis_uploc ); \ bli_param_map_netlib_to_blis_trans( *transa, &blis_transa ); \ \ /* Typecast BLAS integers to BLIS integers. */ \ bli_convert_blas_dim1( *m, m0 ); \ bli_convert_blas_dim1( *k, k0 ); \ \ /* We emulate the BLAS early return behavior with the following conditional, which returns if one of the following is true: - matrix C is empty - the rank-2k product is empty (either because alpha is zero or k is zero) AND matrix C is not scaled. */ \ if ( m0 == 0 || \ ( ( PASTEMAC(ch,eq0)( *alpha ) || k0 == 0 ) \ && PASTEMAC(chr,eq1)( *beta ) \ ) \ ) \ { \ /* Finalize BLIS. */ \ bli_finalize_auto(); \ \ return; \ } \ \ /* Set the row and column strides of the matrix operands. */ \ const inc_t rs_a = 1; \ const inc_t cs_a = *lda; \ const inc_t rs_b = 1; \ const inc_t cs_b = *ldb; \ const inc_t rs_c = 1; \ const inc_t cs_c = *ldc; \ \ /* Call BLIS interface. */ \ PASTEMAC2(ch,blisname,BLIS_TAPI_EX_SUF) \ ( \ blis_uploc, \ blis_transa, \ blis_transa, \ m0, \ k0, \ (ftype*)alpha, \ (ftype*)a, rs_a, cs_a, \ (ftype*)b, rs_b, cs_b, \ (ftype_r*)beta, \ (ftype*)c, rs_c, cs_c, \ NULL, \ NULL \ ); \ \ /* Finalize BLIS. */ \ bli_finalize_auto(); \ } #else #undef GENTFUNCCO #define GENTFUNCCO( ftype, ftype_r, ch, chr, blasname, blisname ) \ \ void PASTEF77(ch,blasname) \ ( \ const f77_char* uploc, \ const f77_char* transa, \ const f77_int* m, \ const f77_int* k, \ const ftype* alpha, \ const ftype* a, const f77_int* lda, \ const ftype* b, const f77_int* ldb, \ const ftype_r* beta, \ ftype* c, const f77_int* ldc \ ) \ { \ uplo_t blis_uploc; \ trans_t blis_transa; \ dim_t m0, k0; \ \ /* Initialize BLIS. */ \ bli_init_auto(); \ \ /* Perform BLAS parameter checking. */ \ PASTEBLACHK(blasname) \ ( \ MKSTR(ch), \ MKSTR(blasname), \ uploc, \ transa, \ m, \ k, \ lda, \ ldb, \ ldc \ ); \ \ /* Map BLAS chars to their corresponding BLIS enumerated type value. */ \ bli_param_map_netlib_to_blis_uplo( *uploc, &blis_uploc ); \ bli_param_map_netlib_to_blis_trans( *transa, &blis_transa ); \ \ /* Typecast BLAS integers to BLIS integers. */ \ bli_convert_blas_dim1( *m, m0 ); \ bli_convert_blas_dim1( *k, k0 ); \ \ /* We emulate the BLAS early return behavior with the following conditional, which returns if one of the following is true: - matrix C is empty - the rank-2k product is empty (either because alpha is zero or k is zero) AND matrix C is not scaled. */ \ if ( m0 == 0 || \ ( ( PASTEMAC(ch,eq0)( *alpha ) || k0 == 0 ) \ && PASTEMAC(chr,eq1)( *beta ) \ ) \ ) \ { \ /* Finalize BLIS. */ \ bli_finalize_auto(); \ \ return; \ } \ \ /* Set the row and column strides of the matrix operands. */ \ const inc_t rs_a = 1; \ const inc_t cs_a = *lda; \ const inc_t rs_b = 1; \ const inc_t cs_b = *ldb; \ const inc_t rs_c = 1; \ const inc_t cs_c = *ldc; \ \ const num_t dt_r = PASTEMAC(chr,type); \ const num_t dt = PASTEMAC(ch,type); \ \ const trans_t transb = blis_transa; \ const struc_t strucc = BLIS_HERMITIAN; \ \ obj_t alphao = BLIS_OBJECT_INITIALIZER_1X1; \ obj_t ao = BLIS_OBJECT_INITIALIZER; \ obj_t bo = BLIS_OBJECT_INITIALIZER; \ obj_t betao = BLIS_OBJECT_INITIALIZER_1X1; \ obj_t co = BLIS_OBJECT_INITIALIZER; \ \ dim_t m0_a, n0_a; \ dim_t m0_b, n0_b; \ \ bli_set_dims_with_trans( blis_transa, m0, k0, &m0_a, &n0_a ); \ bli_set_dims_with_trans( transb, m0, k0, &m0_b, &n0_b ); \ \ bli_obj_init_finish_1x1( dt, (ftype* )alpha, &alphao ); \ bli_obj_init_finish_1x1( dt_r, (ftype_r*)beta, &betao ); \ \ bli_obj_init_finish( dt, m0_a, n0_a, (ftype*)a, rs_a, cs_a, &ao ); \ bli_obj_init_finish( dt, m0_b, n0_b, (ftype*)b, rs_b, cs_b, &bo ); \ bli_obj_init_finish( dt, m0, m0, (ftype*)c, rs_c, cs_c, &co ); \ \ bli_obj_set_uplo( blis_uploc, &co ); \ bli_obj_set_conjtrans( blis_transa, &ao ); \ bli_obj_set_conjtrans( transb, &bo ); \ \ bli_obj_set_struc( strucc, &co ); \ \ PASTEMAC(blisname,BLIS_OAPI_EX_SUF) \ ( \ &alphao, \ &ao, \ &bo, \ &betao, \ &co, \ NULL, \ NULL \ ); \ \ /* Finalize BLIS. */ \ bli_finalize_auto(); \ } #endif #ifdef BLIS_ENABLE_BLAS INSERT_GENTFUNCCO_BLAS( her2k, her2k ) #endif blis-0.9.0/frame/compat/bla_her2k.h000066400000000000000000000043151422157504600170410ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype BLAS-to-BLIS interfaces. // #undef GENTPROTCO #define GENTPROTCO( ftype, ftype_r, ch, chr, blasname ) \ \ BLIS_EXPORT_BLAS void PASTEF77(ch,blasname) \ ( \ const f77_char* uploc, \ const f77_char* transa, \ const f77_int* m, \ const f77_int* k, \ const ftype* alpha, \ const ftype* a, const f77_int* lda, \ const ftype* b, const f77_int* ldb, \ const ftype_r* beta, \ ftype* c, const f77_int* ldc \ ); #ifdef BLIS_ENABLE_BLAS INSERT_GENTPROTCO_BLAS( her2k ) #endif blis-0.9.0/frame/compat/bla_herk.c000066400000000000000000000147121422157504600167540ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // Define BLAS-to-BLIS interfaces. // #ifdef BLIS_BLAS3_CALLS_TAPI #undef GENTFUNCCO #define GENTFUNCCO( ftype, ftype_r, ch, chr, blasname, blisname ) \ \ void PASTEF77(ch,blasname) \ ( \ const f77_char* uploc, \ const f77_char* transa, \ const f77_int* m, \ const f77_int* k, \ const ftype_r* alpha, \ const ftype* a, const f77_int* lda, \ const ftype_r* beta, \ ftype* c, const f77_int* ldc \ ) \ { \ uplo_t blis_uploc; \ trans_t blis_transa; \ dim_t m0, k0; \ \ /* Initialize BLIS. */ \ bli_init_auto(); \ \ /* Perform BLAS parameter checking. */ \ PASTEBLACHK(blasname) \ ( \ MKSTR(ch), \ MKSTR(blasname), \ uploc, \ transa, \ m, \ k, \ lda, \ ldc \ ); \ \ /* Map BLAS chars to their corresponding BLIS enumerated type value. */ \ bli_param_map_netlib_to_blis_uplo( *uploc, &blis_uploc ); \ bli_param_map_netlib_to_blis_trans( *transa, &blis_transa ); \ \ /* Typecast BLAS integers to BLIS integers. */ \ bli_convert_blas_dim1( *m, m0 ); \ bli_convert_blas_dim1( *k, k0 ); \ \ /* We emulate the BLAS early return behavior with the following conditional, which returns if one of the following is true: - matrix C is empty - the rank-k product is empty (either because alpha is zero or k is zero) AND matrix C is not scaled. */ \ if ( m0 == 0 || \ ( ( PASTEMAC(chr,eq0)( *alpha ) || k0 == 0 ) \ && PASTEMAC(chr,eq1)( *beta ) \ ) \ ) \ { \ /* Finalize BLIS. */ \ bli_finalize_auto(); \ \ return; \ } \ \ /* Set the row and column strides of the matrix operands. */ \ const inc_t rs_a = 1; \ const inc_t cs_a = *lda; \ const inc_t rs_c = 1; \ const inc_t cs_c = *ldc; \ \ /* Call BLIS interface. */ \ PASTEMAC2(ch,blisname,BLIS_TAPI_EX_SUF) \ ( \ blis_uploc, \ blis_transa, \ m0, \ k0, \ (ftype_r*)alpha, \ (ftype*)a, rs_a, cs_a, \ (ftype_r*)beta, \ (ftype*)c, rs_c, cs_c, \ NULL, \ NULL \ ); \ \ /* Finalize BLIS. */ \ bli_finalize_auto(); \ } #else #undef GENTFUNCCO #define GENTFUNCCO( ftype, ftype_r, ch, chr, blasname, blisname ) \ \ void PASTEF77(ch,blasname) \ ( \ const f77_char* uploc, \ const f77_char* transa, \ const f77_int* m, \ const f77_int* k, \ const ftype_r* alpha, \ const ftype* a, const f77_int* lda, \ const ftype_r* beta, \ ftype* c, const f77_int* ldc \ ) \ { \ uplo_t blis_uploc; \ trans_t blis_transa; \ dim_t m0, k0; \ \ /* Initialize BLIS. */ \ bli_init_auto(); \ \ /* Perform BLAS parameter checking. */ \ PASTEBLACHK(blasname) \ ( \ MKSTR(ch), \ MKSTR(blasname), \ uploc, \ transa, \ m, \ k, \ lda, \ ldc \ ); \ \ /* Map BLAS chars to their corresponding BLIS enumerated type value. */ \ bli_param_map_netlib_to_blis_uplo( *uploc, &blis_uploc ); \ bli_param_map_netlib_to_blis_trans( *transa, &blis_transa ); \ \ /* Typecast BLAS integers to BLIS integers. */ \ bli_convert_blas_dim1( *m, m0 ); \ bli_convert_blas_dim1( *k, k0 ); \ \ /* We emulate the BLAS early return behavior with the following conditional, which returns if one of the following is true: - matrix C is empty - the rank-k product is empty (either because alpha is zero or k is zero) AND matrix C is not scaled. */ \ if ( m0 == 0 || \ ( ( PASTEMAC(chr,eq0)( *alpha ) || k0 == 0 ) \ && PASTEMAC(chr,eq1)( *beta ) \ ) \ ) \ { \ /* Finalize BLIS. */ \ bli_finalize_auto(); \ \ return; \ } \ \ /* Set the row and column strides of the matrix operands. */ \ const inc_t rs_a = 1; \ const inc_t cs_a = *lda; \ const inc_t rs_c = 1; \ const inc_t cs_c = *ldc; \ \ const num_t dt_r = PASTEMAC(chr,type); \ const num_t dt = PASTEMAC(ch,type); \ \ const struc_t strucc = BLIS_HERMITIAN; \ \ obj_t alphao = BLIS_OBJECT_INITIALIZER_1X1; \ obj_t ao = BLIS_OBJECT_INITIALIZER; \ obj_t betao = BLIS_OBJECT_INITIALIZER_1X1; \ obj_t co = BLIS_OBJECT_INITIALIZER; \ \ dim_t m0_a, n0_a; \ \ bli_set_dims_with_trans( blis_transa, m0, k0, &m0_a, &n0_a ); \ \ bli_obj_init_finish_1x1( dt_r, (ftype_r*)alpha, &alphao ); \ bli_obj_init_finish_1x1( dt_r, (ftype_r*)beta, &betao ); \ \ bli_obj_init_finish( dt, m0_a, n0_a, (ftype*)a, rs_a, cs_a, &ao ); \ bli_obj_init_finish( dt, m0, m0, (ftype*)c, rs_c, cs_c, &co ); \ \ bli_obj_set_uplo( blis_uploc, &co ); \ bli_obj_set_conjtrans( blis_transa, &ao ); \ \ bli_obj_set_struc( strucc, &co ); \ \ PASTEMAC(blisname,BLIS_OAPI_EX_SUF) \ ( \ &alphao, \ &ao, \ &betao, \ &co, \ NULL, \ NULL \ ); \ \ /* Finalize BLIS. */ \ bli_finalize_auto(); \ } #endif #ifdef BLIS_ENABLE_BLAS INSERT_GENTFUNCCO_BLAS( herk, herk ) #endif blis-0.9.0/frame/compat/bla_herk.h000066400000000000000000000042341422157504600167570ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype BLAS-to-BLIS interfaces. // #undef GENTPROTCO #define GENTPROTCO( ftype, ftype_r, ch, chr, blasname ) \ \ BLIS_EXPORT_BLAS void PASTEF77(ch,blasname) \ ( \ const f77_char* uploc, \ const f77_char* transa, \ const f77_int* m, \ const f77_int* k, \ const ftype_r* alpha, \ const ftype* a, const f77_int* lda, \ const ftype_r* beta, \ ftype* c, const f77_int* ldc \ ); #ifdef BLIS_ENABLE_BLAS INSERT_GENTPROTCO_BLAS( herk ) #endif blis-0.9.0/frame/compat/bla_nrm2.c000066400000000000000000000051171422157504600167000ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // Define BLAS-to-BLIS interfaces. // #undef GENTFUNCR2 #define GENTFUNCR2( ftype_x, ftype_r, chx, chr, blasname, blisname ) \ \ ftype_r PASTEF772(chr,chx,blasname) \ ( \ const f77_int* n, \ const ftype_x* x, const f77_int* incx \ ) \ { \ dim_t n0; \ ftype_x* x0; \ inc_t incx0; \ ftype_r norm; \ \ /* Initialize BLIS. */ \ bli_init_auto(); \ \ /* Convert/typecast negative values of n to zero. */ \ bli_convert_blas_dim1( *n, n0 ); \ \ /* If the input increments are negative, adjust the pointers so we can use positive increments instead. */ \ bli_convert_blas_incv( n0, (ftype_x*)x, *incx, x0, incx0 ); \ \ /* Call BLIS interface. */ \ PASTEMAC2(chx,blisname,BLIS_TAPI_EX_SUF) \ ( \ n0, \ x0, incx0, \ &norm, \ NULL, \ NULL \ ); \ \ /* Finalize BLIS. */ \ bli_finalize_auto(); \ \ return norm; \ } #ifdef BLIS_ENABLE_BLAS INSERT_GENTFUNCR2_BLAS( nrm2, normfv ) #endif blis-0.9.0/frame/compat/bla_nrm2.h000066400000000000000000000037331422157504600167070ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype BLAS-to-BLIS interfaces. // #undef GENTPROTR2 #define GENTPROTR2( ftype_x, ftype_r, chx, chr, blasname ) \ \ BLIS_EXPORT_BLAS ftype_r PASTEF772(chr,chx,blasname) \ ( \ const f77_int* n, \ const ftype_x* x, const f77_int* incx \ ); #ifdef BLIS_ENABLE_BLAS INSERT_GENTPROTR2_BLAS( nrm2 ) #endif blis-0.9.0/frame/compat/bla_scal.c000066400000000000000000000057041422157504600167460ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // Define BLAS-to-BLIS interfaces. // #undef GENTFUNCSCAL #define GENTFUNCSCAL( ftype_x, ftype_a, chx, cha, blasname, blisname ) \ \ void PASTEF772(chx,cha,blasname) \ ( \ const f77_int* n, \ const ftype_a* alpha, \ ftype_x* x, const f77_int* incx \ ) \ { \ dim_t n0; \ ftype_x* x0; \ inc_t incx0; \ ftype_x alpha_cast; \ \ /* Initialize BLIS. */ \ bli_init_auto(); \ \ /* Convert/typecast negative values of n to zero. */ \ bli_convert_blas_dim1( *n, n0 ); \ \ /* If the input increments are negative, adjust the pointers so we can use positive increments instead. */ \ bli_convert_blas_incv( n0, (ftype_x*)x, *incx, x0, incx0 ); \ \ /* NOTE: We do not natively implement BLAS's csscal/zdscal in BLIS. that is, we just always sub-optimally implement those cases by casting alpha to ctype_x (potentially the complex domain) and using the homogeneous datatype instance according to that type. */ \ PASTEMAC2(cha,chx,copys)( *alpha, alpha_cast ); \ \ /* Call BLIS interface. */ \ PASTEMAC2(chx,blisname,BLIS_TAPI_EX_SUF) \ ( \ BLIS_NO_CONJUGATE, \ n0, \ &alpha_cast, \ x0, incx0, \ NULL, \ NULL \ ); \ \ /* Finalize BLIS. */ \ bli_finalize_auto(); \ } #ifdef BLIS_ENABLE_BLAS INSERT_GENTFUNCSCAL_BLAS( scal, scalv ) #endif blis-0.9.0/frame/compat/bla_scal.h000066400000000000000000000037671422157504600167620ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype BLAS-to-BLIS interfaces. // #undef GENTPROTSCAL #define GENTPROTSCAL( ftype_a, ftype_x, cha, chx, blasname ) \ \ BLIS_EXPORT_BLAS void PASTEF772(chx,cha,blasname) \ ( \ const f77_int* n, \ const ftype_a* alpha, \ ftype_x* x, const f77_int* incx \ ); #ifdef BLIS_ENABLE_BLAS INSERT_GENTPROTSCAL_BLAS( scal ) #endif blis-0.9.0/frame/compat/bla_swap.c000066400000000000000000000052051422157504600167720ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // Define BLAS-to-BLIS interfaces. // #undef GENTFUNC #define GENTFUNC( ftype, ch, blasname, blisname ) \ \ void PASTEF77(ch,blasname) \ ( \ const f77_int* n, \ ftype* x, const f77_int* incx, \ ftype* y, const f77_int* incy \ ) \ { \ dim_t n0; \ ftype* x0; \ ftype* y0; \ inc_t incx0; \ inc_t incy0; \ \ /* Initialize BLIS. */ \ bli_init_auto(); \ \ /* Convert/typecast negative values of n to zero. */ \ bli_convert_blas_dim1( *n, n0 ); \ \ /* If the input increments are negative, adjust the pointers so we can use positive increments instead. */ \ bli_convert_blas_incv( n0, (ftype*)x, *incx, x0, incx0 ); \ bli_convert_blas_incv( n0, (ftype*)y, *incy, y0, incy0 ); \ \ /* Call BLIS interface. */ \ PASTEMAC2(ch,blisname,BLIS_TAPI_EX_SUF) \ ( \ n0, \ x0, incx0, \ y0, incy0, \ NULL, \ NULL \ ); \ \ /* Finalize BLIS. */ \ bli_finalize_auto(); \ } #ifdef BLIS_ENABLE_BLAS INSERT_GENTFUNC_BLAS( swap, swapv ) #endif blis-0.9.0/frame/compat/bla_swap.h000066400000000000000000000037361422157504600170060ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype BLAS-to-BLIS interfaces. // #undef GENTPROT #define GENTPROT( ftype, ch, blasname ) \ \ BLIS_EXPORT_BLAS void PASTEF77(ch,blasname) \ ( \ const f77_int* n, \ ftype* x, const f77_int* incx, \ ftype* y, const f77_int* incy \ ); #ifdef BLIS_ENABLE_BLAS INSERT_GENTPROT_BLAS( swap ) #endif blis-0.9.0/frame/compat/bla_symm.c000066400000000000000000000140301422157504600170010ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // Define BLAS-to-BLIS interfaces. // #ifdef BLIS_BLAS3_CALLS_TAPI #undef GENTFUNC #define GENTFUNC( ftype, ch, blasname, blisname ) \ \ void PASTEF77(ch,blasname) \ ( \ const f77_char* side, \ const f77_char* uploa, \ const f77_int* m, \ const f77_int* n, \ const ftype* alpha, \ const ftype* a, const f77_int* lda, \ const ftype* b, const f77_int* ldb, \ const ftype* beta, \ ftype* c, const f77_int* ldc \ ) \ { \ side_t blis_side; \ uplo_t blis_uploa; \ dim_t m0, n0; \ \ /* Initialize BLIS. */ \ bli_init_auto(); \ \ /* Perform BLAS parameter checking. */ \ PASTEBLACHK(blasname) \ ( \ MKSTR(ch), \ MKSTR(blasname), \ side, \ uploa, \ m, \ n, \ lda, \ ldb, \ ldc \ ); \ \ /* Map BLAS chars to their corresponding BLIS enumerated type value. */ \ bli_param_map_netlib_to_blis_side( *side, &blis_side ); \ bli_param_map_netlib_to_blis_uplo( *uploa, &blis_uploa ); \ \ /* Typecast BLAS integers to BLIS integers. */ \ bli_convert_blas_dim1( *m, m0 ); \ bli_convert_blas_dim1( *n, n0 ); \ \ /* Set the row and column strides of the matrix operands. */ \ const inc_t rs_a = 1; \ const inc_t cs_a = *lda; \ const inc_t rs_b = 1; \ const inc_t cs_b = *ldb; \ const inc_t rs_c = 1; \ const inc_t cs_c = *ldc; \ \ /* Call BLIS interface. */ \ PASTEMAC2(ch,blisname,BLIS_TAPI_EX_SUF) \ ( \ blis_side, \ blis_uploa, \ BLIS_NO_CONJUGATE, \ BLIS_NO_TRANSPOSE, \ m0, \ n0, \ (ftype*)alpha, \ (ftype*)a, rs_a, cs_a, \ (ftype*)b, rs_b, cs_b, \ (ftype*)beta, \ (ftype*)c, rs_c, cs_c, \ NULL, \ NULL \ ); \ \ /* Finalize BLIS. */ \ bli_finalize_auto(); \ } #else #undef GENTFUNC #define GENTFUNC( ftype, ch, blasname, blisname ) \ \ void PASTEF77(ch,blasname) \ ( \ const f77_char* side, \ const f77_char* uploa, \ const f77_int* m, \ const f77_int* n, \ const ftype* alpha, \ const ftype* a, const f77_int* lda, \ const ftype* b, const f77_int* ldb, \ const ftype* beta, \ ftype* c, const f77_int* ldc \ ) \ { \ side_t blis_side; \ uplo_t blis_uploa; \ dim_t m0, n0; \ \ /* Initialize BLIS. */ \ bli_init_auto(); \ \ /* Perform BLAS parameter checking. */ \ PASTEBLACHK(blasname) \ ( \ MKSTR(ch), \ MKSTR(blasname), \ side, \ uploa, \ m, \ n, \ lda, \ ldb, \ ldc \ ); \ \ /* Map BLAS chars to their corresponding BLIS enumerated type value. */ \ bli_param_map_netlib_to_blis_side( *side, &blis_side ); \ bli_param_map_netlib_to_blis_uplo( *uploa, &blis_uploa ); \ \ /* Typecast BLAS integers to BLIS integers. */ \ bli_convert_blas_dim1( *m, m0 ); \ bli_convert_blas_dim1( *n, n0 ); \ \ /* Set the row and column strides of the matrix operands. */ \ const inc_t rs_a = 1; \ const inc_t cs_a = *lda; \ const inc_t rs_b = 1; \ const inc_t cs_b = *ldb; \ const inc_t rs_c = 1; \ const inc_t cs_c = *ldc; \ \ const num_t dt = PASTEMAC(ch,type); \ \ const conj_t conja = BLIS_NO_CONJUGATE; \ const trans_t transb = BLIS_NO_TRANSPOSE; \ const struc_t struca = BLIS_SYMMETRIC; \ \ obj_t alphao = BLIS_OBJECT_INITIALIZER_1X1; \ obj_t ao = BLIS_OBJECT_INITIALIZER; \ obj_t bo = BLIS_OBJECT_INITIALIZER; \ obj_t betao = BLIS_OBJECT_INITIALIZER_1X1; \ obj_t co = BLIS_OBJECT_INITIALIZER; \ \ dim_t mn0_a; \ dim_t m0_b, n0_b; \ \ bli_set_dim_with_side( blis_side, m0, n0, &mn0_a ); \ bli_set_dims_with_trans( transb, m0, n0, &m0_b, &n0_b ); \ \ bli_obj_init_finish_1x1( dt, (ftype*)alpha, &alphao ); \ bli_obj_init_finish_1x1( dt, (ftype*)beta, &betao ); \ \ bli_obj_init_finish( dt, mn0_a, mn0_a, (ftype*)a, rs_a, cs_a, &ao ); \ bli_obj_init_finish( dt, m0_b, n0_b, (ftype*)b, rs_b, cs_b, &bo ); \ bli_obj_init_finish( dt, m0, n0, (ftype*)c, rs_c, cs_c, &co ); \ \ bli_obj_set_uplo( blis_uploa, &ao ); \ bli_obj_set_conj( conja, &ao ); \ bli_obj_set_conjtrans( transb, &bo ); \ \ bli_obj_set_struc( struca, &ao ); \ \ PASTEMAC(blisname,BLIS_OAPI_EX_SUF) \ ( \ blis_side, \ &alphao, \ &ao, \ &bo, \ &betao, \ &co, \ NULL, \ NULL \ ); \ \ /* Finalize BLIS. */ \ bli_finalize_auto(); \ } #endif #ifdef BLIS_ENABLE_BLAS INSERT_GENTFUNC_BLAS( symm, symm ) #endif blis-0.9.0/frame/compat/bla_symm.h000066400000000000000000000042661422157504600170200ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype BLAS-to-BLIS interfaces. // #undef GENTPROT #define GENTPROT( ftype, ch, blasname ) \ \ BLIS_EXPORT_BLAS void PASTEF77(ch,blasname) \ ( \ const f77_char* side, \ const f77_char* uploa, \ const f77_int* m, \ const f77_int* n, \ const ftype* alpha, \ const ftype* a, const f77_int* lda, \ const ftype* b, const f77_int* ldb, \ const ftype* beta, \ ftype* c, const f77_int* ldc \ ); #ifdef BLIS_ENABLE_BLAS INSERT_GENTPROT_BLAS( symm ) #endif blis-0.9.0/frame/compat/bla_symv.c000066400000000000000000000065421422157504600170230ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // Define BLAS-to-BLIS interfaces. // #undef GENTFUNCRO #define GENTFUNCRO( ftype, ch, blasname, blisname ) \ \ void PASTEF77(ch,blasname) \ ( \ const f77_char* uploa, \ const f77_int* m, \ const ftype* alpha, \ const ftype* a, const f77_int* lda, \ const ftype* x, const f77_int* incx, \ const ftype* beta, \ ftype* y, const f77_int* incy \ ) \ { \ uplo_t blis_uploa; \ dim_t m0; \ ftype* x0; \ ftype* y0; \ inc_t incx0; \ inc_t incy0; \ \ /* Initialize BLIS. */ \ bli_init_auto(); \ \ /* Perform BLAS parameter checking. */ \ PASTEBLACHK(blasname) \ ( \ MKSTR(ch), \ MKSTR(blasname), \ uploa, \ m, \ lda, \ incx, \ incy \ ); \ \ /* Map BLAS chars to their corresponding BLIS enumerated type value. */ \ bli_param_map_netlib_to_blis_uplo( *uploa, &blis_uploa ); \ \ /* Convert/typecast negative values of m to zero. */ \ bli_convert_blas_dim1( *m, m0 ); \ \ /* If the input increments are negative, adjust the pointers so we can use positive increments instead. */ \ bli_convert_blas_incv( m0, (ftype*)x, *incx, x0, incx0 ); \ bli_convert_blas_incv( m0, (ftype*)y, *incy, y0, incy0 ); \ \ /* Set the row and column strides of A. */ \ const inc_t rs_a = 1; \ const inc_t cs_a = *lda; \ \ /* Call BLIS interface. */ \ PASTEMAC2(ch,blisname,BLIS_TAPI_EX_SUF) \ ( \ blis_uploa, \ BLIS_NO_CONJUGATE, \ BLIS_NO_CONJUGATE, \ m0, \ (ftype*)alpha, \ (ftype*)a, rs_a, cs_a, \ x0, incx0, \ (ftype*)beta, \ y0, incy0, \ NULL, \ NULL \ ); \ \ /* Finalize BLIS. */ \ bli_finalize_auto(); \ } #ifdef BLIS_ENABLE_BLAS INSERT_GENTFUNCRO_BLAS( symv, symv ) #endif blis-0.9.0/frame/compat/bla_symv.h000066400000000000000000000042031422157504600170200ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype BLAS-to-BLIS interfaces. // #undef GENTPROTRO #define GENTPROTRO( ftype, ch, blasname ) \ \ BLIS_EXPORT_BLAS void PASTEF77(ch,blasname) \ ( \ const f77_char* uploa, \ const f77_int* m, \ const ftype* alpha, \ const ftype* a, const f77_int* lda, \ const ftype* x, const f77_int* incx, \ const ftype* beta, \ ftype* y, const f77_int* incy \ ); #ifdef BLIS_ENABLE_BLAS INSERT_GENTPROTRO_BLAS( symv ) #endif blis-0.9.0/frame/compat/bla_syr.c000066400000000000000000000061541422157504600166410ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // Define BLAS-to-BLIS interfaces. // #undef GENTFUNCRO #define GENTFUNCRO( ftype, ch, blasname, blisname ) \ \ void PASTEF77(ch,blasname) \ ( \ const f77_char* uploa, \ const f77_int* m, \ const ftype* alpha, \ const ftype* x, const f77_int* incx, \ ftype* a, const f77_int* lda \ ) \ { \ uplo_t blis_uploa; \ dim_t m0; \ ftype* x0; \ inc_t incx0; \ \ /* Initialize BLIS. */ \ bli_init_auto(); \ \ /* Perform BLAS parameter checking. */ \ PASTEBLACHK(blasname) \ ( \ MKSTR(ch), \ MKSTR(blasname), \ uploa, \ m, \ incx, \ lda \ ); \ \ /* Map BLAS chars to their corresponding BLIS enumerated type value. */ \ bli_param_map_netlib_to_blis_uplo( *uploa, &blis_uploa ); \ \ /* Convert/typecast negative values of m to zero. */ \ bli_convert_blas_dim1( *m, m0 ); \ \ /* If the input increments are negative, adjust the pointers so we can use positive increments instead. */ \ bli_convert_blas_incv( m0, (ftype*)x, *incx, x0, incx0 ); \ \ /* Set the row and column strides of A. */ \ const inc_t rs_a = 1; \ const inc_t cs_a = *lda; \ \ /* Call BLIS interface. */ \ PASTEMAC2(ch,blisname,BLIS_TAPI_EX_SUF) \ ( \ blis_uploa, \ BLIS_NO_CONJUGATE, \ m0, \ (ftype*)alpha, \ x0, incx0, \ (ftype*)a, rs_a, cs_a, \ NULL, \ NULL \ ); \ \ /* Finalize BLIS. */ \ bli_finalize_auto(); \ } #ifdef BLIS_ENABLE_BLAS INSERT_GENTFUNCRO_BLAS( syr, syr ) #endif blis-0.9.0/frame/compat/bla_syr.h000066400000000000000000000040621422157504600166420ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype BLAS-to-BLIS interfaces. // #undef GENTPROTRO #define GENTPROTRO( ftype, ch, blasname ) \ \ BLIS_EXPORT_BLAS void PASTEF77(ch,blasname) \ ( \ const f77_char* uploa, \ const f77_int* m, \ const ftype* alpha, \ const ftype* x, const f77_int* incx, \ ftype* a, const f77_int* lda \ ); #ifdef BLIS_ENABLE_BLAS INSERT_GENTPROTRO_BLAS( syr ) #endif blis-0.9.0/frame/compat/bla_syr2.c000066400000000000000000000064621422157504600167250ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // Define BLAS-to-BLIS interfaces. // #undef GENTFUNCRO #define GENTFUNCRO( ftype, ch, blasname, blisname ) \ \ void PASTEF77(ch,blasname) \ ( \ const f77_char* uploa, \ const f77_int* m, \ const ftype* alpha, \ const ftype* x, const f77_int* incx, \ const ftype* y, const f77_int* incy, \ ftype* a, const f77_int* lda \ ) \ { \ uplo_t blis_uploa; \ dim_t m0; \ ftype* x0; \ ftype* y0; \ inc_t incx0; \ inc_t incy0; \ \ /* Initialize BLIS. */ \ bli_init_auto(); \ \ /* Perform BLAS parameter checking. */ \ PASTEBLACHK(blasname) \ ( \ MKSTR(ch), \ MKSTR(blasname), \ uploa, \ m, \ incx, \ incy, \ lda \ ); \ \ \ /* Map BLAS chars to their corresponding BLIS enumerated type value. */ \ bli_param_map_netlib_to_blis_uplo( *uploa, &blis_uploa ); \ \ /* Convert/typecast negative values of m to zero. */ \ bli_convert_blas_dim1( *m, m0 ); \ \ /* If the input increments are negative, adjust the pointers so we can use positive increments instead. */ \ bli_convert_blas_incv( m0, (ftype*)x, *incx, x0, incx0 ); \ bli_convert_blas_incv( m0, (ftype*)y, *incy, y0, incy0 ); \ \ /* Set the row and column strides of A. */ \ const inc_t rs_a = 1; \ const inc_t cs_a = *lda; \ \ /* Call BLIS interface. */ \ PASTEMAC2(ch,blisname,BLIS_TAPI_EX_SUF) \ ( \ blis_uploa, \ BLIS_NO_CONJUGATE, \ BLIS_NO_CONJUGATE, \ m0, \ (ftype*)alpha, \ x0, incx0, \ y0, incy0, \ (ftype*)a, rs_a, cs_a, \ NULL, \ NULL \ ); \ \ /* Finalize BLIS. */ \ bli_finalize_auto(); \ } #ifdef BLIS_ENABLE_BLAS INSERT_GENTFUNCRO_BLAS( syr2, syr2 ) #endif blis-0.9.0/frame/compat/bla_syr2.h000066400000000000000000000041441422157504600167250ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype BLAS-to-BLIS interfaces. // #undef GENTPROTRO #define GENTPROTRO( ftype, ch, blasname ) \ \ BLIS_EXPORT_BLAS void PASTEF77(ch,blasname) \ ( \ const f77_char* uploa, \ const f77_int* m, \ const ftype* alpha, \ const ftype* x, const f77_int* incx, \ const ftype* y, const f77_int* incy, \ ftype* a, const f77_int* lda \ ); #ifdef BLIS_ENABLE_BLAS INSERT_GENTPROTRO_BLAS( syr2 ) #endif blis-0.9.0/frame/compat/bla_syr2k.c000066400000000000000000000152171422157504600170760ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // Define BLAS-to-BLIS interfaces. // #ifdef BLIS_BLAS3_CALLS_TAPI #undef GENTFUNC #define GENTFUNC( ftype, ch, blasname, blisname ) \ \ void PASTEF77(ch,blasname) \ ( \ const f77_char* uploc, \ const f77_char* transa, \ const f77_int* m, \ const f77_int* k, \ const ftype* alpha, \ const ftype* a, const f77_int* lda, \ const ftype* b, const f77_int* ldb, \ const ftype* beta, \ ftype* c, const f77_int* ldc \ ) \ { \ uplo_t blis_uploc; \ trans_t blis_transa; \ dim_t m0, k0; \ \ /* Initialize BLIS. */ \ bli_init_auto(); \ \ /* Perform BLAS parameter checking. */ \ PASTEBLACHK(blasname) \ ( \ MKSTR(ch), \ MKSTR(blasname), \ uploc, \ transa, \ m, \ k, \ lda, \ ldb, \ ldc \ ); \ \ /* Map BLAS chars to their corresponding BLIS enumerated type value. */ \ bli_param_map_netlib_to_blis_uplo( *uploc, &blis_uploc ); \ bli_param_map_netlib_to_blis_trans( *transa, &blis_transa ); \ \ /* The real domain ssyr2k and dsyr2k in netlib BLAS treat a trans value of 'C' (conjugate-transpose) as 'T' (transpose only). So, we have to go out of our way a little to support this behavior. */ \ if ( bli_is_real( PASTEMAC(ch,type) ) && \ bli_is_conjtrans( blis_transa ) ) \ { \ blis_transa = BLIS_TRANSPOSE; \ } \ \ /* Typecast BLAS integers to BLIS integers. */ \ bli_convert_blas_dim1( *m, m0 ); \ bli_convert_blas_dim1( *k, k0 ); \ \ /* Set the row and column strides of the matrix operands. */ \ const inc_t rs_a = 1; \ const inc_t cs_a = *lda; \ const inc_t rs_b = 1; \ const inc_t cs_b = *ldb; \ const inc_t rs_c = 1; \ const inc_t cs_c = *ldc; \ \ /* Call BLIS interface. */ \ PASTEMAC2(ch,blisname,BLIS_TAPI_EX_SUF) \ ( \ blis_uploc, \ blis_transa, \ blis_transa, \ m0, \ k0, \ (ftype*)alpha, \ (ftype*)a, rs_a, cs_a, \ (ftype*)b, rs_b, cs_b, \ (ftype*)beta, \ (ftype*)c, rs_c, cs_c, \ NULL, \ NULL \ ); \ \ /* Finalize BLIS. */ \ bli_finalize_auto(); \ } #else #undef GENTFUNC #define GENTFUNC( ftype, ch, blasname, blisname ) \ \ void PASTEF77(ch,blasname) \ ( \ const f77_char* uploc, \ const f77_char* transa, \ const f77_int* m, \ const f77_int* k, \ const ftype* alpha, \ const ftype* a, const f77_int* lda, \ const ftype* b, const f77_int* ldb, \ const ftype* beta, \ ftype* c, const f77_int* ldc \ ) \ { \ uplo_t blis_uploc; \ trans_t blis_transa; \ dim_t m0, k0; \ \ /* Initialize BLIS. */ \ bli_init_auto(); \ \ /* Perform BLAS parameter checking. */ \ PASTEBLACHK(blasname) \ ( \ MKSTR(ch), \ MKSTR(blasname), \ uploc, \ transa, \ m, \ k, \ lda, \ ldb, \ ldc \ ); \ \ /* Map BLAS chars to their corresponding BLIS enumerated type value. */ \ bli_param_map_netlib_to_blis_uplo( *uploc, &blis_uploc ); \ bli_param_map_netlib_to_blis_trans( *transa, &blis_transa ); \ \ /* The real domain ssyr2k and dsyr2k in netlib BLAS treat a trans value of 'C' (conjugate-transpose) as 'T' (transpose only). So, we have to go out of our way a little to support this behavior. */ \ if ( bli_is_real( PASTEMAC(ch,type) ) && \ bli_is_conjtrans( blis_transa ) ) \ { \ blis_transa = BLIS_TRANSPOSE; \ } \ \ /* Typecast BLAS integers to BLIS integers. */ \ bli_convert_blas_dim1( *m, m0 ); \ bli_convert_blas_dim1( *k, k0 ); \ \ /* Set the row and column strides of the matrix operands. */ \ const inc_t rs_a = 1; \ const inc_t cs_a = *lda; \ const inc_t rs_b = 1; \ const inc_t cs_b = *ldb; \ const inc_t rs_c = 1; \ const inc_t cs_c = *ldc; \ \ const num_t dt = PASTEMAC(ch,type); \ \ const trans_t transb = blis_transa; \ const struc_t strucc = BLIS_SYMMETRIC; \ \ obj_t alphao = BLIS_OBJECT_INITIALIZER_1X1; \ obj_t ao = BLIS_OBJECT_INITIALIZER; \ obj_t bo = BLIS_OBJECT_INITIALIZER; \ obj_t betao = BLIS_OBJECT_INITIALIZER_1X1; \ obj_t co = BLIS_OBJECT_INITIALIZER; \ \ dim_t m0_a, n0_a; \ dim_t m0_b, n0_b; \ \ bli_set_dims_with_trans( blis_transa, m0, k0, &m0_a, &n0_a ); \ bli_set_dims_with_trans( transb, m0, k0, &m0_b, &n0_b ); \ \ bli_obj_init_finish_1x1( dt, (ftype*)alpha, &alphao ); \ bli_obj_init_finish_1x1( dt, (ftype*)beta, &betao ); \ \ bli_obj_init_finish( dt, m0_a, n0_a, (ftype*)a, rs_a, cs_a, &ao ); \ bli_obj_init_finish( dt, m0_b, n0_b, (ftype*)b, rs_b, cs_b, &bo ); \ bli_obj_init_finish( dt, m0, m0, (ftype*)c, rs_c, cs_c, &co ); \ \ bli_obj_set_uplo( blis_uploc, &co ); \ bli_obj_set_conjtrans( blis_transa, &ao ); \ bli_obj_set_conjtrans( transb, &bo ); \ \ bli_obj_set_struc( strucc, &co ); \ \ PASTEMAC(blisname,BLIS_OAPI_EX_SUF) \ ( \ &alphao, \ &ao, \ &bo, \ &betao, \ &co, \ NULL, \ NULL \ ); \ \ /* Finalize BLIS. */ \ bli_finalize_auto(); \ } #endif #ifdef BLIS_ENABLE_BLAS INSERT_GENTFUNC_BLAS( syr2k, syr2k ) #endif blis-0.9.0/frame/compat/bla_syr2k.h000066400000000000000000000042711422157504600171010ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype BLAS-to-BLIS interfaces. // #undef GENTPROT #define GENTPROT( ftype, ch, blasname ) \ \ BLIS_EXPORT_BLAS void PASTEF77(ch,blasname) \ ( \ const f77_char* uploc, \ const f77_char* transa, \ const f77_int* m, \ const f77_int* k, \ const ftype* alpha, \ const ftype* a, const f77_int* lda, \ const ftype* b, const f77_int* ldb, \ const ftype* beta, \ ftype* c, const f77_int* ldc \ ); #ifdef BLIS_ENABLE_BLAS INSERT_GENTPROT_BLAS( syr2k ) #endif blis-0.9.0/frame/compat/bla_syrk.c000066400000000000000000000141201422157504600170040ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // Define BLAS-to-BLIS interfaces. // #ifdef BLIS_BLAS3_CALLS_TAPI #undef GENTFUNC #define GENTFUNC( ftype, ch, blasname, blisname ) \ \ void PASTEF77(ch,blasname) \ ( \ const f77_char* uploc, \ const f77_char* transa, \ const f77_int* m, \ const f77_int* k, \ const ftype* alpha, \ const ftype* a, const f77_int* lda, \ const ftype* beta, \ ftype* c, const f77_int* ldc \ ) \ { \ uplo_t blis_uploc; \ trans_t blis_transa; \ dim_t m0, k0; \ \ /* Initialize BLIS. */ \ bli_init_auto(); \ \ /* Perform BLAS parameter checking. */ \ PASTEBLACHK(blasname) \ ( \ MKSTR(ch), \ MKSTR(blasname), \ uploc, \ transa, \ m, \ k, \ lda, \ ldc \ ); \ \ /* Map BLAS chars to their corresponding BLIS enumerated type value. */ \ bli_param_map_netlib_to_blis_uplo( *uploc, &blis_uploc ); \ bli_param_map_netlib_to_blis_trans( *transa, &blis_transa ); \ \ /* The real domain ssyrk and dsyrk in netlib BLAS treat a trans value of 'C' (conjugate-transpose) as 'T' (transpose only). So, we have to go out of our way a little to support this behavior. */ \ if ( bli_is_real( PASTEMAC(ch,type) ) && \ bli_is_conjtrans( blis_transa ) ) \ { \ blis_transa = BLIS_TRANSPOSE; \ } \ \ /* Typecast BLAS integers to BLIS integers. */ \ bli_convert_blas_dim1( *m, m0 ); \ bli_convert_blas_dim1( *k, k0 ); \ \ /* Set the row and column strides of the matrix operands. */ \ const inc_t rs_a = 1; \ const inc_t cs_a = *lda; \ const inc_t rs_c = 1; \ const inc_t cs_c = *ldc; \ \ /* Call BLIS interface. */ \ PASTEMAC2(ch,blisname,BLIS_TAPI_EX_SUF) \ ( \ blis_uploc, \ blis_transa, \ m0, \ k0, \ (ftype*)alpha, \ (ftype*)a, rs_a, cs_a, \ (ftype*)beta, \ (ftype*)c, rs_c, cs_c, \ NULL, \ NULL \ ); \ \ /* Finalize BLIS. */ \ bli_finalize_auto(); \ } #else #undef GENTFUNC #define GENTFUNC( ftype, ch, blasname, blisname ) \ \ void PASTEF77(ch,blasname) \ ( \ const f77_char* uploc, \ const f77_char* transa, \ const f77_int* m, \ const f77_int* k, \ const ftype* alpha, \ const ftype* a, const f77_int* lda, \ const ftype* beta, \ ftype* c, const f77_int* ldc \ ) \ { \ uplo_t blis_uploc; \ trans_t blis_transa; \ dim_t m0, k0; \ \ /* Initialize BLIS. */ \ bli_init_auto(); \ \ /* Perform BLAS parameter checking. */ \ PASTEBLACHK(blasname) \ ( \ MKSTR(ch), \ MKSTR(blasname), \ uploc, \ transa, \ m, \ k, \ lda, \ ldc \ ); \ \ /* Map BLAS chars to their corresponding BLIS enumerated type value. */ \ bli_param_map_netlib_to_blis_uplo( *uploc, &blis_uploc ); \ bli_param_map_netlib_to_blis_trans( *transa, &blis_transa ); \ \ /* The real domain ssyrk and dsyrk in netlib BLAS treat a trans value of 'C' (conjugate-transpose) as 'T' (transpose only). So, we have to go out of our way a little to support this behavior. */ \ if ( bli_is_real( PASTEMAC(ch,type) ) && \ bli_is_conjtrans( blis_transa ) ) \ { \ blis_transa = BLIS_TRANSPOSE; \ } \ \ /* Typecast BLAS integers to BLIS integers. */ \ bli_convert_blas_dim1( *m, m0 ); \ bli_convert_blas_dim1( *k, k0 ); \ \ /* Set the row and column strides of the matrix operands. */ \ const inc_t rs_a = 1; \ const inc_t cs_a = *lda; \ const inc_t rs_c = 1; \ const inc_t cs_c = *ldc; \ \ const num_t dt = PASTEMAC(ch,type); \ \ const struc_t strucc = BLIS_SYMMETRIC; \ \ obj_t alphao = BLIS_OBJECT_INITIALIZER_1X1; \ obj_t ao = BLIS_OBJECT_INITIALIZER; \ obj_t betao = BLIS_OBJECT_INITIALIZER_1X1; \ obj_t co = BLIS_OBJECT_INITIALIZER; \ \ dim_t m0_a, n0_a; \ \ bli_set_dims_with_trans( blis_transa, m0, k0, &m0_a, &n0_a ); \ \ bli_obj_init_finish_1x1( dt, (ftype*)alpha, &alphao ); \ bli_obj_init_finish_1x1( dt, (ftype*)beta, &betao ); \ \ bli_obj_init_finish( dt, m0_a, n0_a, (ftype*)a, rs_a, cs_a, &ao ); \ bli_obj_init_finish( dt, m0, m0, (ftype*)c, rs_c, cs_c, &co ); \ \ bli_obj_set_uplo( blis_uploc, &co ); \ bli_obj_set_conjtrans( blis_transa, &ao ); \ \ bli_obj_set_struc( strucc, &co ); \ \ PASTEMAC(blisname,BLIS_OAPI_EX_SUF) \ ( \ &alphao, \ &ao, \ &betao, \ &co, \ NULL, \ NULL \ ); \ \ /* Finalize BLIS. */ \ bli_finalize_auto(); \ } #endif #ifdef BLIS_ENABLE_BLAS INSERT_GENTFUNC_BLAS( syrk, syrk ) #endif blis-0.9.0/frame/compat/bla_syrk.h000066400000000000000000000042101422157504600170100ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype BLAS-to-BLIS interfaces. // #undef GENTPROT #define GENTPROT( ftype, ch, blasname ) \ \ BLIS_EXPORT_BLAS void PASTEF77(ch,blasname) \ ( \ const f77_char* uploc, \ const f77_char* transa, \ const f77_int* m, \ const f77_int* k, \ const ftype* alpha, \ const ftype* a, const f77_int* lda, \ const ftype* beta, \ ftype* c, const f77_int* ldc \ ); #ifdef BLIS_ENABLE_BLAS INSERT_GENTPROT_BLAS( syrk ) #endif blis-0.9.0/frame/compat/bla_trmm.c000066400000000000000000000134461422157504600170050ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // Define BLAS-to-BLIS interfaces. // #ifdef BLIS_BLAS3_CALLS_TAPI #undef GENTFUNC #define GENTFUNC( ftype, ch, blasname, blisname ) \ \ void PASTEF77(ch,blasname) \ ( \ const f77_char* side, \ const f77_char* uploa, \ const f77_char* transa, \ const f77_char* diaga, \ const f77_int* m, \ const f77_int* n, \ const ftype* alpha, \ const ftype* a, const f77_int* lda, \ ftype* b, const f77_int* ldb \ ) \ { \ side_t blis_side; \ uplo_t blis_uploa; \ trans_t blis_transa; \ diag_t blis_diaga; \ dim_t m0, n0; \ \ /* Initialize BLIS. */ \ bli_init_auto(); \ \ /* Perform BLAS parameter checking. */ \ PASTEBLACHK(blasname) \ ( \ MKSTR(ch), \ MKSTR(blasname), \ side, \ uploa, \ transa, \ diaga, \ m, \ n, \ lda, \ ldb \ ); \ \ /* Map BLAS chars to their corresponding BLIS enumerated type value. */ \ bli_param_map_netlib_to_blis_side( *side, &blis_side ); \ bli_param_map_netlib_to_blis_uplo( *uploa, &blis_uploa ); \ bli_param_map_netlib_to_blis_trans( *transa, &blis_transa ); \ bli_param_map_netlib_to_blis_diag( *diaga, &blis_diaga ); \ \ /* Typecast BLAS integers to BLIS integers. */ \ bli_convert_blas_dim1( *m, m0 ); \ bli_convert_blas_dim1( *n, n0 ); \ \ /* Set the row and column strides of the matrix operands. */ \ const inc_t rs_a = 1; \ const inc_t cs_a = *lda; \ const inc_t rs_b = 1; \ const inc_t cs_b = *ldb; \ \ /* Call BLIS interface. */ \ PASTEMAC2(ch,blisname,BLIS_TAPI_EX_SUF) \ ( \ blis_side, \ blis_uploa, \ blis_transa, \ blis_diaga, \ m0, \ n0, \ (ftype*)alpha, \ (ftype*)a, rs_a, cs_a, \ (ftype*)b, rs_b, cs_b, \ NULL, \ NULL \ ); \ \ /* Finalize BLIS. */ \ bli_finalize_auto(); \ } #else #undef GENTFUNC #define GENTFUNC( ftype, ch, blasname, blisname ) \ \ void PASTEF77(ch,blasname) \ ( \ const f77_char* side, \ const f77_char* uploa, \ const f77_char* transa, \ const f77_char* diaga, \ const f77_int* m, \ const f77_int* n, \ const ftype* alpha, \ const ftype* a, const f77_int* lda, \ ftype* b, const f77_int* ldb \ ) \ { \ side_t blis_side; \ uplo_t blis_uploa; \ trans_t blis_transa; \ diag_t blis_diaga; \ dim_t m0, n0; \ \ /* Initialize BLIS. */ \ bli_init_auto(); \ \ /* Perform BLAS parameter checking. */ \ PASTEBLACHK(blasname) \ ( \ MKSTR(ch), \ MKSTR(blasname), \ side, \ uploa, \ transa, \ diaga, \ m, \ n, \ lda, \ ldb \ ); \ \ /* Map BLAS chars to their corresponding BLIS enumerated type value. */ \ bli_param_map_netlib_to_blis_side( *side, &blis_side ); \ bli_param_map_netlib_to_blis_uplo( *uploa, &blis_uploa ); \ bli_param_map_netlib_to_blis_trans( *transa, &blis_transa ); \ bli_param_map_netlib_to_blis_diag( *diaga, &blis_diaga ); \ \ /* Typecast BLAS integers to BLIS integers. */ \ bli_convert_blas_dim1( *m, m0 ); \ bli_convert_blas_dim1( *n, n0 ); \ \ /* Set the row and column strides of the matrix operands. */ \ const inc_t rs_a = 1; \ const inc_t cs_a = *lda; \ const inc_t rs_b = 1; \ const inc_t cs_b = *ldb; \ \ const num_t dt = PASTEMAC(ch,type); \ \ const struc_t struca = BLIS_TRIANGULAR; \ \ obj_t alphao = BLIS_OBJECT_INITIALIZER_1X1; \ obj_t ao = BLIS_OBJECT_INITIALIZER; \ obj_t bo = BLIS_OBJECT_INITIALIZER; \ \ dim_t mn0_a; \ \ bli_set_dim_with_side( blis_side, m0, n0, &mn0_a ); \ \ bli_obj_init_finish_1x1( dt, (ftype*)alpha, &alphao ); \ \ bli_obj_init_finish( dt, mn0_a, mn0_a, (ftype*)a, rs_a, cs_a, &ao ); \ bli_obj_init_finish( dt, m0, n0, (ftype*)b, rs_b, cs_b, &bo ); \ \ bli_obj_set_uplo( blis_uploa, &ao ); \ bli_obj_set_diag( blis_diaga, &ao ); \ bli_obj_set_conjtrans( blis_transa, &ao ); \ \ bli_obj_set_struc( struca, &ao ); \ \ PASTEMAC(blisname,BLIS_OAPI_EX_SUF) \ ( \ blis_side, \ &alphao, \ &ao, \ &bo, \ NULL, \ NULL \ ); \ \ /* Finalize BLIS. */ \ bli_finalize_auto(); \ } #endif #ifdef BLIS_ENABLE_BLAS INSERT_GENTFUNC_BLAS( trmm, trmm ) #endif blis-0.9.0/frame/compat/bla_trmm.h000066400000000000000000000042501422157504600170030ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype BLAS-to-BLIS interfaces. // #undef GENTPROT #define GENTPROT( ftype, ch, blasname ) \ \ BLIS_EXPORT_BLAS void PASTEF77(ch,blasname) \ ( \ const f77_char* side, \ const f77_char* uploa, \ const f77_char* transa, \ const f77_char* diaga, \ const f77_int* m, \ const f77_int* n, \ const ftype* alpha, \ const ftype* a, const f77_int* lda, \ ftype* b, const f77_int* ldb \ ); #ifdef BLIS_ENABLE_BLAS INSERT_GENTPROT_BLAS( trmm ) #endif blis-0.9.0/frame/compat/bla_trmv.c000066400000000000000000000067031422157504600170140ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // Define BLAS-to-BLIS interfaces. // #undef GENTFUNC #define GENTFUNC( ftype, ch, blasname, blisname ) \ \ void PASTEF77(ch,blasname) \ ( \ const f77_char* uploa, \ const f77_char* transa, \ const f77_char* diaga, \ const f77_int* m, \ const ftype* a, const f77_int* lda, \ ftype* x, const f77_int* incx \ ) \ { \ uplo_t blis_uploa; \ trans_t blis_transa; \ diag_t blis_diaga; \ dim_t m0; \ ftype* x0; \ inc_t incx0; \ ftype* one_p; \ \ /* Initialize BLIS. */ \ bli_init_auto(); \ \ /* Perform BLAS parameter checking. */ \ PASTEBLACHK(blasname) \ ( \ MKSTR(ch), \ MKSTR(blasname), \ uploa, \ transa, \ diaga, \ m, \ lda, \ incx \ ); \ \ /* Map BLAS chars to their corresponding BLIS enumerated type value. */ \ bli_param_map_netlib_to_blis_uplo( *uploa, &blis_uploa ); \ bli_param_map_netlib_to_blis_trans( *transa, &blis_transa ); \ bli_param_map_netlib_to_blis_diag( *diaga, &blis_diaga ); \ \ /* Convert/typecast negative values of m to zero. */ \ bli_convert_blas_dim1( *m, m0 ); \ \ /* If the input increments are negative, adjust the pointers so we can use positive increments instead. */ \ bli_convert_blas_incv( m0, (ftype*)x, *incx, x0, incx0 ); \ \ /* Set the row and column strides of A. */ \ const inc_t rs_a = 1; \ const inc_t cs_a = *lda; \ \ /* Acquire a pointer to the global scalar constant BLIS_ONE. */ \ one_p = PASTEMAC(ch,1); \ \ /* Call BLIS interface. */ \ PASTEMAC2(ch,blisname,BLIS_TAPI_EX_SUF) \ ( \ blis_uploa, \ blis_transa, \ blis_diaga, \ m0, \ one_p, \ (ftype*)a, rs_a, cs_a, \ x0, incx0, \ NULL, \ NULL \ ); \ \ /* Finalize BLIS. */ \ bli_finalize_auto(); \ } #ifdef BLIS_ENABLE_BLAS INSERT_GENTFUNC_BLAS( trmv, trmv ) #endif blis-0.9.0/frame/compat/bla_trmv.h000066400000000000000000000041161422157504600170150ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype BLAS-to-BLIS interfaces. // #undef GENTPROT #define GENTPROT( ftype, ch, blasname ) \ \ BLIS_EXPORT_BLAS void PASTEF77(ch,blasname) \ ( \ const f77_char* uploa, \ const f77_char* transa, \ const f77_char* diaga, \ const f77_int* m, \ const ftype* a, const f77_int* lda, \ ftype* x, const f77_int* incx \ ); #ifdef BLIS_ENABLE_BLAS INSERT_GENTPROT_BLAS( trmv ) #endif blis-0.9.0/frame/compat/bla_trsm.c000066400000000000000000000134461422157504600170130ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // Define BLAS-to-BLIS interfaces. // #ifdef BLIS_BLAS3_CALLS_TAPI #undef GENTFUNC #define GENTFUNC( ftype, ch, blasname, blisname ) \ \ void PASTEF77(ch,blasname) \ ( \ const f77_char* side, \ const f77_char* uploa, \ const f77_char* transa, \ const f77_char* diaga, \ const f77_int* m, \ const f77_int* n, \ const ftype* alpha, \ const ftype* a, const f77_int* lda, \ ftype* b, const f77_int* ldb \ ) \ { \ side_t blis_side; \ uplo_t blis_uploa; \ trans_t blis_transa; \ diag_t blis_diaga; \ dim_t m0, n0; \ \ /* Initialize BLIS. */ \ bli_init_auto(); \ \ /* Perform BLAS parameter checking. */ \ PASTEBLACHK(blasname) \ ( \ MKSTR(ch), \ MKSTR(blasname), \ side, \ uploa, \ transa, \ diaga, \ m, \ n, \ lda, \ ldb \ ); \ \ /* Map BLAS chars to their corresponding BLIS enumerated type value. */ \ bli_param_map_netlib_to_blis_side( *side, &blis_side ); \ bli_param_map_netlib_to_blis_uplo( *uploa, &blis_uploa ); \ bli_param_map_netlib_to_blis_trans( *transa, &blis_transa ); \ bli_param_map_netlib_to_blis_diag( *diaga, &blis_diaga ); \ \ /* Typecast BLAS integers to BLIS integers. */ \ bli_convert_blas_dim1( *m, m0 ); \ bli_convert_blas_dim1( *n, n0 ); \ \ /* Set the row and column strides of the matrix operands. */ \ const inc_t rs_a = 1; \ const inc_t cs_a = *lda; \ const inc_t rs_b = 1; \ const inc_t cs_b = *ldb; \ \ /* Call BLIS interface. */ \ PASTEMAC2(ch,blisname,BLIS_TAPI_EX_SUF) \ ( \ blis_side, \ blis_uploa, \ blis_transa, \ blis_diaga, \ m0, \ n0, \ (ftype*)alpha, \ (ftype*)a, rs_a, cs_a, \ (ftype*)b, rs_b, cs_b, \ NULL, \ NULL \ ); \ \ /* Finalize BLIS. */ \ bli_finalize_auto(); \ } #else #undef GENTFUNC #define GENTFUNC( ftype, ch, blasname, blisname ) \ \ void PASTEF77(ch,blasname) \ ( \ const f77_char* side, \ const f77_char* uploa, \ const f77_char* transa, \ const f77_char* diaga, \ const f77_int* m, \ const f77_int* n, \ const ftype* alpha, \ const ftype* a, const f77_int* lda, \ ftype* b, const f77_int* ldb \ ) \ { \ side_t blis_side; \ uplo_t blis_uploa; \ trans_t blis_transa; \ diag_t blis_diaga; \ dim_t m0, n0; \ \ /* Initialize BLIS. */ \ bli_init_auto(); \ \ /* Perform BLAS parameter checking. */ \ PASTEBLACHK(blasname) \ ( \ MKSTR(ch), \ MKSTR(blasname), \ side, \ uploa, \ transa, \ diaga, \ m, \ n, \ lda, \ ldb \ ); \ \ /* Map BLAS chars to their corresponding BLIS enumerated type value. */ \ bli_param_map_netlib_to_blis_side( *side, &blis_side ); \ bli_param_map_netlib_to_blis_uplo( *uploa, &blis_uploa ); \ bli_param_map_netlib_to_blis_trans( *transa, &blis_transa ); \ bli_param_map_netlib_to_blis_diag( *diaga, &blis_diaga ); \ \ /* Typecast BLAS integers to BLIS integers. */ \ bli_convert_blas_dim1( *m, m0 ); \ bli_convert_blas_dim1( *n, n0 ); \ \ /* Set the row and column strides of the matrix operands. */ \ const inc_t rs_a = 1; \ const inc_t cs_a = *lda; \ const inc_t rs_b = 1; \ const inc_t cs_b = *ldb; \ \ const num_t dt = PASTEMAC(ch,type); \ \ const struc_t struca = BLIS_TRIANGULAR; \ \ obj_t alphao = BLIS_OBJECT_INITIALIZER_1X1; \ obj_t ao = BLIS_OBJECT_INITIALIZER; \ obj_t bo = BLIS_OBJECT_INITIALIZER; \ \ dim_t mn0_a; \ \ bli_set_dim_with_side( blis_side, m0, n0, &mn0_a ); \ \ bli_obj_init_finish_1x1( dt, (ftype*)alpha, &alphao ); \ \ bli_obj_init_finish( dt, mn0_a, mn0_a, (ftype*)a, rs_a, cs_a, &ao ); \ bli_obj_init_finish( dt, m0, n0, (ftype*)b, rs_b, cs_b, &bo ); \ \ bli_obj_set_uplo( blis_uploa, &ao ); \ bli_obj_set_diag( blis_diaga, &ao ); \ bli_obj_set_conjtrans( blis_transa, &ao ); \ \ bli_obj_set_struc( struca, &ao ); \ \ PASTEMAC(blisname,BLIS_OAPI_EX_SUF) \ ( \ blis_side, \ &alphao, \ &ao, \ &bo, \ NULL, \ NULL \ ); \ \ /* Finalize BLIS. */ \ bli_finalize_auto(); \ } #endif #ifdef BLIS_ENABLE_BLAS INSERT_GENTFUNC_BLAS( trsm, trsm ) #endif blis-0.9.0/frame/compat/bla_trsm.h000066400000000000000000000042501422157504600170110ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype BLAS-to-BLIS interfaces. // #undef GENTPROT #define GENTPROT( ftype, ch, blasname ) \ \ BLIS_EXPORT_BLAS void PASTEF77(ch,blasname) \ ( \ const f77_char* side, \ const f77_char* uploa, \ const f77_char* transa, \ const f77_char* diaga, \ const f77_int* m, \ const f77_int* n, \ const ftype* alpha, \ const ftype* a, const f77_int* lda, \ ftype* b, const f77_int* ldb \ ); #ifdef BLIS_ENABLE_BLAS INSERT_GENTPROT_BLAS( trsm ) #endif blis-0.9.0/frame/compat/bla_trsv.c000066400000000000000000000067031422157504600170220ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // Define BLAS-to-BLIS interfaces. // #undef GENTFUNC #define GENTFUNC( ftype, ch, blasname, blisname ) \ \ void PASTEF77(ch,blasname) \ ( \ const f77_char* uploa, \ const f77_char* transa, \ const f77_char* diaga, \ const f77_int* m, \ const ftype* a, const f77_int* lda, \ ftype* x, const f77_int* incx \ ) \ { \ uplo_t blis_uploa; \ trans_t blis_transa; \ diag_t blis_diaga; \ dim_t m0; \ ftype* x0; \ inc_t incx0; \ ftype* one_p; \ \ /* Initialize BLIS. */ \ bli_init_auto(); \ \ /* Perform BLAS parameter checking. */ \ PASTEBLACHK(blasname) \ ( \ MKSTR(ch), \ MKSTR(blasname), \ uploa, \ transa, \ diaga, \ m, \ lda, \ incx \ ); \ \ /* Map BLAS chars to their corresponding BLIS enumerated type value. */ \ bli_param_map_netlib_to_blis_uplo( *uploa, &blis_uploa ); \ bli_param_map_netlib_to_blis_trans( *transa, &blis_transa ); \ bli_param_map_netlib_to_blis_diag( *diaga, &blis_diaga ); \ \ /* Convert/typecast negative values of m to zero. */ \ bli_convert_blas_dim1( *m, m0 ); \ \ /* If the input increments are negative, adjust the pointers so we can use positive increments instead. */ \ bli_convert_blas_incv( m0, (ftype*)x, *incx, x0, incx0 ); \ \ /* Set the row and column strides of A. */ \ const inc_t rs_a = 1; \ const inc_t cs_a = *lda; \ \ /* Acquire a pointer to the global scalar constant BLIS_ONE. */ \ one_p = PASTEMAC(ch,1); \ \ /* Call BLIS interface. */ \ PASTEMAC2(ch,blisname,BLIS_TAPI_EX_SUF) \ ( \ blis_uploa, \ blis_transa, \ blis_diaga, \ m0, \ one_p, \ (ftype*)a, rs_a, cs_a, \ x0, incx0, \ NULL, \ NULL \ ); \ \ /* Finalize BLIS. */ \ bli_finalize_auto(); \ } #ifdef BLIS_ENABLE_BLAS INSERT_GENTFUNC_BLAS( trsv, trsv ) #endif blis-0.9.0/frame/compat/bla_trsv.h000066400000000000000000000041161422157504600170230ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype BLAS-to-BLIS interfaces. // #undef GENTPROT #define GENTPROT( ftype, ch, blasname ) \ \ BLIS_EXPORT_BLAS void PASTEF77(ch,blasname) \ ( \ const f77_char* uploa, \ const f77_char* transa, \ const f77_char* diaga, \ const f77_int* m, \ const ftype* a, const f77_int* lda, \ ftype* x, const f77_int* incx \ ); #ifdef BLIS_ENABLE_BLAS INSERT_GENTPROT_BLAS( trsv ) #endif blis-0.9.0/frame/compat/bli_blas.h000066400000000000000000000126431422157504600167620ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // If the CBLAS compatibility layer was enabled while the BLAS layer // was not enabled, we must enable it here. #ifdef BLIS_ENABLE_CBLAS #ifndef BLIS_ENABLE_BLAS #define BLIS_ENABLE_BLAS #endif #endif // BLIS_ENABLE_CBLAS // By default, if the BLAS compatibility layer is enabled, we define // (include) all of the BLAS prototypes. However, if the user is // #including "blis.h" and also #including another header that also // declares the BLAS functions, then we provide an opportunity to // #undefine the BLIS_ENABLE_BLAS_DEFS macro (see below). #ifdef BLIS_ENABLE_BLAS #define BLIS_ENABLE_BLAS_DEFS #else #undef BLIS_ENABLE_BLAS_DEFS #endif // Skip prototyping all of the BLAS if the BLAS test drivers are being // compiled. #ifdef BLIS_VIA_BLASTEST #undef BLIS_ENABLE_BLAS_DEFS #endif // Skip prototyping all of the BLAS if the environment has defined the // macro BLIS_DISABLE_BLAS_DEFS. #ifdef BLIS_DISABLE_BLAS_DEFS #undef BLIS_ENABLE_BLAS_DEFS #endif // Begin including all BLAS prototypes. #ifdef BLIS_ENABLE_BLAS_DEFS // -- System headers needed by BLAS compatibility layer -- #include // for toupper(), used in xerbla() // -- Constants -- #define BLIS_MAX_BLAS_FUNC_STR_LENGTH (7+1) // -- Utility macros -- #include "bla_r_sign.h" #include "bla_d_sign.h" #include "bla_r_cnjg.h" #include "bla_d_cnjg.h" #include "bla_r_imag.h" #include "bla_d_imag.h" #include "bla_c_div.h" #include "bla_z_div.h" #include "bla_f__cabs.h" // needed by c_abs, z_abs #include "bla_r_abs.h" #include "bla_d_abs.h" #include "bla_c_abs.h" #include "bla_z_abs.h" #include "bla_lsame.h" #include "bla_xerbla.h" #include "bla_xerbla_array.h" // -- Level-0 BLAS prototypes -- #include "bla_cabs1.h" // -- Level-1 BLAS prototypes -- #include "bla_amax.h" #include "bla_asum.h" #include "bla_axpy.h" #include "bla_copy.h" #include "bla_dot.h" #include "bla_nrm2.h" #include "bla_rot.h" #include "bla_rotg.h" #include "bla_rotm.h" #include "bla_rotmg.h" #include "bla_scal.h" #include "bla_swap.h" #include "f77_amax_sub.h" #include "f77_asum_sub.h" #include "f77_dot_sub.h" #include "f77_nrm2_sub.h" // -- Level-2 BLAS prototypes -- // dense #include "bla_gemv.h" #include "bla_ger.h" #include "bla_hemv.h" #include "bla_her.h" #include "bla_her2.h" #include "bla_symv.h" #include "bla_syr.h" #include "bla_syr2.h" #include "bla_trmv.h" #include "bla_trsv.h" #include "bla_gemv_check.h" #include "bla_ger_check.h" #include "bla_hemv_check.h" #include "bla_her_check.h" #include "bla_her2_check.h" #include "bla_symv_check.h" #include "bla_syr_check.h" #include "bla_syr2_check.h" #include "bla_trmv_check.h" #include "bla_trsv_check.h" // packed #include "bla_hpmv.h" #include "bla_hpr.h" #include "bla_hpr2.h" #include "bla_spmv.h" #include "bla_spr.h" #include "bla_spr2.h" #include "bla_tpmv.h" #include "bla_tpsv.h" // banded #include "bla_gbmv.h" #include "bla_hbmv.h" #include "bla_sbmv.h" #include "bla_tbmv.h" #include "bla_tbsv.h" // -- Level-3 BLAS prototypes -- #include "bla_gemm.h" #include "bla_hemm.h" #include "bla_herk.h" #include "bla_her2k.h" #include "bla_symm.h" #include "bla_syrk.h" #include "bla_syr2k.h" #include "bla_trmm.h" #include "bla_trsm.h" #include "bla_gemm_check.h" #include "bla_hemm_check.h" #include "bla_herk_check.h" #include "bla_her2k_check.h" #include "bla_symm_check.h" #include "bla_syrk_check.h" #include "bla_syr2k_check.h" #include "bla_trmm_check.h" #include "bla_trsm_check.h" // -- BLAS extension prototypes -- // unique to BLIS #include "bla_axpby.h" // level-3 #include "bla_gemmt.h" #include "bla_gemmt_check.h" // batch #include "bla_gemm_batch.h" // 3m #include "bla_gemm3m.h" #include "bla_gemm3m_check.h" // -- Fortran-compatible APIs to BLIS functions -- #include "b77_thread.h" #endif // BLIS_ENABLE_BLAS blis-0.9.0/frame/compat/blis/000077500000000000000000000000001422157504600157655ustar00rootroot00000000000000blis-0.9.0/frame/compat/blis/thread/000077500000000000000000000000001422157504600172345ustar00rootroot00000000000000blis-0.9.0/frame/compat/blis/thread/b77_thread.c000066400000000000000000000053021422157504600213260ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2018, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // Define Fortran-compatible BLIS interfaces. // void PASTEF770(bli_thread_set_ways) ( const f77_int* jc, const f77_int* pc, const f77_int* ic, const f77_int* jr, const f77_int* ir ) { dim_t jc0 = *jc; dim_t pc0 = *pc; dim_t ic0 = *ic; dim_t jr0 = *jr; dim_t ir0 = *ir; // Initialize BLIS. bli_init_auto(); // Convert/typecast negative values to zero. //bli_convert_blas_dim1( *jc, jc0 ); //bli_convert_blas_dim1( *pc, pc0 ); //bli_convert_blas_dim1( *ic, ic0 ); //bli_convert_blas_dim1( *jr, jr0 ); //bli_convert_blas_dim1( *ir, ir0 ); // Call the BLIS function. bli_thread_set_ways( jc0, pc0, ic0, jr0, ir0 ); // Finalize BLIS. bli_finalize_auto(); } void PASTEF770(bli_thread_set_num_threads) ( const f77_int* nt ) { dim_t nt0 = *nt; // Initialize BLIS. bli_init_auto(); // Convert/typecast negative values to zero. //bli_convert_blas_dim1( *nt, nt0 ); // Call the BLIS function. bli_thread_set_num_threads( nt0 ); // Finalize BLIS. bli_finalize_auto(); } blis-0.9.0/frame/compat/blis/thread/b77_thread.h000066400000000000000000000037551422157504600213450ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype Fortran-compatible BLIS interfaces. // BLIS_EXPORT_BLAS void PASTEF770(bli_thread_set_ways) ( const f77_int* jc, const f77_int* pc, const f77_int* ic, const f77_int* jr, const f77_int* ir ); BLIS_EXPORT_BLAS void PASTEF770(bli_thread_set_num_threads) ( const f77_int* nt ); blis-0.9.0/frame/compat/cblas/000077500000000000000000000000001422157504600161205ustar00rootroot00000000000000blis-0.9.0/frame/compat/cblas/bli_cblas.h000066400000000000000000000041551422157504600202100ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_CBLAS_H #define BLIS_CBLAS_H #ifdef BLIS_ENABLE_CBLAS // Undefine these macros so that no internal conversion is done by CBLAS. // The function signatures have been modified to use the proper integer types // directly. #undef F77_INT #undef F77_CHAR // Include the main CBLAS header so that including this header file // (probably via blis.h) allows applications to access CBLAS // prototypes and definitions. #include "cblas.h" #endif // BLIS_ENABLE_CBLAS #endif blis-0.9.0/frame/compat/cblas/cblas.tgz000066400000000000000000006015341422157504600177430ustar00rootroot00000000000000‹ š8Mì½}â8²0ºÿN>…îìÙ É‚ y›Ù>÷BwÓMH ÛÉî9¿þâ$LȤ_æœùî·J’mÙ–eÙØºñô°õR*•ªJ¥ªrý´Uëîÿ%Ó«\.úyxH?Ëf•}ò‹ÆqhÕJå” Ó88ú 9È,v½Ìæý)€òûËhh)ÊA±û{Ås>çsM®:ëkÿéydͲ!„øó_9::ØÌ›ÿáx0z¹³2âñæÿçÿ°llæ?‹Íÿhx›¡ ˆ?ÿæ‘YÝÌ›ÿóþ'ë~8R ðqX­†Í¿Q)Uaþ+Õj¹ rŸòÿÃJù/¤œ 8ÞëŸÿ»ÑçyEJû¥-.ÈðæŽC¥áxk«?ýJàp ü˜ÏædkëÑ=ÿºõÓÿG¬Áã„üŒÈìej‘o“҇ϗÙpü@“éỔР¹ŸL±Ô”Ì¾ÍæÖSég·™ÚœÌ‡32²>[£"éÏf/OØ 6úØÿl‘»É—ñhrgÝ!$dl ¬Ù¬?ýFàšÁžf¤?¾#O}U  ‡PŸÉ=AÒ'ÓÉË|8†’DÞf‚ð‰O{–3,çÓ3ítwv¡#ºÈH¡N†ã¹5½ïh÷B3ø|‡Â:· »)ƒG‡M=ö†³ád<+‘à%4Ó¼Çò€wÀÞxBö `†¶ÆF? ˆÃõ‹d843˜Z}€0ûEhãËpþHÁ÷Ÿ(ü´Q?áoŠ<¡™§>t8¶J?“ÜMlŒݹOÈüÛ3L¢`4š|™yZû¬×kþŸâŒ|¡£¶Ÿàð'c„ñWq"a¸ÙÛÛ#´vJkÄ F­%ÎõN¥³‹«ÓVƒ\võf·yÑè4P¿8¿l5®ÅzĨ·kŠUÙ*…ʪªH[]…7âÌTCaJqYIÀ™ e‘õCP¦[OŠ2S…23Ê*j(*R”EVò“ñ#-²…¤éÖ“"­¢BZEi\°H °ù â‘uâ’!u‘3†JÛ ]äÚ5+ÝÃ6µ›‘ÍCÜÊÁɘÓ„ú>Qâ¢P`¡Ü™¢ÓŒH²þµkF£S«™0tÆ©,E§¦•h€$¼A»¦2ljµ†Í8•¥Ø¬ÄÅf%›\ÝS4X÷hwž–¦/c^»ñռ̭8•}` ëD0¸ÊÔ'ÀǦ¨Œú•¹Z«ÚÎ`dËÃvÓþÌr¿Ò„6c} û·#¦¹ÎÄVhMÎ:uCŠ[_­`qEÓ'ÖÁéXOàÉî ©66*nT$zø-ƒ‹þ0ƒU(¬‘ÙBg7š!@>*±(Ä®.l€®ü`Jöçdp;êÏ>Beø,ì zøe2ý$lMFßB„ ›^hìC:Æ öo¯Öêë—þxN~Á>'\Œq(²ŸÎÎ]vî¾…lS^æîÂ%H9´¦ÃùÜ“Ûoä½5œ÷Óþx8{ …*ûÕý“c¨¶µõWÒ“k ¥`£5÷ìeõÜM8÷èÎ Í^n÷ì}Á –(aÁV°@ŒìWÿ;8#ïþt6ŸÀbïžìѲ¹²¾Î7“7?¹ý]ÙÔç?eóàÀàç?fµb‘²Q­V6ç?y\…M€wö·þŠÿ¾«q,ôƒÇþøÁr`“#œç”h­­¿î¥yÝGk4J»Ù­îÛF«E^‘ýÛáxö˜Ü—ü\$uÐ/[µ@Îf*}¸[tc?ägìDpFRÅi Ä ä!Ê“R‹ 0<ˆ,Qg&fþ£€ÃÝÇé”ަŒ®^‡ [¯ñóþèh«uQ;ktàÇ^×w2ÌëQÿ™™²ÖëVíMF±7›ßd¯¹ÿ2›Ú®CdžÓ¢¢4|[wa7n æ3²wV;;û¸õÚ©|Oö^(Fø ÐQã”çéäaÚbÄ|Oq”:Vjú[VJ¿Ù£œnujmFÑSj [UeÉ'ÿß^^¦.þ£åùÀ/ÿ+Õ£üÏãJUþ§¾º6 €¿e[À…š—üO»²RòÿûÿÙIÿ_.ªd¯ÖÁÞ¾¨¿­µß4È/–+ßáñÒ¤{ú„)ÝñLeUe»Îå“ÿÃq}DÊÿÊ_þ›c#ÿó¸<ò¿Õl_]oäÿâd/ÿÙTå£XjûW3VûtõíŸM°…Ïgû§“—Ñd¾?ê?÷Ÿöî¬Ïüëþ|ú2þ´OµŠ‚ïPux°u‡  9l¿3b À=²ÖºBˆª0XqK€OþÓ5•vQò¿ 7}òÿã6ò?ûk#ÿ7òßm}cH¡éO·Ïâßцßwùä÷Mó°švÑûÿjàüßÜÄæryä?ýÍùÿÂd/þÙL­©øÿ¤ÿ÷kþwå>Ù¾½÷4|žÁÇÔ lÏ« È g’çߣò0XeíÁ/ÿ¯Ú©‹ÿèýÿQ@þW6þ¹\^ù³¿Ùþ/ÞAògj#þBßæÿ{‘ÿDP‚ûþ‡eúôm\ú¸$ò¿{Ñ2Sí#rÿ_ñûÿ@ÉüÏã Èœý°xùèt¶ÖTø¡N¾E@¢½þx6${ÏÖ]<ÈÞ‡>,Øpí`sD°:“ÿFí켑Uò¿jT|ò¿R®nÎÿs¹šín¯ÖöÚ¼hÓÀãË‘…ya,;3ΣÅña<ñýpŠÕ,c ÿ€÷ô<ÿO2“½™K€«Ä“Bʲ<}ô‘“£Å²©G{‘k™}»HE\ÑtE2™b+4Ñàä˘|7œŒIáËãpðHf“—ѹ¨§ÃÏÃþ5”» eˆ,• M­2·ó—©5Û)acnÒJ(<³0cŒãÿ âÓá#y†>ï¹5ú†)Ph÷žqþºÅqQ?=kvŽ ñ&äN¤ãFeêeŒnlÖK ÔŸÒ,/¼6‡X›vѲúƒo,K%O¸Cûé=Zcš$1d"h89¦æ3}ŽFäÙ$MÐIî¬yº¿ƒæY¼8fu¤9gv›ÒÖVãºQ¿ê5ÛoHïmƒôÝ^£Óe ÀÍKû<à|ÿëŒÆ”â­»à­AðÖÁ[¬-“üÃŽgߟ Çf°i±Ä¯Ä Pbà+ñG Ä¾ ŽŠŽJŽŠŽJŽŠŽJŽŠŽÊÖÇt/NA@cH‡ýÌZ:*ψ˜žf_ ?ºPÄ4GðøÓxò…<ÂÿðýÌ_E–¿sÛ¡ÂÒöÖVxb"R8Ø7Ëû'Ç;Ùtj1žöò|Ç’tQ¥€Ò2 `Œ·Öü‹e±äF8Þp 扊j¶ãI8U"µÁ`2½ÃƒùJq©óò,‹’5†SèëŽ"ƒªdv+>,Û]Òt¹ãÉœV¸³î·­»¡Ch£ÙÄk´ì”” äTœ4cl‘­Á'Êóxr+lÄú:´¸“˜ö òÌó`Òä®·ý;ã¹à–îàßòéÛoØÌ8îtÈNÁp¨m¨‚ $°þ™3tigÞ*!1D@»ƒþ|k± f ÄyŒ rÇ–]‚÷ lzòÄ2SÍh#â¦ô“îË:¿Ôž‹6ÁAÚ¡“2vÒCcl:l¤¸€PÜæ·¶®(¶ïbßY÷÷äíd:R¨ìû''P«Ðc§Dê# òá±?²¾‘‚¹oVöË•4¯‡_¹ôþ¿ý§þW6–ç¬ ¤þ<™Rº{œZÀæ­>ÐEÿaò+A´Þõ§w •s$¤­fí¼v 5@‚(C,Né¿LþñŠ ióÿ í"¹}™CÁ{bˆ×/ýy‚µ+|<ú¶ÅZ@Dކ°æ_ýŠ Øõ_‘vi]´áïbúÿl:X±üÿÕÍû?r¹ØüÛG6}Ä›žÿóþ‡\.ïü÷_¾GC™¥AŠ}Džÿ2ûÿ¡Y=8ª0ÿ‡eccÿÏåÚßÝ"»t›(èè½y["g“"1Pñ89¦òýz§vC:°;Æm4ì v÷·þj§ÿøÇ öÜã‡Òãº÷~¦æÛÒãÏþ[‘ÞðþÖçÉðŽÀ~ó#zHÏž'3ë#*À…Á#lwñk‘jÓ,êÇ^§Öî^^tð +ìÿEnx_ è‹Í·'cOöC9>f°Sâ£Û<ƒ•‰ÅÂñú°=gú¬{5>¦Šæ;‘Íw†6ø#6–ͰS¾¼òðq`?Y©Šµü7@ÚøåÿAõÀÜÈÿ<.Q€ß 'ùP¦£á‚Ýš|*òo#k:µ¿Ç÷“ßh©Ñpü‰§eÕë\5~ÛbŒ…•CCÕo[ÐÏýuf…uxÊØþâÆû½7›¢gB‘ÐB»Ÿ±«ß¶þŠË9P‘õVc|7¼ç¢VT)àwÆ×ˆõunMÑŠ¨3RoyaÌâ£àÀ òORp[%¯^à_ jï‡öî ?ïâEš­VãM­EþYk]5ÈÅkrYëÔνF‡´¯ÎOáãow¤}Ñ#gp¯Þkœ‘Óò·¡µÿ Ĉ³ýÙùwgb™Ð›n9·|ž«P ¦7ᘦ­1è9êï¡J$aX´ÉûѤ?'¤öoó¿áÙÿ”Kå"üÿg‘8üškÕÃÕCzÒä/ ¥ \¿l=qYëvÖÜA82yv_äœcð`=}Ùl0Ùì…›RÇ+â)ê%I iÏ{—–,4Û°šgEV_$eúO˜X… ü3ŠäšþE¢(’›"®=§ Æv¤€˜¿yæî¼®µº x\OÑÂEâ@›)|•Äðy‘(B›¨Õ”@- ÐfêQJ šYâó$=|êYN¤‘|¥°ÊË2(õ–9Ua¤7à ·Ë.oék‚·+?¤KYøI!5s\÷IaÌuÙg d䪇Ú–†ÅåV_q¹ W\´ØÝm”:³ JÍm¤R³ ªÊp—)Àš N$Àå¼$ÈAz—s$‡)l`^®Ž¦‰a#KÜ1X—¬ÙŠ——ZR®&eü°êIÂÛH-rtI +ÃjÁ»DN›Þe1ÚDð.‘Ï.€ß¼Ùì æÍeó5UþQßù¨°AêȘǠe’{/_Œ0J.Um—'"/k†¡§IFA™Ý&ÿ8ø2ä 1VÇÂf¦v=Fï–©mÉ`[î Idž $x¹®ÌàKC`êÛ¾´}=m_îh—.3£m^Ë›a;Z?SX¶•+ Е9ÄÓÔX²yHÄ¥à¥cv²>ÚIJTq¶ZæÊNçªÒiÀ™çºNá²èR1 åY_Ey^PEyNº§ÏV9y^`CŸ­Z",þ^%[9¢þ­³r^Ðe'8ŸØ$g*2%€-‘ê@˜Ñe\ l}>Õfë´èlëËÙ:ýîØ«%£æh€ ÅŒ+ÙReñÄ0Ÿ”zì^¥îÂ[F½ hŒ‘ÈY\lõ<+†Ñ‹LâØàê‰Ð”Á5ª·aNP‘R•¬.œɺ”Õ® ä2{ó^ëY€˜ÝRÏÚtVzöpê,ô(uFß>_Ð>5¤Çv†Ê¢ž šJ®i=+05õš0cñº U›EÁ áwI Ö;ëOâò"LZïô?}ˆ°jZ8Ò6;µLuR°,–¥ ç’9V(—À°²€2S~•=À)³«\N‰[åkª¥þÈ|ÁyèH":}¥Ru’5ˆšêäG" ¨©HFwÓœ¾ ¹(€á[æôU±tau0š®^£:ÈÉÕhB¸´E“¾\×Lðe´d²5rÅDCÍô¡f CÍVÿj¶ÇPA(áÙC©aŒË1²9†ZÆp®‘Í1Tªàfy •* CÍRÖ 29† ¹ÌŞļ×z f·Ô³‡6Ãc¨TáLåJ_¹]P¹MOÉò*U&Ëc¨•š,¡RÔk²<†ÊFµÉò*m¥!ûc¨´!Îô*m`3<†JU-Ëð*EÍ,Ãc¨•³ ¡²ÑÏ2<†J[õÉü*m€³<†JÖTŽ¡ôUËçUËçT-eC¥m&Ëà*]YÇPéÈ28†ÊÌ:–Á1T§ô¡Ò67¥ •®­)ýc¨t MéCefeJÿ*ÓMráú`MñCe­äùPtáŠõ ~¥–w±È®GµI7­,ö&4†A7~ê¹ šYJå0x0PNлž¤Ð齫wÍm¸¬{3”¦¶;—´¦Mš dI€ú d@ ;O‰üô{7ãâ=š™ô™ù`Af>X3¬3À°f.ƒ!?fÙ{¶Ì<Ð}žÌ|°|f!f.!7fÙy¦Ì\Ö{ÚÌüÑššÚ)e¡èÌ뇦ŸÉƒ«S–ÌÕe0H÷ày°÷(`râó±ÀÈáGÁ{íE“©4y¦ ÅÒ8¿ „\ˆ4,ùÈ‚XPd'¢ÀH]:<ëK‡ç¥ÃsLér²ø¢!åTc È…t…B$! .]‰w¹¥›,>N7 Ø<8UHÚô°(‘ä­kZ7°äbúp(ÃëxÆ“…&¬âv‰{×ÖµX]b0´µßÓñvzo„º™"ȵ ‡K‘ ô:ÏšâC‘. Äï? D«rºlíy1¶ö¬ÍÖÒVábð´´•·$ -mµ-7Û õÿ'=ŠÇ%ÌÆ·Ö3¾±Ã‹“çép<¿/üLþ¶g˜3ûÝõ½· Òkt{]rñš4:‹Î^ãºÙëþ×øç¢°ÊY/È'üÍí²‹üml¶M^›ö´üçÖ_²¹ê§­ZwnÍæÃñÃþàã H³Jƒ4û(—ˇÕ*ÁÏ£ÃCúY6Ùoøb˜F™F¥zhVŽ*)Õã/¤œ&a×ËlÞŸ(¿¿Œ†–¢»¿W<§ƒ)çsM®¿ǃÑËEþ1›ß '¥ÇÿÜo?xî1AVzüÙë#ÒÞߢ'ö³ÈÈšN‹Âêÿ– ÇŸ> …Û¯˜<ö§d×%ýß¶ Ÿû;ëž¼>:úX‡§[Ÿ'Ã;ú‹U,Øè½ÙtܲЄÚýŒ]Áêù+]•þЬ¯°ã»áý«ÃÙ~çâÝú:·¦c¢7RoyaÌâ£àÀ=Ì [Ev Š£`xØ i¶Z7µŽ|Õ@¶rYëÔνF‡´¯ÎOáãow¤}Ñ#gp¯Þ&tzƒÉá7ÌA¶æ°c䚤LGÝrn3øùË‹2SMBîüÐiÃ%Æpì™4.æXq$9DwÈþ.ôG#2´@¾Ngs2ŸP2&»ûXÅ«ðÚ‹Ë” QñçŸr¢[àïn=.µ¨äîOO?ÃsÍW°óÒl¤~mÄðéXºàª8>·>ﯲýO$5ÙNô§ì/Í€^aÂŽÜJ¶ÂXSà,+¸teZŸêæö¼> ç°®# `/jo¨^YóXó•ê8Va|M _/Ø×ïKú^ôO|z/{°&ЯìëŒ÷¥a]ב5½ Xè× öuÆûÒ°®—£+>½› å’¹¸×j›ZP›Ë ‘PêÖƒ9Ñ>X7"$#_eÀÛ\|»`›YŠût±ÐYmBõØßD’ÍþsõÁNUD.윀֊ì@v]VÒ¼²ðkúc}…l+©Ðú²¶ø)Ðúz€¾ÆX_!»JZ´¾”í}:´¾ ¯1Ö—iSÉØão=“['R#󸯉¼€^X5OÇ¢²0ig¾›î”Ó"ê¼wøép@ ¨S5§ä¶—õ2 …í8ãÐu’2ÜË3]å¶—ˆë|0m_ø32*1Ä‹PQ >1Ž/á£Ìñ¬3|xœs<´&_x0ò]¸5\¸ÜЋe;CÉ¡e(µîç«åÒ ¬ˆÜ¶¡ C-Rð- ›¯»u€ZÂ.VÆy%eç°é\j e¯ØAÊ^¨å‚0k°uãÈcPv"½Kwo¿0¼ršÎn3‘&‚9Y¬‚]:Îp·¦›z+]^`K¼0ÀÎv‹–&Šõ‰xUPwÙ%‚8%M?'Ú/ ð"T¼ˆ âå£xá‘ê¹ûc¸QdE6€ñ€^•ý_bT/sû—ÕËÜý-JÕKÙ,LÕkõŠlý¦ê¥ìü¥êœ÷%iÐsžû¾E)ymл¤]_ L9ÃsÐEáMF¿KXÊŠWÞd¼ÀšI Ó¥àT·OùQðRNDÁ+‚ภ0Þˆ8Až}‹‚l×Ñ;AÆÒkr‚Ì@õïÊWõY­° Vé9Ø¥oÅcB½*„äÈ^µdMd¯Ú r,Ê^™CÍx”½`¯ˆaqÊ^™äX”½œ±izÙ'ȱ¨y}¼B'Èi“pæÇ›ñhxNÓ&âUAñ gCÅofDÅËx5O3¢âÌNx×çYôªìÿ£zÅN5Q½b'ȱ¨zUŽ5ãQõ@½"[¿…©zUNcQõò8cÓó’OcQòÚ wuNã2åep¦N¿Kx%OS§à¬OÓ¦à¬83¢à¥¼’'ÈQp'Èóiüd»ŽÞ 2–œ ×ýn“ËFÏ Œ¯ÆÃ¹‘ •R=Pfû7éÒå\¡×31È¡°/£GÖÀë&F/Û¹g ºÞqQ,Ð#Qï{§FRÐõrc§ ºõ’÷l¯Ì(Öj ‘¼ŽS6ŒµDPÛXÇ©ÅZA¢G­ãT„ #ÏA-]VˆÙ0Wmk5†ÅeÅJc­±°¬XåQ¬Õ—+=Œ<¡é´‘¥°0¥ÂN׆žÙÖüTD„¹L JA:,þ…òIhA™°lðS+³J‚Eà_Äšš 0Wcëþâ2@¾†—?‚u?u°Ä† Xæ HS/ùÀ¯õšúèsñ˜èÏÆz—Ê Öi«z¸Î(Öi +z´Ê Öi«z°Î(–{®³ŒÈÆj—«ŒX…!¬ê¡B¾2bư¢G ¹ÊˆUª(ä+#2:OÈYH,¸Ëþ5>«Ã„ŒÁ¹K…e‚ŸÑQÂ2¨?FªÄ“æAÂR¨?½smðƒ6°ü7鞃ä½7X&ôéóþ…ÀËåý9ƒŸÆf`E¨%Î0—Íû—Hýià_>Þˆ Kš%KšÅ Kš­mXÒl­Ã’dÐ Ø_í°¤àEä¯ZXR Ð#QŸsXRš {QŸ§×ÜQ¬ÕVõä0¥a¬Õ Vôì0Q¬ÕVõô0¥a¬bXRv²"O¯ÿ¬dÅJŒaUOs–+1ˆ=CÌWV¬ÄVõ1gY‘kXRvÂB~‘zTCVrbÙà¯MXR–Òa©ð¯KXRV2aÙà¯MXR–’ ]“þ²eÀÂ&ýåÊ€¼Á_›°¤ÌdÀ²á_—°¤¼dÀ2WÀJ‡%e&ƒ_ÓmÞ~Ã’âb†°ª‡ éŒbư¢G © b†°ª éŒbÃ’²“9úþg%#Va«z¨¯ŒX…1¬è‘B®2b†°ª ùʈ<Ã’² îã2‚M _—°¤,¥Â2Á_“°¤¬dÁ Qÿ*‡%e)_Ó³>Ó Bºç yï – ýº„%åÆûsMÂ’2ܬ õ¯rXRn¼_>ÞˆKz´¦Ÿâ†%ÙuôÂ’°tÁ•$c[,ðB2þއÖ:±ßh¥wâCÁ¤…† e©^¼‘Òfš¨zÑEz :xU¿Ew•@®OÆ¿¯Ð2¹F ç†g½³˜ô,jVdÏ« ´”ž×äÜð¬õ&]f¿’FÎÒ×8†Ášê[õ`ðkfÄ)„6Œ€W³!”›fSàÁqMŽÚ´¸o,JÈ ·R²]U܆sÜLpk0Û¬YšÀÆã æ2ÀM…n—ìrp›Ã]>´9H³…áMJºËÁn–º‚†kö-¾Ë®£gÇÂÒ Ù±¼&Ól¬XHÿüÄ´b-§ž K g„^”°z¦ =`5­+«ð€›Àzµ:箞i"&ýª «ð€›ÀZµ:ç®–}Â…v!+•ÒT-)zFhFKÅh,ëÔR1*¡Ô¼0šjºv“¸Ü5ÆÜç…ÓX[£åâTÎQ3À©žñ!&3ÍfI¥ ª6 æMN—jÞ8Í…¡.Ö¼§?–º¬f#û5¬LÖÔäf&3Ž»”Ï_Ê\ÌÐtÎËÔmÊ\Øâ”ÀÚÞS€êO†k{Êè@¬iYAȵ|VöV©„7Eâ+=þì¿·>O†wäõÑÑÇAÿëó·Â`2žÍ ð²ÛÎDÑ"»ýÑóc¿È\KY*jCO×v離ïÉÍÎ=ìåöŒýñ> "¯Säå)cœZó—éy™ö`Û†1j= i?Øz,èî&óÁbЩ ´Ã^¼Ðâ³—Ûˆ‹„VQÂý’!ÜØ/°_¢À~Q€=ôG Ö£b){Á¤ÝHVY(h÷£Iždh»1`ûÒ.ÍÙLs!ÑÞ ‹ë"kð¦(_DXÁúOý¯ŠY É;D5m·MþúÙÿþ/{‚?vx/…²Ø§­ÑñîDÜùÅ Ô›*j6OŸÌ$@ñÞXg¼Ogžú³—'͵(ïƒ6ècÙrñG¹¤úŸ™§þwX92Í€þwx´Ñÿò¸˜þ‡— Ä•.Kä¼?Yߊälø*݈4þïËðùÉ‚Å\ŸLŸ'Óþ|8—ìÚ—Së~øÕº#?×?þLæ‚tEp{7[ @ŽïÈüÑNÉ5õYå™­?âu>¹Þ¡è¿W"oKälR$ÕýòñþÉq‘tß4÷ëÚ éX3«?<–¼ºä?fó»Ñð¶ôøŸ2=2LåÄ̃õô¹@YÕdz‡ûôÁcJvç¸Q.2&öÄ?Ç­"¨‡ éúúˆ›áõ‹óËVã ñfFw}/[þZt˜å×Ð.n­¹#‰¿¹¾¡‹â–¼ÃJ,8,þ^lÑŸÖøåÉ.Ü©µ»—Ý¡£¥Þ‹Öü#ûdf}œ{¶ 6*þN¿PéDeÅh§‹Ïßu‡I莼”ýb»?Öü.ÈÀÜyêF“AÚ|ÚÙ…Š»³áÖä¾ ÔŽcýH _•#Ãì>Áß_~q ìéïøô÷ìŽá/>ýQM¨ýaÜþò;ùïÒÔê^õÿ ÀäììþþËßü-´Êð©ÿ¨‚7Ý*²o\Å ”F|æÎ93!‰!yqõ¨VÄŽŠäk‘ÅÖOØ#oìæ7SË*Ôè/ìÑqpõÍPý¢Eg( (×nÅ€’èT>0á#fN)ˆ®éÈÓéUû¬ñºÙnœ¥Ü¡G‹|¸µ¼éç§‘ýåVãOŠÍ Š\ëª6|k_Q’Tö$ ;N'_Š¿&£%1†O/¿¢1mîðJ¶Úw‰Í ÀI ¼‡=H¸ƒ”9|záÜÁ]ÿ8úW†½¡»b!¯ ð`G¼Ë™ >Œä'…ß÷°ÜÎ/ØE\Î⯬ÏcøÇÅJÇÁ9¿Ç€Þ_% æ?=3„ð|–(Añæj¸Gg+t®lºQÌXØ`ÝÉPÌXذ=•U3f³ÄÛhá@eJ1±õ0 & J‰ÛP)À¬£À Jˆ[©„H¡3¯t°¦/éà— ®¬:šŸGqkQÛ‹#;1Ô¼¤*Ú+ OÝuYðS"ö»‚º™_1*ð¯=Ÿæá*61ÙË/5…T6ÄWLü¦ªBÇÀD€õ,¦0:ÈrY²ø Õ±Ua½ÇkÑ¿¨k³¨éZ\¢&ú«š¬õž ha³´µ—ö “¥=Hki?Ê5/Ï#ØÌh¬ï-­E)oá«];‚hnÓ’m®.[ììÊðÛ1<ü?v’ó‹(3 ¨Ô‰ô€ñêñ /³x”h™K²Í<Êl3x$6 ‘–žýè·Äh4Òºw¡ÊÍ.¾…ÊŒ,|]-d` m!ZrÓ‘„7à_´!K–-XfTÌ*Ù®],‚ÈÿóJpè#ÿ;ñÜ¥hº³ççÈGí"›¦Û,)àK½Ù¤tî.eÛæã˜{ŸQï6pã®ËhDd¼‘á à÷Ú…¦Þ38ˆ¶vÙÖ¡à£0ñ7N´)›ÐÐØõçVØ4ÉxJ˱!åÝÁ&0'É+ê ̈ûÍG‰t„åõ qh™[Ï$†3Õðˆm?‹ d¾ £©9™M  [š-2"9^¸€¸]PÈó–~bú¶G<ßþ‰'úÞ,“ü!lÙ ©{I ªØ¥TX¸;¯jðœ†/}þ¦¹W3ÑÜaȵKQ}ÿ´Ÿ‡ð©Ø3ÿÐ0eÓ­VÆñ/Ûf¸† äv aÙÕ.£Ú#…¶ù‹AuŠ}sg×Eø3I¦c€ä(’O>ñ!cµ\ùóo¨ÁhÅÍÐó¿É§H¶*n…x…H&jƒÆÇ Û½y;Ʃ¥ p„ýÃ[!Êúá‚JþÇŸß…ñ¯éôÐa‘Ä<óã.⨉ –L>#"ë‰Þm_ÊûƒÈÄ+JÛ7.í;&Ú•?kíÊŸ5áVîΟ#wç±»ñÈâ¹r›îu•`¿î†ý‡1ïÀ·_̬æHh“8n³©þ ­Ãª¬Eù0„ aÏý³fí Á1Fø<.j ŽO±=ö”aïïø‘Ó&®ÞäócUHÐõ¸’·õ“MZq¶õ²]=Ùlë7ÛzIÅ·õ¾]½txZ£K:¸DcûÓ]ä~>ŒŠ¥»ù¸›ùÅ÷ò nåÿ”â& ;ȸ“R†&ìæ·ØÞÃÕˆ_SH¸iŸ‡nÚ•l–x¹l@ ˜K7æÚMúþlŸ®Ä÷ŠüÌOQæÏË|âÝܧ"ýã ÿ„îôÿ‘¥šFý\€U0é ›ûõ±å˘œ† Àå¿cCd*@lÓ€ Ó €DþÏÒ“ÿJã»¶üOj}Wìí}¶sðŸ62>\ÆË¬g*!/ZŠ"ŽéE+½RžGšè½zµn ³Îÿ”²‰`c•ßXå½Ó}K4LJâ9G«¼”¯„HÑ6Ÿ¹Ù}nv×àuA¡*7­G6哦‹ì¦7Âtu„éìû¦²ô§u¤KáØ)IÒ4öʈPu…X’J˜ÊjHÒYº’t–‚$¦q¢9:„ë*Nah¯bÄ…¦fœû)IH̰1o ¥FÍ•ësM#îÃí>z}jš¦ZGHró‘¸J:=Ji±µÍzåë5Äõµfâ>õ¢¸¼2Xwùþcáþä_²Úæ`ÿ’•Åj%9ýjë,Ì'›¶™`ÝJœ®§Ñ>מœ\%JSÕÖßœ.ê%ÇÑ)ˆfí?ÇØ¦à M<ÛClP™PGêýÓªùA¯ÙvD²MüŽí­k¶‡—íWcv¹Œ„`0°È“zJ¤LÏIq¨µ"EFOzúLE¤R­I©4Õ%™A¯ðôèq•%ÌNF¡SEP_¨!‰ ˜†Dê…´á×Í’h¤‘(GÕÔw¨CšªC†°”(ÜcÅIG­TÚmHl¥RÝœL¡\5}2Û#âŸü\„¤"r³5h€Îþˆ!£KÇ}þ§ 䫨F LšÃj)ú¡Þ [ D—KDé ?J®šj˜dfTë/O¥pÙ3’•:hFG’Jó£)4CS1Þœ/ÓZlƒabca²tˆ9gE‹u¦ïl‰dî]ÇNÎÈåƒy©ÉŠgP$MŒqØ?YbÌ\‰)¤JDÌ„¯\É6¬¨J‘H[ÓÝÐÃR#¦³«#élì~ÒJ}º²‹=Âx®{|¶~ëÝ _ð Ó¥~+?©Ðf+7”$ÜN“qßœE)Öÿþ§JžïªÂ|ÿçauóþ§<®•ÿ“qáûŸþzP-âYç?•}÷¹œøÉpï; ”¾gøÞ$õúª™¾÷çmØ›¥”‘ÕzÙP·B…ø­SêV•»8¼ÓÀ€¨ä7°¥Sø¿î“ã(%NñO]íˆÓç>·j›¾ý꙾ãF#-wk—»eêeM;öþºñ Åõ“£8ß¡à—£´ã~Yú)<`wˆ}þò»£Dü¾Ë¤æ/ðH]§W"Äa1¬ªÌÒOÑHòx;`Dv,}ŠÂÒÓò±ä#±[5‰zuS¸N£|»hˆý©{$1úB£ÂO)2NôÝrd܆¢O¨AÑç­—ÈN+1Mˆ!ªÇÇ'2™íMo)æ‡%{kS÷’O]ëmu]_^?Y¨Y—u:²ºƒ‹Ù@Ž ¡8E„·¸ôeîëæžäïVrMQx³? lÐòHN¹$ãC©H#©!&ˆˆW>\ý^œâƇ«b¼æLúëÔó«žls$`Ú÷ž(5¦ŒcATß¹¾Âp=(ríCº‹býû#·2èûOïK)dzßt>º—Ya\•Ïéqeï§äŠž²ÿ¬T½0¯ênó¬AfÃ;K#-.>Å¢ì)Eôßñw,õ+8’·eÝÏ%šOiQûhf©Û­€ÖB?pÅ=b¨v±ÏýhŠ”»Šœ5¹¢) µEè"„ÓŽBg[ì-L^„ÄÔB⨠ÒÖ;üã_ ÍãQ¦y ãqì{ò÷þÚú…L&mTŽ0»*‡ÅN¬„#ÜC‘¬Ö5ýºFêŠJÆìÛ¢JÆ‚jÆ"¥6ªFLûHšF¨8ôJBÁÿ¬zhlqeºŽH_@¢Ë´W6ÿ¶ŠF¹dõ Õß<œ–ò¾Õ”¢¡BQ‡¢Ë@ ØÉW²Ž³€^‡OºÁÇÒÌy¼•tß)Ç+…¿F"¼DÙÄ¥R˜<ÓYHe-Á—¬/ÀhtNBrbõ«t² DŒN˜›9?÷ s\5޹_\$~=Çý"ð8U»m»Üõ‰:ûäÖõyM.ÛÆ«³CL¼'´ÑŠïG£#ž‚xŒÚBOaúÉzñ½Ù·…Þ{¾DoJÛˆCÆÎ2‡Gn„áF®¬0¤¼OGúdáFJ‘! µx‚ö%ãôñ§Ï·}11H²>d÷‰Ê.ýÒ/O£däéw.'e®<)l%©i¸kîÂÆ Šb²|­ ¼—¹·EL6‰öô*Qg¯ÌL¿½dJ…õüNt\……|§ “S TšãÁ6Wï.jœ^!­%¥#^­1•–;ñ9ïêëboqU™Èž¼‡¹)è3 ç¦qš»ÑoVE¿IU½Ùh7ËÓnâ…>h¹¸gG±Ñké5z©°WJ«aÒjQ­f£Ô 3é(5zGõ)è4J•f>ÕõOÓL.DFÆWt<-…fÔ©¦¢ÔR|šˆàS–,|y:Åøìä¶lKþrÉ•¹Õ9IÛñn¿»¼=éÝ78<ùe°èoåÍ ïu¾B>îõ‰KÏq<8àW>œü^œâÀ‡}œä½O~‰‡$àÆ&—¶´Ÿ¿¸D}ø^•3KMÒ¦)k7Òv¥-‰· +øFànîw'pgK¸³œî,m»ìüLY_túòÍ’*ÓUìKÿëèÀ< æÿ:ªlòåq±Ù¹xÓ©“:’CÏØÚ¥w{@äy:y˜öŸ%a/b+(¬ÏÖˆL‡*ñJ§ý™ukn2¦Å'ÓáÃpܱB ÍÎ FæPy|Îåõ_—ßÔ^“Æ×þÓóÈ"—¼ûžõuÎK”Jä²÷¬¹5Á/ηší^ãM£ã²¼öÅU?»¬Áè=÷i¾:Üq›ìú£>´7“úäé Ào¹Y¯uE¸_¿¦oŠäüâ î´yÖÅ(Órk\Öº]·¯Ö:sztúé4Ä*pu_×êá0¸í5¾*ÉÝ—['åšÓlãÞš®¿mÔßEöiÉÛFí¬Ñq›ãã¿™þIhfþü¢-€·w`V÷9:Ú2Œx~ÖŸ÷ ¬¤¹…‰ä„¶Ïj½Z`èû'¥£ÃƒCó ±WÝGk ^æý[ Ž®¤©f¯Á&¸x‚—-VÏ.ˆY¼Nƒ7Ê®x¤€Ûͺ{¦¯å`†wŽEÇÃù°?‡Í;dÌr‡Ã¦‹¥OÆÖ2€åPr«÷`I|î^,‚Ñrn°XXõ/ÃшôŸŸ-Ø© é:r[¸³æýá–‰~~™Q ÷Çߊ´1ìnúsr7!ã ì¬ÆŸ'£ÏBЈîggtî¨qL€ˆR¯sÕ( á6Âì¹y¸Iá”|M Ç¥V£t°Czom÷©lFŽœyA7n´`jÜÞ4J‡ÊŒ@í3¨ïŽo˜ ì9½àáÀw´sLÛª©_´{ÍöUƒWêö..m”¼Èë‹Îy­G Û¸p€g}弎²O›u¬ÙËh>Û.î×;´â±PQãÚËÍýºmÆgCuuÚÈA÷ ,éï‚aÖ¦Óþ7‘!½(ëä®qÀ›)åÕbdÒÎþ6Û ÕÏ.zõíý𢦧蕪hÅ-Z»¾¼Q­ºEëê¢nÑî‡Ú¥ªè¡S´[owÎMUÙ#¡l­{u®*{,€$¡*z"* „a†i>¯]o/"RlŠn1¶d¯ÅN£wÕi8Ãþ6c“{2{¹µ5ªñËÓ­5Ý.6+Å“ëbÍ8P®hs‹·®• ;teÃr{xñ!" ¡0%OHÀôÔ(ACåW½-¾"y3Üvо4"™Q°W¢…ãâAÑÜ)²Ÿ‡îϺ_¯è¹-ö¸Î?\Ö»°2‹ô[¯p°>ìäeéת[X2>,QÁAEòõËx@Sô*çž®eÜöCw”àwÕ|òŠÓ‹bÕ¤J/¡ÜM9k¶Î[ÇQ†ŸnÍñ…Ùp CŒ¯ÓlwAtæ©v_ôd*{€ºaµýr©Ò(I¡\ªÂç^¹tÔnZ«Pâlßbó•Qâ|  Z [0Je(fâ_ EåÏ|a˜Ø£ˆÀßú¸ÕЧ˜úgư Ø£ã`:`¿ öû€6sÕŒ§˜úgÒF4I@?tËxD[=Ž‚ÅSLýS»F,>È8é¨f¨*«e²Ÿ”‹•(H<Å”?5–±™tSj,ØÝª~æÛˆS¢+Eµâ)¦þ™q#~*§4Wµ\h‡œðŽÖT1À1q¦qâg“•“¥«šÌœ”+îä±¥x©èÉa@9Pœ™t åˆéÁ'ά:Sy̪jIÅA³M¦ðý馰vj†dEx4 %õzxG6Ê…f#A¦àQ7¢ÇoómE$”•,¬‹ø™‚¶:âá>…$+ñè$Jœ‹GW[áLáð;Õþéü™kª(°ED“«'ˆËk=ô„2ÓêE5áX¸KÕ(A¹ãpÆL¹@MyÍòabi¿€­Á]öߟ.\ök§ ©^_ðp‡%k¾eC8öTÔ¶HÈ™ÅÂz€oÙk«î ±Kx˜B Ë„wèI{v„´„"1Ù?ýcÕ³ rX¶}K°-§axT-ã±{r°%öÚ†›øhžû­>1wÏk×…6(®Ï§kÍÉgk0GçœàÙ¦Ó1: ±n[>/¸ê×…æ<¥¦U¢ˆàÛ^"¼ˆ×W„cÊñ`iüǃe×Û6‚èzù#ÜÉ…RÜ‚0Ôú5£ÈÏÿ.ÅÜ;Ç„´ñ¹Ë€Ë |¤Ø>±‹Ø.¸ 0Ëé| 0= ƒ•>Døjˆòrtx4 Åø.ØpÉAvK5:Q È>Ð •]†Ö=´ÃàÐÓšQ›{î66vv[p ŠÔÅO¸‘j‚@ø›N^Fwãíí9¹µÈ£5µ¨_õÃØöצaž.¸ÛÞ¬RÖ ò…CÁ¥Ìv¿³¡ýSIÏ”RÝŸµ»;ÒgÞµÔ÷ýÚ‰õ_ú#|ïÖt" ¯ŽÑ.f¦äÿ;vøŸ—í2ïÊýB*ÛYb{'Ã)t@ƒ0‘léÈ—ž@™ø˜‚Bÿv=ì@cݸ‹!!öºˆ=:rÖŒrFhÆUhsÖö|mGãN“±åGƒDƒ*CÆo?4ÌöÓpü2“ ~O2újôè÷”ÃwžA¦‘òøY9ΧØî¿æ<áßünhæÆ -™HÏÆùe8(Ôãì=|¼oÃÿÝæ¿T ½¦0øv~“Àíì¢W@e¯Žm…ªýÕ,14üQ)U…4¯÷Œò5”¯iuøu#ü:,ØßŽØ7E;Çn=h~ìó†àÏp4ÁTuépºØ7À|¡cÁ/š>m/1tÑåÞaè‚» ÏºæòÖÐõ–E×ZÁ-±ÇYí´ ôÐl¯šÛY½¶¯ëkFçrŸí÷ðCYö†–Å‚ô#¼,Òe-WéøW)’£ðJPÅÙÊVËµâøøùÀ±caŠ`ó«)´¤¬ÈPî¡`CpQp|.•‡Å…Ðó£­C§.³GDÙŽ<õœ±¸VX~Ü9nUr¬—Ç:ô‚†ÆcñpáˆY«;þA)(ŽVTÿ̼zªšDÕX`|µ¼°)æÒ(¸Ô³bõA§cê;>q¨¹Â©ò$5šÒ¡msCÛ™Ž͹Gâ\Gr]¶«ªae>Ž£cVŸq—9ÃY·GWUw]ˆÌ[ÕëGÖ¡Iú• ég:¢8¤o°CœçU‡Ÿôª˜æI„Ê%åìlhZ^œ½º!ïŒGÿúòÀ§Ûf1(m¥* wàåÁ¿mpˆMEïh_Æi8iŸD"íT=rU¯*ëÚŒt„HÚ-âá„O‡ËTÊ|WŽ ôX ßcvÜzàìm¦\‰æeÉ{=:ä³yàŒ¶Ra·ŽÍˆ > L0ëÒáÈ*˜O8­ñé…þÊ\‰»ž<}bKU¦ÝEN—Éjž„-MÍÑ Õ°.Mwïªéh=š2iG ¥„¯µäA³]ØŽY4b¬‡ìñ.VIò$5©ä€[=#(sTÖžìU&›peÛá á¦×È‘Ÿpõ,™ù éX Ð1,‘^ókÑk„} ÈÐ#kÙVwCÖ)nt=ÌlÅÈZ[y÷’u:c¬Ýsv€ze;Ù õf¥Mxç}-´ ‰\9²>oOO¸ùŽNŽ¼Ç«D¹ FsA®‡RhÑ¡›)Ï‹M'F«JÓ3ûØçåÉsîCñ'ÐRJØÐµ' èÐ#ìïãÌZPe'Ô¥Tv8@FÚ±Ñtn”ŽœàBj7éioT·I·K¤;ÏOƒe0x¤¿ ž‚«P3íæJ£:°5 <W¡fÜÐÉ÷<Ö ºåtÁƒˆ˜‹ô{1΀§ëf.Óž'çX£vÚ-øBÎoÜû7;bšpžù¾èžðèLè¡íq Þìðè¼Ù.˜EÿStr‡‡Ô‹û}»x~x|#>¾ Ävݼì}LžÎƒà‹×7ÞßS9ò<"BŒçµáÔÀ§7üéý4Fä§Æg;ž‡FñÙÜ·bý¦H¶iXARæõ° a¾Vi‹FËыРÄQä0OZñ–¦r\WQãºÊz\G ÇU —íÚ:.»€'žÔZDðåM‘ŽþF nâoü¢}5z;!z»@pVô@G]× |ET} ˆtåqᮼ@l ¯Y´+Ú¶5€NaÌþöâDŸšiFŸ²òÑ_]'.¸‹ñE,r»Ø¥1Jb4ØnÔÅZR”s^·Ñ{ÛìRhDS­Óè’Z§S»éb¢h¸SØ!5'…¾_¼Fñ¦÷–&è]ðVº J`@S¤×蜓ÓöyÖ|ýºÑi´ë ¢¹jõš—­fã ŸãxŠÐWƒ7Ñn¼i5ß4O[’\½DZð¯ö¡{Ñ.’w—­"1NŽªä¬QÇw‹ìÆ ŽKòî­Ð8Õ;dZ !tˆF‘é5I‘•Aƒ¡`§ßWüµ:g¡$L…ÞEb²W? Œ=tŽãêWï³U7m¥i|²¼Ý3¸ÉHô¢=NÍØ;EB•IF1Í_è/ ÏÝîÙNÑóhAYàœ¶2ýæ6@"¾’Gz½…¥M¡³VÒ¾è‘z ßò mØ`z^ƒ’”+öBÖŸYŽèí&­G^ך-rÞèvko”3±·°²Ê~½Îëˆá~è;‹$ÏŽÓÿìÈy1…tΛEžMŠ x|f/i6Õ0I|ùÞ…8Úö¿g›Ð70ÁÞî_èV…¾I(Nqmû¶ZÛÄžmÕÅK lˆ¢…áAxgÏ‘²êE_ÝQià‡Ù¨–ŽáÃ0A튤˜@5˜5âÈQÞ€ZÐze(ü«µ)·ë@  îèz€ìP I!¾—×ï4þÏU³Ó8o}÷ÞÂÈ?€nFjäì궇µÎ›+úˆõ@¥s[áµkõÞpB§ØùH~ ý rÚp*‹Žû½Ñ¢}‰rV"f©˜=¥l¬hq†{.çÙ$„|©ìîøe?";’ÍŸ!‹XÖŒ2îúƒ”#x¹Ý·Í·íŒ#6$xŸá„ÝwÓø€vªý©5É^_µë½&ˆ-&ºµb÷4†‰•”:$ƒ`Ž¥°ÔQMì}¸ í«óÓF§[’hrL‘{Ý8%ÆARóÍv æùTÛºÃF÷ ÓLìa=%fÅä nî:K4WÛˆhëè¬Mî’Áâ\\_ ¤?¨ új]ÐWë}5D‡TiŠšKž­:³ì(Íì+…Á,'_þÝERÔšçµ7E lÛcHŠ4>ÄÝæe"Øj¡ÎEòޤ¢HK1Ìxã²[VLhLRŠaÜÛ˜­mJŠ ‰¥LIÚ&;š»ªý±MQ«ØIi…ÍÐVú|±¡÷Ö6ë°wبü³ÖiÖ`· šÞ§º,•ÞèµV³wSrXAªûáô’ÅÈ2¾ fÙˆV,iŒ¤§³\²{D¬yf¡´áƌѤö^ŒnÅ!ñM¥¬ÜdïÝzÉlû%Ý{…n¼Bw]Í3ú¢XÍ'!y¨½˜@„Eœe²»-å%ßmE@Ù^á»­¨í•Ù¬›†)n«–ýÞìïå’¾ÿÝÌñýï£zX>ܼÿ}I[QÎûßñõï&cèQog{¼INGýß´ã;®ízO€^<¿¸›?[ ¹¾‘>™=N¦sr‡é¤î‡#«D+ܧPÒ8"Sk0™ÞͰ¡É=í ‘þÔ‚Gý;ò2B%£ál¾w7„ÂsëD6}60üÍøªÒ&'Ó§þ„MÍ0A‡5Éì'Ƥ?OPøÝ‹¿~@èSP±! È ?ÆMnç}PÌïpHwÖÈš;MÓTÈàÔœÕrî§“'û%Þ÷“Ñhò Wª0 Píé‹ï·æKÝví’1÷6¨<¸WÅ;Ý· 4A®À^–¼n¶¨Ò²gø9íU»ÙãÛZOE¬r©G®º <"¥HX¶åxíL$WX^·pCÐC¹Ûi|hâùЧ¡ÚkTĵú[x^¿èœ•¢šÁÃ)ú £+P1i…ž¢Ý€6: èçºÙcL»BÙ)R¿h]·÷Îkï.: m:÷;웦sóô¢÷Û1K츾÷`y{Ñ:u·uÅì´v­×¤gG‡Yæ"—Véâ7º#-Cï&Lú9áE}ªZm½wÛ+ø èµEE;UÜA¼ÓC«@4{¦¤Ý@áŠVµÖåÛG'tÁÙ¡Ìü[¹tDÝÎvÝ9õôº9môÂ{1JÑìÅ®†"möqð`=}Fº£‹ PE錃êkQ#6»Êmì*ñ{yLÐËsì*óiü*ñ›'l°øUžcWy°¦ƒøU^b̔ĞýøU¬©¿Í*öA»eý*îÏ&ãt¿"ïJð¯HÎ^H}:ùÃþù¶ÿôÔŸŽP¢¶?¾ƒ[ãìo;X ä6’òÜß¼%3‹¾Hý5(SÅä´Æ®ˆRÜÿ¬[è²ë¼f}VaêYƒÇñ·ÞäÜzš@w}`:“Y‰T R˜ZŸ‡³!€PÙ¡E(ØÙ êÂp0s§¸Å&°;Zãc² Zmú0á^»V8è²Õ¿…ç“é·¢ÛÐÉh‹ÝÉËü‘Ôû³©žôbíê°5Ž&Ã9,W+'Eâž]LÅ_íÚqëÐ4ƒMXeÿøˆÝëTá+À×~y²¦´ m2Ο„ñ½™N^žA:ÏïJEÞlÝÆs÷÷Ã@F̃CÄÿøöeú öª“þ]‘\|åêN€ïÚ$G¸á½z_äh“õÌ;lŽØŸa”A½©³¹ÛPw>µ,Ðò`n‡s Ób‘ƾŒQłڟ"YÆÁžaVàîU·FqFõ¦=òºj"0ÏFy¯öòJêžqr|dÓ\gˆÚ›MEÒ°‡}ÏDÎì²ï¬©õôÍ&î"E•)†¨R|ãi7ñ­ó*(¯Pˆ¼"¬ |;$á9sI»{uÚU¶†Ш{ä4L$LþÕè\À$·ª¦°f2Ç4éøÂÑ2Ù¡uè=ùG\›hàø¤Ã:ê¼­µ^ÃGD‡Þ#íÖ¡?XM–¨\‰œó3Ïà;ÜU8‚çˆè»0¾oDÙp“5Ýnž±Ï÷§ì³ÖbŸ§¨.›¼Ó#»ø~b·Dï³êÿA‚ë†W¦]áw}Þ!™‘Æe·ˆZy‘kÎáƒnvº ÈÑlÖm:Ø×´ÿBó?Úu:ð½N 6gµw­ª°«èÕZP %S¯H÷,E* èñ.}íÔŠŽzÝîf¤ü´×À[˜•:Øu6\x<Þ >¶ë.nÝzçáùeÀÃ›Ô œN)AÀŠªñ;»üFøa 61`Å®·"ªÊ›@Tí\œÎ¯í6øBPV»ö—%7NKáÕn]›žN½›@½ˆÉGNáo춤 Ô[°×áåÎ…ŸïO öÂÜ 'Y–·Ÿ3ÜBêºc} ß4¯wš œºÍ[ƒ®¬n‘– v¯éŸ@êõ·ï"ý0ÙG…}TÙÇû8TÌi½nB XÔõóÖß&ΘÎS¦ã*òäMuø·^_ô˜Ø­‡ãõâ½bjCç©­öÉÙÇÎëû"E¡+IÚW}ßßeŒ|îœ÷·Å­ôv‘l‹ûämÅìm‹»ãíⶸó~>k6C÷²n½¹·™¹~33o3ÞŸÏ3½fè>Ñ­G÷€Â p§…›gZp[ܱ‰¸ÁŸ:Böa% ŒÅAñik ´ƒŽA¥šøËx8'ã—§[€-¼³Ü’}#°¦a_à ¯Pnò Ú2µÕ n>µ³SS_Ÿ£ò¹Kv˜` Ž?¦"ƒ/¥7’ý•&È)öl‡8Xº¸l´ \% vÈWLŽáPˆz¼»Ã¤ÖØQͲý9aÆâ™Z_† Íî“›—gãþóìq2ç U çñ‡&u#øÐ,ÕÚg% rtß³ùäù™v¶æoä¾?½L•2&¼i˦F¾ ;ú¸6¸¦¸†èÁ€ïðܳÚua!Àºd4ŽzÏ¡]í…תëÞ%Ñ®‹Q)‹O| ‚Wf± 00 Ypî²Uaï84ç©Jvš•:ÁBø"X_¯¬þ¥ý)ù pF,âŒÞÙM­Ñ°; çߎ©ûJY_ûæª%ØxR1‹^{)ýë;N4.Áàa¯áQvjúÚK:©øâv(µ?Á’lMbU"K®…Y½wî½û¢{‹½FÖW¡©ÈÀ¼q*¿Û-ƒ‚ìì½} òÜÛÅï{øžV°§ fvsCp+;£hf¸„ÝíËh^"cºEg¾a å7=VšWfSƒ¥É€Q*u6£em^FO"^Ø3Ú¤Nó`™{ÊN`èñ[‘ÔŠüáš¾æ±ÝÐï7@+odfªxîžýð#F[Œ¯:óOÝ^¡­¸@ka“í ØÅb¨‹A{¥vÃ^šØ1lkø˜ØÚ+œ*BwpÔ‹£=I{ß'–œˆ4±XÀI†öðùËtì‘I&.e<ß“ ‡(õÉ ÍÎiK;|h»J]2œ‘ñDnZRa¢Â…I×éFØQù“p0û8³+zªˆ01$¹6/Ôz)U*EÂc'?¾-»*‰Ïê)€È8õWðÈx:î¹{ñ^¢&~º*‹X'¶h*à›ª‹üÏ÷Ï!ÿ#Y/Ä}*þ9rþ‡U;Ƨ'ìlŸyÁñ×ß4Îÿ èu±ú›SúÓÄð7k¦3%ѯ:º“õö½˜*¾Ô™šn/sf›Ž8kfÇÓ6{`gáüDüý)žÚ§åø'´v”ÎÏÓñ ¦ N ”Õðÿnx3Èãðÿ.eo”umGÊrJo!ú:ôIÑgD£Ïn*KÈ÷-#_<&}ËH·Ê)ùí%ýy@)ù ìÎD!;aþá£ãà<¨¨øÇ…;% ÷:”R1КÑð~eô{\ôÔ€Â]¼}B ãW£Ì ¾wI”àã|%çIs¦!|ÒB¦G‚û oæ§Ÿ~J‡ˆ¿|,F˜o #ðë|­Pâ:ŠC\Õ|é0‚…Ð)]å¡Í¸O‡î~T-F’oÑïÐpe<þb"þ8Qü˜N‡(T-L”&nÌ\ªÄŸG”,Oâåá€ëtÈò‡@•œ,ÑÄ„è`«À@§VÌ Êw¾@ò5eG妡yæàXñæªì$Á ÚŽå a T4 .ùX!˜BðˆsïhÀ׃ؾ‰Ñ ޵í}»[ì\ŽeW(ÐÌ nè,õ±pbf™û';UÃ|« óÕ8Û†&ٜۊ´&ùðV)‡uZ‹Ù. ØMRÓe9>nöÞºUÀ- _#ŒGÓd@Pœ!AÁN}ˆ‡ôÖkÃ,Uà.íËie›eü:‡™5qvE3¾®]µzt’pmÕ@4½…%Ô¬ãtÚ«f·SÚö@SŒ1{#q2ml±“›–Œk{8‘1pì®X艎çièÚ ±€ SØîEÁ(.\Ze¦`!:… }^Ö@Çø{ž2Ep&fìà‘úÓÛBÕ(MÃ!3†¶¢k8ä:^¸ýPj¬i2Ï›7“ÌŒɸ§1ÜÙºöòu8bÐ}äH]²ý¹g$ifV074^ö­ëx©0ËÃX ,U/bVÕ‰$K’å’'"éÚú©,<ªn¹†Ç}2Š ¥+ϺhŠ™á1 l¿Ãb1ø„„Õ%É"ª€éÄY¾VGc†…_öh`¥F„c0øRc^Ý ¾L/Æ2œfâ„U6ÏŨʺS©´,›2Ô©p^ºËðõ¿RQÛR9:qÀ×Ù7$̉ó“ùÁÿï¯à²d1ßòGšö/•ôLP +}ßÂÿá¶÷þª‹!Ð}VS´O± 4Ñ ƒðZ9çŽ-µÎü† ï ŸjÕ¡d醯4¡ häõU KÒ¿À p…3gš:œOGHä4G¿$‚ÚÎlT—GX;Ù‚šb¨<~Z{!…£¢J+•¥Á°0f[ÞÃ]ÅBÁŽôƒf™ÓBû2À2[»øW§ýÅã[¦âÄ­¡ìo·{u­ÀIV)Ûv*“_É óßܶl÷1¶¤en·y?gÖ=ê2èÃÇã+1“œ-e\wìëÏç-DW,zWÙع·sÁî;¬|ÅUB×ÿàóºàðC—«ßÛ‡ñ:ô?¥Z„àí…”Ͷ4J ïòp× ï#rÚû&ºJúÞGÝ@¹ã˜é1DÓ›sê"4óÛΡmÐæ‘‰ù½SÜÚfHmôXmD”2q´hBŽ^>*t‘ò„gù«œhAÃ[,hx§áwe”v0…¿(€à¢•iX| øa–9(°çúÔz.Ù ìÆáFhò‡—4‚É¡æ(¤Ð…Ï OôyìÉÓp<|zyâÁžÃ{ØLž/÷ÒÀ¶ý ¡úáþE–|¬ÞyÈ $p@Œ&5 e â_Jý>,|>³XS+º4ZãÉËÃcø°±»7Šîü^ä.5Çn’‹k—Z ÈvN¿ó8¿±ÆÖX$aÞñ i¾’ZÉ·në-×éÚsqoÛšãòX Ç”câž›ÿ9§šŠãz[Sé:Ç\OºrÔƒUºÒN`¡ÕÙ:«HˆÀ¶¼4Ñ#¸Yÿ ËVžàв”Ù··Ãˆ‘Ø* Zdà;†ð·'½)ìB¯n#B,‹ÛvO·mÞººí¨fhõÉø÷ðf¤ë0ÔA"äHQîïúvpFˆs¬Ñ]ÐpS*•?k·dË–„®s»9Y»9YW>I*^@WÇ@WײxQñr_ÉZÀÒ2‚«e¿„••ßÙm·Â«{–ågk0ŸLɵdY²ËYœ‚Âw‰KtûÁÚW&­e ¨,Aö%Œ¤ Öf‚Ç¿Nå¸Âýs 9ž¡¢ ÂRµ@ÇØ a;nA(i3qËëòð e  ”Ž€n¢h€ˆïß-`…ÀÕº( º'N VÍ -Jø~›§¡•5»ô5~ŸºQ”ªÒ„°£†W<óT°–†]2Z¾ ¥eçRJßAݸS¦!0‘”í^hîfˆÒù9£ó­DJ.ßEÕxøÃÔj5^»ýϱ>[Óo¾Ö­uZìóFìò¤ÎE+¢8a&?¸ˆ6Ã&[ýF9´¼ôMÒÁ Í>LË‹†XxgÏu4À×À××ÀæÂS‹ã‚Q@œÒébýÃ.OÚ†ÖMôØnœ±¡“­’ÆØnøØn"×gßRNÓÅXfaöUù€ïˆâ²SX–%!IÚÙá•N;unæãJ=3ÁR™E©!V !ëHÄ0iF&½Qò´öB6*ÕX˜cšà ü¢HÄñÅà÷®9ÚÆÇ57Çk…²Q1ñ1ŠãQØ•ñÄ%õØ»<Št)Ǧ´¢¢Ó0*ÂqÆ¢)"9ÅkDÄ’>=yãFC._>¼gÑ’{4ØùKFæýOÖ˜ ǃÉ“¢¾é±=2zñ^—x£¤(.'ä1 )½¸¦°Àø.=´auò…&C;÷à±?~ o8™ ïDaáMkb›y †ýü6ÁM8)Ðíî¦H™P?J6ÃìÎsC ±8—}lB¦³¯÷áDTe›´sZ/JïãU*´ ë*jºcKEÖE•©c-Ú‡ŽÖçV=`)(0‚Ýèú«Õtˆ‹7pÈí ;VßÜšGn×x´ˆ¤jSÔ?¦õ©F_å­‡¹uOhÝS†1 ÅŒðý|Œ¹q;3ÊîH©gÉ *w:# ·EõÔA·ka‹k7g_t?ÉNP[ØUj5Ì.ç»ì¡öôߨÓ%“jâ"{ÏH&r£F|+ 6n´^ÔÎøV¢E}´è¢>N¼¨O\Ôœ‚“­jNy-k3·emþ8˺Yëi#Í{¦‡ æ&èl¶^R$Sš®.¢tú›ZÞD"a÷mÕÒ¾¼ ²ð<e¼}š^5"ŽÂ¦Ör³Q·RÌÍQ %Í(\]Üö ¦Ñ]•™kºš0 œ$Љ7qÍ¥Ù‘¦üñX'4w•Îådòì âï¾n—YO¡xí¨² ).Ççƒú°_´{_Î9ì÷äa‚é¬ú#`·4Óòì‹5µ9®ùèVl¦ « ¦¹Þ´I…J$˜µÏ“!r°g«ÏÞóHOð¿ çä¼4²Je2™F·Ò¦Eõ×™¡»Î¢K`C!LÆûBóCY)o‘£@ïóã²âáI9ä‰áDþyoû’¿Ñ{Þ×°³ñó¼©~ž€„ÃH½6˜ç²^Úמ< ='yY¯ š-Ö©æó!õHu>ÉOß!¦c.…Š×gû À! (èí`X!F5± @@áŽVvì6-@qòy| ̳£^êoACí7 6vÑé4ê=н1+bÄ¡3æÿÜÓO ÇV Æã í9½ê±È$ áæùÕ¹bÉ£(ýQJ{¤{Õ½€ýàŠá‹vóÜøbXú¢ÍÄ4òw † 1èuêh°T•®UA%«ÐïÔ»¨à£$Ä %ÿvq¸Ï×"¯ RÝžœ¢V 7NùR PFBmf u °+Q„ìÆGñˆX˜µÖZÍ36w»~²rÉÀ7…!QaSæ6ÅRÑ4`n°Mô”sm¢§‚䵉žÚDO­[ôÔâSðOŒ–òE)ÖŠ7Dê}ü¨ËZý=Þ"¡‚KÈnàê²< ÿª" ðyà±óêö$ê-€â"ç¾L7*Û¨• ‚ºjåÅʰU!-óœrœ”“C_3N*WÅa )ÜlÒÇ‹„UºaU‚uSy ŒO œ˜ø#“üÇ NL’4$)êð½‹äÏ}+9¹y/-’X´’EÁËC†ÁB2pYÙ¶ X—Ê¡ðè ¡A‘qAò  p:ç°Ñˆ!PvY¤{µ›H# ~<‘G>»½7LÇô÷‚1*Dch°å1W¡!4uÞ–>sõülMq/a±3Áú­ÉYý3¶¬Ãª˜†A:Û âªè?¨ªèèЗ`Ü‹ô(FÌKTÀKT´‹~°K ÔE7Ò…žŸGF¹àž$2Â%$¼E'ºEۤעԈhi+âit£YℲċc‰Ä’$‚E;|%šVùÛ[ôÏýq+¢ÕmD/fE;`eÁhmzºë˜„Ý•ðÈè“÷4¤DUB3œ$f,I¬@ç½’xñ#±‚Gt€Ô Ñ‹‰0+ZDs0šq"ñƒDbùÂÆòð—»÷Wâ¹÷×™j¢ã«ÇQ_ßKßÎÀë ôðƒ¡?ù.oˆ‡ëf£‰h‡ü$þ™)L|Ì  wâß/´tâ8•‡3¤ ŠÅ.½€‡ôJ>bÆýÃJñ„Ëôx‚„èL¢†·fZ7q£mBß5Q/–÷!·h˜J—(,Å ¯Qtå Š±M¢M_UËÔ n‰'ÍÅÈ™ðOýØîïÞˆmßwoLLÇwÃ~§w£¾¾Ã{\o÷ W Ow=7wA÷¸¡©Ä2ޝº–£z JAÏK=‘f#.‚÷,z$ýÇ_7 cÁ‚-–8,aüWÂu“0ò+ÖÂQÅ|Å_9Ù/˜q[‰”¾Éú0)AåCÐÇÙÓóñ: ‚“˜Ä¬¡ÖiÆ)EE%h)iG(ÅOJ›”00)YT’–+vÉÃÄ•>øu w A ÂÉ j’Ä.…·sÝêœÈ¿|‘E+|”Z”Qý ÿôðÏUX Ñ5*©á˜ ‹+Ê9tè¬Y¦‹»NúH–ˆ¯#¬¨ÈïëØP ¬cD÷ö*PF|SïDŽ0 ‰‹5*Éè'Ê·pâ©SAG vxE„›È%­È¥+ºD ±ÇßåDœÁƒv1MÓÕŒi:ÖÛˆB”ô"šŽ‚^ú8vD½‰1:/Ïäk:±= Q[£ Æ™^Ñϵí2m¸þe;XÚŠˆ×öãÖßÄLmb¦<ãÜÄL±˜©«È ©+Œšºú•–]›¸)ß}rTï79aðF½÷+-¿y™“§™È¸ŸúYAñR 82$Ÿ!’Ï~¥5B_éC X!Í8 Þ´‹èñÕx8—‚D‘ M›\M)™u#öإݽÇT};|/\¹´/'¾/V»xÐU䋬ˆV@»4ÃúØï…VDëV$Í@?v)Ãý´ZP¿üŠè²K+<M$Ȯȳt½P/8/ÍX­H.Í×Ñ 5”öÃ’ªCÂ"âÁ¼ñSê(/iˆ—4z*ÒC#¸Ë ¥tœ’†uI#¡"ót…ÓKÌ(\=œ›å_©×•:OŸ·£—Óz„NÙI뎀pNt5@Î,D-þ )T‹;²«-y?ÎwœÀ÷«2‡’è¦äsø>ù4®C¤Rp—>}’(¥Å– æ´©=?Y•1æÙ†1gΘ»ƼöŒ9Í9Ü0f9´2æ´—`:Œ9Ê­>•€ÒXѤ‰BIõÇ£v#q’Føh‚ØQOà¨î;Ø<=¶Žîu£ªTµTõåò¡rIâäb…é$¨ÓÐñ7.ÎÁcð ›`ÈYˆ ¸0Ɖ Œ-×½oõŠË †Ç%˜£¬ æ8K‚Q‡s­Áœ$!] bŽ‘`2Ä¡ëOæáLfœXúH!™F0^t$ž^^¼¼dxI¢ï„ÞEUãÝe¢8E¦·4£-¹ÙFéqýœ¿]´‹Eé1ïßÙN‡×q£ôpÍ祧i¬‰Äýäéùen‘þóótòuøDý¬Ñe2> ÑõŽòEÏ OÜÈ—oDa"¸Ù'^ø›žqíÆ@•6eW°/I¿"î‘JØ›ºˆöë5Iù_IIùzɤüº„EË‘²/a@ªN4ªN¼©~°©ÿ3Œ1ÕáÿŠS‘ÿobGUÕÖ.v4`P «ßHš^ì¨Ì&ëé>´ë…ãF£‡-v»‰ýQâFCb+'¼‘ìø^͆ѡþ^+ã>ãtâ {ÙDOÆÙTŽË«ê)ßpËŠF¸e5ËpKá…rš——·Å…¶”ù¦Ñ©³ÀKøvµ ¼Ü^:WÓûÎ9Oøå÷y™ôEsIÃ0ƒ¡—î+ä«¥ön¹ì#=}·\ª/”;{‘œð¾¸p ÅÞ…¾C_U|ÞÂ>Ãg.3u<(¨‰ïì8P1þÓ‡M@¥™èqbxOëpIeU‘}^¥úÆ7Äù> šíõŒ¡ŒuÄ1º!І!Øðñ‚ÝèÂTÞyfêÆï¹÷1ýÔ™_¹sߎ<—Å©àþ¯yŽã5‚¦•sÛÞƒÞû¸BË>3’[Û ©Ýl³`/º¾ÓôZD“Çß±X·ó@« ç3…²y¢ÖJÒyHü žT„žDEœMÎ#^¸¥ˆ/Q†•DD“œ Ñ$žH•m´Äs­wFá윫ãB€¤ÏÕá ò(óÈ(E<ÞIäK¢šÑoˆ’¾j7P,Æ‹–¢"°Ò{­’òmJ‹¿ìF'Æ5>q^oÒzرΫ¸dïá NÉ6ˆÎCçÎæ¹çx“I„÷rðu2Ÿ!@kDA¥uÞ È  E¨Rä[©´ßG¥ù&*õ‰UT€’î{§4ß8¥Æ”ŽÖ›£4ß Nä{¢âHé¸äj8T³%Ú‚çý-lß:»UVÕþzÞ¹:~¹Ü#w®G$Òy?K4« î+x—ê°#I¥·Pã»Êy|JŸ Å=‰õ݈CO¶BkhúÁpý·rªÆ€¦ßpøøEŸásê£Âüõß13á0Ï´«œÇOû,èŽ0ßïÁ•T^Ó?0èæ©á¨^æ¾|vc¼R*zEª 9 øÈÊ©7†?_”ßž†Ó^ ½îz±}õâ:êEÈô.z)ó%5ud0½<Éí7þ-*W>îyÊÑ€ϯ^ç\®ÛW¤U¤U”c/Ï–0ÜQ4YŽ ¬t“ÑPíØÄR¸¼Óp™ã3r£9#Ķ3£Z[€õ[Ã}Ö;9¡­F;4;:e uz§&á‚ý[Ù}àEçÔLÀu«Ù§eð®'Ü%¯€í¼Ã½«÷5¸ýbî‡ï¸û! ìX[·‘€;žž¿èšyÐU(“<Šï]­ô¯S8×Sç:2™FºÙEøØ‰lüXå@wæ@Ç=å· ‰ùý8ДÃܲBÁÞ±Õd.w:îmž-™«L;?Øx‘}Ï^d<+®Û µNƒÖÎU †…`È­«ó6ÅmEÓ=,ø.åû0;¾ëª%&õÓîËœÅrqáªj¸pü`.\oáõàz{ÙÙ8pm¸œkãÀ%ÎÆ+®¾[@9¼|vCá´¹ê!‰úßÁ?xþŽûi…#Rtàz'MدpΊHÒ‰<.µ"ÉÕ¯Ÿ?ðXLÁ¿q«£ÔC_0y麂殽aH¿ëé3­>˪¿xò|+ÿÄøNêz½L÷‡Þ½a*~leí<ôöý„aêj_°G0]/0µ ˜$Aº2£Cdjô€…PêK´_ÛIÏe®nÂsLLy©Þ}ѩεòœËì›Z Î%&L*Jˆ›  :ʧì''1ôçá'×Nè'§çX¥áU69i¶d…ŸÜQ¤'UÇö£BTp½©¤X»,aW­¢Û Y…€;&«‚Äf³·Ý@¥[qî¤ùÎ)yØéεœµO­vlO­(7­4|´"T‡úhu˜‡V'ì$^Ï?KÇ9KañVºeiùdé8d)ˆÌ­íø¤“¥,¹gTÈÛvC[éxl¾JǨ Hw î ʳ?ù`Û݈饾gЪ\€b$xJË -²³Çó¥Ï8v³Hˆ{‰ÂÁhAÿ*M窘ÙuÜT‰-ã], c¬ü‹šîT_ªw¦ åá±]©bùQé88ÅO°zž/Ír&•ñmÛÁIc9(™M˜€CÈ\H?M ‚ÓòŒŠr‹òø+|¢â:DÅó†R»BUô…»®Tj,DC´ãSr¯§8.O^··ÐbDêì” _œÒ?G?í–LÛëà$õÀŠJáÞóŽîŸäϘOV¤Ï“ßåç_Ô‹)Â[mÎ#½£Þ½ ]-,ñ.´D”ÃÔ;uu»Ç‘*¼#µUÀÇ mç‚“S!Ùa·?èùEÇË ­ö ÜœpóÎqjJ˜<,Ò£)FFc} œtß¡U."­†Óœ§-å<­w3(IÎíKA·}$pKÅ?LÓ9Ìãw¥H]&Y¨O˜Ü! ôs¥³]¡F±ü5• AÜ…æQ;–ºq¿±€ÇØ÷âfçQ3b»-/óš°O÷Û å9 Ù?ËöÉ›„fW´E\Ñìœav®0Áúœyhûœ]Ê|ÍRè@åÓ–oZ² Ÿ¶ÃϧÍtœÚÌWÛÆ«Í¹6^m’á|w^mEbªÈñûÉL&uhÓÍLf§&]ßdn˜¦Lq&òC¸¿¹ôô¸¿™ÜÿÍÌ(ÚÆçmµ}ÞNô¶}vñãà.Ž>^Äç­úû¼UWÁç ÷á?œÓM¸ñz[S¯7š¢q“î{MGý 䇓 x(:Š¡þ‰$ÛœrŽŠ³Ãb¶•¯bt#«“v.«‘l’Ïm’ÏÉÛÓ;ZÕ|mt:Θ$^¶:’A¦6ÜÛIܳOF§ÿ6Î…¦$®Ë&‘LI޳q™Íl¬kÖ<Õ›·ãe§:Ì2k^øÛ¶ã¾j{“N ›ÛÇa[å,Lìb‰ŽË0ã0”2=Þ[•àÕ˜)dÇÛJdÒÁ˜¾¦‘~È$Ò™èy¢F6B´}’‰NjG©g²É}‹ÿÅ|‹›ªx ÉeþÉšÍ0·…‡²68Úiõý”I\ò!1¼•‰™ø[Œ¢¢õêæXŽÒjJÿîÞ}@5“ü²\Få¶Ôòl&qR»É,}ãRZÊž˜ò˜‰ósõûq~>*‡%•Œr~>\¦ó³h òßP—ª7t˜ýI¤¾£KôÆ%zA—hozNqxü®*=ç"®Ò u¼|êÃ(j¦ ò×·{2íÚ™EˆkÚèÕp„¡R‰±®ã¡-MFÎÿiCK÷ä3aS>CÈñç`òôü2·Œ©üüÜùS]çHå"éDxN ~ʬ0îŒt}–ÃC‘fÂa³éÖ„R¯fç°‰‘§ëÌÌk…{)ŸÿÓ†/èsII~Açä]îQ¼Ëýwm_ö…Ý ýöÜAßë¶®@i§ÓT “­åC)~pGYÍ{üь봎Ü:¢Žùc,èSYkž×Þ“ ¢û?ž@w¶Ã¡¬m  mCU›Ü¡ŸáÐ×Ö*:³_ ÷Ë-U§NÜ!„ÌïiûF"¢ MJpÔw«g»{Õêö#~ØFçV̧§·¼®müm;zÕâsñ‘]Ô®êQ+gKbw{»:‡0[›ØÔž!í––7‚Å EÏ7òžÑ©éÜÛóªç›@Ï7’žmÖ\§¢Æ"Ö×gk0·îlûðp ‹™¼ÌpGàmÒ½èMÉWû¡ÿò`Q_à7Âf!yokÅžÃq<È3С+àmóƹßñ>x‡È}/nÙ#1\0GÛ€×ò<óvî|ý…šwŠhÝ÷Nrîæ‚öÆ­D×S*³;¼‰`#tðçFøØì:ÒÎÖEº"ˆí„s¤¶½Q€:ç!7Úž!û‡XI2™MjªK42V5ÑÈ*Š‘ùLIäÌ|,ÀZÄîßéÑšƒÊ-Æþ!`mzÞŠØ]¤ðçÆ(ðÌža/tÔN©—™¢RÈ´ÏÇá,`é@£—gA{_Ó$Ì m[ìÐa€{Ž/"þf謁©³4èO^ð†Ö-µ%OzÃÿøÿÙûöçDr$áýõú¯PÌÞ®±cЇ3Ûwccì<ݾû.&°]n3mƒðôôÞÍÿþ)SR•T%U©ŠâÕcb¦ÁUz¤R©T*J¥øÚ{°42`…Ò.ÏÊn«­Óg;°5ç@p£Ý¼§Ý€¤¨óg=Y‰Â°ØbâýãxüŒ2þ#ˆ§yÞQâ0˜¸d0#ôƒÇ{2¸½}ÏE±¥².‹A]Ó=åÒlrø4ìõ–H£†ÉŸªíTaréŸ5¼ÇljÍ‹9 œbf8‚ Dô–°:ÝÒ<(ªŠ>°AY*sô§[¦þhsiõH»Ùë‘þÊÐ?ÔÊœ­Rk4®ºµ~ÓS] .Dÿi~%6hûÒ|à„GÕ˜.„ö Ú€÷Nµ°Ïuâ7hœ4p8\ëàB¨>¹ê4@ļ>º”Pº˜úÒóuLWFsÁâÞQ sHÏ ›~"6Ÿ(5g—v7Ýq­Ûâ²î©ÝKwn²–öU¯Ü®Ê8ÁŸOu±û¹Â·oP2 ò1V¥ê _¾Á+œÔ(û(ðýØ[¯ ­Ò’¶”ŠÞDýë˦p"âj#ïÎüƒTúºL²¦ß _TLµûÏ ¡uBwTOðànAV°­‡ç­?Åcnußèn ½õ‚B)uµëWx‹¿R-ÊDëMzÆoQÒÊ{vprEÊÚ.6]Xïñ„Ñ(>¥TܰՓ‚æ¸+ø̯Z'gh¾æ‰Æ°žÑÉ>/_‘¦(HÙ:= [àÝ_­¥bð ‘<ÞP´C©†cΆ9Ñ9@À,…ÜtVdÞ@ÈdÌP;ÔØŽ/}llWÍ<¸Ž8€ù@Ž/d¶+:ªÚÙ–œÝ¶DÆyõüÿP¤j4Öñ·€Ãˆ-€Öí‚?x»@ƒNUŽGÅr^/‚‹¦\ªÿ‡ðRæ>%σá5ûÊIÇOÞ«—Ѳé§ÇoÐÂÝp:› o^`Ÿ¸qg_]Ê¢w‹…*ª[è÷÷Ëú5|q›–Õ6P§{NžŸJýCT“î7Ò«ýÜ ¼±‘¤z^¼tßšŸ³ ¤*æÌéêÚÁãð_prTü6˜ ¡/*œ~Îa!I ä¸b¥zà?"ÒŸ§êŸ-9è›Hqßþò!!õa‚z¨ôâŽn] qŒÕFjoÔr ‚ÌÍøet'ѵƒDMO‚–è±xÈÆ(jO,åËùýü<8Êã¹ùÙ Çwäëž—o\ÊG¢¨ÀCmÅR5ªbU[Çñ;kÀ ^¦tD³1¹™¸ƒ/äåY®sóL¿ ŸŸAwêððu#¼*JöIÄ}«!<žøÜÚ9æ ô Û9› ¾…ý¢X,îPn¼?¼S,ößžªoQÛÜýE5¸3I@Ü!¨Î='n¶ýñÄì|]…n 7¼?ˆ¥–ŸI!†&u,Íÿí·NèèÙôZðßµ`‹)ï7‚qXó;x#ƒ†,—X2ÖŽÑ«òqæ¸F©s%½†”zá£xv¥K©¡lŽœ9ÀT FTÀ¤ë¤ãÅ⢃œŒè:º¡þ:¼›=àÖˆcàª:k#ë8»Â©éÍÆ—ÙÏy˼ú€Éú5ñ÷»þcòr;{™€±ýŸ/É{mÐFÑþÎÈ&ϼÔ^F_#åÄ6ug°Ø)-½ðÎô‡µÏ7üÈÿ²ßÏðïl‚ÿÞl‘‹.ýÞü£\¢ÛËÒÜ[q™NÍqñþ*Ú°Á]ÚbÓ¡²ïLo83· €pWÀ•Ò÷@¹ˆJ##Ñ5ŒkÕ;_³U'ñþ‡pÆ1vWÜ à2Ç)ÜaÞIà•$ŸÈ[''Ì€þvfÆÄû&EVûâ#Ä|ö®ÏÑÑf¯:­~>|v7_¥ói àN­¹Ù ÞÎ'…ªŽçp»˜šÂ0fã¡C[=Gº$E:S.•E‡îýƒxßGãKèýL¼ÊŒ´v¨°¡aaýNALá¶×2t3ha Wÿ6|ïnaèæˆ¿}š4&ŠÂSò2 Ü"ÕD®‡`nàÝ i|Ž#áÏßãsÍ‘Z«½8A™ Ãú jáŸgW¬qÝF 5Þ‹ °b6tkpù÷M ïÔ“/•UVã} ÷rC·ÃhÆÙ¥Ã©B(ä´à[¨ßIoU‡÷*hÙ6}3JüSÿ‘£SÈ#Uæ–ÁÀgˆ§yc™á¼ÛšŒoÞèŒù¿ßJ[8¯ŠËÊ\——/iLÉ(¶)Êp¾ÜzðÛ « º9ÂBÏiR*Ê·óàì°«BÞò X Q±ÏpÂȪØê×̪TsGžÀ@…R˜RqTƒS@tØ;ÊG øn7¬àD h¨÷ãPæœbÜŽr Û¿åz¿¥¨ÛØP2μ紼>ç4çh ‚ËTÉ<[åè‡/Í'¡+óMÓEÏ ¸›‰¿é©A3}N9c…··šM –kÄuúi³×*щžíéTë± qÝ».DÌ’A]oØwì•øx¹U´?~™ûaJ&Út„RÈ“\Óq-'ÂÇŒøWéÅ™,†áÙEb¶m1l^énãÏaßcçªmýDã¹øëðʼ ¬L-c…hŸ4+óì üÛ:bæT‹®IÀ¡PIÏm×ñ™­Äæ•×®2»•ŒCKÁrذK¶X[äÚöw'oÜk K¾’Å’×îìJ7Õù–¼Øϼµ_ír?›µ½ÿǯ}J7‹_ü–‹ÿ9°øŸC‹Tªêpi´6À2íÆ‘2~iøÒ¼ IÍAL´©ÑÇ;ÍaCß‘¬f 6>9éÛQc¢'‡ŽNüsô⟌wƒ=ôóªÿ/+û4êíZoTÓÃÑç½Û_no³rá>Ë>ŠÅâ~¥Bàû`¿‹%öw±X.–ÊT~)WöK•êAÙ!E§Z98ø )f „éó2 &”__‡nD9Zì> +8˜"ñ¾7äÃh𒮀níœ5ô˾§›b®‹JHÉÉleÙ†ÆcQì¬w“áo.ÞK4 ÓðkFÀýðÑ-`…ûá„–tÊdâÞŽ'wShˆ‡MB!t§›¸ƒ;»ò8œÎvï†æ‚7=¿Ì˜}÷¬äV5±Åñäi0£ɶKd»@j#2Æ $½#îïpøÀ»ÚRhḌ`<ã›Ù@˜¯îÜGwæ5ã(ÃU\“Á-ZRî'ã'x‡mŒÇ_¡p©D1r§?Âã-†øB¯S»džÀ•N.N <ý²÷á¢O.®ú—W}rÒj£Î}×!rSó-W„$ס¿® ½uB ‰Qß~âÍ£ðŠlƒÞ¿b~q¢ÚPí,ÍZã}߸èâšéõ/.!àb¯¯˜7¥‘ˆ ûÍœ«!d˜UðŒE¯‹ÁÞ=¯^tAÔÏ»ÅÃ’÷°~ÑÇt Î~ñrvKÃEû"‘¯×~Ð9”Üm7>r±J~¡CG‘ö^¢“^¥”Ç>e«¶Øý´xLfôÿm’s¼_ÅÂA~·X8ÚuáÕ³ëãWM½8…r~×)8á^D5Ø!¦¿Ü~vŸž`‘(1&¾ÃP]`·À±Ùa“Ç«<$¯2ý–¸Êl’¢Ê4ùX&_%qÚKéKâ^,« ±Ýuôä“ãñè3(mÉiþ—VcÿÏû{*Ö‘^ÍõOOƒ ^Ýææ&}Ç;±- À¢Õ¦Œ,ŸÝÚ|ïå†ï’ƒEß½}A9wŸÆàT÷òD:ãÂá!ÉuÝ߆Sˆru¨´v> ¼”²ïáíàP#™&¤w;D¯¥ã!«““äx4r9í`6ž|Ë“£ƒbQh°Ç/³ÒL§¤F7«׫JEe¸%{<œ’ýb¥|”§¬Tk°?Ü=¡#|L¾ÅÞó„:Ü~ñ° çDwD8-Ýì6)²'_ÝÇG£YÿåÉ ò(ŽÇž‡§)y?¿<“öìNÔêÁìO›EµhÏ=¶&H)]kï`"‘*+HíGåvêô®ê½ÈÖ Ä Ey,Äc!âf–Ù-Ù<§ftSn+0ãÆ·ðëQî­Ú¯F6Ò:IÖØw½×,Ö”‹Zàr(jÂo c~ÄÕ ‰áèŠìѽ íû/A\Ü”Dš¸è¤píÚµÍu màœ}‘Že¾êñw, £¹‹~¯ƒiðû¤»r:Óõ 5îgU—SrÐ…]7ÊÒûË^ÿ‰³Âùèê^‚¶Øün"y¨ÈRg®X¯º¥³˜´Y1˜¯Ȱg®Úh«†Ú²Éi÷;î(ÉéæÌ_'—Ó¥jo;†Bz~A¢üW4 £·a8^¦Dw ÖÅügšîí’ŸÁm?f>;c ÐÎÊì«Â¾ªí|ž4hÂm&蔕mþ³6²‹³ˆ £ã>—|ãçN’–ÇN#ªa½`ÇIRª1*ÛÛ’à)Kû[«gK–ñ¥Š(À+OíB™\ªˆ·í ‚‚6©â¼Ôj€xP¦âGpîȈŠM(/¿Œ†3‘Ô)ÓÑàyú0¦âòËŒŠ®\Í*Âg*¦¡fÄkž®Íã®X`ôÞ·ç…ÊëÞK Xú†w¸'‚§PhK©T5íÅe³ãår€cÿ;¶«xLGÄ øãDåÇã´ pa?ªfàþ€¯ÃÑœ¸2Ç5 |Øq½×Ai _èâÄr´Æö=™³þT;ßÈý`øø2‰ì”míæ¦a,·èôüõÁ¥¯&üÖÈÍÀB>!vÀEW_÷.ª'&$éi2þºû4ø•ö†ª³ÇÁ7J8Öýqy'ÐßìaâÒÙx¼óÃð1¨þð&ˆ¨0M!v ß[ïNògqf]ÄEûÒÑïg/º¤EÏRÖA¼PþU–födñ㻨ÍTNÅ{„Y¿4Y.i#$t°åDDL?Kü,‰òå ¾Ka "šKD}¼-Fä?ñrZ^Ð@ÏSe<š!‘€gZàJ Jä¤ÚiñµxúbRà€ž‹…¶s‚}n‰ÃÅ\ó²ŽÉÓ‚ù•CÃT/u ²îIÜ8Jú§?JøFÉEVÛQB—[óVºA¢Ä¬ ²îG1ï*?ŠË[™RêãU°‘ï+6Äo¼öÕk1);²ýOÛïa%¸ýY4f¼”E9âš“ŽGŒÙkèC²OÆíÁ[Ú8û²X4L/8p;2;ó3qúܧcݧ®i'ªéb°éDP#'pGA}HˆÃ…#%ÂÍ6lØ¢‡·Þ–Í+Š}›þóM#¨>肆%eñÎ{ÌYšåÀ­xF€/Pr=Ìæ°_ä·3÷…BÃï»bêmëX ð.N”¦ë=ª".Üê¶h^ LDð³ZT‡¬ë] b&o´/(¹0í¢ÏúÄ Wp»SŽ%‰¼}€ˆ¬g*$¢‚x[2Å_öÐÛ€ií±çˆ§ˆ º·LeÅ.Œ4…n¨’cÙý@Ó·ã_t%‡Ö‡/#buà_ì.±‡dŠxƒ—ÒÃ<7ÃÇáìsA ÇfnuÜ2s¬tœŽTåR^Õ^pÏHmÌÄ‘!)葼 ôyk‰„yÂפ֙‚×=å0¼å©8NÕ׎÷ú4øºáeØðùú@7Ü 3<&Pñ6wrè·„ ìœBRg:åÙŽç×Dß–ß0—Ì€XÕh¶Yt#C<¿a\ŒðÁ¬Ål~}VšWVÒü U£ùËÊsö ñ•kåGuåO¤qîÝ“ìiQ›ÊRܲŒu-ª94«¸‡Ä\ýÆtà ñgƒ]žÜhèaE —*raðìRx³m î„·|Ì>Eå2Úžtkœ…TvÛrLåëëRˆÏ­H`ñÝxEô"Í™ÃëUÇ,4¹gtLC.æ„o2:è£&YÔ5³ Í„xŸ.Rã/òÆë"]äߢ}€éŒ¸T\“¤nŒýWò¢ü\dæ@­ wÖóF*DOlI„NîHØõýàn€ÑX¯}‹B‰ÈÛÒóºñ+…\~™nž©^•*2L I¾R…¼Ú0ûð¼·åÆ/ßyOÂ@°x*I@1,(å>¦ ÕËš~.Î4g:"å`TμìÃäè¸àçÁ)^ü³ïýsÀÿѲcçÞR|Cã}óüœJ¬tëûùà •Cƒ‡SÃΜ\½|2=€X£LåmYf¶h±´™µ›Û¼Ñ .ÙÂëéåù% uÿšC ªÓ×p­½–Û°ëèy|©¨§ùà«ûŠ/†/'_üºž£¢†"?0Šóhï–‘8«Éˆ³ôç@vfÄù'ÁלÄÙï"E‚µ¾ßíÁÏ*ç~2â,/Ù•¦Vl0Ì…4ÑÆ¿ý[f¤÷]`cn®×=£Ô´\ a$#¬ÊŸcgFz|ÍOœ% ÉCFøûÉó0yV×Ý>nƒHü¸Ö÷½ $½ñB ñsÁ¢#LÏ–›±¿ÖëϪ¾W6oŽ›^JáKÜõ TM „Õkzk†ƒvu–î¹äÞ³Ñ7¾{¤x¾æžî”;o˜%ÓOú(GŠ`?”ˆù¿1;de„lÒsõ1dW`FK/I„¶$…PkýJ·ÆJ\ü¶Ç&Õ¦àlÉM<+E(±(f©à96ƒ™"h'Í6­üs“œ×ànÉËn³ÑêÁ}ær¤3[oÒœKº  ¥ Õ!a.IŠr%Y†÷(¾ï6k}Ì[ª‚Š%0% gúôb¸:j‹E¹ÅP UF†2ã MÕ(ÇæÏÍ6„³´k=ÈÖ±·…åN‚0^´Û[÷’ß<òÇebõ&Æày G+JÂQŒÕQ í먵Oy>½Ò,;TZæ Çòú¹>½ŸØòLÅ#'ðôZÆüB´ìH-S„Ð%…ô>…´›V§Açs¬vkפ×ú/ŠªVGÄ£º•ƲéªÕé"½è4ƒI`¥ÅÕ»ª‹èVŒ©Ä„¨¥<¥Ê‹>†0¾ïÐ^Õ|´ýàÄFvw(-K·H‡ÀLx» ßÚmÃÒ9¦ýQHޝœƒÔ›@)M PŠ\Èßò±{Ñyß¾.0ÐX{˜Ã—î‡ðòåú¦V(µï±¤¯ÆÐ26ŒL§­p-0}Û†ù× 4[<̱S*@êWQÿ]jçtÚ(YÓÕGÁI 3äÒáÃò$¬©Q&ÿ.ŠV¦^¬3J ÝBûlëÓÃzØ÷3ÛÀĶùâ>à)÷œ?çšâן†Ž¶aþ™¼j'à0Ð¥® y‚;ygƒyކO/O<ÎgxO¦ñ“j>‡Zï4×]Óçë ó×T‚ÁwJäËð™Eú@wà-áŽÆ/Ÿ4=‹^Þ›zKTÊñXß;ªÂ8¸tÁ-ØJsŽ¿d ÏaõÌ„cú9óÑ|¦Î×\¨Ö¨±6ÊÁ÷DòÕj{-ú#–×ÝN|ðÔé5žV݃î=hl…¡ ž:ŒV¸Õú?Ó¿ÃŽCã'Æ«Esº*¢9]W÷öad[KA¶ìuÁ¹Ø€úÚLÃr ðo’9„öô¬ök¤jö ¸ˆ+ Õ8H;š'Ô+uÅ÷̳¥\)hI„{©ajžÖ„ˆÎkl·¥†1Ë øá›=wz×õʯ„nÔÍ+„HNu|‘ÔÄ*ºEÂK×Å:©×I=j©Ô£– ýœCæ×a1™×Œh×PQ´kèÖ¸xˆX?õÔ뇬N—PÝŒ7Z"nyíÀ¿ú…DR¬% €˜åDÔx xuÞJu‹Šè×U]¿®HÌÒª3éYx~‚$fUÂd÷øÕE¼ÛÝk~𜑴˜¶ø¹«™Û$^Z÷ºZg,J?¨-~ÇCòê’KûÑ!·aD.ûD¢O+8eT°Å?Y¡™}PìpQ'jˆ˜—ÐýÍ|ƒÀºþnÜ{X“Tâ~ä7FU÷ý]cÐÂŽNžÌW´î5,rö9ï™wvöéô"™#ýœõ"Ùrì!1úáÅÚš|ºY–0Ý c×#—ðîF|´·>p˜f›p ”~å01PÖ=(Aá¡,ÍeAÙsQ.…:›Æâ'Ñ 2vÌXÞX@ÇÓ äÐH5–K#z‘5èbbwJØ.­ÕXß6ò›Ën£ã䘎Ô\¹ÎÔ…qœ&èûÎØÔY^è‘,ä+ܘª‰bà ùCÃ{2âFÆoõ”n‰@*rbÀú!Ù2\ä^âÁz«©lÛ`¸à¬;nŸaÑT¾@÷ø]Œ®û:˜’Ùà‹;"ÃÑíx…<~³  ¸8‹‘ÙÇ(SÏsm{½‡?üD\29ì¨Ð~z®K¾âµ) W¹¥Bãg¼Qw:¼“WÖ4I\­†ŒÀ?°² Ê¢bɯXë6Ë,ª´•"÷,^¾Â½°|äLòòU,†å#÷3^~Ÿm>m¬»»ñJ,ÜBqЋ­†[]4Å𪇬*Ý¥ Ã˜mŠ×9ò»«s§%ŠmºÃÔŠ¸Ñðþ"7Q‰‘E!%nÿÁ 6@…c³ØD%HhXlàÖ=¤Èsš¾õ.xŸI(—={Ö\?>‹‚N›åB]™OIƒOI̾ٺgkx¡ÄÅÚÏ“ ^Õ\}0qÕ@,퇻ij4õ*ÐÀÆL» ìꎿžÃõ·¦>å²ñ£Z6|Ý_ðžËmJ´l½h¨C[¥²m±ç¿±asð£ÂYNøW0VÄ)Ò6d–GòlG@nUÙú9žXáÆ¿ µBÌN QËu0þÏàx—- êïZxuAuAuA'¯.èüó]¸ ÷àŸ+ßý¼¦á^nƘ…ß¹äVnnGø›ÇøšÓóó)øŸÀú ú›Gº0ZÇ¿‡þKû¸ºl_°{¡^¶ÁVã¢äÃÕŸÁÕüCÈÕV lv¯.ç \Î{{[íîÖ£›½­«¶•û¹²s*®|Ë‘ÃÁVÇÒU»¾K£ç¡.2©Ïå¡^Lç¡~ôê tP?šÓ?=„¥4þœÜS„ó¦Ùg31–"<4õXòý1æ$+/ÌxÏ@ÙõRö¬4îBZW@áëßc$_z¨» ó`¨FïG,2ìÀžë›–ÆeÝÖ8*#¡œÉ¨÷Ö7˜³±p¨½/ñ\^øÌ¾²íÛøßG:ß'ó¶q»7ùÜîo…3û•èÄ FW@W?bq½£’BÞîäi8RdCj¨oOôÀDWö>ýʆ!„\€s¿YøÂçœeåÜoå{líxœÀë8Ëqbc{gcÃ5¼áO"Oc;7ãy|Œí<&QPæÌÊXhZ¾…b<Šc܉m<…“¸ ÛûǺoXx'q ¶÷ ¶€,Ö#ØÂ8‰/°½#°ð.À ým}{pÉèúí°ÊŽ™Œ3~ÒGÖ÷Í,$r4ñþ¾6ξО:b=ÄElŠOph°Vü³3p"ßœxWº8/?>*8ånÒ¨â\{3ñ~NäúœÊïÙÞ•{{8fŸ¡Xœdáë¬8:ã‰ù‘¢¶HÅÅ÷K¨¹a&rnNäÙ¬¸5[¹)+ŽÍ |”Ußf eÕ£ÙÞ;Yõj¶ðLV}™mÜ’í}’U—çÉq|*Ôp¾ÈÖ|&¨RdKÿãHÏÄxçc;ÏãdnÇé|ŽÓ8§ð6Žªú/„3ÇÂfë[œÐ±8V¥¢´-ù c~Xü‡-¯s?Š)‰Ï¿Îý8qÈ*€¦ñ?F3O‚6; ÇÇID¢Ì—mBŸ½¿‰`CQ¼‘Ò¥{^n gn{Oîd ?ìÃéÀmöÞ6¸nëü¶CNÛ¯ÚËwÐ.Ãþñ¬@Bí’Ù·1òÌ&ã€;#1y¿zf¿zfÿÉ=³ ‹¥8bË.Ù`w(ÉžØ*°‰¼²eWlµ£[6¼]‘kvÉÎ5; û2í¼údgåíÃ.aíŒÝË7®x o&9ÉLt ý0sGf.¿m÷~fr öË2Oâá燙Ñ‚}^…ú¼RÛ¹z~vîȲíñWW¾.ÐÒœD:@/ßûYa3ÈtU/f…¯xÌ9äû¬©;±ûsyIîÏâDÄ}›íÈ>Ï"÷’Þ¥Rt1—fÈÐõêÒœ½K3¦~åElýš±>s6Ó×ùÕË9¹—óŽÍkçAE.ÉÂ#¹qì¹$÷~ɧ’k²Sz¯äsí ×QŽQ®ÈI[5Êáß^^uH–ïÁ†7”Í@Å{.#ú<ÿå`IùíþŸÀ»9àÕÌ’S6pß{õn¶ônöš‘¨úürmü㘾èðßÜ:Í¥ÛŽxØ¥‚#ݰÿåNÆÂ× dœvo\è‘sÊ>Š Lq#R_ä¼”7¢­Kl¹Žªg$诣ª"y»•”7—çr´þ.]ˆáÎ`ɇXÁó´>÷<­;†›ÀAõ·ßÞ@‰WÏÞT òì Ò±píÅ›úÓùö†ËЏŠFŸÄ^|Ío‡GÖFÿG¬å! qc3˜¼ 0X»ÇÐîñX)æÊßCË›„‰Þ§wÇ\<ÁEåÞGqÃM¶„~ŒIP¾[³YDR?êÕæ!o܄Л¯ƒÖ@—`  |a3o,¶ò)&–nÅ$Ñ È(sÓ’ðU.‹ëí/7.Ï{¹ñ|WíZ^n\™÷rãy.È“\™p!0œpŠ?¢oîÜOO[v·OZ_(Ld;f9GR^*LTïbqTd,QÖÆÆ·#Ôµ6÷%ZÝ,L¬/&ž×-œÂr:#™-o$DƒÛ4ò‡3Ùx‡#íL_iGãi§—ídB:v”cq#óŸáÞêêZÞ[mçÎí×JâÑí×*{W]3—èxÉEqðF1êÅÉ1Ч·ýÙû /È>HsáõaRgr¿ê‘µ?9Iy—t1ÅõØöwI£ý·ë ï’NÂv, sBNôYÜ%m땘Ù]ÒÕ ¾KZ{×-Y§»¤-¹· œö‹3VT»‹š¤¸ŽZôlí;κÑ\b­ø'ZáÄ|uÒv¸E:puâV|B/Pc'ÃÏÃÑà1¾ ¦±³ZëìŠa²¢4~ «)`ÉÙ”ÄÔ$oIŽþ½ ¢èNâ¹$$^?á.±ºÐY% .Fu—°>ò&vY8dC‹ø$gÑÙóhðÙ‘XtŠHöaü¡¾nüá„JøëΣÙ42bÑ›<V<ÚªÐ÷™yÂ^‚=ŒÏƒFM…%2+k™‰fßõ± õèj4TæGSÔë\ô{‰üb$nXÇ ûòÞ“[&R HË–í¼*›™åÂXßä¢{&’\tÏ^#ÂÖ;É*<âÿX8“½¦½Ø”€°×´ZÃi/š}» 3J;¼v«wYý®Ô@\N /öìÌ‹=;¥ öôS?EÙëYŒ»zH Eó²b´iç5‹fn'QZŒP,oAÔ½ôÖš&;Ê\\ß}û<ý?SžŒî™.OFW ÓJIÖ Tÿ ¨H–’ôŸ)¬LÄ’5–’4C¨~çNš¡Ê2Ed¥Ì{ÁòW(ÊÙ¨Œ†t¶6щ.¸Ú³()Ïåáü g¦°µ3IgÆT }C r&]ÐŒ¦œˆ @rhh²à=ºý C » YÊE¯ô@jjÅh~<‡cè™æ…!„KoA;×­„š_X Øùæ‚ŦxÀa§ÝH¸`åKÓ3Gê ]I*pÇU®Ê8¿ƒ¶˜åEã]Ñì‚9Þ¸Ùæ)Jãþ™ó¥=ŽImhµy²P˜ Ú_²Þåm²Ñã‘_^\ Ÿ‹·Q£'±¦_%A‘Ř¢[´E¿ 7G£g^8.›- Á¨&ø‡ Y5ŽêáÑvaÙ?"²ª°Ë–íLú^®å± ˆ²Š¹cDZ­ša‘;ë6DöI°\X¤]7Úñ<Î%Å&\/fͬo’d¼±yz2y#ÑmÄ"³4WÚ‘´9S“vÄûöa¾ãÀ~êh0Éî•çY¬»²¿k“°BºvÐ8$«ø/Ëà//I÷ÌÏÕ‰S&ÄpM´uV'BæÌ=’fÊ+YN¹<ã¡›$ /`JAy’Å”†ò¯ˆ ý^ò©”2ΧRZ§|*‰’£”¼8ºžGW©œ$I ¸;ÃÂY+JD^—‡ÌÍ)º$Ïçb—Òc é^’â ¢‚ˆ›KJQÚMÎ#³$Ns´  1GJ€¡ö“Àµº“÷¡Ë"SLqs3Å”7/SLºô{‹Îc³çÄ–6S ¹?¾<ÈÍ7þË"ŒÞŽM~:†9Ðèš•aÆÇHøM…ÎJS±nü§ Gp¢J°^,Þ!L…hmsz×?û´¡ÜiL9»è’S›¦D—²KÇþ6D«€‰X[@àŠCêó8$° ;ID_öp*S4l§ ‚áÕ½ÚÉÒò‘åÐF.5’&õ”€·çÈÞCÒÅ:ÚQš>ˆ©ŸÁüòœôó§ÔþSΟírMÆÌ€™ž‚RÖÏš`„ÀŽWÉ-fņ¾Ó¸-f¼O}™Øk:ª×¨-¸ÔŽ p`Uvd’ÔKØôÀ}jÊeý¥•+UÍ®)Ú¬»õ¡Fí×$¤Ó“fJU)&èKÛU¸'­AÌâkÚkÚw6Gb-ôE1Ñk’Z·Épßì]µ)1œ J?l9–MZ..!FHQÁüZÒGÀ/ˆ­¼¤bD_WHm&œ7,xi©Ñw»è»Š9úÎ*îÎÂàcwÇZáÞÌód “a—±Ž¸Ãh;^ÄÛX_£Þ’D½­Oš ëðÔ¢Ð"hÚ2­,‡”Åç E™áO’±eÅç§#^®1}öÂPš‰ ì¯/Eb¼²W6ð}²eu%¢ìM«ëhZ—"MMa¦äcòHÓ’jZz5ÝÔ샯A¨Ù¡†bNë9RÚ±‹Ý”ãS5a¨uÛÐȨÓPp©¹`ÔiTpiD36;5Ó ÓÓÓZTÒC“ê§GÔÄŸŠTˆæFŒ1ª¯¡¨kŠZÒÇ¢–æF…I|ÿ“º„˜TÐ5WLª9Qà÷“Z¶ŠIÅ4©ƒRY†¸×¨TM+¯Q©I¢RgAa©±Sn·JÅ&tá©Ï,$#Ú%ôtc ‰}- FÑá0¸³Ûf÷ NCtƳ†c¾2šŽåLoÑ™'føbÖ ™ƒøÐ¯gk˜˜\nX"°  ^JÍeÇ@¥‹6G¾F/%º8Ipñkl±îó=ÆÛÄú®o0¯‹S›ˆ3md¬—‚ÓTd3ÃŒËs…§ ¯Ø¼0ãƒEÅœ‚8'Ó­4.õ+Y¦†#S=i(™o¶E$֢ޫ+¤€U&/𨸲$€?k0sDZ×`f»`æÄáÄË‹¥µËÎÈêg¶4VH˜ÌƒZ³Læ®$4Y¤Í<6Ùo˜e?}ý‚ˆIæ±ÆÖŒ0» äÒæ%W6/(Y¾³ò d›½#¶× dÞT|Pòi­l¸lŸ¯ñ5p9ê“4pYɲl(äÏGOS‚I&A‹ì' ,%ÌzɵϠOÔÌ>‰V 5ïÿ`÷n¥L•¨“Ì7nþá÷ºuRFpâ| þg%ãôHÝ”F›}l’ió’1ú¥„!Þ,Oh=ÇXà¶ol‹p Ô~²=*²¬z¼Lã5óëe¯—i¬áe‰ÓAî§0]»±ô‹5Œpç €›¢Ûè—{»FÕîvjæaõzFž4¶¾þzÏÆk€ýثԽÌË6|Æä­EÁ |^e¬—æÊƒÍå ž€P}å^K¯ãOÈ1ÃA®‘þÎôèï__6G8nÕ pl( wÒ7*oØÚBœAS7ÅÛ/#rÎ9ŒÂ4Oh ð+à…‡#ükÀî!¨‰¿ïX ìäåvö2'„¾ '.ê§h«è—ÀÜÝòäëpö@^F_£™{GÜGè:ug­7~áñ;* d8±Cèá³5ý¶E(Ø[³ÉÖë5p͇¦ŸîÅû«È>°6¸K[l:´Qös}HìÅ!Êe!ævâî ¸l®Ñ ‚-PÓ®Íc"Ùâ—ôÒšwd¦}˜p."¹j®;€å6gÒû‘ñ~Çân ÃÅõ&…´Eù#»ªâÔ<æ÷MŠ– Ì´/>ÂWïúÄ ÚÊU§ÕwCxpDݾ UƒB"¸µæÂxë5=ßµê1×ÐQƒ/,"(oä/>`¢÷âÁ{AÑ"¿ ”¿ `É/fÞ^.bsÐ(ÀÑ&à *°Ð69ÚQLÐGÛ:m¯:Mè¬ÜÂ@¥~%Cˆ‡ e¬|òã,)ì¹¥„^©ñù ù¥xd~8XæÆ§Z|ŽâÏßãs™Dgƒà-´ ‚Ýœ’IŽß¿°MÞª ^§Uè`'Ìå?×>?¹þ¾I÷̹“q°-"iÑËþ)zuï•LV^‰…[ümd‰To¯a9’‹Ä9¤Oˆ½£ÚCгkÏ0\½OóÔ䍿%¯„‡9÷ N"<$–%)ö^lkÂc½Ñó¿•vr^—›¹./_ÒÅPôIÏ_†=ømA œá$æœ)æ ¨õÃT‚ìÎC«c&ßJ~bpCˆhÊ!ë`  î}Ææ¼.‚ÒÜ‘'7TtTuâ­Ä·‘mJìZù›ri ÎŽ 8‹1áÃn«óLõ©Å°Ž`ƒ«9` ´Nô–}QÅfYiZˆ‰EëÆj‰W±É€Ú·¦¨â-†]hdAEûq¤zÀzñE¦”kâ ®£CÞ vŽeÎh¡ 7jaÞÌÁæu0œê¸ªxL•ÉîÛ†Y<Ò®Ry’=)cÂB'wÕBÀ~)§{ðgâ:>& Ô…xæ+9¼°¾˜˜FîˆÄ‡<¿Kü[ö&âBÆv˜Êåüg¡'À‚©S0…Ÿ·ã§g*šò“/ÞgózÏþžðü{&Îã•™–'ã¼t¿fêsmØœdºwnUcj΃gAµ m~$¦„k>r·¸óŸÍÇbu)¦>ü"ˆxö­ç¨;üŽKy'ö~K6¨q™åNÌ•6§kݶ1Ýn+ò\~ê;>ë.i 3‚ï:C(Çk=ý)¹a™µÖ9è.‚7ÒÓþvûyŠ£²®mÍ€iÛNTmrçÞGÃ@CP+GÉöP¸ƒm0ødn|† ‹‡Ö{Ä™Ýv‚ö4¶¤ÂuQ¸,\W 74M«/M5üówY>•ývoAo˶„c(¥ö3Jà‹•Ö¯Hç¤=Ñd‡ š;ºua1ñ/ú«rÙ)k7ã—Ñ´€\=ôäæQë=²1ŠZÀ|Kùr~?Žò¨²x¦Ô6¾#_‡´1ʰ¢¨ÀCmÅR5ªbU[Çñ;kÀ ^¦tD³1¹™¸ƒ/„R¼Tçæ™~>?ƒ+ƒÃÇyñýö%ßfÀ}Ë»¦Šïý­sáZƒNŒ;çbW÷°1‹ÅÊö÷¼H.ì¿=UßbÈ@”JÕÐ5Dà·îÕ¹çÄÍöYî-É.«B7Іs1‡Kù™ä¤õ„¤Mêx=:áxŒ¾wÜ:¡Cø”'ׂѿòßôüWãᨵf[8”>ѹ¾Žœ^,©Îï_àÓ¨·k½=˜-:ª½Û_îJ·_ÜÂí_2üа_©ø>ØßÇïb‰ýÍ«ÄqÊ•ýå˜e‡je¿úRÌÓç…nL ʯ/C7¢-vñž †xßòùëptûørç’LgwÃqáá?ÞÈè–ûYyöÃ-D‘~>úhž¿Ò=ž=Éó_îd"~G÷㟰]I_~ùÝÐÇï@ˆýéÍí](;¬°“ŸÞÐ~îïÜ{rrpðKƒ¾}óÛxx‡±Š9ñŸM'£8´a¡ß «íŸÞüÕ}œº¡Š¬/SÑÝðþ «CW­’ƒßÛäa¹“HìFª–—Æ,¿ ö©{’ó[%ïÞaf‘ÿåkø™NÎì>÷S<·Úíæ{ÊM~®µ¯šäâ$|MÓßîHç¢OŽé3TׯÉߦLÑüÿF?È0‹ßÈöO¼;1PØ¥>üã÷˜ÁGÁûéÍo|L3nÂ1­1è9êïÑ%žÓaa“wãàuµÿ.ý}÷¿àØLÿÿ#/]g@>E½¼Žz‰´wè- ö1øœž0ä  –w/ôf“ÏÑó)&T"€m²·ƒ¹ô@€™Ò“žŠ0ªÊ=¨ò¿ úéúPú]äøÁ›,™Ìý÷ëmóô§gV!› e^ù5cþ (gÝ>=çÈô>Ï×ÿÝg÷é·ò޳ýî]q;7Îñ;¢U € RŸbÉ\«ƒ×?å•;:ò¤ˆÿç„Hôüþ ÿeQ×yXA^l]ok)ý¤Ì-}‚¢¸<åb z€Ð.¾rjøT$ÊÐ.ÔJF %hêAF –‰Ï£ìðid1Nú”Á*/ê ´[æ(ˆhš eW·ô-Á[ƒ•Ÿ Ò•,ü´––¸îÓ¸Ôe¿X cW=ýã³àrc/¸Ü˜+vw'άƒPs+Ô¬ƒh£ÒÌà °¥€ pqY;H5;€‹KÙHö3¸‚yµ2š%†EâÖIÀº,`]ìö’áRKËL»LV»ð&VŠ\YRäÚ°ÚTð®Ó¦…wUŒ6¼+ä³sàwÙlvP—Íe—j¢üô›µ(Eçå¡~@”Ç‹W/¿#dòûJÅvp2òÍ0ì$É8(wÈ?̾ò†«cn&vùàéÅ®UJ[:ØV»BR¹Ì’¼¥®…Á—ņi¯ûšÎ©ûš†u_þhW¾gÆë¼V»mšN´A¦°j-W kcijÔY±zÈÄ•ð2ƒqq{}¼Še¥Û½éµÊ•Îu1ÒYÀ¹ÌuÂUè21 åÙ^DyžSDyN{¦_¬pò<Ç~±b‰²äg•Åîó1 Zà/Õ:+. ºÅmœÏs’ºej[!Õ¥€pyD·à2`볉5[Ç¢s°u¨¯gëøÛÓWkFÍ Œ®FÃbÆßÙ2eñ¢‰Å/J;v¯ƒÒváÍ£Ý4ÆXdÊ,.1Œvžsè"Óƒ81¸v[hÆà–Rjw`ÎP™2ÝY}85;ëJV»%«\ì)@\öZ_ˆ‹[ꋇ6›•¾x8mzœ8c¯HŸÍ©HŸéɇ½@‰&J£¾@-…[Õú¢À´”kbÀLÄë(ÚÌ ¦ß¥ØÎÖŸ1ÄÅy˜´õ?{ˆ°Zj8²vqbY”¥`U,ËÎs¬P®€a-Ê…ò«Åœ1»Z Àq«¥Àš…hio™Íi™ ©$êì…Ê(KÈ¢A´'ç0‰Ì  ¥ `ÒCsö"会ÌÙ‹bÙÂêa4[¹&ʳüUc áÊM ø–ºfß‚–ÌâA]1±f¨©½j:§jºþf¨éF˜¡ÂPÎÃ-c†Š†1)ÇXŒjNÍ\c1f¨LÁ]¤*S@h†šf,,Ä r•‹=ˆË^ë‹qqK}ñÐ.Ð •)œ™˜¡ìÅ™›9Å™›ìÄ™Eš¡2•hi†ÊP¨Y¤*C¹f‘f¨Åˆ6‹4Ce-4,Þ •5Ä 5Ce ìÍP™Še 4Ce(™-Ð •¡p¶@3Ôb䳚¡²}n†ÊàE𡲆53”½hù<§hùœ©¦lf¨¬Õd 0Ce«#[€*[ÙÌP ÓŽ-À µSöf¨¬ÕMÙ›¡²Õ5eo†ÊVÑ”½jaZ¦ìÍP Pݤß\?»º·­îΟÌu-…((ѲÈ.ÖuíÉ5ÙÞ)Kë›6̹A°½ ?‚"u΂å¥Z”ñStn·GXtÎF^LÔ¹åù[Ó{i!Ô§½nzÇš5ñÙA°HÚ³†`¤—®ïŒ(ϺóRR¤Ç^<8)Y_ dõqp$^{ñdª½bM@±2®¯a)Dš–å쉠XÜžFæ»Ã³ýîð<çîðœpwÈø¦šä[CÆÒ̱/d»)Ä@bXpÙîI`ð—[¶—È$gÃÙÞ3ΔÇ’5=Ì B,9ÄKÄ– (9ŸŠÅâ~¥Bàû`¿‹%öw±èì‹å qœre¿T©”Rtª•jå/¤˜%¦ÏËt6˜PP~}yºåh±ûûˆ÷8˜"ñ¾7äó×áèöñåÎ%ÿ˜Îî†ãÂü‘Q*ÿ¬ï‡“éŒÌÆH$dgª¨²¦ ]J¿‹ü?x“%“¹_àï~½m1ƒþâÔÂ2dS¡L,ß.ýQè}žž~ ï-SéòÒú¼ÜN@P€Ò9_$ ¸g¨ÅÒÔ«4 œ!ëyÿ&ÛF%sràÖ ´5ÆZΗu¢z m@V5¹¯mÈKØÖCG°ŠÚP¦ÑµyÙ[¦ÆµÀqÆ7úÍ‚}“ñ¾2¬[&1OLïEeýfÁ¾Éx_Öm]LSл4€ ~³`ßd¼¯ ëvw­$§÷RÊ}©´¸7ê/YA]Z©ÛæTç`Û@tŒ|ŸìÒÚàÛ»´Èí>[l/ èEBíØßD²˜óçúƒé¹°—´U„¦²ï’²–ê•y€ß(Ð7ëk¤[É„ÖWuÄÏ€Ö7ô ÆúéU²¢õ•ﳡõ }ƒ±¾Jʉ=ùÑ3½v"32O®œXÐs‹æÙhTæ&í…Ÿ&Â'嬈zÙ'ül8 Ô™ªS–¶Wõ*… :q&¡ë4,$c¸W§ºZÚj\!®ix)˜ÄoP”¶ó„Ò!'³îðóÃŒ¹=þÊ# Ví®Å@E ŒîZ~\ĪŸôÐ2”º÷³õr_‰VFsC-Sð-!›¯»M€ZÃ.ÖÆQ%e/á€97ÔÊްÔ½ Pë7ÂEƒmÙ€²SÉX¶çø¹áÕÓôâY"˜“Åæ اãžÌl/ÂÊ–„ç8þÎ °††{ËÅöD¼.(NºìRAœ‘¤ŸŠŠSvçx*^ ÄsPñêQ<Ïæ‘©]‚7¨Y“`2 ×åü—Õ«<þ¥Gõ*OóRõJÎ#sSõ@½&G¿¹©z%'¿y©zÉç’,èy™ç¾y)ycл¢S_Ly6ÏyáMG¿+XËŠ×Þt<À– fKÁ™Ÿ–GÁ+8¯ ‚“Rp,Àð .)Ý$‰íX”¶³Céí8¼ð·0øëÆÍ ¨Éø‚ûQ¦¦dyðxŸPoÑÐ[¦®ÓB/a_ëÊ¢·Lk¼î̾hÐ-Þ%=õú$S‰A·Lžœ)è*ê5·q®Í(6j šÍx§Â4ŒDXÎØÄ©0Œb£Æ ‘ 6q*LÃXæ V¾WÈKë6ŠÃü{ÅZc£1÷^±Î£Ø¨1Ì¿W¬õ0–9KwEn%ífg«=_Ø6üL¶ˆÒ*)(ƒÝa¥ðϽ1¬š„æÜV ~&ÛÁÚ¬€”;Á<ðÏ£M]ÌPZl øóïú5¼úl ü™ï+\Yì«\Yn«Árà·ºÊC‚>Þ"žý‹ÑÞe2ˆMº²Å&aMM ™ b“†°®†…lF±Z»Â’÷ˆÅhí–ºG¬ÃÖÕ¨°Ü=bư¦&…¥îë0„u5(,wX=aɛĜç¸Á¿!Ð/ʘ0‡2xé»Â*Á_)aÔ¿|F¦Ä“¥!a%ÔŸÁü°lù„lí Ë>¬úìyÿÜJàÕòþ%ƒŸÅa`M¨-l˜«æý+¤þ,ð><ˆ Hš& Hš& Hšnl@Òt£’tÐKØ_àeä¯[@RÐcQ¿ä€¤,AWQ¿Lÿ¤£Ø¨1¬«Í0£alÔ ÖÔj˜Í(6j ëj7Ìhë´¸½b™þþ‹Ú+Öb ëj;\ò^±ƒXSëár÷еúÚ—¼W,5 iq›…Þ ‘y<âö‰Uƒ¿1I‹ÜV ÿ¦$-jOX5ø´È [eþª÷€¹•ù«Ý– þÆ$-lX5ü›´¬=`•+`­’¶$€ßN󥵇zàorDRÒAlÒÖÕºÍ(6i kj[Èd›4„uµ,d3Š5ŒHZܱD·ÿEíë0„uµ*,wX‡1¬©Ma©{Ä: a]- ËÝ#–‘´¸Mb΃܂àßè7%"i‘»Â*Á߈¤EíkDýë‘´È`ð-êz@ÈÖ²ì³Á*¡ß”ˆ¤¥ñþ%ƒ¿!I <¬ õ¯sDÒÒxøð &"iúmòÅ>"I”¶‹H‚Ò¡ˆ$[Ž¥‹ÃHšÀÊÎØÃÀD€ŒáG‹†Ô6±²R­Q!:YÀiUg,RÍzЕ‚¼Û²Å5yÛ…˜e@Çf]ÍJAÞ€méxMA^À–Yr=xƒÂH2 } Êèk«RjbÙXM@¸+ǪÅ.« â¹QÀ¦G뢸­‘–†W[r] ¼Zsعñê8Kb®Y,®Lµµ´ P³ ×•»t¼.‰Á®Ú¥Á’Xìj0» ™ÀNUâú¨’>ª”L!UJ¯‘2] ²HÅTi.ÍT†[+¨tËhŽÒPe¯µF"Þx$Gºì­ôÜ–M®9èKÜZc1?Gº­ôÜšÎ×ô%n«æ(Í{3ùV,P5csÄ:A,è87ÄI{]°lIÑ‹ÄòÂx¶è…*n2àÖ:ÿ‚•àÙšœ× Ïö:#<Û¹Ã-„9—Rã9[ Fäåá95{^%žSòçLñ¼4)¢—Ä¡WŠéÔ,z¥˜NÉ£çÀtX³(¿®èÄ´‘Jù:7ÈÊ«zUx^2^¨WEKæÑ+Âô\çBLÿÿ€%„3þBÞ±…G¶EOÏ“áhvŸûüm×)MÉe­×k“þ‡&é7{ý¹8!Ín÷¢»ÛüÔê÷þß臼d(a½€½%ØÜ|Èߦ'­vDƒd‡} a¥Ý?ÞüåõóÝõv­·7s§³áèóÞí/w@Ná6Ë>ŠÅâ~¥Bàû`¿‹%ö7|Ê•ƒ2qœre¿T©”Rtª•ýÊ_H1K LŸ—él0¡ üúò8t#ÊÑb÷÷ïÙXˆ÷½!Ÿ½7d‡øóNÿ‚ý—r’ñçÉà‰ §d@äëdû¹OÈpŠ™Sà¥?N†³™;"7ßÈ™;œ HߥÌt8}(óÜsœ=çèèÞ{ó×áèöñåÎ&^ ¾ÂÃÁçðènüróè’“ƒƒ_îÓ—§Üíx4ÊáÈN'OøëO”%ú/h3Ÿ¶ß QyâÎ^&#±` P–g¥€Ë½ùm<¼ã]üþü-ÐûKt4x|~~Òoˆ|h¯ƒÐ^sh˜ô-ºàæÉužWøÉ]` ·ãÐÌhÊ-è¶b_2B# ”§òn<‹D³Ðœj #¤*@ÇFx@Ž&O¥„PjûÄv¢¨n2ž}Îù$æÏ×ÿóÖÿ9Uçkò7ùÛü4‚,h±±' ¯o|{è "ã6øÁTá,|ʳ®ó¬Zq' îéíàÑfIÆ,FÝŠTñˆéV]p_Ï °j†ÌzÅaa4F®¶i8'ŽÁ–‚ÿe`œJ'Æå’¬+ÃjZÐÏðnð4ø=ݲ1|§CþA…õÿû?öþØæ äŠ2…ÄÎ;T zë|?â±Vþ+-Sþ«÷ËŰüç¼ÊËø0ù>’w\¸,óÁèÑý–'ÇÃÏT¤{$; ŸŸ\º¨ãÉóx2˜ Ç£‚¨}9q»w䇯/?Ù˜]8JG. Gwdöà©èèÞ>Xå©ás>¾Þi´ÿ~|(ã1=Wï•Ê{G‡yÒ{ßÚktkפëNÝÁäö¡ Ê’ÿ˜Îî‡7…‡ÿÐÉ‘&‘SâåŸÝ§ßrÈ2Æ“;P Ü> &dgZçzN~vg¿°ÁŒ§î/³oÏnNŒíïø¹òHD**š½þ/Ý‹¿œŸv=7MÚyGqðV¸^Öèÿïˆ`vÈöÓàñq|›£-=mïÐâ;Óá¿Üñ½'ãl{Êz–È‘á»âOdø'úïÛ·¾b„½ýÞþúýWy =ÿ7@³3|û+ùŸwƒÿ¦RtoïüúvHþ‡÷À÷œÝ ^‡ ˜§¨‡¹…yZËCÓyò{^LŸ§oy1%b ×ÍÕð/Ðöx¾¯46.ÚˆFX¾jŠ¥…ŠþÇ(*,_!¤ttÕ9nž´:Íã :ùC]<eíĬízà @GþyݲŠ_K¥ç‚öœã(Ú‚žÿx˜×I.@ÕÁéôgQLŸ n»esÌwòÌ+$4ˆà"°'Ô5Î&ZVþòü8þäë쯻áàóHP`˜jãx9›á´ÌYy{uÙ¾ iàùq«öž˜1Ì\ðrÂKAS¬þßáË -²× ‡/xýÚ%Ù FɈÐ~#@Ú¬@‰·é·€,¾ß½Oê†îClØãìûr›kOÔÞÁ¥3Mµt|ñ%ñâ!k¸z¢OôÚY·¥“¥…ä‘nõèä%f í~/É Û $Í·¨½ F>‘Äòd¼/Ä(õaÛJDí=ÇäwLt8…Z¢‹ØA¶µÙ 4èw¤ÁhQÙЫª6ü6IM’¿{$©!>‰×¾’Yr2 ‰Òá ÷ÅPFoY/É$h#½NâÉÕ‡ž®†2K‹!ÍØãÜ+Á¦ ØRŠ ÿÖ‰vKIˆ7t ©#néòðûË£øñ’kóBrAœ<j"(X)÷†JÊ¿æ½?f¨æK´&¾¼¼¥¸y[²XP0Éâøò‰ÍÓð;Þçîð'ï9`à]Ž¾Ø–Ÿrâ„—që)÷ë.Û~ =DhW¤…(zUð.î‹£šv8:ÓN2¤ w-F¤ˆy1£F§­ j„ÊæÆ¬OõT7°¤`9IZrº*æÒ¬š€jOÍ@ )Tœ3=OI¬Tb<&å°$Z–þ@¬~ÿª¦/ÒÁ‡bØôÐAo¾Ë­¤¨ 0ªÐ’ôW¥¼ %Fµxnê’r+UržõSeh˜e¬äöx²Š ¢Þ»ŽëÙ®coN8·Ô0Jä0>)?ÑòH‹LÈ$=ô¨Üy‡ÚXƒ…âѤ9¹±V/BG:•`€é¥S¾2½ï‘éi—–Ýe.–‘µat §[`çÄŠÛEíA‘ÛOÃKÊñL,ÏZSlÉò´" ßM6 o)åÙ—,>ævÑ#Ô#ì¨?".HQòÅJQ²‘rØ+cú¾ÓÔ(‹ &±(‹‚Q6 vœÒªð<¥ë9ľìì[F•ß©]Ê\êËÕ¸q¼ ¨(’/Õ.M\-—£ß:È×¶÷JÛsó6º$óäKĺ”9à¯|µÑæõÁUÇÏÿM¾h–­èM§œöaJà:»Äöu_=ƒJ4Ú_%>X„f¨c´b•?kckå¥^÷ÄòŒœEüui–ˆ$"-—Ï6¨‡ÁH“­êÙêìG¡“9 ú¾üIÎ}¯Œì•‘­Š‘ÍÌŒ,ìësãçcÁ·ff¾öúy:ü(l*Õ+›zeSkϦ^ù.÷¥ò©i6|jú¼(/°gv7±¦×³ØŸƒ7È‹åOÉ`…ÅÅ$—¾ËŠÉ¬¦PF!aXy—uò9JH0YÎavÃ'ÏøÑ&>c‡–"½-Ÿuܹž–¯›Âë¦ðº)ð…—dWÜf_÷‡×ýØí¥D„äÑÌ·ŠeÝÿ ½ÿ£¼Ìû?JåƒýJèþƒòëýËø¬ùý¥=çh÷üõŽB=r‰±ûoÅÀs.Åü›ã?÷Âmö]'p“È“1ú` þyŽF0'½¯I´“É÷ð&xé”ÞŽ{ëU¸ E#PÖT§ÿ7dYíâíã:üÓˆVp¸^ä&Zs9ñ /¾V[îF”»±:¡kÚÛ­ù µò~òl!ÜÛN "Áµ&DÝkÃ7›öBplÑ;< ¡£·¿‚¯Ã¯;ÌÙáí0z+æyR!hƒ—ŒýX¾Äåiž±xsu=Wu5\‹~ê¦!æ˜R=Ã!œ·ë8Ä: ñ†ñÆbºê!º3ކhÖc‰ÃL¤g7ºúÕ‰h˜gM#&4ȈáØõÔ@€ð-ø–¬ˆfÈœµ+£’ƒGBÞ@4!ª8+ä<µL1«a)cyçÒ¬¼®+5R_Lô¤­‰A“ð]Òàé&Ïv$¨Û<ßp~ÒÉÐ ‚àE é=p_€nóžÌïu:ß6ì³k¿]›,޽Öq“L‡wn¬ê‡½…¢ì-âêïðw¢-*xL¿íÞÏ4»³Ý¦¶€ z®M h;4”‘åPâƒC‰eøÆÈ#›¡„vÞˆm÷)fÛóò·˜j#¶&|íß8Þ™`QxªÃubÿÑ0½ïiK’ðãoIQøñÜh=ÖoÆPô^ĺ–ö¢t¼‡á‹­K (!Å>”vÏ‘·¾±ÈÛíNc cÞob.pJx4L~2\Þûp˜zï‰ ß%íÁÉvï±çè#Žžþ’[ŽNWq”gŠ)â x%,™ƒƒëÈ+9Oͳ ¾2ÆÐ‡0 âX4íÉt ^º^B7ãdÄ’³:X2ê Ÿ®ëxuý;ç×:-Ë|<ã% r9 ÏÜ™;™Ò¿8huúÍ÷Í®Ï:W}þî²FÇØìûosðòÝþ¶ßdïvð8 í G¤1~z¢à›[n5j½fž>o|¯óäüâ˜>éðí‹÷´LÛ¯¹Ýý¾ÚcÚ™×£×OÁ½“Zà ƒß^ówŠ @rïåÆs¼õšm~¢ïHÐ4>4gÅ<ûvøw‰—óäC³vÜìúÍs|ÜÐmè‹Ônãâüœéöè:Ë{=†TDfB××Ì÷bµ~È@ÅÞQá`¿º_ªïVöäÑ»·/³ì…=MS»­~“Mxþ>ÛºI©HñH·[Чèo'8ú¸ÕðŸÑél{˜á³þ[£ál8x¤»2›ç<áãæh<.¤¹_É-]$Qn–ËoƒÇ—”XÚÇ]H¬‘¯ÃÇGù¸© >dk,ÐÎ; é"$”ž_fyØÛ£oylºžZo‰SÉh éR?þj‡6M÷Åge©íø¡RúÝ«fA™>†!(¯Cq8¡’'$‡è/4ÿ³PÞ&ýÍŽÿVÌ£à…$4ÛtÖ”Há¢[ Þ߇¿ðoÖÂ[¹¯„SŒ„Á‰‡Á ôY ü]…a?„R<•ÈÊ¡:Ç´¾O »»” Óã—:K0ÿÛ¡ÕuˆíÐuÕ¸èô[«&¯Ôë_\RêÁHN.ºçµ>Ém‘®ëm ¸çvßu§/³éV~Ïù´µ¥ZŸ]ø0ÅŸ[b|tp¤«z—‚M¥«Çû.ö—Úd2ø&óëÊr‡J]¬™%ïõâó¤í½-~T?¾èoí™K–ü’µO—×$ªlÙ/Û½è¿,[QÊF­úE1 ìûe{k—‘eü²îy)²ì¡„†ÞÕydÙ#   ¨²”6DáÖqí¼öikžMWu›±%±»ÍþU·â {[ŒŒïÉôåFH¢£—§w²•o•óGŸò5§¹¨•M"ÙÒŽ\ÛÆÅMWÜç— e:&Ô¥b )øBJÁ“ôè½GOè½ý¿gè,Žç„[>®9”bó@pTp`?ëüQÝÔÀGš]‘·Ûƒ÷©%`‚Lùtxðå$ç‚ eƒ€¦½b¡|LÅôb¡_»üÏÝÀßÅB‘~1Å^¾Œ‹¦`·«öè4¦3‡uVŒé¬í³’‡¼yùOþ—“ÉÈzЙܬ©Ï,F†DMû«²Âò×®úm5,‹yã•ÕZ£Ñ`<Ÿg º\èƒæ'/üø2%_†·ô¤1‚ÓÅ =CL(/OÜ;^‡2»;÷vøD×+-¡ÞÉ‚3gŽe C}[†·»Æ×Õ`e¯q<ò±ß¡rÚé¹3Òyw†g¤áåð~x‹ ¸ì$ÅRþº¥Ÿmì,æüâõúò˜Ò¯|Vxß/n“÷¤A*E¥@4ÝÀAÏTms”ÈÀFÏQÈ÷ºËQ®N™:åéTr—cŒ qÞ|¶-ý œ‚•êyŽ{¨T·¬ÔÈŸ‡ì+¦x/lŠ÷tÅáÜ£T–…m²Ezã—Ç»ÑÖRåƒ;qqßE9aKE(Wü–Ùˆ„6•¢`¼‚9Äy•CâåMOT`lÒµsé¤5€ Ê òìgÙÿYÍæ«ùüù³øiä½ÈÂ()œ_Rο„ Òû”;Ü6ƒåJ´[¤rò2ºÅXøhi‰JôLNÁƒü4÷†RºTD#÷hÚËËSKT-\¤´Y8WH’UXÀjf“áh:¼Õ¡€ŽªÛêôZ ¯a Ùº g½šÍvåmSÚDËþWÄÆ[f_ûýÏ´g –XW_ÆŽÕ¼ã2ûK÷elH[' 1V¢›`¯#¿Š…RT ¾˜ƒýVY%Ý—±‰ªèÈQk!¯áãýè6ØëÀ¯zÈþR¾Œ é ‹/Ùûë(º!¥”þ‹·C/b*ç 96‡‚DÄ”U“@¤ZG"1e1s$Dð¯–ãA±æpñel™8Š…OðŽi¡jေ ÇFÎÇM Ö~F«¾¤"nŽõ\ýÒ×<«>†oP‚òHI`5õÂ÷è°(XWñˆ™`ÅHV®]ü>˜wÙÛ1uüº·d¢AŸVœRZBó–mq߂Р«CufŽLmFᣬòÖȾ?‰DÁRô׈y‰2YoÖ2 ÿ+Û+LéÉô°(ŒgЀú ¯ö‹ ³7Uå ÇOxµKå9•šé›Ò•žr¼³<ƒÂq÷7÷v&ÉðiÁë ¤¬ÛvÀ~D?TömÁI›ŠÐ­<"à ûûx‡¥¥²j¤Óœ’žˆ„ :çÂ8ôÏä| AÐK9?z­Q„ô>1`óØŒø7tü ›ÒÍÀ ÑÚØr<°¢µy€=2+¤t °Li @ÿµ\Øu¶wªor¤`ÝcPYD âÎN-Õ ñTŠ~á€Qƒªœ)8جø×7ža7Œÿ8dÂ;ìäü‚ò,ñCà) D°¹$: g+LW²š‚ÈšŠýb‡!£¬¥î¢ôª»HgC‰RkœæÉý:£'Ó³^뿚¸\>á¿ýu~Fåá?åò•|UNñZúë ‡¿Œ[ÝqÿÐ/ýÉÉD•½Æ÷¤À;¹ŠøYÊ9T¬ôúŸXþudC=^ J™F§«‡À”±_Sôö?,u,ÈñE_Ršh* ¤VŽ }š«]ÀNÌ‚8KUI­Þ£dÓꬫ¾$Bx‚ùÝc‚Ó.üïD–½Æ²P¿ÌeF (k¹‚?èe*õ™+Ñ*žW‰8“}’ÌXBsÀO…ܤt$±bŽ×ý\;{¾.â(|„ô5 ‘Š„*êˆy P…æÅáÇÛ’Å©NT‰™‹«Ê¡Ð{pƒ‘ƒŠ¦"ý.³Ãré z(‡¾ .|,µ<¤úFµÃ¹›PZ¢Ã;Úf@âÌDg9ðu—G¶ªË#UsY²ÖwMfÝ$^ßiT‡ê&T»Ï£õ,' I©„BRö‹a›Óeá .þZã:iÐ,HqnXç©ÈµÊ)aÚ0,P(ú­þ•7·¯´Öc­Ñí’p5m An„Ê!XxmØmõ*]¡¦’ÇŸ•4ÏÊšgÖƒú°ª)¸¯+x )x¨yv¤« S¡’Ž.z­áµf„×âõ¡fˆ×lˆ%õÙ¾¦Åð¯Ùƒ j†x͇èÆ £ã‡¸( Ã(B4¡Pxú;l eù ë´,µï[°ªJóœ{µ”‡×º‡ ËÍëž_žS 4”çÏwCÊìÅ>Ù WâïZôÝ~°^ÅÐQÅÔÑ~DGûè¼/B»ï4@ÐåbêèÈБãDô$^Š®œ}%j?\gø° 0|Xt)?Ä•V <¬K^‹ŽäÕ‚OKÕ‚Ùš> uu-ºÚUAuŠšÎðqI_šõW >ÖŒ>Õ NtèŸjF'º =Õ Oô&-ìRQË8¸ÈÈ9ªFdäŒH~lâлÊL g6¦³mVóSèR04<‰××Á×Ün$Þ÷QPÒñ›è_‹"Îah‹ç}*"ç”y”ÉFø®žç;ê6 4Ãäœ*¯ÍÀ_ 'Tþšô¾DùRx«·¿JñÇ ÌÆàc4ÊFÙ¸k)¢œwÛ^ÿC«‡ €%è²ÖmöH­Û­]÷ÀP@Ÿä¶IÊ[,Æz›\œ€Èþ¾ÿïè_ðVzMt. 2:é7»ç¤~;[''Ín³Óh‚9êªÝo]¶[ÍcxãÉÓ¾š¼‰Nó}»õ¾Uo7¥« ¤Mÿ«}ì]tòäô²MÉüè BŽ› ¸^}'¡:ÍýÊVê¨kõÛMɇæ\»&ù´²0ƒŠß8ð{Í3 !HyuYˆI¬ž Ý”½ôNf-¥âeÜYm£0ÜuÐ;¦IÐ|×»ò@bìô¸ŒHÈÁñžQ euoñ/Jž;½ãí¼òjÖ¨Fá͵†wQäNð¼ø| K¡€QVÒ¹è“F²[Ñ6˜Ê5ÿ))ÐrÂn|gý•Š1½]ÒIë““Z«MΛ½^í}9»i]:ü‹4'5z•žÓ6hÞJGóà»ïæi휷ò>u‘À}},–´ç§ß)·ÛÛ}G[ÁKî÷¶&¡ & $€(ÅE|¶J¯-"f;ê#®äv€pCˆ†é^þd‡n帛»ÜªÂW鸼_8¤_N©P‰¼©Û»”‚ê°mÔI²ò¢7Zu¥ÿÕ:Èíº´‡¦ ¥îZƒ‚rq\£”›$!¤ãõ»Íÿ¼ju›çMJßýtä?Ð͵FޝÎϯéùþ _±pwÎC+¼v­Ñ¿¢œÐ+v~Ew~Jû¤Þô*‹®ÿ»Ùƾä}V³Íâ6»/ﲉœ¶îù>Ϧ ÍFÈ—ÊÎvr×(¶ýë5yýrðrÑ·àÛB:Às†ö\,³ô-I†0prÕiô½½“ÝÖ›@†„J‘2$ƒœÂzE—–:ˆ‰ý¤su^ov{$ǹ“f8Õ´$¦~Ø óÖ÷c±Ñ½ƒw¡^$f¥Å,nêÁ)›yì1ÚŠá*a©\8f Ù˜Çϵn«FQAy<Ç]¶Â ¥Önõ¯ ‹‘¤³óöÔ¹lfÙˆÖÌëSwCîR<ìbÙ ³–PÄPǨÒZŽC1Ž‘àz r‹åb’{Y˜è¦•ÛŒB›Qbk¨ÌF³Ë‰H_#NŽ“È.4^ I-ò£—Ôâ@@Ƴ¤'š•Zåý|Ë)É"Ùª“¾~–þÑæÿ,-1ÿgÙ©:EMþσ×üŸËø°Åïåÿ„ôŸ%¶÷$ÉþY"õÇÁ”ŸMú®WÌÅw“áo.Ýf¿‘™>Œ'3rþç÷ÃG·€î‡ZÒ9 ÷v<¹›BCã{ì ‘ÁÄ¥¯wäeJ •<§³Ý»!-‘žô>ÐýnTd''­6JX»NpS¸ê´ú\zW*B ØBûäª×+<)´©0Àr¾ˆÚBº:i×ÞÓ“*ˆÝæÇ¨‘•†j' 56kô}ã¢{\ˆk|lè¾yEåa¬Ð¨€jðf·K¿ÍO­>«PŠ^‘ÆEûê¼³{^;½èRÑØ{Þ½ø(–¼‡õ‹þhÇÙ/0çþ ˇ‹ö1•ÍÛWìøƒµkôô%÷CÛ®\¬Òƒ_¨(ÒÞKtÒ«äˆ ¨Xµuæ·%W°k ¥»’xö“WyNÓK)y/–U„ÙÏu”O—ÇãÑgˆß'§ú_ž¿Ædü/ñç‡ÁÓÓ`ò;è„ ñ‡ÁhJÏÌ]( % ¦(Ý7gîè²O]ÌÛxB÷ú Ý2!#øð–´éŽ:…ÇÏî í²çeuœd˜úîíÃhÇyrî>iwÊ.ÆÓ©8$7qN!'Wy:tò´à€n±tWÞNý†à­HN6!½Û¡;ºu阇¬Z­6ù<賦ù¢]¶7´ÇÙxò-ï7tt@…ºÞøeö@ƒé”Ô¨8óâæEuzØ|¤8§d¿X)åé^«Œèb"ÿÕ©½—ÙuŸ)š¦ôXWÞ;<@ ûÝ ýIáë¼<¹,E‘6ž gOÒøÞOÆ/ÏtÝò¼Ù†;¢§˜»¸¿ÞRÈH©ºøݼL¾ÑÓïxp—'¿SèN‚ïS‰Àúê,ÏѦë™wØÝBŽS¤RHÙ™Îü†z³‰ëRaŒÎípæ‚÷\hìë$!Zû7€HBVÕ©î:¥ý2}zÕ«!ÎP¼Ù%i—”šg§¸[{ùLeÉ]çèð@Ð\wB– Ç<éQ°‡e"§¢ì©;qŸ¾ âÎ#ª¦¢ Éj¤Ó‚¬TQj5*cÒBàn ¢G9•tzWõ^dkP¬~3%ë5»tíÖÚ'tª;ͨ¡(sh¨‚a­Jx½H ÏkLYš¢`§ïUQœh"n±¦;­cö}Vgßµ6û®7ãºlñND+ô÷‘h Ÿ³êÿNÂÖ ¯Œ]Áo²jXDš“æe/Bmž žæA·(vzT4ÂÛÁ;8Øì¿ChÃW§cˆ¾ß­Ñ³MíÚ'ϰ• åýZ›ƒƒ¶"74á;ÚN£ÑQ¿×ÇqÁa I¿»ø-©~ºi¯|·Öé…_ ¹´'Ÿ~è}Yz›åZ3µ§S$ˆmʺù“þÀI’=r,ùªèÀ9l4lhduóX&ܽ¥µ’7>œAî<úUb_eöUa_Uöµ1aã-AïñùÏ©o"àWÀjQî#HdСN.úlÛk˜ñzq1µCç’×ÚZCö óÆž B^êJSûjì»LpO§Ä½-ù\º•'[ò¡s+bö¶ä£æV~K>FJ>[6ƒC¿ÞLmffßÌTmFýóyj× º¤Q|Sÿ|žKÜÐóŽR¯D¬RÒ {ÒGÁ¾(D¾.èGTäCÑ÷e4œñ4ó¨ùœŽÏÓ‡ñL$fIZpüLåSTbJfþÚqŽ †'ç îím¶e™ßÃVÍ_ãf ÐÑ…÷M/^¥Ew önƒª<¼\\6;9¾Ù£‚îÛ! ‘,;z# õ”PXf„©Q§dâ~Ršô¸âÕ6¡~¼×Á¾ µÎqaŽï{:??c×#Ì­|?>¾L";e≹iË-%HDíÒWâN&t2Ý߇´CP ÏÆ ÉÛ‡{Õp’ô4Ý}üJ{C5÷ãà¥ëþ¸Ìèoö0qél<Þ±üÚb’ 92#OԘȩP;Ðïíƒ{û›y‘½[hü¡}épþ3{K;ïD4åâß uv Ýûë}¿ •¢Ñæ›Ãõ)šD3æöVgKñ~inÍ.Uj7ÖãÒI æ·‰Iç)zàT^ùÝÁh¼ú0¢"ŒÈ£ÒŒÉ8,zŠë(ãÑ I•#˦ä,jJÎêò„œÕýé ¿l.ÙNÆÙ–8EÍ5 *SqV—'ÂõÀÇÀkâ$Xã»J¶íq]ŠÀ5ªÌa ¡Ê<ïô½²: i!Ð?pèhÆŒzE]k¢3÷š ]]†<å¢ü&° xeæœL>ËÞS¶*Ä Ârž*d[Ñ'XÌV9b¶˜"b–èOž%ú§?KðÌ?ÚÎö¹%”sÍ@•Ù5Ívh˜h‰eÝ;Xã(éŸþ(á%?ÆÚŽºÜ hbÒ OÑÊ é¤·k–TìOt´Þž5õÅ/= e²ù¾d³-è«:qLL_­¿è´¢è!ªâaŽ}¢@O1&ñXÁ :ä‡ú-Q‹Æô8;ò™È&‘¡*äœÖÐ?/9&wÉwñzCócÎuÞ‹†énG@æ€Ó‹ q³«ß§cݧ®i'ªéb°éDPGOàŽŒúÐq ×éTÒÀŽ ’3ÈÊÃÛOvæ…Mÿù¦‘ѵA7²Êœxj#Øx”IøV‹a6D©µ’ÇQ¾ƒk¶™*RhGý¾÷M}Ãb•íB1…{ r²eÜñ™c8®W¿Žö<¼”¸bá ¨Y–uT-2Ì…¯F`Q?ÌFáO7˜Îšäàð4¸} ÓGžéi gRtz'Œ G¡%¨Ë¡5á-S„ÃOÐú !‡LÉNi¬ÿŸ½oïN#WöÝÿî| ­Ùwo?Bl~Î융c°àI¼Ï=k¶qÂÄÀ“dŸ;ßýªJR·Ô-µÔM7„^31Ðz”¤R©TúUi»æí¡Y¢cŒ¯vÙdYà_¬,R¤P¡I¼†{û¡qÿqл<¦ß€…ÑœÆDý¯½;†_’Œ „…T!¥¢00K›‰¢m[šƒðBÚf(zNy/Åñ„»›ÑEüœ¶‡¦dÓ²-MÌòû¿Ýˆß ·_iƒR5%™7^æóíM²É¨ [Ûô·Ý"¥Jùm>¿Ïô-¸<ÂJÙÍ ]ì»™õ%ÝØ¾`\QvtvƒŸo(¯œéŒR7ô½¢ÃJo1‘ê?¿Ëð&æ‚"[á’FËÛiÕø´pÐÁŽè††7‰Ú€¥ÂË"…aQd·×EÝø]ôFî£7ße'y`[éSÙ'-a`ûž¾Œ‡ÊbT„‰ gvÚUÁ¦7yírKÚâMÛ–zÔÇKÁ„ Gz›RTO”ø*Òñª‘¶RÁ0@ÌÎ,ŠJ™&ÖI¾iM¥í–ZmRâ;~j±¬'°WwèJ0wJ$2yØ€ pH@xø ï¹¼ÐèG„Ÿ˜ê|U‰X˜6!ìKŽÿ³¯þsÀÿÑLâ¿•ÿ9„Žø?úlÇð¶ØoᦟœÕš¿Ò•ƒ²&è_'güZâ Þ… 32Å0¨.ŠqªÐ(ñIÎTs1Á™AÚrtÌN›…``GÛü€û¢Ç„âðþ1–ÂNÆùñ8œ‹³Ãq “€¬ ÿwÌÅ€tƒÿ;(ØP u„p#y=“É?A÷µ×Ý§í¾‚½û„WR^þäW8 í0ÖÝãœÜ¹Â¯ûÈÉûñ8¹øCEjœücvߌœÜm#¿À Œ“á#ã⣜’ƒ&îÀÏǘ>òœí»Wøµ€líKs7o$Ìãf!M÷ÿK”ò׿þ55NþnzdFæ<ôVi‡ñ˜jo>]èÉ€™:Q;ÁÅxýœžèü!zkæ5˜±ä­óðmYó(kîÿkþ½5;kBÚ}Ÿ7áë2çq<æ<øº;5æü!zËÀœ`m*æ}îÚd´#ÈŠA¡g Äcâ¢î¸¼Xp`ëòKÙ`·štp(Ÿ\cȾÓòu£‹ã“¡L—“w”çëUQø„#àöΆBN.ÆzSß‹ñЬˆ~.|ÃC©ˆî#ŠÑJïxäŽHPªØÏFðÆ|pÐß` 6墊¼p‰ã® Úxé€_QM¶e[•0¦luG»³ïKqµûqÅÌlþÓšYê 1³åÇF™°cÿD…ƒ¤Ë/_ƒÞø'†¥FSÑNYBŸ×H×Rž&¦W)Ix¡°ÌdBûÓùU…‡¨Ùi’ñ†‘®ËÞŒfJ¶`Þì…ÉSÍo}ŒxšvïEÏIñ4Ú•Ñ仨…/¾ƒ¢¹„õ\Œ`á¬XoʾŠUÉS1™Ë/ê+00ìfú±Òhú'®‘â(AÀ…nGÿ¿¸¦ÿ€””ãßÈÂ0xæþÀû¦h*È@%ÛEþ§?@y×poá“rDô-$„Û¯!âý–ÒäH‘rû >Á ;Y5½@ØwÌS Vµ-äôº)ñ_:ëa*3ø†áeiMþżg5~Æ"|NUï‡ìE©©Ëþ“z/c íu ê%WGT½§)º’Ò6‹%8ì,*' WäêrZåX€*‡œ4Ë+ç=ê•?»w¨WT¯OÊ(»­nÕÉ ‘eΰšMrü39fhȾÀc±9 Ms»Áë9é?€z˜8î¬áÊÄrâ#›7Y}ü ÎXÀ+‰hÆ8¼)ê6¥W™H†)|_• 48]ƒø&ó Q‚OáeZ-­¿üÊù> ~‡¾iíy¸Q•‰Uôßð®¨7l6–5Ö²EõkaA³¥Ÿ»hÈ Ð¥% [u‚÷ã™z—· 0GŠ£ÑßΆ j²°UU\rvq-܂娢fFúIwMÞECôMðÆ‡¨*®¢pèð‚±`ÝK Æ‹@d£)¬Q€‰+§ Ç?õ†äi0<½Ûƒæƒøˆ¿ô&dÚûÜ’Áðn4†cßÜD:b^^¸r¯-ÞHÄã9†} µ7ÔBf˜ÀãØo~Ÿ|Ál`ë¾ûÔ~Ä«4&ƒ{yÁ˜8t?óÀÕÎÛ•+ç/–¬l‡ÕÄ|6¥g)aV•mœb/i¬Š=¦K5°•ÍϺÏB1€?3œ™áÌ)—]¸‚pÀ (cåvÝËÏyèW ç‚ ûF‹€&ÿæG ï%³+Q~ÞcÌ[a=æ U¾16~eT³õZŠHÐÌ\Zj¶ßØjjöXÚßÅÚŠ‰7ƒŒà¹¥-¡S[MVµÀ#šZÃ#†ß¶¦%]÷åIvÁXƺË"Fw]˜Ï¶í"‰•hRÎ:©Oêã'5çàd³šóļ¦uqnÓºøãLëRüií¦FÔ˜*—¤l …"GƶÍR €èÆ}5®†éá`Q'µI 'Øö.ãåc°ð®à]XwšnBƒô3ÅÜÖ„âadݽ٠r×Y™¹ŠêH³$IlüHÔ(NXÈZÑÀQ, ŽûAïñâå({Ÿøû¦‚ª„Ó‰WNTìˆÇlàé¾€¬a,û(PÁðq±zTÜbÄáÉ—þXH˜óöR„P°ÒêyD9Î7gV…EÅJfùÑ$Øs¿ÇnÄó÷/ƒé'ÒÜyìïäÉhl/¥…IÝçY!Î<Û7ˆ?<¤:Ð¥R“†’¨ïò/ó†7Ï·Mý9ç SâòªÑAƒ3Ø‚1. *z8(ýð†df-áÑ5˜GBä€w5®’½`Ì^gWUgBŠRIKš€ ’¹E¿àìÆýö Ž~{Ç"b¡4º]¸1°oÐ3{•¹n0ÆY6(Æ@ÑÆú¹±P©;d€ÖÐáÏÆBÄ­Ôld|tŸ)æØÍÐx߀+‹ï^ˆóCvúó=v6˜£È&8º€r Ë\gKõ(ª\w™ÃþzóºÉ|¥B˜Û w „RÞÎuçªVíÊŽ'A/JÝŠã²Ð]ÐÑ î”öÎf®;~¥¢aKA ×8{êê‰èçz‚Ž›z"ßkƒ{d¢/¤ðZª¾ y}µÎjè§wÙnÓ¤;2ÕçHqòôÙ‚CvM•ZªÒuÈqœÅ0«eè‡<è1*Š÷膻j)Ñ—-¦².òœ$÷e_/FýÏ^ÞM×½\R’#{T—ð3œàŸîíá@³„.`‰r»T0Ím|ȉဘ ’ÞäBŽ£ô÷-²öKµRVŒE‰ ~V³nyÂÕ£¬dåHßQ{ÓÞÿµÜ¨Ÿ°1ز‡?œA6ðMsð_+þèþk,®ÆTóé­ÝؼgíÆ¶vc f[»±¥âÆ6»ýOv[S½Ó"&…ê«vßíª\½€ß$—´ð\\_5¨˜£\Ñà}èµwQûá‰&{ž?Z‡û¥±ŸU\«f÷Hû1œÑ®iø¢}sóEciؤЦyNÙ_Í»ÀÑ_-ä߯i5¤?ïÖñõ îmW÷6ÉNy ö }=Ä‚Fžo˜Ö5Ìvœ{áù„£UiÎà.´>^®ä\6z¹ëVÈiKG.KÛÒ¬2ÒQËì¥ÃEË꟥wÎ2³9§ =·¨R°Í<Ù E{ß<¾4ý£x€N`Tw©b°Xm®R`ä„t(b®®LU^–ïÆtýü܇üL>LáüÑ]~ÃiiÖîmL¿@cR+þçâÝf÷BrpA ûióbøÙl^GîNG!#W‡#DBX`[au42x¹8Eû˜9¹¹ù…‹ZnM®NEq<Šâ¹Åó%JâHäìEdçU~)û)rÐ}HaZ×BÜ\‡œý†ftrveÀ=¥IÚ[é ·:] gOT G¯ž˜.=±üy\` nž<ñÜxbùð¸éê½ãæºÏo'–ÓŽccÝuâûêÄB5Çò²Ð»X”â¹XT™j¢óÍq÷—ˆã,áî)ÁÝ$À¤à»IɵèO꣺ÙÄòtHŸMa4c:\ù£yaP{) ñŠvĽ&¹¸Æ¹Êu^Ì_á!qX jËxR`˜>S¡ ½Tsù*µ¹œt;àeÓòUŠë¨d¼õØ’/þ“["Š‘ 4—^JÉ3IqK¦Ù•«èê^o–}—bø (¾±>I®ÞO¤x®ŠËD·ÅUÂÝå ®¿Aد"†¯›£A°Š°“AlÇ^È8ÞN®!?7?DÊ‹< .˜ÿNþ?ozã%tÅ›É/±^B¼„ó&¡ï]¬‰åuæd?ubzÎ%Rú–aýHÄÐIúp> }”=?­ÒBp“™Ô:GO1›_ˆ“›˜³Xl±ÄÞa ]Ã’ù…9Ù¦b{„e¸p¡3†X|0Ùÿk£å§ ï/Ï¡+ÆDU]¿o®¥˜¯QQˆ£ÓWr¯ܽÜ|½b9z¹1¡ÝÅ+¿‹9m¹M†h‡-«·–ÍU+ÒOËì¤eðÐÒ¹g…|³Ö~Xó÷Ã*åÃnp,A~X%ÕÊlÔW&c:>X{†ºU´R±ÍL¯l;¹€iÍŸ–VK_a¯¹µÇ×Úãkíñ¥Tùx| O.ßGª|l§Õj9º4Î\Iº#äÄæDŒB@q¾Þd.·¡•æâMð3–bôc¶ï¶Y­_X·~aÝ ûsÅþ´;ìÇwë^u~e‘(s1|±r<ÞC ¥•³°ãÞ]‡ÒÈ׈u<ï­.÷Þ‚Õÿâ"Éš*.ø üÐY{x9yx]3/d½.¿{ ¿œÐ­4|¿ÆËéûuäfM¹r¹y~†wíø:®çþ¾L/ÏäßýñH ÅAÂâ‹n ÜRlGÿ@TWmm~þµoÙÚ·LiçÚ·Œù–][Ë®Á»ìúgL»2þeß¹kVµK\n'—j÷gL¿¾|L)ÆêU=10OE5EÖÉ'ÐÉ'?cã Td2Ø»šÁ‹ö;zx=Lu­ H‚TìQT䡾«g#{¼ ¬^ŽL·nŽæ­ˆxé=?G_O^4Êh<ø8¬;ä³ pɧ¯%1‘ DâÄ ¾ã×vŒ®r–¯ì ×¥)ÀRñ[⩘n¯#Î`:²ò¿’²ò‡³òi™2ª—­k_B`ï_ÿ^wç^ùkqëµúôºÈÿ^Yþ¯}u×¾º òÕ ÿB+hÐMÏWWg?Vª7V=³Ÿ®½Ùrµk?ݵŸîÚO÷ðÓ-m¢o*se—- ÿÓòUŽú!‘?®®Å37Ðz—Ü8þ¶QͲºÛ.ί¶äàW»—¥_­t9c:žµ¡›嘜oϨ²öª]j¯ZÎ0²oíwàV›ôêÅ|lCî³æìþm‹é]ª8£·î¬—*&ºI±iºAQº(ÑÜpƒâ¹ñöD¸æ¼Ù‘|wÍ!óŸD;õ27^Ù}7ÐaAXM½ÇÃas«æ/{¸ÙkvvÏWúO½µ’î¯F/U–ÂÍwÔwúLãʾ¢«[¥ÿ;øûƒûûCÍ4›:÷!ØêÖ›hq[¼šÂ N0Éò랟»hÈ]o1<œ¢LÀ©†êän‘̱"hyü¶9“¡âL¸sÙÞiÜ Ñ§5Â#ÈæòÿiZî‹‹pû‰ôö±8ù4%'Å'ÊäJ­¦Ó•g0:ÍhwÊÒÍh/½sNÓêœá&yl½ã¬n¿àL{»Ùv(YŒ{ÂlŽqéÝ yØì7ØÝ¸¸^ê%ëMZ7عÜ$§»F.5ǛԢOmŽc®÷¦9Þ˜MŒâ,f"Çéæ3Ç;ϬäXï9‹ã¸æ•vº³)e,A¹ÇˆmžŒ£ë‡¶¢ 9ø™ªÞ>ö¹)‡õor¹ä‘QÌ¥€Y˜ÍŽYv,Ï¥Œ97\¥Û3·Fã¯ÊæöËèä&¢Á âÌýö ˜W9„op°ƒòÀ Ž- ü³_…ÄÊÙ® pD"†¥XÇHø¡ EÊça'ÆealÖéI‰ZîòѸî´Að1À ±aq1–e*0eÁMÓÕAø¹=¾< Éí7þÉætSôø¼l¨€Ì ÂÎ{|„™¯ekÙ0Ä<0G|Â@I®³pD+ŒÈq%0CŢŜ; óøˆÜ8ŽFPÐÔ6i ³B±åÒ`ëpîwޱT+~,tFw§\¿ù—8)y¿ºIYÂz›PÎ9ì˜ q/Ñ¥ŸÏ9E7;Qt-$ÎsC®ž®„rì0>Ö:mµk"ÔŽŒÆVÐq'KÚ£(8ݱ NÇqs¡Ÿ 8]q §[œn?oi¡aç,Ç^2ž ØMÙÂ7“XùþS¶Æ”­1e«Ž)caó q)·kŒYjëmÚ)Ž! (vnÉ,¦¹²A†g© ”¯C¯rØ"¡G› ¦kÏÓµÿƒaº:7mvgBçj îZƒ»àYƒ»4Ù×à.îª.`8§ÿÑ÷çºeîÓu®½ˆ!¯e¹|âµ\y<¯¹ƒÁýž…Ðkùj…5J,x«]=ðÏM{}O‚Ë= ìš„ÙoCø6ÿ›¼»Ü®.8P÷Ìi àòÎ ˆßbÉB1ñ£Qd™+~,<¦‰x¢Ãë>d‡Õ¢Ð§"н4èG°‡Hãh<„ ´Ç®w \¯³";E¬×ŠqÑ ~t'JXbw”2ÂNsœ2„]+!ÂÎ ’å€Ç²ÇÁNþ:awhÅ`…Xá4!8&fŽá"j;”%\+ÜN„‡XÄ wBjy0­Vl˜– £•@Ë5ÜЊFg¹A³\pYÇ‘ˆ,'8– +‚kÈngÌ“Kà¸ä (Ã%ÎÆR[ö< QT¥ †ƒÔ¡¢ü÷_‰| #¸VZP³X½š}‡^9u¨L§šMæ%‹õÒ«0$¢½³E·Œ×Ò<96 3ææŠ¶Ð ]ÐÓ®Ò-沬ÍðDÊàÁãcã}1‚ÓBÙ ` l8ÿüù û*¹/Ю€¯Ô$H vWr„Wx— ñ3&#Z`W‚0|‘X$÷hf21-Ì¥E›YˆŠ€2ã.FÿŽáϬø.\õ¯h¨ŒÛ[`ççfªØÓ€çÆ6LØytvQ‡3W  aÄÀD-Ä6’-öó{7|V!ç¡ÄÀ8ž&s–0›#>´;cαç`³„õuÀ*eEŽ3qºé"’åüº"øÖRGˆ]*ø:Gp‚[‹§i™S§ÔQ­<DÇ G`W‰ Xé''HZåQ鎴0:Ž» !îÖ0ºÅE¥+ĆÑ-.Ž]bç ºDAã ›wÍ&}n ä[ùÖ@>°ŒOD^Û ù” ßUœ(o‰j0‚‹ ó¶ï <øñ EX\ƒ× @²Î˜#þ¡ÂŠâã}“„:  €‹8Åú!P„>S|—(Â"‡×8ÂïGxì¶GÉÂ{^|=ŽpïÆî-ŽŒ?8®‘„+Š$Ä€™ë`}ßk°>Ä–'ˆÖ§M–/JæáOµŒ>4‹Y¢°£öB–' eJ֑בõ幘;Þ­ž<–Ä HœÄíu0[txÚE!hÉ ÆÔ&ŒweíLC[K4C2ÇѸÊf4,áå–6àcÔõôñâªdðÑ|%}Üûè×qW*î£3ì4E}¢F€tû-Ç‹ŒªwK2ü¬J,I«Ì‹¦g¹cIÚŒ€òÍqÁ;ïp’1ikÍ'¢dÌ8‘Ü3N‹Š" $ïmmø?§–Ø{û()mÞ>ʨ·£°ßDøe»„÷Tàò1£)uQJm‰ÃlŽ+vœ¸A‡­…g9In1‹*”{Ó9̧ŸT)w-†¡B"PåÎô8‡uÇ–“¸Db ̉§K´±qº¼<¸=šÙ¿»›Ò÷Q«8ž_dW[1…ðcµ{Gg<œÛ¼  Ñš«¹dªl]Ç]E€!rìÆ{*/^óJ½Ê_ãpšY…$#oàwZÌ~”ph# ιJ@TÑH.¹4ú°}žwlx*ܦ‚V’L·6Z¦ÂÅÍ„'<›àù"HTÔ !׉sáªÌxéµlí6u°i æ8kv1Þdr!Òo—/æ 9£p7̱½4æ˜v)UªÙŸmމeç›lûÖ*Ò™lº·pè8Ùž“í94Ù`×J|wBN»I“HºéV íú`åq¤ö‘m¨y“ñf>â˜À»HõŸí4h§Fï44Ú´¾"Ù°naA§}ôÚ‡Ü+Þ1ÓÐ…‘  V#)Â8pϸTÑ3z‹+µnìÀúvqÂÆa€eÕ‡õ#Í_…ù!q 7ÊáëÝèéùe*ŒyxĽ6+Š'Ú¬èUËȇ ²8±SÓ†éð¼0|à ažË…£ù+O¢1"/¦aÿ;Ûd?ð¿7âo—}0²1ºâ¸Xu!NÚízD§±©Ô`xxJóü Ó¤aîBèŸÙCPÆþÏv×ÙÒ•¢½¬Ì€ö]¶äx߫²Æ=PZAyÙl¨’½ßÅÎ]]$šò+‘TdUŸŠmh`šjIÊv=͵ÕbúB8y!¢æ}ÍàÛTk¾‰ªù&Tó¦f!Jª(û¤ÿõ¹'9N<RÞ&/À £%¸Âà±ÒÍN ÷ÇÞËGvªt&™d€’‹¿e+‹Ô˜Bà²t~?‡¾½P@+z6!Â|*“ò-Õí}|íß¶ét?׸iø”ù™ÀÉ6”3œ©§ÿ¼f<¯#va!Gµ»7ˆ©$I¤ætjn·'ÐÀ$‚qÑØ–Ȇåcû&èîÓÊ(D/ã­íár^972%ýç5›ð¢¤1L Æí½°Èm¦|LB`1À *ŒªøNÈüR]¥¾ñ|µá;Së%¯m &A—Q•åÏ0/˜®qWUF^ üÙ= øa0Zì1ÇÒn©…Óß¶AªoÂòMk9«í€b ‹’Á€‰ °ŽÔ¯ÇÑè5°Gª®Lr|G…~Ö÷IoJû=ªp}ê=>ÞÝÝ œ”xÇBXÂǸNÅÀzT&=²¡áƒ@·WZ7 =öêX:2•<AK»´ËP1û¡äĈ†ËøFÌø¨ÚbÖ‚äÕ·t³ñ@™ ¤&€ë?@ƒuj'ÎBêÒ¨u:¤ûŽJêwåF qJÊÕêu»Ü­yH„îøOíàpü9’*XŸ"ŒfB ËaŽÏ G;0ìatû¡<^·ª€?bÎmpÛ†°[è€Êú_Fì0ƒqùàž*Aªô­úÆÃ¼Ðè¨v2å»]çúuû<ù¹»³Bªh«Hábˆ ;©1 Å.•Çc¦lH,C)ÏWJ}†Ó2•;|yÒïÉiJWNE§I½Äwç<0&sƒTùwÒd ¡|:`êþÿ¼x À÷L¾mÊ¿hOú¡8^€[Ì›ÒÌ+åMV=C¬tüoIa+Tå<À]Ò¡DN6]ô'¶YŽpµ "Ï`óù*_öôY˜ÏK„RëìmžêA *zÑù(/Æiô ØKKVüL}íz”i&Ÿ‰‚çì’KoØSI^½ü?Êëµ,?¿E,4±nÉo9P06Aà阊ÍÑX8!/ÕÉOßÈý`2n_`E¸íO¿ô©0~“ßÙG{ýûý y#01¡P­ÈAªâ3y¡,ýÜò¯µ O‡sÇ5ÙP¦pÕ,Ì ò óF÷¦ƒÞãàß°»ƒ¶ÿÑ /¬%}š0GŽeSñïņ¯rPJ"Å¥ôŸ„ìU]ˆ:DõŽþð®3€ã™é§:h·£—á½Ä¢äOºlA7¥F=—aÅ\)w;eå8‡Öçþx0º'_t£zÛ§óÞwòió÷ yöµÉ ~UhÅË„6a:"·ã~ï3yy–óÜ~#“σçg0Ìx,MÖú!‘`ìØ¹õª8­€í¦gQ†¯ »óùü6•Œ»tR“†¾^…]ÿ~èø/0lâ¾u¼»áb\Ƕ¤ûPT…ç Á¥º£ycJ¶“ú)¥›nñn„d[ y”ðÚᾇ¶Ó®þ¶¤è~…”jÇþeý¬êS­4Ê]`h*vï~»¿}ìMK;iÖAÃÁÞ¿‡ø7_dßé‡ýâáÞ)J{ŽýÃRä ûûùÒ_H>M"L“½1%å÷—ÇA?"MöÕ+ؘ<ñþ®ÈÃ&ñUûò¬]n‚ -wKþN^r°ˆ„Ä “|%YòÁ+ò=Ñî…ê~<ø£Ñezdò °x(ô0xìï`†‡Á˜¦,”ȸ7ßO  ~ú‰Ð\@W³{~¤ôHÕÉ7÷ƒ131 †Ï/S¶2>‚%ø@.%K¤:ioJ6Ñÿ‘4ŠTÁ'å!]ê‡#÷¤ÿµöfŒ¸”BAHÇ]oíÝN{ÂWê¾ÿØŸzEc;JPiÜ»Ãóõ‡1Õˆé;,côø8ú‚kï1mİ?ù~Þ`¿Ói•¯˜Å|zÉå)8÷^uÞ]vÉåu÷êºKNëL{ã™ă¸îK)g„d³E?]ƒ—gý”À9!Éã®þTäö¬> pŠéÂ’Ìãß©•Oáð¿V®¾£ï«—í“[1îå8×Kã5ÛmP‰È€.•Ì îy,ƒgßÈ{Id_U‰ß=_Yº"~¬\vñ*€ÂÁÛœ1üËÆ xý]c_û¾œò ØÁRçb–|B­6Ok/ÒAß'Ç{½I·¢â;œ¦®µk´³Ç_úÆÝ=Õ§ÇØy´G”žOOrFuþgÒ˜Þ‹\XÃüasÈ ¸Òìð[p¿‹„[Ò®Zx¡Â>KH?D]aÓê\W:‘¥A¥”yÝÜd¦Ù÷ëÔ“Ì"ïìGR?—7±¿•š­X̤"XDNøœˆåA­Nљҡr‘X-ïâ© 8{‹ë§—MyO£|ã‚wk€,ëŠÛ§ØU<þŽÝ°¦±nò§Ûéb3ª<Òm[¾èÊ„Ÿ+s?õJ8rÉUØU·$½¿ê{Þá&Ÿð…WïÚ§më­Qâv,‘7p –9c¥¨–Žß¦à¢ÈŒÁ›¶ª+¼ÌY«Õ`ÖPY.7eIW{AHºmùn“È ²ätºûŽ€ë„¬Ù²pBÇO(Ù/âù&ƒ•"‚œÏ¯ñ\†¼xñ’¦zç[—ªï. 9üSdJìÏû³W0•臚<™OšMùʪٽ¦³¸” ®R2 퇦dÜžýÖ&s¬«º¬2ÎíNŒßv7dÝΟeÅv#b¾lÈꬔuÕ܆¬‡º”ƒÚ§Ó]S> ‰îm‡T·@¥òe8˜Šû¢`Ó>ymå¡,KÕ;¾—CÞ3Uepûí_ò=Gx°Š8•=ì=ÓÍüÔ¥ðv­|²É´†AÚÆx[&M÷^мÎâÈ¿ÅŬÊÂô+ŘW­Ì—Wµ–T6®oÙ"B׺n¹{ úÎF«ö~ÓEâœÀo7nç{°¯‡Hâhlàݾ߃ÒÎÍ^/°›› ®÷ú=ØÏázº³; ­uO¦#f¸±âyè _Æ‘•²•Ý\4´åî¾|êÓWcW„ ñ ¤ç}4y÷ï£jbºAœšÆ£/ožz¿ÓÚÐôØûFɹ>®îê›~÷éh<ÞûGø3³‚Õ¦œ) Øù΋•ü,”x9ÂŽ(_Ú‹ýê*µ¢ø[º ƒ!Âw0ÎÏξÁõb|qu GT ƒÊòø©9Ȩ¨=eÑѶ)nfÃk/‰}›Œ{ôQO›ÝðøGäGX:´ÈÿÅ»4ÍI·&-¥=š&)­*„ФþÈÑöµÃâßHTç×£úƒ_€z®ºŽ Ö¹!v3 »I¼¿5ÔL´êD´²â)ÜØJúÕo%|VrÕµ•PåF`£•¬‘¨0+¬øpâ¡xýÓ[ofJw:CCF¾ßsa~cHóøDe,FµÙ$ ïÎä¬Ã l˰`m½G{ÁåÏ¡0#ZÙÛŠƒÎnÄžÕWõ?CPQ&íUÜ Ä›ñ Dׯš^pâ¶qMEW0–\gÁ¹N]Ñ…¨¢óÁ¢cQÀm¥ëC #Né6\ì`Á†%zp÷É[²yF±nÓ¾iT5‘àaÉúD¼m L#rÇŠ˜Õ€\ ìz”# ev Âáv…=ï{ÏT7†áÁLÐïb£i䆽¢Øß£‡§‚Cø¸ŸW›¬ëy ð¯jã’² 3÷ù¢O¸–€_Å&»½îî ž©’ˆÛ-étþ 4]n° ƒÅ K8ê,s¯™¥ 5ÄzrçÈÈ3¯p0ðmûÎ%2î(T!Ëÿb]‘}zD¶ ‰×néÆŠÇAïvð8˜~c˜{ºgæ§{ý¯½;v¶(íkP* ;Ь¢fî) ’& }`ê"”}Žðé¨õ’æyÏ9 ¯ùíçêë‚÷ú<øº*nð…€ú@5<¼G¸M` âeno¢û?’°}ÍÒ&(¿m{áèÛÒ+ê# QU«mæ1Í:ž{5‘Ë!n ØÑ'Ÿj—¥æ™•›G¡ñ,ÓÊŽž2îÔ6äŸ*ÊOü €¦ç;îÙтʮÝd‘ü+Ü1X³ Wû. à†7fø®Š¯UæP^­ê aI ŽæþüÂt¡¥aÁ­ðjâP•Œ–ç{j9ècG° zƒÙz}OjâË)X@ü~î®û9Ã~æ!r³U'*4wfèD†œ¬v1†}B ²Èkšñð‹ )…ˆñ§xw=Å×Süûêgÿd~2%}ª¥IÊ6zC)׫¡ÚœgÇZýÕ¶Åó*4N,i+¾R=ü …áŽ{Ñ-ªK¹¾Ûñªñ3…¼F˜}žY`•,2M¬“|Û£JÚyµ_öð{8ñrÕa<®Úûq¦qj|÷õÙìœYÖ<@Ö<ŠÇšû+ÑÍ~Ÿûî}2ï{ê”xÌõÊ JˆC%B\:†Ë*ùápAwŒ_ ›·õÛQºÌ‹ã‡*Åp@}û¦Âö3ýaEOhdÔ²pŒ’ßxïl‡¾ññâG€u{Ö °+l‡n·Snj£,]‡07vÂØa—‚ÕèÖùDwל6„ZR³äMsc<ñ ¯¼lN{[]vÀáÑž‚¡™Xô'~Ӛ檹v­AsÿZ#ÍrõÄ”õ!¡@ÞóEG·R£E®¨²w¼SÐ\§s¤Á›Æè;% Un™:k×Ê]¼ÀN%Sà=ešß<§£–Zb^.1T‚|ñë5p[zWÓøåÕ~­5À¤Qî@¬Ý Lw$ò²Ñ¸|_oI€xÞæ÷u*Î*5ôónžÛSnžCçUÎкŽë¡»ßDjmON}xzàA1”%Ę^ædJ<Ȉ÷£™ë­*íH¼¯]¾!ú¿h³ê-áíè é–?Öµå V—­ÚIðæ>y6t®+Ây]ö¼KÁá<äÎZ´ÚõÁnp"ë;’çó‹£`§joÀìô¦á“i…””“ë*Ÿõ•Œk †3t³!Ä8{ß¾l5nvm¬<¼{‘®cð®9ôíóЮà݆ v|32¦€¢P¡ï8-†gájn¸Ó_†šaZŠ;p“§©ûŽÎ&:ʆ'tºÐ©{ZÆ« i;‡ÚEeó;ÊÅõ*Œ¿¸ò‘²C{'0×ßöç€/c`p|:*qáØ¸CÂØ+¢ðÈŸú”`TînØ öåú€xÑ\y´ä¼ÜÏc ¨"/¡` èj Ð-»¬ Ó\Œúˆ³Fc8ÈoióHäY[Spðþ§ÓÎã ä .7œ~ê ÉÓ`8xzyâ>-ƒª¥ŒžÔ3cÈõVsÃ'ýpý²ìü?Lð/À…B>ž™W Tþpôòñ“¦fQË™©áK=§RŽÕ½­šÑ@úŠ .þD·‘&~’{˜xÍ SÓçÂïæ u„¼"àâžj™•Q ¾'<©šôgL¯»™eá×R”ƒ÷R”ÅÅ!*ˆÿ@9êFÏ&~¡‡‡ÚOŒWn‰âtYDqºª4˜ö0¶-'`[ö@^@Ó:‡¾6ó°\üädN¡;?«õ¹š=H´BR™“´Ý*{š´’WÜêËPÜìvö-‹pdÞ"¿qæ« "þi–Ù ºEÞ¬àÃxòÖÕÊïÖ¬VÌ3„H@2>I*?cÝ$á©+bžT‚ó¤5Oˆ?U*QS…>M¨Âü)0L&óœå2Šr Õ'ó§’xþ‚Ù骘û¦°Í"¯øW?‘H‚¹$`™NDu ÐWáämSET7©ˆ~^UôóŠX¦V…iÌíˬ"„éëöÙE¼»#ʾ£˜‘µ˜åô-w/+›Ë$"÷‡d0¼!ôÅã7Þ@ìûå…E3dÑõÛ’O{C”éáûÞ¢A•aOÀW@ûtú}ò€ñ䎪†1êédp/ÏŸ‰­“¸Á §»¿-eËCÆ¢Ÿ±"2V\2–˜³$Þι2ñô{Ì ÓGŽ$O¿é/0}äªÅÓðûâ0ƒu ã™™/8™ t«Œ Z4Çð¬G^c¯ƒØëãY¡×á~JVäEM "‰f@bì~Š€êûÉúÀ bh‡½É¸B6h\J´87dï0¦/¾ d‚‚ÁsìSíüŒiCG°üÀaM;Ά…‹ýéL'`z(ºá‡JÑeg‚˜3tx+t¤í.D–ǃº`ÊM€òš<ðV µ¯ ,@Ð \\ÿŒÉõø…½á¤>åð»8õÎ͆PIß[Y‚Ô0´ÎÚèÙÐÙØ¸YwЬ!„jø‰…˜uƒË΂•uCþ¡zËå’1ª½4ü5&² c-°XÄk¸«;ÖÕŠOp@¹Æ¸ºã[(³"[`­q0­î€Vâ ¬1q¬® Vÿ°³h„°j7¥‡m™fò"dÌïŸ-ÈÖØq«. UŽX…=šX55ÁIØ…Pª1©©ÀRcaRRÝ!Fü¾`ÆqXq¨i€P* v¼Š%J²+ØSó%RÎÇBÆ‚œ*xS'ü¨‚8 €NíÈÑÔÔ6€›Ú!£*ÈÔ/êU±¨1¢6˜h¨à0¢v€¨®º@Cq¡‘h1;(Ô š ššjÕbâ?3‘ÌVÚ\1Ÿ1ŸÖM¿R¶ Å«(ñ6½š¾ I4¦ÛcHÓ€Bñ4!F±A¡ö¨.óÕ6ÏSïá{ìí2+¨>!ÌvVŒ­ÀÖ]oâ‡qµ‘ Z3¢Ö§ÕaiC@Ú5hvþ Ùb>ŒYf b‚f‹fZäV1ÌÆè1¡z×hÙ5Zv–ÕãËŠ›€Ž•q²€ª(Ê 2…Ú8HY Eí Fm]Z¶¨¢euˆ¶¸rʴĦ”M %ëÓNáŒíäª×<…·Ô’MéÄ.ˆ×ìˆ(ƒa6úS\ÓKÊÀƒŸ¦F„(4k¼Õx­sýüÜ7Dդї¾º¼˜Ti<"©ó‡£G-Í Ž*v7kj,GÆ Š+]øü&*ø.BY¼ÿg CM†š×P,*»„š*Ìs¦®!©ñ!©3 P%…­žxÒnEz.IÍM×cH›ÚؼQÇø©GOêe* áßNNE‘Ê!|Á©•-3Uv¸)öŸ: ¦”CwÕHG£¡Úñx¹{ £—fBÒ~—QpbW– ¢Jï0(mÓƒÒ¶ QŒÁn–t3b Ü P•p3ÈʼnQÆ“A7Ãip¾Ú%Ö ½<²5€«ÝŸ1O*€õÕ3™*â5„ÀŒI½9”­†úHع+ýtújF[u‘G()‰½mšþF¥K#t«{`ÖÒ¬Yg ê˜uoÖÀ¬³Dý’à«3Es ©~F`®ÜOOn1õœƒ¡ù°´ID%*¢Tì™HŒÎfP— pNQQ‰s`Tâ!Maë¥Gšò¦¹ GB4to`¡Q… µ#FŒü1Yó‡ÒÆ ù£3þ IÄ!dìXw)ëºÁšý\qÍ~®’‹—AƒíJˆtFòÙTñìÁ÷ fßÃ$y₪ý¬Çθj’0Øm>.›Ä v›2Wb»#w¨+„Ðäi»u…ç¥ìv…ƒÝjq’e vë(¾]ètŸVµÛ,—$‰—Kb‚¨y=š(» š:Ö‡Çh7vAì@7n7v)ž]! ¬˜=I‚ô'IËž6[ „€g'Î^þaÇÀºœçÍˬ==¿Lû¤÷ü<}ÜÉgV'Ÿû­Ù<«0»°Ìâ¬]|Ö.>kGŸ½t]|¶„Z”ÿNÉÍ§äæ¿c9EÑ™…b»ðð|zï!JÍ~;ªÔ §áÅCG\—lqk€·¨þî<‘!ýgŽè# œxþ0ì’O’‡×Ã20á”^Ê)¿§'ÆÙ†é›…ÇS‘yOëÐûk?'²½o½_ë&нïyM]x^SçT Ÿã=-QçÔÌ»ŠÅž‘œ¨¼èû ZF³,¼¨Ìå8†ßùO1…”¿+ofhœ©PáÊaŒ8ükg¨P|þ¶ä´v‚Ò;A)ŽO3èvËYôëýƒLÎA cì³XùŠa1*º¾!´¾«ÏGtP}n²ËK†_m<}%˜¾æŠ‚ “cÕ…ßwÆXï&ï”B:·M:]ç»(ðRò¿Wµ.D˜Ít6Ö„Í”îþuƒ»þx§©M,J Ÿ™ÓQsuœŽ¬Ñât¸úÄDz’$ ènñ™!н.%]µ9²’7~Üøñ¡pü¹ ïèUáä¸Ã´4!ùÌ´GûÙ\t ’Ž=«*4}bÈ^œ)"{Òpò ‹ÈíEœ±YÂ%x›…ð-•¡UzJSŽ¶Þ¾ØTi×è$ÊjCV)Êz)å(ëÅeв+dzÑó*èø^¶L¥8¡Ó™ûÁ&6 ÐU‰³¢2ýðçÇE??V}$€«1œR ~ž_Ýàç¥Õ ~žì"”¬ƒŸ»L+mIƒŸ“»ÑãËÓÜ~ãŸ,øÞsPk Q)˜×²#öèg[GÈéù¹­~ö4 ݹ%ÄòÜ¥(Qe‹¼¡mm%Ñ 5hµ9 Ú¡ÔÁP\ˆ«ÐxU¹ `°Û{(Ïîåf R¼2¨Þ s©$PRP¿)÷nÍË$Cû»±Y8~7Áƒž+$<%÷9x®5ž1zÖ?®®‘7)%—˜–úNaËÌüŸ84Æúf‚5h"]n&ÀØ­ 2Kê5SºÇ;7] ü¼·IŒÐCãFÐ #@òkÈóò¼†<« =†`„®èÔH¹]c_ë\7(7œbŸ@!±¥\9Ã;Ì÷ ˆÇƒO—æ ŸÞsƒOï™áÓNÀi˲pš•Âa7³\{ ÓNã ™F¸4Oâ-2kà²#pyypÄ‚¥Ã£j€G°³#¸$ã‚îJH*bÜPÃûˆ®H°a#fø½§JÜŸ€?aÄÅ5Žx#^q6\¡³}Û ~+CŒ5HâŠ+Œ78Â›Ë ‡#ñÁæbÎ| ñ{Ñ«">?/GÝ¿À@ÆþM @±¸•Á\ˆt¼Æ¯ ¶¸¸Ï \,{³€‹Í—|ÿàâÒ,àb¼Q 1º˜£_ËE)kx±îŽâtðÅÖ!w Óå›é2¸“1/⢃Ö@ ߸’â†&AChCx7ê š‘µÔƒ¢Ø¤Â‚‹S_'d®ð9šBSQï°§äqÛ;’üü9¥Ç–ðßÏðwIg1,Kwð˜mr_‡-òZt =õVÂŽ/IðŒùdôÔ÷Wºü»?iŒPž}¡„äŸ#d·h²ÉôJî…Áq",¤,6·ÎËw÷ï gd ·ò Té-”š_ýŸ ª}Li ¤t£á\´‰~-É}žÙœ—§/j q¨6øƒê3x>tPB;l‚4߃Ë=µçÍ ®0t×4Ãeª—:—Ãã\ Y$Up°D Ü9JÓ\‘·(îé*Ù× ªÏg’¨C$I8MúÈrLk‡îÄÝç«Ãr–yhqˆ•õ§"‹ çkJ°“ÄÚ¢=ž7‘ij8ä7@­[“T9œÄ*4äÀ56ÖÓVÃkÒ™—|z¼Ì4;þà•vñ‘›¡àJ›×>Ù$}r¦„}Â2údÏÐ'û}`–ˆ>9Œî“ƒÙøä?ÍÆ'çüE« 4?B ÔðIDwGwÇÑl,’ ;B,"wÇ‘¡;Ž#º# ò 'ÙhÑ…ëý¶ß*Xø·«Z“ƒ×ÖôrÝÚVÛ…~ª¼I^)X‡ß„öìÄ—Í Y¢£ƒ>Ç4ÇOƒIYCp ^bA×bXr颵o˜7§q—j;¡M*kX“dåÿ,þìž…•ΕcÉ·BµÐŸ·aÞ‹VwVÛ].T›¢PР“tF‘:SÙG£gÔÛ©î9Éð0Z}o܇uõ±ß£jú§ÞãéÝݽ€¥Ð³€zžÐÓ]wÙ¨íx)­Ç‚`s,™ïÞ=è!Ø”„fµÙ7#'Æ8' ±*9ÜKò ðJÕLº‘I‡È$o£ÉúË`àÚ GGz‡4jé¾+·È»r#8%åjõº]îÖ<à‚i$.þÈ¿Dt 䧃Mðô0GŠg…£þú01º#´é¦jݦ[(ϧ׭* e˜œ0´©´m´EQ]ÙcúeÄl†lR î©ò ÛºõîÖqwkÞlêNÅÚÉvtí:ß‚µÏ“Q9ïxTü¶*˜€¾B1a—2&9Ù5,ápÞ”ƒr’e`aŠÂq»y†Ó2a;\‘Ö[¢hJ×)Œò±??ðçÁ+Ñb˜(“þ#Û¢ÉÖöÀìéÿÏ‹7säÓtb’@(:ÖÄ8ÀJz8£;HÑ™Ž7bd”¬3õµëé[äÉÃLÄ8š“Ü#ÂØq&ÜõKÌ‘ðË0æñW™£ˆU†&Ö-4!ùà­8Ê9~6î ïGOdøòt &ò—ဠÿ§Çoä~0™Ž·/°èÜö§_úTž¾Éïì£þ]¯&3¯&FêÃÁtÐ{üöÀ@ý½ñŠ™HÎNM˜ÎGÇ’¥¯r¸M"EÜôç ?éBªõ‡w}˜,ËH?ÕAº½ ï%n. +Ó‘Ç:T«B깸+æJ¹ƒÜ!(PÇ9ÜÖ?ÓQÝ“/º¿íSaÈ»yŽ´yŠû†<ûÚ俊*´âeB›0‘Ûq¿÷™P~“òÜ~#“σçg°ÐxìFÖú!9ÐйuÏY/¤õí¦wJ_AÌçóùm*Dw è% }½ V“ýU`ظ#¯ŽûrÂÖ%æ »åC5xœ܉«»Oš/¦<©ŸRšéžøFÀµØJ.¶4š(t­û†ƒŽü:î7ÑC )Õ±þ‹ñ©VåÎ. !mêîÝo“âݧÏý;sŽø{{þàß|‘}g?å÷I¡PÚ;(îí– $_ØßÏïý…äÓ$Âô¼PY?¦¤üþò8èG¤£É"Þ³ÆïïŠ< ï_îû䟓éý`´óé?^É?)W(¿ýtŽ ;Ÿ~ þôðüþj@—MöÓèsŽzìÇâó`ø0úSÑéõù·¯ý1ýù-¨~¿¼ºûDgÏ6K2æ—W´ž‡ûþ9=<ü­Jß¾úc4¸Ço,ã¦x¿MÆÃœºb¢í? ª­_^ý­ÿ8é‡2²ºL9†÷ƒ‡W,4Ë&|Þ"ÿ Óª(_âÖR5½ÔfùU¸áôÝàlú¥’·o1˜Øÿò‰ýLgú°ù³¯ÖÚU‹~-7®käò4ì"÷÷{Òºì’úJ+7äïfNý¿ÃŸdšÅg dë^h(¬Uüó•÷3£’÷Ë«?_ù=ͤ ïi,QÏ»þW2ø6 ‹|xõ¦t¡ù¯âÓwÿ›ßÉçèÿæ$ò!êåMÔK<z ¯ð >‡'Ü ò€Ž>Ó ÷ŸÎtü1z<Å€J °Ev·14(¨#ºšÆtô€4d{²ü¯Òý‚u}*ý*r?ýä –Ìæ~‚øù¶øúCˆ# ³„2®ÜÇÓo• û§çM2yÈñù?ùØúã§\¡°õöm~+@7Žñ[¢$U ˆRÅ”›õºæ'±ÉãÁ--!4îz?à¿ +tƒw¹zU°y½¥%¤ø‹2¶ôT¢uä)¾]p?§6SúJ‰éS;Q¦6#R÷R"5/Q›©‡)‘Z̲?ÓëO7"ó ˆ,$Ÿ@)Ìò¼ŽJ·iŽŠˆöGå"í⦾#yK0óQº‰Ÿ”Òâç}Rç:í³%Ò:ëé—? lÌŠË­»ârkV\œÄÝ­MY¥æÖªÔ,ƒj£¡Ò,à2%ØQÁ±œŸ× ²ŸÁù¹,$)\ ѼXͱ‡ Yöm!†èr 5Ûå%Å©–T*˜V™ ­n+á­U‹\]RCäÒˆÚDô.PÒ&¥wQ‚6½ ”³3ôï¼Åì ¤Î[Ê΃ÔTùÉ7gU“ΠÊCþ€*³¯¿#eúûBÕvqrçe-0Ü4I•ÙmòR¡/CÙcvÌL`fj—Ož^íZ¤¶¥£m±3$‘óœ È›ëüÈŒ¾4LwÛ×dFÛ×$lûò[»ð5ÓnóZì²iÚÑ…¢­\6B—æÏЂÍC$.ü/5³[ëí&–….÷¦mÔ"gv:—åÎÎyÎëd.ú€.5ÓPQžÝU”çU”ç¤{úl•“ç6ôÙª%ÊâïU²]ç-$:ô_¢y–ŸuÙ-œÏ3l’3]25„-ëP8?¦Ë†¸Äútì,Ö1é bòëÅ:~öìÕšVóÃëá`Š=ã¯l©Šx$Ñ$âç@¥›¸×Qé:ñf§Ñmj£ÑÚ™²ˆ‹M£²bfÕÎô(ŽM®Ûš2¹Å„ºm˜S&Tf€TWVŸNÍʺÙîHä"'{ç=׳ 1»©ž=µéÌôìét™è6uÆÝ>Ñ>5Òã7;C&Ê¢>B•WÓzVd:ê52cɺ U›YÉ4È»$»õ§Lq~!ívúŸ>Å…´:Z8Ò'6;µ,ê¤`Q"Ë‘ÎK¬T.@`eAe¦ò*{‚SWs!8%i5ZÓP-Ý@¦3€L ‰4êô•ʨ“¬ItT'g8™‘@GEÒB`ÜMsú*䬚·Ìé«béÒêõhºzMÔAÎüg#… ›4 è›ëœÉ‚¾Œ¦Lö¤ZgŒõjâ~ 5™ñj²üÇP“•8† S9‹´Èæ*šÆ¸#›c¨i4KlŽ¡R%7Ëc¨T Íðj’²^É1T˜ÈENö$Î{®gAbvS={j3<†J•ÎTŽ¡ÜÕ™ÛÕ™ÛôÔ™,¡RÕh²<†JQ©Éò*E½&Ëc¨lT›,¡ÒV²?†J›âL¡Ò&6Ãc¨TÕ² ¡RÔÌ2<†JQ9Ëð*ý,Ãc¨´UŸÌ¡Ò&8Ëc¨´iMåÊ]µ|žQµ|NÕR–Á1TÚf² Ž¡Òµ‘ep •®,ƒc¨Ì¬cCe`qJÿ*msSúÇPéÚšÒ?†J×Дþ1TfV¦ô¡20Ý$_\?öÇtmÍ;ÅÎÏ–RÔh™gsëºñôštcÊÒü¦sf\cá‡HP´Î™Hp Pª%Ai>Aånk„Cå¬åùX•;î¿5µ3á>m¸éq”kÚÌçFA–¼çLA¬—¬î”8ϹòbÜN·Ò¤3HpÈo R0YŽ,X˜ëhÐjjóë6bæ$àc‘‘¡¨·Ñ{îÙÙTbMP±0©¯#a.Lš€–ù¬±¨ÈnM°‘‘úêðì¾:<ϸ:<Ç\RŽTiH9 Í ëBº‹‚…ÄKwEˆCƒ?ÝÒ "_ §+fœª¶’6?ÌJ‚•ì±£ERΦ» ¼,aga—…_Ðe¡úÆrYè¼qTÍ ”Lgá–v_°e VÆjè“qô¸™48Wiö<›4{v•fi+nî¢,m-K[U‹%ÄÖ=¿d=ÿ'Ðø×eÃ]ÆL^lñäÞmÙäïo ʼn¸Ñ¸û®FºµN·7f×ÚíËö›Ú‡z·#]ˆí_‚·ˆŠÛfܤ}Z®7"Š$<)­”üç«Þÿ^­4Ê]¸»}0ü¸{÷Û¤D;¶¿s—fù|þ`oÀßÃü›/²ïù|á Ÿ/B¡´wPÜÛ?,H¾°¿w¸ÿ’O“Óó2™öÆ””ß_ýˆt4ÙÃCÄ{lLžxWäùÛ`x÷ørß'ÿœLï£OÿñJþ‰rùGå7¶Êí|ú)øÓoÀCðû+ÿõÑgÝ%ê ~ÁTÒUèoÙ⮹6ýoƒ‡ûþÞh^¥oýËåYÆMñ‚]8?öžú9‚‰¶ÿ€ªè ûÎÜ`F~ ½!Çð~ðÀo²ç¢>óµ?ta|TKÕôR›åWá†+ÝÃþ´OûPD©7µ³rƒP™}]ÑsUn—›µn­MZ×Í ýó÷{Òºì’ú[µKU外'“$šÃ¢Ï“ØxK|ž]ÿç+ïg~O|€8ó{šIÞÓX£žwýͲIPÚbE><ŽzSBÊÿUüoúîó;ùýÿOå¾õ²õ×’·ð £—§àð„;AÐÑç`zy‹O1 l‘Ýmr×{|$ÓO}ª|> Æ“)™ŽIÈö.dQuMÁº>•~¹Ÿ~òKfs?Á?ü|[bý1Ä¡…iȆBX¾\ú­Ðcžž~¢ï¯Òå© º²ª'@âM_#  3ÔoyñŸ4ò* ,d%粭ư1Ç'n©H[â^‹è³¬èr¾§žRPUMèµÕ!yN»tt«]ºhtiIž7ÁŽ7ã:ôqT¯õ«Eû*÷ûÂzÝñóØüžW°"Ô¯í«Üï ëuW„i~—°"Ô¯í«Üï ëu·P+ñù½˜p]*.†îU¡:‚Ç‹NTÁ#Fîv£9Ñ>ØÕO#™ _fÂg »¸4ýí“]Ìr¹O··çEtV›P7ñ7“d³ÿ\~²S]"CvD»m•µÞ&Í>$e)í+³¿R¤¯p¯/‘q%^_Ô?^_ ÒW¸×—Ȱ’¯/dŸ¯¯é+Üë‹4ªdÈìñ÷žÉÍ©±y|ëļˆžY7OǤ23kg¾o•ÓbêyoñÓ‘€T§jO™Û\\ Õ‹°f´ãŒÃ×IDHÊt/Îv5·Ù¸À¾Îº§á«§`Ü H­7ÒQf:„2k>~šò67F_¸§Á¢ñZŒT$ʈ×òý"|ÒS˺´ÿ0].üŠ•X¹sç°åœ™j™ƒWˆl©³ù¼[ª5âbi*±8{Ì™©Öpö*æìU Z¿fM¶«gw ÎN¤c¹îãg¦WÏÓÙmÒì`ΫÓÁ>g¸3s „•. ϰý™` g»K³‹Ý™xYº8î´KDqJš~".N´Ù™àY¸x1ÏÀÅ‹ïâYtqÁA È’ìã½,ÀÄ]½Èý_ò®^äöoV®^Ȇdf®^ª—dï73W/dë7+WÏyc’?Ïsã7+'¯L÷.hÛ—‚PÎðÐsVz“ñï ÖŠâ%¦7Ï@°cdÁt98ÕýÓü8x!'âà%éà¸ì´Ý³ÝJ7Žsx,R»CêÐáqxàgqâ¯k7O ÞÆ\R=Kf”÷çöõ²¦Þñî:-õRïëã®dM¼ã½v6âu{ö¬Iw¼ñ.éÖ®×ß2›tÇÛ“S%]ízM8Î¥iÅJµA³¯âP˜š±Rë«8†V¬T4Ô*…©ólÄáÂ× ÙeiÙZ±Rm˜}­Xêf¬T#f^+–¹+Õ†Ù׊¥nÆ<áˆ×Èr±(j;Wëyf XòSY"Š‹ä V‡…Ò?ó°hšqMX4ù©,K3®³Ð?‹55›5 ¸ Xòg_ôsxñ-XúS_8ÒX9Ò\„ß‚ èw³|iN@%òíGâ1û?ó]*X¥&,ëéB:­X¥6,éÙB*X¥&,ëÉB:­XìÁœ׈lÌvs]#–¡ Ëzª0ß5bÚ°¤g s]#–¡ Ëz¢0ß5"£…9/3nä2¢E¨Ïê4akðÜW…E’ŸÑYÂ"¸?c#FÖÌ“æIÂB¸?½ƒgòÃF°ùoÒ=™÷Þ`‘Ô§/ûg¶/VöÏ™ü46KÂýKqˆ¹hÙ¿@îO£ÿ#ȇ¬I“XI“XI“•õHš¬´G’Žz©÷—Û#ÉB¼ÜùËæ‘ƒtk×ÏÙ#)MÒÕ®Ÿ'à?n+Vª Ëzf˜R3VªKzj˜N+Vª Ëzn˜R3–Ñ#)»µbž€ÿ¬ÖŠ¥hòžÎy­XŠF,ééá|׊¥hòžÎy­˜«GRv‹…þ"u‡†¬Ö‰E“¿2IY® ¥U<’²ZMþÊx$e¹¤kÌ_ô0³1±kÀ¼É_¤ÌÖ€EÓ¿*IóZ9–Ú#)³5 ýn–/íy¨Gþ*{$ÅmÄ*5aYOÒiÅ*µaIÏRiÄ*5aYOÒiÅz$e·FÌöŸÕ± MXÖS…ù®ËІ%=S˜ë± MXÖ…ù®óôHÊn‘˜q#—ý+Býªx$e¹*,’üñHÊj-X"î_f¤,W€YÈwÕgºAH÷ dÞ{ƒER¿*Is“ýs&E<’2Ü, ÷/³GÒÜdùðƒÅ#iòmüÙÝ#I¤vóH‚Ô!$W‰¥óÈ{ƒ•Ûa# 2ºeM©ëÕÊ:JånrÑIƒN7¯";ÖN5ÛAJòJì*—”äyìæb–›m5 %y%våã%%y;^“ëÑTFb°qHéËèJ_'ZÍ”êLóîÕŒ»ð^uãØlz5#™ElònÍJÚ9`nýêÊ®KѯÎvæ~-æ$\Ó˜\©ëNjq¤¦Á¯ !vîý:'»xjçÎs±‹éÙŒt7sT‘Û£Šnö¨b<ƒT1¹EÊ$KÃTq&ËTŠ;¨tËÝe¡J‘^g‹„^{'GBöNúJî*&—œô9îl±˜Ï#aG '}¥wæóå&}Ž„»š9гnÆLØŠ M3N4GP¬SÄ’©Ž3S‡±—¥—9:Ë^ÎLfë‰ÎÔp“‚´Öá ÒÏÎì¼Lýì.¡Sêg78\&¹˜¸ŸÓ%:k„Iž_?'Ï‹ìç„ò9Õ~ž›€Nµ£ç$¡ÚÓ‰EôB{:¡Œž¡§Ãœ¬d´}-\ ѱy#‘ñuf’SÔ9Cô¢úyÎ2z ¨^sÌYF/¨§gÚºôôŸðœ„0bFŸÉ[6ñÈ–¨éy<N6"S(NÈU¹Ó©î»éÖ:ݹ<%µvû²ý¦ö¡ÞíüßáO9é „Õç-Áâ¶á!ŸÐ>©7" $Ûì‚•rÿ|õ—õó?ÕJ£ÜÙö'ÓÁðãîÝo`€ÂÎ]šuäóùƒ½=ðo¾È¾ÃSÚ;8$…ýSÜÛ?,H¾°¿Ÿ?ø ɧI„éy™L{cJÊï/ƒ~D:šìá!â=k ñþ®È³»ýŠlÜé7ø¡û©OåÈèã¸÷DÒ#Uòe܃U‰<ŒÆdrbZØá©ßÓiHn¿‘‹þ`Ú#Ý>¥ƒÉ§Á»…Ânáøøˆ%Þ}õ·Áðîñå¾/xùv>ýü~zxõ¦äôðð·Ioòò´y7N¦„Š7²ÝÊövû‡þï´[¯ð@yÜŸ¾Œ‡bÀ MÏR„{õÇhpÏkøúü-PûÆëé=>ê~û _.ôx¤ÞI½á¤ ¨XT&hÍ‘›Ïð‹ß4l€ÔGwšNÂö¹öÑ¡“ä:†ã§¢¶›âÕ„ÅD ÇÝ(z8Âåˆv0ûë“ rëóûÑ4*}¶±Ñ«v$Ôo¤Z%Õ8rñ&’u䯣éÇMoÖxÌë}ºó>MÔ1Àœ½Ümî.7 uºRÁ&q”ÒÜ{¥ëm¯wÕÎ@"Õ´B/|ȱjnr¬šo;Šv:ǤL´|Ñ •:¬F'I¢HûÒ{vïW3a®3ë waˆBÈ&½§Þ×D øv‹ü“ªéÿïÿ±7ðe‹W³™—+º:¯Oaõ×…ïK1ÖêÅyê{ù½b)¬ÿå×úß<¦ÿÁ#)q';W;¤Ù>ö¿åÈÉà#UéIí^ÏO}:±ª£ñóhÜ›FÑûjÜ|íß“Ÿª¿ýD¦#|E`#9ö©9¼'ÓOýÁ˜Ü÷ï{,óDèð4G÷ƒ‡-€ÖßÝ!ïvÈɈîªw‹¥Ýã£éœÕw«íò i÷'ýÞøîÓŽªKþs2½Üî|úiR9%á÷±ÿôÇ&ŠÑøLwŸzc²=›ÀsŽ ”'þw˜ HëWU%_'|¼÷Eùל'•¾úkbªÉþÍOú:ò•÷ª r ^r¿ç'øµ?|y"8‘ë¶Ë­ÎÕe§FpDL~ìOcÍMú¿M¿=÷7E«þPö¡„Ħ£¢ÖéþÖ¾|ÿ[ó¼íÁ3iuä-mýk¹,Óÿß¾Ôo“­§Þããèn“ô´µMSoOÿî„.°å™Hèb“ Þæ!ƒn?Ñ_¿öÍ!ìíïðö÷né¿Ê[¨÷¿€–íÁëßÉ¿íý­vôÖöï¯ä¿y |‰ÁQ Z3±ÑÐë´ÛaLa<ÅH–sPtŽ|͉‘âcô-'ÆC´aÜïo–ñØx<Äk «— ìDY¾AŠ‘¥¥ŠþÇxÉB–oR*ºnÔNë­ÚI •ü©Nš±2g¢g‰n"pÖ×0~N3™¬“aŽŒÁÉžÙÆÊŒüç«À€Ž7ìGøÄ¸ ¶v›šd¾•Û`ž¡F¹ß¥œCCl8ke÷ËóãèKP³o÷ƒÞÇ¡`¾»Z¤7ß„Yy{}Õ¸$@fà÷“zùŒ.ä7á© (–€µýðÇ %²×¬ýÿ€?ð:õi3Œ!ÿ‡ñøÏ]ø#[& tˆ·@ó×Å~BÞ¯ÞçrCõ!ÑëIsÑ÷r™’8UÞŸÁY3I4k|u%æ¼!Ë7q¢çMô´Y®Y“¦Ö„œ‘lâèÔ#vZüZâ϶H¦‹oQ+@¤:"éßqtvOcQ2Ã:‡Ë%>¶°âwËl8tZf‹ÔËA…uPÍ ¼çWä½hØP«jFû6NÈŠ_=V s$\× “ÁB*sx¨}u“qZšJ! ]ŒIñù…3™gø ÐÜ·¼Æ7ƒ_¼ß¡ýo7é‹-ùWΔðÒ66ɶ^C fFÀÒR=x•¿G×Å»Š.ðîÀ~.Äë”Áìc§ˆa1w†N¿·‚]#l1·f ©g“©ÓH2xÓ 1“­ÔDDÐj&iH`´œêeIlk“-³Z@*àøÓ¤ôvé÷oCú,­Êf- 6  êòQ³’ñ5 £B³ÑŸò\”dÔVàw)WPù’‹«_‚ÒB#'­Ê†EbñeÁŽze¬ÚV³[ÅÞ˜pA©‘‘†Aa"RþE+uÒ1¦|ôºG”(6ÜŒ" ,Š&»È­³Ý*ÒÙúò.™o-ï¾3y§™WZI—º2F–FÆ)B.Ãʉ“ ‹Z~"Wž(YWØ™¤³ ØQÚi?¿štdÝ$R·3I2®Nò®ž ¡Ùš lK¨ßfdùìbYEÕk-¾o41ª_B8duT`TÇ‚'<.xN~tõ”Z.V&É”Û._ÉÒéó´™ì%ÊWY¶¹I³½. 4ÛÚ-nÍ*ÑèD̑ϳQ–{¿ó9Fs˜g7 ?ÿù¬™¬¢6áÙ§i ‘c¨ì Ë×Ysõb)Vk—̼±Hͺv†Öйý¬1~i¯ôö%£ÓÊþáʬúHuGžA>»Ô­nø"%J|8Ô³ÃþŽ’&KØØ}þAövkáµ^‹^S³ð Ãt®" :vY55˪0Vç9ÓQDS:¶¨µhZ‹¦åMkÙ„ó|^²i’ŽlšE¯²3l³,I+¶¡¬ ®E0`ÿ©¤š¦Ò2<)¿õ›b[ ’ÄØ~ JÿXí'!+^ðcE»R²J‚±¸—Hæ¯EþZä¯EþÒŠüÉ.ò'óù“ÔEþ¢á~¡G‡ÿœv¢Ž±Ÿhüç!ü¾ÿmoÿœÇÃ&ïUûò¬]n’°C·ðjíR®ðn¦œ¤]+7!ÛèÿÑ$¶Nïð¬•Þ¤OçÊhˆ™FãÁÇÁ°÷È`7 %Ó]f?ÑYÿe0ýô3Ïš?¨•OIíkïéù±O®8Ýþ×)O±³C®zô·þ´?žÐo\Õ[ÝÚY­í“׺¼îòwWeÚÆZ×» /ßlùEvîz=ZÞ`Hª£§'J¾¹äzµÜ©åèïÕøïMŽ4/Oè/-ž£qyFÓH½7»ûu5F´2¯F¯žPwNËU3 ~yµ¯´+ “;/·ðÖ+¶ö6¼%]}W«^äsìoÿ-ò¿¥yW+ŸÔÚ~ñ¼?néRøY*·zÙl^¶$rwé/t”wy÷´t=¤vÄIoÚ#t~Mû/–Ê>)wË¡®Ø=Þ9<Ø?(î×ÞìíÊ­ïß½L{·”[:š¢Þ·ëÝðÜ1¸›ªÿ6ÇåÜ÷§½Á#„„²ÂóË4 loi´¨zBh>ª¿ÜÈpW¦þ1zü#T-š.ÎÏÊTÛö;šJûh§Û¾®íH}GI¦?C”oB?bsB)OÉ&vÿNí?wJ[¤û®Öòߊq`¼ L!©"µ5¥€C²sÙÞ!Þ÷£À÷cüÎJx-×â¥(ä#i(Øi(ê,¾ï[i8ˆ$¡h'a/²€R¨€Ö Íïó›7T ÓÍŸ:J0þ[¡Ùu„åÐyU½luë­ëÏÔé^^QîÁ HN/ÛÍr—lnvß[pÍâ¾ÝŸ¼/f“²÷rÉyJÒÖî· œ\vÉÆ®9iÑOZþpu™¶ä§m_vÏ"Óî)i#“îûI«—ü´÷å«È´‡~ÚV»YŒL{$uC纙öX¢8(*-e‘¸Þ)7Ë6fYuW7˜\ó±]ë^·[!Ѱ»ÁÂèL^n…*:|yºí7rõRîøC®\ØœÕÊ*onGNnãì¦SîãK #BJÓêÉ…‚!¡æI:åéTèÿUúÇHÐ…Mè„K>)(Çæ€á¨æÀ>VøOÿ§*þ¤Yy)xŸX&(ÀÔ@› ñÅ`¦rºi7¿SªQ==¿³Þð¯oßó;yúÇØSì5)Àãd‡!Øå媵*µTV`•å-•U¡²–òˆ/åß ©´¬•ÉÅšêL£eÈÔ´¾}–XþóFýëÔ,‡qãæ•æÕ:w£×@»œ› :]è&ƒîæÇ/|ÿ2!_> î>ѭƶ·t1¦²|4îßó6 ÁL•ï{ÈTqÌTÍœ‡ì%y'b’wtÉaã£d–•í-²A:ŸF/÷à äÊOýq×]Ô6Ô…ýŠ_2Û‘ÐÎf///¡A)¬õ»¢©‰*Œ5º²¶® T `Õ9ö±äÜß<ÊíçŠðõWñÑ(!;eÐ…QSh^QÉŸ„¢Òù°y´e&ÒiµMåôex‡ÎðÑzÕ蹞øh® µt)‰FïÑ”—“3&Ö¨ê8IA[¤/iVa«>œŽÃÉàN×´Uíz«S¯zSÊ–M9ë”…nöF^6¥E´äÿ‰XxK¡ÄìOÄzÿ+­¹ ‹¬ªˆ?ÆŠÕļâû¦ûc,H›' 1îEÁ^GþÉïÿ?{oßF®ì ïÏ| =ûÞsìмøeæä®;Ø€sOÂ>÷¬½°MöØÆìÉdŸ{¾ûSU’º¥nI­nÀN&ôLlLë¥$•¤RÕ¯J®"1‡ê­ñL¦_Ö"j²¢@¬¥¼F_ï»Ëà¯c¿DÖCþ—öËZ)±ü%(;â¹ ÒR™‰òRøEå,ÇÇP²ˆ²Z*â\(,"‡,eŒ¤~æ Bªs޶‘HÆV™£´w Þ)%T%ð%#ð‘óiÓ¹¿¢Y_Ö;n‰ùŸýʯef}ʺ ²’ìÕÜ?äÃ’\ºJG‚ÉäPr.åÆÉ­ËN{¿…CR>ï=— Y`Ä+A9/£…Ó¶´ïÁhXÕ¡>2G¶2]ýQÑ×^È~Ôe5pÑRŠæˆ}ŠrYï5Îe þ¯ø+LádzX’Ö3, :}À«ýJÀüMM;¨àñ_í²@û¤fxSÞé©Ð+Û‰3(wŸ\?¢M2yZ+F )¯¶3 Á²oOÚ B·‹@DÉ— þ„‡¥-³n¥3œ’‘RDS†• aëçr>PÇéçGYtÈà'¶HÅÈŸ‰ãgÒ–vh'VŠÖÄVÒ‰•¥-Cì‘X)¥ˆådÈX½P@vƒíÚ+¤<$)ž÷U–¡¾À³S;ì‹Zœyª¥(qÌŒh語*Vþôè›Ð²›ìœè8dë~Ø)D ÕQ‡>ì§$ñâ²è(‚­$_©j ¦j*öKñþ;LXe=uåî"Ÿ Å¥Ö8+²søu'ÓóAûo-š.è'’Ÿº£<* ô¡pP¬«¤êJ#寃}²nuÇÃÃ(õ‡ pàJ;¢÷°PñA¡*?– A•+ƒáž`8r4É0•½Ã`¸T ÿ=¨.ü_Çr|1t+Md‚ÜʲO mÚ‰ÅG4¯RURo €mÚ½oU_âžp|_sÁiÿδ#J‹ é—=-ò&å%Wéü_©Ïž ²„R\Õq&û ˜±¤æ@œ …IéH9c¥¯õŒ‚ב.â(y„Œ4 NE Qå:b('T©y Äñ¶ìqª“ÙPbÇâÚv( ߥôÈAÕ~Wøa¹|ànÊadƒKK=©‘Qípé"´’ y‡ù ±•¤˜ªŽfÔòb k¹"Ò˜,6ªÖáI'£r¨—U;ÐçÕAJŸŠiqt˜èÅU îREÈÊÞ:HY<¦â[\†* +âôÏ34žó6½ Ôy›qPVßJŽBRÊ:H[kÑêB÷žràk°T¬l1MÞ%¦Š}GÌ<ÛV5mW6ÿåT r‚[@kßkº3€IÜ¿V´×ˆ¡w‘ì>Û¯® ´QÑ&°ÞM®ÕhUËÚÊÖÇšÖªd„Uy¶{5­T¢[qAÁJ J#²/‹KÑâÙIží&VêÜ ‰}E¥,zw–µúW'ò®l=[Í’rÒ”ý¦tL²àg”V;#ÞHNÊl¬Ÿ()MBÓ¹ÌyØæZ³˜E8ض±rjÖòk†Zog((Ø <~[‹ñÌŸ³?L«èô  NTØ1ª‘Š]è¸:ò¼½­½ñ7£Ø›.æ¨7…˜Å¤;оm«2¬¿õ÷õ3añƒ*zºq”ÈðªÛîÊÅø[Ô-ÃKR™ž÷ŠÝ‰×#õõ(a/T¼Çè(´ôðAWI‡ ˆ,‡ «…´~ í„ i0oGòm&kb`·y 5®Õä%,o"YdÒ)FE£"ªÐ¡`xíìÇäìÆ!ò2E•6E¡7¶Ò,™.Ap<7Ï…æ¹Q<?θuî°pVäÍÅtÙír#$Ê+JË@‘¸Ô¯Wjö^‘*tC¯pc¹óDó„ñ#m¥ûÞ ”x$kÛEÂþ¤uǾÖ+Ìv[®HàA®À!¸úïCÔ´þóïéÃ̬ôÛx?¤uÜR=/)‹q¶œÁ8‹‹»Þò é2ëiœ­lŒ³¹Œ³nÇ6´Ì®Å@‹+Ç¡㧑@¤©6Û£ÐdkÝc„q64Âvß¿k‚€DŸ†T•µJÂi€8Šò‘òGj)¼ §ýWØy­¥,eÿÚ½Ôn™íÞ(ì›ÿd³gð#TL·:ËíÆ.ûâvY¾Ri>Œ.MÙÑJÕþ+3}H­i5²ÁY|(;{8¨Óõêo]ËŸ·] [[éTÅŠ:ÐÕ¶Giš¤*]Nôâ*FwyÒ¦´ÑÕ–4ýmjDÝX.kÝHVÕºky_zǤNÝÌ‹@yù!Ö‹ ¹.àÈò,Ãì\Wj,(¹pÙ¸Sj¯WÁâñ²jÕ”R\ü°2]x) oöNÓ¶Ê=<(§”åšlš9a7ÂÉý;üê.§œ†ÿÈÇ)+YM©%6ü9ÇGôVÀg¯£š ¾ì*Í'ÂrÓ7mÞf\{À2Ó×RV»«œˆÙœbàÆFð6‚ý—5T_ÚB`WÂWíÊʾU ï6°4»3™â "å呯îòHW]–½U—}›Áƒ¥+<­ºóDÞŒz÷eÔž•,>)Õ„OÊ~)iÔáÊ, áÍ5¡”FÍ‚âèFIiœJB­® °Ð¶& Û×Ê𲡢•%¬‚˜ó A†Èº˜•¹RA¥¶J|W6|W1|W ËW¾¬î›¾;2eF_©DÊ H&Z82´p$#øè_š8âM,ëßíJL¶pÄ[/ÐÐÄ‘hb¬š Î…AäÜÿtÎÄDÉáïñ†TÔox¥¥üÈvUÓŠËV[ûrdúµ¸EÓ÷#Ë÷À–ôâûÝD† ±Ïv“™Ä»6¼Ûç«Z*ªÚ*ÚwT´ï¨èÀ\àH¾HTth-l$߈€éb«èÈRQ8j’/eUÁ¾‰“P©_ŒÏ3ú²ã0ú²"ùRý’fZ5öe-žr$+Rg }[ŽÍú’Ïéø·‰ªF²ª]Ô d¨Œ¾.›Sóújñ¯ mƒo “ño ­“Õ%¾54OÖ¦LìrɸpYQ¬¨YQ,Dê\&à fº78·.oóœáÀÈä$_⯅ÅH¾’„dH1É$Áabouj²X)‹D(Šˆ(.‰í¼(öÓíx)TDMdæÔÊ_1É&‘~Ć¿dúrrŸO7¼*ŽÇÍ òÈ&¯c²ªÖØ´‡—äH†Ù¾mˆ´½«÷[Vï÷ë£à›Â6«ƒœÅ«·ÙÅ Šê§Ã·`x!J´U²9¶ú]ÖñßÇí““V¿Õk¶Ð uÙ¶ßuÚ­c|í)B]-QD¯uÚiŸ¶–puàÿúûÁE¯ÈÎÞu€Ëªì¸ÕÄÀê;Óy"+{™¦]õ;-ÅøFv\¿"©ó!³´ÊÏ4øù¿càØJANÚ2“œ=qƒ)œÍJ áçˆVísô·9ל%`#ß c(ë:“© x¬ç+Ý+ú Øsgp¼]Ô^mãšÔ'¢©Î#DîÄÏÙ±ç-Lm¢NKIïbÈš¼V Êdjþ‘R¶éöõÎë+—Rj{ƒ6d'õv‡u[ƒAý´E+±®úå'u8‚*ß[/l0¼;TŽäñwaÈi㘷‹ahj"ÙðúXNéÿfÞ)’qíý죭xxû×[Œ®Ÿ`=. @w%Ç9ž­˜²k‹ÉÑv=2‡²$ ¢náý Dä?I`'¯bPîJ»†¿Ê­ÊþÞ!ü Ê{Ugˆî0(ðm4ȲŠÜ­¾‡Âÿõ­v}¨¡¥RÜ]o)Çuà$Ü$¡…xÿœÈßoýŸËv¿ÕmßBËß¿…͵Ύ/»Ýl‘§—ôŠ×@»sK¹ëÍá%¬„a²î%ìüÀû¬Ñ 3°‹~ô¹Õ¡ºÔ}Ö°ÍÒ6»¯î²™ÐZ¼ïÅ>χ ÏF(¦ÊÎvvLŸ‡Q\Í`@Ný}›íW6f‹Ï³ù#»AôùÇéíd2|œÎ!epÀæ“ëÙüfÍ>R˜ˆçx5¾aO `Tv;]<îÞL!ñãä¤ ºàP̾ZL,+9›ßaw¬å"ë”Ù6œqîÝT2Æ'ââQ aL¤bADÈõø4»zÃ!ä›t3¹<†ESC*t3ûøš³óÙ¾£2f··³/˜¸RVÀ1†®<Ýâ=¿7èÕßñݨR æøÍà-ìò°‚àÎNÚ’³vƒøÖpÙk… ¯eĸ‘Ùå …6x¶×‘€ßùv¤±N:õS8¯¢ Ðo½o£2Y+¨~‚²c«Þ| ï›ýã½´b À@¤ÂÝó¤bÊ0td ex«ß‡CpëC{È3”e†R˜¤yѹìöv»õ³‹>Èá÷ý‹÷òËrøeãbøË ö÷8tcøhy{Ñ9 ½sÉA”»g0L¹ŸØ|£Î¥,üDZÔ^†A¯±#‘4– êUÖyT–š!–À¯,’Eè¬ò5J¦Ù-ÊM$®xÕQï¼{['š¡OøWÚ;H”&ò+³ÑÆŠLv©L#.êþ4¹û9ЦÊ< ÓX¢çl·%ø„³‘Ìr•9Ëâkö,9jyÈœåqž=KvÂó¶ÈNXö,™³|šÌYæÑÏžå!O-åìµxf‘Æ¿ÉägõŒy<»ÿ„îûìlþ/²ã'ÖœÏþ)ÿ|;¾»ÏoqÇBÍ^cüv|¿€“s(—à ûæãäþo^LèÚÆØëç°eâàÓkÖ5 ·Ÿ&WPå ¼Ôq±§Ò4œ\¾Ÿâ¡žu'w3(àf ËÅl±Çª+Ì'¿Ox%We›: Šp [,ìêÓëET¾•w“ÍÙàz:¹¿ž@›§¼ÈVŸšÝßÃw=ºå ªìŒ¯ ÆÇÙük1*è脺Áìéñ3kŽ VqæiR”ÙáÈy }4›.Ø~©Z9*Â^«µèb®þÕ«ŸªìO ›p¸«¼>< ¢‡ý*|úzOw“9¥‚N›Í§Ÿï”öÎgO°‰>ÞìE±ÍÉ=ô8ôÜÅÇÓk Œ•kûØÿ÷WOó¯pžoŠìânú>”Ù¤/Ï‹¢ÛL5‹ Û÷×X_”@ ©‹Ç¨ Áã|2a Ævú8A]yìË=JBûw¤Hé¬ZPÛ ÊûøörP§>#ñf—½‡*›ŒsPÚ­?}Yr78:<<ן¢%ù±È@öt¬ äB¦=›Ì'w_%s©«dOñŽÚË®Vc½6^JåR®Œ ‰s¬ÇîàÊzƒËÆÀY&@›cTŒAÕú·Vÿæn½sCÝk¹ ĤŒÜ+ñ ô¹FÙ]Ÿç$·[犼žÉE5¼Ç¦×dbÄÐ8 nó¢{ícþû¼Á×;üw£•Ve[Tz KÏG²$úžgÿŸ,ùðjDfª ?³„UÃÃÅœµÞ Š(Î…Èiotïࡈ‚÷¨±'TÿšÐîâ¯^“Úà"~دé¦>Š3©Aq|Xï@2Ü+ |ö‹´eˆÞA9Í–£¢á`HíÂc@ ~÷é·T¤FM‡éûõÞ ùZJ¤<ó ï+Êûw©÷[ ^|J ± ‹¶øfG|ao! @A2fèQ-Hq•sZ+ÿ |”ʼn9á*áÇxZ6 K²g%ª`£¡O¾Q"ßß ¬,î`aàÒ‚œoÜO?œŠðçy£ 'à¶5ùb©ÛNa˜A”PQÀg‰ü®aUL䄨ø¤¡‘ç-RšdõžÖJ6h¾=Gã+ü*ó_þ«ÊÕø¯}Ç€5eH“·ûkómî"Î-A&ƒ|ur1ä^ÓÞ¯玡…ê*\ok {•7_«$•ª ¨®æëx•â#N|½¥žH·ŠlK=nn9FoK=dn·Ô¤òçƒg1t$Œò=êÅ<ú³Ð‹Ñÿ|XøCÇ-¥_õ?æÌ³oणå+3¯»è¥=Œx¢p_”Â^5ƒ÷ ì‘Ðût?}÷Ë“Îsq?~X|ž=Ê›¹.Î@2%õ¥b毸HxÒEAo‡mó-Ëþ·jñš6[¤>ì¶ö¤§Jv þn›œ©Â~¹x×êÄfOª¹7|‡dŠa=n”v’‚òvŒšÊñ#ãúÓ›O¾LAr†žÐ¸†­æ ´“BCøú=Báð×^½w¼G$§×½xœ=‡±œü1… Qü8C.=&7®š¸|“¥¦ùìËîÝøPé·oÇ_q¼ë"[¬¾ÇÏó ŒÆí ¿W[ÇæxÖqµ€Kœ³#û^ž\ÿFÅ<È“Ž¼µ[ªú±|åTþ+ •÷\üŒû¿Â¸ô7ª›ƒ½‹þÿët¸'å¡Éä[ é)‹$+æöVoKÊðQjaÌ®”tn·ÓVÂI›äÛ$ŠÂ CNaÚ«¨:lM˜[TÂEß`« m²6 Žo=­=†&i­ T¹Øœ»†ä¼¡Èy#øŒd yÌw0ηä!j©Á@QPŠó†:‘hÔÑ‘“Á»¿klÛ¿¯Ë޾&]9Î!Ò•;úÞk3¡×T&üAóÀÄ3ö®×ôô4'zKÏ Ðõ)ÑkªQ)©obBdæØdhB–Ãoù¬Ïqª²mMà1ZÇhqëƒc”à„§Žüþ£$ξ£DunI]ÅR£CçOmtPC³h&YD­l„çjj%üµÿÀVŠS¬o+±Ê­˜"&_#é­5¾ÁF†»ªGåþ­ ÷¬E$}™ ­°mçû²Ï¶`Τ-bæl¥ôIgÌxxäâWÆCWGLA@1.ñx0Á‹ãñõ–₨Gaæ>; g’ÉH •À¦5Í_#HŽË]j Þ°iQa[¾hÚ^âv$e¢]¢®]£:ï:ME®¢Kñ¢3QíÀµë§)š§ Eý;&JÎ(+O¯?‡²³È(høñÕ £}nT]9 µF¸ñhƒƒÖJÉe¸µZ¤V¾ÁèÛ\)•£QÝû¶ºqñLØíR/E{ v°å«ã-ŽI¯^ó<Ú—ôˆT2²ÂAIo²F,¯¨Vâ=—ŒˆÀ~¸q">a)C•5+à!àn|ý†=Ài,fŠs&z#­ G‰¨KÈN¦„W\ŽI\ ³ƒÒ9œ``;­t4Hì´Â#4Ot„i ‘xüI•9—X1IØðð<4ŸÜNÇWÓÛéãWdaÒ¦ äÐäñ5.):Æ#©°JYê—•ÃD9Œ²­ÌA|¡349§^ KAi<ñÎfr?ƒö@J>1+3yØBbžï,ún$¿ÃÞþÉ’©©˜È…™Ïv ¬À©`Û;ðÝë2P¥}·ƒŸwñ3¼E‡ç )”F O± êfÞ—p°}º}Üc÷t:çH)Þå£!O-2ó¡ÁÔìš3)A¯(­\ÆÈ¼ôÂqQr9¹i`šËÍ*ĆEV/ »À 'Êmf#ú<^95é¤Fð>2è; ç-¾¤†ãOÖ÷7¨.P.,²—Üq1ŠaPÞ^¯%¦…‡ vÑ$n´AME˜E‰¾¢­Ýa ³wÑ®ÚG»ÊN :P·2µOÙÂPõýø4¿×6£2Nd4Ùw…4¹)lŸ\Ç©¤mÑ´¥G# ›.Øý̬SrõDEì"ƒ°å(þÃUá\¡¨eQiâ©Öt*Hmi”&¾F‹B¼žØYÝ£+YLÝ©È× ÄiD‹‚ñçâÜ 1a05¹ª2¹10èKQü¨é?öÅÃtaÑ[õÇþ8?ÌÙŽð-)¨ß’Mœ¶º¿Âά‰ò×à´A–‘ø ¼ÈeF.ÆÅE9NdŸJŒ’˜ä\4—œë£S,ÇÜØ,nÙöíóZ ¥íXKá†qaG³8·+ZÀêøo`/W7ü7 …V¡\ÜXÉÌdêWØ}ýM÷»/Hï>é”T2°ï`DüŠÆÐgݪàäÁ;ú³Fœ\ËÆÉår(VÆÉ?f÷-ÉÉÃ>ñë>:7sN>Àœ‹‹úf?ìðë#JŒƒ’`ûá;ú3 ¶ßÏÆö•g·p$ìãf!C÷ÿM–ò/ÿò/+ãä?M,Éœ§Þ ¸Tp©ªÏÓ…á°T''¸µ˜°ŸW·tþ½µôžÌX ÷yü«J¬y˜5k?Bg¯Œ5ˆÞZž51òl-âMüsŸ˜ó(sîÿݽ2æü!zËœ¨m*—"î*pÚ dÅ¡P1 ™¸l2——O»Cd´ÅU¹5¡œT"› lT< À=fHFrPPqQãC£¼‰pÃòKô¾õލúÛù‰Ûæx”„E`ˆO¤>S—©5 “žúð(‘š5zÙ'û’ÉéšÂ¬éU¦„Ž"h„–“}K¾†ñ¼`õdŒ„X7CïËpQ|Øê hÖE¯u,¿|¨2êà²!C.ŸÿV‘lQ8t«?íAµÇ8¼Jùñv×§²5w¦‡FpÛÚ.ª¾w;8—¡B åø²)–µF y¦…¬¯¸øVê‹Þig´Çiã彯h¯Æ×íáÛÈÊÓ;ˆ—UŠÃÉ…ýv‚¢x‰&úêޤpØ¢º¢R¶x¼­. 0ññ%Eì;©_v†4N8ê°¼žo7qDñ\a€û{[9Å Ný0hÄOܰ"û9ø ‡;‡R[º£)•"߉™ PHªøÏGp7ÆR|Ðw)‚ŸòHQCݸ¤¹«…€ö"ú‡bà7ÆjTtÙ©B¶¬²§Þë÷¬¥øêý„`fWÿÕ,mŽ˜ÙŽ‚¢,¸Y%²¨týééít<ÿʤŠÔñ0*†ˆ)ß ³«Ó§T¤ÉàNÊr^"¬2˜”üLîFMéj÷—ä|a}{Ûª#£Ýw’%¸§asR‹ZŸ!”fºãbèŸxâöb´¹-ñÈ7Ñ^Âwê´è`é§ØîªnŠMÅI1Ÿ·/É*80êføØèH$ü á¤ý±ã B.l`\;øw~ ?p…TCßárEðìýAWLA*Ì«ÚyÿÁXÞùå}„ÑQø¸î(ÞbB¼ñƒíÁÿPJW DêýSü„3ìg™kzáB?°O)ÜÑZPÈÉeSÒO˜õ8•9tƒ"ðò´6×bѳc3§ivACÓ´U×I³ƒ±ö6RûÅ×ÕìdJ^¤Ðf¹ý&ýDÕDÉŠ|½M›Ðð€A·þÝ9ކå/ï•ÅáåõVoØôr@äY³%¤¦ÀŽ~fG ¹5‘X,>Œi®¶D=Ç“(Z Nø)bŒ2¹D¨æ¯/†½¡‹X%ÈX€† ²n[zy‰‰¢”¢÷M>CÓ5Žákž„ *Ð)ºD«gôµÂo(?ƒá÷Ø7½×eDÆnÁ#D¥@a•£7¢+Ú]Z'e]‰³ìlkX\eå.[r#ø³Ñ Èwø•x¶Þ­B¼‘æäÄ̲QÂ@O–ԨʛÍÎ/¥KB¼œ4‚à¡ÌäÜŸL7ãwdÏA‚Ýžª=¦FȱÃkÁ¦—|ÃpF¸G!.`w3DŽß³»éýôîéN¸LN?‚L>»KÜ5èÑXö¤êÒýÊ@–¹‘<_×Ò}rT ±¶òñ'q¬~›>pMl+â'÷³§OŸíÍÆêNÕÅñØuAÇN’“ù ×Ûë´¸;X—>%#ŸNî'sX!ǘÃFó«ïÅæ »z'Â/k@®ÖCü`Ò‚‰'ð-ñ£K‚Jc­»Dêc!&]†Ò‡ !>«Í´#˜hM>Ï*&Š6¢kÛÍŸ1±i6¡„ÒÒZßÛ²1#“ *Hà3zÂ÷fÃ9œ 02Å#$*{è[¶(Ý]vZ1TDsvÿ{1ÆùÀx×A*åÈQÑßͭ䈰Ð0гNhxºÄ¥æw½ŽiÚ2ë<—Å™²ÈâLUÅ6Rõ÷\~0y]ªOtÅlS› žŽ¼T–§ßÞéul!Ƶiùûäúq6g Ó’?áäTT±G¢[Ÿ&[êÌĦu$öÞ¥— ¥°Ý`v¾óÄ'ª¹³ð ÜÁ%/p±ãgÝÛ–u'J)XÕÎy…+„³0b‚`‚Q0õBáf°t<‘ p§Û±UÏB§zähhMÊĹ‹'źi½Œ^ƒÂ‘3¢+5c\§ÿFø16å¥í11óÈÊÌáãÜrbO {ãI™ÜIÒY;|Pû¨Œñy—óy†RR·®ØCb<üàrµ»_ãß'lòûdþ]¡@ĺš|D± Îy·"rJ ‘O…çp äF’¸;°/ÄáC;“}öóç¼3 ©/-Ù%%»LIV§ÒTWtÛ£E I+%9ãº=îÿ‡ÊÁ6ŸýAÉšÞvYuìAµóÒ)ŽB5t>¤ü!$øÃ‡àòÒ“FŒ¯‚iD4h8—yÛ£E?èŒÒÛ6 Û†ªHѶÊ*Ú6m¥ÎÏ&ÌCÅ'Ã4³é \éð Ç#ñ"[”µÆÃ0 /3ÚÌhæÔë>\! Øç€è…•§Ë^Q΃¨j´ âÚß±j ù)?ÉPt%Yºå=¢¼ ÞcR‡ñ cU’mØRBiŒP2ói©]“VSqÇÊù.ÓQL>täçÈ­ ½ÚjÓªÅÙÔ@ÿHÚž–wßW'Ù9g™ÔS‹Í08uQ¾´c‹M¬\“ú`ÙI}˜{R-9©ç›Õ‚'žkZ—ŸmZ—œi]É>­ýĈöG.@ È¥[R (²9…lK)tó‰SÃö ¨—ؤ‰B vz—‰ò)ÐzVˆ.l{M7)AF™2k±‰(ªnuyÅ@ÅwV®]Dõ¤YYIÒø‘éœ(¨PjEÌüFÓ,xžÃ'Œ•£}²Ÿ›F!üT ¥“­WÜÇ6Ⱥ/!kÇ%}`aø4øNã[X®(ÚðâËd.Wœóé¥ÈE!•ÖÐÊs¾y³jÎßñÔŸMq{˜Œùõdÿ2}ü̺{·“½›ÍÓKéQRÿyd™g5Ë…æÂTû¦Tz’ƒDýýaÉñò¨dy„~mú×±gô“W ŸñÈœqQÁÑÃñÕ.GæÚ)Ѱ‹(ˆì®G¿Õ²ÖìA2».²xRVJ’XÒUìÅhò…`7á³xúìÉh…ÊP˜NáÖà¿‘BÏ®ìÕæºE—r@±‰¶Ö/”…ZÝ ´Žh6Ž ©ùÈDÎä:S.òK¡;-ô¼!o°Ðµæ‡êðyëlq'‘:¹í£p‹ÛÜ`[÷&j\¹³ »{Ùå~‚J!ÜeP¸b)»lp9x×jU§“¸¥…nÍ¿ñ[¡;0Ñ®”éÍÝv¢JcDã‘78zšêqtŽw=q§M³÷Pä±!¼1ÉRz,5ß&<¾z§-òÑ»è÷¡áD¦ûiž¡[|è“n©J+Uú9³f½ óǽEeñ!ÝxA-}Ñãr!ï¢ÐA²¦úyqêóh\«E¼Ÿ¤Èª°Wè3ZðOª{q'8”,± x¢âkX˜ÿ€Šr<ðåô£bÂk¾ßf{I§ÔTÒÊ™HcŠðk=«BQ%•#ï4áB Ýþk½Ó>æ¿ç‹hã^kèæá´VþÑÖx05 ¤ÅPÛø®…ÏÆwm㻦fÛø®­Äwmy·5ø_õUÓ]Ò“BwP;Ïîö®Þ<Çï?´ä\‘\¾ëÀƒ?]þgø>ñ:¼’ý‡p?SÝÍÐ m œÑxHÏ&íSË»¡ýh—U8 }õs@ãiø¤0¦yX±“Zx€§“Z©MÐjI”<¢Óë%|Ú_Ÿ6E9í´¢&ï¸[XÜJ:„ýÁÒl¸ç¡#X<<•Áðvntì28nå÷ÚJ£Wøk%<µLäò´=±ñ*ÞYv׬ ~Y©NYf,;› ÚÈ] „‚î¦È¯h(§÷ÅÍËÐ?šÛWÌì¢ûH•ãµàv˜æ…šMLGKÌ¥Õ©)ÊŠ|—.&ó„Ó‘Íq)™¿3ûbÊo1‘®Û§Ë¤Aêåpj£ÿ}\ÚÒ]<üŽ’NGF^‡£4o£4W#O£„›‘¯—ÁR=ŒðX‘ê]dq-òñ,r;–yùù9%¼‰z_&_O¢,nDÙ|ˆ²9åñòvJçUq ¿é8î3¤1­o!~þBÞÎBKz yû/Й hRÎVfÂS=ÎÉÇ•ÂÓ•'£O&'쇟ûN6ßLŽ;>DúºìøùëdsÖÉä©ãÙOì:™ Ì™\+Ì~•l~M.š˜rü$²xHø»GßT)D¾qrSä'ýÑ}k2¹7äÁÌ®`43zYE£ynÐôR^|ÄÆ›ä?àªhÔE1ÿ‚Ë®#[ìY dt”JLèoj.¿[Ù\Î;=@²«rPÊêd½æ8%_&ЧÐD”H4Ÿ^Z‘;’æ‹$Uª&Þ•«ìëS”mV–28h™½tG$o—Ýý(£¿æ'‘Å×@óð÷3Èêdt¦Èà`àç]¯"éYÙ›7$2‹‹€—@Â9ÄÏ9 —ð¢N‚sî´“…ÿ³Ï›œ.x9ýï–r¾Ëíy—Óí.ç¼Éép—iâ¸\í²ÏœõOŒîr¹„¾o`ÿÈÇÐûyúàyúpýü|ø=mG™ÙC¬ótKsñò óv Ëì–Û%,§?X>g0/ÝTf7°5|èÌàú•ÝïKuúÚêEæ4éòzqe˜¨º¿—æÂ•¡û½é ñôôÊïæµ/?¯LÞ]~L˜î×åpêâžZ~“Áí¥•ê¢•æŸåtβ{fYܲL>Y ‡¬óÕó;_UJIß7ž` ÎWÝùɤÔOÃUú^U-ÕŸÛ)H«Þ,o{¹~5 ZåNO¯¤·ÜÆÓkãéµñôÒªüxzI®È5ªþ.ÞÎT/ªïÆ—+Ow$|×¼ˆÑ(?¯3™Ï h•gq&‹¹‡YK±ºqõMxìÑ-lØ'·°aƒÿzÇõüËð¾üx¾bEà#¹gp£l(ð핞ÉwÌì/¦²£à4S/bö3_Â',rS¼½ìù“n`0I|ò%]Âþ&³9Fi]îZ™ý²šÇøcˆ?.m®YPâ¶wÍë™­ŽÛuXÒðç ŒuÊcO38bE„‡&”H«zeQǽ½L¤Q/þx®[Cẅûý¦ÝCYkš´qÐ+ÚfèÃ`ãÞååÞuÉý»ˆõ†â¶1úã^ôVáø5ÿ6¿ýô ?.?·¯ƒäy^guû¢ïБééýs2ŸI˜8 ?4CÂÑUÁÀ=Mqô7‰B•q]Ñåß8–mË´vn˸cÙeªgÙ%º–]þLi¿ç²Ø÷Â/«9d>w¡‡Ksø3¥ß\7¦“êÕ<¶0”H’"ïäcìäãŸ)‡õÎ)VÀ éÝŒÍEG}y?}4µ‚¥à”¢˜dWGQN‹¾¯[#<\ R]¹l/}íGù„N™<ù#<ÓR¯Zc^^üñô}äO¶+ט׭kl•ÞüqúDz•à¾ùzOòǡR$ÍïIÉŸTà‚Ÿ?œ‡3œ§C—»›ç½Yt‚†TÊØÐ@·ß\ŠÓœîdæv…3úÁ]ÌRa/pºÇ˜¥fô}3º‹¥¦y½Ùù%£—Î±š¥Ÿ ¢H»ÎÝï[éÓéûð/“á8›áº%y¼6TlÄýQ¥D¨×êÈŸžáú¦?‘KYrÏ¿•14x‹åÃóüÃø=¸…%‡ñŇÏà¶Üô67Ì6UÓ¼Ø,Ìk_˜›…ù»_˜W9†›…ÙLíæUOÁÕ,Ìi> +ñÞÍ些Ëo×¥ŸŽŽNí“UøêæpÔÕ¼t}ïÔ¼§¤ŽÎºiYª^ÞÀþûò~‰yœ3ùDåw_ôð†Šnt… 3¬D›¢ÈYjˆhÌâ‚™y_×o®K÷Múbge˜ƒu3Ìá:Æí;÷m0ÌQ†ñ• –Y1r f§ÿÁÜÿ3Kà‚ÔMržén~>Ùóy;æquÌá瘮TÍæá¸Á)•6¿©™®É]¯K¤Ï¹ýí¢×ZÎ%’ƒiÿ&Q†²ºD✗HOeMjßÏîž'lüð0Ÿý1½#Ø2¢Qfóé§)bí¸‘/}LDtK1}S3J$-^ø7Ù¸v2t•÷úÊŸd]†R*~Ã"“Ší¾:æ}å¥'+ÿ-/+xaV>©£¦ñrêÞ—Óû×Çõ×ǹ×ß³×cýMñéMuèõYÿî¼êú¿qÔÝ8ê¾£nBù—˜Xq…îê¼tÓë6è“W祛^½ZíÆKw㥻ñÒý¼t+òLåî±âŠEá}ZWdñ†~ÈåkªDóËõ„Ù!7‹·­«Y©Î¶/çU[ñ𪭮ӫV¹™q5~µ‰k­åØ\oOA ÙøÔ~£>µ‚UTÏÚ?SmÞ[Wàa›pžµg.Z\Ý}ŠKúê.{Ÿb®K»¶Ë•;í]€—'žY/NÄkÍ»Ås×^1ÿ±Û¥—;ñªÎ»±‹{Ãúë=™†íu|gÞ²M\à‹šÓìòޝð£Ýû.½_­Nª<…Ÿëhäó¹Šëúʾ^•Ñ÷è„Þí~/}4»&ï!<å¶»¤pH*¼ºR ‡>8ËJ1å^”»lÉÝîq<š£|…ÓõÔù½"¹b7Aзã¶SÍÙÜ 5_½‹þ^×âUH.­‡ 4? „ûO7å®8‡×ÓÙ'Åǧ«øøhþ;.+È\]¯ëÎptºno`é®ÛIÇì›ÓMõÍqxI¥ÞoÖN¿ÜÌx³ÙN"Y†;ÂÒüâVw#˜ó"°åo¯ùx^¡ì¥ŽëhU·×úÜ"gºB.9xìy]£áìj—7¦Œ&S®ŸÓ2 ª=œÓVä™Ö$6Šˆ ‡YêjÞw©yÞ¢æ6$¦ùùÞ™æy[š›ÍWÌFŽ×­gž÷¥’“zÇY¿5¤´ÎO)k ÚFüôd]4t*Z`ŸAôŽ Ï]5–htëÏœb± سå!Ëþxe«YÊšÃp#DºªÅÚê†_y”ííWÁÉ]ƒY–3ÿ›ƒ2^ã¼½!“§á=`lIÜ_ú5q¨\ÚUž@Ä$žÔêèD¦HÅ<d¸(ŒÏ:3)œ…~'Ƶpoä`BИ˜˜˜˜²Me®xarÓãu­A½Ç®g·Ow÷ìê«ø”æs‚SåøR:ÖPØY»ð‰f©p­T¬V„XÄåÈN Éms%9¾º!T¿,aðnƒëÚàº6¸®Ä³Áuq\WÓróÂüïÏjËÞ *œëÌxƒª•rëjyò¼áòÿ ¯Õ;6±øu °oЯQsA‚Ï ü~„å¯AøúüW„—øÝY°¯Ÿ–W}+yß( ¿Ï‰"KÃwãÇ,à1_ä˜6fuïŒÍ‘ä>¡5âÏ’ö¾ÞŒB×cˆqŒ0ž@¦­÷ŠXoÒ{…ª7¨ˆiÓ`QX' , ®;\1¶Î`Hyl]/'¶ÎŒåÄJ€7îµ[wоJB¯’i@LÊ„#–¨D– @­,@;côyb|Þ £´z™Ziè¬U@³RÂ…[¡Yn\–(Ë‘å088±X^@,–ƒ€ÔXÝÞh'ŸˆqùáP–«›­¥hZìçCHiÂCEïa ä)Yl†¨Z«™eêÕõwè;¯µÀh@ª%qdž ²Œá.}P®H!Žö.Ö2S@KOØXÌXfÀX&´˜Œ+{¼B;hÁ5θK÷$Ž+eoÆÇ¹ŽØ !{,0þa|¸*üWøK ;_Ya_Ù0_nÀWŃö…z­lqÐïÊíÊìÒÁ}ÖdÌéÊωBòc¦ÓÓa\FœY QÓbÌï8ò,Ùªþæiá¸ñ“q*ôëìÌN:˜âÌš" væÎ.+QböŠÜ±: UÔ <¬€”ló¯ßû!³‚bˆCåx€@ÎB8XÎl©X° ¡ýƒ Ž=C•XJ<_D V–sœ™×N–‹êrðmJ9Àu+AÖyÂê4Äš#œ¡eV4JR¹>ÇG¨WqPl¾íS¤ìrÖpt‡F@Ü%°vÝË…£ 2è^.€]\-t¹"ÅYï†Cú&"Ü·ðm |i>Œº†>nm+†ãÓZ(±{ﲄvËUƒ‚|©Øn50àþ,‡hÀò¸nà€ñg­pÀ"‹Ì ß)"0k¤7;h‚bÔ7‡ýê‡ÀFLñ§Ä–€°¼AþÉ„G~§c™ü0yÚ¥×K «?0‚°ú- Q]ñÃA)hãCøb)Hæ&@ߟ5@¡ÊsDè3&ËeÏÕÏM}l×;¸P£é…|;qÿRð¥lýoýÏ\žŸ­Üó:õÕcY¶pÌ ÓÉünN ²ehgúÁé0ãñ ³ÝR»ÔdEÕ2Ã<ãh¼[Ïh¤„”ûfƒ<ºn¤ÏKmAí·Ðg½‚~ëñ»ŠõhG {Mш¨œQýaÃQ ’1"]õnâG&Ÿï%~dêšç¦çÛŽ™†aD|oQ,¼ÏB2#m½ç‰"™16¤pÁÌÒ¢² ý(zÛòÏ«%é½}˜—¶Xo®©·]¨o&=²}BzjØoÕÌhK]VR§ÄÞÌ N…Œ³TÔ8ó §¼áã,WˆQ4b–u9õ¦whO%&© Lî[ ǃ8ðäÞôx‡õG•³¬Ä2`Ë™§ÄKLcæu_y&X»›Ùÿt—£×Hª8z¾h®i1\½pè,KTí(hk¬]JèVÓ›²9ÖkÅU¯n ê/U?(Ù‚§¦AÕ÷¿¨ºÆâqáºÀëš"L)û¾°o ì+˜k¡h×g·¾})hû~´Û…‡£w-©m‚—,²9¹.ÿ¾á¸ºùÓ5ȯ¨Zúϧé|rƒe@¡¤mâš÷"Ÿî¿Œï¡ÊÉ­Ñ-&ˆûšÏ>=‰ÊÂûŽMVñé .¾ÒOþù>ÎéçÕƒQÞz|Øú¡0õÐô*‚ÞZjÿâôÒY"%€rv¡ VŸ€†ù@|ϯ8äºúHb4Gi‚ˆ×p1Ÿ}nð0rÜ’Àû‰ºßñŒ[pß_ép…k7Z@u»…7ø¶/NNÎ}~nï…ÓtTçâ=]0=êâ‚E^öÚC ¿‰rá— M)rÅ3@ŽñmXtVhqòþêÀ-4xÇ v™ŸQÝC¸ÀOJM7½_È÷@éý£|/‡, !F˜a›ì*QÃûÔİd ¬ºß¦È–¤‘7?D*Ñâ ­Xt£-‡ÃM’:I “¼œz Éz nuÁãøPKßSKÄ÷§ô½á nÒaép ¤Â(?^µCž_òÂM›æ8•9Ú¨¤¬Ö¢£ª“ŠøŒ§ÈsNÞf¯ô%%|,*"µ VÑÐÎö^ºÆB!&AöshÙê¤ñ $I‡!ixF$†ò+Ï ÏKÿ6ú*vñÖ@"HRNÙl“øüJÙ DVšö¼"½é†J"Á!šül‘DP I ލ 0ùù¢1ÙŠw.·_uþ´*q‡˜%s%¡~ŠU!Œ¨]T’qFöŠÂ¼jª¤fÔˆÏÂ>¹2õ‰Í"Lj3m6»I³m¸ŠK¥z?­kÐÔUFBPä7ÜÃzñJTVþŠ.|3Ì*"¡l!|ƒßC1»âÆ1,á (´qU¨²}´*î†'£g°Dì ÛpTLûŽüdbÃð¡zÓ8~)¦BLö¤h6Û–B\LÞð&{.Ë2‹ÏJe(!$Þ£!ÊF’Èâ¹Cðèu’JP4ªÃÐKéÓÜpmY¼!D²d¾U+R§[kXêƒü+—A;ŸÔÍ‹ŽMN…«ØT0®dí–Æ”©p~™hÁIÎÎ&dÂ…•Í‹ïÄ9÷fÂôF¶ö›:Ô´sœ7»œm2ùµ+Z惢uq·Ì±ê*æ˜q+Õª©-7Çä¶sN¶Zj•û«™l¦ 78ðœl±Éö˜lxje‘+¡ Ý&Iä݉L»†q°¬åYVíô¡M¦_†ùHc‚ïœâ??i@§ºOiÚ\‘ªØI¶00IYúP{%4!q ]*HQù™ª %Ùb—(†ÊÑ0\q£5¬£ØÜN&­k‚8Vs0?ÖýUªN ·Pðp ¤ÿ¼žÝ=<=JE™·7*EùØUŠae™Ô€bÈùËA“§4cxŽÐû"R òѹìÑ7º¿Š$õ ñá*t§þûƒø=’¿‡üƒ•…ÉÇGkh mÒï·ƧQ‡wþa!€æsü‡‰S¤cïBìŸåCSÿŸþÐ[ˇ•’®¬Îö[C¾Ý„7¥VMxžôâke·£¯ê=ü[žÚõ ¢«¾’IeVmÑ Á°<óB=Ep£®'…¹±ZJ$“ŽšGæšÑùµ«×O â5FÕ|&T~ÇU]OwCmü›‹ôŠ·6‘€mTgùSÊ‹jkÚ¼uqQÔ‚¿^ŸÆü/8­îXäi·õÂá»\Õ ¸}C-§­= LÑ18 QÔñb¸àu;›=ôu ¢Ê¢ÈÐgTÊfãù„Ùíd ÂÖçñíG6¾¾~B+Ih¢*6&ä)ÒûkÒ-1p´2ºg˜1WGaƒ5Ïm¡…n@É2±¨ØýOŠrDAÊø:f¼«¶ŒµyímÓlÜ×&#å¨ XÆû/ ˜ÁA:­ccaíë´6| +õÛz'Ì8aõfó²_¶B„ Av¢§õñ7Q‰A/(J‘D1vå ÈʧÁáÞ¾‚çÓG O'—½&⎸SZaûn+p ¬ÿeÆ œË§7 MAèûÞös€AFíôó ßý¶¯ûgùmîÞ©t ¯¯HŠXf‘˜¤s_¡ø5Ę́\‰-HNæÎª¦CVð^žyHâîyr?}œŽo§ÿĶý÷ñ|ŠÅ„!,áéâ¼<ݰ/S8œ^M`®[òV1Ï¡1O¹fÉS3&¢*šØŠ§4áqÆ®æ“ñoìéAÍsõ•-~›>< 2.q3yëï™Y§Îm7¥uJvº¡ÿÄõºT*íÀjø: ‡4eèÛM<é׿¾Ø°É[eôñLÌ7ä:~ ­aXU°…5˜ §ÇZvÜ>Já 7’kÙ7±å4•`;¼g'µ:÷jŒÜ}‰)õÎüË_þÒltêƒ×Ø1ÀJ¯¯ÿ¾¸º?Vö>þe…°Ô~µÊð÷Áþ>ý.•ùßð¡V)_A¥º_®Ö*+µZ©öVZ%¶Æv<Rþñt;8ÒA²®^¡Æ”Xøû;y83¼ë_œöë]˜oú°û´É‚ËO‚]ù ª¨3g™ïº×¶›ùô÷ Å ³ÅgTב áãôv²G>Nç2¨°ùäz6¿Y`AÂN‹‰èp ëà0@Ü‚ ²{3óéôþá鑯©·¨7ÜWK‰å¤Aš?²yɱNÄAV¿‡Mâ~†S N¸ŒQ;Iq™‰R,ˆè¸ßc{fWcéQsçáǰhjGÃîÌÇ×d‰ý8Y ÞQ³ÛÛÙZµ ÷“ÅÏøõïø½A¯þŽë·Ðó“]œ  è»ÁÛ‹!»¸¾»²“v‡ƒ»‹=„wjFÌÁ =øt‰¾€í†V%V¢3àI8ŽRGÐA÷‰!.æ"Jš^PýÍÄ­zó-¼o^ô÷ÒŠ /Þ¡ :¾]rÙxÄ‘ï¸Î¸x†ð4\ “¨’߇•šC~Ù¸RÀø`‹òÜkû¢sŒ¾a—ÔבǦÜw°Ò¹”e€ŸH‚å ªª°;Ic *^eñ`aXЈÆöÒÞA¢¼0‘_™hõP‹ ö*‰"eškŒÔü÷ŧÉÝŽ±¹öx'îñXN¼ßù°ˆ,‹¯™³<ÎsdYd'lþ[ö,åß¼²Ýdòs¸ÓÏî?¡2ŒíÁÿEyìˆþü"³GòèÛñÝÝxN¡VR²¨Sˆt<ÇÉuuŒb}V ”n?M® øÁÓ•X`1c8¹þ|údÖÜÍð÷tÇz³½ÃCVèO~Ÿ.¦(ÏlÃÉa ‹¬ÓëÒ¡Û·æ «LI¬>žòß-Ø)ÈŽ¬óx#s p‹†Í#›šc8öðåb„æô(ì~'„Oû®‹NzƒËÆÀY&ÐJYÿÍ>vj#ß?3±<2Ë~ÍYHûX^îÃ7ZiÅR4¤É\xJ•9ñsNÀNOK½æÈVpBìô‹‰è ,¯'R.#bɧSù £:¸– åEü–xÇoà²W1 ©1Mµ¯^‡dC[Õ…7s#™N» )éÔYQÞ¿Äûßã¾—äµHðr Ô»…äJ2oì²${ÆF#V-ŒbAò’3cü>¦fì¢'{Öf3ž5Q–Ï}JÊP¸lG½Ãy’šÎt+r\k¶S8a%TÎÁÙ¼Xñ´ë 'Tƒ›|\1/]Ïc¨ÞûnžæÛó H¿ÊüW…ÿªò_5¡ |pÍ·A·«Þs´¼»íšnòá ÃÉÐ-]EKºüU?ö TWóu¼Ê,Wqö{½¥ŠÂh¼TåÜ-Ç€m©Ò­’‘D×­â–*–ú”C¨×Eá…>ØQh¶Á½@¨«ðô{Ò‰O÷ÓGyïëO(Ï|eÀÔ ŠÓ6ªŒ@Ø¡zX6̳ãQ8ìd‡B+…0$Ó{%È6þ†ö1T*JÝŸN\×0³‹w­^@ŸoøVShX^¢Ô²Õk½ßÒ0h¶La"©LŽ:‡Nî·c<ÂchiÒ+ ¢ Nê7(Ÿ MÄâ~ü°ø<{Ýbo4î­áë÷mR~¾çŽàüRÀÔº3®Ý¡^â+û8žÞ>Í•òMÜ^4¶åšì;_>OàÕ\àØ0Š8·Þ£²yBZÒÉ«&.d©i>û²{7þÔFzŸÛñW`7ïú„d«ïñó|£q{é¿ékÔ[6ÏÕ.í¨e"Ó_‡Ás¤¼®†\‘å+Ç®_CÓCÏ5 ”û±(:þz˜Îü/¼oJì£>1Â@"¥¸˜¸/ðëÌ®?£1û„DRÎn+Ýw( Ý\ED] 娈{ÅUS„à—7ª©£B’ÂÂQ›·y¨©ÃD…< þ¤ºœ}zȶ1IØnå ƒÛéøjz;}üÊÁØp†¼ÉãknFT?L8‘WÊRe¢Š0–PJG–Àõ¨, c‘sD[Æ6/21®³"ᕦ¿Â×gñ×M*>ò AêcÕˆ˜É6¡.H”¹S Ÿp"aç o…&hßí„>ãð¶òÿ“¨šM†‚6w£å/Ü]ØÅ= ¸•“OsÈS‹ÌÚUÄÐd6¥´ªà Nǹ-õ«†ö•ˆ ß ŠCÕ"©Lù=Œ<´{CxŒŽØzßcy¡cã:îðø&÷2n6M…ð$ïãXLwq ù@iTp/¹ÛÓ ) ’Ay‘ ‡[ž3ËÈšûÄš‡ÙX³ö]tsÔ§ñ¾{ÿ +⟸²±ÞOaÌIÆ¢ë 3°Ü|( Ë PNªÆÍGÙá,Š™r2J‡¹€š­€¤îÍlèȺÃ0£É@#PPQãC»¼‰`“òKD‡šÔIì$®JÓ®ý‚Vî#ø·Nø S-8v›..3fÂø=z–’­bk®xà 5t@7—oõj«~:"„P<Þ)$®í2Ü[Öou ÷¯-Ö­7ßbÒwýV³=@_R¤Ž.‚Ñm´ ˆàLÒ£½Àp™É߆®­‚wZl£¯,:í·êCº M'–RÐ¥W†ëÃBߤž^bI-1Q‚z‹ï5ôn¢ûÃâî{­_[t3éÔ\éõ¥;‰yÑé\¼o÷Nô¼hóû6¬n9—…טUµkÌȇF_/ ®£ö~â"1™š‡pSSœì‡cPN¤G4 ³¦W9ˆ‡I@üHØ@ÈÜî5¡_è–µ~}Äí¿A³Ú=éë åÊ8ÞµõL«‹^ë8~ œ:— écIž}á }è—‡Žt§=¨öX¿’.ÆÊUß¡:¸û4‚[ävQeµÛAV?† ”ã˦˜õŽk ‡3qMÎzß¿èvF{œ6^]äÛ¾Æ;ó"Ý>¶+~Q.;‘ šR`Q´‘«2#»xÏ3^G/ãäð(u8­ƒò^ 'h¾…¹Ñ…¡6<†éS÷¤N÷äA ;'Úkó[àâvÇ_ÞìÐßÓG Þãæ«ãˆÖÜŽ˜Ž‡Z°1>îØƒ8öÚRxM} Ux%d‚ššÀe-…Kªq.¡›òÄø¡‰Ÿà8Në^¯Èàã9æ«;]qeëàšFÞàÅòkÐúH¯š‰ß^L#ÖA¦î È]ñ_ÿÿBc0šuv®ï]v:á=¦ÜzŠ»¿0©¼eFJ5ÉÄo‡÷`èßV}¤Ì¾2ÛHZCNxz™™ÝÈŠ"ä–Ü“ž`j¢dE¾þdMaì£;Š+ð [»SXXþò>_aQY|¹€-^oõ†ÍlîSÈçh“¯È/Ô@Gap*ÕÈ˧¶Dê)6~ºIøu¯ üVÏ»B%À¢|ˆ èó1ŽqY{1Ã:Æ€Ù&þ€Ýá%zŸÇ÷ìnz?½{ºn2Ó £Ìît34æzc¸I¾GWuéüŸ±LøH!¿M¸£ V‡¨ƒÉýìéÓgCͲ–S[-2²”nk‡EŽ×½£+ÛpñA`^0Iž(]ú¤ö0 AŸç¶>†ç<êæs}„Â"ð‚˜f—Q‰¿g â©(Hú3¥7ÝIKW Ôãw Ôå% *Xë¾îº9²‹…Ÿ›ßQʼnö3ëÕN²8SYœ©*Ì‚?œmë9Ø–?˜º–Î×vVKÀŸqNúó³^¯•«ùCYk$ÕI;½z(Gkyåí±Îoß3²ˆ{ÑMå[§¨ÕÚbòG·Î7øÄMåvñ€±¿ ܸ©Vq‡c³aŸ!LÁ¦‰IÒø™²˜&‰HÝó¤Ÿ' ׃Ʉ}¡¨#¨V¹¡ñES]LoÔ™µHë$¡I£… :°ò Ê#c9ÊØ>+Ü3“îtîY"}•;MQzçHŠô5JNéû™H¿/n-£ ©»›ÈtÀ½…Ñ£…`uÚêÜ#²ò¬°Ka…)Û”ÈsU×h”Š}ªƒ­”××õ97™‰³EƒwJÚþCñ)P…ã3Ùd å¨IdÊkÒÖån’óœf)žîÌQ$P!|¼—Az¢ÌEžñšlu1&M1&)gû#Ÿì¸*Ë œüE6§p®"0tÀ|¢{4aÓO_ÓtW~ÔÀ¦ (™Ü¼5&:£ºÎ†ëy”#u×d®×^‘‡fu ‘GsZóâû5n>t*óÓÉjLwä×oG´æpø%J)*Ãt‹ß4ÅQšÈPÁ•‘!Ñšœ¡œTGGFne·4r¯É~?fH>0å?ÍÐadæ¯ìŠ"]-¾Lær®+A€mœînC$§Ï”ÊÌ—5ÓÓo(ÜO$IÜ`hyX²½9J\þCÖR)ù]`¸9T0ŠÏq§& #êÕ8!qËÆ “¸ cX‰Dpq@é5­Ùkö ™]ß ½ )+%ŬÞYªØ‹Ñ¶FÁE†kp·ãp 1®ê‰ã;'¾Äj”dqÓ)/qŽ#:“èßðÎÞú£"¢Öi!"œ!"—±N6© Ä`±¡û(´`CÛ:Æ­q9ä >èâv÷²ËáµJ!i+дXÊ.\ðâM[[èÖ`Áß Ý‰nD §w6GçE•ƈFQ7à£Mõ8:Ç»ž8ÖÙ Œ°UÄLða, oˆÉÞ)ÞÑk^ôûÐQìºo¨2l"^ýÙ/z|¦ñ*C°pMƒGR›~ó¶¶b?èè4V`eAP(Ô· c^ÝÃd¸õcÓèìþáç-%I¼±Í0Ùöž ÑlîÒL)äÐÜ_ëö1oôŽ;jY"~RÇXîÐüoi™qÉrêlRÖ-±€Çñ QݲÒpŒŠÁS‰\æb¨)Q¥r.Lƒü‚ˆkëyô²Ê¿èS¬ˆz±9”„»0+(6öÞVln’uc >`@ÞÞl8áIÑc¼if{[ ¢Œd ‰´”®9»ÿ‡žVÝøÂZ6º¾t7lt72ÐÝÈ@·*Äêì7©N*¨?ûÒű¶:Õ´ÍÙ­ž6"/r˜–Ïw³T·=vøŸ|Ö4üPËPòS|Å)— Œ¬Ë›œæÊ*gXÙdgWÅ­ü;ÃqÛ•ÊF 7+ع7@nžcäÞ¹WäàËÄÝ!í¾iÛ{À½­€³íåHÔv b»Ó:Á©ÇmÛ2`ñö1báç@Þ?‰á¤h7ßRg¼½üóCµUˆ6îJ¸½l Ú)PíÁë­Në5ç‘×[—|°í²üb Øv)lûhƒÚŽ£¶–m'û)ÌQ  -p`íPÆÌýä.šû)‚)ÆúÀ œ˜˜S‰*àк“r?àL_þ)– ÷ìE˜Psð3¥M:p÷Ac¤¦“hǀߥ~Ät6û˜Än±òRâD)fˆíRàtŽ+ï%LÞ>°t'&=ˆÖnƒ¢Çpè±·ã}iaxP0à\p‰\pù3%7ãw4öÆË–&Àá×YÐíƒÑ–”Hˆß{ë„·{¡o½¡·p·@·™·þp[K<×ä“ kë´]eë‡$éV¬KÖD$õB"ümM”‚©MÔú`e³eýQ²©è|lp¬?2Öƒ²TL¬ 6 Ö ëA¼6#Öþ™BËVð«²Éφ| æëEBYêÌÙ˜³5éˆW¸«Àºâ-ÂºÚšàµØ%®þÈÕ•ÀV3aVsVýHÂ>ØQ©8ÕU€T5„*-ìt/Œke×°©´Ìcç:Ÿ •š ’ªáQ½ð¥"5¸T¥z Ku(ª?¬T‡£z@JuªžÔLªcU3 IÓ`¤‰‚W€!M¦ GcÀV/è¨'nÔ‰%Kú!F³ÁEóaEóEs¡DS¥ŒøÐµ¬Í©´ùbB3BSýZÙ t”nƤ|‚u#”,hMh4³·!’f’9!C™A£wW—E‚›×jøˆSöwÚe©°ûœ0Üe1¸\ôm¶‰ŸÄÝ:A·vÄ­nkÂÚ&€¶PíóƒjË¥$¦™'Ȫ-ÛjÎÃb’c 4fCýnд4íMkFž• ˆžUq´«(«ð2Ú,HZ_†íŒ‚})4m9ަåŸãHÚ,ë”m‹]!„vUøÙˆöd oìì Ø¼)­–›]É9àQÐìL>>Ú€œaRûœ~úühÅŽb3¨ÆËD—Z1—+tTOÚ™}™˜‘£ß.ZU'VõùªåªVž ¨*O7…j-GE§Ê+eÌàS¼ˆ|jé:¢ uõ0Ô¢¼›¥bQùØ .?,uHÍH]ƒú‚@ÒLèÑæqÆ0¤g ŒÔÞt3‚´kŒéë²â¯6zÜ®ÃBˆ?ECª†þE_’´ìT¥ƒM©ÿBÈi<¥:xøãRùxMÚp6ÀÔ`ª£' E@aúã^ôÄg^̓X•W|gF¬ò¡<2Øÿ9™Ï$ºê°]„Á·€kº# 8¢¿b´~‚į—þ® c„ÐÐux¢ÜjÎèÇ•¥p´J|(:¸k+Q­w8¶i{–èǨ3[p3–bÛŒQµ&Øfœ?˜n“¢“çn&ÓJØ|sÈRƒýŠˆØ]l¦<.L$Âê›Çv2EB*x¹ÇXîñÏ”)%Ìé¡gôTfFqîØ“gÎ>ðrØq¬\jŠ€¬v±Ht¼k™‘z{\õNй/ý1lú÷¥Õ EÊ<¤,SÔW’³!%þv¥[EÈWÿ€®•eº.^Ô3 kuÙ€®ËDSÀ«k‚JÚÄQýL°$Ú¹ïî¶ü"îyQeª°R`9©2O*‡|IÌÍ”*PŸq^ÑT™w@UâLñäeÆ™Š¦ù.ŽŒ:Á×¹A}Ä*›%±2Ïböø½™ âvàXßÌ¥„*‰*ùÌÚÙÝÃÓã„æ³?¦wÎ@…öl>ý4½ߦÁuw^Ó{òK#‘« xžÅ)f©jTâ “W¬ï¢@º“y,K—Ô'Y%e—Ú«,4dK0O2ötìQ÷±gâ„5Íñ|«ôE¯¥¬Ñ9œ=øÃׇƷ¶>œ€œÿÍ/Ò4Í-Ñßóx­Ñ^‰þœ÷ý…ØÃô€ûGnß "ßò2°ùesÀýŠÁ7¨ºñ z ß }áT[Ö7ȡݵ+o5f7âœEœýýgПË3( ²n× Šþ„¾AÕÕúmËeè¥*~Ž??ÇŸ+‹Á¤7eöý W-“Û\Lí?úº™LŸÁý‡!¹‰¾ÜÇ"i¸­þ~@Î[–¾$ ÃY®Àa·|¬‘|y?Õ&™2ìQ5efo© ÎRÏç+ÅùÚ2y×á(UæŽRá{÷›Ê´Ìú¹HU¿ÏXþÖü–PþýóÕ&”?ϱñœÚ„òO„òo sÅòý°ÎC?¬3X¨ÎÎèB˜s—›ûkñP6Š[VÍ¿etëÒ/Ë^Žg8ÿ„GQ$|N ƒ{ (BdÌ×ã^•ˆ÷ßWÜ6nUF·*Í•j‰€ÿR¹lÀ³Ç‘ÍÝ(gÌ~{_Ó7º¢õ[Bõûz‘¸ƒô M^IÑãókÁù WœÛ\µÎ£¾;·ÆŽ·ù‹Ð"dr1¤“hxq´B¿§èï¦Ñ)‰²ÙLf]]cbYJ¢øµ¹1u¿7¦Ôèó1:|½lœ¾)yħx¤,ß”6m¹7}"¼ñ; Hïé§áå Ä…4¹òÙiw{îœ,+¾ïÐó(è³ôïå¥"¼ç OÿbÞ#Ó[ÕazK‰¿ž’·a&â]™)]qôöþyA§ÝD ×ÒP×ò=Em¯¬8j{ù[ŠÚž){9t7Dîi™*YB±s¿„sJl_@¿—¸í¸T®>œúÑš¢©éΊL Ä Þ+ ¦^ú~ƒ©W¾Ç`êù®VYw0uŸ%3•¶¼ÁÔÙõìöéîž]}ŸR€¿g(Ø®ÜÚŒôóÊ'õì,­~þt0ÝYJ:?ìå™OQ²ÊÛ…¶¿J%Ñ N˜ªuˆ=Dt(C³£¦8È*Ò„Ýj¬Qùž*²‡¹¹ˆ”­ œQc®’cŠ8pïö±áY>7?6KÆÕ®bð°ç‚üƒ§åþ!Ïw¢f[Æp=Cý@§×Jß*¥–¸ªèOŠgæ€Üá667lÐÌ=ËrÓyPs¨,i–Má”wf» #*ºZ`VD¢‡z#®ˆ‘èù úÏ„…+ÝÜ’°š±+-Vï·xç·—à†êì "¶’@1¯ñŽû½ ò QÕ•çEUWýPÕU;ªÚ Oí¡[öÀSóRîf™kTš“i¼‘Ô„¢IÂMfƒgöÄ3;—1H–NŽªcì`gO„qE {ܽw‰ñƒ×¾58qCÁÛÀÄì}vës*mφö?«7Òðö^þaÂ7®'«G€vÇ}ËSŸ÷áÁÄÿ(âyYjÎÙ+ÿÅ“hö ´þž«L\•g«X©ÜvQ|® )]åó¬{aløTÛµxÙÊyiÿ~Dˆ¾×¤ÕnÈ58wrŽÌÃgù'Â2Õ*U»/È9 z«:p7ÆG›*Wg+F1®ÎVP84®ÎVÆî¥ÂÔ-Ï«ç„ÈB¿^ –XEçýI]aª$ŽÚîÉä “Œýï üoúo ùoŠ÷Ÿö¿q…y¹ÀþÕ¹Â,}A@m®0qéæn€?ÌÆæ;ó‡Q^;|câöbN25?'™ÚÊdÌö ¬ž2»ÌÆ]Æ”öåÜetÆ~)ŸÖXû ‡} GïÂ{:´ËCâ +é°ˆµ:r’P”‡í-È)e|Ϻ¨*î©ð5 êqÒ4i•Eâé=ý5æž uù÷ ÇÝΟ®áô‚*èÿ|šÎ'tÖRI+Í ŠEöeúø™=Ýß?NnØäVÀj“G„ÎgŸžDeÂu»Më4m1 xkØßÚøÝ¬Þ麗WŠ$)Î7”ä‡c-µqzé,‘@9»PP+ÈïÓÃÙܶ¡ Y_Ü r ØtšN¶K^䣘¹ . È´K^ °#oØñðE±¸“4Z@i–™bhÃ0´÷´…W ]¼§ F]Ü–!óe¯=”îaõ.Cc@€\ë > øV)Ú‚¶‰DÈô+í‘°È…sÔU_Àú ^@+Ô°`ˆ[XÀ¼¦ÝfÛdÂTᆲ¿Þ§&î„%CŸ°¡M Âëu¼È["iÉ„…B,¥‘<È\Iš†9ÓAîxø†Bò„Þd.ÔÒ÷Ôñý)}oP™´…uåJ^³‚pmØf¯ôI§ÑÓÞëQ%ÜtÉâBʳ»I´ÀêÿÏÉ|fP@…º… ‘F×e›îK¥Wñ%Œ—ˆŒãÐŽòˆHB3¯^å{‰1üʳPeÖN¾¾ tݘÖ@"Hë"NÙl“øüJYóEVbd{^‘¾lP‘È jÄàül‘PHH@ê¨ Ê|w.7xmÍŒ0qõ4‡aêw<דã\Ih#cU¨D•ÛE(Ó^Q¸)VM•ÔLƒñ™²ÔÑ‚¤¬p†>:²ôQЉ÷“µ=â «ãvƒZylq‚•Í–™Å‡ó %¤“ÄÛb4ÍÛHY(؉Ràkä`´u““Vô§ñÓ'®F:ÕNO@‹4盄ܩÑ,?½î9l‹èµg;f„M: ó¡ûN˜²ÓaIoµùáV9ÐøöIÍÝ'Õ<}rN‡¥œ}Â3[ú¤j铚GŸÄ˜ÅÑ'î>Ù_ŽOÎèÓr|r&¾Ð$ÊXó OÝqäîŽÃåX$Gw$XDíŽCKw9º#&îKX÷ÒEûýNÔ*ÜøwšFuCØÞrhÝÞÑÛE.©¢Ia)TŽ€Ý$Îë,Z›Qª$)6GYŽKŸ§‹¢†ÑšXxe4S‹qË•¤ËÖîrÇ=AãkvTÞ:Ô$©ÎÈÿ3^,þz}št=àTJW‘'ßNÔ_ïà&\@‰ ª;mí¡$—¨MVT’I!Òæâúílö@2û-È‹"CgB)ÑçÜWo'cÑ?o?²ñõõj CígèQ;}„}÷–Ú^ˆŒ2z*˜5GawDÌ0zØCx IÌj»WFQŽqQb}åð/), ,Õ0é–D$8Iá!“÷WL€ƒBZÇÁÚÖi lø¶Þcoë8Là„Õ›ÍË~}Ø ¢Q¸ø"b¢À%^P”" 2!óçA‘•OƒÃ½}ñú 7ª#qà†Ã´éÀ-…ç“Ë^Q2Ü ­ }Xm;±hzS˜)_f\_È'Åô„_<ÒmN¶ž'[ûaÓdëç;ÑõÛâÖ?Ëožò>ñè¾ö}}aBRÄÄ$ÉøÊÉ/^IðF&¶Nò <"Q2R·ÈpR‡{B6k¡(ß” ßEÕÜ/ ý"\%iËbe1¹åG4UÓ›=“ÿ| gŽjE'û9*7“j“Jš™íZ•µÙŽ5U Æ­×€œ0;ç³)´‹¨1Ýâc´Œ2u‘°›c°øz¨ÞÆ%ƒBs('Cc8¨¹vˆS„²·¡&ƒñ*¯aÆdD1šK,¦ FŒJªc©¾öµ¼9­KQÁ,§¸E$1ã|q7o1‡ÒÚ'Úe» $6m4´>„»Œf·Áæãû›Ù»º»B•øÓýü»Û¯ìfºxœO¯žp£¹š<~™Àº[Ú«‘n~ov¥w+þ(犺E¶¢Ma@Ì(÷ þk+>a’¹SVr3†XJGy´ï§ÓñíôŸxîEêϧXÌBqlêâ>ÿƀߔØß§ß¥2ÿŸƒr©Ì‚ RÝ/Wk•€•‚Zm¿öVZ%¶ç öÎ9ò§ÛéÄ‘’}üèxÏÛÂÂßßÉó?¦÷×·O7öo‹Ç›élïóÿþ)úêúñëÃDÿ RçŸâßÍy´ïþz¾"{ŸÿÿêïÈjøýO¿Ï¦7ŒÇ™®0ùezÿqVd׳{X±¯?ÃBµƒ ¹þ Ê®EXwö¶ú/\B&„Yf˜—w;™Ï‹â³(>Ï~û%––ÏßDõñWÒ)fð8ÿ¤¾ã4ð‘6z‡ÿ^ïH±èö+Ôø÷¿W®?ÿ6á[ü5-ˆ¦±/‘—-€;ìÓíìJ‘¡TªÞÀÙ˜“ƒñ /½)Ôd¥=YØkÿoЦÿˆFžjˆÉ'slÛ „¶ñß¹ÐÂÁ±Ó9t´(k >Óš=»œChÑ`d<‚b'ŸÆ×_}u;½šqó£ì¯ñ×ô#+(„n ÿ÷_~’/£ždÿßuìý/„^ß=(/‹ÔsÛ˜¦´ý_bçxÆ{üXø+WÓhõ î=Yï ·#ù¦ú=Çêßþuñ¿Aª [õcvqÂÿ*ùÿ{ÿW^ƒäªíQd(„DSúþ¿Ã&¨¬Bò“¤Xb8CÉD7Šø…!œn'¼ïo¦°.@pÀ0ìwÔ¿¼ª¿šÜ™„nX;ì~Âe›õûÇÙííì "lý¿í±÷Ÿ'Zvdä»ÉÂlT’æôUþ>R¨¿5Ø2]f·ãëhä9Ï”²>cRu{ÀyO ö©ºIæBY ƒ$8𬔉EåEv{3Fú¡Ú‡ÙbŠâ†‚SøñˆÏ‹Û›+‘.*(Ìq¤f‚ðhÂ9S pü_ ±ÿ+6䯂ÉD9–<9=\TØ›7Wf¬úK”pr» péaª’°æJQÂ#W£¨Ä ÿû§Xj­q‹¯aãØÿûL{÷ù9î&óqn'>g!ó@©}ßEæ¾’ðÀL`•ß3RÝf²†Š‹’J”®êIÈÕ³bìº(“³kQº}ßžghW%Á²‹Œò¶Wë·ÄZ/’ZÛÿŦڼl†Ñ»Ú…o‹zA¿Aê7jjW-Ù¨hã×@d$beÛ’ñ~(þ_oÔíø_1<-û×…º%«ÒÿlØ—Q܃Òx÷–Í«eã~ù Z÷?¦o&IÖj‚”ÇEÔHò*ÈôÝb~?F$%Úù:á§ÿå'òq‘Ñ’áþfúäØxÝØ%Û/2eø;âßÿð_[×[Å­+øw ÿÆðoÿþÿþo)åÇÿ¢5º}ÿ8I‡U(²$õ üKüÝTÕšdÍ»™ëxq$ö;sÑtCñÎÁQ,7ÿ>ö êÈ| ì ”u&÷ÛZ‚\†ñ‘Êž§¡è%Æl›¯f¿O,R¬*ä)ߣ^L2 ”såìñ¦0}Sú cìß`²é«WÛ|§¯öq$g·ƒ ÀðïÓÿàŒÎsÂ.9ÿ7ìüð{ww›hâ¹ÿgíÀÿf8¼êÑäýƒÏι–˜†‰[LQIõÐù“ùGùØøæfAÀ`¼F¤˜ˆ2 Š‚·¤H+“(V‘g›…*ÿkJõ¾ Š|ýúë6κ—>ÿØO\ÿóÏ2ZŸQÿ”‚ýZRÿS*oô?Ïñ8õ?ù;‘fö[Ñ¢‘ùå§Ø"ÿͧ¿ü”T®,¿)ÿ’yWŽö ®¤úüd)àçmfÖ8¹ZêØØ˜[«©G¸¬ò†Bñ›%­6HW§õ,ºl¡8•/òUïbÈŽá;6F¡°EÚ¤¾Ì¦)±h[Ód©€‘ö4_M ‘"OP/ºþ#Y†Hõ³Í‹¼™=¡ŒÕÿ½L¢ :]Á¿ÿ.*áhØ×Ë‘ë%aªã ”÷ˆ®Æ×Öúòš!xÙdÿ©¼Ô=ú+z4ØÓ…VUx\m‡š=H#¶ÞÿÒFNr}D¥¢\£½˜§VgH”à)¢¾¢ýR˜'0DƒT΢FÀ¢rª=¶øXKÇ?é,] ‚í7oJÛ1º‰=Þ0-©Î“R ¢K) íEð*j±™Š¬DÿÇXŒ)^¡AÍ_tÕqò…Uð%aÛHHùmlµHŒ<-¤^+¨]+}•Üôé¨R»&R«+"µ¤P»&RVDjyýy´ºþô#²”ƒÈ ÿZÁ,/™¨ô›æ$ÿ´Q)á_jê{’÷ Ìü\”¾ÈÄÏKiùç}^ŸuÚ¯—ÈÔYÏB¡Up¹ò\®ì‚‹×rw•&Î| BÍUªPó-ˆ6*í ÜZ öpR .=×R[Á¥gÙHöWDp9AóËÊhž=¬³oƒ K—­ëÝ^V8Õò® ¶]&N«ßNx•*E~²¤Èof©ÍEï ®´yé}©…6½/¸Î.ѿϽÌ.Aês¯²ÏAê DùÏþ:ÈϤÏó9©™¤8õ//¿NQJ¾¨Øn"Ní¼u/~’d•ë;䮄¾5® fÇÒ®Mìúœ¢¼{IiËDÛËÎD>çÉAÞ³ÎµÑ·Š Ó_÷õyIÝ×ç¤î+jí‹ï™é:¯—Ý6m'Úø¢ðÒZ®4B¿#ž¡Á «‡÷\_‰ë›êë§vf¨•Ò¹3”¿8sµ¤8sµ:qff¨•J4ë4C­P¨Y§j…rÍ:ÍPëmÖi†ZµÐ°~3Ôª)^«jÕÄ®Ñ µR±lf¨Jfk4C­P8[£j=òÙÍP«}Ön†Z5Áë4C­šÖ•˜¡üEˇ%Eˇ•jÊÖ`†Zµšl f¨ÕêÈÖ`†Z­‚l f¨µiÇÖ`†ZƒÆiõf¨U«›Vo†Z­®iõf¨Õ*šVo†Z›–iõf¨5¨nòo®Ÿ&ó'Ø\K^Áó!é›+æ/Ä…ZîÜÅ=»F¡h³Ú°²X¯mÓ\šßxøI4Ñs)<£”šiÐz ”£v¿Â§vÞöR¦Ú=á¦êËkaAcØiY¹Ù¡uÕèIÂ:П„5ð_ÎÊWÄ~þµ—³ö{úb~í¿˜_/¹˜_¿Ðb~ý ,æ ^`1ÿÿÙ{Ó®Fr&QøùÚõ+ôöÜy0”1N/,ýLÝsŒ1`° c›®¢æÎécÀî›±M-}oÿ÷7BK¦2SR*Óé­ Ÿ*¼¤–P( E„T0,Ž™Gö>_fê~‘ÌüvùÌ<Â♹ „…1óÈÎçÊÌU½§ÍÌéM¿¶)e¡è ÌëkÓÏ,‚«S–ÌÕU0(÷à‹`ïQÀ,ˆÏÇcŽ ? ŽØk/šL•É3Kãü*B¤ `YŒ,ˆÅü„B©K‡g{éð<£txŽ)RÎA_4¤œjl¹®Pˆ€D³àÒ•q`ð–[ºéÁâ³át³€ÍÀƒSeÀ€¤M³‚Iѱ¥uKΦk^Û7žyhÂ&n—¸wkØŠÕ%ÃZûà1maÏCïP7S$µ6aâp)R]çó&‚øP¤KñûCѪœ-[{ž­=[³µ´U¸<-må- CK[m‹ÇÍ^‘¿zÈÿ›Åãf ã­õŒolòâäy<Nï3¿’ßv qw}÷´FºµN·C.ŽI­Ý¾ho×>Ô»ÿ3ü5+­rÖ ò‰`s[ìEþ}¬7 M^›öµü÷›ÌåU=lT:;Óþd:~Ú¹ýã¯"ଟ»M³|>¿[*|ßÛÝ¥ïùû å‚“'ŽS,íJå½¢CòN¹œÏÿƒäÓB÷z™L{cåÏ—ÇAßPŠÝßžÓÁä‰û¾&¯ o_îúä?&Ó»Á(÷ð¿ßÈ?òýÆäXîá×àO áïo€æ‰Xab}<öÇ㬴øÿEK=†Ÿÿ€ ?¿còûö¡7&[åÿë ôs׿'Ç{{Táé›/£ÁýÆ*fÄúÛd<ì=õ³„Úú‚]Áâù7º(ƒY_ºûÁýV‡süÌ¥{ÿÛ´?»‘úËKc–…îãUØ*r+ÐO\ýÂÇ]H½Ñ¨TòU ¹Êe¥]iÖºµ6i]5áíßïHë¢KŽà·jxÐá52$—ÝH0‡¹šË‘i’!•ÿ*ý7íøù¿ù\>+ýÿ;+8,¾m Vm Rqò_…ÿ– º¬ués_Ÿ§I´/,@ÚX…} RDï2 >ËË"ÓLBÞüÐiÃ%Æpì›4.åXq$9‰D7Éιí=>’éCàûÁx2%Ó%c²µƒUüú®X\Þ <ˆ²¿þê’“¼½ÿôêq¡íB¥ö–xzúž[ÞÀÎK³‘•' v`錧á¼úüßòâŸL>j>ô‡ì/M€^aÁŽÜJ¶ÂX3àl^pÙúÉ ´ÍWçõ¼> /`[? À~Ô†.¨^Y °åê86a|M _/Ø×ïKú]ðO|zÏû°&ЯìëŒ÷¥aÝÖ5½KXè× öuÆûÒ°n—¢+>½Ê¥Ârà^¨ 4^°‚º° ÑR·̉öÁ¶!Éù*>Ø…•Á·važâ>]l/ èymBíØß D2Ÿýçꃪˆ\Ø Ú*°_ÙósYIóÊ,À¯èkŒõ²­¤BëËÚâ§@ëëúc}…ì*iÑúR¶÷éÐú€¾ÆX_¦MeŽÄë™Ü:‘™Ç7N, è™Uót,*3“öÜwárZD½è~:ÐêTÍ) [‹K„z†Â9í8ãÐu’2ÜË3]-l5.׋Á´xá×È D¡<¢Pxb_•ãY{ðéaÊñÐ}å± Ëváz°páò"/–í ¥†–¡´?]-—–H`eä.`:3Ô2¯Ø²ùº[¨ìbeœWbQö63C­ ìu;LÙëµZÎlÛ0ò”Hï²ÝÛÏ ¯š¦ç·™HÁœ,ÖÁÏq·f›y+]žaK<3À žï-MÛñª 8î²KqJš~"*N´žàY¨x9Ï@ÅËGñ,Â#Õs÷½QdE6€ñ€^•ý_bT/sû—ÕËÜýÍJÕKÙÌLÕkõŠlýf¦ê¥ìüf¥êïKÒ çEîûf¥äµAï’v})0å9žƒÎ o2ú]"ÀJV¼Âð&£à¶Ìa˜.§º}Z/àD¼"ŽKÁ‘ã'È“ïñOE»d,½&'È Ôà®|UOÕÐJ«`•N#]úV<&Ô«bAHŽìU;A¶Döª Ç¢ì•9ÔŒGÙëöŠ˜f§ì•9AŽEÙ+pÀ›¦—}‚‹š×Á+t‚œ6 Ïýx3 ¯Â rÚD¼*(^¡äùPñ7çDÅËx5OçDÅs;A–à]ŸdЫ²ÿKŒê;A¶DõŠ Ç¢êU9ÖŒGÕkõŠlýf¦êU9AŽEÕË?âŒMÏK>AŽEÉkƒÞÕ9AŽË”—}À™:ý.à•V»…ʈUª*,VF¬ÂVôHa¡2b†°ª ‹•s:OX°˜q7'ø×úy&Ì` ^¸TX&øs:JXõ/Þ†‘*ñ¤y°êOïÁü° lñ„tÏA½7X&ôéóþ™ÀËåý ?ÍÀŠPÿJœa.›÷/‘úÓÀ¿|ü!2,i’ ,i+,i²¶aI“µKRA/aµÃ’"€—‘¿jaI1@Dý‚Ã’ÒÝúEzýÇÅZaUOSÆZ bEÏÓÅZaUOSÆ*†%ÍOV,Òë^²b%ưª'ˆ –+1ˆ=C\¬¬X‰1¬ê)â‚eÅBÃ’æ',Ôg©G5ÌKN,üµ Kš§tX*üë–4/™°lð×&,iž’ ]“þ²eÀÌ&ýåÊ€Eƒ¿6aIs“ˆ]Â’%–¹V:,in2`6ø-Ýæ]è×9,)î Öi«z¸Î(Öi +z´Ê Öi«z°Î(V0,i~2b¾ÿó’«0„U=TX¬ŒX…1¬è‘ÂBeÄ* aU+#–4?!1ã>nNð¯ ôë–4O©°Lð×$,i^²`…¨•Ã’æ)fßÒ³~®„tÏA½7X&ôë–´0Þ¿`ð×$,iŽû€U¡þUKZï7€?D„%=ôÇŸã†%‰:vaIX:ˆJR±-x¡ÛGkíØ7ZÙøP0)@Ú¤¹Cjo¤„TÃLçª]t‘¨.^Í·è®ÈÕÑðϵZÅ"×ä…áÙ.ä,&=K†šYÂój­¤çõyax¶ºI׃9¨¤èÈYy£ÖToýµƒUÂoaNœbFhu¼Š˜ÕPîâ0›Ž lrÔ¦Å}cQ¢p«$ÛUÅ­žãηŽ3f;¯E–&°ñxBaà¦B·Ëv9¸] Ã]>´ f3Û”t—ƒÝyê v¬É÷øv,QÇÎŽ…¥g²cùM¦ó±bQ ƒóÓŠ5œv6,%œzÑ€µ3UØki]Y€×ÜÖ«ÕxàÚ™&bÒ¯Ù0±:¯¸ ¬U«ðÀµ²OxÐÎd¥RCšª%ÅÒÍh©eZ*F”º(Œ¦Àcãš®Ý$.w1÷‹Âi¬­Ñrqªæ¨sÀ©ñ!&3Ï’JTk@ K4:]¨‹ÆéBêÒa]ôô/„¥.«ó‘ýV¦‡þ¸ÀÍL…8îR…xþR…Ù Maç¼¹ºMf¶8¥°µ÷”`ƒú3Gˆ­=el ¶´¬ äÖN>+{«Ô B¾`¬[{ÑÄ¢u³qb!·vZØX°VòcÝÖí¦†]+4OO!-ŽÿÌ@/ ϱ¬]«ç˜Ç¬óÂs¼ÛæùúÅçÚvä1_7­XüzÅ1Ó]+LÛÅpÎI’c:U˜ãqÔ ÃtR6½LL'çÓébzAŒ:]T/ŒS/×IYõRqœWÏ‚ë°i'^L*.æ$$‘¦73Ô)êKy™˜^(¯^ “ì_Ò¢…òê%ázÖ½bZ޹ñLÜJÖ®¹s82™Ÿ‹î|NLæçª_ñšÐÖšs>3Y.àkvJ§%Ë|q`[{pÎùœd¹€¯Ø),ðÅmëö9·³‘¹9ªÚ@œÀ\¿p Ï|*²p Çðš†ÓàÑqôòù¹±ÆãÎÖúÅãxfKÄâqÃW8ÛY¹çÀŒ ‰qœ*È l®‹Çņ̃‹Çq2~œ*ŽÄSEòB8ò2±<ó‰Ç°œŒ'Ï€e+kv\žœHî-ä¶ÕÅœžn±—„ã…òäåü$²X(O^–gÙïEcù›ž;à™ƒfô™¼{‡åEÏãÁpzŸù•üû¶S˜ËJ§S;"ÝÓéÖ:ݹ8&µvû¢½]ûPïvþÏð׬tÒÁzÅc“`s[ø"ÿ>ŒÔ†É{aþvÿ~ó××R^ÕÃF¥³3íO¦ƒá§Û?þÂiqr·iö‘ÏçwK%‚ï{»»ô=_`ßñU,” ÄqŠ¥ÝB©¼WtHÞ)—ó¥|š@è^/“io  üùò8èÊA±û{Ãs6⾯Ékgë Ù"Þ¼Ã7ü¡ûЇÕ=ú4î=‘Á„ôH•|÷PLûјü…«wêäxé÷ãÁtÚ’›ïä¼?˜öH·üm0yä)ì8ÎŽsp°Ï ï¼ù·Áðöñå®/ÎM‘ør¿ÇŸ¾Œwäxoï¿zßž¿gnGÃÉ”Ï![-àLô-²Õ{|~èeù—J–J¤ÚÐÓQú:xr½ù†örŽN{ÆþxP‘׿Îòò”1ŽûÓ—ñy™öí(¶€1 j; i?Øz,èîFÓ[R­aôÕ ƒše°7?ÔøË“— äYB«á™ »& {`¿„À~‰ûÅöä¶÷¨ÄûÝèåæ±oGÎ*šÀIûÁÖ·´kN &-Ø\Ðb@öµ÷œ!–Ó­ËrEÑÞ ‹YÖàuV½š°:‚7ø«÷Ôûk5ñQ_Ûj‘ÿEíÿý?ö¿lò^2y¹O®ÙñÞdÜ|ëPMê '"êî¯áø©(ÖGoÆ×[¸«ÞäåÉr5ª;¡ „:Y¶„ü±_Jý¯°Hýo·¸_‚ú_!ÿªÿ-âÅô?|IJÜQî2Gš½ácÿ{– >J÷Hjÿó2x~êÃ®ŽÆÏ£qo: s¢öå¸?øÖ¿#¿Vÿø•LGéŠàön0ìƒ9¼#Ó‡þ`Lîú·=Vy"ôG|5Gwƒû4ýwsä4GŽFYRÚÉïïìgI社SmW®I»?é÷Æ·9¿.ù“éÝãà&÷ð¿Uz¤N唤˧þÓ— eP£ñîÓozc²5Åús–±®'þ>ôia=TzH×׸þããEó²Qû…x3w=?7þ–uYä7m7ý©+~¿{¾£‹âu‡ Xpý3Û8¢_û×'Q¸]iu./:5BGK½?õ§°±&ý?¦ßŸûŠÒT(QÑEñ…†Úiûâýͳ¶ë0 Ý‘w€²·Âý±Bà{FææSïñqt›6Ÿ6· âÖdðWtŸQ jÓ5‚À~$Cïòÿ"ƒÿØz‚¿oßzöôO|úçl á/>ý¿²vPù/„qkðöOòß¹q¿÷ø®÷_LÎæÖŸoüÇi« žzŸBUðG¯Êßì×,(¥‘€¹sÊ BHbH^\+ªd±£,ù–åDñælˆ‘Àwöãwã~?S¡ß°G×Á50CÕ‹!PžÝŠ¥P¥`Â?FÌ.œJ=Ó‘¯Ó«ÖQí¸Þª¥Ü¡OyütkyÓ÷Ïâà ¬Æ_ šA¹ÖMmÖ¾¡$©êIv0¾fÿ¼=.‰1|~y ˆ~[ÜájµoÁ2ÀI ¼=(¸ƒ’9|~áÜÁ[ÿ8úw†í·b!ï2ð`Sþ•3|ÉO2nc¹Í·ØE\άlÏcøÛÅ*ÇÁ9Æ€>X% æ¿}3„ð9|–(A8ñæj°MgK;W‚n 3¦¬7†Ó ÛWÙ4c‚%ÞD ʘ(S ‰‰7¿ã0°`2£”¸ÑJ =t³Ž/,!n”"…ÎüÒ¡?~ñI‡ <0p}`ÕÑü<Š[ËÚ^„ÙŒ¡æ%UÑÞ)xê–Ç‚Ÿ±ßÔÍ‚ŠPApí4OáÄ$–_j ©jˆïB˜ø—© w!Ö3›Âè"ËcÈâ T«b«Òz×bpQ߮͢¦kq ‹šØ¯j²Ö{. …×¥m½´oç²´oÓZÚjcÍËó#lf,Ö÷«E©nᛨÁ ,·iI6W— ‚vweø…mÈþ‰o›ÉùE”™TêDzÀpõø…ŸY<¨ 4ˆÌ%ÙfT¶™< ›…ÈJÏ~Zb,š×´î_¨j³K`¡2# _W3X´-DKn:}ÁE«Y²lÁ2£ŠdV™ïÚÅ"Xüï$‡>òÏ߯ÔMZwbîqŽÔ.³iºÍRÒî°Ì›MJçÞR6×ÜÃøŒy·w[F##㌌@¿ß.25ð–˜ÁA¶5°—°m†éLD$Ø8™ÑRdlÂB?b¯¿ßè¾ IÆWZ %ï 69I]Ñn`Þ@¼OJ¤#̯ÿ‰KËÜz¦0œ™†G„ý,‚ù2Œ¦ædV4+dli ´¨ˆ@æxz/q»°ç-ý ô¶G|ß…þ‰'ú]Þ¬’ü¶ì‡Ô{) «Ø¥R˜¹;¿j𜆯|þ¬ÓÜÃÇ«sÑÜaÈ•KY}ÿ<“¿à9R3ÿÒ0UÓmV†>ñ¯Úfx† äv iÙU.£Ú#™ ¶ùÖ¡:ÅæNasË…þÀ™$Ó1@rdÉç€øP±Z®ŒüÉù7TŠ`´òfèù¿ÈçH¶*o…x…H&*@ãcPíÞ|ƒHã4 áÒ8Âþá¯eýÁ$ÿãÎÏŸÒø×tzè0Hb¾ùñqÔÄ„K&Ÿ™õDï¶/U‡ýadâ+J‹.Å/'Ú•?[íÊŸ-á6îΟ#wç±»ñÉâ©q›îw•`ßî½OCÞA`?›YÍ•Ð6&qÜfSýZ‡TY‹òaÐ aßïGõÊ Á1Fø®F‚šBÂMûT»i7²Yâç²!-`ªÜ˜[7ø“~ºß/ò_e~Š2’Xæÿæ>éOø'Üp¿JÿŸYú§iÔ_¨° &}is¿>¶|“³P¸ünlˆJˆmð`šAPÈÿIzòßh|·–ÿI­ï†½}ÀvŽþó«Œ×Ëx•õÌ$äeKQÄ1½l¥7ÊóH½ßBoÖ TÖù_R6¼Zå_­òþé ɾ%šãµx^ U^ÉW4G¶ÍÏÝì>Õ›Ý-x]X¨ªMë‘M¤é,»éWaº:Âtòã S YúË:HÒ¥pì”$iš {eD¨¹ÂO,ILe5$é$]I:IA’ŽÓ8ˆNÑNBu§0´w1âBÓ‰Ñç~I3lÌB©ÑråEÓˆûðº^Ÿ–&¤±Õ’Ú|$¯Ò™NRZ§Dníu½òõ ⊈úŒZ³º¨O»(.¿ ¶]¾¿ÄX¸¿—¬µ98¸dU±ZINÇÖÆßÐ:ÓùdÓ6¬[…Óõ8ÚçÚŸ…’ëDÉ‚ªzÏö»ÓYݤ±CDüE„J…ÂY{Ï1¶†)xCßþ4fÔQúCÿ²jŽÐk¶Qì`ƒëšmâU›ÅÕ˜=—‘¢pB yRW‰”é94é2­V¤ŒÃèIOŸ©ÈTj5é2•¦º$ç@Ð+<=v\e ³3§Ø±!ªO«A(ÆšP=MAe°B42嘚úuÈ‚é”A—…»¬¸¹Q⨕Fà ‰­Tš›S)”«¦OÎ÷Œø— !©ˆÜùZ´C@ÏÿŒAƒÑ¥ã~ñÇ 䛨F(L™Äj)ú¡Ý [ Ä–KDé ¿„J®šj˜dfLëo‘Já²gd^ê`!:”T™ Í Ì!£úæ©Öâ[ [ “%D\p^´X‡`:…çLçþ…ìf\îA˜Ÿœúñ,†´‰1Žûâ§KŒ™-1…d‰ˆýÒUìò¦$‰´5Û]V—1mIgg÷‹UòÓ•]ìÖsÛ´õ[ïý‚O˜0õÇ[ùI¥6[¹ZDr»MÆ»1‹Òkðþ§â"ï*Á«ºÿÉÙ}½ÿi¯•¿ÿÉ)Ïñþ§»¨‡}â[å¿ä¿s)ñ‹ãýî.O û¶¸IêI{ÕLÏÿõFw³”1²Ú.ê­¿qKݘrë¸u¸%&é LéþWReÄ!þ©šqzÜÇáÆìaÓWÏô\7e¹Qî&–¥—5íšKøuã›aƒëgWm )Þ¡”¢¡´ãAIúY°;À>ßþéªn1™ùv ‹ÔukpB®¡‹aýÛd•~ŠF’ÏÙ#²`és–ž–¥‰Ý˜IìЯ™Âë0Ê·‹†Ø°G£O~H‘qè¢ï†#ãF‹>©EŸ¿F\"; ­Ä4!†¨ŸÈT¦7»¥¸8,‰MÕO>U«Û ª¶¾¼A²0³.?:ªtdU·|d·j\HÅ)"üÅ•—!x×Í=©ïVrMVºY(˜6lx$‡\’ñŒ¡T¤‘ÔFÄ»®þ¥/NqÀU1~k&ývèûVM¶5’0¸'ÊŒi7ãXÕ7Y®¯0\ßf¹ö¡ÜC±þƒ‘[sèûoÿ¥*½o<}¼WÙ`<•Ïíqeï—䊞±ÿy©z:¯êNý¨F&ƒ»¾EZ\|ŠEÙSŠèâ÷XêVp%o£?Uhv¥Åì¢9OÝn´ú†+.ìpCµ‹åxDS¤Ü5ä¬Y(šBZ[„.B8ít¶Ùnaò#$¦Gq¶ÞÿZh*ÍkÝSßû+ô •LzU9t(öTŠÝX W¸k‘lÖ5‚ºFêÊJÆäû¬JÆŒjÆ,¥^U˜ö‘EhZqè—„’ûYõ ÑØâÊt‘>ƒDW h¿lþ×*Ô’Õ/Tÿåã´”÷­¦Õ EIÊBnPÂÎb ëx¾ÐïÞðÙ6øXyÁœßYÉöR9QK9ŒB|ÉÒ‰Ë%D³Z¡Xe+Ñ™l/ÂhtÎBÄìWé8dF™2wý…o™ã ©aÌã,ì Ü1—3ű ëåV@؉³[Ïé5¹t®Î1ñ®P QŒD£+ ÂxŒÚBOºýd½øÄÞäûŒbo†]_¢»Ò^Å!cgs‡s8|†¯Âpe…!å}6Â0 _E¡‰¢0´U‹'i?Q‚0N|ÛgƒdÞǬ¾¢±Ï „ ÈÃ(!yøƒ J•7O {II,DÚî†Ö¶;ÇXAYL–ï¦ø*·ˆÉ&Ñ‚~- êø•ù‚Ù·—L«pãžÀ‰Ž«±Tea‚*ÎB³<‹õÖ¬öéR[R:åuÑS‹aÙ3\³ó–ÝÑ.öW—‰ìÉž›‚B3ã‰nº¯úͪè7©ª7¯ÚÍò´›xÑV^îó ¥xÕké5vÙ°WJ«aÒjV­æU© YfÒQjìNëSÐiŒ*Ítlë¢f™)\ ŽŒ¯èøZÒ&—Ô¥¦bÔRšˆäV¦Ë¾<Æœeü'ös[¶©.sÉ•¹Õ9IÛ÷n×»E;Ó{—8<e°ìråO ï÷¿B>îw‹KÏw<<àwœüK_œâ €{œäj§ ÄƒCòdSK[ÚÆ5.QÛr&©IÚ4eí«´]giK¢Å­Á þ*p_î'p'¯—Ì*p' ¸“´î²S4ÍõEh ÿ×ÔÉ™2]Å~™óí•‹N)”ÿ«à¼æÿZÄ‹-÷ËöÅI»Ò$‘ºÎ›-úk¨‚üÆëçwO*Ǥö­÷ôüØ'—¼ûnÿÛ”—ÈåÈe~ëOûã |ãL«ÞêÖNjmßµ.®ºüÙeFWëzO3øðÝî¦×dç¶÷؃öCR==øú–ëÕJ§–…ß«èßë,i^Á/-^£qqe^ËJ§ãõÕAgnn?GW‡LF­ZïÔ/Z¤s\©êaðÚ«}T ’;/7nÊ5·ÙÚxK‚¦zZ«ž;Yö^È’ÓZå¨Ööšãã¿þYjf¾ @y¯øfu‡££¥ÂˆàG½iÀJšö1‘œ<ôJ·Bä}ç ··[Þ-”¶K;òhû·/Ó:YuM½o×»56ÁÙ|mºè%…<à ¼“÷d#ü\¯z¿Áô5\Ìðαèp0ôA»¡Có³Üá°ébé‘aÿ+¹…åóªwaI|é=¾ô BFËy ÀbaÕ¿Iïù¹Û´]G^ wýioðKŒÀD?¿L³(‚{ÃïYÚv7 ½)¹‘á¶UÃ/£Ç/RÐÈígwtÞ¨qL€ˆ\·}UËIág„Ù÷ãuèG ¨ä1ÉPçµ\y“tOk-ï©@6#Ç Î¼¤×05^'µÜ®±'Ô@ëê{ãßÞ¦N?x8ðÍíìÓv€jª­n½uUã•:Ý‹K@%/r|ÑnVº$³ xÖ7Îë(ûü«ÝŸ¼\^›Š–¼¢Õ sѲW´ó¾ri*ºë=úØj7 ¦²{RÙJçªi*»/$a*z ¡+ª,†(\ÿXiV>lÌ"RE7[k±]ë^µ[!ΰ³Á˜ÁèžL^n„F5|yºé7²õböàC¶â”+ÚÇÜâ­kãÂÖ®lXnŸ^‚ÔÔP˜Š’ˆ'$` vj”¤¡òWµ¢‡¿¢‡/KÎ`†kÀZ—N$3 ÷ŠB´œÙÏ–³…Í,ûºë}ýÝûøˆžbߒЫùþ²Ú•™¥Ÿº™ò¦~4ØG–¥K^aÅø°DK„Éã—á-MÑkš{¶–qÏŸ%Œàg}tÙIEBŠ©¦Å¬\5©ÒK(7aÍ1nÁ>Wyøæ ÚðÝë¥>œ‚²0ܪPcl×[P)ݹª|ˆ/~æ*€Âa•|®x”Ï’L>W‚÷í|nï8¢¶V&ZÏžeÍlý“=ƒ7Ђ-пªÍ8¹<+à_ Gã×Å6Â0±Mß‹ôq)ª_1ó×97Â&`›Žƒ ¨Ì¾;ì{™6³ÕŒ¯˜ùkÒF,I@ßõÊ…¸G[Ý‚ÅWÌüÕºF,È8é˜f¨¤ªU`_)%f‹QøŠ¿Z,ãBÒeL©1[Ýš¾.¶‘à2¦D—Ý‹jÅWÌüuΩœÒ\öÀŸ¼ª£ÈÄE‹ékÒF,I¥è_üÁU]J†–=?÷ö}ZÆžà‘¼À·ÚżJT²ÁʾÝxÁÄòõ˘éu ñ0a”Az •äü-¢…’×­Ã#¼Ù›±`%L¡ý1µ\h»œðöÖT1À1ìq¦qà’g“Ń¥«–Ìœä‹Þäì±¥¸©èÉa@d9Pœè@òÓ‚O\¡äNå>«j%lËF,™Â§c(˜ÂÚ©ŠáÓ4ŒÔëãóQ., 3Ÿº=~Á;¬-+™Y 2kuÄÇ; IVâÓIŒ8—9Ž­¶Â™Âîª)0üÓù+¬©¢À]LžžP–—×zè y¦ÕËj¾ôK,UK åÃ#0ã-¨kæwKûl Þ²ÿñtð²_;U Lõöš€;,Y,ûŠÀ¾¯¢µEBÍ,fÖËÞZ ðq…]ÂÇbX&¼ÃNÚ³c¤4 dIý³?Z=º »yá_‚ ¼q†G¥<½±'å7r¯-ømÇ÷{£†O [ÍʇL ”ÏïƒÓéOÉ—þítÂç›nÇè(ĺmõq >ÁÚÔ;Ì×wAÃK”EÈüaWr/®x‚!НFºv©Õû©rwGzÌÛ–ú"¢“;éÿÏKïïæý«?I(¬bèK†™†é_ AÀ ÷]^ègÁÌrBMe"œX!¶rÜBû!TH“é-Á²z JZÆÇú·ãcëÇ[ 1ØA ÒÑû0çäç„:lØ€º# wÊ5;K<Œ†ý œ0 Ñh 2U7|ñÐ)¬È°Ÿ׉jðÛŠÑ—¢G¿m¾ûÔ 3”ÇÏÊq~žpŸ6÷ ÿtM+¼º¦%sMË~ìÖš—zP¨Ú9¼·à§þ±F•Òô/Ÿš× ÜÓŽ.ºP¥HÛt2%ñ±Ùcniø¥˜qJ©^í:ùP¾”¥ÕáÛµôm7#>í±O†vö½zÐ }sØû5ïz4ÁTuèpºØ'À| cÁ–~n Ï1tÛžcÝ«ýÐÐ]—·†î¸ü#ºÛJi‰=Ð*‡ ‡zkÕÜЪ•[ß3:—;l7¹ÿcÙkZ Ò7}Y¤,ÊZ.Ñð¯˜%{úJPÅÝÚ–ôÅ€Zq|ü¼`ßµGJŽ0M°‚®9¶ µd¬ÈRÞ!á‘ä²àú`ì1‹ ¡çG]»n]fŸ(GÙ#ö|õܱ”=«,?~ˆ ·2¹ÖÌ}zAÃã¾|Ø°Ç¬Ž¥Íà ŒFW Ëš¿Î½zÊšDÉY`µü°æÒÉ•Ëõ¬FÐÙ˜þö\j.rª›ew´Å"ûi¿1Á»¡ f]ºÙó§Õ=>½Ð_ž«#qד¯Ol©Ä´û½Èé*°šº¥i9¤ÖeÁÛ»Z:^G&ÏDÚ^DCNîaà«Ã,yÐl§Û1ËFŒõ=~ÃÅ*Iž¤&•àÖNÅË“µgþ*“ \Õvø•pÓkd/H¸v–ÌÅ iß –Ð1,‘~ó«Žè-Â@%dØ‘µj«ûJÖ)nt}ÌlÅÈÚZy÷“u˜:cH¬Ýwv€zU;ÙWê—6áŸ÷µÐ&rEæÈö¼==uâú:9ò?®å&<]rí8”A›ˆåLy^ìhúÇ81ZUšÙÇ>/Ÿã|çþ1T?•R†­=QB‡aÿçAkCØ+¤ÃŤëmÙÆ–Y§=/v4ýc­*M++^­Øk-U1í^ì%UÆp2@]JU‡ôk¤{MçNnÏ 6¤&ñ=í궨èv‰tçûê°Œü7¡ÀWpjF ½°Òh§NìÍŒ_ÁU¨7”òœÇ”Þ¸]ð`"æ"}.ÇðÞÌeÚ÷¤‰5*‡L „ yíý~½)§gášç­P÷„GkB-Œõf‡GÍz+SÈŸ¢“;<¤^Üç­lóCèñµüø:ë9ðrµ÷0¡:€~ßx~/NeÏ÷ˆH1Ÿœ`¤>½æO¯ÅÓ‘ Ž!œ;žë£ùx/Ò-[½ÎR‡mV†”yý¬rØ¿UÖ¢“ŲYôâôqdy Ì“UüeÁ8®«¨q]Í{\{ ÇUÔK¸ökÇ% øâJÅÐ"‚0¯±ú 9Yð~ÇvЗôЋh-ô¢@xVì@G]×|Q 4]6„òò¸ }(//è,êmÛ@§0æ`{q¢P iF¡²òÑ_7>¸ƒñE,’;Û¡1Jr4ØVÔ‹µd(ç^ÁÑ=­w(4¢©Ò®uH¥Ý®\w0ü%³I*0N |¾8FqÒ=¥‰º¼•NÐéÖÚMrxÍÞêÇǵv­U­aÍU£[¿lÔkGøÇ“…¾j¼‰Ví¤Q?©6j9¸jŽ4à_å}碕%g—,qöJä¨VÅûF¶bÇ%¹Á*4Ît¯L£&…Ñ(2»&)ò¡2h0”Äg:øyůÚ9ÒB0=z‰I¬ž`{è6/Æ Ô¯EÜq¡U7·Ü!“’:OFç~d$zÑ6§Ÿæ ì"!ƒÊ$£˜úææ[ú Ès«s´™õ=ÚDA—8§P¦O.`a$ò5=Ê×),m XIë¢Kª ¼öÚ`ú®ÄAHIÊå»$†õWÈGôv “Ö%Ç•zƒ4kNå¤F9»™E’UâÊã ˆéwí=FŠgû’Î|¶ç^V¡œózÖŇo“"pÄ’fXÒIŠð…8v/ÄÑFðRœ Boe‚½ݿЭ ½](ÎðÚlµ6ˆ˜mÓ‹–H ÜE ÃtÏž ²êE ¯ó(ÖËøV8*îæöáÍ)€Ú)H ‡‰Q'Žå ˜­_†Â¿J‹r»6ôP“¡ê®T” Øêר„âý¸¼~»öŸWõv­YúîžÂÈ߃nF*äèª ÛÃJûäŠ>b=PéœÅVxíJµ{œÐ-ּɴAknrÑö>×´/YÎ*Äì>³»²”-ÎpÏå<›‚$‚/•­Í  Fdk@ !Ùlñ9ªˆeË(ãN0H9‚—‹¾ß™G$ø;à ûÝKëÚ­Vû3k’! _µª]Wvf:•lç0†‰•Œ:$ƒ`Ž¥´ÔQM쾿 ­«æa­ÝÉ)49¦È׉SNJbþÞËÑ9´¶î°Ñ½Ã4ÛXψY99ƒ—ÇÎÍÙÃ6"Ö::kÄ’»Ìaqή¯†ÒT%}µ*é«U…¾ªÑ!Mš¢å’g«®w•fö‘ÂPÈ'_þYRÕ›•“,9PãØ5)Óø·êÛ”‰`«™*É›Šb´B ,Å0ãoŒËnU1©1E)†qcBÛT““Ké›$îXØ2íYñèU,R[Ñfh*+{¾XÐ Â{kÁ:ÄU€ß+ízPšþNuY *¼Ð *z÷:粂T÷Ãé%‹Qe|A̲­XÒEOG Éî±æ™…І3F“Ö{1ºc„Ä7a”v°rÝ=º%õ2·í—rï¥Ýxiw]õ#zy,Žf›“ºFÔ^L"Â,Î2YÝ–ñ¥ÞmE@Ù¾ô»­¨íU¡^ÜÍÖ‚¼­Zö]ÚëøRÞÿ^XàýïE§\„C÷¿ï¾Þÿ¾ˆ[=îýïxý{1ï¨ÛßÝ»¾@{¾GÇk®EÕ'À0WÜ_ú ¨¾“™<ŒÆSr‡Ù£îý­p?CIgŒû·£ñÝÝÓn±éûð¨wG^&@«äq0™nß  ð´šÞ……Œ`3ª´ÉÑø©7ÙRq  ²È&l†¤7ŽPÖÝ‘>¿@èQP±! ÈmoˆÝL{ ‡ßáîúý©Û4H‘Ü>€VsK•šûñèIÜã}?z|}ÅÂÅŒ4ùßðgz9m·ë´*—Œ—·@ÃÁ­)þÒ9 b¶®ä¸Î4óm'ÈX¯Zõ.ßÅú*b C]rÕ©á)É5@ ²Ʊ;‘\?9n þßE1Û®½¯ãqН¡Ê1ê]µJõžW/ÚG¹¨fð,ŠàdÏh”´B×Pî7kíöôó¡Þe ¢BÞ-R½h\5[ÛÍÊÙE”K÷÷öÅ{ñcÁýñð¢{Ší8»9v:ß=XN/G Ý6®˜€Ö®tëô¨H¢rþòK«tðÝ€æ¡÷Lz™ð¢%«¶Î½¶ä vmQINõtætàÐ*ÍvAÑn¨pѪJãò´‚ÅÑç=n6iÀ2ÿ”ÏíQ/³ÍPwn=»nk]}/N®HØÃ½ˆj· Õ&üõ©ÿôéŽ."Ô+@ó¤3š>®5FMŒØD•›ØUâ÷ò —çØU¦ãøUâ6MØ$>`ñ«<Ç®ò©?¾_å%6ÁŒIìÙ_¥?.ÄïŲŠ8Wï÷“·~G£á'ô¶"g9ø—%G/¤:ý%¾žöžžzãG…htí ïà§á¶³m,óÉ yÚÞ¼%“>½Ký”ˆ1ÈbrØCÛVD)n÷?õo ËŽ{Óú$'ÃÔíß> ¸Ó&ÍþÓ¸ëÓMr¤ä̸ÿe0ÅM о“…‚=Ý . n'^Cø·ß xÀvnýámÆ<` @µÊøÓh8„ßZ=4ºA—Þ ô8¿g½†ö@aìŒ^¦¤Ú›LHô¤—~VT‡à#àh4˜Ý|©x!îÑÅXþÖªœÈƒl÷ŸMØswö÷(ÐÝv >|­—§þ˜–¤ÆƒéÓ4¾“ñèå¤óô.—åÍVûCÀ8`îâþ~p ‘Byñ?¼y‡­é¨w—%ß@¹º“àûP {¸¿½:Ïr´©zæÖ‡·ØŸãäA½):“©×Pg:î÷A˃¹Lû˜;‹4öuˆ*Ôþ‚IÈ*;åm§°[„_¯:Š3ª7m“÷Ð%PyvòÛ•—O ¤n;û{‚æÚÔÞ=fIÀô|9eÏúãþÓwAÜYŠ*)†¨\|[iÕñây“Å ”W(DÞ‘2+Ÿv‰>E.iu®;ÆÖ°Úp÷Üf ÿÇZû&¹U35……0q9ËŠžeod3KX¥ÿE/h’Vq|U\P*mKû´Ò8†·˜Ú(­E¿ÒëTÛ¬{‡õjÀb³ÂÌ6x×» ™ðg¤, ã½$Ɔë¬éVýˆ½Ÿ²÷Jƒ½Ö¢º¬óN÷D+ðù@´D×£ŸuÃ+Ó®ð3‰>QÌKí²“Eõ=ËUlý ë€h|4Ëu‹ö˜öߥC¨7ñ­U¥c0ßmW`W¹öÖKØÚ Ûn¥ÅP„Aû¸¹ÉRIF}é3h§Z3tÔíté¸pÛSk#Õà»X,§0+U(°åîÌðؼ~,4ðîñº¡çEéùeÈBÛ›T2œN)AÀ²«ð_¶øúÂd1`ÅŽ¿"êÔA ¦v>dÜÎ?ˆ6øB0Vû,K®Ý–ôÕ®C]ë®M½ëP½Rà£ÕSø‰hÛ@Ú@½±7)p—(|=?̈…¹©'Y–ÏŸsæÍBêx%#~ Ÿ5øIòZSóQpذË«›¥eÂÝ[ú-ÕÓs'Kß ì­ÈÞJì­ÌÞv sZýX€°¨?6¯ž&ΤÎS©ã*òåSu(?_t™|®êñzqn˜ZÀPS:͵>ñ!;ØyuG!+u¥¨@ûªî»Œ‘çSâΆ¼çÞÈ’ yC½a˜½ y½‘Ý·ÈÒ×gËfè¦×«7õ73µofâoÆÿõyb× ÝPzõèfQn­póL nÈ[;7øÕ&pH²QÒÀŸBUm£Átª*UÙ_†ƒ)¾<ÝŒh ž¼àÞí;5  n¡…r£gP«©QWrÿ©e˜>{ÜD-u‹l2Á¦Ž?¦"ƒ¹“ZN\¯R9ÅžmÒàK—µV†«Ô`ùŽÉQ"QOxo˜ÔlûØCûmoJ˜UyBÆý¯Pûa{ÊíГaïyò0šòêÁGÕÂ}üý"ð-Wiå(ÈÑ}O¦£çgÚ5¥¿“ûÞàñelì”é0ú¦q,·0ýòõ¡?EbëÇ0•ýoèmäÓ¶ñ4¨gê‰iAqz¾n?õþ„Þ¨Õÿ±÷Ǻ?®Øú›>Œû0wäKïñ¥/&‰^Ú3ÆšiL/õÑ:’ïíCÿö3mæYlÓXë÷ Û—L ¿³§ÐyËDϨ H„K¿£ÞÉ]´sìÛI7'´?AÓcä ]¢Iz2º¹ÑÚš¾Wšó~j×ÖáªJj)̇‡B$)@°Mö=òºÃѸõqDy‘÷ ŽJ1&í°` ÛòG1$ߨÙ'0%ç¦)9?”'äüЛøŒ`síÌv2Î7ÄVk¦É@ÅÐ7ç‡òDx~VÞøxM: Öø.“M{\ ¸¦'¸†è ‚ïðÜ·ZUi!ÀºT4£G½ïô‚®‰ÖÌkÕuÿ’hUå‰(æå'Á+³˜†2¸¿²U!v–óT"›>£ƒÅl ³Å` ³û@y–à«7Køg‰ïmg‰ö¹!,3ÍÝ¥úf9›¡aÒ Ã(ÝÝ7%|õF‰_p”|¯k;Jìr#`®I6HºÕö ~ÁAºR m»B>Áh]™5ñ´/5 E²i|^° êªNSWËG/:eÅý=˜*î›pìu>clÉìTÝo>¨ˆZ4¦ÆÙ«ÈX4ÁLU!w·ªúgô»cj—ËíŽÌkŒ¹ë¹ªº¶-˜ƒ^@&D̯קcݧªiÇÔt>Øt,¨Íó·%c>´—¢Ët"ÙBP`¢âŒªòàöÁUyE¡?ßï ]Š'Ûù‰kBB¹ã›ä€ga9æB@¬¥,å;¼­u“™+…Õë{W×7®V Ñ.ŒTuϪÏw¹Œ9îQÞŽDV/£]/%ž÷òþ!û€e•ó sû¡®X, ;Xñ¦Ÿò¡]›dpðÔ»}€é#ϰY£§}RÌ zçF„º@œPSY†9¼eærú™* ìœBBHÏßž_lÕÜm4+u€…ð~Ø@¯¬þ¥ýÙ 0F,âŽÞÝûƒÞÍàq0ýŽtLíkܧªÿ­wË\º$³ÏíAŠ…, XTée®gœh<‚ÁÒVçëT2ô6L:©x¿;”Ú†¯o±$[“X•¨rn@aVïÌûíZü†è~Ãn— ÔDhŠ*0¯ÝÊg[’aPÍ-øm§Pù~ÛÂÏÛøž±§°bv}Mp';¡hf¸„ÍíËã4G.†t‡Î|Ȫå×]VšWfSƒ¥É-£Tê”FË ^F"^Ø2 R§é°L†=e0ôh/K*Y~‚ðÞ~ÈÚ®éçk •••êž{G?üD…Ñã«îüS÷wh*ÎÐZØd+,u±ªbÐ^®U ÃBÛ‡] ;ßAs…[EJàãà.Žºñq´-#iûÇÄ’(‚–>°@I’¡9|ú2údR—2ï)…C”öäP°sÚÒ&Ú–„RÏ׃ &d8R[–L˜(raÒq»‘6TÁÜÌ<ÎÌŠ¾*2L IžÍ5^*uJ‰ðøAF&ØO`ÇnJ0zJ 2ŽAý‚0â¹û~½8W¨I„®ªÙ‰M¼À:Ëÿ”ývùÅz!ÞSùÏžûg_WmŸ°?°{Fä…Çÿñ¤ÖüÐ'êbOé׎€_¸M˜:̔Ġê(&‹\…¦Š/u¦¥‹eÎLÓGÍìtZ°vÎÄÏñøP–ãm+ì$§ã9:;L—|(«àÿ޾äqø¿CÙåEÁâH^MiòOˆ¾ö+ú”ès¢Ñ'bžò ò=eä‹§¤§ŒtKœ’O/é×2¥ärÞ› !»Qø)'"@Çáy0QñOŽ;' wFî¶)¥î w ïáGF¿ûY_ (ÜÁŸhaüèä9Áw/éW‡ün‚/.xÒÜiÐOšfz¸ÿèzÕýòË/éñƒÙó¤ÖÀ0B?^ÁÇ"%®½8ÄUZ 2]F0:•«\ÛŒ‡ñtèî§@Õl$yŠn‡Ž'ãññûqˆ²ü3`:¢ü)P53QpcæQ%~Ý£dy‡,w\§C–?ªÔd‰&& D[:õ¯b^Póâ’oAuR^p,ϼ+Þ\‰$¶cuŽ®¢eÔ#+„CHqÞàÝ xâ9‹1jĵ6¢½oë ;—cI24¡ƒbK],ÜØZæýÉNÕ0 kƆՎ6 Ivçµ¢¬„¹?üUòºŽµµˆ”#ƒýÐÜ5–ÚƒåúÂh^t2ÆJš÷Õ òŶµNÀçrSÞTзêx?WàìË£©5 öï5Ò¬TO1UŽçBÀUÎi²YØrAÎ%,˃œÃ›Ùó`UºnÐU³ÁábpÀ" œ´kŒ÷ÂJK@µºtWÔknù[ÌË-†Z(«Z8´ _’ W;0iÝšW‹:æ@_4¡4 êØ7ˆ¢‡(6q,ao0Ú¡Qû½ÖÀô Ì#ÙÙÙ`) ƒxºh4.Þ×['Rè Gûû:pÔÃÿM K^„Å>úyôuPßå¥PéóPé=·t>TÚç¿ä/½*Mýhä¶}#ÝËldtK9'‹^ÁîÇMÚðoÌ~Lý‚ £ë ™½á=™$šÈeéò¥¾¸l°@À€XzGL‡˲%²Pz…ù™¬TQ­Ú‘øOÙþ®G1«C‘Ó‚fQØÈÒ44Õ&-8iA¯GH/RóA’1wWöºc™ `ìxnmçÛ d GÐ@rtUå,ò°†4XCÒ vkâ¸þEë¤qc ±öÞW:Tìããz÷Ô;§fáa,š¦‚âü 6p¢èCâfäxÃNfÄïÎ1‹ˆœIŸØ÷–,ôŠTÇó9tDG. Àbê›Áí( å•K«lÓôŒ… D‡²çe5ô‹¿çÙU$GU¦7Ù©Ï1½M«FY™PÛŠ­áëxzû¡ÒXSgž7›^Ò™ ©â‘ ÝITñ4†ûZW^¾ s Ž©Gv0M"Í ü†cöØáñ©çv©Hq— ¬–¹fD˜ktTm›ûCè`ð…Ñ’dè‰LÙB}UOUE¬>*”¤¾eS—Ã5õ¢l;Ä"5ø|iBî’äµÏt£0ͱšºàÌ. »´ˆ ‡f*"0õÕ½ÐÌô"0õ4'è²Þ”c.«RÄ¥EH³jÊPçÂyéP,ÃÇCüHEqÃ@æèãÓªCÁÓѯ4”°5häøª%é_`¸Â™/ M8ΧCWÍѯˆ¯ ’ªêøk7éP]ŽUGW+`¯#„ mmÕ‘´4TÆ,Ôp0¬\(Ü‘mHm•û4T¹«ÃÇfe½¢c1fÕí`öðW·©8a­@);­nÕ*®’UAÒNBrð9`þ}á^ƲÌÍï稺úøñðKÌH'ÄŒç®aý¼‰è’Eï+‘¸{CgDߺòEOIuo ÂçUÉ!ˆ®× 7cvèŸJõÉ ,ë-eþÊ£ <7ü‘ÓÚ) +eà²9ê&ÊË >C5 ÀiRò°°)œG[ í# z¯xµ šÚèÑÚˆ(dòh+Ô„½|TèBå‹Þ"ê hAÇ_,l˜§Ñyy"Ö"ØN@ð¢•iÔ| ù—a†ÀØö|n}/Õ DãˆpGÛ°ê¡Âe`’©)J)tñsÈÓ}âzCò4ž^žx,èàv £§Ð`˜À¶ß!Toî· °ÔƒdõššA(à€ l$«4>IÊÄ¿”úXø¨ÂIå—w“kK« ^ qw++¿¹Õjèò±û–å—þít4&Ë’½ÜÅ)Y)/y‰n|êoÈ+‡Ö&K‘xIciƒµ™à ®S5®pÝ@Žç˜(ƒ°LE Ð165lÇ+%`Æ2ny]ÞalÁ@„ÒÀÐÀu ùÚÞ VÐ ^k‰ àV³¡ëž¸\/€R[”ð 16O#/+*vh¼ zA–¦Ò„°³ˆw<>óP²¦ê^*Z¾ÖÒ²û2JœÀ+‚ºq«LCd")Û{¡9Tš!JçMFç1Z‰”\UãáS«Íxíô¾ôIÿKüû@úéߣÖ½Gžò:¢/JÄr::BDnvô|Ø}QÁ¤_ýìuÞèP¥/ªØ-vQ¬B[“Cìu/_f P´"Šfóch4¬³Õïäµå•P‡_h÷aZ^4ÄÒU?¢þàüრpaf€©IŒqÁ( étH©t/_V‡Æuôخݱ¡“­˜ÆØ®ùØ®#×g/7§Ù‰b,3½ÀT>ä[bx ç–„IÊaÆCv¸eÓN•Ûù¸RÏl°TggvQj‰µHJJ1Lš°Én”<=¾”¬Ê4Ò…6¸ ?ˆÈy|1ø½gøøÀ­ÄñZa–l”ALüDŒ"Âx¤{¥C<å¸Ä ±Ë“¨È–r¥­ê¨Ç‹d¤Èä¯Köôä+Õ¼XüùàžESnÓ`诽 ™ö>÷‡d0¼1gÚãw;¶GCJ/Îm‰7*Šáå†D†£%•/n)†,0—Ú0;ùJsÊ¡ûö¡7üDoJ™ îdaáOb›y %†ýüÁM8ÉÐíî¦HžP?K6Ãì—M榪±¸/qnB¦»¯÷áDTe›´&­¥÷ñ*EZ…u5ݱ¥"ë¢ÄÔ±íÃFëóª–YŠ ŒðÆs7ºþ*ââ ì²@{ÃΣÕ7¯æž×5ž-¢ihm Šúû´>UÃè pÑz˜W÷€Ö=d³PÌßÏǘ¯3'ï”zž\£rg3R½(ª§6ºeK[ÄX»9ñ¢ûIp‚ÚÒ®Òj¬:»\à%†êˆé¿Ó%“jò";g$¹Q#7Z/jçF +Ñ¢Þ›uQï'^Ô3.jNÁÉV5§‰E-ë–uáçYÖÅøËÚN©ß3=57IgzI–Œi6»ˆVÐ)pÜ÷'ѽ¸ó«•öåO …‡àÑ(ãíÓô+¨qÖ­–›PD½J17G¡”M4ápivÛƒœVÆvUÎ]Óµ„Yâ$QôHü‰­h®¥ÈŽˆ2%Ï:a¹«t_n!ß*þîëÚu©õ%Š×Ž)‘áåú|Pÿövȉ£†ýž|aº«Þ#°ƒšˆyòµ?×|t+‚)DÂêF‹Y®7kRE¡ fåËh€ì¹ßc÷EÒü¯ƒéiæû¹<£[iÑ¢öë̱]gÑ%°¡²†ÉøïAßU•òÙ ñ?ßÏä5O72Ðÿs 9ýÍ{;?O«ä H8Œ´Ñkƒ¹.Ûe…=àÉ¥Ðu’—õ« Úd²nµ€©OªóIæ‘„Že$áÈŸ( Oµ÷Õf#öŒqz3­o…i iÛmÖjmÿÜÐçë[c:öÁáQ¸c¸u;pèFaÀ!@/¢a‚a‡9UßÅ‚(@B‡›"îlßkZ¡â¹äóøA¹'¢bª§¡¨¢ÖIÆ•]´Ûµj4dL‹‘è†9@wíÆê±Ñ€ñøb¯º,t H¸Þ¼jJ!˜<Ê2Æ´M:WK8®Þ(šwáÆ fè‹Ó CnL_Y%bÐÿæÖÍÐhªl+JV¤Ÿ©wQ&0FE JþìpŸoY^¤º˜œ¬U ×nùM’ XFB]˜7Ô1À.F²?Å#faÖ~¯4êGlî¶‚då‘A0® C¦,ª ?{XKVÅ4a,º 3„ýÑU6áU†ø*½¦?¾*"Àê5Âê5ÂJz½FXÍ%Âjöà*ø'GTù§ kÅFu?Jê²R=Çߤh©ð \]6€íá_S”>=vo‰ÿI‚¤Ny—’<}fºÁR?IœÔUcaR¬ [Ê2Ï)‡R¹iø-C©B¡WVMùƒð~”>ž%òʱ¼’  Æ“ºpSèP%¼<‰pÖ”QKQç„çn¸R0}®âpç\~¤0z%-Š‚—G…â‰Tಲ-°Á.1Dú¢ÑC‘¡Cê¸!=sØhP¨ [,˜ŽÝŽPˆÆ&I_pRÀ´ïä){AŃa6XŽò˜+m”M•·åEØ\=?÷Ç¡Ð]xM¸~côUU_s 7ïÈ+¦aÐÓÐV‚Ð+úÏ&ð*:@Æ":&£<'ŠcІ± †¡Gì‘0¸'‰ ‚ÑDÀØÀ˜ÃŸ¬B_ìâ^BA/-CÈmÀKœh—x¡.ñâ\’¹XG¸DÓ*¿Æþx2Úâ#ZÛFìÂZ¬cZf h±v³§».€IÚ]© P9§Q'¦–'1ÃMbÅšØøØE™Ä 1‰_b¤md‰]XI¼˜’X%–ƒ± %‰GË]6V€: / ÊT}àˆ;_~{G~îÅê‹ ‚¡?^þ(Ï?FÑ>ûI\8S˜ø˜qCÞÄŸÏ4´tâ8T‡;¤ŽŠ9Å^v1&å+úˆb +Å.Óã v`3‰iÅäÄ ÈÑÞVQ/–ƒ"·hŒ^S6XŠcèÊ7#L²MßT«`ÿOšËÁ51œä}Îü±=äýA3ÖîñþP™˜¾ñ>Ÿþ8~ñ>_~{Ÿø¸ñaÇÿÎðvžðÁ.Â^ðq£W‰ dwv+_öP ƒ#{"ÍF^ç,À$ýÇ_7 ÃÅÆŠÍ(–8J,aˆXÂu“08,ÖÂ1……Å_9ó_:1C»)}+ ?’ônR‚Þ[ AïÏŸž÷×IÄ$f µÎ2”)*pÁ*ŽÉ:ˆ)vSâ𥄱KÉ—¬l\±C–渰3F˜Rü%9@i£åˉð$7â(žeHŠMò…Å´!¨o>шeTRò¤â‘ì‚‘bE"Ùat ’!‰EÙ-sDQd°PT¤1LH#¤ RE…Bƒ~”0 b>Ùdj~¦0 ¢? Gop÷x:!@%MßçÉ#Ô ¬U’Ò¤1j)à(´õpôS±ØÿýZ>¥ˆK£#¢v ášì£„KŒ/’#‹‚PG·`/šµö°F6€!%¸……ECU?žžÛ\2U\H4T ¾I׊6ì‰mÐÝë@UaMüöx~s<¿5žßOoˆ÷.‡ÿéb²@FB Ì7àÉP@ _k!¥ŽŠ’Œë¥A(Ê‹}R„8éÛùЕê…â ÈÇ@ÒŠÅ(¥ŒT=Â?]üs¥‹Gú€º¬“ºð£GÕ+À›ñoÇMDÉRúecDey ••C‘(âN¯Beä;º?~¼’—„ÑJ]½„¾£ÔO•ÊCZ°Í+‚À| p² pºbN”»üV(úå´Ò}¯fèÓ¾Ý~=Édø´ÞÓDZŸèÊóòLþêGÂQ•:º`<@r‡myL^…¦PEü&"¯þkhÕkh•oœ¯¡U,´ê*2¶ê ƒ«®~£e×&¼*ð;Lªv‰ÍPãQíþFË¿^ åk&2<¨z¤!(^ G†ä#DòÑo´†ör ’Á ÑhÆað¦=D¯†ƒ©j$â$]jŠr54e<‹¶ ìc/‹  È ?¦ê‹(?½r)^n`¬X?öâ±Y‘Wb«¸?ö²Œþc¯xWc«Û±Hšñ€ìeŒ ´jÁ|±d/«(B^4y,!{E¹ÛE„Y„ƒY†ÄX|Y^pD7ÔPJÚ+hŽ‹ó‡Y™ƒÁ”‘`Ê «H‡ ‹0̔ѿJý¥ ˜ŠÌ÷¥§—˜qR¸z87-ý†®gTæ<}Ùˆ^Lë_%’/V]ñàûZ€<·8 ´kã(8¤P+ÞÈ^-Å=;?PœTxÏWe!PÉçð<ù4®C8Sx—>}ŠP¦Ù– å´™ÝCÝY ³åÉ+[ž;[î¼²åµgËiÎá+[VC;G¶œöL‡-GyÞ§s+à4Q´©½oy´Oo$NÒˆ0M^ê‹-µ½ÉÍó#¬otŸU¥dÃj/—gˆ¦KJ+’'yÐE O°qevƒPØ$#ÎLLÀƒ1Nà`l¹î¿,:r3A—`öæM0ûó$sÄ×jÌA‚±Õ fá &3A¨ºýdî®ÁdÆ ·’iÄëEëÙEêÅ ÓK£—$@/At^´A5^\Þ\§HØì–f”w¾a|\;g'o­Úla|Ì=ø£p7ü7ŒWüBÂø¬ 5‘˜==¿Lû¤÷ü<}4€Í`À¥™ïé‘£¾§5 ȬR™–eïW©^w„H?¡ñ•ð§ÞZÏ ËˆXH£ÃXöL}·ñb½àÃTnN+؆÷y¿cœ º±3·s÷w,ØT…±à6±ÞÄñ:a LS˜…йh>`mòj4µë- F—7ã™~Ãiòð< × ´:ñs[‘.ÎÍÔ–»hçššð6[iˆL‰ H Å¡4#®í2„Ÿ£N"‚MšR°‰/ÄdE±iuóÎNÓ6$Ý4G‹¨ƒDš‘A"†p½ƒÈ«¦êÑ÷L)/™Ú ‹q]ST€Vz—3ïdšý"±k› Tøäy½Në"±}› ½T·y…'Ì7Æ.bçÍfÓw^Ädév¾.5ó©Ú"H*¥©f'$'<( ‘L‘w[YßjeyŸ•ù`+*~Éöö*Ë{«ÌÀøb–tàXÝ?eyóT$8‘·MʼnŸ²ñÚµð¹fKJÛ‚ï¶íÒÎ.BDUU³Ë€¯ë.wÚÅÍ…ç´Û”SMº·¼D³ â]äãz]ëN.EóßÕ‚ÇgtšÝÙØÞÓX{¦­aé*Ãõß’æ¬ÔŒK×býøe·â&uãÒ0û›jb^¾- Ú›Îçégá€öØ‹N»tr‹JMoéBöµpR4/ó÷O¾N;1.¦Š^‘&HBn´jêáòåÚgá×é/G_lw¾¸¾|2=†_Ê|É Uý ã¹=¾< ÉÍwþ)*XW>îyòÑN‚>1 ¯s_žwX¤¯U¤£U”ï/O¦0ÜQÔY !¬ö¦±ÐìÿÄ2¼œYxÖñ¹¶œ"Į̀Öf ‡Y]¨åÖpŸuæ!GÛj´Ï³«SF°P·wfΈŒý‡îƒhR;W®>ŠÓ²÷ø« 'Üu/ƒíœáæÕ‰{›âwS¤rÛ6rÛ³ó*]3O»"å’{ñ=°~x'¼&uÂ#£q¤;^„/žÌÇ÷MŽv:G;îQúÙQ8Ú~G»r^ç¾¥u;c5JÉ\ólÜà|{²à^™v^~õ6û‘½ÍxÖ2\§F*í&¬« ÁWÍÅmÑÒ,|¥€ñL²ï¹tÉwÈÙûUNe qõ*Y¸z•2W¯Sø…zz^¶_½^½^½^½ÖÄÑ+†P¯ï-œÂ᫪Iøÿàù÷çÒ#Rvô:S&þ78qE$ûǤ —îZQäü·Ïëz,§òu«¢tDŸ1)»Œê>\ÇŽ€~×Ów,f‚~–Ÿö4üýŧØw“àÛåÌßõï"SqyË[g´¿'t %c7»i|ÆlÆÌÞbŠTëÆü‘IÖCÆD¥ÛYØÔ-Ò§«¼½Ôé˜â3\‡£“¦[eLW™B­R¥+¬T˜/µö©ÛOÙ¥Nq&°—ºVB—:;, ¬èÌIó.\êö"®ÚÂå ePÆs¼RšjݲTˆe<ÍŠî9T5B®›¬ R›ào[¡J1œ»â8ç)S§Sú™Ó­»\¯®Vl¯®(—®4ü¹"r]ký¹ÚÌ›«­;µ·óå²qä2Ç.\Vþ[6Î["SM[;IÙ$=KîE¥¹ßWÛJÛg6:QExEºq¿!Пƒ¹ [Þ^Ì.‹>ƒÖä.#_TZ.kñ=<_ðlc׉‹h\Q ÎH3úbY:bÅLöhãê`Ê•aïlIc¥s´t½òù]µ¹ã•–‡Çv»Šåseã ?_Ÿöì_™4M)ã[ÂÊb9™ÎaÀ%d .dŸuÐ@ˆiyQE¹Pù|” þSq§âyN™Ý¦ŠöÂÝÖa*5b€!ÚI*¹‡T÷(¿‹œ¶Q:F%H?gôå±Ïä%Óò;C)½µ"€2¸Ñ ”úóߊô ¹}¤.O®…l{éJuv¦‡½XâL["Ê»êÌ\]tàz]é;2;\…ü¡Ð~.9De’Möó{;_$'ëzD¡å>KncÎ\¨„ É"½ŸbdH¶' Âi÷ ír‰m-<ì|mç™XÝô`$9¯/ÝFô‘À,_2KG2Ÿ–!šbdZÿ1µó(èF‡1f½B bõ•— IÞíis³í+]ƸYÈ»ìGq¹ÙœØ.cËËæ&mÔƒƒD¹Ó4hÕFù5IÚ«ÛÚ,nk"™È?&¹­Qÿ4ß…Ú¥Ê/-…Lþo‹KuVýxz^¶ðÛýùüß ®\áÕîÕîÕîÕNá—%Aʯ…;Ä‘xÉÏäW¬DhJ¿8ÛDh"šìA§r”ìh†s•ŸÂ‹Î#µÄ‹®ÀÝè óJ½öê9·Úžsv[GQ|?¼¤gñœ+ýÄžs¥UðœÃ½üOç:Gs¾úέ©ïÍ ùšîGÍGG½©$¤S ¹9º^ŽZ'G2ß$vÞŽ³Ãbö“Ãct#«“ç.Â5’¼f»{Ív§nÏîxÖò*ët<:I¼ôxd©áps§ð=œö;ûBgš’¸~ŸD1% œËùÌÆº¦é3Ý/Öî<Óôéo{ý÷k¶¾µÊÖ§wUµZ¢P óöÙû¬z#gù3õûš0ôZ— €‘,Ï ÏjgŒòšCßÒ,绋N¶ÖbòÆÌîÇ#㌨ ’÷ql+ÓªY$ÛûIa `{NØ6yˆl“”Ñõ;¦Â}Kö>f£2æã{/t QC6íDæ9Œé²éÎL"=š‰Ckd#ÄÚµ™Ø¤“T:8¸‹òGæ¢ìD˜Uå—”RåælÙ óž18:[ƒcéÑÞÝ™Ä%Ãé™X‘I°Å(: V·JÇò·6Súw…u™*‹K¬•NÓÊAšÄIŸìåÏ ŒKÊ¢©zRP§Ý,*|¨K?Žõ^^—Ç2ʇzw™>Ô²1ÈG6A[]ªNÕ:”L}{¯žÕ¯žÕ3zVû3‚ÊÃ㿚2‚Îâq=SÇËuŦnÖQ®ØLAä7Ëû’ûŠ %ÄÙ?¬u+8B­Tb¬†ëxhNS‡±‘æïZº-ŸHûò BŽ_oGOÏ/Sá«LåçOä5ÍŸÆq•ŽtcÎ’v„¶Ï™™Çý‘½k³>‰"ÒŽ>A'B"*ŸÝs'F¦žÏ3¯¥wfnþ.à û_Rҟчy‹;oq·á-áÌ>°_ô£?aÏ]ìr«”¶Ûu:Ùšn0”âwš…ÑœãD3®×†¹UDs͘տ²Þ¬œ(ÒÂêûÏvW"<á|¨j\hÜ1Õ&wès84„µ2¤Êlè ²UU©w¡ó߬ý$SÐ&¥8êÇÕ®_ÕУªxÄ[èèÁжfÃïFÐÂïÂéЯ7åG¢¨¨êÓ…]‹gCaƒ;ÇíK„-NljÛQvKË;á⎡çkuÏèàÔô÷|mêù:Ôóµ¢gÁ£«TæôIÿÛsÿvÚ¿¶âÁV3y™àNŽ'ÀxÌI7¥×¹@íO½—O}ê|"íz’ók—V¥ƒy<È4й+äysâþÞö?8CäžK]‚` æ4"Œy ß3çîÇ·ÔΓEKép¸3ŜډW‰®!·*Tf¿ð&ÂÐaÀŸ·Œ:ð±Ú~º¥Ý=ŒrEás¤®éQ{Áco¹}cޱ˜d6ëÔh—hd¬j¢‘ # •$È™-Y‚õˆ­ë ¤4•ƒCÀÚ.ô¼¹ºJáÏ[Æ)ðʲ!V:ê©Ô倌Q=dzèÃ`²y ùË·¢ý—DIs‡b[È:lpÛuLÄïì¢ÉE‘zNƒåg'´n®UËù&þ/_7ø¶s8vdÀ ó]–•Ýô·¿m¡lΠêÝœ@7¨-ªœÂÙñžlNaX¬3Eÿq4z¦Úþ#¨Æ“,AW)±èû¤7%ý(÷½Ç{Ò»½}A7F!SYûù ÕéØô#›> »yõ±¤ÖÖäMÕžrªèÕÖ¿+˜þÜ5+æ4´‡Š˜a0ô³:ÕÒÜËûM~x eiÖQïs™!¤vÄM¤Þ!Z§Cº§ÀÑO+³ÎÆ1©T«WíJ·æ1¨UDýª}@sm<ÐíKñ €2!j0Ø£w•@¯h8qʹ]n-ŸÑö¤ØŠã6[µjõñU«Š&!æÒBic˜Z Šx+æëVíÂÅ1¸s;…ußë÷”ŠÝK£lÃÖ®ó-YûÌnË¥Ú9Y«û~ݶŸq (‚?Ÿ©|9cc¿Âé<€L‚|ŒU`÷„…³yð Ç`9.Ýõê£U(iK©Ôµ¨{}YEÜ€Ä虳Ÿ~'ýG¦ZÃ;ÃèÉ¢îÿÏ‹KÐØ:‰Êƒ úx%ÙÆÃóÆÏEñôfwï^Hzꆈ"Z9*Ö=]9èN.¾%Z>ÀDk°É¯ieÝq…yÅÍÚ.6UŒïñ˜Ñ(ý¨((°ý[Å~ Wpb•ÏØ|ÅUq=Sû¬œsÍg*eëtO,lwoµòÁ_ˆ´ãq‡ò JY3”ˆƒmœ•+ÎRÈqAužÌóü*N‘}.û´±m4³àÚ°!òŽœB<—Ù.© (+g[ò| Ÿ*2ΫæÿûâžHmOìDVI‰?¸‚à#ÌV†GÉrv/‚&\±ÿÆCz¿OÈso0¦fþ10ÓÑ“ûèe8Nýôø[¸L¦ãÁÍ ŠŠ›þôk¸ôv>W¦&xÿq¹¿‚RÜ&å¶UjØmÂÇæ™Ô?F9¹á^#Êïµ Ík‰kìe©ü­y:‹Z dż;]ˆÐfÛ{ü…»GÄÅ—Þx€Í¸aâðjâbÞ?˜H9c©¼çý‚E¤¯gþ¯u9 œHàÞ"!b£|@ƒéoûHä4x›’{5—3TfnF/Ã;‰°JÕ°ÛÄ[㣨…|±-fw³{øÃA–îŸûãÁèŽ|Àžù¦¼ÄÔ@ ?ì++ʦŠeeÇ묊ƒz™Àˆ¦#r3î÷>“—g¹ÎÍw2ùŸß޼ƒÜ,-ì==ó?¥&ç*Ú0ÊAé$‘˜Ð?÷ìËG&Å}l“]Æ~°;'—Ïò‹Žåß\ ÔœÛTñáÐa‡ËŽêÇ0ج^ n¼L2af$BGb¿çÂÑ£·2ÍŒ˜¥%#OÇit«¼Ã9ªãIUÓw‡‡´znp`<¿RÝÛá–œWàdô† s²i¹±ºÔ{ 7K°¬nÇ_wÓ**iâ ºÈΔ“œ_ÑÉéLGã>;\ç-óê=¦þWÄ÷;–dür;}ãIüÿ¼ Æý;l¥‡óŒp²Ì…íeøµ7ômâ&ý)®} ¦Þ™zÿöé†ïâð/ûüŒ§cú÷fƒ\´á}ýww±2¤¥Ÿ-"Ó™Ê6rqrevÀ´ÑmlÕfÙ{ÊÔô-Eƒ(`Ü%tZðe¶RèU°Îézv·åŒDip¼¿ðÞq•¹íà}~ ¸}™aóî0÷&tk’7òõ‹ãcæAÿÏÏõ˜8©²ï1n´sÝDfÍ^µêÝlx˯Ï5¥ZKŽàæáôPô錚kÀE¡‰IÊü×)Fˆ'<žòÃLÂÒü -ðÌ*!l€Õóñ¼KOmBϧ⹰‚d°%ôÀ ›4À,l¡“Q¸á¶ Dê´¬—І ßÍ0!ŽÈ¹˜ñ„¬ÎÔâ³”Jþ „eÕ¨÷7`°p9tÆ8ýŽ„ÿ~BWìÅ•fcª§ÑÆh}TÏè×ó+Ö¸ŠÅbQ•¼3Z£Ýj¢¼³Ówþý2(¸>fã¾4Nû¾†ô9f㬣µâL !Aò3Ä=xGÛïä³r¿õ#4îP·mÙœ`%úWï'GeZ‘‡ê›\ÃÓáù=uî“MÅõsîð´­yŸßJ¢žW¥ K_——/(N¡©zç³£ó×ÁϺP ©Î®è³Û5ƒÓÃR޼åû$n¶WÅ™é@ÒXú5’ÇÞþO“d™¢—¹뤣MGØ’\í5×r þiÄKÉu¢`1$ƒS‰Ü,ì4ؼ †3¥äPð±ÍÕ¦z&ƒQaüqxiÞ–¦’³bÌP’¥y~ŽÎ 5s²¥nMȱPAÍmò¹­Òæ–W.3»¥L‡–€ç°al!Õð6ãâöÄŽ“Õ Íš/¥±æ•¢Ý×My¶5/Ä๻øË‘]øÍ @ôâºYÀêß³\ýÏÕÿZýhHðÛÜ™:Uk ޵ý(ÚãC¦o A‰Ÿ…ôæ &êˆTóO±ÝPw$Û‚„7Oê6ÂäÄéJF¢£Òµ(#^s‚¦|¿¹ÿ¯/þª6*´ª†Ÿvnÿøëæ±7-æîÓì#ŸÏï–Jß÷vwé{¾À¾çóÅ|©°ç€JU,íJå½¢CòN¹\ÈÿƒäÓB÷z™L{cåÏ—ÇAßPŠÝ›°B“'îûš¼Øš¸„Ù®4ÉG †nÑóÛó´àaêfvS”O`ð$\T} ã¡ñÝxð¥O³.õÈ䵩â~ðØÏÑ ÷ƒ1”tŠdÜ¿ï&ØÅBÔ?pÜïÝñhœÇÁdº}73ŸÂÁðùeÊ«Ñcü@n%P“¶8?õ¦ 1þ·Q ›9R’Þp8BÛíéë¡÷ MDOÅv(·½!gt3퉳·»þcê¶L‡QÄ 144ûO#ôõ{y"­QnŸdÚý/ƒ à:  6{Àn'‡?ÆjL:·êKu4`u²xê9û¾szè`:Ï’ƒ½|^ÈG/ÓRíM&¤Rç¥ïV=“y²›/²À•~ûÛÇ0Â—Þø;:¸þYg½ÛÏ.v¹>R '(¡t­]d¿öµÞ/Oý1Eàxð<hR_rÝÏ毰›ç©§»ÂÂáõ]ÒõMOüi%Ä»Øbê2–”E¨»U*l^ O‰ðc9ï²X7Ó‰&>¾Ú¸rafIõ‰¤]˜°*Ã.Á¼}Àˆ²gP©eySò¸ìPfÌ ‡Ó#Nx¤%µÙ½e6,– ÑJº%‡ç{ ùoËËÝ%g çWbuð/íΈØ}²‰EÜÁK×ß<z7ƒÇÁô;ó‹€m4?íëݲYi{#ü»Š…, X<¨³¥2šã@sé –ÜðêŠW·]d _“J^÷ŒÃð–_5ræì¸Ï‚«îõ!n„B膻‡†Ç„v#ÞæV†ºSQ¶ÎðÒj‚ï·-×Ý žß0WÑ€ZU­Ô¶Yt&C>|“" <êü«ƒÝzá¸CeÛÐàæT`˜žkeèåë”ÙÄe&xóQ3;œK›óCpz..Žã]3<‰É¡—¹QÁ‚á1æêWr6@d—/åÕô ÿ„øj¿â‹áˉÆÏ>tWPä)£H<-Eÿ9øX¤ÄYŽGœ…ŸÙ©çO‚¯‰4éxx.˜ð±L‰s7qŒlJ]+6æJšhã—_xÝÔ(ðGBÊÌ<°}´µ›eþ¸ðq’Ù^<2+ýk:5 üIð5;q$÷³Ü§>PòÜGžåÕG·‡Û ßÏþ`x‰GnoÜØHB¼Kp©“LGs.?^vTŽ…°m\½õ\½ysüX¦ÎY¯n ¬k lzSŸt8ôŒ‡`EÕ) ÷ròïžÁÏ—Rüˆì®] [oØ)§wÛ¥pDÁ^¤ó•cg”vf öÜGè-Å4Ý;1”uð ¼WÃ×­¶Ràê žÉ²CoTUÞ=Z—žø%¡Ué¥ürÑàÅÐI­•¯‘f¥zŠy3=WR„^b 3{XƒœKX•9‡„îKUÅ(ÑK4å¾»AÌyÒ®UºôÂV?¨´½‚“„¯8uC¼Zþór‹¡Ü›N7Æ0DŒ_äêw¤nÔ~¯50F¦Qéàå$;´àqÆ‹Fãâ}½u"9Ùó!¿¯/;¬Ñ=÷¦Õ’ï¦Uäç3Ð×A}—.8uK³Ë¤Ò>hö2ìâSï’S÷fSÚòoÌü#ß\ê¶L¯SJ¡eGjKŠÒ7õ?„nê­*Ì ½\¶]¹&úG@U½%VÝJ7å²ùªÂ"½hÕŽ‚·ßJ‹«su(Â_iÈ%½ ¶ª¼èÒÇ“ôz俈·œXcwûÒ²da0v¼·¶¯í.#è 9ºªrrXCJ©!„îÆëjÞ·/Z'ëµG//±ˆñ¢`ºÓøH²eÓØel4”ZábxÚÀù£}Ðlð[£pŽBï¼åuOa©5aÚ€¬`õ#8®Ð«aø¸<÷óT€ÉŸÂ¢¨WqêÅBJhçØ`[}/®‹}ï"ìû†Ùaåû}Øœ#úpÞ}\ußc$Ò(íˆe¹€úÎ#3AîË+Ý»˜³„èP–(¡TÑ4v8"£1µ§‰{¼#Ô#¦é´{ýH{ÒÁ^I?2©HÚêÌóÇwÕ µÐ&I"\Ô'þ¹‚g¼™˜ÆÎ¥—Ø.•¯.¶,*¬LFæ^/,E]ãÒGޱÍóLç˜Ôê̘Í×Ö …oñˆ¬csÜV0òé0а¾ª6r«K¿XG€ã¶BáY†ªú¸-=-ĉȪ7I¢+™Åí鎸0ý°Ñ1'¿aÑsüÕD="âMø¡ŠŸÎá?2ÞV–ÀÇs¼p«bŒ|DÖÚ@¦JÓVÃzG×!ýC?ÒGUz¼¾™&¦¼†JÍN–E`âÿö ~ÃCm<žîèIëªÑpóà³C`T>øÉ°"øQT¤¥:¼7Mº9êr”˜:$RfAË`Ë :u”\–_¥#Dr8ÐM.îÈ6\®Ê$i–£,™=6nAaqn/i…½¹ Æ gÙÙhu«ñâ¾æÑÍ (~¯ q¯Š‘Ï­Ù2'â gÉoæ¤N þü•{Õ7¹¥ƒxõÐß¡¥¬G˜ï&¯Ú 8 `VXêè¶à'Ì#<}è ÉÓ`8xzyâ1@ƒ{P˜FOÿ?{oÞÞÆô‹¾ÿŽ>&3Ç–ZI-I<š{¹8‰¬Å¾¢ôÆò{æÉ#‘”ÄXyØÔXäœ|÷‹¥,…n ÙO‘Íj] ª ¿*ˆ[ëä® I7¾Nâ xùúwé&ò‚«:òµ7`Q@¤9‚¤è>öŸn£V~ѵÎ"â°ÄcmoŠ~C"‰Ü‹äî¦a6'ôÏaƒYt<Æå(aó‘ø†â*H ¸FÕQ•GŽë@‡0éO”J©Må Š¯…Çȳìíñ…Ækµ(v‡áÛSRqŸÊàßhÃÊó#m6ɨ:è–¨:¨): ¶µÖr/k˜ƒÖa¾òy$‡=4Ïb»ÚQÍŠºT »´yZ‹•záÞ(1?C½³ãd¶À!"Øè±7á‘-(úßI­öʱ7z]–p±ñP«aëF]?C¸ 'Iý'z 4IBêz4Oêò<©§Í”L•zÚTÁå„4¡ÿ™ö@3™ôs&ªWscT¯¦YíäAÑü©çž?ÑÛñªëù†)²fQ\ù?<‘P޹Äu c:!1Öè^=ìÞ&VJ¡I…àyU‡çʘZu¦=G¨PâɘU1Ý={v¡8#}- ¬Ó-æ->Ãñjú:Q|Š}= »Ó’âB½Åa¸^s`bnCË\VRYL­•F–3J®±ÚEFlf…*‚§¡ª“öˆô Æî¿»Ã1 ºÁóïº{Cæ$Ö¸ïÃD‚i·'XØ ¶0Ó)Ö²Hë1©f’³rÒү쬜¶R…#.G­T1‡ÈplÑÁ˜„ƒEÉx2±|¦ÓÜ5†ë¦òæÓYã´¼Î|„Äý:×™»0KÒȸx&¦ŽJ‘É@¿¢Ës5anhÔ¡äÑh¬' “~r™Dô `·õèáG2¸É“LJ*Ö롛ʴÆ‹Ptg­3,2ë:ÿ†FÞ}» Ðèêk÷õÛý!I"r?654xàãQ†ÎÈŠ6ˆ>ã¾ö®"âÕZÄ’Êl–V·‹¾Ñ”*Ä¯ÒÆJã-Í·ô:üÌ ²˜ºÕ¨ H V¶@ÜXIn¬G7ÖMn¬²ˆÓ¹)uÍ éwX(¥O}“!ý.¥?¢ô©ëYH¿ÇŸczCæêÞ´ÏB¡I˜Å´ÕèR—>bÂ[`·âUŠ4˜±L…÷ü˜4W±KD+6iŽ Iš°½Ô'º‰ ‹:cJÖúC“oŽÉd‹Z¨$D7téJ¤T; ®ýŒ€Ð84Ô=[ÆR–D€¥õ<˜ê]5|%ð•d¬›‡7l®YÈIÁhî—ЦI«‚¤EvÅ -°„ð‚l‘&¦) ØŒÖLC×èi}Œ‡™b6çÉ™‹&J Ƨ¬v¦Ðw„0<£A?Õ¤ŸÜäLhHÌN@càÓ›H´Œ4(ó¹)±ñ Š„y=@d&3É´y5™ñš)7²ýšY}£›‹’ó_-x²ßöI¬,Ñ5Íß|ë£YÎåeÖ•h¢§w1F¦šL&ë1¹ Í/îÜDħ§ù};åǶu¿ü¨œUB¹ÛÛêµ2p”c˜–Iý„[ì5‡1(çåüŒ"Õ;L‹È 0åMh™œ6´·—µ·—ÕÛŕѸ#®&iïÛ¦CU}5¢Ž¢V DôkS§1Fø^ySBSOEê‡Ì;Å€£ýTÑÌñÁ6ìé¨X Vdp‚ $¸¹bŒýM°r!¦•à4÷ˆºB´µ!Bíêç HˆY|xrqÂÃ\% <„I-oPë¢õé}㜇¸É@jM¿ ó¢ô» õ›€ª³™Í@‚I£R§‰’ˆ;.¾5í¤0Ǹ ¾ C@VÌ~ÍþfðÈÆ¯ õôr¬ÈiããÙæßñ¥Œ¶åØQ“ñ’SAðíOÙDcMÆè]¤Ié§øÞõׯCÔ*ù ~úX]§§–ãË/¤ƒ&=àu)¤ÄªûÌ×󺤽µߺ±¥À·uœNž!Vsá¿kLJMÆ‹MØ !@ ¸S€FŸy¨¥KußdH²P¤Ë8‘¤í¨ÑX.&Õ …‘‡°©l…b…3ÀYNuAÂ'?î° g4F­Ô8*ˆ×e´Îm·Ÿ¾–ÖäÝèx?¬Â§ýó!V§¢$!q.;a_WCX‡ZƒBKéýÇ?DZ~)Œ[­ëú]7íw]×ïºE¿ëýæU©Í³m“VtÖÿvBRãêÚäiý{‘VM(çÀÜÀƒ–Í`t€·ìl¬ùk&bŽ|Ø EŽúIŽ)oã:x‘‡JlE ÒŠÜÊ>àëTâE3\|䳿.EØEL¥• ÀszÔq}Ð< ‚>?ºÍ.iu g¶x zT<Þúbè-ò¿‹„~L7$"¹žcès\®¯'Bg αý ƒ&óGFŸëÔG<1›äÈüܯŧãìÿ-åŽøHÂÃÆ¯”%¿^¼Àù¯ à}ºäyà¹ð¼õöõñÙë·lܼ}}qlB:yú!J ·Ž~ø‰ìرc¶» °1Æ©GGÀO…Sß·SÿÑÃÔe˜úS¢Ô.åAu†`N ÿ)N=rÓšK)8M˜K *SÚT2Âbfãy&¯Ô®B 0Bü·Ø¯¬I7‘U…ᘠ*ªÑú‰Ò*Û;dÍ"óSÓi} À•) nGÆìk6µ)±R Œ(ž ‹Ï`ô§Ê¿ ?‚o‡6ßë÷ì^ú5‚´_h†.D`£à‚Œ‚‹Ÿ(9 W†÷]wøÐõ0³ÉaRãl6a#ËÙ/,‘rC'Á©ñ×+_´Ä-#ˆ¿Ù~l=¶[£ŽÍ!ÇšD½j±Â›§A›á&©¢ +-U 1ù«%ÊÀg€ŠMðÂ6`as¤p&ˆÃ#l6Gô,l ¶A›Ã :o¶D›B€“]ኜ[ef&ÁL^(^âÔû“Í”ú4Ù¨_È/©‰Z™ø£ü«€ VÖH"¤‡[!t²uYX¿ð©ˆ•»LO•ð-m€Î…~6´…˜²9”É“"ÏÜ™®ô¥´%R:Óõ’Ü’º`ZAœ­ð͸٬,À›-Ê"ÂÙ¦,âšÍ1Ê"¶ÙŸ,"šMÀÉæÈdølKÎ’SJÅ ’åLV§*@dCr*>1‚l†?¶çCççÀg*U–hã™HæÌ¾™"Œ-áÅ™.¡n‰LO¥ÿcÓë$‰e²AþC dëÀUÒ5…L·y,ê°†!gGK¤²,ÑM ãæ#XR–e†pävO‹ê6€t›ã¹í&¾ŠäN…që1Ü7„ÞV Û¦í¦]ÙVQòŒÀ¦]Ñ#SmnuK F¤Ã‘{|¶Çg¿p|¶·XY'pl˜Mö*<[ì¬6›d‹ÕhÁÙä×9´+fmñ¥[y DfËNú®RC²[¥ÆEH¯ÀhÛ&•ÂÄ?Ì@É ø{ܽé -Ã÷nïFZP2yÚæ…Òæ…XÏÅ`ÐÕ‚’%Úãþ·. J^\ 4÷NRaÐî1Ђ˜¡BWÄ2 r%Î ¸‰HlktÕ:²ˆB„³¶ùË›É!^ ØLÎðòÀæÂ€Íì\×ð¬y$ƒµ˜fz ½^6Å:ë¡Îó@9{|³=¾y HóÂá’SF‘9Â"7š1ù\B$à@ÉzNÁxä0Ãu„# „l ?nÖ°$&ÿo•D(2Ÿ›¸Q=Pß©lÌ2e_Œ\–)ù<Úç«k–ñÌìàÊ]ñ<®Ùל@™é :“kÓ/MüÃiø9Ä>çIº]Ž.Xƒ™éE‚]ÄKõ¤;ìG(/¢¥Ðמ,nMó!Üîœ_€Hü QÉ‹eӺ˭·eÑÈ(RGtB†õîäÌ^ b½’àa’óAè0‡¸Ã0Ö'1ÆúT“ œ8ýfê•(<¦WêÕŒ0½òø@ ^š©?ªW¥"*ç(3ñu˜ž@Xç?Ñ{Ò°±$â¢ÑÔw3$Ä «·IêmþDoÊHùûƒa&a£y7õä‰Êã"pGÃבgŒiP  Y¯"‰ELm®àp-{¯O ô>5"Á´ÿRàÂrf,6B#C@1²Ê€LunLIþ¦Ñ‘þØ<¹quÚäÆÓ¥Ú5Ln¼3mrãiäq æ$c&ÊÛ?QT]¹^›eŸ4N(ŒøÌê:Ê™T‰¸âÈTd"‘÷Ãf×9jMò%eFÆÉ…QŒ·%VØ:´ý>™©lDàé1| …l6F;v?v„gœáØi4v :f#Ç #óKÈ[½»y«Í€ÜÉ]6Xîä®jœêš¡³5ÚMÕr_–#`¼ÍdïY&ÈÞÏ“ðú[yrëÆHr”3—ôvŽôØæ¹¤·Ó‘ÛuË\Ò6bÇ we>_D.iSµm=l?ZÊfm[Iì‡Èƒ¡¦%O ld„@§E¡Gï B¢çd Ü7 ¢WÊ’³?sAƦ‘É\í? žF]t5 ûϽ !þëþ°wÛ{¼ºÏ®‚¹êŒ&9Ëêí ™Œ²(ñ»%U³â ¿‡Äü#ߣuüý ÑA7m_%)™«?_Ô&é푳ʦõèIÈ=jöu©ð«×~*±²y–Rìesñ™€u8Ùœ#8…&êÓI‡ă$~ƪ}±ò¹xÍ^AcZù¼¯ÀHF­æ‘æªëÙGNü˜Ë¡ù±¬‹e*Wà#'ª@,ÓŽešG,Ó^Ë´;m,SŠ7Wï¬;¾OšØó‘L>’i%#™ dÚ± d²cÚˆE’üÌìÏœB–ªf!KU³¥Œ}`—EÞG²ŽZ "i«U«Jo¸„<¹A‚Ó›!i¼î¾œ¦Ô£3jaMùΨ‰}I=‚‚ÑAAÞ¾¦×M±×=áý¤1_yÒU öbC\3géÿŽ$±Œ¸Ã/t2P¦X6‹ìÚYÎã-´÷kN·8;ŠN·8;òA`‹ºuzdŸqÁbÉÂH2âÅòD„ù/b¶ª'^¼?7‹2Ãc'¼ûŒÞ~Æî?ã*È:#>;ŠƒÏ>`Aûá=ûé(mÞ©±¬C\,Z| Æ1®ã¤£éë±:C Fcj.Qy?Ås 8ƒê^¡Jý=7?"ãü%‘qv‘qÆÅiÙ†’5xØ&Ãÿ¯‰GôK ,‹¢ÉN̈|ÀS˜‡eéb²ržyÁή¼´i§]hŽº0 µI?ä"ôns^tþ| õl#]àÚQ¤#í1 çš0*š °€.Š  Ã¡†d‘ß)ð‡BRXd@G­bËTW‹vò„Ø£GÀš .x+í$ŽjQªŸY(ØÉò„‚eï õÃ4R)5¾G:lÁMœÕ3ű%VBèjè#*ølÌ0ÉøYTY×ÃÊõ›Ÿ15]@×}/d%xS:Hmš#(t„æÖÏÂ:ÙãÓ/©[¿yôü¡†›öø(sX8žÈà¡Ò†vTþC‚p×±Uz‡ä²×EFaZa Š kúœä>jáÎìì”3UXªe³Ýýø¤9bewÇ,„haÕ÷==LYY±˜/,Úî,|ž…N1 Ù˘3‹{üˆð¡ÜLÍ„žÅ̰’ô:2™Y™êБ¼'¦ÌæÐ3î›…%‚½ÜaÜX)<ÉúŒ÷蟙WÁ%Ô>’Q ˜aX|þÈÙQrR‡ú$FB¡økâCŸé„Д'äyå;E¾rþ+y$µ]žÁ+%þ“"^©rúJôBWå4•JÁ§©Té4«£Q*q,]+‰¥Ëº©jsD º;¢ÄE(+BTÞY67¥êbš‹Ù{±å ¤J eÜTZŠPgTå4:‹õ1?Îè|˜… CЄ±@YŸ–’ÞqNÌöòžS]¾sbò¾7ësbL֜̾å='µû÷Oèz~2¥7S(´ŽÉ;¼ÍÂcf‡K$U©.g¡ªLDÿâG(§Q°,/†P„!̉hxóáCVû¬ºtf&LªŠš=îM‰.E‹¶À¦Ô–’¹FÂ}0šF[Á`´)ŽÕŠâ¿0'ZïQíì=ãýûÖÅ1 ?S–þÐÎVå±båŠ"'ø . B>]‹+p,)q<[ÕÑbHè>D$V£ž&u¼â,¯A"LÌñvôxF!x>!x¬–Ð<Í™a|ŸUãà;x’Ä «€³ €[œh´h\«¯V–2¦ ÃѪ|tYöIcJÀýˆJQ˜™4ù’ƒÆP|Ò|v¡Œ¦{ /’` /¼XM1 Ì. %Ê,ætwÑbNë\Щ.âýftZI¢N+>ìt ÏÌŠCIªIj¨ñ§Ó„Ÿ*ѦõuTÙ4‹Úä#SÔºiôgj¼©Vª¯GŽ7M +M©æ·ˆË|Zh¸é‡µ´óY4jr2"y‚¨¯DêƒP.µG¡V Cm’×ø‹GuŽÅrMŽª?%põÃQ«Fá¨ôŒ¿Üñ¨ìx8 ÔâRmRËåE¤f¾r£U¬ 0µ‹š{z5!b Ê&QÀãÆ´'æÑ³H •û¡Á±›ínªŒ³ðèQ5Ø« ×±Ž%Ó÷Å“ñøÑ[Ó(óžÏÆ}bš¹QǬº¥~Æçiºþ1_ø³>®øWì&®Ø&¬ØGCe£ŠM¢|7ŒWŒ‰M?‰<†3oLl|§Žd9Œ«Sç ¬X¾ãýYE›} K©›kD*u±’ªÆ¤Æê*Û kñÆ»sóIžõ`ÏWäx©aÌ)g{ø0f³0fë@bw‘ÂÊÁ¡fgsJ§†&çZjo° IÃY‹I+KPrtháQÉIÅììÓ;â`ˆ¢‘Ã(ccAX\8reyÑw–/ Ü™{8²ÉÚ‘Ù7ŽV•Žü¡VÏ 6 Y6?´Ñ‡,§ÛeáŒe½BÁ—ßbO =i’¸‘“S(+–G_†îgâÏ>¦™«YÃ÷:l„ºBɦxœ’2×qhºKøü¦Ïn|4#’žØúTФÌå9ã±®;E›“³´CÊŒØüʦet7;-´¾ÎdàF²Ý–‚K¼áÃÒ[%‘ÚVÕðQÝR ¶]wâ¨n!PÛ®ŽB£ò…óyÍDTnÁO–XHÐñ§’õÀ? çL8ø?pèK“ÎhäU® ÈBìP®‰lþ² \RØãç—EFú)âµO#6†Öýó}8 Š`ÞŠ&ÌØ¡¶­îÐu«„ê¡È©'"ëCÖœ… „¬œ‚ìfÌïÄã‚fä<9Y§ ‰›•æy,„9$oL›Ò‰ÂYQ­¦fÑðG:û,>‹ÆfѰ>Z“˜B—oÃyF m¿×5×…µ ½w—VƒÑš¥ÕØ-<žä¶AõuŸ`ÃGÖ/`d½8º]fÙHS<#•È*í}yrmì/¯lLBT½ÄˆkòãJ ÊaYjäOÖÁýç—ŸÞG"¡yX#‘³tÆ*g† }­÷†Ž¶ãHŸ‰‚ мWè„€Nùp0Ü©Qˆ)® $î=ÒoW,A-úÞa‘°Ã§öèiH@ÿç©7ìR®•âÜ­„¾õFwèéñÛÕã¨ÛAÝû0Ò5èŽH¸Þ°û6f§ l@½ ¢Ÿ×Áø5ÂÝ~=¾ö >Š?W^Ÿåƒ}ª½1#Б³¿\¤v‚ÐJßZ˸Zö7ã”ûÌóí¥t"úš²»õñMÔ3“ä$3ØÖ­ìaÜ$“œï‹§²B·V£PÐpS )™‘9³’D)?6ifüuÓ ƒ†&½Eý=îé!–¡,¡Åý3ÿò³åW¢ðüüi]ž•×rqzxeˆû‘–£š1¸'‘DWÓ*Ð_㪧Mž æMÈH€Ÿ›€€ñ뢪 á¿Ò`Åø‡»øÌþ,fÃpÇøFñŠE>®“JI”®‚ü!7°ø7>&2zE¿™Þs·ƒ_E4R2N“@KÆ8|Ž®FXú†«Tb²³h'Þ%Äg‰QüÄ?ŒùÈ¢éÃ2¬#‰ ü€{K¯Ó ¯ÿB¯›)Ðî‰ð¢û‡¸i2PÖÃ, è{qÊ ý9Ü:¥0\ ’ ‰~úÝdqÅ ë¤;ìËu!Î×^¥Ýÿ@¡ßo+º½ ¡¿‰•kü5}·#  âš¡]ËPs^§Ô°æ¸Æ´úè3«Oó¼ð> p5¹Tw¡bŠ˜uóY>„Üb‘³á9Æñ/@müxÚÚ’Ïßs ~x+pú{Cú °yFµÆdð%±E>kTE¢'*qiô8ñ%¿*†ášB,Þ‰2ïhhå÷šŒälPFMUÙE”šÑÒ'dSºZêŠu‡¨‘]hˆ$£–“ÜTpr[øŽå4À³5<ËØê'+.`MF‹f"‘Ešì®(FD·˜Ì+ †ì.±gÑ®º.…·t)y±m€TÀ”Ñ&&Œ¢½¬¡ºÏZIÔ¦œsb?«¡†ÈÃN1-Ô#/ö¦­2 ô,Wõá(V£ˆTe ü†æ5þNSþ-Ç›©L6F[ ÄÄ·Ø'Á @Dk¡­)ùG‰;$ŽÿË~ !K!Ì(ÆgÒï<î(„iëaΙ“ÿŽ 4ö à‚ò„äk»ÿ0Àêih"ÓÌ7ÞZ/ÞZÏa¨gÚÇ%šbÓØJ. 9s[¹ê” 1¨zëðHvjGc<4ñÖ‹!îä¿õF²8%s›Â´‹Ô®¯³®n†y1i—73sb²‡ÚŒ`nfäµ4±µž6ŽSÞÅÙÙaª•þ!JC‰ ‰P"댡!_ëùmæ‰ãlžO†’tÿÿßÙ97>#»ªxb\y9ínÔéÞô{REä®uÌI¶œ’Dl©¡WˆúÍ®‘>G­|Ê´(Ø7ÚT`æt|¡ñš#®GÄu™¸.7€ªÅ¥ª‰1Þ ²›σn›xzÙÚPÂR»E§]Ðõº%šùñ=$ ±ÂZðe"h>çÆ–TõíÕÓ-sIÿ"šø¼/eìÓ˜dúh¬¼_¢_b¿ašùF£ö(Û’l{ŒQª¦ÂL”0à‘O ¤fQ,¡ÓѧïCUík<$§–ÎüŸé—ø>:@ã»ñýìJ\‹ší…g@СęÚF\¡€<6ð@åŽÙ|Z®!)Šbœ†wœ+âˆýé\Lgd\…^†ÓòyGƒzEb¨Cæ Óÿ3˜¶—‡iñ“΋Uºõæ<=U’=UigŽUèGÙÚlÿ!'ÛÃyÚ:uÎéƒbL&½é à[úAÿ~Ì9V |;ƒk4yßl‹Â)³ĺȔr9÷hµ¨¡š5Qœ8íµ $+nê›Aæò7ƒÇ´IÓ € BHófÕDhüË­ê' _4®§&Í'`ÂûÌ…ÊûŒY„fÊq5ïÏñ]CŽ›; &HÆ"Re.´(k­]ži¡Æò/iêi‘±¾†T™k,2Ðnæ7ÒS‚¤eæ'¡¤nIÁß© ’i2±Õ„iÄ}³Ùwßb…¬ ³DƒÙ²„f— Í’¸vZe[ëÚŒ{ÚŠÄI““¡!q2wã]/PB¼uj(† á„Îx$Nø‘"6¼ayÃN¾}ÿIL¥C·•)%ÙËöîþ.WLþ¼ýEM¬ÃúE–ù†Ò ¾¼I|ëÄs†Ûûå}”‰VjŽfUhîûJY”«@›}‡ÌÕ{ß憎÷¾;ê%D²MFÞà«a—˜ú÷Ý«`„î®îoÐU»ýDvêc kyw[À»¹]ݳÇ^öú‘s‰¡ ¸8g¶"ÕõI‡JÑ[.q/YÔËÌkŠ+ˆkæceº(¹ý(J®¢FÉÅŒ_jìŒMÁBÞ7Ã`tØBÇï[-tþkíýZ;–£)~FµFãâ¬vþ>ŽÓ¡¡Spyÿ™ÄDÑÚåŠhk@‘:¤Ä1,è> cAÐùKywk/„hFŸIÀRxë~î( e—ç¤ñ+´Ë¹B¾8m *–à‘ΰØ?–Î4ëá)ö­Ï6ÑÙlêuº#²à·S ·SôÛ˜ŽÃ‚ÙøôÏ×™7þìC~d›±ßWL*}&J4Ò•hqù%Y E. äVϬÇãQ°ìv0Šz8}xÃÏ5,ûèXNÃ[Ÿ˜ÒtJМ~< :@‡‡Ò-ci¢Ý{ænæá'ÒìéþŸ§xæðèbŠ(¾ ÿ$…Ÿ\³˜\R5šGêþÚÌà§Â¦I´}+ƒ* d®(ðÒÔy %¶˜ ‡áˆz¬©¾c=ˆè ¹èTpüÌ~$C"¾'‚¡’ÅdôÊ‹Z‚F é¯ÁýX |ª™Ÿ©xo SK…äLÕ —ûCM=À„>¼ôü%ÑÞ“¬>?¤¬>˜Z€$y¯C,W¡aÏ3z|z¸&P« ®zCŠ€^=vúñOO=¼L<ÜI ^0ö®ŸÈJuÝ}ëbáûf{k—ntâ¿~é™zéÑÆ>äõ f8ÁO>pí“Mâ#“JZµÿ~/O0m%ù‚Œ–ÉžŽ_1~Hp W÷½ ±ß /þ}5ì‘j.iÐ ‘?üÈI¬"†wv÷9_à¾~¿ò§"î Âd¾"%¡ú99ªkjÝÇv—̦0þ :$úÙ¢´]÷Ÿ;Ü *Óéƒ-¸x¸Þ {Æè."„+¥ji¯´O.üX¢Þ‹nýúÖ»¿Ç•aÁ•VÁùðxce7íÆ]ðžrÒXƒ<ÔS€ŸhÔG×ÃîÕW„‡üËÚh<èf°(ôtsß¿b™ß…Ÿ{W·ïПb~_c¯œ-ieDj¤/Uº)öG·ìùéG28~‡ˆnc¢=JªÒ×”Ð<€D¤OmŸ:IŸ:ú>u’>ut}ê$}êhûß®aÇÉG˜¨ÝŒC"ò&ºzމÈG¨\=\=S"öîyÒ©Ž¶S¤Sm§:I§:úNu’Nu´j'jk;ÕN:ÕÖvªtª­ïT;éT[Û©IÒ©‰¶S“¤Sm§&I§&úNM’NM´ :É„éègBÓÑÒ$u´ÑÃŒ?jjЉ:Z¢vBÔÖM¢IJM1U[ß© ׫IJ·ð“?…Ý"µD턨­i0®i¢­i’Ô4ÑÖ<B8ý¨ÁS$ÉGøÍ$5u´5u’š:Úš‚v\û¨¡Šëbá'q]죆*®‹}Ô̆xÜ0æ—±Š~«´ï¾vÑD?«½àH:0I›#iÃ$Žd“ÁøáßÑü ŸŠkŽâ¤pˆâ¶;Dþ u#!ÀŸ¡68‚\C…«¡VQáªP):3: 3:3: 3:3: 3:3:3:3:3:3:3:3: 3:3: 3ÚwÝøAèg€âš£€˜Ñ¾p3Ú˜‘ ¤ŸAŠ6Gцz³ƒ|†ºÁü"wU¸ n 8 ˆ_Ž__Ž__Ž__Ž__Ž__Ž_ˆ_Ž_ˆ_Ž__Ž__X$RãâWpËIž[PòŒ† ù PpuŒà:8é5¥×hp­`+Å5H1à(E‡ãGäG‡ãGäG‡ãGäG‡ãGäG‡ãGäG‡ãGäG‡ãGäG‡ãGäG›ãGäG›ãGäG›ãGäG›ãGäG›ãGäG›ãGäG›ãGäG›ãGäÇ„ãÇäÇ„ãÇäÇ„ãÇäÇ„ãÇäÇ„ãÇäÇ„ãÇäÇ„ãÇäÇ„ãÇ„ñƒW®ªzåªÊ)WUX¹âH:0I›#iÃ$Žd¢©/ÑK%ŸÁ…çkB1ü /M_ŠŠJ2áš™€ÍL¸f&`3®™ Ü ÒQ3ô3¨LÆä3¨¥}M(€ŽPÝíkBuܸò”ØE Rt¸‡é€Óá¦>L‡{˜ø0îa:ðÃt¸‡é€Óá¦>L›{˜6ø0mîaÚàô¹‡iƒÓæ¦ ?L›{˜6ø0mîaÚàÃL¸‡™€3áf>Ì„{˜ ø0îa&ðÃL¸‡™€3áfÂæoÝ{Îõyñ©Qk½×9?Ñç÷gXŒÙ;?[gÏ!Wˆ&ô3š-J*jh+JhN ÎóÙÔuˆs|6µâüž„H[OBö‡óz¶Z¿Õ>4‰×¬Õøøé¤Iœf­Úg˜†sy’3†kŸÁN'jê:Ä9<›ºqþΦ¶C‰»ó°©ëçílè:Ä9;ºq¾Î†¶C‰«ó°¡ëçéü¢ëçèü¢ëççü¢íPâæ<ü¢ëçål55C1!iêH¸jšºz8g«Õ¨ÃÅ4M çálèh8ç}=|EÚš¸.}Ñ÷)qJ6ðã_èhÚ (†8çæ]=œoó‹®εÙ:=;©ÀÓ>öG¶j­ Xä%õ4uõp~ͦ®έ‰å¶Gm®K mŸ&\§¾h{5áºõEÛ¯Ž0â¡kí×l´*_Þ+½à(š çÕl4@ Î©ÙøRp>Mà~ÿÞ_áî¯@T¸ ΗÙhBLà\™˜`çÉÄ8Gf£ 0óc’.¿¸ßU&p^Lz?ðŒŽ`çÃl4~}¯>çÂÄ8&&˜À90 Ì„ ˆ Í4 %TØÀy/I€ßcg½à€#ØÄ¹._ 6qžKL°‰s\b€Mœß²ñb綤 ›8¯%é¤ÂÎiIºüž°é Ä&ÎeI+Pç\â!“’ œ\ù’+‰ÿ¥Ñ:?ƒ¸ÎÁ8ÉtI¦ÄùBšhAMpuˆ`À|R 8O%™÷`àD ÄÎOÙhB|àÜ”˜¬N8'%ix ŽMˆœ‹’4¡pJ2³!ÙÀIˆœ²Ñ€øÀ¹'1X'Ÿ >pÎIÒð8×$iB%à<“dêB“Ÿ8¿dã ÄÎ-‰ À8ñsJ’&€§àøðâç’$M`kd£UÕ"Ž¢ RpþÈF¤àÜ‘/p‰›.†'ÐBò5!8;Wš¯ AE¡à\‘t%QÚà<‘T C5Äm|ÛàüT +mpnHªÿAq'ˆv¥6‘x‡˜ú¥R$Î!*ÉÕ6ß•à ç¤RT%࣠=ç¤ú‘ÒIÎýÈ(•‚{Œ&ôœó‘ŠQuÐpÑ€ƒs=6ÐcpžGB ;î1àcp~G*GÕ6¸Çh@Áy© S ¸Çø=çs$ÀÈæã øœÇ‘ŠAµ î1¾ÐÇý§¿’ÃKµGöw ¸%D£ -!"”T¤­'!y€h ¨%D£ -!"”T¤­'!ûÁ,U^EYªžd)Ó€Ku¾«K…@Xª. `©tÂWª3W…W*4ºR¡À•J‡ l¥:Uh¥B +X©tÂU*ï^…U*oCEUª/ž£ÑÕ*ÕŠTL¥úRUH¥ÊgQ©ÖÃW¤­ T*u1GaŒ¥„~os0JµzÿDwèdœèîŒ1nRâÔûC&¾³û;ºûC§bGwäPL@’*EØ…¶¶¡#1Gªa7&Ú~D#1AEæE*­+˜Hå-+Hå=*ˆHHy‘*„‡T $8$ À hHHûDI€ßE,$¨½r÷§9R= ¤J á U  ¨¿ Ò]QÒàw ê¾ÜýiÎC†€„ì%©HøG•@‚?ʳˆ~„ð#d’¡¤“ dè#hÒq÷§9ð2ùÜ£J ÁU õ(ç"è"0U‰’N*l UÊÝŸæ/z»)$ RwÞ)|ኔÿ£÷X)¾ôüÛÕòNYÊÿ±³SÞóù?\”×dœW¶Z§µO,=òiíä=úø3"WZ¿~<ÇÔ•,곿½9©}Àw¬ãÇb‰GXæèðòa‹¾on¬•÷¶X.Åó_qW~ýxÜDÿ];¾ f•ÕÎ?®íÉlåXJé[äÓéÚ6*£ VawÑ!ÿëŽQ-Ga-<5ÿ«Y-‡§Ï¨F}6.×H}xl¼©5Š”U£ÚéIkëÛ[Û%üo­—ãOÛ[û¥7Û[?n( ±›Ì gR‚õ—·ª¥7å­²Z?½‡¥Ê -ÊsDgÍ~ÊFÇj‘ ÄÆMýµýeýw¶õìè™ÝgAoÙŸ‘uËþXÒìè™SÌŠþÉn<Ÿ™Íûµ¤§>7«úÍèç½Àù’Zý¯Z|ú_e{oWÑÿ*U¯ÿ¹(Lÿ«zýÐÿ¶ãßyí®„•'E,aý'ºXÿxþ«[½outªKÉŠž9†¬tKúÀ²ÿÄeÓ;zæ µªßŒ~ÞB˗ЏþwæâÿÁÿ©þŸ¿þ»(¯›Þÿ³ôëÿªù}°Ò€°ò€°Z¢Ôj­$•©¬ã´Ž¥G§céÑ a^ô¶õÛyP:–Ž¥G§céÑéXzt:–Ž¥G'ÄÌÙ¼_Kz;Mˆ±³ªß{h|É(ŠþçÞÿSÞÝßWô¿ª÷ÿ8)LÿóþŸ×ÿ"íojÿÏLt«òVU©LÒ­l<#KOMÇÒSÓ±ôÔt,=/åñ¤ˆòÿäêk÷¦wŸ&s” ù¿_)W$ù¿[ÝöòßIùÛÚßèÙlÑ›§G â¿j£oëÁ€ƒøØ¡gb‘Ïä8,:h¶ZûÛÚZçþß÷äð·­·[kÑa/_'W7âá´Õ{\ÃíÔ†í»Þ¿»è†ÖÿØmwƒ€½5êG­®Öqe_Ç-Ö7ð‡ú1ý@nÿxýG·= ï&Ýð OJAƒa·Ý zýǵ€ôô¾ÜÇõ´È|,oõ×ÂËîre«O>ÒÈ$üñ*: Œ^fÁ»ÉUîÆ*»±šq#Ðcîl®Ç¾Ç¸Ç¾Ç¤Ç¬wøw’wrô8äqt0fÒé6ßévÜé6ßévÒévV§Û|§ÛI§ÛùÙ¬vzÂwzv® ßëIÒëIV¯'|¯'I¯'Y½¾º¿ÿ áÿ•Éÿ*äUD.–BtÀ•Q‡ýi³?ö‡TB’ #©0’ #©ŠjHQeUFQeUÌëûîÕãOk> 77˜MÃ.Ú$}Ýê?Ðó&û½ý‡Ž„tŸ»1Áó& g ~€ç€¼¿Q™ Dr¡^hGÚá…Ita^`•TâJ*¬’J\I…UR‰+©°J*q%•°’j\I•UR+©²Jªq%UVI5®s‰ˆÆ“K¨{Õ¾ãÆÑßȰk%âg-z䟰ȊÐF(/FdbüåïëÇkÍ÷gD¨‘ODmm 7ý˜]¹P ¦Ç"0j¢’4QIš¨5QáÈ…ZÄ&ªIÕ¤‰ªQUŽ\¨%lâo¨™ÈÀµh`;Û:&lëÄlë$lë(lë$lëpl똰­³­“°­£°­“°­Ã±­c¶N̶N¶ŽÌ6”Œ·Pª­Esˆ´Úæx×6á];æ];á][á];á]›ã]Û„wí˜wí„wm…wí„wmŽwmÞµcÞµÞµeÞ%c.ZÖ"qCZp¼›˜ðnón’ðn¢ðn’ðnÂñnb»IÌ»I»‰Â»I» Ç»‰ ï&1ï& ï&ʸCTõ:»8¥æKkmøDŽÿ·Û¾ë£ïÞ¼ù'½|xú ªÂ–ñÔÂß„cAÿñæÍwø–­·± ûg¸Æ‘Å$½2åŒÑ¤²húãÚ:†µ…‡îÕµ“êÚvK«5+ÁµN j­˜ð¯‚þAÔ²JÄÆJv™l$uvXÃ:³™I*m³JÛvÍfiå/ÿ@\÷_BÆfÔ]5al•1¶1¶š]g&c«Œ±Õˆ±uf3¶Ê[kÞÑlÆVc«Ñˆ¥uÿeí/k[­‹Ÿ>üü¾õ²bëmµ×Ö¶n¶ú?9ósƒÈŒŸ#ÓFßܺYÛj‡?7ðÏo±‘˜˜ˆ ¶=WÈ‹,¢ÿ'˜þ£¬â?ªÿ᤼nyü‡ÿñ8x¯"°Ä–8ÀXâ@KH`‰ ,q %$°Ä–8ÀXâ@KH`‰ ,q Çø¢/Šþ· øÝŠ×ÿ\¦ÿyüÇ‚ã?Š‹ÿ™þ#°Ä–øÀÿXâ?KüG°¬øÉÂäÿØÙõòßEyýÅÛÿÞþ_PûqcU'–^‚‰¥—`b™ÿcb™ÿcb™ÿcbé%˜Xz &–^‚‰¥—`bé%˜Xz &–ù?&–ù?&–ù?&–ù?&–ù?&>ÿÇjEÿ[üÞþwS˜þçíÿcÿ/¶Nec•O,óL,½ K¯ÂÄÒ«0±Ìÿ1±ôBL,óL–ÇkáKQ…­ÿÁ°ý6LCNXÚjÚFÆú/2üǾZ­ì“øŸí}¿þ»(,3¾ðîñrD †ýÛáÕêè 5PïqÔÞ\µ»4d‡R‡Ä¿ {£Q÷]ÑQ·7ºBçÝáÕc/¸ëm!Ty[.¿-ÿøãŒøíÚß"Øw´á­»ïäK¿ßìï“Ë4û4×»uÔî?#ÒtZ ¿P¢Í«ûÁÝ•xésiMY¸XIjÁí~.…ô—%ñ‡ËµÿàžÝtº74«÷á)=Å=üHÿžàn¤žVYøõ’|½|GŽ ºHÎ~Š×mé¹›öøá’ö'Ê"v"dÉ+Z_ …À=xUWB—É·Ëwk"Qz+óŸœÂæzþWöÕù¿íç¿‹"ÌöîMç?¥v8ÿI{)ó_;ÙWd®³Çæzú$7×ДùONÝû=xº.PdíÿoïîIó¯RñøO'E˜ÿÉ»7•ä"Ðá+÷÷á[núCrXE@Œ®»7$€ôo“»\IŽè¹R¥‡,'@iÂߢH»NZ[ta’p$[ ”}"+±âË’Hþ?¹–ÿ{ÛŠüß){ùï¢ÈòŸ½û ùÿËÿnÆðäxxÊ\`õQÖ W€§%Xž¬V€'¿¬`Qä?*8µÿËÛåªbÿWw=þËIä?{÷™‚¿ƒÂCR7ù'‰m„vßV¶ß2ûÁ¨ÓëoÝýS¼tß»®Y‰vÒ‘u&…¹³è>ž5ߟ¡þ°Ór]!ONÙ;'‡ìÕx¹~R ]mä×£cžöèBK¬óX¢M¡éûÎUzÝ"4qÝAU„7ƒ>Ò9àï¼öŽ_À¿Ö΢Ń|¦( Y£äe缆^á$E[vҗ“ƒ“’¸&âG? Ÿ±@Jõàw@?]]h:w‚N –TÜ:yòå£cüš•‹ømëÖäg“5™¼ÇƒíêÑÿá»èÓ'dïèæ¾5B›ÏÏh=ü¼BFw%SäÅ#î2´.vîêþOå_%²ýŠÿ¾‹º0bË=ùóÌÑo>mŽ“¯˜z3‘NoŽž¶éMÝg,*i…l~5°â÷ó°ÿÐ>ë;¹ú£?l†·ô7þ~\¹*Õ‚(³.ß u:ÉÑÁjÐèßÓûiêŠÿ„#Ÿ±‰Óöé… <Ìqm¯O_¿ i©ÆÜ Ÿg’7ú·4Ä[ÂÏÿIæ&“g,CÔz¥‰<*à¾+}wxß½½º º#‚Ø)¡ÿÕùßß•ÂËï’úTžms¿ª|ŽvGOÃÇèŸá_@°NwüÜ•ŸéOëxæÇIFxHÊ6»)T1OJ±úŠM±èÃE¼©’ùUAE…¨ÀRÑ'{F£Š_›8z"®£GbUùñ¨Ê&–ƒ0Uêøaszû_T$¼“(ãÞàðî7:ÿé=˜]òuz ¾.Þ"÷5äÄ ú'÷Ä×þ#¼°G|Ï úÇ?î±òŒ¯?à!Úo¯?n½I·Ã$ËÆ†H8"”ÏLpí®Ó546¤&Éïøú;i½“¦R“T”_°@CÏß?Š×ÿd¯EßÊæú›Ê†¶•7P3ä¡€žÑ÷ëJm ß:}á«Ò¯MÒ*^/ÔÚñ %z~ßlÒvØiõ7úc/­WßîH¾´õgô×ü|Ò<Œäw¨*|‰×ÑyäÄ+;_BV+¤ìèe’ K6t¤zè*ÈÞê¥XÐhDü†Q ¿Ž¿ÿß/5ŒÖO¥¹‚€·GF«Z5ˆM¨Ö½OÕ—DGÕ}•Ÿ:}µ!\6Ǥÿë›cuô’‡Þ9"Ó¾êõ1ø¦é}oä>pc…ûHçÕ3¯¯ Ï„“ÒôrN“¥i××Si%Ëj¼ÐÒÕ¡¤Y^q©¡R²Â>—¸–¬Ð‹äi’§[Ჟ£[ºußÜÀ"äTŽ}Þ@7Ãnwý™&ÐD'W¦€ÖO;hÎr˜}ò0Ñv„iR–§ ŠçÉGªÉÓ„êI¬ÝüPg†w.|Qý݇·øŸÝ½ÝŠ÷ÿÍ©Pÿ勞Ÿ¹{Aúæ¥MßÂ!¿î¼ýAØÂÉëèíé}Tf• üzêz’uO=¯/0 H|}iЕM ¯‹¾Áë ÷"[Ã{â½mÑÓ‡Õ ú;D¼u™?æ‚ÃäéŽ?åz_¯'þ@k‡àÑÁàÄ\À_®G ~B|½=•ðÉ—4>AÜò>ÔËmÂê5Îþ(Ô3®Åef‚ûæ#èC’kLë’8€üH§?!vK#û–ÐI‚H0¹å4·g K^sq¯áKL¬+L¬§0±3±žÂÄ:Ìĺ-«L¬ÃL¬Ï’‰9í¤ˆ .ÔeCj-¡eK‰(Ît®ÈØ„5)‰R}‘בÒˆ/µCçcòF?NãyÔMÚ´ñ¦™´iãM3i­ÇÛBMZ‘‡êœM|š9›&ø4s¶pÁçtβ¿ 1e7Bq^¸U[á|I+Êúç:ÿËöÞ>þ¢¬ÿ>þÃIÖÿ;³ü/dý¿KÏÿRþ!×òoè(ⵄ»"ò¿\|:þˆ.÷ý¯DðÁ¶ Å"Á~.޳a?”Ò'.ŽÑ+üÏö“¯a©ÌL•aŸeɳ¯8„ÿ +ô™Y1ÕqÿÖ$ð $0ƒc‚!_ôñE^Ï N[zm^{Œôñ’=Æ‹ãÏ]G}q,íÞi<MÑe²8;‰65 ˜—DMJ’×™™Ká¼™ò¶x$%ŽCQT ”b$~¢ž€iE ”"<ÚDëÅ1&z|‰[¢âJT&€( á$6L9YèÀ”Ó„DMxÕ 4E“DnDJ _—(Zx ,!% ˜D·¯­úõ)5w‡}âŽDØó]ç6¸œé6Hg²ŽÃ{ÿŒ´¯CÈ4vîó_žåí€gn¿@¿˜dlõÍ9Eêɳ/Á8ð´¨ö¿ûüÿ×Çÿ8)rþ‡;‹üwNó?Ü™æàn6ߣV¯Óµó¸±`çPs<;RS<´š%â@)iªG ÕD¯ð?%ÅCä)ÈâÁYf‡•Lã@‡y²(önïFø½¼>"“ÚãîÍ1ÚãÜ:—KµrqÆy¬|ÈÚ$傪{"Fldžªž nuÏé”ÏOmž ÕL ˾‹Â²©aVë¬NS(h' `¥h'ÌÙÊNˆ Ú cg«ù L„¯ÎÛt#±I§·ã–:/ÓÈþs½ÿ»·à¿üù¿NÊ[Éø3ÞÿMÏÿïÿÎþWDþÐò›½±·b[¾ïô¶­»ôÇjÌ`cWku¢ü;»i›µVÛÀVZôêììvWÿ"¦dð{¹~/×ïå¢UÝËåó$‰zG»ºÙ¢~yvu!QEþ?§‹ú‚vr»Kº“‹+øL†û3ZÜí\§»¹ö°ÿ‡›ÿ™û¿Û%þ¿¼_õö¿‹"ÙÿCcó¸Ñÿ¸#F1b ±¯ÈSàth¶0šDŒ)µ•ôa¨8;Ýp»5ÃJ/Ð,WAÕ¡å+à°ü,}=Ï*ìÍž¼¹;\jXÔŒ†*Ü Þãô¤8”»°sç¯ìf½ÒeÐu ¶å£beɧf Ô¤Ôó`’ 03 .- &' ˜Ð,ɘ0% 6ûßtf}ü]oÕ›õ)6½Ð-øÜÀ¤­Tiòœ"MPüÆÍì§á<Ì'†c† oö,¬µáË¢Èþ«8ÞÿÝÝS쿊ßÿuSdû¯bnVô`õm¥êЬhB6à|²† E³ïäŽA[òØœL’É=‡ìAyå2 Lq×5yjºç$ 3JÇÞ*M3a*«d–Vt{³Û±iEɸÒmÖpxÁ&mZvŘ(ÅÖ¥],Ð$~ž¥MüœË(VÎ2ù²Ï296K3Wm•f’¾,Ó<“ ëxºË‚ù‡ÉöÛXèsQ$õØ&Å”]É/Fé2eo2H¢©•°‡Bj®M‘I™+™˜qóÙx1+ÎR™Ÿ#ð£H©C…¼¡+â_íÿ¯Å:²öwöweûggÏÛÿ.ŠÿK_¿i0!vŒ›³=>ÍÔÏ<°yt Á ‡…3¯‡ÄÁ~fvÜûYF,ðùz…ÿM <“SÞÿHw5ÎÔ>•N@è"=='œÁ+;ˆ86næ?+Y‰_çHøÀŽj–Ï;C)‡CÃgCŸ¥œ  }6Åqî Y½à™J‹RIøÌºt–å›ù«´‘Ø2I&„P¾ši¼±Á ›aÀíâ̰„ ú œË˜1Á²ï'˜Ý ‹4ÁÂyàd~YFz¨ÓQ7!¬³ál\‹ÞYªùÕ‡4Èþ+ØüËÎÿ´_Uó?ùý_'°ÿlÌ?·Ö_¡Æ_¡¶_VØ8.˜³íVÌ’sk¼-GƦ¹ÛZÞÔšÎÔzy–V¶¡õ °´?.³µ¸!·Ñ<'XÂ…åµ´–~Y&‡*j~Mi>yëé¥Õþ8Ïÿ´»§äÚÙöñŸNŠˆÿåêß JºùŸ3;ÿGwcÊ™?Ÿü)?… †í“<ùO†g÷ f¥¦ãˆµ‰?æ$¬PާAJާOþ°{mB—?ÁÓ;þŸßÉçw ˪æwÒ ÷y„d w´ØÒ=S¼§ŸÒóIŽD.(§Ó`ár: ý^ÚãyÁŸ«ƒì×ùŸvö·üo¥ì÷Éþ7Îÿ4HÉÿä4úw0¿üO)·3QnþÎ9˜7GŽ'ŸÌiŽÖî %s'sZÁ€×Ìù‚ã]§Há$*p>ƒ“ðÃ4†{üuÆf»Ð/8…“©yÖ 3iŽ©›ØÏ¼}ãÞ¤€ô×ùªeEÿ¯no{ýßE‘õãü?ƒ´ü?N3ÀŠÍÿÃägdçʬ„Ê'³D@ƒµù™ ®vïæØ'yG>¯Ï´zí åõ˜æõ‘Rõ VÒ`ñzreèI±k晘§K'ÊË£±t;CyFÙxàšs%ã.³qÁ¬¹g¾£ ˜Š‡ã˜‹‡û}±’ñD*o6ž¹¥ÍÆ“²þ(ÙxxSw`Ÿ]g°$ÙuR^ª­µ¥(Šý´¯îÝÚÿøG%ÿou§âíE°ÿÙ»B3]”úf+$×Ç€n!Ty[. 1 ùL}Òâzf‚Þ,³\²ËÉî\Î4%X2ÅþÌ™¼Tô³‡I±96\ˆ4uþ/²ç¿‚ÿß­øý'Eœÿ–€’»œÿZ ìÒk÷çkþ‹Úu Ôùÿíjàxý߯¨ç¿ûóßÜqþÓwo<ý µËÙÛ“&¿öõÈËn$.óˆØ9n'Ô”Ø&*è“G’Bï—Ì!/Ôù?~xpÿE=ÿcgÛ¯ÿNŠœÿ…½~³ü/”ÖYþÒšmþ—Öaó=jõ:]» @N<œˆi`tÕ¤„š¦~ éuY?MâÓrÅ´š%²›ˆ rÅÒÔÅV½Âÿ¦ÍsrpR¥kY?OЉ žgÖÏÙå“!#=ÙêÝÞ6ð{?x}$mh»7#Ähs§“!ó“O@ý‹äâ¬ÓÉÌ!«NUφ¹dÕq˜³‚ŠeQj„ɉᘙFL8óü0º å‡ÑM˜³•0n²äø ÃÉcÿÁúˆœ¶ ‰1¸L‰CWûˆ¢ÁùÚA‚vëOr˜*½¨Â@çù Ñ­Œ2 )Å‘ø18Êa!¬ÉyÛQþ`‡3eN/Ó|c–aºÙš)v§?ªa®²ÿ 6ÿòœÿ°Söçÿ9)€ýgcþ¹µþýü‡¢v7¹ VÇsk»y#ÍÌHó6Út6Ú 4ÑŠ±ÐVßóÖØTÖØË3Æ t}L³èæøo’-BQì¿Ñµëóö÷¶ü·ßÿsRü7{÷FàoJjÿÅÊà#M™Ø%Ëà«õ5k¿ fïêV[`Z›~º³!xKï¼ö޳ú’ÏÍÃì 1$¡0¿²Ð{@°†MÀlÊW›‡èþg}d„°­Ûˆ9’Tš[ƒP hĈ6L—Æ0’;<—O(#[‰³;¡‘ù¤åx±ÊcnD’y:ç¼!äÉØ–5Q¬¸ÖÈÓª«tƒ@Xy¬G·ä>çLâ_بêÖfÌC"é’¡ôØm`ù¢Iíiÿ‘'·3¨w´¼ mÈœ /MH@ǧò×dÊ „ y˜rZ]ÉIòæ!p¦6¿A£~äƒ £§^• Fs•DÆ¢([¶XJ®D©¬’ë{ˆN¥³2þ# vžÆgå< RFa–8ós\”d+õ•<:NJ럨!^~&rðX.Vé $¦ÀQž…IzÞ¬o ys¢6Äœ;HHmƒÒò¨’»…³8¸{ÿ´Ò‹´8,ðê°DÊPQ«ƒËåA/ÑÒ$Ž’ ÉóošÉ)gÄBæ³S˜‰Éº§óƒ±Á–åë/92ðÿÎý?euÿÛûœÉÿ˜û‚ÿîKÿOàý?„Øûæãÿñî3£+˜·R¶äîŸÀ»`^¼x÷OàÝ?Ë"‰ŒEÑR¸Ÿ¤ZJÓy€„ßiBîÍÊæú(“¢;E<Ñ“}h¶k±Ã)®¤é\A‹ä šó:á áõÍ{¡p¹Rè…Ûü™ÁÜ7Ê–Û'3ð /^¢ª²E)SÓ& €”È­š³ež"ÆXÆ,…³åcm¦ØÎG3p±Ì[ì{¹/¼¾yËý¼‚_’ûhÁ<'14ƒ—€¡Yæøœãª5ÿ£Ïÿá¦HþsüÏ`öøŸÁÒá¼ÿgÖþŸ$&ËûÒŒ3É™Îÿã19^¼D; !e‹’÷ÿÌYĢ¥ðÿÌl#zS<Öfaä¿_„×7ï ï °è—ž Ñ,qQý?C×ç?îïìøÿå¤Èù_Ùë7ËÿJiå%­¹=ÿ1ÕWdPaâŸÏ<%±Z ˆÑb†˜å({þŸò¿H'ÈßwÊ‹R6ïUÀ/Âë[ŒeÍ~%@s€¥ÏK‡`£¡;3,€ÿ'pÿÙ«î«þŸŠ÷ÿ¸(*þ'°ÀÿNñ?cüÏËÿÌ û#_…½J÷ãâ¤iugÚ)î'XÔi·¸Ÿ`q÷¥—e[:ðÛÒ^øméìmé` ‘²ÔÎRd ¹AŠ\r»ByÉí%·—Ü ÉOtCˆ";Ñmàa V`ù\ãvËþÇçÿqR$üyþŸáìóÿ —6ÿì£Ià>iÕ¬lz ÿYFøO!4üǧÒðâåîûFЬ‡ÿ,º2AKÿ™ãq^IJÓôBb/"½Ð¼×¿8¯ïe,èå&úäCš"û:WÁ“cü9LöÿT÷¼ÿÇIáý?á»AY. FM(G¨§J€Fø–›þp„Å ú6¼¢aß×]|¥K ðdKîJÇ m!Ty[. ¸!s/R§ÿt}ßåŸjòÖ„d@b^˜€Tð.o*d%Ëa.drvý÷àéz=–ü|VQü‘lpR(쫹(Rçÿó`ìzþï—ÿïö¾Ÿÿ.Š8ÿé»7žÿ„zÆ3™óÓöÒæ±€–Kæ¶F9’¦|)¾ãR’—Ä%k;ù㯗äëe.Y þpIû£ Ê—xç+dƒ((.“o—X^ü‰"¡Ìÿvßýü¯V•õ߯ÿNŠ0ÿÙ»7ÿ”Úáü'íe¬ãš¹¾2S±Öä)n¦(ó¿Ó<ý³æ+òü¯øóÝaþÓwo:ý ±µöÞäNùÇ #3ÄÛ@É‘X ¸U{ƒÁ¥ ÁL³+xY‚?bjÁÈ ÷'þ¾Œ_ø¢ÈÿÛk×ùvª»;ªÿÇÇ9)RüWøúâ¿­Iü×^Úi, ¤ rcÄEdùõ蘧=ºÐ§X¦F‘\ÒŠ£Jªóº;‚j‰ï×­Z1Ú(U”‘êÙ”®¥_¥zŽŽð» Ÿ.Ž.fßutŒ_·rñ¿õ©VáE„-Ö&A PÙ°X›ÔmDý.¡² Èd]´÷'G£¼b£2úp‘¸|4¥ÍBÁL%†l:¢‚$sPÀ·øq•Œ«Si|Ñá°p\i†*ñÃÊnTivjCŽÏd§v)·gg^Tý¿ëúü—ݽÿ_ÝÛöú¿‹¢èÿ]ãó_­«ü´5ÛüyÒ6H÷ÔóÚ»SÄH«ƒŠVé9«C–ÕÀdq|{C¼½-Zx1«[ƒÉíÎ~9¯ãëõÄN°6ŽŽÒáÿ¤åÔðB Dæ°¾ZÈUeþÇÿዊÿ¿R-ûùï¢óhÿ7œ}(oàæÖ…I¬¾%nîBj¹0ûÛÒ÷ ¸``æ+Ò žúÐ/LéF²T œ0 ÛÃÏö*ØH׸ ùëxý¯ç¿oûùï¤ÈóÿÖJÜ:–·ëÉÌNP›×ÉÇvò1·Â¢Is»~Uº.µKxJ“È[¤@óßuþ¯Ý}%ÿ×ζÿwRrOE9¥–~9æ×b{"}Þü4ÓEyªíãH¸<˜…ÒÚX°Àypþ¬dÍÿ=eþïîúõßI‘×ÿ;àÁµð€U€H,tʉléT8u ¬4º†»k © ¸%Ü®W÷ Ì“ê,QQæà<ÿCu¿ªæØ÷ùÿœyÿ/°ÈÿäËÿsòE$€PÎø<‚,nk丘,ä¥t"vø ²>æÍš^!3ÀZzäßœO}¡“,ãÌzmñ’±«à« Šv¿8–ÀWGzðžFqpž3a·o˜ „Yÿãv Àï}&I‚Ù%9@¶›ëªþ×¾ºwìÿÙÛ©(úߎßÿuRû½{SóR;´þH{ùŸ9G”‘·ésçR»»ìyÒàH,NuþŸ6cþ—ËÛ@þ?ŸÿÙIç¿UØ@É{c’6p—–.Pr„Ç@Z& ïZö°Oë‹*ÿÎý»;êùeïÿwRÿßÀÂÿ7ÈåÿC¹=€ƒÙyó9ý>½D7ŸãV寮3ƒrÓ ïLäžûä½rvï}y¼riï]ãûT n°8N¸9@ÿsÿY-ï+ö¥êóÿ;)ªþgÿIHÝíþÌâ?AMO‘&Ó"§Ã¸Õëg†‰2µ.ÊœJ' *Q~¥+M²ÒÐlßáRë\ââ;Ô®½RLé ŠÍV£P.=*M5²Rº^Ì«Œõáï±w™¡ùàßR ýÏqüoµ àÿÊ^ÿsRÞJÊ_%Òþ²6i¨:JZB»o+Ûo§ÞîÅ-8Qù´)@2•>› ‹¢:pÚyýQ§tT–YëÈŠ¡Ö!¥TYMur©ß¬¢Oæ{µäݪ—¯_.FQõ¿oWçù_öÔøOþ“"êôÝãµKün/OÐ)¼— Çœ.úÑïìé‹<úuþŸÿUÞSì¿þ»›¢øÿÇæçQZgç‘ÖlÏÿj6ߣV¯ÓÍ ™OVxå/;ÌHÚ!_­f‰ØŸÈà/Bšjжšèþ§¼Y’û/gg{­äA^tÄ'æTïön´ßûÁë3à¨ö¸{3BŒ6¿14Ψ¡õ˺=¹8㓸lç@&!R HĈí¸PÕrÁ-Rc:›0$À›'h5SÝãð˜žDf˜%Ì×(gnÔÒNÀ1¤0g«:a &h'ŒwÌOuÂdne2WÖP"J|©‡Y¡ün/°H²ÿ\ãÿ÷vªŠýWññŸN `ÿ™ãÿÇNóŒ ýïS~éçõ˜Q¼Àx…âÆiñ>GÞ°<i~ß³Iã1^@ÿsŽÿ¯n+ùŸ+UŸÿÍIQõ?süÿØ%þìÿŸ –zÚZäW¨±€û"Êüò¨/på]j¨¹ä´2Fš'zØ*â½–ûJp¯|/Õè5vGàŠSHÿsÿßÝUÏÿòñŸn  ÿU,ÀŠS p•âÒj[8¥1v屯*‘‰¥k—^½Ô©"K =—õËœAÇÏjë Kýâ%4oÌAæ«7ÔT_fH¨ÿ}uzþ 9ìA9ÿeÛûÿœHÿûj£~u«~µ…§¨€ÀþðùYí´õécë=:Çý¬N‰(hϸ,°˜HÛó3#0ðy- |~†^áÓ‚3N“ÈžêP‰¥ÇšÊ\€°’žòuÞÀ>Â:¡ãg£ß6ðàG¯ÏFˆÔþãì ¹åàu#óŽÓ~Dè§ùq‘"ÿXµ2ÙãÌ„ƒÓ){!á3Gp~–e|µAv»Ù  &èM¦3À\Ø_Þ›sQì¿‘óóß÷ªUõüÏ}ÿé¤ù¿FÜáïÉ¿FáÙï³Ëÿ:Ê<ï½X{¯Ô×<¬ý‚š½«[m}€u˜ÃðÓGˆòfÞyígò%Ÿ›‡Ùø°dûŽý¥÷€ö_ Û5Øú“¯6Ñ+üoº¨ÑØ@ÌqrAž“á}¤(½[p4ÿs¿É“±)k”X­‘§TPé°%òXÇniäUY%þ…í€:kmÆ<$r+J½Ñ–š‘$Оöyr;ÃxGË Ú†Ì rqñ j! œî^“ (ƒ‚æaJØ*]ÏÉäæ¡ªäK̰~/œV,dy®’ÈXeËKÉ¥ˆ¢Ü~©¹‹¢–EKŠ’E.…‘(tNöRf‚ºõ[»f°ÿçöÿŽšÿ×ïÿº)’ý˜ÛÿÁÌíÿÀÛÿÞþ÷ö¿cû?˜·ž´äöàí˜/Þþ¼ý¿,’h5ìÿ9‹"/‹BF°¿ó–EsFzó?XþzK^Tûà|ÿ{·¬žÿSöö¿‹"ÚÿóýÿÁÌ÷ÿK·ÿŸ˜üƒÒK³ésXïÞ&Gfšð`î{Ëm“üž¼†/QNHÙ“©iÎç YEc{ž"f%ŒíyË/dBF°¿ó2y¥Œ½=X,ô¾Ì«ö¿óýÿí]ÿ¿Sñç;)’ýo¾ÿ?˜ùþÿ`éöÿ½ýïíÿ™Øÿ~O~:ûßïÉkxñUó„”­1ÞþŸ³ˆY ûßo¶{!ƒ4ö¿¹”É¢ø]t_òÕþ><¸µÿ÷÷¶Õýÿíoÿ»(rþ7öúÍò¿QZgÙ¿Ik¶ùßZ‡Í÷¨Õëts ê,0¨0ñp€7'OkÓ‡+yãpe­f‰8Upö—Üjà{HÉ'']o5Ñ«VöJæž;98)¥Ä)ÄÁþž ×EFªðÅL8ÇF¡#S"1Vz·wXçk5^Ÿ¹ÚãîÍ1Úüî <‘9íÖ/«+äâŒsbÍ!ç^UË„ùæÜí'}Ò=À~"¹Áj)Y÷“Ž%«Ù¦ÝÛÑr0%9ØŒ ®u¤\ˆ˜PðP‚ ®ÜŽ»ZV¸µ·Ü\xYà ZÍé,2¢KðË—Ö0;É8cžK-_tæB†2ê„ôÙR i)í&}£—ÒÈKi/¥#R:!µÒ§œ°6ÒÙn5ú¶²ÜjKäÿqÿ¨ìñþü7'ðÿüÛÐÿÜvY ˆ¥ÿåw-/ dº«|29Ð#>ÑÃt ’¡*™ T2ôA%^¼ÄýÞ„”­SÙÛ½>ÁÃ<%±ZdÌɼE—A!#Øß"ƒ2ífŽÒ÷p”E.€ý¸ÆìW”óßw*Uoÿ»(ªýXà?§øÀ1þc5áÿñÒñìïÜQ ÁüQ '¦Ã‚L  `“1bdÜ_ØÖ¡Ín£õfcØÆ&@°{/ÕGd¹ç8õ–cà·í€!An`ˆ² ïAN ‰Üœ!#s”èÆ"Ý 825nÄ‹t/Ò½H_.‘ÃHd±>-¬Dx}sG•@þçøÝªêÿñç:)o%çqþáÌó —8ÿ‡ì¡áÑiUy¸‡‡{ÌîásˆL÷ð9D4¼xñ[­FÑýî1O d,‚îáSŒx„æ&ƒRLZŸ€dY‹bÿO®‚§‚ öÿö~U±ÿw÷<þÃIìÿð݇f}¦€‘ÒÃjãé ¾ç¦?áE}^-]wñ•.%À»-:²…Påm¹,@GÌ= ¡½Í?Ø:d²Sr˜ á0ðíïòfÂT †©0©d§=ÿ=xº^Å8ŸŠŽx*1Á'*ÃÎÊKuþ?*sŸÿ;û>ÿ“"Îöîç?%·ŸÿÑmç?irŠùOnŸÓü'M§ÎB ÌÖÙœóÿö¾}u*²æÿ¶êÿßÛ÷ç;)€“ô+Þ²s”\›wW}™A‘ç¯}õpõìxýßÝUôÿŠŸÿN ¿þGïÞpýÉm×ÿä¶Y®ÿL¦ž6ßžÎJ `:ýJî‹ÀºªÐÎ *½‚þö÷MýDœ) F ÌÿÎ<æ¿ÿ±[õç:)ÂüïØÍÿN¾ùß™Óüïhç¨å/ªèÌP(ó?˜ÇüßSæÿŽÏÿâ¤ó?°›ÿA¾ùÌiþÚùsß¿-ìôf©(ó²ëÿ®ŸÿNŠ0ÿ'vó’oþOæ4ÿ'Ë©ÿOrLÿu`þo­ÿAñÛÙó¿¢Øÿ;e¯ÿ;)üü¬¶ÿ‚\»‹Í?¶žse·ê‡¾öûܶþ‚ïü±¢ÎÿçÁØíü/oïî¨ø?ÿqþÓwo<ÿ µýüïšåüçÂh{)Ó_ȰK 4J¥è†KI„\ÍÁVdÄ_/É×Ë\Dýá’öG-”)rbsQ¼\&ß.‰î€üÐ Eþ·çÿRòÿîîzùï¤ò¿m§¶ói€mç*`;/ükÞ*`{æ: :ÿçÿRóïUüüwQÄùo…ÿ Éíç¿ ü—8ÿó¿X-sC±ŽÏýÍÿ¾kûœÿeÿvRÄùß·±ÿ(µCKŽ´—îÈјm«bµ1À‚@¶ÖrÏÿNTðôÏöÿì+øÏJÅïÿ8)Âü§ïÞtúbëµ?¼ÉÙÊÛ+Ddw‚#Öp“öÊ‚K1‚;˜¦Rð’ÄÔ‚~AïOüÝ»ƒV¡¨ò¿ø Kþ—w¶½ÿgNE”ÿ–+@Î5Àý*±Xm¬ôÒ .Ù›~‘Xâ¢ÈÿÛk×çÿíT÷ÔøÏm/ÿ)ÿøú Ïÿ»Îuþ_NóŸ´–žNØÆ9ß,Ró“_ŽyÚ£ -±~}1HâÏÓNJ±Âëîª#º[·0ÅI沓Ée$ø7L—‘œ_¿ìIõà·@?]]Ì"›ÿÑ1~ÑÊÅ ü¾§Zi1=ÝråeK²JQ©°yÙRséSý(™|˜”c7‰ÆÙ¨Œ>\$Ú™’¥–)ã°s@†ì7D'[®d[/j\Jã‹§x€…ãJ3¬PiŠa¥É#²Üç‘rZTý¿ûàÿ½»¯žÿ]Ý÷þ'EÑÿéë7Ôÿ ­‰þÿC!ú?nÍöü¯<ÇvI÷Ôóš™.&b¤Õ@¥«xƒ|šW†ÑÀdqtsC¼¹-Zx1«[†ÉíNü:¯ãëõÄN°6ŽŽÒŽó’îÇOˆ¯·§2 ŽÐ‘¡­ü¥\nVsÚá¸F€é‘`Z½Ëî|d}@È&²?!„WÔ°XøN§¨ ´éRsë së)Ì­ÃÌ­§0·3·nËÜjNæÖaæÖçvIfŠU,‚º¬@ 4YD¨³Ð„óCÀóBbE¹_k ÇëN}$”nF§ :ÍŒNtšm=è–bF‹¼U'tš´ÔLè4i©™Ð«)-Ùß…˜ÏŠeœÌga “;c>‡,×Ú¾ô½À¯e‡ÅV0dÿ¹ÞÿÁWÕýþ“Øæû?]Ûý4ü“´¶û?©öœßÓ±ÚÓ)~ÏÆ|'¦pC,Ý{[1]—.óâ=äÝ´HŸ=ßÊ<õ;,ÃeiUN“(™zGA[)]¿•â‹Iôÿ¡ãøJ¹ªäÿ©”}þ_'EÕÿ‡æêÿÐ!ú«;4: ÔD‘tpP‘WõòôJTU¼¤5 ²£Ìæ¡NèÍVÀX—åáºVŸKC5'»sÑŠ]°ú&uÐĉå¦ÖuP¯ ½zàËëñéòäÿ«V|þ'Eˆÿ±Kÿ/ûƒóäÚÜfùÿæ—üaæ¹HQæÿÐyü÷öþ¾ÿWÙÝöóßEæÿÐ&úo8û >Þ*|ºùË'xÐltʺº Ì·¥ïAqy!ŠQÄ%9A8cÊìU@Sù%qyÐü¿u¼þWUüçNÙŸÿç¤ÈóÿÖJÜ:–·ëѲ¼7¯ãOíøSn…Eävýªt]j—ðð'óßÛ&Qæ¿óüß»5ÿ¯ßÿwRäùo‘þ‘R»ÿrÇ)T€T`óÓâ¯ùf \>m¤Fâƒó¿` kþï¨çîî{ûßIQæ¿ðàZxÀ*@8G;åxšw*‰6PÖOy\“Ü3´Ü®WŠ+{…é6Õ–«(ó?pžÿ¡ºWôŸÿÁI‘÷ÿ‹üA¾üùæ~™þAEû]|:þˆ.÷}aûpšlIñZ)‘Zˆº­tDßÅq6¢Ò@ZÇÅ1z…ÿG_e]M¯ó˜‡V-or¦EFaLyA<ãø…Յйˆûßâã¼h«@Œg§-H~ôÚ¼€Vôñ ÕÅq Ð*ˆbÙ/Ž% •.ò&ž~F𪢠yúw~lóÎ/føÎéEÿÎ ¶ÌƒÕÌN êí«{ÇþŸ=5ÿcÕçÿwSû½{SóR;´þH{ÙIÌÈñó9£§ˆÝ]ö4ix$'F§:ÿÎí¿Ý²ÿUõóßIQì¿…ý7piÿ ÿJ ©C½>Í3¸«XSp1ýÜ eÉ¡±â+dÅ >Òä?ѵP³†;Oc7wK.û½/%—öÞá÷ÍFCAvÜ`fvÜ2núŸëøŸjy_9ÿ·âóÿ»)ªþgÿCHÅÿàÆŠñþ39«‘vGhàµAÁZš­·^6QóX¨K¡|¥éSVššÍ"<\jÝK\„‡Ú5X 3"›ßtiÍV§P.}*ME²R¾^Ì«Œõâï±w™¡#ùð°R ýÏqüWµªÆW½ÿÏMô¿Š…XqªVf«¦G„gê€æá‹¢$:pä®L‚ËÍ2ê’•eÖ@de²b¨Hö«©Z.õ›UtË|¯–¼[CU³âÝqó+ªþ÷íjà<þ_ñÿí”}ü“"â?è»7Æj—øÜž}ü¼£ ‡ÿ,úÑïìÙ‹=úuþŸÿRòÿVýù/NŠbÿÍÏ¡´ÎÎ!­ÙžÿÒ:l¾G­^§›2‡¤ÀÊ!/6°‘´C^ZÍ17‘Á!/„4Õòl5Ñ+üO‘v¸$÷!/ÎÎv™ê gf-³kq¡ƒ=±žz·w£ üÞ^Ÿ‡ ´ÇÝ›b´ùmŸ±Ùé´aYÇ'g| ‚í½È4Dª!‰±{ªöìq ï˜Îh °(à ZÍTÁ8ð;ò^¼D­8!e+L¦RL„9Ÿ”fMïyŠ˜•0½ç-c¼ ÁþÎ[Èä•2ö&õÀo¡ûbSûßùþÿöî¶ÿžS÷ÿæûÿƒ™ïÿ–nÿßüÞàŸÁï·ä§3øý–¼†/QOHÙ ã þ9‹˜Õ0øý^»2Hcð›K^ȘZü~Ý—üEµÿ‡níÿýÝ]Õþ÷çÿ9)Êþ?}ý†ûÿ„ÖYöoÒšmþ·Öaó=jõ:Ý\gC§: *L¼œ àdÊ“§Íã ”äáJÚ8\U«Y"Þd•œý%·8RÒÉI×[MôªÕ„]†©çNNJ)Ñq q°¿'èÄÀo‘‘*|1óͱqAèÈlH,•ÞíVøZ̓×g@~&ö¸{3BŒ6¿/ÏaN5¤õ˺ ¹8ã¼VsH¹WÕ2a¾™õ@ãIŸZ0žH~¯ZJn=Åžc ¾j¶Éõv´LÉã5ckk)Ö"ö<” k+$·cÅ®Ì 4'k˹…מ ÕœÎ#z¿~iͲ“ŒC湤ÕEç%ÔIi(/¡NJŸ-¥”6Ón’3Ê3ËËéœrÚ(áâ Ôs’Ó€N“Íib9M"ë„1à{7–§œ4Ž¥pXUª,Ž}gzç™4>_àÑÿÇ5þ£²ïñó*€ÿÇ<þcè2þc¸¼ñSe€XE¸ˆà”ÉYÍ4î %CC2¤dècH4¼x‰»½ )[¥²7{}v‡yJ c´Èˆ“y‹ /ƒBF°¿/M¥˜Ô²D°ÿ×ø½í²jÿ—½ýö`ÿœâ?ÇøE„XyTÈê#@N=d± àr©`Ž{‹ –yk1˜ïÖbÂÄùï,s„€°¿K† <DRK$¥]!@¼”öRÚKi´àRDˆL ^6òÿ8ÇìªþŸÿ㤼•œ?Æù?†3Ïÿ1\Þü²‹†Ãw¤Uäð1#À‡Ï!2àÃçÑðbõX»ÍV£è~ø˜§2A øð)F¼ Bs“A)v²|,o‘íö‚‹udØÿÕÝ$þcwwo›Øÿ»Õ}oÿ»(±!þ`Ôéõ·îþ¹&\ºï]Ë׆xb+tWCñZ¦©ÏÛú¡Ta&ðMŒ¿ ¦îæ°ÿ4¯Üô‡%´µµ&´H3éè݇Áhü?åa±òÝwôò¿¯~¿ïá q·£!³óð52Fëì"6Úq;Ñþ:ZçëV,<"GÃuÚÙïn»ßm ¿b)¶¡.j˜œ–uò¬diÜEˆ}Fh‡[â54"ÜáwÓËå„ðÇ4“Ëey‰‹©…‡ Æñáÿû‘ðÛËOï&íÓt“úvÍ»¹Ïµ¾—ÖÍ=Žp߬›x¨üÛ¢+;(j¡šÖ“jB·cØ‘kgY—Ð¥ŽìÝ„nÏ”ÃC‹çªÆo°’ÖʆÑÓÿ°¡tVóð!ÙÚg’žê®;¬hgá þm#i5*¯^ÉsvXùŠÉHU&,šò¡þŒä)ù5jïf€W•Ñ ~F¬'bÑûݧ«áÕCËu¬A‡3é+ñúý¯}» ˆÏ¯?vÛ#ª]²Eƒ0óßrulÅ`r}#Z°½Î_Š;9ôWÚ¹È"!:q¸FÑ¥kÒô÷wèí&ú¹?lwÑ}ïñ+êß þÓ#Ülˆî®;÷ø6ß²uª7ZSÞX$uVÖÿ&Wσ±Ûý|Q=ÿÝŸÿæ¦ðû?á»wu²¶€uH¬Go!Ty[.OLÛ[‡¶](Ѧ–e—´V®´çR é/¥èÛK¢`Úf@¿^’¯—á‡uM͈®þpIûÃmsë!K" ?䟬¸„.“o—Dò Qô(ó¿Ýw?ÿñœ—çÅÛNŠ0ÿÙ»7ÿ”Úáü'í¥Ìíd_‘¹Î?šëé“Ü\½Pæ§?jÿ<](2æ iþHˆŸÿ.Š0ÿ“wo*È4èp„ÚW÷÷á[°º=ÂÓ}^‘&tÝÅWº” ÷x›ÜåJrDÏ•*=d9JþE‚D¢…4·èÒ$aI¶D)!úDÞ!¿‚’ÿOÎåÿŽ"ÿ÷}þ''E–ÿOÖòÿ)—ür,ÿŸŠ‘ÿæ+ÀÓ¬OV+À“_V¯¨ò?ÀÓÔéþ/ýQ²ÿww¼þ龜òŸ½{cáOÉ]ÊqÒ (Ä;ý§ëûnä£÷˜»ÿòHê\¢Y–ÀìqäCé°±ÙÊYeþ“}@§þ¿2V÷ÔüŸÛÛ~þ»(Âügï>sî÷o%%„Vñ†+™@:’&¢ ãP‹Œä×£cžöèBK¬Û±0Êî!Ыz«ÐÄuwUÞ ú@{’c’‘øÃ0N$ãØ½~,Õst|€ßýtqpt1‹,GÇø5+/ðÛÖÉýg•œ¼Çêl—è=á"¿îpÛ|~>@ëÑ— Ì2ŠøKá "oñ×ÉH õ…WjÇŸ~­ýOå_¥úûsò÷]Ô‹SøÉŸgþ†Íç±á1÷ß°ŒHç7GÏrœÍ„á,WüI‚ž§BnâOR1ÏzH³‚XfB;*+™Ø4‹>\Ä›(i/°™·a©ø“wGPÁ¡s )PÇ›ÔÛÿ: báüCÿðÿ€?p¿Q@ïÁì’¯Ó[ðuñ¹¯!'NÐ?ÈÑ„öˆï9AÿøGÂ=Vžñõpc…ûHçÕ³ ³ Ï„•Ò"ôr—N“ÅiWØSi¥% k¼ÔÒõ¡¤Y`q©¡R²Æ>—¸%–¬Ð‹äy’§[៣[º•ß"þ• ²ÏèfØí®?óÚÉâìÊ”ÐúyM:PÐÓïO~f†q…Óćq½´¢úÿº®ÏÞÝÛQñeïÿsR¤ü¿áë7ÊÿËhMòÿþP@þ_Úšmþß·#„3³%`É"Ôej-¡e ‰(ÌtNÈØD5)`’ÁÈúhÄ—Úg‡ÕLٴᦙ²iÃM3e­‡Û"MY‘…êŒM“zš›&õ43¶h©çtƲ¿ 1açAþËIy+Æøî¢à?º‹ÿðŽ‚ ÅC6ÌÔròHŒ¯‘s1³Ô©Œ:þÊ&YÇrÝlœëÎdÝzeÚŒ¼–Ï‚C—²w›wm¤î·sŸ¤þðJÙäûÕè·cX2V0v’1zÈ€î1ºoLQ‹f†÷‹`ÒT_Ò<_R¼^`ÝÛ 3’âåbðpC‹@aED§£)te1»±˜\Xt÷ÝŒ 8®D^+y¬˜ªÃ hÅT]UbJ“>5è¥b¢v¢„IÞ+N)FOÐÇô.ÑüJL›àº!ÙÆCvù¦Â§¹‹ ‘×|ë´ Ã_õ½÷Õ0üÔøùƒwpv/òt“AÁr¦!É& èM®C°$B¶çè>þŸ“[uOàVØ40‹“Œ +¢ÓØžJ~ÜËde6]ÿ¯>þCûP¿ÿ­UÛÿ+Ijü‡ëñ®+ÿpmÿAÌîŸõ^ þÈæ³”¸±Ï  Çx°6¤†xè÷šÔ €,B<Т©~=&ÿ´±¥ pˆ‡Ê";ÜË0lšsQ8ú|½Ø%ßýä‡sàp²TöÕðj²¯ ¯´”ƒ°¬u @_®8‚—œ'ê’aA_q¢°p>4tÌh¨vŹܒ3*@H[,Ðï¥;Žfs®awŠ^©VDÁH0€nb$˜ó{K0Œ“OC«  ÈG_§’¼GEά½UÂÕÀ›˜ ý¯êýß#Èÿ«Þÿ­$=Q”?ëýßôøðþï*Üÿ¯Ëˆÿj~«WöîÙ–oÉ;½õ¶îÊ·uº'*¾¯›¶U›k8×Zúþìë3ÿ&Æa¨wrëÜz'—¦{º“+FL°böíéf3ûíÙÓ…˜= •Ù—´;ÜÒ}\ÒÀG:ßoÑænæV°—[$ú¿_²úŸ¥ÿ·´óÿN§SëÿU$Eÿ÷­Õ3Nÿ“X•}fÞ,œª½kÍ5ÍGÂPyŠºå~k†š^¢^®«ß‘Þ«êà&øV}±¸]Õ¹´ x®ÍC«5`yUäëŽnà >a”œä.í^Çõ/t³>é6¬sËÖäã”KO DhˆBhVåÁ(`ðASäACØA0æ ]” 0Ì`JŒAc€Áå”úäÙ¬ÓÛªô)½4¬Ô¨u™üä6…Ÿ ÌÀŒDs]NãÏ+ê(ëQ  õ¿SõþY/«ñ¿êøÕ$uýïØ+ŽYèÐô¿N½ÿWI’ýçVñfWˆÝŒø?ó•Ýÿbª˜rçË»ú–—R<†ë ?+¿»…ºjº+±1ðÃ:|‰ç÷(ÊÏ<%ÊÏ»ú²–.´¼`ñ?ÏÄœ:ÂOá'J÷6‰½¯ãh@6{G›Íß3|ú--ïÔÓ¨%Eõ™o\TiÜ[{= -ðm›}iôÿêãÿ´µû_œƒZÿ¯$)ú¿uüŸyJüŸJOÿÎ×ÿ'¥~ÈÁ£Íß5Ÿæ-ã§æ³^M÷ó™[ó¹‡Ç]3?äC>ìºDyíVGð‘2–QÚ“Ç«ìÒ¸ !|lÙÈ­äP‘üuhH¢~#ê6UªÐú¿êø?Íÿ³ÓqêõI]ÿ[Çÿ™§Åÿ©4è¼Üø?!§ì@™0Îdh¾»³>m¡ªÝ;c`Ÿ²Cùð/£Gò©ã÷X-`û¤ŠX†ïQ"òÌï¥f’õa²j’7O¸FÙ䉼(oe-ÇJÇÑW֪ʢ5ÿм)þÖ¼1šMÙú‹¢Uª kÆf4…BÍ(£ÉeF€L܆C|_ÎJ» ·0¡ÙÒ¢ÐhßP.ýS[š$HÚ*5ö£Æ´Iïç7½@'LŽu«åùÀbí˜Û¿‹ÛçÀˆ"¥x\žÈ›Ë–'ELiayDÅw^,ÌŽ, 67ÊNJÇ[°Ñ¶¡IÓÿw0®VÿouŽ4ýÿø¨Öÿ«H’þ~ûè@h¦ €•Ž ›O€î#ä® ghÞí!»`°ÇìÂl¬ÈÍ5tú¿›LªŽÿpÔÖÏÿÔ÷W’Ôøáç·‹ÿÀÊVÿö–7þCÿ¬÷õGÞ°ð%ௗ»<ï•àæ¨6çƒÒ"Eô{Mº›€,"EТ© ýzLþ-)âõÉë¦Ì[Kú÷½¶àÀë ú·ºht¦s“ôèóõb—|÷“Î#ÛRÙWë Ë&AéS<4Ì:Píô媃I¬!¦FÇŒ†µÄÔ¨ðÄ:cË2׈Ö#¯Sï/7¬Ë¤`+a"(:„‰`Îï-ÁT#£&Ñ¥)"k‚±£—Ä l´«_aE!Pm‹Ý¬è•Çïj÷¿ÖöŸj’®ÿåˆÿ®PÜæøï¹ÀÔm”Ám x¿#À—­ ®W’V·u÷¥‚ j¬<úY)kã\áC/ŠcöcÆ}#´ÉuëQuP÷s¦·‰ÞÂÛ@n%ªu¨öµ&Hÿ+Yý³ˆÿ®ÿ?¨ÏÿW“ý/úW­ö·éñßËÚÜ¿ßE®ZÝ­VÒì”´ZG[NG{€*Z9ÚýWÇjml)mìá)c%š>–ÓÉj•ì¡$Mÿ[\Vÿýø¨ø×ç?*I’ÿwøí­œ¿YÑÜñr)|´‹2;d)|§@{½³ÓŸQo4øllPs«~&7vQÓ{úLÐúøïÞYv„FT”,¬¨žðVÕ·½3ô˜üË2^ÚÖKtÄ1êìµAèŽ4~Á:f¢1>¶d—¢K¨zâêb³‡jd±(ir…”°W#)¥®9˜…,¤bu-J–®§:`ñªTŠz§R0â‚õ¡b‚¾Ü¼ÀQ6„Eÿ©Z€!ˆè¥ÜÀd Ä»c^Þ;nÔ·h€ð¤aÆPß—°&kåDÖ¬(›·ää\œé¨RÛˆFˆÞ(Aòÿ’¦‹¦A‹¢°ˆbJ$¡_“ERˆKÿ¤ãèC1“Púòë[‰_|bTB¬ 96ˆŠâ•üÔØ“ŠÄ}È1Hø¥QD@ôo;òßm,¶(l*K:T)Ì-ãhA™J˧!ÙS§D‰\î™ aádË2„ͶÚØ‚Êí?mýþ÷Nmÿ©$)öŸÀÞþ¤ØL7ä´ÿµý‡®í?k²ÿÔæK¥+X÷¢lËÍ?AmþqñàÍ?AmþÙNdÍŠ¶ÂüƒŒAjѲ )ŸEéÝsö‹dNÊæùêEÄ®õ`·zÈN1%-g Ú$KКåD-(¤Ï·nAQ¥¤03·õY‚*4÷Õ¤Ûæ•ûÿtÚÚùÿÚþSQ’í?s{ÿŸùêýæ[çÿ›|ææÐ”÷Ò¦³Ä “µMf56ËÛ´k›Œa­=¯]r ¸xˆKm^4K™+m*”pÞè¾[ÖÉb¬yÌV[°¯ÍÛùh&–u³ýšïKŸoÝ|¿(ãWø>Ú0ËI…>4óûïC³Í °ÿTîÿÓq=þGÿ¿’¤Øìýæ«÷ÿ™oÿOmÿY¹ýG8“UÛÒ”³Ú'g9ûOí“cÀÅCÔxÑP,ÕöŸ5³k³öŸõ9ÛÈÖ”Ú×fcø-¤Ï·nPTlºM•– {ëD³ÅI·ÿøUßÿx|ÔÖí?úþJ’ÿ5üüvñ_YÙÊâ¿ÒÞª½ÿ1ÕVdÑ 7U|¡¤áú-p,iŠ^BÕ;³ «Xœâû«2,O)e•÷áµ’êÛÐ&Uò•’«»:r3#Άó¾ò¾Çn5—DR"^ßw ºî Çû\Ñ%‘*ÖwWQ…Q¨ ›#ïëVV'%ô®¦ž‡BOóÆÞ=0ã0%BèŠ5´Ò44Du.x6AZT<.͸¨VC«FE3_²ˆŠèp>p #¨Ê¥_c*Þ„Qvc#«®äzÒõ²j^]M çšW×¼ºæÕRåÕé7èB¼:1[™íV~%7ã®ÉnÙªöÿ9âÿÔþ?Õ¤'ŠñÇÚÿÇ_ýù/kÏ-òç>úIF˜ÎBu\Ÿµøùõ²¥|ˆüú ™q ™ E[örÏgÈšm…‹Q}ÄL|·NÏ¢uK…Z,HŸo3ÄZ½d@×õȯ¡`ÿ *÷ÿ9ÐãÿtjûOI÷ÿ røÿ•úÿûÿ<÷ŸUùþ¨oa«Rí÷SÅMÓúnr¥~?Á¦n&Wë÷lî^ò¶l%õV²õVröVr°„Û&jWèdÁ¹+rÚpÎ]•P͹kÎ]sn^  Î]ŒuC^@ùXwbQJ1)÷Â+²ÿTïÿs¬ÙkÿŸJ’âÿcÿÇ_}ükãÿ¨6îî“Ö̽ T»ÿl§ûOBh9÷Ÿ:„wŸ7^ÊÖî?›Î¬YÐV¸ÿ¬ñ:/žo^HnâA„Z·l¨…ƒôù†p@ب>&ÁþãÍnps¹Ÿfå(”2ì?­Ã–êÿspÜ>¬í?U$—Qÿö;îNøJ³]ÍüáèOÀÎ`“ç°Þ~Tãß&' }„œ'ívèäF„Kzóg7 ªËǽ7¦ÍÛ&áV·Í;úç®Ißï&5B%œ/+½tg“ùxx¾k Ô\õ™ s¶HÛSªÜ6öv›wäI´ú kIJÌþBJ4õ¶à•$ÓÿÍÆÐ§¶ÿV’8ýߤÿ›RèÿÆ@ÿ7ú¿èÿ¦)d¤ÿFÿ7þ½Ap3Y ýj×è¿öÿ­&…¤}ûi^úgõö—fñÔãTG_”Ï &ÄÊ,øs莂Ñlf6…2 0U»9­}ÂJÆroIŸ%þ ß[ ùgËÿv[¥ÿÃÃzý_IŠè?þö9ÉŸT[žøÃ¾!áqòÚÈxžYúƒôÏ–´Gq)pBÛ»ï þ§þÄY“üWãÿÖò¿’Ñòís2ZoyõÎi¾€ˆŸ¾7R?Íl % ˆZû„5ô@Ä¿HÿÁªäÿñA«¦ÿ*RDÿAÁ@PÊ È·ÒÖ4³i³ð‡¤-Ðp±•üámeýãU²åÿ‘êÿٮ鿚Ñ?ÿö9«¸<ÀÖœjÀyl¢!P±à‡béU @ú'k‚šþ«H1ýUp9¶Vpª€ó( ý‡*~(:§ÿ‘;˜ n×BÿGÚý?­c§¦ÿ*RH¸Â·ÏGÿaÅ¥é?éŸÓÿˆ¾@XT¡îèmX)òA’gµNÂ&Í‹I omô¯íÿú¯íÿ•¤eéß³§Ç1Ó¿gOÿHÿžý§›ÿ"Fà= F а6ú?ÔζÛG5ýW‘"úŠÒPŽüìé?é?°£ÿÄè§Ò|ð€h^LýãõÉÕþØvjý¿’Ñ?.Jÿ¸úÇöôAúǹ䚀'àôÿzðex5§Ñ@Á”NÿíÎq›®ÿÛv§uèÑý¿ƒVíÿ[Iú.Œó|Fäo€„üÙä@‘;ßíxã¯ct‚ö÷Ÿìïľoз»ÉüÙMwHÑïÐ  Ñ`ãá×á9è1êìì }Ÿ–"à Ïü|Ï.〴( "ñÚúÛpdl4hvÅF›À; í“æ¾oÐíÝè‡ÿèÐQ¯»ˆ‚LÔPözÅFÙf¿CÌœrœ„=S`ùl…’è'¤x@;O  üÙâs}šÈryBÿQOàÁŸƒ9/¸ƒ1-=º³ùÏܲ'½ u•} Ââìù®¡Æùé›(7,F;î|Ì‹;Ž@ËîÏKí¥o"f7îÈÍ !T#B½o÷-{Ä©ýй’4NEý˜4žˆzCëbóƒ´æÓ—Î2K‡ÓÈçáä+'‹Ï—ÒÓÐ$|˜•<ÎÙ#§ëä½/•ò܉­wRÉ;ßÚ[H#Z\âÓ\Ê›âÙå‚Pƒ~Xl§ ¨ç¸ó$Üyî<wžŒ;Ï€;OÂ'áΓpçI¸ó ¸ó$Üyî< wžŒ;Ï€;/Á]a!αçJØs%ì¹×RÞµœcÏ?Iu$hÝŒ¤d·7K‘ïy#=¹âh…¯AŸ ¯AÆ-• ¿nñåÇ$–0‰%Lb “øZ΃1‰%Lb “XÂ$–0‰ ˜Ä&±„I,aK˜ÄLb “8ÆdŠôvéíĒˉŠóyg·¸ÈvžŠíÇúœÌÖªd mEj;OEìû«äåÎSö½ƒUr sçiòñrõV±ñN"âmúT¥}v§r¿³ŒÜïHrŸ¯à©d–žü/Ò“#<Ò«¬÷gX%¯‹ ÕŽ$TùPî½\ï8îçï¬bǽ; ÷ÎÙgT%­'fI˜…ZîôiTŸˆK1aêhg¿ÿáå˳/úO!­}í_‘—dõ”VèvYá¨ÑŸÎö÷ŸÄöŸ\ôýÞ¾»³•}ÉʾŒË²ì«b;R|ÿ'X_ü‡íüçñaíÿQI 7nƒ‚Ç?‚RN¶‡?á`ãÇÕqÝéƒòÊ´$п»¶ó_‡šÿgÛ©ÏW’"úw‹2·àZ³Wã®0ö x Œ@¤ÿµÿÒé¿Õ9¨é¿ŠÓÁó_ÑfÜòôo{þ+,)Ó¿Õ™/óa¯°šþ×ÿéàHõÿ>8jÕëÿJRDÿÅÂ?”ý!_ð!öCHýùC=hqžN´=‰ô¿*EÿDÚëëÿZþW’bú/ÌJây¹€ÎÊü< È/aè}ñßtûßÑQíÿ]IŠè¿èò¿œÕ¿õâ_[û[-ýuû_¸îÀËþ$qúÜâ˽ú“¥ úoÄñ_:Gí£ãðüG}þ«’”ÜÃùÏ`áfû×ÿâWsþÓ]ÜÍ‡Ò«Ì E—¸H·Z„ L†Ñuš{_GÓ«Ùnt‹¤ZÝ”¹g¨Þ.üt‹¦XïÙŽp…<Ë ,ë÷ÿ¢ô×îÍ.É¿1ù7 ÿòïù÷ŸVÆÿ¾=ÛI¹8sŽñ„ô™ø~$\—Iï¡T˱ D¥§Ýi AÂL`{ét?õߟ7DŒ‹ßmWê†^¤´/]0GäDctÒz†Fô±òêÇwCœŽ~<¢h]ÌÆôæ¸FØíï£ÿ&wþ°Rbí°Eh\$œˆÑ÷gøù±Ý¤õš)·ãIœûGW BCßo¢GïDè òÐ?7ùZ Îÿ“kˆÿ©Æÿ:8®ãÿV“Â¥ÿöùÖ¸”ûâÞmïÿÁÂ5?ŠÃ¶¿8 Ü„ïùm@2ý¯éþ€þëø?Õ$NÿEîÿÁ¥Üÿ÷n{ÿ®ùèßò ú¿aôŸo é?ZË?‰V÷%÷‘NÿÇÇDë‹éÿðð¨Æÿ¬í¿•$¢L©"®àIô´äYÔIÕwžìí =ôbz3!$¾zÌo’,žG_Éoª3$ÿ‰ÒÖÙ›Þ‹(áá§BOöЂ˜ îÐׇ.‡‹?‡„}Ìǃa-“€¶°3$}Dõßž÷^œ£¿ºtŠÆ·pž´[íf|‹é8~å K¨øþüôMÿÝÛþ‹¨rt}óI»ן¦r#*yבûðîÕÛ¨v!öIÛ‰[aw^“g¥ûÞÙéÏIÏìÂÜ“v'®=*Uúg½x°¯†W¤ÀA\þ|ôùš>;‚ùé“;ßôßN¤ó=ê>"êM¬¤…Ÿë¤¼D›{çÏ3ö­…P mÄÎ>\ÝLÝõ E˜½|êBí‚"*T|8b·ü=Ù¹Ï 92Æ”ôLUá7M>„Åãùõ@~µg¸N—·AoÔUêüÖ”ó#Ê_,a¢#©ãØûØÌê”Ö§|Z—PŸ@r•l8 }F…òôWúŒ&õËd¦]¾Òø sŸðœ[2)/Sê¢Ùt|Ǧ3%'1âCôÐPCc‘Õ@…цµ´±Æ¶'¶–y¦Â­z.Åž4 ¼ÈÀkCFæ\ê£êwQïà/l!Yk4Êœó5 PœiF’ÓhÖ4†´0\Ó( ŸNÃk„¹ œJ†`š·péaÆœyZe)žÛ¾øX N¶où‘ anm%ð¶pbþÚö\C#€­Ã‚,3ÿ·%¶ó_2HmÊ2ĸ1`½1îaˆÙ†ˆÝæÐ6,?D<¦cÊ´ö°ßÑk‰Ç-\v˜PfšJYvàm_r”Ží[nD(˜Ûšþ·p©aúʶ,B›ô[‡›I_|Îo:læ¼´GU//ø|Èò™¨—¥,/p½¼ÀõòBÁǽ_^࿼ÀõòB™ó[‡«å…«½Ürö£7³•³#øŠ|Ù´ ¯U$¦{1äò:V"!²v 7-+¶džß§§DØ?}+Ðm–’Y Z"•Ü ûÎê½³Êî{æúœF˜ø×†ù6À0×1ïlð°­§WJK৺@kçfV/7Óý,EDžCÇR|ûæU Ï­ÂÍê%h*:Ì2´"”/FÓOrY Ò”ƒ¦íSõË®Z”æ<±¦27[0V-MËc®ãŲeÉ‘ç˜hy„ª·z¡Zàf¶žµIW`ÙeÛ+æ®)¦rKIc2•§Œóì _W,€·'«¼f4˜¥îê§—”—&q³ Í ˆ1Iº”b·Öß; ®-—Fe*GÖÚA°UÜhWÅPŽô%¤§Íút™yUÊ´Zj}°ÎÕóZÒ‡h¨%½Ž“*éñ}”ôø>Jz¼rIil¥Šz¼rQŸB1YャÇ÷FÖW{¡³±&¦oúÖðM5çƒü Ï 0Öíi?—'ýežmÝ®\×Õ¶áò#—Å# VAêª<Ú…†Aaz ¶ô¿äÅà2Ž42꤉·r<æ›Y¾S*bÊÅL¨)aŽY"sáWM¦K2SîÚU1Ù>†Y¢Æç’øTãl¥.uïÜZNƒ;Çé,ÀÛhI]j˜#µ‹‘‰Æ×e"3çÛ‘½$zJ™l¶}Pr{Écú"zL†¥Ë£T=æ¿•Ò»,s¼µàÖÒé ÀÝh©‚>K)c@ŸŽ-½Kôm¼´. ‰¹&Õ6Èée³üô²Ã䃒ÏË|øKè1 jl.…Mõt|-•W!•q-•—‘ʸ–ʬÔR¹ ©Œk©\¢TƵT^Z*Ã;ÙÉöuìœoòɯeMq ðz¸ñ²Æè”[hwÕ+µ¬ÉÚZ5bRõ¤­é³øZp èÓìIWl7Å/5…fn£X‘èíÐ'4s—t¯>Ú£7tÊoè]ñM´¿¿¿ ߈þ-¾=úó·:‰‰M¬'£©;¾ñ†OBô_ï_—ØG«Õ::8@ôïñÑûÛrÂgúªux|ˆÚíÎÁAË9<Ê7ãÑ0¥)vu•’ƒ’¿[’B·Sá»ÓÇû£Åb8E—wè×áh1@ߌ‚ëÉ¥>̽ÁbèÑÿoxu…~™ùÓ¡Os^ýÏCOl-•£ç™¿ }º;d}=aD;¥Tò¸—ÇÇŸ~Ùù޼ ëîèÝ{Sw÷üô7ÊY¾‹f-úgÔîþõ¿Øû¨.m©ûËé9útåzbF×yÉ2ƒ]Ô@„W,f¤D‘ç&j£]´«–î¿'…›h”o—J Ú1©ñêÅÖí~<œîÆ(†ãßÑï½yÑU«ž½yƳégµ|TA˜ä|7C=?d•jƒQgRqÚyÈ^ã¡ì©ùŽ¥÷Ǡ쨾†‚Âl¯qÚë}Ú¡_ ÷2³i"b(”(üóIÅ»Â3”6ì'X`ò9)0K ÞÜÏŸh<>ƒÇÇàÁcðø‡ÇÇáÁãðø8<Ó8\>‡ËÇá‚ãpù8\x.‡kæãÀà80Çù80<ÌÇMã<2«hòuÉOðÓñ"ž©ˆÐŒgj‡]sOEòh%)à\^À `^Z›€Û† ã ބಟàD#./ã‚“€·ƒMí`Þ6µLý‰–a?Á2ƒàf•¡?ÁÏÈÛñLíx¼ÏÔNà r#r…!¹Æ1aaPØ8*, ÇåIÓ=™¨¢´q¸´ÑæïÝäk<ÉO`‚_ò—`9/0‡ |ú(*@~ Ü%ùä'ÔÏŸÃõ^ßpxz#Á‘àq$x <ŽD‚Ç‘àAHð8< G‚!ÁãHð@$x ˆq%b"ô'Pà’€ÀsÄ $°Qú,àò.4È ô'4ž ‰Yy} s^Bæh š0GÑ„9š0ˆ&ÌÑ„A4aŽ& ¢ s4aM˜£ ChÂMDæh šØ5Ãaö(ÀùÊg¯ÐèæQú(À[XÀ-pδ9 %t€]ð—`9/0 xˆãÁñàqÃÁð8†ÇÁð@0<†ƒáq0< ƒá`¸ Ãå`¸ .ÃÁp9. †ËÁpA0\† ‚9s00æ`` ÌÁÀ0˜ƒA00‡`|7 ¶°ﺧýy¬aèã‹s’¯Í^n‰êŸ¿}ÿ3”¢hþk°â €õyökmÚñþ{Pÿ‚!¬ö/ØÁz@ÿ‚¬õ/XÁúýŸ¾ÓUÑÄØÒï¾}÷›®<'¶–þéG=_0õO_Ÿ~ìx®So2†4ÁÖƒÆ Ø¿zà¸ùë¬gƒ`ýêBcŒ_]h ‚í« Ž›¾Îº†1–¯ h ‚áëƒ`÷ºÇÀÍ^g†1f€~ïí{èkñ=C ¡‘ž¡ÁÚÔïwO_ém$ù=(_0xu¡|ÁÞu×[†p©ºÊдâ6*Z¤ }uÞÊ…¡ÁÒuahE0tõßœ¿v "ÜÔ?íx }9ÞJÏЊ`åêZ\ý®i4‚‹ ×0ÁÄÕ»0H°põ.Lcò¤™ÏÊÜö­~ÿ·×ÿ«ç_òüçPþœç¿ò¹]§ÿó‹s û$»ÿ=çÙïÀÚ¯í@Õ^]ËìZ=xÁ¬Õƒ€¬Z=xÁ¨Õ€lZ=xÁ¤Õ€,Z=xÁ Õƒ€ìYÝ_^èƒÌYÝ_àkV÷xÁ˜Õ%À€ò]ž¯m† ¦,2> |Á’Eº² ­ @?çùv3Ö„ÁŠuaG0b]@ØlXvÖ„Á‚u`G0`]ØìWvóÕ„ÁzE¨¢zÎ5~†¸×ÑûïÏ¡|^ÿ=XŸs÷×á :i¿µÏóŸCùsžÿNϬV=~ÁhÕƒàlV=~ÁdÕƒà,V=~Á`ÕƒàìU=~Á\Õƒà¬U]~ÁXÕ…àlU]~ÁTÕ…à,U]~ÁPÕ…àìT]~ÁLÕ…à¬Tü‚‘ê‚_°Q]@ð &ª ~ÁBuÁ/¨. øûÔ¿`žº`ðç¶NQ‘¢id‚qŠ2å_A¦ý%Éw´‚iêê@°L]@†© °Á.E S&º\‚òãЉÞ>·°‹^€›(gÔ;àÖÊÙt¥›Ѓ R=ÁÕƒÌQ=ÁÕƒŒQ=ÁÕ…LQ]ÁÕ… Q]ÁÕ…ÌP]Á u ¡. Ô€`‚º,P‚ê‚ ÛŸÞ¼íþrúæç|¨ð¯6Y,(_rÇ‚ ÞXŸgO´¹¦øbAù’+TñÀú<[ë_õÃÒEÙ KWke/,5rÂÒ VöÁÒò,])–=°´1X:ÍÉþWZ¾â~¥å+ÞWÚç+ldß+-_q½ÒòÏ+m €ã•®©«~W¶5·+ý{ê^Wú¼“®ô6dŸ+ý{É.W:.e+½¾êp¥µ ù[imèîVPÅÛJïGs¶‚Š(¾V>uW+T5O+ 뺣•NlšŸ•Î37+½àe¥u9Yé…+}^C.V=¬ô|ÙÁJÏ—ý«€%è^­ÈPÒ=-9Wë9^;ÍÅ~BË1ѳJÏ—«ô|Ù¯ XŠnUÐj%ÝÙ’S¸äµÓ,P¼êQ¥çËUz¾ìO,%%w*(_ô¦‚Ô”ŒO_ñ¥•^;ÍÅ~BºŽèH¥çË~Tz¾ìF¬S%/*(_t¢‚t)”ŒO_q¡51^;Í…!ì¨þSz¾ì>éY¢÷”ž/;Oéù²ï¤§‰®S@û’çоä8éy¢ß”ž/»MAjšè5¥çËNSz¾ì3©y¢Ëоä1´/9LAj¢è/¥çËîR–'zKéù²³”ž/ûJAZ¢è*´/yJíKŽR–)úIéù²›¤$Š^Rz¾ì$¥çË>R’)ºHíKR@û’ƒTAÿ(ˆ)‹îQ Ó½£ ®,:GA|Môùžè16Ñ3 Z.‰ŽQЊDô‹W,¢[ÄE¯(ˆ³‰NQg}¢ %è­*D(pÕ!:DA¬Mô‡‚X“è±ÑJ×ndg( _ò…‚ò%W(ˆ7‰žPo¡ Þ úAéê›ìäK^PP¾ä1Ñ b¢ ”zgãÒy[*6öØ6~óH€ÖnÊkMŸ¡q­ˆøžLÚ âé!÷—"æRzä–ñ´ RÎ…ÉÁTWTÙÓšx‰éŒK›ÎÇ^êtÆ¥NgœÊqSQQ„ø.KÚèMLÛLKÆy(PÙ­YJa¢©X!ã½,±γ֥Ö.¨ó”¬h$tCGIé×€JÐOw¡ò½t‡ÔzÙ@qòŸL…ÅÐäeF“…öƒòÇšÑdá†çùðšÑX>ÀÓ)|è7Ê™Øäëç§Þ Ú(Þ"Ñ:µÆœ¥¹KøÒÜÇ]é}$˜±SöÓEI–^i÷6]˲—'¼Ç$Tò¢¢Xç©’¥Š¯a/æ¾ËèÕRÆä3Nä’29›¶“3yÇ›CÒälÚNÖX.;icÍ`ySlºgQ7(!–´ŸÁbǶQU*x&ÉS !)ý¤Ï’ýHÈÞ&•.‰ÒÔëìwi–!{ù·²‚A\kÀ¯ìëTQ³Â~ îq¹¾,ÅŠ½1—HÉѬ{¶ÙŠ5ç9‡TÊr®qFAúú.$>òNáT1ôoÊìÃÀl´ûAS÷—2xJ:53Ð’*”Ã(™Ï†¼&ñƒ7AüàÊÅ^“øÁŠ\¶øÁ«?¸<ñƒË?x5â—&~pâW!~°Aü¨Ê€ý¨+?Ø l 4e¥ å“@¢Sí²{>“†™RDæ ¶]ÒFRÑü/åŽ!«;§äþò‚]峬b#ÊÚJYmoÖöiÛi_‰yÔfîW3 (×HkGU_€–³ð †Üæ¶–m†8p7@„ƒ®y ÕŠ¤ð2ÏêºÛ ]Õ¹æAT*†Ý*Ű•dƒÄ1ÞqŒ­P5©z]€­8Q¹]nÌRÛ±¤*FRõ¢W²(J»w4ú‹¯8¤\kÝ—?þ-¾ÿsx; L5ˆ.Ûûn)}¤ßÿÙrŽœV|ÿçAÇ9F­öqËiÕ÷V‘žÄ—Fß|ßîäŒïÖ ÞhFoÖ”^G—Ò»G¬‘ýëG;;ô~ÇÉ`4E ´»ó%Fí6ä½ ù™’Å/7¦æ§`ðŒ õ˜ÖM´wKþÝ=ÞF×Ó»†ÙkÖuM›ìcòèÞ²ÿß‘ÿ‡Í±žÑ êÒávgã׃?fáHÂNã¬73vÃrXiBÞÕjÏþÔª¸¬%^‹ <©÷j8ðˆª…¼Ñd8e+Ráí¡‚à…?ºE£€>? awoIÍv„÷.y`XJž(²ÈC+þLŽ™íNãñÌmd¼³«èõîÞdo2Õ[‹ÂQÑ;û¢Ð÷%Ãñ@¹(ŒEW#Ÿ°Þ=ˆƒß[ÿåPýÞ¦NôàЇNôÐù/ÃaJëÁ°vOm~"6?ù±-?:òc‡?:Y\|½=i¨ä1ì‡|rÄ_±2‡BÖÛQ*Âf7þâZï®#7Õ »;^°ÎŽ…¬Êÿh-¦¬³[v£ïé‚ øVü*·âW¹ýÝs„Ý…uZÑC[|pć ÿBVºƒ†´ÜŒ·~Ä ¸¹|ù]ÈP2ßù”‡ÜE軚ù 4b# þ‰¦äÏ?ZšÓÒWGèî)õ«ÿL‘›dà£ÿ†m^ùÃac ü¾~ß…¿ýáâÆŸRÔ|«|I&ÿjäÿÁaËÑå¿SËÿ*’*ÿ¥Ê«ðp².ˆC?œ½ùßÓWg=ôS[\+Ð_ÿ³ÛŒîªÞ#_ãÍôg7‹“ŸÚÍÑôjvÒjNšÓæ—&¥ñ±wIþ¹âºà4d"µö[Mòï[ ”ÿ<-³›–yúêÝ/§'4 =ñžýz&d³‘^¡ý 9»E™tè¤ÑÁb6¢™_ ¿Û+Rp¤<'Êû¶#4¶@¸ç.Š¥¯.NZü¥À“º×C÷ ]=‚œmNÐÕ`4&l|Šæ@x:Y†¶µ+@"o„Ë!²ra+¥& ŸÙâ¨)-•šñ‡m¢ýOãµ1›ˆü×&( ÿOIb÷®ÇCø¦Ø^ÄÃÜ &`‰·$(KÑYÄÿ»$ˆÉû|ÈÉ ž“^gYðÚíásŠÀ§~¾odU d²iAÚQœDsîšž•Èú?ÂùNÚôÏeøÇ=i Uø¦$zôž,I½!ÿ{LVHÉéñôÇöÇlíôœý¸$ÿOP@ž]{:ÐNùè-žY*ï!§@3ð+€<›|SÁøí›;é_ÛIƒùÍ#T ÐÙD t»¥AÝJ vòÌñUCýMhkÝ+ör“²þ=øBViã´…pþ”±þovÚÊúÿð Ó©×ÿU$oüuLÖŸûOöwâuû÷ úr÷Éþ~2öGÓÁxüÅ¦áø‡³³¿zŠvþþ}£ÛÝE?¹¤‘îËW§?÷ÉÃi(ð]¤Ú–iéWoO{/ÎI¡Y’ÝV ÎhcÏ_=ß%?ž¿¢?’N\:ÆNµ Ô)%~w<L)&vþîOÐOWhoº³ål¡NuªSêT§:Õ©NuªSêT§:Õ©NuªSêT§:Õ©N[šþ?™6È;¸blis-0.9.0/frame/compat/cblas/f77_sub/000077500000000000000000000000001422157504600173745ustar00rootroot00000000000000blis-0.9.0/frame/compat/cblas/f77_sub/f77_amax_sub.c000066400000000000000000000041451422157504600220260ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "f77_amax_sub.h" // // Define CBLAS subrotine wrapper interfaces. // #undef GENTFUNC #define GENTFUNC( ftype_x, chx, blasname, blisname ) \ \ void PASTEF773(i,chx,blasname,sub) \ ( \ const f77_int* n, \ const ftype_x* x, const f77_int* incx, \ f77_int* rval \ ) \ { \ *rval = PASTEF772(i,chx,blasname) \ ( \ n, \ x, incx \ ); \ } #ifdef BLIS_ENABLE_CBLAS INSERT_GENTFUNC_BLAS( amax, NULL ) #endif blis-0.9.0/frame/compat/cblas/f77_sub/f77_amax_sub.h000066400000000000000000000037601422157504600220350ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype CBLAS subroutine wrapper interfaces. // #undef GENTPROT #define GENTPROT( ftype_x, chx, blasname ) \ \ BLIS_EXPORT_BLAS void PASTEF773(i,chx,blasname,sub) \ ( \ const f77_int* n, \ const ftype_x* x, const f77_int* incx, \ f77_int* rval \ ); #ifdef BLIS_ENABLE_CBLAS INSERT_GENTPROT_BLAS( amax ) #endif blis-0.9.0/frame/compat/cblas/f77_sub/f77_asum_sub.c000066400000000000000000000041751422157504600220500ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "f77_asum_sub.h" // // Define CBLAS subrotine wrapper interfaces. // #undef GENTFUNCR2 #define GENTFUNCR2( ftype_x, ftype_r, chx, chr, blasname, blisname ) \ \ void PASTEF773(chr,chx,blasname,sub) \ ( \ const f77_int* n, \ const ftype_x* x, const f77_int* incx, \ ftype_r* rval \ ) \ { \ *rval = PASTEF772(chr,chx,blasname) \ ( \ n, \ x, incx \ ); \ } #ifdef BLIS_ENABLE_CBLAS INSERT_GENTFUNCR2_BLAS( asum, NULL ) #endif blis-0.9.0/frame/compat/cblas/f77_sub/f77_asum_sub.h000066400000000000000000000040061422157504600220460ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype CBLAS subroutine wrapper interfaces. // #undef GENTPROTR2 #define GENTPROTR2( ftype_x, ftype_r, chx, chr, blasname ) \ \ BLIS_EXPORT_BLAS void PASTEF773(chr,chx,blasname,sub) \ ( \ const f77_int* n, \ const ftype_x* x, const f77_int* incx, \ ftype_r* rval \ ); #ifdef BLIS_ENABLE_CBLAS INSERT_GENTPROTR2_BLAS( asum ) #endif blis-0.9.0/frame/compat/cblas/f77_sub/f77_dot_sub.c000066400000000000000000000072601422157504600216670ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "f77_dot_sub.h" #ifdef BLIS_ENABLE_CBLAS // // Define CBLAS subrotine wrapper interfaces. // #undef GENTFUNCDOT #define GENTFUNCDOT( ftype, ch, chc, blis_conjx, blasname, blisname ) \ \ void PASTEF773(ch,blasname,chc,sub) \ ( \ const f77_int* n, \ const ftype* x, const f77_int* incx, \ const ftype* y, const f77_int* incy, \ ftype* rval \ ) \ { \ *rval = PASTEF772(ch,blasname,chc) \ ( \ n, \ x, incx, \ y, incy \ ); \ } INSERT_GENTFUNCDOTR_BLAS( dot, NULL ) #ifdef BLIS_DISABLE_COMPLEX_RETURN_INTEL INSERT_GENTFUNCDOTC_BLAS( dot, NULL ) #else // // Define CBLAS subrotine wrapper interfaces for complex types. // For the "intel" complex return type, pass a hidden first parameter // (by address). // #undef GENTFUNCDOT #define GENTFUNCDOT( ftype, ch, chc, blis_conjx, blasname, blisname ) \ \ void PASTEF773(ch,blasname,chc,sub) \ ( \ const f77_int* n, \ const ftype* x, const f77_int* incx, \ const ftype* y, const f77_int* incy, \ ftype* rval \ ) \ { \ PASTEF772(ch,blasname,chc) \ ( \ rval, \ n, \ x, incx, \ y, incy \ ); \ } INSERT_GENTFUNCDOTC_BLAS( dot, NULL ) #endif // -- "Black sheep" dot product function definitions -- // Input vectors stored in single precision, computed in double precision, // with result returned in single precision. void PASTEF772(sds,dot,sub) ( const f77_int* n, const float* sb, const float* x, const f77_int* incx, const float* y, const f77_int* incy, float* rval ) { *rval = PASTEF77(sds,dot) ( n, sb, x, incx, y, incy ); } // Input vectors stored in single precision, computed in double precision, // with result returned in double precision. void PASTEF772(ds,dot,sub) ( const f77_int* n, const float* x, const f77_int* incx, const float* y, const f77_int* incy, double* rval ) { *rval = PASTEF77(ds,dot) ( n, x, incx, y, incy ); } #endif blis-0.9.0/frame/compat/cblas/f77_sub/f77_dot_sub.h000066400000000000000000000050261422157504600216720ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype CBLAS subroutine wrapper interfaces. // #undef GENTPROTDOT #define GENTPROTDOT( ftype, ch, chc, blasname ) \ \ BLIS_EXPORT_BLAS void PASTEF773(ch,blasname,chc,sub) \ ( \ const f77_int* n, \ const ftype* x, const f77_int* incx, \ const ftype* y, const f77_int* incy, \ ftype* rval \ ); #ifdef BLIS_ENABLE_CBLAS INSERT_GENTPROTDOT_BLAS( dot ) // -- "Black sheep" dot product function prototypes -- BLIS_EXPORT_BLAS void PASTEF772(sds,dot,sub) ( const f77_int* n, const float* sb, const float* x, const f77_int* incx, const float* y, const f77_int* incy, float* rval ); BLIS_EXPORT_BLAS void PASTEF772(ds,dot,sub) ( const f77_int* n, const float* x, const f77_int* incx, const float* y, const f77_int* incy, double* rval ); #endif blis-0.9.0/frame/compat/cblas/f77_sub/f77_nrm2_sub.c000066400000000000000000000041751422157504600217610ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "f77_nrm2_sub.h" // // Define CBLAS subrotine wrapper interfaces. // #undef GENTFUNCR2 #define GENTFUNCR2( ftype_x, ftype_r, chx, chr, blasname, blisname ) \ \ void PASTEF773(chr,chx,blasname,sub) \ ( \ const f77_int* n, \ const ftype_x* x, const f77_int* incx, \ ftype_r* rval \ ) \ { \ *rval = PASTEF772(chr,chx,blasname) \ ( \ n, \ x, incx \ ); \ } #ifdef BLIS_ENABLE_CBLAS INSERT_GENTFUNCR2_BLAS( nrm2, NULL ) #endif blis-0.9.0/frame/compat/cblas/f77_sub/f77_nrm2_sub.h000066400000000000000000000040061422157504600217570ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype CBLAS subroutine wrapper interfaces. // #undef GENTPROTR2 #define GENTPROTR2( ftype_x, ftype_r, chx, chr, blasname ) \ \ BLIS_EXPORT_BLAS void PASTEF773(chr,chx,blasname,sub) \ ( \ const f77_int* n, \ const ftype_x* x, const f77_int* incx, \ ftype_r* rval \ ); #ifdef BLIS_ENABLE_CBLAS INSERT_GENTPROTR2_BLAS( nrm2 ) #endif blis-0.9.0/frame/compat/cblas/integrate-cblas-tarball.sh000077500000000000000000000204211422157504600231410ustar00rootroot00000000000000#!/bin/bash # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2014, The University of Texas at Austin # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # # # bump-version.sh # # Field G. Van Zee # print_usage() { #local script_name # Get the script name #script_name=${0##*/} # Echo usage info echo " " echo " "$script_name echo " " echo " Field G. Van Zee" echo " " echo " Unpacks a CBLAS tarball and performs whatever preprocessing is" echo " necessary and appropriate in order to integrate the CBLAS source" echo " code into BLIS." echo " " echo " IMPORTANT: This script is designed to be run from the following" echo " directory:" echo " " echo " frame/compat/cblas" echo " " echo " Usage:" echo " ${script_name} tarball" echo " " echo " Arguments:" echo " " echo " tarball The name of the CBLAS package that will be unpacked." echo " If tarball is not in the current directory, the full" echo " directory path should be given." echo " " # Exit with non-zero exit status exit 1 } main() { # -- BEGIN GLOBAL VARIABLE DECLARATIONS -- # The name of the script, stripped of any preceeding path. script_name=${0##*/} # The name and path of the CBLAS tarball. tarball_path= # The name of the CBLAS directory after it is unpacked. cblas_dir=CBLAS # The name of the sub-directory that we will create and into which # we will copy the source code for CBLAS wrappers. src_dir=src # -- END GLOBAL VARIABLE DECLARATIONS -- # Process our command line options. while getopts ":h" opt; do case $opt in h ) print_usage ;; \? ) print_usage esac done shift $(($OPTIND - 1)) # Check the number of arguments after command line option processing. if [ $# = "1" ]; then tarball_path=$1 echo "${script_name}: preparing to extract from '${tarball_path}'." else print_usage fi # Check that src_dir does not already exist. If it does, abort. if [ -d ${src_dir} ] ; then echo "${script_name}: found '${src_dir}' directory; please remove before proceeding." return 0 fi # Un-tar and un-gzip the tarball. echo "${script_name}: extracting '${tarball_path}'." echo "${script_name}: expecting unpacked directory to be named '${cblas_dir}'." tar xzf ${tarball_path} # Create the directory into which we will copy the source code for the # CBLAS wrappers. echo "${script_name}: creating local '${src_dir}' directory." mkdir -p ${src_dir} # Copy the cblas.h header file. echo "${script_name}: copying cblas.h from '${cblas_dir}/include' to '${src_dir}'." cp ${cblas_dir}/include/cblas.h ${src_dir}/cblas.h # Copy the cblas_f77.h header file, removing all prototypes. echo "${script_name}: copying cblas_f77.h from '${cblas_dir}/include' to '${src_dir}'" cp ${cblas_dir}/include/cblas_f77.h ${src_dir}/cblas_f77.h # Create some temporary files to facilitate #including BLIS-specific # cpp macros. echo "${script_name}: creating temporary files." echo "#include \"bli_config.h\"" > include_bli_config.h echo "#include \"bli_system.h\"" > include_bli_system.h echo "#include \"bli_type_defs.h\"" > include_bli_type_defs.h echo "#include \"bli_cblas.h\"" > include_bli_cblas.h echo "#ifdef BLIS_ENABLE_CBLAS" > ifdef_cblas.h echo "#endif" > endif_cblas.h # Process each CBLAS source file. echo "${script_name}: copying source from '${cblas_dir}/src' to '${src_dir}' with" echo "${script_name}: '#ifdef BLIS_ENABLE_CBLAS' guard:" for cbl_src_filepath in ${cblas_dir}/src/cblas_*.c; do # Strip the path to obtain just the filename. cbl_src_file=${cbl_src_filepath##*/} # Append the ifdef and prepend the endif macro statements to the # current file and output to its new location in ${src_dir}. echo "${script_name}: ...copying/BLIS-ifying ${cbl_src_file}" cat include_bli_config.h \ include_bli_system.h \ include_bli_type_defs.h \ include_bli_cblas.h \ ifdef_cblas.h \ ${cbl_src_filepath} \ endif_cblas.h > ${src_dir}/${cbl_src_file} done # Remove the temporary files. echo "${script_name}: cleaning up temporary files." rm -f include_bli_config.h rm -f include_bli_system.h rm -f include_bli_type_defs.h rm -f include_bli_cblas.h rm -f ifdef_cblas.h rm -f endif_cblas.h # Process some bugfixes to syntax errors present in the CBLAS source. echo "${script_name}: fixing syntax errors in CBLAS source:" fix_file ${src_dir}/cblas_chpmv.c "s/ F77_K=K,//g" fix_file ${src_dir}/cblas_chpmv.c "s/ F77_lda=lda,//g" fix_file ${src_dir}/cblas_zhpmv.c "s/ F77_K=K,//g" fix_file ${src_dir}/cblas_zhpmv.c "s/ F77_lda=lda,//g" fix_file ${src_dir}/cblas_ssyr2.c "s/F77__lda/F77_lda/g" fix_file ${src_dir}/cblas_dsyr2.c "s/F77__lda/F77_lda/g" fix_file ${src_dir}/cblas_strsm.c "s/F77_N=M/F77_M=M/g" # Now process some optional fixes that eliminate compiler warnings. echo "${script_name}: fixing compiler warnings in CBLAS source:" incx_string="s/, incx=incX//g" incy_string="s/, incy=incY//g" fix_file ${src_dir}/cblas_cgbmv.c "${incx_string}" fix_file ${src_dir}/cblas_cgemv.c "${incx_string}" fix_file ${src_dir}/cblas_cgerc.c "${incy_string}" fix_file ${src_dir}/cblas_chbmv.c "${incx_string}" fix_file ${src_dir}/cblas_chemv.c "${incx_string}" fix_file ${src_dir}/cblas_cher.c "${incx_string}" fix_file ${src_dir}/cblas_cher2.c "${incx_string}" fix_file ${src_dir}/cblas_cher2.c "${incy_string}" fix_file ${src_dir}/cblas_chpmv.c "${incx_string}" fix_file ${src_dir}/cblas_chpr.c "${incx_string}" fix_file ${src_dir}/cblas_chpr2.c "${incx_string}" fix_file ${src_dir}/cblas_chpr2.c "${incy_string}" fix_file ${src_dir}/cblas_zgbmv.c "${incx_string}" fix_file ${src_dir}/cblas_zgemv.c "${incx_string}" fix_file ${src_dir}/cblas_zgerc.c "${incy_string}" fix_file ${src_dir}/cblas_zhbmv.c "${incx_string}" fix_file ${src_dir}/cblas_zhemv.c "${incx_string}" fix_file ${src_dir}/cblas_zher.c "${incx_string}" fix_file ${src_dir}/cblas_zher2.c "${incx_string}" fix_file ${src_dir}/cblas_zher2.c "${incy_string}" fix_file ${src_dir}/cblas_zhpmv.c "${incx_string}" fix_file ${src_dir}/cblas_zhpr.c "${incx_string}" fix_file ${src_dir}/cblas_zhpr2.c "${incx_string}" fix_file ${src_dir}/cblas_zhpr2.c "${incy_string}" # Now that we're done with everything, we can remove the CBLAS directory. echo "${script_name}: removing '${cblas_dir}' directory." rm -rf ${cblas_dir} # Exit peacefully. return 0 } fix_file() { # Get the first function argument: the filename and path to fix. local filepath="$1" # Get the second function argument: the sed command to apply. local sedstring="$2" filename=${filepath##*/} echo "${script_name}: ...fixing ${filename} with 'sed -e ${sedstring}'" cat ${filepath} | sed -e "${sedstring}" > ${filepath}.new mv ${filepath}.new ${filepath} } # The script's main entry point, passing all parameters given. main "$@" blis-0.9.0/frame/compat/cblas/src/000077500000000000000000000000001422157504600167075ustar00rootroot00000000000000blis-0.9.0/frame/compat/cblas/src/cblas.h000066400000000000000000001103551422157504600201510ustar00rootroot00000000000000 #ifndef CBLAS_H #define CBLAS_H #include // We need to #include "bli_type_defs.h" in order to pull in the // definition of f77_int. But in order to #include that header, we // also need to pull in the headers that precede it in blis.h. #include "bli_system.h" #include "bli_config.h" #include "bli_config_macro_defs.h" #include "bli_type_defs.h" /* * Enumerated and derived types */ enum CBLAS_ORDER {CblasRowMajor=101, CblasColMajor=102}; enum CBLAS_TRANSPOSE {CblasNoTrans=111, CblasTrans=112, CblasConjTrans=113}; enum CBLAS_UPLO {CblasUpper=121, CblasLower=122}; enum CBLAS_DIAG {CblasNonUnit=131, CblasUnit=132}; enum CBLAS_SIDE {CblasLeft=141, CblasRight=142}; #ifdef __cplusplus extern "C" { #endif /* * =========================================================================== * Prototypes for level 1 BLAS functions (complex are recast as routines) * =========================================================================== */ BLIS_EXPORT_BLAS float cblas_sdsdot(f77_int N, float alpha, const float *X, f77_int incX, const float *Y, f77_int incY); BLIS_EXPORT_BLAS double cblas_dsdot(f77_int N, const float *X, f77_int incX, const float *Y, f77_int incY); BLIS_EXPORT_BLAS float cblas_sdot(f77_int N, const float *X, f77_int incX, const float *Y, f77_int incY); BLIS_EXPORT_BLAS double cblas_ddot(f77_int N, const double *X, f77_int incX, const double *Y, f77_int incY); /* * Functions having prefixes Z and C only */ BLIS_EXPORT_BLAS void cblas_cdotu_sub(f77_int N, const void *X, f77_int incX, const void *Y, f77_int incY, void *dotu); BLIS_EXPORT_BLAS void cblas_cdotc_sub(f77_int N, const void *X, f77_int incX, const void *Y, f77_int incY, void *dotc); BLIS_EXPORT_BLAS void cblas_zdotu_sub(f77_int N, const void *X, f77_int incX, const void *Y, f77_int incY, void *dotu); BLIS_EXPORT_BLAS void cblas_zdotc_sub(f77_int N, const void *X, f77_int incX, const void *Y, f77_int incY, void *dotc); /* * Functions having prefixes S D SC DZ */ BLIS_EXPORT_BLAS float cblas_snrm2(f77_int N, const float *X, f77_int incX); BLIS_EXPORT_BLAS float cblas_sasum(f77_int N, const float *X, f77_int incX); BLIS_EXPORT_BLAS double cblas_dnrm2(f77_int N, const double *X, f77_int incX); BLIS_EXPORT_BLAS double cblas_dasum(f77_int N, const double *X, f77_int incX); BLIS_EXPORT_BLAS float cblas_scnrm2(f77_int N, const void *X, f77_int incX); BLIS_EXPORT_BLAS float cblas_scasum(f77_int N, const void *X, f77_int incX); BLIS_EXPORT_BLAS double cblas_dznrm2(f77_int N, const void *X, f77_int incX); BLIS_EXPORT_BLAS double cblas_dzasum(f77_int N, const void *X, f77_int incX); /* * Functions having standard 4 prefixes (S D C Z) */ BLIS_EXPORT_BLAS f77_int cblas_isamax(f77_int N, const float *X, f77_int incX); BLIS_EXPORT_BLAS f77_int cblas_idamax(f77_int N, const double *X, f77_int incX); BLIS_EXPORT_BLAS f77_int cblas_icamax(f77_int N, const void *X, f77_int incX); BLIS_EXPORT_BLAS f77_int cblas_izamax(f77_int N, const void *X, f77_int incX); /* * =========================================================================== * Prototypes for level 1 BLAS routines * =========================================================================== */ /* * Routines with standard 4 prefixes (s, d, c, z) */ void BLIS_EXPORT_BLAS cblas_sswap(f77_int N, float *X, f77_int incX, float *Y, f77_int incY); void BLIS_EXPORT_BLAS cblas_scopy(f77_int N, const float *X, f77_int incX, float *Y, f77_int incY); void BLIS_EXPORT_BLAS cblas_saxpy(f77_int N, float alpha, const float *X, f77_int incX, float *Y, f77_int incY); void BLIS_EXPORT_BLAS cblas_dswap(f77_int N, double *X, f77_int incX, double *Y, f77_int incY); void BLIS_EXPORT_BLAS cblas_dcopy(f77_int N, const double *X, f77_int incX, double *Y, f77_int incY); void BLIS_EXPORT_BLAS cblas_daxpy(f77_int N, double alpha, const double *X, f77_int incX, double *Y, f77_int incY); void BLIS_EXPORT_BLAS cblas_cswap(f77_int N, void *X, f77_int incX, void *Y, f77_int incY); void BLIS_EXPORT_BLAS cblas_ccopy(f77_int N, const void *X, f77_int incX, void *Y, f77_int incY); void BLIS_EXPORT_BLAS cblas_caxpy(f77_int N, const void *alpha, const void *X, f77_int incX, void *Y, f77_int incY); void BLIS_EXPORT_BLAS cblas_zswap(f77_int N, void *X, f77_int incX, void *Y, f77_int incY); void BLIS_EXPORT_BLAS cblas_zcopy(f77_int N, const void *X, f77_int incX, void *Y, f77_int incY); void BLIS_EXPORT_BLAS cblas_zaxpy(f77_int N, const void *alpha, const void *X, f77_int incX, void *Y, f77_int incY); /* * Routines with S and D prefix only */ void BLIS_EXPORT_BLAS cblas_srotg(float *a, float *b, float *c, float *s); void BLIS_EXPORT_BLAS cblas_srotmg(float *d1, float *d2, float *b1, const float b2, float *P); void BLIS_EXPORT_BLAS cblas_srot(f77_int N, float *X, f77_int incX, float *Y, f77_int incY, const float c, const float s); void BLIS_EXPORT_BLAS cblas_srotm(f77_int N, float *X, f77_int incX, float *Y, f77_int incY, const float *P); void BLIS_EXPORT_BLAS cblas_drotg(double *a, double *b, double *c, double *s); void BLIS_EXPORT_BLAS cblas_drotmg(double *d1, double *d2, double *b1, const double b2, double *P); void BLIS_EXPORT_BLAS cblas_drot(f77_int N, double *X, f77_int incX, double *Y, f77_int incY, const double c, const double s); void BLIS_EXPORT_BLAS cblas_drotm(f77_int N, double *X, f77_int incX, double *Y, f77_int incY, const double *P); /* * Routines with S D C Z CS and ZD prefixes */ void BLIS_EXPORT_BLAS cblas_sscal(f77_int N, float alpha, float *X, f77_int incX); void BLIS_EXPORT_BLAS cblas_dscal(f77_int N, double alpha, double *X, f77_int incX); void BLIS_EXPORT_BLAS cblas_cscal(f77_int N, const void *alpha, void *X, f77_int incX); void BLIS_EXPORT_BLAS cblas_zscal(f77_int N, const void *alpha, void *X, f77_int incX); void BLIS_EXPORT_BLAS cblas_csscal(f77_int N, float alpha, void *X, f77_int incX); void BLIS_EXPORT_BLAS cblas_zdscal(f77_int N, double alpha, void *X, f77_int incX); /* * =========================================================================== * Prototypes for level 2 BLAS * =========================================================================== */ /* * Routines with standard 4 prefixes (S, D, C, Z) */ void BLIS_EXPORT_BLAS cblas_sgemv(enum CBLAS_ORDER order, enum CBLAS_TRANSPOSE TransA, f77_int M, f77_int N, float alpha, const float *A, f77_int lda, const float *X, f77_int incX, float beta, float *Y, f77_int incY); void BLIS_EXPORT_BLAS cblas_sgbmv(enum CBLAS_ORDER order, enum CBLAS_TRANSPOSE TransA, f77_int M, f77_int N, f77_int KL, f77_int KU, float alpha, const float *A, f77_int lda, const float *X, f77_int incX, float beta, float *Y, f77_int incY); void BLIS_EXPORT_BLAS cblas_strmv(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE TransA, enum CBLAS_DIAG Diag, f77_int N, const float *A, f77_int lda, float *X, f77_int incX); void BLIS_EXPORT_BLAS cblas_stbmv(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE TransA, enum CBLAS_DIAG Diag, f77_int N, f77_int K, const float *A, f77_int lda, float *X, f77_int incX); void BLIS_EXPORT_BLAS cblas_stpmv(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE TransA, enum CBLAS_DIAG Diag, f77_int N, const float *Ap, float *X, f77_int incX); void BLIS_EXPORT_BLAS cblas_strsv(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE TransA, enum CBLAS_DIAG Diag, f77_int N, const float *A, f77_int lda, float *X, f77_int incX); void BLIS_EXPORT_BLAS cblas_stbsv(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE TransA, enum CBLAS_DIAG Diag, f77_int N, f77_int K, const float *A, f77_int lda, float *X, f77_int incX); void BLIS_EXPORT_BLAS cblas_stpsv(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE TransA, enum CBLAS_DIAG Diag, f77_int N, const float *Ap, float *X, f77_int incX); void BLIS_EXPORT_BLAS cblas_dgemv(enum CBLAS_ORDER order, enum CBLAS_TRANSPOSE TransA, f77_int M, f77_int N, double alpha, const double *A, f77_int lda, const double *X, f77_int incX, double beta, double *Y, f77_int incY); void BLIS_EXPORT_BLAS cblas_dgbmv(enum CBLAS_ORDER order, enum CBLAS_TRANSPOSE TransA, f77_int M, f77_int N, f77_int KL, f77_int KU, double alpha, const double *A, f77_int lda, const double *X, f77_int incX, double beta, double *Y, f77_int incY); void BLIS_EXPORT_BLAS cblas_dtrmv(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE TransA, enum CBLAS_DIAG Diag, f77_int N, const double *A, f77_int lda, double *X, f77_int incX); void BLIS_EXPORT_BLAS cblas_dtbmv(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE TransA, enum CBLAS_DIAG Diag, f77_int N, f77_int K, const double *A, f77_int lda, double *X, f77_int incX); void BLIS_EXPORT_BLAS cblas_dtpmv(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE TransA, enum CBLAS_DIAG Diag, f77_int N, const double *Ap, double *X, f77_int incX); void BLIS_EXPORT_BLAS cblas_dtrsv(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE TransA, enum CBLAS_DIAG Diag, f77_int N, const double *A, f77_int lda, double *X, f77_int incX); void BLIS_EXPORT_BLAS cblas_dtbsv(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE TransA, enum CBLAS_DIAG Diag, f77_int N, f77_int K, const double *A, f77_int lda, double *X, f77_int incX); void BLIS_EXPORT_BLAS cblas_dtpsv(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE TransA, enum CBLAS_DIAG Diag, f77_int N, const double *Ap, double *X, f77_int incX); void BLIS_EXPORT_BLAS cblas_cgemv(enum CBLAS_ORDER order, enum CBLAS_TRANSPOSE TransA, f77_int M, f77_int N, const void *alpha, const void *A, f77_int lda, const void *X, f77_int incX, const void *beta, void *Y, f77_int incY); void BLIS_EXPORT_BLAS cblas_cgbmv(enum CBLAS_ORDER order, enum CBLAS_TRANSPOSE TransA, f77_int M, f77_int N, f77_int KL, f77_int KU, const void *alpha, const void *A, f77_int lda, const void *X, f77_int incX, const void *beta, void *Y, f77_int incY); void BLIS_EXPORT_BLAS cblas_ctrmv(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE TransA, enum CBLAS_DIAG Diag, f77_int N, const void *A, f77_int lda, void *X, f77_int incX); void BLIS_EXPORT_BLAS cblas_ctbmv(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE TransA, enum CBLAS_DIAG Diag, f77_int N, f77_int K, const void *A, f77_int lda, void *X, f77_int incX); void BLIS_EXPORT_BLAS cblas_ctpmv(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE TransA, enum CBLAS_DIAG Diag, f77_int N, const void *Ap, void *X, f77_int incX); void BLIS_EXPORT_BLAS cblas_ctrsv(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE TransA, enum CBLAS_DIAG Diag, f77_int N, const void *A, f77_int lda, void *X, f77_int incX); void BLIS_EXPORT_BLAS cblas_ctbsv(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE TransA, enum CBLAS_DIAG Diag, f77_int N, f77_int K, const void *A, f77_int lda, void *X, f77_int incX); void BLIS_EXPORT_BLAS cblas_ctpsv(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE TransA, enum CBLAS_DIAG Diag, f77_int N, const void *Ap, void *X, f77_int incX); void BLIS_EXPORT_BLAS cblas_zgemv(enum CBLAS_ORDER order, enum CBLAS_TRANSPOSE TransA, f77_int M, f77_int N, const void *alpha, const void *A, f77_int lda, const void *X, f77_int incX, const void *beta, void *Y, f77_int incY); void BLIS_EXPORT_BLAS cblas_zgbmv(enum CBLAS_ORDER order, enum CBLAS_TRANSPOSE TransA, f77_int M, f77_int N, f77_int KL, f77_int KU, const void *alpha, const void *A, f77_int lda, const void *X, f77_int incX, const void *beta, void *Y, f77_int incY); void BLIS_EXPORT_BLAS cblas_ztrmv(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE TransA, enum CBLAS_DIAG Diag, f77_int N, const void *A, f77_int lda, void *X, f77_int incX); void BLIS_EXPORT_BLAS cblas_ztbmv(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE TransA, enum CBLAS_DIAG Diag, f77_int N, f77_int K, const void *A, f77_int lda, void *X, f77_int incX); void BLIS_EXPORT_BLAS cblas_ztpmv(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE TransA, enum CBLAS_DIAG Diag, f77_int N, const void *Ap, void *X, f77_int incX); void BLIS_EXPORT_BLAS cblas_ztrsv(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE TransA, enum CBLAS_DIAG Diag, f77_int N, const void *A, f77_int lda, void *X, f77_int incX); void BLIS_EXPORT_BLAS cblas_ztbsv(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE TransA, enum CBLAS_DIAG Diag, f77_int N, f77_int K, const void *A, f77_int lda, void *X, f77_int incX); void BLIS_EXPORT_BLAS cblas_ztpsv(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE TransA, enum CBLAS_DIAG Diag, f77_int N, const void *Ap, void *X, f77_int incX); /* * Routines with S and D prefixes only */ void BLIS_EXPORT_BLAS cblas_ssymv(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, f77_int N, float alpha, const float *A, f77_int lda, const float *X, f77_int incX, float beta, float *Y, f77_int incY); void BLIS_EXPORT_BLAS cblas_ssbmv(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, f77_int N, f77_int K, float alpha, const float *A, f77_int lda, const float *X, f77_int incX, float beta, float *Y, f77_int incY); void BLIS_EXPORT_BLAS cblas_sspmv(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, f77_int N, float alpha, const float *Ap, const float *X, f77_int incX, float beta, float *Y, f77_int incY); void BLIS_EXPORT_BLAS cblas_sger(enum CBLAS_ORDER order, f77_int M, f77_int N, float alpha, const float *X, f77_int incX, const float *Y, f77_int incY, float *A, f77_int lda); void BLIS_EXPORT_BLAS cblas_ssyr(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, f77_int N, float alpha, const float *X, f77_int incX, float *A, f77_int lda); void BLIS_EXPORT_BLAS cblas_sspr(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, f77_int N, float alpha, const float *X, f77_int incX, float *Ap); void BLIS_EXPORT_BLAS cblas_ssyr2(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, f77_int N, float alpha, const float *X, f77_int incX, const float *Y, f77_int incY, float *A, f77_int lda); void BLIS_EXPORT_BLAS cblas_sspr2(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, f77_int N, float alpha, const float *X, f77_int incX, const float *Y, f77_int incY, float *A); void BLIS_EXPORT_BLAS cblas_dsymv(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, f77_int N, double alpha, const double *A, f77_int lda, const double *X, f77_int incX, double beta, double *Y, f77_int incY); void BLIS_EXPORT_BLAS cblas_dsbmv(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, f77_int N, f77_int K, double alpha, const double *A, f77_int lda, const double *X, f77_int incX, double beta, double *Y, f77_int incY); void BLIS_EXPORT_BLAS cblas_dspmv(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, f77_int N, double alpha, const double *Ap, const double *X, f77_int incX, double beta, double *Y, f77_int incY); void BLIS_EXPORT_BLAS cblas_dger(enum CBLAS_ORDER order, f77_int M, f77_int N, double alpha, const double *X, f77_int incX, const double *Y, f77_int incY, double *A, f77_int lda); void BLIS_EXPORT_BLAS cblas_dsyr(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, f77_int N, double alpha, const double *X, f77_int incX, double *A, f77_int lda); void BLIS_EXPORT_BLAS cblas_dspr(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, f77_int N, double alpha, const double *X, f77_int incX, double *Ap); void BLIS_EXPORT_BLAS cblas_dsyr2(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, f77_int N, double alpha, const double *X, f77_int incX, const double *Y, f77_int incY, double *A, f77_int lda); void BLIS_EXPORT_BLAS cblas_dspr2(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, f77_int N, double alpha, const double *X, f77_int incX, const double *Y, f77_int incY, double *A); /* * Routines with C and Z prefixes only */ void BLIS_EXPORT_BLAS cblas_chemv(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, f77_int N, const void *alpha, const void *A, f77_int lda, const void *X, f77_int incX, const void *beta, void *Y, f77_int incY); void BLIS_EXPORT_BLAS cblas_chbmv(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, f77_int N, f77_int K, const void *alpha, const void *A, f77_int lda, const void *X, f77_int incX, const void *beta, void *Y, f77_int incY); void BLIS_EXPORT_BLAS cblas_chpmv(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, f77_int N, const void *alpha, const void *Ap, const void *X, f77_int incX, const void *beta, void *Y, f77_int incY); void BLIS_EXPORT_BLAS cblas_cgeru(enum CBLAS_ORDER order, f77_int M, f77_int N, const void *alpha, const void *X, f77_int incX, const void *Y, f77_int incY, void *A, f77_int lda); void BLIS_EXPORT_BLAS cblas_cgerc(enum CBLAS_ORDER order, f77_int M, f77_int N, const void *alpha, const void *X, f77_int incX, const void *Y, f77_int incY, void *A, f77_int lda); void BLIS_EXPORT_BLAS cblas_cher(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, f77_int N, float alpha, const void *X, f77_int incX, void *A, f77_int lda); void BLIS_EXPORT_BLAS cblas_chpr(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, f77_int N, float alpha, const void *X, f77_int incX, void *A); void BLIS_EXPORT_BLAS cblas_cher2(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, f77_int N, const void *alpha, const void *X, f77_int incX, const void *Y, f77_int incY, void *A, f77_int lda); void BLIS_EXPORT_BLAS cblas_chpr2(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, f77_int N, const void *alpha, const void *X, f77_int incX, const void *Y, f77_int incY, void *Ap); void BLIS_EXPORT_BLAS cblas_zhemv(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, f77_int N, const void *alpha, const void *A, f77_int lda, const void *X, f77_int incX, const void *beta, void *Y, f77_int incY); void BLIS_EXPORT_BLAS cblas_zhbmv(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, f77_int N, f77_int K, const void *alpha, const void *A, f77_int lda, const void *X, f77_int incX, const void *beta, void *Y, f77_int incY); void BLIS_EXPORT_BLAS cblas_zhpmv(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, f77_int N, const void *alpha, const void *Ap, const void *X, f77_int incX, const void *beta, void *Y, f77_int incY); void BLIS_EXPORT_BLAS cblas_zgeru(enum CBLAS_ORDER order, f77_int M, f77_int N, const void *alpha, const void *X, f77_int incX, const void *Y, f77_int incY, void *A, f77_int lda); void BLIS_EXPORT_BLAS cblas_zgerc(enum CBLAS_ORDER order, f77_int M, f77_int N, const void *alpha, const void *X, f77_int incX, const void *Y, f77_int incY, void *A, f77_int lda); void BLIS_EXPORT_BLAS cblas_zher(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, f77_int N, double alpha, const void *X, f77_int incX, void *A, f77_int lda); void BLIS_EXPORT_BLAS cblas_zhpr(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, f77_int N, double alpha, const void *X, f77_int incX, void *A); void BLIS_EXPORT_BLAS cblas_zher2(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, f77_int N, const void *alpha, const void *X, f77_int incX, const void *Y, f77_int incY, void *A, f77_int lda); void BLIS_EXPORT_BLAS cblas_zhpr2(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, f77_int N, const void *alpha, const void *X, f77_int incX, const void *Y, f77_int incY, void *Ap); /* * =========================================================================== * Prototypes for level 3 BLAS * =========================================================================== */ /* * Routines with standard 4 prefixes (S, D, C, Z) */ void BLIS_EXPORT_BLAS cblas_sgemm(enum CBLAS_ORDER Order, enum CBLAS_TRANSPOSE TransA, enum CBLAS_TRANSPOSE TransB, f77_int M, f77_int N, f77_int K, float alpha, const float *A, f77_int lda, const float *B, f77_int ldb, float beta, float *C, f77_int ldc); void BLIS_EXPORT_BLAS cblas_ssymm(enum CBLAS_ORDER Order, enum CBLAS_SIDE Side, enum CBLAS_UPLO Uplo, f77_int M, f77_int N, float alpha, const float *A, f77_int lda, const float *B, f77_int ldb, float beta, float *C, f77_int ldc); void BLIS_EXPORT_BLAS cblas_ssyrk(enum CBLAS_ORDER Order, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE Trans, f77_int N, f77_int K, float alpha, const float *A, f77_int lda, float beta, float *C, f77_int ldc); void BLIS_EXPORT_BLAS cblas_ssyr2k(enum CBLAS_ORDER Order, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE Trans, f77_int N, f77_int K, float alpha, const float *A, f77_int lda, const float *B, f77_int ldb, float beta, float *C, f77_int ldc); void BLIS_EXPORT_BLAS cblas_strmm(enum CBLAS_ORDER Order, enum CBLAS_SIDE Side, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE TransA, enum CBLAS_DIAG Diag, f77_int M, f77_int N, float alpha, const float *A, f77_int lda, float *B, f77_int ldb); void BLIS_EXPORT_BLAS cblas_strsm(enum CBLAS_ORDER Order, enum CBLAS_SIDE Side, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE TransA, enum CBLAS_DIAG Diag, f77_int M, f77_int N, float alpha, const float *A, f77_int lda, float *B, f77_int ldb); void BLIS_EXPORT_BLAS cblas_dgemm(enum CBLAS_ORDER Order, enum CBLAS_TRANSPOSE TransA, enum CBLAS_TRANSPOSE TransB, f77_int M, f77_int N, f77_int K, double alpha, const double *A, f77_int lda, const double *B, f77_int ldb, double beta, double *C, f77_int ldc); void BLIS_EXPORT_BLAS cblas_dsymm(enum CBLAS_ORDER Order, enum CBLAS_SIDE Side, enum CBLAS_UPLO Uplo, f77_int M, f77_int N, double alpha, const double *A, f77_int lda, const double *B, f77_int ldb, double beta, double *C, f77_int ldc); void BLIS_EXPORT_BLAS cblas_dsyrk(enum CBLAS_ORDER Order, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE Trans, f77_int N, f77_int K, double alpha, const double *A, f77_int lda, double beta, double *C, f77_int ldc); void BLIS_EXPORT_BLAS cblas_dsyr2k(enum CBLAS_ORDER Order, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE Trans, f77_int N, f77_int K, double alpha, const double *A, f77_int lda, const double *B, f77_int ldb, double beta, double *C, f77_int ldc); void BLIS_EXPORT_BLAS cblas_dtrmm(enum CBLAS_ORDER Order, enum CBLAS_SIDE Side, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE TransA, enum CBLAS_DIAG Diag, f77_int M, f77_int N, double alpha, const double *A, f77_int lda, double *B, f77_int ldb); void BLIS_EXPORT_BLAS cblas_dtrsm(enum CBLAS_ORDER Order, enum CBLAS_SIDE Side, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE TransA, enum CBLAS_DIAG Diag, f77_int M, f77_int N, double alpha, const double *A, f77_int lda, double *B, f77_int ldb); void BLIS_EXPORT_BLAS cblas_cgemm(enum CBLAS_ORDER Order, enum CBLAS_TRANSPOSE TransA, enum CBLAS_TRANSPOSE TransB, f77_int M, f77_int N, f77_int K, const void *alpha, const void *A, f77_int lda, const void *B, f77_int ldb, const void *beta, void *C, f77_int ldc); void BLIS_EXPORT_BLAS cblas_csymm(enum CBLAS_ORDER Order, enum CBLAS_SIDE Side, enum CBLAS_UPLO Uplo, f77_int M, f77_int N, const void *alpha, const void *A, f77_int lda, const void *B, f77_int ldb, const void *beta, void *C, f77_int ldc); void BLIS_EXPORT_BLAS cblas_csyrk(enum CBLAS_ORDER Order, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE Trans, f77_int N, f77_int K, const void *alpha, const void *A, f77_int lda, const void *beta, void *C, f77_int ldc); void BLIS_EXPORT_BLAS cblas_csyr2k(enum CBLAS_ORDER Order, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE Trans, f77_int N, f77_int K, const void *alpha, const void *A, f77_int lda, const void *B, f77_int ldb, const void *beta, void *C, f77_int ldc); void BLIS_EXPORT_BLAS cblas_ctrmm(enum CBLAS_ORDER Order, enum CBLAS_SIDE Side, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE TransA, enum CBLAS_DIAG Diag, f77_int M, f77_int N, const void *alpha, const void *A, f77_int lda, void *B, f77_int ldb); void BLIS_EXPORT_BLAS cblas_ctrsm(enum CBLAS_ORDER Order, enum CBLAS_SIDE Side, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE TransA, enum CBLAS_DIAG Diag, f77_int M, f77_int N, const void *alpha, const void *A, f77_int lda, void *B, f77_int ldb); void BLIS_EXPORT_BLAS cblas_zgemm(enum CBLAS_ORDER Order, enum CBLAS_TRANSPOSE TransA, enum CBLAS_TRANSPOSE TransB, f77_int M, f77_int N, f77_int K, const void *alpha, const void *A, f77_int lda, const void *B, f77_int ldb, const void *beta, void *C, f77_int ldc); void BLIS_EXPORT_BLAS cblas_zsymm(enum CBLAS_ORDER Order, enum CBLAS_SIDE Side, enum CBLAS_UPLO Uplo, f77_int M, f77_int N, const void *alpha, const void *A, f77_int lda, const void *B, f77_int ldb, const void *beta, void *C, f77_int ldc); void BLIS_EXPORT_BLAS cblas_zsyrk(enum CBLAS_ORDER Order, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE Trans, f77_int N, f77_int K, const void *alpha, const void *A, f77_int lda, const void *beta, void *C, f77_int ldc); void BLIS_EXPORT_BLAS cblas_zsyr2k(enum CBLAS_ORDER Order, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE Trans, f77_int N, f77_int K, const void *alpha, const void *A, f77_int lda, const void *B, f77_int ldb, const void *beta, void *C, f77_int ldc); void BLIS_EXPORT_BLAS cblas_ztrmm(enum CBLAS_ORDER Order, enum CBLAS_SIDE Side, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE TransA, enum CBLAS_DIAG Diag, f77_int M, f77_int N, const void *alpha, const void *A, f77_int lda, void *B, f77_int ldb); void BLIS_EXPORT_BLAS cblas_ztrsm(enum CBLAS_ORDER Order, enum CBLAS_SIDE Side, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE TransA, enum CBLAS_DIAG Diag, f77_int M, f77_int N, const void *alpha, const void *A, f77_int lda, void *B, f77_int ldb); /* * Routines with prefixes C and Z only */ void BLIS_EXPORT_BLAS cblas_chemm(enum CBLAS_ORDER Order, enum CBLAS_SIDE Side, enum CBLAS_UPLO Uplo, f77_int M, f77_int N, const void *alpha, const void *A, f77_int lda, const void *B, f77_int ldb, const void *beta, void *C, f77_int ldc); void BLIS_EXPORT_BLAS cblas_cherk(enum CBLAS_ORDER Order, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE Trans, f77_int N, f77_int K, float alpha, const void *A, f77_int lda, float beta, void *C, f77_int ldc); void BLIS_EXPORT_BLAS cblas_cher2k(enum CBLAS_ORDER Order, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE Trans, f77_int N, f77_int K, const void *alpha, const void *A, f77_int lda, const void *B, f77_int ldb, float beta, void *C, f77_int ldc); void BLIS_EXPORT_BLAS cblas_zhemm(enum CBLAS_ORDER Order, enum CBLAS_SIDE Side, enum CBLAS_UPLO Uplo, f77_int M, f77_int N, const void *alpha, const void *A, f77_int lda, const void *B, f77_int ldb, const void *beta, void *C, f77_int ldc); void BLIS_EXPORT_BLAS cblas_zherk(enum CBLAS_ORDER Order, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE Trans, f77_int N, f77_int K, double alpha, const void *A, f77_int lda, double beta, void *C, f77_int ldc); void BLIS_EXPORT_BLAS cblas_zher2k(enum CBLAS_ORDER Order, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE Trans, f77_int N, f77_int K, const void *alpha, const void *A, f77_int lda, const void *B, f77_int ldb, double beta, void *C, f77_int ldc); void BLIS_EXPORT_BLAS cblas_xerbla(f77_int p, const char *rout, const char *form, ...); /* * =========================================================================== * BLAS Extension prototypes * =========================================================================== */ // -- APIs to operations unique to BLIS -- void BLIS_EXPORT_BLAS cblas_saxpby(f77_int N, float alpha, const float *X, f77_int incX, float beta, float *Y, f77_int incY); void BLIS_EXPORT_BLAS cblas_daxpby(f77_int N, double alpha, const double *X, f77_int incX, double beta, double *Y, f77_int incY); void BLIS_EXPORT_BLAS cblas_caxpby(f77_int N, const void *alpha, const void *X, f77_int incX, const void* beta, void *Y, f77_int incY); void BLIS_EXPORT_BLAS cblas_zaxpby(f77_int N, const void *alpha, const void *X, f77_int incX, const void *beta, void *Y, f77_int incY); // -- APIs to level-3-like operations -- void BLIS_EXPORT_BLAS cblas_sgemmt(enum CBLAS_ORDER Order, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE TransA, enum CBLAS_TRANSPOSE TransB, f77_int N, f77_int K, float alpha, const float *A, f77_int lda, const float *B, f77_int ldb, float beta, float *C, f77_int ldc); void BLIS_EXPORT_BLAS cblas_dgemmt(enum CBLAS_ORDER Order, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE TransA, enum CBLAS_TRANSPOSE TransB, f77_int N, f77_int K, double alpha, const double *A, f77_int lda, const double *B, f77_int ldb, double beta, double *C, f77_int ldc); void BLIS_EXPORT_BLAS cblas_cgemmt(enum CBLAS_ORDER Order, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE TransA, enum CBLAS_TRANSPOSE TransB, f77_int N, f77_int K, const void *alpha, const void *A, f77_int lda, const void *B, f77_int ldb, const void *beta, void *C, f77_int ldc); void BLIS_EXPORT_BLAS cblas_zgemmt(enum CBLAS_ORDER Order, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE TransA, enum CBLAS_TRANSPOSE TransB, f77_int N, f77_int K, const void *alpha, const void *A, f77_int lda, const void *B, f77_int ldb, const void *beta, void *C, f77_int ldc); // -- Batch APIs -- void BLIS_EXPORT_BLAS cblas_sgemm_batch(enum CBLAS_ORDER Order, enum CBLAS_TRANSPOSE *TransA_array, enum CBLAS_TRANSPOSE *TransB_array, f77_int *M_array, f77_int *N_array, f77_int *K_array, const float *alpha_array, const float **A, f77_int *lda_array, const float **B, f77_int *ldb_array, const float *beta_array, float **C, f77_int *ldc_array, f77_int group_count, f77_int *group_size); void BLIS_EXPORT_BLAS cblas_dgemm_batch(enum CBLAS_ORDER Order, enum CBLAS_TRANSPOSE *TransA_array, enum CBLAS_TRANSPOSE *TransB_array, f77_int *M_array, f77_int *N_array, f77_int *K_array, const double *alpha_array, const double **A,f77_int *lda_array, const double **B, f77_int *ldb_array, const double *beta_array, double **C, f77_int *ldc_array, f77_int group_count, f77_int *group_size); void BLIS_EXPORT_BLAS cblas_cgemm_batch(enum CBLAS_ORDER Order, enum CBLAS_TRANSPOSE *TransA_array, enum CBLAS_TRANSPOSE *TransB_array, f77_int *M_array, f77_int *N_array, f77_int *K_array, const void *alpha_array, const void **A, f77_int *lda_array, const void **B, f77_int *ldb_array, const void *beta_array, void **C, f77_int *ldc_array, f77_int group_count, f77_int *group_size); void BLIS_EXPORT_BLAS cblas_zgemm_batch(enum CBLAS_ORDER Order, enum CBLAS_TRANSPOSE *TransA_array, enum CBLAS_TRANSPOSE *TransB_array, f77_int *M_array, f77_int *N_array, f77_int *K_array, const void *alpha_array, const void **A, f77_int *lda_array, const void **B, f77_int *ldb_array, const void *beta_array, void **C, f77_int *ldc_array, f77_int group_count, f77_int *group_size); // -- 3m APIs -- void BLIS_EXPORT_BLAS cblas_cgemm3m(enum CBLAS_ORDER Order, enum CBLAS_TRANSPOSE TransA, enum CBLAS_TRANSPOSE TransB, f77_int M, f77_int N, f77_int K, const void *alpha, const void *A, f77_int lda, const void *B, f77_int ldb, const void *beta, void *C, f77_int ldc); void BLIS_EXPORT_BLAS cblas_zgemm3m(enum CBLAS_ORDER Order, enum CBLAS_TRANSPOSE TransA, enum CBLAS_TRANSPOSE TransB, f77_int M, f77_int N, f77_int K, const void *alpha, const void *A, f77_int lda, const void *B, f77_int ldb, const void *beta, void *C, f77_int ldc); #ifdef __cplusplus } #endif #endif blis-0.9.0/frame/compat/cblas/src/cblas_caxpy.c000066400000000000000000000011001422157504600213330ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_caxpy.c * * The program is a C interface to caxpy. * * Written by Keita Teranishi. 2/11/1998 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_caxpy( f77_int N, const void *alpha, const void *X, f77_int incX, void *Y, f77_int incY) { #ifdef F77_INT F77_INT F77_N=N, F77_incX=incX, F77_incY=incY; #else #define F77_N N #define F77_incX incX #define F77_incY incY #endif F77_caxpy( &F77_N, (scomplex*)alpha, (scomplex*)X, &F77_incX, (scomplex*)Y, &F77_incY); } #endif blis-0.9.0/frame/compat/cblas/src/cblas_ccopy.c000066400000000000000000000010311422157504600213270ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_ccopy.c * * The program is a C interface to ccopy. * * Written by Keita Teranishi. 2/11/1998 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_ccopy( f77_int N, const void *X, f77_int incX, void *Y, f77_int incY) { #ifdef F77_INT F77_INT F77_N=N, F77_incX=incX, F77_incY=incY; #else #define F77_N N #define F77_incX incX #define F77_incY incY #endif F77_ccopy( &F77_N, (scomplex*)X, &F77_incX, (scomplex*)Y, &F77_incY); } #endif blis-0.9.0/frame/compat/cblas/src/cblas_cdotc_sub.c000066400000000000000000000011731422157504600221660ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_cdotc_sub.c * * The program is a C interface to cdotc. * It calls the fortran wrapper before calling cdotc. * * Written by Keita Teranishi. 2/11/1998 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_cdotc_sub( f77_int N, const void *X, f77_int incX, const void *Y, f77_int incY,void *dotc) { #ifdef F77_INT F77_INT F77_N=N, F77_incX=incX, F77_incY=incY; #else #define F77_N N #define F77_incX incX #define F77_incY incY #endif F77_cdotc_sub( &F77_N, (scomplex*)X, &F77_incX, (scomplex*)Y, &F77_incY, (scomplex*)dotc); } #endif blis-0.9.0/frame/compat/cblas/src/cblas_cdotu_sub.c000066400000000000000000000011751422157504600222120ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_cdotu_sub.f * * The program is a C interface to cdotu. * It calls the forteran wrapper before calling cdotu. * * Written by Keita Teranishi. 2/11/1998 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_cdotu_sub( f77_int N, const void *X, f77_int incX, const void *Y, f77_int incY,void *dotu) { #ifdef F77_INT F77_INT F77_N=N, F77_incX=incX, F77_incY=incY; #else #define F77_N N #define F77_incX incX #define F77_incY incY #endif F77_cdotu_sub( &F77_N, (scomplex*)X, &F77_incX, (scomplex*)Y, &F77_incY, (scomplex*)dotu); } #endif blis-0.9.0/frame/compat/cblas/src/cblas_cgbmv.c000066400000000000000000000103761422157504600213240ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_cgbmv.c * The program is a C interface of cgbmv * * Keita Teranishi 5/20/98 * */ #include #include #include "cblas.h" #include "cblas_f77.h" void cblas_cgbmv(enum CBLAS_ORDER order, enum CBLAS_TRANSPOSE TransA, f77_int M, f77_int N, f77_int KL, f77_int KU, const void *alpha, const void *A, f77_int lda, const void *X, f77_int incX, const void *beta, void *Y, f77_int incY) { char TA; #ifdef F77_CHAR F77_CHAR F77_TA; #else #define F77_TA &TA #endif #ifdef F77_INT F77_INT F77_M=M, F77_N=N, F77_lda=lda, F77_incX=incX, F77_incY=incY; F77_INT F77_KL=KL,F77_KU=KU; #else #define F77_M M #define F77_N N #define F77_lda lda #define F77_KL KL #define F77_KU KU #define F77_incX incX #define F77_incY incY #endif int n=0, i=0; const float *xx= (float *)X, *alp= (float *)alpha, *bet = (float *)beta; float ALPHA[2],BETA[2]; int tincY, tincx; float *x=(float *)X, *y=(float *)Y, *st=0, *tx=0; extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if (order == CblasColMajor) { if (TransA == CblasNoTrans) TA = 'N'; else if (TransA == CblasTrans) TA = 'T'; else if (TransA == CblasConjTrans) TA = 'C'; else { cblas_xerbla(2, "cblas_cgbmv","Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_TA = C2F_CHAR(&TA); #endif F77_cgbmv(F77_TA, &F77_M, &F77_N, &F77_KL, &F77_KU, (scomplex*)alpha, (scomplex*)A, &F77_lda, (scomplex*)X, &F77_incX, (scomplex*)beta, (scomplex*)Y, &F77_incY); } else if (order == CblasRowMajor) { RowMajorStrg = 1; if (TransA == CblasNoTrans) TA = 'T'; else if (TransA == CblasTrans) TA = 'N'; else if (TransA == CblasConjTrans) { ALPHA[0]= *alp; ALPHA[1]= -alp[1]; BETA[0]= *bet; BETA[1]= -bet[1]; TA = 'N'; if (M > 0) { n = M << 1; x = malloc(n*sizeof(float)); tx = x; if( incX > 0 ) { i = incX << 1 ; tincx = 2; st= x+n; } else { i = incX *(-2); tincx = -2; st = x-2; x +=(n-2); } do { *x = *xx; x[1] = -xx[1]; x += tincx ; xx += i; } while (x != st); x=tx; #ifdef F77_INT F77_incX = 1; #else incX = 1; #endif if( incY > 0 ) tincY = incY; else tincY = -incY; y++; if (N > 0) { i = tincY << 1; n = i * N ; st = y + n; do { *y = -(*y); y += i; } while(y != st); y -= n; } } else x = (float *) X; } else { cblas_xerbla(2, "cblas_cgbmv","Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_TA = C2F_CHAR(&TA); #endif if (TransA == CblasConjTrans) F77_cgbmv(F77_TA, &F77_N, &F77_M, &F77_KU, &F77_KL, (scomplex*)ALPHA, (scomplex*)A ,&F77_lda, (scomplex*)x,&F77_incX, (scomplex*)BETA, (scomplex*)Y, &F77_incY); else F77_cgbmv(F77_TA, &F77_N, &F77_M, &F77_KU, &F77_KL, (scomplex*)alpha, (scomplex*)A ,&F77_lda, (scomplex*)x,&F77_incX, (scomplex*)beta, (scomplex*)Y, &F77_incY); if (TransA == CblasConjTrans) { if (x != X) free(x); if (N > 0) { do { *y = -(*y); y += i; } while (y != st); } } } else cblas_xerbla(1, "cblas_cgbmv", "Illegal Order setting, %d\n", order); CBLAS_CallFromC = 0; RowMajorStrg = 0; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_cgemm.c000066400000000000000000000060541422157504600213140ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * * cblas_cgemm.c * This program is a C interface to cgemm. * Written by Keita Teranishi * 4/8/1998 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_cgemm(enum CBLAS_ORDER Order, enum CBLAS_TRANSPOSE TransA, enum CBLAS_TRANSPOSE TransB, f77_int M, f77_int N, f77_int K, const void *alpha, const void *A, f77_int lda, const void *B, f77_int ldb, const void *beta, void *C, f77_int ldc) { char TA, TB; #ifdef F77_CHAR F77_CHAR F77_TA, F77_TB; #else #define F77_TA &TA #define F77_TB &TB #endif #ifdef F77_INT F77_INT F77_M=M, F77_N=N, F77_K=K, F77_lda=lda, F77_ldb=ldb; F77_INT F77_ldc=ldc; #else #define F77_M M #define F77_N N #define F77_K K #define F77_lda lda #define F77_ldb ldb #define F77_ldc ldc #endif extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if( Order == CblasColMajor ) { if(TransA == CblasTrans) TA='T'; else if ( TransA == CblasConjTrans ) TA='C'; else if ( TransA == CblasNoTrans ) TA='N'; else { cblas_xerbla(2, "cblas_cgemm", "Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if(TransB == CblasTrans) TB='T'; else if ( TransB == CblasConjTrans ) TB='C'; else if ( TransB == CblasNoTrans ) TB='N'; else { cblas_xerbla(3, "cblas_cgemm", "Illegal TransB setting, %d\n", TransB); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_TA = C2F_CHAR(&TA); F77_TB = C2F_CHAR(&TB); #endif F77_cgemm(F77_TA, F77_TB, &F77_M, &F77_N, &F77_K, (scomplex*)alpha, (scomplex*)A, &F77_lda, (scomplex*)B, &F77_ldb, (scomplex*)beta, (scomplex*)C, &F77_ldc); } else if (Order == CblasRowMajor) { RowMajorStrg = 1; if(TransA == CblasTrans) TB='T'; else if ( TransA == CblasConjTrans ) TB='C'; else if ( TransA == CblasNoTrans ) TB='N'; else { cblas_xerbla(2, "cblas_cgemm", "Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if(TransB == CblasTrans) TA='T'; else if ( TransB == CblasConjTrans ) TA='C'; else if ( TransB == CblasNoTrans ) TA='N'; else { cblas_xerbla(2, "cblas_cgemm", "Illegal TransB setting, %d\n", TransB); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_TA = C2F_CHAR(&TA); F77_TB = C2F_CHAR(&TB); #endif F77_cgemm(F77_TA, F77_TB, &F77_N, &F77_M, &F77_K, (scomplex*)alpha, (scomplex*)B, &F77_ldb, (scomplex*)A, &F77_lda, (scomplex*)beta, (scomplex*)C, &F77_ldc); } else cblas_xerbla(1, "cblas_cgemm", "Illegal Order setting, %d\n", Order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_cgemv.c000066400000000000000000000102371422157504600213230ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_cgemv.c * The program is a C interface of cgemv * * Keita Teranishi 5/20/98 * */ #include #include #include "cblas.h" #include "cblas_f77.h" void cblas_cgemv(enum CBLAS_ORDER order, enum CBLAS_TRANSPOSE TransA, f77_int M, f77_int N, const void *alpha, const void *A, f77_int lda, const void *X, f77_int incX, const void *beta, void *Y, f77_int incY) { char TA; #ifdef F77_CHAR F77_CHAR F77_TA; #else #define F77_TA &TA #endif #ifdef F77_INT F77_INT F77_M=M, F77_N=N, F77_lda=lda, F77_incX=incX, F77_incY=incY; #else #define F77_M M #define F77_N N #define F77_lda lda #define F77_incX incX #define F77_incY incY #endif int n=0, i=0; const float *xx= (const float *)X; float ALPHA[2],BETA[2]; int tincY, tincx; float *x=(float *)X, *y=(float *)Y, *st=0, *tx=0; const float *stx = x; extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if (order == CblasColMajor) { if (TransA == CblasNoTrans) TA = 'N'; else if (TransA == CblasTrans) TA = 'T'; else if (TransA == CblasConjTrans) TA = 'C'; else { cblas_xerbla(2, "cblas_cgemv","Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_TA = C2F_CHAR(&TA); #endif F77_cgemv(F77_TA, &F77_M, &F77_N, (scomplex*)alpha, (scomplex*)A, &F77_lda, (scomplex*)X, &F77_incX, (scomplex*)beta, (scomplex*)Y, &F77_incY); } else if (order == CblasRowMajor) { RowMajorStrg = 1; if (TransA == CblasNoTrans) TA = 'T'; else if (TransA == CblasTrans) TA = 'N'; else if (TransA == CblasConjTrans) { ALPHA[0]= *( (const float *) alpha ); ALPHA[1]= -( *( (const float *) alpha+1) ); BETA[0]= *( (const float *) beta ); BETA[1]= -( *( (const float *) beta+1 ) ); TA = 'N'; if (M > 0) { n = M << 1; x = malloc(n*sizeof(float)); tx = x; if( incX > 0 ) { i = incX << 1 ; tincx = 2; st= x+n; } else { i = incX *(-2); tincx = -2; st = x-2; x +=(n-2); } do { *x = *xx; x[1] = -xx[1]; x += tincx ; xx += i; } while (x != st); x=tx; F77_incX = 1; if(incY > 0) tincY = incY; else tincY = -incY; y++; if (N > 0) { i = tincY << 1; n = i * N ; st = y + n; do { *y = -(*y); y += i; } while(y != st); y -= n; } stx = x; } else stx = (const float *)X; } else { cblas_xerbla(2, "cblas_cgemv","Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_TA = C2F_CHAR(&TA); #endif if (TransA == CblasConjTrans) F77_cgemv(F77_TA, &F77_N, &F77_M, (scomplex*)ALPHA, (scomplex*)A, &F77_lda, (scomplex*)stx, &F77_incX, (scomplex*)BETA, (scomplex*)Y, &F77_incY); else F77_cgemv(F77_TA, &F77_N, &F77_M, (scomplex*)alpha, (scomplex*)A, &F77_lda, (scomplex*)x, &F77_incX, (scomplex*)beta, (scomplex*)Y, &F77_incY); if (TransA == CblasConjTrans) { if (x != (const float *)X) free(x); if (N > 0) { do { *y = -(*y); y += i; } while (y != st); } } } else cblas_xerbla(1, "cblas_cgemv", "Illegal Order setting, %d\n", order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_cgerc.c000066400000000000000000000037651422157504600213150ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_cgerc.c * The program is a C interface to cgerc. * * Keita Teranishi 5/20/98 * */ #include #include #include "cblas.h" #include "cblas_f77.h" void cblas_cgerc(enum CBLAS_ORDER order, f77_int M, f77_int N, const void *alpha, const void *X, f77_int incX, const void *Y, f77_int incY, void *A, f77_int lda) { #ifdef F77_INT F77_INT F77_M=M, F77_N=N, F77_lda=lda, F77_incX=incX, F77_incY=incY; #else #define F77_M M #define F77_N N #define F77_incX incX #define F77_incY incY #define F77_lda lda #endif int n, i, tincy; float *y=(float *)Y, *yy=(float *)Y, *ty, *st; extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if (order == CblasColMajor) { F77_cgerc( &F77_M, &F77_N, (scomplex*)alpha, (scomplex*)X, &F77_incX, (scomplex*)Y, &F77_incY, (scomplex*)A, &F77_lda); } else if (order == CblasRowMajor) { RowMajorStrg = 1; if (N > 0) { n = N << 1; y = malloc(n*sizeof(float)); ty = y; if( incY > 0 ) { i = incY << 1; tincy = 2; st= y+n; } else { i = incY *(-2); tincy = -2; st = y-2; y +=(n-2); } do { *y = *yy; y[1] = -yy[1]; y += tincy ; yy += i; } while (y != st); y = ty; #ifdef F77_INT F77_incY = 1; #else incY = 1; #endif } else y = (float *) Y; F77_cgeru( &F77_N, &F77_M, (scomplex*)alpha, (scomplex*)y, &F77_incY, (scomplex*)X, &F77_incX, (scomplex*)A, &F77_lda); if(Y!=y) free(y); } else cblas_xerbla(1, "cblas_cgerc", "Illegal Order setting, %d\n", order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_cgeru.c000066400000000000000000000023431422157504600213260ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_cgeru.c * The program is a C interface to cgeru. * * Keita Teranishi 5/20/98 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_cgeru(enum CBLAS_ORDER order, f77_int M, f77_int N, const void *alpha, const void *X, f77_int incX, const void *Y, f77_int incY, void *A, f77_int lda) { #ifdef F77_INT F77_INT F77_M=M, F77_N=N, F77_lda=lda, F77_incX=incX, F77_incY=incY; #else #define F77_M M #define F77_N N #define F77_incX incX #define F77_incY incY #define F77_lda lda #endif extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if (order == CblasColMajor) { F77_cgeru( &F77_M, &F77_N, (scomplex*)alpha, (scomplex*)X, &F77_incX, (scomplex*)Y, &F77_incY, (scomplex*)A, &F77_lda); } else if (order == CblasRowMajor) { RowMajorStrg = 1; F77_cgeru( &F77_N, &F77_M, (scomplex*)alpha, (scomplex*)Y, &F77_incY, (scomplex*)X, &F77_incX, (scomplex*)A, &F77_lda); } else cblas_xerbla(1, "cblas_cgeru","Illegal Order setting, %d\n", order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_chbmv.c000066400000000000000000000071131422157504600213200ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_chbmv.c * The program is a C interface to chbmv * * Keita Teranishi 5/18/98 * */ #include "cblas.h" #include "cblas_f77.h" #include #include void cblas_chbmv(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo,f77_int N,f77_int K, const void *alpha, const void *A, f77_int lda, const void *X, f77_int incX, const void *beta, void *Y, f77_int incY) { char UL; #ifdef F77_CHAR F77_CHAR F77_UL; #else #define F77_UL &UL #endif #ifdef F77_INT F77_INT F77_N=N, F77_K=K, F77_lda=lda, F77_incX=incX, F77_incY=incY; #else #define F77_N N #define F77_K K #define F77_lda lda #define F77_incX incX #define F77_incY incY #endif int n, i=0; const float *xx= (float *)X, *alp= (float *)alpha, *bet = (float *)beta; float ALPHA[2],BETA[2]; int tincY, tincx; float *x=(float *)X, *y=(float *)Y, *st=0, *tx; extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if (order == CblasColMajor) { if (Uplo == CblasLower) UL = 'L'; else if (Uplo == CblasUpper) UL = 'U'; else { cblas_xerbla(2, "cblas_chbmv","Illegal Uplo setting, %d\n",Uplo ); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); #endif F77_chbmv(F77_UL, &F77_N, &F77_K, (scomplex*)alpha, (scomplex*)A, &F77_lda, (scomplex*)X, &F77_incX, (scomplex*)beta, (scomplex*)Y, &F77_incY); } else if (order == CblasRowMajor) { RowMajorStrg = 1; ALPHA[0]= *alp; ALPHA[1]= -alp[1]; BETA[0]= *bet; BETA[1]= -bet[1]; if (N > 0) { n = N << 1; x = malloc(n*sizeof(float)); tx = x; if( incX > 0 ) { i = incX << 1 ; tincx = 2; st= x+n; } else { i = incX *(-2); tincx = -2; st = x-2; x +=(n-2); } do { *x = *xx; x[1] = -xx[1]; x += tincx ; xx += i; } while (x != st); x=tx; #ifdef F77_INT F77_incX = 1; #else incX = 1; #endif if(incY > 0) tincY = incY; else tincY = -incY; y++; i = tincY << 1; n = i * N ; st = y + n; do { *y = -(*y); y += i; } while(y != st); y -= n; } else x = (float *) X; if (Uplo == CblasUpper) UL = 'L'; else if (Uplo == CblasLower) UL = 'U'; else { cblas_xerbla(2, "cblas_chbmv","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); #endif F77_chbmv(F77_UL, &F77_N, &F77_K, (scomplex*)ALPHA, (scomplex*)A ,&F77_lda, (scomplex*)x,&F77_incX, (scomplex*)BETA, (scomplex*)Y, &F77_incY); } else { cblas_xerbla(1, "cblas_chbmv","Illegal Order setting, %d\n", order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if ( order == CblasRowMajor ) { RowMajorStrg = 1; if(X!=x) free(x); if (N > 0) { do { *y = -(*y); y += i; } while (y != st); } } CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_chemm.c000066400000000000000000000053561422157504600213210ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * * cblas_chemm.c * This program is a C interface to chemm. * Written by Keita Teranishi * 4/8/1998 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_chemm(enum CBLAS_ORDER Order, const enum CBLAS_SIDE Side, enum CBLAS_UPLO Uplo, f77_int M, f77_int N, const void *alpha, const void *A, f77_int lda, const void *B, f77_int ldb, const void *beta, void *C, f77_int ldc) { char SD, UL; #ifdef F77_CHAR F77_CHAR F77_SD, F77_UL; #else #define F77_SD &SD #define F77_UL &UL #endif #ifdef F77_INT F77_INT F77_M=M, F77_N=N, F77_lda=lda, F77_ldb=ldb; F77_INT F77_ldc=ldc; #else #define F77_M M #define F77_N N #define F77_lda lda #define F77_ldb ldb #define F77_ldc ldc #endif extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if( Order == CblasColMajor ) { if( Side == CblasRight) SD='R'; else if ( Side == CblasLeft ) SD='L'; else { cblas_xerbla(2, "cblas_chemm", "Illegal Side setting, %d\n", Side); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if( Uplo == CblasUpper) UL='U'; else if ( Uplo == CblasLower ) UL='L'; else { cblas_xerbla(3, "cblas_chemm", "Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_SD = C2F_CHAR(&SD); #endif F77_chemm(F77_SD, F77_UL, &F77_M, &F77_N, (scomplex*)alpha, (scomplex*)A, &F77_lda, (scomplex*)B, &F77_ldb, (scomplex*)beta, (scomplex*)C, &F77_ldc); } else if (Order == CblasRowMajor) { RowMajorStrg = 1; if( Side == CblasRight) SD='L'; else if ( Side == CblasLeft ) SD='R'; else { cblas_xerbla(2, "cblas_chemm", "Illegal Side setting, %d\n", Side); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if( Uplo == CblasUpper) UL='L'; else if ( Uplo == CblasLower ) UL='U'; else { cblas_xerbla(3, "cblas_chemm", "Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_SD = C2F_CHAR(&SD); #endif F77_chemm(F77_SD, F77_UL, &F77_N, &F77_M, (scomplex*)alpha, (scomplex*)A, &F77_lda, (scomplex*)B, &F77_ldb, (scomplex*)beta, (scomplex*)C, &F77_ldc); } else cblas_xerbla(1, "cblas_chemm", "Illegal Order setting, %d\n", Order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_chemv.c000066400000000000000000000070411422157504600213230ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_chemv.c * The program is a C interface to chemv * * Keita Teranishi 5/18/98 * */ #include #include #include "cblas.h" #include "cblas_f77.h" void cblas_chemv(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, f77_int N, const void *alpha, const void *A, f77_int lda, const void *X, f77_int incX, const void *beta, void *Y, f77_int incY) { char UL; #ifdef F77_CHAR F77_CHAR F77_UL; #else #define F77_UL &UL #endif #ifdef F77_INT F77_INT F77_N=N, F77_lda=lda, F77_incX=incX, F77_incY=incY; #else #define F77_N N #define F77_lda lda #define F77_incX incX #define F77_incY incY #endif int n=0, i=0; const float *xx= (float *)X, *alp= (float *)alpha, *bet = (float *)beta; float ALPHA[2],BETA[2]; int tincY, tincx; float *x=(float *)X, *y=(float *)Y, *st=0, *tx; extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if (order == CblasColMajor) { if (Uplo == CblasUpper) UL = 'U'; else if (Uplo == CblasLower) UL = 'L'; else { cblas_xerbla(2, "cblas_chemv","Illegal Uplo setting, %d\n",Uplo ); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); #endif F77_chemv(F77_UL, &F77_N, (scomplex*)alpha, (scomplex*)A, &F77_lda, (scomplex*)X, &F77_incX, (scomplex*)beta, (scomplex*)Y, &F77_incY); } else if (order == CblasRowMajor) { RowMajorStrg = 1; ALPHA[0]= *alp; ALPHA[1]= -alp[1]; BETA[0]= *bet; BETA[1]= -bet[1]; if (N > 0) { n = N << 1; x = malloc(n*sizeof(float)); tx = x; if( incX > 0 ) { i = incX << 1 ; tincx = 2; st= x+n; } else { i = incX *(-2); tincx = -2; st = x-2; x +=(n-2); } do { *x = *xx; x[1] = -xx[1]; x += tincx ; xx += i; } while (x != st); x=tx; #ifdef F77_INT F77_incX = 1; #else incX = 1; #endif if(incY > 0) tincY = incY; else tincY = -incY; y++; i = tincY << 1; n = i * N ; st = y + n; do { *y = -(*y); y += i; } while(y != st); y -= n; } else x = (float *) X; if (Uplo == CblasUpper) UL = 'L'; else if (Uplo == CblasLower) UL = 'U'; else { cblas_xerbla(2, "cblas_chemv","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); #endif F77_chemv(F77_UL, &F77_N, (scomplex*)ALPHA, (scomplex*)A, &F77_lda, (scomplex*)x, &F77_incX, (scomplex*)BETA, (scomplex*)Y, &F77_incY); } else { cblas_xerbla(1, "cblas_chemv","Illegal Order setting, %d\n", order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if ( order == CblasRowMajor ) { RowMajorStrg = 1; if ( X != x ) free(x); if (N > 0) { do { *y = -(*y); y += i; } while (y != st); } } CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_cher.c000066400000000000000000000051131422157504600211400ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_cher.c * The program is a C interface to cher. * * Keita Teranishi 5/20/98 * */ #include #include #include "cblas.h" #include "cblas_f77.h" void cblas_cher(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, f77_int N, float alpha, const void *X, f77_int incX ,void *A, f77_int lda) { char UL; #ifdef F77_CHAR F77_CHAR F77_UL; #else #define F77_UL &UL #endif #ifdef F77_INT F77_INT F77_N=N, F77_lda=lda, F77_incX=incX; #else #define F77_N N #define F77_lda lda #define F77_incX incX #endif int n, i, tincx; float *x=(float *)X, *xx=(float *)X, *tx, *st; extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if (order == CblasColMajor) { if (Uplo == CblasLower) UL = 'L'; else if (Uplo == CblasUpper) UL = 'U'; else { cblas_xerbla(2, "cblas_cher","Illegal Uplo setting, %d\n",Uplo ); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); #endif F77_cher(F77_UL, &F77_N, &alpha, (scomplex*)X, &F77_incX, (scomplex*)A, &F77_lda); } else if (order == CblasRowMajor) { RowMajorStrg = 1; if (Uplo == CblasUpper) UL = 'L'; else if (Uplo == CblasLower) UL = 'U'; else { cblas_xerbla(2, "cblas_cher","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); #endif if (N > 0) { n = N << 1; x = malloc(n*sizeof(float)); tx = x; if( incX > 0 ) { i = incX << 1 ; tincx = 2; st= x+n; } else { i = incX *(-2); tincx = -2; st = x-2; x +=(n-2); } do { *x = *xx; x[1] = -xx[1]; x += tincx ; xx += i; } while (x != st); x=tx; #ifdef F77_INT F77_incX = 1; #else incX = 1; #endif } else x = (float *) X; F77_cher(F77_UL, &F77_N, &alpha, (scomplex*)x, &F77_incX, (scomplex*)A, &F77_lda); } else { cblas_xerbla(1, "cblas_cher","Illegal Order setting, %d\n", order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if(X!=x) free(x); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_cher2.c000066400000000000000000000066621422157504600212340ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_cher2.c * The program is a C interface to cher2. * * Keita Teranishi 3/23/98 * */ #include #include #include "cblas.h" #include "cblas_f77.h" void cblas_cher2(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, f77_int N, const void *alpha, const void *X, f77_int incX, const void *Y, f77_int incY, void *A, f77_int lda) { char UL; #ifdef F77_CHAR F77_CHAR F77_UL; #else #define F77_UL &UL #endif #ifdef F77_INT F77_INT F77_N=N, F77_lda=lda, F77_incX=incX, F77_incY=incY; #else #define F77_N N #define F77_lda lda #define F77_incX incX #define F77_incY incY #endif int n, i, j, tincx, tincy; float *x=(float *)X, *xx=(float *)X, *y=(float *)Y, *yy=(float *)Y, *tx, *ty, *stx, *sty; extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if (order == CblasColMajor) { if (Uplo == CblasLower) UL = 'L'; else if (Uplo == CblasUpper) UL = 'U'; else { cblas_xerbla(2, "cblas_cher2","Illegal Uplo setting, %d\n",Uplo ); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); #endif F77_cher2(F77_UL, &F77_N, (scomplex*)alpha, (scomplex*)X, &F77_incX, (scomplex*)Y, &F77_incY, (scomplex*)A, &F77_lda); } else if (order == CblasRowMajor) { RowMajorStrg = 1; if (Uplo == CblasUpper) UL = 'L'; else if (Uplo == CblasLower) UL = 'U'; else { cblas_xerbla(2, "cblas_cher2","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); #endif if (N > 0) { n = N << 1; x = malloc(n*sizeof(float)); y = malloc(n*sizeof(float)); tx = x; ty = y; if( incX > 0 ) { i = incX << 1 ; tincx = 2; stx= x+n; } else { i = incX *(-2); tincx = -2; stx = x-2; x +=(n-2); } if( incY > 0 ) { j = incY << 1; tincy = 2; sty= y+n; } else { j = incY *(-2); tincy = -2; sty = y-2; y +=(n-2); } do { *x = *xx; x[1] = -xx[1]; x += tincx ; xx += i; } while (x != stx); do { *y = *yy; y[1] = -yy[1]; y += tincy ; yy += j; } while (y != sty); x=tx; y=ty; #ifdef F77_INT F77_incX = 1; F77_incY = 1; #else incX = 1; incY = 1; #endif } else { x = (float *) X; y = (float *) Y; } F77_cher2(F77_UL, &F77_N, (scomplex*)alpha, (scomplex*)y, &F77_incY, (scomplex*)x, &F77_incX, (scomplex*)A, &F77_lda); } else { cblas_xerbla(1, "cblas_cher2","Illegal Order setting, %d\n", order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if(X!=x) free(x); if(Y!=y) free(y); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_cher2k.c000066400000000000000000000056451422157504600214070ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * * cblas_cher2k.c * This program is a C interface to cher2k. * Written by Keita Teranishi * 4/8/1998 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_cher2k(enum CBLAS_ORDER Order, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE Trans, f77_int N, f77_int K, const void *alpha, const void *A, f77_int lda, const void *B, f77_int ldb, float beta, void *C, f77_int ldc) { char UL, TR; #ifdef F77_CHAR F77_CHAR F77_TR, F77_UL; #else #define F77_TR &TR #define F77_UL &UL #endif #ifdef F77_INT F77_INT F77_N=N, F77_K=K, F77_lda=lda, F77_ldb=ldb; F77_INT F77_ldc=ldc; #else #define F77_N N #define F77_K K #define F77_lda lda #define F77_ldb ldb #define F77_ldc ldc #endif extern int CBLAS_CallFromC; extern int RowMajorStrg; float ALPHA[2]; const float *alp=(float *)alpha; CBLAS_CallFromC = 1; RowMajorStrg = 0; if( Order == CblasColMajor ) { if( Uplo == CblasUpper) UL='U'; else if ( Uplo == CblasLower ) UL='L'; else { cblas_xerbla(2, "cblas_cher2k", "Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if( Trans == CblasTrans) TR ='T'; else if ( Trans == CblasConjTrans ) TR='C'; else if ( Trans == CblasNoTrans ) TR='N'; else { cblas_xerbla(3, "cblas_cher2k", "Illegal Trans setting, %d\n", Trans); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TR = C2F_CHAR(&TR); #endif F77_cher2k(F77_UL, F77_TR, &F77_N, &F77_K, (scomplex*)alpha, (scomplex*)A, &F77_lda, (scomplex*)B, &F77_ldb, &beta, (scomplex*)C, &F77_ldc); } else if (Order == CblasRowMajor) { RowMajorStrg = 1; if( Uplo == CblasUpper) UL='L'; else if ( Uplo == CblasLower ) UL='U'; else { cblas_xerbla(2, "cblas_cher2k", "Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if( Trans == CblasTrans) TR ='N'; else if ( Trans == CblasConjTrans ) TR='N'; else if ( Trans == CblasNoTrans ) TR='C'; else { cblas_xerbla(3, "cblas_cher2k", "Illegal Trans setting, %d\n", Trans); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TR = C2F_CHAR(&TR); #endif ALPHA[0]= *alp; ALPHA[1]= -alp[1]; F77_cher2k(F77_UL,F77_TR, &F77_N, &F77_K, (scomplex*)ALPHA, (scomplex*)A, &F77_lda, (scomplex*)B, &F77_ldb, &beta, (scomplex*)C, &F77_ldc); } else cblas_xerbla(1, "cblas_cher2k", "Illegal Order setting, %d\n", Order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_cherk.c000066400000000000000000000052631422157504600213210ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * * cblas_cherk.c * This program is a C interface to cherk. * Written by Keita Teranishi * 4/8/1998 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_cherk(enum CBLAS_ORDER Order, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE Trans, f77_int N, f77_int K, float alpha, const void *A, f77_int lda, float beta, void *C, f77_int ldc) { char UL, TR; #ifdef F77_CHAR F77_CHAR F77_TR, F77_UL; #else #define F77_TR &TR #define F77_UL &UL #endif #ifdef F77_INT F77_INT F77_N=N, F77_K=K, F77_lda=lda; F77_INT F77_ldc=ldc; #else #define F77_N N #define F77_K K #define F77_lda lda #define F77_ldc ldc #endif extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if( Order == CblasColMajor ) { if( Uplo == CblasUpper) UL='U'; else if ( Uplo == CblasLower ) UL='L'; else { cblas_xerbla(2, "cblas_cherk", "Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if( Trans == CblasTrans) TR ='T'; else if ( Trans == CblasConjTrans ) TR='C'; else if ( Trans == CblasNoTrans ) TR='N'; else { cblas_xerbla(3, "cblas_cherk", "Illegal Trans setting, %d\n", Trans); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TR = C2F_CHAR(&TR); #endif F77_cherk(F77_UL, F77_TR, &F77_N, &F77_K, &alpha, (scomplex*)A, &F77_lda, &beta, (scomplex*)C, &F77_ldc); } else if (Order == CblasRowMajor) { RowMajorStrg = 1; if( Uplo == CblasUpper) UL='L'; else if ( Uplo == CblasLower ) UL='U'; else { cblas_xerbla(3, "cblas_cherk", "Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if( Trans == CblasTrans) TR ='N'; else if ( Trans == CblasConjTrans ) TR='N'; else if ( Trans == CblasNoTrans ) TR='C'; else { cblas_xerbla(3, "cblas_cherk", "Illegal Trans setting, %d\n", Trans); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_SD = C2F_CHAR(&SD); #endif F77_cherk(F77_UL, F77_TR, &F77_N, &F77_K, &alpha, (scomplex*)A, &F77_lda, &beta, (scomplex*)C, &F77_ldc); } else cblas_xerbla(1, "cblas_cherk", "Illegal Order setting, %d\n", Order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_chpmv.c000066400000000000000000000067271422157504600213500ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_chpmv.c * The program is a C interface of chpmv * * Keita Teranishi 5/18/98 * */ #include #include #include "cblas.h" #include "cblas_f77.h" void cblas_chpmv(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo,f77_int N, const void *alpha, const void *AP, const void *X, f77_int incX, const void *beta, void *Y, f77_int incY) { char UL; #ifdef F77_CHAR F77_CHAR F77_UL; #else #define F77_UL &UL #endif #ifdef F77_INT F77_INT F77_N=N, F77_incX=incX, F77_incY=incY; #else #define F77_N N #define F77_incX incX #define F77_incY incY #endif int n, i=0; const float *xx= (float *)X, *alp= (float *)alpha, *bet = (float *)beta; float ALPHA[2],BETA[2]; int tincY, tincx; float *x=(float *)X, *y=(float *)Y, *st=0, *tx; extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if (order == CblasColMajor) { if (Uplo == CblasLower) UL = 'L'; else if (Uplo == CblasUpper) UL = 'U'; else { cblas_xerbla(2, "cblas_chpmv","Illegal Uplo setting, %d\n",Uplo ); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); #endif F77_chpmv(F77_UL, &F77_N, (scomplex*)alpha, (scomplex*)AP, (scomplex*)X, &F77_incX, (scomplex*)beta, (scomplex*)Y, &F77_incY); } else if (order == CblasRowMajor) { RowMajorStrg = 1; ALPHA[0]= *alp; ALPHA[1]= -alp[1]; BETA[0]= *bet; BETA[1]= -bet[1]; if (N > 0) { n = N << 1; x = malloc(n*sizeof(float)); tx = x; if( incX > 0 ) { i = incX << 1; tincx = 2; st= x+n; } else { i = incX *(-2); tincx = -2; st = x-2; x +=(n-2); } do { *x = *xx; x[1] = -xx[1]; x += tincx ; xx += i; } while (x != st); x=tx; #ifdef F77_INT F77_incX = 1; #else incX = 1; #endif if(incY > 0) tincY = incY; else tincY = -incY; y++; i = tincY << 1; n = i * N ; st = y + n; do { *y = -(*y); y += i; } while(y != st); y -= n; } else x = (float *) X; if (Uplo == CblasUpper) UL = 'L'; else if (Uplo == CblasLower) UL = 'U'; else { cblas_xerbla(2, "cblas_chpmv","Illegal Uplo setting, %d\n", Uplo ); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); #endif F77_chpmv(F77_UL, &F77_N, (scomplex*)ALPHA, (scomplex*)AP, (scomplex*)x, &F77_incX, (scomplex*)BETA, (scomplex*)Y, &F77_incY); } else { cblas_xerbla(1, "cblas_chpmv","Illegal Order setting, %d\n", order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if ( order == CblasRowMajor ) { RowMajorStrg = 1; if(X!=x) free(x); if (N > 0) { do { *y = -(*y); y += i; } while (y != st); } } CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_chpr.c000066400000000000000000000050021422157504600211500ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_chpr.c * The program is a C interface to chpr. * * Keita Teranishi 3/23/98 * */ #include #include #include "cblas.h" #include "cblas_f77.h" void cblas_chpr(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, f77_int N, float alpha, const void *X, f77_int incX, void *A) { char UL; #ifdef F77_CHAR F77_CHAR F77_UL; #else #define F77_UL &UL #endif #ifdef F77_INT F77_INT F77_N=N, F77_incX=incX; #else #define F77_N N #define F77_incX incX #endif int n, i, tincx; float *x=(float *)X, *xx=(float *)X, *tx, *st; extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if (order == CblasColMajor) { if (Uplo == CblasLower) UL = 'L'; else if (Uplo == CblasUpper) UL = 'U'; else { cblas_xerbla(2, "cblas_chpr","Illegal Uplo setting, %d\n",Uplo ); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); #endif F77_chpr(F77_UL, &F77_N, &alpha, (scomplex*)X, &F77_incX, (scomplex*)A); } else if (order == CblasRowMajor) { RowMajorStrg = 1; if (Uplo == CblasUpper) UL = 'L'; else if (Uplo == CblasLower) UL = 'U'; else { cblas_xerbla(2, "cblas_chpr","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); #endif if (N > 0) { n = N << 1; x = malloc(n*sizeof(float)); tx = x; if( incX > 0 ) { i = incX << 1; tincx = 2; st= x+n; } else { i = incX *(-2); tincx = -2; st = x-2; x +=(n-2); } do { *x = *xx; x[1] = -xx[1]; x += tincx ; xx += i; } while (x != st); x=tx; #ifdef F77_INT F77_incX = 1; #else incX = 1; #endif } else x = (float *) X; F77_chpr(F77_UL, &F77_N, &alpha, (scomplex*)x, &F77_incX, (scomplex*)A); } else { cblas_xerbla(1, "cblas_chpr","Illegal Order setting, %d\n", order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if(X!=x) free(x); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_chpr2.c000066400000000000000000000064571422157504600212510ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_chpr2.c * The program is a C interface to chpr2. * * Keita Teranishi 5/20/98 * */ #include #include #include "cblas.h" #include "cblas_f77.h" void cblas_chpr2(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, f77_int N,const void *alpha, const void *X, f77_int incX,const void *Y, f77_int incY, void *Ap) { char UL; #ifdef F77_CHAR F77_CHAR F77_UL; #else #define F77_UL &UL #endif #ifdef F77_INT F77_INT F77_N=N, F77_incX=incX, F77_incY=incY; #else #define F77_N N #define F77_incX incX #define F77_incY incY #endif int n, i, j, tincx, tincy; float *x=(float *)X, *xx=(float *)X, *y=(float *)Y, *yy=(float *)Y, *tx, *ty, *stx, *sty; extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if (order == CblasColMajor) { if (Uplo == CblasLower) UL = 'L'; else if (Uplo == CblasUpper) UL = 'U'; else { cblas_xerbla(2, "cblas_chpr2","Illegal Uplo setting, %d\n",Uplo ); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); #endif F77_chpr2(F77_UL, &F77_N, (scomplex*)alpha, (scomplex*)X, &F77_incX, (scomplex*)Y, &F77_incY, (scomplex*)Ap); } else if (order == CblasRowMajor) { RowMajorStrg = 1; if (Uplo == CblasUpper) UL = 'L'; else if (Uplo == CblasLower) UL = 'U'; else { cblas_xerbla(2, "cblas_chpr2","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); #endif if (N > 0) { n = N << 1; x = malloc(n*sizeof(float)); y = malloc(n*sizeof(float)); tx = x; ty = y; if( incX > 0 ) { i = incX << 1 ; tincx = 2; stx= x+n; } else { i = incX *(-2); tincx = -2; stx = x-2; x +=(n-2); } if( incY > 0 ) { j = incY << 1; tincy = 2; sty= y+n; } else { j = incY *(-2); tincy = -2; sty = y-2; y +=(n-2); } do { *x = *xx; x[1] = -xx[1]; x += tincx ; xx += i; } while (x != stx); do { *y = *yy; y[1] = -yy[1]; y += tincy ; yy += j; } while (y != sty); x=tx; y=ty; #ifdef F77_INT F77_incX = 1; F77_incY = 1; #else incX = 1; incY = 1; #endif } else { x = (float *) X; y = (void *) Y; } F77_chpr2(F77_UL, &F77_N, (scomplex*)alpha, (scomplex*)y, &F77_incY, (scomplex*)x, &F77_incX, (scomplex*)Ap); } else { cblas_xerbla(1, "cblas_chpr2","Illegal Order setting, %d\n", order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if(X!=x) free(x); if(Y!=y) free(y); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_cscal.c000066400000000000000000000007441422157504600213110ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_cscal.c * * The program is a C interface to cscal.f. * * Written by Keita Teranishi. 2/11/1998 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_cscal( f77_int N, const void *alpha, void *X, f77_int incX) { #ifdef F77_INT F77_INT F77_N=N, F77_incX=incX; #else #define F77_N N #define F77_incX incX #endif F77_cscal( &F77_N, (scomplex*)alpha, (scomplex*)X, &F77_incX); } #endif blis-0.9.0/frame/compat/cblas/src/cblas_csscal.c000066400000000000000000000007251422157504600214730ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_csscal.c * * The program is a C interface to csscal. * * Written by Keita Teranishi. 2/11/1998 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_csscal( f77_int N, float alpha, void *X, f77_int incX) { #ifdef F77_INT F77_INT F77_N=N, F77_incX=incX; #else #define F77_N N #define F77_incX incX #endif F77_csscal( &F77_N, &alpha, (scomplex*)X, &F77_incX); } #endif blis-0.9.0/frame/compat/cblas/src/cblas_cswap.c000066400000000000000000000010241422157504600213310ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_cswap.c * * The program is a C interface to cswap. * * Written by Keita Teranishi. 2/11/1998 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_cswap( f77_int N, void *X, f77_int incX, void *Y, f77_int incY) { #ifdef F77_INT F77_INT F77_N=N, F77_incX=incX, F77_incY=incY; #else #define F77_N N #define F77_incX incX #define F77_incY incY #endif F77_cswap( &F77_N, (scomplex*)X, &F77_incX, (scomplex*)Y, &F77_incY); } #endif blis-0.9.0/frame/compat/cblas/src/cblas_csymm.c000066400000000000000000000053511422157504600213530ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * * cblas_csymm.c * This program is a C interface to csymm. * Written by Keita Teranishi * 4/8/1998 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_csymm(enum CBLAS_ORDER Order, enum CBLAS_SIDE Side, enum CBLAS_UPLO Uplo, f77_int M, f77_int N, const void *alpha, const void *A, f77_int lda, const void *B, f77_int ldb, const void *beta, void *C, f77_int ldc) { char SD, UL; #ifdef F77_CHAR F77_CHAR F77_SD, F77_UL; #else #define F77_SD &SD #define F77_UL &UL #endif #ifdef F77_INT F77_INT F77_M=M, F77_N=N, F77_lda=lda, F77_ldb=ldb; F77_INT F77_ldc=ldc; #else #define F77_M M #define F77_N N #define F77_lda lda #define F77_ldb ldb #define F77_ldc ldc #endif extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if( Order == CblasColMajor ) { if( Side == CblasRight) SD='R'; else if ( Side == CblasLeft ) SD='L'; else { cblas_xerbla(2, "cblas_csymm", "Illegal Side setting, %d\n", Side); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if( Uplo == CblasUpper) UL='U'; else if ( Uplo == CblasLower ) UL='L'; else { cblas_xerbla(3, "cblas_csymm", "Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_SD = C2F_CHAR(&SD); #endif F77_csymm(F77_SD, F77_UL, &F77_M, &F77_N, (scomplex*)alpha, (scomplex*)A, &F77_lda, (scomplex*)B, &F77_ldb, (scomplex*)beta, (scomplex*)C, &F77_ldc); } else if (Order == CblasRowMajor) { RowMajorStrg = 1; if( Side == CblasRight) SD='L'; else if ( Side == CblasLeft ) SD='R'; else { cblas_xerbla(2, "cblas_csymm", "Illegal Side setting, %d\n", Side); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if( Uplo == CblasUpper) UL='L'; else if ( Uplo == CblasLower ) UL='U'; else { cblas_xerbla(3, "cblas_csymm", "Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_SD = C2F_CHAR(&SD); #endif F77_csymm(F77_SD, F77_UL, &F77_N, &F77_M, (scomplex*)alpha, (scomplex*)A, &F77_lda, (scomplex*)B, &F77_ldb, (scomplex*)beta, (scomplex*)C, &F77_ldc); } else cblas_xerbla(1, "cblas_csymm", "Illegal Order setting, %d\n", Order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_csyr2k.c000066400000000000000000000055471422157504600214470ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * * cblas_csyr2k.c * This program is a C interface to csyr2k. * Written by Keita Teranishi * 4/8/1998 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_csyr2k(enum CBLAS_ORDER Order, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE Trans, f77_int N, f77_int K, const void *alpha, const void *A, f77_int lda, const void *B, f77_int ldb, const void *beta, void *C, f77_int ldc) { char UL, TR; #ifdef F77_CHAR F77_CHAR F77_TR, F77_UL; #else #define F77_TR &TR #define F77_UL &UL #endif #ifdef F77_INT F77_INT F77_N=N, F77_K=K, F77_lda=lda, F77_ldb=ldb; F77_INT F77_ldc=ldc; #else #define F77_N N #define F77_K K #define F77_lda lda #define F77_ldb ldb #define F77_ldc ldc #endif extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if( Order == CblasColMajor ) { if( Uplo == CblasUpper) UL='U'; else if ( Uplo == CblasLower ) UL='L'; else { cblas_xerbla(2, "cblas_csyr2k", "Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if( Trans == CblasTrans) TR ='T'; else if ( Trans == CblasConjTrans ) TR='C'; else if ( Trans == CblasNoTrans ) TR='N'; else { cblas_xerbla(3, "cblas_csyr2k", "Illegal Trans setting, %d\n", Trans); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TR = C2F_CHAR(&TR); #endif F77_csyr2k(F77_UL, F77_TR, &F77_N, &F77_K, (scomplex*)alpha, (scomplex*)A, &F77_lda, (scomplex*)B, &F77_ldb, (scomplex*)beta, (scomplex*)C, &F77_ldc); } else if (Order == CblasRowMajor) { RowMajorStrg = 1; if( Uplo == CblasUpper) UL='L'; else if ( Uplo == CblasLower ) UL='U'; else { cblas_xerbla(3, "cblas_csyr2k", "Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if( Trans == CblasTrans) TR ='N'; else if ( Trans == CblasConjTrans ) TR='N'; else if ( Trans == CblasNoTrans ) TR='T'; else { cblas_xerbla(3, "cblas_csyr2k", "Illegal Trans setting, %d\n", Trans); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TR = C2F_CHAR(&TR); #endif F77_csyr2k(F77_UL, F77_TR, &F77_N, &F77_K, (scomplex*)alpha, (scomplex*)A, &F77_lda, (scomplex*)B, &F77_ldb, (scomplex*)beta, (scomplex*)C, &F77_ldc); } else cblas_xerbla(1, "cblas_csyr2k", "Illegal Order setting, %d\n", Order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_csyrk.c000066400000000000000000000053461422157504600213620ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * * cblas_csyrk.c * This program is a C interface to csyrk. * Written by Keita Teranishi * 4/8/1998 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_csyrk(enum CBLAS_ORDER Order, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE Trans, f77_int N, f77_int K, const void *alpha, const void *A, f77_int lda, const void *beta, void *C, f77_int ldc) { char UL, TR; #ifdef F77_CHAR F77_CHAR F77_TR, F77_UL; #else #define F77_TR &TR #define F77_UL &UL #endif #ifdef F77_INT F77_INT F77_N=N, F77_K=K, F77_lda=lda; F77_INT F77_ldc=ldc; #else #define F77_N N #define F77_K K #define F77_lda lda #define F77_ldc ldc #endif extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if( Order == CblasColMajor ) { if( Uplo == CblasUpper) UL='U'; else if ( Uplo == CblasLower ) UL='L'; else { cblas_xerbla(2, "cblas_csyrk", "Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if( Trans == CblasTrans) TR ='T'; else if ( Trans == CblasConjTrans ) TR='C'; else if ( Trans == CblasNoTrans ) TR='N'; else { cblas_xerbla(3, "cblas_csyrk", "Illegal Trans setting, %d\n", Trans); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TR = C2F_CHAR(&TR); #endif F77_csyrk(F77_UL, F77_TR, &F77_N, &F77_K, (scomplex*)alpha, (scomplex*)A, &F77_lda, (scomplex*)beta, (scomplex*)C, &F77_ldc); } else if (Order == CblasRowMajor) { RowMajorStrg = 1; if( Uplo == CblasUpper) UL='L'; else if ( Uplo == CblasLower ) UL='U'; else { cblas_xerbla(3, "cblas_csyrk", "Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if( Trans == CblasTrans) TR ='N'; else if ( Trans == CblasConjTrans ) TR='N'; else if ( Trans == CblasNoTrans ) TR='T'; else { cblas_xerbla(3, "cblas_csyrk", "Illegal Trans setting, %d\n", Trans); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TR = C2F_CHAR(&TR); #endif F77_csyrk(F77_UL, F77_TR, &F77_N, &F77_K, (scomplex*)alpha, (scomplex*)A, &F77_lda, (scomplex*)beta, (scomplex*)C, &F77_ldc); } else cblas_xerbla(1, "cblas_csyrk", "Illegal Order setting, %d\n", Order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_ctbmv.c000066400000000000000000000077001422157504600213360ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_ctbmv.c * The program is a C interface to ctbmv. * * Keita Teranishi 5/20/98 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_ctbmv(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE TransA, enum CBLAS_DIAG Diag, f77_int N, f77_int K, const void *A, f77_int lda, void *X, f77_int incX) { char TA; char UL; char DI; #ifdef F77_CHAR F77_CHAR F77_TA, F77_UL, F77_DI; #else #define F77_TA &TA #define F77_UL &UL #define F77_DI &DI #endif #ifdef F77_INT F77_INT F77_N=N, F77_lda=lda, F77_K=K, F77_incX=incX; #else #define F77_N N #define F77_K K #define F77_lda lda #define F77_incX incX #endif int n, i=0, tincX; float *st=0, *x=(float *)X; extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if (order == CblasColMajor) { if (Uplo == CblasUpper) UL = 'U'; else if (Uplo == CblasLower) UL = 'L'; else { cblas_xerbla(2, "cblas_ctbmv","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (TransA == CblasNoTrans) TA = 'N'; else if (TransA == CblasTrans) TA = 'T'; else if (TransA == CblasConjTrans) TA = 'C'; else { cblas_xerbla(3, "cblas_ctbmv","Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (Diag == CblasUnit) DI = 'U'; else if (Diag == CblasNonUnit) DI = 'N'; else { cblas_xerbla(4, "cblas_ctbmv","Illegal Diag setting, %d\n", Diag); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TA = C2F_CHAR(&TA); F77_DI = C2F_CHAR(&DI); #endif F77_ctbmv( F77_UL, F77_TA, F77_DI, &F77_N, &F77_K, (scomplex*)A, &F77_lda, (scomplex*)X, &F77_incX); } else if (order == CblasRowMajor) { RowMajorStrg = 1; if (Uplo == CblasUpper) UL = 'L'; else if (Uplo == CblasLower) UL = 'U'; else { cblas_xerbla(2, "cblas_ctbmv","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (TransA == CblasNoTrans) TA = 'T'; else if (TransA == CblasTrans) TA = 'N'; else if (TransA == CblasConjTrans) { TA = 'N'; if ( N > 0) { if(incX > 0) tincX = incX; else tincX = -incX; i = tincX << 1; n = i * N; x++; st = x + n; do { *x = -(*x); x+= i; } while (x != st); x -= n; } } else { cblas_xerbla(3, "cblas_ctbmv","Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (Diag == CblasUnit) DI = 'U'; else if (Diag == CblasNonUnit) DI = 'N'; else { cblas_xerbla(4, "cblas_ctbmv","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TA = C2F_CHAR(&TA); F77_DI = C2F_CHAR(&DI); #endif F77_ctbmv( F77_UL, F77_TA, F77_DI, &F77_N, &F77_K, (scomplex*)A, &F77_lda, (scomplex*)X, &F77_incX); if (TransA == CblasConjTrans) { if (N > 0) { do { *x = -(*x); x += i; } while (x != st); } } } else cblas_xerbla(1, "cblas_ctbmv", "Illegal Order setting, %d\n", order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_ctbsv.c000066400000000000000000000077111422157504600213460ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_ctbsv.c * The program is a C interface to ctbsv. * * Keita Teranishi 3/23/98 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_ctbsv(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE TransA, enum CBLAS_DIAG Diag, f77_int N, f77_int K, const void *A, f77_int lda, void *X, f77_int incX) { char TA; char UL; char DI; #ifdef F77_CHAR F77_CHAR F77_TA, F77_UL, F77_DI; #else #define F77_TA &TA #define F77_UL &UL #define F77_DI &DI #endif #ifdef F77_INT F77_INT F77_N=N, F77_lda=lda, F77_K=K, F77_incX=incX; #else #define F77_N N #define F77_K K #define F77_lda lda #define F77_incX incX #endif int n, i=0, tincX; float *st=0,*x=(float *)X; extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if (order == CblasColMajor) { if (Uplo == CblasUpper) UL = 'U'; else if (Uplo == CblasLower) UL = 'L'; else { cblas_xerbla(2, "cblas_ctbsv","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (TransA == CblasNoTrans) TA = 'N'; else if (TransA == CblasTrans) TA = 'T'; else if (TransA == CblasConjTrans) TA = 'C'; else { cblas_xerbla(3, "cblas_ctbsv","Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (Diag == CblasUnit) DI = 'U'; else if (Diag == CblasNonUnit) DI = 'N'; else { cblas_xerbla(4, "cblas_ctbsv","Illegal Diag setting, %d\n", Diag); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TA = C2F_CHAR(&TA); F77_DI = C2F_CHAR(&DI); #endif F77_ctbsv( F77_UL, F77_TA, F77_DI, &F77_N, &F77_K, (scomplex*)A, &F77_lda, (scomplex*)X, &F77_incX); } else if (order == CblasRowMajor) { RowMajorStrg = 1; if (Uplo == CblasUpper) UL = 'L'; else if (Uplo == CblasLower) UL = 'U'; else { cblas_xerbla(2, "cblas_ctbsv","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (TransA == CblasNoTrans) TA = 'T'; else if (TransA == CblasTrans) TA = 'N'; else if (TransA == CblasConjTrans) { TA = 'N'; if ( N > 0) { if ( incX > 0 ) tincX = incX; else tincX = -incX; n = N*2*(tincX); x++; st=x+n; i = tincX << 1; do { *x = -(*x); x+=i; } while (x != st); x -= n; } } else { cblas_xerbla(3, "cblas_ctbsv","Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (Diag == CblasUnit) DI = 'U'; else if (Diag == CblasNonUnit) DI = 'N'; else { cblas_xerbla(4, "cblas_ctbsv","Illegal Diag setting, %d\n", Diag); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TA = C2F_CHAR(&TA); F77_DI = C2F_CHAR(&DI); #endif F77_ctbsv( F77_UL, F77_TA, F77_DI, &F77_N, &F77_K, (scomplex*)A, &F77_lda, (scomplex*)X, &F77_incX); if (TransA == CblasConjTrans) { if (N > 0) { do { *x = -(*x); x+= i; } while (x != st); } } } else cblas_xerbla(1, "cblas_ctbsv", "Illegal Order setting, %d\n", order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_ctpmv.c000066400000000000000000000074101422157504600213520ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_ctpmv.c * The program is a C interface to ctpmv. * * Keita Teranishi 5/20/98 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_ctpmv(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE TransA, enum CBLAS_DIAG Diag, f77_int N, const void *Ap, void *X, f77_int incX) { char TA; char UL; char DI; #ifdef F77_CHAR F77_CHAR F77_TA, F77_UL, F77_DI; #else #define F77_TA &TA #define F77_UL &UL #define F77_DI &DI #endif #ifdef F77_INT F77_INT F77_N=N, F77_incX=incX; #else #define F77_N N #define F77_incX incX #endif int n, i=0, tincX; float *st=0,*x=(float *)X; extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if (order == CblasColMajor) { if (Uplo == CblasUpper) UL = 'U'; else if (Uplo == CblasLower) UL = 'L'; else { cblas_xerbla(2, "cblas_ctpmv","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (TransA == CblasNoTrans) TA = 'N'; else if (TransA == CblasTrans) TA = 'T'; else if (TransA == CblasConjTrans) TA = 'C'; else { cblas_xerbla(3, "cblas_ctpmv","Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (Diag == CblasUnit) DI = 'U'; else if (Diag == CblasNonUnit) DI = 'N'; else { cblas_xerbla(4, "cblas_ctpmv","Illegal Diag setting, %d\n", Diag); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TA = C2F_CHAR(&TA); F77_DI = C2F_CHAR(&DI); #endif F77_ctpmv( F77_UL, F77_TA, F77_DI, &F77_N, (scomplex*)Ap, (scomplex*)X, &F77_incX); } else if (order == CblasRowMajor) { RowMajorStrg = 1; if (Uplo == CblasUpper) UL = 'L'; else if (Uplo == CblasLower) UL = 'U'; else { cblas_xerbla(2, "cblas_ctpmv","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (TransA == CblasNoTrans) TA = 'T'; else if (TransA == CblasTrans) TA = 'N'; else if (TransA == CblasConjTrans) { TA = 'N'; if ( N > 0) { if(incX > 0) tincX = incX; else tincX = -incX; i = tincX << 1; n = i * N; x++; st = x + n; do { *x = -(*x); x += i; } while (x != st); x -= n; } } else { cblas_xerbla(3, "cblas_ctpmv","Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (Diag == CblasUnit) DI = 'U'; else if (Diag == CblasNonUnit) DI = 'N'; else { cblas_xerbla(4, "cblas_ctpmv","Illegal Diag setting, %d\n", Diag); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TA = C2F_CHAR(&TA); F77_DI = C2F_CHAR(&DI); #endif F77_ctpmv( F77_UL, F77_TA, F77_DI, &F77_N, (scomplex*)Ap, (scomplex*)X,&F77_incX); if (TransA == CblasConjTrans) { if (N > 0) { do { *x = -(*x); x += i; } while (x != st); } } } else cblas_xerbla(1, "cblas_ctpmv", "Illegal Order setting, %d\n", order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_ctpsv.c000066400000000000000000000074221422157504600213630ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_ctpsv.c * The program is a C interface to ctpsv. * * Keita Teranishi 3/23/98 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_ctpsv(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE TransA, enum CBLAS_DIAG Diag, f77_int N, const void *Ap, void *X, f77_int incX) { char TA; char UL; char DI; #ifdef F77_CHAR F77_CHAR F77_TA, F77_UL, F77_DI; #else #define F77_TA &TA #define F77_UL &UL #define F77_DI &DI #endif #ifdef F77_INT F77_INT F77_N=N, F77_incX=incX; #else #define F77_N N #define F77_incX incX #endif int n, i=0, tincX; float *st=0, *x=(float*)X; extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if (order == CblasColMajor) { if (Uplo == CblasUpper) UL = 'U'; else if (Uplo == CblasLower) UL = 'L'; else { cblas_xerbla(2, "cblas_ctpsv","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (TransA == CblasNoTrans) TA = 'N'; else if (TransA == CblasTrans) TA = 'T'; else if (TransA == CblasConjTrans) TA = 'C'; else { cblas_xerbla(3, "cblas_ctpsv","Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (Diag == CblasUnit) DI = 'U'; else if (Diag == CblasNonUnit) DI = 'N'; else { cblas_xerbla(4, "cblas_ctpsv","Illegal Diag setting, %d\n", Diag); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TA = C2F_CHAR(&TA); F77_DI = C2F_CHAR(&DI); #endif F77_ctpsv( F77_UL, F77_TA, F77_DI, &F77_N, (scomplex*)Ap, (scomplex*)X, &F77_incX); } else if (order == CblasRowMajor) { RowMajorStrg = 1; if (Uplo == CblasUpper) UL = 'L'; else if (Uplo == CblasLower) UL = 'U'; else { cblas_xerbla(2, "cblas_ctpsv","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (TransA == CblasNoTrans) TA = 'T'; else if (TransA == CblasTrans) TA = 'N'; else if (TransA == CblasConjTrans) { TA = 'N'; if ( N > 0) { if ( incX > 0 ) tincX = incX; else tincX = -incX; n = N*2*(tincX); x++; st=x+n; i = tincX << 1; do { *x = -(*x); x+=i; } while (x != st); x -= n; } } else { cblas_xerbla(3, "cblas_ctpsv","Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (Diag == CblasUnit) DI = 'U'; else if (Diag == CblasNonUnit) DI = 'N'; else { cblas_xerbla(4, "cblas_ctpsv","Illegal Diag setting, %d\n", Diag); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TA = C2F_CHAR(&TA); F77_DI = C2F_CHAR(&DI); #endif F77_ctpsv( F77_UL, F77_TA, F77_DI, &F77_N, (scomplex*)Ap, (scomplex*)X,&F77_incX); if (TransA == CblasConjTrans) { if (N > 0) { do { *x = -(*x); x += i; } while (x != st); } } } else cblas_xerbla(1, "cblas_ctpsv", "Illegal Order setting, %d\n", order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_ctrmm.c000066400000000000000000000076221422157504600213500ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * * cblas_ctrmm.c * This program is a C interface to ctrmm. * Written by Keita Teranishi * 4/8/1998 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_ctrmm(enum CBLAS_ORDER Order, enum CBLAS_SIDE Side, enum CBLAS_UPLO Uplo, const enum CBLAS_TRANSPOSE TransA, enum CBLAS_DIAG Diag, f77_int M, f77_int N, const void *alpha, const void *A, f77_int lda, void *B, f77_int ldb) { char UL, TA, SD, DI; #ifdef F77_CHAR F77_CHAR F77_TA, F77_UL, F77_SD, F77_DI; #else #define F77_TA &TA #define F77_UL &UL #define F77_SD &SD #define F77_DI &DI #endif #ifdef F77_INT F77_INT F77_M=M, F77_N=N, F77_lda=lda, F77_ldb=ldb; #else #define F77_M M #define F77_N N #define F77_lda lda #define F77_ldb ldb #endif extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if( Order == CblasColMajor ) { if( Side == CblasRight ) SD='R'; else if ( Side == CblasLeft ) SD='L'; else { cblas_xerbla(2, "cblas_ctrmm", "Illegal Side setting, %d\n", Side); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if( Uplo == CblasUpper ) UL='U'; else if ( Uplo == CblasLower ) UL='L'; else { cblas_xerbla(3, "cblas_ctrmm", "Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if( TransA == CblasTrans ) TA ='T'; else if ( TransA == CblasConjTrans ) TA='C'; else if ( TransA == CblasNoTrans ) TA='N'; else { cblas_xerbla(4, "cblas_ctrmm", "Illegal Trans setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if( Diag == CblasUnit ) DI='U'; else if ( Diag == CblasNonUnit ) DI='N'; else cblas_xerbla(5, "cblas_ctrmm", "Illegal Diag setting, %d\n", Diag); #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TA = C2F_CHAR(&TA); F77_SD = C2F_CHAR(&SD); F77_DI = C2F_CHAR(&DI); #endif F77_ctrmm(F77_SD, F77_UL, F77_TA, F77_DI, &F77_M, &F77_N, (scomplex*)alpha, (scomplex*)A, &F77_lda, (scomplex*)B, &F77_ldb); } else if (Order == CblasRowMajor) { RowMajorStrg = 1; if( Side == CblasRight ) SD='L'; else if ( Side == CblasLeft ) SD='R'; else { cblas_xerbla(2, "cblas_ctrmm", "Illegal Side setting, %d\n", Side); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if( Uplo == CblasUpper ) UL='L'; else if ( Uplo == CblasLower ) UL='U'; else { cblas_xerbla(3, "cblas_ctrmm", "Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if( TransA == CblasTrans ) TA ='T'; else if ( TransA == CblasConjTrans ) TA='C'; else if ( TransA == CblasNoTrans ) TA='N'; else { cblas_xerbla(4, "cblas_ctrmm", "Illegal Trans setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if( Diag == CblasUnit ) DI='U'; else if ( Diag == CblasNonUnit ) DI='N'; else { cblas_xerbla(5, "cblas_ctrmm", "Illegal Diag setting, %d\n", Diag); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TA = C2F_CHAR(&TA); F77_SD = C2F_CHAR(&SD); F77_DI = C2F_CHAR(&DI); #endif F77_ctrmm(F77_SD, F77_UL, F77_TA, F77_DI, &F77_N, &F77_M, (scomplex*)alpha, (scomplex*)A, &F77_lda, (scomplex*)B, &F77_ldb); } else cblas_xerbla(1, "cblas_ctrmm", "Illegal Order setting, %d\n", Order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_ctrmv.c000066400000000000000000000075751422157504600213700ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_ctrmv.c * The program is a C interface to ctrmv. * * Keita Teranishi 3/23/98 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_ctrmv(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE TransA, enum CBLAS_DIAG Diag, f77_int N, const void *A, f77_int lda, void *X, f77_int incX) { char TA; char UL; char DI; #ifdef F77_CHAR F77_CHAR F77_TA, F77_UL, F77_DI; #else #define F77_TA &TA #define F77_UL &UL #define F77_DI &DI #endif #ifdef F77_INT F77_INT F77_N=N, F77_lda=lda, F77_incX=incX; #else #define F77_N N #define F77_lda lda #define F77_incX incX #endif int n, i=0, tincX; float *st=0,*x=(float *)X; extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if (order == CblasColMajor) { if (Uplo == CblasUpper) UL = 'U'; else if (Uplo == CblasLower) UL = 'L'; else { cblas_xerbla(2, "cblas_ctrmv","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (TransA == CblasNoTrans) TA = 'N'; else if (TransA == CblasTrans) TA = 'T'; else if (TransA == CblasConjTrans) TA = 'C'; else { cblas_xerbla(3, "cblas_ctrmv","Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (Diag == CblasUnit) DI = 'U'; else if (Diag == CblasNonUnit) DI = 'N'; else { cblas_xerbla(4, "cblas_ctrmv","Illegal Diag setting, %d\n", Diag); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TA = C2F_CHAR(&TA); F77_DI = C2F_CHAR(&DI); #endif F77_ctrmv( F77_UL, F77_TA, F77_DI, &F77_N, (scomplex*)A, &F77_lda, (scomplex*)X, &F77_incX); } else if (order == CblasRowMajor) { RowMajorStrg = 1; if (Uplo == CblasUpper) UL = 'L'; else if (Uplo == CblasLower) UL = 'U'; else { cblas_xerbla(2, "cblas_ctrmv","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (TransA == CblasNoTrans) TA = 'T'; else if (TransA == CblasTrans) TA = 'N'; else if (TransA == CblasConjTrans) { TA = 'N'; if ( N > 0) { if(incX > 0) tincX = incX; else tincX = -incX; i = tincX << 1; n = i * N; st = x + n; do { x[1] = -x[1]; x+= i; } while (x != st); x -= n; } } else { cblas_xerbla(3, "cblas_ctrmv","Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (Diag == CblasUnit) DI = 'U'; else if (Diag == CblasNonUnit) DI = 'N'; else { cblas_xerbla(4, "cblas_ctrmv","Illegal Diag setting, %d\n", Diag); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TA = C2F_CHAR(&TA); F77_DI = C2F_CHAR(&DI); #endif F77_ctrmv( F77_UL, F77_TA, F77_DI, &F77_N, (scomplex*)A, &F77_lda, (scomplex*)X, &F77_incX); if (TransA == CblasConjTrans) { if (N > 0) { do { x[1] = -x[1]; x += i; } while (x != st); } } } else cblas_xerbla(1, "cblas_ctrmv", "Illegal Order setting, %d\n", order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_ctrsm.c000066400000000000000000000077141422157504600213600ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * * cblas_ctrsm.c * This program is a C interface to ctrsm. * Written by Keita Teranishi * 4/8/1998 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_ctrsm(enum CBLAS_ORDER Order, enum CBLAS_SIDE Side, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE TransA, enum CBLAS_DIAG Diag, f77_int M, f77_int N, const void *alpha, const void *A, f77_int lda, void *B, f77_int ldb) { char UL, TA, SD, DI; #ifdef F77_CHAR F77_CHAR F77_TA, F77_UL, F77_SD, F77_DI; #else #define F77_TA &TA #define F77_UL &UL #define F77_SD &SD #define F77_DI &DI #endif #ifdef F77_INT F77_INT F77_M=M, F77_N=N, F77_lda=lda, F77_ldb=ldb; #else #define F77_M M #define F77_N N #define F77_lda lda #define F77_ldb ldb #endif extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if( Order == CblasColMajor ) { if( Side == CblasRight) SD='R'; else if ( Side == CblasLeft ) SD='L'; else { cblas_xerbla(2, "cblas_ctrsm", "Illegal Side setting, %d\n", Side); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if( Uplo == CblasUpper) UL='U'; else if ( Uplo == CblasLower ) UL='L'; else { cblas_xerbla(3, "cblas_ctrsm", "Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if( TransA == CblasTrans) TA ='T'; else if ( TransA == CblasConjTrans ) TA='C'; else if ( TransA == CblasNoTrans ) TA='N'; else { cblas_xerbla(4, "cblas_ctrsm", "Illegal Trans setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if( Diag == CblasUnit ) DI='U'; else if ( Diag == CblasNonUnit ) DI='N'; else { cblas_xerbla(5, "cblas_ctrsm", "Illegal Diag setting, %d\n", Diag); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TA = C2F_CHAR(&TA); F77_SD = C2F_CHAR(&SD); F77_DI = C2F_CHAR(&DI); #endif F77_ctrsm(F77_SD, F77_UL, F77_TA, F77_DI, &F77_M, &F77_N, alpha, A, &F77_lda, B, &F77_ldb); } else if (Order == CblasRowMajor) { RowMajorStrg = 1; if( Side == CblasRight) SD='L'; else if ( Side == CblasLeft ) SD='R'; else { cblas_xerbla(2, "cblas_ctrsm", "Illegal Side setting, %d\n", Side); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if( Uplo == CblasUpper) UL='L'; else if ( Uplo == CblasLower ) UL='U'; else { cblas_xerbla(3, "cblas_ctrsm", "Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if( TransA == CblasTrans) TA ='T'; else if ( TransA == CblasConjTrans ) TA='C'; else if ( TransA == CblasNoTrans ) TA='N'; else { cblas_xerbla(4, "cblas_ctrsm", "Illegal Trans setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if( Diag == CblasUnit ) DI='U'; else if ( Diag == CblasNonUnit ) DI='N'; else { cblas_xerbla(5, "cblas_ctrsm", "Illegal Diag setting, %d\n", Diag); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TA = C2F_CHAR(&TA); F77_SD = C2F_CHAR(&SD); F77_DI = C2F_CHAR(&DI); #endif F77_ctrsm(F77_SD, F77_UL, F77_TA, F77_DI, &F77_N, &F77_M, (scomplex*)alpha, (scomplex*)A, &F77_lda, (scomplex*)B, &F77_ldb); } else cblas_xerbla(1, "cblas_ctrsm", "Illegal Order setting, %d\n", Order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_ctrsv.c000066400000000000000000000076151422157504600213710ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_ctrsv.c * The program is a C interface to ctrsv. * * Keita Teranishi 3/23/98 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_ctrsv(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE TransA, enum CBLAS_DIAG Diag, f77_int N, const void *A, f77_int lda, void *X, f77_int incX) { char TA; char UL; char DI; #ifdef F77_CHAR F77_CHAR F77_TA, F77_UL, F77_DI; #else #define F77_TA &TA #define F77_UL &UL #define F77_DI &DI #endif #ifdef F77_INT F77_INT F77_N=N, F77_lda=lda, F77_incX=incX; #else #define F77_N N #define F77_lda lda #define F77_incX incX #endif int n, i=0, tincX; float *st=0,*x=(float *)X; extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if (order == CblasColMajor) { if (Uplo == CblasUpper) UL = 'U'; else if (Uplo == CblasLower) UL = 'L'; else { cblas_xerbla(2, "cblas_ctrsv","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (TransA == CblasNoTrans) TA = 'N'; else if (TransA == CblasTrans) TA = 'T'; else if (TransA == CblasConjTrans) TA = 'C'; else { cblas_xerbla(3, "cblas_ctrsv","Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (Diag == CblasUnit) DI = 'U'; else if (Diag == CblasNonUnit) DI = 'N'; else { cblas_xerbla(4, "cblas_ctrsv","Illegal Diag setting, %d\n", Diag); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TA = C2F_CHAR(&TA); F77_DI = C2F_CHAR(&DI); #endif F77_ctrsv( F77_UL, F77_TA, F77_DI, &F77_N, (scomplex*)A, &F77_lda, (scomplex*)X, &F77_incX); } else if (order == CblasRowMajor) { RowMajorStrg = 1; if (Uplo == CblasUpper) UL = 'L'; else if (Uplo == CblasLower) UL = 'U'; else { cblas_xerbla(2, "cblas_ctrsv","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (TransA == CblasNoTrans) TA = 'T'; else if (TransA == CblasTrans) TA = 'N'; else if (TransA == CblasConjTrans) { TA = 'N'; if ( N > 0) { if ( incX > 0 ) tincX = incX; else tincX = -incX; n = N*2*(tincX); x++; st=x+n; i = tincX << 1; do { *x = -(*x); x+=i; } while (x != st); x -= n; } } else { cblas_xerbla(3, "cblas_ctrsv","Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (Diag == CblasUnit) DI = 'U'; else if (Diag == CblasNonUnit) DI = 'N'; else { cblas_xerbla(4, "cblas_ctrsv","Illegal Diag setting, %d\n", Diag); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TA = C2F_CHAR(&TA); F77_DI = C2F_CHAR(&DI); #endif F77_ctrsv( F77_UL, F77_TA, F77_DI, &F77_N, (scomplex*)A, &F77_lda, (scomplex*)X, &F77_incX); if (TransA == CblasConjTrans) { if (N > 0) { do { *x = -(*x); x += i; } while (x != st); } } } else cblas_xerbla(1, "cblas_ctrsv", "Illegal Order setting, %d\n", order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_dasum.c000066400000000000000000000010061422157504600213250ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_dasum.c * * The program is a C interface to dasum. * It calls the fortran wrapper before calling dasum. * * Written by Keita Teranishi. 2/11/1998 * */ #include "cblas.h" #include "cblas_f77.h" double cblas_dasum( f77_int N, const double *X, f77_int incX) { double asum; #ifdef F77_INT F77_INT F77_N=N, F77_incX=incX; #else #define F77_N N #define F77_incX incX #endif F77_dasum_sub( &F77_N, X, &F77_incX, &asum); return asum; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_daxpy.c000066400000000000000000000010371422157504600213450ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_daxpy.c * * The program is a C interface to daxpy. * * Written by Keita Teranishi. 2/11/1998 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_daxpy( f77_int N, double alpha, const double *X, f77_int incX, double *Y, f77_int incY) { #ifdef F77_INT F77_INT F77_N=N, F77_incX=incX, F77_incY=incY; #else #define F77_N N #define F77_incX incX #define F77_incY incY #endif F77_daxpy( &F77_N, &alpha, X, &F77_incX, Y, &F77_incY); } #endif blis-0.9.0/frame/compat/cblas/src/cblas_dcopy.c000066400000000000000000000010071422157504600213330ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_dcopy.c * * The program is a C interface to dcopy. * * Written by Keita Teranishi. 2/11/1998 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_dcopy( f77_int N, const double *X, f77_int incX, double *Y, f77_int incY) { #ifdef F77_INT F77_INT F77_N=N, F77_incX=incX, F77_incY=incY; #else #define F77_N N #define F77_incX incX #define F77_incY incY #endif F77_dcopy( &F77_N, X, &F77_incX, Y, &F77_incY); } #endif blis-0.9.0/frame/compat/cblas/src/cblas_ddot.c000066400000000000000000000011531422157504600211510ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_ddot.c * * The program is a C interface to ddot. * It calls the fortran wrapper before calling ddot. * * Written by Keita Teranishi. 2/11/1998 * */ #include "cblas.h" #include "cblas_f77.h" double cblas_ddot( f77_int N, const double *X, f77_int incX, const double *Y, f77_int incY) { double dot; #ifdef F77_INT F77_INT F77_N=N, F77_incX=incX, F77_incY=incY; #else #define F77_N N #define F77_incX incX #define F77_incY incY #endif F77_ddot_sub( &F77_N, X, &F77_incX, Y, &F77_incY, &dot); return dot; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_dgbmv.c000066400000000000000000000043701422157504600213220ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * * cblas_dgbmv.c * This program is a C interface to dgbmv. * Written by Keita Teranishi * 4/6/1998 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_dgbmv(enum CBLAS_ORDER order, enum CBLAS_TRANSPOSE TransA, f77_int M, f77_int N, f77_int KL, f77_int KU, double alpha, const double *A, f77_int lda, const double *X, f77_int incX, double beta, double *Y, f77_int incY) { char TA; #ifdef F77_CHAR F77_CHAR F77_TA; #else #define F77_TA &TA #endif #ifdef F77_INT F77_INT F77_M=M, F77_N=N, F77_lda=lda, F77_incX=incX, F77_incY=incY; F77_INT F77_KL=KL,F77_KU=KU; #else #define F77_M M #define F77_N N #define F77_lda lda #define F77_KL KL #define F77_KU KU #define F77_incX incX #define F77_incY incY #endif extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if (order == CblasColMajor) { if (TransA == CblasNoTrans) TA = 'N'; else if (TransA == CblasTrans) TA = 'T'; else if (TransA == CblasConjTrans) TA = 'C'; else { cblas_xerbla(2, "cblas_dgbmv","Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_TA = C2F_CHAR(&TA); #endif F77_dgbmv(F77_TA, &F77_M, &F77_N, &F77_KL, &F77_KU, &alpha, A, &F77_lda, X, &F77_incX, &beta, Y, &F77_incY); } else if (order == CblasRowMajor) { RowMajorStrg = 1; if (TransA == CblasNoTrans) TA = 'T'; else if (TransA == CblasTrans) TA = 'N'; else if (TransA == CblasConjTrans) TA = 'N'; else { cblas_xerbla(2, "cblas_dgbmv","Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_TA = C2F_CHAR(&TA); #endif F77_dgbmv(F77_TA, &F77_N, &F77_M, &F77_KU, &F77_KL, &alpha, A ,&F77_lda, X,&F77_incX, &beta, Y, &F77_incY); } else cblas_xerbla(1, "cblas_dgbmv", "Illegal Order setting, %d\n", order); CBLAS_CallFromC = 0; RowMajorStrg = 0; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_dgemm.c000066400000000000000000000056551422157504600213230ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * * cblas_dgemm.c * This program is a C interface to dgemm. * Written by Keita Teranishi * 4/8/1998 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_dgemm(enum CBLAS_ORDER Order, enum CBLAS_TRANSPOSE TransA, enum CBLAS_TRANSPOSE TransB, f77_int M, f77_int N, f77_int K, double alpha, const double *A, f77_int lda, const double *B, f77_int ldb, double beta, double *C, f77_int ldc) { char TA, TB; #ifdef F77_CHAR F77_CHAR F77_TA, F77_TB; #else #define F77_TA &TA #define F77_TB &TB #endif #ifdef F77_INT F77_INT F77_M=M, F77_N=N, F77_K=K, F77_lda=lda, F77_ldb=ldb; F77_INT F77_ldc=ldc; #else #define F77_M M #define F77_N N #define F77_K K #define F77_lda lda #define F77_ldb ldb #define F77_ldc ldc #endif extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if( Order == CblasColMajor ) { if(TransA == CblasTrans) TA='T'; else if ( TransA == CblasConjTrans ) TA='C'; else if ( TransA == CblasNoTrans ) TA='N'; else { cblas_xerbla(2, "cblas_dgemm","Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if(TransB == CblasTrans) TB='T'; else if ( TransB == CblasConjTrans ) TB='C'; else if ( TransB == CblasNoTrans ) TB='N'; else { cblas_xerbla(3, "cblas_dgemm","Illegal TransB setting, %d\n", TransB); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_TA = C2F_CHAR(&TA); F77_TB = C2F_CHAR(&TB); #endif F77_dgemm(F77_TA, F77_TB, &F77_M, &F77_N, &F77_K, &alpha, A, &F77_lda, B, &F77_ldb, &beta, C, &F77_ldc); } else if (Order == CblasRowMajor) { RowMajorStrg = 1; if(TransA == CblasTrans) TB='T'; else if ( TransA == CblasConjTrans ) TB='C'; else if ( TransA == CblasNoTrans ) TB='N'; else { cblas_xerbla(2, "cblas_dgemm","Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if(TransB == CblasTrans) TA='T'; else if ( TransB == CblasConjTrans ) TA='C'; else if ( TransB == CblasNoTrans ) TA='N'; else { cblas_xerbla(2, "cblas_dgemm","Illegal TransB setting, %d\n", TransB); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_TA = C2F_CHAR(&TA); F77_TB = C2F_CHAR(&TB); #endif F77_dgemm(F77_TA, F77_TB, &F77_N, &F77_M, &F77_K, &alpha, B, &F77_ldb, A, &F77_lda, &beta, C, &F77_ldc); } else cblas_xerbla(1, "cblas_dgemm", "Illegal Order setting, %d\n", Order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_dgemv.c000066400000000000000000000041411422157504600213210ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * * cblas_dgemv.c * This program is a C interface to dgemv. * Written by Keita Teranishi * 4/6/1998 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_dgemv(enum CBLAS_ORDER order, enum CBLAS_TRANSPOSE TransA, f77_int M, f77_int N, double alpha, const double *A, f77_int lda, const double *X, f77_int incX, double beta, double *Y, f77_int incY) { char TA; #ifdef F77_CHAR F77_CHAR F77_TA; #else #define F77_TA &TA #endif #ifdef F77_INT F77_INT F77_M=M, F77_N=N, F77_lda=lda, F77_incX=incX, F77_incY=incY; #else #define F77_M M #define F77_N N #define F77_lda lda #define F77_incX incX #define F77_incY incY #endif extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if (order == CblasColMajor) { if (TransA == CblasNoTrans) TA = 'N'; else if (TransA == CblasTrans) TA = 'T'; else if (TransA == CblasConjTrans) TA = 'C'; else { cblas_xerbla(2, "cblas_dgemv","Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_TA = C2F_CHAR(&TA); #endif F77_dgemv(F77_TA, &F77_M, &F77_N, &alpha, A, &F77_lda, X, &F77_incX, &beta, Y, &F77_incY); } else if (order == CblasRowMajor) { RowMajorStrg = 1; if (TransA == CblasNoTrans) TA = 'T'; else if (TransA == CblasTrans) TA = 'N'; else if (TransA == CblasConjTrans) TA = 'N'; else { cblas_xerbla(2, "cblas_dgemv","Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_TA = C2F_CHAR(&TA); #endif F77_dgemv(F77_TA, &F77_N, &F77_M, &alpha, A, &F77_lda, X, &F77_incX, &beta, Y, &F77_incY); } else cblas_xerbla(1, "cblas_dgemv", "Illegal Order setting, %d\n", order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_dger.c000066400000000000000000000022331422157504600211400ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * * cblas_dger.c * This program is a C interface to dger. * Written by Keita Teranishi * 4/6/1998 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_dger(enum CBLAS_ORDER order, f77_int M, f77_int N, double alpha, const double *X, f77_int incX, const double *Y, f77_int incY, double *A, f77_int lda) { #ifdef F77_INT F77_INT F77_M=M, F77_N=N, F77_lda=lda, F77_incX=incX, F77_incY=incY; #else #define F77_M M #define F77_N N #define F77_incX incX #define F77_incY incY #define F77_lda lda #endif extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if (order == CblasColMajor) { F77_dger( &F77_M, &F77_N, &alpha, X, &F77_incX, Y, &F77_incY, A, &F77_lda); } else if (order == CblasRowMajor) { RowMajorStrg = 1; F77_dger( &F77_N, &F77_M ,&alpha, Y, &F77_incY, X, &F77_incX, A, &F77_lda); } else cblas_xerbla(1, "cblas_dger", "Illegal Order setting, %d\n", order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_dnrm2.c000066400000000000000000000010051422157504600212350ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_dnrm2.c * * The program is a C interface to dnrm2. * It calls the fortranwrapper before calling dnrm2. * * Written by Keita Teranishi. 2/11/1998 * */ #include "cblas.h" #include "cblas_f77.h" double cblas_dnrm2( f77_int N, const double *X, f77_int incX) { double nrm2; #ifdef F77_INT F77_INT F77_N=N, F77_incX=incX; #else #define F77_N N #define F77_incX incX #endif F77_dnrm2_sub( &F77_N, X, &F77_incX, &nrm2); return nrm2; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_drot.c000066400000000000000000000010351422157504600211660ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_drot.c * * The program is a C interface to drot. * * Written by Keita Teranishi. 2/11/1998 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_drot(f77_int N, double *X, f77_int incX, double *Y, f77_int incY, const double c, const double s) { #ifdef F77_INT F77_INT F77_N=N, F77_incX=incX, F77_incY=incY; #else #define F77_N N #define F77_incX incX #define F77_incY incY #endif F77_drot(&F77_N, X, &F77_incX, Y, &F77_incY, &c, &s); return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_drotg.c000066400000000000000000000004571422157504600213440ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_drotg.c * * The program is a C interface to drotg. * * Written by Keita Teranishi. 2/11/1998 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_drotg( double *a, double *b, double *c, double *s) { F77_drotg(a,b,c,s); } #endif blis-0.9.0/frame/compat/cblas/src/cblas_drotm.c000066400000000000000000000006441422157504600213500ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS #include "cblas.h" #include "cblas_f77.h" void cblas_drotm( f77_int N, double *X, f77_int incX, double *Y, f77_int incY, const double *P) { #ifdef F77_INT F77_INT F77_N=N, F77_incX=incX, F77_incY=incY; #else #define F77_N N #define F77_incX incX #define F77_incY incY #endif F77_drotm( &F77_N, X, &F77_incX, Y, &F77_incY, P); } #endif blis-0.9.0/frame/compat/cblas/src/cblas_drotmg.c000066400000000000000000000005421422157504600215140ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_drotmg.c * * The program is a C interface to drotmg. * * Written by Keita Teranishi. 2/11/1998 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_drotmg( double *d1, double *d2, double *b1, const double b2, double *p) { F77_drotmg(d1,d2,b1,&b2,p); } #endif blis-0.9.0/frame/compat/cblas/src/cblas_dsbmv.c000066400000000000000000000037541422157504600213430ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * * cblas_dsbmv.c * This program is a C interface to dsbmv. * Written by Keita Teranishi * 4/6/1998 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_dsbmv(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, f77_int N, f77_int K, double alpha, const double *A, f77_int lda, const double *X, f77_int incX, double beta, double *Y, f77_int incY) { char UL; #ifdef F77_CHAR F77_CHAR F77_UL; #else #define F77_UL &UL #endif #ifdef F77_INT F77_INT F77_N=N, F77_K=K, F77_lda=lda, F77_incX=incX, F77_incY=incY; #else #define F77_N N #define F77_K K #define F77_lda lda #define F77_incX incX #define F77_incY incY #endif extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if (order == CblasColMajor) { if (Uplo == CblasUpper) UL = 'U'; else if (Uplo == CblasLower) UL = 'L'; else { cblas_xerbla(2, "cblas_dsbmv","Illegal Uplo setting, %d\n",Uplo ); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); #endif F77_dsbmv(F77_UL, &F77_N, &F77_K, &alpha, A, &F77_lda, X, &F77_incX, &beta, Y, &F77_incY); } else if (order == CblasRowMajor) { RowMajorStrg = 1; if (Uplo == CblasUpper) UL = 'L'; else if (Uplo == CblasLower) UL = 'U'; else { cblas_xerbla(2, "cblas_dsbmv","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); #endif F77_dsbmv(F77_UL, &F77_N, &F77_K, &alpha, A ,&F77_lda, X,&F77_incX, &beta, Y, &F77_incY); } else cblas_xerbla(1, "cblas_dsbmv", "Illegal Order setting, %d\n", order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_dscal.c000066400000000000000000000007121422157504600213050ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_dscal.c * * The program is a C interface to dscal. * * Written by Keita Teranishi. 2/11/1998 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_dscal( f77_int N, double alpha, double *X, f77_int incX) { #ifdef F77_INT F77_INT F77_N=N, F77_incX=incX; #else #define F77_N N #define F77_incX incX #endif F77_dscal( &F77_N, &alpha, X, &F77_incX); } #endif blis-0.9.0/frame/compat/cblas/src/cblas_dsdot.c000066400000000000000000000011601422157504600213320ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_dsdot.c * * The program is a C interface to dsdot. * It calls fthe fortran wrapper before calling dsdot. * * Written by Keita Teranishi. 2/11/1998 * */ #include "cblas.h" #include "cblas_f77.h" double cblas_dsdot( f77_int N, const float *X, f77_int incX, const float *Y, f77_int incY) { double dot; #ifdef F77_INT F77_INT F77_N=N, F77_incX=incX, F77_incY=incY; #else #define F77_N N #define F77_incX incX #define F77_incY incY #endif F77_dsdot_sub( &F77_N, X, &F77_incX, Y, &F77_incY, &dot); return dot; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_dspmv.c000066400000000000000000000035651422157504600213610ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * * cblas_dspmv.c * This program is a C interface to dspmv. * Written by Keita Teranishi * 4/6/1998 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_dspmv(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, f77_int N, double alpha, const double *AP, const double *X, f77_int incX, double beta, double *Y, f77_int incY) { char UL; #ifdef F77_CHAR F77_CHAR F77_UL; #else #define F77_UL &UL #endif #ifdef F77_INT F77_INT F77_N=N, F77_incX=incX, F77_incY=incY; #else #define F77_N N #define F77_incX incX #define F77_incY incY #endif extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if (order == CblasColMajor) { if (Uplo == CblasUpper) UL = 'U'; else if (Uplo == CblasLower) UL = 'L'; else { cblas_xerbla(2, "cblas_dspmv","Illegal Uplo setting, %d\n",Uplo ); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); #endif F77_dspmv(F77_UL, &F77_N, &alpha, AP, X, &F77_incX, &beta, Y, &F77_incY); } else if (order == CblasRowMajor) { RowMajorStrg = 1; if (Uplo == CblasUpper) UL = 'L'; else if (Uplo == CblasLower) UL = 'U'; else { cblas_xerbla(2, "cblas_dspmv","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); #endif F77_dspmv(F77_UL, &F77_N, &alpha, AP, X,&F77_incX, &beta, Y, &F77_incY); } else cblas_xerbla(1, "cblas_dspmv", "Illegal Order setting, %d\n", order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_dspr.c000066400000000000000000000032301422157504600211650ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * * cblas_dspr.c * This program is a C interface to dspr. * Written by Keita Teranishi * 4/6/1998 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_dspr(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, f77_int N, double alpha, const double *X, f77_int incX, double *Ap) { char UL; #ifdef F77_CHAR F77_CHAR F77_UL; #else #define F77_UL &UL #endif #ifdef F77_INT F77_INT F77_N=N, F77_incX=incX; #else #define F77_N N #define F77_incX incX #endif extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if (order == CblasColMajor) { if (Uplo == CblasLower) UL = 'L'; else if (Uplo == CblasUpper) UL = 'U'; else { cblas_xerbla(2, "cblas_dspr","Illegal Uplo setting, %d\n",Uplo ); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); #endif F77_dspr(F77_UL, &F77_N, &alpha, X, &F77_incX, Ap); } else if (order == CblasRowMajor) { RowMajorStrg = 1; if (Uplo == CblasLower) UL = 'U'; else if (Uplo == CblasUpper) UL = 'L'; else { cblas_xerbla(2, "cblas_dspr","Illegal Uplo setting, %d\n",Uplo ); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); #endif F77_dspr(F77_UL, &F77_N, &alpha, X, &F77_incX, Ap); } else cblas_xerbla(1, "cblas_dspr", "Illegal Order setting, %d\n", order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_dspr2.c000066400000000000000000000033741422157504600212600ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_dspr2.c * The program is a C interface to dspr2. * * Keita Teranishi 5/20/98 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_dspr2(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, f77_int N, const double alpha, const double *X, f77_int incX, const double *Y, f77_int incY, double *A) { char UL; #ifdef F77_CHAR F77_CHAR F77_UL; #else #define F77_UL &UL #endif #ifdef F77_INT F77_INT F77_N=N, F77_incX=incX, F77_incY=incY; #else #define F77_N N #define F77_incX incX #define F77_incY incY #endif extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if (order == CblasColMajor) { if (Uplo == CblasLower) UL = 'L'; else if (Uplo == CblasUpper) UL = 'U'; else { cblas_xerbla(2, "cblas_dspr2","Illegal Uplo setting, %d\n",Uplo ); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); #endif F77_dspr2(F77_UL, &F77_N, &alpha, X, &F77_incX, Y, &F77_incY, A); } else if (order == CblasRowMajor) { RowMajorStrg = 1; if (Uplo == CblasLower) UL = 'U'; else if (Uplo == CblasUpper) UL = 'L'; else { cblas_xerbla(2, "cblas_dspr2","Illegal Uplo setting, %d\n",Uplo ); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); #endif F77_dspr2(F77_UL, &F77_N, &alpha, X, &F77_incX, Y, &F77_incY, A); } else cblas_xerbla(1, "cblas_dspr2", "Illegal Order setting, %d\n", order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_dswap.c000066400000000000000000000010021422157504600213260ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_dswap.c * * The program is a C interface to dswap. * * Written by Keita Teranishi. 2/11/1998 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_dswap( f77_int N, double *X, f77_int incX, double *Y, f77_int incY) { #ifdef F77_INT F77_INT F77_N=N, F77_incX=incX, F77_incY=incY; #else #define F77_N N #define F77_incX incX #define F77_incY incY #endif F77_dswap( &F77_N, X, &F77_incX, Y, &F77_incY); } #endif blis-0.9.0/frame/compat/cblas/src/cblas_dsymm.c000066400000000000000000000051761422157504600213610ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * * cblas_dsymm.c * This program is a C interface to dsymm. * Written by Keita Teranishi * 4/8/1998 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_dsymm(enum CBLAS_ORDER Order, enum CBLAS_SIDE Side, enum CBLAS_UPLO Uplo, f77_int M, f77_int N, double alpha, const double *A, f77_int lda, const double *B, f77_int ldb, double beta, double *C, f77_int ldc) { char SD, UL; #ifdef F77_CHAR F77_CHAR F77_SD, F77_UL; #else #define F77_SD &SD #define F77_UL &UL #endif #ifdef F77_INT F77_INT F77_M=M, F77_N=N, F77_lda=lda, F77_ldb=ldb; F77_INT F77_ldc=ldc; #else #define F77_M M #define F77_N N #define F77_lda lda #define F77_ldb ldb #define F77_ldc ldc #endif extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if( Order == CblasColMajor ) { if( Side == CblasRight) SD='R'; else if ( Side == CblasLeft ) SD='L'; else { cblas_xerbla(2, "cblas_dsymm","Illegal Side setting, %d\n", Side); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if( Uplo == CblasUpper) UL='U'; else if ( Uplo == CblasLower ) UL='L'; else { cblas_xerbla(3, "cblas_dsymm","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_SD = C2F_CHAR(&SD); #endif F77_dsymm(F77_SD, F77_UL, &F77_M, &F77_N, &alpha, A, &F77_lda, B, &F77_ldb, &beta, C, &F77_ldc); } else if (Order == CblasRowMajor) { RowMajorStrg = 1; if( Side == CblasRight) SD='L'; else if ( Side == CblasLeft ) SD='R'; else { cblas_xerbla(2, "cblas_dsymm","Illegal Side setting, %d\n", Side); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if( Uplo == CblasUpper) UL='L'; else if ( Uplo == CblasLower ) UL='U'; else { cblas_xerbla(3, "cblas_dsymm","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_SD = C2F_CHAR(&SD); #endif F77_dsymm(F77_SD, F77_UL, &F77_N, &F77_M, &alpha, A, &F77_lda, B, &F77_ldb, &beta, C, &F77_ldc); } else cblas_xerbla(1, "cblas_dsymm","Illegal Order setting, %d\n", Order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_dsymv.c000066400000000000000000000036651422157504600213730ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * * cblas_dsymv.c * This program is a C interface to dsymv. * Written by Keita Teranishi * 4/6/1998 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_dsymv(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, f77_int N, double alpha, const double *A, f77_int lda, const double *X, f77_int incX, double beta, double *Y, f77_int incY) { char UL; #ifdef F77_CHAR F77_CHAR F77_UL; #else #define F77_UL &UL #endif #ifdef F77_INT F77_INT F77_N=N, F77_lda=lda, F77_incX=incX, F77_incY=incY; #else #define F77_N N #define F77_lda lda #define F77_incX incX #define F77_incY incY #endif extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if (order == CblasColMajor) { if (Uplo == CblasUpper) UL = 'U'; else if (Uplo == CblasLower) UL = 'L'; else { cblas_xerbla(2, "cblas_dsymv","Illegal Uplo setting, %d\n",Uplo ); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); #endif F77_dsymv(F77_UL, &F77_N, &alpha, A, &F77_lda, X, &F77_incX, &beta, Y, &F77_incY); } else if (order == CblasRowMajor) { RowMajorStrg = 1; if (Uplo == CblasUpper) UL = 'L'; else if (Uplo == CblasLower) UL = 'U'; else { cblas_xerbla(2, "cblas_dsymv","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); #endif F77_dsymv(F77_UL, &F77_N, &alpha, A ,&F77_lda, X,&F77_incX, &beta, Y, &F77_incY); } else cblas_xerbla(1, "cblas_dsymv", "Illegal Order setting, %d\n", order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_dsyr.c000066400000000000000000000033451422157504600212050ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * * cblas_dsyr.c * This program is a C interface to dsyr. * Written by Keita Teranishi * 4/6/1998 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_dsyr(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, f77_int N, const double alpha, const double *X, f77_int incX, double *A, f77_int lda) { char UL; #ifdef F77_CHAR F77_CHAR F77_UL; #else #define F77_UL &UL #endif #ifdef F77_INT F77_INT F77_N=N, F77_incX=incX, F77_lda=lda; #else #define F77_N N #define F77_incX incX #define F77_lda lda #endif extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if (order == CblasColMajor) { if (Uplo == CblasLower) UL = 'L'; else if (Uplo == CblasUpper) UL = 'U'; else { cblas_xerbla(2, "cblas_dsyr","Illegal Uplo setting, %d\n",Uplo ); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); #endif F77_dsyr(F77_UL, &F77_N, &alpha, X, &F77_incX, A, &F77_lda); } else if (order == CblasRowMajor) { RowMajorStrg = 1; if (Uplo == CblasLower) UL = 'U'; else if (Uplo == CblasUpper) UL = 'L'; else { cblas_xerbla(2, "cblas_dsyr","Illegal Uplo setting, %d\n",Uplo ); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); #endif F77_dsyr(F77_UL, &F77_N, &alpha, X, &F77_incX, A, &F77_lda); } else cblas_xerbla(1, "cblas_dsyr", "Illegal Order setting, %d\n", order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_dsyr2.c000066400000000000000000000036141422157504600212660ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * * cblas_dsyr2.c * This program is a C interface to dsyr2. * Written by Keita Teranishi * 4/6/1998 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_dsyr2(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, f77_int N, const double alpha, const double *X, f77_int incX, const double *Y, f77_int incY, double *A, f77_int lda) { char UL; #ifdef F77_CHAR F77_CHAR F77_UL; #else #define F77_UL &UL #endif #ifdef F77_INT F77_INT F77_N=N, F77_incX=incX, F77_incY=incY, F77_lda=lda; #else #define F77_N N #define F77_incX incX #define F77_incY incY #define F77_lda lda #endif extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if (order == CblasColMajor) { if (Uplo == CblasLower) UL = 'L'; else if (Uplo == CblasUpper) UL = 'U'; else { cblas_xerbla(2, "cblas_dsyr2","Illegal Uplo setting, %d\n",Uplo ); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); #endif F77_dsyr2(F77_UL, &F77_N, &alpha, X, &F77_incX, Y, &F77_incY, A, &F77_lda); } else if (order == CblasRowMajor) { RowMajorStrg = 1; if (Uplo == CblasLower) UL = 'U'; else if (Uplo == CblasUpper) UL = 'L'; else { cblas_xerbla(2, "cblas_dsyr2","Illegal Uplo setting, %d\n",Uplo ); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); #endif F77_dsyr2(F77_UL, &F77_N, &alpha, X, &F77_incX, Y, &F77_incY, A, &F77_lda); } else cblas_xerbla(1, "cblas_dsyr2", "Illegal Order setting, %d\n", order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_dsyr2k.c000066400000000000000000000054111422157504600214360ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * * cblas_dsyr2k.c * This program is a C interface to dsyr2k. * Written by Keita Teranishi * 4/6/1998 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_dsyr2k(enum CBLAS_ORDER Order, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE Trans, f77_int N, f77_int K, double alpha, const double *A, f77_int lda, const double *B, f77_int ldb, double beta, double *C, f77_int ldc) { char UL, TR; #ifdef F77_CHAR F77_CHAR F77_TA, F77_UL; #else #define F77_TR &TR #define F77_UL &UL #endif #ifdef F77_INT F77_INT F77_N=N, F77_K=K, F77_lda=lda, F77_ldb=ldb; F77_INT F77_ldc=ldc; #else #define F77_N N #define F77_K K #define F77_lda lda #define F77_ldb ldb #define F77_ldc ldc #endif extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if( Order == CblasColMajor ) { if( Uplo == CblasUpper) UL='U'; else if ( Uplo == CblasLower ) UL='L'; else { cblas_xerbla(2, "cblas_dsyr2k","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if( Trans == CblasTrans) TR ='T'; else if ( Trans == CblasConjTrans ) TR='C'; else if ( Trans == CblasNoTrans ) TR='N'; else { cblas_xerbla(3, "cblas_dsyr2k","Illegal Trans setting, %d\n", Trans); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TR = C2F_CHAR(&TR); #endif F77_dsyr2k(F77_UL, F77_TR, &F77_N, &F77_K, &alpha, A, &F77_lda, B, &F77_ldb, &beta, C, &F77_ldc); } else if (Order == CblasRowMajor) { RowMajorStrg = 1; if( Uplo == CblasUpper) UL='L'; else if ( Uplo == CblasLower ) UL='U'; else { cblas_xerbla(3, "cblas_dsyr2k","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if( Trans == CblasTrans) TR ='N'; else if ( Trans == CblasConjTrans ) TR='N'; else if ( Trans == CblasNoTrans ) TR='T'; else { cblas_xerbla(3, "cblas_dsyr2k","Illegal Trans setting, %d\n", Trans); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TR = C2F_CHAR(&TR); #endif F77_dsyr2k(F77_UL, F77_TR, &F77_N, &F77_K, &alpha, A, &F77_lda, B, &F77_ldb, &beta, C, &F77_ldc); } else cblas_xerbla(1, "cblas_dsyr2k","Illegal Order setting, %d\n", Order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_dsyrk.c000066400000000000000000000052141422157504600213550ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * * cblas_dsyrk.c * This program is a C interface to dsyrk. * Written by Keita Teranishi * 4/8/1998 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_dsyrk(enum CBLAS_ORDER Order, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE Trans, f77_int N, f77_int K, double alpha, const double *A, f77_int lda, double beta, double *C, f77_int ldc) { char UL, TR; #ifdef F77_CHAR F77_CHAR F77_TR, F77_UL; #else #define F77_TR &TR #define F77_UL &UL #endif #ifdef F77_INT F77_INT F77_N=N, F77_K=K, F77_lda=lda; F77_INT F77_ldc=ldc; #else #define F77_N N #define F77_K K #define F77_lda lda #define F77_ldc ldc #endif extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if( Order == CblasColMajor ) { if( Uplo == CblasUpper) UL='U'; else if ( Uplo == CblasLower ) UL='L'; else { cblas_xerbla(2, "cblas_dsyrk","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if( Trans == CblasTrans) TR ='T'; else if ( Trans == CblasConjTrans ) TR='C'; else if ( Trans == CblasNoTrans ) TR='N'; else { cblas_xerbla(3, "cblas_dsyrk","Illegal Trans setting, %d\n", Trans); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TR = C2F_CHAR(&TR); #endif F77_dsyrk(F77_UL, F77_TR, &F77_N, &F77_K, &alpha, A, &F77_lda, &beta, C, &F77_ldc); } else if (Order == CblasRowMajor) { RowMajorStrg = 1; if( Uplo == CblasUpper) UL='L'; else if ( Uplo == CblasLower ) UL='U'; else { cblas_xerbla(3, "cblas_dsyrk","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if( Trans == CblasTrans) TR ='N'; else if ( Trans == CblasConjTrans ) TR='N'; else if ( Trans == CblasNoTrans ) TR='T'; else { cblas_xerbla(3, "cblas_dsyrk","Illegal Trans setting, %d\n", Trans); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TR = C2F_CHAR(&TR); #endif F77_dsyrk(F77_UL, F77_TR, &F77_N, &F77_K, &alpha, A, &F77_lda, &beta, C, &F77_ldc); } else cblas_xerbla(1, "cblas_dsyrk","Illegal Order setting, %d\n", Order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_dtbmv.c000066400000000000000000000063541422157504600213430ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_dtbmv.c * The program is a C interface to dtbmv. * * Keita Teranishi 5/20/98 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_dtbmv(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE TransA, enum CBLAS_DIAG Diag, f77_int N, f77_int K, const double *A, f77_int lda, double *X, f77_int incX) { char TA; char UL; char DI; #ifdef F77_CHAR F77_CHAR F77_TA, F77_UL, F77_DI; #else #define F77_TA &TA #define F77_UL &UL #define F77_DI &DI #endif #ifdef F77_INT F77_INT F77_N=N, F77_lda=lda, F77_K=K, F77_incX=incX; #else #define F77_N N #define F77_K K #define F77_lda lda #define F77_incX incX #endif extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if (order == CblasColMajor) { if (Uplo == CblasUpper) UL = 'U'; else if (Uplo == CblasLower) UL = 'L'; else { cblas_xerbla(2, "cblas_dtbmv","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (TransA == CblasNoTrans) TA = 'N'; else if (TransA == CblasTrans) TA = 'T'; else if (TransA == CblasConjTrans) TA = 'C'; else { cblas_xerbla(3, "cblas_dtbmv","Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (Diag == CblasUnit) DI = 'U'; else if (Diag == CblasNonUnit) DI = 'N'; else { cblas_xerbla(4, "cblas_dtbmv","Illegal Diag setting, %d\n", Diag); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TA = C2F_CHAR(&TA); F77_DI = C2F_CHAR(&DI); #endif F77_dtbmv( F77_UL, F77_TA, F77_DI, &F77_N, &F77_K, A, &F77_lda, X, &F77_incX); } else if (order == CblasRowMajor) { RowMajorStrg = 1; if (Uplo == CblasUpper) UL = 'L'; else if (Uplo == CblasLower) UL = 'U'; else { cblas_xerbla(2, "cblas_dtbmv","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (TransA == CblasNoTrans) TA = 'T'; else if (TransA == CblasTrans) TA = 'N'; else if (TransA == CblasConjTrans) TA = 'N'; else { cblas_xerbla(3, "cblas_dtbmv","Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (Diag == CblasUnit) DI = 'U'; else if (Diag == CblasNonUnit) DI = 'N'; else { cblas_xerbla(4, "cblas_dtbmv","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TA = C2F_CHAR(&TA); F77_DI = C2F_CHAR(&DI); #endif F77_dtbmv( F77_UL, F77_TA, F77_DI, &F77_N, &F77_K, A, &F77_lda, X, &F77_incX); } else cblas_xerbla(1, "cblas_dtbmv", "Illegal Order setting, %d\n", order); CBLAS_CallFromC = 0; RowMajorStrg = 0; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_dtbsv.c000066400000000000000000000063661422157504600213540ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_dtbsv.c * The program is a C interface to dtbsv. * * Keita Teranishi 5/20/98 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_dtbsv(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE TransA, enum CBLAS_DIAG Diag, f77_int N, f77_int K, const double *A, f77_int lda, double *X, f77_int incX) { char TA; char UL; char DI; #ifdef F77_CHAR F77_CHAR F77_TA, F77_UL, F77_DI; #else #define F77_TA &TA #define F77_UL &UL #define F77_DI &DI #endif #ifdef F77_INT F77_INT F77_N=N, F77_lda=lda, F77_K=K, F77_incX=incX; #else #define F77_N N #define F77_K K #define F77_lda lda #define F77_incX incX #endif extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if (order == CblasColMajor) { if (Uplo == CblasUpper) UL = 'U'; else if (Uplo == CblasLower) UL = 'L'; else { cblas_xerbla(2, "cblas_dtbsv","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (TransA == CblasNoTrans) TA = 'N'; else if (TransA == CblasTrans) TA = 'T'; else if (TransA == CblasConjTrans) TA = 'C'; else { cblas_xerbla(3, "cblas_dtbsv","Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (Diag == CblasUnit) DI = 'U'; else if (Diag == CblasNonUnit) DI = 'N'; else { cblas_xerbla(4, "cblas_dtbsv","Illegal Diag setting, %d\n", Diag); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TA = C2F_CHAR(&TA); F77_DI = C2F_CHAR(&DI); #endif F77_dtbsv( F77_UL, F77_TA, F77_DI, &F77_N, &F77_K, A, &F77_lda, X, &F77_incX); } else if (order == CblasRowMajor) { RowMajorStrg = 1; if (Uplo == CblasUpper) UL = 'L'; else if (Uplo == CblasLower) UL = 'U'; else { cblas_xerbla(2, "cblas_dtbsv","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (TransA == CblasNoTrans) TA = 'T'; else if (TransA == CblasTrans) TA = 'N'; else if (TransA == CblasConjTrans) TA = 'N'; else { cblas_xerbla(3, "cblas_dtbsv","Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (Diag == CblasUnit) DI = 'U'; else if (Diag == CblasNonUnit) DI = 'N'; else { cblas_xerbla(4, "cblas_dtbsv","Illegal Diag setting, %d\n", Diag); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TA = C2F_CHAR(&TA); F77_DI = C2F_CHAR(&DI); #endif F77_dtbsv( F77_UL, F77_TA, F77_DI, &F77_N, &F77_K, A, &F77_lda, X, &F77_incX); } else cblas_xerbla(1, "cblas_dtbsv", "Illegal Order setting, %d\n", order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_dtpmv.c000066400000000000000000000060771422157504600213630ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_dtpmv.c * The program is a C interface to dtpmv. * * Keita Teranishi 5/20/98 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_dtpmv(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE TransA, enum CBLAS_DIAG Diag, f77_int N, const double *Ap, double *X, f77_int incX) { char TA; char UL; char DI; #ifdef F77_CHAR F77_CHAR F77_TA, F77_UL, F77_DI; #else #define F77_TA &TA #define F77_UL &UL #define F77_DI &DI #endif #ifdef F77_INT F77_INT F77_N=N, F77_incX=incX; #else #define F77_N N #define F77_incX incX #endif extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if (order == CblasColMajor) { if (Uplo == CblasUpper) UL = 'U'; else if (Uplo == CblasLower) UL = 'L'; else { cblas_xerbla(2, "cblas_dtpmv","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (TransA == CblasNoTrans) TA = 'N'; else if (TransA == CblasTrans) TA = 'T'; else if (TransA == CblasConjTrans) TA = 'C'; else { cblas_xerbla(3, "cblas_dtpmv","Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (Diag == CblasUnit) DI = 'U'; else if (Diag == CblasNonUnit) DI = 'N'; else { cblas_xerbla(4, "cblas_dtpmv","Illegal Diag setting, %d\n", Diag); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TA = C2F_CHAR(&TA); F77_DI = C2F_CHAR(&DI); #endif F77_dtpmv( F77_UL, F77_TA, F77_DI, &F77_N, Ap, X, &F77_incX); } else if (order == CblasRowMajor) { RowMajorStrg = 1; if (Uplo == CblasUpper) UL = 'L'; else if (Uplo == CblasLower) UL = 'U'; else { cblas_xerbla(2, "cblas_dtpmv","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (TransA == CblasNoTrans) TA = 'T'; else if (TransA == CblasTrans) TA = 'N'; else if (TransA == CblasConjTrans) TA = 'N'; else { cblas_xerbla(3, "cblas_dtpmv","Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (Diag == CblasUnit) DI = 'U'; else if (Diag == CblasNonUnit) DI = 'N'; else { cblas_xerbla(4, "cblas_dtpmv","Illegal Diag setting, %d\n", Diag); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TA = C2F_CHAR(&TA); F77_DI = C2F_CHAR(&DI); #endif F77_dtpmv( F77_UL, F77_TA, F77_DI, &F77_N, Ap, X,&F77_incX); } else cblas_xerbla(1, "cblas_dtpmv", "Illegal Order setting, %d\n", order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_dtpsv.c000066400000000000000000000061001422157504600213540ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_dtpsv.c * The program is a C interface to dtpsv. * * Keita Teranishi 5/20/98 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_dtpsv(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE TransA, enum CBLAS_DIAG Diag, f77_int N, const double *Ap, double *X, f77_int incX) { char TA; char UL; char DI; #ifdef F77_CHAR F77_CHAR F77_TA, F77_UL, F77_DI; #else #define F77_TA &TA #define F77_UL &UL #define F77_DI &DI #endif #ifdef F77_INT F77_INT F77_N=N, F77_incX=incX; #else #define F77_N N #define F77_incX incX #endif extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if (order == CblasColMajor) { if (Uplo == CblasUpper) UL = 'U'; else if (Uplo == CblasLower) UL = 'L'; else { cblas_xerbla(2, "cblas_dtpsv","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (TransA == CblasNoTrans) TA = 'N'; else if (TransA == CblasTrans) TA = 'T'; else if (TransA == CblasConjTrans) TA = 'C'; else { cblas_xerbla(3, "cblas_dtpsv","Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (Diag == CblasUnit) DI = 'U'; else if (Diag == CblasNonUnit) DI = 'N'; else { cblas_xerbla(4, "cblas_dtpsv","Illegal Diag setting, %d\n", Diag); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TA = C2F_CHAR(&TA); F77_DI = C2F_CHAR(&DI); #endif F77_dtpsv( F77_UL, F77_TA, F77_DI, &F77_N, Ap, X, &F77_incX); } else if (order == CblasRowMajor) { RowMajorStrg = 1; if (Uplo == CblasUpper) UL = 'L'; else if (Uplo == CblasLower) UL = 'U'; else { cblas_xerbla(2, "cblas_dtpsv","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (TransA == CblasNoTrans) TA = 'T'; else if (TransA == CblasTrans) TA = 'N'; else if (TransA == CblasConjTrans) TA = 'N'; else { cblas_xerbla(3, "cblas_dtpsv","Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (Diag == CblasUnit) DI = 'U'; else if (Diag == CblasNonUnit) DI = 'N'; else { cblas_xerbla(4, "cblas_dtpsv","Illegal Diag setting, %d\n", Diag); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TA = C2F_CHAR(&TA); F77_DI = C2F_CHAR(&DI); #endif F77_dtpsv( F77_UL, F77_TA, F77_DI, &F77_N, Ap, X,&F77_incX); } else cblas_xerbla(1, "cblas_dtpsv", "Illegal Order setting, %d\n", order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_dtrmm.c000066400000000000000000000076151422157504600213530ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * * cblas_dtrmm.c * This program is a C interface to dtrmm. * Written by Keita Teranishi * 4/6/1998 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_dtrmm(enum CBLAS_ORDER Order, enum CBLAS_SIDE Side, enum CBLAS_UPLO Uplo, const enum CBLAS_TRANSPOSE TransA, enum CBLAS_DIAG Diag, f77_int M, f77_int N, double alpha, const double *A, f77_int lda, double *B, f77_int ldb) { char UL, TA, SD, DI; #ifdef F77_CHAR F77_CHAR F77_TA, F77_UL, F77_SD, F77_DI; #else #define F77_TA &TA #define F77_UL &UL #define F77_SD &SD #define F77_DI &DI #endif #ifdef F77_INT F77_INT F77_M=M, F77_N=N, F77_lda=lda, F77_ldb=ldb; #else #define F77_M M #define F77_N N #define F77_lda lda #define F77_ldb ldb #endif extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if( Order == CblasColMajor ) { if( Side == CblasRight) SD='R'; else if ( Side == CblasLeft ) SD='L'; else { cblas_xerbla(2, "cblas_dtrmm","Illegal Side setting, %d\n", Side); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if( Uplo == CblasUpper) UL='U'; else if ( Uplo == CblasLower ) UL='L'; else { cblas_xerbla(3, "cblas_dtrmm","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if( TransA == CblasTrans) TA ='T'; else if ( TransA == CblasConjTrans ) TA='C'; else if ( TransA == CblasNoTrans ) TA='N'; else { cblas_xerbla(4, "cblas_dtrmm","Illegal Trans setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if( Diag == CblasUnit ) DI='U'; else if ( Diag == CblasNonUnit ) DI='N'; else { cblas_xerbla(5, "cblas_dtrmm","Illegal Diag setting, %d\n", Diag); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TA = C2F_CHAR(&TA); F77_SD = C2F_CHAR(&SD); F77_DI = C2F_CHAR(&DI); #endif F77_dtrmm(F77_SD, F77_UL, F77_TA, F77_DI, &F77_M, &F77_N, &alpha, A, &F77_lda, B, &F77_ldb); } else if (Order == CblasRowMajor) { RowMajorStrg = 1; if( Side == CblasRight) SD='L'; else if ( Side == CblasLeft ) SD='R'; else { cblas_xerbla(2, "cblas_dtrmm","Illegal Side setting, %d\n", Side); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if( Uplo == CblasUpper) UL='L'; else if ( Uplo == CblasLower ) UL='U'; else { cblas_xerbla(3, "cblas_dtrmm","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if( TransA == CblasTrans) TA ='T'; else if ( TransA == CblasConjTrans ) TA='C'; else if ( TransA == CblasNoTrans ) TA='N'; else { cblas_xerbla(4, "cblas_dtrmm","Illegal Trans setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if( Diag == CblasUnit ) DI='U'; else if ( Diag == CblasNonUnit ) DI='N'; else { cblas_xerbla(5, "cblas_dtrmm","Illegal Diag setting, %d\n", Diag); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TA = C2F_CHAR(&TA); F77_SD = C2F_CHAR(&SD); F77_DI = C2F_CHAR(&DI); #endif F77_dtrmm(F77_SD, F77_UL, F77_TA, F77_DI, &F77_N, &F77_M, &alpha, A, &F77_lda, B, &F77_ldb); } else cblas_xerbla(1, "cblas_dtrmm", "Illegal Order setting, %d\n", Order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_dtrmv.c000066400000000000000000000063151422157504600213600ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * * cblas_dtrmv.c * This program is a C interface to sgemv. * Written by Keita Teranishi * 4/6/1998 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_dtrmv(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE TransA, enum CBLAS_DIAG Diag, f77_int N, const double *A, f77_int lda, double *X, f77_int incX) { char TA; char UL; char DI; #ifdef F77_CHAR F77_CHAR F77_TA, F77_UL, F77_DI; #else #define F77_TA &TA #define F77_UL &UL #define F77_DI &DI #endif #ifdef F77_INT F77_INT F77_N=N, F77_lda=lda, F77_incX=incX; #else #define F77_N N #define F77_lda lda #define F77_incX incX #endif extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if (order == CblasColMajor) { if (Uplo == CblasUpper) UL = 'U'; else if (Uplo == CblasLower) UL = 'L'; else { cblas_xerbla(2, "cblas_dtrmv","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (TransA == CblasNoTrans) TA = 'N'; else if (TransA == CblasTrans) TA = 'T'; else if (TransA == CblasConjTrans) TA = 'C'; else { cblas_xerbla(3, "cblas_dtrmv","Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (Diag == CblasUnit) DI = 'U'; else if (Diag == CblasNonUnit) DI = 'N'; else { cblas_xerbla(4, "cblas_dtrmv","Illegal Diag setting, %d\n", Diag); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TA = C2F_CHAR(&TA); F77_DI = C2F_CHAR(&DI); #endif F77_dtrmv( F77_UL, F77_TA, F77_DI, &F77_N, A, &F77_lda, X, &F77_incX); } else if (order == CblasRowMajor) { RowMajorStrg = 1; if (Uplo == CblasUpper) UL = 'L'; else if (Uplo == CblasLower) UL = 'U'; else { cblas_xerbla(2, "cblas_dtrmv","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (TransA == CblasNoTrans) TA = 'T'; else if (TransA == CblasTrans) TA = 'N'; else if (TransA == CblasConjTrans) TA = 'N'; else { cblas_xerbla(3, "cblas_dtrmv","Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (Diag == CblasUnit) DI = 'U'; else if (Diag == CblasNonUnit) DI = 'N'; else { cblas_xerbla(4, "cblas_dtrmv","Illegal Diag setting, %d\n", Diag); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TA = C2F_CHAR(&TA); F77_DI = C2F_CHAR(&DI); #endif F77_dtrmv( F77_UL, F77_TA, F77_DI, &F77_N, A, &F77_lda, X, &F77_incX); } else cblas_xerbla(1, "cblas_dtrmv", "Illegal order setting, %d\n", order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_dtrsm.c000066400000000000000000000077351422157504600213640ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * * cblas_dtrsm.c * This program is a C interface to dtrsm. * Written by Keita Teranishi * 4/6/1998 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_dtrsm(enum CBLAS_ORDER Order, enum CBLAS_SIDE Side, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE TransA, enum CBLAS_DIAG Diag, f77_int M, f77_int N, double alpha, const double *A, f77_int lda, double *B, f77_int ldb) { char UL, TA, SD, DI; #ifdef F77_CHAR F77_CHAR F77_TA, F77_UL, F77_SD, F77_DI; #else #define F77_TA &TA #define F77_UL &UL #define F77_SD &SD #define F77_DI &DI #endif #ifdef F77_INT F77_INT F77_M=M, F77_N=N, F77_lda=lda, F77_ldb=ldb; #else #define F77_M M #define F77_N N #define F77_lda lda #define F77_ldb ldb #endif extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if( Order == CblasColMajor ) { if ( Side == CblasRight) SD='R'; else if ( Side == CblasLeft ) SD='L'; else { cblas_xerbla(2, "cblas_dtrsm","Illegal Side setting, %d\n", Side); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if ( Uplo == CblasUpper) UL='U'; else if ( Uplo == CblasLower) UL='L'; else { cblas_xerbla(3, "cblas_dtrsm","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if ( TransA == CblasTrans ) TA='T'; else if ( TransA == CblasConjTrans) TA='C'; else if ( TransA == CblasNoTrans ) TA='N'; else { cblas_xerbla(4, "cblas_dtrsm","Illegal Trans setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if ( Diag == CblasUnit ) DI='U'; else if ( Diag == CblasNonUnit) DI='N'; else { cblas_xerbla(5, "cblas_dtrsm","Illegal Diag setting, %d\n", Diag); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TA = C2F_CHAR(&TA); F77_SD = C2F_CHAR(&SD); F77_DI = C2F_CHAR(&DI); #endif F77_dtrsm(F77_SD, F77_UL, F77_TA, F77_DI, &F77_M, &F77_N, &alpha, A, &F77_lda, B, &F77_ldb); } else if (Order == CblasRowMajor) { RowMajorStrg = 1; if ( Side == CblasRight) SD='L'; else if ( Side == CblasLeft ) SD='R'; else { cblas_xerbla(2, "cblas_dtrsm","Illegal Side setting, %d\n", Side); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if ( Uplo == CblasUpper) UL='L'; else if ( Uplo == CblasLower) UL='U'; else { cblas_xerbla(3, "cblas_dtrsm","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if ( TransA == CblasTrans ) TA='T'; else if ( TransA == CblasConjTrans) TA='C'; else if ( TransA == CblasNoTrans ) TA='N'; else { cblas_xerbla(4, "cblas_dtrsm","Illegal Trans setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if ( Diag == CblasUnit ) DI='U'; else if ( Diag == CblasNonUnit) DI='N'; else { cblas_xerbla(5, "cblas_dtrsm","Illegal Diag setting, %d\n", Diag); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TA = C2F_CHAR(&TA); F77_SD = C2F_CHAR(&SD); F77_DI = C2F_CHAR(&DI); #endif F77_dtrsm(F77_SD, F77_UL, F77_TA, F77_DI, &F77_N, &F77_M, &alpha, A, &F77_lda, B, &F77_ldb); } else cblas_xerbla(1, "cblas_dtrsm","Illegal Order setting, %d\n", Order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_dtrsv.c000066400000000000000000000062771422157504600213750ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_dtrsv.c * The program is a C interface to dtrsv. * * Keita Teranishi 5/20/98 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_dtrsv(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE TransA, enum CBLAS_DIAG Diag, f77_int N, const double *A, f77_int lda, double *X, f77_int incX) { char TA; char UL; char DI; #ifdef F77_CHAR F77_CHAR F77_TA, F77_UL, F77_DI; #else #define F77_TA &TA #define F77_UL &UL #define F77_DI &DI #endif #ifdef F77_INT F77_INT F77_N=N, F77_lda=lda, F77_incX=incX; #else #define F77_N N #define F77_lda lda #define F77_incX incX #endif extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if (order == CblasColMajor) { if (Uplo == CblasUpper) UL = 'U'; else if (Uplo == CblasLower) UL = 'L'; else { cblas_xerbla(2, "cblas_dtrsv","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (TransA == CblasNoTrans) TA = 'N'; else if (TransA == CblasTrans) TA = 'T'; else if (TransA == CblasConjTrans) TA = 'C'; else { cblas_xerbla(3, "cblas_dtrsv","Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (Diag == CblasUnit) DI = 'U'; else if (Diag == CblasNonUnit) DI = 'N'; else { cblas_xerbla(4, "cblas_dtrsv","Illegal Diag setting, %d\n", Diag); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TA = C2F_CHAR(&TA); F77_DI = C2F_CHAR(&DI); #endif F77_dtrsv( F77_UL, F77_TA, F77_DI, &F77_N, A, &F77_lda, X, &F77_incX); } else if (order == CblasRowMajor) { RowMajorStrg = 1; if (Uplo == CblasUpper) UL = 'L'; else if (Uplo == CblasLower) UL = 'U'; else { cblas_xerbla(2, "cblas_dtrsv","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (TransA == CblasNoTrans) TA = 'T'; else if (TransA == CblasTrans) TA = 'N'; else if (TransA == CblasConjTrans) TA = 'N'; else { cblas_xerbla(3, "cblas_dtrsv","Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (Diag == CblasUnit) DI = 'U'; else if (Diag == CblasNonUnit) DI = 'N'; else { cblas_xerbla(4, "cblas_dtrsv","Illegal Diag setting, %d\n", Diag); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TA = C2F_CHAR(&TA); F77_DI = C2F_CHAR(&DI); #endif F77_dtrsv( F77_UL, F77_TA, F77_DI, &F77_N, A, &F77_lda, X, &F77_incX); } else cblas_xerbla(1, "cblas_dtrsv", "Illegal Order setting, %d\n", order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_dzasum.c000066400000000000000000000010111422157504600215130ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_dzasum.c * * The program is a C interface to dzasum. * It calls the fortran wrapper before calling dzasum. * * Written by Keita Teranishi. 2/11/1998 * */ #include "cblas.h" #include "cblas_f77.h" double cblas_dzasum( f77_int N, const void *X, f77_int incX) { double asum; #ifdef F77_INT F77_INT F77_N=N, F77_incX=incX; #else #define F77_N N #define F77_incX incX #endif F77_dzasum_sub( &F77_N, X, &F77_incX, &asum); return asum; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_dznrm2.c000066400000000000000000000010111422157504600214240ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_dznrm2.c * * The program is a C interface to dznrm2. * It calls the fortran wrapper before calling dznrm2. * * Written by Keita Teranishi. 2/11/1998 * */ #include "cblas.h" #include "cblas_f77.h" double cblas_dznrm2( f77_int N, const void *X, f77_int incX) { double nrm2; #ifdef F77_INT F77_INT F77_N=N, F77_incX=incX; #else #define F77_N N #define F77_incX incX #endif F77_dznrm2_sub( &F77_N, X, &F77_incX, &nrm2); return nrm2; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_f77.h000066400000000000000000000143401422157504600206310ustar00rootroot00000000000000/* cblas_f77.h Written by Keita Teranishi Updated by Jeff Horner Merged cblas_f77.h and cblas_fortran_header.h (Heavily hacked down from the original) */ /* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef CBLAS_F77_H #define CBLAS_F77_H /* * Level 1 BLAS */ #define F77_xerbla xerbla_ #define F77_srotg srotg_ #define F77_srotmg srotmg_ #define F77_srot srot_ #define F77_srotm srotm_ #define F77_drotg drotg_ #define F77_drotmg drotmg_ #define F77_drot drot_ #define F77_drotm drotm_ #define F77_sswap sswap_ #define F77_scopy scopy_ #define F77_saxpy saxpy_ #define F77_isamax_sub isamaxsub_ #define F77_dswap dswap_ #define F77_dcopy dcopy_ #define F77_daxpy daxpy_ #define F77_idamax_sub idamaxsub_ #define F77_cswap cswap_ #define F77_ccopy ccopy_ #define F77_caxpy caxpy_ #define F77_icamax_sub icamaxsub_ #define F77_zswap zswap_ #define F77_zcopy zcopy_ #define F77_zaxpy zaxpy_ #define F77_izamax_sub izamaxsub_ #define F77_sdot_sub sdotsub_ #define F77_ddot_sub ddotsub_ #define F77_dsdot_sub dsdotsub_ #define F77_sscal sscal_ #define F77_dscal dscal_ #define F77_cscal cscal_ #define F77_zscal zscal_ #define F77_csscal csscal_ #define F77_zdscal zdscal_ #define F77_cdotu_sub cdotusub_ #define F77_cdotc_sub cdotcsub_ #define F77_zdotu_sub zdotusub_ #define F77_zdotc_sub zdotcsub_ #define F77_snrm2_sub snrm2sub_ #define F77_sasum_sub sasumsub_ #define F77_dnrm2_sub dnrm2sub_ #define F77_dasum_sub dasumsub_ #define F77_scnrm2_sub scnrm2sub_ #define F77_scasum_sub scasumsub_ #define F77_dznrm2_sub dznrm2sub_ #define F77_dzasum_sub dzasumsub_ #define F77_sdsdot_sub sdsdotsub_ /* * Level 2 BLAS */ #define F77_ssymv ssymv_ #define F77_ssbmv ssbmv_ #define F77_sspmv sspmv_ #define F77_sger sger_ #define F77_ssyr ssyr_ #define F77_sspr sspr_ #define F77_ssyr2 ssyr2_ #define F77_sspr2 sspr2_ #define F77_dsymv dsymv_ #define F77_dsbmv dsbmv_ #define F77_dspmv dspmv_ #define F77_dger dger_ #define F77_dsyr dsyr_ #define F77_dspr dspr_ #define F77_dsyr2 dsyr2_ #define F77_dspr2 dspr2_ #define F77_chemv chemv_ #define F77_chbmv chbmv_ #define F77_chpmv chpmv_ #define F77_cgeru cgeru_ #define F77_cgerc cgerc_ #define F77_cher cher_ #define F77_chpr chpr_ #define F77_cher2 cher2_ #define F77_chpr2 chpr2_ #define F77_zhemv zhemv_ #define F77_zhbmv zhbmv_ #define F77_zhpmv zhpmv_ #define F77_zgeru zgeru_ #define F77_zgerc zgerc_ #define F77_zher zher_ #define F77_zhpr zhpr_ #define F77_zher2 zher2_ #define F77_zhpr2 zhpr2_ #define F77_sgemv sgemv_ #define F77_sgbmv sgbmv_ #define F77_strmv strmv_ #define F77_stbmv stbmv_ #define F77_stpmv stpmv_ #define F77_strsv strsv_ #define F77_stbsv stbsv_ #define F77_stpsv stpsv_ #define F77_dgemv dgemv_ #define F77_dgbmv dgbmv_ #define F77_dtrmv dtrmv_ #define F77_dtbmv dtbmv_ #define F77_dtpmv dtpmv_ #define F77_dtrsv dtrsv_ #define F77_dtbsv dtbsv_ #define F77_dtpsv dtpsv_ #define F77_cgemv cgemv_ #define F77_cgbmv cgbmv_ #define F77_ctrmv ctrmv_ #define F77_ctbmv ctbmv_ #define F77_ctpmv ctpmv_ #define F77_ctrsv ctrsv_ #define F77_ctbsv ctbsv_ #define F77_ctpsv ctpsv_ #define F77_zgemv zgemv_ #define F77_zgbmv zgbmv_ #define F77_ztrmv ztrmv_ #define F77_ztbmv ztbmv_ #define F77_ztpmv ztpmv_ #define F77_ztrsv ztrsv_ #define F77_ztbsv ztbsv_ #define F77_ztpsv ztpsv_ /* * Level 3 BLAS */ #define F77_chemm chemm_ #define F77_cherk cherk_ #define F77_cher2k cher2k_ #define F77_zhemm zhemm_ #define F77_zherk zherk_ #define F77_zher2k zher2k_ #define F77_sgemm sgemm_ #define F77_ssymm ssymm_ #define F77_ssyrk ssyrk_ #define F77_ssyr2k ssyr2k_ #define F77_strmm strmm_ #define F77_strsm strsm_ #define F77_dgemm dgemm_ #define F77_dsymm dsymm_ #define F77_dsyrk dsyrk_ #define F77_dsyr2k dsyr2k_ #define F77_dtrmm dtrmm_ #define F77_dtrsm dtrsm_ #define F77_cgemm cgemm_ #define F77_csymm csymm_ #define F77_csyrk csyrk_ #define F77_csyr2k csyr2k_ #define F77_ctrmm ctrmm_ #define F77_ctrsm ctrsm_ #define F77_zgemm zgemm_ #define F77_zsymm zsymm_ #define F77_zsyrk zsyrk_ #define F77_zsyr2k zsyr2k_ #define F77_ztrmm ztrmm_ #define F77_ztrsm ztrsm_ /* * BLAS extensions */ #define F77_saxpby saxpby_ #define F77_daxpby daxpby_ #define F77_caxpby caxpby_ #define F77_zaxpby zaxpby_ #define F77_sgemmt sgemmt_ #define F77_dgemmt dgemmt_ #define F77_cgemmt cgemmt_ #define F77_zgemmt zgemmt_ #define F77_sgemm_batch sgemm_batch_ #define F77_dgemm_batch dgemm_batch_ #define F77_cgemm_batch cgemm_batch_ #define F77_zgemm_batch zgemm_batch_ #define F77_cgemm3m cgemm3m_ #define F77_zgemm3m zgemm3m_ #endif /* CBLAS_F77_H */ blis-0.9.0/frame/compat/cblas/src/cblas_globals.c000066400000000000000000000001351422157504600216410ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS int CBLAS_CallFromC=0; int RowMajorStrg=0; #endif blis-0.9.0/frame/compat/cblas/src/cblas_icamax.c000066400000000000000000000010461422157504600214620ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_icamax.c * * The program is a C interface to icamax. * It calls the fortran wrapper before calling icamax. * * Written by Keita Teranishi. 2/11/1998 * */ #include "cblas.h" #include "cblas_f77.h" f77_int cblas_icamax( f77_int N, const void *X, f77_int incX) { f77_int iamax; #ifdef F77_INT F77_INT F77_N=N, F77_incX=incX; #else #define F77_N N #define F77_incX incX #endif F77_icamax_sub( &F77_N, (scomplex*)X, &F77_incX, &iamax); return iamax ? iamax-1 : 0; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_idamax.c000066400000000000000000000010351422157504600214610ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_idamax.c * * The program is a C interface to idamax. * It calls the fortran wrapper before calling idamax. * * Written by Keita Teranishi. 2/11/1998 * */ #include "cblas.h" #include "cblas_f77.h" f77_int cblas_idamax( f77_int N, const double *X, f77_int incX) { f77_int iamax; #ifdef F77_INT F77_INT F77_N=N, F77_incX=incX; #else #define F77_N N #define F77_incX incX #endif F77_idamax_sub( &F77_N, X, &F77_incX, &iamax); return iamax ? iamax-1 : 0; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_isamax.c000066400000000000000000000010341422157504600214770ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_isamax.c * * The program is a C interface to isamax. * It calls the fortran wrapper before calling isamax. * * Written by Keita Teranishi. 2/11/1998 * */ #include "cblas.h" #include "cblas_f77.h" f77_int cblas_isamax( f77_int N, const float *X, f77_int incX) { f77_int iamax; #ifdef F77_INT F77_INT F77_N=N, F77_incX=incX; #else #define F77_N N #define F77_incX incX #endif F77_isamax_sub( &F77_N, X, &F77_incX, &iamax); return iamax ? iamax-1 : 0; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_izamax.c000066400000000000000000000010501422157504600215040ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_izamax.c * * The program is a C interface to izamax. * It calls the fortran wrapper before calling izamax. * * Written by Keita Teranishi. 2/11/1998 * */ #include "cblas.h" #include "cblas_f77.h" f77_int cblas_izamax( f77_int N, const void *X, f77_int incX) { f77_int iamax; #ifdef F77_INT F77_INT F77_N=N, F77_incX=incX; #else #define F77_N N #define F77_incX incX #endif F77_izamax_sub( &F77_N, (dcomplex*)X, &F77_incX, &iamax); return (iamax ? iamax-1 : 0); } #endif blis-0.9.0/frame/compat/cblas/src/cblas_sasum.c000066400000000000000000000010031422157504600213410ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_sasum.c * * The program is a C interface to sasum. * It calls the fortran wrapper before calling sasum. * * Written by Keita Teranishi. 2/11/1998 * */ #include "cblas.h" #include "cblas_f77.h" float cblas_sasum( f77_int N, const float *X, f77_int incX) { float asum; #ifdef F77_INT F77_INT F77_N=N, F77_incX=incX; #else #define F77_N N #define F77_incX incX #endif F77_sasum_sub( &F77_N, X, &F77_incX, &asum); return asum; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_saxpy.c000066400000000000000000000011221422157504600213570ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_saxpy.c * * The program is a C interface to saxpy. * It calls the fortran wrapper before calling saxpy. * * Written by Keita Teranishi. 2/11/1998 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_saxpy( f77_int N, float alpha, const float *X, f77_int incX, float *Y, f77_int incY) { #ifdef F77_INT F77_INT F77_N=N, F77_incX=incX, F77_incY=incY; #else #define F77_N N #define F77_incX incX #define F77_incY incY #endif F77_saxpy( &F77_N, &alpha, X, &F77_incX, Y, &F77_incY); } #endif blis-0.9.0/frame/compat/cblas/src/cblas_scasum.c000066400000000000000000000010071422157504600215100ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_scasum.c * * The program is a C interface to scasum. * It calls the fortran wrapper before calling scasum. * * Written by Keita Teranishi. 2/11/1998 * */ #include "cblas.h" #include "cblas_f77.h" float cblas_scasum( f77_int N, const void *X, f77_int incX) { float asum; #ifdef F77_INT F77_INT F77_N=N, F77_incX=incX; #else #define F77_N N #define F77_incX incX #endif F77_scasum_sub( &F77_N, X, &F77_incX, &asum); return asum; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_scnrm2.c000066400000000000000000000010071422157504600214210ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_scnrm2.c * * The program is a C interface to scnrm2. * It calls the fortran wrapper before calling scnrm2. * * Written by Keita Teranishi. 2/11/1998 * */ #include "cblas.h" #include "cblas_f77.h" float cblas_scnrm2( f77_int N, const void *X, f77_int incX) { float nrm2; #ifdef F77_INT F77_INT F77_N=N, F77_incX=incX; #else #define F77_N N #define F77_incX incX #endif F77_scnrm2_sub( &F77_N, X, &F77_incX, &nrm2); return nrm2; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_scopy.c000066400000000000000000000010051422157504600213500ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_scopy.c * * The program is a C interface to scopy. * * Written by Keita Teranishi. 2/11/1998 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_scopy( f77_int N, const float *X, f77_int incX, float *Y, f77_int incY) { #ifdef F77_INT F77_INT F77_N=N, F77_incX=incX, F77_incY=incY; #else #define F77_N N #define F77_incX incX #define F77_incY incY #endif F77_scopy( &F77_N, X, &F77_incX, Y, &F77_incY); } #endif blis-0.9.0/frame/compat/cblas/src/cblas_sdot.c000066400000000000000000000011471422157504600211730ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_sdot.c * * The program is a C interface to sdot. * It calls the fortran wrapper before calling sdot. * * Written by Keita Teranishi. 2/11/1998 * */ #include "cblas.h" #include "cblas_f77.h" float cblas_sdot( f77_int N, const float *X, f77_int incX, const float *Y, f77_int incY) { float dot; #ifdef F77_INT F77_INT F77_N=N, F77_incX=incX, F77_incY=incY; #else #define F77_N N #define F77_incX incX #define F77_incY incY #endif F77_sdot_sub( &F77_N, X, &F77_incX, Y, &F77_incY, &dot); return dot; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_sdsdot.c000066400000000000000000000012061422157504600215160ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_sdsdot.c * * The program is a C interface to sdsdot. * It calls the fortran wrapper before calling sdsdot. * * Written by Keita Teranishi. 2/11/1998 * */ #include "cblas.h" #include "cblas_f77.h" float cblas_sdsdot( f77_int N, float alpha, const float *X, f77_int incX, const float *Y, f77_int incY) { float dot; #ifdef F77_INT F77_INT F77_N=N, F77_incX=incX, F77_incY=incY; #else #define F77_N N #define F77_incX incX #define F77_incY incY #endif F77_sdsdot_sub( &F77_N, &alpha, X, &F77_incX, Y, &F77_incY, &dot); return dot; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_sgbmv.c000066400000000000000000000043771422157504600213500ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * * cblas_sgbmv.c * This program is a C interface to sgbmv. * Written by Keita Teranishi * 4/6/1998 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_sgbmv(enum CBLAS_ORDER order, enum CBLAS_TRANSPOSE TransA, f77_int M, f77_int N, f77_int KL, f77_int KU, float alpha, const float *A, f77_int lda, const float *X, f77_int incX, float beta, float *Y, f77_int incY) { char TA; #ifdef F77_CHAR F77_CHAR F77_TA; #else #define F77_TA &TA #endif #ifdef F77_INT F77_INT F77_M=M, F77_N=N, F77_lda=lda, F77_incX=incX, F77_incY=incY; F77_INT F77_KL=KL,F77_KU=KU; #else #define F77_M M #define F77_N N #define F77_lda lda #define F77_KL KL #define F77_KU KU #define F77_incX incX #define F77_incY incY #endif extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if (order == CblasColMajor) { if (TransA == CblasNoTrans) TA = 'N'; else if (TransA == CblasTrans) TA = 'T'; else if (TransA == CblasConjTrans) TA = 'C'; else { cblas_xerbla(2, "cblas_sgbmv","Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_TA = C2F_CHAR(&TA); #endif F77_sgbmv(F77_TA, &F77_M, &F77_N, &F77_KL, &F77_KU, &alpha, A, &F77_lda, X, &F77_incX, &beta, Y, &F77_incY); } else if (order == CblasRowMajor) { RowMajorStrg = 1; if (TransA == CblasNoTrans) TA = 'T'; else if (TransA == CblasTrans) TA = 'N'; else if (TransA == CblasConjTrans) TA = 'N'; else { cblas_xerbla(2, "cblas_sgbmv","Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_TA = C2F_CHAR(&TA); #endif F77_sgbmv(F77_TA, &F77_N, &F77_M, &F77_KU, &F77_KL, &alpha, A ,&F77_lda, X, &F77_incX, &beta, Y, &F77_incY); } else cblas_xerbla(1, "cblas_sgbmv", "Illegal Order setting, %d\n", order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_sgemm.c000066400000000000000000000060711422157504600213330ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * * cblas_sgemm.c * This program is a C interface to sgemm. * Written by Keita Teranishi * 4/8/1998 * * Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved. * */ #include "cblas.h" #include "cblas_f77.h" void cblas_sgemm(enum CBLAS_ORDER Order, enum CBLAS_TRANSPOSE TransA, enum CBLAS_TRANSPOSE TransB, f77_int M, f77_int N, f77_int K, float alpha, const float *A, f77_int lda, const float *B, f77_int ldb, float beta, float *C, f77_int ldc) { char TA, TB; #ifdef F77_CHAR F77_CHAR F77_TA, F77_TB; #else #define F77_TA &TA #define F77_TB &TB #endif #ifdef F77_INT F77_INT F77_M=M, F77_N=N, F77_K=K, F77_lda=lda, F77_ldb=ldb; F77_INT F77_ldc=ldc; #else #define F77_M M #define F77_N N #define F77_K K #define F77_lda lda #define F77_ldb ldb #define F77_ldc ldc #endif extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if( Order == CblasColMajor ) { if(TransA == CblasTrans) TA='T'; else if ( TransA == CblasConjTrans ) TA='C'; else if ( TransA == CblasNoTrans ) TA='N'; else { cblas_xerbla(2, "cblas_sgemm", "Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if(TransB == CblasTrans) TB='T'; else if ( TransB == CblasConjTrans ) TB='C'; else if ( TransB == CblasNoTrans ) TB='N'; else { cblas_xerbla(3, "cblas_sgemm", "Illegal TransB setting, %d\n", TransB); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_TA = C2F_CHAR(&TA); F77_TB = C2F_CHAR(&TB); #endif F77_sgemm(F77_TA, F77_TB, &F77_M, &F77_N, &F77_K, &alpha, A, &F77_lda, B, &F77_ldb, &beta, C, &F77_ldc); } else if (Order == CblasRowMajor) { RowMajorStrg = 1; if(TransA == CblasTrans) TB='T'; else if ( TransA == CblasConjTrans ) TB='C'; else if ( TransA == CblasNoTrans ) TB='N'; else { cblas_xerbla(2, "cblas_sgemm", "Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if(TransB == CblasTrans) TA='T'; else if ( TransB == CblasConjTrans ) TA='C'; else if ( TransB == CblasNoTrans ) TA='N'; else { cblas_xerbla(2, "cblas_sgemm", "Illegal TransB setting, %d\n", TransB); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_TA = C2F_CHAR(&TA); F77_TB = C2F_CHAR(&TB); #endif F77_sgemm(F77_TA, F77_TB, &F77_N, &F77_M, &F77_K, &alpha, B, &F77_ldb, A, &F77_lda, &beta, C, &F77_ldc); } else cblas_xerbla(1, "cblas_sgemm", "Illegal Order setting, %d\n", Order); CBLAS_CallFromC = 0; RowMajorStrg = 0; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_sgemv.c000066400000000000000000000041161422157504600213420ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * * cblas_sgemv.c * This program is a C interface to sgemv. * Written by Keita Teranishi * 4/6/1998 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_sgemv(enum CBLAS_ORDER order, enum CBLAS_TRANSPOSE TransA, f77_int M, f77_int N, float alpha, const float *A, f77_int lda, const float *X, f77_int incX, float beta, float *Y, f77_int incY) { char TA; #ifdef F77_CHAR F77_CHAR F77_TA; #else #define F77_TA &TA #endif #ifdef F77_INT F77_INT F77_M=M, F77_N=N, F77_lda=lda, F77_incX=incX, F77_incY=incY; #else #define F77_M M #define F77_N N #define F77_lda lda #define F77_incX incX #define F77_incY incY #endif extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if (order == CblasColMajor) { if (TransA == CblasNoTrans) TA = 'N'; else if (TransA == CblasTrans) TA = 'T'; else if (TransA == CblasConjTrans) TA = 'C'; else { cblas_xerbla(2, "cblas_sgemv","Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; } #ifdef F77_CHAR F77_TA = C2F_CHAR(&TA); #endif F77_sgemv(F77_TA, &F77_M, &F77_N, &alpha, A, &F77_lda, X, &F77_incX, &beta, Y, &F77_incY); } else if (order == CblasRowMajor) { RowMajorStrg = 1; if (TransA == CblasNoTrans) TA = 'T'; else if (TransA == CblasTrans) TA = 'N'; else if (TransA == CblasConjTrans) TA = 'N'; else { cblas_xerbla(2, "cblas_sgemv", "Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_TA = C2F_CHAR(&TA); #endif F77_sgemv(F77_TA, &F77_N, &F77_M, &alpha, A, &F77_lda, X, &F77_incX, &beta, Y, &F77_incY); } else cblas_xerbla(1, "cblas_sgemv", "Illegal Order setting, %d\n", order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_sger.c000066400000000000000000000021771422157504600211660ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * * cblas_sger.c * This program is a C interface to sger. * Written by Keita Teranishi * 4/6/1998 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_sger(enum CBLAS_ORDER order, f77_int M, f77_int N, const float alpha, const float *X, f77_int incX, const float *Y, f77_int incY, float *A, f77_int lda) { #ifdef F77_INT F77_INT F77_M=M, F77_N=N, F77_lda=lda, F77_incX=incX, F77_incY=incY; #else #define F77_M M #define F77_N N #define F77_incX incX #define F77_incY incY #define F77_lda lda #endif extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if (order == CblasColMajor) { F77_sger( &F77_M, &F77_N, &alpha, X, &F77_incX, Y, &F77_incY, A, &F77_lda); } else if (order == CblasRowMajor) { RowMajorStrg = 1; F77_sger( &F77_N, &F77_M, &alpha, Y, &F77_incY, X, &F77_incX, A, &F77_lda); } else cblas_xerbla(1, "cblas_sger", "Illegal Order setting, %d\n", order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_snrm2.c000066400000000000000000000010031422157504600212520ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_snrm2.c * * The program is a C interface to snrm2. * It calls the fortran wrapper before calling snrm2. * * Written by Keita Teranishi. 2/11/1998 * */ #include "cblas.h" #include "cblas_f77.h" float cblas_snrm2( f77_int N, const float *X, f77_int incX) { float nrm2; #ifdef F77_INT F77_INT F77_N=N, F77_incX=incX; #else #define F77_N N #define F77_incX incX #endif F77_snrm2_sub( &F77_N, X, &F77_incX, &nrm2); return nrm2; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_srot.c000066400000000000000000000010441422157504600212050ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_srot.c * * The program is a C interface to srot. * * Written by Keita Teranishi. 2/11/1998 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_srot( f77_int N, float *X, f77_int incX, float *Y, f77_int incY, const float c, const float s) { #ifdef F77_INT F77_INT F77_N=N, F77_incX=incX, F77_incY=incY; #else #define F77_N N #define F77_incX incX #define F77_incY incY #endif F77_srot(&F77_N, X, &F77_incX, Y, &F77_incY, &c, &s); } #endif blis-0.9.0/frame/compat/cblas/src/cblas_srotg.c000066400000000000000000000004531422157504600213570ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_srotg.c * * The program is a C interface to srotg. * * Written by Keita Teranishi. 2/11/1998 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_srotg( float *a, float *b, float *c, float *s) { F77_srotg(a,b,c,s); } #endif blis-0.9.0/frame/compat/cblas/src/cblas_srotm.c000066400000000000000000000010261422157504600213620ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_srotm.c * * The program is a C interface to srotm. * * Written by Keita Teranishi. 2/11/1998 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_srotm( f77_int N, float *X, f77_int incX, float *Y, f77_int incY, const float *P) { #ifdef F77_INT F77_INT F77_N=N, F77_incX=incX, F77_incY=incY; #else #define F77_N N #define F77_incX incX #define F77_incY incY #endif F77_srotm( &F77_N, X, &F77_incX, Y, &F77_incY, P); } #endif blis-0.9.0/frame/compat/cblas/src/cblas_srotmg.c000066400000000000000000000005351422157504600215350ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_srotmg.c * * The program is a C interface to srotmg. * * Written by Keita Teranishi. 2/11/1998 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_srotmg( float *d1, float *d2, float *b1, const float b2, float *p) { F77_srotmg(d1,d2,b1,&b2,p); } #endif blis-0.9.0/frame/compat/cblas/src/cblas_ssbmv.c000066400000000000000000000036411422157504600213550ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * * cblas_ssbmv.c * This program is a C interface to ssbmv. * Written by Keita Teranishi * 4/6/1998 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_ssbmv(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, f77_int N, f77_int K, float alpha, const float *A, f77_int lda, const float *X, f77_int incX, float beta, float *Y, f77_int incY) { char UL; #ifdef F77_CHAR F77_CHAR F77_UL; #else #define F77_UL &UL #endif #ifdef F77_INT F77_INT F77_N=N, F77_K=K, F77_lda=lda, F77_incX=incX, F77_incY=incY; #else #define F77_N N #define F77_K K #define F77_lda lda #define F77_incX incX #define F77_incY incY #endif extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if (order == CblasColMajor) { if (Uplo == CblasUpper) UL = 'U'; else if (Uplo == CblasLower) UL = 'L'; else { cblas_xerbla(2, "cblas_ssbmv","Illegal Uplo setting, %d\n",Uplo ); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); #endif F77_ssbmv(F77_UL, &F77_N, &F77_K, &alpha, A, &F77_lda, X, &F77_incX, &beta, Y, &F77_incY); }else if (order == CblasRowMajor) { RowMajorStrg = 1; if (Uplo == CblasUpper) UL = 'L'; else if (Uplo == CblasLower) UL = 'U'; else { cblas_xerbla(2, "cblas_ssbmv","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); #endif F77_ssbmv(F77_UL, &F77_N, &F77_K, &alpha, A, &F77_lda, X, &F77_incX, &beta, Y, &F77_incY); } else cblas_xerbla(1, "cblas_ssbmv", "Illegal Order setting, %d\n", order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_sscal.c000066400000000000000000000007101422157504600213220ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_sscal.c * * The program is a C interface to sscal. * * Written by Keita Teranishi. 2/11/1998 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_sscal( f77_int N, float alpha, float *X, f77_int incX) { #ifdef F77_INT F77_INT F77_N=N, F77_incX=incX; #else #define F77_N N #define F77_incX incX #endif F77_sscal( &F77_N, &alpha, X, &F77_incX); } #endif blis-0.9.0/frame/compat/cblas/src/cblas_sspmv.c000066400000000000000000000035421422157504600213730ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * * cblas_sspmv.c * This program is a C interface to sspmv. * Written by Keita Teranishi * 4/6/1998 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_sspmv(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, f77_int N, float alpha, const float *AP, const float *X, f77_int incX, float beta, float *Y, f77_int incY) { char UL; #ifdef F77_CHAR F77_CHAR F77_UL; #else #define F77_UL &UL #endif #ifdef F77_INT F77_INT F77_N=N, F77_incX=incX, F77_incY=incY; #else #define F77_N N #define F77_incX incX #define F77_incY incY #endif extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if (order == CblasColMajor) { if (Uplo == CblasUpper) UL = 'U'; else if (Uplo == CblasLower) UL = 'L'; else { cblas_xerbla(2, "cblas_sspmv","Illegal Uplo setting, %d\n",Uplo ); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); #endif F77_sspmv(F77_UL, &F77_N, &alpha, AP, X, &F77_incX, &beta, Y, &F77_incY); } else if (order == CblasRowMajor) { RowMajorStrg = 1; if (Uplo == CblasUpper) UL = 'L'; else if (Uplo == CblasLower) UL = 'U'; else { cblas_xerbla(2, "cblas_sspmv","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); #endif F77_sspmv(F77_UL, &F77_N, &alpha, AP, X,&F77_incX, &beta, Y, &F77_incY); } else cblas_xerbla(1, "cblas_sspmv", "Illegal Order setting, %d\n", order); CBLAS_CallFromC = 0; RowMajorStrg = 0; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_sspr.c000066400000000000000000000032361422157504600212120ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * * cblas_sspr.c * This program is a C interface to sspr. * Written by Keita Teranishi * 4/6/1998 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_sspr(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, f77_int N, const float alpha, const float *X, f77_int incX, float *Ap) { char UL; #ifdef F77_CHAR F77_CHAR F77_UL; #else #define F77_UL &UL #endif #ifdef F77_INT F77_INT F77_N=N, F77_incX=incX; #else #define F77_N N #define F77_incX incX #endif extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if (order == CblasColMajor) { if (Uplo == CblasLower) UL = 'L'; else if (Uplo == CblasUpper) UL = 'U'; else { cblas_xerbla(2, "cblas_sspr","Illegal Uplo setting, %d\n",Uplo ); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); #endif F77_sspr(F77_UL, &F77_N, &alpha, X, &F77_incX, Ap); } else if (order == CblasRowMajor) { RowMajorStrg = 1; if (Uplo == CblasLower) UL = 'U'; else if (Uplo == CblasUpper) UL = 'L'; else { cblas_xerbla(2, "cblas_sspr","Illegal Uplo setting, %d\n",Uplo ); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); #endif F77_sspr(F77_UL, &F77_N, &alpha, X, &F77_incX, Ap); } else cblas_xerbla(1, "cblas_sspr", "Illegal Order setting, %d\n", order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_sspr2.c000066400000000000000000000033751422157504600213000ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * * cblas_sspr2.c * This program is a C interface to sspr2. * Written by Keita Teranishi * 4/6/1998 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_sspr2(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, f77_int N, const float alpha, const float *X, f77_int incX, const float *Y, f77_int incY, float *A) { char UL; #ifdef F77_CHAR F77_CHAR F77_UL; #else #define F77_UL &UL #endif #ifdef F77_INT F77_INT F77_N=N, F77_incX=incX, F77_incY=incY; #else #define F77_N N #define F77_incX incX #define F77_incY incY #endif extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if (order == CblasColMajor) { if (Uplo == CblasLower) UL = 'L'; else if (Uplo == CblasUpper) UL = 'U'; else { cblas_xerbla(2, "cblas_sspr2","Illegal Uplo setting, %d\n",Uplo ); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); #endif F77_sspr2(F77_UL, &F77_N, &alpha, X, &F77_incX, Y, &F77_incY, A); } else if (order == CblasRowMajor) { RowMajorStrg = 1; if (Uplo == CblasLower) UL = 'U'; else if (Uplo == CblasUpper) UL = 'L'; else { cblas_xerbla(2, "cblas_sspr2","Illegal Uplo setting, %d\n",Uplo ); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); #endif F77_sspr2(F77_UL, &F77_N, &alpha, X, &F77_incX, Y, &F77_incY, A); } else cblas_xerbla(1, "cblas_sspr2", "Illegal Order setting, %d\n", order); CBLAS_CallFromC = 0; RowMajorStrg = 0; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_sswap.c000066400000000000000000000010001422157504600213430ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_sswap.c * * The program is a C interface to sswap. * * Written by Keita Teranishi. 2/11/1998 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_sswap( f77_int N, float *X, f77_int incX, float *Y, f77_int incY) { #ifdef F77_INT F77_INT F77_N=N, F77_incX=incX, F77_incY=incY; #else #define F77_N N #define F77_incX incX #define F77_incY incY #endif F77_sswap( &F77_N, X, &F77_incX, Y, &F77_incY); } #endif blis-0.9.0/frame/compat/cblas/src/cblas_ssymm.c000066400000000000000000000053101422157504600213660ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * * cblas_ssymm.c * This program is a C interface to ssymm. * Written by Keita Teranishi * 4/8/1998 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_ssymm(enum CBLAS_ORDER Order, enum CBLAS_SIDE Side, enum CBLAS_UPLO Uplo, f77_int M, f77_int N, float alpha, const float *A, f77_int lda, const float *B, f77_int ldb, float beta, float *C, f77_int ldc) { char SD, UL; #ifdef F77_CHAR F77_CHAR F77_SD, F77_UL; #else #define F77_SD &SD #define F77_UL &UL #endif #ifdef F77_INT F77_INT F77_M=M, F77_N=N, F77_lda=lda, F77_ldb=ldb; F77_INT F77_ldc=ldc; #else #define F77_M M #define F77_N N #define F77_lda lda #define F77_ldb ldb #define F77_ldc ldc #endif extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if( Order == CblasColMajor ) { if( Side == CblasRight) SD='R'; else if ( Side == CblasLeft ) SD='L'; else { cblas_xerbla(2, "cblas_ssymm", "Illegal Side setting, %d\n", Side); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if( Uplo == CblasUpper) UL='U'; else if ( Uplo == CblasLower ) UL='L'; else { cblas_xerbla(3, "cblas_ssymm", "Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_SD = C2F_CHAR(&SD); #endif F77_ssymm(F77_SD, F77_UL, &F77_M, &F77_N, &alpha, A, &F77_lda, B, &F77_ldb, &beta, C, &F77_ldc); } else if (Order == CblasRowMajor) { RowMajorStrg = 1; if( Side == CblasRight) SD='L'; else if ( Side == CblasLeft ) SD='R'; else { cblas_xerbla(2, "cblas_ssymm", "Illegal Side setting, %d\n", Side); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if( Uplo == CblasUpper) UL='L'; else if ( Uplo == CblasLower ) UL='U'; else { cblas_xerbla(3, "cblas_ssymm", "Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_SD = C2F_CHAR(&SD); #endif F77_ssymm(F77_SD, F77_UL, &F77_N, &F77_M, &alpha, A, &F77_lda, B, &F77_ldb, &beta, C, &F77_ldc); } else cblas_xerbla(1, "cblas_ssymm", "Illegal Order setting, %d\n", Order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_ssymv.c000066400000000000000000000036601422157504600214050ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * * cblas_ssymv.c * This program is a C interface to ssymv. * Written by Keita Teranishi * 4/6/1998 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_ssymv(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, f77_int N, float alpha, const float *A, f77_int lda, const float *X, f77_int incX, float beta, float *Y, f77_int incY) { char UL; #ifdef F77_CHAR F77_CHAR F77_UL; #else #define F77_UL &UL #endif #ifdef F77_INT F77_INT F77_N=N, F77_lda=lda, F77_incX=incX, F77_incY=incY; #else #define F77_N N #define F77_lda lda #define F77_incX incX #define F77_incY incY #endif extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if (order == CblasColMajor) { if (Uplo == CblasUpper) UL = 'U'; else if (Uplo == CblasLower) UL = 'L'; else { cblas_xerbla(2, "cblas_ssymv","Illegal Uplo setting, %d\n",Uplo ); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); #endif F77_ssymv(F77_UL, &F77_N, &alpha, A, &F77_lda, X, &F77_incX, &beta, Y, &F77_incY); } else if (order == CblasRowMajor) { RowMajorStrg = 1; if (Uplo == CblasUpper) UL = 'L'; else if (Uplo == CblasLower) UL = 'U'; else { cblas_xerbla(2, "cblas_ssymv","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); #endif F77_ssymv(F77_UL, &F77_N, &alpha, A ,&F77_lda, X,&F77_incX, &beta, Y, &F77_incY); } else cblas_xerbla(1, "cblas_ssymv", "Illegal Order setting, %d\n", order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_ssyr.c000066400000000000000000000033411422157504600212200ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * * cblas_ssyr.c * This program is a C interface to ssyr. * Written by Keita Teranishi * 4/6/1998 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_ssyr(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, f77_int N, const float alpha, const float *X, f77_int incX, float *A, f77_int lda) { char UL; #ifdef F77_CHAR F77_CHAR F77_UL; #else #define F77_UL &UL #endif #ifdef F77_INT F77_INT F77_N=N, F77_incX=incX, F77_lda=lda; #else #define F77_N N #define F77_incX incX #define F77_lda lda #endif extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if (order == CblasColMajor) { if (Uplo == CblasLower) UL = 'L'; else if (Uplo == CblasUpper) UL = 'U'; else { cblas_xerbla(2, "cblas_ssyr","Illegal Uplo setting, %d\n",Uplo ); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); #endif F77_ssyr(F77_UL, &F77_N, &alpha, X, &F77_incX, A, &F77_lda); } else if (order == CblasRowMajor) { RowMajorStrg = 1; if (Uplo == CblasLower) UL = 'U'; else if (Uplo == CblasUpper) UL = 'L'; else { cblas_xerbla(2, "cblas_ssyr","Illegal Uplo setting, %d\n",Uplo ); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); #endif F77_ssyr(F77_UL, &F77_N, &alpha, X, &F77_incX, A, &F77_lda); } else cblas_xerbla(1, "cblas_ssyr", "Illegal Order setting, %d\n", order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_ssyr2.c000066400000000000000000000036101422157504600213010ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * * cblas_ssyr2.c * This program is a C interface to ssyr2. * Written by Keita Teranishi * 4/6/1998 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_ssyr2(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, f77_int N, const float alpha, const float *X, f77_int incX, const float *Y, f77_int incY, float *A, f77_int lda) { char UL; #ifdef F77_CHAR F77_CHAR F77_UL; #else #define F77_UL &UL #endif #ifdef F77_INT F77_INT F77_N=N, F77_incX=incX, F77_incY=incY, F77_lda=lda; #else #define F77_N N #define F77_incX incX #define F77_incY incY #define F77_lda lda #endif extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if (order == CblasColMajor) { if (Uplo == CblasLower) UL = 'L'; else if (Uplo == CblasUpper) UL = 'U'; else { cblas_xerbla(2, "cblas_ssyr2","Illegal Uplo setting, %d\n",Uplo ); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); #endif F77_ssyr2(F77_UL, &F77_N, &alpha, X, &F77_incX, Y, &F77_incY, A, &F77_lda); } else if (order == CblasRowMajor) { RowMajorStrg = 1; if (Uplo == CblasLower) UL = 'U'; else if (Uplo == CblasUpper) UL = 'L'; else { cblas_xerbla(2, "cblas_ssyr2","Illegal Uplo setting, %d\n",Uplo ); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); #endif F77_ssyr2(F77_UL, &F77_N, &alpha, X, &F77_incX, Y, &F77_incY, A, &F77_lda); } else cblas_xerbla(1, "cblas_ssyr2", "Illegal Order setting, %d\n", order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_ssyr2k.c000066400000000000000000000055241422157504600214620ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * * cblas_ssyr2k.c * This program is a C interface to ssyr2k. * Written by Keita Teranishi * 4/6/1998 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_ssyr2k(enum CBLAS_ORDER Order, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE Trans, f77_int N, f77_int K, float alpha, const float *A, f77_int lda, const float *B, f77_int ldb, float beta, float *C, f77_int ldc) { char UL, TR; #ifdef F77_CHAR F77_CHAR F77_TA, F77_UL; #else #define F77_TR &TR #define F77_UL &UL #endif #ifdef F77_INT F77_INT F77_N=N, F77_K=K, F77_lda=lda, F77_ldb=ldb; F77_INT F77_ldc=ldc; #else #define F77_N N #define F77_K K #define F77_lda lda #define F77_ldb ldb #define F77_ldc ldc #endif extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if( Order == CblasColMajor ) { if( Uplo == CblasUpper) UL='U'; else if ( Uplo == CblasLower ) UL='L'; else { cblas_xerbla(2, "cblas_ssyr2k", "Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if( Trans == CblasTrans) TR ='T'; else if ( Trans == CblasConjTrans ) TR='C'; else if ( Trans == CblasNoTrans ) TR='N'; else { cblas_xerbla(3, "cblas_ssyr2k", "Illegal Trans setting, %d\n", Trans); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TR = C2F_CHAR(&TR); #endif F77_ssyr2k(F77_UL, F77_TR, &F77_N, &F77_K, &alpha, A, &F77_lda, B, &F77_ldb, &beta, C, &F77_ldc); } else if (Order == CblasRowMajor) { RowMajorStrg = 1; if( Uplo == CblasUpper) UL='L'; else if ( Uplo == CblasLower ) UL='U'; else { cblas_xerbla(3, "cblas_ssyr2k", "Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if( Trans == CblasTrans) TR ='N'; else if ( Trans == CblasConjTrans ) TR='N'; else if ( Trans == CblasNoTrans ) TR='T'; else { cblas_xerbla(3, "cblas_ssyr2k", "Illegal Trans setting, %d\n", Trans); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TR = C2F_CHAR(&TR); #endif F77_ssyr2k(F77_UL, F77_TR, &F77_N, &F77_K, &alpha, A, &F77_lda, B, &F77_ldb, &beta, C, &F77_ldc); } else cblas_xerbla(1, "cblas_ssyr2k", "Illegal Order setting, %d\n", Order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_ssyrk.c000066400000000000000000000053321422157504600213750ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * * cblas_ssyrk.c * This program is a C interface to ssyrk. * Written by Keita Teranishi * 4/8/1998 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_ssyrk(enum CBLAS_ORDER Order, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE Trans, f77_int N, f77_int K, float alpha, const float *A, f77_int lda, float beta, float *C, f77_int ldc) { char UL, TR; #ifdef F77_CHAR F77_CHAR F77_TR, F77_UL; #else #define F77_TR &TR #define F77_UL &UL #endif #ifdef F77_INT F77_INT F77_N=N, F77_K=K, F77_lda=lda; F77_INT F77_ldc=ldc; #else #define F77_N N #define F77_K K #define F77_lda lda #define F77_ldc ldc #endif extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if( Order == CblasColMajor ) { if( Uplo == CblasUpper) UL='U'; else if ( Uplo == CblasLower ) UL='L'; else { cblas_xerbla(2, "cblas_ssyrk", "Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if( Trans == CblasTrans) TR ='T'; else if ( Trans == CblasConjTrans ) TR='C'; else if ( Trans == CblasNoTrans ) TR='N'; else { cblas_xerbla(3, "cblas_ssyrk", "Illegal Trans setting, %d\n", Trans); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TR = C2F_CHAR(&TR); #endif F77_ssyrk(F77_UL, F77_TR, &F77_N, &F77_K, &alpha, A, &F77_lda, &beta, C, &F77_ldc); } else if (Order == CblasRowMajor) { RowMajorStrg = 1; if( Uplo == CblasUpper) UL='L'; else if ( Uplo == CblasLower ) UL='U'; else { cblas_xerbla(3, "cblas_ssyrk", "Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if( Trans == CblasTrans) TR ='N'; else if ( Trans == CblasConjTrans ) TR='N'; else if ( Trans == CblasNoTrans ) TR='T'; else { cblas_xerbla(3, "cblas_ssyrk", "Illegal Trans setting, %d\n", Trans); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TR = C2F_CHAR(&TR); #endif F77_ssyrk(F77_UL, F77_TR, &F77_N, &F77_K, &alpha, A, &F77_lda, &beta, C, &F77_ldc); } else cblas_xerbla(1, "cblas_ssyrk", "Illegal Order setting, %d\n", Order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_stbmv.c000066400000000000000000000064051422157504600213570ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_stbmv.c * This program is a C interface to stbmv. * Written by Keita Teranishi * 3/3/1998 */ #include "cblas.h" #include "cblas_f77.h" void cblas_stbmv(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE TransA, enum CBLAS_DIAG Diag, f77_int N, f77_int K, const float *A, f77_int lda, float *X, f77_int incX) { char TA; char UL; char DI; #ifdef F77_CHAR F77_CHAR F77_TA, F77_UL, F77_DI; #else #define F77_TA &TA #define F77_UL &UL #define F77_DI &DI #endif #ifdef F77_INT F77_INT F77_N=N, F77_lda=lda, F77_K=K, F77_incX=incX; #else #define F77_N N #define F77_K K #define F77_lda lda #define F77_incX incX #endif extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if (order == CblasColMajor) { if (Uplo == CblasUpper) UL = 'U'; else if (Uplo == CblasLower) UL = 'L'; else { cblas_xerbla(2, "cblas_stbmv","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (TransA == CblasNoTrans) TA = 'N'; else if (TransA == CblasTrans) TA = 'T'; else if (TransA == CblasConjTrans) TA = 'C'; else { cblas_xerbla(3, "cblas_stbmv","Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (Diag == CblasUnit) DI = 'U'; else if (Diag == CblasNonUnit) DI = 'N'; else { cblas_xerbla(4, "cblas_stbmv","Illegal Diag setting, %d\n", Diag); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TA = C2F_CHAR(&TA); F77_DI = C2F_CHAR(&DI); #endif F77_stbmv( F77_UL, F77_TA, F77_DI, &F77_N, &F77_K, A, &F77_lda, X, &F77_incX); } else if (order == CblasRowMajor) { RowMajorStrg = 1; if (Uplo == CblasUpper) UL = 'L'; else if (Uplo == CblasLower) UL = 'U'; else { cblas_xerbla(2, "cblas_stbmv","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (TransA == CblasNoTrans) TA = 'T'; else if (TransA == CblasTrans) TA = 'N'; else if (TransA == CblasConjTrans) TA = 'N'; else { cblas_xerbla(3, "cblas_stbmv","Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (Diag == CblasUnit) DI = 'U'; else if (Diag == CblasNonUnit) DI = 'N'; else { cblas_xerbla(4, "cblas_stbmv","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TA = C2F_CHAR(&TA); F77_DI = C2F_CHAR(&DI); #endif F77_stbmv( F77_UL, F77_TA, F77_DI, &F77_N, &F77_K, A, &F77_lda, X, &F77_incX); } else cblas_xerbla(1, "cblas_stbmv", "Illegal Order setting, %d\n", order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_stbsv.c000066400000000000000000000063651422157504600213720ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_stbsv.c * The program is a C interface to stbsv. * * Keita Teranishi 5/20/98 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_stbsv(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE TransA, enum CBLAS_DIAG Diag, f77_int N, f77_int K, const float *A, f77_int lda, float *X, f77_int incX) { char TA; char UL; char DI; #ifdef F77_CHAR F77_CHAR F77_TA, F77_UL, F77_DI; #else #define F77_TA &TA #define F77_UL &UL #define F77_DI &DI #endif #ifdef F77_INT F77_INT F77_N=N, F77_lda=lda, F77_K=K, F77_incX=incX; #else #define F77_N N #define F77_K K #define F77_lda lda #define F77_incX incX #endif extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if (order == CblasColMajor) { if (Uplo == CblasUpper) UL = 'U'; else if (Uplo == CblasLower) UL = 'L'; else { cblas_xerbla(2, "cblas_stbsv","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (TransA == CblasNoTrans) TA = 'N'; else if (TransA == CblasTrans) TA = 'T'; else if (TransA == CblasConjTrans) TA = 'C'; else { cblas_xerbla(3, "cblas_stbsv","Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (Diag == CblasUnit) DI = 'U'; else if (Diag == CblasNonUnit) DI = 'N'; else { cblas_xerbla(4, "cblas_stbsv","Illegal Diag setting, %d\n", Diag); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TA = C2F_CHAR(&TA); F77_DI = C2F_CHAR(&DI); #endif F77_stbsv( F77_UL, F77_TA, F77_DI, &F77_N, &F77_K, A, &F77_lda, X, &F77_incX); } else if (order == CblasRowMajor) { RowMajorStrg = 1; if (Uplo == CblasUpper) UL = 'L'; else if (Uplo == CblasLower) UL = 'U'; else { cblas_xerbla(2, "cblas_stbsv","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (TransA == CblasNoTrans) TA = 'T'; else if (TransA == CblasTrans) TA = 'N'; else if (TransA == CblasConjTrans) TA = 'N'; else { cblas_xerbla(3, "cblas_stbsv","Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (Diag == CblasUnit) DI = 'U'; else if (Diag == CblasNonUnit) DI = 'N'; else { cblas_xerbla(4, "cblas_stbsv","Illegal Diag setting, %d\n", Diag); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TA = C2F_CHAR(&TA); F77_DI = C2F_CHAR(&DI); #endif F77_stbsv( F77_UL, F77_TA, F77_DI, &F77_N, &F77_K, A, &F77_lda, X, &F77_incX); } else cblas_xerbla(1, "cblas_stbsv", "Illegal Order setting, %d\n", order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_stpmv.c000066400000000000000000000061141422157504600213720ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * * cblas_stpmv.c * This program is a C interface to stpmv. * Written by Keita Teranishi * 4/6/1998 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_stpmv(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE TransA, enum CBLAS_DIAG Diag, f77_int N, const float *Ap, float *X, f77_int incX) { char TA; char UL; char DI; #ifdef F77_CHAR F77_CHAR F77_TA, F77_UL, F77_DI; #else #define F77_TA &TA #define F77_UL &UL #define F77_DI &DI #endif #ifdef F77_INT F77_INT F77_N=N, F77_incX=incX; #else #define F77_N N #define F77_incX incX #endif extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if (order == CblasColMajor) { if (Uplo == CblasUpper) UL = 'U'; else if (Uplo == CblasLower) UL = 'L'; else { cblas_xerbla(2, "cblas_stpmv","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (TransA == CblasNoTrans) TA = 'N'; else if (TransA == CblasTrans) TA = 'T'; else if (TransA == CblasConjTrans) TA = 'C'; else { cblas_xerbla(3, "cblas_stpmv","Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (Diag == CblasUnit) DI = 'U'; else if (Diag == CblasNonUnit) DI = 'N'; else { cblas_xerbla(4, "cblas_stpmv","Illegal Diag setting, %d\n", Diag); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TA = C2F_CHAR(&TA); F77_DI = C2F_CHAR(&DI); #endif F77_stpmv( F77_UL, F77_TA, F77_DI, &F77_N, Ap, X, &F77_incX); } else if (order == CblasRowMajor) { RowMajorStrg = 1; if (Uplo == CblasUpper) UL = 'L'; else if (Uplo == CblasLower) UL = 'U'; else { cblas_xerbla(2, "cblas_stpmv","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (TransA == CblasNoTrans) TA = 'T'; else if (TransA == CblasTrans) TA = 'N'; else if (TransA == CblasConjTrans) TA = 'N'; else { cblas_xerbla(3, "cblas_stpmv","Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (Diag == CblasUnit) DI = 'U'; else if (Diag == CblasNonUnit) DI = 'N'; else { cblas_xerbla(4, "cblas_stpmv","Illegal Diag setting, %d\n", Diag); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TA = C2F_CHAR(&TA); F77_DI = C2F_CHAR(&DI); #endif F77_stpmv( F77_UL, F77_TA, F77_DI, &F77_N, Ap, X,&F77_incX); } else cblas_xerbla(1, "cblas_stpmv", "Illegal Order setting, %d\n", order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_stpsv.c000066400000000000000000000060761422157504600214070ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_stpsv.c * The program is a C interface to stpsv. * * Keita Teranishi 5/20/98 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_stpsv(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE TransA, enum CBLAS_DIAG Diag, f77_int N, const float *Ap, float *X, f77_int incX) { char TA; char UL; char DI; #ifdef F77_CHAR F77_CHAR F77_TA, F77_UL, F77_DI; #else #define F77_TA &TA #define F77_UL &UL #define F77_DI &DI #endif #ifdef F77_INT F77_INT F77_N=N, F77_incX=incX; #else #define F77_N N #define F77_incX incX #endif extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if (order == CblasColMajor) { if (Uplo == CblasUpper) UL = 'U'; else if (Uplo == CblasLower) UL = 'L'; else { cblas_xerbla(2, "cblas_stpsv","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (TransA == CblasNoTrans) TA = 'N'; else if (TransA == CblasTrans) TA = 'T'; else if (TransA == CblasConjTrans) TA = 'C'; else { cblas_xerbla(3, "cblas_stpsv","Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (Diag == CblasUnit) DI = 'U'; else if (Diag == CblasNonUnit) DI = 'N'; else { cblas_xerbla(4, "cblas_stpsv","Illegal Diag setting, %d\n", Diag); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TA = C2F_CHAR(&TA); F77_DI = C2F_CHAR(&DI); #endif F77_stpsv( F77_UL, F77_TA, F77_DI, &F77_N, Ap, X, &F77_incX); } else if (order == CblasRowMajor) { RowMajorStrg = 1; if (Uplo == CblasUpper) UL = 'L'; else if (Uplo == CblasLower) UL = 'U'; else { cblas_xerbla(2, "cblas_stpsv","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (TransA == CblasNoTrans) TA = 'T'; else if (TransA == CblasTrans) TA = 'N'; else if (TransA == CblasConjTrans) TA = 'N'; else { cblas_xerbla(3, "cblas_stpsv","Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (Diag == CblasUnit) DI = 'U'; else if (Diag == CblasNonUnit) DI = 'N'; else { cblas_xerbla(4, "cblas_stpsv","Illegal Diag setting, %d\n", Diag); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TA = C2F_CHAR(&TA); F77_DI = C2F_CHAR(&DI); #endif F77_stpsv( F77_UL, F77_TA, F77_DI, &F77_N, Ap, X,&F77_incX); } else cblas_xerbla(1, "cblas_stpsv", "Illegal Order setting, %d\n", order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_strmm.c000066400000000000000000000075611422157504600213720ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * * cblas_strmm.c * This program is a C interface to strmm. * Written by Keita Teranishi * 4/6/1998 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_strmm(enum CBLAS_ORDER Order, enum CBLAS_SIDE Side, enum CBLAS_UPLO Uplo, const enum CBLAS_TRANSPOSE TransA, enum CBLAS_DIAG Diag, f77_int M, f77_int N, float alpha, const float *A, f77_int lda, float *B, f77_int ldb) { char UL, TA, SD, DI; #ifdef F77_CHAR F77_CHAR F77_TA, F77_UL, F77_SD, F77_DI; #else #define F77_TA &TA #define F77_UL &UL #define F77_SD &SD #define F77_DI &DI #endif #ifdef F77_INT F77_INT F77_M=M, F77_N=N, F77_lda=lda, F77_ldb=ldb; #else #define F77_M M #define F77_N N #define F77_lda lda #define F77_ldb ldb #endif extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if( Order == CblasColMajor ) { if( Side == CblasRight) SD='R'; else if ( Side == CblasLeft ) SD='L'; else { cblas_xerbla(2, "cblas_strmm","Illegal Side setting, %d\n", Side); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if( Uplo == CblasUpper) UL='U'; else if ( Uplo == CblasLower ) UL='L'; else { cblas_xerbla(3, "cblas_strmm","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if( TransA == CblasTrans) TA ='T'; else if ( TransA == CblasConjTrans ) TA='C'; else if ( TransA == CblasNoTrans ) TA='N'; else { cblas_xerbla(4, "cblas_strmm","Illegal Trans setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if( Diag == CblasUnit ) DI='U'; else if ( Diag == CblasNonUnit ) DI='N'; else { cblas_xerbla(5, "cblas_strmm", "Illegal Diag setting, %d\n", Diag); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TA = C2F_CHAR(&TA); F77_SD = C2F_CHAR(&SD); F77_DI = C2F_CHAR(&DI); #endif F77_strmm(F77_SD, F77_UL, F77_TA, F77_DI, &F77_M, &F77_N, &alpha, A, &F77_lda, B, &F77_ldb); } else if (Order == CblasRowMajor) { RowMajorStrg = 1; if( Side == CblasRight) SD='L'; else if ( Side == CblasLeft ) SD='R'; else { cblas_xerbla(2, "cblas_strmm","Illegal Side setting, %d\n", Side); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if( Uplo == CblasUpper) UL='L'; else if ( Uplo == CblasLower ) UL='U'; else { cblas_xerbla(3, "cblas_strmm", "Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if( TransA == CblasTrans) TA ='T'; else if ( TransA == CblasConjTrans ) TA='C'; else if ( TransA == CblasNoTrans ) TA='N'; else { cblas_xerbla(4, "cblas_strmm", "Illegal Trans setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if( Diag == CblasUnit ) DI='U'; else if ( Diag == CblasNonUnit ) DI='N'; else { cblas_xerbla(5, "cblas_strmm","Illegal Diag setting, %d\n", Diag); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TA = C2F_CHAR(&TA); F77_SD = C2F_CHAR(&SD); F77_DI = C2F_CHAR(&DI); #endif F77_strmm(F77_SD, F77_UL, F77_TA, F77_DI, &F77_N, &F77_M, &alpha, A, &F77_lda, B, &F77_ldb); } else cblas_xerbla(1, "cblas_strmm", "Illegal Order setting, %d\n", Order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_strmv.c000066400000000000000000000063141422157504600213760ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * * cblas_strmv.c * This program is a C interface to strmv. * Written by Keita Teranishi * 4/6/1998 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_strmv(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE TransA, enum CBLAS_DIAG Diag, f77_int N, const float *A, f77_int lda, float *X, f77_int incX) { char TA; char UL; char DI; #ifdef F77_CHAR F77_CHAR F77_TA, F77_UL, F77_DI; #else #define F77_TA &TA #define F77_UL &UL #define F77_DI &DI #endif #ifdef F77_INT F77_INT F77_N=N, F77_lda=lda, F77_incX=incX; #else #define F77_N N #define F77_lda lda #define F77_incX incX #endif extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if (order == CblasColMajor) { if (Uplo == CblasUpper) UL = 'U'; else if (Uplo == CblasLower) UL = 'L'; else { cblas_xerbla(2, "cblas_strmv","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (TransA == CblasNoTrans) TA = 'N'; else if (TransA == CblasTrans) TA = 'T'; else if (TransA == CblasConjTrans) TA = 'C'; else { cblas_xerbla(3, "cblas_strmv","Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (Diag == CblasUnit) DI = 'U'; else if (Diag == CblasNonUnit) DI = 'N'; else { cblas_xerbla(4, "cblas_strmv","Illegal Diag setting, %d\n", Diag); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TA = C2F_CHAR(&TA); F77_DI = C2F_CHAR(&DI); #endif F77_strmv( F77_UL, F77_TA, F77_DI, &F77_N, A, &F77_lda, X, &F77_incX); } else if (order == CblasRowMajor) { RowMajorStrg = 1; if (Uplo == CblasUpper) UL = 'L'; else if (Uplo == CblasLower) UL = 'U'; else { cblas_xerbla(2, "cblas_strmv","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (TransA == CblasNoTrans) TA = 'T'; else if (TransA == CblasTrans) TA = 'N'; else if (TransA == CblasConjTrans) TA = 'N'; else { cblas_xerbla(3, "cblas_strmv","Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (Diag == CblasUnit) DI = 'U'; else if (Diag == CblasNonUnit) DI = 'N'; else { cblas_xerbla(4, "cblas_strmv","Illegal Diag setting, %d\n", Diag); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TA = C2F_CHAR(&TA); F77_DI = C2F_CHAR(&DI); #endif F77_strmv( F77_UL, F77_TA, F77_DI, &F77_N, A, &F77_lda, X, &F77_incX); } else cblas_xerbla(1, "cblas_strmv", "Illegal Order setting, %d\n", order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_strsm.c000066400000000000000000000076071422157504600214010ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * * cblas_strsm.c * This program is a C interface to strsm. * Written by Keita Teranishi * 4/6/1998 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_strsm(enum CBLAS_ORDER Order, enum CBLAS_SIDE Side, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE TransA, enum CBLAS_DIAG Diag, f77_int M, f77_int N, float alpha, const float *A, f77_int lda, float *B, f77_int ldb) { char UL, TA, SD, DI; #ifdef F77_CHAR F77_CHAR F77_TA, F77_UL, F77_SD, F77_DI; #else #define F77_TA &TA #define F77_UL &UL #define F77_SD &SD #define F77_DI &DI #endif #ifdef F77_INT F77_INT F77_M=M, F77_N=N, F77_lda=lda, F77_ldb=ldb; #else #define F77_M M #define F77_N N #define F77_lda lda #define F77_ldb ldb #endif extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if( Order == CblasColMajor ) { if( Side == CblasRight) SD='R'; else if ( Side == CblasLeft ) SD='L'; else { cblas_xerbla(2, "cblas_strsm", "Illegal Side setting, %d\n", Side); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if( Uplo == CblasUpper) UL='U'; else if ( Uplo == CblasLower ) UL='L'; else { cblas_xerbla(3, "cblas_strsm", "Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if( TransA == CblasTrans) TA ='T'; else if ( TransA == CblasConjTrans ) TA='C'; else if ( TransA == CblasNoTrans ) TA='N'; else { cblas_xerbla(4, "cblas_strsm", "Illegal Trans setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if( Diag == CblasUnit ) DI='U'; else if ( Diag == CblasNonUnit ) DI='N'; else { cblas_xerbla(5, "cblas_strsm", "Illegal Diag setting, %d\n", Diag); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TA = C2F_CHAR(&TA); F77_SD = C2F_CHAR(&SD); F77_DI = C2F_CHAR(&DI); #endif F77_strsm(F77_SD, F77_UL, F77_TA, F77_DI, &F77_M, &F77_N, &alpha, A, &F77_lda, B, &F77_ldb); } else if (Order == CblasRowMajor) { RowMajorStrg = 1; if( Side == CblasRight) SD='L'; else if ( Side == CblasLeft ) SD='R'; else { cblas_xerbla(2, "cblas_strsm", "Illegal Side setting, %d\n", Side); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if( Uplo == CblasUpper) UL='L'; else if ( Uplo == CblasLower ) UL='U'; else { cblas_xerbla(3, "cblas_strsm", "Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if( TransA == CblasTrans) TA ='T'; else if ( TransA == CblasConjTrans ) TA='C'; else if ( TransA == CblasNoTrans ) TA='N'; else { cblas_xerbla(4, "cblas_strsm", "Illegal Trans setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if( Diag == CblasUnit ) DI='U'; else if ( Diag == CblasNonUnit ) DI='N'; else { cblas_xerbla(5, "cblas_strsm", "Illegal Diag setting, %d\n", Diag); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TA = C2F_CHAR(&TA); F77_SD = C2F_CHAR(&SD); F77_DI = C2F_CHAR(&DI); #endif F77_strsm(F77_SD, F77_UL, F77_TA, F77_DI, &F77_N, &F77_M, &alpha, A, &F77_lda, B, &F77_ldb); } else cblas_xerbla(1, "cblas_strsm", "Illegal Order setting, %d\n", Order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_strsv.c000066400000000000000000000062751422157504600214120ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_strsv.c * The program is a C interface to strsv. * * Keita Teranishi 5/20/98 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_strsv(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE TransA, enum CBLAS_DIAG Diag, f77_int N, const float *A, f77_int lda, float *X, f77_int incX) { char TA; char UL; char DI; #ifdef F77_CHAR F77_CHAR F77_TA, F77_UL, F77_DI; #else #define F77_TA &TA #define F77_UL &UL #define F77_DI &DI #endif #ifdef F77_INT F77_INT F77_N=N, F77_lda=lda, F77_incX=incX; #else #define F77_N N #define F77_lda lda #define F77_incX incX #endif extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if (order == CblasColMajor) { if (Uplo == CblasUpper) UL = 'U'; else if (Uplo == CblasLower) UL = 'L'; else { cblas_xerbla(2, "cblas_strsv","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (TransA == CblasNoTrans) TA = 'N'; else if (TransA == CblasTrans) TA = 'T'; else if (TransA == CblasConjTrans) TA = 'C'; else { cblas_xerbla(3, "cblas_strsv","Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (Diag == CblasUnit) DI = 'U'; else if (Diag == CblasNonUnit) DI = 'N'; else { cblas_xerbla(4, "cblas_strsv","Illegal Diag setting, %d\n", Diag); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TA = C2F_CHAR(&TA); F77_DI = C2F_CHAR(&DI); #endif F77_strsv( F77_UL, F77_TA, F77_DI, &F77_N, A, &F77_lda, X, &F77_incX); } else if (order == CblasRowMajor) { RowMajorStrg = 1; if (Uplo == CblasUpper) UL = 'L'; else if (Uplo == CblasLower) UL = 'U'; else { cblas_xerbla(2, "cblas_strsv","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (TransA == CblasNoTrans) TA = 'T'; else if (TransA == CblasTrans) TA = 'N'; else if (TransA == CblasConjTrans) TA = 'N'; else { cblas_xerbla(3, "cblas_strsv","Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (Diag == CblasUnit) DI = 'U'; else if (Diag == CblasNonUnit) DI = 'N'; else { cblas_xerbla(4, "cblas_strsv","Illegal Diag setting, %d\n", Diag); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TA = C2F_CHAR(&TA); F77_DI = C2F_CHAR(&DI); #endif F77_strsv( F77_UL, F77_TA, F77_DI, &F77_N, A, &F77_lda, X, &F77_incX); } else cblas_xerbla(1, "cblas_strsv", "Illegal Order setting, %d\n", order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_xerbla.c000066400000000000000000000036761422157504600215100ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS #include #include #include #include #include "cblas.h" #include "cblas_f77.h" void cblas_xerbla(f77_int info, const char *rout, const char *form, ...) { extern int RowMajorStrg; char empty[1] = ""; va_list argptr; va_start(argptr, form); if (RowMajorStrg) { if (strstr(rout,"gemm") != 0) { if (info == 5 ) info = 4; else if (info == 4 ) info = 5; else if (info == 11) info = 9; else if (info == 9 ) info = 11; } else if (strstr(rout,"symm") != 0 || strstr(rout,"hemm") != 0) { if (info == 5 ) info = 4; else if (info == 4 ) info = 5; } else if (strstr(rout,"trmm") != 0 || strstr(rout,"trsm") != 0) { if (info == 7 ) info = 6; else if (info == 6 ) info = 7; } else if (strstr(rout,"gemv") != 0) { if (info == 4) info = 3; else if (info == 3) info = 4; } else if (strstr(rout,"gbmv") != 0) { if (info == 4) info = 3; else if (info == 3) info = 4; else if (info == 6) info = 5; else if (info == 5) info = 6; } else if (strstr(rout,"ger") != 0) { if (info == 3) info = 2; else if (info == 2) info = 3; else if (info == 8) info = 6; else if (info == 6) info = 8; } else if ( (strstr(rout,"her2") != 0 || strstr(rout,"hpr2") != 0) && strstr(rout,"her2k") == 0 ) { if (info == 8) info = 6; else if (info == 6) info = 8; } } if (info) fprintf(stderr, "Parameter %jd to routine %s was incorrect\n", ( intmax_t )info, rout); vfprintf(stderr, form, argptr); va_end(argptr); if (info && !info) F77_xerbla(empty, &info, 0); /* Force link of our F77 error handler */ exit(-1); } #endif blis-0.9.0/frame/compat/cblas/src/cblas_zaxpy.c000066400000000000000000000011001422157504600213620ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_zaxpy.c * * The program is a C interface to zaxpy. * * Written by Keita Teranishi. 2/11/1998 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_zaxpy( f77_int N, const void *alpha, const void *X, f77_int incX, void *Y, f77_int incY) { #ifdef F77_INT F77_INT F77_N=N, F77_incX=incX, F77_incY=incY; #else #define F77_N N #define F77_incX incX #define F77_incY incY #endif F77_zaxpy( &F77_N, (dcomplex*)alpha, (dcomplex*)X, &F77_incX, (dcomplex*)Y, &F77_incY); } #endif blis-0.9.0/frame/compat/cblas/src/cblas_zcopy.c000066400000000000000000000010311422157504600213560ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_zcopy.c * * The program is a C interface to zcopy. * * Written by Keita Teranishi. 2/11/1998 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_zcopy( f77_int N, const void *X, f77_int incX, void *Y, f77_int incY) { #ifdef F77_INT F77_INT F77_N=N, F77_incX=incX, F77_incY=incY; #else #define F77_N N #define F77_incX incX #define F77_incY incY #endif F77_zcopy( &F77_N, (dcomplex*)X, &F77_incX, (dcomplex*)Y, &F77_incY); } #endif blis-0.9.0/frame/compat/cblas/src/cblas_zdotc_sub.c000066400000000000000000000012071422157504600222130ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_zdotc_sub.c * * The program is a C interface to zdotc. * It calls the fortran wrapper before calling zdotc. * * Written by Keita Teranishi. 2/11/1998 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_zdotc_sub( f77_int N, const void *X, f77_int incX, const void *Y, f77_int incY, void *dotc) { #ifdef F77_INT F77_INT F77_N=N, F77_incX=incX, F77_incY=incY; #else #define F77_N N #define F77_incX incX #define F77_incY incY #endif F77_zdotc_sub( &F77_N, (dcomplex*)X, &F77_incX, (dcomplex*)Y, &F77_incY, (dcomplex*)dotc); return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_zdotu_sub.c000066400000000000000000000012111422157504600222300ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_zdotu_sub.c * * The program is a C interface to zdotu. * It calls the fortran wrapper before calling zdotu. * * Written by Keita Teranishi. 2/11/1998 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_zdotu_sub( f77_int N, const void *X, f77_int incX, const void *Y, f77_int incY, void *dotu) { #ifdef F77_INT F77_INT F77_N=N, F77_incX=incX, F77_incY=incY; #else #define F77_N N #define F77_incX incX #define F77_incY incY #endif F77_zdotu_sub( &F77_N, (dcomplex*)X, &F77_incX, (dcomplex*)Y, &F77_incY, (dcomplex*)dotu); return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_zdscal.c000066400000000000000000000007271422157504600215050ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_zdscal.c * * The program is a C interface to zdscal. * * Written by Keita Teranishi. 2/11/1998 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_zdscal( f77_int N, double alpha, void *X, f77_int incX) { #ifdef F77_INT F77_INT F77_N=N, F77_incX=incX; #else #define F77_N N #define F77_incX incX #endif F77_zdscal( &F77_N, &alpha, (dcomplex*)X, &F77_incX); } #endif blis-0.9.0/frame/compat/cblas/src/cblas_zgbmv.c000066400000000000000000000104171422157504600213470ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_zgbmv.c * The program is a C interface of zgbmv * * Keita Teranishi 5/20/98 * */ #include #include #include "cblas.h" #include "cblas_f77.h" void cblas_zgbmv(enum CBLAS_ORDER order, enum CBLAS_TRANSPOSE TransA, f77_int M, f77_int N, f77_int KL, f77_int KU, const void *alpha, const void *A, f77_int lda, const void *X, f77_int incX, const void *beta, void *Y, f77_int incY) { char TA; #ifdef F77_CHAR F77_CHAR F77_TA; #else #define F77_TA &TA #endif #ifdef F77_INT F77_INT F77_M=M, F77_N=N, F77_lda=lda, F77_incX=incX, F77_incY=incY; F77_INT F77_KL=KL,F77_KU=KU; #else #define F77_M M #define F77_N N #define F77_lda lda #define F77_KL KL #define F77_KU KU #define F77_incX incX #define F77_incY incY #endif int n, i=0; const double *xx= (double *)X, *alp= (double *)alpha, *bet = (double *)beta; double ALPHA[2],BETA[2]; int tincY, tincx; double *x=(double *)X, *y=(double *)Y, *st=0, *tx; extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if (order == CblasColMajor) { if (TransA == CblasNoTrans) TA = 'N'; else if (TransA == CblasTrans) TA = 'T'; else if (TransA == CblasConjTrans) TA = 'C'; else { cblas_xerbla(2, "cblas_zgbmv","Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_TA = C2F_CHAR(&TA); #endif F77_zgbmv(F77_TA, &F77_M, &F77_N, &F77_KL, &F77_KU, (dcomplex*)alpha, (dcomplex*)A, &F77_lda, (dcomplex*)X, &F77_incX, (dcomplex*)beta, (dcomplex*)Y, &F77_incY); } else if (order == CblasRowMajor) { RowMajorStrg = 1; if (TransA == CblasNoTrans) TA = 'T'; else if (TransA == CblasTrans) TA = 'N'; else if (TransA == CblasConjTrans) { ALPHA[0]= *alp; ALPHA[1]= -alp[1]; BETA[0]= *bet; BETA[1]= -bet[1]; TA = 'N'; if (M > 0) { n = M << 1; x = malloc(n*sizeof(double)); tx = x; if( incX > 0 ) { i = incX << 1 ; tincx = 2; st= x+n; } else { i = incX *(-2); tincx = -2; st = x-2; x +=(n-2); } do { *x = *xx; x[1] = -xx[1]; x += tincx ; xx += i; } while (x != st); x=tx; #ifdef F77_INT F77_incX = 1; #else incX = 1; #endif if( incY > 0 ) tincY = incY; else tincY = -incY; y++; if (N > 0) { i = tincY << 1; n = i * N ; st = y + n; do { *y = -(*y); y += i; } while(y != st); y -= n; } } else x = (double *) X; } else { cblas_xerbla(2, "cblas_zgbmv","Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_TA = C2F_CHAR(&TA); #endif if (TransA == CblasConjTrans) F77_zgbmv(F77_TA, &F77_N, &F77_M, &F77_KU, &F77_KL, (dcomplex*)ALPHA, (dcomplex*)A ,&F77_lda, (dcomplex*)x,&F77_incX, (dcomplex*)BETA, (dcomplex*)Y, &F77_incY); else F77_zgbmv(F77_TA, &F77_N, &F77_M, &F77_KU, &F77_KL, (dcomplex*)alpha, (dcomplex*)A ,&F77_lda, (dcomplex*)x,&F77_incX, (dcomplex*)beta, (dcomplex*)Y, &F77_incY); if (TransA == CblasConjTrans) { if (x != X) free(x); if (N > 0) { do { *y = -(*y); y += i; } while (y != st); } } } else cblas_xerbla(1, "cblas_zgbmv", "Illegal Order setting, %d\n", order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_zgemm.c000066400000000000000000000060501422157504600213370ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * * cblas_zgemm.c * This program is a C interface to zgemm. * Written by Keita Teranishi * 4/8/1998 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_zgemm(enum CBLAS_ORDER Order, enum CBLAS_TRANSPOSE TransA, enum CBLAS_TRANSPOSE TransB, f77_int M, f77_int N, f77_int K, const void *alpha, const void *A, f77_int lda, const void *B, f77_int ldb, const void *beta, void *C, f77_int ldc) { char TA, TB; #ifdef F77_CHAR F77_CHAR F77_TA, F77_TB; #else #define F77_TA &TA #define F77_TB &TB #endif #ifdef F77_INT F77_INT F77_M=M, F77_N=N, F77_K=K, F77_lda=lda, F77_ldb=ldb; F77_INT F77_ldc=ldc; #else #define F77_M M #define F77_N N #define F77_K K #define F77_lda lda #define F77_ldb ldb #define F77_ldc ldc #endif extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if( Order == CblasColMajor ) { if(TransA == CblasTrans) TA='T'; else if ( TransA == CblasConjTrans ) TA='C'; else if ( TransA == CblasNoTrans ) TA='N'; else { cblas_xerbla(2, "cblas_zgemm","Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if(TransB == CblasTrans) TB='T'; else if ( TransB == CblasConjTrans ) TB='C'; else if ( TransB == CblasNoTrans ) TB='N'; else { cblas_xerbla(3, "cblas_zgemm","Illegal TransB setting, %d\n", TransB); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_TA = C2F_CHAR(&TA); F77_TB = C2F_CHAR(&TB); #endif F77_zgemm(F77_TA, F77_TB, &F77_M, &F77_N, &F77_K, (dcomplex*)alpha, (dcomplex*)A, &F77_lda, (dcomplex*)B, &F77_ldb, (dcomplex*)beta, (dcomplex*)C, &F77_ldc); } else if (Order == CblasRowMajor) { RowMajorStrg = 1; if(TransA == CblasTrans) TB='T'; else if ( TransA == CblasConjTrans ) TB='C'; else if ( TransA == CblasNoTrans ) TB='N'; else { cblas_xerbla(2, "cblas_zgemm","Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if(TransB == CblasTrans) TA='T'; else if ( TransB == CblasConjTrans ) TA='C'; else if ( TransB == CblasNoTrans ) TA='N'; else { cblas_xerbla(2, "cblas_zgemm","Illegal TransB setting, %d\n", TransB); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_TA = C2F_CHAR(&TA); F77_TB = C2F_CHAR(&TB); #endif F77_zgemm(F77_TA, F77_TB, &F77_N, &F77_M, &F77_K, (dcomplex*)alpha, (dcomplex*)B, &F77_ldb, (dcomplex*)A, &F77_lda, (dcomplex*)beta, (dcomplex*)C, &F77_ldc); } else cblas_xerbla(1, "cblas_zgemm", "Illegal Order setting, %d\n", Order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_zgemv.c000066400000000000000000000101731422157504600213510ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_zgemv.c * The program is a C interface of zgemv * * Keita Teranishi 5/20/98 * */ #include #include #include "cblas.h" #include "cblas_f77.h" void cblas_zgemv(enum CBLAS_ORDER order, enum CBLAS_TRANSPOSE TransA, f77_int M, f77_int N, const void *alpha, const void *A, f77_int lda, const void *X, f77_int incX, const void *beta, void *Y, f77_int incY) { char TA; #ifdef F77_CHAR F77_CHAR F77_TA; #else #define F77_TA &TA #endif #ifdef F77_INT F77_INT F77_M=M, F77_N=N, F77_lda=lda, F77_incX=incX, F77_incY=incY; #else #define F77_M M #define F77_N N #define F77_lda lda #define F77_incX incX #define F77_incY incY #endif int n, i=0; const double *xx= (double *)X, *alp= (double *)alpha, *bet = (double *)beta; double ALPHA[2],BETA[2]; int tincY, tincx; double *x=(double *)X, *y=(double *)Y, *st=0, *tx; extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if (order == CblasColMajor) { if (TransA == CblasNoTrans) TA = 'N'; else if (TransA == CblasTrans) TA = 'T'; else if (TransA == CblasConjTrans) TA = 'C'; else { cblas_xerbla(2, "cblas_zgemv","Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_TA = C2F_CHAR(&TA); #endif F77_zgemv(F77_TA, &F77_M, &F77_N, (dcomplex*)alpha, (dcomplex*)A, &F77_lda, (dcomplex*)X, &F77_incX, (dcomplex*)beta, (dcomplex*)Y, &F77_incY); } else if (order == CblasRowMajor) { RowMajorStrg = 1; if (TransA == CblasNoTrans) TA = 'T'; else if (TransA == CblasTrans) TA = 'N'; else if (TransA == CblasConjTrans) { ALPHA[0]= *alp; ALPHA[1]= -alp[1]; BETA[0]= *bet; BETA[1]= -bet[1]; TA = 'N'; if (M > 0) { n = M << 1; x = malloc(n*sizeof(double)); tx = x; if( incX > 0 ) { i = incX << 1 ; tincx = 2; st= x+n; } else { i = incX *(-2); tincx = -2; st = x-2; x +=(n-2); } do { *x = *xx; x[1] = -xx[1]; x += tincx ; xx += i; } while (x != st); x=tx; #ifdef F77_INT F77_incX = 1; #else incX = 1; #endif if(incY > 0) tincY = incY; else tincY = -incY; y++; if (N > 0) { i = tincY << 1; n = i * N ; st = y + n; do { *y = -(*y); y += i; } while(y != st); y -= n; } } else x = (double *) X; } else { cblas_xerbla(2, "cblas_zgemv","Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_TA = C2F_CHAR(&TA); #endif if (TransA == CblasConjTrans) F77_zgemv(F77_TA, &F77_N, &F77_M, (dcomplex*)ALPHA, (dcomplex*)A, &F77_lda, (dcomplex*)x, &F77_incX, (dcomplex*)BETA, (dcomplex*)Y, &F77_incY); else F77_zgemv(F77_TA, &F77_N, &F77_M, (dcomplex*)alpha, (dcomplex*)A, &F77_lda, (dcomplex*)x, &F77_incX, (dcomplex*)beta, (dcomplex*)Y, &F77_incY); if (TransA == CblasConjTrans) { if (x != (double *)X) free(x); if (N > 0) { do { *y = -(*y); y += i; } while (y != st); } } } else cblas_xerbla(1, "cblas_zgemv", "Illegal Order setting, %d\n", order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_zgerc.c000066400000000000000000000037721422157504600213420ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_zgerc.c * The program is a C interface to zgerc. * * Keita Teranishi 5/20/98 * */ #include #include #include "cblas.h" #include "cblas_f77.h" void cblas_zgerc(enum CBLAS_ORDER order, f77_int M, f77_int N, const void *alpha, const void *X, f77_int incX, const void *Y, f77_int incY, void *A, f77_int lda) { #ifdef F77_INT F77_INT F77_M=M, F77_N=N, F77_lda=lda, F77_incX=incX, F77_incY=incY; #else #define F77_M M #define F77_N N #define F77_incX incX #define F77_incY incY #define F77_lda lda #endif int n, i, tincy; double *y=(double *)Y, *yy=(double *)Y, *ty, *st; extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if (order == CblasColMajor) { F77_zgerc( &F77_M, &F77_N, (dcomplex*)alpha, (dcomplex*)X, &F77_incX, (dcomplex*)Y, &F77_incY, (dcomplex*)A, &F77_lda); } else if (order == CblasRowMajor) { RowMajorStrg = 1; if (N > 0) { n = N << 1; y = malloc(n*sizeof(double)); ty = y; if( incY > 0 ) { i = incY << 1; tincy = 2; st= y+n; } else { i = incY *(-2); tincy = -2; st = y-2; y +=(n-2); } do { *y = *yy; y[1] = -yy[1]; y += tincy ; yy += i; } while (y != st); y = ty; #ifdef F77_INT F77_incY = 1; #else incY = 1; #endif } else y = (double *) Y; F77_zgeru( &F77_N, &F77_M, (dcomplex*)alpha, (dcomplex*)y, &F77_incY, (dcomplex*)X, &F77_incX, (dcomplex*)A, &F77_lda); if(Y!=y) free(y); } else cblas_xerbla(1, "cblas_zgerc", "Illegal Order setting, %d\n", order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_zgeru.c000066400000000000000000000023431422157504600213550ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_zgeru.c * The program is a C interface to zgeru. * * Keita Teranishi 5/20/98 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_zgeru(enum CBLAS_ORDER order, f77_int M, f77_int N, const void *alpha, const void *X, f77_int incX, const void *Y, f77_int incY, void *A, f77_int lda) { #ifdef F77_INT F77_INT F77_M=M, F77_N=N, F77_lda=lda, F77_incX=incX, F77_incY=incY; #else #define F77_M M #define F77_N N #define F77_incX incX #define F77_incY incY #define F77_lda lda #endif extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if (order == CblasColMajor) { F77_zgeru( &F77_M, &F77_N, (dcomplex*)alpha, (dcomplex*)X, &F77_incX, (dcomplex*)Y, &F77_incY, (dcomplex*)A, &F77_lda); } else if (order == CblasRowMajor) { RowMajorStrg = 1; F77_zgeru( &F77_N, &F77_M, (dcomplex*)alpha, (dcomplex*)Y, &F77_incY, (dcomplex*)X, &F77_incX, (dcomplex*)A, &F77_lda); } else cblas_xerbla(1, "cblas_zgeru", "Illegal Order setting, %d\n", order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_zhbmv.c000066400000000000000000000071251422157504600213520ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_zhbmv.c * The program is a C interface to zhbmv * * Keita Teranishi 5/18/98 * */ #include "cblas.h" #include "cblas_f77.h" #include #include void cblas_zhbmv(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo,f77_int N,f77_int K, const void *alpha, const void *A, f77_int lda, const void *X, f77_int incX, const void *beta, void *Y, f77_int incY) { char UL; #ifdef F77_CHAR F77_CHAR F77_UL; #else #define F77_UL &UL #endif #ifdef F77_INT F77_INT F77_N=N, F77_K=K, F77_lda=lda, F77_incX=incX, F77_incY=incY; #else #define F77_N N #define F77_K K #define F77_lda lda #define F77_incX incX #define F77_incY incY #endif int n, i=0; const double *xx= (double *)X, *alp= (double *)alpha, *bet = (double *)beta; double ALPHA[2],BETA[2]; int tincY, tincx; double *x=(double *)X, *y=(double *)Y, *st=0, *tx; extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if (order == CblasColMajor) { if (Uplo == CblasLower) UL = 'L'; else if (Uplo == CblasUpper) UL = 'U'; else { cblas_xerbla(2, "cblas_zhbmv","Illegal Uplo setting, %d\n",Uplo ); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); #endif F77_zhbmv(F77_UL, &F77_N, &F77_K, (dcomplex*)alpha, (dcomplex*)A, &F77_lda, (dcomplex*)X, &F77_incX, (dcomplex*)beta, (dcomplex*)Y, &F77_incY); } else if (order == CblasRowMajor) { RowMajorStrg = 1; ALPHA[0]= *alp; ALPHA[1]= -alp[1]; BETA[0]= *bet; BETA[1]= -bet[1]; if (N > 0) { n = N << 1; x = malloc(n*sizeof(double)); tx = x; if( incX > 0 ) { i = incX << 1 ; tincx = 2; st= x+n; } else { i = incX *(-2); tincx = -2; st = x-2; x +=(n-2); } do { *x = *xx; x[1] = -xx[1]; x += tincx ; xx += i; } while (x != st); x=tx; #ifdef F77_INT F77_incX = 1; #else incX = 1; #endif if(incY > 0) tincY = incY; else tincY = -incY; y++; i = tincY << 1; n = i * N ; st = y + n; do { *y = -(*y); y += i; } while(y != st); y -= n; } else x = (double *) X; if (Uplo == CblasUpper) UL = 'L'; else if (Uplo == CblasLower) UL = 'U'; else { cblas_xerbla(2, "cblas_zhbmv","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); #endif F77_zhbmv(F77_UL, &F77_N, &F77_K, (dcomplex*)ALPHA, (dcomplex*)A ,&F77_lda, (dcomplex*)x,&F77_incX, (dcomplex*)BETA, (dcomplex*)Y, &F77_incY); } else { cblas_xerbla(1, "cblas_zhbmv","Illegal Order setting, %d\n", order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if ( order == CblasRowMajor ) { RowMajorStrg = 1; if(X!=x) free(x); if (N > 0) { do { *y = -(*y); y += i; } while (y != st); } } CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_zhemm.c000066400000000000000000000053571422157504600213510ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * * cblas_zhemm.c * This program is a C interface to zhemm. * Written by Keita Teranishi * 4/8/1998 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_zhemm(enum CBLAS_ORDER Order, const enum CBLAS_SIDE Side, enum CBLAS_UPLO Uplo, f77_int M, f77_int N, const void *alpha, const void *A, f77_int lda, const void *B, f77_int ldb, const void *beta, void *C, f77_int ldc) { char SD, UL; #ifdef F77_CHAR F77_CHAR F77_SD, F77_UL; #else #define F77_SD &SD #define F77_UL &UL #endif #ifdef F77_INT F77_INT F77_M=M, F77_N=N, F77_lda=lda, F77_ldb=ldb; F77_INT F77_ldc=ldc; #else #define F77_M M #define F77_N N #define F77_lda lda #define F77_ldb ldb #define F77_ldc ldc #endif extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if( Order == CblasColMajor ) { if( Side == CblasRight) SD='R'; else if ( Side == CblasLeft ) SD='L'; else { cblas_xerbla(2, "cblas_zhemm", "Illegal Side setting, %d\n", Side); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if( Uplo == CblasUpper) UL='U'; else if ( Uplo == CblasLower ) UL='L'; else { cblas_xerbla(3, "cblas_zhemm", "Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_SD = C2F_CHAR(&SD); #endif F77_zhemm(F77_SD, F77_UL, &F77_M, &F77_N, (dcomplex*)alpha, (dcomplex*)A, &F77_lda, (dcomplex*)B, &F77_ldb, (dcomplex*)beta, (dcomplex*)C, &F77_ldc); } else if (Order == CblasRowMajor) { RowMajorStrg = 1; if( Side == CblasRight) SD='L'; else if ( Side == CblasLeft ) SD='R'; else { cblas_xerbla(2, "cblas_zhemm", "Illegal Side setting, %d\n", Side); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if( Uplo == CblasUpper) UL='L'; else if ( Uplo == CblasLower ) UL='U'; else { cblas_xerbla(3, "cblas_zhemm", "Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_SD = C2F_CHAR(&SD); #endif F77_zhemm(F77_SD, F77_UL, &F77_N, &F77_M, (dcomplex*)alpha, (dcomplex*)A, &F77_lda, (dcomplex*)B, &F77_ldb, (dcomplex*)beta, (dcomplex*)C, &F77_ldc); } else cblas_xerbla(1, "cblas_zhemm", "Illegal Order setting, %d\n", Order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_zhemv.c000066400000000000000000000070511422157504600213530ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_zhemv.c * The program is a C interface to zhemv * * Keita Teranishi 5/18/98 * */ #include #include #include "cblas.h" #include "cblas_f77.h" void cblas_zhemv(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, f77_int N, const void *alpha, const void *A, f77_int lda, const void *X, f77_int incX, const void *beta, void *Y, f77_int incY) { char UL; #ifdef F77_CHAR F77_CHAR F77_UL; #else #define F77_UL &UL #endif #ifdef F77_INT F77_INT F77_N=N, F77_lda=lda, F77_incX=incX, F77_incY=incY; #else #define F77_N N #define F77_lda lda #define F77_incX incX #define F77_incY incY #endif int n, i=0; const double *xx= (double *)X, *alp= (double *)alpha, *bet = (double *)beta; double ALPHA[2],BETA[2]; int tincY, tincx; double *x=(double *)X, *y=(double *)Y, *st=0, *tx; extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if (order == CblasColMajor) { if (Uplo == CblasUpper) UL = 'U'; else if (Uplo == CblasLower) UL = 'L'; else { cblas_xerbla(2, "cblas_zhemv","Illegal Uplo setting, %d\n",Uplo ); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); #endif F77_zhemv(F77_UL, &F77_N, (dcomplex*)alpha, (dcomplex*)A, &F77_lda, (dcomplex*)X, &F77_incX, (dcomplex*)beta, (dcomplex*)Y, &F77_incY); } else if (order == CblasRowMajor) { RowMajorStrg = 1; ALPHA[0]= *alp; ALPHA[1]= -alp[1]; BETA[0]= *bet; BETA[1]= -bet[1]; if (N > 0) { n = N << 1; x = malloc(n*sizeof(double)); tx = x; if( incX > 0 ) { i = incX << 1 ; tincx = 2; st= x+n; } else { i = incX *(-2); tincx = -2; st = x-2; x +=(n-2); } do { *x = *xx; x[1] = -xx[1]; x += tincx ; xx += i; } while (x != st); x=tx; #ifdef F77_INT F77_incX = 1; #else incX = 1; #endif if(incY > 0) tincY = incY; else tincY = -incY; y++; i = tincY << 1; n = i * N ; st = y + n; do { *y = -(*y); y += i; } while(y != st); y -= n; } else x = (double *) X; if (Uplo == CblasUpper) UL = 'L'; else if (Uplo == CblasLower) UL = 'U'; else { cblas_xerbla(2, "cblas_zhemv","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); #endif F77_zhemv(F77_UL, &F77_N, (dcomplex*)ALPHA, (dcomplex*)A, &F77_lda, (dcomplex*)x, &F77_incX, (dcomplex*)BETA, (dcomplex*)Y, &F77_incY); } else { cblas_xerbla(1, "cblas_zhemv","Illegal Order setting, %d\n", order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if ( order == CblasRowMajor ) { RowMajorStrg = 1; if ( X != x ) free(x); if (N > 0) { do { *y = -(*y); y += i; } while (y != st); } } CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_zher.c000066400000000000000000000050001422157504600211620ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_zher.c * The program is a C interface to zher. * * Keita Teranishi 5/20/98 * */ #include #include #include "cblas.h" #include "cblas_f77.h" void cblas_zher(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, f77_int N, double alpha, const void *X, f77_int incX ,void *A, f77_int lda) { char UL; #ifdef F77_CHAR F77_CHAR F77_UL; #else #define F77_UL &UL #endif #ifdef F77_INT F77_INT F77_N=N, F77_lda=lda, F77_incX=incX; #else #define F77_N N #define F77_lda lda #define F77_incX incX #endif int n, i, tincx; double *x=(double *)X, *xx=(double *)X, *tx, *st; extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if (order == CblasColMajor) { if (Uplo == CblasLower) UL = 'L'; else if (Uplo == CblasUpper) UL = 'U'; else { cblas_xerbla(2, "cblas_zher","Illegal Uplo setting, %d\n",Uplo ); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); #endif F77_zher(F77_UL, &F77_N, &alpha, (dcomplex*)X, &F77_incX, (dcomplex*)A, &F77_lda); } else if (order == CblasRowMajor) { RowMajorStrg = 1; if (Uplo == CblasUpper) UL = 'L'; else if (Uplo == CblasLower) UL = 'U'; else { cblas_xerbla(2, "cblas_zher","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); #endif if (N > 0) { n = N << 1; x = malloc(n*sizeof(double)); tx = x; if( incX > 0 ) { i = incX << 1 ; tincx = 2; st= x+n; } else { i = incX *(-2); tincx = -2; st = x-2; x +=(n-2); } do { *x = *xx; x[1] = -xx[1]; x += tincx ; xx += i; } while (x != st); x=tx; #ifdef F77_INT F77_incX = 1; #else incX = 1; #endif } else x = (double *) X; F77_zher(F77_UL, &F77_N, &alpha, (dcomplex*)x, &F77_incX, (dcomplex*)A, &F77_lda); } else cblas_xerbla(1, "cblas_zher", "Illegal Order setting, %d\n", order); if(X!=x) free(x); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_zher2.c000066400000000000000000000067021422157504600212560ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_zher2.c * The program is a C interface to zher2. * * Keita Teranishi 3/23/98 * */ #include #include #include "cblas.h" #include "cblas_f77.h" void cblas_zher2(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, f77_int N, const void *alpha, const void *X, f77_int incX, const void *Y, f77_int incY, void *A, f77_int lda) { char UL; #ifdef F77_CHAR F77_CHAR F77_UL; #else #define F77_UL &UL #endif #ifdef F77_INT F77_INT F77_N=N, F77_lda=lda, F77_incX=incX, F77_incY=incY; #else #define F77_N N #define F77_lda lda #define F77_incX incX #define F77_incY incY #endif int n, i, j, tincx, tincy; double *x=(double *)X, *xx=(double *)X, *y=(double *)Y, *yy=(double *)Y, *tx, *ty, *stx, *sty; extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if (order == CblasColMajor) { if (Uplo == CblasLower) UL = 'L'; else if (Uplo == CblasUpper) UL = 'U'; else { cblas_xerbla(2, "cblas_zher2", "Illegal Uplo setting, %d\n",Uplo ); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); #endif F77_zher2(F77_UL, &F77_N, (dcomplex*)alpha, (dcomplex*)X, &F77_incX, (dcomplex*)Y, &F77_incY, (dcomplex*)A, &F77_lda); } else if (order == CblasRowMajor) { RowMajorStrg = 1; if (Uplo == CblasUpper) UL = 'L'; else if (Uplo == CblasLower) UL = 'U'; else { cblas_xerbla(2, "cblas_zher2", "Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); #endif if (N > 0) { n = N << 1; x = malloc(n*sizeof(double)); y = malloc(n*sizeof(double)); tx = x; ty = y; if( incX > 0 ) { i = incX << 1 ; tincx = 2; stx= x+n; } else { i = incX *(-2); tincx = -2; stx = x-2; x +=(n-2); } if( incY > 0 ) { j = incY << 1; tincy = 2; sty= y+n; } else { j = incY *(-2); tincy = -2; sty = y-2; y +=(n-2); } do { *x = *xx; x[1] = -xx[1]; x += tincx ; xx += i; } while (x != stx); do { *y = *yy; y[1] = -yy[1]; y += tincy ; yy += j; } while (y != sty); x=tx; y=ty; #ifdef F77_INT F77_incX = 1; F77_incY = 1; #else incX = 1; incY = 1; #endif } else { x = (double *) X; y = (double *) Y; } F77_zher2(F77_UL, &F77_N, (dcomplex*)alpha, (dcomplex*)y, &F77_incY, (dcomplex*)x, &F77_incX, (dcomplex*)A, &F77_lda); } else { cblas_xerbla(1, "cblas_zher2", "Illegal Order setting, %d\n", order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if(X!=x) free(x); if(Y!=y) free(y); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_zher2k.c000066400000000000000000000056451422157504600214360ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * * cblas_zher2k.c * This program is a C interface to zher2k. * Written by Keita Teranishi * 4/8/1998 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_zher2k(enum CBLAS_ORDER Order, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE Trans, f77_int N, f77_int K, const void *alpha, const void *A, f77_int lda, const void *B, f77_int ldb, double beta, void *C, f77_int ldc) { char UL, TR; #ifdef F77_CHAR F77_CHAR F77_TR, F77_UL; #else #define F77_TR &TR #define F77_UL &UL #endif #ifdef F77_INT F77_INT F77_N=N, F77_K=K, F77_lda=lda, F77_ldb=ldb; F77_INT F77_ldc=ldc; #else #define F77_N N #define F77_K K #define F77_lda lda #define F77_ldb ldb #define F77_ldc ldc #endif extern int CBLAS_CallFromC; extern int RowMajorStrg; double ALPHA[2]; const double *alp=(double *)alpha; CBLAS_CallFromC = 1; RowMajorStrg = 0; if( Order == CblasColMajor ) { if( Uplo == CblasUpper) UL='U'; else if ( Uplo == CblasLower ) UL='L'; else { cblas_xerbla(2, "cblas_zher2k", "Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if( Trans == CblasTrans) TR ='T'; else if ( Trans == CblasConjTrans ) TR='C'; else if ( Trans == CblasNoTrans ) TR='N'; else { cblas_xerbla(3, "cblas_zher2k", "Illegal Trans setting, %d\n", Trans); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TR = C2F_CHAR(&TR); #endif F77_zher2k(F77_UL, F77_TR, &F77_N, &F77_K, (dcomplex*)alpha, (dcomplex*)A, &F77_lda, (dcomplex*)B, &F77_ldb, &beta, (dcomplex*)C, &F77_ldc); } else if (Order == CblasRowMajor) { RowMajorStrg = 1; if( Uplo == CblasUpper) UL='L'; else if ( Uplo == CblasLower ) UL='U'; else { cblas_xerbla(2, "cblas_zher2k", "Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if( Trans == CblasTrans) TR ='N'; else if ( Trans == CblasConjTrans ) TR='N'; else if ( Trans == CblasNoTrans ) TR='C'; else { cblas_xerbla(3, "cblas_zher2k", "Illegal Trans setting, %d\n", Trans); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TR = C2F_CHAR(&TR); #endif ALPHA[0]= *alp; ALPHA[1]= -alp[1]; F77_zher2k(F77_UL,F77_TR, &F77_N, &F77_K, (dcomplex*)ALPHA, (dcomplex*)A, &F77_lda, (dcomplex*)B, &F77_ldb, &beta, (dcomplex*)C, &F77_ldc); } else cblas_xerbla(1, "cblas_zher2k", "Illegal Order setting, %d\n", Order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_zherk.c000066400000000000000000000052651422157504600213520ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * * cblas_zherk.c * This program is a C interface to zherk. * Written by Keita Teranishi * 4/8/1998 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_zherk(enum CBLAS_ORDER Order, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE Trans, f77_int N, f77_int K, double alpha, const void *A, f77_int lda, double beta, void *C, f77_int ldc) { char UL, TR; #ifdef F77_CHAR F77_CHAR F77_TR, F77_UL; #else #define F77_TR &TR #define F77_UL &UL #endif #ifdef F77_INT F77_INT F77_N=N, F77_K=K, F77_lda=lda; F77_INT F77_ldc=ldc; #else #define F77_N N #define F77_K K #define F77_lda lda #define F77_ldc ldc #endif extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if( Order == CblasColMajor ) { if( Uplo == CblasUpper) UL='U'; else if ( Uplo == CblasLower ) UL='L'; else { cblas_xerbla(2, "cblas_zherk", "Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if( Trans == CblasTrans) TR ='T'; else if ( Trans == CblasConjTrans ) TR='C'; else if ( Trans == CblasNoTrans ) TR='N'; else { cblas_xerbla(3, "cblas_zherk", "Illegal Trans setting, %d\n", Trans); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TR = C2F_CHAR(&TR); #endif F77_zherk(F77_UL, F77_TR, &F77_N, &F77_K, &alpha, (dcomplex*)A, &F77_lda, &beta, (dcomplex*)C, &F77_ldc); } else if (Order == CblasRowMajor) { RowMajorStrg = 1; if( Uplo == CblasUpper) UL='L'; else if ( Uplo == CblasLower ) UL='U'; else { cblas_xerbla(3, "cblas_zherk", "Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if( Trans == CblasTrans) TR ='N'; else if ( Trans == CblasConjTrans ) TR='N'; else if ( Trans == CblasNoTrans ) TR='C'; else { cblas_xerbla(3, "cblas_zherk", "Illegal Trans setting, %d\n", Trans); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_SD = C2F_CHAR(&SD); #endif F77_zherk(F77_UL, F77_TR, &F77_N, &F77_K, &alpha, (dcomplex*)A, &F77_lda, &beta, (dcomplex*)C, &F77_ldc); } else cblas_xerbla(1, "cblas_zherk", "Illegal Order setting, %d\n", Order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_zhpmv.c000066400000000000000000000067411422157504600213730ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_zhpmv.c * The program is a C interface of zhpmv * * Keita Teranishi 5/18/98 * */ #include #include #include "cblas.h" #include "cblas_f77.h" void cblas_zhpmv(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo,f77_int N, const void *alpha, const void *AP, const void *X, f77_int incX, const void *beta, void *Y, f77_int incY) { char UL; #ifdef F77_CHAR F77_CHAR F77_UL; #else #define F77_UL &UL #endif #ifdef F77_INT F77_INT F77_N=N, F77_incX=incX, F77_incY=incY; #else #define F77_N N #define F77_incX incX #define F77_incY incY #endif int n, i=0; const double *xx= (double *)X, *alp= (double *)alpha, *bet = (double *)beta; double ALPHA[2],BETA[2]; int tincY, tincx; double *x=(double *)X, *y=(double *)Y, *st=0, *tx; extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if (order == CblasColMajor) { if (Uplo == CblasLower) UL = 'L'; else if (Uplo == CblasUpper) UL = 'U'; else { cblas_xerbla(2, "cblas_zhpmv","Illegal Uplo setting, %d\n",Uplo ); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); #endif F77_zhpmv(F77_UL, &F77_N, (dcomplex*)alpha, (dcomplex*)AP, (dcomplex*)X, &F77_incX, (dcomplex*)beta, (dcomplex*)Y, &F77_incY); } else if (order == CblasRowMajor) { RowMajorStrg = 1; ALPHA[0]= *alp; ALPHA[1]= -alp[1]; BETA[0]= *bet; BETA[1]= -bet[1]; if (N > 0) { n = N << 1; x = malloc(n*sizeof(double)); tx = x; if( incX > 0 ) { i = incX << 1; tincx = 2; st= x+n; } else { i = incX *(-2); tincx = -2; st = x-2; x +=(n-2); } do { *x = *xx; x[1] = -xx[1]; x += tincx ; xx += i; } while (x != st); x=tx; #ifdef F77_INT F77_incX = 1; #else incX = 1; #endif if(incY > 0) tincY = incY; else tincY = -incY; y++; i = tincY << 1; n = i * N ; st = y + n; do { *y = -(*y); y += i; } while(y != st); y -= n; } else x = (double *) X; if (Uplo == CblasUpper) UL = 'L'; else if (Uplo == CblasLower) UL = 'U'; else { cblas_xerbla(2, "cblas_zhpmv","Illegal Uplo setting, %d\n", Uplo ); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); #endif F77_zhpmv(F77_UL, &F77_N, (dcomplex*)ALPHA, (dcomplex*)AP, (dcomplex*)x, &F77_incX, (dcomplex*)BETA, (dcomplex*)Y, &F77_incY); } else { cblas_xerbla(1, "cblas_zhpmv","Illegal Order setting, %d\n", order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if ( order == CblasRowMajor ) { RowMajorStrg = 1; if(X!=x) free(x); if (N > 0) { do { *y = -(*y); y += i; } while (y != st); } } CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_zhpr.c000066400000000000000000000050101422157504600211760ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_zhpr.c * The program is a C interface to zhpr. * * Keita Teranishi 3/23/98 * */ #include #include #include "cblas.h" #include "cblas_f77.h" void cblas_zhpr(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, f77_int N, double alpha, const void *X, f77_int incX, void *A) { char UL; #ifdef F77_CHAR F77_CHAR F77_UL; #else #define F77_UL &UL #endif #ifdef F77_INT F77_INT F77_N=N, F77_incX=incX; #else #define F77_N N #define F77_incX incX #endif int n, i, tincx; double *x=(double *)X, *xx=(double *)X, *tx, *st; extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if (order == CblasColMajor) { if (Uplo == CblasLower) UL = 'L'; else if (Uplo == CblasUpper) UL = 'U'; else { cblas_xerbla(2, "cblas_zhpr","Illegal Uplo setting, %d\n",Uplo ); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); #endif F77_zhpr(F77_UL, &F77_N, &alpha, (dcomplex*)X, &F77_incX, (dcomplex*)A); } else if (order == CblasRowMajor) { RowMajorStrg = 1; if (Uplo == CblasUpper) UL = 'L'; else if (Uplo == CblasLower) UL = 'U'; else { cblas_xerbla(2, "cblas_zhpr","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); #endif if (N > 0) { n = N << 1; x = malloc(n*sizeof(double)); tx = x; if( incX > 0 ) { i = incX << 1; tincx = 2; st= x+n; } else { i = incX *(-2); tincx = -2; st = x-2; x +=(n-2); } do { *x = *xx; x[1] = -xx[1]; x += tincx ; xx += i; } while (x != st); x=tx; #ifdef F77_INT F77_incX = 1; #else incX = 1; #endif } else x = (double *) X; F77_zhpr(F77_UL, &F77_N, &alpha, (dcomplex*)x, &F77_incX, (dcomplex*)A); } else { cblas_xerbla(1, "cblas_zhpr","Illegal Order setting, %d\n", order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if(X!=x) free(x); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_zhpr2.c000066400000000000000000000065071422157504600212740ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_zhpr2.c * The program is a C interface to zhpr2. * * Keita Teranishi 5/20/98 * */ #include #include #include "cblas.h" #include "cblas_f77.h" void cblas_zhpr2(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, f77_int N,const void *alpha, const void *X, f77_int incX,const void *Y, f77_int incY, void *Ap) { char UL; #ifdef F77_CHAR F77_CHAR F77_UL; #else #define F77_UL &UL #endif #ifdef F77_INT F77_INT F77_N=N, F77_incX=incX, F77_incY=incY; #else #define F77_N N #define F77_incX incX #define F77_incY incY #endif int n, i, j; double *x=(double *)X, *xx=(double *)X, *y=(double *)Y, *yy=(double *)Y, *stx, *sty; extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if (order == CblasColMajor) { if (Uplo == CblasLower) UL = 'L'; else if (Uplo == CblasUpper) UL = 'U'; else { cblas_xerbla(2, "cblas_zhpr2","Illegal Uplo setting, %d\n",Uplo ); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); #endif F77_zhpr2(F77_UL, &F77_N, (dcomplex*)alpha, (dcomplex*)X, &F77_incX, (dcomplex*)Y, &F77_incY, (dcomplex*)Ap); } else if (order == CblasRowMajor) { RowMajorStrg = 1; if (Uplo == CblasUpper) UL = 'L'; else if (Uplo == CblasLower) UL = 'U'; else { cblas_xerbla(2, "cblas_zhpr2","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); #endif if (N > 0) { n = N << 1; x = malloc(n*sizeof(double)); y = malloc(n*sizeof(double)); stx = x + n; sty = y + n; if( incX > 0 ) i = incX << 1; else i = incX *(-2); if( incY > 0 ) j = incY << 1; else j = incY *(-2); do { *x = *xx; x[1] = -xx[1]; x += 2; xx += i; } while (x != stx); do { *y = *yy; y[1] = -yy[1]; y += 2; yy += j; } while (y != sty); x -= n; y -= n; #ifdef F77_INT if(incX > 0 ) F77_incX = 1; else F77_incX = -1; if(incY > 0 ) F77_incY = 1; else F77_incY = -1; #else if(incX > 0 ) incX = 1; else incX = -1; if(incY > 0 ) incY = 1; else incY = -1; #endif } else { x = (double *) X; y = (void *) Y; } F77_zhpr2(F77_UL, &F77_N, (dcomplex*)alpha, (dcomplex*)y, &F77_incY, (dcomplex*)x, &F77_incX, (dcomplex*)Ap); } else { cblas_xerbla(1, "cblas_zhpr2","Illegal Order setting, %d\n", order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if(X!=x) free(x); if(Y!=y) free(y); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_zscal.c000066400000000000000000000007421422157504600213360ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_zscal.c * * The program is a C interface to zscal. * * Written by Keita Teranishi. 2/11/1998 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_zscal( f77_int N, const void *alpha, void *X, f77_int incX) { #ifdef F77_INT F77_INT F77_N=N, F77_incX=incX; #else #define F77_N N #define F77_incX incX #endif F77_zscal( &F77_N, (dcomplex*)alpha, (dcomplex*)X, &F77_incX); } #endif blis-0.9.0/frame/compat/cblas/src/cblas_zswap.c000066400000000000000000000010261422157504600213620ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_zswap.c * * The program is a C interface to zswap. * * Written by Keita Teranishi. 2/11/1998 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_zswap( f77_int N, void *X, f77_int incX, void *Y, f77_int incY) { #ifdef F77_INT F77_INT F77_N=N, F77_incX=incX, F77_incY=incY; #else #define F77_N N #define F77_incX incX #define F77_incY incY #endif F77_zswap( &F77_N, (dcomplex*)X, &F77_incX, (dcomplex*)Y, &F77_incY); } #endif blis-0.9.0/frame/compat/cblas/src/cblas_zsymm.c000066400000000000000000000053521422157504600214030ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * * cblas_zsymm.c * This program is a C interface to zsymm. * Written by Keita Teranishi * 4/8/1998 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_zsymm(enum CBLAS_ORDER Order, enum CBLAS_SIDE Side, enum CBLAS_UPLO Uplo, f77_int M, f77_int N, const void *alpha, const void *A, f77_int lda, const void *B, f77_int ldb, const void *beta, void *C, f77_int ldc) { char SD, UL; #ifdef F77_CHAR F77_CHAR F77_SD, F77_UL; #else #define F77_SD &SD #define F77_UL &UL #endif #ifdef F77_INT F77_INT F77_M=M, F77_N=N, F77_lda=lda, F77_ldb=ldb; F77_INT F77_ldc=ldc; #else #define F77_M M #define F77_N N #define F77_lda lda #define F77_ldb ldb #define F77_ldc ldc #endif extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if( Order == CblasColMajor ) { if( Side == CblasRight) SD='R'; else if ( Side == CblasLeft ) SD='L'; else { cblas_xerbla(2, "cblas_zsymm", "Illegal Side setting, %d\n", Side); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if( Uplo == CblasUpper) UL='U'; else if ( Uplo == CblasLower ) UL='L'; else { cblas_xerbla(3, "cblas_zsymm", "Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_SD = C2F_CHAR(&SD); #endif F77_zsymm(F77_SD, F77_UL, &F77_M, &F77_N, (dcomplex*)alpha, (dcomplex*)A, &F77_lda, (dcomplex*)B, &F77_ldb, (dcomplex*)beta, (dcomplex*)C, &F77_ldc); } else if (Order == CblasRowMajor) { RowMajorStrg = 1; if( Side == CblasRight) SD='L'; else if ( Side == CblasLeft ) SD='R'; else { cblas_xerbla(2, "cblas_zsymm", "Illegal Side setting, %d\n", Side); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if( Uplo == CblasUpper) UL='L'; else if ( Uplo == CblasLower ) UL='U'; else { cblas_xerbla(3, "cblas_zsymm", "Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_SD = C2F_CHAR(&SD); #endif F77_zsymm(F77_SD, F77_UL, &F77_N, &F77_M, (dcomplex*)alpha, (dcomplex*)A, &F77_lda, (dcomplex*)B, &F77_ldb, (dcomplex*)beta, (dcomplex*)C, &F77_ldc); } else cblas_xerbla(1, "cblas_zsymm", "Illegal Order setting, %d\n", Order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_zsyr2k.c000066400000000000000000000055471422157504600214760ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * * cblas_zsyr2k.c * This program is a C interface to zsyr2k. * Written by Keita Teranishi * 4/8/1998 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_zsyr2k(enum CBLAS_ORDER Order, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE Trans, f77_int N, f77_int K, const void *alpha, const void *A, f77_int lda, const void *B, f77_int ldb, const void *beta, void *C, f77_int ldc) { char UL, TR; #ifdef F77_CHAR F77_CHAR F77_TR, F77_UL; #else #define F77_TR &TR #define F77_UL &UL #endif #ifdef F77_INT F77_INT F77_N=N, F77_K=K, F77_lda=lda, F77_ldb=ldb; F77_INT F77_ldc=ldc; #else #define F77_N N #define F77_K K #define F77_lda lda #define F77_ldb ldb #define F77_ldc ldc #endif extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if( Order == CblasColMajor ) { if( Uplo == CblasUpper) UL='U'; else if ( Uplo == CblasLower ) UL='L'; else { cblas_xerbla(2, "cblas_zsyr2k", "Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if( Trans == CblasTrans) TR ='T'; else if ( Trans == CblasConjTrans ) TR='C'; else if ( Trans == CblasNoTrans ) TR='N'; else { cblas_xerbla(3, "cblas_zsyr2k", "Illegal Trans setting, %d\n", Trans); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TR = C2F_CHAR(&TR); #endif F77_zsyr2k(F77_UL, F77_TR, &F77_N, &F77_K, (dcomplex*)alpha, (dcomplex*)A, &F77_lda, (dcomplex*)B, &F77_ldb, (dcomplex*)beta, (dcomplex*)C, &F77_ldc); } else if (Order == CblasRowMajor) { RowMajorStrg = 1; if( Uplo == CblasUpper) UL='L'; else if ( Uplo == CblasLower ) UL='U'; else { cblas_xerbla(3, "cblas_zsyr2k", "Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if( Trans == CblasTrans) TR ='N'; else if ( Trans == CblasConjTrans ) TR='N'; else if ( Trans == CblasNoTrans ) TR='T'; else { cblas_xerbla(3, "cblas_zsyr2k", "Illegal Trans setting, %d\n", Trans); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TR = C2F_CHAR(&TR); #endif F77_zsyr2k(F77_UL, F77_TR, &F77_N, &F77_K, (dcomplex*)alpha, (dcomplex*)A, &F77_lda, (dcomplex*)B, &F77_ldb, (dcomplex*)beta, (dcomplex*)C, &F77_ldc); } else cblas_xerbla(1, "cblas_zsyr2k", "Illegal Order setting, %d\n", Order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_zsyrk.c000066400000000000000000000053461422157504600214110ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * * cblas_zsyrk.c * This program is a C interface to zsyrk. * Written by Keita Teranishi * 4/8/1998 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_zsyrk(enum CBLAS_ORDER Order, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE Trans, f77_int N, f77_int K, const void *alpha, const void *A, f77_int lda, const void *beta, void *C, f77_int ldc) { char UL, TR; #ifdef F77_CHAR F77_CHAR F77_TR, F77_UL; #else #define F77_TR &TR #define F77_UL &UL #endif #ifdef F77_INT F77_INT F77_N=N, F77_K=K, F77_lda=lda; F77_INT F77_ldc=ldc; #else #define F77_N N #define F77_K K #define F77_lda lda #define F77_ldc ldc #endif extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if( Order == CblasColMajor ) { if( Uplo == CblasUpper) UL='U'; else if ( Uplo == CblasLower ) UL='L'; else { cblas_xerbla(2, "cblas_zsyrk", "Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if( Trans == CblasTrans) TR ='T'; else if ( Trans == CblasConjTrans ) TR='C'; else if ( Trans == CblasNoTrans ) TR='N'; else { cblas_xerbla(3, "cblas_zsyrk", "Illegal Trans setting, %d\n", Trans); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TR = C2F_CHAR(&TR); #endif F77_zsyrk(F77_UL, F77_TR, &F77_N, &F77_K, (dcomplex*)alpha, (dcomplex*)A, &F77_lda, (dcomplex*)beta, (dcomplex*)C, &F77_ldc); } else if (Order == CblasRowMajor) { RowMajorStrg = 1; if( Uplo == CblasUpper) UL='L'; else if ( Uplo == CblasLower ) UL='U'; else { cblas_xerbla(3, "cblas_zsyrk", "Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if( Trans == CblasTrans) TR ='N'; else if ( Trans == CblasConjTrans ) TR='N'; else if ( Trans == CblasNoTrans ) TR='T'; else { cblas_xerbla(3, "cblas_zsyrk", "Illegal Trans setting, %d\n", Trans); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TR = C2F_CHAR(&TR); #endif F77_zsyrk(F77_UL, F77_TR, &F77_N, &F77_K, (dcomplex*)alpha, (dcomplex*)A, &F77_lda, (dcomplex*)beta, (dcomplex*)C, &F77_ldc); } else cblas_xerbla(1, "cblas_zsyrk", "Illegal Order setting, %d\n", Order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_ztbmv.c000066400000000000000000000077021422157504600213670ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_ztbmv.c * The program is a C interface to ztbmv. * * Keita Teranishi 5/20/98 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_ztbmv(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE TransA, enum CBLAS_DIAG Diag, f77_int N, f77_int K, const void *A, f77_int lda, void *X, f77_int incX) { char TA; char UL; char DI; #ifdef F77_CHAR F77_CHAR F77_TA, F77_UL, F77_DI; #else #define F77_TA &TA #define F77_UL &UL #define F77_DI &DI #endif #ifdef F77_INT F77_INT F77_N=N, F77_lda=lda, F77_K=K, F77_incX=incX; #else #define F77_N N #define F77_K K #define F77_lda lda #define F77_incX incX #endif int n, i=0, tincX; double *st=0, *x=(double *)X; extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if (order == CblasColMajor) { if (Uplo == CblasUpper) UL = 'U'; else if (Uplo == CblasLower) UL = 'L'; else { cblas_xerbla(2, "cblas_ztbmv","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (TransA == CblasNoTrans) TA = 'N'; else if (TransA == CblasTrans) TA = 'T'; else if (TransA == CblasConjTrans) TA = 'C'; else { cblas_xerbla(3, "cblas_ztbmv","Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (Diag == CblasUnit) DI = 'U'; else if (Diag == CblasNonUnit) DI = 'N'; else { cblas_xerbla(4, "cblas_ztbmv","Illegal Diag setting, %d\n", Diag); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TA = C2F_CHAR(&TA); F77_DI = C2F_CHAR(&DI); #endif F77_ztbmv( F77_UL, F77_TA, F77_DI, &F77_N, &F77_K, (dcomplex*)A, &F77_lda, (dcomplex*)X, &F77_incX); } else if (order == CblasRowMajor) { RowMajorStrg = 1; if (Uplo == CblasUpper) UL = 'L'; else if (Uplo == CblasLower) UL = 'U'; else { cblas_xerbla(2, "cblas_ztbmv","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (TransA == CblasNoTrans) TA = 'T'; else if (TransA == CblasTrans) TA = 'N'; else if (TransA == CblasConjTrans) { TA = 'N'; if ( N > 0) { if(incX > 0) tincX = incX; else tincX = -incX; i = tincX << 1; n = i * N; x++; st = x + n; do { *x = -(*x); x+= i; } while (x != st); x -= n; } } else { cblas_xerbla(3, "cblas_ztbmv","Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (Diag == CblasUnit) DI = 'U'; else if (Diag == CblasNonUnit) DI = 'N'; else { cblas_xerbla(4, "cblas_ztbmv","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TA = C2F_CHAR(&TA); F77_DI = C2F_CHAR(&DI); #endif F77_ztbmv( F77_UL, F77_TA, F77_DI, &F77_N, &F77_K, (dcomplex*)A, &F77_lda, (dcomplex*)X, &F77_incX); if (TransA == CblasConjTrans) { if (N > 0) { do { *x = -(*x); x += i; } while (x != st); } } } else cblas_xerbla(1, "cblas_ztbmv", "Illegal Order setting, %d\n", order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_ztbsv.c000066400000000000000000000077131422157504600213770ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_ztbsv.c * The program is a C interface to ztbsv. * * Keita Teranishi 3/23/98 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_ztbsv(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE TransA, enum CBLAS_DIAG Diag, f77_int N, f77_int K, const void *A, f77_int lda, void *X, f77_int incX) { char TA; char UL; char DI; #ifdef F77_CHAR F77_CHAR F77_TA, F77_UL, F77_DI; #else #define F77_TA &TA #define F77_UL &UL #define F77_DI &DI #endif #ifdef F77_INT F77_INT F77_N=N, F77_lda=lda, F77_K=K, F77_incX=incX; #else #define F77_N N #define F77_K K #define F77_lda lda #define F77_incX incX #endif int n, i=0, tincX; double *st=0,*x=(double *)X; extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if (order == CblasColMajor) { if (Uplo == CblasUpper) UL = 'U'; else if (Uplo == CblasLower) UL = 'L'; else { cblas_xerbla(2, "cblas_ztbsv","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (TransA == CblasNoTrans) TA = 'N'; else if (TransA == CblasTrans) TA = 'T'; else if (TransA == CblasConjTrans) TA = 'C'; else { cblas_xerbla(3, "cblas_ztbsv","Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (Diag == CblasUnit) DI = 'U'; else if (Diag == CblasNonUnit) DI = 'N'; else { cblas_xerbla(4, "cblas_ztbsv","Illegal Diag setting, %d\n", Diag); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TA = C2F_CHAR(&TA); F77_DI = C2F_CHAR(&DI); #endif F77_ztbsv( F77_UL, F77_TA, F77_DI, &F77_N, &F77_K, (dcomplex*)A, &F77_lda, (dcomplex*)X, &F77_incX); } else if (order == CblasRowMajor) { RowMajorStrg = 1; if (Uplo == CblasUpper) UL = 'L'; else if (Uplo == CblasLower) UL = 'U'; else { cblas_xerbla(2, "cblas_ztbsv","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (TransA == CblasNoTrans) TA = 'T'; else if (TransA == CblasTrans) TA = 'N'; else if (TransA == CblasConjTrans) { TA = 'N'; if ( N > 0) { if ( incX > 0 ) tincX = incX; else tincX = -incX; n = N*2*(tincX); x++; st=x+n; i = tincX << 1; do { *x = -(*x); x+=i; } while (x != st); x -= n; } } else { cblas_xerbla(3, "cblas_ztbsv","Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (Diag == CblasUnit) DI = 'U'; else if (Diag == CblasNonUnit) DI = 'N'; else { cblas_xerbla(4, "cblas_ztbsv","Illegal Diag setting, %d\n", Diag); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TA = C2F_CHAR(&TA); F77_DI = C2F_CHAR(&DI); #endif F77_ztbsv( F77_UL, F77_TA, F77_DI, &F77_N, &F77_K, (dcomplex*)A, &F77_lda, (dcomplex*)X, &F77_incX); if (TransA == CblasConjTrans) { if (N > 0) { do { *x = -(*x); x+= i; } while (x != st); } } } else cblas_xerbla(1, "cblas_ztbsv", "Illegal Order setting, %d\n", order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_ztpmv.c000066400000000000000000000074121422157504600214030ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_ztpmv.c * The program is a C interface to ztpmv. * * Keita Teranishi 5/20/98 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_ztpmv(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE TransA, enum CBLAS_DIAG Diag, f77_int N, const void *Ap, void *X, f77_int incX) { char TA; char UL; char DI; #ifdef F77_CHAR F77_CHAR F77_TA, F77_UL, F77_DI; #else #define F77_TA &TA #define F77_UL &UL #define F77_DI &DI #endif #ifdef F77_INT F77_INT F77_N=N, F77_incX=incX; #else #define F77_N N #define F77_incX incX #endif int n, i=0, tincX; double *st=0,*x=(double *)X; extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if (order == CblasColMajor) { if (Uplo == CblasUpper) UL = 'U'; else if (Uplo == CblasLower) UL = 'L'; else { cblas_xerbla(2, "cblas_ztpmv","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (TransA == CblasNoTrans) TA = 'N'; else if (TransA == CblasTrans) TA = 'T'; else if (TransA == CblasConjTrans) TA = 'C'; else { cblas_xerbla(3, "cblas_ztpmv","Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (Diag == CblasUnit) DI = 'U'; else if (Diag == CblasNonUnit) DI = 'N'; else { cblas_xerbla(4, "cblas_ztpmv","Illegal Diag setting, %d\n", Diag); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TA = C2F_CHAR(&TA); F77_DI = C2F_CHAR(&DI); #endif F77_ztpmv( F77_UL, F77_TA, F77_DI, &F77_N, (dcomplex*)Ap, (dcomplex*)X, &F77_incX); } else if (order == CblasRowMajor) { RowMajorStrg = 1; if (Uplo == CblasUpper) UL = 'L'; else if (Uplo == CblasLower) UL = 'U'; else { cblas_xerbla(2, "cblas_ztpmv","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (TransA == CblasNoTrans) TA = 'T'; else if (TransA == CblasTrans) TA = 'N'; else if (TransA == CblasConjTrans) { TA = 'N'; if ( N > 0) { if(incX > 0) tincX = incX; else tincX = -incX; i = tincX << 1; n = i * N; x++; st = x + n; do { *x = -(*x); x += i; } while (x != st); x -= n; } } else { cblas_xerbla(3, "cblas_ztpmv","Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (Diag == CblasUnit) DI = 'U'; else if (Diag == CblasNonUnit) DI = 'N'; else { cblas_xerbla(4, "cblas_ztpmv","Illegal Diag setting, %d\n", Diag); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TA = C2F_CHAR(&TA); F77_DI = C2F_CHAR(&DI); #endif F77_ztpmv( F77_UL, F77_TA, F77_DI, &F77_N, (dcomplex*)Ap, (dcomplex*)X,&F77_incX); if (TransA == CblasConjTrans) { if (N > 0) { do { *x = -(*x); x += i; } while (x != st); } } } else cblas_xerbla(1, "cblas_ztpmv", "Illegal Order setting, %d\n", order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_ztpsv.c000066400000000000000000000074241422157504600214140ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_ztpsv.c * The program is a C interface to ztpsv. * * Keita Teranishi 3/23/98 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_ztpsv(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE TransA, enum CBLAS_DIAG Diag, f77_int N, const void *Ap, void *X, f77_int incX) { char TA; char UL; char DI; #ifdef F77_CHAR F77_CHAR F77_TA, F77_UL, F77_DI; #else #define F77_TA &TA #define F77_UL &UL #define F77_DI &DI #endif #ifdef F77_INT F77_INT F77_N=N, F77_incX=incX; #else #define F77_N N #define F77_incX incX #endif int n, i=0, tincX; double *st=0, *x=(double*)X; extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if (order == CblasColMajor) { if (Uplo == CblasUpper) UL = 'U'; else if (Uplo == CblasLower) UL = 'L'; else { cblas_xerbla(2, "cblas_ztpsv","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (TransA == CblasNoTrans) TA = 'N'; else if (TransA == CblasTrans) TA = 'T'; else if (TransA == CblasConjTrans) TA = 'C'; else { cblas_xerbla(3, "cblas_ztpsv","Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (Diag == CblasUnit) DI = 'U'; else if (Diag == CblasNonUnit) DI = 'N'; else { cblas_xerbla(4, "cblas_ztpsv","Illegal Diag setting, %d\n", Diag); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TA = C2F_CHAR(&TA); F77_DI = C2F_CHAR(&DI); #endif F77_ztpsv( F77_UL, F77_TA, F77_DI, &F77_N, (dcomplex*)Ap, (dcomplex*)X, &F77_incX); } else if (order == CblasRowMajor) { RowMajorStrg = 1; if (Uplo == CblasUpper) UL = 'L'; else if (Uplo == CblasLower) UL = 'U'; else { cblas_xerbla(2, "cblas_ztpsv","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (TransA == CblasNoTrans) TA = 'T'; else if (TransA == CblasTrans) TA = 'N'; else if (TransA == CblasConjTrans) { TA = 'N'; if ( N > 0) { if ( incX > 0 ) tincX = incX; else tincX = -incX; n = N*2*(tincX); x++; st=x+n; i = tincX << 1; do { *x = -(*x); x+=i; } while (x != st); x -= n; } } else { cblas_xerbla(3, "cblas_ztpsv","Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (Diag == CblasUnit) DI = 'U'; else if (Diag == CblasNonUnit) DI = 'N'; else { cblas_xerbla(4, "cblas_ztpsv","Illegal Diag setting, %d\n", Diag); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TA = C2F_CHAR(&TA); F77_DI = C2F_CHAR(&DI); #endif F77_ztpsv( F77_UL, F77_TA, F77_DI, &F77_N, (dcomplex*)Ap, (dcomplex*)X,&F77_incX); if (TransA == CblasConjTrans) { if (N > 0) { do { *x = -(*x); x += i; } while (x != st); } } } else cblas_xerbla(1, "cblas_ztpsv", "Illegal Order setting, %d\n", order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_ztrmm.c000066400000000000000000000077361422157504600214050ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * * cblas_ztrmm.c * This program is a C interface to ztrmm. * Written by Keita Teranishi * 4/8/1998 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_ztrmm(enum CBLAS_ORDER Order, enum CBLAS_SIDE Side, enum CBLAS_UPLO Uplo, const enum CBLAS_TRANSPOSE TransA, enum CBLAS_DIAG Diag, f77_int M, f77_int N, const void *alpha, const void *A, f77_int lda, void *B, f77_int ldb) { char UL, TA, SD, DI; #ifdef F77_CHAR F77_CHAR F77_TA, F77_UL, F77_SD, F77_DI; #else #define F77_TA &TA #define F77_UL &UL #define F77_SD &SD #define F77_DI &DI #endif #ifdef F77_INT F77_INT F77_M=M, F77_N=N, F77_lda=lda, F77_ldb=ldb; #else #define F77_M M #define F77_N N #define F77_lda lda #define F77_ldb ldb #endif extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if( Order == CblasColMajor ) { if( Side == CblasRight ) SD='R'; else if ( Side == CblasLeft ) SD='L'; else { cblas_xerbla(2, "cblas_ztrmm", "Illegal Side setting, %d\n", Side); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if( Uplo == CblasUpper ) UL='U'; else if ( Uplo == CblasLower ) UL='L'; else { cblas_xerbla(3, "cblas_ztrmm", "Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if( TransA == CblasTrans ) TA ='T'; else if ( TransA == CblasConjTrans ) TA='C'; else if ( TransA == CblasNoTrans ) TA='N'; else { cblas_xerbla(4, "cblas_ztrmm", "Illegal Trans setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if( Diag == CblasUnit ) DI='U'; else if ( Diag == CblasNonUnit ) DI='N'; else { cblas_xerbla(5, "cblas_ztrmm", "Illegal Diag setting, %d\n", Diag); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TA = C2F_CHAR(&TA); F77_SD = C2F_CHAR(&SD); F77_DI = C2F_CHAR(&DI); #endif F77_ztrmm(F77_SD, F77_UL, F77_TA, F77_DI, &F77_M, &F77_N, (dcomplex*)alpha, (dcomplex*)A, &F77_lda, (dcomplex*)B, &F77_ldb); } else if (Order == CblasRowMajor) { RowMajorStrg = 1; if( Side == CblasRight ) SD='L'; else if ( Side == CblasLeft ) SD='R'; else { cblas_xerbla(2, "cblas_ztrmm", "Illegal Side setting, %d\n", Side); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if( Uplo == CblasUpper ) UL='L'; else if ( Uplo == CblasLower ) UL='U'; else { cblas_xerbla(3, "cblas_ztrmm", "Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if( TransA == CblasTrans ) TA ='T'; else if ( TransA == CblasConjTrans ) TA='C'; else if ( TransA == CblasNoTrans ) TA='N'; else { cblas_xerbla(4, "cblas_ztrmm", "Illegal Trans setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if( Diag == CblasUnit ) DI='U'; else if ( Diag == CblasNonUnit ) DI='N'; else { cblas_xerbla(5, "cblas_ztrmm", "Illegal Diag setting, %d\n", Diag); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TA = C2F_CHAR(&TA); F77_SD = C2F_CHAR(&SD); F77_DI = C2F_CHAR(&DI); #endif F77_ztrmm(F77_SD, F77_UL, F77_TA, F77_DI, &F77_N, &F77_M, (dcomplex*)alpha, (dcomplex*)A, &F77_lda, (dcomplex*)B, &F77_ldb); } else cblas_xerbla(1, "cblas_ztrmm", "Illegal Order setting, %d\n", Order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_ztrmv.c000066400000000000000000000076151422157504600214120ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_ztrmv.c * The program is a C interface to ztrmv. * * Keita Teranishi 5/20/98 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_ztrmv(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE TransA, enum CBLAS_DIAG Diag, f77_int N, const void *A, f77_int lda, void *X, f77_int incX) { char TA; char UL; char DI; #ifdef F77_CHAR F77_CHAR F77_TA, F77_UL, F77_DI; #else #define F77_TA &TA #define F77_UL &UL #define F77_DI &DI #endif #ifdef F77_INT F77_INT F77_N=N, F77_lda=lda, F77_incX=incX; #else #define F77_N N #define F77_lda lda #define F77_incX incX #endif int n, i=0, tincX; double *st=0,*x=(double *)X; extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if (order == CblasColMajor) { if (Uplo == CblasUpper) UL = 'U'; else if (Uplo == CblasLower) UL = 'L'; else { cblas_xerbla(2, "cblas_ztrmv","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (TransA == CblasNoTrans) TA = 'N'; else if (TransA == CblasTrans) TA = 'T'; else if (TransA == CblasConjTrans) TA = 'C'; else { cblas_xerbla(3, "cblas_ztrmv","Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (Diag == CblasUnit) DI = 'U'; else if (Diag == CblasNonUnit) DI = 'N'; else { cblas_xerbla(4, "cblas_ztrmv","Illegal Diag setting, %d\n", Diag); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TA = C2F_CHAR(&TA); F77_DI = C2F_CHAR(&DI); #endif F77_ztrmv( F77_UL, F77_TA, F77_DI, &F77_N, (dcomplex*)A, &F77_lda, (dcomplex*)X, &F77_incX); } else if (order == CblasRowMajor) { RowMajorStrg = 1; if (Uplo == CblasUpper) UL = 'L'; else if (Uplo == CblasLower) UL = 'U'; else { cblas_xerbla(2, "cblas_ztrmv","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (TransA == CblasNoTrans) TA = 'T'; else if (TransA == CblasTrans) TA = 'N'; else if (TransA == CblasConjTrans) { TA = 'N'; if ( N > 0) { if(incX > 0) tincX = incX; else tincX = -incX; i = tincX << 1; n = i * N; x++; st = x + n; do { *x = -(*x); x += i; } while (x != st); x -= n; } } else { cblas_xerbla(3, "cblas_ztrmv","Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (Diag == CblasUnit) DI = 'U'; else if (Diag == CblasNonUnit) DI = 'N'; else { cblas_xerbla(4, "cblas_ztrmv","Illegal Diag setting, %d\n", Diag); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TA = C2F_CHAR(&TA); F77_DI = C2F_CHAR(&DI); #endif F77_ztrmv( F77_UL, F77_TA, F77_DI, &F77_N, (dcomplex*)A, &F77_lda, (dcomplex*)X, &F77_incX); if (TransA == CblasConjTrans) { if (N > 0) { do { *x = -(*x); x += i; } while (x != st); } } } else cblas_xerbla(1, "cblas_ztrmv", "Illegal Order setting, %d\n", order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_ztrsm.c000066400000000000000000000077561422157504600214150ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * * cblas_ztrsm.c * This program is a C interface to ztrsm. * Written by Keita Teranishi * 4/8/1998 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_ztrsm(enum CBLAS_ORDER Order, enum CBLAS_SIDE Side, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE TransA, enum CBLAS_DIAG Diag, f77_int M, f77_int N, const void *alpha, const void *A, f77_int lda, void *B, f77_int ldb) { char UL, TA, SD, DI; #ifdef F77_CHAR F77_CHAR F77_TA, F77_UL, F77_SD, F77_DI; #else #define F77_TA &TA #define F77_UL &UL #define F77_SD &SD #define F77_DI &DI #endif #ifdef F77_INT F77_INT F77_M=M, F77_N=N, F77_lda=lda, F77_ldb=ldb; #else #define F77_M M #define F77_N N #define F77_lda lda #define F77_ldb ldb #endif extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if( Order == CblasColMajor ) { if( Side == CblasRight) SD='R'; else if ( Side == CblasLeft ) SD='L'; else { cblas_xerbla(2, "cblas_ztrsm", "Illegal Side setting, %d\n", Side); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if( Uplo == CblasUpper) UL='U'; else if ( Uplo == CblasLower ) UL='L'; else { cblas_xerbla(3, "cblas_ztrsm", "Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if( TransA == CblasTrans) TA ='T'; else if ( TransA == CblasConjTrans ) TA='C'; else if ( TransA == CblasNoTrans ) TA='N'; else { cblas_xerbla(4, "cblas_ztrsm", "Illegal Trans setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if( Diag == CblasUnit ) DI='U'; else if ( Diag == CblasNonUnit ) DI='N'; else { cblas_xerbla(5, "cblas_ztrsm", "Illegal Diag setting, %d\n", Diag); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TA = C2F_CHAR(&TA); F77_SD = C2F_CHAR(&SD); F77_DI = C2F_CHAR(&DI); #endif F77_ztrsm(F77_SD, F77_UL, F77_TA, F77_DI, &F77_M, &F77_N, (dcomplex*)alpha, (dcomplex*)A, &F77_lda, (dcomplex*)B, &F77_ldb); } else if (Order == CblasRowMajor) { RowMajorStrg = 1; if( Side == CblasRight) SD='L'; else if ( Side == CblasLeft ) SD='R'; else { cblas_xerbla(2, "cblas_ztrsm", "Illegal Side setting, %d\n", Side); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if( Uplo == CblasUpper) UL='L'; else if ( Uplo == CblasLower ) UL='U'; else { cblas_xerbla(3, "cblas_ztrsm", "Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if( TransA == CblasTrans) TA ='T'; else if ( TransA == CblasConjTrans ) TA='C'; else if ( TransA == CblasNoTrans ) TA='N'; else { cblas_xerbla(4, "cblas_ztrsm", "Illegal Trans setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if( Diag == CblasUnit ) DI='U'; else if ( Diag == CblasNonUnit ) DI='N'; else { cblas_xerbla(5, "cblas_ztrsm", "Illegal Diag setting, %d\n", Diag); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TA = C2F_CHAR(&TA); F77_SD = C2F_CHAR(&SD); F77_DI = C2F_CHAR(&DI); #endif F77_ztrsm(F77_SD, F77_UL, F77_TA, F77_DI, &F77_N, &F77_M, (dcomplex*)alpha, (dcomplex*)A, &F77_lda, (dcomplex*)B, &F77_ldb); } else cblas_xerbla(1, "cblas_ztrsm", "Illegal Order setting, %d\n", Order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/cblas_ztrsv.c000066400000000000000000000076171422157504600214220ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_ztrsv.c * The program is a C interface to ztrsv. * * Keita Teranishi 3/23/98 * */ #include "cblas.h" #include "cblas_f77.h" void cblas_ztrsv(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE TransA, enum CBLAS_DIAG Diag, f77_int N, const void *A, f77_int lda, void *X, f77_int incX) { char TA; char UL; char DI; #ifdef F77_CHAR F77_CHAR F77_TA, F77_UL, F77_DI; #else #define F77_TA &TA #define F77_UL &UL #define F77_DI &DI #endif #ifdef F77_INT F77_INT F77_N=N, F77_lda=lda, F77_incX=incX; #else #define F77_N N #define F77_lda lda #define F77_incX incX #endif int n, i=0, tincX; double *st=0,*x=(double *)X; extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if (order == CblasColMajor) { if (Uplo == CblasUpper) UL = 'U'; else if (Uplo == CblasLower) UL = 'L'; else { cblas_xerbla(2, "cblas_ztrsv","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (TransA == CblasNoTrans) TA = 'N'; else if (TransA == CblasTrans) TA = 'T'; else if (TransA == CblasConjTrans) TA = 'C'; else { cblas_xerbla(3, "cblas_ztrsv","Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (Diag == CblasUnit) DI = 'U'; else if (Diag == CblasNonUnit) DI = 'N'; else { cblas_xerbla(4, "cblas_ztrsv","Illegal Diag setting, %d\n", Diag); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TA = C2F_CHAR(&TA); F77_DI = C2F_CHAR(&DI); #endif F77_ztrsv( F77_UL, F77_TA, F77_DI, &F77_N, (dcomplex*)A, &F77_lda, (dcomplex*)X, &F77_incX); } else if (order == CblasRowMajor) { RowMajorStrg = 1; if (Uplo == CblasUpper) UL = 'L'; else if (Uplo == CblasLower) UL = 'U'; else { cblas_xerbla(2, "cblas_ztrsv","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (TransA == CblasNoTrans) TA = 'T'; else if (TransA == CblasTrans) TA = 'N'; else if (TransA == CblasConjTrans) { TA = 'N'; if ( N > 0) { if ( incX > 0 ) tincX = incX; else tincX = -incX; n = N*2*(tincX); x++; st=x+n; i = tincX << 1; do { *x = -(*x); x+=i; } while (x != st); x -= n; } } else { cblas_xerbla(3, "cblas_ztrsv","Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if (Diag == CblasUnit) DI = 'U'; else if (Diag == CblasNonUnit) DI = 'N'; else { cblas_xerbla(4, "cblas_ztrsv","Illegal Diag setting, %d\n", Diag); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TA = C2F_CHAR(&TA); F77_DI = C2F_CHAR(&DI); #endif F77_ztrsv( F77_UL, F77_TA, F77_DI, &F77_N, (dcomplex*)A, &F77_lda, (dcomplex*)X, &F77_incX); if (TransA == CblasConjTrans) { if (N > 0) { do { *x = -(*x); x += i; } while (x != st); } } } else cblas_xerbla(1, "cblas_ztrsv", "Illegal Order setting, %d\n", order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/extra/000077500000000000000000000000001422157504600200325ustar00rootroot00000000000000blis-0.9.0/frame/compat/cblas/src/extra/cblas_caxpby.c000066400000000000000000000012061422157504600226270ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_caxpby.c * * The program is a C interface to caxpby. * * Copyright (C) 2020, Advanced Micro Devices, Inc * */ #include "cblas.h" #include "cblas_f77.h" void cblas_caxpby( f77_int N, const void *alpha, const void *X, f77_int incX, const void *beta, void *Y, f77_int incY) { #ifdef F77_INT F77_INT F77_N=N, F77_incX=incX, F77_incY=incY; #else #define F77_N N #define F77_incX incX #define F77_incY incY #endif F77_caxpby( &F77_N, (scomplex*)alpha, (scomplex*)X, &F77_incX, (scomplex*)beta, (scomplex*)Y, &F77_incY); } #endif blis-0.9.0/frame/compat/cblas/src/extra/cblas_cgemm3m.c000066400000000000000000000061551422157504600227010ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * * cblas_cgemm3m.c * * This program is a C interface to cgemm3m. * * Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved. * */ #include "cblas.h" #include "cblas_f77.h" void cblas_cgemm3m(enum CBLAS_ORDER Order, enum CBLAS_TRANSPOSE TransA, enum CBLAS_TRANSPOSE TransB, f77_int M, f77_int N, f77_int K, const void *alpha, const void *A, f77_int lda, const void *B, f77_int ldb, const void *beta, void *C, f77_int ldc) { char TA, TB; #ifdef F77_CHAR F77_CHAR F77_TA, F77_TB; #else #define F77_TA &TA #define F77_TB &TB #endif #ifdef F77_INT F77_INT F77_M=M, F77_N=N, F77_K=K, F77_lda=lda, F77_ldb=ldb; F77_INT F77_ldc=ldc; #else #define F77_M M #define F77_N N #define F77_K K #define F77_lda lda #define F77_ldb ldb #define F77_ldc ldc #endif extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if( Order == CblasColMajor ) { if(TransA == CblasTrans) TA='T'; else if ( TransA == CblasConjTrans ) TA='C'; else if ( TransA == CblasNoTrans ) TA='N'; else { cblas_xerbla(2, "cblas_cgemm3m", "Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if(TransB == CblasTrans) TB='T'; else if ( TransB == CblasConjTrans ) TB='C'; else if ( TransB == CblasNoTrans ) TB='N'; else { cblas_xerbla(3, "cblas_cgemm3m", "Illegal TransB setting, %d\n", TransB); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_TA = C2F_CHAR(&TA); F77_TB = C2F_CHAR(&TB); #endif F77_cgemm3m(F77_TA, F77_TB, &F77_M, &F77_N, &F77_K, (scomplex*)alpha, (scomplex*)A, &F77_lda, (scomplex*)B, &F77_ldb, (scomplex*)beta, (scomplex*)C, &F77_ldc); } else if (Order == CblasRowMajor) { RowMajorStrg = 1; if(TransA == CblasTrans) TB='T'; else if ( TransA == CblasConjTrans ) TB='C'; else if ( TransA == CblasNoTrans ) TB='N'; else { cblas_xerbla(2, "cblas_cgemm3m", "Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if(TransB == CblasTrans) TA='T'; else if ( TransB == CblasConjTrans ) TA='C'; else if ( TransB == CblasNoTrans ) TA='N'; else { cblas_xerbla(2, "cblas_cgemm3m", "Illegal TransB setting, %d\n", TransB); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_TA = C2F_CHAR(&TA); F77_TB = C2F_CHAR(&TB); #endif F77_cgemm3m(F77_TA, F77_TB, &F77_N, &F77_M, &F77_K, (scomplex*)alpha, (scomplex*)B, &F77_ldb, (scomplex*)A, &F77_lda, (scomplex*)beta, (scomplex*)C, &F77_ldc); } else cblas_xerbla(1, "cblas_cgemm3m", "Illegal Order setting, %d\n", Order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/extra/cblas_cgemm_batch.c000066400000000000000000000127311422157504600235770ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * * cblas_cgemm_batch.c * This program is a C interface to cgemm_batch. * * Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved. * */ #include "cblas.h" #include "cblas_f77.h" void cblas_cgemm_batch(enum CBLAS_ORDER Order, enum CBLAS_TRANSPOSE *TransA_array, enum CBLAS_TRANSPOSE *TransB_array, f77_int *M_array, f77_int *N_array, f77_int *K_array, const void *alpha_array, const void **A_array, f77_int *lda_array, const void **B_array, f77_int *ldb_array, const void *beta_array, void **C_array, f77_int *ldc_array, f77_int group_count, f77_int *group_size) { char TA[group_count], TB[group_count]; #ifdef F77_CHAR F77_CHAR F77_TA[group_count], F77_TB[group_count]; #else #define F77_TA TA #define F77_TB TB #endif #ifdef F77_INT F77_INT F77_GRP_COUNT = group_count; F77_INT F77_M[F77_GRP_COUNT], F77_N[F77_GRP_COUNT], F77_K[F77_GRP_COUNT]; F77_INT F77_lda[F77_GRP_COUNT], F77_ldb[F77_GRP_COUNT], F77_ldc[F77_GRP_COUNT]; F77_INT F77_GRP_SIZE[F77_GRP_COUNT]; #else #define F77_GRP_COUNT group_count #define F77_M M_array #define F77_N N_array #define F77_K K_array #define F77_lda lda_array #define F77_ldb ldb_array #define F77_ldc ldc_array #define F77_GRP_SIZE group_size #endif extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; dim_t i; if( Order == CblasColMajor ) { for(i = 0; i < group_count; i++) { if(TransA_array[i] == CblasTrans) TA[i]='T'; else if ( TransA_array[i] == CblasConjTrans ) TA[i]='C'; else if ( TransA_array[i] == CblasNoTrans ) TA[i]='N'; else { cblas_xerbla(2, "cblas_cgemm_batch", "Illegal TransA setting %d for group %d\n", TransA_array[i], i); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if(TransB_array[i] == CblasTrans) TB[i]='T'; else if ( TransB_array[i] == CblasConjTrans ) TB[i]='C'; else if ( TransB_array[i] == CblasNoTrans ) TB[i]='N'; else { cblas_xerbla(3, "cblas_cgemm_batch", "Illegal TransB setting %d for group %d\n", TransB_array[i], i); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_TA[i] = C2F_CHAR(TA+i); F77_TB[i] = C2F_CHAR(TB+i); #endif #ifdef F77_INT F77_M[i] = M_array[i]; F77_N[i] = N_array[i]; F77_K[i] = K_array[i]; F77_lda[i] = lda_array[i]; F77_ldb[i] = ldb_array[i]; F77_ldc[i] = ldc_array[i]; F77_GRP_SIZE[i] = group_size[i]; #endif } F77_cgemm_batch(F77_TA, F77_TB, F77_M, F77_N, F77_K, (const scomplex*)alpha_array, (const scomplex**)A_array, F77_lda, (const scomplex**)B_array, F77_ldb, (const scomplex*)beta_array, (scomplex**)C_array, F77_ldc, &F77_GRP_COUNT, F77_GRP_SIZE); } else if (Order == CblasRowMajor) { RowMajorStrg = 1; dim_t i; for(i = 0; i < group_count; i++) { if(TransA_array[i] == CblasTrans) TB[i]='T'; else if ( TransA_array[i] == CblasConjTrans ) TB[i]='C'; else if ( TransA_array[i] == CblasNoTrans ) TB[i]='N'; else { cblas_xerbla(2, "cblas_cgemm_batch", "Illegal TransA setting %d for group %d\n", TransA_array[i], i); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if(TransB_array[i] == CblasTrans) TA[i]='T'; else if ( TransB_array[i] == CblasConjTrans ) TA[i]='C'; else if ( TransB_array[i] == CblasNoTrans ) TA[i]='N'; else { cblas_xerbla(2, "cblas_cgemm_batch", "Illegal TransB setting %d for group %d\n", TransB_array[i], i); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_TA = C2F_CHAR(&TA); F77_TB = C2F_CHAR(&TB); #endif #ifdef F77_INT F77_M[i] = M_array[i]; F77_N[i] = N_array[i]; F77_K[i] = K_array[i]; F77_lda[i] = lda_array[i]; F77_ldb[i] = ldb_array[i]; F77_ldc[i] = ldc_array[i]; F77_GRP_SIZE = group_size[i]; #endif } F77_cgemm_batch(F77_TA, F77_TB, F77_N, F77_M, F77_K, (const scomplex*)alpha_array, (const scomplex**)B_array, F77_ldb, (const scomplex**)A_array, F77_lda, (const scomplex*)beta_array, (scomplex**)C_array, F77_ldc, &F77_GRP_COUNT, F77_GRP_SIZE); } else cblas_xerbla(1, "cblas_cgemm_batch", "Illegal Order setting, %d\n", Order); CBLAS_CallFromC = 0; RowMajorStrg = 0; } #endif blis-0.9.0/frame/compat/cblas/src/extra/cblas_cgemmt.c000066400000000000000000000123451422157504600226230ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* cblas_cgemmt.c Based off of cblas_cgemm.c. */ /* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "cblas.h" #include "cblas_f77.h" void cblas_cgemmt(enum CBLAS_ORDER Order, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE TransA, enum CBLAS_TRANSPOSE TransB, f77_int M, f77_int K, const void *alpha, const void *A, f77_int lda, const void *B, f77_int ldb, const void *beta, void *C, f77_int ldc) { char UL, TA, TB; #ifdef F77_CHAR F77_CHAR F77_UL, F77_TA, F77_TB; #else #define F77_UL &UL #define F77_TA &TA #define F77_TB &TB #endif #ifdef F77_INT F77_INT F77_M=M, F77_K=K, F77_lda=lda, F77_ldb=ldb; F77_INT F77_ldc=ldc; #else #define F77_M M #define F77_K K #define F77_lda lda #define F77_ldb ldb #define F77_ldc ldc #endif extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if( Order == CblasColMajor ) { if( Uplo == CblasUpper) UL='U'; else if ( Uplo == CblasLower ) UL='L'; else { cblas_xerbla(2, "cblas_cgemmt","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if(TransA == CblasTrans) TA='T'; else if ( TransA == CblasConjTrans ) TA='C'; else if ( TransA == CblasNoTrans ) TA='N'; else { cblas_xerbla(3, "cblas_cgemmt","Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if(TransB == CblasTrans) TB='T'; else if ( TransB == CblasConjTrans ) TB='C'; else if ( TransB == CblasNoTrans ) TB='N'; else { cblas_xerbla(4, "cblas_cgemmt","Illegal TransB setting, %d\n", TransB); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TA = C2F_CHAR(&TA); F77_TB = C2F_CHAR(&TB); #endif F77_cgemmt(F77_UL, F77_TA, F77_TB, &F77_M, &F77_K, (scomplex*)alpha, (scomplex*)A, &F77_lda, (scomplex*)B, &F77_ldb, (scomplex*)beta, (scomplex*)C, &F77_ldc); } else if (Order == CblasRowMajor) { RowMajorStrg = 1; if( Uplo == CblasUpper) UL='L'; else if ( Uplo == CblasLower ) UL='U'; else { cblas_xerbla(2, "cblas_cgemmt","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if(TransA == CblasTrans) TB='T'; else if ( TransA == CblasConjTrans ) TB='C'; else if ( TransA == CblasNoTrans ) TB='N'; else { cblas_xerbla(3, "cblas_cgemmt","Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if(TransB == CblasTrans) TA='T'; else if ( TransB == CblasConjTrans ) TA='C'; else if ( TransB == CblasNoTrans ) TA='N'; else { cblas_xerbla(4, "cblas_cgemmt","Illegal TransB setting, %d\n", TransB); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TA = C2F_CHAR(&TA); F77_TB = C2F_CHAR(&TB); #endif F77_cgemmt(F77_UL, F77_TA, F77_TB, &F77_M, &F77_K, (scomplex*)alpha, (scomplex*)B, &F77_ldb, (scomplex*)A, &F77_lda, (scomplex*)beta, (scomplex*)C, &F77_ldc); } else cblas_xerbla(1, "cblas_cgemmt", "Illegal Order setting, %d\n", Order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/extra/cblas_daxpby.c000066400000000000000000000011221422157504600226250ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_daxpby.c * * The program is a C interface to daxpby. * * Copyright (C) 2020, Advanced Micro Devices, Inc. */ #include "cblas.h" #include "cblas_f77.h" void cblas_daxpby( f77_int N, double alpha, const double *X, f77_int incX, double beta, double *Y, f77_int incY) { #ifdef F77_INT F77_INT F77_N=N, F77_incX=incX, F77_incY=incY; #else #define F77_N N #define F77_incX incX #define F77_incY incY #endif F77_daxpby( &F77_N, &alpha, X, &F77_incX, &beta, Y, &F77_incY); } #endif blis-0.9.0/frame/compat/cblas/src/extra/cblas_dgemm_batch.c000066400000000000000000000124771422157504600236070ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * * cblas_dgemm_batch.c * This program is a C interface to dgemm_batch. * * Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved. * */ #include "cblas.h" #include "cblas_f77.h" void cblas_dgemm_batch(enum CBLAS_ORDER Order, enum CBLAS_TRANSPOSE *TransA_array, enum CBLAS_TRANSPOSE *TransB_array, f77_int *M_array, f77_int *N_array, f77_int *K_array, const double *alpha_array, const double **A_array, f77_int *lda_array, const double **B_array, f77_int *ldb_array, const double *beta_array, double **C_array, f77_int *ldc_array, f77_int group_count, f77_int *group_size) { char TA[group_count], TB[group_count]; #ifdef F77_CHAR F77_CHAR F77_TA[group_count], F77_TB[group_count]; #else #define F77_TA TA #define F77_TB TB #endif #ifdef F77_INT F77_INT F77_GRP_COUNT = group_count; F77_INT F77_M[F77_GRP_COUNT], F77_N[F77_GRP_COUNT], F77_K[F77_GRP_COUNT]; F77_INT F77_lda[F77_GRP_COUNT], F77_ldb[F77_GRP_COUNT], F77_ldc[F77_GRP_COUNT]; F77_INT F77_GRP_SIZE[F77_GRP_COUNT]; #else #define F77_GRP_COUNT group_count #define F77_M M_array #define F77_N N_array #define F77_K K_array #define F77_lda lda_array #define F77_ldb ldb_array #define F77_ldc ldc_array #define F77_GRP_SIZE group_size #endif extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; dim_t i; if( Order == CblasColMajor ) { for(i = 0; i < group_count; i++) { if(TransA_array[i] == CblasTrans) TA[i]='T'; else if ( TransA_array[i] == CblasConjTrans ) TA[i]='C'; else if ( TransA_array[i] == CblasNoTrans ) TA[i]='N'; else { cblas_xerbla(2, "cblas_dgemm_batch", "Illegal TransA setting %d for group %d\n", TransA_array[i], i); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if(TransB_array[i] == CblasTrans) TB[i]='T'; else if ( TransB_array[i] == CblasConjTrans ) TB[i]='C'; else if ( TransB_array[i] == CblasNoTrans ) TB[i]='N'; else { cblas_xerbla(3, "cblas_dgemm_batch", "Illegal TransB setting %d for group %d\n", TransB_array[i], i); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_TA[i] = C2F_CHAR(TA+i); F77_TB[i] = C2F_CHAR(TB+i); #endif #ifdef F77_INT F77_M[i] = M_array[i]; F77_N[i] = N_array[i]; F77_K[i] = K_array[i]; F77_lda[i] = lda_array[i]; F77_ldb[i] = ldb_array[i]; F77_ldc[i] = ldc_array[i]; F77_GRP_SIZE[i] = group_size[i]; #endif } F77_dgemm_batch(F77_TA, F77_TB, F77_M, F77_N, F77_K, alpha_array, A_array, F77_lda, B_array, F77_ldb, beta_array, C_array, F77_ldc, &F77_GRP_COUNT, F77_GRP_SIZE); } else if (Order == CblasRowMajor) { RowMajorStrg = 1; dim_t i; for(i = 0; i < group_count; i++) { if(TransA_array[i] == CblasTrans) TB[i]='T'; else if ( TransA_array[i] == CblasConjTrans ) TB[i]='C'; else if ( TransA_array[i] == CblasNoTrans ) TB[i]='N'; else { cblas_xerbla(2, "cblas_dgemm_batch", "Illegal TransA setting %d for group %d\n", TransA_array[i], i); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if(TransB_array[i] == CblasTrans) TA[i]='T'; else if ( TransB_array[i] == CblasConjTrans ) TA[i]='C'; else if ( TransB_array[i] == CblasNoTrans ) TA[i]='N'; else { cblas_xerbla(2, "cblas_dgemm_batch", "Illegal TransB setting %d for group %d\n", TransB_array[i], i); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_TA = C2F_CHAR(&TA); F77_TB = C2F_CHAR(&TB); #endif #ifdef F77_INT F77_M[i] = M_array[i]; F77_N[i] = N_array[i]; F77_K[i] = K_array[i]; F77_lda[i] = lda_array[i]; F77_ldb[i] = ldb_array[i]; F77_ldc[i] = ldc_array[i]; F77_GRP_SIZE = group_size[i]; #endif } F77_dgemm_batch(F77_TA, F77_TB, F77_N, F77_M, F77_K, alpha_array, B_array, F77_ldb, A_array, F77_lda, beta_array, C_array, F77_ldc, &F77_GRP_COUNT, F77_GRP_SIZE); } else cblas_xerbla(1, "cblas_dgemm_batch", "Illegal Order setting, %d\n", Order); CBLAS_CallFromC = 0; RowMajorStrg = 0; } #endif blis-0.9.0/frame/compat/cblas/src/extra/cblas_dgemmt.c000066400000000000000000000121671422157504600226260ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* cblas_dgemmt.c Based off of cblas_dgemm.c. */ /* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "cblas.h" #include "cblas_f77.h" void cblas_dgemmt(enum CBLAS_ORDER Order, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE TransA, enum CBLAS_TRANSPOSE TransB, f77_int M, f77_int K, double alpha, const double *A, f77_int lda, const double *B, f77_int ldb, double beta, double *C, f77_int ldc) { char UL, TA, TB; #ifdef F77_CHAR F77_CHAR F77_UL, F77_TA, F77_TB; #else #define F77_UL &UL #define F77_TA &TA #define F77_TB &TB #endif #ifdef F77_INT F77_INT F77_M=M, F77_K=K, F77_lda=lda, F77_ldb=ldb; F77_INT F77_ldc=ldc; #else #define F77_M M #define F77_K K #define F77_lda lda #define F77_ldb ldb #define F77_ldc ldc #endif extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if( Order == CblasColMajor ) { if( Uplo == CblasUpper) UL='U'; else if ( Uplo == CblasLower ) UL='L'; else { cblas_xerbla(2, "cblas_dgemmt","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if(TransA == CblasTrans) TA='T'; else if ( TransA == CblasConjTrans ) TA='C'; else if ( TransA == CblasNoTrans ) TA='N'; else { cblas_xerbla(3, "cblas_dgemmt","Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if(TransB == CblasTrans) TB='T'; else if ( TransB == CblasConjTrans ) TB='C'; else if ( TransB == CblasNoTrans ) TB='N'; else { cblas_xerbla(4, "cblas_dgemmt","Illegal TransB setting, %d\n", TransB); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TA = C2F_CHAR(&TA); F77_TB = C2F_CHAR(&TB); #endif F77_dgemmt(F77_UL, F77_TA, F77_TB, &F77_M, &F77_K, &alpha, A, &F77_lda, B, &F77_ldb, &beta, C, &F77_ldc); } else if (Order == CblasRowMajor) { RowMajorStrg = 1; if( Uplo == CblasUpper) UL='L'; else if ( Uplo == CblasLower ) UL='U'; else { cblas_xerbla(2, "cblas_dgemmt","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if(TransA == CblasTrans) TB='T'; else if ( TransA == CblasConjTrans ) TB='C'; else if ( TransA == CblasNoTrans ) TB='N'; else { cblas_xerbla(3, "cblas_dgemmt","Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if(TransB == CblasTrans) TA='T'; else if ( TransB == CblasConjTrans ) TA='C'; else if ( TransB == CblasNoTrans ) TA='N'; else { cblas_xerbla(4, "cblas_dgemmt","Illegal TransB setting, %d\n", TransB); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TA = C2F_CHAR(&TA); F77_TB = C2F_CHAR(&TB); #endif F77_dgemmt(F77_UL, F77_TA, F77_TB, &F77_M, &F77_K, &alpha, B, &F77_ldb, A, &F77_lda, &beta, C, &F77_ldc); } else cblas_xerbla(1, "cblas_dgemmt", "Illegal Order setting, %d\n", Order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/extra/cblas_saxpby.c000066400000000000000000000012071422157504600226500ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_saxpby.c * * The program is a C interface to saxpby. * It calls the fortran wrapper before calling saxpby. * * Copyright (C) 2020, Advanced Micro Devices, Inc. */ #include "cblas.h" #include "cblas_f77.h" void cblas_saxpby( f77_int N, float alpha, const float *X, f77_int incX, float beta, float *Y, f77_int incY) { #ifdef F77_INT F77_INT F77_N=N, F77_incX=incX, F77_incY=incY; #else #define F77_N N #define F77_incX incX #define F77_incY incY #endif F77_saxpby( &F77_N, &alpha, X, &F77_incX, &beta, Y, &F77_incY); } #endif blis-0.9.0/frame/compat/cblas/src/extra/cblas_sgemm_batch.c000066400000000000000000000124731422157504600236220ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * * cblas_sgemm_batch.c * This program is a C interface to sgemm_batch. * * Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved. * */ #include "cblas.h" #include "cblas_f77.h" void cblas_sgemm_batch(enum CBLAS_ORDER Order, enum CBLAS_TRANSPOSE *TransA_array, enum CBLAS_TRANSPOSE *TransB_array, f77_int *M_array, f77_int *N_array, f77_int *K_array, const float *alpha_array, const float **A_array, f77_int *lda_array, const float **B_array, f77_int *ldb_array, const float *beta_array, float **C_array, f77_int *ldc_array, f77_int group_count, f77_int *group_size) { char TA[group_count], TB[group_count]; #ifdef F77_CHAR F77_CHAR F77_TA[group_count], F77_TB[group_count]; #else #define F77_TA TA #define F77_TB TB #endif #ifdef F77_INT F77_INT F77_GRP_COUNT = group_count; F77_INT F77_M[F77_GRP_COUNT], F77_N[F77_GRP_COUNT], F77_K[F77_GRP_COUNT]; F77_INT F77_lda[F77_GRP_COUNT], F77_ldb[F77_GRP_COUNT], F77_ldc[F77_GRP_COUNT]; F77_INT F77_GRP_SIZE[F77_GRP_COUNT]; #else #define F77_GRP_COUNT group_count #define F77_M M_array #define F77_N N_array #define F77_K K_array #define F77_lda lda_array #define F77_ldb ldb_array #define F77_ldc ldc_array #define F77_GRP_SIZE group_size #endif extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; dim_t i; if( Order == CblasColMajor ) { for(i = 0; i < group_count; i++) { if(TransA_array[i] == CblasTrans) TA[i]='T'; else if ( TransA_array[i] == CblasConjTrans ) TA[i]='C'; else if ( TransA_array[i] == CblasNoTrans ) TA[i]='N'; else { cblas_xerbla(2, "cblas_sgemm_batch", "Illegal TransA setting %d for group %d\n", TransA_array[i], i); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if(TransB_array[i] == CblasTrans) TB[i]='T'; else if ( TransB_array[i] == CblasConjTrans ) TB[i]='C'; else if ( TransB_array[i] == CblasNoTrans ) TB[i]='N'; else { cblas_xerbla(3, "cblas_sgemm_batch", "Illegal TransB setting %d for group %d\n", TransB_array[i], i); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_TA[i] = C2F_CHAR(TA+i); F77_TB[i] = C2F_CHAR(TB+i); #endif #ifdef F77_INT F77_M[i] = M_array[i]; F77_N[i] = N_array[i]; F77_K[i] = K_array[i]; F77_lda[i] = lda_array[i]; F77_ldb[i] = ldb_array[i]; F77_ldc[i] = ldc_array[i]; F77_GRP_SIZE[i] = group_size[i]; #endif } F77_sgemm_batch(F77_TA, F77_TB, F77_M, F77_N, F77_K, alpha_array, A_array, F77_lda, B_array, F77_ldb, beta_array, C_array, F77_ldc, &F77_GRP_COUNT, F77_GRP_SIZE); } else if (Order == CblasRowMajor) { RowMajorStrg = 1; dim_t i; for(i = 0; i < group_count; i++) { if(TransA_array[i] == CblasTrans) TB[i]='T'; else if ( TransA_array[i] == CblasConjTrans ) TB[i]='C'; else if ( TransA_array[i] == CblasNoTrans ) TB[i]='N'; else { cblas_xerbla(2, "cblas_sgemm_batch", "Illegal TransA setting %d for group %d\n", TransA_array[i], i); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if(TransB_array[i] == CblasTrans) TA[i]='T'; else if ( TransB_array[i] == CblasConjTrans ) TA[i]='C'; else if ( TransB_array[i] == CblasNoTrans ) TA[i]='N'; else { cblas_xerbla(2, "cblas_sgemm_batch", "Illegal TransB setting %d for group %d\n", TransB_array[i], i); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_TA = C2F_CHAR(&TA); F77_TB = C2F_CHAR(&TB); #endif #ifdef F77_INT F77_M[i] = M_array[i]; F77_N[i] = N_array[i]; F77_K[i] = K_array[i]; F77_lda[i] = lda_array[i]; F77_ldb[i] = ldb_array[i]; F77_ldc[i] = ldc_array[i]; F77_GRP_SIZE = group_size[i]; #endif } F77_sgemm_batch(F77_TA, F77_TB, F77_N, F77_M, F77_K, alpha_array, B_array, F77_ldb, A_array, F77_lda, beta_array, C_array, F77_ldc, &F77_GRP_COUNT, F77_GRP_SIZE); } else cblas_xerbla(1, "cblas_sgemm_batch", "Illegal Order setting, %d\n", Order); CBLAS_CallFromC = 0; RowMajorStrg = 0; } #endif blis-0.9.0/frame/compat/cblas/src/extra/cblas_sgemmt.c000066400000000000000000000121621422157504600226400ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* cblas_sgemmt.c Based off of cblas_sgemm.c. */ /* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "cblas.h" #include "cblas_f77.h" void cblas_sgemmt(enum CBLAS_ORDER Order, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE TransA, enum CBLAS_TRANSPOSE TransB, f77_int M, f77_int K, float alpha, const float *A, f77_int lda, const float *B, f77_int ldb, float beta, float *C, f77_int ldc) { char UL, TA, TB; #ifdef F77_CHAR F77_CHAR F77_UL, F77_TA, F77_TB; #else #define F77_UL &UL #define F77_TA &TA #define F77_TB &TB #endif #ifdef F77_INT F77_INT F77_M=M, F77_K=K, F77_lda=lda, F77_ldb=ldb; F77_INT F77_ldc=ldc; #else #define F77_M M #define F77_K K #define F77_lda lda #define F77_ldb ldb #define F77_ldc ldc #endif extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if( Order == CblasColMajor ) { if( Uplo == CblasUpper) UL='U'; else if ( Uplo == CblasLower ) UL='L'; else { cblas_xerbla(2, "cblas_sgemmt","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if(TransA == CblasTrans) TA='T'; else if ( TransA == CblasConjTrans ) TA='C'; else if ( TransA == CblasNoTrans ) TA='N'; else { cblas_xerbla(3, "cblas_sgemmt","Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if(TransB == CblasTrans) TB='T'; else if ( TransB == CblasConjTrans ) TB='C'; else if ( TransB == CblasNoTrans ) TB='N'; else { cblas_xerbla(4, "cblas_sgemmt","Illegal TransB setting, %d\n", TransB); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TA = C2F_CHAR(&TA); F77_TB = C2F_CHAR(&TB); #endif F77_sgemmt(F77_UL, F77_TA, F77_TB, &F77_M, &F77_K, &alpha, A, &F77_lda, B, &F77_ldb, &beta, C, &F77_ldc); } else if (Order == CblasRowMajor) { RowMajorStrg = 1; if( Uplo == CblasUpper) UL='L'; else if ( Uplo == CblasLower ) UL='U'; else { cblas_xerbla(2, "cblas_sgemmt","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if(TransA == CblasTrans) TB='T'; else if ( TransA == CblasConjTrans ) TB='C'; else if ( TransA == CblasNoTrans ) TB='N'; else { cblas_xerbla(3, "cblas_sgemmt","Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if(TransB == CblasTrans) TA='T'; else if ( TransB == CblasConjTrans ) TA='C'; else if ( TransB == CblasNoTrans ) TA='N'; else { cblas_xerbla(4, "cblas_sgemmt","Illegal TransB setting, %d\n", TransB); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TA = C2F_CHAR(&TA); F77_TB = C2F_CHAR(&TB); #endif F77_sgemmt(F77_UL, F77_TA, F77_TB, &F77_M, &F77_K, &alpha, B, &F77_ldb, A, &F77_lda, &beta, C, &F77_ldc); } else cblas_xerbla(1, "cblas_sgemmt", "Illegal Order setting, %d\n", Order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/extra/cblas_zaxpby.c000066400000000000000000000012101422157504600226510ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * cblas_zaxpby.c * * The program is a C interface to zaxpby. * * Copyright (C) 2020, Advanced Micro Devices, Inc. * */ #include "cblas.h" #include "cblas_f77.h" void cblas_zaxpby( f77_int N, const void *alpha, const void *X, f77_int incX, const void *beta, void *Y, f77_int incY) { #ifdef F77_INT F77_INT F77_N=N, F77_incX=incX, F77_incY=incY; #else #define F77_N N #define F77_incX incX #define F77_incY incY #endif F77_zaxpby( &F77_N, (dcomplex*)alpha, (dcomplex*)X, &F77_incX, (dcomplex*)beta, (dcomplex*)Y, &F77_incY); } #endif blis-0.9.0/frame/compat/cblas/src/extra/cblas_zgemm3m.c000066400000000000000000000061531422157504600227260ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * * cblas_zgemm3m.c * * This program is a C interface to zgemm3m. * * Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved. * */ #include "cblas.h" #include "cblas_f77.h" void cblas_zgemm3m(enum CBLAS_ORDER Order, enum CBLAS_TRANSPOSE TransA, enum CBLAS_TRANSPOSE TransB, f77_int M, f77_int N, f77_int K, const void *alpha, const void *A, f77_int lda, const void *B, f77_int ldb, const void *beta, void *C, f77_int ldc) { char TA, TB; #ifdef F77_CHAR F77_CHAR F77_TA, F77_TB; #else #define F77_TA &TA #define F77_TB &TB #endif #ifdef F77_INT F77_INT F77_M=M, F77_N=N, F77_K=K, F77_lda=lda, F77_ldb=ldb; F77_INT F77_ldc=ldc; #else #define F77_M M #define F77_N N #define F77_K K #define F77_lda lda #define F77_ldb ldb #define F77_ldc ldc #endif extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if( Order == CblasColMajor ) { if(TransA == CblasTrans) TA='T'; else if ( TransA == CblasConjTrans ) TA='C'; else if ( TransA == CblasNoTrans ) TA='N'; else { cblas_xerbla(2, "cblas_zgemm3m", "Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if(TransB == CblasTrans) TB='T'; else if ( TransB == CblasConjTrans ) TB='C'; else if ( TransB == CblasNoTrans ) TB='N'; else { cblas_xerbla(3, "cblas_zgemm3m", "Illegal TransB setting, %d\n", TransB); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_TA = C2F_CHAR(&TA); F77_TB = C2F_CHAR(&TB); #endif F77_zgemm3m(F77_TA, F77_TB, &F77_M, &F77_N, &F77_K, (dcomplex*)alpha, (dcomplex*)A, &F77_lda, (dcomplex*)B, &F77_ldb, (dcomplex*)beta, (dcomplex*)C, &F77_ldc); } else if (Order == CblasRowMajor) { RowMajorStrg = 1; if(TransA == CblasTrans) TB='T'; else if ( TransA == CblasConjTrans ) TB='C'; else if ( TransA == CblasNoTrans ) TB='N'; else { cblas_xerbla(2, "cblas_zgemm3m", "Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if(TransB == CblasTrans) TA='T'; else if ( TransB == CblasConjTrans ) TA='C'; else if ( TransB == CblasNoTrans ) TA='N'; else { cblas_xerbla(2, "cblas_zgemm3m", "Illegal TransB setting, %d\n", TransB); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_TA = C2F_CHAR(&TA); F77_TB = C2F_CHAR(&TB); #endif F77_zgemm3m(F77_TA, F77_TB, &F77_N, &F77_M, &F77_K, (dcomplex*)alpha, (dcomplex*)B, &F77_ldb, (dcomplex*)A, &F77_lda, (dcomplex*)beta, (dcomplex*)C, &F77_ldc); } else cblas_xerbla(1, "cblas_zgemm3m", "Illegal Order setting, %d\n", Order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/cblas/src/extra/cblas_zgemm_batch.c000066400000000000000000000127311422157504600236260ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* * * cblas_zgemm_batch.c * This program is a C interface to zgemm_batch. * * Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved. * */ #include "cblas.h" #include "cblas_f77.h" void cblas_zgemm_batch(enum CBLAS_ORDER Order, enum CBLAS_TRANSPOSE *TransA_array, enum CBLAS_TRANSPOSE *TransB_array, f77_int *M_array, f77_int *N_array, f77_int *K_array, const void *alpha_array, const void **A_array, f77_int *lda_array, const void **B_array, f77_int *ldb_array, const void *beta_array, void **C_array, f77_int *ldc_array, f77_int group_count, f77_int *group_size) { char TA[group_count], TB[group_count]; #ifdef F77_CHAR F77_CHAR F77_TA[group_count], F77_TB[group_count]; #else #define F77_TA TA #define F77_TB TB #endif #ifdef F77_INT F77_INT F77_GRP_COUNT = group_count; F77_INT F77_M[F77_GRP_COUNT], F77_N[F77_GRP_COUNT], F77_K[F77_GRP_COUNT]; F77_INT F77_lda[F77_GRP_COUNT], F77_ldb[F77_GRP_COUNT], F77_ldc[F77_GRP_COUNT]; F77_INT F77_GRP_SIZE[F77_GRP_COUNT]; #else #define F77_GRP_COUNT group_count #define F77_M M_array #define F77_N N_array #define F77_K K_array #define F77_lda lda_array #define F77_ldb ldb_array #define F77_ldc ldc_array #define F77_GRP_SIZE group_size #endif extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; dim_t i; if( Order == CblasColMajor ) { for(i = 0; i < group_count; i++) { if(TransA_array[i] == CblasTrans) TA[i]='T'; else if ( TransA_array[i] == CblasConjTrans ) TA[i]='C'; else if ( TransA_array[i] == CblasNoTrans ) TA[i]='N'; else { cblas_xerbla(2, "cblas_zgemm_batch", "Illegal TransA setting %d for group %d\n", TransA_array[i], i); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if(TransB_array[i] == CblasTrans) TB[i]='T'; else if ( TransB_array[i] == CblasConjTrans ) TB[i]='C'; else if ( TransB_array[i] == CblasNoTrans ) TB[i]='N'; else { cblas_xerbla(3, "cblas_zgemm_batch", "Illegal TransB setting %d for group %d\n", TransB_array[i], i); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_TA[i] = C2F_CHAR(TA+i); F77_TB[i] = C2F_CHAR(TB+i); #endif #ifdef F77_INT F77_M[i] = M_array[i]; F77_N[i] = N_array[i]; F77_K[i] = K_array[i]; F77_lda[i] = lda_array[i]; F77_ldb[i] = ldb_array[i]; F77_ldc[i] = ldc_array[i]; F77_GRP_SIZE[i] = group_size[i]; #endif } F77_zgemm_batch(F77_TA, F77_TB, F77_M, F77_N, F77_K, (const dcomplex*)alpha_array, (const dcomplex**)A_array, F77_lda, (const dcomplex**)B_array, F77_ldb, (const dcomplex*)beta_array, (dcomplex**)C_array, F77_ldc, &F77_GRP_COUNT, F77_GRP_SIZE); } else if (Order == CblasRowMajor) { RowMajorStrg = 1; dim_t i; for(i = 0; i < group_count; i++) { if(TransA_array[i] == CblasTrans) TB[i]='T'; else if ( TransA_array[i] == CblasConjTrans ) TB[i]='C'; else if ( TransA_array[i] == CblasNoTrans ) TB[i]='N'; else { cblas_xerbla(2, "cblas_zgemm_batch", "Illegal TransA setting %d for group %d\n", TransA_array[i], i); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if(TransB_array[i] == CblasTrans) TA[i]='T'; else if ( TransB_array[i] == CblasConjTrans ) TA[i]='C'; else if ( TransB_array[i] == CblasNoTrans ) TA[i]='N'; else { cblas_xerbla(2, "cblas_zgemm_batch", "Illegal TransB setting %d for group %d\n", TransB_array[i], i); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_TA = C2F_CHAR(&TA); F77_TB = C2F_CHAR(&TB); #endif #ifdef F77_INT F77_M[i] = M_array[i]; F77_N[i] = N_array[i]; F77_K[i] = K_array[i]; F77_lda[i] = lda_array[i]; F77_ldb[i] = ldb_array[i]; F77_ldc[i] = ldc_array[i]; F77_GRP_SIZE = group_size[i]; #endif } F77_zgemm_batch(F77_TA, F77_TB, F77_N, F77_M, F77_K, (const dcomplex*)alpha_array, (const dcomplex**)B_array, F77_ldb, (const dcomplex**)A_array, F77_lda, (const dcomplex*)beta_array, (dcomplex**)C_array, F77_ldc, &F77_GRP_COUNT, F77_GRP_SIZE); } else cblas_xerbla(1, "cblas_zgemm_batch", "Illegal Order setting, %d\n", Order); CBLAS_CallFromC = 0; RowMajorStrg = 0; } #endif blis-0.9.0/frame/compat/cblas/src/extra/cblas_zgemmt.c000066400000000000000000000123451422157504600226520ustar00rootroot00000000000000#include "blis.h" #ifdef BLIS_ENABLE_CBLAS /* cblas_zgemmt.c Based off of cblas_zgemm.c. */ /* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "cblas.h" #include "cblas_f77.h" void cblas_zgemmt(enum CBLAS_ORDER Order, enum CBLAS_UPLO Uplo, enum CBLAS_TRANSPOSE TransA, enum CBLAS_TRANSPOSE TransB, f77_int M, f77_int K, const void *alpha, const void *A, f77_int lda, const void *B, f77_int ldb, const void *beta, void *C, f77_int ldc) { char UL, TA, TB; #ifdef F77_CHAR F77_CHAR F77_UL, F77_TA, F77_TB; #else #define F77_UL &UL #define F77_TA &TA #define F77_TB &TB #endif #ifdef F77_INT F77_INT F77_M=M, F77_K=K, F77_lda=lda, F77_ldb=ldb; F77_INT F77_ldc=ldc; #else #define F77_M M #define F77_K K #define F77_lda lda #define F77_ldb ldb #define F77_ldc ldc #endif extern int CBLAS_CallFromC; extern int RowMajorStrg; RowMajorStrg = 0; CBLAS_CallFromC = 1; if( Order == CblasColMajor ) { if( Uplo == CblasUpper) UL='U'; else if ( Uplo == CblasLower ) UL='L'; else { cblas_xerbla(2, "cblas_zgemmt","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if(TransA == CblasTrans) TA='T'; else if ( TransA == CblasConjTrans ) TA='C'; else if ( TransA == CblasNoTrans ) TA='N'; else { cblas_xerbla(3, "cblas_zgemmt","Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if(TransB == CblasTrans) TB='T'; else if ( TransB == CblasConjTrans ) TB='C'; else if ( TransB == CblasNoTrans ) TB='N'; else { cblas_xerbla(4, "cblas_zgemmt","Illegal TransB setting, %d\n", TransB); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TA = C2F_CHAR(&TA); F77_TB = C2F_CHAR(&TB); #endif F77_zgemmt(F77_UL, F77_TA, F77_TB, &F77_M, &F77_K, (dcomplex*)alpha, (dcomplex*)A, &F77_lda, (dcomplex*)B, &F77_ldb, (dcomplex*)beta, (dcomplex*)C, &F77_ldc); } else if (Order == CblasRowMajor) { RowMajorStrg = 1; if( Uplo == CblasUpper) UL='L'; else if ( Uplo == CblasLower ) UL='U'; else { cblas_xerbla(2, "cblas_zgemmt","Illegal Uplo setting, %d\n", Uplo); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if(TransA == CblasTrans) TB='T'; else if ( TransA == CblasConjTrans ) TB='C'; else if ( TransA == CblasNoTrans ) TB='N'; else { cblas_xerbla(3, "cblas_zgemmt","Illegal TransA setting, %d\n", TransA); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } if(TransB == CblasTrans) TA='T'; else if ( TransB == CblasConjTrans ) TA='C'; else if ( TransB == CblasNoTrans ) TA='N'; else { cblas_xerbla(4, "cblas_zgemmt","Illegal TransB setting, %d\n", TransB); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #ifdef F77_CHAR F77_UL = C2F_CHAR(&UL); F77_TA = C2F_CHAR(&TA); F77_TB = C2F_CHAR(&TB); #endif F77_zgemmt(F77_UL, F77_TA, F77_TB, &F77_M, &F77_K, (dcomplex*)alpha, (dcomplex*)B, &F77_ldb, (dcomplex*)A, &F77_lda, (dcomplex*)beta, (dcomplex*)C, &F77_ldc); } else cblas_xerbla(1, "cblas_zgemmt", "Illegal Order setting, %d\n", Order); CBLAS_CallFromC = 0; RowMajorStrg = 0; return; } #endif blis-0.9.0/frame/compat/check/000077500000000000000000000000001422157504600161115ustar00rootroot00000000000000blis-0.9.0/frame/compat/check/bla_gemm3m_check.h000066400000000000000000000061031422157504600214220ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifdef BLIS_ENABLE_BLAS #define bla_gemm3m_check( dt_str, op_str, transa, transb, m, n, k, lda, ldb, ldc ) \ { \ f77_int info = 0; \ f77_int nota, notb; \ f77_int conja, conjb; \ f77_int ta, tb; \ f77_int nrowa, nrowb; \ \ nota = PASTEF770(lsame)( transa, "N", (ftnlen)1, (ftnlen)1 ); \ notb = PASTEF770(lsame)( transb, "N", (ftnlen)1, (ftnlen)1 ); \ conja = PASTEF770(lsame)( transa, "C", (ftnlen)1, (ftnlen)1 ); \ conjb = PASTEF770(lsame)( transb, "C", (ftnlen)1, (ftnlen)1 ); \ ta = PASTEF770(lsame)( transa, "T", (ftnlen)1, (ftnlen)1 ); \ tb = PASTEF770(lsame)( transb, "T", (ftnlen)1, (ftnlen)1 ); \ \ if ( nota ) { nrowa = *m; } \ else { nrowa = *k; } \ if ( notb ) { nrowb = *k; } \ else { nrowb = *n; } \ \ if ( !nota && !conja && !ta ) \ info = 1; \ else if ( !notb && !conjb && !tb ) \ info = 2; \ else if ( *m < 0 ) \ info = 3; \ else if ( *n < 0 ) \ info = 4; \ else if ( *k < 0 ) \ info = 5; \ else if ( *lda < bli_max( 1, nrowa ) ) \ info = 8; \ else if ( *ldb < bli_max( 1, nrowb ) ) \ info = 10; \ else if ( *ldc < bli_max( 1, *m ) ) \ info = 13; \ \ if ( info != 0 ) \ { \ char func_str[ BLIS_MAX_BLAS_FUNC_STR_LENGTH ]; \ \ sprintf( func_str, "%s%-5s", dt_str, op_str ); \ \ bli_string_mkupper( func_str ); \ \ PASTEF770(xerbla)( func_str, &info, (ftnlen)6 ); \ \ return; \ } \ } #endif blis-0.9.0/frame/compat/check/bla_gemm_check.h000066400000000000000000000057701422157504600211730ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifdef BLIS_ENABLE_BLAS #define bla_gemm_check( dt_str, op_str, transa, transb, m, n, k, lda, ldb, ldc ) \ { \ f77_int info = 0; \ f77_int nota, notb; \ f77_int conja, conjb; \ f77_int ta, tb; \ f77_int nrowa, nrowb; \ \ nota = PASTEF770(lsame)( transa, "N", (ftnlen)1, (ftnlen)1 ); \ notb = PASTEF770(lsame)( transb, "N", (ftnlen)1, (ftnlen)1 ); \ conja = PASTEF770(lsame)( transa, "C", (ftnlen)1, (ftnlen)1 ); \ conjb = PASTEF770(lsame)( transb, "C", (ftnlen)1, (ftnlen)1 ); \ ta = PASTEF770(lsame)( transa, "T", (ftnlen)1, (ftnlen)1 ); \ tb = PASTEF770(lsame)( transb, "T", (ftnlen)1, (ftnlen)1 ); \ \ if ( nota ) { nrowa = *m; } \ else { nrowa = *k; } \ if ( notb ) { nrowb = *k; } \ else { nrowb = *n; } \ \ if ( !nota && !conja && !ta ) \ info = 1; \ else if ( !notb && !conjb && !tb ) \ info = 2; \ else if ( *m < 0 ) \ info = 3; \ else if ( *n < 0 ) \ info = 4; \ else if ( *k < 0 ) \ info = 5; \ else if ( *lda < bli_max( 1, nrowa ) ) \ info = 8; \ else if ( *ldb < bli_max( 1, nrowb ) ) \ info = 10; \ else if ( *ldc < bli_max( 1, *m ) ) \ info = 13; \ \ if ( info != 0 ) \ { \ char func_str[ BLIS_MAX_BLAS_FUNC_STR_LENGTH ]; \ \ sprintf( func_str, "%s%-5s", dt_str, op_str ); \ \ bli_string_mkupper( func_str ); \ \ PASTEF770(xerbla)( func_str, &info, (ftnlen)6 ); \ \ return; \ } \ } #endif blis-0.9.0/frame/compat/check/bla_gemmt_check.h000066400000000000000000000062341422157504600213530ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifdef BLIS_ENABLE_BLAS #define bla_gemmt_check( dt_str, op_str, uploc, transa, transb, m, k, lda, ldb, ldc ) \ { \ f77_int info = 0; \ f77_int nota, notb; \ f77_int conja, conjb; \ f77_int ta, tb; \ f77_int lower, upper; \ f77_int nrowa, nrowb; \ \ nota = PASTEF770(lsame)( transa, "N", (ftnlen)1, (ftnlen)1 ); \ notb = PASTEF770(lsame)( transb, "N", (ftnlen)1, (ftnlen)1 ); \ conja = PASTEF770(lsame)( transa, "C", (ftnlen)1, (ftnlen)1 ); \ conjb = PASTEF770(lsame)( transb, "C", (ftnlen)1, (ftnlen)1 ); \ ta = PASTEF770(lsame)( transa, "T", (ftnlen)1, (ftnlen)1 ); \ tb = PASTEF770(lsame)( transb, "T", (ftnlen)1, (ftnlen)1 ); \ \ lower = PASTEF770(lsame)( uploc, "L", (ftnlen)1, (ftnlen)1 ); \ upper = PASTEF770(lsame)( uploc, "U", (ftnlen)1, (ftnlen)1 ); \ \ if ( nota ) { nrowa = *m; } \ else { nrowa = *k; } \ if ( notb ) { nrowb = *k; } \ else { nrowb = *m; } \ \ if ( !lower && !upper ) \ info = 1; \ else if ( !nota && !conja && !ta ) \ info = 2; \ else if ( !notb && !conjb && !tb ) \ info = 3; \ else if ( *m < 0 ) \ info = 4; \ else if ( *k < 0 ) \ info = 5; \ else if ( *lda < bli_max( 1, nrowa ) ) \ info = 8; \ else if ( *ldb < bli_max( 1, nrowb ) ) \ info = 10; \ else if ( *ldc < bli_max( 1, *m ) ) \ info = 13; \ \ if ( info != 0 ) \ { \ char func_str[ BLIS_MAX_BLAS_FUNC_STR_LENGTH ]; \ \ sprintf( func_str, "%s%-5s", dt_str, op_str ); \ \ bli_string_mkupper( func_str ); \ \ PASTEF770(xerbla)( func_str, &info, (ftnlen)6 ); \ \ return; \ } \ } #endif blis-0.9.0/frame/compat/check/bla_gemv_check.h000066400000000000000000000047531422157504600212040ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifdef BLIS_ENABLE_BLAS #define bla_gemv_check( dt_str, op_str, transa, m, n, lda, incx, incy ) \ { \ f77_int info = 0; \ f77_int nota, ta, conja; \ \ nota = PASTEF770(lsame)( transa, "N", (ftnlen)1, (ftnlen)1 ); \ ta = PASTEF770(lsame)( transa, "T", (ftnlen)1, (ftnlen)1 ); \ conja = PASTEF770(lsame)( transa, "C", (ftnlen)1, (ftnlen)1 ); \ \ if ( !nota && !ta && !conja ) \ info = 1; \ else if ( *m < 0 ) \ info = 2; \ else if ( *n < 0 ) \ info = 3; \ else if ( *lda < bli_max( 1, *m ) ) \ info = 6; \ else if ( *incx == 0 ) \ info = 8; \ else if ( *incy == 0 ) \ info = 11; \ \ if ( info != 0 ) \ { \ char func_str[ BLIS_MAX_BLAS_FUNC_STR_LENGTH ]; \ \ sprintf( func_str, "%s%-5s", dt_str, op_str ); \ \ bli_string_mkupper( func_str ); \ \ PASTEF770(xerbla)( func_str, &info, (ftnlen)6 ); \ \ return; \ } \ } #endif blis-0.9.0/frame/compat/check/bla_ger_check.h000066400000000000000000000045021422157504600210130ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifdef BLIS_ENABLE_BLAS #define bla_ger_check( dt_str, op_str, conj_str, m, n, incx, incy, lda ) \ { \ f77_int info = 0; \ \ if ( *m < 0 ) \ info = 1; \ else if ( *n < 0 ) \ info = 2; \ else if ( *incx == 0 ) \ info = 5; \ else if ( *incy == 0 ) \ info = 7; \ else if ( *lda < bli_max( 1, *m ) ) \ info = 9; \ \ if ( info != 0 ) \ { \ char func_str[ BLIS_MAX_BLAS_FUNC_STR_LENGTH ]; \ \ /* We have to append an extra character to denote whether we are testing geru or gerc. */ \ sprintf( func_str, "%s%s%-2s", dt_str, op_str, conj_str ); \ \ bli_string_mkupper( func_str ); \ \ PASTEF770(xerbla)( func_str, &info, (ftnlen)6 ); \ \ return; \ } \ } #endif blis-0.9.0/frame/compat/check/bla_hemm_check.h000066400000000000000000000053361422157504600211720ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifdef BLIS_ENABLE_BLAS #define bla_hemm_check( dt_str, op_str, sidea, uploa, m, n, lda, ldb, ldc ) \ { \ f77_int info = 0; \ f77_int left, right; \ f77_int lower, upper; \ f77_int nrowa; \ \ left = PASTEF770(lsame)( sidea, "L", (ftnlen)1, (ftnlen)1 ); \ right = PASTEF770(lsame)( sidea, "R", (ftnlen)1, (ftnlen)1 ); \ lower = PASTEF770(lsame)( uploa, "L", (ftnlen)1, (ftnlen)1 ); \ upper = PASTEF770(lsame)( uploa, "U", (ftnlen)1, (ftnlen)1 ); \ \ if ( left ) { nrowa = *m; } \ else { nrowa = *n; } \ \ if ( !left && !right ) \ info = 1; \ else if ( !lower && !upper ) \ info = 2; \ else if ( *m < 0 ) \ info = 3; \ else if ( *n < 0 ) \ info = 4; \ else if ( *lda < bli_max( 1, nrowa ) ) \ info = 7; \ else if ( *ldb < bli_max( 1, *m ) ) \ info = 9; \ else if ( *ldc < bli_max( 1, *m ) ) \ info = 12; \ \ if ( info != 0 ) \ { \ char func_str[ BLIS_MAX_BLAS_FUNC_STR_LENGTH ]; \ \ sprintf( func_str, "%s%-5s", dt_str, op_str ); \ \ bli_string_mkupper( func_str ); \ \ PASTEF770(xerbla)( func_str, &info, (ftnlen)6 ); \ \ return; \ } \ } #endif blis-0.9.0/frame/compat/check/bla_hemv_check.h000066400000000000000000000045661422157504600212070ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifdef BLIS_ENABLE_BLAS #define bla_hemv_check( dt_str, op_str, uploa, m, lda, incx, incy ) \ { \ f77_int info = 0; \ f77_int lower, upper; \ \ lower = PASTEF770(lsame)( uploa, "L", (ftnlen)1, (ftnlen)1 ); \ upper = PASTEF770(lsame)( uploa, "U", (ftnlen)1, (ftnlen)1 ); \ \ if ( !lower && !upper ) \ info = 1; \ else if ( *m < 0 ) \ info = 2; \ else if ( *lda < bli_max( 1, *m ) ) \ info = 5; \ else if ( *incx == 0 ) \ info = 7; \ else if ( *incy == 0 ) \ info = 10; \ \ if ( info != 0 ) \ { \ char func_str[ BLIS_MAX_BLAS_FUNC_STR_LENGTH ]; \ \ sprintf( func_str, "%s%-5s", dt_str, op_str ); \ \ bli_string_mkupper( func_str ); \ \ PASTEF770(xerbla)( func_str, &info, (ftnlen)6 ); \ \ return; \ } \ } #endif blis-0.9.0/frame/compat/check/bla_her2_check.h000066400000000000000000000045651422157504600211070ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifdef BLIS_ENABLE_BLAS #define bla_her2_check( dt_str, op_str, uploa, m, incx, incy, lda ) \ { \ f77_int info = 0; \ f77_int lower, upper; \ \ lower = PASTEF770(lsame)( uploa, "L", (ftnlen)1, (ftnlen)1 ); \ upper = PASTEF770(lsame)( uploa, "U", (ftnlen)1, (ftnlen)1 ); \ \ if ( !lower && !upper ) \ info = 1; \ else if ( *m < 0 ) \ info = 2; \ else if ( *incx == 0 ) \ info = 5; \ else if ( *incy == 0 ) \ info = 7; \ else if ( *lda < bli_max( 1, *m ) ) \ info = 9; \ \ if ( info != 0 ) \ { \ char func_str[ BLIS_MAX_BLAS_FUNC_STR_LENGTH ]; \ \ sprintf( func_str, "%s%-5s", dt_str, op_str ); \ \ bli_string_mkupper( func_str ); \ \ PASTEF770(xerbla)( func_str, &info, (ftnlen)6 ); \ \ return; \ } \ } #endif blis-0.9.0/frame/compat/check/bla_her2k_check.h000066400000000000000000000053371422157504600212600ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifdef BLIS_ENABLE_BLAS #define bla_her2k_check( dt_str, op_str, uploa, trans, m, k, lda, ldb, ldc ) \ { \ f77_int info = 0; \ f77_int nota, conja; \ f77_int lower, upper; \ f77_int nrowa; \ \ nota = PASTEF770(lsame)( trans, "N", (ftnlen)1, (ftnlen)1 ); \ conja = PASTEF770(lsame)( trans, "C", (ftnlen)1, (ftnlen)1 ); \ lower = PASTEF770(lsame)( uploa, "L", (ftnlen)1, (ftnlen)1 ); \ upper = PASTEF770(lsame)( uploa, "U", (ftnlen)1, (ftnlen)1 ); \ \ if ( nota ) { nrowa = *m; } \ else { nrowa = *k; } \ \ if ( !lower && !upper ) \ info = 1; \ else if ( !nota && !conja ) \ info = 2; \ else if ( *m < 0 ) \ info = 3; \ else if ( *k < 0 ) \ info = 4; \ else if ( *lda < bli_max( 1, nrowa ) ) \ info = 7; \ else if ( *ldb < bli_max( 1, nrowa ) ) \ info = 9; \ else if ( *ldc < bli_max( 1, *m ) ) \ info = 12; \ \ if ( info != 0 ) \ { \ char func_str[ BLIS_MAX_BLAS_FUNC_STR_LENGTH ]; \ \ sprintf( func_str, "%s%-5s", dt_str, op_str ); \ \ bli_string_mkupper( func_str ); \ \ PASTEF770(xerbla)( func_str, &info, (ftnlen)6 ); \ \ return; \ } \ } #endif blis-0.9.0/frame/compat/check/bla_her_check.h000066400000000000000000000045061422157504600210200ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifdef BLIS_ENABLE_BLAS #define bla_her_check( dt_str, op_str, uploa, m, incx, lda ) \ { \ f77_int info = 0; \ f77_int lower, upper; \ \ lower = PASTEF770(lsame)( uploa, "L", (ftnlen)1, (ftnlen)1 ); \ upper = PASTEF770(lsame)( uploa, "U", (ftnlen)1, (ftnlen)1 ); \ \ if ( !lower && !upper ) \ info = 1; \ else if ( *m < 0 ) \ info = 2; \ else if ( *incx == 0 ) \ info = 5; \ else if ( *lda < bli_max( 1, *m ) ) \ info = 7; \ \ if ( info != 0 ) \ { \ char func_str[ BLIS_MAX_BLAS_FUNC_STR_LENGTH ]; \ \ sprintf( func_str, "%s%-5s", dt_str, op_str ); \ \ bli_string_mkupper( func_str ); \ \ PASTEF770(xerbla)( func_str, &info, (ftnlen)6 ); \ \ return; \ } \ } #endif blis-0.9.0/frame/compat/check/bla_herk_check.h000066400000000000000000000052461422157504600211750ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifdef BLIS_ENABLE_BLAS #define bla_herk_check( dt_str, op_str, uploa, transa, m, k, lda, ldc ) \ { \ f77_int info = 0; \ f77_int nota, conja; \ f77_int lower, upper; \ f77_int nrowa; \ \ nota = PASTEF770(lsame)( transa, "N", (ftnlen)1, (ftnlen)1 ); \ conja = PASTEF770(lsame)( transa, "C", (ftnlen)1, (ftnlen)1 ); \ lower = PASTEF770(lsame)( uploc, "L", (ftnlen)1, (ftnlen)1 ); \ upper = PASTEF770(lsame)( uploc, "U", (ftnlen)1, (ftnlen)1 ); \ \ if ( nota ) { nrowa = *m; } \ else { nrowa = *k; } \ \ if ( !lower && !upper ) \ info = 1; \ else if ( !nota && !conja ) \ info = 2; \ else if ( *m < 0 ) \ info = 3; \ else if ( *k < 0 ) \ info = 4; \ else if ( *lda < bli_max( 1, nrowa ) ) \ info = 7; \ else if ( *ldc < bli_max( 1, *m ) ) \ info = 10; \ \ if ( info != 0 ) \ { \ char func_str[ BLIS_MAX_BLAS_FUNC_STR_LENGTH ]; \ \ sprintf( func_str, "%s%-5s", dt_str, op_str ); \ \ bli_string_mkupper( func_str ); \ \ PASTEF770(xerbla)( func_str, &info, (ftnlen)6 ); \ \ return; \ } \ } #endif blis-0.9.0/frame/compat/check/bla_symm_check.h000066400000000000000000000033201422157504600212200ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifdef BLIS_ENABLE_BLAS #define bla_symm_check bla_hemm_check #endif blis-0.9.0/frame/compat/check/bla_symv_check.h000066400000000000000000000033201422157504600212310ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifdef BLIS_ENABLE_BLAS #define bla_symv_check bla_hemv_check #endif blis-0.9.0/frame/compat/check/bla_syr2_check.h000066400000000000000000000033201422157504600211320ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifdef BLIS_ENABLE_BLAS #define bla_syr2_check bla_her2_check #endif blis-0.9.0/frame/compat/check/bla_syr2k_check.h000066400000000000000000000056351422157504600213200ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifdef BLIS_ENABLE_BLAS #define bla_syr2k_check( dt_str, op_str, uploa, trans, m, k, lda, ldb, ldc ) \ { \ f77_int info = 0; \ f77_int is_r; \ f77_int nota, ta, cta; \ f77_int lower, upper; \ f77_int nrowa; \ \ static char* dt_cst = dt_str; \ \ is_r = ( dt_cst[0] == 's' || dt_cst[0] == 'd' ); \ nota = PASTEF770(lsame)( trans, "N", (ftnlen)1, (ftnlen)1 ); \ ta = PASTEF770(lsame)( trans, "T", (ftnlen)1, (ftnlen)1 ); \ cta = PASTEF770(lsame)( trans, "C", (ftnlen)1, (ftnlen)1 ); \ lower = PASTEF770(lsame)( uploa, "L", (ftnlen)1, (ftnlen)1 ); \ upper = PASTEF770(lsame)( uploa, "U", (ftnlen)1, (ftnlen)1 ); \ \ if ( nota ) { nrowa = *m; } \ else { nrowa = *k; } \ \ if ( !lower && !upper ) \ info = 1; \ else if ( !nota && !ta && (is_r ? !cta : 1) ) \ info = 2; \ else if ( *m < 0 ) \ info = 3; \ else if ( *k < 0 ) \ info = 4; \ else if ( *lda < bli_max( 1, nrowa ) ) \ info = 7; \ else if ( *ldb < bli_max( 1, nrowa ) ) \ info = 9; \ else if ( *ldc < bli_max( 1, *m ) ) \ info = 12; \ \ if ( info != 0 ) \ { \ char func_str[ BLIS_MAX_BLAS_FUNC_STR_LENGTH ]; \ \ sprintf( func_str, "%s%-5s", dt_str, op_str ); \ \ bli_string_mkupper( func_str ); \ \ PASTEF770(xerbla)( func_str, &info, (ftnlen)6 ); \ \ return; \ } \ } #endif blis-0.9.0/frame/compat/check/bla_syr_check.h000066400000000000000000000033161422157504600210550ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifdef BLIS_ENABLE_BLAS #define bla_syr_check bla_her_check #endif blis-0.9.0/frame/compat/check/bla_syrk_check.h000066400000000000000000000055451422157504600212360ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifdef BLIS_ENABLE_BLAS #define bla_syrk_check( dt_str, op_str, uploa, transa, m, k, lda, ldc ) \ { \ f77_int info = 0; \ f77_int is_r; \ f77_int nota, ta, cta; \ f77_int lower, upper; \ f77_int nrowa; \ \ static char* dt_cst = dt_str; \ \ is_r = ( dt_cst[0] == 's' || dt_cst[0] == 'd' ); \ nota = PASTEF770(lsame)( transa, "N", (ftnlen)1, (ftnlen)1 ); \ ta = PASTEF770(lsame)( transa, "T", (ftnlen)1, (ftnlen)1 ); \ cta = PASTEF770(lsame)( transa, "C", (ftnlen)1, (ftnlen)1 ); \ lower = PASTEF770(lsame)( uploc, "L", (ftnlen)1, (ftnlen)1 ); \ upper = PASTEF770(lsame)( uploc, "U", (ftnlen)1, (ftnlen)1 ); \ \ if ( nota ) { nrowa = *m; } \ else { nrowa = *k; } \ \ if ( !lower && !upper ) \ info = 1; \ else if ( !nota && !ta && (is_r ? !cta : 1) ) \ info = 2; \ else if ( *m < 0 ) \ info = 3; \ else if ( *k < 0 ) \ info = 4; \ else if ( *lda < bli_max( 1, nrowa ) ) \ info = 7; \ else if ( *ldc < bli_max( 1, *m ) ) \ info = 10; \ \ if ( info != 0 ) \ { \ char func_str[ BLIS_MAX_BLAS_FUNC_STR_LENGTH ]; \ \ sprintf( func_str, "%s%-5s", dt_str, op_str ); \ \ bli_string_mkupper( func_str ); \ \ PASTEF770(xerbla)( func_str, &info, (ftnlen)6 ); \ \ return; \ } \ } #endif blis-0.9.0/frame/compat/check/bla_trmm_check.h000066400000000000000000000062251422157504600212210ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifdef BLIS_ENABLE_BLAS #define bla_trmm_check( dt_str, op_str, sidea, uploa, transa, diaga, m, n, lda, ldb ) \ { \ f77_int info = 0; \ f77_int left, right; \ f77_int lower, upper; \ f77_int nota, ta, conja; \ f77_int unita, nonua; \ f77_int nrowa; \ \ left = PASTEF770(lsame)( sidea, "L", (ftnlen)1, (ftnlen)1 ); \ right = PASTEF770(lsame)( sidea, "R", (ftnlen)1, (ftnlen)1 ); \ lower = PASTEF770(lsame)( uploa, "L", (ftnlen)1, (ftnlen)1 ); \ upper = PASTEF770(lsame)( uploa, "U", (ftnlen)1, (ftnlen)1 ); \ nota = PASTEF770(lsame)( transa, "N", (ftnlen)1, (ftnlen)1 ); \ ta = PASTEF770(lsame)( transa, "T", (ftnlen)1, (ftnlen)1 ); \ conja = PASTEF770(lsame)( transa, "C", (ftnlen)1, (ftnlen)1 ); \ unita = PASTEF770(lsame)( diaga, "U", (ftnlen)1, (ftnlen)1 ); \ nonua = PASTEF770(lsame)( diaga, "N", (ftnlen)1, (ftnlen)1 ); \ \ if ( left ) { nrowa = *m; } \ else { nrowa = *n; } \ \ if ( !left && !right ) \ info = 1; \ else if ( !lower && !upper ) \ info = 2; \ else if ( !nota && !ta && !conja ) \ info = 3; \ else if ( !unita && !nonua ) \ info = 4; \ else if ( *m < 0 ) \ info = 5; \ else if ( *n < 0 ) \ info = 6; \ else if ( *lda < bli_max( 1, nrowa ) ) \ info = 9; \ else if ( *ldb < bli_max( 1, *m ) ) \ info = 11; \ \ if ( info != 0 ) \ { \ char func_str[ BLIS_MAX_BLAS_FUNC_STR_LENGTH ]; \ \ sprintf( func_str, "%s%-5s", dt_str, op_str ); \ \ bli_string_mkupper( func_str ); \ \ PASTEF770(xerbla)( func_str, &info, (ftnlen)6 ); \ \ return; \ } \ } #endif blis-0.9.0/frame/compat/check/bla_trmv_check.h000066400000000000000000000054711422157504600212340ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifdef BLIS_ENABLE_BLAS #define bla_trmv_check( dt_str, op_str, uploa, transa, diaga, m, lda, incx ) \ { \ f77_int info = 0; \ f77_int lower, upper; \ f77_int nota, ta, conja; \ f77_int unita, nonua; \ \ lower = PASTEF770(lsame)( uploa, "L", (ftnlen)1, (ftnlen)1 ); \ upper = PASTEF770(lsame)( uploa, "U", (ftnlen)1, (ftnlen)1 ); \ nota = PASTEF770(lsame)( transa, "N", (ftnlen)1, (ftnlen)1 ); \ ta = PASTEF770(lsame)( transa, "T", (ftnlen)1, (ftnlen)1 ); \ conja = PASTEF770(lsame)( transa, "C", (ftnlen)1, (ftnlen)1 ); \ unita = PASTEF770(lsame)( diaga, "U", (ftnlen)1, (ftnlen)1 ); \ nonua = PASTEF770(lsame)( diaga, "N", (ftnlen)1, (ftnlen)1 ); \ \ if ( !lower && !upper ) \ info = 1; \ else if ( !nota && !ta && !conja ) \ info = 2; \ else if ( !unita && !nonua ) \ info = 3; \ else if ( *m < 0 ) \ info = 4; \ else if ( *lda < bli_max( 1, *m ) ) \ info = 6; \ else if ( *incx == 0 ) \ info = 8; \ \ if ( info != 0 ) \ { \ char func_str[ BLIS_MAX_BLAS_FUNC_STR_LENGTH ]; \ \ sprintf( func_str, "%s%-5s", dt_str, op_str ); \ \ bli_string_mkupper( func_str ); \ \ PASTEF770(xerbla)( func_str, &info, (ftnlen)6 ); \ \ return; \ } \ } #endif blis-0.9.0/frame/compat/check/bla_trsm_check.h000066400000000000000000000033201422157504600212200ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifdef BLIS_ENABLE_BLAS #define bla_trsm_check bla_trmm_check #endif blis-0.9.0/frame/compat/check/bla_trsv_check.h000066400000000000000000000033201422157504600212310ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifdef BLIS_ENABLE_BLAS #define bla_trsv_check bla_trmv_check #endif blis-0.9.0/frame/compat/extra/000077500000000000000000000000001422157504600161575ustar00rootroot00000000000000blis-0.9.0/frame/compat/extra/bla_axpby.c000066400000000000000000000054151422157504600202710ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // Define BLAS-to-BLIS interfaces. // #undef GENTFUNC #define GENTFUNC( ftype, ch, blasname, blisname ) \ \ void PASTEF77(ch,blasname) \ ( \ const f77_int* n, \ const ftype* alpha, \ const ftype* x, const f77_int* incx, \ const ftype* beta, \ ftype* y, const f77_int* incy \ ) \ { \ dim_t n0; \ ftype* x0; \ ftype* y0; \ inc_t incx0; \ inc_t incy0; \ \ /* Initialize BLIS. */ \ bli_init_auto(); \ \ /* Convert/typecast negative values of n to zero. */ \ bli_convert_blas_dim1( *n, n0 ); \ \ /* If the input increments are negative, adjust the pointers so we can use positive increments instead. */ \ bli_convert_blas_incv( n0, (ftype*)x, *incx, x0, incx0 ); \ bli_convert_blas_incv( n0, (ftype*)y, *incy, y0, incy0 ); \ \ /* Call BLIS interface. */ \ PASTEMAC2(ch,blisname,BLIS_TAPI_EX_SUF) \ ( \ BLIS_NO_CONJUGATE, \ n0, \ (ftype*)alpha, \ x0, incx0, \ (ftype*)beta, \ y0, incy0, \ NULL, \ NULL \ ); \ \ /* Finalize BLIS. */ \ bli_finalize_auto(); \ } #ifdef BLIS_ENABLE_BLAS INSERT_GENTFUNC_BLAS( axpby, axpbyv ) #endif blis-0.9.0/frame/compat/extra/bla_axpby.h000066400000000000000000000040431422157504600202720ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype BLAS-to-BLIS interfaces. // #undef GENTPROT #define GENTPROT( ftype, ch, blasname ) \ \ BLIS_EXPORT_BLAS void PASTEF77(ch,blasname) \ ( \ const f77_int* n, \ const ftype* alpha, \ const ftype* x, const f77_int* incx, \ const ftype* beta, \ ftype* y, const f77_int* incy \ ); #ifdef BLIS_ENABLE_BLAS INSERT_GENTPROT_BLAS( axpby ) #endif blis-0.9.0/frame/compat/extra/bla_gemm3m.c000066400000000000000000000165701422157504600203370ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // Define BLAS-to-BLIS interfaces. // #ifdef BLIS_BLAS3_CALLS_TAPI #undef GENTFUNCCO #define GENTFUNCCO( ftype, ftype_r, ch, chr, blasname, blisname ) \ \ void PASTEF77(ch,blasname) \ ( \ const f77_char* transa, \ const f77_char* transb, \ const f77_int* m, \ const f77_int* n, \ const f77_int* k, \ const ftype* alpha, \ const ftype* a, const f77_int* lda, \ const ftype* b, const f77_int* ldb, \ const ftype* beta, \ ftype* c, const f77_int* ldc \ ) \ { \ trans_t blis_transa; \ trans_t blis_transb; \ dim_t m0, n0, k0; \ \ /* Initialize BLIS. */ \ bli_init_auto(); \ \ /* Perform BLAS parameter checking. */ \ PASTEBLACHK(blisname) \ ( \ MKSTR(ch), \ MKSTR(blasname), \ transa, \ transb, \ m, \ n, \ k, \ lda, \ ldb, \ ldc \ ); \ \ /* Map BLAS chars to their corresponding BLIS enumerated type value. */ \ bli_param_map_netlib_to_blis_trans( *transa, &blis_transa ); \ bli_param_map_netlib_to_blis_trans( *transb, &blis_transb ); \ \ /* Typecast BLAS integers to BLIS integers. */ \ bli_convert_blas_dim1( *m, m0 ); \ bli_convert_blas_dim1( *n, n0 ); \ bli_convert_blas_dim1( *k, k0 ); \ \ /* Set the row and column strides of the matrix operands. */ \ const inc_t rs_a = 1; \ const inc_t cs_a = *lda; \ const inc_t rs_b = 1; \ const inc_t cs_b = *ldb; \ const inc_t rs_c = 1; \ const inc_t cs_c = *ldc; \ \ /* As a placeholder, invoke 1m since BLIS does no longer contains an official 3m implementation. Note that we do this by inlining an abbreviated version of bli_gemm_ex() so that we can bypass consideration of sup, which doesn't make sense in this context. */ \ { \ cntx_t* cntx = bli_gks_query_ind_cntx( BLIS_1M, dt ); \ \ rntm_t rntm_l; \ rntm_t* rntm = &rntm_l; \ bli_rntm_init_from_global( rntm ); \ \ /* Note that we MUST disable sup handling since it could redirect execution for some problem sizes to a non-3m implementation. */ \ bli_rntm_disable_l3_sup( rntm ); \ \ /* Call BLIS interface. */ \ PASTEMAC2(ch,blisname,BLIS_TAPI_EX_SUF) \ ( \ blis_transa, \ blis_transb, \ m0, \ n0, \ k0, \ (ftype*)alpha, \ (ftype*)a, rs_a, cs_a, \ (ftype*)b, rs_b, cs_b, \ (ftype*)beta, \ (ftype*)c, rs_c, cs_c, \ cntx, \ rntm \ ); \ } \ \ /* Finalize BLIS. */ \ bli_finalize_auto(); \ } #else #undef GENTFUNCCO #define GENTFUNCCO( ftype, ftype_r, ch, chr, blasname, blisname ) \ \ void PASTEF77(ch,blasname) \ ( \ const f77_char* transa, \ const f77_char* transb, \ const f77_int* m, \ const f77_int* n, \ const f77_int* k, \ const ftype* alpha, \ const ftype* a, const f77_int* lda, \ const ftype* b, const f77_int* ldb, \ const ftype* beta, \ ftype* c, const f77_int* ldc \ ) \ { \ trans_t blis_transa; \ trans_t blis_transb; \ dim_t m0, n0, k0; \ \ /* Initialize BLIS. */ \ bli_init_auto(); \ \ /* Perform BLAS parameter checking. */ \ PASTEBLACHK(blisname) \ ( \ MKSTR(ch), \ MKSTR(blasname), \ transa, \ transb, \ m, \ n, \ k, \ lda, \ ldb, \ ldc \ ); \ \ /* Map BLAS chars to their corresponding BLIS enumerated type value. */ \ bli_param_map_netlib_to_blis_trans( *transa, &blis_transa ); \ bli_param_map_netlib_to_blis_trans( *transb, &blis_transb ); \ \ /* Typecast BLAS integers to BLIS integers. */ \ bli_convert_blas_dim1( *m, m0 ); \ bli_convert_blas_dim1( *n, n0 ); \ bli_convert_blas_dim1( *k, k0 ); \ \ /* Set the row and column strides of the matrix operands. */ \ const inc_t rs_a = 1; \ const inc_t cs_a = *lda; \ const inc_t rs_b = 1; \ const inc_t cs_b = *ldb; \ const inc_t rs_c = 1; \ const inc_t cs_c = *ldc; \ \ const num_t dt = PASTEMAC(ch,type); \ \ obj_t alphao = BLIS_OBJECT_INITIALIZER_1X1; \ obj_t ao = BLIS_OBJECT_INITIALIZER; \ obj_t bo = BLIS_OBJECT_INITIALIZER; \ obj_t betao = BLIS_OBJECT_INITIALIZER_1X1; \ obj_t co = BLIS_OBJECT_INITIALIZER; \ \ dim_t m0_a, n0_a; \ dim_t m0_b, n0_b; \ \ bli_set_dims_with_trans( blis_transa, m0, k0, &m0_a, &n0_a ); \ bli_set_dims_with_trans( blis_transb, k0, n0, &m0_b, &n0_b ); \ \ bli_obj_init_finish_1x1( dt, (ftype*)alpha, &alphao ); \ bli_obj_init_finish_1x1( dt, (ftype*)beta, &betao ); \ \ bli_obj_init_finish( dt, m0_a, n0_a, (ftype*)a, rs_a, cs_a, &ao ); \ bli_obj_init_finish( dt, m0_b, n0_b, (ftype*)b, rs_b, cs_b, &bo ); \ bli_obj_init_finish( dt, m0, n0, (ftype*)c, rs_c, cs_c, &co ); \ \ bli_obj_set_conjtrans( blis_transa, &ao ); \ bli_obj_set_conjtrans( blis_transb, &bo ); \ \ /* As a placeholder, invoke 1m since BLIS does no longer contains an official 3m implementation. Note that we do this by inlining an abbreviated version of bli_gemm_ex() so that we can bypass consideration of sup, which doesn't make sense in this context. */ \ { \ cntx_t* cntx = bli_gks_query_ind_cntx( BLIS_1M, dt ); \ \ rntm_t rntm_l; \ rntm_t* rntm = &rntm_l; \ bli_rntm_init_from_global( &rntm_l ); \ \ /* This is probably not needed given that we performed BLAS-style parameter checking above, but bli_gemm_check() is normally called in the normal course of bli_gemm_ex(). */ \ if ( bli_error_checking_is_enabled() ) \ bli_gemm_check( &alphao, &ao, &bo, &betao, &co, cntx ); \ \ PASTEMAC(blisname,_front) \ ( \ &alphao, \ &ao, \ &bo, \ &betao, \ &co, \ cntx, \ rntm, \ NULL \ ); \ } \ \ /* Finalize BLIS. */ \ bli_finalize_auto(); \ } #endif #ifdef BLIS_ENABLE_BLAS INSERT_GENTFUNCCO_BLAS( gemm3m, gemm ) #endif blis-0.9.0/frame/compat/extra/bla_gemm3m.h000066400000000000000000000043731422157504600203420ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype BLAS-to-BLIS interfaces. // #undef GENTPROTCO #define GENTPROTCO( ftype, ftype_r, ch, chr, blasname ) \ \ BLIS_EXPORT_BLAS void PASTEF77(ch,blasname) \ ( \ const f77_char* transa, \ const f77_char* transb, \ const f77_int* m, \ const f77_int* n, \ const f77_int* k, \ const ftype* alpha, \ const ftype* a, const f77_int* lda, \ const ftype* b, const f77_int* ldb, \ const ftype* beta, \ ftype* c, const f77_int* ldc \ ); #ifdef BLIS_ENABLE_BLAS INSERT_GENTPROTCO_BLAS( gemm3m ) #endif blis-0.9.0/frame/compat/extra/bla_gemm_batch.c000066400000000000000000000162001422157504600212260ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // Define BLAS-to-BLIS interfaces. // #ifdef BLIS_BLAS3_CALLS_TAPI #undef GENTFUNC #define GENTFUNC( ftype, ch, blasname, blisname ) \ \ void PASTEF77(ch,blasname) \ ( \ const f77_char* transa_array, \ const f77_char* transb_array, \ const f77_int* m_array, \ const f77_int* n_array, \ const f77_int* k_array, \ const ftype* alpha_array, \ const ftype** a_array, const f77_int* lda_array, \ const ftype** b_array, const f77_int* ldb_array, \ const ftype* beta_array, \ ftype** c_array, const f77_int* ldc_array, \ const f77_int* group_count, \ const f77_int* group_size \ ) \ { \ trans_t blis_transa; \ trans_t blis_transb; \ dim_t m0, n0, k0; \ \ /* Initialize BLIS. */ \ bli_init_auto(); \ \ /* Perform BLAS parameter checking. */ \ for ( f77_int gi = 0; gi < *group_count; gi++ ) \ { \ PASTEBLACHK(blisname) \ ( \ MKSTR(ch), \ MKSTR(blisname), \ transa_array+gi, \ transb_array+gi, \ m_array+gi, \ n_array+gi, \ k_array+gi, \ lda_array+gi, \ ldb_array+gi, \ ldc_array+gi \ ); \ } \ \ f77_int idx = 0; \ \ for ( f77_int i = 0; i < *group_count; i++ ) \ { \ /* Map BLAS chars to their corresponding BLIS enumerated type value. */ \ bli_param_map_netlib_to_blis_trans( transa_array[i], &blis_transa ); \ bli_param_map_netlib_to_blis_trans( transb_array[i], &blis_transb ); \ \ /* Typecast BLAS integers to BLIS integers. */ \ bli_convert_blas_dim1( m_array[i], m0 ); \ bli_convert_blas_dim1( n_array[i], n0 ); \ bli_convert_blas_dim1( k_array[i], k0 ); \ \ /* Set the row and column strides of the matrix operands. */ \ const inc_t rs_a = 1; \ const inc_t cs_a = lda_array[i]; \ const inc_t rs_b = 1; \ const inc_t cs_b = ldb_array[i]; \ const inc_t rs_c = 1; \ const inc_t cs_c = ldc_array[i]; \ \ for ( f77_int j = 0; j < group_size[i]; j++ ) \ { \ /* Call BLIS interface. */ \ PASTEMAC2(ch,blisname,BLIS_TAPI_EX_SUF) \ ( \ blis_transa, \ blis_transb, \ m0, \ n0, \ k0, \ (ftype*)(alpha_array + i), \ (ftype*)*(a_array + idx), rs_a, cs_a, \ (ftype*)*(b_array + idx), rs_b, cs_b, \ (ftype*)(beta_array + i), \ (ftype*)*(c_array + idx), rs_c, cs_c, \ NULL, \ NULL \ ); \ \ idx++; \ } \ } \ \ bli_finalize_auto(); \ } #else #undef GENTFUNC #define GENTFUNC( ftype, ch, blasname, blisname ) \ \ void PASTEF77(ch,blasname) \ ( \ const f77_char* transa_array, \ const f77_char* transb_array, \ const f77_int* m_array, \ const f77_int* n_array, \ const f77_int* k_array, \ const ftype* alpha_array, \ const ftype** a_array, const f77_int* lda_array, \ const ftype** b_array, const f77_int* ldb_array, \ const ftype* beta_array, \ ftype** c_array, const f77_int* ldc_array, \ const f77_int* group_count, \ const f77_int* group_size ) \ { \ trans_t blis_transa; \ trans_t blis_transb; \ dim_t m0, n0, k0; \ \ /* Initialize BLIS. */ \ bli_init_auto(); \ \ /* Perform BLAS parameter checking. */ \ for ( f77_int gi = 0; gi < *group_count; gi++ ) \ { \ PASTEBLACHK(blisname) \ ( \ MKSTR(ch), \ MKSTR(blisname), \ transa_array+gi, \ transb_array+gi, \ m_array+gi, \ n_array+gi, \ k_array+gi, \ lda_array+gi, \ ldb_array+gi, \ ldc_array+gi \ ); \ } \ \ const num_t dt = PASTEMAC(ch,type); \ \ f77_int idx = 0, i, j; \ \ for ( i = 0; i < *group_count; i++ ) \ { \ /* Map BLAS chars to their corresponding BLIS enumerated type value. */ \ bli_param_map_netlib_to_blis_trans( transa_array[i], &blis_transa ); \ bli_param_map_netlib_to_blis_trans( transb_array[i], &blis_transb ); \ \ /* Typecast BLAS integers to BLIS integers. */ \ bli_convert_blas_dim1( m_array[i], m0 ); \ bli_convert_blas_dim1( n_array[i], n0 ); \ bli_convert_blas_dim1( k_array[i], k0 ); \ \ /* Set the row and column strides of the matrix operands. */ \ const inc_t rs_a = 1; \ const inc_t cs_a = lda_array[i]; \ const inc_t rs_b = 1; \ const inc_t cs_b = ldb_array[i]; \ const inc_t rs_c = 1; \ const inc_t cs_c = ldc_array[i]; \ \ obj_t alphao = BLIS_OBJECT_INITIALIZER_1X1; \ obj_t betao = BLIS_OBJECT_INITIALIZER_1X1; \ \ dim_t m0_a, n0_a; \ dim_t m0_b, n0_b; \ \ bli_set_dims_with_trans( blis_transa, m0, k0, &m0_a, &n0_a ); \ bli_set_dims_with_trans( blis_transb, k0, n0, &m0_b, &n0_b ); \ \ bli_obj_init_finish_1x1( dt, (ftype*)(alpha_array + i), &alphao ); \ bli_obj_init_finish_1x1( dt, (ftype*)(beta_array + i), &betao ); \ \ for( j = 0; j < group_size[i]; j++ ) \ { \ obj_t ao = BLIS_OBJECT_INITIALIZER; \ obj_t bo = BLIS_OBJECT_INITIALIZER; \ obj_t co = BLIS_OBJECT_INITIALIZER; \ \ bli_obj_init_finish( dt, m0_a, n0_a, (ftype*)*(a_array + idx), rs_a, cs_a, &ao ); \ bli_obj_init_finish( dt, m0_b, n0_b, (ftype*)*(b_array + idx), rs_b, cs_b, &bo ); \ bli_obj_init_finish( dt, m0, n0, (ftype*)*(c_array + idx), rs_c, cs_c, &co ); \ bli_obj_set_conjtrans( blis_transa, &ao ); \ bli_obj_set_conjtrans( blis_transb, &bo ); \ \ PASTEMAC(blisname,BLIS_OAPI_EX_SUF) \ ( \ &alphao, \ &ao, \ &bo, \ &betao, \ &co, \ NULL, \ NULL \ ); \ \ idx++; \ } \ } \ \ /* Finalize BLIS. */ \ bli_finalize_auto(); \ } #endif #ifdef BLIS_ENABLE_BLAS INSERT_GENTFUNC_BLAS( gemm_batch, gemm ) #endif blis-0.9.0/frame/compat/extra/bla_gemm_batch.h000066400000000000000000000045571422157504600212470ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype BLAS-to-BLIS interfaces. // #undef GENTPROT #define GENTPROT( ftype, ch, blasname ) \ \ BLIS_EXPORT_BLAS void PASTEF77(ch,blasname) \ ( \ const f77_char* transa_array, \ const f77_char* transb_array, \ const f77_int* m_array, \ const f77_int* n_array, \ const f77_int* k_array, \ const ftype* alpha_array, \ const ftype** a_array, const f77_int* lda_array, \ const ftype** b_array, const f77_int* ldb_array, \ const ftype* beta_array, \ ftype** c_array, const f77_int* ldc_array, \ const f77_int* group_count, \ const f77_int* group_size \ ); #ifdef BLIS_ENABLE_BLAS INSERT_GENTPROT_BLAS( gemm_batch ) #endif blis-0.9.0/frame/compat/extra/bla_gemmt.c000066400000000000000000000143171422157504600202600ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // Define BLAS-to-BLIS interfaces. // #ifdef BLIS_BLAS3_CALLS_TAPI #undef GENTFUNC #define GENTFUNC( ftype, ch, blasname, blisname ) \ \ void PASTEF77(ch,blasname) \ ( \ const f77_char* uploc, \ const f77_char* transa, \ const f77_char* transb, \ const f77_int* m, \ const f77_int* k, \ const ftype* alpha, \ const ftype* a, const f77_int* lda, \ const ftype* b, const f77_int* ldb, \ const ftype* beta, \ ftype* c, const f77_int* ldc \ ) \ { \ uplo_t blis_uploc; \ trans_t blis_transa; \ trans_t blis_transb; \ dim_t m0, k0; \ \ /* Initialize BLIS. */ \ bli_init_auto(); \ \ /* Perform BLAS parameter checking. */ \ PASTEBLACHK(blasname) \ ( \ MKSTR(ch), \ MKSTR(blasname), \ uploc, \ transa, \ transb, \ m, \ k, \ lda, \ ldb, \ ldc \ ); \ \ /* Map BLAS chars to their corresponding BLIS enumerated type value. */ \ bli_param_map_netlib_to_blis_uplo( *uploc, &blis_uploc ); \ bli_param_map_netlib_to_blis_trans( *transa, &blis_transa ); \ bli_param_map_netlib_to_blis_trans( *transb, &blis_transb ); \ \ /* Typecast BLAS integers to BLIS integers. */ \ bli_convert_blas_dim1( *m, m0 ); \ bli_convert_blas_dim1( *k, k0 ); \ \ /* Set the row and column strides of the matrix operands. */ \ const inc_t rs_a = 1; \ const inc_t cs_a = *lda; \ const inc_t rs_b = 1; \ const inc_t cs_b = *ldb; \ const inc_t rs_c = 1; \ const inc_t cs_c = *ldc; \ \ /* Call BLIS interface. */ \ PASTEMAC2(ch,blisname,BLIS_TAPI_EX_SUF) \ ( \ blis_uploc, \ blis_transa, \ blis_transb, \ m0, \ k0, \ (ftype*)alpha, \ (ftype*)a, rs_a, cs_a, \ (ftype*)b, rs_b, cs_b, \ (ftype*)beta, \ (ftype*)c, rs_c, cs_c, \ NULL, \ NULL \ ); \ \ /* Finalize BLIS. */ \ bli_finalize_auto(); \ } #else #undef GENTFUNC #define GENTFUNC( ftype, ch, blasname, blisname ) \ \ void PASTEF77(ch,blasname) \ ( \ const f77_char* uploc, \ const f77_char* transa, \ const f77_char* transb, \ const f77_int* m, \ const f77_int* k, \ const ftype* alpha, \ const ftype* a, const f77_int* lda, \ const ftype* b, const f77_int* ldb, \ const ftype* beta, \ ftype* c, const f77_int* ldc \ ) \ { \ uplo_t blis_uploc; \ trans_t blis_transa; \ trans_t blis_transb; \ dim_t m0, k0; \ \ /* Initialize BLIS. */ \ bli_init_auto(); \ \ /* Perform BLAS parameter checking. */ \ PASTEBLACHK(blasname) \ ( \ MKSTR(ch), \ MKSTR(blasname), \ uploc, \ transa, \ transb, \ m, \ k, \ lda, \ ldb, \ ldc \ ); \ \ /* Map BLAS chars to their corresponding BLIS enumerated type value. */ \ bli_param_map_netlib_to_blis_uplo( *uploc, &blis_uploc ); \ bli_param_map_netlib_to_blis_trans( *transa, &blis_transa ); \ bli_param_map_netlib_to_blis_trans( *transb, &blis_transb ); \ \ /* Typecast BLAS integers to BLIS integers. */ \ bli_convert_blas_dim1( *m, m0 ); \ bli_convert_blas_dim1( *k, k0 ); \ \ /* Set the row and column strides of the matrix operands. */ \ const inc_t rs_a = 1; \ const inc_t cs_a = *lda; \ const inc_t rs_b = 1; \ const inc_t cs_b = *ldb; \ const inc_t rs_c = 1; \ const inc_t cs_c = *ldc; \ \ const num_t dt = PASTEMAC(ch,type); \ \ const struc_t strucc = BLIS_SYMMETRIC; \ \ obj_t alphao = BLIS_OBJECT_INITIALIZER_1X1; \ obj_t ao = BLIS_OBJECT_INITIALIZER; \ obj_t bo = BLIS_OBJECT_INITIALIZER; \ obj_t betao = BLIS_OBJECT_INITIALIZER_1X1; \ obj_t co = BLIS_OBJECT_INITIALIZER; \ \ dim_t m0_a, n0_a; \ dim_t m0_b, n0_b; \ \ bli_set_dims_with_trans( blis_transa, m0, k0, &m0_a, &n0_a ); \ bli_set_dims_with_trans( blis_transb, k0, m0, &m0_b, &n0_b ); \ \ bli_obj_init_finish_1x1( dt, (ftype*)alpha, &alphao ); \ bli_obj_init_finish_1x1( dt, (ftype*)beta, &betao ); \ \ bli_obj_init_finish( dt, m0_a, n0_a, (ftype*)a, rs_a, cs_a, &ao ); \ bli_obj_init_finish( dt, m0_b, n0_b, (ftype*)b, rs_b, cs_b, &bo ); \ bli_obj_init_finish( dt, m0, m0, (ftype*)c, rs_c, cs_c, &co ); \ \ bli_obj_set_uplo( blis_uploc, &co ); \ bli_obj_set_conjtrans( blis_transa, &ao ); \ bli_obj_set_conjtrans( blis_transb, &bo ); \ \ bli_obj_set_struc( strucc, &co ); \ \ PASTEMAC(blisname,BLIS_OAPI_EX_SUF) \ ( \ &alphao, \ &ao, \ &bo, \ &betao, \ &co, \ NULL, \ NULL \ ); \ \ /* Finalize BLIS. */ \ bli_finalize_auto(); \ } #endif #ifdef BLIS_ENABLE_BLAS INSERT_GENTFUNC_BLAS( gemmt, gemmt ) #endif blis-0.9.0/frame/compat/extra/bla_gemmt.h000066400000000000000000000044161422157504600202640ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype BLAS-to-BLIS interfaces. // #undef GENTPROT #define GENTPROT( ftype, ch, blasname ) \ \ BLIS_EXPORT_BLAS void PASTEF77(ch,blasname) \ ( \ const f77_char* uploc, \ const f77_char* transa, \ const f77_char* transb, \ const f77_int* m, \ const f77_int* k, \ const ftype* alpha, \ const ftype* a, const f77_int* lda, \ const ftype* b, const f77_int* ldb, \ const ftype* beta, \ ftype* c, const f77_int* ldc \ ); #ifdef BLIS_ENABLE_BLAS INSERT_GENTPROT_BLAS( gemmt ) #endif blis-0.9.0/frame/compat/f2c/000077500000000000000000000000001422157504600155065ustar00rootroot00000000000000blis-0.9.0/frame/compat/f2c/bla_cabs1.c000066400000000000000000000044531422157504600174670ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #ifdef BLIS_ENABLE_BLAS /* scabs1.f -- translated by f2c (version 19991025). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ /* Subroutine */ bla_real PASTEF77(s,cabs1)(bla_scomplex *z) { return bli_fabs( bli_creal( *z ) ) + bli_fabs( bli_cimag( *z ) ); } /* scabs1_ */ /* dcabs1.f -- translated by f2c (version 19991025). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ /* Subroutine */ bla_double PASTEF77(d,cabs1)(bla_dcomplex *z) { return bli_fabs( bli_zreal( *z ) ) + bli_fabs( bli_zimag( *z ) ); } /* dcabs1_ */ #endif blis-0.9.0/frame/compat/f2c/bla_cabs1.h000066400000000000000000000034521422157504600174720ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifdef BLIS_ENABLE_BLAS BLIS_EXPORT_BLAS bla_real PASTEF77(s,cabs1)(bla_scomplex *z); BLIS_EXPORT_BLAS bla_double PASTEF77(d,cabs1)(bla_dcomplex *z); #endif blis-0.9.0/frame/compat/f2c/bla_gbmv.c000066400000000000000000001450771422157504600174410ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #ifdef BLIS_ENABLE_BLAS /* cgbmv.f -- translated by f2c (version 19991025). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ /* Subroutine */ int PASTEF77(c,gbmv)(const bla_character *trans, const bla_integer *m, const bla_integer *n, const bla_integer *kl, const bla_integer *ku, const bla_scomplex *alpha, const bla_scomplex *a, const bla_integer *lda, const bla_scomplex *x, const bla_integer *incx, const bla_scomplex *beta, bla_scomplex *y, const bla_integer *incy) { /* System generated locals */ bla_integer a_dim1, a_offset, i__1, i__2, i__3, i__4, i__5, i__6; bla_scomplex q__1, q__2, q__3; /* Builtin functions */ //void bla_r_cnjg(bla_scomplex *, bla_scomplex *); /* Local variables */ bla_integer info; bla_scomplex temp; bla_integer lenx, leny, i__, j, k; //extern bla_logical PASTEF770(lsame)(bla_character *, bla_character *, ftnlen, ftnlen); bla_integer ix, iy, jx, jy, kx, ky; //extern /* Subroutine */ int PASTEF770(xerbla)(bla_character *, bla_integer *, ftnlen); bla_logical noconj; bla_integer kup1; /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* CGBMV performs one of the matrix-vector operations */ /* y := alpha*A*x + beta*y, or y := alpha*A'*x + beta*y, or */ /* y := alpha*conjg( A' )*x + beta*y, */ /* where alpha and beta are scalars, x and y are vectors and A is an */ /* m by n band matrix, with kl sub-diagonals and ku super-diagonals. */ /* Parameters */ /* ========== */ /* TRANS - CHARACTER*1. */ /* On entry, TRANS specifies the operation to be performed as */ /* follows: */ /* TRANS = 'N' or 'n' y := alpha*A*x + beta*y. */ /* TRANS = 'T' or 't' y := alpha*A'*x + beta*y. */ /* TRANS = 'C' or 'c' y := alpha*conjg( A' )*x + beta*y. */ /* Unchanged on exit. */ /* M - INTEGER. */ /* On entry, M specifies the number of rows of the matrix A. */ /* M must be at least zero. */ /* Unchanged on exit. */ /* N - INTEGER. */ /* On entry, N specifies the number of columns of the matrix A. */ /* N must be at least zero. */ /* Unchanged on exit. */ /* KL - INTEGER. */ /* On entry, KL specifies the number of sub-diagonals of the */ /* matrix A. KL must satisfy 0 .le. KL. */ /* Unchanged on exit. */ /* KU - INTEGER. */ /* On entry, KU specifies the number of super-diagonals of the */ /* matrix A. KU must satisfy 0 .le. KU. */ /* Unchanged on exit. */ /* ALPHA - COMPLEX . */ /* On entry, ALPHA specifies the scalar alpha. */ /* Unchanged on exit. */ /* A - COMPLEX array of DIMENSION ( LDA, n ). */ /* Before entry, the leading ( kl + ku + 1 ) by n part of the */ /* array A must contain the matrix of coefficients, supplied */ /* column by column, with the leading diagonal of the matrix in */ /* row ( ku + 1 ) of the array, the first super-diagonal */ /* starting at position 2 in row ku, the first sub-diagonal */ /* starting at position 1 in row ( ku + 2 ), and so on. */ /* Elements in the array A that do not correspond to elements */ /* in the band matrix (such as the top left ku by ku triangle) */ /* are not referenced. */ /* The following program segment will transfer a band matrix */ /* from conventional full matrix storage to band storage: */ /* DO 20, J = 1, N */ /* K = KU + 1 - J */ /* DO 10, I = MAX( 1, J - KU ), MIN( M, J + KL ) */ /* A( K + I, J ) = matrix( I, J ) */ /* 10 CONTINUE */ /* 20 CONTINUE */ /* Unchanged on exit. */ /* LDA - INTEGER. */ /* On entry, LDA specifies the first dimension of A as declared */ /* in the calling (sub) program. LDA must be at least */ /* ( kl + ku + 1 ). */ /* Unchanged on exit. */ /* X - COMPLEX array of DIMENSION at least */ /* ( 1 + ( n - 1 )*abs( INCX ) ) when TRANS = 'N' or 'n' */ /* and at least */ /* ( 1 + ( m - 1 )*abs( INCX ) ) otherwise. */ /* Before entry, the incremented array X must contain the */ /* vector x. */ /* Unchanged on exit. */ /* INCX - INTEGER. */ /* On entry, INCX specifies the increment for the elements of */ /* X. INCX must not be zero. */ /* Unchanged on exit. */ /* BETA - COMPLEX . */ /* On entry, BETA specifies the scalar beta. When BETA is */ /* supplied as zero then Y need not be set on input. */ /* Unchanged on exit. */ /* Y - COMPLEX array of DIMENSION at least */ /* ( 1 + ( m - 1 )*abs( INCY ) ) when TRANS = 'N' or 'n' */ /* and at least */ /* ( 1 + ( n - 1 )*abs( INCY ) ) otherwise. */ /* Before entry, the incremented array Y must contain the */ /* vector y. On exit, Y is overwritten by the updated vector y. */ /* INCY - INTEGER. */ /* On entry, INCY specifies the increment for the elements of */ /* Y. INCY must not be zero. */ /* Unchanged on exit. */ /* Level 2 Blas routine. */ /* -- Written on 22-October-1986. */ /* Jack Dongarra, Argonne National Lab. */ /* Jeremy Du Croz, Nag Central Office. */ /* Sven Hammarling, Nag Central Office. */ /* Richard Hanson, Sandia National Labs. */ /* .. Parameters .. */ /* .. Local Scalars .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. */ /* .. Executable Statements .. */ /* Test the input parameters. */ /* Parameter adjustments */ a_dim1 = *lda; a_offset = 1 + a_dim1 * 1; a -= a_offset; --x; --y; /* Function Body */ info = 0; if (! PASTEF770(lsame)(trans, "N", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(trans, "T", ( ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(trans, "C", (ftnlen)1, (ftnlen)1) ) { info = 1; } else if (*m < 0) { info = 2; } else if (*n < 0) { info = 3; } else if (*kl < 0) { info = 4; } else if (*ku < 0) { info = 5; } else if (*lda < *kl + *ku + 1) { info = 8; } else if (*incx == 0) { info = 10; } else if (*incy == 0) { info = 13; } if (info != 0) { PASTEF770(xerbla)("CGBMV ", &info, (ftnlen)6); return 0; } /* Quick return if possible. */ if (*m == 0 || *n == 0 || (bli_creal(*alpha) == 0.f && bli_cimag(*alpha) == 0.f && (bli_creal(*beta) == 1.f && bli_cimag(*beta) == 0.f))) { return 0; } noconj = PASTEF770(lsame)(trans, "T", (ftnlen)1, (ftnlen)1); /* Set LENX and LENY, the lengths of the vectors x and y, and set */ /* up the start points in X and Y. */ if (PASTEF770(lsame)(trans, "N", (ftnlen)1, (ftnlen)1)) { lenx = *n; leny = *m; } else { lenx = *m; leny = *n; } if (*incx > 0) { kx = 1; } else { kx = 1 - (lenx - 1) * *incx; } if (*incy > 0) { ky = 1; } else { ky = 1 - (leny - 1) * *incy; } /* Start the operations. In this version the elements of A are */ /* accessed sequentially with one pass through the band part of A. */ /* First form y := beta*y. */ if (bli_creal(*beta) != 1.f || bli_cimag(*beta) != 0.f) { if (*incy == 1) { if (bli_creal(*beta) == 0.f && bli_cimag(*beta) == 0.f) { i__1 = leny; for (i__ = 1; i__ <= i__1; ++i__) { i__2 = i__; bli_csets( (0.f), (0.f), y[i__2] ); /* L10: */ } } else { i__1 = leny; for (i__ = 1; i__ <= i__1; ++i__) { i__2 = i__; i__3 = i__; bli_csets( (bli_creal(*beta) * bli_creal(y[i__3]) - bli_cimag(*beta) * bli_cimag(y[i__3])), (bli_creal(*beta) * bli_cimag(y[i__3]) + bli_cimag(*beta) * bli_creal(y[i__3])), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), y[i__2] ); /* L20: */ } } } else { iy = ky; if (bli_creal(*beta) == 0.f && bli_cimag(*beta) == 0.f) { i__1 = leny; for (i__ = 1; i__ <= i__1; ++i__) { i__2 = iy; bli_csets( (0.f), (0.f), y[i__2] ); iy += *incy; /* L30: */ } } else { i__1 = leny; for (i__ = 1; i__ <= i__1; ++i__) { i__2 = iy; i__3 = iy; bli_csets( (bli_creal(*beta) * bli_creal(y[i__3]) - bli_cimag(*beta) * bli_cimag(y[i__3])), (bli_creal(*beta) * bli_cimag(y[i__3]) + bli_cimag(*beta) * bli_creal(y[i__3])), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), y[i__2] ); iy += *incy; /* L40: */ } } } } if (bli_creal(*alpha) == 0.f && bli_cimag(*alpha) == 0.f) { return 0; } kup1 = *ku + 1; if (PASTEF770(lsame)(trans, "N", (ftnlen)1, (ftnlen)1)) { /* Form y := alpha*A*x + y. */ jx = kx; if (*incy == 1) { i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = jx; if (bli_creal(x[i__2]) != 0.f || bli_cimag(x[i__2]) != 0.f) { i__2 = jx; bli_csets( (bli_creal(*alpha) * bli_creal(x[i__2]) - bli_cimag(*alpha) * bli_cimag(x[i__2])), (bli_creal(*alpha) * bli_cimag(x[i__2]) + bli_cimag(*alpha) * bli_creal(x[i__2])), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp ); k = kup1 - j; /* Computing MAX */ i__2 = 1, i__3 = j - *ku; /* Computing MIN */ i__5 = *m, i__6 = j + *kl; i__4 = f2c_min(i__5,i__6); for (i__ = f2c_max(i__2,i__3); i__ <= i__4; ++i__) { i__2 = i__; i__3 = i__; i__5 = k + i__ + j * a_dim1; bli_csets( (bli_creal(temp) * bli_creal(a[i__5]) - bli_cimag(temp) * bli_cimag(a[i__5])), (bli_creal(temp) * bli_cimag(a[i__5]) + bli_cimag(temp) * bli_creal(a[i__5])), q__2 ); bli_csets( (bli_creal(y[i__3]) + bli_creal(q__2)), (bli_cimag(y[i__3]) + bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), y[i__2] ); /* L50: */ } } jx += *incx; /* L60: */ } } else { i__1 = *n; for (j = 1; j <= i__1; ++j) { i__4 = jx; if (bli_creal(x[i__4]) != 0.f || bli_cimag(x[i__4]) != 0.f) { i__4 = jx; bli_csets( (bli_creal(*alpha) * bli_creal(x[i__4]) - bli_cimag(*alpha) * bli_cimag(x[i__4])), (bli_creal(*alpha) * bli_cimag(x[i__4]) + bli_cimag(*alpha) * bli_creal(x[i__4])), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp ); iy = ky; k = kup1 - j; /* Computing MAX */ i__4 = 1, i__2 = j - *ku; /* Computing MIN */ i__5 = *m, i__6 = j + *kl; i__3 = f2c_min(i__5,i__6); for (i__ = f2c_max(i__4,i__2); i__ <= i__3; ++i__) { i__4 = iy; i__2 = iy; i__5 = k + i__ + j * a_dim1; bli_csets( (bli_creal(temp) * bli_creal(a[i__5]) - bli_cimag(temp) * bli_cimag(a[i__5])), (bli_creal(temp) * bli_cimag(a[i__5]) + bli_cimag(temp) * bli_creal(a[i__5])), q__2 ); bli_csets( (bli_creal(y[i__2]) + bli_creal(q__2)), (bli_cimag(y[i__2]) + bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), y[i__4] ); iy += *incy; /* L70: */ } } jx += *incx; if (j > *ku) { ky += *incy; } /* L80: */ } } } else { /* Form y := alpha*A'*x + y or y := alpha*conjg( A' )*x + y. */ jy = ky; if (*incx == 1) { i__1 = *n; for (j = 1; j <= i__1; ++j) { bli_csets( (0.f), (0.f), temp ); k = kup1 - j; if (noconj) { /* Computing MAX */ i__3 = 1, i__4 = j - *ku; /* Computing MIN */ i__5 = *m, i__6 = j + *kl; i__2 = f2c_min(i__5,i__6); for (i__ = f2c_max(i__3,i__4); i__ <= i__2; ++i__) { i__3 = k + i__ + j * a_dim1; i__4 = i__; bli_csets( (bli_creal(a[i__3]) * bli_creal(x[i__4]) - bli_cimag(a[i__3]) * bli_cimag(x[i__4])), (bli_creal(a[i__3]) * bli_cimag(x[i__4]) + bli_cimag(a[i__3]) * bli_creal(x[i__4])), q__2 ); bli_csets( (bli_creal(temp) + bli_creal(q__2)), (bli_cimag(temp) + bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp ); /* L90: */ } } else { /* Computing MAX */ i__2 = 1, i__3 = j - *ku; /* Computing MIN */ i__5 = *m, i__6 = j + *kl; i__4 = f2c_min(i__5,i__6); for (i__ = f2c_max(i__2,i__3); i__ <= i__4; ++i__) { bla_r_cnjg(&q__3, &a[k + i__ + j * a_dim1]); i__2 = i__; bli_csets( (bli_creal(q__3) * bli_creal(x[i__2]) - bli_cimag(q__3) * bli_cimag(x[i__2])), (bli_creal(q__3) * bli_cimag(x[i__2]) + bli_cimag(q__3) * bli_creal(x[i__2])), q__2 ); bli_csets( (bli_creal(temp) + bli_creal(q__2)), (bli_cimag(temp) + bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp ); /* L100: */ } } i__4 = jy; i__2 = jy; bli_csets( (bli_creal(*alpha) * bli_creal(temp) - bli_cimag(*alpha) * bli_cimag(temp)), (bli_creal(*alpha) * bli_cimag(temp) + bli_cimag(*alpha) * bli_creal(temp)), q__2 ); bli_csets( (bli_creal(y[i__2]) + bli_creal(q__2)), (bli_cimag(y[i__2]) + bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), y[i__4] ); jy += *incy; /* L110: */ } } else { i__1 = *n; for (j = 1; j <= i__1; ++j) { bli_csets( (0.f), (0.f), temp ); ix = kx; k = kup1 - j; if (noconj) { /* Computing MAX */ i__4 = 1, i__2 = j - *ku; /* Computing MIN */ i__5 = *m, i__6 = j + *kl; i__3 = f2c_min(i__5,i__6); for (i__ = f2c_max(i__4,i__2); i__ <= i__3; ++i__) { i__4 = k + i__ + j * a_dim1; i__2 = ix; bli_csets( (bli_creal(a[i__4]) * bli_creal(x[i__2]) - bli_cimag(a[i__4]) * bli_cimag(x[i__2])), (bli_creal(a[i__4]) * bli_cimag(x[i__2]) + bli_cimag(a[i__4]) * bli_creal(x[i__2])), q__2 ); bli_csets( (bli_creal(temp) + bli_creal(q__2)), (bli_cimag(temp) + bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp ); ix += *incx; /* L120: */ } } else { /* Computing MAX */ i__3 = 1, i__4 = j - *ku; /* Computing MIN */ i__5 = *m, i__6 = j + *kl; i__2 = f2c_min(i__5,i__6); for (i__ = f2c_max(i__3,i__4); i__ <= i__2; ++i__) { bla_r_cnjg(&q__3, &a[k + i__ + j * a_dim1]); i__3 = ix; bli_csets( (bli_creal(q__3) * bli_creal(x[i__3]) - bli_cimag(q__3) * bli_cimag(x[i__3])), (bli_creal(q__3) * bli_cimag(x[i__3]) + bli_cimag(q__3) * bli_creal(x[i__3])), q__2 ); bli_csets( (bli_creal(temp) + bli_creal(q__2)), (bli_cimag(temp) + bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp ); ix += *incx; /* L130: */ } } i__2 = jy; i__3 = jy; bli_csets( (bli_creal(*alpha) * bli_creal(temp) - bli_cimag(*alpha) * bli_cimag(temp)), (bli_creal(*alpha) * bli_cimag(temp) + bli_cimag(*alpha) * bli_creal(temp)), q__2 ); bli_csets( (bli_creal(y[i__3]) + bli_creal(q__2)), (bli_cimag(y[i__3]) + bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), y[i__2] ); jy += *incy; if (j > *ku) { kx += *incx; } /* L140: */ } } } return 0; /* End of CGBMV . */ } /* cgbmv_ */ /* dgbmv.f -- translated by f2c (version 19991025). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ /* Subroutine */ int PASTEF77(d,gbmv)(const bla_character *trans, const bla_integer *m, const bla_integer *n, const bla_integer *kl, const bla_integer *ku, const bla_double *alpha, const bla_double *a, const bla_integer *lda, const bla_double *x, const bla_integer *incx, const bla_double *beta, bla_double *y, const bla_integer *incy) { /* System generated locals */ bla_integer a_dim1, a_offset, i__1, i__2, i__3, i__4, i__5, i__6; /* Local variables */ bla_integer info; bla_double temp; bla_integer lenx, leny, i__, j, k; //extern bla_logical PASTEF770(lsame)(bla_character *, bla_character *, ftnlen, ftnlen); bla_integer ix, iy, jx, jy, kx, ky; //extern /* Subroutine */ int PASTEF770(xerbla)(bla_character *, bla_integer *, ftnlen); bla_integer kup1; /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* DGBMV performs one of the matrix-vector operations */ /* y := alpha*A*x + beta*y, or y := alpha*A'*x + beta*y, */ /* where alpha and beta are scalars, x and y are vectors and A is an */ /* m by n band matrix, with kl sub-diagonals and ku super-diagonals. */ /* Parameters */ /* ========== */ /* TRANS - CHARACTER*1. */ /* On entry, TRANS specifies the operation to be performed as */ /* follows: */ /* TRANS = 'N' or 'n' y := alpha*A*x + beta*y. */ /* TRANS = 'T' or 't' y := alpha*A'*x + beta*y. */ /* TRANS = 'C' or 'c' y := alpha*A'*x + beta*y. */ /* Unchanged on exit. */ /* M - INTEGER. */ /* On entry, M specifies the number of rows of the matrix A. */ /* M must be at least zero. */ /* Unchanged on exit. */ /* N - INTEGER. */ /* On entry, N specifies the number of columns of the matrix A. */ /* N must be at least zero. */ /* Unchanged on exit. */ /* KL - INTEGER. */ /* On entry, KL specifies the number of sub-diagonals of the */ /* matrix A. KL must satisfy 0 .le. KL. */ /* Unchanged on exit. */ /* KU - INTEGER. */ /* On entry, KU specifies the number of super-diagonals of the */ /* matrix A. KU must satisfy 0 .le. KU. */ /* Unchanged on exit. */ /* ALPHA - DOUBLE PRECISION. */ /* On entry, ALPHA specifies the scalar alpha. */ /* Unchanged on exit. */ /* A - DOUBLE PRECISION array of DIMENSION ( LDA, n ). */ /* Before entry, the leading ( kl + ku + 1 ) by n part of the */ /* array A must contain the matrix of coefficients, supplied */ /* column by column, with the leading diagonal of the matrix in */ /* row ( ku + 1 ) of the array, the first super-diagonal */ /* starting at position 2 in row ku, the first sub-diagonal */ /* starting at position 1 in row ( ku + 2 ), and so on. */ /* Elements in the array A that do not correspond to elements */ /* in the band matrix (such as the top left ku by ku triangle) */ /* are not referenced. */ /* The following program segment will transfer a band matrix */ /* from conventional full matrix storage to band storage: */ /* DO 20, J = 1, N */ /* K = KU + 1 - J */ /* DO 10, I = MAX( 1, J - KU ), MIN( M, J + KL ) */ /* A( K + I, J ) = matrix( I, J ) */ /* 10 CONTINUE */ /* 20 CONTINUE */ /* Unchanged on exit. */ /* LDA - INTEGER. */ /* On entry, LDA specifies the first dimension of A as declared */ /* in the calling (sub) program. LDA must be at least */ /* ( kl + ku + 1 ). */ /* Unchanged on exit. */ /* X - DOUBLE PRECISION array of DIMENSION at least */ /* ( 1 + ( n - 1 )*abs( INCX ) ) when TRANS = 'N' or 'n' */ /* and at least */ /* ( 1 + ( m - 1 )*abs( INCX ) ) otherwise. */ /* Before entry, the incremented array X must contain the */ /* vector x. */ /* Unchanged on exit. */ /* INCX - INTEGER. */ /* On entry, INCX specifies the increment for the elements of */ /* X. INCX must not be zero. */ /* Unchanged on exit. */ /* BETA - DOUBLE PRECISION. */ /* On entry, BETA specifies the scalar beta. When BETA is */ /* supplied as zero then Y need not be set on input. */ /* Unchanged on exit. */ /* Y - DOUBLE PRECISION array of DIMENSION at least */ /* ( 1 + ( m - 1 )*abs( INCY ) ) when TRANS = 'N' or 'n' */ /* and at least */ /* ( 1 + ( n - 1 )*abs( INCY ) ) otherwise. */ /* Before entry, the incremented array Y must contain the */ /* vector y. On exit, Y is overwritten by the updated vector y. */ /* INCY - INTEGER. */ /* On entry, INCY specifies the increment for the elements of */ /* Y. INCY must not be zero. */ /* Unchanged on exit. */ /* Level 2 Blas routine. */ /* -- Written on 22-October-1986. */ /* Jack Dongarra, Argonne National Lab. */ /* Jeremy Du Croz, Nag Central Office. */ /* Sven Hammarling, Nag Central Office. */ /* Richard Hanson, Sandia National Labs. */ /* .. Parameters .. */ /* .. Local Scalars .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. */ /* .. Executable Statements .. */ /* Test the input parameters. */ /* Parameter adjustments */ a_dim1 = *lda; a_offset = 1 + a_dim1 * 1; a -= a_offset; --x; --y; /* Function Body */ info = 0; if (! PASTEF770(lsame)(trans, "N", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(trans, "T", ( ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(trans, "C", (ftnlen)1, (ftnlen)1) ) { info = 1; } else if (*m < 0) { info = 2; } else if (*n < 0) { info = 3; } else if (*kl < 0) { info = 4; } else if (*ku < 0) { info = 5; } else if (*lda < *kl + *ku + 1) { info = 8; } else if (*incx == 0) { info = 10; } else if (*incy == 0) { info = 13; } if (info != 0) { PASTEF770(xerbla)("DGBMV ", &info, (ftnlen)6); return 0; } /* Quick return if possible. */ if (*m == 0 || *n == 0 || (*alpha == 0. && *beta == 1.)) { return 0; } /* Set LENX and LENY, the lengths of the vectors x and y, and set */ /* up the start points in X and Y. */ if (PASTEF770(lsame)(trans, "N", (ftnlen)1, (ftnlen)1)) { lenx = *n; leny = *m; } else { lenx = *m; leny = *n; } if (*incx > 0) { kx = 1; } else { kx = 1 - (lenx - 1) * *incx; } if (*incy > 0) { ky = 1; } else { ky = 1 - (leny - 1) * *incy; } /* Start the operations. In this version the elements of A are */ /* accessed sequentially with one pass through the band part of A. */ /* First form y := beta*y. */ if (*beta != 1.) { if (*incy == 1) { if (*beta == 0.) { i__1 = leny; for (i__ = 1; i__ <= i__1; ++i__) { y[i__] = 0.; /* L10: */ } } else { i__1 = leny; for (i__ = 1; i__ <= i__1; ++i__) { y[i__] = *beta * y[i__]; /* L20: */ } } } else { iy = ky; if (*beta == 0.) { i__1 = leny; for (i__ = 1; i__ <= i__1; ++i__) { y[iy] = 0.; iy += *incy; /* L30: */ } } else { i__1 = leny; for (i__ = 1; i__ <= i__1; ++i__) { y[iy] = *beta * y[iy]; iy += *incy; /* L40: */ } } } } if (*alpha == 0.) { return 0; } kup1 = *ku + 1; if (PASTEF770(lsame)(trans, "N", (ftnlen)1, (ftnlen)1)) { /* Form y := alpha*A*x + y. */ jx = kx; if (*incy == 1) { i__1 = *n; for (j = 1; j <= i__1; ++j) { if (x[jx] != 0.) { temp = *alpha * x[jx]; k = kup1 - j; /* Computing MAX */ i__2 = 1, i__3 = j - *ku; /* Computing MIN */ i__5 = *m, i__6 = j + *kl; i__4 = f2c_min(i__5,i__6); for (i__ = f2c_max(i__2,i__3); i__ <= i__4; ++i__) { y[i__] += temp * a[k + i__ + j * a_dim1]; /* L50: */ } } jx += *incx; /* L60: */ } } else { i__1 = *n; for (j = 1; j <= i__1; ++j) { if (x[jx] != 0.) { temp = *alpha * x[jx]; iy = ky; k = kup1 - j; /* Computing MAX */ i__4 = 1, i__2 = j - *ku; /* Computing MIN */ i__5 = *m, i__6 = j + *kl; i__3 = f2c_min(i__5,i__6); for (i__ = f2c_max(i__4,i__2); i__ <= i__3; ++i__) { y[iy] += temp * a[k + i__ + j * a_dim1]; iy += *incy; /* L70: */ } } jx += *incx; if (j > *ku) { ky += *incy; } /* L80: */ } } } else { /* Form y := alpha*A'*x + y. */ jy = ky; if (*incx == 1) { i__1 = *n; for (j = 1; j <= i__1; ++j) { temp = 0.; k = kup1 - j; /* Computing MAX */ i__3 = 1, i__4 = j - *ku; /* Computing MIN */ i__5 = *m, i__6 = j + *kl; i__2 = f2c_min(i__5,i__6); for (i__ = f2c_max(i__3,i__4); i__ <= i__2; ++i__) { temp += a[k + i__ + j * a_dim1] * x[i__]; /* L90: */ } y[jy] += *alpha * temp; jy += *incy; /* L100: */ } } else { i__1 = *n; for (j = 1; j <= i__1; ++j) { temp = 0.; ix = kx; k = kup1 - j; /* Computing MAX */ i__2 = 1, i__3 = j - *ku; /* Computing MIN */ i__5 = *m, i__6 = j + *kl; i__4 = f2c_min(i__5,i__6); for (i__ = f2c_max(i__2,i__3); i__ <= i__4; ++i__) { temp += a[k + i__ + j * a_dim1] * x[ix]; ix += *incx; /* L110: */ } y[jy] += *alpha * temp; jy += *incy; if (j > *ku) { kx += *incx; } /* L120: */ } } } return 0; /* End of DGBMV . */ } /* dgbmv_ */ /* sgbmv.f -- translated by f2c (version 19991025). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ /* Subroutine */ int PASTEF77(s,gbmv)(const bla_character *trans, const bla_integer *m, const bla_integer *n, const bla_integer *kl, const bla_integer *ku, const bla_real *alpha, const bla_real *a, const bla_integer *lda, const bla_real *x, const bla_integer * incx, const bla_real *beta, bla_real *y, const bla_integer *incy) { /* System generated locals */ bla_integer a_dim1, a_offset, i__1, i__2, i__3, i__4, i__5, i__6; /* Local variables */ bla_integer info; bla_real temp; bla_integer lenx, leny, i__, j, k; //extern bla_logical PASTEF770(lsame)(bla_character *, bla_character *, ftnlen, ftnlen); bla_integer ix, iy, jx, jy, kx, ky; //extern /* Subroutine */ int PASTEF770(xerbla)(bla_character *, bla_integer *, ftnlen); bla_integer kup1; /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* SGBMV performs one of the matrix-vector operations */ /* y := alpha*A*x + beta*y, or y := alpha*A'*x + beta*y, */ /* where alpha and beta are scalars, x and y are vectors and A is an */ /* m by n band matrix, with kl sub-diagonals and ku super-diagonals. */ /* Parameters */ /* ========== */ /* TRANS - CHARACTER*1. */ /* On entry, TRANS specifies the operation to be performed as */ /* follows: */ /* TRANS = 'N' or 'n' y := alpha*A*x + beta*y. */ /* TRANS = 'T' or 't' y := alpha*A'*x + beta*y. */ /* TRANS = 'C' or 'c' y := alpha*A'*x + beta*y. */ /* Unchanged on exit. */ /* M - INTEGER. */ /* On entry, M specifies the number of rows of the matrix A. */ /* M must be at least zero. */ /* Unchanged on exit. */ /* N - INTEGER. */ /* On entry, N specifies the number of columns of the matrix A. */ /* N must be at least zero. */ /* Unchanged on exit. */ /* KL - INTEGER. */ /* On entry, KL specifies the number of sub-diagonals of the */ /* matrix A. KL must satisfy 0 .le. KL. */ /* Unchanged on exit. */ /* KU - INTEGER. */ /* On entry, KU specifies the number of super-diagonals of the */ /* matrix A. KU must satisfy 0 .le. KU. */ /* Unchanged on exit. */ /* ALPHA - REAL . */ /* On entry, ALPHA specifies the scalar alpha. */ /* Unchanged on exit. */ /* A - REAL array of DIMENSION ( LDA, n ). */ /* Before entry, the leading ( kl + ku + 1 ) by n part of the */ /* array A must contain the matrix of coefficients, supplied */ /* column by column, with the leading diagonal of the matrix in */ /* row ( ku + 1 ) of the array, the first super-diagonal */ /* starting at position 2 in row ku, the first sub-diagonal */ /* starting at position 1 in row ( ku + 2 ), and so on. */ /* Elements in the array A that do not correspond to elements */ /* in the band matrix (such as the top left ku by ku triangle) */ /* are not referenced. */ /* The following program segment will transfer a band matrix */ /* from conventional full matrix storage to band storage: */ /* DO 20, J = 1, N */ /* K = KU + 1 - J */ /* DO 10, I = MAX( 1, J - KU ), MIN( M, J + KL ) */ /* A( K + I, J ) = matrix( I, J ) */ /* 10 CONTINUE */ /* 20 CONTINUE */ /* Unchanged on exit. */ /* LDA - INTEGER. */ /* On entry, LDA specifies the first dimension of A as declared */ /* in the calling (sub) program. LDA must be at least */ /* ( kl + ku + 1 ). */ /* Unchanged on exit. */ /* X - REAL array of DIMENSION at least */ /* ( 1 + ( n - 1 )*abs( INCX ) ) when TRANS = 'N' or 'n' */ /* and at least */ /* ( 1 + ( m - 1 )*abs( INCX ) ) otherwise. */ /* Before entry, the incremented array X must contain the */ /* vector x. */ /* Unchanged on exit. */ /* INCX - INTEGER. */ /* On entry, INCX specifies the increment for the elements of */ /* X. INCX must not be zero. */ /* Unchanged on exit. */ /* BETA - REAL . */ /* On entry, BETA specifies the scalar beta. When BETA is */ /* supplied as zero then Y need not be set on input. */ /* Unchanged on exit. */ /* Y - REAL array of DIMENSION at least */ /* ( 1 + ( m - 1 )*abs( INCY ) ) when TRANS = 'N' or 'n' */ /* and at least */ /* ( 1 + ( n - 1 )*abs( INCY ) ) otherwise. */ /* Before entry, the incremented array Y must contain the */ /* vector y. On exit, Y is overwritten by the updated vector y. */ /* INCY - INTEGER. */ /* On entry, INCY specifies the increment for the elements of */ /* Y. INCY must not be zero. */ /* Unchanged on exit. */ /* Level 2 Blas routine. */ /* -- Written on 22-October-1986. */ /* Jack Dongarra, Argonne National Lab. */ /* Jeremy Du Croz, Nag Central Office. */ /* Sven Hammarling, Nag Central Office. */ /* Richard Hanson, Sandia National Labs. */ /* .. Parameters .. */ /* .. Local Scalars .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. */ /* .. Executable Statements .. */ /* Test the input parameters. */ /* Parameter adjustments */ a_dim1 = *lda; a_offset = 1 + a_dim1 * 1; a -= a_offset; --x; --y; /* Function Body */ info = 0; if (! PASTEF770(lsame)(trans, "N", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(trans, "T", ( ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(trans, "C", (ftnlen)1, (ftnlen)1) ) { info = 1; } else if (*m < 0) { info = 2; } else if (*n < 0) { info = 3; } else if (*kl < 0) { info = 4; } else if (*ku < 0) { info = 5; } else if (*lda < *kl + *ku + 1) { info = 8; } else if (*incx == 0) { info = 10; } else if (*incy == 0) { info = 13; } if (info != 0) { PASTEF770(xerbla)("SGBMV ", &info, (ftnlen)6); return 0; } /* Quick return if possible. */ if (*m == 0 || *n == 0 || (*alpha == 0.f && *beta == 1.f)) { return 0; } /* Set LENX and LENY, the lengths of the vectors x and y, and set */ /* up the start points in X and Y. */ if (PASTEF770(lsame)(trans, "N", (ftnlen)1, (ftnlen)1)) { lenx = *n; leny = *m; } else { lenx = *m; leny = *n; } if (*incx > 0) { kx = 1; } else { kx = 1 - (lenx - 1) * *incx; } if (*incy > 0) { ky = 1; } else { ky = 1 - (leny - 1) * *incy; } /* Start the operations. In this version the elements of A are */ /* accessed sequentially with one pass through the band part of A. */ /* First form y := beta*y. */ if (*beta != 1.f) { if (*incy == 1) { if (*beta == 0.f) { i__1 = leny; for (i__ = 1; i__ <= i__1; ++i__) { y[i__] = 0.f; /* L10: */ } } else { i__1 = leny; for (i__ = 1; i__ <= i__1; ++i__) { y[i__] = *beta * y[i__]; /* L20: */ } } } else { iy = ky; if (*beta == 0.f) { i__1 = leny; for (i__ = 1; i__ <= i__1; ++i__) { y[iy] = 0.f; iy += *incy; /* L30: */ } } else { i__1 = leny; for (i__ = 1; i__ <= i__1; ++i__) { y[iy] = *beta * y[iy]; iy += *incy; /* L40: */ } } } } if (*alpha == 0.f) { return 0; } kup1 = *ku + 1; if (PASTEF770(lsame)(trans, "N", (ftnlen)1, (ftnlen)1)) { /* Form y := alpha*A*x + y. */ jx = kx; if (*incy == 1) { i__1 = *n; for (j = 1; j <= i__1; ++j) { if (x[jx] != 0.f) { temp = *alpha * x[jx]; k = kup1 - j; /* Computing MAX */ i__2 = 1, i__3 = j - *ku; /* Computing MIN */ i__5 = *m, i__6 = j + *kl; i__4 = f2c_min(i__5,i__6); for (i__ = f2c_max(i__2,i__3); i__ <= i__4; ++i__) { y[i__] += temp * a[k + i__ + j * a_dim1]; /* L50: */ } } jx += *incx; /* L60: */ } } else { i__1 = *n; for (j = 1; j <= i__1; ++j) { if (x[jx] != 0.f) { temp = *alpha * x[jx]; iy = ky; k = kup1 - j; /* Computing MAX */ i__4 = 1, i__2 = j - *ku; /* Computing MIN */ i__5 = *m, i__6 = j + *kl; i__3 = f2c_min(i__5,i__6); for (i__ = f2c_max(i__4,i__2); i__ <= i__3; ++i__) { y[iy] += temp * a[k + i__ + j * a_dim1]; iy += *incy; /* L70: */ } } jx += *incx; if (j > *ku) { ky += *incy; } /* L80: */ } } } else { /* Form y := alpha*A'*x + y. */ jy = ky; if (*incx == 1) { i__1 = *n; for (j = 1; j <= i__1; ++j) { temp = 0.f; k = kup1 - j; /* Computing MAX */ i__3 = 1, i__4 = j - *ku; /* Computing MIN */ i__5 = *m, i__6 = j + *kl; i__2 = f2c_min(i__5,i__6); for (i__ = f2c_max(i__3,i__4); i__ <= i__2; ++i__) { temp += a[k + i__ + j * a_dim1] * x[i__]; /* L90: */ } y[jy] += *alpha * temp; jy += *incy; /* L100: */ } } else { i__1 = *n; for (j = 1; j <= i__1; ++j) { temp = 0.f; ix = kx; k = kup1 - j; /* Computing MAX */ i__2 = 1, i__3 = j - *ku; /* Computing MIN */ i__5 = *m, i__6 = j + *kl; i__4 = f2c_min(i__5,i__6); for (i__ = f2c_max(i__2,i__3); i__ <= i__4; ++i__) { temp += a[k + i__ + j * a_dim1] * x[ix]; ix += *incx; /* L110: */ } y[jy] += *alpha * temp; jy += *incy; if (j > *ku) { kx += *incx; } /* L120: */ } } } return 0; /* End of SGBMV . */ } /* sgbmv_ */ /* zgbmv.f -- translated by f2c (version 19991025). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ /* Subroutine */ int PASTEF77(z,gbmv)(const bla_character *trans, const bla_integer *m, const bla_integer *n, const bla_integer *kl, const bla_integer *ku, const bla_dcomplex *alpha, const bla_dcomplex *a, const bla_integer *lda, const bla_dcomplex *x, const bla_integer *incx, const bla_dcomplex *beta, bla_dcomplex * y, const bla_integer *incy) { /* System generated locals */ bla_integer a_dim1, a_offset, i__1, i__2, i__3, i__4, i__5, i__6; bla_dcomplex z__1, z__2, z__3; /* Builtin functions */ //void bla_d_cnjg(bla_dcomplex *, bla_dcomplex *); /* Local variables */ bla_integer info; bla_dcomplex temp; bla_integer lenx, leny, i__, j, k; //extern bla_logical PASTEF770(lsame)(bla_character *, bla_character *, ftnlen, ftnlen); bla_integer ix, iy, jx, jy, kx, ky; //extern /* Subroutine */ int PASTEF770(xerbla)(bla_character *, bla_integer *, ftnlen); bla_logical noconj; bla_integer kup1; /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* ZGBMV performs one of the matrix-vector operations */ /* y := alpha*A*x + beta*y, or y := alpha*A'*x + beta*y, or */ /* y := alpha*conjg( A' )*x + beta*y, */ /* where alpha and beta are scalars, x and y are vectors and A is an */ /* m by n band matrix, with kl sub-diagonals and ku super-diagonals. */ /* Parameters */ /* ========== */ /* TRANS - CHARACTER*1. */ /* On entry, TRANS specifies the operation to be performed as */ /* follows: */ /* TRANS = 'N' or 'n' y := alpha*A*x + beta*y. */ /* TRANS = 'T' or 't' y := alpha*A'*x + beta*y. */ /* TRANS = 'C' or 'c' y := alpha*conjg( A' )*x + beta*y. */ /* Unchanged on exit. */ /* M - INTEGER. */ /* On entry, M specifies the number of rows of the matrix A. */ /* M must be at least zero. */ /* Unchanged on exit. */ /* N - INTEGER. */ /* On entry, N specifies the number of columns of the matrix A. */ /* N must be at least zero. */ /* Unchanged on exit. */ /* KL - INTEGER. */ /* On entry, KL specifies the number of sub-diagonals of the */ /* matrix A. KL must satisfy 0 .le. KL. */ /* Unchanged on exit. */ /* KU - INTEGER. */ /* On entry, KU specifies the number of super-diagonals of the */ /* matrix A. KU must satisfy 0 .le. KU. */ /* Unchanged on exit. */ /* ALPHA - COMPLEX*16 . */ /* On entry, ALPHA specifies the scalar alpha. */ /* Unchanged on exit. */ /* A - COMPLEX*16 array of DIMENSION ( LDA, n ). */ /* Before entry, the leading ( kl + ku + 1 ) by n part of the */ /* array A must contain the matrix of coefficients, supplied */ /* column by column, with the leading diagonal of the matrix in */ /* row ( ku + 1 ) of the array, the first super-diagonal */ /* starting at position 2 in row ku, the first sub-diagonal */ /* starting at position 1 in row ( ku + 2 ), and so on. */ /* Elements in the array A that do not correspond to elements */ /* in the band matrix (such as the top left ku by ku triangle) */ /* are not referenced. */ /* The following program segment will transfer a band matrix */ /* from conventional full matrix storage to band storage: */ /* DO 20, J = 1, N */ /* K = KU + 1 - J */ /* DO 10, I = MAX( 1, J - KU ), MIN( M, J + KL ) */ /* A( K + I, J ) = matrix( I, J ) */ /* 10 CONTINUE */ /* 20 CONTINUE */ /* Unchanged on exit. */ /* LDA - INTEGER. */ /* On entry, LDA specifies the first dimension of A as declared */ /* in the calling (sub) program. LDA must be at least */ /* ( kl + ku + 1 ). */ /* Unchanged on exit. */ /* X - COMPLEX*16 array of DIMENSION at least */ /* ( 1 + ( n - 1 )*abs( INCX ) ) when TRANS = 'N' or 'n' */ /* and at least */ /* ( 1 + ( m - 1 )*abs( INCX ) ) otherwise. */ /* Before entry, the incremented array X must contain the */ /* vector x. */ /* Unchanged on exit. */ /* INCX - INTEGER. */ /* On entry, INCX specifies the increment for the elements of */ /* X. INCX must not be zero. */ /* Unchanged on exit. */ /* BETA - COMPLEX*16 . */ /* On entry, BETA specifies the scalar beta. When BETA is */ /* supplied as zero then Y need not be set on input. */ /* Unchanged on exit. */ /* Y - COMPLEX*16 array of DIMENSION at least */ /* ( 1 + ( m - 1 )*abs( INCY ) ) when TRANS = 'N' or 'n' */ /* and at least */ /* ( 1 + ( n - 1 )*abs( INCY ) ) otherwise. */ /* Before entry, the incremented array Y must contain the */ /* vector y. On exit, Y is overwritten by the updated vector y. */ /* INCY - INTEGER. */ /* On entry, INCY specifies the increment for the elements of */ /* Y. INCY must not be zero. */ /* Unchanged on exit. */ /* Level 2 Blas routine. */ /* -- Written on 22-October-1986. */ /* Jack Dongarra, Argonne National Lab. */ /* Jeremy Du Croz, Nag Central Office. */ /* Sven Hammarling, Nag Central Office. */ /* Richard Hanson, Sandia National Labs. */ /* .. Parameters .. */ /* .. Local Scalars .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. */ /* .. Executable Statements .. */ /* Test the input parameters. */ /* Parameter adjustments */ a_dim1 = *lda; a_offset = 1 + a_dim1 * 1; a -= a_offset; --x; --y; /* Function Body */ info = 0; if (! PASTEF770(lsame)(trans, "N", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(trans, "T", ( ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(trans, "C", (ftnlen)1, (ftnlen)1) ) { info = 1; } else if (*m < 0) { info = 2; } else if (*n < 0) { info = 3; } else if (*kl < 0) { info = 4; } else if (*ku < 0) { info = 5; } else if (*lda < *kl + *ku + 1) { info = 8; } else if (*incx == 0) { info = 10; } else if (*incy == 0) { info = 13; } if (info != 0) { PASTEF770(xerbla)("ZGBMV ", &info, (ftnlen)6); return 0; } /* Quick return if possible. */ if (*m == 0 || *n == 0 || (bli_zreal(*alpha) == 0. && bli_zimag(*alpha) == 0. && (bli_zreal(*beta) == 1. && bli_zimag(*beta) == 0.))) { return 0; } noconj = PASTEF770(lsame)(trans, "T", (ftnlen)1, (ftnlen)1); /* Set LENX and LENY, the lengths of the vectors x and y, and set */ /* up the start points in X and Y. */ if (PASTEF770(lsame)(trans, "N", (ftnlen)1, (ftnlen)1)) { lenx = *n; leny = *m; } else { lenx = *m; leny = *n; } if (*incx > 0) { kx = 1; } else { kx = 1 - (lenx - 1) * *incx; } if (*incy > 0) { ky = 1; } else { ky = 1 - (leny - 1) * *incy; } /* Start the operations. In this version the elements of A are */ /* accessed sequentially with one pass through the band part of A. */ /* First form y := beta*y. */ if (bli_zreal(*beta) != 1. || bli_zimag(*beta) != 0.) { if (*incy == 1) { if (bli_zreal(*beta) == 0. && bli_zimag(*beta) == 0.) { i__1 = leny; for (i__ = 1; i__ <= i__1; ++i__) { i__2 = i__; bli_zsets( (0.), (0.), y[i__2] ); /* L10: */ } } else { i__1 = leny; for (i__ = 1; i__ <= i__1; ++i__) { i__2 = i__; i__3 = i__; bli_zsets( (bli_zreal(*beta) * bli_zreal(y[i__3]) - bli_zimag(*beta) * bli_zimag(y[i__3])), (bli_zreal(*beta) * bli_zimag(y[i__3]) + bli_zimag(*beta) * bli_zreal(y[i__3])), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), y[i__2] ); /* L20: */ } } } else { iy = ky; if (bli_zreal(*beta) == 0. && bli_zimag(*beta) == 0.) { i__1 = leny; for (i__ = 1; i__ <= i__1; ++i__) { i__2 = iy; bli_zsets( (0.), (0.), y[i__2] ); iy += *incy; /* L30: */ } } else { i__1 = leny; for (i__ = 1; i__ <= i__1; ++i__) { i__2 = iy; i__3 = iy; bli_zsets( (bli_zreal(*beta) * bli_zreal(y[i__3]) - bli_zimag(*beta) * bli_zimag(y[i__3])), (bli_zreal(*beta) * bli_zimag(y[i__3]) + bli_zimag(*beta) * bli_zreal(y[i__3])), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), y[i__2] ); iy += *incy; /* L40: */ } } } } if (bli_zreal(*alpha) == 0. && bli_zimag(*alpha) == 0.) { return 0; } kup1 = *ku + 1; if (PASTEF770(lsame)(trans, "N", (ftnlen)1, (ftnlen)1)) { /* Form y := alpha*A*x + y. */ jx = kx; if (*incy == 1) { i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = jx; if (bli_zreal(x[i__2]) != 0. || bli_zimag(x[i__2]) != 0.) { i__2 = jx; bli_zsets( (bli_zreal(*alpha) * bli_zreal(x[i__2]) - bli_zimag(*alpha) * bli_zimag(x[i__2])), (bli_zreal(*alpha) * bli_zimag(x[i__2]) + bli_zimag(*alpha) * bli_zreal(x[i__2])), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp ); k = kup1 - j; /* Computing MAX */ i__2 = 1, i__3 = j - *ku; /* Computing MIN */ i__5 = *m, i__6 = j + *kl; i__4 = f2c_min(i__5,i__6); for (i__ = f2c_max(i__2,i__3); i__ <= i__4; ++i__) { i__2 = i__; i__3 = i__; i__5 = k + i__ + j * a_dim1; bli_zsets( (bli_zreal(temp) * bli_zreal(a[i__5]) - bli_zimag(temp) * bli_zimag(a[i__5])), (bli_zreal(temp) * bli_zimag(a[i__5]) + bli_zimag(temp) * bli_zreal(a[i__5])), z__2 ); bli_zsets( (bli_zreal(y[i__3]) + bli_zreal(z__2)), (bli_zimag(y[i__3]) + bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), y[i__2] ); /* L50: */ } } jx += *incx; /* L60: */ } } else { i__1 = *n; for (j = 1; j <= i__1; ++j) { i__4 = jx; if (bli_zreal(x[i__4]) != 0. || bli_zimag(x[i__4]) != 0.) { i__4 = jx; bli_zsets( (bli_zreal(*alpha) * bli_zreal(x[i__4]) - bli_zimag(*alpha) * bli_zimag(x[i__4])), (bli_zreal(*alpha) * bli_zimag(x[i__4]) + bli_zimag(*alpha) * bli_zreal(x[i__4])), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp ); iy = ky; k = kup1 - j; /* Computing MAX */ i__4 = 1, i__2 = j - *ku; /* Computing MIN */ i__5 = *m, i__6 = j + *kl; i__3 = f2c_min(i__5,i__6); for (i__ = f2c_max(i__4,i__2); i__ <= i__3; ++i__) { i__4 = iy; i__2 = iy; i__5 = k + i__ + j * a_dim1; bli_zsets( (bli_zreal(temp) * bli_zreal(a[i__5]) - bli_zimag(temp) * bli_zimag(a[i__5])), (bli_zreal(temp) * bli_zimag(a[i__5]) + bli_zimag(temp) * bli_zreal(a[i__5])), z__2 ); bli_zsets( (bli_zreal(y[i__2]) + bli_zreal(z__2)), (bli_zimag(y[i__2]) + bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), y[i__4] ); iy += *incy; /* L70: */ } } jx += *incx; if (j > *ku) { ky += *incy; } /* L80: */ } } } else { /* Form y := alpha*A'*x + y or y := alpha*conjg( A' )*x + y. */ jy = ky; if (*incx == 1) { i__1 = *n; for (j = 1; j <= i__1; ++j) { bli_zsets( (0.), (0.), temp ); k = kup1 - j; if (noconj) { /* Computing MAX */ i__3 = 1, i__4 = j - *ku; /* Computing MIN */ i__5 = *m, i__6 = j + *kl; i__2 = f2c_min(i__5,i__6); for (i__ = f2c_max(i__3,i__4); i__ <= i__2; ++i__) { i__3 = k + i__ + j * a_dim1; i__4 = i__; bli_zsets( (bli_zreal(a[i__3]) * bli_zreal(x[i__4]) - bli_zimag(a[i__3]) * bli_zimag(x[i__4])), (bli_zreal(a[i__3]) * bli_zimag(x[i__4]) + bli_zimag(a[i__3]) * bli_zreal(x[i__4])), z__2 ); bli_zsets( (bli_zreal(temp) + bli_zreal(z__2)), (bli_zimag(temp) + bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp ); /* L90: */ } } else { /* Computing MAX */ i__2 = 1, i__3 = j - *ku; /* Computing MIN */ i__5 = *m, i__6 = j + *kl; i__4 = f2c_min(i__5,i__6); for (i__ = f2c_max(i__2,i__3); i__ <= i__4; ++i__) { bla_d_cnjg(&z__3, &a[k + i__ + j * a_dim1]); i__2 = i__; bli_zsets( (bli_zreal(z__3) * bli_zreal(x[i__2]) - bli_zimag(z__3) * bli_zimag(x[i__2])), (bli_zreal(z__3) * bli_zimag(x[i__2]) + bli_zimag(z__3) * bli_zreal(x[i__2])), z__2 ); bli_zsets( (bli_zreal(temp) + bli_zreal(z__2)), (bli_zimag(temp) + bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp ); /* L100: */ } } i__4 = jy; i__2 = jy; bli_zsets( (bli_zreal(*alpha) * bli_zreal(temp) - bli_zimag(*alpha) * bli_zimag(temp)), (bli_zreal(*alpha) * bli_zimag(temp) + bli_zimag(*alpha) * bli_zreal(temp)), z__2 ); bli_zsets( (bli_zreal(y[i__2]) + bli_zreal(z__2)), (bli_zimag(y[i__2]) + bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), y[i__4] ); jy += *incy; /* L110: */ } } else { i__1 = *n; for (j = 1; j <= i__1; ++j) { bli_zsets( (0.), (0.), temp ); ix = kx; k = kup1 - j; if (noconj) { /* Computing MAX */ i__4 = 1, i__2 = j - *ku; /* Computing MIN */ i__5 = *m, i__6 = j + *kl; i__3 = f2c_min(i__5,i__6); for (i__ = f2c_max(i__4,i__2); i__ <= i__3; ++i__) { i__4 = k + i__ + j * a_dim1; i__2 = ix; bli_zsets( (bli_zreal(a[i__4]) * bli_zreal(x[i__2]) - bli_zimag(a[i__4]) * bli_zimag(x[i__2])), (bli_zreal(a[i__4]) * bli_zimag(x[i__2]) + bli_zimag(a[i__4]) * bli_zreal(x[i__2])), z__2 ); bli_zsets( (bli_zreal(temp) + bli_zreal(z__2)), (bli_zimag(temp) + bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp ); ix += *incx; /* L120: */ } } else { /* Computing MAX */ i__3 = 1, i__4 = j - *ku; /* Computing MIN */ i__5 = *m, i__6 = j + *kl; i__2 = f2c_min(i__5,i__6); for (i__ = f2c_max(i__3,i__4); i__ <= i__2; ++i__) { bla_d_cnjg(&z__3, &a[k + i__ + j * a_dim1]); i__3 = ix; bli_zsets( (bli_zreal(z__3) * bli_zreal(x[i__3]) - bli_zimag(z__3) * bli_zimag(x[i__3])), (bli_zreal(z__3) * bli_zimag(x[i__3]) + bli_zimag(z__3) * bli_zreal(x[i__3])), z__2 ); bli_zsets( (bli_zreal(temp) + bli_zreal(z__2)), (bli_zimag(temp) + bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp ); ix += *incx; /* L130: */ } } i__2 = jy; i__3 = jy; bli_zsets( (bli_zreal(*alpha) * bli_zreal(temp) - bli_zimag(*alpha) * bli_zimag(temp)), (bli_zreal(*alpha) * bli_zimag(temp) + bli_zimag(*alpha) * bli_zreal(temp)), z__2 ); bli_zsets( (bli_zreal(y[i__3]) + bli_zreal(z__2)), (bli_zimag(y[i__3]) + bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), y[i__2] ); jy += *incy; if (j > *ku) { kx += *incx; } /* L140: */ } } } return 0; /* End of ZGBMV . */ } /* zgbmv_ */ #endif blis-0.9.0/frame/compat/f2c/bla_gbmv.h000066400000000000000000000057721422157504600174430ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifdef BLIS_ENABLE_BLAS BLIS_EXPORT_BLAS int PASTEF77(c,gbmv)(const bla_character *trans, const bla_integer *m, const bla_integer *n, const bla_integer *kl, const bla_integer *ku, const bla_scomplex *alpha, const bla_scomplex *a, const bla_integer *lda, const bla_scomplex *x, const bla_integer *incx, const bla_scomplex *beta, bla_scomplex *y, const bla_integer *incy); BLIS_EXPORT_BLAS int PASTEF77(d,gbmv)(const bla_character *trans, const bla_integer *m, const bla_integer *n, const bla_integer *kl, const bla_integer *ku, const bla_double *alpha, const bla_double *a, const bla_integer *lda, const bla_double *x, const bla_integer *incx, const bla_double *beta, bla_double *y, const bla_integer *incy); BLIS_EXPORT_BLAS int PASTEF77(s,gbmv)(const bla_character *trans, const bla_integer *m, const bla_integer *n, const bla_integer *kl, const bla_integer *ku, const bla_real *alpha, const bla_real *a, const bla_integer *lda, const bla_real *x, const bla_integer * incx, const bla_real *beta, bla_real *y, const bla_integer *incy); BLIS_EXPORT_BLAS int PASTEF77(z,gbmv)(const bla_character *trans, const bla_integer *m, const bla_integer *n, const bla_integer *kl, const bla_integer *ku, const bla_dcomplex *alpha, const bla_dcomplex *a, const bla_integer *lda, const bla_dcomplex *x, const bla_integer *incx, const bla_dcomplex *beta, bla_dcomplex * y, const bla_integer *incy); #endif blis-0.9.0/frame/compat/f2c/bla_hbmv.c000066400000000000000000001072731422157504600174360ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #ifdef BLIS_ENABLE_BLAS /* chbmv.f -- translated by f2c (version 19991025). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ /* Subroutine */ int PASTEF77(c,hbmv)(const bla_character *uplo, const bla_integer *n, const bla_integer *k, const bla_scomplex * alpha, const bla_scomplex *a, const bla_integer *lda, const bla_scomplex *x, const bla_integer *incx, const bla_scomplex *beta, bla_scomplex *y, const bla_integer *incy) { /* System generated locals */ bla_integer a_dim1, a_offset, i__1, i__2, i__3, i__4, i__5; bla_real r__1; bla_scomplex q__1, q__2, q__3, q__4; /* Builtin functions */ //void bla_r_cnjg(bla_scomplex *, bla_scomplex *); /* Local variables */ bla_integer info; bla_scomplex temp1, temp2; bla_integer i__, j, l; //extern bla_logical PASTEF770(lsame)(bla_character *, bla_character *, ftnlen, ftnlen); bla_integer kplus1, ix, iy, jx, jy, kx, ky; //extern /* Subroutine */ int PASTEF770(xerbla)(bla_character *, bla_integer *, ftnlen); /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* CHBMV performs the matrix-vector operation */ /* y := alpha*A*x + beta*y, */ /* where alpha and beta are scalars, x and y are n element vectors and */ /* A is an n by n hermitian band matrix, with k super-diagonals. */ /* Parameters */ /* ========== */ /* UPLO - CHARACTER*1. */ /* On entry, UPLO specifies whether the upper or lower */ /* triangular part of the band matrix A is being supplied as */ /* follows: */ /* UPLO = 'U' or 'u' The upper triangular part of A is */ /* being supplied. */ /* UPLO = 'L' or 'l' The lower triangular part of A is */ /* being supplied. */ /* Unchanged on exit. */ /* N - INTEGER. */ /* On entry, N specifies the order of the matrix A. */ /* N must be at least zero. */ /* Unchanged on exit. */ /* K - INTEGER. */ /* On entry, K specifies the number of super-diagonals of the */ /* matrix A. K must satisfy 0 .le. K. */ /* Unchanged on exit. */ /* ALPHA - COMPLEX . */ /* On entry, ALPHA specifies the scalar alpha. */ /* Unchanged on exit. */ /* A - COMPLEX array of DIMENSION ( LDA, n ). */ /* Before entry with UPLO = 'U' or 'u', the leading ( k + 1 ) */ /* by n part of the array A must contain the upper triangular */ /* band part of the hermitian matrix, supplied column by */ /* column, with the leading diagonal of the matrix in row */ /* ( k + 1 ) of the array, the first super-diagonal starting at */ /* position 2 in row k, and so on. The top left k by k triangle */ /* of the array A is not referenced. */ /* The following program segment will transfer the upper */ /* triangular part of a hermitian band matrix from conventional */ /* full matrix storage to band storage: */ /* DO 20, J = 1, N */ /* M = K + 1 - J */ /* DO 10, I = MAX( 1, J - K ), J */ /* A( M + I, J ) = matrix( I, J ) */ /* 10 CONTINUE */ /* 20 CONTINUE */ /* Before entry with UPLO = 'L' or 'l', the leading ( k + 1 ) */ /* by n part of the array A must contain the lower triangular */ /* band part of the hermitian matrix, supplied column by */ /* column, with the leading diagonal of the matrix in row 1 of */ /* the array, the first sub-diagonal starting at position 1 in */ /* row 2, and so on. The bottom right k by k triangle of the */ /* array A is not referenced. */ /* The following program segment will transfer the lower */ /* triangular part of a hermitian band matrix from conventional */ /* full matrix storage to band storage: */ /* DO 20, J = 1, N */ /* M = 1 - J */ /* DO 10, I = J, MIN( N, J + K ) */ /* A( M + I, J ) = matrix( I, J ) */ /* 10 CONTINUE */ /* 20 CONTINUE */ /* Note that the imaginary parts of the diagonal elements need */ /* not be set and are assumed to be zero. */ /* Unchanged on exit. */ /* LDA - INTEGER. */ /* On entry, LDA specifies the first dimension of A as declared */ /* in the calling (sub) program. LDA must be at least */ /* ( k + 1 ). */ /* Unchanged on exit. */ /* X - COMPLEX array of DIMENSION at least */ /* ( 1 + ( n - 1 )*abs( INCX ) ). */ /* Before entry, the incremented array X must contain the */ /* vector x. */ /* Unchanged on exit. */ /* INCX - INTEGER. */ /* On entry, INCX specifies the increment for the elements of */ /* X. INCX must not be zero. */ /* Unchanged on exit. */ /* BETA - COMPLEX . */ /* On entry, BETA specifies the scalar beta. */ /* Unchanged on exit. */ /* Y - COMPLEX array of DIMENSION at least */ /* ( 1 + ( n - 1 )*abs( INCY ) ). */ /* Before entry, the incremented array Y must contain the */ /* vector y. On exit, Y is overwritten by the updated vector y. */ /* INCY - INTEGER. */ /* On entry, INCY specifies the increment for the elements of */ /* Y. INCY must not be zero. */ /* Unchanged on exit. */ /* Level 2 Blas routine. */ /* -- Written on 22-October-1986. */ /* Jack Dongarra, Argonne National Lab. */ /* Jeremy Du Croz, Nag Central Office. */ /* Sven Hammarling, Nag Central Office. */ /* Richard Hanson, Sandia National Labs. */ /* .. Parameters .. */ /* .. Local Scalars .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. */ /* .. Executable Statements .. */ /* Test the input parameters. */ /* Parameter adjustments */ a_dim1 = *lda; a_offset = 1 + a_dim1 * 1; a -= a_offset; --x; --y; /* Function Body */ info = 0; if (! PASTEF770(lsame)(uplo, "U", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(uplo, "L", ( ftnlen)1, (ftnlen)1)) { info = 1; } else if (*n < 0) { info = 2; } else if (*k < 0) { info = 3; } else if (*lda < *k + 1) { info = 6; } else if (*incx == 0) { info = 8; } else if (*incy == 0) { info = 11; } if (info != 0) { PASTEF770(xerbla)("CHBMV ", &info, (ftnlen)6); return 0; } /* Quick return if possible. */ if (*n == 0 || (bli_creal(*alpha) == 0.f && bli_cimag(*alpha) == 0.f && (bli_creal(*beta) == 1.f && bli_cimag(*beta) == 0.f))) { return 0; } /* Set up the start points in X and Y. */ if (*incx > 0) { kx = 1; } else { kx = 1 - (*n - 1) * *incx; } if (*incy > 0) { ky = 1; } else { ky = 1 - (*n - 1) * *incy; } /* Start the operations. In this version the elements of the array A */ /* are accessed sequentially with one pass through A. */ /* First form y := beta*y. */ if (bli_creal(*beta) != 1.f || bli_cimag(*beta) != 0.f) { if (*incy == 1) { if (bli_creal(*beta) == 0.f && bli_cimag(*beta) == 0.f) { i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { i__2 = i__; bli_csets( (0.f), (0.f), y[i__2] ); /* L10: */ } } else { i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { i__2 = i__; i__3 = i__; bli_csets( (bli_creal(*beta) * bli_creal(y[i__3]) - bli_cimag(*beta) * bli_cimag(y[i__3])), (bli_creal(*beta) * bli_cimag(y[i__3]) + bli_cimag(*beta) * bli_creal(y[i__3])), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), y[i__2] ); /* L20: */ } } } else { iy = ky; if (bli_creal(*beta) == 0.f && bli_cimag(*beta) == 0.f) { i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { i__2 = iy; bli_csets( (0.f), (0.f), y[i__2] ); iy += *incy; /* L30: */ } } else { i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { i__2 = iy; i__3 = iy; bli_csets( (bli_creal(*beta) * bli_creal(y[i__3]) - bli_cimag(*beta) * bli_cimag(y[i__3])), (bli_creal(*beta) * bli_cimag(y[i__3]) + bli_cimag(*beta) * bli_creal(y[i__3])), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), y[i__2] ); iy += *incy; /* L40: */ } } } } if (bli_creal(*alpha) == 0.f && bli_cimag(*alpha) == 0.f) { return 0; } if (PASTEF770(lsame)(uplo, "U", (ftnlen)1, (ftnlen)1)) { /* Form y when upper triangle of A is stored. */ kplus1 = *k + 1; if (*incx == 1 && *incy == 1) { i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = j; bli_csets( (bli_creal(*alpha) * bli_creal(x[i__2]) - bli_cimag(*alpha) * bli_cimag(x[i__2])), (bli_creal(*alpha) * bli_cimag(x[i__2]) + bli_cimag(*alpha) * bli_creal(x[i__2])), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp1 ); bli_csets( (0.f), (0.f), temp2 ); l = kplus1 - j; /* Computing MAX */ i__2 = 1, i__3 = j - *k; i__4 = j - 1; for (i__ = f2c_max(i__2,i__3); i__ <= i__4; ++i__) { i__2 = i__; i__3 = i__; i__5 = l + i__ + j * a_dim1; bli_csets( (bli_creal(temp1) * bli_creal(a[i__5]) - bli_cimag(temp1) * bli_cimag(a[i__5])), (bli_creal(temp1) * bli_cimag(a[i__5]) + bli_cimag(temp1) * bli_creal(a[i__5])), q__2 ); bli_csets( (bli_creal(y[i__3]) + bli_creal(q__2)), (bli_cimag(y[i__3]) + bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), y[i__2] ); bla_r_cnjg(&q__3, &a[l + i__ + j * a_dim1]); i__2 = i__; bli_csets( (bli_creal(q__3) * bli_creal(x[i__2]) - bli_cimag(q__3) * bli_cimag(x[i__2])), (bli_creal(q__3) * bli_cimag(x[i__2]) + bli_cimag(q__3) * bli_creal(x[i__2])), q__2 ); bli_csets( (bli_creal(temp2) + bli_creal(q__2)), (bli_cimag(temp2) + bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp2 ); /* L50: */ } i__4 = j; i__2 = j; i__3 = kplus1 + j * a_dim1; r__1 = bli_creal(a[i__3]); bli_csets( (r__1 * bli_creal(temp1)), (r__1 * bli_cimag(temp1)), q__3 ); bli_csets( (bli_creal(y[i__2]) + bli_creal(q__3)), (bli_cimag(y[i__2]) + bli_cimag(q__3)), q__2 ); bli_csets( (bli_creal(*alpha) * bli_creal(temp2) - bli_cimag(*alpha) * bli_cimag(temp2)), (bli_creal(*alpha) * bli_cimag(temp2) + bli_cimag(*alpha) * bli_creal(temp2)), q__4 ); bli_csets( (bli_creal(q__2) + bli_creal(q__4)), (bli_cimag(q__2) + bli_cimag(q__4)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), y[i__4] ); /* L60: */ } } else { jx = kx; jy = ky; i__1 = *n; for (j = 1; j <= i__1; ++j) { i__4 = jx; bli_csets( (bli_creal(*alpha) * bli_creal(x[i__4]) - bli_cimag(*alpha) * bli_cimag(x[i__4])), (bli_creal(*alpha) * bli_cimag(x[i__4]) + bli_cimag(*alpha) * bli_creal(x[i__4])), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp1 ); bli_csets( (0.f), (0.f), temp2 ); ix = kx; iy = ky; l = kplus1 - j; /* Computing MAX */ i__4 = 1, i__2 = j - *k; i__3 = j - 1; for (i__ = f2c_max(i__4,i__2); i__ <= i__3; ++i__) { i__4 = iy; i__2 = iy; i__5 = l + i__ + j * a_dim1; bli_csets( (bli_creal(temp1) * bli_creal(a[i__5]) - bli_cimag(temp1) * bli_cimag(a[i__5])), (bli_creal(temp1) * bli_cimag(a[i__5]) + bli_cimag(temp1) * bli_creal(a[i__5])), q__2 ); bli_csets( (bli_creal(y[i__2]) + bli_creal(q__2)), (bli_cimag(y[i__2]) + bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), y[i__4] ); bla_r_cnjg(&q__3, &a[l + i__ + j * a_dim1]); i__4 = ix; bli_csets( (bli_creal(q__3) * bli_creal(x[i__4]) - bli_cimag(q__3) * bli_cimag(x[i__4])), (bli_creal(q__3) * bli_cimag(x[i__4]) + bli_cimag(q__3) * bli_creal(x[i__4])), q__2 ); bli_csets( (bli_creal(temp2) + bli_creal(q__2)), (bli_cimag(temp2) + bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp2 ); ix += *incx; iy += *incy; /* L70: */ } i__3 = jy; i__4 = jy; i__2 = kplus1 + j * a_dim1; r__1 = bli_creal(a[i__2]); bli_csets( (r__1 * bli_creal(temp1)), (r__1 * bli_cimag(temp1)), q__3 ); bli_csets( (bli_creal(y[i__4]) + bli_creal(q__3)), (bli_cimag(y[i__4]) + bli_cimag(q__3)), q__2 ); bli_csets( (bli_creal(*alpha) * bli_creal(temp2) - bli_cimag(*alpha) * bli_cimag(temp2)), (bli_creal(*alpha) * bli_cimag(temp2) + bli_cimag(*alpha) * bli_creal(temp2)), q__4 ); bli_csets( (bli_creal(q__2) + bli_creal(q__4)), (bli_cimag(q__2) + bli_cimag(q__4)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), y[i__3] ); jx += *incx; jy += *incy; if (j > *k) { kx += *incx; ky += *incy; } /* L80: */ } } } else { /* Form y when lower triangle of A is stored. */ if (*incx == 1 && *incy == 1) { i__1 = *n; for (j = 1; j <= i__1; ++j) { i__3 = j; bli_csets( (bli_creal(*alpha) * bli_creal(x[i__3]) - bli_cimag(*alpha) * bli_cimag(x[i__3])), (bli_creal(*alpha) * bli_cimag(x[i__3]) + bli_cimag(*alpha) * bli_creal(x[i__3])), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp1 ); bli_csets( (0.f), (0.f), temp2 ); i__3 = j; i__4 = j; i__2 = j * a_dim1 + 1; r__1 = bli_creal(a[i__2]); bli_csets( (r__1 * bli_creal(temp1)), (r__1 * bli_cimag(temp1)), q__2 ); bli_csets( (bli_creal(y[i__4]) + bli_creal(q__2)), (bli_cimag(y[i__4]) + bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), y[i__3] ); l = 1 - j; /* Computing MIN */ i__4 = *n, i__2 = j + *k; i__3 = f2c_min(i__4,i__2); for (i__ = j + 1; i__ <= i__3; ++i__) { i__4 = i__; i__2 = i__; i__5 = l + i__ + j * a_dim1; bli_csets( (bli_creal(temp1) * bli_creal(a[i__5]) - bli_cimag(temp1) * bli_cimag(a[i__5])), (bli_creal(temp1) * bli_cimag(a[i__5]) + bli_cimag(temp1) * bli_creal(a[i__5])), q__2 ); bli_csets( (bli_creal(y[i__2]) + bli_creal(q__2)), (bli_cimag(y[i__2]) + bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), y[i__4] ); bla_r_cnjg(&q__3, &a[l + i__ + j * a_dim1]); i__4 = i__; bli_csets( (bli_creal(q__3) * bli_creal(x[i__4]) - bli_cimag(q__3) * bli_cimag(x[i__4])), (bli_creal(q__3) * bli_cimag(x[i__4]) + bli_cimag(q__3) * bli_creal(x[i__4])), q__2 ); bli_csets( (bli_creal(temp2) + bli_creal(q__2)), (bli_cimag(temp2) + bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp2 ); /* L90: */ } i__3 = j; i__4 = j; bli_csets( (bli_creal(*alpha) * bli_creal(temp2) - bli_cimag(*alpha) * bli_cimag(temp2)), (bli_creal(*alpha) * bli_cimag(temp2) + bli_cimag(*alpha) * bli_creal(temp2)), q__2 ); bli_csets( (bli_creal(y[i__4]) + bli_creal(q__2)), (bli_cimag(y[i__4]) + bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), y[i__3] ); /* L100: */ } } else { jx = kx; jy = ky; i__1 = *n; for (j = 1; j <= i__1; ++j) { i__3 = jx; bli_csets( (bli_creal(*alpha) * bli_creal(x[i__3]) - bli_cimag(*alpha) * bli_cimag(x[i__3])), (bli_creal(*alpha) * bli_cimag(x[i__3]) + bli_cimag(*alpha) * bli_creal(x[i__3])), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp1 ); bli_csets( (0.f), (0.f), temp2 ); i__3 = jy; i__4 = jy; i__2 = j * a_dim1 + 1; r__1 = bli_creal(a[i__2]); bli_csets( (r__1 * bli_creal(temp1)), (r__1 * bli_cimag(temp1)), q__2 ); bli_csets( (bli_creal(y[i__4]) + bli_creal(q__2)), (bli_cimag(y[i__4]) + bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), y[i__3] ); l = 1 - j; ix = jx; iy = jy; /* Computing MIN */ i__4 = *n, i__2 = j + *k; i__3 = f2c_min(i__4,i__2); for (i__ = j + 1; i__ <= i__3; ++i__) { ix += *incx; iy += *incy; i__4 = iy; i__2 = iy; i__5 = l + i__ + j * a_dim1; bli_csets( (bli_creal(temp1) * bli_creal(a[i__5]) - bli_cimag(temp1) * bli_cimag(a[i__5])), (bli_creal(temp1) * bli_cimag(a[i__5]) + bli_cimag(temp1) * bli_creal(a[i__5])), q__2 ); bli_csets( (bli_creal(y[i__2]) + bli_creal(q__2)), (bli_cimag(y[i__2]) + bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), y[i__4] ); bla_r_cnjg(&q__3, &a[l + i__ + j * a_dim1]); i__4 = ix; bli_csets( (bli_creal(q__3) * bli_creal(x[i__4]) - bli_cimag(q__3) * bli_cimag(x[i__4])), (bli_creal(q__3) * bli_cimag(x[i__4]) + bli_cimag(q__3) * bli_creal(x[i__4])), q__2 ); bli_csets( (bli_creal(temp2) + bli_creal(q__2)), (bli_cimag(temp2) + bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp2 ); /* L110: */ } i__3 = jy; i__4 = jy; bli_csets( (bli_creal(*alpha) * bli_creal(temp2) - bli_cimag(*alpha) * bli_cimag(temp2)), (bli_creal(*alpha) * bli_cimag(temp2) + bli_cimag(*alpha) * bli_creal(temp2)), q__2 ); bli_csets( (bli_creal(y[i__4]) + bli_creal(q__2)), (bli_cimag(y[i__4]) + bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), y[i__3] ); jx += *incx; jy += *incy; /* L120: */ } } } return 0; /* End of CHBMV . */ } /* chbmv_ */ /* zhbmv.f -- translated by f2c (version 19991025). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ /* Subroutine */ int PASTEF77(z,hbmv)(const bla_character *uplo, const bla_integer *n, const bla_integer *k, const bla_dcomplex *alpha, const bla_dcomplex *a, const bla_integer *lda, const bla_dcomplex *x, const bla_integer * incx, const bla_dcomplex *beta, bla_dcomplex *y, const bla_integer *incy) { /* System generated locals */ bla_integer a_dim1, a_offset, i__1, i__2, i__3, i__4, i__5; bla_double d__1; bla_dcomplex z__1, z__2, z__3, z__4; /* Builtin functions */ //void bla_d_cnjg(bla_dcomplex *, bla_dcomplex *); /* Local variables */ bla_integer info; bla_dcomplex temp1, temp2; bla_integer i__, j, l; //extern bla_logical PASTEF770(lsame)(bla_character *, bla_character *, ftnlen, ftnlen); bla_integer kplus1, ix, iy, jx, jy, kx, ky; //extern /* Subroutine */ int PASTEF770(xerbla)(bla_character *, bla_integer *, ftnlen); /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* ZHBMV performs the matrix-vector operation */ /* y := alpha*A*x + beta*y, */ /* where alpha and beta are scalars, x and y are n element vectors and */ /* A is an n by n hermitian band matrix, with k super-diagonals. */ /* Parameters */ /* ========== */ /* UPLO - CHARACTER*1. */ /* On entry, UPLO specifies whether the upper or lower */ /* triangular part of the band matrix A is being supplied as */ /* follows: */ /* UPLO = 'U' or 'u' The upper triangular part of A is */ /* being supplied. */ /* UPLO = 'L' or 'l' The lower triangular part of A is */ /* being supplied. */ /* Unchanged on exit. */ /* N - INTEGER. */ /* On entry, N specifies the order of the matrix A. */ /* N must be at least zero. */ /* Unchanged on exit. */ /* K - INTEGER. */ /* On entry, K specifies the number of super-diagonals of the */ /* matrix A. K must satisfy 0 .le. K. */ /* Unchanged on exit. */ /* ALPHA - COMPLEX*16 . */ /* On entry, ALPHA specifies the scalar alpha. */ /* Unchanged on exit. */ /* A - COMPLEX*16 array of DIMENSION ( LDA, n ). */ /* Before entry with UPLO = 'U' or 'u', the leading ( k + 1 ) */ /* by n part of the array A must contain the upper triangular */ /* band part of the hermitian matrix, supplied column by */ /* column, with the leading diagonal of the matrix in row */ /* ( k + 1 ) of the array, the first super-diagonal starting at */ /* position 2 in row k, and so on. The top left k by k triangle */ /* of the array A is not referenced. */ /* The following program segment will transfer the upper */ /* triangular part of a hermitian band matrix from conventional */ /* full matrix storage to band storage: */ /* DO 20, J = 1, N */ /* M = K + 1 - J */ /* DO 10, I = MAX( 1, J - K ), J */ /* A( M + I, J ) = matrix( I, J ) */ /* 10 CONTINUE */ /* 20 CONTINUE */ /* Before entry with UPLO = 'L' or 'l', the leading ( k + 1 ) */ /* by n part of the array A must contain the lower triangular */ /* band part of the hermitian matrix, supplied column by */ /* column, with the leading diagonal of the matrix in row 1 of */ /* the array, the first sub-diagonal starting at position 1 in */ /* row 2, and so on. The bottom right k by k triangle of the */ /* array A is not referenced. */ /* The following program segment will transfer the lower */ /* triangular part of a hermitian band matrix from conventional */ /* full matrix storage to band storage: */ /* DO 20, J = 1, N */ /* M = 1 - J */ /* DO 10, I = J, MIN( N, J + K ) */ /* A( M + I, J ) = matrix( I, J ) */ /* 10 CONTINUE */ /* 20 CONTINUE */ /* Note that the imaginary parts of the diagonal elements need */ /* not be set and are assumed to be zero. */ /* Unchanged on exit. */ /* LDA - INTEGER. */ /* On entry, LDA specifies the first dimension of A as declared */ /* in the calling (sub) program. LDA must be at least */ /* ( k + 1 ). */ /* Unchanged on exit. */ /* X - COMPLEX*16 array of DIMENSION at least */ /* ( 1 + ( n - 1 )*abs( INCX ) ). */ /* Before entry, the incremented array X must contain the */ /* vector x. */ /* Unchanged on exit. */ /* INCX - INTEGER. */ /* On entry, INCX specifies the increment for the elements of */ /* X. INCX must not be zero. */ /* Unchanged on exit. */ /* BETA - COMPLEX*16 . */ /* On entry, BETA specifies the scalar beta. */ /* Unchanged on exit. */ /* Y - COMPLEX*16 array of DIMENSION at least */ /* ( 1 + ( n - 1 )*abs( INCY ) ). */ /* Before entry, the incremented array Y must contain the */ /* vector y. On exit, Y is overwritten by the updated vector y. */ /* INCY - INTEGER. */ /* On entry, INCY specifies the increment for the elements of */ /* Y. INCY must not be zero. */ /* Unchanged on exit. */ /* Level 2 Blas routine. */ /* -- Written on 22-October-1986. */ /* Jack Dongarra, Argonne National Lab. */ /* Jeremy Du Croz, Nag Central Office. */ /* Sven Hammarling, Nag Central Office. */ /* Richard Hanson, Sandia National Labs. */ /* .. Parameters .. */ /* .. Local Scalars .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. */ /* .. Executable Statements .. */ /* Test the input parameters. */ /* Parameter adjustments */ a_dim1 = *lda; a_offset = 1 + a_dim1 * 1; a -= a_offset; --x; --y; /* Function Body */ info = 0; if (! PASTEF770(lsame)(uplo, "U", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(uplo, "L", ( ftnlen)1, (ftnlen)1)) { info = 1; } else if (*n < 0) { info = 2; } else if (*k < 0) { info = 3; } else if (*lda < *k + 1) { info = 6; } else if (*incx == 0) { info = 8; } else if (*incy == 0) { info = 11; } if (info != 0) { PASTEF770(xerbla)("ZHBMV ", &info, (ftnlen)6); return 0; } /* Quick return if possible. */ if (*n == 0 || (bli_zreal(*alpha) == 0. && bli_zimag(*alpha) == 0. && (bli_zreal(*beta) == 1. && bli_zimag(*beta) == 0.))) { return 0; } /* Set up the start points in X and Y. */ if (*incx > 0) { kx = 1; } else { kx = 1 - (*n - 1) * *incx; } if (*incy > 0) { ky = 1; } else { ky = 1 - (*n - 1) * *incy; } /* Start the operations. In this version the elements of the array A */ /* are accessed sequentially with one pass through A. */ /* First form y := beta*y. */ if (bli_zreal(*beta) != 1. || bli_zimag(*beta) != 0.) { if (*incy == 1) { if (bli_zreal(*beta) == 0. && bli_zimag(*beta) == 0.) { i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { i__2 = i__; bli_zsets( (0.), (0.), y[i__2] ); /* L10: */ } } else { i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { i__2 = i__; i__3 = i__; bli_zsets( (bli_zreal(*beta) * bli_zreal(y[i__3]) - bli_zimag(*beta) * bli_zimag(y[i__3])), (bli_zreal(*beta) * bli_zimag(y[i__3]) + bli_zimag(*beta) * bli_zreal(y[i__3])), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), y[i__2] ); /* L20: */ } } } else { iy = ky; if (bli_zreal(*beta) == 0. && bli_zimag(*beta) == 0.) { i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { i__2 = iy; bli_zsets( (0.), (0.), y[i__2] ); iy += *incy; /* L30: */ } } else { i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { i__2 = iy; i__3 = iy; bli_zsets( (bli_zreal(*beta) * bli_zreal(y[i__3]) - bli_zimag(*beta) * bli_zimag(y[i__3])), (bli_zreal(*beta) * bli_zimag(y[i__3]) + bli_zimag(*beta) * bli_zreal(y[i__3])), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), y[i__2] ); iy += *incy; /* L40: */ } } } } if (bli_zreal(*alpha) == 0. && bli_zimag(*alpha) == 0.) { return 0; } if (PASTEF770(lsame)(uplo, "U", (ftnlen)1, (ftnlen)1)) { /* Form y when upper triangle of A is stored. */ kplus1 = *k + 1; if (*incx == 1 && *incy == 1) { i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = j; bli_zsets( (bli_zreal(*alpha) * bli_zreal(x[i__2]) - bli_zimag(*alpha) * bli_zimag(x[i__2])), (bli_zreal(*alpha) * bli_zimag(x[i__2]) + bli_zimag(*alpha) * bli_zreal(x[i__2])), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp1 ); bli_zsets( (0.), (0.), temp2 ); l = kplus1 - j; /* Computing MAX */ i__2 = 1, i__3 = j - *k; i__4 = j - 1; for (i__ = f2c_max(i__2,i__3); i__ <= i__4; ++i__) { i__2 = i__; i__3 = i__; i__5 = l + i__ + j * a_dim1; bli_zsets( (bli_zreal(temp1) * bli_zreal(a[i__5]) - bli_zimag(temp1) * bli_zimag(a[i__5])), (bli_zreal(temp1) * bli_zimag(a[i__5]) + bli_zimag(temp1) * bli_zreal(a[i__5])), z__2 ); bli_zsets( (bli_zreal(y[i__3]) + bli_zreal(z__2)), (bli_zimag(y[i__3]) + bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), y[i__2] ); bla_d_cnjg(&z__3, &a[l + i__ + j * a_dim1]); i__2 = i__; bli_zsets( (bli_zreal(z__3) * bli_zreal(x[i__2]) - bli_zimag(z__3) * bli_zimag(x[i__2])), (bli_zreal(z__3) * bli_zimag(x[i__2]) + bli_zimag(z__3) * bli_zreal(x[i__2])), z__2 ); bli_zsets( (bli_zreal(temp2) + bli_zreal(z__2)), (bli_zimag(temp2) + bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp2 ); /* L50: */ } i__4 = j; i__2 = j; i__3 = kplus1 + j * a_dim1; d__1 = bli_zreal(a[i__3]); bli_zsets( (d__1 * bli_zreal(temp1)), (d__1 * bli_zimag(temp1)), z__3 ); bli_zsets( (bli_zreal(y[i__2]) + bli_zreal(z__3)), (bli_zimag(y[i__2]) + bli_zimag(z__3)), z__2 ); bli_zsets( (bli_zreal(*alpha) * bli_zreal(temp2) - bli_zimag(*alpha) * bli_zimag(temp2)), (bli_zreal(*alpha) * bli_zimag(temp2) + bli_zimag(*alpha) * bli_zreal(temp2)), z__4 ); bli_zsets( (bli_zreal(z__2) + bli_zreal(z__4)), (bli_zimag(z__2) + bli_zimag(z__4)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), y[i__4] ); /* L60: */ } } else { jx = kx; jy = ky; i__1 = *n; for (j = 1; j <= i__1; ++j) { i__4 = jx; bli_zsets( (bli_zreal(*alpha) * bli_zreal(x[i__4]) - bli_zimag(*alpha) * bli_zimag(x[i__4])), (bli_zreal(*alpha) * bli_zimag(x[i__4]) + bli_zimag(*alpha) * bli_zreal(x[i__4])), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp1 ); bli_zsets( (0.), (0.), temp2 ); ix = kx; iy = ky; l = kplus1 - j; /* Computing MAX */ i__4 = 1, i__2 = j - *k; i__3 = j - 1; for (i__ = f2c_max(i__4,i__2); i__ <= i__3; ++i__) { i__4 = iy; i__2 = iy; i__5 = l + i__ + j * a_dim1; bli_zsets( (bli_zreal(temp1) * bli_zreal(a[i__5]) - bli_zimag(temp1) * bli_zimag(a[i__5])), (bli_zreal(temp1) * bli_zimag(a[i__5]) + bli_zimag(temp1) * bli_zreal(a[i__5])), z__2 ); bli_zsets( (bli_zreal(y[i__2]) + bli_zreal(z__2)), (bli_zimag(y[i__2]) + bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), y[i__4] ); bla_d_cnjg(&z__3, &a[l + i__ + j * a_dim1]); i__4 = ix; bli_zsets( (bli_zreal(z__3) * bli_zreal(x[i__4]) - bli_zimag(z__3) * bli_zimag(x[i__4])), (bli_zreal(z__3) * bli_zimag(x[i__4]) + bli_zimag(z__3) * bli_zreal(x[i__4])), z__2 ); bli_zsets( (bli_zreal(temp2) + bli_zreal(z__2)), (bli_zimag(temp2) + bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp2 ); ix += *incx; iy += *incy; /* L70: */ } i__3 = jy; i__4 = jy; i__2 = kplus1 + j * a_dim1; d__1 = bli_zreal(a[i__2]); bli_zsets( (d__1 * bli_zreal(temp1)), (d__1 * bli_zimag(temp1)), z__3 ); bli_zsets( (bli_zreal(y[i__4]) + bli_zreal(z__3)), (bli_zimag(y[i__4]) + bli_zimag(z__3)), z__2 ); bli_zsets( (bli_zreal(*alpha) * bli_zreal(temp2) - bli_zimag(*alpha) * bli_zimag(temp2)), (bli_zreal(*alpha) * bli_zimag(temp2) + bli_zimag(*alpha) * bli_zreal(temp2)), z__4 ); bli_zsets( (bli_zreal(z__2) + bli_zreal(z__4)), (bli_zimag(z__2) + bli_zimag(z__4)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), y[i__3] ); jx += *incx; jy += *incy; if (j > *k) { kx += *incx; ky += *incy; } /* L80: */ } } } else { /* Form y when lower triangle of A is stored. */ if (*incx == 1 && *incy == 1) { i__1 = *n; for (j = 1; j <= i__1; ++j) { i__3 = j; bli_zsets( (bli_zreal(*alpha) * bli_zreal(x[i__3]) - bli_zimag(*alpha) * bli_zimag(x[i__3])), (bli_zreal(*alpha) * bli_zimag(x[i__3]) + bli_zimag(*alpha) * bli_zreal(x[i__3])), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp1 ); bli_zsets( (0.), (0.), temp2 ); i__3 = j; i__4 = j; i__2 = j * a_dim1 + 1; d__1 = bli_zreal(a[i__2]); bli_zsets( (d__1 * bli_zreal(temp1)), (d__1 * bli_zimag(temp1)), z__2 ); bli_zsets( (bli_zreal(y[i__4]) + bli_zreal(z__2)), (bli_zimag(y[i__4]) + bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), y[i__3] ); l = 1 - j; /* Computing MIN */ i__4 = *n, i__2 = j + *k; i__3 = f2c_min(i__4,i__2); for (i__ = j + 1; i__ <= i__3; ++i__) { i__4 = i__; i__2 = i__; i__5 = l + i__ + j * a_dim1; bli_zsets( (bli_zreal(temp1) * bli_zreal(a[i__5]) - bli_zimag(temp1) * bli_zimag(a[i__5])), (bli_zreal(temp1) * bli_zimag(a[i__5]) + bli_zimag(temp1) * bli_zreal(a[i__5])), z__2 ); bli_zsets( (bli_zreal(y[i__2]) + bli_zreal(z__2)), (bli_zimag(y[i__2]) + bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), y[i__4] ); bla_d_cnjg(&z__3, &a[l + i__ + j * a_dim1]); i__4 = i__; bli_zsets( (bli_zreal(z__3) * bli_zreal(x[i__4]) - bli_zimag(z__3) * bli_zimag(x[i__4])), (bli_zreal(z__3) * bli_zimag(x[i__4]) + bli_zimag(z__3) * bli_zreal(x[i__4])), z__2 ); bli_zsets( (bli_zreal(temp2) + bli_zreal(z__2)), (bli_zimag(temp2) + bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp2 ); /* L90: */ } i__3 = j; i__4 = j; bli_zsets( (bli_zreal(*alpha) * bli_zreal(temp2) - bli_zimag(*alpha) * bli_zimag(temp2)), (bli_zreal(*alpha) * bli_zimag(temp2) + bli_zimag(*alpha) * bli_zreal(temp2)), z__2 ); bli_zsets( (bli_zreal(y[i__4]) + bli_zreal(z__2)), (bli_zimag(y[i__4]) + bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), y[i__3] ); /* L100: */ } } else { jx = kx; jy = ky; i__1 = *n; for (j = 1; j <= i__1; ++j) { i__3 = jx; bli_zsets( (bli_zreal(*alpha) * bli_zreal(x[i__3]) - bli_zimag(*alpha) * bli_zimag(x[i__3])), (bli_zreal(*alpha) * bli_zimag(x[i__3]) + bli_zimag(*alpha) * bli_zreal(x[i__3])), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp1 ); bli_zsets( (0.), (0.), temp2 ); i__3 = jy; i__4 = jy; i__2 = j * a_dim1 + 1; d__1 = bli_zreal(a[i__2]); bli_zsets( (d__1 * bli_zreal(temp1)), (d__1 * bli_zimag(temp1)), z__2 ); bli_zsets( (bli_zreal(y[i__4]) + bli_zreal(z__2)), (bli_zimag(y[i__4]) + bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), y[i__3] ); l = 1 - j; ix = jx; iy = jy; /* Computing MIN */ i__4 = *n, i__2 = j + *k; i__3 = f2c_min(i__4,i__2); for (i__ = j + 1; i__ <= i__3; ++i__) { ix += *incx; iy += *incy; i__4 = iy; i__2 = iy; i__5 = l + i__ + j * a_dim1; bli_zsets( (bli_zreal(temp1) * bli_zreal(a[i__5]) - bli_zimag(temp1) * bli_zimag(a[i__5])), (bli_zreal(temp1) * bli_zimag(a[i__5]) + bli_zimag(temp1) * bli_zreal(a[i__5])), z__2 ); bli_zsets( (bli_zreal(y[i__2]) + bli_zreal(z__2)), (bli_zimag(y[i__2]) + bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), y[i__4] ); bla_d_cnjg(&z__3, &a[l + i__ + j * a_dim1]); i__4 = ix; bli_zsets( (bli_zreal(z__3) * bli_zreal(x[i__4]) - bli_zimag(z__3) * bli_zimag(x[i__4])), (bli_zreal(z__3) * bli_zimag(x[i__4]) + bli_zimag(z__3) * bli_zreal(x[i__4])), z__2 ); bli_zsets( (bli_zreal(temp2) + bli_zreal(z__2)), (bli_zimag(temp2) + bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp2 ); /* L110: */ } i__3 = jy; i__4 = jy; bli_zsets( (bli_zreal(*alpha) * bli_zreal(temp2) - bli_zimag(*alpha) * bli_zimag(temp2)), (bli_zreal(*alpha) * bli_zimag(temp2) + bli_zimag(*alpha) * bli_zreal(temp2)), z__2 ); bli_zsets( (bli_zreal(y[i__4]) + bli_zreal(z__2)), (bli_zimag(y[i__4]) + bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), y[i__3] ); jx += *incx; jy += *incy; /* L120: */ } } } return 0; /* End of ZHBMV . */ } /* zhbmv_ */ #endif blis-0.9.0/frame/compat/f2c/bla_hbmv.h000066400000000000000000000044021422157504600174310ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifdef BLIS_ENABLE_BLAS BLIS_EXPORT_BLAS int PASTEF77(c,hbmv)(const bla_character *uplo, const bla_integer *n, const bla_integer *k, const bla_scomplex *alpha, const bla_scomplex *a, const bla_integer *lda, const bla_scomplex *x, const bla_integer *incx, const bla_scomplex *beta, bla_scomplex *y, const bla_integer *incy); BLIS_EXPORT_BLAS int PASTEF77(z,hbmv)(const bla_character *uplo, const bla_integer *n, const bla_integer *k, const bla_dcomplex *alpha, const bla_dcomplex *a, const bla_integer *lda, const bla_dcomplex *x, const bla_integer *incx, const bla_dcomplex *beta, bla_dcomplex *y, const bla_integer *incy); #endif blis-0.9.0/frame/compat/f2c/bla_hpmv.c000066400000000000000000000770761422157504600174630ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #ifdef BLIS_ENABLE_BLAS /* chpmv.f -- translated by f2c (version 19991025). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ /* Subroutine */ int PASTEF77(c,hpmv)(const bla_character *uplo, const bla_integer *n, const bla_scomplex *alpha, const bla_scomplex * ap, const bla_scomplex *x, const bla_integer *incx, const bla_scomplex *beta, bla_scomplex *y, const bla_integer *incy) { /* System generated locals */ bla_integer i__1, i__2, i__3, i__4, i__5; bla_real r__1; bla_scomplex q__1, q__2, q__3, q__4; /* Builtin functions */ //void bla_r_cnjg(bla_scomplex *, bla_scomplex *); /* Local variables */ bla_integer info; bla_scomplex temp1, temp2; bla_integer i__, j, k; //extern bla_logical PASTEF770(lsame)(bla_character *, bla_character *, ftnlen, ftnlen); bla_integer kk, ix, iy, jx, jy, kx, ky; //extern /* Subroutine */ int PASTEF770(xerbla)(bla_character *, bla_integer *, ftnlen); /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* CHPMV performs the matrix-vector operation */ /* y := alpha*A*x + beta*y, */ /* where alpha and beta are scalars, x and y are n element vectors and */ /* A is an n by n hermitian matrix, supplied in packed form. */ /* Parameters */ /* ========== */ /* UPLO - CHARACTER*1. */ /* On entry, UPLO specifies whether the upper or lower */ /* triangular part of the matrix A is supplied in the packed */ /* array AP as follows: */ /* UPLO = 'U' or 'u' The upper triangular part of A is */ /* supplied in AP. */ /* UPLO = 'L' or 'l' The lower triangular part of A is */ /* supplied in AP. */ /* Unchanged on exit. */ /* N - INTEGER. */ /* On entry, N specifies the order of the matrix A. */ /* N must be at least zero. */ /* Unchanged on exit. */ /* ALPHA - COMPLEX . */ /* On entry, ALPHA specifies the scalar alpha. */ /* Unchanged on exit. */ /* AP - COMPLEX array of DIMENSION at least */ /* ( ( n*( n + 1 ) )/2 ). */ /* Before entry with UPLO = 'U' or 'u', the array AP must */ /* contain the upper triangular part of the hermitian matrix */ /* packed sequentially, column by column, so that AP( 1 ) */ /* contains a( 1, 1 ), AP( 2 ) and AP( 3 ) contain a( 1, 2 ) */ /* and a( 2, 2 ) respectively, and so on. */ /* Before entry with UPLO = 'L' or 'l', the array AP must */ /* contain the lower triangular part of the hermitian matrix */ /* packed sequentially, column by column, so that AP( 1 ) */ /* contains a( 1, 1 ), AP( 2 ) and AP( 3 ) contain a( 2, 1 ) */ /* and a( 3, 1 ) respectively, and so on. */ /* Note that the imaginary parts of the diagonal elements need */ /* not be set and are assumed to be zero. */ /* Unchanged on exit. */ /* X - COMPLEX array of dimension at least */ /* ( 1 + ( n - 1 )*abs( INCX ) ). */ /* Before entry, the incremented array X must contain the n */ /* element vector x. */ /* Unchanged on exit. */ /* INCX - INTEGER. */ /* On entry, INCX specifies the increment for the elements of */ /* X. INCX must not be zero. */ /* Unchanged on exit. */ /* BETA - COMPLEX . */ /* On entry, BETA specifies the scalar beta. When BETA is */ /* supplied as zero then Y need not be set on input. */ /* Unchanged on exit. */ /* Y - COMPLEX array of dimension at least */ /* ( 1 + ( n - 1 )*abs( INCY ) ). */ /* Before entry, the incremented array Y must contain the n */ /* element vector y. On exit, Y is overwritten by the updated */ /* vector y. */ /* INCY - INTEGER. */ /* On entry, INCY specifies the increment for the elements of */ /* Y. INCY must not be zero. */ /* Unchanged on exit. */ /* Level 2 Blas routine. */ /* -- Written on 22-October-1986. */ /* Jack Dongarra, Argonne National Lab. */ /* Jeremy Du Croz, Nag Central Office. */ /* Sven Hammarling, Nag Central Office. */ /* Richard Hanson, Sandia National Labs. */ /* .. Parameters .. */ /* .. Local Scalars .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. */ /* .. Executable Statements .. */ /* Test the input parameters. */ /* Parameter adjustments */ --y; --x; --ap; /* Function Body */ info = 0; if (! PASTEF770(lsame)(uplo, "U", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(uplo, "L", ( ftnlen)1, (ftnlen)1)) { info = 1; } else if (*n < 0) { info = 2; } else if (*incx == 0) { info = 6; } else if (*incy == 0) { info = 9; } if (info != 0) { PASTEF770(xerbla)("CHPMV ", &info, (ftnlen)6); return 0; } /* Quick return if possible. */ if (*n == 0 || (bli_creal(*alpha) == 0.f && bli_cimag(*alpha) == 0.f && (bli_creal(*beta) == 1.f && bli_cimag(*beta) == 0.f))) { return 0; } /* Set up the start points in X and Y. */ if (*incx > 0) { kx = 1; } else { kx = 1 - (*n - 1) * *incx; } if (*incy > 0) { ky = 1; } else { ky = 1 - (*n - 1) * *incy; } /* Start the operations. In this version the elements of the array AP */ /* are accessed sequentially with one pass through AP. */ /* First form y := beta*y. */ if (bli_creal(*beta) != 1.f || bli_cimag(*beta) != 0.f) { if (*incy == 1) { if (bli_creal(*beta) == 0.f && bli_cimag(*beta) == 0.f) { i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { i__2 = i__; bli_csets( (0.f), (0.f), y[i__2] ); /* L10: */ } } else { i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { i__2 = i__; i__3 = i__; bli_csets( (bli_creal(*beta) * bli_creal(y[i__3]) - bli_cimag(*beta) * bli_cimag(y[i__3])), (bli_creal(*beta) * bli_cimag(y[i__3]) + bli_cimag(*beta) * bli_creal(y[i__3])), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), y[i__2] ); /* L20: */ } } } else { iy = ky; if (bli_creal(*beta) == 0.f && bli_cimag(*beta) == 0.f) { i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { i__2 = iy; bli_csets( (0.f), (0.f), y[i__2] ); iy += *incy; /* L30: */ } } else { i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { i__2 = iy; i__3 = iy; bli_csets( (bli_creal(*beta) * bli_creal(y[i__3]) - bli_cimag(*beta) * bli_cimag(y[i__3])), (bli_creal(*beta) * bli_cimag(y[i__3]) + bli_cimag(*beta) * bli_creal(y[i__3])), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), y[i__2] ); iy += *incy; /* L40: */ } } } } if (bli_creal(*alpha) == 0.f && bli_cimag(*alpha) == 0.f) { return 0; } kk = 1; if (PASTEF770(lsame)(uplo, "U", (ftnlen)1, (ftnlen)1)) { /* Form y when AP contains the upper triangle. */ if (*incx == 1 && *incy == 1) { i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = j; bli_csets( (bli_creal(*alpha) * bli_creal(x[i__2]) - bli_cimag(*alpha) * bli_cimag(x[i__2])), (bli_creal(*alpha) * bli_cimag(x[i__2]) + bli_cimag(*alpha) * bli_creal(x[i__2])), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp1 ); bli_csets( (0.f), (0.f), temp2 ); k = kk; i__2 = j - 1; for (i__ = 1; i__ <= i__2; ++i__) { i__3 = i__; i__4 = i__; i__5 = k; bli_csets( (bli_creal(temp1) * bli_creal(ap[i__5]) - bli_cimag(temp1) * bli_cimag(ap[i__5])), (bli_creal(temp1) * bli_cimag(ap[i__5]) + bli_cimag(temp1) * bli_creal(ap[i__5])), q__2 ); bli_csets( (bli_creal(y[i__4]) + bli_creal(q__2)), (bli_cimag(y[i__4]) + bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), y[i__3] ); bla_r_cnjg(&q__3, &ap[k]); i__3 = i__; bli_csets( (bli_creal(q__3) * bli_creal(x[i__3]) - bli_cimag(q__3) * bli_cimag(x[i__3])), (bli_creal(q__3) * bli_cimag(x[i__3]) + bli_cimag(q__3) * bli_creal(x[i__3])), q__2 ); bli_csets( (bli_creal(temp2) + bli_creal(q__2)), (bli_cimag(temp2) + bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp2 ); ++k; /* L50: */ } i__2 = j; i__3 = j; i__4 = kk + j - 1; r__1 = bli_creal(ap[i__4]); bli_csets( (r__1 * bli_creal(temp1)), (r__1 * bli_cimag(temp1)), q__3 ); bli_csets( (bli_creal(y[i__3]) + bli_creal(q__3)), (bli_cimag(y[i__3]) + bli_cimag(q__3)), q__2 ); bli_csets( (bli_creal(*alpha) * bli_creal(temp2) - bli_cimag(*alpha) * bli_cimag(temp2)), (bli_creal(*alpha) * bli_cimag(temp2) + bli_cimag(*alpha) * bli_creal(temp2)), q__4 ); bli_csets( (bli_creal(q__2) + bli_creal(q__4)), (bli_cimag(q__2) + bli_cimag(q__4)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), y[i__2] ); kk += j; /* L60: */ } } else { jx = kx; jy = ky; i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = jx; bli_csets( (bli_creal(*alpha) * bli_creal(x[i__2]) - bli_cimag(*alpha) * bli_cimag(x[i__2])), (bli_creal(*alpha) * bli_cimag(x[i__2]) + bli_cimag(*alpha) * bli_creal(x[i__2])), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp1 ); bli_csets( (0.f), (0.f), temp2 ); ix = kx; iy = ky; i__2 = kk + j - 2; for (k = kk; k <= i__2; ++k) { i__3 = iy; i__4 = iy; i__5 = k; bli_csets( (bli_creal(temp1) * bli_creal(ap[i__5]) - bli_cimag(temp1) * bli_cimag(ap[i__5])), (bli_creal(temp1) * bli_cimag(ap[i__5]) + bli_cimag(temp1) * bli_creal(ap[i__5])), q__2 ); bli_csets( (bli_creal(y[i__4]) + bli_creal(q__2)), (bli_cimag(y[i__4]) + bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), y[i__3] ); bla_r_cnjg(&q__3, &ap[k]); i__3 = ix; bli_csets( (bli_creal(q__3) * bli_creal(x[i__3]) - bli_cimag(q__3) * bli_cimag(x[i__3])), (bli_creal(q__3) * bli_cimag(x[i__3]) + bli_cimag(q__3) * bli_creal(x[i__3])), q__2 ); bli_csets( (bli_creal(temp2) + bli_creal(q__2)), (bli_cimag(temp2) + bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp2 ); ix += *incx; iy += *incy; /* L70: */ } i__2 = jy; i__3 = jy; i__4 = kk + j - 1; r__1 = bli_creal(ap[i__4]); bli_csets( (r__1 * bli_creal(temp1)), (r__1 * bli_cimag(temp1)), q__3 ); bli_csets( (bli_creal(y[i__3]) + bli_creal(q__3)), (bli_cimag(y[i__3]) + bli_cimag(q__3)), q__2 ); bli_csets( (bli_creal(*alpha) * bli_creal(temp2) - bli_cimag(*alpha) * bli_cimag(temp2)), (bli_creal(*alpha) * bli_cimag(temp2) + bli_cimag(*alpha) * bli_creal(temp2)), q__4 ); bli_csets( (bli_creal(q__2) + bli_creal(q__4)), (bli_cimag(q__2) + bli_cimag(q__4)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), y[i__2] ); jx += *incx; jy += *incy; kk += j; /* L80: */ } } } else { /* Form y when AP contains the lower triangle. */ if (*incx == 1 && *incy == 1) { i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = j; bli_csets( (bli_creal(*alpha) * bli_creal(x[i__2]) - bli_cimag(*alpha) * bli_cimag(x[i__2])), (bli_creal(*alpha) * bli_cimag(x[i__2]) + bli_cimag(*alpha) * bli_creal(x[i__2])), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp1 ); bli_csets( (0.f), (0.f), temp2 ); i__2 = j; i__3 = j; i__4 = kk; r__1 = bli_creal(ap[i__4]); bli_csets( (r__1 * bli_creal(temp1)), (r__1 * bli_cimag(temp1)), q__2 ); bli_csets( (bli_creal(y[i__3]) + bli_creal(q__2)), (bli_cimag(y[i__3]) + bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), y[i__2] ); k = kk + 1; i__2 = *n; for (i__ = j + 1; i__ <= i__2; ++i__) { i__3 = i__; i__4 = i__; i__5 = k; bli_csets( (bli_creal(temp1) * bli_creal(ap[i__5]) - bli_cimag(temp1) * bli_cimag(ap[i__5])), (bli_creal(temp1) * bli_cimag(ap[i__5]) + bli_cimag(temp1) * bli_creal(ap[i__5])), q__2 ); bli_csets( (bli_creal(y[i__4]) + bli_creal(q__2)), (bli_cimag(y[i__4]) + bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), y[i__3] ); bla_r_cnjg(&q__3, &ap[k]); i__3 = i__; bli_csets( (bli_creal(q__3) * bli_creal(x[i__3]) - bli_cimag(q__3) * bli_cimag(x[i__3])), (bli_creal(q__3) * bli_cimag(x[i__3]) + bli_cimag(q__3) * bli_creal(x[i__3])), q__2 ); bli_csets( (bli_creal(temp2) + bli_creal(q__2)), (bli_cimag(temp2) + bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp2 ); ++k; /* L90: */ } i__2 = j; i__3 = j; bli_csets( (bli_creal(*alpha) * bli_creal(temp2) - bli_cimag(*alpha) * bli_cimag(temp2)), (bli_creal(*alpha) * bli_cimag(temp2) + bli_cimag(*alpha) * bli_creal(temp2)), q__2 ); bli_csets( (bli_creal(y[i__3]) + bli_creal(q__2)), (bli_cimag(y[i__3]) + bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), y[i__2] ); kk += *n - j + 1; /* L100: */ } } else { jx = kx; jy = ky; i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = jx; bli_csets( (bli_creal(*alpha) * bli_creal(x[i__2]) - bli_cimag(*alpha) * bli_cimag(x[i__2])), (bli_creal(*alpha) * bli_cimag(x[i__2]) + bli_cimag(*alpha) * bli_creal(x[i__2])), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp1 ); bli_csets( (0.f), (0.f), temp2 ); i__2 = jy; i__3 = jy; i__4 = kk; r__1 = bli_creal(ap[i__4]); bli_csets( (r__1 * bli_creal(temp1)), (r__1 * bli_cimag(temp1)), q__2 ); bli_csets( (bli_creal(y[i__3]) + bli_creal(q__2)), (bli_cimag(y[i__3]) + bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), y[i__2] ); ix = jx; iy = jy; i__2 = kk + *n - j; for (k = kk + 1; k <= i__2; ++k) { ix += *incx; iy += *incy; i__3 = iy; i__4 = iy; i__5 = k; bli_csets( (bli_creal(temp1) * bli_creal(ap[i__5]) - bli_cimag(temp1) * bli_cimag(ap[i__5])), (bli_creal(temp1) * bli_cimag(ap[i__5]) + bli_cimag(temp1) * bli_creal(ap[i__5])), q__2 ); bli_csets( (bli_creal(y[i__4]) + bli_creal(q__2)), (bli_cimag(y[i__4]) + bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), y[i__3] ); bla_r_cnjg(&q__3, &ap[k]); i__3 = ix; bli_csets( (bli_creal(q__3) * bli_creal(x[i__3]) - bli_cimag(q__3) * bli_cimag(x[i__3])), (bli_creal(q__3) * bli_cimag(x[i__3]) + bli_cimag(q__3) * bli_creal(x[i__3])), q__2 ); bli_csets( (bli_creal(temp2) + bli_creal(q__2)), (bli_cimag(temp2) + bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp2 ); /* L110: */ } i__2 = jy; i__3 = jy; bli_csets( (bli_creal(*alpha) * bli_creal(temp2) - bli_cimag(*alpha) * bli_cimag(temp2)), (bli_creal(*alpha) * bli_cimag(temp2) + bli_cimag(*alpha) * bli_creal(temp2)), q__2 ); bli_csets( (bli_creal(y[i__3]) + bli_creal(q__2)), (bli_cimag(y[i__3]) + bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), y[i__2] ); jx += *incx; jy += *incy; kk += *n - j + 1; /* L120: */ } } } return 0; /* End of CHPMV . */ } /* chpmv_ */ /* zhpmv.f -- translated by f2c (version 19991025). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ /* Subroutine */ int PASTEF77(z,hpmv)(const bla_character *uplo, const bla_integer *n, const bla_dcomplex *alpha, const bla_dcomplex *ap, const bla_dcomplex *x, const bla_integer *incx, const bla_dcomplex *beta, bla_dcomplex *y, const bla_integer *incy) { /* System generated locals */ bla_integer i__1, i__2, i__3, i__4, i__5; bla_double d__1; bla_dcomplex z__1, z__2, z__3, z__4; /* Builtin functions */ //void bla_d_cnjg(bla_dcomplex *, bla_dcomplex *); /* Local variables */ bla_integer info; bla_dcomplex temp1, temp2; bla_integer i__, j, k; //extern bla_logical PASTEF770(lsame)(bla_character *, bla_character *, ftnlen, ftnlen); bla_integer kk, ix, iy, jx, jy, kx, ky; //extern /* Subroutine */ int PASTEF770(xerbla)(bla_character *, bla_integer *, ftnlen); /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* ZHPMV performs the matrix-vector operation */ /* y := alpha*A*x + beta*y, */ /* where alpha and beta are scalars, x and y are n element vectors and */ /* A is an n by n hermitian matrix, supplied in packed form. */ /* Parameters */ /* ========== */ /* UPLO - CHARACTER*1. */ /* On entry, UPLO specifies whether the upper or lower */ /* triangular part of the matrix A is supplied in the packed */ /* array AP as follows: */ /* UPLO = 'U' or 'u' The upper triangular part of A is */ /* supplied in AP. */ /* UPLO = 'L' or 'l' The lower triangular part of A is */ /* supplied in AP. */ /* Unchanged on exit. */ /* N - INTEGER. */ /* On entry, N specifies the order of the matrix A. */ /* N must be at least zero. */ /* Unchanged on exit. */ /* ALPHA - COMPLEX*16 . */ /* On entry, ALPHA specifies the scalar alpha. */ /* Unchanged on exit. */ /* AP - COMPLEX*16 array of DIMENSION at least */ /* ( ( n*( n + 1 ) )/2 ). */ /* Before entry with UPLO = 'U' or 'u', the array AP must */ /* contain the upper triangular part of the hermitian matrix */ /* packed sequentially, column by column, so that AP( 1 ) */ /* contains a( 1, 1 ), AP( 2 ) and AP( 3 ) contain a( 1, 2 ) */ /* and a( 2, 2 ) respectively, and so on. */ /* Before entry with UPLO = 'L' or 'l', the array AP must */ /* contain the lower triangular part of the hermitian matrix */ /* packed sequentially, column by column, so that AP( 1 ) */ /* contains a( 1, 1 ), AP( 2 ) and AP( 3 ) contain a( 2, 1 ) */ /* and a( 3, 1 ) respectively, and so on. */ /* Note that the imaginary parts of the diagonal elements need */ /* not be set and are assumed to be zero. */ /* Unchanged on exit. */ /* X - COMPLEX*16 array of dimension at least */ /* ( 1 + ( n - 1 )*abs( INCX ) ). */ /* Before entry, the incremented array X must contain the n */ /* element vector x. */ /* Unchanged on exit. */ /* INCX - INTEGER. */ /* On entry, INCX specifies the increment for the elements of */ /* X. INCX must not be zero. */ /* Unchanged on exit. */ /* BETA - COMPLEX*16 . */ /* On entry, BETA specifies the scalar beta. When BETA is */ /* supplied as zero then Y need not be set on input. */ /* Unchanged on exit. */ /* Y - COMPLEX*16 array of dimension at least */ /* ( 1 + ( n - 1 )*abs( INCY ) ). */ /* Before entry, the incremented array Y must contain the n */ /* element vector y. On exit, Y is overwritten by the updated */ /* vector y. */ /* INCY - INTEGER. */ /* On entry, INCY specifies the increment for the elements of */ /* Y. INCY must not be zero. */ /* Unchanged on exit. */ /* Level 2 Blas routine. */ /* -- Written on 22-October-1986. */ /* Jack Dongarra, Argonne National Lab. */ /* Jeremy Du Croz, Nag Central Office. */ /* Sven Hammarling, Nag Central Office. */ /* Richard Hanson, Sandia National Labs. */ /* .. Parameters .. */ /* .. Local Scalars .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. */ /* .. Executable Statements .. */ /* Test the input parameters. */ /* Parameter adjustments */ --y; --x; --ap; /* Function Body */ info = 0; if (! PASTEF770(lsame)(uplo, "U", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(uplo, "L", ( ftnlen)1, (ftnlen)1)) { info = 1; } else if (*n < 0) { info = 2; } else if (*incx == 0) { info = 6; } else if (*incy == 0) { info = 9; } if (info != 0) { PASTEF770(xerbla)("ZHPMV ", &info, (ftnlen)6); return 0; } /* Quick return if possible. */ if (*n == 0 || (bli_zreal(*alpha) == 0. && bli_zimag(*alpha) == 0. && (bli_zreal(*beta) == 1. && bli_zimag(*beta) == 0.))) { return 0; } /* Set up the start points in X and Y. */ if (*incx > 0) { kx = 1; } else { kx = 1 - (*n - 1) * *incx; } if (*incy > 0) { ky = 1; } else { ky = 1 - (*n - 1) * *incy; } /* Start the operations. In this version the elements of the array AP */ /* are accessed sequentially with one pass through AP. */ /* First form y := beta*y. */ if (bli_zreal(*beta) != 1. || bli_zimag(*beta) != 0.) { if (*incy == 1) { if (bli_zreal(*beta) == 0. && bli_zimag(*beta) == 0.) { i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { i__2 = i__; bli_zsets( (0.), (0.), y[i__2] ); /* L10: */ } } else { i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { i__2 = i__; i__3 = i__; bli_zsets( (bli_zreal(*beta) * bli_zreal(y[i__3]) - bli_zimag(*beta) * bli_zimag(y[i__3])), (bli_zreal(*beta) * bli_zimag(y[i__3]) + bli_zimag(*beta) * bli_zreal(y[i__3])), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), y[i__2] ); /* L20: */ } } } else { iy = ky; if (bli_zreal(*beta) == 0. && bli_zimag(*beta) == 0.) { i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { i__2 = iy; bli_zsets( (0.), (0.), y[i__2] ); iy += *incy; /* L30: */ } } else { i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { i__2 = iy; i__3 = iy; bli_zsets( (bli_zreal(*beta) * bli_zreal(y[i__3]) - bli_zimag(*beta) * bli_zimag(y[i__3])), (bli_zreal(*beta) * bli_zimag(y[i__3]) + bli_zimag(*beta) * bli_zreal(y[i__3])), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), y[i__2] ); iy += *incy; /* L40: */ } } } } if (bli_zreal(*alpha) == 0. && bli_zimag(*alpha) == 0.) { return 0; } kk = 1; if (PASTEF770(lsame)(uplo, "U", (ftnlen)1, (ftnlen)1)) { /* Form y when AP contains the upper triangle. */ if (*incx == 1 && *incy == 1) { i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = j; bli_zsets( (bli_zreal(*alpha) * bli_zreal(x[i__2]) - bli_zimag(*alpha) * bli_zimag(x[i__2])), (bli_zreal(*alpha) * bli_zimag(x[i__2]) + bli_zimag(*alpha) * bli_zreal(x[i__2])), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp1 ); bli_zsets( (0.), (0.), temp2 ); k = kk; i__2 = j - 1; for (i__ = 1; i__ <= i__2; ++i__) { i__3 = i__; i__4 = i__; i__5 = k; bli_zsets( (bli_zreal(temp1) * bli_zreal(ap[i__5]) - bli_zimag(temp1) * bli_zimag(ap[i__5])), (bli_zreal(temp1) * bli_zimag(ap[i__5]) + bli_zimag(temp1) * bli_zreal(ap[i__5])), z__2 ); bli_zsets( (bli_zreal(y[i__4]) + bli_zreal(z__2)), (bli_zimag(y[i__4]) + bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), y[i__3] ); bla_d_cnjg(&z__3, &ap[k]); i__3 = i__; bli_zsets( (bli_zreal(z__3) * bli_zreal(x[i__3]) - bli_zimag(z__3) * bli_zimag(x[i__3])), (bli_zreal(z__3) * bli_zimag(x[i__3]) + bli_zimag(z__3) * bli_zreal(x[i__3])), z__2 ); bli_zsets( (bli_zreal(temp2) + bli_zreal(z__2)), (bli_zimag(temp2) + bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp2 ); ++k; /* L50: */ } i__2 = j; i__3 = j; i__4 = kk + j - 1; d__1 = bli_zreal(ap[i__4]); bli_zsets( (d__1 * bli_zreal(temp1)), (d__1 * bli_zimag(temp1)), z__3 ); bli_zsets( (bli_zreal(y[i__3]) + bli_zreal(z__3)), (bli_zimag(y[i__3]) + bli_zimag(z__3)), z__2 ); bli_zsets( (bli_zreal(*alpha) * bli_zreal(temp2) - bli_zimag(*alpha) * bli_zimag(temp2)), (bli_zreal(*alpha) * bli_zimag(temp2) + bli_zimag(*alpha) * bli_zreal(temp2)), z__4 ); bli_zsets( (bli_zreal(z__2) + bli_zreal(z__4)), (bli_zimag(z__2) + bli_zimag(z__4)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), y[i__2] ); kk += j; /* L60: */ } } else { jx = kx; jy = ky; i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = jx; bli_zsets( (bli_zreal(*alpha) * bli_zreal(x[i__2]) - bli_zimag(*alpha) * bli_zimag(x[i__2])), (bli_zreal(*alpha) * bli_zimag(x[i__2]) + bli_zimag(*alpha) * bli_zreal(x[i__2])), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp1 ); bli_zsets( (0.), (0.), temp2 ); ix = kx; iy = ky; i__2 = kk + j - 2; for (k = kk; k <= i__2; ++k) { i__3 = iy; i__4 = iy; i__5 = k; bli_zsets( (bli_zreal(temp1) * bli_zreal(ap[i__5]) - bli_zimag(temp1) * bli_zimag(ap[i__5])), (bli_zreal(temp1) * bli_zimag(ap[i__5]) + bli_zimag(temp1) * bli_zreal(ap[i__5])), z__2 ); bli_zsets( (bli_zreal(y[i__4]) + bli_zreal(z__2)), (bli_zimag(y[i__4]) + bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), y[i__3] ); bla_d_cnjg(&z__3, &ap[k]); i__3 = ix; bli_zsets( (bli_zreal(z__3) * bli_zreal(x[i__3]) - bli_zimag(z__3) * bli_zimag(x[i__3])), (bli_zreal(z__3) * bli_zimag(x[i__3]) + bli_zimag(z__3) * bli_zreal(x[i__3])), z__2 ); bli_zsets( (bli_zreal(temp2) + bli_zreal(z__2)), (bli_zimag(temp2) + bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp2 ); ix += *incx; iy += *incy; /* L70: */ } i__2 = jy; i__3 = jy; i__4 = kk + j - 1; d__1 = bli_zreal(ap[i__4]); bli_zsets( (d__1 * bli_zreal(temp1)), (d__1 * bli_zimag(temp1)), z__3 ); bli_zsets( (bli_zreal(y[i__3]) + bli_zreal(z__3)), (bli_zimag(y[i__3]) + bli_zimag(z__3)), z__2 ); bli_zsets( (bli_zreal(*alpha) * bli_zreal(temp2) - bli_zimag(*alpha) * bli_zimag(temp2)), (bli_zreal(*alpha) * bli_zimag(temp2) + bli_zimag(*alpha) * bli_zreal(temp2)), z__4 ); bli_zsets( (bli_zreal(z__2) + bli_zreal(z__4)), (bli_zimag(z__2) + bli_zimag(z__4)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), y[i__2] ); jx += *incx; jy += *incy; kk += j; /* L80: */ } } } else { /* Form y when AP contains the lower triangle. */ if (*incx == 1 && *incy == 1) { i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = j; bli_zsets( (bli_zreal(*alpha) * bli_zreal(x[i__2]) - bli_zimag(*alpha) * bli_zimag(x[i__2])), (bli_zreal(*alpha) * bli_zimag(x[i__2]) + bli_zimag(*alpha) * bli_zreal(x[i__2])), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp1 ); bli_zsets( (0.), (0.), temp2 ); i__2 = j; i__3 = j; i__4 = kk; d__1 = bli_zreal(ap[i__4]); bli_zsets( (d__1 * bli_zreal(temp1)), (d__1 * bli_zimag(temp1)), z__2 ); bli_zsets( (bli_zreal(y[i__3]) + bli_zreal(z__2)), (bli_zimag(y[i__3]) + bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), y[i__2] ); k = kk + 1; i__2 = *n; for (i__ = j + 1; i__ <= i__2; ++i__) { i__3 = i__; i__4 = i__; i__5 = k; bli_zsets( (bli_zreal(temp1) * bli_zreal(ap[i__5]) - bli_zimag(temp1) * bli_zimag(ap[i__5])), (bli_zreal(temp1) * bli_zimag(ap[i__5]) + bli_zimag(temp1) * bli_zreal(ap[i__5])), z__2 ); bli_zsets( (bli_zreal(y[i__4]) + bli_zreal(z__2)), (bli_zimag(y[i__4]) + bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), y[i__3] ); bla_d_cnjg(&z__3, &ap[k]); i__3 = i__; bli_zsets( (bli_zreal(z__3) * bli_zreal(x[i__3]) - bli_zimag(z__3) * bli_zimag(x[i__3])), (bli_zreal(z__3) * bli_zimag(x[i__3]) + bli_zimag(z__3) * bli_zreal(x[i__3])), z__2 ); bli_zsets( (bli_zreal(temp2) + bli_zreal(z__2)), (bli_zimag(temp2) + bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp2 ); ++k; /* L90: */ } i__2 = j; i__3 = j; bli_zsets( (bli_zreal(*alpha) * bli_zreal(temp2) - bli_zimag(*alpha) * bli_zimag(temp2)), (bli_zreal(*alpha) * bli_zimag(temp2) + bli_zimag(*alpha) * bli_zreal(temp2)), z__2 ); bli_zsets( (bli_zreal(y[i__3]) + bli_zreal(z__2)), (bli_zimag(y[i__3]) + bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), y[i__2] ); kk += *n - j + 1; /* L100: */ } } else { jx = kx; jy = ky; i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = jx; bli_zsets( (bli_zreal(*alpha) * bli_zreal(x[i__2]) - bli_zimag(*alpha) * bli_zimag(x[i__2])), (bli_zreal(*alpha) * bli_zimag(x[i__2]) + bli_zimag(*alpha) * bli_zreal(x[i__2])), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp1 ); bli_zsets( (0.), (0.), temp2 ); i__2 = jy; i__3 = jy; i__4 = kk; d__1 = bli_zreal(ap[i__4]); bli_zsets( (d__1 * bli_zreal(temp1)), (d__1 * bli_zimag(temp1)), z__2 ); bli_zsets( (bli_zreal(y[i__3]) + bli_zreal(z__2)), (bli_zimag(y[i__3]) + bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), y[i__2] ); ix = jx; iy = jy; i__2 = kk + *n - j; for (k = kk + 1; k <= i__2; ++k) { ix += *incx; iy += *incy; i__3 = iy; i__4 = iy; i__5 = k; bli_zsets( (bli_zreal(temp1) * bli_zreal(ap[i__5]) - bli_zimag(temp1) * bli_zimag(ap[i__5])), (bli_zreal(temp1) * bli_zimag(ap[i__5]) + bli_zimag(temp1) * bli_zreal(ap[i__5])), z__2 ); bli_zsets( (bli_zreal(y[i__4]) + bli_zreal(z__2)), (bli_zimag(y[i__4]) + bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), y[i__3] ); bla_d_cnjg(&z__3, &ap[k]); i__3 = ix; bli_zsets( (bli_zreal(z__3) * bli_zreal(x[i__3]) - bli_zimag(z__3) * bli_zimag(x[i__3])), (bli_zreal(z__3) * bli_zimag(x[i__3]) + bli_zimag(z__3) * bli_zreal(x[i__3])), z__2 ); bli_zsets( (bli_zreal(temp2) + bli_zreal(z__2)), (bli_zimag(temp2) + bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp2 ); /* L110: */ } i__2 = jy; i__3 = jy; bli_zsets( (bli_zreal(*alpha) * bli_zreal(temp2) - bli_zimag(*alpha) * bli_zimag(temp2)), (bli_zreal(*alpha) * bli_zimag(temp2) + bli_zimag(*alpha) * bli_zreal(temp2)), z__2 ); bli_zsets( (bli_zreal(y[i__3]) + bli_zreal(z__2)), (bli_zimag(y[i__3]) + bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), y[i__2] ); jx += *incx; jy += *incy; kk += *n - j + 1; /* L120: */ } } } return 0; /* End of ZHPMV . */ } /* zhpmv_ */ #endif blis-0.9.0/frame/compat/f2c/bla_hpmv.h000066400000000000000000000042501422157504600174500ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifdef BLIS_ENABLE_BLAS BLIS_EXPORT_BLAS int PASTEF77(c,hpmv)(const bla_character *uplo, const bla_integer *n, const bla_scomplex *alpha, const bla_scomplex *ap, const bla_scomplex *x, const bla_integer *incx, const bla_scomplex *beta, bla_scomplex *y, const bla_integer *incy); BLIS_EXPORT_BLAS int PASTEF77(z,hpmv)(const bla_character *uplo, const bla_integer *n, const bla_dcomplex *alpha, const bla_dcomplex *ap, const bla_dcomplex *x, const bla_integer *incx, const bla_dcomplex *beta, bla_dcomplex *y, const bla_integer *incy); #endif blis-0.9.0/frame/compat/f2c/bla_hpr.c000066400000000000000000000546501422157504600172730ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #ifdef BLIS_ENABLE_BLAS /* chpr.f -- translated by f2c (version 19991025). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ /* Subroutine */ int PASTEF77(c,hpr)(const bla_character *uplo, const bla_integer *n, const bla_real *alpha, const bla_scomplex *x, const bla_integer *incx, bla_scomplex *ap) { /* System generated locals */ bla_integer i__1, i__2, i__3, i__4, i__5; bla_real r__1; bla_scomplex q__1, q__2; /* Builtin functions */ //void bla_r_cnjg(bla_scomplex *, bla_scomplex *); /* Local variables */ bla_integer info; bla_scomplex temp; bla_integer i__, j, k; //extern bla_logical PASTEF770(lsame)(bla_character *, bla_character *, ftnlen, ftnlen); bla_integer kk, ix, jx, kx = 0; //extern /* Subroutine */ int PASTEF770(xerbla)(bla_character *, bla_integer *, ftnlen); /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* CHPR performs the hermitian rank 1 operation */ /* A := alpha*x*conjg( x' ) + A, */ /* where alpha is a bla_real scalar, x is an n element vector and A is an */ /* n by n hermitian matrix, supplied in packed form. */ /* Parameters */ /* ========== */ /* UPLO - CHARACTER*1. */ /* On entry, UPLO specifies whether the upper or lower */ /* triangular part of the matrix A is supplied in the packed */ /* array AP as follows: */ /* UPLO = 'U' or 'u' The upper triangular part of A is */ /* supplied in AP. */ /* UPLO = 'L' or 'l' The lower triangular part of A is */ /* supplied in AP. */ /* Unchanged on exit. */ /* N - INTEGER. */ /* On entry, N specifies the order of the matrix A. */ /* N must be at least zero. */ /* Unchanged on exit. */ /* ALPHA - REAL . */ /* On entry, ALPHA specifies the scalar alpha. */ /* Unchanged on exit. */ /* X - COMPLEX array of dimension at least */ /* ( 1 + ( n - 1 )*abs( INCX ) ). */ /* Before entry, the incremented array X must contain the n */ /* element vector x. */ /* Unchanged on exit. */ /* INCX - INTEGER. */ /* On entry, INCX specifies the increment for the elements of */ /* X. INCX must not be zero. */ /* Unchanged on exit. */ /* AP - COMPLEX array of DIMENSION at least */ /* ( ( n*( n + 1 ) )/2 ). */ /* Before entry with UPLO = 'U' or 'u', the array AP must */ /* contain the upper triangular part of the hermitian matrix */ /* packed sequentially, column by column, so that AP( 1 ) */ /* contains a( 1, 1 ), AP( 2 ) and AP( 3 ) contain a( 1, 2 ) */ /* and a( 2, 2 ) respectively, and so on. On exit, the array */ /* AP is overwritten by the upper triangular part of the */ /* updated matrix. */ /* Before entry with UPLO = 'L' or 'l', the array AP must */ /* contain the lower triangular part of the hermitian matrix */ /* packed sequentially, column by column, so that AP( 1 ) */ /* contains a( 1, 1 ), AP( 2 ) and AP( 3 ) contain a( 2, 1 ) */ /* and a( 3, 1 ) respectively, and so on. On exit, the array */ /* AP is overwritten by the lower triangular part of the */ /* updated matrix. */ /* Note that the imaginary parts of the diagonal elements need */ /* not be set, they are assumed to be zero, and on exit they */ /* are set to zero. */ /* Level 2 Blas routine. */ /* -- Written on 22-October-1986. */ /* Jack Dongarra, Argonne National Lab. */ /* Jeremy Du Croz, Nag Central Office. */ /* Sven Hammarling, Nag Central Office. */ /* Richard Hanson, Sandia National Labs. */ /* .. Parameters .. */ /* .. Local Scalars .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. */ /* .. Executable Statements .. */ /* Test the input parameters. */ /* Parameter adjustments */ --ap; --x; /* Function Body */ info = 0; if (! PASTEF770(lsame)(uplo, "U", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(uplo, "L", ( ftnlen)1, (ftnlen)1)) { info = 1; } else if (*n < 0) { info = 2; } else if (*incx == 0) { info = 5; } if (info != 0) { PASTEF770(xerbla)("CHPR ", &info, (ftnlen)6); return 0; } /* Quick return if possible. */ if (*n == 0 || *alpha == 0.f) { return 0; } /* Set the start point in X if the increment is not unity. */ if (*incx <= 0) { kx = 1 - (*n - 1) * *incx; } else if (*incx != 1) { kx = 1; } /* Start the operations. In this version the elements of the array AP */ /* are accessed sequentially with one pass through AP. */ kk = 1; if (PASTEF770(lsame)(uplo, "U", (ftnlen)1, (ftnlen)1)) { /* Form A when upper triangle is stored in AP. */ if (*incx == 1) { i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = j; if (bli_creal(x[i__2]) != 0.f || bli_cimag(x[i__2]) != 0.f) { bla_r_cnjg(&q__2, &x[j]); bli_csets( (*alpha * bli_creal(q__2)), (*alpha * bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp ); k = kk; i__2 = j - 1; for (i__ = 1; i__ <= i__2; ++i__) { i__3 = k; i__4 = k; i__5 = i__; bli_csets( (bli_creal(x[i__5]) * bli_creal(temp) - bli_cimag(x[i__5]) * bli_cimag(temp)), (bli_creal(x[i__5]) * bli_cimag(temp) + bli_cimag(x[i__5]) * bli_creal(temp)), q__2 ); bli_csets( (bli_creal(ap[i__4]) + bli_creal(q__2)), (bli_cimag(ap[i__4]) + bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), ap[i__3] ); ++k; /* L10: */ } i__2 = kk + j - 1; i__3 = kk + j - 1; i__4 = j; bli_csets( (bli_creal(x[i__4]) * bli_creal(temp) - bli_cimag(x[i__4]) * bli_cimag(temp)), (bli_creal(x[i__4]) * bli_cimag(temp) + bli_cimag(x[i__4]) * bli_creal(temp)), q__1 ); r__1 = bli_creal(ap[i__3]) + bli_creal(q__1); bli_csets( (r__1), (0.f), ap[i__2] ); } else { i__2 = kk + j - 1; i__3 = kk + j - 1; r__1 = bli_creal(ap[i__3]); bli_csets( (r__1), (0.f), ap[i__2] ); } kk += j; /* L20: */ } } else { jx = kx; i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = jx; if (bli_creal(x[i__2]) != 0.f || bli_cimag(x[i__2]) != 0.f) { bla_r_cnjg(&q__2, &x[jx]); bli_csets( (*alpha * bli_creal(q__2)), (*alpha * bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp ); ix = kx; i__2 = kk + j - 2; for (k = kk; k <= i__2; ++k) { i__3 = k; i__4 = k; i__5 = ix; bli_csets( (bli_creal(x[i__5]) * bli_creal(temp) - bli_cimag(x[i__5]) * bli_cimag(temp)), (bli_creal(x[i__5]) * bli_cimag(temp) + bli_cimag(x[i__5]) * bli_creal(temp)), q__2 ); bli_csets( (bli_creal(ap[i__4]) + bli_creal(q__2)), (bli_cimag(ap[i__4]) + bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), ap[i__3] ); ix += *incx; /* L30: */ } i__2 = kk + j - 1; i__3 = kk + j - 1; i__4 = jx; bli_csets( (bli_creal(x[i__4]) * bli_creal(temp) - bli_cimag(x[i__4]) * bli_cimag(temp)), (bli_creal(x[i__4]) * bli_cimag(temp) + bli_cimag(x[i__4]) * bli_creal(temp)), q__1 ); r__1 = bli_creal(ap[i__3]) + bli_creal(q__1); bli_csets( (r__1), (0.f), ap[i__2] ); } else { i__2 = kk + j - 1; i__3 = kk + j - 1; r__1 = bli_creal(ap[i__3]); bli_csets( (r__1), (0.f), ap[i__2] ); } jx += *incx; kk += j; /* L40: */ } } } else { /* Form A when lower triangle is stored in AP. */ if (*incx == 1) { i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = j; if (bli_creal(x[i__2]) != 0.f || bli_cimag(x[i__2]) != 0.f) { bla_r_cnjg(&q__2, &x[j]); bli_csets( (*alpha * bli_creal(q__2)), (*alpha * bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp ); i__2 = kk; i__3 = kk; i__4 = j; bli_csets( (bli_creal(temp) * bli_creal(x[i__4]) - bli_cimag(temp) * bli_cimag(x[i__4])), (bli_creal(temp) * bli_cimag(x[i__4]) + bli_cimag(temp) * bli_creal(x[i__4])), q__1 ); r__1 = bli_creal(ap[i__3]) + bli_creal(q__1); bli_csets( (r__1), (0.f), ap[i__2] ); k = kk + 1; i__2 = *n; for (i__ = j + 1; i__ <= i__2; ++i__) { i__3 = k; i__4 = k; i__5 = i__; bli_csets( (bli_creal(x[i__5]) * bli_creal(temp) - bli_cimag(x[i__5]) * bli_cimag(temp)), (bli_creal(x[i__5]) * bli_cimag(temp) + bli_cimag(x[i__5]) * bli_creal(temp)), q__2 ); bli_csets( (bli_creal(ap[i__4]) + bli_creal(q__2)), (bli_cimag(ap[i__4]) + bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), ap[i__3] ); ++k; /* L50: */ } } else { i__2 = kk; i__3 = kk; r__1 = bli_creal(ap[i__3]); bli_csets( (r__1), (0.f), ap[i__2] ); } kk = kk + *n - j + 1; /* L60: */ } } else { jx = kx; i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = jx; if (bli_creal(x[i__2]) != 0.f || bli_cimag(x[i__2]) != 0.f) { bla_r_cnjg(&q__2, &x[jx]); bli_csets( (*alpha * bli_creal(q__2)), (*alpha * bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp ); i__2 = kk; i__3 = kk; i__4 = jx; bli_csets( (bli_creal(temp) * bli_creal(x[i__4]) - bli_cimag(temp) * bli_cimag(x[i__4])), (bli_creal(temp) * bli_cimag(x[i__4]) + bli_cimag(temp) * bli_creal(x[i__4])), q__1 ); r__1 = bli_creal(ap[i__3]) + bli_creal(q__1); bli_csets( (r__1), (0.f), ap[i__2] ); ix = jx; i__2 = kk + *n - j; for (k = kk + 1; k <= i__2; ++k) { ix += *incx; i__3 = k; i__4 = k; i__5 = ix; bli_csets( (bli_creal(x[i__5]) * bli_creal(temp) - bli_cimag(x[i__5]) * bli_cimag(temp)), (bli_creal(x[i__5]) * bli_cimag(temp) + bli_cimag(x[i__5]) * bli_creal(temp)), q__2 ); bli_csets( (bli_creal(ap[i__4]) + bli_creal(q__2)), (bli_cimag(ap[i__4]) + bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), ap[i__3] ); /* L70: */ } } else { i__2 = kk; i__3 = kk; r__1 = bli_creal(ap[i__3]); bli_csets( (r__1), (0.f), ap[i__2] ); } jx += *incx; kk = kk + *n - j + 1; /* L80: */ } } } return 0; /* End of CHPR . */ } /* chpr_ */ /* zhpr.f -- translated by f2c (version 19991025). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ /* Subroutine */ int PASTEF77(z,hpr)(const bla_character *uplo, const bla_integer *n, const bla_double *alpha, const bla_dcomplex *x, const bla_integer *incx, bla_dcomplex *ap) { /* System generated locals */ bla_integer i__1, i__2, i__3, i__4, i__5; bla_double d__1; bla_dcomplex z__1, z__2; /* Builtin functions */ //void bla_d_cnjg(bla_dcomplex *, bla_dcomplex *); /* Local variables */ bla_integer info; bla_dcomplex temp; bla_integer i__, j, k; //extern bla_logical PASTEF770(lsame)(bla_character *, bla_character *, ftnlen, ftnlen); bla_integer kk, ix, jx, kx = 0; //extern /* Subroutine */ int PASTEF770(xerbla)(bla_character *, bla_integer *, ftnlen); /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* ZHPR performs the hermitian rank 1 operation */ /* A := alpha*x*conjg( x' ) + A, */ /* where alpha is a bla_real scalar, x is an n element vector and A is an */ /* n by n hermitian matrix, supplied in packed form. */ /* Parameters */ /* ========== */ /* UPLO - CHARACTER*1. */ /* On entry, UPLO specifies whether the upper or lower */ /* triangular part of the matrix A is supplied in the packed */ /* array AP as follows: */ /* UPLO = 'U' or 'u' The upper triangular part of A is */ /* supplied in AP. */ /* UPLO = 'L' or 'l' The lower triangular part of A is */ /* supplied in AP. */ /* Unchanged on exit. */ /* N - INTEGER. */ /* On entry, N specifies the order of the matrix A. */ /* N must be at least zero. */ /* Unchanged on exit. */ /* ALPHA - DOUBLE PRECISION. */ /* On entry, ALPHA specifies the scalar alpha. */ /* Unchanged on exit. */ /* X - COMPLEX*16 array of dimension at least */ /* ( 1 + ( n - 1 )*abs( INCX ) ). */ /* Before entry, the incremented array X must contain the n */ /* element vector x. */ /* Unchanged on exit. */ /* INCX - INTEGER. */ /* On entry, INCX specifies the increment for the elements of */ /* X. INCX must not be zero. */ /* Unchanged on exit. */ /* AP - COMPLEX*16 array of DIMENSION at least */ /* ( ( n*( n + 1 ) )/2 ). */ /* Before entry with UPLO = 'U' or 'u', the array AP must */ /* contain the upper triangular part of the hermitian matrix */ /* packed sequentially, column by column, so that AP( 1 ) */ /* contains a( 1, 1 ), AP( 2 ) and AP( 3 ) contain a( 1, 2 ) */ /* and a( 2, 2 ) respectively, and so on. On exit, the array */ /* AP is overwritten by the upper triangular part of the */ /* updated matrix. */ /* Before entry with UPLO = 'L' or 'l', the array AP must */ /* contain the lower triangular part of the hermitian matrix */ /* packed sequentially, column by column, so that AP( 1 ) */ /* contains a( 1, 1 ), AP( 2 ) and AP( 3 ) contain a( 2, 1 ) */ /* and a( 3, 1 ) respectively, and so on. On exit, the array */ /* AP is overwritten by the lower triangular part of the */ /* updated matrix. */ /* Note that the imaginary parts of the diagonal elements need */ /* not be set, they are assumed to be zero, and on exit they */ /* are set to zero. */ /* Level 2 Blas routine. */ /* -- Written on 22-October-1986. */ /* Jack Dongarra, Argonne National Lab. */ /* Jeremy Du Croz, Nag Central Office. */ /* Sven Hammarling, Nag Central Office. */ /* Richard Hanson, Sandia National Labs. */ /* .. Parameters .. */ /* .. Local Scalars .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. */ /* .. Executable Statements .. */ /* Test the input parameters. */ /* Parameter adjustments */ --ap; --x; /* Function Body */ info = 0; if (! PASTEF770(lsame)(uplo, "U", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(uplo, "L", ( ftnlen)1, (ftnlen)1)) { info = 1; } else if (*n < 0) { info = 2; } else if (*incx == 0) { info = 5; } if (info != 0) { PASTEF770(xerbla)("ZHPR ", &info, (ftnlen)6); return 0; } /* Quick return if possible. */ if (*n == 0 || *alpha == 0.) { return 0; } /* Set the start point in X if the increment is not unity. */ if (*incx <= 0) { kx = 1 - (*n - 1) * *incx; } else if (*incx != 1) { kx = 1; } /* Start the operations. In this version the elements of the array AP */ /* are accessed sequentially with one pass through AP. */ kk = 1; if (PASTEF770(lsame)(uplo, "U", (ftnlen)1, (ftnlen)1)) { /* Form A when upper triangle is stored in AP. */ if (*incx == 1) { i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = j; if (bli_zreal(x[i__2]) != 0. || bli_zimag(x[i__2]) != 0.) { bla_d_cnjg(&z__2, &x[j]); bli_zsets( (*alpha * bli_zreal(z__2)), (*alpha * bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp ); k = kk; i__2 = j - 1; for (i__ = 1; i__ <= i__2; ++i__) { i__3 = k; i__4 = k; i__5 = i__; bli_zsets( (bli_zreal(x[i__5]) * bli_zreal(temp) - bli_zimag(x[i__5]) * bli_zimag(temp)), (bli_zreal(x[i__5]) * bli_zimag(temp) + bli_zimag(x[i__5]) * bli_zreal(temp)), z__2 ); bli_zsets( (bli_zreal(ap[i__4]) + bli_zreal(z__2)), (bli_zimag(ap[i__4]) + bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), ap[i__3] ); ++k; /* L10: */ } i__2 = kk + j - 1; i__3 = kk + j - 1; i__4 = j; bli_zsets( (bli_zreal(x[i__4]) * bli_zreal(temp) - bli_zimag(x[i__4]) * bli_zimag(temp)), (bli_zreal(x[i__4]) * bli_zimag(temp) + bli_zimag(x[i__4]) * bli_zreal(temp)), z__1 ); d__1 = bli_zreal(ap[i__3]) + bli_zreal(z__1); bli_zsets( (d__1), (0.), ap[i__2] ); } else { i__2 = kk + j - 1; i__3 = kk + j - 1; d__1 = bli_zreal(ap[i__3]); bli_zsets( (d__1), (0.), ap[i__2] ); } kk += j; /* L20: */ } } else { jx = kx; i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = jx; if (bli_zreal(x[i__2]) != 0. || bli_zimag(x[i__2]) != 0.) { bla_d_cnjg(&z__2, &x[jx]); bli_zsets( (*alpha * bli_zreal(z__2)), (*alpha * bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp ); ix = kx; i__2 = kk + j - 2; for (k = kk; k <= i__2; ++k) { i__3 = k; i__4 = k; i__5 = ix; bli_zsets( (bli_zreal(x[i__5]) * bli_zreal(temp) - bli_zimag(x[i__5]) * bli_zimag(temp)), (bli_zreal(x[i__5]) * bli_zimag(temp) + bli_zimag(x[i__5]) * bli_zreal(temp)), z__2 ); bli_zsets( (bli_zreal(ap[i__4]) + bli_zreal(z__2)), (bli_zimag(ap[i__4]) + bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), ap[i__3] ); ix += *incx; /* L30: */ } i__2 = kk + j - 1; i__3 = kk + j - 1; i__4 = jx; bli_zsets( (bli_zreal(x[i__4]) * bli_zreal(temp) - bli_zimag(x[i__4]) * bli_zimag(temp)), (bli_zreal(x[i__4]) * bli_zimag(temp) + bli_zimag(x[i__4]) * bli_zreal(temp)), z__1 ); d__1 = bli_zreal(ap[i__3]) + bli_zreal(z__1); bli_zsets( (d__1), (0.), ap[i__2] ); } else { i__2 = kk + j - 1; i__3 = kk + j - 1; d__1 = bli_zreal(ap[i__3]); bli_zsets( (d__1), (0.), ap[i__2] ); } jx += *incx; kk += j; /* L40: */ } } } else { /* Form A when lower triangle is stored in AP. */ if (*incx == 1) { i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = j; if (bli_zreal(x[i__2]) != 0. || bli_zimag(x[i__2]) != 0.) { bla_d_cnjg(&z__2, &x[j]); bli_zsets( (*alpha * bli_zreal(z__2)), (*alpha * bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp ); i__2 = kk; i__3 = kk; i__4 = j; bli_zsets( (bli_zreal(temp) * bli_zreal(x[i__4]) - bli_zimag(temp) * bli_zimag(x[i__4])), (bli_zreal(temp) * bli_zimag(x[i__4]) + bli_zimag(temp) * bli_zreal(x[i__4])), z__1 ); d__1 = bli_zreal(ap[i__3]) + bli_zreal(z__1); bli_zsets( (d__1), (0.), ap[i__2] ); k = kk + 1; i__2 = *n; for (i__ = j + 1; i__ <= i__2; ++i__) { i__3 = k; i__4 = k; i__5 = i__; bli_zsets( (bli_zreal(x[i__5]) * bli_zreal(temp) - bli_zimag(x[i__5]) * bli_zimag(temp)), (bli_zreal(x[i__5]) * bli_zimag(temp) + bli_zimag(x[i__5]) * bli_zreal(temp)), z__2 ); bli_zsets( (bli_zreal(ap[i__4]) + bli_zreal(z__2)), (bli_zimag(ap[i__4]) + bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), ap[i__3] ); ++k; /* L50: */ } } else { i__2 = kk; i__3 = kk; d__1 = bli_zreal(ap[i__3]); bli_zsets( (d__1), (0.), ap[i__2] ); } kk = kk + *n - j + 1; /* L60: */ } } else { jx = kx; i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = jx; if (bli_zreal(x[i__2]) != 0. || bli_zimag(x[i__2]) != 0.) { bla_d_cnjg(&z__2, &x[jx]); bli_zsets( (*alpha * bli_zreal(z__2)), (*alpha * bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp ); i__2 = kk; i__3 = kk; i__4 = jx; bli_zsets( (bli_zreal(temp) * bli_zreal(x[i__4]) - bli_zimag(temp) * bli_zimag(x[i__4])), (bli_zreal(temp) * bli_zimag(x[i__4]) + bli_zimag(temp) * bli_zreal(x[i__4])), z__1 ); d__1 = bli_zreal(ap[i__3]) + bli_zreal(z__1); bli_zsets( (d__1), (0.), ap[i__2] ); ix = jx; i__2 = kk + *n - j; for (k = kk + 1; k <= i__2; ++k) { ix += *incx; i__3 = k; i__4 = k; i__5 = ix; bli_zsets( (bli_zreal(x[i__5]) * bli_zreal(temp) - bli_zimag(x[i__5]) * bli_zimag(temp)), (bli_zreal(x[i__5]) * bli_zimag(temp) + bli_zimag(x[i__5]) * bli_zreal(temp)), z__2 ); bli_zsets( (bli_zreal(ap[i__4]) + bli_zreal(z__2)), (bli_zimag(ap[i__4]) + bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), ap[i__3] ); /* L70: */ } } else { i__2 = kk; i__3 = kk; d__1 = bli_zreal(ap[i__3]); bli_zsets( (d__1), (0.), ap[i__2] ); } jx += *incx; kk = kk + *n - j + 1; /* L80: */ } } } return 0; /* End of ZHPR . */ } /* zhpr_ */ #endif blis-0.9.0/frame/compat/f2c/bla_hpr.h000066400000000000000000000040141422157504600172650ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifdef BLIS_ENABLE_BLAS BLIS_EXPORT_BLAS int PASTEF77(c,hpr)(const bla_character *uplo, const bla_integer *n, const bla_real *alpha, const bla_scomplex *x, const bla_integer *incx, bla_scomplex *ap); BLIS_EXPORT_BLAS int PASTEF77(z,hpr)(const bla_character *uplo, const bla_integer *n, const bla_double *alpha, const bla_dcomplex *x, const bla_integer *incx, bla_dcomplex *ap); #endif blis-0.9.0/frame/compat/f2c/bla_hpr2.c000066400000000000000000001011571422157504600173500ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #ifdef BLIS_ENABLE_BLAS /* chpr2.f -- translated by f2c (version 19991025). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ /* Subroutine */ int PASTEF77(c,hpr2)(const bla_character *uplo, const bla_integer *n, const bla_scomplex *alpha, const bla_scomplex *x, const bla_integer *incx, const bla_scomplex *y, const bla_integer *incy, bla_scomplex *ap) { /* System generated locals */ bla_integer i__1, i__2, i__3, i__4, i__5, i__6; bla_real r__1; bla_scomplex q__1, q__2, q__3, q__4; /* Builtin functions */ //void bla_r_cnjg(bla_scomplex *, bla_scomplex *); /* Local variables */ bla_integer info; bla_scomplex temp1, temp2; bla_integer i__, j, k; //extern bla_logical PASTEF770(lsame)(bla_character *, bla_character *, ftnlen, ftnlen); bla_integer kk, ix, iy, jx = 0, jy = 0, kx = 0, ky = 0; //extern /* Subroutine */ int PASTEF770(xerbla)(bla_character *, bla_integer *, ftnlen); /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* CHPR2 performs the hermitian rank 2 operation */ /* A := alpha*x*conjg( y' ) + conjg( alpha )*y*conjg( x' ) + A, */ /* where alpha is a scalar, x and y are n element vectors and A is an */ /* n by n hermitian matrix, supplied in packed form. */ /* Parameters */ /* ========== */ /* UPLO - CHARACTER*1. */ /* On entry, UPLO specifies whether the upper or lower */ /* triangular part of the matrix A is supplied in the packed */ /* array AP as follows: */ /* UPLO = 'U' or 'u' The upper triangular part of A is */ /* supplied in AP. */ /* UPLO = 'L' or 'l' The lower triangular part of A is */ /* supplied in AP. */ /* Unchanged on exit. */ /* N - INTEGER. */ /* On entry, N specifies the order of the matrix A. */ /* N must be at least zero. */ /* Unchanged on exit. */ /* ALPHA - COMPLEX . */ /* On entry, ALPHA specifies the scalar alpha. */ /* Unchanged on exit. */ /* X - COMPLEX array of dimension at least */ /* ( 1 + ( n - 1 )*abs( INCX ) ). */ /* Before entry, the incremented array X must contain the n */ /* element vector x. */ /* Unchanged on exit. */ /* INCX - INTEGER. */ /* On entry, INCX specifies the increment for the elements of */ /* X. INCX must not be zero. */ /* Unchanged on exit. */ /* Y - COMPLEX array of dimension at least */ /* ( 1 + ( n - 1 )*abs( INCY ) ). */ /* Before entry, the incremented array Y must contain the n */ /* element vector y. */ /* Unchanged on exit. */ /* INCY - INTEGER. */ /* On entry, INCY specifies the increment for the elements of */ /* Y. INCY must not be zero. */ /* Unchanged on exit. */ /* AP - COMPLEX array of DIMENSION at least */ /* ( ( n*( n + 1 ) )/2 ). */ /* Before entry with UPLO = 'U' or 'u', the array AP must */ /* contain the upper triangular part of the hermitian matrix */ /* packed sequentially, column by column, so that AP( 1 ) */ /* contains a( 1, 1 ), AP( 2 ) and AP( 3 ) contain a( 1, 2 ) */ /* and a( 2, 2 ) respectively, and so on. On exit, the array */ /* AP is overwritten by the upper triangular part of the */ /* updated matrix. */ /* Before entry with UPLO = 'L' or 'l', the array AP must */ /* contain the lower triangular part of the hermitian matrix */ /* packed sequentially, column by column, so that AP( 1 ) */ /* contains a( 1, 1 ), AP( 2 ) and AP( 3 ) contain a( 2, 1 ) */ /* and a( 3, 1 ) respectively, and so on. On exit, the array */ /* AP is overwritten by the lower triangular part of the */ /* updated matrix. */ /* Note that the imaginary parts of the diagonal elements need */ /* not be set, they are assumed to be zero, and on exit they */ /* are set to zero. */ /* Level 2 Blas routine. */ /* -- Written on 22-October-1986. */ /* Jack Dongarra, Argonne National Lab. */ /* Jeremy Du Croz, Nag Central Office. */ /* Sven Hammarling, Nag Central Office. */ /* Richard Hanson, Sandia National Labs. */ /* .. Parameters .. */ /* .. Local Scalars .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. */ /* .. Executable Statements .. */ /* Test the input parameters. */ /* Parameter adjustments */ --ap; --y; --x; /* Function Body */ info = 0; if (! PASTEF770(lsame)(uplo, "U", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(uplo, "L", ( ftnlen)1, (ftnlen)1)) { info = 1; } else if (*n < 0) { info = 2; } else if (*incx == 0) { info = 5; } else if (*incy == 0) { info = 7; } if (info != 0) { PASTEF770(xerbla)("CHPR2 ", &info, (ftnlen)6); return 0; } /* Quick return if possible. */ if (*n == 0 || (bli_creal(*alpha) == 0.f && bli_cimag(*alpha) == 0.f)) { return 0; } /* Set up the start points in X and Y if the increments are not both */ /* unity. */ if (*incx != 1 || *incy != 1) { if (*incx > 0) { kx = 1; } else { kx = 1 - (*n - 1) * *incx; } if (*incy > 0) { ky = 1; } else { ky = 1 - (*n - 1) * *incy; } jx = kx; jy = ky; } /* Start the operations. In this version the elements of the array AP */ /* are accessed sequentially with one pass through AP. */ kk = 1; if (PASTEF770(lsame)(uplo, "U", (ftnlen)1, (ftnlen)1)) { /* Form A when upper triangle is stored in AP. */ if (*incx == 1 && *incy == 1) { i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = j; i__3 = j; if (bli_creal(x[i__2]) != 0.f || bli_cimag(x[i__2]) != 0.f || (bli_creal(y[i__3]) != 0.f || bli_cimag(y[i__3]) != 0.f)) { bla_r_cnjg(&q__2, &y[j]); bli_csets( (bli_creal(*alpha) * bli_creal(q__2) - bli_cimag(*alpha) * bli_cimag(q__2)), (bli_creal(*alpha) * bli_cimag(q__2) + bli_cimag(*alpha) * bli_creal(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp1 ); i__2 = j; bli_csets( (bli_creal(*alpha) * bli_creal(x[i__2]) - bli_cimag(*alpha) * bli_cimag(x[i__2])), (bli_creal(*alpha) * bli_cimag(x[i__2]) + bli_cimag(*alpha) * bli_creal(x[i__2])), q__2 ); bla_r_cnjg(&q__1, &q__2); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp2 ); k = kk; i__2 = j - 1; for (i__ = 1; i__ <= i__2; ++i__) { i__3 = k; i__4 = k; i__5 = i__; bli_csets( (bli_creal(x[i__5]) * bli_creal(temp1) - bli_cimag(x[i__5]) * bli_cimag(temp1)), (bli_creal(x[i__5]) * bli_cimag(temp1) + bli_cimag(x[i__5]) * bli_creal(temp1)), q__3 ); bli_csets( (bli_creal(ap[i__4]) + bli_creal(q__3)), (bli_cimag(ap[i__4]) + bli_cimag(q__3)), q__2 ); i__6 = i__; bli_csets( (bli_creal(y[i__6]) * bli_creal(temp2) - bli_cimag(y[i__6]) * bli_cimag(temp2)), (bli_creal(y[i__6]) * bli_cimag(temp2) + bli_cimag(y[i__6]) * bli_creal(temp2)), q__4 ); bli_csets( (bli_creal(q__2) + bli_creal(q__4)), (bli_cimag(q__2) + bli_cimag(q__4)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), ap[i__3] ); ++k; /* L10: */ } i__2 = kk + j - 1; i__3 = kk + j - 1; i__4 = j; bli_csets( (bli_creal(x[i__4]) * bli_creal(temp1) - bli_cimag(x[i__4]) * bli_cimag(temp1)), (bli_creal(x[i__4]) * bli_cimag(temp1) + bli_cimag(x[i__4]) * bli_creal(temp1)), q__2 ); i__5 = j; bli_csets( (bli_creal(y[i__5]) * bli_creal(temp2) - bli_cimag(y[i__5]) * bli_cimag(temp2)), (bli_creal(y[i__5]) * bli_cimag(temp2) + bli_cimag(y[i__5]) * bli_creal(temp2)), q__3 ); bli_csets( (bli_creal(q__2) + bli_creal(q__3)), (bli_cimag(q__2) + bli_cimag(q__3)), q__1 ); r__1 = bli_creal(ap[i__3]) + bli_creal(q__1); bli_csets( (r__1), (0.f), ap[i__2] ); } else { i__2 = kk + j - 1; i__3 = kk + j - 1; r__1 = bli_creal(ap[i__3]); bli_csets( (r__1), (0.f), ap[i__2] ); } kk += j; /* L20: */ } } else { i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = jx; i__3 = jy; if (bli_creal(x[i__2]) != 0.f || bli_cimag(x[i__2]) != 0.f || (bli_creal(y[i__3]) != 0.f || bli_cimag(y[i__3]) != 0.f)) { bla_r_cnjg(&q__2, &y[jy]); bli_csets( (bli_creal(*alpha) * bli_creal(q__2) - bli_cimag(*alpha) * bli_cimag(q__2)), (bli_creal(*alpha) * bli_cimag(q__2) + bli_cimag(*alpha) * bli_creal(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp1 ); i__2 = jx; bli_csets( (bli_creal(*alpha) * bli_creal(x[i__2]) - bli_cimag(*alpha) * bli_cimag(x[i__2])), (bli_creal(*alpha) * bli_cimag(x[i__2]) + bli_cimag(*alpha) * bli_creal(x[i__2])), q__2 ); bla_r_cnjg(&q__1, &q__2); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp2 ); ix = kx; iy = ky; i__2 = kk + j - 2; for (k = kk; k <= i__2; ++k) { i__3 = k; i__4 = k; i__5 = ix; bli_csets( (bli_creal(x[i__5]) * bli_creal(temp1) - bli_cimag(x[i__5]) * bli_cimag(temp1)), (bli_creal(x[i__5]) * bli_cimag(temp1) + bli_cimag(x[i__5]) * bli_creal(temp1)), q__3 ); bli_csets( (bli_creal(ap[i__4]) + bli_creal(q__3)), (bli_cimag(ap[i__4]) + bli_cimag(q__3)), q__2 ); i__6 = iy; bli_csets( (bli_creal(y[i__6]) * bli_creal(temp2) - bli_cimag(y[i__6]) * bli_cimag(temp2)), (bli_creal(y[i__6]) * bli_cimag(temp2) + bli_cimag(y[i__6]) * bli_creal(temp2)), q__4 ); bli_csets( (bli_creal(q__2) + bli_creal(q__4)), (bli_cimag(q__2) + bli_cimag(q__4)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), ap[i__3] ); ix += *incx; iy += *incy; /* L30: */ } i__2 = kk + j - 1; i__3 = kk + j - 1; i__4 = jx; bli_csets( (bli_creal(x[i__4]) * bli_creal(temp1) - bli_cimag(x[i__4]) * bli_cimag(temp1)), (bli_creal(x[i__4]) * bli_cimag(temp1) + bli_cimag(x[i__4]) * bli_creal(temp1)), q__2 ); i__5 = jy; bli_csets( (bli_creal(y[i__5]) * bli_creal(temp2) - bli_cimag(y[i__5]) * bli_cimag(temp2)), (bli_creal(y[i__5]) * bli_cimag(temp2) + bli_cimag(y[i__5]) * bli_creal(temp2)), q__3 ); bli_csets( (bli_creal(q__2) + bli_creal(q__3)), (bli_cimag(q__2) + bli_cimag(q__3)), q__1 ); r__1 = bli_creal(ap[i__3]) + bli_creal(q__1); bli_csets( (r__1), (0.f), ap[i__2] ); } else { i__2 = kk + j - 1; i__3 = kk + j - 1; r__1 = bli_creal(ap[i__3]); bli_csets( (r__1), (0.f), ap[i__2] ); } jx += *incx; jy += *incy; kk += j; /* L40: */ } } } else { /* Form A when lower triangle is stored in AP. */ if (*incx == 1 && *incy == 1) { i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = j; i__3 = j; if (bli_creal(x[i__2]) != 0.f || bli_cimag(x[i__2]) != 0.f || (bli_creal(y[i__3]) != 0.f || bli_cimag(y[i__3]) != 0.f)) { bla_r_cnjg(&q__2, &y[j]); bli_csets( (bli_creal(*alpha) * bli_creal(q__2) - bli_cimag(*alpha) * bli_cimag(q__2)), (bli_creal(*alpha) * bli_cimag(q__2) + bli_cimag(*alpha) * bli_creal(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp1 ); i__2 = j; bli_csets( (bli_creal(*alpha) * bli_creal(x[i__2]) - bli_cimag(*alpha) * bli_cimag(x[i__2])), (bli_creal(*alpha) * bli_cimag(x[i__2]) + bli_cimag(*alpha) * bli_creal(x[i__2])), q__2 ); bla_r_cnjg(&q__1, &q__2); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp2 ); i__2 = kk; i__3 = kk; i__4 = j; bli_csets( (bli_creal(x[i__4]) * bli_creal(temp1) - bli_cimag(x[i__4]) * bli_cimag(temp1)), (bli_creal(x[i__4]) * bli_cimag(temp1) + bli_cimag(x[i__4]) * bli_creal(temp1)), q__2 ); i__5 = j; bli_csets( (bli_creal(y[i__5]) * bli_creal(temp2) - bli_cimag(y[i__5]) * bli_cimag(temp2)), (bli_creal(y[i__5]) * bli_cimag(temp2) + bli_cimag(y[i__5]) * bli_creal(temp2)), q__3 ); bli_csets( (bli_creal(q__2) + bli_creal(q__3)), (bli_cimag(q__2) + bli_cimag(q__3)), q__1 ); r__1 = bli_creal(ap[i__3]) + bli_creal(q__1); bli_csets( (r__1), (0.f), ap[i__2] ); k = kk + 1; i__2 = *n; for (i__ = j + 1; i__ <= i__2; ++i__) { i__3 = k; i__4 = k; i__5 = i__; bli_csets( (bli_creal(x[i__5]) * bli_creal(temp1) - bli_cimag(x[i__5]) * bli_cimag(temp1)), (bli_creal(x[i__5]) * bli_cimag(temp1) + bli_cimag(x[i__5]) * bli_creal(temp1)), q__3 ); bli_csets( (bli_creal(ap[i__4]) + bli_creal(q__3)), (bli_cimag(ap[i__4]) + bli_cimag(q__3)), q__2 ); i__6 = i__; bli_csets( (bli_creal(y[i__6]) * bli_creal(temp2) - bli_cimag(y[i__6]) * bli_cimag(temp2)), (bli_creal(y[i__6]) * bli_cimag(temp2) + bli_cimag(y[i__6]) * bli_creal(temp2)), q__4 ); bli_csets( (bli_creal(q__2) + bli_creal(q__4)), (bli_cimag(q__2) + bli_cimag(q__4)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), ap[i__3] ); ++k; /* L50: */ } } else { i__2 = kk; i__3 = kk; r__1 = bli_creal(ap[i__3]); bli_csets( (r__1), (0.f), ap[i__2] ); } kk = kk + *n - j + 1; /* L60: */ } } else { i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = jx; i__3 = jy; if (bli_creal(x[i__2]) != 0.f || bli_cimag(x[i__2]) != 0.f || (bli_creal(y[i__3]) != 0.f || bli_cimag(y[i__3]) != 0.f)) { bla_r_cnjg(&q__2, &y[jy]); bli_csets( (bli_creal(*alpha) * bli_creal(q__2) - bli_cimag(*alpha) * bli_cimag(q__2)), (bli_creal(*alpha) * bli_cimag(q__2) + bli_cimag(*alpha) * bli_creal(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp1 ); i__2 = jx; bli_csets( (bli_creal(*alpha) * bli_creal(x[i__2]) - bli_cimag(*alpha) * bli_cimag(x[i__2])), (bli_creal(*alpha) * bli_cimag(x[i__2]) + bli_cimag(*alpha) * bli_creal(x[i__2])), q__2 ); bla_r_cnjg(&q__1, &q__2); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp2 ); i__2 = kk; i__3 = kk; i__4 = jx; bli_csets( (bli_creal(x[i__4]) * bli_creal(temp1) - bli_cimag(x[i__4]) * bli_cimag(temp1)), (bli_creal(x[i__4]) * bli_cimag(temp1) + bli_cimag(x[i__4]) * bli_creal(temp1)), q__2 ); i__5 = jy; bli_csets( (bli_creal(y[i__5]) * bli_creal(temp2) - bli_cimag(y[i__5]) * bli_cimag(temp2)), (bli_creal(y[i__5]) * bli_cimag(temp2) + bli_cimag(y[i__5]) * bli_creal(temp2)), q__3 ); bli_csets( (bli_creal(q__2) + bli_creal(q__3)), (bli_cimag(q__2) + bli_cimag(q__3)), q__1 ); r__1 = bli_creal(ap[i__3]) + bli_creal(q__1); bli_csets( (r__1), (0.f), ap[i__2] ); ix = jx; iy = jy; i__2 = kk + *n - j; for (k = kk + 1; k <= i__2; ++k) { ix += *incx; iy += *incy; i__3 = k; i__4 = k; i__5 = ix; bli_csets( (bli_creal(x[i__5]) * bli_creal(temp1) - bli_cimag(x[i__5]) * bli_cimag(temp1)), (bli_creal(x[i__5]) * bli_cimag(temp1) + bli_cimag(x[i__5]) * bli_creal(temp1)), q__3 ); bli_csets( (bli_creal(ap[i__4]) + bli_creal(q__3)), (bli_cimag(ap[i__4]) + bli_cimag(q__3)), q__2 ); i__6 = iy; bli_csets( (bli_creal(y[i__6]) * bli_creal(temp2) - bli_cimag(y[i__6]) * bli_cimag(temp2)), (bli_creal(y[i__6]) * bli_cimag(temp2) + bli_cimag(y[i__6]) * bli_creal(temp2)), q__4 ); bli_csets( (bli_creal(q__2) + bli_creal(q__4)), (bli_cimag(q__2) + bli_cimag(q__4)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), ap[i__3] ); /* L70: */ } } else { i__2 = kk; i__3 = kk; r__1 = bli_creal(ap[i__3]); bli_csets( (r__1), (0.f), ap[i__2] ); } jx += *incx; jy += *incy; kk = kk + *n - j + 1; /* L80: */ } } } return 0; /* End of CHPR2 . */ } /* chpr2_ */ /* zhpr2.f -- translated by f2c (version 19991025). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ /* Subroutine */ int PASTEF77(z,hpr2)(const bla_character *uplo, const bla_integer *n, const bla_dcomplex *alpha, const bla_dcomplex *x, const bla_integer *incx, const bla_dcomplex *y, const bla_integer *incy, bla_dcomplex *ap) { /* System generated locals */ bla_integer i__1, i__2, i__3, i__4, i__5, i__6; bla_double d__1; bla_dcomplex z__1, z__2, z__3, z__4; /* Builtin functions */ //void bla_d_cnjg(bla_dcomplex *, bla_dcomplex *); /* Local variables */ bla_integer info; bla_dcomplex temp1, temp2; bla_integer i__, j, k; //extern bla_logical PASTEF770(lsame)(bla_character *, bla_character *, ftnlen, ftnlen); bla_integer kk, ix, iy, jx = 0, jy = 0, kx = 0, ky = 0; //extern /* Subroutine */ int PASTEF770(xerbla)(bla_character *, bla_integer *, ftnlen); /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* ZHPR2 performs the hermitian rank 2 operation */ /* A := alpha*x*conjg( y' ) + conjg( alpha )*y*conjg( x' ) + A, */ /* where alpha is a scalar, x and y are n element vectors and A is an */ /* n by n hermitian matrix, supplied in packed form. */ /* Parameters */ /* ========== */ /* UPLO - CHARACTER*1. */ /* On entry, UPLO specifies whether the upper or lower */ /* triangular part of the matrix A is supplied in the packed */ /* array AP as follows: */ /* UPLO = 'U' or 'u' The upper triangular part of A is */ /* supplied in AP. */ /* UPLO = 'L' or 'l' The lower triangular part of A is */ /* supplied in AP. */ /* Unchanged on exit. */ /* N - INTEGER. */ /* On entry, N specifies the order of the matrix A. */ /* N must be at least zero. */ /* Unchanged on exit. */ /* ALPHA - COMPLEX*16 . */ /* On entry, ALPHA specifies the scalar alpha. */ /* Unchanged on exit. */ /* X - COMPLEX*16 array of dimension at least */ /* ( 1 + ( n - 1 )*abs( INCX ) ). */ /* Before entry, the incremented array X must contain the n */ /* element vector x. */ /* Unchanged on exit. */ /* INCX - INTEGER. */ /* On entry, INCX specifies the increment for the elements of */ /* X. INCX must not be zero. */ /* Unchanged on exit. */ /* Y - COMPLEX*16 array of dimension at least */ /* ( 1 + ( n - 1 )*abs( INCY ) ). */ /* Before entry, the incremented array Y must contain the n */ /* element vector y. */ /* Unchanged on exit. */ /* INCY - INTEGER. */ /* On entry, INCY specifies the increment for the elements of */ /* Y. INCY must not be zero. */ /* Unchanged on exit. */ /* AP - COMPLEX*16 array of DIMENSION at least */ /* ( ( n*( n + 1 ) )/2 ). */ /* Before entry with UPLO = 'U' or 'u', the array AP must */ /* contain the upper triangular part of the hermitian matrix */ /* packed sequentially, column by column, so that AP( 1 ) */ /* contains a( 1, 1 ), AP( 2 ) and AP( 3 ) contain a( 1, 2 ) */ /* and a( 2, 2 ) respectively, and so on. On exit, the array */ /* AP is overwritten by the upper triangular part of the */ /* updated matrix. */ /* Before entry with UPLO = 'L' or 'l', the array AP must */ /* contain the lower triangular part of the hermitian matrix */ /* packed sequentially, column by column, so that AP( 1 ) */ /* contains a( 1, 1 ), AP( 2 ) and AP( 3 ) contain a( 2, 1 ) */ /* and a( 3, 1 ) respectively, and so on. On exit, the array */ /* AP is overwritten by the lower triangular part of the */ /* updated matrix. */ /* Note that the imaginary parts of the diagonal elements need */ /* not be set, they are assumed to be zero, and on exit they */ /* are set to zero. */ /* Level 2 Blas routine. */ /* -- Written on 22-October-1986. */ /* Jack Dongarra, Argonne National Lab. */ /* Jeremy Du Croz, Nag Central Office. */ /* Sven Hammarling, Nag Central Office. */ /* Richard Hanson, Sandia National Labs. */ /* .. Parameters .. */ /* .. Local Scalars .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. */ /* .. Executable Statements .. */ /* Test the input parameters. */ /* Parameter adjustments */ --ap; --y; --x; /* Function Body */ info = 0; if (! PASTEF770(lsame)(uplo, "U", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(uplo, "L", ( ftnlen)1, (ftnlen)1)) { info = 1; } else if (*n < 0) { info = 2; } else if (*incx == 0) { info = 5; } else if (*incy == 0) { info = 7; } if (info != 0) { PASTEF770(xerbla)("ZHPR2 ", &info, (ftnlen)6); return 0; } /* Quick return if possible. */ if (*n == 0 || (bli_zreal(*alpha) == 0. && bli_zimag(*alpha) == 0.)) { return 0; } /* Set up the start points in X and Y if the increments are not both */ /* unity. */ if (*incx != 1 || *incy != 1) { if (*incx > 0) { kx = 1; } else { kx = 1 - (*n - 1) * *incx; } if (*incy > 0) { ky = 1; } else { ky = 1 - (*n - 1) * *incy; } jx = kx; jy = ky; } /* Start the operations. In this version the elements of the array AP */ /* are accessed sequentially with one pass through AP. */ kk = 1; if (PASTEF770(lsame)(uplo, "U", (ftnlen)1, (ftnlen)1)) { /* Form A when upper triangle is stored in AP. */ if (*incx == 1 && *incy == 1) { i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = j; i__3 = j; if (bli_zreal(x[i__2]) != 0. || bli_zimag(x[i__2]) != 0. || (bli_zreal(y[i__3]) != 0. || bli_zimag(y[i__3]) != 0.)) { bla_d_cnjg(&z__2, &y[j]); bli_zsets( (bli_zreal(*alpha) * bli_zreal(z__2) - bli_zimag(*alpha) * bli_zimag(z__2)), (bli_zreal(*alpha) * bli_zimag(z__2) + bli_zimag(*alpha) * bli_zreal(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp1 ); i__2 = j; bli_zsets( (bli_zreal(*alpha) * bli_zreal(x[i__2]) - bli_zimag(*alpha) * bli_zimag(x[i__2])), (bli_zreal(*alpha) * bli_zimag(x[i__2]) + bli_zimag(*alpha) * bli_zreal(x[i__2])), z__2 ); bla_d_cnjg(&z__1, &z__2); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp2 ); k = kk; i__2 = j - 1; for (i__ = 1; i__ <= i__2; ++i__) { i__3 = k; i__4 = k; i__5 = i__; bli_zsets( (bli_zreal(x[i__5]) * bli_zreal(temp1) - bli_zimag(x[i__5]) * bli_zimag(temp1)), (bli_zreal(x[i__5]) * bli_zimag(temp1) + bli_zimag(x[i__5]) * bli_zreal(temp1)), z__3 ); bli_zsets( (bli_zreal(ap[i__4]) + bli_zreal(z__3)), (bli_zimag(ap[i__4]) + bli_zimag(z__3)), z__2 ); i__6 = i__; bli_zsets( (bli_zreal(y[i__6]) * bli_zreal(temp2) - bli_zimag(y[i__6]) * bli_zimag(temp2)), (bli_zreal(y[i__6]) * bli_zimag(temp2) + bli_zimag(y[i__6]) * bli_zreal(temp2)), z__4 ); bli_zsets( (bli_zreal(z__2) + bli_zreal(z__4)), (bli_zimag(z__2) + bli_zimag(z__4)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), ap[i__3] ); ++k; /* L10: */ } i__2 = kk + j - 1; i__3 = kk + j - 1; i__4 = j; bli_zsets( (bli_zreal(x[i__4]) * bli_zreal(temp1) - bli_zimag(x[i__4]) * bli_zimag(temp1)), (bli_zreal(x[i__4]) * bli_zimag(temp1) + bli_zimag(x[i__4]) * bli_zreal(temp1)), z__2 ); i__5 = j; bli_zsets( (bli_zreal(y[i__5]) * bli_zreal(temp2) - bli_zimag(y[i__5]) * bli_zimag(temp2)), (bli_zreal(y[i__5]) * bli_zimag(temp2) + bli_zimag(y[i__5]) * bli_zreal(temp2)), z__3 ); bli_zsets( (bli_zreal(z__2) + bli_zreal(z__3)), (bli_zimag(z__2) + bli_zimag(z__3)), z__1 ); d__1 = bli_zreal(ap[i__3]) + bli_zreal(z__1); bli_zsets( (d__1), (0.), ap[i__2] ); } else { i__2 = kk + j - 1; i__3 = kk + j - 1; d__1 = bli_zreal(ap[i__3]); bli_zsets( (d__1), (0.), ap[i__2] ); } kk += j; /* L20: */ } } else { i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = jx; i__3 = jy; if (bli_zreal(x[i__2]) != 0. || bli_zimag(x[i__2]) != 0. || (bli_zreal(y[i__3]) != 0. || bli_zimag(y[i__3]) != 0.)) { bla_d_cnjg(&z__2, &y[jy]); bli_zsets( (bli_zreal(*alpha) * bli_zreal(z__2) - bli_zimag(*alpha) * bli_zimag(z__2)), (bli_zreal(*alpha) * bli_zimag(z__2) + bli_zimag(*alpha) * bli_zreal(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp1 ); i__2 = jx; bli_zsets( (bli_zreal(*alpha) * bli_zreal(x[i__2]) - bli_zimag(*alpha) * bli_zimag(x[i__2])), (bli_zreal(*alpha) * bli_zimag(x[i__2]) + bli_zimag(*alpha) * bli_zreal(x[i__2])), z__2 ); bla_d_cnjg(&z__1, &z__2); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp2 ); ix = kx; iy = ky; i__2 = kk + j - 2; for (k = kk; k <= i__2; ++k) { i__3 = k; i__4 = k; i__5 = ix; bli_zsets( (bli_zreal(x[i__5]) * bli_zreal(temp1) - bli_zimag(x[i__5]) * bli_zimag(temp1)), (bli_zreal(x[i__5]) * bli_zimag(temp1) + bli_zimag(x[i__5]) * bli_zreal(temp1)), z__3 ); bli_zsets( (bli_zreal(ap[i__4]) + bli_zreal(z__3)), (bli_zimag(ap[i__4]) + bli_zimag(z__3)), z__2 ); i__6 = iy; bli_zsets( (bli_zreal(y[i__6]) * bli_zreal(temp2) - bli_zimag(y[i__6]) * bli_zimag(temp2)), (bli_zreal(y[i__6]) * bli_zimag(temp2) + bli_zimag(y[i__6]) * bli_zreal(temp2)), z__4 ); bli_zsets( (bli_zreal(z__2) + bli_zreal(z__4)), (bli_zimag(z__2) + bli_zimag(z__4)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), ap[i__3] ); ix += *incx; iy += *incy; /* L30: */ } i__2 = kk + j - 1; i__3 = kk + j - 1; i__4 = jx; bli_zsets( (bli_zreal(x[i__4]) * bli_zreal(temp1) - bli_zimag(x[i__4]) * bli_zimag(temp1)), (bli_zreal(x[i__4]) * bli_zimag(temp1) + bli_zimag(x[i__4]) * bli_zreal(temp1)), z__2 ); i__5 = jy; bli_zsets( (bli_zreal(y[i__5]) * bli_zreal(temp2) - bli_zimag(y[i__5]) * bli_zimag(temp2)), (bli_zreal(y[i__5]) * bli_zimag(temp2) + bli_zimag(y[i__5]) * bli_zreal(temp2)), z__3 ); bli_zsets( (bli_zreal(z__2) + bli_zreal(z__3)), (bli_zimag(z__2) + bli_zimag(z__3)), z__1 ); d__1 = bli_zreal(ap[i__3]) + bli_zreal(z__1); bli_zsets( (d__1), (0.), ap[i__2] ); } else { i__2 = kk + j - 1; i__3 = kk + j - 1; d__1 = bli_zreal(ap[i__3]); bli_zsets( (d__1), (0.), ap[i__2] ); } jx += *incx; jy += *incy; kk += j; /* L40: */ } } } else { /* Form A when lower triangle is stored in AP. */ if (*incx == 1 && *incy == 1) { i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = j; i__3 = j; if (bli_zreal(x[i__2]) != 0. || bli_zimag(x[i__2]) != 0. || (bli_zreal(y[i__3]) != 0. || bli_zimag(y[i__3]) != 0.)) { bla_d_cnjg(&z__2, &y[j]); bli_zsets( (bli_zreal(*alpha) * bli_zreal(z__2) - bli_zimag(*alpha) * bli_zimag(z__2)), (bli_zreal(*alpha) * bli_zimag(z__2) + bli_zimag(*alpha) * bli_zreal(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp1 ); i__2 = j; bli_zsets( (bli_zreal(*alpha) * bli_zreal(x[i__2]) - bli_zimag(*alpha) * bli_zimag(x[i__2])), (bli_zreal(*alpha) * bli_zimag(x[i__2]) + bli_zimag(*alpha) * bli_zreal(x[i__2])), z__2 ); bla_d_cnjg(&z__1, &z__2); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp2 ); i__2 = kk; i__3 = kk; i__4 = j; bli_zsets( (bli_zreal(x[i__4]) * bli_zreal(temp1) - bli_zimag(x[i__4]) * bli_zimag(temp1)), (bli_zreal(x[i__4]) * bli_zimag(temp1) + bli_zimag(x[i__4]) * bli_zreal(temp1)), z__2 ); i__5 = j; bli_zsets( (bli_zreal(y[i__5]) * bli_zreal(temp2) - bli_zimag(y[i__5]) * bli_zimag(temp2)), (bli_zreal(y[i__5]) * bli_zimag(temp2) + bli_zimag(y[i__5]) * bli_zreal(temp2)), z__3 ); bli_zsets( (bli_zreal(z__2) + bli_zreal(z__3)), (bli_zimag(z__2) + bli_zimag(z__3)), z__1 ); d__1 = bli_zreal(ap[i__3]) + bli_zreal(z__1); bli_zsets( (d__1), (0.), ap[i__2] ); k = kk + 1; i__2 = *n; for (i__ = j + 1; i__ <= i__2; ++i__) { i__3 = k; i__4 = k; i__5 = i__; bli_zsets( (bli_zreal(x[i__5]) * bli_zreal(temp1) - bli_zimag(x[i__5]) * bli_zimag(temp1)), (bli_zreal(x[i__5]) * bli_zimag(temp1) + bli_zimag(x[i__5]) * bli_zreal(temp1)), z__3 ); bli_zsets( (bli_zreal(ap[i__4]) + bli_zreal(z__3)), (bli_zimag(ap[i__4]) + bli_zimag(z__3)), z__2 ); i__6 = i__; bli_zsets( (bli_zreal(y[i__6]) * bli_zreal(temp2) - bli_zimag(y[i__6]) * bli_zimag(temp2)), (bli_zreal(y[i__6]) * bli_zimag(temp2) + bli_zimag(y[i__6]) * bli_zreal(temp2)), z__4 ); bli_zsets( (bli_zreal(z__2) + bli_zreal(z__4)), (bli_zimag(z__2) + bli_zimag(z__4)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), ap[i__3] ); ++k; /* L50: */ } } else { i__2 = kk; i__3 = kk; d__1 = bli_zreal(ap[i__3]); bli_zsets( (d__1), (0.), ap[i__2] ); } kk = kk + *n - j + 1; /* L60: */ } } else { i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = jx; i__3 = jy; if (bli_zreal(x[i__2]) != 0. || bli_zimag(x[i__2]) != 0. || (bli_zreal(y[i__3]) != 0. || bli_zimag(y[i__3]) != 0.)) { bla_d_cnjg(&z__2, &y[jy]); bli_zsets( (bli_zreal(*alpha) * bli_zreal(z__2) - bli_zimag(*alpha) * bli_zimag(z__2)), (bli_zreal(*alpha) * bli_zimag(z__2) + bli_zimag(*alpha) * bli_zreal(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp1 ); i__2 = jx; bli_zsets( (bli_zreal(*alpha) * bli_zreal(x[i__2]) - bli_zimag(*alpha) * bli_zimag(x[i__2])), (bli_zreal(*alpha) * bli_zimag(x[i__2]) + bli_zimag(*alpha) * bli_zreal(x[i__2])), z__2 ); bla_d_cnjg(&z__1, &z__2); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp2 ); i__2 = kk; i__3 = kk; i__4 = jx; bli_zsets( (bli_zreal(x[i__4]) * bli_zreal(temp1) - bli_zimag(x[i__4]) * bli_zimag(temp1)), (bli_zreal(x[i__4]) * bli_zimag(temp1) + bli_zimag(x[i__4]) * bli_zreal(temp1)), z__2 ); i__5 = jy; bli_zsets( (bli_zreal(y[i__5]) * bli_zreal(temp2) - bli_zimag(y[i__5]) * bli_zimag(temp2)), (bli_zreal(y[i__5]) * bli_zimag(temp2) + bli_zimag(y[i__5]) * bli_zreal(temp2)), z__3 ); bli_zsets( (bli_zreal(z__2) + bli_zreal(z__3)), (bli_zimag(z__2) + bli_zimag(z__3)), z__1 ); d__1 = bli_zreal(ap[i__3]) + bli_zreal(z__1); bli_zsets( (d__1), (0.), ap[i__2] ); ix = jx; iy = jy; i__2 = kk + *n - j; for (k = kk + 1; k <= i__2; ++k) { ix += *incx; iy += *incy; i__3 = k; i__4 = k; i__5 = ix; bli_zsets( (bli_zreal(x[i__5]) * bli_zreal(temp1) - bli_zimag(x[i__5]) * bli_zimag(temp1)), (bli_zreal(x[i__5]) * bli_zimag(temp1) + bli_zimag(x[i__5]) * bli_zreal(temp1)), z__3 ); bli_zsets( (bli_zreal(ap[i__4]) + bli_zreal(z__3)), (bli_zimag(ap[i__4]) + bli_zimag(z__3)), z__2 ); i__6 = iy; bli_zsets( (bli_zreal(y[i__6]) * bli_zreal(temp2) - bli_zimag(y[i__6]) * bli_zimag(temp2)), (bli_zreal(y[i__6]) * bli_zimag(temp2) + bli_zimag(y[i__6]) * bli_zreal(temp2)), z__4 ); bli_zsets( (bli_zreal(z__2) + bli_zreal(z__4)), (bli_zimag(z__2) + bli_zimag(z__4)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), ap[i__3] ); /* L70: */ } } else { i__2 = kk; i__3 = kk; d__1 = bli_zreal(ap[i__3]); bli_zsets( (d__1), (0.), ap[i__2] ); } jx += *incx; jy += *incy; kk = kk + *n - j + 1; /* L80: */ } } } return 0; /* End of ZHPR2 . */ } /* zhpr2_ */ #endif blis-0.9.0/frame/compat/f2c/bla_hpr2.h000066400000000000000000000041641422157504600173550ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifdef BLIS_ENABLE_BLAS BLIS_EXPORT_BLAS int PASTEF77(c,hpr2)(const bla_character *uplo, const bla_integer *n, const bla_scomplex *alpha, const bla_scomplex *x, const bla_integer *incx, const bla_scomplex *y, const bla_integer *incy, bla_scomplex *ap); BLIS_EXPORT_BLAS int PASTEF77(z,hpr2)(const bla_character *uplo, const bla_integer *n, const bla_dcomplex *alpha, const bla_dcomplex *x, const bla_integer *incx, const bla_dcomplex *y, const bla_integer *incy, bla_dcomplex *ap); #endif blis-0.9.0/frame/compat/f2c/bla_lsame.c000066400000000000000000000107621422157504600175770ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #ifdef BLIS_ENABLE_BLAS /* lsame.f -- translated by f2c (version 19991025). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ #ifdef LAPACK_ILP64 long PASTEF770(lsame)(const char *ca, const char *cb, long ca_len, long cb_len) #else int PASTEF770(lsame)(const char *ca, const char *cb, int ca_len, int cb_len) #endif { /* System generated locals */ bla_logical ret_val; /* Local variables */ bla_integer inta, intb, zcode; /* -- LAPACK auxiliary routine (version 2.0) -- */ /* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., */ /* Courant Institute, Argonne National Lab, and Rice University */ /* January 31, 1994 */ /* .. Scalar Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* LSAME returns .TRUE. if CA is the same letter as CB regardless of */ /* case. */ /* Arguments */ /* ========= */ /* CA (input) CHARACTER*1 */ /* CB (input) CHARACTER*1 */ /* CA and CB specify the single bla_characters to be compared. */ /* ===================================================================== */ /* .. Intrinsic Functions .. */ /* .. */ /* .. Local Scalars .. */ /* .. */ /* .. Executable Statements .. */ /* Test if the bla_characters are equal */ ret_val = *(unsigned char *)ca == *(unsigned char *)cb; if (ret_val) { return ret_val; } /* Now test for equivalence if both bla_characters are alphabetic. */ zcode = 'Z'; /* Use 'Z' rather than 'A' so that ASCII can be detected on Prime */ /* machines, on which ICHAR returns a value with bit 8 set. */ /* ICHAR('A') on Prime machines returns 193 which is the same as */ /* ICHAR('A') on an EBCDIC machine. */ inta = *(unsigned char *)ca; intb = *(unsigned char *)cb; if (zcode == 90 || zcode == 122) { /* ASCII is assumed - ZCODE is the ASCII code of either lower or */ /* upper case 'Z'. */ if (inta >= 97 && inta <= 122) { inta += -32; } if (intb >= 97 && intb <= 122) { intb += -32; } } else if (zcode == 233 || zcode == 169) { /* EBCDIC is assumed - ZCODE is the EBCDIC code of either lower or */ /* upper case 'Z'. */ if ((inta >= 129 && inta <= 137) || (inta >= 145 && inta <= 153) || (inta >= 162 && inta <= 169)) { inta += 64; } if ((intb >= 129 && intb <= 137) || (intb >= 145 && intb <= 153) || (intb >= 162 && intb <= 169)) { intb += 64; } } else if (zcode == 218 || zcode == 250) { /* ASCII is assumed, on Prime machines - ZCODE is the ASCII code */ /* plus 128 of either lower or upper case 'Z'. */ if (inta >= 225 && inta <= 250) { inta += -32; } if (intb >= 225 && intb <= 250) { intb += -32; } } ret_val = inta == intb; /* RETURN */ /* End of LSAME */ return ret_val; } /* lsame */ #endif blis-0.9.0/frame/compat/f2c/bla_lsame.h000066400000000000000000000035731422157504600176060ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifdef BLIS_ENABLE_BLAS #ifdef LAPACK_ILP64 long PASTEF770(lsame)(const char *ca, const char *cb, long ca_len, long cb_len); #else BLIS_EXPORT_BLAS int PASTEF770(lsame)(const char *ca, const char *cb, int ca_len, int cb_len); #endif #endif blis-0.9.0/frame/compat/f2c/bla_rot.c000066400000000000000000000244561422157504600173070ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #ifdef BLIS_ENABLE_BLAS /* srot.f -- translated by f2c (version 19991025). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ /* Subroutine */ int PASTEF77(s,rot)(const bla_integer *n, bla_real *sx, const bla_integer *incx, bla_real *sy, const bla_integer *incy, const bla_real *c__, const bla_real *s) { /* System generated locals */ bla_integer i__1; /* Local variables */ bla_integer i__; bla_real stemp; bla_integer ix, iy; /* applies a plane rotation. */ /* jack dongarra, linpack, 3/11/78. */ /* modified 12/3/93, array(1) declarations changed to array(*) */ /* Parameter adjustments */ --sy; --sx; /* Function Body */ if (*n <= 0) { return 0; } if (*incx == 1 && *incy == 1) { goto L20; } /* code for unequal increments or equal increments not equal */ /* to 1 */ ix = 1; iy = 1; if (*incx < 0) { ix = (-(*n) + 1) * *incx + 1; } if (*incy < 0) { iy = (-(*n) + 1) * *incy + 1; } i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { stemp = *c__ * sx[ix] + *s * sy[iy]; sy[iy] = *c__ * sy[iy] - *s * sx[ix]; sx[ix] = stemp; ix += *incx; iy += *incy; /* L10: */ } return 0; /* code for both increments equal to 1 */ L20: i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { stemp = *c__ * sx[i__] + *s * sy[i__]; sy[i__] = *c__ * sy[i__] - *s * sx[i__]; sx[i__] = stemp; /* L30: */ } return 0; } /* srot_ */ /* drot.f -- translated by f2c (version 19991025). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ /* Subroutine */ int PASTEF77(d,rot)(const bla_integer *n, bla_double *dx, const bla_integer *incx, bla_double *dy, const bla_integer *incy, const bla_double *c__, const bla_double *s) { /* System generated locals */ bla_integer i__1; /* Local variables */ bla_integer i__; bla_double dtemp; bla_integer ix, iy; /* applies a plane rotation. */ /* jack dongarra, linpack, 3/11/78. */ /* modified 12/3/93, array(1) declarations changed to array(*) */ /* Parameter adjustments */ --dy; --dx; /* Function Body */ if (*n <= 0) { return 0; } if (*incx == 1 && *incy == 1) { goto L20; } /* code for unequal increments or equal increments not equal */ /* to 1 */ ix = 1; iy = 1; if (*incx < 0) { ix = (-(*n) + 1) * *incx + 1; } if (*incy < 0) { iy = (-(*n) + 1) * *incy + 1; } i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { dtemp = *c__ * dx[ix] + *s * dy[iy]; dy[iy] = *c__ * dy[iy] - *s * dx[ix]; dx[ix] = dtemp; ix += *incx; iy += *incy; /* L10: */ } return 0; /* code for both increments equal to 1 */ L20: i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { dtemp = *c__ * dx[i__] + *s * dy[i__]; dy[i__] = *c__ * dy[i__] - *s * dx[i__]; dx[i__] = dtemp; /* L30: */ } return 0; } /* drot_ */ /* csrot.f -- translated by f2c (version 19991025). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ /* Subroutine */ int PASTEF77(cs,rot)(const bla_integer *n, bla_scomplex *cx, const bla_integer *incx, bla_scomplex *cy, const bla_integer *incy, const bla_real *c__, const bla_real *s) { /* System generated locals */ bla_integer i__1, i__2, i__3, i__4; bla_scomplex q__1, q__2, q__3; /* Local variables */ bla_integer i__; bla_scomplex ctemp; bla_integer ix, iy; /* applies a plane rotation, where the cos and sin (c and s) are bla_real */ /* and the vectors cx and cy are complex. */ /* jack dongarra, linpack, 3/11/78. */ /* Parameter adjustments */ --cy; --cx; /* Function Body */ if (*n <= 0) { return 0; } if (*incx == 1 && *incy == 1) { goto L20; } /* code for unequal increments or equal increments not equal */ /* to 1 */ ix = 1; iy = 1; if (*incx < 0) { ix = (-(*n) + 1) * *incx + 1; } if (*incy < 0) { iy = (-(*n) + 1) * *incy + 1; } i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { i__2 = ix; bli_csets( (*c__ * bli_creal(cx[i__2])), (*c__ * bli_cimag(cx[i__2])), q__2 ); i__3 = iy; bli_csets( (*s * bli_creal(cy[i__3])), (*s * bli_cimag(cy[i__3])), q__3 ); bli_csets( (bli_creal(q__2) + bli_creal(q__3)), (bli_cimag(q__2) + bli_cimag(q__3)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), ctemp ); i__2 = iy; i__3 = iy; bli_csets( (*c__ * bli_creal(cy[i__3])), (*c__ * bli_cimag(cy[i__3])), q__2 ); i__4 = ix; bli_csets( (*s * bli_creal(cx[i__4])), (*s * bli_cimag(cx[i__4])), q__3 ); bli_csets( (bli_creal(q__2) - bli_creal(q__3)), (bli_cimag(q__2) - bli_cimag(q__3)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), cy[i__2] ); i__2 = ix; bli_csets( (bli_creal(ctemp)), (bli_cimag(ctemp)), cx[i__2] ); ix += *incx; iy += *incy; /* L10: */ } return 0; /* code for both increments equal to 1 */ L20: i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { i__2 = i__; bli_csets( (*c__ * bli_creal(cx[i__2])), (*c__ * bli_cimag(cx[i__2])), q__2 ); i__3 = i__; bli_csets( (*s * bli_creal(cy[i__3])), (*s * bli_cimag(cy[i__3])), q__3 ); bli_csets( (bli_creal(q__2) + bli_creal(q__3)), (bli_cimag(q__2) + bli_cimag(q__3)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), ctemp ); i__2 = i__; i__3 = i__; bli_csets( (*c__ * bli_creal(cy[i__3])), (*c__ * bli_cimag(cy[i__3])), q__2 ); i__4 = i__; bli_csets( (*s * bli_creal(cx[i__4])), (*s * bli_cimag(cx[i__4])), q__3 ); bli_csets( (bli_creal(q__2) - bli_creal(q__3)), (bli_cimag(q__2) - bli_cimag(q__3)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), cy[i__2] ); i__2 = i__; bli_csets( (bli_creal(ctemp)), (bli_cimag(ctemp)), cx[i__2] ); /* L30: */ } return 0; } /* csrot_ */ /* zdrot.f -- translated by f2c (version 19991025). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ /* Subroutine */ int PASTEF77(zd,rot)(const bla_integer *n, bla_dcomplex *zx, const bla_integer *incx, bla_dcomplex *zy, const bla_integer *incy, const bla_double *c__, const bla_double *s) { /* System generated locals */ bla_integer i__1, i__2, i__3, i__4; bla_dcomplex z__1, z__2, z__3; /* Local variables */ bla_integer i__; bla_dcomplex ztemp; bla_integer ix, iy; /* applies a plane rotation, where the cos and sin (c and s) are */ /* double precision and the vectors zx and zy are double complex. */ /* jack dongarra, linpack, 3/11/78. */ /* Parameter adjustments */ --zy; --zx; /* Function Body */ if (*n <= 0) { return 0; } if (*incx == 1 && *incy == 1) { goto L20; } /* code for unequal increments or equal increments not equal */ /* to 1 */ ix = 1; iy = 1; if (*incx < 0) { ix = (-(*n) + 1) * *incx + 1; } if (*incy < 0) { iy = (-(*n) + 1) * *incy + 1; } i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { i__2 = ix; bli_zsets( (*c__ * bli_zreal(zx[i__2])), (*c__ * bli_zimag(zx[i__2])), z__2 ); i__3 = iy; bli_zsets( (*s * bli_zreal(zy[i__3])), (*s * bli_zimag(zy[i__3])), z__3 ); bli_zsets( (bli_zreal(z__2) + bli_zreal(z__3)), (bli_zimag(z__2) + bli_zimag(z__3)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), ztemp ); i__2 = iy; i__3 = iy; bli_zsets( (*c__ * bli_zreal(zy[i__3])), (*c__ * bli_zimag(zy[i__3])), z__2 ); i__4 = ix; bli_zsets( (*s * bli_zreal(zx[i__4])), (*s * bli_zimag(zx[i__4])), z__3 ); bli_zsets( (bli_zreal(z__2) - bli_zreal(z__3)), (bli_zimag(z__2) - bli_zimag(z__3)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), zy[i__2] ); i__2 = ix; bli_zsets( (bli_zreal(ztemp)), (bli_zimag(ztemp)), zx[i__2] ); ix += *incx; iy += *incy; /* L10: */ } return 0; /* code for both increments equal to 1 */ L20: i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { i__2 = i__; bli_zsets( (*c__ * bli_zreal(zx[i__2])), (*c__ * bli_zimag(zx[i__2])), z__2 ); i__3 = i__; bli_zsets( (*s * bli_zreal(zy[i__3])), (*s * bli_zimag(zy[i__3])), z__3 ); bli_zsets( (bli_zreal(z__2) + bli_zreal(z__3)), (bli_zimag(z__2) + bli_zimag(z__3)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), ztemp ); i__2 = i__; i__3 = i__; bli_zsets( (*c__ * bli_zreal(zy[i__3])), (*c__ * bli_zimag(zy[i__3])), z__2 ); i__4 = i__; bli_zsets( (*s * bli_zreal(zx[i__4])), (*s * bli_zimag(zx[i__4])), z__3 ); bli_zsets( (bli_zreal(z__2) - bli_zreal(z__3)), (bli_zimag(z__2) - bli_zimag(z__3)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), zy[i__2] ); i__2 = i__; bli_zsets( (bli_zreal(ztemp)), (bli_zimag(ztemp)), zx[i__2] ); /* L30: */ } return 0; } /* zdrot_ */ #endif blis-0.9.0/frame/compat/f2c/bla_rot.h000066400000000000000000000046201422157504600173030ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifdef BLIS_ENABLE_BLAS BLIS_EXPORT_BLAS int PASTEF77(s,rot)(const bla_integer *n, bla_real *sx, const bla_integer *incx, bla_real *sy, const bla_integer *incy, const bla_real *c__, const bla_real *s); BLIS_EXPORT_BLAS int PASTEF77(d,rot)(const bla_integer *n, bla_double *dx, const bla_integer *incx, bla_double *dy, const bla_integer *incy, const bla_double *c__, const bla_double *s); BLIS_EXPORT_BLAS int PASTEF77(cs,rot)(const bla_integer *n, bla_scomplex *cx, const bla_integer *incx, bla_scomplex *cy, const bla_integer *incy, const bla_real *c__, const bla_real *s); BLIS_EXPORT_BLAS int PASTEF77(zd,rot)(const bla_integer *n, bla_dcomplex *zx, const bla_integer *incx, bla_dcomplex *zy, const bla_integer *incy, const bla_double *c__, const bla_double *s); #endif blis-0.9.0/frame/compat/f2c/bla_rotg.c000066400000000000000000000175331422157504600174540ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #ifdef BLIS_ENABLE_BLAS /* srotg.f -- translated by f2c (version 19991025). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ /* Table of constant values */ static bla_real sc_b4 = 1.f; /* Subroutine */ int PASTEF77(s,rotg)(bla_real *sa, bla_real *sb, bla_real *c__, bla_real *s) { /* System generated locals */ bla_real r__1, r__2; /* Builtin functions */ //double sqrt(bla_double), bla_r_sign(bla_real *, bla_real *); /* Local variables */ bla_real r__, scale, z__, roe; /* construct givens plane rotation. */ /* jack dongarra, linpack, 3/11/78. */ roe = *sb; if (bli_fabs(*sa) > bli_fabs(*sb)) { roe = *sa; } scale = bli_fabs(*sa) + bli_fabs(*sb); if (scale != 0.f) { goto L10; } *c__ = 1.f; *s = 0.f; r__ = 0.f; z__ = 0.f; goto L20; L10: /* Computing 2nd power */ r__1 = *sa / scale; /* Computing 2nd power */ r__2 = *sb / scale; r__ = scale * sqrt(r__1 * r__1 + r__2 * r__2); r__ = bla_r_sign(&sc_b4, &roe) * r__; *c__ = *sa / r__; *s = *sb / r__; z__ = 1.f; if (bli_fabs(*sa) > bli_fabs(*sb)) { z__ = *s; } if (bli_fabs(*sb) >= bli_fabs(*sa) && *c__ != 0.f) { z__ = 1.f / *c__; } L20: *sa = r__; *sb = z__; return 0; } /* srotg_ */ /* drotg.f -- translated by f2c (version 19991025). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ /* Table of constant values */ static bla_double dc_b4 = 1.; /* Subroutine */ int PASTEF77(d,rotg)(bla_double *da, bla_double *db, bla_double *c__, bla_double *s) { /* System generated locals */ bla_double d__1, d__2; /* Builtin functions */ //double sqrt(bla_double), bla_d_sign(bla_double *, bla_double *); /* Local variables */ bla_double r__, scale, z__, roe; /* construct givens plane rotation. */ /* jack dongarra, linpack, 3/11/78. */ roe = *db; if (bli_fabs(*da) > bli_fabs(*db)) { roe = *da; } scale = bli_fabs(*da) + bli_fabs(*db); if (scale != 0.) { goto L10; } *c__ = 1.; *s = 0.; r__ = 0.; z__ = 0.; goto L20; L10: /* Computing 2nd power */ d__1 = *da / scale; /* Computing 2nd power */ d__2 = *db / scale; r__ = scale * sqrt(d__1 * d__1 + d__2 * d__2); r__ = bla_d_sign(&dc_b4, &roe) * r__; *c__ = *da / r__; *s = *db / r__; z__ = 1.; if (bli_fabs(*da) > bli_fabs(*db)) { z__ = *s; } if (bli_fabs(*db) >= bli_fabs(*da) && *c__ != 0.) { z__ = 1. / *c__; } L20: *da = r__; *db = z__; return 0; } /* drotg_ */ /* crotg.f -- translated by f2c (version 19991025). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ /* Subroutine */ int PASTEF77(c,rotg)(bla_scomplex *ca, bla_scomplex *cb, bla_real *c__, bla_scomplex *s) { /* System generated locals */ bla_real r__1, r__2; bla_scomplex q__1, q__2, q__3; /* Builtin functions */ //double bla_c_abs(bla_scomplex *), sqrt(bla_double); //void bla_r_cnjg(bla_scomplex *, bla_scomplex *); /* Local variables */ bla_real norm; bla_scomplex alpha; bla_real scale; if (bla_c_abs(ca) != 0.f) { goto L10; } *c__ = 0.f; bli_csets( 1.f, 0.f, *s ); bli_csets( bli_creal(*cb), bli_cimag(*cb), *ca ); goto L20; L10: scale = bla_c_abs(ca) + bla_c_abs(cb); bli_csets( (bli_creal(*ca) / scale), (bli_cimag(*ca) / scale), q__1 ); /* Computing 2nd power */ r__1 = bla_c_abs(&q__1); bli_csets( (bli_creal(*cb) / scale), (bli_cimag(*cb) / scale), q__2 ); /* Computing 2nd power */ r__2 = bla_c_abs(&q__2); norm = scale * sqrt(r__1 * r__1 + r__2 * r__2); r__1 = bla_c_abs(ca); bli_csets( (bli_creal(*ca) / r__1), (bli_cimag(*ca) / r__1), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), alpha ); *c__ = bla_c_abs(ca) / norm; bla_r_cnjg(&q__3, cb); bli_csets( (bli_creal(alpha) * bli_creal(q__3) - bli_cimag(alpha) * bli_cimag(q__3)), (bli_creal(alpha) * bli_cimag(q__3) + bli_cimag(alpha) * bli_creal(q__3)), q__2 ); bli_csets( (bli_creal(q__2) / norm), (bli_cimag(q__2) / norm), q__1 ); bli_csets( bli_creal(q__1), bli_cimag(q__1), *s ); bli_csets( (norm * bli_creal(alpha)), (norm * bli_cimag(alpha)), q__1 ); bli_csets( bli_creal(q__1), bli_cimag(q__1), *ca ); L20: return 0; } /* crotg_ */ /* zrotg.f -- translated by f2c (version 19991025). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ /* Subroutine */ int PASTEF77(z,rotg)(bla_dcomplex *ca, bla_dcomplex *cb, bla_double *c__, bla_dcomplex *s) { /* System generated locals */ bla_double d__1, d__2; bla_dcomplex z__1, z__2, z__3, z__4; /* Builtin functions */ //double bla_z_abs(bla_dcomplex *); //void bla_z_div(bla_dcomplex *, bla_dcomplex *, bla_dcomplex *); //double sqrt(bla_double); //void bla_d_cnjg(bla_dcomplex *, bla_dcomplex *); /* Local variables */ bla_double norm; bla_dcomplex alpha; bla_double scale; if (bla_z_abs(ca) != 0.) { goto L10; } *c__ = 0.; bli_zsets( 1., 0., *s ); bli_zsets( bli_zreal(*cb), bli_zimag(*cb), *ca ); goto L20; L10: scale = bla_z_abs(ca) + bla_z_abs(cb); bli_zsets( (scale), (0.), z__2 ); bla_z_div(&z__1, ca, &z__2); /* Computing 2nd power */ d__1 = bla_z_abs(&z__1); bli_zsets( (scale), (0.), z__4 ); bla_z_div(&z__3, cb, &z__4); /* Computing 2nd power */ d__2 = bla_z_abs(&z__3); norm = scale * sqrt(d__1 * d__1 + d__2 * d__2); d__1 = bla_z_abs(ca); bli_zsets( (bli_zreal(*ca) / d__1), (bli_zimag(*ca) / d__1), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), alpha ); *c__ = bla_z_abs(ca) / norm; bla_d_cnjg(&z__3, cb); bli_zsets( (bli_zreal(alpha) * bli_zreal(z__3) - bli_zimag(alpha) * bli_zimag(z__3)), (bli_zreal(alpha) * bli_zimag(z__3) + bli_zimag(alpha) * bli_zreal(z__3)), z__2 ); bli_zsets( (bli_zreal(z__2) / norm), (bli_zimag(z__2) / norm), z__1 ); bli_zsets( bli_zreal(z__1), bli_zimag(z__1), *s ); bli_zsets( (norm * bli_zreal(alpha)), (norm * bli_zimag(alpha)), z__1 ); bli_zsets( bli_zreal(z__1), bli_zimag(z__1), *ca ); L20: return 0; } /* zrotg_ */ #endif blis-0.9.0/frame/compat/f2c/bla_rotg.h000066400000000000000000000041101422157504600174440ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifdef BLIS_ENABLE_BLAS BLIS_EXPORT_BLAS int PASTEF77(s,rotg)(bla_real *sa, bla_real *sb, bla_real *c__, bla_real *s); BLIS_EXPORT_BLAS int PASTEF77(d,rotg)(bla_double *da, bla_double *db, bla_double *c__, bla_double *s); BLIS_EXPORT_BLAS int PASTEF77(c,rotg)(bla_scomplex *ca, bla_scomplex *cb, bla_real *c__, bla_scomplex *s); BLIS_EXPORT_BLAS int PASTEF77(z,rotg)(bla_dcomplex *ca, bla_dcomplex *cb, bla_double *c__, bla_dcomplex *s); #endif blis-0.9.0/frame/compat/f2c/bla_rotm.c000066400000000000000000000215401422157504600174530ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #ifdef BLIS_ENABLE_BLAS /* srotm.f -- translated by f2c (version 19991025). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ /* Subroutine */ int PASTEF77(s,rotm)(const bla_integer *n, bla_real *sx, const bla_integer *incx, bla_real *sy, const bla_integer *incy, const bla_real *sparam) { /* Initialized data */ static bla_real zero = 0.f; static bla_real two = 2.f; /* System generated locals */ bla_integer i__1, i__2; /* Local variables */ bla_integer i__; bla_real w, z__, sflag; bla_integer kx, ky, nsteps; bla_real sh11, sh12, sh21, sh22; /* APPLY THE MODIFIED GIVENS TRANSFORMATION, H, TO THE 2 BY N MATRIX */ /* (SX**T) , WHERE **T INDICATES TRANSPOSE. THE ELEMENTS OF SX ARE IN */ /* (DX**T) */ /* SX(LX+I*INCX), I = 0 TO N-1, WHERE LX = 1 IF INCX .GE. 0, ELSE */ /* LX = (-INCX)*N, AND SIMILARLY FOR SY USING USING LY AND INCY. */ /* WITH SPARAM(1)=SFLAG, H HAS ONE OF THE FOLLOWING FORMS.. */ /* SFLAG=-1.E0 SFLAG=0.E0 SFLAG=1.E0 SFLAG=-2.E0 */ /* (SH11 SH12) (1.E0 SH12) (SH11 1.E0) (1.E0 0.E0) */ /* H=( ) ( ) ( ) ( ) */ /* (SH21 SH22), (SH21 1.E0), (-1.E0 SH22), (0.E0 1.E0). */ /* SEE SROTMG FOR A DESCRIPTION OF DATA STORAGE IN SPARAM. */ /* Parameter adjustments */ --sparam; --sy; --sx; /* Function Body */ sflag = sparam[1]; if (*n <= 0 || sflag + two == zero) { goto L140; } if (! (*incx == *incy && *incx > 0)) { goto L70; } nsteps = *n * *incx; if (sflag < 0.f) { goto L50; } else if (sflag == 0) { goto L10; } else { goto L30; } L10: sh12 = sparam[4]; sh21 = sparam[3]; i__1 = nsteps; i__2 = *incx; for (i__ = 1; i__2 < 0 ? i__ >= i__1 : i__ <= i__1; i__ += i__2) { w = sx[i__]; z__ = sy[i__]; sx[i__] = w + z__ * sh12; sy[i__] = w * sh21 + z__; /* L20: */ } goto L140; L30: sh11 = sparam[2]; sh22 = sparam[5]; i__2 = nsteps; i__1 = *incx; for (i__ = 1; i__1 < 0 ? i__ >= i__2 : i__ <= i__2; i__ += i__1) { w = sx[i__]; z__ = sy[i__]; sx[i__] = w * sh11 + z__; sy[i__] = -w + sh22 * z__; /* L40: */ } goto L140; L50: sh11 = sparam[2]; sh12 = sparam[4]; sh21 = sparam[3]; sh22 = sparam[5]; i__1 = nsteps; i__2 = *incx; for (i__ = 1; i__2 < 0 ? i__ >= i__1 : i__ <= i__1; i__ += i__2) { w = sx[i__]; z__ = sy[i__]; sx[i__] = w * sh11 + z__ * sh12; sy[i__] = w * sh21 + z__ * sh22; /* L60: */ } goto L140; L70: kx = 1; ky = 1; if (*incx < 0) { kx = (1 - *n) * *incx + 1; } if (*incy < 0) { ky = (1 - *n) * *incy + 1; } if (sflag < 0.f) { goto L120; } else if (sflag == 0) { goto L80; } else { goto L100; } L80: sh12 = sparam[4]; sh21 = sparam[3]; i__2 = *n; for (i__ = 1; i__ <= i__2; ++i__) { w = sx[kx]; z__ = sy[ky]; sx[kx] = w + z__ * sh12; sy[ky] = w * sh21 + z__; kx += *incx; ky += *incy; /* L90: */ } goto L140; L100: sh11 = sparam[2]; sh22 = sparam[5]; i__2 = *n; for (i__ = 1; i__ <= i__2; ++i__) { w = sx[kx]; z__ = sy[ky]; sx[kx] = w * sh11 + z__; sy[ky] = -w + sh22 * z__; kx += *incx; ky += *incy; /* L110: */ } goto L140; L120: sh11 = sparam[2]; sh12 = sparam[4]; sh21 = sparam[3]; sh22 = sparam[5]; i__2 = *n; for (i__ = 1; i__ <= i__2; ++i__) { w = sx[kx]; z__ = sy[ky]; sx[kx] = w * sh11 + z__ * sh12; sy[ky] = w * sh21 + z__ * sh22; kx += *incx; ky += *incy; /* L130: */ } L140: return 0; } /* srotm_ */ /* drotm.f -- translated by f2c (version 19991025). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ /* Subroutine */ int PASTEF77(d,rotm)(const bla_integer *n, bla_double *dx, const bla_integer *incx, bla_double *dy, const bla_integer *incy, const bla_double *dparam) { /* Initialized data */ static bla_double zero = 0.; static bla_double two = 2.; /* System generated locals */ bla_integer i__1, i__2; /* Local variables */ bla_integer i__; bla_double dflag, w, z__; bla_integer kx, ky, nsteps; bla_double dh11, dh12, dh22, dh21; /* APPLY THE MODIFIED GIVENS TRANSFORMATION, H, TO THE 2 BY N MATRIX */ /* (DX**T) , WHERE **T INDICATES TRANSPOSE. THE ELEMENTS OF DX ARE IN */ /* (DY**T) */ /* DX(LX+I*INCX), I = 0 TO N-1, WHERE LX = 1 IF INCX .GE. 0, ELSE */ /* LX = (-INCX)*N, AND SIMILARLY FOR SY USING LY AND INCY. */ /* WITH DPARAM(1)=DFLAG, H HAS ONE OF THE FOLLOWING FORMS.. */ /* DFLAG=-1.D0 DFLAG=0.D0 DFLAG=1.D0 DFLAG=-2.D0 */ /* (DH11 DH12) (1.D0 DH12) (DH11 1.D0) (1.D0 0.D0) */ /* H=( ) ( ) ( ) ( ) */ /* (DH21 DH22), (DH21 1.D0), (-1.D0 DH22), (0.D0 1.D0). */ /* SEE DROTMG FOR A DESCRIPTION OF DATA STORAGE IN DPARAM. */ /* Parameter adjustments */ --dparam; --dy; --dx; /* Function Body */ dflag = dparam[1]; if (*n <= 0 || dflag + two == zero) { goto L140; } if (! (*incx == *incy && *incx > 0)) { goto L70; } nsteps = *n * *incx; if (dflag < 0.) { goto L50; } else if (dflag == 0) { goto L10; } else { goto L30; } L10: dh12 = dparam[4]; dh21 = dparam[3]; i__1 = nsteps; i__2 = *incx; for (i__ = 1; i__2 < 0 ? i__ >= i__1 : i__ <= i__1; i__ += i__2) { w = dx[i__]; z__ = dy[i__]; dx[i__] = w + z__ * dh12; dy[i__] = w * dh21 + z__; /* L20: */ } goto L140; L30: dh11 = dparam[2]; dh22 = dparam[5]; i__2 = nsteps; i__1 = *incx; for (i__ = 1; i__1 < 0 ? i__ >= i__2 : i__ <= i__2; i__ += i__1) { w = dx[i__]; z__ = dy[i__]; dx[i__] = w * dh11 + z__; dy[i__] = -w + dh22 * z__; /* L40: */ } goto L140; L50: dh11 = dparam[2]; dh12 = dparam[4]; dh21 = dparam[3]; dh22 = dparam[5]; i__1 = nsteps; i__2 = *incx; for (i__ = 1; i__2 < 0 ? i__ >= i__1 : i__ <= i__1; i__ += i__2) { w = dx[i__]; z__ = dy[i__]; dx[i__] = w * dh11 + z__ * dh12; dy[i__] = w * dh21 + z__ * dh22; /* L60: */ } goto L140; L70: kx = 1; ky = 1; if (*incx < 0) { kx = (1 - *n) * *incx + 1; } if (*incy < 0) { ky = (1 - *n) * *incy + 1; } if (dflag < 0.) { goto L120; } else if (dflag == 0) { goto L80; } else { goto L100; } L80: dh12 = dparam[4]; dh21 = dparam[3]; i__2 = *n; for (i__ = 1; i__ <= i__2; ++i__) { w = dx[kx]; z__ = dy[ky]; dx[kx] = w + z__ * dh12; dy[ky] = w * dh21 + z__; kx += *incx; ky += *incy; /* L90: */ } goto L140; L100: dh11 = dparam[2]; dh22 = dparam[5]; i__2 = *n; for (i__ = 1; i__ <= i__2; ++i__) { w = dx[kx]; z__ = dy[ky]; dx[kx] = w * dh11 + z__; dy[ky] = -w + dh22 * z__; kx += *incx; ky += *incy; /* L110: */ } goto L140; L120: dh11 = dparam[2]; dh12 = dparam[4]; dh21 = dparam[3]; dh22 = dparam[5]; i__2 = *n; for (i__ = 1; i__ <= i__2; ++i__) { w = dx[kx]; z__ = dy[ky]; dx[kx] = w * dh11 + z__ * dh12; dy[ky] = w * dh21 + z__ * dh22; kx += *incx; ky += *incy; /* L130: */ } L140: return 0; } /* drotm_ */ #endif blis-0.9.0/frame/compat/f2c/bla_rotm.h000066400000000000000000000037661422157504600174720ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifdef BLIS_ENABLE_BLAS BLIS_EXPORT_BLAS int PASTEF77(s,rotm)(const bla_integer *n, bla_real *sx, const bla_integer *incx, bla_real *sy, const bla_integer *incy, const bla_real *sparam); BLIS_EXPORT_BLAS int PASTEF77(d,rotm)(const bla_integer *n, bla_double *dx, const bla_integer *incx, bla_double *dy, const bla_integer *incy, const bla_double *dparam); #endif blis-0.9.0/frame/compat/f2c/bla_rotmg.c000066400000000000000000000264261422157504600176320ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #ifdef BLIS_ENABLE_BLAS /* srotmg.f -- translated by f2c (version 19991025). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ /* Subroutine */ int PASTEF77(s,rotmg)(bla_real *sd1, bla_real *sd2, bla_real *sx1, const bla_real *sy1, bla_real *sparam) { /* Initialized data */ static bla_real zero = 0.f; static bla_real one = 1.f; static bla_real two = 2.f; static bla_real gam = 4096.f; static bla_real gamsq = 16777200.f; static bla_real rgamsq = 5.96046e-8f; /* Format strings */ /* System generated locals */ bla_real r__1; /* Local variables */ bla_real sflag, stemp, su, sp1, sp2, sq2, sq1, sh11 = 0.f, sh21 = 0.f, sh12 = 0.f, sh22 = 0.f; bla_integer igo; /* Assigned format variables */ /* CONSTRUCT THE MODIFIED GIVENS TRANSFORMATION MATRIX H WHICH ZEROS */ /* THE SECOND COMPONENT OF THE 2-VECTOR (SQRT(SD1)*SX1,SQRT(SD2)* */ /* SY2)**T. */ /* WITH SPARAM(1)=SFLAG, H HAS ONE OF THE FOLLOWING FORMS.. */ /* SFLAG=-1.E0 SFLAG=0.E0 SFLAG=1.E0 SFLAG=-2.E0 */ /* (SH11 SH12) (1.E0 SH12) (SH11 1.E0) (1.E0 0.E0) */ /* H=( ) ( ) ( ) ( ) */ /* (SH21 SH22), (SH21 1.E0), (-1.E0 SH22), (0.E0 1.E0). */ /* LOCATIONS 2-4 OF SPARAM CONTAIN SH11,SH21,SH12, AND SH22 */ /* RESPECTIVELY. (VALUES OF 1.E0, -1.E0, OR 0.E0 IMPLIED BY THE */ /* VALUE OF SPARAM(1) ARE NOT STORED IN SPARAM.) */ /* THE VALUES OF GAMSQ AND RGAMSQ SET IN THE DATA STATEMENT MAY BE */ /* INEXACT. THIS IS OK AS THEY ARE ONLY USED FOR TESTING THE SIZE */ /* OF SD1 AND SD2. ALL ACTUAL SCALING OF DATA IS DONE USING GAM. */ /* Parameter adjustments */ --sparam; /* Function Body */ if (! (*sd1 < zero)) { goto L10; } /* GO ZERO-H-D-AND-SX1.. */ goto L60; L10: /* CASE-SD1-NONNEGATIVE */ sp2 = *sd2 * *sy1; if (! (sp2 == zero)) { goto L20; } sflag = -two; goto L260; /* REGULAR-CASE.. */ L20: sp1 = *sd1 * *sx1; sq2 = sp2 * *sy1; sq1 = sp1 * *sx1; if (! (bli_fabs(sq1) > bli_fabs(sq2))) { goto L40; } sh21 = -(*sy1) / *sx1; sh12 = sp2 / sp1; su = one - sh12 * sh21; if (! (su <= zero)) { goto L30; } /* GO ZERO-H-D-AND-SX1.. */ goto L60; L30: sflag = zero; *sd1 /= su; *sd2 /= su; *sx1 *= su; /* GO SCALE-CHECK.. */ goto L100; L40: if (! (sq2 < zero)) { goto L50; } /* GO ZERO-H-D-AND-SX1.. */ goto L60; L50: sflag = one; sh11 = sp1 / sp2; sh22 = *sx1 / *sy1; su = one + sh11 * sh22; stemp = *sd2 / su; *sd2 = *sd1 / su; *sd1 = stemp; *sx1 = *sy1 * su; /* GO SCALE-CHECK */ goto L100; /* PROCEDURE..ZERO-H-D-AND-SX1.. */ L60: sflag = -one; sh11 = zero; sh12 = zero; sh21 = zero; sh22 = zero; *sd1 = zero; *sd2 = zero; *sx1 = zero; /* RETURN.. */ goto L220; /* PROCEDURE..FIX-H.. */ L70: if (! (sflag >= zero)) { goto L90; } if (! (sflag == zero)) { goto L80; } sh11 = one; sh22 = one; sflag = -one; goto L90; L80: sh21 = -one; sh12 = one; sflag = -one; L90: switch (igo) { case 0: goto L120; case 1: goto L150; case 2: goto L180; case 3: goto L210; } /* PROCEDURE..SCALE-CHECK */ L100: L110: if (! (*sd1 <= rgamsq)) { goto L130; } if (*sd1 == zero) { goto L160; } igo = 0; /* FIX-H.. */ goto L70; L120: /* Computing 2nd power */ r__1 = gam; *sd1 *= r__1 * r__1; *sx1 /= gam; sh11 /= gam; sh12 /= gam; goto L110; L130: L140: if (! (*sd1 >= gamsq)) { goto L160; } igo = 1; /* FIX-H.. */ goto L70; L150: /* Computing 2nd power */ r__1 = gam; *sd1 /= r__1 * r__1; *sx1 *= gam; sh11 *= gam; sh12 *= gam; goto L140; L160: L170: if (! (bli_fabs(*sd2) <= rgamsq)) { goto L190; } if (*sd2 == zero) { goto L220; } igo = 2; /* FIX-H.. */ goto L70; L180: /* Computing 2nd power */ r__1 = gam; *sd2 *= r__1 * r__1; sh21 /= gam; sh22 /= gam; goto L170; L190: L200: if (! (bli_fabs(*sd2) >= gamsq)) { goto L220; } igo = 3; /* FIX-H.. */ goto L70; L210: /* Computing 2nd power */ r__1 = gam; *sd2 /= r__1 * r__1; sh21 *= gam; sh22 *= gam; goto L200; L220: if (sflag < 0.f) { goto L250; } else if (sflag == 0) { goto L230; } else { goto L240; } L230: sparam[3] = sh21; sparam[4] = sh12; goto L260; L240: sparam[2] = sh11; sparam[5] = sh22; goto L260; L250: sparam[2] = sh11; sparam[3] = sh21; sparam[4] = sh12; sparam[5] = sh22; L260: sparam[1] = sflag; return 0; } /* srotmg_ */ /* drotmg.f -- translated by f2c (version 19991025). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ /* Subroutine */ int PASTEF77(d,rotmg)(bla_double *dd1, bla_double *dd2, bla_double *dx1, const bla_double *dy1, bla_double *dparam) { /* Initialized data */ static bla_double zero = 0.; static bla_double one = 1.; static bla_double two = 2.; static bla_double gam = 4096.; static bla_double gamsq = 16777216.; static bla_double rgamsq = 5.9604645e-8; /* Format strings */ /* System generated locals */ bla_double d__1; /* Local variables */ bla_double dflag, dtemp, du, dp1, dp2, dq2, dq1, dh11 = 0.f, dh21 = 0.f, dh12 = 0.f, dh22 = 0.f; bla_integer igo; /* Assigned format variables */ /* CONSTRUCT THE MODIFIED GIVENS TRANSFORMATION MATRIX H WHICH ZEROS */ /* THE SECOND COMPONENT OF THE 2-VECTOR (DSQRT(DD1)*DX1,DSQRT(DD2)* */ /* DY2)**T. */ /* WITH DPARAM(1)=DFLAG, H HAS ONE OF THE FOLLOWING FORMS.. */ /* DFLAG=-1.D0 DFLAG=0.D0 DFLAG=1.D0 DFLAG=-2.D0 */ /* (DH11 DH12) (1.D0 DH12) (DH11 1.D0) (1.D0 0.D0) */ /* H=( ) ( ) ( ) ( ) */ /* (DH21 DH22), (DH21 1.D0), (-1.D0 DH22), (0.D0 1.D0). */ /* LOCATIONS 2-4 OF DPARAM CONTAIN DH11, DH21, DH12, AND DH22 */ /* RESPECTIVELY. (VALUES OF 1.D0, -1.D0, OR 0.D0 IMPLIED BY THE */ /* VALUE OF DPARAM(1) ARE NOT STORED IN DPARAM.) */ /* THE VALUES OF GAMSQ AND RGAMSQ SET IN THE DATA STATEMENT MAY BE */ /* INEXACT. THIS IS OK AS THEY ARE ONLY USED FOR TESTING THE SIZE */ /* OF DD1 AND DD2. ALL ACTUAL SCALING OF DATA IS DONE USING GAM. */ /* Parameter adjustments */ --dparam; /* Function Body */ if (! (*dd1 < zero)) { goto L10; } /* GO ZERO-H-D-AND-DX1.. */ goto L60; L10: /* CASE-DD1-NONNEGATIVE */ dp2 = *dd2 * *dy1; if (! (dp2 == zero)) { goto L20; } dflag = -two; goto L260; /* REGULAR-CASE.. */ L20: dp1 = *dd1 * *dx1; dq2 = dp2 * *dy1; dq1 = dp1 * *dx1; if (! (bli_fabs(dq1) > bli_fabs(dq2))) { goto L40; } dh21 = -(*dy1) / *dx1; dh12 = dp2 / dp1; du = one - dh12 * dh21; if (! (du <= zero)) { goto L30; } /* GO ZERO-H-D-AND-DX1.. */ goto L60; L30: dflag = zero; *dd1 /= du; *dd2 /= du; *dx1 *= du; /* GO SCALE-CHECK.. */ goto L100; L40: if (! (dq2 < zero)) { goto L50; } /* GO ZERO-H-D-AND-DX1.. */ goto L60; L50: dflag = one; dh11 = dp1 / dp2; dh22 = *dx1 / *dy1; du = one + dh11 * dh22; dtemp = *dd2 / du; *dd2 = *dd1 / du; *dd1 = dtemp; *dx1 = *dy1 * du; /* GO SCALE-CHECK */ goto L100; /* PROCEDURE..ZERO-H-D-AND-DX1.. */ L60: dflag = -one; dh11 = zero; dh12 = zero; dh21 = zero; dh22 = zero; *dd1 = zero; *dd2 = zero; *dx1 = zero; /* RETURN.. */ goto L220; /* PROCEDURE..FIX-H.. */ L70: if (! (dflag >= zero)) { goto L90; } if (! (dflag == zero)) { goto L80; } dh11 = one; dh22 = one; dflag = -one; goto L90; L80: dh21 = -one; dh12 = one; dflag = -one; L90: switch (igo) { case 0: goto L120; case 1: goto L150; case 2: goto L180; case 3: goto L210; } /* PROCEDURE..SCALE-CHECK */ L100: L110: if (! (*dd1 <= rgamsq)) { goto L130; } if (*dd1 == zero) { goto L160; } igo = 0; /* FIX-H.. */ goto L70; L120: /* Computing 2nd power */ d__1 = gam; *dd1 *= d__1 * d__1; *dx1 /= gam; dh11 /= gam; dh12 /= gam; goto L110; L130: L140: if (! (*dd1 >= gamsq)) { goto L160; } igo = 1; /* FIX-H.. */ goto L70; L150: /* Computing 2nd power */ d__1 = gam; *dd1 /= d__1 * d__1; *dx1 *= gam; dh11 *= gam; dh12 *= gam; goto L140; L160: L170: if (! (bli_fabs(*dd2) <= rgamsq)) { goto L190; } if (*dd2 == zero) { goto L220; } igo = 2; /* FIX-H.. */ goto L70; L180: /* Computing 2nd power */ d__1 = gam; *dd2 *= d__1 * d__1; dh21 /= gam; dh22 /= gam; goto L170; L190: L200: if (! (bli_fabs(*dd2) >= gamsq)) { goto L220; } igo = 3; /* FIX-H.. */ goto L70; L210: /* Computing 2nd power */ d__1 = gam; *dd2 /= d__1 * d__1; dh21 *= gam; dh22 *= gam; goto L200; L220: if (dflag < 0.) { goto L250; } else if (dflag == 0) { goto L230; } else { goto L240; } L230: dparam[3] = dh21; dparam[4] = dh12; goto L260; L240: dparam[2] = dh11; dparam[5] = dh22; goto L260; L250: dparam[2] = dh11; dparam[3] = dh21; dparam[4] = dh12; dparam[5] = dh22; L260: dparam[1] = dflag; return 0; } /* drotmg_ */ #endif blis-0.9.0/frame/compat/f2c/bla_rotmg.h000066400000000000000000000036541422157504600176350ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifdef BLIS_ENABLE_BLAS BLIS_EXPORT_BLAS int PASTEF77(s,rotmg)(bla_real *sd1, bla_real *sd2, bla_real *sx1, const bla_real *sy1, bla_real *sparam); BLIS_EXPORT_BLAS int PASTEF77(d,rotmg)(bla_double *dd1, bla_double *dd2, bla_double *dx1, const bla_double *dy1, bla_double *dparam); #endif blis-0.9.0/frame/compat/f2c/bla_sbmv.c000066400000000000000000000522451422157504600174470ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #ifdef BLIS_ENABLE_BLAS /* dsbmv.f -- translated by f2c (version 19991025). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ /* Subroutine */ int PASTEF77(d,sbmv)(const bla_character *uplo, const bla_integer *n, const bla_integer *k, const bla_double *alpha, const bla_double *a, const bla_integer *lda, const bla_double *x, const bla_integer *incx, const bla_double *beta, bla_double *y, const bla_integer *incy) { /* System generated locals */ bla_integer a_dim1, a_offset, i__1, i__2, i__3, i__4; /* Local variables */ bla_integer info; bla_double temp1, temp2; bla_integer i__, j, l; //extern bla_logical PASTEF770(lsame)(bla_character *, bla_character *, ftnlen, ftnlen); bla_integer kplus1, ix, iy, jx, jy, kx, ky; //extern /* Subroutine */ int PASTEF770(xerbla)(bla_character *, bla_integer *, ftnlen); /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* DSBMV performs the matrix-vector operation */ /* y := alpha*A*x + beta*y, */ /* where alpha and beta are scalars, x and y are n element vectors and */ /* A is an n by n symmetric band matrix, with k super-diagonals. */ /* Parameters */ /* ========== */ /* UPLO - CHARACTER*1. */ /* On entry, UPLO specifies whether the upper or lower */ /* triangular part of the band matrix A is being supplied as */ /* follows: */ /* UPLO = 'U' or 'u' The upper triangular part of A is */ /* being supplied. */ /* UPLO = 'L' or 'l' The lower triangular part of A is */ /* being supplied. */ /* Unchanged on exit. */ /* N - INTEGER. */ /* On entry, N specifies the order of the matrix A. */ /* N must be at least zero. */ /* Unchanged on exit. */ /* K - INTEGER. */ /* On entry, K specifies the number of super-diagonals of the */ /* matrix A. K must satisfy 0 .le. K. */ /* Unchanged on exit. */ /* ALPHA - DOUBLE PRECISION. */ /* On entry, ALPHA specifies the scalar alpha. */ /* Unchanged on exit. */ /* A - DOUBLE PRECISION array of DIMENSION ( LDA, n ). */ /* Before entry with UPLO = 'U' or 'u', the leading ( k + 1 ) */ /* by n part of the array A must contain the upper triangular */ /* band part of the symmetric matrix, supplied column by */ /* column, with the leading diagonal of the matrix in row */ /* ( k + 1 ) of the array, the first super-diagonal starting at */ /* position 2 in row k, and so on. The top left k by k triangle */ /* of the array A is not referenced. */ /* The following program segment will transfer the upper */ /* triangular part of a symmetric band matrix from conventional */ /* full matrix storage to band storage: */ /* DO 20, J = 1, N */ /* M = K + 1 - J */ /* DO 10, I = MAX( 1, J - K ), J */ /* A( M + I, J ) = matrix( I, J ) */ /* 10 CONTINUE */ /* 20 CONTINUE */ /* Before entry with UPLO = 'L' or 'l', the leading ( k + 1 ) */ /* by n part of the array A must contain the lower triangular */ /* band part of the symmetric matrix, supplied column by */ /* column, with the leading diagonal of the matrix in row 1 of */ /* the array, the first sub-diagonal starting at position 1 in */ /* row 2, and so on. The bottom right k by k triangle of the */ /* array A is not referenced. */ /* The following program segment will transfer the lower */ /* triangular part of a symmetric band matrix from conventional */ /* full matrix storage to band storage: */ /* DO 20, J = 1, N */ /* M = 1 - J */ /* DO 10, I = J, MIN( N, J + K ) */ /* A( M + I, J ) = matrix( I, J ) */ /* 10 CONTINUE */ /* 20 CONTINUE */ /* Unchanged on exit. */ /* LDA - INTEGER. */ /* On entry, LDA specifies the first dimension of A as declared */ /* in the calling (sub) program. LDA must be at least */ /* ( k + 1 ). */ /* Unchanged on exit. */ /* X - DOUBLE PRECISION array of DIMENSION at least */ /* ( 1 + ( n - 1 )*abs( INCX ) ). */ /* Before entry, the incremented array X must contain the */ /* vector x. */ /* Unchanged on exit. */ /* INCX - INTEGER. */ /* On entry, INCX specifies the increment for the elements of */ /* X. INCX must not be zero. */ /* Unchanged on exit. */ /* BETA - DOUBLE PRECISION. */ /* On entry, BETA specifies the scalar beta. */ /* Unchanged on exit. */ /* Y - DOUBLE PRECISION array of DIMENSION at least */ /* ( 1 + ( n - 1 )*abs( INCY ) ). */ /* Before entry, the incremented array Y must contain the */ /* vector y. On exit, Y is overwritten by the updated vector y. */ /* INCY - INTEGER. */ /* On entry, INCY specifies the increment for the elements of */ /* Y. INCY must not be zero. */ /* Unchanged on exit. */ /* Level 2 Blas routine. */ /* -- Written on 22-October-1986. */ /* Jack Dongarra, Argonne National Lab. */ /* Jeremy Du Croz, Nag Central Office. */ /* Sven Hammarling, Nag Central Office. */ /* Richard Hanson, Sandia National Labs. */ /* .. Parameters .. */ /* .. Local Scalars .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. */ /* .. Executable Statements .. */ /* Test the input parameters. */ /* Parameter adjustments */ a_dim1 = *lda; a_offset = 1 + a_dim1 * 1; a -= a_offset; --x; --y; /* Function Body */ info = 0; if (! PASTEF770(lsame)(uplo, "U", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(uplo, "L", ( ftnlen)1, (ftnlen)1)) { info = 1; } else if (*n < 0) { info = 2; } else if (*k < 0) { info = 3; } else if (*lda < *k + 1) { info = 6; } else if (*incx == 0) { info = 8; } else if (*incy == 0) { info = 11; } if (info != 0) { PASTEF770(xerbla)("DSBMV ", &info, (ftnlen)6); return 0; } /* Quick return if possible. */ if (*n == 0 || (*alpha == 0. && *beta == 1.)) { return 0; } /* Set up the start points in X and Y. */ if (*incx > 0) { kx = 1; } else { kx = 1 - (*n - 1) * *incx; } if (*incy > 0) { ky = 1; } else { ky = 1 - (*n - 1) * *incy; } /* Start the operations. In this version the elements of the array A */ /* are accessed sequentially with one pass through A. */ /* First form y := beta*y. */ if (*beta != 1.) { if (*incy == 1) { if (*beta == 0.) { i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { y[i__] = 0.; /* L10: */ } } else { i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { y[i__] = *beta * y[i__]; /* L20: */ } } } else { iy = ky; if (*beta == 0.) { i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { y[iy] = 0.; iy += *incy; /* L30: */ } } else { i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { y[iy] = *beta * y[iy]; iy += *incy; /* L40: */ } } } } if (*alpha == 0.) { return 0; } if (PASTEF770(lsame)(uplo, "U", (ftnlen)1, (ftnlen)1)) { /* Form y when upper triangle of A is stored. */ kplus1 = *k + 1; if (*incx == 1 && *incy == 1) { i__1 = *n; for (j = 1; j <= i__1; ++j) { temp1 = *alpha * x[j]; temp2 = 0.; l = kplus1 - j; /* Computing MAX */ i__2 = 1, i__3 = j - *k; i__4 = j - 1; for (i__ = f2c_max(i__2,i__3); i__ <= i__4; ++i__) { y[i__] += temp1 * a[l + i__ + j * a_dim1]; temp2 += a[l + i__ + j * a_dim1] * x[i__]; /* L50: */ } y[j] = y[j] + temp1 * a[kplus1 + j * a_dim1] + *alpha * temp2; /* L60: */ } } else { jx = kx; jy = ky; i__1 = *n; for (j = 1; j <= i__1; ++j) { temp1 = *alpha * x[jx]; temp2 = 0.; ix = kx; iy = ky; l = kplus1 - j; /* Computing MAX */ i__4 = 1, i__2 = j - *k; i__3 = j - 1; for (i__ = f2c_max(i__4,i__2); i__ <= i__3; ++i__) { y[iy] += temp1 * a[l + i__ + j * a_dim1]; temp2 += a[l + i__ + j * a_dim1] * x[ix]; ix += *incx; iy += *incy; /* L70: */ } y[jy] = y[jy] + temp1 * a[kplus1 + j * a_dim1] + *alpha * temp2; jx += *incx; jy += *incy; if (j > *k) { kx += *incx; ky += *incy; } /* L80: */ } } } else { /* Form y when lower triangle of A is stored. */ if (*incx == 1 && *incy == 1) { i__1 = *n; for (j = 1; j <= i__1; ++j) { temp1 = *alpha * x[j]; temp2 = 0.; y[j] += temp1 * a[j * a_dim1 + 1]; l = 1 - j; /* Computing MIN */ i__4 = *n, i__2 = j + *k; i__3 = f2c_min(i__4,i__2); for (i__ = j + 1; i__ <= i__3; ++i__) { y[i__] += temp1 * a[l + i__ + j * a_dim1]; temp2 += a[l + i__ + j * a_dim1] * x[i__]; /* L90: */ } y[j] += *alpha * temp2; /* L100: */ } } else { jx = kx; jy = ky; i__1 = *n; for (j = 1; j <= i__1; ++j) { temp1 = *alpha * x[jx]; temp2 = 0.; y[jy] += temp1 * a[j * a_dim1 + 1]; l = 1 - j; ix = jx; iy = jy; /* Computing MIN */ i__4 = *n, i__2 = j + *k; i__3 = f2c_min(i__4,i__2); for (i__ = j + 1; i__ <= i__3; ++i__) { ix += *incx; iy += *incy; y[iy] += temp1 * a[l + i__ + j * a_dim1]; temp2 += a[l + i__ + j * a_dim1] * x[ix]; /* L110: */ } y[jy] += *alpha * temp2; jx += *incx; jy += *incy; /* L120: */ } } } return 0; /* End of DSBMV . */ } /* dsbmv_ */ /* ssbmv.f -- translated by f2c (version 19991025). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ /* Subroutine */ int PASTEF77(s,sbmv)(const bla_character *uplo, const bla_integer *n, const bla_integer *k, const bla_real *alpha, const bla_real *a, const bla_integer *lda, const bla_real *x, const bla_integer *incx, const bla_real *beta, bla_real *y, const bla_integer *incy) { /* System generated locals */ bla_integer a_dim1, a_offset, i__1, i__2, i__3, i__4; /* Local variables */ bla_integer info; bla_real temp1, temp2; bla_integer i__, j, l; //extern bla_logical PASTEF770(lsame)(bla_character *, bla_character *, ftnlen, ftnlen); bla_integer kplus1, ix, iy, jx, jy, kx, ky; //extern /* Subroutine */ int PASTEF770(xerbla)(bla_character *, bla_integer *, ftnlen); /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* SSBMV performs the matrix-vector operation */ /* y := alpha*A*x + beta*y, */ /* where alpha and beta are scalars, x and y are n element vectors and */ /* A is an n by n symmetric band matrix, with k super-diagonals. */ /* Parameters */ /* ========== */ /* UPLO - CHARACTER*1. */ /* On entry, UPLO specifies whether the upper or lower */ /* triangular part of the band matrix A is being supplied as */ /* follows: */ /* UPLO = 'U' or 'u' The upper triangular part of A is */ /* being supplied. */ /* UPLO = 'L' or 'l' The lower triangular part of A is */ /* being supplied. */ /* Unchanged on exit. */ /* N - INTEGER. */ /* On entry, N specifies the order of the matrix A. */ /* N must be at least zero. */ /* Unchanged on exit. */ /* K - INTEGER. */ /* On entry, K specifies the number of super-diagonals of the */ /* matrix A. K must satisfy 0 .le. K. */ /* Unchanged on exit. */ /* ALPHA - REAL . */ /* On entry, ALPHA specifies the scalar alpha. */ /* Unchanged on exit. */ /* A - REAL array of DIMENSION ( LDA, n ). */ /* Before entry with UPLO = 'U' or 'u', the leading ( k + 1 ) */ /* by n part of the array A must contain the upper triangular */ /* band part of the symmetric matrix, supplied column by */ /* column, with the leading diagonal of the matrix in row */ /* ( k + 1 ) of the array, the first super-diagonal starting at */ /* position 2 in row k, and so on. The top left k by k triangle */ /* of the array A is not referenced. */ /* The following program segment will transfer the upper */ /* triangular part of a symmetric band matrix from conventional */ /* full matrix storage to band storage: */ /* DO 20, J = 1, N */ /* M = K + 1 - J */ /* DO 10, I = MAX( 1, J - K ), J */ /* A( M + I, J ) = matrix( I, J ) */ /* 10 CONTINUE */ /* 20 CONTINUE */ /* Before entry with UPLO = 'L' or 'l', the leading ( k + 1 ) */ /* by n part of the array A must contain the lower triangular */ /* band part of the symmetric matrix, supplied column by */ /* column, with the leading diagonal of the matrix in row 1 of */ /* the array, the first sub-diagonal starting at position 1 in */ /* row 2, and so on. The bottom right k by k triangle of the */ /* array A is not referenced. */ /* The following program segment will transfer the lower */ /* triangular part of a symmetric band matrix from conventional */ /* full matrix storage to band storage: */ /* DO 20, J = 1, N */ /* M = 1 - J */ /* DO 10, I = J, MIN( N, J + K ) */ /* A( M + I, J ) = matrix( I, J ) */ /* 10 CONTINUE */ /* 20 CONTINUE */ /* Unchanged on exit. */ /* LDA - INTEGER. */ /* On entry, LDA specifies the first dimension of A as declared */ /* in the calling (sub) program. LDA must be at least */ /* ( k + 1 ). */ /* Unchanged on exit. */ /* X - REAL array of DIMENSION at least */ /* ( 1 + ( n - 1 )*abs( INCX ) ). */ /* Before entry, the incremented array X must contain the */ /* vector x. */ /* Unchanged on exit. */ /* INCX - INTEGER. */ /* On entry, INCX specifies the increment for the elements of */ /* X. INCX must not be zero. */ /* Unchanged on exit. */ /* BETA - REAL . */ /* On entry, BETA specifies the scalar beta. */ /* Unchanged on exit. */ /* Y - REAL array of DIMENSION at least */ /* ( 1 + ( n - 1 )*abs( INCY ) ). */ /* Before entry, the incremented array Y must contain the */ /* vector y. On exit, Y is overwritten by the updated vector y. */ /* INCY - INTEGER. */ /* On entry, INCY specifies the increment for the elements of */ /* Y. INCY must not be zero. */ /* Unchanged on exit. */ /* Level 2 Blas routine. */ /* -- Written on 22-October-1986. */ /* Jack Dongarra, Argonne National Lab. */ /* Jeremy Du Croz, Nag Central Office. */ /* Sven Hammarling, Nag Central Office. */ /* Richard Hanson, Sandia National Labs. */ /* .. Parameters .. */ /* .. Local Scalars .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. */ /* .. Executable Statements .. */ /* Test the input parameters. */ /* Parameter adjustments */ a_dim1 = *lda; a_offset = 1 + a_dim1 * 1; a -= a_offset; --x; --y; /* Function Body */ info = 0; if (! PASTEF770(lsame)(uplo, "U", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(uplo, "L", ( ftnlen)1, (ftnlen)1)) { info = 1; } else if (*n < 0) { info = 2; } else if (*k < 0) { info = 3; } else if (*lda < *k + 1) { info = 6; } else if (*incx == 0) { info = 8; } else if (*incy == 0) { info = 11; } if (info != 0) { PASTEF770(xerbla)("SSBMV ", &info, (ftnlen)6); return 0; } /* Quick return if possible. */ if (*n == 0 || (*alpha == 0.f && *beta == 1.f)) { return 0; } /* Set up the start points in X and Y. */ if (*incx > 0) { kx = 1; } else { kx = 1 - (*n - 1) * *incx; } if (*incy > 0) { ky = 1; } else { ky = 1 - (*n - 1) * *incy; } /* Start the operations. In this version the elements of the array A */ /* are accessed sequentially with one pass through A. */ /* First form y := beta*y. */ if (*beta != 1.f) { if (*incy == 1) { if (*beta == 0.f) { i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { y[i__] = 0.f; /* L10: */ } } else { i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { y[i__] = *beta * y[i__]; /* L20: */ } } } else { iy = ky; if (*beta == 0.f) { i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { y[iy] = 0.f; iy += *incy; /* L30: */ } } else { i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { y[iy] = *beta * y[iy]; iy += *incy; /* L40: */ } } } } if (*alpha == 0.f) { return 0; } if (PASTEF770(lsame)(uplo, "U", (ftnlen)1, (ftnlen)1)) { /* Form y when upper triangle of A is stored. */ kplus1 = *k + 1; if (*incx == 1 && *incy == 1) { i__1 = *n; for (j = 1; j <= i__1; ++j) { temp1 = *alpha * x[j]; temp2 = 0.f; l = kplus1 - j; /* Computing MAX */ i__2 = 1, i__3 = j - *k; i__4 = j - 1; for (i__ = f2c_max(i__2,i__3); i__ <= i__4; ++i__) { y[i__] += temp1 * a[l + i__ + j * a_dim1]; temp2 += a[l + i__ + j * a_dim1] * x[i__]; /* L50: */ } y[j] = y[j] + temp1 * a[kplus1 + j * a_dim1] + *alpha * temp2; /* L60: */ } } else { jx = kx; jy = ky; i__1 = *n; for (j = 1; j <= i__1; ++j) { temp1 = *alpha * x[jx]; temp2 = 0.f; ix = kx; iy = ky; l = kplus1 - j; /* Computing MAX */ i__4 = 1, i__2 = j - *k; i__3 = j - 1; for (i__ = f2c_max(i__4,i__2); i__ <= i__3; ++i__) { y[iy] += temp1 * a[l + i__ + j * a_dim1]; temp2 += a[l + i__ + j * a_dim1] * x[ix]; ix += *incx; iy += *incy; /* L70: */ } y[jy] = y[jy] + temp1 * a[kplus1 + j * a_dim1] + *alpha * temp2; jx += *incx; jy += *incy; if (j > *k) { kx += *incx; ky += *incy; } /* L80: */ } } } else { /* Form y when lower triangle of A is stored. */ if (*incx == 1 && *incy == 1) { i__1 = *n; for (j = 1; j <= i__1; ++j) { temp1 = *alpha * x[j]; temp2 = 0.f; y[j] += temp1 * a[j * a_dim1 + 1]; l = 1 - j; /* Computing MIN */ i__4 = *n, i__2 = j + *k; i__3 = f2c_min(i__4,i__2); for (i__ = j + 1; i__ <= i__3; ++i__) { y[i__] += temp1 * a[l + i__ + j * a_dim1]; temp2 += a[l + i__ + j * a_dim1] * x[i__]; /* L90: */ } y[j] += *alpha * temp2; /* L100: */ } } else { jx = kx; jy = ky; i__1 = *n; for (j = 1; j <= i__1; ++j) { temp1 = *alpha * x[jx]; temp2 = 0.f; y[jy] += temp1 * a[j * a_dim1 + 1]; l = 1 - j; ix = jx; iy = jy; /* Computing MIN */ i__4 = *n, i__2 = j + *k; i__3 = f2c_min(i__4,i__2); for (i__ = j + 1; i__ <= i__3; ++i__) { ix += *incx; iy += *incy; y[iy] += temp1 * a[l + i__ + j * a_dim1]; temp2 += a[l + i__ + j * a_dim1] * x[ix]; /* L110: */ } y[jy] += *alpha * temp2; jx += *incx; jy += *incy; /* L120: */ } } } return 0; /* End of SSBMV . */ } /* ssbmv_ */ #endif blis-0.9.0/frame/compat/f2c/bla_sbmv.h000066400000000000000000000043441422157504600174510ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifdef BLIS_ENABLE_BLAS BLIS_EXPORT_BLAS int PASTEF77(d,sbmv)(const bla_character *uplo, const bla_integer *n, const bla_integer *k, const bla_double *alpha, const bla_double *a, const bla_integer *lda, const bla_double *x, const bla_integer *incx, const bla_double *beta, bla_double *y, const bla_integer *incy); BLIS_EXPORT_BLAS int PASTEF77(s,sbmv)(const bla_character *uplo, const bla_integer *n, const bla_integer *k, const bla_real *alpha, const bla_real *a, const bla_integer *lda, const bla_real *x, const bla_integer *incx, const bla_real *beta, bla_real *y, const bla_integer *incy); #endif blis-0.9.0/frame/compat/f2c/bla_spmv.c000066400000000000000000000416511422157504600174640ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #ifdef BLIS_ENABLE_BLAS /* dspmv.f -- translated by f2c (version 19991025). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ /* Subroutine */ int PASTEF77(d,spmv)(const bla_character *uplo, const bla_integer *n, const bla_double *alpha, const bla_double *ap, const bla_double *x, const bla_integer *incx, const bla_double *beta, bla_double *y, const bla_integer *incy) { /* System generated locals */ bla_integer i__1, i__2; /* Local variables */ bla_integer info; bla_double temp1, temp2; bla_integer i__, j, k; //extern bla_logical PASTEF770(lsame)(bla_character *, bla_character *, ftnlen, ftnlen); bla_integer kk, ix, iy, jx, jy, kx, ky; //extern /* Subroutine */ int PASTEF770(xerbla)(bla_character *, bla_integer *, ftnlen); /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* DSPMV performs the matrix-vector operation */ /* y := alpha*A*x + beta*y, */ /* where alpha and beta are scalars, x and y are n element vectors and */ /* A is an n by n symmetric matrix, supplied in packed form. */ /* Parameters */ /* ========== */ /* UPLO - CHARACTER*1. */ /* On entry, UPLO specifies whether the upper or lower */ /* triangular part of the matrix A is supplied in the packed */ /* array AP as follows: */ /* UPLO = 'U' or 'u' The upper triangular part of A is */ /* supplied in AP. */ /* UPLO = 'L' or 'l' The lower triangular part of A is */ /* supplied in AP. */ /* Unchanged on exit. */ /* N - INTEGER. */ /* On entry, N specifies the order of the matrix A. */ /* N must be at least zero. */ /* Unchanged on exit. */ /* ALPHA - DOUBLE PRECISION. */ /* On entry, ALPHA specifies the scalar alpha. */ /* Unchanged on exit. */ /* AP - DOUBLE PRECISION array of DIMENSION at least */ /* ( ( n*( n + 1 ) )/2 ). */ /* Before entry with UPLO = 'U' or 'u', the array AP must */ /* contain the upper triangular part of the symmetric matrix */ /* packed sequentially, column by column, so that AP( 1 ) */ /* contains a( 1, 1 ), AP( 2 ) and AP( 3 ) contain a( 1, 2 ) */ /* and a( 2, 2 ) respectively, and so on. */ /* Before entry with UPLO = 'L' or 'l', the array AP must */ /* contain the lower triangular part of the symmetric matrix */ /* packed sequentially, column by column, so that AP( 1 ) */ /* contains a( 1, 1 ), AP( 2 ) and AP( 3 ) contain a( 2, 1 ) */ /* and a( 3, 1 ) respectively, and so on. */ /* Unchanged on exit. */ /* X - DOUBLE PRECISION array of dimension at least */ /* ( 1 + ( n - 1 )*abs( INCX ) ). */ /* Before entry, the incremented array X must contain the n */ /* element vector x. */ /* Unchanged on exit. */ /* INCX - INTEGER. */ /* On entry, INCX specifies the increment for the elements of */ /* X. INCX must not be zero. */ /* Unchanged on exit. */ /* BETA - DOUBLE PRECISION. */ /* On entry, BETA specifies the scalar beta. When BETA is */ /* supplied as zero then Y need not be set on input. */ /* Unchanged on exit. */ /* Y - DOUBLE PRECISION array of dimension at least */ /* ( 1 + ( n - 1 )*abs( INCY ) ). */ /* Before entry, the incremented array Y must contain the n */ /* element vector y. On exit, Y is overwritten by the updated */ /* vector y. */ /* INCY - INTEGER. */ /* On entry, INCY specifies the increment for the elements of */ /* Y. INCY must not be zero. */ /* Unchanged on exit. */ /* Level 2 Blas routine. */ /* -- Written on 22-October-1986. */ /* Jack Dongarra, Argonne National Lab. */ /* Jeremy Du Croz, Nag Central Office. */ /* Sven Hammarling, Nag Central Office. */ /* Richard Hanson, Sandia National Labs. */ /* .. Parameters .. */ /* .. Local Scalars .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. */ /* .. Executable Statements .. */ /* Test the input parameters. */ /* Parameter adjustments */ --y; --x; --ap; /* Function Body */ info = 0; if (! PASTEF770(lsame)(uplo, "U", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(uplo, "L", ( ftnlen)1, (ftnlen)1)) { info = 1; } else if (*n < 0) { info = 2; } else if (*incx == 0) { info = 6; } else if (*incy == 0) { info = 9; } if (info != 0) { PASTEF770(xerbla)("DSPMV ", &info, (ftnlen)6); return 0; } /* Quick return if possible. */ if (*n == 0 || (*alpha == 0. && *beta == 1.)) { return 0; } /* Set up the start points in X and Y. */ if (*incx > 0) { kx = 1; } else { kx = 1 - (*n - 1) * *incx; } if (*incy > 0) { ky = 1; } else { ky = 1 - (*n - 1) * *incy; } /* Start the operations. In this version the elements of the array AP */ /* are accessed sequentially with one pass through AP. */ /* First form y := beta*y. */ if (*beta != 1.) { if (*incy == 1) { if (*beta == 0.) { i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { y[i__] = 0.; /* L10: */ } } else { i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { y[i__] = *beta * y[i__]; /* L20: */ } } } else { iy = ky; if (*beta == 0.) { i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { y[iy] = 0.; iy += *incy; /* L30: */ } } else { i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { y[iy] = *beta * y[iy]; iy += *incy; /* L40: */ } } } } if (*alpha == 0.) { return 0; } kk = 1; if (PASTEF770(lsame)(uplo, "U", (ftnlen)1, (ftnlen)1)) { /* Form y when AP contains the upper triangle. */ if (*incx == 1 && *incy == 1) { i__1 = *n; for (j = 1; j <= i__1; ++j) { temp1 = *alpha * x[j]; temp2 = 0.; k = kk; i__2 = j - 1; for (i__ = 1; i__ <= i__2; ++i__) { y[i__] += temp1 * ap[k]; temp2 += ap[k] * x[i__]; ++k; /* L50: */ } y[j] = y[j] + temp1 * ap[kk + j - 1] + *alpha * temp2; kk += j; /* L60: */ } } else { jx = kx; jy = ky; i__1 = *n; for (j = 1; j <= i__1; ++j) { temp1 = *alpha * x[jx]; temp2 = 0.; ix = kx; iy = ky; i__2 = kk + j - 2; for (k = kk; k <= i__2; ++k) { y[iy] += temp1 * ap[k]; temp2 += ap[k] * x[ix]; ix += *incx; iy += *incy; /* L70: */ } y[jy] = y[jy] + temp1 * ap[kk + j - 1] + *alpha * temp2; jx += *incx; jy += *incy; kk += j; /* L80: */ } } } else { /* Form y when AP contains the lower triangle. */ if (*incx == 1 && *incy == 1) { i__1 = *n; for (j = 1; j <= i__1; ++j) { temp1 = *alpha * x[j]; temp2 = 0.; y[j] += temp1 * ap[kk]; k = kk + 1; i__2 = *n; for (i__ = j + 1; i__ <= i__2; ++i__) { y[i__] += temp1 * ap[k]; temp2 += ap[k] * x[i__]; ++k; /* L90: */ } y[j] += *alpha * temp2; kk += *n - j + 1; /* L100: */ } } else { jx = kx; jy = ky; i__1 = *n; for (j = 1; j <= i__1; ++j) { temp1 = *alpha * x[jx]; temp2 = 0.; y[jy] += temp1 * ap[kk]; ix = jx; iy = jy; i__2 = kk + *n - j; for (k = kk + 1; k <= i__2; ++k) { ix += *incx; iy += *incy; y[iy] += temp1 * ap[k]; temp2 += ap[k] * x[ix]; /* L110: */ } y[jy] += *alpha * temp2; jx += *incx; jy += *incy; kk += *n - j + 1; /* L120: */ } } } return 0; /* End of DSPMV . */ } /* dspmv_ */ /* sspmv.f -- translated by f2c (version 19991025). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ /* Subroutine */ int PASTEF77(s,spmv)(const bla_character *uplo, const bla_integer *n, const bla_real *alpha, const bla_real *ap, const bla_real *x, const bla_integer *incx, const bla_real *beta, bla_real *y, const bla_integer *incy) { /* System generated locals */ bla_integer i__1, i__2; /* Local variables */ bla_integer info; bla_real temp1, temp2; bla_integer i__, j, k; //extern bla_logical PASTEF770(lsame)(bla_character *, bla_character *, ftnlen, ftnlen); bla_integer kk, ix, iy, jx, jy, kx, ky; //extern /* Subroutine */ int PASTEF770(xerbla)(bla_character *, bla_integer *, ftnlen); /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* SSPMV performs the matrix-vector operation */ /* y := alpha*A*x + beta*y, */ /* where alpha and beta are scalars, x and y are n element vectors and */ /* A is an n by n symmetric matrix, supplied in packed form. */ /* Parameters */ /* ========== */ /* UPLO - CHARACTER*1. */ /* On entry, UPLO specifies whether the upper or lower */ /* triangular part of the matrix A is supplied in the packed */ /* array AP as follows: */ /* UPLO = 'U' or 'u' The upper triangular part of A is */ /* supplied in AP. */ /* UPLO = 'L' or 'l' The lower triangular part of A is */ /* supplied in AP. */ /* Unchanged on exit. */ /* N - INTEGER. */ /* On entry, N specifies the order of the matrix A. */ /* N must be at least zero. */ /* Unchanged on exit. */ /* ALPHA - REAL . */ /* On entry, ALPHA specifies the scalar alpha. */ /* Unchanged on exit. */ /* AP - REAL array of DIMENSION at least */ /* ( ( n*( n + 1 ) )/2 ). */ /* Before entry with UPLO = 'U' or 'u', the array AP must */ /* contain the upper triangular part of the symmetric matrix */ /* packed sequentially, column by column, so that AP( 1 ) */ /* contains a( 1, 1 ), AP( 2 ) and AP( 3 ) contain a( 1, 2 ) */ /* and a( 2, 2 ) respectively, and so on. */ /* Before entry with UPLO = 'L' or 'l', the array AP must */ /* contain the lower triangular part of the symmetric matrix */ /* packed sequentially, column by column, so that AP( 1 ) */ /* contains a( 1, 1 ), AP( 2 ) and AP( 3 ) contain a( 2, 1 ) */ /* and a( 3, 1 ) respectively, and so on. */ /* Unchanged on exit. */ /* X - REAL array of dimension at least */ /* ( 1 + ( n - 1 )*abs( INCX ) ). */ /* Before entry, the incremented array X must contain the n */ /* element vector x. */ /* Unchanged on exit. */ /* INCX - INTEGER. */ /* On entry, INCX specifies the increment for the elements of */ /* X. INCX must not be zero. */ /* Unchanged on exit. */ /* BETA - REAL . */ /* On entry, BETA specifies the scalar beta. When BETA is */ /* supplied as zero then Y need not be set on input. */ /* Unchanged on exit. */ /* Y - REAL array of dimension at least */ /* ( 1 + ( n - 1 )*abs( INCY ) ). */ /* Before entry, the incremented array Y must contain the n */ /* element vector y. On exit, Y is overwritten by the updated */ /* vector y. */ /* INCY - INTEGER. */ /* On entry, INCY specifies the increment for the elements of */ /* Y. INCY must not be zero. */ /* Unchanged on exit. */ /* Level 2 Blas routine. */ /* -- Written on 22-October-1986. */ /* Jack Dongarra, Argonne National Lab. */ /* Jeremy Du Croz, Nag Central Office. */ /* Sven Hammarling, Nag Central Office. */ /* Richard Hanson, Sandia National Labs. */ /* .. Parameters .. */ /* .. Local Scalars .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. */ /* .. Executable Statements .. */ /* Test the input parameters. */ /* Parameter adjustments */ --y; --x; --ap; /* Function Body */ info = 0; if (! PASTEF770(lsame)(uplo, "U", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(uplo, "L", ( ftnlen)1, (ftnlen)1)) { info = 1; } else if (*n < 0) { info = 2; } else if (*incx == 0) { info = 6; } else if (*incy == 0) { info = 9; } if (info != 0) { PASTEF770(xerbla)("SSPMV ", &info, (ftnlen)6); return 0; } /* Quick return if possible. */ if (*n == 0 || (*alpha == 0.f && *beta == 1.f)) { return 0; } /* Set up the start points in X and Y. */ if (*incx > 0) { kx = 1; } else { kx = 1 - (*n - 1) * *incx; } if (*incy > 0) { ky = 1; } else { ky = 1 - (*n - 1) * *incy; } /* Start the operations. In this version the elements of the array AP */ /* are accessed sequentially with one pass through AP. */ /* First form y := beta*y. */ if (*beta != 1.f) { if (*incy == 1) { if (*beta == 0.f) { i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { y[i__] = 0.f; /* L10: */ } } else { i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { y[i__] = *beta * y[i__]; /* L20: */ } } } else { iy = ky; if (*beta == 0.f) { i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { y[iy] = 0.f; iy += *incy; /* L30: */ } } else { i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { y[iy] = *beta * y[iy]; iy += *incy; /* L40: */ } } } } if (*alpha == 0.f) { return 0; } kk = 1; if (PASTEF770(lsame)(uplo, "U", (ftnlen)1, (ftnlen)1)) { /* Form y when AP contains the upper triangle. */ if (*incx == 1 && *incy == 1) { i__1 = *n; for (j = 1; j <= i__1; ++j) { temp1 = *alpha * x[j]; temp2 = 0.f; k = kk; i__2 = j - 1; for (i__ = 1; i__ <= i__2; ++i__) { y[i__] += temp1 * ap[k]; temp2 += ap[k] * x[i__]; ++k; /* L50: */ } y[j] = y[j] + temp1 * ap[kk + j - 1] + *alpha * temp2; kk += j; /* L60: */ } } else { jx = kx; jy = ky; i__1 = *n; for (j = 1; j <= i__1; ++j) { temp1 = *alpha * x[jx]; temp2 = 0.f; ix = kx; iy = ky; i__2 = kk + j - 2; for (k = kk; k <= i__2; ++k) { y[iy] += temp1 * ap[k]; temp2 += ap[k] * x[ix]; ix += *incx; iy += *incy; /* L70: */ } y[jy] = y[jy] + temp1 * ap[kk + j - 1] + *alpha * temp2; jx += *incx; jy += *incy; kk += j; /* L80: */ } } } else { /* Form y when AP contains the lower triangle. */ if (*incx == 1 && *incy == 1) { i__1 = *n; for (j = 1; j <= i__1; ++j) { temp1 = *alpha * x[j]; temp2 = 0.f; y[j] += temp1 * ap[kk]; k = kk + 1; i__2 = *n; for (i__ = j + 1; i__ <= i__2; ++i__) { y[i__] += temp1 * ap[k]; temp2 += ap[k] * x[i__]; ++k; /* L90: */ } y[j] += *alpha * temp2; kk += *n - j + 1; /* L100: */ } } else { jx = kx; jy = ky; i__1 = *n; for (j = 1; j <= i__1; ++j) { temp1 = *alpha * x[jx]; temp2 = 0.f; y[jy] += temp1 * ap[kk]; ix = jx; iy = jy; i__2 = kk + *n - j; for (k = kk + 1; k <= i__2; ++k) { ix += *incx; iy += *incy; y[iy] += temp1 * ap[k]; temp2 += ap[k] * x[ix]; /* L110: */ } y[jy] += *alpha * temp2; jx += *incx; jy += *incy; kk += *n - j + 1; /* L120: */ } } } return 0; /* End of SSPMV . */ } /* sspmv_ */ #endif blis-0.9.0/frame/compat/f2c/bla_spmv.h000066400000000000000000000042121422157504600174610ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifdef BLIS_ENABLE_BLAS BLIS_EXPORT_BLAS int PASTEF77(d,spmv)(const bla_character *uplo, const bla_integer *n, const bla_double *alpha, const bla_double *ap, const bla_double *x, const bla_integer *incx, const bla_double *beta, bla_double *y, const bla_integer *incy); BLIS_EXPORT_BLAS int PASTEF77(s,spmv)(const bla_character *uplo, const bla_integer *n, const bla_real *alpha, const bla_real *ap, const bla_real *x, const bla_integer *incx, const bla_real *beta, bla_real *y, const bla_integer *incy); #endif blis-0.9.0/frame/compat/f2c/bla_spr.c000066400000000000000000000331001422157504600172710ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #ifdef BLIS_ENABLE_BLAS /* dspr.f -- translated by f2c (version 19991025). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ /* Subroutine */ int PASTEF77(d,spr)(const bla_character *uplo, const bla_integer *n, const bla_double *alpha, const bla_double *x, const bla_integer *incx, bla_double *ap) { /* System generated locals */ bla_integer i__1, i__2; /* Local variables */ bla_integer info; bla_double temp; bla_integer i__, j, k; //extern bla_logical PASTEF770(lsame)(bla_character *, bla_character *, ftnlen, ftnlen); bla_integer kk, ix, jx, kx = 0; //extern /* Subroutine */ int PASTEF770(xerbla)(bla_character *, bla_integer *, ftnlen); /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* DSPR performs the symmetric rank 1 operation */ /* A := alpha*x*x' + A, */ /* where alpha is a bla_real scalar, x is an n element vector and A is an */ /* n by n symmetric matrix, supplied in packed form. */ /* Parameters */ /* ========== */ /* UPLO - CHARACTER*1. */ /* On entry, UPLO specifies whether the upper or lower */ /* triangular part of the matrix A is supplied in the packed */ /* array AP as follows: */ /* UPLO = 'U' or 'u' The upper triangular part of A is */ /* supplied in AP. */ /* UPLO = 'L' or 'l' The lower triangular part of A is */ /* supplied in AP. */ /* Unchanged on exit. */ /* N - INTEGER. */ /* On entry, N specifies the order of the matrix A. */ /* N must be at least zero. */ /* Unchanged on exit. */ /* ALPHA - DOUBLE PRECISION. */ /* On entry, ALPHA specifies the scalar alpha. */ /* Unchanged on exit. */ /* X - DOUBLE PRECISION array of dimension at least */ /* ( 1 + ( n - 1 )*abs( INCX ) ). */ /* Before entry, the incremented array X must contain the n */ /* element vector x. */ /* Unchanged on exit. */ /* INCX - INTEGER. */ /* On entry, INCX specifies the increment for the elements of */ /* X. INCX must not be zero. */ /* Unchanged on exit. */ /* AP - DOUBLE PRECISION array of DIMENSION at least */ /* ( ( n*( n + 1 ) )/2 ). */ /* Before entry with UPLO = 'U' or 'u', the array AP must */ /* contain the upper triangular part of the symmetric matrix */ /* packed sequentially, column by column, so that AP( 1 ) */ /* contains a( 1, 1 ), AP( 2 ) and AP( 3 ) contain a( 1, 2 ) */ /* and a( 2, 2 ) respectively, and so on. On exit, the array */ /* AP is overwritten by the upper triangular part of the */ /* updated matrix. */ /* Before entry with UPLO = 'L' or 'l', the array AP must */ /* contain the lower triangular part of the symmetric matrix */ /* packed sequentially, column by column, so that AP( 1 ) */ /* contains a( 1, 1 ), AP( 2 ) and AP( 3 ) contain a( 2, 1 ) */ /* and a( 3, 1 ) respectively, and so on. On exit, the array */ /* AP is overwritten by the lower triangular part of the */ /* updated matrix. */ /* Level 2 Blas routine. */ /* -- Written on 22-October-1986. */ /* Jack Dongarra, Argonne National Lab. */ /* Jeremy Du Croz, Nag Central Office. */ /* Sven Hammarling, Nag Central Office. */ /* Richard Hanson, Sandia National Labs. */ /* .. Parameters .. */ /* .. Local Scalars .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. */ /* .. Executable Statements .. */ /* Test the input parameters. */ /* Parameter adjustments */ --ap; --x; /* Function Body */ info = 0; if (! PASTEF770(lsame)(uplo, "U", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(uplo, "L", ( ftnlen)1, (ftnlen)1)) { info = 1; } else if (*n < 0) { info = 2; } else if (*incx == 0) { info = 5; } if (info != 0) { PASTEF770(xerbla)("DSPR ", &info, (ftnlen)6); return 0; } /* Quick return if possible. */ if (*n == 0 || *alpha == 0.) { return 0; } /* Set the start point in X if the increment is not unity. */ if (*incx <= 0) { kx = 1 - (*n - 1) * *incx; } else if (*incx != 1) { kx = 1; } /* Start the operations. In this version the elements of the array AP */ /* are accessed sequentially with one pass through AP. */ kk = 1; if (PASTEF770(lsame)(uplo, "U", (ftnlen)1, (ftnlen)1)) { /* Form A when upper triangle is stored in AP. */ if (*incx == 1) { i__1 = *n; for (j = 1; j <= i__1; ++j) { if (x[j] != 0.) { temp = *alpha * x[j]; k = kk; i__2 = j; for (i__ = 1; i__ <= i__2; ++i__) { ap[k] += x[i__] * temp; ++k; /* L10: */ } } kk += j; /* L20: */ } } else { jx = kx; i__1 = *n; for (j = 1; j <= i__1; ++j) { if (x[jx] != 0.) { temp = *alpha * x[jx]; ix = kx; i__2 = kk + j - 1; for (k = kk; k <= i__2; ++k) { ap[k] += x[ix] * temp; ix += *incx; /* L30: */ } } jx += *incx; kk += j; /* L40: */ } } } else { /* Form A when lower triangle is stored in AP. */ if (*incx == 1) { i__1 = *n; for (j = 1; j <= i__1; ++j) { if (x[j] != 0.) { temp = *alpha * x[j]; k = kk; i__2 = *n; for (i__ = j; i__ <= i__2; ++i__) { ap[k] += x[i__] * temp; ++k; /* L50: */ } } kk = kk + *n - j + 1; /* L60: */ } } else { jx = kx; i__1 = *n; for (j = 1; j <= i__1; ++j) { if (x[jx] != 0.) { temp = *alpha * x[jx]; ix = jx; i__2 = kk + *n - j; for (k = kk; k <= i__2; ++k) { ap[k] += x[ix] * temp; ix += *incx; /* L70: */ } } jx += *incx; kk = kk + *n - j + 1; /* L80: */ } } } return 0; /* End of DSPR . */ } /* dspr_ */ /* sspr.f -- translated by f2c (version 19991025). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ /* Subroutine */ int PASTEF77(s,spr)(const bla_character *uplo, const bla_integer *n, const bla_real *alpha, const bla_real *x, const bla_integer *incx, bla_real *ap) { /* System generated locals */ bla_integer i__1, i__2; /* Local variables */ bla_integer info; bla_real temp; bla_integer i__, j, k; //extern bla_logical PASTEF770(lsame)(bla_character *, bla_character *, ftnlen, ftnlen); bla_integer kk, ix, jx, kx = 0; //extern /* Subroutine */ int PASTEF770(xerbla)(bla_character *, bla_integer *, ftnlen); /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* SSPR performs the symmetric rank 1 operation */ /* A := alpha*x*x' + A, */ /* where alpha is a bla_real scalar, x is an n element vector and A is an */ /* n by n symmetric matrix, supplied in packed form. */ /* Parameters */ /* ========== */ /* UPLO - CHARACTER*1. */ /* On entry, UPLO specifies whether the upper or lower */ /* triangular part of the matrix A is supplied in the packed */ /* array AP as follows: */ /* UPLO = 'U' or 'u' The upper triangular part of A is */ /* supplied in AP. */ /* UPLO = 'L' or 'l' The lower triangular part of A is */ /* supplied in AP. */ /* Unchanged on exit. */ /* N - INTEGER. */ /* On entry, N specifies the order of the matrix A. */ /* N must be at least zero. */ /* Unchanged on exit. */ /* ALPHA - REAL . */ /* On entry, ALPHA specifies the scalar alpha. */ /* Unchanged on exit. */ /* X - REAL array of dimension at least */ /* ( 1 + ( n - 1 )*abs( INCX ) ). */ /* Before entry, the incremented array X must contain the n */ /* element vector x. */ /* Unchanged on exit. */ /* INCX - INTEGER. */ /* On entry, INCX specifies the increment for the elements of */ /* X. INCX must not be zero. */ /* Unchanged on exit. */ /* AP - REAL array of DIMENSION at least */ /* ( ( n*( n + 1 ) )/2 ). */ /* Before entry with UPLO = 'U' or 'u', the array AP must */ /* contain the upper triangular part of the symmetric matrix */ /* packed sequentially, column by column, so that AP( 1 ) */ /* contains a( 1, 1 ), AP( 2 ) and AP( 3 ) contain a( 1, 2 ) */ /* and a( 2, 2 ) respectively, and so on. On exit, the array */ /* AP is overwritten by the upper triangular part of the */ /* updated matrix. */ /* Before entry with UPLO = 'L' or 'l', the array AP must */ /* contain the lower triangular part of the symmetric matrix */ /* packed sequentially, column by column, so that AP( 1 ) */ /* contains a( 1, 1 ), AP( 2 ) and AP( 3 ) contain a( 2, 1 ) */ /* and a( 3, 1 ) respectively, and so on. On exit, the array */ /* AP is overwritten by the lower triangular part of the */ /* updated matrix. */ /* Level 2 Blas routine. */ /* -- Written on 22-October-1986. */ /* Jack Dongarra, Argonne National Lab. */ /* Jeremy Du Croz, Nag Central Office. */ /* Sven Hammarling, Nag Central Office. */ /* Richard Hanson, Sandia National Labs. */ /* .. Parameters .. */ /* .. Local Scalars .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. */ /* .. Executable Statements .. */ /* Test the input parameters. */ /* Parameter adjustments */ --ap; --x; /* Function Body */ info = 0; if (! PASTEF770(lsame)(uplo, "U", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(uplo, "L", ( ftnlen)1, (ftnlen)1)) { info = 1; } else if (*n < 0) { info = 2; } else if (*incx == 0) { info = 5; } if (info != 0) { PASTEF770(xerbla)("SSPR ", &info, (ftnlen)6); return 0; } /* Quick return if possible. */ if (*n == 0 || *alpha == 0.f) { return 0; } /* Set the start point in X if the increment is not unity. */ if (*incx <= 0) { kx = 1 - (*n - 1) * *incx; } else if (*incx != 1) { kx = 1; } /* Start the operations. In this version the elements of the array AP */ /* are accessed sequentially with one pass through AP. */ kk = 1; if (PASTEF770(lsame)(uplo, "U", (ftnlen)1, (ftnlen)1)) { /* Form A when upper triangle is stored in AP. */ if (*incx == 1) { i__1 = *n; for (j = 1; j <= i__1; ++j) { if (x[j] != 0.f) { temp = *alpha * x[j]; k = kk; i__2 = j; for (i__ = 1; i__ <= i__2; ++i__) { ap[k] += x[i__] * temp; ++k; /* L10: */ } } kk += j; /* L20: */ } } else { jx = kx; i__1 = *n; for (j = 1; j <= i__1; ++j) { if (x[jx] != 0.f) { temp = *alpha * x[jx]; ix = kx; i__2 = kk + j - 1; for (k = kk; k <= i__2; ++k) { ap[k] += x[ix] * temp; ix += *incx; /* L30: */ } } jx += *incx; kk += j; /* L40: */ } } } else { /* Form A when lower triangle is stored in AP. */ if (*incx == 1) { i__1 = *n; for (j = 1; j <= i__1; ++j) { if (x[j] != 0.f) { temp = *alpha * x[j]; k = kk; i__2 = *n; for (i__ = j; i__ <= i__2; ++i__) { ap[k] += x[i__] * temp; ++k; /* L50: */ } } kk = kk + *n - j + 1; /* L60: */ } } else { jx = kx; i__1 = *n; for (j = 1; j <= i__1; ++j) { if (x[jx] != 0.f) { temp = *alpha * x[jx]; ix = jx; i__2 = kk + *n - j; for (k = kk; k <= i__2; ++k) { ap[k] += x[ix] * temp; ix += *incx; /* L70: */ } } jx += *incx; kk = kk + *n - j + 1; /* L80: */ } } } return 0; /* End of SSPR . */ } /* sspr_ */ #endif blis-0.9.0/frame/compat/f2c/bla_spr.h000066400000000000000000000040001422157504600172730ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifdef BLIS_ENABLE_BLAS BLIS_EXPORT_BLAS int PASTEF77(d,spr)(const bla_character *uplo, const bla_integer *n, const bla_double *alpha, const bla_double *x, const bla_integer *incx, bla_double *ap); BLIS_EXPORT_BLAS int PASTEF77(s,spr)(const bla_character *uplo, const bla_integer *n, const bla_real *alpha, const bla_real *x, const bla_integer *incx, bla_real *ap); #endif blis-0.9.0/frame/compat/f2c/bla_spr2.c000066400000000000000000000372721422157504600173710ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #ifdef BLIS_ENABLE_BLAS /* dspr2.f -- translated by f2c (version 19991025). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ /* Subroutine */ int PASTEF77(d,spr2)(const bla_character *uplo, const bla_integer *n, const bla_double *alpha, const bla_double *x, const bla_integer *incx, const bla_double *y, const bla_integer *incy, bla_double *ap) { /* System generated locals */ bla_integer i__1, i__2; /* Local variables */ bla_integer info; bla_double temp1, temp2; bla_integer i__, j, k; //extern bla_logical PASTEF770(lsame)(bla_character *, bla_character *, ftnlen, ftnlen); bla_integer kk, ix, iy, jx = 0, jy = 0, kx = 0, ky = 0; //extern /* Subroutine */ int PASTEF770(xerbla)(bla_character *, bla_integer *, ftnlen); /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* DSPR2 performs the symmetric rank 2 operation */ /* A := alpha*x*y' + alpha*y*x' + A, */ /* where alpha is a scalar, x and y are n element vectors and A is an */ /* n by n symmetric matrix, supplied in packed form. */ /* Parameters */ /* ========== */ /* UPLO - CHARACTER*1. */ /* On entry, UPLO specifies whether the upper or lower */ /* triangular part of the matrix A is supplied in the packed */ /* array AP as follows: */ /* UPLO = 'U' or 'u' The upper triangular part of A is */ /* supplied in AP. */ /* UPLO = 'L' or 'l' The lower triangular part of A is */ /* supplied in AP. */ /* Unchanged on exit. */ /* N - INTEGER. */ /* On entry, N specifies the order of the matrix A. */ /* N must be at least zero. */ /* Unchanged on exit. */ /* ALPHA - DOUBLE PRECISION. */ /* On entry, ALPHA specifies the scalar alpha. */ /* Unchanged on exit. */ /* X - DOUBLE PRECISION array of dimension at least */ /* ( 1 + ( n - 1 )*abs( INCX ) ). */ /* Before entry, the incremented array X must contain the n */ /* element vector x. */ /* Unchanged on exit. */ /* INCX - INTEGER. */ /* On entry, INCX specifies the increment for the elements of */ /* X. INCX must not be zero. */ /* Unchanged on exit. */ /* Y - DOUBLE PRECISION array of dimension at least */ /* ( 1 + ( n - 1 )*abs( INCY ) ). */ /* Before entry, the incremented array Y must contain the n */ /* element vector y. */ /* Unchanged on exit. */ /* INCY - INTEGER. */ /* On entry, INCY specifies the increment for the elements of */ /* Y. INCY must not be zero. */ /* Unchanged on exit. */ /* AP - DOUBLE PRECISION array of DIMENSION at least */ /* ( ( n*( n + 1 ) )/2 ). */ /* Before entry with UPLO = 'U' or 'u', the array AP must */ /* contain the upper triangular part of the symmetric matrix */ /* packed sequentially, column by column, so that AP( 1 ) */ /* contains a( 1, 1 ), AP( 2 ) and AP( 3 ) contain a( 1, 2 ) */ /* and a( 2, 2 ) respectively, and so on. On exit, the array */ /* AP is overwritten by the upper triangular part of the */ /* updated matrix. */ /* Before entry with UPLO = 'L' or 'l', the array AP must */ /* contain the lower triangular part of the symmetric matrix */ /* packed sequentially, column by column, so that AP( 1 ) */ /* contains a( 1, 1 ), AP( 2 ) and AP( 3 ) contain a( 2, 1 ) */ /* and a( 3, 1 ) respectively, and so on. On exit, the array */ /* AP is overwritten by the lower triangular part of the */ /* updated matrix. */ /* Level 2 Blas routine. */ /* -- Written on 22-October-1986. */ /* Jack Dongarra, Argonne National Lab. */ /* Jeremy Du Croz, Nag Central Office. */ /* Sven Hammarling, Nag Central Office. */ /* Richard Hanson, Sandia National Labs. */ /* .. Parameters .. */ /* .. Local Scalars .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. */ /* .. Executable Statements .. */ /* Test the input parameters. */ /* Parameter adjustments */ --ap; --y; --x; /* Function Body */ info = 0; if (! PASTEF770(lsame)(uplo, "U", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(uplo, "L", ( ftnlen)1, (ftnlen)1)) { info = 1; } else if (*n < 0) { info = 2; } else if (*incx == 0) { info = 5; } else if (*incy == 0) { info = 7; } if (info != 0) { PASTEF770(xerbla)("DSPR2 ", &info, (ftnlen)6); return 0; } /* Quick return if possible. */ if (*n == 0 || *alpha == 0.) { return 0; } /* Set up the start points in X and Y if the increments are not both */ /* unity. */ if (*incx != 1 || *incy != 1) { if (*incx > 0) { kx = 1; } else { kx = 1 - (*n - 1) * *incx; } if (*incy > 0) { ky = 1; } else { ky = 1 - (*n - 1) * *incy; } jx = kx; jy = ky; } /* Start the operations. In this version the elements of the array AP */ /* are accessed sequentially with one pass through AP. */ kk = 1; if (PASTEF770(lsame)(uplo, "U", (ftnlen)1, (ftnlen)1)) { /* Form A when upper triangle is stored in AP. */ if (*incx == 1 && *incy == 1) { i__1 = *n; for (j = 1; j <= i__1; ++j) { if (x[j] != 0. || y[j] != 0.) { temp1 = *alpha * y[j]; temp2 = *alpha * x[j]; k = kk; i__2 = j; for (i__ = 1; i__ <= i__2; ++i__) { ap[k] = ap[k] + x[i__] * temp1 + y[i__] * temp2; ++k; /* L10: */ } } kk += j; /* L20: */ } } else { i__1 = *n; for (j = 1; j <= i__1; ++j) { if (x[jx] != 0. || y[jy] != 0.) { temp1 = *alpha * y[jy]; temp2 = *alpha * x[jx]; ix = kx; iy = ky; i__2 = kk + j - 1; for (k = kk; k <= i__2; ++k) { ap[k] = ap[k] + x[ix] * temp1 + y[iy] * temp2; ix += *incx; iy += *incy; /* L30: */ } } jx += *incx; jy += *incy; kk += j; /* L40: */ } } } else { /* Form A when lower triangle is stored in AP. */ if (*incx == 1 && *incy == 1) { i__1 = *n; for (j = 1; j <= i__1; ++j) { if (x[j] != 0. || y[j] != 0.) { temp1 = *alpha * y[j]; temp2 = *alpha * x[j]; k = kk; i__2 = *n; for (i__ = j; i__ <= i__2; ++i__) { ap[k] = ap[k] + x[i__] * temp1 + y[i__] * temp2; ++k; /* L50: */ } } kk = kk + *n - j + 1; /* L60: */ } } else { i__1 = *n; for (j = 1; j <= i__1; ++j) { if (x[jx] != 0. || y[jy] != 0.) { temp1 = *alpha * y[jy]; temp2 = *alpha * x[jx]; ix = jx; iy = jy; i__2 = kk + *n - j; for (k = kk; k <= i__2; ++k) { ap[k] = ap[k] + x[ix] * temp1 + y[iy] * temp2; ix += *incx; iy += *incy; /* L70: */ } } jx += *incx; jy += *incy; kk = kk + *n - j + 1; /* L80: */ } } } return 0; /* End of DSPR2 . */ } /* dspr2_ */ /* sspr2.f -- translated by f2c (version 19991025). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ /* Subroutine */ int PASTEF77(s,spr2)(const bla_character *uplo, const bla_integer *n, const bla_real *alpha, const bla_real *x, const bla_integer *incx, const bla_real *y, const bla_integer *incy, bla_real *ap) { /* System generated locals */ bla_integer i__1, i__2; /* Local variables */ bla_integer info; bla_real temp1, temp2; bla_integer i__, j, k; //extern bla_logical PASTEF770(lsame)(bla_character *, bla_character *, ftnlen, ftnlen); bla_integer kk, ix, iy, jx = 0, jy = 0, kx = 0, ky = 0; //extern /* Subroutine */ int PASTEF770(xerbla)(bla_character *, bla_integer *, ftnlen); /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* SSPR2 performs the symmetric rank 2 operation */ /* A := alpha*x*y' + alpha*y*x' + A, */ /* where alpha is a scalar, x and y are n element vectors and A is an */ /* n by n symmetric matrix, supplied in packed form. */ /* Parameters */ /* ========== */ /* UPLO - CHARACTER*1. */ /* On entry, UPLO specifies whether the upper or lower */ /* triangular part of the matrix A is supplied in the packed */ /* array AP as follows: */ /* UPLO = 'U' or 'u' The upper triangular part of A is */ /* supplied in AP. */ /* UPLO = 'L' or 'l' The lower triangular part of A is */ /* supplied in AP. */ /* Unchanged on exit. */ /* N - INTEGER. */ /* On entry, N specifies the order of the matrix A. */ /* N must be at least zero. */ /* Unchanged on exit. */ /* ALPHA - REAL . */ /* On entry, ALPHA specifies the scalar alpha. */ /* Unchanged on exit. */ /* X - REAL array of dimension at least */ /* ( 1 + ( n - 1 )*abs( INCX ) ). */ /* Before entry, the incremented array X must contain the n */ /* element vector x. */ /* Unchanged on exit. */ /* INCX - INTEGER. */ /* On entry, INCX specifies the increment for the elements of */ /* X. INCX must not be zero. */ /* Unchanged on exit. */ /* Y - REAL array of dimension at least */ /* ( 1 + ( n - 1 )*abs( INCY ) ). */ /* Before entry, the incremented array Y must contain the n */ /* element vector y. */ /* Unchanged on exit. */ /* INCY - INTEGER. */ /* On entry, INCY specifies the increment for the elements of */ /* Y. INCY must not be zero. */ /* Unchanged on exit. */ /* AP - REAL array of DIMENSION at least */ /* ( ( n*( n + 1 ) )/2 ). */ /* Before entry with UPLO = 'U' or 'u', the array AP must */ /* contain the upper triangular part of the symmetric matrix */ /* packed sequentially, column by column, so that AP( 1 ) */ /* contains a( 1, 1 ), AP( 2 ) and AP( 3 ) contain a( 1, 2 ) */ /* and a( 2, 2 ) respectively, and so on. On exit, the array */ /* AP is overwritten by the upper triangular part of the */ /* updated matrix. */ /* Before entry with UPLO = 'L' or 'l', the array AP must */ /* contain the lower triangular part of the symmetric matrix */ /* packed sequentially, column by column, so that AP( 1 ) */ /* contains a( 1, 1 ), AP( 2 ) and AP( 3 ) contain a( 2, 1 ) */ /* and a( 3, 1 ) respectively, and so on. On exit, the array */ /* AP is overwritten by the lower triangular part of the */ /* updated matrix. */ /* Level 2 Blas routine. */ /* -- Written on 22-October-1986. */ /* Jack Dongarra, Argonne National Lab. */ /* Jeremy Du Croz, Nag Central Office. */ /* Sven Hammarling, Nag Central Office. */ /* Richard Hanson, Sandia National Labs. */ /* .. Parameters .. */ /* .. Local Scalars .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. */ /* .. Executable Statements .. */ /* Test the input parameters. */ /* Parameter adjustments */ --ap; --y; --x; /* Function Body */ info = 0; if (! PASTEF770(lsame)(uplo, "U", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(uplo, "L", ( ftnlen)1, (ftnlen)1)) { info = 1; } else if (*n < 0) { info = 2; } else if (*incx == 0) { info = 5; } else if (*incy == 0) { info = 7; } if (info != 0) { PASTEF770(xerbla)("SSPR2 ", &info, (ftnlen)6); return 0; } /* Quick return if possible. */ if (*n == 0 || *alpha == 0.f) { return 0; } /* Set up the start points in X and Y if the increments are not both */ /* unity. */ if (*incx != 1 || *incy != 1) { if (*incx > 0) { kx = 1; } else { kx = 1 - (*n - 1) * *incx; } if (*incy > 0) { ky = 1; } else { ky = 1 - (*n - 1) * *incy; } jx = kx; jy = ky; } /* Start the operations. In this version the elements of the array AP */ /* are accessed sequentially with one pass through AP. */ kk = 1; if (PASTEF770(lsame)(uplo, "U", (ftnlen)1, (ftnlen)1)) { /* Form A when upper triangle is stored in AP. */ if (*incx == 1 && *incy == 1) { i__1 = *n; for (j = 1; j <= i__1; ++j) { if (x[j] != 0.f || y[j] != 0.f) { temp1 = *alpha * y[j]; temp2 = *alpha * x[j]; k = kk; i__2 = j; for (i__ = 1; i__ <= i__2; ++i__) { ap[k] = ap[k] + x[i__] * temp1 + y[i__] * temp2; ++k; /* L10: */ } } kk += j; /* L20: */ } } else { i__1 = *n; for (j = 1; j <= i__1; ++j) { if (x[jx] != 0.f || y[jy] != 0.f) { temp1 = *alpha * y[jy]; temp2 = *alpha * x[jx]; ix = kx; iy = ky; i__2 = kk + j - 1; for (k = kk; k <= i__2; ++k) { ap[k] = ap[k] + x[ix] * temp1 + y[iy] * temp2; ix += *incx; iy += *incy; /* L30: */ } } jx += *incx; jy += *incy; kk += j; /* L40: */ } } } else { /* Form A when lower triangle is stored in AP. */ if (*incx == 1 && *incy == 1) { i__1 = *n; for (j = 1; j <= i__1; ++j) { if (x[j] != 0.f || y[j] != 0.f) { temp1 = *alpha * y[j]; temp2 = *alpha * x[j]; k = kk; i__2 = *n; for (i__ = j; i__ <= i__2; ++i__) { ap[k] = ap[k] + x[i__] * temp1 + y[i__] * temp2; ++k; /* L50: */ } } kk = kk + *n - j + 1; /* L60: */ } } else { i__1 = *n; for (j = 1; j <= i__1; ++j) { if (x[jx] != 0.f || y[jy] != 0.f) { temp1 = *alpha * y[jy]; temp2 = *alpha * x[jx]; ix = jx; iy = jy; i__2 = kk + *n - j; for (k = kk; k <= i__2; ++k) { ap[k] = ap[k] + x[ix] * temp1 + y[iy] * temp2; ix += *incx; iy += *incy; /* L70: */ } } jx += *incx; jy += *incy; kk = kk + *n - j + 1; /* L80: */ } } } return 0; /* End of SSPR2 . */ } /* sspr2_ */ #endif blis-0.9.0/frame/compat/f2c/bla_spr2.h000066400000000000000000000041341422157504600173650ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifdef BLIS_ENABLE_BLAS BLIS_EXPORT_BLAS int PASTEF77(d,spr2)(const bla_character *uplo, const bla_integer *n, const bla_double *alpha, const bla_double *x, const bla_integer *incx, const bla_double *y, const bla_integer *incy, bla_double *ap); BLIS_EXPORT_BLAS int PASTEF77(s,spr2)(const bla_character *uplo, const bla_integer *n, const bla_real *alpha, const bla_real *x, const bla_integer *incx, const bla_real *y, const bla_integer *incy, bla_real *ap); #endif blis-0.9.0/frame/compat/f2c/bla_tbmv.c000066400000000000000000002041231422157504600174420ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #ifdef BLIS_ENABLE_BLAS /* ctbmv.f -- translated by f2c (version 19991025). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ /* Subroutine */ int PASTEF77(c,tbmv)(const bla_character *uplo, const bla_character *trans, const bla_character *diag, const bla_integer *n, const bla_integer *k, const bla_scomplex *a, const bla_integer *lda, bla_scomplex *x, const bla_integer *incx) { /* System generated locals */ bla_integer a_dim1, a_offset, i__1, i__2, i__3, i__4, i__5; bla_scomplex q__1, q__2, q__3; /* Builtin functions */ //void bla_r_cnjg(bla_scomplex *, bla_scomplex *); /* Local variables */ bla_integer info; bla_scomplex temp; bla_integer i__, j, l; //extern bla_logical PASTEF770(lsame)(bla_character *, bla_character *, ftnlen, ftnlen); bla_integer kplus1, ix, jx, kx = 0; //extern /* Subroutine */ int PASTEF770(xerbla)(bla_character *, bla_integer *, ftnlen); bla_logical noconj, nounit; /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* CTBMV performs one of the matrix-vector operations */ /* x := A*x, or x := A'*x, or x := conjg( A' )*x, */ /* where x is an n element vector and A is an n by n unit, or non-unit, */ /* upper or lower triangular band matrix, with ( k + 1 ) diagonals. */ /* Parameters */ /* ========== */ /* UPLO - CHARACTER*1. */ /* On entry, UPLO specifies whether the matrix is an upper or */ /* lower triangular matrix as follows: */ /* UPLO = 'U' or 'u' A is an upper triangular matrix. */ /* UPLO = 'L' or 'l' A is a lower triangular matrix. */ /* Unchanged on exit. */ /* TRANS - CHARACTER*1. */ /* On entry, TRANS specifies the operation to be performed as */ /* follows: */ /* TRANS = 'N' or 'n' x := A*x. */ /* TRANS = 'T' or 't' x := A'*x. */ /* TRANS = 'C' or 'c' x := conjg( A' )*x. */ /* Unchanged on exit. */ /* DIAG - CHARACTER*1. */ /* On entry, DIAG specifies whether or not A is unit */ /* triangular as follows: */ /* DIAG = 'U' or 'u' A is assumed to be unit triangular. */ /* DIAG = 'N' or 'n' A is not assumed to be unit */ /* triangular. */ /* Unchanged on exit. */ /* N - INTEGER. */ /* On entry, N specifies the order of the matrix A. */ /* N must be at least zero. */ /* Unchanged on exit. */ /* K - INTEGER. */ /* On entry with UPLO = 'U' or 'u', K specifies the number of */ /* super-diagonals of the matrix A. */ /* On entry with UPLO = 'L' or 'l', K specifies the number of */ /* sub-diagonals of the matrix A. */ /* K must satisfy 0 .le. K. */ /* Unchanged on exit. */ /* A - COMPLEX array of DIMENSION ( LDA, n ). */ /* Before entry with UPLO = 'U' or 'u', the leading ( k + 1 ) */ /* by n part of the array A must contain the upper triangular */ /* band part of the matrix of coefficients, supplied column by */ /* column, with the leading diagonal of the matrix in row */ /* ( k + 1 ) of the array, the first super-diagonal starting at */ /* position 2 in row k, and so on. The top left k by k triangle */ /* of the array A is not referenced. */ /* The following program segment will transfer an upper */ /* triangular band matrix from conventional full matrix storage */ /* to band storage: */ /* DO 20, J = 1, N */ /* M = K + 1 - J */ /* DO 10, I = MAX( 1, J - K ), J */ /* A( M + I, J ) = matrix( I, J ) */ /* 10 CONTINUE */ /* 20 CONTINUE */ /* Before entry with UPLO = 'L' or 'l', the leading ( k + 1 ) */ /* by n part of the array A must contain the lower triangular */ /* band part of the matrix of coefficients, supplied column by */ /* column, with the leading diagonal of the matrix in row 1 of */ /* the array, the first sub-diagonal starting at position 1 in */ /* row 2, and so on. The bottom right k by k triangle of the */ /* array A is not referenced. */ /* The following program segment will transfer a lower */ /* triangular band matrix from conventional full matrix storage */ /* to band storage: */ /* DO 20, J = 1, N */ /* M = 1 - J */ /* DO 10, I = J, MIN( N, J + K ) */ /* A( M + I, J ) = matrix( I, J ) */ /* 10 CONTINUE */ /* 20 CONTINUE */ /* Note that when DIAG = 'U' or 'u' the elements of the array A */ /* corresponding to the diagonal elements of the matrix are not */ /* referenced, but are assumed to be unity. */ /* Unchanged on exit. */ /* LDA - INTEGER. */ /* On entry, LDA specifies the first dimension of A as declared */ /* in the calling (sub) program. LDA must be at least */ /* ( k + 1 ). */ /* Unchanged on exit. */ /* X - COMPLEX array of dimension at least */ /* ( 1 + ( n - 1 )*abs( INCX ) ). */ /* Before entry, the incremented array X must contain the n */ /* element vector x. On exit, X is overwritten with the */ /* tranformed vector x. */ /* INCX - INTEGER. */ /* On entry, INCX specifies the increment for the elements of */ /* X. INCX must not be zero. */ /* Unchanged on exit. */ /* Level 2 Blas routine. */ /* -- Written on 22-October-1986. */ /* Jack Dongarra, Argonne National Lab. */ /* Jeremy Du Croz, Nag Central Office. */ /* Sven Hammarling, Nag Central Office. */ /* Richard Hanson, Sandia National Labs. */ /* .. Parameters .. */ /* .. Local Scalars .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. */ /* .. Executable Statements .. */ /* Test the input parameters. */ /* Parameter adjustments */ a_dim1 = *lda; a_offset = 1 + a_dim1 * 1; a -= a_offset; --x; /* Function Body */ info = 0; if (! PASTEF770(lsame)(uplo, "U", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(uplo, "L", ( ftnlen)1, (ftnlen)1)) { info = 1; } else if (! PASTEF770(lsame)(trans, "N", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(trans, "T", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(trans, "C", (ftnlen)1, ( ftnlen)1)) { info = 2; } else if (! PASTEF770(lsame)(diag, "U", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(diag, "N", (ftnlen)1, (ftnlen)1)) { info = 3; } else if (*n < 0) { info = 4; } else if (*k < 0) { info = 5; } else if (*lda < *k + 1) { info = 7; } else if (*incx == 0) { info = 9; } if (info != 0) { PASTEF770(xerbla)("CTBMV ", &info, (ftnlen)6); return 0; } /* Quick return if possible. */ if (*n == 0) { return 0; } noconj = PASTEF770(lsame)(trans, "T", (ftnlen)1, (ftnlen)1); nounit = PASTEF770(lsame)(diag, "N", (ftnlen)1, (ftnlen)1); /* Set up the start point in X if the increment is not unity. This */ /* will be ( N - 1 )*INCX too small for descending loops. */ if (*incx <= 0) { kx = 1 - (*n - 1) * *incx; } else if (*incx != 1) { kx = 1; } /* Start the operations. In this version the elements of A are */ /* accessed sequentially with one pass through A. */ if (PASTEF770(lsame)(trans, "N", (ftnlen)1, (ftnlen)1)) { /* Form x := A*x. */ if (PASTEF770(lsame)(uplo, "U", (ftnlen)1, (ftnlen)1)) { kplus1 = *k + 1; if (*incx == 1) { i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = j; if (bli_creal(x[i__2]) != 0.f || bli_cimag(x[i__2]) != 0.f) { i__2 = j; bli_csets( (bli_creal(x[i__2])), (bli_cimag(x[i__2])), temp ); l = kplus1 - j; /* Computing MAX */ i__2 = 1, i__3 = j - *k; i__4 = j - 1; for (i__ = f2c_max(i__2,i__3); i__ <= i__4; ++i__) { i__2 = i__; i__3 = i__; i__5 = l + i__ + j * a_dim1; bli_csets( (bli_creal(temp) * bli_creal(a[i__5]) - bli_cimag(temp) * bli_cimag(a[i__5])), (bli_creal(temp) * bli_cimag(a[i__5]) + bli_cimag(temp) * bli_creal(a[i__5])), q__2 ); bli_csets( (bli_creal(x[i__3]) + bli_creal(q__2)), (bli_cimag(x[i__3]) + bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), x[i__2] ); /* L10: */ } if (nounit) { i__4 = j; i__2 = j; i__3 = kplus1 + j * a_dim1; bli_csets( (bli_creal(x[i__2]) * bli_creal(a[i__3]) - bli_cimag(x[i__2]) * bli_cimag(a[i__3])), (bli_creal(x[i__2]) * bli_cimag(a[i__3]) + bli_cimag(x[i__2]) * bli_creal(a[i__3])), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), x[i__4] ); } } /* L20: */ } } else { jx = kx; i__1 = *n; for (j = 1; j <= i__1; ++j) { i__4 = jx; if (bli_creal(x[i__4]) != 0.f || bli_cimag(x[i__4]) != 0.f) { i__4 = jx; bli_csets( (bli_creal(x[i__4])), (bli_cimag(x[i__4])), temp ); ix = kx; l = kplus1 - j; /* Computing MAX */ i__4 = 1, i__2 = j - *k; i__3 = j - 1; for (i__ = f2c_max(i__4,i__2); i__ <= i__3; ++i__) { i__4 = ix; i__2 = ix; i__5 = l + i__ + j * a_dim1; bli_csets( (bli_creal(temp) * bli_creal(a[i__5]) - bli_cimag(temp) * bli_cimag(a[i__5])), (bli_creal(temp) * bli_cimag(a[i__5]) + bli_cimag(temp) * bli_creal(a[i__5])), q__2 ); bli_csets( (bli_creal(x[i__2]) + bli_creal(q__2)), (bli_cimag(x[i__2]) + bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), x[i__4] ); ix += *incx; /* L30: */ } if (nounit) { i__3 = jx; i__4 = jx; i__2 = kplus1 + j * a_dim1; bli_csets( (bli_creal(x[i__4]) * bli_creal(a[i__2]) - bli_cimag(x[i__4]) * bli_cimag(a[i__2])), (bli_creal(x[i__4]) * bli_cimag(a[i__2]) + bli_cimag(x[i__4]) * bli_creal(a[i__2])), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), x[i__3] ); } } jx += *incx; if (j > *k) { kx += *incx; } /* L40: */ } } } else { if (*incx == 1) { for (j = *n; j >= 1; --j) { i__1 = j; if (bli_creal(x[i__1]) != 0.f || bli_cimag(x[i__1]) != 0.f) { i__1 = j; bli_csets( (bli_creal(x[i__1])), (bli_cimag(x[i__1])), temp ); l = 1 - j; /* Computing MIN */ i__1 = *n, i__3 = j + *k; i__4 = j + 1; for (i__ = f2c_min(i__1,i__3); i__ >= i__4; --i__) { i__1 = i__; i__3 = i__; i__2 = l + i__ + j * a_dim1; bli_csets( (bli_creal(temp) * bli_creal(a[i__2]) - bli_cimag(temp) * bli_cimag(a[i__2])), (bli_creal(temp) * bli_cimag(a[i__2]) + bli_cimag(temp) * bli_creal(a[i__2])), q__2 ); bli_csets( (bli_creal(x[i__3]) + bli_creal(q__2)), (bli_cimag(x[i__3]) + bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), x[i__1] ); /* L50: */ } if (nounit) { i__4 = j; i__1 = j; i__3 = j * a_dim1 + 1; bli_csets( (bli_creal(x[i__1]) * bli_creal(a[i__3]) - bli_cimag(x[i__1]) * bli_cimag(a[i__3])), (bli_creal(x[i__1]) * bli_cimag(a[i__3]) + bli_cimag(x[i__1]) * bli_creal(a[i__3])), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), x[i__4] ); } } /* L60: */ } } else { kx += (*n - 1) * *incx; jx = kx; for (j = *n; j >= 1; --j) { i__4 = jx; if (bli_creal(x[i__4]) != 0.f || bli_cimag(x[i__4]) != 0.f) { i__4 = jx; bli_csets( (bli_creal(x[i__4])), (bli_cimag(x[i__4])), temp ); ix = kx; l = 1 - j; /* Computing MIN */ i__4 = *n, i__1 = j + *k; i__3 = j + 1; for (i__ = f2c_min(i__4,i__1); i__ >= i__3; --i__) { i__4 = ix; i__1 = ix; i__2 = l + i__ + j * a_dim1; bli_csets( (bli_creal(temp) * bli_creal(a[i__2]) - bli_cimag(temp) * bli_cimag(a[i__2])), (bli_creal(temp) * bli_cimag(a[i__2]) + bli_cimag(temp) * bli_creal(a[i__2])), q__2 ); bli_csets( (bli_creal(x[i__1]) + bli_creal(q__2)), (bli_cimag(x[i__1]) + bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), x[i__4] ); ix -= *incx; /* L70: */ } if (nounit) { i__3 = jx; i__4 = jx; i__1 = j * a_dim1 + 1; bli_csets( (bli_creal(x[i__4]) * bli_creal(a[i__1]) - bli_cimag(x[i__4]) * bli_cimag(a[i__1])), (bli_creal(x[i__4]) * bli_cimag(a[i__1]) + bli_cimag(x[i__4]) * bli_creal(a[i__1])), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), x[i__3] ); } } jx -= *incx; if (*n - j >= *k) { kx -= *incx; } /* L80: */ } } } } else { /* Form x := A'*x or x := conjg( A' )*x. */ if (PASTEF770(lsame)(uplo, "U", (ftnlen)1, (ftnlen)1)) { kplus1 = *k + 1; if (*incx == 1) { for (j = *n; j >= 1; --j) { i__3 = j; bli_csets( (bli_creal(x[i__3])), (bli_cimag(x[i__3])), temp ); l = kplus1 - j; if (noconj) { if (nounit) { i__3 = kplus1 + j * a_dim1; bli_csets( (bli_creal(temp) * bli_creal(a[i__3]) - bli_cimag(temp) * bli_cimag(a[i__3])), (bli_creal(temp) * bli_cimag(a[i__3]) + bli_cimag(temp) * bli_creal(a[i__3])), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp ); } /* Computing MAX */ i__4 = 1, i__1 = j - *k; i__3 = f2c_max(i__4,i__1); for (i__ = j - 1; i__ >= i__3; --i__) { i__4 = l + i__ + j * a_dim1; i__1 = i__; bli_csets( (bli_creal(a[i__4]) * bli_creal(x[i__1]) - bli_cimag(a[i__4]) * bli_cimag(x[i__1])), (bli_creal(a[i__4]) * bli_cimag(x[i__1]) + bli_cimag(a[i__4]) * bli_creal(x[i__1])), q__2 ); bli_csets( (bli_creal(temp) + bli_creal(q__2)), (bli_cimag(temp) + bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp ); /* L90: */ } } else { if (nounit) { bla_r_cnjg(&q__2, &a[kplus1 + j * a_dim1]); bli_csets( (bli_creal(temp) * bli_creal(q__2) - bli_cimag(temp) * bli_cimag(q__2)), (bli_creal(temp) * bli_cimag(q__2) + bli_cimag(temp) * bli_creal(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp ); } /* Computing MAX */ i__4 = 1, i__1 = j - *k; i__3 = f2c_max(i__4,i__1); for (i__ = j - 1; i__ >= i__3; --i__) { bla_r_cnjg(&q__3, &a[l + i__ + j * a_dim1]); i__4 = i__; bli_csets( (bli_creal(q__3) * bli_creal(x[i__4]) - bli_cimag(q__3) * bli_cimag(x[i__4])), (bli_creal(q__3) * bli_cimag(x[i__4]) + bli_cimag(q__3) * bli_creal(x[i__4])), q__2 ); bli_csets( (bli_creal(temp) + bli_creal(q__2)), (bli_cimag(temp) + bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp ); /* L100: */ } } i__3 = j; bli_csets( (bli_creal(temp)), (bli_cimag(temp)), x[i__3] ); /* L110: */ } } else { kx += (*n - 1) * *incx; jx = kx; for (j = *n; j >= 1; --j) { i__3 = jx; bli_csets( (bli_creal(x[i__3])), (bli_cimag(x[i__3])), temp ); kx -= *incx; ix = kx; l = kplus1 - j; if (noconj) { if (nounit) { i__3 = kplus1 + j * a_dim1; bli_csets( (bli_creal(temp) * bli_creal(a[i__3]) - bli_cimag(temp) * bli_cimag(a[i__3])), (bli_creal(temp) * bli_cimag(a[i__3]) + bli_cimag(temp) * bli_creal(a[i__3])), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp ); } /* Computing MAX */ i__4 = 1, i__1 = j - *k; i__3 = f2c_max(i__4,i__1); for (i__ = j - 1; i__ >= i__3; --i__) { i__4 = l + i__ + j * a_dim1; i__1 = ix; bli_csets( (bli_creal(a[i__4]) * bli_creal(x[i__1]) - bli_cimag(a[i__4]) * bli_cimag(x[i__1])), (bli_creal(a[i__4]) * bli_cimag(x[i__1]) + bli_cimag(a[i__4]) * bli_creal(x[i__1])), q__2 ); bli_csets( (bli_creal(temp) + bli_creal(q__2)), (bli_cimag(temp) + bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp ); ix -= *incx; /* L120: */ } } else { if (nounit) { bla_r_cnjg(&q__2, &a[kplus1 + j * a_dim1]); bli_csets( (bli_creal(temp) * bli_creal(q__2) - bli_cimag(temp) * bli_cimag(q__2)), (bli_creal(temp) * bli_cimag(q__2) + bli_cimag(temp) * bli_creal(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp ); } /* Computing MAX */ i__4 = 1, i__1 = j - *k; i__3 = f2c_max(i__4,i__1); for (i__ = j - 1; i__ >= i__3; --i__) { bla_r_cnjg(&q__3, &a[l + i__ + j * a_dim1]); i__4 = ix; bli_csets( (bli_creal(q__3) * bli_creal(x[i__4]) - bli_cimag(q__3) * bli_cimag(x[i__4])), (bli_creal(q__3) * bli_cimag(x[i__4]) + bli_cimag(q__3) * bli_creal(x[i__4])), q__2 ); bli_csets( (bli_creal(temp) + bli_creal(q__2)), (bli_cimag(temp) + bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp ); ix -= *incx; /* L130: */ } } i__3 = jx; bli_csets( (bli_creal(temp)), (bli_cimag(temp)), x[i__3] ); jx -= *incx; /* L140: */ } } } else { if (*incx == 1) { i__3 = *n; for (j = 1; j <= i__3; ++j) { i__4 = j; bli_csets( (bli_creal(x[i__4])), (bli_cimag(x[i__4])), temp ); l = 1 - j; if (noconj) { if (nounit) { i__4 = j * a_dim1 + 1; bli_csets( (bli_creal(temp) * bli_creal(a[i__4]) - bli_cimag(temp) * bli_cimag(a[i__4])), (bli_creal(temp) * bli_cimag(a[i__4]) + bli_cimag(temp) * bli_creal(a[i__4])), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp ); } /* Computing MIN */ i__1 = *n, i__2 = j + *k; i__4 = f2c_min(i__1,i__2); for (i__ = j + 1; i__ <= i__4; ++i__) { i__1 = l + i__ + j * a_dim1; i__2 = i__; bli_csets( (bli_creal(a[i__1]) * bli_creal(x[i__2]) - bli_cimag(a[i__1]) * bli_cimag(x[i__2])), (bli_creal(a[i__1]) * bli_cimag(x[i__2]) + bli_cimag(a[i__1]) * bli_creal(x[i__2])), q__2 ); bli_csets( (bli_creal(temp) + bli_creal(q__2)), (bli_cimag(temp) + bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp ); /* L150: */ } } else { if (nounit) { bla_r_cnjg(&q__2, &a[j * a_dim1 + 1]); bli_csets( (bli_creal(temp) * bli_creal(q__2) - bli_cimag(temp) * bli_cimag(q__2)), (bli_creal(temp) * bli_cimag(q__2) + bli_cimag(temp) * bli_creal(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp ); } /* Computing MIN */ i__1 = *n, i__2 = j + *k; i__4 = f2c_min(i__1,i__2); for (i__ = j + 1; i__ <= i__4; ++i__) { bla_r_cnjg(&q__3, &a[l + i__ + j * a_dim1]); i__1 = i__; bli_csets( (bli_creal(q__3) * bli_creal(x[i__1]) - bli_cimag(q__3) * bli_cimag(x[i__1])), (bli_creal(q__3) * bli_cimag(x[i__1]) + bli_cimag(q__3) * bli_creal(x[i__1])), q__2 ); bli_csets( (bli_creal(temp) + bli_creal(q__2)), (bli_cimag(temp) + bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp ); /* L160: */ } } i__4 = j; bli_csets( (bli_creal(temp)), (bli_cimag(temp)), x[i__4] ); /* L170: */ } } else { jx = kx; i__3 = *n; for (j = 1; j <= i__3; ++j) { i__4 = jx; bli_csets( (bli_creal(x[i__4])), (bli_cimag(x[i__4])), temp ); kx += *incx; ix = kx; l = 1 - j; if (noconj) { if (nounit) { i__4 = j * a_dim1 + 1; bli_csets( (bli_creal(temp) * bli_creal(a[i__4]) - bli_cimag(temp) * bli_cimag(a[i__4])), (bli_creal(temp) * bli_cimag(a[i__4]) + bli_cimag(temp) * bli_creal(a[i__4])), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp ); } /* Computing MIN */ i__1 = *n, i__2 = j + *k; i__4 = f2c_min(i__1,i__2); for (i__ = j + 1; i__ <= i__4; ++i__) { i__1 = l + i__ + j * a_dim1; i__2 = ix; bli_csets( (bli_creal(a[i__1]) * bli_creal(x[i__2]) - bli_cimag(a[i__1]) * bli_cimag(x[i__2])), (bli_creal(a[i__1]) * bli_cimag(x[i__2]) + bli_cimag(a[i__1]) * bli_creal(x[i__2])), q__2 ); bli_csets( (bli_creal(temp) + bli_creal(q__2)), (bli_cimag(temp) + bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp ); ix += *incx; /* L180: */ } } else { if (nounit) { bla_r_cnjg(&q__2, &a[j * a_dim1 + 1]); bli_csets( (bli_creal(temp) * bli_creal(q__2) - bli_cimag(temp) * bli_cimag(q__2)), (bli_creal(temp) * bli_cimag(q__2) + bli_cimag(temp) * bli_creal(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp ); } /* Computing MIN */ i__1 = *n, i__2 = j + *k; i__4 = f2c_min(i__1,i__2); for (i__ = j + 1; i__ <= i__4; ++i__) { bla_r_cnjg(&q__3, &a[l + i__ + j * a_dim1]); i__1 = ix; bli_csets( (bli_creal(q__3) * bli_creal(x[i__1]) - bli_cimag(q__3) * bli_cimag(x[i__1])), (bli_creal(q__3) * bli_cimag(x[i__1]) + bli_cimag(q__3) * bli_creal(x[i__1])), q__2 ); bli_csets( (bli_creal(temp) + bli_creal(q__2)), (bli_cimag(temp) + bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp ); ix += *incx; /* L190: */ } } i__4 = jx; bli_csets( (bli_creal(temp)), (bli_cimag(temp)), x[i__4] ); jx += *incx; /* L200: */ } } } } return 0; /* End of CTBMV . */ } /* ctbmv_ */ /* dtbmv.f -- translated by f2c (version 19991025). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ /* Subroutine */ int PASTEF77(d,tbmv)(const bla_character *uplo, const bla_character *trans, const bla_character *diag, const bla_integer *n, const bla_integer *k, const bla_double *a, const bla_integer *lda, bla_double *x, const bla_integer *incx) { /* System generated locals */ bla_integer a_dim1, a_offset, i__1, i__2, i__3, i__4; /* Local variables */ bla_integer info; bla_double temp; bla_integer i__, j, l; //extern bla_logical PASTEF770(lsame)(bla_character *, bla_character *, ftnlen, ftnlen); bla_integer kplus1, ix, jx, kx = 0; //extern /* Subroutine */ int PASTEF770(xerbla)(bla_character *, bla_integer *, ftnlen); bla_logical nounit; /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* DTBMV performs one of the matrix-vector operations */ /* x := A*x, or x := A'*x, */ /* where x is an n element vector and A is an n by n unit, or non-unit, */ /* upper or lower triangular band matrix, with ( k + 1 ) diagonals. */ /* Parameters */ /* ========== */ /* UPLO - CHARACTER*1. */ /* On entry, UPLO specifies whether the matrix is an upper or */ /* lower triangular matrix as follows: */ /* UPLO = 'U' or 'u' A is an upper triangular matrix. */ /* UPLO = 'L' or 'l' A is a lower triangular matrix. */ /* Unchanged on exit. */ /* TRANS - CHARACTER*1. */ /* On entry, TRANS specifies the operation to be performed as */ /* follows: */ /* TRANS = 'N' or 'n' x := A*x. */ /* TRANS = 'T' or 't' x := A'*x. */ /* TRANS = 'C' or 'c' x := A'*x. */ /* Unchanged on exit. */ /* DIAG - CHARACTER*1. */ /* On entry, DIAG specifies whether or not A is unit */ /* triangular as follows: */ /* DIAG = 'U' or 'u' A is assumed to be unit triangular. */ /* DIAG = 'N' or 'n' A is not assumed to be unit */ /* triangular. */ /* Unchanged on exit. */ /* N - INTEGER. */ /* On entry, N specifies the order of the matrix A. */ /* N must be at least zero. */ /* Unchanged on exit. */ /* K - INTEGER. */ /* On entry with UPLO = 'U' or 'u', K specifies the number of */ /* super-diagonals of the matrix A. */ /* On entry with UPLO = 'L' or 'l', K specifies the number of */ /* sub-diagonals of the matrix A. */ /* K must satisfy 0 .le. K. */ /* Unchanged on exit. */ /* A - DOUBLE PRECISION array of DIMENSION ( LDA, n ). */ /* Before entry with UPLO = 'U' or 'u', the leading ( k + 1 ) */ /* by n part of the array A must contain the upper triangular */ /* band part of the matrix of coefficients, supplied column by */ /* column, with the leading diagonal of the matrix in row */ /* ( k + 1 ) of the array, the first super-diagonal starting at */ /* position 2 in row k, and so on. The top left k by k triangle */ /* of the array A is not referenced. */ /* The following program segment will transfer an upper */ /* triangular band matrix from conventional full matrix storage */ /* to band storage: */ /* DO 20, J = 1, N */ /* M = K + 1 - J */ /* DO 10, I = MAX( 1, J - K ), J */ /* A( M + I, J ) = matrix( I, J ) */ /* 10 CONTINUE */ /* 20 CONTINUE */ /* Before entry with UPLO = 'L' or 'l', the leading ( k + 1 ) */ /* by n part of the array A must contain the lower triangular */ /* band part of the matrix of coefficients, supplied column by */ /* column, with the leading diagonal of the matrix in row 1 of */ /* the array, the first sub-diagonal starting at position 1 in */ /* row 2, and so on. The bottom right k by k triangle of the */ /* array A is not referenced. */ /* The following program segment will transfer a lower */ /* triangular band matrix from conventional full matrix storage */ /* to band storage: */ /* DO 20, J = 1, N */ /* M = 1 - J */ /* DO 10, I = J, MIN( N, J + K ) */ /* A( M + I, J ) = matrix( I, J ) */ /* 10 CONTINUE */ /* 20 CONTINUE */ /* Note that when DIAG = 'U' or 'u' the elements of the array A */ /* corresponding to the diagonal elements of the matrix are not */ /* referenced, but are assumed to be unity. */ /* Unchanged on exit. */ /* LDA - INTEGER. */ /* On entry, LDA specifies the first dimension of A as declared */ /* in the calling (sub) program. LDA must be at least */ /* ( k + 1 ). */ /* Unchanged on exit. */ /* X - DOUBLE PRECISION array of dimension at least */ /* ( 1 + ( n - 1 )*abs( INCX ) ). */ /* Before entry, the incremented array X must contain the n */ /* element vector x. On exit, X is overwritten with the */ /* tranformed vector x. */ /* INCX - INTEGER. */ /* On entry, INCX specifies the increment for the elements of */ /* X. INCX must not be zero. */ /* Unchanged on exit. */ /* Level 2 Blas routine. */ /* -- Written on 22-October-1986. */ /* Jack Dongarra, Argonne National Lab. */ /* Jeremy Du Croz, Nag Central Office. */ /* Sven Hammarling, Nag Central Office. */ /* Richard Hanson, Sandia National Labs. */ /* .. Parameters .. */ /* .. Local Scalars .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. */ /* .. Executable Statements .. */ /* Test the input parameters. */ /* Parameter adjustments */ a_dim1 = *lda; a_offset = 1 + a_dim1 * 1; a -= a_offset; --x; /* Function Body */ info = 0; if (! PASTEF770(lsame)(uplo, "U", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(uplo, "L", ( ftnlen)1, (ftnlen)1)) { info = 1; } else if (! PASTEF770(lsame)(trans, "N", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(trans, "T", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(trans, "C", (ftnlen)1, ( ftnlen)1)) { info = 2; } else if (! PASTEF770(lsame)(diag, "U", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(diag, "N", (ftnlen)1, (ftnlen)1)) { info = 3; } else if (*n < 0) { info = 4; } else if (*k < 0) { info = 5; } else if (*lda < *k + 1) { info = 7; } else if (*incx == 0) { info = 9; } if (info != 0) { PASTEF770(xerbla)("DTBMV ", &info, (ftnlen)6); return 0; } /* Quick return if possible. */ if (*n == 0) { return 0; } nounit = PASTEF770(lsame)(diag, "N", (ftnlen)1, (ftnlen)1); /* Set up the start point in X if the increment is not unity. This */ /* will be ( N - 1 )*INCX too small for descending loops. */ if (*incx <= 0) { kx = 1 - (*n - 1) * *incx; } else if (*incx != 1) { kx = 1; } /* Start the operations. In this version the elements of A are */ /* accessed sequentially with one pass through A. */ if (PASTEF770(lsame)(trans, "N", (ftnlen)1, (ftnlen)1)) { /* Form x := A*x. */ if (PASTEF770(lsame)(uplo, "U", (ftnlen)1, (ftnlen)1)) { kplus1 = *k + 1; if (*incx == 1) { i__1 = *n; for (j = 1; j <= i__1; ++j) { if (x[j] != 0.) { temp = x[j]; l = kplus1 - j; /* Computing MAX */ i__2 = 1, i__3 = j - *k; i__4 = j - 1; for (i__ = f2c_max(i__2,i__3); i__ <= i__4; ++i__) { x[i__] += temp * a[l + i__ + j * a_dim1]; /* L10: */ } if (nounit) { x[j] *= a[kplus1 + j * a_dim1]; } } /* L20: */ } } else { jx = kx; i__1 = *n; for (j = 1; j <= i__1; ++j) { if (x[jx] != 0.) { temp = x[jx]; ix = kx; l = kplus1 - j; /* Computing MAX */ i__4 = 1, i__2 = j - *k; i__3 = j - 1; for (i__ = f2c_max(i__4,i__2); i__ <= i__3; ++i__) { x[ix] += temp * a[l + i__ + j * a_dim1]; ix += *incx; /* L30: */ } if (nounit) { x[jx] *= a[kplus1 + j * a_dim1]; } } jx += *incx; if (j > *k) { kx += *incx; } /* L40: */ } } } else { if (*incx == 1) { for (j = *n; j >= 1; --j) { if (x[j] != 0.) { temp = x[j]; l = 1 - j; /* Computing MIN */ i__1 = *n, i__3 = j + *k; i__4 = j + 1; for (i__ = f2c_min(i__1,i__3); i__ >= i__4; --i__) { x[i__] += temp * a[l + i__ + j * a_dim1]; /* L50: */ } if (nounit) { x[j] *= a[j * a_dim1 + 1]; } } /* L60: */ } } else { kx += (*n - 1) * *incx; jx = kx; for (j = *n; j >= 1; --j) { if (x[jx] != 0.) { temp = x[jx]; ix = kx; l = 1 - j; /* Computing MIN */ i__4 = *n, i__1 = j + *k; i__3 = j + 1; for (i__ = f2c_min(i__4,i__1); i__ >= i__3; --i__) { x[ix] += temp * a[l + i__ + j * a_dim1]; ix -= *incx; /* L70: */ } if (nounit) { x[jx] *= a[j * a_dim1 + 1]; } } jx -= *incx; if (*n - j >= *k) { kx -= *incx; } /* L80: */ } } } } else { /* Form x := A'*x. */ if (PASTEF770(lsame)(uplo, "U", (ftnlen)1, (ftnlen)1)) { kplus1 = *k + 1; if (*incx == 1) { for (j = *n; j >= 1; --j) { temp = x[j]; l = kplus1 - j; if (nounit) { temp *= a[kplus1 + j * a_dim1]; } /* Computing MAX */ i__4 = 1, i__1 = j - *k; i__3 = f2c_max(i__4,i__1); for (i__ = j - 1; i__ >= i__3; --i__) { temp += a[l + i__ + j * a_dim1] * x[i__]; /* L90: */ } x[j] = temp; /* L100: */ } } else { kx += (*n - 1) * *incx; jx = kx; for (j = *n; j >= 1; --j) { temp = x[jx]; kx -= *incx; ix = kx; l = kplus1 - j; if (nounit) { temp *= a[kplus1 + j * a_dim1]; } /* Computing MAX */ i__4 = 1, i__1 = j - *k; i__3 = f2c_max(i__4,i__1); for (i__ = j - 1; i__ >= i__3; --i__) { temp += a[l + i__ + j * a_dim1] * x[ix]; ix -= *incx; /* L110: */ } x[jx] = temp; jx -= *incx; /* L120: */ } } } else { if (*incx == 1) { i__3 = *n; for (j = 1; j <= i__3; ++j) { temp = x[j]; l = 1 - j; if (nounit) { temp *= a[j * a_dim1 + 1]; } /* Computing MIN */ i__1 = *n, i__2 = j + *k; i__4 = f2c_min(i__1,i__2); for (i__ = j + 1; i__ <= i__4; ++i__) { temp += a[l + i__ + j * a_dim1] * x[i__]; /* L130: */ } x[j] = temp; /* L140: */ } } else { jx = kx; i__3 = *n; for (j = 1; j <= i__3; ++j) { temp = x[jx]; kx += *incx; ix = kx; l = 1 - j; if (nounit) { temp *= a[j * a_dim1 + 1]; } /* Computing MIN */ i__1 = *n, i__2 = j + *k; i__4 = f2c_min(i__1,i__2); for (i__ = j + 1; i__ <= i__4; ++i__) { temp += a[l + i__ + j * a_dim1] * x[ix]; ix += *incx; /* L150: */ } x[jx] = temp; jx += *incx; /* L160: */ } } } } return 0; /* End of DTBMV . */ } /* dtbmv_ */ /* stbmv.f -- translated by f2c (version 19991025). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ /* Subroutine */ int PASTEF77(s,tbmv)(const bla_character *uplo, const bla_character *trans, const bla_character *diag, const bla_integer *n, const bla_integer *k, const bla_real *a, const bla_integer *lda, bla_real *x, const bla_integer *incx) { /* System generated locals */ bla_integer a_dim1, a_offset, i__1, i__2, i__3, i__4; /* Local variables */ bla_integer info; bla_real temp; bla_integer i__, j, l; //extern bla_logical PASTEF770(lsame)(bla_character *, bla_character *, ftnlen, ftnlen); bla_integer kplus1, ix, jx, kx = 0; //extern /* Subroutine */ int PASTEF770(xerbla)(bla_character *, bla_integer *, ftnlen); bla_logical nounit; /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* STBMV performs one of the matrix-vector operations */ /* x := A*x, or x := A'*x, */ /* where x is an n element vector and A is an n by n unit, or non-unit, */ /* upper or lower triangular band matrix, with ( k + 1 ) diagonals. */ /* Parameters */ /* ========== */ /* UPLO - CHARACTER*1. */ /* On entry, UPLO specifies whether the matrix is an upper or */ /* lower triangular matrix as follows: */ /* UPLO = 'U' or 'u' A is an upper triangular matrix. */ /* UPLO = 'L' or 'l' A is a lower triangular matrix. */ /* Unchanged on exit. */ /* TRANS - CHARACTER*1. */ /* On entry, TRANS specifies the operation to be performed as */ /* follows: */ /* TRANS = 'N' or 'n' x := A*x. */ /* TRANS = 'T' or 't' x := A'*x. */ /* TRANS = 'C' or 'c' x := A'*x. */ /* Unchanged on exit. */ /* DIAG - CHARACTER*1. */ /* On entry, DIAG specifies whether or not A is unit */ /* triangular as follows: */ /* DIAG = 'U' or 'u' A is assumed to be unit triangular. */ /* DIAG = 'N' or 'n' A is not assumed to be unit */ /* triangular. */ /* Unchanged on exit. */ /* N - INTEGER. */ /* On entry, N specifies the order of the matrix A. */ /* N must be at least zero. */ /* Unchanged on exit. */ /* K - INTEGER. */ /* On entry with UPLO = 'U' or 'u', K specifies the number of */ /* super-diagonals of the matrix A. */ /* On entry with UPLO = 'L' or 'l', K specifies the number of */ /* sub-diagonals of the matrix A. */ /* K must satisfy 0 .le. K. */ /* Unchanged on exit. */ /* A - REAL array of DIMENSION ( LDA, n ). */ /* Before entry with UPLO = 'U' or 'u', the leading ( k + 1 ) */ /* by n part of the array A must contain the upper triangular */ /* band part of the matrix of coefficients, supplied column by */ /* column, with the leading diagonal of the matrix in row */ /* ( k + 1 ) of the array, the first super-diagonal starting at */ /* position 2 in row k, and so on. The top left k by k triangle */ /* of the array A is not referenced. */ /* The following program segment will transfer an upper */ /* triangular band matrix from conventional full matrix storage */ /* to band storage: */ /* DO 20, J = 1, N */ /* M = K + 1 - J */ /* DO 10, I = MAX( 1, J - K ), J */ /* A( M + I, J ) = matrix( I, J ) */ /* 10 CONTINUE */ /* 20 CONTINUE */ /* Before entry with UPLO = 'L' or 'l', the leading ( k + 1 ) */ /* by n part of the array A must contain the lower triangular */ /* band part of the matrix of coefficients, supplied column by */ /* column, with the leading diagonal of the matrix in row 1 of */ /* the array, the first sub-diagonal starting at position 1 in */ /* row 2, and so on. The bottom right k by k triangle of the */ /* array A is not referenced. */ /* The following program segment will transfer a lower */ /* triangular band matrix from conventional full matrix storage */ /* to band storage: */ /* DO 20, J = 1, N */ /* M = 1 - J */ /* DO 10, I = J, MIN( N, J + K ) */ /* A( M + I, J ) = matrix( I, J ) */ /* 10 CONTINUE */ /* 20 CONTINUE */ /* Note that when DIAG = 'U' or 'u' the elements of the array A */ /* corresponding to the diagonal elements of the matrix are not */ /* referenced, but are assumed to be unity. */ /* Unchanged on exit. */ /* LDA - INTEGER. */ /* On entry, LDA specifies the first dimension of A as declared */ /* in the calling (sub) program. LDA must be at least */ /* ( k + 1 ). */ /* Unchanged on exit. */ /* X - REAL array of dimension at least */ /* ( 1 + ( n - 1 )*abs( INCX ) ). */ /* Before entry, the incremented array X must contain the n */ /* element vector x. On exit, X is overwritten with the */ /* tranformed vector x. */ /* INCX - INTEGER. */ /* On entry, INCX specifies the increment for the elements of */ /* X. INCX must not be zero. */ /* Unchanged on exit. */ /* Level 2 Blas routine. */ /* -- Written on 22-October-1986. */ /* Jack Dongarra, Argonne National Lab. */ /* Jeremy Du Croz, Nag Central Office. */ /* Sven Hammarling, Nag Central Office. */ /* Richard Hanson, Sandia National Labs. */ /* .. Parameters .. */ /* .. Local Scalars .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. */ /* .. Executable Statements .. */ /* Test the input parameters. */ /* Parameter adjustments */ a_dim1 = *lda; a_offset = 1 + a_dim1 * 1; a -= a_offset; --x; /* Function Body */ info = 0; if (! PASTEF770(lsame)(uplo, "U", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(uplo, "L", ( ftnlen)1, (ftnlen)1)) { info = 1; } else if (! PASTEF770(lsame)(trans, "N", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(trans, "T", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(trans, "C", (ftnlen)1, ( ftnlen)1)) { info = 2; } else if (! PASTEF770(lsame)(diag, "U", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(diag, "N", (ftnlen)1, (ftnlen)1)) { info = 3; } else if (*n < 0) { info = 4; } else if (*k < 0) { info = 5; } else if (*lda < *k + 1) { info = 7; } else if (*incx == 0) { info = 9; } if (info != 0) { PASTEF770(xerbla)("STBMV ", &info, (ftnlen)6); return 0; } /* Quick return if possible. */ if (*n == 0) { return 0; } nounit = PASTEF770(lsame)(diag, "N", (ftnlen)1, (ftnlen)1); /* Set up the start point in X if the increment is not unity. This */ /* will be ( N - 1 )*INCX too small for descending loops. */ if (*incx <= 0) { kx = 1 - (*n - 1) * *incx; } else if (*incx != 1) { kx = 1; } /* Start the operations. In this version the elements of A are */ /* accessed sequentially with one pass through A. */ if (PASTEF770(lsame)(trans, "N", (ftnlen)1, (ftnlen)1)) { /* Form x := A*x. */ if (PASTEF770(lsame)(uplo, "U", (ftnlen)1, (ftnlen)1)) { kplus1 = *k + 1; if (*incx == 1) { i__1 = *n; for (j = 1; j <= i__1; ++j) { if (x[j] != 0.f) { temp = x[j]; l = kplus1 - j; /* Computing MAX */ i__2 = 1, i__3 = j - *k; i__4 = j - 1; for (i__ = f2c_max(i__2,i__3); i__ <= i__4; ++i__) { x[i__] += temp * a[l + i__ + j * a_dim1]; /* L10: */ } if (nounit) { x[j] *= a[kplus1 + j * a_dim1]; } } /* L20: */ } } else { jx = kx; i__1 = *n; for (j = 1; j <= i__1; ++j) { if (x[jx] != 0.f) { temp = x[jx]; ix = kx; l = kplus1 - j; /* Computing MAX */ i__4 = 1, i__2 = j - *k; i__3 = j - 1; for (i__ = f2c_max(i__4,i__2); i__ <= i__3; ++i__) { x[ix] += temp * a[l + i__ + j * a_dim1]; ix += *incx; /* L30: */ } if (nounit) { x[jx] *= a[kplus1 + j * a_dim1]; } } jx += *incx; if (j > *k) { kx += *incx; } /* L40: */ } } } else { if (*incx == 1) { for (j = *n; j >= 1; --j) { if (x[j] != 0.f) { temp = x[j]; l = 1 - j; /* Computing MIN */ i__1 = *n, i__3 = j + *k; i__4 = j + 1; for (i__ = f2c_min(i__1,i__3); i__ >= i__4; --i__) { x[i__] += temp * a[l + i__ + j * a_dim1]; /* L50: */ } if (nounit) { x[j] *= a[j * a_dim1 + 1]; } } /* L60: */ } } else { kx += (*n - 1) * *incx; jx = kx; for (j = *n; j >= 1; --j) { if (x[jx] != 0.f) { temp = x[jx]; ix = kx; l = 1 - j; /* Computing MIN */ i__4 = *n, i__1 = j + *k; i__3 = j + 1; for (i__ = f2c_min(i__4,i__1); i__ >= i__3; --i__) { x[ix] += temp * a[l + i__ + j * a_dim1]; ix -= *incx; /* L70: */ } if (nounit) { x[jx] *= a[j * a_dim1 + 1]; } } jx -= *incx; if (*n - j >= *k) { kx -= *incx; } /* L80: */ } } } } else { /* Form x := A'*x. */ if (PASTEF770(lsame)(uplo, "U", (ftnlen)1, (ftnlen)1)) { kplus1 = *k + 1; if (*incx == 1) { for (j = *n; j >= 1; --j) { temp = x[j]; l = kplus1 - j; if (nounit) { temp *= a[kplus1 + j * a_dim1]; } /* Computing MAX */ i__4 = 1, i__1 = j - *k; i__3 = f2c_max(i__4,i__1); for (i__ = j - 1; i__ >= i__3; --i__) { temp += a[l + i__ + j * a_dim1] * x[i__]; /* L90: */ } x[j] = temp; /* L100: */ } } else { kx += (*n - 1) * *incx; jx = kx; for (j = *n; j >= 1; --j) { temp = x[jx]; kx -= *incx; ix = kx; l = kplus1 - j; if (nounit) { temp *= a[kplus1 + j * a_dim1]; } /* Computing MAX */ i__4 = 1, i__1 = j - *k; i__3 = f2c_max(i__4,i__1); for (i__ = j - 1; i__ >= i__3; --i__) { temp += a[l + i__ + j * a_dim1] * x[ix]; ix -= *incx; /* L110: */ } x[jx] = temp; jx -= *incx; /* L120: */ } } } else { if (*incx == 1) { i__3 = *n; for (j = 1; j <= i__3; ++j) { temp = x[j]; l = 1 - j; if (nounit) { temp *= a[j * a_dim1 + 1]; } /* Computing MIN */ i__1 = *n, i__2 = j + *k; i__4 = f2c_min(i__1,i__2); for (i__ = j + 1; i__ <= i__4; ++i__) { temp += a[l + i__ + j * a_dim1] * x[i__]; /* L130: */ } x[j] = temp; /* L140: */ } } else { jx = kx; i__3 = *n; for (j = 1; j <= i__3; ++j) { temp = x[jx]; kx += *incx; ix = kx; l = 1 - j; if (nounit) { temp *= a[j * a_dim1 + 1]; } /* Computing MIN */ i__1 = *n, i__2 = j + *k; i__4 = f2c_min(i__1,i__2); for (i__ = j + 1; i__ <= i__4; ++i__) { temp += a[l + i__ + j * a_dim1] * x[ix]; ix += *incx; /* L150: */ } x[jx] = temp; jx += *incx; /* L160: */ } } } } return 0; /* End of STBMV . */ } /* stbmv_ */ /* ztbmv.f -- translated by f2c (version 19991025). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ /* Subroutine */ int PASTEF77(z,tbmv)(const bla_character *uplo, const bla_character *trans, const bla_character *diag, const bla_integer *n, const bla_integer *k, const bla_dcomplex *a, const bla_integer *lda, bla_dcomplex *x, const bla_integer *incx) { /* System generated locals */ bla_integer a_dim1, a_offset, i__1, i__2, i__3, i__4, i__5; bla_dcomplex z__1, z__2, z__3; /* Builtin functions */ //void bla_d_cnjg(bla_dcomplex *, bla_dcomplex *); /* Local variables */ bla_integer info; bla_dcomplex temp; bla_integer i__, j, l; //extern bla_logical PASTEF770(lsame)(bla_character *, bla_character *, ftnlen, ftnlen); bla_integer kplus1, ix, jx, kx = 0; //extern /* Subroutine */ int PASTEF770(xerbla)(bla_character *, bla_integer *, ftnlen); bla_logical noconj, nounit; /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* ZTBMV performs one of the matrix-vector operations */ /* x := A*x, or x := A'*x, or x := conjg( A' )*x, */ /* where x is an n element vector and A is an n by n unit, or non-unit, */ /* upper or lower triangular band matrix, with ( k + 1 ) diagonals. */ /* Parameters */ /* ========== */ /* UPLO - CHARACTER*1. */ /* On entry, UPLO specifies whether the matrix is an upper or */ /* lower triangular matrix as follows: */ /* UPLO = 'U' or 'u' A is an upper triangular matrix. */ /* UPLO = 'L' or 'l' A is a lower triangular matrix. */ /* Unchanged on exit. */ /* TRANS - CHARACTER*1. */ /* On entry, TRANS specifies the operation to be performed as */ /* follows: */ /* TRANS = 'N' or 'n' x := A*x. */ /* TRANS = 'T' or 't' x := A'*x. */ /* TRANS = 'C' or 'c' x := conjg( A' )*x. */ /* Unchanged on exit. */ /* DIAG - CHARACTER*1. */ /* On entry, DIAG specifies whether or not A is unit */ /* triangular as follows: */ /* DIAG = 'U' or 'u' A is assumed to be unit triangular. */ /* DIAG = 'N' or 'n' A is not assumed to be unit */ /* triangular. */ /* Unchanged on exit. */ /* N - INTEGER. */ /* On entry, N specifies the order of the matrix A. */ /* N must be at least zero. */ /* Unchanged on exit. */ /* K - INTEGER. */ /* On entry with UPLO = 'U' or 'u', K specifies the number of */ /* super-diagonals of the matrix A. */ /* On entry with UPLO = 'L' or 'l', K specifies the number of */ /* sub-diagonals of the matrix A. */ /* K must satisfy 0 .le. K. */ /* Unchanged on exit. */ /* A - COMPLEX*16 array of DIMENSION ( LDA, n ). */ /* Before entry with UPLO = 'U' or 'u', the leading ( k + 1 ) */ /* by n part of the array A must contain the upper triangular */ /* band part of the matrix of coefficients, supplied column by */ /* column, with the leading diagonal of the matrix in row */ /* ( k + 1 ) of the array, the first super-diagonal starting at */ /* position 2 in row k, and so on. The top left k by k triangle */ /* of the array A is not referenced. */ /* The following program segment will transfer an upper */ /* triangular band matrix from conventional full matrix storage */ /* to band storage: */ /* DO 20, J = 1, N */ /* M = K + 1 - J */ /* DO 10, I = MAX( 1, J - K ), J */ /* A( M + I, J ) = matrix( I, J ) */ /* 10 CONTINUE */ /* 20 CONTINUE */ /* Before entry with UPLO = 'L' or 'l', the leading ( k + 1 ) */ /* by n part of the array A must contain the lower triangular */ /* band part of the matrix of coefficients, supplied column by */ /* column, with the leading diagonal of the matrix in row 1 of */ /* the array, the first sub-diagonal starting at position 1 in */ /* row 2, and so on. The bottom right k by k triangle of the */ /* array A is not referenced. */ /* The following program segment will transfer a lower */ /* triangular band matrix from conventional full matrix storage */ /* to band storage: */ /* DO 20, J = 1, N */ /* M = 1 - J */ /* DO 10, I = J, MIN( N, J + K ) */ /* A( M + I, J ) = matrix( I, J ) */ /* 10 CONTINUE */ /* 20 CONTINUE */ /* Note that when DIAG = 'U' or 'u' the elements of the array A */ /* corresponding to the diagonal elements of the matrix are not */ /* referenced, but are assumed to be unity. */ /* Unchanged on exit. */ /* LDA - INTEGER. */ /* On entry, LDA specifies the first dimension of A as declared */ /* in the calling (sub) program. LDA must be at least */ /* ( k + 1 ). */ /* Unchanged on exit. */ /* X - COMPLEX*16 array of dimension at least */ /* ( 1 + ( n - 1 )*abs( INCX ) ). */ /* Before entry, the incremented array X must contain the n */ /* element vector x. On exit, X is overwritten with the */ /* tranformed vector x. */ /* INCX - INTEGER. */ /* On entry, INCX specifies the increment for the elements of */ /* X. INCX must not be zero. */ /* Unchanged on exit. */ /* Level 2 Blas routine. */ /* -- Written on 22-October-1986. */ /* Jack Dongarra, Argonne National Lab. */ /* Jeremy Du Croz, Nag Central Office. */ /* Sven Hammarling, Nag Central Office. */ /* Richard Hanson, Sandia National Labs. */ /* .. Parameters .. */ /* .. Local Scalars .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. */ /* .. Executable Statements .. */ /* Test the input parameters. */ /* Parameter adjustments */ a_dim1 = *lda; a_offset = 1 + a_dim1 * 1; a -= a_offset; --x; /* Function Body */ info = 0; if (! PASTEF770(lsame)(uplo, "U", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(uplo, "L", ( ftnlen)1, (ftnlen)1)) { info = 1; } else if (! PASTEF770(lsame)(trans, "N", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(trans, "T", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(trans, "C", (ftnlen)1, ( ftnlen)1)) { info = 2; } else if (! PASTEF770(lsame)(diag, "U", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(diag, "N", (ftnlen)1, (ftnlen)1)) { info = 3; } else if (*n < 0) { info = 4; } else if (*k < 0) { info = 5; } else if (*lda < *k + 1) { info = 7; } else if (*incx == 0) { info = 9; } if (info != 0) { PASTEF770(xerbla)("ZTBMV ", &info, (ftnlen)6); return 0; } /* Quick return if possible. */ if (*n == 0) { return 0; } noconj = PASTEF770(lsame)(trans, "T", (ftnlen)1, (ftnlen)1); nounit = PASTEF770(lsame)(diag, "N", (ftnlen)1, (ftnlen)1); /* Set up the start point in X if the increment is not unity. This */ /* will be ( N - 1 )*INCX too small for descending loops. */ if (*incx <= 0) { kx = 1 - (*n - 1) * *incx; } else if (*incx != 1) { kx = 1; } /* Start the operations. In this version the elements of A are */ /* accessed sequentially with one pass through A. */ if (PASTEF770(lsame)(trans, "N", (ftnlen)1, (ftnlen)1)) { /* Form x := A*x. */ if (PASTEF770(lsame)(uplo, "U", (ftnlen)1, (ftnlen)1)) { kplus1 = *k + 1; if (*incx == 1) { i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = j; if (bli_zreal(x[i__2]) != 0. || bli_zimag(x[i__2]) != 0.) { i__2 = j; bli_zsets( (bli_zreal(x[i__2])), (bli_zimag(x[i__2])), temp ); l = kplus1 - j; /* Computing MAX */ i__2 = 1, i__3 = j - *k; i__4 = j - 1; for (i__ = f2c_max(i__2,i__3); i__ <= i__4; ++i__) { i__2 = i__; i__3 = i__; i__5 = l + i__ + j * a_dim1; bli_zsets( (bli_zreal(temp) * bli_zreal(a[i__5]) - bli_zimag(temp) * bli_zimag(a[i__5])), (bli_zreal(temp) * bli_zimag(a[i__5]) + bli_zimag(temp) * bli_zreal(a[i__5])), z__2 ); bli_zsets( (bli_zreal(x[i__3]) + bli_zreal(z__2)), (bli_zimag(x[i__3]) + bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), x[i__2] ); /* L10: */ } if (nounit) { i__4 = j; i__2 = j; i__3 = kplus1 + j * a_dim1; bli_zsets( (bli_zreal(x[i__2]) * bli_zreal(a[i__3]) - bli_zimag(x[i__2]) * bli_zimag(a[i__3])), (bli_zreal(x[i__2]) * bli_zimag(a[i__3]) + bli_zimag(x[i__2]) * bli_zreal(a[i__3])), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), x[i__4] ); } } /* L20: */ } } else { jx = kx; i__1 = *n; for (j = 1; j <= i__1; ++j) { i__4 = jx; if (bli_zreal(x[i__4]) != 0. || bli_zimag(x[i__4]) != 0.) { i__4 = jx; bli_zsets( (bli_zreal(x[i__4])), (bli_zimag(x[i__4])), temp ); ix = kx; l = kplus1 - j; /* Computing MAX */ i__4 = 1, i__2 = j - *k; i__3 = j - 1; for (i__ = f2c_max(i__4,i__2); i__ <= i__3; ++i__) { i__4 = ix; i__2 = ix; i__5 = l + i__ + j * a_dim1; bli_zsets( (bli_zreal(temp) * bli_zreal(a[i__5]) - bli_zimag(temp) * bli_zimag(a[i__5])), (bli_zreal(temp) * bli_zimag(a[i__5]) + bli_zimag(temp) * bli_zreal(a[i__5])), z__2 ); bli_zsets( (bli_zreal(x[i__2]) + bli_zreal(z__2)), (bli_zimag(x[i__2]) + bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), x[i__4] ); ix += *incx; /* L30: */ } if (nounit) { i__3 = jx; i__4 = jx; i__2 = kplus1 + j * a_dim1; bli_zsets( (bli_zreal(x[i__4]) * bli_zreal(a[i__2]) - bli_zimag(x[i__4]) * bli_zimag(a[i__2])), (bli_zreal(x[i__4]) * bli_zimag(a[i__2]) + bli_zimag(x[i__4]) * bli_zreal(a[i__2])), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), x[i__3] ); } } jx += *incx; if (j > *k) { kx += *incx; } /* L40: */ } } } else { if (*incx == 1) { for (j = *n; j >= 1; --j) { i__1 = j; if (bli_zreal(x[i__1]) != 0. || bli_zimag(x[i__1]) != 0.) { i__1 = j; bli_zsets( (bli_zreal(x[i__1])), (bli_zimag(x[i__1])), temp ); l = 1 - j; /* Computing MIN */ i__1 = *n, i__3 = j + *k; i__4 = j + 1; for (i__ = f2c_min(i__1,i__3); i__ >= i__4; --i__) { i__1 = i__; i__3 = i__; i__2 = l + i__ + j * a_dim1; bli_zsets( (bli_zreal(temp) * bli_zreal(a[i__2]) - bli_zimag(temp) * bli_zimag(a[i__2])), (bli_zreal(temp) * bli_zimag(a[i__2]) + bli_zimag(temp) * bli_zreal(a[i__2])), z__2 ); bli_zsets( (bli_zreal(x[i__3]) + bli_zreal(z__2)), (bli_zimag(x[i__3]) + bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), x[i__1] ); /* L50: */ } if (nounit) { i__4 = j; i__1 = j; i__3 = j * a_dim1 + 1; bli_zsets( (bli_zreal(x[i__1]) * bli_zreal(a[i__3]) - bli_zimag(x[i__1]) * bli_zimag(a[i__3])), (bli_zreal(x[i__1]) * bli_zimag(a[i__3]) + bli_zimag(x[i__1]) * bli_zreal(a[i__3])), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), x[i__4] ); } } /* L60: */ } } else { kx += (*n - 1) * *incx; jx = kx; for (j = *n; j >= 1; --j) { i__4 = jx; if (bli_zreal(x[i__4]) != 0. || bli_zimag(x[i__4]) != 0.) { i__4 = jx; bli_zsets( (bli_zreal(x[i__4])), (bli_zimag(x[i__4])), temp ); ix = kx; l = 1 - j; /* Computing MIN */ i__4 = *n, i__1 = j + *k; i__3 = j + 1; for (i__ = f2c_min(i__4,i__1); i__ >= i__3; --i__) { i__4 = ix; i__1 = ix; i__2 = l + i__ + j * a_dim1; bli_zsets( (bli_zreal(temp) * bli_zreal(a[i__2]) - bli_zimag(temp) * bli_zimag(a[i__2])), (bli_zreal(temp) * bli_zimag(a[i__2]) + bli_zimag(temp) * bli_zreal(a[i__2])), z__2 ); bli_zsets( (bli_zreal(x[i__1]) + bli_zreal(z__2)), (bli_zimag(x[i__1]) + bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), x[i__4] ); ix -= *incx; /* L70: */ } if (nounit) { i__3 = jx; i__4 = jx; i__1 = j * a_dim1 + 1; bli_zsets( (bli_zreal(x[i__4]) * bli_zreal(a[i__1]) - bli_zimag(x[i__4]) * bli_zimag(a[i__1])), (bli_zreal(x[i__4]) * bli_zimag(a[i__1]) + bli_zimag(x[i__4]) * bli_zreal(a[i__1])), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), x[i__3] ); } } jx -= *incx; if (*n - j >= *k) { kx -= *incx; } /* L80: */ } } } } else { /* Form x := A'*x or x := conjg( A' )*x. */ if (PASTEF770(lsame)(uplo, "U", (ftnlen)1, (ftnlen)1)) { kplus1 = *k + 1; if (*incx == 1) { for (j = *n; j >= 1; --j) { i__3 = j; bli_zsets( (bli_zreal(x[i__3])), (bli_zimag(x[i__3])), temp ); l = kplus1 - j; if (noconj) { if (nounit) { i__3 = kplus1 + j * a_dim1; bli_zsets( (bli_zreal(temp) * bli_zreal(a[i__3]) - bli_zimag(temp) * bli_zimag(a[i__3])), (bli_zreal(temp) * bli_zimag(a[i__3]) + bli_zimag(temp) * bli_zreal(a[i__3])), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp ); } /* Computing MAX */ i__4 = 1, i__1 = j - *k; i__3 = f2c_max(i__4,i__1); for (i__ = j - 1; i__ >= i__3; --i__) { i__4 = l + i__ + j * a_dim1; i__1 = i__; bli_zsets( (bli_zreal(a[i__4]) * bli_zreal(x[i__1]) - bli_zimag(a[i__4]) * bli_zimag(x[i__1])), (bli_zreal(a[i__4]) * bli_zimag(x[i__1]) + bli_zimag(a[i__4]) * bli_zreal(x[i__1])), z__2 ); bli_zsets( (bli_zreal(temp) + bli_zreal(z__2)), (bli_zimag(temp) + bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp ); /* L90: */ } } else { if (nounit) { bla_d_cnjg(&z__2, &a[kplus1 + j * a_dim1]); bli_zsets( (bli_zreal(temp) * bli_zreal(z__2) - bli_zimag(temp) * bli_zimag(z__2)), (bli_zreal(temp) * bli_zimag(z__2) + bli_zimag(temp) * bli_zreal(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp ); } /* Computing MAX */ i__4 = 1, i__1 = j - *k; i__3 = f2c_max(i__4,i__1); for (i__ = j - 1; i__ >= i__3; --i__) { bla_d_cnjg(&z__3, &a[l + i__ + j * a_dim1]); i__4 = i__; bli_zsets( (bli_zreal(z__3) * bli_zreal(x[i__4]) - bli_zimag(z__3) * bli_zimag(x[i__4])), (bli_zreal(z__3) * bli_zimag(x[i__4]) + bli_zimag(z__3) * bli_zreal(x[i__4])), z__2 ); bli_zsets( (bli_zreal(temp) + bli_zreal(z__2)), (bli_zimag(temp) + bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp ); /* L100: */ } } i__3 = j; bli_zsets( (bli_zreal(temp)), (bli_zimag(temp)), x[i__3] ); /* L110: */ } } else { kx += (*n - 1) * *incx; jx = kx; for (j = *n; j >= 1; --j) { i__3 = jx; bli_zsets( (bli_zreal(x[i__3])), (bli_zimag(x[i__3])), temp ); kx -= *incx; ix = kx; l = kplus1 - j; if (noconj) { if (nounit) { i__3 = kplus1 + j * a_dim1; bli_zsets( (bli_zreal(temp) * bli_zreal(a[i__3]) - bli_zimag(temp) * bli_zimag(a[i__3])), (bli_zreal(temp) * bli_zimag(a[i__3]) + bli_zimag(temp) * bli_zreal(a[i__3])), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp ); } /* Computing MAX */ i__4 = 1, i__1 = j - *k; i__3 = f2c_max(i__4,i__1); for (i__ = j - 1; i__ >= i__3; --i__) { i__4 = l + i__ + j * a_dim1; i__1 = ix; bli_zsets( (bli_zreal(a[i__4]) * bli_zreal(x[i__1]) - bli_zimag(a[i__4]) * bli_zimag(x[i__1])), (bli_zreal(a[i__4]) * bli_zimag(x[i__1]) + bli_zimag(a[i__4]) * bli_zreal(x[i__1])), z__2 ); bli_zsets( (bli_zreal(temp) + bli_zreal(z__2)), (bli_zimag(temp) + bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp ); ix -= *incx; /* L120: */ } } else { if (nounit) { bla_d_cnjg(&z__2, &a[kplus1 + j * a_dim1]); bli_zsets( (bli_zreal(temp) * bli_zreal(z__2) - bli_zimag(temp) * bli_zimag(z__2)), (bli_zreal(temp) * bli_zimag(z__2) + bli_zimag(temp) * bli_zreal(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp ); } /* Computing MAX */ i__4 = 1, i__1 = j - *k; i__3 = f2c_max(i__4,i__1); for (i__ = j - 1; i__ >= i__3; --i__) { bla_d_cnjg(&z__3, &a[l + i__ + j * a_dim1]); i__4 = ix; bli_zsets( (bli_zreal(z__3) * bli_zreal(x[i__4]) - bli_zimag(z__3) * bli_zimag(x[i__4])), (bli_zreal(z__3) * bli_zimag(x[i__4]) + bli_zimag(z__3) * bli_zreal(x[i__4])), z__2 ); bli_zsets( (bli_zreal(temp) + bli_zreal(z__2)), (bli_zimag(temp) + bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp ); ix -= *incx; /* L130: */ } } i__3 = jx; bli_zsets( (bli_zreal(temp)), (bli_zimag(temp)), x[i__3] ); jx -= *incx; /* L140: */ } } } else { if (*incx == 1) { i__3 = *n; for (j = 1; j <= i__3; ++j) { i__4 = j; bli_zsets( (bli_zreal(x[i__4])), (bli_zimag(x[i__4])), temp ); l = 1 - j; if (noconj) { if (nounit) { i__4 = j * a_dim1 + 1; bli_zsets( (bli_zreal(temp) * bli_zreal(a[i__4]) - bli_zimag(temp) * bli_zimag(a[i__4])), (bli_zreal(temp) * bli_zimag(a[i__4]) + bli_zimag(temp) * bli_zreal(a[i__4])), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp ); } /* Computing MIN */ i__1 = *n, i__2 = j + *k; i__4 = f2c_min(i__1,i__2); for (i__ = j + 1; i__ <= i__4; ++i__) { i__1 = l + i__ + j * a_dim1; i__2 = i__; bli_zsets( (bli_zreal(a[i__1]) * bli_zreal(x[i__2]) - bli_zimag(a[i__1]) * bli_zimag(x[i__2])), (bli_zreal(a[i__1]) * bli_zimag(x[i__2]) + bli_zimag(a[i__1]) * bli_zreal(x[i__2])), z__2 ); bli_zsets( (bli_zreal(temp) + bli_zreal(z__2)), (bli_zimag(temp) + bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp ); /* L150: */ } } else { if (nounit) { bla_d_cnjg(&z__2, &a[j * a_dim1 + 1]); bli_zsets( (bli_zreal(temp) * bli_zreal(z__2) - bli_zimag(temp) * bli_zimag(z__2)), (bli_zreal(temp) * bli_zimag(z__2) + bli_zimag(temp) * bli_zreal(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp ); } /* Computing MIN */ i__1 = *n, i__2 = j + *k; i__4 = f2c_min(i__1,i__2); for (i__ = j + 1; i__ <= i__4; ++i__) { bla_d_cnjg(&z__3, &a[l + i__ + j * a_dim1]); i__1 = i__; bli_zsets( (bli_zreal(z__3) * bli_zreal(x[i__1]) - bli_zimag(z__3) * bli_zimag(x[i__1])), (bli_zreal(z__3) * bli_zimag(x[i__1]) + bli_zimag(z__3) * bli_zreal(x[i__1])), z__2 ); bli_zsets( (bli_zreal(temp) + bli_zreal(z__2)), (bli_zimag(temp) + bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp ); /* L160: */ } } i__4 = j; bli_zsets( (bli_zreal(temp)), (bli_zimag(temp)), x[i__4] ); /* L170: */ } } else { jx = kx; i__3 = *n; for (j = 1; j <= i__3; ++j) { i__4 = jx; bli_zsets( (bli_zreal(x[i__4])), (bli_zimag(x[i__4])), temp ); kx += *incx; ix = kx; l = 1 - j; if (noconj) { if (nounit) { i__4 = j * a_dim1 + 1; bli_zsets( (bli_zreal(temp) * bli_zreal(a[i__4]) - bli_zimag(temp) * bli_zimag(a[i__4])), (bli_zreal(temp) * bli_zimag(a[i__4]) + bli_zimag(temp) * bli_zreal(a[i__4])), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp ); } /* Computing MIN */ i__1 = *n, i__2 = j + *k; i__4 = f2c_min(i__1,i__2); for (i__ = j + 1; i__ <= i__4; ++i__) { i__1 = l + i__ + j * a_dim1; i__2 = ix; bli_zsets( (bli_zreal(a[i__1]) * bli_zreal(x[i__2]) - bli_zimag(a[i__1]) * bli_zimag(x[i__2])), (bli_zreal(a[i__1]) * bli_zimag(x[i__2]) + bli_zimag(a[i__1]) * bli_zreal(x[i__2])), z__2 ); bli_zsets( (bli_zreal(temp) + bli_zreal(z__2)), (bli_zimag(temp) + bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp ); ix += *incx; /* L180: */ } } else { if (nounit) { bla_d_cnjg(&z__2, &a[j * a_dim1 + 1]); bli_zsets( (bli_zreal(temp) * bli_zreal(z__2) - bli_zimag(temp) * bli_zimag(z__2)), (bli_zreal(temp) * bli_zimag(z__2) + bli_zimag(temp) * bli_zreal(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp ); } /* Computing MIN */ i__1 = *n, i__2 = j + *k; i__4 = f2c_min(i__1,i__2); for (i__ = j + 1; i__ <= i__4; ++i__) { bla_d_cnjg(&z__3, &a[l + i__ + j * a_dim1]); i__1 = ix; bli_zsets( (bli_zreal(z__3) * bli_zreal(x[i__1]) - bli_zimag(z__3) * bli_zimag(x[i__1])), (bli_zreal(z__3) * bli_zimag(x[i__1]) + bli_zimag(z__3) * bli_zreal(x[i__1])), z__2 ); bli_zsets( (bli_zreal(temp) + bli_zreal(z__2)), (bli_zimag(temp) + bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp ); ix += *incx; /* L190: */ } } i__4 = jx; bli_zsets( (bli_zreal(temp)), (bli_zimag(temp)), x[i__4] ); jx += *incx; /* L200: */ } } } } return 0; /* End of ZTBMV . */ } /* ztbmv_ */ #endif blis-0.9.0/frame/compat/f2c/bla_tbmv.h000066400000000000000000000052261422157504600174520ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifdef BLIS_ENABLE_BLAS BLIS_EXPORT_BLAS int PASTEF77(c,tbmv)(const bla_character *uplo, const bla_character *trans, const bla_character *diag, const bla_integer *n, const bla_integer *k, const bla_scomplex *a, const bla_integer *lda, bla_scomplex *x, const bla_integer *incx); BLIS_EXPORT_BLAS int PASTEF77(d,tbmv)(const bla_character *uplo, const bla_character *trans, const bla_character *diag, const bla_integer *n, const bla_integer *k, const bla_double *a, const bla_integer *lda, bla_double *x, const bla_integer *incx); BLIS_EXPORT_BLAS int PASTEF77(s,tbmv)(const bla_character *uplo, const bla_character *trans, const bla_character *diag, const bla_integer *n, const bla_integer *k, const bla_real *a, const bla_integer *lda, bla_real *x, const bla_integer *incx); BLIS_EXPORT_BLAS int PASTEF77(z,tbmv)(const bla_character *uplo, const bla_character *trans, const bla_character *diag, const bla_integer *n, const bla_integer *k, const bla_dcomplex *a, const bla_integer *lda, bla_dcomplex *x, const bla_integer *incx); #endif blis-0.9.0/frame/compat/f2c/bla_tbsv.c000066400000000000000000001761311422157504600174570ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #ifdef BLIS_ENABLE_BLAS /* ctbsv.f -- translated by f2c (version 19991025). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ /* Subroutine */ int PASTEF77(c,tbsv)(const bla_character *uplo, const bla_character *trans, const bla_character *diag, const bla_integer *n, const bla_integer *k, const bla_scomplex *a, const bla_integer *lda, bla_scomplex *x, const bla_integer *incx) { /* System generated locals */ bla_integer a_dim1, a_offset, i__1, i__2, i__3, i__4, i__5; bla_scomplex q__1, q__2, q__3; /* Builtin functions */ //void bla_c_div(bla_scomplex *, bla_scomplex *, bla_scomplex *), bla_r_cnjg(bla_scomplex *, bla_scomplex *); /* Local variables */ bla_integer info; bla_scomplex temp; bla_integer i__, j, l; //extern bla_logical PASTEF770(lsame)(bla_character *, bla_character *, ftnlen, ftnlen); bla_integer kplus1, ix, jx, kx = 0; //extern /* Subroutine */ int PASTEF770(xerbla)(bla_character *, bla_integer *, ftnlen); bla_logical noconj, nounit; /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* CTBSV solves one of the systems of equations */ /* A*x = b, or A'*x = b, or conjg( A' )*x = b, */ /* where b and x are n element vectors and A is an n by n unit, or */ /* non-unit, upper or lower triangular band matrix, with ( k + 1 ) */ /* diagonals. */ /* No test for singularity or near-singularity is included in this */ /* routine. Such tests must be performed before calling this routine. */ /* Parameters */ /* ========== */ /* UPLO - CHARACTER*1. */ /* On entry, UPLO specifies whether the matrix is an upper or */ /* lower triangular matrix as follows: */ /* UPLO = 'U' or 'u' A is an upper triangular matrix. */ /* UPLO = 'L' or 'l' A is a lower triangular matrix. */ /* Unchanged on exit. */ /* TRANS - CHARACTER*1. */ /* On entry, TRANS specifies the equations to be solved as */ /* follows: */ /* TRANS = 'N' or 'n' A*x = b. */ /* TRANS = 'T' or 't' A'*x = b. */ /* TRANS = 'C' or 'c' conjg( A' )*x = b. */ /* Unchanged on exit. */ /* DIAG - CHARACTER*1. */ /* On entry, DIAG specifies whether or not A is unit */ /* triangular as follows: */ /* DIAG = 'U' or 'u' A is assumed to be unit triangular. */ /* DIAG = 'N' or 'n' A is not assumed to be unit */ /* triangular. */ /* Unchanged on exit. */ /* N - INTEGER. */ /* On entry, N specifies the order of the matrix A. */ /* N must be at least zero. */ /* Unchanged on exit. */ /* K - INTEGER. */ /* On entry with UPLO = 'U' or 'u', K specifies the number of */ /* super-diagonals of the matrix A. */ /* On entry with UPLO = 'L' or 'l', K specifies the number of */ /* sub-diagonals of the matrix A. */ /* K must satisfy 0 .le. K. */ /* Unchanged on exit. */ /* A - COMPLEX array of DIMENSION ( LDA, n ). */ /* Before entry with UPLO = 'U' or 'u', the leading ( k + 1 ) */ /* by n part of the array A must contain the upper triangular */ /* band part of the matrix of coefficients, supplied column by */ /* column, with the leading diagonal of the matrix in row */ /* ( k + 1 ) of the array, the first super-diagonal starting at */ /* position 2 in row k, and so on. The top left k by k triangle */ /* of the array A is not referenced. */ /* The following program segment will transfer an upper */ /* triangular band matrix from conventional full matrix storage */ /* to band storage: */ /* DO 20, J = 1, N */ /* M = K + 1 - J */ /* DO 10, I = MAX( 1, J - K ), J */ /* A( M + I, J ) = matrix( I, J ) */ /* 10 CONTINUE */ /* 20 CONTINUE */ /* Before entry with UPLO = 'L' or 'l', the leading ( k + 1 ) */ /* by n part of the array A must contain the lower triangular */ /* band part of the matrix of coefficients, supplied column by */ /* column, with the leading diagonal of the matrix in row 1 of */ /* the array, the first sub-diagonal starting at position 1 in */ /* row 2, and so on. The bottom right k by k triangle of the */ /* array A is not referenced. */ /* The following program segment will transfer a lower */ /* triangular band matrix from conventional full matrix storage */ /* to band storage: */ /* DO 20, J = 1, N */ /* M = 1 - J */ /* DO 10, I = J, MIN( N, J + K ) */ /* A( M + I, J ) = matrix( I, J ) */ /* 10 CONTINUE */ /* 20 CONTINUE */ /* Note that when DIAG = 'U' or 'u' the elements of the array A */ /* corresponding to the diagonal elements of the matrix are not */ /* referenced, but are assumed to be unity. */ /* Unchanged on exit. */ /* LDA - INTEGER. */ /* On entry, LDA specifies the first dimension of A as declared */ /* in the calling (sub) program. LDA must be at least */ /* ( k + 1 ). */ /* Unchanged on exit. */ /* X - COMPLEX array of dimension at least */ /* ( 1 + ( n - 1 )*abs( INCX ) ). */ /* Before entry, the incremented array X must contain the n */ /* element right-hand side vector b. On exit, X is overwritten */ /* with the solution vector x. */ /* INCX - INTEGER. */ /* On entry, INCX specifies the increment for the elements of */ /* X. INCX must not be zero. */ /* Unchanged on exit. */ /* Level 2 Blas routine. */ /* -- Written on 22-October-1986. */ /* Jack Dongarra, Argonne National Lab. */ /* Jeremy Du Croz, Nag Central Office. */ /* Sven Hammarling, Nag Central Office. */ /* Richard Hanson, Sandia National Labs. */ /* .. Parameters .. */ /* .. Local Scalars .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. */ /* .. Executable Statements .. */ /* Test the input parameters. */ /* Parameter adjustments */ a_dim1 = *lda; a_offset = 1 + a_dim1 * 1; a -= a_offset; --x; /* Function Body */ info = 0; if (! PASTEF770(lsame)(uplo, "U", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(uplo, "L", ( ftnlen)1, (ftnlen)1)) { info = 1; } else if (! PASTEF770(lsame)(trans, "N", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(trans, "T", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(trans, "C", (ftnlen)1, ( ftnlen)1)) { info = 2; } else if (! PASTEF770(lsame)(diag, "U", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(diag, "N", (ftnlen)1, (ftnlen)1)) { info = 3; } else if (*n < 0) { info = 4; } else if (*k < 0) { info = 5; } else if (*lda < *k + 1) { info = 7; } else if (*incx == 0) { info = 9; } if (info != 0) { PASTEF770(xerbla)("CTBSV ", &info, (ftnlen)6); return 0; } /* Quick return if possible. */ if (*n == 0) { return 0; } noconj = PASTEF770(lsame)(trans, "T", (ftnlen)1, (ftnlen)1); nounit = PASTEF770(lsame)(diag, "N", (ftnlen)1, (ftnlen)1); /* Set up the start point in X if the increment is not unity. This */ /* will be ( N - 1 )*INCX too small for descending loops. */ if (*incx <= 0) { kx = 1 - (*n - 1) * *incx; } else if (*incx != 1) { kx = 1; } /* Start the operations. In this version the elements of A are */ /* accessed by sequentially with one pass through A. */ if (PASTEF770(lsame)(trans, "N", (ftnlen)1, (ftnlen)1)) { /* Form x := inv( A )*x. */ if (PASTEF770(lsame)(uplo, "U", (ftnlen)1, (ftnlen)1)) { kplus1 = *k + 1; if (*incx == 1) { for (j = *n; j >= 1; --j) { i__1 = j; if (bli_creal(x[i__1]) != 0.f || bli_cimag(x[i__1]) != 0.f) { l = kplus1 - j; if (nounit) { i__1 = j; bla_c_div(&q__1, &x[j], &a[kplus1 + j * a_dim1]); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), x[i__1] ); } i__1 = j; bli_csets( (bli_creal(x[i__1])), (bli_cimag(x[i__1])), temp ); /* Computing MAX */ i__2 = 1, i__3 = j - *k; i__1 = f2c_max(i__2,i__3); for (i__ = j - 1; i__ >= i__1; --i__) { i__2 = i__; i__3 = i__; i__4 = l + i__ + j * a_dim1; bli_csets( (bli_creal(temp) * bli_creal(a[i__4]) - bli_cimag(temp) * bli_cimag(a[i__4])), (bli_creal(temp) * bli_cimag(a[i__4]) + bli_cimag(temp) * bli_creal(a[i__4])), q__2 ); bli_csets( (bli_creal(x[i__3]) - bli_creal(q__2)), (bli_cimag(x[i__3]) - bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), x[i__2] ); /* L10: */ } } /* L20: */ } } else { kx += (*n - 1) * *incx; jx = kx; for (j = *n; j >= 1; --j) { kx -= *incx; i__1 = jx; if (bli_creal(x[i__1]) != 0.f || bli_cimag(x[i__1]) != 0.f) { ix = kx; l = kplus1 - j; if (nounit) { i__1 = jx; bla_c_div(&q__1, &x[jx], &a[kplus1 + j * a_dim1]); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), x[i__1] ); } i__1 = jx; bli_csets( (bli_creal(x[i__1])), (bli_cimag(x[i__1])), temp ); /* Computing MAX */ i__2 = 1, i__3 = j - *k; i__1 = f2c_max(i__2,i__3); for (i__ = j - 1; i__ >= i__1; --i__) { i__2 = ix; i__3 = ix; i__4 = l + i__ + j * a_dim1; bli_csets( (bli_creal(temp) * bli_creal(a[i__4]) - bli_cimag(temp) * bli_cimag(a[i__4])), (bli_creal(temp) * bli_cimag(a[i__4]) + bli_cimag(temp) * bli_creal(a[i__4])), q__2 ); bli_csets( (bli_creal(x[i__3]) - bli_creal(q__2)), (bli_cimag(x[i__3]) - bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), x[i__2] ); ix -= *incx; /* L30: */ } } jx -= *incx; /* L40: */ } } } else { if (*incx == 1) { i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = j; if (bli_creal(x[i__2]) != 0.f || bli_cimag(x[i__2]) != 0.f) { l = 1 - j; if (nounit) { i__2 = j; bla_c_div(&q__1, &x[j], &a[j * a_dim1 + 1]); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), x[i__2] ); } i__2 = j; bli_csets( (bli_creal(x[i__2])), (bli_cimag(x[i__2])), temp ); /* Computing MIN */ i__3 = *n, i__4 = j + *k; i__2 = f2c_min(i__3,i__4); for (i__ = j + 1; i__ <= i__2; ++i__) { i__3 = i__; i__4 = i__; i__5 = l + i__ + j * a_dim1; bli_csets( (bli_creal(temp) * bli_creal(a[i__5]) - bli_cimag(temp) * bli_cimag(a[i__5])), (bli_creal(temp) * bli_cimag(a[i__5]) + bli_cimag(temp) * bli_creal(a[i__5])), q__2 ); bli_csets( (bli_creal(x[i__4]) - bli_creal(q__2)), (bli_cimag(x[i__4]) - bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), x[i__3] ); /* L50: */ } } /* L60: */ } } else { jx = kx; i__1 = *n; for (j = 1; j <= i__1; ++j) { kx += *incx; i__2 = jx; if (bli_creal(x[i__2]) != 0.f || bli_cimag(x[i__2]) != 0.f) { ix = kx; l = 1 - j; if (nounit) { i__2 = jx; bla_c_div(&q__1, &x[jx], &a[j * a_dim1 + 1]); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), x[i__2] ); } i__2 = jx; bli_csets( (bli_creal(x[i__2])), (bli_cimag(x[i__2])), temp ); /* Computing MIN */ i__3 = *n, i__4 = j + *k; i__2 = f2c_min(i__3,i__4); for (i__ = j + 1; i__ <= i__2; ++i__) { i__3 = ix; i__4 = ix; i__5 = l + i__ + j * a_dim1; bli_csets( (bli_creal(temp) * bli_creal(a[i__5]) - bli_cimag(temp) * bli_cimag(a[i__5])), (bli_creal(temp) * bli_cimag(a[i__5]) + bli_cimag(temp) * bli_creal(a[i__5])), q__2 ); bli_csets( (bli_creal(x[i__4]) - bli_creal(q__2)), (bli_cimag(x[i__4]) - bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), x[i__3] ); ix += *incx; /* L70: */ } } jx += *incx; /* L80: */ } } } } else { /* Form x := inv( A' )*x or x := inv( conjg( A') )*x. */ if (PASTEF770(lsame)(uplo, "U", (ftnlen)1, (ftnlen)1)) { kplus1 = *k + 1; if (*incx == 1) { i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = j; bli_csets( (bli_creal(x[i__2])), (bli_cimag(x[i__2])), temp ); l = kplus1 - j; if (noconj) { /* Computing MAX */ i__2 = 1, i__3 = j - *k; i__4 = j - 1; for (i__ = f2c_max(i__2,i__3); i__ <= i__4; ++i__) { i__2 = l + i__ + j * a_dim1; i__3 = i__; bli_csets( (bli_creal(a[i__2]) * bli_creal(x[i__3]) - bli_cimag(a[i__2]) * bli_cimag(x[i__3])), (bli_creal(a[i__2]) * bli_cimag(x[i__3]) + bli_cimag(a[i__2]) * bli_creal(x[i__3])), q__2 ); bli_csets( (bli_creal(temp) - bli_creal(q__2)), (bli_cimag(temp) - bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp ); /* L90: */ } if (nounit) { bla_c_div(&q__1, &temp, &a[kplus1 + j * a_dim1]); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp ); } } else { /* Computing MAX */ i__4 = 1, i__2 = j - *k; i__3 = j - 1; for (i__ = f2c_max(i__4,i__2); i__ <= i__3; ++i__) { bla_r_cnjg(&q__3, &a[l + i__ + j * a_dim1]); i__4 = i__; bli_csets( (bli_creal(q__3) * bli_creal(x[i__4]) - bli_cimag(q__3) * bli_cimag(x[i__4])), (bli_creal(q__3) * bli_cimag(x[i__4]) + bli_cimag(q__3) * bli_creal(x[i__4])), q__2 ); bli_csets( (bli_creal(temp) - bli_creal(q__2)), (bli_cimag(temp) - bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp ); /* L100: */ } if (nounit) { bla_r_cnjg(&q__2, &a[kplus1 + j * a_dim1]); bla_c_div(&q__1, &temp, &q__2); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp ); } } i__3 = j; bli_csets( (bli_creal(temp)), (bli_cimag(temp)), x[i__3] ); /* L110: */ } } else { jx = kx; i__1 = *n; for (j = 1; j <= i__1; ++j) { i__3 = jx; bli_csets( (bli_creal(x[i__3])), (bli_cimag(x[i__3])), temp ); ix = kx; l = kplus1 - j; if (noconj) { /* Computing MAX */ i__3 = 1, i__4 = j - *k; i__2 = j - 1; for (i__ = f2c_max(i__3,i__4); i__ <= i__2; ++i__) { i__3 = l + i__ + j * a_dim1; i__4 = ix; bli_csets( (bli_creal(a[i__3]) * bli_creal(x[i__4]) - bli_cimag(a[i__3]) * bli_cimag(x[i__4])), (bli_creal(a[i__3]) * bli_cimag(x[i__4]) + bli_cimag(a[i__3]) * bli_creal(x[i__4])), q__2 ); bli_csets( (bli_creal(temp) - bli_creal(q__2)), (bli_cimag(temp) - bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp ); ix += *incx; /* L120: */ } if (nounit) { bla_c_div(&q__1, &temp, &a[kplus1 + j * a_dim1]); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp ); } } else { /* Computing MAX */ i__2 = 1, i__3 = j - *k; i__4 = j - 1; for (i__ = f2c_max(i__2,i__3); i__ <= i__4; ++i__) { bla_r_cnjg(&q__3, &a[l + i__ + j * a_dim1]); i__2 = ix; bli_csets( (bli_creal(q__3) * bli_creal(x[i__2]) - bli_cimag(q__3) * bli_cimag(x[i__2])), (bli_creal(q__3) * bli_cimag(x[i__2]) + bli_cimag(q__3) * bli_creal(x[i__2])), q__2 ); bli_csets( (bli_creal(temp) - bli_creal(q__2)), (bli_cimag(temp) - bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp ); ix += *incx; /* L130: */ } if (nounit) { bla_r_cnjg(&q__2, &a[kplus1 + j * a_dim1]); bla_c_div(&q__1, &temp, &q__2); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp ); } } i__4 = jx; bli_csets( (bli_creal(temp)), (bli_cimag(temp)), x[i__4] ); jx += *incx; if (j > *k) { kx += *incx; } /* L140: */ } } } else { if (*incx == 1) { for (j = *n; j >= 1; --j) { i__1 = j; bli_csets( (bli_creal(x[i__1])), (bli_cimag(x[i__1])), temp ); l = 1 - j; if (noconj) { /* Computing MIN */ i__1 = *n, i__4 = j + *k; i__2 = j + 1; for (i__ = f2c_min(i__1,i__4); i__ >= i__2; --i__) { i__1 = l + i__ + j * a_dim1; i__4 = i__; bli_csets( (bli_creal(a[i__1]) * bli_creal(x[i__4]) - bli_cimag(a[i__1]) * bli_cimag(x[i__4])), (bli_creal(a[i__1]) * bli_cimag(x[i__4]) + bli_cimag(a[i__1]) * bli_creal(x[i__4])), q__2 ); bli_csets( (bli_creal(temp) - bli_creal(q__2)), (bli_cimag(temp) - bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp ); /* L150: */ } if (nounit) { bla_c_div(&q__1, &temp, &a[j * a_dim1 + 1]); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp ); } } else { /* Computing MIN */ i__2 = *n, i__1 = j + *k; i__4 = j + 1; for (i__ = f2c_min(i__2,i__1); i__ >= i__4; --i__) { bla_r_cnjg(&q__3, &a[l + i__ + j * a_dim1]); i__2 = i__; bli_csets( (bli_creal(q__3) * bli_creal(x[i__2]) - bli_cimag(q__3) * bli_cimag(x[i__2])), (bli_creal(q__3) * bli_cimag(x[i__2]) + bli_cimag(q__3) * bli_creal(x[i__2])), q__2 ); bli_csets( (bli_creal(temp) - bli_creal(q__2)), (bli_cimag(temp) - bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp ); /* L160: */ } if (nounit) { bla_r_cnjg(&q__2, &a[j * a_dim1 + 1]); bla_c_div(&q__1, &temp, &q__2); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp ); } } i__4 = j; bli_csets( (bli_creal(temp)), (bli_cimag(temp)), x[i__4] ); /* L170: */ } } else { kx += (*n - 1) * *incx; jx = kx; for (j = *n; j >= 1; --j) { i__4 = jx; bli_csets( (bli_creal(x[i__4])), (bli_cimag(x[i__4])), temp ); ix = kx; l = 1 - j; if (noconj) { /* Computing MIN */ i__4 = *n, i__2 = j + *k; i__1 = j + 1; for (i__ = f2c_min(i__4,i__2); i__ >= i__1; --i__) { i__4 = l + i__ + j * a_dim1; i__2 = ix; bli_csets( (bli_creal(a[i__4]) * bli_creal(x[i__2]) - bli_cimag(a[i__4]) * bli_cimag(x[i__2])), (bli_creal(a[i__4]) * bli_cimag(x[i__2]) + bli_cimag(a[i__4]) * bli_creal(x[i__2])), q__2 ); bli_csets( (bli_creal(temp) - bli_creal(q__2)), (bli_cimag(temp) - bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp ); ix -= *incx; /* L180: */ } if (nounit) { bla_c_div(&q__1, &temp, &a[j * a_dim1 + 1]); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp ); } } else { /* Computing MIN */ i__1 = *n, i__4 = j + *k; i__2 = j + 1; for (i__ = f2c_min(i__1,i__4); i__ >= i__2; --i__) { bla_r_cnjg(&q__3, &a[l + i__ + j * a_dim1]); i__1 = ix; bli_csets( (bli_creal(q__3) * bli_creal(x[i__1]) - bli_cimag(q__3) * bli_cimag(x[i__1])), (bli_creal(q__3) * bli_cimag(x[i__1]) + bli_cimag(q__3) * bli_creal(x[i__1])), q__2 ); bli_csets( (bli_creal(temp) - bli_creal(q__2)), (bli_cimag(temp) - bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp ); ix -= *incx; /* L190: */ } if (nounit) { bla_r_cnjg(&q__2, &a[j * a_dim1 + 1]); bla_c_div(&q__1, &temp, &q__2); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp ); } } i__2 = jx; bli_csets( (bli_creal(temp)), (bli_cimag(temp)), x[i__2] ); jx -= *incx; if (*n - j >= *k) { kx -= *incx; } /* L200: */ } } } } return 0; /* End of CTBSV . */ } /* ctbsv_ */ /* dtbsv.f -- translated by f2c (version 19991025). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ /* Subroutine */ int PASTEF77(d,tbsv)(const bla_character *uplo, const bla_character *trans, const bla_character *diag, const bla_integer *n, const bla_integer *k, const bla_double *a, const bla_integer *lda, bla_double *x, const bla_integer *incx) { /* System generated locals */ bla_integer a_dim1, a_offset, i__1, i__2, i__3, i__4; /* Local variables */ bla_integer info; bla_double temp; bla_integer i__, j, l; //extern bla_logical PASTEF770(lsame)(bla_character *, bla_character *, ftnlen, ftnlen); bla_integer kplus1, ix, jx, kx = 0; //extern /* Subroutine */ int PASTEF770(xerbla)(bla_character *, bla_integer *, ftnlen); bla_logical nounit; /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* DTBSV solves one of the systems of equations */ /* A*x = b, or A'*x = b, */ /* where b and x are n element vectors and A is an n by n unit, or */ /* non-unit, upper or lower triangular band matrix, with ( k + 1 ) */ /* diagonals. */ /* No test for singularity or near-singularity is included in this */ /* routine. Such tests must be performed before calling this routine. */ /* Parameters */ /* ========== */ /* UPLO - CHARACTER*1. */ /* On entry, UPLO specifies whether the matrix is an upper or */ /* lower triangular matrix as follows: */ /* UPLO = 'U' or 'u' A is an upper triangular matrix. */ /* UPLO = 'L' or 'l' A is a lower triangular matrix. */ /* Unchanged on exit. */ /* TRANS - CHARACTER*1. */ /* On entry, TRANS specifies the equations to be solved as */ /* follows: */ /* TRANS = 'N' or 'n' A*x = b. */ /* TRANS = 'T' or 't' A'*x = b. */ /* TRANS = 'C' or 'c' A'*x = b. */ /* Unchanged on exit. */ /* DIAG - CHARACTER*1. */ /* On entry, DIAG specifies whether or not A is unit */ /* triangular as follows: */ /* DIAG = 'U' or 'u' A is assumed to be unit triangular. */ /* DIAG = 'N' or 'n' A is not assumed to be unit */ /* triangular. */ /* Unchanged on exit. */ /* N - INTEGER. */ /* On entry, N specifies the order of the matrix A. */ /* N must be at least zero. */ /* Unchanged on exit. */ /* K - INTEGER. */ /* On entry with UPLO = 'U' or 'u', K specifies the number of */ /* super-diagonals of the matrix A. */ /* On entry with UPLO = 'L' or 'l', K specifies the number of */ /* sub-diagonals of the matrix A. */ /* K must satisfy 0 .le. K. */ /* Unchanged on exit. */ /* A - DOUBLE PRECISION array of DIMENSION ( LDA, n ). */ /* Before entry with UPLO = 'U' or 'u', the leading ( k + 1 ) */ /* by n part of the array A must contain the upper triangular */ /* band part of the matrix of coefficients, supplied column by */ /* column, with the leading diagonal of the matrix in row */ /* ( k + 1 ) of the array, the first super-diagonal starting at */ /* position 2 in row k, and so on. The top left k by k triangle */ /* of the array A is not referenced. */ /* The following program segment will transfer an upper */ /* triangular band matrix from conventional full matrix storage */ /* to band storage: */ /* DO 20, J = 1, N */ /* M = K + 1 - J */ /* DO 10, I = MAX( 1, J - K ), J */ /* A( M + I, J ) = matrix( I, J ) */ /* 10 CONTINUE */ /* 20 CONTINUE */ /* Before entry with UPLO = 'L' or 'l', the leading ( k + 1 ) */ /* by n part of the array A must contain the lower triangular */ /* band part of the matrix of coefficients, supplied column by */ /* column, with the leading diagonal of the matrix in row 1 of */ /* the array, the first sub-diagonal starting at position 1 in */ /* row 2, and so on. The bottom right k by k triangle of the */ /* array A is not referenced. */ /* The following program segment will transfer a lower */ /* triangular band matrix from conventional full matrix storage */ /* to band storage: */ /* DO 20, J = 1, N */ /* M = 1 - J */ /* DO 10, I = J, MIN( N, J + K ) */ /* A( M + I, J ) = matrix( I, J ) */ /* 10 CONTINUE */ /* 20 CONTINUE */ /* Note that when DIAG = 'U' or 'u' the elements of the array A */ /* corresponding to the diagonal elements of the matrix are not */ /* referenced, but are assumed to be unity. */ /* Unchanged on exit. */ /* LDA - INTEGER. */ /* On entry, LDA specifies the first dimension of A as declared */ /* in the calling (sub) program. LDA must be at least */ /* ( k + 1 ). */ /* Unchanged on exit. */ /* X - DOUBLE PRECISION array of dimension at least */ /* ( 1 + ( n - 1 )*abs( INCX ) ). */ /* Before entry, the incremented array X must contain the n */ /* element right-hand side vector b. On exit, X is overwritten */ /* with the solution vector x. */ /* INCX - INTEGER. */ /* On entry, INCX specifies the increment for the elements of */ /* X. INCX must not be zero. */ /* Unchanged on exit. */ /* Level 2 Blas routine. */ /* -- Written on 22-October-1986. */ /* Jack Dongarra, Argonne National Lab. */ /* Jeremy Du Croz, Nag Central Office. */ /* Sven Hammarling, Nag Central Office. */ /* Richard Hanson, Sandia National Labs. */ /* .. Parameters .. */ /* .. Local Scalars .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. */ /* .. Executable Statements .. */ /* Test the input parameters. */ /* Parameter adjustments */ a_dim1 = *lda; a_offset = 1 + a_dim1 * 1; a -= a_offset; --x; /* Function Body */ info = 0; if (! PASTEF770(lsame)(uplo, "U", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(uplo, "L", ( ftnlen)1, (ftnlen)1)) { info = 1; } else if (! PASTEF770(lsame)(trans, "N", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(trans, "T", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(trans, "C", (ftnlen)1, ( ftnlen)1)) { info = 2; } else if (! PASTEF770(lsame)(diag, "U", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(diag, "N", (ftnlen)1, (ftnlen)1)) { info = 3; } else if (*n < 0) { info = 4; } else if (*k < 0) { info = 5; } else if (*lda < *k + 1) { info = 7; } else if (*incx == 0) { info = 9; } if (info != 0) { PASTEF770(xerbla)("DTBSV ", &info, (ftnlen)6); return 0; } /* Quick return if possible. */ if (*n == 0) { return 0; } nounit = PASTEF770(lsame)(diag, "N", (ftnlen)1, (ftnlen)1); /* Set up the start point in X if the increment is not unity. This */ /* will be ( N - 1 )*INCX too small for descending loops. */ if (*incx <= 0) { kx = 1 - (*n - 1) * *incx; } else if (*incx != 1) { kx = 1; } /* Start the operations. In this version the elements of A are */ /* accessed by sequentially with one pass through A. */ if (PASTEF770(lsame)(trans, "N", (ftnlen)1, (ftnlen)1)) { /* Form x := inv( A )*x. */ if (PASTEF770(lsame)(uplo, "U", (ftnlen)1, (ftnlen)1)) { kplus1 = *k + 1; if (*incx == 1) { for (j = *n; j >= 1; --j) { if (x[j] != 0.) { l = kplus1 - j; if (nounit) { x[j] /= a[kplus1 + j * a_dim1]; } temp = x[j]; /* Computing MAX */ i__2 = 1, i__3 = j - *k; i__1 = f2c_max(i__2,i__3); for (i__ = j - 1; i__ >= i__1; --i__) { x[i__] -= temp * a[l + i__ + j * a_dim1]; /* L10: */ } } /* L20: */ } } else { kx += (*n - 1) * *incx; jx = kx; for (j = *n; j >= 1; --j) { kx -= *incx; if (x[jx] != 0.) { ix = kx; l = kplus1 - j; if (nounit) { x[jx] /= a[kplus1 + j * a_dim1]; } temp = x[jx]; /* Computing MAX */ i__2 = 1, i__3 = j - *k; i__1 = f2c_max(i__2,i__3); for (i__ = j - 1; i__ >= i__1; --i__) { x[ix] -= temp * a[l + i__ + j * a_dim1]; ix -= *incx; /* L30: */ } } jx -= *incx; /* L40: */ } } } else { if (*incx == 1) { i__1 = *n; for (j = 1; j <= i__1; ++j) { if (x[j] != 0.) { l = 1 - j; if (nounit) { x[j] /= a[j * a_dim1 + 1]; } temp = x[j]; /* Computing MIN */ i__3 = *n, i__4 = j + *k; i__2 = f2c_min(i__3,i__4); for (i__ = j + 1; i__ <= i__2; ++i__) { x[i__] -= temp * a[l + i__ + j * a_dim1]; /* L50: */ } } /* L60: */ } } else { jx = kx; i__1 = *n; for (j = 1; j <= i__1; ++j) { kx += *incx; if (x[jx] != 0.) { ix = kx; l = 1 - j; if (nounit) { x[jx] /= a[j * a_dim1 + 1]; } temp = x[jx]; /* Computing MIN */ i__3 = *n, i__4 = j + *k; i__2 = f2c_min(i__3,i__4); for (i__ = j + 1; i__ <= i__2; ++i__) { x[ix] -= temp * a[l + i__ + j * a_dim1]; ix += *incx; /* L70: */ } } jx += *incx; /* L80: */ } } } } else { /* Form x := inv( A')*x. */ if (PASTEF770(lsame)(uplo, "U", (ftnlen)1, (ftnlen)1)) { kplus1 = *k + 1; if (*incx == 1) { i__1 = *n; for (j = 1; j <= i__1; ++j) { temp = x[j]; l = kplus1 - j; /* Computing MAX */ i__2 = 1, i__3 = j - *k; i__4 = j - 1; for (i__ = f2c_max(i__2,i__3); i__ <= i__4; ++i__) { temp -= a[l + i__ + j * a_dim1] * x[i__]; /* L90: */ } if (nounit) { temp /= a[kplus1 + j * a_dim1]; } x[j] = temp; /* L100: */ } } else { jx = kx; i__1 = *n; for (j = 1; j <= i__1; ++j) { temp = x[jx]; ix = kx; l = kplus1 - j; /* Computing MAX */ i__4 = 1, i__2 = j - *k; i__3 = j - 1; for (i__ = f2c_max(i__4,i__2); i__ <= i__3; ++i__) { temp -= a[l + i__ + j * a_dim1] * x[ix]; ix += *incx; /* L110: */ } if (nounit) { temp /= a[kplus1 + j * a_dim1]; } x[jx] = temp; jx += *incx; if (j > *k) { kx += *incx; } /* L120: */ } } } else { if (*incx == 1) { for (j = *n; j >= 1; --j) { temp = x[j]; l = 1 - j; /* Computing MIN */ i__1 = *n, i__3 = j + *k; i__4 = j + 1; for (i__ = f2c_min(i__1,i__3); i__ >= i__4; --i__) { temp -= a[l + i__ + j * a_dim1] * x[i__]; /* L130: */ } if (nounit) { temp /= a[j * a_dim1 + 1]; } x[j] = temp; /* L140: */ } } else { kx += (*n - 1) * *incx; jx = kx; for (j = *n; j >= 1; --j) { temp = x[jx]; ix = kx; l = 1 - j; /* Computing MIN */ i__4 = *n, i__1 = j + *k; i__3 = j + 1; for (i__ = f2c_min(i__4,i__1); i__ >= i__3; --i__) { temp -= a[l + i__ + j * a_dim1] * x[ix]; ix -= *incx; /* L150: */ } if (nounit) { temp /= a[j * a_dim1 + 1]; } x[jx] = temp; jx -= *incx; if (*n - j >= *k) { kx -= *incx; } /* L160: */ } } } } return 0; /* End of DTBSV . */ } /* dtbsv_ */ /* stbsv.f -- translated by f2c (version 19991025). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ /* Subroutine */ int PASTEF77(s,tbsv)(const bla_character *uplo, const bla_character *trans, const bla_character *diag, const bla_integer *n, const bla_integer *k, const bla_real *a, const bla_integer *lda, bla_real *x, const bla_integer *incx) { /* System generated locals */ bla_integer a_dim1, a_offset, i__1, i__2, i__3, i__4; /* Local variables */ bla_integer info; bla_real temp; bla_integer i__, j, l; //extern bla_logical PASTEF770(lsame)(bla_character *, bla_character *, ftnlen, ftnlen); bla_integer kplus1, ix, jx, kx = 0; //extern /* Subroutine */ int PASTEF770(xerbla)(bla_character *, bla_integer *, ftnlen); bla_logical nounit; /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* STBSV solves one of the systems of equations */ /* A*x = b, or A'*x = b, */ /* where b and x are n element vectors and A is an n by n unit, or */ /* non-unit, upper or lower triangular band matrix, with ( k + 1 ) */ /* diagonals. */ /* No test for singularity or near-singularity is included in this */ /* routine. Such tests must be performed before calling this routine. */ /* Parameters */ /* ========== */ /* UPLO - CHARACTER*1. */ /* On entry, UPLO specifies whether the matrix is an upper or */ /* lower triangular matrix as follows: */ /* UPLO = 'U' or 'u' A is an upper triangular matrix. */ /* UPLO = 'L' or 'l' A is a lower triangular matrix. */ /* Unchanged on exit. */ /* TRANS - CHARACTER*1. */ /* On entry, TRANS specifies the equations to be solved as */ /* follows: */ /* TRANS = 'N' or 'n' A*x = b. */ /* TRANS = 'T' or 't' A'*x = b. */ /* TRANS = 'C' or 'c' A'*x = b. */ /* Unchanged on exit. */ /* DIAG - CHARACTER*1. */ /* On entry, DIAG specifies whether or not A is unit */ /* triangular as follows: */ /* DIAG = 'U' or 'u' A is assumed to be unit triangular. */ /* DIAG = 'N' or 'n' A is not assumed to be unit */ /* triangular. */ /* Unchanged on exit. */ /* N - INTEGER. */ /* On entry, N specifies the order of the matrix A. */ /* N must be at least zero. */ /* Unchanged on exit. */ /* K - INTEGER. */ /* On entry with UPLO = 'U' or 'u', K specifies the number of */ /* super-diagonals of the matrix A. */ /* On entry with UPLO = 'L' or 'l', K specifies the number of */ /* sub-diagonals of the matrix A. */ /* K must satisfy 0 .le. K. */ /* Unchanged on exit. */ /* A - REAL array of DIMENSION ( LDA, n ). */ /* Before entry with UPLO = 'U' or 'u', the leading ( k + 1 ) */ /* by n part of the array A must contain the upper triangular */ /* band part of the matrix of coefficients, supplied column by */ /* column, with the leading diagonal of the matrix in row */ /* ( k + 1 ) of the array, the first super-diagonal starting at */ /* position 2 in row k, and so on. The top left k by k triangle */ /* of the array A is not referenced. */ /* The following program segment will transfer an upper */ /* triangular band matrix from conventional full matrix storage */ /* to band storage: */ /* DO 20, J = 1, N */ /* M = K + 1 - J */ /* DO 10, I = MAX( 1, J - K ), J */ /* A( M + I, J ) = matrix( I, J ) */ /* 10 CONTINUE */ /* 20 CONTINUE */ /* Before entry with UPLO = 'L' or 'l', the leading ( k + 1 ) */ /* by n part of the array A must contain the lower triangular */ /* band part of the matrix of coefficients, supplied column by */ /* column, with the leading diagonal of the matrix in row 1 of */ /* the array, the first sub-diagonal starting at position 1 in */ /* row 2, and so on. The bottom right k by k triangle of the */ /* array A is not referenced. */ /* The following program segment will transfer a lower */ /* triangular band matrix from conventional full matrix storage */ /* to band storage: */ /* DO 20, J = 1, N */ /* M = 1 - J */ /* DO 10, I = J, MIN( N, J + K ) */ /* A( M + I, J ) = matrix( I, J ) */ /* 10 CONTINUE */ /* 20 CONTINUE */ /* Note that when DIAG = 'U' or 'u' the elements of the array A */ /* corresponding to the diagonal elements of the matrix are not */ /* referenced, but are assumed to be unity. */ /* Unchanged on exit. */ /* LDA - INTEGER. */ /* On entry, LDA specifies the first dimension of A as declared */ /* in the calling (sub) program. LDA must be at least */ /* ( k + 1 ). */ /* Unchanged on exit. */ /* X - REAL array of dimension at least */ /* ( 1 + ( n - 1 )*abs( INCX ) ). */ /* Before entry, the incremented array X must contain the n */ /* element right-hand side vector b. On exit, X is overwritten */ /* with the solution vector x. */ /* INCX - INTEGER. */ /* On entry, INCX specifies the increment for the elements of */ /* X. INCX must not be zero. */ /* Unchanged on exit. */ /* Level 2 Blas routine. */ /* -- Written on 22-October-1986. */ /* Jack Dongarra, Argonne National Lab. */ /* Jeremy Du Croz, Nag Central Office. */ /* Sven Hammarling, Nag Central Office. */ /* Richard Hanson, Sandia National Labs. */ /* .. Parameters .. */ /* .. Local Scalars .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. */ /* .. Executable Statements .. */ /* Test the input parameters. */ /* Parameter adjustments */ a_dim1 = *lda; a_offset = 1 + a_dim1 * 1; a -= a_offset; --x; /* Function Body */ info = 0; if (! PASTEF770(lsame)(uplo, "U", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(uplo, "L", ( ftnlen)1, (ftnlen)1)) { info = 1; } else if (! PASTEF770(lsame)(trans, "N", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(trans, "T", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(trans, "C", (ftnlen)1, ( ftnlen)1)) { info = 2; } else if (! PASTEF770(lsame)(diag, "U", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(diag, "N", (ftnlen)1, (ftnlen)1)) { info = 3; } else if (*n < 0) { info = 4; } else if (*k < 0) { info = 5; } else if (*lda < *k + 1) { info = 7; } else if (*incx == 0) { info = 9; } if (info != 0) { PASTEF770(xerbla)("STBSV ", &info, (ftnlen)6); return 0; } /* Quick return if possible. */ if (*n == 0) { return 0; } nounit = PASTEF770(lsame)(diag, "N", (ftnlen)1, (ftnlen)1); /* Set up the start point in X if the increment is not unity. This */ /* will be ( N - 1 )*INCX too small for descending loops. */ if (*incx <= 0) { kx = 1 - (*n - 1) * *incx; } else if (*incx != 1) { kx = 1; } /* Start the operations. In this version the elements of A are */ /* accessed by sequentially with one pass through A. */ if (PASTEF770(lsame)(trans, "N", (ftnlen)1, (ftnlen)1)) { /* Form x := inv( A )*x. */ if (PASTEF770(lsame)(uplo, "U", (ftnlen)1, (ftnlen)1)) { kplus1 = *k + 1; if (*incx == 1) { for (j = *n; j >= 1; --j) { if (x[j] != 0.f) { l = kplus1 - j; if (nounit) { x[j] /= a[kplus1 + j * a_dim1]; } temp = x[j]; /* Computing MAX */ i__2 = 1, i__3 = j - *k; i__1 = f2c_max(i__2,i__3); for (i__ = j - 1; i__ >= i__1; --i__) { x[i__] -= temp * a[l + i__ + j * a_dim1]; /* L10: */ } } /* L20: */ } } else { kx += (*n - 1) * *incx; jx = kx; for (j = *n; j >= 1; --j) { kx -= *incx; if (x[jx] != 0.f) { ix = kx; l = kplus1 - j; if (nounit) { x[jx] /= a[kplus1 + j * a_dim1]; } temp = x[jx]; /* Computing MAX */ i__2 = 1, i__3 = j - *k; i__1 = f2c_max(i__2,i__3); for (i__ = j - 1; i__ >= i__1; --i__) { x[ix] -= temp * a[l + i__ + j * a_dim1]; ix -= *incx; /* L30: */ } } jx -= *incx; /* L40: */ } } } else { if (*incx == 1) { i__1 = *n; for (j = 1; j <= i__1; ++j) { if (x[j] != 0.f) { l = 1 - j; if (nounit) { x[j] /= a[j * a_dim1 + 1]; } temp = x[j]; /* Computing MIN */ i__3 = *n, i__4 = j + *k; i__2 = f2c_min(i__3,i__4); for (i__ = j + 1; i__ <= i__2; ++i__) { x[i__] -= temp * a[l + i__ + j * a_dim1]; /* L50: */ } } /* L60: */ } } else { jx = kx; i__1 = *n; for (j = 1; j <= i__1; ++j) { kx += *incx; if (x[jx] != 0.f) { ix = kx; l = 1 - j; if (nounit) { x[jx] /= a[j * a_dim1 + 1]; } temp = x[jx]; /* Computing MIN */ i__3 = *n, i__4 = j + *k; i__2 = f2c_min(i__3,i__4); for (i__ = j + 1; i__ <= i__2; ++i__) { x[ix] -= temp * a[l + i__ + j * a_dim1]; ix += *incx; /* L70: */ } } jx += *incx; /* L80: */ } } } } else { /* Form x := inv( A')*x. */ if (PASTEF770(lsame)(uplo, "U", (ftnlen)1, (ftnlen)1)) { kplus1 = *k + 1; if (*incx == 1) { i__1 = *n; for (j = 1; j <= i__1; ++j) { temp = x[j]; l = kplus1 - j; /* Computing MAX */ i__2 = 1, i__3 = j - *k; i__4 = j - 1; for (i__ = f2c_max(i__2,i__3); i__ <= i__4; ++i__) { temp -= a[l + i__ + j * a_dim1] * x[i__]; /* L90: */ } if (nounit) { temp /= a[kplus1 + j * a_dim1]; } x[j] = temp; /* L100: */ } } else { jx = kx; i__1 = *n; for (j = 1; j <= i__1; ++j) { temp = x[jx]; ix = kx; l = kplus1 - j; /* Computing MAX */ i__4 = 1, i__2 = j - *k; i__3 = j - 1; for (i__ = f2c_max(i__4,i__2); i__ <= i__3; ++i__) { temp -= a[l + i__ + j * a_dim1] * x[ix]; ix += *incx; /* L110: */ } if (nounit) { temp /= a[kplus1 + j * a_dim1]; } x[jx] = temp; jx += *incx; if (j > *k) { kx += *incx; } /* L120: */ } } } else { if (*incx == 1) { for (j = *n; j >= 1; --j) { temp = x[j]; l = 1 - j; /* Computing MIN */ i__1 = *n, i__3 = j + *k; i__4 = j + 1; for (i__ = f2c_min(i__1,i__3); i__ >= i__4; --i__) { temp -= a[l + i__ + j * a_dim1] * x[i__]; /* L130: */ } if (nounit) { temp /= a[j * a_dim1 + 1]; } x[j] = temp; /* L140: */ } } else { kx += (*n - 1) * *incx; jx = kx; for (j = *n; j >= 1; --j) { temp = x[jx]; ix = kx; l = 1 - j; /* Computing MIN */ i__4 = *n, i__1 = j + *k; i__3 = j + 1; for (i__ = f2c_min(i__4,i__1); i__ >= i__3; --i__) { temp -= a[l + i__ + j * a_dim1] * x[ix]; ix -= *incx; /* L150: */ } if (nounit) { temp /= a[j * a_dim1 + 1]; } x[jx] = temp; jx -= *incx; if (*n - j >= *k) { kx -= *incx; } /* L160: */ } } } } return 0; /* End of STBSV . */ } /* stbsv_ */ /* ztbsv.f -- translated by f2c (version 19991025). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ /* Subroutine */ int PASTEF77(z,tbsv)(const bla_character *uplo, const bla_character *trans, const bla_character *diag, const bla_integer *n, const bla_integer *k, const bla_dcomplex *a, const bla_integer *lda, bla_dcomplex *x, const bla_integer *incx) { /* System generated locals */ bla_integer a_dim1, a_offset, i__1, i__2, i__3, i__4, i__5; bla_dcomplex z__1, z__2, z__3; /* Builtin functions */ //void bla_z_div(bla_dcomplex *, bla_dcomplex *, bla_dcomplex *), bla_d_cnjg( // bla_dcomplex *, bla_dcomplex *); /* Local variables */ bla_integer info; bla_dcomplex temp; bla_integer i__, j, l; //extern bla_logical PASTEF770(lsame)(bla_character *, bla_character *, ftnlen, ftnlen); bla_integer kplus1, ix, jx, kx = 0; //extern /* Subroutine */ int PASTEF770(xerbla)(bla_character *, bla_integer *, ftnlen); bla_logical noconj, nounit; /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* ZTBSV solves one of the systems of equations */ /* A*x = b, or A'*x = b, or conjg( A' )*x = b, */ /* where b and x are n element vectors and A is an n by n unit, or */ /* non-unit, upper or lower triangular band matrix, with ( k + 1 ) */ /* diagonals. */ /* No test for singularity or near-singularity is included in this */ /* routine. Such tests must be performed before calling this routine. */ /* Parameters */ /* ========== */ /* UPLO - CHARACTER*1. */ /* On entry, UPLO specifies whether the matrix is an upper or */ /* lower triangular matrix as follows: */ /* UPLO = 'U' or 'u' A is an upper triangular matrix. */ /* UPLO = 'L' or 'l' A is a lower triangular matrix. */ /* Unchanged on exit. */ /* TRANS - CHARACTER*1. */ /* On entry, TRANS specifies the equations to be solved as */ /* follows: */ /* TRANS = 'N' or 'n' A*x = b. */ /* TRANS = 'T' or 't' A'*x = b. */ /* TRANS = 'C' or 'c' conjg( A' )*x = b. */ /* Unchanged on exit. */ /* DIAG - CHARACTER*1. */ /* On entry, DIAG specifies whether or not A is unit */ /* triangular as follows: */ /* DIAG = 'U' or 'u' A is assumed to be unit triangular. */ /* DIAG = 'N' or 'n' A is not assumed to be unit */ /* triangular. */ /* Unchanged on exit. */ /* N - INTEGER. */ /* On entry, N specifies the order of the matrix A. */ /* N must be at least zero. */ /* Unchanged on exit. */ /* K - INTEGER. */ /* On entry with UPLO = 'U' or 'u', K specifies the number of */ /* super-diagonals of the matrix A. */ /* On entry with UPLO = 'L' or 'l', K specifies the number of */ /* sub-diagonals of the matrix A. */ /* K must satisfy 0 .le. K. */ /* Unchanged on exit. */ /* A - COMPLEX*16 array of DIMENSION ( LDA, n ). */ /* Before entry with UPLO = 'U' or 'u', the leading ( k + 1 ) */ /* by n part of the array A must contain the upper triangular */ /* band part of the matrix of coefficients, supplied column by */ /* column, with the leading diagonal of the matrix in row */ /* ( k + 1 ) of the array, the first super-diagonal starting at */ /* position 2 in row k, and so on. The top left k by k triangle */ /* of the array A is not referenced. */ /* The following program segment will transfer an upper */ /* triangular band matrix from conventional full matrix storage */ /* to band storage: */ /* DO 20, J = 1, N */ /* M = K + 1 - J */ /* DO 10, I = MAX( 1, J - K ), J */ /* A( M + I, J ) = matrix( I, J ) */ /* 10 CONTINUE */ /* 20 CONTINUE */ /* Before entry with UPLO = 'L' or 'l', the leading ( k + 1 ) */ /* by n part of the array A must contain the lower triangular */ /* band part of the matrix of coefficients, supplied column by */ /* column, with the leading diagonal of the matrix in row 1 of */ /* the array, the first sub-diagonal starting at position 1 in */ /* row 2, and so on. The bottom right k by k triangle of the */ /* array A is not referenced. */ /* The following program segment will transfer a lower */ /* triangular band matrix from conventional full matrix storage */ /* to band storage: */ /* DO 20, J = 1, N */ /* M = 1 - J */ /* DO 10, I = J, MIN( N, J + K ) */ /* A( M + I, J ) = matrix( I, J ) */ /* 10 CONTINUE */ /* 20 CONTINUE */ /* Note that when DIAG = 'U' or 'u' the elements of the array A */ /* corresponding to the diagonal elements of the matrix are not */ /* referenced, but are assumed to be unity. */ /* Unchanged on exit. */ /* LDA - INTEGER. */ /* On entry, LDA specifies the first dimension of A as declared */ /* in the calling (sub) program. LDA must be at least */ /* ( k + 1 ). */ /* Unchanged on exit. */ /* X - COMPLEX*16 array of dimension at least */ /* ( 1 + ( n - 1 )*abs( INCX ) ). */ /* Before entry, the incremented array X must contain the n */ /* element right-hand side vector b. On exit, X is overwritten */ /* with the solution vector x. */ /* INCX - INTEGER. */ /* On entry, INCX specifies the increment for the elements of */ /* X. INCX must not be zero. */ /* Unchanged on exit. */ /* Level 2 Blas routine. */ /* -- Written on 22-October-1986. */ /* Jack Dongarra, Argonne National Lab. */ /* Jeremy Du Croz, Nag Central Office. */ /* Sven Hammarling, Nag Central Office. */ /* Richard Hanson, Sandia National Labs. */ /* .. Parameters .. */ /* .. Local Scalars .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. */ /* .. Executable Statements .. */ /* Test the input parameters. */ /* Parameter adjustments */ a_dim1 = *lda; a_offset = 1 + a_dim1 * 1; a -= a_offset; --x; /* Function Body */ info = 0; if (! PASTEF770(lsame)(uplo, "U", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(uplo, "L", ( ftnlen)1, (ftnlen)1)) { info = 1; } else if (! PASTEF770(lsame)(trans, "N", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(trans, "T", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(trans, "C", (ftnlen)1, ( ftnlen)1)) { info = 2; } else if (! PASTEF770(lsame)(diag, "U", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(diag, "N", (ftnlen)1, (ftnlen)1)) { info = 3; } else if (*n < 0) { info = 4; } else if (*k < 0) { info = 5; } else if (*lda < *k + 1) { info = 7; } else if (*incx == 0) { info = 9; } if (info != 0) { PASTEF770(xerbla)("ZTBSV ", &info, (ftnlen)6); return 0; } /* Quick return if possible. */ if (*n == 0) { return 0; } noconj = PASTEF770(lsame)(trans, "T", (ftnlen)1, (ftnlen)1); nounit = PASTEF770(lsame)(diag, "N", (ftnlen)1, (ftnlen)1); /* Set up the start point in X if the increment is not unity. This */ /* will be ( N - 1 )*INCX too small for descending loops. */ if (*incx <= 0) { kx = 1 - (*n - 1) * *incx; } else if (*incx != 1) { kx = 1; } /* Start the operations. In this version the elements of A are */ /* accessed by sequentially with one pass through A. */ if (PASTEF770(lsame)(trans, "N", (ftnlen)1, (ftnlen)1)) { /* Form x := inv( A )*x. */ if (PASTEF770(lsame)(uplo, "U", (ftnlen)1, (ftnlen)1)) { kplus1 = *k + 1; if (*incx == 1) { for (j = *n; j >= 1; --j) { i__1 = j; if (bli_zreal(x[i__1]) != 0. || bli_zimag(x[i__1]) != 0.) { l = kplus1 - j; if (nounit) { i__1 = j; bla_z_div(&z__1, &x[j], &a[kplus1 + j * a_dim1]); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), x[i__1] ); } i__1 = j; bli_zsets( (bli_zreal(x[i__1])), (bli_zimag(x[i__1])), temp ); /* Computing MAX */ i__2 = 1, i__3 = j - *k; i__1 = f2c_max(i__2,i__3); for (i__ = j - 1; i__ >= i__1; --i__) { i__2 = i__; i__3 = i__; i__4 = l + i__ + j * a_dim1; bli_zsets( (bli_zreal(temp) * bli_zreal(a[i__4]) - bli_zimag(temp) * bli_zimag(a[i__4])), (bli_zreal(temp) * bli_zimag(a[i__4]) + bli_zimag(temp) * bli_zreal(a[i__4])), z__2 ); bli_zsets( (bli_zreal(x[i__3]) - bli_zreal(z__2)), (bli_zimag(x[i__3]) - bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), x[i__2] ); /* L10: */ } } /* L20: */ } } else { kx += (*n - 1) * *incx; jx = kx; for (j = *n; j >= 1; --j) { kx -= *incx; i__1 = jx; if (bli_zreal(x[i__1]) != 0. || bli_zimag(x[i__1]) != 0.) { ix = kx; l = kplus1 - j; if (nounit) { i__1 = jx; bla_z_div(&z__1, &x[jx], &a[kplus1 + j * a_dim1]); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), x[i__1] ); } i__1 = jx; bli_zsets( (bli_zreal(x[i__1])), (bli_zimag(x[i__1])), temp ); /* Computing MAX */ i__2 = 1, i__3 = j - *k; i__1 = f2c_max(i__2,i__3); for (i__ = j - 1; i__ >= i__1; --i__) { i__2 = ix; i__3 = ix; i__4 = l + i__ + j * a_dim1; bli_zsets( (bli_zreal(temp) * bli_zreal(a[i__4]) - bli_zimag(temp) * bli_zimag(a[i__4])), (bli_zreal(temp) * bli_zimag(a[i__4]) + bli_zimag(temp) * bli_zreal(a[i__4])), z__2 ); bli_zsets( (bli_zreal(x[i__3]) - bli_zreal(z__2)), (bli_zimag(x[i__3]) - bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), x[i__2] ); ix -= *incx; /* L30: */ } } jx -= *incx; /* L40: */ } } } else { if (*incx == 1) { i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = j; if (bli_zreal(x[i__2]) != 0. || bli_zimag(x[i__2]) != 0.) { l = 1 - j; if (nounit) { i__2 = j; bla_z_div(&z__1, &x[j], &a[j * a_dim1 + 1]); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), x[i__2] ); } i__2 = j; bli_zsets( (bli_zreal(x[i__2])), (bli_zimag(x[i__2])), temp ); /* Computing MIN */ i__3 = *n, i__4 = j + *k; i__2 = f2c_min(i__3,i__4); for (i__ = j + 1; i__ <= i__2; ++i__) { i__3 = i__; i__4 = i__; i__5 = l + i__ + j * a_dim1; bli_zsets( (bli_zreal(temp) * bli_zreal(a[i__5]) - bli_zimag(temp) * bli_zimag(a[i__5])), (bli_zreal(temp) * bli_zimag(a[i__5]) + bli_zimag(temp) * bli_zreal(a[i__5])), z__2 ); bli_zsets( (bli_zreal(x[i__4]) - bli_zreal(z__2)), (bli_zimag(x[i__4]) - bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), x[i__3] ); /* L50: */ } } /* L60: */ } } else { jx = kx; i__1 = *n; for (j = 1; j <= i__1; ++j) { kx += *incx; i__2 = jx; if (bli_zreal(x[i__2]) != 0. || bli_zimag(x[i__2]) != 0.) { ix = kx; l = 1 - j; if (nounit) { i__2 = jx; bla_z_div(&z__1, &x[jx], &a[j * a_dim1 + 1]); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), x[i__2] ); } i__2 = jx; bli_zsets( (bli_zreal(x[i__2])), (bli_zimag(x[i__2])), temp ); /* Computing MIN */ i__3 = *n, i__4 = j + *k; i__2 = f2c_min(i__3,i__4); for (i__ = j + 1; i__ <= i__2; ++i__) { i__3 = ix; i__4 = ix; i__5 = l + i__ + j * a_dim1; bli_zsets( (bli_zreal(temp) * bli_zreal(a[i__5]) - bli_zimag(temp) * bli_zimag(a[i__5])), (bli_zreal(temp) * bli_zimag(a[i__5]) + bli_zimag(temp) * bli_zreal(a[i__5])), z__2 ); bli_zsets( (bli_zreal(x[i__4]) - bli_zreal(z__2)), (bli_zimag(x[i__4]) - bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), x[i__3] ); ix += *incx; /* L70: */ } } jx += *incx; /* L80: */ } } } } else { /* Form x := inv( A' )*x or x := inv( conjg( A') )*x. */ if (PASTEF770(lsame)(uplo, "U", (ftnlen)1, (ftnlen)1)) { kplus1 = *k + 1; if (*incx == 1) { i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = j; bli_zsets( (bli_zreal(x[i__2])), (bli_zimag(x[i__2])), temp ); l = kplus1 - j; if (noconj) { /* Computing MAX */ i__2 = 1, i__3 = j - *k; i__4 = j - 1; for (i__ = f2c_max(i__2,i__3); i__ <= i__4; ++i__) { i__2 = l + i__ + j * a_dim1; i__3 = i__; bli_zsets( (bli_zreal(a[i__2]) * bli_zreal(x[i__3]) - bli_zimag(a[i__2]) * bli_zimag(x[i__3])), (bli_zreal(a[i__2]) * bli_zimag(x[i__3]) + bli_zimag(a[i__2]) * bli_zreal(x[i__3])), z__2 ); bli_zsets( (bli_zreal(temp) - bli_zreal(z__2)), (bli_zimag(temp) - bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp ); /* L90: */ } if (nounit) { bla_z_div(&z__1, &temp, &a[kplus1 + j * a_dim1]); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp ); } } else { /* Computing MAX */ i__4 = 1, i__2 = j - *k; i__3 = j - 1; for (i__ = f2c_max(i__4,i__2); i__ <= i__3; ++i__) { bla_d_cnjg(&z__3, &a[l + i__ + j * a_dim1]); i__4 = i__; bli_zsets( (bli_zreal(z__3) * bli_zreal(x[i__4]) - bli_zimag(z__3) * bli_zimag(x[i__4])), (bli_zreal(z__3) * bli_zimag(x[i__4]) + bli_zimag(z__3) * bli_zreal(x[i__4])), z__2 ); bli_zsets( (bli_zreal(temp) - bli_zreal(z__2)), (bli_zimag(temp) - bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp ); /* L100: */ } if (nounit) { bla_d_cnjg(&z__2, &a[kplus1 + j * a_dim1]); bla_z_div(&z__1, &temp, &z__2); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp ); } } i__3 = j; bli_zsets( (bli_zreal(temp)), (bli_zimag(temp)), x[i__3] ); /* L110: */ } } else { jx = kx; i__1 = *n; for (j = 1; j <= i__1; ++j) { i__3 = jx; bli_zsets( (bli_zreal(x[i__3])), (bli_zimag(x[i__3])), temp ); ix = kx; l = kplus1 - j; if (noconj) { /* Computing MAX */ i__3 = 1, i__4 = j - *k; i__2 = j - 1; for (i__ = f2c_max(i__3,i__4); i__ <= i__2; ++i__) { i__3 = l + i__ + j * a_dim1; i__4 = ix; bli_zsets( (bli_zreal(a[i__3]) * bli_zreal(x[i__4]) - bli_zimag(a[i__3]) * bli_zimag(x[i__4])), (bli_zreal(a[i__3]) * bli_zimag(x[i__4]) + bli_zimag(a[i__3]) * bli_zreal(x[i__4])), z__2 ); bli_zsets( (bli_zreal(temp) - bli_zreal(z__2)), (bli_zimag(temp) - bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp ); ix += *incx; /* L120: */ } if (nounit) { bla_z_div(&z__1, &temp, &a[kplus1 + j * a_dim1]); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp ); } } else { /* Computing MAX */ i__2 = 1, i__3 = j - *k; i__4 = j - 1; for (i__ = f2c_max(i__2,i__3); i__ <= i__4; ++i__) { bla_d_cnjg(&z__3, &a[l + i__ + j * a_dim1]); i__2 = ix; bli_zsets( (bli_zreal(z__3) * bli_zreal(x[i__2]) - bli_zimag(z__3) * bli_zimag(x[i__2])), (bli_zreal(z__3) * bli_zimag(x[i__2]) + bli_zimag(z__3) * bli_zreal(x[i__2])), z__2 ); bli_zsets( (bli_zreal(temp) - bli_zreal(z__2)), (bli_zimag(temp) - bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp ); ix += *incx; /* L130: */ } if (nounit) { bla_d_cnjg(&z__2, &a[kplus1 + j * a_dim1]); bla_z_div(&z__1, &temp, &z__2); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp ); } } i__4 = jx; bli_zsets( (bli_zreal(temp)), (bli_zimag(temp)), x[i__4] ); jx += *incx; if (j > *k) { kx += *incx; } /* L140: */ } } } else { if (*incx == 1) { for (j = *n; j >= 1; --j) { i__1 = j; bli_zsets( (bli_zreal(x[i__1])), (bli_zimag(x[i__1])), temp ); l = 1 - j; if (noconj) { /* Computing MIN */ i__1 = *n, i__4 = j + *k; i__2 = j + 1; for (i__ = f2c_min(i__1,i__4); i__ >= i__2; --i__) { i__1 = l + i__ + j * a_dim1; i__4 = i__; bli_zsets( (bli_zreal(a[i__1]) * bli_zreal(x[i__4]) - bli_zimag(a[i__1]) * bli_zimag(x[i__4])), (bli_zreal(a[i__1]) * bli_zimag(x[i__4]) + bli_zimag(a[i__1]) * bli_zreal(x[i__4])), z__2 ); bli_zsets( (bli_zreal(temp) - bli_zreal(z__2)), (bli_zimag(temp) - bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp ); /* L150: */ } if (nounit) { bla_z_div(&z__1, &temp, &a[j * a_dim1 + 1]); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp ); } } else { /* Computing MIN */ i__2 = *n, i__1 = j + *k; i__4 = j + 1; for (i__ = f2c_min(i__2,i__1); i__ >= i__4; --i__) { bla_d_cnjg(&z__3, &a[l + i__ + j * a_dim1]); i__2 = i__; bli_zsets( (bli_zreal(z__3) * bli_zreal(x[i__2]) - bli_zimag(z__3) * bli_zimag(x[i__2])), (bli_zreal(z__3) * bli_zimag(x[i__2]) + bli_zimag(z__3) * bli_zreal(x[i__2])), z__2 ); bli_zsets( (bli_zreal(temp) - bli_zreal(z__2)), (bli_zimag(temp) - bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp ); /* L160: */ } if (nounit) { bla_d_cnjg(&z__2, &a[j * a_dim1 + 1]); bla_z_div(&z__1, &temp, &z__2); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp ); } } i__4 = j; bli_zsets( (bli_zreal(temp)), (bli_zimag(temp)), x[i__4] ); /* L170: */ } } else { kx += (*n - 1) * *incx; jx = kx; for (j = *n; j >= 1; --j) { i__4 = jx; bli_zsets( (bli_zreal(x[i__4])), (bli_zimag(x[i__4])), temp ); ix = kx; l = 1 - j; if (noconj) { /* Computing MIN */ i__4 = *n, i__2 = j + *k; i__1 = j + 1; for (i__ = f2c_min(i__4,i__2); i__ >= i__1; --i__) { i__4 = l + i__ + j * a_dim1; i__2 = ix; bli_zsets( (bli_zreal(a[i__4]) * bli_zreal(x[i__2]) - bli_zimag(a[i__4]) * bli_zimag(x[i__2])), (bli_zreal(a[i__4]) * bli_zimag(x[i__2]) + bli_zimag(a[i__4]) * bli_zreal(x[i__2])), z__2 ); bli_zsets( (bli_zreal(temp) - bli_zreal(z__2)), (bli_zimag(temp) - bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp ); ix -= *incx; /* L180: */ } if (nounit) { bla_z_div(&z__1, &temp, &a[j * a_dim1 + 1]); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp ); } } else { /* Computing MIN */ i__1 = *n, i__4 = j + *k; i__2 = j + 1; for (i__ = f2c_min(i__1,i__4); i__ >= i__2; --i__) { bla_d_cnjg(&z__3, &a[l + i__ + j * a_dim1]); i__1 = ix; bli_zsets( (bli_zreal(z__3) * bli_zreal(x[i__1]) - bli_zimag(z__3) * bli_zimag(x[i__1])), (bli_zreal(z__3) * bli_zimag(x[i__1]) + bli_zimag(z__3) * bli_zreal(x[i__1])), z__2 ); bli_zsets( (bli_zreal(temp) - bli_zreal(z__2)), (bli_zimag(temp) - bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp ); ix -= *incx; /* L190: */ } if (nounit) { bla_d_cnjg(&z__2, &a[j * a_dim1 + 1]); bla_z_div(&z__1, &temp, &z__2); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp ); } } i__2 = jx; bli_zsets( (bli_zreal(temp)), (bli_zimag(temp)), x[i__2] ); jx -= *incx; if (*n - j >= *k) { kx -= *incx; } /* L200: */ } } } } return 0; /* End of ZTBSV . */ } /* ztbsv_ */ #endif blis-0.9.0/frame/compat/f2c/bla_tbsv.h000066400000000000000000000052261422157504600174600ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifdef BLIS_ENABLE_BLAS BLIS_EXPORT_BLAS int PASTEF77(c,tbsv)(const bla_character *uplo, const bla_character *trans, const bla_character *diag, const bla_integer *n, const bla_integer *k, const bla_scomplex *a, const bla_integer *lda, bla_scomplex *x, const bla_integer *incx); BLIS_EXPORT_BLAS int PASTEF77(d,tbsv)(const bla_character *uplo, const bla_character *trans, const bla_character *diag, const bla_integer *n, const bla_integer *k, const bla_double *a, const bla_integer *lda, bla_double *x, const bla_integer *incx); BLIS_EXPORT_BLAS int PASTEF77(s,tbsv)(const bla_character *uplo, const bla_character *trans, const bla_character *diag, const bla_integer *n, const bla_integer *k, const bla_real *a, const bla_integer *lda, bla_real *x, const bla_integer *incx); BLIS_EXPORT_BLAS int PASTEF77(z,tbsv)(const bla_character *uplo, const bla_character *trans, const bla_character *diag, const bla_integer *n, const bla_integer *k, const bla_dcomplex *a, const bla_integer *lda, bla_dcomplex *x, const bla_integer *incx); #endif blis-0.9.0/frame/compat/f2c/bla_tpmv.c000066400000000000000000001550311422157504600174630ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #ifdef BLIS_ENABLE_BLAS /* ctpmv.f -- translated by f2c (version 19991025). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ /* Subroutine */ int PASTEF77(c,tpmv)(const bla_character *uplo, const bla_character *trans, const bla_character *diag, const bla_integer *n, const bla_scomplex *ap, bla_scomplex *x, const bla_integer *incx) { /* System generated locals */ bla_integer i__1, i__2, i__3, i__4, i__5; bla_scomplex q__1, q__2, q__3; /* Builtin functions */ //void bla_r_cnjg(bla_scomplex *, bla_scomplex *); /* Local variables */ bla_integer info; bla_scomplex temp; bla_integer i__, j, k; //extern bla_logical PASTEF770(lsame)(bla_character *, bla_character *, ftnlen, ftnlen); bla_integer kk, ix, jx, kx = 0; //extern /* Subroutine */ int PASTEF770(xerbla)(bla_character *, bla_integer *, ftnlen); bla_logical noconj, nounit; /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* CTPMV performs one of the matrix-vector operations */ /* x := A*x, or x := A'*x, or x := conjg( A' )*x, */ /* where x is an n element vector and A is an n by n unit, or non-unit, */ /* upper or lower triangular matrix, supplied in packed form. */ /* Parameters */ /* ========== */ /* UPLO - CHARACTER*1. */ /* On entry, UPLO specifies whether the matrix is an upper or */ /* lower triangular matrix as follows: */ /* UPLO = 'U' or 'u' A is an upper triangular matrix. */ /* UPLO = 'L' or 'l' A is a lower triangular matrix. */ /* Unchanged on exit. */ /* TRANS - CHARACTER*1. */ /* On entry, TRANS specifies the operation to be performed as */ /* follows: */ /* TRANS = 'N' or 'n' x := A*x. */ /* TRANS = 'T' or 't' x := A'*x. */ /* TRANS = 'C' or 'c' x := conjg( A' )*x. */ /* Unchanged on exit. */ /* DIAG - CHARACTER*1. */ /* On entry, DIAG specifies whether or not A is unit */ /* triangular as follows: */ /* DIAG = 'U' or 'u' A is assumed to be unit triangular. */ /* DIAG = 'N' or 'n' A is not assumed to be unit */ /* triangular. */ /* Unchanged on exit. */ /* N - INTEGER. */ /* On entry, N specifies the order of the matrix A. */ /* N must be at least zero. */ /* Unchanged on exit. */ /* AP - COMPLEX array of DIMENSION at least */ /* ( ( n*( n + 1 ) )/2 ). */ /* Before entry with UPLO = 'U' or 'u', the array AP must */ /* contain the upper triangular matrix packed sequentially, */ /* column by column, so that AP( 1 ) contains a( 1, 1 ), */ /* AP( 2 ) and AP( 3 ) contain a( 1, 2 ) and a( 2, 2 ) */ /* respectively, and so on. */ /* Before entry with UPLO = 'L' or 'l', the array AP must */ /* contain the lower triangular matrix packed sequentially, */ /* column by column, so that AP( 1 ) contains a( 1, 1 ), */ /* AP( 2 ) and AP( 3 ) contain a( 2, 1 ) and a( 3, 1 ) */ /* respectively, and so on. */ /* Note that when DIAG = 'U' or 'u', the diagonal elements of */ /* A are not referenced, but are assumed to be unity. */ /* Unchanged on exit. */ /* X - COMPLEX array of dimension at least */ /* ( 1 + ( n - 1 )*abs( INCX ) ). */ /* Before entry, the incremented array X must contain the n */ /* element vector x. On exit, X is overwritten with the */ /* tranformed vector x. */ /* INCX - INTEGER. */ /* On entry, INCX specifies the increment for the elements of */ /* X. INCX must not be zero. */ /* Unchanged on exit. */ /* Level 2 Blas routine. */ /* -- Written on 22-October-1986. */ /* Jack Dongarra, Argonne National Lab. */ /* Jeremy Du Croz, Nag Central Office. */ /* Sven Hammarling, Nag Central Office. */ /* Richard Hanson, Sandia National Labs. */ /* .. Parameters .. */ /* .. Local Scalars .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. */ /* .. Executable Statements .. */ /* Test the input parameters. */ /* Parameter adjustments */ --x; --ap; /* Function Body */ info = 0; if (! PASTEF770(lsame)(uplo, "U", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(uplo, "L", ( ftnlen)1, (ftnlen)1)) { info = 1; } else if (! PASTEF770(lsame)(trans, "N", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(trans, "T", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(trans, "C", (ftnlen)1, ( ftnlen)1)) { info = 2; } else if (! PASTEF770(lsame)(diag, "U", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(diag, "N", (ftnlen)1, (ftnlen)1)) { info = 3; } else if (*n < 0) { info = 4; } else if (*incx == 0) { info = 7; } if (info != 0) { PASTEF770(xerbla)("CTPMV ", &info, (ftnlen)6); return 0; } /* Quick return if possible. */ if (*n == 0) { return 0; } noconj = PASTEF770(lsame)(trans, "T", (ftnlen)1, (ftnlen)1); nounit = PASTEF770(lsame)(diag, "N", (ftnlen)1, (ftnlen)1); /* Set up the start point in X if the increment is not unity. This */ /* will be ( N - 1 )*INCX too small for descending loops. */ if (*incx <= 0) { kx = 1 - (*n - 1) * *incx; } else if (*incx != 1) { kx = 1; } /* Start the operations. In this version the elements of AP are */ /* accessed sequentially with one pass through AP. */ if (PASTEF770(lsame)(trans, "N", (ftnlen)1, (ftnlen)1)) { /* Form x:= A*x. */ if (PASTEF770(lsame)(uplo, "U", (ftnlen)1, (ftnlen)1)) { kk = 1; if (*incx == 1) { i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = j; if (bli_creal(x[i__2]) != 0.f || bli_cimag(x[i__2]) != 0.f) { i__2 = j; bli_csets( (bli_creal(x[i__2])), (bli_cimag(x[i__2])), temp ); k = kk; i__2 = j - 1; for (i__ = 1; i__ <= i__2; ++i__) { i__3 = i__; i__4 = i__; i__5 = k; bli_csets( (bli_creal(temp) * bli_creal(ap[i__5]) - bli_cimag(temp) * bli_cimag(ap[i__5])), (bli_creal(temp) * bli_cimag(ap[i__5]) + bli_cimag(temp) * bli_creal(ap[i__5])), q__2 ); bli_csets( (bli_creal(x[i__4]) + bli_creal(q__2)), (bli_cimag(x[i__4]) + bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), x[i__3] ); ++k; /* L10: */ } if (nounit) { i__2 = j; i__3 = j; i__4 = kk + j - 1; bli_csets( (bli_creal(x[i__3]) * bli_creal(ap[i__4]) - bli_cimag(x[i__3]) * bli_cimag(ap[i__4])), (bli_creal(x[i__3]) * bli_cimag(ap[i__4]) + bli_cimag(x[i__3]) * bli_creal(ap[i__4])), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), x[i__2] ); } } kk += j; /* L20: */ } } else { jx = kx; i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = jx; if (bli_creal(x[i__2]) != 0.f || bli_cimag(x[i__2]) != 0.f) { i__2 = jx; bli_csets( (bli_creal(x[i__2])), (bli_cimag(x[i__2])), temp ); ix = kx; i__2 = kk + j - 2; for (k = kk; k <= i__2; ++k) { i__3 = ix; i__4 = ix; i__5 = k; bli_csets( (bli_creal(temp) * bli_creal(ap[i__5]) - bli_cimag(temp) * bli_cimag(ap[i__5])), (bli_creal(temp) * bli_cimag(ap[i__5]) + bli_cimag(temp) * bli_creal(ap[i__5])), q__2 ); bli_csets( (bli_creal(x[i__4]) + bli_creal(q__2)), (bli_cimag(x[i__4]) + bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), x[i__3] ); ix += *incx; /* L30: */ } if (nounit) { i__2 = jx; i__3 = jx; i__4 = kk + j - 1; bli_csets( (bli_creal(x[i__3]) * bli_creal(ap[i__4]) - bli_cimag(x[i__3]) * bli_cimag(ap[i__4])), (bli_creal(x[i__3]) * bli_cimag(ap[i__4]) + bli_cimag(x[i__3]) * bli_creal(ap[i__4])), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), x[i__2] ); } } jx += *incx; kk += j; /* L40: */ } } } else { kk = *n * (*n + 1) / 2; if (*incx == 1) { for (j = *n; j >= 1; --j) { i__1 = j; if (bli_creal(x[i__1]) != 0.f || bli_cimag(x[i__1]) != 0.f) { i__1 = j; bli_csets( (bli_creal(x[i__1])), (bli_cimag(x[i__1])), temp ); k = kk; i__1 = j + 1; for (i__ = *n; i__ >= i__1; --i__) { i__2 = i__; i__3 = i__; i__4 = k; bli_csets( (bli_creal(temp) * bli_creal(ap[i__4]) - bli_cimag(temp) * bli_cimag(ap[i__4])), (bli_creal(temp) * bli_cimag(ap[i__4]) + bli_cimag(temp) * bli_creal(ap[i__4])), q__2 ); bli_csets( (bli_creal(x[i__3]) + bli_creal(q__2)), (bli_cimag(x[i__3]) + bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), x[i__2] ); --k; /* L50: */ } if (nounit) { i__1 = j; i__2 = j; i__3 = kk - *n + j; bli_csets( (bli_creal(x[i__2]) * bli_creal(ap[i__3]) - bli_cimag(x[i__2]) * bli_cimag(ap[i__3])), (bli_creal(x[i__2]) * bli_cimag(ap[i__3]) + bli_cimag(x[i__2]) * bli_creal(ap[i__3])), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), x[i__1] ); } } kk -= *n - j + 1; /* L60: */ } } else { kx += (*n - 1) * *incx; jx = kx; for (j = *n; j >= 1; --j) { i__1 = jx; if (bli_creal(x[i__1]) != 0.f || bli_cimag(x[i__1]) != 0.f) { i__1 = jx; bli_csets( (bli_creal(x[i__1])), (bli_cimag(x[i__1])), temp ); ix = kx; i__1 = kk - (*n - (j + 1)); for (k = kk; k >= i__1; --k) { i__2 = ix; i__3 = ix; i__4 = k; bli_csets( (bli_creal(temp) * bli_creal(ap[i__4]) - bli_cimag(temp) * bli_cimag(ap[i__4])), (bli_creal(temp) * bli_cimag(ap[i__4]) + bli_cimag(temp) * bli_creal(ap[i__4])), q__2 ); bli_csets( (bli_creal(x[i__3]) + bli_creal(q__2)), (bli_cimag(x[i__3]) + bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), x[i__2] ); ix -= *incx; /* L70: */ } if (nounit) { i__1 = jx; i__2 = jx; i__3 = kk - *n + j; bli_csets( (bli_creal(x[i__2]) * bli_creal(ap[i__3]) - bli_cimag(x[i__2]) * bli_cimag(ap[i__3])), (bli_creal(x[i__2]) * bli_cimag(ap[i__3]) + bli_cimag(x[i__2]) * bli_creal(ap[i__3])), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), x[i__1] ); } } jx -= *incx; kk -= *n - j + 1; /* L80: */ } } } } else { /* Form x := A'*x or x := conjg( A' )*x. */ if (PASTEF770(lsame)(uplo, "U", (ftnlen)1, (ftnlen)1)) { kk = *n * (*n + 1) / 2; if (*incx == 1) { for (j = *n; j >= 1; --j) { i__1 = j; bli_csets( (bli_creal(x[i__1])), (bli_cimag(x[i__1])), temp ); k = kk - 1; if (noconj) { if (nounit) { i__1 = kk; bli_csets( (bli_creal(temp) * bli_creal(ap[i__1]) - bli_cimag(temp) * bli_cimag(ap[i__1])), (bli_creal(temp) * bli_cimag(ap[i__1]) + bli_cimag(temp) * bli_creal(ap[i__1])), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp ); } for (i__ = j - 1; i__ >= 1; --i__) { i__1 = k; i__2 = i__; bli_csets( (bli_creal(ap[i__1]) * bli_creal(x[i__2]) - bli_cimag(ap[i__1]) * bli_cimag(x[i__2])), (bli_creal(ap[i__1]) * bli_cimag(x[i__2]) + bli_cimag(ap[i__1]) * bli_creal(x[i__2])), q__2 ); bli_csets( (bli_creal(temp) + bli_creal(q__2)), (bli_cimag(temp) + bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp ); --k; /* L90: */ } } else { if (nounit) { bla_r_cnjg(&q__2, &ap[kk]); bli_csets( (bli_creal(temp) * bli_creal(q__2) - bli_cimag(temp) * bli_cimag(q__2)), (bli_creal(temp) * bli_cimag(q__2) + bli_cimag(temp) * bli_creal(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp ); } for (i__ = j - 1; i__ >= 1; --i__) { bla_r_cnjg(&q__3, &ap[k]); i__1 = i__; bli_csets( (bli_creal(q__3) * bli_creal(x[i__1]) - bli_cimag(q__3) * bli_cimag(x[i__1])), (bli_creal(q__3) * bli_cimag(x[i__1]) + bli_cimag(q__3) * bli_creal(x[i__1])), q__2 ); bli_csets( (bli_creal(temp) + bli_creal(q__2)), (bli_cimag(temp) + bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp ); --k; /* L100: */ } } i__1 = j; bli_csets( (bli_creal(temp)), (bli_cimag(temp)), x[i__1] ); kk -= j; /* L110: */ } } else { jx = kx + (*n - 1) * *incx; for (j = *n; j >= 1; --j) { i__1 = jx; bli_csets( (bli_creal(x[i__1])), (bli_cimag(x[i__1])), temp ); ix = jx; if (noconj) { if (nounit) { i__1 = kk; bli_csets( (bli_creal(temp) * bli_creal(ap[i__1]) - bli_cimag(temp) * bli_cimag(ap[i__1])), (bli_creal(temp) * bli_cimag(ap[i__1]) + bli_cimag(temp) * bli_creal(ap[i__1])), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp ); } i__1 = kk - j + 1; for (k = kk - 1; k >= i__1; --k) { ix -= *incx; i__2 = k; i__3 = ix; bli_csets( (bli_creal(ap[i__2]) * bli_creal(x[i__3]) - bli_cimag(ap[i__2]) * bli_cimag(x[i__3])), (bli_creal(ap[i__2]) * bli_cimag(x[i__3]) + bli_cimag(ap[i__2]) * bli_creal(x[i__3])), q__2 ); bli_csets( (bli_creal(temp) + bli_creal(q__2)), (bli_cimag(temp) + bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp ); /* L120: */ } } else { if (nounit) { bla_r_cnjg(&q__2, &ap[kk]); bli_csets( (bli_creal(temp) * bli_creal(q__2) - bli_cimag(temp) * bli_cimag(q__2)), (bli_creal(temp) * bli_cimag(q__2) + bli_cimag(temp) * bli_creal(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp ); } i__1 = kk - j + 1; for (k = kk - 1; k >= i__1; --k) { ix -= *incx; bla_r_cnjg(&q__3, &ap[k]); i__2 = ix; bli_csets( (bli_creal(q__3) * bli_creal(x[i__2]) - bli_cimag(q__3) * bli_cimag(x[i__2])), (bli_creal(q__3) * bli_cimag(x[i__2]) + bli_cimag(q__3) * bli_creal(x[i__2])), q__2 ); bli_csets( (bli_creal(temp) + bli_creal(q__2)), (bli_cimag(temp) + bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp ); /* L130: */ } } i__1 = jx; bli_csets( (bli_creal(temp)), (bli_cimag(temp)), x[i__1] ); jx -= *incx; kk -= j; /* L140: */ } } } else { kk = 1; if (*incx == 1) { i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = j; bli_csets( (bli_creal(x[i__2])), (bli_cimag(x[i__2])), temp ); k = kk + 1; if (noconj) { if (nounit) { i__2 = kk; bli_csets( (bli_creal(temp) * bli_creal(ap[i__2]) - bli_cimag(temp) * bli_cimag(ap[i__2])), (bli_creal(temp) * bli_cimag(ap[i__2]) + bli_cimag(temp) * bli_creal(ap[i__2])), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp ); } i__2 = *n; for (i__ = j + 1; i__ <= i__2; ++i__) { i__3 = k; i__4 = i__; bli_csets( (bli_creal(ap[i__3]) * bli_creal(x[i__4]) - bli_cimag(ap[i__3]) * bli_cimag(x[i__4])), (bli_creal(ap[i__3]) * bli_cimag(x[i__4]) + bli_cimag(ap[i__3]) * bli_creal(x[i__4])), q__2 ); bli_csets( (bli_creal(temp) + bli_creal(q__2)), (bli_cimag(temp) + bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp ); ++k; /* L150: */ } } else { if (nounit) { bla_r_cnjg(&q__2, &ap[kk]); bli_csets( (bli_creal(temp) * bli_creal(q__2) - bli_cimag(temp) * bli_cimag(q__2)), (bli_creal(temp) * bli_cimag(q__2) + bli_cimag(temp) * bli_creal(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp ); } i__2 = *n; for (i__ = j + 1; i__ <= i__2; ++i__) { bla_r_cnjg(&q__3, &ap[k]); i__3 = i__; bli_csets( (bli_creal(q__3) * bli_creal(x[i__3]) - bli_cimag(q__3) * bli_cimag(x[i__3])), (bli_creal(q__3) * bli_cimag(x[i__3]) + bli_cimag(q__3) * bli_creal(x[i__3])), q__2 ); bli_csets( (bli_creal(temp) + bli_creal(q__2)), (bli_cimag(temp) + bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp ); ++k; /* L160: */ } } i__2 = j; bli_csets( (bli_creal(temp)), (bli_cimag(temp)), x[i__2] ); kk += *n - j + 1; /* L170: */ } } else { jx = kx; i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = jx; bli_csets( (bli_creal(x[i__2])), (bli_cimag(x[i__2])), temp ); ix = jx; if (noconj) { if (nounit) { i__2 = kk; bli_csets( (bli_creal(temp) * bli_creal(ap[i__2]) - bli_cimag(temp) * bli_cimag(ap[i__2])), (bli_creal(temp) * bli_cimag(ap[i__2]) + bli_cimag(temp) * bli_creal(ap[i__2])), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp ); } i__2 = kk + *n - j; for (k = kk + 1; k <= i__2; ++k) { ix += *incx; i__3 = k; i__4 = ix; bli_csets( (bli_creal(ap[i__3]) * bli_creal(x[i__4]) - bli_cimag(ap[i__3]) * bli_cimag(x[i__4])), (bli_creal(ap[i__3]) * bli_cimag(x[i__4]) + bli_cimag(ap[i__3]) * bli_creal(x[i__4])), q__2 ); bli_csets( (bli_creal(temp) + bli_creal(q__2)), (bli_cimag(temp) + bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp ); /* L180: */ } } else { if (nounit) { bla_r_cnjg(&q__2, &ap[kk]); bli_csets( (bli_creal(temp) * bli_creal(q__2) - bli_cimag(temp) * bli_cimag(q__2)), (bli_creal(temp) * bli_cimag(q__2) + bli_cimag(temp) * bli_creal(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp ); } i__2 = kk + *n - j; for (k = kk + 1; k <= i__2; ++k) { ix += *incx; bla_r_cnjg(&q__3, &ap[k]); i__3 = ix; bli_csets( (bli_creal(q__3) * bli_creal(x[i__3]) - bli_cimag(q__3) * bli_cimag(x[i__3])), (bli_creal(q__3) * bli_cimag(x[i__3]) + bli_cimag(q__3) * bli_creal(x[i__3])), q__2 ); bli_csets( (bli_creal(temp) + bli_creal(q__2)), (bli_cimag(temp) + bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp ); /* L190: */ } } i__2 = jx; bli_csets( (bli_creal(temp)), (bli_cimag(temp)), x[i__2] ); jx += *incx; kk += *n - j + 1; /* L200: */ } } } } return 0; /* End of CTPMV . */ } /* ctpmv_ */ /* dtpmv.f -- translated by f2c (version 19991025). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ /* Subroutine */ int PASTEF77(d,tpmv)(const bla_character *uplo, const bla_character *trans, const bla_character *diag, const bla_integer *n, const bla_double *ap, bla_double *x, const bla_integer *incx) { /* System generated locals */ bla_integer i__1, i__2; /* Local variables */ bla_integer info; bla_double temp; bla_integer i__, j, k; //extern bla_logical PASTEF770(lsame)(bla_character *, bla_character *, ftnlen, ftnlen); bla_integer kk, ix, jx, kx = 0; //extern /* Subroutine */ int PASTEF770(xerbla)(bla_character *, bla_integer *, ftnlen); bla_logical nounit; /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* DTPMV performs one of the matrix-vector operations */ /* x := A*x, or x := A'*x, */ /* where x is an n element vector and A is an n by n unit, or non-unit, */ /* upper or lower triangular matrix, supplied in packed form. */ /* Parameters */ /* ========== */ /* UPLO - CHARACTER*1. */ /* On entry, UPLO specifies whether the matrix is an upper or */ /* lower triangular matrix as follows: */ /* UPLO = 'U' or 'u' A is an upper triangular matrix. */ /* UPLO = 'L' or 'l' A is a lower triangular matrix. */ /* Unchanged on exit. */ /* TRANS - CHARACTER*1. */ /* On entry, TRANS specifies the operation to be performed as */ /* follows: */ /* TRANS = 'N' or 'n' x := A*x. */ /* TRANS = 'T' or 't' x := A'*x. */ /* TRANS = 'C' or 'c' x := A'*x. */ /* Unchanged on exit. */ /* DIAG - CHARACTER*1. */ /* On entry, DIAG specifies whether or not A is unit */ /* triangular as follows: */ /* DIAG = 'U' or 'u' A is assumed to be unit triangular. */ /* DIAG = 'N' or 'n' A is not assumed to be unit */ /* triangular. */ /* Unchanged on exit. */ /* N - INTEGER. */ /* On entry, N specifies the order of the matrix A. */ /* N must be at least zero. */ /* Unchanged on exit. */ /* AP - DOUBLE PRECISION array of DIMENSION at least */ /* ( ( n*( n + 1 ) )/2 ). */ /* Before entry with UPLO = 'U' or 'u', the array AP must */ /* contain the upper triangular matrix packed sequentially, */ /* column by column, so that AP( 1 ) contains a( 1, 1 ), */ /* AP( 2 ) and AP( 3 ) contain a( 1, 2 ) and a( 2, 2 ) */ /* respectively, and so on. */ /* Before entry with UPLO = 'L' or 'l', the array AP must */ /* contain the lower triangular matrix packed sequentially, */ /* column by column, so that AP( 1 ) contains a( 1, 1 ), */ /* AP( 2 ) and AP( 3 ) contain a( 2, 1 ) and a( 3, 1 ) */ /* respectively, and so on. */ /* Note that when DIAG = 'U' or 'u', the diagonal elements of */ /* A are not referenced, but are assumed to be unity. */ /* Unchanged on exit. */ /* X - DOUBLE PRECISION array of dimension at least */ /* ( 1 + ( n - 1 )*abs( INCX ) ). */ /* Before entry, the incremented array X must contain the n */ /* element vector x. On exit, X is overwritten with the */ /* tranformed vector x. */ /* INCX - INTEGER. */ /* On entry, INCX specifies the increment for the elements of */ /* X. INCX must not be zero. */ /* Unchanged on exit. */ /* Level 2 Blas routine. */ /* -- Written on 22-October-1986. */ /* Jack Dongarra, Argonne National Lab. */ /* Jeremy Du Croz, Nag Central Office. */ /* Sven Hammarling, Nag Central Office. */ /* Richard Hanson, Sandia National Labs. */ /* .. Parameters .. */ /* .. Local Scalars .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. */ /* .. Executable Statements .. */ /* Test the input parameters. */ /* Parameter adjustments */ --x; --ap; /* Function Body */ info = 0; if (! PASTEF770(lsame)(uplo, "U", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(uplo, "L", ( ftnlen)1, (ftnlen)1)) { info = 1; } else if (! PASTEF770(lsame)(trans, "N", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(trans, "T", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(trans, "C", (ftnlen)1, ( ftnlen)1)) { info = 2; } else if (! PASTEF770(lsame)(diag, "U", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(diag, "N", (ftnlen)1, (ftnlen)1)) { info = 3; } else if (*n < 0) { info = 4; } else if (*incx == 0) { info = 7; } if (info != 0) { PASTEF770(xerbla)("DTPMV ", &info, (ftnlen)6); return 0; } /* Quick return if possible. */ if (*n == 0) { return 0; } nounit = PASTEF770(lsame)(diag, "N", (ftnlen)1, (ftnlen)1); /* Set up the start point in X if the increment is not unity. This */ /* will be ( N - 1 )*INCX too small for descending loops. */ if (*incx <= 0) { kx = 1 - (*n - 1) * *incx; } else if (*incx != 1) { kx = 1; } /* Start the operations. In this version the elements of AP are */ /* accessed sequentially with one pass through AP. */ if (PASTEF770(lsame)(trans, "N", (ftnlen)1, (ftnlen)1)) { /* Form x:= A*x. */ if (PASTEF770(lsame)(uplo, "U", (ftnlen)1, (ftnlen)1)) { kk = 1; if (*incx == 1) { i__1 = *n; for (j = 1; j <= i__1; ++j) { if (x[j] != 0.) { temp = x[j]; k = kk; i__2 = j - 1; for (i__ = 1; i__ <= i__2; ++i__) { x[i__] += temp * ap[k]; ++k; /* L10: */ } if (nounit) { x[j] *= ap[kk + j - 1]; } } kk += j; /* L20: */ } } else { jx = kx; i__1 = *n; for (j = 1; j <= i__1; ++j) { if (x[jx] != 0.) { temp = x[jx]; ix = kx; i__2 = kk + j - 2; for (k = kk; k <= i__2; ++k) { x[ix] += temp * ap[k]; ix += *incx; /* L30: */ } if (nounit) { x[jx] *= ap[kk + j - 1]; } } jx += *incx; kk += j; /* L40: */ } } } else { kk = *n * (*n + 1) / 2; if (*incx == 1) { for (j = *n; j >= 1; --j) { if (x[j] != 0.) { temp = x[j]; k = kk; i__1 = j + 1; for (i__ = *n; i__ >= i__1; --i__) { x[i__] += temp * ap[k]; --k; /* L50: */ } if (nounit) { x[j] *= ap[kk - *n + j]; } } kk -= *n - j + 1; /* L60: */ } } else { kx += (*n - 1) * *incx; jx = kx; for (j = *n; j >= 1; --j) { if (x[jx] != 0.) { temp = x[jx]; ix = kx; i__1 = kk - (*n - (j + 1)); for (k = kk; k >= i__1; --k) { x[ix] += temp * ap[k]; ix -= *incx; /* L70: */ } if (nounit) { x[jx] *= ap[kk - *n + j]; } } jx -= *incx; kk -= *n - j + 1; /* L80: */ } } } } else { /* Form x := A'*x. */ if (PASTEF770(lsame)(uplo, "U", (ftnlen)1, (ftnlen)1)) { kk = *n * (*n + 1) / 2; if (*incx == 1) { for (j = *n; j >= 1; --j) { temp = x[j]; if (nounit) { temp *= ap[kk]; } k = kk - 1; for (i__ = j - 1; i__ >= 1; --i__) { temp += ap[k] * x[i__]; --k; /* L90: */ } x[j] = temp; kk -= j; /* L100: */ } } else { jx = kx + (*n - 1) * *incx; for (j = *n; j >= 1; --j) { temp = x[jx]; ix = jx; if (nounit) { temp *= ap[kk]; } i__1 = kk - j + 1; for (k = kk - 1; k >= i__1; --k) { ix -= *incx; temp += ap[k] * x[ix]; /* L110: */ } x[jx] = temp; jx -= *incx; kk -= j; /* L120: */ } } } else { kk = 1; if (*incx == 1) { i__1 = *n; for (j = 1; j <= i__1; ++j) { temp = x[j]; if (nounit) { temp *= ap[kk]; } k = kk + 1; i__2 = *n; for (i__ = j + 1; i__ <= i__2; ++i__) { temp += ap[k] * x[i__]; ++k; /* L130: */ } x[j] = temp; kk += *n - j + 1; /* L140: */ } } else { jx = kx; i__1 = *n; for (j = 1; j <= i__1; ++j) { temp = x[jx]; ix = jx; if (nounit) { temp *= ap[kk]; } i__2 = kk + *n - j; for (k = kk + 1; k <= i__2; ++k) { ix += *incx; temp += ap[k] * x[ix]; /* L150: */ } x[jx] = temp; jx += *incx; kk += *n - j + 1; /* L160: */ } } } } return 0; /* End of DTPMV . */ } /* dtpmv_ */ /* stpmv.f -- translated by f2c (version 19991025). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ /* Subroutine */ int PASTEF77(s,tpmv)(const bla_character *uplo, const bla_character *trans, const bla_character *diag, const bla_integer *n, const bla_real *ap, bla_real *x, const bla_integer *incx) { /* System generated locals */ bla_integer i__1, i__2; /* Local variables */ bla_integer info; bla_real temp; bla_integer i__, j, k; //extern bla_logical PASTEF770(lsame)(bla_character *, bla_character *, ftnlen, ftnlen); bla_integer kk, ix, jx, kx = 0; //extern /* Subroutine */ int PASTEF770(xerbla)(bla_character *, bla_integer *, ftnlen); bla_logical nounit; /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* STPMV performs one of the matrix-vector operations */ /* x := A*x, or x := A'*x, */ /* where x is an n element vector and A is an n by n unit, or non-unit, */ /* upper or lower triangular matrix, supplied in packed form. */ /* Parameters */ /* ========== */ /* UPLO - CHARACTER*1. */ /* On entry, UPLO specifies whether the matrix is an upper or */ /* lower triangular matrix as follows: */ /* UPLO = 'U' or 'u' A is an upper triangular matrix. */ /* UPLO = 'L' or 'l' A is a lower triangular matrix. */ /* Unchanged on exit. */ /* TRANS - CHARACTER*1. */ /* On entry, TRANS specifies the operation to be performed as */ /* follows: */ /* TRANS = 'N' or 'n' x := A*x. */ /* TRANS = 'T' or 't' x := A'*x. */ /* TRANS = 'C' or 'c' x := A'*x. */ /* Unchanged on exit. */ /* DIAG - CHARACTER*1. */ /* On entry, DIAG specifies whether or not A is unit */ /* triangular as follows: */ /* DIAG = 'U' or 'u' A is assumed to be unit triangular. */ /* DIAG = 'N' or 'n' A is not assumed to be unit */ /* triangular. */ /* Unchanged on exit. */ /* N - INTEGER. */ /* On entry, N specifies the order of the matrix A. */ /* N must be at least zero. */ /* Unchanged on exit. */ /* AP - REAL array of DIMENSION at least */ /* ( ( n*( n + 1 ) )/2 ). */ /* Before entry with UPLO = 'U' or 'u', the array AP must */ /* contain the upper triangular matrix packed sequentially, */ /* column by column, so that AP( 1 ) contains a( 1, 1 ), */ /* AP( 2 ) and AP( 3 ) contain a( 1, 2 ) and a( 2, 2 ) */ /* respectively, and so on. */ /* Before entry with UPLO = 'L' or 'l', the array AP must */ /* contain the lower triangular matrix packed sequentially, */ /* column by column, so that AP( 1 ) contains a( 1, 1 ), */ /* AP( 2 ) and AP( 3 ) contain a( 2, 1 ) and a( 3, 1 ) */ /* respectively, and so on. */ /* Note that when DIAG = 'U' or 'u', the diagonal elements of */ /* A are not referenced, but are assumed to be unity. */ /* Unchanged on exit. */ /* X - REAL array of dimension at least */ /* ( 1 + ( n - 1 )*abs( INCX ) ). */ /* Before entry, the incremented array X must contain the n */ /* element vector x. On exit, X is overwritten with the */ /* tranformed vector x. */ /* INCX - INTEGER. */ /* On entry, INCX specifies the increment for the elements of */ /* X. INCX must not be zero. */ /* Unchanged on exit. */ /* Level 2 Blas routine. */ /* -- Written on 22-October-1986. */ /* Jack Dongarra, Argonne National Lab. */ /* Jeremy Du Croz, Nag Central Office. */ /* Sven Hammarling, Nag Central Office. */ /* Richard Hanson, Sandia National Labs. */ /* .. Parameters .. */ /* .. Local Scalars .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. */ /* .. Executable Statements .. */ /* Test the input parameters. */ /* Parameter adjustments */ --x; --ap; /* Function Body */ info = 0; if (! PASTEF770(lsame)(uplo, "U", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(uplo, "L", ( ftnlen)1, (ftnlen)1)) { info = 1; } else if (! PASTEF770(lsame)(trans, "N", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(trans, "T", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(trans, "C", (ftnlen)1, ( ftnlen)1)) { info = 2; } else if (! PASTEF770(lsame)(diag, "U", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(diag, "N", (ftnlen)1, (ftnlen)1)) { info = 3; } else if (*n < 0) { info = 4; } else if (*incx == 0) { info = 7; } if (info != 0) { PASTEF770(xerbla)("STPMV ", &info, (ftnlen)6); return 0; } /* Quick return if possible. */ if (*n == 0) { return 0; } nounit = PASTEF770(lsame)(diag, "N", (ftnlen)1, (ftnlen)1); /* Set up the start point in X if the increment is not unity. This */ /* will be ( N - 1 )*INCX too small for descending loops. */ if (*incx <= 0) { kx = 1 - (*n - 1) * *incx; } else if (*incx != 1) { kx = 1; } /* Start the operations. In this version the elements of AP are */ /* accessed sequentially with one pass through AP. */ if (PASTEF770(lsame)(trans, "N", (ftnlen)1, (ftnlen)1)) { /* Form x:= A*x. */ if (PASTEF770(lsame)(uplo, "U", (ftnlen)1, (ftnlen)1)) { kk = 1; if (*incx == 1) { i__1 = *n; for (j = 1; j <= i__1; ++j) { if (x[j] != 0.f) { temp = x[j]; k = kk; i__2 = j - 1; for (i__ = 1; i__ <= i__2; ++i__) { x[i__] += temp * ap[k]; ++k; /* L10: */ } if (nounit) { x[j] *= ap[kk + j - 1]; } } kk += j; /* L20: */ } } else { jx = kx; i__1 = *n; for (j = 1; j <= i__1; ++j) { if (x[jx] != 0.f) { temp = x[jx]; ix = kx; i__2 = kk + j - 2; for (k = kk; k <= i__2; ++k) { x[ix] += temp * ap[k]; ix += *incx; /* L30: */ } if (nounit) { x[jx] *= ap[kk + j - 1]; } } jx += *incx; kk += j; /* L40: */ } } } else { kk = *n * (*n + 1) / 2; if (*incx == 1) { for (j = *n; j >= 1; --j) { if (x[j] != 0.f) { temp = x[j]; k = kk; i__1 = j + 1; for (i__ = *n; i__ >= i__1; --i__) { x[i__] += temp * ap[k]; --k; /* L50: */ } if (nounit) { x[j] *= ap[kk - *n + j]; } } kk -= *n - j + 1; /* L60: */ } } else { kx += (*n - 1) * *incx; jx = kx; for (j = *n; j >= 1; --j) { if (x[jx] != 0.f) { temp = x[jx]; ix = kx; i__1 = kk - (*n - (j + 1)); for (k = kk; k >= i__1; --k) { x[ix] += temp * ap[k]; ix -= *incx; /* L70: */ } if (nounit) { x[jx] *= ap[kk - *n + j]; } } jx -= *incx; kk -= *n - j + 1; /* L80: */ } } } } else { /* Form x := A'*x. */ if (PASTEF770(lsame)(uplo, "U", (ftnlen)1, (ftnlen)1)) { kk = *n * (*n + 1) / 2; if (*incx == 1) { for (j = *n; j >= 1; --j) { temp = x[j]; if (nounit) { temp *= ap[kk]; } k = kk - 1; for (i__ = j - 1; i__ >= 1; --i__) { temp += ap[k] * x[i__]; --k; /* L90: */ } x[j] = temp; kk -= j; /* L100: */ } } else { jx = kx + (*n - 1) * *incx; for (j = *n; j >= 1; --j) { temp = x[jx]; ix = jx; if (nounit) { temp *= ap[kk]; } i__1 = kk - j + 1; for (k = kk - 1; k >= i__1; --k) { ix -= *incx; temp += ap[k] * x[ix]; /* L110: */ } x[jx] = temp; jx -= *incx; kk -= j; /* L120: */ } } } else { kk = 1; if (*incx == 1) { i__1 = *n; for (j = 1; j <= i__1; ++j) { temp = x[j]; if (nounit) { temp *= ap[kk]; } k = kk + 1; i__2 = *n; for (i__ = j + 1; i__ <= i__2; ++i__) { temp += ap[k] * x[i__]; ++k; /* L130: */ } x[j] = temp; kk += *n - j + 1; /* L140: */ } } else { jx = kx; i__1 = *n; for (j = 1; j <= i__1; ++j) { temp = x[jx]; ix = jx; if (nounit) { temp *= ap[kk]; } i__2 = kk + *n - j; for (k = kk + 1; k <= i__2; ++k) { ix += *incx; temp += ap[k] * x[ix]; /* L150: */ } x[jx] = temp; jx += *incx; kk += *n - j + 1; /* L160: */ } } } } return 0; /* End of STPMV . */ } /* stpmv_ */ /* ztpmv.f -- translated by f2c (version 19991025). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ /* Subroutine */ int PASTEF77(z,tpmv)(const bla_character *uplo, const bla_character *trans, const bla_character *diag, const bla_integer *n, const bla_dcomplex *ap, bla_dcomplex *x, const bla_integer *incx) { /* System generated locals */ bla_integer i__1, i__2, i__3, i__4, i__5; bla_dcomplex z__1, z__2, z__3; /* Builtin functions */ //void bla_d_cnjg(bla_dcomplex *, bla_dcomplex *); /* Local variables */ bla_integer info; bla_dcomplex temp; bla_integer i__, j, k; //extern bla_logical PASTEF770(lsame)(bla_character *, bla_character *, ftnlen, ftnlen); bla_integer kk, ix, jx, kx = 0; //extern /* Subroutine */ int PASTEF770(xerbla)(bla_character *, bla_integer *, ftnlen); bla_logical noconj, nounit; /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* ZTPMV performs one of the matrix-vector operations */ /* x := A*x, or x := A'*x, or x := conjg( A' )*x, */ /* where x is an n element vector and A is an n by n unit, or non-unit, */ /* upper or lower triangular matrix, supplied in packed form. */ /* Parameters */ /* ========== */ /* UPLO - CHARACTER*1. */ /* On entry, UPLO specifies whether the matrix is an upper or */ /* lower triangular matrix as follows: */ /* UPLO = 'U' or 'u' A is an upper triangular matrix. */ /* UPLO = 'L' or 'l' A is a lower triangular matrix. */ /* Unchanged on exit. */ /* TRANS - CHARACTER*1. */ /* On entry, TRANS specifies the operation to be performed as */ /* follows: */ /* TRANS = 'N' or 'n' x := A*x. */ /* TRANS = 'T' or 't' x := A'*x. */ /* TRANS = 'C' or 'c' x := conjg( A' )*x. */ /* Unchanged on exit. */ /* DIAG - CHARACTER*1. */ /* On entry, DIAG specifies whether or not A is unit */ /* triangular as follows: */ /* DIAG = 'U' or 'u' A is assumed to be unit triangular. */ /* DIAG = 'N' or 'n' A is not assumed to be unit */ /* triangular. */ /* Unchanged on exit. */ /* N - INTEGER. */ /* On entry, N specifies the order of the matrix A. */ /* N must be at least zero. */ /* Unchanged on exit. */ /* AP - COMPLEX*16 array of DIMENSION at least */ /* ( ( n*( n + 1 ) )/2 ). */ /* Before entry with UPLO = 'U' or 'u', the array AP must */ /* contain the upper triangular matrix packed sequentially, */ /* column by column, so that AP( 1 ) contains a( 1, 1 ), */ /* AP( 2 ) and AP( 3 ) contain a( 1, 2 ) and a( 2, 2 ) */ /* respectively, and so on. */ /* Before entry with UPLO = 'L' or 'l', the array AP must */ /* contain the lower triangular matrix packed sequentially, */ /* column by column, so that AP( 1 ) contains a( 1, 1 ), */ /* AP( 2 ) and AP( 3 ) contain a( 2, 1 ) and a( 3, 1 ) */ /* respectively, and so on. */ /* Note that when DIAG = 'U' or 'u', the diagonal elements of */ /* A are not referenced, but are assumed to be unity. */ /* Unchanged on exit. */ /* X - COMPLEX*16 array of dimension at least */ /* ( 1 + ( n - 1 )*abs( INCX ) ). */ /* Before entry, the incremented array X must contain the n */ /* element vector x. On exit, X is overwritten with the */ /* tranformed vector x. */ /* INCX - INTEGER. */ /* On entry, INCX specifies the increment for the elements of */ /* X. INCX must not be zero. */ /* Unchanged on exit. */ /* Level 2 Blas routine. */ /* -- Written on 22-October-1986. */ /* Jack Dongarra, Argonne National Lab. */ /* Jeremy Du Croz, Nag Central Office. */ /* Sven Hammarling, Nag Central Office. */ /* Richard Hanson, Sandia National Labs. */ /* .. Parameters .. */ /* .. Local Scalars .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. */ /* .. Executable Statements .. */ /* Test the input parameters. */ /* Parameter adjustments */ --x; --ap; /* Function Body */ info = 0; if (! PASTEF770(lsame)(uplo, "U", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(uplo, "L", ( ftnlen)1, (ftnlen)1)) { info = 1; } else if (! PASTEF770(lsame)(trans, "N", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(trans, "T", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(trans, "C", (ftnlen)1, ( ftnlen)1)) { info = 2; } else if (! PASTEF770(lsame)(diag, "U", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(diag, "N", (ftnlen)1, (ftnlen)1)) { info = 3; } else if (*n < 0) { info = 4; } else if (*incx == 0) { info = 7; } if (info != 0) { PASTEF770(xerbla)("ZTPMV ", &info, (ftnlen)6); return 0; } /* Quick return if possible. */ if (*n == 0) { return 0; } noconj = PASTEF770(lsame)(trans, "T", (ftnlen)1, (ftnlen)1); nounit = PASTEF770(lsame)(diag, "N", (ftnlen)1, (ftnlen)1); /* Set up the start point in X if the increment is not unity. This */ /* will be ( N - 1 )*INCX too small for descending loops. */ if (*incx <= 0) { kx = 1 - (*n - 1) * *incx; } else if (*incx != 1) { kx = 1; } /* Start the operations. In this version the elements of AP are */ /* accessed sequentially with one pass through AP. */ if (PASTEF770(lsame)(trans, "N", (ftnlen)1, (ftnlen)1)) { /* Form x:= A*x. */ if (PASTEF770(lsame)(uplo, "U", (ftnlen)1, (ftnlen)1)) { kk = 1; if (*incx == 1) { i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = j; if (bli_zreal(x[i__2]) != 0. || bli_zimag(x[i__2]) != 0.) { i__2 = j; bli_zsets( (bli_zreal(x[i__2])), (bli_zimag(x[i__2])), temp ); k = kk; i__2 = j - 1; for (i__ = 1; i__ <= i__2; ++i__) { i__3 = i__; i__4 = i__; i__5 = k; bli_zsets( (bli_zreal(temp) * bli_zreal(ap[i__5]) - bli_zimag(temp) * bli_zimag(ap[i__5])), (bli_zreal(temp) * bli_zimag(ap[i__5]) + bli_zimag(temp) * bli_zreal(ap[i__5])), z__2 ); bli_zsets( (bli_zreal(x[i__4]) + bli_zreal(z__2)), (bli_zimag(x[i__4]) + bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), x[i__3] ); ++k; /* L10: */ } if (nounit) { i__2 = j; i__3 = j; i__4 = kk + j - 1; bli_zsets( (bli_zreal(x[i__3]) * bli_zreal(ap[i__4]) - bli_zimag(x[i__3]) * bli_zimag(ap[i__4])), (bli_zreal(x[i__3]) * bli_zimag(ap[i__4]) + bli_zimag(x[i__3]) * bli_zreal(ap[i__4])), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), x[i__2] ); } } kk += j; /* L20: */ } } else { jx = kx; i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = jx; if (bli_zreal(x[i__2]) != 0. || bli_zimag(x[i__2]) != 0.) { i__2 = jx; bli_zsets( (bli_zreal(x[i__2])), (bli_zimag(x[i__2])), temp ); ix = kx; i__2 = kk + j - 2; for (k = kk; k <= i__2; ++k) { i__3 = ix; i__4 = ix; i__5 = k; bli_zsets( (bli_zreal(temp) * bli_zreal(ap[i__5]) - bli_zimag(temp) * bli_zimag(ap[i__5])), (bli_zreal(temp) * bli_zimag(ap[i__5]) + bli_zimag(temp) * bli_zreal(ap[i__5])), z__2 ); bli_zsets( (bli_zreal(x[i__4]) + bli_zreal(z__2)), (bli_zimag(x[i__4]) + bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), x[i__3] ); ix += *incx; /* L30: */ } if (nounit) { i__2 = jx; i__3 = jx; i__4 = kk + j - 1; bli_zsets( (bli_zreal(x[i__3]) * bli_zreal(ap[i__4]) - bli_zimag(x[i__3]) * bli_zimag(ap[i__4])), (bli_zreal(x[i__3]) * bli_zimag(ap[i__4]) + bli_zimag(x[i__3]) * bli_zreal(ap[i__4])), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), x[i__2] ); } } jx += *incx; kk += j; /* L40: */ } } } else { kk = *n * (*n + 1) / 2; if (*incx == 1) { for (j = *n; j >= 1; --j) { i__1 = j; if (bli_zreal(x[i__1]) != 0. || bli_zimag(x[i__1]) != 0.) { i__1 = j; bli_zsets( (bli_zreal(x[i__1])), (bli_zimag(x[i__1])), temp ); k = kk; i__1 = j + 1; for (i__ = *n; i__ >= i__1; --i__) { i__2 = i__; i__3 = i__; i__4 = k; bli_zsets( (bli_zreal(temp) * bli_zreal(ap[i__4]) - bli_zimag(temp) * bli_zimag(ap[i__4])), (bli_zreal(temp) * bli_zimag(ap[i__4]) + bli_zimag(temp) * bli_zreal(ap[i__4])), z__2 ); bli_zsets( (bli_zreal(x[i__3]) + bli_zreal(z__2)), (bli_zimag(x[i__3]) + bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), x[i__2] ); --k; /* L50: */ } if (nounit) { i__1 = j; i__2 = j; i__3 = kk - *n + j; bli_zsets( (bli_zreal(x[i__2]) * bli_zreal(ap[i__3]) - bli_zimag(x[i__2]) * bli_zimag(ap[i__3])), (bli_zreal(x[i__2]) * bli_zimag(ap[i__3]) + bli_zimag(x[i__2]) * bli_zreal(ap[i__3])), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), x[i__1] ); } } kk -= *n - j + 1; /* L60: */ } } else { kx += (*n - 1) * *incx; jx = kx; for (j = *n; j >= 1; --j) { i__1 = jx; if (bli_zreal(x[i__1]) != 0. || bli_zimag(x[i__1]) != 0.) { i__1 = jx; bli_zsets( (bli_zreal(x[i__1])), (bli_zimag(x[i__1])), temp ); ix = kx; i__1 = kk - (*n - (j + 1)); for (k = kk; k >= i__1; --k) { i__2 = ix; i__3 = ix; i__4 = k; bli_zsets( (bli_zreal(temp) * bli_zreal(ap[i__4]) - bli_zimag(temp) * bli_zimag(ap[i__4])), (bli_zreal(temp) * bli_zimag(ap[i__4]) + bli_zimag(temp) * bli_zreal(ap[i__4])), z__2 ); bli_zsets( (bli_zreal(x[i__3]) + bli_zreal(z__2)), (bli_zimag(x[i__3]) + bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), x[i__2] ); ix -= *incx; /* L70: */ } if (nounit) { i__1 = jx; i__2 = jx; i__3 = kk - *n + j; bli_zsets( (bli_zreal(x[i__2]) * bli_zreal(ap[i__3]) - bli_zimag(x[i__2]) * bli_zimag(ap[i__3])), (bli_zreal(x[i__2]) * bli_zimag(ap[i__3]) + bli_zimag(x[i__2]) * bli_zreal(ap[i__3])), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), x[i__1] ); } } jx -= *incx; kk -= *n - j + 1; /* L80: */ } } } } else { /* Form x := A'*x or x := conjg( A' )*x. */ if (PASTEF770(lsame)(uplo, "U", (ftnlen)1, (ftnlen)1)) { kk = *n * (*n + 1) / 2; if (*incx == 1) { for (j = *n; j >= 1; --j) { i__1 = j; bli_zsets( (bli_zreal(x[i__1])), (bli_zimag(x[i__1])), temp ); k = kk - 1; if (noconj) { if (nounit) { i__1 = kk; bli_zsets( (bli_zreal(temp) * bli_zreal(ap[i__1]) - bli_zimag(temp) * bli_zimag(ap[i__1])), (bli_zreal(temp) * bli_zimag(ap[i__1]) + bli_zimag(temp) * bli_zreal(ap[i__1])), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp ); } for (i__ = j - 1; i__ >= 1; --i__) { i__1 = k; i__2 = i__; bli_zsets( (bli_zreal(ap[i__1]) * bli_zreal(x[i__2]) - bli_zimag(ap[i__1]) * bli_zimag(x[i__2])), (bli_zreal(ap[i__1]) * bli_zimag(x[i__2]) + bli_zimag(ap[i__1]) * bli_zreal(x[i__2])), z__2 ); bli_zsets( (bli_zreal(temp) + bli_zreal(z__2)), (bli_zimag(temp) + bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp ); --k; /* L90: */ } } else { if (nounit) { bla_d_cnjg(&z__2, &ap[kk]); bli_zsets( (bli_zreal(temp) * bli_zreal(z__2) - bli_zimag(temp) * bli_zimag(z__2)), (bli_zreal(temp) * bli_zimag(z__2) + bli_zimag(temp) * bli_zreal(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp ); } for (i__ = j - 1; i__ >= 1; --i__) { bla_d_cnjg(&z__3, &ap[k]); i__1 = i__; bli_zsets( (bli_zreal(z__3) * bli_zreal(x[i__1]) - bli_zimag(z__3) * bli_zimag(x[i__1])), (bli_zreal(z__3) * bli_zimag(x[i__1]) + bli_zimag(z__3) * bli_zreal(x[i__1])), z__2 ); bli_zsets( (bli_zreal(temp) + bli_zreal(z__2)), (bli_zimag(temp) + bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp ); --k; /* L100: */ } } i__1 = j; bli_zsets( (bli_zreal(temp)), (bli_zimag(temp)), x[i__1] ); kk -= j; /* L110: */ } } else { jx = kx + (*n - 1) * *incx; for (j = *n; j >= 1; --j) { i__1 = jx; bli_zsets( (bli_zreal(x[i__1])), (bli_zimag(x[i__1])), temp ); ix = jx; if (noconj) { if (nounit) { i__1 = kk; bli_zsets( (bli_zreal(temp) * bli_zreal(ap[i__1]) - bli_zimag(temp) * bli_zimag(ap[i__1])), (bli_zreal(temp) * bli_zimag(ap[i__1]) + bli_zimag(temp) * bli_zreal(ap[i__1])), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp ); } i__1 = kk - j + 1; for (k = kk - 1; k >= i__1; --k) { ix -= *incx; i__2 = k; i__3 = ix; bli_zsets( (bli_zreal(ap[i__2]) * bli_zreal(x[i__3]) - bli_zimag(ap[i__2]) * bli_zimag(x[i__3])), (bli_zreal(ap[i__2]) * bli_zimag(x[i__3]) + bli_zimag(ap[i__2]) * bli_zreal(x[i__3])), z__2 ); bli_zsets( (bli_zreal(temp) + bli_zreal(z__2)), (bli_zimag(temp) + bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp ); /* L120: */ } } else { if (nounit) { bla_d_cnjg(&z__2, &ap[kk]); bli_zsets( (bli_zreal(temp) * bli_zreal(z__2) - bli_zimag(temp) * bli_zimag(z__2)), (bli_zreal(temp) * bli_zimag(z__2) + bli_zimag(temp) * bli_zreal(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp ); } i__1 = kk - j + 1; for (k = kk - 1; k >= i__1; --k) { ix -= *incx; bla_d_cnjg(&z__3, &ap[k]); i__2 = ix; bli_zsets( (bli_zreal(z__3) * bli_zreal(x[i__2]) - bli_zimag(z__3) * bli_zimag(x[i__2])), (bli_zreal(z__3) * bli_zimag(x[i__2]) + bli_zimag(z__3) * bli_zreal(x[i__2])), z__2 ); bli_zsets( (bli_zreal(temp) + bli_zreal(z__2)), (bli_zimag(temp) + bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp ); /* L130: */ } } i__1 = jx; bli_zsets( (bli_zreal(temp)), (bli_zimag(temp)), x[i__1] ); jx -= *incx; kk -= j; /* L140: */ } } } else { kk = 1; if (*incx == 1) { i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = j; bli_zsets( (bli_zreal(x[i__2])), (bli_zimag(x[i__2])), temp ); k = kk + 1; if (noconj) { if (nounit) { i__2 = kk; bli_zsets( (bli_zreal(temp) * bli_zreal(ap[i__2]) - bli_zimag(temp) * bli_zimag(ap[i__2])), (bli_zreal(temp) * bli_zimag(ap[i__2]) + bli_zimag(temp) * bli_zreal(ap[i__2])), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp ); } i__2 = *n; for (i__ = j + 1; i__ <= i__2; ++i__) { i__3 = k; i__4 = i__; bli_zsets( (bli_zreal(ap[i__3]) * bli_zreal(x[i__4]) - bli_zimag(ap[i__3]) * bli_zimag(x[i__4])), (bli_zreal(ap[i__3]) * bli_zimag(x[i__4]) + bli_zimag(ap[i__3]) * bli_zreal(x[i__4])), z__2 ); bli_zsets( (bli_zreal(temp) + bli_zreal(z__2)), (bli_zimag(temp) + bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp ); ++k; /* L150: */ } } else { if (nounit) { bla_d_cnjg(&z__2, &ap[kk]); bli_zsets( (bli_zreal(temp) * bli_zreal(z__2) - bli_zimag(temp) * bli_zimag(z__2)), (bli_zreal(temp) * bli_zimag(z__2) + bli_zimag(temp) * bli_zreal(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp ); } i__2 = *n; for (i__ = j + 1; i__ <= i__2; ++i__) { bla_d_cnjg(&z__3, &ap[k]); i__3 = i__; bli_zsets( (bli_zreal(z__3) * bli_zreal(x[i__3]) - bli_zimag(z__3) * bli_zimag(x[i__3])), (bli_zreal(z__3) * bli_zimag(x[i__3]) + bli_zimag(z__3) * bli_zreal(x[i__3])), z__2 ); bli_zsets( (bli_zreal(temp) + bli_zreal(z__2)), (bli_zimag(temp) + bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp ); ++k; /* L160: */ } } i__2 = j; bli_zsets( (bli_zreal(temp)), (bli_zimag(temp)), x[i__2] ); kk += *n - j + 1; /* L170: */ } } else { jx = kx; i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = jx; bli_zsets( (bli_zreal(x[i__2])), (bli_zimag(x[i__2])), temp ); ix = jx; if (noconj) { if (nounit) { i__2 = kk; bli_zsets( (bli_zreal(temp) * bli_zreal(ap[i__2]) - bli_zimag(temp) * bli_zimag(ap[i__2])), (bli_zreal(temp) * bli_zimag(ap[i__2]) + bli_zimag(temp) * bli_zreal(ap[i__2])), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp ); } i__2 = kk + *n - j; for (k = kk + 1; k <= i__2; ++k) { ix += *incx; i__3 = k; i__4 = ix; bli_zsets( (bli_zreal(ap[i__3]) * bli_zreal(x[i__4]) - bli_zimag(ap[i__3]) * bli_zimag(x[i__4])), (bli_zreal(ap[i__3]) * bli_zimag(x[i__4]) + bli_zimag(ap[i__3]) * bli_zreal(x[i__4])), z__2 ); bli_zsets( (bli_zreal(temp) + bli_zreal(z__2)), (bli_zimag(temp) + bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp ); /* L180: */ } } else { if (nounit) { bla_d_cnjg(&z__2, &ap[kk]); bli_zsets( (bli_zreal(temp) * bli_zreal(z__2) - bli_zimag(temp) * bli_zimag(z__2)), (bli_zreal(temp) * bli_zimag(z__2) + bli_zimag(temp) * bli_zreal(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp ); } i__2 = kk + *n - j; for (k = kk + 1; k <= i__2; ++k) { ix += *incx; bla_d_cnjg(&z__3, &ap[k]); i__3 = ix; bli_zsets( (bli_zreal(z__3) * bli_zreal(x[i__3]) - bli_zimag(z__3) * bli_zimag(x[i__3])), (bli_zreal(z__3) * bli_zimag(x[i__3]) + bli_zimag(z__3) * bli_zreal(x[i__3])), z__2 ); bli_zsets( (bli_zreal(temp) + bli_zreal(z__2)), (bli_zimag(temp) + bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp ); /* L190: */ } } i__2 = jx; bli_zsets( (bli_zreal(temp)), (bli_zimag(temp)), x[i__2] ); jx += *incx; kk += *n - j + 1; /* L200: */ } } } } return 0; /* End of ZTPMV . */ } /* ztpmv_ */ #endif blis-0.9.0/frame/compat/f2c/bla_tpmv.h000066400000000000000000000047421422157504600174720ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifdef BLIS_ENABLE_BLAS BLIS_EXPORT_BLAS int PASTEF77(c,tpmv)(const bla_character *uplo, const bla_character *trans, const bla_character *diag, const bla_integer *n, const bla_scomplex *ap, bla_scomplex *x, const bla_integer *incx); BLIS_EXPORT_BLAS int PASTEF77(d,tpmv)(const bla_character *uplo, const bla_character *trans, const bla_character *diag, const bla_integer *n, const bla_double *ap, bla_double *x, const bla_integer *incx); BLIS_EXPORT_BLAS int PASTEF77(s,tpmv)(const bla_character *uplo, const bla_character *trans, const bla_character *diag, const bla_integer *n, const bla_real *ap, bla_real *x, const bla_integer *incx); BLIS_EXPORT_BLAS int PASTEF77(z,tpmv)(const bla_character *uplo, const bla_character *trans, const bla_character *diag, const bla_integer *n, const bla_dcomplex *ap, bla_dcomplex *x, const bla_integer *incx); #endif blis-0.9.0/frame/compat/f2c/bla_tpsv.c000066400000000000000000001471011422157504600174700ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #ifdef BLIS_ENABLE_BLAS /* ctpsv.f -- translated by f2c (version 19991025). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ /* Subroutine */ int PASTEF77(c,tpsv)(const bla_character *uplo, const bla_character *trans, const bla_character *diag, const bla_integer *n, const bla_scomplex *ap, bla_scomplex *x, const bla_integer *incx) { /* System generated locals */ bla_integer i__1, i__2, i__3, i__4, i__5; bla_scomplex q__1, q__2, q__3; /* Builtin functions */ //void bla_c_div(bla_scomplex *, bla_scomplex *, bla_scomplex *), bla_r_cnjg(bla_scomplex *, bla_scomplex *); /* Local variables */ bla_integer info; bla_scomplex temp; bla_integer i__, j, k; //extern bla_logical PASTEF770(lsame)(bla_character *, bla_character *, ftnlen, ftnlen); bla_integer kk, ix, jx, kx = 0; //extern /* Subroutine */ int PASTEF770(xerbla)(bla_character *, bla_integer *, ftnlen); bla_logical noconj, nounit; /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* CTPSV solves one of the systems of equations */ /* A*x = b, or A'*x = b, or conjg( A' )*x = b, */ /* where b and x are n element vectors and A is an n by n unit, or */ /* non-unit, upper or lower triangular matrix, supplied in packed form. */ /* No test for singularity or near-singularity is included in this */ /* routine. Such tests must be performed before calling this routine. */ /* Parameters */ /* ========== */ /* UPLO - CHARACTER*1. */ /* On entry, UPLO specifies whether the matrix is an upper or */ /* lower triangular matrix as follows: */ /* UPLO = 'U' or 'u' A is an upper triangular matrix. */ /* UPLO = 'L' or 'l' A is a lower triangular matrix. */ /* Unchanged on exit. */ /* TRANS - CHARACTER*1. */ /* On entry, TRANS specifies the equations to be solved as */ /* follows: */ /* TRANS = 'N' or 'n' A*x = b. */ /* TRANS = 'T' or 't' A'*x = b. */ /* TRANS = 'C' or 'c' conjg( A' )*x = b. */ /* Unchanged on exit. */ /* DIAG - CHARACTER*1. */ /* On entry, DIAG specifies whether or not A is unit */ /* triangular as follows: */ /* DIAG = 'U' or 'u' A is assumed to be unit triangular. */ /* DIAG = 'N' or 'n' A is not assumed to be unit */ /* triangular. */ /* Unchanged on exit. */ /* N - INTEGER. */ /* On entry, N specifies the order of the matrix A. */ /* N must be at least zero. */ /* Unchanged on exit. */ /* AP - COMPLEX array of DIMENSION at least */ /* ( ( n*( n + 1 ) )/2 ). */ /* Before entry with UPLO = 'U' or 'u', the array AP must */ /* contain the upper triangular matrix packed sequentially, */ /* column by column, so that AP( 1 ) contains a( 1, 1 ), */ /* AP( 2 ) and AP( 3 ) contain a( 1, 2 ) and a( 2, 2 ) */ /* respectively, and so on. */ /* Before entry with UPLO = 'L' or 'l', the array AP must */ /* contain the lower triangular matrix packed sequentially, */ /* column by column, so that AP( 1 ) contains a( 1, 1 ), */ /* AP( 2 ) and AP( 3 ) contain a( 2, 1 ) and a( 3, 1 ) */ /* respectively, and so on. */ /* Note that when DIAG = 'U' or 'u', the diagonal elements of */ /* A are not referenced, but are assumed to be unity. */ /* Unchanged on exit. */ /* X - COMPLEX array of dimension at least */ /* ( 1 + ( n - 1 )*abs( INCX ) ). */ /* Before entry, the incremented array X must contain the n */ /* element right-hand side vector b. On exit, X is overwritten */ /* with the solution vector x. */ /* INCX - INTEGER. */ /* On entry, INCX specifies the increment for the elements of */ /* X. INCX must not be zero. */ /* Unchanged on exit. */ /* Level 2 Blas routine. */ /* -- Written on 22-October-1986. */ /* Jack Dongarra, Argonne National Lab. */ /* Jeremy Du Croz, Nag Central Office. */ /* Sven Hammarling, Nag Central Office. */ /* Richard Hanson, Sandia National Labs. */ /* .. Parameters .. */ /* .. Local Scalars .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. */ /* .. Executable Statements .. */ /* Test the input parameters. */ /* Parameter adjustments */ --x; --ap; /* Function Body */ info = 0; if (! PASTEF770(lsame)(uplo, "U", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(uplo, "L", ( ftnlen)1, (ftnlen)1)) { info = 1; } else if (! PASTEF770(lsame)(trans, "N", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(trans, "T", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(trans, "C", (ftnlen)1, ( ftnlen)1)) { info = 2; } else if (! PASTEF770(lsame)(diag, "U", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(diag, "N", (ftnlen)1, (ftnlen)1)) { info = 3; } else if (*n < 0) { info = 4; } else if (*incx == 0) { info = 7; } if (info != 0) { PASTEF770(xerbla)("CTPSV ", &info, (ftnlen)6); return 0; } /* Quick return if possible. */ if (*n == 0) { return 0; } noconj = PASTEF770(lsame)(trans, "T", (ftnlen)1, (ftnlen)1); nounit = PASTEF770(lsame)(diag, "N", (ftnlen)1, (ftnlen)1); /* Set up the start point in X if the increment is not unity. This */ /* will be ( N - 1 )*INCX too small for descending loops. */ if (*incx <= 0) { kx = 1 - (*n - 1) * *incx; } else if (*incx != 1) { kx = 1; } /* Start the operations. In this version the elements of AP are */ /* accessed sequentially with one pass through AP. */ if (PASTEF770(lsame)(trans, "N", (ftnlen)1, (ftnlen)1)) { /* Form x := inv( A )*x. */ if (PASTEF770(lsame)(uplo, "U", (ftnlen)1, (ftnlen)1)) { kk = *n * (*n + 1) / 2; if (*incx == 1) { for (j = *n; j >= 1; --j) { i__1 = j; if (bli_creal(x[i__1]) != 0.f || bli_cimag(x[i__1]) != 0.f) { if (nounit) { i__1 = j; bla_c_div(&q__1, &x[j], &ap[kk]); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), x[i__1] ); } i__1 = j; bli_csets( (bli_creal(x[i__1])), (bli_cimag(x[i__1])), temp ); k = kk - 1; for (i__ = j - 1; i__ >= 1; --i__) { i__1 = i__; i__2 = i__; i__3 = k; bli_csets( (bli_creal(temp) * bli_creal(ap[i__3]) - bli_cimag(temp) * bli_cimag(ap[i__3])), (bli_creal(temp) * bli_cimag(ap[i__3]) + bli_cimag(temp) * bli_creal(ap[i__3])), q__2 ); bli_csets( (bli_creal(x[i__2]) - bli_creal(q__2)), (bli_cimag(x[i__2]) - bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), x[i__1] ); --k; /* L10: */ } } kk -= j; /* L20: */ } } else { jx = kx + (*n - 1) * *incx; for (j = *n; j >= 1; --j) { i__1 = jx; if (bli_creal(x[i__1]) != 0.f || bli_cimag(x[i__1]) != 0.f) { if (nounit) { i__1 = jx; bla_c_div(&q__1, &x[jx], &ap[kk]); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), x[i__1] ); } i__1 = jx; bli_csets( (bli_creal(x[i__1])), (bli_cimag(x[i__1])), temp ); ix = jx; i__1 = kk - j + 1; for (k = kk - 1; k >= i__1; --k) { ix -= *incx; i__2 = ix; i__3 = ix; i__4 = k; bli_csets( (bli_creal(temp) * bli_creal(ap[i__4]) - bli_cimag(temp) * bli_cimag(ap[i__4])), (bli_creal(temp) * bli_cimag(ap[i__4]) + bli_cimag(temp) * bli_creal(ap[i__4])), q__2 ); bli_csets( (bli_creal(x[i__3]) - bli_creal(q__2)), (bli_cimag(x[i__3]) - bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), x[i__2] ); /* L30: */ } } jx -= *incx; kk -= j; /* L40: */ } } } else { kk = 1; if (*incx == 1) { i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = j; if (bli_creal(x[i__2]) != 0.f || bli_cimag(x[i__2]) != 0.f) { if (nounit) { i__2 = j; bla_c_div(&q__1, &x[j], &ap[kk]); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), x[i__2] ); } i__2 = j; bli_csets( (bli_creal(x[i__2])), (bli_cimag(x[i__2])), temp ); k = kk + 1; i__2 = *n; for (i__ = j + 1; i__ <= i__2; ++i__) { i__3 = i__; i__4 = i__; i__5 = k; bli_csets( (bli_creal(temp) * bli_creal(ap[i__5]) - bli_cimag(temp) * bli_cimag(ap[i__5])), (bli_creal(temp) * bli_cimag(ap[i__5]) + bli_cimag(temp) * bli_creal(ap[i__5])), q__2 ); bli_csets( (bli_creal(x[i__4]) - bli_creal(q__2)), (bli_cimag(x[i__4]) - bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), x[i__3] ); ++k; /* L50: */ } } kk += *n - j + 1; /* L60: */ } } else { jx = kx; i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = jx; if (bli_creal(x[i__2]) != 0.f || bli_cimag(x[i__2]) != 0.f) { if (nounit) { i__2 = jx; bla_c_div(&q__1, &x[jx], &ap[kk]); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), x[i__2] ); } i__2 = jx; bli_csets( (bli_creal(x[i__2])), (bli_cimag(x[i__2])), temp ); ix = jx; i__2 = kk + *n - j; for (k = kk + 1; k <= i__2; ++k) { ix += *incx; i__3 = ix; i__4 = ix; i__5 = k; bli_csets( (bli_creal(temp) * bli_creal(ap[i__5]) - bli_cimag(temp) * bli_cimag(ap[i__5])), (bli_creal(temp) * bli_cimag(ap[i__5]) + bli_cimag(temp) * bli_creal(ap[i__5])), q__2 ); bli_csets( (bli_creal(x[i__4]) - bli_creal(q__2)), (bli_cimag(x[i__4]) - bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), x[i__3] ); /* L70: */ } } jx += *incx; kk += *n - j + 1; /* L80: */ } } } } else { /* Form x := inv( A' )*x or x := inv( conjg( A' ) )*x. */ if (PASTEF770(lsame)(uplo, "U", (ftnlen)1, (ftnlen)1)) { kk = 1; if (*incx == 1) { i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = j; bli_csets( (bli_creal(x[i__2])), (bli_cimag(x[i__2])), temp ); k = kk; if (noconj) { i__2 = j - 1; for (i__ = 1; i__ <= i__2; ++i__) { i__3 = k; i__4 = i__; bli_csets( (bli_creal(ap[i__3]) * bli_creal(x[i__4]) - bli_cimag(ap[i__3]) * bli_cimag(x[i__4])), (bli_creal(ap[i__3]) * bli_cimag(x[i__4]) + bli_cimag(ap[i__3]) * bli_creal(x[i__4])), q__2 ); bli_csets( (bli_creal(temp) - bli_creal(q__2)), (bli_cimag(temp) - bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp ); ++k; /* L90: */ } if (nounit) { bla_c_div(&q__1, &temp, &ap[kk + j - 1]); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp ); } } else { i__2 = j - 1; for (i__ = 1; i__ <= i__2; ++i__) { bla_r_cnjg(&q__3, &ap[k]); i__3 = i__; bli_csets( (bli_creal(q__3) * bli_creal(x[i__3]) - bli_cimag(q__3) * bli_cimag(x[i__3])), (bli_creal(q__3) * bli_cimag(x[i__3]) + bli_cimag(q__3) * bli_creal(x[i__3])), q__2 ); bli_csets( (bli_creal(temp) - bli_creal(q__2)), (bli_cimag(temp) - bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp ); ++k; /* L100: */ } if (nounit) { bla_r_cnjg(&q__2, &ap[kk + j - 1]); bla_c_div(&q__1, &temp, &q__2); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp ); } } i__2 = j; bli_csets( (bli_creal(temp)), (bli_cimag(temp)), x[i__2] ); kk += j; /* L110: */ } } else { jx = kx; i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = jx; bli_csets( (bli_creal(x[i__2])), (bli_cimag(x[i__2])), temp ); ix = kx; if (noconj) { i__2 = kk + j - 2; for (k = kk; k <= i__2; ++k) { i__3 = k; i__4 = ix; bli_csets( (bli_creal(ap[i__3]) * bli_creal(x[i__4]) - bli_cimag(ap[i__3]) * bli_cimag(x[i__4])), (bli_creal(ap[i__3]) * bli_cimag(x[i__4]) + bli_cimag(ap[i__3]) * bli_creal(x[i__4])), q__2 ); bli_csets( (bli_creal(temp) - bli_creal(q__2)), (bli_cimag(temp) - bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp ); ix += *incx; /* L120: */ } if (nounit) { bla_c_div(&q__1, &temp, &ap[kk + j - 1]); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp ); } } else { i__2 = kk + j - 2; for (k = kk; k <= i__2; ++k) { bla_r_cnjg(&q__3, &ap[k]); i__3 = ix; bli_csets( (bli_creal(q__3) * bli_creal(x[i__3]) - bli_cimag(q__3) * bli_cimag(x[i__3])), (bli_creal(q__3) * bli_cimag(x[i__3]) + bli_cimag(q__3) * bli_creal(x[i__3])), q__2 ); bli_csets( (bli_creal(temp) - bli_creal(q__2)), (bli_cimag(temp) - bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp ); ix += *incx; /* L130: */ } if (nounit) { bla_r_cnjg(&q__2, &ap[kk + j - 1]); bla_c_div(&q__1, &temp, &q__2); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp ); } } i__2 = jx; bli_csets( (bli_creal(temp)), (bli_cimag(temp)), x[i__2] ); jx += *incx; kk += j; /* L140: */ } } } else { kk = *n * (*n + 1) / 2; if (*incx == 1) { for (j = *n; j >= 1; --j) { i__1 = j; bli_csets( (bli_creal(x[i__1])), (bli_cimag(x[i__1])), temp ); k = kk; if (noconj) { i__1 = j + 1; for (i__ = *n; i__ >= i__1; --i__) { i__2 = k; i__3 = i__; bli_csets( (bli_creal(ap[i__2]) * bli_creal(x[i__3]) - bli_cimag(ap[i__2]) * bli_cimag(x[i__3])), (bli_creal(ap[i__2]) * bli_cimag(x[i__3]) + bli_cimag(ap[i__2]) * bli_creal(x[i__3])), q__2 ); bli_csets( (bli_creal(temp) - bli_creal(q__2)), (bli_cimag(temp) - bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp ); --k; /* L150: */ } if (nounit) { bla_c_div(&q__1, &temp, &ap[kk - *n + j]); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp ); } } else { i__1 = j + 1; for (i__ = *n; i__ >= i__1; --i__) { bla_r_cnjg(&q__3, &ap[k]); i__2 = i__; bli_csets( (bli_creal(q__3) * bli_creal(x[i__2]) - bli_cimag(q__3) * bli_cimag(x[i__2])), (bli_creal(q__3) * bli_cimag(x[i__2]) + bli_cimag(q__3) * bli_creal(x[i__2])), q__2 ); bli_csets( (bli_creal(temp) - bli_creal(q__2)), (bli_cimag(temp) - bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp ); --k; /* L160: */ } if (nounit) { bla_r_cnjg(&q__2, &ap[kk - *n + j]); bla_c_div(&q__1, &temp, &q__2); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp ); } } i__1 = j; bli_csets( (bli_creal(temp)), (bli_cimag(temp)), x[i__1] ); kk -= *n - j + 1; /* L170: */ } } else { kx += (*n - 1) * *incx; jx = kx; for (j = *n; j >= 1; --j) { i__1 = jx; bli_csets( (bli_creal(x[i__1])), (bli_cimag(x[i__1])), temp ); ix = kx; if (noconj) { i__1 = kk - (*n - (j + 1)); for (k = kk; k >= i__1; --k) { i__2 = k; i__3 = ix; bli_csets( (bli_creal(ap[i__2]) * bli_creal(x[i__3]) - bli_cimag(ap[i__2]) * bli_cimag(x[i__3])), (bli_creal(ap[i__2]) * bli_cimag(x[i__3]) + bli_cimag(ap[i__2]) * bli_creal(x[i__3])), q__2 ); bli_csets( (bli_creal(temp) - bli_creal(q__2)), (bli_cimag(temp) - bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp ); ix -= *incx; /* L180: */ } if (nounit) { bla_c_div(&q__1, &temp, &ap[kk - *n + j]); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp ); } } else { i__1 = kk - (*n - (j + 1)); for (k = kk; k >= i__1; --k) { bla_r_cnjg(&q__3, &ap[k]); i__2 = ix; bli_csets( (bli_creal(q__3) * bli_creal(x[i__2]) - bli_cimag(q__3) * bli_cimag(x[i__2])), (bli_creal(q__3) * bli_cimag(x[i__2]) + bli_cimag(q__3) * bli_creal(x[i__2])), q__2 ); bli_csets( (bli_creal(temp) - bli_creal(q__2)), (bli_cimag(temp) - bli_cimag(q__2)), q__1 ); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp ); ix -= *incx; /* L190: */ } if (nounit) { bla_r_cnjg(&q__2, &ap[kk - *n + j]); bla_c_div(&q__1, &temp, &q__2); bli_csets( (bli_creal(q__1)), (bli_cimag(q__1)), temp ); } } i__1 = jx; bli_csets( (bli_creal(temp)), (bli_cimag(temp)), x[i__1] ); jx -= *incx; kk -= *n - j + 1; /* L200: */ } } } } return 0; /* End of CTPSV . */ } /* ctpsv_ */ /* dtpsv.f -- translated by f2c (version 19991025). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ /* Subroutine */ int PASTEF77(d,tpsv)(const bla_character *uplo, const bla_character *trans, const bla_character *diag, const bla_integer *n, const bla_double *ap, bla_double *x, const bla_integer *incx) { /* System generated locals */ bla_integer i__1, i__2; /* Local variables */ bla_integer info; bla_double temp; bla_integer i__, j, k; //extern bla_logical PASTEF770(lsame)(bla_character *, bla_character *, ftnlen, ftnlen); bla_integer kk, ix, jx, kx = 0; //extern /* Subroutine */ int PASTEF770(xerbla)(bla_character *, bla_integer *, ftnlen); bla_logical nounit; /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* DTPSV solves one of the systems of equations */ /* A*x = b, or A'*x = b, */ /* where b and x are n element vectors and A is an n by n unit, or */ /* non-unit, upper or lower triangular matrix, supplied in packed form. */ /* No test for singularity or near-singularity is included in this */ /* routine. Such tests must be performed before calling this routine. */ /* Parameters */ /* ========== */ /* UPLO - CHARACTER*1. */ /* On entry, UPLO specifies whether the matrix is an upper or */ /* lower triangular matrix as follows: */ /* UPLO = 'U' or 'u' A is an upper triangular matrix. */ /* UPLO = 'L' or 'l' A is a lower triangular matrix. */ /* Unchanged on exit. */ /* TRANS - CHARACTER*1. */ /* On entry, TRANS specifies the equations to be solved as */ /* follows: */ /* TRANS = 'N' or 'n' A*x = b. */ /* TRANS = 'T' or 't' A'*x = b. */ /* TRANS = 'C' or 'c' A'*x = b. */ /* Unchanged on exit. */ /* DIAG - CHARACTER*1. */ /* On entry, DIAG specifies whether or not A is unit */ /* triangular as follows: */ /* DIAG = 'U' or 'u' A is assumed to be unit triangular. */ /* DIAG = 'N' or 'n' A is not assumed to be unit */ /* triangular. */ /* Unchanged on exit. */ /* N - INTEGER. */ /* On entry, N specifies the order of the matrix A. */ /* N must be at least zero. */ /* Unchanged on exit. */ /* AP - DOUBLE PRECISION array of DIMENSION at least */ /* ( ( n*( n + 1 ) )/2 ). */ /* Before entry with UPLO = 'U' or 'u', the array AP must */ /* contain the upper triangular matrix packed sequentially, */ /* column by column, so that AP( 1 ) contains a( 1, 1 ), */ /* AP( 2 ) and AP( 3 ) contain a( 1, 2 ) and a( 2, 2 ) */ /* respectively, and so on. */ /* Before entry with UPLO = 'L' or 'l', the array AP must */ /* contain the lower triangular matrix packed sequentially, */ /* column by column, so that AP( 1 ) contains a( 1, 1 ), */ /* AP( 2 ) and AP( 3 ) contain a( 2, 1 ) and a( 3, 1 ) */ /* respectively, and so on. */ /* Note that when DIAG = 'U' or 'u', the diagonal elements of */ /* A are not referenced, but are assumed to be unity. */ /* Unchanged on exit. */ /* X - DOUBLE PRECISION array of dimension at least */ /* ( 1 + ( n - 1 )*abs( INCX ) ). */ /* Before entry, the incremented array X must contain the n */ /* element right-hand side vector b. On exit, X is overwritten */ /* with the solution vector x. */ /* INCX - INTEGER. */ /* On entry, INCX specifies the increment for the elements of */ /* X. INCX must not be zero. */ /* Unchanged on exit. */ /* Level 2 Blas routine. */ /* -- Written on 22-October-1986. */ /* Jack Dongarra, Argonne National Lab. */ /* Jeremy Du Croz, Nag Central Office. */ /* Sven Hammarling, Nag Central Office. */ /* Richard Hanson, Sandia National Labs. */ /* .. Parameters .. */ /* .. Local Scalars .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. */ /* .. Executable Statements .. */ /* Test the input parameters. */ /* Parameter adjustments */ --x; --ap; /* Function Body */ info = 0; if (! PASTEF770(lsame)(uplo, "U", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(uplo, "L", ( ftnlen)1, (ftnlen)1)) { info = 1; } else if (! PASTEF770(lsame)(trans, "N", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(trans, "T", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(trans, "C", (ftnlen)1, ( ftnlen)1)) { info = 2; } else if (! PASTEF770(lsame)(diag, "U", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(diag, "N", (ftnlen)1, (ftnlen)1)) { info = 3; } else if (*n < 0) { info = 4; } else if (*incx == 0) { info = 7; } if (info != 0) { PASTEF770(xerbla)("DTPSV ", &info, (ftnlen)6); return 0; } /* Quick return if possible. */ if (*n == 0) { return 0; } nounit = PASTEF770(lsame)(diag, "N", (ftnlen)1, (ftnlen)1); /* Set up the start point in X if the increment is not unity. This */ /* will be ( N - 1 )*INCX too small for descending loops. */ if (*incx <= 0) { kx = 1 - (*n - 1) * *incx; } else if (*incx != 1) { kx = 1; } /* Start the operations. In this version the elements of AP are */ /* accessed sequentially with one pass through AP. */ if (PASTEF770(lsame)(trans, "N", (ftnlen)1, (ftnlen)1)) { /* Form x := inv( A )*x. */ if (PASTEF770(lsame)(uplo, "U", (ftnlen)1, (ftnlen)1)) { kk = *n * (*n + 1) / 2; if (*incx == 1) { for (j = *n; j >= 1; --j) { if (x[j] != 0.) { if (nounit) { x[j] /= ap[kk]; } temp = x[j]; k = kk - 1; for (i__ = j - 1; i__ >= 1; --i__) { x[i__] -= temp * ap[k]; --k; /* L10: */ } } kk -= j; /* L20: */ } } else { jx = kx + (*n - 1) * *incx; for (j = *n; j >= 1; --j) { if (x[jx] != 0.) { if (nounit) { x[jx] /= ap[kk]; } temp = x[jx]; ix = jx; i__1 = kk - j + 1; for (k = kk - 1; k >= i__1; --k) { ix -= *incx; x[ix] -= temp * ap[k]; /* L30: */ } } jx -= *incx; kk -= j; /* L40: */ } } } else { kk = 1; if (*incx == 1) { i__1 = *n; for (j = 1; j <= i__1; ++j) { if (x[j] != 0.) { if (nounit) { x[j] /= ap[kk]; } temp = x[j]; k = kk + 1; i__2 = *n; for (i__ = j + 1; i__ <= i__2; ++i__) { x[i__] -= temp * ap[k]; ++k; /* L50: */ } } kk += *n - j + 1; /* L60: */ } } else { jx = kx; i__1 = *n; for (j = 1; j <= i__1; ++j) { if (x[jx] != 0.) { if (nounit) { x[jx] /= ap[kk]; } temp = x[jx]; ix = jx; i__2 = kk + *n - j; for (k = kk + 1; k <= i__2; ++k) { ix += *incx; x[ix] -= temp * ap[k]; /* L70: */ } } jx += *incx; kk += *n - j + 1; /* L80: */ } } } } else { /* Form x := inv( A' )*x. */ if (PASTEF770(lsame)(uplo, "U", (ftnlen)1, (ftnlen)1)) { kk = 1; if (*incx == 1) { i__1 = *n; for (j = 1; j <= i__1; ++j) { temp = x[j]; k = kk; i__2 = j - 1; for (i__ = 1; i__ <= i__2; ++i__) { temp -= ap[k] * x[i__]; ++k; /* L90: */ } if (nounit) { temp /= ap[kk + j - 1]; } x[j] = temp; kk += j; /* L100: */ } } else { jx = kx; i__1 = *n; for (j = 1; j <= i__1; ++j) { temp = x[jx]; ix = kx; i__2 = kk + j - 2; for (k = kk; k <= i__2; ++k) { temp -= ap[k] * x[ix]; ix += *incx; /* L110: */ } if (nounit) { temp /= ap[kk + j - 1]; } x[jx] = temp; jx += *incx; kk += j; /* L120: */ } } } else { kk = *n * (*n + 1) / 2; if (*incx == 1) { for (j = *n; j >= 1; --j) { temp = x[j]; k = kk; i__1 = j + 1; for (i__ = *n; i__ >= i__1; --i__) { temp -= ap[k] * x[i__]; --k; /* L130: */ } if (nounit) { temp /= ap[kk - *n + j]; } x[j] = temp; kk -= *n - j + 1; /* L140: */ } } else { kx += (*n - 1) * *incx; jx = kx; for (j = *n; j >= 1; --j) { temp = x[jx]; ix = kx; i__1 = kk - (*n - (j + 1)); for (k = kk; k >= i__1; --k) { temp -= ap[k] * x[ix]; ix -= *incx; /* L150: */ } if (nounit) { temp /= ap[kk - *n + j]; } x[jx] = temp; jx -= *incx; kk -= *n - j + 1; /* L160: */ } } } } return 0; /* End of DTPSV . */ } /* dtpsv_ */ /* stpsv.f -- translated by f2c (version 19991025). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ /* Subroutine */ int PASTEF77(s,tpsv)(const bla_character *uplo, const bla_character *trans, const bla_character *diag, const bla_integer *n, const bla_real *ap, bla_real *x, const bla_integer *incx) { /* System generated locals */ bla_integer i__1, i__2; /* Local variables */ bla_integer info; bla_real temp; bla_integer i__, j, k; //extern bla_logical PASTEF770(lsame)(bla_character *, bla_character *, ftnlen, ftnlen); bla_integer kk, ix, jx, kx = 0; //extern /* Subroutine */ int PASTEF770(xerbla)(bla_character *, bla_integer *, ftnlen); bla_logical nounit; /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* STPSV solves one of the systems of equations */ /* A*x = b, or A'*x = b, */ /* where b and x are n element vectors and A is an n by n unit, or */ /* non-unit, upper or lower triangular matrix, supplied in packed form. */ /* No test for singularity or near-singularity is included in this */ /* routine. Such tests must be performed before calling this routine. */ /* Parameters */ /* ========== */ /* UPLO - CHARACTER*1. */ /* On entry, UPLO specifies whether the matrix is an upper or */ /* lower triangular matrix as follows: */ /* UPLO = 'U' or 'u' A is an upper triangular matrix. */ /* UPLO = 'L' or 'l' A is a lower triangular matrix. */ /* Unchanged on exit. */ /* TRANS - CHARACTER*1. */ /* On entry, TRANS specifies the equations to be solved as */ /* follows: */ /* TRANS = 'N' or 'n' A*x = b. */ /* TRANS = 'T' or 't' A'*x = b. */ /* TRANS = 'C' or 'c' A'*x = b. */ /* Unchanged on exit. */ /* DIAG - CHARACTER*1. */ /* On entry, DIAG specifies whether or not A is unit */ /* triangular as follows: */ /* DIAG = 'U' or 'u' A is assumed to be unit triangular. */ /* DIAG = 'N' or 'n' A is not assumed to be unit */ /* triangular. */ /* Unchanged on exit. */ /* N - INTEGER. */ /* On entry, N specifies the order of the matrix A. */ /* N must be at least zero. */ /* Unchanged on exit. */ /* AP - REAL array of DIMENSION at least */ /* ( ( n*( n + 1 ) )/2 ). */ /* Before entry with UPLO = 'U' or 'u', the array AP must */ /* contain the upper triangular matrix packed sequentially, */ /* column by column, so that AP( 1 ) contains a( 1, 1 ), */ /* AP( 2 ) and AP( 3 ) contain a( 1, 2 ) and a( 2, 2 ) */ /* respectively, and so on. */ /* Before entry with UPLO = 'L' or 'l', the array AP must */ /* contain the lower triangular matrix packed sequentially, */ /* column by column, so that AP( 1 ) contains a( 1, 1 ), */ /* AP( 2 ) and AP( 3 ) contain a( 2, 1 ) and a( 3, 1 ) */ /* respectively, and so on. */ /* Note that when DIAG = 'U' or 'u', the diagonal elements of */ /* A are not referenced, but are assumed to be unity. */ /* Unchanged on exit. */ /* X - REAL array of dimension at least */ /* ( 1 + ( n - 1 )*abs( INCX ) ). */ /* Before entry, the incremented array X must contain the n */ /* element right-hand side vector b. On exit, X is overwritten */ /* with the solution vector x. */ /* INCX - INTEGER. */ /* On entry, INCX specifies the increment for the elements of */ /* X. INCX must not be zero. */ /* Unchanged on exit. */ /* Level 2 Blas routine. */ /* -- Written on 22-October-1986. */ /* Jack Dongarra, Argonne National Lab. */ /* Jeremy Du Croz, Nag Central Office. */ /* Sven Hammarling, Nag Central Office. */ /* Richard Hanson, Sandia National Labs. */ /* .. Parameters .. */ /* .. Local Scalars .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. */ /* .. Executable Statements .. */ /* Test the input parameters. */ /* Parameter adjustments */ --x; --ap; /* Function Body */ info = 0; if (! PASTEF770(lsame)(uplo, "U", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(uplo, "L", ( ftnlen)1, (ftnlen)1)) { info = 1; } else if (! PASTEF770(lsame)(trans, "N", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(trans, "T", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(trans, "C", (ftnlen)1, ( ftnlen)1)) { info = 2; } else if (! PASTEF770(lsame)(diag, "U", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(diag, "N", (ftnlen)1, (ftnlen)1)) { info = 3; } else if (*n < 0) { info = 4; } else if (*incx == 0) { info = 7; } if (info != 0) { PASTEF770(xerbla)("STPSV ", &info, (ftnlen)6); return 0; } /* Quick return if possible. */ if (*n == 0) { return 0; } nounit = PASTEF770(lsame)(diag, "N", (ftnlen)1, (ftnlen)1); /* Set up the start point in X if the increment is not unity. This */ /* will be ( N - 1 )*INCX too small for descending loops. */ if (*incx <= 0) { kx = 1 - (*n - 1) * *incx; } else if (*incx != 1) { kx = 1; } /* Start the operations. In this version the elements of AP are */ /* accessed sequentially with one pass through AP. */ if (PASTEF770(lsame)(trans, "N", (ftnlen)1, (ftnlen)1)) { /* Form x := inv( A )*x. */ if (PASTEF770(lsame)(uplo, "U", (ftnlen)1, (ftnlen)1)) { kk = *n * (*n + 1) / 2; if (*incx == 1) { for (j = *n; j >= 1; --j) { if (x[j] != 0.f) { if (nounit) { x[j] /= ap[kk]; } temp = x[j]; k = kk - 1; for (i__ = j - 1; i__ >= 1; --i__) { x[i__] -= temp * ap[k]; --k; /* L10: */ } } kk -= j; /* L20: */ } } else { jx = kx + (*n - 1) * *incx; for (j = *n; j >= 1; --j) { if (x[jx] != 0.f) { if (nounit) { x[jx] /= ap[kk]; } temp = x[jx]; ix = jx; i__1 = kk - j + 1; for (k = kk - 1; k >= i__1; --k) { ix -= *incx; x[ix] -= temp * ap[k]; /* L30: */ } } jx -= *incx; kk -= j; /* L40: */ } } } else { kk = 1; if (*incx == 1) { i__1 = *n; for (j = 1; j <= i__1; ++j) { if (x[j] != 0.f) { if (nounit) { x[j] /= ap[kk]; } temp = x[j]; k = kk + 1; i__2 = *n; for (i__ = j + 1; i__ <= i__2; ++i__) { x[i__] -= temp * ap[k]; ++k; /* L50: */ } } kk += *n - j + 1; /* L60: */ } } else { jx = kx; i__1 = *n; for (j = 1; j <= i__1; ++j) { if (x[jx] != 0.f) { if (nounit) { x[jx] /= ap[kk]; } temp = x[jx]; ix = jx; i__2 = kk + *n - j; for (k = kk + 1; k <= i__2; ++k) { ix += *incx; x[ix] -= temp * ap[k]; /* L70: */ } } jx += *incx; kk += *n - j + 1; /* L80: */ } } } } else { /* Form x := inv( A' )*x. */ if (PASTEF770(lsame)(uplo, "U", (ftnlen)1, (ftnlen)1)) { kk = 1; if (*incx == 1) { i__1 = *n; for (j = 1; j <= i__1; ++j) { temp = x[j]; k = kk; i__2 = j - 1; for (i__ = 1; i__ <= i__2; ++i__) { temp -= ap[k] * x[i__]; ++k; /* L90: */ } if (nounit) { temp /= ap[kk + j - 1]; } x[j] = temp; kk += j; /* L100: */ } } else { jx = kx; i__1 = *n; for (j = 1; j <= i__1; ++j) { temp = x[jx]; ix = kx; i__2 = kk + j - 2; for (k = kk; k <= i__2; ++k) { temp -= ap[k] * x[ix]; ix += *incx; /* L110: */ } if (nounit) { temp /= ap[kk + j - 1]; } x[jx] = temp; jx += *incx; kk += j; /* L120: */ } } } else { kk = *n * (*n + 1) / 2; if (*incx == 1) { for (j = *n; j >= 1; --j) { temp = x[j]; k = kk; i__1 = j + 1; for (i__ = *n; i__ >= i__1; --i__) { temp -= ap[k] * x[i__]; --k; /* L130: */ } if (nounit) { temp /= ap[kk - *n + j]; } x[j] = temp; kk -= *n - j + 1; /* L140: */ } } else { kx += (*n - 1) * *incx; jx = kx; for (j = *n; j >= 1; --j) { temp = x[jx]; ix = kx; i__1 = kk - (*n - (j + 1)); for (k = kk; k >= i__1; --k) { temp -= ap[k] * x[ix]; ix -= *incx; /* L150: */ } if (nounit) { temp /= ap[kk - *n + j]; } x[jx] = temp; jx -= *incx; kk -= *n - j + 1; /* L160: */ } } } } return 0; /* End of STPSV . */ } /* stpsv_ */ /* ztpsv.f -- translated by f2c (version 19991025). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ /* Subroutine */ int PASTEF77(z,tpsv)(const bla_character *uplo, const bla_character *trans, const bla_character *diag, const bla_integer *n, const bla_dcomplex *ap, bla_dcomplex *x, const bla_integer *incx) { /* System generated locals */ bla_integer i__1, i__2, i__3, i__4, i__5; bla_dcomplex z__1, z__2, z__3; /* Builtin functions */ //void bla_z_div(bla_dcomplex *, bla_dcomplex *, bla_dcomplex *), bla_d_cnjg( // bla_dcomplex *, bla_dcomplex *); /* Local variables */ bla_integer info; bla_dcomplex temp; bla_integer i__, j, k; //extern bla_logical PASTEF770(lsame)(bla_character *, bla_character *, ftnlen, ftnlen); bla_integer kk, ix, jx, kx = 0; //extern /* Subroutine */ int PASTEF770(xerbla)(bla_character *, bla_integer *, ftnlen); bla_logical noconj, nounit; /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* ZTPSV solves one of the systems of equations */ /* A*x = b, or A'*x = b, or conjg( A' )*x = b, */ /* where b and x are n element vectors and A is an n by n unit, or */ /* non-unit, upper or lower triangular matrix, supplied in packed form. */ /* No test for singularity or near-singularity is included in this */ /* routine. Such tests must be performed before calling this routine. */ /* Parameters */ /* ========== */ /* UPLO - CHARACTER*1. */ /* On entry, UPLO specifies whether the matrix is an upper or */ /* lower triangular matrix as follows: */ /* UPLO = 'U' or 'u' A is an upper triangular matrix. */ /* UPLO = 'L' or 'l' A is a lower triangular matrix. */ /* Unchanged on exit. */ /* TRANS - CHARACTER*1. */ /* On entry, TRANS specifies the equations to be solved as */ /* follows: */ /* TRANS = 'N' or 'n' A*x = b. */ /* TRANS = 'T' or 't' A'*x = b. */ /* TRANS = 'C' or 'c' conjg( A' )*x = b. */ /* Unchanged on exit. */ /* DIAG - CHARACTER*1. */ /* On entry, DIAG specifies whether or not A is unit */ /* triangular as follows: */ /* DIAG = 'U' or 'u' A is assumed to be unit triangular. */ /* DIAG = 'N' or 'n' A is not assumed to be unit */ /* triangular. */ /* Unchanged on exit. */ /* N - INTEGER. */ /* On entry, N specifies the order of the matrix A. */ /* N must be at least zero. */ /* Unchanged on exit. */ /* AP - COMPLEX*16 array of DIMENSION at least */ /* ( ( n*( n + 1 ) )/2 ). */ /* Before entry with UPLO = 'U' or 'u', the array AP must */ /* contain the upper triangular matrix packed sequentially, */ /* column by column, so that AP( 1 ) contains a( 1, 1 ), */ /* AP( 2 ) and AP( 3 ) contain a( 1, 2 ) and a( 2, 2 ) */ /* respectively, and so on. */ /* Before entry with UPLO = 'L' or 'l', the array AP must */ /* contain the lower triangular matrix packed sequentially, */ /* column by column, so that AP( 1 ) contains a( 1, 1 ), */ /* AP( 2 ) and AP( 3 ) contain a( 2, 1 ) and a( 3, 1 ) */ /* respectively, and so on. */ /* Note that when DIAG = 'U' or 'u', the diagonal elements of */ /* A are not referenced, but are assumed to be unity. */ /* Unchanged on exit. */ /* X - COMPLEX*16 array of dimension at least */ /* ( 1 + ( n - 1 )*abs( INCX ) ). */ /* Before entry, the incremented array X must contain the n */ /* element right-hand side vector b. On exit, X is overwritten */ /* with the solution vector x. */ /* INCX - INTEGER. */ /* On entry, INCX specifies the increment for the elements of */ /* X. INCX must not be zero. */ /* Unchanged on exit. */ /* Level 2 Blas routine. */ /* -- Written on 22-October-1986. */ /* Jack Dongarra, Argonne National Lab. */ /* Jeremy Du Croz, Nag Central Office. */ /* Sven Hammarling, Nag Central Office. */ /* Richard Hanson, Sandia National Labs. */ /* .. Parameters .. */ /* .. Local Scalars .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. Intrinsic Functions .. */ /* .. */ /* .. Executable Statements .. */ /* Test the input parameters. */ /* Parameter adjustments */ --x; --ap; /* Function Body */ info = 0; if (! PASTEF770(lsame)(uplo, "U", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(uplo, "L", ( ftnlen)1, (ftnlen)1)) { info = 1; } else if (! PASTEF770(lsame)(trans, "N", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(trans, "T", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(trans, "C", (ftnlen)1, ( ftnlen)1)) { info = 2; } else if (! PASTEF770(lsame)(diag, "U", (ftnlen)1, (ftnlen)1) && ! PASTEF770(lsame)(diag, "N", (ftnlen)1, (ftnlen)1)) { info = 3; } else if (*n < 0) { info = 4; } else if (*incx == 0) { info = 7; } if (info != 0) { PASTEF770(xerbla)("ZTPSV ", &info, (ftnlen)6); return 0; } /* Quick return if possible. */ if (*n == 0) { return 0; } noconj = PASTEF770(lsame)(trans, "T", (ftnlen)1, (ftnlen)1); nounit = PASTEF770(lsame)(diag, "N", (ftnlen)1, (ftnlen)1); /* Set up the start point in X if the increment is not unity. This */ /* will be ( N - 1 )*INCX too small for descending loops. */ if (*incx <= 0) { kx = 1 - (*n - 1) * *incx; } else if (*incx != 1) { kx = 1; } /* Start the operations. In this version the elements of AP are */ /* accessed sequentially with one pass through AP. */ if (PASTEF770(lsame)(trans, "N", (ftnlen)1, (ftnlen)1)) { /* Form x := inv( A )*x. */ if (PASTEF770(lsame)(uplo, "U", (ftnlen)1, (ftnlen)1)) { kk = *n * (*n + 1) / 2; if (*incx == 1) { for (j = *n; j >= 1; --j) { i__1 = j; if (bli_zreal(x[i__1]) != 0. || bli_zimag(x[i__1]) != 0.) { if (nounit) { i__1 = j; bla_z_div(&z__1, &x[j], &ap[kk]); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), x[i__1] ); } i__1 = j; bli_zsets( (bli_zreal(x[i__1])), (bli_zimag(x[i__1])), temp ); k = kk - 1; for (i__ = j - 1; i__ >= 1; --i__) { i__1 = i__; i__2 = i__; i__3 = k; bli_zsets( (bli_zreal(temp) * bli_zreal(ap[i__3]) - bli_zimag(temp) * bli_zimag(ap[i__3])), (bli_zreal(temp) * bli_zimag(ap[i__3]) + bli_zimag(temp) * bli_zreal(ap[i__3])), z__2 ); bli_zsets( (bli_zreal(x[i__2]) - bli_zreal(z__2)), (bli_zimag(x[i__2]) - bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), x[i__1] ); --k; /* L10: */ } } kk -= j; /* L20: */ } } else { jx = kx + (*n - 1) * *incx; for (j = *n; j >= 1; --j) { i__1 = jx; if (bli_zreal(x[i__1]) != 0. || bli_zimag(x[i__1]) != 0.) { if (nounit) { i__1 = jx; bla_z_div(&z__1, &x[jx], &ap[kk]); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), x[i__1] ); } i__1 = jx; bli_zsets( (bli_zreal(x[i__1])), (bli_zimag(x[i__1])), temp ); ix = jx; i__1 = kk - j + 1; for (k = kk - 1; k >= i__1; --k) { ix -= *incx; i__2 = ix; i__3 = ix; i__4 = k; bli_zsets( (bli_zreal(temp) * bli_zreal(ap[i__4]) - bli_zimag(temp) * bli_zimag(ap[i__4])), (bli_zreal(temp) * bli_zimag(ap[i__4]) + bli_zimag(temp) * bli_zreal(ap[i__4])), z__2 ); bli_zsets( (bli_zreal(x[i__3]) - bli_zreal(z__2)), (bli_zimag(x[i__3]) - bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), x[i__2] ); /* L30: */ } } jx -= *incx; kk -= j; /* L40: */ } } } else { kk = 1; if (*incx == 1) { i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = j; if (bli_zreal(x[i__2]) != 0. || bli_zimag(x[i__2]) != 0.) { if (nounit) { i__2 = j; bla_z_div(&z__1, &x[j], &ap[kk]); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), x[i__2] ); } i__2 = j; bli_zsets( (bli_zreal(x[i__2])), (bli_zimag(x[i__2])), temp ); k = kk + 1; i__2 = *n; for (i__ = j + 1; i__ <= i__2; ++i__) { i__3 = i__; i__4 = i__; i__5 = k; bli_zsets( (bli_zreal(temp) * bli_zreal(ap[i__5]) - bli_zimag(temp) * bli_zimag(ap[i__5])), (bli_zreal(temp) * bli_zimag(ap[i__5]) + bli_zimag(temp) * bli_zreal(ap[i__5])), z__2 ); bli_zsets( (bli_zreal(x[i__4]) - bli_zreal(z__2)), (bli_zimag(x[i__4]) - bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), x[i__3] ); ++k; /* L50: */ } } kk += *n - j + 1; /* L60: */ } } else { jx = kx; i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = jx; if (bli_zreal(x[i__2]) != 0. || bli_zimag(x[i__2]) != 0.) { if (nounit) { i__2 = jx; bla_z_div(&z__1, &x[jx], &ap[kk]); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), x[i__2] ); } i__2 = jx; bli_zsets( (bli_zreal(x[i__2])), (bli_zimag(x[i__2])), temp ); ix = jx; i__2 = kk + *n - j; for (k = kk + 1; k <= i__2; ++k) { ix += *incx; i__3 = ix; i__4 = ix; i__5 = k; bli_zsets( (bli_zreal(temp) * bli_zreal(ap[i__5]) - bli_zimag(temp) * bli_zimag(ap[i__5])), (bli_zreal(temp) * bli_zimag(ap[i__5]) + bli_zimag(temp) * bli_zreal(ap[i__5])), z__2 ); bli_zsets( (bli_zreal(x[i__4]) - bli_zreal(z__2)), (bli_zimag(x[i__4]) - bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), x[i__3] ); /* L70: */ } } jx += *incx; kk += *n - j + 1; /* L80: */ } } } } else { /* Form x := inv( A' )*x or x := inv( conjg( A' ) )*x. */ if (PASTEF770(lsame)(uplo, "U", (ftnlen)1, (ftnlen)1)) { kk = 1; if (*incx == 1) { i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = j; bli_zsets( (bli_zreal(x[i__2])), (bli_zimag(x[i__2])), temp ); k = kk; if (noconj) { i__2 = j - 1; for (i__ = 1; i__ <= i__2; ++i__) { i__3 = k; i__4 = i__; bli_zsets( (bli_zreal(ap[i__3]) * bli_zreal(x[i__4]) - bli_zimag(ap[i__3]) * bli_zimag(x[i__4])), (bli_zreal(ap[i__3]) * bli_zimag(x[i__4]) + bli_zimag(ap[i__3]) * bli_zreal(x[i__4])), z__2 ); bli_zsets( (bli_zreal(temp) - bli_zreal(z__2)), (bli_zimag(temp) - bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp ); ++k; /* L90: */ } if (nounit) { bla_z_div(&z__1, &temp, &ap[kk + j - 1]); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp ); } } else { i__2 = j - 1; for (i__ = 1; i__ <= i__2; ++i__) { bla_d_cnjg(&z__3, &ap[k]); i__3 = i__; bli_zsets( (bli_zreal(z__3) * bli_zreal(x[i__3]) - bli_zimag(z__3) * bli_zimag(x[i__3])), (bli_zreal(z__3) * bli_zimag(x[i__3]) + bli_zimag(z__3) * bli_zreal(x[i__3])), z__2 ); bli_zsets( (bli_zreal(temp) - bli_zreal(z__2)), (bli_zimag(temp) - bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp ); ++k; /* L100: */ } if (nounit) { bla_d_cnjg(&z__2, &ap[kk + j - 1]); bla_z_div(&z__1, &temp, &z__2); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp ); } } i__2 = j; bli_zsets( (bli_zreal(temp)), (bli_zimag(temp)), x[i__2] ); kk += j; /* L110: */ } } else { jx = kx; i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = jx; bli_zsets( (bli_zreal(x[i__2])), (bli_zimag(x[i__2])), temp ); ix = kx; if (noconj) { i__2 = kk + j - 2; for (k = kk; k <= i__2; ++k) { i__3 = k; i__4 = ix; bli_zsets( (bli_zreal(ap[i__3]) * bli_zreal(x[i__4]) - bli_zimag(ap[i__3]) * bli_zimag(x[i__4])), (bli_zreal(ap[i__3]) * bli_zimag(x[i__4]) + bli_zimag(ap[i__3]) * bli_zreal(x[i__4])), z__2 ); bli_zsets( (bli_zreal(temp) - bli_zreal(z__2)), (bli_zimag(temp) - bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp ); ix += *incx; /* L120: */ } if (nounit) { bla_z_div(&z__1, &temp, &ap[kk + j - 1]); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp ); } } else { i__2 = kk + j - 2; for (k = kk; k <= i__2; ++k) { bla_d_cnjg(&z__3, &ap[k]); i__3 = ix; bli_zsets( (bli_zreal(z__3) * bli_zreal(x[i__3]) - bli_zimag(z__3) * bli_zimag(x[i__3])), (bli_zreal(z__3) * bli_zimag(x[i__3]) + bli_zimag(z__3) * bli_zreal(x[i__3])), z__2 ); bli_zsets( (bli_zreal(temp) - bli_zreal(z__2)), (bli_zimag(temp) - bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp ); ix += *incx; /* L130: */ } if (nounit) { bla_d_cnjg(&z__2, &ap[kk + j - 1]); bla_z_div(&z__1, &temp, &z__2); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp ); } } i__2 = jx; bli_zsets( (bli_zreal(temp)), (bli_zimag(temp)), x[i__2] ); jx += *incx; kk += j; /* L140: */ } } } else { kk = *n * (*n + 1) / 2; if (*incx == 1) { for (j = *n; j >= 1; --j) { i__1 = j; bli_zsets( (bli_zreal(x[i__1])), (bli_zimag(x[i__1])), temp ); k = kk; if (noconj) { i__1 = j + 1; for (i__ = *n; i__ >= i__1; --i__) { i__2 = k; i__3 = i__; bli_zsets( (bli_zreal(ap[i__2]) * bli_zreal(x[i__3]) - bli_zimag(ap[i__2]) * bli_zimag(x[i__3])), (bli_zreal(ap[i__2]) * bli_zimag(x[i__3]) + bli_zimag(ap[i__2]) * bli_zreal(x[i__3])), z__2 ); bli_zsets( (bli_zreal(temp) - bli_zreal(z__2)), (bli_zimag(temp) - bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp ); --k; /* L150: */ } if (nounit) { bla_z_div(&z__1, &temp, &ap[kk - *n + j]); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp ); } } else { i__1 = j + 1; for (i__ = *n; i__ >= i__1; --i__) { bla_d_cnjg(&z__3, &ap[k]); i__2 = i__; bli_zsets( (bli_zreal(z__3) * bli_zreal(x[i__2]) - bli_zimag(z__3) * bli_zimag(x[i__2])), (bli_zreal(z__3) * bli_zimag(x[i__2]) + bli_zimag(z__3) * bli_zreal(x[i__2])), z__2 ); bli_zsets( (bli_zreal(temp) - bli_zreal(z__2)), (bli_zimag(temp) - bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp ); --k; /* L160: */ } if (nounit) { bla_d_cnjg(&z__2, &ap[kk - *n + j]); bla_z_div(&z__1, &temp, &z__2); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp ); } } i__1 = j; bli_zsets( (bli_zreal(temp)), (bli_zimag(temp)), x[i__1] ); kk -= *n - j + 1; /* L170: */ } } else { kx += (*n - 1) * *incx; jx = kx; for (j = *n; j >= 1; --j) { i__1 = jx; bli_zsets( (bli_zreal(x[i__1])), (bli_zimag(x[i__1])), temp ); ix = kx; if (noconj) { i__1 = kk - (*n - (j + 1)); for (k = kk; k >= i__1; --k) { i__2 = k; i__3 = ix; bli_zsets( (bli_zreal(ap[i__2]) * bli_zreal(x[i__3]) - bli_zimag(ap[i__2]) * bli_zimag(x[i__3])), (bli_zreal(ap[i__2]) * bli_zimag(x[i__3]) + bli_zimag(ap[i__2]) * bli_zreal(x[i__3])), z__2 ); bli_zsets( (bli_zreal(temp) - bli_zreal(z__2)), (bli_zimag(temp) - bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp ); ix -= *incx; /* L180: */ } if (nounit) { bla_z_div(&z__1, &temp, &ap[kk - *n + j]); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp ); } } else { i__1 = kk - (*n - (j + 1)); for (k = kk; k >= i__1; --k) { bla_d_cnjg(&z__3, &ap[k]); i__2 = ix; bli_zsets( (bli_zreal(z__3) * bli_zreal(x[i__2]) - bli_zimag(z__3) * bli_zimag(x[i__2])), (bli_zreal(z__3) * bli_zimag(x[i__2]) + bli_zimag(z__3) * bli_zreal(x[i__2])), z__2 ); bli_zsets( (bli_zreal(temp) - bli_zreal(z__2)), (bli_zimag(temp) - bli_zimag(z__2)), z__1 ); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp ); ix -= *incx; /* L190: */ } if (nounit) { bla_d_cnjg(&z__2, &ap[kk - *n + j]); bla_z_div(&z__1, &temp, &z__2); bli_zsets( (bli_zreal(z__1)), (bli_zimag(z__1)), temp ); } } i__1 = jx; bli_zsets( (bli_zreal(temp)), (bli_zimag(temp)), x[i__1] ); jx -= *incx; kk -= *n - j + 1; /* L200: */ } } } } return 0; /* End of ZTPSV . */ } /* ztpsv_ */ #endif blis-0.9.0/frame/compat/f2c/bla_tpsv.h000066400000000000000000000047421422157504600175000ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifdef BLIS_ENABLE_BLAS BLIS_EXPORT_BLAS int PASTEF77(c,tpsv)(const bla_character *uplo, const bla_character *trans, const bla_character *diag, const bla_integer *n, const bla_scomplex *ap, bla_scomplex *x, const bla_integer *incx); BLIS_EXPORT_BLAS int PASTEF77(d,tpsv)(const bla_character *uplo, const bla_character *trans, const bla_character *diag, const bla_integer *n, const bla_double *ap, bla_double *x, const bla_integer *incx); BLIS_EXPORT_BLAS int PASTEF77(s,tpsv)(const bla_character *uplo, const bla_character *trans, const bla_character *diag, const bla_integer *n, const bla_real *ap, bla_real *x, const bla_integer *incx); BLIS_EXPORT_BLAS int PASTEF77(z,tpsv)(const bla_character *uplo, const bla_character *trans, const bla_character *diag, const bla_integer *n, const bla_dcomplex *ap, bla_dcomplex *x, const bla_integer *incx); #endif blis-0.9.0/frame/compat/f2c/bla_xerbla.c000066400000000000000000000062171422157504600177530ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #ifdef BLIS_ENABLE_BLAS /* xerbla.f -- translated by f2c (version 19991025). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ /* Table of constant values */ /* Subroutine */ int PASTEF770(xerbla)(const bla_character *srname, const bla_integer *info, ftnlen srname_len) { /* -- LAPACK auxiliary routine (preliminary version) -- */ /* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., */ /* Courant Institute, Argonne National Lab, and Rice University */ /* February 29, 1992 */ /* .. Scalar Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* XERBLA is an error handler for the LAPACK routines. */ /* It is called by an LAPACK routine if an input parameter has an */ /* invalid value. A message is printed and execution stops. */ /* Installers may consider modifying the STOP statement in order to */ /* call system-specific exception-handling facilities. */ /* Arguments */ /* ========= */ /* SRNAME (input) CHARACTER*6 */ /* The name of the routine which called XERBLA. */ /* INFO (input) INTEGER */ /* The position of the invalid parameter in the parameter list */ /* of the calling routine. */ //int i; //for ( i = 0; i < srname_len; ++i ) // srname[i] = toupper( srname[i] ); printf("** On entry to %6s, parameter number %2i had an illegal value\n", srname, (int)*info); //bli_abort(); /* End of XERBLA */ return 0; } /* xerbla */ #endif blis-0.9.0/frame/compat/f2c/bla_xerbla.h000066400000000000000000000034541422157504600177600ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifdef BLIS_ENABLE_BLAS BLIS_EXPORT_BLAS BLIS_OVERRIDABLE int PASTEF770(xerbla)(const bla_character *srname, const bla_integer *info, ftnlen srname_len); #endif blis-0.9.0/frame/compat/f2c/bla_xerbla_array.c000066400000000000000000000050471422157504600211510ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #ifdef BLIS_ENABLE_BLAS #define MAX_NUM_CHARS 32 int PASTEF770(xerbla_array)(const bla_character *srname_array, const bla_integer srname_len, const bla_integer *info) { int i; #if 1 // 01234567890123456789012345678901 char srname[ MAX_NUM_CHARS + 1 ] = " "; #else char srname[ MAX_NUM_CHARS + 1 ]; // Initialize srname to contain blank characters. for ( i = 0; i < MAX_NUM_CHARS; ++i ) srname[i] = ' '; #endif // Compute the number of chars to copy as the minimum of the length of // srname_array and MAX_NUM_CHARS. const int n_copy = bli_min( srname_len, MAX_NUM_CHARS ); // Copy over each element of srname_array. for ( i = 0; i < n_copy; ++i ) { srname[i] = srname_array[i]; } // NULL terminate. srname[i] = '\0'; // Call xerbla_(). PASTEF770(xerbla)( srname, info, ( ftnlen )srname_len ); return 0; } #endif blis-0.9.0/frame/compat/f2c/bla_xerbla_array.h000066400000000000000000000034541422157504600211560ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifdef BLIS_ENABLE_BLAS BLIS_EXPORT_BLAS int PASTEF770(xerbla_array)(const bla_character *srname, const bla_integer srname_len, const bla_integer *info); #endif blis-0.9.0/frame/compat/f2c/util/000077500000000000000000000000001422157504600164635ustar00rootroot00000000000000blis-0.9.0/frame/compat/f2c/util/bla_c_abs.c000066400000000000000000000034741422157504600205240ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #ifdef BLIS_ENABLE_BLAS double bla_c_abs(const bla_scomplex *z) { return( bla_f__cabs( bli_creal( *z ), bli_cimag( *z ) ) ); } #endif blis-0.9.0/frame/compat/f2c/util/bla_c_abs.h000066400000000000000000000033241422157504600205230ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifdef BLIS_ENABLE_BLAS double bla_c_abs(const bla_scomplex *z); #endif blis-0.9.0/frame/compat/f2c/util/bla_c_div.c000066400000000000000000000035101422157504600205300ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #ifdef BLIS_ENABLE_BLAS void bla_c_div(bla_scomplex *cp, const bla_scomplex *ap, const bla_scomplex *bp) { bli_ccopys( *ap, *cp ); bli_cinvscals( *bp, *cp ); } #endif blis-0.9.0/frame/compat/f2c/util/bla_c_div.h000066400000000000000000000033751422157504600205460ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifdef BLIS_ENABLE_BLAS void bla_c_div(bla_scomplex *cp, const bla_scomplex *ap, const bla_scomplex *bp); #endif blis-0.9.0/frame/compat/f2c/util/bla_d_abs.c000066400000000000000000000034251422157504600205210ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #ifdef BLIS_ENABLE_BLAS double bla_d_abs(const bla_double *x) { if(*x >= 0.0) return(*x); return(- *x); } #endif blis-0.9.0/frame/compat/f2c/util/bla_d_abs.h000066400000000000000000000033221422157504600205220ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifdef BLIS_ENABLE_BLAS double bla_d_abs(const bla_double *x); #endif blis-0.9.0/frame/compat/f2c/util/bla_d_cnjg.c000066400000000000000000000034341422157504600206750ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #ifdef BLIS_ENABLE_BLAS void bla_d_cnjg(bla_dcomplex *dest, const bla_dcomplex *src) { bli_zcopyjs( *src, *dest ); } #endif blis-0.9.0/frame/compat/f2c/util/bla_d_cnjg.h000066400000000000000000000033511422157504600207000ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifdef BLIS_ENABLE_BLAS void bla_d_cnjg(bla_dcomplex *dest, const bla_dcomplex *src); #endif blis-0.9.0/frame/compat/f2c/util/bla_d_imag.c000066400000000000000000000034041422157504600206660ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #ifdef BLIS_ENABLE_BLAS double bla_d_imag(const bla_dcomplex *z) { return bli_zimag( *z ); } #endif blis-0.9.0/frame/compat/f2c/util/bla_d_imag.h000066400000000000000000000033251422157504600206750ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifdef BLIS_ENABLE_BLAS double bla_d_imag(const bla_dcomplex *z); #endif blis-0.9.0/frame/compat/f2c/util/bla_d_sign.c000066400000000000000000000035011422157504600207070ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #ifdef BLIS_ENABLE_BLAS double bla_d_sign(const bla_double *a, const bla_double *b) { double x = (*a >= 0.0 ? *a : - *a); return(*b >= 0.0 ? x : -x); } #endif blis-0.9.0/frame/compat/f2c/util/bla_d_sign.h000066400000000000000000000033501422157504600207160ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifdef BLIS_ENABLE_BLAS double bla_d_sign(const bla_double *a, const bla_double *b); #endif blis-0.9.0/frame/compat/f2c/util/bla_f__cabs.c000066400000000000000000000041041422157504600210200ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #ifdef BLIS_ENABLE_BLAS double bla_f__cabs(double real_val, double imag_val) { double temp; if(real_val < 0) real_val = -real_val; if(imag_val < 0) imag_val = -imag_val; if(imag_val > real_val) { temp = real_val; real_val = imag_val; imag_val = temp; } if((real_val+imag_val) == real_val) return(real_val); temp = imag_val/real_val; temp = real_val*sqrt(1.0 + temp*temp); return(temp); } #endif blis-0.9.0/frame/compat/f2c/util/bla_f__cabs.h000066400000000000000000000033311422157504600210260ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifdef BLIS_ENABLE_BLAS double bla_f__cabs(double real, double imag); #endif blis-0.9.0/frame/compat/f2c/util/bla_r_abs.c000066400000000000000000000034231422157504600205350ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #ifdef BLIS_ENABLE_BLAS double bla_r_abs(const bla_real *x) { if(*x >= 0.0) return(*x); return(- *x); } #endif blis-0.9.0/frame/compat/f2c/util/bla_r_abs.h000066400000000000000000000033201422157504600205360ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifdef BLIS_ENABLE_BLAS double bla_r_abs(const bla_real *x); #endif blis-0.9.0/frame/compat/f2c/util/bla_r_cnjg.c000066400000000000000000000034341422157504600207130ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #ifdef BLIS_ENABLE_BLAS void bla_r_cnjg(bla_scomplex *dest, const bla_scomplex *src) { bli_ccopyjs( *src, *dest ); } #endif blis-0.9.0/frame/compat/f2c/util/bla_r_cnjg.h000066400000000000000000000033511422157504600207160ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifdef BLIS_ENABLE_BLAS void bla_r_cnjg(bla_scomplex *dest, const bla_scomplex *src); #endif blis-0.9.0/frame/compat/f2c/util/bla_r_imag.c000066400000000000000000000034061422157504600207060ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #ifdef BLIS_ENABLE_BLAS bla_real bla_r_imag(const bla_scomplex *z) { return bli_cimag( *z ); } #endif blis-0.9.0/frame/compat/f2c/util/bla_r_imag.h000066400000000000000000000033271422157504600207150ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifdef BLIS_ENABLE_BLAS bla_real bla_r_imag(const bla_scomplex *z); #endif blis-0.9.0/frame/compat/f2c/util/bla_r_sign.c000066400000000000000000000034751422157504600207370ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #ifdef BLIS_ENABLE_BLAS double bla_r_sign(const bla_real *a, const bla_real *b) { double x = (*a >= 0.0 ? *a : - *a); return(*b >= 0.0 ? x : -x); } #endif blis-0.9.0/frame/compat/f2c/util/bla_r_sign.h000066400000000000000000000033441422157504600207370ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifdef BLIS_ENABLE_BLAS double bla_r_sign(const bla_real *a, const bla_real *b); #endif blis-0.9.0/frame/compat/f2c/util/bla_z_abs.c000066400000000000000000000034741422157504600205530ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #ifdef BLIS_ENABLE_BLAS double bla_z_abs(const bla_dcomplex *z) { return( bla_f__cabs( bli_zreal( *z ), bli_zimag( *z ) ) ); } #endif blis-0.9.0/frame/compat/f2c/util/bla_z_abs.h000066400000000000000000000033241422157504600205520ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifdef BLIS_ENABLE_BLAS double bla_z_abs(const bla_dcomplex *z); #endif blis-0.9.0/frame/compat/f2c/util/bla_z_div.c000066400000000000000000000035101422157504600205570ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #ifdef BLIS_ENABLE_BLAS void bla_z_div(bla_dcomplex *cp, const bla_dcomplex *ap, const bla_dcomplex *bp) { bli_zcopys( *ap, *cp ); bli_zinvscals( *bp, *cp ); } #endif blis-0.9.0/frame/compat/f2c/util/bla_z_div.h000066400000000000000000000033751422157504600205750ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifdef BLIS_ENABLE_BLAS void bla_z_div(bla_dcomplex *cp, const bla_dcomplex *ap, const bla_dcomplex *bp); #endif blis-0.9.0/frame/include/000077500000000000000000000000001422157504600151745ustar00rootroot00000000000000blis-0.9.0/frame/include/bli_arch_config.h000066400000000000000000000166131422157504600204440ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2016, Hewlett Packard Enterprise Development LP Copyright (C) 2019 - 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_ARCH_CONFIG_H #define BLIS_ARCH_CONFIG_H // // -- Context initialization prototypes ---------------------------------------- // // -- Intel64 architectures -- #ifdef BLIS_CONFIG_SKX CNTX_INIT_PROTS( skx ) #endif #ifdef BLIS_CONFIG_KNL CNTX_INIT_PROTS( knl ) #endif #ifdef BLIS_CONFIG_KNC CNTX_INIT_PROTS( knc ) #endif #ifdef BLIS_CONFIG_HASWELL CNTX_INIT_PROTS( haswell ) #endif #ifdef BLIS_CONFIG_SANDYBRIDGE CNTX_INIT_PROTS( sandybridge ) #endif #ifdef BLIS_CONFIG_PENRYN CNTX_INIT_PROTS( penryn ) #endif // -- AMD64 architectures -- #ifdef BLIS_CONFIG_ZEN3 CNTX_INIT_PROTS( zen3 ) #endif #ifdef BLIS_CONFIG_ZEN2 CNTX_INIT_PROTS( zen2 ) #endif #ifdef BLIS_CONFIG_ZEN CNTX_INIT_PROTS( zen ) #endif #ifdef BLIS_CONFIG_EXCAVATOR CNTX_INIT_PROTS( excavator ) #endif #ifdef BLIS_CONFIG_STEAMROLLER CNTX_INIT_PROTS( steamroller ) #endif #ifdef BLIS_CONFIG_PILEDRIVER CNTX_INIT_PROTS( piledriver ) #endif #ifdef BLIS_CONFIG_BULLDOZER CNTX_INIT_PROTS( bulldozer ) #endif // -- ARM architectures -- #ifdef BLIS_CONFIG_ARMSVE CNTX_INIT_PROTS( armsve ) #endif #ifdef BLIS_CONFIG_A64FX CNTX_INIT_PROTS( a64fx ) #endif #ifdef BLIS_CONFIG_FIRESTORM CNTX_INIT_PROTS( firestorm ) #endif #ifdef BLIS_CONFIG_THUNDERX2 CNTX_INIT_PROTS( thunderx2 ) #endif #ifdef BLIS_CONFIG_CORTEXA57 CNTX_INIT_PROTS( cortexa57 ) #endif #ifdef BLIS_CONFIG_CORTEXA53 CNTX_INIT_PROTS( cortexa53 ) #endif #ifdef BLIS_CONFIG_CORTEXA15 CNTX_INIT_PROTS( cortexa15 ) #endif #ifdef BLIS_CONFIG_CORTEXA9 CNTX_INIT_PROTS( cortexa9 ) #endif // -- IBM Power -- #ifdef BLIS_CONFIG_POWER10 CNTX_INIT_PROTS( power10 ) #endif #ifdef BLIS_CONFIG_POWER9 CNTX_INIT_PROTS( power9 ) #endif #ifdef BLIS_CONFIG_POWER7 CNTX_INIT_PROTS( power7 ) #endif // -- IBM BG/Q -- #ifdef BLIS_CONFIG_BGQ CNTX_INIT_PROTS( bgq ) #endif // -- Generic -- #ifdef BLIS_CONFIG_GENERIC CNTX_INIT_PROTS( generic ) #endif // // -- Architecture family-specific headers ------------------------------------- // // -- x86_64 families -- #ifdef BLIS_FAMILY_INTEL64 #include "bli_family_intel64.h" #endif #ifdef BLIS_FAMILY_AMD64 #include "bli_family_amd64.h" #endif #ifdef BLIS_FAMILY_AMD64_LEGACY #include "bli_family_amd64_legacy.h" #endif #ifdef BLIS_FAMILY_X86_64 #include "bli_family_x86_64.h" #endif // -- Intel64 architectures -- #ifdef BLIS_FAMILY_SKX #include "bli_family_skx.h" #endif #ifdef BLIS_FAMILY_KNL #include "bli_family_knl.h" #endif #ifdef BLIS_FAMILY_KNC #include "bli_family_knc.h" #endif #ifdef BLIS_FAMILY_HASWELL #include "bli_family_haswell.h" #endif #ifdef BLIS_FAMILY_SANDYBRIDGE #include "bli_family_sandybridge.h" #endif #ifdef BLIS_FAMILY_PENRYN #include "bli_family_penryn.h" #endif // -- AMD64 architectures -- #ifdef BLIS_FAMILY_ZEN3 #include "bli_family_zen3.h" #endif #ifdef BLIS_FAMILY_ZEN2 #include "bli_family_zen2.h" #endif #ifdef BLIS_FAMILY_ZEN #include "bli_family_zen.h" #endif #ifdef BLIS_FAMILY_EXCAVATOR #include "bli_family_excavator.h" #endif #ifdef BLIS_FAMILY_STEAMROLLER #include "bli_family_steamroller.h" #endif #ifdef BLIS_FAMILY_PILEDRIVER #include "bli_family_piledriver.h" #endif #ifdef BLIS_FAMILY_BULLDOZER #include "bli_family_bulldozer.h" #endif // -- ARM families -- #ifdef BLIS_FAMILY_ARM64 #include "bli_family_arm64.h" #endif #ifdef BLIS_FAMILY_ARM32 #include "bli_family_arm32.h" #endif // -- ARM architectures -- #ifdef BLIS_FAMILY_ARMSVE #include "bli_family_armsve.h" #endif #ifdef BLIS_FAMILY_A64FX #include "bli_family_a64fx.h" #endif #ifdef BLIS_FAMILY_FIRESTORM #include "bli_family_firestorm.h" #endif #ifdef BLIS_FAMILY_THUNDERX2 #include "bli_family_thunderx2.h" #endif #ifdef BLIS_FAMILY_CORTEXA57 #include "bli_family_cortexa57.h" #endif #ifdef BLIS_FAMILY_CORTEXA53 #include "bli_family_cortexa53.h" #endif #ifdef BLIS_FAMILY_CORTEXA15 #include "bli_family_cortexa15.h" #endif #ifdef BLIS_FAMILY_CORTEXA9 #include "bli_family_cortexa9.h" #endif // -- IBM Power -- #ifdef BLIS_FAMILY_POWER10 #include "bli_family_power10.h" #endif #ifdef BLIS_FAMILY_POWER9 #include "bli_family_power9.h" #endif #ifdef BLIS_FAMILY_POWER7 #include "bli_family_power7.h" #endif // -- IBM BG/Q -- #ifdef BLIS_FAMILY_BGQ #include "bli_family_bgq.h" #endif // -- Generic -- #ifdef BLIS_FAMILY_GENERIC #include "bli_family_generic.h" #endif // // -- kernel set prototypes ---------------------------------------------------- // // -- Intel64 architectures -- #ifdef BLIS_KERNELS_SKX #include "bli_kernels_skx.h" #endif #ifdef BLIS_KERNELS_KNL #include "bli_kernels_knl.h" #endif #ifdef BLIS_KERNELS_KNC #include "bli_kernels_knc.h" #endif #ifdef BLIS_KERNELS_HASWELL #include "bli_kernels_haswell.h" #endif #ifdef BLIS_KERNELS_SANDYBRIDGE #include "bli_kernels_sandybridge.h" #endif #ifdef BLIS_KERNELS_PENRYN #include "bli_kernels_penryn.h" #endif // -- AMD64 architectures -- #ifdef BLIS_KERNELS_ZEN2 #include "bli_kernels_zen2.h" #endif #ifdef BLIS_KERNELS_ZEN #include "bli_kernels_zen.h" #endif //#ifdef BLIS_KERNELS_EXCAVATOR //#include "bli_kernels_excavator.h" //#endif //#ifdef BLIS_KERNELS_STEAMROLLER //#include "bli_kernels_steamroller.h" //#endif #ifdef BLIS_KERNELS_PILEDRIVER #include "bli_kernels_piledriver.h" #endif #ifdef BLIS_KERNELS_BULLDOZER #include "bli_kernels_bulldozer.h" #endif // -- ARM architectures -- #ifdef BLIS_KERNELS_ARMSVE #include "bli_kernels_armsve.h" #endif #ifdef BLIS_KERNELS_ARMV8A #include "bli_kernels_armv8a.h" #endif #ifdef BLIS_KERNELS_ARMV7A #include "bli_kernels_armv7a.h" #endif // -- IBM Power -- #ifdef BLIS_KERNELS_POWER10 #include "bli_kernels_power10.h" #endif #ifdef BLIS_KERNELS_POWER9 #include "bli_kernels_power9.h" #endif #ifdef BLIS_KERNELS_POWER7 #include "bli_kernels_power7.h" #endif // -- IBM BG/Q -- #ifdef BLIS_KERNELS_BGQ #include "bli_kernels_bgq.h" #endif #endif blis-0.9.0/frame/include/bli_arch_config_pre.h000066400000000000000000000053701422157504600213100ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_ARCH_CONFIG_PRE_H #define BLIS_ARCH_CONFIG_PRE_H // -- Naming-related kernel definitions ---------------------------------------- // The default suffix appended to reference kernels. #define BLIS_REF_SUFFIX _ref // A suffix used for labeling certain induced method aware functions. #define BLIS_IND_SUFFIX _ind // Add an underscore to the BLIS kernel set string, if it was defined. #ifdef BLIS_CNAME #define BLIS_CNAME_INFIX PASTECH(_,BLIS_CNAME) #endif // Combine the CNAME and _ref for convenience to the code that defines // reference kernels. //#define BLIS_CNAME_REF_SUFFIX PASTECH2(_,BLIS_CNAME,BLIS_REF_SUFFIX) // -- Prototype-generating macro definitions ----------------------------------- // Prototype-generating macro for bli_cntx_init_*() functions. #define CNTX_INIT_PROTS( archname ) \ \ void PASTEMAC(cntx_init_,archname) \ ( \ cntx_t* cntx \ ); \ void PASTEMAC2(cntx_init_,archname,BLIS_REF_SUFFIX) \ ( \ cntx_t* cntx \ ); \ void PASTEMAC2(cntx_init_,archname,BLIS_IND_SUFFIX) \ ( \ ind_t method, \ cntx_t* cntx \ ); #endif blis-0.9.0/frame/include/bli_blas_macro_defs.h000066400000000000000000000061501422157504600213000ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_BLAS_MACRO_DEFS_H #define BLIS_BLAS_MACRO_DEFS_H // -- Various Fortran compatibility macros -- // Macro to treat negative dimensions as zero. #define bli_convert_blas_dim1( n_blas, n_blis )\ { \ if ( n_blas < 0 ) n_blis = ( dim_t )0; \ else n_blis = ( dim_t )n_blas; \ } // Macro to flip signs of increments if input increments are negative. #define bli_convert_blas_incv( n, x_blas, incx_blas, \ x_blis, incx_blis ) \ { \ if ( incx_blas < 0 ) \ { \ /* The semantics of negative stride in BLAS are that the vector operand be traversed in reverse order. (Another way to think of this is that negative strides effectively reverse the order of the vector, but without any explicit data movements.) This is also how BLIS interprets negative strides. The differences is that with BLAS, the caller *always* passes in the 0th (i.e., top-most or left-most) element of the vector, even when the stride is negative. By contrast, in BLIS, negative strides are used *relative* to the vector address as it is given. Thus, in BLIS, if this backwards traversal is desired, the caller *must* pass in the address to the (n-1)th (i.e., the bottom-most or right-most) element along with a negative stride. */ \ x_blis = (x_blas) + (n-1)*(-incx_blas); \ incx_blis = ( inc_t )(incx_blas); \ } \ else \ { \ x_blis = (x_blas); \ incx_blis = ( inc_t )(incx_blas); \ } \ } #endif blis-0.9.0/frame/include/bli_builtin_macro_defs.h000066400000000000000000000040041422157504600220210ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2019, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_BUILTIN_MACRO_DEFS_H #define BLIS_BUILTIN_MACRO_DEFS_H #if defined(__ICC) || defined(__INTEL_COMPILER) // icc #define bli_prefetch( addr, rw, loc ) #elif defined(__clang__) // clang #define bli_prefetch( addr, rw, loc ) #elif defined(__GNUC__) // gcc #define bli_prefetch( addr, rw, loc ) __builtin_prefetch( addr, rw, loc ); #endif #endif blis-0.9.0/frame/include/bli_complex_macro_defs.h000066400000000000000000000044411422157504600220270ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_COMPLEX_MACRO_DEFS_H #define BLIS_COMPLEX_MACRO_DEFS_H // -- Real and imaginary accessor macros -- #define bli_sreal( x ) ( x ) #define bli_simag( x ) ( 0.0F ) #define bli_dreal( x ) ( x ) #define bli_dimag( x ) ( 0.0 ) #ifndef BLIS_ENABLE_C99_COMPLEX #define bli_creal( x ) ( (x).real ) #define bli_cimag( x ) ( (x).imag ) #define bli_zreal( x ) ( (x).real ) #define bli_zimag( x ) ( (x).imag ) #else // ifdef BLIS_ENABLE_C99_COMPLEX #define bli_creal( x ) ( crealf(x) ) #define bli_cimag( x ) ( cimagf(x) ) #define bli_zreal( x ) ( creal(x) ) #define bli_zimag( x ) ( cimag(x) ) #endif // BLIS_ENABLE_C99_COMPLEX #endif blis-0.9.0/frame/include/bli_config_macro_defs.h000066400000000000000000000241471422157504600216320ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_CONFIG_MACRO_DEFS_H #define BLIS_CONFIG_MACRO_DEFS_H // -- INTEGER PROPERTIES ------------------------------------------------------- // The bit size of the integer type used to track values such as dimensions, // strides, diagonal offsets. A value of 32 results in BLIS using 32-bit signed // integers while 64 results in 64-bit integers. Any other value results in use // of the C99 type "long int". Note that this ONLY affects integers used // internally within BLIS as well as those exposed in the native BLAS-like BLIS // interface. #ifndef BLIS_INT_TYPE_SIZE #ifdef BLIS_ARCH_64 #define BLIS_INT_TYPE_SIZE 64 #else #define BLIS_INT_TYPE_SIZE 32 #endif #endif // -- FLOATING-POINT PROPERTIES ------------------------------------------------ // Enable use of built-in C99 "float complex" and "double complex" types and // associated overloaded operations and functions? Disabling results in // scomplex and dcomplex being defined in terms of simple structs. // NOTE: AVOID USING THIS FEATURE. IT IS PROBABLY BROKEN. #ifdef BLIS_ENABLE_C99_COMPLEX // No additional definitions needed. #else // Default behavior is disabled. #endif // -- MULTITHREADING ----------------------------------------------------------- // Enable multithreading via POSIX threads. #ifdef BLIS_ENABLE_PTHREADS // No additional definitions needed. #else // Default behavior is disabled. #endif // Enable multithreading via OpenMP. #ifdef BLIS_ENABLE_OPENMP // No additional definitions needed. #else // Default behavior is disabled. #endif // Perform a sanity check to make sure the user doesn't try to enable // both OpenMP and pthreads. #if defined ( BLIS_ENABLE_OPENMP ) && \ defined ( BLIS_ENABLE_PTHREADS ) #error "BLIS_ENABLE_OPENMP and BLIS_ENABLE_PTHREADS may not be simultaneously defined." #endif // Here, we define BLIS_ENABLE_MULTITHREADING if either OpenMP // or pthreads are enabled. This macro is useful in situations when // we want to detect use of either OpenMP or pthreads (as opposed // to neither being used). #if defined ( BLIS_ENABLE_OPENMP ) || \ defined ( BLIS_ENABLE_PTHREADS ) #define BLIS_ENABLE_MULTITHREADING #endif // Enable the use of prime numbers of threads when requesting automatic thread // factorization. When disabled, requesting a prime number of threads will // result in a reduction (by one) of the number of threads, provided that the // prime number exceeds a minimum threshold (see below). #ifdef BLIS_ENABLE_AUTO_PRIME_NUM_THREADS #undef BLIS_DISABLE_AUTO_PRIME_NUM_THREADS #else // Default behavior is disabled. #undef BLIS_DISABLE_AUTO_PRIME_NUM_THREADS // In case user explicitly disabled. #define BLIS_DISABLE_AUTO_PRIME_NUM_THREADS #endif // Set the maximum requested number of threads that BLIS will accept from the // user that may be prime. If a larger prime number of threads is requested, // it will be reduced by one to allow for more efficient thread factorizations. // This value will only be used if BLIS_ENABLE_AUTO_PRIME_NUM_THREADS is defined. #ifndef BLIS_NT_MAX_PRIME #define BLIS_NT_MAX_PRIME 11 #endif // -- MIXED DATATYPE SUPPORT --------------------------------------------------- // Enable mixed datatype support? #ifdef BLIS_DISABLE_MIXED_DT #undef BLIS_ENABLE_GEMM_MD #else // Default behavior is enabled. #define BLIS_ENABLE_GEMM_MD #endif // Enable memory-intensive optimizations for mixed datatype support? #ifdef BLIS_DISABLE_MIXED_DT_EXTRA_MEM #undef BLIS_ENABLE_GEMM_MD_EXTRA_MEM #else // Default behavior is enabled. #define BLIS_ENABLE_GEMM_MD_EXTRA_MEM #endif // -- MISCELLANEOUS OPTIONS ---------------------------------------------------- // Do NOT require the cross-blocksize constraints. That is, do not enforce // MC % NR = 0 and NC % MR = 0 in bli_kernel_macro_defs.h. These are ONLY // needed when implementing trsm_r by allowing the right-hand matrix B to // be triangular. #ifndef BLIS_RELAX_MCNR_NCMR_CONSTRAINTS #define BLIS_RELAX_MCNR_NCMR_CONSTRAINTS #endif // -- BLAS COMPATIBILITY LAYER ------------------------------------------------- // Enable the BLAS compatibility layer? #ifdef BLIS_DISABLE_BLAS #undef BLIS_ENABLE_BLAS #else // Default behavior is enabled. #undef BLIS_ENABLE_BLAS // In case user explicitly enabled. #define BLIS_ENABLE_BLAS #endif // The bit size of the integer type used to track values such as dimensions and // leading dimensions (ie: column strides) within the BLAS compatibility layer. // A value of 32 results in the compatibility layer using 32-bit signed integers // while 64 results in 64-bit integers. Any other value results in use of the // C99 type "long int". Note that this ONLY affects integers used within the // BLAS compatibility layer. #ifndef BLIS_BLAS_INT_TYPE_SIZE #define BLIS_BLAS_INT_TYPE_SIZE 32 #endif // By default, the level-3 BLAS routines are implemented by directly calling // the BLIS object API. Alternatively, they may first call the typed BLIS // API, which will then call the object API. //#define BLIS_BLAS3_CALLS_TAPI #ifdef BLIS_BLAS3_CALLS_TAPI #undef BLIS_BLAS3_CALLS_OAPI #else // Default behavior is to call object API directly. #undef BLIS_BLAS3_CALLS_OAPI // In case user explicitly enabled. #define BLIS_BLAS3_CALLS_OAPI #endif // -- CBLAS COMPATIBILITY LAYER ------------------------------------------------ // Enable the CBLAS compatibility layer? // NOTE: Enabling CBLAS will automatically enable the BLAS compatibility layer // regardless of whether or not it was explicitly enabled above. Furthermore, // the CBLAS compatibility layer will use the integer type size definition // specified above when defining the size of its own integers (regardless of // whether the BLAS layer was enabled directly or indirectly). #ifdef BLIS_ENABLE_CBLAS // No additional definitions needed. #else // Default behavior is disabled. #endif // -- SHARED LIBRARY SYMBOL EXPORT --------------------------------------------- // When building shared libraries, we can control which symbols are exported for // linking by external applications. BLIS annotates all function prototypes that // are meant to be "public" with BLIS_EXPORT_BLIS (with BLIS_EXPORT_BLAS playing // a similar role for BLAS compatibility routines). Which symbols are exported // is controlled by the default symbol visibility, as specifed by the gcc option // -fvisibility=[default|hidden]. The default for this option is 'default', or, // "public", which, if allowed to stand, causes all symbols in BLIS to be // linkable from the outside. But when compiling with -fvisibility=hidden, all // symbols start out hidden (that is, restricted only for internal use by BLIS), // with that setting overridden only for function prototypes or variable // declarations that are annotated with BLIS_EXPORT_BLIS. #ifndef BLIS_EXPORT #if !defined(BLIS_ENABLE_SHARED) #define BLIS_EXPORT #else #if defined(_WIN32) || defined(__CYGWIN__) #ifdef BLIS_IS_BUILDING_LIBRARY #define BLIS_EXPORT __declspec(dllexport) #else #define BLIS_EXPORT __declspec(dllimport) #endif #elif defined(__GNUC__) && __GNUC__ >= 4 #define BLIS_EXPORT __attribute__ ((visibility ("default"))) #else #define BLIS_EXPORT #endif #endif #endif #define BLIS_EXPORT_BLIS BLIS_EXPORT #define BLIS_EXPORT_BLAS BLIS_EXPORT #define BLIS_EXPORT_ADDON BLIS_EXPORT // -- OVERRIDABLE (WEAK) SYMBOLS ----------------------------------------------- // On Linux, functions called from a shared library can be overriden by the main // program simply by providing a new definition. However, macOS uses a "two-level // namespace" which causes calls to shared library functions to be tied to the // library and not overridable. As a workaround, certain symbols can be defined // as "weak" and are given lower preference during linking. #ifndef BLIS_OVERRIDABLE #if BLIS_OS_OSX #define BLIS_OVERRIDABLE __attribute__((weak)) #else #define BLIS_OVERRIDABLE #endif #endif // -- STATIC INLINE FUNCTIONS -------------------------------------------------- // C and C++ have different semantics for defining "inline" functions. In C, // the keyword phrase "static inline" accomplishes this, though the "inline" // is optional. In C++, the "inline" keyword is required and obviates "static" // altogether. Why does this matter? While BLIS is compiled in C99, blis.h may // be #included by a source file that is compiled with C++. #ifdef __cplusplus #define BLIS_INLINE inline #else //#define BLIS_INLINE static inline #define BLIS_INLINE static #endif #endif blis-0.9.0/frame/include/bli_edge_case_macro_defs.h000066400000000000000000000170711422157504600222620ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2021, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_EDGE_CASE_MACRO_DEFS_H #define BLIS_EDGE_CASE_MACRO_DEFS_H // // Macros for edge-case handling within gemm microkernels. // // -- Setup helper macros -- #define GEMM_UKR_SETUP_CT_PRE(ch,mr,nr,row_major,alignment) \ \ PASTEMAC(ch,ctype)* restrict _beta = beta; \ PASTEMAC(ch,ctype)* restrict _c = c; \ const inc_t _rs_c = rs_c; \ const inc_t _cs_c = cs_c; \ PASTEMAC(ch,ctype) _ct[ BLIS_STACK_BUF_MAX_SIZE / sizeof( PASTEMAC(ch,type) ) ] \ __attribute__((aligned(alignment))); \ const inc_t _rs_ct = row_major ? nr : 1; \ const inc_t _cs_ct = row_major ? 1 : mr; #define GEMM_UKR_SETUP_CT_POST(ch) \ \ PASTEMAC(ch,ctype) _zero; \ PASTEMAC(ch,set0s)( _zero ); \ \ if ( _use_ct ) \ { \ c = _ct; \ rs_c = _rs_ct; \ cs_c = _cs_ct; \ beta = &_zero; \ } // -- Setup macros -- #define GEMM_UKR_SETUP_CT(ch,mr,nr,row_major) \ \ /* Scenario 1: the ukernel contains assembly-level support only for its IO preference (e.g. only row-oriented or only column-oriented IO). Use a temporary microtile for the other two cases as well as edge cases. */ \ GEMM_UKR_SETUP_CT_PRE(ch,mr,nr,row_major,1); \ const bool _use_ct = ( row_major ? cs_c != 1 : rs_c != 1 ) || \ m != mr || n != nr; \ GEMM_UKR_SETUP_CT_POST(ch); #define GEMM_UKR_SETUP_CT_AMBI(ch,mr,nr,row_major) \ \ /* Scenario 2: the ukernel contains assembly-level support for its IO preference as well as its opposite via in-register transpose (e.g. both row- and column-oriented IO). Use a temporary microtile for the general stride case as well as edge cases. */ \ GEMM_UKR_SETUP_CT_PRE(ch,mr,nr,row_major,1); \ const bool _use_ct = ( cs_c != 1 && rs_c != 1 ) || \ m != mr || n != nr; \ GEMM_UKR_SETUP_CT_POST(ch); #define GEMM_UKR_SETUP_CT_ANY(ch,mr,nr,row_major) \ \ /* Scenario 3: Similar to (2) where the assembly region also supports general stride I0. Use a temporary microtile only for edge cases. */ \ GEMM_UKR_SETUP_CT_PRE(ch,mr,nr,row_major,1); \ const bool _use_ct = ( m != mr || n != nr ); \ GEMM_UKR_SETUP_CT_POST(ch); #define GEMM_UKR_SETUP_CT_ALIGNED(ch,mr,nr,row_major,alignment) \ \ /* Scenario 4: Similar to (1), but uses temporary microtile to handle cases where the pointer to the C microtile is not aligned. */ \ GEMM_UKR_SETUP_CT_PRE(ch,mr,nr,row_major,alignment); \ const bool _use_ct = ( row_major ? cs_c != 1 : rs_c != 1 ) || \ m != mr || n != nr || \ ( (uintptr_t)_c % alignment ) || \ ( ( ( row_major ? _rs_c : _cs_c )*sizeof( PASTEMAC(ch,ctype) ) ) % alignment ); \ GEMM_UKR_SETUP_CT_POST(ch); // -- Flush macros -- #define GEMM_UKR_FLUSH_CT(ch) \ \ /* If we actually used the temporary microtile, accumulate it to the output microtile. */ \ if ( _use_ct ) \ { \ PASTEMAC(ch,xpbys_mxn) \ ( \ m, n, \ _ct, _rs_ct, _cs_ct, \ _beta, \ _c, _rs_c, _cs_c \ ); \ } \ // // Macros for edge-case handling within gemmtrsm microkernels. // // -- Setup helper macros -- #define GEMMTRSM_UKR_SETUP_CT_PRE(ch,mr,nr,row_major,alignment) \ \ PASTEMAC(ch,ctype)* restrict _c = c11; \ const inc_t _rs_c = rs_c; \ const inc_t _cs_c = cs_c; \ PASTEMAC(ch,ctype) _ct[ BLIS_STACK_BUF_MAX_SIZE / sizeof( PASTEMAC(ch,type) ) ] \ __attribute__((aligned(alignment))); \ const inc_t _rs_ct = row_major ? nr : 1; \ const inc_t _cs_ct = row_major ? 1 : mr; #define GEMMTRSM_UKR_SETUP_CT_POST(ch) \ \ if ( _use_ct ) \ { \ c11 = _ct; \ rs_c = _rs_ct; \ cs_c = _cs_ct; \ } // -- Setup macros -- #define GEMMTRSM_UKR_SETUP_CT(ch,mr,nr,row_major) \ \ /* Scenario 1: the ukernel contains assembly-level support only for its IO preference (e.g. only row-oriented or only column-oriented IO). Use a temporary microtile for the other two cases as well as edge cases. */ \ GEMMTRSM_UKR_SETUP_CT_PRE(ch,mr,nr,row_major,1); \ const bool _use_ct = ( row_major ? cs_c != 1 : rs_c != 1 ) || \ m != mr || n != nr; \ GEMMTRSM_UKR_SETUP_CT_POST(ch); #define GEMMTRSM_UKR_SETUP_CT_AMBI(ch,mr,nr,row_major) \ \ /* Scenario 2: the ukernel contains assembly-level support for its IO preference as well as its opposite via in-register transpose (e.g. both row- and column-oriented IO). Use a temporary microtile for the general stride case as well as edge cases. */ \ GEMMTRSM_UKR_SETUP_CT_PRE(ch,mr,nr,row_major,1); \ const bool _use_ct = ( cs_c != 1 && rs_c != 1 ) || \ m != mr || n != nr; \ GEMMTRSM_UKR_SETUP_CT_POST(ch); #define GEMMTRSM_UKR_SETUP_CT_ANY(ch,mr,nr,row_major) \ \ /* Scenario 3: Similar to (2) where the assembly region also supports general stride I0. Use a temporary microtile only for edge cases. */ \ GEMMTRSM_UKR_SETUP_CT_PRE(ch,mr,nr,row_major,1); \ const bool _use_ct = ( m != mr || n != nr ); \ GEMMTRSM_UKR_SETUP_CT_POST(ch); #define GEMMTRSM_UKR_SETUP_CT_ALIGNED(ch,mr,nr,row_major,alignment) \ \ /* Scenario 4: Similar to (1), but uses temporary microtile to handle cases where the pointer to the C microtile is not aligned. */ \ GEMMTRSM_UKR_SETUP_CT_PRE(ch,mr,nr,row_major,alignment); \ const bool _use_ct = ( row_major ? cs_c != 1 : rs_c != 1 ) || \ m != mr || n != nr || \ ( (uintptr_t)_c % alignment ) || \ ( ( ( row_major ? _rs_c : _cs_c )*sizeof( PASTEMAC(ch,ctype) ) ) % alignment ); \ GEMMTRSM_UKR_SETUP_CT_POST(ch); // -- Flush macros -- #define GEMMTRSM_UKR_FLUSH_CT(ch) \ \ /* If we actually used the temporary microtile, use it to overwrite the output microtile. Used by trsm. */ \ if ( _use_ct ) \ { \ PASTEMAC(ch,copys_mxn) \ ( \ m, n, \ _ct, _rs_ct, _cs_ct, \ _c, _rs_c, _cs_c \ ); \ } \ #endif blis-0.9.0/frame/include/bli_error_macro_defs.h000066400000000000000000000036021422157504600215070ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_ERROR_MACRO_DEFS_H #define BLIS_ERROR_MACRO_DEFS_H // Used to insert filenames and line numbers into error-checking code. #define bli_check_error_code( code ) \ bli_check_error_code_helper( code, __FILE__, __LINE__ ) #endif blis-0.9.0/frame/include/bli_extern_defs.h000066400000000000000000000042611422157504600205040ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_EXTERN_DEFS_H #define BLIS_EXTERN_DEFS_H BLIS_EXPORT_BLIS extern obj_t BLIS_TWO; BLIS_EXPORT_BLIS extern obj_t BLIS_ONE; //BLIS_EXPORT_BLIS extern obj_t BLIS_ONE_HALF; BLIS_EXPORT_BLIS extern obj_t BLIS_ZERO; //BLIS_EXPORT_BLIS extern obj_t BLIS_MINUS_ONE_HALF; BLIS_EXPORT_BLIS extern obj_t BLIS_MINUS_ONE; BLIS_EXPORT_BLIS extern obj_t BLIS_MINUS_TWO; BLIS_EXPORT_BLIS extern thrcomm_t BLIS_SINGLE_COMM; BLIS_EXPORT_BLIS extern thrinfo_t BLIS_PACKM_SINGLE_THREADED; BLIS_EXPORT_BLIS extern thrinfo_t BLIS_GEMM_SINGLE_THREADED; #endif blis-0.9.0/frame/include/bli_f2c.h000066400000000000000000000043751422157504600166560ustar00rootroot00000000000000// f2c.h -- Standard Fortran to C header file // barf [ba:rf] 2. "He suggested using FORTRAN, and everybody barfed." // - From The Shogakukan DICTIONARY OF NEW ENGLISH (Second edition) #ifndef BLIS_F2C_H #define BLIS_F2C_H typedef f77_int bla_integer; typedef f77_char bla_character; //typedef char *address; //typedef short int shortint; typedef float bla_real; typedef double bla_double; typedef scomplex bla_scomplex; typedef dcomplex bla_dcomplex; typedef f77_int bla_logical; //typedef short int shortlogical; //typedef char logical1; //typedef char integer1; #ifdef INTEGER_STAR_8 // Adjust for integer*8. typedef long long longint; // system-dependent typedef unsigned long long ulongint; // system-dependent #define qbit_clear(a,b) ((a) & ~((ulongint)1 << (b))) #define qbit_set(a,b) ((a) | ((ulongint)1 << (b))) #endif #ifndef TRUE_ #define TRUE_ (1) #endif #ifndef FALSE_ #define FALSE_ (0) #endif // Extern is for use with -E #ifndef Extern #define Extern extern #endif // I/O stuff #ifdef f2c_i2 // for -i2 //typedef short flag; //typedef short ftnlen; typedef bla_integer ftnlen; //typedef short ftnint; #else //typedef long int flag; //typedef long int ftnlen; typedef bla_integer ftnlen; //typedef long int ftnint; #endif #ifndef VOID #define VOID void #endif #ifndef f2c_abs #define f2c_abs(x) ((x) >= 0 ? (x) : -(x)) #endif #ifndef f2c_dabs #define f2c_dabs(x) (doublereal)f2c_abs(x) #endif #ifndef f2c_min #define f2c_min(a,b) ((a) <= (b) ? (a) : (b)) #endif #ifndef f2c_max #define f2c_max(a,b) ((a) >= (b) ? (a) : (b)) #endif #ifndef f2c_dmin #define f2c_dmin(a,b) (doublereal)f2c_min(a,b) #endif #ifndef f2c_dmax #define f2c_dmax(a,b) (doublereal)f2c_max(a,b) #endif #ifndef bit_test #define bit_test(a,b) ((a) >> (b) & 1) #endif #ifndef bit_clear #define bit_clear(a,b) ((a) & ~((uinteger)1 << (b))) #endif #ifndef bit_set #define bit_set(a,b) ((a) | ((uinteger)1 << (b))) #endif // undef any lower-case symbols that your C compiler predefines, e.g.: #ifndef Skip_f2c_Undefs #undef cray #undef gcos #undef mc68010 #undef mc68020 #undef mips #undef pdp11 #undef sgi #undef sparc #undef sun #undef sun2 #undef sun3 #undef sun4 #undef u370 #undef u3b #undef u3b2 #undef u3b5 #undef unix #undef vax #endif #endif blis-0.9.0/frame/include/bli_genarray_macro_defs.h000066400000000000000000000250241422157504600221700ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_GENARRAY_MACRO_DEFS_H #define BLIS_GENARRAY_MACRO_DEFS_H // -- Macros to generate function arrays --------------------------------------- // -- "Smart" one-operand macro -- #define GENARRAY_FPA(tname,opname) \ \ static tname PASTECH(opname,_fpa)[BLIS_NUM_FP_TYPES] = \ { \ ( tname )PASTEMAC(s,opname), \ ( tname )PASTEMAC(c,opname), \ ( tname )PASTEMAC(d,opname), \ ( tname )PASTEMAC(z,opname) \ } // -- "Smart" one-operand macro (with integer support) -- #define GENARRAY_FPA_I(tname,opname) \ \ static tname PASTECH(opname,_fpa)[BLIS_NUM_FP_TYPES+1] = \ { \ ( tname )PASTEMAC(s,opname), \ ( tname )PASTEMAC(c,opname), \ ( tname )PASTEMAC(d,opname), \ ( tname )PASTEMAC(z,opname), \ ( tname )PASTEMAC(i,opname) \ } // -- "Smart" two-operand macro -- #define GENARRAY_FPA2(tname,op) \ \ static tname PASTECH(op,_fpa2)[BLIS_NUM_FP_TYPES][BLIS_NUM_FP_TYPES] = \ { \ { ( tname )PASTEMAC2(s,s,op), ( tname )PASTEMAC2(s,c,op), ( tname )PASTEMAC2(s,d,op), ( tname )PASTEMAC2(s,z,op) }, \ { ( tname )PASTEMAC2(c,s,op), ( tname )PASTEMAC2(c,c,op), ( tname )PASTEMAC2(c,d,op), ( tname )PASTEMAC2(c,z,op) }, \ { ( tname )PASTEMAC2(d,s,op), ( tname )PASTEMAC2(d,c,op), ( tname )PASTEMAC2(d,d,op), ( tname )PASTEMAC2(d,z,op) }, \ { ( tname )PASTEMAC2(z,s,op), ( tname )PASTEMAC2(z,c,op), ( tname )PASTEMAC2(z,d,op), ( tname )PASTEMAC2(z,z,op) } \ } // -- "Smart" two-operand macro -- /* #define GENARRAY2_VFP(arrayname,op) \ \ arrayname[BLIS_NUM_FP_TYPES][BLIS_NUM_FP_TYPES] = \ { \ { PASTEMAC2(s,s,op), PASTEMAC2(s,c,op), PASTEMAC2(s,d,op), PASTEMAC2(s,z,op) }, \ { PASTEMAC2(c,s,op), PASTEMAC2(c,c,op), PASTEMAC2(c,d,op), PASTEMAC2(c,z,op) }, \ { PASTEMAC2(d,s,op), PASTEMAC2(d,c,op), PASTEMAC2(d,d,op), PASTEMAC2(d,z,op) }, \ { PASTEMAC2(z,s,op), PASTEMAC2(z,c,op), PASTEMAC2(z,d,op), PASTEMAC2(z,z,op) } \ } */ // -- One-operand macro -- #define GENARRAY(arrayname,op) \ \ arrayname[BLIS_NUM_FP_TYPES] = \ { \ PASTEMAC(s,op), \ PASTEMAC(c,op), \ PASTEMAC(d,op), \ PASTEMAC(z,op) \ } #define GENARRAY_I(arrayname,op) \ \ arrayname[BLIS_NUM_FP_TYPES+1] = \ { \ PASTEMAC(s,op), \ PASTEMAC(c,op), \ PASTEMAC(d,op), \ PASTEMAC(z,op), \ PASTEMAC(i,op) \ } /* #define GENARRAYR(arrayname,op) \ \ arrayname[BLIS_NUM_FP_TYPES][BLIS_NUM_FP_TYPES] = \ { \ { PASTEMAC2(s,s,op), NULL, PASTEMAC2(s,d,op), NULL, }, \ { PASTEMAC2(c,s,op), NULL, PASTEMAC2(c,d,op), NULL, }, \ { PASTEMAC2(d,s,op), NULL, PASTEMAC2(d,d,op), NULL, }, \ { PASTEMAC2(z,s,op), NULL, PASTEMAC2(z,d,op), NULL, } \ } */ // -- One-operand macro (with custom prefix) -- #define GENARRAY_PREF(arrayname,prefix,op) \ \ arrayname[BLIS_NUM_FP_TYPES] = \ { \ PASTECH2(prefix,s,op), \ PASTECH2(prefix,c,op), \ PASTECH2(prefix,d,op), \ PASTECH2(prefix,z,op) \ } // -- Two-operand macros -- #define GENARRAY2_ALL(arrayname,op) \ \ arrayname[BLIS_NUM_FP_TYPES][BLIS_NUM_FP_TYPES] = \ { \ { PASTEMAC2(s,s,op), PASTEMAC2(s,c,op), PASTEMAC2(s,d,op), PASTEMAC2(s,z,op) }, \ { PASTEMAC2(c,s,op), PASTEMAC2(c,c,op), PASTEMAC2(c,d,op), PASTEMAC2(c,z,op) }, \ { PASTEMAC2(d,s,op), PASTEMAC2(d,c,op), PASTEMAC2(d,d,op), PASTEMAC2(d,z,op) }, \ { PASTEMAC2(z,s,op), PASTEMAC2(z,c,op), PASTEMAC2(z,d,op), PASTEMAC2(z,z,op) } \ } #define GENARRAY2_EXT(arrayname,op) \ \ arrayname[BLIS_NUM_FP_TYPES][BLIS_NUM_FP_TYPES] = \ { \ { PASTEMAC2(s,s,op), PASTEMAC2(s,c,op), NULL, NULL, }, \ { PASTEMAC2(c,s,op), PASTEMAC2(c,c,op), NULL, NULL, }, \ { NULL, NULL, PASTEMAC2(d,d,op), PASTEMAC2(d,z,op) }, \ { NULL, NULL, PASTEMAC2(z,d,op), PASTEMAC2(z,z,op) } \ } #define GENARRAY2_MIN(arrayname,op) \ \ arrayname[BLIS_NUM_FP_TYPES][BLIS_NUM_FP_TYPES] = \ { \ { PASTEMAC2(s,s,op), NULL, NULL, NULL, }, \ { NULL, PASTEMAC2(c,c,op), NULL, NULL, }, \ { NULL, NULL, PASTEMAC2(d,d,op), NULL, }, \ { NULL, NULL, NULL, PASTEMAC2(z,z,op) } \ } // -- Three-operand macros -- #define GENARRAY3_ALL(arrayname,op) \ \ arrayname[BLIS_NUM_FP_TYPES][BLIS_NUM_FP_TYPES][BLIS_NUM_FP_TYPES] = \ { \ { \ { PASTEMAC3(s,s,s,op), PASTEMAC3(s,s,c,op), PASTEMAC3(s,s,d,op), PASTEMAC3(s,s,z,op) }, \ { PASTEMAC3(s,c,s,op), PASTEMAC3(s,c,c,op), PASTEMAC3(s,c,d,op), PASTEMAC3(s,c,z,op) }, \ { PASTEMAC3(s,d,s,op), PASTEMAC3(s,d,c,op), PASTEMAC3(s,d,d,op), PASTEMAC3(s,d,z,op) }, \ { PASTEMAC3(s,z,s,op), PASTEMAC3(s,z,c,op), PASTEMAC3(s,z,d,op), PASTEMAC3(s,z,z,op) } \ }, \ { \ { PASTEMAC3(c,s,s,op), PASTEMAC3(c,s,c,op), PASTEMAC3(c,s,d,op), PASTEMAC3(c,s,z,op) }, \ { PASTEMAC3(c,c,s,op), PASTEMAC3(c,c,c,op), PASTEMAC3(c,c,d,op), PASTEMAC3(c,c,z,op) }, \ { PASTEMAC3(c,d,s,op), PASTEMAC3(c,d,c,op), PASTEMAC3(c,d,d,op), PASTEMAC3(c,d,z,op) }, \ { PASTEMAC3(c,z,s,op), PASTEMAC3(c,z,c,op), PASTEMAC3(c,z,d,op), PASTEMAC3(c,z,z,op) } \ }, \ { \ { PASTEMAC3(d,s,s,op), PASTEMAC3(d,s,c,op), PASTEMAC3(d,s,d,op), PASTEMAC3(d,s,z,op) }, \ { PASTEMAC3(d,c,s,op), PASTEMAC3(d,c,c,op), PASTEMAC3(d,c,d,op), PASTEMAC3(d,c,z,op) }, \ { PASTEMAC3(d,d,s,op), PASTEMAC3(d,d,c,op), PASTEMAC3(d,d,d,op), PASTEMAC3(d,d,z,op) }, \ { PASTEMAC3(d,z,s,op), PASTEMAC3(d,z,c,op), PASTEMAC3(d,z,d,op), PASTEMAC3(d,z,z,op) } \ }, \ { \ { PASTEMAC3(z,s,s,op), PASTEMAC3(z,s,c,op), PASTEMAC3(z,s,d,op), PASTEMAC3(z,s,z,op) }, \ { PASTEMAC3(z,c,s,op), PASTEMAC3(z,c,c,op), PASTEMAC3(z,c,d,op), PASTEMAC3(z,c,z,op) }, \ { PASTEMAC3(z,d,s,op), PASTEMAC3(z,d,c,op), PASTEMAC3(z,d,d,op), PASTEMAC3(z,d,z,op) }, \ { PASTEMAC3(z,z,s,op), PASTEMAC3(z,z,c,op), PASTEMAC3(z,z,d,op), PASTEMAC3(z,z,z,op) } \ } \ } #define GENARRAY3_EXT(arrayname,op) \ \ arrayname[BLIS_NUM_FP_TYPES][BLIS_NUM_FP_TYPES][BLIS_NUM_FP_TYPES] = \ { \ { \ { PASTEMAC3(s,s,s,op), PASTEMAC3(s,s,c,op), NULL, NULL, }, \ { PASTEMAC3(s,c,s,op), PASTEMAC3(s,c,c,op), NULL, NULL, }, \ { NULL, NULL, NULL, NULL, }, \ { NULL, NULL, NULL, NULL, } \ }, \ { \ { PASTEMAC3(c,s,s,op), PASTEMAC3(c,s,c,op), NULL, NULL, }, \ { PASTEMAC3(c,c,s,op), PASTEMAC3(c,c,c,op), NULL, NULL, }, \ { NULL, NULL, NULL, NULL, }, \ { NULL, NULL, NULL, NULL, } \ }, \ { \ { NULL, NULL, NULL, NULL, }, \ { NULL, NULL, NULL, NULL, }, \ { NULL, NULL, PASTEMAC3(d,d,d,op), PASTEMAC3(d,d,z,op) }, \ { NULL, NULL, PASTEMAC3(d,z,d,op), PASTEMAC3(d,z,z,op) } \ }, \ { \ { NULL, NULL, NULL, NULL, }, \ { NULL, NULL, NULL, NULL, }, \ { NULL, NULL, PASTEMAC3(z,d,d,op), PASTEMAC3(z,d,z,op) }, \ { NULL, NULL, PASTEMAC3(z,z,d,op), PASTEMAC3(z,z,z,op) } \ } \ } #define GENARRAY3_MIN(arrayname,op) \ \ arrayname[BLIS_NUM_FP_TYPES][BLIS_NUM_FP_TYPES][BLIS_NUM_FP_TYPES] = \ { \ { \ { PASTEMAC3(s,s,s,op), NULL, NULL, NULL, }, \ { NULL, NULL, NULL, NULL, }, \ { NULL, NULL, NULL, NULL, }, \ { NULL, NULL, NULL, NULL, } \ }, \ { \ { NULL, NULL, NULL, NULL, }, \ { NULL, PASTEMAC3(c,c,c,op), NULL, NULL, }, \ { NULL, NULL, NULL, NULL, }, \ { NULL, NULL, NULL, NULL, } \ }, \ { \ { NULL, NULL, NULL, NULL, }, \ { NULL, NULL, NULL, NULL, }, \ { NULL, NULL, PASTEMAC3(d,d,d,op), NULL, }, \ { NULL, NULL, NULL, NULL, } \ }, \ { \ { NULL, NULL, NULL, NULL, }, \ { NULL, NULL, NULL, NULL, }, \ { NULL, NULL, NULL, NULL, }, \ { NULL, NULL, NULL, PASTEMAC3(z,z,z,op) } \ } \ } #endif blis-0.9.0/frame/include/bli_gentdef_macro_defs.h000066400000000000000000000054671422157504600220050ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_GENTDEF_MACRO_DEFS_H #define BLIS_GENTDEF_MACRO_DEFS_H // // -- MACROS TO INSERT TYPEDEF-GENERATING MACROS ------------------------------- // // -- function typedef macro (both typed and void) -- #define INSERT_GENTDEF( opname ) \ \ GENTDEF( float, s, opname, _ft ) \ GENTDEF( double, d, opname, _ft ) \ GENTDEF( scomplex, c, opname, _ft ) \ GENTDEF( dcomplex, z, opname, _ft ) \ \ GENTDEF( void, s, opname, _vft ) \ GENTDEF( void, d, opname, _vft ) \ GENTDEF( void, c, opname, _vft ) \ GENTDEF( void, z, opname, _vft ) \ \ GENTDEF( void, , opname, _vft ) // -- function typedef macro (both typed and void) with real projection -- #define INSERT_GENTDEFR( opname ) \ \ GENTDEFR( float, float, s, s, opname, _ft ) \ GENTDEFR( double, double, d, d, opname, _ft ) \ GENTDEFR( scomplex, float, c, s, opname, _ft ) \ GENTDEFR( dcomplex, double, z, d, opname, _ft ) \ \ GENTDEFR( void, void, s, s, opname, _vft ) \ GENTDEFR( void, void, d, d, opname, _vft ) \ GENTDEFR( void, void, c, s, opname, _vft ) \ GENTDEFR( void, void, z, d, opname, _vft ) \ \ GENTDEFR( void, void, , , opname, _vft ) #endif blis-0.9.0/frame/include/bli_gentfunc_macro_defs.h000066400000000000000000001522771422157504600222040ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_GENTFUNC_MACRO_DEFS_H #define BLIS_GENTFUNC_MACRO_DEFS_H // // -- MACROS TO INSERT FUNCTION-GENERATING MACROS ------------------------------ // // -- Macros for generating BLAS routines -------------------------------------- // -- Basic one-operand macro -- #define INSERT_GENTFUNC_BLAS( blasname, blisname ) \ \ GENTFUNC( float, s, blasname, blisname ) \ GENTFUNC( double, d, blasname, blisname ) \ GENTFUNC( scomplex, c, blasname, blisname ) \ GENTFUNC( dcomplex, z, blasname, blisname ) // -- Basic one-operand macro with real domain only -- #define INSERT_GENTFUNCRO_BLAS( blasname, blisname ) \ \ GENTFUNCRO( float, s, blasname, blisname ) \ GENTFUNCRO( double, d, blasname, blisname ) // -- Basic one-operand macro with complex domain only and real projection -- #define INSERT_GENTFUNCCO_BLAS( blasname, blisname ) \ \ GENTFUNCCO( scomplex, float, c, s, blasname, blisname ) \ GENTFUNCCO( dcomplex, double, z, d, blasname, blisname ) // -- Basic one-operand macro with conjugation (real funcs only, used only for dot, ger) -- #define INSERT_GENTFUNCDOTR_BLAS( blasname, blisname ) \ \ GENTFUNCDOT( float, s, , BLIS_NO_CONJUGATE, blasname, blisname ) \ GENTFUNCDOT( double, d, , BLIS_NO_CONJUGATE, blasname, blisname ) // -- Basic one-operand macro with conjugation (complex funcs only, used only for dot, ger) -- #define INSERT_GENTFUNCDOTC_BLAS( blasname, blisname ) \ \ GENTFUNCDOT( scomplex, c, c, BLIS_CONJUGATE, blasname, blisname ) \ GENTFUNCDOT( scomplex, c, u, BLIS_NO_CONJUGATE, blasname, blisname ) \ GENTFUNCDOT( dcomplex, z, c, BLIS_CONJUGATE, blasname, blisname ) \ GENTFUNCDOT( dcomplex, z, u, BLIS_NO_CONJUGATE, blasname, blisname ) // -- Basic one-operand macro with conjugation (used only for dot, ger) -- #define INSERT_GENTFUNCDOT_BLAS( blasname, blisname ) \ \ INSERT_GENTFUNCDOTR_BLAS( blasname, blisname ) \ INSERT_GENTFUNCDOTC_BLAS( blasname, blisname ) // -- Basic one-operand macro with real projection -- #define INSERT_GENTFUNCR_BLAS( rblasname, cblasname, blisname ) \ \ GENTFUNCR( float, float, s, s, rblasname, blisname ) \ GENTFUNCR( double, double, d, d, rblasname, blisname ) \ GENTFUNCR( scomplex, float, c, s, cblasname, blisname ) \ GENTFUNCR( dcomplex, double, z, d, cblasname, blisname ) // -- Alternate two-operand macro (one char for complex, one for real proj) -- #define INSERT_GENTFUNCR2_BLAS( blasname, blisname ) \ \ GENTFUNCR2( float, float, s, , blasname, blisname ) \ GENTFUNCR2( double, double, d, , blasname, blisname ) \ GENTFUNCR2( scomplex, float, c, s, blasname, blisname ) \ GENTFUNCR2( dcomplex, double, z, d, blasname, blisname ) // -- Extended two-operand macro (used only for scal) -- #define INSERT_GENTFUNCSCAL_BLAS( blasname, blisname ) \ \ GENTFUNCSCAL( float, float, s, , blasname, blisname ) \ GENTFUNCSCAL( double, double, d, , blasname, blisname ) \ GENTFUNCSCAL( scomplex, scomplex, c, , blasname, blisname ) \ GENTFUNCSCAL( dcomplex, dcomplex, z, , blasname, blisname ) \ GENTFUNCSCAL( scomplex, float, c, s, blasname, blisname ) \ GENTFUNCSCAL( dcomplex, double, z, d, blasname, blisname ) // -- Macros for functions with one operand ------------------------------------ // -- Basic one-operand macro -- // -- (no auxiliary arguments) -- #define INSERT_GENTFUNC_BASIC0( tfuncname ) \ \ GENTFUNC( float, s, tfuncname ) \ GENTFUNC( double, d, tfuncname ) \ GENTFUNC( scomplex, c, tfuncname ) \ GENTFUNC( dcomplex, z, tfuncname ) // -- (one auxiliary argument) -- #define INSERT_GENTFUNC_BASIC( tfuncname, varname ) \ \ GENTFUNC( float, s, tfuncname, varname ) \ GENTFUNC( double, d, tfuncname, varname ) \ GENTFUNC( scomplex, c, tfuncname, varname ) \ GENTFUNC( dcomplex, z, tfuncname, varname ) // -- (two auxiliary arguments) -- #define INSERT_GENTFUNC_BASIC2( tfuncname, varname1, varname2 ) \ \ GENTFUNC( float, s, tfuncname, varname1, varname2 ) \ GENTFUNC( double, d, tfuncname, varname1, varname2 ) \ GENTFUNC( scomplex, c, tfuncname, varname1, varname2 ) \ GENTFUNC( dcomplex, z, tfuncname, varname1, varname2 ) // -- (three auxiliary arguments) -- #define INSERT_GENTFUNC_BASIC3( tfuncname, varname1, varname2, varname3 ) \ \ GENTFUNC( float, s, tfuncname, varname1, varname2, varname3 ) \ GENTFUNC( double, d, tfuncname, varname1, varname2, varname3 ) \ GENTFUNC( scomplex, c, tfuncname, varname1, varname2, varname3 ) \ GENTFUNC( dcomplex, z, tfuncname, varname1, varname2, varname3 ) // -- (four auxiliary arguments) -- #define INSERT_GENTFUNC_BASIC4( tfuncname, varname1, varname2, varname3, varname4 ) \ \ GENTFUNC( float, s, tfuncname, varname1, varname2, varname3, varname4 ) \ GENTFUNC( double, d, tfuncname, varname1, varname2, varname3, varname4 ) \ GENTFUNC( scomplex, c, tfuncname, varname1, varname2, varname3, varname4 ) \ GENTFUNC( dcomplex, z, tfuncname, varname1, varname2, varname3, varname4 ) // -- Basic one-operand with real projection -- // -- (no auxiliary arguments) -- #define INSERT_GENTFUNCR_BASIC0( tfuncname ) \ \ GENTFUNCR( float, float, s, s, tfuncname ) \ GENTFUNCR( double, double, d, d, tfuncname ) \ GENTFUNCR( scomplex, float, c, s, tfuncname ) \ GENTFUNCR( dcomplex, double, z, d, tfuncname ) // -- (one auxiliary argument) -- #define INSERT_GENTFUNCR_BASIC( tfuncname, varname ) \ \ GENTFUNCR( float, float, s, s, tfuncname, varname ) \ GENTFUNCR( double, double, d, d, tfuncname, varname ) \ GENTFUNCR( scomplex, float, c, s, tfuncname, varname ) \ GENTFUNCR( dcomplex, double, z, d, tfuncname, varname ) // -- (two auxiliary arguments) -- #define INSERT_GENTFUNCR_BASIC2( tfuncname, varname1, varname2 ) \ \ GENTFUNCR( float, float, s, s, tfuncname, varname1, varname2 ) \ GENTFUNCR( double, double, d, d, tfuncname, varname1, varname2 ) \ GENTFUNCR( scomplex, float, c, s, tfuncname, varname1, varname2 ) \ GENTFUNCR( dcomplex, double, z, d, tfuncname, varname1, varname2 ) // -- (three auxiliary arguments) -- #define INSERT_GENTFUNCR_BASIC3( tfuncname, varname1, varname2, varname3 ) \ \ GENTFUNCR( float, float, s, s, tfuncname, varname1, varname2, varname3 ) \ GENTFUNCR( double, double, d, d, tfuncname, varname1, varname2, varname3 ) \ GENTFUNCR( scomplex, float, c, s, tfuncname, varname1, varname2, varname3 ) \ GENTFUNCR( dcomplex, double, z, d, tfuncname, varname1, varname2, varname3 ) // -- (four auxiliary arguments) -- #define INSERT_GENTFUNCR_BASIC4( tfuncname, varname1, varname2, varname3, varname4 ) \ \ GENTFUNCR( float, float, s, s, tfuncname, varname1, varname2, varname3, varname4 ) \ GENTFUNCR( double, double, d, d, tfuncname, varname1, varname2, varname3, varname4 ) \ GENTFUNCR( scomplex, float, c, s, tfuncname, varname1, varname2, varname3, varname4 ) \ GENTFUNCR( dcomplex, double, z, d, tfuncname, varname1, varname2, varname3, varname4 ) // -- Basic one-operand macro with real domain only -- // -- (no auxiliary arguments) -- #define INSERT_GENTFUNCRO_BASIC0( tfuncname ) \ \ GENTFUNCRO( float, s, tfuncname ) \ GENTFUNCRO( double, d, tfuncname ) \ // -- (one auxiliary argument) -- #define INSERT_GENTFUNCRO_BASIC( tfuncname, varname ) \ \ GENTFUNCRO( float, s, tfuncname, varname ) \ GENTFUNCRO( double, d, tfuncname, varname ) \ // -- Basic one-operand macro with complex domain only and real projection -- // -- (no auxiliary arguments) -- #define INSERT_GENTFUNCCO_BASIC0( tfuncname ) \ \ GENTFUNCCO( scomplex, float, c, s, tfuncname ) \ GENTFUNCCO( dcomplex, double, z, d, tfuncname ) // -- (one auxiliary argument) -- #define INSERT_GENTFUNCCO_BASIC( tfuncname, varname ) \ \ GENTFUNCCO( scomplex, float, c, s, tfuncname, varname ) \ GENTFUNCCO( dcomplex, double, z, d, tfuncname, varname ) // -- (two auxiliary arguments) -- #define INSERT_GENTFUNCCO_BASIC2( tfuncname, varname1, varname2 ) \ \ GENTFUNCCO( scomplex, float, c, s, tfuncname, varname1, varname2 ) \ GENTFUNCCO( dcomplex, double, z, d, tfuncname, varname1, varname2 ) // -- (three auxiliary arguments) -- #define INSERT_GENTFUNCCO_BASIC3( tfuncname, varname1, varname2, varname3 ) \ \ GENTFUNCCO( scomplex, float, c, s, tfuncname, varname1, varname2, varname3 ) \ GENTFUNCCO( dcomplex, double, z, d, tfuncname, varname1, varname2, varname3 ) // -- Basic one-operand macro with integer instance -- // -- (no auxiliary arguments) -- #define INSERT_GENTFUNC_BASIC0_I( tfuncname ) \ \ GENTFUNC( float, s, tfuncname ) \ GENTFUNC( double, d, tfuncname ) \ GENTFUNC( scomplex, c, tfuncname ) \ GENTFUNC( dcomplex, z, tfuncname ) \ GENTFUNC( gint_t, i, tfuncname ) // -- (one auxiliary argument) -- #define INSERT_GENTFUNC_BASIC_I( tfuncname, varname ) \ \ GENTFUNC( float, s, tfuncname, varname ) \ GENTFUNC( double, d, tfuncname, varname ) \ GENTFUNC( scomplex, c, tfuncname, varname ) \ GENTFUNC( dcomplex, z, tfuncname, varname ) \ GENTFUNC( gint_t, i, tfuncname, varname ) // -- Basic one-operand with integer projection -- // -- (no auxiliary arguments) -- #define INSERT_GENTFUNCI_BASIC0( tfuncname ) \ \ GENTFUNCI( float, gint_t, s, i, tfuncname ) \ GENTFUNCI( double, gint_t, d, i, tfuncname ) \ GENTFUNCI( scomplex, gint_t, c, i, tfuncname ) \ GENTFUNCI( dcomplex, gint_t, z, i, tfuncname ) // -- (one auxiliary argument) -- #define INSERT_GENTFUNCI_BASIC( tfuncname, varname ) \ \ GENTFUNCI( float, gint_t, s, i, tfuncname, varname ) \ GENTFUNCI( double, gint_t, d, i, tfuncname, varname ) \ GENTFUNCI( scomplex, gint_t, c, i, tfuncname, varname ) \ GENTFUNCI( dcomplex, gint_t, z, i, tfuncname, varname ) // -- Basic one-operand with real and integer projections -- // -- (no auxiliary arguments) -- #define INSERT_GENTFUNCRI_BASIC0( tfuncname ) \ \ GENTFUNCRI( float, float, gint_t, s, s, i, tfuncname ) \ GENTFUNCRI( double, double, gint_t, d, d, i, tfuncname ) \ GENTFUNCRI( scomplex, float, gint_t, c, s, i, tfuncname ) \ GENTFUNCRI( dcomplex, double, gint_t, z, d, i, tfuncname ) // -- Macros for functions with two primary operands --------------------------- // -- Basic two-operand macro -- // -- (no auxiliary arguments) -- #define INSERT_GENTFUNC2_BASIC0( tfuncname ) \ \ GENTFUNC2( float, float, s, s, tfuncname ) \ GENTFUNC2( double, double, d, d, tfuncname ) \ GENTFUNC2( scomplex, scomplex, c, c, tfuncname ) \ GENTFUNC2( dcomplex, dcomplex, z, z, tfuncname ) // -- (one auxiliary argument) -- #define INSERT_GENTFUNC2_BASIC( tfuncname, varname ) \ \ GENTFUNC2( float, float, s, s, tfuncname, varname ) \ GENTFUNC2( double, double, d, d, tfuncname, varname ) \ GENTFUNC2( scomplex, scomplex, c, c, tfuncname, varname ) \ GENTFUNC2( dcomplex, dcomplex, z, z, tfuncname, varname ) // -- Mixed domain two-operand macro -- // -- (no auxiliary arguments) -- #define INSERT_GENTFUNC2_MIX_D0( tfuncname ) \ \ GENTFUNC2( float, scomplex, s, c, tfuncname ) \ GENTFUNC2( scomplex, float, c, s, tfuncname ) \ \ GENTFUNC2( double, dcomplex, d, z, tfuncname ) \ GENTFUNC2( dcomplex, double, z, d, tfuncname ) // -- (one auxiliary argument) -- #define INSERT_GENTFUNC2_MIX_D( tfuncname, varname ) \ \ GENTFUNC2( float, scomplex, s, c, tfuncname, varname ) \ GENTFUNC2( scomplex, float, c, s, tfuncname, varname ) \ \ GENTFUNC2( double, dcomplex, d, z, tfuncname, varname ) \ GENTFUNC2( dcomplex, double, z, d, tfuncname, varname ) // -- Mixed precision two-operand macro -- // -- (no auxiliary arguments) -- #define INSERT_GENTFUNC2_MIX_P0( tfuncname ) \ \ GENTFUNC2( float, double, s, d, tfuncname ) \ GENTFUNC2( float, dcomplex, s, z, tfuncname ) \ \ GENTFUNC2( double, float, d, s, tfuncname ) \ GENTFUNC2( double, scomplex, d, c, tfuncname ) \ \ GENTFUNC2( scomplex, double, c, d, tfuncname ) \ GENTFUNC2( scomplex, dcomplex, c, z, tfuncname ) \ \ GENTFUNC2( dcomplex, float, z, s, tfuncname ) \ GENTFUNC2( dcomplex, scomplex, z, c, tfuncname ) \ // -- (one auxiliary argument) -- #define INSERT_GENTFUNC2_MIX_P( tfuncname, varname ) \ \ GENTFUNC2( float, double, s, d, tfuncname, varname ) \ GENTFUNC2( float, dcomplex, s, z, tfuncname, varname ) \ \ GENTFUNC2( double, float, d, s, tfuncname, varname ) \ GENTFUNC2( double, scomplex, d, c, tfuncname, varname ) \ \ GENTFUNC2( scomplex, double, c, d, tfuncname, varname ) \ GENTFUNC2( scomplex, dcomplex, c, z, tfuncname, varname ) \ \ GENTFUNC2( dcomplex, float, z, s, tfuncname, varname ) \ GENTFUNC2( dcomplex, scomplex, z, c, tfuncname, varname ) \ // -- Mixed domain/precision (all) two-operand macro -- // -- (no auxiliary arguments) -- #define INSERT_GENTFUNC2_MIXDP0( tfuncname ) \ \ GENTFUNC2( float, double, s, d, tfuncname ) \ GENTFUNC2( float, scomplex, s, c, tfuncname ) \ GENTFUNC2( float, dcomplex, s, z, tfuncname ) \ \ GENTFUNC2( double, float, d, s, tfuncname ) \ GENTFUNC2( double, scomplex, d, c, tfuncname ) \ GENTFUNC2( double, dcomplex, d, z, tfuncname ) \ \ GENTFUNC2( scomplex, float, c, s, tfuncname ) \ GENTFUNC2( scomplex, double, c, d, tfuncname ) \ GENTFUNC2( scomplex, dcomplex, c, z, tfuncname ) \ \ GENTFUNC2( dcomplex, float, z, s, tfuncname ) \ GENTFUNC2( dcomplex, double, z, d, tfuncname ) \ GENTFUNC2( dcomplex, scomplex, z, c, tfuncname ) // -- (one auxiliary argument) -- #define INSERT_GENTFUNC2_MIX_DP( tfuncname, varname ) \ \ GENTFUNC2( float, double, s, d, tfuncname, varname ) \ GENTFUNC2( float, scomplex, s, c, tfuncname, varname ) \ GENTFUNC2( float, dcomplex, s, z, tfuncname, varname ) \ \ GENTFUNC2( double, float, d, s, tfuncname, varname ) \ GENTFUNC2( double, scomplex, d, c, tfuncname, varname ) \ GENTFUNC2( double, dcomplex, d, z, tfuncname, varname ) \ \ GENTFUNC2( scomplex, float, c, s, tfuncname, varname ) \ GENTFUNC2( scomplex, double, c, d, tfuncname, varname ) \ GENTFUNC2( scomplex, dcomplex, c, z, tfuncname, varname ) \ \ GENTFUNC2( dcomplex, float, z, s, tfuncname, varname ) \ GENTFUNC2( dcomplex, double, z, d, tfuncname, varname ) \ GENTFUNC2( dcomplex, scomplex, z, c, tfuncname, varname ) // -- Basic two-operand with real projection of second operand -- // -- (no auxiliary arguments) -- #define INSERT_GENTFUNC2R_BASIC0( tfuncname ) \ \ GENTFUNC2R( float, float, float, s, s, s, tfuncname ) \ GENTFUNC2R( double, double, double, d, d, d, tfuncname ) \ GENTFUNC2R( scomplex, scomplex, float, c, c, s, tfuncname ) \ GENTFUNC2R( dcomplex, dcomplex, double, z, z, d, tfuncname ) // -- (one auxiliary argument) -- #define INSERT_GENTFUNC2R_BASIC( tfuncname, varname ) \ \ GENTFUNC2R( float, float, float, s, s, s, tfuncname, varname ) \ GENTFUNC2R( double, double, double, d, d, d, tfuncname, varname ) \ GENTFUNC2R( scomplex, scomplex, float, c, c, s, tfuncname, varname ) \ GENTFUNC2R( dcomplex, dcomplex, double, z, z, d, tfuncname, varname ) // -- Mixed domain two-operand with real projection of second operand -- // -- (no auxiliary arguments) -- #define INSERT_GENTFUNC2R_MIX_D0( tfuncname ) \ \ GENTFUNC2R( float, scomplex, float, s, c, s, tfuncname ) \ GENTFUNC2R( scomplex, float, float, c, s, s, tfuncname ) \ \ GENTFUNC2R( double, dcomplex, double, d, z, d, tfuncname ) \ GENTFUNC2R( dcomplex, double, double, z, d, d, tfuncname ) // -- (one auxiliary argument) -- #define INSERT_GENTFUNC2R_MIX_D( tfuncname, varname ) \ \ GENTFUNC2R( float, scomplex, float, s, c, s, tfuncname, varname ) \ GENTFUNC2R( scomplex, float, float, c, s, s, tfuncname, varname ) \ \ GENTFUNC2R( double, dcomplex, double, d, z, d, tfuncname, varname ) \ GENTFUNC2R( dcomplex, double, double, z, d, d, tfuncname, varname ) // -- Mixed precision two-operand with real projection of second operand -- // -- (no auxiliary arguments) -- #define INSERT_GENTFUNC2R_MIX_P0( tfuncname ) \ \ GENTFUNC2R( float, double, double, s, d, d, tfuncname ) \ GENTFUNC2R( float, dcomplex, double, s, z, d, tfuncname ) \ \ GENTFUNC2R( double, float, float, d, s, s, tfuncname ) \ GENTFUNC2R( double, scomplex, float, d, c, s, tfuncname ) \ \ GENTFUNC2R( scomplex, double, double, c, d, d, tfuncname ) \ GENTFUNC2R( scomplex, dcomplex, double, c, z, d, tfuncname ) \ \ GENTFUNC2R( dcomplex, float, float, z, s, s, tfuncname ) \ GENTFUNC2R( dcomplex, scomplex, float, z, c, s, tfuncname ) // -- (one auxiliary argument) -- #define INSERT_GENTFUNC2R_MIX_P( tfuncname, varname ) \ \ GENTFUNC2R( float, double, double, s, d, d, tfuncname, varname ) \ GENTFUNC2R( float, dcomplex, double, s, z, d, tfuncname, varname ) \ \ GENTFUNC2R( double, float, float, d, s, s, tfuncname, varname ) \ GENTFUNC2R( double, scomplex, float, d, c, s, tfuncname, varname ) \ \ GENTFUNC2R( scomplex, double, double, c, d, d, tfuncname, varname ) \ GENTFUNC2R( scomplex, dcomplex, double, c, z, d, tfuncname, varname ) \ \ GENTFUNC2R( dcomplex, float, float, z, s, s, tfuncname, varname ) \ GENTFUNC2R( dcomplex, scomplex, float, z, c, s, tfuncname, varname ) // -- Mixed domain/precision (all) two-operand macro with real projection of second operand -- // -- (no auxiliary arguments) -- #define INSERT_GENTFUNC2R_MIXDP0( tfuncname ) \ \ GENTFUNC2R( float, double, double, s, d, d, tfuncname ) \ GENTFUNC2R( float, scomplex, float, s, c, s, tfuncname ) \ GENTFUNC2R( float, dcomplex, double, s, z, d, tfuncname ) \ \ GENTFUNC2R( double, float, float, d, s, s, tfuncname ) \ GENTFUNC2R( double, scomplex, float, d, c, s, tfuncname ) \ GENTFUNC2R( double, dcomplex, double, d, z, d, tfuncname ) \ \ GENTFUNC2R( scomplex, float, float, c, s, s, tfuncname ) \ GENTFUNC2R( scomplex, double, double, c, d, d, tfuncname ) \ GENTFUNC2R( scomplex, dcomplex, double, c, z, d, tfuncname ) \ \ GENTFUNC2R( dcomplex, float, float, z, s, s, tfuncname ) \ GENTFUNC2R( dcomplex, double, double, z, d, d, tfuncname ) \ GENTFUNC2R( dcomplex, scomplex, float, z, c, s, tfuncname ) \ // -- (one auxiliary argument) -- #define INSERT_GENTFUNC2R_MIX_DP( tfuncname, varname ) \ \ GENTFUNC2R( float, double, double, s, d, d, tfuncname, varname ) \ GENTFUNC2R( float, scomplex, float, s, c, s, tfuncname, varname ) \ GENTFUNC2R( float, dcomplex, double, s, z, d, tfuncname, varname ) \ \ GENTFUNC2R( double, float, float, d, s, s, tfuncname, varname ) \ GENTFUNC2R( double, scomplex, float, d, c, s, tfuncname, varname ) \ GENTFUNC2R( double, dcomplex, double, d, z, d, tfuncname, varname ) \ \ GENTFUNC2R( scomplex, float, float, c, s, s, tfuncname, varname ) \ GENTFUNC2R( scomplex, double, double, c, d, d, tfuncname, varname ) \ GENTFUNC2R( scomplex, dcomplex, double, c, z, d, tfuncname, varname ) \ \ GENTFUNC2R( dcomplex, float, float, z, s, s, tfuncname, varname ) \ GENTFUNC2R( dcomplex, double, double, z, d, d, tfuncname, varname ) \ GENTFUNC2R( dcomplex, scomplex, float, z, c, s, tfuncname, varname ) \ // -- Macros for functions with three primary operands ------------------------- // -- Basic three-operand macro -- // -- (no auxiliary arguments) -- #define INSERT_GENTFUNC3_BASIC0( tfuncname ) \ \ GENTFUNC3( float, float, float, s, s, s, tfuncname ) \ GENTFUNC3( double, double, double, d, d, d, tfuncname ) \ GENTFUNC3( scomplex, scomplex, scomplex, c, c, c, tfuncname ) \ GENTFUNC3( dcomplex, dcomplex, dcomplex, z, z, z, tfuncname ) // -- (one auxiliary argument) -- #define INSERT_GENTFUNC3_BASIC( tfuncname, varname ) \ \ GENTFUNC3( float, float, float, s, s, s, tfuncname, varname ) \ GENTFUNC3( double, double, double, d, d, d, tfuncname, varname ) \ GENTFUNC3( scomplex, scomplex, scomplex, c, c, c, tfuncname, varname ) \ GENTFUNC3( dcomplex, dcomplex, dcomplex, z, z, z, tfuncname, varname ) // -- (two auxiliary arguments) -- #define INSERT_GENTFUNC3_BASIC2( tfuncname, varname1, varname2 ) \ \ GENTFUNC3( float, float, float, s, s, s, tfuncname, varname1, varname2 ) \ GENTFUNC3( double, double, double, d, d, d, tfuncname, varname1, varname2 ) \ GENTFUNC3( scomplex, scomplex, scomplex, c, c, c, tfuncname, varname1, varname2 ) \ GENTFUNC3( dcomplex, dcomplex, dcomplex, z, z, z, tfuncname, varname1, varname2 ) // -- Mixed domain three-operand macro -- // -- (no auxiliary arguments) -- #define INSERT_GENTFUNC3_MIX_D0( tfuncname ) \ \ GENTFUNC3( float, float, scomplex, s, s, c, tfuncname ) \ GENTFUNC3( float, scomplex, float, s, c, s, tfuncname ) \ GENTFUNC3( float, scomplex, scomplex, s, c, c, tfuncname ) \ \ GENTFUNC3( double, double, dcomplex, d, d, z, tfuncname ) \ GENTFUNC3( double, dcomplex, double, d, z, d, tfuncname ) \ GENTFUNC3( double, dcomplex, dcomplex, d, z, z, tfuncname ) \ \ GENTFUNC3( scomplex, float, float, c, s, s, tfuncname ) \ GENTFUNC3( scomplex, float, scomplex, c, s, c, tfuncname ) \ GENTFUNC3( scomplex, scomplex, float, c, c, s, tfuncname ) \ \ GENTFUNC3( dcomplex, double, double, z, d, d, tfuncname ) \ GENTFUNC3( dcomplex, double, dcomplex, z, d, z, tfuncname ) \ GENTFUNC3( dcomplex, dcomplex, double, z, z, d, tfuncname ) // -- (one auxiliary argument) -- #define INSERT_GENTFUNC3_MIX_D( tfuncname, varname ) \ \ GENTFUNC3( float, float, scomplex, s, s, c, tfuncname, varname ) \ GENTFUNC3( float, scomplex, float, s, c, s, tfuncname, varname ) \ GENTFUNC3( float, scomplex, scomplex, s, c, c, tfuncname, varname ) \ \ GENTFUNC3( double, double, dcomplex, d, d, z, tfuncname, varname ) \ GENTFUNC3( double, dcomplex, double, d, z, d, tfuncname, varname ) \ GENTFUNC3( double, dcomplex, dcomplex, d, z, z, tfuncname, varname ) \ \ GENTFUNC3( scomplex, float, float, c, s, s, tfuncname, varname ) \ GENTFUNC3( scomplex, float, scomplex, c, s, c, tfuncname, varname ) \ GENTFUNC3( scomplex, scomplex, float, c, c, s, tfuncname, varname ) \ \ GENTFUNC3( dcomplex, double, double, z, d, d, tfuncname, varname ) \ GENTFUNC3( dcomplex, double, dcomplex, z, d, z, tfuncname, varname ) \ GENTFUNC3( dcomplex, dcomplex, double, z, z, d, tfuncname, varname ) // -- (two auxiliary arguments) -- #define INSERT_GENTFUNC3_MIX_D2( tfuncname, varname1, varname2 ) \ \ GENTFUNC3( float, float, scomplex, s, s, c, tfuncname, varname1, varname2 ) \ GENTFUNC3( float, scomplex, float, s, c, s, tfuncname, varname1, varname2 ) \ GENTFUNC3( float, scomplex, scomplex, s, c, c, tfuncname, varname1, varname2 ) \ \ GENTFUNC3( double, double, dcomplex, d, d, z, tfuncname, varname1, varname2 ) \ GENTFUNC3( double, dcomplex, double, d, z, d, tfuncname, varname1, varname2 ) \ GENTFUNC3( double, dcomplex, dcomplex, d, z, z, tfuncname, varname1, varname2 ) \ \ GENTFUNC3( scomplex, float, float, c, s, s, tfuncname, varname1, varname2 ) \ GENTFUNC3( scomplex, float, scomplex, c, s, c, tfuncname, varname1, varname2 ) \ GENTFUNC3( scomplex, scomplex, float, c, c, s, tfuncname, varname1, varname2 ) \ \ GENTFUNC3( dcomplex, double, double, z, d, d, tfuncname, varname1, varname2 ) \ GENTFUNC3( dcomplex, double, dcomplex, z, d, z, tfuncname, varname1, varname2 ) \ GENTFUNC3( dcomplex, dcomplex, double, z, z, d, tfuncname, varname1, varname2 ) // -- Mixed precision three-operand macro -- // -- (no auxiliary arguments) -- #define INSERT_GENTFUNC3_MIX_P0( tfuncname ) \ \ GENTFUNC3( float, float, double, s, s, d, tfuncname ) \ GENTFUNC3( float, float, dcomplex, s, s, z, tfuncname ) \ \ GENTFUNC3( float, double, float, s, d, s, tfuncname ) \ GENTFUNC3( float, double, double, s, d, d, tfuncname ) \ GENTFUNC3( float, double, scomplex, s, d, c, tfuncname ) \ GENTFUNC3( float, double, dcomplex, s, d, z, tfuncname ) \ \ GENTFUNC3( float, scomplex, double, s, c, d, tfuncname ) \ GENTFUNC3( float, scomplex, dcomplex, s, c, z, tfuncname ) \ \ GENTFUNC3( float, dcomplex, float, s, z, s, tfuncname ) \ GENTFUNC3( float, dcomplex, double, s, z, d, tfuncname ) \ GENTFUNC3( float, dcomplex, scomplex, s, z, c, tfuncname ) \ GENTFUNC3( float, dcomplex, dcomplex, s, z, z, tfuncname ) \ \ \ GENTFUNC3( double, float, float, d, s, s, tfuncname ) \ GENTFUNC3( double, float, double, d, s, d, tfuncname ) \ GENTFUNC3( double, float, scomplex, d, s, c, tfuncname ) \ GENTFUNC3( double, float, dcomplex, d, s, z, tfuncname ) \ \ GENTFUNC3( double, double, float, d, d, s, tfuncname ) \ GENTFUNC3( double, double, scomplex, d, d, c, tfuncname ) \ \ GENTFUNC3( double, scomplex, float, d, c, s, tfuncname ) \ GENTFUNC3( double, scomplex, double, d, c, d, tfuncname ) \ GENTFUNC3( double, scomplex, scomplex, d, c, c, tfuncname ) \ GENTFUNC3( double, scomplex, dcomplex, d, c, z, tfuncname ) \ \ GENTFUNC3( double, dcomplex, float, d, z, s, tfuncname ) \ GENTFUNC3( double, dcomplex, scomplex, d, z, c, tfuncname ) \ \ \ GENTFUNC3( scomplex, float, double, c, s, d, tfuncname ) \ GENTFUNC3( scomplex, float, dcomplex, c, s, z, tfuncname ) \ \ GENTFUNC3( scomplex, double, float, c, d, s, tfuncname ) \ GENTFUNC3( scomplex, double, double, c, d, d, tfuncname ) \ GENTFUNC3( scomplex, double, scomplex, c, d, c, tfuncname ) \ GENTFUNC3( scomplex, double, dcomplex, c, d, z, tfuncname ) \ \ GENTFUNC3( scomplex, scomplex, double, c, c, d, tfuncname ) \ GENTFUNC3( scomplex, scomplex, dcomplex, c, c, z, tfuncname ) \ \ GENTFUNC3( scomplex, dcomplex, float, c, z, s, tfuncname ) \ GENTFUNC3( scomplex, dcomplex, double, c, z, d, tfuncname ) \ GENTFUNC3( scomplex, dcomplex, scomplex, c, z, c, tfuncname ) \ GENTFUNC3( scomplex, dcomplex, dcomplex, c, z, z, tfuncname ) \ \ \ GENTFUNC3( dcomplex, float, float, z, s, s, tfuncname ) \ GENTFUNC3( dcomplex, float, double, z, s, d, tfuncname ) \ GENTFUNC3( dcomplex, float, scomplex, z, s, c, tfuncname ) \ GENTFUNC3( dcomplex, float, dcomplex, z, s, z, tfuncname ) \ \ GENTFUNC3( dcomplex, double, float, z, d, s, tfuncname ) \ GENTFUNC3( dcomplex, double, scomplex, z, d, c, tfuncname ) \ \ GENTFUNC3( dcomplex, scomplex, float, z, c, s, tfuncname ) \ GENTFUNC3( dcomplex, scomplex, double, z, c, d, tfuncname ) \ GENTFUNC3( dcomplex, scomplex, scomplex, z, c, c, tfuncname ) \ GENTFUNC3( dcomplex, scomplex, dcomplex, z, c, z, tfuncname ) \ \ GENTFUNC3( dcomplex, dcomplex, float, z, z, s, tfuncname ) \ GENTFUNC3( dcomplex, dcomplex, scomplex, z, z, c, tfuncname ) // -- (one auxiliary argument) -- #define INSERT_GENTFUNC3_MIX_P( tfuncname, varname ) \ \ GENTFUNC3( float, float, double, s, s, d, tfuncname, varname ) \ GENTFUNC3( float, float, dcomplex, s, s, z, tfuncname, varname ) \ \ GENTFUNC3( float, double, float, s, d, s, tfuncname, varname ) \ GENTFUNC3( float, double, double, s, d, d, tfuncname, varname ) \ GENTFUNC3( float, double, scomplex, s, d, c, tfuncname, varname ) \ GENTFUNC3( float, double, dcomplex, s, d, z, tfuncname, varname ) \ \ GENTFUNC3( float, scomplex, double, s, c, d, tfuncname, varname ) \ GENTFUNC3( float, scomplex, dcomplex, s, c, z, tfuncname, varname ) \ \ GENTFUNC3( float, dcomplex, float, s, z, s, tfuncname, varname ) \ GENTFUNC3( float, dcomplex, double, s, z, d, tfuncname, varname ) \ GENTFUNC3( float, dcomplex, scomplex, s, z, c, tfuncname, varname ) \ GENTFUNC3( float, dcomplex, dcomplex, s, z, z, tfuncname, varname ) \ \ \ GENTFUNC3( double, float, float, d, s, s, tfuncname, varname ) \ GENTFUNC3( double, float, double, d, s, d, tfuncname, varname ) \ GENTFUNC3( double, float, scomplex, d, s, c, tfuncname, varname ) \ GENTFUNC3( double, float, dcomplex, d, s, z, tfuncname, varname ) \ \ GENTFUNC3( double, double, float, d, d, s, tfuncname, varname ) \ GENTFUNC3( double, double, scomplex, d, d, c, tfuncname, varname ) \ \ GENTFUNC3( double, scomplex, float, d, c, s, tfuncname, varname ) \ GENTFUNC3( double, scomplex, double, d, c, d, tfuncname, varname ) \ GENTFUNC3( double, scomplex, scomplex, d, c, c, tfuncname, varname ) \ GENTFUNC3( double, scomplex, dcomplex, d, c, z, tfuncname, varname ) \ \ GENTFUNC3( double, dcomplex, float, d, z, s, tfuncname, varname ) \ GENTFUNC3( double, dcomplex, scomplex, d, z, c, tfuncname, varname ) \ \ \ GENTFUNC3( scomplex, float, double, c, s, d, tfuncname, varname ) \ GENTFUNC3( scomplex, float, dcomplex, c, s, z, tfuncname, varname ) \ \ GENTFUNC3( scomplex, double, float, c, d, s, tfuncname, varname ) \ GENTFUNC3( scomplex, double, double, c, d, d, tfuncname, varname ) \ GENTFUNC3( scomplex, double, scomplex, c, d, c, tfuncname, varname ) \ GENTFUNC3( scomplex, double, dcomplex, c, d, z, tfuncname, varname ) \ \ GENTFUNC3( scomplex, scomplex, double, c, c, d, tfuncname, varname ) \ GENTFUNC3( scomplex, scomplex, dcomplex, c, c, z, tfuncname, varname ) \ \ GENTFUNC3( scomplex, dcomplex, float, c, z, s, tfuncname, varname ) \ GENTFUNC3( scomplex, dcomplex, double, c, z, d, tfuncname, varname ) \ GENTFUNC3( scomplex, dcomplex, scomplex, c, z, c, tfuncname, varname ) \ GENTFUNC3( scomplex, dcomplex, dcomplex, c, z, z, tfuncname, varname ) \ \ \ GENTFUNC3( dcomplex, float, float, z, s, s, tfuncname, varname ) \ GENTFUNC3( dcomplex, float, double, z, s, d, tfuncname, varname ) \ GENTFUNC3( dcomplex, float, scomplex, z, s, c, tfuncname, varname ) \ GENTFUNC3( dcomplex, float, dcomplex, z, s, z, tfuncname, varname ) \ \ GENTFUNC3( dcomplex, double, float, z, d, s, tfuncname, varname ) \ GENTFUNC3( dcomplex, double, scomplex, z, d, c, tfuncname, varname ) \ \ GENTFUNC3( dcomplex, scomplex, float, z, c, s, tfuncname, varname ) \ GENTFUNC3( dcomplex, scomplex, double, z, c, d, tfuncname, varname ) \ GENTFUNC3( dcomplex, scomplex, scomplex, z, c, c, tfuncname, varname ) \ GENTFUNC3( dcomplex, scomplex, dcomplex, z, c, z, tfuncname, varname ) \ \ GENTFUNC3( dcomplex, dcomplex, float, z, z, s, tfuncname, varname ) \ GENTFUNC3( dcomplex, dcomplex, scomplex, z, z, c, tfuncname, varname ) // -- (two auxiliary arguments) -- #define INSERT_GENTFUNC3_MIX_P2( tfuncname, varname1, varname2 ) \ \ GENTFUNC3( float, float, double, s, s, d, tfuncname, varname1, varname2 ) \ GENTFUNC3( float, float, dcomplex, s, s, z, tfuncname, varname1, varname2 ) \ \ GENTFUNC3( float, double, float, s, d, s, tfuncname, varname1, varname2 ) \ GENTFUNC3( float, double, double, s, d, d, tfuncname, varname1, varname2 ) \ GENTFUNC3( float, double, scomplex, s, d, c, tfuncname, varname1, varname2 ) \ GENTFUNC3( float, double, dcomplex, s, d, z, tfuncname, varname1, varname2 ) \ \ GENTFUNC3( float, scomplex, double, s, c, d, tfuncname, varname1, varname2 ) \ GENTFUNC3( float, scomplex, dcomplex, s, c, z, tfuncname, varname1, varname2 ) \ \ GENTFUNC3( float, dcomplex, float, s, z, s, tfuncname, varname1, varname2 ) \ GENTFUNC3( float, dcomplex, double, s, z, d, tfuncname, varname1, varname2 ) \ GENTFUNC3( float, dcomplex, scomplex, s, z, c, tfuncname, varname1, varname2 ) \ GENTFUNC3( float, dcomplex, dcomplex, s, z, z, tfuncname, varname1, varname2 ) \ \ \ GENTFUNC3( double, float, float, d, s, s, tfuncname, varname1, varname2 ) \ GENTFUNC3( double, float, double, d, s, d, tfuncname, varname1, varname2 ) \ GENTFUNC3( double, float, scomplex, d, s, c, tfuncname, varname1, varname2 ) \ GENTFUNC3( double, float, dcomplex, d, s, z, tfuncname, varname1, varname2 ) \ \ GENTFUNC3( double, double, float, d, d, s, tfuncname, varname1, varname2 ) \ GENTFUNC3( double, double, scomplex, d, d, c, tfuncname, varname1, varname2 ) \ \ GENTFUNC3( double, scomplex, float, d, c, s, tfuncname, varname1, varname2 ) \ GENTFUNC3( double, scomplex, double, d, c, d, tfuncname, varname1, varname2 ) \ GENTFUNC3( double, scomplex, scomplex, d, c, c, tfuncname, varname1, varname2 ) \ GENTFUNC3( double, scomplex, dcomplex, d, c, z, tfuncname, varname1, varname2 ) \ \ GENTFUNC3( double, dcomplex, float, d, z, s, tfuncname, varname1, varname2 ) \ GENTFUNC3( double, dcomplex, scomplex, d, z, c, tfuncname, varname1, varname2 ) \ \ \ GENTFUNC3( scomplex, float, double, c, s, d, tfuncname, varname1, varname2 ) \ GENTFUNC3( scomplex, float, dcomplex, c, s, z, tfuncname, varname1, varname2 ) \ \ GENTFUNC3( scomplex, double, float, c, d, s, tfuncname, varname1, varname2 ) \ GENTFUNC3( scomplex, double, double, c, d, d, tfuncname, varname1, varname2 ) \ GENTFUNC3( scomplex, double, scomplex, c, d, c, tfuncname, varname1, varname2 ) \ GENTFUNC3( scomplex, double, dcomplex, c, d, z, tfuncname, varname1, varname2 ) \ \ GENTFUNC3( scomplex, scomplex, double, c, c, d, tfuncname, varname1, varname2 ) \ GENTFUNC3( scomplex, scomplex, dcomplex, c, c, z, tfuncname, varname1, varname2 ) \ \ GENTFUNC3( scomplex, dcomplex, float, c, z, s, tfuncname, varname1, varname2 ) \ GENTFUNC3( scomplex, dcomplex, double, c, z, d, tfuncname, varname1, varname2 ) \ GENTFUNC3( scomplex, dcomplex, scomplex, c, z, c, tfuncname, varname1, varname2 ) \ GENTFUNC3( scomplex, dcomplex, dcomplex, c, z, z, tfuncname, varname1, varname2 ) \ \ \ GENTFUNC3( dcomplex, float, float, z, s, s, tfuncname, varname1, varname2 ) \ GENTFUNC3( dcomplex, float, double, z, s, d, tfuncname, varname1, varname2 ) \ GENTFUNC3( dcomplex, float, scomplex, z, s, c, tfuncname, varname1, varname2 ) \ GENTFUNC3( dcomplex, float, dcomplex, z, s, z, tfuncname, varname1, varname2 ) \ \ GENTFUNC3( dcomplex, double, float, z, d, s, tfuncname, varname1, varname2 ) \ GENTFUNC3( dcomplex, double, scomplex, z, d, c, tfuncname, varname1, varname2 ) \ \ GENTFUNC3( dcomplex, scomplex, float, z, c, s, tfuncname, varname1, varname2 ) \ GENTFUNC3( dcomplex, scomplex, double, z, c, d, tfuncname, varname1, varname2 ) \ GENTFUNC3( dcomplex, scomplex, scomplex, z, c, c, tfuncname, varname1, varname2 ) \ GENTFUNC3( dcomplex, scomplex, dcomplex, z, c, z, tfuncname, varname1, varname2 ) \ \ GENTFUNC3( dcomplex, dcomplex, float, z, z, s, tfuncname, varname1, varname2 ) \ GENTFUNC3( dcomplex, dcomplex, scomplex, z, z, c, tfuncname, varname1, varname2 ) // -- Basic three-operand with union of operands 1 and 2 -- // -- (no auxiliary arguments) -- #define INSERT_GENTFUNC3U12_BASIC0( tfuncname ) \ \ GENTFUNC3U12( float, float, float, float, s, s, s, s, tfuncname ) \ GENTFUNC3U12( double, double, double, double, d, d, d, d, tfuncname ) \ GENTFUNC3U12( scomplex, scomplex, scomplex, scomplex, c, c, c, c, tfuncname ) \ GENTFUNC3U12( dcomplex, dcomplex, dcomplex, dcomplex, z, z, z, z, tfuncname ) // -- (one auxiliary argument) -- #define INSERT_GENTFUNC3U12_BASIC( tfuncname, varname ) \ \ GENTFUNC3U12( float, float, float, float, s, s, s, s, tfuncname, varname ) \ GENTFUNC3U12( double, double, double, double, d, d, d, d, tfuncname, varname ) \ GENTFUNC3U12( scomplex, scomplex, scomplex, scomplex, c, c, c, c, tfuncname, varname ) \ GENTFUNC3U12( dcomplex, dcomplex, dcomplex, dcomplex, z, z, z, z, tfuncname, varname ) // -- (two auxiliary arguments) -- #define INSERT_GENTFUNC3U12_BASIC2( tfuncname, varname1, varname2 ) \ \ GENTFUNC3U12( float, float, float, float, s, s, s, s, tfuncname, varname1, varname2 ) \ GENTFUNC3U12( double, double, double, double, d, d, d, d, tfuncname, varname1, varname2 ) \ GENTFUNC3U12( scomplex, scomplex, scomplex, scomplex, c, c, c, c, tfuncname, varname1, varname2 ) \ GENTFUNC3U12( dcomplex, dcomplex, dcomplex, dcomplex, z, z, z, z, tfuncname, varname1, varname2 ) // -- Mixed domain three-operand with union of operands 1 and 2 -- // -- (no auxiliary arguments) -- #define INSERT_GENTFUNC3U12_MIX_D0( tfuncname ) \ \ GENTFUNC3U12( float, float, scomplex, float, s, s, c, s, tfuncname ) \ GENTFUNC3U12( float, scomplex, float, scomplex, s, c, s, c, tfuncname ) \ GENTFUNC3U12( float, scomplex, scomplex, scomplex, s, c, c, c, tfuncname ) \ \ GENTFUNC3U12( double, double, dcomplex, double, d, d, z, d, tfuncname ) \ GENTFUNC3U12( double, dcomplex, double, dcomplex, d, z, d, z, tfuncname ) \ GENTFUNC3U12( double, dcomplex, dcomplex, dcomplex, d, z, z, z, tfuncname ) \ \ GENTFUNC3U12( scomplex, float, float, scomplex, c, s, s, c, tfuncname ) \ GENTFUNC3U12( scomplex, float, scomplex, scomplex, c, s, c, c, tfuncname ) \ GENTFUNC3U12( scomplex, scomplex, float, scomplex, c, c, s, c, tfuncname ) \ \ GENTFUNC3U12( dcomplex, double, double, dcomplex, z, d, d, z, tfuncname ) \ GENTFUNC3U12( dcomplex, double, dcomplex, dcomplex, z, d, z, z, tfuncname ) \ GENTFUNC3U12( dcomplex, dcomplex, double, dcomplex, z, z, d, z, tfuncname ) // -- (one auxiliary argument) -- #define INSERT_GENTFUNC3U12_MIX_D( tfuncname, varname ) \ \ GENTFUNC3U12( float, float, scomplex, float, s, s, c, s, tfuncname, varname ) \ GENTFUNC3U12( float, scomplex, float, scomplex, s, c, s, c, tfuncname, varname ) \ GENTFUNC3U12( float, scomplex, scomplex, scomplex, s, c, c, c, tfuncname, varname ) \ \ GENTFUNC3U12( double, double, dcomplex, double, d, d, z, d, tfuncname, varname ) \ GENTFUNC3U12( double, dcomplex, double, dcomplex, d, z, d, z, tfuncname, varname ) \ GENTFUNC3U12( double, dcomplex, dcomplex, dcomplex, d, z, z, z, tfuncname, varname ) \ \ GENTFUNC3U12( scomplex, float, float, scomplex, c, s, s, c, tfuncname, varname ) \ GENTFUNC3U12( scomplex, float, scomplex, scomplex, c, s, c, c, tfuncname, varname ) \ GENTFUNC3U12( scomplex, scomplex, float, scomplex, c, c, s, c, tfuncname, varname ) \ \ GENTFUNC3U12( dcomplex, double, double, dcomplex, z, d, d, z, tfuncname, varname ) \ GENTFUNC3U12( dcomplex, double, dcomplex, dcomplex, z, d, z, z, tfuncname, varname ) \ GENTFUNC3U12( dcomplex, dcomplex, double, dcomplex, z, z, d, z, tfuncname, varname ) // -- (two auxiliary arguments) -- #define INSERT_GENTFUNC3U12_MIX_D2( tfuncname, varname1, varname2 ) \ \ GENTFUNC3U12( float, float, scomplex, float, s, s, c, s, tfuncname, varname1, varname2 ) \ GENTFUNC3U12( float, scomplex, float, scomplex, s, c, s, c, tfuncname, varname1, varname2 ) \ GENTFUNC3U12( float, scomplex, scomplex, scomplex, s, c, c, c, tfuncname, varname1, varname2 ) \ \ GENTFUNC3U12( double, double, dcomplex, double, d, d, z, d, tfuncname, varname1, varname2 ) \ GENTFUNC3U12( double, dcomplex, double, dcomplex, d, z, d, z, tfuncname, varname1, varname2 ) \ GENTFUNC3U12( double, dcomplex, dcomplex, dcomplex, d, z, z, z, tfuncname, varname1, varname2 ) \ \ GENTFUNC3U12( scomplex, float, float, scomplex, c, s, s, c, tfuncname, varname1, varname2 ) \ GENTFUNC3U12( scomplex, float, scomplex, scomplex, c, s, c, c, tfuncname, varname1, varname2 ) \ GENTFUNC3U12( scomplex, scomplex, float, scomplex, c, c, s, c, tfuncname, varname1, varname2 ) \ \ GENTFUNC3U12( dcomplex, double, double, dcomplex, z, d, d, z, tfuncname, varname1, varname2 ) \ GENTFUNC3U12( dcomplex, double, dcomplex, dcomplex, z, d, z, z, tfuncname, varname1, varname2 ) \ GENTFUNC3U12( dcomplex, dcomplex, double, dcomplex, z, z, d, z, tfuncname, varname1, varname2 ) // -- Mixed precision three-operand with union of operands 1 and 2 -- // -- (no auxiliary arguments) -- #define INSERT_GENTFUNC3U12_MIX_P0( tfuncname ) \ \ GENTFUNC3U12( float, float, double, float, s, s, d, s, tfuncname ) \ GENTFUNC3U12( float, float, dcomplex, float, s, s, z, s, tfuncname ) \ \ GENTFUNC3U12( float, double, float, double, s, d, s, d, tfuncname ) \ GENTFUNC3U12( float, double, double, double, s, d, d, d, tfuncname ) \ GENTFUNC3U12( float, double, scomplex, double, s, d, c, d, tfuncname ) \ GENTFUNC3U12( float, double, dcomplex, double, s, d, z, d, tfuncname ) \ \ GENTFUNC3U12( float, scomplex, double, scomplex, s, c, d, c, tfuncname ) \ GENTFUNC3U12( float, scomplex, dcomplex, scomplex, s, c, z, c, tfuncname ) \ \ GENTFUNC3U12( float, dcomplex, float, dcomplex, s, z, s, z, tfuncname ) \ GENTFUNC3U12( float, dcomplex, double, dcomplex, s, z, d, z, tfuncname ) \ GENTFUNC3U12( float, dcomplex, scomplex, dcomplex, s, z, c, z, tfuncname ) \ GENTFUNC3U12( float, dcomplex, dcomplex, dcomplex, s, z, z, z, tfuncname ) \ \ \ GENTFUNC3U12( double, float, float, double, d, s, s, d, tfuncname ) \ GENTFUNC3U12( double, float, double, double, d, s, d, d, tfuncname ) \ GENTFUNC3U12( double, float, scomplex, double, d, s, c, d, tfuncname ) \ GENTFUNC3U12( double, float, dcomplex, double, d, s, z, d, tfuncname ) \ \ GENTFUNC3U12( double, double, float, double, d, d, s, d, tfuncname ) \ GENTFUNC3U12( double, double, scomplex, double, d, d, c, d, tfuncname ) \ \ GENTFUNC3U12( double, scomplex, float, dcomplex, d, c, s, z, tfuncname ) \ GENTFUNC3U12( double, scomplex, double, dcomplex, d, c, d, z, tfuncname ) \ GENTFUNC3U12( double, scomplex, scomplex, dcomplex, d, c, c, z, tfuncname ) \ GENTFUNC3U12( double, scomplex, dcomplex, dcomplex, d, c, z, z, tfuncname ) \ \ GENTFUNC3U12( double, dcomplex, float, dcomplex, d, z, s, z, tfuncname ) \ GENTFUNC3U12( double, dcomplex, scomplex, dcomplex, d, z, c, z, tfuncname ) \ \ \ GENTFUNC3U12( scomplex, float, double, scomplex, c, s, d, c, tfuncname ) \ GENTFUNC3U12( scomplex, float, dcomplex, scomplex, c, s, z, c, tfuncname ) \ \ GENTFUNC3U12( scomplex, double, float, dcomplex, c, d, s, z, tfuncname ) \ GENTFUNC3U12( scomplex, double, double, dcomplex, c, d, d, z, tfuncname ) \ GENTFUNC3U12( scomplex, double, scomplex, dcomplex, c, d, c, z, tfuncname ) \ GENTFUNC3U12( scomplex, double, dcomplex, dcomplex, c, d, z, z, tfuncname ) \ \ GENTFUNC3U12( scomplex, scomplex, double, scomplex, c, c, d, c, tfuncname ) \ GENTFUNC3U12( scomplex, scomplex, dcomplex, scomplex, c, c, z, c, tfuncname ) \ \ GENTFUNC3U12( scomplex, dcomplex, float, dcomplex, c, z, s, z, tfuncname ) \ GENTFUNC3U12( scomplex, dcomplex, double, dcomplex, c, z, d, z, tfuncname ) \ GENTFUNC3U12( scomplex, dcomplex, scomplex, dcomplex, c, z, c, z, tfuncname ) \ GENTFUNC3U12( scomplex, dcomplex, dcomplex, dcomplex, c, z, z, z, tfuncname ) \ \ \ GENTFUNC3U12( dcomplex, float, float, dcomplex, z, s, s, z, tfuncname ) \ GENTFUNC3U12( dcomplex, float, double, dcomplex, z, s, d, z, tfuncname ) \ GENTFUNC3U12( dcomplex, float, scomplex, dcomplex, z, s, c, z, tfuncname ) \ GENTFUNC3U12( dcomplex, float, dcomplex, dcomplex, z, s, z, z, tfuncname ) \ \ GENTFUNC3U12( dcomplex, double, float, dcomplex, z, d, s, z, tfuncname ) \ GENTFUNC3U12( dcomplex, double, scomplex, dcomplex, z, d, c, z, tfuncname ) \ \ GENTFUNC3U12( dcomplex, scomplex, float, dcomplex, z, c, s, z, tfuncname ) \ GENTFUNC3U12( dcomplex, scomplex, double, dcomplex, z, c, d, z, tfuncname ) \ GENTFUNC3U12( dcomplex, scomplex, scomplex, dcomplex, z, c, c, z, tfuncname ) \ GENTFUNC3U12( dcomplex, scomplex, dcomplex, dcomplex, z, c, z, z, tfuncname ) \ \ GENTFUNC3U12( dcomplex, dcomplex, float, dcomplex, z, z, s, z, tfuncname ) \ GENTFUNC3U12( dcomplex, dcomplex, scomplex, dcomplex, z, z, c, z, tfuncname ) // -- (one auxiliary argument) -- #define INSERT_GENTFUNC3U12_MIX_P( tfuncname, varname ) \ \ GENTFUNC3U12( float, float, double, float, s, s, d, s, tfuncname, varname ) \ GENTFUNC3U12( float, float, dcomplex, float, s, s, z, s, tfuncname, varname ) \ \ GENTFUNC3U12( float, double, float, double, s, d, s, d, tfuncname, varname ) \ GENTFUNC3U12( float, double, double, double, s, d, d, d, tfuncname, varname ) \ GENTFUNC3U12( float, double, scomplex, double, s, d, c, d, tfuncname, varname ) \ GENTFUNC3U12( float, double, dcomplex, double, s, d, z, d, tfuncname, varname ) \ \ GENTFUNC3U12( float, scomplex, double, scomplex, s, c, d, c, tfuncname, varname ) \ GENTFUNC3U12( float, scomplex, dcomplex, scomplex, s, c, z, c, tfuncname, varname ) \ \ GENTFUNC3U12( float, dcomplex, float, dcomplex, s, z, s, z, tfuncname, varname ) \ GENTFUNC3U12( float, dcomplex, double, dcomplex, s, z, d, z, tfuncname, varname ) \ GENTFUNC3U12( float, dcomplex, scomplex, dcomplex, s, z, c, z, tfuncname, varname ) \ GENTFUNC3U12( float, dcomplex, dcomplex, dcomplex, s, z, z, z, tfuncname, varname ) \ \ \ GENTFUNC3U12( double, float, float, double, d, s, s, d, tfuncname, varname ) \ GENTFUNC3U12( double, float, double, double, d, s, d, d, tfuncname, varname ) \ GENTFUNC3U12( double, float, scomplex, double, d, s, c, d, tfuncname, varname ) \ GENTFUNC3U12( double, float, dcomplex, double, d, s, z, d, tfuncname, varname ) \ \ GENTFUNC3U12( double, double, float, double, d, d, s, d, tfuncname, varname ) \ GENTFUNC3U12( double, double, scomplex, double, d, d, c, d, tfuncname, varname ) \ \ GENTFUNC3U12( double, scomplex, float, dcomplex, d, c, s, z, tfuncname, varname ) \ GENTFUNC3U12( double, scomplex, double, dcomplex, d, c, d, z, tfuncname, varname ) \ GENTFUNC3U12( double, scomplex, scomplex, dcomplex, d, c, c, z, tfuncname, varname ) \ GENTFUNC3U12( double, scomplex, dcomplex, dcomplex, d, c, z, z, tfuncname, varname ) \ \ GENTFUNC3U12( double, dcomplex, float, dcomplex, d, z, s, z, tfuncname, varname ) \ GENTFUNC3U12( double, dcomplex, scomplex, dcomplex, d, z, c, z, tfuncname, varname ) \ \ \ GENTFUNC3U12( scomplex, float, double, scomplex, c, s, d, c, tfuncname, varname ) \ GENTFUNC3U12( scomplex, float, dcomplex, scomplex, c, s, z, c, tfuncname, varname ) \ \ GENTFUNC3U12( scomplex, double, float, dcomplex, c, d, s, z, tfuncname, varname ) \ GENTFUNC3U12( scomplex, double, double, dcomplex, c, d, d, z, tfuncname, varname ) \ GENTFUNC3U12( scomplex, double, scomplex, dcomplex, c, d, c, z, tfuncname, varname ) \ GENTFUNC3U12( scomplex, double, dcomplex, dcomplex, c, d, z, z, tfuncname, varname ) \ \ GENTFUNC3U12( scomplex, scomplex, double, scomplex, c, c, d, c, tfuncname, varname ) \ GENTFUNC3U12( scomplex, scomplex, dcomplex, scomplex, c, c, z, c, tfuncname, varname ) \ \ GENTFUNC3U12( scomplex, dcomplex, float, dcomplex, c, z, s, z, tfuncname, varname ) \ GENTFUNC3U12( scomplex, dcomplex, double, dcomplex, c, z, d, z, tfuncname, varname ) \ GENTFUNC3U12( scomplex, dcomplex, scomplex, dcomplex, c, z, c, z, tfuncname, varname ) \ GENTFUNC3U12( scomplex, dcomplex, dcomplex, dcomplex, c, z, z, z, tfuncname, varname ) \ \ \ GENTFUNC3U12( dcomplex, float, float, dcomplex, z, s, s, z, tfuncname, varname ) \ GENTFUNC3U12( dcomplex, float, double, dcomplex, z, s, d, z, tfuncname, varname ) \ GENTFUNC3U12( dcomplex, float, scomplex, dcomplex, z, s, c, z, tfuncname, varname ) \ GENTFUNC3U12( dcomplex, float, dcomplex, dcomplex, z, s, z, z, tfuncname, varname ) \ \ GENTFUNC3U12( dcomplex, double, float, dcomplex, z, d, s, z, tfuncname, varname ) \ GENTFUNC3U12( dcomplex, double, scomplex, dcomplex, z, d, c, z, tfuncname, varname ) \ \ GENTFUNC3U12( dcomplex, scomplex, float, dcomplex, z, c, s, z, tfuncname, varname ) \ GENTFUNC3U12( dcomplex, scomplex, double, dcomplex, z, c, d, z, tfuncname, varname ) \ GENTFUNC3U12( dcomplex, scomplex, scomplex, dcomplex, z, c, c, z, tfuncname, varname ) \ GENTFUNC3U12( dcomplex, scomplex, dcomplex, dcomplex, z, c, z, z, tfuncname, varname ) \ \ GENTFUNC3U12( dcomplex, dcomplex, float, dcomplex, z, z, s, z, tfuncname, varname ) \ GENTFUNC3U12( dcomplex, dcomplex, scomplex, dcomplex, z, z, c, z, tfuncname, varname ) // -- (two auxiliary arguments) -- #define INSERT_GENTFUNC3U12_MIX_P2( tfuncname, varname1, varname2 ) \ \ GENTFUNC3U12( float, float, double, float, s, s, d, s, tfuncname, varname1, varname2 ) \ GENTFUNC3U12( float, float, dcomplex, float, s, s, z, s, tfuncname, varname1, varname2 ) \ \ GENTFUNC3U12( float, double, float, double, s, d, s, d, tfuncname, varname1, varname2 ) \ GENTFUNC3U12( float, double, double, double, s, d, d, d, tfuncname, varname1, varname2 ) \ GENTFUNC3U12( float, double, scomplex, double, s, d, c, d, tfuncname, varname1, varname2 ) \ GENTFUNC3U12( float, double, dcomplex, double, s, d, z, d, tfuncname, varname1, varname2 ) \ \ GENTFUNC3U12( float, scomplex, double, scomplex, s, c, d, c, tfuncname, varname1, varname2 ) \ GENTFUNC3U12( float, scomplex, dcomplex, scomplex, s, c, z, c, tfuncname, varname1, varname2 ) \ \ GENTFUNC3U12( float, dcomplex, float, dcomplex, s, z, s, z, tfuncname, varname1, varname2 ) \ GENTFUNC3U12( float, dcomplex, double, dcomplex, s, z, d, z, tfuncname, varname1, varname2 ) \ GENTFUNC3U12( float, dcomplex, scomplex, dcomplex, s, z, c, z, tfuncname, varname1, varname2 ) \ GENTFUNC3U12( float, dcomplex, dcomplex, dcomplex, s, z, z, z, tfuncname, varname1, varname2 ) \ \ \ GENTFUNC3U12( double, float, float, double, d, s, s, d, tfuncname, varname1, varname2 ) \ GENTFUNC3U12( double, float, double, double, d, s, d, d, tfuncname, varname1, varname2 ) \ GENTFUNC3U12( double, float, scomplex, double, d, s, c, d, tfuncname, varname1, varname2 ) \ GENTFUNC3U12( double, float, dcomplex, double, d, s, z, d, tfuncname, varname1, varname2 ) \ \ GENTFUNC3U12( double, double, float, double, d, d, s, d, tfuncname, varname1, varname2 ) \ GENTFUNC3U12( double, double, scomplex, double, d, d, c, d, tfuncname, varname1, varname2 ) \ \ GENTFUNC3U12( double, scomplex, float, dcomplex, d, c, s, z, tfuncname, varname1, varname2 ) \ GENTFUNC3U12( double, scomplex, double, dcomplex, d, c, d, z, tfuncname, varname1, varname2 ) \ GENTFUNC3U12( double, scomplex, scomplex, dcomplex, d, c, c, z, tfuncname, varname1, varname2 ) \ GENTFUNC3U12( double, scomplex, dcomplex, dcomplex, d, c, z, z, tfuncname, varname1, varname2 ) \ \ GENTFUNC3U12( double, dcomplex, float, dcomplex, d, z, s, z, tfuncname, varname1, varname2 ) \ GENTFUNC3U12( double, dcomplex, scomplex, dcomplex, d, z, c, z, tfuncname, varname1, varname2 ) \ \ \ GENTFUNC3U12( scomplex, float, double, scomplex, c, s, d, c, tfuncname, varname1, varname2 ) \ GENTFUNC3U12( scomplex, float, dcomplex, scomplex, c, s, z, c, tfuncname, varname1, varname2 ) \ \ GENTFUNC3U12( scomplex, double, float, dcomplex, c, d, s, z, tfuncname, varname1, varname2 ) \ GENTFUNC3U12( scomplex, double, double, dcomplex, c, d, d, z, tfuncname, varname1, varname2 ) \ GENTFUNC3U12( scomplex, double, scomplex, dcomplex, c, d, c, z, tfuncname, varname1, varname2 ) \ GENTFUNC3U12( scomplex, double, dcomplex, dcomplex, c, d, z, z, tfuncname, varname1, varname2 ) \ \ GENTFUNC3U12( scomplex, scomplex, double, scomplex, c, c, d, c, tfuncname, varname1, varname2 ) \ GENTFUNC3U12( scomplex, scomplex, dcomplex, scomplex, c, c, z, c, tfuncname, varname1, varname2 ) \ \ GENTFUNC3U12( scomplex, dcomplex, float, dcomplex, c, z, s, z, tfuncname, varname1, varname2 ) \ GENTFUNC3U12( scomplex, dcomplex, double, dcomplex, c, z, d, z, tfuncname, varname1, varname2 ) \ GENTFUNC3U12( scomplex, dcomplex, scomplex, dcomplex, c, z, c, z, tfuncname, varname1, varname2 ) \ GENTFUNC3U12( scomplex, dcomplex, dcomplex, dcomplex, c, z, z, z, tfuncname, varname1, varname2 ) \ \ \ GENTFUNC3U12( dcomplex, float, float, dcomplex, z, s, s, z, tfuncname, varname1, varname2 ) \ GENTFUNC3U12( dcomplex, float, double, dcomplex, z, s, d, z, tfuncname, varname1, varname2 ) \ GENTFUNC3U12( dcomplex, float, scomplex, dcomplex, z, s, c, z, tfuncname, varname1, varname2 ) \ GENTFUNC3U12( dcomplex, float, dcomplex, dcomplex, z, s, z, z, tfuncname, varname1, varname2 ) \ \ GENTFUNC3U12( dcomplex, double, float, dcomplex, z, d, s, z, tfuncname, varname1, varname2 ) \ GENTFUNC3U12( dcomplex, double, scomplex, dcomplex, z, d, c, z, tfuncname, varname1, varname2 ) \ \ GENTFUNC3U12( dcomplex, scomplex, float, dcomplex, z, c, s, z, tfuncname, varname1, varname2 ) \ GENTFUNC3U12( dcomplex, scomplex, double, dcomplex, z, c, d, z, tfuncname, varname1, varname2 ) \ GENTFUNC3U12( dcomplex, scomplex, scomplex, dcomplex, z, c, c, z, tfuncname, varname1, varname2 ) \ GENTFUNC3U12( dcomplex, scomplex, dcomplex, dcomplex, z, c, z, z, tfuncname, varname1, varname2 ) \ \ GENTFUNC3U12( dcomplex, dcomplex, float, dcomplex, z, z, s, z, tfuncname, varname1, varname2 ) \ GENTFUNC3U12( dcomplex, dcomplex, scomplex, dcomplex, z, z, c, z, tfuncname, varname1, varname2 ) #endif blis-0.9.0/frame/include/bli_gentprot_macro_defs.h000066400000000000000000000654261422157504600222340ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_GENTPROT_MACRO_DEFS_H #define BLIS_GENTPROT_MACRO_DEFS_H // // -- MACROS TO INSERT PROTOTYPE-GENERATING MACROS ----------------------------- // // -- Macros for generating BLAS routines -------------------------------------- // -- Basic one-operand macro -- #define INSERT_GENTPROT_BLAS( blasname ) \ \ GENTPROT( float, s, blasname ) \ GENTPROT( double, d, blasname ) \ GENTPROT( scomplex, c, blasname ) \ GENTPROT( dcomplex, z, blasname ) // -- Basic one-operand macro with real domain only -- #define INSERT_GENTPROTRO_BLAS( blasname ) \ \ GENTPROTRO( float, s, blasname ) \ GENTPROTRO( double, d, blasname ) // -- Basic one-operand macro with complex domain only and real projection -- #define INSERT_GENTPROTCO_BLAS( blasname ) \ \ GENTPROTCO( scomplex, float, c, s, blasname ) \ GENTPROTCO( dcomplex, double, z, d, blasname ) // -- Basic one-operand macro with conjugation (real funcs only, used only for dot, ger) -- #define INSERT_GENTPROTDOTR_BLAS( blasname ) \ \ GENTPROTDOT( float, s, , blasname ) \ GENTPROTDOT( double, d, , blasname ) // -- Basic one-operand macro with conjugation (complex funcs only, used only for dot, ger) -- #define INSERT_GENTPROTDOTC_BLAS( blasname ) \ \ GENTPROTDOT( scomplex, c, c, blasname ) \ GENTPROTDOT( scomplex, c, u, blasname ) \ GENTPROTDOT( dcomplex, z, c, blasname ) \ GENTPROTDOT( dcomplex, z, u, blasname ) // -- Basic one-operand macro with conjugation (used only for dot, ger) -- #define INSERT_GENTPROTDOT_BLAS( blasname ) \ \ INSERT_GENTPROTDOTR_BLAS( blasname ) \ INSERT_GENTPROTDOTC_BLAS( blasname ) // -- Basic one-operand macro with real projection -- #define INSERT_GENTPROTR_BLAS( rblasname, cblasname ) \ \ GENTPROTR( float, float, s, s, rblasname ) \ GENTPROTR( double, double, d, d, rblasname ) \ GENTPROTR( scomplex, float, c, s, cblasname ) \ GENTPROTR( dcomplex, double, z, d, cblasname ) // -- Alternate two-operand macro (one char for complex, one for real proj) -- #define INSERT_GENTPROTR2_BLAS( blasname ) \ \ GENTPROTR2( float, float, , s, blasname ) \ GENTPROTR2( double, double, , d, blasname ) \ GENTPROTR2( scomplex, float, c, s, blasname ) \ GENTPROTR2( dcomplex, double, z, d, blasname ) // -- Extended two-operand macro (used only for scal) -- #define INSERT_GENTPROTSCAL_BLAS( blasname ) \ \ GENTPROTSCAL( float, float, , s, blasname ) \ GENTPROTSCAL( double, double, , d, blasname ) \ GENTPROTSCAL( scomplex, scomplex, , c, blasname ) \ GENTPROTSCAL( dcomplex, dcomplex, , z, blasname ) \ GENTPROTSCAL( float, scomplex, s, c, blasname ) \ GENTPROTSCAL( double, dcomplex, d, z, blasname ) // -- Macros for functions with one operand ------------------------------------ // -- Basic one-operand macro -- // -- (no auxiliary arguments) -- #define INSERT_GENTPROT_BASIC0( tfuncname ) \ \ GENTPROT( float, s, tfuncname ) \ GENTPROT( double, d, tfuncname ) \ GENTPROT( scomplex, c, tfuncname ) \ GENTPROT( dcomplex, z, tfuncname ) // -- (one auxiliary argument) -- #define INSERT_GENTPROT_BASIC( tfuncname, varname ) \ \ GENTPROT( float, s, tfuncname, varname ) \ GENTPROT( double, d, tfuncname, varname ) \ GENTPROT( scomplex, c, tfuncname, varname ) \ GENTPROT( dcomplex, z, tfuncname, varname ) // -- (two auxiliary arguments) -- #define INSERT_GENTPROT_BASIC2( tfuncname, varname1, varname2 ) \ \ GENTPROT( float, s, tfuncname, varname1, varname2 ) \ GENTPROT( double, d, tfuncname, varname1, varname2 ) \ GENTPROT( scomplex, c, tfuncname, varname1, varname2 ) \ GENTPROT( dcomplex, z, tfuncname, varname1, varname2 ) // -- (three auxiliary arguments) -- #define INSERT_GENTPROT_BASIC3( tfuncname, varname1, varname2, varname3 ) \ \ GENTPROT( float, s, tfuncname, varname1, varname2, varname3 ) \ GENTPROT( double, d, tfuncname, varname1, varname2, varname3 ) \ GENTPROT( scomplex, c, tfuncname, varname1, varname2, varname3 ) \ GENTPROT( dcomplex, z, tfuncname, varname1, varname2, varname3 ) // -- (four auxiliary arguments) -- #define INSERT_GENTPROT_BASIC4( tfuncname, varname1, varname2, varname3, varname4 ) \ \ GENTPROT( float, s, tfuncname, varname1, varname2, varname3, varname4 ) \ GENTPROT( double, d, tfuncname, varname1, varname2, varname3, varname4 ) \ GENTPROT( scomplex, c, tfuncname, varname1, varname2, varname3, varname4 ) \ GENTPROT( dcomplex, z, tfuncname, varname1, varname2, varname3, varname4 ) // -- Basic one-operand with real projection -- // -- (no auxiliary arguments) -- #define INSERT_GENTPROTR_BASIC0( tfuncname ) \ \ GENTPROTR( float, float, s, s, tfuncname ) \ GENTPROTR( double, double, d, d, tfuncname ) \ GENTPROTR( scomplex, float, c, s, tfuncname ) \ GENTPROTR( dcomplex, double, z, d, tfuncname ) // -- (one auxiliary argument) -- #define INSERT_GENTPROTR_BASIC( tfuncname, varname ) \ \ GENTPROTR( float, float, s, s, tfuncname, varname ) \ GENTPROTR( double, double, d, d, tfuncname, varname ) \ GENTPROTR( scomplex, float, c, s, tfuncname, varname ) \ GENTPROTR( dcomplex, double, z, d, tfuncname, varname ) // -- (two auxiliary arguments) -- #define INSERT_GENTPROTR_BASIC2( tfuncname, varname1, varname2 ) \ \ GENTPROTR( float, float, s, s, tfuncname, varname1, varname2 ) \ GENTPROTR( double, double, d, d, tfuncname, varname1, varname2 ) \ GENTPROTR( scomplex, float, c, s, tfuncname, varname1, varname2 ) \ GENTPROTR( dcomplex, double, z, d, tfuncname, varname1, varname2 ) // -- (three auxiliary arguments) -- #define INSERT_GENTPROTR_BASIC3( tfuncname, varname1, varname2, varname3 ) \ \ GENTPROTR( float, float, s, s, tfuncname, varname1, varname2, varname3 ) \ GENTPROTR( double, double, d, d, tfuncname, varname1, varname2, varname3 ) \ GENTPROTR( scomplex, float, c, s, tfuncname, varname1, varname2, varname3 ) \ GENTPROTR( dcomplex, double, z, d, tfuncname, varname1, varname2, varname3 ) // -- (four auxiliary arguments) -- #define INSERT_GENTPROTR_BASIC4( tfuncname, varname1, varname2, varname3, varname4 ) \ \ GENTPROTR( float, float, s, s, tfuncname, varname1, varname2, varname3, varname4 ) \ GENTPROTR( double, double, d, d, tfuncname, varname1, varname2, varname3, varname4 ) \ GENTPROTR( scomplex, float, c, s, tfuncname, varname1, varname2, varname3, varname4 ) \ GENTPROTR( dcomplex, double, z, d, tfuncname, varname1, varname2, varname3, varname4 ) // -- Basic one-operand macro with complex domain only and real projection -- // -- (no auxiliary arguments) -- #define INSERT_GENTPROTCO_BASIC0( tfuncname ) \ \ GENTPROTCO( scomplex, float, c, s, tfuncname ) \ GENTPROTCO( dcomplex, double, z, d, tfuncname ) // -- (one auxiliary argument) -- #define INSERT_GENTPROTCO_BASIC( tfuncname, varname ) \ \ GENTPROTCO( scomplex, float, c, s, tfuncname, varname ) \ GENTPROTCO( dcomplex, double, z, d, tfuncname, varname ) // -- (two auxiliary arguments) -- #define INSERT_GENTPROTCO_BASIC2( tfuncname, varname1, varname2 ) \ \ GENTPROTCO( scomplex, float, c, s, tfuncname, varname1, varname2 ) \ GENTPROTCO( dcomplex, double, z, d, tfuncname, varname1, varname2 ) // -- Basic one-operand macro with integer instance -- // -- (no auxiliary arguments) -- #define INSERT_GENTPROT_BASIC0_I( funcname ) \ \ GENTPROT( float, s, funcname ) \ GENTPROT( double, d, funcname ) \ GENTPROT( scomplex, c, funcname ) \ GENTPROT( dcomplex, z, funcname ) \ GENTPROT( gint_t, i, funcname ) // -- (one auxiliary argument) -- #define INSERT_GENTPROT_BASIC_I( tfuncname, varname ) \ \ GENTPROT( float, s, tfuncname, varname ) \ GENTPROT( double, d, tfuncname, varname ) \ GENTPROT( scomplex, c, tfuncname, varname ) \ GENTPROT( dcomplex, z, tfuncname, varname ) \ GENTPROT( gint_t, i, tfuncname, varname ) // -- Basic one-operand with integer projection -- // -- (no auxiliary arguments) -- #define INSERT_GENTPROTI_BASIC0( funcname ) \ \ GENTPROTI( float, gint_t, s, i, funcname ) \ GENTPROTI( double, gint_t, d, i, funcname ) \ GENTPROTI( scomplex, gint_t, c, i, funcname ) \ GENTPROTI( dcomplex, gint_t, z, i, funcname ) // -- (one auxiliary argument) -- #define INSERT_GENTPROTI_BASIC( tfuncname, varname ) \ \ GENTPROTI( float, gint_t, s, i, tfuncname, varname ) \ GENTPROTI( double, gint_t, d, i, tfuncname, varname ) \ GENTPROTI( scomplex, gint_t, c, i, tfuncname, varname ) \ GENTPROTI( dcomplex, gint_t, z, i, tfuncname, varname ) // -- Basic one-operand with real and integer projections -- // -- (no auxiliary arguments) -- #define INSERT_GENTPROTRI_BASIC( funcname ) \ \ GENTPROTRI( float, float, gint_t, s, s, i, funcname ) \ GENTPROTRI( double, double, gint_t, d, d, i, funcname ) \ GENTPROTRI( scomplex, float, gint_t, c, s, i, funcname ) \ GENTPROTRI( dcomplex, double, gint_t, z, d, i, funcname ) // -- Macros for functions with two primary operands --------------------------- // -- Basic two-operand macro -- // -- (no auxiliary arguments) -- #define INSERT_GENTPROT2_BASIC0( funcname ) \ \ GENTPROT2( float, float, s, s, funcname ) \ GENTPROT2( double, double, d, d, funcname ) \ GENTPROT2( scomplex, scomplex, c, c, funcname ) \ GENTPROT2( dcomplex, dcomplex, z, z, funcname ) // -- (one auxiliary argument) -- #define INSERT_GENTPROT2_BASIC( tfuncname, varname ) \ \ GENTPROT2( float, float, s, s, tfuncname, varname ) \ GENTPROT2( double, double, d, d, tfuncname, varname ) \ GENTPROT2( scomplex, scomplex, c, c, tfuncname, varname ) \ GENTPROT2( dcomplex, dcomplex, z, z, tfuncname, varname ) // -- Mixed domain two-operand macro -- // -- (no auxiliary arguments) -- #define INSERT_GENTPROT2_MIX_D0( funcname ) \ \ GENTPROT2( float, scomplex, s, c, funcname ) \ GENTPROT2( scomplex, float, c, s, funcname ) \ \ GENTPROT2( double, dcomplex, d, z, funcname ) \ GENTPROT2( dcomplex, double, z, d, funcname ) // -- (one auxiliary argument) -- #define INSERT_GENTPROT2_MIX_D( tfuncname, varname ) \ \ GENTPROT2( float, scomplex, s, c, tfuncname, varname ) \ GENTPROT2( scomplex, float, c, s, tfuncname, varname ) \ \ GENTPROT2( double, dcomplex, d, z, tfuncname, varname ) \ GENTPROT2( dcomplex, double, z, d, tfuncname, varname ) // -- Mixed precision two-operand macro -- // -- (no auxiliary arguments) -- #define INSERT_GENTPROT2_MIX_P0( funcname ) \ \ GENTPROT2( float, double, s, d, funcname ) \ GENTPROT2( float, dcomplex, s, z, funcname ) \ \ GENTPROT2( double, float, d, s, funcname ) \ GENTPROT2( double, scomplex, d, c, funcname ) \ \ GENTPROT2( scomplex, double, c, d, funcname ) \ GENTPROT2( scomplex, dcomplex, c, z, funcname ) \ \ GENTPROT2( dcomplex, float, z, s, funcname ) \ GENTPROT2( dcomplex, scomplex, z, c, funcname ) \ // -- (one auxiliary argument) -- #define INSERT_GENTPROT2_MIX_P( tfuncname, varname ) \ \ GENTPROT2( float, double, s, d, tfuncname, varname ) \ GENTPROT2( float, dcomplex, s, z, tfuncname, varname ) \ \ GENTPROT2( double, float, d, s, tfuncname, varname ) \ GENTPROT2( double, scomplex, d, c, tfuncname, varname ) \ \ GENTPROT2( scomplex, double, c, d, tfuncname, varname ) \ GENTPROT2( scomplex, dcomplex, c, z, tfuncname, varname ) \ \ GENTPROT2( dcomplex, float, z, s, tfuncname, varname ) \ GENTPROT2( dcomplex, scomplex, z, c, tfuncname, varname ) \ // -- Mixed domain/precision (all) two-operand macro -- // -- (no auxiliary arguments) -- #define INSERT_GENTPROT2_MIXDP0( funcname ) \ \ GENTPROT2( float, double, s, d, funcname ) \ GENTPROT2( float, scomplex, s, c, funcname ) \ GENTPROT2( float, dcomplex, s, z, funcname ) \ \ GENTPROT2( double, float, d, s, funcname ) \ GENTPROT2( double, scomplex, d, c, funcname ) \ GENTPROT2( double, dcomplex, d, z, funcname ) \ \ GENTPROT2( scomplex, float, c, s, funcname ) \ GENTPROT2( scomplex, double, c, d, funcname ) \ GENTPROT2( scomplex, dcomplex, c, z, funcname ) \ \ GENTPROT2( dcomplex, float, z, s, funcname ) \ GENTPROT2( dcomplex, double, z, d, funcname ) \ GENTPROT2( dcomplex, scomplex, z, c, funcname ) // -- (one auxiliary argument) -- #define INSERT_GENTPROT2_MIX_DP( tfuncname, varname ) \ \ GENTPROT2( float, double, s, d, tfuncname, varname ) \ GENTPROT2( float, scomplex, s, c, tfuncname, varname ) \ GENTPROT2( float, dcomplex, s, z, tfuncname, varname ) \ \ GENTPROT2( double, float, d, s, tfuncname, varname ) \ GENTPROT2( double, scomplex, d, c, tfuncname, varname ) \ GENTPROT2( double, dcomplex, d, z, tfuncname, varname ) \ \ GENTPROT2( scomplex, float, c, s, tfuncname, varname ) \ GENTPROT2( scomplex, double, c, d, tfuncname, varname ) \ GENTPROT2( scomplex, dcomplex, c, z, tfuncname, varname ) \ \ GENTPROT2( dcomplex, float, z, s, tfuncname, varname ) \ GENTPROT2( dcomplex, double, z, d, tfuncname, varname ) \ GENTPROT2( dcomplex, scomplex, z, c, tfuncname, varname ) // -- Basic two-operand with real projection of first operand -- // -- (no auxiliary arguments) -- #define INSERT_GENTPROT2R_BASIC0( funcname ) \ \ GENTPROT2R( float, float, float, s, s, s, funcname ) \ GENTPROT2R( double, double, double, d, d, d, funcname ) \ GENTPROT2R( scomplex, scomplex, float, c, c, s, funcname ) \ GENTPROT2R( dcomplex, dcomplex, double, z, z, d, funcname ) // -- (one auxiliary argument) -- #define INSERT_GENTPROT2R_BASIC( tfuncname, varname ) \ \ GENTPROT2R( float, float, float, s, s, s, tfuncname, varname ) \ GENTPROT2R( double, double, double, d, d, d, tfuncname, varname ) \ GENTPROT2R( scomplex, scomplex, float, c, c, s, tfuncname, varname ) \ GENTPROT2R( dcomplex, dcomplex, double, z, z, d, tfuncname, varname ) // -- Mixed domain two-operand with real projection of first operand -- // -- (no auxiliary arguments) -- #define INSERT_GENTPROT2R_MIX_D0( tfuncname ) \ \ GENTPROT2R( float, scomplex, float, s, c, s, tfuncname ) \ GENTPROT2R( scomplex, float, float, c, s, s, tfuncname ) \ \ GENTPROT2R( double, dcomplex, double, d, z, d, tfuncname ) \ GENTPROT2R( dcomplex, double, double, z, d, d, tfuncname ) // -- (one auxiliary argument) -- #define INSERT_GENTPROT2R_MIX_D( tfuncname, varname ) \ \ GENTPROT2R( float, scomplex, float, s, c, s, tfuncname, varname ) \ GENTPROT2R( scomplex, float, float, c, s, s, tfuncname, varname ) \ \ GENTPROT2R( double, dcomplex, double, d, z, d, tfuncname, varname ) \ GENTPROT2R( dcomplex, double, double, z, d, d, tfuncname, varname ) // -- Mixed precision two-operand with real projection of first operand -- // -- (no auxiliary arguments) -- #define INSERT_GENTPROT2R_MIX_P0( tfuncname ) \ \ GENTPROT2R( float, double, float, s, d, s, tfuncname ) \ GENTPROT2R( float, dcomplex, float, s, z, s, tfuncname ) \ \ GENTPROT2R( double, float, double, d, s, d, tfuncname ) \ GENTPROT2R( double, scomplex, double, d, c, d, tfuncname ) \ \ GENTPROT2R( scomplex, double, float, c, d, s, tfuncname ) \ GENTPROT2R( scomplex, dcomplex, float, c, z, s, tfuncname ) \ \ GENTPROT2R( dcomplex, float, double, z, s, d, tfuncname ) \ GENTPROT2R( dcomplex, scomplex, double, z, c, d, tfuncname ) // -- (one auxiliary argument) -- #define INSERT_GENTPROT2R_MIX_P( tfuncname, varname ) \ \ GENTPROT2R( float, double, float, s, d, s, tfuncname, varname ) \ GENTPROT2R( float, dcomplex, float, s, z, s, tfuncname, varname ) \ \ GENTPROT2R( double, float, double, d, s, d, tfuncname, varname ) \ GENTPROT2R( double, scomplex, double, d, c, d, tfuncname, varname ) \ \ GENTPROT2R( scomplex, double, float, c, d, s, tfuncname, varname ) \ GENTPROT2R( scomplex, dcomplex, float, c, z, s, tfuncname, varname ) \ \ GENTPROT2R( dcomplex, float, double, z, s, d, tfuncname, varname ) \ GENTPROT2R( dcomplex, scomplex, double, z, c, d, tfuncname, varname ) // -- Macros for functions with three primary operands ------------------------- // -- Basic three-operand macro -- #define INSERT_GENTPROT3_BASIC( funcname ) \ \ GENTPROT3( float, float, float, s, s, s, funcname ) \ GENTPROT3( double, double, double, d, d, d, funcname ) \ GENTPROT3( scomplex, scomplex, scomplex, c, c, c, funcname ) \ GENTPROT3( dcomplex, dcomplex, dcomplex, z, z, z, funcname ) // -- Mixed domain three-operand macro -- #define INSERT_GENTPROT3_MIX_D( funcname ) \ \ GENTPROT3( float, float, scomplex, s, s, c, funcname ) \ GENTPROT3( float, scomplex, float, s, c, s, funcname ) \ GENTPROT3( float, scomplex, scomplex, s, c, c, funcname ) \ \ GENTPROT3( double, double, dcomplex, d, d, z, funcname ) \ GENTPROT3( double, dcomplex, double, d, z, d, funcname ) \ GENTPROT3( double, dcomplex, dcomplex, d, z, z, funcname ) \ \ GENTPROT3( scomplex, float, float, c, s, s, funcname ) \ GENTPROT3( scomplex, float, scomplex, c, s, c, funcname ) \ GENTPROT3( scomplex, scomplex, float, c, c, s, funcname ) \ \ GENTPROT3( dcomplex, double, double, z, d, d, funcname ) \ GENTPROT3( dcomplex, double, dcomplex, z, d, z, funcname ) \ GENTPROT3( dcomplex, dcomplex, double, z, z, d, funcname ) // -- Mixed precision three-operand macro -- #define INSERT_GENTPROT3_MIX_P( funcname ) \ \ GENTPROT3( float, float, double, s, s, d, funcname ) \ GENTPROT3( float, float, dcomplex, s, s, z, funcname ) \ \ GENTPROT3( float, double, float, s, d, s, funcname ) \ GENTPROT3( float, double, double, s, d, d, funcname ) \ GENTPROT3( float, double, scomplex, s, d, c, funcname ) \ GENTPROT3( float, double, dcomplex, s, d, z, funcname ) \ \ GENTPROT3( float, scomplex, double, s, c, d, funcname ) \ GENTPROT3( float, scomplex, dcomplex, s, c, z, funcname ) \ \ GENTPROT3( float, dcomplex, float, s, z, s, funcname ) \ GENTPROT3( float, dcomplex, double, s, z, d, funcname ) \ GENTPROT3( float, dcomplex, scomplex, s, z, c, funcname ) \ GENTPROT3( float, dcomplex, dcomplex, s, z, z, funcname ) \ \ \ GENTPROT3( double, float, float, d, s, s, funcname ) \ GENTPROT3( double, float, double, d, s, d, funcname ) \ GENTPROT3( double, float, scomplex, d, s, c, funcname ) \ GENTPROT3( double, float, dcomplex, d, s, z, funcname ) \ \ GENTPROT3( double, double, float, d, d, s, funcname ) \ GENTPROT3( double, double, scomplex, d, d, c, funcname ) \ \ GENTPROT3( double, scomplex, float, d, c, s, funcname ) \ GENTPROT3( double, scomplex, double, d, c, d, funcname ) \ GENTPROT3( double, scomplex, scomplex, d, c, c, funcname ) \ GENTPROT3( double, scomplex, dcomplex, d, c, z, funcname ) \ \ GENTPROT3( double, dcomplex, float, d, z, s, funcname ) \ GENTPROT3( double, dcomplex, scomplex, d, z, c, funcname ) \ \ \ GENTPROT3( scomplex, float, double, c, s, d, funcname ) \ GENTPROT3( scomplex, float, dcomplex, c, s, z, funcname ) \ \ GENTPROT3( scomplex, double, float, c, d, s, funcname ) \ GENTPROT3( scomplex, double, double, c, d, d, funcname ) \ GENTPROT3( scomplex, double, scomplex, c, d, c, funcname ) \ GENTPROT3( scomplex, double, dcomplex, c, d, z, funcname ) \ \ GENTPROT3( scomplex, scomplex, double, c, c, d, funcname ) \ GENTPROT3( scomplex, scomplex, dcomplex, c, c, z, funcname ) \ \ GENTPROT3( scomplex, dcomplex, float, c, z, s, funcname ) \ GENTPROT3( scomplex, dcomplex, double, c, z, d, funcname ) \ GENTPROT3( scomplex, dcomplex, scomplex, c, z, c, funcname ) \ GENTPROT3( scomplex, dcomplex, dcomplex, c, z, z, funcname ) \ \ \ GENTPROT3( dcomplex, float, float, z, s, s, funcname ) \ GENTPROT3( dcomplex, float, double, z, s, d, funcname ) \ GENTPROT3( dcomplex, float, scomplex, z, s, c, funcname ) \ GENTPROT3( dcomplex, float, dcomplex, z, s, z, funcname ) \ \ GENTPROT3( dcomplex, double, float, z, d, s, funcname ) \ GENTPROT3( dcomplex, double, scomplex, z, d, c, funcname ) \ \ GENTPROT3( dcomplex, scomplex, float, z, c, s, funcname ) \ GENTPROT3( dcomplex, scomplex, double, z, c, d, funcname ) \ GENTPROT3( dcomplex, scomplex, scomplex, z, c, c, funcname ) \ GENTPROT3( dcomplex, scomplex, dcomplex, z, c, z, funcname ) \ \ GENTPROT3( dcomplex, dcomplex, float, z, z, s, funcname ) \ GENTPROT3( dcomplex, dcomplex, scomplex, z, z, c, funcname ) \ // -- Basic three-operand with union of operands 1 and 2 -- #define INSERT_GENTPROT3U12_BASIC( funcname ) \ \ GENTPROT3U12( float, float, float, float, s, s, s, s, funcname ) \ GENTPROT3U12( double, double, double, double, d, d, d, d, funcname ) \ GENTPROT3U12( scomplex, scomplex, scomplex, scomplex, c, c, c, c, funcname ) \ GENTPROT3U12( dcomplex, dcomplex, dcomplex, dcomplex, z, z, z, z, funcname ) // -- Mixed domain three-operand with union of operands 1 and 2 -- #define INSERT_GENTPROT3U12_MIX_D( funcname ) \ \ GENTPROT3U12( float, float, scomplex, float, s, s, c, s, funcname ) \ GENTPROT3U12( float, scomplex, float, scomplex, s, c, s, c, funcname ) \ GENTPROT3U12( float, scomplex, scomplex, scomplex, s, c, c, c, funcname ) \ \ GENTPROT3U12( double, double, dcomplex, double, d, d, z, d, funcname ) \ GENTPROT3U12( double, dcomplex, double, dcomplex, d, z, d, z, funcname ) \ GENTPROT3U12( double, dcomplex, dcomplex, dcomplex, d, z, z, z, funcname ) \ \ GENTPROT3U12( scomplex, float, float, scomplex, c, s, s, c, funcname ) \ GENTPROT3U12( scomplex, float, scomplex, scomplex, c, s, c, c, funcname ) \ GENTPROT3U12( scomplex, scomplex, float, scomplex, c, c, s, c, funcname ) \ \ GENTPROT3U12( dcomplex, double, double, dcomplex, z, d, d, z, funcname ) \ GENTPROT3U12( dcomplex, double, dcomplex, dcomplex, z, d, z, z, funcname ) \ GENTPROT3U12( dcomplex, dcomplex, double, dcomplex, z, z, d, z, funcname ) // -- Mixed precision three-operand with union of operands 1 and 2 -- #define INSERT_GENTPROT3U12_MIX_P( funcname ) \ \ GENTPROT3U12( float, float, double, float, s, s, d, s, funcname ) \ GENTPROT3U12( float, float, dcomplex, float, s, s, z, s, funcname ) \ \ GENTPROT3U12( float, double, float, double, s, d, s, d, funcname ) \ GENTPROT3U12( float, double, double, double, s, d, d, d, funcname ) \ GENTPROT3U12( float, double, scomplex, double, s, d, c, d, funcname ) \ GENTPROT3U12( float, double, dcomplex, double, s, d, z, d, funcname ) \ \ GENTPROT3U12( float, scomplex, double, scomplex, s, c, d, c, funcname ) \ GENTPROT3U12( float, scomplex, dcomplex, scomplex, s, c, z, c, funcname ) \ \ GENTPROT3U12( float, dcomplex, float, dcomplex, s, z, s, z, funcname ) \ GENTPROT3U12( float, dcomplex, double, dcomplex, s, z, d, z, funcname ) \ GENTPROT3U12( float, dcomplex, scomplex, dcomplex, s, z, c, z, funcname ) \ GENTPROT3U12( float, dcomplex, dcomplex, dcomplex, s, z, z, z, funcname ) \ \ \ GENTPROT3U12( double, float, float, double, d, s, s, d, funcname ) \ GENTPROT3U12( double, float, double, double, d, s, d, d, funcname ) \ GENTPROT3U12( double, float, scomplex, double, d, s, c, d, funcname ) \ GENTPROT3U12( double, float, dcomplex, double, d, s, z, d, funcname ) \ \ GENTPROT3U12( double, double, float, double, d, d, s, d, funcname ) \ GENTPROT3U12( double, double, scomplex, double, d, d, c, d, funcname ) \ \ GENTPROT3U12( double, scomplex, float, dcomplex, d, c, s, z, funcname ) \ GENTPROT3U12( double, scomplex, double, dcomplex, d, c, d, z, funcname ) \ GENTPROT3U12( double, scomplex, scomplex, dcomplex, d, c, c, z, funcname ) \ GENTPROT3U12( double, scomplex, dcomplex, dcomplex, d, c, z, z, funcname ) \ \ GENTPROT3U12( double, dcomplex, float, dcomplex, d, z, s, z, funcname ) \ GENTPROT3U12( double, dcomplex, scomplex, dcomplex, d, z, c, z, funcname ) \ \ \ GENTPROT3U12( scomplex, float, double, scomplex, c, s, d, c, funcname ) \ GENTPROT3U12( scomplex, float, dcomplex, scomplex, c, s, z, c, funcname ) \ \ GENTPROT3U12( scomplex, double, float, dcomplex, c, d, s, z, funcname ) \ GENTPROT3U12( scomplex, double, double, dcomplex, c, d, d, z, funcname ) \ GENTPROT3U12( scomplex, double, scomplex, dcomplex, c, d, c, z, funcname ) \ GENTPROT3U12( scomplex, double, dcomplex, dcomplex, c, d, z, z, funcname ) \ \ GENTPROT3U12( scomplex, scomplex, double, scomplex, c, c, d, c, funcname ) \ GENTPROT3U12( scomplex, scomplex, dcomplex, scomplex, c, c, z, c, funcname ) \ \ GENTPROT3U12( scomplex, dcomplex, float, dcomplex, c, z, s, z, funcname ) \ GENTPROT3U12( scomplex, dcomplex, double, dcomplex, c, z, d, z, funcname ) \ GENTPROT3U12( scomplex, dcomplex, scomplex, dcomplex, c, z, c, z, funcname ) \ GENTPROT3U12( scomplex, dcomplex, dcomplex, dcomplex, c, z, z, z, funcname ) \ \ \ GENTPROT3U12( dcomplex, float, float, dcomplex, z, s, s, z, funcname ) \ GENTPROT3U12( dcomplex, float, double, dcomplex, z, s, d, z, funcname ) \ GENTPROT3U12( dcomplex, float, scomplex, dcomplex, z, s, c, z, funcname ) \ GENTPROT3U12( dcomplex, float, dcomplex, dcomplex, z, s, z, z, funcname ) \ \ GENTPROT3U12( dcomplex, double, float, dcomplex, z, d, s, z, funcname ) \ GENTPROT3U12( dcomplex, double, scomplex, dcomplex, z, d, c, z, funcname ) \ \ GENTPROT3U12( dcomplex, scomplex, float, dcomplex, z, c, s, z, funcname ) \ GENTPROT3U12( dcomplex, scomplex, double, dcomplex, z, c, d, z, funcname ) \ GENTPROT3U12( dcomplex, scomplex, scomplex, dcomplex, z, c, c, z, funcname ) \ GENTPROT3U12( dcomplex, scomplex, dcomplex, dcomplex, z, c, z, z, funcname ) \ \ GENTPROT3U12( dcomplex, dcomplex, float, dcomplex, z, z, s, z, funcname ) \ GENTPROT3U12( dcomplex, dcomplex, scomplex, dcomplex, z, z, c, z, funcname ) #endif blis-0.9.0/frame/include/bli_kernel_macro_defs.h000066400000000000000000000203371422157504600216420ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_KERNEL_MACRO_DEFS_H #define BLIS_KERNEL_MACRO_DEFS_H // -- Define default threading parameters -------------------------------------- // -- Conventional (large code path) values -- // These BLIS_THREAD_RATIO_? macros distort the amount of work in the m and n // dimensions for the purposes of factorizing the total number of threads into // ways of parallelism in the ic and jc loops. See bli_rntm.c to see how these // macros are used. #ifndef BLIS_THREAD_RATIO_M #define BLIS_THREAD_RATIO_M 1 #endif #ifndef BLIS_THREAD_RATIO_N #define BLIS_THREAD_RATIO_N 1 #endif // These BLIS_THREAD_MAX_?R macros place a ceiling on the maximum amount of // parallelism allowed when performing automatic factorization. See bli_rntm.c // to see how these macros are used. #ifndef BLIS_THREAD_MAX_IR #define BLIS_THREAD_MAX_IR 1 #endif #ifndef BLIS_THREAD_MAX_JR #define BLIS_THREAD_MAX_JR 4 #endif #if 0 // -- Skinny/small possibly-unpacked (sup code path) values -- #ifndef BLIS_THREAD_SUP_RATIO_M #define BLIS_THREAD_SUP_RATIO_M 1 #endif #ifndef BLIS_THREAD_SUP_RATIO_N #define BLIS_THREAD_SUP_RATIO_N 2 #endif #ifndef BLIS_THREAD_SUP_MAX_IR #define BLIS_THREAD_SUP_MAX_IR 1 #endif #ifndef BLIS_THREAD_SUP_MAX_JR #define BLIS_THREAD_SUP_MAX_JR 8 #endif #endif // -- Memory allocation -------------------------------------------------------- // hbwmalloc.h provides hbw_malloc() and hbw_free() on systems with // libmemkind. But disable use of libmemkind if BLIS_DISABLE_MEMKIND // was explicitly defined. #ifdef BLIS_DISABLE_MEMKIND #undef BLIS_ENABLE_MEMKIND #endif #ifdef BLIS_ENABLE_MEMKIND #include #endif // Memory allocation functions. These macros define the three types of // malloc()-style functions, and their free() counterparts: one for each // type of memory to be allocated. // NOTE: ANY ALTERNATIVE TO malloc()/free() USED FOR ANY OF THE FOLLOWING // THREE PAIRS OF MACROS MUST USE THE SAME FUNCTION PROTOTYPE AS malloc() // and free(): // // void* malloc( size_t size ); // void free( void* p ); // // This allocation function is called to allocate memory for blocks within // BLIS's internal memory pools. #ifndef BLIS_MALLOC_POOL // If use of libmemkind was enabled at configure-time, the default // memory allocation function for memory pools should be hbw_malloc() // instead of malloc(). #ifdef BLIS_ENABLE_MEMKIND #define BLIS_MALLOC_POOL hbw_malloc #else #define BLIS_MALLOC_POOL malloc #endif #endif #ifndef BLIS_FREE_POOL // If use of libmemkind was enabled at configure-time, the default // memory deallocation function for memory pools should be hbw_free() // instead of free(). #ifdef BLIS_ENABLE_MEMKIND #define BLIS_FREE_POOL hbw_free #else #define BLIS_FREE_POOL free #endif #endif // This allocation function is called to allocate memory for internally- // used objects and structures, such as control tree nodes. #ifndef BLIS_MALLOC_INTL #define BLIS_MALLOC_INTL malloc #endif #ifndef BLIS_FREE_INTL #define BLIS_FREE_INTL free #endif // This allocation function is called to allocate memory for objects // created by user-level API functions, such as bli_obj_create(). #ifndef BLIS_MALLOC_USER #define BLIS_MALLOC_USER malloc #endif #ifndef BLIS_FREE_USER #define BLIS_FREE_USER free #endif // -- Other system-related definitions ----------------------------------------- // Size of a virtual memory page. This is used to align blocks within the // memory pools. #ifndef BLIS_PAGE_SIZE #define BLIS_PAGE_SIZE 4096 #endif // The maximum number of named SIMD vector registers available for use. // When configuring with umbrella configuration families, this should be // set to the maximum number of registers across all sub-configurations in // the family. #ifndef BLIS_SIMD_MAX_NUM_REGISTERS #define BLIS_SIMD_MAX_NUM_REGISTERS 32 #endif // The maximum size (in bytes) of each SIMD vector. // When configuring with umbrella configuration families, this should be // set to the maximum SIMD size across all sub-configurations in the family. #ifndef BLIS_SIMD_MAX_SIZE #define BLIS_SIMD_MAX_SIZE 64 #endif // Alignment size (in bytes) needed by the instruction set for aligned // SIMD/vector instructions. #ifndef BLIS_SIMD_ALIGN_SIZE #define BLIS_SIMD_ALIGN_SIZE BLIS_SIMD_MAX_SIZE #endif // The maximum size in bytes of local stack buffers within macro-kernel // functions. These buffers are usually used to store a temporary copy // of a single microtile. The reason we multiply by 2 is to handle induced // methods, where we use real domain register blocksizes in units of // complex elements. Specifically, the macro-kernels will need this larger // micro-tile footprint, even though the virtual micro-kernels will only // ever be writing to half (real or imaginary part) at a time. #ifndef BLIS_STACK_BUF_MAX_SIZE #define BLIS_STACK_BUF_MAX_SIZE ( BLIS_SIMD_MAX_NUM_REGISTERS * \ BLIS_SIMD_MAX_SIZE * 2 ) #endif // Alignment size used to align local stack buffers within macro-kernel // functions. #ifndef BLIS_STACK_BUF_ALIGN_SIZE #define BLIS_STACK_BUF_ALIGN_SIZE BLIS_SIMD_ALIGN_SIZE #endif // Alignment size used when allocating memory via BLIS_MALLOC_USER. // To disable heap alignment, set this to 1. #ifndef BLIS_HEAP_ADDR_ALIGN_SIZE #define BLIS_HEAP_ADDR_ALIGN_SIZE BLIS_SIMD_ALIGN_SIZE #endif // Alignment size used when sizing leading dimensions of memory allocated // via BLIS_MALLOC_USER. #ifndef BLIS_HEAP_STRIDE_ALIGN_SIZE #define BLIS_HEAP_STRIDE_ALIGN_SIZE BLIS_SIMD_ALIGN_SIZE #endif // Alignment sizes used when allocating blocks to the internal memory // pool, via BLIS_MALLOC_POOL. #ifndef BLIS_POOL_ADDR_ALIGN_SIZE_A #define BLIS_POOL_ADDR_ALIGN_SIZE_A BLIS_PAGE_SIZE #endif #ifndef BLIS_POOL_ADDR_ALIGN_SIZE_B #define BLIS_POOL_ADDR_ALIGN_SIZE_B BLIS_PAGE_SIZE #endif #ifndef BLIS_POOL_ADDR_ALIGN_SIZE_C #define BLIS_POOL_ADDR_ALIGN_SIZE_C BLIS_PAGE_SIZE #endif #ifndef BLIS_POOL_ADDR_ALIGN_SIZE_GEN #define BLIS_POOL_ADDR_ALIGN_SIZE_GEN BLIS_PAGE_SIZE #endif // Offsets from alignment specified by BLIS_POOL_ADDR_ALIGN_SIZE_*. #ifndef BLIS_POOL_ADDR_OFFSET_SIZE_A #define BLIS_POOL_ADDR_OFFSET_SIZE_A 0 #endif #ifndef BLIS_POOL_ADDR_OFFSET_SIZE_B #define BLIS_POOL_ADDR_OFFSET_SIZE_B 0 #endif #ifndef BLIS_POOL_ADDR_OFFSET_SIZE_C #define BLIS_POOL_ADDR_OFFSET_SIZE_C 0 #endif #ifndef BLIS_POOL_ADDR_OFFSET_SIZE_GEN #define BLIS_POOL_ADDR_OFFSET_SIZE_GEN 0 #endif #endif blis-0.9.0/frame/include/bli_lang_defs.h000066400000000000000000000077131422157504600201250ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_LANG_DEFS_H #define BLIS_LANG_DEFS_H // -- Undefine restrict for C++ and C89/90 -- #ifdef __cplusplus // Language is C++; define restrict as nothing. #ifndef restrict #define restrict #endif #elif __STDC_VERSION__ >= 199901L // Language is C99 (or later); do nothing since restrict is recognized. #else // Language is pre-C99; define restrict as nothing. #ifndef restrict #define restrict #endif #endif // -- Define typeof() operator if using non-GNU compiler -- #ifndef __GNUC__ #define typeof __typeof__ #else #ifndef typeof #define typeof __typeof__ #endif #endif // -- BLIS Thread Local Storage Keyword -- // __thread for TLS is supported by GCC, CLANG, ICC, and IBMC. // There is a small risk here as __GNUC__ can also be defined by some other // compiler (other than ICC and CLANG which we know define it) that // doesn't support __thread, as __GNUC__ is not quite unique to GCC. // But the possibility of someone using such non-main-stream compiler // for building BLIS is low. #if defined(__GNUC__) || defined(__clang__) || defined(__ICC) || defined(__IBMC__) #define BLIS_THREAD_LOCAL __thread #else #define BLIS_THREAD_LOCAL #endif // -- BLIS constructor/destructor function attribute -- // __attribute__((constructor/destructor)) is supported by GCC only. // There is a small risk here as __GNUC__ can also be defined by some other // compiler (other than ICC and CLANG which we know define it) that // doesn't support this, as __GNUC__ is not quite unique to GCC. // But the possibility of someone using such non-main-stream compiler // for building BLIS is low. #if defined(__ICC) || defined(__INTEL_COMPILER) // ICC defines __GNUC__ but doesn't support this #define BLIS_ATTRIB_CTOR #define BLIS_ATTRIB_DTOR #elif defined(__clang__) // CLANG supports __attribute__, but its documentation doesn't // mention support for constructor/destructor. Compiling with // clang and testing shows that it does support. #define BLIS_ATTRIB_CTOR __attribute__((constructor)) #define BLIS_ATTRIB_DTOR __attribute__((destructor)) #elif defined(__GNUC__) #define BLIS_ATTRIB_CTOR __attribute__((constructor)) #define BLIS_ATTRIB_DTOR __attribute__((destructor)) #else #define BLIS_ATTRIB_CTOR #define BLIS_ATTRIB_DTOR #endif #endif blis-0.9.0/frame/include/bli_macro_defs.h000066400000000000000000000106571422157504600203060ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_MACRO_DEFS_H #define BLIS_MACRO_DEFS_H // -- Concatenation macros -- #define BLIS_FUNC_PREFIX_STR "bli" // We add an extra layer the definitions of these string-pasting macros // because sometimes it is needed if, for example, one of the PASTE // macros is invoked with an "op" argument that is itself a macro. #define PASTEMAC0_(op) bli_ ## op #define PASTEMAC0(op) PASTEMAC0_(op) #define PASTEMAC_(ch,op) bli_ ## ch ## op #define PASTEMAC(ch,op) PASTEMAC_(ch,op) #define PASTEMAC2_(ch1,ch2,op) bli_ ## ch1 ## ch2 ## op #define PASTEMAC2(ch1,ch2,op) PASTEMAC2_(ch1,ch2,op) #define PASTEMAC3_(ch1,ch2,ch3,op) bli_ ## ch1 ## ch2 ## ch3 ## op #define PASTEMAC3(ch1,ch2,ch3,op) PASTEMAC3_(ch1,ch2,ch3,op) #define PASTEMAC4_(ch1,ch2,ch3,ch4,op) bli_ ## ch1 ## ch2 ## ch3 ## ch4 ## op #define PASTEMAC4(ch1,ch2,ch3,ch4,op) PASTEMAC4_(ch1,ch2,ch3,ch4,op) #define PASTEMAC5_(ch1,ch2,ch3,ch4,ch5,op) bli_ ## ch1 ## ch2 ## ch3 ## ch4 ## ch5 ## op #define PASTEMAC5(ch1,ch2,ch3,ch4,ch5,op) PASTEMAC5_(ch1,ch2,ch3,ch4,ch5,op) #define PASTEMAC6_(ch1,ch2,ch3,ch4,ch5,ch6,op) bli_ ## ch1 ## ch2 ## ch3 ## ch4 ## ch5 ## ch6 ## op #define PASTEMAC6(ch1,ch2,ch3,ch4,ch5,ch6,op) PASTEMAC6_(ch1,ch2,ch3,ch4,ch5,ch6,op) #define PASTEBLACHK_(op) bla_ ## op ## _check #define PASTEBLACHK(op) PASTEBLACHK_(op) #define PASTECH0_(op) op #define PASTECH0(op) PASTECH0_(op) #define PASTECH_(ch,op) ch ## op #define PASTECH(ch,op) PASTECH_(ch,op) #define PASTECH2_(ch1,ch2,op) ch1 ## ch2 ## op #define PASTECH2(ch1,ch2,op) PASTECH2_(ch1,ch2,op) #define PASTECH3_(ch1,ch2,ch3,op) ch1 ## ch2 ## ch3 ## op #define PASTECH3(ch1,ch2,ch3,op) PASTECH3_(ch1,ch2,ch3,op) #define MKSTR(s1) #s1 #define STRINGIFY_INT( s ) MKSTR( s ) // Fortran-77 name-mangling macros. #define PASTEF770(name) name ## _ #define PASTEF77(ch1,name) ch1 ## name ## _ #define PASTEF772(ch1,ch2,name) ch1 ## ch2 ## name ## _ #define PASTEF773(ch1,ch2,ch3,name) ch1 ## ch2 ## ch3 ## name ## _ // -- Include other groups of macros #include "bli_genarray_macro_defs.h" #include "bli_gentdef_macro_defs.h" #include "bli_gentfunc_macro_defs.h" #include "bli_gentprot_macro_defs.h" #include "bli_misc_macro_defs.h" #include "bli_edge_case_macro_defs.h" #include "bli_param_macro_defs.h" #include "bli_obj_macro_defs.h" #include "bli_complex_macro_defs.h" #include "bli_scalar_macro_defs.h" #include "bli_error_macro_defs.h" #include "bli_blas_macro_defs.h" #include "bli_builtin_macro_defs.h" #include "bli_oapi_macro_defs.h" #include "bli_tapi_macro_defs.h" #endif blis-0.9.0/frame/include/bli_misc_macro_defs.h000066400000000000000000000105231422157504600213110ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_MISC_MACRO_DEFS_H #define BLIS_MISC_MACRO_DEFS_H // -- Miscellaneous macros -- // min, max, abs // NOTE: These must remain macros since we don't know the types of a and b. #define bli_min( a, b ) ( (a) < (b) ? (a) : (b) ) #define bli_max( a, b ) ( (a) > (b) ? (a) : (b) ) #define bli_abs( a ) ( (a) <= 0 ? -(a) : (a) ) // fmin, fmax, fabs // NOTE: These must remain macros since we don't know the types of a and b. #define bli_fmin( a, b ) bli_min( a, b ) #define bli_fmax( a, b ) bli_max( a, b ) #define bli_fabs( a ) ( (a) <= 0.0 ? -(a) : (a) ) // fminabs, fmaxabs // NOTE: These must remain macros since we don't know the types of a and b. #define bli_fminabs( a, b ) \ \ bli_fmin( bli_fabs( a ), \ bli_fabs( b ) ) #define bli_fmaxabs( a, b ) \ \ bli_fmax( bli_fabs( a ), \ bli_fabs( b ) ) // round BLIS_INLINE double bli_round( double a ) { return round( a ); } // round_to_mult BLIS_INLINE guint_t bli_round_to_mult( guint_t val, guint_t mult ) { return ( guint_t ) ( ( ( ( guint_t )val + ( guint_t )mult / 2 ) / mult ) * mult ); } // isnan, isinf // NOTE: These must remain macros, since isinf() and isnan() are macros // (defined in math.h) that likely depend on the type of the argument 'a' // below. #define bli_isinf( a ) isinf( a ) #define bli_isnan( a ) isnan( a ) // is_odd, is_even BLIS_INLINE bool bli_is_odd( gint_t a ) { return ( bool )( a % 2 == 1 ); } BLIS_INLINE bool bli_is_even( gint_t a ) { return ( bool )( a % 2 == 0 ); } // swap_dims BLIS_INLINE void bli_swap_dims( dim_t* dim1, dim_t* dim2 ) { dim_t temp = *dim1; *dim1 = *dim2; *dim2 = temp; } // swap_incs BLIS_INLINE void bli_swap_incs( inc_t* inc1, inc_t* inc2 ) { inc_t temp = *inc1; *inc1 = *inc2; *inc2 = temp; } // toggle_bool BLIS_INLINE void bli_toggle_bool( bool* b ) { if ( *b == TRUE ) *b = FALSE; else *b = TRUE; } // return datatype for char #define bli_stype ( BLIS_FLOAT ) #define bli_dtype ( BLIS_DOUBLE ) #define bli_ctype ( BLIS_SCOMPLEX ) #define bli_ztype ( BLIS_DCOMPLEX ) // return C type for char #define bli_sctype float #define bli_dctype double #define bli_cctype scomplex #define bli_zctype dcomplex // return real proj of C type for char #define bli_sctyper float #define bli_dctyper double #define bli_cctyper float #define bli_zctyper double // return default format specifier for char // NOTE: These must remain macros due to the way they are used to initialize // local char arrays. #define bli_sformatspec() "%9.2e" #define bli_dformatspec() "%9.2e" #define bli_cformatspec() "%9.2e + %9.2e " #define bli_zformatspec() "%9.2e + %9.2e " #define bli_iformatspec() "%6d" #endif blis-0.9.0/frame/include/bli_oapi_ba.h000066400000000000000000000047631422157504600175770ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // This file defines macros used to allow the _oapi.c files to produce // object APIs that omit expert parameters. // Define a macro that allows the source code to determine which interface // (basic or expert) we are compiling. #undef BLIS_OAPI_BASIC #define BLIS_OAPI_BASIC // Define the macro to omit a suffix from the function names (in function // definitions). #undef EX_SUF #define EX_SUF // Define the macro to omit expert arguments from function signatures // and prototypes. #undef BLIS_OAPI_EX_PARAMS #define BLIS_OAPI_EX_PARAMS // Define the macro to add local expert variables that are initialized // to NULL. The "( void )" statements are to prevent unused variable // warnings by the compiler. #undef BLIS_OAPI_EX_DECLS #define BLIS_OAPI_EX_DECLS cntx_t* cntx = NULL; ( void )cntx; \ rntm_t* rntm = NULL; ( void )rntm; blis-0.9.0/frame/include/bli_oapi_ex.h000066400000000000000000000046451422157504600176300ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // This file defines macros used to allow the _oapi.c files to produce // object APIs that contain context parameters. // Define a macro that allows the source code to determine which interface // (basic or expert) we are compiling. #undef BLIS_OAPI_EXPERT #define BLIS_OAPI_EXPERT // Define the macro to add a suffix to the function names (in function // definitions). #undef EX_SUF #define EX_SUF BLIS_OAPI_EX_SUF // Define the macro to add expert arguments to function signatures // and prototypes. #undef BLIS_OAPI_EX_PARAMS #define BLIS_OAPI_EX_PARAMS ,cntx_t* cntx, rntm_t* rntm // Define the macro to omit the expert variable declaration block, since // it is not needed when expert parameters are passed in through the API. #undef BLIS_OAPI_EX_DECLS #define BLIS_OAPI_EX_DECLS blis-0.9.0/frame/include/bli_oapi_macro_defs.h000066400000000000000000000034201422157504600213040ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // Define the suffix to add to object API function names that include // additional "expert" parameters. #define BLIS_OAPI_EX_SUF _ex blis-0.9.0/frame/include/bli_obj_macro_defs.h000066400000000000000000001171171422157504600211370ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2016, Hewlett Packard Enterprise Development LP Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_OBJ_MACRO_DEFS_H #define BLIS_OBJ_MACRO_DEFS_H // -- Object query/modification macros -- // Info query BLIS_INLINE num_t bli_obj_dt( obj_t* obj ) { return ( num_t ) ( obj->info & BLIS_DATATYPE_BITS ); } BLIS_INLINE bool bli_obj_is_float( obj_t* obj ) { return ( bool ) ( bli_obj_dt( obj ) == BLIS_BITVAL_FLOAT_TYPE ); } BLIS_INLINE bool bli_obj_is_double( obj_t* obj ) { return ( bool ) ( bli_obj_dt( obj ) == BLIS_BITVAL_DOUBLE_TYPE ); } BLIS_INLINE bool bli_obj_is_scomplex( obj_t* obj ) { return ( bool ) ( bli_obj_dt( obj ) == BLIS_BITVAL_SCOMPLEX_TYPE ); } BLIS_INLINE bool bli_obj_is_dcomplex( obj_t* obj ) { return ( bool ) ( bli_obj_dt( obj ) == BLIS_BITVAL_DCOMPLEX_TYPE ); } BLIS_INLINE bool bli_obj_is_int( obj_t* obj ) { return ( bool ) ( bli_obj_dt( obj ) == BLIS_BITVAL_INT_TYPE ); } BLIS_INLINE bool bli_obj_is_const( obj_t* obj ) { return ( bool ) ( bli_obj_dt( obj ) == BLIS_BITVAL_CONST_TYPE ); } BLIS_INLINE dom_t bli_obj_domain( obj_t* obj ) { return ( dom_t ) ( obj->info & BLIS_DOMAIN_BIT ); } BLIS_INLINE prec_t bli_obj_prec( obj_t* obj ) { return ( prec_t ) ( obj->info & BLIS_PRECISION_BIT ); } BLIS_INLINE bool bli_obj_is_single_prec( obj_t* obj ) { return ( bool ) ( bli_obj_prec( obj ) == BLIS_BITVAL_SINGLE_PREC ); } BLIS_INLINE bool bli_obj_is_double_prec( obj_t* obj ) { return ( bool ) ( bli_obj_prec( obj ) == BLIS_BITVAL_DOUBLE_PREC ); } BLIS_INLINE num_t bli_obj_dt_proj_to_single_prec( obj_t* obj ) { return ( num_t ) ( bli_obj_dt( obj ) & ~BLIS_BITVAL_SINGLE_PREC ); } BLIS_INLINE num_t bli_obj_dt_proj_to_double_prec( obj_t* obj ) { return ( num_t ) ( bli_obj_dt( obj ) | BLIS_BITVAL_DOUBLE_PREC ); } BLIS_INLINE bool bli_obj_is_real( obj_t* obj ) { return ( bool ) ( bli_obj_domain( obj ) == BLIS_BITVAL_REAL && !bli_obj_is_const( obj ) ); } BLIS_INLINE bool bli_obj_is_complex( obj_t* obj ) { return ( bool ) ( bli_obj_domain( obj ) == BLIS_BITVAL_COMPLEX && !bli_obj_is_const( obj ) ); } BLIS_INLINE num_t bli_obj_dt_proj_to_real( obj_t* obj ) { return ( num_t ) ( bli_obj_dt( obj ) & ~BLIS_BITVAL_COMPLEX ); } BLIS_INLINE num_t bli_obj_dt_proj_to_complex( obj_t* obj ) { return ( num_t ) ( bli_obj_dt( obj ) | BLIS_BITVAL_COMPLEX ); } BLIS_INLINE num_t bli_obj_target_dt( obj_t* obj ) { return ( num_t ) ( ( obj->info & BLIS_TARGET_DT_BITS ) >> BLIS_TARGET_DT_SHIFT ); } BLIS_INLINE dom_t bli_obj_target_domain( obj_t* obj ) { return ( dom_t ) ( ( obj->info & BLIS_TARGET_DOMAIN_BIT ) >> BLIS_TARGET_DT_SHIFT ); } BLIS_INLINE prec_t bli_obj_target_prec( obj_t* obj ) { return ( prec_t ) ( ( obj->info & BLIS_TARGET_PREC_BIT ) >> BLIS_TARGET_DT_SHIFT ); } BLIS_INLINE num_t bli_obj_exec_dt( obj_t* obj ) { return ( num_t ) ( ( obj->info & BLIS_EXEC_DT_BITS ) >> BLIS_EXEC_DT_SHIFT ); } BLIS_INLINE dom_t bli_obj_exec_domain( obj_t* obj ) { return ( dom_t ) ( ( obj->info & BLIS_EXEC_DOMAIN_BIT ) >> BLIS_EXEC_DT_SHIFT ); } BLIS_INLINE prec_t bli_obj_exec_prec( obj_t* obj ) { return ( prec_t ) ( ( obj->info & BLIS_EXEC_PREC_BIT ) >> BLIS_EXEC_DT_SHIFT ); } BLIS_INLINE num_t bli_obj_comp_dt( obj_t* obj ) { return ( num_t ) ( ( obj->info & BLIS_COMP_DT_BITS ) >> BLIS_COMP_DT_SHIFT ); } BLIS_INLINE dom_t bli_obj_comp_domain( obj_t* obj ) { return ( dom_t ) ( ( obj->info & BLIS_COMP_DOMAIN_BIT ) >> BLIS_COMP_DT_SHIFT ); } BLIS_INLINE prec_t bli_obj_comp_prec( obj_t* obj ) { return ( prec_t ) ( ( obj->info & BLIS_COMP_PREC_BIT ) >> BLIS_COMP_DT_SHIFT ); } // NOTE: This function queries info2. BLIS_INLINE num_t bli_obj_scalar_dt( obj_t* obj ) { return ( num_t ) ( ( obj->info2 & BLIS_SCALAR_DT_BITS ) >> BLIS_SCALAR_DT_SHIFT ); } // NOTE: This function queries info2. BLIS_INLINE dom_t bli_obj_scalar_domain( obj_t* obj ) { return ( dom_t ) ( ( obj->info2 & BLIS_SCALAR_DOMAIN_BIT ) >> BLIS_SCALAR_DT_SHIFT ); } // NOTE: This function queries info2. BLIS_INLINE prec_t bli_obj_scalar_prec( obj_t* obj ) { return ( prec_t ) ( ( obj->info2 & BLIS_SCALAR_PREC_BIT ) >> BLIS_SCALAR_DT_SHIFT ); } BLIS_INLINE trans_t bli_obj_conjtrans_status( obj_t* obj ) { return ( trans_t ) ( obj->info & BLIS_CONJTRANS_BITS ); } BLIS_INLINE trans_t bli_obj_onlytrans_status( obj_t* obj ) { return ( trans_t ) ( obj->info & BLIS_TRANS_BIT ); } BLIS_INLINE bool bli_obj_has_trans( obj_t* obj ) { return ( bool ) ( bli_obj_onlytrans_status( obj ) == BLIS_BITVAL_TRANS ); } BLIS_INLINE bool bli_obj_has_notrans( obj_t* obj ) { return ( bool ) ( bli_obj_onlytrans_status( obj ) == BLIS_BITVAL_NO_TRANS ); } BLIS_INLINE conj_t bli_obj_conj_status( obj_t* obj ) { return ( conj_t ) ( obj->info & BLIS_CONJ_BIT ); } BLIS_INLINE bool bli_obj_has_conj( obj_t* obj ) { return ( bool ) ( bli_obj_conj_status( obj ) == BLIS_BITVAL_CONJ ); } BLIS_INLINE bool bli_obj_has_noconj( obj_t* obj ) { return ( bool ) ( bli_obj_conj_status( obj ) == BLIS_BITVAL_NO_CONJ ); } BLIS_INLINE uplo_t bli_obj_uplo( obj_t* obj ) { return ( uplo_t ) ( obj->info & BLIS_UPLO_BITS ); } BLIS_INLINE bool bli_obj_is_upper( obj_t* obj ) { return ( bool ) ( bli_obj_uplo( obj ) == BLIS_BITVAL_UPPER ); } BLIS_INLINE bool bli_obj_is_lower( obj_t* obj ) { return ( bool ) ( bli_obj_uplo( obj ) == BLIS_BITVAL_LOWER ); } BLIS_INLINE bool bli_obj_is_upper_or_lower( obj_t* obj ) { return ( bool ) ( bli_obj_is_upper( obj ) || bli_obj_is_lower( obj ) ); } BLIS_INLINE bool bli_obj_is_dense( obj_t* obj ) { return ( bool ) ( bli_obj_uplo( obj ) == BLIS_BITVAL_DENSE ); } BLIS_INLINE bool bli_obj_is_zeros( obj_t* obj ) { return ( bool ) ( bli_obj_uplo( obj ) == BLIS_BITVAL_ZEROS ); } BLIS_INLINE diag_t bli_obj_diag( obj_t* obj ) { return ( diag_t ) ( obj->info & BLIS_UNIT_DIAG_BIT ); } BLIS_INLINE bool bli_obj_has_nonunit_diag( obj_t* obj ) { return ( bool ) ( bli_obj_diag( obj ) == BLIS_BITVAL_NONUNIT_DIAG ); } BLIS_INLINE bool bli_obj_has_unit_diag( obj_t* obj ) { return ( bool ) ( bli_obj_diag( obj ) == BLIS_BITVAL_UNIT_DIAG ); } BLIS_INLINE bool bli_obj_has_inverted_diag( obj_t* obj ) { return ( bool ) ( ( obj->info & BLIS_INVERT_DIAG_BIT ) == BLIS_BITVAL_INVERT_DIAG ); } BLIS_INLINE bool bli_obj_is_pack_rev_if_upper( obj_t* obj ) { return ( bool ) ( ( obj->info & BLIS_PACK_REV_IF_UPPER_BIT ) == BLIS_BITVAL_PACK_REV_IF_UPPER ); } BLIS_INLINE bool bli_obj_is_pack_rev_if_lower( obj_t* obj ) { return ( bool ) ( ( obj->info & BLIS_PACK_REV_IF_LOWER_BIT ) == BLIS_BITVAL_PACK_REV_IF_LOWER ); } BLIS_INLINE pack_t bli_obj_pack_schema( obj_t* obj ) { return ( pack_t ) ( obj->info & BLIS_PACK_SCHEMA_BITS ); } BLIS_INLINE bool bli_obj_is_packed( obj_t* obj ) { return ( bool ) ( obj->info & BLIS_PACK_BIT ); } BLIS_INLINE bool bli_obj_is_row_packed( obj_t* obj ) { return ( bool ) ( ( obj->info & BLIS_PACK_RC_BIT ) == ( BLIS_BITVAL_PACKED_UNSPEC ^ BLIS_BITVAL_PACKED_ROWS ) ); } BLIS_INLINE bool bli_obj_is_col_packed( obj_t* obj ) { return ( bool ) ( ( obj->info & BLIS_PACK_RC_BIT ) == ( BLIS_BITVAL_PACKED_UNSPEC ^ BLIS_BITVAL_PACKED_COLUMNS ) ); } BLIS_INLINE bool bli_obj_is_panel_packed( obj_t* obj ) { return ( bool ) ( obj->info & BLIS_PACK_PANEL_BIT ); } BLIS_INLINE packbuf_t bli_obj_pack_buffer_type( obj_t* obj ) { return ( packbuf_t ) ( obj->info & BLIS_PACK_BUFFER_BITS ); } BLIS_INLINE struc_t bli_obj_struc( obj_t* obj ) { return ( struc_t ) ( obj->info & BLIS_STRUC_BITS ); } BLIS_INLINE bool bli_obj_is_general( obj_t* obj ) { return ( bool ) ( bli_obj_struc( obj ) == BLIS_BITVAL_GENERAL ); } BLIS_INLINE bool bli_obj_is_hermitian( obj_t* obj ) { return ( bool ) ( bli_obj_struc( obj ) == BLIS_BITVAL_HERMITIAN ); } BLIS_INLINE bool bli_obj_is_symmetric( obj_t* obj ) { return ( bool ) ( bli_obj_struc( obj ) == BLIS_BITVAL_SYMMETRIC ); } BLIS_INLINE bool bli_obj_is_triangular( obj_t* obj ) { return ( bool ) ( bli_obj_struc( obj ) == BLIS_BITVAL_TRIANGULAR ); } // Info modification BLIS_INLINE void bli_obj_apply_trans( trans_t trans, obj_t* obj ) { obj->info = ( objbits_t ) ( obj->info ^ trans ); } BLIS_INLINE void bli_obj_apply_conj( conj_t conj, obj_t* obj ) { obj->info = ( objbits_t ) ( obj->info ^ conj ); } BLIS_INLINE void bli_obj_set_conjtrans( trans_t trans, obj_t* obj ) { obj->info = ( objbits_t ) ( ( obj->info & ~BLIS_CONJTRANS_BITS ) | trans ); } BLIS_INLINE void bli_obj_set_onlytrans( trans_t trans, obj_t* obj ) { obj->info = ( objbits_t ) ( ( obj->info & ~BLIS_TRANS_BIT ) | trans ); } BLIS_INLINE void bli_obj_set_conj( conj_t conj, obj_t* obj ) { obj->info = ( objbits_t ) ( ( obj->info & ~BLIS_CONJ_BIT ) | conj ); } BLIS_INLINE void bli_obj_set_uplo( uplo_t uplo, obj_t* obj ) { obj->info = ( objbits_t ) ( ( obj->info & ~BLIS_UPLO_BITS ) | uplo ); } BLIS_INLINE void bli_obj_set_diag( diag_t diag, obj_t* obj ) { obj->info = ( objbits_t ) ( ( obj->info & ~BLIS_UNIT_DIAG_BIT ) | diag ); } BLIS_INLINE void bli_obj_set_invert_diag( invdiag_t invdiag, obj_t* obj ) { obj->info = ( objbits_t ) ( ( obj->info & ~BLIS_INVERT_DIAG_BIT ) | invdiag ); } BLIS_INLINE void bli_obj_set_dt( num_t dt, obj_t* obj ) { obj->info = ( objbits_t ) ( ( obj->info & ~BLIS_DATATYPE_BITS ) | dt ); } BLIS_INLINE void bli_obj_set_target_dt( num_t dt, obj_t* obj ) { obj->info = ( objbits_t ) ( ( obj->info & ~BLIS_TARGET_DT_BITS ) | ( dt << BLIS_TARGET_DT_SHIFT ) ); } BLIS_INLINE void bli_obj_set_target_domain( dom_t dt, obj_t* obj ) { obj->info = ( objbits_t ) ( ( obj->info & ~BLIS_TARGET_DOMAIN_BIT ) | ( dt << BLIS_TARGET_DT_SHIFT ) ); } BLIS_INLINE void bli_obj_set_target_prec( prec_t dt, obj_t* obj ) { obj->info = ( objbits_t ) ( ( obj->info & ~BLIS_TARGET_PREC_BIT ) | ( dt << BLIS_TARGET_DT_SHIFT ) ); } BLIS_INLINE void bli_obj_set_exec_dt( num_t dt, obj_t* obj ) { obj->info = ( objbits_t ) ( ( obj->info & ~BLIS_EXEC_DT_BITS ) | ( dt << BLIS_EXEC_DT_SHIFT ) ); } BLIS_INLINE void bli_obj_set_exec_domain( dom_t dt, obj_t* obj ) { obj->info = ( objbits_t ) ( ( obj->info & ~BLIS_EXEC_DOMAIN_BIT ) | ( dt << BLIS_EXEC_DT_SHIFT ) ); } BLIS_INLINE void bli_obj_set_exec_prec( prec_t dt, obj_t* obj ) { obj->info = ( objbits_t ) ( ( obj->info & ~BLIS_EXEC_PREC_BIT ) | ( dt << BLIS_EXEC_DT_SHIFT ) ); } BLIS_INLINE void bli_obj_set_comp_dt( num_t dt, obj_t* obj ) { obj->info = ( objbits_t ) ( ( obj->info & ~BLIS_COMP_DT_BITS ) | ( dt << BLIS_COMP_DT_SHIFT ) ); } BLIS_INLINE void bli_obj_set_comp_domain( dom_t dt, obj_t* obj ) { obj->info = ( objbits_t ) ( ( obj->info & ~BLIS_COMP_DOMAIN_BIT ) | ( dt << BLIS_COMP_DT_SHIFT ) ); } BLIS_INLINE void bli_obj_set_comp_prec( prec_t dt, obj_t* obj ) { obj->info = ( objbits_t ) ( ( obj->info & ~BLIS_COMP_PREC_BIT ) | ( dt << BLIS_COMP_DT_SHIFT ) ); } // NOTE: This function queries and modifies info2. BLIS_INLINE void bli_obj_set_scalar_dt( num_t dt, obj_t* obj ) { obj->info2 = ( objbits_t ) ( ( obj->info2 & ~BLIS_SCALAR_DT_BITS ) | ( dt << BLIS_SCALAR_DT_SHIFT ) ); } // NOTE: This function queries and modifies info2. BLIS_INLINE void bli_obj_set_scalar_domain( dom_t dt, obj_t* obj ) { obj->info2 = ( objbits_t ) ( ( obj->info2 & ~BLIS_SCALAR_DOMAIN_BIT ) | ( dt << BLIS_SCALAR_DT_SHIFT ) ); } // NOTE: This function queries and modifies info2. BLIS_INLINE void bli_obj_set_scalar_prec( prec_t dt, obj_t* obj ) { obj->info2 = ( objbits_t ) ( ( obj->info2 & ~BLIS_SCALAR_PREC_BIT ) | ( dt << BLIS_SCALAR_DT_SHIFT ) ); } BLIS_INLINE void bli_obj_set_pack_schema( pack_t schema, obj_t* obj ) { obj->info = ( objbits_t ) ( ( obj->info & ~BLIS_PACK_SCHEMA_BITS ) | schema ); } BLIS_INLINE void bli_obj_set_pack_order_if_upper( packord_t ordif, obj_t* obj ) { obj->info = ( objbits_t ) ( ( obj->info & ~BLIS_PACK_REV_IF_UPPER_BIT ) | ordif ); } BLIS_INLINE void bli_obj_set_pack_order_if_lower( packord_t ordif, obj_t* obj ) { obj->info = ( objbits_t ) ( ( obj->info & ~BLIS_PACK_REV_IF_LOWER_BIT ) | ordif ); } // NOTE: The packbuf_t bitfield in the obj_t is currently unused. Instead, // packbuf_t is stored/used from the context in order to support various // induced methods. (Though ideally the packbuf_t field would only be // present in the control tree). BLIS_INLINE void bli_obj_set_pack_buffer_type( packbuf_t buf_type, obj_t* obj ) { obj->info = ( objbits_t ) ( ( obj->info & ~BLIS_PACK_BUFFER_BITS ) | buf_type ); } BLIS_INLINE void bli_obj_set_struc( struc_t struc, obj_t* obj ) { obj->info = ( objbits_t ) ( ( obj->info & ~BLIS_STRUC_BITS ) | struc ); } BLIS_INLINE void bli_obj_toggle_trans( obj_t* obj ) { bli_obj_apply_trans( BLIS_TRANSPOSE, obj ); } BLIS_INLINE void bli_obj_toggle_conj( obj_t* obj ) { bli_obj_apply_conj( BLIS_CONJUGATE, obj ); } BLIS_INLINE void bli_obj_toggle_uplo( obj_t* obj ) { obj->info = ( objbits_t ) ( obj->info ^ BLIS_LOWER_BIT ) ^ BLIS_UPPER_BIT; } // Root matrix query BLIS_INLINE obj_t* bli_obj_root( obj_t* obj ) { return ( obj_t* )( obj->root ); } BLIS_INLINE bool bli_obj_root_is_general( obj_t* obj ) { return ( bool ) ( bli_obj_is_general( bli_obj_root( obj ) ) ); } BLIS_INLINE bool bli_obj_root_is_hermitian( obj_t* obj ) { return ( bool ) ( bli_obj_is_hermitian( bli_obj_root( obj ) ) ); } BLIS_INLINE bool bli_obj_root_is_symmetric( obj_t* obj ) { return ( bool ) ( bli_obj_is_symmetric( bli_obj_root( obj ) ) ); } BLIS_INLINE bool bli_obj_root_is_triangular( obj_t* obj ) { return ( bool ) ( bli_obj_is_triangular( bli_obj_root( obj ) ) ); } BLIS_INLINE bool bli_obj_root_is_herm_or_symm( obj_t* obj ) { return ( bool ) ( bli_obj_is_hermitian( bli_obj_root( obj ) ) || bli_obj_is_symmetric( bli_obj_root( obj ) ) ); } BLIS_INLINE bool bli_obj_root_is_upper( obj_t* obj ) { return ( bool ) ( bli_obj_is_upper( bli_obj_root( obj ) ) ); } BLIS_INLINE bool bli_obj_root_is_lower( obj_t* obj ) { return ( bool ) ( bli_obj_is_lower( bli_obj_root( obj ) ) ); } // Root matrix modification BLIS_INLINE void bli_obj_set_as_root( obj_t* obj ) { obj->root = obj; } // Diagonal offset query BLIS_INLINE doff_t bli_obj_diag_offset( obj_t* obj ) { return ( doff_t ) ( obj->diag_off ); } BLIS_INLINE doff_t bli_obj_diag_offset_after_trans( obj_t* obj ) { return ( doff_t ) ( bli_obj_has_trans( obj ) ? -bli_obj_diag_offset( obj ) : bli_obj_diag_offset( obj ) ); } // Diagonal offset modification BLIS_INLINE void bli_obj_set_diag_offset( doff_t offset, obj_t* obj ) { obj->diag_off = ( doff_t )offset; } BLIS_INLINE void bli_obj_negate_diag_offset( obj_t* obj ) { obj->diag_off = -(obj->diag_off); } BLIS_INLINE void bli_obj_inc_diag_offset( doff_t offset, obj_t* obj ) { obj->diag_off += ( doff_t )offset; } // Dimension query BLIS_INLINE dim_t bli_obj_length( obj_t* obj ) { return ( obj->dim[ BLIS_M ] ); } BLIS_INLINE dim_t bli_obj_width( obj_t* obj ) { return ( obj->dim[ BLIS_N ] ); } BLIS_INLINE dim_t bli_obj_dim( mdim_t mdim, obj_t* obj ) { return ( obj->dim[ mdim ] ); } BLIS_INLINE dim_t bli_obj_min_dim( obj_t* obj ) { return bli_min( bli_obj_length( obj ), bli_obj_width( obj ) ); } BLIS_INLINE dim_t bli_obj_max_dim( obj_t* obj ) { return bli_max( bli_obj_length( obj ), bli_obj_width( obj ) ); } BLIS_INLINE dim_t bli_obj_length_after_trans( obj_t* obj ) { return ( bli_obj_has_trans( obj ) ? bli_obj_width( obj ) : bli_obj_length( obj ) ); } BLIS_INLINE dim_t bli_obj_width_after_trans( obj_t* obj ) { return ( bli_obj_has_trans( obj ) ? bli_obj_length( obj ) : bli_obj_width( obj ) ); } BLIS_INLINE bool bli_obj_is_1x1( obj_t* x ) { return ( bool ) ( bli_obj_length( x ) == 1 && bli_obj_width( x ) == 1 ); } // Stride/increment query BLIS_INLINE inc_t bli_obj_row_stride( obj_t* obj ) { return ( obj->rs ); } BLIS_INLINE inc_t bli_obj_col_stride( obj_t* obj ) { return ( obj->cs ); } BLIS_INLINE inc_t bli_obj_imag_stride( obj_t* obj ) { return ( obj->is ); } BLIS_INLINE inc_t bli_obj_row_stride_mag( obj_t* obj ) { return ( inc_t ) ( bli_abs( obj->rs ) ); } BLIS_INLINE inc_t bli_obj_col_stride_mag( obj_t* obj ) { return ( inc_t ) ( bli_abs( obj->cs ) ); } BLIS_INLINE inc_t bli_obj_imag_stride_mag( obj_t* obj ) { return ( inc_t ) ( bli_abs( obj->is ) ); } // Note: The purpose of these functions is to obtain the length and width // of the smallest submatrices of an object that could still encompass // the stored data above (if obj is upper) or below (if obj is lower) // the diagonal. BLIS_INLINE dim_t bli_obj_length_stored( obj_t* obj ) { return ( dim_t ) ( bli_obj_is_upper( obj ) ? bli_min( bli_obj_length( obj ), bli_obj_width( obj ) - bli_obj_diag_offset( obj ) ) : bli_min( bli_obj_length( obj ), bli_obj_length( obj ) + bli_obj_diag_offset( obj ) ) ); } BLIS_INLINE dim_t bli_obj_width_stored( obj_t* obj ) { return ( dim_t ) ( bli_obj_is_lower( obj ) ? bli_min( bli_obj_width( obj ), bli_obj_length( obj ) + bli_obj_diag_offset( obj ) ) : bli_min( bli_obj_width( obj ), bli_obj_width( obj ) - bli_obj_diag_offset( obj ) ) ); } BLIS_INLINE dim_t bli_obj_length_stored_after_trans( obj_t* obj ) { return ( bli_obj_has_trans( obj ) ? bli_obj_width_stored( obj ) : bli_obj_length_stored( obj ) ); } BLIS_INLINE dim_t bli_obj_width_stored_after_trans( obj_t* obj ) { return ( bli_obj_has_trans( obj ) ? bli_obj_length_stored( obj ) : bli_obj_width_stored( obj ) ); } BLIS_INLINE dim_t bli_obj_vector_dim( obj_t* x ) { return ( bli_obj_length( x ) == 1 ? bli_obj_width( x ) : bli_obj_length( x ) ); } BLIS_INLINE inc_t bli_obj_vector_inc( obj_t* x ) { return ( bli_obj_is_1x1( x ) ? 1 : ( bli_obj_length( x ) == 1 ? bli_obj_col_stride( x ) : bli_obj_row_stride( x ) ) ); } BLIS_INLINE bool bli_obj_is_vector( obj_t* x ) { return ( bool ) ( bli_obj_length( x ) == 1 || bli_obj_width( x ) == 1 ); } BLIS_INLINE bool bli_obj_is_row_vector( obj_t* x ) { return ( bool ) ( bli_obj_length( x ) == 1 ); } BLIS_INLINE bool bli_obj_is_col_vector( obj_t* x ) { return ( bool ) ( bli_obj_width( x ) == 1 ); } BLIS_INLINE bool bli_obj_has_zero_dim( obj_t* x ) { return ( bool ) ( bli_obj_length( x ) == 0 || bli_obj_width( x ) == 0 ); } // Dimension modification BLIS_INLINE void bli_obj_set_length( dim_t m, obj_t* obj ) { obj->dim[ BLIS_M ] = m; } BLIS_INLINE void bli_obj_set_width( dim_t n, obj_t* obj ) { obj->dim[ BLIS_N ] = n; } BLIS_INLINE void bli_obj_set_dim( mdim_t mdim, dim_t dim_val, obj_t* obj ) { obj->dim[ mdim ] = dim_val; } BLIS_INLINE void bli_obj_set_dims( dim_t m, dim_t n, obj_t* obj ) { bli_obj_set_length( m, obj ); bli_obj_set_width( n, obj ); } BLIS_INLINE void bli_obj_set_dims_with_trans( trans_t trans, dim_t m, dim_t n, obj_t* obj ) { if ( bli_does_notrans( trans ) ) { bli_obj_set_length( m, obj ); bli_obj_set_width( n, obj ); } else // if ( bli_does_trans( trans ) ) { bli_obj_set_length( n, obj ); bli_obj_set_width( m, obj ); } } // Stride/increment predicates // // NOTE: The following two macros differ from their non-obj counterparts // in that they do not identify m x 1 and 1 x n objects as row-stored and // column-stored, respectively, which is needed when considering packed // objects. But this is okay, since none of the invocations of these // "obj" macros are used on packed matrices. // BLIS_INLINE bool bli_obj_is_row_stored( obj_t* obj ) { return ( bool ) ( bli_obj_col_stride_mag( obj ) == 1 ); } BLIS_INLINE bool bli_obj_is_col_stored( obj_t* obj ) { return ( bool ) ( bli_obj_row_stride_mag( obj ) == 1 ); } BLIS_INLINE bool bli_obj_is_gen_stored( obj_t* obj ) { return ( bool ) ( bli_obj_row_stride_mag( obj ) != 1 && bli_obj_col_stride_mag( obj ) != 1 ); } BLIS_INLINE bool bli_obj_is_row_tilted( obj_t* obj ) { return ( bool ) ( bli_obj_col_stride_mag( obj ) < bli_obj_row_stride_mag( obj ) ); } BLIS_INLINE bool bli_obj_is_col_tilted( obj_t* obj ) { return ( bool ) ( bli_obj_row_stride_mag( obj ) < bli_obj_col_stride_mag( obj ) ); } // Stride/increment modification BLIS_INLINE void bli_obj_set_row_stride( inc_t rs, obj_t* obj ) { obj->rs = rs; } BLIS_INLINE void bli_obj_set_col_stride( inc_t cs, obj_t* obj ) { obj->cs = cs; } BLIS_INLINE void bli_obj_set_strides( inc_t rs, inc_t cs, obj_t* obj ) { bli_obj_set_row_stride( rs, obj ); bli_obj_set_col_stride( cs, obj ); } BLIS_INLINE void bli_obj_set_imag_stride( inc_t is, obj_t* obj ) { obj->is = is; } // Offset query BLIS_INLINE dim_t bli_obj_row_off( obj_t* obj ) { return ( obj->off[ BLIS_M ] ); } BLIS_INLINE dim_t bli_obj_col_off( obj_t* obj ) { return ( obj->off[ BLIS_N ] ); } BLIS_INLINE dim_t bli_obj_off( mdim_t mdim, obj_t* obj ) { return ( obj->off[ mdim ] ); } // Offset modification BLIS_INLINE void bli_obj_set_off( mdim_t mdim, dim_t offset, obj_t* obj ) { obj->off[ mdim ] = offset; } BLIS_INLINE void bli_obj_set_offs( dim_t offm, dim_t offn, obj_t* obj ) { bli_obj_set_off( BLIS_M, offm, obj ); bli_obj_set_off( BLIS_N, offn, obj ); } BLIS_INLINE void bli_obj_inc_off( mdim_t mdim, dim_t offset, obj_t* obj ) { obj->off[ mdim ] += offset; } BLIS_INLINE void bli_obj_inc_offs( dim_t offm, dim_t offn, obj_t* obj ) { bli_obj_inc_off( BLIS_M, offm, obj ); bli_obj_inc_off( BLIS_N, offn, obj ); } // Diagonal offset predicates BLIS_INLINE bool bli_obj_is_strictly_above_diag( obj_t* obj ) { return ( bool ) ( ( doff_t )bli_obj_length( obj ) <= -bli_obj_diag_offset( obj ) ); } BLIS_INLINE bool bli_obj_is_strictly_below_diag( obj_t* obj ) { return ( bool ) ( ( doff_t )bli_obj_width( obj ) <= bli_obj_diag_offset( obj ) ); } BLIS_INLINE bool bli_obj_is_outside_diag( obj_t* obj ) { return ( bool ) ( bli_obj_is_strictly_above_diag( obj ) || bli_obj_is_strictly_below_diag( obj ) ); } BLIS_INLINE bool bli_obj_intersects_diag( obj_t* obj ) { return ( bool ) ( !bli_obj_is_strictly_above_diag( obj ) && !bli_obj_is_strictly_below_diag( obj ) ); } BLIS_INLINE bool bli_obj_is_unstored_subpart( obj_t* obj ) { return ( bool ) ( ( bli_obj_root_is_lower( obj ) && bli_obj_is_strictly_above_diag( obj ) ) || ( bli_obj_root_is_upper( obj ) && bli_obj_is_strictly_below_diag( obj ) ) ); } // Buffer address query BLIS_INLINE void* bli_obj_buffer( obj_t* obj ) { return ( void* ) ( obj->buffer ); } // Buffer address modification BLIS_INLINE void bli_obj_set_buffer( void* p, obj_t* obj ) { obj->buffer = p; } // Bufferless scalar field query BLIS_INLINE void* bli_obj_internal_scalar_buffer( obj_t* obj ) { return ( void* ) ( &( obj->scalar ) ); } // Bufferless scalar field modification BLIS_INLINE void bli_obj_copy_internal_scalar( obj_t* a, obj_t* b ) { b->scalar = a->scalar; } // Element size query BLIS_INLINE siz_t bli_obj_elem_size( obj_t* obj ) { return ( siz_t ) ( obj->elem_size ); } // Element size modification BLIS_INLINE void bli_obj_set_elem_size( siz_t size, obj_t* obj ) { obj->elem_size = size; } // Packed matrix info query BLIS_INLINE dim_t bli_obj_padded_length( obj_t* obj ) { return ( obj->m_padded ); } BLIS_INLINE dim_t bli_obj_padded_width( obj_t* obj ) { return ( obj->n_padded ); } // Packed matrix info modification BLIS_INLINE void bli_obj_set_padded_length( dim_t m, obj_t* obj ) { obj->m_padded = m; } BLIS_INLINE void bli_obj_set_padded_width( dim_t n, obj_t* obj ) { obj->n_padded = n; } BLIS_INLINE void bli_obj_set_padded_dims( dim_t m, dim_t n, obj_t* obj ) { bli_obj_set_padded_length( m, obj ); bli_obj_set_padded_width( n, obj ); } // Packed panel info query BLIS_INLINE dim_t bli_obj_panel_length( obj_t* obj ) { return ( obj->m_panel ); } BLIS_INLINE dim_t bli_obj_panel_width( obj_t* obj ) { return ( obj->n_panel ); } BLIS_INLINE inc_t bli_obj_panel_dim( obj_t* obj ) { return ( obj->pd ); } BLIS_INLINE inc_t bli_obj_panel_stride( obj_t* obj ) { return ( obj->ps ); } // Packed panel info modification BLIS_INLINE void bli_obj_set_panel_length( dim_t m, obj_t* obj ) { obj->m_panel = m; } BLIS_INLINE void bli_obj_set_panel_width( dim_t n, obj_t* obj ) { obj->n_panel = n; } BLIS_INLINE void bli_obj_set_panel_dims( dim_t m, dim_t n, obj_t* obj ) { bli_obj_set_panel_length( m, obj ); bli_obj_set_panel_width( n, obj ); } BLIS_INLINE void bli_obj_set_panel_dim( inc_t pd, obj_t* obj ) { obj->pd = pd; } BLIS_INLINE void bli_obj_set_panel_stride( inc_t ps, obj_t* obj ) { obj->ps = ps; } // stor3_t-related BLIS_INLINE stor3_t bli_obj_stor3_from_strides( obj_t* c, obj_t* a, obj_t* b ) { const inc_t rs_c = bli_obj_row_stride( c ); const inc_t cs_c = bli_obj_col_stride( c ); inc_t rs_a, cs_a; inc_t rs_b, cs_b; if ( bli_obj_has_notrans( a ) ) { rs_a = bli_obj_row_stride( a ); cs_a = bli_obj_col_stride( a ); } else { rs_a = bli_obj_col_stride( a ); cs_a = bli_obj_row_stride( a ); } if ( bli_obj_has_notrans( b ) ) { rs_b = bli_obj_row_stride( b ); cs_b = bli_obj_col_stride( b ); } else { rs_b = bli_obj_col_stride( b ); cs_b = bli_obj_row_stride( b ); } return bli_stor3_from_strides( rs_c, cs_c, rs_a, cs_a, rs_b, cs_b ); } // -- User-provided information macros -- // Function pointer query BLIS_INLINE obj_pack_fn_t bli_obj_pack_fn( obj_t* obj ) { return obj->pack_fn; } BLIS_INLINE void* bli_obj_pack_params( obj_t* obj ) { return obj->pack_params; } BLIS_INLINE obj_ker_fn_t bli_obj_ker_fn( obj_t* obj ) { return obj->ker_fn; } BLIS_INLINE void* bli_obj_ker_params( obj_t* obj ) { return obj->ker_params; } // Function pointer modification BLIS_INLINE void bli_obj_set_pack_fn( obj_pack_fn_t pack_fn, obj_t* obj ) { obj->pack_fn = pack_fn; } BLIS_INLINE void bli_obj_set_pack_params( void* params, obj_t* obj ) { obj->pack_params = params; } BLIS_INLINE void bli_obj_set_ker_fn( obj_ker_fn_t ker_fn, obj_t* obj ) { obj->ker_fn = ker_fn; } BLIS_INLINE void bli_obj_set_ker_params( void* params, obj_t* obj ) { obj->ker_params = params; } // -- Initialization-related macros -- // Finish the initialization started by the matrix-specific static initializer // (e.g. BLIS_OBJECT_INITIALIZER) // NOTE: This is intended only for use in the BLAS compatibility API and typed // BLIS API. BLIS_INLINE void bli_obj_init_finish( num_t dt, dim_t m, dim_t n, void* p, inc_t rs, inc_t cs, obj_t* obj ) { bli_obj_set_as_root( obj ); bli_obj_set_dt( dt, obj ); bli_obj_set_target_dt( dt, obj ); bli_obj_set_exec_dt( dt, obj ); bli_obj_set_comp_dt( dt, obj ); bli_obj_set_dims( m, n, obj ); bli_obj_set_strides( rs, cs, obj ); siz_t elem_size = sizeof( float ); if ( bli_dt_prec_is_double( dt ) ) elem_size *= 2; if ( bli_dt_dom_is_complex( dt ) ) elem_size *= 2; bli_obj_set_elem_size( elem_size, obj ); bli_obj_set_buffer( p, obj ); bli_obj_set_scalar_dt( dt, obj ); void* restrict s = bli_obj_internal_scalar_buffer( obj ); if ( bli_dt_prec_is_single( dt ) ) { (( scomplex* )s)->real = 1.0F; (( scomplex* )s)->imag = 0.0F; } else if ( bli_dt_prec_is_double( dt ) ) { (( dcomplex* )s)->real = 1.0; (( dcomplex* )s)->imag = 0.0; } } // Finish the initialization started by the 1x1-specific static initializer // (e.g. BLIS_OBJECT_INITIALIZER_1X1) // NOTE: This is intended only for use in the BLAS compatibility API and typed // BLIS API. BLIS_INLINE void bli_obj_init_finish_1x1( num_t dt, void* p, obj_t* obj ) { bli_obj_set_as_root( obj ); bli_obj_set_dt( dt, obj ); bli_obj_set_buffer( p, obj ); } // -- Miscellaneous object macros -- // Toggle the region referenced (or "stored"). BLIS_INLINE void bli_obj_toggle_region_ref( obj_t* obj ) { if ( bli_obj_is_upper( obj ) ) bli_obj_inc_diag_offset( -1, obj ); else if ( bli_obj_is_lower( obj ) ) bli_obj_inc_diag_offset( 1, obj ); bli_obj_toggle_uplo( obj ); } BLIS_INLINE void bli_obj_toggle_uplo_if_trans( trans_t trans, obj_t* obj ) { if ( bli_does_trans( trans ) && bli_obj_is_upper_or_lower( obj ) ) { bli_obj_toggle_uplo( obj ); bli_obj_negate_diag_offset( obj ); } } // Initialize object with default properties (info field). BLIS_INLINE void bli_obj_set_defaults( obj_t* obj ) { obj->info = 0x0; obj->info = obj->info | BLIS_BITVAL_DENSE | BLIS_BITVAL_GENERAL; } // Acquire buffer at object's submatrix offset (offset-aware buffer query). BLIS_INLINE void* bli_obj_buffer_at_off( obj_t* obj ) { return ( void* ) ( ( ( char* )( bli_obj_buffer ( obj ) ) + ( dim_t )( bli_obj_elem_size( obj ) ) * ( bli_obj_col_off( obj ) * bli_obj_col_stride( obj ) + bli_obj_row_off( obj ) * bli_obj_row_stride( obj ) ) ) ); } // Acquire buffer from BLIS_CONSTANT object. BLIS_INLINE void* bli_obj_buffer_for_const( num_t dt, obj_t* obj ) { void* p; if ( dt == BLIS_FLOAT ) p = &((( constdata_t* )bli_obj_buffer( obj ))->s); else if ( dt == BLIS_DOUBLE ) p = &((( constdata_t* )bli_obj_buffer( obj ))->d); else if ( dt == BLIS_SCOMPLEX ) p = &((( constdata_t* )bli_obj_buffer( obj ))->c); else if ( dt == BLIS_DCOMPLEX ) p = &((( constdata_t* )bli_obj_buffer( obj ))->z); else p = &((( constdata_t* )bli_obj_buffer( obj ))->i); return p; } // Acquire buffer from scalar (1x1) object, including BLIS_CONSTANT objects. BLIS_INLINE void* bli_obj_buffer_for_1x1( num_t dt, obj_t* obj ) { return ( void* ) ( bli_obj_is_const( obj ) ? bli_obj_buffer_for_const( dt, obj ) : bli_obj_buffer_at_off( obj ) ); } // Adjust the pointer based on current offsets, zero the offsets, and then // set the current object as the root. For obj_t's with at least one non-zero // offset, this effectively makes the obj_t "forget" that it was ever a view // into a larger matrix. BLIS_INLINE void bli_obj_reset_origin( obj_t* obj ) { bli_obj_set_buffer( bli_obj_buffer_at_off( obj ), obj ); bli_obj_set_offs( 0, 0, obj ); bli_obj_set_as_root( obj ); } // Make a full alias (shallow copy). BLIS_INLINE void bli_obj_alias_to( obj_t* a, obj_t* b ) { bli_obj_init_full_shallow_copy_of( a, b ); } // Check if two objects are aliases of one another. BLIS_INLINE bool bli_obj_is_alias_of( obj_t* a, obj_t* b ) { return ( bool ) ( bli_obj_buffer( a ) == bli_obj_buffer( b ) ); } // Create an alias with a trans value applied. // (Note: trans may include a conj component.) BLIS_INLINE void bli_obj_alias_with_trans( trans_t trans, obj_t* a, obj_t* b ) { bli_obj_alias_to( a, b ); bli_obj_apply_trans( trans, b ); } // Create an alias with a conj value applied. BLIS_INLINE void bli_obj_alias_with_conj( conj_t conja, obj_t* a, obj_t* b ) { bli_obj_alias_to( a, b ); bli_obj_apply_conj( conja, b ); } // Alias only the real part. BLIS_INLINE void bli_obj_real_part( obj_t* c, obj_t* r ) { bli_obj_alias_to( c, r ); if ( bli_obj_is_complex( c ) ) { // Change the datatypes. const num_t dt_stor_r = bli_dt_proj_to_real( bli_obj_dt( c ) ); const num_t dt_targ_r = bli_dt_proj_to_real( bli_obj_target_dt( c ) ); const num_t dt_exec_r = bli_dt_proj_to_real( bli_obj_exec_dt( c ) ); const num_t dt_comp_r = bli_dt_proj_to_real( bli_obj_comp_dt( c ) ); bli_obj_set_dt( dt_stor_r, r ); bli_obj_set_target_dt( dt_targ_r, r ); bli_obj_set_exec_dt( dt_exec_r, r ); bli_obj_set_comp_dt( dt_comp_r, r ); // Don't touch the attached scalar datatype. // Update the element size. siz_t es_c = bli_obj_elem_size( c ); bli_obj_set_elem_size( es_c/2, r ); // Update the strides. inc_t rs_c = bli_obj_row_stride( c ); inc_t cs_c = bli_obj_col_stride( c ); bli_obj_set_strides( 2*rs_c, 2*cs_c, r ); // Buffer is left unchanged. } } // Alias only the imaginary part. BLIS_INLINE void bli_obj_imag_part( obj_t* c, obj_t* i ) { if ( bli_obj_is_complex( c ) ) { bli_obj_alias_to( c, i ); // Change the datatype. const num_t dt_stor_r = bli_dt_proj_to_real( bli_obj_dt( c ) ); const num_t dt_targ_r = bli_dt_proj_to_real( bli_obj_target_dt( c ) ); const num_t dt_exec_r = bli_dt_proj_to_real( bli_obj_exec_dt( c ) ); const num_t dt_comp_r = bli_dt_proj_to_real( bli_obj_comp_dt( c ) ); bli_obj_set_dt( dt_stor_r, i ); bli_obj_set_target_dt( dt_targ_r, i ); bli_obj_set_exec_dt( dt_exec_r, i ); bli_obj_set_comp_dt( dt_comp_r, i ); // Don't touch the attached scalar datatype. // Update the element size. siz_t es_c = bli_obj_elem_size( c ); bli_obj_set_elem_size( es_c/2, i ); // Update the strides. inc_t rs_c = bli_obj_row_stride( c ); inc_t cs_c = bli_obj_col_stride( c ); bli_obj_set_strides( 2*rs_c, 2*cs_c, i ); // Update the buffer. inc_t is_c = bli_obj_imag_stride( c ); char* p = ( char* )bli_obj_buffer_at_off( c ); bli_obj_set_buffer( p + is_c * es_c/2, i ); } } // Given a 1x1 object, acquire an address to the buffer depending on whether // the object is a BLIS_CONSTANT, and also set a datatype associated with the // chosen buffer (possibly using an auxiliary datatype if the object is // BLIS_CONSTANT). BLIS_INLINE void bli_obj_scalar_set_dt_buffer( obj_t* obj, num_t dt_aux, num_t* dt, void** buf ) { if ( bli_obj_is_const( obj ) ) { *dt = dt_aux; *buf = bli_obj_buffer_for_1x1( dt_aux, obj ); } else { *dt = bli_obj_dt( obj ); *buf = bli_obj_buffer_at_off( obj ); } } // Swap all object fields (metadata/properties). BLIS_INLINE void bli_obj_swap( obj_t* a, obj_t* b ) { bool a_root_is_self = ( bli_obj_root( a ) == a ); bool b_root_is_self = ( bli_obj_root( b ) == b ); obj_t t = *b; *b = *a; *a = t; if ( a_root_is_self ) bli_obj_set_as_root( b ); if ( b_root_is_self ) bli_obj_set_as_root( a ); } // Swap object pack schemas. BLIS_INLINE void bli_obj_swap_pack_schemas( obj_t* a, obj_t* b ) { const pack_t schema_a = bli_obj_pack_schema( a ); const pack_t schema_b = bli_obj_pack_schema( b ); bli_obj_set_pack_schema( schema_b, a ); bli_obj_set_pack_schema( schema_a, b ); } // Induce a transposition on an object: swap dimensions, increments, and // offsets, then clear the trans bit. BLIS_INLINE void bli_obj_induce_trans( obj_t* obj ) { // Induce transposition among basic fields. dim_t m = bli_obj_length( obj ); dim_t n = bli_obj_width( obj ); inc_t rs = bli_obj_row_stride( obj ); inc_t cs = bli_obj_col_stride( obj ); dim_t offm = bli_obj_row_off( obj ); dim_t offn = bli_obj_col_off( obj ); doff_t diag_off = bli_obj_diag_offset( obj ); bli_obj_set_dims( n, m, obj ); bli_obj_set_strides( cs, rs, obj ); bli_obj_set_offs( offn, offm, obj ); bli_obj_set_diag_offset( -diag_off, obj ); if ( bli_obj_is_upper_or_lower( obj ) ) bli_obj_toggle_uplo( obj ); // Induce transposition among packed fields. dim_t m_padded = bli_obj_padded_length( obj ); dim_t n_padded = bli_obj_padded_width( obj ); dim_t m_panel = bli_obj_panel_length( obj ); dim_t n_panel = bli_obj_panel_width( obj ); bli_obj_set_padded_dims( n_padded, m_padded, obj ); bli_obj_set_panel_dims( n_panel, m_panel, obj ); // Note that this macro DOES NOT touch the transposition bit! If // the calling code is using this function to handle an object whose // transposition bit is set prior to computation, that code needs // to manually clear or toggle the bit, via // bli_obj_set_onlytrans() or bli_obj_toggle_trans(), // respectively. } BLIS_INLINE void bli_obj_induce_fast_trans( obj_t* obj ) { // NOTE: This function is only used in situations where the matrices // are guaranteed to not have structure or be packed. // Induce transposition among basic fields. dim_t m = bli_obj_length( obj ); dim_t n = bli_obj_width( obj ); inc_t rs = bli_obj_row_stride( obj ); inc_t cs = bli_obj_col_stride( obj ); dim_t offm = bli_obj_row_off( obj ); dim_t offn = bli_obj_col_off( obj ); bli_obj_set_dims( n, m, obj ); bli_obj_set_strides( cs, rs, obj ); bli_obj_set_offs( offn, offm, obj ); // Note that this macro DOES NOT touch the transposition bit! If // the calling code is using this function to handle an object whose // transposition bit is set prior to computation, that code needs // to manually clear or toggle the bit, via // bli_obj_set_onlytrans() or bli_obj_toggle_trans(), // respectively. } // Sometimes we need to "reflect" a partition because the data we want is // actually stored on the other side of the diagonal. The nuts and bolts of // this macro look a lot like an induced transposition, except that the row // and column strides are left unchanged (which, of course, drastically // changes the effect of the macro). BLIS_INLINE void bli_obj_reflect_about_diag( obj_t* obj ) { dim_t m = bli_obj_length( obj ); dim_t n = bli_obj_width( obj ); dim_t offm = bli_obj_row_off( obj ); dim_t offn = bli_obj_col_off( obj ); doff_t diag_off = bli_obj_diag_offset( obj ); bli_obj_set_dims( n, m, obj ); bli_obj_set_offs( offn, offm, obj ); bli_obj_set_diag_offset( -diag_off, obj ); bli_obj_toggle_trans( obj ); } #endif blis-0.9.0/frame/include/bli_param_macro_defs.h000066400000000000000000001020271422157504600214570ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_PARAM_MACRO_DEFS_H #define BLIS_PARAM_MACRO_DEFS_H // -- Parameter query macros -- // buffer BLIS_INLINE bool bli_is_aligned_to( siz_t p, siz_t size ) { return ( bool ) ( p % size == 0 ); } BLIS_INLINE bool bli_is_unaligned_to( siz_t p, siz_t size ) { return ( bool ) ( p % size != 0 ); } BLIS_INLINE siz_t bli_offset_past_alignment( siz_t p, siz_t size ) { return ( siz_t ) ( p % size ); } // datatype BLIS_INLINE bool bli_is_float( num_t dt ) { return ( bool ) ( dt == BLIS_FLOAT ); } BLIS_INLINE bool bli_is_double( num_t dt ) { return ( bool ) ( dt == BLIS_DOUBLE ); } BLIS_INLINE bool bli_is_scomplex( num_t dt ) { return ( bool ) ( dt == BLIS_SCOMPLEX ); } BLIS_INLINE bool bli_is_dcomplex( num_t dt ) { return ( bool ) ( dt == BLIS_DCOMPLEX ); } BLIS_INLINE bool bli_is_constant( num_t dt ) { return ( bool ) ( dt == BLIS_CONSTANT ); } BLIS_INLINE bool bli_is_int( num_t dt ) { return ( bool ) ( dt == BLIS_INT ); } BLIS_INLINE bool bli_is_real( num_t dt ) { return ( bool ) ( bli_is_float( dt ) || bli_is_double( dt ) ); } BLIS_INLINE bool bli_is_complex( num_t dt ) { return ( bool ) ( bli_is_scomplex( dt ) || bli_is_dcomplex( dt ) ); } BLIS_INLINE bool bli_is_single_prec( num_t dt ) { return ( bool ) ( bli_is_float( dt ) || bli_is_scomplex( dt ) ); } BLIS_INLINE bool bli_is_double_prec( num_t dt ) { return ( bool ) ( bli_is_double( dt ) || bli_is_dcomplex( dt ) ); } BLIS_INLINE dom_t bli_dt_domain( num_t dt ) { return ( dom_t ) ( dt & BLIS_DOMAIN_BIT ); } BLIS_INLINE bool bli_dt_dom_is_real( num_t dt ) { return ( bool ) ( ( dt & BLIS_DOMAIN_BIT ) == BLIS_REAL ); } BLIS_INLINE bool bli_dt_dom_is_complex( num_t dt ) { return ( bool ) ( ( dt & BLIS_DOMAIN_BIT ) == BLIS_COMPLEX ); } BLIS_INLINE prec_t bli_dt_prec( num_t dt ) { return ( prec_t ) ( dt & BLIS_PRECISION_BIT ); } BLIS_INLINE bool bli_dt_prec_is_single( num_t dt ) { return ( bool ) ( ( dt & BLIS_PRECISION_BIT ) == BLIS_SINGLE_PREC ); } BLIS_INLINE bool bli_dt_prec_is_double( num_t dt ) { return ( bool ) ( ( dt & BLIS_PRECISION_BIT ) == BLIS_DOUBLE_PREC ); } BLIS_INLINE num_t bli_dt_proj_to_real( num_t dt ) { return ( num_t ) ( dt & ~BLIS_BITVAL_COMPLEX ); } BLIS_INLINE num_t bli_dt_proj_to_complex( num_t dt ) { return ( num_t ) ( dt | BLIS_BITVAL_COMPLEX ); } BLIS_INLINE num_t bli_dt_proj_to_single_prec( num_t dt ) { return ( num_t ) ( dt & ~BLIS_BITVAL_DOUBLE_PREC ); } BLIS_INLINE num_t bli_dt_proj_to_double_prec( num_t dt ) { return ( num_t ) ( dt | BLIS_BITVAL_DOUBLE_PREC ); } // trans BLIS_INLINE bool bli_is_notrans( trans_t trans ) { return ( bool ) ( trans == BLIS_NO_TRANSPOSE ); } BLIS_INLINE bool bli_is_trans( trans_t trans ) { return ( bool ) ( trans == BLIS_TRANSPOSE ); } BLIS_INLINE bool bli_is_conjnotrans( trans_t trans ) { return ( bool ) ( trans == BLIS_CONJ_NO_TRANSPOSE ); } BLIS_INLINE bool bli_is_conjtrans( trans_t trans ) { return ( bool ) ( trans == BLIS_CONJ_TRANSPOSE ); } BLIS_INLINE bool bli_does_notrans( trans_t trans ) { return ( bool ) ( (~trans & BLIS_TRANS_BIT ) == BLIS_BITVAL_TRANS ); } BLIS_INLINE bool bli_does_trans( trans_t trans ) { return ( bool ) ( ( trans & BLIS_TRANS_BIT ) == BLIS_BITVAL_TRANS ); } BLIS_INLINE bool bli_does_noconj( trans_t trans ) { return ( bool ) ( (~trans & BLIS_CONJ_BIT ) == BLIS_BITVAL_CONJ ); } BLIS_INLINE bool bli_does_conj( trans_t trans ) { return ( bool ) ( ( trans & BLIS_CONJ_BIT ) == BLIS_BITVAL_CONJ ); } BLIS_INLINE trans_t bli_extract_trans( trans_t trans ) { return ( trans_t ) ( trans & BLIS_TRANS_BIT ); } BLIS_INLINE conj_t bli_extract_conj( trans_t trans ) { return ( conj_t ) ( trans & BLIS_CONJ_BIT ); } BLIS_INLINE trans_t bli_trans_toggled( trans_t trans ) { return ( trans_t ) ( trans ^ BLIS_TRANS_BIT ); } BLIS_INLINE trans_t bli_trans_toggled_conj( trans_t trans ) { return ( trans_t ) ( trans ^ BLIS_CONJ_BIT ); } BLIS_INLINE trans_t bli_apply_trans( trans_t transapp, trans_t trans ) { return ( trans_t ) ( trans ^ transapp ); } BLIS_INLINE void bli_toggle_trans( trans_t* trans ) { *trans = bli_trans_toggled( *trans ); } // side BLIS_INLINE bool bli_is_left( side_t side ) { return ( bool ) ( side == BLIS_LEFT ); } BLIS_INLINE bool bli_is_right( side_t side ) { return ( bool ) ( side == BLIS_RIGHT ); } BLIS_INLINE side_t bli_side_toggled( side_t side ) { return ( bli_is_left( side ) ? BLIS_RIGHT : BLIS_LEFT ); } BLIS_INLINE void bli_toggle_side( side_t* side ) { *side = bli_side_toggled( *side ); } // uplo BLIS_INLINE bool bli_is_lower( uplo_t uplo ) { return ( bool ) ( uplo == BLIS_LOWER ); } BLIS_INLINE bool bli_is_upper( uplo_t uplo ) { return ( bool ) ( uplo == BLIS_UPPER ); } BLIS_INLINE bool bli_is_upper_or_lower( uplo_t uplo ) { return ( bool ) ( bli_is_upper( uplo ) || bli_is_lower( uplo ) ); } BLIS_INLINE bool bli_is_dense( uplo_t uplo ) { return ( bool ) ( uplo == BLIS_DENSE ); } BLIS_INLINE bool bli_is_zeros( uplo_t uplo ) { return ( bool ) ( uplo == BLIS_ZEROS ); } BLIS_INLINE uplo_t bli_uplo_toggled( uplo_t uplo ) { return ( uplo_t ) ( bli_is_upper_or_lower( uplo ) ? ( ( uplo ^ BLIS_LOWER_BIT ) ^ BLIS_UPPER_BIT ) : uplo ); } BLIS_INLINE void bli_toggle_uplo( uplo_t* uplo ) { *uplo = bli_uplo_toggled( *uplo ); } // structure BLIS_INLINE bool bli_is_general( struc_t struc ) { return ( bool ) ( struc == BLIS_GENERAL ); } BLIS_INLINE bool bli_is_hermitian( struc_t struc ) { return ( bool ) ( struc == BLIS_HERMITIAN ); } BLIS_INLINE bool bli_is_symmetric( struc_t struc ) { return ( bool ) ( struc == BLIS_SYMMETRIC ); } BLIS_INLINE bool bli_is_triangular( struc_t struc ) { return ( bool ) ( struc == BLIS_TRIANGULAR ); } BLIS_INLINE bool bli_is_herm_or_symm( struc_t struc ) { return ( bool ) ( bli_is_hermitian( struc ) || bli_is_symmetric( struc ) ); } // conj BLIS_INLINE bool bli_is_noconj( conj_t conj ) { return ( bool ) ( conj == BLIS_NO_CONJUGATE ); } BLIS_INLINE bool bli_is_conj( conj_t conj ) { return ( bool ) ( conj == BLIS_CONJUGATE ); } BLIS_INLINE conj_t bli_conj_toggled( conj_t conj ) { return ( conj_t ) ( conj ^ BLIS_CONJ_BIT ); } BLIS_INLINE conj_t bli_apply_conj( conj_t conjapp, conj_t conj ) { return ( conj_t ) ( conj ^ conjapp ); } BLIS_INLINE void bli_toggle_conj( conj_t* conj ) { *conj = bli_conj_toggled( *conj ); } // diag BLIS_INLINE bool bli_is_nonunit_diag( diag_t diag ) { return ( bool ) ( diag == BLIS_NONUNIT_DIAG ); } BLIS_INLINE bool bli_is_unit_diag( diag_t diag ) { return ( bool ) ( diag == BLIS_UNIT_DIAG ); } // err_t-related BLIS_INLINE bool bli_is_success( err_t err ) { return ( bool ) ( err == BLIS_SUCCESS ); } BLIS_INLINE bool bli_is_failure( err_t err ) { return ( bool ) ( err != BLIS_SUCCESS ); } // dimension-related BLIS_INLINE bool bli_zero_dim1( dim_t m ) { return ( bool ) ( m == 0 ); } BLIS_INLINE bool bli_zero_dim2( dim_t m, dim_t n ) { return ( bool ) ( m == 0 || n == 0 ); } BLIS_INLINE bool bli_zero_dim3( dim_t m, dim_t n, dim_t k ) { return ( bool ) ( m == 0 || n == 0 || k == 0 ); } BLIS_INLINE bool bli_nonzero_dim( dim_t m ) { return ( bool ) ( m > 0 ); } BLIS_INLINE bool bli_vector_dim( dim_t m, dim_t n ) { return ( bool ) ( m == 1 ? n : m ); } BLIS_INLINE bool bli_is_vector( dim_t m, dim_t n ) { return ( bool ) ( m == 1 || n == 1 ); } BLIS_INLINE bool bli_is_row_vector( dim_t m, dim_t n ) { return ( bool ) ( m == 1 ); } BLIS_INLINE bool bli_is_col_vector( dim_t m, dim_t n ) { return ( bool ) ( n == 1 ); } BLIS_INLINE void bli_set_dim_with_side( side_t side, dim_t m, dim_t n, dim_t* dim ) { if ( bli_is_left( side ) ) *dim = m; else *dim = n; } BLIS_INLINE void bli_set_dims_with_trans( trans_t trans, dim_t m, dim_t n, dim_t* mt, dim_t* nt ) { if ( bli_does_notrans( trans ) ) { *mt = m; *nt = n; } else { *mt = n; *nt = m; } } BLIS_INLINE void bli_set_dims_incs_with_trans( trans_t trans, dim_t m, dim_t n, inc_t rs, inc_t cs, dim_t* mt, dim_t* nt, inc_t* rst, inc_t* cst ) { if ( bli_does_notrans( trans ) ) { *mt = m; *nt = n; *rst = rs; *cst = cs; } else { *mt = n; *nt = m; *rst = cs; *cst = rs; } } // blocksize-related BLIS_INLINE dim_t bli_determine_blocksize_dim_f( dim_t i, dim_t dim, dim_t b_alg ) { return ( dim_t ) ( bli_min( b_alg, dim - i ) ); } BLIS_INLINE dim_t bli_determine_blocksize_dim_b( dim_t i, dim_t dim, dim_t b_alg ) { return ( dim_t ) ( i == 0 && dim % b_alg != 0 ? dim % b_alg : b_alg ); } // stride-related BLIS_INLINE inc_t bli_vector_inc( trans_t trans, dim_t m, dim_t n, inc_t rs, inc_t cs ) { return ( inc_t ) ( bli_does_notrans( trans ) ? ( m == 1 ? cs : rs ) : ( m == 1 ? rs : cs ) ); } BLIS_INLINE bool bli_is_row_stored( inc_t rs, inc_t cs ) { return ( bool ) ( bli_abs( cs ) == 1 ); } BLIS_INLINE bool bli_is_col_stored( inc_t rs, inc_t cs ) { return ( bool ) ( bli_abs( rs ) == 1 ); } BLIS_INLINE bool bli_is_row_stored_f( dim_t m, dim_t n, inc_t rs, inc_t cs ) { return ( bool ) ( cs == 1 && ( rs > 1 || n == 1 ) ); } BLIS_INLINE bool bli_is_col_stored_f( dim_t m, dim_t n, inc_t rs, inc_t cs ) { return ( bool ) ( rs == 1 && ( cs > 1 || m == 1 ) ); } BLIS_INLINE bool bli_is_gen_stored( inc_t rs, inc_t cs ) { return ( bool ) ( bli_abs( rs ) != 1 && bli_abs( cs ) != 1 ); } BLIS_INLINE bool bli_is_row_tilted( dim_t m, dim_t n, inc_t rs, inc_t cs ) { return ( bool ) ( bli_abs( cs ) == bli_abs( rs ) ? n < m : bli_abs( cs ) < bli_abs( rs ) ); } BLIS_INLINE bool bli_is_col_tilted( dim_t m, dim_t n, inc_t rs, inc_t cs ) { return ( bool ) ( bli_abs( rs ) == bli_abs( cs ) ? m < n : bli_abs( rs ) < bli_abs( cs ) ); } BLIS_INLINE bool bli_has_nonunit_inc1( inc_t s1 ) { return ( bool ) ( s1 != 1 ); } BLIS_INLINE bool bli_has_nonunit_inc2( inc_t s1, inc_t s2 ) { return ( bool ) ( s1 != 1 || s2 != 1 ); } BLIS_INLINE bool bli_has_nonunit_inc3( inc_t s1, inc_t s2, inc_t s3 ) { return ( bool ) ( s1 != 1 || s2 != 1 || s3 != 1 ); } // diag offset-related BLIS_INLINE void bli_negate_diag_offset( doff_t* diagoff ) { *diagoff = -(*diagoff); } BLIS_INLINE void bli_shift_diag_offset_to_grow_uplo( uplo_t uplo, doff_t* diagoff ) { if ( bli_is_upper( uplo ) ) *diagoff -= 1; else if ( bli_is_lower( uplo ) ) *diagoff += 1; } BLIS_INLINE void bli_shift_diag_offset_to_shrink_uplo( uplo_t uplo, doff_t* diagoff ) { if ( bli_is_upper( uplo ) ) *diagoff += 1; else if ( bli_is_lower( uplo ) ) *diagoff -= 1; } BLIS_INLINE doff_t bli_diag_offset_with_trans( trans_t trans, doff_t diagoff ) { return ( doff_t ) ( bli_does_trans( trans ) ? -diagoff : diagoff ); } BLIS_INLINE bool bli_is_strictly_above_diag( doff_t diagoff, trans_t trans, dim_t m, dim_t n ) { return ( bool ) ( bli_does_trans( trans ) ? ( ( doff_t )n <= -diagoff ) : ( ( doff_t )m <= -diagoff ) ); } BLIS_INLINE bool bli_is_strictly_below_diag( doff_t diagoff, trans_t trans, dim_t m, dim_t n ) { return ( bool ) ( bli_does_trans( trans ) ? ( ( doff_t )m <= diagoff ) : ( ( doff_t )n <= diagoff ) ); } BLIS_INLINE bool bli_is_outside_diag( doff_t diagoff, trans_t trans, dim_t m, dim_t n ) { return ( bool ) ( bli_is_strictly_above_diag( diagoff, trans, m, n ) || bli_is_strictly_below_diag( diagoff, trans, m, n ) ); } BLIS_INLINE bool bli_is_stored_subpart( doff_t diagoff, trans_t trans, uplo_t uplo, dim_t m, dim_t n ) { return ( bool ) ( ( bli_is_upper( uplo ) && bli_is_strictly_above_diag( diagoff, trans, m, n ) ) || ( bli_is_lower( uplo ) && bli_is_strictly_below_diag( diagoff, trans, m, n ) ) ); } BLIS_INLINE bool bli_is_unstored_subpart( doff_t diagoff, trans_t trans, uplo_t uplo, dim_t m, dim_t n ) { return ( bool ) ( ( bli_is_upper( uplo ) && bli_is_strictly_below_diag( diagoff, trans, m, n ) ) || ( bli_is_lower( uplo ) && bli_is_strictly_above_diag( diagoff, trans, m, n ) ) ); } BLIS_INLINE bool bli_is_strictly_above_diag_n( doff_t diagoff, dim_t m, dim_t n ) { return ( bool ) ( ( doff_t )m <= -diagoff ); } BLIS_INLINE bool bli_is_strictly_below_diag_n( doff_t diagoff, dim_t m, dim_t n ) { return ( bool ) ( ( doff_t )n <= diagoff ); } BLIS_INLINE bool bli_intersects_diag_n( doff_t diagoff, dim_t m, dim_t n ) { return ( bool ) ( !bli_is_strictly_above_diag_n( diagoff, m, n ) && !bli_is_strictly_below_diag_n( diagoff, m, n ) ); } BLIS_INLINE bool bli_is_outside_diag_n( doff_t diagoff, dim_t m, dim_t n ) { return ( bool ) ( bli_is_strictly_above_diag_n( diagoff, m, n ) || bli_is_strictly_below_diag_n( diagoff, m, n ) ); } BLIS_INLINE bool bli_is_stored_subpart_n( doff_t diagoff, uplo_t uplo, dim_t m, dim_t n ) { return ( bool ) ( ( bli_is_upper( uplo ) && bli_is_strictly_above_diag_n( diagoff, m, n ) ) || ( bli_is_lower( uplo ) && bli_is_strictly_below_diag_n( diagoff, m, n ) ) ); } BLIS_INLINE bool bli_is_unstored_subpart_n( doff_t diagoff, uplo_t uplo, dim_t m, dim_t n ) { return ( bool ) ( ( bli_is_upper( uplo ) && bli_is_strictly_below_diag_n( diagoff, m, n ) ) || ( bli_is_lower( uplo ) && bli_is_strictly_above_diag_n( diagoff, m, n ) ) ); } // pruning-related BLIS_INLINE void bli_prune_unstored_region_top_l( doff_t* diagoff, dim_t* m, dim_t* n, dim_t* offm_inc ) { *offm_inc = 0; // If the diagonal intersects the left side of the matrix, // ignore the area above that intersection. if ( *diagoff < 0 ) { *m = *m + *diagoff; *offm_inc = - *diagoff; *diagoff = 0; } } BLIS_INLINE void bli_prune_unstored_region_right_l( doff_t* diagoff, dim_t* m, dim_t* n, dim_t* offn_inc ) { *offn_inc = 0; // If the diagonal intersects the bottom side of the matrix, // ignore the area to the right of that intersection. if ( *n > *diagoff + *m ) { *n = *diagoff + *m; } } BLIS_INLINE void bli_prune_unstored_region_left_u( doff_t* diagoff, dim_t* m, dim_t* n, dim_t* offn_inc ) { *offn_inc = 0; // If the diagonal intersects the top side of the matrix, // ignore the area to the left of that intersection. if ( *diagoff > 0 ) { *n = *n - *diagoff; *offn_inc = + *diagoff; *diagoff = 0; } } BLIS_INLINE void bli_prune_unstored_region_bottom_u( doff_t* diagoff, dim_t* m, dim_t* n, dim_t* offm_inc ) { *offm_inc = 0; // If the diagonal intersects the right side of the matrix, // ignore the area below that intersection. if ( *m > -(*diagoff) + *n ) { *m = -(*diagoff) + *n; } } // thread range-related BLIS_INLINE void bli_rotate180_trapezoid( doff_t* diagoff, uplo_t* uplo, dim_t* m, dim_t* n ) { *diagoff = *n - *diagoff - *m; bli_toggle_uplo( uplo ); } BLIS_INLINE void bli_reflect_about_diag( doff_t* diagoff, uplo_t* uplo, dim_t* m, dim_t* n ) { bli_swap_dims( m, n ); bli_negate_diag_offset( diagoff ); bli_toggle_uplo( uplo ); } BLIS_INLINE void bli_reverse_index_direction( dim_t n, dim_t* start, dim_t* end ) { dim_t start2 = n - *start; dim_t end2 = n - *end; *start = end2; *end = start2; } // mdim_t-related BLIS_INLINE bool bli_is_m_dim( mdim_t mdim ) { return ( bool ) ( mdim == BLIS_M ); } BLIS_INLINE bool bli_is_n_dim( mdim_t mdim ) { return ( bool ) ( mdim == BLIS_N ); } BLIS_INLINE mdim_t bli_dim_toggled( mdim_t mdim ) { return ( mdim_t ) ( mdim == BLIS_M ? BLIS_N : BLIS_M ); } BLIS_INLINE void bli_toggle_dim( mdim_t* mdim ) { *mdim = bli_dim_toggled( *mdim ); } // stor3_t-related BLIS_INLINE stor3_t bli_stor3_from_strides( inc_t rs_c, inc_t cs_c, inc_t rs_a, inc_t cs_a, inc_t rs_b, inc_t cs_b ) { // If any matrix is general-stored, return the stor3_t id for the // general-purpose sup microkernel. if ( bli_is_gen_stored( rs_c, cs_c ) || bli_is_gen_stored( rs_a, cs_a ) || bli_is_gen_stored( rs_b, cs_b ) ) return BLIS_XXX; // Otherwise, compute and return the stor3_t id as follows. const bool c_is_col = bli_is_col_stored( rs_c, cs_c ); const bool a_is_col = bli_is_col_stored( rs_a, cs_a ); const bool b_is_col = bli_is_col_stored( rs_b, cs_b ); return ( stor3_t )( 4 * c_is_col + 2 * a_is_col + 1 * b_is_col ); } BLIS_INLINE stor3_t bli_stor3_trans( stor3_t id ) { #if 1 stor3_t map[ BLIS_NUM_3OP_RC_COMBOS ] = { ( stor3_t )7, // BLIS_RRR = 0 -> BLIS_CCC = 7 ( stor3_t )5, // BLIS_RRC = 1 -> BLIS_CRC = 5 ( stor3_t )6, // BLIS_RCR = 2 -> BLIS_CCR = 6 ( stor3_t )4, // BLIS_RCC = 3 -> BLIS_CRR = 4 ( stor3_t )3, // BLIS_CRR = 4 -> BLIS_RCC = 3 ( stor3_t )1, // BLIS_CRC = 5 -> BLIS_RRC = 1 ( stor3_t )2, // BLIS_CCR = 6 -> BLIS_RCR = 2 ( stor3_t )0, // BLIS_CCC = 7 -> BLIS_RRR = 0 }; return map[id]; #else return ( ( id & 0x4 ) ^ 0x4 ) | // flip c bit ( ( ( id & 0x1 ) ^ 0x1 ) << 1 ) | // flip b bit and move to a position ( ( ( id & 0x2 ) ^ 0x2 ) >> 1 ); // flip a bit and move to b position #endif } BLIS_INLINE stor3_t bli_stor3_transa( stor3_t id ) { #if 0 stor3_t map[ BLIS_NUM_3OP_RC_COMBOS ] = { ( stor3_t )1, // BLIS_RRR = 0 -> BLIS_RRC = 1 ( stor3_t )0, // BLIS_RRC = 1 -> BLIS_RRR = 0 ( stor3_t )3, // BLIS_RCR = 2 -> BLIS_RCC = 3 ( stor3_t )2, // BLIS_RCC = 3 -> BLIS_RCR = 2 ( stor3_t )5, // BLIS_CRR = 4 -> BLIS_CRC = 5 ( stor3_t )4, // BLIS_CRC = 5 -> BLIS_CRR = 4 ( stor3_t )7, // BLIS_CCR = 6 -> BLIS_CCC = 7 ( stor3_t )6, // BLIS_CCC = 7 -> BLIS_CCR = 6 }; return map[id]; #else return ( stor3_t )( id ^ 0x1 ); #endif } BLIS_INLINE stor3_t bli_stor3_transb( stor3_t id ) { #if 0 stor3_t map[ BLIS_NUM_3OP_RC_COMBOS ] = { ( stor3_t )2, // BLIS_RRR = 0 -> BLIS_RCR = 2 ( stor3_t )3, // BLIS_RRC = 1 -> BLIS_RCC = 3 ( stor3_t )0, // BLIS_RCR = 2 -> BLIS_RRR = 0 ( stor3_t )1, // BLIS_RCC = 3 -> BLIS_RRC = 1 ( stor3_t )6, // BLIS_CRR = 4 -> BLIS_CCR = 6 ( stor3_t )7, // BLIS_CRC = 5 -> BLIS_CCC = 7 ( stor3_t )4, // BLIS_CCR = 6 -> BLIS_CRR = 4 ( stor3_t )5, // BLIS_CCC = 7 -> BLIS_CRC = 5 }; return map[id]; #else return ( stor3_t )( id ^ 0x2 ); #endif } // index-related BLIS_INLINE bool bli_is_edge_f( dim_t i, dim_t n_iter, dim_t n_left ) { return ( bool ) ( i == n_iter - 1 && n_left != 0 ); } BLIS_INLINE bool bli_is_not_edge_f( dim_t i, dim_t n_iter, dim_t n_left ) { return ( bool ) ( i != n_iter - 1 || n_left == 0 ); } BLIS_INLINE bool bli_is_edge_b( dim_t i, dim_t n_iter, dim_t n_left ) { return ( bool ) ( i == 0 && n_left != 0 ); } BLIS_INLINE bool bli_is_not_edge_b( dim_t i, dim_t n_iter, dim_t n_left ) { return ( bool ) ( i != 0 || n_left == 0 ); } BLIS_INLINE bool bli_is_last_iter_sl( dim_t i, dim_t end_iter, dim_t tid, dim_t nth ) { return ( bool ) ( i == end_iter - 1 ); } BLIS_INLINE bool bli_is_last_iter_rr( dim_t i, dim_t end_iter, dim_t tid, dim_t nth ) { return ( bool ) ( i == end_iter - 1 - ( ( end_iter - tid - 1 ) % nth ) ); } BLIS_INLINE bool bli_is_last_iter( dim_t i, dim_t end_iter, dim_t tid, dim_t nth ) { #ifdef BLIS_ENABLE_JRIR_SLAB return bli_is_last_iter_sl( i, end_iter, tid, nth ); #else // BLIS_ENABLE_JRIR_RR return bli_is_last_iter_rr( i, end_iter, tid, nth ); #endif } // packbuf_t-related BLIS_INLINE guint_t bli_packbuf_index( packbuf_t buf_type ) { return ( guint_t ) ( ( buf_type & BLIS_PACK_BUFFER_BITS ) >> BLIS_PACK_BUFFER_SHIFT ); } // pack_t-related BLIS_INLINE bool bli_is_packed( pack_t schema ) { return ( bool ) ( schema & BLIS_PACK_BIT ); } BLIS_INLINE bool bli_is_row_packed( pack_t schema ) { return ( bool ) ( ( schema & BLIS_PACK_RC_BIT ) == ( BLIS_BITVAL_PACKED_UNSPEC ^ BLIS_BITVAL_PACKED_ROWS ) ); } BLIS_INLINE bool bli_is_col_packed( pack_t schema ) { return ( bool ) ( ( schema & BLIS_PACK_RC_BIT ) == ( BLIS_BITVAL_PACKED_UNSPEC ^ BLIS_BITVAL_PACKED_COLUMNS ) ); } BLIS_INLINE bool bli_is_panel_packed( pack_t schema ) { return ( bool ) ( schema & BLIS_PACK_PANEL_BIT ); } BLIS_INLINE bool bli_is_1r_packed( pack_t schema ) { return ( bool ) ( ( schema & BLIS_PACK_FORMAT_BITS ) == BLIS_BITVAL_1R ); } BLIS_INLINE bool bli_is_1e_packed( pack_t schema ) { return ( bool ) ( ( schema & BLIS_PACK_FORMAT_BITS ) == BLIS_BITVAL_1E ); } BLIS_INLINE bool bli_is_1m_packed( pack_t schema ) { return ( bool ) ( bli_is_1r_packed( schema ) || bli_is_1e_packed( schema ) ); } BLIS_INLINE bool bli_is_nat_packed( pack_t schema ) { return ( bool ) ( ( schema & BLIS_PACK_FORMAT_BITS ) == 0 ); } BLIS_INLINE bool bli_is_ind_packed( pack_t schema ) { return ( bool ) ( ( schema & BLIS_PACK_FORMAT_BITS ) != 0 ); } BLIS_INLINE guint_t bli_pack_schema_index( pack_t schema ) { return ( guint_t ) ( ( schema & BLIS_PACK_FORMAT_BITS ) >> BLIS_PACK_FORMAT_SHIFT ); } // Set dimensions, increments, effective uplo/diagoff, etc for ONE matrix // argument. BLIS_INLINE void bli_set_dims_incs_uplo_1m ( doff_t diagoffa, diag_t diaga, uplo_t uploa, dim_t m, dim_t n, inc_t rs_a, inc_t cs_a, uplo_t* uplo_eff, dim_t* n_elem_max, dim_t* n_iter, inc_t* inca, inc_t* lda, dim_t* ij0, dim_t* n_shift ) { // This is to prevent the compiler from warning about uninitialized // variables. *ij0 = 0; *n_shift = 0; // If matrix A is entirely "unstored", that is, if either: // - A is lower-stored and entirely above the diagonal, or // - A is upper-stored and entirely below the diagonal // then we mark the storage as implicitly zero. if ( bli_is_unstored_subpart( diagoffa, BLIS_NO_TRANSPOSE, uploa, m, n ) ) { *uplo_eff = BLIS_ZEROS; } else { doff_t diagoffa_use_ = diagoffa; doff_t diagoff_eff_; dim_t n_iter_max_; if ( bli_is_unit_diag( diaga ) ) bli_shift_diag_offset_to_shrink_uplo( uploa, &diagoffa_use_ ); // If matrix A is entirely "stored", that is, if either: // - A is upper-stored and entirely above the diagonal, or // - A is lower-stored and entirely below the diagonal // then we mark the storage as dense. if ( bli_is_stored_subpart( diagoffa_use_, BLIS_NO_TRANSPOSE, uploa, m, n ) ) uploa = BLIS_DENSE; n_iter_max_ = n; *n_elem_max = m; *inca = rs_a; *lda = cs_a; *uplo_eff = uploa; diagoff_eff_ = diagoffa_use_; if ( bli_is_row_tilted( *n_elem_max, n_iter_max_, *inca, *lda ) ) { bli_swap_dims( &n_iter_max_, n_elem_max ); bli_swap_incs( inca, lda ); bli_toggle_uplo( uplo_eff ); bli_negate_diag_offset( &diagoff_eff_ ); } if ( bli_is_dense( *uplo_eff ) ) { *n_iter = n_iter_max_; } else if ( bli_is_upper( *uplo_eff ) ) { if ( diagoff_eff_ < 0 ) { *ij0 = 0; *n_shift = -diagoff_eff_; *n_elem_max = bli_min( *n_elem_max, *n_shift + bli_min( m, n ) ); *n_iter = n_iter_max_; } else { *ij0 = diagoff_eff_; *n_shift = 0; *n_iter = n_iter_max_ - diagoff_eff_; } } else // if ( bli_is_lower( *uplo_eff ) ) { if ( diagoff_eff_ < 0 ) { *ij0 = -diagoff_eff_; *n_shift = 0; *n_elem_max = *n_elem_max + diagoff_eff_; *n_iter = bli_min( *n_elem_max, bli_min( m, n ) ); } else { *ij0 = 0; *n_shift = diagoff_eff_; *n_iter = bli_min( n_iter_max_, *n_shift + bli_min( m, n ) ); } } } } // Set dimensions, increments, effective uplo/diagoff, etc for ONE matrix // argument (without column-wise stride optimization). BLIS_INLINE void bli_set_dims_incs_uplo_1m_noswap ( doff_t diagoffa, diag_t diaga, uplo_t uploa, dim_t m, dim_t n, inc_t rs_a, inc_t cs_a, uplo_t* uplo_eff, dim_t* n_elem_max, dim_t* n_iter, inc_t* inca, inc_t* lda, dim_t* ij0, dim_t* n_shift ) { // This is to prevent the compiler from warning about uninitialized // variables. *ij0 = 0; *n_shift = 0; // If matrix A is entirely "unstored", that is, if either: // - A is lower-stored and entirely above the diagonal, or // - A is upper-stored and entirely below the diagonal // then we mark the storage as implicitly zero. if ( bli_is_unstored_subpart( diagoffa, BLIS_NO_TRANSPOSE, uploa, m, n ) ) { *uplo_eff = BLIS_ZEROS; } else { doff_t diagoffa_use_ = diagoffa; doff_t diagoff_eff_; dim_t n_iter_max_; if ( bli_is_unit_diag( diaga ) ) bli_shift_diag_offset_to_shrink_uplo( uploa, &diagoffa_use_ ); // If matrix A is entirely "stored", that is, if either: // - A is upper-stored and entirely above the diagonal, or // - A is lower-stored and entirely below the diagonal // then we mark the storage as dense. if ( bli_is_stored_subpart( diagoffa_use_, BLIS_NO_TRANSPOSE, uploa, m, n ) ) uploa = BLIS_DENSE; n_iter_max_ = n; *n_elem_max = m; *inca = rs_a; *lda = cs_a; *uplo_eff = uploa; diagoff_eff_ = diagoffa_use_; if ( bli_is_dense( *uplo_eff ) ) { *n_iter = n_iter_max_; } else if ( bli_is_upper( *uplo_eff ) ) { if ( diagoff_eff_ < 0 ) { *ij0 = 0; *n_shift = -diagoff_eff_; *n_elem_max = bli_min( *n_elem_max, *n_shift + bli_min( m, n ) ); *n_iter = n_iter_max_; } else { *ij0 = diagoff_eff_; *n_shift = 0; *n_iter = n_iter_max_ - diagoff_eff_; } } else // if ( bli_is_lower( *uplo_eff ) ) { if ( diagoff_eff_ < 0 ) { *ij0 = -diagoff_eff_; *n_shift = 0; *n_elem_max = *n_elem_max + diagoff_eff_; *n_iter = bli_min( *n_elem_max, bli_min( m, n ) ); } else { *ij0 = 0; *n_shift = diagoff_eff_; *n_iter = bli_min( n_iter_max_, *n_shift + bli_min( m, n ) ); } } } } // Set dimensions and increments for TWO matrix arguments. BLIS_INLINE void bli_set_dims_incs_2m ( trans_t transa, dim_t m, dim_t n, inc_t rs_a, inc_t cs_a, inc_t rs_b, inc_t cs_b, dim_t* n_elem, dim_t* n_iter, inc_t* inca, inc_t* lda, inc_t* incb, inc_t* ldb ) { { *n_iter = n; *n_elem = m; *inca = rs_a; *lda = cs_a; *incb = rs_b; *ldb = cs_b; if ( bli_does_trans( transa ) ) { bli_swap_incs( inca, lda ); } if ( bli_is_row_tilted( *n_elem, *n_iter, *incb, *ldb ) && bli_is_row_tilted( *n_elem, *n_iter, *inca, *lda ) ) { bli_swap_dims( n_iter, n_elem ); bli_swap_incs( inca, lda ); bli_swap_incs( incb, ldb ); } } } // Set dimensions, increments, effective uplo/diagoff, etc for TWO matrix // arguments. BLIS_INLINE void bli_set_dims_incs_uplo_2m ( doff_t diagoffa, diag_t diaga, trans_t transa, uplo_t uploa, dim_t m, dim_t n, inc_t rs_a, inc_t cs_a, inc_t rs_b, inc_t cs_b, uplo_t* uplo_eff, dim_t* n_elem_max, dim_t* n_iter, inc_t* inca, inc_t* lda, inc_t* incb, inc_t* ldb, dim_t* ij0, dim_t* n_shift ) { // This is to prevent the compiler from warning about uninitialized // variables. *ij0 = 0; *n_shift = 0; // If matrix A is entirely "unstored", that is, if either: // - A is lower-stored and entirely above the diagonal, or // - A is upper-stored and entirely below the diagonal // then we mark the storage as implicitly zero. if ( bli_is_unstored_subpart( diagoffa, transa, uploa, m, n ) ) { *uplo_eff = BLIS_ZEROS; } else { doff_t diagoffa_use_ = diagoffa; doff_t diagoff_eff_; dim_t n_iter_max_; if ( bli_is_unit_diag( diaga ) ) bli_shift_diag_offset_to_shrink_uplo( uploa, &diagoffa_use_ ); // If matrix A is entirely "stored", that is, if either: // - A is upper-stored and entirely above the diagonal, or // - A is lower-stored and entirely below the diagonal // then we mark the storage as dense. if ( bli_is_stored_subpart( diagoffa_use_, transa, uploa, m, n ) ) uploa = BLIS_DENSE; n_iter_max_ = n; *n_elem_max = m; *inca = rs_a; *lda = cs_a; *incb = rs_b; *ldb = cs_b; *uplo_eff = uploa; diagoff_eff_ = diagoffa_use_; if ( bli_does_trans( transa ) ) { bli_swap_incs( inca, lda ); bli_toggle_uplo( uplo_eff ); bli_negate_diag_offset( &diagoff_eff_ ); } if ( bli_is_row_tilted( *n_elem_max, n_iter_max_, *incb, *ldb ) && bli_is_row_tilted( *n_elem_max, n_iter_max_, *inca, *lda ) ) { bli_swap_dims( &n_iter_max_, n_elem_max ); bli_swap_incs( inca, lda ); bli_swap_incs( incb, ldb ); bli_toggle_uplo( uplo_eff ); bli_negate_diag_offset( &diagoff_eff_ ); } if ( bli_is_dense( *uplo_eff ) ) { *n_iter = n_iter_max_; } else if ( bli_is_upper( *uplo_eff ) ) { if ( diagoff_eff_ < 0 ) { *ij0 = 0; *n_shift = -diagoff_eff_; *n_elem_max = bli_min( *n_elem_max, *n_shift + bli_min( m, n ) ); *n_iter = n_iter_max_; } else { *ij0 = diagoff_eff_; *n_shift = 0; *n_iter = n_iter_max_ - diagoff_eff_; } } else // if ( bli_is_lower( *uplo_eff ) ) { if ( diagoff_eff_ < 0 ) { *ij0 = -diagoff_eff_; *n_shift = 0; *n_elem_max = *n_elem_max + diagoff_eff_; *n_iter = bli_min( *n_elem_max, bli_min( m, n ) ); } else { *ij0 = 0; *n_shift = diagoff_eff_; *n_iter = bli_min( n_iter_max_, *n_shift + bli_min( m, n ) ); } } } } // Set dimensions, increments, etc for ONE matrix argument when operating // on the diagonal. BLIS_INLINE void bli_set_dims_incs_1d ( doff_t diagoffx, dim_t m, dim_t n, inc_t rs_x, inc_t cs_x, dim_t* offx, dim_t* n_elem, inc_t* incx ) { if ( diagoffx < 0 ) { *n_elem = bli_min( m - ( dim_t )(-diagoffx), n ); *offx = ( dim_t )(-diagoffx) * rs_x; } else { *n_elem = bli_min( n - ( dim_t )( diagoffx), m ); *offx = ( dim_t )( diagoffx) * cs_x; } *incx = rs_x + cs_x; \ } // Set dimensions, increments, etc for TWO matrix arguments when operating // on diagonals. BLIS_INLINE void bli_set_dims_incs_2d ( doff_t diagoffx, trans_t transx, dim_t m, dim_t n, inc_t rs_x, inc_t cs_x, inc_t rs_y, inc_t cs_y, dim_t* offx, dim_t* offy, dim_t* n_elem, inc_t* incx, inc_t* incy ) { doff_t diagoffy_ = bli_diag_offset_with_trans( transx, diagoffx ); if ( diagoffx < 0 ) *offx = -diagoffx * rs_x; else *offx = diagoffx * cs_x; if ( diagoffy_ < 0 ) { *n_elem = bli_min( m - ( dim_t )(-diagoffy_), n ); *offy = -diagoffy_ * rs_y; } else { *n_elem = bli_min( n - ( dim_t )( diagoffy_), m ); *offy = diagoffy_ * cs_y; } *incx = rs_x + cs_x; *incy = rs_y + cs_y; } #endif blis-0.9.0/frame/include/bli_pragma_macro_defs.h000066400000000000000000000051771422157504600216360ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2019, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ /* NOTE: The following code is based on [1]. [1] https://github.com/jeffhammond/nwchem-tce-triples-kernels/blob/master/src/pragma_vendor.h */ #ifndef BLIS_PRAGMA_MACRO_DEFS_H #define BLIS_PRAGMA_MACRO_DEFS_H // Generally speaking, if BLIS_ENABLE_PRAGMA_OMP_SIMD is set, then we define // all instances of PRAGMA_SIMD as _Pragma("omp simd"). #ifdef BLIS_ENABLE_PRAGMA_OMP_SIMD #define PRAGMA_OMP_SIMD _Pragma("omp simd") #else #define PRAGMA_OMP_SIMD #endif // Require ISO C99 or later for SIMD-related pragmas. #if (( __STDC_VERSION__ >= 199901L )) #define GEN_PRAGMA(x) _Pragma(#x) #if defined(__ICC) || defined(__INTEL_COMPILER) // Intel icc. //#define PRAGMA_SIMD GEN_PRAGMA(simd) #define PRAGMA_SIMD PRAGMA_OMP_SIMD #elif defined(__clang__) // clang/llvm. #define PRAGMA_SIMD PRAGMA_OMP_SIMD #elif defined(__GNUC__) // GNU gcc. #define PRAGMA_SIMD PRAGMA_OMP_SIMD #else // Unknown compiler. #define PRAGMA_SIMD #endif #endif #endif blis-0.9.0/frame/include/bli_sbox.h000066400000000000000000000037631422157504600171570ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_SBOX_H #define BLIS_SBOX_H // Each sandbox must have a bli_sandbox.h file present somewhere inside. // If a sandbox was enabled at configure-time, we need to #include its // header file here so that it will get pulled into blis.h when it is // flattened into a monolithic header. #ifdef BLIS_ENABLE_SANDBOX #include "bli_sandbox.h" #endif #endif blis-0.9.0/frame/include/bli_scalar_macro_defs.h000066400000000000000000000132021422157504600216200ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_SCALAR_MACRO_DEFS_H #define BLIS_SCALAR_MACRO_DEFS_H // -- Assignment/Accessor macros -- // NOTE: This macro is defined first since some of the other scalar macros // use it to abstract away the method used to assign complex values (ie: // whether fields of a struct are set directly or whether native C99 // assignment is used). #include "bli_sets.h" // sets both real and imaginary components // NOTE: These macros are not used by other scalar macros, but they are // related to those defined in bli_sets.h, and so we #include them here. #include "bli_setrs.h" // sets real component only #include "bli_setis.h" // sets imaginary component only // NOTE: This macro also needs to be defined early on since it determines // how real and imaginary components are accessed (ie: whether the fields // of a struct are read directly or whether native C99 functions are used.) #include "bli_gets.h" // -- Scalar constant initialization macros -- #include "bli_constants.h" // -- Separated scalar macros (separated real/imaginary values) -- #include "bli_absq2ris.h" #include "bli_abval2ris.h" #include "bli_addris.h" #include "bli_addjris.h" #include "bli_add3ris.h" #include "bli_axpbyris.h" #include "bli_axpbyjris.h" #include "bli_axpyris.h" #include "bli_axpyjris.h" #include "bli_axmyris.h" #include "bli_conjris.h" #include "bli_copyris.h" #include "bli_copyjris.h" #include "bli_copycjris.h" #include "bli_eqris.h" #include "bli_invertris.h" #include "bli_invscalris.h" #include "bli_invscaljris.h" #include "bli_neg2ris.h" #include "bli_scalris.h" #include "bli_scaljris.h" #include "bli_scalcjris.h" #include "bli_scal2ris.h" #include "bli_scal2jris.h" #include "bli_set0ris.h" #include "bli_sqrt2ris.h" #include "bli_subris.h" #include "bli_subjris.h" #include "bli_swapris.h" #include "bli_xpbyris.h" #include "bli_xpbyjris.h" // Inlined scalar macros in loops #include "bli_scal2ris_mxn.h" #include "bli_scalris_mxn_uplo.h" // -- Conventional scalar macros (paired real/imaginary values) -- #include "bli_absq2s.h" #include "bli_abval2s.h" #include "bli_adds.h" #include "bli_addjs.h" #include "bli_add3s.h" #include "bli_axpbys.h" #include "bli_axpbyjs.h" #include "bli_axpys.h" #include "bli_axpyjs.h" #include "bli_axmys.h" #include "bli_conjs.h" #include "bli_copys.h" #include "bli_copyjs.h" #include "bli_copycjs.h" #include "bli_copynzs.h" #include "bli_copyjnzs.h" #include "bli_dots.h" #include "bli_dotjs.h" #include "bli_eq.h" #include "bli_fprints.h" #include "bli_inverts.h" #include "bli_invscals.h" #include "bli_invscaljs.h" #include "bli_neg2s.h" #include "bli_rands.h" #include "bli_randnp2s.h" #include "bli_scals.h" #include "bli_scaljs.h" #include "bli_scalcjs.h" #include "bli_scal2s.h" #include "bli_scal2js.h" #include "bli_set0s.h" #include "bli_set1s.h" #include "bli_seti0s.h" #include "bli_sqrt2s.h" #include "bli_subs.h" #include "bli_subjs.h" #include "bli_swaps.h" #include "bli_xpbys.h" #include "bli_xpbyjs.h" // Inlined scalar macros in loops #include "bli_adds_mxn.h" #include "bli_adds_mxn_uplo.h" #include "bli_set0s_mxn.h" #include "bli_copys_mxn.h" #include "bli_scal2s_mxn.h" #include "bli_xpbys_mxn.h" #include "bli_xpbys_mxn_uplo.h" // -- "broadcast B" scalar macros -- #include "bli_bcastbbs_mxn.h" #include "bli_scal2bbs_mxn.h" #include "bli_set0bbs_mxn.h" // -- 1m-specific scalar macros -- // 1e #include "bli_copy1es.h" #include "bli_copyj1es.h" #include "bli_invert1es.h" #include "bli_scal1es.h" #include "bli_scal21es.h" #include "bli_scal2j1es.h" // 1r #include "bli_copy1rs.h" #include "bli_copyj1rs.h" #include "bli_invert1rs.h" #include "bli_scal1rs.h" #include "bli_scal21rs.h" #include "bli_scal2j1rs.h" // 1m (1e or 1r) #include "bli_invert1ms_mxn_diag.h" #include "bli_scal1ms_mxn.h" #include "bli_scal21ms_mxn.h" #include "bli_scal21ms_mxn_diag.h" #include "bli_scal21ms_mxn_uplo.h" #include "bli_set1ms_mxn.h" #include "bli_set1ms_mxn_diag.h" #include "bli_set1ms_mxn_uplo.h" #include "bli_seti01ms_mxn_diag.h" #endif blis-0.9.0/frame/include/bli_system.h000066400000000000000000000100431422157504600175150ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_SYSTEM_H #define BLIS_SYSTEM_H // NOTE: If not yet defined, we define _POSIX_C_SOURCE to make sure that // various parts of POSIX are defined and made available. #ifndef _POSIX_C_SOURCE #define _POSIX_C_SOURCE 200809L #endif #include #include #include #include #include #include #include #include // Determine the compiler (hopefully) and define conveniently named macros // accordingly. #if defined(__ICC) || defined(__INTEL_COMPILER) #define BLIS_ICC #elif defined(__clang__) #define BLIS_CLANG #elif defined(__GNUC__) #define BLIS_GCC #endif // Determine if we are on a 64-bit or 32-bit architecture. #if defined(_M_X64) || defined(__x86_64) || defined(__aarch64__) || \ defined(_ARCH_PPC64) || defined(__s390x__) || defined(_LP64) #define BLIS_ARCH_64 #else #define BLIS_ARCH_32 #endif // Determine the target operating system. #if defined(BLIS_ENABLE_SYSTEM) #if defined(_WIN32) || defined(__CYGWIN__) #define BLIS_OS_WINDOWS 1 #elif defined(__gnu_hurd__) #define BLIS_OS_GNU 1 #elif defined(__APPLE__) || defined(__MACH__) #define BLIS_OS_OSX 1 #elif defined(__ANDROID__) #define BLIS_OS_ANDROID 1 #elif defined(__linux__) #define BLIS_OS_LINUX 1 #elif defined(__bgq__) #define BLIS_OS_BGQ 1 #elif defined(__bg__) #define BLIS_OS_BGP 1 #elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || \ defined(__bsdi__) || defined(__DragonFly__) || \ defined(__FreeBSD_kernel__) || defined(__HAIKU__) #define BLIS_OS_BSD 1 #elif defined(EMSCRIPTEN) #define BLIS_OS_EMSCRIPTEN #else #error "Cannot determine operating system" #endif #else // #if defined(BLIS_DISABLE_SYSTEM) #define BLIS_OS_NONE #endif // A few changes that may be necessary in Windows environments. #if BLIS_OS_WINDOWS // Include Windows header file. #define WIN32_LEAN_AND_MEAN #define VC_EXTRALEAN #include #if !defined(__clang__) && !defined(__GNUC__) // Undefine attribute specifiers in Windows. #define __attribute__(x) // Undefine restrict. #define restrict #endif #endif // time.h provides clock_gettime(). #if BLIS_OS_WINDOWS #include #elif BLIS_OS_OSX #include #else //#include #include #endif #endif blis-0.9.0/frame/include/bli_tapi_ba.h000066400000000000000000000047621422157504600176030ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // This file defines macros used to allow the _tapi.c files to produce // typed APIs that omit expert parameters. // Define a macro that allows the source code to determine which interface // (basic or expert) we are compiling. #undef BLIS_TAPI_BASIC #define BLIS_TAPI_BASIC // Define the macro to omit a suffix from the function names (in function // definitions). #undef EX_SUF #define EX_SUF // Define the macro to omit expert arguments from function signatures // and prototypes. #undef BLIS_TAPI_EX_PARAMS #define BLIS_TAPI_EX_PARAMS // Define the macro to add local expert variables that are initialized // to NULL. The "( void )" statements are to prevent unused variable // warnings by the compiler. #undef BLIS_TAPI_EX_DECLS #define BLIS_TAPI_EX_DECLS cntx_t* cntx = NULL; ( void )cntx; \ rntm_t* rntm = NULL; ( void )rntm; blis-0.9.0/frame/include/bli_tapi_ex.h000066400000000000000000000046441422157504600176340ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // This file defines macros used to allow the _tapi.c files to produce // typed APIs that contain context parameters. // Define a macro that allows the source code to determine which interface // (basic or expert) we are compiling. #undef BLIS_TAPI_EXPERT #define BLIS_TAPI_EXPERT // Define the macro to add a suffix to the function names (in function // definitions). #undef EX_SUF #define EX_SUF BLIS_TAPI_EX_SUF // Define the macro to add expert arguments to function signatures // and prototypes. #undef BLIS_TAPI_EX_PARAMS #define BLIS_TAPI_EX_PARAMS ,cntx_t* cntx, rntm_t* rntm // Define the macro to omit the expert variable declaration block, since // it is not needed when expert parameters are passed in through the API. #undef BLIS_TAPI_EX_DECLS #define BLIS_TAPI_EX_DECLS blis-0.9.0/frame/include/bli_tapi_macro_defs.h000066400000000000000000000034171422157504600213170ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // Define the suffix to add to typed API function names that include // additional "expert" parameters. #define BLIS_TAPI_EX_SUF _ex blis-0.9.0/frame/include/bli_type_defs.h000066400000000000000000001253151422157504600201640ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2016, Hewlett Packard Enterprise Development LP Copyright (C) 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_TYPE_DEFS_H #define BLIS_TYPE_DEFS_H // // -- BLIS basic types --------------------------------------------------------- // #ifdef __cplusplus // For C++, include stdint.h. #include #elif __STDC_VERSION__ >= 199901L // For C99 (or later), include stdint.h. #include #include #else // When stdint.h is not available, manually typedef the types we will use. #ifdef _WIN32 typedef __int32 int32_t; typedef unsigned __int32 uint32_t; typedef __int64 int64_t; typedef unsigned __int64 uint64_t; #else #error "Attempting to compile on pre-C99 system without stdint.h." #endif #endif // -- General-purpose integers -- // If BLAS integers are 64 bits, mandate that BLIS integers also be 64 bits. // NOTE: This cpp guard will only meaningfully change BLIS's behavior on // systems where the BLIS integer size would have been automatically selected // to be 32 bits, since explicit selection of 32 bits is prohibited at // configure-time (and explicit or automatic selection of 64 bits is fine // and would have had the same result). #if BLIS_BLAS_INT_SIZE == 64 #undef BLIS_INT_TYPE_SIZE #define BLIS_INT_TYPE_SIZE 64 #endif // Define integer types depending on what size integer was requested. #if BLIS_INT_TYPE_SIZE == 32 typedef int32_t gint_t; typedef uint32_t guint_t; #elif BLIS_INT_TYPE_SIZE == 64 typedef int64_t gint_t; typedef uint64_t guint_t; #else typedef signed long int gint_t; typedef unsigned long int guint_t; #endif // -- Boolean type -- // NOTE: bool_t is no longer used and has been replaced with C99's bool type. //typedef bool bool_t; // BLIS uses TRUE and FALSE macro constants as possible boolean values, but we // define these macros in terms of true and false, respectively, which are // defined by C99 in stdbool.h. #ifndef TRUE #define TRUE true #endif #ifndef FALSE #define FALSE false #endif // -- Special-purpose integers -- // This cpp guard provides a temporary hack to allow libflame // interoperability with BLIS. #ifndef _DEFINED_DIM_T #define _DEFINED_DIM_T typedef gint_t dim_t; // dimension type #endif typedef gint_t inc_t; // increment/stride type typedef gint_t doff_t; // diagonal offset type typedef guint_t siz_t; // byte size type typedef uint32_t objbits_t; // object information bit field // -- Real types -- // Define the number of floating-point types supported, and the size of the // largest type. #define BLIS_NUM_FP_TYPES 4 #define BLIS_MAX_TYPE_SIZE sizeof(dcomplex) // There are some places where we need to use sizeof() inside of a C // preprocessor #if conditional, and so here we define the various sizes // for those purposes. #define BLIS_SIZEOF_S 4 // sizeof(float) #define BLIS_SIZEOF_D 8 // sizeof(double) #define BLIS_SIZEOF_C 8 // sizeof(scomplex) #define BLIS_SIZEOF_Z 16 // sizeof(dcomplex) // -- Complex types -- #ifdef BLIS_ENABLE_C99_COMPLEX #if __STDC_VERSION__ >= 199901L #include // Typedef official complex types to BLIS complex type names. typedef float complex scomplex; typedef double complex dcomplex; #else #error "Configuration requested C99 complex types, but C99 does not appear to be supported." #endif #else // ifndef BLIS_ENABLE_C99_COMPLEX // This cpp guard provides a temporary hack to allow libflame // interoperability with BLIS. #ifndef _DEFINED_SCOMPLEX #define _DEFINED_SCOMPLEX typedef struct scomplex { float real; float imag; } scomplex; #endif // This cpp guard provides a temporary hack to allow libflame // interoperability with BLIS. #ifndef _DEFINED_DCOMPLEX #define _DEFINED_DCOMPLEX typedef struct dcomplex { double real; double imag; } dcomplex; #endif #endif // BLIS_ENABLE_C99_COMPLEX // -- Atom type -- // Note: atom types are used to hold "bufferless" scalar object values. Note // that it needs to be as large as the largest possible scalar value we might // want to hold. Thus, for now, it is a dcomplex. typedef dcomplex atom_t; // -- Fortran-77 types -- // Note: These types are typically only used by BLAS compatibility layer, but // we must define them even when the compatibility layer isn't being built // because they also occur in bli_slamch() and bli_dlamch(). // Define f77_int depending on what size of integer was requested. #if BLIS_BLAS_INT_TYPE_SIZE == 32 typedef int32_t f77_int; #elif BLIS_BLAS_INT_TYPE_SIZE == 64 typedef int64_t f77_int; #else typedef long int f77_int; #endif typedef char f77_char; typedef float f77_float; typedef double f77_double; typedef scomplex f77_scomplex; typedef dcomplex f77_dcomplex; // -- Misc. function pointer types -- // Note: This type should be used in any situation where the address of a // *function* will be conveyed or stored prior to it being typecast back // to the correct function type. It does not need to be used when conveying // or storing the address of *data* (such as an array of float or double). //typedef void (*void_fp)( void ); typedef void* void_fp; // Typedef function pointer types for malloc() and free() substitutes. typedef void* (*malloc_ft)( size_t size ); typedef void (*free_ft) ( void* p ); // // -- BLIS info bit field offsets ---------------------------------------------- // /* info field description bit(s) purpose ------- ------- 2 ~ 0 Stored numerical datatype - 0: domain (0 == real, 1 == complex) - 1: precision (0 == single, 1 == double) - 2: special (100 = int; 101 = const) 3 Transposition required [during pack]? 4 Conjugation required [during pack]? 7 ~ 5 Part of matrix stored: - 5: strictly upper triangular - 6: diagonal - 7: strictly lower triangular 8 Implicit unit diagonal? 9 Invert diagonal required [during pack]? 12 ~ 10 Target numerical datatype - 10: domain (0 == real, 1 == complex) - 11: precision (0 == single, 1 == double) - 12: used to encode integer, constant types 15 ~ 13 Execution numerical datatype - 13: domain (0 == real, 1 == complex) - 14: precision (0 == single, 1 == double) - 15: used to encode integer, constant types 22 ~ 16 Packed type/status - 0 0000 00: not packed - 1 0000 00: packed (unspecified; by rows, columns, or vector) - 1 0000 00: packed by rows - 1 0000 01: packed by columns - 1 0000 10: packed by row panels - 1 0000 11: packed by column panels - 1 0001 10: packed by 1m expanded row panels - 1 0001 11: packed by 1m expanded column panels - 1 0010 10: packed by 1m reordered row panels - 1 0010 11: packed by 1m reordered column panels 23 Packed panel order if upper-stored - 0 == forward order if upper - 1 == reverse order if upper 24 Packed panel order if lower-stored - 0 == forward order if lower - 1 == reverse order if lower 26 ~ 25 Packed buffer type - 0 == block of A - 1 == panel of B - 2 == panel of C - 3 == general use 28 ~ 27 Structure type - 0 == general - 1 == Hermitian - 2 == symmetric - 3 == triangular 31 ~ 29 Computation numerical datatype - 29: domain (0 == real, 1 == complex) - 30: precision (0 == single, 1 == double) - 31: used to encode integer, constant types info2 field description bit(s) purpose ------- ------- 2 ~ 0 Scalar storage numerical datatype - 0: domain (0 == real, 1 == complex) - 1: precision (0 == single, 1 == double) - 2: used to encode integer, constant types */ // info #define BLIS_DATATYPE_SHIFT 0 #define BLIS_DOMAIN_SHIFT 0 #define BLIS_PRECISION_SHIFT 1 #define BLIS_CONJTRANS_SHIFT 3 #define BLIS_TRANS_SHIFT 3 #define BLIS_CONJ_SHIFT 4 #define BLIS_UPLO_SHIFT 5 #define BLIS_UPPER_SHIFT 5 #define BLIS_DIAG_SHIFT 6 #define BLIS_LOWER_SHIFT 7 #define BLIS_UNIT_DIAG_SHIFT 8 #define BLIS_INVERT_DIAG_SHIFT 9 #define BLIS_TARGET_DT_SHIFT 10 #define BLIS_TARGET_DOMAIN_SHIFT 10 #define BLIS_TARGET_PREC_SHIFT 11 #define BLIS_EXEC_DT_SHIFT 13 #define BLIS_EXEC_DOMAIN_SHIFT 13 #define BLIS_EXEC_PREC_SHIFT 14 #define BLIS_PACK_SCHEMA_SHIFT 16 #define BLIS_PACK_RC_SHIFT 16 #define BLIS_PACK_PANEL_SHIFT 17 #define BLIS_PACK_FORMAT_SHIFT 18 #define BLIS_PACK_SHIFT 22 #define BLIS_PACK_REV_IF_UPPER_SHIFT 23 #define BLIS_PACK_REV_IF_LOWER_SHIFT 24 #define BLIS_PACK_BUFFER_SHIFT 25 #define BLIS_STRUC_SHIFT 27 #define BLIS_COMP_DT_SHIFT 29 #define BLIS_COMP_DOMAIN_SHIFT 29 #define BLIS_COMP_PREC_SHIFT 30 // info2 #define BLIS_SCALAR_DT_SHIFT 0 #define BLIS_SCALAR_DOMAIN_SHIFT 0 #define BLIS_SCALAR_PREC_SHIFT 1 // // -- BLIS info bit field masks ------------------------------------------------ // // info #define BLIS_DATATYPE_BITS ( 0x7 << BLIS_DATATYPE_SHIFT ) #define BLIS_DOMAIN_BIT ( 0x1 << BLIS_DOMAIN_SHIFT ) #define BLIS_PRECISION_BIT ( 0x1 << BLIS_PRECISION_SHIFT ) #define BLIS_CONJTRANS_BITS ( 0x3 << BLIS_CONJTRANS_SHIFT ) #define BLIS_TRANS_BIT ( 0x1 << BLIS_TRANS_SHIFT ) #define BLIS_CONJ_BIT ( 0x1 << BLIS_CONJ_SHIFT ) #define BLIS_UPLO_BITS ( 0x7 << BLIS_UPLO_SHIFT ) #define BLIS_UPPER_BIT ( 0x1 << BLIS_UPPER_SHIFT ) #define BLIS_DIAG_BIT ( 0x1 << BLIS_DIAG_SHIFT ) #define BLIS_LOWER_BIT ( 0x1 << BLIS_LOWER_SHIFT ) #define BLIS_UNIT_DIAG_BIT ( 0x1 << BLIS_UNIT_DIAG_SHIFT ) #define BLIS_INVERT_DIAG_BIT ( 0x1 << BLIS_INVERT_DIAG_SHIFT ) #define BLIS_TARGET_DT_BITS ( 0x7 << BLIS_TARGET_DT_SHIFT ) #define BLIS_TARGET_DOMAIN_BIT ( 0x1 << BLIS_TARGET_DOMAIN_SHIFT ) #define BLIS_TARGET_PREC_BIT ( 0x1 << BLIS_TARGET_PREC_SHIFT ) #define BLIS_EXEC_DT_BITS ( 0x7 << BLIS_EXEC_DT_SHIFT ) #define BLIS_EXEC_DOMAIN_BIT ( 0x1 << BLIS_EXEC_DOMAIN_SHIFT ) #define BLIS_EXEC_PREC_BIT ( 0x1 << BLIS_EXEC_PREC_SHIFT ) #define BLIS_PACK_SCHEMA_BITS ( 0x7F << BLIS_PACK_SCHEMA_SHIFT ) #define BLIS_PACK_RC_BIT ( 0x1 << BLIS_PACK_RC_SHIFT ) #define BLIS_PACK_PANEL_BIT ( 0x1 << BLIS_PACK_PANEL_SHIFT ) #define BLIS_PACK_FORMAT_BITS ( 0xF << BLIS_PACK_FORMAT_SHIFT ) #define BLIS_PACK_BIT ( 0x1 << BLIS_PACK_SHIFT ) #define BLIS_PACK_REV_IF_UPPER_BIT ( 0x1 << BLIS_PACK_REV_IF_UPPER_SHIFT ) #define BLIS_PACK_REV_IF_LOWER_BIT ( 0x1 << BLIS_PACK_REV_IF_LOWER_SHIFT ) #define BLIS_PACK_BUFFER_BITS ( 0x3 << BLIS_PACK_BUFFER_SHIFT ) #define BLIS_STRUC_BITS ( 0x3 << BLIS_STRUC_SHIFT ) #define BLIS_COMP_DT_BITS ( 0x7 << BLIS_COMP_DT_SHIFT ) #define BLIS_COMP_DOMAIN_BIT ( 0x1 << BLIS_COMP_DOMAIN_SHIFT ) #define BLIS_COMP_PREC_BIT ( 0x1 << BLIS_COMP_PREC_SHIFT ) // info2 #define BLIS_SCALAR_DT_BITS ( 0x7 << BLIS_SCALAR_DT_SHIFT ) #define BLIS_SCALAR_DOMAIN_BIT ( 0x1 << BLIS_SCALAR_DOMAIN_SHIFT ) #define BLIS_SCALAR_PREC_BIT ( 0x1 << BLIS_SCALAR_PREC_SHIFT ) // // -- BLIS enumerated type value definitions ----------------------------------- // #define BLIS_BITVAL_REAL 0x0 #define BLIS_BITVAL_COMPLEX BLIS_DOMAIN_BIT #define BLIS_BITVAL_SINGLE_PREC 0x0 #define BLIS_BITVAL_DOUBLE_PREC BLIS_PRECISION_BIT #define BLIS_BITVAL_FLOAT_TYPE 0x0 #define BLIS_BITVAL_SCOMPLEX_TYPE BLIS_DOMAIN_BIT #define BLIS_BITVAL_DOUBLE_TYPE BLIS_PRECISION_BIT #define BLIS_BITVAL_DCOMPLEX_TYPE ( BLIS_DOMAIN_BIT | BLIS_PRECISION_BIT ) #define BLIS_BITVAL_INT_TYPE 0x04 #define BLIS_BITVAL_CONST_TYPE 0x05 #define BLIS_BITVAL_NO_TRANS 0x0 #define BLIS_BITVAL_TRANS BLIS_TRANS_BIT #define BLIS_BITVAL_NO_CONJ 0x0 #define BLIS_BITVAL_CONJ BLIS_CONJ_BIT #define BLIS_BITVAL_CONJ_TRANS ( BLIS_CONJ_BIT | BLIS_TRANS_BIT ) #define BLIS_BITVAL_ZEROS 0x0 #define BLIS_BITVAL_UPPER ( BLIS_UPPER_BIT | BLIS_DIAG_BIT ) #define BLIS_BITVAL_LOWER ( BLIS_LOWER_BIT | BLIS_DIAG_BIT ) #define BLIS_BITVAL_DENSE BLIS_UPLO_BITS #define BLIS_BITVAL_NONUNIT_DIAG 0x0 #define BLIS_BITVAL_UNIT_DIAG BLIS_UNIT_DIAG_BIT #define BLIS_BITVAL_INVERT_DIAG BLIS_INVERT_DIAG_BIT #define BLIS_BITVAL_NOT_PACKED 0x0 #define BLIS_BITVAL_1E ( 0x1 << BLIS_PACK_FORMAT_SHIFT ) #define BLIS_BITVAL_1R ( 0x2 << BLIS_PACK_FORMAT_SHIFT ) #define BLIS_BITVAL_PACKED_UNSPEC ( BLIS_PACK_BIT ) #define BLIS_BITVAL_PACKED_ROWS ( BLIS_PACK_BIT ) #define BLIS_BITVAL_PACKED_COLUMNS ( BLIS_PACK_BIT | BLIS_PACK_RC_BIT ) #define BLIS_BITVAL_PACKED_ROW_PANELS ( BLIS_PACK_BIT | BLIS_PACK_PANEL_BIT ) #define BLIS_BITVAL_PACKED_COL_PANELS ( BLIS_PACK_BIT | BLIS_PACK_PANEL_BIT | BLIS_PACK_RC_BIT ) #define BLIS_BITVAL_PACKED_ROW_PANELS_1E ( BLIS_PACK_BIT | BLIS_BITVAL_1E | BLIS_PACK_PANEL_BIT ) #define BLIS_BITVAL_PACKED_COL_PANELS_1E ( BLIS_PACK_BIT | BLIS_BITVAL_1E | BLIS_PACK_PANEL_BIT | BLIS_PACK_RC_BIT ) #define BLIS_BITVAL_PACKED_ROW_PANELS_1R ( BLIS_PACK_BIT | BLIS_BITVAL_1R | BLIS_PACK_PANEL_BIT ) #define BLIS_BITVAL_PACKED_COL_PANELS_1R ( BLIS_PACK_BIT | BLIS_BITVAL_1R | BLIS_PACK_PANEL_BIT | BLIS_PACK_RC_BIT ) #define BLIS_BITVAL_PACK_FWD_IF_UPPER 0x0 #define BLIS_BITVAL_PACK_REV_IF_UPPER BLIS_PACK_REV_IF_UPPER_BIT #define BLIS_BITVAL_PACK_FWD_IF_LOWER 0x0 #define BLIS_BITVAL_PACK_REV_IF_LOWER BLIS_PACK_REV_IF_LOWER_BIT #define BLIS_BITVAL_BUFFER_FOR_A_BLOCK 0x0 #define BLIS_BITVAL_BUFFER_FOR_B_PANEL ( 0x1 << BLIS_PACK_BUFFER_SHIFT ) #define BLIS_BITVAL_BUFFER_FOR_C_PANEL ( 0x2 << BLIS_PACK_BUFFER_SHIFT ) #define BLIS_BITVAL_BUFFER_FOR_GEN_USE ( 0x3 << BLIS_PACK_BUFFER_SHIFT ) #define BLIS_BITVAL_GENERAL 0x0 #define BLIS_BITVAL_HERMITIAN ( 0x1 << BLIS_STRUC_SHIFT ) #define BLIS_BITVAL_SYMMETRIC ( 0x2 << BLIS_STRUC_SHIFT ) #define BLIS_BITVAL_TRIANGULAR ( 0x3 << BLIS_STRUC_SHIFT ) // // -- BLIS enumerated type definitions ----------------------------------------- // // -- Operational parameter types -- typedef enum { BLIS_NO_TRANSPOSE = 0x0, BLIS_TRANSPOSE = BLIS_BITVAL_TRANS, BLIS_CONJ_NO_TRANSPOSE = BLIS_BITVAL_CONJ, BLIS_CONJ_TRANSPOSE = BLIS_BITVAL_CONJ_TRANS } trans_t; typedef enum { BLIS_NO_CONJUGATE = 0x0, BLIS_CONJUGATE = BLIS_BITVAL_CONJ } conj_t; typedef enum { BLIS_ZEROS = BLIS_BITVAL_ZEROS, BLIS_LOWER = BLIS_BITVAL_LOWER, BLIS_UPPER = BLIS_BITVAL_UPPER, BLIS_DENSE = BLIS_BITVAL_DENSE } uplo_t; typedef enum { BLIS_LEFT = 0x0, BLIS_RIGHT } side_t; typedef enum { BLIS_NONUNIT_DIAG = 0x0, BLIS_UNIT_DIAG = BLIS_BITVAL_UNIT_DIAG } diag_t; typedef enum { BLIS_NO_INVERT_DIAG = 0x0, BLIS_INVERT_DIAG = BLIS_BITVAL_INVERT_DIAG } invdiag_t; typedef enum { BLIS_GENERAL = BLIS_BITVAL_GENERAL, BLIS_HERMITIAN = BLIS_BITVAL_HERMITIAN, BLIS_SYMMETRIC = BLIS_BITVAL_SYMMETRIC, BLIS_TRIANGULAR = BLIS_BITVAL_TRIANGULAR } struc_t; // -- Data type -- typedef enum { BLIS_FLOAT = BLIS_BITVAL_FLOAT_TYPE, BLIS_DOUBLE = BLIS_BITVAL_DOUBLE_TYPE, BLIS_SCOMPLEX = BLIS_BITVAL_SCOMPLEX_TYPE, BLIS_DCOMPLEX = BLIS_BITVAL_DCOMPLEX_TYPE, BLIS_INT = BLIS_BITVAL_INT_TYPE, BLIS_CONSTANT = BLIS_BITVAL_CONST_TYPE, BLIS_DT_LO = BLIS_FLOAT, BLIS_DT_HI = BLIS_DCOMPLEX } num_t; typedef enum { BLIS_REAL = BLIS_BITVAL_REAL, BLIS_COMPLEX = BLIS_BITVAL_COMPLEX } dom_t; typedef enum { BLIS_SINGLE_PREC = BLIS_BITVAL_SINGLE_PREC, BLIS_DOUBLE_PREC = BLIS_BITVAL_DOUBLE_PREC } prec_t; // -- Pack schema type -- typedef enum { BLIS_NOT_PACKED = BLIS_BITVAL_NOT_PACKED, BLIS_PACKED_UNSPEC = BLIS_BITVAL_PACKED_UNSPEC, BLIS_PACKED_VECTOR = BLIS_BITVAL_PACKED_UNSPEC, BLIS_PACKED_ROWS = BLIS_BITVAL_PACKED_ROWS, BLIS_PACKED_COLUMNS = BLIS_BITVAL_PACKED_COLUMNS, BLIS_PACKED_ROW_PANELS = BLIS_BITVAL_PACKED_ROW_PANELS, BLIS_PACKED_COL_PANELS = BLIS_BITVAL_PACKED_COL_PANELS, BLIS_PACKED_ROW_PANELS_1E = BLIS_BITVAL_PACKED_ROW_PANELS_1E, BLIS_PACKED_COL_PANELS_1E = BLIS_BITVAL_PACKED_COL_PANELS_1E, BLIS_PACKED_ROW_PANELS_1R = BLIS_BITVAL_PACKED_ROW_PANELS_1R, BLIS_PACKED_COL_PANELS_1R = BLIS_BITVAL_PACKED_COL_PANELS_1R } pack_t; // We combine row and column packing into one "type", and we start // with BLIS_PACKED_ROW_PANELS, _COLUMN_PANELS. #define BLIS_NUM_PACK_SCHEMA_TYPES 3 // -- Pack order type -- typedef enum { BLIS_PACK_FWD_IF_UPPER = BLIS_BITVAL_PACK_FWD_IF_UPPER, BLIS_PACK_REV_IF_UPPER = BLIS_BITVAL_PACK_REV_IF_UPPER, BLIS_PACK_FWD_IF_LOWER = BLIS_BITVAL_PACK_FWD_IF_LOWER, BLIS_PACK_REV_IF_LOWER = BLIS_BITVAL_PACK_REV_IF_LOWER } packord_t; // -- Pack buffer type -- typedef enum { BLIS_BUFFER_FOR_A_BLOCK = BLIS_BITVAL_BUFFER_FOR_A_BLOCK, BLIS_BUFFER_FOR_B_PANEL = BLIS_BITVAL_BUFFER_FOR_B_PANEL, BLIS_BUFFER_FOR_C_PANEL = BLIS_BITVAL_BUFFER_FOR_C_PANEL, BLIS_BUFFER_FOR_GEN_USE = BLIS_BITVAL_BUFFER_FOR_GEN_USE } packbuf_t; // -- Partitioning direction -- typedef enum { BLIS_FWD, BLIS_BWD } dir_t; // -- Subpartition type -- typedef enum { BLIS_SUBPART0, BLIS_SUBPART1, BLIS_SUBPART2, BLIS_SUBPART1AND0, BLIS_SUBPART1AND2, BLIS_SUBPART1A, BLIS_SUBPART1B, BLIS_SUBPART00, BLIS_SUBPART10, BLIS_SUBPART20, BLIS_SUBPART01, BLIS_SUBPART11, BLIS_SUBPART21, BLIS_SUBPART02, BLIS_SUBPART12, BLIS_SUBPART22 } subpart_t; // -- Matrix dimension type -- typedef enum { BLIS_M = 0, BLIS_N = 1 } mdim_t; // -- Machine parameter types -- typedef enum { BLIS_MACH_EPS = 0, BLIS_MACH_SFMIN, BLIS_MACH_BASE, BLIS_MACH_PREC, BLIS_MACH_NDIGMANT, BLIS_MACH_RND, BLIS_MACH_EMIN, BLIS_MACH_RMIN, BLIS_MACH_EMAX, BLIS_MACH_RMAX, BLIS_MACH_EPS2 } machval_t; #define BLIS_NUM_MACH_PARAMS 11 #define BLIS_MACH_PARAM_FIRST BLIS_MACH_EPS #define BLIS_MACH_PARAM_LAST BLIS_MACH_EPS2 // -- Induced method types -- typedef enum { BLIS_1M = 0, BLIS_NAT, BLIS_IND_FIRST = 0, BLIS_IND_LAST = BLIS_NAT } ind_t; #define BLIS_NUM_IND_METHODS (BLIS_NAT+1) // These are used in bli_l3_*_oapi.c to construct the ind_t values from // the induced method substrings that go into function names. #define bli_1m BLIS_1M #define bli_nat BLIS_NAT // -- Kernel ID types -- typedef enum { BLIS_ADDV_KER = 0, BLIS_AMAXV_KER, BLIS_AXPBYV_KER, BLIS_AXPYV_KER, BLIS_COPYV_KER, BLIS_DOTV_KER, BLIS_DOTXV_KER, BLIS_INVERTV_KER, BLIS_SCALV_KER, BLIS_SCAL2V_KER, BLIS_SETV_KER, BLIS_SUBV_KER, BLIS_SWAPV_KER, BLIS_XPBYV_KER } l1vkr_t; #define BLIS_NUM_LEVEL1V_KERS 14 typedef enum { BLIS_AXPY2V_KER = 0, BLIS_DOTAXPYV_KER, BLIS_AXPYF_KER, BLIS_DOTXF_KER, BLIS_DOTXAXPYF_KER } l1fkr_t; #define BLIS_NUM_LEVEL1F_KERS 5 typedef enum { BLIS_PACKM_0XK_KER = 0, BLIS_PACKM_1XK_KER = 1, BLIS_PACKM_2XK_KER = 2, BLIS_PACKM_3XK_KER = 3, BLIS_PACKM_4XK_KER = 4, BLIS_PACKM_5XK_KER = 5, BLIS_PACKM_6XK_KER = 6, BLIS_PACKM_7XK_KER = 7, BLIS_PACKM_8XK_KER = 8, BLIS_PACKM_9XK_KER = 9, BLIS_PACKM_10XK_KER = 10, BLIS_PACKM_11XK_KER = 11, BLIS_PACKM_12XK_KER = 12, BLIS_PACKM_13XK_KER = 13, BLIS_PACKM_14XK_KER = 14, BLIS_PACKM_15XK_KER = 15, BLIS_PACKM_16XK_KER = 16, BLIS_PACKM_17XK_KER = 17, BLIS_PACKM_18XK_KER = 18, BLIS_PACKM_19XK_KER = 19, BLIS_PACKM_20XK_KER = 20, BLIS_PACKM_21XK_KER = 21, BLIS_PACKM_22XK_KER = 22, BLIS_PACKM_23XK_KER = 23, BLIS_PACKM_24XK_KER = 24, BLIS_PACKM_25XK_KER = 25, BLIS_PACKM_26XK_KER = 26, BLIS_PACKM_27XK_KER = 27, BLIS_PACKM_28XK_KER = 28, BLIS_PACKM_29XK_KER = 29, BLIS_PACKM_30XK_KER = 30, BLIS_PACKM_31XK_KER = 31, BLIS_UNPACKM_0XK_KER = 0, BLIS_UNPACKM_1XK_KER = 1, BLIS_UNPACKM_2XK_KER = 2, BLIS_UNPACKM_3XK_KER = 3, BLIS_UNPACKM_4XK_KER = 4, BLIS_UNPACKM_5XK_KER = 5, BLIS_UNPACKM_6XK_KER = 6, BLIS_UNPACKM_7XK_KER = 7, BLIS_UNPACKM_8XK_KER = 8, BLIS_UNPACKM_9XK_KER = 9, BLIS_UNPACKM_10XK_KER = 10, BLIS_UNPACKM_11XK_KER = 11, BLIS_UNPACKM_12XK_KER = 12, BLIS_UNPACKM_13XK_KER = 13, BLIS_UNPACKM_14XK_KER = 14, BLIS_UNPACKM_15XK_KER = 15, BLIS_UNPACKM_16XK_KER = 16, BLIS_UNPACKM_17XK_KER = 17, BLIS_UNPACKM_18XK_KER = 18, BLIS_UNPACKM_19XK_KER = 19, BLIS_UNPACKM_20XK_KER = 20, BLIS_UNPACKM_21XK_KER = 21, BLIS_UNPACKM_22XK_KER = 22, BLIS_UNPACKM_23XK_KER = 23, BLIS_UNPACKM_24XK_KER = 24, BLIS_UNPACKM_25XK_KER = 25, BLIS_UNPACKM_26XK_KER = 26, BLIS_UNPACKM_27XK_KER = 27, BLIS_UNPACKM_28XK_KER = 28, BLIS_UNPACKM_29XK_KER = 29, BLIS_UNPACKM_30XK_KER = 30, BLIS_UNPACKM_31XK_KER = 31 } l1mkr_t; #define BLIS_NUM_PACKM_KERS 32 #define BLIS_NUM_UNPACKM_KERS 32 typedef enum { BLIS_GEMM_UKR = 0, BLIS_GEMMTRSM_L_UKR, BLIS_GEMMTRSM_U_UKR, BLIS_TRSM_L_UKR, BLIS_TRSM_U_UKR } l3ukr_t; #define BLIS_NUM_LEVEL3_UKRS 5 typedef enum { BLIS_REFERENCE_UKERNEL = 0, BLIS_VIRTUAL_UKERNEL, BLIS_OPTIMIZED_UKERNEL, BLIS_NOTAPPLIC_UKERNEL } kimpl_t; #define BLIS_NUM_UKR_IMPL_TYPES 4 #if 0 typedef enum { // RV = row-stored, contiguous vector-loading // RG = row-stored, non-contiguous gather-loading // CV = column-stored, contiguous vector-loading // CG = column-stored, non-contiguous gather-loading // RD = row-stored, dot-based // CD = col-stored, dot-based // RC = row-stored, column-times-column // CR = column-stored, row-times-row // GX = general-stored generic implementation BLIS_GEMMSUP_RV_UKR = 0, BLIS_GEMMSUP_RG_UKR, BLIS_GEMMSUP_CV_UKR, BLIS_GEMMSUP_CG_UKR, BLIS_GEMMSUP_RD_UKR, BLIS_GEMMSUP_CD_UKR, BLIS_GEMMSUP_RC_UKR, BLIS_GEMMSUP_CR_UKR, BLIS_GEMMSUP_GX_UKR, } l3sup_t; #define BLIS_NUM_LEVEL3_SUP_UKRS 9 #endif typedef enum { // 3-operand storage combinations BLIS_RRR = 0, BLIS_RRC, // 1 BLIS_RCR, // 2 BLIS_RCC, // 3 BLIS_CRR, // 4 BLIS_CRC, // 5 BLIS_CCR, // 6 BLIS_CCC, // 7 BLIS_XXX, // 8 #if 0 BLIS_RRG, BLIS_RCG, BLIS_RGR, BLIS_RGC, BLIS_RGG, BLIS_CRG, BLIS_CCG, BLIS_CGR, BLIS_CGC, BLIS_CGG, BLIS_GRR, BLIS_GRC, BLIS_GRG, BLIS_GCR, BLIS_GCC, BLIS_GCG, BLIS_GGR, BLIS_GGC, BLIS_GGG, #endif } stor3_t; #define BLIS_NUM_3OP_RC_COMBOS 9 //#define BLIS_NUM_3OP_RCG_COMBOS 27 #if 0 typedef enum { BLIS_JC_IDX = 0, BLIS_PC_IDX, BLIS_IC_IDX, BLIS_JR_IDX, BLIS_IR_IDX, BLIS_PR_IDX } thridx_t; #endif #define BLIS_NUM_LOOPS 6 // -- Operation ID type -- typedef enum { // // NOTE: If/when additional type values are added to this enum, // you must either: // - keep the level-3 values (starting with _GEMM) beginning at // index 0; or // - if the value range is moved such that it does not begin at // index 0, implement something like a BLIS_OPID_LEVEL3_RANGE_START // value that can be subtracted from the opid_t value to map it // to a zero-based range. // This is needed because these level-3 opid_t values are used in // bli_l3_ind.c to index into arrays. // BLIS_GEMM = 0, BLIS_GEMMT, BLIS_HEMM, BLIS_HERK, BLIS_HER2K, BLIS_SYMM, BLIS_SYRK, BLIS_SYR2K, BLIS_TRMM3, BLIS_TRMM, BLIS_TRSM, BLIS_NOID } opid_t; #define BLIS_NUM_LEVEL3_OPS 11 // -- Blocksize ID type -- typedef enum { // NOTE: the level-3 blocksizes MUST be indexed starting at zero. // At one point, we made this assumption in bli_cntx_set_blkszs() // and friends. BLIS_KR = 0, BLIS_MR, BLIS_NR, BLIS_MC, BLIS_KC, BLIS_NC, BLIS_M2, // level-2 blocksize in m dimension BLIS_N2, // level-2 blocksize in n dimension BLIS_AF, // level-1f axpyf fusing factor BLIS_DF, // level-1f dotxf fusing factor BLIS_XF, // level-1f dotxaxpyf fusing factor BLIS_NO_PART // used as a placeholder when blocksizes are not applicable. } bszid_t; #define BLIS_NUM_BLKSZS 11 // -- Threshold ID type -- typedef enum { BLIS_MT = 0, // level-3 small/unpacked matrix threshold in m dimension BLIS_NT, // level-3 small/unpacked matrix threshold in n dimension BLIS_KT // level-3 small/unpacked matrix threshold in k dimension } threshid_t; #define BLIS_NUM_THRESH 3 // -- Architecture ID type -- // NOTE: This typedef enum must be kept up-to-date with the arch_t // string array in bli_arch.c. Whenever values are added/inserted // OR if values are rearranged, be sure to update the string array // in bli_arch.c. typedef enum { // NOTE: The C language standard guarantees that the first enum value // starts at 0. // Intel BLIS_ARCH_SKX, BLIS_ARCH_KNL, BLIS_ARCH_KNC, BLIS_ARCH_HASWELL, BLIS_ARCH_SANDYBRIDGE, BLIS_ARCH_PENRYN, // AMD BLIS_ARCH_ZEN3, BLIS_ARCH_ZEN2, BLIS_ARCH_ZEN, BLIS_ARCH_EXCAVATOR, BLIS_ARCH_STEAMROLLER, BLIS_ARCH_PILEDRIVER, BLIS_ARCH_BULLDOZER, // ARM BLIS_ARCH_ARMSVE, BLIS_ARCH_A64FX, BLIS_ARCH_FIRESTORM, BLIS_ARCH_THUNDERX2, BLIS_ARCH_CORTEXA57, BLIS_ARCH_CORTEXA53, BLIS_ARCH_CORTEXA15, BLIS_ARCH_CORTEXA9, // IBM/Power BLIS_ARCH_POWER10, BLIS_ARCH_POWER9, BLIS_ARCH_POWER7, BLIS_ARCH_BGQ, // Generic architecture/configuration BLIS_ARCH_GENERIC, // The total number of defined architectures. This must be last in the // list of enums since its definition assumes that the previous enum // value (BLIS_ARCH_GENERIC) is given index num_archs-1. BLIS_NUM_ARCHS } arch_t; // // -- BLIS misc. structure types ----------------------------------------------- // // This header must be included here (or earlier) because definitions it // provides are needed in the pool_t and related structs. #include "bli_pthread.h" // -- Pool block type -- typedef struct { void* buf; siz_t block_size; } pblk_t; // -- Pool type -- typedef struct { void* block_ptrs; dim_t block_ptrs_len; dim_t top_index; dim_t num_blocks; siz_t block_size; siz_t align_size; siz_t offset_size; malloc_ft malloc_fp; free_ft free_fp; } pool_t; // -- Array type -- typedef struct { void* buf; siz_t num_elem; siz_t elem_size; } array_t; // -- Locked pool-of-arrays-of-pools type -- typedef struct { bli_pthread_mutex_t mutex; pool_t pool; siz_t def_array_len; } apool_t; // -- packing block allocator: Locked set of pools type -- typedef struct pba_s { pool_t pools[3]; bli_pthread_mutex_t mutex; // These fields are used for general-purpose allocation. siz_t align_size; malloc_ft malloc_fp; free_ft free_fp; } pba_t; // -- Memory object type -- typedef struct mem_s { pblk_t pblk; packbuf_t buf_type; pool_t* pool; siz_t size; } mem_t; // -- Control tree node type -- struct cntl_s { // Basic fields (usually required). opid_t family; bszid_t bszid; void_fp var_func; struct cntl_s* sub_prenode; struct cntl_s* sub_node; // Optional fields (needed only by some operations such as packm). // NOTE: first field of params must be a uint64_t containing the size // of the struct. void* params; // Internal fields that track "cached" data. mem_t pack_mem; }; typedef struct cntl_s cntl_t; // -- Blocksize object type -- typedef struct blksz_s { // Primary blocksize values. dim_t v[BLIS_NUM_FP_TYPES]; // Blocksize extensions. dim_t e[BLIS_NUM_FP_TYPES]; } blksz_t; // -- Function pointer object type -- typedef struct func_s { // Kernel function address. void_fp ptr[BLIS_NUM_FP_TYPES]; } func_t; // -- Multi-boolean object type -- typedef struct mbool_s { bool v[BLIS_NUM_FP_TYPES]; } mbool_t; // -- Auxiliary kernel info type -- // Note: This struct is used by macro-kernels to package together extra // parameter values that may be of use to the micro-kernel without // cluttering up the micro-kernel interface itself. typedef struct { // The pack schemas of A and B. pack_t schema_a; pack_t schema_b; // Pointers to the micro-panels of A and B which will be used by the // next call to the micro-kernel. void* a_next; void* b_next; // The imaginary strides of A and B. inc_t is_a; inc_t is_b; // The panel strides of A and B. // NOTE: These are only used in situations where iteration over the // micropanels takes place in part within the kernel code (e.g. sup // millikernels). inc_t ps_a; inc_t ps_b; // The type to convert to on output. //num_t dt_on_output; // (Virtual) microkernel address and additional parameters. void_fp ukr; void* params; } auxinfo_t; // -- Global scalar constant data struct -- // Note: This struct is used only when statically initializing the // global scalar constants in bli_const.c. typedef struct constdata_s { float s; double d; scomplex c; dcomplex z; gint_t i; } constdata_t; // // -- BLIS object type definitions --------------------------------------------- // // Forward declarations for function pointer types struct obj_s; struct cntx_s; struct rntm_s; struct thrinfo_s; typedef void (*obj_pack_fn_t) ( struct obj_s* a, struct obj_s* ap, struct cntx_s* cntx, struct rntm_s* rntm, struct cntl_s* cntl, struct thrinfo_s* thread ); typedef void (*obj_ker_fn_t) ( struct obj_s* a, struct obj_s* b, struct obj_s* c, struct cntx_s* cntx, struct rntm_s* rntm, struct cntl_s* cntl, struct thrinfo_s* thread ); typedef struct obj_s { // Basic fields struct obj_s* root; dim_t off[2]; dim_t dim[2]; doff_t diag_off; objbits_t info; objbits_t info2; siz_t elem_size; void* buffer; inc_t rs; inc_t cs; inc_t is; // Bufferless scalar storage atom_t scalar; // Pack-related fields dim_t m_padded; // m dimension of matrix, including any padding dim_t n_padded; // n dimension of matrix, including any padding inc_t ps; // panel stride (distance to next panel) inc_t pd; // panel dimension (the "width" of a panel: // usually MR or NR) dim_t m_panel; // m dimension of a "full" panel dim_t n_panel; // n dimension of a "full" panel // User-customizable fields obj_pack_fn_t pack_fn; void* pack_params; obj_ker_fn_t ker_fn; void* ker_params; } obj_t; // Pre-initializors. Things that must be set afterwards: // - root object pointer // - info bitfields: dt, target_dt, exec_dt, comp_dt // - info2 bitfields: scalar_dt // - elem_size // - dims, strides // - buffer // - internal scalar buffer (must always set imaginary component) #define BLIS_OBJECT_INITIALIZER \ { \ .root = NULL, \ \ .off = { 0, 0 }, \ .dim = { 0, 0 }, \ .diag_off = 0, \ \ .info = 0x0 | BLIS_BITVAL_DENSE | \ BLIS_BITVAL_GENERAL, \ .info2 = 0x0, \ .elem_size = sizeof( float ), /* this is changed later. */ \ \ .buffer = NULL, \ .rs = 0, \ .cs = 0, \ .is = 1, \ \ .scalar = { 0.0, 0.0 }, \ \ .m_padded = 0, \ .n_padded = 0, \ .ps = 0, \ .pd = 0, \ .m_panel = 0, \ .n_panel = 0, \ \ .pack_fn = NULL, \ .pack_params = NULL, \ .ker_fn = NULL, \ .ker_params = NULL \ } #define BLIS_OBJECT_INITIALIZER_1X1 \ { \ .root = NULL, \ \ .off = { 0, 0 }, \ .dim = { 1, 1 }, \ .diag_off = 0, \ \ .info = 0x0 | BLIS_BITVAL_DENSE | \ BLIS_BITVAL_GENERAL, \ .info2 = 0x0, \ .elem_size = sizeof( float ), /* this is changed later. */ \ \ .buffer = NULL, \ .rs = 0, \ .cs = 0, \ .is = 1, \ \ .scalar = { 0.0, 0.0 }, \ \ .m_padded = 0, \ .n_padded = 0, \ .ps = 0, \ .pd = 0, \ .m_panel = 0, \ .n_panel = 0, \ \ .pack_fn = NULL, \ .pack_params = NULL, \ .ker_fn = NULL, \ .ker_params = NULL \ } // Define these macros here since they must be updated if contents of // obj_t changes. BLIS_INLINE void bli_obj_init_full_shallow_copy_of( obj_t* a, obj_t* b ) { b->root = a->root; b->off[0] = a->off[0]; b->off[1] = a->off[1]; b->dim[0] = a->dim[0]; b->dim[1] = a->dim[1]; b->diag_off = a->diag_off; b->info = a->info; b->info2 = a->info2; b->elem_size = a->elem_size; b->buffer = a->buffer; b->rs = a->rs; b->cs = a->cs; b->is = a->is; b->scalar = a->scalar; //b->pack_mem = a->pack_mem; b->m_padded = a->m_padded; b->n_padded = a->n_padded; b->ps = a->ps; b->pd = a->pd; b->m_panel = a->m_panel; b->n_panel = a->n_panel; b->pack_fn = a->pack_fn; b->pack_params = a->pack_params; b->ker_fn = a->ker_fn; b->ker_params = a->ker_params; } BLIS_INLINE void bli_obj_init_subpart_from( obj_t* a, obj_t* b ) { b->root = a->root; b->off[0] = a->off[0]; b->off[1] = a->off[1]; // Avoid copying m and n since they will be overwritten. //b->dim[0] = a->dim[0]; //b->dim[1] = a->dim[1]; b->diag_off = a->diag_off; b->info = a->info; b->info2 = a->info2; b->elem_size = a->elem_size; b->buffer = a->buffer; b->rs = a->rs; b->cs = a->cs; b->is = a->is; b->scalar = a->scalar; // Avoid copying pack_mem entry. // FGVZ: You should probably make sure this is right. //b->pack_mem = a->pack_mem; b->m_padded = a->m_padded; b->n_padded = a->n_padded; b->ps = a->ps; b->pd = a->pd; b->m_panel = a->m_panel; b->n_panel = a->n_panel; b->pack_fn = a->pack_fn; b->pack_params = a->pack_params; b->ker_fn = a->ker_fn; b->ker_params = a->ker_params; } // Initializors for global scalar constants. // NOTE: These must remain cpp macros since they are initializor // expressions, not functions. #define bli_obj_init_const( buffer0 ) \ { \ .root = NULL, \ \ .off = { 0, 0 }, \ .dim = { 1, 1 }, \ .diag_off = 0, \ \ .info = 0x0 | BLIS_BITVAL_CONST_TYPE | \ BLIS_BITVAL_DENSE | \ BLIS_BITVAL_GENERAL, \ .info2 = 0x0, \ .elem_size = sizeof( constdata_t ), \ \ .buffer = buffer0, \ .rs = 1, \ .cs = 1, \ .is = 1 \ } #define bli_obj_init_constdata( val ) \ { \ .s = ( float )val, \ .d = ( double )val, \ .c = { .real = ( float )val, .imag = 0.0f }, \ .z = { .real = ( double )val, .imag = 0.0 }, \ .i = ( gint_t )val, \ } // -- Context type -- typedef struct cntx_s { blksz_t blkszs[ BLIS_NUM_BLKSZS ]; bszid_t bmults[ BLIS_NUM_BLKSZS ]; func_t l3_vir_ukrs[ BLIS_NUM_LEVEL3_UKRS ]; func_t l3_nat_ukrs[ BLIS_NUM_LEVEL3_UKRS ]; mbool_t l3_nat_ukrs_prefs[ BLIS_NUM_LEVEL3_UKRS ]; blksz_t l3_sup_thresh[ BLIS_NUM_THRESH ]; void* l3_sup_handlers[ BLIS_NUM_LEVEL3_OPS ]; blksz_t l3_sup_blkszs[ BLIS_NUM_BLKSZS ]; func_t l3_sup_kers[ BLIS_NUM_3OP_RC_COMBOS ]; mbool_t l3_sup_kers_prefs[ BLIS_NUM_3OP_RC_COMBOS ]; func_t l1f_kers[ BLIS_NUM_LEVEL1F_KERS ]; func_t l1v_kers[ BLIS_NUM_LEVEL1V_KERS ]; func_t packm_kers[ BLIS_NUM_PACKM_KERS ]; func_t unpackm_kers[ BLIS_NUM_UNPACKM_KERS ]; ind_t method; } cntx_t; // -- Runtime type -- // NOTE: The order of these fields must be kept consistent with the definition // of the BLIS_RNTM_INITIALIZER macro in bli_rntm.h. typedef struct rntm_s { // "External" fields: these may be queried by the end-user. bool auto_factor; dim_t num_threads; dim_t thrloop[ BLIS_NUM_LOOPS ]; bool pack_a; // enable/disable packing of left-hand matrix A. bool pack_b; // enable/disable packing of right-hand matrix B. bool l3_sup; // enable/disable small matrix handling in level-3 ops. // "Internal" fields: these should not be exposed to the end-user. // The small block pool, which is attached in the l3 thread decorator. pool_t* sba_pool; // The packing block allocator, which is attached in the l3 thread decorator. pba_t* pba; } rntm_t; // -- Error types -- typedef enum { BLIS_NO_ERROR_CHECKING = 0, BLIS_FULL_ERROR_CHECKING } errlev_t; typedef enum { // Generic error codes BLIS_SUCCESS = ( -1), BLIS_FAILURE = ( -2), BLIS_ERROR_CODE_MIN = ( -9), // General errors BLIS_INVALID_ERROR_CHECKING_LEVEL = ( -10), BLIS_UNDEFINED_ERROR_CODE = ( -11), BLIS_NULL_POINTER = ( -12), BLIS_NOT_YET_IMPLEMENTED = ( -13), // Parameter-specific errors BLIS_INVALID_SIDE = ( -20), BLIS_INVALID_UPLO = ( -21), BLIS_INVALID_TRANS = ( -22), BLIS_INVALID_CONJ = ( -23), BLIS_INVALID_DIAG = ( -24), BLIS_INVALID_MACHVAL = ( -25), BLIS_EXPECTED_NONUNIT_DIAG = ( -26), // Datatype-specific errors BLIS_INVALID_DATATYPE = ( -30), BLIS_EXPECTED_FLOATING_POINT_DATATYPE = ( -31), BLIS_EXPECTED_NONINTEGER_DATATYPE = ( -32), BLIS_EXPECTED_NONCONSTANT_DATATYPE = ( -33), BLIS_EXPECTED_REAL_DATATYPE = ( -34), BLIS_EXPECTED_INTEGER_DATATYPE = ( -35), BLIS_INCONSISTENT_DATATYPES = ( -36), BLIS_EXPECTED_REAL_PROJ_OF = ( -37), BLIS_EXPECTED_REAL_VALUED_OBJECT = ( -38), BLIS_INCONSISTENT_PRECISIONS = ( -39), // Dimension-specific errors BLIS_NONCONFORMAL_DIMENSIONS = ( -40), BLIS_EXPECTED_SCALAR_OBJECT = ( -41), BLIS_EXPECTED_VECTOR_OBJECT = ( -42), BLIS_UNEQUAL_VECTOR_LENGTHS = ( -43), BLIS_EXPECTED_SQUARE_OBJECT = ( -44), BLIS_UNEXPECTED_OBJECT_LENGTH = ( -45), BLIS_UNEXPECTED_OBJECT_WIDTH = ( -46), BLIS_UNEXPECTED_VECTOR_DIM = ( -47), BLIS_UNEXPECTED_DIAG_OFFSET = ( -48), BLIS_NEGATIVE_DIMENSION = ( -49), // Stride-specific errors BLIS_INVALID_ROW_STRIDE = ( -50), BLIS_INVALID_COL_STRIDE = ( -51), BLIS_INVALID_DIM_STRIDE_COMBINATION = ( -52), // Structure-specific errors BLIS_EXPECTED_GENERAL_OBJECT = ( -60), BLIS_EXPECTED_HERMITIAN_OBJECT = ( -61), BLIS_EXPECTED_SYMMETRIC_OBJECT = ( -62), BLIS_EXPECTED_TRIANGULAR_OBJECT = ( -63), // Storage-specific errors BLIS_EXPECTED_UPPER_OR_LOWER_OBJECT = ( -70), // Partitioning-specific errors BLIS_INVALID_3x1_SUBPART = ( -80), BLIS_INVALID_1x3_SUBPART = ( -81), BLIS_INVALID_3x3_SUBPART = ( -82), // Control tree-specific errors BLIS_UNEXPECTED_NULL_CONTROL_TREE = ( -90), // Packing-specific errors BLIS_PACK_SCHEMA_NOT_SUPPORTED_FOR_UNPACK = (-100), // Buffer-specific errors BLIS_EXPECTED_NONNULL_OBJECT_BUFFER = (-110), // Memory errors BLIS_MALLOC_RETURNED_NULL = (-120), // Internal memory pool errors BLIS_INVALID_PACKBUF = (-130), BLIS_EXHAUSTED_CONTIG_MEMORY_POOL = (-131), BLIS_INSUFFICIENT_STACK_BUF_SIZE = (-132), BLIS_ALIGNMENT_NOT_POWER_OF_TWO = (-133), BLIS_ALIGNMENT_NOT_MULT_OF_PTR_SIZE = (-134), // Object-related errors BLIS_EXPECTED_OBJECT_ALIAS = (-140), // Architecture-related errors BLIS_INVALID_ARCH_ID = (-150), BLIS_UNINITIALIZED_GKS_CNTX = (-151), // Blocksize-related errors BLIS_MC_DEF_NONMULTIPLE_OF_MR = (-160), BLIS_MC_MAX_NONMULTIPLE_OF_MR = (-161), BLIS_NC_DEF_NONMULTIPLE_OF_NR = (-162), BLIS_NC_MAX_NONMULTIPLE_OF_NR = (-163), BLIS_KC_DEF_NONMULTIPLE_OF_KR = (-164), BLIS_KC_MAX_NONMULTIPLE_OF_KR = (-165), BLIS_ERROR_CODE_MAX = (-170) } err_t; #endif blis-0.9.0/frame/include/bli_x86_asm_macros.h000066400000000000000000001334531422157504600210350ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2018, The University of Texas at Austin Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_X86_ASM_MACROS_H #define BLIS_X86_ASM_MACROS_H // // Assembly macros to make inline x86 with AT&T syntax somewhat less painful // // "Private" macros end with _ // // Default syntax is Intel #if !defined(BLIS_ASM_SYNTAX_ATT) && !defined(BLIS_ASM_SYNTAX_INTEL) #define BLIS_ASM_SYNTAX_INTEL #endif #define STRINGIFY_(...) #__VA_ARGS__ #define GET_MACRO_(_1_,_2_,_3_,_4_,NAME,...) NAME #if (defined(_WIN32) && !defined(__clang__) && !defined(__MINGW32__)) || defined(__MIC__) // Intel-style assembly blocks #define BEGIN_ASM __asm { #define END_ASM(...) } #ifdef BLIS_ASM_SYNTAX_INTEL #define INSTR_4_(name,_0,_1,_2,_3) name _0,_1,_2,_3 #define INSTR_3_(name,_0,_1,_2) name _0,_1,_2 #define INSTR_2_(name,_0,_1) name _0,_1 #define INSTR_1_(name,_0) name _0 #define INSTR_0_(name) name #else #define INSTR_4_(name,_0,_1,_2,_3) name _3,_2,_1,_0 #define INSTR_3_(name,_0,_1,_2) name _2,_1,_0 #define INSTR_2_(name,_0,_1) name _1,_0 #define INSTR_1_(name,_0) name _0 #define INSTR_0_(name) name #endif #define LABEL(label) label: #define REGISTER_(r) r #define IMM(x) x #define VAR(x) x #define MASK_(x) {x} #define JMP_(insn, target) insn target #define MEM_4_(reg,off,scale,disp) [reg + off*scale + disp] #define MEM_3_(reg,off,scale) [reg + off*scale] #define MEM_2_(reg,disp) [reg + disp] #define MEM_1_(reg) [reg] #define ALIGN4 align 4 #define ALIGN8 align 8 #define ALIGN16 align 16 #define ALIGN32 align 32 #else // GCC extended assembly with AT&T syntax #define COMMENT_BEGIN "#" #define COMMENT_END #define BEGIN_ASM() __asm__ volatile ( #define END_ASM(...) __VA_ARGS__ ); #ifdef BLIS_ASM_SYNTAX_ATT #define INSTR_4_(name,_0,_1,_2,_3) STRINGIFY_(name) " " STRINGIFY_(_0,_1,_2,_3) "\n\t" #define INSTR_3_(name,_0,_1,_2) STRINGIFY_(name) " " STRINGIFY_(_0,_1,_2) "\n\t" #define INSTR_2_(name,_0,_1) STRINGIFY_(name) " " STRINGIFY_(_0,_1) "\n\t" #define INSTR_1_(name,_0) STRINGIFY_(name) " " STRINGIFY_(_0) "\n\t" #define INSTR_0_(name) STRINGIFY_(name) "\n\t" #else #define INSTR_4_(name,_0,_1,_2,_3) STRINGIFY_(name) " " STRINGIFY_(_3,_2,_1,_0) "\n\t" #define INSTR_3_(name,_0,_1,_2) STRINGIFY_(name) " " STRINGIFY_(_2,_1,_0) "\n\t" #define INSTR_2_(name,_0,_1) STRINGIFY_(name) " " STRINGIFY_(_1,_0) "\n\t" #define INSTR_1_(name,_0) STRINGIFY_(name) " " STRINGIFY_(_0) "\n\t" #define INSTR_0_(name) STRINGIFY_(name) "\n\t" #endif #if BLIS_OS_OSX #define LABEL_(label) "L" STRINGIFY_(label) "%=" #else #define LABEL_(label) ".L" STRINGIFY_(label) "%=" #endif #define REGISTER_(r) %%r #define IMM(x) $##x #define VAR(x) %[x] #define MASK_(x) %{x%} #define LABEL(target) LABEL_(target) ":\n\t" #define JMP_(insn, target) STRINGIFY_(insn) " " LABEL_(target) "\n\t" #define MEM_4_(reg,off,scale,disp) disp(reg,off,scale) #define MEM_3_(reg,off,scale) (reg,off,scale) #define MEM_2_(reg,disp) disp(reg) #define MEM_1_(reg) (reg) #define ALIGN4 ".p2align 2 \n\t" #define ALIGN8 ".p2align 3 \n\t" #define ALIGN16 ".p2align 4 \n\t" #define ALIGN32 ".p2align 5 \n\t" #endif #define begin_asm() BEGIN_ASM() #define end_asm(...) END_ASM(__VA_ARGS__) #define label(...) LABEL(__VA_ARGS__) #define imm(...) IMM(__VA_ARGS__) #define var(...) VAR(__VA_ARGS__) #define align16 ALIGN16 #define align32 ALIGN32 // General-purpose registers #define AL REGISTER_(al) #define AH REGISTER_(ah) #define BL REGISTER_(bl) #define BH REGISTER_(bh) #define CL REGISTER_(cl) #define CH REGISTER_(ch) #define DL REGISTER_(dl) #define DH REGISTER_(dh) #define R8B REGISTER_(r8b) #define R9B REGISTER_(r9b) #define R10B REGISTER_(r10b) #define R11B REGISTER_(r11b) #define R12B REGISTER_(r12b) #define R13B REGISTER_(r13b) #define R14B REGISTER_(r14b) #define R15B REGISTER_(r15b) #define al AL #define ah AH #define bl BL #define bh BH #define cl CL #define ch CH #define dl DL #define dh DH #define r8b R8B #define r9b R9B #define r10b R10B #define r11b R11B #define r12b R12B #define r13b R13B #define r14b R14B #define r15b R15B #define AX REGISTER_(ax) #define BX REGISTER_(bx) #define CX REGISTER_(cx) #define DX REGISTER_(dx) #define SI REGISTER_(si) #define DI REGISTER_(di) #define BP REGISTER_(bp) #define SP REGISTER_(sp) #define R8W REGISTER_(r8w) #define R9W REGISTER_(r9w) #define R10W REGISTER_(r10w) #define R11W REGISTER_(r11w) #define R12W REGISTER_(r12w) #define R13W REGISTER_(r13w) #define R14W REGISTER_(r14w) #define R15W REGISTER_(r15w) #define ax AX #define bx BX #define cx CX #define dx DX #define si SI #define di DI #define bp BP #define sp SP #define r8w R8W #define r9w R9W #define r10w R10W #define r11w R11W #define r12w R12W #define r13w R13W #define r14w R14W #define r15w R15W #define EAX REGISTER_(eax) #define EBX REGISTER_(ebx) #define ECX REGISTER_(ecx) #define EDX REGISTER_(edx) #define ESP REGISTER_(esp) #define EBP REGISTER_(ebp) #define EDI REGISTER_(edi) #define ESI REGISTER_(esi) #define R8D REGISTER_(r8d) #define R9D REGISTER_(r9d) #define R10D REGISTER_(r10d) #define R11D REGISTER_(r11d) #define R12D REGISTER_(r12d) #define R13D REGISTER_(r13d) #define R14D REGISTER_(r14d) #define R15D REGISTER_(r15d) #define eax EAX #define ebx EBX #define ecx ECX #define edx EDX #define esp ESP #define ebp EBP #define edi EDI #define esi ESI #define r8d R8D #define r9d R9D #define r10d R10D #define r11d R11D #define r12d R12D #define r13d R13D #define r14d R14D #define r15d R15D #define RAX REGISTER_(rax) #define RBX REGISTER_(rbx) #define RCX REGISTER_(rcx) #define RDX REGISTER_(rdx) #define RSP REGISTER_(rsp) #define RBP REGISTER_(rbp) #define RDI REGISTER_(rdi) #define RSI REGISTER_(rsi) #define R8 REGISTER_(r8) #define R9 REGISTER_(r9) #define R10 REGISTER_(r10) #define R11 REGISTER_(r11) #define R12 REGISTER_(r12) #define R13 REGISTER_(r13) #define R14 REGISTER_(r14) #define R15 REGISTER_(r15) #define rax RAX #define rbx RBX #define rcx RCX #define rdx RDX #define rsp RSP #define rbp RBP #define rdi RDI #define rsi RSI #define r8 R8 #define r9 R9 #define r10 R10 #define r11 R11 #define r12 R12 #define r13 R13 #define r14 R14 #define r15 R15 // Vector registers #define XMM(x) REGISTER_(Xmm##x) #define YMM(x) REGISTER_(Ymm##x) #define ZMM(x) REGISTER_(Zmm##x) #define K(x) REGISTER_(k##x) #define MASK_K(n) MASK_(K(n)) #define MASK_KZ(n) MASK_(K(n))MASK_(z) #define xmm(x) XMM(x) #define ymm(x) YMM(x) #define zmm(x) ZMM(x) #define k(x) K(x) #define mask_k(x) MASK_K(x) #define mask_kz(x) MASK_KZ(x) #define XMM0 XMM(0) #define XMM1 XMM(1) #define XMM2 XMM(2) #define XMM3 XMM(3) #define XMM4 XMM(4) #define XMM5 XMM(5) #define XMM6 XMM(6) #define XMM7 XMM(7) #define XMM8 XMM(8) #define XMM9 XMM(9) #define XMM10 XMM(10) #define XMM11 XMM(11) #define XMM12 XMM(12) #define XMM13 XMM(13) #define XMM14 XMM(14) #define XMM15 XMM(15) #define XMM16 XMM(16) #define XMM17 XMM(17) #define XMM18 XMM(18) #define XMM19 XMM(19) #define XMM20 XMM(20) #define XMM21 XMM(21) #define XMM22 XMM(22) #define XMM23 XMM(23) #define XMM24 XMM(24) #define XMM25 XMM(25) #define XMM26 XMM(26) #define XMM27 XMM(27) #define XMM28 XMM(28) #define XMM29 XMM(29) #define XMM30 XMM(30) #define XMM31 XMM(31) #define YMM0 YMM(0) #define YMM1 YMM(1) #define YMM2 YMM(2) #define YMM3 YMM(3) #define YMM4 YMM(4) #define YMM5 YMM(5) #define YMM6 YMM(6) #define YMM7 YMM(7) #define YMM8 YMM(8) #define YMM9 YMM(9) #define YMM10 YMM(10) #define YMM11 YMM(11) #define YMM12 YMM(12) #define YMM13 YMM(13) #define YMM14 YMM(14) #define YMM15 YMM(15) #define YMM16 YMM(16) #define YMM17 YMM(17) #define YMM18 YMM(18) #define YMM19 YMM(19) #define YMM20 YMM(20) #define YMM21 YMM(21) #define YMM22 YMM(22) #define YMM23 YMM(23) #define YMM24 YMM(24) #define YMM25 YMM(25) #define YMM26 YMM(26) #define YMM27 YMM(27) #define YMM28 YMM(28) #define YMM29 YMM(29) #define YMM30 YMM(30) #define YMM31 YMM(31) #define ZMM0 ZMM(0) #define ZMM1 ZMM(1) #define ZMM2 ZMM(2) #define ZMM3 ZMM(3) #define ZMM4 ZMM(4) #define ZMM5 ZMM(5) #define ZMM6 ZMM(6) #define ZMM7 ZMM(7) #define ZMM8 ZMM(8) #define ZMM9 ZMM(9) #define ZMM10 ZMM(10) #define ZMM11 ZMM(11) #define ZMM12 ZMM(12) #define ZMM13 ZMM(13) #define ZMM14 ZMM(14) #define ZMM15 ZMM(15) #define ZMM16 ZMM(16) #define ZMM17 ZMM(17) #define ZMM18 ZMM(18) #define ZMM19 ZMM(19) #define ZMM20 ZMM(20) #define ZMM21 ZMM(21) #define ZMM22 ZMM(22) #define ZMM23 ZMM(23) #define ZMM24 ZMM(24) #define ZMM25 ZMM(25) #define ZMM26 ZMM(26) #define ZMM27 ZMM(27) #define ZMM28 ZMM(28) #define ZMM29 ZMM(29) #define ZMM30 ZMM(30) #define ZMM31 ZMM(31) #define xmm0 xmm(0) #define xmm1 xmm(1) #define xmm2 xmm(2) #define xmm3 xmm(3) #define xmm4 xmm(4) #define xmm5 xmm(5) #define xmm6 xmm(6) #define xmm7 xmm(7) #define xmm8 xmm(8) #define xmm9 xmm(9) #define xmm10 xmm(10) #define xmm11 xmm(11) #define xmm12 xmm(12) #define xmm13 xmm(13) #define xmm14 xmm(14) #define xmm15 xmm(15) #define xmm16 xmm(16) #define xmm17 xmm(17) #define xmm18 xmm(18) #define xmm19 xmm(19) #define xmm20 xmm(20) #define xmm21 xmm(21) #define xmm22 xmm(22) #define xmm23 xmm(23) #define xmm24 xmm(24) #define xmm25 xmm(25) #define xmm26 xmm(26) #define xmm27 xmm(27) #define xmm28 xmm(28) #define xmm29 xmm(29) #define xmm30 xmm(30) #define xmm31 xmm(31) #define ymm0 ymm(0) #define ymm1 ymm(1) #define ymm2 ymm(2) #define ymm3 ymm(3) #define ymm4 ymm(4) #define ymm5 ymm(5) #define ymm6 ymm(6) #define ymm7 ymm(7) #define ymm8 ymm(8) #define ymm9 ymm(9) #define ymm10 ymm(10) #define ymm11 ymm(11) #define ymm12 ymm(12) #define ymm13 ymm(13) #define ymm14 ymm(14) #define ymm15 ymm(15) #define ymm16 ymm(16) #define ymm17 ymm(17) #define ymm18 ymm(18) #define ymm19 ymm(19) #define ymm20 ymm(20) #define ymm21 ymm(21) #define ymm22 ymm(22) #define ymm23 ymm(23) #define ymm24 ymm(24) #define ymm25 ymm(25) #define ymm26 ymm(26) #define ymm27 ymm(27) #define ymm28 ymm(28) #define ymm29 ymm(29) #define ymm30 ymm(30) #define ymm31 ymm(31) #define zmm0 zmm(0) #define zmm1 zmm(1) #define zmm2 zmm(2) #define zmm3 zmm(3) #define zmm4 zmm(4) #define zmm5 zmm(5) #define zmm6 zmm(6) #define zmm7 zmm(7) #define zmm8 zmm(8) #define zmm9 zmm(9) #define zmm10 zmm(10) #define zmm11 zmm(11) #define zmm12 zmm(12) #define zmm13 zmm(13) #define zmm14 zmm(14) #define zmm15 zmm(15) #define zmm16 zmm(16) #define zmm17 zmm(17) #define zmm18 zmm(18) #define zmm19 zmm(19) #define zmm20 zmm(20) #define zmm21 zmm(21) #define zmm22 zmm(22) #define zmm23 zmm(23) #define zmm24 zmm(24) #define zmm25 zmm(25) #define zmm26 zmm(26) #define zmm27 zmm(27) #define zmm28 zmm(28) #define zmm29 zmm(29) #define zmm30 zmm(30) #define zmm31 zmm(31) // Memory access // MEM(rax) -> (%rax) or [rax] // MEM(rax,0x80) -> 0x80(%rax) or [rax + 0x80] // MEM(rax,rsi,4) -> (%rax,%rsi,4) or [rax + rsi*4] // MEM(rax,rsi,4,0x80) -> 0x80(%rax,%rsi,4) or [rax + rsi*4 + 0x80] #define MEM(...) GET_MACRO_(__VA_ARGS__,MEM_4_,MEM_3_,MEM_2_,MEM_1_)(__VA_ARGS__) #define MEM_1TO8(...) MEM(__VA_ARGS__) MASK_(1to8) #define MEM_1TO16(...) MEM(__VA_ARGS__) MASK_(1to16) #define MEM_BCAST(...) MEM(__VA_ARGS__) MASK_(b) #define mem(...) MEM(__VA_ARGS__) #define mem_1to8(...) MEM_1TO8(__VA_ARGS__) #define mem_1to16(...) MEM_1TO16(__VA_ARGS__) #define mem_bcast(...) MEM_BCAST(__VA_ARGS__) #define VAR_1TO8(...) VAR(__VA_ARGS__) MASK_(1to8) #define VAR_1TO16(...) VAR(__VA_ARGS__) MASK_(1to16) #define VAR_BCAST(...) VAR(__VA_ARGS__) MASK_(b) #define var_1to8(...) VAR_1TO8(__VA_ARGS__) #define var_1to16(...) VAR_1TO16(__VA_ARGS__) #define var_bcast(...) VAR_BCAST(__VA_ARGS__) // Instructions #define INSTR_(name,...) GET_MACRO_(__VA_ARGS__,INSTR_4_,INSTR_3_,INSTR_2_, \ INSTR_1_,INSTR_0_)(name,__VA_ARGS__) // Jumps #define JC(_0) JMP_(jc, _0) #define JB(_0) JC(_0) #define JNAE(_0) JC(_0) #define JNC(_0) JMP_(jnc, _0) #define JNB(_0) JNC(_0) #define JAE(_0) JNC(_0) #define jc(_0) JC(_0) #define jb(_0) JB(_0) #define jnae(_0) JNAE(_0) #define jnc(_0) JNC(_0) #define jnb(_0) JNB(_0) #define jae(_0) JAE(_0) #define JO(_0) JMP_(jo, _0) #define JNO(_0) JMP_(jno, _0) #define jo(_0) JO(_0) #define jno(_0) JNO(_0) #define JP(_0) JMP_(jp, _0) #define JPE(_0) JP(_0) #define JNP(_0) JMP_(jnp, _0) #define JPO(_0) JNP(_0) #define jp(_0) JP(_0) #define jpe(_0) JPE(_0) #define jnp(_0) JNP(_0) #define jpo(_0) JPO(_0) #define JS(_0) JMP_(js, _0) #define JNS(_0) JMP_(jns, _0) #define js(_0) JS(_0) #define jns(_0) JNS(_0) #define JA(_0) JMP_(ja, _0) #define JNBE(_0) JA(_0) #define JNA(_0) JMP_(jna, _0) #define JBE(_0) JNA(_0) #define ja(_0) JA(_0) #define jnbe(_0) JNBE(_0) #define jna(_0) JNA(_0) #define jbe(_0) JBE(_0) #define JL(_0) JMP_(jl, _0) #define JNGE(_0) JL(_0) #define JNL(_0) JMP_(jnl, _0) #define JGE(_0) JNL(_0) #define jl(_0) JL(_0) #define jnge(_0) JNGE(_0) #define jnl(_0) JNL(_0) #define jge(_0) JGE(_0) #define JG(_0) JMP_(jg, _0) #define JNLE(_0) JG(_0) #define JNG(_0) JMP_(jng, _0) #define JLE(_0) JNG(_0) #define jg(_0) JG(_0) #define jnle(_0) JNLE(_0) #define jng(_0) JNG(_0) #define jle(_0) JLE(_0) #define JE(_0) JMP_(je, _0) #define JZ(_0) JE(_0) #define JNE(_0) JMP_(jne, _0) #define JNZ(_0) JNE(_0) #define je(_0) JE(_0) #define jz(_0) JZ(_0) #define jne(_0) JNE(_0) #define jnz(_0) JNZ(_0) #define JMP(_0) JMP_(jmp, _0) #define jmp(_0) JMP(_0) #define SETE(_0) INSTR_(sete, _0) #define SETZ(_0) SETE(_0) #define sete(_0) SETE(_0) #define setz(_0) SETZ(_0) // Comparisons #define CMP(_0, _1) INSTR_(cmp, _0, _1) #define TEST(_0, _1) INSTR_(test, _0, _1) #define cmp(_0, _1) CMP(_0, _1) #define test(_0, _1) TEST(_0, _1) // Integer math #define AND(_0, _1) INSTR_(and, _0, _1) #define OR(_0, _1) INSTR_(or, _0, _1) #define XOR(_0, _1) INSTR_(xor, _0, _1) #define ADD(_0, _1) INSTR_(add, _0, _1) #define SUB(_0, _1) INSTR_(sub, _0, _1) #define IMUL(_0, _1) INSTR_(imul, _0, _1) #define SAL(...) INSTR_(sal, __VA_ARGS__) #define SAR(...) INSTR_(sar, __VA_ARGS__) #define SHLX(_0, _1, _2) INSTR_(shlx, _0, _1, _2) #define SHRX(_0, _1, _2) INSTR_(shrx, _0, _1, _2) #define RORX(_0, _1, _2) INSTR_(rorx, _0, _1, _2) #define DEC(_0) INSTR_(dec, _0) #define INC(_0) INSTR_(inc, _0) #define and(_0, _1) AND(_0, _1) #define or(_0, _1) OR(_0, _1) #define xor(_0, _1) XOR(_0, _1) #define add(_0, _1) ADD(_0, _1) #define sub(_0, _1) SUB(_0, _1) #define imul(_0, _1) IMUL(_0, _1) #define sal(...) SAL(__VA_ARGS__) #define sar(...) SAR(__VA_ARGS__) #define shlx(_0, _1, _2) SHLX(_0, _1, _2) #define shrx(_0, _1, _2) SHRX(_0, _1, _2) #define rorx(_0, _1, _2) RORX(_0, _1, _2) #define dec(_0) DEC(_0) #define inc(_0) INC(_0) // Memory access #define LEA(_0, _1) INSTR_(lea, _0, _1) #define MOV(_0, _1) INSTR_(mov, _0, _1) #define MOVD(_0, _1) INSTR_(movd, _0, _1) #define MOVL(_0, _1) INSTR_(movl, _0, _1) #define MOVQ(_0, _1) INSTR_(movq, _0, _1) #define CMOVA(_0, _1) INSTR_(cmova, _0, _1) #define CMOVAE(_0, _1) INSTR_(cmovae, _0, _1) #define CMOVB(_0, _1) INSTR_(cmovb, _0, _1) #define CMOVBE(_0, _1) INSTR_(cmovbe, _0, _1) #define CMOVC(_0, _1) INSTR_(cmovc, _0, _1) #define CMOVP(_0, _1) INSTR_(cmovp, _0, _1) #define CMOVO(_0, _1) INSTR_(cmovo, _0, _1) #define CMOVS(_0, _1) INSTR_(cmovs, _0, _1) #define CMOVE(_0, _1) INSTR_(cmove, _0, _1) #define CMOVZ(_0, _1) INSTR_(cmovz, _0, _1) #define CMOVG(_0, _1) INSTR_(cmovg, _0, _1) #define CMOVGE(_0, _1) INSTR_(cmovge, _0, _1) #define CMOVL(_0, _1) INSTR_(cmovl, _0, _1) #define CMOVLE(_0, _1) INSTR_(cmovle, _0, _1) #define CMOVNA(_0, _1) INSTR_(cmovna, _0, _1) #define CMOVNAE(_0, _1) INSTR_(cmovnae, _0, _1) #define CMOVNB(_0, _1) INSTR_(cmovnb, _0, _1) #define CMOVNBE(_0, _1) INSTR_(cmovnbe, _0, _1) #define CMOVNC(_0, _1) INSTR_(cmovnc, _0, _1) #define CMOVNP(_0, _1) INSTR_(cmovnp, _0, _1) #define CMOVNO(_0, _1) INSTR_(cmovno, _0, _1) #define CMOVNS(_0, _1) INSTR_(cmovns, _0, _1) #define CMOVNE(_0, _1) INSTR_(cmovne, _0, _1) #define CMOVNZ(_0, _1) INSTR_(cmovnz, _0, _1) #define CMOVNG(_0, _1) INSTR_(cmovng, _0, _1) #define CMOVNGE(_0, _1) INSTR_(cmovnge, _0, _1) #define CMOVNL(_0, _1) INSTR_(cmovnl, _0, _1) #define CMOVNLE(_0, _1) INSTR_(cmovnle, _0, _1) #define lea(_0, _1) LEA(_0, _1) #define mov(_0, _1) MOV(_0, _1) #define movd(_0, _1) MOVD(_0, _1) #define movl(_0, _1) MOVL(_0, _1) #define movq(_0, _1) MOVQ(_0, _1) #define cmova(_0, _1) CMOVA(_0, _1) #define cmovae(_0, _1) CMOVAE(_0, _1) #define cmovb(_0, _1) CMOVB(_0, _1) #define cmovbe(_0, _1) CMOVBE(_0, _1) #define cmovc(_0, _1) CMOVC(_0, _1) #define cmovp(_0, _1) CMOVP(_0, _1) #define cmovo(_0, _1) CMOVO(_0, _1) #define cmovs(_0, _1) CMOVS(_0, _1) #define cmove(_0, _1) CMOVE(_0, _1) #define cmovz(_0, _1) CMOVZ(_0, _1) #define cmovg(_0, _1) CMOVG(_0, _1) #define cmovge(_0, _1) CMOVGE(_0, _1) #define cmovl(_0, _1) CMOVL(_0, _1) #define cmovle(_0, _1) CMOVLE(_0, _1) #define cmovna(_0, _1) CMOVNA(_0, _1) #define cmovnae(_0, _1) CMOVNAE(_0, _1) #define cmovnb(_0, _1) CMOVNB(_0, _1) #define cmovnbe(_0, _1) CMOVNBE(_0, _1) #define cmovnc(_0, _1) CMOVNC(_0, _1) #define cmovnp(_0, _1) CMOVNP(_0, _1) #define cmovno(_0, _1) CMOVNO(_0, _1) #define cmovns(_0, _1) CMOVNS(_0, _1) #define cmovne(_0, _1) CMOVNE(_0, _1) #define cmovnz(_0, _1) CMOVNZ(_0, _1) #define cmovng(_0, _1) CMOVNG(_0, _1) #define cmovnge(_0, _1) CMOVNGE(_0, _1) #define cmovnl(_0, _1) CMOVNL(_0, _1) #define cmovnle(_0, _1) CMOVNLE(_0, _1) // Vector moves #define MOVSS(_0, _1) INSTR_(movss, _0, _1) #define MOVSD(_0, _1) INSTR_(movsd, _0, _1) #define MOVAPS(_0, _1) INSTR_(movaps, _0, _1) #define MOVAPD(_0, _1) INSTR_(movaps, _0, _1) //use movaps because it is shorter #define MOVDDUP(_0, _1) INSTR_(movddup, _0, _1) #define MOVLPS(_0, _1) INSTR_(movlps, _0, _1) #define MOVHPS(_0, _1) INSTR_(movhps, _0, _1) #define MOVLPD(_0, _1) INSTR_(movlpd, _0, _1) #define MOVHPD(_0, _1) INSTR_(movhpd, _0, _1) #define movss(_0, _1) MOVSS(_0, _1) #define movsd(_0, _1) MOVSD(_0, _1) #define movaps(_0, _1) MOVAPS(_0, _1) #define movapd(_0, _1) MOVAPD(_0, _1) #define movddup(_0, _1) MOVDDUP(_0, _1) #define movlps(_0, _1) MOVLPS(_0, _1) #define movhps(_0, _1) MOVHPS(_0, _1) #define movlpd(_0, _1) MOVLPD(_0, _1) #define movhpd(_0, _1) MOVHPD(_0, _1) #define VMOVDDUP(_0, _1) INSTR_(vmovddup, _0, _1) #define VMOVSLDUP(_0, _1) INSTR_(vmovsldup, _0, _1) #define VMOVSHDUP(_0, _1) INSTR_(vmovshdup, _0, _1) #define VMOVD(_0, _1) INSTR_(vmovd, _0, _1) #define VMOVQ(_0, _1) INSTR_(vmovq, _0, _1) #define VMOVSS(_0, _1) INSTR_(vmovss, _0, _1) #define VMOVSD(_0, _1) INSTR_(vmovsd, _0, _1) #define VMOVAPS(_0, _1) INSTR_(vmovaps, _0, _1) #define VMOVUPS(_0, _1) INSTR_(vmovups, _0, _1) #define VMOVAPD(_0, _1) INSTR_(vmovapd, _0, _1) #define VMOVUPD(_0, _1) INSTR_(vmovupd, _0, _1) #define VMOVLPS(...) INSTR_(vmovlps, __VA_ARGS__) #define VMOVHPS(...) INSTR_(vmovhps, __VA_ARGS__) #define VMOVLPD(...) INSTR_(vmovlpd, __VA_ARGS__) #define VMOVHPD(...) INSTR_(vmovhpd, __VA_ARGS__) #define VMOVDQA(_0, _1) INSTR_(vmovdqa, _0, _1) #define VMOVDQA32(_0, _1) INSTR_(vmovdqa32, _0, _1) #define VMOVDQA64(_0, _1) INSTR_(vmovdqa64, _0, _1) #define VBROADCASTSS(_0, _1) INSTR_(vbroadcastss, _0, _1) #define VBROADCASTSD(_0, _1) INSTR_(vbroadcastsd, _0, _1) #define VPBROADCASTD(_0, _1) INSTR_(vpbroadcastd, _0, _1) #define VPBROADCASTQ(_0, _1) INSTR_(vpbroadcastq, _0, _1) #define VBROADCASTF128(_0, _1) INSTR_(vbroadcastf128, _0, _1) #define VBROADCASTF64X4(_0, _1) INSTR_(vbroadcastf64x4, _0, _1) #define VGATHERDPS(...) INSTR_(vgatherdps, __VA_ARGS__) #define VSCATTERDPS(_0, _1) INSTR_(vscatterdps, _0, _1) #define VGATHERDPD(...) INSTR_(vgatherdpd, __VA_ARGS__) #define VSCATTERDPD(_0, _1) INSTR_(vscatterdpd, _0, _1) #define VGATHERQPS(...) INSTR_(vgatherqps, __VA_ARGS__) #define VSCATTERQPS(_0, _1) INSTR_(vscatterqps, _0, _1) #define VGATHERQPD(...) INSTR_(vgatherqpd, __VA_ARGS__) #define VSCATTERQPD(_0, _1) INSTR_(vscatterqpd, _0, _1) #define vmovddup(_0, _1) VMOVDDUP(_0, _1) #define vmovsldup(_0, _1) VMOVSLDUP(_0, _1) #define vmovshdup(_0, _1) VMOVSHDUP(_0, _1) #define vmovd(_0, _1) VMOVD(_0, _1) #define vmovq(_0, _1) VMOVQ(_0, _1) #define vmovss(_0, _1) VMOVSS(_0, _1) #define vmovsd(_0, _1) VMOVSD(_0, _1) #define vmovaps(_0, _1) VMOVAPS(_0, _1) #define vmovups(_0, _1) VMOVUPS(_0, _1) #define vmovapd(_0, _1) VMOVAPD(_0, _1) #define vmovupd(_0, _1) VMOVUPD(_0, _1) #define vmovlps(...) VMOVLPS(__VA_ARGS__) #define vmovhps(...) VMOVHPS(__VA_ARGS__) #define vmovlpd(...) VMOVLPD(__VA_ARGS__) #define vmovhpd(...) VMOVHPD(__VA_ARGS__) #define vmovdqa(_0, _1) VMOVDQA(_0, _1) #define vmovdqa32(_0, _1) VMOVDQA32(_0, _1) #define vmovdqa64(_0, _1) VMOVDQA64(_0, _1) #define vbroadcastss(_0, _1) VBROADCASTSS(_0, _1) #define vbroadcastsd(_0, _1) VBROADCASTSD(_0, _1) #define vpbroadcastd(_0, _1) VPBROADCASTD(_0, _1) #define vpbroadcastq(_0, _1) VPBROADCASTQ(_0, _1) #define vbroadcastf128(_0, _1) VBROADCASTF128(_0, _1) #define vbroadcastf64x4(_0, _1) VBROADCASTF64X4(_0, _1) #define vgatherdps(...) VGATHERDPS(__VA_ARGS__) #define vscatterdps(_0, _1) VSCATTERDPS(_0, _1) #define vgatherdpd(...) VGATHERDPD(__VA_ARGS__) #define vscatterdpd(_0, _1) VSCATTERDPD(_0, _1) #define vgatherqps(...) VGATHERQPS(__VA_ARGS__) #define vscatterqps(_0, _1) VSCATTERQPS(_0, _1) #define vgatherqpd(...) VGATHERQPD(__VA_ARGS__) #define vscatterqpd(_0, _1) VSCATTERQPD(_0, _1) // Vector comparisons #define VPCMPEQB(_0, _1, _2) INSTR_(vpcmpeqb, _0, _1, _2) #define VPCMPEQW(_0, _1, _2) INSTR_(vpcmpeqw, _0, _1, _2) #define VPCMPEQD(_0, _1, _2) INSTR_(vpcmpeqd, _0, _1, _2) #define vpcmpeqb(_0, _1, _2) VPCMPEQB(_0, _1, _2) #define vpcmpeqw(_0, _1, _2) VPCMPEQW(_0, _1, _2) #define vpcmpeqd(_0, _1, _2) VPCMPEQD(_0, _1, _2) // Vector integer math #define VPADDB(_0, _1, _2) INSTR_(vpaddb, _0, _1, _2) #define VPADDW(_0, _1, _2) INSTR_(vpaddw, _0, _1, _2) #define VPADDD(_0, _1, _2) INSTR_(vpaddd, _0, _1, _2) #define VPADDQ(_0, _1, _2) INSTR_(vpaddq, _0, _1, _2) #define vpaddb(_0, _1, _2) VPADDB(_0, _1, _2) #define vpaddw(_0, _1, _2) VPADDW(_0, _1, _2) #define vpaddd(_0, _1, _2) VPADDD(_0, _1, _2) #define vpaddq(_0, _1, _2) VPADDQ(_0, _1, _2) // Vector math #define ADDPS(_0, _1) INSTR_(addps, _0, _1) #define ADDPD(_0, _1) INSTR_(addpd, _0, _1) #define SUBPS(_0, _1) INSTR_(subps, _0, _1) #define SUBPD(_0, _1) INSTR_(subpd, _0, _1) #define MULPS(_0, _1) INSTR_(mulps, _0, _1) #define MULPD(_0, _1) INSTR_(mulpd, _0, _1) #define DIVPS(_0, _1) INSTR_(divps, _0, _1) #define DIVPD(_0, _1) INSTR_(divpd, _0, _1) #define XORPS(_0, _1) INSTR_(xorps, _0, _1) #define XORPD(_0, _1) INSTR_(xorpd, _0, _1) #define UCOMISS(_0, _1) INSTR_(ucomiss, _0, _1) #define UCOMISD(_0, _1) INSTR_(ucomisd, _0, _1) #define COMISS(_0, _1) INSTR_(comiss, _0, _1) #define COMISD(_0, _1) INSTR_(comisd, _0, _1) #define addps(_0, _1) ADDPS(_0, _1) #define addpd(_0, _1) ADDPD(_0, _1) #define subps(_0, _1) SUBPS(_0, _1) #define subpd(_0, _1) SUBPD(_0, _1) #define mulps(_0, _1) MULPS(_0, _1) #define mulpd(_0, _1) MULPD(_0, _1) #define divps(_0, _1) DIVPS(_0, _1) #define divpd(_0, _1) DIVPD(_0, _1) #define xorps(_0, _1) XORPS(_0, _1) #define xorpd(_0, _1) XORPD(_0, _1) #define ucomiss(_0, _1) UCOMISS(_0, _1) #define ucomisd(_0, _1) UCOMISD(_0, _1) #define cmoiss(_0, _1) COMISS(_0, _1) #define comisd(_0, _1) COMISD(_0, _1) #define VADDSUBPS(_0, _1, _2) INSTR_(vaddsubps, _0, _1, _2) #define VADDSUBPD(_0, _1, _2) INSTR_(vaddsubpd, _0, _1, _2) #define VHADDPD(_0, _1, _2) INSTR_(vhaddpd, _0, _1, _2) #define VHADDPS(_0, _1, _2) INSTR_(vhaddps, _0, _1, _2) #define VHSUBPD(_0, _1, _2) INSTR_(vhsubpd, _0, _1, _2) #define VHSUBPS(_0, _1, _2) INSTR_(vhsubps, _0, _1, _2) #define VADDPS(_0, _1, _2) INSTR_(vaddps, _0, _1, _2) #define VADDPD(_0, _1, _2) INSTR_(vaddpd, _0, _1, _2) #define VSUBPS(_0, _1, _2) INSTR_(vsubps, _0, _1, _2) #define VSUBPD(_0, _1, _2) INSTR_(vsubpd, _0, _1, _2) #define VMULSS(_0, _1, _2) INSTR_(vmulss, _0, _1, _2) #define VMULSD(_0, _1, _2) INSTR_(vmulsd, _0, _1, _2) #define VMULPS(_0, _1, _2) INSTR_(vmulps, _0, _1, _2) #define VMULPD(_0, _1, _2) INSTR_(vmulpd, _0, _1, _2) #define VDIVSS(_0, _1, _2) INSTR_(vdivss, _0, _1, _2) #define VDIVSD(_0, _1, _2) INSTR_(vdivsd, _0, _1, _2) #define VDIVPS(_0, _1, _2) INSTR_(vdivps, _0, _1, _2) #define VDIVPD(_0, _1, _2) INSTR_(vdivpd, _0, _1, _2) #define VPMULLD(_0, _1, _2) INSTR_(vpmulld, _0, _1, _2) #define VPMULLQ(_0, _1, _2) INSTR_(vpmullq, _0, _1, _2) #define VPADDD(_0, _1, _2) INSTR_(vpaddd, _0, _1, _2) #define VPSLLD(_0, _1, _2) INSTR_(vpslld, _0, _1, _2) #define VXORPS(_0, _1, _2) INSTR_(vxorps, _0, _1, _2) #define VXORPD(_0, _1, _2) INSTR_(vxorpd, _0, _1, _2) #define VPXORD(_0, _1, _2) INSTR_(vpxord, _0, _1, _2) #define VUCOMISS(_0, _1) INSTR_(vucomiss, _0, _1) #define VUCOMISD(_0, _1) INSTR_(vucomisd, _0, _1) #define VCOMISS(_0, _1) INSTR_(vcomiss, _0, _1) #define VCOMISD(_0, _1) INSTR_(vcomisd, _0, _1) #define VFMADD132SS(_0, _1, _2) INSTR_(vfmadd132ss, _0, _1, _2) #define VFMADD213SS(_0, _1, _2) INSTR_(vfmadd213ss, _0, _1, _2) #define VFMADD231SS(_0, _1, _2) INSTR_(vfmadd231ss, _0, _1, _2) #define VFMADD132SD(_0, _1, _2) INSTR_(vfmadd132sd, _0, _1, _2) #define VFMADD213SD(_0, _1, _2) INSTR_(vfmadd213sd, _0, _1, _2) #define VFMADD231SD(_0, _1, _2) INSTR_(vfmadd231sd, _0, _1, _2) #define VFMADD132PS(_0, _1, _2) INSTR_(vfmadd132ps, _0, _1, _2) #define VFMADD213PS(_0, _1, _2) INSTR_(vfmadd213ps, _0, _1, _2) #define VFMADD231PS(_0, _1, _2) INSTR_(vfmadd231ps, _0, _1, _2) #define VFMADD132PD(_0, _1, _2) INSTR_(vfmadd132pd, _0, _1, _2) #define VFMADD213PD(_0, _1, _2) INSTR_(vfmadd213pd, _0, _1, _2) #define VFMADD231PD(_0, _1, _2) INSTR_(vfmadd231pd, _0, _1, _2) #define VFMSUB132SS(_0, _1, _2) INSTR_(vfmsub132ss, _0, _1, _2) #define VFMSUB213SS(_0, _1, _2) INSTR_(vfmsub213ss, _0, _1, _2) #define VFMSUB231SS(_0, _1, _2) INSTR_(vfmsub231ss, _0, _1, _2) #define VFMSUB132SD(_0, _1, _2) INSTR_(vfmsub132sd, _0, _1, _2) #define VFMSUB213SD(_0, _1, _2) INSTR_(vfmsub213sd, _0, _1, _2) #define VFMSUB231SD(_0, _1, _2) INSTR_(vfmsub231sd, _0, _1, _2) #define VFMSUB132PS(_0, _1, _2) INSTR_(vfmsub132ps, _0, _1, _2) #define VFMSUB213PS(_0, _1, _2) INSTR_(vfmsub213ps, _0, _1, _2) #define VFMSUB231PS(_0, _1, _2) INSTR_(vfmsub231ps, _0, _1, _2) #define VFMSUB132PD(_0, _1, _2) INSTR_(vfmsub132pd, _0, _1, _2) #define VFMSUB213PD(_0, _1, _2) INSTR_(vfmsub213pd, _0, _1, _2) #define VFMSUB231PD(_0, _1, _2) INSTR_(vfmsub231pd, _0, _1, _2) #define VFNMADD132SS(_0, _1, _2) INSTR_(vfnmadd132ss, _0, _1, _2) #define VFNMADD213SS(_0, _1, _2) INSTR_(vfnmadd213ss, _0, _1, _2) #define VFNMADD231SS(_0, _1, _2) INSTR_(vfnmadd231ss, _0, _1, _2) #define VFNMADD132SD(_0, _1, _2) INSTR_(vfnmadd132sd, _0, _1, _2) #define VFNMADD213SD(_0, _1, _2) INSTR_(vfnmadd213sd, _0, _1, _2) #define VFNMADD231SD(_0, _1, _2) INSTR_(vfnmadd231sd, _0, _1, _2) #define VFNMADD132PS(_0, _1, _2) INSTR_(vfnmadd132ps, _0, _1, _2) #define VFNMADD213PS(_0, _1, _2) INSTR_(vfnmadd213ps, _0, _1, _2) #define VFNMADD231PS(_0, _1, _2) INSTR_(vfnmadd231ps, _0, _1, _2) #define VFNMADD132PD(_0, _1, _2) INSTR_(vfnmadd132pd, _0, _1, _2) #define VFNMADD213PD(_0, _1, _2) INSTR_(vfnmadd213pd, _0, _1, _2) #define VFNMADD231PD(_0, _1, _2) INSTR_(vfnmadd231pd, _0, _1, _2) #define VFNMSUB132SS(_0, _1, _2) INSTR_(vfnmsub132ss, _0, _1, _2) #define VFNMSUB213SS(_0, _1, _2) INSTR_(vfnmsub213ss, _0, _1, _2) #define VFNMSUB231SS(_0, _1, _2) INSTR_(vfnmsub231ss, _0, _1, _2) #define VFNMSUB132SD(_0, _1, _2) INSTR_(vfnmsub132sd, _0, _1, _2) #define VFNMSUB213SD(_0, _1, _2) INSTR_(vfnmsub213sd, _0, _1, _2) #define VFNMSUB231SD(_0, _1, _2) INSTR_(vfnmsub231sd, _0, _1, _2) #define VFNMSUB132PS(_0, _1, _2) INSTR_(vfnmsub132ps, _0, _1, _2) #define VFNMSUB213PS(_0, _1, _2) INSTR_(vfnmsub213ps, _0, _1, _2) #define VFNMSUB231PS(_0, _1, _2) INSTR_(vfnmsub231ps, _0, _1, _2) #define VFNMSUB132PD(_0, _1, _2) INSTR_(vfnmsub132pd, _0, _1, _2) #define VFNMSUB213PD(_0, _1, _2) INSTR_(vfnmsub213pd, _0, _1, _2) #define VFNMSUB231PD(_0, _1, _2) INSTR_(vfnmsub231pd, _0, _1, _2) #define VFMADDSUB132SS(_0, _1, _2) INSTR_(vfmaddsub132ss, _0, _1, _2) #define VFMADDSUB213SS(_0, _1, _2) INSTR_(vfmaddsub213ss, _0, _1, _2) #define VFMADDSUB231SS(_0, _1, _2) INSTR_(vfmaddsub231ss, _0, _1, _2) #define VFMADDSUB132SD(_0, _1, _2) INSTR_(vfmaddsub132sd, _0, _1, _2) #define VFMADDSUB213SD(_0, _1, _2) INSTR_(vfmaddsub213sd, _0, _1, _2) #define VFMADDSUB231SD(_0, _1, _2) INSTR_(vfmaddsub231sd, _0, _1, _2) #define VFMADDSUB132PS(_0, _1, _2) INSTR_(vfmaddsub132ps, _0, _1, _2) #define VFMADDSUB213PS(_0, _1, _2) INSTR_(vfmaddsub213ps, _0, _1, _2) #define VFMADDSUB231PS(_0, _1, _2) INSTR_(vfmaddsub231ps, _0, _1, _2) #define VFMADDSUB132PD(_0, _1, _2) INSTR_(vfmaddsub132pd, _0, _1, _2) #define VFMADDSUB213PD(_0, _1, _2) INSTR_(vfmaddsub213pd, _0, _1, _2) #define VFMADDSUB231PD(_0, _1, _2) INSTR_(vfmaddsub231pd, _0, _1, _2) #define VFMSUBADD132SS(_0, _1, _2) INSTR_(vfmsubadd132ss, _0, _1, _2) #define VFMSUBADD213SS(_0, _1, _2) INSTR_(vfmsubadd213ss, _0, _1, _2) #define VFMSUBADD231SS(_0, _1, _2) INSTR_(vfmsubadd231ss, _0, _1, _2) #define VFMSUBADD132SD(_0, _1, _2) INSTR_(vfmsubadd132sd, _0, _1, _2) #define VFMSUBADD213SD(_0, _1, _2) INSTR_(vfmsubadd213sd, _0, _1, _2) #define VFMSUBADD231SD(_0, _1, _2) INSTR_(vfmsubadd231sd, _0, _1, _2) #define VFMSUBADD132PS(_0, _1, _2) INSTR_(vfmsubadd132ps, _0, _1, _2) #define VFMSUBADD213PS(_0, _1, _2) INSTR_(vfmsubadd213ps, _0, _1, _2) #define VFMSUBADD231PS(_0, _1, _2) INSTR_(vfmsubadd231ps, _0, _1, _2) #define VFMSUBADD132PD(_0, _1, _2) INSTR_(vfmsubadd132pd, _0, _1, _2) #define VFMSUBADD213PD(_0, _1, _2) INSTR_(vfmsubadd213pd, _0, _1, _2) #define VFMSUBADD231PD(_0, _1, _2) INSTR_(vfmsubadd231pd, _0, _1, _2) #define VFMADDSS(_0, _1, _2, _3) INSTR_(vfmaddss, _0, _1, _2, _3) #define VFMADDSD(_0, _1, _2, _3) INSTR_(vfmaddsd, _0, _1, _2, _3) #define VFMADDPS(_0, _1, _2, _3) INSTR_(vfmaddps, _0, _1, _2, _3) #define VFMADDPD(_0, _1, _2, _3) INSTR_(vfmaddpd, _0, _1, _2, _3) #define VFMSUBSS(_0, _1, _2, _3) INSTR_(vfmsubss, _0, _1, _2, _3) #define VFMSUBSD(_0, _1, _2, _3) INSTR_(vfmsubsd, _0, _1, _2, _3) #define VFMSUBPS(_0, _1, _2, _3) INSTR_(vfmsubps, _0, _1, _2, _3) #define VFMSUBPD(_0, _1, _2, _3) INSTR_(vfmsubpd, _0, _1, _2, _3) #define VFNMADDSS(_0, _1, _2, _3) INSTR_(vfnmaddss, _0, _1, _2, _3) #define VFNMADDSD(_0, _1, _2, _3) INSTR_(vfnmaddsd, _0, _1, _2, _3) #define VFNMADDPS(_0, _1, _2, _3) INSTR_(vfnmaddps, _0, _1, _2, _3) #define VFNMADDPD(_0, _1, _2, _3) INSTR_(vfnmaddpd, _0, _1, _2, _3) #define VFNMSUBSS(_0, _1, _2, _3) INSTR_(vfnmsubss, _0, _1, _2, _3) #define VFNMSUBSD(_0, _1, _2, _3) INSTR_(vfnmsubsd, _0, _1, _2, _3) #define VFNMSUBPS(_0, _1, _2, _3) INSTR_(vfnmsubps, _0, _1, _2, _3) #define VFNMSUBPD(_0, _1, _2, _3) INSTR_(vfnmsubpd, _0, _1, _2, _3) #define VFMADDSUBSS(_0, _1, _2, _3) INSTR_(vfmaddsubss, _0, _1, _2, _3) #define VFMADDSUBSD(_0, _1, _2, _3) INSTR_(vfmaddsubsd, _0, _1, _2, _3) #define VFMADDSUBPS(_0, _1, _2, _3) INSTR_(vfmaddsubps, _0, _1, _2, _3) #define VFMADDSUBPD(_0, _1, _2, _3) INSTR_(vfmaddsubpd, _0, _1, _2, _3) #define VFMSUBADDSS(_0, _1, _2, _3) INSTR_(vfmsubaddss, _0, _1, _2, _3) #define VFMSUBADDSD(_0, _1, _2, _3) INSTR_(vfmsubaddsd, _0, _1, _2, _3) #define VFMSUBADDPS(_0, _1, _2, _3) INSTR_(vfmsubaddps, _0, _1, _2, _3) #define VFMSUBADDPD(_0, _1, _2, _3) INSTR_(vfmsubaddpd, _0, _1, _2, _3) #define V4FMADDSS(_0, _1, _2) INSTR_(v4fmaddss, _0, _1, _2) #define V4FMADDPS(_0, _1, _2) INSTR_(v4fmaddps, _0, _1, _2) #define V4FNMADDSS(_0, _1, _2) INSTR_(v4fnmaddss, _0, _1, _2) #define V4FNMADDPS(_0, _1, _2) INSTR_(v4fnmaddps, _0, _1, _2) #define vaddsubps(_0, _1, _2) VADDSUBPS(_0, _1, _2) #define vaddsubpd(_0, _1, _2) VADDSUBPD(_0, _1, _2) #define vhaddpd(_0, _1, _2) VHADDPD(_0, _1, _2) #define vhaddps(_0, _1, _2) VHADDPS(_0, _1, _2) #define vhsubpd(_0, _1, _2) VHSUBPD(_0, _1, _2) #define vhsubps(_0, _1, _2) VHSUBPS(_0, _1, _2) #define vaddps(_0, _1, _2) VADDPS(_0, _1, _2) #define vaddpd(_0, _1, _2) VADDPD(_0, _1, _2) #define vsubps(_0, _1, _2) VSUBPS(_0, _1, _2) #define vsubpd(_0, _1, _2) VSUBPD(_0, _1, _2) #define vmulss(_0, _1, _2) VMULSS(_0, _1, _2) #define vmulps(_0, _1, _2) VMULPS(_0, _1, _2) #define vmulsd(_0, _1, _2) VMULSD(_0, _1, _2) #define vmulpd(_0, _1, _2) VMULPD(_0, _1, _2) #define vdivss(_0, _1, _2) VDIVSS(_0, _1, _2) #define vdivps(_0, _1, _2) VDIVPS(_0, _1, _2) #define vdivsd(_0, _1, _2) VDIVSD(_0, _1, _2) #define vdivpd(_0, _1, _2) VDIVPD(_0, _1, _2) #define vpmulld(_0, _1, _2) VPMULLD(_0, _1, _2) #define vpmullq(_0, _1, _2) VPMULLQ(_0, _1, _2) #define vpaddd(_0, _1, _2) VPADDD(_0, _1, _2) #define vpslld(_0, _1, _2) VPSLLD(_0, _1, _2) #define vxorps(_0, _1, _2) VXORPS(_0, _1, _2) #define vxorpd(_0, _1, _2) VXORPD(_0, _1, _2) #define vpxord(_0, _1, _2) VPXORD(_0, _1, _2) #define vucomiss(_0, _1) VUCOMISS(_0, _1) #define vucomisd(_0, _1) VUCOMISD(_0, _1) #define vcomiss(_0, _1) VCOMISS(_0, _1) #define vcomisd(_0, _1) VCOMISD(_0, _1) #define vfmadd132ss(_0, _1, _2) VFMADD132SS(_0, _1, _2) #define vfmadd213ss(_0, _1, _2) VFMADD213SS(_0, _1, _2) #define vfmadd231ss(_0, _1, _2) VFMADD231SS(_0, _1, _2) #define vfmadd132sd(_0, _1, _2) VFMADD132SD(_0, _1, _2) #define vfmadd213sd(_0, _1, _2) VFMADD213SD(_0, _1, _2) #define vfmadd231sd(_0, _1, _2) VFMADD231SD(_0, _1, _2) #define vfmadd132ps(_0, _1, _2) VFMADD132PS(_0, _1, _2) #define vfmadd213ps(_0, _1, _2) VFMADD213PS(_0, _1, _2) #define vfmadd231ps(_0, _1, _2) VFMADD231PS(_0, _1, _2) #define vfmadd132pd(_0, _1, _2) VFMADD132PD(_0, _1, _2) #define vfmadd213pd(_0, _1, _2) VFMADD213PD(_0, _1, _2) #define vfmadd231pd(_0, _1, _2) VFMADD231PD(_0, _1, _2) #define vfmadd132ss(_0, _1, _2) VFMADD132SS(_0, _1, _2) #define vfmsub213ss(_0, _1, _2) VFMSUB213SS(_0, _1, _2) #define vfmsub231ss(_0, _1, _2) VFMSUB231SS(_0, _1, _2) #define vfmsub132sd(_0, _1, _2) VFMSUB132SD(_0, _1, _2) #define vfmsub213sd(_0, _1, _2) VFMSUB213SD(_0, _1, _2) #define vfmsub231sd(_0, _1, _2) VFMSUB231SD(_0, _1, _2) #define vfmsub132ps(_0, _1, _2) VFMSUB132PS(_0, _1, _2) #define vfmsub213ps(_0, _1, _2) VFMSUB213PS(_0, _1, _2) #define vfmsub231ps(_0, _1, _2) VFMSUB231PS(_0, _1, _2) #define vfmsub132pd(_0, _1, _2) VFMSUB132PD(_0, _1, _2) #define vfmsub213pd(_0, _1, _2) VFMSUB213PD(_0, _1, _2) #define vfmsub231pd(_0, _1, _2) VFMSUB231PD(_0, _1, _2) #define vfnmadd132ss(_0, _1, _2) VFNMADD132SS(_0, _1, _2) #define vfnmadd213ss(_0, _1, _2) VFNMADD213SS(_0, _1, _2) #define vfnmadd231ss(_0, _1, _2) VFNMADD231SS(_0, _1, _2) #define vfnmadd132sd(_0, _1, _2) VFNMADD132SD(_0, _1, _2) #define vfnmadd213sd(_0, _1, _2) VFNMADD213SD(_0, _1, _2) #define vfnmadd231sd(_0, _1, _2) VFNMADD231SD(_0, _1, _2) #define vfnmadd132ps(_0, _1, _2) VFNMADD132PS(_0, _1, _2) #define vfnmadd213ps(_0, _1, _2) VFNMADD213PS(_0, _1, _2) #define vfnmadd231ps(_0, _1, _2) VFNMADD231PS(_0, _1, _2) #define vfnmadd132pd(_0, _1, _2) VFNMADD132PD(_0, _1, _2) #define vfnmadd213pd(_0, _1, _2) VFNMADD213PD(_0, _1, _2) #define vfnmadd231pd(_0, _1, _2) VFNMADD231PD(_0, _1, _2) #define vfnmadd132ss(_0, _1, _2) VFNMADD132SS(_0, _1, _2) #define vfnmsub213ss(_0, _1, _2) VFNMSUB213SS(_0, _1, _2) #define vfnmsub231ss(_0, _1, _2) VFNMSUB231SS(_0, _1, _2) #define vfnmsub132sd(_0, _1, _2) VFNMSUB132SD(_0, _1, _2) #define vfnmsub213sd(_0, _1, _2) VFNMSUB213SD(_0, _1, _2) #define vfnmsub231sd(_0, _1, _2) VFNMSUB231SD(_0, _1, _2) #define vfnmsub132ps(_0, _1, _2) VFNMSUB132PS(_0, _1, _2) #define vfnmsub213ps(_0, _1, _2) VFNMSUB213PS(_0, _1, _2) #define vfnmsub231ps(_0, _1, _2) VFNMSUB231PS(_0, _1, _2) #define vfnmsub132pd(_0, _1, _2) VFNMSUB132PD(_0, _1, _2) #define vfnmsub213pd(_0, _1, _2) VFNMSUB213PD(_0, _1, _2) #define vfnmsub231pd(_0, _1, _2) VFNMSUB231PD(_0, _1, _2) #define vfmaddsub132ss(_0, _1, _2) VFMADDSUB132SS(_0, _1, _2) #define vfmaddsub213ss(_0, _1, _2) VFMADDSUB213SS(_0, _1, _2) #define vfmaddsub231ss(_0, _1, _2) VFMADDSUB231SS(_0, _1, _2) #define vfmaddsub132sd(_0, _1, _2) VFMADDSUB132SD(_0, _1, _2) #define vfmaddsub213sd(_0, _1, _2) VFMADDSUB213SD(_0, _1, _2) #define vfmaddsub231sd(_0, _1, _2) VFMADDSUB231SD(_0, _1, _2) #define vfmaddsub132ps(_0, _1, _2) VFMADDSUB132PS(_0, _1, _2) #define vfmaddsub213ps(_0, _1, _2) VFMADDSUB213PS(_0, _1, _2) #define vfmaddsub231ps(_0, _1, _2) VFMADDSUB231PS(_0, _1, _2) #define vfmaddsub132pd(_0, _1, _2) VFMADDSUB132PD(_0, _1, _2) #define vfmaddsub213pd(_0, _1, _2) VFMADDSUB213PD(_0, _1, _2) #define vfmaddsub231pd(_0, _1, _2) VFMADDSUB231PD(_0, _1, _2) #define vfmsubadd132ss(_0, _1, _2) VFMSUBADD132SS(_0, _1, _2) #define vfmsubadd213ss(_0, _1, _2) VFMSUBADD213SS(_0, _1, _2) #define vfmsubadd231ss(_0, _1, _2) VFMSUBADD231SS(_0, _1, _2) #define vfmsubadd132sd(_0, _1, _2) VFMSUBADD132SD(_0, _1, _2) #define vfmsubadd213sd(_0, _1, _2) VFMSUBADD213SD(_0, _1, _2) #define vfmsubadd231sd(_0, _1, _2) VFMSUBADD231SD(_0, _1, _2) #define vfmsubadd132ps(_0, _1, _2) VFMSUBADD132PS(_0, _1, _2) #define vfmsubadd213ps(_0, _1, _2) VFMSUBADD213PS(_0, _1, _2) #define vfmsubadd231ps(_0, _1, _2) VFMSUBADD231PS(_0, _1, _2) #define vfmsubadd132pd(_0, _1, _2) VFMSUBADD132PD(_0, _1, _2) #define vfmsubadd213pd(_0, _1, _2) VFMSUBADD213PD(_0, _1, _2) #define vfmsubadd231pd(_0, _1, _2) VFMSUBADD231PD(_0, _1, _2) #define vfmaddss(_0, _1, _2, _3) VFMADDSS(_0, _1, _2, _3) #define vfmaddsd(_0, _1, _2, _3) VFMADDSD(_0, _1, _2, _3) #define vfmaddps(_0, _1, _2, _3) VFMADDPS(_0, _1, _2, _3) #define vfmaddpd(_0, _1, _2, _3) VFMADDPD(_0, _1, _2, _3) #define vfmsubss(_0, _1, _2, _3) VFMSUBSS(_0, _1, _2, _3) #define vfmsubsd(_0, _1, _2, _3) VFMSUBSD(_0, _1, _2, _3) #define vfmsubps(_0, _1, _2, _3) VFMSUBPS(_0, _1, _2, _3) #define vfmsubpd(_0, _1, _2, _3) VFMSUBPD(_0, _1, _2, _3) #define vfnmaddss(_0, _1, _2, _3) VFNMADDSS(_0, _1, _2, _3) #define vfnmaddsd(_0, _1, _2, _3) VFNMADDSD(_0, _1, _2, _3) #define vfnmaddps(_0, _1, _2, _3) VFNMADDPS(_0, _1, _2, _3) #define vfnmaddpd(_0, _1, _2, _3) VFNMADDPD(_0, _1, _2, _3) #define vfnmsubss(_0, _1, _2, _3) VFNMSUBSS(_0, _1, _2, _3) #define vfnmsubsd(_0, _1, _2, _3) VFNMSUBSD(_0, _1, _2, _3) #define vfnmsubps(_0, _1, _2, _3) VFNMSUBPS(_0, _1, _2, _3) #define vfnmsubpd(_0, _1, _2, _3) VFNMSUBPD(_0, _1, _2, _3) #define vfmaddsubss(_0, _1, _2, _3) VFMADDSUBSS(_0, _1, _2, _3) #define vfmaddsubsd(_0, _1, _2, _3) VFMADDSUBSD(_0, _1, _2, _3) #define vfmaddsubps(_0, _1, _2, _3) VFMADDSUBPS(_0, _1, _2, _3) #define vfmaddsubpd(_0, _1, _2, _3) VFMADDSUBPD(_0, _1, _2, _3) #define vfmsubaddss(_0, _1, _2, _3) VFMSUBADDSS(_0, _1, _2, _3) #define vfmsubaddsd(_0, _1, _2, _3) VFMSUBADDSD(_0, _1, _2, _3) #define vfmsubaddps(_0, _1, _2, _3) VFMSUBADDPS(_0, _1, _2, _3) #define vfmsubaddpd(_0, _1, _2, _3) VFMSUBADDPD(_0, _1, _2, _3) #define v4fmaddss(_0, _1, _2) V4FMADDSS(_0, _1, _2) #define v4fmaddps(_0, _1, _2) V4FMADDPS(_0, _1, _2) #define v4fnmaddss(_0, _1, _2) V4FNMADDSS(_0, _1, _2) #define v4fnmaddps(_0, _1, _2) V4FNMADDPS(_0, _1, _2) // Conversions #define CVTSS2SD(_0, _1) INSTR_(cvtss2sd, _0, _1) #define CVTSD2SS(_0, _1) INSTR_(cvtsd2ss, _0, _1) #define CVTPS2PD(_0, _1) INSTR_(cvtps2pd, _0, _1) #define CVTPD2PS(_0, _1) INSTR_(cvtpd2ps, _0, _1) #define cvtss2sd(_0, _1) CVTSS2SD(_0, _1) #define cvtsd2ss(_0, _1) CVTSD2SS(_0, _1) #define cvtps2pd(_0, _1) CVTPS2PD(_0, _1) #define cvtpd2ps(_0, _1) CVTPD2PS(_0, _1) #define VCVTSS2SD(_0, _1) INSTR_(vcvtss2sd, _0, _1) #define VCVTSD2SS(_0, _1) INSTR_(vcvtsd2ss, _0, _1) #define VCVTPS2PD(_0, _1) INSTR_(vcvtps2pd, _0, _1) #define VCVTPD2PS(_0, _1) INSTR_(vcvtpd2ps, _0, _1) #define vcvtss2sd(_0, _1) VCVTSS2SD(_0, _1) #define vcvtsd2ss(_0, _1) VCVTSD2SS(_0, _1) #define vcvtps2pd(_0, _1) VCVTPS2PD(_0, _1) #define vcvtpd2ps(_0, _1) VCVTPD2PS(_0, _1) // Vector shuffles #define PSHUFD(_0, _1, _2) INSTR_(pshufd, _0, _1, _2) #define SHUFPS(_0, _1, _2) INSTR_(shufps, _0, _1, _2) #define SHUFPD(_0, _1, _2) INSTR_(shufpd, _0, _1, _2) #define UNPCKLPS(_0, _1) INSTR_(unpcklps, _0, _1) #define UNPCKHPS(_0, _1) INSTR_(unpckhps, _0, _1) #define UNPCKLPD(_0, _1) INSTR_(unpcklpd, _0, _1) #define UNPCKHPD(_0, _1) INSTR_(unpckhpd, _0, _1) #define pshufd(_0, _1, _2) PSHUFD(_0, _1, _2) #define shufps(_0, _1, _2) SHUFPS(_0, _1, _2) #define shufpd(_0, _1, _2) SHUFPD(_0, _1, _2) #define unpcklps(_0, _1) UNPCKLPS(_0, _1) #define unpckhps(_0, _1) UNPCKHPS(_0, _1) #define unpcklpd(_0, _1) UNPCKLPD(_0, _1) #define unpckhpd(_0, _1) UNPCKHPD(_0, _1) #define VSHUFPS(_0, _1, _2, _3) INSTR_(vshufps, _0, _1, _2, _3) #define VSHUFPD(_0, _1, _2, _3) INSTR_(vshufpd, _0, _1, _2, _3) #define VPERMILPS(_0, _1, _2) INSTR_(vpermilps, _0, _1, _2) #define VPERMILPD(_0, _1, _2) INSTR_(vpermilpd, _0, _1, _2) #define VPERM2F128(_0, _1, _2, _3) INSTR_(vperm2f128, _0, _1, _2, _3) #define VPERMPD(_0, _1, _2) INSTR_(vpermpd, _0, _1, _2) #define VUNPCKLPS(_0, _1, _2) INSTR_(vunpcklps, _0, _1, _2) #define VUNPCKHPS(_0, _1, _2) INSTR_(vunpckhps, _0, _1, _2) #define VUNPCKLPD(_0, _1, _2) INSTR_(vunpcklpd, _0, _1, _2) #define VUNPCKHPD(_0, _1, _2) INSTR_(vunpckhpd, _0, _1, _2) #define VSHUFF32X4(_0, _1, _2, _3) INSTR_(vshuff32x4, _0, _1, _2, _3) #define VSHUFF64X2(_0, _1, _2, _3) INSTR_(vshuff64x2, _0, _1, _2, _3) #define VINSERTF128(_0, _1, _2, _3) INSTR_(vinsertf128, _0, _1, _2, _3) #define VINSERTF32X4(_0, _1, _2, _3) INSTR_(vinsertf32x4, _0, _1, _2, _3) #define VINSERTF32X8(_0, _1, _2, _3) INSTR_(vinsertf32x8, _0, _1, _2, _3) #define VINSERTF64X2(_0, _1, _2, _3) INSTR_(vinsertf64x2, _0, _1, _2, _3) #define VINSERTF64X4(_0, _1, _2, _3) INSTR_(vinsertf64x4, _0, _1, _2, _3) #define VEXTRACTF128(_0, _1, _2) INSTR_(vextractf128, _0, _1, _2) #define VEXTRACTF32X4(_0, _1, _2) INSTR_(vextractf32x4, _0, _1, _2) #define VEXTRACTF32X8(_0, _1, _2) INSTR_(vextractf32x8, _0, _1, _2) #define VEXTRACTF64X2(_0, _1, _2) INSTR_(vextractf64x4, _0, _1, _2) #define VEXTRACTF64X4(_0, _1, _2) INSTR_(vextractf64x4, _0, _1, _2) #define VBLENDPS(_0, _1, _2, _3) INSTR_(vblendps, _0, _1, _2, _3) #define VBLENDPD(_0, _1, _2, _3) INSTR_(vblendpd, _0, _1, _2, _3) #define VBLENDMPS(_0, _1, _2) INSTR_(vblendmps, _0, _1, _2) #define VBLENDMPD(_0, _1, _2) INSTR_(vblendmpd, _0, _1, _2) #define vshufps(_0, _1, _2, _3) VSHUFPS(_0, _1, _2, _3) #define vshufpd(_0, _1, _2, _3) VSHUFPD(_0, _1, _2, _3) #define vpermilps(_0, _1, _2) VPERMILPS(_0, _1, _2) #define vpermilpd(_0, _1, _2) VPERMILPD(_0, _1, _2) #define vperm2f128(_0, _1, _2, _3) VPERM2F128(_0, _1, _2, _3) #define vpermpd(_0, _1, _2) VPERMPD(_0, _1, _2) #define vunpcklps(_0, _1, _2) VUNPCKLPS(_0, _1, _2) #define vunpckhps(_0, _1, _2) VUNPCKHPS(_0, _1, _2) #define vunpcklpd(_0, _1, _2) VUNPCKLPD(_0, _1, _2) #define vunpckhpd(_0, _1, _2) VUNPCKHPD(_0, _1, _2) #define vshuff32x4(_0, _1, _2, _3) VSHUFF32x4(_0, _1, _2, _3) #define vshuff64x2(_0, _1, _2, _3) VSHUFF64x2(_0, _1, _2, _3) #define vinsertf128(_0, _1, _2, _3) VINSERTF128(_0, _1, _2, _3) #define vinsertf32x4(_0, _1, _2, _3) VINSERTF32x4(_0, _1, _2, _3) #define vinsertf32x8(_0, _1, _2, _3) VINSERTF32x8(_0, _1, _2, _3) #define vinsertf64x2(_0, _1, _2, _3) VINSERTF64x2(_0, _1, _2, _3) #define vinsertf64x4(_0, _1, _2, _3) VINSERTF64x4(_0, _1, _2, _3) #define vextractf128(_0, _1, _2) VEXTRACTF128(_0, _1, _2) #define vextractf32x4(_0, _1, _2) VEXTRACTF32x4(_0, _1, _2) #define vextractf32x8(_0, _1, _2) VEXTRACTF32x8(_0, _1, _2) #define vextractf64x2(_0, _1, _2) VEXTRACTF64x2(_0, _1, _2) #define vextractf64x4(_0, _1, _2) VEXTRACTF64x4(_0, _1, _2) #define vblendps(_0, _1, _2, _3) VBLENDPS(_0, _1, _2, _3) #define vblendpd(_0, _1, _2, _3) VBLENDPD(_0, _1, _2, _3) #define vblendmps(_0, _1, _2) VBLENDMSD(_0, _1, _2) #define vblendmpd(_0, _1, _2) VBLENDMPD(_0, _1, _2) // Prefetches #define PREFETCH(_0, _1) INSTR_(prefetcht##_0, _1) #define PREFETCHW0(_0) INSTR_(prefetchw, _0) #define PREFETCHW1(_0) INSTR_(prefetchwt1, _0) #define VGATHERPFDPS(_0, _1) INSTR_(vgatherpf##_0##dps, _1) #define VSCATTERPFDPS(_0, _1) INSTR_(vscatterpf##_0##dps, _1) #define VGATHERPFDPD(_0, _1) INSTR_(vgatherpf##_0##dpd, _1) #define VSCATTERPFDPD(_0, _1) INSTR_(vscatterpf##_0##dpd, _1) #define VGATHERPFQPS(_0, _1) INSTR_(vgatherpf##_0##qps, _1) #define VSCATTERPFQPS(_0, _1) INSTR_(vscatterpf##_0##qps, _1) #define VGATHERPFQPD(_0, _1) INSTR_(vgatherpf##_0##qpd, _1) #define VSCATTERPFQPD(_0, _1) INSTR_(vscatterpf##_0##qpd, _1) #define prefetch(_0, _1) PREFETCH(_0, _1) #define prefetchw0(_0) PREFETCHW0(_0) #define prefetchw1(_0) PREFETCHW1(_0) #define vgatherpfdps(_0, _1) VGATHERPFDPS(_0, _1) #define vscatterpfdps(_0, _1) VSCATTERPFDPS(_0, _1) #define vgatherpfdpd(_0, _1) VGATHERPFDPD(_0, _1) #define vscatterpfdpd(_0, _1) VSCATTERPFDPD(_0, _1) #define vgatherpfqps(_0, _1) VGATHERPFQPS(_0, _1) #define vscatterpfqps(_0, _1) VSCATTERPFQPS(_0, _1) #define vgatherpfqpd(_0, _1) VGATHERPFQPD(_0, _1) #define vscatterpfqpd(_0, _1) VSCATTERPFQPD(_0, _1) // Mask operations #ifdef __MIC__ #define KMOVW(_0, _1) INSTR_(kmov, _0, _1) #define JKNZD(_0, _1) INSTR_(jknzd, _0, _1) #else #define KMOVW(_0, _1) INSTR_(kmovw, _0, _1) #define JKNZD(_0, _1) INSTR_(kortestw, _0, _0) INSTR_(jnz, _1) #endif #define KXNORW(_0, _1, _2) INSTR_(kxnorw, _0, _1, _2) #define KSHIFTRW(_0, _1, _2) INSTR_(kshiftrw, _0, _1, _2) #define kmovw(_0, _1) KMOVW(_0, _1) #define jknzd(_0, _1) JKNZD(_0, _1) #define kxnorw(_0, _1, _2) KXNORW(_0, _1, _2) #define kshiftrw(_0, _1, _2) KSHIFTRW(_0, _1, _2) // Other #define RDTSC() INSTR_(rdtsc) #define VZEROALL() INSTR_(vzeroall) #define VZEROUPPER() INSTR_(vzeroupper) #define rdtsc() RDTSC() #define vzeroall() VZEROALL() #define vzeroupper() VZEROUPPER() #endif blis-0.9.0/frame/include/bli_xapi_undef.h000066400000000000000000000045711422157504600203240ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // This file un-defines macros used to allow the _oapi.c and _tapi.c files to // produce object and typed APIs that omit or contain expert parameters. // Un-define all macros that allow the source code to determine which interface // (basic or expert) we are compiling. #undef BLIS_OAPI_BASIC #undef BLIS_OAPI_EXPERT #undef BLIS_TAPI_BASIC #undef BLIS_TAPI_EXPERT // Un-define the macro to omit or add the function name suffix (in function // definitions). #undef EX_SUF // Un-define the macro to omit or add expert arguments from function signatures // and prototypes. #undef BLIS_OAPI_EX_PARAMS #undef BLIS_TAPI_EX_PARAMS // Un-define the macro to omit or add local expert variables. #undef BLIS_OAPI_EX_DECLS #undef BLIS_TAPI_EX_DECLS blis-0.9.0/frame/include/blis.h000066400000000000000000000125601422157504600163020ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2016, Hewlett Packard Enterprise Development LP Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_H #define BLIS_H // Allow C++ users to include this header file in their source code. However, // we make the extern "C" conditional on whether we're using a C++ compiler, // since regular C compilers don't understand the extern "C" construct. #ifdef __cplusplus extern "C" { #endif // NOTE: PLEASE DON'T CHANGE THE ORDER IN WHICH HEADERS ARE INCLUDED UNLESS // YOU ARE SURE THAT IT DOESN'T BREAK INTER-HEADER MACRO DEPENDENCIES. // -- configure definitions -- // NOTE: bli_config.h header must be included before any BLIS header. // It is bootstrapped by ./configure and does not depend on later // headers. Moreover, these configuration variables are necessary to change // some default behaviors (e.g. disable OS-detection in bli_system.h in case // of --disable-system). #include "bli_config.h" // -- System and language-related headers -- // NOTE: bli_system.h header must be included before bli_config_macro_defs.h. #include "bli_system.h" #include "bli_lang_defs.h" // -- configure default definitions -- #include "bli_config_macro_defs.h" // -- Common BLIS definitions -- #include "bli_type_defs.h" #include "bli_macro_defs.h" // -- pragma definitions -- #include "bli_pragma_macro_defs.h" // -- Threading definitions -- #include "bli_thread.h" #include "bli_pthread.h" // -- Constant definitions -- #include "bli_extern_defs.h" // -- BLIS architecture/kernel definitions -- #include "bli_l1v_ker_prot.h" #include "bli_l1f_ker_prot.h" #include "bli_l1m_ker_prot.h" #include "bli_l3_ukr_prot.h" #include "bli_l3_sup_ker_prot.h" #include "bli_arch_config_pre.h" #include "bli_arch_config.h" #include "bli_kernel_macro_defs.h" // -- Base operation prototypes -- #include "bli_init.h" #include "bli_malloc.h" #include "bli_const.h" #include "bli_obj.h" #include "bli_obj_scalar.h" #include "bli_blksz.h" #include "bli_func.h" #include "bli_mbool.h" #include "bli_cntx.h" #include "bli_rntm.h" #include "bli_gks.h" #include "bli_ind.h" #include "bli_pba.h" #include "bli_pool.h" #include "bli_array.h" #include "bli_apool.h" #include "bli_sba.h" #include "bli_memsys.h" #include "bli_mem.h" #include "bli_part.h" #include "bli_prune.h" #include "bli_query.h" #include "bli_auxinfo.h" #include "bli_param_map.h" #include "bli_clock.h" #include "bli_check.h" #include "bli_error.h" #include "bli_f2c.h" #include "bli_machval.h" #include "bli_getopt.h" #include "bli_opid.h" #include "bli_cntl.h" #include "bli_env.h" #include "bli_pack.h" #include "bli_info.h" #include "bli_arch.h" #include "bli_cpuid.h" #include "bli_string.h" #include "bli_setgetijm.h" #include "bli_setgetijv.h" #include "bli_setri.h" #include "bli_castm.h" #include "bli_castnzm.h" #include "bli_castv.h" #include "bli_projm.h" #include "bli_projv.h" // -- Level-0 operations -- #include "bli_l0.h" // -- Level-1v operations -- #include "bli_l1v.h" // -- Level-1d operations -- #include "bli_l1d.h" // -- Level-1f operations -- #include "bli_l1f.h" // -- Level-1m operations -- #include "bli_l1m.h" // -- Level-2 operations -- #include "bli_l2.h" // -- Level-3 operations -- #include "bli_l3.h" // -- Utility operations -- #include "bli_util.h" // -- addon definitions -- // NOTE: These definitions should not be included much earlier since an addon // may wish to utilize other types and definitions provided by BLIS. #include "bli_addon.h" // -- sandbox implementation -- #include "bli_sbox.h" // -- BLAS compatibility layer -- #include "bli_blas.h" // -- CBLAS compatibility layer -- #include "bli_cblas.h" // -- Windows definitions #include "bli_winsys.h" // End extern "C" construct block. #ifdef __cplusplus } #endif #endif blis-0.9.0/frame/include/level0/000077500000000000000000000000001422157504600163635ustar00rootroot00000000000000blis-0.9.0/frame/include/level0/1e/000077500000000000000000000000001422157504600166705ustar00rootroot00000000000000blis-0.9.0/frame/include/level0/1e/bli_copy1es.h000066400000000000000000000063221422157504600212550ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_COPY1ES_H #define BLIS_COPY1ES_H // copy1es // Notes: // - The first char encodes the type of x. // - The second char encodes the type of y. #define bli_sscopy1es( a, bri, bir ) {} #define bli_dscopy1es( a, bri, bir ) {} #define bli_cscopy1es( a, bri, bir ) {} #define bli_zscopy1es( a, bri, bir ) {} #define bli_sdcopy1es( a, bri, bir ) {} #define bli_ddcopy1es( a, bri, bir ) {} #define bli_cdcopy1es( a, bri, bir ) {} #define bli_zdcopy1es( a, bri, bir ) {} #define bli_sccopy1es( a, bri, bir ) {} #define bli_dccopy1es( a, bri, bir ) {} #define bli_cccopy1es( a, bri, bir ) \ { \ bli_cccopyris( bli_creal(a), bli_cimag(a), bli_creal(bri), bli_cimag(bri) ); \ bli_cccopyris( -bli_cimag(a), bli_creal(a), bli_creal(bir), bli_cimag(bir) ); \ } #define bli_zccopy1es( a, bri, bir ) \ { \ bli_zccopyris( bli_zreal(a), bli_zimag(a), bli_creal(bri), bli_cimag(bri) ); \ bli_zccopyris( -bli_zimag(a), bli_zreal(a), bli_creal(bir), bli_cimag(bir) ); \ } #define bli_szcopy1es( a, bri, bir ) {} #define bli_dzcopy1es( a, bri, bir ) {} #define bli_czcopy1es( a, bri, bir ) \ { \ bli_czcopyris( bli_creal(a), bli_cimag(a), bli_zreal(bri), bli_zimag(bri) ); \ bli_czcopyris( -bli_cimag(a), bli_creal(a), bli_zreal(bir), bli_zimag(bir) ); \ } #define bli_zzcopy1es( a, bri, bir ) \ { \ bli_zzcopyris( bli_zreal(a), bli_zimag(a), bli_zreal(bri), bli_zimag(bri) ); \ bli_zzcopyris( -bli_zimag(a), bli_zreal(a), bli_zreal(bir), bli_zimag(bir) ); \ } #define bli_ccopy1es( a, bri, bir ) bli_cccopy1es( a, bri, bir ) #define bli_zcopy1es( a, bri, bir ) bli_zzcopy1es( a, bri, bir ) #endif blis-0.9.0/frame/include/level0/1e/bli_copyj1es.h000066400000000000000000000063511422157504600214310ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_COPYJ1ES_H #define BLIS_COPYJ1ES_H // copyj1es // Notes: // - The first char encodes the type of x. // - The second char encodes the type of y. #define bli_sscopyj1es( a, bri, bir ) {} #define bli_dscopyj1es( a, bri, bir ) {} #define bli_cscopyj1es( a, bri, bir ) {} #define bli_zscopyj1es( a, bri, bir ) {} #define bli_sdcopyj1es( a, bri, bir ) {} #define bli_ddcopyj1es( a, bri, bir ) {} #define bli_cdcopyj1es( a, bri, bir ) {} #define bli_zdcopyj1es( a, bri, bir ) {} #define bli_sccopyj1es( a, bri, bir ) {} #define bli_dccopyj1es( a, bri, bir ) {} #define bli_cccopyj1es( a, bri, bir ) \ { \ bli_cccopyris( bli_creal(a), -bli_cimag(a), bli_creal(bri), bli_cimag(bri) ); \ bli_cccopyris( bli_cimag(a), bli_creal(a), bli_creal(bir), bli_cimag(bir) ); \ } #define bli_zccopyj1es( a, bri, bir ) \ { \ bli_zccopyris( bli_zreal(a), -bli_zimag(a), bli_creal(bri), bli_cimag(bri) ); \ bli_zccopyris( bli_zimag(a), bli_zreal(a), bli_creal(bir), bli_cimag(bir) ); \ } #define bli_szcopyj1es( a, bri, bir ) {} #define bli_dzcopyj1es( a, bri, bir ) {} #define bli_czcopyj1es( a, bri, bir ) \ { \ bli_czcopyris( bli_creal(a), -bli_cimag(a), bli_zreal(bri), bli_zimag(bri) ); \ bli_czcopyris( bli_cimag(a), bli_creal(a), bli_zreal(bir), bli_zimag(bir) ); \ } #define bli_zzcopyj1es( a, bri, bir ) \ { \ bli_zzcopyris( bli_zreal(a), -bli_zimag(a), bli_zreal(bri), bli_zimag(bri) ); \ bli_zzcopyris( bli_zimag(a), bli_zreal(a), bli_zreal(bir), bli_zimag(bir) ); \ } #define bli_ccopyj1es( a, bri, bir ) bli_cccopyj1es( a, bri, bir ) #define bli_zcopyj1es( a, bri, bir ) bli_zzcopyj1es( a, bri, bir ) #endif blis-0.9.0/frame/include/level0/1e/bli_invert1es.h000066400000000000000000000040741422157504600216140ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_INVERT1ES_H #define BLIS_INVERT1ES_H // invert1es #define bli_cinvert1es( bri, bir ) \ { \ bli_cinvertris( bli_creal(bri), bli_cimag(bri) ); \ bli_ccopyris( bli_creal(bri), -bli_cimag(bri), bli_cimag(bir), bli_creal(bir) ); \ } #define bli_zinvert1es( bri, bir ) \ { \ bli_zinvertris( bli_zreal(bri), bli_zimag(bri) ); \ bli_zcopyris( bli_zreal(bri), -bli_zimag(bri), bli_zimag(bir), bli_zreal(bir) ); \ } #endif blis-0.9.0/frame/include/level0/1e/bli_scal1es.h000066400000000000000000000041661422157504600212310ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_SCAL1ES_H #define BLIS_SCAL1ES_H // scal1es #define bli_cscal1es( a, yri, yir ) \ { \ bli_cscalris( bli_creal(a), bli_cimag(a), bli_creal(yri), bli_cimag(yri) ); \ bli_ccopyris( -bli_cimag(yri), bli_creal(yri), bli_creal(yir), bli_cimag(yir) ); \ } #define bli_zscal1es( a, yri, yir ) \ { \ bli_zscalris( bli_zreal(a), bli_zimag(a), bli_zreal(yri), bli_zimag(yri) ); \ bli_zcopyris( -bli_zimag(yri), bli_zreal(yri), bli_zreal(yir), bli_zimag(yir) ); \ } #endif blis-0.9.0/frame/include/level0/1e/bli_scal21es.h000066400000000000000000000246431422157504600213150ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_SCAL21ES_H #define BLIS_SCAL21ES_H // scal21es // Notes: // - The first char encodes the type of a. // - The second char encodes the type of x. // - The third char encodes the type of y. // -- (axy) = (??s) ------------------------------------------------------------ #define bli_sssscal21es( a, x, yri, yir ) {} #define bli_sdsscal21es( a, x, yri, yir ) {} #define bli_scsscal21es( a, x, yri, yir ) {} #define bli_szsscal21es( a, x, yri, yir ) {} #define bli_dssscal21es( a, x, yri, yir ) {} #define bli_ddsscal21es( a, x, yri, yir ) {} #define bli_dcsscal21es( a, x, yri, yir ) {} #define bli_dzsscal21es( a, x, yri, yir ) {} #define bli_cssscal21es( a, x, yri, yir ) {} #define bli_cdsscal21es( a, x, yri, yir ) {} #define bli_ccsscal21es( a, x, yri, yir ) {} #define bli_czsscal21es( a, x, yri, yir ) {} #define bli_zssscal21es( a, x, yri, yir ) {} #define bli_zdsscal21es( a, x, yri, yir ) {} #define bli_zcsscal21es( a, x, yri, yir ) {} #define bli_zzsscal21es( a, x, yri, yir ) {} // -- (axy) = (??d) ------------------------------------------------------------ #define bli_ssdscal21es( a, x, yri, yir ) {} #define bli_sddscal21es( a, x, yri, yir ) {} #define bli_scdscal21es( a, x, yri, yir ) {} #define bli_szdscal21es( a, x, yri, yir ) {} #define bli_dsdscal21es( a, x, yri, yir ) {} #define bli_dddscal21es( a, x, yri, yir ) {} #define bli_dcdscal21es( a, x, yri, yir ) {} #define bli_dzdscal21es( a, x, yri, yir ) {} #define bli_csdscal21es( a, x, yri, yir ) {} #define bli_cddscal21es( a, x, yri, yir ) {} #define bli_ccdscal21es( a, x, yri, yir ) {} #define bli_czdscal21es( a, x, yri, yir ) {} #define bli_zsdscal21es( a, x, yri, yir ) {} #define bli_zddscal21es( a, x, yri, yir ) {} #define bli_zcdscal21es( a, x, yri, yir ) {} #define bli_zzdscal21es( a, x, yri, yir ) {} // -- (axy) = (??c) ------------------------------------------------------------ #define bli_sscscal21es( a, x, yri, yir ) {} #define bli_sdcscal21es( a, x, yri, yir ) {} #define bli_sccscal21es( a, x, yri, yir ) \ { \ bli_cxscal2ris( bli_sreal(a), bli_simag(a), bli_creal(x), bli_cimag(x), bli_zreal(yri), bli_zimag(yri) ); \ bli_cxscal2ris( bli_sreal(a), bli_simag(a), -bli_cimag(x), bli_creal(x), bli_zreal(yir), bli_zimag(yir) ); \ } #define bli_szcscal21es( a, x, yri, yir ) \ { \ bli_cxscal2ris( bli_sreal(a), bli_simag(a), bli_zreal(x), bli_zimag(x), bli_zreal(yri), bli_zimag(yri) ); \ bli_cxscal2ris( bli_sreal(a), bli_simag(a), -bli_zimag(x), bli_zreal(x), bli_zreal(yir), bli_zimag(yir) ); \ } #define bli_dscscal21es( a, x, yri, yir ) {} #define bli_ddcscal21es( a, x, yri, yir ) {} #define bli_dccscal21es( a, x, yri, yir ) \ { \ bli_cxscal2ris( bli_dreal(a), bli_dimag(a), bli_creal(x), bli_cimag(x), bli_zreal(yri), bli_zimag(yri) ); \ bli_cxscal2ris( bli_dreal(a), bli_dimag(a), -bli_cimag(x), bli_creal(x), bli_zreal(yir), bli_zimag(yir) ); \ } #define bli_dzcscal21es( a, x, yri, yir ) \ { \ bli_cxscal2ris( bli_dreal(a), bli_dimag(a), bli_zreal(x), bli_zimag(x), bli_zreal(yri), bli_zimag(yri) ); \ bli_cxscal2ris( bli_dreal(a), bli_dimag(a), -bli_zimag(x), bli_zreal(x), bli_zreal(yir), bli_zimag(yir) ); \ } #define bli_cscscal21es( a, x, yri, yir ) \ { \ bli_cxscal2ris( bli_creal(a), bli_cimag(a), bli_sreal(x), bli_simag(x), bli_zreal(yri), bli_zimag(yri) ); \ bli_cxscal2ris( bli_creal(a), bli_cimag(a), -bli_simag(x), bli_sreal(x), bli_zreal(yir), bli_zimag(yir) ); \ } #define bli_cdcscal21es( a, x, yri, yir ) \ { \ bli_cxscal2ris( bli_creal(a), bli_cimag(a), bli_dreal(x), bli_dimag(x), bli_zreal(yri), bli_zimag(yri) ); \ bli_cxscal2ris( bli_creal(a), bli_cimag(a), -bli_dimag(x), bli_dreal(x), bli_zreal(yir), bli_zimag(yir) ); \ } #define bli_cccscal21es( a, x, yri, yir ) \ { \ bli_cxscal2ris( bli_creal(a), bli_cimag(a), bli_creal(x), bli_cimag(x), bli_zreal(yri), bli_zimag(yri) ); \ bli_cxscal2ris( bli_creal(a), bli_cimag(a), -bli_cimag(x), bli_creal(x), bli_zreal(yir), bli_zimag(yir) ); \ } #define bli_czcscal21es( a, x, yri, yir ) \ { \ bli_cxscal2ris( bli_creal(a), bli_cimag(a), bli_zreal(x), bli_zimag(x), bli_zreal(yri), bli_zimag(yri) ); \ bli_cxscal2ris( bli_creal(a), bli_cimag(a), -bli_zimag(x), bli_zreal(x), bli_zreal(yir), bli_zimag(yir) ); \ } #define bli_zscscal21es( a, x, yri, yir ) \ { \ bli_cxscal2ris( bli_zreal(a), bli_zimag(a), bli_sreal(x), bli_simag(x), bli_zreal(yri), bli_zimag(yri) ); \ bli_cxscal2ris( bli_zreal(a), bli_zimag(a), -bli_simag(x), bli_sreal(x), bli_zreal(yir), bli_zimag(yir) ); \ } #define bli_zdcscal21es( a, x, yri, yir ) \ { \ bli_cxscal2ris( bli_zreal(a), bli_zimag(a), bli_dreal(x), bli_dimag(x), bli_zreal(yri), bli_zimag(yri) ); \ bli_cxscal2ris( bli_zreal(a), bli_zimag(a), -bli_dimag(x), bli_dreal(x), bli_zreal(yir), bli_zimag(yir) ); \ } #define bli_zccscal21es( a, x, yri, yir ) \ { \ bli_cxscal2ris( bli_zreal(a), bli_zimag(a), bli_creal(x), bli_cimag(x), bli_zreal(yri), bli_zimag(yri) ); \ bli_cxscal2ris( bli_zreal(a), bli_zimag(a), -bli_cimag(x), bli_creal(x), bli_zreal(yir), bli_zimag(yir) ); \ } #define bli_zzcscal21es( a, x, yri, yir ) \ { \ bli_cxscal2ris( bli_zreal(a), bli_zimag(a), bli_zreal(x), bli_zimag(x), bli_zreal(yri), bli_zimag(yri) ); \ bli_cxscal2ris( bli_zreal(a), bli_zimag(a), -bli_zimag(x), bli_zreal(x), bli_zreal(yir), bli_zimag(yir) ); \ } // -- (axy) = (??z) ------------------------------------------------------------ #define bli_sszscal21es( a, x, yri, yir ) {} #define bli_sdzscal21es( a, x, yri, yir ) {} #define bli_sczscal21es( a, x, yri, yir ) \ { \ bli_cxscal2ris( bli_sreal(a), bli_simag(a), bli_creal(x), bli_cimag(x), bli_zreal(yri), bli_zimag(yri) ); \ bli_cxscal2ris( bli_sreal(a), bli_simag(a), -bli_cimag(x), bli_creal(x), bli_zreal(yir), bli_zimag(yir) ); \ } #define bli_szzscal21es( a, x, yri, yir ) \ { \ bli_cxscal2ris( bli_sreal(a), bli_simag(a), bli_zreal(x), bli_zimag(x), bli_zreal(yri), bli_zimag(yri) ); \ bli_cxscal2ris( bli_sreal(a), bli_simag(a), -bli_zimag(x), bli_zreal(x), bli_zreal(yir), bli_zimag(yir) ); \ } #define bli_dszscal21es( a, x, yri, yir ) {} #define bli_ddzscal21es( a, x, yri, yir ) {} #define bli_dczscal21es( a, x, yri, yir ) \ { \ bli_cxscal2ris( bli_dreal(a), bli_dimag(a), bli_creal(x), bli_cimag(x), bli_zreal(yri), bli_zimag(yri) ); \ bli_cxscal2ris( bli_dreal(a), bli_dimag(a), -bli_cimag(x), bli_creal(x), bli_zreal(yir), bli_zimag(yir) ); \ } #define bli_dzzscal21es( a, x, yri, yir ) \ { \ bli_cxscal2ris( bli_dreal(a), bli_dimag(a), bli_zreal(x), bli_zimag(x), bli_zreal(yri), bli_zimag(yri) ); \ bli_cxscal2ris( bli_dreal(a), bli_dimag(a), -bli_zimag(x), bli_zreal(x), bli_zreal(yir), bli_zimag(yir) ); \ } #define bli_cszscal21es( a, x, yri, yir ) \ { \ bli_cxscal2ris( bli_creal(a), bli_cimag(a), bli_sreal(x), bli_simag(x), bli_zreal(yri), bli_zimag(yri) ); \ bli_cxscal2ris( bli_creal(a), bli_cimag(a), -bli_simag(x), bli_sreal(x), bli_zreal(yir), bli_zimag(yir) ); \ } #define bli_cdzscal21es( a, x, yri, yir ) \ { \ bli_cxscal2ris( bli_creal(a), bli_cimag(a), bli_dreal(x), bli_dimag(x), bli_zreal(yri), bli_zimag(yri) ); \ bli_cxscal2ris( bli_creal(a), bli_cimag(a), -bli_dimag(x), bli_dreal(x), bli_zreal(yir), bli_zimag(yir) ); \ } #define bli_cczscal21es( a, x, yri, yir ) \ { \ bli_cxscal2ris( bli_creal(a), bli_cimag(a), bli_creal(x), bli_cimag(x), bli_zreal(yri), bli_zimag(yri) ); \ bli_cxscal2ris( bli_creal(a), bli_cimag(a), -bli_cimag(x), bli_creal(x), bli_zreal(yir), bli_zimag(yir) ); \ } #define bli_czzscal21es( a, x, yri, yir ) \ { \ bli_cxscal2ris( bli_creal(a), bli_cimag(a), bli_zreal(x), bli_zimag(x), bli_zreal(yri), bli_zimag(yri) ); \ bli_cxscal2ris( bli_creal(a), bli_cimag(a), -bli_zimag(x), bli_zreal(x), bli_zreal(yir), bli_zimag(yir) ); \ } #define bli_zszscal21es( a, x, yri, yir ) \ { \ bli_cxscal2ris( bli_zreal(a), bli_zimag(a), bli_sreal(x), bli_simag(x), bli_zreal(yri), bli_zimag(yri) ); \ bli_cxscal2ris( bli_zreal(a), bli_zimag(a), -bli_simag(x), bli_sreal(x), bli_zreal(yir), bli_zimag(yir) ); \ } #define bli_zdzscal21es( a, x, yri, yir ) \ { \ bli_cxscal2ris( bli_zreal(a), bli_zimag(a), bli_dreal(x), bli_dimag(x), bli_zreal(yri), bli_zimag(yri) ); \ bli_cxscal2ris( bli_zreal(a), bli_zimag(a), -bli_dimag(x), bli_dreal(x), bli_zreal(yir), bli_zimag(yir) ); \ } #define bli_zczscal21es( a, x, yri, yir ) \ { \ bli_cxscal2ris( bli_zreal(a), bli_zimag(a), bli_creal(x), bli_cimag(x), bli_zreal(yri), bli_zimag(yri) ); \ bli_cxscal2ris( bli_zreal(a), bli_zimag(a), -bli_cimag(x), bli_creal(x), bli_zreal(yir), bli_zimag(yir) ); \ } #define bli_zzzscal21es( a, x, yri, yir ) \ { \ bli_cxscal2ris( bli_zreal(a), bli_zimag(a), bli_zreal(x), bli_zimag(x), bli_zreal(yri), bli_zimag(yri) ); \ bli_cxscal2ris( bli_zreal(a), bli_zimag(a), -bli_zimag(x), bli_zreal(x), bli_zreal(yir), bli_zimag(yir) ); \ } #define bli_cscal21es( a, x, yri, yir ) bli_cccscal21es( a, x, yri, yir ) #define bli_zscal21es( a, x, yri, yir ) bli_zzzscal21es( a, x, yri, yir ) #endif blis-0.9.0/frame/include/level0/1e/bli_scal2j1es.h000066400000000000000000000247521422157504600214700ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_SCAL2J1ES_H #define BLIS_SCAL2J1ES_H // scal2j1es // Notes: // - The first char encodes the type of a. // - The second char encodes the type of x. // - The third char encodes the type of y. // -- (axy) = (??s) ------------------------------------------------------------ #define bli_sssscal2j1es( a, x, yri, yir ) {} #define bli_sdsscal2j1es( a, x, yri, yir ) {} #define bli_scsscal2j1es( a, x, yri, yir ) {} #define bli_szsscal2j1es( a, x, yri, yir ) {} #define bli_dssscal2j1es( a, x, yri, yir ) {} #define bli_ddsscal2j1es( a, x, yri, yir ) {} #define bli_dcsscal2j1es( a, x, yri, yir ) {} #define bli_dzsscal2j1es( a, x, yri, yir ) {} #define bli_cssscal2j1es( a, x, yri, yir ) {} #define bli_cdsscal2j1es( a, x, yri, yir ) {} #define bli_ccsscal2j1es( a, x, yri, yir ) {} #define bli_czsscal2j1es( a, x, yri, yir ) {} #define bli_zssscal2j1es( a, x, yri, yir ) {} #define bli_zdsscal2j1es( a, x, yri, yir ) {} #define bli_zcsscal2j1es( a, x, yri, yir ) {} #define bli_zzsscal2j1es( a, x, yri, yir ) {} // -- (axy) = (??d) ------------------------------------------------------------ #define bli_ssdscal2j1es( a, x, yri, yir ) {} #define bli_sddscal2j1es( a, x, yri, yir ) {} #define bli_scdscal2j1es( a, x, yri, yir ) {} #define bli_szdscal2j1es( a, x, yri, yir ) {} #define bli_dsdscal2j1es( a, x, yri, yir ) {} #define bli_dddscal2j1es( a, x, yri, yir ) {} #define bli_dcdscal2j1es( a, x, yri, yir ) {} #define bli_dzdscal2j1es( a, x, yri, yir ) {} #define bli_csdscal2j1es( a, x, yri, yir ) {} #define bli_cddscal2j1es( a, x, yri, yir ) {} #define bli_ccdscal2j1es( a, x, yri, yir ) {} #define bli_czdscal2j1es( a, x, yri, yir ) {} #define bli_zsdscal2j1es( a, x, yri, yir ) {} #define bli_zddscal2j1es( a, x, yri, yir ) {} #define bli_zcdscal2j1es( a, x, yri, yir ) {} #define bli_zzdscal2j1es( a, x, yri, yir ) {} // -- (axy) = (??c) ------------------------------------------------------------ #define bli_sscscal2j1es( a, x, yri, yir ) {} #define bli_sdcscal2j1es( a, x, yri, yir ) {} #define bli_sccscal2j1es( a, x, yri, yir ) \ { \ bli_cxscal2ris( bli_sreal(a), bli_simag(a), bli_creal(x), -bli_cimag(x), bli_zreal(yri), bli_zimag(yri) ); \ bli_cxscal2ris( bli_sreal(a), bli_simag(a), bli_cimag(x), bli_creal(x), bli_zreal(yir), bli_zimag(yir) ); \ } #define bli_szcscal2j1es( a, x, yri, yir ) \ { \ bli_cxscal2ris( bli_sreal(a), bli_simag(a), bli_zreal(x), -bli_zimag(x), bli_zreal(yri), bli_zimag(yri) ); \ bli_cxscal2ris( bli_sreal(a), bli_simag(a), bli_zimag(x), bli_zreal(x), bli_zreal(yir), bli_zimag(yir) ); \ } #define bli_dscscal2j1es( a, x, yri, yir ) {} #define bli_ddcscal2j1es( a, x, yri, yir ) {} #define bli_dccscal2j1es( a, x, yri, yir ) \ { \ bli_cxscal2ris( bli_dreal(a), bli_dimag(a), bli_creal(x), -bli_cimag(x), bli_zreal(yri), bli_zimag(yri) ); \ bli_cxscal2ris( bli_dreal(a), bli_dimag(a), bli_cimag(x), bli_creal(x), bli_zreal(yir), bli_zimag(yir) ); \ } #define bli_dzcscal2j1es( a, x, yri, yir ) \ { \ bli_cxscal2ris( bli_dreal(a), bli_dimag(a), bli_zreal(x), -bli_zimag(x), bli_zreal(yri), bli_zimag(yri) ); \ bli_cxscal2ris( bli_dreal(a), bli_dimag(a), bli_zimag(x), bli_zreal(x), bli_zreal(yir), bli_zimag(yir) ); \ } #define bli_cscscal2j1es( a, x, yri, yir ) \ { \ bli_cxscal2ris( bli_creal(a), bli_cimag(a), bli_sreal(x), -bli_simag(x), bli_zreal(yri), bli_zimag(yri) ); \ bli_cxscal2ris( bli_creal(a), bli_cimag(a), bli_simag(x), bli_sreal(x), bli_zreal(yir), bli_zimag(yir) ); \ } #define bli_cdcscal2j1es( a, x, yri, yir ) \ { \ bli_cxscal2ris( bli_creal(a), bli_cimag(a), bli_dreal(x), -bli_dimag(x), bli_zreal(yri), bli_zimag(yri) ); \ bli_cxscal2ris( bli_creal(a), bli_cimag(a), bli_dimag(x), bli_dreal(x), bli_zreal(yir), bli_zimag(yir) ); \ } #define bli_cccscal2j1es( a, x, yri, yir ) \ { \ bli_cxscal2ris( bli_creal(a), bli_cimag(a), bli_creal(x), -bli_cimag(x), bli_zreal(yri), bli_zimag(yri) ); \ bli_cxscal2ris( bli_creal(a), bli_cimag(a), bli_cimag(x), bli_creal(x), bli_zreal(yir), bli_zimag(yir) ); \ } #define bli_czcscal2j1es( a, x, yri, yir ) \ { \ bli_cxscal2ris( bli_creal(a), bli_cimag(a), bli_zreal(x), -bli_zimag(x), bli_zreal(yri), bli_zimag(yri) ); \ bli_cxscal2ris( bli_creal(a), bli_cimag(a), bli_zimag(x), bli_zreal(x), bli_zreal(yir), bli_zimag(yir) ); \ } #define bli_zscscal2j1es( a, x, yri, yir ) \ { \ bli_cxscal2ris( bli_zreal(a), bli_zimag(a), bli_sreal(x), -bli_simag(x), bli_zreal(yri), bli_zimag(yri) ); \ bli_cxscal2ris( bli_zreal(a), bli_zimag(a), bli_simag(x), bli_sreal(x), bli_zreal(yir), bli_zimag(yir) ); \ } #define bli_zdcscal2j1es( a, x, yri, yir ) \ { \ bli_cxscal2ris( bli_zreal(a), bli_zimag(a), bli_dreal(x), -bli_dimag(x), bli_zreal(yri), bli_zimag(yri) ); \ bli_cxscal2ris( bli_zreal(a), bli_zimag(a), bli_dimag(x), bli_dreal(x), bli_zreal(yir), bli_zimag(yir) ); \ } #define bli_zccscal2j1es( a, x, yri, yir ) \ { \ bli_cxscal2ris( bli_zreal(a), bli_zimag(a), bli_creal(x), -bli_cimag(x), bli_zreal(yri), bli_zimag(yri) ); \ bli_cxscal2ris( bli_zreal(a), bli_zimag(a), bli_cimag(x), bli_creal(x), bli_zreal(yir), bli_zimag(yir) ); \ } #define bli_zzcscal2j1es( a, x, yri, yir ) \ { \ bli_cxscal2ris( bli_zreal(a), bli_zimag(a), bli_zreal(x), -bli_zimag(x), bli_zreal(yri), bli_zimag(yri) ); \ bli_cxscal2ris( bli_zreal(a), bli_zimag(a), bli_zimag(x), bli_zreal(x), bli_zreal(yir), bli_zimag(yir) ); \ } // -- (axy) = (??z) ------------------------------------------------------------ #define bli_sszscal2j1es( a, x, yri, yir ) {} #define bli_sdzscal2j1es( a, x, yri, yir ) {} #define bli_sczscal2j1es( a, x, yri, yir ) \ { \ bli_cxscal2ris( bli_sreal(a), bli_simag(a), bli_creal(x), -bli_cimag(x), bli_zreal(yri), bli_zimag(yri) ); \ bli_cxscal2ris( bli_sreal(a), bli_simag(a), bli_cimag(x), bli_creal(x), bli_zreal(yir), bli_zimag(yir) ); \ } #define bli_szzscal2j1es( a, x, yri, yir ) \ { \ bli_cxscal2ris( bli_sreal(a), bli_simag(a), bli_zreal(x), -bli_zimag(x), bli_zreal(yri), bli_zimag(yri) ); \ bli_cxscal2ris( bli_sreal(a), bli_simag(a), bli_zimag(x), bli_zreal(x), bli_zreal(yir), bli_zimag(yir) ); \ } #define bli_dszscal2j1es( a, x, yri, yir ) {} #define bli_ddzscal2j1es( a, x, yri, yir ) {} #define bli_dczscal2j1es( a, x, yri, yir ) \ { \ bli_cxscal2ris( bli_dreal(a), bli_dimag(a), bli_creal(x), -bli_cimag(x), bli_zreal(yri), bli_zimag(yri) ); \ bli_cxscal2ris( bli_dreal(a), bli_dimag(a), bli_cimag(x), bli_creal(x), bli_zreal(yir), bli_zimag(yir) ); \ } #define bli_dzzscal2j1es( a, x, yri, yir ) \ { \ bli_cxscal2ris( bli_dreal(a), bli_dimag(a), bli_zreal(x), -bli_zimag(x), bli_zreal(yri), bli_zimag(yri) ); \ bli_cxscal2ris( bli_dreal(a), bli_dimag(a), bli_zimag(x), bli_zreal(x), bli_zreal(yir), bli_zimag(yir) ); \ } #define bli_cszscal2j1es( a, x, yri, yir ) \ { \ bli_cxscal2ris( bli_creal(a), bli_cimag(a), bli_sreal(x), -bli_simag(x), bli_zreal(yri), bli_zimag(yri) ); \ bli_cxscal2ris( bli_creal(a), bli_cimag(a), bli_simag(x), bli_sreal(x), bli_zreal(yir), bli_zimag(yir) ); \ } #define bli_cdzscal2j1es( a, x, yri, yir ) \ { \ bli_cxscal2ris( bli_creal(a), bli_cimag(a), bli_dreal(x), -bli_dimag(x), bli_zreal(yri), bli_zimag(yri) ); \ bli_cxscal2ris( bli_creal(a), bli_cimag(a), bli_dimag(x), bli_dreal(x), bli_zreal(yir), bli_zimag(yir) ); \ } #define bli_cczscal2j1es( a, x, yri, yir ) \ { \ bli_cxscal2ris( bli_creal(a), bli_cimag(a), bli_creal(x), -bli_cimag(x), bli_zreal(yri), bli_zimag(yri) ); \ bli_cxscal2ris( bli_creal(a), bli_cimag(a), bli_cimag(x), bli_creal(x), bli_zreal(yir), bli_zimag(yir) ); \ } #define bli_czzscal2j1es( a, x, yri, yir ) \ { \ bli_cxscal2ris( bli_creal(a), bli_cimag(a), bli_zreal(x), -bli_zimag(x), bli_zreal(yri), bli_zimag(yri) ); \ bli_cxscal2ris( bli_creal(a), bli_cimag(a), bli_zimag(x), bli_zreal(x), bli_zreal(yir), bli_zimag(yir) ); \ } #define bli_zszscal2j1es( a, x, yri, yir ) \ { \ bli_cxscal2ris( bli_zreal(a), bli_zimag(a), bli_sreal(x), -bli_simag(x), bli_zreal(yri), bli_zimag(yri) ); \ bli_cxscal2ris( bli_zreal(a), bli_zimag(a), bli_simag(x), bli_sreal(x), bli_zreal(yir), bli_zimag(yir) ); \ } #define bli_zdzscal2j1es( a, x, yri, yir ) \ { \ bli_cxscal2ris( bli_zreal(a), bli_zimag(a), bli_dreal(x), -bli_dimag(x), bli_zreal(yri), bli_zimag(yri) ); \ bli_cxscal2ris( bli_zreal(a), bli_zimag(a), bli_dimag(x), bli_dreal(x), bli_zreal(yir), bli_zimag(yir) ); \ } #define bli_zczscal2j1es( a, x, yri, yir ) \ { \ bli_cxscal2ris( bli_zreal(a), bli_zimag(a), bli_creal(x), -bli_cimag(x), bli_zreal(yri), bli_zimag(yri) ); \ bli_cxscal2ris( bli_zreal(a), bli_zimag(a), bli_cimag(x), bli_creal(x), bli_zreal(yir), bli_zimag(yir) ); \ } #define bli_zzzscal2j1es( a, x, yri, yir ) \ { \ bli_cxscal2ris( bli_zreal(a), bli_zimag(a), bli_zreal(x), -bli_zimag(x), bli_zreal(yri), bli_zimag(yri) ); \ bli_cxscal2ris( bli_zreal(a), bli_zimag(a), bli_zimag(x), bli_zreal(x), bli_zreal(yir), bli_zimag(yir) ); \ } #define bli_cscal2j1es( a, x, yri, yir ) bli_cccscal2j1es( a, x, yri, yir ) #define bli_zscal2j1es( a, x, yri, yir ) bli_zzzscal2j1es( a, x, yri, yir ) #endif blis-0.9.0/frame/include/level0/1m/000077500000000000000000000000001422157504600167005ustar00rootroot00000000000000blis-0.9.0/frame/include/level0/1m/bli_invert1ms_mxn_diag.h000066400000000000000000000106271422157504600235030ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_INVERT1MS_MXN_DIAG_H #define BLIS_INVERT1MS_MXN_DIAG_H // invert1ms_mxn_diag #define bli_cinvert1ms_mxn_diag( schema, offm, offn, m, n, y, rs_y, cs_y, ld_y ) \ { \ dim_t min_m_n = bli_min( m, n ); \ dim_t i; \ \ /* Handle 1e and 1r separately. */ \ if ( bli_is_1e_packed( schema ) ) \ { \ scomplex* restrict y_off_ri = y + (offm )*rs_y \ + (offn )*cs_y; \ scomplex* restrict y_off_ir = y + (offm )*rs_y \ + (offn )*cs_y + ld_y/2; \ \ for ( i = 0; i < min_m_n; ++i ) \ { \ bli_cinvert1es( *(y_off_ri + i*rs_y + i*cs_y), \ *(y_off_ir + i*rs_y + i*cs_y) ); \ } \ } \ else /* if ( bli_is_1r_packed( schema ) ) */ \ { \ inc_t rs_y2 = rs_y; \ inc_t cs_y2 = cs_y; \ \ /* Scale the non-unit stride by two for the 1r loop, which steps in units of real (not complex) values. */ \ if ( rs_y2 == 1 ) { cs_y2 *= 2; } \ else /* if ( cs_y2 == 1 ) */ { rs_y2 *= 2; } \ \ float* restrict y_cast = ( float* )y; \ float* restrict y_off_r = y_cast + (offm )*rs_y2 \ + (offn )*cs_y2; \ float* restrict y_off_i = y_cast + (offm )*rs_y2 \ + (offn )*cs_y2 + ld_y; \ \ for ( i = 0; i < min_m_n; ++i ) \ { \ bli_cinvert1rs( *(y_off_r + i*rs_y2 + i*cs_y2), \ *(y_off_i + i*rs_y2 + i*cs_y2) ); \ } \ } \ } #define bli_zinvert1ms_mxn_diag( schema, offm, offn, m, n, y, rs_y, cs_y, ld_y ) \ { \ dim_t min_m_n = bli_min( m, n ); \ dim_t i; \ \ /* Handle 1e and 1r separately. */ \ if ( bli_is_1e_packed( schema ) ) \ { \ dcomplex* restrict y_off_ri = y + (offm )*rs_y \ + (offn )*cs_y; \ dcomplex* restrict y_off_ir = y + (offm )*rs_y \ + (offn )*cs_y + ld_y/2; \ \ for ( i = 0; i < min_m_n; ++i ) \ { \ bli_zinvert1es( *(y_off_ri + i*rs_y + i*cs_y), \ *(y_off_ir + i*rs_y + i*cs_y) ); \ } \ } \ else /* if ( bli_is_1r_packed( schema ) ) */ \ { \ inc_t rs_y2 = rs_y; \ inc_t cs_y2 = cs_y; \ \ /* Scale the non-unit stride by two for the 1r loop, which steps in units of real (not complex) values. */ \ if ( rs_y2 == 1 ) { cs_y2 *= 2; } \ else /* if ( cs_y2 == 1 ) */ { rs_y2 *= 2; } \ \ double* restrict y_cast = ( double* )y; \ double* restrict y_off_r = y_cast + (offm )*rs_y2 \ + (offn )*cs_y2; \ double* restrict y_off_i = y_cast + (offm )*rs_y2 \ + (offn )*cs_y2 + ld_y; \ \ for ( i = 0; i < min_m_n; ++i ) \ { \ bli_zinvert1rs( *(y_off_r + i*rs_y2 + i*cs_y2), \ *(y_off_i + i*rs_y2 + i*cs_y2) ); \ } \ } \ } #endif blis-0.9.0/frame/include/level0/1m/bli_scal1ms_mxn.h000066400000000000000000000075461422157504600221400ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_SCAL1MS_MXN_H #define BLIS_SCAL1MS_MXN_H // scal1ms_mxn #define bli_cscal1ms_mxn( schema, m, n, a, y, rs_y, cs_y, ld_y ) \ { \ dim_t i, j; \ \ /* Handle 1e and 1r separately. */ \ if ( bli_is_1e_packed( schema ) ) \ { \ scomplex* restrict y_ri = y; \ scomplex* restrict y_ir = y + ld_y/2; \ \ for ( j = 0; j < n; ++j ) \ for ( i = 0; i < m; ++i ) \ { \ bli_cscal1es( *(a), \ *(y_ri + i*rs_y + j*cs_y), \ *(y_ir + i*rs_y + j*cs_y) ); \ } \ } \ else /* if ( bli_is_1r_packed( schema ) ) */ \ { \ inc_t rs_y2 = rs_y; \ inc_t cs_y2 = cs_y; \ \ /* Scale the non-unit stride by two for the 1r loop, which steps in units of real (not complex) values. */ \ if ( rs_y2 == 1 ) { cs_y2 *= 2; } \ else /* if ( cs_y2 == 1 ) */ { rs_y2 *= 2; } \ \ float* restrict y_cast = ( float* )y; \ float* restrict y_r = y_cast; \ float* restrict y_i = y_cast + ld_y; \ \ for ( j = 0; j < n; ++j ) \ for ( i = 0; i < m; ++i ) \ { \ bli_cscal1rs( *(a), \ *(y_r + i*rs_y2 + j*cs_y2), \ *(y_i + i*rs_y2 + j*cs_y2) ); \ } \ } \ } #define bli_zscal1ms_mxn( schema, m, n, a, y, rs_y, cs_y, ld_y ) \ { \ dim_t i, j; \ \ /* Handle 1e and 1r separately. */ \ if ( bli_is_1e_packed( schema ) ) \ { \ dcomplex* restrict y_ri = y; \ dcomplex* restrict y_ir = y + ld_y/2; \ \ for ( j = 0; j < n; ++j ) \ for ( i = 0; i < m; ++i ) \ { \ bli_zscal1es( *(a), \ *(y_ri + i*rs_y + j*cs_y), \ *(y_ir + i*rs_y + j*cs_y) ); \ } \ } \ else /* if ( bli_is_1r_packed( schema ) ) */ \ { \ inc_t rs_y2 = rs_y; \ inc_t cs_y2 = cs_y; \ \ /* Scale the non-unit stride by two for the 1r loop, which steps in units of real (not complex) values. */ \ if ( rs_y2 == 1 ) { cs_y2 *= 2; } \ else /* if ( cs_y2 == 1 ) */ { rs_y2 *= 2; } \ \ double* restrict y_cast = ( double* )y; \ double* restrict y_r = y_cast; \ double* restrict y_i = y_cast + ld_y; \ \ for ( j = 0; j < n; ++j ) \ for ( i = 0; i < m; ++i ) \ { \ bli_zscal1rs( *(a), \ *(y_r + i*rs_y2 + j*cs_y2), \ *(y_i + i*rs_y2 + j*cs_y2) ); \ } \ } \ } #endif blis-0.9.0/frame/include/level0/1m/bli_scal21ms_mxn.h000066400000000000000000000134551422157504600222160ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_SCAL21MS_MXN_H #define BLIS_SCAL21MS_MXN_H // scal21ms_mxn BLIS_INLINE void bli_cscal21ms_mxn ( const pack_t schema, const conj_t conjx, const dim_t m, const dim_t n, scomplex* restrict alpha, scomplex* restrict x, const inc_t rs_x, const inc_t cs_x, scomplex* restrict y, const inc_t rs_y, const inc_t cs_y, const inc_t ld_y ) { dim_t i, j; /* Handle 1e and 1r separately. */ if ( bli_is_1e_packed( schema ) ) { scomplex* restrict y_ri = y; scomplex* restrict y_ir = y + ld_y/2; if ( bli_is_conj( conjx ) ) { for ( j = 0; j < n; ++j ) for ( i = 0; i < m; ++i ) { bli_cscal2j1es( *(alpha), *(x + i*rs_x + j*cs_x), *(y_ri + i*rs_y + j*cs_y), *(y_ir + i*rs_y + j*cs_y) ); } } else /* if ( bli_is_noconj( conjx ) ) */ { for ( j = 0; j < n; ++j ) for ( i = 0; i < m; ++i ) { bli_cscal21es( *(alpha), *(x + i*rs_x + j*cs_x), *(y_ri + i*rs_y + j*cs_y), *(y_ir + i*rs_y + j*cs_y) ); } } } else /* if ( bli_is_1r_packed( schema ) ) */ { inc_t rs_y2 = rs_y; inc_t cs_y2 = cs_y; /* Scale the non-unit stride by two for the 1r loop, which steps in units of real (not complex) values. */ if ( rs_y2 == 1 ) { cs_y2 *= 2; } else /* if ( cs_y2 == 1 ) */ { rs_y2 *= 2; } float* restrict y_cast = ( float* )y; float* restrict y_r = y_cast; float* restrict y_i = y_cast + ld_y; if ( bli_is_conj( conjx ) ) { for ( j = 0; j < n; ++j ) for ( i = 0; i < m; ++i ) { bli_cscal2j1rs( *(alpha), *(x + i*rs_x + j*cs_x ), *(y_r + i*rs_y2 + j*cs_y2), *(y_i + i*rs_y2 + j*cs_y2) ); } } else /* if ( bli_is_noconj( conjx ) ) */ { for ( j = 0; j < n; ++j ) for ( i = 0; i < m; ++i ) { bli_cscal21rs( *(alpha), *(x + i*rs_x + j*cs_x ), *(y_r + i*rs_y2 + j*cs_y2), *(y_i + i*rs_y2 + j*cs_y2) ); } } } } BLIS_INLINE void bli_zscal21ms_mxn ( const pack_t schema, const conj_t conjx, const dim_t m, const dim_t n, dcomplex* restrict alpha, dcomplex* restrict x, const inc_t rs_x, const inc_t cs_x, dcomplex* restrict y, const inc_t rs_y, const inc_t cs_y, const inc_t ld_y ) { dim_t i, j; /* Handle 1e and 1r separately. */ if ( bli_is_1e_packed( schema ) ) { dcomplex* restrict y_ri = y; dcomplex* restrict y_ir = y + ld_y/2; if ( bli_is_conj( conjx ) ) { for ( j = 0; j < n; ++j ) for ( i = 0; i < m; ++i ) { bli_zscal2j1es( *(alpha), *(x + i*rs_x + j*cs_x), *(y_ri + i*rs_y + j*cs_y), *(y_ir + i*rs_y + j*cs_y) ); } } else /* if ( bli_is_noconj( conjx ) ) */ { for ( j = 0; j < n; ++j ) for ( i = 0; i < m; ++i ) { bli_zscal21es( *(alpha), *(x + i*rs_x + j*cs_x), *(y_ri + i*rs_y + j*cs_y), *(y_ir + i*rs_y + j*cs_y) ); } } } else /* if ( bli_is_1r_packed( schema ) ) */ { inc_t rs_y2 = rs_y; inc_t cs_y2 = cs_y; /* Scale the non-unit stride by two for the 1r loop, which steps in units of real (not complex) values. */ if ( rs_y2 == 1 ) { cs_y2 *= 2; } else /* if ( cs_y2 == 1 ) */ { rs_y2 *= 2; } double* restrict y_cast = ( double* )y; double* restrict y_r = y_cast; double* restrict y_i = y_cast + ld_y; if ( bli_is_conj( conjx ) ) { for ( j = 0; j < n; ++j ) for ( i = 0; i < m; ++i ) { bli_zscal2j1rs( *(alpha), *(x + i*rs_x + j*cs_x ), *(y_r + i*rs_y2 + j*cs_y2), *(y_i + i*rs_y2 + j*cs_y2) ); } } else /* if ( bli_is_noconj( conjx ) ) */ { for ( j = 0; j < n; ++j ) for ( i = 0; i < m; ++i ) { bli_zscal21rs( *(alpha), *(x + i*rs_x + j*cs_x ), *(y_r + i*rs_y2 + j*cs_y2), *(y_i + i*rs_y2 + j*cs_y2) ); } } } } #endif blis-0.9.0/frame/include/level0/1m/bli_scal21ms_mxn_diag.h000066400000000000000000000102701422157504600231720ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_SCAL21MS_MXN_DIAG_H #define BLIS_SCAL21MS_MXN_DIAG_H // scal21ms_mxn_diag #define bli_cscscal21ms_mxn_diag( schema, m, n, a, x, rs_x, cs_x, y, rs_y, cs_y, ld_y ) \ { \ dim_t min_m_n = bli_min( m, n ); \ dim_t i; \ \ /* Handle 1e and 1r separately. */ \ if ( bli_is_1e_packed( schema ) ) \ { \ scomplex* restrict y_off_ri = y; \ scomplex* restrict y_off_ir = y + ld_y/2; \ \ for ( i = 0; i < min_m_n; ++i ) \ { \ bli_cscscal21es( *(a), \ *(x + i*rs_x + i*cs_x), \ *(y_off_ri + i*rs_y + i*cs_y), \ *(y_off_ir + i*rs_y + i*cs_y) ); \ } \ } \ else /* if ( bli_is_1r_packed( schema ) ) */ \ { \ inc_t rs_y2 = rs_y; \ inc_t cs_y2 = cs_y; \ \ /* Scale the non-unit stride by two for the 1r loop, which steps in units of real (not complex) values. */ \ if ( rs_y2 == 1 ) { cs_y2 *= 2; } \ else /* if ( cs_y2 == 1 ) */ { rs_y2 *= 2; } \ \ float* restrict y_cast = ( float* )y; \ float* restrict y_off_r = y_cast; \ float* restrict y_off_i = y_cast + ld_y; \ \ for ( i = 0; i < min_m_n; ++i ) \ { \ bli_cscscal21rs( *(a), \ *(x + i*rs_x + i*cs_x ), \ *(y_off_r + i*rs_y2 + i*cs_y2), \ *(y_off_i + i*rs_y2 + i*cs_y2) ); \ } \ } \ } #define bli_zdzscal21ms_mxn_diag( schema, m, n, a, x, rs_x, cs_x, y, rs_y, cs_y, ld_y ) \ { \ dim_t min_m_n = bli_min( m, n ); \ dim_t i; \ \ /* Handle 1e and 1r separately. */ \ if ( bli_is_1e_packed( schema ) ) \ { \ dcomplex* restrict y_off_ri = y; \ dcomplex* restrict y_off_ir = y + ld_y/2; \ \ for ( i = 0; i < min_m_n; ++i ) \ { \ bli_zdzscal21es( *(a), \ *(x + i*rs_x + i*cs_x), \ *(y_off_ri + i*rs_y + i*cs_y), \ *(y_off_ir + i*rs_y + i*cs_y) ); \ } \ } \ else /* if ( bli_is_1r_packed( schema ) ) */ \ { \ inc_t rs_y2 = rs_y; \ inc_t cs_y2 = cs_y; \ \ /* Scale the non-unit stride by two for the 1r loop, which steps in units of real (not complex) values. */ \ if ( rs_y2 == 1 ) { cs_y2 *= 2; } \ else /* if ( cs_y2 == 1 ) */ { rs_y2 *= 2; } \ \ double* restrict y_cast = ( double* )y; \ double* restrict y_off_r = y_cast; \ double* restrict y_off_i = y_cast + ld_y; \ \ for ( i = 0; i < min_m_n; ++i ) \ { \ bli_zdzscal21rs( *(a), \ *(x + i*rs_x + i*cs_x ), \ *(y_off_r + i*rs_y2 + i*cs_y2), \ *(y_off_i + i*rs_y2 + i*cs_y2) ); \ } \ } \ } #endif blis-0.9.0/frame/include/level0/1m/bli_scal21ms_mxn_uplo.h000066400000000000000000000210021422157504600232400ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_SCAL21MS_MXN_UPLO_H #define BLIS_SCAL21MS_MXN_UPLO_H // scal21ms_mxn_uplo #define bli_cscal21ms_mxn_uplo( schema, uplo, conjx, m, a, x, rs_x, cs_x, y, rs_y, cs_y, ld_y ) \ { \ dim_t i, j; \ \ /* Handle 1e and 1r separately. */ \ if ( bli_is_1e_packed( schema ) ) \ { \ scomplex* restrict y_ri = y; \ scomplex* restrict y_ir = y + ld_y/2; \ \ if ( bli_is_lower( uplo ) ) \ { \ if ( bli_is_conj( conjx ) ) \ { \ for ( j = 0; j < m; ++j ) \ for ( i = j; i < m; ++i ) \ { \ bli_cscal2j1es( *(a), \ *(x + i*rs_x + j*cs_x), \ *(y_ri + i*rs_y + j*cs_y), \ *(y_ir + i*rs_y + j*cs_y) ); \ } \ } \ else /* if ( bli_is_noconj( conjx ) ) */ \ { \ for ( j = 0; j < m; ++j ) \ for ( i = j; i < m; ++i ) \ { \ bli_cscal21es( *(a), \ *(x + i*rs_x + j*cs_x), \ *(y_ri + i*rs_y + j*cs_y), \ *(y_ir + i*rs_y + j*cs_y) ); \ } \ } \ } \ else /* if ( bli_is_upper( uplo ) ) */ \ { \ if ( bli_is_conj( conjx ) ) \ { \ for ( j = 0; j < m; ++j ) \ for ( i = 0; i < j + 1; ++i ) \ { \ bli_cscal2j1es( *(a), \ *(x + i*rs_x + j*cs_x), \ *(y_ri + i*rs_y + j*cs_y), \ *(y_ir + i*rs_y + j*cs_y) ); \ } \ } \ else /* if ( bli_is_noconj( conjx ) ) */ \ { \ for ( j = 0; j < m; ++j ) \ for ( i = 0; i < j + 1; ++i ) \ { \ bli_cscal21es( *(a), \ *(x + i*rs_x + j*cs_x), \ *(y_ri + i*rs_y + j*cs_y), \ *(y_ir + i*rs_y + j*cs_y) ); \ } \ } \ } \ } \ else /* if ( bli_is_1r_packed( schema ) ) */ \ { \ inc_t rs_y2 = rs_y; \ inc_t cs_y2 = cs_y; \ \ /* Scale the non-unit stride by two for the 1r loop, which steps in units of real (not complex) values. */ \ if ( rs_y2 == 1 ) { cs_y2 *= 2; } \ else /* if ( cs_y2 == 1 ) */ { rs_y2 *= 2; } \ \ float* restrict y_cast = ( float* )y; \ float* restrict y_r = y_cast; \ float* restrict y_i = y_cast + ld_y; \ \ if ( bli_is_lower( uplo ) ) \ { \ if ( bli_is_conj( conjx ) ) \ { \ for ( j = 0; j < m; ++j ) \ for ( i = j; i < m; ++i ) \ { \ bli_cscal2j1rs( *(a), \ *(x + i*rs_x + j*cs_x ), \ *(y_r + i*rs_y2 + j*cs_y2), \ *(y_i + i*rs_y2 + j*cs_y2) ); \ } \ } \ else /* if ( bli_is_noconj( conjx ) ) */ \ { \ for ( j = 0; j < m; ++j ) \ for ( i = j; i < m; ++i ) \ { \ bli_cscal21rs( *(a), \ *(x + i*rs_x + j*cs_x ), \ *(y_r + i*rs_y2 + j*cs_y2), \ *(y_i + i*rs_y2 + j*cs_y2) ); \ } \ } \ } \ else /* if ( bli_is_upper( uplo ) ) */ \ { \ if ( bli_is_conj( conjx ) ) \ { \ for ( j = 0; j < m; ++j ) \ for ( i = 0; i < j + 1; ++i ) \ { \ bli_cscal2j1rs( *(a), \ *(x + i*rs_x + j*cs_x ), \ *(y_r + i*rs_y2 + j*cs_y2), \ *(y_i + i*rs_y2 + j*cs_y2) ); \ } \ } \ else /* if ( bli_is_noconj( conjx ) ) */ \ { \ for ( j = 0; j < m; ++j ) \ for ( i = 0; i < j + 1; ++i ) \ { \ bli_cscal21rs( *(a), \ *(x + i*rs_x + j*cs_x ), \ *(y_r + i*rs_y2 + j*cs_y2), \ *(y_i + i*rs_y2 + j*cs_y2) ); \ } \ } \ } \ } \ } #define bli_zscal21ms_mxn_uplo( schema, uplo, conjx, m, a, x, rs_x, cs_x, y, rs_y, cs_y, ld_y ) \ { \ dim_t i, j; \ \ /* Handle 1e and 1r separately. */ \ if ( bli_is_1e_packed( schema ) ) \ { \ dcomplex* restrict y_ri = y; \ dcomplex* restrict y_ir = y + ld_y/2; \ \ if ( bli_is_lower( uplo ) ) \ { \ if ( bli_is_conj( conjx ) ) \ { \ for ( j = 0; j < m; ++j ) \ for ( i = j; i < m; ++i ) \ { \ bli_zscal2j1es( *(a), \ *(x + i*rs_x + j*cs_x), \ *(y_ri + i*rs_y + j*cs_y), \ *(y_ir + i*rs_y + j*cs_y) ); \ } \ } \ else /* if ( bli_is_noconj( conjx ) ) */ \ { \ for ( j = 0; j < m; ++j ) \ for ( i = j; i < m; ++i ) \ { \ bli_zscal21es( *(a), \ *(x + i*rs_x + j*cs_x), \ *(y_ri + i*rs_y + j*cs_y), \ *(y_ir + i*rs_y + j*cs_y) ); \ } \ } \ } \ else /* if ( bli_is_upper( uplo ) ) */ \ { \ if ( bli_is_conj( conjx ) ) \ { \ for ( j = 0; j < m; ++j ) \ for ( i = 0; i < j + 1; ++i ) \ { \ bli_zscal2j1es( *(a), \ *(x + i*rs_x + j*cs_x), \ *(y_ri + i*rs_y + j*cs_y), \ *(y_ir + i*rs_y + j*cs_y) ); \ } \ } \ else /* if ( bli_is_noconj( conjx ) ) */ \ { \ for ( j = 0; j < m; ++j ) \ for ( i = 0; i < j + 1; ++i ) \ { \ bli_zscal21es( *(a), \ *(x + i*rs_x + j*cs_x), \ *(y_ri + i*rs_y + j*cs_y), \ *(y_ir + i*rs_y + j*cs_y) ); \ } \ } \ } \ } \ else /* if ( bli_is_1r_packed( schema ) ) */ \ { \ inc_t rs_y2 = rs_y; \ inc_t cs_y2 = cs_y; \ \ /* Scale the non-unit stride by two for the 1r loop, which steps in units of real (not complex) values. */ \ if ( rs_y2 == 1 ) { cs_y2 *= 2; } \ else /* if ( cs_y2 == 1 ) */ { rs_y2 *= 2; } \ \ double* restrict y_cast = ( double* )y; \ double* restrict y_r = y_cast; \ double* restrict y_i = y_cast + ld_y; \ \ if ( bli_is_lower( uplo ) ) \ { \ if ( bli_is_conj( conjx ) ) \ { \ for ( j = 0; j < m; ++j ) \ for ( i = j; i < m; ++i ) \ { \ bli_zscal2j1rs( *(a), \ *(x + i*rs_x + j*cs_x ), \ *(y_r + i*rs_y2 + j*cs_y2), \ *(y_i + i*rs_y2 + j*cs_y2) ); \ } \ } \ else /* if ( bli_is_noconj( conjx ) ) */ \ { \ for ( j = 0; j < m; ++j ) \ for ( i = j; i < m; ++i ) \ { \ bli_zscal21rs( *(a), \ *(x + i*rs_x + j*cs_x ), \ *(y_r + i*rs_y2 + j*cs_y2), \ *(y_i + i*rs_y2 + j*cs_y2) ); \ } \ } \ } \ else /* if ( bli_is_upper( uplo ) ) */ \ { \ if ( bli_is_conj( conjx ) ) \ { \ for ( j = 0; j < m; ++j ) \ for ( i = 0; i < j + 1; ++i ) \ { \ bli_zscal2j1rs( *(a), \ *(x + i*rs_x + j*cs_x ), \ *(y_r + i*rs_y2 + j*cs_y2), \ *(y_i + i*rs_y2 + j*cs_y2) ); \ } \ } \ else /* if ( bli_is_noconj( conjx ) ) */ \ { \ for ( j = 0; j < m; ++j ) \ for ( i = 0; i < j + 1; ++i ) \ { \ bli_zscal21rs( *(a), \ *(x + i*rs_x + j*cs_x ), \ *(y_r + i*rs_y2 + j*cs_y2), \ *(y_i + i*rs_y2 + j*cs_y2) ); \ } \ } \ } \ } \ } #endif blis-0.9.0/frame/include/level0/1m/bli_set1ms_mxn.h000066400000000000000000000145311422157504600220010ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_SET1MS_MXN_H #define BLIS_SET1MS_MXN_H // set1ms_mxn #define bli_sset1ms_mxn( schema, offm, offn, m, n, a, y, rs_y, cs_y, ld_y ) \ { \ /* Include real domain version to facilitate macro-izing mixed-datatype components of packm. */ \ } #define bli_dset1ms_mxn( schema, offm, offn, m, n, a, y, rs_y, cs_y, ld_y ) \ { \ /* Include real domain version to facilitate macro-izing mixed-datatype components of packm. */ \ } BLIS_INLINE void bli_cset1ms_mxn ( const pack_t schema, const dim_t offm, const dim_t offn, const dim_t m, const dim_t n, scomplex* restrict alpha, scomplex* restrict y, const inc_t rs_y, const inc_t cs_y, const inc_t ld_y ) { inc_t offm_local = offm; inc_t offn_local = offn; dim_t m_local = m; dim_t n_local = n; inc_t rs_y1 = rs_y; inc_t cs_y1 = cs_y; inc_t rs_y2 = rs_y; inc_t cs_y2 = cs_y; dim_t i, j; /* Optimization: The loops walk through y with unit stride if y is column-stored. If y is row-stored, swap the dimensions and strides to preserve unit stride movement. */ if ( cs_y == 1 ) { bli_swap_incs( &offm_local, &offn_local ); bli_swap_dims( &m_local, &n_local ); bli_swap_incs( &rs_y1, &cs_y1 ); bli_swap_incs( &rs_y2, &cs_y2 ); } /* Handle 1e and 1r separately. */ if ( bli_is_1e_packed( schema ) ) { scomplex* restrict y_off_ri = y + (offm_local )*rs_y1 + (offn_local )*cs_y1; scomplex* restrict y_off_ir = y + (offm_local )*rs_y1 + (offn_local )*cs_y1 + ld_y/2; for ( j = 0; j < n_local; ++j ) for ( i = 0; i < m_local; ++i ) { bli_ccopy1es( *(alpha), *(y_off_ri + i*rs_y1 + j*cs_y1), *(y_off_ir + i*rs_y1 + j*cs_y1) ); } } else /* if ( bli_is_1r_packed( schema ) ) */ { /* Scale the non-unit stride by two for the 1r loop, which steps in units of real (not complex) values. */ if ( rs_y2 == 1 ) { cs_y2 *= 2; } else /* if ( cs_y2 == 1 ) */ { rs_y2 *= 2; } float* restrict y_cast = ( float* )y; float* restrict y_off_r = y_cast + (offm_local )*rs_y2 + (offn_local )*cs_y2; float* restrict y_off_i = y_cast + (offm_local )*rs_y2 + (offn_local )*cs_y2 + ld_y; for ( j = 0; j < n_local; ++j ) for ( i = 0; i < m_local; ++i ) { bli_ccopy1rs( *(alpha), *(y_off_r + i*rs_y2 + j*cs_y2), *(y_off_i + i*rs_y2 + j*cs_y2) ); } } } BLIS_INLINE void bli_zset1ms_mxn ( const pack_t schema, const dim_t offm, const dim_t offn, const dim_t m, const dim_t n, dcomplex* restrict alpha, dcomplex* restrict y, const inc_t rs_y, const inc_t cs_y, const inc_t ld_y ) { inc_t offm_local = offm; inc_t offn_local = offn; dim_t m_local = m; dim_t n_local = n; inc_t rs_y1 = rs_y; inc_t cs_y1 = cs_y; inc_t rs_y2 = rs_y; inc_t cs_y2 = cs_y; dim_t i, j; /* Optimization: The loops walk through y with unit stride if y is column-stored. If y is row-stored, swap the dimensions and strides to preserve unit stride movement. */ if ( cs_y == 1 ) { bli_swap_incs( &offm_local, &offn_local ); bli_swap_dims( &m_local, &n_local ); bli_swap_incs( &rs_y1, &cs_y1 ); bli_swap_incs( &rs_y2, &cs_y2 ); } /* Handle 1e and 1r separately. */ if ( bli_is_1e_packed( schema ) ) { dcomplex* restrict y_off_ri = y + (offm_local )*rs_y1 + (offn_local )*cs_y1; dcomplex* restrict y_off_ir = y + (offm_local )*rs_y1 + (offn_local )*cs_y1 + ld_y/2; for ( j = 0; j < n_local; ++j ) for ( i = 0; i < m_local; ++i ) { bli_zcopy1es( *(alpha), *(y_off_ri + i*rs_y1 + j*cs_y1), *(y_off_ir + i*rs_y1 + j*cs_y1) ); } } else /* if ( bli_is_1r_packed( schema ) ) */ { /* Scale the non-unit stride by two for the 1r loop, which steps in units of real (not complex) values. */ if ( rs_y2 == 1 ) { cs_y2 *= 2; } else /* if ( cs_y2 == 1 ) */ { rs_y2 *= 2; } double* restrict y_cast = ( double* )y; double* restrict y_off_r = y_cast + (offm_local )*rs_y2 + (offn_local )*cs_y2; double* restrict y_off_i = y_cast + (offm_local )*rs_y2 + (offn_local )*cs_y2 + ld_y; for ( j = 0; j < n_local; ++j ) for ( i = 0; i < m_local; ++i ) { bli_zcopy1rs( *(alpha), *(y_off_r + i*rs_y2 + j*cs_y2), *(y_off_i + i*rs_y2 + j*cs_y2) ); } } } #endif blis-0.9.0/frame/include/level0/1m/bli_set1ms_mxn_diag.h000066400000000000000000000107421422157504600227650ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_SET1MS_MXN_DIAG_H #define BLIS_SET1MS_MXN_DIAG_H // set1ms_mxn_diag #define bli_cset1ms_mxn_diag( schema, offm, offn, m, n, a, y, rs_y, cs_y, ld_y ) \ { \ dim_t min_m_n = bli_min( m, n ); \ dim_t i; \ \ /* Handle 1e and 1r separately. */ \ if ( bli_is_1e_packed( schema ) ) \ { \ scomplex* restrict y_off_ri = y + (offm )*rs_y \ + (offn )*cs_y; \ scomplex* restrict y_off_ir = y + (offm )*rs_y \ + (offn )*cs_y + ld_y/2; \ \ for ( i = 0; i < min_m_n; ++i ) \ { \ bli_ccopy1es( *(a), \ *(y_off_ri + i*rs_y + i*cs_y), \ *(y_off_ir + i*rs_y + i*cs_y) ); \ } \ } \ else /* if ( bli_is_1r_packed( schema ) ) */ \ { \ inc_t rs_y2 = rs_y; \ inc_t cs_y2 = cs_y; \ \ /* Scale the non-unit stride by two for the 1r loop, which steps in units of real (not complex) values. */ \ if ( rs_y2 == 1 ) { cs_y2 *= 2; } \ else /* if ( cs_y2 == 1 ) */ { rs_y2 *= 2; } \ \ float* restrict y_cast = ( float* )y; \ float* restrict y_off_r = y_cast + (offm )*rs_y2 \ + (offn )*cs_y2; \ float* restrict y_off_i = y_cast + (offm )*rs_y2 \ + (offn )*cs_y2 + ld_y; \ \ for ( i = 0; i < min_m_n; ++i ) \ { \ bli_ccopy1rs( *(a), \ *(y_off_r + i*rs_y2 + i*cs_y2), \ *(y_off_i + i*rs_y2 + i*cs_y2) ); \ } \ } \ } #define bli_zset1ms_mxn_diag( schema, offm, offn, m, n, a, y, rs_y, cs_y, ld_y ) \ { \ dim_t min_m_n = bli_min( m, n ); \ dim_t i; \ \ /* Handle 1e and 1r separately. */ \ if ( bli_is_1e_packed( schema ) ) \ { \ dcomplex* restrict y_off_ri = y + (offm )*rs_y \ + (offn )*cs_y; \ dcomplex* restrict y_off_ir = y + (offm )*rs_y \ + (offn )*cs_y + ld_y/2; \ \ for ( i = 0; i < min_m_n; ++i ) \ { \ bli_zcopy1es( *(a), \ *(y_off_ri + i*rs_y + i*cs_y), \ *(y_off_ir + i*rs_y + i*cs_y) ); \ } \ } \ else /* if ( bli_is_1r_packed( schema ) ) */ \ { \ inc_t rs_y2 = rs_y; \ inc_t cs_y2 = cs_y; \ \ /* Scale the non-unit stride by two for the 1r loop, which steps in units of real (not complex) values. */ \ if ( rs_y2 == 1 ) { cs_y2 *= 2; } \ else /* if ( cs_y2 == 1 ) */ { rs_y2 *= 2; } \ \ double* restrict y_cast = ( double* )y; \ double* restrict y_off_r = y_cast + (offm )*rs_y2 \ + (offn )*cs_y2; \ double* restrict y_off_i = y_cast + (offm )*rs_y2 \ + (offn )*cs_y2 + ld_y; \ \ for ( i = 0; i < min_m_n; ++i ) \ { \ bli_zcopy1rs( *(a), \ *(y_off_r + i*rs_y2 + i*cs_y2), \ *(y_off_i + i*rs_y2 + i*cs_y2) ); \ } \ } \ } #endif blis-0.9.0/frame/include/level0/1m/bli_set1ms_mxn_uplo.h000066400000000000000000000137641422157504600230470ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_SET1MS_MXN_UPLO_H #define BLIS_SET1MS_MXN_UPLO_H // set1ms_mxn_uplo #define bli_cset1ms_mxn_uplo( schema, diagoff, uplo, m, n, a, y, rs_y, cs_y, ld_y ) \ { \ doff_t diagoff_abs = bli_abs( diagoff ); \ inc_t offdiag_inc; \ dim_t i, j; \ \ /* Handle 1e and 1r separately. */ \ if ( bli_is_1e_packed( schema ) ) \ { \ /* Set the off-diagonal increment. */ \ if ( diagoff > 0 ) offdiag_inc = cs_y; \ else /* if ( diagoff < 0 ) */ offdiag_inc = rs_y; \ \ scomplex* restrict y0 = y + (diagoff_abs )*offdiag_inc; \ scomplex* restrict y_ri = y0; \ scomplex* restrict y_ir = y0 + ld_y/2; \ \ if ( bli_is_lower( uplo ) ) \ { \ for ( j = 0; j < n; ++j ) \ for ( i = j; i < m; ++i ) \ { \ bli_ccopy1es( *(a), \ *(y_ri + i*rs_y + j*cs_y), \ *(y_ir + i*rs_y + j*cs_y) ); \ } \ } \ else /* if ( bli_is_upper( uplo ) ) */ \ { \ for ( j = 0; j < n; ++j ) \ for ( i = 0; i < j + 1; ++i ) \ { \ bli_ccopy1es( *(a), \ *(y_ri + i*rs_y + j*cs_y), \ *(y_ir + i*rs_y + j*cs_y) ); \ } \ } \ } \ else /* if ( bli_is_1r_packed( schema ) ) */ \ { \ inc_t rs_y2 = rs_y; \ inc_t cs_y2 = cs_y; \ \ /* Scale the non-unit stride by two for the 1r loop, which steps in units of real (not complex) values. */ \ if ( rs_y2 == 1 ) { cs_y2 *= 2; } \ else /* if ( cs_y2 == 1 ) */ { rs_y2 *= 2; } \ \ /* Set the off-diagonal increment. */ \ if ( diagoff > 0 ) offdiag_inc = cs_y2; \ else /* if ( diagoff < 0 ) */ offdiag_inc = rs_y2; \ \ float* restrict y0 = ( float* )y + (diagoff_abs )*offdiag_inc; \ float* restrict y_r = y0; \ float* restrict y_i = y0 + ld_y; \ \ if ( bli_is_lower( uplo ) ) \ { \ for ( j = 0; j < n; ++j ) \ for ( i = j; i < m; ++i ) \ { \ bli_ccopy1rs( *(a), \ *(y_r + i*rs_y2 + j*cs_y2), \ *(y_i + i*rs_y2 + j*cs_y2) ); \ } \ } \ else /* if ( bli_is_upper( uplo ) ) */ \ { \ for ( j = 0; j < n; ++j ) \ for ( i = 0; i < j + 1; ++i ) \ { \ bli_ccopy1rs( *(a), \ *(y_r + i*rs_y2 + j*cs_y2), \ *(y_i + i*rs_y2 + j*cs_y2) ); \ } \ } \ } \ } #define bli_zset1ms_mxn_uplo( schema, diagoff, uplo, m, n, a, y, rs_y, cs_y, ld_y ) \ { \ doff_t diagoff_abs = bli_abs( diagoff ); \ inc_t offdiag_inc; \ dim_t i, j; \ \ /* Handle 1e and 1r separately. */ \ if ( bli_is_1e_packed( schema ) ) \ { \ /* Set the off-diagonal increment. */ \ if ( diagoff > 0 ) offdiag_inc = cs_y; \ else /* if ( diagoff < 0 ) */ offdiag_inc = rs_y; \ \ dcomplex* restrict y0 = y + (diagoff_abs )*offdiag_inc; \ dcomplex* restrict y_ri = y0; \ dcomplex* restrict y_ir = y0 + ld_y/2; \ \ if ( bli_is_lower( uplo ) ) \ { \ for ( j = 0; j < n; ++j ) \ for ( i = j; i < m; ++i ) \ { \ bli_zcopy1es( *(a), \ *(y_ri + i*rs_y + j*cs_y), \ *(y_ir + i*rs_y + j*cs_y) ); \ } \ } \ else /* if ( bli_is_upper( uplo ) ) */ \ { \ for ( j = 0; j < n; ++j ) \ for ( i = 0; i < j + 1; ++i ) \ { \ bli_zcopy1es( *(a), \ *(y_ri + i*rs_y + j*cs_y), \ *(y_ir + i*rs_y + j*cs_y) ); \ } \ } \ } \ else /* if ( bli_is_1r_packed( schema ) ) */ \ { \ inc_t rs_y2 = rs_y; \ inc_t cs_y2 = cs_y; \ \ /* Scale the non-unit stride by two for the 1r loop, which steps in units of real (not complex) values. */ \ if ( rs_y2 == 1 ) { cs_y2 *= 2; } \ else /* if ( cs_y2 == 1 ) */ { rs_y2 *= 2; } \ \ /* Set the off-diagonal increment. */ \ if ( diagoff > 0 ) offdiag_inc = cs_y2; \ else /* if ( diagoff < 0 ) */ offdiag_inc = rs_y2; \ \ double* restrict y0 = ( double* )y + (diagoff_abs )*offdiag_inc; \ double* restrict y_r = y0; \ double* restrict y_i = y0 + ld_y; \ \ if ( bli_is_lower( uplo ) ) \ { \ for ( j = 0; j < n; ++j ) \ for ( i = j; i < m; ++i ) \ { \ bli_zcopy1rs( *(a), \ *(y_r + i*rs_y2 + j*cs_y2), \ *(y_i + i*rs_y2 + j*cs_y2) ); \ } \ } \ else /* if ( bli_is_upper( uplo ) ) */ \ { \ for ( j = 0; j < n; ++j ) \ for ( i = 0; i < j + 1; ++i ) \ { \ bli_zcopy1rs( *(a), \ *(y_r + i*rs_y2 + j*cs_y2), \ *(y_i + i*rs_y2 + j*cs_y2) ); \ } \ } \ } \ } #endif blis-0.9.0/frame/include/level0/1m/bli_seti01ms_mxn_diag.h000066400000000000000000000071661422157504600232240ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_SETI01MS_MXN_DIAG_H #define BLIS_SETI01MS_MXN_DIAG_H // seti01ms_mxn_diag #define bli_cseti01ms_mxn_diag( schema, m, n, y, rs_y, cs_y, ld_y ) \ { \ dim_t min_m_n = bli_min( m, n ); \ dim_t i; \ \ /* Handle 1e and 1r separately. */ \ if ( bli_is_1e_packed( schema ) ) \ { \ scomplex* restrict y_off_ri = y; \ scomplex* restrict y_off_ir = y + ld_y/2; \ \ for ( i = 0; i < min_m_n; ++i ) \ { \ bli_cseti0s( *(y_off_ri + i*rs_y + i*cs_y) ); \ bli_csetr0s( *(y_off_ir + i*rs_y + i*cs_y) ); \ } \ } \ else /* if ( bli_is_1r_packed( schema ) ) */ \ { \ inc_t rs_y2 = rs_y; \ inc_t cs_y2 = cs_y; \ \ /* Scale the non-unit stride by two for the 1r loop, which steps in units of real (not complex) values. */ \ if ( rs_y2 == 1 ) { cs_y2 *= 2; } \ else /* if ( cs_y2 == 1 ) */ { rs_y2 *= 2; } \ \ float* restrict y_cast = ( float* )y; \ float* restrict y_off_i = y_cast + ld_y; \ \ for ( i = 0; i < min_m_n; ++i ) \ { \ bli_sset0s( *(y_off_i + i*rs_y2 + i*cs_y2) ); \ } \ } \ } #define bli_zseti01ms_mxn_diag( schema, m, n, y, rs_y, cs_y, ld_y ) \ { \ dim_t min_m_n = bli_min( m, n ); \ dim_t i; \ \ /* Handle 1e and 1r separately. */ \ if ( bli_is_1e_packed( schema ) ) \ { \ dcomplex* restrict y_off_ri = y; \ dcomplex* restrict y_off_ir = y + ld_y/2; \ \ for ( i = 0; i < min_m_n; ++i ) \ { \ bli_zseti0s( *(y_off_ri + i*rs_y + i*cs_y) ); \ bli_zsetr0s( *(y_off_ir + i*rs_y + i*cs_y) ); \ } \ } \ else /* if ( bli_is_1r_packed( schema ) ) */ \ { \ inc_t rs_y2 = rs_y; \ inc_t cs_y2 = cs_y; \ \ /* Scale the non-unit stride by two for the 1r loop, which steps in units of real (not complex) values. */ \ if ( rs_y2 == 1 ) { cs_y2 *= 2; } \ else /* if ( cs_y2 == 1 ) */ { rs_y2 *= 2; } \ \ double* restrict y_cast = ( double* )y; \ double* restrict y_off_i = y_cast + ld_y; \ \ for ( i = 0; i < min_m_n; ++i ) \ { \ bli_dset0s( *(y_off_i + i*rs_y2 + i*cs_y2) ); \ } \ } \ } #endif blis-0.9.0/frame/include/level0/1r/000077500000000000000000000000001422157504600167055ustar00rootroot00000000000000blis-0.9.0/frame/include/level0/1r/bli_copy1rs.h000066400000000000000000000036201422157504600213050ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_COPY1RS_H #define BLIS_COPY1RS_H // copy1rs #define bli_ccopy1rs( a, br, bi ) \ { \ bli_ccopyris( bli_creal(a), bli_cimag(a), br, bi ); \ } #define bli_zcopy1rs( a, br, bi ) \ { \ bli_zcopyris( bli_zreal(a), bli_zimag(a), br, bi ); \ } #endif blis-0.9.0/frame/include/level0/1r/bli_copyj1rs.h000066400000000000000000000036271422157504600214660ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_COPYJ1RS_H #define BLIS_COPYJ1RS_H // copyj1rs #define bli_ccopyj1rs( a, br, bi ) \ { \ bli_ccopyjris( bli_creal(a), bli_cimag(a), br, bi ); \ } #define bli_zcopyj1rs( a, br, bi ) \ { \ bli_zcopyjris( bli_zreal(a), bli_zimag(a), br, bi ); \ } #endif blis-0.9.0/frame/include/level0/1r/bli_invert1rs.h000066400000000000000000000035101422157504600216400ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_INVERT1RS_H #define BLIS_INVERT1RS_H // invert1rs #define bli_cinvert1rs( xr, xi ) bli_cinvertris( xr, xi ) #define bli_zinvert1rs( xr, xi ) bli_zinvertris( xr, xi ) #endif blis-0.9.0/frame/include/level0/1r/bli_scal1rs.h000066400000000000000000000041301422157504600212520ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_SCAL1RS_H #define BLIS_SCAL1RS_H // scal1rs #define bli_cscal1rs( a, yr, yi ) \ { \ bli_cscalris( bli_creal(a), bli_cimag(a), yr, yi ); \ } #define bli_zscal1rs( a, yr, yi ) \ { \ bli_zscalris( bli_zreal(a), bli_zimag(a), yr, yi ); \ } #define bli_scscal1rs( a, yr, yi ) \ { \ bli_scscalris( bli_sreal(a), bli_simag(a), yr, yi ); \ } #define bli_dzscal1rs( a, yr, yi ) \ { \ bli_dzscalris( bli_dreal(a), bli_dimag(a), yr, yi ); \ } #endif blis-0.9.0/frame/include/level0/1r/bli_scal21rs.h000066400000000000000000000045651422157504600213500ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_SCAL21RS_H #define BLIS_SCAL21RS_H // scal21rs #define bli_cscscal21rs( a, x, yr, yi ) \ { \ bli_cxscal2ris( bli_creal(a), bli_cimag(a), bli_sreal(x), bli_simag(x), yr, yi ); \ } #define bli_cccscal21rs( a, x, yr, yi ) \ { \ bli_cxscal2ris( bli_creal(a), bli_cimag(a), bli_creal(x), bli_cimag(x), yr, yi ); \ } #define bli_zdzscal21rs( a, x, yr, yi ) \ { \ bli_cxscal2ris( bli_zreal(a), bli_zimag(a), bli_dreal(x), bli_dimag(x), yr, yi ); \ } #define bli_zzzscal21rs( a, x, yr, yi ) \ { \ bli_cxscal2ris( bli_zreal(a), bli_zimag(a), bli_zreal(x), bli_zimag(x), yr, yi ); \ } #define bli_cscal21rs( a, x, yr, yi ) bli_cccscal21rs( a, x, yr, yi ) #define bli_zscal21rs( a, x, yr, yi ) bli_zzzscal21rs( a, x, yr, yi ) #endif blis-0.9.0/frame/include/level0/1r/bli_scal2j1rs.h000066400000000000000000000046001422157504600215100ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_SCAL2J1RS_H #define BLIS_SCAL2J1RS_H // scal2j1rs #define bli_cscscal2j1rs( a, x, yr, yi ) \ { \ bli_cscal2jris( bli_creal(a), bli_cimag(a), bli_sreal(x), bli_simag(x), yr, yi ); \ } #define bli_cccscal2j1rs( a, x, yr, yi ) \ { \ bli_cscal2jris( bli_creal(a), bli_cimag(a), bli_creal(x), bli_cimag(x), yr, yi ); \ } #define bli_zdzscal2j1rs( a, x, yr, yi ) \ { \ bli_zscal2jris( bli_zreal(a), bli_zimag(a), bli_dreal(x), bli_dimag(x), yr, yi ); \ } #define bli_zzzscal2j1rs( a, x, yr, yi ) \ { \ bli_zscal2jris( bli_zreal(a), bli_zimag(a), bli_zreal(x), bli_zimag(x), yr, yi ); \ } #define bli_cscal2j1rs( a, x, yr, yi ) bli_cccscal2j1rs( a, x, yr, yi ) #define bli_zscal2j1rs( a, x, yr, yi ) bli_zzzscal2j1rs( a, x, yr, yi ) #endif blis-0.9.0/frame/include/level0/bb/000077500000000000000000000000001422157504600167465ustar00rootroot00000000000000blis-0.9.0/frame/include/level0/bb/bli_bcastbbs_mxn.h000066400000000000000000000046601422157504600224200ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_BCASTBBS_MXN_H #define BLIS_BCASTBBS_MXN_H // bcastbbs_mxn #undef GENTFUNC #define GENTFUNC( ctype, ch, opname ) \ \ BLIS_INLINE void PASTEMAC(ch,opname) \ ( \ const dim_t m, \ const dim_t n, \ ctype* restrict y, const inc_t incy, const inc_t ldy \ ) \ { \ /* Assume that the duplication factor is the column stride of y. */ \ const dim_t d = ldy; \ const dim_t ds_y = 1; \ \ for ( dim_t i = 0; i < m; ++i ) \ { \ ctype* restrict yi = y + i*incy; \ \ for ( dim_t j = 0; j < n; ++j ) \ { \ ctype* restrict yij = yi + j*ldy; \ \ for ( dim_t p = 1; p < d; ++p ) \ { \ ctype* restrict yijd = yij + p*ds_y; \ \ PASTEMAC(ch,copys)( *yij, *yijd ); \ } \ } \ } \ } INSERT_GENTFUNC_BASIC0( bcastbbs_mxn ) #endif blis-0.9.0/frame/include/level0/bb/bli_scal2bbs_mxn.h000066400000000000000000000143051422157504600223250ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_SCAL2BBS_MXN_H #define BLIS_SCAL2BBS_MXN_H // scal2bbs_mxn #undef GENTFUNCRO #define GENTFUNCRO( ctype, ch, opname ) \ \ BLIS_INLINE void PASTEMAC(ch,opname) \ ( \ const conj_t conjx, \ const dim_t m, \ const dim_t n, \ ctype* restrict alpha, \ ctype* restrict x, const inc_t incx, const inc_t ldx, \ ctype* restrict y, const inc_t incy, const inc_t ldy \ ) \ { \ /* Assume that the duplication factor is the row stride of y. */ \ const dim_t d = incy; \ const dim_t ds_y = 1; \ \ if ( bli_is_conj( conjx ) ) \ { \ for ( dim_t j = 0; j < n; ++j ) \ { \ ctype* restrict xj = x + j*ldx; \ ctype* restrict yj = y + j*ldy; \ \ for ( dim_t i = 0; i < m; ++i ) \ { \ ctype* restrict xij = xj + i*incx; \ ctype* restrict yij = yj + i*incy; \ \ PASTEMAC(ch,scal2js)( *alpha, *xij, *yij ); \ \ for ( dim_t p = 1; p < d; ++p ) \ { \ ctype* restrict yijd = yij + p*ds_y; \ \ PASTEMAC(ch,copys)( *yij, *yijd ); \ } \ } \ } \ } \ else /* if ( bli_is_noconj( conjx ) ) */ \ { \ for ( dim_t j = 0; j < n; ++j ) \ { \ ctype* restrict xj = x + j*ldx; \ ctype* restrict yj = y + j*ldy; \ \ for ( dim_t i = 0; i < m; ++i ) \ { \ ctype* restrict xij = xj + i*incx; \ ctype* restrict yij = yj + i*incy; \ \ PASTEMAC(ch,scal2s)( *alpha, *xij, *yij ); \ \ for ( dim_t p = 1; p < d; ++p ) \ { \ ctype* restrict yijd = yij + p*ds_y; \ \ PASTEMAC(ch,copys)( *yij, *yijd ); \ } \ } \ } \ } \ } INSERT_GENTFUNCRO_BASIC0( scal2bbs_mxn ) #undef GENTFUNCCO #define GENTFUNCCO( ctype, ctype_r, ch, chr, opname ) \ \ BLIS_INLINE void PASTEMAC(ch,opname) \ ( \ const conj_t conjx, \ const dim_t m, \ const dim_t n, \ ctype* restrict alpha, \ ctype* restrict x, const inc_t incx, const inc_t ldx, \ ctype* restrict y, const inc_t incy, const inc_t ldy \ ) \ { \ /* Assume that the duplication factor is the row stride of y. */ \ const dim_t d = incy; \ const dim_t ds_y = 1; \ \ const inc_t incx2 = 2 * incx; \ const inc_t ldx2 = 2 * ldx; \ \ const inc_t incy2 = 2 * incy; \ const inc_t ldy2 = 2 * ldy; \ \ ctype_r* restrict alpha_r = ( ctype_r* )alpha; \ ctype_r* restrict alpha_i = ( ctype_r* )alpha + 1; \ ctype_r* restrict chi_r = ( ctype_r* )x; \ ctype_r* restrict chi_i = ( ctype_r* )x + 1; \ ctype_r* restrict psi_r = ( ctype_r* )y; \ ctype_r* restrict psi_i = ( ctype_r* )y + 1*d; \ \ if ( bli_is_conj( conjx ) ) \ { \ for ( dim_t j = 0; j < n; ++j ) \ { \ ctype_r* restrict chij_r = chi_r + j*ldx2; \ ctype_r* restrict chij_i = chi_i + j*ldx2; \ ctype_r* restrict psij_r = psi_r + j*ldy2; \ ctype_r* restrict psij_i = psi_i + j*ldy2; \ \ for ( dim_t i = 0; i < m; ++i ) \ { \ ctype_r* restrict chiij_r = chij_r + i*incx2; \ ctype_r* restrict chiij_i = chij_i + i*incx2; \ ctype_r* restrict psiij_r = psij_r + i*incy2; \ ctype_r* restrict psiij_i = psij_i + i*incy2; \ \ PASTEMAC(ch,scal2jris)( *alpha_r, *alpha_i, \ *chiij_r, *chiij_i, \ *psiij_r, *psiij_i ); \ \ for ( dim_t p = 1; p < d; ++p ) \ { \ ctype_r* restrict psiijd_r = psiij_r + p*ds_y; \ ctype_r* restrict psiijd_i = psiij_i + p*ds_y; \ \ PASTEMAC(ch,copyris)( *psiij_r, *psiij_i, \ *psiijd_r, *psiijd_i ); \ } \ } \ } \ } \ else /* if ( bli_is_noconj( conjx ) ) */ \ { \ for ( dim_t j = 0; j < n; ++j ) \ { \ ctype_r* restrict chij_r = chi_r + j*ldx2; \ ctype_r* restrict chij_i = chi_i + j*ldx2; \ ctype_r* restrict psij_r = psi_r + j*ldy2; \ ctype_r* restrict psij_i = psi_i + j*ldy2; \ \ for ( dim_t i = 0; i < m; ++i ) \ { \ ctype_r* restrict chiij_r = chij_r + i*incx2; \ ctype_r* restrict chiij_i = chij_i + i*incx2; \ ctype_r* restrict psiij_r = psij_r + i*incy2; \ ctype_r* restrict psiij_i = psij_i + i*incy2; \ \ PASTEMAC(ch,scal2ris)( *alpha_r, *alpha_i, \ *chiij_r, *chiij_i, \ *psiij_r, *psiij_i ); \ \ for ( dim_t p = 1; p < d; ++p ) \ { \ ctype_r* restrict psiijd_r = psiij_r + p*ds_y; \ ctype_r* restrict psiijd_i = psiij_i + p*ds_y; \ \ PASTEMAC(ch,copyris)( *psiij_r, *psiij_i, \ *psiijd_r, *psiijd_i ); \ } \ } \ } \ } \ } INSERT_GENTFUNCCO_BASIC0( scal2bbs_mxn ) #endif blis-0.9.0/frame/include/level0/bb/bli_set0bbs_mxn.h000066400000000000000000000046441422157504600222010ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_SET0BBS_MXN_H #define BLIS_SET0BBS_MXN_H // set0bbs_mxn #undef GENTFUNC #define GENTFUNC( ctype, ch, opname ) \ \ BLIS_INLINE void PASTEMAC(ch,opname) \ ( \ const dim_t m, \ const dim_t n, \ ctype* restrict y, const inc_t incy, const inc_t ldy \ ) \ { \ /* Assume that the duplication factor is the row stride of y. */ \ const dim_t d = incy; \ const dim_t ds_y = 1; \ \ for ( dim_t j = 0; j < n; ++j ) \ { \ ctype* restrict yj = y + j*ldy; \ \ for ( dim_t i = 0; i < m; ++i ) \ { \ ctype* restrict yij = yj + i*incy; \ \ for ( dim_t p = 0; p < d; ++p ) \ { \ ctype* restrict yijd = yij + p*ds_y; \ \ PASTEMAC(ch,set0s)( *yijd ); \ } \ } \ } \ } INSERT_GENTFUNC_BASIC0( set0bbs_mxn ) #endif blis-0.9.0/frame/include/level0/bli_absq2s.h000066400000000000000000000115721422157504600205630ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_ABSQR2_H #define BLIS_ABSQR2_H // absq2s // Notes: // - The first char encodes the type of x. // - The second char encodes the type of a. #define bli_ssabsq2s( x, a ) bli_sabsq2ris( bli_sreal(x), bli_simag(x), bli_sreal(a), 0.0F ) #define bli_dsabsq2s( x, a ) bli_dabsq2ris( bli_dreal(x), bli_dimag(x), bli_sreal(a), 0.0F ) #define bli_csabsq2s( x, a ) { float ti; bli_cabsq2ris( bli_creal(x), bli_cimag(x), bli_sreal(a), ti ); ( void )ti; } #define bli_zsabsq2s( x, a ) { float ti; bli_zabsq2ris( bli_zreal(x), bli_zimag(x), bli_sreal(a), ti ); ( void )ti; } #define bli_sdabsq2s( x, a ) bli_sabsq2ris( bli_sreal(x), bli_simag(x), bli_dreal(a), 0.0 ) #define bli_ddabsq2s( x, a ) bli_dabsq2ris( bli_dreal(x), bli_dimag(x), bli_dreal(a), 0.0 ) #define bli_cdabsq2s( x, a ) { double ti; bli_cabsq2ris( bli_creal(x), bli_cimag(x), bli_dreal(a), ti ); ( void )ti; } #define bli_zdabsq2s( x, a ) { double ti; bli_zabsq2ris( bli_zreal(x), bli_zimag(x), bli_dreal(a), ti ); ( void )ti; } #ifndef BLIS_ENABLE_C99_COMPLEX #define bli_scabsq2s( x, a ) bli_sabsq2ris( bli_sreal(x), bli_simag(x), bli_creal(a), bli_cimag(a) ) #define bli_dcabsq2s( x, a ) bli_dabsq2ris( bli_dreal(x), bli_dimag(x), bli_creal(a), bli_cimag(a) ) #define bli_ccabsq2s( x, a ) bli_cabsq2ris( bli_creal(x), bli_cimag(x), bli_creal(a), bli_cimag(a) ) #define bli_zcabsq2s( x, a ) bli_zabsq2ris( bli_zreal(x), bli_zimag(x), bli_creal(a), bli_cimag(a) ) #define bli_szabsq2s( x, a ) bli_sabsq2ris( bli_sreal(x), bli_simag(x), bli_zreal(a), bli_zimag(a) ) #define bli_dzabsq2s( x, a ) bli_dabsq2ris( bli_dreal(x), bli_dimag(x), bli_zreal(a), bli_zimag(a) ) #define bli_czabsq2s( x, a ) bli_cabsq2ris( bli_creal(x), bli_cimag(x), bli_zreal(a), bli_zimag(a) ) #define bli_zzabsq2s( x, a ) bli_zabsq2ris( bli_zreal(x), bli_zimag(x), bli_zreal(a), bli_zimag(a) ) #else // ifdef BLIS_ENABLE_C99_COMPLEX #define bli_scabsq2s( x, a ) bli_scsets( (x) * (x), 0.0, (a) ) #define bli_dcabsq2s( x, a ) bli_dcsets( (x) * (x), 0.0, (a) ) #define bli_ccabsq2s( x, a ) bli_ccsets( bli_creal(x) * bli_creal(x) + \ bli_cimag(x) * bli_cimag(x), 0.0, (a) ) #define bli_zcabsq2s( x, a ) bli_zcsets( bli_zreal(x) * bli_zreal(x) + \ bli_zimag(x) * bli_zimag(x), 0.0, (a) ) #define bli_szabsq2s( x, a ) bli_szsets( (x) * (x), 0.0, (a) ) #define bli_dzabsq2s( x, a ) bli_dzsets( (x) * (x), 0.0, (a) ) #define bli_czabsq2s( x, a ) bli_czsets( bli_creal(x) * bli_creal(x) + \ bli_cimag(x) * bli_cimag(x), 0.0, (a) ) #define bli_zzabsq2s( x, a ) bli_zzsets( bli_zreal(x) * bli_zreal(x) + \ bli_zimag(x) * bli_zimag(x), 0.0, (a) ) #endif // BLIS_ENABLE_C99_COMPLEX #define bli_sabsq2s( x, a ) bli_ssabsq2s( x, a ) #define bli_dabsq2s( x, a ) bli_ddabsq2s( x, a ) #define bli_cabsq2s( x, a ) bli_ccabsq2s( x, a ) #define bli_zabsq2s( x, a ) bli_zzabsq2s( x, a ) #endif blis-0.9.0/frame/include/level0/bli_abval2s.h000066400000000000000000000117601422157504600207210ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_ABVAL2S_H #define BLIS_ABVAL2S_H // abval2s // Notes: // - The first char encodes the type of x. // - The second char encodes the type of a. #ifndef BLIS_ENABLE_C99_COMPLEX #define bli_ssabval2s( x, a ) bli_sabval2ris( bli_sreal(x), bli_simag(x), bli_sreal(a), 0.0F ) #define bli_dsabval2s( x, a ) bli_dabval2ris( bli_dreal(x), bli_dimag(x), bli_sreal(a), 0.0F ) #define bli_csabval2s( x, a ) { float ti; bli_cabval2ris( bli_creal(x), bli_cimag(x), bli_sreal(a), ti ); ( void )ti; } #define bli_zsabval2s( x, a ) { float ti; bli_zabval2ris( bli_zreal(x), bli_zimag(x), bli_sreal(a), ti ); ( void )ti; } #define bli_sdabval2s( x, a ) bli_sabval2ris( bli_sreal(x), bli_simag(x), bli_dreal(a), 0.0 ) #define bli_ddabval2s( x, a ) bli_dabval2ris( bli_dreal(x), bli_dimag(x), bli_dreal(a), 0.0 ) #define bli_cdabval2s( x, a ) { double ti; bli_cabval2ris( bli_creal(x), bli_cimag(x), bli_dreal(a), ti ); ( void )ti; } #define bli_zdabval2s( x, a ) { double ti; bli_zabval2ris( bli_zreal(x), bli_zimag(x), bli_dreal(a), ti ); ( void )ti; } #define bli_scabval2s( x, a ) bli_sabval2ris( bli_sreal(x), bli_simag(x), bli_creal(a), bli_cimag(a) ) #define bli_dcabval2s( x, a ) bli_dabval2ris( bli_dreal(x), bli_dimag(x), bli_creal(a), bli_cimag(a) ) #define bli_ccabval2s( x, a ) bli_cabval2ris( bli_creal(x), bli_cimag(x), bli_creal(a), bli_cimag(a) ) #define bli_zcabval2s( x, a ) bli_zabval2ris( bli_zreal(x), bli_zimag(x), bli_creal(a), bli_cimag(a) ) #define bli_szabval2s( x, a ) bli_sabval2ris( bli_sreal(x), bli_simag(x), bli_zreal(a), bli_zimag(a) ) #define bli_dzabval2s( x, a ) bli_dabval2ris( bli_dreal(x), bli_dimag(x), bli_zreal(a), bli_zimag(a) ) #define bli_czabval2s( x, a ) bli_cabval2ris( bli_creal(x), bli_cimag(x), bli_zreal(a), bli_zimag(a) ) #define bli_zzabval2s( x, a ) bli_zabval2ris( bli_zreal(x), bli_zimag(x), bli_zreal(a), bli_zimag(a) ) #else // ifdef BLIS_ENABLE_C99_COMPLEX #define bli_ssabval2s( x, a ) bli_sssets( fabsf(x), 0.0, (a) ) #define bli_dsabval2s( x, a ) bli_dssets( fabs (x), 0.0, (a) ) #define bli_csabval2s( x, a ) bli_cssets( cabsf(x), 0.0, (a) ) #define bli_zsabval2s( x, a ) bli_zssets( cabs (x), 0.0, (a) ) #define bli_sdabval2s( x, a ) bli_sdsets( fabsf(x), 0.0, (a) ) #define bli_ddabval2s( x, a ) bli_ddsets( fabs (x), 0.0, (a) ) #define bli_cdabval2s( x, a ) bli_cdsets( cabsf(x), 0.0, (a) ) #define bli_zdabval2s( x, a ) bli_zdsets( cabs (x), 0.0, (a) ) #define bli_scabval2s( x, a ) bli_scsets( fabsf(x), 0.0, (a) ) #define bli_dcabval2s( x, a ) bli_dcsets( fabs (x), 0.0, (a) ) #define bli_ccabval2s( x, a ) bli_ccsets( cabsf(x), 0.0, (a) ) #define bli_zcabval2s( x, a ) bli_zcsets( cabs (x), 0.0, (a) ) #define bli_szabval2s( x, a ) bli_szsets( fabsf(x), 0.0, (a) ) #define bli_dzabval2s( x, a ) bli_dzsets( fabs (x), 0.0, (a) ) #define bli_czabval2s( x, a ) bli_czsets( cabsf(x), 0.0, (a) ) #define bli_zzabval2s( x, a ) bli_zzsets( cabs (x), 0.0, (a) ) #endif // BLIS_ENABLE_C99_COMPLEX #define bli_sabval2s( x, a ) bli_ssabval2s( x, a ) #define bli_dabval2s( x, a ) bli_ddabval2s( x, a ) #define bli_cabval2s( x, a ) bli_ccabval2s( x, a ) #define bli_zabval2s( x, a ) bli_zzabval2s( x, a ) #endif blis-0.9.0/frame/include/level0/bli_add3s.h000066400000000000000000000311431422157504600203620ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_ADD3S_H #define BLIS_ADD3S_H // add3s // Notes: // - The first char encodes the type of a. // - The second char encodes the type of b. // - The third char encodes the type of c. // -- (axy) = (??s) ------------------------------------------------------------ #define bli_sssadd3s( a, b, c ) bli_sadd3ris( bli_sreal(a), bli_simag(a), bli_sreal(b), bli_simag(b), bli_sreal(c), bli_simag(c) ) #define bli_dssadd3s( a, b, c ) bli_sadd3ris( bli_dreal(a), bli_dimag(a), bli_sreal(b), bli_simag(b), bli_sreal(c), bli_simag(c) ) #define bli_cssadd3s( a, b, c ) bli_sadd3ris( bli_creal(a), bli_cimag(a), bli_sreal(b), bli_simag(b), bli_sreal(c), bli_simag(c) ) #define bli_zssadd3s( a, b, c ) bli_sadd3ris( bli_zreal(a), bli_zimag(a), bli_sreal(b), bli_simag(b), bli_sreal(c), bli_simag(c) ) #define bli_sdsadd3s( a, b, c ) bli_sadd3ris( bli_sreal(a), bli_simag(a), bli_dreal(b), bli_dimag(b), bli_sreal(c), bli_simag(c) ) #define bli_ddsadd3s( a, b, c ) bli_sadd3ris( bli_dreal(a), bli_dimag(a), bli_dreal(b), bli_dimag(b), bli_sreal(c), bli_simag(c) ) #define bli_cdsadd3s( a, b, c ) bli_sadd3ris( bli_creal(a), bli_cimag(a), bli_dreal(b), bli_dimag(b), bli_sreal(c), bli_simag(c) ) #define bli_zdsadd3s( a, b, c ) bli_sadd3ris( bli_zreal(a), bli_zimag(a), bli_dreal(b), bli_dimag(b), bli_sreal(c), bli_simag(c) ) #define bli_scsadd3s( a, b, c ) bli_sadd3ris( bli_sreal(a), bli_simag(a), bli_creal(b), bli_cimag(b), bli_sreal(c), bli_simag(c) ) #define bli_dcsadd3s( a, b, c ) bli_sadd3ris( bli_dreal(a), bli_dimag(a), bli_creal(b), bli_cimag(b), bli_sreal(c), bli_simag(c) ) #define bli_ccsadd3s( a, b, c ) bli_sadd3ris( bli_creal(a), bli_cimag(a), bli_creal(b), bli_cimag(b), bli_sreal(c), bli_simag(c) ) #define bli_zcsadd3s( a, b, c ) bli_sadd3ris( bli_zreal(a), bli_zimag(a), bli_creal(b), bli_cimag(b), bli_sreal(c), bli_simag(c) ) #define bli_szsadd3s( a, b, c ) bli_sadd3ris( bli_sreal(a), bli_simag(a), bli_zreal(b), bli_zimag(b), bli_sreal(c), bli_simag(c) ) #define bli_dzsadd3s( a, b, c ) bli_sadd3ris( bli_dreal(a), bli_dimag(a), bli_zreal(b), bli_zimag(b), bli_sreal(c), bli_simag(c) ) #define bli_czsadd3s( a, b, c ) bli_sadd3ris( bli_creal(a), bli_cimag(a), bli_zreal(b), bli_zimag(b), bli_sreal(c), bli_simag(c) ) #define bli_zzsadd3s( a, b, c ) bli_sadd3ris( bli_zreal(a), bli_zimag(a), bli_zreal(b), bli_zimag(b), bli_sreal(c), bli_simag(c) ) // -- (axy) = (??d) ------------------------------------------------------------ #define bli_ssdadd3s( a, b, c ) bli_dadd3ris( bli_sreal(a), bli_simag(a), bli_sreal(b), bli_simag(b), bli_dreal(c), bli_dimag(c) ) #define bli_dsdadd3s( a, b, c ) bli_dadd3ris( bli_dreal(a), bli_dimag(a), bli_sreal(b), bli_simag(b), bli_dreal(c), bli_dimag(c) ) #define bli_csdadd3s( a, b, c ) bli_dadd3ris( bli_creal(a), bli_cimag(a), bli_sreal(b), bli_simag(b), bli_dreal(c), bli_dimag(c) ) #define bli_zsdadd3s( a, b, c ) bli_dadd3ris( bli_zreal(a), bli_zimag(a), bli_sreal(b), bli_simag(b), bli_dreal(c), bli_dimag(c) ) #define bli_sddadd3s( a, b, c ) bli_dadd3ris( bli_sreal(a), bli_simag(a), bli_dreal(b), bli_dimag(b), bli_dreal(c), bli_dimag(c) ) #define bli_dddadd3s( a, b, c ) bli_dadd3ris( bli_dreal(a), bli_dimag(a), bli_dreal(b), bli_dimag(b), bli_dreal(c), bli_dimag(c) ) #define bli_cddadd3s( a, b, c ) bli_dadd3ris( bli_creal(a), bli_cimag(a), bli_dreal(b), bli_dimag(b), bli_dreal(c), bli_dimag(c) ) #define bli_zddadd3s( a, b, c ) bli_dadd3ris( bli_zreal(a), bli_zimag(a), bli_dreal(b), bli_dimag(b), bli_dreal(c), bli_dimag(c) ) #define bli_scdadd3s( a, b, c ) bli_dadd3ris( bli_sreal(a), bli_simag(a), bli_creal(b), bli_cimag(b), bli_dreal(c), bli_dimag(c) ) #define bli_dcdadd3s( a, b, c ) bli_dadd3ris( bli_dreal(a), bli_dimag(a), bli_creal(b), bli_cimag(b), bli_dreal(c), bli_dimag(c) ) #define bli_ccdadd3s( a, b, c ) bli_dadd3ris( bli_creal(a), bli_cimag(a), bli_creal(b), bli_cimag(b), bli_dreal(c), bli_dimag(c) ) #define bli_zcdadd3s( a, b, c ) bli_dadd3ris( bli_zreal(a), bli_zimag(a), bli_creal(b), bli_cimag(b), bli_dreal(c), bli_dimag(c) ) #define bli_szdadd3s( a, b, c ) bli_dadd3ris( bli_sreal(a), bli_simag(a), bli_zreal(b), bli_zimag(b), bli_dreal(c), bli_dimag(c) ) #define bli_dzdadd3s( a, b, c ) bli_dadd3ris( bli_dreal(a), bli_dimag(a), bli_zreal(b), bli_zimag(b), bli_dreal(c), bli_dimag(c) ) #define bli_czdadd3s( a, b, c ) bli_dadd3ris( bli_creal(a), bli_cimag(a), bli_zreal(b), bli_zimag(b), bli_dreal(c), bli_dimag(c) ) #define bli_zzdadd3s( a, b, c ) bli_dadd3ris( bli_zreal(a), bli_zimag(a), bli_zreal(b), bli_zimag(b), bli_dreal(c), bli_dimag(c) ) #ifndef BLIS_ENABLE_C99_COMPLEX // -- (axy) = (??c) ------------------------------------------------------------ #define bli_sscadd3s( a, b, c ) bli_sadd3ris( bli_sreal(a), bli_simag(a), bli_sreal(b), bli_simag(b), bli_creal(c), bli_cimag(c) ) #define bli_dscadd3s( a, b, c ) bli_sadd3ris( bli_dreal(a), bli_dimag(a), bli_sreal(b), bli_simag(b), bli_creal(c), bli_cimag(c) ) #define bli_cscadd3s( a, b, c ) bli_cadd3ris( bli_creal(a), bli_cimag(a), bli_sreal(b), bli_simag(b), bli_creal(c), bli_cimag(c) ) #define bli_zscadd3s( a, b, c ) bli_cadd3ris( bli_zreal(a), bli_zimag(a), bli_sreal(b), bli_simag(b), bli_creal(c), bli_cimag(c) ) #define bli_sdcadd3s( a, b, c ) bli_sadd3ris( bli_sreal(a), bli_simag(a), bli_dreal(b), bli_dimag(b), bli_creal(c), bli_cimag(c) ) #define bli_ddcadd3s( a, b, c ) bli_sadd3ris( bli_dreal(a), bli_dimag(a), bli_dreal(b), bli_dimag(b), bli_creal(c), bli_cimag(c) ) #define bli_cdcadd3s( a, b, c ) bli_cadd3ris( bli_creal(a), bli_cimag(a), bli_dreal(b), bli_dimag(b), bli_creal(c), bli_cimag(c) ) #define bli_zdcadd3s( a, b, c ) bli_cadd3ris( bli_zreal(a), bli_zimag(a), bli_dreal(b), bli_dimag(b), bli_creal(c), bli_cimag(c) ) #define bli_sccadd3s( a, b, c ) bli_cadd3ris( bli_sreal(a), bli_simag(a), bli_creal(b), bli_cimag(b), bli_creal(c), bli_cimag(c) ) #define bli_dccadd3s( a, b, c ) bli_cadd3ris( bli_dreal(a), bli_dimag(a), bli_creal(b), bli_cimag(b), bli_creal(c), bli_cimag(c) ) #define bli_cccadd3s( a, b, c ) bli_cadd3ris( bli_creal(a), bli_cimag(a), bli_creal(b), bli_cimag(b), bli_creal(c), bli_cimag(c) ) #define bli_zccadd3s( a, b, c ) bli_cadd3ris( bli_zreal(a), bli_zimag(a), bli_creal(b), bli_cimag(b), bli_creal(c), bli_cimag(c) ) #define bli_szcadd3s( a, b, c ) bli_cadd3ris( bli_sreal(a), bli_simag(a), bli_zreal(b), bli_zimag(b), bli_creal(c), bli_cimag(c) ) #define bli_dzcadd3s( a, b, c ) bli_cadd3ris( bli_dreal(a), bli_dimag(a), bli_zreal(b), bli_zimag(b), bli_creal(c), bli_cimag(c) ) #define bli_czcadd3s( a, b, c ) bli_cadd3ris( bli_creal(a), bli_cimag(a), bli_zreal(b), bli_zimag(b), bli_creal(c), bli_cimag(c) ) #define bli_zzcadd3s( a, b, c ) bli_cadd3ris( bli_zreal(a), bli_zimag(a), bli_zreal(b), bli_zimag(b), bli_creal(c), bli_cimag(c) ) // -- (axy) = (??z) ------------------------------------------------------------ #define bli_sszadd3s( a, b, c ) bli_dadd3ris( bli_sreal(a), bli_simag(a), bli_sreal(b), bli_simag(b), bli_zreal(c), bli_zimag(c) ) #define bli_dszadd3s( a, b, c ) bli_dadd3ris( bli_dreal(a), bli_dimag(a), bli_sreal(b), bli_simag(b), bli_zreal(c), bli_zimag(c) ) #define bli_cszadd3s( a, b, c ) bli_zadd3ris( bli_creal(a), bli_cimag(a), bli_sreal(b), bli_simag(b), bli_zreal(c), bli_zimag(c) ) #define bli_zszadd3s( a, b, c ) bli_zadd3ris( bli_zreal(a), bli_zimag(a), bli_sreal(b), bli_simag(b), bli_zreal(c), bli_zimag(c) ) #define bli_sdzadd3s( a, b, c ) bli_dadd3ris( bli_sreal(a), bli_simag(a), bli_dreal(b), bli_dimag(b), bli_zreal(c), bli_zimag(c) ) #define bli_ddzadd3s( a, b, c ) bli_dadd3ris( bli_dreal(a), bli_dimag(a), bli_dreal(b), bli_dimag(b), bli_zreal(c), bli_zimag(c) ) #define bli_cdzadd3s( a, b, c ) bli_zadd3ris( bli_creal(a), bli_cimag(a), bli_dreal(b), bli_dimag(b), bli_zreal(c), bli_zimag(c) ) #define bli_zdzadd3s( a, b, c ) bli_zadd3ris( bli_zreal(a), bli_zimag(a), bli_dreal(b), bli_dimag(b), bli_zreal(c), bli_zimag(c) ) #define bli_sczadd3s( a, b, c ) bli_zadd3ris( bli_sreal(a), bli_simag(a), bli_creal(b), bli_cimag(b), bli_zreal(c), bli_zimag(c) ) #define bli_dczadd3s( a, b, c ) bli_zadd3ris( bli_dreal(a), bli_dimag(a), bli_creal(b), bli_cimag(b), bli_zreal(c), bli_zimag(c) ) #define bli_cczadd3s( a, b, c ) bli_zadd3ris( bli_creal(a), bli_cimag(a), bli_creal(b), bli_cimag(b), bli_zreal(c), bli_zimag(c) ) #define bli_zczadd3s( a, b, c ) bli_zadd3ris( bli_zreal(a), bli_zimag(a), bli_creal(b), bli_cimag(b), bli_zreal(c), bli_zimag(c) ) #define bli_szzadd3s( a, b, c ) bli_zadd3ris( bli_sreal(a), bli_simag(a), bli_zreal(b), bli_zimag(b), bli_zreal(c), bli_zimag(c) ) #define bli_dzzadd3s( a, b, c ) bli_zadd3ris( bli_dreal(a), bli_dimag(a), bli_zreal(b), bli_zimag(b), bli_zreal(c), bli_zimag(c) ) #define bli_czzadd3s( a, b, c ) bli_zadd3ris( bli_creal(a), bli_cimag(a), bli_zreal(b), bli_zimag(b), bli_zreal(c), bli_zimag(c) ) #define bli_zzzadd3s( a, b, c ) bli_zadd3ris( bli_zreal(a), bli_zimag(a), bli_zreal(b), bli_zimag(b), bli_zreal(c), bli_zimag(c) ) #else // ifdef BLIS_ENABLE_C99_COMPLEX // -- (axy) = (??c) ------------------------------------------------------------ #define bli_sscadd3s( a, b, c ) { (c) = (a) + (b); } #define bli_dscadd3s( a, b, c ) { (c) = (a) + (b); } #define bli_cscadd3s( a, b, c ) { (c) = (a) + (b); } #define bli_zscadd3s( a, b, c ) { (c) = (a) + (b); } #define bli_sdcadd3s( a, b, c ) { (c) = (a) + (b); } #define bli_ddcadd3s( a, b, c ) { (c) = (a) + (b); } #define bli_cdcadd3s( a, b, c ) { (c) = (a) + (b); } #define bli_zdcadd3s( a, b, c ) { (c) = (a) + (b); } #define bli_sccadd3s( a, b, c ) { (c) = (a) + (b); } #define bli_dccadd3s( a, b, c ) { (c) = (a) + (b); } #define bli_cccadd3s( a, b, c ) { (c) = (a) + (b); } #define bli_zccadd3s( a, b, c ) { (c) = (a) + (b); } #define bli_szcadd3s( a, b, c ) { (c) = (a) + (b); } #define bli_dzcadd3s( a, b, c ) { (c) = (a) + (b); } #define bli_czcadd3s( a, b, c ) { (c) = (a) + (b); } #define bli_zzcadd3s( a, b, c ) { (c) = (a) + (b); } // -- (axy) = (??z) ------------------------------------------------------------ #define bli_sszadd3s( a, b, c ) { (c) = (a) + (b); } #define bli_dszadd3s( a, b, c ) { (c) = (a) + (b); } #define bli_cszadd3s( a, b, c ) { (c) = (a) + (b); } #define bli_zszadd3s( a, b, c ) { (c) = (a) + (b); } #define bli_sdzadd3s( a, b, c ) { (c) = (a) + (b); } #define bli_ddzadd3s( a, b, c ) { (c) = (a) + (b); } #define bli_cdzadd3s( a, b, c ) { (c) = (a) + (b); } #define bli_zdzadd3s( a, b, c ) { (c) = (a) + (b); } #define bli_sczadd3s( a, b, c ) { (c) = (a) + (b); } #define bli_dczadd3s( a, b, c ) { (c) = (a) + (b); } #define bli_cczadd3s( a, b, c ) { (c) = (a) + (b); } #define bli_zczadd3s( a, b, c ) { (c) = (a) + (b); } #define bli_szzadd3s( a, b, c ) { (c) = (a) + (b); } #define bli_dzzadd3s( a, b, c ) { (c) = (a) + (b); } #define bli_czzadd3s( a, b, c ) { (c) = (a) + (b); } #define bli_zzzadd3s( a, b, c ) { (c) = (a) + (b); } #endif // BLIS_ENABLE_C99_COMPLEX #define bli_sadd3s( a, b, c ) bli_sssadd3s( a, b, c ) #define bli_dadd3s( a, b, c ) bli_dddadd3s( a, b, c ) #define bli_cadd3s( a, b, c ) bli_cccadd3s( a, b, c ) #define bli_zadd3s( a, b, c ) bli_zzzadd3s( a, b, c ) #endif blis-0.9.0/frame/include/level0/bli_addjs.h000066400000000000000000000100551422157504600204500ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_ADDJS_H #define BLIS_ADDJS_H // addjs // Notes: // - The first char encodes the type of a. // - The second char encodes the type of y. #define bli_ssaddjs( a, y ) bli_saddjris( bli_sreal(a), bli_simag(a), bli_sreal(y), bli_simag(y) ) #define bli_dsaddjs( a, y ) bli_saddjris( bli_dreal(a), bli_dimag(a), bli_sreal(y), bli_simag(y) ) #define bli_csaddjs( a, y ) bli_saddjris( bli_creal(a), bli_cimag(a), bli_sreal(y), bli_simag(y) ) #define bli_zsaddjs( a, y ) bli_saddjris( bli_zreal(a), bli_zimag(a), bli_sreal(y), bli_simag(y) ) #define bli_sdaddjs( a, y ) bli_daddjris( bli_sreal(a), bli_simag(a), bli_dreal(y), bli_dimag(y) ) #define bli_ddaddjs( a, y ) bli_daddjris( bli_dreal(a), bli_dimag(a), bli_dreal(y), bli_dimag(y) ) #define bli_cdaddjs( a, y ) bli_daddjris( bli_creal(a), bli_cimag(a), bli_dreal(y), bli_dimag(y) ) #define bli_zdaddjs( a, y ) bli_daddjris( bli_zreal(a), bli_zimag(a), bli_dreal(y), bli_dimag(y) ) #ifndef BLIS_ENABLE_C99_COMPLEX #define bli_scaddjs( a, y ) bli_caddjris( bli_sreal(a), bli_simag(a), bli_creal(y), bli_cimag(y) ) #define bli_dcaddjs( a, y ) bli_caddjris( bli_dreal(a), bli_dimag(a), bli_creal(y), bli_cimag(y) ) #define bli_ccaddjs( a, y ) bli_caddjris( bli_creal(a), bli_cimag(a), bli_creal(y), bli_cimag(y) ) #define bli_zcaddjs( a, y ) bli_caddjris( bli_zreal(a), bli_zimag(a), bli_creal(y), bli_cimag(y) ) #define bli_szaddjs( a, y ) bli_zaddjris( bli_sreal(a), bli_simag(a), bli_zreal(y), bli_zimag(y) ) #define bli_dzaddjs( a, y ) bli_zaddjris( bli_dreal(a), bli_dimag(a), bli_zreal(y), bli_zimag(y) ) #define bli_czaddjs( a, y ) bli_zaddjris( bli_creal(a), bli_cimag(a), bli_zreal(y), bli_zimag(y) ) #define bli_zzaddjs( a, y ) bli_zaddjris( bli_zreal(a), bli_zimag(a), bli_zreal(y), bli_zimag(y) ) #else // ifdef BLIS_ENABLE_C99_COMPLEX #define bli_scaddjs( a, y ) { (y) += (a); } #define bli_dcaddjs( a, y ) { (y) += (a); } #define bli_ccaddjs( a, y ) { (y) += conjf(a); } #define bli_zcaddjs( a, y ) { (y) += conj (a); } #define bli_szaddjs( a, y ) { (y) += (a); } #define bli_dzaddjs( a, y ) { (y) += (a); } #define bli_czaddjs( a, y ) { (y) += conjf(a); } #define bli_zzaddjs( a, y ) { (y) += conj (a); } #endif // BLIS_ENABLE_C99_COMPLEX #define bli_saddjs( a, y ) bli_ssaddjs( a, y ) #define bli_daddjs( a, y ) bli_ddaddjs( a, y ) #define bli_caddjs( a, y ) bli_ccaddjs( a, y ) #define bli_zaddjs( a, y ) bli_zzaddjs( a, y ) #endif blis-0.9.0/frame/include/level0/bli_adds.h000066400000000000000000000077221422157504600203050ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_ADDS_H #define BLIS_ADDS_H // adds // Notes: // - The first char encodes the type of a. // - The second char encodes the type of y. #define bli_ssadds( a, y ) bli_saddris( bli_sreal(a), bli_simag(a), bli_sreal(y), bli_simag(y) ) #define bli_dsadds( a, y ) bli_saddris( bli_dreal(a), bli_dimag(a), bli_sreal(y), bli_simag(y) ) #define bli_csadds( a, y ) bli_saddris( bli_creal(a), bli_cimag(a), bli_sreal(y), bli_simag(y) ) #define bli_zsadds( a, y ) bli_saddris( bli_zreal(a), bli_zimag(a), bli_sreal(y), bli_simag(y) ) #define bli_sdadds( a, y ) bli_daddris( bli_sreal(a), bli_simag(a), bli_dreal(y), bli_dimag(y) ) #define bli_ddadds( a, y ) bli_daddris( bli_dreal(a), bli_dimag(a), bli_dreal(y), bli_dimag(y) ) #define bli_cdadds( a, y ) bli_daddris( bli_creal(a), bli_cimag(a), bli_dreal(y), bli_dimag(y) ) #define bli_zdadds( a, y ) bli_daddris( bli_zreal(a), bli_zimag(a), bli_dreal(y), bli_dimag(y) ) #ifndef BLIS_ENABLE_C99_COMPLEX #define bli_scadds( a, y ) bli_caddris( bli_sreal(a), bli_simag(a), bli_creal(y), bli_cimag(y) ) #define bli_dcadds( a, y ) bli_caddris( bli_dreal(a), bli_dimag(a), bli_creal(y), bli_cimag(y) ) #define bli_ccadds( a, y ) bli_caddris( bli_creal(a), bli_cimag(a), bli_creal(y), bli_cimag(y) ) #define bli_zcadds( a, y ) bli_caddris( bli_zreal(a), bli_zimag(a), bli_creal(y), bli_cimag(y) ) #define bli_szadds( a, y ) bli_zaddris( bli_sreal(a), bli_simag(a), bli_zreal(y), bli_zimag(y) ) #define bli_dzadds( a, y ) bli_zaddris( bli_dreal(a), bli_dimag(a), bli_zreal(y), bli_zimag(y) ) #define bli_czadds( a, y ) bli_zaddris( bli_creal(a), bli_cimag(a), bli_zreal(y), bli_zimag(y) ) #define bli_zzadds( a, y ) bli_zaddris( bli_zreal(a), bli_zimag(a), bli_zreal(y), bli_zimag(y) ) #else // ifdef BLIS_ENABLE_C99_COMPLEX #define bli_scadds( a, y ) { (y) += (a); } #define bli_dcadds( a, y ) { (y) += (a); } #define bli_ccadds( a, y ) { (y) += (a); } #define bli_zcadds( a, y ) { (y) += (a); } #define bli_szadds( a, y ) { (y) += (a); } #define bli_dzadds( a, y ) { (y) += (a); } #define bli_czadds( a, y ) { (y) += (a); } #define bli_zzadds( a, y ) { (y) += (a); } #endif // BLIS_ENABLE_C99_COMPLEX #define bli_sadds( a, y ) bli_ssadds( a, y ) #define bli_dadds( a, y ) bli_ddadds( a, y ) #define bli_cadds( a, y ) bli_ccadds( a, y ) #define bli_zadds( a, y ) bli_zzadds( a, y ) #endif blis-0.9.0/frame/include/level0/bli_adds_mxn.h000066400000000000000000000374051422157504600211700ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_ADDS_MXN_H #define BLIS_ADDS_MXN_H // adds_mxn // Notes: // - The first char encodes the type of x. // - The second char encodes the type of y. // xy = ?s BLIS_INLINE void bli_ssadds_mxn( const dim_t m, const dim_t n, float* restrict x, const inc_t rs_x, const inc_t cs_x, float* restrict y, const inc_t rs_y, const inc_t cs_y ) { #ifdef BLIS_ENABLE_CR_CASES if ( rs_x == 1 && rs_y == 1 ) { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_ssadds( *(x + ii + jj*cs_x), *(y + ii + jj*cs_y) ); } else if ( cs_x == 1 && cs_y == 1 ) { for ( dim_t ii = 0; ii < m; ++ii ) for ( dim_t jj = 0; jj < n; ++jj ) bli_ssadds( *(x + ii*rs_x + jj), *(y + ii*rs_y + jj) ); } else #endif { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_ssadds( *(x + ii*rs_x + jj*cs_x), *(y + ii*rs_y + jj*cs_y) ); } } BLIS_INLINE void bli_dsadds_mxn( const dim_t m, const dim_t n, double* restrict x, const inc_t rs_x, const inc_t cs_x, float* restrict y, const inc_t rs_y, const inc_t cs_y ) { #ifdef BLIS_ENABLE_CR_CASES if ( rs_x == 1 && rs_y == 1 ) { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_dsadds( *(x + ii + jj*cs_x), *(y + ii + jj*cs_y) ); } else if ( cs_x == 1 && cs_y == 1 ) { for ( dim_t ii = 0; ii < m; ++ii ) for ( dim_t jj = 0; jj < n; ++jj ) bli_dsadds( *(x + ii*rs_x + jj), *(y + ii*rs_y + jj) ); } else #endif { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_dsadds( *(x + ii*rs_x + jj*cs_x), *(y + ii*rs_y + jj*cs_y) ); } } BLIS_INLINE void bli_csadds_mxn( const dim_t m, const dim_t n, scomplex* restrict x, const inc_t rs_x, const inc_t cs_x, float* restrict y, const inc_t rs_y, const inc_t cs_y ) { #ifdef BLIS_ENABLE_CR_CASES if ( rs_x == 1 && rs_y == 1 ) { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_csadds( *(x + ii + jj*cs_x), *(y + ii + jj*cs_y) ); } else if ( cs_x == 1 && cs_y == 1 ) { for ( dim_t ii = 0; ii < m; ++ii ) for ( dim_t jj = 0; jj < n; ++jj ) bli_csadds( *(x + ii*rs_x + jj), *(y + ii*rs_y + jj) ); } else #endif { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_csadds( *(x + ii*rs_x + jj*cs_x), *(y + ii*rs_y + jj*cs_y) ); } } BLIS_INLINE void bli_zsadds_mxn( const dim_t m, const dim_t n, dcomplex* restrict x, const inc_t rs_x, const inc_t cs_x, float* restrict y, const inc_t rs_y, const inc_t cs_y ) { #ifdef BLIS_ENABLE_CR_CASES if ( rs_x == 1 && rs_y == 1 ) { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_zsadds( *(x + ii + jj*cs_x), *(y + ii + jj*cs_y) ); } else if ( cs_x == 1 && cs_y == 1 ) { for ( dim_t ii = 0; ii < m; ++ii ) for ( dim_t jj = 0; jj < n; ++jj ) bli_zsadds( *(x + ii*rs_x + jj), *(y + ii*rs_y + jj) ); } else #endif { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_zsadds( *(x + ii*rs_x + jj*cs_x), *(y + ii*rs_y + jj*cs_y) ); } } // xy = ?d BLIS_INLINE void bli_sdadds_mxn( const dim_t m, const dim_t n, float* restrict x, const inc_t rs_x, const inc_t cs_x, double* restrict y, const inc_t rs_y, const inc_t cs_y ) { #ifdef BLIS_ENABLE_CR_CASES if ( rs_x == 1 && rs_y == 1 ) { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_sdadds( *(x + ii + jj*cs_x), *(y + ii + jj*cs_y) ); } else if ( cs_x == 1 && cs_y == 1 ) { for ( dim_t ii = 0; ii < m; ++ii ) for ( dim_t jj = 0; jj < n; ++jj ) bli_sdadds( *(x + ii*rs_x + jj), *(y + ii*rs_y + jj) ); } else #endif { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_sdadds( *(x + ii*rs_x + jj*cs_x), *(y + ii*rs_y + jj*cs_y) ); } } BLIS_INLINE void bli_ddadds_mxn( const dim_t m, const dim_t n, double* restrict x, const inc_t rs_x, const inc_t cs_x, double* restrict y, const inc_t rs_y, const inc_t cs_y ) { #ifdef BLIS_ENABLE_CR_CASES if ( rs_x == 1 && rs_y == 1 ) { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_ddadds( *(x + ii + jj*cs_x), *(y + ii + jj*cs_y) ); } else if ( cs_x == 1 && cs_y == 1 ) { for ( dim_t ii = 0; ii < m; ++ii ) for ( dim_t jj = 0; jj < n; ++jj ) bli_ddadds( *(x + ii*rs_x + jj), *(y + ii*rs_y + jj) ); } else #endif { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_ddadds( *(x + ii*rs_x + jj*cs_x), *(y + ii*rs_y + jj*cs_y) ); } } BLIS_INLINE void bli_cdadds_mxn( const dim_t m, const dim_t n, scomplex* restrict x, const inc_t rs_x, const inc_t cs_x, double* restrict y, const inc_t rs_y, const inc_t cs_y ) { #ifdef BLIS_ENABLE_CR_CASES if ( rs_x == 1 && rs_y == 1 ) { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_cdadds( *(x + ii + jj*cs_x), *(y + ii + jj*cs_y) ); } else if ( cs_x == 1 && cs_y == 1 ) { for ( dim_t ii = 0; ii < m; ++ii ) for ( dim_t jj = 0; jj < n; ++jj ) bli_cdadds( *(x + ii*rs_x + jj), *(y + ii*rs_y + jj) ); } else #endif { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_cdadds( *(x + ii*rs_x + jj*cs_x), *(y + ii*rs_y + jj*cs_y) ); } } BLIS_INLINE void bli_zdadds_mxn( const dim_t m, const dim_t n, dcomplex* restrict x, const inc_t rs_x, const inc_t cs_x, double* restrict y, const inc_t rs_y, const inc_t cs_y ) { #ifdef BLIS_ENABLE_CR_CASES if ( rs_x == 1 && rs_y == 1 ) { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_zdadds( *(x + ii + jj*cs_x), *(y + ii + jj*cs_y) ); } else if ( cs_x == 1 && cs_y == 1 ) { for ( dim_t ii = 0; ii < m; ++ii ) for ( dim_t jj = 0; jj < n; ++jj ) bli_zdadds( *(x + ii*rs_x + jj), *(y + ii*rs_y + jj) ); } else #endif { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_zdadds( *(x + ii*rs_x + jj*cs_x), *(y + ii*rs_y + jj*cs_y) ); } } // xy = ?c BLIS_INLINE void bli_scadds_mxn( const dim_t m, const dim_t n, float* restrict x, const inc_t rs_x, const inc_t cs_x, scomplex* restrict y, const inc_t rs_y, const inc_t cs_y ) { #ifdef BLIS_ENABLE_CR_CASES if ( rs_x == 1 && rs_y == 1 ) { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_scadds( *(x + ii + jj*cs_x), *(y + ii + jj*cs_y) ); } else if ( cs_x == 1 && cs_y == 1 ) { for ( dim_t ii = 0; ii < m; ++ii ) for ( dim_t jj = 0; jj < n; ++jj ) bli_scadds( *(x + ii*rs_x + jj), *(y + ii*rs_y + jj) ); } else #endif { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_scadds( *(x + ii*rs_x + jj*cs_x), *(y + ii*rs_y + jj*cs_y) ); } } BLIS_INLINE void bli_dcadds_mxn( const dim_t m, const dim_t n, double* restrict x, const inc_t rs_x, const inc_t cs_x, scomplex* restrict y, const inc_t rs_y, const inc_t cs_y ) { #ifdef BLIS_ENABLE_CR_CASES if ( rs_x == 1 && rs_y == 1 ) { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_dcadds( *(x + ii + jj*cs_x), *(y + ii + jj*cs_y) ); } else if ( cs_x == 1 && cs_y == 1 ) { for ( dim_t ii = 0; ii < m; ++ii ) for ( dim_t jj = 0; jj < n; ++jj ) bli_dcadds( *(x + ii*rs_x + jj), *(y + ii*rs_y + jj) ); } else #endif { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_dcadds( *(x + ii*rs_x + jj*cs_x), *(y + ii*rs_y + jj*cs_y) ); } } BLIS_INLINE void bli_ccadds_mxn( const dim_t m, const dim_t n, scomplex* restrict x, const inc_t rs_x, const inc_t cs_x, scomplex* restrict y, const inc_t rs_y, const inc_t cs_y ) { #ifdef BLIS_ENABLE_CR_CASES if ( rs_x == 1 && rs_y == 1 ) { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_ccadds( *(x + ii + jj*cs_x), *(y + ii + jj*cs_y) ); } else if ( cs_x == 1 && cs_y == 1 ) { for ( dim_t ii = 0; ii < m; ++ii ) for ( dim_t jj = 0; jj < n; ++jj ) bli_ccadds( *(x + ii*rs_x + jj), *(y + ii*rs_y + jj) ); } else #endif { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_ccadds( *(x + ii*rs_x + jj*cs_x), *(y + ii*rs_y + jj*cs_y) ); } } BLIS_INLINE void bli_zcadds_mxn( const dim_t m, const dim_t n, dcomplex* restrict x, const inc_t rs_x, const inc_t cs_x, scomplex* restrict y, const inc_t rs_y, const inc_t cs_y ) { #ifdef BLIS_ENABLE_CR_CASES if ( rs_x == 1 && rs_y == 1 ) { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_zcadds( *(x + ii + jj*cs_x), *(y + ii + jj*cs_y) ); } else if ( cs_x == 1 && cs_y == 1 ) { for ( dim_t ii = 0; ii < m; ++ii ) for ( dim_t jj = 0; jj < n; ++jj ) bli_zcadds( *(x + ii*rs_x + jj), *(y + ii*rs_y + jj) ); } else #endif { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_zcadds( *(x + ii*rs_x + jj*cs_x), *(y + ii*rs_y + jj*cs_y) ); } } // xy = ?z BLIS_INLINE void bli_szadds_mxn( const dim_t m, const dim_t n, float* restrict x, const inc_t rs_x, const inc_t cs_x, dcomplex* restrict y, const inc_t rs_y, const inc_t cs_y ) { #ifdef BLIS_ENABLE_CR_CASES if ( rs_x == 1 && rs_y == 1 ) { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_szadds( *(x + ii + jj*cs_x), *(y + ii + jj*cs_y) ); } else if ( cs_x == 1 && cs_y == 1 ) { for ( dim_t ii = 0; ii < m; ++ii ) for ( dim_t jj = 0; jj < n; ++jj ) bli_szadds( *(x + ii*rs_x + jj), *(y + ii*rs_y + jj) ); } else #endif { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_szadds( *(x + ii*rs_x + jj*cs_x), *(y + ii*rs_y + jj*cs_y) ); } } BLIS_INLINE void bli_dzadds_mxn( const dim_t m, const dim_t n, double* restrict x, const inc_t rs_x, const inc_t cs_x, dcomplex* restrict y, const inc_t rs_y, const inc_t cs_y ) { #ifdef BLIS_ENABLE_CR_CASES if ( rs_x == 1 && rs_y == 1 ) { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_dzadds( *(x + ii + jj*cs_x), *(y + ii + jj*cs_y) ); } else if ( cs_x == 1 && cs_y == 1 ) { for ( dim_t ii = 0; ii < m; ++ii ) for ( dim_t jj = 0; jj < n; ++jj ) bli_dzadds( *(x + ii*rs_x + jj), *(y + ii*rs_y + jj) ); } else #endif { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_dzadds( *(x + ii*rs_x + jj*cs_x), *(y + ii*rs_y + jj*cs_y) ); } } BLIS_INLINE void bli_czadds_mxn( const dim_t m, const dim_t n, scomplex* restrict x, const inc_t rs_x, const inc_t cs_x, dcomplex* restrict y, const inc_t rs_y, const inc_t cs_y ) { #ifdef BLIS_ENABLE_CR_CASES if ( rs_x == 1 && rs_y == 1 ) { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_czadds( *(x + ii + jj*cs_x), *(y + ii + jj*cs_y) ); } else if ( cs_x == 1 && cs_y == 1 ) { for ( dim_t ii = 0; ii < m; ++ii ) for ( dim_t jj = 0; jj < n; ++jj ) bli_czadds( *(x + ii*rs_x + jj), *(y + ii*rs_y + jj) ); } else #endif { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_czadds( *(x + ii*rs_x + jj*cs_x), *(y + ii*rs_y + jj*cs_y) ); } } BLIS_INLINE void bli_zzadds_mxn( const dim_t m, const dim_t n, dcomplex* restrict x, const inc_t rs_x, const inc_t cs_x, dcomplex* restrict y, const inc_t rs_y, const inc_t cs_y ) { #ifdef BLIS_ENABLE_CR_CASES if ( rs_x == 1 && rs_y == 1 ) { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_zzadds( *(x + ii + jj*cs_x), *(y + ii + jj*cs_y) ); } else if ( cs_x == 1 && cs_y == 1 ) { for ( dim_t ii = 0; ii < m; ++ii ) for ( dim_t jj = 0; jj < n; ++jj ) bli_zzadds( *(x + ii*rs_x + jj), *(y + ii*rs_y + jj) ); } else #endif { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_zzadds( *(x + ii*rs_x + jj*cs_x), *(y + ii*rs_y + jj*cs_y) ); } } BLIS_INLINE void bli_sadds_mxn( const dim_t m, const dim_t n, float* restrict x, const inc_t rs_x, const inc_t cs_x, float* restrict y, const inc_t rs_y, const inc_t cs_y ) { bli_ssadds_mxn( m, n, x, rs_x, cs_x, y, rs_y, cs_y ); } BLIS_INLINE void bli_dadds_mxn( const dim_t m, const dim_t n, double* restrict x, const inc_t rs_x, const inc_t cs_x, double* restrict y, const inc_t rs_y, const inc_t cs_y ) { bli_ddadds_mxn( m, n, x, rs_x, cs_x, y, rs_y, cs_y ); } BLIS_INLINE void bli_cadds_mxn( const dim_t m, const dim_t n, scomplex* restrict x, const inc_t rs_x, const inc_t cs_x, scomplex* restrict y, const inc_t rs_y, const inc_t cs_y ) { bli_ccadds_mxn( m, n, x, rs_x, cs_x, y, rs_y, cs_y ); } BLIS_INLINE void bli_zadds_mxn( const dim_t m, const dim_t n, dcomplex* restrict x, const inc_t rs_x, const inc_t cs_x, dcomplex* restrict y, const inc_t rs_y, const inc_t cs_y ) { bli_zzadds_mxn( m, n, x, rs_x, cs_x, y, rs_y, cs_y ); } #endif blis-0.9.0/frame/include/level0/bli_adds_mxn_uplo.h000066400000000000000000000130231422157504600222150ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_ADDS_MXN_UPLO_H #define BLIS_ADDS_MXN_UPLO_H // adds_mxn_u #define bli_ssadds_mxn_u( diagoff, m, n, x, rs_x, cs_x, y, rs_y, cs_y ) \ { \ dim_t _i, _j; \ \ for ( _j = 0; _j < n; ++_j ) \ { \ for ( _i = 0; _i < m; ++_i ) \ { \ if ( (doff_t)_j - (doff_t)_i >= diagoff ) \ { \ bli_ssadds( *(x + _i*rs_x + _j*cs_x), \ *(y + _i*rs_y + _j*cs_y) ); \ } \ } \ } \ } #define bli_ddadds_mxn_u( diagoff, m, n, x, rs_x, cs_x, y, rs_y, cs_y ) \ { \ dim_t _i, _j; \ \ for ( _j = 0; _j < n; ++_j ) \ { \ for ( _i = 0; _i < m; ++_i ) \ { \ if ( (doff_t)_j - (doff_t)_i >= diagoff ) \ { \ bli_ddadds( *(x + _i*rs_x + _j*cs_x), \ *(y + _i*rs_y + _j*cs_y) ); \ } \ } \ } \ } #define bli_ccadds_mxn_u( diagoff, m, n, x, rs_x, cs_x, y, rs_y, cs_y ) \ { \ dim_t _i, _j; \ \ for ( _j = 0; _j < n; ++_j ) \ { \ for ( _i = 0; _i < m; ++_i ) \ { \ if ( (doff_t)_j - (doff_t)_i >= diagoff ) \ { \ bli_ccadds( *(x + _i*rs_x + _j*cs_x), \ *(y + _i*rs_y + _j*cs_y) ); \ } \ } \ } \ } #define bli_zzadds_mxn_u( diagoff, m, n, x, rs_x, cs_x, y, rs_y, cs_y ) \ { \ dim_t _i, _j; \ \ for ( _j = 0; _j < n; ++_j ) \ { \ for ( _i = 0; _i < m; ++_i ) \ { \ if ( (doff_t)_j - (doff_t)_i >= diagoff ) \ { \ bli_zzadds( *(x + _i*rs_x + _j*cs_x), \ *(y + _i*rs_y + _j*cs_y) ); \ } \ } \ } \ } // adds_mxn_l #define bli_ssadds_mxn_l( diagoff, m, n, x, rs_x, cs_x, y, rs_y, cs_y ) \ { \ dim_t _i, _j; \ \ for ( _j = 0; _j < n; ++_j ) \ { \ for ( _i = 0; _i < m; ++_i ) \ { \ if ( (doff_t)_j - (doff_t)_i <= diagoff ) \ { \ bli_ssadds( *(x + _i*rs_x + _j*cs_x), \ *(y + _i*rs_y + _j*cs_y) ); \ } \ } \ } \ } #define bli_ddadds_mxn_l( diagoff, m, n, x, rs_x, cs_x, y, rs_y, cs_y ) \ { \ dim_t _i, _j; \ \ for ( _j = 0; _j < n; ++_j ) \ { \ for ( _i = 0; _i < m; ++_i ) \ { \ if ( (doff_t)_j - (doff_t)_i <= diagoff ) \ { \ bli_ddadds( *(x + _i*rs_x + _j*cs_x), \ *(y + _i*rs_y + _j*cs_y) ); \ } \ } \ } \ } #define bli_ccadds_mxn_l( diagoff, m, n, x, rs_x, cs_x, y, rs_y, cs_y ) \ { \ dim_t _i, _j; \ \ for ( _j = 0; _j < n; ++_j ) \ { \ for ( _i = 0; _i < m; ++_i ) \ { \ if ( (doff_t)_j - (doff_t)_i <= diagoff ) \ { \ bli_ccadds( *(x + _i*rs_x + _j*cs_x), \ *(y + _i*rs_y + _j*cs_y) ); \ } \ } \ } \ } #define bli_zzadds_mxn_l( diagoff, m, n, x, rs_x, cs_x, y, rs_y, cs_y ) \ { \ dim_t _i, _j; \ \ for ( _j = 0; _j < n; ++_j ) \ { \ for ( _i = 0; _i < m; ++_i ) \ { \ if ( (doff_t)_j - (doff_t)_i <= diagoff ) \ { \ bli_zzadds( *(x + _i*rs_x + _j*cs_x), \ *(y + _i*rs_y + _j*cs_y) ); \ } \ } \ } \ } #define bli_sadds_mxn_u( diagoff, m, n, x, rs_x, cs_x, y, rs_y, cs_y ) \ { \ bli_ssadds_mxn_u( diagoff, m, n, x, rs_x, cs_x, y, rs_y, cs_y ); \ } #define bli_dadds_mxn_u( diagoff, m, n, x, rs_x, cs_x, y, rs_y, cs_y ) \ { \ bli_ddadds_mxn_u( diagoff, m, n, x, rs_x, cs_x, y, rs_y, cs_y ); \ } #define bli_cadds_mxn_u( diagoff, m, n, x, rs_x, cs_x, y, rs_y, cs_y ) \ { \ bli_ccadds_mxn_u( diagoff, m, n, x, rs_x, cs_x, y, rs_y, cs_y ); \ } #define bli_zadds_mxn_u( diagoff, m, n, x, rs_x, cs_x, y, rs_y, cs_y ) \ { \ bli_zzadds_mxn_u( diagoff, m, n, x, rs_x, cs_x, y, rs_y, cs_y ); \ } #define bli_sadds_mxn_l( diagoff, m, n, x, rs_x, cs_x, y, rs_y, cs_y ) \ { \ bli_ssadds_mxn_l( diagoff, m, n, x, rs_x, cs_x, y, rs_y, cs_y ); \ } #define bli_dadds_mxn_l( diagoff, m, n, x, rs_x, cs_x, y, rs_y, cs_y ) \ { \ bli_ddadds_mxn_l( diagoff, m, n, x, rs_x, cs_x, y, rs_y, cs_y ); \ } #define bli_cadds_mxn_l( diagoff, m, n, x, rs_x, cs_x, y, rs_y, cs_y ) \ { \ bli_ccadds_mxn_l( diagoff, m, n, x, rs_x, cs_x, y, rs_y, cs_y ); \ } #define bli_zadds_mxn_l( diagoff, m, n, x, rs_x, cs_x, y, rs_y, cs_y ) \ { \ bli_zzadds_mxn_l( diagoff, m, n, x, rs_x, cs_x, y, rs_y, cs_y ); \ } #endif blis-0.9.0/frame/include/level0/bli_axmys.h000066400000000000000000000312231422157504600205240ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_AXMYS_H #define BLIS_AXMYS_H // axmys // Notes: // - The first char encodes the type of a. // - The second char encodes the type of x. // - The third char encodes the type of y. // -- (axy) = (??s) ------------------------------------------------------------ #define bli_sssaxmys( a, x, y ) bli_saxmyris( bli_sreal(a), bli_simag(a), bli_sreal(x), bli_simag(x), bli_sreal(y), bli_simag(y) ) #define bli_dssaxmys( a, x, y ) bli_saxmyris( bli_dreal(a), bli_dimag(a), bli_sreal(x), bli_simag(x), bli_sreal(y), bli_simag(y) ) #define bli_cssaxmys( a, x, y ) bli_saxmyris( bli_creal(a), bli_cimag(a), bli_sreal(x), bli_simag(x), bli_sreal(y), bli_simag(y) ) #define bli_zssaxmys( a, x, y ) bli_saxmyris( bli_zreal(a), bli_zimag(a), bli_sreal(x), bli_simag(x), bli_sreal(y), bli_simag(y) ) #define bli_sdsaxmys( a, x, y ) bli_saxmyris( bli_sreal(a), bli_simag(a), bli_dreal(x), bli_dimag(x), bli_sreal(y), bli_simag(y) ) #define bli_ddsaxmys( a, x, y ) bli_saxmyris( bli_dreal(a), bli_dimag(a), bli_dreal(x), bli_dimag(x), bli_sreal(y), bli_simag(y) ) #define bli_cdsaxmys( a, x, y ) bli_saxmyris( bli_creal(a), bli_cimag(a), bli_dreal(x), bli_dimag(x), bli_sreal(y), bli_simag(y) ) #define bli_zdsaxmys( a, x, y ) bli_saxmyris( bli_zreal(a), bli_zimag(a), bli_dreal(x), bli_dimag(x), bli_sreal(y), bli_simag(y) ) #define bli_scsaxmys( a, x, y ) bli_saxmyris( bli_sreal(a), bli_simag(a), bli_creal(x), bli_cimag(x), bli_sreal(y), bli_simag(y) ) #define bli_dcsaxmys( a, x, y ) bli_saxmyris( bli_dreal(a), bli_dimag(a), bli_creal(x), bli_cimag(x), bli_sreal(y), bli_simag(y) ) #define bli_ccsaxmys( a, x, y ) bli_saxmyris( bli_creal(a), bli_cimag(a), bli_creal(x), bli_cimag(x), bli_sreal(y), bli_simag(y) ) #define bli_zcsaxmys( a, x, y ) bli_saxmyris( bli_zreal(a), bli_zimag(a), bli_creal(x), bli_cimag(x), bli_sreal(y), bli_simag(y) ) #define bli_szsaxmys( a, x, y ) bli_saxmyris( bli_sreal(a), bli_simag(a), bli_zreal(x), bli_zimag(x), bli_sreal(y), bli_simag(y) ) #define bli_dzsaxmys( a, x, y ) bli_saxmyris( bli_dreal(a), bli_dimag(a), bli_zreal(x), bli_zimag(x), bli_sreal(y), bli_simag(y) ) #define bli_czsaxmys( a, x, y ) bli_saxmyris( bli_creal(a), bli_cimag(a), bli_zreal(x), bli_zimag(x), bli_sreal(y), bli_simag(y) ) #define bli_zzsaxmys( a, x, y ) bli_saxmyris( bli_zreal(a), bli_zimag(a), bli_zreal(x), bli_zimag(x), bli_sreal(y), bli_simag(y) ) // -- (axy) = (??d) ------------------------------------------------------------ #define bli_ssdaxmys( a, x, y ) bli_daxmyris( bli_sreal(a), bli_simag(a), bli_sreal(x), bli_simag(x), bli_dreal(y), bli_dimag(y) ) #define bli_dsdaxmys( a, x, y ) bli_daxmyris( bli_dreal(a), bli_dimag(a), bli_sreal(x), bli_simag(x), bli_dreal(y), bli_dimag(y) ) #define bli_csdaxmys( a, x, y ) bli_daxmyris( bli_creal(a), bli_cimag(a), bli_sreal(x), bli_simag(x), bli_dreal(y), bli_dimag(y) ) #define bli_zsdaxmys( a, x, y ) bli_daxmyris( bli_zreal(a), bli_zimag(a), bli_sreal(x), bli_simag(x), bli_dreal(y), bli_dimag(y) ) #define bli_sddaxmys( a, x, y ) bli_daxmyris( bli_sreal(a), bli_simag(a), bli_dreal(x), bli_dimag(x), bli_dreal(y), bli_dimag(y) ) #define bli_dddaxmys( a, x, y ) bli_daxmyris( bli_dreal(a), bli_dimag(a), bli_dreal(x), bli_dimag(x), bli_dreal(y), bli_dimag(y) ) #define bli_cddaxmys( a, x, y ) bli_daxmyris( bli_creal(a), bli_cimag(a), bli_dreal(x), bli_dimag(x), bli_dreal(y), bli_dimag(y) ) #define bli_zddaxmys( a, x, y ) bli_daxmyris( bli_zreal(a), bli_zimag(a), bli_dreal(x), bli_dimag(x), bli_dreal(y), bli_dimag(y) ) #define bli_scdaxmys( a, x, y ) bli_daxmyris( bli_sreal(a), bli_simag(a), bli_creal(x), bli_cimag(x), bli_dreal(y), bli_dimag(y) ) #define bli_dcdaxmys( a, x, y ) bli_daxmyris( bli_dreal(a), bli_dimag(a), bli_creal(x), bli_cimag(x), bli_dreal(y), bli_dimag(y) ) #define bli_ccdaxmys( a, x, y ) bli_daxmyris( bli_creal(a), bli_cimag(a), bli_creal(x), bli_cimag(x), bli_dreal(y), bli_dimag(y) ) #define bli_zcdaxmys( a, x, y ) bli_daxmyris( bli_zreal(a), bli_zimag(a), bli_creal(x), bli_cimag(x), bli_dreal(y), bli_dimag(y) ) #define bli_szdaxmys( a, x, y ) bli_daxmyris( bli_sreal(a), bli_simag(a), bli_zreal(x), bli_zimag(x), bli_dreal(y), bli_dimag(y) ) #define bli_dzdaxmys( a, x, y ) bli_daxmyris( bli_dreal(a), bli_dimag(a), bli_zreal(x), bli_zimag(x), bli_dreal(y), bli_dimag(y) ) #define bli_czdaxmys( a, x, y ) bli_daxmyris( bli_creal(a), bli_cimag(a), bli_zreal(x), bli_zimag(x), bli_dreal(y), bli_dimag(y) ) #define bli_zzdaxmys( a, x, y ) bli_daxmyris( bli_zreal(a), bli_zimag(a), bli_zreal(x), bli_zimag(x), bli_dreal(y), bli_dimag(y) ) #ifndef BLIS_ENABLE_C99_COMPLEX // -- (axy) = (??c) ------------------------------------------------------------ #define bli_sscaxmys( a, x, y ) bli_saxmyris( bli_sreal(a), bli_simag(a), bli_sreal(x), bli_simag(x), bli_creal(y), bli_cimag(y) ) #define bli_dscaxmys( a, x, y ) bli_saxmyris( bli_dreal(a), bli_dimag(a), bli_sreal(x), bli_simag(x), bli_creal(y), bli_cimag(y) ) #define bli_cscaxmys( a, x, y ) bli_caxmyris( bli_creal(a), bli_cimag(a), bli_sreal(x), bli_simag(x), bli_creal(y), bli_cimag(y) ) #define bli_zscaxmys( a, x, y ) bli_caxmyris( bli_zreal(a), bli_zimag(a), bli_sreal(x), bli_simag(x), bli_creal(y), bli_cimag(y) ) #define bli_sdcaxmys( a, x, y ) bli_saxmyris( bli_sreal(a), bli_simag(a), bli_dreal(x), bli_dimag(x), bli_creal(y), bli_cimag(y) ) #define bli_ddcaxmys( a, x, y ) bli_saxmyris( bli_dreal(a), bli_dimag(a), bli_dreal(x), bli_dimag(x), bli_creal(y), bli_cimag(y) ) #define bli_cdcaxmys( a, x, y ) bli_caxmyris( bli_creal(a), bli_cimag(a), bli_dreal(x), bli_dimag(x), bli_creal(y), bli_cimag(y) ) #define bli_zdcaxmys( a, x, y ) bli_caxmyris( bli_zreal(a), bli_zimag(a), bli_dreal(x), bli_dimag(x), bli_creal(y), bli_cimag(y) ) #define bli_sccaxmys( a, x, y ) bli_scaxmyris( bli_sreal(a), bli_simag(a), bli_creal(x), bli_cimag(x), bli_creal(y), bli_cimag(y) ) #define bli_dccaxmys( a, x, y ) bli_scaxmyris( bli_dreal(a), bli_dimag(a), bli_creal(x), bli_cimag(x), bli_creal(y), bli_cimag(y) ) #define bli_cccaxmys( a, x, y ) bli_caxmyris( bli_creal(a), bli_cimag(a), bli_creal(x), bli_cimag(x), bli_creal(y), bli_cimag(y) ) #define bli_zccaxmys( a, x, y ) bli_caxmyris( bli_zreal(a), bli_zimag(a), bli_creal(x), bli_cimag(x), bli_creal(y), bli_cimag(y) ) #define bli_szcaxmys( a, x, y ) bli_scaxmyris( bli_sreal(a), bli_simag(a), bli_zreal(x), bli_zimag(x), bli_creal(y), bli_cimag(y) ) #define bli_dzcaxmys( a, x, y ) bli_scaxmyris( bli_dreal(a), bli_dimag(a), bli_zreal(x), bli_zimag(x), bli_creal(y), bli_cimag(y) ) #define bli_czcaxmys( a, x, y ) bli_caxmyris( bli_creal(a), bli_cimag(a), bli_zreal(x), bli_zimag(x), bli_creal(y), bli_cimag(y) ) #define bli_zzcaxmys( a, x, y ) bli_caxmyris( bli_zreal(a), bli_zimag(a), bli_zreal(x), bli_zimag(x), bli_creal(y), bli_cimag(y) ) // -- (axy) = (??z) ------------------------------------------------------------ #define bli_sszaxmys( a, x, y ) bli_daxmyris( bli_sreal(a), bli_simag(a), bli_sreal(x), bli_simag(x), bli_zreal(y), bli_zimag(y) ) #define bli_dszaxmys( a, x, y ) bli_daxmyris( bli_dreal(a), bli_dimag(a), bli_sreal(x), bli_simag(x), bli_zreal(y), bli_zimag(y) ) #define bli_cszaxmys( a, x, y ) bli_zaxmyris( bli_creal(a), bli_cimag(a), bli_sreal(x), bli_simag(x), bli_zreal(y), bli_zimag(y) ) #define bli_zszaxmys( a, x, y ) bli_zaxmyris( bli_zreal(a), bli_zimag(a), bli_sreal(x), bli_simag(x), bli_zreal(y), bli_zimag(y) ) #define bli_sdzaxmys( a, x, y ) bli_daxmyris( bli_sreal(a), bli_simag(a), bli_dreal(x), bli_dimag(x), bli_zreal(y), bli_zimag(y) ) #define bli_ddzaxmys( a, x, y ) bli_daxmyris( bli_dreal(a), bli_dimag(a), bli_dreal(x), bli_dimag(x), bli_zreal(y), bli_zimag(y) ) #define bli_cdzaxmys( a, x, y ) bli_zaxmyris( bli_creal(a), bli_cimag(a), bli_dreal(x), bli_dimag(x), bli_zreal(y), bli_zimag(y) ) #define bli_zdzaxmys( a, x, y ) bli_zaxmyris( bli_zreal(a), bli_zimag(a), bli_dreal(x), bli_dimag(x), bli_zreal(y), bli_zimag(y) ) #define bli_sczaxmys( a, x, y ) bli_dzaxmyris( bli_sreal(a), bli_simag(a), bli_creal(x), bli_cimag(x), bli_zreal(y), bli_zimag(y) ) #define bli_dczaxmys( a, x, y ) bli_dzaxmyris( bli_dreal(a), bli_dimag(a), bli_creal(x), bli_cimag(x), bli_zreal(y), bli_zimag(y) ) #define bli_cczaxmys( a, x, y ) bli_zaxmyris( bli_creal(a), bli_cimag(a), bli_creal(x), bli_cimag(x), bli_zreal(y), bli_zimag(y) ) #define bli_zczaxmys( a, x, y ) bli_zaxmyris( bli_zreal(a), bli_zimag(a), bli_creal(x), bli_cimag(x), bli_zreal(y), bli_zimag(y) ) #define bli_szzaxmys( a, x, y ) bli_dzaxmyris( bli_sreal(a), bli_simag(a), bli_zreal(x), bli_zimag(x), bli_zreal(y), bli_zimag(y) ) #define bli_dzzaxmys( a, x, y ) bli_dzaxmyris( bli_dreal(a), bli_dimag(a), bli_zreal(x), bli_zimag(x), bli_zreal(y), bli_zimag(y) ) #define bli_czzaxmys( a, x, y ) bli_zaxmyris( bli_creal(a), bli_cimag(a), bli_zreal(x), bli_zimag(x), bli_zreal(y), bli_zimag(y) ) #define bli_zzzaxmys( a, x, y ) bli_zaxmyris( bli_zreal(a), bli_zimag(a), bli_zreal(x), bli_zimag(x), bli_zreal(y), bli_zimag(y) ) #else // ifdef BLIS_ENABLE_C99_COMPLEX // -- (axy) = (??c) ------------------------------------------------------------ #define bli_sscaxmys( a, x, y ) { (y) -= (a) * (x); } #define bli_dscaxmys( a, x, y ) { (y) -= (a) * (x); } #define bli_cscaxmys( a, x, y ) { (y) -= (a) * (x); } #define bli_zscaxmys( a, x, y ) { (y) -= (a) * (x); } #define bli_sdcaxmys( a, x, y ) { (y) -= (a) * (x); } #define bli_ddcaxmys( a, x, y ) { (y) -= (a) * (x); } #define bli_cdcaxmys( a, x, y ) { (y) -= (a) * (x); } #define bli_zdcaxmys( a, x, y ) { (y) -= (a) * (x); } #define bli_sccaxmys( a, x, y ) { (y) -= (a) * (x); } #define bli_dccaxmys( a, x, y ) { (y) -= (a) * (x); } #define bli_cccaxmys( a, x, y ) { (y) -= (a) * (x); } #define bli_zccaxmys( a, x, y ) { (y) -= (a) * (x); } #define bli_szcaxmys( a, x, y ) { (y) -= (a) * (x); } #define bli_dzcaxmys( a, x, y ) { (y) -= (a) * (x); } #define bli_czcaxmys( a, x, y ) { (y) -= (a) * (x); } #define bli_zzcaxmys( a, x, y ) { (y) -= (a) * (x); } // -- (axy) = (??z) ------------------------------------------------------------ #define bli_sszaxmys( a, x, y ) { (y) -= (a) * (x); } #define bli_dszaxmys( a, x, y ) { (y) -= (a) * (x); } #define bli_cszaxmys( a, x, y ) { (y) -= (a) * (x); } #define bli_zszaxmys( a, x, y ) { (y) -= (a) * (x); } #define bli_sdzaxmys( a, x, y ) { (y) -= (a) * (x); } #define bli_ddzaxmys( a, x, y ) { (y) -= (a) * (x); } #define bli_cdzaxmys( a, x, y ) { (y) -= (a) * (x); } #define bli_zdzaxmys( a, x, y ) { (y) -= (a) * (x); } #define bli_sczaxmys( a, x, y ) { (y) -= (a) * (x); } #define bli_dczaxmys( a, x, y ) { (y) -= (a) * (x); } #define bli_cczaxmys( a, x, y ) { (y) -= (a) * (x); } #define bli_zczaxmys( a, x, y ) { (y) -= (a) * (x); } #define bli_szzaxmys( a, x, y ) { (y) -= (a) * (x); } #define bli_dzzaxmys( a, x, y ) { (y) -= (a) * (x); } #define bli_czzaxmys( a, x, y ) { (y) -= (a) * (x); } #define bli_zzzaxmys( a, x, y ) { (y) -= (a) * (x); } #endif // BLIS_ENABLE_C99_COMPLEX #define bli_saxmys( a, x, y ) bli_sssaxmys( a, x, y ) #define bli_daxmys( a, x, y ) bli_dddaxmys( a, x, y ) #define bli_caxmys( a, x, y ) bli_cccaxmys( a, x, y ) #define bli_zaxmys( a, x, y ) bli_zzzaxmys( a, x, y ) #endif blis-0.9.0/frame/include/level0/bli_axpbyjs.h000066400000000000000000001552001422157504600210450ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_AXPBYJS_H #define BLIS_AXPBYJS_H // axpbyjs // Notes: // - The first char encodes the type of a. // - The second char encodes the type of x. // - The third char encodes the type of b. // - The fourth char encodes the type of y. // -- (axby) = (???s) ---------------------------------------------------------- #define bli_ssssaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_sreal(a), bli_simag(a), bli_sreal(x), bli_simag(x), bli_sreal(b), bli_simag(b), bli_sreal(y), bli_simag(y) ) #define bli_dsssaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_dreal(a), bli_dimag(a), bli_sreal(x), bli_simag(x), bli_sreal(b), bli_simag(b), bli_sreal(y), bli_simag(y) ) #define bli_csssaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_creal(a), bli_cimag(a), bli_sreal(x), bli_simag(x), bli_sreal(b), bli_simag(b), bli_sreal(y), bli_simag(y) ) #define bli_zsssaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_zreal(a), bli_zimag(a), bli_sreal(x), bli_simag(x), bli_sreal(b), bli_simag(b), bli_sreal(y), bli_simag(y) ) #define bli_sdssaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_sreal(a), bli_simag(a), bli_dreal(x), bli_dimag(x), bli_sreal(b), bli_simag(b), bli_sreal(y), bli_simag(y) ) #define bli_ddssaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_dreal(a), bli_dimag(a), bli_dreal(x), bli_dimag(x), bli_sreal(b), bli_simag(b), bli_sreal(y), bli_simag(y) ) #define bli_cdssaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_creal(a), bli_cimag(a), bli_dreal(x), bli_dimag(x), bli_sreal(b), bli_simag(b), bli_sreal(y), bli_simag(y) ) #define bli_zdssaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_zreal(a), bli_zimag(a), bli_dreal(x), bli_dimag(x), bli_sreal(b), bli_simag(b), bli_sreal(y), bli_simag(y) ) #define bli_scssaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_sreal(a), bli_simag(a), bli_creal(x), bli_cimag(x), bli_sreal(b), bli_simag(b), bli_sreal(y), bli_simag(y) ) #define bli_dcssaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_dreal(a), bli_dimag(a), bli_creal(x), bli_cimag(x), bli_sreal(b), bli_simag(b), bli_sreal(y), bli_simag(y) ) #define bli_ccssaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_creal(a), bli_cimag(a), bli_creal(x), bli_cimag(x), bli_sreal(b), bli_simag(b), bli_sreal(y), bli_simag(y) ) #define bli_zcssaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_zreal(a), bli_zimag(a), bli_creal(x), bli_cimag(x), bli_sreal(b), bli_simag(b), bli_sreal(y), bli_simag(y) ) #define bli_szssaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_sreal(a), bli_simag(a), bli_zreal(x), bli_zimag(x), bli_sreal(b), bli_simag(b), bli_sreal(y), bli_simag(y) ) #define bli_dzssaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_dreal(a), bli_dimag(a), bli_zreal(x), bli_zimag(x), bli_sreal(b), bli_simag(b), bli_sreal(y), bli_simag(y) ) #define bli_czssaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_creal(a), bli_cimag(a), bli_zreal(x), bli_zimag(x), bli_sreal(b), bli_simag(b), bli_sreal(y), bli_simag(y) ) #define bli_zzssaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_zreal(a), bli_zimag(a), bli_zreal(x), bli_zimag(x), bli_sreal(b), bli_simag(b), bli_sreal(y), bli_simag(y) ) #define bli_ssdsaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_sreal(a), bli_simag(a), bli_sreal(x), bli_simag(x), bli_dreal(b), bli_dimag(b), bli_sreal(y), bli_simag(y) ) #define bli_dsdsaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_dreal(a), bli_dimag(a), bli_sreal(x), bli_simag(x), bli_dreal(b), bli_dimag(b), bli_sreal(y), bli_simag(y) ) #define bli_csdsaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_creal(a), bli_cimag(a), bli_sreal(x), bli_simag(x), bli_dreal(b), bli_dimag(b), bli_sreal(y), bli_simag(y) ) #define bli_zsdsaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_zreal(a), bli_zimag(a), bli_sreal(x), bli_simag(x), bli_dreal(b), bli_dimag(b), bli_sreal(y), bli_simag(y) ) #define bli_sddsaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_sreal(a), bli_simag(a), bli_dreal(x), bli_dimag(x), bli_dreal(b), bli_dimag(b), bli_sreal(y), bli_simag(y) ) #define bli_dddsaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_dreal(a), bli_dimag(a), bli_dreal(x), bli_dimag(x), bli_dreal(b), bli_dimag(b), bli_sreal(y), bli_simag(y) ) #define bli_cddsaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_creal(a), bli_cimag(a), bli_dreal(x), bli_dimag(x), bli_dreal(b), bli_dimag(b), bli_sreal(y), bli_simag(y) ) #define bli_zddsaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_zreal(a), bli_zimag(a), bli_dreal(x), bli_dimag(x), bli_dreal(b), bli_dimag(b), bli_sreal(y), bli_simag(y) ) #define bli_scdsaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_sreal(a), bli_simag(a), bli_creal(x), bli_cimag(x), bli_dreal(b), bli_dimag(b), bli_sreal(y), bli_simag(y) ) #define bli_dcdsaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_dreal(a), bli_dimag(a), bli_creal(x), bli_cimag(x), bli_dreal(b), bli_dimag(b), bli_sreal(y), bli_simag(y) ) #define bli_ccdsaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_creal(a), bli_cimag(a), bli_creal(x), bli_cimag(x), bli_dreal(b), bli_dimag(b), bli_sreal(y), bli_simag(y) ) #define bli_zcdsaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_zreal(a), bli_zimag(a), bli_creal(x), bli_cimag(x), bli_dreal(b), bli_dimag(b), bli_sreal(y), bli_simag(y) ) #define bli_szdsaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_sreal(a), bli_simag(a), bli_zreal(x), bli_zimag(x), bli_dreal(b), bli_dimag(b), bli_sreal(y), bli_simag(y) ) #define bli_dzdsaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_dreal(a), bli_dimag(a), bli_zreal(x), bli_zimag(x), bli_dreal(b), bli_dimag(b), bli_sreal(y), bli_simag(y) ) #define bli_czdsaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_creal(a), bli_cimag(a), bli_zreal(x), bli_zimag(x), bli_dreal(b), bli_dimag(b), bli_sreal(y), bli_simag(y) ) #define bli_zzdsaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_zreal(a), bli_zimag(a), bli_zreal(x), bli_zimag(x), bli_dreal(b), bli_dimag(b), bli_sreal(y), bli_simag(y) ) #define bli_sscsaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_sreal(a), bli_simag(a), bli_sreal(x), bli_simag(x), bli_creal(b), bli_cimag(b), bli_sreal(y), bli_simag(y) ) #define bli_dscsaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_dreal(a), bli_dimag(a), bli_sreal(x), bli_simag(x), bli_creal(b), bli_cimag(b), bli_sreal(y), bli_simag(y) ) #define bli_cscsaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_creal(a), bli_cimag(a), bli_sreal(x), bli_simag(x), bli_creal(b), bli_cimag(b), bli_sreal(y), bli_simag(y) ) #define bli_zscsaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_zreal(a), bli_zimag(a), bli_sreal(x), bli_simag(x), bli_creal(b), bli_cimag(b), bli_sreal(y), bli_simag(y) ) #define bli_sdcsaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_sreal(a), bli_simag(a), bli_dreal(x), bli_dimag(x), bli_creal(b), bli_cimag(b), bli_sreal(y), bli_simag(y) ) #define bli_ddcsaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_dreal(a), bli_dimag(a), bli_dreal(x), bli_dimag(x), bli_creal(b), bli_cimag(b), bli_sreal(y), bli_simag(y) ) #define bli_cdcsaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_creal(a), bli_cimag(a), bli_dreal(x), bli_dimag(x), bli_creal(b), bli_cimag(b), bli_sreal(y), bli_simag(y) ) #define bli_zdcsaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_zreal(a), bli_zimag(a), bli_dreal(x), bli_dimag(x), bli_creal(b), bli_cimag(b), bli_sreal(y), bli_simag(y) ) #define bli_sccsaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_sreal(a), bli_simag(a), bli_creal(x), bli_cimag(x), bli_creal(b), bli_cimag(b), bli_sreal(y), bli_simag(y) ) #define bli_dccsaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_dreal(a), bli_dimag(a), bli_creal(x), bli_cimag(x), bli_creal(b), bli_cimag(b), bli_sreal(y), bli_simag(y) ) #define bli_cccsaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_creal(a), bli_cimag(a), bli_creal(x), bli_cimag(x), bli_creal(b), bli_cimag(b), bli_sreal(y), bli_simag(y) ) #define bli_zccsaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_zreal(a), bli_zimag(a), bli_creal(x), bli_cimag(x), bli_creal(b), bli_cimag(b), bli_sreal(y), bli_simag(y) ) #define bli_szcsaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_sreal(a), bli_simag(a), bli_zreal(x), bli_zimag(x), bli_creal(b), bli_cimag(b), bli_sreal(y), bli_simag(y) ) #define bli_dzcsaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_dreal(a), bli_dimag(a), bli_zreal(x), bli_zimag(x), bli_creal(b), bli_cimag(b), bli_sreal(y), bli_simag(y) ) #define bli_czcsaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_creal(a), bli_cimag(a), bli_zreal(x), bli_zimag(x), bli_creal(b), bli_cimag(b), bli_sreal(y), bli_simag(y) ) #define bli_zzcsaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_zreal(a), bli_zimag(a), bli_zreal(x), bli_zimag(x), bli_creal(b), bli_cimag(b), bli_sreal(y), bli_simag(y) ) #define bli_sszsaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_sreal(a), bli_simag(a), bli_sreal(x), bli_simag(x), bli_zreal(b), bli_zimag(b), bli_sreal(y), bli_simag(y) ) #define bli_dszsaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_dreal(a), bli_dimag(a), bli_sreal(x), bli_simag(x), bli_zreal(b), bli_zimag(b), bli_sreal(y), bli_simag(y) ) #define bli_cszsaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_creal(a), bli_cimag(a), bli_sreal(x), bli_simag(x), bli_zreal(b), bli_zimag(b), bli_sreal(y), bli_simag(y) ) #define bli_zszsaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_zreal(a), bli_zimag(a), bli_sreal(x), bli_simag(x), bli_zreal(b), bli_zimag(b), bli_sreal(y), bli_simag(y) ) #define bli_sdzsaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_sreal(a), bli_simag(a), bli_dreal(x), bli_dimag(x), bli_zreal(b), bli_zimag(b), bli_sreal(y), bli_simag(y) ) #define bli_ddzsaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_dreal(a), bli_dimag(a), bli_dreal(x), bli_dimag(x), bli_zreal(b), bli_zimag(b), bli_sreal(y), bli_simag(y) ) #define bli_cdzsaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_creal(a), bli_cimag(a), bli_dreal(x), bli_dimag(x), bli_zreal(b), bli_zimag(b), bli_sreal(y), bli_simag(y) ) #define bli_zdzsaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_zreal(a), bli_zimag(a), bli_dreal(x), bli_dimag(x), bli_zreal(b), bli_zimag(b), bli_sreal(y), bli_simag(y) ) #define bli_sczsaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_sreal(a), bli_simag(a), bli_creal(x), bli_cimag(x), bli_zreal(b), bli_zimag(b), bli_sreal(y), bli_simag(y) ) #define bli_dczsaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_dreal(a), bli_dimag(a), bli_creal(x), bli_cimag(x), bli_zreal(b), bli_zimag(b), bli_sreal(y), bli_simag(y) ) #define bli_cczsaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_creal(a), bli_cimag(a), bli_creal(x), bli_cimag(x), bli_zreal(b), bli_zimag(b), bli_sreal(y), bli_simag(y) ) #define bli_zczsaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_zreal(a), bli_zimag(a), bli_creal(x), bli_cimag(x), bli_zreal(b), bli_zimag(b), bli_sreal(y), bli_simag(y) ) #define bli_szzsaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_sreal(a), bli_simag(a), bli_zreal(x), bli_zimag(x), bli_zreal(b), bli_zimag(b), bli_sreal(y), bli_simag(y) ) #define bli_dzzsaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_dreal(a), bli_dimag(a), bli_zreal(x), bli_zimag(x), bli_zreal(b), bli_zimag(b), bli_sreal(y), bli_simag(y) ) #define bli_czzsaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_creal(a), bli_cimag(a), bli_zreal(x), bli_zimag(x), bli_zreal(b), bli_zimag(b), bli_sreal(y), bli_simag(y) ) #define bli_zzzsaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_zreal(a), bli_zimag(a), bli_zreal(x), bli_zimag(x), bli_zreal(b), bli_zimag(b), bli_sreal(y), bli_simag(y) ) // -- (axby) = (???d) ---------------------------------------------------------- #define bli_sssdaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_sreal(a), bli_simag(a), bli_sreal(x), bli_simag(x), bli_sreal(b), bli_simag(b), bli_dreal(y), bli_dimag(y) ) #define bli_dssdaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_dreal(a), bli_dimag(a), bli_sreal(x), bli_simag(x), bli_sreal(b), bli_simag(b), bli_dreal(y), bli_dimag(y) ) #define bli_cssdaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_creal(a), bli_cimag(a), bli_sreal(x), bli_simag(x), bli_sreal(b), bli_simag(b), bli_dreal(y), bli_dimag(y) ) #define bli_zssdaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_zreal(a), bli_zimag(a), bli_sreal(x), bli_simag(x), bli_sreal(b), bli_simag(b), bli_dreal(y), bli_dimag(y) ) #define bli_sdsdaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_sreal(a), bli_simag(a), bli_dreal(x), bli_dimag(x), bli_sreal(b), bli_simag(b), bli_dreal(y), bli_dimag(y) ) #define bli_ddsdaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_dreal(a), bli_dimag(a), bli_dreal(x), bli_dimag(x), bli_sreal(b), bli_simag(b), bli_dreal(y), bli_dimag(y) ) #define bli_cdsdaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_creal(a), bli_cimag(a), bli_dreal(x), bli_dimag(x), bli_sreal(b), bli_simag(b), bli_dreal(y), bli_dimag(y) ) #define bli_zdsdaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_zreal(a), bli_zimag(a), bli_dreal(x), bli_dimag(x), bli_sreal(b), bli_simag(b), bli_dreal(y), bli_dimag(y) ) #define bli_scsdaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_sreal(a), bli_simag(a), bli_creal(x), bli_cimag(x), bli_sreal(b), bli_simag(b), bli_dreal(y), bli_dimag(y) ) #define bli_dcsdaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_dreal(a), bli_dimag(a), bli_creal(x), bli_cimag(x), bli_sreal(b), bli_simag(b), bli_dreal(y), bli_dimag(y) ) #define bli_ccsdaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_creal(a), bli_cimag(a), bli_creal(x), bli_cimag(x), bli_sreal(b), bli_simag(b), bli_dreal(y), bli_dimag(y) ) #define bli_zcsdaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_zreal(a), bli_zimag(a), bli_creal(x), bli_cimag(x), bli_sreal(b), bli_simag(b), bli_dreal(y), bli_dimag(y) ) #define bli_szsdaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_sreal(a), bli_simag(a), bli_zreal(x), bli_zimag(x), bli_sreal(b), bli_simag(b), bli_dreal(y), bli_dimag(y) ) #define bli_dzsdaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_dreal(a), bli_dimag(a), bli_zreal(x), bli_zimag(x), bli_sreal(b), bli_simag(b), bli_dreal(y), bli_dimag(y) ) #define bli_czsdaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_creal(a), bli_cimag(a), bli_zreal(x), bli_zimag(x), bli_sreal(b), bli_simag(b), bli_dreal(y), bli_dimag(y) ) #define bli_zzsdaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_zreal(a), bli_zimag(a), bli_zreal(x), bli_zimag(x), bli_sreal(b), bli_simag(b), bli_dreal(y), bli_dimag(y) ) #define bli_ssddaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_sreal(a), bli_simag(a), bli_sreal(x), bli_simag(x), bli_dreal(b), bli_dimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_dsddaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_dreal(a), bli_dimag(a), bli_sreal(x), bli_simag(x), bli_dreal(b), bli_dimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_csddaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_creal(a), bli_cimag(a), bli_sreal(x), bli_simag(x), bli_dreal(b), bli_dimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_zsddaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_zreal(a), bli_zimag(a), bli_sreal(x), bli_simag(x), bli_dreal(b), bli_dimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_sdddaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_sreal(a), bli_simag(a), bli_dreal(x), bli_dimag(x), bli_dreal(b), bli_dimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_ddddaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_dreal(a), bli_dimag(a), bli_dreal(x), bli_dimag(x), bli_dreal(b), bli_dimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_cdddaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_creal(a), bli_cimag(a), bli_dreal(x), bli_dimag(x), bli_dreal(b), bli_dimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_zdddaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_zreal(a), bli_zimag(a), bli_dreal(x), bli_dimag(x), bli_dreal(b), bli_dimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_scddaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_sreal(a), bli_simag(a), bli_creal(x), bli_cimag(x), bli_dreal(b), bli_dimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_dcddaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_dreal(a), bli_dimag(a), bli_creal(x), bli_cimag(x), bli_dreal(b), bli_dimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_ccddaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_creal(a), bli_cimag(a), bli_creal(x), bli_cimag(x), bli_dreal(b), bli_dimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_zcddaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_zreal(a), bli_zimag(a), bli_creal(x), bli_cimag(x), bli_dreal(b), bli_dimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_szddaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_sreal(a), bli_simag(a), bli_zreal(x), bli_zimag(x), bli_dreal(b), bli_dimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_dzddaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_dreal(a), bli_dimag(a), bli_zreal(x), bli_zimag(x), bli_dreal(b), bli_dimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_czddaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_creal(a), bli_cimag(a), bli_zreal(x), bli_zimag(x), bli_dreal(b), bli_dimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_zzddaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_zreal(a), bli_zimag(a), bli_zreal(x), bli_zimag(x), bli_dreal(b), bli_dimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_sscdaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_sreal(a), bli_simag(a), bli_sreal(x), bli_simag(x), bli_creal(b), bli_cimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_dscdaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_dreal(a), bli_dimag(a), bli_sreal(x), bli_simag(x), bli_creal(b), bli_cimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_cscdaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_creal(a), bli_cimag(a), bli_sreal(x), bli_simag(x), bli_creal(b), bli_cimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_zscdaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_zreal(a), bli_zimag(a), bli_sreal(x), bli_simag(x), bli_creal(b), bli_cimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_sdcdaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_sreal(a), bli_simag(a), bli_dreal(x), bli_dimag(x), bli_creal(b), bli_cimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_ddcdaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_dreal(a), bli_dimag(a), bli_dreal(x), bli_dimag(x), bli_creal(b), bli_cimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_cdcdaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_creal(a), bli_cimag(a), bli_dreal(x), bli_dimag(x), bli_creal(b), bli_cimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_zdcdaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_zreal(a), bli_zimag(a), bli_dreal(x), bli_dimag(x), bli_creal(b), bli_cimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_sccdaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_sreal(a), bli_simag(a), bli_creal(x), bli_cimag(x), bli_creal(b), bli_cimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_dccdaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_dreal(a), bli_dimag(a), bli_creal(x), bli_cimag(x), bli_creal(b), bli_cimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_cccdaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_creal(a), bli_cimag(a), bli_creal(x), bli_cimag(x), bli_creal(b), bli_cimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_zccdaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_zreal(a), bli_zimag(a), bli_creal(x), bli_cimag(x), bli_creal(b), bli_cimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_szcdaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_sreal(a), bli_simag(a), bli_zreal(x), bli_zimag(x), bli_creal(b), bli_cimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_dzcdaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_dreal(a), bli_dimag(a), bli_zreal(x), bli_zimag(x), bli_creal(b), bli_cimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_czcdaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_creal(a), bli_cimag(a), bli_zreal(x), bli_zimag(x), bli_creal(b), bli_cimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_zzcdaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_zreal(a), bli_zimag(a), bli_zreal(x), bli_zimag(x), bli_creal(b), bli_cimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_sszdaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_sreal(a), bli_simag(a), bli_sreal(x), bli_simag(x), bli_zreal(b), bli_zimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_dszdaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_dreal(a), bli_dimag(a), bli_sreal(x), bli_simag(x), bli_zreal(b), bli_zimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_cszdaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_creal(a), bli_cimag(a), bli_sreal(x), bli_simag(x), bli_zreal(b), bli_zimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_zszdaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_zreal(a), bli_zimag(a), bli_sreal(x), bli_simag(x), bli_zreal(b), bli_zimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_sdzdaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_sreal(a), bli_simag(a), bli_dreal(x), bli_dimag(x), bli_zreal(b), bli_zimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_ddzdaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_dreal(a), bli_dimag(a), bli_dreal(x), bli_dimag(x), bli_zreal(b), bli_zimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_cdzdaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_creal(a), bli_cimag(a), bli_dreal(x), bli_dimag(x), bli_zreal(b), bli_zimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_zdzdaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_zreal(a), bli_zimag(a), bli_dreal(x), bli_dimag(x), bli_zreal(b), bli_zimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_sczdaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_sreal(a), bli_simag(a), bli_creal(x), bli_cimag(x), bli_zreal(b), bli_zimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_dczdaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_dreal(a), bli_dimag(a), bli_creal(x), bli_cimag(x), bli_zreal(b), bli_zimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_cczdaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_creal(a), bli_cimag(a), bli_creal(x), bli_cimag(x), bli_zreal(b), bli_zimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_zczdaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_zreal(a), bli_zimag(a), bli_creal(x), bli_cimag(x), bli_zreal(b), bli_zimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_szzdaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_sreal(a), bli_simag(a), bli_zreal(x), bli_zimag(x), bli_zreal(b), bli_zimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_dzzdaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_dreal(a), bli_dimag(a), bli_zreal(x), bli_zimag(x), bli_zreal(b), bli_zimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_czzdaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_creal(a), bli_cimag(a), bli_zreal(x), bli_zimag(x), bli_zreal(b), bli_zimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_zzzdaxpbyjs( a, x, b, y ) bli_rxaxpbyjris( bli_zreal(a), bli_zimag(a), bli_zreal(x), bli_zimag(x), bli_zreal(b), bli_zimag(b), bli_dreal(y), bli_dimag(y) ) #ifndef BLIS_ENABLE_C99_COMPLEX // -- (axby) = (???c) ---------------------------------------------------------- #define bli_ssscaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_sreal(a), bli_simag(a), bli_sreal(x), bli_simag(x), bli_sreal(b), bli_simag(b), bli_creal(y), bli_cimag(y) ) #define bli_dsscaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_dreal(a), bli_dimag(a), bli_sreal(x), bli_simag(x), bli_sreal(b), bli_simag(b), bli_creal(y), bli_cimag(y) ) #define bli_csscaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_creal(a), bli_cimag(a), bli_sreal(x), bli_simag(x), bli_sreal(b), bli_simag(b), bli_creal(y), bli_cimag(y) ) #define bli_zsscaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_zreal(a), bli_zimag(a), bli_sreal(x), bli_simag(x), bli_sreal(b), bli_simag(b), bli_creal(y), bli_cimag(y) ) #define bli_sdscaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_sreal(a), bli_simag(a), bli_dreal(x), bli_dimag(x), bli_sreal(b), bli_simag(b), bli_creal(y), bli_cimag(y) ) #define bli_ddscaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_dreal(a), bli_dimag(a), bli_dreal(x), bli_dimag(x), bli_sreal(b), bli_simag(b), bli_creal(y), bli_cimag(y) ) #define bli_cdscaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_creal(a), bli_cimag(a), bli_dreal(x), bli_dimag(x), bli_sreal(b), bli_simag(b), bli_creal(y), bli_cimag(y) ) #define bli_zdscaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_zreal(a), bli_zimag(a), bli_dreal(x), bli_dimag(x), bli_sreal(b), bli_simag(b), bli_creal(y), bli_cimag(y) ) #define bli_scscaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_sreal(a), bli_simag(a), bli_creal(x), bli_cimag(x), bli_sreal(b), bli_simag(b), bli_creal(y), bli_cimag(y) ) #define bli_dcscaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_dreal(a), bli_dimag(a), bli_creal(x), bli_cimag(x), bli_sreal(b), bli_simag(b), bli_creal(y), bli_cimag(y) ) #define bli_ccscaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_creal(a), bli_cimag(a), bli_creal(x), bli_cimag(x), bli_sreal(b), bli_simag(b), bli_creal(y), bli_cimag(y) ) #define bli_zcscaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_zreal(a), bli_zimag(a), bli_creal(x), bli_cimag(x), bli_sreal(b), bli_simag(b), bli_creal(y), bli_cimag(y) ) #define bli_szscaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_sreal(a), bli_simag(a), bli_zreal(x), bli_zimag(x), bli_sreal(b), bli_simag(b), bli_creal(y), bli_cimag(y) ) #define bli_dzscaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_dreal(a), bli_dimag(a), bli_zreal(x), bli_zimag(x), bli_sreal(b), bli_simag(b), bli_creal(y), bli_cimag(y) ) #define bli_czscaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_creal(a), bli_cimag(a), bli_zreal(x), bli_zimag(x), bli_sreal(b), bli_simag(b), bli_creal(y), bli_cimag(y) ) #define bli_zzscaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_zreal(a), bli_zimag(a), bli_zreal(x), bli_zimag(x), bli_sreal(b), bli_simag(b), bli_creal(y), bli_cimag(y) ) #define bli_ssdcaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_sreal(a), bli_simag(a), bli_sreal(x), bli_simag(x), bli_dreal(b), bli_dimag(b), bli_creal(y), bli_cimag(y) ) #define bli_dsdcaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_dreal(a), bli_dimag(a), bli_sreal(x), bli_simag(x), bli_dreal(b), bli_dimag(b), bli_creal(y), bli_cimag(y) ) #define bli_csdcaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_creal(a), bli_cimag(a), bli_sreal(x), bli_simag(x), bli_dreal(b), bli_dimag(b), bli_creal(y), bli_cimag(y) ) #define bli_zsdcaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_zreal(a), bli_zimag(a), bli_sreal(x), bli_simag(x), bli_dreal(b), bli_dimag(b), bli_creal(y), bli_cimag(y) ) #define bli_sddcaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_sreal(a), bli_simag(a), bli_dreal(x), bli_dimag(x), bli_dreal(b), bli_dimag(b), bli_creal(y), bli_cimag(y) ) #define bli_dddcaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_dreal(a), bli_dimag(a), bli_dreal(x), bli_dimag(x), bli_dreal(b), bli_dimag(b), bli_creal(y), bli_cimag(y) ) #define bli_cddcaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_creal(a), bli_cimag(a), bli_dreal(x), bli_dimag(x), bli_dreal(b), bli_dimag(b), bli_creal(y), bli_cimag(y) ) #define bli_zddcaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_zreal(a), bli_zimag(a), bli_dreal(x), bli_dimag(x), bli_dreal(b), bli_dimag(b), bli_creal(y), bli_cimag(y) ) #define bli_scdcaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_sreal(a), bli_simag(a), bli_creal(x), bli_cimag(x), bli_dreal(b), bli_dimag(b), bli_creal(y), bli_cimag(y) ) #define bli_dcdcaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_dreal(a), bli_dimag(a), bli_creal(x), bli_cimag(x), bli_dreal(b), bli_dimag(b), bli_creal(y), bli_cimag(y) ) #define bli_ccdcaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_creal(a), bli_cimag(a), bli_creal(x), bli_cimag(x), bli_dreal(b), bli_dimag(b), bli_creal(y), bli_cimag(y) ) #define bli_zcdcaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_zreal(a), bli_zimag(a), bli_creal(x), bli_cimag(x), bli_dreal(b), bli_dimag(b), bli_creal(y), bli_cimag(y) ) #define bli_szdcaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_sreal(a), bli_simag(a), bli_zreal(x), bli_zimag(x), bli_dreal(b), bli_dimag(b), bli_creal(y), bli_cimag(y) ) #define bli_dzdcaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_dreal(a), bli_dimag(a), bli_zreal(x), bli_zimag(x), bli_dreal(b), bli_dimag(b), bli_creal(y), bli_cimag(y) ) #define bli_czdcaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_creal(a), bli_cimag(a), bli_zreal(x), bli_zimag(x), bli_dreal(b), bli_dimag(b), bli_creal(y), bli_cimag(y) ) #define bli_zzdcaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_zreal(a), bli_zimag(a), bli_zreal(x), bli_zimag(x), bli_dreal(b), bli_dimag(b), bli_creal(y), bli_cimag(y) ) #define bli_ssccaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_sreal(a), bli_simag(a), bli_sreal(x), bli_simag(x), bli_creal(b), bli_cimag(b), bli_creal(y), bli_cimag(y) ) #define bli_dsccaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_dreal(a), bli_dimag(a), bli_sreal(x), bli_simag(x), bli_creal(b), bli_cimag(b), bli_creal(y), bli_cimag(y) ) #define bli_csccaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_creal(a), bli_cimag(a), bli_sreal(x), bli_simag(x), bli_creal(b), bli_cimag(b), bli_creal(y), bli_cimag(y) ) #define bli_zsccaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_zreal(a), bli_zimag(a), bli_sreal(x), bli_simag(x), bli_creal(b), bli_cimag(b), bli_creal(y), bli_cimag(y) ) #define bli_sdccaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_sreal(a), bli_simag(a), bli_dreal(x), bli_dimag(x), bli_creal(b), bli_cimag(b), bli_creal(y), bli_cimag(y) ) #define bli_ddccaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_dreal(a), bli_dimag(a), bli_dreal(x), bli_dimag(x), bli_creal(b), bli_cimag(b), bli_creal(y), bli_cimag(y) ) #define bli_cdccaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_creal(a), bli_cimag(a), bli_dreal(x), bli_dimag(x), bli_creal(b), bli_cimag(b), bli_creal(y), bli_cimag(y) ) #define bli_zdccaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_zreal(a), bli_zimag(a), bli_dreal(x), bli_dimag(x), bli_creal(b), bli_cimag(b), bli_creal(y), bli_cimag(y) ) #define bli_scccaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_sreal(a), bli_simag(a), bli_creal(x), bli_cimag(x), bli_creal(b), bli_cimag(b), bli_creal(y), bli_cimag(y) ) #define bli_dcccaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_dreal(a), bli_dimag(a), bli_creal(x), bli_cimag(x), bli_creal(b), bli_cimag(b), bli_creal(y), bli_cimag(y) ) #define bli_ccccaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_creal(a), bli_cimag(a), bli_creal(x), bli_cimag(x), bli_creal(b), bli_cimag(b), bli_creal(y), bli_cimag(y) ) #define bli_zcccaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_zreal(a), bli_zimag(a), bli_creal(x), bli_cimag(x), bli_creal(b), bli_cimag(b), bli_creal(y), bli_cimag(y) ) #define bli_szccaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_sreal(a), bli_simag(a), bli_zreal(x), bli_zimag(x), bli_creal(b), bli_cimag(b), bli_creal(y), bli_cimag(y) ) #define bli_dzccaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_dreal(a), bli_dimag(a), bli_zreal(x), bli_zimag(x), bli_creal(b), bli_cimag(b), bli_creal(y), bli_cimag(y) ) #define bli_czccaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_creal(a), bli_cimag(a), bli_zreal(x), bli_zimag(x), bli_creal(b), bli_cimag(b), bli_creal(y), bli_cimag(y) ) #define bli_zzccaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_zreal(a), bli_zimag(a), bli_zreal(x), bli_zimag(x), bli_creal(b), bli_cimag(b), bli_creal(y), bli_cimag(y) ) #define bli_sszcaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_sreal(a), bli_simag(a), bli_sreal(x), bli_simag(x), bli_zreal(b), bli_zimag(b), bli_creal(y), bli_cimag(y) ) #define bli_dszcaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_dreal(a), bli_dimag(a), bli_sreal(x), bli_simag(x), bli_zreal(b), bli_zimag(b), bli_creal(y), bli_cimag(y) ) #define bli_cszcaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_creal(a), bli_cimag(a), bli_sreal(x), bli_simag(x), bli_zreal(b), bli_zimag(b), bli_creal(y), bli_cimag(y) ) #define bli_zszcaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_zreal(a), bli_zimag(a), bli_sreal(x), bli_simag(x), bli_zreal(b), bli_zimag(b), bli_creal(y), bli_cimag(y) ) #define bli_sdzcaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_sreal(a), bli_simag(a), bli_dreal(x), bli_dimag(x), bli_zreal(b), bli_zimag(b), bli_creal(y), bli_cimag(y) ) #define bli_ddzcaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_dreal(a), bli_dimag(a), bli_dreal(x), bli_dimag(x), bli_zreal(b), bli_zimag(b), bli_creal(y), bli_cimag(y) ) #define bli_cdzcaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_creal(a), bli_cimag(a), bli_dreal(x), bli_dimag(x), bli_zreal(b), bli_zimag(b), bli_creal(y), bli_cimag(y) ) #define bli_zdzcaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_zreal(a), bli_zimag(a), bli_dreal(x), bli_dimag(x), bli_zreal(b), bli_zimag(b), bli_creal(y), bli_cimag(y) ) #define bli_sczcaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_sreal(a), bli_simag(a), bli_creal(x), bli_cimag(x), bli_zreal(b), bli_zimag(b), bli_creal(y), bli_cimag(y) ) #define bli_dczcaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_dreal(a), bli_dimag(a), bli_creal(x), bli_cimag(x), bli_zreal(b), bli_zimag(b), bli_creal(y), bli_cimag(y) ) #define bli_cczcaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_creal(a), bli_cimag(a), bli_creal(x), bli_cimag(x), bli_zreal(b), bli_zimag(b), bli_creal(y), bli_cimag(y) ) #define bli_zczcaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_zreal(a), bli_zimag(a), bli_creal(x), bli_cimag(x), bli_zreal(b), bli_zimag(b), bli_creal(y), bli_cimag(y) ) #define bli_szzcaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_sreal(a), bli_simag(a), bli_zreal(x), bli_zimag(x), bli_zreal(b), bli_zimag(b), bli_creal(y), bli_cimag(y) ) #define bli_dzzcaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_dreal(a), bli_dimag(a), bli_zreal(x), bli_zimag(x), bli_zreal(b), bli_zimag(b), bli_creal(y), bli_cimag(y) ) #define bli_czzcaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_creal(a), bli_cimag(a), bli_zreal(x), bli_zimag(x), bli_zreal(b), bli_zimag(b), bli_creal(y), bli_cimag(y) ) #define bli_zzzcaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_zreal(a), bli_zimag(a), bli_zreal(x), bli_zimag(x), bli_zreal(b), bli_zimag(b), bli_creal(y), bli_cimag(y) ) // -- (axby) = (???z) ---------------------------------------------------------- #define bli_ssszaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_sreal(a), bli_simag(a), bli_sreal(x), bli_simag(x), bli_sreal(b), bli_simag(b), bli_zreal(y), bli_zimag(y) ) #define bli_dsszaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_dreal(a), bli_dimag(a), bli_sreal(x), bli_simag(x), bli_sreal(b), bli_simag(b), bli_zreal(y), bli_zimag(y) ) #define bli_csszaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_creal(a), bli_cimag(a), bli_sreal(x), bli_simag(x), bli_sreal(b), bli_simag(b), bli_zreal(y), bli_zimag(y) ) #define bli_zsszaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_zreal(a), bli_zimag(a), bli_sreal(x), bli_simag(x), bli_sreal(b), bli_simag(b), bli_zreal(y), bli_zimag(y) ) #define bli_sdszaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_sreal(a), bli_simag(a), bli_dreal(x), bli_dimag(x), bli_sreal(b), bli_simag(b), bli_zreal(y), bli_zimag(y) ) #define bli_ddszaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_dreal(a), bli_dimag(a), bli_dreal(x), bli_dimag(x), bli_sreal(b), bli_simag(b), bli_zreal(y), bli_zimag(y) ) #define bli_cdszaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_creal(a), bli_cimag(a), bli_dreal(x), bli_dimag(x), bli_sreal(b), bli_simag(b), bli_zreal(y), bli_zimag(y) ) #define bli_zdszaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_zreal(a), bli_zimag(a), bli_dreal(x), bli_dimag(x), bli_sreal(b), bli_simag(b), bli_zreal(y), bli_zimag(y) ) #define bli_scszaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_sreal(a), bli_simag(a), bli_creal(x), bli_cimag(x), bli_sreal(b), bli_simag(b), bli_zreal(y), bli_zimag(y) ) #define bli_dcszaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_dreal(a), bli_dimag(a), bli_creal(x), bli_cimag(x), bli_sreal(b), bli_simag(b), bli_zreal(y), bli_zimag(y) ) #define bli_ccszaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_creal(a), bli_cimag(a), bli_creal(x), bli_cimag(x), bli_sreal(b), bli_simag(b), bli_zreal(y), bli_zimag(y) ) #define bli_zcszaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_zreal(a), bli_zimag(a), bli_creal(x), bli_cimag(x), bli_sreal(b), bli_simag(b), bli_zreal(y), bli_zimag(y) ) #define bli_szszaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_sreal(a), bli_simag(a), bli_zreal(x), bli_zimag(x), bli_sreal(b), bli_simag(b), bli_zreal(y), bli_zimag(y) ) #define bli_dzszaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_dreal(a), bli_dimag(a), bli_zreal(x), bli_zimag(x), bli_sreal(b), bli_simag(b), bli_zreal(y), bli_zimag(y) ) #define bli_czszaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_creal(a), bli_cimag(a), bli_zreal(x), bli_zimag(x), bli_sreal(b), bli_simag(b), bli_zreal(y), bli_zimag(y) ) #define bli_zzszaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_zreal(a), bli_zimag(a), bli_zreal(x), bli_zimag(x), bli_sreal(b), bli_simag(b), bli_zreal(y), bli_zimag(y) ) #define bli_ssdzaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_sreal(a), bli_simag(a), bli_sreal(x), bli_simag(x), bli_dreal(b), bli_dimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_dsdzaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_dreal(a), bli_dimag(a), bli_sreal(x), bli_simag(x), bli_dreal(b), bli_dimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_csdzaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_creal(a), bli_cimag(a), bli_sreal(x), bli_simag(x), bli_dreal(b), bli_dimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_zsdzaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_zreal(a), bli_zimag(a), bli_sreal(x), bli_simag(x), bli_dreal(b), bli_dimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_sddzaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_sreal(a), bli_simag(a), bli_dreal(x), bli_dimag(x), bli_dreal(b), bli_dimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_dddzaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_dreal(a), bli_dimag(a), bli_dreal(x), bli_dimag(x), bli_dreal(b), bli_dimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_cddzaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_creal(a), bli_cimag(a), bli_dreal(x), bli_dimag(x), bli_dreal(b), bli_dimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_zddzaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_zreal(a), bli_zimag(a), bli_dreal(x), bli_dimag(x), bli_dreal(b), bli_dimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_scdzaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_sreal(a), bli_simag(a), bli_creal(x), bli_cimag(x), bli_dreal(b), bli_dimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_dcdzaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_dreal(a), bli_dimag(a), bli_creal(x), bli_cimag(x), bli_dreal(b), bli_dimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_ccdzaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_creal(a), bli_cimag(a), bli_creal(x), bli_cimag(x), bli_dreal(b), bli_dimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_zcdzaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_zreal(a), bli_zimag(a), bli_creal(x), bli_cimag(x), bli_dreal(b), bli_dimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_szdzaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_sreal(a), bli_simag(a), bli_zreal(x), bli_zimag(x), bli_dreal(b), bli_dimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_dzdzaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_dreal(a), bli_dimag(a), bli_zreal(x), bli_zimag(x), bli_dreal(b), bli_dimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_czdzaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_creal(a), bli_cimag(a), bli_zreal(x), bli_zimag(x), bli_dreal(b), bli_dimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_zzdzaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_zreal(a), bli_zimag(a), bli_zreal(x), bli_zimag(x), bli_dreal(b), bli_dimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_ssczaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_sreal(a), bli_simag(a), bli_sreal(x), bli_simag(x), bli_creal(b), bli_cimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_dsczaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_dreal(a), bli_dimag(a), bli_sreal(x), bli_simag(x), bli_creal(b), bli_cimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_csczaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_creal(a), bli_cimag(a), bli_sreal(x), bli_simag(x), bli_creal(b), bli_cimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_zsczaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_zreal(a), bli_zimag(a), bli_sreal(x), bli_simag(x), bli_creal(b), bli_cimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_sdczaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_sreal(a), bli_simag(a), bli_dreal(x), bli_dimag(x), bli_creal(b), bli_cimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_ddczaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_dreal(a), bli_dimag(a), bli_dreal(x), bli_dimag(x), bli_creal(b), bli_cimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_cdczaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_creal(a), bli_cimag(a), bli_dreal(x), bli_dimag(x), bli_creal(b), bli_cimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_zdczaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_zreal(a), bli_zimag(a), bli_dreal(x), bli_dimag(x), bli_creal(b), bli_cimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_scczaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_sreal(a), bli_simag(a), bli_creal(x), bli_cimag(x), bli_creal(b), bli_cimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_dcczaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_dreal(a), bli_dimag(a), bli_creal(x), bli_cimag(x), bli_creal(b), bli_cimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_ccczaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_creal(a), bli_cimag(a), bli_creal(x), bli_cimag(x), bli_creal(b), bli_cimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_zcczaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_zreal(a), bli_zimag(a), bli_creal(x), bli_cimag(x), bli_creal(b), bli_cimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_szczaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_sreal(a), bli_simag(a), bli_zreal(x), bli_zimag(x), bli_creal(b), bli_cimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_dzczaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_dreal(a), bli_dimag(a), bli_zreal(x), bli_zimag(x), bli_creal(b), bli_cimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_czczaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_creal(a), bli_cimag(a), bli_zreal(x), bli_zimag(x), bli_creal(b), bli_cimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_zzczaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_zreal(a), bli_zimag(a), bli_zreal(x), bli_zimag(x), bli_creal(b), bli_cimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_sszzaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_sreal(a), bli_simag(a), bli_sreal(x), bli_simag(x), bli_zreal(b), bli_zimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_dszzaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_dreal(a), bli_dimag(a), bli_sreal(x), bli_simag(x), bli_zreal(b), bli_zimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_cszzaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_creal(a), bli_cimag(a), bli_sreal(x), bli_simag(x), bli_zreal(b), bli_zimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_zszzaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_zreal(a), bli_zimag(a), bli_sreal(x), bli_simag(x), bli_zreal(b), bli_zimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_sdzzaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_sreal(a), bli_simag(a), bli_dreal(x), bli_dimag(x), bli_zreal(b), bli_zimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_ddzzaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_dreal(a), bli_dimag(a), bli_dreal(x), bli_dimag(x), bli_zreal(b), bli_zimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_cdzzaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_creal(a), bli_cimag(a), bli_dreal(x), bli_dimag(x), bli_zreal(b), bli_zimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_zdzzaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_zreal(a), bli_zimag(a), bli_dreal(x), bli_dimag(x), bli_zreal(b), bli_zimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_sczzaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_sreal(a), bli_simag(a), bli_creal(x), bli_cimag(x), bli_zreal(b), bli_zimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_dczzaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_dreal(a), bli_dimag(a), bli_creal(x), bli_cimag(x), bli_zreal(b), bli_zimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_cczzaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_creal(a), bli_cimag(a), bli_creal(x), bli_cimag(x), bli_zreal(b), bli_zimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_zczzaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_zreal(a), bli_zimag(a), bli_creal(x), bli_cimag(x), bli_zreal(b), bli_zimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_szzzaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_sreal(a), bli_simag(a), bli_zreal(x), bli_zimag(x), bli_zreal(b), bli_zimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_dzzzaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_dreal(a), bli_dimag(a), bli_zreal(x), bli_zimag(x), bli_zreal(b), bli_zimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_czzzaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_creal(a), bli_cimag(a), bli_zreal(x), bli_zimag(x), bli_zreal(b), bli_zimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_zzzzaxpbyjs( a, x, b, y ) bli_cxaxpbyjris( bli_zreal(a), bli_zimag(a), bli_zreal(x), bli_zimag(x), bli_zreal(b), bli_zimag(b), bli_zreal(y), bli_zimag(y) ) #else // ifdef BLIS_ENABLE_C99_COMPLEX // -- (axby) = (???c) ---------------------------------------------------------- #define bli_ssscaxpbyjs( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_dsscaxpbyjs( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_csscaxpbyjs( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_zsscaxpbyjs( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_sdscaxpbyjs( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_ddscaxpbyjs( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_cdscaxpbyjs( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_zdscaxpbyjs( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_scscaxpbyjs( a, x, b, y ) { (y) = (a) * conjf(x) + (b) * (y); } #define bli_dcscaxpbyjs( a, x, b, y ) { (y) = (a) * conjf(x) + (b) * (y); } #define bli_ccscaxpbyjs( a, x, b, y ) { (y) = (a) * conjf(x) + (b) * (y); } #define bli_zcscaxpbyjs( a, x, b, y ) { (y) = (a) * conjf(x) + (b) * (y); } #define bli_szscaxpbyjs( a, x, b, y ) { (y) = (a) * conj(x) + (b) * (y); } #define bli_dzscaxpbyjs( a, x, b, y ) { (y) = (a) * conj(x) + (b) * (y); } #define bli_czscaxpbyjs( a, x, b, y ) { (y) = (a) * conj(x) + (b) * (y); } #define bli_zzscaxpbyjs( a, x, b, y ) { (y) = (a) * conj(x) + (b) * (y); } #define bli_ssdcaxpbyjs( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_dsdcaxpbyjs( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_csdcaxpbyjs( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_zsdcaxpbyjs( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_sddcaxpbyjs( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_dddcaxpbyjs( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_cddcaxpbyjs( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_zddcaxpbyjs( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_scdcaxpbyjs( a, x, b, y ) { (y) = (a) * conjf(x) + (b) * (y); } #define bli_dcdcaxpbyjs( a, x, b, y ) { (y) = (a) * conjf(x) + (b) * (y); } #define bli_ccdcaxpbyjs( a, x, b, y ) { (y) = (a) * conjf(x) + (b) * (y); } #define bli_zcdcaxpbyjs( a, x, b, y ) { (y) = (a) * conjf(x) + (b) * (y); } #define bli_szdcaxpbyjs( a, x, b, y ) { (y) = (a) * conj(x) + (b) * (y); } #define bli_dzdcaxpbyjs( a, x, b, y ) { (y) = (a) * conj(x) + (b) * (y); } #define bli_czdcaxpbyjs( a, x, b, y ) { (y) = (a) * conj(x) + (b) * (y); } #define bli_zzdcaxpbyjs( a, x, b, y ) { (y) = (a) * conj(x) + (b) * (y); } #define bli_ssccaxpbyjs( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_dsccaxpbyjs( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_csccaxpbyjs( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_zsccaxpbyjs( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_sdccaxpbyjs( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_ddccaxpbyjs( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_cdccaxpbyjs( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_zdccaxpbyjs( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_scccaxpbyjs( a, x, b, y ) { (y) = (a) * conjf(x) + (b) * (y); } #define bli_dcccaxpbyjs( a, x, b, y ) { (y) = (a) * conjf(x) + (b) * (y); } #define bli_ccccaxpbyjs( a, x, b, y ) { (y) = (a) * conjf(x) + (b) * (y); } #define bli_zcccaxpbyjs( a, x, b, y ) { (y) = (a) * conjf(x) + (b) * (y); } #define bli_szccaxpbyjs( a, x, b, y ) { (y) = (a) * conj(x) + (b) * (y); } #define bli_dzccaxpbyjs( a, x, b, y ) { (y) = (a) * conj(x) + (b) * (y); } #define bli_czccaxpbyjs( a, x, b, y ) { (y) = (a) * conj(x) + (b) * (y); } #define bli_zzccaxpbyjs( a, x, b, y ) { (y) = (a) * conj(x) + (b) * (y); } #define bli_sszcaxpbyjs( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_dszcaxpbyjs( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_cszcaxpbyjs( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_zszcaxpbyjs( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_sdzcaxpbyjs( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_ddzcaxpbyjs( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_cdzcaxpbyjs( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_zdzcaxpbyjs( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_sczcaxpbyjs( a, x, b, y ) { (y) = (a) * conjf(x) + (b) * (y); } #define bli_dczcaxpbyjs( a, x, b, y ) { (y) = (a) * conjf(x) + (b) * (y); } #define bli_cczcaxpbyjs( a, x, b, y ) { (y) = (a) * conjf(x) + (b) * (y); } #define bli_zczcaxpbyjs( a, x, b, y ) { (y) = (a) * conjf(x) + (b) * (y); } #define bli_szzcaxpbyjs( a, x, b, y ) { (y) = (a) * conj(x) + (b) * (y); } #define bli_dzzcaxpbyjs( a, x, b, y ) { (y) = (a) * conj(x) + (b) * (y); } #define bli_czzcaxpbyjs( a, x, b, y ) { (y) = (a) * conj(x) + (b) * (y); } #define bli_zzzcaxpbyjs( a, x, b, y ) { (y) = (a) * conj(x) + (b) * (y); } // -- (axby) = (???z) ---------------------------------------------------------- #define bli_ssszaxpbyjs( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_dsszaxpbyjs( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_csszaxpbyjs( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_zsszaxpbyjs( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_sdszaxpbyjs( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_ddszaxpbyjs( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_cdszaxpbyjs( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_zdszaxpbyjs( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_scszaxpbyjs( a, x, b, y ) { (y) = (a) * conjf(x) + (b) * (y); } #define bli_dcszaxpbyjs( a, x, b, y ) { (y) = (a) * conjf(x) + (b) * (y); } #define bli_ccszaxpbyjs( a, x, b, y ) { (y) = (a) * conjf(x) + (b) * (y); } #define bli_zcszaxpbyjs( a, x, b, y ) { (y) = (a) * conjf(x) + (b) * (y); } #define bli_szszaxpbyjs( a, x, b, y ) { (y) = (a) * conj(x) + (b) * (y); } #define bli_dzszaxpbyjs( a, x, b, y ) { (y) = (a) * conj(x) + (b) * (y); } #define bli_czszaxpbyjs( a, x, b, y ) { (y) = (a) * conj(x) + (b) * (y); } #define bli_zzszaxpbyjs( a, x, b, y ) { (y) = (a) * conj(x) + (b) * (y); } #define bli_ssdzaxpbyjs( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_dsdzaxpbyjs( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_csdzaxpbyjs( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_zsdzaxpbyjs( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_sddzaxpbyjs( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_dddzaxpbyjs( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_cddzaxpbyjs( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_zddzaxpbyjs( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_scdzaxpbyjs( a, x, b, y ) { (y) = (a) * conjf(x) + (b) * (y); } #define bli_dcdzaxpbyjs( a, x, b, y ) { (y) = (a) * conjf(x) + (b) * (y); } #define bli_ccdzaxpbyjs( a, x, b, y ) { (y) = (a) * conjf(x) + (b) * (y); } #define bli_zcdzaxpbyjs( a, x, b, y ) { (y) = (a) * conjf(x) + (b) * (y); } #define bli_szdzaxpbyjs( a, x, b, y ) { (y) = (a) * conj(x) + (b) * (y); } #define bli_dzdzaxpbyjs( a, x, b, y ) { (y) = (a) * conj(x) + (b) * (y); } #define bli_czdzaxpbyjs( a, x, b, y ) { (y) = (a) * conj(x) + (b) * (y); } #define bli_zzdzaxpbyjs( a, x, b, y ) { (y) = (a) * conj(x) + (b) * (y); } #define bli_ssczaxpbyjs( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_dsczaxpbyjs( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_csczaxpbyjs( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_zsczaxpbyjs( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_sdczaxpbyjs( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_ddczaxpbyjs( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_cdczaxpbyjs( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_zdczaxpbyjs( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_scczaxpbyjs( a, x, b, y ) { (y) = (a) * conjf(x) + (b) * (y); } #define bli_dcczaxpbyjs( a, x, b, y ) { (y) = (a) * conjf(x) + (b) * (y); } #define bli_ccczaxpbyjs( a, x, b, y ) { (y) = (a) * conjf(x) + (b) * (y); } #define bli_zcczaxpbyjs( a, x, b, y ) { (y) = (a) * conjf(x) + (b) * (y); } #define bli_szczaxpbyjs( a, x, b, y ) { (y) = (a) * conj(x) + (b) * (y); } #define bli_dzczaxpbyjs( a, x, b, y ) { (y) = (a) * conj(x) + (b) * (y); } #define bli_czczaxpbyjs( a, x, b, y ) { (y) = (a) * conj(x) + (b) * (y); } #define bli_zzczaxpbyjs( a, x, b, y ) { (y) = (a) * conj(x) + (b) * (y); } #define bli_sszzaxpbyjs( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_dszzaxpbyjs( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_cszzaxpbyjs( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_zszzaxpbyjs( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_sdzzaxpbyjs( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_ddzzaxpbyjs( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_cdzzaxpbyjs( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_zdzzaxpbyjs( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_sczzaxpbyjs( a, x, b, y ) { (y) = (a) * conjf(x) + (b) * (y); } #define bli_dczzaxpbyjs( a, x, b, y ) { (y) = (a) * conjf(x) + (b) * (y); } #define bli_cczzaxpbyjs( a, x, b, y ) { (y) = (a) * conjf(x) + (b) * (y); } #define bli_zczzaxpbyjs( a, x, b, y ) { (y) = (a) * conjf(x) + (b) * (y); } #define bli_szzzaxpbyjs( a, x, b, y ) { (y) = (a) * conj(x) + (b) * (y); } #define bli_dzzzaxpbyjs( a, x, b, y ) { (y) = (a) * conj(x) + (b) * (y); } #define bli_czzzaxpbyjs( a, x, b, y ) { (y) = (a) * conj(x) + (b) * (y); } #define bli_zzzzaxpbyjs( a, x, b, y ) { (y) = (a) * conj(x) + (b) * (y); } #endif // BLIS_ENABLE_C99_COMPLEX #define bli_saxpbyjs( a, x, b, y ) bli_ssssaxpbyjs( a, x, b, y ) #define bli_daxpbyjs( a, x, b, y ) bli_ddddaxpbyjs( a, x, b, y ) #define bli_caxpbyjs( a, x, b, y ) bli_ccccaxpbyjs( a, x, b, y ) #define bli_zaxpbyjs( a, x, b, y ) bli_zzzzaxpbyjs( a, x, b, y ) #endif blis-0.9.0/frame/include/level0/bli_axpbys.h000066400000000000000000001525651422157504600207060ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_AXPBYS_H #define BLIS_AXPBYS_H // axpbys // Notes: // - The first char encodes the type of a. // - The second char encodes the type of x. // - The third char encodes the type of b. // - The fourth char encodes the type of y. // -- (axby) = (???s) ---------------------------------------------------------- #define bli_ssssaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_sreal(a), bli_simag(a), bli_sreal(x), bli_simag(x), bli_sreal(b), bli_simag(b), bli_sreal(y), bli_simag(y) ) #define bli_dsssaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_dreal(a), bli_dimag(a), bli_sreal(x), bli_simag(x), bli_sreal(b), bli_simag(b), bli_sreal(y), bli_simag(y) ) #define bli_csssaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_creal(a), bli_cimag(a), bli_sreal(x), bli_simag(x), bli_sreal(b), bli_simag(b), bli_sreal(y), bli_simag(y) ) #define bli_zsssaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_zreal(a), bli_zimag(a), bli_sreal(x), bli_simag(x), bli_sreal(b), bli_simag(b), bli_sreal(y), bli_simag(y) ) #define bli_sdssaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_sreal(a), bli_simag(a), bli_dreal(x), bli_dimag(x), bli_sreal(b), bli_simag(b), bli_sreal(y), bli_simag(y) ) #define bli_ddssaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_dreal(a), bli_dimag(a), bli_dreal(x), bli_dimag(x), bli_sreal(b), bli_simag(b), bli_sreal(y), bli_simag(y) ) #define bli_cdssaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_creal(a), bli_cimag(a), bli_dreal(x), bli_dimag(x), bli_sreal(b), bli_simag(b), bli_sreal(y), bli_simag(y) ) #define bli_zdssaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_zreal(a), bli_zimag(a), bli_dreal(x), bli_dimag(x), bli_sreal(b), bli_simag(b), bli_sreal(y), bli_simag(y) ) #define bli_scssaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_sreal(a), bli_simag(a), bli_creal(x), bli_cimag(x), bli_sreal(b), bli_simag(b), bli_sreal(y), bli_simag(y) ) #define bli_dcssaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_dreal(a), bli_dimag(a), bli_creal(x), bli_cimag(x), bli_sreal(b), bli_simag(b), bli_sreal(y), bli_simag(y) ) #define bli_ccssaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_creal(a), bli_cimag(a), bli_creal(x), bli_cimag(x), bli_sreal(b), bli_simag(b), bli_sreal(y), bli_simag(y) ) #define bli_zcssaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_zreal(a), bli_zimag(a), bli_creal(x), bli_cimag(x), bli_sreal(b), bli_simag(b), bli_sreal(y), bli_simag(y) ) #define bli_szssaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_sreal(a), bli_simag(a), bli_zreal(x), bli_zimag(x), bli_sreal(b), bli_simag(b), bli_sreal(y), bli_simag(y) ) #define bli_dzssaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_dreal(a), bli_dimag(a), bli_zreal(x), bli_zimag(x), bli_sreal(b), bli_simag(b), bli_sreal(y), bli_simag(y) ) #define bli_czssaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_creal(a), bli_cimag(a), bli_zreal(x), bli_zimag(x), bli_sreal(b), bli_simag(b), bli_sreal(y), bli_simag(y) ) #define bli_zzssaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_zreal(a), bli_zimag(a), bli_zreal(x), bli_zimag(x), bli_sreal(b), bli_simag(b), bli_sreal(y), bli_simag(y) ) #define bli_ssdsaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_sreal(a), bli_simag(a), bli_sreal(x), bli_simag(x), bli_dreal(b), bli_dimag(b), bli_sreal(y), bli_simag(y) ) #define bli_dsdsaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_dreal(a), bli_dimag(a), bli_sreal(x), bli_simag(x), bli_dreal(b), bli_dimag(b), bli_sreal(y), bli_simag(y) ) #define bli_csdsaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_creal(a), bli_cimag(a), bli_sreal(x), bli_simag(x), bli_dreal(b), bli_dimag(b), bli_sreal(y), bli_simag(y) ) #define bli_zsdsaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_zreal(a), bli_zimag(a), bli_sreal(x), bli_simag(x), bli_dreal(b), bli_dimag(b), bli_sreal(y), bli_simag(y) ) #define bli_sddsaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_sreal(a), bli_simag(a), bli_dreal(x), bli_dimag(x), bli_dreal(b), bli_dimag(b), bli_sreal(y), bli_simag(y) ) #define bli_dddsaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_dreal(a), bli_dimag(a), bli_dreal(x), bli_dimag(x), bli_dreal(b), bli_dimag(b), bli_sreal(y), bli_simag(y) ) #define bli_cddsaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_creal(a), bli_cimag(a), bli_dreal(x), bli_dimag(x), bli_dreal(b), bli_dimag(b), bli_sreal(y), bli_simag(y) ) #define bli_zddsaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_zreal(a), bli_zimag(a), bli_dreal(x), bli_dimag(x), bli_dreal(b), bli_dimag(b), bli_sreal(y), bli_simag(y) ) #define bli_scdsaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_sreal(a), bli_simag(a), bli_creal(x), bli_cimag(x), bli_dreal(b), bli_dimag(b), bli_sreal(y), bli_simag(y) ) #define bli_dcdsaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_dreal(a), bli_dimag(a), bli_creal(x), bli_cimag(x), bli_dreal(b), bli_dimag(b), bli_sreal(y), bli_simag(y) ) #define bli_ccdsaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_creal(a), bli_cimag(a), bli_creal(x), bli_cimag(x), bli_dreal(b), bli_dimag(b), bli_sreal(y), bli_simag(y) ) #define bli_zcdsaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_zreal(a), bli_zimag(a), bli_creal(x), bli_cimag(x), bli_dreal(b), bli_dimag(b), bli_sreal(y), bli_simag(y) ) #define bli_szdsaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_sreal(a), bli_simag(a), bli_zreal(x), bli_zimag(x), bli_dreal(b), bli_dimag(b), bli_sreal(y), bli_simag(y) ) #define bli_dzdsaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_dreal(a), bli_dimag(a), bli_zreal(x), bli_zimag(x), bli_dreal(b), bli_dimag(b), bli_sreal(y), bli_simag(y) ) #define bli_czdsaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_creal(a), bli_cimag(a), bli_zreal(x), bli_zimag(x), bli_dreal(b), bli_dimag(b), bli_sreal(y), bli_simag(y) ) #define bli_zzdsaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_zreal(a), bli_zimag(a), bli_zreal(x), bli_zimag(x), bli_dreal(b), bli_dimag(b), bli_sreal(y), bli_simag(y) ) #define bli_sscsaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_sreal(a), bli_simag(a), bli_sreal(x), bli_simag(x), bli_creal(b), bli_cimag(b), bli_sreal(y), bli_simag(y) ) #define bli_dscsaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_dreal(a), bli_dimag(a), bli_sreal(x), bli_simag(x), bli_creal(b), bli_cimag(b), bli_sreal(y), bli_simag(y) ) #define bli_cscsaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_creal(a), bli_cimag(a), bli_sreal(x), bli_simag(x), bli_creal(b), bli_cimag(b), bli_sreal(y), bli_simag(y) ) #define bli_zscsaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_zreal(a), bli_zimag(a), bli_sreal(x), bli_simag(x), bli_creal(b), bli_cimag(b), bli_sreal(y), bli_simag(y) ) #define bli_sdcsaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_sreal(a), bli_simag(a), bli_dreal(x), bli_dimag(x), bli_creal(b), bli_cimag(b), bli_sreal(y), bli_simag(y) ) #define bli_ddcsaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_dreal(a), bli_dimag(a), bli_dreal(x), bli_dimag(x), bli_creal(b), bli_cimag(b), bli_sreal(y), bli_simag(y) ) #define bli_cdcsaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_creal(a), bli_cimag(a), bli_dreal(x), bli_dimag(x), bli_creal(b), bli_cimag(b), bli_sreal(y), bli_simag(y) ) #define bli_zdcsaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_zreal(a), bli_zimag(a), bli_dreal(x), bli_dimag(x), bli_creal(b), bli_cimag(b), bli_sreal(y), bli_simag(y) ) #define bli_sccsaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_sreal(a), bli_simag(a), bli_creal(x), bli_cimag(x), bli_creal(b), bli_cimag(b), bli_sreal(y), bli_simag(y) ) #define bli_dccsaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_dreal(a), bli_dimag(a), bli_creal(x), bli_cimag(x), bli_creal(b), bli_cimag(b), bli_sreal(y), bli_simag(y) ) #define bli_cccsaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_creal(a), bli_cimag(a), bli_creal(x), bli_cimag(x), bli_creal(b), bli_cimag(b), bli_sreal(y), bli_simag(y) ) #define bli_zccsaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_zreal(a), bli_zimag(a), bli_creal(x), bli_cimag(x), bli_creal(b), bli_cimag(b), bli_sreal(y), bli_simag(y) ) #define bli_szcsaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_sreal(a), bli_simag(a), bli_zreal(x), bli_zimag(x), bli_creal(b), bli_cimag(b), bli_sreal(y), bli_simag(y) ) #define bli_dzcsaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_dreal(a), bli_dimag(a), bli_zreal(x), bli_zimag(x), bli_creal(b), bli_cimag(b), bli_sreal(y), bli_simag(y) ) #define bli_czcsaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_creal(a), bli_cimag(a), bli_zreal(x), bli_zimag(x), bli_creal(b), bli_cimag(b), bli_sreal(y), bli_simag(y) ) #define bli_zzcsaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_zreal(a), bli_zimag(a), bli_zreal(x), bli_zimag(x), bli_creal(b), bli_cimag(b), bli_sreal(y), bli_simag(y) ) #define bli_sszsaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_sreal(a), bli_simag(a), bli_sreal(x), bli_simag(x), bli_zreal(b), bli_zimag(b), bli_sreal(y), bli_simag(y) ) #define bli_dszsaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_dreal(a), bli_dimag(a), bli_sreal(x), bli_simag(x), bli_zreal(b), bli_zimag(b), bli_sreal(y), bli_simag(y) ) #define bli_cszsaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_creal(a), bli_cimag(a), bli_sreal(x), bli_simag(x), bli_zreal(b), bli_zimag(b), bli_sreal(y), bli_simag(y) ) #define bli_zszsaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_zreal(a), bli_zimag(a), bli_sreal(x), bli_simag(x), bli_zreal(b), bli_zimag(b), bli_sreal(y), bli_simag(y) ) #define bli_sdzsaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_sreal(a), bli_simag(a), bli_dreal(x), bli_dimag(x), bli_zreal(b), bli_zimag(b), bli_sreal(y), bli_simag(y) ) #define bli_ddzsaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_dreal(a), bli_dimag(a), bli_dreal(x), bli_dimag(x), bli_zreal(b), bli_zimag(b), bli_sreal(y), bli_simag(y) ) #define bli_cdzsaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_creal(a), bli_cimag(a), bli_dreal(x), bli_dimag(x), bli_zreal(b), bli_zimag(b), bli_sreal(y), bli_simag(y) ) #define bli_zdzsaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_zreal(a), bli_zimag(a), bli_dreal(x), bli_dimag(x), bli_zreal(b), bli_zimag(b), bli_sreal(y), bli_simag(y) ) #define bli_sczsaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_sreal(a), bli_simag(a), bli_creal(x), bli_cimag(x), bli_zreal(b), bli_zimag(b), bli_sreal(y), bli_simag(y) ) #define bli_dczsaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_dreal(a), bli_dimag(a), bli_creal(x), bli_cimag(x), bli_zreal(b), bli_zimag(b), bli_sreal(y), bli_simag(y) ) #define bli_cczsaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_creal(a), bli_cimag(a), bli_creal(x), bli_cimag(x), bli_zreal(b), bli_zimag(b), bli_sreal(y), bli_simag(y) ) #define bli_zczsaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_zreal(a), bli_zimag(a), bli_creal(x), bli_cimag(x), bli_zreal(b), bli_zimag(b), bli_sreal(y), bli_simag(y) ) #define bli_szzsaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_sreal(a), bli_simag(a), bli_zreal(x), bli_zimag(x), bli_zreal(b), bli_zimag(b), bli_sreal(y), bli_simag(y) ) #define bli_dzzsaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_dreal(a), bli_dimag(a), bli_zreal(x), bli_zimag(x), bli_zreal(b), bli_zimag(b), bli_sreal(y), bli_simag(y) ) #define bli_czzsaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_creal(a), bli_cimag(a), bli_zreal(x), bli_zimag(x), bli_zreal(b), bli_zimag(b), bli_sreal(y), bli_simag(y) ) #define bli_zzzsaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_zreal(a), bli_zimag(a), bli_zreal(x), bli_zimag(x), bli_zreal(b), bli_zimag(b), bli_sreal(y), bli_simag(y) ) // -- (axby) = (???d) ---------------------------------------------------------- #define bli_sssdaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_sreal(a), bli_simag(a), bli_sreal(x), bli_simag(x), bli_sreal(b), bli_simag(b), bli_dreal(y), bli_dimag(y) ) #define bli_dssdaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_dreal(a), bli_dimag(a), bli_sreal(x), bli_simag(x), bli_sreal(b), bli_simag(b), bli_dreal(y), bli_dimag(y) ) #define bli_cssdaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_creal(a), bli_cimag(a), bli_sreal(x), bli_simag(x), bli_sreal(b), bli_simag(b), bli_dreal(y), bli_dimag(y) ) #define bli_zssdaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_zreal(a), bli_zimag(a), bli_sreal(x), bli_simag(x), bli_sreal(b), bli_simag(b), bli_dreal(y), bli_dimag(y) ) #define bli_sdsdaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_sreal(a), bli_simag(a), bli_dreal(x), bli_dimag(x), bli_sreal(b), bli_simag(b), bli_dreal(y), bli_dimag(y) ) #define bli_ddsdaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_dreal(a), bli_dimag(a), bli_dreal(x), bli_dimag(x), bli_sreal(b), bli_simag(b), bli_dreal(y), bli_dimag(y) ) #define bli_cdsdaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_creal(a), bli_cimag(a), bli_dreal(x), bli_dimag(x), bli_sreal(b), bli_simag(b), bli_dreal(y), bli_dimag(y) ) #define bli_zdsdaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_zreal(a), bli_zimag(a), bli_dreal(x), bli_dimag(x), bli_sreal(b), bli_simag(b), bli_dreal(y), bli_dimag(y) ) #define bli_scsdaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_sreal(a), bli_simag(a), bli_creal(x), bli_cimag(x), bli_sreal(b), bli_simag(b), bli_dreal(y), bli_dimag(y) ) #define bli_dcsdaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_dreal(a), bli_dimag(a), bli_creal(x), bli_cimag(x), bli_sreal(b), bli_simag(b), bli_dreal(y), bli_dimag(y) ) #define bli_ccsdaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_creal(a), bli_cimag(a), bli_creal(x), bli_cimag(x), bli_sreal(b), bli_simag(b), bli_dreal(y), bli_dimag(y) ) #define bli_zcsdaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_zreal(a), bli_zimag(a), bli_creal(x), bli_cimag(x), bli_sreal(b), bli_simag(b), bli_dreal(y), bli_dimag(y) ) #define bli_szsdaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_sreal(a), bli_simag(a), bli_zreal(x), bli_zimag(x), bli_sreal(b), bli_simag(b), bli_dreal(y), bli_dimag(y) ) #define bli_dzsdaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_dreal(a), bli_dimag(a), bli_zreal(x), bli_zimag(x), bli_sreal(b), bli_simag(b), bli_dreal(y), bli_dimag(y) ) #define bli_czsdaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_creal(a), bli_cimag(a), bli_zreal(x), bli_zimag(x), bli_sreal(b), bli_simag(b), bli_dreal(y), bli_dimag(y) ) #define bli_zzsdaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_zreal(a), bli_zimag(a), bli_zreal(x), bli_zimag(x), bli_sreal(b), bli_simag(b), bli_dreal(y), bli_dimag(y) ) #define bli_ssddaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_sreal(a), bli_simag(a), bli_sreal(x), bli_simag(x), bli_dreal(b), bli_dimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_dsddaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_dreal(a), bli_dimag(a), bli_sreal(x), bli_simag(x), bli_dreal(b), bli_dimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_csddaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_creal(a), bli_cimag(a), bli_sreal(x), bli_simag(x), bli_dreal(b), bli_dimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_zsddaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_zreal(a), bli_zimag(a), bli_sreal(x), bli_simag(x), bli_dreal(b), bli_dimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_sdddaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_sreal(a), bli_simag(a), bli_dreal(x), bli_dimag(x), bli_dreal(b), bli_dimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_ddddaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_dreal(a), bli_dimag(a), bli_dreal(x), bli_dimag(x), bli_dreal(b), bli_dimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_cdddaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_creal(a), bli_cimag(a), bli_dreal(x), bli_dimag(x), bli_dreal(b), bli_dimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_zdddaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_zreal(a), bli_zimag(a), bli_dreal(x), bli_dimag(x), bli_dreal(b), bli_dimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_scddaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_sreal(a), bli_simag(a), bli_creal(x), bli_cimag(x), bli_dreal(b), bli_dimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_dcddaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_dreal(a), bli_dimag(a), bli_creal(x), bli_cimag(x), bli_dreal(b), bli_dimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_ccddaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_creal(a), bli_cimag(a), bli_creal(x), bli_cimag(x), bli_dreal(b), bli_dimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_zcddaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_zreal(a), bli_zimag(a), bli_creal(x), bli_cimag(x), bli_dreal(b), bli_dimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_szddaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_sreal(a), bli_simag(a), bli_zreal(x), bli_zimag(x), bli_dreal(b), bli_dimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_dzddaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_dreal(a), bli_dimag(a), bli_zreal(x), bli_zimag(x), bli_dreal(b), bli_dimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_czddaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_creal(a), bli_cimag(a), bli_zreal(x), bli_zimag(x), bli_dreal(b), bli_dimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_zzddaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_zreal(a), bli_zimag(a), bli_zreal(x), bli_zimag(x), bli_dreal(b), bli_dimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_sscdaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_sreal(a), bli_simag(a), bli_sreal(x), bli_simag(x), bli_creal(b), bli_cimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_dscdaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_dreal(a), bli_dimag(a), bli_sreal(x), bli_simag(x), bli_creal(b), bli_cimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_cscdaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_creal(a), bli_cimag(a), bli_sreal(x), bli_simag(x), bli_creal(b), bli_cimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_zscdaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_zreal(a), bli_zimag(a), bli_sreal(x), bli_simag(x), bli_creal(b), bli_cimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_sdcdaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_sreal(a), bli_simag(a), bli_dreal(x), bli_dimag(x), bli_creal(b), bli_cimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_ddcdaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_dreal(a), bli_dimag(a), bli_dreal(x), bli_dimag(x), bli_creal(b), bli_cimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_cdcdaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_creal(a), bli_cimag(a), bli_dreal(x), bli_dimag(x), bli_creal(b), bli_cimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_zdcdaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_zreal(a), bli_zimag(a), bli_dreal(x), bli_dimag(x), bli_creal(b), bli_cimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_sccdaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_sreal(a), bli_simag(a), bli_creal(x), bli_cimag(x), bli_creal(b), bli_cimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_dccdaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_dreal(a), bli_dimag(a), bli_creal(x), bli_cimag(x), bli_creal(b), bli_cimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_cccdaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_creal(a), bli_cimag(a), bli_creal(x), bli_cimag(x), bli_creal(b), bli_cimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_zccdaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_zreal(a), bli_zimag(a), bli_creal(x), bli_cimag(x), bli_creal(b), bli_cimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_szcdaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_sreal(a), bli_simag(a), bli_zreal(x), bli_zimag(x), bli_creal(b), bli_cimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_dzcdaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_dreal(a), bli_dimag(a), bli_zreal(x), bli_zimag(x), bli_creal(b), bli_cimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_czcdaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_creal(a), bli_cimag(a), bli_zreal(x), bli_zimag(x), bli_creal(b), bli_cimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_zzcdaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_zreal(a), bli_zimag(a), bli_zreal(x), bli_zimag(x), bli_creal(b), bli_cimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_sszdaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_sreal(a), bli_simag(a), bli_sreal(x), bli_simag(x), bli_zreal(b), bli_zimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_dszdaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_dreal(a), bli_dimag(a), bli_sreal(x), bli_simag(x), bli_zreal(b), bli_zimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_cszdaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_creal(a), bli_cimag(a), bli_sreal(x), bli_simag(x), bli_zreal(b), bli_zimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_zszdaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_zreal(a), bli_zimag(a), bli_sreal(x), bli_simag(x), bli_zreal(b), bli_zimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_sdzdaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_sreal(a), bli_simag(a), bli_dreal(x), bli_dimag(x), bli_zreal(b), bli_zimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_ddzdaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_dreal(a), bli_dimag(a), bli_dreal(x), bli_dimag(x), bli_zreal(b), bli_zimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_cdzdaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_creal(a), bli_cimag(a), bli_dreal(x), bli_dimag(x), bli_zreal(b), bli_zimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_zdzdaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_zreal(a), bli_zimag(a), bli_dreal(x), bli_dimag(x), bli_zreal(b), bli_zimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_sczdaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_sreal(a), bli_simag(a), bli_creal(x), bli_cimag(x), bli_zreal(b), bli_zimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_dczdaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_dreal(a), bli_dimag(a), bli_creal(x), bli_cimag(x), bli_zreal(b), bli_zimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_cczdaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_creal(a), bli_cimag(a), bli_creal(x), bli_cimag(x), bli_zreal(b), bli_zimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_zczdaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_zreal(a), bli_zimag(a), bli_creal(x), bli_cimag(x), bli_zreal(b), bli_zimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_szzdaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_sreal(a), bli_simag(a), bli_zreal(x), bli_zimag(x), bli_zreal(b), bli_zimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_dzzdaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_dreal(a), bli_dimag(a), bli_zreal(x), bli_zimag(x), bli_zreal(b), bli_zimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_czzdaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_creal(a), bli_cimag(a), bli_zreal(x), bli_zimag(x), bli_zreal(b), bli_zimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_zzzdaxpbys( a, x, b, y ) bli_rxaxpbyris( bli_zreal(a), bli_zimag(a), bli_zreal(x), bli_zimag(x), bli_zreal(b), bli_zimag(b), bli_dreal(y), bli_dimag(y) ) #ifndef BLIS_ENABLE_C99_COMPLEX // -- (axby) = (???c) ---------------------------------------------------------- #define bli_ssscaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_sreal(a), bli_simag(a), bli_sreal(x), bli_simag(x), bli_sreal(b), bli_simag(b), bli_creal(y), bli_cimag(y) ) #define bli_dsscaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_dreal(a), bli_dimag(a), bli_sreal(x), bli_simag(x), bli_sreal(b), bli_simag(b), bli_creal(y), bli_cimag(y) ) #define bli_csscaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_creal(a), bli_cimag(a), bli_sreal(x), bli_simag(x), bli_sreal(b), bli_simag(b), bli_creal(y), bli_cimag(y) ) #define bli_zsscaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_zreal(a), bli_zimag(a), bli_sreal(x), bli_simag(x), bli_sreal(b), bli_simag(b), bli_creal(y), bli_cimag(y) ) #define bli_sdscaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_sreal(a), bli_simag(a), bli_dreal(x), bli_dimag(x), bli_sreal(b), bli_simag(b), bli_creal(y), bli_cimag(y) ) #define bli_ddscaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_dreal(a), bli_dimag(a), bli_dreal(x), bli_dimag(x), bli_sreal(b), bli_simag(b), bli_creal(y), bli_cimag(y) ) #define bli_cdscaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_creal(a), bli_cimag(a), bli_dreal(x), bli_dimag(x), bli_sreal(b), bli_simag(b), bli_creal(y), bli_cimag(y) ) #define bli_zdscaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_zreal(a), bli_zimag(a), bli_dreal(x), bli_dimag(x), bli_sreal(b), bli_simag(b), bli_creal(y), bli_cimag(y) ) #define bli_scscaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_sreal(a), bli_simag(a), bli_creal(x), bli_cimag(x), bli_sreal(b), bli_simag(b), bli_creal(y), bli_cimag(y) ) #define bli_dcscaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_dreal(a), bli_dimag(a), bli_creal(x), bli_cimag(x), bli_sreal(b), bli_simag(b), bli_creal(y), bli_cimag(y) ) #define bli_ccscaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_creal(a), bli_cimag(a), bli_creal(x), bli_cimag(x), bli_sreal(b), bli_simag(b), bli_creal(y), bli_cimag(y) ) #define bli_zcscaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_zreal(a), bli_zimag(a), bli_creal(x), bli_cimag(x), bli_sreal(b), bli_simag(b), bli_creal(y), bli_cimag(y) ) #define bli_szscaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_sreal(a), bli_simag(a), bli_zreal(x), bli_zimag(x), bli_sreal(b), bli_simag(b), bli_creal(y), bli_cimag(y) ) #define bli_dzscaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_dreal(a), bli_dimag(a), bli_zreal(x), bli_zimag(x), bli_sreal(b), bli_simag(b), bli_creal(y), bli_cimag(y) ) #define bli_czscaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_creal(a), bli_cimag(a), bli_zreal(x), bli_zimag(x), bli_sreal(b), bli_simag(b), bli_creal(y), bli_cimag(y) ) #define bli_zzscaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_zreal(a), bli_zimag(a), bli_zreal(x), bli_zimag(x), bli_sreal(b), bli_simag(b), bli_creal(y), bli_cimag(y) ) #define bli_ssdcaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_sreal(a), bli_simag(a), bli_sreal(x), bli_simag(x), bli_dreal(b), bli_dimag(b), bli_creal(y), bli_cimag(y) ) #define bli_dsdcaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_dreal(a), bli_dimag(a), bli_sreal(x), bli_simag(x), bli_dreal(b), bli_dimag(b), bli_creal(y), bli_cimag(y) ) #define bli_csdcaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_creal(a), bli_cimag(a), bli_sreal(x), bli_simag(x), bli_dreal(b), bli_dimag(b), bli_creal(y), bli_cimag(y) ) #define bli_zsdcaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_zreal(a), bli_zimag(a), bli_sreal(x), bli_simag(x), bli_dreal(b), bli_dimag(b), bli_creal(y), bli_cimag(y) ) #define bli_sddcaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_sreal(a), bli_simag(a), bli_dreal(x), bli_dimag(x), bli_dreal(b), bli_dimag(b), bli_creal(y), bli_cimag(y) ) #define bli_dddcaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_dreal(a), bli_dimag(a), bli_dreal(x), bli_dimag(x), bli_dreal(b), bli_dimag(b), bli_creal(y), bli_cimag(y) ) #define bli_cddcaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_creal(a), bli_cimag(a), bli_dreal(x), bli_dimag(x), bli_dreal(b), bli_dimag(b), bli_creal(y), bli_cimag(y) ) #define bli_zddcaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_zreal(a), bli_zimag(a), bli_dreal(x), bli_dimag(x), bli_dreal(b), bli_dimag(b), bli_creal(y), bli_cimag(y) ) #define bli_scdcaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_sreal(a), bli_simag(a), bli_creal(x), bli_cimag(x), bli_dreal(b), bli_dimag(b), bli_creal(y), bli_cimag(y) ) #define bli_dcdcaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_dreal(a), bli_dimag(a), bli_creal(x), bli_cimag(x), bli_dreal(b), bli_dimag(b), bli_creal(y), bli_cimag(y) ) #define bli_ccdcaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_creal(a), bli_cimag(a), bli_creal(x), bli_cimag(x), bli_dreal(b), bli_dimag(b), bli_creal(y), bli_cimag(y) ) #define bli_zcdcaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_zreal(a), bli_zimag(a), bli_creal(x), bli_cimag(x), bli_dreal(b), bli_dimag(b), bli_creal(y), bli_cimag(y) ) #define bli_szdcaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_sreal(a), bli_simag(a), bli_zreal(x), bli_zimag(x), bli_dreal(b), bli_dimag(b), bli_creal(y), bli_cimag(y) ) #define bli_dzdcaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_dreal(a), bli_dimag(a), bli_zreal(x), bli_zimag(x), bli_dreal(b), bli_dimag(b), bli_creal(y), bli_cimag(y) ) #define bli_czdcaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_creal(a), bli_cimag(a), bli_zreal(x), bli_zimag(x), bli_dreal(b), bli_dimag(b), bli_creal(y), bli_cimag(y) ) #define bli_zzdcaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_zreal(a), bli_zimag(a), bli_zreal(x), bli_zimag(x), bli_dreal(b), bli_dimag(b), bli_creal(y), bli_cimag(y) ) #define bli_ssccaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_sreal(a), bli_simag(a), bli_sreal(x), bli_simag(x), bli_creal(b), bli_cimag(b), bli_creal(y), bli_cimag(y) ) #define bli_dsccaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_dreal(a), bli_dimag(a), bli_sreal(x), bli_simag(x), bli_creal(b), bli_cimag(b), bli_creal(y), bli_cimag(y) ) #define bli_csccaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_creal(a), bli_cimag(a), bli_sreal(x), bli_simag(x), bli_creal(b), bli_cimag(b), bli_creal(y), bli_cimag(y) ) #define bli_zsccaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_zreal(a), bli_zimag(a), bli_sreal(x), bli_simag(x), bli_creal(b), bli_cimag(b), bli_creal(y), bli_cimag(y) ) #define bli_sdccaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_sreal(a), bli_simag(a), bli_dreal(x), bli_dimag(x), bli_creal(b), bli_cimag(b), bli_creal(y), bli_cimag(y) ) #define bli_ddccaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_dreal(a), bli_dimag(a), bli_dreal(x), bli_dimag(x), bli_creal(b), bli_cimag(b), bli_creal(y), bli_cimag(y) ) #define bli_cdccaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_creal(a), bli_cimag(a), bli_dreal(x), bli_dimag(x), bli_creal(b), bli_cimag(b), bli_creal(y), bli_cimag(y) ) #define bli_zdccaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_zreal(a), bli_zimag(a), bli_dreal(x), bli_dimag(x), bli_creal(b), bli_cimag(b), bli_creal(y), bli_cimag(y) ) #define bli_scccaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_sreal(a), bli_simag(a), bli_creal(x), bli_cimag(x), bli_creal(b), bli_cimag(b), bli_creal(y), bli_cimag(y) ) #define bli_dcccaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_dreal(a), bli_dimag(a), bli_creal(x), bli_cimag(x), bli_creal(b), bli_cimag(b), bli_creal(y), bli_cimag(y) ) #define bli_ccccaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_creal(a), bli_cimag(a), bli_creal(x), bli_cimag(x), bli_creal(b), bli_cimag(b), bli_creal(y), bli_cimag(y) ) #define bli_zcccaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_zreal(a), bli_zimag(a), bli_creal(x), bli_cimag(x), bli_creal(b), bli_cimag(b), bli_creal(y), bli_cimag(y) ) #define bli_szccaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_sreal(a), bli_simag(a), bli_zreal(x), bli_zimag(x), bli_creal(b), bli_cimag(b), bli_creal(y), bli_cimag(y) ) #define bli_dzccaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_dreal(a), bli_dimag(a), bli_zreal(x), bli_zimag(x), bli_creal(b), bli_cimag(b), bli_creal(y), bli_cimag(y) ) #define bli_czccaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_creal(a), bli_cimag(a), bli_zreal(x), bli_zimag(x), bli_creal(b), bli_cimag(b), bli_creal(y), bli_cimag(y) ) #define bli_zzccaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_zreal(a), bli_zimag(a), bli_zreal(x), bli_zimag(x), bli_creal(b), bli_cimag(b), bli_creal(y), bli_cimag(y) ) #define bli_sszcaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_sreal(a), bli_simag(a), bli_sreal(x), bli_simag(x), bli_zreal(b), bli_zimag(b), bli_creal(y), bli_cimag(y) ) #define bli_dszcaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_dreal(a), bli_dimag(a), bli_sreal(x), bli_simag(x), bli_zreal(b), bli_zimag(b), bli_creal(y), bli_cimag(y) ) #define bli_cszcaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_creal(a), bli_cimag(a), bli_sreal(x), bli_simag(x), bli_zreal(b), bli_zimag(b), bli_creal(y), bli_cimag(y) ) #define bli_zszcaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_zreal(a), bli_zimag(a), bli_sreal(x), bli_simag(x), bli_zreal(b), bli_zimag(b), bli_creal(y), bli_cimag(y) ) #define bli_sdzcaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_sreal(a), bli_simag(a), bli_dreal(x), bli_dimag(x), bli_zreal(b), bli_zimag(b), bli_creal(y), bli_cimag(y) ) #define bli_ddzcaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_dreal(a), bli_dimag(a), bli_dreal(x), bli_dimag(x), bli_zreal(b), bli_zimag(b), bli_creal(y), bli_cimag(y) ) #define bli_cdzcaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_creal(a), bli_cimag(a), bli_dreal(x), bli_dimag(x), bli_zreal(b), bli_zimag(b), bli_creal(y), bli_cimag(y) ) #define bli_zdzcaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_zreal(a), bli_zimag(a), bli_dreal(x), bli_dimag(x), bli_zreal(b), bli_zimag(b), bli_creal(y), bli_cimag(y) ) #define bli_sczcaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_sreal(a), bli_simag(a), bli_creal(x), bli_cimag(x), bli_zreal(b), bli_zimag(b), bli_creal(y), bli_cimag(y) ) #define bli_dczcaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_dreal(a), bli_dimag(a), bli_creal(x), bli_cimag(x), bli_zreal(b), bli_zimag(b), bli_creal(y), bli_cimag(y) ) #define bli_cczcaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_creal(a), bli_cimag(a), bli_creal(x), bli_cimag(x), bli_zreal(b), bli_zimag(b), bli_creal(y), bli_cimag(y) ) #define bli_zczcaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_zreal(a), bli_zimag(a), bli_creal(x), bli_cimag(x), bli_zreal(b), bli_zimag(b), bli_creal(y), bli_cimag(y) ) #define bli_szzcaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_sreal(a), bli_simag(a), bli_zreal(x), bli_zimag(x), bli_zreal(b), bli_zimag(b), bli_creal(y), bli_cimag(y) ) #define bli_dzzcaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_dreal(a), bli_dimag(a), bli_zreal(x), bli_zimag(x), bli_zreal(b), bli_zimag(b), bli_creal(y), bli_cimag(y) ) #define bli_czzcaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_creal(a), bli_cimag(a), bli_zreal(x), bli_zimag(x), bli_zreal(b), bli_zimag(b), bli_creal(y), bli_cimag(y) ) #define bli_zzzcaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_zreal(a), bli_zimag(a), bli_zreal(x), bli_zimag(x), bli_zreal(b), bli_zimag(b), bli_creal(y), bli_cimag(y) ) // -- (axby) = (???z) ---------------------------------------------------------- #define bli_ssszaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_sreal(a), bli_simag(a), bli_sreal(x), bli_simag(x), bli_sreal(b), bli_simag(b), bli_zreal(y), bli_zimag(y) ) #define bli_dsszaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_dreal(a), bli_dimag(a), bli_sreal(x), bli_simag(x), bli_sreal(b), bli_simag(b), bli_zreal(y), bli_zimag(y) ) #define bli_csszaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_creal(a), bli_cimag(a), bli_sreal(x), bli_simag(x), bli_sreal(b), bli_simag(b), bli_zreal(y), bli_zimag(y) ) #define bli_zsszaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_zreal(a), bli_zimag(a), bli_sreal(x), bli_simag(x), bli_sreal(b), bli_simag(b), bli_zreal(y), bli_zimag(y) ) #define bli_sdszaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_sreal(a), bli_simag(a), bli_dreal(x), bli_dimag(x), bli_sreal(b), bli_simag(b), bli_zreal(y), bli_zimag(y) ) #define bli_ddszaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_dreal(a), bli_dimag(a), bli_dreal(x), bli_dimag(x), bli_sreal(b), bli_simag(b), bli_zreal(y), bli_zimag(y) ) #define bli_cdszaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_creal(a), bli_cimag(a), bli_dreal(x), bli_dimag(x), bli_sreal(b), bli_simag(b), bli_zreal(y), bli_zimag(y) ) #define bli_zdszaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_zreal(a), bli_zimag(a), bli_dreal(x), bli_dimag(x), bli_sreal(b), bli_simag(b), bli_zreal(y), bli_zimag(y) ) #define bli_scszaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_sreal(a), bli_simag(a), bli_creal(x), bli_cimag(x), bli_sreal(b), bli_simag(b), bli_zreal(y), bli_zimag(y) ) #define bli_dcszaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_dreal(a), bli_dimag(a), bli_creal(x), bli_cimag(x), bli_sreal(b), bli_simag(b), bli_zreal(y), bli_zimag(y) ) #define bli_ccszaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_creal(a), bli_cimag(a), bli_creal(x), bli_cimag(x), bli_sreal(b), bli_simag(b), bli_zreal(y), bli_zimag(y) ) #define bli_zcszaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_zreal(a), bli_zimag(a), bli_creal(x), bli_cimag(x), bli_sreal(b), bli_simag(b), bli_zreal(y), bli_zimag(y) ) #define bli_szszaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_sreal(a), bli_simag(a), bli_zreal(x), bli_zimag(x), bli_sreal(b), bli_simag(b), bli_zreal(y), bli_zimag(y) ) #define bli_dzszaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_dreal(a), bli_dimag(a), bli_zreal(x), bli_zimag(x), bli_sreal(b), bli_simag(b), bli_zreal(y), bli_zimag(y) ) #define bli_czszaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_creal(a), bli_cimag(a), bli_zreal(x), bli_zimag(x), bli_sreal(b), bli_simag(b), bli_zreal(y), bli_zimag(y) ) #define bli_zzszaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_zreal(a), bli_zimag(a), bli_zreal(x), bli_zimag(x), bli_sreal(b), bli_simag(b), bli_zreal(y), bli_zimag(y) ) #define bli_ssdzaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_sreal(a), bli_simag(a), bli_sreal(x), bli_simag(x), bli_dreal(b), bli_dimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_dsdzaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_dreal(a), bli_dimag(a), bli_sreal(x), bli_simag(x), bli_dreal(b), bli_dimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_csdzaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_creal(a), bli_cimag(a), bli_sreal(x), bli_simag(x), bli_dreal(b), bli_dimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_zsdzaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_zreal(a), bli_zimag(a), bli_sreal(x), bli_simag(x), bli_dreal(b), bli_dimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_sddzaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_sreal(a), bli_simag(a), bli_dreal(x), bli_dimag(x), bli_dreal(b), bli_dimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_dddzaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_dreal(a), bli_dimag(a), bli_dreal(x), bli_dimag(x), bli_dreal(b), bli_dimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_cddzaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_creal(a), bli_cimag(a), bli_dreal(x), bli_dimag(x), bli_dreal(b), bli_dimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_zddzaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_zreal(a), bli_zimag(a), bli_dreal(x), bli_dimag(x), bli_dreal(b), bli_dimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_scdzaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_sreal(a), bli_simag(a), bli_creal(x), bli_cimag(x), bli_dreal(b), bli_dimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_dcdzaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_dreal(a), bli_dimag(a), bli_creal(x), bli_cimag(x), bli_dreal(b), bli_dimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_ccdzaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_creal(a), bli_cimag(a), bli_creal(x), bli_cimag(x), bli_dreal(b), bli_dimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_zcdzaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_zreal(a), bli_zimag(a), bli_creal(x), bli_cimag(x), bli_dreal(b), bli_dimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_szdzaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_sreal(a), bli_simag(a), bli_zreal(x), bli_zimag(x), bli_dreal(b), bli_dimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_dzdzaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_dreal(a), bli_dimag(a), bli_zreal(x), bli_zimag(x), bli_dreal(b), bli_dimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_czdzaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_creal(a), bli_cimag(a), bli_zreal(x), bli_zimag(x), bli_dreal(b), bli_dimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_zzdzaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_zreal(a), bli_zimag(a), bli_zreal(x), bli_zimag(x), bli_dreal(b), bli_dimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_ssczaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_sreal(a), bli_simag(a), bli_sreal(x), bli_simag(x), bli_creal(b), bli_cimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_dsczaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_dreal(a), bli_dimag(a), bli_sreal(x), bli_simag(x), bli_creal(b), bli_cimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_csczaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_creal(a), bli_cimag(a), bli_sreal(x), bli_simag(x), bli_creal(b), bli_cimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_zsczaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_zreal(a), bli_zimag(a), bli_sreal(x), bli_simag(x), bli_creal(b), bli_cimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_sdczaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_sreal(a), bli_simag(a), bli_dreal(x), bli_dimag(x), bli_creal(b), bli_cimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_ddczaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_dreal(a), bli_dimag(a), bli_dreal(x), bli_dimag(x), bli_creal(b), bli_cimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_cdczaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_creal(a), bli_cimag(a), bli_dreal(x), bli_dimag(x), bli_creal(b), bli_cimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_zdczaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_zreal(a), bli_zimag(a), bli_dreal(x), bli_dimag(x), bli_creal(b), bli_cimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_scczaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_sreal(a), bli_simag(a), bli_creal(x), bli_cimag(x), bli_creal(b), bli_cimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_dcczaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_dreal(a), bli_dimag(a), bli_creal(x), bli_cimag(x), bli_creal(b), bli_cimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_ccczaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_creal(a), bli_cimag(a), bli_creal(x), bli_cimag(x), bli_creal(b), bli_cimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_zcczaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_zreal(a), bli_zimag(a), bli_creal(x), bli_cimag(x), bli_creal(b), bli_cimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_szczaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_sreal(a), bli_simag(a), bli_zreal(x), bli_zimag(x), bli_creal(b), bli_cimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_dzczaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_dreal(a), bli_dimag(a), bli_zreal(x), bli_zimag(x), bli_creal(b), bli_cimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_czczaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_creal(a), bli_cimag(a), bli_zreal(x), bli_zimag(x), bli_creal(b), bli_cimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_zzczaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_zreal(a), bli_zimag(a), bli_zreal(x), bli_zimag(x), bli_creal(b), bli_cimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_sszzaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_sreal(a), bli_simag(a), bli_sreal(x), bli_simag(x), bli_zreal(b), bli_zimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_dszzaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_dreal(a), bli_dimag(a), bli_sreal(x), bli_simag(x), bli_zreal(b), bli_zimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_cszzaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_creal(a), bli_cimag(a), bli_sreal(x), bli_simag(x), bli_zreal(b), bli_zimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_zszzaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_zreal(a), bli_zimag(a), bli_sreal(x), bli_simag(x), bli_zreal(b), bli_zimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_sdzzaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_sreal(a), bli_simag(a), bli_dreal(x), bli_dimag(x), bli_zreal(b), bli_zimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_ddzzaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_dreal(a), bli_dimag(a), bli_dreal(x), bli_dimag(x), bli_zreal(b), bli_zimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_cdzzaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_creal(a), bli_cimag(a), bli_dreal(x), bli_dimag(x), bli_zreal(b), bli_zimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_zdzzaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_zreal(a), bli_zimag(a), bli_dreal(x), bli_dimag(x), bli_zreal(b), bli_zimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_sczzaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_sreal(a), bli_simag(a), bli_creal(x), bli_cimag(x), bli_zreal(b), bli_zimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_dczzaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_dreal(a), bli_dimag(a), bli_creal(x), bli_cimag(x), bli_zreal(b), bli_zimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_cczzaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_creal(a), bli_cimag(a), bli_creal(x), bli_cimag(x), bli_zreal(b), bli_zimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_zczzaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_zreal(a), bli_zimag(a), bli_creal(x), bli_cimag(x), bli_zreal(b), bli_zimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_szzzaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_sreal(a), bli_simag(a), bli_zreal(x), bli_zimag(x), bli_zreal(b), bli_zimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_dzzzaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_dreal(a), bli_dimag(a), bli_zreal(x), bli_zimag(x), bli_zreal(b), bli_zimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_czzzaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_creal(a), bli_cimag(a), bli_zreal(x), bli_zimag(x), bli_zreal(b), bli_zimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_zzzzaxpbys( a, x, b, y ) bli_cxaxpbyris( bli_zreal(a), bli_zimag(a), bli_zreal(x), bli_zimag(x), bli_zreal(b), bli_zimag(b), bli_zreal(y), bli_zimag(y) ) #else // ifdef BLIS_ENABLE_C99_COMPLEX // -- (axby) = (???c) ---------------------------------------------------------- #define bli_ssscaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_dsscaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_csscaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_zsscaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_sdscaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_ddscaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_cdscaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_zdscaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_scscaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_dcscaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_ccscaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_zcscaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_szscaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_dzscaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_czscaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_zzscaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_ssdcaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_dsdcaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_csdcaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_zsdcaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_sddcaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_dddcaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_cddcaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_zddcaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_scdcaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_dcdcaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_ccdcaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_zcdcaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_szdcaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_dzdcaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_czdcaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_zzdcaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_ssccaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_dsccaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_csccaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_zsccaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_sdccaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_ddccaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_cdccaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_zdccaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_scccaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_dcccaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_ccccaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_zcccaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_szccaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_dzccaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_czccaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_zzccaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_sszcaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_dszcaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_cszcaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_zszcaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_sdzcaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_ddzcaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_cdzcaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_zdzcaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_sczcaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_dczcaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_cczcaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_zczcaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_szzcaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_dzzcaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_czzcaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_zzzcaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } // -- (axby) = (???z) ---------------------------------------------------------- #define bli_ssszaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_dsszaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_csszaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_zsszaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_sdszaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_ddszaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_cdszaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_zdszaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_scszaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_dcszaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_ccszaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_zcszaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_szszaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_dzszaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_czszaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_zzszaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_ssdzaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_dsdzaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_csdzaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_zsdzaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_sddzaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_dddzaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_cddzaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_zddzaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_scdzaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_dcdzaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_ccdzaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_zcdzaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_szdzaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_dzdzaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_czdzaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_zzdzaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_ssczaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_dsczaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_csczaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_zsczaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_sdczaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_ddczaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_cdczaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_zdczaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_scczaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_dcczaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_ccczaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_zcczaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_szczaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_dzczaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_czczaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_zzczaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_sszzaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_dszzaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_cszzaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_zszzaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_sdzzaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_ddzzaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_cdzzaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_zdzzaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_sczzaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_dczzaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_cczzaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_zczzaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_szzzaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_dzzzaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_czzzaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #define bli_zzzzaxpbys( a, x, b, y ) { (y) = (a) * (x) + (b) * (y); } #endif // BLIS_ENABLE_C99_COMPLEX #define bli_saxpbys( a, x, b, y ) bli_ssssaxpbys( a, x, b, y ) #define bli_daxpbys( a, x, b, y ) bli_ddddaxpbys( a, x, b, y ) #define bli_caxpbys( a, x, b, y ) bli_ccccaxpbys( a, x, b, y ) #define bli_zaxpbys( a, x, b, y ) bli_zzzzaxpbys( a, x, b, y ) #endif blis-0.9.0/frame/include/level0/bli_axpyjs.h000066400000000000000000000316061422157504600207060ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_AXPYJS_H #define BLIS_AXPYJS_H // axpyjs // Notes: // - The first char encodes the type of a. // - The second char encodes the type of x. // - The third char encodes the type of y. // -- (axy) = (??s) ------------------------------------------------------------ #define bli_sssaxpyjs( a, x, y ) bli_saxpyjris( bli_sreal(a), bli_simag(a), bli_sreal(x), bli_simag(x), bli_sreal(y), bli_simag(y) ) #define bli_dssaxpyjs( a, x, y ) bli_saxpyjris( bli_dreal(a), bli_dimag(a), bli_sreal(x), bli_simag(x), bli_sreal(y), bli_simag(y) ) #define bli_cssaxpyjs( a, x, y ) bli_saxpyjris( bli_creal(a), bli_cimag(a), bli_sreal(x), bli_simag(x), bli_sreal(y), bli_simag(y) ) #define bli_zssaxpyjs( a, x, y ) bli_saxpyjris( bli_zreal(a), bli_zimag(a), bli_sreal(x), bli_simag(x), bli_sreal(y), bli_simag(y) ) #define bli_sdsaxpyjs( a, x, y ) bli_saxpyjris( bli_sreal(a), bli_simag(a), bli_dreal(x), bli_dimag(x), bli_sreal(y), bli_simag(y) ) #define bli_ddsaxpyjs( a, x, y ) bli_saxpyjris( bli_dreal(a), bli_dimag(a), bli_dreal(x), bli_dimag(x), bli_sreal(y), bli_simag(y) ) #define bli_cdsaxpyjs( a, x, y ) bli_saxpyjris( bli_creal(a), bli_cimag(a), bli_dreal(x), bli_dimag(x), bli_sreal(y), bli_simag(y) ) #define bli_zdsaxpyjs( a, x, y ) bli_saxpyjris( bli_zreal(a), bli_zimag(a), bli_dreal(x), bli_dimag(x), bli_sreal(y), bli_simag(y) ) #define bli_scsaxpyjs( a, x, y ) bli_saxpyjris( bli_sreal(a), bli_simag(a), bli_creal(x), bli_cimag(x), bli_sreal(y), bli_simag(y) ) #define bli_dcsaxpyjs( a, x, y ) bli_saxpyjris( bli_dreal(a), bli_dimag(a), bli_creal(x), bli_cimag(x), bli_sreal(y), bli_simag(y) ) #define bli_ccsaxpyjs( a, x, y ) bli_saxpyjris( bli_creal(a), bli_cimag(a), bli_creal(x), bli_cimag(x), bli_sreal(y), bli_simag(y) ) #define bli_zcsaxpyjs( a, x, y ) bli_saxpyjris( bli_zreal(a), bli_zimag(a), bli_creal(x), bli_cimag(x), bli_sreal(y), bli_simag(y) ) #define bli_szsaxpyjs( a, x, y ) bli_saxpyjris( bli_sreal(a), bli_simag(a), bli_zreal(x), bli_zimag(x), bli_sreal(y), bli_simag(y) ) #define bli_dzsaxpyjs( a, x, y ) bli_saxpyjris( bli_dreal(a), bli_dimag(a), bli_zreal(x), bli_zimag(x), bli_sreal(y), bli_simag(y) ) #define bli_czsaxpyjs( a, x, y ) bli_saxpyjris( bli_creal(a), bli_cimag(a), bli_zreal(x), bli_zimag(x), bli_sreal(y), bli_simag(y) ) #define bli_zzsaxpyjs( a, x, y ) bli_saxpyjris( bli_zreal(a), bli_zimag(a), bli_zreal(x), bli_zimag(x), bli_sreal(y), bli_simag(y) ) // -- (axy) = (??d) ------------------------------------------------------------ #define bli_ssdaxpyjs( a, x, y ) bli_daxpyjris( bli_sreal(a), bli_simag(a), bli_sreal(x), bli_simag(x), bli_dreal(y), bli_dimag(y) ) #define bli_dsdaxpyjs( a, x, y ) bli_daxpyjris( bli_dreal(a), bli_dimag(a), bli_sreal(x), bli_simag(x), bli_dreal(y), bli_dimag(y) ) #define bli_csdaxpyjs( a, x, y ) bli_daxpyjris( bli_creal(a), bli_cimag(a), bli_sreal(x), bli_simag(x), bli_dreal(y), bli_dimag(y) ) #define bli_zsdaxpyjs( a, x, y ) bli_daxpyjris( bli_zreal(a), bli_zimag(a), bli_sreal(x), bli_simag(x), bli_dreal(y), bli_dimag(y) ) #define bli_sddaxpyjs( a, x, y ) bli_daxpyjris( bli_sreal(a), bli_simag(a), bli_dreal(x), bli_dimag(x), bli_dreal(y), bli_dimag(y) ) #define bli_dddaxpyjs( a, x, y ) bli_daxpyjris( bli_dreal(a), bli_dimag(a), bli_dreal(x), bli_dimag(x), bli_dreal(y), bli_dimag(y) ) #define bli_cddaxpyjs( a, x, y ) bli_daxpyjris( bli_creal(a), bli_cimag(a), bli_dreal(x), bli_dimag(x), bli_dreal(y), bli_dimag(y) ) #define bli_zddaxpyjs( a, x, y ) bli_daxpyjris( bli_zreal(a), bli_zimag(a), bli_dreal(x), bli_dimag(x), bli_dreal(y), bli_dimag(y) ) #define bli_scdaxpyjs( a, x, y ) bli_daxpyjris( bli_sreal(a), bli_simag(a), bli_creal(x), bli_cimag(x), bli_dreal(y), bli_dimag(y) ) #define bli_dcdaxpyjs( a, x, y ) bli_daxpyjris( bli_dreal(a), bli_dimag(a), bli_creal(x), bli_cimag(x), bli_dreal(y), bli_dimag(y) ) #define bli_ccdaxpyjs( a, x, y ) bli_daxpyjris( bli_creal(a), bli_cimag(a), bli_creal(x), bli_cimag(x), bli_dreal(y), bli_dimag(y) ) #define bli_zcdaxpyjs( a, x, y ) bli_daxpyjris( bli_zreal(a), bli_zimag(a), bli_creal(x), bli_cimag(x), bli_dreal(y), bli_dimag(y) ) #define bli_szdaxpyjs( a, x, y ) bli_daxpyjris( bli_sreal(a), bli_simag(a), bli_zreal(x), bli_zimag(x), bli_dreal(y), bli_dimag(y) ) #define bli_dzdaxpyjs( a, x, y ) bli_daxpyjris( bli_dreal(a), bli_dimag(a), bli_zreal(x), bli_zimag(x), bli_dreal(y), bli_dimag(y) ) #define bli_czdaxpyjs( a, x, y ) bli_daxpyjris( bli_creal(a), bli_cimag(a), bli_zreal(x), bli_zimag(x), bli_dreal(y), bli_dimag(y) ) #define bli_zzdaxpyjs( a, x, y ) bli_daxpyjris( bli_zreal(a), bli_zimag(a), bli_zreal(x), bli_zimag(x), bli_dreal(y), bli_dimag(y) ) #ifndef BLIS_ENABLE_C99_COMPLEX // -- (axy) = (??c) ------------------------------------------------------------ #define bli_sscaxpyjs( a, x, y ) bli_saxpyjris( bli_sreal(a), bli_simag(a), bli_sreal(x), bli_simag(x), bli_creal(y), bli_cimag(y) ) #define bli_dscaxpyjs( a, x, y ) bli_saxpyjris( bli_dreal(a), bli_dimag(a), bli_sreal(x), bli_simag(x), bli_creal(y), bli_cimag(y) ) #define bli_cscaxpyjs( a, x, y ) bli_caxpyjris( bli_creal(a), bli_cimag(a), bli_sreal(x), bli_simag(x), bli_creal(y), bli_cimag(y) ) #define bli_zscaxpyjs( a, x, y ) bli_caxpyjris( bli_zreal(a), bli_zimag(a), bli_sreal(x), bli_simag(x), bli_creal(y), bli_cimag(y) ) #define bli_sdcaxpyjs( a, x, y ) bli_saxpyjris( bli_sreal(a), bli_simag(a), bli_dreal(x), bli_dimag(x), bli_creal(y), bli_cimag(y) ) #define bli_ddcaxpyjs( a, x, y ) bli_saxpyjris( bli_dreal(a), bli_dimag(a), bli_dreal(x), bli_dimag(x), bli_creal(y), bli_cimag(y) ) #define bli_cdcaxpyjs( a, x, y ) bli_caxpyjris( bli_creal(a), bli_cimag(a), bli_dreal(x), bli_dimag(x), bli_creal(y), bli_cimag(y) ) #define bli_zdcaxpyjs( a, x, y ) bli_caxpyjris( bli_zreal(a), bli_zimag(a), bli_dreal(x), bli_dimag(x), bli_creal(y), bli_cimag(y) ) #define bli_sccaxpyjs( a, x, y ) bli_scaxpyjris( bli_sreal(a), bli_simag(a), bli_creal(x), bli_cimag(x), bli_creal(y), bli_cimag(y) ) #define bli_dccaxpyjs( a, x, y ) bli_scaxpyjris( bli_dreal(a), bli_dimag(a), bli_creal(x), bli_cimag(x), bli_creal(y), bli_cimag(y) ) #define bli_cccaxpyjs( a, x, y ) bli_caxpyjris( bli_creal(a), bli_cimag(a), bli_creal(x), bli_cimag(x), bli_creal(y), bli_cimag(y) ) #define bli_zccaxpyjs( a, x, y ) bli_caxpyjris( bli_zreal(a), bli_zimag(a), bli_creal(x), bli_cimag(x), bli_creal(y), bli_cimag(y) ) #define bli_szcaxpyjs( a, x, y ) bli_scaxpyjris( bli_sreal(a), bli_simag(a), bli_zreal(x), bli_zimag(x), bli_creal(y), bli_cimag(y) ) #define bli_dzcaxpyjs( a, x, y ) bli_scaxpyjris( bli_dreal(a), bli_dimag(a), bli_zreal(x), bli_zimag(x), bli_creal(y), bli_cimag(y) ) #define bli_czcaxpyjs( a, x, y ) bli_caxpyjris( bli_creal(a), bli_cimag(a), bli_zreal(x), bli_zimag(x), bli_creal(y), bli_cimag(y) ) #define bli_zzcaxpyjs( a, x, y ) bli_caxpyjris( bli_zreal(a), bli_zimag(a), bli_zreal(x), bli_zimag(x), bli_creal(y), bli_cimag(y) ) // -- (axy) = (??z) ------------------------------------------------------------ #define bli_sszaxpyjs( a, x, y ) bli_daxpyjris( bli_sreal(a), bli_simag(a), bli_sreal(x), bli_simag(x), bli_zreal(y), bli_zimag(y) ) #define bli_dszaxpyjs( a, x, y ) bli_daxpyjris( bli_dreal(a), bli_dimag(a), bli_sreal(x), bli_simag(x), bli_zreal(y), bli_zimag(y) ) #define bli_cszaxpyjs( a, x, y ) bli_zaxpyjris( bli_creal(a), bli_cimag(a), bli_sreal(x), bli_simag(x), bli_zreal(y), bli_zimag(y) ) #define bli_zszaxpyjs( a, x, y ) bli_zaxpyjris( bli_zreal(a), bli_zimag(a), bli_sreal(x), bli_simag(x), bli_zreal(y), bli_zimag(y) ) #define bli_sdzaxpyjs( a, x, y ) bli_daxpyjris( bli_sreal(a), bli_simag(a), bli_dreal(x), bli_dimag(x), bli_zreal(y), bli_zimag(y) ) #define bli_ddzaxpyjs( a, x, y ) bli_daxpyjris( bli_dreal(a), bli_dimag(a), bli_dreal(x), bli_dimag(x), bli_zreal(y), bli_zimag(y) ) #define bli_cdzaxpyjs( a, x, y ) bli_zaxpyjris( bli_creal(a), bli_cimag(a), bli_dreal(x), bli_dimag(x), bli_zreal(y), bli_zimag(y) ) #define bli_zdzaxpyjs( a, x, y ) bli_zaxpyjris( bli_zreal(a), bli_zimag(a), bli_dreal(x), bli_dimag(x), bli_zreal(y), bli_zimag(y) ) #define bli_sczaxpyjs( a, x, y ) bli_dzaxpyjris( bli_sreal(a), bli_simag(a), bli_creal(x), bli_cimag(x), bli_zreal(y), bli_zimag(y) ) #define bli_dczaxpyjs( a, x, y ) bli_dzaxpyjris( bli_dreal(a), bli_dimag(a), bli_creal(x), bli_cimag(x), bli_zreal(y), bli_zimag(y) ) #define bli_cczaxpyjs( a, x, y ) bli_zaxpyjris( bli_creal(a), bli_cimag(a), bli_creal(x), bli_cimag(x), bli_zreal(y), bli_zimag(y) ) #define bli_zczaxpyjs( a, x, y ) bli_zaxpyjris( bli_zreal(a), bli_zimag(a), bli_creal(x), bli_cimag(x), bli_zreal(y), bli_zimag(y) ) #define bli_szzaxpyjs( a, x, y ) bli_dzaxpyjris( bli_sreal(a), bli_simag(a), bli_zreal(x), bli_zimag(x), bli_zreal(y), bli_zimag(y) ) #define bli_dzzaxpyjs( a, x, y ) bli_dzaxpyjris( bli_dreal(a), bli_dimag(a), bli_zreal(x), bli_zimag(x), bli_zreal(y), bli_zimag(y) ) #define bli_czzaxpyjs( a, x, y ) bli_zaxpyjris( bli_creal(a), bli_cimag(a), bli_zreal(x), bli_zimag(x), bli_zreal(y), bli_zimag(y) ) #define bli_zzzaxpyjs( a, x, y ) bli_zaxpyjris( bli_zreal(a), bli_zimag(a), bli_zreal(x), bli_zimag(x), bli_zreal(y), bli_zimag(y) ) #else // ifdef BLIS_ENABLE_C99_COMPLEX // -- (axy) = (??c) ------------------------------------------------------------ #define bli_sscaxpyjs( a, x, y ) { (y) += (a) * (x); } #define bli_dscaxpyjs( a, x, y ) { (y) += (a) * (x); } #define bli_cscaxpyjs( a, x, y ) { (y) += (a) * (x); } #define bli_zscaxpyjs( a, x, y ) { (y) += (a) * (x); } #define bli_sdcaxpyjs( a, x, y ) { (y) += (a) * (x); } #define bli_ddcaxpyjs( a, x, y ) { (y) += (a) * (x); } #define bli_cdcaxpyjs( a, x, y ) { (y) += (a) * (x); } #define bli_zdcaxpyjs( a, x, y ) { (y) += (a) * (x); } #define bli_sccaxpyjs( a, x, y ) { (y) += (a) * conjf(x); } #define bli_dccaxpyjs( a, x, y ) { (y) += (a) * conjf(x); } #define bli_cccaxpyjs( a, x, y ) { (y) += (a) * conjf(x); } #define bli_zccaxpyjs( a, x, y ) { (y) += (a) * conjf(x); } #define bli_szcaxpyjs( a, x, y ) { (y) += (a) * conj(x); } #define bli_dzcaxpyjs( a, x, y ) { (y) += (a) * conj(x); } #define bli_czcaxpyjs( a, x, y ) { (y) += (a) * conj(x); } #define bli_zzcaxpyjs( a, x, y ) { (y) += (a) * conj(x); } // -- (axy) = (??z) ------------------------------------------------------------ #define bli_sszaxpyjs( a, x, y ) { (y) += (a) * (x); } #define bli_dszaxpyjs( a, x, y ) { (y) += (a) * (x); } #define bli_cszaxpyjs( a, x, y ) { (y) += (a) * (x); } #define bli_zszaxpyjs( a, x, y ) { (y) += (a) * (x); } #define bli_sdzaxpyjs( a, x, y ) { (y) += (a) * (x); } #define bli_ddzaxpyjs( a, x, y ) { (y) += (a) * (x); } #define bli_cdzaxpyjs( a, x, y ) { (y) += (a) * (x); } #define bli_zdzaxpyjs( a, x, y ) { (y) += (a) * (x); } #define bli_sczaxpyjs( a, x, y ) { (y) += (a) * conjf(x); } #define bli_dczaxpyjs( a, x, y ) { (y) += (a) * conjf(x); } #define bli_cczaxpyjs( a, x, y ) { (y) += (a) * conjf(x); } #define bli_zczaxpyjs( a, x, y ) { (y) += (a) * conjf(x); } #define bli_szzaxpyjs( a, x, y ) { (y) += (a) * conj(x); } #define bli_dzzaxpyjs( a, x, y ) { (y) += (a) * conj(x); } #define bli_czzaxpyjs( a, x, y ) { (y) += (a) * conj(x); } #define bli_zzzaxpyjs( a, x, y ) { (y) += (a) * conj(x); } #endif // BLIS_ENABLE_C99_COMPLEX #define bli_saxpyjs( a, x, y ) bli_sssaxpyjs( a, x, y ) #define bli_daxpyjs( a, x, y ) bli_dddaxpyjs( a, x, y ) #define bli_caxpyjs( a, x, y ) bli_cccaxpyjs( a, x, y ) #define bli_zaxpyjs( a, x, y ) bli_zzzaxpyjs( a, x, y ) #endif blis-0.9.0/frame/include/level0/bli_axpys.h000066400000000000000000000312231422157504600205270ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_AXPYS_H #define BLIS_AXPYS_H // axpys // Notes: // - The first char encodes the type of a. // - The second char encodes the type of x. // - The third char encodes the type of y. // -- (axy) = (??s) ------------------------------------------------------------ #define bli_sssaxpys( a, x, y ) bli_saxpyris( bli_sreal(a), bli_simag(a), bli_sreal(x), bli_simag(x), bli_sreal(y), bli_simag(y) ) #define bli_dssaxpys( a, x, y ) bli_saxpyris( bli_dreal(a), bli_dimag(a), bli_sreal(x), bli_simag(x), bli_sreal(y), bli_simag(y) ) #define bli_cssaxpys( a, x, y ) bli_saxpyris( bli_creal(a), bli_cimag(a), bli_sreal(x), bli_simag(x), bli_sreal(y), bli_simag(y) ) #define bli_zssaxpys( a, x, y ) bli_saxpyris( bli_zreal(a), bli_zimag(a), bli_sreal(x), bli_simag(x), bli_sreal(y), bli_simag(y) ) #define bli_sdsaxpys( a, x, y ) bli_saxpyris( bli_sreal(a), bli_simag(a), bli_dreal(x), bli_dimag(x), bli_sreal(y), bli_simag(y) ) #define bli_ddsaxpys( a, x, y ) bli_saxpyris( bli_dreal(a), bli_dimag(a), bli_dreal(x), bli_dimag(x), bli_sreal(y), bli_simag(y) ) #define bli_cdsaxpys( a, x, y ) bli_saxpyris( bli_creal(a), bli_cimag(a), bli_dreal(x), bli_dimag(x), bli_sreal(y), bli_simag(y) ) #define bli_zdsaxpys( a, x, y ) bli_saxpyris( bli_zreal(a), bli_zimag(a), bli_dreal(x), bli_dimag(x), bli_sreal(y), bli_simag(y) ) #define bli_scsaxpys( a, x, y ) bli_saxpyris( bli_sreal(a), bli_simag(a), bli_creal(x), bli_cimag(x), bli_sreal(y), bli_simag(y) ) #define bli_dcsaxpys( a, x, y ) bli_saxpyris( bli_dreal(a), bli_dimag(a), bli_creal(x), bli_cimag(x), bli_sreal(y), bli_simag(y) ) #define bli_ccsaxpys( a, x, y ) bli_saxpyris( bli_creal(a), bli_cimag(a), bli_creal(x), bli_cimag(x), bli_sreal(y), bli_simag(y) ) #define bli_zcsaxpys( a, x, y ) bli_saxpyris( bli_zreal(a), bli_zimag(a), bli_creal(x), bli_cimag(x), bli_sreal(y), bli_simag(y) ) #define bli_szsaxpys( a, x, y ) bli_saxpyris( bli_sreal(a), bli_simag(a), bli_zreal(x), bli_zimag(x), bli_sreal(y), bli_simag(y) ) #define bli_dzsaxpys( a, x, y ) bli_saxpyris( bli_dreal(a), bli_dimag(a), bli_zreal(x), bli_zimag(x), bli_sreal(y), bli_simag(y) ) #define bli_czsaxpys( a, x, y ) bli_saxpyris( bli_creal(a), bli_cimag(a), bli_zreal(x), bli_zimag(x), bli_sreal(y), bli_simag(y) ) #define bli_zzsaxpys( a, x, y ) bli_saxpyris( bli_zreal(a), bli_zimag(a), bli_zreal(x), bli_zimag(x), bli_sreal(y), bli_simag(y) ) // -- (axy) = (??d) ------------------------------------------------------------ #define bli_ssdaxpys( a, x, y ) bli_daxpyris( bli_sreal(a), bli_simag(a), bli_sreal(x), bli_simag(x), bli_dreal(y), bli_dimag(y) ) #define bli_dsdaxpys( a, x, y ) bli_daxpyris( bli_dreal(a), bli_dimag(a), bli_sreal(x), bli_simag(x), bli_dreal(y), bli_dimag(y) ) #define bli_csdaxpys( a, x, y ) bli_daxpyris( bli_creal(a), bli_cimag(a), bli_sreal(x), bli_simag(x), bli_dreal(y), bli_dimag(y) ) #define bli_zsdaxpys( a, x, y ) bli_daxpyris( bli_zreal(a), bli_zimag(a), bli_sreal(x), bli_simag(x), bli_dreal(y), bli_dimag(y) ) #define bli_sddaxpys( a, x, y ) bli_daxpyris( bli_sreal(a), bli_simag(a), bli_dreal(x), bli_dimag(x), bli_dreal(y), bli_dimag(y) ) #define bli_dddaxpys( a, x, y ) bli_daxpyris( bli_dreal(a), bli_dimag(a), bli_dreal(x), bli_dimag(x), bli_dreal(y), bli_dimag(y) ) #define bli_cddaxpys( a, x, y ) bli_daxpyris( bli_creal(a), bli_cimag(a), bli_dreal(x), bli_dimag(x), bli_dreal(y), bli_dimag(y) ) #define bli_zddaxpys( a, x, y ) bli_daxpyris( bli_zreal(a), bli_zimag(a), bli_dreal(x), bli_dimag(x), bli_dreal(y), bli_dimag(y) ) #define bli_scdaxpys( a, x, y ) bli_daxpyris( bli_sreal(a), bli_simag(a), bli_creal(x), bli_cimag(x), bli_dreal(y), bli_dimag(y) ) #define bli_dcdaxpys( a, x, y ) bli_daxpyris( bli_dreal(a), bli_dimag(a), bli_creal(x), bli_cimag(x), bli_dreal(y), bli_dimag(y) ) #define bli_ccdaxpys( a, x, y ) bli_daxpyris( bli_creal(a), bli_cimag(a), bli_creal(x), bli_cimag(x), bli_dreal(y), bli_dimag(y) ) #define bli_zcdaxpys( a, x, y ) bli_daxpyris( bli_zreal(a), bli_zimag(a), bli_creal(x), bli_cimag(x), bli_dreal(y), bli_dimag(y) ) #define bli_szdaxpys( a, x, y ) bli_daxpyris( bli_sreal(a), bli_simag(a), bli_zreal(x), bli_zimag(x), bli_dreal(y), bli_dimag(y) ) #define bli_dzdaxpys( a, x, y ) bli_daxpyris( bli_dreal(a), bli_dimag(a), bli_zreal(x), bli_zimag(x), bli_dreal(y), bli_dimag(y) ) #define bli_czdaxpys( a, x, y ) bli_daxpyris( bli_creal(a), bli_cimag(a), bli_zreal(x), bli_zimag(x), bli_dreal(y), bli_dimag(y) ) #define bli_zzdaxpys( a, x, y ) bli_daxpyris( bli_zreal(a), bli_zimag(a), bli_zreal(x), bli_zimag(x), bli_dreal(y), bli_dimag(y) ) #ifndef BLIS_ENABLE_C99_COMPLEX // -- (axy) = (??c) ------------------------------------------------------------ #define bli_sscaxpys( a, x, y ) bli_saxpyris( bli_sreal(a), bli_simag(a), bli_sreal(x), bli_simag(x), bli_creal(y), bli_cimag(y) ) #define bli_dscaxpys( a, x, y ) bli_saxpyris( bli_dreal(a), bli_dimag(a), bli_sreal(x), bli_simag(x), bli_creal(y), bli_cimag(y) ) #define bli_cscaxpys( a, x, y ) bli_caxpyris( bli_creal(a), bli_cimag(a), bli_sreal(x), bli_simag(x), bli_creal(y), bli_cimag(y) ) #define bli_zscaxpys( a, x, y ) bli_caxpyris( bli_zreal(a), bli_zimag(a), bli_sreal(x), bli_simag(x), bli_creal(y), bli_cimag(y) ) #define bli_sdcaxpys( a, x, y ) bli_saxpyris( bli_sreal(a), bli_simag(a), bli_dreal(x), bli_dimag(x), bli_creal(y), bli_cimag(y) ) #define bli_ddcaxpys( a, x, y ) bli_saxpyris( bli_dreal(a), bli_dimag(a), bli_dreal(x), bli_dimag(x), bli_creal(y), bli_cimag(y) ) #define bli_cdcaxpys( a, x, y ) bli_caxpyris( bli_creal(a), bli_cimag(a), bli_dreal(x), bli_dimag(x), bli_creal(y), bli_cimag(y) ) #define bli_zdcaxpys( a, x, y ) bli_caxpyris( bli_zreal(a), bli_zimag(a), bli_dreal(x), bli_dimag(x), bli_creal(y), bli_cimag(y) ) #define bli_sccaxpys( a, x, y ) bli_scaxpyris( bli_sreal(a), bli_simag(a), bli_creal(x), bli_cimag(x), bli_creal(y), bli_cimag(y) ) #define bli_dccaxpys( a, x, y ) bli_scaxpyris( bli_dreal(a), bli_dimag(a), bli_creal(x), bli_cimag(x), bli_creal(y), bli_cimag(y) ) #define bli_cccaxpys( a, x, y ) bli_caxpyris( bli_creal(a), bli_cimag(a), bli_creal(x), bli_cimag(x), bli_creal(y), bli_cimag(y) ) #define bli_zccaxpys( a, x, y ) bli_caxpyris( bli_zreal(a), bli_zimag(a), bli_creal(x), bli_cimag(x), bli_creal(y), bli_cimag(y) ) #define bli_szcaxpys( a, x, y ) bli_scaxpyris( bli_sreal(a), bli_simag(a), bli_zreal(x), bli_zimag(x), bli_creal(y), bli_cimag(y) ) #define bli_dzcaxpys( a, x, y ) bli_scaxpyris( bli_dreal(a), bli_dimag(a), bli_zreal(x), bli_zimag(x), bli_creal(y), bli_cimag(y) ) #define bli_czcaxpys( a, x, y ) bli_caxpyris( bli_creal(a), bli_cimag(a), bli_zreal(x), bli_zimag(x), bli_creal(y), bli_cimag(y) ) #define bli_zzcaxpys( a, x, y ) bli_caxpyris( bli_zreal(a), bli_zimag(a), bli_zreal(x), bli_zimag(x), bli_creal(y), bli_cimag(y) ) // -- (axy) = (??z) ------------------------------------------------------------ #define bli_sszaxpys( a, x, y ) bli_daxpyris( bli_sreal(a), bli_simag(a), bli_sreal(x), bli_simag(x), bli_zreal(y), bli_zimag(y) ) #define bli_dszaxpys( a, x, y ) bli_daxpyris( bli_dreal(a), bli_dimag(a), bli_sreal(x), bli_simag(x), bli_zreal(y), bli_zimag(y) ) #define bli_cszaxpys( a, x, y ) bli_zaxpyris( bli_creal(a), bli_cimag(a), bli_sreal(x), bli_simag(x), bli_zreal(y), bli_zimag(y) ) #define bli_zszaxpys( a, x, y ) bli_zaxpyris( bli_zreal(a), bli_zimag(a), bli_sreal(x), bli_simag(x), bli_zreal(y), bli_zimag(y) ) #define bli_sdzaxpys( a, x, y ) bli_daxpyris( bli_sreal(a), bli_simag(a), bli_dreal(x), bli_dimag(x), bli_zreal(y), bli_zimag(y) ) #define bli_ddzaxpys( a, x, y ) bli_daxpyris( bli_dreal(a), bli_dimag(a), bli_dreal(x), bli_dimag(x), bli_zreal(y), bli_zimag(y) ) #define bli_cdzaxpys( a, x, y ) bli_zaxpyris( bli_creal(a), bli_cimag(a), bli_dreal(x), bli_dimag(x), bli_zreal(y), bli_zimag(y) ) #define bli_zdzaxpys( a, x, y ) bli_zaxpyris( bli_zreal(a), bli_zimag(a), bli_dreal(x), bli_dimag(x), bli_zreal(y), bli_zimag(y) ) #define bli_sczaxpys( a, x, y ) bli_dzaxpyris( bli_sreal(a), bli_simag(a), bli_creal(x), bli_cimag(x), bli_zreal(y), bli_zimag(y) ) #define bli_dczaxpys( a, x, y ) bli_dzaxpyris( bli_dreal(a), bli_dimag(a), bli_creal(x), bli_cimag(x), bli_zreal(y), bli_zimag(y) ) #define bli_cczaxpys( a, x, y ) bli_zaxpyris( bli_creal(a), bli_cimag(a), bli_creal(x), bli_cimag(x), bli_zreal(y), bli_zimag(y) ) #define bli_zczaxpys( a, x, y ) bli_zaxpyris( bli_zreal(a), bli_zimag(a), bli_creal(x), bli_cimag(x), bli_zreal(y), bli_zimag(y) ) #define bli_szzaxpys( a, x, y ) bli_dzaxpyris( bli_sreal(a), bli_simag(a), bli_zreal(x), bli_zimag(x), bli_zreal(y), bli_zimag(y) ) #define bli_dzzaxpys( a, x, y ) bli_dzaxpyris( bli_dreal(a), bli_dimag(a), bli_zreal(x), bli_zimag(x), bli_zreal(y), bli_zimag(y) ) #define bli_czzaxpys( a, x, y ) bli_zaxpyris( bli_creal(a), bli_cimag(a), bli_zreal(x), bli_zimag(x), bli_zreal(y), bli_zimag(y) ) #define bli_zzzaxpys( a, x, y ) bli_zaxpyris( bli_zreal(a), bli_zimag(a), bli_zreal(x), bli_zimag(x), bli_zreal(y), bli_zimag(y) ) #else // ifdef BLIS_ENABLE_C99_COMPLEX // -- (axy) = (??c) ------------------------------------------------------------ #define bli_sscaxpys( a, x, y ) { (y) += (a) * (x); } #define bli_dscaxpys( a, x, y ) { (y) += (a) * (x); } #define bli_cscaxpys( a, x, y ) { (y) += (a) * (x); } #define bli_zscaxpys( a, x, y ) { (y) += (a) * (x); } #define bli_sdcaxpys( a, x, y ) { (y) += (a) * (x); } #define bli_ddcaxpys( a, x, y ) { (y) += (a) * (x); } #define bli_cdcaxpys( a, x, y ) { (y) += (a) * (x); } #define bli_zdcaxpys( a, x, y ) { (y) += (a) * (x); } #define bli_sccaxpys( a, x, y ) { (y) += (a) * (x); } #define bli_dccaxpys( a, x, y ) { (y) += (a) * (x); } #define bli_cccaxpys( a, x, y ) { (y) += (a) * (x); } #define bli_zccaxpys( a, x, y ) { (y) += (a) * (x); } #define bli_szcaxpys( a, x, y ) { (y) += (a) * (x); } #define bli_dzcaxpys( a, x, y ) { (y) += (a) * (x); } #define bli_czcaxpys( a, x, y ) { (y) += (a) * (x); } #define bli_zzcaxpys( a, x, y ) { (y) += (a) * (x); } // -- (axy) = (??z) ------------------------------------------------------------ #define bli_sszaxpys( a, x, y ) { (y) += (a) * (x); } #define bli_dszaxpys( a, x, y ) { (y) += (a) * (x); } #define bli_cszaxpys( a, x, y ) { (y) += (a) * (x); } #define bli_zszaxpys( a, x, y ) { (y) += (a) * (x); } #define bli_sdzaxpys( a, x, y ) { (y) += (a) * (x); } #define bli_ddzaxpys( a, x, y ) { (y) += (a) * (x); } #define bli_cdzaxpys( a, x, y ) { (y) += (a) * (x); } #define bli_zdzaxpys( a, x, y ) { (y) += (a) * (x); } #define bli_sczaxpys( a, x, y ) { (y) += (a) * (x); } #define bli_dczaxpys( a, x, y ) { (y) += (a) * (x); } #define bli_cczaxpys( a, x, y ) { (y) += (a) * (x); } #define bli_zczaxpys( a, x, y ) { (y) += (a) * (x); } #define bli_szzaxpys( a, x, y ) { (y) += (a) * (x); } #define bli_dzzaxpys( a, x, y ) { (y) += (a) * (x); } #define bli_czzaxpys( a, x, y ) { (y) += (a) * (x); } #define bli_zzzaxpys( a, x, y ) { (y) += (a) * (x); } #endif // BLIS_ENABLE_C99_COMPLEX #define bli_saxpys( a, x, y ) bli_sssaxpys( a, x, y ) #define bli_daxpys( a, x, y ) bli_dddaxpys( a, x, y ) #define bli_caxpys( a, x, y ) bli_cccaxpys( a, x, y ) #define bli_zaxpys( a, x, y ) bli_zzzaxpys( a, x, y ) #endif blis-0.9.0/frame/include/level0/bli_conjs.h000066400000000000000000000042401422157504600204760ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_CONJS_H #define BLIS_CONJS_H // conjs #define bli_sconjs( x ) bli_sconjris( bli_sreal(x), bli_simag(x) ) #define bli_dconjs( x ) bli_dconjris( bli_dreal(x), bli_dimag(x) ) #ifndef BLIS_ENABLE_C99_COMPLEX #define bli_cconjs( x ) bli_cconjris( bli_creal(x), bli_cimag(x) ) #define bli_zconjs( x ) bli_zconjris( bli_zreal(x), bli_zimag(x) ) #else // ifdef BLIS_ENABLE_C99_COMPLEX #define bli_cconjs( x ) { (x) = conjf(x); } #define bli_zconjs( x ) { (x) = conj (x); } #endif // BLIS_ENABLE_C99_COMPLEX #endif blis-0.9.0/frame/include/level0/bli_constants.h000066400000000000000000000062051422157504600214010ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_CONSTANTS_H #define BLIS_CONSTANTS_H // return pointers to constants // 1 #define bli_s1 \ \ ( ( float* ) bli_obj_buffer_for_const( BLIS_FLOAT, &BLIS_ONE ) ) #define bli_d1 \ \ ( ( double* ) bli_obj_buffer_for_const( BLIS_DOUBLE, &BLIS_ONE ) ) #define bli_c1 \ \ ( ( scomplex* ) bli_obj_buffer_for_const( BLIS_SCOMPLEX, &BLIS_ONE ) ) #define bli_z1 \ \ ( ( dcomplex* ) bli_obj_buffer_for_const( BLIS_DCOMPLEX, &BLIS_ONE ) ) #define bli_i1 \ \ ( ( gint_t* ) bli_obj_buffer_for_const( BLIS_INT, &BLIS_ONE ) ) // 0 #define bli_s0 \ \ ( ( float* ) bli_obj_buffer_for_const( BLIS_FLOAT, &BLIS_ZERO ) ) #define bli_d0 \ \ ( ( double* ) bli_obj_buffer_for_const( BLIS_DOUBLE, &BLIS_ZERO ) ) #define bli_c0 \ \ ( ( scomplex* ) bli_obj_buffer_for_const( BLIS_SCOMPLEX, &BLIS_ZERO ) ) #define bli_z0 \ \ ( ( dcomplex* ) bli_obj_buffer_for_const( BLIS_DCOMPLEX, &BLIS_ZERO ) ) #define bli_i0 \ \ ( ( gint_t* ) bli_obj_buffer_for_const( BLIS_INT, &BLIS_ZERO ) ) // -1 #define bli_sm1 \ \ ( ( float* ) bli_obj_buffer_for_const( BLIS_FLOAT, &BLIS_MINUS_ONE ) ) #define bli_dm1 \ \ ( ( double* ) bli_obj_buffer_for_const( BLIS_DOUBLE, &BLIS_MINUS_ONE ) ) #define bli_cm1 \ \ ( ( scomplex* ) bli_obj_buffer_for_const( BLIS_SCOMPLEX, &BLIS_MINUS_ONE ) ) #define bli_zm1 \ \ ( ( dcomplex* ) bli_obj_buffer_for_const( BLIS_DCOMPLEX, &BLIS_MINUS_ONE ) ) #define bli_im1 \ \ ( ( gint_t* ) bli_obj_buffer_for_const( BLIS_INT, &BLIS_MINUS_ONE ) ) #endif blis-0.9.0/frame/include/level0/bli_copycjs.h000066400000000000000000000113171422157504600210370ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_COPYCJS_H #define BLIS_COPYCJS_H // copycjs // Notes: // - The first char encodes the type of x. // - The second char encodes the type of y. #define bli_sscopycjs( conjx, x, y ) bli_scopycjris( conjx, bli_sreal(x), bli_simag(x), bli_sreal(y), bli_simag(y) ) #define bli_dscopycjs( conjx, x, y ) bli_scopycjris( conjx, bli_dreal(x), bli_dimag(x), bli_sreal(y), bli_simag(y) ) #define bli_cscopycjs( conjx, x, y ) bli_scopycjris( conjx, bli_creal(x), bli_cimag(x), bli_sreal(y), bli_simag(y) ) #define bli_zscopycjs( conjx, x, y ) bli_scopycjris( conjx, bli_zreal(x), bli_zimag(x), bli_sreal(y), bli_simag(y) ) #define bli_sdcopycjs( conjx, x, y ) bli_dcopycjris( conjx, bli_sreal(x), bli_simag(x), bli_dreal(y), bli_dimag(y) ) #define bli_ddcopycjs( conjx, x, y ) bli_dcopycjris( conjx, bli_dreal(x), bli_dimag(x), bli_dreal(y), bli_dimag(y) ) #define bli_cdcopycjs( conjx, x, y ) bli_dcopycjris( conjx, bli_creal(x), bli_cimag(x), bli_dreal(y), bli_dimag(y) ) #define bli_zdcopycjs( conjx, x, y ) bli_dcopycjris( conjx, bli_zreal(x), bli_zimag(x), bli_dreal(y), bli_dimag(y) ) #ifndef BLIS_ENABLE_C99_COMPLEX #define bli_sccopycjs( conjx, x, y ) bli_ccopycjris( conjx, bli_sreal(x), bli_simag(x), bli_creal(y), bli_cimag(y) ) #define bli_dccopycjs( conjx, x, y ) bli_ccopycjris( conjx, bli_dreal(x), bli_dimag(x), bli_creal(y), bli_cimag(y) ) #define bli_cccopycjs( conjx, x, y ) bli_ccopycjris( conjx, bli_creal(x), bli_cimag(x), bli_creal(y), bli_cimag(y) ) #define bli_zccopycjs( conjx, x, y ) bli_ccopycjris( conjx, bli_zreal(x), bli_zimag(x), bli_creal(y), bli_cimag(y) ) #define bli_szcopycjs( conjx, x, y ) bli_zcopycjris( conjx, bli_sreal(x), bli_simag(x), bli_zreal(y), bli_zimag(y) ) #define bli_dzcopycjs( conjx, x, y ) bli_zcopycjris( conjx, bli_dreal(x), bli_dimag(x), bli_zreal(y), bli_zimag(y) ) #define bli_czcopycjs( conjx, x, y ) bli_zcopycjris( conjx, bli_creal(x), bli_cimag(x), bli_zreal(y), bli_zimag(y) ) #define bli_zzcopycjs( conjx, x, y ) bli_zcopycjris( conjx, bli_zreal(x), bli_zimag(x), bli_zreal(y), bli_zimag(y) ) #else // ifdef BLIS_ENABLE_C99_COMPLEX #define bli_sccopycjs( conjx, x, y ) { (y) = (x); } #define bli_dccopycjs( conjx, x, y ) { (y) = (x); } #define bli_cccopycjs( conjx, x, y ) { (y) = ( bli_is_conj( conjx ) ? conjf(x) : (x) ); } #define bli_zccopycjs( conjx, x, y ) { (y) = ( bli_is_conj( conjx ) ? conj (x) : (x) ); } #define bli_szcopycjs( conjx, x, y ) { (y) = (x); } #define bli_dzcopycjs( conjx, x, y ) { (y) = (x); } #define bli_czcopycjs( conjx, x, y ) { (y) = ( bli_is_conj( conjx ) ? conjf(x) : (x) ); } #define bli_zzcopycjs( conjx, x, y ) { (y) = ( bli_is_conj( conjx ) ? conj (x) : (x) ); } #endif // BLIS_ENABLE_C99_COMPLEX #define bli_iicopycjs( conjx, x, y ) { (y) = ( gint_t ) (x); } #define bli_scopycjs( conjx, x, y ) bli_sscopycjs( conjx, x, y ) #define bli_dcopycjs( conjx, x, y ) bli_ddcopycjs( conjx, x, y ) #define bli_ccopycjs( conjx, x, y ) bli_cccopycjs( conjx, x, y ) #define bli_zcopycjs( conjx, x, y ) bli_zzcopycjs( conjx, x, y ) #define bli_icopycjs( conjx, x, y ) bli_iicopycjs( conjx, x, y ) #endif blis-0.9.0/frame/include/level0/bli_copyjnzs.h000066400000000000000000000077501422157504600212520ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_COPYJNZS_H #define BLIS_COPYJNZS_H // copyjnzs // Notes: // - The first char encodes the type of x. // - The second char encodes the type of y. #define bli_sscopyjnzs( x, y ) bli_scopyjris( bli_sreal(x), bli_simag(x), bli_sreal(y), bli_simag(y) ) #define bli_dscopyjnzs( x, y ) bli_scopyjris( bli_dreal(x), bli_dimag(x), bli_sreal(y), bli_simag(y) ) #define bli_cscopyjnzs( x, y ) bli_scopyjris( bli_creal(x), bli_cimag(x), bli_sreal(y), bli_simag(y) ) #define bli_zscopyjnzs( x, y ) bli_scopyjris( bli_zreal(x), bli_zimag(x), bli_sreal(y), bli_simag(y) ) #define bli_sdcopyjnzs( x, y ) bli_dcopyjris( bli_sreal(x), bli_simag(x), bli_dreal(y), bli_dimag(y) ) #define bli_ddcopyjnzs( x, y ) bli_dcopyjris( bli_dreal(x), bli_dimag(x), bli_dreal(y), bli_dimag(y) ) #define bli_cdcopyjnzs( x, y ) bli_dcopyjris( bli_creal(x), bli_cimag(x), bli_dreal(y), bli_dimag(y) ) #define bli_zdcopyjnzs( x, y ) bli_dcopyjris( bli_zreal(x), bli_zimag(x), bli_dreal(y), bli_dimag(y) ) // NOTE: Use of scopyjris() (implemented in terms of scopyris()), is so we // don't touch the imaginary part of y. #define bli_sccopyjnzs( x, y ) bli_scopyjris( bli_sreal(x), bli_simag(x), bli_creal(y), bli_cimag(y) ) #define bli_dccopyjnzs( x, y ) bli_scopyjris( bli_dreal(x), bli_dimag(x), bli_creal(y), bli_cimag(y) ) #define bli_cccopyjnzs( x, y ) bli_ccopyjris( bli_creal(x), bli_cimag(x), bli_creal(y), bli_cimag(y) ) #define bli_zccopyjnzs( x, y ) bli_ccopyjris( bli_zreal(x), bli_zimag(x), bli_creal(y), bli_cimag(y) ) // NOTE: Use of dcopyjris() (implemented in terms of dcopyris()), is so we // don't touch the imaginary part of y. #define bli_szcopyjnzs( x, y ) bli_dcopyjris( bli_sreal(x), bli_simag(x), bli_zreal(y), bli_zimag(y) ) #define bli_dzcopyjnzs( x, y ) bli_dcopyjris( bli_dreal(x), bli_dimag(x), bli_zreal(y), bli_zimag(y) ) #define bli_czcopyjnzs( x, y ) bli_zcopyjris( bli_creal(x), bli_cimag(x), bli_zreal(y), bli_zimag(y) ) #define bli_zzcopyjnzs( x, y ) bli_zcopyjris( bli_zreal(x), bli_zimag(x), bli_zreal(y), bli_zimag(y) ) #define bli_iicopyjnzs( x, y ) { (y) = ( gint_t ) (x); } #define bli_scopyjnzs( x, y ) bli_sscopyjnzs( x, y ) #define bli_dcopyjnzs( x, y ) bli_ddcopyjnzs( x, y ) #define bli_ccopyjnzs( x, y ) bli_cccopyjnzs( x, y ) #define bli_zcopyjnzs( x, y ) bli_zzcopyjnzs( x, y ) #define bli_icopyjnzs( x, y ) bli_iicopyjnzs( x, y ) #endif blis-0.9.0/frame/include/level0/bli_copyjs.h000066400000000000000000000103041422157504600206670ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_COPYJS_H #define BLIS_COPYJS_H // copyjs // Notes: // - The first char encodes the type of x. // - The second char encodes the type of y. #define bli_sscopyjs( x, y ) bli_scopyjris( bli_sreal(x), bli_simag(x), bli_sreal(y), bli_simag(y) ) #define bli_dscopyjs( x, y ) bli_scopyjris( bli_dreal(x), bli_dimag(x), bli_sreal(y), bli_simag(y) ) #define bli_cscopyjs( x, y ) bli_scopyjris( bli_creal(x), bli_cimag(x), bli_sreal(y), bli_simag(y) ) #define bli_zscopyjs( x, y ) bli_scopyjris( bli_zreal(x), bli_zimag(x), bli_sreal(y), bli_simag(y) ) #define bli_sdcopyjs( x, y ) bli_dcopyjris( bli_sreal(x), bli_simag(x), bli_dreal(y), bli_dimag(y) ) #define bli_ddcopyjs( x, y ) bli_dcopyjris( bli_dreal(x), bli_dimag(x), bli_dreal(y), bli_dimag(y) ) #define bli_cdcopyjs( x, y ) bli_dcopyjris( bli_creal(x), bli_cimag(x), bli_dreal(y), bli_dimag(y) ) #define bli_zdcopyjs( x, y ) bli_dcopyjris( bli_zreal(x), bli_zimag(x), bli_dreal(y), bli_dimag(y) ) #ifndef BLIS_ENABLE_C99_COMPLEX #define bli_sccopyjs( x, y ) bli_ccopyjris( bli_sreal(x), bli_simag(x), bli_creal(y), bli_cimag(y) ) #define bli_dccopyjs( x, y ) bli_ccopyjris( bli_dreal(x), bli_dimag(x), bli_creal(y), bli_cimag(y) ) #define bli_cccopyjs( x, y ) bli_ccopyjris( bli_creal(x), bli_cimag(x), bli_creal(y), bli_cimag(y) ) #define bli_zccopyjs( x, y ) bli_ccopyjris( bli_zreal(x), bli_zimag(x), bli_creal(y), bli_cimag(y) ) #define bli_szcopyjs( x, y ) bli_zcopyjris( bli_sreal(x), bli_simag(x), bli_zreal(y), bli_zimag(y) ) #define bli_dzcopyjs( x, y ) bli_zcopyjris( bli_dreal(x), bli_dimag(x), bli_zreal(y), bli_zimag(y) ) #define bli_czcopyjs( x, y ) bli_zcopyjris( bli_creal(x), bli_cimag(x), bli_zreal(y), bli_zimag(y) ) #define bli_zzcopyjs( x, y ) bli_zcopyjris( bli_zreal(x), bli_zimag(x), bli_zreal(y), bli_zimag(y) ) #else // ifdef BLIS_ENABLE_C99_COMPLEX #define bli_sccopyjs( x, y ) { (y) = (x); } #define bli_dccopyjs( x, y ) { (y) = (x); } #define bli_cccopyjs( x, y ) { (y) = conjf(x); } #define bli_zccopyjs( x, y ) { (y) = conj (x); } #define bli_szcopyjs( x, y ) { (y) = (x); } #define bli_dzcopyjs( x, y ) { (y) = (x); } #define bli_czcopyjs( x, y ) { (y) = conjf(x); } #define bli_zzcopyjs( x, y ) { (y) = conj (x); } #endif // BLIS_ENABLE_C99_COMPLEX #define bli_iicopyjs( x, y ) { (y) = ( gint_t ) (x); } #define bli_scopyjs( x, y ) bli_sscopyjs( x, y ) #define bli_dcopyjs( x, y ) bli_ddcopyjs( x, y ) #define bli_ccopyjs( x, y ) bli_cccopyjs( x, y ) #define bli_zcopyjs( x, y ) bli_zzcopyjs( x, y ) #define bli_icopyjs( x, y ) bli_iicopyjs( x, y ) #endif blis-0.9.0/frame/include/level0/bli_copynzs.h000066400000000000000000000075461422157504600211030ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_COPYNZS_H #define BLIS_COPYNZS_H // copynzs // Notes: // - The first char encodes the type of x. // - The second char encodes the type of y. #define bli_sscopynzs( x, y ) bli_scopyris( bli_sreal(x), bli_simag(x), bli_sreal(y), bli_simag(y) ) #define bli_dscopynzs( x, y ) bli_scopyris( bli_dreal(x), bli_dimag(x), bli_sreal(y), bli_simag(y) ) #define bli_cscopynzs( x, y ) bli_scopyris( bli_creal(x), bli_cimag(x), bli_sreal(y), bli_simag(y) ) #define bli_zscopynzs( x, y ) bli_scopyris( bli_zreal(x), bli_zimag(x), bli_sreal(y), bli_simag(y) ) #define bli_sdcopynzs( x, y ) bli_dcopyris( bli_sreal(x), bli_simag(x), bli_dreal(y), bli_dimag(y) ) #define bli_ddcopynzs( x, y ) bli_dcopyris( bli_dreal(x), bli_dimag(x), bli_dreal(y), bli_dimag(y) ) #define bli_cdcopynzs( x, y ) bli_dcopyris( bli_creal(x), bli_cimag(x), bli_dreal(y), bli_dimag(y) ) #define bli_zdcopynzs( x, y ) bli_dcopyris( bli_zreal(x), bli_zimag(x), bli_dreal(y), bli_dimag(y) ) // NOTE: Use of scopyris() is so we don't touch the imaginary part of y. #define bli_sccopynzs( x, y ) bli_scopyris( bli_sreal(x), bli_simag(x), bli_creal(y), bli_cimag(y) ) #define bli_dccopynzs( x, y ) bli_scopyris( bli_dreal(x), bli_dimag(x), bli_creal(y), bli_cimag(y) ) #define bli_cccopynzs( x, y ) bli_ccopyris( bli_creal(x), bli_cimag(x), bli_creal(y), bli_cimag(y) ) #define bli_zccopynzs( x, y ) bli_ccopyris( bli_zreal(x), bli_zimag(x), bli_creal(y), bli_cimag(y) ) // NOTE: Use of dcopyris() is so we don't touch the imaginary part of y. #define bli_szcopynzs( x, y ) bli_dcopyris( bli_sreal(x), bli_simag(x), bli_zreal(y), bli_zimag(y) ) #define bli_dzcopynzs( x, y ) bli_dcopyris( bli_dreal(x), bli_dimag(x), bli_zreal(y), bli_zimag(y) ) #define bli_czcopynzs( x, y ) bli_zcopyris( bli_creal(x), bli_cimag(x), bli_zreal(y), bli_zimag(y) ) #define bli_zzcopynzs( x, y ) bli_zcopyris( bli_zreal(x), bli_zimag(x), bli_zreal(y), bli_zimag(y) ) #define bli_iicopynzs( x, y ) { (y) = ( gint_t ) (x); } #define bli_scopynzs( x, y ) bli_sscopynzs( x, y ) #define bli_dcopynzs( x, y ) bli_ddcopynzs( x, y ) #define bli_ccopynzs( x, y ) bli_cccopynzs( x, y ) #define bli_zcopynzs( x, y ) bli_zzcopynzs( x, y ) #define bli_icopynzs( x, y ) bli_iicopynzs( x, y ) #endif blis-0.9.0/frame/include/level0/bli_copys.h000066400000000000000000000075101422157504600205220ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_COPYS_H #define BLIS_COPYS_H // copys // Notes: // - The first char encodes the type of x. // - The second char encodes the type of y. #define bli_sscopys( x, y ) bli_scopyris( bli_sreal(x), bli_simag(x), bli_sreal(y), bli_simag(y) ) #define bli_dscopys( x, y ) bli_scopyris( bli_dreal(x), bli_dimag(x), bli_sreal(y), bli_simag(y) ) #define bli_cscopys( x, y ) bli_scopyris( bli_creal(x), bli_cimag(x), bli_sreal(y), bli_simag(y) ) #define bli_zscopys( x, y ) bli_scopyris( bli_zreal(x), bli_zimag(x), bli_sreal(y), bli_simag(y) ) #define bli_sdcopys( x, y ) bli_dcopyris( bli_sreal(x), bli_simag(x), bli_dreal(y), bli_dimag(y) ) #define bli_ddcopys( x, y ) bli_dcopyris( bli_dreal(x), bli_dimag(x), bli_dreal(y), bli_dimag(y) ) #define bli_cdcopys( x, y ) bli_dcopyris( bli_creal(x), bli_cimag(x), bli_dreal(y), bli_dimag(y) ) #define bli_zdcopys( x, y ) bli_dcopyris( bli_zreal(x), bli_zimag(x), bli_dreal(y), bli_dimag(y) ) // NOTE: Use of ccopyris() means the imaginary part of y will be overwritten with zero. #define bli_sccopys( x, y ) bli_ccopyris( bli_sreal(x), bli_simag(x), bli_creal(y), bli_cimag(y) ) #define bli_dccopys( x, y ) bli_ccopyris( bli_dreal(x), bli_dimag(x), bli_creal(y), bli_cimag(y) ) #define bli_cccopys( x, y ) bli_ccopyris( bli_creal(x), bli_cimag(x), bli_creal(y), bli_cimag(y) ) #define bli_zccopys( x, y ) bli_ccopyris( bli_zreal(x), bli_zimag(x), bli_creal(y), bli_cimag(y) ) // NOTE: Use of zcopyris() means the imaginary part of y will be overwritten with zero. #define bli_szcopys( x, y ) bli_zcopyris( bli_sreal(x), bli_simag(x), bli_zreal(y), bli_zimag(y) ) #define bli_dzcopys( x, y ) bli_zcopyris( bli_dreal(x), bli_dimag(x), bli_zreal(y), bli_zimag(y) ) #define bli_czcopys( x, y ) bli_zcopyris( bli_creal(x), bli_cimag(x), bli_zreal(y), bli_zimag(y) ) #define bli_zzcopys( x, y ) bli_zcopyris( bli_zreal(x), bli_zimag(x), bli_zreal(y), bli_zimag(y) ) #define bli_iicopys( x, y ) { (y) = ( gint_t ) (x); } #define bli_scopys( x, y ) bli_sscopys( x, y ) #define bli_dcopys( x, y ) bli_ddcopys( x, y ) #define bli_ccopys( x, y ) bli_cccopys( x, y ) #define bli_zcopys( x, y ) bli_zzcopys( x, y ) #define bli_icopys( x, y ) bli_iicopys( x, y ) #endif blis-0.9.0/frame/include/level0/bli_copys_mxn.h000066400000000000000000000376211422157504600214120ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_COPYS_MXN_H #define BLIS_COPYS_MXN_H // copys_mxn // Notes: // - The first char encodes the type of x. // - The second char encodes the type of y. // xy = ?s BLIS_INLINE void bli_sscopys_mxn( const dim_t m, const dim_t n, float* restrict x, const inc_t rs_x, const inc_t cs_x, float* restrict y, const inc_t rs_y, const inc_t cs_y ) { #ifdef BLIS_ENABLE_CR_CASES if ( rs_x == 1 && rs_y == 1 ) { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_sscopys( *(x + ii + jj*cs_x), *(y + ii + jj*cs_y) ); } else if ( cs_x == 1 && cs_y == 1 ) { for ( dim_t ii = 0; ii < m; ++ii ) for ( dim_t jj = 0; jj < n; ++jj ) bli_sscopys( *(x + ii*rs_x + jj), *(y + ii*rs_y + jj) ); } else #endif { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_sscopys( *(x + ii*rs_x + jj*cs_x), *(y + ii*rs_y + jj*cs_y) ); } } BLIS_INLINE void bli_dscopys_mxn( const dim_t m, const dim_t n, double* restrict x, const inc_t rs_x, const inc_t cs_x, float* restrict y, const inc_t rs_y, const inc_t cs_y ) { #ifdef BLIS_ENABLE_CR_CASES if ( rs_x == 1 && rs_y == 1 ) { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_dscopys( *(x + ii + jj*cs_x), *(y + ii + jj*cs_y) ); } else if ( cs_x == 1 && cs_y == 1 ) { for ( dim_t ii = 0; ii < m; ++ii ) for ( dim_t jj = 0; jj < n; ++jj ) bli_dscopys( *(x + ii*rs_x + jj), *(y + ii*rs_y + jj) ); } else #endif { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_dscopys( *(x + ii*rs_x + jj*cs_x), *(y + ii*rs_y + jj*cs_y) ); } } BLIS_INLINE void bli_cscopys_mxn( const dim_t m, const dim_t n, scomplex* restrict x, const inc_t rs_x, const inc_t cs_x, float* restrict y, const inc_t rs_y, const inc_t cs_y ) { #ifdef BLIS_ENABLE_CR_CASES if ( rs_x == 1 && rs_y == 1 ) { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_cscopys( *(x + ii + jj*cs_x), *(y + ii + jj*cs_y) ); } else if ( cs_x == 1 && cs_y == 1 ) { for ( dim_t ii = 0; ii < m; ++ii ) for ( dim_t jj = 0; jj < n; ++jj ) bli_cscopys( *(x + ii*rs_x + jj), *(y + ii*rs_y + jj) ); } else #endif { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_cscopys( *(x + ii*rs_x + jj*cs_x), *(y + ii*rs_y + jj*cs_y) ); } } BLIS_INLINE void bli_zscopys_mxn( const dim_t m, const dim_t n, dcomplex* restrict x, const inc_t rs_x, const inc_t cs_x, float* restrict y, const inc_t rs_y, const inc_t cs_y ) { #ifdef BLIS_ENABLE_CR_CASES if ( rs_x == 1 && rs_y == 1 ) { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_zscopys( *(x + ii + jj*cs_x), *(y + ii + jj*cs_y) ); } else if ( cs_x == 1 && cs_y == 1 ) { for ( dim_t ii = 0; ii < m; ++ii ) for ( dim_t jj = 0; jj < n; ++jj ) bli_zscopys( *(x + ii*rs_x + jj), *(y + ii*rs_y + jj) ); } else #endif { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_zscopys( *(x + ii*rs_x + jj*cs_x), *(y + ii*rs_y + jj*cs_y) ); } } // xy = ?d BLIS_INLINE void bli_sdcopys_mxn( const dim_t m, const dim_t n, float* restrict x, const inc_t rs_x, const inc_t cs_x, double* restrict y, const inc_t rs_y, const inc_t cs_y ) { #ifdef BLIS_ENABLE_CR_CASES if ( rs_x == 1 && rs_y == 1 ) { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_sdcopys( *(x + ii + jj*cs_x), *(y + ii + jj*cs_y) ); } else if ( cs_x == 1 && cs_y == 1 ) { for ( dim_t ii = 0; ii < m; ++ii ) for ( dim_t jj = 0; jj < n; ++jj ) bli_sdcopys( *(x + ii*rs_x + jj), *(y + ii*rs_y + jj) ); } else #endif { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_sdcopys( *(x + ii*rs_x + jj*cs_x), *(y + ii*rs_y + jj*cs_y) ); } } BLIS_INLINE void bli_ddcopys_mxn( const dim_t m, const dim_t n, double* restrict x, const inc_t rs_x, const inc_t cs_x, double* restrict y, const inc_t rs_y, const inc_t cs_y ) { #ifdef BLIS_ENABLE_CR_CASES if ( rs_x == 1 && rs_y == 1 ) { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_ddcopys( *(x + ii + jj*cs_x), *(y + ii + jj*cs_y) ); } else if ( cs_x == 1 && cs_y == 1 ) { for ( dim_t ii = 0; ii < m; ++ii ) for ( dim_t jj = 0; jj < n; ++jj ) bli_ddcopys( *(x + ii*rs_x + jj), *(y + ii*rs_y + jj) ); } else #endif { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_ddcopys( *(x + ii*rs_x + jj*cs_x), *(y + ii*rs_y + jj*cs_y) ); } } BLIS_INLINE void bli_cdcopys_mxn( const dim_t m, const dim_t n, scomplex* restrict x, const inc_t rs_x, const inc_t cs_x, double* restrict y, const inc_t rs_y, const inc_t cs_y ) { #ifdef BLIS_ENABLE_CR_CASES if ( rs_x == 1 && rs_y == 1 ) { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_cdcopys( *(x + ii + jj*cs_x), *(y + ii + jj*cs_y) ); } else if ( cs_x == 1 && cs_y == 1 ) { for ( dim_t ii = 0; ii < m; ++ii ) for ( dim_t jj = 0; jj < n; ++jj ) bli_cdcopys( *(x + ii*rs_x + jj), *(y + ii*rs_y + jj) ); } else #endif { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_cdcopys( *(x + ii*rs_x + jj*cs_x), *(y + ii*rs_y + jj*cs_y) ); } } BLIS_INLINE void bli_zdcopys_mxn( const dim_t m, const dim_t n, dcomplex* restrict x, const inc_t rs_x, const inc_t cs_x, double* restrict y, const inc_t rs_y, const inc_t cs_y ) { #ifdef BLIS_ENABLE_CR_CASES if ( rs_x == 1 && rs_y == 1 ) { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_zdcopys( *(x + ii + jj*cs_x), *(y + ii + jj*cs_y) ); } else if ( cs_x == 1 && cs_y == 1 ) { for ( dim_t ii = 0; ii < m; ++ii ) for ( dim_t jj = 0; jj < n; ++jj ) bli_zdcopys( *(x + ii*rs_x + jj), *(y + ii*rs_y + jj) ); } else #endif { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_zdcopys( *(x + ii*rs_x + jj*cs_x), *(y + ii*rs_y + jj*cs_y) ); } } // xy = ?c BLIS_INLINE void bli_sccopys_mxn( const dim_t m, const dim_t n, float* restrict x, const inc_t rs_x, const inc_t cs_x, scomplex* restrict y, const inc_t rs_y, const inc_t cs_y ) { #ifdef BLIS_ENABLE_CR_CASES if ( rs_x == 1 && rs_y == 1 ) { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_sccopys( *(x + ii + jj*cs_x), *(y + ii + jj*cs_y) ); } else if ( cs_x == 1 && cs_y == 1 ) { for ( dim_t ii = 0; ii < m; ++ii ) for ( dim_t jj = 0; jj < n; ++jj ) bli_sccopys( *(x + ii*rs_x + jj), *(y + ii*rs_y + jj) ); } else #endif { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_sccopys( *(x + ii*rs_x + jj*cs_x), *(y + ii*rs_y + jj*cs_y) ); } } BLIS_INLINE void bli_dccopys_mxn( const dim_t m, const dim_t n, double* restrict x, const inc_t rs_x, const inc_t cs_x, scomplex* restrict y, const inc_t rs_y, const inc_t cs_y ) { #ifdef BLIS_ENABLE_CR_CASES if ( rs_x == 1 && rs_y == 1 ) { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_dccopys( *(x + ii + jj*cs_x), *(y + ii + jj*cs_y) ); } else if ( cs_x == 1 && cs_y == 1 ) { for ( dim_t ii = 0; ii < m; ++ii ) for ( dim_t jj = 0; jj < n; ++jj ) bli_dccopys( *(x + ii*rs_x + jj), *(y + ii*rs_y + jj) ); } else #endif { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_dccopys( *(x + ii*rs_x + jj*cs_x), *(y + ii*rs_y + jj*cs_y) ); } } BLIS_INLINE void bli_cccopys_mxn( const dim_t m, const dim_t n, scomplex* restrict x, const inc_t rs_x, const inc_t cs_x, scomplex* restrict y, const inc_t rs_y, const inc_t cs_y ) { #ifdef BLIS_ENABLE_CR_CASES if ( rs_x == 1 && rs_y == 1 ) { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_cccopys( *(x + ii + jj*cs_x), *(y + ii + jj*cs_y) ); } else if ( cs_x == 1 && cs_y == 1 ) { for ( dim_t ii = 0; ii < m; ++ii ) for ( dim_t jj = 0; jj < n; ++jj ) bli_cccopys( *(x + ii*rs_x + jj), *(y + ii*rs_y + jj) ); } else #endif { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_cccopys( *(x + ii*rs_x + jj*cs_x), *(y + ii*rs_y + jj*cs_y) ); } } BLIS_INLINE void bli_zccopys_mxn( const dim_t m, const dim_t n, dcomplex* restrict x, const inc_t rs_x, const inc_t cs_x, scomplex* restrict y, const inc_t rs_y, const inc_t cs_y ) { #ifdef BLIS_ENABLE_CR_CASES if ( rs_x == 1 && rs_y == 1 ) { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_zccopys( *(x + ii + jj*cs_x), *(y + ii + jj*cs_y) ); } else if ( cs_x == 1 && cs_y == 1 ) { for ( dim_t ii = 0; ii < m; ++ii ) for ( dim_t jj = 0; jj < n; ++jj ) bli_zccopys( *(x + ii*rs_x + jj), *(y + ii*rs_y + jj) ); } else #endif { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_zccopys( *(x + ii*rs_x + jj*cs_x), *(y + ii*rs_y + jj*cs_y) ); } } // xy = ?c BLIS_INLINE void bli_szcopys_mxn( const dim_t m, const dim_t n, float* restrict x, const inc_t rs_x, const inc_t cs_x, dcomplex* restrict y, const inc_t rs_y, const inc_t cs_y ) { #ifdef BLIS_ENABLE_CR_CASES if ( rs_x == 1 && rs_y == 1 ) { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_szcopys( *(x + ii + jj*cs_x), *(y + ii + jj*cs_y) ); } else if ( cs_x == 1 && cs_y == 1 ) { for ( dim_t ii = 0; ii < m; ++ii ) for ( dim_t jj = 0; jj < n; ++jj ) bli_szcopys( *(x + ii*rs_x + jj), *(y + ii*rs_y + jj) ); } else #endif { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_szcopys( *(x + ii*rs_x + jj*cs_x), *(y + ii*rs_y + jj*cs_y) ); } } BLIS_INLINE void bli_dzcopys_mxn( const dim_t m, const dim_t n, double* restrict x, const inc_t rs_x, const inc_t cs_x, dcomplex* restrict y, const inc_t rs_y, const inc_t cs_y ) { #ifdef BLIS_ENABLE_CR_CASES if ( rs_x == 1 && rs_y == 1 ) { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_dzcopys( *(x + ii + jj*cs_x), *(y + ii + jj*cs_y) ); } else if ( cs_x == 1 && cs_y == 1 ) { for ( dim_t ii = 0; ii < m; ++ii ) for ( dim_t jj = 0; jj < n; ++jj ) bli_dzcopys( *(x + ii*rs_x + jj), *(y + ii*rs_y + jj) ); } else #endif { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_dzcopys( *(x + ii*rs_x + jj*cs_x), *(y + ii*rs_y + jj*cs_y) ); } } BLIS_INLINE void bli_czcopys_mxn( const dim_t m, const dim_t n, scomplex* restrict x, const inc_t rs_x, const inc_t cs_x, dcomplex* restrict y, const inc_t rs_y, const inc_t cs_y ) { #ifdef BLIS_ENABLE_CR_CASES if ( rs_x == 1 && rs_y == 1 ) { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_czcopys( *(x + ii + jj*cs_x), *(y + ii + jj*cs_y) ); } else if ( cs_x == 1 && cs_y == 1 ) { for ( dim_t ii = 0; ii < m; ++ii ) for ( dim_t jj = 0; jj < n; ++jj ) bli_czcopys( *(x + ii*rs_x + jj), *(y + ii*rs_y + jj) ); } else #endif { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_czcopys( *(x + ii*rs_x + jj*cs_x), *(y + ii*rs_y + jj*cs_y) ); } } BLIS_INLINE void bli_zzcopys_mxn( const dim_t m, const dim_t n, dcomplex* restrict x, const inc_t rs_x, const inc_t cs_x, dcomplex* restrict y, const inc_t rs_y, const inc_t cs_y ) { #ifdef BLIS_ENABLE_CR_CASES if ( rs_x == 1 && rs_y == 1 ) { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_zzcopys( *(x + ii + jj*cs_x), *(y + ii + jj*cs_y) ); } else if ( cs_x == 1 && cs_y == 1 ) { for ( dim_t ii = 0; ii < m; ++ii ) for ( dim_t jj = 0; jj < n; ++jj ) bli_zzcopys( *(x + ii*rs_x + jj), *(y + ii*rs_y + jj) ); } else #endif { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_zzcopys( *(x + ii*rs_x + jj*cs_x), *(y + ii*rs_y + jj*cs_y) ); } } BLIS_INLINE void bli_scopys_mxn( const dim_t m, const dim_t n, float* restrict x, const inc_t rs_x, const inc_t cs_x, float* restrict y, const inc_t rs_y, const inc_t cs_y ) { bli_sscopys_mxn( m, n, x, rs_x, cs_x, y, rs_y, cs_y ); } BLIS_INLINE void bli_dcopys_mxn( const dim_t m, const dim_t n, double* restrict x, const inc_t rs_x, const inc_t cs_x, double* restrict y, const inc_t rs_y, const inc_t cs_y ) { bli_ddcopys_mxn( m, n, x, rs_x, cs_x, y, rs_y, cs_y ); } BLIS_INLINE void bli_ccopys_mxn( const dim_t m, const dim_t n, scomplex* restrict x, const inc_t rs_x, const inc_t cs_x, scomplex* restrict y, const inc_t rs_y, const inc_t cs_y ) { bli_cccopys_mxn( m, n, x, rs_x, cs_x, y, rs_y, cs_y ); } BLIS_INLINE void bli_zcopys_mxn( const dim_t m, const dim_t n, dcomplex* restrict x, const inc_t rs_x, const inc_t cs_x, dcomplex* restrict y, const inc_t rs_y, const inc_t cs_y ) { bli_zzcopys_mxn( m, n, x, rs_x, cs_x, y, rs_y, cs_y ); } #endif blis-0.9.0/frame/include/level0/bli_dotjs.h000066400000000000000000000133561422157504600205150ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_DOTJS_H #define BLIS_DOTJS_H // dotjs // Notes: // - The first char encodes the type of x. // - The second char encodes the type of y. // - The third char encodes the type of rho. // - x is used in conjugated form. #define bli_sssdotjs( x, y, a ) bli_sssaxpyjs( y, x, a ) #define bli_dssdotjs( x, y, a ) bli_sdsaxpyjs( y, x, a ) #define bli_cssdotjs( x, y, a ) bli_scsaxpyjs( y, x, a ) #define bli_zssdotjs( x, y, a ) bli_szsaxpyjs( y, x, a ) #define bli_sdsdotjs( x, y, a ) bli_dssaxpyjs( y, x, a ) #define bli_ddsdotjs( x, y, a ) bli_ddsaxpyjs( y, x, a ) #define bli_cdsdotjs( x, y, a ) bli_dcsaxpyjs( y, x, a ) #define bli_zdsdotjs( x, y, a ) bli_dzsaxpyjs( y, x, a ) #define bli_scsdotjs( x, y, a ) bli_cssaxpyjs( y, x, a ) #define bli_dcsdotjs( x, y, a ) bli_cdsaxpyjs( y, x, a ) #define bli_ccsdotjs( x, y, a ) bli_ccsaxpyjs( y, x, a ) #define bli_zcsdotjs( x, y, a ) bli_czsaxpyjs( y, x, a ) #define bli_szsdotjs( x, y, a ) bli_zssaxpyjs( y, x, a ) #define bli_dzsdotjs( x, y, a ) bli_zdsaxpyjs( y, x, a ) #define bli_czsdotjs( x, y, a ) bli_zcsaxpyjs( y, x, a ) #define bli_zzsdotjs( x, y, a ) bli_zzsaxpyjs( y, x, a ) #define bli_ssddotjs( x, y, a ) bli_ssdaxpyjs( y, x, a ) #define bli_dsddotjs( x, y, a ) bli_sddaxpyjs( y, x, a ) #define bli_csddotjs( x, y, a ) bli_scdaxpyjs( y, x, a ) #define bli_zsddotjs( x, y, a ) bli_szdaxpyjs( y, x, a ) #define bli_sdddotjs( x, y, a ) bli_dsdaxpyjs( y, x, a ) #define bli_ddddotjs( x, y, a ) bli_dddaxpyjs( y, x, a ) #define bli_cdddotjs( x, y, a ) bli_dcdaxpyjs( y, x, a ) #define bli_zdddotjs( x, y, a ) bli_dzdaxpyjs( y, x, a ) #define bli_scddotjs( x, y, a ) bli_csdaxpyjs( y, x, a ) #define bli_dcddotjs( x, y, a ) bli_cddaxpyjs( y, x, a ) #define bli_ccddotjs( x, y, a ) bli_ccdaxpyjs( y, x, a ) #define bli_zcddotjs( x, y, a ) bli_czdaxpyjs( y, x, a ) #define bli_szddotjs( x, y, a ) bli_zsdaxpyjs( y, x, a ) #define bli_dzddotjs( x, y, a ) bli_zddaxpyjs( y, x, a ) #define bli_czddotjs( x, y, a ) bli_zcdaxpyjs( y, x, a ) #define bli_zzddotjs( x, y, a ) bli_zzdaxpyjs( y, x, a ) #define bli_sscdotjs( x, y, a ) bli_sscaxpyjs( y, x, a ) #define bli_dscdotjs( x, y, a ) bli_sdcaxpyjs( y, x, a ) #define bli_cscdotjs( x, y, a ) bli_sccaxpyjs( y, x, a ) #define bli_zscdotjs( x, y, a ) bli_szcaxpyjs( y, x, a ) #define bli_sdcdotjs( x, y, a ) bli_dscaxpyjs( y, x, a ) #define bli_ddcdotjs( x, y, a ) bli_ddcaxpyjs( y, x, a ) #define bli_cdcdotjs( x, y, a ) bli_dccaxpyjs( y, x, a ) #define bli_zdcdotjs( x, y, a ) bli_dzcaxpyjs( y, x, a ) #define bli_sccdotjs( x, y, a ) bli_cscaxpyjs( y, x, a ) #define bli_dccdotjs( x, y, a ) bli_cdcaxpyjs( y, x, a ) #define bli_cccdotjs( x, y, a ) bli_cccaxpyjs( y, x, a ) #define bli_zccdotjs( x, y, a ) bli_czcaxpyjs( y, x, a ) #define bli_szcdotjs( x, y, a ) bli_zscaxpyjs( y, x, a ) #define bli_dzcdotjs( x, y, a ) bli_zdcaxpyjs( y, x, a ) #define bli_czcdotjs( x, y, a ) bli_zccaxpyjs( y, x, a ) #define bli_zzcdotjs( x, y, a ) bli_zzcaxpyjs( y, x, a ) #define bli_sszdotjs( x, y, a ) bli_sszaxpyjs( y, x, a ) #define bli_dszdotjs( x, y, a ) bli_sdzaxpyjs( y, x, a ) #define bli_cszdotjs( x, y, a ) bli_sczaxpyjs( y, x, a ) #define bli_zszdotjs( x, y, a ) bli_szzaxpyjs( y, x, a ) #define bli_sdzdotjs( x, y, a ) bli_dszaxpyjs( y, x, a ) #define bli_ddzdotjs( x, y, a ) bli_ddzaxpyjs( y, x, a ) #define bli_cdzdotjs( x, y, a ) bli_dczaxpyjs( y, x, a ) #define bli_zdzdotjs( x, y, a ) bli_dzzaxpyjs( y, x, a ) #define bli_sczdotjs( x, y, a ) bli_cszaxpyjs( y, x, a ) #define bli_dczdotjs( x, y, a ) bli_cdzaxpyjs( y, x, a ) #define bli_cczdotjs( x, y, a ) bli_cczaxpyjs( y, x, a ) #define bli_zczdotjs( x, y, a ) bli_czzaxpyjs( y, x, a ) #define bli_szzdotjs( x, y, a ) bli_zszaxpyjs( y, x, a ) #define bli_dzzdotjs( x, y, a ) bli_zdzaxpyjs( y, x, a ) #define bli_czzdotjs( x, y, a ) bli_zczaxpyjs( y, x, a ) #define bli_zzzdotjs( x, y, a ) bli_zzzaxpyjs( y, x, a ) #define bli_sdotjs( x, y, a ) bli_sssdotjs( x, y, a ) #define bli_ddotjs( x, y, a ) bli_ddddotjs( x, y, a ) #define bli_cdotjs( x, y, a ) bli_cccdotjs( x, y, a ) #define bli_zdotjs( x, y, a ) bli_zzzdotjs( x, y, a ) #endif blis-0.9.0/frame/include/level0/bli_dots.h000066400000000000000000000131011422157504600203270ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_DOTS_H #define BLIS_DOTS_H // dots // Notes: // - The first char encodes the type of x. // - The second char encodes the type of y. // - The third char encodes the type of rho. #define bli_sssdots( x, y, a ) bli_sssaxpys( x, y, a ) #define bli_dssdots( x, y, a ) bli_dssaxpys( x, y, a ) #define bli_cssdots( x, y, a ) bli_cssaxpys( x, y, a ) #define bli_zssdots( x, y, a ) bli_zssaxpys( x, y, a ) #define bli_sdsdots( x, y, a ) bli_sdsaxpys( x, y, a ) #define bli_ddsdots( x, y, a ) bli_ddsaxpys( x, y, a ) #define bli_cdsdots( x, y, a ) bli_cdsaxpys( x, y, a ) #define bli_zdsdots( x, y, a ) bli_zdsaxpys( x, y, a ) #define bli_scsdots( x, y, a ) bli_scsaxpys( x, y, a ) #define bli_dcsdots( x, y, a ) bli_dcsaxpys( x, y, a ) #define bli_ccsdots( x, y, a ) bli_ccsaxpys( x, y, a ) #define bli_zcsdots( x, y, a ) bli_zcsaxpys( x, y, a ) #define bli_szsdots( x, y, a ) bli_szsaxpys( x, y, a ) #define bli_dzsdots( x, y, a ) bli_dzsaxpys( x, y, a ) #define bli_czsdots( x, y, a ) bli_czsaxpys( x, y, a ) #define bli_zzsdots( x, y, a ) bli_zzsaxpys( x, y, a ) #define bli_ssddots( x, y, a ) bli_ssdaxpys( x, y, a ) #define bli_dsddots( x, y, a ) bli_dsdaxpys( x, y, a ) #define bli_csddots( x, y, a ) bli_csdaxpys( x, y, a ) #define bli_zsddots( x, y, a ) bli_zsdaxpys( x, y, a ) #define bli_sdddots( x, y, a ) bli_sddaxpys( x, y, a ) #define bli_ddddots( x, y, a ) bli_dddaxpys( x, y, a ) #define bli_cdddots( x, y, a ) bli_cddaxpys( x, y, a ) #define bli_zdddots( x, y, a ) bli_zddaxpys( x, y, a ) #define bli_scddots( x, y, a ) bli_scdaxpys( x, y, a ) #define bli_dcddots( x, y, a ) bli_dcdaxpys( x, y, a ) #define bli_ccddots( x, y, a ) bli_ccdaxpys( x, y, a ) #define bli_zcddots( x, y, a ) bli_zcdaxpys( x, y, a ) #define bli_szddots( x, y, a ) bli_szdaxpys( x, y, a ) #define bli_dzddots( x, y, a ) bli_dzdaxpys( x, y, a ) #define bli_czddots( x, y, a ) bli_czdaxpys( x, y, a ) #define bli_zzddots( x, y, a ) bli_zzdaxpys( x, y, a ) #define bli_sscdots( x, y, a ) bli_sscaxpys( x, y, a ) #define bli_dscdots( x, y, a ) bli_dscaxpys( x, y, a ) #define bli_cscdots( x, y, a ) bli_cscaxpys( x, y, a ) #define bli_zscdots( x, y, a ) bli_zscaxpys( x, y, a ) #define bli_sdcdots( x, y, a ) bli_sdcaxpys( x, y, a ) #define bli_ddcdots( x, y, a ) bli_ddcaxpys( x, y, a ) #define bli_cdcdots( x, y, a ) bli_cdcaxpys( x, y, a ) #define bli_zdcdots( x, y, a ) bli_zdcaxpys( x, y, a ) #define bli_sccdots( x, y, a ) bli_sccaxpys( x, y, a ) #define bli_dccdots( x, y, a ) bli_dccaxpys( x, y, a ) #define bli_cccdots( x, y, a ) bli_cccaxpys( x, y, a ) #define bli_zccdots( x, y, a ) bli_zccaxpys( x, y, a ) #define bli_szcdots( x, y, a ) bli_szcaxpys( x, y, a ) #define bli_dzcdots( x, y, a ) bli_dzcaxpys( x, y, a ) #define bli_czcdots( x, y, a ) bli_czcaxpys( x, y, a ) #define bli_zzcdots( x, y, a ) bli_zzcaxpys( x, y, a ) #define bli_sszdots( x, y, a ) bli_sszaxpys( x, y, a ) #define bli_dszdots( x, y, a ) bli_dszaxpys( x, y, a ) #define bli_cszdots( x, y, a ) bli_cszaxpys( x, y, a ) #define bli_zszdots( x, y, a ) bli_zszaxpys( x, y, a ) #define bli_sdzdots( x, y, a ) bli_sdzaxpys( x, y, a ) #define bli_ddzdots( x, y, a ) bli_ddzaxpys( x, y, a ) #define bli_cdzdots( x, y, a ) bli_cdzaxpys( x, y, a ) #define bli_zdzdots( x, y, a ) bli_zdzaxpys( x, y, a ) #define bli_sczdots( x, y, a ) bli_sczaxpys( x, y, a ) #define bli_dczdots( x, y, a ) bli_dczaxpys( x, y, a ) #define bli_cczdots( x, y, a ) bli_cczaxpys( x, y, a ) #define bli_zczdots( x, y, a ) bli_zczaxpys( x, y, a ) #define bli_szzdots( x, y, a ) bli_szzaxpys( x, y, a ) #define bli_dzzdots( x, y, a ) bli_dzzaxpys( x, y, a ) #define bli_czzdots( x, y, a ) bli_czzaxpys( x, y, a ) #define bli_zzzdots( x, y, a ) bli_zzzaxpys( x, y, a ) #define bli_sdots( x, y, a ) bli_sssdots( x, y, a ) #define bli_ddots( x, y, a ) bli_ddddots( x, y, a ) #define bli_cdots( x, y, a ) bli_cccdots( x, y, a ) #define bli_zdots( x, y, a ) bli_zzzdots( x, y, a ) #endif blis-0.9.0/frame/include/level0/bli_eq.h000066400000000000000000000077561422157504600200060ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_EQ_H #define BLIS_EQ_H // eq (passed by value) #define bli_seq( a, b ) ( (a) == (b) ) #define bli_deq( a, b ) ( (a) == (b) ) #ifndef BLIS_ENABLE_C99_COMPLEX #define bli_ceq( a, b ) ( ( bli_creal(a) == bli_creal(b) ) && ( bli_cimag(a) == bli_cimag(b) ) ) #define bli_zeq( a, b ) ( ( bli_zreal(a) == bli_zreal(b) ) && ( bli_zimag(a) == bli_zimag(b) ) ) #else // ifdef BLIS_ENABLE_C99_COMPLEX #define bli_ceq( a, b ) ( (a) == (b) ) #define bli_zeq( a, b ) ( (a) == (b) ) #endif // BLIS_ENABLE_C99_COMPLEX #define bli_ieq( a, b ) ( (a) == (b) ) // eqtori (passed by value) #define bli_seqtori( a, br, bi ) ( (a) == (br) ) #define bli_deqtori( a, br, bi ) ( (a) == (br) ) #ifndef BLIS_ENABLE_C99_COMPLEX #define bli_ceqtori( a, br, bi ) ( ( bli_creal(a) == (br) ) && ( bli_cimag(a) == (bi) ) ) #define bli_zeqtori( a, br, bi ) ( ( bli_zreal(a) == (br) ) && ( bli_zimag(a) == (bi) ) ) #else // ifdef BLIS_ENABLE_C99_COMPLEX #define bli_ceqtori( a, br, bi ) ( (a) == (br) + (bi) * (I) ) #define bli_zeqtori( a, br, bi ) ( (a) == (br) + (bi) * (I) ) #endif // BLIS_ENABLE_C99_COMPLEX // eqa (passed by address) #define bli_seqa( a, b ) bli_seq( *(( float* )(a)), *(( float* )(b)) ) #define bli_deqa( a, b ) bli_deq( *(( double* )(a)), *(( double* )(b)) ) #define bli_ceqa( a, b ) bli_ceq( *(( scomplex* )(a)), *(( scomplex* )(b)) ) #define bli_zeqa( a, b ) bli_zeq( *(( dcomplex* )(a)), *(( dcomplex* )(b)) ) #define bli_ieqa( a, b ) bli_ieq( *(( gint_t* )(a)), *(( gint_t* )(b)) ) // eq1 #define bli_seq1( a ) bli_seqtori( (a), 1.0F, 0.0F ) #define bli_deq1( a ) bli_deqtori( (a), 1.0, 0.0 ) #define bli_ceq1( a ) bli_ceqtori( (a), 1.0F, 0.0F ) #define bli_zeq1( a ) bli_zeqtori( (a), 1.0, 0.0 ) #define bli_ieq1( a ) bli_ieq ( (a), 1 ) // eq0 #define bli_seq0( a ) bli_seqtori( (a), 0.0F, 0.0F ) #define bli_deq0( a ) bli_deqtori( (a), 0.0, 0.0 ) #define bli_ceq0( a ) bli_ceqtori( (a), 0.0F, 0.0F ) #define bli_zeq0( a ) bli_zeqtori( (a), 0.0, 0.0 ) #define bli_ieq0( a ) bli_ieq ( (a), 0 ) // eqm1 #define bli_seqm1( a ) bli_seqtori( (a), -1.0F, 0.0F ) #define bli_deqm1( a ) bli_deqtori( (a), -1.0, 0.0 ) #define bli_ceqm1( a ) bli_ceqtori( (a), -1.0F, 0.0F ) #define bli_zeqm1( a ) bli_zeqtori( (a), -1.0, 0.0 ) #define bli_ieqm1( a ) bli_ieq ( (a), -1 ) #endif blis-0.9.0/frame/include/level0/bli_fprints.h000066400000000000000000000044271422157504600210560ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_FPRINTS_H #define BLIS_FPRINTS_H // prints #define bli_sfprints( file, spec, x ) \ { \ fprintf( file, spec, (x) ); \ } #define bli_dfprints( file, spec, x ) \ { \ fprintf( file, spec, (x) ); \ } #define bli_cfprints( file, spec, x ) \ { \ fprintf( file, spec, bli_creal(x) ); \ fprintf( file, " + " ); \ fprintf( file, spec, bli_cimag(x) ); \ fprintf( file, " " ); \ } #define bli_zfprints( file, spec, x ) \ { \ fprintf( file, spec, bli_zreal(x) ); \ fprintf( file, " + " ); \ fprintf( file, spec, bli_zimag(x) ); \ fprintf( file, " " ); \ } #define bli_ifprints( file, spec, x ) \ { \ fprintf( file, spec, (x) ); \ } #endif blis-0.9.0/frame/include/level0/bli_gets.h000066400000000000000000000076451422157504600203400ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_GETS_H #define BLIS_GETS_H // gets // Notes: // - The first char encodes the type of x. // - The second char encodes the type of y. #define bli_ssgets( x, yr, yi ) { (yr) = bli_sreal(x); (yi) = bli_simag(x); } #define bli_dsgets( x, yr, yi ) { (yr) = bli_dreal(x); (yi) = bli_dimag(x); } #define bli_csgets( x, yr, yi ) { (yr) = bli_creal(x); (yi) = bli_cimag(x); } #define bli_zsgets( x, yr, yi ) { (yr) = bli_zreal(x); (yi) = bli_zimag(x); } #define bli_isgets( x, yr, yi ) { (yr) = ( float )(x); (yi) = 0.0F; } #define bli_sdgets( x, yr, yi ) { (yr) = bli_sreal(x); (yi) = bli_simag(x); } #define bli_ddgets( x, yr, yi ) { (yr) = bli_dreal(x); (yi) = bli_dimag(x); } #define bli_cdgets( x, yr, yi ) { (yr) = bli_creal(x); (yi) = bli_cimag(x); } #define bli_zdgets( x, yr, yi ) { (yr) = bli_zreal(x); (yi) = bli_zimag(x); } #define bli_idgets( x, yr, yi ) { (yr) = ( double )(x); (yi) = 0.0; } #define bli_scgets( x, yr, yi ) { (yr) = bli_sreal(x); (yi) = bli_simag(x); } #define bli_dcgets( x, yr, yi ) { (yr) = bli_dreal(x); (yi) = bli_dimag(x); } #define bli_ccgets( x, yr, yi ) { (yr) = bli_creal(x); (yi) = bli_cimag(x); } #define bli_zcgets( x, yr, yi ) { (yr) = bli_zreal(x); (yi) = bli_zimag(x); } #define bli_icgets( x, yr, yi ) { (yr) = ( float )(x); (yi) = 0.0F; } #define bli_szgets( x, yr, yi ) { (yr) = bli_sreal(x); (yi) = bli_simag(x); } #define bli_dzgets( x, yr, yi ) { (yr) = bli_dreal(x); (yi) = bli_dimag(x); } #define bli_czgets( x, yr, yi ) { (yr) = bli_creal(x); (yi) = bli_cimag(x); } #define bli_zzgets( x, yr, yi ) { (yr) = bli_zreal(x); (yi) = bli_zimag(x); } #define bli_izgets( x, yr, yi ) { (yr) = ( double )(x); (yi) = 0.0; } #define bli_sigets( x, yr, yi ) { (yr) = bli_sreal(x); (yi) = 0; } #define bli_digets( x, yr, yi ) { (yr) = bli_dreal(x); (yi) = 0; } #define bli_cigets( x, yr, yi ) { (yr) = bli_creal(x); (yi) = 0; } #define bli_zigets( x, yr, yi ) { (yr) = bli_zreal(x); (yi) = 0; } #define bli_iigets( x, yr, yi ) { (yr) = (x); (yi) = 0; } #define bli_sgets( x, yr, yi ) bli_ssgets( x, yr, yi ) #define bli_dgets( x, yr, yi ) bli_ddgets( x, yr, yi ) #define bli_cgets( x, yr, yi ) bli_csgets( x, yr, yi ) #define bli_zgets( x, yr, yi ) bli_zdgets( x, yr, yi ) #define bli_igets( x, yr, yi ) bli_idgets( x, yr, yi ) #endif blis-0.9.0/frame/include/level0/bli_inverts.h000066400000000000000000000043641422157504600210630ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_INVERTS_H #define BLIS_INVERTS_H // inverts // Notes: // - The first char encodes the type of x. #define bli_sinverts( x ) bli_sinvertris( bli_sreal(x), bli_simag(x) ) #define bli_dinverts( x ) bli_dinvertris( bli_dreal(x), bli_dimag(x) ) #ifndef BLIS_ENABLE_C99_COMPLEX #define bli_cinverts( x ) bli_cinvertris( bli_creal(x), bli_cimag(x) ) #define bli_zinverts( x ) bli_zinvertris( bli_zreal(x), bli_zimag(x) ) #else // ifdef BLIS_ENABLE_C99_COMPLEX #define bli_cinverts( x ) { (x) = 1.0F / (x); } #define bli_zinverts( x ) { (x) = 1.0 / (x); } #endif // BLIS_ENABLE_C99_COMPLEX #endif blis-0.9.0/frame/include/level0/bli_invscaljs.h000066400000000000000000000104011422157504600213520ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_INVSCALJS_H #define BLIS_INVSCALJS_H // invscaljs // Notes: // - The first char encodes the type of a. // - The second char encodes the type of y. #define bli_ssinvscaljs( a, y ) bli_sinvscaljris( bli_sreal(a), bli_simag(a), bli_sreal(y), bli_simag(y) ) #define bli_dsinvscaljs( a, y ) bli_sinvscaljris( bli_dreal(a), bli_dimag(a), bli_sreal(y), bli_simag(y) ) #define bli_csinvscaljs( a, y ) bli_sinvscaljris( bli_creal(a), bli_cimag(a), bli_sreal(y), bli_simag(y) ) #define bli_zsinvscaljs( a, y ) bli_sinvscaljris( bli_zreal(a), bli_zimag(a), bli_sreal(y), bli_simag(y) ) #define bli_sdinvscaljs( a, y ) bli_dinvscaljris( bli_sreal(a), bli_simag(a), bli_dreal(y), bli_dimag(y) ) #define bli_ddinvscaljs( a, y ) bli_dinvscaljris( bli_dreal(a), bli_dimag(a), bli_dreal(y), bli_dimag(y) ) #define bli_cdinvscaljs( a, y ) bli_dinvscaljris( bli_creal(a), bli_cimag(a), bli_dreal(y), bli_dimag(y) ) #define bli_zdinvscaljs( a, y ) bli_dinvscaljris( bli_zreal(a), bli_zimag(a), bli_dreal(y), bli_dimag(y) ) #ifndef BLIS_ENABLE_C99_COMPLEX #define bli_scinvscaljs( a, y ) bli_scinvscaljris( bli_sreal(a), bli_simag(a), bli_creal(y), bli_cimag(y) ) #define bli_dcinvscaljs( a, y ) bli_scinvscaljris( bli_dreal(a), bli_dimag(a), bli_creal(y), bli_cimag(y) ) #define bli_ccinvscaljs( a, y ) bli_cinvscaljris( bli_creal(a), bli_cimag(a), bli_creal(y), bli_cimag(y) ) #define bli_zcinvscaljs( a, y ) bli_cinvscaljris( bli_zreal(a), bli_zimag(a), bli_creal(y), bli_cimag(y) ) #define bli_szinvscaljs( a, y ) bli_dzinvscaljris( bli_sreal(a), bli_simag(a), bli_zreal(y), bli_zimag(y) ) #define bli_dzinvscaljs( a, y ) bli_dzinvscaljris( bli_dreal(a), bli_dimag(a), bli_zreal(y), bli_zimag(y) ) #define bli_czinvscaljs( a, y ) bli_zinvscaljris( bli_creal(a), bli_cimag(a), bli_zreal(y), bli_zimag(y) ) #define bli_zzinvscaljs( a, y ) bli_zinvscaljris( bli_zreal(a), bli_zimag(a), bli_zreal(y), bli_zimag(y) ) #else // ifdef BLIS_ENABLE_C99_COMPLEX #define bli_scinvscaljs( a, y ) { (y) /= (a); } #define bli_dcinvscaljs( a, y ) { (y) /= (a); } #define bli_ccinvscaljs( a, y ) { (y) /= conjf(a); } #define bli_zcinvscaljs( a, y ) { (y) /= conj (a); } #define bli_szinvscaljs( a, y ) { (y) /= (a); } #define bli_dzinvscaljs( a, y ) { (y) /= (a); } #define bli_czinvscaljs( a, y ) { (y) /= conjf(a); } #define bli_zzinvscaljs( a, y ) { (y) /= conj (a); } #endif // BLIS_ENABLE_C99_COMPLEX #define bli_sinvscaljs( a, y ) bli_ssinvscaljs( a, y ) #define bli_dinvscaljs( a, y ) bli_ddinvscaljs( a, y ) #define bli_cinvscaljs( a, y ) bli_ccinvscaljs( a, y ) #define bli_zinvscaljs( a, y ) bli_zzinvscaljs( a, y ) #endif blis-0.9.0/frame/include/level0/bli_invscals.h000066400000000000000000000102461422157504600212070ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_INVSCALS_H #define BLIS_INVSCALS_H // invscals // Notes: // - The first char encodes the type of a. // - The second char encodes the type of y. #define bli_ssinvscals( a, y ) bli_sinvscalris( bli_sreal(a), bli_simag(a), bli_sreal(y), bli_simag(y) ) #define bli_dsinvscals( a, y ) bli_sinvscalris( bli_dreal(a), bli_dimag(a), bli_sreal(y), bli_simag(y) ) #define bli_csinvscals( a, y ) bli_sinvscalris( bli_creal(a), bli_cimag(a), bli_sreal(y), bli_simag(y) ) #define bli_zsinvscals( a, y ) bli_sinvscalris( bli_zreal(a), bli_zimag(a), bli_sreal(y), bli_simag(y) ) #define bli_sdinvscals( a, y ) bli_dinvscalris( bli_sreal(a), bli_simag(a), bli_dreal(y), bli_dimag(y) ) #define bli_ddinvscals( a, y ) bli_dinvscalris( bli_dreal(a), bli_dimag(a), bli_dreal(y), bli_dimag(y) ) #define bli_cdinvscals( a, y ) bli_dinvscalris( bli_creal(a), bli_cimag(a), bli_dreal(y), bli_dimag(y) ) #define bli_zdinvscals( a, y ) bli_dinvscalris( bli_zreal(a), bli_zimag(a), bli_dreal(y), bli_dimag(y) ) #ifndef BLIS_ENABLE_C99_COMPLEX #define bli_scinvscals( a, y ) bli_scinvscalris( bli_sreal(a), bli_simag(a), bli_creal(y), bli_cimag(y) ) #define bli_dcinvscals( a, y ) bli_scinvscalris( bli_dreal(a), bli_dimag(a), bli_creal(y), bli_cimag(y) ) #define bli_ccinvscals( a, y ) bli_cinvscalris( bli_creal(a), bli_cimag(a), bli_creal(y), bli_cimag(y) ) #define bli_zcinvscals( a, y ) bli_cinvscalris( bli_zreal(a), bli_zimag(a), bli_creal(y), bli_cimag(y) ) #define bli_szinvscals( a, y ) bli_dzinvscalris( bli_sreal(a), bli_simag(a), bli_zreal(y), bli_zimag(y) ) #define bli_dzinvscals( a, y ) bli_dzinvscalris( bli_dreal(a), bli_dimag(a), bli_zreal(y), bli_zimag(y) ) #define bli_czinvscals( a, y ) bli_zinvscalris( bli_creal(a), bli_cimag(a), bli_zreal(y), bli_zimag(y) ) #define bli_zzinvscals( a, y ) bli_zinvscalris( bli_zreal(a), bli_zimag(a), bli_zreal(y), bli_zimag(y) ) #else // ifdef BLIS_ENABLE_C99_COMPLEX #define bli_scinvscals( a, y ) { (y) /= (a); } #define bli_dcinvscals( a, y ) { (y) /= (a); } #define bli_ccinvscals( a, y ) { (y) /= (a); } #define bli_zcinvscals( a, y ) { (y) /= (a); } #define bli_szinvscals( a, y ) { (y) /= (a); } #define bli_dzinvscals( a, y ) { (y) /= (a); } #define bli_czinvscals( a, y ) { (y) /= (a); } #define bli_zzinvscals( a, y ) { (y) /= (a); } #endif // BLIS_ENABLE_C99_COMPLEX #define bli_sinvscals( a, y ) bli_ssinvscals( a, y ) #define bli_dinvscals( a, y ) bli_ddinvscals( a, y ) #define bli_cinvscals( a, y ) bli_ccinvscals( a, y ) #define bli_zinvscals( a, y ) bli_zzinvscals( a, y ) #endif blis-0.9.0/frame/include/level0/bli_neg2s.h000066400000000000000000000100051422157504600203740ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_NEG2S_H #define BLIS_NEG2S_H // neg2s // Notes: // - The first char encodes the type of x. // - The second char encodes the type of y. #define bli_ssneg2s( x, y ) bli_sneg2ris( bli_sreal(x), bli_simag(x), bli_sreal(y), bli_simag(y) ) #define bli_dsneg2s( x, y ) bli_sneg2ris( bli_dreal(x), bli_dimag(x), bli_sreal(y), bli_simag(y) ) #define bli_csneg2s( x, y ) bli_sneg2ris( bli_creal(x), bli_cimag(x), bli_sreal(y), bli_simag(y) ) #define bli_zsneg2s( x, y ) bli_sneg2ris( bli_zreal(x), bli_zimag(x), bli_sreal(y), bli_simag(y) ) #define bli_sdneg2s( x, y ) bli_dneg2ris( bli_sreal(x), bli_simag(x), bli_dreal(y), bli_dimag(y) ) #define bli_ddneg2s( x, y ) bli_dneg2ris( bli_dreal(x), bli_dimag(x), bli_dreal(y), bli_dimag(y) ) #define bli_cdneg2s( x, y ) bli_dneg2ris( bli_creal(x), bli_cimag(x), bli_dreal(y), bli_dimag(y) ) #define bli_zdneg2s( x, y ) bli_dneg2ris( bli_zreal(x), bli_zimag(x), bli_dreal(y), bli_dimag(y) ) #ifndef BLIS_ENABLE_C99_COMPLEX #define bli_scneg2s( x, y ) bli_cneg2ris( bli_sreal(x), bli_simag(x), bli_creal(y), bli_cimag(y) ) #define bli_dcneg2s( x, y ) bli_cneg2ris( bli_dreal(x), bli_dimag(x), bli_creal(y), bli_cimag(y) ) #define bli_ccneg2s( x, y ) bli_cneg2ris( bli_creal(x), bli_cimag(x), bli_creal(y), bli_cimag(y) ) #define bli_zcneg2s( x, y ) bli_cneg2ris( bli_zreal(x), bli_zimag(x), bli_creal(y), bli_cimag(y) ) #define bli_szneg2s( x, y ) bli_zneg2ris( bli_sreal(x), bli_simag(x), bli_zreal(y), bli_zimag(y) ) #define bli_dzneg2s( x, y ) bli_zneg2ris( bli_dreal(x), bli_dimag(x), bli_zreal(y), bli_zimag(y) ) #define bli_czneg2s( x, y ) bli_zneg2ris( bli_creal(x), bli_cimag(x), bli_zreal(y), bli_zimag(y) ) #define bli_zzneg2s( x, y ) bli_zneg2ris( bli_zreal(x), bli_zimag(x), bli_zreal(y), bli_zimag(y) ) #else // ifdef BLIS_ENABLE_C99_COMPLEX #define bli_scneg2s( x, y ) { (y) = -(x); } #define bli_dcneg2s( x, y ) { (y) = -(x); } #define bli_ccneg2s( x, y ) { (y) = -(x); } #define bli_zcneg2s( x, y ) { (y) = -(x); } #define bli_szneg2s( x, y ) { (y) = -(x); } #define bli_dzneg2s( x, y ) { (y) = -(x); } #define bli_czneg2s( x, y ) { (y) = -(x); } #define bli_zzneg2s( x, y ) { (y) = -(x); } #endif // BLIS_ENABLE_C99_COMPLEX #define bli_sneg2s( x, y ) bli_ssneg2s( x, y ) #define bli_dneg2s( x, y ) bli_ddneg2s( x, y ) #define bli_cneg2s( x, y ) bli_ccneg2s( x, y ) #define bli_zneg2s( x, y ) bli_zzneg2s( x, y ) #endif blis-0.9.0/frame/include/level0/bli_randnp2s.h000066400000000000000000000124031422157504600211110ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_RANDNP2S_H #define BLIS_RANDNP2S_H // randnp2s #define bli_srandnp2s( a ) \ { \ bli_drandnp2s( a ); \ } #if 0 #define bli_drandnp2s_prev( a ) \ { \ const double m_max = 3.0; \ const double m_max2 = m_max + 2.0; \ double t; \ double r_val; \ \ /* Compute a narrow-range power of two. For the purposes of commentary, we'll assume that m_max = 4. This represents the largest power of two we will use to generate the random numbers. */ \ \ /* Generate a random real number t on the interval: [0.0, 6.0]. */ \ t = ( ( double ) rand() / ( double ) RAND_MAX ) * m_max2; \ \ /* Modify t to guarantee that is never equal to the upper bound of the interval (in this case, 6.0). */ \ if ( t == m_max2 ) t = t - 1.0; \ \ /* Transform the interval into the set of integers, {0,1,2,3,4,5}. */ \ t = floor( t ); \ \ /* Map values of t == 0 to a final value of 0. */ \ if ( t == 0.0 ) r_val = 0.0; \ else \ { \ /* This case handles values of t = {1,2,3,4,5}. */ \ \ double s_exp, s_val; \ \ /* Compute two random numbers to determine the signs of the exponent and the end result. */ \ PASTEMAC(d,rands)( s_exp ); \ PASTEMAC(d,rands)( s_val ); \ \ /* Compute r_val = 2^s where s = +/-(t-1) = {-4,-3,-2,-1,0,1,2,3,4}. */ \ if ( s_exp < 0.0 ) r_val = pow( 2.0, -(t - 1.0) ); \ else r_val = pow( 2.0, t - 1.0 ); \ \ /* If our sign value is negative, our random power of two will be negative. */ \ if ( s_val < 0.0 ) r_val = -r_val; \ } \ \ /* Normalize by the largest possible positive value. */ \ r_val = r_val / pow( 2.0, m_max ); \ \ /* r_val = 0, or +/-{2^-4, 2^-3, 2^-2, 2^-1, 2^0, 2^1, 2^2, 2^3, 2^4}. */ \ /* NOTE: For single-precision macros, this assignment results in typecast down to float. */ \ a = r_val; \ } #endif #define bli_drandnp2s( a ) \ { \ const double m_max = 6.0; \ const double m_max2 = m_max + 2.0; \ double t; \ double r_val; \ \ /* Compute a narrow-range power of two. For the purposes of commentary, we'll assume that m_max = 4. This represents the largest power of two we will use to generate the random numbers. */ \ \ do \ { \ /* Generate a random real number t on the interval: [0.0, 6.0]. */ \ t = ( ( double ) rand() / ( double ) RAND_MAX ) * m_max2; \ \ /* Transform the interval into the set of integers, {0,1,2,3,4,5}. Note that 6 is prohibited by the loop guard below. */ \ t = floor( t ); \ } \ /* If t is ever equal to m_max2, we re-randomize. The guard against m_max2 < t is for sanity and shouldn't happen, unless perhaps there is weirdness in the typecasting to double when computing t above. */ \ while ( m_max2 <= t ); \ \ /* Map values of t == 0 to a final value of 0. */ \ if ( t == 0.0 ) r_val = 0.0; \ else \ { \ /* This case handles values of t = {1,2,3,4,5}. */ \ \ double s_val; \ \ /* Compute r_val = 2^s where s = -(t-1) = {-4,-3,-2,-1,0}. */ \ r_val = pow( 2.0, -(t - 1.0) ); \ \ /* Compute a random number to determine the sign of the final result. */ \ PASTEMAC(d,rands)( s_val ); \ \ /* If our sign value is negative, our random power of two will be negative. */ \ if ( s_val < 0.0 ) r_val = -r_val; \ } \ \ /* r_val = 0, or +/-{2^0, 2^-1, 2^-2, 2^-3, 2^-4}. */ \ /* NOTE: For single-precision macros, this assignment results in typecast down to float. */ \ a = r_val; \ } #define bli_crandnp2s( a ) \ { \ float ar, ai; \ \ bli_srandnp2s( ar ); \ bli_srandnp2s( ai ); \ \ bli_csets( ar, ai, (a) ); \ } #define bli_zrandnp2s( a ) \ { \ double ar, ai; \ \ bli_drandnp2s( ar ); \ bli_drandnp2s( ai ); \ \ bli_zsets( ar, ai, (a) ); \ } #endif blis-0.9.0/frame/include/level0/bli_rands.h000066400000000000000000000043761422157504600205030ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_RANDS_H #define BLIS_RANDS_H // rands #define bli_srands( a ) \ { \ (a) = ( float ) ( ( double ) rand() / \ ( ( double ) RAND_MAX / 2.0 ) \ ) - 1.0F; \ } #define bli_drands( a ) \ { \ (a) = ( double ) ( ( double ) rand() / \ ( ( double ) RAND_MAX / 2.0 ) \ ) - 1.0; \ } #define bli_crands( a ) \ { \ float ar, ai; \ \ bli_srands( ar ); \ bli_srands( ai ); \ \ bli_csets( ar, ai, (a) ); \ } #define bli_zrands( a ) \ { \ double ar, ai; \ \ bli_drands( ar ); \ bli_drands( ai ); \ \ bli_zsets( ar, ai, (a) ); \ } #endif blis-0.9.0/frame/include/level0/bli_scal2js.h000066400000000000000000000321011422157504600207200ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_SCAL2JS_H #define BLIS_SCAL2JS_H // scal2js // Notes: // - The first char encodes the type of a. // - The second char encodes the type of x. // - The third char encodes the type of y. // -- (axy) = (??s) ------------------------------------------------------------ #define bli_sssscal2js( a, x, y ) bli_rxscal2jris( bli_sreal(a), bli_simag(a), bli_sreal(x), bli_simag(x), bli_sreal(y), bli_simag(y) ) #define bli_dssscal2js( a, x, y ) bli_rxscal2jris( bli_dreal(a), bli_dimag(a), bli_sreal(x), bli_simag(x), bli_sreal(y), bli_simag(y) ) #define bli_cssscal2js( a, x, y ) bli_rxscal2jris( bli_creal(a), bli_cimag(a), bli_sreal(x), bli_simag(x), bli_sreal(y), bli_simag(y) ) #define bli_zssscal2js( a, x, y ) bli_rxscal2jris( bli_zreal(a), bli_zimag(a), bli_sreal(x), bli_simag(x), bli_sreal(y), bli_simag(y) ) #define bli_sdsscal2js( a, x, y ) bli_rxscal2jris( bli_sreal(a), bli_simag(a), bli_dreal(x), bli_dimag(x), bli_sreal(y), bli_simag(y) ) #define bli_ddsscal2js( a, x, y ) bli_rxscal2jris( bli_dreal(a), bli_dimag(a), bli_dreal(x), bli_dimag(x), bli_sreal(y), bli_simag(y) ) #define bli_cdsscal2js( a, x, y ) bli_rxscal2jris( bli_creal(a), bli_cimag(a), bli_dreal(x), bli_dimag(x), bli_sreal(y), bli_simag(y) ) #define bli_zdsscal2js( a, x, y ) bli_rxscal2jris( bli_zreal(a), bli_zimag(a), bli_dreal(x), bli_dimag(x), bli_sreal(y), bli_simag(y) ) #define bli_scsscal2js( a, x, y ) bli_rxscal2jris( bli_sreal(a), bli_simag(a), bli_creal(x), bli_cimag(x), bli_sreal(y), bli_simag(y) ) #define bli_dcsscal2js( a, x, y ) bli_rxscal2jris( bli_dreal(a), bli_dimag(a), bli_creal(x), bli_cimag(x), bli_sreal(y), bli_simag(y) ) #define bli_ccsscal2js( a, x, y ) bli_roscal2jris( bli_creal(a), bli_cimag(a), bli_creal(x), bli_cimag(x), bli_sreal(y), bli_simag(y) ) #define bli_zcsscal2js( a, x, y ) bli_roscal2jris( bli_zreal(a), bli_zimag(a), bli_creal(x), bli_cimag(x), bli_sreal(y), bli_simag(y) ) #define bli_szsscal2js( a, x, y ) bli_rxscal2jris( bli_sreal(a), bli_simag(a), bli_zreal(x), bli_zimag(x), bli_sreal(y), bli_simag(y) ) #define bli_dzsscal2js( a, x, y ) bli_rxscal2jris( bli_dreal(a), bli_dimag(a), bli_zreal(x), bli_zimag(x), bli_sreal(y), bli_simag(y) ) #define bli_czsscal2js( a, x, y ) bli_roscal2jris( bli_creal(a), bli_cimag(a), bli_zreal(x), bli_zimag(x), bli_sreal(y), bli_simag(y) ) #define bli_zzsscal2js( a, x, y ) bli_roscal2jris( bli_zreal(a), bli_zimag(a), bli_zreal(x), bli_zimag(x), bli_sreal(y), bli_simag(y) ) // -- (axy) = (??d) ------------------------------------------------------------ #define bli_ssdscal2js( a, x, y ) bli_rxscal2jris( bli_sreal(a), bli_simag(a), bli_sreal(x), bli_simag(x), bli_dreal(y), bli_dimag(y) ) #define bli_dsdscal2js( a, x, y ) bli_rxscal2jris( bli_dreal(a), bli_dimag(a), bli_sreal(x), bli_simag(x), bli_dreal(y), bli_dimag(y) ) #define bli_csdscal2js( a, x, y ) bli_rxscal2jris( bli_creal(a), bli_cimag(a), bli_sreal(x), bli_simag(x), bli_dreal(y), bli_dimag(y) ) #define bli_zsdscal2js( a, x, y ) bli_rxscal2jris( bli_zreal(a), bli_zimag(a), bli_sreal(x), bli_simag(x), bli_dreal(y), bli_dimag(y) ) #define bli_sddscal2js( a, x, y ) bli_rxscal2jris( bli_sreal(a), bli_simag(a), bli_dreal(x), bli_dimag(x), bli_dreal(y), bli_dimag(y) ) #define bli_dddscal2js( a, x, y ) bli_rxscal2jris( bli_dreal(a), bli_dimag(a), bli_dreal(x), bli_dimag(x), bli_dreal(y), bli_dimag(y) ) #define bli_cddscal2js( a, x, y ) bli_rxscal2jris( bli_creal(a), bli_cimag(a), bli_dreal(x), bli_dimag(x), bli_dreal(y), bli_dimag(y) ) #define bli_zddscal2js( a, x, y ) bli_rxscal2jris( bli_zreal(a), bli_zimag(a), bli_dreal(x), bli_dimag(x), bli_dreal(y), bli_dimag(y) ) #define bli_scdscal2js( a, x, y ) bli_rxscal2jris( bli_sreal(a), bli_simag(a), bli_creal(x), bli_cimag(x), bli_dreal(y), bli_dimag(y) ) #define bli_dcdscal2js( a, x, y ) bli_rxscal2jris( bli_dreal(a), bli_dimag(a), bli_creal(x), bli_cimag(x), bli_dreal(y), bli_dimag(y) ) #define bli_ccdscal2js( a, x, y ) bli_roscal2jris( bli_creal(a), bli_cimag(a), bli_creal(x), bli_cimag(x), bli_dreal(y), bli_dimag(y) ) #define bli_zcdscal2js( a, x, y ) bli_roscal2jris( bli_zreal(a), bli_zimag(a), bli_creal(x), bli_cimag(x), bli_dreal(y), bli_dimag(y) ) #define bli_szdscal2js( a, x, y ) bli_rxscal2jris( bli_sreal(a), bli_simag(a), bli_zreal(x), bli_zimag(x), bli_dreal(y), bli_dimag(y) ) #define bli_dzdscal2js( a, x, y ) bli_rxscal2jris( bli_dreal(a), bli_dimag(a), bli_zreal(x), bli_zimag(x), bli_dreal(y), bli_dimag(y) ) #define bli_czdscal2js( a, x, y ) bli_roscal2jris( bli_creal(a), bli_cimag(a), bli_zreal(x), bli_zimag(x), bli_dreal(y), bli_dimag(y) ) #define bli_zzdscal2js( a, x, y ) bli_roscal2jris( bli_zreal(a), bli_zimag(a), bli_zreal(x), bli_zimag(x), bli_dreal(y), bli_dimag(y) ) #ifndef BLIS_ENABLE_C99_COMPLEX // -- (axy) = (??c) ------------------------------------------------------------ #define bli_sscscal2js( a, x, y ) bli_rxscal2jris( bli_sreal(a), bli_simag(a), bli_sreal(x), bli_simag(x), bli_creal(y), bli_cimag(y) ) #define bli_dscscal2js( a, x, y ) bli_rxscal2jris( bli_dreal(a), bli_dimag(a), bli_sreal(x), bli_simag(x), bli_creal(y), bli_cimag(y) ) #define bli_cscscal2js( a, x, y ) bli_rcscal2jris( bli_creal(a), bli_cimag(a), bli_sreal(x), bli_simag(x), bli_creal(y), bli_cimag(y) ) #define bli_zscscal2js( a, x, y ) bli_rcscal2jris( bli_zreal(a), bli_zimag(a), bli_sreal(x), bli_simag(x), bli_creal(y), bli_cimag(y) ) #define bli_sdcscal2js( a, x, y ) bli_rxscal2jris( bli_sreal(a), bli_simag(a), bli_dreal(x), bli_dimag(x), bli_creal(y), bli_cimag(y) ) #define bli_ddcscal2js( a, x, y ) bli_rxscal2jris( bli_dreal(a), bli_dimag(a), bli_dreal(x), bli_dimag(x), bli_creal(y), bli_cimag(y) ) #define bli_cdcscal2js( a, x, y ) bli_rcscal2jris( bli_creal(a), bli_cimag(a), bli_dreal(x), bli_dimag(x), bli_creal(y), bli_cimag(y) ) #define bli_zdcscal2js( a, x, y ) bli_rcscal2jris( bli_zreal(a), bli_zimag(a), bli_dreal(x), bli_dimag(x), bli_creal(y), bli_cimag(y) ) #define bli_sccscal2js( a, x, y ) bli_crscal2jris( bli_sreal(a), bli_simag(a), bli_creal(x), bli_cimag(x), bli_creal(y), bli_cimag(y) ) #define bli_dccscal2js( a, x, y ) bli_crscal2jris( bli_dreal(a), bli_dimag(a), bli_creal(x), bli_cimag(x), bli_creal(y), bli_cimag(y) ) #define bli_cccscal2js( a, x, y ) bli_cxscal2jris( bli_creal(a), bli_cimag(a), bli_creal(x), bli_cimag(x), bli_creal(y), bli_cimag(y) ) #define bli_zccscal2js( a, x, y ) bli_cxscal2jris( bli_zreal(a), bli_zimag(a), bli_creal(x), bli_cimag(x), bli_creal(y), bli_cimag(y) ) #define bli_szcscal2js( a, x, y ) bli_crscal2jris( bli_sreal(a), bli_simag(a), bli_zreal(x), bli_zimag(x), bli_creal(y), bli_cimag(y) ) #define bli_dzcscal2js( a, x, y ) bli_crscal2jris( bli_dreal(a), bli_dimag(a), bli_zreal(x), bli_zimag(x), bli_creal(y), bli_cimag(y) ) #define bli_czcscal2js( a, x, y ) bli_cxscal2jris( bli_creal(a), bli_cimag(a), bli_zreal(x), bli_zimag(x), bli_creal(y), bli_cimag(y) ) #define bli_zzcscal2js( a, x, y ) bli_cxscal2jris( bli_zreal(a), bli_zimag(a), bli_zreal(x), bli_zimag(x), bli_creal(y), bli_cimag(y) ) // -- (axy) = (??z) ------------------------------------------------------------ #define bli_sszscal2js( a, x, y ) bli_rxscal2jris( bli_sreal(a), bli_simag(a), bli_sreal(x), bli_simag(x), bli_zreal(y), bli_zimag(y) ) #define bli_dszscal2js( a, x, y ) bli_rxscal2jris( bli_dreal(a), bli_dimag(a), bli_sreal(x), bli_simag(x), bli_zreal(y), bli_zimag(y) ) #define bli_cszscal2js( a, x, y ) bli_rcscal2jris( bli_creal(a), bli_cimag(a), bli_sreal(x), bli_simag(x), bli_zreal(y), bli_zimag(y) ) #define bli_zszscal2js( a, x, y ) bli_rcscal2jris( bli_zreal(a), bli_zimag(a), bli_sreal(x), bli_simag(x), bli_zreal(y), bli_zimag(y) ) #define bli_sdzscal2js( a, x, y ) bli_rxscal2jris( bli_sreal(a), bli_simag(a), bli_dreal(x), bli_dimag(x), bli_zreal(y), bli_zimag(y) ) #define bli_ddzscal2js( a, x, y ) bli_rxscal2jris( bli_dreal(a), bli_dimag(a), bli_dreal(x), bli_dimag(x), bli_zreal(y), bli_zimag(y) ) #define bli_cdzscal2js( a, x, y ) bli_rcscal2jris( bli_creal(a), bli_cimag(a), bli_dreal(x), bli_dimag(x), bli_zreal(y), bli_zimag(y) ) #define bli_zdzscal2js( a, x, y ) bli_rcscal2jris( bli_zreal(a), bli_zimag(a), bli_dreal(x), bli_dimag(x), bli_zreal(y), bli_zimag(y) ) #define bli_sczscal2js( a, x, y ) bli_crscal2jris( bli_sreal(a), bli_simag(a), bli_creal(x), bli_cimag(x), bli_zreal(y), bli_zimag(y) ) #define bli_dczscal2js( a, x, y ) bli_crscal2jris( bli_dreal(a), bli_dimag(a), bli_creal(x), bli_cimag(x), bli_zreal(y), bli_zimag(y) ) #define bli_cczscal2js( a, x, y ) bli_cxscal2jris( bli_creal(a), bli_cimag(a), bli_creal(x), bli_cimag(x), bli_zreal(y), bli_zimag(y) ) #define bli_zczscal2js( a, x, y ) bli_cxscal2jris( bli_zreal(a), bli_zimag(a), bli_creal(x), bli_cimag(x), bli_zreal(y), bli_zimag(y) ) #define bli_szzscal2js( a, x, y ) bli_crscal2jris( bli_sreal(a), bli_simag(a), bli_zreal(x), bli_zimag(x), bli_zreal(y), bli_zimag(y) ) #define bli_dzzscal2js( a, x, y ) bli_crscal2jris( bli_dreal(a), bli_dimag(a), bli_zreal(x), bli_zimag(x), bli_zreal(y), bli_zimag(y) ) #define bli_czzscal2js( a, x, y ) bli_cxscal2jris( bli_creal(a), bli_cimag(a), bli_zreal(x), bli_zimag(x), bli_zreal(y), bli_zimag(y) ) #define bli_zzzscal2js( a, x, y ) bli_cxscal2jris( bli_zreal(a), bli_zimag(a), bli_zreal(x), bli_zimag(x), bli_zreal(y), bli_zimag(y) ) #else // ifdef BLIS_ENABLE_C99_COMPLEX // -- (axy) = (??c) ------------------------------------------------------------ #define bli_sscscal2js( a, x, y ) { (y) = (a) * (x); } #define bli_dscscal2js( a, x, y ) { (y) = (a) * (x); } #define bli_cscscal2js( a, x, y ) { (y) = (a) * (x); } #define bli_zscscal2js( a, x, y ) { (y) = (a) * (x); } #define bli_sdcscal2js( a, x, y ) { (y) = (a) * (x); } #define bli_ddcscal2js( a, x, y ) { (y) = (a) * (x); } #define bli_cdcscal2js( a, x, y ) { (y) = (a) * (x); } #define bli_zdcscal2js( a, x, y ) { (y) = (a) * (x); } #define bli_sccscal2js( a, x, y ) { (y) = (a) * conjf(x); } #define bli_dccscal2js( a, x, y ) { (y) = (a) * conjf(x); } #define bli_cccscal2js( a, x, y ) { (y) = (a) * conjf(x); } #define bli_zccscal2js( a, x, y ) { (y) = (a) * conjf(x); } #define bli_szcscal2js( a, x, y ) { (y) = (a) * conj(x); } #define bli_dzcscal2js( a, x, y ) { (y) = (a) * conj(x); } #define bli_czcscal2js( a, x, y ) { (y) = (a) * conj(x); } #define bli_zzcscal2js( a, x, y ) { (y) = (a) * conj(x); } // -- (axy) = (??z) ------------------------------------------------------------ #define bli_sszscal2js( a, x, y ) { (y) = (a) * (x); } #define bli_dszscal2js( a, x, y ) { (y) = (a) * (x); } #define bli_cszscal2js( a, x, y ) { (y) = (a) * (x); } #define bli_zszscal2js( a, x, y ) { (y) = (a) * (x); } #define bli_sdzscal2js( a, x, y ) { (y) = (a) * (x); } #define bli_ddzscal2js( a, x, y ) { (y) = (a) * (x); } #define bli_cdzscal2js( a, x, y ) { (y) = (a) * (x); } #define bli_zdzscal2js( a, x, y ) { (y) = (a) * (x); } #define bli_sczscal2js( a, x, y ) { (y) = (a) * conjf(x); } #define bli_dczscal2js( a, x, y ) { (y) = (a) * conjf(x); } #define bli_cczscal2js( a, x, y ) { (y) = (a) * conjf(x); } #define bli_zczscal2js( a, x, y ) { (y) = (a) * conjf(x); } #define bli_szzscal2js( a, x, y ) { (y) = (a) * conj(x); } #define bli_dzzscal2js( a, x, y ) { (y) = (a) * conj(x); } #define bli_czzscal2js( a, x, y ) { (y) = (a) * conj(x); } #define bli_zzzscal2js( a, x, y ) { (y) = (a) * conj(x); } #endif // BLIS_ENABLE_C99_COMPLEX #define bli_sscal2js( a, x, y ) bli_sssscal2js( a, x, y ) #define bli_dscal2js( a, x, y ) bli_dddscal2js( a, x, y ) #define bli_cscal2js( a, x, y ) bli_cccscal2js( a, x, y ) #define bli_zscal2js( a, x, y ) bli_zzzscal2js( a, x, y ) #endif blis-0.9.0/frame/include/level0/bli_scal2s.h000066400000000000000000000315151422157504600205560ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_SCAL2S_H #define BLIS_SCAL2S_H // scal2s // Notes: // - The first char encodes the type of a. // - The second char encodes the type of x. // - The third char encodes the type of y. // -- (axy) = (??s) ------------------------------------------------------------ #define bli_sssscal2s( a, x, y ) bli_rxscal2ris( bli_sreal(a), bli_simag(a), bli_sreal(x), bli_simag(x), bli_sreal(y), bli_simag(y) ) #define bli_dssscal2s( a, x, y ) bli_rxscal2ris( bli_dreal(a), bli_dimag(a), bli_sreal(x), bli_simag(x), bli_sreal(y), bli_simag(y) ) #define bli_cssscal2s( a, x, y ) bli_rxscal2ris( bli_creal(a), bli_cimag(a), bli_sreal(x), bli_simag(x), bli_sreal(y), bli_simag(y) ) #define bli_zssscal2s( a, x, y ) bli_rxscal2ris( bli_zreal(a), bli_zimag(a), bli_sreal(x), bli_simag(x), bli_sreal(y), bli_simag(y) ) #define bli_sdsscal2s( a, x, y ) bli_rxscal2ris( bli_sreal(a), bli_simag(a), bli_dreal(x), bli_dimag(x), bli_sreal(y), bli_simag(y) ) #define bli_ddsscal2s( a, x, y ) bli_rxscal2ris( bli_dreal(a), bli_dimag(a), bli_dreal(x), bli_dimag(x), bli_sreal(y), bli_simag(y) ) #define bli_cdsscal2s( a, x, y ) bli_rxscal2ris( bli_creal(a), bli_cimag(a), bli_dreal(x), bli_dimag(x), bli_sreal(y), bli_simag(y) ) #define bli_zdsscal2s( a, x, y ) bli_rxscal2ris( bli_zreal(a), bli_zimag(a), bli_dreal(x), bli_dimag(x), bli_sreal(y), bli_simag(y) ) #define bli_scsscal2s( a, x, y ) bli_rxscal2ris( bli_sreal(a), bli_simag(a), bli_creal(x), bli_cimag(x), bli_sreal(y), bli_simag(y) ) #define bli_dcsscal2s( a, x, y ) bli_rxscal2ris( bli_dreal(a), bli_dimag(a), bli_creal(x), bli_cimag(x), bli_sreal(y), bli_simag(y) ) #define bli_ccsscal2s( a, x, y ) bli_roscal2ris( bli_creal(a), bli_cimag(a), bli_creal(x), bli_cimag(x), bli_sreal(y), bli_simag(y) ) #define bli_zcsscal2s( a, x, y ) bli_roscal2ris( bli_zreal(a), bli_zimag(a), bli_creal(x), bli_cimag(x), bli_sreal(y), bli_simag(y) ) #define bli_szsscal2s( a, x, y ) bli_rxscal2ris( bli_sreal(a), bli_simag(a), bli_zreal(x), bli_zimag(x), bli_sreal(y), bli_simag(y) ) #define bli_dzsscal2s( a, x, y ) bli_rxscal2ris( bli_dreal(a), bli_dimag(a), bli_zreal(x), bli_zimag(x), bli_sreal(y), bli_simag(y) ) #define bli_czsscal2s( a, x, y ) bli_roscal2ris( bli_creal(a), bli_cimag(a), bli_zreal(x), bli_zimag(x), bli_sreal(y), bli_simag(y) ) #define bli_zzsscal2s( a, x, y ) bli_roscal2ris( bli_zreal(a), bli_zimag(a), bli_zreal(x), bli_zimag(x), bli_sreal(y), bli_simag(y) ) // -- (axy) = (??d) ------------------------------------------------------------ #define bli_ssdscal2s( a, x, y ) bli_rxscal2ris( bli_sreal(a), bli_simag(a), bli_sreal(x), bli_simag(x), bli_dreal(y), bli_dimag(y) ) #define bli_dsdscal2s( a, x, y ) bli_rxscal2ris( bli_dreal(a), bli_dimag(a), bli_sreal(x), bli_simag(x), bli_dreal(y), bli_dimag(y) ) #define bli_csdscal2s( a, x, y ) bli_rxscal2ris( bli_creal(a), bli_cimag(a), bli_sreal(x), bli_simag(x), bli_dreal(y), bli_dimag(y) ) #define bli_zsdscal2s( a, x, y ) bli_rxscal2ris( bli_zreal(a), bli_zimag(a), bli_sreal(x), bli_simag(x), bli_dreal(y), bli_dimag(y) ) #define bli_sddscal2s( a, x, y ) bli_rxscal2ris( bli_sreal(a), bli_simag(a), bli_dreal(x), bli_dimag(x), bli_dreal(y), bli_dimag(y) ) #define bli_dddscal2s( a, x, y ) bli_rxscal2ris( bli_dreal(a), bli_dimag(a), bli_dreal(x), bli_dimag(x), bli_dreal(y), bli_dimag(y) ) #define bli_cddscal2s( a, x, y ) bli_rxscal2ris( bli_creal(a), bli_cimag(a), bli_dreal(x), bli_dimag(x), bli_dreal(y), bli_dimag(y) ) #define bli_zddscal2s( a, x, y ) bli_rxscal2ris( bli_zreal(a), bli_zimag(a), bli_dreal(x), bli_dimag(x), bli_dreal(y), bli_dimag(y) ) #define bli_scdscal2s( a, x, y ) bli_rxscal2ris( bli_sreal(a), bli_simag(a), bli_creal(x), bli_cimag(x), bli_dreal(y), bli_dimag(y) ) #define bli_dcdscal2s( a, x, y ) bli_rxscal2ris( bli_dreal(a), bli_dimag(a), bli_creal(x), bli_cimag(x), bli_dreal(y), bli_dimag(y) ) #define bli_ccdscal2s( a, x, y ) bli_roscal2ris( bli_creal(a), bli_cimag(a), bli_creal(x), bli_cimag(x), bli_dreal(y), bli_dimag(y) ) #define bli_zcdscal2s( a, x, y ) bli_roscal2ris( bli_zreal(a), bli_zimag(a), bli_creal(x), bli_cimag(x), bli_dreal(y), bli_dimag(y) ) #define bli_szdscal2s( a, x, y ) bli_rxscal2ris( bli_sreal(a), bli_simag(a), bli_zreal(x), bli_zimag(x), bli_dreal(y), bli_dimag(y) ) #define bli_dzdscal2s( a, x, y ) bli_rxscal2ris( bli_dreal(a), bli_dimag(a), bli_zreal(x), bli_zimag(x), bli_dreal(y), bli_dimag(y) ) #define bli_czdscal2s( a, x, y ) bli_roscal2ris( bli_creal(a), bli_cimag(a), bli_zreal(x), bli_zimag(x), bli_dreal(y), bli_dimag(y) ) #define bli_zzdscal2s( a, x, y ) bli_roscal2ris( bli_zreal(a), bli_zimag(a), bli_zreal(x), bli_zimag(x), bli_dreal(y), bli_dimag(y) ) #ifndef BLIS_ENABLE_C99_COMPLEX // -- (axy) = (??c) ------------------------------------------------------------ #define bli_sscscal2s( a, x, y ) bli_rxscal2ris( bli_sreal(a), bli_simag(a), bli_sreal(x), bli_simag(x), bli_creal(y), bli_cimag(y) ) #define bli_dscscal2s( a, x, y ) bli_rxscal2ris( bli_dreal(a), bli_dimag(a), bli_sreal(x), bli_simag(x), bli_creal(y), bli_cimag(y) ) #define bli_cscscal2s( a, x, y ) bli_rcscal2ris( bli_creal(a), bli_cimag(a), bli_sreal(x), bli_simag(x), bli_creal(y), bli_cimag(y) ) #define bli_zscscal2s( a, x, y ) bli_rcscal2ris( bli_zreal(a), bli_zimag(a), bli_sreal(x), bli_simag(x), bli_creal(y), bli_cimag(y) ) #define bli_sdcscal2s( a, x, y ) bli_rxscal2ris( bli_sreal(a), bli_simag(a), bli_dreal(x), bli_dimag(x), bli_creal(y), bli_cimag(y) ) #define bli_ddcscal2s( a, x, y ) bli_rxscal2ris( bli_dreal(a), bli_dimag(a), bli_dreal(x), bli_dimag(x), bli_creal(y), bli_cimag(y) ) #define bli_cdcscal2s( a, x, y ) bli_rcscal2ris( bli_creal(a), bli_cimag(a), bli_dreal(x), bli_dimag(x), bli_creal(y), bli_cimag(y) ) #define bli_zdcscal2s( a, x, y ) bli_rcscal2ris( bli_zreal(a), bli_zimag(a), bli_dreal(x), bli_dimag(x), bli_creal(y), bli_cimag(y) ) #define bli_sccscal2s( a, x, y ) bli_crscal2ris( bli_sreal(a), bli_simag(a), bli_creal(x), bli_cimag(x), bli_creal(y), bli_cimag(y) ) #define bli_dccscal2s( a, x, y ) bli_crscal2ris( bli_dreal(a), bli_dimag(a), bli_creal(x), bli_cimag(x), bli_creal(y), bli_cimag(y) ) #define bli_cccscal2s( a, x, y ) bli_cxscal2ris( bli_creal(a), bli_cimag(a), bli_creal(x), bli_cimag(x), bli_creal(y), bli_cimag(y) ) #define bli_zccscal2s( a, x, y ) bli_cxscal2ris( bli_zreal(a), bli_zimag(a), bli_creal(x), bli_cimag(x), bli_creal(y), bli_cimag(y) ) #define bli_szcscal2s( a, x, y ) bli_crscal2ris( bli_sreal(a), bli_simag(a), bli_zreal(x), bli_zimag(x), bli_creal(y), bli_cimag(y) ) #define bli_dzcscal2s( a, x, y ) bli_crscal2ris( bli_dreal(a), bli_dimag(a), bli_zreal(x), bli_zimag(x), bli_creal(y), bli_cimag(y) ) #define bli_czcscal2s( a, x, y ) bli_cxscal2ris( bli_creal(a), bli_cimag(a), bli_zreal(x), bli_zimag(x), bli_creal(y), bli_cimag(y) ) #define bli_zzcscal2s( a, x, y ) bli_cxscal2ris( bli_zreal(a), bli_zimag(a), bli_zreal(x), bli_zimag(x), bli_creal(y), bli_cimag(y) ) // -- (axy) = (??z) ------------------------------------------------------------ #define bli_sszscal2s( a, x, y ) bli_rxscal2ris( bli_sreal(a), bli_simag(a), bli_sreal(x), bli_simag(x), bli_zreal(y), bli_zimag(y) ) #define bli_dszscal2s( a, x, y ) bli_rxscal2ris( bli_dreal(a), bli_dimag(a), bli_sreal(x), bli_simag(x), bli_zreal(y), bli_zimag(y) ) #define bli_cszscal2s( a, x, y ) bli_rcscal2ris( bli_creal(a), bli_cimag(a), bli_sreal(x), bli_simag(x), bli_zreal(y), bli_zimag(y) ) #define bli_zszscal2s( a, x, y ) bli_rcscal2ris( bli_zreal(a), bli_zimag(a), bli_sreal(x), bli_simag(x), bli_zreal(y), bli_zimag(y) ) #define bli_sdzscal2s( a, x, y ) bli_rxscal2ris( bli_sreal(a), bli_simag(a), bli_dreal(x), bli_dimag(x), bli_zreal(y), bli_zimag(y) ) #define bli_ddzscal2s( a, x, y ) bli_rxscal2ris( bli_dreal(a), bli_dimag(a), bli_dreal(x), bli_dimag(x), bli_zreal(y), bli_zimag(y) ) #define bli_cdzscal2s( a, x, y ) bli_rcscal2ris( bli_creal(a), bli_cimag(a), bli_dreal(x), bli_dimag(x), bli_zreal(y), bli_zimag(y) ) #define bli_zdzscal2s( a, x, y ) bli_rcscal2ris( bli_zreal(a), bli_zimag(a), bli_dreal(x), bli_dimag(x), bli_zreal(y), bli_zimag(y) ) #define bli_sczscal2s( a, x, y ) bli_crscal2ris( bli_sreal(a), bli_simag(a), bli_creal(x), bli_cimag(x), bli_zreal(y), bli_zimag(y) ) #define bli_dczscal2s( a, x, y ) bli_crscal2ris( bli_dreal(a), bli_dimag(a), bli_creal(x), bli_cimag(x), bli_zreal(y), bli_zimag(y) ) #define bli_cczscal2s( a, x, y ) bli_cxscal2ris( bli_creal(a), bli_cimag(a), bli_creal(x), bli_cimag(x), bli_zreal(y), bli_zimag(y) ) #define bli_zczscal2s( a, x, y ) bli_cxscal2ris( bli_zreal(a), bli_zimag(a), bli_creal(x), bli_cimag(x), bli_zreal(y), bli_zimag(y) ) #define bli_szzscal2s( a, x, y ) bli_crscal2ris( bli_sreal(a), bli_simag(a), bli_zreal(x), bli_zimag(x), bli_zreal(y), bli_zimag(y) ) #define bli_dzzscal2s( a, x, y ) bli_crscal2ris( bli_dreal(a), bli_dimag(a), bli_zreal(x), bli_zimag(x), bli_zreal(y), bli_zimag(y) ) #define bli_czzscal2s( a, x, y ) bli_cxscal2ris( bli_creal(a), bli_cimag(a), bli_zreal(x), bli_zimag(x), bli_zreal(y), bli_zimag(y) ) #define bli_zzzscal2s( a, x, y ) bli_cxscal2ris( bli_zreal(a), bli_zimag(a), bli_zreal(x), bli_zimag(x), bli_zreal(y), bli_zimag(y) ) #else // ifdef BLIS_ENABLE_C99_COMPLEX // -- (axy) = (??c) ------------------------------------------------------------ #define bli_sscscal2s( a, x, y ) { (y) = (a) * (x); } #define bli_dscscal2s( a, x, y ) { (y) = (a) * (x); } #define bli_cscscal2s( a, x, y ) { (y) = (a) * (x); } #define bli_zscscal2s( a, x, y ) { (y) = (a) * (x); } #define bli_sdcscal2s( a, x, y ) { (y) = (a) * (x); } #define bli_ddcscal2s( a, x, y ) { (y) = (a) * (x); } #define bli_cdcscal2s( a, x, y ) { (y) = (a) * (x); } #define bli_zdcscal2s( a, x, y ) { (y) = (a) * (x); } #define bli_sccscal2s( a, x, y ) { (y) = (a) * (x); } #define bli_dccscal2s( a, x, y ) { (y) = (a) * (x); } #define bli_cccscal2s( a, x, y ) { (y) = (a) * (x); } #define bli_zccscal2s( a, x, y ) { (y) = (a) * (x); } #define bli_szcscal2s( a, x, y ) { (y) = (a) * (x); } #define bli_dzcscal2s( a, x, y ) { (y) = (a) * (x); } #define bli_czcscal2s( a, x, y ) { (y) = (a) * (x); } #define bli_zzcscal2s( a, x, y ) { (y) = (a) * (x); } // -- (axy) = (??z) ------------------------------------------------------------ #define bli_sszscal2s( a, x, y ) { (y) = (a) * (x); } #define bli_dszscal2s( a, x, y ) { (y) = (a) * (x); } #define bli_cszscal2s( a, x, y ) { (y) = (a) * (x); } #define bli_zszscal2s( a, x, y ) { (y) = (a) * (x); } #define bli_sdzscal2s( a, x, y ) { (y) = (a) * (x); } #define bli_ddzscal2s( a, x, y ) { (y) = (a) * (x); } #define bli_cdzscal2s( a, x, y ) { (y) = (a) * (x); } #define bli_zdzscal2s( a, x, y ) { (y) = (a) * (x); } #define bli_sczscal2s( a, x, y ) { (y) = (a) * (x); } #define bli_dczscal2s( a, x, y ) { (y) = (a) * (x); } #define bli_cczscal2s( a, x, y ) { (y) = (a) * (x); } #define bli_zczscal2s( a, x, y ) { (y) = (a) * (x); } #define bli_szzscal2s( a, x, y ) { (y) = (a) * (x); } #define bli_dzzscal2s( a, x, y ) { (y) = (a) * (x); } #define bli_czzscal2s( a, x, y ) { (y) = (a) * (x); } #define bli_zzzscal2s( a, x, y ) { (y) = (a) * (x); } #endif // BLIS_ENABLE_C99_COMPLEX #define bli_sscal2s( a, x, y ) bli_sssscal2s( a, x, y ) #define bli_dscal2s( a, x, y ) bli_dddscal2s( a, x, y ) #define bli_cscal2s( a, x, y ) bli_cccscal2s( a, x, y ) #define bli_zscal2s( a, x, y ) bli_zzzscal2s( a, x, y ) #endif blis-0.9.0/frame/include/level0/bli_scal2s_mxn.h000066400000000000000000000055131422157504600214370ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_SCAL2S_MXN_H #define BLIS_SCAL2S_MXN_H // scal2s_mxn #undef GENTFUNC #define GENTFUNC( ctype, ch, opname ) \ \ BLIS_INLINE void PASTEMAC(ch,opname) \ ( \ const conj_t conjx, \ const dim_t m, \ const dim_t n, \ ctype* restrict alpha, \ ctype* restrict x, const inc_t rs_x, const inc_t cs_x, \ ctype* restrict y, const inc_t rs_y, const inc_t cs_y \ ) \ { \ if ( bli_is_conj( conjx ) ) \ { \ for ( dim_t j = 0; j < n; ++j ) \ { \ ctype* restrict xj = x + j*cs_x; \ ctype* restrict yj = y + j*cs_y; \ \ for ( dim_t i = 0; i < m; ++i ) \ { \ ctype* restrict xij = xj + i*rs_x; \ ctype* restrict yij = yj + i*rs_y; \ \ PASTEMAC(ch,scal2js)( *alpha, *xij, *yij ); \ } \ } \ } \ else /* if ( bli_is_noconj( conjx ) ) */ \ { \ for ( dim_t j = 0; j < n; ++j ) \ { \ ctype* restrict xj = x + j*cs_x; \ ctype* restrict yj = y + j*cs_y; \ \ for ( dim_t i = 0; i < m; ++i ) \ { \ ctype* restrict xij = xj + i*rs_x; \ ctype* restrict yij = yj + i*rs_y; \ \ PASTEMAC(ch,scal2s)( *alpha, *xij, *yij ); \ } \ } \ } \ } INSERT_GENTFUNC_BASIC0( scal2s_mxn ) #endif blis-0.9.0/frame/include/level0/bli_scalcjs.h000066400000000000000000000111331422157504600210030ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_SCALCJS_H #define BLIS_SCALCJS_H // scalcjs // Notes: // - The first char encodes the type of x. // - The second char encodes the type of y. #define bli_ssscalcjs( conjx, x, y ) bli_sscalcjris( conjx, bli_sreal(x), bli_simag(x), bli_sreal(y), bli_simag(y) ) #define bli_dsscalcjs( conjx, x, y ) bli_sscalcjris( conjx, bli_dreal(x), bli_dimag(x), bli_sreal(y), bli_simag(y) ) #define bli_csscalcjs( conjx, x, y ) bli_sscalcjris( conjx, bli_creal(x), bli_cimag(x), bli_sreal(y), bli_simag(y) ) #define bli_zsscalcjs( conjx, x, y ) bli_sscalcjris( conjx, bli_zreal(x), bli_zimag(x), bli_sreal(y), bli_simag(y) ) #define bli_sdscalcjs( conjx, x, y ) bli_dscalcjris( conjx, bli_sreal(x), bli_simag(x), bli_dreal(y), bli_dimag(y) ) #define bli_ddscalcjs( conjx, x, y ) bli_dscalcjris( conjx, bli_dreal(x), bli_dimag(x), bli_dreal(y), bli_dimag(y) ) #define bli_cdscalcjs( conjx, x, y ) bli_dscalcjris( conjx, bli_creal(x), bli_cimag(x), bli_dreal(y), bli_dimag(y) ) #define bli_zdscalcjs( conjx, x, y ) bli_dscalcjris( conjx, bli_zreal(x), bli_zimag(x), bli_dreal(y), bli_dimag(y) ) #ifndef BLIS_ENABLE_C99_COMPLEX #define bli_scscalcjs( conjx, x, y ) bli_scscalcjris( conjx, bli_sreal(x), bli_simag(x), bli_creal(y), bli_cimag(y) ) #define bli_dcscalcjs( conjx, x, y ) bli_scscalcjris( conjx, bli_dreal(x), bli_dimag(x), bli_creal(y), bli_cimag(y) ) #define bli_ccscalcjs( conjx, x, y ) bli_cscalcjris( conjx, bli_creal(x), bli_cimag(x), bli_creal(y), bli_cimag(y) ) #define bli_zcscalcjs( conjx, x, y ) bli_cscalcjris( conjx, bli_zreal(x), bli_zimag(x), bli_creal(y), bli_cimag(y) ) #define bli_szscalcjs( conjx, x, y ) bli_dzscalcjris( conjx, bli_sreal(x), bli_simag(x), bli_zreal(y), bli_zimag(y) ) #define bli_dzscalcjs( conjx, x, y ) bli_dzscalcjris( conjx, bli_dreal(x), bli_dimag(x), bli_zreal(y), bli_zimag(y) ) #define bli_czscalcjs( conjx, x, y ) bli_zscalcjris( conjx, bli_creal(x), bli_cimag(x), bli_zreal(y), bli_zimag(y) ) #define bli_zzscalcjs( conjx, x, y ) bli_zscalcjris( conjx, bli_zreal(x), bli_zimag(x), bli_zreal(y), bli_zimag(y) ) #else // ifdef BLIS_ENABLE_C99_COMPLEX #define bli_scscalcjs( conjx, x, y ) { (y) *= (x); } #define bli_dcscalcjs( conjx, x, y ) { (y) *= (x); } #define bli_ccscalcjs( conjx, x, y ) { (y) *= ( bli_is_conj( conjx ) ? conjf(x) : (x) ); } #define bli_zcscalcjs( conjx, x, y ) { (y) *= ( bli_is_conj( conjx ) ? conj (x) : (x) ); } #define bli_szscalcjs( conjx, x, y ) { (y) *= (x); } #define bli_dzscalcjs( conjx, x, y ) { (y) *= (x); } #define bli_czscalcjs( conjx, x, y ) { (y) *= ( bli_is_conj( conjx ) ? conjf(x) : (x) ); } #define bli_zzscalcjs( conjx, x, y ) { (y) *= ( bli_is_conj( conjx ) ? conj (x) : (x) ); } #endif // BLIS_ENABLE_C99_COMPLEX #define bli_sscalcjs( conjx, x, y ) bli_ssscalcjs( conjx, x, y ) #define bli_dscalcjs( conjx, x, y ) bli_ddscalcjs( conjx, x, y ) #define bli_cscalcjs( conjx, x, y ) bli_ccscalcjs( conjx, x, y ) #define bli_zscalcjs( conjx, x, y ) bli_zzscalcjs( conjx, x, y ) #endif blis-0.9.0/frame/include/level0/bli_scaljs.h000066400000000000000000000101501422157504600206360ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_SCALJS_H #define BLIS_SCALJS_H // scaljs // Notes: // - The first char encodes the type of a. // - The second char encodes the type of y. #define bli_ssscaljs( a, y ) bli_sscaljris( bli_sreal(a), bli_simag(a), bli_sreal(y), bli_simag(y) ) #define bli_dsscaljs( a, y ) bli_sscaljris( bli_dreal(a), bli_dimag(a), bli_sreal(y), bli_simag(y) ) #define bli_csscaljs( a, y ) bli_sscaljris( bli_creal(a), bli_cimag(a), bli_sreal(y), bli_simag(y) ) #define bli_zsscaljs( a, y ) bli_sscaljris( bli_zreal(a), bli_zimag(a), bli_sreal(y), bli_simag(y) ) #define bli_sdscaljs( a, y ) bli_dscaljris( bli_sreal(a), bli_simag(a), bli_dreal(y), bli_dimag(y) ) #define bli_ddscaljs( a, y ) bli_dscaljris( bli_dreal(a), bli_dimag(a), bli_dreal(y), bli_dimag(y) ) #define bli_cdscaljs( a, y ) bli_dscaljris( bli_creal(a), bli_cimag(a), bli_dreal(y), bli_dimag(y) ) #define bli_zdscaljs( a, y ) bli_dscaljris( bli_zreal(a), bli_zimag(a), bli_dreal(y), bli_dimag(y) ) #ifndef BLIS_ENABLE_C99_COMPLEX #define bli_scscaljs( a, y ) bli_scscaljris( bli_sreal(a), bli_simag(a), bli_creal(y), bli_cimag(y) ) #define bli_dcscaljs( a, y ) bli_scscaljris( bli_dreal(a), bli_dimag(a), bli_creal(y), bli_cimag(y) ) #define bli_ccscaljs( a, y ) bli_cscaljris( bli_creal(a), bli_cimag(a), bli_creal(y), bli_cimag(y) ) #define bli_zcscaljs( a, y ) bli_cscaljris( bli_zreal(a), bli_zimag(a), bli_creal(y), bli_cimag(y) ) #define bli_szscaljs( a, y ) bli_dzscaljris( bli_sreal(a), bli_simag(a), bli_zreal(y), bli_zimag(y) ) #define bli_dzscaljs( a, y ) bli_dzscaljris( bli_dreal(a), bli_dimag(a), bli_zreal(y), bli_zimag(y) ) #define bli_czscaljs( a, y ) bli_zscaljris( bli_creal(a), bli_cimag(a), bli_zreal(y), bli_zimag(y) ) #define bli_zzscaljs( a, y ) bli_zscaljris( bli_zreal(a), bli_zimag(a), bli_zreal(y), bli_zimag(y) ) #else // ifdef BLIS_ENABLE_C99_COMPLEX #define bli_scscaljs( a, y ) { (y) *= (a); } #define bli_dcscaljs( a, y ) { (y) *= (a); } #define bli_ccscaljs( a, y ) { (y) *= conjf(a); } #define bli_zcscaljs( a, y ) { (y) *= conj (a); } #define bli_szscaljs( a, y ) { (y) *= (a); } #define bli_dzscaljs( a, y ) { (y) *= (a); } #define bli_czscaljs( a, y ) { (y) *= conjf(a); } #define bli_zzscaljs( a, y ) { (y) *= conj (a); } #endif // BLIS_ENABLE_C99_COMPLEX #define bli_sscaljs( a, y ) bli_ssscaljs( a, y ) #define bli_dscaljs( a, y ) bli_ddscaljs( a, y ) #define bli_cscaljs( a, y ) bli_ccscaljs( a, y ) #define bli_zscaljs( a, y ) bli_zzscaljs( a, y ) #endif blis-0.9.0/frame/include/level0/bli_scals.h000066400000000000000000000100151422157504600204640ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_SCALS_H #define BLIS_SCALS_H // scals // Notes: // - The first char encodes the type of a. // - The second char encodes the type of y. #define bli_ssscals( a, y ) bli_sscalris( bli_sreal(a), bli_simag(a), bli_sreal(y), bli_simag(y) ) #define bli_dsscals( a, y ) bli_sscalris( bli_dreal(a), bli_dimag(a), bli_sreal(y), bli_simag(y) ) #define bli_csscals( a, y ) bli_sscalris( bli_creal(a), bli_cimag(a), bli_sreal(y), bli_simag(y) ) #define bli_zsscals( a, y ) bli_sscalris( bli_zreal(a), bli_zimag(a), bli_sreal(y), bli_simag(y) ) #define bli_sdscals( a, y ) bli_dscalris( bli_sreal(a), bli_simag(a), bli_dreal(y), bli_dimag(y) ) #define bli_ddscals( a, y ) bli_dscalris( bli_dreal(a), bli_dimag(a), bli_dreal(y), bli_dimag(y) ) #define bli_cdscals( a, y ) bli_dscalris( bli_creal(a), bli_cimag(a), bli_dreal(y), bli_dimag(y) ) #define bli_zdscals( a, y ) bli_dscalris( bli_zreal(a), bli_zimag(a), bli_dreal(y), bli_dimag(y) ) #ifndef BLIS_ENABLE_C99_COMPLEX #define bli_scscals( a, y ) bli_scscalris( bli_sreal(a), bli_simag(a), bli_creal(y), bli_cimag(y) ) #define bli_dcscals( a, y ) bli_scscalris( bli_dreal(a), bli_dimag(a), bli_creal(y), bli_cimag(y) ) #define bli_ccscals( a, y ) bli_cscalris( bli_creal(a), bli_cimag(a), bli_creal(y), bli_cimag(y) ) #define bli_zcscals( a, y ) bli_cscalris( bli_zreal(a), bli_zimag(a), bli_creal(y), bli_cimag(y) ) #define bli_szscals( a, y ) bli_dzscalris( bli_sreal(a), bli_simag(a), bli_zreal(y), bli_zimag(y) ) #define bli_dzscals( a, y ) bli_dzscalris( bli_dreal(a), bli_dimag(a), bli_zreal(y), bli_zimag(y) ) #define bli_czscals( a, y ) bli_zscalris( bli_creal(a), bli_cimag(a), bli_zreal(y), bli_zimag(y) ) #define bli_zzscals( a, y ) bli_zscalris( bli_zreal(a), bli_zimag(a), bli_zreal(y), bli_zimag(y) ) #else // ifdef BLIS_ENABLE_C99_COMPLEX #define bli_scscals( a, y ) { (y) *= (a); } #define bli_dcscals( a, y ) { (y) *= (a); } #define bli_ccscals( a, y ) { (y) *= (a); } #define bli_zcscals( a, y ) { (y) *= (a); } #define bli_szscals( a, y ) { (y) *= (a); } #define bli_dzscals( a, y ) { (y) *= (a); } #define bli_czscals( a, y ) { (y) *= (a); } #define bli_zzscals( a, y ) { (y) *= (a); } #endif // BLIS_ENABLE_C99_COMPLEX #define bli_sscals( a, y ) bli_ssscals( a, y ) #define bli_dscals( a, y ) bli_ddscals( a, y ) #define bli_cscals( a, y ) bli_ccscals( a, y ) #define bli_zscals( a, y ) bli_zzscals( a, y ) #endif blis-0.9.0/frame/include/level0/bli_set0s.h000066400000000000000000000036251422157504600204260ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_SET0S_H #define BLIS_SET0S_H #define bli_sset0s( a ) bli_ssets( 0.0F, 0.0F, (a) ) #define bli_dset0s( a ) bli_dsets( 0.0 , 0.0 , (a) ) #define bli_cset0s( a ) bli_csets( 0.0F, 0.0F, (a) ) #define bli_zset0s( a ) bli_zsets( 0.0 , 0.0 , (a) ) #endif blis-0.9.0/frame/include/level0/bli_set0s_mxn.h000066400000000000000000000055031422157504600213050ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_SET0S_MXN_H #define BLIS_SET0S_MXN_H // set0s_mxn // Notes: // - The first char encodes the type of x. // - The second char encodes the type of y. BLIS_INLINE void bli_sset0s_mxn( const dim_t m, const dim_t n, float* restrict y, const inc_t rs_y, const inc_t cs_y ) { for ( dim_t j = 0; j < n; ++j ) for ( dim_t i = 0; i < m; ++i ) bli_sset0s( *(y + i*rs_y + j*cs_y) ); } BLIS_INLINE void bli_dset0s_mxn( const dim_t m, const dim_t n, double* restrict y, const inc_t rs_y, const inc_t cs_y ) { for ( dim_t j = 0; j < n; ++j ) for ( dim_t i = 0; i < m; ++i ) bli_dset0s( *(y + i*rs_y + j*cs_y) ); } BLIS_INLINE void bli_cset0s_mxn( const dim_t m, const dim_t n, scomplex* restrict y, const inc_t rs_y, const inc_t cs_y ) { for ( dim_t j = 0; j < n; ++j ) for ( dim_t i = 0; i < m; ++i ) bli_cset0s( *(y + i*rs_y + j*cs_y) ); } BLIS_INLINE void bli_zset0s_mxn( const dim_t m, const dim_t n, dcomplex* restrict y, const inc_t rs_y, const inc_t cs_y ) { for ( dim_t j = 0; j < n; ++j ) for ( dim_t i = 0; i < m; ++i ) bli_zset0s( *(y + i*rs_y + j*cs_y) ); } #endif blis-0.9.0/frame/include/level0/bli_set1s.h000066400000000000000000000036251422157504600204270ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_SET1S_H #define BLIS_SET1S_H #define bli_sset1s( a ) bli_ssets( 1.0F, 0.0F, (a) ) #define bli_dset1s( a ) bli_dsets( 1.0 , 0.0 , (a) ) #define bli_cset1s( a ) bli_csets( 1.0F, 0.0F, (a) ) #define bli_zset1s( a ) bli_zsets( 1.0 , 0.0 , (a) ) #endif blis-0.9.0/frame/include/level0/bli_seti0s.h000066400000000000000000000036071422157504600205770ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_SETI0S_H #define BLIS_SETI0S_H #define bli_sseti0s( a ) bli_ssetis( 0.0F, (a) ) #define bli_dseti0s( a ) bli_dsetis( 0.0 , (a) ) #define bli_cseti0s( a ) bli_csetis( 0.0F, (a) ) #define bli_zseti0s( a ) bli_zsetis( 0.0 , (a) ) #endif blis-0.9.0/frame/include/level0/bli_setis.h000066400000000000000000000053351422157504600205170ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_SETIS_H #define BLIS_SETIS_H // setis // Notes: // - The first char encodes the type of x. // - The second char encodes the type of y. #define bli_sssetis( xi, y ) { ; } #define bli_dssetis( xi, y ) { ; } #define bli_sdsetis( xi, y ) { ; } #define bli_ddsetis( xi, y ) { ; } #ifndef BLIS_ENABLE_C99_COMPLEX #define bli_scsetis( xi, y ) { bli_cimag(y) = (xi); } #define bli_dcsetis( xi, y ) { bli_cimag(y) = (xi); } #define bli_szsetis( xi, y ) { bli_zimag(y) = (xi); } #define bli_dzsetis( xi, y ) { bli_zimag(y) = (xi); } #else // ifdef BLIS_ENABLE_C99_COMPLEX #define bli_scsetis( xi, y ) { (y) = bli_creal(y) + (xi) * (I); } #define bli_dcsetis( xi, y ) { (y) = bli_creal(y) + (xi) * (I); } #define bli_szsetis( xi, y ) { (y) = bli_zreal(y) + (xi) * (I); } #define bli_dzsetis( xi, y ) { (y) = bli_zreal(y) + (xi) * (I); } #endif // BLIS_ENABLE_C99_COMPLEX #define bli_ssetis( xi, y ) bli_sssetis( xi, y ) #define bli_dsetis( xi, y ) bli_ddsetis( xi, y ) #define bli_csetis( xi, y ) bli_scsetis( xi, y ) #define bli_zsetis( xi, y ) bli_dzsetis( xi, y ) #endif blis-0.9.0/frame/include/level0/bli_setrs.h000066400000000000000000000054051422157504600205260ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_SETRS_H #define BLIS_SETRS_H // setrs // Notes: // - The first char encodes the type of x. // - The second char encodes the type of y. #define bli_sssetrs( xr, y ) { (y) = (xr); } #define bli_dssetrs( xr, y ) { (y) = (xr); } #define bli_sdsetrs( xr, y ) { (y) = (xr); } #define bli_ddsetrs( xr, y ) { (y) = (xr); } #ifndef BLIS_ENABLE_C99_COMPLEX #define bli_scsetrs( xr, y ) { bli_creal(y) = (xr); } #define bli_dcsetrs( xr, y ) { bli_creal(y) = (xr); } #define bli_szsetrs( xr, y ) { bli_zreal(y) = (xr); } #define bli_dzsetrs( xr, y ) { bli_zreal(y) = (xr); } #else // ifdef BLIS_ENABLE_C99_COMPLEX #define bli_scsetrs( xr, y ) { (y) = (xr) + bli_cimag(y) * (I); } #define bli_dcsetrs( xr, y ) { (y) = (xr) + bli_cimag(y) * (I); } #define bli_szsetrs( xr, y ) { (y) = (xr) + bli_zimag(y) * (I); } #define bli_dzsetrs( xr, y ) { (y) = (xr) + bli_zimag(y) * (I); } #endif // BLIS_ENABLE_C99_COMPLEX #define bli_ssetrs( xr, y ) bli_sssetrs( xr, y ) #define bli_dsetrs( xr, y ) bli_ddsetrs( xr, y ) #define bli_csetrs( xr, y ) bli_scsetrs( xr, y ) #define bli_zsetrs( xr, y ) bli_dzsetrs( xr, y ) #endif blis-0.9.0/frame/include/level0/bli_sets.h000066400000000000000000000102671422157504600203460ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_SETS_H #define BLIS_SETS_H // sets // Notes: // - The first char encodes the type of x. // - The second char encodes the type of y. #define bli_sssets( xr, xi, y ) { (y) = (xr); } #define bli_dssets( xr, xi, y ) { (y) = (xr); } #define bli_cssets( xr, xi, y ) { (y) = (xr); } #define bli_zssets( xr, xi, y ) { (y) = (xr); } #define bli_issets( xr, xi, y ) { (y) = (xr); } #define bli_sdsets( xr, xi, y ) { (y) = (xr); } #define bli_ddsets( xr, xi, y ) { (y) = (xr); } #define bli_cdsets( xr, xi, y ) { (y) = (xr); } #define bli_zdsets( xr, xi, y ) { (y) = (xr); } #define bli_idsets( xr, xi, y ) { (y) = (xr); } #ifndef BLIS_ENABLE_C99_COMPLEX #define bli_scsets( xr, xi, y ) { bli_creal(y) = (xr); bli_cimag(y) = (xi); } #define bli_dcsets( xr, xi, y ) { bli_creal(y) = (xr); bli_cimag(y) = (xi); } #define bli_ccsets( xr, xi, y ) { bli_creal(y) = (xr); bli_cimag(y) = (xi); } #define bli_zcsets( xr, xi, y ) { bli_creal(y) = (xr); bli_cimag(y) = (xi); } #define bli_icsets( xr, xi, y ) { bli_creal(y) = (xr); bli_cimag(y) = (xi); } #define bli_szsets( xr, xi, y ) { bli_zreal(y) = (xr); bli_zimag(y) = (xi); } #define bli_dzsets( xr, xi, y ) { bli_zreal(y) = (xr); bli_zimag(y) = (xi); } #define bli_czsets( xr, xi, y ) { bli_zreal(y) = (xr); bli_zimag(y) = (xi); } #define bli_zzsets( xr, xi, y ) { bli_zreal(y) = (xr); bli_zimag(y) = (xi); } #define bli_izsets( xr, xi, y ) { bli_zreal(y) = (xr); bli_zimag(y) = (xi); } #else // ifdef BLIS_ENABLE_C99_COMPLEX #define bli_scsets( xr, xi, y ) { (y) = (xr) + (xi) * (I); } #define bli_dcsets( xr, xi, y ) { (y) = (xr) + (xi) * (I); } #define bli_ccsets( xr, xi, y ) { (y) = (xr) + (xi) * (I); } #define bli_zcsets( xr, xi, y ) { (y) = (xr) + (xi) * (I); } #define bli_szsets( xr, xi, y ) { (y) = (xr) + (xi) * (I); } #define bli_dzsets( xr, xi, y ) { (y) = (xr) + (xi) * (I); } #define bli_czsets( xr, xi, y ) { (y) = (xr) + (xi) * (I); } #define bli_zzsets( xr, xi, y ) { (y) = (xr) + (xi) * (I); } #endif // BLIS_ENABLE_C99_COMPLEX #define bli_sisets( xr, xi, y ) { (y) = bli_sreal(xr); } #define bli_disets( xr, xi, y ) { (y) = bli_dreal(xr); } #define bli_cisets( xr, xi, y ) { (y) = bli_creal(xr); } #define bli_zisets( xr, xi, y ) { (y) = bli_zreal(xr); } #define bli_iisets( xr, xi, y ) { (y) = (xr); } #define bli_ssets( xr, xi, y ) bli_sssets( xr, xi, y ) #define bli_dsets( xr, xi, y ) bli_ddsets( xr, xi, y ) #define bli_csets( xr, xi, y ) bli_scsets( xr, xi, y ) #define bli_zsets( xr, xi, y ) bli_dzsets( xr, xi, y ) #define bli_isets( xr, xi, y ) bli_disets( xr, xi, y ) #endif blis-0.9.0/frame/include/level0/bli_sqrt2s.h000066400000000000000000000117211422157504600206220ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_SQRT2S_H #define BLIS_SQRT2S_H // sqrt2s // Notes: // - The first char encodes the type of x. // - The second char encodes the type of a. #ifndef BLIS_ENABLE_C99_COMPLEX #define bli_sssqrt2s( x, a ) bli_ssqrt2ris( bli_sreal(x), bli_simag(x), bli_sreal(a), bli_simag(a) ) #define bli_dssqrt2s( x, a ) bli_ssqrt2ris( bli_dreal(x), bli_dimag(x), bli_sreal(a), bli_simag(a) ) #define bli_cssqrt2s( x, a ) bli_ssqrt2ris( bli_creal(x), bli_cimag(x), bli_sreal(a), bli_simag(a) ) #define bli_zssqrt2s( x, a ) bli_ssqrt2ris( bli_zreal(x), bli_zimag(x), bli_sreal(a), bli_simag(a) ) #define bli_sdsqrt2s( x, a ) bli_dsqrt2ris( bli_sreal(x), bli_simag(x), bli_dreal(a), bli_dimag(a) ) #define bli_ddsqrt2s( x, a ) bli_dsqrt2ris( bli_dreal(x), bli_dimag(x), bli_dreal(a), bli_dimag(a) ) #define bli_cdsqrt2s( x, a ) bli_dsqrt2ris( bli_creal(x), bli_cimag(x), bli_dreal(a), bli_dimag(a) ) #define bli_zdsqrt2s( x, a ) bli_dsqrt2ris( bli_zreal(x), bli_zimag(x), bli_dreal(a), bli_dimag(a) ) #define bli_scsqrt2s( x, a ) bli_scsqrt2ris( bli_sreal(x), bli_simag(x), bli_creal(a), bli_cimag(a) ) #define bli_dcsqrt2s( x, a ) bli_scsqrt2ris( bli_dreal(x), bli_dimag(x), bli_creal(a), bli_cimag(a) ) #define bli_ccsqrt2s( x, a ) bli_csqrt2ris( bli_creal(x), bli_cimag(x), bli_creal(a), bli_cimag(a) ) #define bli_zcsqrt2s( x, a ) bli_csqrt2ris( bli_zreal(x), bli_zimag(x), bli_creal(a), bli_cimag(a) ) #define bli_szsqrt2s( x, a ) bli_dzsqrt2ris( bli_sreal(x), bli_simag(x), bli_zreal(a), bli_zimag(a) ) #define bli_dzsqrt2s( x, a ) bli_dzsqrt2ris( bli_dreal(x), bli_dimag(x), bli_zreal(a), bli_zimag(a) ) #define bli_czsqrt2s( x, a ) bli_zsqrt2ris( bli_creal(x), bli_cimag(x), bli_zreal(a), bli_zimag(a) ) #define bli_zzsqrt2s( x, a ) bli_zsqrt2ris( bli_zreal(x), bli_zimag(x), bli_zreal(a), bli_zimag(a) ) #else // ifdef BLIS_ENABLE_C99_COMPLEX #define bli_sssqrt2s( x, a ) { (a) = ( float ) sqrtf( (x) ) ; } #define bli_dssqrt2s( x, a ) { (a) = ( float ) sqrt ( (x) ) ; } #define bli_cssqrt2s( x, a ) { (a) = ( float )bli_creal( csqrtf( (x) ) ); } #define bli_zssqrt2s( x, a ) { (a) = ( float )bli_zreal( csqrt ( (x) ) ); } #define bli_sdsqrt2s( x, a ) { (a) = ( double ) sqrtf( (x) ) ; } #define bli_ddsqrt2s( x, a ) { (a) = ( double ) sqrt ( (x) ) ; } #define bli_cdsqrt2s( x, a ) { (a) = ( double )bli_creal( csqrtf( (x) ) ); } #define bli_zdsqrt2s( x, a ) { (a) = ( double )bli_zreal( csqrt ( (x) ) ); } #define bli_scsqrt2s( x, a ) { (a) = ( scomplex ) sqrtf( (x) ) ; } #define bli_dcsqrt2s( x, a ) { (a) = ( scomplex ) sqrt ( (x) ) ; } #define bli_ccsqrt2s( x, a ) { (a) = ( scomplex ) csqrtf( (x) ) ; } #define bli_zcsqrt2s( x, a ) { (a) = ( scomplex ) csqrt ( (x) ) ; } #define bli_szsqrt2s( x, a ) { (a) = ( dcomplex ) sqrtf( (x) ) ; } #define bli_dzsqrt2s( x, a ) { (a) = ( dcomplex ) sqrt ( (x) ) ; } #define bli_czsqrt2s( x, a ) { (a) = ( dcomplex ) csqrtf( (x) ) ; } #define bli_zzsqrt2s( x, a ) { (a) = ( dcomplex ) csqrt ( (x) ) ; } #endif // BLIS_ENABLE_C99_COMPLEX #define bli_ssqrt2s( x, a ) bli_sssqrt2s( x, a ) #define bli_dsqrt2s( x, a ) bli_ddsqrt2s( x, a ) #define bli_csqrt2s( x, a ) bli_ccsqrt2s( x, a ) #define bli_zsqrt2s( x, a ) bli_zzsqrt2s( x, a ) #endif blis-0.9.0/frame/include/level0/bli_subjs.h000066400000000000000000000100551422157504600205110ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_SUBJS_H #define BLIS_SUBJS_H // subjs // Notes: // - The first char encodes the type of a. // - The second char encodes the type of y. #define bli_sssubjs( a, y ) bli_ssubjris( bli_sreal(a), bli_simag(a), bli_sreal(y), bli_simag(y) ) #define bli_dssubjs( a, y ) bli_ssubjris( bli_dreal(a), bli_dimag(a), bli_sreal(y), bli_simag(y) ) #define bli_cssubjs( a, y ) bli_ssubjris( bli_creal(a), bli_cimag(a), bli_sreal(y), bli_simag(y) ) #define bli_zssubjs( a, y ) bli_ssubjris( bli_zreal(a), bli_zimag(a), bli_sreal(y), bli_simag(y) ) #define bli_sdsubjs( a, y ) bli_dsubjris( bli_sreal(a), bli_simag(a), bli_dreal(y), bli_dimag(y) ) #define bli_ddsubjs( a, y ) bli_dsubjris( bli_dreal(a), bli_dimag(a), bli_dreal(y), bli_dimag(y) ) #define bli_cdsubjs( a, y ) bli_dsubjris( bli_creal(a), bli_cimag(a), bli_dreal(y), bli_dimag(y) ) #define bli_zdsubjs( a, y ) bli_dsubjris( bli_zreal(a), bli_zimag(a), bli_dreal(y), bli_dimag(y) ) #ifndef BLIS_ENABLE_C99_COMPLEX #define bli_scsubjs( a, y ) bli_csubjris( bli_sreal(a), bli_simag(a), bli_creal(y), bli_cimag(y) ) #define bli_dcsubjs( a, y ) bli_csubjris( bli_dreal(a), bli_dimag(a), bli_creal(y), bli_cimag(y) ) #define bli_ccsubjs( a, y ) bli_csubjris( bli_creal(a), bli_cimag(a), bli_creal(y), bli_cimag(y) ) #define bli_zcsubjs( a, y ) bli_csubjris( bli_zreal(a), bli_zimag(a), bli_creal(y), bli_cimag(y) ) #define bli_szsubjs( a, y ) bli_zsubjris( bli_sreal(a), bli_simag(a), bli_zreal(y), bli_zimag(y) ) #define bli_dzsubjs( a, y ) bli_zsubjris( bli_dreal(a), bli_dimag(a), bli_zreal(y), bli_zimag(y) ) #define bli_czsubjs( a, y ) bli_zsubjris( bli_creal(a), bli_cimag(a), bli_zreal(y), bli_zimag(y) ) #define bli_zzsubjs( a, y ) bli_zsubjris( bli_zreal(a), bli_zimag(a), bli_zreal(y), bli_zimag(y) ) #else // ifdef BLIS_ENABLE_C99_COMPLEX #define bli_scsubjs( a, y ) { (y) -= (a); } #define bli_dcsubjs( a, y ) { (y) -= (a); } #define bli_ccsubjs( a, y ) { (y) -= conjf(a); } #define bli_zcsubjs( a, y ) { (y) -= conj (a); } #define bli_szsubjs( a, y ) { (y) -= (a); } #define bli_dzsubjs( a, y ) { (y) -= (a); } #define bli_czsubjs( a, y ) { (y) -= conjf(a); } #define bli_zzsubjs( a, y ) { (y) -= conj (a); } #endif // BLIS_ENABLE_C99_COMPLEX #define bli_ssubjs( a, y ) bli_sssubjs( a, y ) #define bli_dsubjs( a, y ) bli_ddsubjs( a, y ) #define bli_csubjs( a, y ) bli_ccsubjs( a, y ) #define bli_zsubjs( a, y ) bli_zzsubjs( a, y ) #endif blis-0.9.0/frame/include/level0/bli_subs.h000066400000000000000000000077221422157504600203460ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_SUBS_H #define BLIS_SUBS_H // subs // Notes: // - The first char encodes the type of a. // - The second char encodes the type of y. #define bli_sssubs( a, y ) bli_ssubris( bli_sreal(a), bli_simag(a), bli_sreal(y), bli_simag(y) ) #define bli_dssubs( a, y ) bli_ssubris( bli_dreal(a), bli_dimag(a), bli_sreal(y), bli_simag(y) ) #define bli_cssubs( a, y ) bli_ssubris( bli_creal(a), bli_cimag(a), bli_sreal(y), bli_simag(y) ) #define bli_zssubs( a, y ) bli_ssubris( bli_zreal(a), bli_zimag(a), bli_sreal(y), bli_simag(y) ) #define bli_sdsubs( a, y ) bli_dsubris( bli_sreal(a), bli_simag(a), bli_dreal(y), bli_dimag(y) ) #define bli_ddsubs( a, y ) bli_dsubris( bli_dreal(a), bli_dimag(a), bli_dreal(y), bli_dimag(y) ) #define bli_cdsubs( a, y ) bli_dsubris( bli_creal(a), bli_cimag(a), bli_dreal(y), bli_dimag(y) ) #define bli_zdsubs( a, y ) bli_dsubris( bli_zreal(a), bli_zimag(a), bli_dreal(y), bli_dimag(y) ) #ifndef BLIS_ENABLE_C99_COMPLEX #define bli_scsubs( a, y ) bli_csubris( bli_sreal(a), bli_simag(a), bli_creal(y), bli_cimag(y) ) #define bli_dcsubs( a, y ) bli_csubris( bli_dreal(a), bli_dimag(a), bli_creal(y), bli_cimag(y) ) #define bli_ccsubs( a, y ) bli_csubris( bli_creal(a), bli_cimag(a), bli_creal(y), bli_cimag(y) ) #define bli_zcsubs( a, y ) bli_csubris( bli_zreal(a), bli_zimag(a), bli_creal(y), bli_cimag(y) ) #define bli_szsubs( a, y ) bli_zsubris( bli_sreal(a), bli_simag(a), bli_zreal(y), bli_zimag(y) ) #define bli_dzsubs( a, y ) bli_zsubris( bli_dreal(a), bli_dimag(a), bli_zreal(y), bli_zimag(y) ) #define bli_czsubs( a, y ) bli_zsubris( bli_creal(a), bli_cimag(a), bli_zreal(y), bli_zimag(y) ) #define bli_zzsubs( a, y ) bli_zsubris( bli_zreal(a), bli_zimag(a), bli_zreal(y), bli_zimag(y) ) #else // ifdef BLIS_ENABLE_C99_COMPLEX #define bli_scsubs( a, y ) { (y) -= (a); } #define bli_dcsubs( a, y ) { (y) -= (a); } #define bli_ccsubs( a, y ) { (y) -= (a); } #define bli_zcsubs( a, y ) { (y) -= (a); } #define bli_szsubs( a, y ) { (y) -= (a); } #define bli_dzsubs( a, y ) { (y) -= (a); } #define bli_czsubs( a, y ) { (y) -= (a); } #define bli_zzsubs( a, y ) { (y) -= (a); } #endif // BLIS_ENABLE_C99_COMPLEX #define bli_ssubs( a, y ) bli_sssubs( a, y ) #define bli_dsubs( a, y ) bli_ddsubs( a, y ) #define bli_csubs( a, y ) bli_ccsubs( a, y ) #define bli_zsubs( a, y ) bli_zzsubs( a, y ) #endif blis-0.9.0/frame/include/level0/bli_swaps.h000066400000000000000000000101421422157504600205150ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_SWAPS_H #define BLIS_SWAPS_H // swaps // Notes: // - The first char encodes the type of x. // - The second char encodes the type of y. #define bli_ssswaps( x, y ) \ { \ float w; \ bli_sscopys( (y), (w) ); \ bli_sscopys( (x), (y) ); \ bli_sscopys( (w), (x) ); \ } #define bli_dsswaps( x, y ) \ { \ double w; \ bli_sdcopys( (y), (w) ); \ bli_dscopys( (x), (y) ); \ bli_ddcopys( (w), (x) ); \ } #define bli_csswaps( x, y ) \ { \ scomplex w; \ bli_sccopys( (y), (w) ); \ bli_cscopys( (x), (y) ); \ bli_cccopys( (w), (x) ); \ } #define bli_zsswaps( x, y ) \ { \ dcomplex w; \ bli_szcopys( (y), (w) ); \ bli_zscopys( (x), (y) ); \ bli_zzcopys( (w), (x) ); \ } #define bli_sdswaps( x, y ) \ { \ float w; \ bli_dscopys( (y), (w) ); \ bli_sdcopys( (x), (y) ); \ bli_sscopys( (w), (x) ); \ } #define bli_ddswaps( x, y ) \ { \ double w; \ bli_ddcopys( (y), (w) ); \ bli_ddcopys( (x), (y) ); \ bli_ddcopys( (w), (x) ); \ } #define bli_cdswaps( x, y ) \ { \ scomplex w; \ bli_dccopys( (y), (w) ); \ bli_cdcopys( (x), (y) ); \ bli_cccopys( (w), (x) ); \ } #define bli_zdswaps( x, y ) \ { \ dcomplex w; \ bli_dzcopys( (y), (w) ); \ bli_zdcopys( (x), (y) ); \ bli_zzcopys( (w), (x) ); \ } #define bli_scswaps( x, y ) \ { \ float w; \ bli_cscopys( (y), (w) ); \ bli_sccopys( (x), (y) ); \ bli_sscopys( (w), (x) ); \ } #define bli_dcswaps( x, y ) \ { \ double w; \ bli_cdcopys( (y), (w) ); \ bli_dccopys( (x), (y) ); \ bli_ddcopys( (w), (x) ); \ } #define bli_ccswaps( x, y ) \ { \ scomplex w; \ bli_cccopys( (y), (w) ); \ bli_cccopys( (x), (y) ); \ bli_cccopys( (w), (x) ); \ } #define bli_zcswaps( x, y ) \ { \ dcomplex w; \ bli_czcopys( (y), (w) ); \ bli_zccopys( (x), (y) ); \ bli_zzcopys( (w), (x) ); \ } #define bli_szswaps( x, y ) \ { \ float w; \ bli_zscopys( (y), (w) ); \ bli_szcopys( (x), (y) ); \ bli_sscopys( (w), (x) ); \ } #define bli_dzswaps( x, y ) \ { \ double w; \ bli_zdcopys( (y), (w) ); \ bli_dzcopys( (x), (y) ); \ bli_ddcopys( (w), (x) ); \ } #define bli_czswaps( x, y ) \ { \ scomplex w; \ bli_zccopys( (y), (w) ); \ bli_czcopys( (x), (y) ); \ bli_cccopys( (w), (x) ); \ } #define bli_zzswaps( x, y ) \ { \ dcomplex w; \ bli_zzcopys( (y), (w) ); \ bli_zzcopys( (x), (y) ); \ bli_zzcopys( (w), (x) ); \ } #define bli_sswaps( x, y ) bli_ssswaps( x, y ) #define bli_dswaps( x, y ) bli_ddswaps( x, y ) #define bli_cswaps( x, y ) bli_ccswaps( x, y ) #define bli_zswaps( x, y ) bli_zzswaps( x, y ) #endif blis-0.9.0/frame/include/level0/bli_xpbyjs.h000066400000000000000000000320151422157504600207020ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_XPBYJS_H #define BLIS_XPBYJS_H // xpbyjs // Notes: // - The first char encodes the type of x. // - The second char encodes the type of b. // - The third char encodes the type of y. // -- (xby) = (??s) ------------------------------------------------------------ #define bli_sssxpbyjs( x, b, y ) bli_rxxpbyjris( bli_sreal(x), bli_simag(x), bli_sreal(b), bli_simag(b), bli_sreal(y), bli_simag(y) ) #define bli_dssxpbyjs( x, b, y ) bli_rxxpbyjris( bli_dreal(x), bli_dimag(x), bli_sreal(b), bli_simag(b), bli_sreal(y), bli_simag(y) ) #define bli_cssxpbyjs( x, b, y ) bli_rxxpbyjris( bli_creal(x), bli_cimag(x), bli_sreal(b), bli_simag(b), bli_sreal(y), bli_simag(y) ) #define bli_zssxpbyjs( x, b, y ) bli_rxxpbyjris( bli_zreal(x), bli_zimag(x), bli_sreal(b), bli_simag(b), bli_sreal(y), bli_simag(y) ) #define bli_sdsxpbyjs( x, b, y ) bli_rxxpbyjris( bli_sreal(x), bli_simag(x), bli_dreal(b), bli_dimag(b), bli_sreal(y), bli_simag(y) ) #define bli_ddsxpbyjs( x, b, y ) bli_rxxpbyjris( bli_dreal(x), bli_dimag(x), bli_dreal(b), bli_dimag(b), bli_sreal(y), bli_simag(y) ) #define bli_cdsxpbyjs( x, b, y ) bli_rxxpbyjris( bli_creal(x), bli_cimag(x), bli_dreal(b), bli_dimag(b), bli_sreal(y), bli_simag(y) ) #define bli_zdsxpbyjs( x, b, y ) bli_rxxpbyjris( bli_zreal(x), bli_zimag(x), bli_dreal(b), bli_dimag(b), bli_sreal(y), bli_simag(y) ) #define bli_scsxpbyjs( x, b, y ) bli_rxxpbyjris( bli_sreal(x), bli_simag(x), bli_creal(b), bli_cimag(b), bli_sreal(y), bli_simag(y) ) #define bli_dcsxpbyjs( x, b, y ) bli_rxxpbyjris( bli_dreal(x), bli_dimag(x), bli_creal(b), bli_cimag(b), bli_sreal(y), bli_simag(y) ) #define bli_ccsxpbyjs( x, b, y ) bli_rxxpbyjris( bli_creal(x), bli_cimag(x), bli_creal(b), bli_cimag(b), bli_sreal(y), bli_simag(y) ) #define bli_zcsxpbyjs( x, b, y ) bli_rxxpbyjris( bli_zreal(x), bli_zimag(x), bli_creal(b), bli_cimag(b), bli_sreal(y), bli_simag(y) ) #define bli_szsxpbyjs( x, b, y ) bli_rxxpbyjris( bli_sreal(x), bli_simag(x), bli_zreal(b), bli_zimag(b), bli_sreal(y), bli_simag(y) ) #define bli_dzsxpbyjs( x, b, y ) bli_rxxpbyjris( bli_dreal(x), bli_dimag(x), bli_zreal(b), bli_zimag(b), bli_sreal(y), bli_simag(y) ) #define bli_czsxpbyjs( x, b, y ) bli_rxxpbyjris( bli_creal(x), bli_cimag(x), bli_zreal(b), bli_zimag(b), bli_sreal(y), bli_simag(y) ) #define bli_zzsxpbyjs( x, b, y ) bli_rxxpbyjris( bli_zreal(x), bli_zimag(x), bli_zreal(b), bli_zimag(b), bli_sreal(y), bli_simag(y) ) // -- (xby) = (??d) ------------------------------------------------------------ #define bli_ssdxpbyjs( x, b, y ) bli_rxxpbyjris( bli_sreal(x), bli_simag(x), bli_sreal(b), bli_simag(b), bli_dreal(y), bli_dimag(y) ) #define bli_dsdxpbyjs( x, b, y ) bli_rxxpbyjris( bli_dreal(x), bli_dimag(x), bli_sreal(b), bli_simag(b), bli_dreal(y), bli_dimag(y) ) #define bli_csdxpbyjs( x, b, y ) bli_rxxpbyjris( bli_creal(x), bli_cimag(x), bli_sreal(b), bli_simag(b), bli_dreal(y), bli_dimag(y) ) #define bli_zsdxpbyjs( x, b, y ) bli_rxxpbyjris( bli_zreal(x), bli_zimag(x), bli_sreal(b), bli_simag(b), bli_dreal(y), bli_dimag(y) ) #define bli_sddxpbyjs( x, b, y ) bli_rxxpbyjris( bli_sreal(x), bli_simag(x), bli_dreal(b), bli_dimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_dddxpbyjs( x, b, y ) bli_rxxpbyjris( bli_dreal(x), bli_dimag(x), bli_dreal(b), bli_dimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_cddxpbyjs( x, b, y ) bli_rxxpbyjris( bli_creal(x), bli_cimag(x), bli_dreal(b), bli_dimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_zddxpbyjs( x, b, y ) bli_rxxpbyjris( bli_zreal(x), bli_zimag(x), bli_dreal(b), bli_dimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_scdxpbyjs( x, b, y ) bli_rxxpbyjris( bli_sreal(x), bli_simag(x), bli_creal(b), bli_cimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_dcdxpbyjs( x, b, y ) bli_rxxpbyjris( bli_dreal(x), bli_dimag(x), bli_creal(b), bli_cimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_ccdxpbyjs( x, b, y ) bli_rxxpbyjris( bli_creal(x), bli_cimag(x), bli_creal(b), bli_cimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_zcdxpbyjs( x, b, y ) bli_rxxpbyjris( bli_zreal(x), bli_zimag(x), bli_creal(b), bli_cimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_szdxpbyjs( x, b, y ) bli_rxxpbyjris( bli_sreal(x), bli_simag(x), bli_zreal(b), bli_zimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_dzdxpbyjs( x, b, y ) bli_rxxpbyjris( bli_dreal(x), bli_dimag(x), bli_zreal(b), bli_zimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_czdxpbyjs( x, b, y ) bli_rxxpbyjris( bli_creal(x), bli_cimag(x), bli_zreal(b), bli_zimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_zzdxpbyjs( x, b, y ) bli_rxxpbyjris( bli_zreal(x), bli_zimag(x), bli_zreal(b), bli_zimag(b), bli_dreal(y), bli_dimag(y) ) #ifndef BLIS_ENABLE_C99_COMPLEX // -- (xby) = (??c) ------------------------------------------------------------ #define bli_sscxpbyjs( x, b, y ) bli_rxxpbyjris( bli_sreal(x), bli_simag(x), bli_sreal(b), bli_simag(b), bli_creal(y), bli_cimag(y) ) #define bli_dscxpbyjs( x, b, y ) bli_rxxpbyjris( bli_dreal(x), bli_dimag(x), bli_sreal(b), bli_simag(b), bli_creal(y), bli_cimag(y) ) #define bli_cscxpbyjs( x, b, y ) bli_crxpbyjris( bli_creal(x), bli_cimag(x), bli_sreal(b), bli_simag(b), bli_creal(y), bli_cimag(y) ) #define bli_zscxpbyjs( x, b, y ) bli_crxpbyjris( bli_zreal(x), bli_zimag(x), bli_sreal(b), bli_simag(b), bli_creal(y), bli_cimag(y) ) #define bli_sdcxpbyjs( x, b, y ) bli_rxxpbyjris( bli_sreal(x), bli_simag(x), bli_dreal(b), bli_dimag(b), bli_creal(y), bli_cimag(y) ) #define bli_ddcxpbyjs( x, b, y ) bli_rxxpbyjris( bli_dreal(x), bli_dimag(x), bli_dreal(b), bli_dimag(b), bli_creal(y), bli_cimag(y) ) #define bli_cdcxpbyjs( x, b, y ) bli_crxpbyjris( bli_creal(x), bli_cimag(x), bli_dreal(b), bli_dimag(b), bli_creal(y), bli_cimag(y) ) #define bli_zdcxpbyjs( x, b, y ) bli_crxpbyjris( bli_zreal(x), bli_zimag(x), bli_dreal(b), bli_dimag(b), bli_creal(y), bli_cimag(y) ) #define bli_sccxpbyjs( x, b, y ) bli_cxxpbyjris( bli_sreal(x), bli_simag(x), bli_creal(b), bli_cimag(b), bli_creal(y), bli_cimag(y) ) #define bli_dccxpbyjs( x, b, y ) bli_cxxpbyjris( bli_dreal(x), bli_dimag(x), bli_creal(b), bli_cimag(b), bli_creal(y), bli_cimag(y) ) #define bli_cccxpbyjs( x, b, y ) bli_cxxpbyjris( bli_creal(x), bli_cimag(x), bli_creal(b), bli_cimag(b), bli_creal(y), bli_cimag(y) ) #define bli_zccxpbyjs( x, b, y ) bli_cxxpbyjris( bli_zreal(x), bli_zimag(x), bli_creal(b), bli_cimag(b), bli_creal(y), bli_cimag(y) ) #define bli_szcxpbyjs( x, b, y ) bli_cxxpbyjris( bli_sreal(x), bli_simag(x), bli_zreal(b), bli_zimag(b), bli_creal(y), bli_cimag(y) ) #define bli_dzcxpbyjs( x, b, y ) bli_cxxpbyjris( bli_dreal(x), bli_dimag(x), bli_zreal(b), bli_zimag(b), bli_creal(y), bli_cimag(y) ) #define bli_czcxpbyjs( x, b, y ) bli_cxxpbyjris( bli_creal(x), bli_cimag(x), bli_zreal(b), bli_zimag(b), bli_creal(y), bli_cimag(y) ) #define bli_zzcxpbyjs( x, b, y ) bli_cxxpbyjris( bli_zreal(x), bli_zimag(x), bli_zreal(b), bli_zimag(b), bli_creal(y), bli_cimag(y) ) // -- (xby) = (??z) ------------------------------------------------------------ #define bli_sszxpbyjs( x, b, y ) bli_rxxpbyjris( bli_sreal(x), bli_simag(x), bli_sreal(b), bli_simag(b), bli_zreal(y), bli_zimag(y) ) #define bli_dszxpbyjs( x, b, y ) bli_rxxpbyjris( bli_dreal(x), bli_dimag(x), bli_sreal(b), bli_simag(b), bli_zreal(y), bli_zimag(y) ) #define bli_cszxpbyjs( x, b, y ) bli_crxpbyjris( bli_creal(x), bli_cimag(x), bli_sreal(b), bli_simag(b), bli_zreal(y), bli_zimag(y) ) #define bli_zszxpbyjs( x, b, y ) bli_crxpbyjris( bli_zreal(x), bli_zimag(x), bli_sreal(b), bli_simag(b), bli_zreal(y), bli_zimag(y) ) #define bli_sdzxpbyjs( x, b, y ) bli_rxxpbyjris( bli_sreal(x), bli_simag(x), bli_dreal(b), bli_dimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_ddzxpbyjs( x, b, y ) bli_rxxpbyjris( bli_dreal(x), bli_dimag(x), bli_dreal(b), bli_dimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_cdzxpbyjs( x, b, y ) bli_crxpbyjris( bli_creal(x), bli_cimag(x), bli_dreal(b), bli_dimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_zdzxpbyjs( x, b, y ) bli_crxpbyjris( bli_zreal(x), bli_zimag(x), bli_dreal(b), bli_dimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_sczxpbyjs( x, b, y ) bli_cxxpbyjris( bli_sreal(x), bli_simag(x), bli_creal(b), bli_cimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_dczxpbyjs( x, b, y ) bli_cxxpbyjris( bli_dreal(x), bli_dimag(x), bli_creal(b), bli_cimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_cczxpbyjs( x, b, y ) bli_cxxpbyjris( bli_creal(x), bli_cimag(x), bli_creal(b), bli_cimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_zczxpbyjs( x, b, y ) bli_cxxpbyjris( bli_zreal(x), bli_zimag(x), bli_creal(b), bli_cimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_szzxpbyjs( x, b, y ) bli_cxxpbyjris( bli_sreal(x), bli_simag(x), bli_zreal(b), bli_zimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_dzzxpbyjs( x, b, y ) bli_cxxpbyjris( bli_dreal(x), bli_dimag(x), bli_zreal(b), bli_zimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_czzxpbyjs( x, b, y ) bli_cxxpbyjris( bli_creal(x), bli_cimag(x), bli_zreal(b), bli_zimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_zzzxpbyjs( x, b, y ) bli_cxxpbyjris( bli_zreal(x), bli_zimag(x), bli_zreal(b), bli_zimag(b), bli_zreal(y), bli_zimag(y) ) #else // ifdef BLIS_ENABLE_C99_COMPLEX // -- (xby) = (??c) ------------------------------------------------------------ #define bli_sscxpbyjs( x, b, y ) { (y) = (x) + (b) * (y); } #define bli_dscxpbyjs( x, b, y ) { (y) = (x) + (b) * (y); } #define bli_cscxpbyjs( x, b, y ) { (y) = (x) + (b) * (y); } #define bli_zscxpbyjs( x, b, y ) { (y) = (x) + (b) * (y); } #define bli_sdcxpbyjs( x, b, y ) { (y) = (x) + (b) * (y); } #define bli_ddcxpbyjs( x, b, y ) { (y) = (x) + (b) * (y); } #define bli_cdcxpbyjs( x, b, y ) { (y) = (x) + (b) * (y); } #define bli_zdcxpbyjs( x, b, y ) { (y) = (x) + (b) * (y); } #define bli_sccxpbyjs( x, b, y ) { (y) = (x) + (b) * (y); } #define bli_dccxpbyjs( x, b, y ) { (y) = (x) + (b) * (y); } #define bli_cccxpbyjs( x, b, y ) { (y) = (x) + (b) * (y); } #define bli_zccxpbyjs( x, b, y ) { (y) = (x) + (b) * (y); } #define bli_szcxpbyjs( x, b, y ) { (y) = (x) + (b) * (y); } #define bli_dzcxpbyjs( x, b, y ) { (y) = (x) + (b) * (y); } #define bli_czcxpbyjs( x, b, y ) { (y) = (x) + (b) * (y); } #define bli_zzcxpbyjs( x, b, y ) { (y) = (x) + (b) * (y); } // -- (xby) = (??z) ------------------------------------------------------------ #define bli_sszxpbyjs( x, b, y ) { (y) = (x) + (b) * (y); } #define bli_dszxpbyjs( x, b, y ) { (y) = (x) + (b) * (y); } #define bli_cszxpbyjs( x, b, y ) { (y) = (x) + (b) * (y); } #define bli_zszxpbyjs( x, b, y ) { (y) = (x) + (b) * (y); } #define bli_sdzxpbyjs( x, b, y ) { (y) = (x) + (b) * (y); } #define bli_ddzxpbyjs( x, b, y ) { (y) = (x) + (b) * (y); } #define bli_cdzxpbyjs( x, b, y ) { (y) = (x) + (b) * (y); } #define bli_zdzxpbyjs( x, b, y ) { (y) = (x) + (b) * (y); } #define bli_sczxpbyjs( x, b, y ) { (y) = (x) + (b) * (y); } #define bli_dczxpbyjs( x, b, y ) { (y) = (x) + (b) * (y); } #define bli_cczxpbyjs( x, b, y ) { (y) = (x) + (b) * (y); } #define bli_zczxpbyjs( x, b, y ) { (y) = (x) + (b) * (y); } #define bli_szzxpbyjs( x, b, y ) { (y) = (x) + (b) * (y); } #define bli_dzzxpbyjs( x, b, y ) { (y) = (x) + (b) * (y); } #define bli_czzxpbyjs( x, b, y ) { (y) = (x) + (b) * (y); } #define bli_zzzxpbyjs( x, b, y ) { (y) = (x) + (b) * (y); } #endif // BLIS_ENABLE_C99_COMPLEX #define bli_sxpbyjs( x, b, y ) bli_sssxpbyjs( x, b, y ) #define bli_dxpbyjs( x, b, y ) bli_dddxpbyjs( x, b, y ) #define bli_cxpbyjs( x, b, y ) bli_cccxpbyjs( x, b, y ) #define bli_zxpbyjs( x, b, y ) bli_zzzxpbyjs( x, b, y ) #endif blis-0.9.0/frame/include/level0/bli_xpbys.h000066400000000000000000000315421422157504600205340ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_XPBYS_H #define BLIS_XPBYS_H // xpbys // Notes: // - The first char encodes the type of x. // - The second char encodes the type of b. // - The third char encodes the type of y. // -- (xby) = (??s) ------------------------------------------------------------ #define bli_sssxpbys( x, b, y ) bli_rxxpbyris( bli_sreal(x), bli_simag(x), bli_sreal(b), bli_simag(b), bli_sreal(y), bli_simag(y) ) #define bli_dssxpbys( x, b, y ) bli_rxxpbyris( bli_dreal(x), bli_dimag(x), bli_sreal(b), bli_simag(b), bli_sreal(y), bli_simag(y) ) #define bli_cssxpbys( x, b, y ) bli_rxxpbyris( bli_creal(x), bli_cimag(x), bli_sreal(b), bli_simag(b), bli_sreal(y), bli_simag(y) ) #define bli_zssxpbys( x, b, y ) bli_rxxpbyris( bli_zreal(x), bli_zimag(x), bli_sreal(b), bli_simag(b), bli_sreal(y), bli_simag(y) ) #define bli_sdsxpbys( x, b, y ) bli_rxxpbyris( bli_sreal(x), bli_simag(x), bli_dreal(b), bli_dimag(b), bli_sreal(y), bli_simag(y) ) #define bli_ddsxpbys( x, b, y ) bli_rxxpbyris( bli_dreal(x), bli_dimag(x), bli_dreal(b), bli_dimag(b), bli_sreal(y), bli_simag(y) ) #define bli_cdsxpbys( x, b, y ) bli_rxxpbyris( bli_creal(x), bli_cimag(x), bli_dreal(b), bli_dimag(b), bli_sreal(y), bli_simag(y) ) #define bli_zdsxpbys( x, b, y ) bli_rxxpbyris( bli_zreal(x), bli_zimag(x), bli_dreal(b), bli_dimag(b), bli_sreal(y), bli_simag(y) ) #define bli_scsxpbys( x, b, y ) bli_rxxpbyris( bli_sreal(x), bli_simag(x), bli_creal(b), bli_cimag(b), bli_sreal(y), bli_simag(y) ) #define bli_dcsxpbys( x, b, y ) bli_rxxpbyris( bli_dreal(x), bli_dimag(x), bli_creal(b), bli_cimag(b), bli_sreal(y), bli_simag(y) ) #define bli_ccsxpbys( x, b, y ) bli_rxxpbyris( bli_creal(x), bli_cimag(x), bli_creal(b), bli_cimag(b), bli_sreal(y), bli_simag(y) ) #define bli_zcsxpbys( x, b, y ) bli_rxxpbyris( bli_zreal(x), bli_zimag(x), bli_creal(b), bli_cimag(b), bli_sreal(y), bli_simag(y) ) #define bli_szsxpbys( x, b, y ) bli_rxxpbyris( bli_sreal(x), bli_simag(x), bli_zreal(b), bli_zimag(b), bli_sreal(y), bli_simag(y) ) #define bli_dzsxpbys( x, b, y ) bli_rxxpbyris( bli_dreal(x), bli_dimag(x), bli_zreal(b), bli_zimag(b), bli_sreal(y), bli_simag(y) ) #define bli_czsxpbys( x, b, y ) bli_rxxpbyris( bli_creal(x), bli_cimag(x), bli_zreal(b), bli_zimag(b), bli_sreal(y), bli_simag(y) ) #define bli_zzsxpbys( x, b, y ) bli_rxxpbyris( bli_zreal(x), bli_zimag(x), bli_zreal(b), bli_zimag(b), bli_sreal(y), bli_simag(y) ) // -- (xby) = (??d) ------------------------------------------------------------ #define bli_ssdxpbys( x, b, y ) bli_rxxpbyris( bli_sreal(x), bli_simag(x), bli_sreal(b), bli_simag(b), bli_dreal(y), bli_dimag(y) ) #define bli_dsdxpbys( x, b, y ) bli_rxxpbyris( bli_dreal(x), bli_dimag(x), bli_sreal(b), bli_simag(b), bli_dreal(y), bli_dimag(y) ) #define bli_csdxpbys( x, b, y ) bli_rxxpbyris( bli_creal(x), bli_cimag(x), bli_sreal(b), bli_simag(b), bli_dreal(y), bli_dimag(y) ) #define bli_zsdxpbys( x, b, y ) bli_rxxpbyris( bli_zreal(x), bli_zimag(x), bli_sreal(b), bli_simag(b), bli_dreal(y), bli_dimag(y) ) #define bli_sddxpbys( x, b, y ) bli_rxxpbyris( bli_sreal(x), bli_simag(x), bli_dreal(b), bli_dimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_dddxpbys( x, b, y ) bli_rxxpbyris( bli_dreal(x), bli_dimag(x), bli_dreal(b), bli_dimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_cddxpbys( x, b, y ) bli_rxxpbyris( bli_creal(x), bli_cimag(x), bli_dreal(b), bli_dimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_zddxpbys( x, b, y ) bli_rxxpbyris( bli_zreal(x), bli_zimag(x), bli_dreal(b), bli_dimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_scdxpbys( x, b, y ) bli_rxxpbyris( bli_sreal(x), bli_simag(x), bli_creal(b), bli_cimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_dcdxpbys( x, b, y ) bli_rxxpbyris( bli_dreal(x), bli_dimag(x), bli_creal(b), bli_cimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_ccdxpbys( x, b, y ) bli_rxxpbyris( bli_creal(x), bli_cimag(x), bli_creal(b), bli_cimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_zcdxpbys( x, b, y ) bli_rxxpbyris( bli_zreal(x), bli_zimag(x), bli_creal(b), bli_cimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_szdxpbys( x, b, y ) bli_rxxpbyris( bli_sreal(x), bli_simag(x), bli_zreal(b), bli_zimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_dzdxpbys( x, b, y ) bli_rxxpbyris( bli_dreal(x), bli_dimag(x), bli_zreal(b), bli_zimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_czdxpbys( x, b, y ) bli_rxxpbyris( bli_creal(x), bli_cimag(x), bli_zreal(b), bli_zimag(b), bli_dreal(y), bli_dimag(y) ) #define bli_zzdxpbys( x, b, y ) bli_rxxpbyris( bli_zreal(x), bli_zimag(x), bli_zreal(b), bli_zimag(b), bli_dreal(y), bli_dimag(y) ) #ifndef BLIS_ENABLE_C99_COMPLEX // -- (xby) = (??c) ------------------------------------------------------------ #define bli_sscxpbys( x, b, y ) bli_rxxpbyris( bli_sreal(x), bli_simag(x), bli_sreal(b), bli_simag(b), bli_creal(y), bli_cimag(y) ) #define bli_dscxpbys( x, b, y ) bli_rxxpbyris( bli_dreal(x), bli_dimag(x), bli_sreal(b), bli_simag(b), bli_creal(y), bli_cimag(y) ) #define bli_cscxpbys( x, b, y ) bli_crxpbyris( bli_creal(x), bli_cimag(x), bli_sreal(b), bli_simag(b), bli_creal(y), bli_cimag(y) ) #define bli_zscxpbys( x, b, y ) bli_crxpbyris( bli_zreal(x), bli_zimag(x), bli_sreal(b), bli_simag(b), bli_creal(y), bli_cimag(y) ) #define bli_sdcxpbys( x, b, y ) bli_rxxpbyris( bli_sreal(x), bli_simag(x), bli_dreal(b), bli_dimag(b), bli_creal(y), bli_cimag(y) ) #define bli_ddcxpbys( x, b, y ) bli_rxxpbyris( bli_dreal(x), bli_dimag(x), bli_dreal(b), bli_dimag(b), bli_creal(y), bli_cimag(y) ) #define bli_cdcxpbys( x, b, y ) bli_crxpbyris( bli_creal(x), bli_cimag(x), bli_dreal(b), bli_dimag(b), bli_creal(y), bli_cimag(y) ) #define bli_zdcxpbys( x, b, y ) bli_crxpbyris( bli_zreal(x), bli_zimag(x), bli_dreal(b), bli_dimag(b), bli_creal(y), bli_cimag(y) ) #define bli_sccxpbys( x, b, y ) bli_cxxpbyris( bli_sreal(x), bli_simag(x), bli_creal(b), bli_cimag(b), bli_creal(y), bli_cimag(y) ) #define bli_dccxpbys( x, b, y ) bli_cxxpbyris( bli_dreal(x), bli_dimag(x), bli_creal(b), bli_cimag(b), bli_creal(y), bli_cimag(y) ) #define bli_cccxpbys( x, b, y ) bli_cxxpbyris( bli_creal(x), bli_cimag(x), bli_creal(b), bli_cimag(b), bli_creal(y), bli_cimag(y) ) #define bli_zccxpbys( x, b, y ) bli_cxxpbyris( bli_zreal(x), bli_zimag(x), bli_creal(b), bli_cimag(b), bli_creal(y), bli_cimag(y) ) #define bli_szcxpbys( x, b, y ) bli_cxxpbyris( bli_sreal(x), bli_simag(x), bli_zreal(b), bli_zimag(b), bli_creal(y), bli_cimag(y) ) #define bli_dzcxpbys( x, b, y ) bli_cxxpbyris( bli_dreal(x), bli_dimag(x), bli_zreal(b), bli_zimag(b), bli_creal(y), bli_cimag(y) ) #define bli_czcxpbys( x, b, y ) bli_cxxpbyris( bli_creal(x), bli_cimag(x), bli_zreal(b), bli_zimag(b), bli_creal(y), bli_cimag(y) ) #define bli_zzcxpbys( x, b, y ) bli_cxxpbyris( bli_zreal(x), bli_zimag(x), bli_zreal(b), bli_zimag(b), bli_creal(y), bli_cimag(y) ) // -- (xby) = (??z) ------------------------------------------------------------ #define bli_sszxpbys( x, b, y ) bli_rxxpbyris( bli_sreal(x), bli_simag(x), bli_sreal(b), bli_simag(b), bli_zreal(y), bli_zimag(y) ) #define bli_dszxpbys( x, b, y ) bli_rxxpbyris( bli_dreal(x), bli_dimag(x), bli_sreal(b), bli_simag(b), bli_zreal(y), bli_zimag(y) ) #define bli_cszxpbys( x, b, y ) bli_crxpbyris( bli_creal(x), bli_cimag(x), bli_sreal(b), bli_simag(b), bli_zreal(y), bli_zimag(y) ) #define bli_zszxpbys( x, b, y ) bli_crxpbyris( bli_zreal(x), bli_zimag(x), bli_sreal(b), bli_simag(b), bli_zreal(y), bli_zimag(y) ) #define bli_sdzxpbys( x, b, y ) bli_rxxpbyris( bli_sreal(x), bli_simag(x), bli_dreal(b), bli_dimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_ddzxpbys( x, b, y ) bli_rxxpbyris( bli_dreal(x), bli_dimag(x), bli_dreal(b), bli_dimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_cdzxpbys( x, b, y ) bli_crxpbyris( bli_creal(x), bli_cimag(x), bli_dreal(b), bli_dimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_zdzxpbys( x, b, y ) bli_crxpbyris( bli_zreal(x), bli_zimag(x), bli_dreal(b), bli_dimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_sczxpbys( x, b, y ) bli_cxxpbyris( bli_sreal(x), bli_simag(x), bli_creal(b), bli_cimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_dczxpbys( x, b, y ) bli_cxxpbyris( bli_dreal(x), bli_dimag(x), bli_creal(b), bli_cimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_cczxpbys( x, b, y ) bli_cxxpbyris( bli_creal(x), bli_cimag(x), bli_creal(b), bli_cimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_zczxpbys( x, b, y ) bli_cxxpbyris( bli_zreal(x), bli_zimag(x), bli_creal(b), bli_cimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_szzxpbys( x, b, y ) bli_cxxpbyris( bli_sreal(x), bli_simag(x), bli_zreal(b), bli_zimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_dzzxpbys( x, b, y ) bli_cxxpbyris( bli_dreal(x), bli_dimag(x), bli_zreal(b), bli_zimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_czzxpbys( x, b, y ) bli_cxxpbyris( bli_creal(x), bli_cimag(x), bli_zreal(b), bli_zimag(b), bli_zreal(y), bli_zimag(y) ) #define bli_zzzxpbys( x, b, y ) bli_cxxpbyris( bli_zreal(x), bli_zimag(x), bli_zreal(b), bli_zimag(b), bli_zreal(y), bli_zimag(y) ) #else // ifdef BLIS_ENABLE_C99_COMPLEX // -- (xby) = (??c) ------------------------------------------------------------ #define bli_sscxpbys( x, b, y ) { (y) = (x) + (b) * (y); } #define bli_dscxpbys( x, b, y ) { (y) = (x) + (b) * (y); } #define bli_cscxpbys( x, b, y ) { (y) = (x) + (b) * (y); } #define bli_zscxpbys( x, b, y ) { (y) = (x) + (b) * (y); } #define bli_sdcxpbys( x, b, y ) { (y) = (x) + (b) * (y); } #define bli_ddcxpbys( x, b, y ) { (y) = (x) + (b) * (y); } #define bli_cdcxpbys( x, b, y ) { (y) = (x) + (b) * (y); } #define bli_zdcxpbys( x, b, y ) { (y) = (x) + (b) * (y); } #define bli_sccxpbys( x, b, y ) { (y) = (x) + (b) * (y); } #define bli_dccxpbys( x, b, y ) { (y) = (x) + (b) * (y); } #define bli_cccxpbys( x, b, y ) { (y) = (x) + (b) * (y); } #define bli_zccxpbys( x, b, y ) { (y) = (x) + (b) * (y); } #define bli_szcxpbys( x, b, y ) { (y) = (x) + (b) * (y); } #define bli_dzcxpbys( x, b, y ) { (y) = (x) + (b) * (y); } #define bli_czcxpbys( x, b, y ) { (y) = (x) + (b) * (y); } #define bli_zzcxpbys( x, b, y ) { (y) = (x) + (b) * (y); } // -- (xby) = (??z) ------------------------------------------------------------ #define bli_sszxpbys( x, b, y ) { (y) = (x) + (b) * (y); } #define bli_dszxpbys( x, b, y ) { (y) = (x) + (b) * (y); } #define bli_cszxpbys( x, b, y ) { (y) = (x) + (b) * (y); } #define bli_zszxpbys( x, b, y ) { (y) = (x) + (b) * (y); } #define bli_sdzxpbys( x, b, y ) { (y) = (x) + (b) * (y); } #define bli_ddzxpbys( x, b, y ) { (y) = (x) + (b) * (y); } #define bli_cdzxpbys( x, b, y ) { (y) = (x) + (b) * (y); } #define bli_zdzxpbys( x, b, y ) { (y) = (x) + (b) * (y); } #define bli_sczxpbys( x, b, y ) { (y) = (x) + (b) * (y); } #define bli_dczxpbys( x, b, y ) { (y) = (x) + (b) * (y); } #define bli_cczxpbys( x, b, y ) { (y) = (x) + (b) * (y); } #define bli_zczxpbys( x, b, y ) { (y) = (x) + (b) * (y); } #define bli_szzxpbys( x, b, y ) { (y) = (x) + (b) * (y); } #define bli_dzzxpbys( x, b, y ) { (y) = (x) + (b) * (y); } #define bli_czzxpbys( x, b, y ) { (y) = (x) + (b) * (y); } #define bli_zzzxpbys( x, b, y ) { (y) = (x) + (b) * (y); } #endif // BLIS_ENABLE_C99_COMPLEX #define bli_sxpbys( x, b, y ) bli_sssxpbys( x, b, y ) #define bli_dxpbys( x, b, y ) bli_dddxpbys( x, b, y ) #define bli_cxpbys( x, b, y ) bli_cccxpbys( x, b, y ) #define bli_zxpbys( x, b, y ) bli_zzzxpbys( x, b, y ) #endif blis-0.9.0/frame/include/level0/bli_xpbys_mxn.h000066400000000000000000000517771422157504600214320ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_XPBYS_MXN_H #define BLIS_XPBYS_MXN_H // xpbys_mxn // Notes: // - The first char encodes the type of x. // - The second char encodes the type of b. // - The third char encodes the type of y. // -- (xby) = (?ss) ------------------------------------------------------------ BLIS_INLINE void bli_sssxpbys_mxn( const dim_t m, const dim_t n, float* restrict x, const inc_t rs_x, const inc_t cs_x, float* restrict beta, float* restrict y, const inc_t rs_y, const inc_t cs_y ) { // If beta is zero, overwrite y with x (in case y has infs or NaNs). if ( bli_seq0( *beta ) ) { bli_sscopys_mxn( m, n, x, rs_x, cs_x, y, rs_y, cs_y ); return; } #ifdef BLIS_ENABLE_CR_CASES if ( rs_x == 1 && rs_y == 1 ) { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_sssxpbys( *(x + ii + jj*cs_x), *beta, *(y + ii + jj*cs_y) ); } else if ( cs_x == 1 && cs_y == 1 ) { for ( dim_t ii = 0; ii < m; ++ii ) for ( dim_t jj = 0; jj < n; ++jj ) bli_sssxpbys( *(x + ii*rs_x + jj), *beta, *(y + ii*rs_y + jj) ); } else #endif { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_sssxpbys( *(x + ii*rs_x + jj*cs_x), *beta, *(y + ii*rs_y + jj*cs_y) ); } } BLIS_INLINE void bli_dssxpbys_mxn( const dim_t m, const dim_t n, double* restrict x, const inc_t rs_x, const inc_t cs_x, float* restrict beta, float* restrict y, const inc_t rs_y, const inc_t cs_y ) { // If beta is zero, overwrite y with x (in case y has infs or NaNs). if ( bli_seq0( *beta ) ) { bli_dscopys_mxn( m, n, x, rs_x, cs_x, y, rs_y, cs_y ); return; } #ifdef BLIS_ENABLE_CR_CASES if ( rs_x == 1 && rs_y == 1 ) { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_dssxpbys( *(x + ii + jj*cs_x), *beta, *(y + ii + jj*cs_y) ); } else if ( cs_x == 1 && cs_y == 1 ) { for ( dim_t ii = 0; ii < m; ++ii ) for ( dim_t jj = 0; jj < n; ++jj ) bli_dssxpbys( *(x + ii*rs_x + jj), *beta, *(y + ii*rs_y + jj) ); } else #endif { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_dssxpbys( *(x + ii*rs_x + jj*cs_x), *beta, *(y + ii*rs_y + jj*cs_y) ); } } BLIS_INLINE void bli_cssxpbys_mxn( const dim_t m, const dim_t n, scomplex* restrict x, const inc_t rs_x, const inc_t cs_x, float* restrict beta, float* restrict y, const inc_t rs_y, const inc_t cs_y ) { // If beta is zero, overwrite y with x (in case y has infs or NaNs). if ( bli_seq0( *beta ) ) { bli_cscopys_mxn( m, n, x, rs_x, cs_x, y, rs_y, cs_y ); return; } #ifdef BLIS_ENABLE_CR_CASES if ( rs_x == 1 && rs_y == 1 ) { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_cssxpbys( *(x + ii + jj*cs_x), *beta, *(y + ii + jj*cs_y) ); } else if ( cs_x == 1 && cs_y == 1 ) { for ( dim_t ii = 0; ii < m; ++ii ) for ( dim_t jj = 0; jj < n; ++jj ) bli_cssxpbys( *(x + ii*rs_x + jj), *beta, *(y + ii*rs_y + jj) ); } else #endif { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_cssxpbys( *(x + ii*rs_x + jj*cs_x), *beta, *(y + ii*rs_y + jj*cs_y) ); } } BLIS_INLINE void bli_zssxpbys_mxn( const dim_t m, const dim_t n, dcomplex* restrict x, const inc_t rs_x, const inc_t cs_x, float* restrict beta, float* restrict y, const inc_t rs_y, const inc_t cs_y ) { // If beta is zero, overwrite y with x (in case y has infs or NaNs). if ( bli_seq0( *beta ) ) { bli_zscopys_mxn( m, n, x, rs_x, cs_x, y, rs_y, cs_y ); return; } #ifdef BLIS_ENABLE_CR_CASES if ( rs_x == 1 && rs_y == 1 ) { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_zssxpbys( *(x + ii + jj*cs_x), *beta, *(y + ii + jj*cs_y) ); } else if ( cs_x == 1 && cs_y == 1 ) { for ( dim_t ii = 0; ii < m; ++ii ) for ( dim_t jj = 0; jj < n; ++jj ) bli_zssxpbys( *(x + ii*rs_x + jj), *beta, *(y + ii*rs_y + jj) ); } else #endif { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_zssxpbys( *(x + ii*rs_x + jj*cs_x), *beta, *(y + ii*rs_y + jj*cs_y) ); } } // -- (xby) = (?dd) ------------------------------------------------------------ BLIS_INLINE void bli_sddxpbys_mxn( const dim_t m, const dim_t n, float* restrict x, const inc_t rs_x, const inc_t cs_x, double* restrict beta, double* restrict y, const inc_t rs_y, const inc_t cs_y ) { // If beta is zero, overwrite y with x (in case y has infs or NaNs). if ( bli_deq0( *beta ) ) { bli_sdcopys_mxn( m, n, x, rs_x, cs_x, y, rs_y, cs_y ); return; } #ifdef BLIS_ENABLE_CR_CASES if ( rs_x == 1 && rs_y == 1 ) { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_sddxpbys( *(x + ii + jj*cs_x), *beta, *(y + ii + jj*cs_y) ); } else if ( cs_x == 1 && cs_y == 1 ) { for ( dim_t ii = 0; ii < m; ++ii ) for ( dim_t jj = 0; jj < n; ++jj ) bli_sddxpbys( *(x + ii*rs_x + jj), *beta, *(y + ii*rs_y + jj) ); } else #endif { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_sddxpbys( *(x + ii*rs_x + jj*cs_x), *beta, *(y + ii*rs_y + jj*cs_y) ); } } BLIS_INLINE void bli_dddxpbys_mxn( const dim_t m, const dim_t n, double* restrict x, const inc_t rs_x, const inc_t cs_x, double* restrict beta, double* restrict y, const inc_t rs_y, const inc_t cs_y ) { // If beta is zero, overwrite y with x (in case y has infs or NaNs). if ( bli_deq0( *beta ) ) { bli_ddcopys_mxn( m, n, x, rs_x, cs_x, y, rs_y, cs_y ); return; } #ifdef BLIS_ENABLE_CR_CASES if ( rs_x == 1 && rs_y == 1 ) { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_dddxpbys( *(x + ii + jj*cs_x), *beta, *(y + ii + jj*cs_y) ); } else if ( cs_x == 1 && cs_y == 1 ) { for ( dim_t ii = 0; ii < m; ++ii ) for ( dim_t jj = 0; jj < n; ++jj ) bli_dddxpbys( *(x + ii*rs_x + jj), *beta, *(y + ii*rs_y + jj) ); } else #endif { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_dddxpbys( *(x + ii*rs_x + jj*cs_x), *beta, *(y + ii*rs_y + jj*cs_y) ); } } BLIS_INLINE void bli_cddxpbys_mxn( const dim_t m, const dim_t n, scomplex* restrict x, const inc_t rs_x, const inc_t cs_x, double* restrict beta, double* restrict y, const inc_t rs_y, const inc_t cs_y ) { // If beta is zero, overwrite y with x (in case y has infs or NaNs). if ( bli_deq0( *beta ) ) { bli_cdcopys_mxn( m, n, x, rs_x, cs_x, y, rs_y, cs_y ); return; } #ifdef BLIS_ENABLE_CR_CASES if ( rs_x == 1 && rs_y == 1 ) { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_cddxpbys( *(x + ii + jj*cs_x), *beta, *(y + ii + jj*cs_y) ); } else if ( cs_x == 1 && cs_y == 1 ) { for ( dim_t ii = 0; ii < m; ++ii ) for ( dim_t jj = 0; jj < n; ++jj ) bli_cddxpbys( *(x + ii*rs_x + jj), *beta, *(y + ii*rs_y + jj) ); } else #endif { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_cddxpbys( *(x + ii*rs_x + jj*cs_x), *beta, *(y + ii*rs_y + jj*cs_y) ); } } BLIS_INLINE void bli_zddxpbys_mxn( const dim_t m, const dim_t n, dcomplex* restrict x, const inc_t rs_x, const inc_t cs_x, double* restrict beta, double* restrict y, const inc_t rs_y, const inc_t cs_y ) { // If beta is zero, overwrite y with x (in case y has infs or NaNs). if ( bli_deq0( *beta ) ) { bli_zdcopys_mxn( m, n, x, rs_x, cs_x, y, rs_y, cs_y ); return; } #ifdef BLIS_ENABLE_CR_CASES if ( rs_x == 1 && rs_y == 1 ) { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_zddxpbys( *(x + ii + jj*cs_x), *beta, *(y + ii + jj*cs_y) ); } else if ( cs_x == 1 && cs_y == 1 ) { for ( dim_t ii = 0; ii < m; ++ii ) for ( dim_t jj = 0; jj < n; ++jj ) bli_zddxpbys( *(x + ii*rs_x + jj), *beta, *(y + ii*rs_y + jj) ); } else #endif { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_zddxpbys( *(x + ii*rs_x + jj*cs_x), *beta, *(y + ii*rs_y + jj*cs_y) ); } } // -- (xby) = (?cc) ------------------------------------------------------------ BLIS_INLINE void bli_sccxpbys_mxn( const dim_t m, const dim_t n, float* restrict x, const inc_t rs_x, const inc_t cs_x, scomplex* restrict beta, scomplex* restrict y, const inc_t rs_y, const inc_t cs_y ) { // If beta is zero, overwrite y with x (in case y has infs or NaNs). if ( bli_ceq0( *beta ) ) { bli_sccopys_mxn( m, n, x, rs_x, cs_x, y, rs_y, cs_y ); return; } #ifdef BLIS_ENABLE_CR_CASES if ( rs_x == 1 && rs_y == 1 ) { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_sccxpbys( *(x + ii + jj*cs_x), *beta, *(y + ii + jj*cs_y) ); } else if ( cs_x == 1 && cs_y == 1 ) { for ( dim_t ii = 0; ii < m; ++ii ) for ( dim_t jj = 0; jj < n; ++jj ) bli_sccxpbys( *(x + ii*rs_x + jj), *beta, *(y + ii*rs_y + jj) ); } else #endif { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_sccxpbys( *(x + ii*rs_x + jj*cs_x), *beta, *(y + ii*rs_y + jj*cs_y) ); } } BLIS_INLINE void bli_dccxpbys_mxn( const dim_t m, const dim_t n, double* restrict x, const inc_t rs_x, const inc_t cs_x, scomplex* restrict beta, scomplex* restrict y, const inc_t rs_y, const inc_t cs_y ) { // If beta is zero, overwrite y with x (in case y has infs or NaNs). if ( bli_ceq0( *beta ) ) { bli_dccopys_mxn( m, n, x, rs_x, cs_x, y, rs_y, cs_y ); return; } #ifdef BLIS_ENABLE_CR_CASES if ( rs_x == 1 && rs_y == 1 ) { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_dccxpbys( *(x + ii + jj*cs_x), *beta, *(y + ii + jj*cs_y) ); } else if ( cs_x == 1 && cs_y == 1 ) { for ( dim_t ii = 0; ii < m; ++ii ) for ( dim_t jj = 0; jj < n; ++jj ) bli_dccxpbys( *(x + ii*rs_x + jj), *beta, *(y + ii*rs_y + jj) ); } else #endif { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_dccxpbys( *(x + ii*rs_x + jj*cs_x), *beta, *(y + ii*rs_y + jj*cs_y) ); } } BLIS_INLINE void bli_cccxpbys_mxn( const dim_t m, const dim_t n, scomplex* restrict x, const inc_t rs_x, const inc_t cs_x, scomplex* restrict beta, scomplex* restrict y, const inc_t rs_y, const inc_t cs_y ) { // If beta is zero, overwrite y with x (in case y has infs or NaNs). if ( bli_ceq0( *beta ) ) { bli_cccopys_mxn( m, n, x, rs_x, cs_x, y, rs_y, cs_y ); return; } #ifdef BLIS_ENABLE_CR_CASES if ( rs_x == 1 && rs_y == 1 ) { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_cccxpbys( *(x + ii + jj*cs_x), *beta, *(y + ii + jj*cs_y) ); } else if ( cs_x == 1 && cs_y == 1 ) { for ( dim_t ii = 0; ii < m; ++ii ) for ( dim_t jj = 0; jj < n; ++jj ) bli_cccxpbys( *(x + ii*rs_x + jj), *beta, *(y + ii*rs_y + jj) ); } else #endif { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_cccxpbys( *(x + ii*rs_x + jj*cs_x), *beta, *(y + ii*rs_y + jj*cs_y) ); } } BLIS_INLINE void bli_zccxpbys_mxn( const dim_t m, const dim_t n, dcomplex* restrict x, const inc_t rs_x, const inc_t cs_x, scomplex* restrict beta, scomplex* restrict y, const inc_t rs_y, const inc_t cs_y ) { // If beta is zero, overwrite y with x (in case y has infs or NaNs). if ( bli_ceq0( *beta ) ) { bli_zccopys_mxn( m, n, x, rs_x, cs_x, y, rs_y, cs_y ); return; } #ifdef BLIS_ENABLE_CR_CASES if ( rs_x == 1 && rs_y == 1 ) { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_zccxpbys( *(x + ii + jj*cs_x), *beta, *(y + ii + jj*cs_y) ); } else if ( cs_x == 1 && cs_y == 1 ) { for ( dim_t ii = 0; ii < m; ++ii ) for ( dim_t jj = 0; jj < n; ++jj ) bli_zccxpbys( *(x + ii*rs_x + jj), *beta, *(y + ii*rs_y + jj) ); } else #endif { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_zccxpbys( *(x + ii*rs_x + jj*cs_x), *beta, *(y + ii*rs_y + jj*cs_y) ); } } // -- (xby) = (?zz) ------------------------------------------------------------ BLIS_INLINE void bli_szzxpbys_mxn( const dim_t m, const dim_t n, float* restrict x, const inc_t rs_x, const inc_t cs_x, dcomplex* restrict beta, dcomplex* restrict y, const inc_t rs_y, const inc_t cs_y ) { // If beta is zero, overwrite y with x (in case y has infs or NaNs). if ( bli_zeq0( *beta ) ) { bli_szcopys_mxn( m, n, x, rs_x, cs_x, y, rs_y, cs_y ); return; } #ifdef BLIS_ENABLE_CR_CASES if ( rs_x == 1 && rs_y == 1 ) { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_szzxpbys( *(x + ii + jj*cs_x), *beta, *(y + ii + jj*cs_y) ); } else if ( cs_x == 1 && cs_y == 1 ) { for ( dim_t ii = 0; ii < m; ++ii ) for ( dim_t jj = 0; jj < n; ++jj ) bli_szzxpbys( *(x + ii*rs_x + jj), *beta, *(y + ii*rs_y + jj) ); } else #endif { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_szzxpbys( *(x + ii*rs_x + jj*cs_x), *beta, *(y + ii*rs_y + jj*cs_y) ); } } BLIS_INLINE void bli_dzzxpbys_mxn( const dim_t m, const dim_t n, double* restrict x, const inc_t rs_x, const inc_t cs_x, dcomplex* restrict beta, dcomplex* restrict y, const inc_t rs_y, const inc_t cs_y ) { // If beta is zero, overwrite y with x (in case y has infs or NaNs). if ( bli_zeq0( *beta ) ) { bli_dzcopys_mxn( m, n, x, rs_x, cs_x, y, rs_y, cs_y ); return; } #ifdef BLIS_ENABLE_CR_CASES if ( rs_x == 1 && rs_y == 1 ) { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_dzzxpbys( *(x + ii + jj*cs_x), *beta, *(y + ii + jj*cs_y) ); } else if ( cs_x == 1 && cs_y == 1 ) { for ( dim_t ii = 0; ii < m; ++ii ) for ( dim_t jj = 0; jj < n; ++jj ) bli_dzzxpbys( *(x + ii*rs_x + jj), *beta, *(y + ii*rs_y + jj) ); } else #endif { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_dzzxpbys( *(x + ii*rs_x + jj*cs_x), *beta, *(y + ii*rs_y + jj*cs_y) ); } } BLIS_INLINE void bli_czzxpbys_mxn( const dim_t m, const dim_t n, scomplex* restrict x, const inc_t rs_x, const inc_t cs_x, dcomplex* restrict beta, dcomplex* restrict y, const inc_t rs_y, const inc_t cs_y ) { // If beta is zero, overwrite y with x (in case y has infs or NaNs). if ( bli_zeq0( *beta ) ) { bli_czcopys_mxn( m, n, x, rs_x, cs_x, y, rs_y, cs_y ); return; } #ifdef BLIS_ENABLE_CR_CASES if ( rs_x == 1 && rs_y == 1 ) { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_czzxpbys( *(x + ii + jj*cs_x), *beta, *(y + ii + jj*cs_y) ); } else if ( cs_x == 1 && cs_y == 1 ) { for ( dim_t ii = 0; ii < m; ++ii ) for ( dim_t jj = 0; jj < n; ++jj ) bli_czzxpbys( *(x + ii*rs_x + jj), *beta, *(y + ii*rs_y + jj) ); } else #endif { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_czzxpbys( *(x + ii*rs_x + jj*cs_x), *beta, *(y + ii*rs_y + jj*cs_y) ); } } BLIS_INLINE void bli_zzzxpbys_mxn( const dim_t m, const dim_t n, dcomplex* restrict x, const inc_t rs_x, const inc_t cs_x, dcomplex* restrict beta, dcomplex* restrict y, const inc_t rs_y, const inc_t cs_y ) { // If beta is zero, overwrite y with x (in case y has infs or NaNs). if ( bli_zeq0( *beta ) ) { bli_zzcopys_mxn( m, n, x, rs_x, cs_x, y, rs_y, cs_y ); return; } #ifdef BLIS_ENABLE_CR_CASES if ( rs_x == 1 && rs_y == 1 ) { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_zzzxpbys( *(x + ii + jj*cs_x), *beta, *(y + ii + jj*cs_y) ); } else if ( cs_x == 1 && cs_y == 1 ) { for ( dim_t ii = 0; ii < m; ++ii ) for ( dim_t jj = 0; jj < n; ++jj ) bli_zzzxpbys( *(x + ii*rs_x + jj), *beta, *(y + ii*rs_y + jj) ); } else #endif { for ( dim_t jj = 0; jj < n; ++jj ) for ( dim_t ii = 0; ii < m; ++ii ) bli_zzzxpbys( *(x + ii*rs_x + jj*cs_x), *beta, *(y + ii*rs_y + jj*cs_y) ); } } BLIS_INLINE void bli_sxpbys_mxn( const dim_t m, const dim_t n, float* restrict x, const inc_t rs_x, const inc_t cs_x, float* restrict beta, float* restrict y, const inc_t rs_y, const inc_t cs_y ) { bli_sssxpbys_mxn( m, n, x, rs_x, cs_x, beta, y, rs_y, cs_y ); } BLIS_INLINE void bli_dxpbys_mxn( const dim_t m, const dim_t n, double* restrict x, const inc_t rs_x, const inc_t cs_x, double* restrict beta, double* restrict y, const inc_t rs_y, const inc_t cs_y ) { bli_dddxpbys_mxn( m, n, x, rs_x, cs_x, beta, y, rs_y, cs_y ); } BLIS_INLINE void bli_cxpbys_mxn( const dim_t m, const dim_t n, scomplex* restrict x, const inc_t rs_x, const inc_t cs_x, scomplex* restrict beta, scomplex* restrict y, const inc_t rs_y, const inc_t cs_y ) { bli_cccxpbys_mxn( m, n, x, rs_x, cs_x, beta, y, rs_y, cs_y ); } BLIS_INLINE void bli_zxpbys_mxn( const dim_t m, const dim_t n, dcomplex* restrict x, const inc_t rs_x, const inc_t cs_x, dcomplex* restrict beta, dcomplex* restrict y, const inc_t rs_y, const inc_t cs_y ) { bli_zzzxpbys_mxn( m, n, x, rs_x, cs_x, beta, y, rs_y, cs_y ); } #endif blis-0.9.0/frame/include/level0/bli_xpbys_mxn_uplo.h000066400000000000000000000206771422157504600224640ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_XPBYS_MXN_UPLO_H #define BLIS_XPBYS_MXN_UPLO_H // xpbys_mxn_u #define bli_sssxpbys_mxn_u( diagoff, m, n, x, rs_x, cs_x, beta, y, rs_y, cs_y ) \ { \ dim_t _i, _j; \ \ /* If beta is zero, overwrite y with x (in case y has infs or NaNs). */ \ if ( bli_seq0( *beta ) ) \ { \ for ( _j = 0; _j < n; ++_j ) \ for ( _i = 0; _i < m; ++_i ) \ if ( (doff_t)_j - (doff_t)_i >= diagoff ) \ { \ bli_sscopys( *(x + _i*rs_x + _j*cs_x), \ *(y + _i*rs_y + _j*cs_y) ); \ } \ } \ else \ { \ for ( _j = 0; _j < n; ++_j ) \ for ( _i = 0; _i < m; ++_i ) \ if ( (doff_t)_j - (doff_t)_i >= diagoff ) \ { \ bli_sssxpbys( *(x + _i*rs_x + _j*cs_x), \ *(beta), \ *(y + _i*rs_y + _j*cs_y) ); \ } \ } \ } #define bli_dddxpbys_mxn_u( diagoff, m, n, x, rs_x, cs_x, beta, y, rs_y, cs_y ) \ { \ dim_t _i, _j; \ \ /* If beta is zero, overwrite y with x (in case y has infs or NaNs). */ \ if ( bli_deq0( *beta ) ) \ { \ for ( _j = 0; _j < n; ++_j ) \ for ( _i = 0; _i < m; ++_i ) \ if ( (doff_t)_j - (doff_t)_i >= diagoff ) \ { \ bli_ddcopys( *(x + _i*rs_x + _j*cs_x), \ *(y + _i*rs_y + _j*cs_y) ); \ } \ } \ else \ { \ for ( _j = 0; _j < n; ++_j ) \ for ( _i = 0; _i < m; ++_i ) \ if ( (doff_t)_j - (doff_t)_i >= diagoff ) \ { \ bli_dddxpbys( *(x + _i*rs_x + _j*cs_x), \ *(beta), \ *(y + _i*rs_y + _j*cs_y) ); \ } \ } \ } #define bli_cccxpbys_mxn_u( diagoff, m, n, x, rs_x, cs_x, beta, y, rs_y, cs_y ) \ { \ dim_t _i, _j; \ \ /* If beta is zero, overwrite y with x (in case y has infs or NaNs). */ \ if ( bli_ceq0( *beta ) ) \ { \ for ( _j = 0; _j < n; ++_j ) \ for ( _i = 0; _i < m; ++_i ) \ if ( (doff_t)_j - (doff_t)_i >= diagoff ) \ { \ bli_cccopys( *(x + _i*rs_x + _j*cs_x), \ *(y + _i*rs_y + _j*cs_y) ); \ } \ } \ else \ { \ for ( _j = 0; _j < n; ++_j ) \ for ( _i = 0; _i < m; ++_i ) \ if ( (doff_t)_j - (doff_t)_i >= diagoff ) \ { \ bli_cccxpbys( *(x + _i*rs_x + _j*cs_x), \ *(beta), \ *(y + _i*rs_y + _j*cs_y) ); \ } \ } \ } #define bli_zzzxpbys_mxn_u( diagoff, m, n, x, rs_x, cs_x, beta, y, rs_y, cs_y ) \ { \ dim_t _i, _j; \ \ /* If beta is zero, overwrite y with x (in case y has infs or NaNs). */ \ if ( bli_zeq0( *beta ) ) \ { \ for ( _j = 0; _j < n; ++_j ) \ for ( _i = 0; _i < m; ++_i ) \ if ( (doff_t)_j - (doff_t)_i >= diagoff ) \ { \ bli_zzcopys( *(x + _i*rs_x + _j*cs_x), \ *(y + _i*rs_y + _j*cs_y) ); \ } \ } \ else \ { \ for ( _j = 0; _j < n; ++_j ) \ for ( _i = 0; _i < m; ++_i ) \ if ( (doff_t)_j - (doff_t)_i >= diagoff ) \ { \ bli_zzzxpbys( *(x + _i*rs_x + _j*cs_x), \ *(beta), \ *(y + _i*rs_y + _j*cs_y) ); \ } \ } \ } // xpbys_mxn_l #define bli_sssxpbys_mxn_l( diagoff, m, n, x, rs_x, cs_x, beta, y, rs_y, cs_y ) \ { \ dim_t _i, _j; \ \ /* If beta is zero, overwrite y with x (in case y has infs or NaNs). */ \ if ( bli_seq0( *beta ) ) \ { \ for ( _j = 0; _j < n; ++_j ) \ for ( _i = 0; _i < m; ++_i ) \ if ( (doff_t)_j - (doff_t)_i <= diagoff ) \ { \ bli_sscopys( *(x + _i*rs_x + _j*cs_x), \ *(y + _i*rs_y + _j*cs_y) ); \ } \ } \ else \ { \ for ( _j = 0; _j < n; ++_j ) \ for ( _i = 0; _i < m; ++_i ) \ if ( (doff_t)_j - (doff_t)_i <= diagoff ) \ { \ bli_sssxpbys( *(x + _i*rs_x + _j*cs_x), \ *(beta), \ *(y + _i*rs_y + _j*cs_y) ); \ } \ } \ } #define bli_dddxpbys_mxn_l( diagoff, m, n, x, rs_x, cs_x, beta, y, rs_y, cs_y ) \ { \ dim_t _i, _j; \ \ /* If beta is zero, overwrite y with x (in case y has infs or NaNs). */ \ if ( bli_deq0( *beta ) ) \ { \ for ( _j = 0; _j < n; ++_j ) \ for ( _i = 0; _i < m; ++_i ) \ if ( (doff_t)_j - (doff_t)_i <= diagoff ) \ { \ bli_ddcopys( *(x + _i*rs_x + _j*cs_x), \ *(y + _i*rs_y + _j*cs_y) ); \ } \ } \ else \ { \ for ( _j = 0; _j < n; ++_j ) \ for ( _i = 0; _i < m; ++_i ) \ if ( (doff_t)_j - (doff_t)_i <= diagoff ) \ { \ bli_dddxpbys( *(x + _i*rs_x + _j*cs_x), \ *(beta), \ *(y + _i*rs_y + _j*cs_y) ); \ } \ } \ } #define bli_cccxpbys_mxn_l( diagoff, m, n, x, rs_x, cs_x, beta, y, rs_y, cs_y ) \ { \ dim_t _i, _j; \ \ /* If beta is zero, overwrite y with x (in case y has infs or NaNs). */ \ if ( bli_ceq0( *beta ) ) \ { \ for ( _j = 0; _j < n; ++_j ) \ for ( _i = 0; _i < m; ++_i ) \ if ( (doff_t)_j - (doff_t)_i <= diagoff ) \ { \ bli_cccopys( *(x + _i*rs_x + _j*cs_x), \ *(y + _i*rs_y + _j*cs_y) ); \ } \ } \ else \ { \ for ( _j = 0; _j < n; ++_j ) \ for ( _i = 0; _i < m; ++_i ) \ if ( (doff_t)_j - (doff_t)_i <= diagoff ) \ { \ bli_cccxpbys( *(x + _i*rs_x + _j*cs_x), \ *(beta), \ *(y + _i*rs_y + _j*cs_y) ); \ } \ } \ } #define bli_zzzxpbys_mxn_l( diagoff, m, n, x, rs_x, cs_x, beta, y, rs_y, cs_y ) \ { \ dim_t _i, _j; \ \ /* If beta is zero, overwrite y with x (in case y has infs or NaNs). */ \ if ( bli_zeq0( *beta ) ) \ { \ for ( _j = 0; _j < n; ++_j ) \ for ( _i = 0; _i < m; ++_i ) \ if ( (doff_t)_j - (doff_t)_i <= diagoff ) \ { \ bli_zzcopys( *(x + _i*rs_x + _j*cs_x), \ *(y + _i*rs_y + _j*cs_y) ); \ } \ } \ else \ { \ for ( _j = 0; _j < n; ++_j ) \ for ( _i = 0; _i < m; ++_i ) \ if ( (doff_t)_j - (doff_t)_i <= diagoff ) \ { \ bli_zzzxpbys( *(x + _i*rs_x + _j*cs_x), \ *(beta), \ *(y + _i*rs_y + _j*cs_y) ); \ } \ } \ } #define bli_sxpbys_mxn_u( diagoff, m, n, x, rs_x, cs_x, beta, y, rs_y, cs_y ) \ {\ bli_sssxpbys_mxn_u( diagoff, m, n, x, rs_x, cs_x, beta, y, rs_y, cs_y ); \ } #define bli_dxpbys_mxn_u( diagoff, m, n, x, rs_x, cs_x, beta, y, rs_y, cs_y ) \ {\ bli_dddxpbys_mxn_u( diagoff, m, n, x, rs_x, cs_x, beta, y, rs_y, cs_y ); \ } #define bli_cxpbys_mxn_u( diagoff, m, n, x, rs_x, cs_x, beta, y, rs_y, cs_y ) \ {\ bli_cccxpbys_mxn_u( diagoff, m, n, x, rs_x, cs_x, beta, y, rs_y, cs_y ); \ } #define bli_zxpbys_mxn_u( diagoff, m, n, x, rs_x, cs_x, beta, y, rs_y, cs_y ) \ {\ bli_zzzxpbys_mxn_u( diagoff, m, n, x, rs_x, cs_x, beta, y, rs_y, cs_y ); \ } #define bli_sxpbys_mxn_l( diagoff, m, n, x, rs_x, cs_x, beta, y, rs_y, cs_y ) \ {\ bli_sssxpbys_mxn_l( diagoff, m, n, x, rs_x, cs_x, beta, y, rs_y, cs_y ); \ } #define bli_dxpbys_mxn_l( diagoff, m, n, x, rs_x, cs_x, beta, y, rs_y, cs_y ) \ {\ bli_dddxpbys_mxn_l( diagoff, m, n, x, rs_x, cs_x, beta, y, rs_y, cs_y ); \ } #define bli_cxpbys_mxn_l( diagoff, m, n, x, rs_x, cs_x, beta, y, rs_y, cs_y ) \ {\ bli_cccxpbys_mxn_l( diagoff, m, n, x, rs_x, cs_x, beta, y, rs_y, cs_y ); \ } #define bli_zxpbys_mxn_l( diagoff, m, n, x, rs_x, cs_x, beta, y, rs_y, cs_y ) \ {\ bli_zzzxpbys_mxn_l( diagoff, m, n, x, rs_x, cs_x, beta, y, rs_y, cs_y ); \ } #endif blis-0.9.0/frame/include/level0/old/000077500000000000000000000000001422157504600171415ustar00rootroot00000000000000blis-0.9.0/frame/include/level0/old/bli_cast.h000066400000000000000000000110021422157504600210640ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_CAST_H #define BLIS_CAST_H // cast // Notes: // - The first char encodes the type of *ap. // - The second char encodes the type of b. #define bli_sscast( ap, b ) \ { \ (b) = ( float ) *(( float* )(ap)); \ } #define bli_dscast( ap, b ) \ { \ (b) = ( float ) *(( double* )(ap)); \ } #define bli_cscast( ap, b ) \ { \ (b) = ( float ) bli_creal( *(( scomplex* )(ap)) ); \ } #define bli_zscast( ap, b ) \ { \ (b) = ( float ) bli_zreal( *(( dcomplex* )(ap)) ); \ } #define bli_sdcast( ap, b ) \ { \ (b) = ( double ) *(( float* )(ap)); \ } #define bli_ddcast( ap, b ) \ { \ (b) = ( double ) *(( double* )(ap)); \ } #define bli_cdcast( ap, b ) \ { \ (b) = ( double ) bli_creal( *(( scomplex* )(ap)) ); \ } #define bli_zdcast( ap, b ) \ { \ (b) = ( double ) bli_zreal( *(( dcomplex* )(ap)) ); \ } #ifndef BLIS_ENABLE_C99_COMPLEX #define bli_sccast( ap, b ) \ { \ bli_scsets( bli_sreal( *(( float* )(ap)) ), \ 0.0, (b) ); \ } #define bli_dccast( ap, b ) \ { \ bli_dcsets( bli_dreal( *(( double* )(ap)) ), \ 0.0, (b) ); \ } #define bli_cccast( ap, b ) \ { \ bli_ccsets( bli_creal( *(( scomplex* )(ap)) ), \ bli_cimag( *(( scomplex* )(ap)) ), (b) ); \ } #define bli_zccast( ap, b ) \ { \ bli_zcsets( bli_zreal( *(( dcomplex* )(ap)) ), \ bli_zimag( *(( dcomplex* )(ap)) ), (b) ); \ } #define bli_szcast( ap, b ) \ { \ bli_szsets( bli_sreal( *(( float* )(ap)) ), \ 0.0, (b) ); \ } #define bli_dzcast( ap, b ) \ { \ bli_dzsets( bli_dreal( *(( double* )(ap)) ), \ 0.0, (b) ); \ } #define bli_czcast( ap, b ) \ { \ bli_czsets( bli_creal( *(( scomplex* )(ap)) ), \ bli_cimag( *(( scomplex* )(ap)) ), (b) ); \ } #define bli_zzcast( ap, b ) \ { \ bli_zzsets( bli_zreal( *(( dcomplex* )(ap)) ), \ bli_zimag( *(( dcomplex* )(ap)) ), (b) ); \ } #else // ifdef BLIS_ENABLE_C99_COMPLEX #define bli_sccast( ap, b ) { (b) = ( scomplex ) *(( float* )(ap)); } #define bli_dccast( ap, b ) { (b) = ( scomplex ) *(( double* )(ap)); } #define bli_cccast( ap, b ) { (b) = ( scomplex ) *(( scomplex* )(ap)); } #define bli_zccast( ap, b ) { (b) = ( scomplex ) *(( dcomplex* )(ap)); } #define bli_szcast( ap, b ) { (b) = ( dcomplex ) *(( float* )(ap)); } #define bli_dzcast( ap, b ) { (b) = ( dcomplex ) *(( double* )(ap)); } #define bli_czcast( ap, b ) { (b) = ( dcomplex ) *(( scomplex* )(ap)); } #define bli_zzcast( ap, b ) { (b) = ( dcomplex ) *(( dcomplex* )(ap)); } #endif // BLIS_ENABLE_C99_COMPLEX #define bli_scast( ap, b ) bli_sscast( ap, b ) #define bli_dcast( ap, b ) bli_ddcast( ap, b ) #define bli_ccast( ap, b ) bli_cccast( ap, b ) #define bli_zcast( ap, b ) bli_zzcast( ap, b ) #endif blis-0.9.0/frame/include/level0/old/bli_castfrom.h000066400000000000000000000032101422157504600217520ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ blis-0.9.0/frame/include/level0/old/bli_castto.h000066400000000000000000000032101422157504600214310ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ blis-0.9.0/frame/include/level0/old/bli_copynzjs.h000066400000000000000000000070061422157504600220220ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_COPYNZJS_H #define BLIS_COPYNZJS_H // copynzjs // Notes: // - The first char encodes the type of x. // - The second char encodes the type of y. // - x is copied in conjugated form. #define bli_sscopynzjs( x, y ) \ { \ (y) = ( float ) (x); \ } #define bli_dscopynzjs( x, y ) \ { \ (y) = ( float ) (x); \ } #define bli_cscopynzjs( x, y ) \ { \ (y) = ( float ) (x).real; \ } #define bli_zscopynzjs( x, y ) \ { \ (y) = ( float ) (x).real; \ } #define bli_sdcopynzjs( x, y ) \ { \ (y) = ( double ) (x); \ } #define bli_ddcopynzjs( x, y ) \ { \ (y) = ( double ) (x); \ } #define bli_cdcopynzjs( x, y ) \ { \ (y) = ( double ) (x).real; \ } #define bli_zdcopynzjs( x, y ) \ { \ (y) = ( double ) (x).real; \ } #define bli_sccopynzjs( x, y ) \ { \ (y).real = ( float ) (x); \ /* (y).imag = 0.0F; (SKIP COPYING OF ZERO) */ \ } #define bli_dccopynzjs( x, y ) \ { \ (y).real = ( float ) (x); \ /* (y).imag = 0.0F; (SKIP COPYING OF ZERO) */ \ } #define bli_cccopynzjs( x, y ) \ { \ (y).real = ( float ) (x).real; \ (y).imag = ( float ) -(x).imag; \ } #define bli_zccopynzjs( x, y ) \ { \ (y).real = ( float ) (x).real; \ (y).imag = ( float ) -(x).imag; \ } #define bli_szcopynzjs( x, y ) \ { \ (y).real = ( double ) (x); \ /* (y).imag = 0.0; (SKIP COPYING OF ZERO) */ \ } #define bli_dzcopynzjs( x, y ) \ { \ (y).real = ( double ) (x); \ /* (y).imag = 0.0; (SKIP COPYING OF ZERO) */ \ } #define bli_czcopynzjs( x, y ) \ { \ (y).real = ( double ) (x).real; \ (y).imag = ( double ) -(x).imag; \ } #define bli_zzcopynzjs( x, y ) \ { \ (y).real = ( double ) (x).real; \ (y).imag = ( double ) -(x).imag; \ } #define bli_scopynzjs( x, y ) \ { \ bli_sscopynzjs( x, y ); \ } #define bli_dcopynzjs( x, y ) \ { \ bli_ddcopynzjs( x, y ); \ } #define bli_ccopynzjs( x, y ) \ { \ bli_cccopynzjs( x, y ); \ } #define bli_zcopynzjs( x, y ) \ { \ bli_zzcopynzjs( x, y ); \ } #endif blis-0.9.0/frame/include/level0/old/bli_copynzs.h000066400000000000000000000066761422157504600216640ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_COPYNZS_H #define BLIS_COPYNZS_H // copynzs // Notes: // - The first char encodes the type of x. // - The second char encodes the type of y. #define bli_sscopynzs( x, y ) \ { \ (y) = ( float ) (x); \ } #define bli_dscopynzs( x, y ) \ { \ (y) = ( float ) (x); \ } #define bli_cscopynzs( x, y ) \ { \ (y) = ( float ) (x).real; \ } #define bli_zscopynzs( x, y ) \ { \ (y) = ( float ) (x).real; \ } #define bli_sdcopynzs( x, y ) \ { \ (y) = ( double ) (x); \ } #define bli_ddcopynzs( x, y ) \ { \ (y) = ( double ) (x); \ } #define bli_cdcopynzs( x, y ) \ { \ (y) = ( double ) (x).real; \ } #define bli_zdcopynzs( x, y ) \ { \ (y) = ( double ) (x).real; \ } #define bli_sccopynzs( x, y ) \ { \ (y).real = ( float ) (x); \ /* (y).imag = 0.0F; (SKIP COPYING OF ZERO) */ \ } #define bli_dccopynzs( x, y ) \ { \ (y).real = ( float ) (x); \ /* (y).imag = 0.0F (SKIP COPYING OF ZERO) */; \ } #define bli_cccopynzs( x, y ) \ { \ (y).real = ( float ) (x).real; \ (y).imag = ( float ) (x).imag; \ } #define bli_zccopynzs( x, y ) \ { \ (y).real = ( float ) (x).real; \ (y).imag = ( float ) (x).imag; \ } #define bli_szcopynzs( x, y ) \ { \ (y).real = ( double ) (x); \ /* (y).imag = 0.0; (SKIP COPYING OF ZERO) */ \ } #define bli_dzcopynzs( x, y ) \ { \ (y).real = ( double ) (x); \ /* (y).imag = 0.0; (SKIP COPYING OF ZERO) */ \ } #define bli_czcopynzs( x, y ) \ { \ (y).real = ( double ) (x).real; \ (y).imag = ( double ) (x).imag; \ } #define bli_zzcopynzs( x, y ) \ { \ (y).real = ( double ) (x).real; \ (y).imag = ( double ) (x).imag; \ } #define bli_scopynzs( x, y ) \ { \ bli_sscopynzs( x, y ); \ } #define bli_dcopynzs( x, y ) \ { \ bli_ddcopynzs( x, y ); \ } #define bli_ccopynzs( x, y ) \ { \ bli_cccopynzs( x, y ); \ } #define bli_zcopynzs( x, y ) \ { \ bli_zzcopynzs( x, y ); \ } #endif blis-0.9.0/frame/include/level0/old/bli_invscalcjs.h000066400000000000000000000122311422157504600222760ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_INVSCALCJS_H #define BLIS_INVSCALCJS_H // invscalcjs // Notes: // - The first char encodes the type of a. // - The second char encodes the type of x. #define bli_ssinvscalcjs( conj, a, x ) \ { \ (x) /= ( float ) (a); \ } #define bli_dsinvscalcjs( conj, a, x ) \ { \ (x) /= ( float ) (a); \ } #define bli_csinvscalcjs( conj, a, x ) \ { \ (x) /= ( float ) (a).real; \ } #define bli_zsinvscalcjs( conj, a, x ) \ { \ (x) /= ( float ) (a).real; \ } #define bli_sdinvscalcjs( conj, a, x ) \ { \ (x) /= ( double ) (a); \ } #define bli_ddinvscalcjs( conj, a, x ) \ { \ (x) /= ( double ) (a); \ } #define bli_cdinvscalcjs( conj, a, x ) \ { \ (x) /= ( double ) (a).real; \ } #define bli_zdinvscalcjs( conj, a, x ) \ { \ (x) /= ( double ) (a).real; \ } #define bli_scinvscalcjs( conj, a, x ) \ { \ (x).real /= ( float ) (a); \ (x).imag /= ( float ) (a); \ } #define bli_dcinvscalcjs( conj, a, x ) \ { \ (x).real /= ( float ) (a); \ (x).imag /= ( float ) (a); \ } #define bli_ccinvscalcjs( conj, a, x ) \ { \ float aimag = ( bli_is_conj( conj ) ? ( float ) -(a).imag : \ ( float ) (a).imag ); \ float temp = ( float ) (a).real * (a).real + ( float ) aimag * (a).imag; \ float xr = ( float ) ( ( float ) (a).real * (x).real + ( float ) aimag * (x).imag ) / temp; \ float xi = ( float ) ( ( float ) (a).real * (x).imag - ( float ) aimag * (x).real ) / temp; \ (x).real = xr; \ (x).imag = xi; \ } #define bli_zcinvscalcjs( conj, a, x ) \ { \ float aimag = ( bli_is_conj( conj ) ? ( float ) -(a).imag : \ ( float ) (a).imag ); \ float temp = ( float ) (a).real * (a).real + ( float ) aimag * (a).imag; \ float xr = ( float ) ( ( float ) (a).real * (x).real + ( float ) aimag * (x).imag ) / temp; \ float xi = ( float ) ( ( float ) (a).real * (x).imag - ( float ) aimag * (x).real ) / temp; \ (x).real = xr; \ (x).imag = xi; \ } #define bli_szinvscalcjs( conj, a, x ) \ { \ (x).real /= ( double ) (a); \ (x).imag /= ( double ) (a); \ } #define bli_dzinvscalcjs( conj, a, x ) \ { \ (x).real /= ( double ) (a); \ (x).imag /= ( double ) (a); \ } #define bli_czinvscalcjs( conj, a, x ) \ { \ double aimag = ( bli_is_conj( conj ) ? ( double ) -(a).imag : \ ( double ) (a).imag ); \ double temp = ( double ) (a).real * (a).real + ( double ) aimag * (a).imag; \ double xr = ( double ) ( ( double ) (a).real * (x).real + ( double ) aimag * (x).imag ) / temp; \ double xi = ( double ) ( ( double ) (a).real * (x).imag - ( double ) aimag * (x).real ) / temp; \ (x).real = xr; \ (x).imag = xi; \ } #define bli_zzinvscalcjs( conj, a, x ) \ { \ double aimag = ( bli_is_conj( conj ) ? ( double ) -(a).imag : \ ( double ) (a).imag ); \ double temp = ( double ) (a).real * (a).real + ( double ) aimag * (a).imag; \ double xr = ( double ) ( ( double ) (a).real * (x).real + ( double ) aimag * (x).imag ) / temp; \ double xi = ( double ) ( ( double ) (a).real * (x).imag - ( double ) aimag * (x).real ) / temp; \ (x).real = xr; \ (x).imag = xi; \ } #define bli_sinvscalcjs( conj, a, x ) \ { \ bli_ssinvscalcjs( conj, a, x ); \ } #define bli_dinvscalcjs( conj, a, x ) \ { \ bli_ddinvscalcjs( conj, a, x ); \ } #define bli_cinvscalcjs( conj, a, x ) \ { \ bli_ccinvscalcjs( conj, a, x ); \ } #define bli_zinvscalcjs( conj, a, x ) \ { \ bli_zzinvscalcjs( conj, a, x ); \ } #endif blis-0.9.0/frame/include/level0/old/bli_scalcjs.h000066400000000000000000000111431422157504600215620ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_SCALCJS_H #define BLIS_SCALCJS_H // scalcjs // Notes: // - The first char encodes the type of a. // - The second char encodes the type of x. // - a is (conditionally) used in conjugated form. #define bli_ssscalcjs( conj, a, x ) \ { \ (x) *= ( float ) (a); \ } #define bli_dsscalcjs( conj, a, x ) \ { \ (x) *= ( float ) (a); \ } #define bli_csscalcjs( conj, a, x ) \ { \ (x) *= ( float ) (a).real; \ } #define bli_zsscalcjs( conj, a, x ) \ { \ (x) *= ( float ) (a).real; \ } #define bli_sdscalcjs( conj, a, x ) \ { \ (x) *= ( double ) (a); \ } #define bli_ddscalcjs( conj, a, x ) \ { \ (x) *= ( double ) (a); \ } #define bli_cdscalcjs( conj, a, x ) \ { \ (x) *= ( double ) (a).real; \ } #define bli_zdscalcjs( conj, a, x ) \ { \ (x) *= ( double ) (a).real; \ } #define bli_scscalcjs( conj, a, x ) \ { \ (x).real *= ( float ) (a); \ (x).imag *= ( float ) (a); \ } #define bli_dcscalcjs( conj, a, x ) \ { \ (x).real *= ( float ) (a); \ (x).imag *= ( float ) (a); \ } #define bli_ccscalcjs( conj, a, x ) \ { \ float aimag = ( bli_is_conj( conj ) ? ( float ) -(a).imag : \ ( float ) (a).imag ); \ float tempr = ( float ) (a).real * (x).real - ( float ) aimag * (x).imag; \ float tempi = ( float ) (a).real * (x).imag + ( float ) aimag * (x).real; \ (x).real = tempr; \ (x).imag = tempi; \ } #define bli_zcscalcjs( conj, a, x ) \ { \ float aimag = ( bli_is_conj( conj ) ? ( float ) -(a).imag : \ ( float ) (a).imag ); \ float tempr = ( float ) (a).real * (x).real - ( float ) aimag * (x).imag; \ float tempi = ( float ) (a).real * (x).imag + ( float ) aimag * (x).real; \ (x).real = tempr; \ (x).imag = tempi; \ } #define bli_szscalcjs( conj, a, x ) \ { \ (x).real *= ( double ) (a); \ (x).imag *= ( double ) (a); \ } #define bli_dzscalcjs( conj, a, x ) \ { \ (x).real *= ( double ) (a); \ (x).imag *= ( double ) (a); \ } #define bli_czscalcjs( conj, a, x ) \ { \ double aimag = ( bli_is_conj( conj ) ? ( double ) -(a).imag : \ ( double ) (a).imag ); \ double tempr = ( double ) (a).real * (x).real - ( double ) aimag * (x).imag; \ double tempi = ( double ) (a).real * (x).imag + ( double ) aimag * (x).real; \ (x).real = tempr; \ (x).imag = tempi; \ } #define bli_zzscalcjs( conj, a, x ) \ { \ double aimag = ( bli_is_conj( conj ) ? ( double ) -(a).imag : \ ( double ) (a).imag ); \ double tempr = ( double ) (a).real * (x).real - ( double ) aimag * (x).imag; \ double tempi = ( double ) (a).real * (x).imag + ( double ) aimag * (x).real; \ (x).real = tempr; \ (x).imag = tempi; \ } #define bli_sscalcjs( conj, a, x ) \ { \ bli_ssscalcjs( conj, a, x ); \ } #define bli_dscalcjs( conj, a, x ) \ { \ bli_ddscalcjs( conj, a, x ); \ } #define bli_cscalcjs( conj, a, x ) \ { \ bli_ccscalcjs( conj, a, x ); \ } #define bli_zscalcjs( conj, a, x ) \ { \ bli_zzscalcjs( conj, a, x ); \ } #endif blis-0.9.0/frame/include/level0/old/bli_set0ris_mxn.h000066400000000000000000000052041422157504600224140ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_SET0RIS_MXN_H #define BLIS_SET0RIS_MXN_H // set0ris_mxn #define bli_sset0ris_mxn( m, n, ar, ai, rs_a, cs_a ) \ { \ dim_t _i, _j; \ \ for ( _j = 0; _j < n; ++_j ) \ for ( _i = 0; _i < m; ++_i ) \ bli_sset0ris( *(ar + _i*rs_a + _j*cs_a), \ *(ai + _i*rs_a + _j*cs_a) ); \ } #define bli_dset0ris_mxn( m, n, ar, ai, rs_a, cs_a ) \ { \ dim_t _i, _j; \ \ for ( _j = 0; _j < n; ++_j ) \ for ( _i = 0; _i < m; ++_i ) \ bli_dset0ris( *(ar + _i*rs_a + _j*cs_a), \ *(ai + _i*rs_a + _j*cs_a) ); \ } #define bli_cset0ris_mxn( m, n, ar, ai, rs_a, cs_a ) \ { \ dim_t _i, _j; \ \ for ( _j = 0; _j < n; ++_j ) \ for ( _i = 0; _i < m; ++_i ) \ bli_cset0ris( *(ar + _i*rs_a + _j*cs_a), \ *(ai + _i*rs_a + _j*cs_a) ); \ } #define bli_zset0ris_mxn( m, n, ar, ai, rs_a, cs_a ) \ { \ dim_t _i, _j; \ \ for ( _j = 0; _j < n; ++_j ) \ for ( _i = 0; _i < m; ++_i ) \ bli_zset0ris( *(ar + _i*rs_a + _j*cs_a), \ *(ai + _i*rs_a + _j*cs_a) ); \ } #endif blis-0.9.0/frame/include/level0/old/io/000077500000000000000000000000001422157504600175505ustar00rootroot00000000000000blis-0.9.0/frame/include/level0/old/io/bli_scal2ios.h000066400000000000000000000041251422157504600222700ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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 copyiight notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyiight notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_SCAL2IOS_H #define BLIS_SCAL2IOS_H // scal2ios #define bli_cscal2ios( a, x, yi ) \ { \ (yi) = bli_cimag(a) * bli_creal(x) + bli_creal(a) * bli_cimag(x); \ } #define bli_zscal2ios( a, x, yi ) \ { \ (yi) = bli_zimag(a) * bli_zreal(x) + bli_zreal(a) * bli_zimag(x); \ } #define bli_scscal2ios( a, x, yi ) \ { \ (yi) = bli_creal(a) * bli_cimag(x); \ } #define bli_dzscal2ios( a, x, yi ) \ { \ (yi) = bli_zreal(a) * bli_zimag(x); \ } #endif blis-0.9.0/frame/include/level0/old/io/bli_scal2jios.h000066400000000000000000000036651422157504600224520ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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 copyiight notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyiight notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_SCAL2JIOS_H #define BLIS_SCAL2JIOS_H // scal2jios #define bli_cscal2jios( a, x, yi ) \ { \ (yi) = bli_cimag(a) * bli_creal(x) - bli_creal(a) * bli_cimag(x); \ } #define bli_zscal2jios( a, x, yi ) \ { \ (yi) = bli_zimag(a) * bli_zreal(x) - bli_zreal(a) * bli_zimag(x); \ } #endif blis-0.9.0/frame/include/level0/old/ri3/000077500000000000000000000000001422157504600176365ustar00rootroot00000000000000blis-0.9.0/frame/include/level0/old/ri3/bli_copyjri3s.h000066400000000000000000000041171422157504600225650ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_COPYJRI3S_H #define BLIS_COPYJRI3S_H // copyjri3s #define bli_scopyjri3s( ar, ai, br, bi, bri ) bli_scopyri3s( (ar), -(ai), (br), (bi), (bri) ) #define bli_dcopyjri3s( ar, ai, br, bi, bri ) bli_dcopyri3s( (ar), -(ai), (br), (bi), (bri) ) #define bli_ccopyjri3s( ar, ai, br, bi, bri ) bli_ccopyri3s( (ar), -(ai), (br), (bi), (bri) ) #define bli_zcopyjri3s( ar, ai, br, bi, bri ) bli_zcopyri3s( (ar), -(ai), (br), (bi), (bri) ) #endif blis-0.9.0/frame/include/level0/old/ri3/bli_copyri3s.h000066400000000000000000000040731422157504600224140ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_COPYRI3S_H #define BLIS_COPYRI3S_H // copyri3s #define bli_scopyri3s( ar, ai, br, bi, bri ) \ { \ (br) = (ar); \ } #define bli_dcopyri3s( ar, ai, br, bi, bri ) \ { \ (br) = (ar); \ } #define bli_ccopyri3s( ar, ai, br, bi, bri ) \ { \ (br) = (ar); \ (bi) = (ai); \ (bri) = (ar) + (ai); \ } #define bli_zcopyri3s( ar, ai, br, bi, bri ) \ { \ (br) = (ar); \ (bi) = (ai); \ (bri) = (ar) + (ai); \ } #endif blis-0.9.0/frame/include/level0/old/ri3/bli_scal2jri3s.h000066400000000000000000000047311422157504600226210ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_SCAL2JRI3S_H #define BLIS_SCAL2JRI3S_H // scal2jri3s #define bli_sscal2jri3s( ar, ai, xr, xi, yr, yi, yri ) \ { \ (yr) = (ar) * (xr); \ } #define bli_dscal2jri3s( ar, ai, xr, xi, yr, yi, yri ) \ { \ (yr) = (ar) * (xr); \ } #define bli_cscal2jri3s( ar, ai, xr, xi, yr, yi, yri ) \ { \ (yr) = (ar) * (xr) + (ai) * (xi); \ (yi) = (ai) * (xr) - (ar) * (xi); \ (yri) = (yr) + (yi); \ } #define bli_zscal2jri3s( ar, ai, xr, xi, yr, yi, yri ) \ { \ (yr) = (ar) * (xr) + (ai) * (xi); \ (yi) = (ai) * (xr) - (ar) * (xi); \ (yri) = (yr) + (yi); \ } #define bli_scscal2jri3s( ar, ai, xr, xi, yr, yi, yri ) \ { \ (yr) = (ar) * (xr); \ (yi) = (ar) * -(xi); \ (yri) = (yr) + (yi); \ } #define bli_dzscal2jri3s( ar, ai, xr, xi, yr, yi, yri ) \ { \ (yr) = (ar) * (xr); \ (yi) = (ar) * -(xi); \ (yri) = (yr) + (yi); \ } #endif blis-0.9.0/frame/include/level0/old/ri3/bli_scal2ri3s.h000066400000000000000000000047141422157504600224500ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_SCAL2RI3S_H #define BLIS_SCAL2RI3S_H // scal2ri3s #define bli_sscal2ri3s( ar, ai, xr, xi, yr, yi, yri ) \ { \ (yr) = (ar) * (xr); \ } #define bli_dscal2ri3s( ar, ai, xr, xi, yr, yi, yri ) \ { \ (yr) = (ar) * (xr); \ } #define bli_cscal2ri3s( ar, ai, xr, xi, yr, yi, yri ) \ { \ (yr) = (ar) * (xr) - (ai) * (xi); \ (yi) = (ai) * (xr) + (ar) * (xi); \ (yri) = (yr) + (yi); \ } #define bli_zscal2ri3s( ar, ai, xr, xi, yr, yi, yri ) \ { \ (yr) = (ar) * (xr) - (ai) * (xi); \ (yi) = (ai) * (xr) + (ar) * (xi); \ (yri) = (yr) + (yi); \ } #define bli_scscal2ri3s( ar, ai, xr, xi, yr, yi, yri ) \ { \ (yr) = (ar) * (xr); \ (yi) = (ar) * (xi); \ (yri) = (yr) + (yi); \ } #define bli_dzscal2ri3s( ar, ai, xr, xi, yr, yi, yri ) \ { \ (yr) = (ar) * (xr); \ (yi) = (ar) * (xi); \ (yri) = (yr) + (yi); \ } #endif blis-0.9.0/frame/include/level0/old/ri3/bli_scal2ri3s_mxn.h000066400000000000000000000132241422157504600233260ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_SCAL2RI3S_MXN_H #define BLIS_SCAL2RI3S_MXN_H // scal2ri3s_mxn BLIS_INLINE void bli_cscal2ri3s_mxn ( const conj_t conjx, const dim_t m, const dim_t n, scomplex* restrict alpha, scomplex* restrict x, const inc_t rs_x, const inc_t cs_x, scomplex* restrict y, const inc_t rs_y, const inc_t cs_y, const inc_t is_y ) { float* restrict alpha_r = ( float* )alpha; \ float* restrict alpha_i = ( float* )alpha + 1; \ float* restrict x_r = ( float* )x; \ float* restrict x_i = ( float* )x + 1; \ float* restrict y_r = ( float* )y; \ float* restrict y_i = ( float* )y + is_y; \ float* restrict y_rpi = ( float* )y + 2*is_y; \ const dim_t incx2 = 2*rs_x; \ const dim_t ldx2 = 2*cs_x; \ /* Treat the micro-panel as panel_dim x panel_len and column-stored (unit row stride). */ \ if ( bli_is_conj( conjx ) ) { for ( dim_t j = 0; j < n; ++j ) for ( dim_t i = 0; i < m; ++i ) { float* restrict chi11_r = x_r + (i )*incx2 + (j )*ldx2; float* restrict chi11_i = x_i + (i )*incx2 + (j )*ldx2; float* restrict psi11_r = y_r + (i )*1 + (j )*cs_y; float* restrict psi11_i = y_i + (i )*1 + (j )*cs_y; float* restrict psi11_rpi = y_rpi + (i )*1 + (j )*cs_y; bli_cscal2jri3s ( *alpha_r, *alpha_i, *chi11_r, *chi11_i, *psi11_r, *psi11_i, *psi11_rpi ); } } else /* if ( bli_is_noconj( conjx ) ) */ { for ( dim_t j = 0; j < n; ++j ) for ( dim_t i = 0; i < m; ++i ) { float* restrict chi11_r = x_r + (i )*incx2 + (j )*ldx2; float* restrict chi11_i = x_i + (i )*incx2 + (j )*ldx2; float* restrict psi11_r = y_r + (i )*1 + (j )*cs_y; float* restrict psi11_i = y_i + (i )*1 + (j )*cs_y; float* restrict psi11_rpi = y_rpi + (i )*1 + (j )*cs_y; bli_cscal2ri3s ( *alpha_r, *alpha_i, *chi11_r, *chi11_i, *psi11_r, *psi11_i, *psi11_rpi ); } } } BLIS_INLINE void bli_zscal2ri3s_mxn ( const conj_t conjx, const dim_t m, const dim_t n, dcomplex* restrict alpha, dcomplex* restrict x, const inc_t rs_x, const inc_t cs_x, dcomplex* restrict y, const inc_t rs_y, const inc_t cs_y, const inc_t is_y ) { double* restrict alpha_r = ( double* )alpha; \ double* restrict alpha_i = ( double* )alpha + 1; \ double* restrict x_r = ( double* )x; \ double* restrict x_i = ( double* )x + 1; \ double* restrict y_r = ( double* )y; \ double* restrict y_i = ( double* )y + is_y; \ double* restrict y_rpi = ( double* )y + 2*is_y; \ const dim_t incx2 = 2*rs_x; \ const dim_t ldx2 = 2*cs_x; \ /* Treat the micro-panel as panel_dim x panel_len and column-stored (unit row stride). */ \ if ( bli_is_conj( conjx ) ) { for ( dim_t j = 0; j < n; ++j ) for ( dim_t i = 0; i < m; ++i ) { double* restrict chi11_r = x_r + (i )*incx2 + (j )*ldx2; double* restrict chi11_i = x_i + (i )*incx2 + (j )*ldx2; double* restrict psi11_r = y_r + (i )*1 + (j )*cs_y; double* restrict psi11_i = y_i + (i )*1 + (j )*cs_y; double* restrict psi11_rpi = y_rpi + (i )*1 + (j )*cs_y; bli_zscal2jri3s ( *alpha_r, *alpha_i, *chi11_r, *chi11_i, *psi11_r, *psi11_i, *psi11_rpi ); } } else /* if ( bli_is_noconj( conjx ) ) */ { for ( dim_t j = 0; j < n; ++j ) for ( dim_t i = 0; i < m; ++i ) { double* restrict chi11_r = x_r + (i )*incx2 + (j )*ldx2; double* restrict chi11_i = x_i + (i )*incx2 + (j )*ldx2; double* restrict psi11_r = y_r + (i )*1 + (j )*cs_y; double* restrict psi11_i = y_i + (i )*1 + (j )*cs_y; double* restrict psi11_rpi = y_rpi + (i )*1 + (j )*cs_y; bli_zscal2ri3s ( *alpha_r, *alpha_i, *chi11_r, *chi11_i, *psi11_r, *psi11_i, *psi11_rpi ); } } } #endif blis-0.9.0/frame/include/level0/old/rih/000077500000000000000000000000001422157504600177235ustar00rootroot00000000000000blis-0.9.0/frame/include/level0/old/rih/bli_scal2rihs_mxn.h000066400000000000000000000152641422157504600235060ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_SCAL2RIHS_MXN_H #define BLIS_SCAL2RIHS_MXN_H // scal2rihs_mxn BLIS_INLINE void bli_cscal2rihs_mxn ( const pack_t schema, const conj_t conjx, const dim_t m, const dim_t n, scomplex* restrict alpha, scomplex* restrict x, const inc_t rs_x, const inc_t cs_x, scomplex* restrict y, const inc_t rs_y, const inc_t cs_y ) { scomplex* restrict x_r = x; float* restrict y_r = ( float* )y; if ( bli_is_ro_packed( schema ) ) { if ( bli_is_conj( conjx ) ) { for ( dim_t j = 0; j < n; ++j ) for ( dim_t i = 0; i < m; ++i ) { scomplex* restrict chi11 = x_r + (i )*rs_x + (j )*cs_x; float* restrict psi11_r = y_r + (i )*rs_y + (j )*cs_y; bli_cscal2jros ( *alpha, *chi11, *psi11_r ); } } else /* if ( bli_is_noconj( conjx ) ) */ { for ( dim_t j = 0; j < n; ++j ) for ( dim_t i = 0; i < m; ++i ) { scomplex* restrict chi11 = x_r + (i )*rs_x + (j )*cs_x; float* restrict psi11_r = y_r + (i )*rs_y + (j )*cs_y; bli_cscal2ros ( *alpha, *chi11, *psi11_r ); } } } else if ( bli_is_io_packed( schema ) ) { if ( bli_is_conj( conjx ) ) { for ( dim_t j = 0; j < n; ++j ) for ( dim_t i = 0; i < m; ++i ) { scomplex* restrict chi11 = x_r + (i )*rs_x + (j )*cs_x; float* restrict psi11_r = y_r + (i )*rs_y + (j )*cs_y; bli_cscal2jios ( *alpha, *chi11, *psi11_r ); } } else /* if ( bli_is_noconj( conjx ) ) */ { for ( dim_t j = 0; j < n; ++j ) for ( dim_t i = 0; i < m; ++i ) { scomplex* restrict chi11 = x_r + (i )*rs_x + (j )*cs_x; float* restrict psi11_r = y_r + (i )*rs_y + (j )*cs_y; bli_cscal2ios ( *alpha, *chi11, *psi11_r ); } } } else /* if ( bli_is_rpi_packed( schema ) ) */ { if ( bli_is_conj( conjx ) ) { for ( dim_t j = 0; j < n; ++j ) for ( dim_t i = 0; i < m; ++i ) { scomplex* restrict chi11 = x_r + (i )*rs_x + (j )*cs_x; float* restrict psi11_r = y_r + (i )*rs_y + (j )*cs_y; bli_cscal2jrpis ( *alpha, *chi11, *psi11_r ); } } else /* if ( bli_is_noconj( conjx ) ) */ { for ( dim_t j = 0; j < n; ++j ) for ( dim_t i = 0; i < m; ++i ) { scomplex* restrict chi11 = x_r + (i )*rs_x + (j )*cs_x; float* restrict psi11_r = y_r + (i )*rs_y + (j )*cs_y; bli_cscal2rpis ( *alpha, *chi11, *psi11_r ); } } } } BLIS_INLINE void bli_zscal2rihs_mxn ( const pack_t schema, const conj_t conjx, const dim_t m, const dim_t n, dcomplex* restrict alpha, dcomplex* restrict x, const inc_t rs_x, const inc_t cs_x, dcomplex* restrict y, const inc_t rs_y, const inc_t cs_y ) { dcomplex* restrict x_r = x; double* restrict y_r = ( double* )y; if ( bli_is_ro_packed( schema ) ) { if ( bli_is_conj( conjx ) ) { for ( dim_t j = 0; j < n; ++j ) for ( dim_t i = 0; i < m; ++i ) { dcomplex* restrict chi11 = x_r + (i )*rs_x + (j )*cs_x; double* restrict psi11_r = y_r + (i )*rs_y + (j )*cs_y; bli_zscal2jros ( *alpha, *chi11, *psi11_r ); } } else /* if ( bli_is_noconj( conjx ) ) */ { for ( dim_t j = 0; j < n; ++j ) for ( dim_t i = 0; i < m; ++i ) { dcomplex* restrict chi11 = x_r + (i )*rs_x + (j )*cs_x; double* restrict psi11_r = y_r + (i )*rs_y + (j )*cs_y; bli_zscal2ros ( *alpha, *chi11, *psi11_r ); } } } else if ( bli_is_io_packed( schema ) ) { if ( bli_is_conj( conjx ) ) { for ( dim_t j = 0; j < n; ++j ) for ( dim_t i = 0; i < m; ++i ) { dcomplex* restrict chi11 = x_r + (i )*rs_x + (j )*cs_x; double* restrict psi11_r = y_r + (i )*rs_y + (j )*cs_y; bli_zscal2jios ( *alpha, *chi11, *psi11_r ); } } else /* if ( bli_is_noconj( conjx ) ) */ { for ( dim_t j = 0; j < n; ++j ) for ( dim_t i = 0; i < m; ++i ) { dcomplex* restrict chi11 = x_r + (i )*rs_x + (j )*cs_x; double* restrict psi11_r = y_r + (i )*rs_y + (j )*cs_y; bli_zscal2ios ( *alpha, *chi11, *psi11_r ); } } } else /* if ( bli_is_rpi_packed( schema ) ) */ { if ( bli_is_conj( conjx ) ) { for ( dim_t j = 0; j < n; ++j ) for ( dim_t i = 0; i < m; ++i ) { dcomplex* restrict chi11 = x_r + (i )*rs_x + (j )*cs_x; double* restrict psi11_r = y_r + (i )*rs_y + (j )*cs_y; bli_zscal2jrpis ( *alpha, *chi11, *psi11_r ); } } else /* if ( bli_is_noconj( conjx ) ) */ { for ( dim_t j = 0; j < n; ++j ) for ( dim_t i = 0; i < m; ++i ) { dcomplex* restrict chi11 = x_r + (i )*rs_x + (j )*cs_x; double* restrict psi11_r = y_r + (i )*rs_y + (j )*cs_y; bli_zscal2rpis ( *alpha, *chi11, *psi11_r ); } } } } #endif blis-0.9.0/frame/include/level0/old/rih/bli_scal2rihs_mxn_diag.h000066400000000000000000000067241422157504600244730ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_SCAL2RIHS_MXN_DIAG_H #define BLIS_SCAL2RIHS_MXN_DIAG_H // scal2rihs_mxn_diag #define bli_cscscal2rihs_mxn_diag( schema, m, n, a, x, rs_x, cs_x, y_r, rs_y, cs_y ) \ { \ dim_t min_m_n = bli_min( m, n ); \ dim_t _i; \ \ /* Handle ro, io, and rpi separately. */ \ if ( bli_is_ro_packed( schema ) ) \ { \ for ( _i = 0; _i < min_m_n; ++_i ) \ { \ bli_scscal2ros( *(x + _i*rs_x + _i*cs_x), \ *(a), \ *(y_r + _i*rs_y + _i*cs_y) ); \ } \ } \ else if ( bli_is_io_packed( schema ) ) \ { \ for ( _i = 0; _i < min_m_n; ++_i ) \ { \ bli_scscal2ios( *(x + _i*rs_x + _i*cs_x), \ *(a), \ *(y_r + _i*rs_y + _i*cs_y) ); \ } \ } \ else /* if ( bli_is_rpi_packed( schema ) ) */ \ { \ for ( _i = 0; _i < min_m_n; ++_i ) \ { \ bli_scscal2rpis( *(x + _i*rs_x + _i*cs_x), \ *(a), \ *(y_r + _i*rs_y + _i*cs_y) ); \ } \ } \ } #define bli_zdzscal2rihs_mxn_diag( schema, m, n, a, x, rs_x, cs_x, y_r, rs_y, cs_y ) \ { \ dim_t min_m_n = bli_min( m, n ); \ dim_t _i; \ \ /* Handle ro, io, and rpi separately. */ \ if ( bli_is_ro_packed( schema ) ) \ { \ for ( _i = 0; _i < min_m_n; ++_i ) \ { \ bli_dzscal2ros( *(x + _i*rs_x + _i*cs_x), \ *(a), \ *(y_r + _i*rs_y + _i*cs_y) ); \ } \ } \ else if ( bli_is_io_packed( schema ) ) \ { \ for ( _i = 0; _i < min_m_n; ++_i ) \ { \ bli_dzscal2ios( *(x + _i*rs_x + _i*cs_x), \ *(a), \ *(y_r + _i*rs_y + _i*cs_y) ); \ } \ } \ else /* if ( bli_is_rpi_packed( schema ) ) */ \ { \ for ( _i = 0; _i < min_m_n; ++_i ) \ { \ bli_dzscal2rpis( *(x + _i*rs_x + _i*cs_x), \ *(a), \ *(y_r + _i*rs_y + _i*cs_y) ); \ } \ } \ } #endif blis-0.9.0/frame/include/level0/old/rih/bli_scal2rihs_mxn_uplo.h000066400000000000000000000226141422157504600245420ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_SCAL2RIHS_MXN_UPLO_H #define BLIS_SCAL2RIHS_MXN_UPLO_H // scal2rihs_mxn_uplo #define bli_cscal2rihs_mxn_uplo( schema, uplo, conjx, m, a, x, rs_x, cs_x, y_r, rs_y, cs_y ) \ { \ dim_t _i, _j; \ \ /* Handle ro, io, and rpi separately. */ \ if ( bli_is_ro_packed( schema ) ) \ { \ if ( bli_is_lower( uplo ) ) \ { \ if ( bli_is_conj( conjx ) ) \ { \ for ( _j = 0; _j < m; ++_j ) \ for ( _i = _j; _i < m; ++_i ) \ { \ bli_cscal2jros( *(a), \ *(x + _i*rs_x + _j*cs_x), \ *(y_r + _i*rs_y + _j*cs_y) ); \ } \ } \ else /* if ( bli_is_noconj( conjx ) ) */ \ { \ for ( _j = 0; _j < m; ++_j ) \ for ( _i = _j; _i < m; ++_i ) \ { \ bli_cscal2ros( *(a), \ *(x + _i*rs_x + _j*cs_x), \ *(y_r + _i*rs_y + _j*cs_y) ); \ } \ } \ } \ else /* if ( bli_is_upper( uplo ) ) */ \ { \ if ( bli_is_conj( conjx ) ) \ { \ for ( _j = 0; _j < m; ++_j ) \ for ( _i = 0; _i < _j + 1; ++_i ) \ { \ bli_cscal2jros( *(a), \ *(x + _i*rs_x + _j*cs_x), \ *(y_r + _i*rs_y + _j*cs_y) ); \ } \ } \ else /* if ( bli_is_noconj( conjx ) ) */ \ { \ for ( _j = 0; _j < m; ++_j ) \ for ( _i = 0; _i < _j + 1; ++_i ) \ { \ bli_cscal2ros( *(a), \ *(x + _i*rs_x + _j*cs_x), \ *(y_r + _i*rs_y + _j*cs_y) ); \ } \ } \ } \ } \ else if ( bli_is_io_packed( schema ) ) \ { \ if ( bli_is_lower( uplo ) ) \ { \ if ( bli_is_conj( conjx ) ) \ { \ for ( _j = 0; _j < m; ++_j ) \ for ( _i = _j; _i < m; ++_i ) \ { \ bli_cscal2jios( *(a), \ *(x + _i*rs_x + _j*cs_x), \ *(y_r + _i*rs_y + _j*cs_y) ); \ } \ } \ else /* if ( bli_is_noconj( conjx ) ) */ \ { \ for ( _j = 0; _j < m; ++_j ) \ for ( _i = _j; _i < m; ++_i ) \ { \ bli_cscal2ios( *(a), \ *(x + _i*rs_x + _j*cs_x), \ *(y_r + _i*rs_y + _j*cs_y) ); \ } \ } \ } \ else /* if ( bli_is_upper( uplo ) ) */ \ { \ if ( bli_is_conj( conjx ) ) \ { \ for ( _j = 0; _j < m; ++_j ) \ for ( _i = 0; _i < _j + 1; ++_i ) \ { \ bli_cscal2jios( *(a), \ *(x + _i*rs_x + _j*cs_x), \ *(y_r + _i*rs_y + _j*cs_y) ); \ } \ } \ else /* if ( bli_is_noconj( conjx ) ) */ \ { \ for ( _j = 0; _j < m; ++_j ) \ for ( _i = 0; _i < _j + 1; ++_i ) \ { \ bli_cscal2ios( *(a), \ *(x + _i*rs_x + _j*cs_x), \ *(y_r + _i*rs_y + _j*cs_y) ); \ } \ } \ } \ } \ else /* if ( bli_is_rpi_packed( schema ) ) */ \ { \ if ( bli_is_lower( uplo ) ) \ { \ if ( bli_is_conj( conjx ) ) \ { \ for ( _j = 0; _j < m; ++_j ) \ for ( _i = _j; _i < m; ++_i ) \ { \ bli_cscal2jrpis( *(a), \ *(x + _i*rs_x + _j*cs_x), \ *(y_r + _i*rs_y + _j*cs_y) ); \ } \ } \ else /* if ( bli_is_noconj( conjx ) ) */ \ { \ for ( _j = 0; _j < m; ++_j ) \ for ( _i = _j; _i < m; ++_i ) \ { \ bli_cscal2rpis( *(a), \ *(x + _i*rs_x + _j*cs_x), \ *(y_r + _i*rs_y + _j*cs_y) ); \ } \ } \ } \ else /* if ( bli_is_upper( uplo ) ) */ \ { \ if ( bli_is_conj( conjx ) ) \ { \ for ( _j = 0; _j < m; ++_j ) \ for ( _i = 0; _i < _j + 1; ++_i ) \ { \ bli_cscal2jrpis( *(a), \ *(x + _i*rs_x + _j*cs_x), \ *(y_r + _i*rs_y + _j*cs_y) ); \ } \ } \ else /* if ( bli_is_noconj( conjx ) ) */ \ { \ for ( _j = 0; _j < m; ++_j ) \ for ( _i = 0; _i < _j + 1; ++_i ) \ { \ bli_cscal2rpis( *(a), \ *(x + _i*rs_x + _j*cs_x), \ *(y_r + _i*rs_y + _j*cs_y) ); \ } \ } \ } \ } \ } #define bli_zscal2rihs_mxn_uplo( schema, uplo, conjx, m, a, x, rs_x, cs_x, y_r, rs_y, cs_y ) \ { \ dim_t _i, _j; \ \ /* Handle ro, io, and rpi separately. */ \ if ( bli_is_ro_packed( schema ) ) \ { \ if ( bli_is_lower( uplo ) ) \ { \ if ( bli_is_conj( conjx ) ) \ { \ for ( _j = 0; _j < m; ++_j ) \ for ( _i = _j; _i < m; ++_i ) \ { \ bli_zscal2jros( *(a), \ *(x + _i*rs_x + _j*cs_x), \ *(y_r + _i*rs_y + _j*cs_y) ); \ } \ } \ else /* if ( bli_is_noconj( conjx ) ) */ \ { \ for ( _j = 0; _j < m; ++_j ) \ for ( _i = _j; _i < m; ++_i ) \ { \ bli_zscal2ros( *(a), \ *(x + _i*rs_x + _j*cs_x), \ *(y_r + _i*rs_y + _j*cs_y) ); \ } \ } \ } \ else /* if ( bli_is_upper( uplo ) ) */ \ { \ if ( bli_is_conj( conjx ) ) \ { \ for ( _j = 0; _j < m; ++_j ) \ for ( _i = 0; _i < _j + 1; ++_i ) \ { \ bli_zscal2jros( *(a), \ *(x + _i*rs_x + _j*cs_x), \ *(y_r + _i*rs_y + _j*cs_y) ); \ } \ } \ else /* if ( bli_is_noconj( conjx ) ) */ \ { \ for ( _j = 0; _j < m; ++_j ) \ for ( _i = 0; _i < _j + 1; ++_i ) \ { \ bli_zscal2ros( *(a), \ *(x + _i*rs_x + _j*cs_x), \ *(y_r + _i*rs_y + _j*cs_y) ); \ } \ } \ } \ } \ else if ( bli_is_io_packed( schema ) ) \ { \ if ( bli_is_lower( uplo ) ) \ { \ if ( bli_is_conj( conjx ) ) \ { \ for ( _j = 0; _j < m; ++_j ) \ for ( _i = _j; _i < m; ++_i ) \ { \ bli_zscal2jios( *(a), \ *(x + _i*rs_x + _j*cs_x), \ *(y_r + _i*rs_y + _j*cs_y) ); \ } \ } \ else /* if ( bli_is_noconj( conjx ) ) */ \ { \ for ( _j = 0; _j < m; ++_j ) \ for ( _i = _j; _i < m; ++_i ) \ { \ bli_zscal2ios( *(a), \ *(x + _i*rs_x + _j*cs_x), \ *(y_r + _i*rs_y + _j*cs_y) ); \ } \ } \ } \ else /* if ( bli_is_upper( uplo ) ) */ \ { \ if ( bli_is_conj( conjx ) ) \ { \ for ( _j = 0; _j < m; ++_j ) \ for ( _i = 0; _i < _j + 1; ++_i ) \ { \ bli_zscal2jios( *(a), \ *(x + _i*rs_x + _j*cs_x), \ *(y_r + _i*rs_y + _j*cs_y) ); \ } \ } \ else /* if ( bli_is_noconj( conjx ) ) */ \ { \ for ( _j = 0; _j < m; ++_j ) \ for ( _i = 0; _i < _j + 1; ++_i ) \ { \ bli_zscal2ios( *(a), \ *(x + _i*rs_x + _j*cs_x), \ *(y_r + _i*rs_y + _j*cs_y) ); \ } \ } \ } \ } \ else /* if ( bli_is_rpi_packed( schema ) ) */ \ { \ if ( bli_is_lower( uplo ) ) \ { \ if ( bli_is_conj( conjx ) ) \ { \ for ( _j = 0; _j < m; ++_j ) \ for ( _i = _j; _i < m; ++_i ) \ { \ bli_zscal2jrpis( *(a), \ *(x + _i*rs_x + _j*cs_x), \ *(y_r + _i*rs_y + _j*cs_y) ); \ } \ } \ else /* if ( bli_is_noconj( conjx ) ) */ \ { \ for ( _j = 0; _j < m; ++_j ) \ for ( _i = _j; _i < m; ++_i ) \ { \ bli_zscal2rpis( *(a), \ *(x + _i*rs_x + _j*cs_x), \ *(y_r + _i*rs_y + _j*cs_y) ); \ } \ } \ } \ else /* if ( bli_is_upper( uplo ) ) */ \ { \ if ( bli_is_conj( conjx ) ) \ { \ for ( _j = 0; _j < m; ++_j ) \ for ( _i = 0; _i < _j + 1; ++_i ) \ { \ bli_zscal2jrpis( *(a), \ *(x + _i*rs_x + _j*cs_x), \ *(y_r + _i*rs_y + _j*cs_y) ); \ } \ } \ else /* if ( bli_is_noconj( conjx ) ) */ \ { \ for ( _j = 0; _j < m; ++_j ) \ for ( _i = 0; _i < _j + 1; ++_i ) \ { \ bli_zscal2rpis( *(a), \ *(x + _i*rs_x + _j*cs_x), \ *(y_r + _i*rs_y + _j*cs_y) ); \ } \ } \ } \ } \ } #endif blis-0.9.0/frame/include/level0/old/rih/bli_setrihs_mxn_diag.h000066400000000000000000000065221422157504600242560ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_SETRIHS_MXN_DIAG_H #define BLIS_SETRIHS_MXN_DIAG_H // setrihs_mxn_diag #define bli_csetrihs_mxn_diag( schema, m, n, a, y_r, rs_y, cs_y ) \ { \ const float a_r = bli_zreal( *a ); \ const float a_i = bli_zimag( *a ); \ dim_t min_m_n = bli_min( m, n ); \ dim_t _i; \ \ /* Handle ro, io, and rpi separately. */ \ if ( bli_is_ro_packed( schema ) ) \ { \ for ( _i = 0; _i < min_m_n; ++_i ) \ { \ bli_scopys( (a_r), \ *(y_r + _i*rs_y + _i*cs_y) ); \ } \ } \ else if ( bli_is_io_packed( schema ) ) \ { \ for ( _i = 0; _i < min_m_n; ++_i ) \ { \ bli_scopys( (a_i), \ *(y_r + _i*rs_y + _i*cs_y) ); \ } \ } \ else /* if ( bli_is_rpi_packed( schema ) ) */ \ { \ for ( _i = 0; _i < min_m_n; ++_i ) \ { \ bli_sadd3s( (a_r), \ (a_i), \ *(y_r + _i*rs_y + _i*cs_y) ); \ } \ } \ } #define bli_zsetrihs_mxn_diag( schema, m, n, a, y_r, rs_y, cs_y ) \ { \ const double a_r = bli_zreal( *a ); \ const double a_i = bli_zimag( *a ); \ dim_t min_m_n = bli_min( m, n ); \ dim_t _i; \ \ /* Handle ro, io, and rpi separately. */ \ if ( bli_is_ro_packed( schema ) ) \ { \ for ( _i = 0; _i < min_m_n; ++_i ) \ { \ bli_dcopys( (a_r), \ *(y_r + _i*rs_y + _i*cs_y) ); \ } \ } \ else if ( bli_is_io_packed( schema ) ) \ { \ for ( _i = 0; _i < min_m_n; ++_i ) \ { \ bli_dcopys( (a_i), \ *(y_r + _i*rs_y + _i*cs_y) ); \ } \ } \ else /* if ( bli_is_rpi_packed( schema ) ) */ \ { \ for ( _i = 0; _i < min_m_n; ++_i ) \ { \ bli_dadd3s( (a_r), \ (a_i), \ *(y_r + _i*rs_y + _i*cs_y) ); \ } \ } \ } #endif blis-0.9.0/frame/include/level0/old/ro/000077500000000000000000000000001422157504600175615ustar00rootroot00000000000000blis-0.9.0/frame/include/level0/old/ro/bli_scal2jros.h000066400000000000000000000036641422157504600224730ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_SCAL2JROS_H #define BLIS_SCAL2JROS_H // scal2jros #define bli_cscal2jros( a, x, yr ) \ { \ (yr) = bli_creal(a) * bli_creal(x) + bli_cimag(a) * bli_cimag(x); \ } #define bli_zscal2jros( a, x, yr ) \ { \ (yr) = bli_zreal(a) * bli_zreal(x) + bli_zimag(a) * bli_zimag(x); \ } #endif blis-0.9.0/frame/include/level0/old/ro/bli_scal2ros.h000066400000000000000000000041261422157504600223130ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_SCAL2ROS_H #define BLIS_SCAL2ROS_H // scal2ros #define bli_cscal2ros( a, x, yr ) \ { \ (yr) = bli_creal(a) * bli_creal(x) - bli_cimag(a) * bli_cimag(x); \ } #define bli_zscal2ros( a, x, yr ) \ { \ (yr) = bli_zreal(a) * bli_zreal(x) - bli_zimag(a) * bli_zimag(x); \ } #define bli_scscal2ros( a, x, yr ) \ { \ (yr) = bli_creal(a) * bli_creal(x); \ } #define bli_dzscal2ros( a, x, yr ) \ { \ (yr) = bli_zreal(a) * bli_zreal(x); \ } #endif blis-0.9.0/frame/include/level0/old/rpi/000077500000000000000000000000001422157504600177335ustar00rootroot00000000000000blis-0.9.0/frame/include/level0/old/rpi/bli_scal2jrpis.h000066400000000000000000000040311422157504600230040ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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 copyrpiight notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyrpiight notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_SCAL2JRPIS_H #define BLIS_SCAL2JRPIS_H // scal2jrpis #define bli_cscal2jrpis( a, x, yrpi ) \ { \ (yrpi) = (bli_creal(a)+bli_cimag(a)) * bli_creal(x) + \ (bli_cimag(a)-bli_creal(a)) * bli_cimag(x); \ } #define bli_zscal2jrpis( a, x, yrpi ) \ { \ (yrpi) = (bli_zreal(a)+bli_zimag(a)) * bli_zreal(x) + \ (bli_zimag(a)-bli_zreal(a)) * bli_zimag(x); \ } #endif blis-0.9.0/frame/include/level0/old/rpi/bli_scal2rpis.h000066400000000000000000000044251422157504600226410ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_SCAL2RPIS_H #define BLIS_SCAL2RPIS_H // scal2rpis #define bli_cscal2rpis( a, x, yrpi ) \ { \ (yrpi) = (bli_creal(a)+bli_cimag(a)) * bli_creal(x) + \ (bli_creal(a)-bli_cimag(a)) * bli_cimag(x); \ } #define bli_zscal2rpis( a, x, yrpi ) \ { \ (yrpi) = (bli_zreal(a)+bli_zimag(a)) * bli_zreal(x) + \ (bli_zreal(a)-bli_zimag(a)) * bli_zimag(x); \ } #define bli_scscal2rpis( a, x, yrpi ) \ { \ (yrpi) = bli_creal(a) * bli_creal(x) + \ bli_creal(a) * bli_cimag(x); \ } #define bli_dzscal2rpis( a, x, yrpi ) \ { \ (yrpi) = bli_zreal(a) * bli_zreal(x) + \ bli_zreal(a) * bli_zimag(x); \ } #endif blis-0.9.0/frame/include/level0/ri/000077500000000000000000000000001422157504600167755ustar00rootroot00000000000000blis-0.9.0/frame/include/level0/ri/bli_absq2ris.h000066400000000000000000000040521422157504600215230ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_ABSQ2RIS_H #define BLIS_ABSQ2RIS_H // absq2ris #define bli_sabsq2ris( ar, ai, br, bi ) \ { \ (br) = (ar) * (ar); \ } #define bli_dabsq2ris( ar, ai, br, bi ) \ { \ (br) = (ar) * (ar); \ } #define bli_cabsq2ris( ar, ai, br, bi ) \ { \ (br) = (ar) * (ar) + (ai) * (ai); \ (bi) = 0.0F; \ } #define bli_zabsq2ris( ar, ai, br, bi ) \ { \ (br) = (ar) * (ar) + (ai) * (ai); \ (bi) = 0.0; \ } #endif blis-0.9.0/frame/include/level0/ri/bli_abval2ris.h000066400000000000000000000047021422157504600216640ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_ABVAL2RIS_H #define BLIS_ABVAL2RIS_H // abval2ris #define bli_sabval2ris( xr, xi, ar, ai ) \ { \ (ar) = fabsf(xr); \ } #define bli_dabval2ris( xr, xi, ar, ai ) \ { \ (ar) = fabs(xr); \ } #define bli_cabval2ris( xr, xi, ar, ai ) \ { \ float s = bli_fmaxabs( (xr), (xi) ); \ float mag; \ if ( s == 0.0F ) mag = 0.0F; \ else \ { \ mag = sqrtf( s ) * \ sqrtf( ( (xr) / s ) * (xr) + \ ( (xi) / s ) * (xi) ); \ } \ (ar) = mag; \ (ai) = 0.0F; \ } #define bli_zabval2ris( xr, xi, ar, ai ) \ { \ double s = bli_fmaxabs( (xr), (xi) ); \ double mag; \ if ( s == 0.0 ) mag = 0.0; \ else \ { \ mag = sqrt( s ) * \ sqrt( ( (xr) / s ) * (xr) + \ ( (xi) / s ) * (xi) ); \ } \ (ar) = mag; \ (ai) = 0.0; \ } #endif blis-0.9.0/frame/include/level0/ri/bli_add3ris.h000066400000000000000000000040661422157504600213330ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_ADD3RIS_H #define BLIS_ADD3RIS_H // add3ris #define bli_sadd3ris( ar, ai, br, bi, cr, ci ) \ { \ (cr) = (ar) + (br); \ } #define bli_dadd3ris( ar, ai, br, bi, cr, ci ) \ { \ (cr) = (ar) + (br); \ } #define bli_cadd3ris( ar, ai, br, bi, cr, ci ) \ { \ (cr) = (ar) + (br); \ (ci) = (ai) + (bi); \ } #define bli_zadd3ris( ar, ai, br, bi, cr, ci ) \ { \ (cr) = (ar) + (br); \ (ci) = (ai) + (bi); \ } #endif blis-0.9.0/frame/include/level0/ri/bli_addjris.h000066400000000000000000000040111422157504600214100ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_ADDJRIS_H #define BLIS_ADDJRIS_H // addjris #define bli_saddjris( ar, ai, xr, xi ) bli_saddris( (ar), -(ai), (xr), (xi) ) #define bli_daddjris( ar, ai, xr, xi ) bli_daddris( (ar), -(ai), (xr), (xi) ) #define bli_caddjris( ar, ai, xr, xi ) bli_caddris( (ar), -(ai), (xr), (xi) ) #define bli_zaddjris( ar, ai, xr, xi ) bli_zaddris( (ar), -(ai), (xr), (xi) ) #endif blis-0.9.0/frame/include/level0/ri/bli_addris.h000066400000000000000000000040171422157504600212440ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_ADDRIS_H #define BLIS_ADDRIS_H // addris #define bli_saddris( ar, ai, xr, xi ) \ { \ (xr) = (xr) + (ar); \ } #define bli_daddris( ar, ai, xr, xi ) \ { \ (xr) = (xr) + (ar); \ } #define bli_caddris( ar, ai, xr, xi ) \ { \ (xr) = (xr) + (ar); \ (xi) = (xi) + (ai); \ } #define bli_zaddris( ar, ai, xr, xi ) \ { \ (xr) = (xr) + (ar); \ (xi) = (xi) + (ai); \ } #endif blis-0.9.0/frame/include/level0/ri/bli_axmyris.h000066400000000000000000000045061422157504600214750ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_AXMYRIS_H #define BLIS_AXMYRIS_H // axmyris #define bli_saxmyris( ar, ai, xr, xi, yr, yi ) \ { \ (yr) -= (ar) * (xr); \ } #define bli_daxmyris( ar, ai, xr, xi, yr, yi ) \ { \ (yr) -= (ar) * (xr); \ } #define bli_caxmyris( ar, ai, xr, xi, yr, yi ) \ { \ (yr) -= (ar) * (xr) - (ai) * (xi); \ (yi) -= (ai) * (xr) + (ar) * (xi); \ } #define bli_zaxmyris( ar, ai, xr, xi, yr, yi ) \ { \ (yr) -= (ar) * (xr) - (ai) * (xi); \ (yi) -= (ai) * (xr) + (ar) * (xi); \ } #define bli_scaxmyris( ar, ai, xr, xi, yr, yi ) \ { \ (yr) -= (ar) * (xr); \ (yi) -= (ar) * (xi); \ } #define bli_dzaxmyris( ar, ai, xr, xi, yr, yi ) \ { \ (yr) -= (ar) * (xr); \ (yi) -= (ar) * (xi); \ } #endif blis-0.9.0/frame/include/level0/ri/bli_axpbyjris.h000066400000000000000000000065041422157504600220140ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_AXPBYJRIS_H #define BLIS_AXPBYJRIS_H // axpbyjris #define bli_rxaxpbyjris( ar, ai, xr, xi, br, bi, yr, yi ) \ { \ (yr) = (ar) * (xr) + (br) * (yr); \ } #define bli_cxaxpbyjris( ar, ai, xr, xi, br, bi, yr, yi ) \ { \ const __typeof__(yr) yt_r = (ar) * (xr) + (ai) * (xi) + (br) * (yr) - (bi) * (yi); \ const __typeof__(yi) yt_i = (ai) * (xr) - (ar) * (xi) + (bi) * (yr) + (br) * (yi); \ (yr) = yt_r; \ (yi) = yt_i; \ } // Notes: // - The first char encodes the type of a. // - The second char encodes the type of x. // - The third char encodes the type of b. // - The fourth char encodes the type of y. // -- (axby) = (??ss) ---------------------------------------------------------- #define bli_ssssxpbyjris bli_rxxpbyjris #define bli_dsssxpbyjris bli_rxxpbyjris #define bli_csssxpbyjris bli_rxxpbyjris #define bli_zsssxpbyjris bli_rxxpbyjris #define bli_sdssxpbyjris bli_rxxpbyjris #define bli_ddssxpbyjris bli_rxxpbyjris #define bli_cdssxpbyjris bli_rxxpbyjris #define bli_zdssxpbyjris bli_rxxpbyjris #define bli_scssxpbyjris bli_rxxpbyjris #define bli_dcssxpbyjris bli_rxxpbyjris #define bli_ccssxpbyjris bli_rxxpbyjris #define bli_zcssxpbyjris bli_rxxpbyjris #define bli_szssxpbyjris bli_rxxpbyjris #define bli_dzssxpbyjris bli_rxxpbyjris #define bli_czssxpbyjris bli_rxxpbyjris #define bli_zzssxpbyjris bli_rxxpbyjris // NOTE: This series needs to be finished for all other char values for (by), but // not until something in BLIS actually needs mixed-datatype axpbyjris. #define bli_saxpbyjris bli_ssssaxpbyjris #define bli_daxpbyjris bli_ddddaxpbyjris #define bli_caxpbyjris bli_ccccaxpbyjris #define bli_zaxpbyjris bli_zzzzaxpbyjris #endif blis-0.9.0/frame/include/level0/ri/bli_axpbyris.h000066400000000000000000000064261422157504600216450ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_AXPBYRIS_H #define BLIS_AXPBYRIS_H // axpbyris #define bli_rxaxpbyris( ar, ai, xr, xi, br, bi, yr, yi ) \ { \ (yr) = (ar) * (xr) + (br) * (yr); \ } #define bli_cxaxpbyris( ar, ai, xr, xi, br, bi, yr, yi ) \ { \ const __typeof__(yr) yt_r = (ar) * (xr) - (ai) * (xi) + (br) * (yr) - (bi) * (yi); \ const __typeof__(yi) yt_i = (ai) * (xr) + (ar) * (xi) + (bi) * (yr) + (br) * (yi); \ (yr) = yt_r; \ (yi) = yt_i; \ } // Notes: // - The first char encodes the type of a. // - The second char encodes the type of x. // - The third char encodes the type of b. // - The fourth char encodes the type of y. // -- (axby) = (??ss) ---------------------------------------------------------- #define bli_ssssxpbyris bli_rxxpbyris #define bli_dsssxpbyris bli_rxxpbyris #define bli_csssxpbyris bli_rxxpbyris #define bli_zsssxpbyris bli_rxxpbyris #define bli_sdssxpbyris bli_rxxpbyris #define bli_ddssxpbyris bli_rxxpbyris #define bli_cdssxpbyris bli_rxxpbyris #define bli_zdssxpbyris bli_rxxpbyris #define bli_scssxpbyris bli_rxxpbyris #define bli_dcssxpbyris bli_rxxpbyris #define bli_ccssxpbyris bli_rxxpbyris #define bli_zcssxpbyris bli_rxxpbyris #define bli_szssxpbyris bli_rxxpbyris #define bli_dzssxpbyris bli_rxxpbyris #define bli_czssxpbyris bli_rxxpbyris #define bli_zzssxpbyris bli_rxxpbyris // NOTE: This series needs to be finished for all other char values for (by), but // not until something in BLIS actually needs mixed-datatype axpbyris. #define bli_saxpbyris bli_ssssaxpbyris #define bli_daxpbyris bli_ddddaxpbyris #define bli_caxpbyris bli_ccccaxpbyris #define bli_zaxpbyris bli_zzzzaxpbyris #endif blis-0.9.0/frame/include/level0/ri/bli_axpyjris.h000066400000000000000000000125511422157504600216510ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_AXPYJRIS_H #define BLIS_AXPYJRIS_H // axpyjris #define bli_rxaxpyjris( ar, ai, xr, xi, yr, yi ) \ { \ (yr) += (ar) * (xr); \ } #define bli_cxaxpyjris( ar, ai, xr, xi, yr, yi ) \ { \ (yr) += (ar) * (xr) + (ai) * (xi); \ (yi) += (ai) * (xr) - (ar) * (xi); \ } #define bli_roaxpyjris( ar, ai, xr, xi, yr, yi ) \ { \ (yr) += (ar) * (xr) + (ai) * (xi); \ } #define bli_craxpyjris( ar, ai, xr, xi, yr, yi ) \ { \ (yr) += (ar) * (xr); \ (yi) += (ar) * -(xi); \ } #define bli_rcaxpyjris( ar, ai, xr, xi, yr, yi ) \ { \ (yr) += (ar) * (xr); \ (yi) += (ai) * (xr); \ } // Notes: // - The first char encodes the type of a. // - The second char encodes the type of x. // - The third char encodes the type of y. // -- (axy) = (??s) ------------------------------------------------------------ #define bli_sssaxpyjris bli_rxaxpyjris #define bli_dssaxpyjris bli_rxaxpyjris #define bli_cssaxpyjris bli_rxaxpyjris #define bli_zssaxpyjris bli_rxaxpyjris #define bli_sdsaxpyjris bli_rxaxpyjris #define bli_ddsaxpyjris bli_rxaxpyjris #define bli_cdsaxpyjris bli_rxaxpyjris #define bli_zdsaxpyjris bli_rxaxpyjris #define bli_scsaxpyjris bli_rxaxpyjris #define bli_dcsaxpyjris bli_rxaxpyjris #define bli_ccsaxpyjris bli_roaxpyjris #define bli_zcsaxpyjris bli_roaxpyjris #define bli_szsaxpyjris bli_rxaxpyjris #define bli_dzsaxpyjris bli_rxaxpyjris #define bli_czsaxpyjris bli_roaxpyjris #define bli_zzsaxpyjris bli_roaxpyjris // -- (axy) = (??d) ------------------------------------------------------------ #define bli_ssdaxpyjris bli_rxaxpyjris #define bli_dsdaxpyjris bli_rxaxpyjris #define bli_csdaxpyjris bli_rxaxpyjris #define bli_zsdaxpyjris bli_rxaxpyjris #define bli_sddaxpyjris bli_rxaxpyjris #define bli_dddaxpyjris bli_rxaxpyjris #define bli_cddaxpyjris bli_rxaxpyjris #define bli_zddaxpyjris bli_rxaxpyjris #define bli_scdaxpyjris bli_rxaxpyjris #define bli_dcdaxpyjris bli_rxaxpyjris #define bli_ccdaxpyjris bli_roaxpyjris #define bli_zcdaxpyjris bli_roaxpyjris #define bli_szdaxpyjris bli_rxaxpyjris #define bli_dzdaxpyjris bli_rxaxpyjris #define bli_czdaxpyjris bli_roaxpyjris #define bli_zzdaxpyjris bli_roaxpyjris // -- (axy) = (??c) ------------------------------------------------------------ #define bli_sscaxpyjris bli_rxaxpyjris #define bli_dscaxpyjris bli_rxaxpyjris #define bli_cscaxpyjris bli_rcaxpyjris #define bli_zscaxpyjris bli_rcaxpyjris #define bli_sdcaxpyjris bli_rxaxpyjris #define bli_ddcaxpyjris bli_rxaxpyjris #define bli_cdcaxpyjris bli_rcaxpyjris #define bli_zdcaxpyjris bli_rcaxpyjris #define bli_sccaxpyjris bli_craxpyjris #define bli_dccaxpyjris bli_craxpyjris #define bli_cccaxpyjris bli_cxaxpyjris #define bli_zccaxpyjris bli_cxaxpyjris #define bli_szcaxpyjris bli_craxpyjris #define bli_dzcaxpyjris bli_craxpyjris #define bli_czcaxpyjris bli_cxaxpyjris #define bli_zzcaxpyjris bli_cxaxpyjris // -- (axy) = (??z) ------------------------------------------------------------ #define bli_sszaxpyjris bli_rxaxpyjris #define bli_dszaxpyjris bli_rxaxpyjris #define bli_cszaxpyjris bli_rcaxpyjris #define bli_zszaxpyjris bli_rcaxpyjris #define bli_sdzaxpyjris bli_rxaxpyjris #define bli_ddzaxpyjris bli_rxaxpyjris #define bli_cdzaxpyjris bli_rcaxpyjris #define bli_zdzaxpyjris bli_rcaxpyjris #define bli_sczaxpyjris bli_craxpyjris #define bli_dczaxpyjris bli_craxpyjris #define bli_cczaxpyjris bli_cxaxpyjris #define bli_zczaxpyjris bli_cxaxpyjris #define bli_szzaxpyjris bli_craxpyjris #define bli_dzzaxpyjris bli_craxpyjris #define bli_czzaxpyjris bli_cxaxpyjris #define bli_zzzaxpyjris bli_cxaxpyjris #define bli_saxpyjris bli_sssaxpyjris #define bli_daxpyjris bli_dddaxpyjris #define bli_caxpyjris bli_cccaxpyjris #define bli_zaxpyjris bli_zzzaxpyjris #endif blis-0.9.0/frame/include/level0/ri/bli_axpyris.h000066400000000000000000000123271422157504600215000ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_AXPYRIS_H #define BLIS_AXPYRIS_H // axpyris #define bli_rxaxpyris( ar, ai, xr, xi, yr, yi ) \ { \ (yr) += (ar) * (xr); \ } #define bli_cxaxpyris( ar, ai, xr, xi, yr, yi ) \ { \ (yr) += (ar) * (xr) - (ai) * (xi); \ (yi) += (ai) * (xr) + (ar) * (xi); \ } #define bli_roaxpyris( ar, ai, xr, xi, yr, yi ) \ { \ (yr) += (ar) * (xr) - (ai) * (xi); \ } #define bli_craxpyris( ar, ai, xr, xi, yr, yi ) \ { \ (yr) += (ar) * (xr); \ (yi) += (ar) * (xi); \ } #define bli_rcaxpyris( ar, ai, xr, xi, yr, yi ) \ { \ (yr) += (ar) * (xr); \ (yi) += (ai) * (xr); \ } // Notes: // - The first char encodes the type of a. // - The second char encodes the type of x. // - The third char encodes the type of y. // -- (axy) = (??s) ------------------------------------------------------------ #define bli_sssaxpyris bli_rxaxpyris #define bli_dssaxpyris bli_rxaxpyris #define bli_cssaxpyris bli_rxaxpyris #define bli_zssaxpyris bli_rxaxpyris #define bli_sdsaxpyris bli_rxaxpyris #define bli_ddsaxpyris bli_rxaxpyris #define bli_cdsaxpyris bli_rxaxpyris #define bli_zdsaxpyris bli_rxaxpyris #define bli_scsaxpyris bli_rxaxpyris #define bli_dcsaxpyris bli_rxaxpyris #define bli_ccsaxpyris bli_roaxpyris #define bli_zcsaxpyris bli_roaxpyris #define bli_szsaxpyris bli_rxaxpyris #define bli_dzsaxpyris bli_rxaxpyris #define bli_czsaxpyris bli_roaxpyris #define bli_zzsaxpyris bli_roaxpyris // -- (axy) = (??d) ------------------------------------------------------------ #define bli_ssdaxpyris bli_rxaxpyris #define bli_dsdaxpyris bli_rxaxpyris #define bli_csdaxpyris bli_rxaxpyris #define bli_zsdaxpyris bli_rxaxpyris #define bli_sddaxpyris bli_rxaxpyris #define bli_dddaxpyris bli_rxaxpyris #define bli_cddaxpyris bli_rxaxpyris #define bli_zddaxpyris bli_rxaxpyris #define bli_scdaxpyris bli_rxaxpyris #define bli_dcdaxpyris bli_rxaxpyris #define bli_ccdaxpyris bli_roaxpyris #define bli_zcdaxpyris bli_roaxpyris #define bli_szdaxpyris bli_rxaxpyris #define bli_dzdaxpyris bli_rxaxpyris #define bli_czdaxpyris bli_roaxpyris #define bli_zzdaxpyris bli_roaxpyris // -- (axy) = (??c) ------------------------------------------------------------ #define bli_sscaxpyris bli_rxaxpyris #define bli_dscaxpyris bli_rxaxpyris #define bli_cscaxpyris bli_rcaxpyris #define bli_zscaxpyris bli_rcaxpyris #define bli_sdcaxpyris bli_rxaxpyris #define bli_ddcaxpyris bli_rxaxpyris #define bli_cdcaxpyris bli_rcaxpyris #define bli_zdcaxpyris bli_rcaxpyris #define bli_sccaxpyris bli_craxpyris #define bli_dccaxpyris bli_craxpyris #define bli_cccaxpyris bli_cxaxpyris #define bli_zccaxpyris bli_cxaxpyris #define bli_szcaxpyris bli_craxpyris #define bli_dzcaxpyris bli_craxpyris #define bli_czcaxpyris bli_cxaxpyris #define bli_zzcaxpyris bli_cxaxpyris // -- (axy) = (??z) ------------------------------------------------------------ #define bli_sszaxpyris bli_rxaxpyris #define bli_dszaxpyris bli_rxaxpyris #define bli_cszaxpyris bli_rcaxpyris #define bli_zszaxpyris bli_rcaxpyris #define bli_sdzaxpyris bli_rxaxpyris #define bli_ddzaxpyris bli_rxaxpyris #define bli_cdzaxpyris bli_rcaxpyris #define bli_zdzaxpyris bli_rcaxpyris #define bli_sczaxpyris bli_craxpyris #define bli_dczaxpyris bli_craxpyris #define bli_cczaxpyris bli_cxaxpyris #define bli_zczaxpyris bli_cxaxpyris #define bli_szzaxpyris bli_craxpyris #define bli_dzzaxpyris bli_craxpyris #define bli_czzaxpyris bli_cxaxpyris #define bli_zzzaxpyris bli_cxaxpyris #define bli_saxpyris bli_sssaxpyris #define bli_daxpyris bli_dddaxpyris #define bli_caxpyris bli_cccaxpyris #define bli_zaxpyris bli_zzzaxpyris #endif blis-0.9.0/frame/include/level0/ri/bli_conjris.h000066400000000000000000000036301422157504600214450ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_CONJRIS_H #define BLIS_CONJRIS_H // conjris #define bli_sconjris( xr, xi ) \ { \ ; \ } #define bli_dconjris( xr, xi ) \ { \ ; \ } #define bli_cconjris( xr, xi ) \ { \ (xi) = -(xi); \ } #define bli_zconjris( xr, xi ) \ { \ (xi) = -(xi); \ } #endif blis-0.9.0/frame/include/level0/ri/bli_copycjris.h000066400000000000000000000045421422157504600220060ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_COPYCJRIS_H #define BLIS_COPYCJRIS_H // copycjris #define bli_scopycjris( conj, xr, xi, yr, yi ) \ { \ bli_scopyris( (xr), (xi), (yr), (yi) ); \ } #define bli_dcopycjris( conj, xr, xi, yr, yi ) \ { \ bli_dcopyris( (xr), (xi), (yr), (yi) ); \ } #define bli_ccopycjris( conj, xr, xi, yr, yi ) \ { \ (yr) = (xr); \ (yi) = ( bli_is_conj( conj ) ? -(xi) \ : (xi) ); \ } #define bli_zcopycjris( conj, xr, xi, yr, yi ) \ { \ (yr) = (xr); \ (yi) = ( bli_is_conj( conj ) ? -(xi) \ : (xi) ); \ } #define bli_icopycjris( conj, xr, xi, yr, yi ) \ { \ bli_icopyris( (xr), (xi), (yr), (yi) ); \ } #endif blis-0.9.0/frame/include/level0/ri/bli_copyjris.h000066400000000000000000000063301422157504600216400ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_COPYJRIS_H #define BLIS_COPYJRIS_H // copyjris #define bli_scopyjris( ar, ai, br, bi ) bli_scopyris( (ar), -(ai), (br), (bi) ) #define bli_dcopyjris( ar, ai, br, bi ) bli_dcopyris( (ar), -(ai), (br), (bi) ) #define bli_ccopyjris( ar, ai, br, bi ) bli_ccopyris( (ar), -(ai), (br), (bi) ) #define bli_zcopyjris( ar, ai, br, bi ) bli_zcopyris( (ar), -(ai), (br), (bi) ) #define bli_sscopyjris( ar, ai, br, bi ) bli_scopyjris( ar, 0.0F, br, bi ) #define bli_dscopyjris( ar, ai, br, bi ) bli_scopyjris( ar, 0.0, br, bi ) #define bli_cscopyjris( ar, ai, br, bi ) bli_scopyjris( ar, ai, br, bi ) #define bli_zscopyjris( ar, ai, br, bi ) bli_scopyjris( ar, ai, br, bi ) #define bli_sdcopyjris( ar, ai, br, bi ) bli_dcopyjris( ar, 0.0F, br, bi ) #define bli_ddcopyjris( ar, ai, br, bi ) bli_dcopyjris( ar, 0.0, br, bi ) #define bli_cdcopyjris( ar, ai, br, bi ) bli_dcopyjris( ar, ai, br, bi ) #define bli_zdcopyjris( ar, ai, br, bi ) bli_dcopyjris( ar, ai, br, bi ) #define bli_sccopyjris( ar, ai, br, bi ) bli_ccopyjris( ar, 0.0F, br, bi ) #define bli_dccopyjris( ar, ai, br, bi ) bli_ccopyjris( ar, 0.0, br, bi ) #define bli_cccopyjris( ar, ai, br, bi ) bli_ccopyjris( ar, ai, br, bi ) #define bli_zccopyjris( ar, ai, br, bi ) bli_ccopyjris( ar, ai, br, bi ) #define bli_szcopyjris( ar, ai, br, bi ) bli_zcopyjris( ar, 0.0F, br, bi ) #define bli_dzcopyjris( ar, ai, br, bi ) bli_zcopyjris( ar, 0.0, br, bi ) #define bli_czcopyjris( ar, ai, br, bi ) bli_zcopyjris( ar, ai, br, bi ) #define bli_zzcopyjris( ar, ai, br, bi ) bli_zcopyjris( ar, ai, br, bi ) #endif blis-0.9.0/frame/include/level0/ri/bli_copyris.h000066400000000000000000000062171422157504600214720ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_COPYRIS_H #define BLIS_COPYRIS_H // copyris #define bli_scopyris( ar, ai, br, bi ) \ { \ (br) = (ar); \ } #define bli_dcopyris( ar, ai, br, bi ) \ { \ (br) = (ar); \ } #define bli_ccopyris( ar, ai, br, bi ) \ { \ (br) = (ar); \ (bi) = (ai); \ } #define bli_zcopyris( ar, ai, br, bi ) \ { \ (br) = (ar); \ (bi) = (ai); \ } #define bli_sscopyris( ar, ai, br, bi ) bli_scopyris( ar, 0.0F, br, bi ) #define bli_dscopyris( ar, ai, br, bi ) bli_scopyris( ar, 0.0, br, bi ) #define bli_cscopyris( ar, ai, br, bi ) bli_scopyris( ar, ai, br, bi ) #define bli_zscopyris( ar, ai, br, bi ) bli_scopyris( ar, ai, br, bi ) #define bli_sdcopyris( ar, ai, br, bi ) bli_dcopyris( ar, 0.0F, br, bi ) #define bli_ddcopyris( ar, ai, br, bi ) bli_dcopyris( ar, 0.0, br, bi ) #define bli_cdcopyris( ar, ai, br, bi ) bli_dcopyris( ar, ai, br, bi ) #define bli_zdcopyris( ar, ai, br, bi ) bli_dcopyris( ar, ai, br, bi ) #define bli_sccopyris( ar, ai, br, bi ) bli_ccopyris( ar, 0.0F, br, bi ) #define bli_dccopyris( ar, ai, br, bi ) bli_ccopyris( ar, 0.0, br, bi ) #define bli_cccopyris( ar, ai, br, bi ) bli_ccopyris( ar, ai, br, bi ) #define bli_zccopyris( ar, ai, br, bi ) bli_ccopyris( ar, ai, br, bi ) #define bli_szcopyris( ar, ai, br, bi ) bli_zcopyris( ar, 0.0F, br, bi ) #define bli_dzcopyris( ar, ai, br, bi ) bli_zcopyris( ar, 0.0, br, bi ) #define bli_czcopyris( ar, ai, br, bi ) bli_zcopyris( ar, ai, br, bi ) #define bli_zzcopyris( ar, ai, br, bi ) bli_zcopyris( ar, ai, br, bi ) #endif blis-0.9.0/frame/include/level0/ri/bli_eqris.h000066400000000000000000000060741422157504600211260ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_EQRIS_H #define BLIS_EQRIS_H // eqris (passed by value) #define bli_seqris( ar, ai, br, bi ) ( (ar) == (br) ) #define bli_deqris( ar, ai, br, bi ) ( (ar) == (br) ) #define bli_ceqris( ar, ai, br, bi ) ( (ar) == (br) && (ai) == (bi) ) #define bli_zeqris( ar, ai, br, bi ) ( (ar) == (br) && (ai) == (bi) ) #define bli_ieqris( ar, ai, br, bi ) ( (ar) == (br) ) // eq1ris #define bli_seq1ris( ar, ai ) bli_seqris( (ar), (ai), 1.0F, 0.0F ) #define bli_deq1ris( ar, ai ) bli_deqris( (ar), (ai), 1.0, 0.0 ) #define bli_ceq1ris( ar, ai ) bli_ceqris( (ar), (ai), 1.0F, 0.0F ) #define bli_zeq1ris( ar, ai ) bli_zeqris( (ar), (ai), 1.0, 0.0 ) #define bli_ieq1ris( ar, ai ) bli_ieqris( (ar), (ai), 1, 0 ) // eq0ris #define bli_seq0ris( ar, ai ) bli_seqris( (ar), (ai), 0.0F, 0.0F ) #define bli_deq0ris( ar, ai ) bli_deqris( (ar), (ai), 0.0, 0.0 ) #define bli_ceq0ris( ar, ai ) bli_ceqris( (ar), (ai), 0.0F, 0.0F ) #define bli_zeq0ris( ar, ai ) bli_zeqris( (ar), (ai), 0.0, 0.0 ) #define bli_ieq0ris( ar, ai ) bli_ieqris( (ar), (ai), 0, 0 ) // eqm1ris #define bli_seqm1ris( ar, ai ) bli_seqris( (ar), (ai), -1.0F, 0.0F ) #define bli_deqm1ris( ar, ai ) bli_deqris( (ar), (ai), -1.0, 0.0 ) #define bli_ceqm1ris( ar, ai ) bli_ceqris( (ar), (ai), -1.0F, 0.0F ) #define bli_zeqm1ris( ar, ai ) bli_zeqris( (ar), (ai), -1.0, 0.0 ) #define bli_ieqm1ris( ar, ai ) bli_ieqris( (ar), (ai), -1, 0 ) #endif blis-0.9.0/frame/include/level0/ri/bli_invertris.h000066400000000000000000000045071422157504600220270ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_INVERTRIS_H #define BLIS_INVERTRIS_H // invertris #define bli_sinvertris( xr, xi ) \ { \ (xr) = 1.0F / (xr); \ } #define bli_dinvertris( xr, xi ) \ { \ (xr) = 1.0 / (xr); \ } #define bli_cinvertris( xr, xi ) \ { \ float s = bli_fmaxabs( (xr), (xi) ); \ float xr_s = (xr) / s; \ float xi_s = (xi) / s; \ float temp = ( xr_s * (xr) + xi_s * (xi) ); \ (xr) = xr_s / temp; \ (xi) = -xi_s / temp; \ } #define bli_zinvertris( xr, xi ) \ { \ double s = bli_fmaxabs( (xr), (xi) ); \ double xr_s = (xr) / s; \ double xi_s = (xi) / s; \ double temp = ( xr_s * (xr) + xi_s * (xi) ); \ (xr) = xr_s / temp; \ (xi) = -xi_s / temp; \ } #endif blis-0.9.0/frame/include/level0/ri/bli_invscaljris.h000066400000000000000000000043501422157504600223250ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_INVSCALJRIS_H #define BLIS_INVSCALJRIS_H // invscaljris #define bli_sinvscaljris( ar, ai, xr, xi ) bli_sinvscalris( (ar), -(ai), (xr), (xi) ) #define bli_dinvscaljris( ar, ai, xr, xi ) bli_dinvscalris( (ar), -(ai), (xr), (xi) ) #define bli_cinvscaljris( ar, ai, xr, xi ) bli_cinvscalris( (ar), -(ai), (xr), (xi) ) #define bli_zinvscaljris( ar, ai, xr, xi ) bli_zinvscalris( (ar), -(ai), (xr), (xi) ) #define bli_scinvscaljris( ar, ai, xr, xi ) bli_scinvscalris( (ar), -(ai), (xr), (xi) ) #define bli_dzinvscaljris( ar, ai, xr, xi ) bli_dzinvscalris( (ar), -(ai), (xr), (xi) ) #endif blis-0.9.0/frame/include/level0/ri/bli_invscalris.h000066400000000000000000000052621422157504600221560ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_INVSCALRIS_H #define BLIS_INVSCALRIS_H // invscalris #define bli_sinvscalris( ar, ai, xr, xi ) \ { \ (xr) /= (ar); \ } #define bli_dinvscalris( ar, ai, xr, xi ) \ { \ (xr) /= (ar); \ } #define bli_cinvscalris( ar, ai, xr, xi ) \ { \ float s = bli_fmaxabs( (ar), (ai) ); \ float ar_s = (ar) / s; \ float ai_s = (ai) / s; \ float xrt = (xr); \ float temp = ( ar_s * (ar) + ai_s * (ai) ); \ (xr) = ( (xrt) * ar_s + (xi) * ai_s ) / temp; \ (xi) = ( (xi) * ar_s - (xrt) * ai_s ) / temp; \ } #define bli_zinvscalris( ar, ai, xr, xi ) \ { \ double s = bli_fmaxabs( (ar), (ai) ); \ double ar_s = (ar) / s; \ double ai_s = (ai) / s; \ double xrt = (xr); \ double temp = ( ar_s * (ar) + ai_s * (ai) ); \ (xr) = ( (xrt) * ar_s + (xi) * ai_s ) / temp; \ (xi) = ( (xi) * ar_s - (xrt) * ai_s ) / temp; \ } #define bli_scinvscalris( ar, ai, xr, xi ) \ { \ (xr) /= (ar); \ (xi) /= (ar); \ } #define bli_dzinvscalris( ar, ai, xr, xi ) \ { \ (xr) /= (ar); \ (xi) /= (ar); \ } #endif blis-0.9.0/frame/include/level0/ri/bli_neg2ris.h000066400000000000000000000037621422157504600213550ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_NEG2RIS_H #define BLIS_NEG2RIS_H // neg2ris #define bli_sneg2ris( ar, ai, br, bi ) \ { \ (br) = -(ar); \ } #define bli_dneg2ris( ar, ai, br, bi ) \ { \ (br) = -(ar); \ } #define bli_cneg2ris( ar, ai, br, bi ) \ { \ (br) = -(ar); \ (bi) = -(ai); \ } #define bli_zneg2ris( ar, ai, br, bi ) \ { \ (br) = -(ar); \ (bi) = -(ai); \ } #endif blis-0.9.0/frame/include/level0/ri/bli_scal2jris.h000066400000000000000000000215651422157504600217010ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_SCAL2JRIS_H #define BLIS_SCAL2JRIS_H // scal2jris #define bli_rxscal2jris( ar, ai, xr, xi, yr, yi ) \ { \ (yr) = (ar) * (xr); \ } #define bli_cxscal2jris( ar, ai, xr, xi, yr, yi ) \ { \ (yr) = (ar) * (xr) + (ai) * (xi); \ (yi) = (ai) * (xr) - (ar) * (xi); \ } #define bli_roscal2jris( ar, ai, xr, xi, yr, yi ) \ { \ (yr) = (ar) * (xr) + (ai) * (xi); \ } #define bli_crscal2jris( ar, ai, xr, xi, yr, yi ) \ { \ (yr) = (ar) * (xr); \ (yi) = (ar) * -(xi); \ } #define bli_rcscal2jris( ar, ai, xr, xi, yr, yi ) \ { \ (yr) = (ar) * (xr); \ (yi) = (ai) * (xr); \ } // Notes: // - The first char encodes the type of a. // - The second char encodes the type of x. // - The third char encodes the type of y. // -- (axy) = (??s) ------------------------------------------------------------ #define bli_sssscal2jris( ar, ai, xr, xi, yr, yi ) bli_rxscal2jris( ar, ai, xr, xi, yr, yi ) #define bli_dssscal2jris( ar, ai, xr, xi, yr, yi ) bli_rxscal2jris( ar, ai, xr, xi, yr, yi ) #define bli_cssscal2jris( ar, ai, xr, xi, yr, yi ) bli_rxscal2jris( ar, ai, xr, xi, yr, yi ) #define bli_zssscal2jris( ar, ai, xr, xi, yr, yi ) bli_rxscal2jris( ar, ai, xr, xi, yr, yi ) #define bli_sdsscal2jris( ar, ai, xr, xi, yr, yi ) bli_rxscal2jris( ar, ai, xr, xi, yr, yi ) #define bli_ddsscal2jris( ar, ai, xr, xi, yr, yi ) bli_rxscal2jris( ar, ai, xr, xi, yr, yi ) #define bli_cdsscal2jris( ar, ai, xr, xi, yr, yi ) bli_rxscal2jris( ar, ai, xr, xi, yr, yi ) #define bli_zdsscal2jris( ar, ai, xr, xi, yr, yi ) bli_rxscal2jris( ar, ai, xr, xi, yr, yi ) #define bli_scsscal2jris( ar, ai, xr, xi, yr, yi ) bli_rxscal2jris( ar, ai, xr, xi, yr, yi ) #define bli_dcsscal2jris( ar, ai, xr, xi, yr, yi ) bli_rxscal2jris( ar, ai, xr, xi, yr, yi ) #define bli_ccsscal2jris( ar, ai, xr, xi, yr, yi ) bli_roscal2jris( ar, ai, xr, xi, yr, yi ) #define bli_zcsscal2jris( ar, ai, xr, xi, yr, yi ) bli_roscal2jris( ar, ai, xr, xi, yr, yi ) #define bli_szsscal2jris( ar, ai, xr, xi, yr, yi ) bli_rxscal2jris( ar, ai, xr, xi, yr, yi ) #define bli_dzsscal2jris( ar, ai, xr, xi, yr, yi ) bli_rxscal2jris( ar, ai, xr, xi, yr, yi ) #define bli_czsscal2jris( ar, ai, xr, xi, yr, yi ) bli_roscal2jris( ar, ai, xr, xi, yr, yi ) #define bli_zzsscal2jris( ar, ai, xr, xi, yr, yi ) bli_roscal2jris( ar, ai, xr, xi, yr, yi ) // -- (axy) = (??d) ------------------------------------------------------------ #define bli_ssdscal2jris( ar, ai, xr, xi, yr, yi ) bli_rxscal2jris( ar, ai, xr, xi, yr, yi ) #define bli_dsdscal2jris( ar, ai, xr, xi, yr, yi ) bli_rxscal2jris( ar, ai, xr, xi, yr, yi ) #define bli_csdscal2jris( ar, ai, xr, xi, yr, yi ) bli_rxscal2jris( ar, ai, xr, xi, yr, yi ) #define bli_zsdscal2jris( ar, ai, xr, xi, yr, yi ) bli_rxscal2jris( ar, ai, xr, xi, yr, yi ) #define bli_sddscal2jris( ar, ai, xr, xi, yr, yi ) bli_rxscal2jris( ar, ai, xr, xi, yr, yi ) #define bli_dddscal2jris( ar, ai, xr, xi, yr, yi ) bli_rxscal2jris( ar, ai, xr, xi, yr, yi ) #define bli_cddscal2jris( ar, ai, xr, xi, yr, yi ) bli_rxscal2jris( ar, ai, xr, xi, yr, yi ) #define bli_zddscal2jris( ar, ai, xr, xi, yr, yi ) bli_rxscal2jris( ar, ai, xr, xi, yr, yi ) #define bli_scdscal2jris( ar, ai, xr, xi, yr, yi ) bli_rxscal2jris( ar, ai, xr, xi, yr, yi ) #define bli_dcdscal2jris( ar, ai, xr, xi, yr, yi ) bli_rxscal2jris( ar, ai, xr, xi, yr, yi ) #define bli_ccdscal2jris( ar, ai, xr, xi, yr, yi ) bli_roscal2jris( ar, ai, xr, xi, yr, yi ) #define bli_zcdscal2jris( ar, ai, xr, xi, yr, yi ) bli_roscal2jris( ar, ai, xr, xi, yr, yi ) #define bli_szdscal2jris( ar, ai, xr, xi, yr, yi ) bli_rxscal2jris( ar, ai, xr, xi, yr, yi ) #define bli_dzdscal2jris( ar, ai, xr, xi, yr, yi ) bli_rxscal2jris( ar, ai, xr, xi, yr, yi ) #define bli_czdscal2jris( ar, ai, xr, xi, yr, yi ) bli_roscal2jris( ar, ai, xr, xi, yr, yi ) #define bli_zzdscal2jris( ar, ai, xr, xi, yr, yi ) bli_roscal2jris( ar, ai, xr, xi, yr, yi ) // -- (axy) = (??c) ------------------------------------------------------------ #define bli_sscscal2jris( ar, ai, xr, xi, yr, yi ) bli_rxscal2jris( ar, ai, xr, xi, yr, yi ) #define bli_dscscal2jris( ar, ai, xr, xi, yr, yi ) bli_rxscal2jris( ar, ai, xr, xi, yr, yi ) #define bli_cscscal2jris( ar, ai, xr, xi, yr, yi ) bli_rcscal2jris( ar, ai, xr, xi, yr, yi ) #define bli_zscscal2jris( ar, ai, xr, xi, yr, yi ) bli_rcscal2jris( ar, ai, xr, xi, yr, yi ) #define bli_sdcscal2jris( ar, ai, xr, xi, yr, yi ) bli_rxscal2jris( ar, ai, xr, xi, yr, yi ) #define bli_ddcscal2jris( ar, ai, xr, xi, yr, yi ) bli_rxscal2jris( ar, ai, xr, xi, yr, yi ) #define bli_cdcscal2jris( ar, ai, xr, xi, yr, yi ) bli_rcscal2jris( ar, ai, xr, xi, yr, yi ) #define bli_zdcscal2jris( ar, ai, xr, xi, yr, yi ) bli_rcscal2jris( ar, ai, xr, xi, yr, yi ) #define bli_sccscal2jris( ar, ai, xr, xi, yr, yi ) bli_crscal2jris( ar, ai, xr, xi, yr, yi ) #define bli_dccscal2jris( ar, ai, xr, xi, yr, yi ) bli_crscal2jris( ar, ai, xr, xi, yr, yi ) #define bli_cccscal2jris( ar, ai, xr, xi, yr, yi ) bli_cxscal2jris( ar, ai, xr, xi, yr, yi ) #define bli_zccscal2jris( ar, ai, xr, xi, yr, yi ) bli_cxscal2jris( ar, ai, xr, xi, yr, yi ) #define bli_szcscal2jris( ar, ai, xr, xi, yr, yi ) bli_crscal2jris( ar, ai, xr, xi, yr, yi ) #define bli_dzcscal2jris( ar, ai, xr, xi, yr, yi ) bli_crscal2jris( ar, ai, xr, xi, yr, yi ) #define bli_czcscal2jris( ar, ai, xr, xi, yr, yi ) bli_cxscal2jris( ar, ai, xr, xi, yr, yi ) #define bli_zzcscal2jris( ar, ai, xr, xi, yr, yi ) bli_cxscal2jris( ar, ai, xr, xi, yr, yi ) // -- (axy) = (??z) ------------------------------------------------------------ #define bli_sszscal2jris( ar, ai, xr, xi, yr, yi ) bli_rxscal2jris( ar, ai, xr, xi, yr, yi ) #define bli_dszscal2jris( ar, ai, xr, xi, yr, yi ) bli_rxscal2jris( ar, ai, xr, xi, yr, yi ) #define bli_cszscal2jris( ar, ai, xr, xi, yr, yi ) bli_rcscal2jris( ar, ai, xr, xi, yr, yi ) #define bli_zszscal2jris( ar, ai, xr, xi, yr, yi ) bli_rcscal2jris( ar, ai, xr, xi, yr, yi ) #define bli_sdzscal2jris( ar, ai, xr, xi, yr, yi ) bli_rxscal2jris( ar, ai, xr, xi, yr, yi ) #define bli_ddzscal2jris( ar, ai, xr, xi, yr, yi ) bli_rxscal2jris( ar, ai, xr, xi, yr, yi ) #define bli_cdzscal2jris( ar, ai, xr, xi, yr, yi ) bli_rcscal2jris( ar, ai, xr, xi, yr, yi ) #define bli_zdzscal2jris( ar, ai, xr, xi, yr, yi ) bli_rcscal2jris( ar, ai, xr, xi, yr, yi ) #define bli_sczscal2jris( ar, ai, xr, xi, yr, yi ) bli_crscal2jris( ar, ai, xr, xi, yr, yi ) #define bli_dczscal2jris( ar, ai, xr, xi, yr, yi ) bli_crscal2jris( ar, ai, xr, xi, yr, yi ) #define bli_cczscal2jris( ar, ai, xr, xi, yr, yi ) bli_cxscal2jris( ar, ai, xr, xi, yr, yi ) #define bli_zczscal2jris( ar, ai, xr, xi, yr, yi ) bli_cxscal2jris( ar, ai, xr, xi, yr, yi ) #define bli_szzscal2jris( ar, ai, xr, xi, yr, yi ) bli_crscal2jris( ar, ai, xr, xi, yr, yi ) #define bli_dzzscal2jris( ar, ai, xr, xi, yr, yi ) bli_crscal2jris( ar, ai, xr, xi, yr, yi ) #define bli_czzscal2jris( ar, ai, xr, xi, yr, yi ) bli_cxscal2jris( ar, ai, xr, xi, yr, yi ) #define bli_zzzscal2jris( ar, ai, xr, xi, yr, yi ) bli_cxscal2jris( ar, ai, xr, xi, yr, yi ) #define bli_sscal2jris( ar, ai, xr, xi, yr, yi ) bli_sssscal2jris( ar, ai, xr, xi, yr, yi ) #define bli_dscal2jris( ar, ai, xr, xi, yr, yi ) bli_dddscal2jris( ar, ai, xr, xi, yr, yi ) #define bli_cscal2jris( ar, ai, xr, xi, yr, yi ) bli_cccscal2jris( ar, ai, xr, xi, yr, yi ) #define bli_zscal2jris( ar, ai, xr, xi, yr, yi ) bli_zzzscal2jris( ar, ai, xr, xi, yr, yi ) #endif blis-0.9.0/frame/include/level0/ri/bli_scal2ris.h000066400000000000000000000125371422157504600215260ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_SCAL2RIS_H #define BLIS_SCAL2RIS_H // scal2ris #define bli_rxscal2ris( ar, ai, xr, xi, yr, yi ) \ { \ (yr) = (ar) * (xr); \ } #define bli_cxscal2ris( ar, ai, xr, xi, yr, yi ) \ { \ (yr) = (ar) * (xr) - (ai) * (xi); \ (yi) = (ai) * (xr) + (ar) * (xi); \ } #define bli_roscal2ris( ar, ai, xr, xi, yr, yi ) \ { \ (yr) = (ar) * (xr) - (ai) * (xi); \ } #define bli_crscal2ris( ar, ai, xr, xi, yr, yi ) \ { \ (yr) = (ar) * (xr); \ (yi) = (ar) * (xi); \ } #define bli_rcscal2ris( ar, ai, xr, xi, yr, yi ) \ { \ (yr) = (ar) * (xr); \ (yi) = (ai) * (xr); \ } // Notes: // - The first char encodes the type of a. // - The second char encodes the type of x. // - The third char encodes the type of y. // -- (axy) = (??s) ------------------------------------------------------------ #define bli_sssscal2ris bli_rxscal2ris #define bli_dssscal2ris bli_rxscal2ris #define bli_cssscal2ris bli_rxscal2ris #define bli_zssscal2ris bli_rxscal2ris #define bli_sdsscal2ris bli_rxscal2ris #define bli_ddsscal2ris bli_rxscal2ris #define bli_cdsscal2ris bli_rxscal2ris #define bli_zdsscal2ris bli_rxscal2ris #define bli_scsscal2ris bli_rxscal2ris #define bli_dcsscal2ris bli_rxscal2ris #define bli_ccsscal2ris bli_roscal2ris #define bli_zcsscal2ris bli_roscal2ris #define bli_szsscal2ris bli_rxscal2ris #define bli_dzsscal2ris bli_rxscal2ris #define bli_czsscal2ris bli_roscal2ris #define bli_zzsscal2ris bli_roscal2ris // -- (axy) = (??d) ------------------------------------------------------------ #define bli_ssdscal2ris bli_rxscal2ris #define bli_dsdscal2ris bli_rxscal2ris #define bli_csdscal2ris bli_rxscal2ris #define bli_zsdscal2ris bli_rxscal2ris #define bli_sddscal2ris bli_rxscal2ris #define bli_dddscal2ris bli_rxscal2ris #define bli_cddscal2ris bli_rxscal2ris #define bli_zddscal2ris bli_rxscal2ris #define bli_scdscal2ris bli_rxscal2ris #define bli_dcdscal2ris bli_rxscal2ris #define bli_ccdscal2ris bli_roscal2ris #define bli_zcdscal2ris bli_roscal2ris #define bli_szdscal2ris bli_rxscal2ris #define bli_dzdscal2ris bli_rxscal2ris #define bli_czdscal2ris bli_roscal2ris #define bli_zzdscal2ris bli_roscal2ris // -- (axy) = (??c) ------------------------------------------------------------ #define bli_sscscal2ris bli_rxscal2ris #define bli_dscscal2ris bli_rxscal2ris #define bli_cscscal2ris bli_rcscal2ris #define bli_zscscal2ris bli_rcscal2ris #define bli_sdcscal2ris bli_rxscal2ris #define bli_ddcscal2ris bli_rxscal2ris #define bli_cdcscal2ris bli_rcscal2ris #define bli_zdcscal2ris bli_rcscal2ris #define bli_sccscal2ris bli_crscal2ris #define bli_dccscal2ris bli_crscal2ris #define bli_cccscal2ris bli_cxscal2ris #define bli_zccscal2ris bli_cxscal2ris #define bli_szcscal2ris bli_crscal2ris #define bli_dzcscal2ris bli_crscal2ris #define bli_czcscal2ris bli_cxscal2ris #define bli_zzcscal2ris bli_cxscal2ris // -- (axy) = (??z) ------------------------------------------------------------ #define bli_sszscal2ris bli_rxscal2ris #define bli_dszscal2ris bli_rxscal2ris #define bli_cszscal2ris bli_rcscal2ris #define bli_zszscal2ris bli_rcscal2ris #define bli_sdzscal2ris bli_rxscal2ris #define bli_ddzscal2ris bli_rxscal2ris #define bli_cdzscal2ris bli_rcscal2ris #define bli_zdzscal2ris bli_rcscal2ris #define bli_sczscal2ris bli_crscal2ris #define bli_dczscal2ris bli_crscal2ris #define bli_cczscal2ris bli_cxscal2ris #define bli_zczscal2ris bli_cxscal2ris #define bli_szzscal2ris bli_crscal2ris #define bli_dzzscal2ris bli_crscal2ris #define bli_czzscal2ris bli_cxscal2ris #define bli_zzzscal2ris bli_cxscal2ris #define bli_sscal2ris bli_sssscal2ris #define bli_dscal2ris bli_dddscal2ris #define bli_cscal2ris bli_cccscal2ris #define bli_zscal2ris bli_zzzscal2ris #endif blis-0.9.0/frame/include/level0/ri/bli_scal2ris_mxn.h000066400000000000000000000122211422157504600223760ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_SCAL2RIS_MXN_H #define BLIS_SCAL2RIS_MXN_H // scal2ris_mxn BLIS_INLINE void bli_cscal2ris_mxn ( const conj_t conjx, const dim_t m, const dim_t n, scomplex* restrict alpha, scomplex* restrict x, const inc_t rs_x, const inc_t cs_x, scomplex* restrict y, const inc_t rs_y, const inc_t cs_y, const inc_t is_y ) { float* restrict alpha_r = ( float* )alpha; \ float* restrict alpha_i = ( float* )alpha + 1; \ float* restrict x_r = ( float* )x; \ float* restrict x_i = ( float* )x + 1; \ float* restrict y_r = ( float* )y; \ float* restrict y_i = ( float* )y + is_y; \ const dim_t incx2 = 2*rs_x; \ const dim_t ldx2 = 2*cs_x; \ /* Treat the micro-panel as panel_dim x panel_len and column-stored (unit row stride). */ \ if ( bli_is_conj( conjx ) ) { for ( dim_t j = 0; j < n; ++j ) for ( dim_t i = 0; i < m; ++i ) { float* restrict chi11_r = x_r + (i )*incx2 + (j )*ldx2; float* restrict chi11_i = x_i + (i )*incx2 + (j )*ldx2; float* restrict psi11_r = y_r + (i )*1 + (j )*cs_y; float* restrict psi11_i = y_i + (i )*1 + (j )*cs_y; bli_cscal2jris ( *alpha_r, *alpha_i, *chi11_r, *chi11_i, *psi11_r, *psi11_i ); } } else /* if ( bli_is_noconj( conjx ) ) */ { for ( dim_t j = 0; j < n; ++j ) for ( dim_t i = 0; i < m; ++i ) { float* restrict chi11_r = x_r + (i )*incx2 + (j )*ldx2; float* restrict chi11_i = x_i + (i )*incx2 + (j )*ldx2; float* restrict psi11_r = y_r + (i )*1 + (j )*cs_y; float* restrict psi11_i = y_i + (i )*1 + (j )*cs_y; bli_cscal2ris ( *alpha_r, *alpha_i, *chi11_r, *chi11_i, *psi11_r, *psi11_i ); } } } BLIS_INLINE void bli_zscal2ris_mxn ( const conj_t conjx, const dim_t m, const dim_t n, dcomplex* restrict alpha, dcomplex* restrict x, const inc_t rs_x, const inc_t cs_x, dcomplex* restrict y, const inc_t rs_y, const inc_t cs_y, const inc_t is_y ) { double* restrict alpha_r = ( double* )alpha; \ double* restrict alpha_i = ( double* )alpha + 1; \ double* restrict x_r = ( double* )x; \ double* restrict x_i = ( double* )x + 1; \ double* restrict y_r = ( double* )y; \ double* restrict y_i = ( double* )y + is_y; \ const dim_t incx2 = 2*rs_x; \ const dim_t ldx2 = 2*cs_x; \ /* Treat the micro-panel as panel_dim x panel_len and column-stored (unit row stride). */ \ if ( bli_is_conj( conjx ) ) { for ( dim_t j = 0; j < n; ++j ) for ( dim_t i = 0; i < m; ++i ) { double* restrict chi11_r = x_r + (i )*incx2 + (j )*ldx2; double* restrict chi11_i = x_i + (i )*incx2 + (j )*ldx2; double* restrict psi11_r = y_r + (i )*1 + (j )*cs_y; double* restrict psi11_i = y_i + (i )*1 + (j )*cs_y; bli_zscal2jris ( *alpha_r, *alpha_i, *chi11_r, *chi11_i, *psi11_r, *psi11_i ); } } else /* if ( bli_is_noconj( conjx ) ) */ { for ( dim_t j = 0; j < n; ++j ) for ( dim_t i = 0; i < m; ++i ) { double* restrict chi11_r = x_r + (i )*incx2 + (j )*ldx2; double* restrict chi11_i = x_i + (i )*incx2 + (j )*ldx2; double* restrict psi11_r = y_r + (i )*1 + (j )*cs_y; double* restrict psi11_i = y_i + (i )*1 + (j )*cs_y; bli_zscal2ris ( *alpha_r, *alpha_i, *chi11_r, *chi11_i, *psi11_r, *psi11_i ); } } } #endif blis-0.9.0/frame/include/level0/ri/bli_scalcjris.h000066400000000000000000000051401422157504600217510ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_SCALCJRIS_H #define BLIS_SCALCJRIS_H // scalcjris #define bli_sscalcjris( conj, ar, ai, xr, xi ) \ { \ bli_sscalris( (ar), (ai), (xr), (xi) ); \ } #define bli_dscalcjris( conj, ar, ai, xr, xi ) \ { \ bli_dscalris( (ar), (ai), (xr), (xi) ); \ } #define bli_cscalcjris( conj, ar, ai, xr, xi ) \ { \ if ( bli_is_conj( conj ) ) { bli_cscaljris( (ar), (ai), (xr), (xi) ); } \ else { bli_cscalris( (ar), (ai), (xr), (xi) ); } \ } #define bli_zscalcjris( conj, ar, ai, xr, xi ) \ { \ if ( bli_is_conj( conj ) ) { bli_zscaljris( (ar), (ai), (xr), (xi) ); } \ else { bli_zscalris( (ar), (ai), (xr), (xi) ); } \ } #define bli_iscalcjris( conj, ar, ai, xr, xi ) \ { \ bli_iscalris( (ar), (xi), (xr), (xi) ); \ } #define bli_scscalcjris( conj, ar, ai, xr, xi ) \ { \ bli_scscalris( (ar), (ai), (xr), (xi) ); \ } #define bli_dzscalcjris( conj, ar, ai, xr, xi ) \ { \ bli_dzscalris( (ar), (ai), (xr), (xi) ); \ } #endif blis-0.9.0/frame/include/level0/ri/bli_scaljris.h000066400000000000000000000042731422157504600216140ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_SCALJRIS_H #define BLIS_SCALJRIS_H // scaljris #define bli_sscaljris( ar, ai, xr, xi ) bli_sscalris( (ar), -(ai), (xr), (xi) ) #define bli_dscaljris( ar, ai, xr, xi ) bli_dscalris( (ar), -(ai), (xr), (xi) ) #define bli_cscaljris( ar, ai, xr, xi ) bli_cscalris( (ar), -(ai), (xr), (xi) ) #define bli_zscaljris( ar, ai, xr, xi ) bli_zscalris( (ar), -(ai), (xr), (xi) ) #define bli_scscaljris( ar, ai, xr, xi ) bli_scscalris( (ar), -(ai), (xr), (xi) ) #define bli_dzscaljris( ar, ai, xr, xi ) bli_dzscalris( (ar), -(ai), (xr), (xi) ) #endif blis-0.9.0/frame/include/level0/ri/bli_scalris.h000066400000000000000000000045661422157504600214470ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_SCALRIS_H #define BLIS_SCALRIS_H // scalris #define bli_sscalris( ar, ai, xr, xi ) \ { \ (xr) = (ar) * (xr); \ } #define bli_dscalris( ar, ai, xr, xi ) \ { \ (xr) = (ar) * (xr); \ } #define bli_cscalris( ar, ai, xr, xi ) \ { \ float yr = (ar) * (xr) - (ai) * (xi); \ float yi = (ai) * (xr) + (ar) * (xi); \ (xr) = yr; \ (xi) = yi; \ } #define bli_zscalris( ar, ai, xr, xi ) \ { \ double yr = (ar) * (xr) - (ai) * (xi); \ double yi = (ai) * (xr) + (ar) * (xi); \ (xr) = yr; \ (xi) = yi; \ } #define bli_scscalris( ar, ai, xr, xi ) \ { \ (xr) = (ar) * (xr); \ (xi) = (ar) * (xi); \ } #define bli_dzscalris( ar, ai, xr, xi ) \ { \ (xr) = (ar) * (xr); \ (xi) = (ar) * (xi); \ } #endif blis-0.9.0/frame/include/level0/ri/bli_scalris_mxn_uplo.h000066400000000000000000000063551422157504600233660ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_SCALRIS_MXN_UPLO_H #define BLIS_SCALRIS_MXN_UPLO_H // scalris_mxn_u #define bli_cscalris_mxn_u( diagoff, m, n, ar, ai, xr, xi, rs_x, cs_x ) \ { \ dim_t _i, _j; \ \ for ( _j = 0; _j < n; ++_j ) \ for ( _i = 0; _i < m; ++_i ) \ { \ if ( (doff_t)_j - (doff_t)_i >= diagoff ) \ { \ bli_cscalris( *(ar), \ *(ai), \ *((xr) + _i*rs_x + _j*cs_x), \ *((xi) + _i*rs_x + _j*cs_x) ); \ } \ } \ } #define bli_zscalris_mxn_u( diagoff, m, n, ar, ai, xr, xi, rs_x, cs_x ) \ { \ dim_t _i, _j; \ \ for ( _j = 0; _j < n; ++_j ) \ for ( _i = 0; _i < m; ++_i ) \ { \ if ( (doff_t)_j - (doff_t)_i >= diagoff ) \ { \ bli_zscalris( *(ar), \ *(ai), \ *((xr) + _i*rs_x + _j*cs_x), \ *((xi) + _i*rs_x + _j*cs_x) ); \ } \ } \ } // scalris_mxn_l #define bli_cscalris_mxn_l( diagoff, m, n, ar, ai, xr, xi, rs_x, cs_x ) \ { \ dim_t _i, _j; \ \ for ( _j = 0; _j < n; ++_j ) \ for ( _i = 0; _i < m; ++_i ) \ { \ if ( (doff_t)_j - (doff_t)_i <= diagoff ) \ { \ bli_cscalris( *(ar), \ *(ai), \ *((xr) + _i*rs_x + _j*cs_x), \ *((xi) + _i*rs_x + _j*cs_x) ); \ } \ } \ } #define bli_zscalris_mxn_l( diagoff, m, n, ar, ai, xr, xi, rs_x, cs_x ) \ { \ dim_t _i, _j; \ \ for ( _j = 0; _j < n; ++_j ) \ for ( _i = 0; _i < m; ++_i ) \ { \ if ( (doff_t)_j - (doff_t)_i <= diagoff ) \ { \ bli_zscalris( *(ar), \ *(ai), \ *((xr) + _i*rs_x + _j*cs_x), \ *((xi) + _i*rs_x + _j*cs_x) ); \ } \ } \ } #endif blis-0.9.0/frame/include/level0/ri/bli_set0ris.h000066400000000000000000000037251422157504600213740ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_SET0RIS_H #define BLIS_SET0RIS_H // set0ris #define bli_sset0ris( xr, xi ) bli_scopyris( 0.0F, 0.0F, xr, xi ) #define bli_dset0ris( xr, xi ) bli_dcopyris( 0.0 , 0.0 , xr, xi ) #define bli_cset0ris( xr, xi ) bli_ccopyris( 0.0F, 0.0F, xr, xi ) #define bli_zset0ris( xr, xi ) bli_zcopyris( 0.0 , 0.0 , xr, xi ) #endif blis-0.9.0/frame/include/level0/ri/bli_sqrt2ris.h000066400000000000000000000053731422157504600215750ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_SQRT2RIS_H #define BLIS_SQRT2RIS_H // sqrt2ris #define bli_ssqrt2ris( xr, xi, ar, ai ) \ { \ (ar) = sqrtf( (xr) ); \ } #define bli_dsqrt2ris( xr, xi, ar, ai ) \ { \ (ar) = sqrt( (xr) ); \ } #define bli_csqrt2ris( xr, xi, ar, ai ) \ { \ float s = bli_fmaxabs( (xr), (xi) ); \ float mag; \ if ( s == 0.0F ) mag = 0.0F; \ else \ { \ mag = sqrtf( s ) * \ sqrtf( ( (xr) / s ) * (xr) + \ ( (xi) / s ) * (xi) ); \ } \ \ (ar) = sqrtf( ( mag + (xr) ) / 2.0F ); \ (ai) = sqrtf( ( mag - (xi) ) / 2.0F ); \ } #define bli_zsqrt2ris( xr, xi, ar, ai ) \ { \ double s = bli_fmaxabs( (xr), (xi) ); \ double mag; \ if ( s == 0.0 ) mag = 0.0; \ else \ { \ mag = sqrt( s ) * \ sqrt( ( (xr) / s ) * (xr) + \ ( (xi) / s ) * (xi) ); \ } \ \ (ar) = sqrt( ( mag + (xr) ) / 2.0 ); \ (ai) = sqrt( ( mag - (xi) ) / 2.0 ); \ } #define bli_scsqrt2ris( xr, xi, ar, ai ) \ { \ (ar) = sqrtf( (xr) ); \ (ai) = 0.0F; \ } #define bli_dzsqrt2ris( xr, xi, ar, ai ) \ { \ (ar) = sqrt( (xr) ); \ (ai) = 0.0; \ } #endif blis-0.9.0/frame/include/level0/ri/bli_subjris.h000066400000000000000000000040111422157504600214510ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_SUBJRIS_H #define BLIS_SUBJRIS_H // subjris #define bli_ssubjris( ar, ai, xr, xi ) bli_ssubris( (ar), -(ai), (xr), (xi) ) #define bli_dsubjris( ar, ai, xr, xi ) bli_dsubris( (ar), -(ai), (xr), (xi) ) #define bli_csubjris( ar, ai, xr, xi ) bli_csubris( (ar), -(ai), (xr), (xi) ) #define bli_zsubjris( ar, ai, xr, xi ) bli_zsubris( (ar), -(ai), (xr), (xi) ) #endif blis-0.9.0/frame/include/level0/ri/bli_subris.h000066400000000000000000000040171422157504600213050ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_SUBRIS_H #define BLIS_SUBRIS_H // subris #define bli_ssubris( ar, ai, xr, xi ) \ { \ (xr) = (xr) - (ar); \ } #define bli_dsubris( ar, ai, xr, xi ) \ { \ (xr) = (xr) - (ar); \ } #define bli_csubris( ar, ai, xr, xi ) \ { \ (xr) = (xr) - (ar); \ (xi) = (xi) - (ai); \ } #define bli_zsubris( ar, ai, xr, xi ) \ { \ (xr) = (xr) - (ar); \ (xi) = (xi) - (ai); \ } #endif blis-0.9.0/frame/include/level0/ri/bli_swapris.h000066400000000000000000000047431422157504600214740ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_SWAPRIS_H #define BLIS_SWAPRIS_H // swapris #define bli_sswapris( ar, ai, br, bi ) \ { \ float tr, ti; \ \ bli_scopyris( (br), (bi), (tr), (ti) ); \ bli_scopyris( (ar), (ai), (br), (bi) ); \ bli_scopyris( (tr), (ti), (ar), (ai) ); \ } #define bli_dswapris( ar, ai, br, bi ) \ { \ double tr, ti; \ \ bli_dcopyris( (br), (bi), (tr), (ti) ); \ bli_dcopyris( (ar), (ai), (br), (bi) ); \ bli_dcopyris( (tr), (ti), (ar), (ai) ); \ } #define bli_cswapris( ar, ai, br, bi ) \ { \ scomplex tr, ti; \ \ bli_ccopyris( (br), (bi), (tr), (ti) ); \ bli_ccopyris( (ar), (ai), (br), (bi) ); \ bli_ccopyris( (tr), (ti), (ar), (ai) ); \ } #define bli_zswapris( ar, ai, br, bi ) \ { \ dcomplex tr, ti; \ \ bli_zcopyris( (br), (bi), (tr), (ti) ); \ bli_zcopyris( (ar), (ai), (br), (bi) ); \ bli_zcopyris( (tr), (ti), (ar), (ai) ); \ } #endif blis-0.9.0/frame/include/level0/ri/bli_xpbyjris.h000066400000000000000000000125231422157504600216510ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_XPBYJRIS_H #define BLIS_XPBYJRIS_H // xpbyjris #define bli_rxxpbyjris( xr, xi, br, bi, yr, yi ) \ { \ (yr) = (xr) + (br) * (yr); \ } #define bli_cxxpbyjris( xr, xi, br, bi, yr, yi ) \ { \ const __typeof__(yr) yt_r = (xr) + (br) * (yr) - (bi) * (yi); \ const __typeof__(yi) yt_i = -(xi) + (bi) * (yr) + (br) * (yi); \ (yr) = yt_r; \ (yi) = yt_i; \ } #define bli_crxpbyjris( xr, xi, br, bi, yr, yi ) \ { \ const __typeof__(yr) yt_r = (xr) + (br) * (yr); \ const __typeof__(yi) yt_i = -(xi) + (br) * (yi); \ (yr) = yt_r; \ (yi) = yt_i; \ } // Notes: // - The first char encodes the type of x. // - The second char encodes the type of b. // - The third char encodes the type of y. // -- (xby) = (??s) ------------------------------------------------------------ #define bli_sssxpbyjris bli_rxxpbyjris #define bli_dssxpbyjris bli_rxxpbyjris #define bli_cssxpbyjris bli_rxxpbyjris #define bli_zssxpbyjris bli_rxxpbyjris #define bli_sdsxpbyjris bli_rxxpbyjris #define bli_ddsxpbyjris bli_rxxpbyjris #define bli_cdsxpbyjris bli_rxxpbyjris #define bli_zdsxpbyjris bli_rxxpbyjris #define bli_scsxpbyjris bli_rxxpbyjris #define bli_dcsxpbyjris bli_rxxpbyjris #define bli_ccsxpbyjris bli_rxxpbyjris #define bli_zcsxpbyjris bli_rxxpbyjris #define bli_szsxpbyjris bli_rxxpbyjris #define bli_dzsxpbyjris bli_rxxpbyjris #define bli_czsxpbyjris bli_rxxpbyjris #define bli_zzsxpbyjris bli_rxxpbyjris // -- (xby) = (??d) ------------------------------------------------------------ #define bli_ssdxpbyjris bli_rxxpbyjris #define bli_dsdxpbyjris bli_rxxpbyjris #define bli_csdxpbyjris bli_rxxpbyjris #define bli_zsdxpbyjris bli_rxxpbyjris #define bli_sddxpbyjris bli_rxxpbyjris #define bli_dddxpbyjris bli_rxxpbyjris #define bli_cddxpbyjris bli_rxxpbyjris #define bli_zddxpbyjris bli_rxxpbyjris #define bli_scdxpbyjris bli_rxxpbyjris #define bli_dcdxpbyjris bli_rxxpbyjris #define bli_ccdxpbyjris bli_rxxpbyjris #define bli_zcdxpbyjris bli_rxxpbyjris #define bli_szdxpbyjris bli_rxxpbyjris #define bli_dzdxpbyjris bli_rxxpbyjris #define bli_czdxpbyjris bli_rxxpbyjris #define bli_zzdxpbyjris bli_rxxpbyjris // -- (xby) = (??c) ------------------------------------------------------------ #define bli_sscxpbyjris bli_rxxpbyjris #define bli_dscxpbyjris bli_rxxpbyjris #define bli_cscxpbyjris bli_crxpbyjris #define bli_zscxpbyjris bli_crxpbyjris #define bli_sdcxpbyjris bli_rxxpbyjris #define bli_ddcxpbyjris bli_rxxpbyjris #define bli_cdcxpbyjris bli_crxpbyjris #define bli_zdcxpbyjris bli_crxpbyjris #define bli_sccxpbyjris bli_cxxpbyjris #define bli_dccxpbyjris bli_cxxpbyjris #define bli_cccxpbyjris bli_cxxpbyjris #define bli_zccxpbyjris bli_cxxpbyjris #define bli_szcxpbyjris bli_cxxpbyjris #define bli_dzcxpbyjris bli_cxxpbyjris #define bli_czcxpbyjris bli_cxxpbyjris #define bli_zzcxpbyjris bli_cxxpbyjris // -- (xby) = (??z) ------------------------------------------------------------ #define bli_sszxpbyjris bli_rxxpbyjris #define bli_dszxpbyjris bli_rxxpbyjris #define bli_cszxpbyjris bli_crxpbyjris #define bli_zszxpbyjris bli_crxpbyjris #define bli_sdzxpbyjris bli_rxxpbyjris #define bli_ddzxpbyjris bli_rxxpbyjris #define bli_cdzxpbyjris bli_crxpbyjris #define bli_zdzxpbyjris bli_crxpbyjris #define bli_sczxpbyjris bli_cxxpbyjris #define bli_dczxpbyjris bli_cxxpbyjris #define bli_cczxpbyjris bli_cxxpbyjris #define bli_zczxpbyjris bli_cxxpbyjris #define bli_szzxpbyjris bli_cxxpbyjris #define bli_dzzxpbyjris bli_cxxpbyjris #define bli_czzxpbyjris bli_cxxpbyjris #define bli_zzzxpbyjris bli_cxxpbyjris #define bli_sxpbyjris bli_sssxpbyjris #define bli_dxpbyjris bli_dddxpbyjris #define bli_cxpbyjris bli_cccxpbyjris #define bli_zxpbyjris bli_zzzxpbyjris #endif blis-0.9.0/frame/include/level0/ri/bli_xpbyris.h000066400000000000000000000123011422157504600214710ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_XPBYRIS_H #define BLIS_XPBYRIS_H // xpbyris #define bli_rxxpbyris( xr, xi, br, bi, yr, yi ) \ { \ (yr) = (xr) + (br) * (yr); \ } #define bli_cxxpbyris( xr, xi, br, bi, yr, yi ) \ { \ const __typeof__(yr) yt_r = (xr) + (br) * (yr) - (bi) * (yi); \ const __typeof__(yi) yt_i = (xi) + (bi) * (yr) + (br) * (yi); \ (yr) = yt_r; \ (yi) = yt_i; \ } #define bli_crxpbyris( xr, xi, br, bi, yr, yi ) \ { \ const __typeof__(yr) yt_r = (xr) + (br) * (yr); \ const __typeof__(yi) yt_i = (xi) + (br) * (yi); \ (yr) = yt_r; \ (yi) = yt_i; \ } // Notes: // - The first char encodes the type of x. // - The second char encodes the type of b. // - The third char encodes the type of y. // -- (xby) = (??s) ------------------------------------------------------------ #define bli_sssxpbyris bli_rxxpbyris #define bli_dssxpbyris bli_rxxpbyris #define bli_cssxpbyris bli_rxxpbyris #define bli_zssxpbyris bli_rxxpbyris #define bli_sdsxpbyris bli_rxxpbyris #define bli_ddsxpbyris bli_rxxpbyris #define bli_cdsxpbyris bli_rxxpbyris #define bli_zdsxpbyris bli_rxxpbyris #define bli_scsxpbyris bli_rxxpbyris #define bli_dcsxpbyris bli_rxxpbyris #define bli_ccsxpbyris bli_rxxpbyris #define bli_zcsxpbyris bli_rxxpbyris #define bli_szsxpbyris bli_rxxpbyris #define bli_dzsxpbyris bli_rxxpbyris #define bli_czsxpbyris bli_rxxpbyris #define bli_zzsxpbyris bli_rxxpbyris // -- (xby) = (??d) ------------------------------------------------------------ #define bli_ssdxpbyris bli_rxxpbyris #define bli_dsdxpbyris bli_rxxpbyris #define bli_csdxpbyris bli_rxxpbyris #define bli_zsdxpbyris bli_rxxpbyris #define bli_sddxpbyris bli_rxxpbyris #define bli_dddxpbyris bli_rxxpbyris #define bli_cddxpbyris bli_rxxpbyris #define bli_zddxpbyris bli_rxxpbyris #define bli_scdxpbyris bli_rxxpbyris #define bli_dcdxpbyris bli_rxxpbyris #define bli_ccdxpbyris bli_rxxpbyris #define bli_zcdxpbyris bli_rxxpbyris #define bli_szdxpbyris bli_rxxpbyris #define bli_dzdxpbyris bli_rxxpbyris #define bli_czdxpbyris bli_rxxpbyris #define bli_zzdxpbyris bli_rxxpbyris // -- (xby) = (??c) ------------------------------------------------------------ #define bli_sscxpbyris bli_rxxpbyris #define bli_dscxpbyris bli_rxxpbyris #define bli_cscxpbyris bli_crxpbyris #define bli_zscxpbyris bli_crxpbyris #define bli_sdcxpbyris bli_rxxpbyris #define bli_ddcxpbyris bli_rxxpbyris #define bli_cdcxpbyris bli_crxpbyris #define bli_zdcxpbyris bli_crxpbyris #define bli_sccxpbyris bli_cxxpbyris #define bli_dccxpbyris bli_cxxpbyris #define bli_cccxpbyris bli_cxxpbyris #define bli_zccxpbyris bli_cxxpbyris #define bli_szcxpbyris bli_cxxpbyris #define bli_dzcxpbyris bli_cxxpbyris #define bli_czcxpbyris bli_cxxpbyris #define bli_zzcxpbyris bli_cxxpbyris // -- (xby) = (??z) ------------------------------------------------------------ #define bli_sszxpbyris bli_rxxpbyris #define bli_dszxpbyris bli_rxxpbyris #define bli_cszxpbyris bli_crxpbyris #define bli_zszxpbyris bli_crxpbyris #define bli_sdzxpbyris bli_rxxpbyris #define bli_ddzxpbyris bli_rxxpbyris #define bli_cdzxpbyris bli_crxpbyris #define bli_zdzxpbyris bli_crxpbyris #define bli_sczxpbyris bli_cxxpbyris #define bli_dczxpbyris bli_cxxpbyris #define bli_cczxpbyris bli_cxxpbyris #define bli_zczxpbyris bli_cxxpbyris #define bli_szzxpbyris bli_cxxpbyris #define bli_dzzxpbyris bli_cxxpbyris #define bli_czzxpbyris bli_cxxpbyris #define bli_zzzxpbyris bli_cxxpbyris #define bli_sxpbyris bli_sssxpbyris #define bli_dxpbyris bli_dddxpbyris #define bli_cxpbyris bli_cccxpbyris #define bli_zxpbyris bli_zzzxpbyris #endif blis-0.9.0/frame/thread/000077500000000000000000000000001422157504600150205ustar00rootroot00000000000000blis-0.9.0/frame/thread/bli_l3_decor.h000066400000000000000000000051141422157504600175120ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_L3_DECOR_H #define BLIS_L3_DECOR_H // -- conventional definitions ------------------------------------------------- // Level-3 internal function type. typedef void (*l3int_t) ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ); // Level-3 thread decorator prototype. void bli_l3_thread_decorator ( l3int_t func, opid_t family, obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl ); // Include definitions specific to the method of multithreading for the // conventional code path. #include "bli_l3_decor_single.h" #include "bli_l3_decor_openmp.h" #include "bli_l3_decor_pthreads.h" #endif blis-0.9.0/frame/thread/bli_l3_decor_openmp.c000066400000000000000000000211261422157504600210640ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #ifdef BLIS_ENABLE_OPENMP // Define a dummy function bli_l3_thread_entry(), which is needed in the // pthreads version, so that when building Windows DLLs (with OpenMP enabled // or no multithreading) we don't risk having an unresolved symbol. void* bli_l3_thread_entry( void* data_void ) { return NULL; } //#define PRINT_THRINFO void bli_l3_thread_decorator ( l3int_t func, opid_t family, obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl ) { // This is part of a hack to support mixed domain in bli_gemm_front(). // Sometimes we need to specify a non-standard schema for A and B, and // we decided to transmit them via the schema field in the obj_t's // rather than pass them in as function parameters. Once the values // have been read, we immediately reset them back to their expected // values for unpacked objects. pack_t schema_a = bli_obj_pack_schema( a ); pack_t schema_b = bli_obj_pack_schema( b ); bli_obj_set_pack_schema( BLIS_NOT_PACKED, a ); bli_obj_set_pack_schema( BLIS_NOT_PACKED, b ); // Query the total number of threads from the rntm_t object. const dim_t n_threads = bli_rntm_num_threads( rntm ); #ifdef PRINT_THRINFO err_t r_val; thrinfo_t** threads = bli_malloc_intl( n_threads * sizeof( thrinfo_t* ), &r_val ); #endif // NOTE: The sba was initialized in bli_init(). // Check out an array_t from the small block allocator. This is done // with an internal lock to ensure only one application thread accesses // the sba at a time. bli_sba_checkout_array() will also automatically // resize the array_t, if necessary. array_t* restrict array = bli_sba_checkout_array( n_threads ); // Access the pool_t* for thread 0 and embed it into the rntm. We do // this up-front only so that we have the rntm_t.sba_pool field // initialized and ready for the global communicator creation below. bli_sba_rntm_set_pool( 0, array, rntm ); // Set the packing block allocator field of the rntm. This will be // inherited by all of the child threads when they make local copies of // the rntm below. bli_pba_rntm_set_pba( rntm ); // Allocate a global communicator for the root thrinfo_t structures. thrcomm_t* restrict gl_comm = bli_thrcomm_create( rntm, n_threads ); _Pragma( "omp parallel num_threads(n_threads)" ) { // Create a thread-local copy of the master thread's rntm_t. This is // necessary since we want each thread to be able to track its own // small block pool_t as it executes down the function stack. rntm_t rntm_l = *rntm; rntm_t* restrict rntm_p = &rntm_l; // Query the thread's id from OpenMP. const dim_t tid = omp_get_thread_num(); // Check for a somewhat obscure OpenMP thread-mistmatch issue. bli_l3_thread_decorator_thread_check( n_threads, tid, gl_comm, rntm_p ); // Use the thread id to access the appropriate pool_t* within the // array_t, and use it to set the sba_pool field within the rntm_t. // If the pool_t* element within the array_t is NULL, it will first // be allocated/initialized. bli_sba_rntm_set_pool( tid, array, rntm_p ); obj_t a_t, b_t, c_t; cntl_t* cntl_use; thrinfo_t* thread; // Alias thread-local copies of A, B, and C. These will be the objects // we pass down the algorithmic function stack. Making thread-local // aliases is highly recommended in case a thread needs to change any // of the properties of an object without affecting other threads' // objects. bli_obj_alias_to( a, &a_t ); bli_obj_alias_to( b, &b_t ); bli_obj_alias_to( c, &c_t ); // Create a default control tree for the operation, if needed. bli_l3_cntl_create_if( family, schema_a, schema_b, &a_t, &b_t, &c_t, rntm_p, cntl, &cntl_use ); // Create the root node of the current thread's thrinfo_t structure. bli_l3_thrinfo_create_root( tid, gl_comm, rntm_p, cntl_use, &thread ); #if 1 func ( alpha, &a_t, &b_t, beta, &c_t, cntx, rntm_p, cntl_use, thread ); #else bli_thrinfo_grow_tree ( rntm_p, cntl_use, thread ); #endif // Free the thread's local control tree. bli_l3_cntl_free( rntm_p, cntl_use, thread ); #ifdef PRINT_THRINFO threads[tid] = thread; #else // Free the current thread's thrinfo_t structure. bli_l3_thrinfo_free( rntm_p, thread ); #endif } // We shouldn't free the global communicator since it was already freed // by the global communicator's chief thread in bli_l3_thrinfo_free() // (called above). #ifdef PRINT_THRINFO if ( family != BLIS_TRSM ) bli_l3_thrinfo_print_gemm_paths( threads ); else bli_l3_thrinfo_print_trsm_paths( threads ); exit(1); #endif // Check the array_t back into the small block allocator. Similar to the // check-out, this is done using a lock embedded within the sba to ensure // mutual exclusion. bli_sba_checkin_array( array ); } // ----------------------------------------------------------------------------- void bli_l3_thread_decorator_thread_check ( dim_t n_threads, dim_t tid, thrcomm_t* gl_comm, rntm_t* rntm ) { dim_t n_threads_real = omp_get_num_threads(); // Check if the number of OpenMP threads created within this parallel // region is different from the number of threads that were requested // of BLIS. This inequality may trigger when, for example, the // following conditions are satisfied: // - an application is executing an OpenMP parallel region in which // BLIS is invoked, // - BLIS is configured for multithreading via OpenMP, // - OMP_NUM_THREADS = t > 1, // - the number of threads requested of BLIS (regardless of method) // is p <= t, // - OpenMP nesting is disabled. // In this situation, the application spawns t threads. Each application // thread calls gemm (for example). Each gemm will attempt to spawn p // threads via OpenMP. However, since nesting is disabled, the OpenMP // implementation finds that t >= p threads are already spawned, and // thus it doesn't spawn *any* additional threads for each gemm. if ( n_threads_real != n_threads ) { // If the number of threads active in the current region is not // equal to the number requested of BLIS, we then only continue // if the number of threads in the current region is 1. If, for // example, BLIS requested 4 threads but only got 3, then we // abort(). //if ( tid == 0 ) //{ if ( n_threads_real != 1 ) { bli_print_msg( "A different number of threads was " "created than was requested.", __FILE__, __LINE__ ); bli_abort(); } //n_threads = 1; // not needed since it has no effect? bli_thrcomm_init( 1, gl_comm ); bli_rntm_set_num_threads_only( 1, rntm ); bli_rntm_set_ways_only( 1, 1, 1, 1, 1, rntm ); //} // Synchronize all threads and continue. _Pragma( "omp barrier" ) } } #endif blis-0.9.0/frame/thread/bli_l3_decor_openmp.h000066400000000000000000000040211422157504600210640ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_L3_DECOR_OPENMP_H #define BLIS_L3_DECOR_OPENMP_H // Definitions specific to situations when OpenMP multithreading is enabled. #ifdef BLIS_ENABLE_OPENMP void bli_l3_thread_decorator_thread_check ( dim_t n_threads, dim_t tid, thrcomm_t* gl_comm, rntm_t* rntm ); #endif #endif blis-0.9.0/frame/thread/bli_l3_decor_pthreads.c000066400000000000000000000207121422157504600214000ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #ifdef BLIS_ENABLE_PTHREADS // A data structure to assist in passing operands to additional threads. typedef struct thread_data { l3int_t func; opid_t family; pack_t schema_a; pack_t schema_b; obj_t* alpha; obj_t* a; obj_t* b; obj_t* beta; obj_t* c; cntx_t* cntx; rntm_t* rntm; cntl_t* cntl; dim_t tid; thrcomm_t* gl_comm; array_t* array; } thread_data_t; // Entry point for additional threads void* bli_l3_thread_entry( void* data_void ) { thread_data_t* data = data_void; l3int_t func = data->func; opid_t family = data->family; pack_t schema_a = data->schema_a; pack_t schema_b = data->schema_b; obj_t* alpha = data->alpha; obj_t* a = data->a; obj_t* b = data->b; obj_t* beta = data->beta; obj_t* c = data->c; cntx_t* cntx = data->cntx; rntm_t* rntm = data->rntm; cntl_t* cntl = data->cntl; dim_t tid = data->tid; array_t* array = data->array; thrcomm_t* gl_comm = data->gl_comm; // Create a thread-local copy of the master thread's rntm_t. This is // necessary since we want each thread to be able to track its own // small block pool_t as it executes down the function stack. rntm_t rntm_l = *rntm; rntm_t* restrict rntm_p = &rntm_l; // Use the thread id to access the appropriate pool_t* within the // array_t, and use it to set the sba_pool field within the rntm_t. // If the pool_t* element within the array_t is NULL, it will first // be allocated/initialized. bli_sba_rntm_set_pool( tid, array, rntm_p ); obj_t a_t, b_t, c_t; cntl_t* cntl_use; thrinfo_t* thread; // Alias thread-local copies of A, B, and C. These will be the objects // we pass down the algorithmic function stack. Making thread-local // aliases is highly recommended in case a thread needs to change any // of the properties of an object without affecting other threads' // objects. bli_obj_alias_to( a, &a_t ); bli_obj_alias_to( b, &b_t ); bli_obj_alias_to( c, &c_t ); // Create a default control tree for the operation, if needed. bli_l3_cntl_create_if( family, schema_a, schema_b, &a_t, &b_t, &c_t, rntm_p, cntl, &cntl_use ); // Create the root node of the current thread's thrinfo_t structure. bli_l3_thrinfo_create_root( tid, gl_comm, rntm_p, cntl_use, &thread ); func ( alpha, &a_t, &b_t, beta, &c_t, cntx, rntm_p, cntl_use, thread ); // Free the thread's local control tree. bli_l3_cntl_free( rntm_p, cntl_use, thread ); // Free the current thread's thrinfo_t structure. bli_l3_thrinfo_free( rntm_p, thread ); return NULL; } void bli_l3_thread_decorator ( l3int_t func, opid_t family, obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl ) { err_t r_val; // This is part of a hack to support mixed domain in bli_gemm_front(). // Sometimes we need to specify a non-standard schema for A and B, and // we decided to transmit them via the schema field in the obj_t's // rather than pass them in as function parameters. Once the values // have been read, we immediately reset them back to their expected // values for unpacked objects. pack_t schema_a = bli_obj_pack_schema( a ); pack_t schema_b = bli_obj_pack_schema( b ); bli_obj_set_pack_schema( BLIS_NOT_PACKED, a ); bli_obj_set_pack_schema( BLIS_NOT_PACKED, b ); // Query the total number of threads from the context. const dim_t n_threads = bli_rntm_num_threads( rntm ); // NOTE: The sba was initialized in bli_init(). // Check out an array_t from the small block allocator. This is done // with an internal lock to ensure only one application thread accesses // the sba at a time. bli_sba_checkout_array() will also automatically // resize the array_t, if necessary. array_t* restrict array = bli_sba_checkout_array( n_threads ); // Access the pool_t* for thread 0 and embed it into the rntm. We do // this up-front only so that we have the rntm_t.sba_pool field // initialized and ready for the global communicator creation below. bli_sba_rntm_set_pool( 0, array, rntm ); // Set the packing block allocator field of the rntm. This will be // inherited by all of the child threads when they make local copies of // the rntm below. bli_pba_rntm_set_pba( rntm ); // Allocate a global communicator for the root thrinfo_t structures. thrcomm_t* restrict gl_comm = bli_thrcomm_create( rntm, n_threads ); // Allocate an array of pthread objects and auxiliary data structs to pass // to the thread entry functions. #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_l3_thread_decorator().pth: " ); #endif bli_pthread_t* pthreads = bli_malloc_intl( sizeof( bli_pthread_t ) * n_threads, &r_val ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_l3_thread_decorator().pth: " ); #endif thread_data_t* datas = bli_malloc_intl( sizeof( thread_data_t ) * n_threads, &r_val ); // NOTE: We must iterate backwards so that the chief thread (thread id 0) // can spawn all other threads before proceeding with its own computation. for ( dim_t tid = n_threads - 1; 0 <= tid; tid-- ) { // Set up thread data for additional threads (beyond thread 0). datas[tid].func = func; datas[tid].family = family; datas[tid].schema_a = schema_a; datas[tid].schema_b = schema_b; datas[tid].alpha = alpha; datas[tid].a = a; datas[tid].b = b; datas[tid].beta = beta; datas[tid].c = c; datas[tid].cntx = cntx; datas[tid].rntm = rntm; datas[tid].cntl = cntl; datas[tid].tid = tid; datas[tid].gl_comm = gl_comm; datas[tid].array = array; // Spawn additional threads for ids greater than 1. if ( tid != 0 ) bli_pthread_create( &pthreads[tid], NULL, &bli_l3_thread_entry, &datas[tid] ); else bli_l3_thread_entry( ( void* )(&datas[0]) ); } // We shouldn't free the global communicator since it was already freed // by the global communicator's chief thread in bli_l3_thrinfo_free() // (called from the thread entry function). // Thread 0 waits for additional threads to finish. for ( dim_t tid = 1; tid < n_threads; tid++ ) { bli_pthread_join( pthreads[tid], NULL ); } // Check the array_t back into the small block allocator. Similar to the // check-out, this is done using a lock embedded within the sba to ensure // mutual exclusion. bli_sba_checkin_array( array ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_l3_thread_decorator().pth: " ); #endif bli_free_intl( pthreads ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_l3_thread_decorator().pth: " ); #endif bli_free_intl( datas ); } #endif blis-0.9.0/frame/thread/bli_l3_decor_pthreads.h000066400000000000000000000036251422157504600214110ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_L3_DECOR_PTHREADS_H #define BLIS_L3_DECOR_PTHREADS_H // Definitions specific to situations when POSIX multithreading is enabled. #ifdef BLIS_ENABLE_PTHREADS // Thread entry point prototype. void* bli_l3_thread_entry( void* data_void ); #endif #endif blis-0.9.0/frame/thread/bli_l3_decor_single.c000066400000000000000000000126351422157504600210540ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #ifndef BLIS_ENABLE_MULTITHREADING void bli_l3_thread_decorator ( l3int_t func, opid_t family, obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl ) { // This is part of a hack to support mixed domain in bli_gemm_front(). // Sometimes we need to specify a non-standard schema for A and B, and // we decided to transmit them via the schema field in the obj_t's // rather than pass them in as function parameters. Once the values // have been read, we immediately reset them back to their expected // values for unpacked objects. pack_t schema_a = bli_obj_pack_schema( a ); pack_t schema_b = bli_obj_pack_schema( b ); bli_obj_set_pack_schema( BLIS_NOT_PACKED, a ); bli_obj_set_pack_schema( BLIS_NOT_PACKED, b ); // For sequential execution, we use only one thread. const dim_t n_threads = 1; // NOTE: The sba was initialized in bli_init(). // Check out an array_t from the small block allocator. This is done // with an internal lock to ensure only one application thread accesses // the sba at a time. bli_sba_checkout_array() will also automatically // resize the array_t, if necessary. array_t* restrict array = bli_sba_checkout_array( n_threads ); // Access the pool_t* for thread 0 and embed it into the rntm. We do // this up-front only so that we can create the global comm below. bli_sba_rntm_set_pool( 0, array, rntm ); // Set the packing block allocator field of the rntm. bli_pba_rntm_set_pba( rntm ); // Allcoate a global communicator for the root thrinfo_t structures. thrcomm_t* restrict gl_comm = bli_thrcomm_create( rntm, n_threads ); { // NOTE: We don't need to create another copy of the rntm_t since // it was already copied in one of the high-level oapi functions. rntm_t* restrict rntm_p = rntm; cntl_t* cntl_use; thrinfo_t* thread; const dim_t tid = 0; // Use the thread id to access the appropriate pool_t* within the // array_t, and use it to set the sba_pool field within the rntm_t. // If the pool_t* element within the array_t is NULL, it will first // be allocated/initialized. // NOTE: This is commented out because, in the single-threaded case, // this is redundant since it's already been done above. //bli_sba_rntm_set_pool( tid, array, rntm_p ); // NOTE: Unlike with the _openmp.c and _pthreads.c variants, we don't // need to alias objects for A, B, and C since they were already aliased // in bli_*_front(). However, we may add aliasing here in the future so // that, with all three (_single.c, _openmp.c, _pthreads.c) implementations // consistently providing local aliases, we can then eliminate aliasing // elsewhere. // Create a default control tree for the operation, if needed. bli_l3_cntl_create_if( family, schema_a, schema_b, a, b, c, rntm_p, cntl, &cntl_use ); // Create the root node of the thread's thrinfo_t structure. bli_l3_thrinfo_create_root( tid, gl_comm, rntm_p, cntl_use, &thread ); func ( alpha, a, b, beta, c, cntx, rntm_p, cntl_use, thread ); // Free the thread's local control tree. bli_l3_cntl_free( rntm_p, cntl_use, thread ); // Free the current thread's thrinfo_t structure. bli_l3_thrinfo_free( rntm_p, thread ); } // We shouldn't free the global communicator since it was already freed // by the global communicator's chief thread in bli_l3_thrinfo_free() // (called above). // Check the array_t back into the small block allocator. Similar to the // check-out, this is done using a lock embedded within the sba to ensure // mutual exclusion. bli_sba_checkin_array( array ); } #endif blis-0.9.0/frame/thread/bli_l3_decor_single.h000066400000000000000000000035031422157504600210530ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_L3_DECOR_SINGLE_H #define BLIS_L3_DECOR_SINGLE_H // Definitions specific to situations when multithreading is disabled. #ifndef BLIS_ENABLE_MULTITHREADING #endif #endif blis-0.9.0/frame/thread/bli_l3_sup_decor.h000066400000000000000000000051261422157504600204040ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_L3_SUP_DECOR_H #define BLIS_L3_SUP_DECOR_H // -- sup definitions ---------------------------------------------------------- // Level-3 sup internal function type. typedef err_t (*l3supint_t) ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, rntm_t* rntm, thrinfo_t* thread ); // Level-3 sup thread decorator prototype. err_t bli_l3_sup_thread_decorator ( l3supint_t func, opid_t family, obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, rntm_t* rntm ); // Include definitions specific to the method of multithreading for the // sup code path. #include "bli_l3_sup_decor_single.h" #include "bli_l3_sup_decor_openmp.h" #include "bli_l3_sup_decor_pthreads.h" #endif blis-0.9.0/frame/thread/bli_l3_sup_decor_openmp.c000066400000000000000000000120031422157504600217450ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #ifdef BLIS_ENABLE_OPENMP // Define a dummy function bli_l3_sup_thread_entry(), which is needed in the // pthreads version, so that when building Windows DLLs (with OpenMP enabled // or no multithreading) we don't risk having an unresolved symbol. void* bli_l3_sup_thread_entry( void* data_void ) { return NULL; } //#define PRINT_THRINFO err_t bli_l3_sup_thread_decorator ( l3supint_t func, opid_t family, obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, rntm_t* rntm ) { // Query the total number of threads from the rntm_t object. const dim_t n_threads = bli_rntm_num_threads( rntm ); // NOTE: The sba was initialized in bli_init(). // Check out an array_t from the small block allocator. This is done // with an internal lock to ensure only one application thread accesses // the sba at a time. bli_sba_checkout_array() will also automatically // resize the array_t, if necessary. array_t* restrict array = bli_sba_checkout_array( n_threads ); // Access the pool_t* for thread 0 and embed it into the rntm. We do // this up-front only so that we have the rntm_t.sba_pool field // initialized and ready for the global communicator creation below. bli_sba_rntm_set_pool( 0, array, rntm ); // Set the packing block allocator field of the rntm. This will be // inherited by all of the child threads when they make local copies of // the rntm below. bli_pba_rntm_set_pba( rntm ); // Allcoate a global communicator for the root thrinfo_t structures. thrcomm_t* restrict gl_comm = bli_thrcomm_create( rntm, n_threads ); _Pragma( "omp parallel num_threads(n_threads)" ) { // Create a thread-local copy of the master thread's rntm_t. This is // necessary since we want each thread to be able to track its own // small block pool_t as it executes down the function stack. rntm_t rntm_l = *rntm; rntm_t* restrict rntm_p = &rntm_l; // Query the thread's id from OpenMP. const dim_t tid = omp_get_thread_num(); // Check for a somewhat obscure OpenMP thread-mistmatch issue. // NOTE: This calls the same function used for the conventional/large // code path. bli_l3_thread_decorator_thread_check( n_threads, tid, gl_comm, rntm_p ); // Use the thread id to access the appropriate pool_t* within the // array_t, and use it to set the sba_pool field within the rntm_t. // If the pool_t* element within the array_t is NULL, it will first // be allocated/initialized. bli_sba_rntm_set_pool( tid, array, rntm_p ); thrinfo_t* thread = NULL; // Create the root node of the thread's thrinfo_t structure. bli_l3_sup_thrinfo_create_root( tid, gl_comm, rntm_p, &thread ); func ( alpha, a, b, beta, c, cntx, rntm_p, thread ); // Free the current thread's thrinfo_t structure. bli_l3_sup_thrinfo_free( rntm_p, thread ); } // We shouldn't free the global communicator since it was already freed // by the global communicator's chief thread in bli_l3_thrinfo_free() // (called from the thread entry function). // Check the array_t back into the small block allocator. Similar to the // check-out, this is done using a lock embedded within the sba to ensure // mutual exclusion. bli_sba_checkin_array( array ); return BLIS_SUCCESS; } #endif blis-0.9.0/frame/thread/bli_l3_sup_decor_openmp.h000066400000000000000000000035101422157504600217550ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_L3_SUP_DECOR_OPENMP_H #define BLIS_L3_SUP_DECOR_OPENMP_H // Definitions specific to situations when OpenMP multithreading is enabled. #ifdef BLIS_ENABLE_OPENMP #endif #endif blis-0.9.0/frame/thread/bli_l3_sup_decor_pthreads.c000066400000000000000000000156631422157504600223000ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #ifdef BLIS_ENABLE_PTHREADS // A data structure to assist in passing operands to additional threads. typedef struct thread_data { l3supint_t func; opid_t family; obj_t* alpha; obj_t* a; obj_t* b; obj_t* beta; obj_t* c; cntx_t* cntx; rntm_t* rntm; dim_t tid; thrcomm_t* gl_comm; array_t* array; } thread_data_t; // Entry point for additional threads void* bli_l3_sup_thread_entry( void* data_void ) { thread_data_t* data = data_void; l3supint_t func = data->func; opid_t family = data->family; obj_t* alpha = data->alpha; obj_t* a = data->a; obj_t* b = data->b; obj_t* beta = data->beta; obj_t* c = data->c; cntx_t* cntx = data->cntx; rntm_t* rntm = data->rntm; dim_t tid = data->tid; array_t* array = data->array; thrcomm_t* gl_comm = data->gl_comm; ( void )family; // Create a thread-local copy of the master thread's rntm_t. This is // necessary since we want each thread to be able to track its own // small block pool_t as it executes down the function stack. rntm_t rntm_l = *rntm; rntm_t* restrict rntm_p = &rntm_l; // Use the thread id to access the appropriate pool_t* within the // array_t, and use it to set the sba_pool field within the rntm_t. // If the pool_t* element within the array_t is NULL, it will first // be allocated/initialized. bli_sba_rntm_set_pool( tid, array, rntm_p ); thrinfo_t* thread = NULL; // Create the root node of the current thread's thrinfo_t structure. bli_l3_sup_thrinfo_create_root( tid, gl_comm, rntm_p, &thread ); func ( alpha, a, b, beta, c, cntx, rntm_p, thread ); // Free the current thread's thrinfo_t structure. bli_l3_sup_thrinfo_free( rntm_p, thread ); return NULL; } err_t bli_l3_sup_thread_decorator ( l3supint_t func, opid_t family, obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, rntm_t* rntm ) { err_t r_val; // Query the total number of threads from the context. const dim_t n_threads = bli_rntm_num_threads( rntm ); // NOTE: The sba was initialized in bli_init(). // Check out an array_t from the small block allocator. This is done // with an internal lock to ensure only one application thread accesses // the sba at a time. bli_sba_checkout_array() will also automatically // resize the array_t, if necessary. array_t* restrict array = bli_sba_checkout_array( n_threads ); // Access the pool_t* for thread 0 and embed it into the rntm. We do // this up-front only so that we have the rntm_t.sba_pool field // initialized and ready for the global communicator creation below. bli_sba_rntm_set_pool( 0, array, rntm ); // Set the packing block allocator field of the rntm. This will be // inherited by all of the child threads when they make local copies of // the rntm below. bli_pba_rntm_set_pba( rntm ); // Allocate a global communicator for the root thrinfo_t structures. thrcomm_t* restrict gl_comm = bli_thrcomm_create( rntm, n_threads ); // Allocate an array of pthread objects and auxiliary data structs to pass // to the thread entry functions. #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_l3_thread_decorator().pth: " ); #endif bli_pthread_t* pthreads = bli_malloc_intl( sizeof( bli_pthread_t ) * n_threads, &r_val ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_l3_thread_decorator().pth: " ); #endif thread_data_t* datas = bli_malloc_intl( sizeof( thread_data_t ) * n_threads, &r_val ); // NOTE: We must iterate backwards so that the chief thread (thread id 0) // can spawn all other threads before proceeding with its own computation. for ( dim_t tid = n_threads - 1; 0 <= tid; tid-- ) { // Set up thread data for additional threads (beyond thread 0). datas[tid].func = func; datas[tid].family = family; datas[tid].alpha = alpha; datas[tid].a = a; datas[tid].b = b; datas[tid].beta = beta; datas[tid].c = c; datas[tid].cntx = cntx; datas[tid].rntm = rntm; datas[tid].tid = tid; datas[tid].gl_comm = gl_comm; datas[tid].array = array; // Spawn additional threads for ids greater than 1. if ( tid != 0 ) bli_pthread_create( &pthreads[tid], NULL, &bli_l3_sup_thread_entry, &datas[tid] ); else bli_l3_sup_thread_entry( ( void* )(&datas[0]) ); } // We shouldn't free the global communicator since it was already freed // by the global communicator's chief thread in bli_l3_thrinfo_free() // (called from the thread entry function). // Thread 0 waits for additional threads to finish. for ( dim_t tid = 1; tid < n_threads; tid++ ) { bli_pthread_join( pthreads[tid], NULL ); } // Check the array_t back into the small block allocator. Similar to the // check-out, this is done using a lock embedded within the sba to ensure // mutual exclusion. bli_sba_checkin_array( array ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_l3_thread_decorator().pth: " ); #endif bli_free_intl( pthreads ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_l3_thread_decorator().pth: " ); #endif bli_free_intl( datas ); return BLIS_SUCCESS; } #endif blis-0.9.0/frame/thread/bli_l3_sup_decor_pthreads.h000066400000000000000000000036411422157504600222760ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_L3_SUP_DECOR_PTHREADS_H #define BLIS_L3_SUP_DECOR_PTHREADS_H // Definitions specific to situations when POSIX multithreading is enabled. #ifdef BLIS_ENABLE_PTHREADS // Thread entry point prototype. void* bli_l3_sup_thread_entry( void* data_void ); #endif #endif blis-0.9.0/frame/thread/bli_l3_sup_decor_single.c000066400000000000000000000114511422157504600217360ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #ifndef BLIS_ENABLE_MULTITHREADING #define SKIP_THRINFO_TREE err_t bli_l3_sup_thread_decorator ( l3supint_t func, opid_t family, //pack_t schema_a, //pack_t schema_b, obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, rntm_t* rntm ) { // For sequential execution, we use only one thread. const dim_t n_threads = 1; // NOTE: The sba was initialized in bli_init(). // Check out an array_t from the small block allocator. This is done // with an internal lock to ensure only one application thread accesses // the sba at a time. bli_sba_checkout_array() will also automatically // resize the array_t, if necessary. array_t* restrict array = bli_sba_checkout_array( n_threads ); // Access the pool_t* for thread 0 and embed it into the rntm. bli_sba_rntm_set_pool( 0, array, rntm ); // Set the packing block allocator field of the rntm. bli_pba_rntm_set_pba( rntm ); #ifndef SKIP_THRINFO_TREE // Allcoate a global communicator for the root thrinfo_t structures. thrcomm_t* restrict gl_comm = bli_thrcomm_create( rntm, n_threads ); #endif { // NOTE: We don't need to create another copy of the rntm_t since // it was already copied in one of the high-level oapi functions. rntm_t* restrict rntm_p = rntm; // There is only one thread id (for the thief thread). const dim_t tid = 0; // Use the thread id to access the appropriate pool_t* within the // array_t, and use it to set the sba_pool field within the rntm_t. // If the pool_t* element within the array_t is NULL, it will first // be allocated/initialized. // NOTE: This is commented out because, in the single-threaded case, // this is redundant since it's already been done above. //bli_sba_rntm_set_pool( tid, array, rntm_p ); #ifndef SKIP_THRINFO_TREE thrinfo_t* thread = NULL; // Create the root node of the thread's thrinfo_t structure. bli_l3_sup_thrinfo_create_root( tid, gl_comm, rntm_p, &thread ); #else // This optimization allows us to use one of the global thrinfo_t // objects for single-threaded execution rather than grow one from // scratch. The key is that bli_thrinfo_sup_grow(), which is called // from within the variants, will immediately return if it detects // that the thrinfo_t* passed into it is either // &BLIS_GEMM_SINGLE_THREADED or &BLIS_PACKM_SINGLE_THREADED. thrinfo_t* thread = &BLIS_GEMM_SINGLE_THREADED; ( void )tid; #endif func ( alpha, a, b, beta, c, cntx, rntm_p, thread ); #ifndef SKIP_THRINFO_TREE // Free the current thread's thrinfo_t structure. bli_l3_sup_thrinfo_free( rntm_p, thread ); #endif } // We shouldn't free the global communicator since it was already freed // by the global communicator's chief thread in bli_l3_thrinfo_free() // (called above). // Check the array_t back into the small block allocator. Similar to the // check-out, this is done using a lock embedded within the sba to ensure // mutual exclusion. bli_sba_checkin_array( array ); return BLIS_SUCCESS; } #endif blis-0.9.0/frame/thread/bli_l3_sup_decor_single.h000066400000000000000000000035131422157504600217430ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_L3_SUP_DECOR_SINGLE_H #define BLIS_L3_SUP_DECOR_SINGLE_H // Definitions specific to situations when multithreading is disabled. #ifndef BLIS_ENABLE_MULTITHREADING #endif #endif blis-0.9.0/frame/thread/bli_pthread.c000066400000000000000000000353761422157504600174570ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2018, Southern Methodist University Copyright (C) 2018, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #if defined(BLIS_DISABLE_SYSTEM) // This branch defines a pthread-like API, bli_pthread_*(), and implements it // in terms of "dummy" code that doesn't depend on POSIX threads or any other // threading mechanism. See issue #454 to see the use case that prompted this // feature. // NOTE: THIS CODE DOES NOT IMPLEMENT THREADING AND IS NOT THREAD-SAFE! // -- pthread_create(), pthread_join() -- int bli_pthread_create ( bli_pthread_t* thread, const bli_pthread_attr_t* attr, void* (*start_routine)(void*), void* arg ) { //return pthread_create( thread, attr, start_routine, arg ); start_routine( arg ); return 0; } int bli_pthread_join ( bli_pthread_t thread, void** retval ) { //return pthread_join( thread, retval ); return 0; } // -- pthread_mutex_*() -- int bli_pthread_mutex_init ( bli_pthread_mutex_t* mutex, const bli_pthread_mutexattr_t* attr ) { //return pthread_mutex_init( mutex, attr ); return 0; } int bli_pthread_mutex_destroy ( bli_pthread_mutex_t* mutex ) { //return pthread_mutex_destroy( mutex ); return 0; } int bli_pthread_mutex_lock ( bli_pthread_mutex_t* mutex ) { //return pthread_mutex_lock( mutex ); return 0; } int bli_pthread_mutex_trylock ( bli_pthread_mutex_t* mutex ) { //return pthread_mutex_trylock( mutex ); return 0; } int bli_pthread_mutex_unlock ( bli_pthread_mutex_t* mutex ) { //return pthread_mutex_unlock( mutex ); return 0; } // -- pthread_cond_*() -- int bli_pthread_cond_init ( bli_pthread_cond_t* cond, const bli_pthread_condattr_t* attr ) { //return pthread_cond_init( cond, attr ); return 0; } int bli_pthread_cond_destroy ( bli_pthread_cond_t* cond ) { //return pthread_cond_destroy( cond ); return 0; } int bli_pthread_cond_wait ( bli_pthread_cond_t* cond, bli_pthread_mutex_t* mutex ) { //return pthread_cond_wait( cond, mutex ); return 0; } int bli_pthread_cond_broadcast ( bli_pthread_cond_t* cond ) { //return pthread_cond_broadcast( cond ); return 0; } // -- pthread_once() -- void bli_pthread_once ( bli_pthread_once_t* once, void (*init)(void) ) { //pthread_once( once, init ); init(); } #if 0 // NOTE: This part of the API is disabled because (1) we don't actually need // _self() or _equal() yet, and (2) when we do try to include these functions, // AppVeyor for some reason fails on all the Windows/clang builds with the // error: // libblis.a(bli_pthread.o) : error LNK2019: unresolved external symbol // __imp_CompareObjectHandles referenced in function bli_pthread_equal // -- pthread_self() -- bli_pthread_t bli_pthread_self ( void ) { return 0; } // -- pthread_equal() -- int bli_pthread_equal ( bli_pthread_t t1, bli_pthread_t t2 ) { // We don't bother comparing t1 and t2 since we must, by definition, be // executing the same thread if there is not threading mechanism on the // system. return 1; } #endif #elif defined(_MSC_VER) // !defined(BLIS_DISABLE_SYSTEM) #include // This branch defines a pthread-like API, bli_pthread_*(), and implements it // in terms of Windows API calls. // -- pthread_create(), pthread_join() -- typedef struct { void* (*start_routine)( void* ); void* param; void** retval; } bli_thread_param; static DWORD bli_thread_func ( void* param_ ) { bli_thread_param* param = param_; *param->retval = param->start_routine( param->param ); return 0; } int bli_pthread_create ( bli_pthread_t* thread, const bli_pthread_attr_t* attr, void* (*start_routine)(void*), void* arg ) { if ( attr ) return EINVAL; bli_thread_param param = { start_routine, arg, &thread->retval }; thread->handle = CreateThread( NULL, 0, bli_thread_func, ¶m, 0, NULL ); if ( !thread->handle ) return EAGAIN; return 0; } int bli_pthread_join ( bli_pthread_t thread, void** retval ) { if ( !WaitForSingleObject( thread.handle, INFINITE ) ) return EAGAIN; if ( retval ) *retval = thread.retval; return 0; } // -- pthread_mutex_*() -- int bli_pthread_mutex_init ( bli_pthread_mutex_t* mutex, const bli_pthread_mutexattr_t* attr ) { if ( attr ) return EINVAL; InitializeSRWLock( mutex ); return 0; } int bli_pthread_mutex_destroy ( bli_pthread_mutex_t* mutex ) { return 0; } int bli_pthread_mutex_lock ( bli_pthread_mutex_t* mutex ) { AcquireSRWLockExclusive( mutex ); return 0; } int bli_pthread_mutex_trylock ( bli_pthread_mutex_t* mutex ) { return TryAcquireSRWLockExclusive( mutex ) ? 0 : EBUSY; } int bli_pthread_mutex_unlock ( bli_pthread_mutex_t* mutex ) { ReleaseSRWLockExclusive( mutex ); return 0; } // -- pthread_cond_*() -- int bli_pthread_cond_init ( bli_pthread_cond_t* cond, const bli_pthread_condattr_t* attr ) { if ( attr ) return EINVAL; InitializeConditionVariable( cond ); return 0; } int bli_pthread_cond_destroy ( bli_pthread_cond_t* cond ) { ( void )cond; return 0; } int bli_pthread_cond_wait ( bli_pthread_cond_t* cond, bli_pthread_mutex_t* mutex ) { if ( !SleepConditionVariableSRW( cond, mutex, INFINITE, 0 ) ) return EAGAIN; return 0; } int bli_pthread_cond_broadcast ( bli_pthread_cond_t* cond ) { WakeAllConditionVariable( cond ); return 0; } // -- pthread_once() -- static BOOL bli_init_once_wrapper ( bli_pthread_once_t* once, void* param, void** context ) { ( void )once; ( void )context; typedef void (*callback)( void ); ((callback)param)(); return TRUE; } void bli_pthread_once ( bli_pthread_once_t* once, void (*init)(void) ) { InitOnceExecuteOnce( once, bli_init_once_wrapper, init, NULL ); } #if 0 // NOTE: This part of the API is disabled because (1) we don't actually need // _self() or _equal() yet, and (2) when we do try to include these functions, // AppVeyor for some reason fails on all the Windows/clang builds with the // error: // libblis.a(bli_pthread.o) : error LNK2019: unresolved external symbol // __imp_CompareObjectHandles referenced in function bli_pthread_equal // -- pthread_self() -- bli_pthread_t bli_pthread_self ( void ) { bli_pthread_t t; // Note: BLIS will only ever use bli_pthread_self() in conjunction with // bli_pthread_equal(), and thus setting the .retval field is unnecessary. // Despite this, we set it to NULL anyway. t.handle = GetCurrentThread(); t.retval = NULL; return t; } // -- pthread_equal() -- int bli_pthread_equal ( bli_pthread_t t1, bli_pthread_t t2 ) { return ( int )CompareObjectHandles( t1.handle, t2.handle ); } #endif #else // !defined(BLIS_DISABLE_SYSTEM) && !defined(_MSC_VER) // This branch defines a pthreads-like API, bli_pthreads_*(), and implements it // in terms of the corresponding pthreads_*() types, macros, and function calls. // This branch is compiled for Linux and other non-Windows environments where // we assume that *some* implementation of pthreads is provided (although it // may lack barriers--see below). // -- pthread_create(), pthread_join() -- int bli_pthread_create ( bli_pthread_t* thread, const bli_pthread_attr_t* attr, void* (*start_routine)(void*), void* arg ) { return pthread_create( thread, attr, start_routine, arg ); } int bli_pthread_join ( bli_pthread_t thread, void** retval ) { return pthread_join( thread, retval ); } // -- pthread_mutex_*() -- int bli_pthread_mutex_init ( bli_pthread_mutex_t* mutex, const bli_pthread_mutexattr_t* attr ) { return pthread_mutex_init( mutex, attr ); } int bli_pthread_mutex_destroy ( bli_pthread_mutex_t* mutex ) { return pthread_mutex_destroy( mutex ); } int bli_pthread_mutex_lock ( bli_pthread_mutex_t* mutex ) { return pthread_mutex_lock( mutex ); } int bli_pthread_mutex_trylock ( bli_pthread_mutex_t* mutex ) { return pthread_mutex_trylock( mutex ); } int bli_pthread_mutex_unlock ( bli_pthread_mutex_t* mutex ) { return pthread_mutex_unlock( mutex ); } // -- pthread_cond_*() -- int bli_pthread_cond_init ( bli_pthread_cond_t* cond, const bli_pthread_condattr_t* attr ) { return pthread_cond_init( cond, attr ); } int bli_pthread_cond_destroy ( bli_pthread_cond_t* cond ) { return pthread_cond_destroy( cond ); } int bli_pthread_cond_wait ( bli_pthread_cond_t* cond, bli_pthread_mutex_t* mutex ) { return pthread_cond_wait( cond, mutex ); } int bli_pthread_cond_broadcast ( bli_pthread_cond_t* cond ) { return pthread_cond_broadcast( cond ); } // -- pthread_once() -- void bli_pthread_once ( bli_pthread_once_t* once, void (*init)(void) ) { pthread_once( once, init ); } #if 0 // NOTE: This part of the API is disabled because (1) we don't actually need // _self() or _equal() yet, and (2) when we do try to include these functions, // AppVeyor for some reason fails on all the Windows/clang builds with the // error: // libblis.a(bli_pthread.o) : error LNK2019: unresolved external symbol // __imp_CompareObjectHandles referenced in function bli_pthread_equal // -- pthread_self() -- bli_pthread_t bli_pthread_self ( void ) { return pthread_self(); } // -- pthread_equal() -- int bli_pthread_equal ( bli_pthread_t t1, bli_pthread_t t2 ) { return pthread_equal( t1, t2 ); } #endif #endif // !defined(BLIS_DISABLE_SYSTEM) && !defined(_MSC_VER) // -- pthread_barrier_*() -- #if defined(BLIS_DISABLE_SYSTEM) int bli_pthread_barrier_init ( bli_pthread_barrier_t* barrier, const bli_pthread_barrierattr_t* attr, unsigned int count ) { //return pthread_barrier_init( barrier, attr, count ); return 0; } int bli_pthread_barrier_destroy ( bli_pthread_barrier_t* barrier ) { //return pthread_barrier_destroy( barrier ); return 0; } int bli_pthread_barrier_wait ( bli_pthread_barrier_t* barrier ) { //return pthread_barrier_wait( barrier ); return 0; } #elif defined(__APPLE__) || defined(_MSC_VER) // !defined(BLIS_DISABLE_SYSTEM) #include // For OS X and Windows, we define barriers ourselves in terms of the rest // of the API, though for slightly different reasons: For Windows, we must // define barriers because we are defining *everything* from scratch. For // OS X, we must define barriers because Apple chose to omit barriers from // their implementation of POSIX threads (since barriers are actually // optional to the POSIX standard). int bli_pthread_barrier_init ( bli_pthread_barrier_t* barrier, const bli_pthread_barrierattr_t* attr, unsigned int count ) { if ( attr ) return EINVAL; if ( count == 0 ) return EINVAL; int err; if ( (err = bli_pthread_mutex_init( &barrier->mutex, 0 )) != 0 ) return err; if ( (err = bli_pthread_cond_init( &barrier->cond, 0 )) != 0 ) { bli_pthread_mutex_destroy( &barrier->mutex ); return err; } barrier->tripCount = count; barrier->count = 0; return 0; } int bli_pthread_barrier_destroy ( bli_pthread_barrier_t *barrier ) { bli_pthread_cond_destroy( &barrier->cond ); bli_pthread_mutex_destroy( &barrier->mutex ); return 0; } int bli_pthread_barrier_wait ( bli_pthread_barrier_t *barrier ) { bli_pthread_mutex_lock( &barrier->mutex ); ++(barrier->count); if ( barrier->count >= barrier->tripCount ) { barrier->count = 0; bli_pthread_cond_broadcast( &barrier->cond ); bli_pthread_mutex_unlock( &barrier->mutex ); return 1; } else { bli_pthread_cond_wait( &barrier->cond, &(barrier->mutex) ); bli_pthread_mutex_unlock( &barrier->mutex ); return 0; } } #else // !defined(BLIS_DISABLE_SYSTEM) && !defined(__APPLE__) && !defined(_MSC_VER) // Linux environments implement the pthread_barrier* sub-API. So, if we're // on Linux, we can simply call those functions, just as we did before for // the other functions. int bli_pthread_barrier_init ( bli_pthread_barrier_t* barrier, const bli_pthread_barrierattr_t* attr, unsigned int count ) { return pthread_barrier_init( barrier, attr, count ); } int bli_pthread_barrier_destroy ( bli_pthread_barrier_t* barrier ) { return pthread_barrier_destroy( barrier ); } int bli_pthread_barrier_wait ( bli_pthread_barrier_t* barrier ) { return pthread_barrier_wait( barrier ); } #endif blis-0.9.0/frame/thread/bli_pthread.h000066400000000000000000000173031422157504600174520ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2018, Southern Methodist University Copyright (C) 2018, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_PTHREAD_H #define BLIS_PTHREAD_H // -- Type and macro definitions ----------------------------------------------- #if defined(BLIS_DISABLE_SYSTEM) // This branch defines a pthread-like API, bli_pthread_*(), and implements it // in terms of "dummy" code that doesn't depend on POSIX threads or any other // threading mechanism. See issue #454 to see the use case that prompted this // feature. // NOTE: THIS CODE DOES NOT IMPLEMENT THREADING AND IS NOT THREAD-SAFE! // -- pthread types -- typedef int bli_pthread_t; typedef int bli_pthread_attr_t; typedef int bli_pthread_mutex_t; typedef int bli_pthread_mutexattr_t; typedef int bli_pthread_cond_t; typedef int bli_pthread_condattr_t; typedef int bli_pthread_once_t; typedef int bli_pthread_barrier_t; typedef int bli_pthread_barrierattr_t; // -- pthreads macros -- #define BLIS_PTHREAD_MUTEX_INITIALIZER 0 #define BLIS_PTHREAD_COND_INITIALIZER 0 #define BLIS_PTHREAD_ONCE_INIT 0 #elif defined(_MSC_VER) // !defined(BLIS_DISABLE_SYSTEM) // This branch defines a pthread-like API, bli_pthread_*(), and implements it // in terms of Windows API calls. // -- pthread types -- typedef struct { HANDLE handle; void* retval; } bli_pthread_t; typedef void bli_pthread_attr_t; typedef SRWLOCK bli_pthread_mutex_t; typedef void bli_pthread_mutexattr_t; typedef CONDITION_VARIABLE bli_pthread_cond_t; typedef void bli_pthread_condattr_t; typedef INIT_ONCE bli_pthread_once_t; typedef struct { bli_pthread_mutex_t mutex; bli_pthread_cond_t cond; int count; int tripCount; } bli_pthread_barrier_t; typedef void bli_pthread_barrierattr_t; // -- pthreads macros -- #define BLIS_PTHREAD_MUTEX_INITIALIZER SRWLOCK_INIT #define BLIS_PTHREAD_ONCE_INIT INIT_ONCE_STATIC_INIT #define BLIS_PTHREAD_COND_INITIALIZER CONDITION_VARIABLE_INIT #else // !defined(BLIS_DISABLE_SYSTEM) && !defined(_MSC_VER) #include // This branch defines a pthreads-like API, bli_pthreads_*(), and implements it // in terms of the corresponding pthreads_*() types, macros, and function calls. // -- pthread types -- typedef pthread_t bli_pthread_t; typedef pthread_attr_t bli_pthread_attr_t; typedef pthread_mutex_t bli_pthread_mutex_t; typedef pthread_mutexattr_t bli_pthread_mutexattr_t; typedef pthread_cond_t bli_pthread_cond_t; typedef pthread_condattr_t bli_pthread_condattr_t; typedef pthread_once_t bli_pthread_once_t; #if defined(__APPLE__) // For OS X, we must define the barrier types ourselves since Apple does // not implement barriers in their variant of pthreads. typedef void bli_pthread_barrierattr_t; typedef struct { bli_pthread_mutex_t mutex; bli_pthread_cond_t cond; int count; int tripCount; } bli_pthread_barrier_t; #else // For other non-Windows OSes (primarily Linux), we can define the barrier // types in terms of existing pthreads barrier types since we expect they // will be provided by the pthreads implementation. typedef pthread_barrier_t bli_pthread_barrier_t; typedef pthread_barrierattr_t bli_pthread_barrierattr_t; #endif // -- pthreads macros -- #define BLIS_PTHREAD_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER #define BLIS_PTHREAD_COND_INITIALIZER PTHREAD_COND_INITIALIZER #define BLIS_PTHREAD_ONCE_INIT PTHREAD_ONCE_INIT #endif // -- Function definitions ----------------------------------------------------- // -- pthread_create(), pthread_join() -- BLIS_EXPORT_BLIS int bli_pthread_create ( bli_pthread_t* thread, const bli_pthread_attr_t* attr, void* (*start_routine)(void*), void* arg ); BLIS_EXPORT_BLIS int bli_pthread_join ( bli_pthread_t thread, void** retval ); // -- pthread_mutex_*() -- BLIS_EXPORT_BLIS int bli_pthread_mutex_init ( bli_pthread_mutex_t* mutex, const bli_pthread_mutexattr_t* attr ); BLIS_EXPORT_BLIS int bli_pthread_mutex_destroy ( bli_pthread_mutex_t* mutex ); BLIS_EXPORT_BLIS int bli_pthread_mutex_lock ( bli_pthread_mutex_t* mutex ); BLIS_EXPORT_BLIS int bli_pthread_mutex_trylock ( bli_pthread_mutex_t* mutex ); BLIS_EXPORT_BLIS int bli_pthread_mutex_unlock ( bli_pthread_mutex_t* mutex ); // -- pthread_cond_*() -- BLIS_EXPORT_BLIS int bli_pthread_cond_init ( bli_pthread_cond_t* cond, const bli_pthread_condattr_t* attr ); BLIS_EXPORT_BLIS int bli_pthread_cond_destroy ( bli_pthread_cond_t* cond ); BLIS_EXPORT_BLIS int bli_pthread_cond_wait ( bli_pthread_cond_t* cond, bli_pthread_mutex_t* mutex ); BLIS_EXPORT_BLIS int bli_pthread_cond_broadcast ( bli_pthread_cond_t* cond ); // -- pthread_once() -- BLIS_EXPORT_BLIS void bli_pthread_once ( bli_pthread_once_t* once, void (*init)(void) ); #if 0 // NOTE: This part of the API is disabled because (1) we don't actually need // _self() or _equal() yet, and (2) when we do try to include these functions, // AppVeyor for some reason fails on all the Windows/clang builds with the // error: // libblis.a(bli_pthread.o) : error LNK2019: unresolved external symbol // __imp_CompareObjectHandles referenced in function bli_pthread_equal // -- pthread_self() -- BLIS_EXPORT_BLIS bli_pthread_t bli_pthread_self ( void ); // -- pthread_equal() -- BLIS_EXPORT_BLIS int bli_pthread_equal ( bli_pthread_t t1, bli_pthread_t t2 ); #endif // -- pthread_barrier_*() -- BLIS_EXPORT_BLIS int bli_pthread_barrier_init ( bli_pthread_barrier_t* barrier, const bli_pthread_barrierattr_t* attr, unsigned int count ); BLIS_EXPORT_BLIS int bli_pthread_barrier_destroy ( bli_pthread_barrier_t* barrier ); BLIS_EXPORT_BLIS int bli_pthread_barrier_wait ( bli_pthread_barrier_t* barrier ); #endif // BLIS_PTHREAD_H blis-0.9.0/frame/thread/bli_thrcomm.c000066400000000000000000000111711422157504600174640ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void* bli_thrcomm_bcast ( dim_t id, void* to_send, thrcomm_t* comm ) { if ( comm == NULL || comm->n_threads == 1 ) return to_send; if ( id == 0 ) comm->sent_object = to_send; bli_thrcomm_barrier( id, comm ); void* object = comm->sent_object; bli_thrcomm_barrier( id, comm ); return object; } // Use __sync_* builtins (assumed available) if __atomic_* ones are not present. #ifndef __ATOMIC_RELAXED #define __ATOMIC_RELAXED #define __ATOMIC_ACQUIRE #define __ATOMIC_RELEASE #define __ATOMIC_ACQ_REL #define __atomic_load_n(ptr, constraint) \ __sync_fetch_and_add(ptr, 0) #define __atomic_add_fetch(ptr, value, constraint) \ __sync_add_and_fetch(ptr, value) #define __atomic_fetch_add(ptr, value, constraint) \ __sync_fetch_and_add(ptr, value) #define __atomic_fetch_xor(ptr, value, constraint) \ __sync_fetch_and_xor(ptr, value) #endif void bli_thrcomm_barrier_atomic( dim_t t_id, thrcomm_t* comm ) { // Return early if the comm is NULL or if there is only one // thread participating. if ( comm == NULL || comm->n_threads == 1 ) return; // Read the "sense" variable. This variable is akin to a unique ID for // the current barrier. The first n-1 threads will spin on this variable // until it changes. The sense variable gets incremented by the last // thread to enter the barrier, just before it exits. But it turns out // that you don't need many unique IDs before you can wrap around. In // fact, if everything else is working, a binary variable is sufficient, // which is what we do here (i.e., 0 is incremented to 1, which is then // decremented back to 0, and so forth). gint_t orig_sense = __atomic_load_n( &comm->barrier_sense, __ATOMIC_RELAXED ); // Register ourselves (the current thread) as having arrived by // incrementing the barrier_threads_arrived variable. We must perform // this increment (and a subsequent read) atomically. dim_t my_threads_arrived = __atomic_add_fetch( &comm->barrier_threads_arrived, 1, __ATOMIC_ACQ_REL ); // If the current thread was the last thread to have arrived, then // it will take actions that effectively ends and resets the barrier. if ( my_threads_arrived == comm->n_threads ) { // Reset the variable tracking the number of threads that have arrived // to zero (which returns the barrier to the "empty" state. Then // atomically toggle the barrier sense variable. This will signal to // the other threads (which are spinning in the branch elow) that it // is now safe to exit the barrier. comm->barrier_threads_arrived = 0; __atomic_fetch_xor( &comm->barrier_sense, 1, __ATOMIC_RELEASE ); } else { // If the current thread is NOT the last thread to have arrived, then // it spins on the sense variable until that sense variable changes at // which time these threads will exit the barrier. while ( __atomic_load_n( &comm->barrier_sense, __ATOMIC_ACQUIRE ) == orig_sense ) ; // Empty loop body. } } blis-0.9.0/frame/thread/bli_thrcomm.h000066400000000000000000000051031422157504600174670ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_THRCOMM_H #define BLIS_THRCOMM_H // Include definitions (mostly thrcomm_t) specific to the method of // multithreading. #include "bli_thrcomm_single.h" #include "bli_thrcomm_openmp.h" #include "bli_thrcomm_pthreads.h" // thrcomm_t query (field only) BLIS_INLINE dim_t bli_thrcomm_num_threads( thrcomm_t* comm ) { return comm->n_threads; } // Thread communicator prototypes. thrcomm_t* bli_thrcomm_create( rntm_t* rntm, dim_t n_threads ); void bli_thrcomm_free( rntm_t* rntm, thrcomm_t* comm ); void bli_thrcomm_init( dim_t n_threads, thrcomm_t* comm ); void bli_thrcomm_cleanup( thrcomm_t* comm ); BLIS_EXPORT_BLIS void bli_thrcomm_barrier( dim_t thread_id, thrcomm_t* comm ); BLIS_EXPORT_BLIS void* bli_thrcomm_bcast( dim_t inside_id, void* to_send, thrcomm_t* comm ); void bli_thrcomm_barrier_atomic( dim_t thread_id, thrcomm_t* comm ); #endif blis-0.9.0/frame/thread/bli_thrcomm_openmp.c000066400000000000000000000127341422157504600210500ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #ifdef BLIS_ENABLE_OPENMP thrcomm_t* bli_thrcomm_create( rntm_t* rntm, dim_t n_threads ) { #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_thrcomm_create(): " ); #endif thrcomm_t* comm = bli_sba_acquire( rntm, sizeof(thrcomm_t) ); bli_thrcomm_init( n_threads, comm ); return comm; } void bli_thrcomm_free( rntm_t* rntm, thrcomm_t* comm ) { if ( comm == NULL ) return; bli_thrcomm_cleanup( comm ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_thrcomm_free(): " ); #endif bli_sba_release( rntm, comm ); } #ifndef BLIS_TREE_BARRIER void bli_thrcomm_init( dim_t n_threads, thrcomm_t* comm ) { if ( comm == NULL ) return; comm->sent_object = NULL; comm->n_threads = n_threads; comm->barrier_sense = 0; comm->barrier_threads_arrived = 0; } void bli_thrcomm_cleanup( thrcomm_t* comm ) { if ( comm == NULL ) return; } //'Normal' barrier for openmp //barrier routine taken from art of multicore programming void bli_thrcomm_barrier( dim_t t_id, thrcomm_t* comm ) { #if 0 if ( comm == NULL || comm->n_threads == 1 ) return; gint_t my_sense = comm->barrier_sense; dim_t my_threads_arrived; _Pragma( "omp atomic capture" ) my_threads_arrived = ++(comm->barrier_threads_arrived); if ( my_threads_arrived == comm->n_threads ) { comm->barrier_threads_arrived = 0; comm->barrier_sense = !comm->barrier_sense; } else { volatile gint_t* listener = &comm->barrier_sense; while ( *listener == my_sense ) {} } #endif bli_thrcomm_barrier_atomic( t_id, comm ); } #else void bli_thrcomm_init( dim_t n_threads, thrcomm_t* comm ) { err_t r_val; if ( comm == NULL ) return; comm->sent_object = NULL; comm->n_threads = n_threads; comm->barriers = bli_malloc_intl( sizeof( barrier_t* ) * n_threads, &r_val ); bli_thrcomm_tree_barrier_create( n_threads, BLIS_TREE_BARRIER_ARITY, comm->barriers, 0 ); } //Tree barrier used for Intel Xeon Phi barrier_t* bli_thrcomm_tree_barrier_create( int num_threads, int arity, barrier_t** leaves, int leaf_index ) { err_t r_val; barrier_t* me = bli_malloc_intl( sizeof( barrier_t ), &r_val ); me->dad = NULL; me->signal = 0; // Base Case if ( num_threads <= arity ) { //Now must be registered as a leaf for ( int i = 0; i < num_threads; i++ ) { leaves[ leaf_index + i ] = me; } me->count = num_threads; me->arity = num_threads; } else { // Otherwise this node has children int threads_per_kid = num_threads / arity; int defecit = num_threads - threads_per_kid * arity; for ( int i = 0; i < arity; i++ ) { int threads_this_kid = threads_per_kid; if ( i < defecit ) threads_this_kid++; barrier_t* kid = bli_thrcomm_tree_barrier_create( threads_this_kid, arity, leaves, leaf_index ); kid->dad = me; leaf_index += threads_this_kid; } me->count = arity; me->arity = arity; } return me; } void bli_thrcomm_cleanup( thrcomm_t* comm ) { if ( comm == NULL ) return; for ( dim_t i = 0; i < comm->n_threads; i++ ) { bli_thrcomm_tree_barrier_free( comm->barriers[i] ); } bli_free_intl( comm->barriers ); } void bli_thrcomm_tree_barrier_free( barrier_t* barrier ) { if ( barrier == NULL ) return; barrier->count--; if ( barrier->count == 0 ) { bli_thrcomm_tree_barrier_free( barrier->dad ); bli_free_intl( barrier ); } return; } void bli_thrcomm_barrier( dim_t t_id, thrcomm_t* comm ) { bli_thrcomm_tree_barrier( comm->barriers[t_id] ); } void bli_thrcomm_tree_barrier( barrier_t* barack ) { int my_signal = barack->signal; int my_count; _Pragma( "omp atomic capture" ) my_count = barack->count--; if ( my_count == 1 ) { if ( barack->dad != NULL ) { bli_thrcomm_tree_barrier( barack->dad ); } barack->count = barack->arity; barack->signal = !barack->signal; } else { volatile int* listener = &barack->signal; while ( *listener == my_signal ) {} } } #endif #endif blis-0.9.0/frame/thread/bli_thrcomm_openmp.h000066400000000000000000000062031422157504600210470ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_THRCOMM_OPENMP_H #define BLIS_THRCOMM_OPENMP_H // Define thrcomm_t for situations when OpenMP multithreading is enabled. #ifdef BLIS_ENABLE_OPENMP #include // Define thrcomm_t for tree barriers and non-tree barriers. #ifdef BLIS_TREE_BARRIER struct barrier_s { int arity; int count; struct barrier_s* dad; volatile int signal; }; typedef struct barrier_s barrier_t; struct thrcomm_s { void* sent_object; dim_t n_threads; barrier_t** barriers; }; #else struct thrcomm_s { void* sent_object; dim_t n_threads; // NOTE: barrier_sense was originally a gint_t-based bool_t, but upon // redefining bool_t as bool we discovered that some gcc __atomic built-ins // don't allow the use of bool for the variables being operated upon. // (Specifically, this was observed of __atomic_fetch_xor(), but it likely // applies to all other related built-ins.) Thus, we get around this by // redefining barrier_sense as a gint_t. //volatile gint_t barrier_sense; gint_t barrier_sense; dim_t barrier_threads_arrived; }; #endif typedef struct thrcomm_s thrcomm_t; // Prototypes specific to tree barriers. #ifdef BLIS_TREE_BARRIER barrier_t* bli_thrcomm_tree_barrier_create( int num_threads, int arity, barrier_t** leaves, int leaf_index ); void bli_thrcomm_tree_barrier_free( barrier_t* barrier ); void bli_thrcomm_tree_barrier( barrier_t* barack ); #endif #endif #endif blis-0.9.0/frame/thread/bli_thrcomm_pthreads.c000066400000000000000000000067171422157504600213700ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #ifdef BLIS_ENABLE_PTHREADS thrcomm_t* bli_thrcomm_create( rntm_t* rntm, dim_t n_threads ) { #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_thrcomm_create(): " ); #endif thrcomm_t* comm = bli_sba_acquire( rntm, sizeof(thrcomm_t) ); bli_thrcomm_init( n_threads, comm ); return comm; } void bli_thrcomm_free( rntm_t* rntm, thrcomm_t* comm ) { if ( comm == NULL ) return; bli_thrcomm_cleanup( comm ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_thrcomm_free(): " ); #endif bli_sba_release( rntm, comm ); } #ifdef BLIS_USE_PTHREAD_BARRIER void bli_thrcomm_init( dim_t n_threads, thrcomm_t* comm ) { if ( comm == NULL ) return; comm->sent_object = NULL; comm->n_threads = n_threads; bli_pthread_barrier_init( &comm->barrier, NULL, n_threads ); } void bli_thrcomm_cleanup( thrcomm_t* comm ) { if ( comm == NULL ) return; bli_pthread_barrier_destroy( &comm->barrier ); } void bli_thrcomm_barrier( dim_t t_id, thrcomm_t* comm ) { bli_pthread_barrier_wait( &comm->barrier ); } #else void bli_thrcomm_init( dim_t n_threads, thrcomm_t* comm ) { if ( comm == NULL ) return; comm->sent_object = NULL; comm->n_threads = n_threads; comm->barrier_sense = 0; comm->barrier_threads_arrived = 0; } void bli_thrcomm_cleanup( thrcomm_t* comm ) { } void bli_thrcomm_barrier( dim_t t_id, thrcomm_t* comm ) { #if 0 if ( comm == NULL || comm->n_threads == 1 ) return; bool my_sense = comm->sense; dim_t my_threads_arrived; my_threads_arrived = __sync_add_and_fetch(&(comm->threads_arrived), 1); if ( my_threads_arrived == comm->n_threads ) { comm->threads_arrived = 0; comm->sense = !comm->sense; } else { volatile bool* listener = &comm->sense; while( *listener == my_sense ) {} } #endif bli_thrcomm_barrier_atomic( t_id, comm ); } #endif #endif blis-0.9.0/frame/thread/bli_thrcomm_pthreads.h000066400000000000000000000051051422157504600213630ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_THRCOMM_PTHREADS_H #define BLIS_THRCOMM_PTHREADS_H // Define thrcomm_t for situations when POSIX multithreading is enabled. #ifdef BLIS_ENABLE_PTHREADS #ifdef BLIS_USE_PTHREAD_BARRIER struct thrcomm_s { void* sent_object; dim_t n_threads; bli_pthread_barrier_t barrier; }; #else struct thrcomm_s { void* sent_object; dim_t n_threads; // NOTE: barrier_sense was originally a gint_t-based bool_t, but upon // redefining bool_t as bool we discovered that some gcc __atomic built-ins // don't allow the use of bool for the variables being operated upon. // (Specifically, this was observed of __atomic_fetch_xor(), but it likely // applies to all other related built-ins.) Thus, we get around this by // redefining barrier_sense as a gint_t. //volatile gint_t barrier_sense; gint_t barrier_sense; dim_t barrier_threads_arrived; }; #endif typedef struct thrcomm_s thrcomm_t; #endif #endif blis-0.9.0/frame/thread/bli_thrcomm_single.c000066400000000000000000000052551422157504600210330ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #ifndef BLIS_ENABLE_MULTITHREADING //Constructors and destructors for constructors thrcomm_t* bli_thrcomm_create( rntm_t* rntm, dim_t n_threads ) { #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_thrcomm_create(): " ); #endif thrcomm_t* comm = bli_sba_acquire( rntm, sizeof( thrcomm_t ) ); bli_thrcomm_init( n_threads, comm ); return comm; } void bli_thrcomm_free( rntm_t* rntm, thrcomm_t* comm ) { if ( comm == NULL ) return; bli_thrcomm_cleanup( comm ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_thrcomm_free(): " ); #endif bli_sba_release( rntm, comm ); } void bli_thrcomm_init( dim_t n_threads, thrcomm_t* comm ) { if ( comm == NULL ) return; comm->sent_object = NULL; comm->n_threads = n_threads; comm->barrier_sense = 0; comm->barrier_threads_arrived = 0; } void bli_thrcomm_cleanup( thrcomm_t* comm ) { if ( comm == NULL ) return; } void bli_thrcomm_barrier( dim_t t_id, thrcomm_t* comm ) { return; } #endif blis-0.9.0/frame/thread/bli_thrcomm_single.h000066400000000000000000000053411422157504600210340ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_THRCOMM_SINGLE_H #define BLIS_THRCOMM_SINGLE_H // Define thrcomm_t for situations when multithreading is disabled. #ifndef BLIS_ENABLE_MULTITHREADING //thread communicators may be implementation dependent #ifdef BLIS_TREE_BARRIER struct barrier_s { int arity; int count; struct barrier_s* dad; int signal; }; typedef struct barrier_s barrier_t; struct thrcomm_s { void* sent_object; dim_t n_threads; barrier_t** barriers; }; #else struct thrcomm_s { void* sent_object; dim_t n_threads; // NOTE: barrier_sense was originally a gint_t-based bool_t, but upon // redefining bool_t as bool we discovered that some gcc __atomic built-ins // don't allow the use of bool for the variables being operated upon. // (Specifically, this was observed of __atomic_fetch_xor(), but it likely // applies to all other related built-ins.) Thus, we get around this by // redefining barrier_sense as a gint_t. gint_t barrier_sense; dim_t barrier_threads_arrived; }; #endif typedef struct thrcomm_s thrcomm_t; #endif #endif blis-0.9.0/frame/thread/bli_thread.c000066400000000000000000001376661422157504600173040ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" thrinfo_t BLIS_PACKM_SINGLE_THREADED = {}; thrinfo_t BLIS_GEMM_SINGLE_THREADED = {}; thrcomm_t BLIS_SINGLE_COMM = {}; // The global rntm_t structure. (The definition resides in bli_rntm.c.) extern rntm_t global_rntm; // A mutex to allow synchronous access to global_rntm. (The definition // resides in bli_rntm.c.) extern bli_pthread_mutex_t global_rntm_mutex; // ----------------------------------------------------------------------------- void bli_thread_init( void ) { bli_thrcomm_init( 1, &BLIS_SINGLE_COMM ); bli_packm_thrinfo_init_single( &BLIS_PACKM_SINGLE_THREADED ); bli_l3_thrinfo_init_single( &BLIS_GEMM_SINGLE_THREADED ); // Read the environment variables and use them to initialize the // global runtime object. bli_thread_init_rntm_from_env( &global_rntm ); } void bli_thread_finalize( void ) { } // ----------------------------------------------------------------------------- void bli_thread_range_sub ( thrinfo_t* thread, dim_t n, dim_t bf, bool handle_edge_low, dim_t* start, dim_t* end ) { dim_t n_way = bli_thread_n_way( thread ); if ( n_way == 1 ) { *start = 0; *end = n; return; } dim_t work_id = bli_thread_work_id( thread ); dim_t all_start = 0; dim_t all_end = n; dim_t size = all_end - all_start; dim_t n_bf_whole = size / bf; dim_t n_bf_left = size % bf; dim_t n_bf_lo = n_bf_whole / n_way; dim_t n_bf_hi = n_bf_whole / n_way; // In this function, we partition the space between all_start and // all_end into n_way partitions, each a multiple of block_factor // with the exception of the one partition that recieves the // "edge" case (if applicable). // // Here are examples of various thread partitionings, in units of // the block_factor, when n_way = 4. (A '+' indicates the thread // that receives the leftover edge case (ie: n_bf_left extra // rows/columns in its sub-range). // (all_start ... all_end) // n_bf_whole _left hel n_th_lo _hi thr0 thr1 thr2 thr3 // 12 =0 f 0 4 3 3 3 3 // 12 >0 f 0 4 3 3 3 3+ // 13 >0 f 1 3 4 3 3 3+ // 14 >0 f 2 2 4 4 3 3+ // 15 >0 f 3 1 4 4 4 3+ // 15 =0 f 3 1 4 4 4 3 // // 12 =0 t 4 0 3 3 3 3 // 12 >0 t 4 0 3+ 3 3 3 // 13 >0 t 3 1 3+ 3 3 4 // 14 >0 t 2 2 3+ 3 4 4 // 15 >0 t 1 3 3+ 4 4 4 // 15 =0 t 1 3 3 4 4 4 // As indicated by the table above, load is balanced as equally // as possible, even in the presence of an edge case. // First, we must differentiate between cases where the leftover // "edge" case (n_bf_left) should be allocated to a thread partition // at the low end of the index range or the high end. if ( handle_edge_low == FALSE ) { // Notice that if all threads receive the same number of // block_factors, those threads are considered "high" and // the "low" thread group is empty. dim_t n_th_lo = n_bf_whole % n_way; //dim_t n_th_hi = n_way - n_th_lo; // If some partitions must have more block_factors than others // assign the slightly larger partitions to lower index threads. if ( n_th_lo != 0 ) n_bf_lo += 1; // Compute the actual widths (in units of rows/columns) of // individual threads in the low and high groups. dim_t size_lo = n_bf_lo * bf; dim_t size_hi = n_bf_hi * bf; // Precompute the starting indices of the low and high groups. dim_t lo_start = all_start; dim_t hi_start = all_start + n_th_lo * size_lo; // Compute the start and end of individual threads' ranges // as a function of their work_ids and also the group to which // they belong (low or high). if ( work_id < n_th_lo ) { *start = lo_start + (work_id ) * size_lo; *end = lo_start + (work_id+1) * size_lo; } else // if ( n_th_lo <= work_id ) { *start = hi_start + (work_id-n_th_lo ) * size_hi; *end = hi_start + (work_id-n_th_lo+1) * size_hi; // Since the edge case is being allocated to the high // end of the index range, we have to advance the last // thread's end. if ( work_id == n_way - 1 ) *end += n_bf_left; } } else // if ( handle_edge_low == TRUE ) { // Notice that if all threads receive the same number of // block_factors, those threads are considered "low" and // the "high" thread group is empty. dim_t n_th_hi = n_bf_whole % n_way; dim_t n_th_lo = n_way - n_th_hi; // If some partitions must have more block_factors than others // assign the slightly larger partitions to higher index threads. if ( n_th_hi != 0 ) n_bf_hi += 1; // Compute the actual widths (in units of rows/columns) of // individual threads in the low and high groups. dim_t size_lo = n_bf_lo * bf; dim_t size_hi = n_bf_hi * bf; // Precompute the starting indices of the low and high groups. dim_t lo_start = all_start; dim_t hi_start = all_start + n_th_lo * size_lo + n_bf_left; // Compute the start and end of individual threads' ranges // as a function of their work_ids and also the group to which // they belong (low or high). if ( work_id < n_th_lo ) { *start = lo_start + (work_id ) * size_lo; *end = lo_start + (work_id+1) * size_lo; // Since the edge case is being allocated to the low // end of the index range, we have to advance the // starts/ends accordingly. if ( work_id == 0 ) *end += n_bf_left; else { *start += n_bf_left; *end += n_bf_left; } } else // if ( n_th_lo <= work_id ) { *start = hi_start + (work_id-n_th_lo ) * size_hi; *end = hi_start + (work_id-n_th_lo+1) * size_hi; } } } siz_t bli_thread_range_l2r ( thrinfo_t* thr, obj_t* a, blksz_t* bmult, dim_t* start, dim_t* end ) { num_t dt = bli_obj_dt( a ); dim_t m = bli_obj_length_after_trans( a ); dim_t n = bli_obj_width_after_trans( a ); dim_t bf = bli_blksz_get_def( dt, bmult ); bli_thread_range_sub( thr, n, bf, FALSE, start, end ); return m * ( *end - *start ); } siz_t bli_thread_range_r2l ( thrinfo_t* thr, obj_t* a, blksz_t* bmult, dim_t* start, dim_t* end ) { num_t dt = bli_obj_dt( a ); dim_t m = bli_obj_length_after_trans( a ); dim_t n = bli_obj_width_after_trans( a ); dim_t bf = bli_blksz_get_def( dt, bmult ); bli_thread_range_sub( thr, n, bf, TRUE, start, end ); return m * ( *end - *start ); } siz_t bli_thread_range_t2b ( thrinfo_t* thr, obj_t* a, blksz_t* bmult, dim_t* start, dim_t* end ) { num_t dt = bli_obj_dt( a ); dim_t m = bli_obj_length_after_trans( a ); dim_t n = bli_obj_width_after_trans( a ); dim_t bf = bli_blksz_get_def( dt, bmult ); bli_thread_range_sub( thr, m, bf, FALSE, start, end ); return n * ( *end - *start ); } siz_t bli_thread_range_b2t ( thrinfo_t* thr, obj_t* a, blksz_t* bmult, dim_t* start, dim_t* end ) { num_t dt = bli_obj_dt( a ); dim_t m = bli_obj_length_after_trans( a ); dim_t n = bli_obj_width_after_trans( a ); dim_t bf = bli_blksz_get_def( dt, bmult ); bli_thread_range_sub( thr, m, bf, TRUE, start, end ); return n * ( *end - *start ); } // ----------------------------------------------------------------------------- dim_t bli_thread_range_width_l ( doff_t diagoff_j, dim_t m, dim_t n_j, dim_t j, dim_t n_way, dim_t bf, dim_t bf_left, double area_per_thr, bool handle_edge_low ) { dim_t width; // In this function, we assume that we are somewhere in the process of // partitioning an m x n lower-stored region (with arbitrary diagonal // offset) n_ways along the n dimension (into column panels). The value // j identifies the left-to-right subpartition index (from 0 to n_way-1) // of the subpartition whose width we are about to compute using the // area per thread determined by the caller. n_j is the number of // columns in the remaining region of the matrix being partitioned, // and diagoff_j is that region's diagonal offset. // If this is the last subpartition, the width is simply equal to n_j. // Note that this statement handles cases where the "edge case" (if // one exists) is assigned to the high end of the index range (ie: // handle_edge_low == FALSE). if ( j == n_way - 1 ) return n_j; // At this point, we know there are at least two subpartitions left. // We also know that IF the submatrix contains a completely dense // rectangular submatrix, it will occur BEFORE the triangular (or // trapezoidal) part. // Here, we implement a somewhat minor load balancing optimization // that ends up getting employed only for relatively small matrices. // First, recall that all subpartition widths will be some multiple // of the blocking factor bf, except perhaps either the first or last // subpartition, which will receive the edge case, if it exists. // Also recall that j represents the current thread (or thread group, // or "caucus") for which we are computing a subpartition width. // If n_j is sufficiently small that we can only allocate bf columns // to each of the remaining threads, then we set the width to bf. We // do not allow the subpartition width to be less than bf, so, under // some conditions, if n_j is small enough, some of the reamining // threads may not get any work. For the purposes of this lower bound // on work (ie: width >= bf), we allow the edge case to count as a // "full" set of bf columns. { dim_t n_j_bf = n_j / bf + ( bf_left > 0 ? 1 : 0 ); if ( n_j_bf <= n_way - j ) { if ( j == 0 && handle_edge_low ) width = ( bf_left > 0 ? bf_left : bf ); else width = bf; // Make sure that the width does not exceed n_j. This would // occur if and when n_j_bf < n_way - j; that is, when the // matrix being partitioned is sufficiently small relative to // n_way such that there is not even enough work for every // (remaining) thread to get bf (or bf_left) columns. The // net effect of this safeguard is that some threads may get // assigned empty ranges (ie: no work), which of course must // happen in some situations. if ( width > n_j ) width = n_j; return width; } } // This block computes the width assuming that we are entirely within // a dense rectangle that precedes the triangular (or trapezoidal) // part. { // First compute the width of the current panel under the // assumption that the diagonal offset would not intersect. width = ( dim_t )bli_round( ( double )area_per_thr / ( double )m ); // Adjust the width, if necessary. Specifically, we may need // to allocate the edge case to the first subpartition, if // requested; otherwise, we just need to ensure that the // subpartition is a multiple of the blocking factor. if ( j == 0 && handle_edge_low ) { if ( width % bf != bf_left ) width += bf_left - ( width % bf ); } else // if interior case { // Round up to the next multiple of the blocking factor. //if ( width % bf != 0 ) width += bf - ( width % bf ); // Round to the nearest multiple of the blocking factor. if ( width % bf != 0 ) width = bli_round_to_mult( width, bf ); } } // We need to recompute width if the panel, according to the width // as currently computed, would intersect the diagonal. if ( diagoff_j < width ) { dim_t offm_inc, offn_inc; // Prune away the unstored region above the diagonal, if it exists. // Note that the entire region was pruned initially, so we know that // we don't need to try to prune the right side. (Also, we discard // the offset deltas since we don't need to actually index into the // subpartition.) bli_prune_unstored_region_top_l( &diagoff_j, &m, &n_j, &offm_inc ); //bli_prune_unstored_region_right_l( &diagoff_j, &m, &n_j, &offn_inc ); // We don't need offm_inc, offn_inc here. These statements should // prevent compiler warnings. ( void )offm_inc; ( void )offn_inc; // Prepare to solve a quadratic equation to find the width of the // current (jth) subpartition given the m dimension, diagonal offset, // and area. // NOTE: We know that the +/- in the quadratic formula must be a + // here because we know that the desired solution (the subpartition // width) will be smaller than (m + diagoff), not larger. If you // don't believe me, draw a picture! const double a = -0.5; const double b = ( double )m + ( double )diagoff_j + 0.5; const double c = -0.5 * ( ( double )diagoff_j * ( ( double )diagoff_j + 1.0 ) ) - area_per_thr; const double r = b * b - 4.0 * a * c; // If the quadratic solution is not imaginary, round it and use that // as our width, but make sure it didn't round to zero. Otherwise, // discard the quadratic solution and leave width, as previously // computed, unchanged. if ( r >= 0.0 ) { const double x = ( -b + sqrt( r ) ) / ( 2.0 * a ); width = ( dim_t )bli_round( x ); if ( width == 0 ) width = 1; } // Adjust the width, if necessary. if ( j == 0 && handle_edge_low ) { if ( width % bf != bf_left ) width += bf_left - ( width % bf ); } else // if interior case { // Round up to the next multiple of the blocking factor. //if ( width % bf != 0 ) width += bf - ( width % bf ); // Round to the nearest multiple of the blocking factor. if ( width % bf != 0 ) width = bli_round_to_mult( width, bf ); } } // Make sure that the width, after being adjusted, does not cause the // subpartition to exceed n_j. if ( width > n_j ) width = n_j; return width; } siz_t bli_find_area_trap_l ( dim_t m, dim_t n, doff_t diagoff ) { dim_t offm_inc = 0; dim_t offn_inc = 0; double tri_area; double area; // Prune away any rectangular region above where the diagonal // intersects the left edge of the subpartition, if it exists. bli_prune_unstored_region_top_l( &diagoff, &m, &n, &offm_inc ); // Prune away any rectangular region to the right of where the // diagonal intersects the bottom edge of the subpartition, if // it exists. (This shouldn't ever be needed, since the caller // would presumably have already performed rightward pruning, // but it's here just in case.) bli_prune_unstored_region_right_l( &diagoff, &m, &n, &offn_inc ); ( void )offm_inc; ( void )offn_inc; // Compute the area of the empty triangle so we can subtract it // from the area of the rectangle that bounds the subpartition. if ( bli_intersects_diag_n( diagoff, m, n ) ) { double tri_dim = ( double )( n - diagoff - 1 ); tri_area = tri_dim * ( tri_dim + 1.0 ) / 2.0; } else { // If the diagonal does not intersect the trapezoid, then // we can compute the area as a simple rectangle. tri_area = 0.0; } area = ( double )m * ( double )n - tri_area; return ( siz_t )area; } // ----------------------------------------------------------------------------- siz_t bli_thread_range_weighted_sub ( thrinfo_t* restrict thread, doff_t diagoff, uplo_t uplo, dim_t m, dim_t n, dim_t bf, bool handle_edge_low, dim_t* restrict j_start_thr, dim_t* restrict j_end_thr ) { dim_t n_way = bli_thread_n_way( thread ); dim_t my_id = bli_thread_work_id( thread ); dim_t bf_left = n % bf; dim_t j; dim_t off_j; doff_t diagoff_j; dim_t n_left; dim_t width_j; dim_t offm_inc, offn_inc; double tri_dim, tri_area; double area_total, area_per_thr; siz_t area = 0; // In this function, we assume that the caller has already determined // that (a) the diagonal intersects the submatrix, and (b) the submatrix // is either lower- or upper-stored. if ( bli_is_lower( uplo ) ) { // Prune away the unstored region above the diagonal, if it exists, // and then to the right of where the diagonal intersects the bottom, // if it exists. (Also, we discard the offset deltas since we don't // need to actually index into the subpartition.) bli_prune_unstored_region_top_l( &diagoff, &m, &n, &offm_inc ); bli_prune_unstored_region_right_l( &diagoff, &m, &n, &offn_inc ); // We don't need offm_inc, offn_inc here. These statements should // prevent compiler warnings. ( void )offm_inc; ( void )offn_inc; // Now that pruning has taken place, we know that diagoff >= 0. // Compute the total area of the submatrix, accounting for the // location of the diagonal, and divide it by the number of ways // of parallelism. tri_dim = ( double )( n - diagoff - 1 ); tri_area = tri_dim * ( tri_dim + 1.0 ) / 2.0; area_total = ( double )m * ( double )n - tri_area; area_per_thr = area_total / ( double )n_way; // Initialize some variables prior to the loop: the offset to the // current subpartition, the remainder of the n dimension, and // the diagonal offset of the current subpartition. off_j = 0; diagoff_j = diagoff; n_left = n; // Iterate over the subpartition indices corresponding to each // thread/caucus participating in the n_way parallelism. for ( j = 0; j < n_way; ++j ) { // Compute the width of the jth subpartition, taking the // current diagonal offset into account, if needed. width_j = bli_thread_range_width_l ( diagoff_j, m, n_left, j, n_way, bf, bf_left, area_per_thr, handle_edge_low ); // If the current thread belongs to caucus j, this is his // subpartition. So we compute the implied index range and // end our search. if ( j == my_id ) { *j_start_thr = off_j; *j_end_thr = off_j + width_j; area = bli_find_area_trap_l( m, width_j, diagoff_j ); break; } // Shift the current subpartition's starting and diagonal offsets, // as well as the remainder of the n dimension, according to the // computed width, and then iterate to the next subpartition. off_j += width_j; diagoff_j -= width_j; n_left -= width_j; } } else // if ( bli_is_upper( uplo ) ) { // Express the upper-stored case in terms of the lower-stored case. // First, we convert the upper-stored trapezoid to an equivalent // lower-stored trapezoid by rotating it 180 degrees. bli_rotate180_trapezoid( &diagoff, &uplo, &m, &n ); // Now that the trapezoid is "flipped" in the n dimension, negate // the bool that encodes whether to handle the edge case at the // low (or high) end of the index range. bli_toggle_bool( &handle_edge_low ); // Compute the appropriate range for the rotated trapezoid. area = bli_thread_range_weighted_sub ( thread, diagoff, uplo, m, n, bf, handle_edge_low, j_start_thr, j_end_thr ); // Reverse the indexing basis for the subpartition ranges so that // the indices, relative to left-to-right iteration through the // unrotated upper-stored trapezoid, map to the correct columns // (relative to the diagonal). This amounts to subtracting the // range from n. bli_reverse_index_direction( n, j_start_thr, j_end_thr ); } return area; } siz_t bli_thread_range_mdim ( dir_t direct, thrinfo_t* thr, obj_t* a, obj_t* b, obj_t* c, cntl_t* cntl, cntx_t* cntx, dim_t* start, dim_t* end ) { bszid_t bszid = bli_cntl_bszid( cntl ); opid_t family = bli_cntl_family( cntl ); // This is part of trsm's current implementation, whereby right side // cases are implemented in left-side micro-kernels, which requires // we swap the usage of the register blocksizes for the purposes of // packing A and B. if ( family == BLIS_TRSM ) { if ( bli_obj_root_is_triangular( a ) ) bszid = BLIS_MR; else bszid = BLIS_NR; } blksz_t* bmult = bli_cntx_get_bmult( bszid, cntx ); obj_t* x; bool use_weighted; // Use the operation family to choose the one of the two matrices // being partitioned that potentially has structure, and also to // decide whether or not we need to use weighted range partitioning. // NOTE: It's important that we use non-weighted range partitioning // for hemm and symm (ie: the gemm family) because the weighted // function will mistakenly skip over unstored regions of the // structured matrix, even though they represent part of that matrix // that will be dense and full (after packing). if ( family == BLIS_GEMM ) { x = a; use_weighted = FALSE; } else if ( family == BLIS_GEMMT ) { x = c; use_weighted = TRUE; } else if ( family == BLIS_TRMM ) { x = a; use_weighted = TRUE; } else /*family == BLIS_TRSM*/ { x = a; use_weighted = FALSE; } if ( use_weighted ) { if ( direct == BLIS_FWD ) return bli_thread_range_weighted_t2b( thr, x, bmult, start, end ); else return bli_thread_range_weighted_b2t( thr, x, bmult, start, end ); } else { if ( direct == BLIS_FWD ) return bli_thread_range_t2b( thr, x, bmult, start, end ); else return bli_thread_range_b2t( thr, x, bmult, start, end ); } } siz_t bli_thread_range_ndim ( dir_t direct, thrinfo_t* thr, obj_t* a, obj_t* b, obj_t* c, cntl_t* cntl, cntx_t* cntx, dim_t* start, dim_t* end ) { bszid_t bszid = bli_cntl_bszid( cntl ); opid_t family = bli_cntl_family( cntl ); // This is part of trsm's current implementation, whereby right side // cases are implemented in left-side micro-kernels, which requires // we swap the usage of the register blocksizes for the purposes of // packing A and B. if ( family == BLIS_TRSM ) { if ( bli_obj_root_is_triangular( b ) ) bszid = BLIS_MR; else bszid = BLIS_NR; } blksz_t* bmult = bli_cntx_get_bmult( bszid, cntx ); obj_t* x; bool use_weighted; // Use the operation family to choose the one of the two matrices // being partitioned that potentially has structure, and also to // decide whether or not we need to use weighted range partitioning. // NOTE: It's important that we use non-weighted range partitioning // for hemm and symm (ie: the gemm family) because the weighted // function will mistakenly skip over unstored regions of the // structured matrix, even though they represent part of that matrix // that will be dense and full (after packing). if ( family == BLIS_GEMM ) { x = b; use_weighted = FALSE; } else if ( family == BLIS_GEMMT ) { x = c; use_weighted = TRUE; } else if ( family == BLIS_TRMM ) { x = b; use_weighted = TRUE; } else /*family == BLIS_TRSM*/ { x = b; use_weighted = FALSE; } if ( use_weighted ) { if ( direct == BLIS_FWD ) return bli_thread_range_weighted_l2r( thr, x, bmult, start, end ); else return bli_thread_range_weighted_r2l( thr, x, bmult, start, end ); } else { if ( direct == BLIS_FWD ) return bli_thread_range_l2r( thr, x, bmult, start, end ); else return bli_thread_range_r2l( thr, x, bmult, start, end ); } } siz_t bli_thread_range_weighted_l2r ( thrinfo_t* thr, obj_t* a, blksz_t* bmult, dim_t* start, dim_t* end ) { siz_t area; // This function assigns area-weighted ranges in the n dimension // where the total range spans 0 to n-1 with 0 at the left end and // n-1 at the right end. if ( bli_obj_intersects_diag( a ) && bli_obj_is_upper_or_lower( a ) ) { num_t dt = bli_obj_dt( a ); doff_t diagoff = bli_obj_diag_offset( a ); uplo_t uplo = bli_obj_uplo( a ); dim_t m = bli_obj_length( a ); dim_t n = bli_obj_width( a ); dim_t bf = bli_blksz_get_def( dt, bmult ); // Support implicit transposition. if ( bli_obj_has_trans( a ) ) { bli_reflect_about_diag( &diagoff, &uplo, &m, &n ); } area = bli_thread_range_weighted_sub ( thr, diagoff, uplo, m, n, bf, FALSE, start, end ); } else // if dense or zeros { area = bli_thread_range_l2r ( thr, a, bmult, start, end ); } return area; } siz_t bli_thread_range_weighted_r2l ( thrinfo_t* thr, obj_t* a, blksz_t* bmult, dim_t* start, dim_t* end ) { siz_t area; // This function assigns area-weighted ranges in the n dimension // where the total range spans 0 to n-1 with 0 at the right end and // n-1 at the left end. if ( bli_obj_intersects_diag( a ) && bli_obj_is_upper_or_lower( a ) ) { num_t dt = bli_obj_dt( a ); doff_t diagoff = bli_obj_diag_offset( a ); uplo_t uplo = bli_obj_uplo( a ); dim_t m = bli_obj_length( a ); dim_t n = bli_obj_width( a ); dim_t bf = bli_blksz_get_def( dt, bmult ); // Support implicit transposition. if ( bli_obj_has_trans( a ) ) { bli_reflect_about_diag( &diagoff, &uplo, &m, &n ); } bli_rotate180_trapezoid( &diagoff, &uplo, &m, &n ); area = bli_thread_range_weighted_sub ( thr, diagoff, uplo, m, n, bf, TRUE, start, end ); } else // if dense or zeros { area = bli_thread_range_r2l ( thr, a, bmult, start, end ); } return area; } siz_t bli_thread_range_weighted_t2b ( thrinfo_t* thr, obj_t* a, blksz_t* bmult, dim_t* start, dim_t* end ) { siz_t area; // This function assigns area-weighted ranges in the m dimension // where the total range spans 0 to m-1 with 0 at the top end and // m-1 at the bottom end. if ( bli_obj_intersects_diag( a ) && bli_obj_is_upper_or_lower( a ) ) { num_t dt = bli_obj_dt( a ); doff_t diagoff = bli_obj_diag_offset( a ); uplo_t uplo = bli_obj_uplo( a ); dim_t m = bli_obj_length( a ); dim_t n = bli_obj_width( a ); dim_t bf = bli_blksz_get_def( dt, bmult ); // Support implicit transposition. if ( bli_obj_has_trans( a ) ) { bli_reflect_about_diag( &diagoff, &uplo, &m, &n ); } bli_reflect_about_diag( &diagoff, &uplo, &m, &n ); area = bli_thread_range_weighted_sub ( thr, diagoff, uplo, m, n, bf, FALSE, start, end ); } else // if dense or zeros { area = bli_thread_range_t2b ( thr, a, bmult, start, end ); } return area; } siz_t bli_thread_range_weighted_b2t ( thrinfo_t* thr, obj_t* a, blksz_t* bmult, dim_t* start, dim_t* end ) { siz_t area; // This function assigns area-weighted ranges in the m dimension // where the total range spans 0 to m-1 with 0 at the bottom end and // m-1 at the top end. if ( bli_obj_intersects_diag( a ) && bli_obj_is_upper_or_lower( a ) ) { num_t dt = bli_obj_dt( a ); doff_t diagoff = bli_obj_diag_offset( a ); uplo_t uplo = bli_obj_uplo( a ); dim_t m = bli_obj_length( a ); dim_t n = bli_obj_width( a ); dim_t bf = bli_blksz_get_def( dt, bmult ); // Support implicit transposition. if ( bli_obj_has_trans( a ) ) { bli_reflect_about_diag( &diagoff, &uplo, &m, &n ); } bli_reflect_about_diag( &diagoff, &uplo, &m, &n ); bli_rotate180_trapezoid( &diagoff, &uplo, &m, &n ); area = bli_thread_range_weighted_sub ( thr, diagoff, uplo, m, n, bf, TRUE, start, end ); } else // if dense or zeros { area = bli_thread_range_b2t ( thr, a, bmult, start, end ); } return area; } // ----------------------------------------------------------------------------- void bli_prime_factorization( dim_t n, bli_prime_factors_t* factors ) { factors->n = n; factors->sqrt_n = ( dim_t )sqrt( ( double )n ); factors->f = 2; } dim_t bli_next_prime_factor( bli_prime_factors_t* factors ) { // Return the prime factorization of the original number n one-by-one. // Return 1 after all factors have been exhausted. // Looping over possible factors in increasing order assures we will // only return prime factors (a la the Sieve of Eratosthenes). while ( factors->f <= factors->sqrt_n ) { // Special cases for factors 2-7 handle all numbers not divisible by 11 // or another larger prime. The slower loop version is used after that. // If you use a number of threads with large prime factors you get // what you deserve. if ( factors->f == 2 ) { if ( factors->n % 2 == 0 ) { factors->n /= 2; return 2; } factors->f = 3; } else if ( factors->f == 3 ) { if ( factors->n % 3 == 0 ) { factors->n /= 3; return 3; } factors->f = 5; } else if ( factors->f == 5 ) { if ( factors->n % 5 == 0 ) { factors->n /= 5; return 5; } factors->f = 7; } else if ( factors->f == 7 ) { if ( factors->n % 7 == 0 ) { factors->n /= 7; return 7; } factors->f = 11; } else { if ( factors->n % factors->f == 0 ) { factors->n /= factors->f; return factors->f; } factors->f++; } } // To get here we must be out of prime factors, leaving only n (if it is // prime) or an endless string of 1s. dim_t tmp = factors->n; factors->n = 1; return tmp; } bool bli_is_prime( dim_t n ) { bli_prime_factors_t factors; bli_prime_factorization( n, &factors ); dim_t f = bli_next_prime_factor( &factors ); if ( f == n ) return TRUE; else return FALSE; } void bli_thread_partition_2x2 ( dim_t n_thread, dim_t work1, dim_t work2, dim_t* restrict nt1, dim_t* restrict nt2 ) { // Partition a number of threads into two factors nt1 and nt2 such that // nt1/nt2 ~= work1/work2. There is a fast heuristic algorithm and a // slower optimal algorithm (which minimizes |nt1*work2 - nt2*work1|). // Return early small prime numbers of threads. if ( n_thread < 4 ) { *nt1 = ( work1 >= work2 ? n_thread : 1 ); *nt2 = ( work1 < work2 ? n_thread : 1 ); return; } #if 1 bli_thread_partition_2x2_fast( n_thread, work1, work2, nt1, nt2 ); #else bli_thread_partition_2x2_slow( n_thread, work1, work2, nt1, nt2 ); #endif } //#define PRINT_FACTORS void bli_thread_partition_2x2_fast ( dim_t n_thread, dim_t work1, dim_t work2, dim_t* restrict nt1, dim_t* restrict nt2 ) { // Compute with these local variables until the end of the function, at // which time we will save the values back to nt1 and nt2. dim_t tn1 = 1; dim_t tn2 = 1; // Both algorithms need the prime factorization of n_thread. bli_prime_factors_t factors; bli_prime_factorization( n_thread, &factors ); // Fast algorithm: assign prime factors in increasing order to whichever // partition has more work to do. The work is divided by the number of // threads assigned at each iteration. This algorithm is sub-optimal in // some cases. We attempt to mitigate the cases that involve at least one // factor of 2. For example, in the partitioning of 12 with equal work // this algorithm tentatively finds 6x2. This factorization involves a // factor of 2 that can be reallocated, allowing us to convert it to the // optimal solution of 4x3. But some cases cannot be corrected this way // because they do not contain a factor of 2. For example, this algorithm // factors 105 (with equal work) into 21x5 whereas 7x15 would be optimal. #ifdef PRINT_FACTORS printf( "w1 w2 = %d %d (initial)\n", (int)work1, (int)work2 ); #endif dim_t f; while ( ( f = bli_next_prime_factor( &factors ) ) > 1 ) { #ifdef PRINT_FACTORS printf( "w1 w2 = %4d %4d nt1 nt2 = %d %d ... f = %d\n", (int)work1, (int)work2, (int)tn1, (int)tn2, (int)f ); #endif if ( work1 > work2 ) { work1 /= f; tn1 *= f; } else { work2 /= f; tn2 *= f; } } #ifdef PRINT_FACTORS printf( "w1 w2 = %4d %4d nt1 nt2 = %d %d\n", (int)work1, (int)work2, (int)tn1, (int)tn2 ); #endif // Sometimes the last factor applied is prime. For example, on a square // matrix, we tentatively arrive (from the logic above) at: // - a 2x6 factorization when given 12 ways of parallelism // - a 2x10 factorization when given 20 ways of parallelism // - a 2x14 factorization when given 28 ways of parallelism // These factorizations are suboptimal under the assumption that we want // the parallelism to be as balanced as possible. Below, we make a final // attempt at rebalancing nt1 and nt2 by checking to see if the gap between // work1 and work2 is narrower if we reallocate a factor of 2. if ( work1 > work2 ) { // Example: nt = 12 // w1 w2 (initial) = 3600 3600; nt1 nt2 = 1 1 // w1 w2 (tentative) = 1800 600; nt1 nt2 = 2 6 // w1 w2 (ideal) = 900 1200; nt1 nt2 = 4 3 if ( tn2 % 2 == 0 ) { dim_t diff = work1 - work2; dim_t diff_mod = bli_abs( work1/2 - work2*2 ); if ( diff_mod < diff ) { tn1 *= 2; tn2 /= 2; } } } else if ( work1 < work2 ) { // Example: nt = 40 // w1 w2 (initial) = 3600 3600; nt1 nt2 = 1 1 // w1 w2 (tentative) = 360 900; nt1 nt2 = 10 4 // w1 w2 (ideal) = 720 450; nt1 nt2 = 5 8 if ( tn1 % 2 == 0 ) { dim_t diff = work2 - work1; dim_t diff_mod = bli_abs( work2/2 - work1*2 ); if ( diff_mod < diff ) { tn1 /= 2; tn2 *= 2; } } } #ifdef PRINT_FACTORS printf( "w1 w2 = %4d %4d nt1 nt2 = %d %d (final)\n", (int)work1, (int)work2, (int)tn1, (int)tn2 ); #endif // Save the final result. *nt1 = tn1; *nt2 = tn2; } #include "limits.h" void bli_thread_partition_2x2_slow ( dim_t n_thread, dim_t work1, dim_t work2, dim_t* restrict nt1, dim_t* restrict nt2 ) { // Slow algorithm: exhaustively constructs all factor pairs of n_thread and // chooses the best one. // Compute with these local variables until the end of the function, at // which time we will save the values back to nt1 and nt2. dim_t tn1 = 1; dim_t tn2 = 1; // Both algorithms need the prime factorization of n_thread. bli_prime_factors_t factors; bli_prime_factorization( n_thread, &factors ); // Eight prime factors handles n_thread up to 223092870. dim_t fact[8]; dim_t mult[8]; // There is always at least one prime factor, so use if for initialization. dim_t nfact = 1; fact[0] = bli_next_prime_factor( &factors ); mult[0] = 1; // Collect the remaining prime factors, accounting for multiplicity of // repeated factors. dim_t f; while ( ( f = bli_next_prime_factor( &factors ) ) > 1 ) { if ( f == fact[nfact-1] ) { mult[nfact-1]++; } else { nfact++; fact[nfact-1] = f; mult[nfact-1] = 1; } } // Now loop over all factor pairs. A single factor pair is denoted by how // many of each prime factor are included in the first factor (ntaken). dim_t ntake[8] = {0}; dim_t min_diff = INT_MAX; // Loop over how many prime factors to assign to the first factor in the // pair, for each prime factor. The total number of iterations is // \Prod_{i=0}^{nfact-1} mult[i]. bool done = FALSE; while ( !done ) { dim_t x = 1; dim_t y = 1; // Form the factors by integer exponentiation and accumulation. for ( dim_t i = 0 ; i < nfact ; i++ ) { x *= bli_ipow( fact[i], ntake[i] ); y *= bli_ipow( fact[i], mult[i]-ntake[i] ); } // Check if this factor pair is optimal by checking // |nt1*work2 - nt2*work1|. dim_t diff = llabs( x*work2 - y*work1 ); if ( diff < min_diff ) { min_diff = diff; tn1 = x; tn2 = y; } // Go to the next factor pair by doing an "odometer loop". for ( dim_t i = 0 ; i < nfact ; i++ ) { if ( ++ntake[i] > mult[i] ) { ntake[i] = 0; if ( i == nfact-1 ) done = TRUE; else continue; } break; } } // Save the final result. *nt1 = tn1; *nt2 = tn2; } #if 0 void bli_thread_partition_2x2_orig ( dim_t n_thread, dim_t work1, dim_t work2, dim_t* restrict nt1, dim_t* restrict nt2 ) { // Copy nt1 and nt2 to local variables and then compute with those local // variables until the end of the function, at which time we will save the // values back to nt1 and nt2. dim_t tn1; // = *nt1; dim_t tn2; // = *nt2; // Partition a number of threads into two factors nt1 and nt2 such that // nt1/nt2 ~= work1/work2. There is a fast heuristic algorithm and a // slower optimal algorithm (which minimizes |nt1*work2 - nt2*work1|). // Return early small prime numbers of threads. if ( n_thread < 4 ) { tn1 = ( work1 >= work2 ? n_thread : 1 ); tn2 = ( work1 < work2 ? n_thread : 1 ); return; } tn1 = 1; tn2 = 1; // Both algorithms need the prime factorization of n_thread. bli_prime_factors_t factors; bli_prime_factorization( n_thread, &factors ); #if 1 // Fast algorithm: assign prime factors in increasing order to whichever // partition has more work to do. The work is divided by the number of // threads assigned at each iteration. This algorithm is sub-optimal in // some cases. We attempt to mitigate the cases that involve at least one // factor of 2. For example, in the partitioning of 12 with equal work // this algorithm tentatively finds 6x2. This factorization involves a // factor of 2 that can be reallocated, allowing us to convert it to the // optimal solution of 4x3. But some cases cannot be corrected this way // because they do not contain a factor of 2. For example, this algorithm // factors 105 (with equal work) into 21x5 whereas 7x15 would be optimal. //printf( "w1 w2 = %d %d (initial)\n", (int)work1, (int)work2 ); dim_t f; while ( ( f = bli_next_prime_factor( &factors ) ) > 1 ) { //printf( "w1 w2 = %4d %4d nt1 nt2 = %d %d ... f = %d\n", (int)work1, (int)work2, (int)tn1, (int)tn2, (int)f ); if ( work1 > work2 ) { work1 /= f; tn1 *= f; } else { work2 /= f; tn2 *= f; } } //printf( "w1 w2 = %4d %4d nt1 nt2 = %d %d\n", (int)work1, (int)work2, (int)tn1, (int)tn2 ); // Sometimes the last factor applied is prime. For example, on a square // matrix, we tentatively arrive (from the logic above) at: // - a 2x6 factorization when given 12 ways of parallelism // - a 2x10 factorization when given 20 ways of parallelism // - a 2x14 factorization when given 28 ways of parallelism // These factorizations are suboptimal under the assumption that we want // the parallelism to be as balanced as possible. Below, we make a final // attempt at rebalancing nt1 and nt2 by checking to see if the gap between // work1 and work2 is narrower if we reallocate a factor of 2. if ( work1 > work2 ) { // Example: nt = 12 // w1 w2 (initial) = 3600 3600; nt1 nt2 = 1 1 // w1 w2 (tentative) = 1800 600; nt1 nt2 = 2 6 // w1 w2 (ideal) = 900 1200; nt1 nt2 = 4 3 if ( tn2 % 2 == 0 ) { dim_t diff = work1 - work2; dim_t diff_mod = bli_abs( work1/2 - work2*2 ); if ( diff_mod < diff ) { tn1 *= 2; tn2 /= 2; } } } else if ( work1 < work2 ) { // Example: nt = 40 // w1 w2 (initial) = 3600 3600; nt1 nt2 = 1 1 // w1 w2 (tentative) = 360 900; nt1 nt2 = 10 4 // w1 w2 (ideal) = 720 450; nt1 nt2 = 5 8 if ( tn1 % 2 == 0 ) { dim_t diff = work2 - work1; dim_t diff_mod = bli_abs( work2/2 - work1*2 ); if ( diff_mod < diff ) { tn1 /= 2; tn2 *= 2; } } } //printf( "w1 w2 = %4d %4d nt1 nt2 = %d %d (final)\n", (int)work1, (int)work2, (int)tn1, (int)tn2 ); #else // Slow algorithm: exhaustively constructs all factor pairs of n_thread and // chooses the best one. // Eight prime factors handles n_thread up to 223092870. dim_t fact[8]; dim_t mult[8]; // There is always at least one prime factor, so use if for initialization. dim_t nfact = 1; fact[0] = bli_next_prime_factor( &factors ); mult[0] = 1; // Collect the remaining prime factors, accounting for multiplicity of // repeated factors. dim_t f; while ( ( f = bli_next_prime_factor( &factors ) ) > 1 ) { if ( f == fact[nfact-1] ) { mult[nfact-1]++; } else { nfact++; fact[nfact-1] = f; mult[nfact-1] = 1; } } // Now loop over all factor pairs. A single factor pair is denoted by how // many of each prime factor are included in the first factor (ntaken). dim_t ntake[8] = {0}; dim_t min_diff = INT_MAX; // Loop over how many prime factors to assign to the first factor in the // pair, for each prime factor. The total number of iterations is // \Prod_{i=0}^{nfact-1} mult[i]. bool done = FALSE; while ( !done ) { dim_t x = 1; dim_t y = 1; // Form the factors by integer exponentiation and accumulation. for (dim_t i = 0 ; i < nfact ; i++ ) { x *= bli_ipow( fact[i], ntake[i] ); y *= bli_ipow( fact[i], mult[i]-ntake[i] ); } // Check if this factor pair is optimal by checking // |nt1*work2 - nt2*work1|. dim_t diff = llabs( x*work2 - y*work1 ); if ( diff < min_diff ) { min_diff = diff; tn1 = x; tn2 = y; } // Go to the next factor pair by doing an "odometer loop". for ( dim_t i = 0 ; i < nfact ; i++ ) { if ( ++ntake[i] > mult[i] ) { ntake[i] = 0; if ( i == nfact-1 ) done = TRUE; else continue; } break; } } #endif // Save the final result. *nt1 = tn1; *nt2 = tn2; } #endif // ----------------------------------------------------------------------------- dim_t bli_gcd( dim_t x, dim_t y ) { while ( y != 0 ) { dim_t t = y; y = x % y; x = t; } return x; } dim_t bli_lcm( dim_t x, dim_t y) { return x * y / bli_gcd( x, y ); } dim_t bli_ipow( dim_t base, dim_t power ) { dim_t p = 1; for ( dim_t mask = 0x1 ; mask <= power ; mask <<= 1 ) { if ( power & mask ) p *= base; base *= base; } return p; } // ----------------------------------------------------------------------------- dim_t bli_thread_get_jc_nt( void ) { // We must ensure that global_rntm has been initialized. bli_init_once(); return bli_rntm_jc_ways( &global_rntm ); } dim_t bli_thread_get_pc_nt( void ) { // We must ensure that global_rntm has been initialized. bli_init_once(); return bli_rntm_pc_ways( &global_rntm ); } dim_t bli_thread_get_ic_nt( void ) { // We must ensure that global_rntm has been initialized. bli_init_once(); return bli_rntm_ic_ways( &global_rntm ); } dim_t bli_thread_get_jr_nt( void ) { // We must ensure that global_rntm has been initialized. bli_init_once(); return bli_rntm_jr_ways( &global_rntm ); } dim_t bli_thread_get_ir_nt( void ) { // We must ensure that global_rntm has been initialized. bli_init_once(); return bli_rntm_ir_ways( &global_rntm ); } dim_t bli_thread_get_num_threads( void ) { // We must ensure that global_rntm has been initialized. bli_init_once(); return bli_rntm_num_threads( &global_rntm ); } // ---------------------------------------------------------------------------- void bli_thread_set_ways( dim_t jc, dim_t pc, dim_t ic, dim_t jr, dim_t ir ) { // We must ensure that global_rntm has been initialized. bli_init_once(); // Acquire the mutex protecting global_rntm. bli_pthread_mutex_lock( &global_rntm_mutex ); bli_rntm_set_ways_only( jc, pc, ic, jr, ir, &global_rntm ); // Release the mutex protecting global_rntm. bli_pthread_mutex_unlock( &global_rntm_mutex ); } void bli_thread_set_num_threads( dim_t n_threads ) { // We must ensure that global_rntm has been initialized. bli_init_once(); // Acquire the mutex protecting global_rntm. bli_pthread_mutex_lock( &global_rntm_mutex ); bli_rntm_set_num_threads_only( n_threads, &global_rntm ); // Release the mutex protecting global_rntm. bli_pthread_mutex_unlock( &global_rntm_mutex ); } // ---------------------------------------------------------------------------- void bli_thread_init_rntm_from_env ( rntm_t* rntm ) { // NOTE: We don't need to acquire the global_rntm_mutex here because this // function is only called from bli_thread_init(), which is only called // by bli_init_once(). bool auto_factor = FALSE; dim_t nt; dim_t jc, pc, ic, jr, ir; #ifdef BLIS_ENABLE_MULTITHREADING // Try to read BLIS_NUM_THREADS first. nt = bli_env_get_var( "BLIS_NUM_THREADS", -1 ); // If BLIS_NUM_THREADS was not set, try to read OMP_NUM_THREADS. if ( nt == -1 ) nt = bli_env_get_var( "OMP_NUM_THREADS", -1 ); // Read the environment variables for the number of threads (ways // of parallelism) for each individual loop. jc = bli_env_get_var( "BLIS_JC_NT", -1 ); pc = bli_env_get_var( "BLIS_PC_NT", -1 ); ic = bli_env_get_var( "BLIS_IC_NT", -1 ); jr = bli_env_get_var( "BLIS_JR_NT", -1 ); ir = bli_env_get_var( "BLIS_IR_NT", -1 ); // If any BLIS_*_NT environment variable was set, then we ignore the // value of BLIS_NUM_THREADS or OMP_NUM_THREADS and use the // BLIS_*_NT values instead (with unset variables being treated as if // they contained 1). if ( jc != -1 || pc != -1 || ic != -1 || jr != -1 || ir != -1 ) { if ( jc == -1 ) jc = 1; if ( pc == -1 ) pc = 1; if ( ic == -1 ) ic = 1; if ( jr == -1 ) jr = 1; if ( ir == -1 ) ir = 1; // Unset the value for nt. nt = -1; } // By this time, one of the following conditions holds: // - nt is -1 and the ways for each loop are -1. // - nt is -1 and the ways for each loop are all set. // - nt is set and the ways for each loop are -1. // If nt is set (ie: not -1), then we know we will perform an automatic // thread factorization (later, in bli_rntm.c). if ( nt != -1 ) auto_factor = TRUE; #else // When multithreading is disabled, always set the rntm_t ways // values to 1. nt = -1; jc = pc = ic = jr = ir = 1; #endif // Save the results back in the runtime object. bli_rntm_set_auto_factor_only( auto_factor, rntm ); bli_rntm_set_num_threads_only( nt, rntm ); bli_rntm_set_ways_only( jc, pc, ic, jr, ir, rntm ); #if 0 printf( "bli_thread_init_rntm_from_env()\n" ); bli_rntm_print( rntm ); #endif } blis-0.9.0/frame/thread/bli_thread.h000066400000000000000000000204421422157504600172700ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2016, Hewlett Packard Enterprise Development LP Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_THREAD_H #define BLIS_THREAD_H // Include thread communicator (thrcomm_t) object definitions and prototypes. #include "bli_thrcomm.h" // Include thread info (thrinfo_t) object definitions and prototypes. #include "bli_thrinfo.h" #include "bli_thrinfo_sup.h" // Include some operation-specific thrinfo_t prototypes. // Note that the bli_packm_thrinfo.h must be included before the others! #include "bli_packm_thrinfo.h" #include "bli_l3_thrinfo.h" // Include the level-3 thread decorator and related definitions and prototypes // for the conventional code path. #include "bli_l3_decor.h" // Include the level-3 thread decorator and related definitions and prototypes // for the sup code path. #include "bli_l3_sup_decor.h" // Initialization-related prototypes. void bli_thread_init( void ); void bli_thread_finalize( void ); // Thread range-related prototypes. BLIS_EXPORT_BLIS void bli_thread_range_sub ( thrinfo_t* thread, dim_t n, dim_t bf, bool handle_edge_low, dim_t* start, dim_t* end ); #undef GENPROT #define GENPROT( opname ) \ \ siz_t PASTEMAC0( opname ) \ ( \ dir_t direct, \ thrinfo_t* thr, \ obj_t* a, \ obj_t* b, \ obj_t* c, \ cntl_t* cntl, \ cntx_t* cntx, \ dim_t* start, \ dim_t* end \ ); GENPROT( thread_range_mdim ) GENPROT( thread_range_ndim ) #undef GENPROT #define GENPROT( opname ) \ \ siz_t PASTEMAC0( opname ) \ ( \ thrinfo_t* thr, \ obj_t* a, \ blksz_t* bmult, \ dim_t* start, \ dim_t* end \ ); GENPROT( thread_range_l2r ) GENPROT( thread_range_r2l ) GENPROT( thread_range_t2b ) GENPROT( thread_range_b2t ) GENPROT( thread_range_weighted_l2r ) GENPROT( thread_range_weighted_r2l ) GENPROT( thread_range_weighted_t2b ) GENPROT( thread_range_weighted_b2t ) dim_t bli_thread_range_width_l ( doff_t diagoff_j, dim_t m, dim_t n_j, dim_t j, dim_t n_way, dim_t bf, dim_t bf_left, double area_per_thr, bool handle_edge_low ); siz_t bli_find_area_trap_l ( dim_t m, dim_t n, doff_t diagoff ); siz_t bli_thread_range_weighted_sub ( thrinfo_t* restrict thread, doff_t diagoff, uplo_t uplo, dim_t m, dim_t n, dim_t bf, bool handle_edge_low, dim_t* restrict j_start_thr, dim_t* restrict j_end_thr ); // ----------------------------------------------------------------------------- // Factorization and partitioning prototypes typedef struct { dim_t n; dim_t sqrt_n; dim_t f; } bli_prime_factors_t; void bli_prime_factorization(dim_t n, bli_prime_factors_t* factors); dim_t bli_next_prime_factor(bli_prime_factors_t* factors); bool bli_is_prime( dim_t n ); void bli_thread_partition_2x2 ( dim_t n_thread, dim_t work1, dim_t work2, dim_t* restrict nt1, dim_t* restrict nt2 ); void bli_thread_partition_2x2_slow ( dim_t n_thread, dim_t work1, dim_t work2, dim_t* restrict nt1, dim_t* restrict nt2 ); void bli_thread_partition_2x2_fast ( dim_t n_thread, dim_t work1, dim_t work2, dim_t* restrict nt1, dim_t* restrict nt2 ); // ----------------------------------------------------------------------------- dim_t bli_gcd( dim_t x, dim_t y ); dim_t bli_lcm( dim_t x, dim_t y ); dim_t bli_ipow( dim_t base, dim_t power ); // ----------------------------------------------------------------------------- BLIS_EXPORT_BLIS dim_t bli_thread_get_jc_nt( void ); BLIS_EXPORT_BLIS dim_t bli_thread_get_pc_nt( void ); BLIS_EXPORT_BLIS dim_t bli_thread_get_ic_nt( void ); BLIS_EXPORT_BLIS dim_t bli_thread_get_jr_nt( void ); BLIS_EXPORT_BLIS dim_t bli_thread_get_ir_nt( void ); BLIS_EXPORT_BLIS dim_t bli_thread_get_num_threads( void ); BLIS_EXPORT_BLIS void bli_thread_set_ways( dim_t jc, dim_t pc, dim_t ic, dim_t jr, dim_t ir ); BLIS_EXPORT_BLIS void bli_thread_set_num_threads( dim_t value ); void bli_thread_init_rntm_from_env( rntm_t* rntm ); // ----------------------------------------------------------------------------- BLIS_INLINE void bli_thread_range_jrir_rr ( thrinfo_t* thread, dim_t n, dim_t bf, bool handle_edge_low, dim_t* start, dim_t* end, dim_t* inc ) { // Use interleaved partitioning of jr/ir loops. *start = bli_thread_work_id( thread ); *inc = bli_thread_n_way( thread ); *end = n; } BLIS_INLINE void bli_thread_range_jrir_sl ( thrinfo_t* thread, dim_t n, dim_t bf, bool handle_edge_low, dim_t* start, dim_t* end, dim_t* inc ) { // Use contiguous slab partitioning of jr/ir loops. bli_thread_range_sub( thread, n, bf, handle_edge_low, start, end ); *inc = 1; } BLIS_INLINE void bli_thread_range_jrir ( thrinfo_t* thread, dim_t n, dim_t bf, bool handle_edge_low, dim_t* start, dim_t* end, dim_t* inc ) { // Define a general-purpose version of bli_thread_range_jrir() whose // definition depends on whether slab or round-robin partitioning was // requested at configure-time. #ifdef BLIS_ENABLE_JRIR_SLAB bli_thread_range_jrir_sl( thread, n, bf, handle_edge_low, start, end, inc ); #else bli_thread_range_jrir_rr( thread, n, bf, handle_edge_low, start, end, inc ); #endif } #if 0 BLIS_INLINE void bli_thread_range_weighted_jrir ( thrinfo_t* thread, doff_t diagoff, uplo_t uplo, dim_t m, dim_t n, dim_t bf, bool handle_edge_low, dim_t* start, dim_t* end, dim_t* inc ) { #ifdef BLIS_ENABLE_JRIR_SLAB // Use contiguous slab partitioning for jr/ir loops. bli_thread_range_weighted_sub( thread, diagoff, uplo, m, n, bf, handle_edge_low, start, end ); *start = *start / bf; *inc = 1; if ( *end % bf ) *end = *end / bf + 1; else *end = *end / bf; #else // Use interleaved partitioning of jr/ir loops. *start = bli_thread_work_id( thread ); *inc = bli_thread_n_way( thread ); *end = n; #endif } #endif #endif blis-0.9.0/frame/thread/bli_thrinfo.c000066400000000000000000000475011422157504600174720ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" thrinfo_t* bli_thrinfo_create ( rntm_t* rntm, thrcomm_t* ocomm, dim_t ocomm_id, dim_t n_way, dim_t work_id, bool free_comm, bszid_t bszid, thrinfo_t* sub_node ) { #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_thrinfo_create(): " ); #endif thrinfo_t* thread = bli_sba_acquire( rntm, sizeof( thrinfo_t ) ); bli_thrinfo_init ( thread, ocomm, ocomm_id, n_way, work_id, free_comm, bszid, sub_node ); return thread; } void bli_thrinfo_init ( thrinfo_t* thread, thrcomm_t* ocomm, dim_t ocomm_id, dim_t n_way, dim_t work_id, bool free_comm, bszid_t bszid, thrinfo_t* sub_node ) { bli_thrinfo_set_ocomm( ocomm, thread ); bli_thrinfo_set_ocomm_id( ocomm_id, thread ); bli_thrinfo_set_n_way( n_way, thread ); bli_thrinfo_set_work_id( work_id, thread ); bli_thrinfo_set_free_comm( free_comm, thread ); bli_thrinfo_set_bszid( bszid, thread ); bli_thrinfo_set_sub_node( sub_node, thread ); bli_thrinfo_set_sub_prenode( NULL, thread ); } void bli_thrinfo_init_single ( thrinfo_t* thread ) { bli_thrinfo_init ( thread, &BLIS_SINGLE_COMM, 0, 1, 0, FALSE, BLIS_NO_PART, thread ); } void bli_thrinfo_free ( rntm_t* rntm, thrinfo_t* thread ) { if ( thread == NULL || thread == &BLIS_PACKM_SINGLE_THREADED || thread == &BLIS_GEMM_SINGLE_THREADED ) return; thrinfo_t* thrinfo_sub_prenode = bli_thrinfo_sub_prenode( thread ); thrinfo_t* thrinfo_sub_node = bli_thrinfo_sub_node( thread ); // Recursively free all children of the current thrinfo_t. if ( thrinfo_sub_prenode != NULL ) { bli_thrinfo_free( rntm, thrinfo_sub_prenode ); } // Recursively free all children of the current thrinfo_t. if ( thrinfo_sub_node != NULL ) { bli_thrinfo_free( rntm, thrinfo_sub_node ); } // Free the communicators, but only if the current thrinfo_t struct // is marked as needing them to be freed. The most common example of // thrinfo_t nodes NOT marked as needing their comms freed are those // associated with packm thrinfo_t nodes. if ( bli_thrinfo_needs_free_comm( thread ) ) { // The ochief always frees his communicator. if ( bli_thread_am_ochief( thread ) ) bli_thrcomm_free( rntm, bli_thrinfo_ocomm( thread ) ); } #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_thrinfo_free(): " ); #endif // Free the thrinfo_t struct. bli_sba_release( rntm, thread ); } // ----------------------------------------------------------------------------- void bli_thrinfo_grow ( rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ) { // First, consider the prenode branch of the thrinfo_t tree, which should be // expanded only if there exists a prenode branch in the cntl_t tree. if ( bli_cntl_sub_prenode( cntl ) != NULL ) { // We only need to take action if the thrinfo_t sub-node is NULL; if it // is non-NULL, then it has already been created and we'll use it as-is. if ( bli_thrinfo_sub_prenode( thread ) == NULL ) { // Assertion / sanity check. if ( bli_cntl_bszid( cntl ) != BLIS_MC ) { printf( "Assertion failed: Expanding prenode for non-IC loop?\n" ); bli_abort(); } // Now we must create the packa, jr, and ir nodes that make up // the prenode branch of current cntl_t node. // Create a new node (or, if needed, multiple nodes) along the // prenode branch of the tree and return the pointer to the // (highest) child. thrinfo_t* thread_prenode = bli_thrinfo_rgrow_prenode ( rntm, cntl, bli_cntl_sub_prenode( cntl ), thread ); // Attach the child thrinfo_t node for the secondary branch to its // parent structure. bli_thrinfo_set_sub_prenode( thread_prenode, thread ); } } // Now, grow the primary branch of the thrinfo_t tree. // NOTE: If bli_thrinfo_rgrow() is being called, the sub_node field will // always be non-NULL, and so there's no need to check it. //if ( bli_cntl_sub_node( cntl ) != NULL ) { // We only need to take action if the thrinfo_t sub-node is NULL; if it // is non-NULL, then it has already been created and we'll use it as-is. if ( bli_thrinfo_sub_node( thread ) == NULL ) { // Create a new node (or, if needed, multiple nodes) along the // main sub-node branch of the tree and return the pointer to the // (highest) child. thrinfo_t* thread_child = bli_thrinfo_rgrow ( rntm, cntl, bli_cntl_sub_node( cntl ), thread ); // Attach the child thrinfo_t node for the primary branch to its // parent structure. bli_thrinfo_set_sub_node( thread_child, thread ); } } } // ----------------------------------------------------------------------------- thrinfo_t* bli_thrinfo_rgrow ( rntm_t* rntm, cntl_t* cntl_par, cntl_t* cntl_cur, thrinfo_t* thread_par ) { thrinfo_t* thread_cur; // We must handle two cases: those where the next node in the // control tree is a partitioning node, and those where it is // a non-partitioning (ie: packing) node. if ( bli_cntl_bszid( cntl_cur ) != BLIS_NO_PART ) { // Create the child thrinfo_t node corresponding to cntl_cur, // with cntl_par being the parent. thread_cur = bli_thrinfo_create_for_cntl ( rntm, cntl_par, cntl_cur, thread_par ); } else // if ( bli_cntl_bszid( cntl_cur ) == BLIS_NO_PART ) { // Recursively grow the thread structure and return the top-most // thrinfo_t node of that segment. thrinfo_t* thread_seg = bli_thrinfo_rgrow ( rntm, cntl_par, bli_cntl_sub_node( cntl_cur ), thread_par ); // Create a thrinfo_t node corresponding to cntl_cur. Since the // corresponding cntl node, cntl_cur, is a non-partitioning node // (bszid = BLIS_NO_PART), this means it's a packing node. Packing // thrinfo_t nodes are formed differently than those corresponding to // partitioning nodes; specifically, their work_id's are set equal to // the their comm_id's. Also, notice that the free_comm field is set // to FALSE since cntl_cur is a non-partitioning node. The reason: // the communicator used here will be freed when thread_seg, or one // of its descendents, is freed. thread_cur = bli_thrinfo_create ( rntm, // rntm bli_thrinfo_ocomm( thread_seg ), // ocomm bli_thread_ocomm_id( thread_seg ), // ocomm_id bli_cntl_calc_num_threads_in( rntm, cntl_cur ), // n_way bli_thread_ocomm_id( thread_seg ), // work_id FALSE, // free_comm BLIS_NO_PART, // bszid thread_seg // sub_node ); } return thread_cur; } #define BLIS_NUM_STATIC_COMMS 80 thrinfo_t* bli_thrinfo_create_for_cntl ( rntm_t* rntm, cntl_t* cntl_par, cntl_t* cntl_chl, thrinfo_t* thread_par ) { // If we are running with a single thread, all of the code can be reduced // and simplified to this. if ( bli_rntm_calc_num_threads( rntm ) == 1 ) { thrinfo_t* thread_chl = bli_thrinfo_create ( rntm, // rntm &BLIS_SINGLE_COMM, // ocomm 0, // ocomm_id 1, // n_way 0, // work_id FALSE, // free_comm BLIS_NO_PART, // bszid NULL // sub_node ); return thread_chl; } thrcomm_t* static_comms[ BLIS_NUM_STATIC_COMMS ]; thrcomm_t** new_comms = NULL; const bszid_t bszid_chl = bli_cntl_bszid( cntl_chl ); const dim_t parent_nt_in = bli_thread_num_threads( thread_par ); const dim_t parent_n_way = bli_thread_n_way( thread_par ); const dim_t parent_comm_id = bli_thread_ocomm_id( thread_par ); const dim_t parent_work_id = bli_thread_work_id( thread_par ); // Sanity check: make sure the number of threads in the parent's // communicator is divisible by the number of new sub-groups. if ( parent_nt_in % parent_n_way != 0 ) { printf( "Assertion failed: parent_nt_in parent_n_way != 0\n" ); bli_abort(); } // Compute: // - the number of threads inside the new child comm, // - the current thread's id within the new communicator, // - the current thread's work id, given the ways of parallelism // to be obtained within the next loop. const dim_t child_nt_in = bli_cntl_calc_num_threads_in( rntm, cntl_chl ); const dim_t child_n_way = bli_rntm_ways_for( bszid_chl, rntm ); const dim_t child_comm_id = parent_comm_id % child_nt_in; const dim_t child_work_id = child_comm_id / ( child_nt_in / child_n_way ); //printf( "thread %d: child_n_way = %d child_nt_in = %d parent_n_way = %d (bszid = %d->%d)\n", (int)child_comm_id, (int)child_nt_in, (int)child_n_way, (int)parent_n_way, (int)bli_cntl_bszid( cntl_par ), (int)bszid_chl ); // The parent's chief thread creates a temporary array of thrcomm_t // pointers. if ( bli_thread_am_ochief( thread_par ) ) { err_t r_val; if ( parent_n_way > BLIS_NUM_STATIC_COMMS ) new_comms = bli_malloc_intl( parent_n_way * sizeof( thrcomm_t* ), &r_val ); else new_comms = static_comms; } // Broadcast the temporary array to all threads in the parent's // communicator. new_comms = bli_thread_broadcast( thread_par, new_comms ); // Chiefs in the child communicator allocate the communicator // object and store it in the array element corresponding to the // parent's work id. if ( child_comm_id == 0 ) new_comms[ parent_work_id ] = bli_thrcomm_create( rntm, child_nt_in ); bli_thread_barrier( thread_par ); // All threads create a new thrinfo_t node using the communicator // that was created by their chief, as identified by parent_work_id. thrinfo_t* thread_chl = bli_thrinfo_create ( rntm, // rntm new_comms[ parent_work_id ], // ocomm child_comm_id, // ocomm_id child_n_way, // n_way child_work_id, // work_id TRUE, // free_comm bszid_chl, // bszid NULL // sub_node ); bli_thread_barrier( thread_par ); // The parent's chief thread frees the temporary array of thrcomm_t // pointers. if ( bli_thread_am_ochief( thread_par ) ) { if ( parent_n_way > BLIS_NUM_STATIC_COMMS ) bli_free_intl( new_comms ); } return thread_chl; } // ----------------------------------------------------------------------------- thrinfo_t* bli_thrinfo_rgrow_prenode ( rntm_t* rntm, cntl_t* cntl_par, cntl_t* cntl_cur, thrinfo_t* thread_par ) { thrinfo_t* thread_cur; // We must handle two cases: those where the next node in the // control tree is a partitioning node, and those where it is // a non-partitioning (ie: packing) node. if ( bli_cntl_bszid( cntl_cur ) != BLIS_NO_PART ) { // Create the child thrinfo_t node corresponding to cntl_cur, // with cntl_par being the parent. thread_cur = bli_thrinfo_create_for_cntl_prenode ( rntm, cntl_par, cntl_cur, thread_par ); } else // if ( bli_cntl_bszid( cntl_cur ) == BLIS_NO_PART ) { // Recursively grow the thread structure and return the top-most // thrinfo_t node of that segment. thrinfo_t* thread_seg = bli_thrinfo_rgrow_prenode ( rntm, cntl_par, bli_cntl_sub_node( cntl_cur ), thread_par ); // Create a thrinfo_t node corresponding to cntl_cur. Since the // corresponding cntl node, cntl_cur, is a non-partitioning node // (bszid = BLIS_NO_PART), this means it's a packing node. Packing // thrinfo_t nodes are formed differently than those corresponding to // partitioning nodes; specifically, their work_id's are set equal to // the their comm_id's. Also, notice that the free_comm field is set // to FALSE since cntl_cur is a non-partitioning node. The reason: // the communicator used here will be freed when thread_seg, or one // of its descendents, is freed. thread_cur = bli_thrinfo_create ( rntm, // rntm bli_thrinfo_ocomm( thread_seg ), // ocomm bli_thread_ocomm_id( thread_seg ), // ocomm_id bli_cntl_calc_num_threads_in( rntm, cntl_par ), // n_way bli_thread_ocomm_id( thread_seg ), // work_id FALSE, // free_comm BLIS_NO_PART, // bszid thread_seg // sub_node ); } return thread_cur; } thrinfo_t* bli_thrinfo_create_for_cntl_prenode ( rntm_t* rntm, cntl_t* cntl_par, cntl_t* cntl_chl, thrinfo_t* thread_par ) { // NOTE: This function only has to work for the ic -> (pa -> jr) // thrinfo_t tree branch extension. After that, the function // bli_thrinfo_create_for_cntl() will be called for the last jr->ir // branch extension. const bszid_t bszid_chl = bli_cntl_bszid( cntl_chl ); const dim_t parent_nt_in = bli_thread_num_threads( thread_par ); const dim_t parent_n_way = bli_thread_n_way( thread_par ); const dim_t parent_comm_id = bli_thread_ocomm_id( thread_par ); //const dim_t parent_work_id = bli_thread_work_id( thread_par ); // Sanity check: make sure the number of threads in the parent's // communicator is divisible by the number of new sub-groups. if ( parent_nt_in % parent_n_way != 0 ) { printf( "Assertion failed: parent_nt_in (%d) parent_n_way (%d) != 0\n", ( int )parent_nt_in, ( int )parent_n_way ); bli_abort(); } //dim_t child_nt_in = bli_cntl_calc_num_threads_in( rntm, cntl_chl ); //dim_t child_n_way = bli_rntm_ways_for( bszid_chl, rntm ); const dim_t child_nt_in = parent_nt_in; const dim_t child_n_way = parent_nt_in; const dim_t child_comm_id = parent_comm_id % child_nt_in; const dim_t child_work_id = child_comm_id / ( child_nt_in / child_n_way ); bli_thread_barrier( thread_par ); // NOTE: Recall that parent_comm_id == child_comm_id, so checking for the // parent's chief-ness is equivalent to checking for chief-ness in the new // about-to-be-created communicator group. thrcomm_t* new_comm = NULL; if ( bli_thread_am_ochief( thread_par ) ) new_comm = bli_thrcomm_create( rntm, child_nt_in ); // Broadcast the new thrcomm_t address to the other threads in the // parent's group. new_comm = bli_thread_broadcast( thread_par, new_comm ); // All threads create a new thrinfo_t node using the communicator // that was created by their chief, as identified by parent_work_id. thrinfo_t* thread_chl = bli_thrinfo_create ( rntm, // rntm new_comm, // ocomm child_comm_id, // ocomm_id child_n_way, // n_way child_work_id, // work_id TRUE, // free_comm bszid_chl, // bszid NULL // sub_node ); bli_thread_barrier( thread_par ); return thread_chl; } // ----------------------------------------------------------------------------- #if 0 void bli_thrinfo_grow_tree ( rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ) { cntl_t* cntl_jc = cntl; thrinfo_t* thrinfo_jc = thread; bli_thrinfo_grow( rntm, cntl_jc, thrinfo_jc ); // inside jc loop: cntl_t* cntl_pc = bli_cntl_sub_node( cntl_jc ); thrinfo_t* thrinfo_pc = bli_thrinfo_sub_node( thrinfo_jc ); bli_thrinfo_grow( rntm, cntl_pc, thrinfo_pc ); // inside pc loop: cntl_t* cntl_pb = bli_cntl_sub_node( cntl_pc ); thrinfo_t* thrinfo_pb = bli_thrinfo_sub_node( thrinfo_pc ); bli_thrinfo_grow( rntm, cntl_pb, thrinfo_pb ); // after pb packing: cntl_t* cntl_ic = bli_cntl_sub_node( cntl_pb ); thrinfo_t* thrinfo_ic = bli_thrinfo_sub_node( thrinfo_pb ); bli_thrinfo_grow( rntm, cntl_ic, thrinfo_ic ); // -- main branch -- // inside ic loop: cntl_t* cntl_pa = bli_cntl_sub_node( cntl_ic ); thrinfo_t* thrinfo_pa = bli_thrinfo_sub_node( thrinfo_ic ); bli_thrinfo_grow( rntm, cntl_pa, thrinfo_pa ); // after pa packing: cntl_t* cntl_jr = bli_cntl_sub_node( cntl_pa ); thrinfo_t* thrinfo_jr = bli_thrinfo_sub_node( thrinfo_pa ); bli_thrinfo_grow( rntm, cntl_jr, thrinfo_jr ); // inside jr loop: //cntl_t* cntl_ir = bli_cntl_sub_node( cntl_jr ); //thrinfo_t* thrinfo_ir = bli_thrinfo_sub_node( thrinfo_jr ); // -- trsm branch -- // inside ic loop: cntl_t* cntl_pa0 = bli_cntl_sub_prenode( cntl_ic ); thrinfo_t* thrinfo_pa0 = bli_thrinfo_sub_prenode( thrinfo_ic ); bli_thrinfo_grow( rntm, cntl_pa0, thrinfo_pa0 ); // after pa packing: cntl_t* cntl_jr0 = bli_cntl_sub_node( cntl_pa0 ); thrinfo_t* thrinfo_jr0 = bli_thrinfo_sub_node( thrinfo_pa0 ); bli_thrinfo_grow( rntm, cntl_jr0, thrinfo_jr0 ); // inside jr loop: //cntl_t* cntl_ir0 = bli_cntl_sub_node( cntl_jr0 ); //thrinfo_t* thrinfo_ir0= bli_thrinfo_sub_node( thrinfo_jr0 ); } void bli_thrinfo_grow_tree_ic ( rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ) { cntl_t* cntl_ic = cntl; thrinfo_t* thrinfo_ic = thread; bli_thrinfo_grow( rntm, cntl_ic, thrinfo_ic ); // -- main branch -- // inside ic loop: cntl_t* cntl_pa = bli_cntl_sub_node( cntl_ic ); thrinfo_t* thrinfo_pa = bli_thrinfo_sub_node( thrinfo_ic ); bli_thrinfo_grow( rntm, cntl_pa, thrinfo_pa ); // after pa packing: cntl_t* cntl_jr = bli_cntl_sub_node( cntl_pa ); thrinfo_t* thrinfo_jr = bli_thrinfo_sub_node( thrinfo_pa ); bli_thrinfo_grow( rntm, cntl_jr, thrinfo_jr ); // inside jr loop: //cntl_t* cntl_ir = bli_cntl_sub_node( cntl_jr ); //thrinfo_t* thrinfo_ir = bli_thrinfo_sub_node( thrinfo_jr ); // -- trsm branch -- // inside ic loop: cntl_t* cntl_pa0 = bli_cntl_sub_prenode( cntl_ic ); thrinfo_t* thrinfo_pa0 = bli_thrinfo_sub_prenode( thrinfo_ic ); bli_thrinfo_grow( rntm, cntl_pa0, thrinfo_pa0 ); // after pa packing: cntl_t* cntl_jr0 = bli_cntl_sub_node( cntl_pa0 ); thrinfo_t* thrinfo_jr0 = bli_thrinfo_sub_node( thrinfo_pa0 ); bli_thrinfo_grow( rntm, cntl_jr0, thrinfo_jr0 ); // inside jr loop: //cntl_t* cntl_ir0 = bli_cntl_sub_node( cntl_jr0 ); //thrinfo_t* thrinfo_ir0= bli_thrinfo_sub_node( thrinfo_jr0 ); } #endif blis-0.9.0/frame/thread/bli_thrinfo.h000066400000000000000000000152361422157504600174770ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_THRINFO_H #define BLIS_THRINFO_H // Thread info structure definition struct thrinfo_s { // The thread communicator for the other threads sharing the same work // at this level. thrcomm_t* ocomm; // Our thread id within the ocomm thread communicator. dim_t ocomm_id; // The number of distinct threads used to parallelize the loop. dim_t n_way; // What we're working on. dim_t work_id; // When freeing, should the communicators in this node be freed? Usually, // this is field is true, but when nodes are created that share the same // communicators as other nodes (such as with packm nodes), this is set // to false. bool free_comm; // The bszid_t to help identify the node. This is mostly only useful when // debugging or tracing the allocation and release of thrinfo_t nodes. bszid_t bszid; struct thrinfo_s* sub_prenode; struct thrinfo_s* sub_node; }; typedef struct thrinfo_s thrinfo_t; // // thrinfo_t functions // NOTE: The naming of these should be made consistent at some point. // (ie: bli_thrinfo_ vs. bli_thread_) // // thrinfo_t query (field only) BLIS_INLINE dim_t bli_thread_num_threads( thrinfo_t* t ) { return (t->ocomm)->n_threads; } BLIS_INLINE dim_t bli_thread_ocomm_id( thrinfo_t* t ) { return t->ocomm_id; } BLIS_INLINE dim_t bli_thread_n_way( thrinfo_t* t ) { return t->n_way; } BLIS_INLINE dim_t bli_thread_work_id( thrinfo_t* t ) { return t->work_id; } BLIS_INLINE thrcomm_t* bli_thrinfo_ocomm( thrinfo_t* t ) { return t->ocomm; } BLIS_INLINE bool bli_thrinfo_needs_free_comm( thrinfo_t* t ) { return t->free_comm; } BLIS_INLINE dim_t bli_thread_bszid( thrinfo_t* t ) { return t->bszid; } BLIS_INLINE thrinfo_t* bli_thrinfo_sub_node( thrinfo_t* t ) { return t->sub_node; } BLIS_INLINE thrinfo_t* bli_thrinfo_sub_prenode( thrinfo_t* t ) { return t->sub_prenode; } // thrinfo_t query (complex) BLIS_INLINE bool bli_thread_am_ochief( thrinfo_t* t ) { return t->ocomm_id == 0; } // thrinfo_t modification BLIS_INLINE void bli_thrinfo_set_ocomm( thrcomm_t* ocomm, thrinfo_t* t ) { t->ocomm = ocomm; } BLIS_INLINE void bli_thrinfo_set_ocomm_id( dim_t ocomm_id, thrinfo_t* t ) { t->ocomm_id = ocomm_id; } BLIS_INLINE void bli_thrinfo_set_n_way( dim_t n_way, thrinfo_t* t ) { t->n_way = n_way; } BLIS_INLINE void bli_thrinfo_set_work_id( dim_t work_id, thrinfo_t* t ) { t->work_id = work_id; } BLIS_INLINE void bli_thrinfo_set_free_comm( bool free_comm, thrinfo_t* t ) { t->free_comm = free_comm; } BLIS_INLINE void bli_thrinfo_set_bszid( bszid_t bszid, thrinfo_t* t ) { t->bszid = bszid; } BLIS_INLINE void bli_thrinfo_set_sub_node( thrinfo_t* sub_node, thrinfo_t* t ) { t->sub_node = sub_node; } BLIS_INLINE void bli_thrinfo_set_sub_prenode( thrinfo_t* sub_prenode, thrinfo_t* t ) { t->sub_prenode = sub_prenode; } // other thrinfo_t-related functions BLIS_INLINE void* bli_thread_broadcast( thrinfo_t* t, void* p ) { return bli_thrcomm_bcast( t->ocomm_id, p, t->ocomm ); } BLIS_INLINE void bli_thread_barrier( thrinfo_t* t ) { bli_thrcomm_barrier( t->ocomm_id, t->ocomm ); } // // Prototypes for level-3 thrinfo functions not specific to any operation. // thrinfo_t* bli_thrinfo_create ( rntm_t* rntm, thrcomm_t* ocomm, dim_t ocomm_id, dim_t n_way, dim_t work_id, bool free_comm, bszid_t bszid, thrinfo_t* sub_node ); void bli_thrinfo_init ( thrinfo_t* thread, thrcomm_t* ocomm, dim_t ocomm_id, dim_t n_way, dim_t work_id, bool free_comm, bszid_t bszid, thrinfo_t* sub_node ); void bli_thrinfo_init_single ( thrinfo_t* thread ); void bli_thrinfo_free ( rntm_t* rntm, thrinfo_t* thread ); // ----------------------------------------------------------------------------- void bli_thrinfo_grow ( rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ); thrinfo_t* bli_thrinfo_rgrow ( rntm_t* rntm, cntl_t* cntl_par, cntl_t* cntl_cur, thrinfo_t* thread_par ); thrinfo_t* bli_thrinfo_create_for_cntl ( rntm_t* rntm, cntl_t* cntl_par, cntl_t* cntl_chl, thrinfo_t* thread_par ); thrinfo_t* bli_thrinfo_rgrow_prenode ( rntm_t* rntm, cntl_t* cntl_par, cntl_t* cntl_cur, thrinfo_t* thread_par ); thrinfo_t* bli_thrinfo_create_for_cntl_prenode ( rntm_t* rntm, cntl_t* cntl_par, cntl_t* cntl_chl, thrinfo_t* thread_par ); // ----------------------------------------------------------------------------- #if 0 void bli_thrinfo_grow_tree ( rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ); void bli_thrinfo_grow_tree_ic ( rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ); #endif #endif blis-0.9.0/frame/thread/bli_thrinfo_sup.c000066400000000000000000000242351422157504600203600ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_thrinfo_sup_grow ( rntm_t* rntm, bszid_t* bszid_par, thrinfo_t* thread ) { if ( thread == &BLIS_GEMM_SINGLE_THREADED || thread == &BLIS_PACKM_SINGLE_THREADED ) return; // NOTE: If bli_thrinfo_sup_rgrow() is being called, the sub_node field will // always be non-NULL, and so there's no need to check it. //if ( bli_cntl_sub_node( cntl ) != NULL ) { // We only need to take action if the thrinfo_t sub-node is NULL; if it // is non-NULL, then it has already been created and we'll use it as-is. if ( bli_thrinfo_sub_node( thread ) == NULL ) { // Create a new node (or, if needed, multiple nodes) along the // main sub-node branch of the tree and return the pointer to the // (highest) child. thrinfo_t* thread_child = bli_thrinfo_sup_rgrow ( rntm, bszid_par, &bszid_par[1], thread ); // Attach the child thrinfo_t node for the primary branch to its // parent structure. bli_thrinfo_set_sub_node( thread_child, thread ); } } } // ----------------------------------------------------------------------------- thrinfo_t* bli_thrinfo_sup_rgrow ( rntm_t* rntm, bszid_t* bszid_par, bszid_t* bszid_cur, thrinfo_t* thread_par ) { thrinfo_t* thread_cur; // We must handle two cases: those where the next node in the // control tree is a partitioning node, and those where it is // a non-partitioning (ie: packing) node. if ( *bszid_cur != BLIS_NO_PART ) { // Create the child thrinfo_t node corresponding to cntl_cur, // with cntl_par being the parent. thread_cur = bli_thrinfo_sup_create_for_cntl ( rntm, bszid_par, bszid_cur, thread_par ); } else // if ( *bszid_cur == BLIS_NO_PART ) { // Recursively grow the thread structure and return the top-most // thrinfo_t node of that segment. thrinfo_t* thread_seg = bli_thrinfo_sup_rgrow ( rntm, bszid_par, &bszid_cur[1], thread_par ); // Create a thrinfo_t node corresponding to cntl_cur. Since the // corresponding cntl node, cntl_cur, is a non-partitioning node // (bszid = BLIS_NO_PART), this means it's a packing node. Packing // thrinfo_t nodes are formed differently than those corresponding to // partitioning nodes; specifically, their work_id's are set equal to // the their comm_id's. Also, notice that the free_comm field is set // to FALSE since cntl_cur is a non-partitioning node. The reason: // the communicator used here will be freed when thread_seg, or one // of its descendents, is freed. thread_cur = bli_thrinfo_create ( rntm, // rntm bli_thrinfo_ocomm( thread_seg ), // ocomm bli_thread_ocomm_id( thread_seg ), // ocomm_id bli_rntm_calc_num_threads_in( bszid_cur, rntm ), // n_way bli_thread_ocomm_id( thread_seg ), // work_id FALSE, // free_comm BLIS_NO_PART, // bszid thread_seg // sub_node ); } return thread_cur; } #define BLIS_NUM_STATIC_COMMS 80 thrinfo_t* bli_thrinfo_sup_create_for_cntl ( rntm_t* rntm, bszid_t* bszid_par, bszid_t* bszid_chl, thrinfo_t* thread_par ) { // If we are running with a single thread, all of the code can be reduced // and simplified to this. if ( bli_rntm_calc_num_threads( rntm ) == 1 ) { thrinfo_t* thread_chl = bli_thrinfo_create ( rntm, // rntm &BLIS_SINGLE_COMM, // ocomm 0, // ocomm_id 1, // n_way 0, // work_id FALSE, // free_comm BLIS_NO_PART, // bszid NULL // sub_node ); return thread_chl; } // The remainder of this function handles the cases involving the use of // multiple BLIS threads. if ( bli_rntm_pack_a( rntm ) == FALSE && bli_rntm_pack_b( rntm ) == FALSE ) { // If we are packing neither A nor B, there are no broadcasts or barriers // needed to synchronize threads (since all threads can work completely // independently). In this special case situation, the thrinfo_t can be // created with much simpler logic. const dim_t parent_comm_id = bli_thread_ocomm_id( thread_par ); // Compute: // - the number of threads inside the new child comm, // - the current thread's id within the new communicator, // - the current thread's work id, given the ways of parallelism // to be obtained within the next loop. const dim_t child_nt_in = bli_rntm_calc_num_threads_in( bszid_chl, rntm ); const dim_t child_n_way = bli_rntm_ways_for( *bszid_chl, rntm ); const dim_t child_comm_id = parent_comm_id % child_nt_in; const dim_t child_work_id = child_comm_id / ( child_nt_in / child_n_way ); // All threads create a new thrinfo_t node using the communicator // that was created by their chief, as identified by parent_work_id. thrinfo_t* thread_chl = bli_thrinfo_create ( rntm, // rntm NULL, // ocomm child_comm_id, // ocomm_id child_n_way, // n_way child_work_id, // work_id TRUE, // free_comm *bszid_chl, // bszid NULL // sub_node ); return thread_chl; } else { // If we are packing at least one of A or B, then we use the general // approach that employs broadcasts and barriers. thrcomm_t* static_comms[ BLIS_NUM_STATIC_COMMS ]; thrcomm_t** new_comms = NULL; const dim_t parent_nt_in = bli_thread_num_threads( thread_par ); const dim_t parent_n_way = bli_thread_n_way( thread_par ); const dim_t parent_comm_id = bli_thread_ocomm_id( thread_par ); const dim_t parent_work_id = bli_thread_work_id( thread_par ); // Sanity check: make sure the number of threads in the parent's // communicator is divisible by the number of new sub-groups. if ( parent_nt_in % parent_n_way != 0 ) { printf( "Assertion failed: parent_nt_in parent_n_way != 0\n" ); bli_abort(); } // Compute: // - the number of threads inside the new child comm, // - the current thread's id within the new communicator, // - the current thread's work id, given the ways of parallelism // to be obtained within the next loop. const dim_t child_nt_in = bli_rntm_calc_num_threads_in( bszid_chl, rntm ); const dim_t child_n_way = bli_rntm_ways_for( *bszid_chl, rntm ); const dim_t child_comm_id = parent_comm_id % child_nt_in; const dim_t child_work_id = child_comm_id / ( child_nt_in / child_n_way ); //printf( "thread %d: child_n_way = %d child_nt_in = %d parent_n_way = %d (bszid = %d->%d)\n", (int)child_comm_id, (int)child_nt_in, (int)child_n_way, (int)parent_n_way, (int)bli_cntl_bszid( cntl_par ), (int)bszid_chl ); // The parent's chief thread creates a temporary array of thrcomm_t // pointers. if ( bli_thread_am_ochief( thread_par ) ) { err_t r_val; if ( parent_n_way > BLIS_NUM_STATIC_COMMS ) new_comms = bli_malloc_intl( parent_n_way * sizeof( thrcomm_t* ), &r_val ); else new_comms = static_comms; } // Broadcast the temporary array to all threads in the parent's // communicator. new_comms = bli_thread_broadcast( thread_par, new_comms ); // Chiefs in the child communicator allocate the communicator // object and store it in the array element corresponding to the // parent's work id. if ( child_comm_id == 0 ) new_comms[ parent_work_id ] = bli_thrcomm_create( rntm, child_nt_in ); bli_thread_barrier( thread_par ); // All threads create a new thrinfo_t node using the communicator // that was created by their chief, as identified by parent_work_id. thrinfo_t* thread_chl = bli_thrinfo_create ( rntm, // rntm new_comms[ parent_work_id ], // ocomm child_comm_id, // ocomm_id child_n_way, // n_way child_work_id, // work_id TRUE, // free_comm *bszid_chl, // bszid NULL // sub_node ); bli_thread_barrier( thread_par ); // The parent's chief thread frees the temporary array of thrcomm_t // pointers. if ( bli_thread_am_ochief( thread_par ) ) { if ( parent_n_way > BLIS_NUM_STATIC_COMMS ) bli_free_intl( new_comms ); } return thread_chl; } } blis-0.9.0/frame/thread/bli_thrinfo_sup.h000066400000000000000000000043741422157504600203670ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_THRINFO_SUP_H #define BLIS_THRINFO_SUP_H // // Prototypes for level-3 thrinfo sup functions. // void bli_thrinfo_sup_grow ( rntm_t* rntm, bszid_t* bszid_par, thrinfo_t* thread ); thrinfo_t* bli_thrinfo_sup_rgrow ( rntm_t* rntm, bszid_t* bszid_par, bszid_t* bszid_cur, thrinfo_t* thread_par ); thrinfo_t* bli_thrinfo_sup_create_for_cntl ( rntm_t* rntm, bszid_t* bszid_par, bszid_t* bszid_chl, thrinfo_t* thread_par ); #endif blis-0.9.0/frame/thread/old/000077500000000000000000000000001422157504600155765ustar00rootroot00000000000000blis-0.9.0/frame/thread/old/bli_mutex.h000066400000000000000000000040061422157504600177370ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2016, Hewlett Packard Enterprise Development LP Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_MUTEX_H #define BLIS_MUTEX_H // Include definitions (mostly mtx_t) specific to the method of // multithreading. #include "bli_mutex_single.h" #include "bli_mutex_openmp.h" #include "bli_mutex_pthreads.h" // Thread mutex prototypes. #endif blis-0.9.0/frame/thread/old/bli_mutex_openmp.h000066400000000000000000000045651422157504600213270ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2016, Hewlett Packard Enterprise Development LP Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_MUTEX_OPENMP_H #define BLIS_MUTEX_OPENMP_H // Define mutex_t for situations when OpenMP multithreading is enabled. #ifdef BLIS_ENABLE_OPENMP #include // Define mtx_t. typedef struct mtx_s { omp_lock_t mutex; } mtx_t; // Define functions to operate on OpenMP-based mtx_t. static void bli_mutex_init( mtx_t* m ) { omp_init_lock( &(m->mutex) ); } static void bli_mutex_finalize( mtx_t* m ) { omp_destroy_lock( &(m->mutex) ); } static void bli_mutex_lock( mtx_t* m ) { omp_set_lock( &(m->mutex) ); } static void bli_mutex_unlock( mtx_t* m ) { omp_unset_lock( &(m->mutex) ); } #endif #endif blis-0.9.0/frame/thread/old/bli_mutex_pthreads.h000066400000000000000000000046451422157504600216420ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2016, Hewlett Packard Enterprise Development LP Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_MUTEX_PTHREADS_H #define BLIS_MUTEX_PTHREADS_H // Define mutex_t for situations when POSIX multithreading is enabled. #ifdef BLIS_ENABLE_PTHREADS #include // Define mtx_t. typedef struct mtx_s { pthread_mutex_t mutex; } mtx_t; // Define macros to operate on pthread-based mtx_t. static void bli_mutex_init( mtx_t* m ) { pthread_mutex_init( &(m->mutex), NULL ); \ } static void bli_mutex_finalize( mtx_t* m ) { pthread_mutex_destroy( &(m->mutex) ); \ } static void bli_mutex_lock( mtx_t* m ) { pthread_mutex_lock( &(m->mutex) ); \ } static void bli_mutex_unlock( mtx_t* m ) { pthread_mutex_unlock( &(m->mutex) ); \ } #endif #endif blis-0.9.0/frame/thread/old/bli_mutex_single.h000066400000000000000000000043201422157504600212770ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2016, Hewlett Packard Enterprise Development LP Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_MUTEX_SINGLE_H #define BLIS_MUTEX_SINGLE_H // Define mtx_t for situations when multithreading is disabled. #ifndef BLIS_ENABLE_MULTITHREADING // Define mtx_t. typedef struct mtx_s { } mtx_t; // Define macros to operate on pthread-based mtx_t. static void bli_mutex_init( mtx_t* m ) { } static void bli_mutex_finalize( mtx_t* m ) { } static void bli_mutex_lock( mtx_t* m ) { } static void bli_mutex_unlock( mtx_t* m ) { } #endif #endif blis-0.9.0/frame/util/000077500000000000000000000000001422157504600145265ustar00rootroot00000000000000blis-0.9.0/frame/util/bli_util.h000066400000000000000000000044471422157504600165130ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "bli_util_check.h" // Prototype object APIs (expert and non-expert). #include "bli_oapi_ex.h" #include "bli_util_oapi.h" #include "bli_xapi_undef.h" #include "bli_oapi_ba.h" #include "bli_util_oapi.h" #include "bli_xapi_undef.h" // Prototype typed APIs (expert and non-expert). #include "bli_tapi_ex.h" #include "bli_util_tapi.h" #include "bli_util_ft.h" #include "bli_xapi_undef.h" #include "bli_tapi_ba.h" #include "bli_util_tapi.h" #include "bli_util_ft.h" #include "bli_xapi_undef.h" // Generate function pointer arrays for tapi functions (expert only). #include "bli_util_fpa.h" // Prototype level-1m implementations. #include "bli_util_unb_var1.h" blis-0.9.0/frame/util/bli_util_check.c000066400000000000000000000215541422157504600176410ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // Define object-based check functions. // #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC(opname,_check) \ ( \ obj_t* x, \ obj_t* asum \ ) \ { \ bli_utilv_xa_check( x, asum ); \ } GENFRONT( asumv ) #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC(opname,_check) \ ( \ obj_t* x \ ) \ { \ bli_utilm_mkhst_check( x ); \ } GENFRONT( mkherm ) GENFRONT( mksymm ) GENFRONT( mktrim ) #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC(opname,_check) \ ( \ obj_t* x, \ obj_t* norm \ ) \ { \ bli_utilv_norm_check( x, norm ); \ } GENFRONT( norm1v ) GENFRONT( normfv ) GENFRONT( normiv ) #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC(opname,_check) \ ( \ obj_t* x, \ obj_t* norm \ ) \ { \ bli_utilm_norm_check( x, norm ); \ } GENFRONT( norm1m ) GENFRONT( normfm ) GENFRONT( normim ) #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC(opname,_check) \ ( \ obj_t* x \ ) \ { \ bli_utilm_rand_check( x ); \ } GENFRONT( randv ) GENFRONT( randnv ) GENFRONT( randm ) GENFRONT( randnm ) #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC(opname,_check) \ ( \ obj_t* x, \ obj_t* scale, \ obj_t* sumsq \ ) \ { \ bli_utilv_sumsqv_check( x, scale, sumsq ); \ } GENFRONT( sumsqv ) // ----------------------------------------------------------------------------- #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC(opname,_check) \ ( \ obj_t* chi, \ obj_t* psi, \ bool* is_eq \ ) \ { \ bli_l0_xxbsc_check( chi, psi, is_eq ); \ } GENFRONT( eqsc ) #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC(opname,_check) \ ( \ obj_t* x, \ obj_t* y, \ bool* is_eq \ ) \ { \ bli_l1v_xy_check( x, y ); \ } GENFRONT( eqv ) #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC(opname,_check) \ ( \ obj_t* x, \ obj_t* y, \ bool* is_eq \ ) \ { \ bli_l1m_xy_check( x, y ); \ } GENFRONT( eqm ) #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC(opname,_check) \ ( \ FILE* file, \ char* s1, \ obj_t* x, \ char* format, \ char* s2 \ ) \ { \ bli_utilm_fprint_check( file, s1, x, format, s2 ); \ } GENFRONT( fprintv ) GENFRONT( fprintm ) // ----------------------------------------------------------------------------- void bli_utilv_xa_check ( obj_t* x, obj_t* asum ) { err_t e_val; // Check object datatypes. e_val = bli_check_floating_object( x ); bli_check_error_code( e_val ); e_val = bli_check_nonconstant_object( asum ); bli_check_error_code( e_val ); // Check object dimensions. e_val = bli_check_vector_object( x ); bli_check_error_code( e_val ); e_val = bli_check_scalar_object( asum ); bli_check_error_code( e_val ); // Check object buffers (for non-NULLness). e_val = bli_check_object_buffer( x ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( asum ); bli_check_error_code( e_val ); } void bli_utilm_mkhst_check ( obj_t* a ) { err_t e_val; // Check object datatypes. e_val = bli_check_floating_object( a ); bli_check_error_code( e_val ); e_val = bli_check_nonconstant_object( a ); bli_check_error_code( e_val ); // Check object dimensions. e_val = bli_check_matrix_object( a ); bli_check_error_code( e_val ); e_val = bli_check_square_object( a ); bli_check_error_code( e_val ); e_val = bli_check_object_diag_offset_equals( a, 0 ); bli_check_error_code( e_val ); // Check matrix storage. e_val = bli_check_upper_or_lower_object( a ); bli_check_error_code( e_val ); // Check object buffers (for non-NULLness). e_val = bli_check_object_buffer( a ); bli_check_error_code( e_val ); } void bli_utilv_norm_check ( obj_t* x, obj_t* norm ) { err_t e_val; // Check object datatypes. e_val = bli_check_floating_object( x ); bli_check_error_code( e_val ); e_val = bli_check_noninteger_object( norm ); bli_check_error_code( e_val ); e_val = bli_check_nonconstant_object( norm ); bli_check_error_code( e_val ); e_val = bli_check_object_real_proj_of( x, norm ); bli_check_error_code( e_val ); // Check object dimensions. e_val = bli_check_vector_object( x ); bli_check_error_code( e_val ); e_val = bli_check_scalar_object( norm ); bli_check_error_code( e_val ); // Check object buffers (for non-NULLness). e_val = bli_check_object_buffer( x ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( norm ); bli_check_error_code( e_val ); } void bli_utilm_norm_check ( obj_t* x, obj_t* norm ) { err_t e_val; // Check object datatypes. e_val = bli_check_floating_object( x ); bli_check_error_code( e_val ); e_val = bli_check_noninteger_object( norm ); bli_check_error_code( e_val ); e_val = bli_check_nonconstant_object( norm ); bli_check_error_code( e_val ); e_val = bli_check_object_real_proj_of( x, norm ); bli_check_error_code( e_val ); // Check object dimensions. e_val = bli_check_matrix_object( x ); bli_check_error_code( e_val ); e_val = bli_check_scalar_object( norm ); bli_check_error_code( e_val ); // Check object buffers (for non-NULLness). e_val = bli_check_object_buffer( x ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( norm ); bli_check_error_code( e_val ); } void bli_utilm_fprint_check ( FILE* file, char* s1, obj_t* x, char* format, char* s2 ) { err_t e_val; // Check argument pointers. e_val = bli_check_null_pointer( file ); bli_check_error_code( e_val ); e_val = bli_check_null_pointer( s1 ); bli_check_error_code( e_val ); e_val = bli_check_null_pointer( s2 ); bli_check_error_code( e_val ); // Check object buffers (for non-NULLness). e_val = bli_check_object_buffer( x ); bli_check_error_code( e_val ); } void bli_utilm_rand_check ( obj_t* x ) { err_t e_val; // Check object datatypes. e_val = bli_check_noninteger_object( x ); bli_check_error_code( e_val ); e_val = bli_check_nonconstant_object( x ); bli_check_error_code( e_val ); // Check object buffers (for non-NULLness). e_val = bli_check_object_buffer( x ); bli_check_error_code( e_val ); } void bli_utilv_sumsqv_check ( obj_t* x, obj_t* scale, obj_t* sumsq ) { err_t e_val; // Check object datatypes. e_val = bli_check_floating_object( x ); bli_check_error_code( e_val ); e_val = bli_check_nonconstant_object( scale ); bli_check_error_code( e_val ); e_val = bli_check_nonconstant_object( sumsq ); bli_check_error_code( e_val ); // Check object dimensions. e_val = bli_check_vector_object( x ); bli_check_error_code( e_val ); e_val = bli_check_scalar_object( scale ); bli_check_error_code( e_val ); e_val = bli_check_scalar_object( sumsq ); bli_check_error_code( e_val ); // Check object buffers (for non-NULLness). e_val = bli_check_object_buffer( x ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( scale ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( sumsq ); bli_check_error_code( e_val ); } blis-0.9.0/frame/util/bli_util_check.h000066400000000000000000000102501422157504600176350ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype object-based check functions. // #undef GENPROT #define GENPROT( opname ) \ \ void PASTEMAC(opname,_check) \ ( \ obj_t* x, \ obj_t* asum \ ); GENPROT( asumv ) #undef GENPROT #define GENPROT( opname ) \ \ void PASTEMAC(opname,_check) \ ( \ obj_t* x \ ); GENPROT( mkherm ) GENPROT( mksymm ) GENPROT( mktrim ) #undef GENPROT #define GENPROT( opname ) \ \ void PASTEMAC(opname,_check) \ ( \ obj_t* x, \ obj_t* norm \ ); GENPROT( norm1v ) GENPROT( normfv ) GENPROT( normiv ) #undef GENPROT #define GENPROT( opname ) \ \ void PASTEMAC(opname,_check) \ ( \ obj_t* x, \ obj_t* norm \ ); GENPROT( norm1m ) GENPROT( normfm ) GENPROT( normim ) #undef GENPROT #define GENPROT( opname ) \ \ void PASTEMAC(opname,_check) \ ( \ obj_t* x \ ); GENPROT( randv ) GENPROT( randnv ) GENPROT( randm ) GENPROT( randnm ) #undef GENPROT #define GENPROT( opname ) \ \ void PASTEMAC(opname,_check) \ ( \ obj_t* x, \ obj_t* scale, \ obj_t* sumsq \ ); GENPROT( sumsqv ) // ----------------------------------------------------------------------------- #undef GENTPROT #define GENTPROT( opname ) \ \ void PASTEMAC(opname,_check) \ ( \ obj_t* chi, \ obj_t* psi, \ bool* is_eq \ ); GENTPROT( eqsc ) #undef GENPROT #define GENPROT( opname ) \ \ void PASTEMAC(opname,_check) \ ( \ obj_t* x, \ obj_t* y, \ bool* is_eq \ ); GENPROT( eqv ) GENPROT( eqm ) #undef GENPROT #define GENPROT( opname ) \ \ void PASTEMAC(opname,_check) \ ( \ FILE* file, \ char* s1, \ obj_t* x, \ char* format, \ char* s2 \ ); GENPROT( fprintv ) GENPROT( fprintm ) // ----------------------------------------------------------------------------- void bli_utilv_xi_check ( obj_t* x, obj_t* index ); void bli_utilv_xa_check ( obj_t* x, obj_t* asum ); void bli_utilm_mkhst_check ( obj_t* a ); void bli_utilv_norm_check ( obj_t* x, obj_t* norm ); void bli_utilm_norm_check ( obj_t* x, obj_t* norm ); void bli_utilm_fprint_check ( FILE* file, char* s1, obj_t* x, char* format, char* s2 ); void bli_utilm_rand_check ( obj_t* x ); void bli_utilv_sumsqv_check ( obj_t* x, obj_t* scale, obj_t* sumsq ); blis-0.9.0/frame/util/bli_util_fpa.c000066400000000000000000000054711422157504600173320ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // Define function pointer query interfaces. // #undef GENFRONT #define GENFRONT( opname ) \ \ GENARRAY_FPA( PASTECH2(opname,BLIS_TAPI_EX_SUF,_vft), \ PASTECH(opname,BLIS_TAPI_EX_SUF) ); \ \ PASTECH2(opname,BLIS_TAPI_EX_SUF,_vft) \ PASTEMAC2(opname,BLIS_TAPI_EX_SUF,_qfp)( num_t dt ) \ { \ return PASTECH2(opname,BLIS_TAPI_EX_SUF,_fpa)[ dt ]; \ } GENFRONT( asumv ) GENFRONT( mkherm ) GENFRONT( mksymm ) GENFRONT( mktrim ) GENFRONT( norm1v ) GENFRONT( normfv ) GENFRONT( normiv ) GENFRONT( norm1m ) GENFRONT( normfm ) GENFRONT( normim ) GENFRONT( randv ) GENFRONT( randnv ) GENFRONT( randm ) GENFRONT( randnm ) GENFRONT( sumsqv ) // ----------------------------------------------------------------------------- // Operations with only basic interfaces. #undef GENFRONT #define GENFRONT( opname ) \ \ /* GENARRAY_FPA( void_fp, opname ); \ */ \ \ GENARRAY_FPA( PASTECH(opname,_vft), \ PASTECH0(opname) ); \ \ PASTECH(opname,_vft) \ PASTEMAC(opname,_qfp)( num_t dt ) \ { \ return PASTECH(opname,_fpa)[ dt ]; \ } GENFRONT( eqsc ) GENFRONT( eqv ) GENFRONT( eqm ) GENFRONT( fprintv ) GENFRONT( fprintm ) //GENFRONT( printv ) //GENFRONT( printm ) blis-0.9.0/frame/util/bli_util_fpa.h000066400000000000000000000046171422157504600173400ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype function pointer query interface. // #undef GENPROT #define GENPROT( opname ) \ \ PASTECH2(opname,BLIS_TAPI_EX_SUF,_vft) \ PASTEMAC2(opname,BLIS_TAPI_EX_SUF,_qfp)( num_t dt ); GENPROT( asumv ) GENPROT( mkherm ) GENPROT( mksymm ) GENPROT( mktrim ) GENPROT( norm1v ) GENPROT( normfv ) GENPROT( normiv ) GENPROT( norm1m ) GENPROT( normfm ) GENPROT( normim ) GENPROT( randv ) GENPROT( randnv ) GENPROT( randm ) GENPROT( randnm ) GENPROT( sumsqv ) // ----------------------------------------------------------------------------- #undef GENPROT #define GENPROT( opname ) \ \ PASTECH(opname,_vft) \ PASTEMAC(opname,_qfp)( num_t dt ); GENPROT( eqsc ) GENPROT( eqv ) GENPROT( eqm ) GENPROT( fprintv ) GENPROT( fprintm ) //GENPROT( printv ) //GENPROT( printm ) blis-0.9.0/frame/util/bli_util_ft.h000066400000000000000000000135251422157504600172010ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // -- Utility function types --------------------------------------------------- // // asumv #undef GENTDEFR #define GENTDEFR( ctype, ctype_r, ch, chr, opname, tsuf ) \ \ typedef void (*PASTECH3(ch,opname,EX_SUF,tsuf)) \ ( \ dim_t n, \ ctype* x, inc_t incx, \ ctype_r* asum \ BLIS_TAPI_EX_PARAMS \ ); INSERT_GENTDEFR( asumv ) // mkherm, mksymm, mktrim #undef GENTDEF #define GENTDEF( ctype, ch, opname, tsuf ) \ \ typedef void (*PASTECH3(ch,opname,EX_SUF,tsuf)) \ ( \ uplo_t uploa, \ dim_t m, \ ctype* a, inc_t rs_a, inc_t cs_a \ BLIS_TAPI_EX_PARAMS \ ); INSERT_GENTDEF( mkherm ) INSERT_GENTDEF( mksymm ) INSERT_GENTDEF( mktrim ) // norm1v, normfv, normiv #undef GENTDEFR #define GENTDEFR( ctype, ctype_r, ch, chr, opname, tsuf ) \ \ typedef void (*PASTECH3(ch,opname,EX_SUF,tsuf)) \ ( \ dim_t n, \ ctype* x, inc_t incx, \ ctype_r* norm \ BLIS_TAPI_EX_PARAMS \ ); INSERT_GENTDEFR( norm1v ) INSERT_GENTDEFR( normfv ) INSERT_GENTDEFR( normiv ) // norm1m, normfm, normim #undef GENTDEFR #define GENTDEFR( ctype, ctype_r, ch, chr, opname, tsuf ) \ \ typedef void (*PASTECH3(ch,opname,EX_SUF,tsuf)) \ ( \ doff_t diagoffx, \ diag_t diagx, \ uplo_t uplox, \ dim_t m, \ dim_t n, \ ctype* x, inc_t rs_x, inc_t cs_x, \ ctype_r* norm \ BLIS_TAPI_EX_PARAMS \ ); INSERT_GENTDEFR( norm1m ) INSERT_GENTDEFR( normfm ) INSERT_GENTDEFR( normim ) // fprintv #undef GENTDEF #define GENTDEF( ctype, ch, opname, tsuf ) \ \ typedef void (*PASTECH3(ch,opname,EX_SUF,tsuf)) \ ( \ FILE* file, \ char* s1, \ dim_t n, \ ctype* x, inc_t incx, \ char* format, \ char* s2 \ ); INSERT_GENTDEF( fprintv ) // fprintm #undef GENTDEF #define GENTDEF( ctype, ch, opname, tsuf ) \ \ typedef void (*PASTECH3(ch,opname,EX_SUF,tsuf)) \ ( \ FILE* file, \ char* s1, \ dim_t m, \ dim_t n, \ ctype* x, inc_t rs_x, inc_t cs_x, \ char* format, \ char* s2 \ ); INSERT_GENTDEF( fprintm ) // randv, randnv #undef GENTDEF #define GENTDEF( ctype, ch, opname, tsuf ) \ \ typedef void (*PASTECH3(ch,opname,EX_SUF,tsuf)) \ ( \ dim_t n, \ ctype* x, inc_t incx \ BLIS_TAPI_EX_PARAMS \ ); INSERT_GENTDEF( randv ) INSERT_GENTDEF( randnv ) // randm, randnm #undef GENTDEF #define GENTDEF( ctype, ch, opname, tsuf ) \ \ typedef void (*PASTECH3(ch,opname,EX_SUF,tsuf)) \ ( \ doff_t diagoffx, \ uplo_t uplox, \ dim_t m, \ dim_t n, \ ctype* x, inc_t rs_x, inc_t cs_x \ BLIS_TAPI_EX_PARAMS \ ); INSERT_GENTDEF( randm ) INSERT_GENTDEF( randnm ) // sumsqv #undef GENTDEFR #define GENTDEFR( ctype, ctype_r, ch, chr, opname, tsuf ) \ \ typedef void (*PASTECH3(ch,opname,EX_SUF,tsuf)) \ ( \ dim_t n, \ ctype* x, inc_t incx, \ ctype_r* scale, \ ctype_r* sumsq \ BLIS_TAPI_EX_PARAMS \ ); INSERT_GENTDEFR( sumsqv ) // ----------------------------------------------------------------------------- // Operations with only basic interfaces. #ifdef BLIS_TAPI_BASIC // eqsc #undef GENTDEF #define GENTDEF( ctype, ch, opname, tsuf ) \ \ typedef void (*PASTECH2(ch,opname,tsuf)) \ ( \ conj_t conjchi, \ ctype* chi, \ ctype* psi, \ bool* is_eq \ ); INSERT_GENTDEF( eqsc ) // eqv #undef GENTDEF #define GENTDEF( ctype, ch, opname, tsuf ) \ \ typedef void (*PASTECH2(ch,opname,tsuf)) \ ( \ conj_t conjx, \ dim_t n, \ ctype* x, inc_t incx, \ ctype* y, inc_t incy, \ bool* is_eq \ ); INSERT_GENTDEF( eqv ) // eqm #undef GENTDEF #define GENTDEF( ctype, ch, opname, tsuf ) \ \ typedef void (*PASTECH2(ch,opname,tsuf)) \ ( \ doff_t diagoffx, \ diag_t diagx, \ uplo_t uplox, \ trans_t transx, \ dim_t m, \ dim_t n, \ ctype* x, inc_t rs_x, inc_t cs_x, \ ctype* y, inc_t rs_y, inc_t cs_y, \ bool* is_eq \ ); INSERT_GENTDEF( eqm ) #endif // #ifdef BLIS_OAPI_BASIC blis-0.9.0/frame/util/bli_util_oapi.c000066400000000000000000000376661422157504600175270ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // Guard the function definitions so that they are only compiled when // #included from files that define the object API macros. #ifdef BLIS_ENABLE_OAPI // // Define object-based interfaces. // #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC(opname,EX_SUF) \ ( \ obj_t* x, \ obj_t* asum \ BLIS_OAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_OAPI_EX_DECLS \ \ num_t dt = bli_obj_dt( x ); \ \ dim_t n = bli_obj_vector_dim( x ); \ void* buf_x = bli_obj_buffer_at_off( x ); \ inc_t incx = bli_obj_vector_inc( x ); \ \ void* buf_asum = bli_obj_buffer_at_off( asum ); \ \ if ( bli_error_checking_is_enabled() ) \ PASTEMAC(opname,_check)( x, asum ); \ \ /* Query a type-specific function pointer, except one that uses void* for function arguments instead of typed pointers. */ \ PASTECH2(opname,BLIS_TAPI_EX_SUF,_vft) f = \ PASTEMAC2(opname,BLIS_TAPI_EX_SUF,_qfp)( dt ); \ \ f \ ( \ n, \ buf_x, incx, \ buf_asum, \ cntx, \ rntm \ ); \ } GENFRONT( asumv ) #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC(opname,EX_SUF) \ ( \ obj_t* a \ BLIS_OAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_OAPI_EX_DECLS \ \ num_t dt = bli_obj_dt( a ); \ \ uplo_t uploa = bli_obj_uplo( a ); \ dim_t m = bli_obj_length( a ); \ void* buf_a = bli_obj_buffer_at_off( a ); \ inc_t rs_a = bli_obj_row_stride( a ); \ inc_t cs_a = bli_obj_col_stride( a ); \ \ if ( bli_error_checking_is_enabled() ) \ PASTEMAC(opname,_check)( a ); \ \ /* Query a type-specific function pointer, except one that uses void* for function arguments instead of typed pointers. */ \ PASTECH2(opname,BLIS_TAPI_EX_SUF,_vft) f = \ PASTEMAC2(opname,BLIS_TAPI_EX_SUF,_qfp)( dt ); \ \ f \ ( \ uploa, \ m, \ buf_a, rs_a, cs_a, \ cntx, \ rntm \ ); \ } GENFRONT( mkherm ) GENFRONT( mksymm ) GENFRONT( mktrim ) #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC(opname,EX_SUF) \ ( \ obj_t* x, \ obj_t* norm \ BLIS_OAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_OAPI_EX_DECLS \ \ num_t dt = bli_obj_dt( x ); \ \ dim_t n = bli_obj_vector_dim( x ); \ void* buf_x = bli_obj_buffer_at_off( x ); \ inc_t incx = bli_obj_vector_inc( x ); \ void* buf_norm = bli_obj_buffer_at_off( norm ); \ \ if ( bli_error_checking_is_enabled() ) \ PASTEMAC(opname,_check)( x, norm ); \ \ /* Query a type-specific function pointer, except one that uses void* for function arguments instead of typed pointers. */ \ PASTECH2(opname,BLIS_TAPI_EX_SUF,_vft) f = \ PASTEMAC2(opname,BLIS_TAPI_EX_SUF,_qfp)( dt ); \ \ f \ ( \ n, \ buf_x, incx, \ buf_norm, \ cntx, \ rntm \ ); \ } GENFRONT( norm1v ) GENFRONT( normfv ) GENFRONT( normiv ) #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC(opname,EX_SUF) \ ( \ obj_t* x, \ obj_t* norm \ BLIS_OAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_OAPI_EX_DECLS \ \ num_t dt = bli_obj_dt( x ); \ \ doff_t diagoffx = bli_obj_diag_offset( x ); \ diag_t diagx = bli_obj_diag( x ); \ uplo_t uplox = bli_obj_uplo( x ); \ dim_t m = bli_obj_length( x ); \ dim_t n = bli_obj_width( x ); \ void* buf_x = bli_obj_buffer_at_off( x ); \ inc_t rs_x = bli_obj_row_stride( x ); \ inc_t cs_x = bli_obj_col_stride( x ); \ void* buf_norm = bli_obj_buffer_at_off( norm ); \ \ if ( bli_error_checking_is_enabled() ) \ PASTEMAC(opname,_check)( x, norm ); \ \ /* Query a type-specific function pointer, except one that uses void* for function arguments instead of typed pointers. */ \ PASTECH2(opname,BLIS_TAPI_EX_SUF,_vft) f = \ PASTEMAC2(opname,BLIS_TAPI_EX_SUF,_qfp)( dt ); \ \ f \ ( \ diagoffx, \ diagx, \ uplox, \ m, \ n, \ buf_x, rs_x, cs_x, \ buf_norm, \ cntx, \ rntm \ ); \ } GENFRONT( norm1m ) GENFRONT( normfm ) GENFRONT( normim ) #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC(opname,EX_SUF) \ ( \ obj_t* x \ BLIS_OAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_OAPI_EX_DECLS \ \ num_t dt = bli_obj_dt( x ); \ \ dim_t n = bli_obj_vector_dim( x ); \ void* buf_x = bli_obj_buffer_at_off( x ); \ inc_t incx = bli_obj_vector_inc( x ); \ \ if ( bli_error_checking_is_enabled() ) \ PASTEMAC(opname,_check)( x ); \ \ /* Query a type-specific function pointer, except one that uses void* for function arguments instead of typed pointers. */ \ PASTECH2(opname,BLIS_TAPI_EX_SUF,_vft) f = \ PASTEMAC2(opname,BLIS_TAPI_EX_SUF,_qfp)( dt ); \ \ f \ ( \ n, \ buf_x, incx, \ cntx, \ rntm \ ); \ } GENFRONT( randv ) GENFRONT( randnv ) #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC(opname,EX_SUF) \ ( \ obj_t* x \ BLIS_OAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_OAPI_EX_DECLS \ \ num_t dt = bli_obj_dt( x ); \ \ doff_t diagoffx = bli_obj_diag_offset( x ); \ uplo_t uplox = bli_obj_uplo( x ); \ dim_t m = bli_obj_length( x ); \ dim_t n = bli_obj_width( x ); \ void* buf_x = bli_obj_buffer_at_off( x ); \ inc_t rs_x = bli_obj_row_stride( x ); \ inc_t cs_x = bli_obj_col_stride( x ); \ \ if ( bli_error_checking_is_enabled() ) \ PASTEMAC(opname,_check)( x ); \ \ /* Query a type-specific function pointer, except one that uses void* for function arguments instead of typed pointers. */ \ PASTECH2(opname,BLIS_TAPI_EX_SUF,_vft) f = \ PASTEMAC2(opname,BLIS_TAPI_EX_SUF,_qfp)( dt ); \ \ f \ ( \ diagoffx, \ uplox, \ m, \ n, \ buf_x, rs_x, cs_x, \ cntx, \ rntm \ ); \ } GENFRONT( randm ) GENFRONT( randnm ) #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC(opname,EX_SUF) \ ( \ obj_t* x, \ obj_t* scale, \ obj_t* sumsq \ BLIS_OAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_OAPI_EX_DECLS \ \ num_t dt = bli_obj_dt( x ); \ \ dim_t n = bli_obj_vector_dim( x ); \ void* buf_x = bli_obj_buffer_at_off( x ); \ inc_t incx = bli_obj_vector_inc( x ); \ void* buf_scale = bli_obj_buffer_at_off( scale ); \ void* buf_sumsq = bli_obj_buffer_at_off( sumsq ); \ \ if ( bli_error_checking_is_enabled() ) \ PASTEMAC(opname,_check)( x, scale, sumsq ); \ \ /* Query a type-specific function pointer, except one that uses void* for function arguments instead of typed pointers. */ \ PASTECH2(opname,BLIS_TAPI_EX_SUF,_vft) f = \ PASTEMAC2(opname,BLIS_TAPI_EX_SUF,_qfp)( dt ); \ \ f \ ( \ n, \ buf_x, incx, \ buf_scale, \ buf_sumsq, \ cntx, \ rntm \ ); \ } GENFRONT( sumsqv ) // ----------------------------------------------------------------------------- // Operations with only basic interfaces. #ifdef BLIS_OAPI_BASIC #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC0(opname) \ ( \ obj_t* chi, \ obj_t* psi, \ bool* is_eq \ ) \ { \ bli_init_once(); \ \ num_t dt_chi = bli_obj_dt( chi ); \ num_t dt_psi = bli_obj_dt( psi ); \ num_t dt; \ \ if ( bli_error_checking_is_enabled() ) \ PASTEMAC(opname,_check)( chi, psi, is_eq ); \ \ /* Decide which datatype will be used to query the buffer from the constant object (if there is one). */ \ if ( bli_is_constant( dt_psi ) ) dt = dt_chi; \ else dt = dt_psi; \ \ /* If chi and psi are both constants, then we compare only the dcomplex fields. */ \ if ( bli_is_constant( dt ) ) dt = BLIS_DCOMPLEX; \ \ void* buf_chi = bli_obj_buffer_for_1x1( dt, chi ); \ void* buf_psi = bli_obj_buffer_for_1x1( dt, psi ); \ \ /* Integer objects are handled separately. */ \ if ( bli_is_int( dt ) ) \ { \ *is_eq = bli_ieqa( buf_chi, buf_psi ); \ return; \ } \ \ /* Query the conj status of each object and use the two to come up with a single "net" conj_t value. */ \ conj_t conjchi = bli_obj_conj_status( chi ); \ conj_t conjpsi = bli_obj_conj_status( psi ); \ conj_t conj = bli_apply_conj( conjchi, conjpsi ); \ \ /* Query a type-specific function pointer, except one that uses void* for function arguments instead of typed pointers. */ \ PASTECH(opname,_vft) f = \ PASTEMAC(opname,_qfp)( dt ); \ \ f \ ( \ conj, \ buf_chi, \ buf_psi, \ is_eq \ ); \ } GENFRONT( eqsc ) #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC0(opname) \ ( \ obj_t* x, \ obj_t* y, \ bool* is_eq \ ) \ { \ bli_init_once(); \ \ num_t dt = bli_obj_dt( x ); \ \ dim_t n = bli_obj_vector_dim( x ); \ void* buf_x = bli_obj_buffer_at_off( x ); \ inc_t inc_x = bli_obj_vector_inc( x ); \ void* buf_y = bli_obj_buffer_at_off( y ); \ inc_t inc_y = bli_obj_vector_inc( y ); \ \ if ( bli_error_checking_is_enabled() ) \ PASTEMAC(opname,_check)( x, y, is_eq ); \ \ /* Query the conj status of each object and use the two to come up with a single "net" conj_t value. */ \ conj_t conjx = bli_obj_conj_status( x ); \ conj_t conjy = bli_obj_conj_status( y ); \ conj_t conj = bli_apply_conj( conjx, conjy ); \ \ /* Query a type-specific function pointer, except one that uses void* for function arguments instead of typed pointers. */ \ PASTECH(opname,_vft) f = \ PASTEMAC(opname,_qfp)( dt ); \ \ f \ ( \ conj, \ n, \ buf_x, inc_x, \ buf_y, inc_y, \ is_eq \ ); \ } GENFRONT( eqv ) #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC0(opname) \ ( \ obj_t* x, \ obj_t* y, \ bool* is_eq \ ) \ { \ bli_init_once(); \ \ num_t dt = bli_obj_dt( x ); \ \ doff_t diagoffx = bli_obj_diag_offset( x ); \ diag_t diagx = bli_obj_diag( x ); \ uplo_t uplox = bli_obj_uplo( x ); \ dim_t m = bli_obj_length( y ); \ dim_t n = bli_obj_width( y ); \ void* buf_x = bli_obj_buffer_at_off( x ); \ inc_t rs_x = bli_obj_row_stride( x ); \ inc_t cs_x = bli_obj_col_stride( x ); \ void* buf_y = bli_obj_buffer_at_off( y ); \ inc_t rs_y = bli_obj_row_stride( y ); \ inc_t cs_y = bli_obj_col_stride( y ); \ \ if ( bli_error_checking_is_enabled() ) \ PASTEMAC(opname,_check)( x, y, is_eq ); \ \ /* Query the combined trans and conj status of each object and use the two to come up with a single "net" trans_t value. */ \ trans_t transx = bli_obj_conjtrans_status( x ); \ trans_t transy = bli_obj_conjtrans_status( y ); \ trans_t trans = bli_apply_trans( transy, transx ); \ \ /* Query a type-specific function pointer, except one that uses void* for function arguments instead of typed pointers. */ \ PASTECH(opname,_vft) f = \ PASTEMAC(opname,_qfp)( dt ); \ \ f \ ( \ diagoffx, \ diagx, \ uplox, \ trans, \ m, \ n, \ buf_x, rs_x, cs_x, \ buf_y, rs_y, cs_y, \ is_eq \ ); \ } GENFRONT( eqm ) #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC0(opname) \ ( \ FILE* file, \ char* s1, \ obj_t* x, \ char* format, \ char* s2 \ ) \ { \ bli_init_once(); \ \ num_t dt = bli_obj_dt( x ); \ \ dim_t n = bli_obj_vector_dim( x ); \ void* buf_x = bli_obj_buffer_at_off( x ); \ inc_t incx = bli_obj_vector_inc( x ); \ \ if ( bli_error_checking_is_enabled() ) \ PASTEMAC(opname,_check)( file, s1, x, format, s2 ); \ \ /* Handle constants up front. */ \ if ( dt == BLIS_CONSTANT ) \ { \ bli_check_error_code( BLIS_NOT_YET_IMPLEMENTED ); \ } \ \ /* Query a type-specific function pointer, except one that uses void* for function arguments instead of typed pointers. */ \ PASTECH(opname,_vft) f = \ PASTEMAC(opname,_qfp)( dt ); \ \ f \ ( \ file, \ s1, \ n, \ buf_x, incx, \ format, \ s2 \ ); \ } GENFRONT( fprintv ) #undef GENFRONT #define GENFRONT( opname ) \ \ void PASTEMAC0(opname) \ ( \ FILE* file, \ char* s1, \ obj_t* x, \ char* format, \ char* s2 \ ) \ { \ bli_init_once(); \ \ num_t dt = bli_obj_dt( x ); \ \ dim_t m = bli_obj_length( x ); \ dim_t n = bli_obj_width( x ); \ void* buf_x = bli_obj_buffer_at_off( x ); \ inc_t rs_x = bli_obj_row_stride( x ); \ inc_t cs_x = bli_obj_col_stride( x ); \ \ if ( bli_error_checking_is_enabled() ) \ PASTEMAC(opname,_check)( file, s1, x, format, s2 ); \ \ /* Handle constants up front. */ \ if ( dt == BLIS_CONSTANT ) \ { \ float* sp = bli_obj_buffer_for_const( BLIS_FLOAT, x ); \ double* dp = bli_obj_buffer_for_const( BLIS_DOUBLE, x ); \ scomplex* cp = bli_obj_buffer_for_const( BLIS_SCOMPLEX, x ); \ dcomplex* zp = bli_obj_buffer_for_const( BLIS_DCOMPLEX, x ); \ gint_t* ip = bli_obj_buffer_for_const( BLIS_INT, x ); \ \ fprintf( file, "%s\n", s1 ); \ fprintf( file, " float: %9.2e\n", bli_sreal( *sp ) ); \ fprintf( file, " double: %9.2e\n", bli_dreal( *dp ) ); \ fprintf( file, " scomplex: %9.2e + %9.2e\n", bli_creal( *cp ), \ bli_cimag( *cp ) ); \ fprintf( file, " dcomplex: %9.2e + %9.2e\n", bli_zreal( *zp ), \ bli_zimag( *zp ) ); \ fprintf( file, " int: %ld\n", ( long )(*ip) ); \ fprintf( file, "\n" ); \ return; \ } \ \ /* Query a type-specific function pointer, except one that uses void* for function arguments instead of typed pointers. */ \ PASTECH(opname,_vft) f = \ PASTEMAC(opname,_qfp)( dt ); \ \ f \ ( \ file, \ s1, \ m, \ n, \ buf_x, rs_x, cs_x, \ format, \ s2 \ ); \ } GENFRONT( fprintm ) #undef GENFRONT #define GENFRONT( opname, varname ) \ \ void PASTEMAC0(opname) \ ( \ char* s1, \ obj_t* x, \ char* format, \ char* s2 \ ) \ { \ bli_init_once(); \ \ /* Invoke the typed function. */ \ PASTEMAC0(varname) \ ( \ stdout, \ s1, \ x, \ format, \ s2 \ ); \ } GENFRONT( printv, fprintv ) GENFRONT( printm, fprintm ) #endif // #ifdef BLIS_OAPI_BASIC #endif blis-0.9.0/frame/util/bli_util_oapi.h000066400000000000000000000106521422157504600175160ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype object-based interfaces. // #undef GENPROT #define GENPROT( opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC(opname,EX_SUF) \ ( \ obj_t* x, \ obj_t* asum \ BLIS_OAPI_EX_PARAMS \ ); GENPROT( asumv ) #undef GENPROT #define GENPROT( opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC(opname,EX_SUF) \ ( \ obj_t* a \ BLIS_OAPI_EX_PARAMS \ ); GENPROT( mkherm ) GENPROT( mksymm ) GENPROT( mktrim ) #undef GENPROT #define GENPROT( opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC(opname,EX_SUF) \ ( \ obj_t* x, \ obj_t* norm \ BLIS_OAPI_EX_PARAMS \ ); GENPROT( norm1v ) GENPROT( normfv ) GENPROT( normiv ) #undef GENPROT #define GENPROT( opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC(opname,EX_SUF) \ ( \ obj_t* x, \ obj_t* norm \ BLIS_OAPI_EX_PARAMS \ ); GENPROT( norm1m ) GENPROT( normfm ) GENPROT( normim ) #undef GENPROT #define GENPROT( opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC(opname,EX_SUF) \ ( \ obj_t* x \ BLIS_OAPI_EX_PARAMS \ ); GENPROT( randv ) GENPROT( randnv ) #undef GENPROT #define GENPROT( opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC(opname,EX_SUF) \ ( \ obj_t* x \ BLIS_OAPI_EX_PARAMS \ ); GENPROT( randm ) GENPROT( randnm ) #undef GENPROT #define GENPROT( opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC(opname,EX_SUF) \ ( \ obj_t* x, \ obj_t* scale, \ obj_t* sumsq \ BLIS_OAPI_EX_PARAMS \ ); GENPROT( sumsqv ) // ----------------------------------------------------------------------------- // Operations with basic interfaces only. #ifdef BLIS_OAPI_BASIC /* #undef GENPROT #define GENPROT( opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC0(opname) \ ( \ obj_t* chi, \ obj_t* psi, \ bool* is_eq \ ); GENPROT( eqsc ) #undef GENPROT #define GENPROT( opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC0(opname) \ ( \ obj_t* x, \ obj_t* y, \ bool* is_eq \ ); GENPROT( eqv ) */ #undef GENPROT #define GENPROT( opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC0(opname) \ ( \ obj_t* x, \ obj_t* y, \ bool* is_eq \ ); GENPROT( eqsc ) GENPROT( eqv ) GENPROT( eqm ) #undef GENPROT #define GENPROT( opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC0(opname) \ ( \ FILE* file, \ char* s1, \ obj_t* x, \ char* format, \ char* s2 \ ); GENPROT( fprintv ) GENPROT( fprintm ) #undef GENPROT #define GENPROT( opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC0(opname) \ ( \ char* s1, \ obj_t* x, \ char* format, \ char* s2 \ ); GENPROT( printv ) GENPROT( printm ) #endif // #ifdef BLIS_OAPI_BASIC blis-0.9.0/frame/util/bli_util_oapi_ba.c000066400000000000000000000036711422157504600201560ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // Include cpp macros that instantiate the API definition templates as // omitting expert parameters. #include "bli_oapi_ba.h" // Define the macro protecting the object API definitions. #define BLIS_ENABLE_OAPI // Include the object API definitions here. #include "bli_util_oapi.c" blis-0.9.0/frame/util/bli_util_oapi_ex.c000066400000000000000000000036671422157504600202150ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // Include cpp macros that instantiate the API definition templates as // having expert parameters. #include "bli_oapi_ex.h" // Define the macro protecting the object API definitions. #define BLIS_ENABLE_OAPI // Include the object API definitions here. #include "bli_util_oapi.c" blis-0.9.0/frame/util/bli_util_tapi.c000066400000000000000000000275011422157504600175170ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // Guard the function definitions so that they are only compiled when // #included from files that define the typed API macros. #ifdef BLIS_ENABLE_TAPI // // Define BLAS-like interfaces with typed operands. // #undef GENTFUNCR #define GENTFUNCR( ctype, ctype_r, ch, chr, opname ) \ \ void PASTEMAC2(ch,opname,EX_SUF) \ ( \ dim_t n, \ ctype* x, inc_t incx, \ ctype_r* asum \ BLIS_TAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_TAPI_EX_DECLS \ \ /* If the vector length is zero, set the absolute sum return value to zero and return early. */ \ if ( bli_zero_dim1( n ) ) \ { \ PASTEMAC(chr,set0s)( *asum ); \ return; \ } \ \ /* Obtain a valid context from the gks if necessary. */ \ /*if ( cntx == NULL ) cntx = bli_gks_query_cntx();*/ \ \ /* Invoke the helper variant, which loops over the appropriate kernel to implement the current operation. */ \ PASTEMAC2(ch,opname,_unb_var1) \ ( \ n, \ x, incx, \ asum, \ cntx, \ rntm \ ); \ } INSERT_GENTFUNCR_BASIC0( asumv ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname ) \ \ void PASTEMAC2(ch,opname,EX_SUF) \ ( \ uplo_t uploa, \ dim_t m, \ ctype* a, inc_t rs_a, inc_t cs_a \ BLIS_TAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_TAPI_EX_DECLS \ \ /* If either dimension is zero, return early. */ \ if ( bli_zero_dim2( m, m ) ) return; \ \ /* Obtain a valid context from the gks if necessary. */ \ if ( cntx == NULL ) cntx = bli_gks_query_cntx(); \ \ /* Invoke the helper variant, which loops over the appropriate kernel to implement the current operation. */ \ PASTEMAC2(ch,opname,_unb_var1) \ ( \ uploa, \ m, \ a, rs_a, cs_a, \ cntx, \ rntm \ ); \ } INSERT_GENTFUNC_BASIC0( mkherm ) INSERT_GENTFUNC_BASIC0( mksymm ) INSERT_GENTFUNC_BASIC0( mktrim ) #undef GENTFUNCR #define GENTFUNCR( ctype, ctype_r, ch, chr, opname ) \ \ void PASTEMAC2(ch,opname,EX_SUF) \ ( \ dim_t n, \ ctype* x, inc_t incx, \ ctype_r* norm \ BLIS_TAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_TAPI_EX_DECLS \ \ /* If the vector length is zero, set the norm to zero and return early. */ \ if ( bli_zero_dim1( n ) ) \ { \ PASTEMAC(chr,set0s)( *norm ); \ return; \ } \ \ /* Obtain a valid context from the gks if necessary. */ \ if ( cntx == NULL ) cntx = bli_gks_query_cntx(); \ \ /* Invoke the helper variant, which loops over the appropriate kernel to implement the current operation. */ \ PASTEMAC2(ch,opname,_unb_var1) \ ( \ n, \ x, incx, \ norm, \ cntx, \ rntm \ ); \ } INSERT_GENTFUNCR_BASIC0( norm1v ) INSERT_GENTFUNCR_BASIC0( normfv ) INSERT_GENTFUNCR_BASIC0( normiv ) #undef GENTFUNCR #define GENTFUNCR( ctype, ctype_r, ch, chr, opname ) \ \ void PASTEMAC2(ch,opname,EX_SUF) \ ( \ doff_t diagoffx, \ diag_t diagx, \ uplo_t uplox, \ dim_t m, \ dim_t n, \ ctype* x, inc_t rs_x, inc_t cs_x, \ ctype_r* norm \ BLIS_TAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_TAPI_EX_DECLS \ \ /* If either dimension is zero, set the norm to zero and return early. */ \ if ( bli_zero_dim2( m, n ) ) \ { \ PASTEMAC(chr,set0s)( *norm ); \ return; \ } \ \ /* Obtain a valid context from the gks if necessary. */ \ if ( cntx == NULL ) cntx = bli_gks_query_cntx(); \ \ /* Invoke the helper variant, which loops over the appropriate kernel to implement the current operation. */ \ PASTEMAC2(ch,opname,_unb_var1) \ ( \ diagoffx, \ diagx, \ uplox, \ m, \ n, \ x, rs_x, cs_x, \ norm, \ cntx, \ rntm \ ); \ } INSERT_GENTFUNCR_BASIC0( norm1m ) INSERT_GENTFUNCR_BASIC0( normfm ) INSERT_GENTFUNCR_BASIC0( normim ) #undef GENTFUNCR #define GENTFUNCR( ctype, ctype_r, ch, chr, opname ) \ \ void PASTEMAC2(ch,opname,EX_SUF) \ ( \ dim_t n, \ ctype* x, inc_t incx \ BLIS_TAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_TAPI_EX_DECLS \ \ /* If the vector length is zero, return early. */ \ if ( bli_zero_dim1( n ) ) return; \ \ /* Obtain a valid context from the gks if necessary. */ \ /*if ( cntx == NULL ) cntx = bli_gks_query_cntx();*/ \ \ ctype_r norm; \ \ /* Set the norm to zero. */ \ PASTEMAC(chr,set0s)( norm ); \ \ /* Iterate at least once, but continue iterating until the norm is not zero. */ \ while ( PASTEMAC(chr,eq0)( norm ) ) \ { \ /* Invoke the helper variant, which loops over the appropriate kernel to implement the current operation. */ \ PASTEMAC2(ch,opname,_unb_var1) \ ( \ n, \ x, incx, \ cntx, \ rntm \ ); \ \ /* Check the 1-norm of the randomzied vector. In the unlikely event that the 1-norm is zero, it means that *all* elements are zero, in which case we want to re-randomize until the 1-norm is not zero. */ \ PASTEMAC2(ch,norm1v,BLIS_TAPI_EX_SUF) \ ( \ n, \ x, incx, \ &norm, \ cntx, \ rntm \ ); \ } \ } INSERT_GENTFUNCR_BASIC0( randv ) INSERT_GENTFUNCR_BASIC0( randnv ) #undef GENTFUNCR #define GENTFUNCR( ctype, ctype_r, ch, chr, opname ) \ \ void PASTEMAC2(ch,opname,EX_SUF) \ ( \ doff_t diagoffx, \ uplo_t uplox, \ dim_t m, \ dim_t n, \ ctype* x, inc_t rs_x, inc_t cs_x \ BLIS_TAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_TAPI_EX_DECLS \ \ /* If either dimension is zero, return early. */ \ if ( bli_zero_dim2( m, n ) ) return; \ \ /* Obtain a valid context from the gks if necessary. */ \ /*if ( cntx == NULL ) cntx = bli_gks_query_cntx();*/ \ \ ctype_r norm; \ \ /* Set the norm to zero. */ \ PASTEMAC(chr,set0s)( norm ); \ \ /* Iterate at least once, but continue iterating until the norm is not zero. */ \ while ( PASTEMAC(chr,eq0)( norm ) ) \ { \ /* Invoke the helper variant, which loops over the appropriate kernel to implement the current operation. */ \ PASTEMAC2(ch,opname,_unb_var1) \ ( \ diagoffx, \ uplox, \ m, \ n, \ x, rs_x, cs_x, \ cntx, \ rntm \ ); \ \ /* Check the 1-norm of the randomzied matrix. In the unlikely event that the 1-norm is zero, it means that *all* elements are zero, in which case we want to re-randomize until the 1-norm is not zero. */ \ PASTEMAC2(ch,norm1m,BLIS_TAPI_EX_SUF) \ ( \ diagoffx, \ BLIS_NONUNIT_DIAG, \ uplox, \ m, \ n, \ x, rs_x, cs_x, \ &norm, \ cntx, \ rntm \ ); \ } \ } INSERT_GENTFUNCR_BASIC0( randm ) INSERT_GENTFUNCR_BASIC0( randnm ) #undef GENTFUNCR #define GENTFUNCR( ctype, ctype_r, ch, chr, opname ) \ \ void PASTEMAC2(ch,opname,EX_SUF) \ ( \ dim_t n, \ ctype* x, inc_t incx, \ ctype_r* scale, \ ctype_r* sumsq \ BLIS_TAPI_EX_PARAMS \ ) \ { \ bli_init_once(); \ \ BLIS_TAPI_EX_DECLS \ \ /* If x is zero length, return with scale and sumsq unchanged. */ \ if ( bli_zero_dim1( n ) ) return; \ \ /* Obtain a valid context from the gks if necessary. */ \ /*if ( cntx == NULL ) cntx = bli_gks_query_cntx();*/ \ \ /* Invoke the helper variant, which loops over the appropriate kernel to implement the current operation. */ \ PASTEMAC2(ch,opname,_unb_var1) \ ( \ n, \ x, incx, \ scale, \ sumsq, \ cntx, \ rntm \ ); \ } INSERT_GENTFUNCR_BASIC0( sumsqv ) // ----------------------------------------------------------------------------- // Operations with only basic interfaces. #ifdef BLIS_TAPI_BASIC #undef GENTFUNC #define GENTFUNC( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ conj_t conjchi, \ ctype* chi, \ ctype* psi, \ bool* is_eq \ ) \ { \ bli_init_once(); \ \ ctype chi_conj; \ \ PASTEMAC(ch,copycjs)( conjchi, *chi, chi_conj ); \ \ *is_eq = PASTEMAC(ch,eq)( chi_conj, *psi ); \ } INSERT_GENTFUNC_BASIC0( eqsc ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ conj_t conjx, \ dim_t n, \ ctype* x, inc_t incx, \ ctype* y, inc_t incy, \ bool* is_eq \ ) \ { \ bli_init_once(); \ \ /* If x is zero length, return with a result of TRUE. */ \ if ( bli_zero_dim1( n ) ) { *is_eq = TRUE; return; } \ \ /* Obtain a valid context from the gks if necessary. */ \ /*if ( cntx == NULL ) cntx = bli_gks_query_cntx();*/ \ \ *is_eq = PASTEMAC2(ch,opname,_unb_var1) \ ( \ conjx, \ n, \ x, incx, \ y, incy \ ); \ } INSERT_GENTFUNC_BASIC0( eqv ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ doff_t diagoffx, \ diag_t diagx, \ uplo_t uplox, \ trans_t transx, \ dim_t m, \ dim_t n, \ ctype* x, inc_t rs_x, inc_t cs_x, \ ctype* y, inc_t rs_y, inc_t cs_y, \ bool* is_eq \ ) \ { \ bli_init_once(); \ \ /* If x has a zero dimension, return with a result of TRUE. See the _unb_var() variant for why we return TRUE in this scenario. */ \ if ( bli_zero_dim2( m, n ) ) { *is_eq = TRUE; return; } \ \ /* Obtain a valid context from the gks if necessary. */ \ /*if ( cntx == NULL ) cntx = bli_gks_query_cntx();*/ \ \ /* Invoke the helper variant. */ \ *is_eq = PASTEMAC2(ch,opname,_unb_var1) \ ( \ diagoffx, \ diagx, \ uplox, \ transx, \ m, \ n, \ x, rs_x, cs_x, \ y, rs_y, cs_y \ ); \ } INSERT_GENTFUNC_BASIC0( eqm ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, varname ) \ \ void PASTEMAC(ch,opname) \ ( \ char* s1, \ dim_t n, \ void* x, inc_t incx, \ char* format, \ char* s2 \ ) \ { \ bli_init_once(); \ \ PASTEMAC(ch,varname) \ ( \ stdout, \ s1, \ n, \ x, incx, \ format, \ s2 \ ); \ } INSERT_GENTFUNC_BASIC_I( printv, fprintv ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, varname ) \ \ void PASTEMAC(ch,opname) \ ( \ char* s1, \ dim_t m, \ dim_t n, \ void* x, inc_t rs_x, inc_t cs_x, \ char* format, \ char* s2 \ ) \ { \ bli_init_once(); \ \ PASTEMAC(ch,varname) \ ( \ stdout, \ s1, \ m, \ n, \ x, rs_x, cs_x, \ format, \ s2 \ ); \ } INSERT_GENTFUNC_BASIC_I( printm, fprintm ) #endif // #ifdef BLIS_TAPI_BASIC #endif blis-0.9.0/frame/util/bli_util_tapi.h000066400000000000000000000133361422157504600175250ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype BLAS-like interfaces with typed operands. // #undef GENTPROTR #define GENTPROTR( ctype, ctype_r, ch, chr, opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC2(ch,opname,EX_SUF) \ ( \ dim_t n, \ ctype* x, inc_t incx, \ ctype_r* asum \ BLIS_TAPI_EX_PARAMS \ ); INSERT_GENTPROTR_BASIC0( asumv ) #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC2(ch,opname,EX_SUF) \ ( \ uplo_t uploa, \ dim_t m, \ ctype* a, inc_t rs_a, inc_t cs_a \ BLIS_TAPI_EX_PARAMS \ ); INSERT_GENTPROT_BASIC0( mkherm ) INSERT_GENTPROT_BASIC0( mksymm ) INSERT_GENTPROT_BASIC0( mktrim ) #undef GENTPROTR #define GENTPROTR( ctype, ctype_r, ch, chr, opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC2(ch,opname,EX_SUF) \ ( \ dim_t n, \ ctype* x, inc_t incx, \ ctype_r* norm \ BLIS_TAPI_EX_PARAMS \ ); INSERT_GENTPROTR_BASIC0( norm1v ) INSERT_GENTPROTR_BASIC0( normfv ) INSERT_GENTPROTR_BASIC0( normiv ) #undef GENTPROTR #define GENTPROTR( ctype, ctype_r, ch, chr, opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC2(ch,opname,EX_SUF) \ ( \ doff_t diagoffx, \ diag_t diagx, \ uplo_t uplox, \ dim_t m, \ dim_t n, \ ctype* x, inc_t rs_x, inc_t cs_x, \ ctype_r* norm \ BLIS_TAPI_EX_PARAMS \ ); INSERT_GENTPROTR_BASIC0( norm1m ) INSERT_GENTPROTR_BASIC0( normfm ) INSERT_GENTPROTR_BASIC0( normim ) #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC2(ch,opname,EX_SUF) \ ( \ dim_t n, \ ctype* x, inc_t incx \ BLIS_TAPI_EX_PARAMS \ ); INSERT_GENTPROT_BASIC0( randv ) INSERT_GENTPROT_BASIC0( randnv ) #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC2(ch,opname,EX_SUF) \ ( \ doff_t diagoffx, \ uplo_t uplox, \ dim_t m, \ dim_t n, \ ctype* x, inc_t rs_x, inc_t cs_x \ BLIS_TAPI_EX_PARAMS \ ); INSERT_GENTPROT_BASIC0( randm ) INSERT_GENTPROT_BASIC0( randnm ) #undef GENTPROTR #define GENTPROTR( ctype, ctype_r, ch, chr, opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC2(ch,opname,EX_SUF) \ ( \ dim_t n, \ ctype* x, inc_t incx, \ ctype_r* scale, \ ctype_r* sumsq \ BLIS_TAPI_EX_PARAMS \ ); INSERT_GENTPROTR_BASIC0( sumsqv ) // ----------------------------------------------------------------------------- // Operations with basic interfaces only. #ifdef BLIS_TAPI_BASIC #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC(ch,opname) \ ( \ conj_t conjchi, \ ctype* chi, \ ctype* psi, \ bool* is_eq \ ); INSERT_GENTPROT_BASIC0( eqsc ) #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC(ch,opname) \ ( \ conj_t conjx, \ dim_t n, \ ctype* x, inc_t incx, \ ctype* y, inc_t incy, \ bool* is_eq \ ); INSERT_GENTPROT_BASIC0( eqv ) #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC(ch,opname) \ ( \ doff_t diagoffx, \ diag_t diagx, \ uplo_t uplox, \ trans_t transx, \ dim_t m, \ dim_t n, \ ctype* x, inc_t rs_x, inc_t cs_x, \ ctype* y, inc_t rs_y, inc_t cs_y, \ bool* is_eq \ ); INSERT_GENTPROT_BASIC0( eqm ) #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC(ch,opname) \ ( \ char* s1, \ dim_t n, \ void* x, inc_t incx, \ char* format, \ char* s2 \ ); INSERT_GENTPROT_BASIC0_I( printv ) #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC(ch,opname) \ ( \ char* s1, \ dim_t m, \ dim_t n, \ void* x, inc_t rs_x, inc_t cs_x, \ char* format, \ char* s2 \ ); INSERT_GENTPROT_BASIC0_I( printm ) #endif // #ifdef BLIS_TAPI_BASIC blis-0.9.0/frame/util/bli_util_tapi_ba.c000066400000000000000000000036671422157504600201700ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // Include cpp macros that instantiate the API definition templates as // omitting expert parameters. #include "bli_tapi_ba.h" // Define the macro protecting the typed API definitions. #define BLIS_ENABLE_TAPI // Include the typed API definitions here. #include "bli_util_tapi.c" blis-0.9.0/frame/util/bli_util_tapi_ex.c000066400000000000000000000036651422157504600202200ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // Include cpp macros that instantiate the API definition templates as // having expert parameters. #include "bli_tapi_ex.h" // Define the macro protecting the typed API definitions. #define BLIS_ENABLE_TAPI // Include the typed API definitions here. #include "bli_util_tapi.c" blis-0.9.0/frame/util/bli_util_unb_var1.c000066400000000000000000001010061422157504600202700ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include // // Define BLAS-like interfaces with typed operands. // #undef GENTFUNCR #define GENTFUNCR( ctype, ctype_r, ch, chr, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ dim_t n, \ ctype* x, inc_t incx, \ ctype_r* asum, \ cntx_t* cntx, \ rntm_t* rntm \ ) \ { \ ctype* chi1; \ ctype_r chi1_r; \ ctype_r chi1_i; \ ctype_r absum; \ dim_t i; \ \ /* Initialize the absolute sum accumulator to zero. */ \ PASTEMAC(chr,set0s)( absum ); \ \ for ( i = 0; i < n; ++i ) \ { \ chi1 = x + (i )*incx; \ \ /* Get the real and imaginary components of chi1. */ \ PASTEMAC2(ch,chr,gets)( *chi1, chi1_r, chi1_i ); \ \ /* Replace chi1_r and chi1_i with their absolute values. */ \ chi1_r = bli_fabs( chi1_r ); \ chi1_i = bli_fabs( chi1_i ); \ \ /* Accumulate the real and imaginary components into absum. */ \ PASTEMAC(chr,adds)( chi1_r, absum ); \ PASTEMAC(chr,adds)( chi1_i, absum ); \ } \ \ /* Store the final value of absum to the output variable. */ \ PASTEMAC(chr,copys)( absum, *asum ); \ } INSERT_GENTFUNCR_BASIC0( asumv_unb_var1 ) #undef GENTFUNCR #define GENTFUNCR( ctype, ctype_r, ch, chr, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ uplo_t uploa, \ dim_t m, \ ctype* a, inc_t rs_a, inc_t cs_a, \ cntx_t* cntx, \ rntm_t* rntm \ ) \ { \ ctype_r* zeror = PASTEMAC(chr,0); \ doff_t diagoffa; \ \ /* If the dimension is zero, return early. */ \ if ( bli_zero_dim1( m ) ) return; \ \ /* In order to avoid the main diagonal, we must nudge the diagonal either up or down by one, depending on which triangle is currently stored. */ \ if ( bli_is_upper( uploa ) ) diagoffa = 1; \ else /*if ( bli_is_lower( uploa ) )*/ diagoffa = -1; \ \ /* We will be reflecting the stored region over the diagonal into the unstored region, so a transposition is necessary. Furthermore, since we are creating a Hermitian matrix, we must also conjugate. */ \ PASTEMAC2(ch,copym,BLIS_TAPI_EX_SUF) \ ( \ diagoffa, \ BLIS_NONUNIT_DIAG, \ uploa, \ BLIS_CONJ_TRANSPOSE, \ m, \ m, \ a, rs_a, cs_a, \ a, rs_a, cs_a, \ cntx, \ rntm \ ); \ \ /* Set the imaginary parts of the diagonal elements to zero. */ \ PASTEMAC2(ch,setid,BLIS_TAPI_EX_SUF) \ ( \ 0, \ m, \ m, \ zeror, \ a, rs_a, cs_a, \ cntx, \ rntm \ ); \ } INSERT_GENTFUNCR_BASIC0( mkherm_unb_var1 ) #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ uplo_t uploa, \ dim_t m, \ ctype* a, inc_t rs_a, inc_t cs_a, \ cntx_t* cntx, \ rntm_t* rntm \ ) \ { \ doff_t diagoffa; \ \ /* If the dimension is zero, return early. */ \ if ( bli_zero_dim1( m ) ) return; \ \ /* In order to avoid the main diagonal, we must nudge the diagonal either up or down by one, depending on which triangle is currently stored. */ \ if ( bli_is_upper( uploa ) ) diagoffa = 1; \ else /*if ( bli_is_lower( uploa ) )*/ diagoffa = -1; \ \ /* We will be reflecting the stored region over the diagonal into the unstored region, so a transposition is necessary. */ \ PASTEMAC2(ch,copym,BLIS_TAPI_EX_SUF) \ ( \ diagoffa, \ BLIS_NONUNIT_DIAG, \ uploa, \ BLIS_TRANSPOSE, \ m, \ m, \ a, rs_a, cs_a, \ a, rs_a, cs_a, \ cntx, \ rntm \ ); \ } INSERT_GENTFUNC_BASIC0( mksymm_unb_var1 ) #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ uplo_t uploa, \ dim_t m, \ ctype* a, inc_t rs_a, inc_t cs_a, \ cntx_t* cntx, \ rntm_t* rntm \ ) \ { \ ctype* zero = PASTEMAC(ch,0); \ doff_t diagoffa; \ \ /* If the dimension is zero, return early. */ \ if ( bli_zero_dim1( m ) ) return; \ \ /* Toggle uplo so that it refers to the unstored triangle. */ \ bli_toggle_uplo( &uploa ); \ \ /* In order to avoid the main diagonal, we must nudge the diagonal either up or down by one, depending on which triangle is to be zeroed. */ \ if ( bli_is_upper( uploa ) ) diagoffa = 1; \ else /*if ( bli_is_lower( uploa ) )*/ diagoffa = -1; \ \ /* Set the unstored triangle to zero. */ \ PASTEMAC2(ch,setm,BLIS_TAPI_EX_SUF) \ ( \ BLIS_NO_CONJUGATE, \ diagoffa, \ BLIS_NONUNIT_DIAG, \ uploa, \ m, \ m, \ zero, \ a, rs_a, cs_a, \ cntx, \ rntm \ ); \ } INSERT_GENTFUNC_BASIC0( mktrim_unb_var1 ) #undef GENTFUNCR #define GENTFUNCR( ctype, ctype_r, ch, chr, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ dim_t n, \ ctype* x, inc_t incx, \ ctype_r* norm, \ cntx_t* cntx, \ rntm_t* rntm \ ) \ { \ ctype* chi1; \ ctype_r abs_chi1; \ ctype_r absum; \ dim_t i; \ \ /* Initialize the absolute sum accumulator to zero. */ \ PASTEMAC(chr,set0s)( absum ); \ \ for ( i = 0; i < n; ++i ) \ { \ chi1 = x + (i )*incx; \ \ /* Compute the absolute value (or complex magnitude) of chi1. */ \ PASTEMAC2(ch,chr,abval2s)( *chi1, abs_chi1 ); \ \ /* Accumulate the absolute value of chi1 into absum. */ \ PASTEMAC(chr,adds)( abs_chi1, absum ); \ } \ \ /* Store final value of absum to the output variable. */ \ PASTEMAC(chr,copys)( absum, *norm ); \ } INSERT_GENTFUNCR_BASIC0( norm1v_unb_var1 ) #undef GENTFUNCR #define GENTFUNCR( ctype, ctype_r, ch, chr, varname, kername ) \ \ void PASTEMAC(ch,varname) \ ( \ dim_t n, \ ctype* x, inc_t incx, \ ctype_r* norm, \ cntx_t* cntx, \ rntm_t* rntm \ ) \ { \ ctype_r* zero = PASTEMAC(chr,0); \ ctype_r* one = PASTEMAC(chr,1); \ ctype_r scale; \ ctype_r sumsq; \ ctype_r sqrt_sumsq; \ \ /* Initialize scale and sumsq to begin the summation. */ \ PASTEMAC(chr,copys)( *zero, scale ); \ PASTEMAC(chr,copys)( *one, sumsq ); \ \ /* Compute the sum of the squares of the vector. */ \ PASTEMAC(ch,kername) \ ( \ n, \ x, incx, \ &scale, \ &sumsq, \ cntx, \ rntm \ ); \ \ /* Compute: norm = scale * sqrt( sumsq ) */ \ PASTEMAC(chr,sqrt2s)( sumsq, sqrt_sumsq ); \ PASTEMAC(chr,scals)( scale, sqrt_sumsq ); \ \ /* Store the final value to the output variable. */ \ PASTEMAC(chr,copys)( sqrt_sumsq, *norm ); \ } //INSERT_GENTFUNCR_BASIC( normfv_unb_var1, sumsqv_unb_var1 ) GENTFUNCR( scomplex, float, c, s, normfv_unb_var1, sumsqv_unb_var1 ) GENTFUNCR( dcomplex, double, z, d, normfv_unb_var1, sumsqv_unb_var1 ) #undef GENTFUNCR // We've disabled the dotv-based implementation because that method of // computing the sum of the squares of x inherently does not check for // overflow. Instead, we use the fallback method based on sumsqv, which // takes care to not overflow unnecessarily (ie: takes care for the // sqrt( sum of the squares of x ) to not overflow if the sum of the // squares of x would normally overflow. See GitHub issue #332 for // discussion. #if 0 //defined(FE_OVERFLOW) && !defined(__APPLE__) #define GENTFUNCR( ctype, ctype_r, ch, chr, varname, kername ) \ \ void PASTEMAC(ch,varname) \ ( \ dim_t n, \ ctype* x, inc_t incx, \ ctype_r* norm, \ cntx_t* cntx, \ rntm_t* rntm \ ) \ { \ ctype_r* zero = PASTEMAC(chr,0); \ ctype_r* one = PASTEMAC(chr,1); \ ctype_r scale; \ ctype_r sumsq; \ ctype_r sqrt_sumsq; \ \ /* Initialize scale and sumsq to begin the summation. */ \ PASTEMAC(chr,copys)( *zero, scale ); \ PASTEMAC(chr,copys)( *one, sumsq ); \ \ /* An optimization: first try to use dotv to compute the sum of the squares of the vector. If no floating-point exceptions (specifically, overflow and invalid exceptions) were produced, then we accept the computed value and returne early. The cost of this optimization is the "sunk" cost of the initial dotv when sumsqv must be used instead. However, we expect that the vast majority of use cases will not produce exceptions, and therefore only one pass through the data, via dotv, will be required. */ \ if ( TRUE ) \ { \ int f_exp_raised;\ ctype sumsqc; \ \ feclearexcept( FE_ALL_EXCEPT );\ \ PASTEMAC2(ch,dotv,BLIS_TAPI_EX_SUF) \ ( \ BLIS_NO_CONJUGATE, \ BLIS_NO_CONJUGATE, \ n,\ x, incx, \ x, incx, \ &sumsqc, \ cntx, \ rntm \ ); \ \ PASTEMAC2(ch,chr,copys)( sumsqc, sumsq ); \ \ f_exp_raised = fetestexcept( FE_OVERFLOW | FE_INVALID );\ \ if ( !f_exp_raised ) \ { \ PASTEMAC(chr,sqrt2s)( sumsq, *norm ); \ return; \ } \ } \ \ /* Compute the sum of the squares of the vector. */ \ PASTEMAC(ch,kername) \ ( \ n, \ x, incx, \ &scale, \ &sumsq, \ cntx, \ rntm \ ); \ \ /* Compute: norm = scale * sqrt( sumsq ) */ \ PASTEMAC(chr,sqrt2s)( sumsq, sqrt_sumsq ); \ PASTEMAC(chr,scals)( scale, sqrt_sumsq ); \ \ /* Store the final value to the output variable. */ \ PASTEMAC(chr,copys)( sqrt_sumsq, *norm ); \ } #else #define GENTFUNCR( ctype, ctype_r, ch, chr, varname, kername ) \ \ void PASTEMAC(ch,varname) \ ( \ dim_t n, \ ctype* x, inc_t incx, \ ctype_r* norm, \ cntx_t* cntx, \ rntm_t* rntm \ ) \ { \ ctype_r* zero = PASTEMAC(chr,0); \ ctype_r* one = PASTEMAC(chr,1); \ ctype_r scale; \ ctype_r sumsq; \ ctype_r sqrt_sumsq; \ \ /* Initialize scale and sumsq to begin the summation. */ \ PASTEMAC(chr,copys)( *zero, scale ); \ PASTEMAC(chr,copys)( *one, sumsq ); \ \ /* Compute the sum of the squares of the vector. */ \ \ PASTEMAC(ch,kername) \ ( \ n, \ x, incx, \ &scale, \ &sumsq, \ cntx, \ rntm \ ); \ \ /* Compute: norm = scale * sqrt( sumsq ) */ \ PASTEMAC(chr,sqrt2s)( sumsq, sqrt_sumsq ); \ PASTEMAC(chr,scals)( scale, sqrt_sumsq ); \ \ /* Store the final value to the output variable. */ \ PASTEMAC(chr,copys)( sqrt_sumsq, *norm ); \ } #endif GENTFUNCR( float, float, s, s, normfv_unb_var1, sumsqv_unb_var1 ) GENTFUNCR( double, double, d, d, normfv_unb_var1, sumsqv_unb_var1 ) #undef GENTFUNCR #define GENTFUNCR( ctype, ctype_r, ch, chr, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ dim_t n, \ ctype* x, inc_t incx, \ ctype_r* norm, \ cntx_t* cntx, \ rntm_t* rntm \ ) \ { \ ctype* chi1; \ ctype_r abs_chi1; \ ctype_r abs_chi1_max; \ dim_t i; \ \ /* Initialize the maximum absolute value to zero. */ \ PASTEMAC(chr,set0s)( abs_chi1_max ); \ \ for ( i = 0; i < n; ++i ) \ { \ chi1 = x + (i )*incx; \ \ /* Compute the absolute value (or complex magnitude) of chi1. */ \ PASTEMAC2(ch,chr,abval2s)( *chi1, abs_chi1 ); \ \ /* If the absolute value of the current element exceeds that of the previous largest, save it and its index. If NaN is encountered, then treat it the same as if it were a valid value that was larger than any previously seen. This behavior mimics that of LAPACK's ?lange(). */ \ if ( abs_chi1_max < abs_chi1 || bli_isnan( abs_chi1 ) ) \ { \ PASTEMAC(chr,copys)( abs_chi1, abs_chi1_max ); \ } \ } \ \ /* Store the final value to the output variable. */ \ PASTEMAC(chr,copys)( abs_chi1_max, *norm ); \ } INSERT_GENTFUNCR_BASIC0( normiv_unb_var1 ) #undef GENTFUNCR #define GENTFUNCR( ctype, ctype_r, ch, chr, varname, kername ) \ \ void PASTEMAC(ch,varname) \ ( \ doff_t diagoffx, \ diag_t diagx, \ uplo_t uplox, \ dim_t m, \ dim_t n, \ ctype* x, inc_t rs_x, inc_t cs_x, \ ctype_r* norm, \ cntx_t* cntx, \ rntm_t* rntm \ ) \ { \ ctype* one = PASTEMAC(ch,1); \ ctype* x0; \ ctype* chi1; \ ctype* x2; \ ctype_r absum_max; \ ctype_r absum_j; \ ctype_r abval_chi1; \ uplo_t uplox_eff; \ dim_t n_iter; \ dim_t n_elem, n_elem_max; \ inc_t ldx, incx; \ dim_t j, i; \ dim_t ij0, n_shift; \ \ /* Initialize the maximum absolute column sum to zero. */ \ PASTEMAC(chr,set0s)( absum_max ); \ \ /* If either dimension is zero, return with absum_max equal to zero. */ \ if ( bli_zero_dim2( m, n ) ) \ { \ PASTEMAC(chr,copys)( absum_max, *norm ); \ return; \ } \ \ /* Set various loop parameters. */ \ bli_set_dims_incs_uplo_1m_noswap \ ( \ diagoffx, BLIS_NONUNIT_DIAG, \ uplox, m, n, rs_x, cs_x, \ &uplox_eff, &n_elem_max, &n_iter, &incx, &ldx, \ &ij0, &n_shift \ ); \ \ /* If the matrix is zeros, return with absum_max equal to zero. */ \ if ( bli_is_zeros( uplox_eff ) ) \ { \ PASTEMAC(chr,copys)( absum_max, *norm ); \ return; \ } \ \ \ /* Handle dense and upper/lower storage cases separately. */ \ if ( bli_is_dense( uplox_eff ) ) \ { \ for ( j = 0; j < n_iter; ++j ) \ { \ n_elem = n_elem_max; \ \ x0 = x + (j )*ldx + (0 )*incx; \ \ /* Compute the norm of the current column. */ \ PASTEMAC(ch,kername) \ ( \ n_elem, \ x0, incx, \ &absum_j, \ cntx, \ rntm \ ); \ \ /* If absum_j is greater than the previous maximum value, then save it. */ \ if ( absum_max < absum_j || bli_isnan( absum_j ) ) \ { \ PASTEMAC(chr,copys)( absum_j, absum_max ); \ } \ } \ } \ else \ { \ if ( bli_is_upper( uplox_eff ) ) \ { \ for ( j = 0; j < n_iter; ++j ) \ { \ n_elem = bli_min( n_shift + j + 1, n_elem_max ); \ \ x0 = x + (ij0+j )*ldx + (0 )*incx; \ chi1 = x + (ij0+j )*ldx + (n_elem-1)*incx; \ \ /* Compute the norm of the super-diagonal elements. */ \ PASTEMAC(ch,kername) \ ( \ n_elem - 1, \ x0, incx, \ &absum_j, \ cntx, \ rntm \ ); \ \ if ( bli_is_unit_diag( diagx ) ) chi1 = one; \ \ /* Handle the diagonal element separately in case it's unit. */ \ PASTEMAC2(ch,chr,abval2s)( *chi1, abval_chi1 ); \ PASTEMAC(chr,adds)( abval_chi1, absum_j ); \ \ /* If absum_j is greater than the previous maximum value, then save it. */ \ if ( absum_max < absum_j || bli_isnan( absum_j ) ) \ { \ PASTEMAC(chr,copys)( absum_j, absum_max ); \ } \ } \ } \ else if ( bli_is_lower( uplox_eff ) ) \ { \ for ( j = 0; j < n_iter; ++j ) \ { \ i = bli_max( 0, ( doff_t )j - ( doff_t )n_shift ); \ n_elem = n_elem_max - i; \ \ chi1 = x + (j )*ldx + (ij0+i )*incx; \ x2 = x + (j )*ldx + (ij0+i+1)*incx; \ \ /* Compute the norm of the sub-diagonal elements. */ \ PASTEMAC(ch,kername) \ ( \ n_elem - 1, \ x2, incx, \ &absum_j, \ cntx, \ rntm \ ); \ \ if ( bli_is_unit_diag( diagx ) ) chi1 = one; \ \ /* Handle the diagonal element separately in case it's unit. */ \ PASTEMAC2(ch,chr,abval2s)( *chi1, abval_chi1 ); \ PASTEMAC(chr,adds)( abval_chi1, absum_j ); \ \ /* If absum_j is greater than the previous maximum value, then save it. */ \ if ( absum_max < absum_j || bli_isnan( absum_j ) ) \ { \ PASTEMAC(chr,copys)( absum_j, absum_max ); \ } \ } \ } \ } \ \ /* Store final value of absum_max to the output variable. */ \ PASTEMAC(chr,copys)( absum_max, *norm ); \ } INSERT_GENTFUNCR_BASIC( norm1m_unb_var1, norm1v_unb_var1 ) #undef GENTFUNCR #define GENTFUNCR( ctype, ctype_r, ch, chr, varname, kername ) \ \ void PASTEMAC(ch,varname) \ ( \ doff_t diagoffx, \ diag_t diagx, \ uplo_t uplox, \ dim_t m, \ dim_t n, \ ctype* x, inc_t rs_x, inc_t cs_x, \ ctype_r* norm, \ cntx_t* cntx, \ rntm_t* rntm \ ) \ { \ ctype* one = PASTEMAC(ch,1); \ ctype_r* one_r = PASTEMAC(chr,1); \ ctype_r* zero_r = PASTEMAC(chr,0); \ ctype* x0; \ ctype* chi1; \ ctype* x2; \ ctype_r scale; \ ctype_r sumsq; \ ctype_r sqrt_sumsq; \ uplo_t uplox_eff; \ dim_t n_iter; \ dim_t n_elem, n_elem_max; \ inc_t ldx, incx; \ dim_t j, i; \ dim_t ij0, n_shift; \ \ /* Return a norm of zero if either dimension is zero. */ \ if ( bli_zero_dim2( m, n ) ) \ { \ PASTEMAC(chr,set0s)( *norm ); \ return; \ } \ \ /* Set various loop parameters. Here, we pretend that diagx is equal to BLIS_NONUNIT_DIAG because we handle the unit diagonal case manually. */ \ bli_set_dims_incs_uplo_1m \ ( \ diagoffx, BLIS_NONUNIT_DIAG, \ uplox, m, n, rs_x, cs_x, \ &uplox_eff, &n_elem_max, &n_iter, &incx, &ldx, \ &ij0, &n_shift \ ); \ \ /* Check the effective uplo; if it's zeros, then our norm is zero. */ \ if ( bli_is_zeros( uplox_eff ) ) \ { \ PASTEMAC(chr,set0s)( *norm ); \ return; \ } \ \ /* Initialize scale and sumsq to begin the summation. */ \ PASTEMAC(chr,copys)( *zero_r, scale ); \ PASTEMAC(chr,copys)( *one_r, sumsq ); \ \ /* Handle dense and upper/lower storage cases separately. */ \ if ( bli_is_dense( uplox_eff ) ) \ { \ for ( j = 0; j < n_iter; ++j ) \ { \ n_elem = n_elem_max; \ \ x0 = x + (j )*ldx + (0 )*incx; \ \ /* Compute the norm of the current column. */ \ PASTEMAC(ch,kername) \ ( \ n_elem, \ x0, incx, \ &scale, \ &sumsq, \ cntx, \ rntm \ ); \ } \ } \ else \ { \ if ( bli_is_upper( uplox_eff ) ) \ { \ for ( j = 0; j < n_iter; ++j ) \ { \ n_elem = bli_min( n_shift + j + 1, n_elem_max ); \ \ x0 = x + (ij0+j )*ldx + (0 )*incx; \ chi1 = x + (ij0+j )*ldx + (n_elem-1)*incx; \ \ /* Sum the squares of the super-diagonal elements. */ \ PASTEMAC(ch,kername) \ ( \ n_elem - 1, \ x0, incx, \ &scale, \ &sumsq, \ cntx, \ rntm \ ); \ \ if ( bli_is_unit_diag( diagx ) ) chi1 = one; \ \ /* Handle the diagonal element separately in case it's unit. */ \ PASTEMAC(ch,kername) \ ( \ 1, \ chi1, incx, \ &scale, \ &sumsq, \ cntx, \ rntm \ ); \ } \ } \ else if ( bli_is_lower( uplox_eff ) ) \ { \ for ( j = 0; j < n_iter; ++j ) \ { \ i = bli_max( 0, ( doff_t )j - ( doff_t )n_shift ); \ n_elem = n_elem_max - i; \ \ chi1 = x + (j )*ldx + (ij0+i )*incx; \ x2 = x + (j )*ldx + (ij0+i+1)*incx; \ \ /* Sum the squares of the sub-diagonal elements. */ \ PASTEMAC(ch,kername) \ ( \ n_elem - 1, \ x2, incx, \ &scale, \ &sumsq, \ cntx, \ rntm \ ); \ \ if ( bli_is_unit_diag( diagx ) ) chi1 = one; \ \ /* Handle the diagonal element separately in case it's unit. */ \ PASTEMAC(ch,kername) \ ( \ 1, \ chi1, incx, \ &scale, \ &sumsq, \ cntx, \ rntm \ ); \ } \ } \ } \ \ /* Compute: norm = scale * sqrt( sumsq ) */ \ PASTEMAC(chr,sqrt2s)( sumsq, sqrt_sumsq ); \ PASTEMAC(chr,scals)( scale, sqrt_sumsq ); \ \ /* Store the final value to the output variable. */ \ PASTEMAC(chr,copys)( sqrt_sumsq, *norm ); \ } INSERT_GENTFUNCR_BASIC( normfm_unb_var1, sumsqv_unb_var1 ) #undef GENTFUNCR #define GENTFUNCR( ctype, ctype_r, ch, chr, varname, kername ) \ \ void PASTEMAC(ch,varname) \ ( \ doff_t diagoffx, \ diag_t diagx, \ uplo_t uplox, \ dim_t m, \ dim_t n, \ ctype* x, inc_t rs_x, inc_t cs_x, \ ctype_r* norm, \ cntx_t* cntx, \ rntm_t* rntm \ ) \ { \ /* Induce a transposition so that rows become columns. */ \ bli_swap_dims( &m, &n ); \ bli_swap_incs( &rs_x, &cs_x ); \ bli_toggle_uplo( &uplox ); \ bli_negate_diag_offset( &diagoffx ); \ \ /* Now we can simply compute the 1-norm of this transposed matrix, which will be equivalent to the infinity-norm of the original matrix. */ \ PASTEMAC(ch,kername) \ ( \ diagoffx, \ diagx, \ uplox, \ m, \ n, \ x, rs_x, cs_x, \ norm, \ cntx, \ rntm \ ); \ } INSERT_GENTFUNCR_BASIC( normim_unb_var1, norm1m_unb_var1 ) #undef GENTFUNC #define GENTFUNC( ctype, ch, varname, randmac ) \ \ void PASTEMAC(ch,varname) \ ( \ dim_t n, \ ctype* x, inc_t incx, \ cntx_t* cntx, \ rntm_t* rntm \ ) \ { \ ctype* chi1; \ dim_t i; \ \ chi1 = x; \ \ for ( i = 0; i < n; ++i ) \ { \ PASTEMAC(ch,randmac)( *chi1 ); \ \ chi1 += incx; \ } \ } INSERT_GENTFUNC_BASIC( randv_unb_var1, rands ) INSERT_GENTFUNC_BASIC( randnv_unb_var1, randnp2s ) #undef GENTFUNC #define GENTFUNC( ctype, ch, varname, kername ) \ \ void PASTEMAC(ch,varname) \ ( \ doff_t diagoffx, \ uplo_t uplox, \ dim_t m, \ dim_t n, \ ctype* x, inc_t rs_x, inc_t cs_x, \ cntx_t* cntx, \ rntm_t* rntm \ ) \ { \ ctype* one = PASTEMAC(ch,1); \ ctype* x0; \ ctype* x1; \ ctype* x2; \ ctype* chi1; \ ctype beta; \ ctype omega; \ double max_m_n; \ uplo_t uplox_eff; \ dim_t n_iter; \ dim_t n_elem, n_elem_max; \ inc_t ldx, incx; \ dim_t j, i; \ dim_t ij0, n_shift; \ \ /* Set various loop parameters. Here, we pretend that diagx is equal to BLIS_NONUNIT_DIAG because we handle the unit diagonal case manually. */ \ bli_set_dims_incs_uplo_1m \ ( \ diagoffx, BLIS_NONUNIT_DIAG, \ uplox, m, n, rs_x, cs_x, \ &uplox_eff, &n_elem_max, &n_iter, &incx, &ldx, \ &ij0, &n_shift \ ); \ \ if ( bli_is_zeros( uplox_eff ) ) return; \ \ /* Handle dense and upper/lower storage cases separately. */ \ if ( bli_is_dense( uplox_eff ) ) \ { \ for ( j = 0; j < n_iter; ++j ) \ { \ n_elem = n_elem_max; \ \ x1 = x + (j )*ldx + (0 )*incx; \ \ /*PASTEMAC2(ch,kername,BLIS_TAPI_EX_SUF)*/ \ PASTEMAC(ch,kername) \ ( \ n_elem, \ x1, incx, \ cntx, \ rntm \ ); \ } \ } \ else \ { \ max_m_n = bli_max( m, n ); \ \ PASTEMAC2(d,ch,sets)( max_m_n, 0.0, omega ); \ PASTEMAC(ch,copys)( *one, beta ); \ PASTEMAC(ch,invscals)( omega, beta ); \ \ if ( bli_is_upper( uplox_eff ) ) \ { \ for ( j = 0; j < n_iter; ++j ) \ { \ n_elem = bli_min( n_shift + j + 1, n_elem_max ); \ \ x1 = x + (ij0+j )*ldx + (0 )*incx; \ x0 = x1; \ chi1 = x1 + (n_elem-1)*incx; \ \ /*PASTEMAC2(ch,kername,BLIS_TAPI_EX_SUF)*/ \ PASTEMAC(ch,kername) \ ( \ n_elem, \ x1, incx, \ cntx, \ rntm \ ); \ \ ( void )x0; \ ( void )chi1; \ /* We want positive diagonal elements between 1 and 2. */ \ /* PASTEMAC(ch,abval2s)( *chi1, *chi1 ); \ PASTEMAC(ch,adds)( *one, *chi1 ); \ */ \ \ /* Scale the super-diagonal elements by 1/max(m,n). */ \ /* PASTEMAC(ch,scalv) \ ( \ BLIS_NO_CONJUGATE, \ n_elem - 1, \ &beta, \ x0, incx, \ cntx \ ); \ */ \ } \ } \ else if ( bli_is_lower( uplox_eff ) ) \ { \ for ( j = 0; j < n_iter; ++j ) \ { \ i = bli_max( 0, ( doff_t )j - ( doff_t )n_shift ); \ n_elem = n_elem_max - i; \ \ x1 = x + (j )*ldx + (ij0+i )*incx; \ x2 = x1 + incx; \ chi1 = x1; \ \ /*PASTEMAC2(ch,kername,BLIS_TAPI_EX_SUF)*/ \ PASTEMAC(ch,kername) \ ( \ n_elem, \ x1, incx, \ cntx, \ rntm \ ); \ \ ( void )x2; \ ( void )chi1; \ /* We want positive diagonal elements between 1 and 2. */ \ /* PASTEMAC(ch,abval2s)( *chi1, *chi1 ); \ PASTEMAC(ch,adds)( *one, *chi1 ); \ */ \ \ /* Scale the sub-diagonal elements by 1/max(m,n). */ \ /* PASTEMAC(ch,scalv) \ ( \ BLIS_NO_CONJUGATE, \ n_elem - 1, \ &beta, \ x2, incx, \ cntx \ ); \ */ \ } \ } \ } \ } INSERT_GENTFUNC_BASIC( randm_unb_var1, randv_unb_var1 ) INSERT_GENTFUNC_BASIC( randnm_unb_var1, randnv_unb_var1 ) #undef GENTFUNCR #define GENTFUNCR( ctype, ctype_r, ch, chr, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ dim_t n, \ ctype* x, inc_t incx, \ ctype_r* scale, \ ctype_r* sumsq, \ cntx_t* cntx, \ rntm_t* rntm \ ) \ { \ const ctype_r zero_r = *PASTEMAC(chr,0); \ const ctype_r one_r = *PASTEMAC(chr,1); \ \ ctype* chi1; \ ctype_r chi1_r; \ ctype_r chi1_i; \ ctype_r scale_r; \ ctype_r sumsq_r; \ ctype_r abs_chi1_r; \ dim_t i; \ \ /* NOTE: This function attempts to mimic the algorithm for computing the Frobenius norm in netlib LAPACK's ?lassq(). */ \ \ /* Copy scale and sumsq to local variables. */ \ PASTEMAC(chr,copys)( *scale, scale_r ); \ PASTEMAC(chr,copys)( *sumsq, sumsq_r ); \ \ chi1 = x; \ \ for ( i = 0; i < n; ++i ) \ { \ /* Get the real and imaginary components of chi1. */ \ PASTEMAC2(ch,chr,gets)( *chi1, chi1_r, chi1_i ); \ \ abs_chi1_r = bli_fabs( chi1_r ); \ \ /* Accumulate real component into sumsq, adjusting scale if needed. */ \ if ( abs_chi1_r > zero_r || bli_isnan( abs_chi1_r) ) \ { \ if ( scale_r < abs_chi1_r ) \ { \ sumsq_r = one_r + \ sumsq_r * ( scale_r / abs_chi1_r ) * \ ( scale_r / abs_chi1_r ); \ \ PASTEMAC(chr,copys)( abs_chi1_r, scale_r ); \ } \ else \ { \ sumsq_r = sumsq_r + ( abs_chi1_r / scale_r ) * \ ( abs_chi1_r / scale_r ); \ } \ } \ \ abs_chi1_r = bli_fabs( chi1_i ); \ \ /* Accumulate imaginary component into sumsq, adjusting scale if needed. */ \ if ( abs_chi1_r > zero_r || bli_isnan( abs_chi1_r) ) \ { \ if ( scale_r < abs_chi1_r ) \ { \ sumsq_r = one_r + \ sumsq_r * ( scale_r / abs_chi1_r ) * \ ( scale_r / abs_chi1_r ); \ \ PASTEMAC(chr,copys)( abs_chi1_r, scale_r ); \ } \ else \ { \ sumsq_r = sumsq_r + ( abs_chi1_r / scale_r ) * \ ( abs_chi1_r / scale_r ); \ } \ } \ \ chi1 += incx; \ } \ \ /* Store final values of scale and sumsq to output variables. */ \ PASTEMAC(chr,copys)( scale_r, *scale ); \ PASTEMAC(chr,copys)( sumsq_r, *sumsq ); \ } INSERT_GENTFUNCR_BASIC0( sumsqv_unb_var1 ) // ----------------------------------------------------------------------------- #undef GENTFUNC #define GENTFUNC( ctype, ch, opname ) \ \ bool PASTEMAC(ch,opname) \ ( \ conj_t conjx, \ dim_t n, \ ctype* x, inc_t incx, \ ctype* y, inc_t incy \ ) \ { \ for ( dim_t i = 0; i < n; ++i ) \ { \ ctype* chi1 = x + (i )*incx; \ ctype* psi1 = y + (i )*incy; \ \ ctype chi1c; \ \ if ( bli_is_conj( conjx ) ) { PASTEMAC(ch,copyjs)( *chi1, chi1c ); } \ else { PASTEMAC(ch,copys)( *chi1, chi1c ); } \ \ if ( !PASTEMAC(ch,eq)( chi1c, *psi1 ) ) \ return FALSE; \ } \ \ return TRUE; \ } INSERT_GENTFUNC_BASIC0( eqv_unb_var1 ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname ) \ \ bool PASTEMAC(ch,opname) \ ( \ doff_t diagoffx, \ diag_t diagx, \ uplo_t uplox, \ trans_t transx, \ dim_t m, \ dim_t n, \ ctype* x, inc_t rs_x, inc_t cs_x, \ ctype* y, inc_t rs_y, inc_t cs_y \ ) \ { \ uplo_t uplox_eff; \ conj_t conjx; \ dim_t n_iter; \ dim_t n_elem_max; \ inc_t ldx, incx; \ inc_t ldy, incy; \ dim_t ij0, n_shift; \ \ /* Set various loop parameters. */ \ bli_set_dims_incs_uplo_2m \ ( \ diagoffx, diagx, transx, \ uplox, m, n, rs_x, cs_x, rs_y, cs_y, \ &uplox_eff, &n_elem_max, &n_iter, &incx, &ldx, &incy, &ldy, \ &ij0, &n_shift \ ); \ \ /* In the odd case where we are comparing against a complete unstored matrix, we assert equality. Why? We assume the matrices are equal unless we can find two corresponding elements that are unequal. So if there are no elements, there is no inequality. Granted, this logic is strange to think about no matter what, and thankfully it should never be used under normal usage. */ \ if ( bli_is_zeros( uplox_eff ) ) return TRUE; \ \ /* Extract the conjugation component from the transx parameter. */ \ conjx = bli_extract_conj( transx ); \ \ /* Handle dense and upper/lower storage cases separately. */ \ if ( bli_is_dense( uplox_eff ) ) \ { \ for ( dim_t j = 0; j < n_iter; ++j ) \ { \ const dim_t n_elem = n_elem_max; \ \ ctype* x1 = x + (j )*ldx + (0 )*incx; \ ctype* y1 = y + (j )*ldy + (0 )*incy; \ \ for ( dim_t i = 0; i < n_elem; ++i ) \ { \ ctype* x11 = x1 + (i )*incx; \ ctype* y11 = y1 + (i )*incy; \ ctype x11c; \ \ if ( bli_is_conj( conjx ) ) { PASTEMAC(ch,copyjs)( *x11, x11c ); } \ else { PASTEMAC(ch,copys)( *x11, x11c ); } \ \ if ( !PASTEMAC(ch,eq)( x11c, *y11 ) ) \ return FALSE; \ } \ } \ } \ else \ { \ if ( bli_is_upper( uplox_eff ) ) \ { \ for ( dim_t j = 0; j < n_iter; ++j ) \ { \ const dim_t n_elem = bli_min( n_shift + j + 1, n_elem_max ); \ \ ctype* x1 = x + (ij0+j )*ldx + (0 )*incx; \ ctype* y1 = y + (ij0+j )*ldy + (0 )*incy; \ \ for ( dim_t i = 0; i < n_elem; ++i ) \ { \ ctype* x11 = x1 + (i )*incx; \ ctype* y11 = y1 + (i )*incy; \ ctype x11c; \ \ if ( bli_is_conj( conjx ) ) { PASTEMAC(ch,copyjs)( *x11, x11c ); } \ else { PASTEMAC(ch,copys)( *x11, x11c ); } \ \ if ( !PASTEMAC(ch,eq)( x11c, *y11 ) ) \ return FALSE; \ } \ } \ } \ else if ( bli_is_lower( uplox_eff ) ) \ { \ for ( dim_t j = 0; j < n_iter; ++j ) \ { \ const dim_t offi = bli_max( 0, ( doff_t )j - ( doff_t )n_shift ); \ const dim_t n_elem = n_elem_max - offi; \ \ ctype* x1 = x + (j )*ldx + (ij0+offi )*incx; \ ctype* y1 = y + (j )*ldy + (ij0+offi )*incy; \ \ for ( dim_t i = 0; i < n_elem; ++i ) \ { \ ctype* x11 = x1 + (i )*incx; \ ctype* y11 = y1 + (i )*incy; \ ctype x11c; \ \ if ( bli_is_conj( conjx ) ) { PASTEMAC(ch,copyjs)( *x11, x11c ); } \ else { PASTEMAC(ch,copys)( *x11, x11c ); } \ \ if ( !PASTEMAC(ch,eq)( x11c, *y11 ) ) \ return FALSE; \ } \ } \ } \ } \ \ return TRUE; \ } INSERT_GENTFUNC_BASIC0( eqm_unb_var1 ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ FILE* file, \ char* s1, \ dim_t n, \ ctype* x, inc_t incx, \ char* format, \ char* s2 \ ) \ { \ dim_t i; \ ctype* chi1; \ char default_spec[32] = PASTEMAC(ch,formatspec)(); \ \ if ( format == NULL ) format = default_spec; \ \ chi1 = x; \ \ fprintf( file, "%s\n", s1 ); \ \ for ( i = 0; i < n; ++i ) \ { \ PASTEMAC(ch,fprints)( file, format, *chi1 ); \ fprintf( file, "\n" ); \ \ chi1 += incx; \ } \ \ fprintf( file, "%s\n", s2 ); \ } INSERT_GENTFUNC_BASIC0_I( fprintv ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ FILE* file, \ char* s1, \ dim_t m, \ dim_t n, \ ctype* x, inc_t rs_x, inc_t cs_x, \ char* format, \ char* s2 \ ) \ { \ dim_t i, j; \ ctype* chi1; \ char default_spec[32] = PASTEMAC(ch,formatspec)(); \ \ if ( format == NULL ) format = default_spec; \ \ fprintf( file, "%s\n", s1 ); \ \ for ( i = 0; i < m; ++i ) \ { \ for ( j = 0; j < n; ++j ) \ { \ chi1 = (( ctype* ) x) + i*rs_x + j*cs_x; \ \ PASTEMAC(ch,fprints)( file, format, *chi1 ); \ fprintf( file, " " ); \ } \ \ fprintf( file, "\n" ); \ } \ \ fprintf( file, "%s\n", s2 ); \ fflush( file ); \ } INSERT_GENTFUNC_BASIC0_I( fprintm ) blis-0.9.0/frame/util/bli_util_unb_var1.h000066400000000000000000000127111422157504600203010ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype BLAS-like interfaces with typed operands. // #undef GENTPROTR #define GENTPROTR( ctype, ctype_r, ch, chr, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ dim_t n, \ ctype* x, inc_t incx, \ ctype_r* asum, \ cntx_t* cntx, \ rntm_t* rntm \ ); INSERT_GENTPROTR_BASIC0( asumv_unb_var1 ) #undef GENTPROT #define GENTPROT( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ uplo_t uploa, \ dim_t m, \ ctype* a, inc_t rs_a, inc_t cs_a, \ cntx_t* cntx, \ rntm_t* rntm \ ); INSERT_GENTPROT_BASIC0( mkherm_unb_var1 ) INSERT_GENTPROT_BASIC0( mksymm_unb_var1 ) INSERT_GENTPROT_BASIC0( mktrim_unb_var1 ) #undef GENTPROTR #define GENTPROTR( ctype, ctype_r, ch, chr, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ dim_t n, \ ctype* x, inc_t incx, \ ctype_r* norm, \ cntx_t* cntx, \ rntm_t* rntm \ ); INSERT_GENTPROTR_BASIC0( norm1v_unb_var1 ) INSERT_GENTPROTR_BASIC0( normfv_unb_var1 ) INSERT_GENTPROTR_BASIC0( normiv_unb_var1 ) #undef GENTPROTR #define GENTPROTR( ctype, ctype_r, ch, chr, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ doff_t diagoffx, \ diag_t diagx, \ uplo_t uplox, \ dim_t m, \ dim_t n, \ ctype* x, inc_t rs_x, inc_t cs_x, \ ctype_r* norm, \ cntx_t* cntx, \ rntm_t* rntm \ ); INSERT_GENTPROTR_BASIC0( norm1m_unb_var1 ) INSERT_GENTPROTR_BASIC0( normfm_unb_var1 ) INSERT_GENTPROTR_BASIC0( normim_unb_var1 ) #undef GENTPROT #define GENTPROT( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ dim_t n, \ ctype* x, inc_t incx, \ cntx_t* cntx, \ rntm_t* rntm \ ); INSERT_GENTPROT_BASIC0( randv_unb_var1 ) INSERT_GENTPROT_BASIC0( randnv_unb_var1 ) #undef GENTPROT #define GENTPROT( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ doff_t diagoffx, \ uplo_t uplox, \ dim_t m, \ dim_t n, \ ctype* x, inc_t rs_x, inc_t cs_x, \ cntx_t* cntx, \ rntm_t* rntm \ ); INSERT_GENTPROT_BASIC0( randm_unb_var1 ) INSERT_GENTPROT_BASIC0( randnm_unb_var1 ) #undef GENTPROTR #define GENTPROTR( ctype, ctype_r, ch, chr, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ dim_t n, \ ctype* x, inc_t incx, \ ctype_r* scale, \ ctype_r* sumsq, \ cntx_t* cntx, \ rntm_t* rntm \ ); INSERT_GENTPROTR_BASIC0( sumsqv_unb_var1 ) // ----------------------------------------------------------------------------- #undef GENTPROT #define GENTPROT( ctype, ch, varname ) \ \ bool PASTEMAC(ch,varname) \ ( \ conj_t conjx, \ dim_t n, \ ctype* x, inc_t incx, \ ctype* y, inc_t incy \ ); INSERT_GENTPROT_BASIC0( eqv_unb_var1 ) #undef GENTPROT #define GENTPROT( ctype, ch, varname ) \ \ bool PASTEMAC(ch,varname) \ ( \ doff_t diagoffx, \ diag_t diagx, \ uplo_t uplox, \ trans_t transx, \ dim_t m, \ dim_t n, \ ctype* x, inc_t rs_x, inc_t cs_x, \ ctype* y, inc_t rs_y, inc_t cs_y \ ); INSERT_GENTPROT_BASIC0( eqm_unb_var1 ) #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC(ch,opname) \ ( \ FILE* file, \ char* s1, \ dim_t n, \ ctype* x, inc_t incx, \ char* format, \ char* s2 \ ); INSERT_GENTPROT_BASIC0_I( fprintv ) #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ BLIS_EXPORT_BLIS void PASTEMAC(ch,opname) \ ( \ FILE* file, \ char* s1, \ dim_t m, \ dim_t n, \ ctype* x, inc_t rs_x, inc_t cs_x, \ char* format, \ char* s2 \ ); INSERT_GENTPROT_BASIC0_I( fprintm ) blis-0.9.0/kernels/000077500000000000000000000000001422157504600141225ustar00rootroot00000000000000blis-0.9.0/kernels/armsve/000077500000000000000000000000001422157504600154175ustar00rootroot00000000000000blis-0.9.0/kernels/armsve/1m/000077500000000000000000000000001422157504600157345ustar00rootroot00000000000000blis-0.9.0/kernels/armsve/1m/armsve512_asm_transpose_d8x2.h000066400000000000000000000043241422157504600234400ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2021, The University of Tokyo 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #define SVE512_IN_REG_TRANSPOSE_d8x2(DST0,DST1,DST2,DST3,DST4,DST5,DST6SRC0,DST7SRC1,PT,P2C,P4C,P6C) \ "trn1 " #DST0".d, " #DST6SRC0".d, " #DST7SRC1".d \n\t" \ "trn2 " #DST1".d, " #DST6SRC0".d, " #DST7SRC1".d \n\t" \ "compact " #DST2".d, " #P2C", " #DST0".d \n\t" \ "compact " #DST3".d, " #P2C", " #DST1".d \n\t" \ "compact " #DST4".d, " #P4C", " #DST0".d \n\t" \ "compact " #DST5".d, " #P4C", " #DST1".d \n\t" \ "compact " #DST6SRC0".d, " #P6C", " #DST0".d \n\t" \ "compact " #DST7SRC1".d, " #P6C", " #DST1".d \n\t" blis-0.9.0/kernels/armsve/1m/armsve512_asm_transpose_d8x8.h000066400000000000000000000113651422157504600234510ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2021, The University of Tokyo 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #define SVE512_IN_REG_TRANSPOSE_d8x8_PREPARE(XTMP,PT,P2C,P4C,P6C,PTFTF,P4,P6) \ "ptrue " #PT".d \n\t" \ "mov " #XTMP", #2 \n\t" \ "whilelo " #P2C".d, xzr, " #XTMP" \n\t" \ "mov " #XTMP", #4 \n\t" \ "whilelo " #P4".d, xzr, " #XTMP" \n\t" \ "mov " #XTMP", #6 \n\t" \ "whilelo " #P6".d, xzr, " #XTMP" \n\t" \ \ "eor " #PTFTF".b, " #PT"/z, " #P6".b, " #P4".b \n\t" /***** o o | o */ \ "orr " #PTFTF".b, " #PT"/z, " #PTFTF".b, " #P2C".b \n\t" /* | o | o */ \ \ "not " #P2C".b, " #PT"/z, " #P2C".b \n\t" \ "not " #P4C".b, " #PT"/z, " #P4".b \n\t" \ "not " #P6C".b, " #PT"/z, " #P6".b \n\t" \ #define SVE512_IN_REG_TRANSPOSE_d8x8(DST0,DST1,DST2,DST3,DST4,DST5,DST6,DST7,SRC0,SRC1,SRC2,SRC3,SRC4,SRC5,SRC6,SRC7,PT,P2C,P4C,P6C,PTFTF,P4,P6) \ "trn1 " #DST0".d, " #SRC0".d, " #SRC1".d \n\t" \ "trn2 " #DST1".d, " #SRC0".d, " #SRC1".d \n\t" \ "trn1 " #DST2".d, " #SRC2".d, " #SRC3".d \n\t" \ "trn2 " #DST3".d, " #SRC2".d, " #SRC3".d \n\t" \ "trn1 " #DST4".d, " #SRC4".d, " #SRC5".d \n\t" \ "trn2 " #DST5".d, " #SRC4".d, " #SRC5".d \n\t" \ "trn1 " #DST6".d, " #SRC6".d, " #SRC7".d \n\t" \ "trn2 " #DST7".d, " #SRC6".d, " #SRC7".d \n\t" \ \ "compact " #SRC0".d, " #P2C", " #DST0".d \n\t" \ "compact " #SRC2".d, " #P2C", " #DST1".d \n\t" \ "ext " #SRC1".b, " #SRC1".b, " #DST2".b, #48 \n\t" \ "ext " #SRC3".b, " #SRC3".b, " #DST3".b, #48 \n\t" \ "compact " #SRC4".d, " #P2C", " #DST4".d \n\t" \ "compact " #SRC6".d, " #P2C", " #DST5".d \n\t" \ "ext " #SRC5".b, " #SRC5".b, " #DST6".b, #48 \n\t" \ "ext " #SRC7".b, " #SRC7".b, " #DST7".b, #48 \n\t" \ \ "sel " #DST0".d, " #PTFTF", " #DST0".d, " #SRC1".d \n\t" \ "sel " #DST2".d, " #PTFTF", " #SRC0".d, " #DST2".d \n\t" \ "sel " #DST1".d, " #PTFTF", " #DST1".d, " #SRC3".d \n\t" \ "sel " #DST3".d, " #PTFTF", " #SRC2".d, " #DST3".d \n\t" \ "sel " #DST4".d, " #PTFTF", " #DST4".d, " #SRC5".d \n\t" \ "sel " #DST6".d, " #PTFTF", " #SRC4".d, " #DST6".d \n\t" \ "sel " #DST5".d, " #PTFTF", " #DST5".d, " #SRC7".d \n\t" \ "sel " #DST7".d, " #PTFTF", " #SRC6".d, " #DST7".d \n\t" \ \ "compact " #SRC0".d, " #P4C", " #DST0".d \n\t" \ "compact " #SRC1".d, " #P4C", " #DST1".d \n\t" \ "compact " #SRC2".d, " #P4C", " #DST2".d \n\t" \ "compact " #SRC3".d, " #P4C", " #DST3".d \n\t" \ "ext " #SRC4".b, " #SRC4".b, " #DST4".b, #32 \n\t" \ "ext " #SRC5".b, " #SRC5".b, " #DST5".b, #32 \n\t" \ "ext " #SRC6".b, " #SRC6".b, " #DST6".b, #32 \n\t" \ "ext " #SRC7".b, " #SRC7".b, " #DST7".b, #32 \n\t" \ \ "sel " #DST0".d, " #P4", " #DST0".d, " #SRC4".d \n\t" \ "sel " #DST1".d, " #P4", " #DST1".d, " #SRC5".d \n\t" \ "sel " #DST2".d, " #P4", " #DST2".d, " #SRC6".d \n\t" \ "sel " #DST3".d, " #P4", " #DST3".d, " #SRC7".d \n\t" \ "sel " #DST4".d, " #P4", " #SRC0".d, " #DST4".d \n\t" \ "sel " #DST5".d, " #P4", " #SRC1".d, " #DST5".d \n\t" \ "sel " #DST6".d, " #P4", " #SRC2".d, " #DST6".d \n\t" \ "sel " #DST7".d, " #P4", " #SRC3".d, " #DST7".d \n\t" blis-0.9.0/kernels/armsve/1m/bli_dpackm_armsve256_int_8xk.c000066400000000000000000000174531422157504600234550ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2020, Linaro Limited 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #if !defined(BLIS_FAMILY_A64FX) #include // assumption: // SVE vector length = 256 bits. // void bli_dpackm_armsve256_int_8xk ( conj_t conja, pack_t schema, dim_t cdim_, dim_t n_, dim_t n_max_, double* restrict kappa, double* restrict a, inc_t inca_, inc_t lda_, double* restrict p, inc_t ldp_, cntx_t* restrict cntx ) { const int64_t cdim = cdim_; const int64_t mnr = 8; const int64_t n = n_; const int64_t n_max = n_max_; const int64_t inca = inca_; const int64_t lda = lda_; const int64_t ldp = ldp_; double* restrict alpha1 = a; double* restrict alpha1_4 = alpha1 + 4 * inca; double* restrict pi1 = p; const svbool_t all_active = svptrue_b64(); svfloat64_t z_a0; svfloat64_t z_a4; svuint64_t z_index; // creating index for gather/scatter // with each element as: 0, 1*inca, 2*inca, 3*inca z_index = svindex_u64( 0, inca * sizeof( double ) ); if ( cdim == mnr ) { if ( bli_deq1( *kappa ) ) { if ( inca == 1 ) // continous memory. packA style { for ( dim_t k = n; k != 0; --k ) { // svld1_f64 retrieves all zero's into z_a0 and z_a4, // which is not correct. // qemu-aarch64 or gcc interpretation of svld1_f64 // should be blamed. // load 8 continuous elments from *a // z_a0 = svld1_f64( all_active, alpha1 ); // z_a4 = svld1_vnum_f64( all_active, alpha1, 1 ); // as a workaround, using gather load // gather load from *a z_a0 = svld1_gather_u64offset_f64( all_active, alpha1, z_index ); z_a4 = svld1_gather_u64offset_f64( all_active, alpha1_4, z_index ); // store them into *p svst1_f64( all_active, pi1, z_a0 ); svst1_vnum_f64( all_active, pi1, 1, z_a4 ); alpha1 += lda; alpha1_4 = alpha1 + 4 * inca; pi1 += ldp; } } else // gather/scatter load/store. packB style { for ( dim_t k = n; k != 0; --k ) { // gather load from *a z_a0 = svld1_gather_u64offset_f64( all_active, alpha1, z_index ); z_a4 = svld1_gather_u64offset_f64( all_active, alpha1_4, z_index ); // scatter store into *p svst1_f64( all_active, pi1, z_a0 ); svst1_vnum_f64( all_active, pi1, 1, z_a4 ); alpha1 += lda; alpha1_4 = alpha1 + 4 * inca; pi1 += ldp; } } } else // *kappa != 1.0 { // load kappa into vector svfloat64_t z_kappa; z_kappa = svdup_f64( *kappa ); if ( inca == 1 ) // continous memory. packA style { for ( dim_t k = n; k != 0; --k ) { // load 8 continuous elments from *a // z_a0 = svld1_f64( all_active, alpha1 ); // z_a4 = svld1_vnum_f64( all_active, alpha1, 1 ); // same reason as above. as a workaround, using gather load // gather load from *a z_a0 = svld1_gather_u64offset_f64( all_active, alpha1, z_index ); z_a4 = svld1_gather_u64offset_f64( all_active, alpha1_4, z_index ); // multiply by *kappa z_a0 = svmul_lane_f64( z_a0, z_kappa, 0 ); z_a4 = svmul_lane_f64( z_a4, z_kappa, 0 ); // store them into *p svst1_f64( all_active, pi1, z_a0 ); svst1_vnum_f64( all_active, pi1, 1, z_a4 ); alpha1 += lda; alpha1_4 = alpha1 + 4 * inca; pi1 += ldp; } } else // gather/scatter load/store. packB style { for ( dim_t k = n; k != 0; --k ) { // gather load from *a z_a0 = svld1_gather_u64offset_f64( all_active, alpha1, z_index ); z_a4 = svld1_gather_u64offset_f64( all_active, alpha1_4, z_index ); // multiply by *kappa z_a0 = svmul_lane_f64( z_a0, z_kappa, 0 ); z_a4 = svmul_lane_f64( z_a4, z_kappa, 0 ); // scatter store into *p svst1_f64( all_active, pi1, z_a0 ); svst1_vnum_f64( all_active, pi1, 1, z_a4 ); alpha1 += lda; alpha1_4 = alpha1 + 4 * inca; pi1 += ldp; } } } // end of if ( *kappa == 1.0 ) } else // if ( cdim < mnr ) { bli_dscal2m_ex ( 0, BLIS_NONUNIT_DIAG, BLIS_DENSE, ( trans_t )conja, cdim, n, kappa, a, inca, lda, p, 1, ldp, cntx, NULL ); // if ( cdim < mnr ) { const dim_t i = cdim; const dim_t m_edge = mnr - i; const dim_t n_edge = n_max; double* restrict p_edge = p + (i )*1; bli_dset0s_mxn ( m_edge, n_edge, p_edge, 1, ldp ); } } if ( n < n_max ) { const dim_t j = n; const dim_t m_edge = mnr; const dim_t n_edge = n_max - j; double* restrict p_edge = p + (j )*ldp; bli_dset0s_mxn ( m_edge, n_edge, p_edge, 1, ldp ); } } #endif // __has_include() blis-0.9.0/kernels/armsve/1m/bli_dpackm_armsve512_asm_10xk.c000066400000000000000000000321461422157504600235030ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2021, The University of Tokyo 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "armsve512_asm_transpose_d8x8.h" #include "armsve512_asm_transpose_d8x2.h" #include "../3/armsve_asm_macros.h" // assumption: // SVE vector length = 512 bits. void bli_dpackm_armsve512_asm_10xk ( conj_t conja, pack_t schema, dim_t cdim_, dim_t n_, dim_t n_max_, double* restrict kappa, double* restrict a, inc_t inca_, inc_t lda_, double* restrict p, inc_t ldp_, cntx_t* restrict cntx ) { const int64_t cdim = cdim_; const int64_t mnr = 10; const int64_t n = n_; const int64_t n_max = n_max_; const int64_t inca = inca_; const int64_t lda = lda_; const int64_t ldp = ldp_; const bool gs = inca != 1 && lda != 1; const bool unitk = bli_deq1( *kappa ); #ifdef _A64FX { // Infer whether A or B is being packed. if ( schema == BLIS_PACKED_ROWS ) p = ( (uint64_t)0x1 << 56 ) | (uint64_t)p; if ( schema == BLIS_PACKED_COLUMNS ) p = ( (uint64_t)0x2 << 56 ) | (uint64_t)p; } #endif if ( cdim == mnr && !gs && unitk ) { uint64_t n_mker = n / 8; uint64_t n_left = n % 8; __asm__ volatile ( "mov x0, %[a] \n\t" "mov x1, %[p] \n\t" "mov x2, %[ldp] \n\t" "mov x3, %[lda] \n\t" "mov x4, %[inca] \n\t" "cmp x4, #1 \n\t" // Skips by sizeof(double). "mov x8, #8 \n\t" "madd x2, x2, x8, xzr \n\t" "madd x3, x3, x8, xzr \n\t" "madd x4, x4, x8, xzr \n\t" // Loop constants. "mov x8, %[n_mker] \n\t" "mov x9, %[n_left] \n\t" "ptrue p0.d \n\t" BNE(AROWSTOR) // A stored in columns. LABEL(ACOLSTOR) // Prefetch distance. "mov x17, #8 \n\t" "madd x17, x17, x3, xzr \n\t" #ifdef _A64FX // Disable hardware prefetch for A. "mov x16, 0x6 \n\t" "lsl x16, x16, #60 \n\t" "orr x0, x0, x16 \n\t" #endif LABEL(ACOLSTORMKER) "cmp x8, xzr \n\t" BEQ(ACOLSTORMKEREND) "add x5, x0, x3 \n\t" "add x6, x5, x3 \n\t" "add x7, x6, x3 \n\t" "ld1d z0.d, p0/z, [x0] \n\t" "ldr q1, [x0, #64] \n\t" "ld1d z2.d, p0/z, [x5] \n\t" "ldr q3, [x5, #64] \n\t" "ld1d z4.d, p0/z, [x6] \n\t" "ldr q5, [x6, #64] \n\t" "ld1d z6.d, p0/z, [x7] \n\t" "ldr q7, [x7, #64] \n\t" "add x18, x17, x0 \n\t" "prfm PLDL1STRM, [x18] \n\t" "add x18, x17, x5 \n\t" "prfm PLDL1STRM, [x18] \n\t" "add x18, x17, x6 \n\t" "prfm PLDL1STRM, [x18] \n\t" "add x18, x17, x7 \n\t" "prfm PLDL1STRM, [x18] \n\t" "add x0, x7, x3 \n\t" "add x5, x0, x3 \n\t" "add x6, x5, x3 \n\t" "add x7, x6, x3 \n\t" "ld1d z8.d, p0/z, [x0] \n\t" "ldr q9, [x0, #64] \n\t" "ld1d z10.d, p0/z, [x5] \n\t" "ldr q11, [x5, #64] \n\t" "ld1d z12.d, p0/z, [x6] \n\t" "ldr q13, [x6, #64] \n\t" "ld1d z14.d, p0/z, [x7] \n\t" "ldr q15, [x7, #64] \n\t" "add x18, x17, x0 \n\t" "prfm PLDL1STRM, [x18] \n\t" "add x18, x17, x5 \n\t" "prfm PLDL1STRM, [x18] \n\t" "add x18, x17, x6 \n\t" "prfm PLDL1STRM, [x18] \n\t" "add x18, x17, x7 \n\t" "prfm PLDL1STRM, [x18] \n\t" // Plain storage "add x10, x1, x2 \n\t" "add x11, x10, x2 \n\t" "add x12, x11, x2 \n\t" "add x13, x12, x2 \n\t" "add x14, x13, x2 \n\t" "add x15, x14, x2 \n\t" "add x16, x15, x2 \n\t" "st1d z0.d, p0, [x1] \n\t" "str q1, [x1, #64] \n\t" "st1d z2.d, p0, [x10] \n\t" "str q3, [x10, #64] \n\t" "st1d z4.d, p0, [x11] \n\t" "str q5, [x11, #64] \n\t" "st1d z6.d, p0, [x12] \n\t" "str q7, [x12, #64] \n\t" "st1d z8.d, p0, [x13] \n\t" "str q9, [x13, #64] \n\t" "st1d z10.d, p0, [x14] \n\t" "str q11, [x14, #64] \n\t" "st1d z12.d, p0, [x15] \n\t" "str q13, [x15, #64] \n\t" "st1d z14.d, p0, [x16] \n\t" "str q15, [x16, #64] \n\t" "add x1, x16, x2 \n\t" // Realign and store. // "ext z1.b, z1.b, z1.b, #16 \n\t" // "ext z1.b, z1.b, z2.b, #48 \n\t" // "ext z2.b, z2.b, z3.b, #16 \n\t" // "ext z2.b, z2.b, z4.b, #32 \n\t" // "ext z4.b, z4.b, z5.b, #16 \n\t" // "ext z4.b, z4.b, z6.b, #16 \n\t" // "ext z6.b, z6.b, z7.b, #16 \n\t" // "ext z9.b, z9.b, z9.b, #16 \n\t" // "ext z9.b, z9.b, z10.b, #48 \n\t" // "ext z10.b, z10.b, z11.b, #16 \n\t" // "ext z10.b, z10.b, z12.b, #32 \n\t" // "ext z12.b, z12.b, z13.b, #16 \n\t" // "ext z12.b, z12.b, z14.b, #16 \n\t" // "ext z14.b, z14.b, z15.b, #16 \n\t" // "st1d z0.d, p0, [x1] \n\t" // "st1d z1.d, p0, [x1, #1, mul vl] \n\t" // "st1d z2.d, p0, [x1, #2, mul vl] \n\t" // "st1d z4.d, p0, [x1, #3, mul vl] \n\t" // "st1d z6.d, p0, [x1, #4, mul vl] \n\t" // "add x1, x1, #320 \n\t" // "st1d z8.d, p0, [x1] \n\t" // "st1d z9.d, p0, [x1, #1, mul vl] \n\t" // "st1d z10.d, p0, [x1, #2, mul vl] \n\t" // "st1d z12.d, p0, [x1, #3, mul vl] \n\t" // "st1d z14.d, p0, [x1, #4, mul vl] \n\t" // "add x1, x1, #320 \n\t" "add x0, x7, x3 \n\t" "sub x8, x8, #1 \n\t" BRANCH(ACOLSTORMKER) LABEL(ACOLSTORMKEREND) LABEL(ACOLSTORLEFT) "cmp x9, xzr \n\t" BEQ(UNITKDONE) "ld1d z0.d, p0/z, [x0] \n\t" "ldr q1, [x0, #64] \n\t" "st1d z0.d, p0, [x1] \n\t" "str q1, [x1, #64] \n\t" "add x0, x0, x3 \n\t" "add x1, x1, x2 \n\t" "sub x9, x9, #1 \n\t" BRANCH(ACOLSTORLEFT) // A stored in rows. LABEL(AROWSTOR) // Prepare predicates for in-reg transpose. SVE512_IN_REG_TRANSPOSE_d8x8_PREPARE(x16,p0,p1,p2,p3,p8,p4,p6) LABEL(AROWSTORMKER) // X[10-16] for A here not P. Be careful. "cmp x8, xzr \n\t" BEQ(AROWSTORMKEREND) "add x10, x0, x4 \n\t" "add x11, x10, x4 \n\t" "add x12, x11, x4 \n\t" "add x13, x12, x4 \n\t" "add x14, x13, x4 \n\t" "add x15, x14, x4 \n\t" "add x16, x15, x4 \n\t" "add x17, x16, x4 \n\t" "add x18, x17, x4 \n\t" "ld1d z0.d, p0/z, [x0] \n\t" "ld1d z1.d, p0/z, [x10] \n\t" "ld1d z2.d, p0/z, [x11] \n\t" "ld1d z3.d, p0/z, [x12] \n\t" "ld1d z4.d, p0/z, [x13] \n\t" "ld1d z5.d, p0/z, [x14] \n\t" "ld1d z6.d, p0/z, [x15] \n\t" "ld1d z7.d, p0/z, [x16] \n\t" "ld1d z22.d, p0/z, [x17] \n\t" "ld1d z23.d, p0/z, [x18] \n\t" // Transpose first 8 rows. SVE512_IN_REG_TRANSPOSE_d8x8(z8,z9,z10,z11,z12,z13,z14,z15,z0,z1,z2,z3,z4,z5,z6,z7,p0,p1,p2,p3,p8,p4,p6) // Transpose last 2 rows. SVE512_IN_REG_TRANSPOSE_d8x2(z16,z17,z18,z19,z20,z21,z22,z23,p0,p1,p2,p3) // Plain storage. "add x10, x1, x2 \n\t" "add x11, x10, x2 \n\t" "add x12, x11, x2 \n\t" "add x13, x12, x2 \n\t" "add x14, x13, x2 \n\t" "add x15, x14, x2 \n\t" "add x16, x15, x2 \n\t" "st1d z8.d, p0, [x1] \n\t" "str q16, [x1, #64] \n\t" "st1d z9.d, p0, [x10] \n\t" "str q17, [x10, #64] \n\t" "st1d z10.d, p0, [x11] \n\t" "str q18, [x11, #64] \n\t" "st1d z11.d, p0, [x12] \n\t" "str q19, [x12, #64] \n\t" "st1d z12.d, p0, [x13] \n\t" "str q20, [x13, #64] \n\t" "st1d z13.d, p0, [x14] \n\t" "str q21, [x14, #64] \n\t" "st1d z14.d, p0, [x15] \n\t" "str q22, [x15, #64] \n\t" "st1d z15.d, p0, [x16] \n\t" "str q23, [x16, #64] \n\t" "add x1, x16, x2 \n\t" "add x0, x0, #64 \n\t" "sub x8, x8, #1 \n\t" BRANCH(AROWSTORMKER) LABEL(AROWSTORMKEREND) "mov x4, %[inca] \n\t" // Restore unshifted inca. "index z30.d, xzr, x4 \n\t" // Generate index. "lsl x4, x4, #3 \n\t" // Shift again. "lsl x5, x4, #3 \n\t" // Virtual column vl. LABEL(AROWSTORLEFT) "cmp x9, xzr \n\t" BEQ(UNITKDONE) "add x6, x0, x5 \n\t" "add x7, x6, x4 \n\t" "ld1d z0.d, p0/z, [x0, z30.d, lsl #3] \n\t" "ldr d1, [x6] \n\t" "ldr d2, [x7] \n\t" "trn1 v1.2d, v1.2d, v2.2d \n\t" "st1d z0.d, p0, [x1] \n\t" "str q1, [x1, #64] \n\t" "add x1, x1, x2 \n\t" "add x0, x0, #8 \n\t" "sub x9, x9, #1 \n\t" BRANCH(AROWSTORLEFT) LABEL(UNITKDONE) "mov x0, #0 \n\t" : : [a] "r" (a), [p] "r" (p), [lda] "r" (lda), [ldp] "r" (ldp), [inca] "r" (inca), [n_mker] "r" (n_mker), [n_left] "r" (n_left) : "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10","x11","x12","x13","x14","x15", "x16","x17","x18", "z0", "z1", "z2", "z3", "z4", "z5", "z6", "z7", "z8", "z9", "z10","z11","z12","z13","z14","z15", "z16","z17","z18","z19","z20","z21","z22","z23", // "z24","z25","z26","z27","z28","z29", "z30","z31", "p0", "p1", "p2", "p3", "p4", // "p5", "p6", "p7", "p8" ); } else // if ( cdim < mnr ) { bli_dscal2m_ex ( 0, BLIS_NONUNIT_DIAG, BLIS_DENSE, ( trans_t )conja, cdim, n, kappa, a, inca, lda, p, 1, ldp, cntx, NULL ); // if ( cdim < mnr ) { const dim_t i = cdim; const dim_t m_edge = mnr - i; const dim_t n_edge = n_max; double* restrict p_edge = p + (i )*1; bli_dset0s_mxn ( m_edge, n_edge, p_edge, 1, ldp ); } } if ( n < n_max ) { const dim_t j = n; const dim_t m_edge = mnr; const dim_t n_edge = n_max - j; double* restrict p_edge = p + (j )*ldp; bli_dset0s_mxn ( m_edge, n_edge, p_edge, 1, ldp ); } } blis-0.9.0/kernels/armsve/1m/bli_dpackm_armsve512_asm_16xk.c000066400000000000000000000325511422157504600235110ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2021, The University of Tokyo 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "armsve512_asm_transpose_d8x8.h" #include "../3/armsve_asm_macros.h" // assumption: // SVE vector length = 512 bits. void bli_dpackm_armsve512_asm_16xk ( conj_t conja, pack_t schema, dim_t cdim_, dim_t n_, dim_t n_max_, double* restrict kappa, double* restrict a, inc_t inca_, inc_t lda_, double* restrict p, inc_t ldp_, cntx_t* restrict cntx ) { const int64_t cdim = cdim_; const int64_t mnr = 16; const int64_t n = n_; const int64_t n_max = n_max_; const int64_t inca = inca_; const int64_t lda = lda_; const int64_t ldp = ldp_; const bool gs = inca != 1 && lda != 1; const bool unitk = bli_deq1( *kappa ); #ifdef _A64FX { // Infer whether A or B is being packed. if ( schema == BLIS_PACKED_ROWS ) p = ( (uint64_t)0x1 << 56 ) | (uint64_t)p; if ( schema == BLIS_PACKED_COLUMNS ) p = ( (uint64_t)0x2 << 56 ) | (uint64_t)p; } #endif if ( cdim == mnr && !gs && unitk ) { uint64_t n_mker = n / 8; uint64_t n_left = n % 8; __asm__ volatile ( "mov x0, %[a] \n\t" "mov x1, %[p] \n\t" "mov x2, %[ldp] \n\t" "mov x3, %[lda] \n\t" "mov x4, %[inca] \n\t" "cmp x4, #1 \n\t" // Skips by sizeof(double). "mov x8, #8 \n\t" "madd x2, x2, x8, xzr \n\t" "madd x3, x3, x8, xzr \n\t" "madd x4, x4, x8, xzr \n\t" // "mov x8, 0x8 \n\t" // Control#0 for A address. // "mov x8, 0x24 \n\t" // Higher 6bit for Control#0: // "lsl x8, x8, #58 \n\t" // Valid|Strong|Strong|Alloc|Load|Strong // "orr x8, x8, x3 \n\t" // Stride. // "msr S3_3_C11_C6_0, x8 \n\t" // Write system register. // Loop constants. "mov x8, %[n_mker] \n\t" "mov x9, %[n_left] \n\t" "ptrue p0.d \n\t" BNE(AROWSTOR) // A stored in columns. LABEL(ACOLSTOR) // Prefetch distance. "mov x17, #8 \n\t" "madd x17, x17, x3, xzr \n\t" #ifdef _A64FX "mov x16, 0x6 \n\t" // Disable hardware prefetch for A. "lsl x16, x16, #60 \n\t" "orr x0, x0, x16 \n\t" #endif // "add x5, x0, x3 \n\t" // "add x6, x5, x3 \n\t" // "add x7, x6, x3 \n\t" // "prfm PLDL1STRM, [x0] \n\t" // "prfm PLDL1STRM, [x5] \n\t" // "prfm PLDL1STRM, [x6] \n\t" // "prfm PLDL1STRM, [x7] \n\t" // "add x18, x7, x3 \n\t" // "add x5, x18, x3 \n\t" // "add x6, x5, x3 \n\t" // "add x7, x6, x3 \n\t" // "prfm PLDL1STRM, [x18] \n\t" // "prfm PLDL1STRM, [x5] \n\t" // "prfm PLDL1STRM, [x6] \n\t" // "prfm PLDL1STRM, [x7] \n\t" LABEL(ACOLSTORMKER) "cmp x8, xzr \n\t" BEQ(ACOLSTORMKEREND) "add x5, x0, x3 \n\t" "add x6, x5, x3 \n\t" "add x7, x6, x3 \n\t" "add x10, x1, x2 \n\t" "add x11, x10, x2 \n\t" "add x12, x11, x2 \n\t" "add x13, x12, x2 \n\t" "add x14, x13, x2 \n\t" "add x15, x14, x2 \n\t" "add x16, x15, x2 \n\t" "ld1d z0.d, p0/z, [x0] \n\t" "ld1d z1.d, p0/z, [x0, #1, mul vl] \n\t" "ld1d z2.d, p0/z, [x5] \n\t" "ld1d z3.d, p0/z, [x5, #1, mul vl] \n\t" "ld1d z4.d, p0/z, [x6] \n\t" "ld1d z5.d, p0/z, [x6, #1, mul vl] \n\t" "ld1d z6.d, p0/z, [x7] \n\t" "ld1d z7.d, p0/z, [x7, #1, mul vl] \n\t" "add x18, x17, x0 \n\t" "prfm PLDL1STRM, [x18] \n\t" "add x18, x17, x5 \n\t" "prfm PLDL1STRM, [x18] \n\t" "add x18, x17, x6 \n\t" "prfm PLDL1STRM, [x18] \n\t" "add x18, x17, x7 \n\t" "prfm PLDL1STRM, [x18] \n\t" "add x0, x7, x3 \n\t" "add x5, x0, x3 \n\t" "add x6, x5, x3 \n\t" "add x7, x6, x3 \n\t" "ld1d z8.d, p0/z, [x0] \n\t" "ld1d z9.d, p0/z, [x0, #1, mul vl] \n\t" "ld1d z10.d, p0/z, [x5] \n\t" "ld1d z11.d, p0/z, [x5, #1, mul vl] \n\t" "ld1d z12.d, p0/z, [x6] \n\t" "ld1d z13.d, p0/z, [x6, #1, mul vl] \n\t" "ld1d z14.d, p0/z, [x7] \n\t" "ld1d z15.d, p0/z, [x7, #1, mul vl] \n\t" "add x18, x17, x0 \n\t" "prfm PLDL1STRM, [x18] \n\t" "add x18, x17, x5 \n\t" "prfm PLDL1STRM, [x18] \n\t" "add x18, x17, x6 \n\t" "prfm PLDL1STRM, [x18] \n\t" "add x18, x17, x7 \n\t" "prfm PLDL1STRM, [x18] \n\t" "st1d z0.d, p0, [x1] \n\t" "st1d z1.d, p0, [x1, #1, mul vl] \n\t" "st1d z2.d, p0, [x10] \n\t" "st1d z3.d, p0, [x10, #1, mul vl] \n\t" "st1d z4.d, p0, [x11] \n\t" "st1d z5.d, p0, [x11, #1, mul vl] \n\t" "st1d z6.d, p0, [x12] \n\t" "st1d z7.d, p0, [x12, #1, mul vl] \n\t" "st1d z8.d, p0, [x13] \n\t" "st1d z9.d, p0, [x13, #1, mul vl] \n\t" "st1d z10.d, p0, [x14] \n\t" "st1d z11.d, p0, [x14, #1, mul vl] \n\t" "st1d z12.d, p0, [x15] \n\t" "st1d z13.d, p0, [x15, #1, mul vl] \n\t" "st1d z14.d, p0, [x16] \n\t" "st1d z15.d, p0, [x16, #1, mul vl] \n\t" "add x0, x7, x3 \n\t" "add x1, x16, x2 \n\t" "sub x8, x8, #1 \n\t" BRANCH(ACOLSTORMKER) LABEL(ACOLSTORMKEREND) LABEL(ACOLSTORLEFT) "cmp x9, xzr \n\t" BEQ(UNITKDONE) "ld1d z0.d, p0/z, [x0] \n\t" "ld1d z1.d, p0/z, [x0, #1, mul vl] \n\t" "st1d z0.d, p0, [x1] \n\t" "st1d z1.d, p0, [x1, #1, mul vl] \n\t" "add x0, x0, x3 \n\t" "add x1, x1, x2 \n\t" "sub x9, x9, #1 \n\t" BRANCH(ACOLSTORLEFT) // A stored in rows. LABEL(AROWSTOR) // Prepare predicates for in-reg transpose. SVE512_IN_REG_TRANSPOSE_d8x8_PREPARE(x16,p0,p1,p2,p3,p8,p4,p6) LABEL(AROWSTORMKER) // X[10-16] for A here not P. Be careful. "cmp x8, xzr \n\t" BEQ(AROWSTORMKEREND) "add x10, x0, x4 \n\t" "add x11, x10, x4 \n\t" "add x12, x11, x4 \n\t" "add x13, x12, x4 \n\t" "add x14, x13, x4 \n\t" "add x15, x14, x4 \n\t" "add x16, x15, x4 \n\t" "ld1d z0.d, p0/z, [x0] \n\t" "ld1d z1.d, p0/z, [x10] \n\t" "ld1d z2.d, p0/z, [x11] \n\t" "ld1d z3.d, p0/z, [x12] \n\t" "ld1d z4.d, p0/z, [x13] \n\t" "ld1d z5.d, p0/z, [x14] \n\t" "ld1d z6.d, p0/z, [x15] \n\t" "ld1d z7.d, p0/z, [x16] \n\t" "add x5, x16, x4 \n\t" "add x10, x5, x4 \n\t" "add x11, x10, x4 \n\t" "add x12, x11, x4 \n\t" "add x13, x12, x4 \n\t" "add x14, x13, x4 \n\t" "add x15, x14, x4 \n\t" "add x16, x15, x4 \n\t" "ld1d z16.d, p0/z, [x5] \n\t" "ld1d z17.d, p0/z, [x10] \n\t" "ld1d z18.d, p0/z, [x11] \n\t" "ld1d z19.d, p0/z, [x12] \n\t" "ld1d z20.d, p0/z, [x13] \n\t" "ld1d z21.d, p0/z, [x14] \n\t" "ld1d z22.d, p0/z, [x15] \n\t" "ld1d z23.d, p0/z, [x16] \n\t" // Transpose first 8 rows. SVE512_IN_REG_TRANSPOSE_d8x8(z8,z9,z10,z11,z12,z13,z14,z15,z0,z1,z2,z3,z4,z5,z6,z7,p0,p1,p2,p3,p8,p4,p6) // Transpose last 8 rows. SVE512_IN_REG_TRANSPOSE_d8x8(z24,z25,z26,z27,z28,z29,z30,z31,z16,z17,z18,z19,z20,z21,z22,z23,p0,p1,p2,p3,p8,p4,p6) "add x10, x1, x2 \n\t" "add x11, x10, x2 \n\t" "add x12, x11, x2 \n\t" "add x13, x12, x2 \n\t" "add x14, x13, x2 \n\t" "add x15, x14, x2 \n\t" "add x16, x15, x2 \n\t" "st1d z8.d, p0, [x1] \n\t" "st1d z24.d, p0, [x1, #1, mul vl] \n\t" "st1d z9.d, p0, [x10] \n\t" "st1d z25.d, p0, [x10, #1, mul vl] \n\t" "st1d z10.d, p0, [x11] \n\t" "st1d z26.d, p0, [x11, #1, mul vl] \n\t" "st1d z11.d, p0, [x12] \n\t" "st1d z27.d, p0, [x12, #1, mul vl] \n\t" "st1d z12.d, p0, [x13] \n\t" "st1d z28.d, p0, [x13, #1, mul vl] \n\t" "st1d z13.d, p0, [x14] \n\t" "st1d z29.d, p0, [x14, #1, mul vl] \n\t" "st1d z14.d, p0, [x15] \n\t" "st1d z30.d, p0, [x15, #1, mul vl] \n\t" "st1d z15.d, p0, [x16] \n\t" "st1d z31.d, p0, [x16, #1, mul vl] \n\t" "add x0, x0, #64 \n\t" "add x1, x16, x2 \n\t" "sub x8, x8, #1 \n\t" BRANCH(AROWSTORMKER) LABEL(AROWSTORMKEREND) "mov x4, %[inca] \n\t" // Restore unshifted inca. "index z30.d, xzr, x4 \n\t" // Generate index. "lsl x4, x4, #3 \n\t" // Shift again. "lsl x5, x4, #3 \n\t" // Virtual column vl. LABEL(AROWSTORLEFT) "cmp x9, xzr \n\t" BEQ(UNITKDONE) "add x6, x0, x5 \n\t" "ld1d z0.d, p0/z, [x0, z30.d, lsl #3] \n\t" "ld1d z1.d, p0/z, [x6, z30.d, lsl #3] \n\t" "st1d z0.d, p0, [x1] \n\t" "st1d z1.d, p0, [x1, #1, mul vl] \n\t" "add x1, x1, x2 \n\t" "add x0, x0, #8 \n\t" "sub x9, x9, #1 \n\t" BRANCH(AROWSTORLEFT) LABEL(UNITKDONE) "mov x0, #0 \n\t" : : [a] "r" (a), [p] "r" (p), [lda] "r" (lda), [ldp] "r" (ldp), [inca] "r" (inca), [n_mker] "r" (n_mker), [n_left] "r" (n_left) : "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10","x11","x12","x13","x14","x15", "x16","x17","x18", "z0", "z1", "z2", "z3", "z4", "z5", "z6", "z7", "z8", "z9", "z10","z11","z12","z13","z14","z15", // "z16","z17","z18","z19","z20","z21","z22","z23", // "z24","z25","z26","z27","z28","z29","z30","z31", "p0", "p1", "p2", "p3", "p4", "p5", "p6", "p7" ); } else // if ( cdim < mnr ) { bli_dscal2m_ex ( 0, BLIS_NONUNIT_DIAG, BLIS_DENSE, ( trans_t )conja, cdim, n, kappa, a, inca, lda, p, 1, ldp, cntx, NULL ); // if ( cdim < mnr ) { const dim_t i = cdim; const dim_t m_edge = mnr - i; const dim_t n_edge = n_max; double* restrict p_edge = p + (i )*1; bli_dset0s_mxn ( m_edge, n_edge, p_edge, 1, ldp ); } } if ( n < n_max ) { const dim_t j = n; const dim_t m_edge = mnr; const dim_t n_edge = n_max - j; double* restrict p_edge = p + (j )*ldp; bli_dset0s_mxn ( m_edge, n_edge, p_edge, 1, ldp ); } } blis-0.9.0/kernels/armsve/1m/old/000077500000000000000000000000001422157504600165125ustar00rootroot00000000000000blis-0.9.0/kernels/armsve/1m/old/bli_dpackm_armsve512_int_12xk.c000066400000000000000000000326531422157504600243000ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2020, Linaro Limited 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include #if !defined(BLIS_FAMILY_A64FX) #include // assumption: // SVE vector length = 512 bits. // TODO: // 2-rows -> 3 vectors packing and use predicator only in odd num of rows to be packed. // prefetching is needed. void bli_dpackm_armsve512_int_12xk ( conj_t conja, pack_t schema, dim_t cdim_, dim_t n_, dim_t n_max_, double* restrict kappa, double* restrict a, inc_t inca_, inc_t lda_, double* restrict p, inc_t ldp_, cntx_t* restrict cntx ) { const int64_t cdim = cdim_; const int64_t mnr = 12; const int64_t n = n_; const int64_t n_max = n_max_; const int64_t inca = inca_; const int64_t lda = lda_; const int64_t ldp = ldp_; double* restrict alpha1 = a; double* restrict alpha1_8 = alpha1 + 8 * inca; double* restrict alpha1_p4 = alpha1 + 4 * inca; double* restrict alpha1_m4 = alpha1 - 4 * inca; double* restrict pi1 = p; const svbool_t all_active = svptrue_b64(); const svbool_t first_half_active = svwhilelt_b64(0, 4); const svbool_t last_half_active = svnot_z(all_active, first_half_active); svfloat64_t z_a0; svfloat64_t z_a8; svfloat64_t z_a8_lh; svfloat64_t z_a16; svuint64_t z_index; // creating index for gather/scatter // with each element as: 0, 1*inca, 2*inca, 3*inca z_index = svindex_u64( 0, inca * sizeof( double ) ); if ( cdim == mnr ) { if ( bli_deq1( *kappa ) ) { if ( inca == 1 ) // continous memory. packA style { dim_t k = n; // 2 pack into 3 case. if ( ldp == mnr ) { for ( ; k > 1; k -= 2 ) { // load 12 continuous elments from *a z_a0 = svld1_f64( all_active, alpha1 ); z_a8 = svld1_vnum_f64( first_half_active, alpha1, 1 ); // forward address - 0 to 1 alpha1 += lda; alpha1_p4 = alpha1 + 4 * inca; alpha1_m4 = alpha1 - 4 * inca; // load 12 continuous elments from *a, filling last half of z8. z_a8_lh = svld1_f64( last_half_active, alpha1_m4 ); z_a8 = svadd_f64_z( all_active, z_a8, z_a8_lh ); z_a16 = svld1_f64( all_active, alpha1_p4 ); // stored packed data into *p svst1_f64( all_active, pi1, z_a0 ); svst1_vnum_f64( all_active, pi1, 1, z_a8 ); svst1_vnum_f64( all_active, pi1, 2, z_a16 ); // forward address - 1 to 0 alpha1 += lda; alpha1_8 = alpha1 + 8 * inca; pi1 += 2 * ldp; } } // line-by-line packing case. for ( ; k != 0; --k ) { // load 12 continuous elments from *a z_a0 = svld1_f64( all_active, alpha1 ); z_a8 = svld1_vnum_f64( first_half_active, alpha1, 1 ); // store them into *p svst1_f64( all_active, pi1, z_a0 ); svst1_vnum_f64( first_half_active, pi1, 1, z_a8 ); alpha1 += lda; alpha1_8 = alpha1 + 8 * inca; pi1 += ldp; } } else // gather/scatter load/store. packB style { dim_t k = n; if ( ldp == mnr ) { for ( ; k > 1; k -= 2 ) { // gather load from *a z_a0 = svld1_gather_u64offset_f64( all_active, alpha1, z_index ); z_a8 = svld1_gather_u64offset_f64( first_half_active, alpha1_8, z_index ); // forward address - 0 to 1 alpha1 += lda; alpha1_p4 = alpha1 + 4 * inca; alpha1_m4 = alpha1 - 4 * inca; // gather load from *a, filling last half of z8. z_a8_lh = svld1_gather_u64offset_f64( last_half_active, alpha1_m4, z_index ); z_a8 = svadd_f64_z( all_active, z_a8, z_a8_lh ); z_a16 = svld1_gather_u64offset_f64( all_active, alpha1_p4, z_index ); // stored packed data into *p svst1_f64( all_active, pi1, z_a0 ); svst1_vnum_f64( all_active, pi1, 1, z_a8 ); svst1_vnum_f64( all_active, pi1, 2, z_a16 ); // forward address - 1 to 0 alpha1 += lda; alpha1_8 = alpha1 + 8 * inca; pi1 += 2 * ldp; } } for ( ; k != 0; --k ) { // gather load from *a z_a0 = svld1_gather_u64offset_f64( all_active, alpha1, z_index ); z_a8 = svld1_gather_u64offset_f64( first_half_active, alpha1_8, z_index ); // scatter store into *p svst1_f64( all_active, pi1, z_a0 ); svst1_vnum_f64( first_half_active, pi1, 1, z_a8 ); alpha1 += lda; alpha1_8 = alpha1 + 8 * inca; pi1 += ldp; } } } else // *kappa != 1.0 { // load kappa into vector svfloat64_t z_kappa; z_kappa = svdup_f64( *kappa ); if ( inca == 1 ) // continous memory. packA style { dim_t k = n; if ( ldp == mnr ) { for ( ; k > 1; k -= 2 ) { // load 12 continuous elments from *a z_a0 = svld1_f64( all_active, alpha1 ); z_a8 = svld1_vnum_f64( first_half_active, alpha1, 1 ); // forward address - 0 to 1 alpha1 += lda; alpha1_p4 = alpha1 + 4 * inca; alpha1_m4 = alpha1 - 4 * inca; // load 12 continuous elments from *a, filling last half of z8. z_a8_lh = svld1_f64( last_half_active, alpha1_m4 ); z_a8 = svadd_f64_z( all_active, z_a8, z_a8_lh ); z_a16 = svld1_f64( all_active, alpha1_p4 ); // multiply by *kappa z_a0 = svmul_lane_f64( z_a0, z_kappa, 0 ); z_a8 = svmul_lane_f64( z_a8, z_kappa, 0 ); z_a16 = svmul_lane_f64( z_a16, z_kappa, 0 ); // stored packed data into *p svst1_f64( all_active, pi1, z_a0 ); svst1_vnum_f64( all_active, pi1, 1, z_a8 ); svst1_vnum_f64( all_active, pi1, 2, z_a16 ); // forward address - 1 to 0 alpha1 += lda; alpha1_8 = alpha1 + 8 * inca; pi1 += 2 * ldp; } } for ( ; k != 0; --k ) { // load 12 continuous elments from *a z_a0 = svld1_f64( all_active, alpha1 ); z_a8 = svld1_vnum_f64( first_half_active, alpha1, 1 ); // multiply by *kappa z_a0 = svmul_lane_f64( z_a0, z_kappa, 0 ); z_a8 = svmul_lane_f64( z_a8, z_kappa, 0 ); // store them into *p svst1_f64( all_active, pi1, z_a0 ); svst1_vnum_f64( first_half_active, pi1, 1, z_a8 ); alpha1 += lda; alpha1_8 = alpha1 + 8 * inca; pi1 += ldp; } } else // gather/scatter load/store. packB style { dim_t k = n; if ( ldp == mnr ) { for ( ; k > 1; k -= 2 ) { // gather load from *a z_a0 = svld1_gather_u64offset_f64( all_active, alpha1, z_index ); z_a8 = svld1_gather_u64offset_f64( first_half_active, alpha1_8, z_index ); // forward address - 0 to 1 alpha1 += lda; alpha1_p4 = alpha1 + 4 * inca; alpha1_m4 = alpha1 - 4 * inca; // gather load from *a, filling last half of z8. z_a8_lh = svld1_gather_u64offset_f64( last_half_active, alpha1_m4, z_index ); z_a8 = svadd_f64_z( all_active, z_a8, z_a8_lh ); z_a16 = svld1_gather_u64offset_f64( all_active, alpha1_p4, z_index ); // multiply by *kappa z_a0 = svmul_lane_f64( z_a0, z_kappa, 0 ); z_a8 = svmul_lane_f64( z_a8, z_kappa, 0 ); z_a16 = svmul_lane_f64( z_a16, z_kappa, 0 ); // stored packed data into *p svst1_f64( all_active, pi1, z_a0 ); svst1_vnum_f64( all_active, pi1, 1, z_a8 ); svst1_vnum_f64( all_active, pi1, 2, z_a16 ); // forward address - 1 to 0 alpha1 += lda; alpha1_8 = alpha1 + 8 * inca; pi1 += 2 * ldp; } } for ( ; k != 0; --k ) { // gather load from *a z_a0 = svld1_gather_u64offset_f64( all_active, alpha1, z_index ); z_a8 = svld1_gather_u64offset_f64( first_half_active, alpha1_8, z_index ); // multiply by *kappa z_a0 = svmul_lane_f64( z_a0, z_kappa, 0 ); z_a8 = svmul_lane_f64( z_a8, z_kappa, 0 ); // scatter store into *p svst1_f64( all_active, pi1, z_a0 ); svst1_vnum_f64( first_half_active, pi1, 1, z_a8 ); alpha1 += lda; alpha1_8 = alpha1 + 8 * inca; pi1 += ldp; } } } // end of if ( *kappa == 1.0 ) } else // if ( cdim < mnr ) { bli_dscal2m_ex ( 0, BLIS_NONUNIT_DIAG, BLIS_DENSE, ( trans_t )conja, cdim, n, kappa, a, inca, lda, p, 1, ldp, cntx, NULL ); // if ( cdim < mnr ) { const dim_t i = cdim; const dim_t m_edge = mnr - i; const dim_t n_edge = n_max; double* restrict p_edge = p + (i )*1; bli_dset0s_mxn ( m_edge, n_edge, p_edge, 1, ldp ); } } if ( n < n_max ) { const dim_t j = n; const dim_t m_edge = mnr; const dim_t n_edge = n_max - j; double* restrict p_edge = p + (j )*ldp; bli_dset0s_mxn ( m_edge, n_edge, p_edge, 1, ldp ); } } #endif // __has_include() blis-0.9.0/kernels/armsve/3/000077500000000000000000000000001422157504600155615ustar00rootroot00000000000000blis-0.9.0/kernels/armsve/3/armsve_asm_2vx10.h000066400000000000000000000314141422157504600210320ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2020, The University of Tokyo 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #define GEMM_2VX10_MKER_LOOP_PLAIN_C_1(C0FH,C1FH,C2FH,C3FH,C4FH,C5FH,C6FH,C7FH,C8FH,C9FH,C0LH,C1LH,C2LH,C3LH,C4LH,C5LH,C6LH,C7LH,C8LH,C9LH,PT,ACOLFH,ACOLLH,BV0,BV1,BV2,BV3,BV4,BV5,BV6,BV7,BADDR,BRSBIT) \ GEMM_FMLA2_LD1R(C0FH,C0LH,PT,ACOLFH,ACOLLH,BV0,BADDR,8) \ GEMM_FMLA2_LD1R(C1FH,C1LH,PT,ACOLFH,ACOLLH,BV1,BADDR,9) \ " add "#BADDR", "#BRSBIT", "#BADDR" \n\t" /* B address forward */ \ GEMM_FMLA2_LD1R(C2FH,C2LH,PT,ACOLFH,ACOLLH,BV2,BADDR,0) \ GEMM_FMLA2_LD1R(C3FH,C3LH,PT,ACOLFH,ACOLLH,BV3,BADDR,1) \ GEMM_FMLA2_LD1R(C4FH,C4LH,PT,ACOLFH,ACOLLH,BV4,BADDR,2) \ GEMM_FMLA2_LD1R(C5FH,C5LH,PT,ACOLFH,ACOLLH,BV5,BADDR,3) \ GEMM_FMLA2_LD1R(C6FH,C6LH,PT,ACOLFH,ACOLLH,BV6,BADDR,4) \ GEMM_FMLA2_LD1R(C7FH,C7LH,PT,ACOLFH,ACOLLH,BV7,BADDR,5) \ \ GEMM_FMLA2_LD1R(C8FH,C8LH,PT,ACOLFH,ACOLLH,BV0,BADDR,6) \ GEMM_FMLA2_LD1R(C9FH,C9LH,PT,ACOLFH,ACOLLH,BV1,BADDR,7) // Second through forth microkernels are the first one with B vectors rotated. #define GEMM_2VX10_MKER_LOOP_PLAIN_C_2(C0FH,C1FH,C2FH,C3FH,C4FH,C5FH,C6FH,C7FH,C8FH,C9FH,C0LH,C1LH,C2LH,C3LH,C4LH,C5LH,C6LH,C7LH,C8LH,C9LH,PT,ACOLFH,ACOLLH,BV0,BV1,BV2,BV3,BV4,BV5,BV6,BV7,BADDR,BRSBIT) \ GEMM_2VX10_MKER_LOOP_PLAIN_C_1(C0FH,C1FH,C2FH,C3FH,C4FH,C5FH,C6FH,C7FH,C8FH,C9FH,C0LH,C1LH,C2LH,C3LH,C4LH,C5LH,C6LH,C7LH,C8LH,C9LH,PT,ACOLFH,ACOLLH,BV2,BV3,BV4,BV5,BV6,BV7,BV0,BV1,BADDR,BRSBIT) #define GEMM_2VX10_MKER_LOOP_PLAIN_C_3(C0FH,C1FH,C2FH,C3FH,C4FH,C5FH,C6FH,C7FH,C8FH,C9FH,C0LH,C1LH,C2LH,C3LH,C4LH,C5LH,C6LH,C7LH,C8LH,C9LH,PT,ACOLFH,ACOLLH,BV0,BV1,BV2,BV3,BV4,BV5,BV6,BV7,BADDR,BRSBIT) \ GEMM_2VX10_MKER_LOOP_PLAIN_C_1(C0FH,C1FH,C2FH,C3FH,C4FH,C5FH,C6FH,C7FH,C8FH,C9FH,C0LH,C1LH,C2LH,C3LH,C4LH,C5LH,C6LH,C7LH,C8LH,C9LH,PT,ACOLFH,ACOLLH,BV4,BV5,BV6,BV7,BV0,BV1,BV2,BV3,BADDR,BRSBIT) #define GEMM_2VX10_MKER_LOOP_PLAIN_C_4(C0FH,C1FH,C2FH,C3FH,C4FH,C5FH,C6FH,C7FH,C8FH,C9FH,C0LH,C1LH,C2LH,C3LH,C4LH,C5LH,C6LH,C7LH,C8LH,C9LH,PT,ACOLFH,ACOLLH,BV0,BV1,BV2,BV3,BV4,BV5,BV6,BV7,BADDR,BRSBIT) \ GEMM_2VX10_MKER_LOOP_PLAIN_C_1(C0FH,C1FH,C2FH,C3FH,C4FH,C5FH,C6FH,C7FH,C8FH,C9FH,C0LH,C1LH,C2LH,C3LH,C4LH,C5LH,C6LH,C7LH,C8LH,C9LH,PT,ACOLFH,ACOLLH,BV6,BV7,BV0,BV1,BV2,BV3,BV4,BV5,BADDR,BRSBIT) // NOTE: // The microkernel (PLAIN_1-4 as a whole) satisfies on entry/exit // (sth. akin to loop-invariant): // - BV[0-7] holds B[0:7, 4*k_cur] // - B's address stops at B[0, 4*k_cur+1] // Final loop inside K=4 microkernels. #define GEMM_2VX10_MKER_LOOP_PLAIN_C_4_RESIDUAL(C0FH,C1FH,C2FH,C3FH,C4FH,C5FH,C6FH,C7FH,C8FH,C9FH,C0LH,C1LH,C2LH,C3LH,C4LH,C5LH,C6LH,C7LH,C8LH,C9LH,PT,ACOLFH,ACOLLH,BV0,BV1,BV2,BV3,BV4,BV5,BV6,BV7,BADDR,BRSBIT) \ GEMM_FMLA2_LD1R(C0FH,C0LH,PT,ACOLFH,ACOLLH,BV6,BADDR,8) \ GEMM_FMLA2_LD1R(C1FH,C1LH,PT,ACOLFH,ACOLLH,BV7,BADDR,9) \ " add "#BADDR", "#BRSBIT", "#BADDR" \n\t" /* B address forward */ \ GEMM_FMLA2(C2FH,C2LH,PT,ACOLFH,ACOLLH,BV0) \ GEMM_FMLA2(C3FH,C3LH,PT,ACOLFH,ACOLLH,BV1) \ GEMM_FMLA2(C4FH,C4LH,PT,ACOLFH,ACOLLH,BV2) \ GEMM_FMLA2(C5FH,C5LH,PT,ACOLFH,ACOLLH,BV3) \ GEMM_FMLA2(C6FH,C6LH,PT,ACOLFH,ACOLLH,BV4) \ GEMM_FMLA2(C7FH,C7LH,PT,ACOLFH,ACOLLH,BV5) \ GEMM_FMLA2(C8FH,C8LH,PT,ACOLFH,ACOLLH,BV6) \ GEMM_FMLA2(C9FH,C9LH,PT,ACOLFH,ACOLLH,BV7) // K=4 MKer loop with B memory scattered. #define GEMM_2VX10_MKER_LOOP_PLAIN_G_1(C0FH,C1FH,C2FH,C3FH,C4FH,C5FH,C6FH,C7FH,C8FH,C9FH,C0LH,C1LH,C2LH,C3LH,C4LH,C5LH,C6LH,C7LH,C8LH,C9LH,PT,ACOLFH,ACOLLH,BV0,BV1,BV2,BV3,BV4,BV5,BV6,BV7,BADDR,BELMADDR,BRSBIT,BCSBIT) \ GEMM_FMLA2_LD1R_G_ELMFWD(C0FH,C0LH,PT,ACOLFH,ACOLLH,BV0,BELMADDR,BCSBIT) \ GEMM_FMLA2_LD1R_G_ELMFWD(C1FH,C1LH,PT,ACOLFH,ACOLLH,BV1,BELMADDR,BCSBIT) \ " add "#BADDR", "#BRSBIT", "#BADDR" \n\t" /* B address forward */ \ " mov "#BELMADDR", "#BADDR" \n\t" \ GEMM_FMLA2_LD1R_G_ELMFWD(C2FH,C2LH,PT,ACOLFH,ACOLLH,BV2,BELMADDR,BCSBIT) \ GEMM_FMLA2_LD1R_G_ELMFWD(C3FH,C3LH,PT,ACOLFH,ACOLLH,BV3,BELMADDR,BCSBIT) \ GEMM_FMLA2_LD1R_G_ELMFWD(C4FH,C4LH,PT,ACOLFH,ACOLLH,BV4,BELMADDR,BCSBIT) \ GEMM_FMLA2_LD1R_G_ELMFWD(C5FH,C5LH,PT,ACOLFH,ACOLLH,BV5,BELMADDR,BCSBIT) \ GEMM_FMLA2_LD1R_G_ELMFWD(C6FH,C6LH,PT,ACOLFH,ACOLLH,BV6,BELMADDR,BCSBIT) \ GEMM_FMLA2_LD1R_G_ELMFWD(C7FH,C7LH,PT,ACOLFH,ACOLLH,BV7,BELMADDR,BCSBIT) \ \ GEMM_FMLA2_LD1R_G_ELMFWD(C8FH,C8LH,PT,ACOLFH,ACOLLH,BV0,BELMADDR,BCSBIT) \ GEMM_FMLA2_LD1R_G_ELMFWD(C9FH,C9LH,PT,ACOLFH,ACOLLH,BV1,BELMADDR,BCSBIT) #define GEMM_2VX10_MKER_LOOP_PLAIN_G_2(C0FH,C1FH,C2FH,C3FH,C4FH,C5FH,C6FH,C7FH,C8FH,C9FH,C0LH,C1LH,C2LH,C3LH,C4LH,C5LH,C6LH,C7LH,C8LH,C9LH,PT,ACOLFH,ACOLLH,BV0,BV1,BV2,BV3,BV4,BV5,BV6,BV7,BADDR,BELMADDR,BRSBIT,BCSBIT) \ GEMM_2VX10_MKER_LOOP_PLAIN_G_1(C0FH,C1FH,C2FH,C3FH,C4FH,C5FH,C6FH,C7FH,C8FH,C9FH,C0LH,C1LH,C2LH,C3LH,C4LH,C5LH,C6LH,C7LH,C8LH,C9LH,PT,ACOLFH,ACOLLH,BV2,BV3,BV4,BV5,BV6,BV7,BV0,BV1,BADDR,BELMADDR,BRSBIT,BCSBIT) #define GEMM_2VX10_MKER_LOOP_PLAIN_G_3(C0FH,C1FH,C2FH,C3FH,C4FH,C5FH,C6FH,C7FH,C8FH,C9FH,C0LH,C1LH,C2LH,C3LH,C4LH,C5LH,C6LH,C7LH,C8LH,C9LH,PT,ACOLFH,ACOLLH,BV0,BV1,BV2,BV3,BV4,BV5,BV6,BV7,BADDR,BELMADDR,BRSBIT,BCSBIT) \ GEMM_2VX10_MKER_LOOP_PLAIN_G_1(C0FH,C1FH,C2FH,C3FH,C4FH,C5FH,C6FH,C7FH,C8FH,C9FH,C0LH,C1LH,C2LH,C3LH,C4LH,C5LH,C6LH,C7LH,C8LH,C9LH,PT,ACOLFH,ACOLLH,BV4,BV5,BV6,BV7,BV0,BV1,BV2,BV3,BADDR,BELMADDR,BRSBIT,BCSBIT) #define GEMM_2VX10_MKER_LOOP_PLAIN_G_4(C0FH,C1FH,C2FH,C3FH,C4FH,C5FH,C6FH,C7FH,C8FH,C9FH,C0LH,C1LH,C2LH,C3LH,C4LH,C5LH,C6LH,C7LH,C8LH,C9LH,PT,ACOLFH,ACOLLH,BV0,BV1,BV2,BV3,BV4,BV5,BV6,BV7,BADDR,BELMADDR,BRSBIT,BCSBIT) \ GEMM_2VX10_MKER_LOOP_PLAIN_G_1(C0FH,C1FH,C2FH,C3FH,C4FH,C5FH,C6FH,C7FH,C8FH,C9FH,C0LH,C1LH,C2LH,C3LH,C4LH,C5LH,C6LH,C7LH,C8LH,C9LH,PT,ACOLFH,ACOLLH,BV6,BV7,BV0,BV1,BV2,BV3,BV4,BV5,BADDR,BELMADDR,BRSBIT,BCSBIT) #define GEMM_2VX10_MKER_LOOP_PLAIN_G_4_RESIDUAL(C0FH,C1FH,C2FH,C3FH,C4FH,C5FH,C6FH,C7FH,C8FH,C9FH,C0LH,C1LH,C2LH,C3LH,C4LH,C5LH,C6LH,C7LH,C8LH,C9LH,PT,ACOLFH,ACOLLH,BV0,BV1,BV2,BV3,BV4,BV5,BV6,BV7,BADDR,BELMADDR,BRSBIT,BCSBIT) \ GEMM_FMLA2_LD1R_G_ELMFWD(C0FH,C0LH,PT,ACOLFH,ACOLLH,BV6,BELMADDR,BCSBIT) \ GEMM_FMLA2_LD1R_G_ELMFWD(C1FH,C1LH,PT,ACOLFH,ACOLLH,BV7,BELMADDR,BCSBIT) \ " add "#BADDR", "#BRSBIT", "#BADDR" \n\t" /* B address forward */ \ " mov "#BELMADDR", "#BADDR" \n\t" \ GEMM_FMLA2(C2FH,C2LH,PT,ACOLFH,ACOLLH,BV0) \ GEMM_FMLA2(C3FH,C3LH,PT,ACOLFH,ACOLLH,BV1) \ GEMM_FMLA2(C4FH,C4LH,PT,ACOLFH,ACOLLH,BV2) \ GEMM_FMLA2(C5FH,C5LH,PT,ACOLFH,ACOLLH,BV3) \ GEMM_FMLA2(C6FH,C6LH,PT,ACOLFH,ACOLLH,BV4) \ GEMM_FMLA2(C7FH,C7LH,PT,ACOLFH,ACOLLH,BV5) \ GEMM_FMLA2(C8FH,C8LH,PT,ACOLFH,ACOLLH,BV6) \ GEMM_FMLA2(C9FH,C9LH,PT,ACOLFH,ACOLLH,BV7) #define CLEAR_COL20(Z00,Z01,Z02,Z03,Z04,Z05,Z06,Z07,Z08,Z09,Z10,Z11,Z12,Z13,Z14,Z15,Z16,Z17,Z18,Z19) \ CLEAR_COL4(Z00,Z01,Z02,Z03) \ CLEAR_COL4(Z04,Z05,Z06,Z07) \ CLEAR_COL4(Z08,Z09,Z10,Z11) \ CLEAR_COL4(Z12,Z13,Z14,Z15) \ CLEAR_COL4(Z16,Z17,Z18,Z19) #define SCALE_COL20(Z00,Z01,Z02,Z03,Z04,Z05,Z06,Z07,Z08,Z09,Z10,Z11,Z12,Z13,Z14,Z15,Z16,Z17,Z18,Z19,ZFACTOR) \ SCALE_COL4(Z00,Z01,Z02,Z03,ZFACTOR) \ SCALE_COL4(Z04,Z05,Z06,Z07,ZFACTOR) \ SCALE_COL4(Z08,Z09,Z10,Z11,ZFACTOR) \ SCALE_COL4(Z12,Z13,Z14,Z15,ZFACTOR) \ SCALE_COL4(Z16,Z17,Z18,Z19,ZFACTOR) #define GEMM_C_FMLA_UKER(C0FH,C1FH,C2FH,C3FH,C4FH,C0LH,C1LH,C2LH,C3LH,C4LH,PT,Z0FH,Z1FH,Z2FH,Z3FH,Z4FH,Z0LH,Z1LH,Z2LH,Z3LH,Z4LH,ZSCALE) \ GEMM_FMLA2(C0FH,C0LH,PT,Z0FH,Z0LH,ZSCALE) \ GEMM_FMLA2(C1FH,C1LH,PT,Z1FH,Z1LH,ZSCALE) \ GEMM_FMLA2(C2FH,C2LH,PT,Z2FH,Z2LH,ZSCALE) \ GEMM_FMLA2(C3FH,C3LH,PT,Z3FH,Z3LH,ZSCALE) \ GEMM_FMLA2(C4FH,C4LH,PT,Z4FH,Z4LH,ZSCALE) #define GEMM_C_FMAD_UKER(Z0FH,Z1FH,Z2FH,Z3FH,Z4FH,Z0LH,Z1LH,Z2LH,Z3LH,Z4LH,PFH,PLH,C0FH,C1FH,C2FH,C3FH,C4FH,C0LH,C1LH,C2LH,C3LH,C4LH,ZSCALE) \ GEMM_CCOL_FMAD(Z0FH,Z0LH,PFH,PLH,C0FH,C0LH,ZSCALE) \ GEMM_CCOL_FMAD(Z1FH,Z1LH,PFH,PLH,C1FH,C1LH,ZSCALE) \ GEMM_CCOL_FMAD(Z2FH,Z2LH,PFH,PLH,C2FH,C2LH,ZSCALE) \ GEMM_CCOL_FMAD(Z3FH,Z3LH,PFH,PLH,C3FH,C3LH,ZSCALE) \ GEMM_CCOL_FMAD(Z4FH,Z4LH,PFH,PLH,C4FH,C4LH,ZSCALE) #define GEMM_C_LOAD_UKER_C(Z0FH,Z1FH,Z2FH,Z3FH,Z4FH,Z0LH,Z1LH,Z2LH,Z3LH,Z4LH,PFH,PLH,CADDR,CCS) \ GEMM_CCOL_CONTIGUOUS_LOAD_FWD(Z0FH,Z0LH,PFH,PLH,CADDR,CCS) \ GEMM_CCOL_CONTIGUOUS_LOAD_FWD(Z1FH,Z1LH,PFH,PLH,CADDR,CCS) \ GEMM_CCOL_CONTIGUOUS_LOAD_FWD(Z2FH,Z2LH,PFH,PLH,CADDR,CCS) \ GEMM_CCOL_CONTIGUOUS_LOAD_FWD(Z3FH,Z3LH,PFH,PLH,CADDR,CCS) \ GEMM_CCOL_CONTIGUOUS_LOAD_FWD(Z4FH,Z4LH,PFH,PLH,CADDR,CCS) #define GEMM_C_STORE_UKER_C(Z0FH,Z1FH,Z2FH,Z3FH,Z4FH,Z0LH,Z1LH,Z2LH,Z3LH,Z4LH,PFH,PLH,CADDR,CCS) \ GEMM_CCOL_CONTIGUOUS_STORE_FWD(Z0FH,Z0LH,PFH,PLH,CADDR,CCS) \ GEMM_CCOL_CONTIGUOUS_STORE_FWD(Z1FH,Z1LH,PFH,PLH,CADDR,CCS) \ GEMM_CCOL_CONTIGUOUS_STORE_FWD(Z2FH,Z2LH,PFH,PLH,CADDR,CCS) \ GEMM_CCOL_CONTIGUOUS_STORE_FWD(Z3FH,Z3LH,PFH,PLH,CADDR,CCS) \ GEMM_CCOL_CONTIGUOUS_STORE_FWD(Z4FH,Z4LH,PFH,PLH,CADDR,CCS) #define GEMM_C_FMAD_LOAD_UKER_C(Z0FH,Z1FH,Z2FH,Z3FH,Z4FH,Z0LH,Z1LH,Z2LH,Z3LH,Z4LH,PFH,PLH,C0FH,C1FH,C2FH,C3FH,C4FH,C0LH,C1LH,C2LH,C3LH,C4LH,ZSCALE,CADDR,CCS) \ GEMM_CCOL_FMAD(Z0FH,Z0LH,PFH,PLH,C0FH,C0LH,ZSCALE) \ GEMM_CCOL_CONTIGUOUS_LOAD_FWD(C0FH,C0LH,PFH,PLH,CADDR,CCS) \ GEMM_CCOL_FMAD(Z1FH,Z1LH,PFH,PLH,C1FH,C1LH,ZSCALE) \ GEMM_CCOL_CONTIGUOUS_LOAD_FWD(C1FH,C1LH,PFH,PLH,CADDR,CCS) \ GEMM_CCOL_FMAD(Z2FH,Z2LH,PFH,PLH,C2FH,C2LH,ZSCALE) \ GEMM_CCOL_CONTIGUOUS_LOAD_FWD(C2FH,C2LH,PFH,PLH,CADDR,CCS) \ GEMM_CCOL_FMAD(Z3FH,Z3LH,PFH,PLH,C3FH,C3LH,ZSCALE) \ GEMM_CCOL_CONTIGUOUS_LOAD_FWD(C3FH,C3LH,PFH,PLH,CADDR,CCS) \ GEMM_CCOL_FMAD(Z4FH,Z4LH,PFH,PLH,C4FH,C4LH,ZSCALE) \ GEMM_CCOL_CONTIGUOUS_LOAD_FWD(C4FH,C4LH,PFH,PLH,CADDR,CCS) #define GEMM_C_LOAD_UKER_G(Z0FH,Z1FH,Z2FH,Z3FH,Z4FH,Z0LH,Z1LH,Z2LH,Z3LH,Z4LH,ZIDX,PFH,PLH,CADDR,CCS,CVSKIP,CTEMP) \ GEMM_CCOL_GATHER_LOAD_FWD(Z0FH,Z0LH,ZIDX,PFH,PLH,CADDR,CCS,CVSKIP,CTEMP) \ GEMM_CCOL_GATHER_LOAD_FWD(Z1FH,Z1LH,ZIDX,PFH,PLH,CADDR,CCS,CVSKIP,CTEMP) \ GEMM_CCOL_GATHER_LOAD_FWD(Z2FH,Z2LH,ZIDX,PFH,PLH,CADDR,CCS,CVSKIP,CTEMP) \ GEMM_CCOL_GATHER_LOAD_FWD(Z3FH,Z3LH,ZIDX,PFH,PLH,CADDR,CCS,CVSKIP,CTEMP) \ GEMM_CCOL_GATHER_LOAD_FWD(Z4FH,Z4LH,ZIDX,PFH,PLH,CADDR,CCS,CVSKIP,CTEMP) #define GEMM_C_STORE_UKER_G(Z0FH,Z1FH,Z2FH,Z3FH,Z4FH,Z0LH,Z1LH,Z2LH,Z3LH,Z4LH,ZIDX,PFH,PLH,CADDR,CCS,CVSKIP,CTEMP) \ GEMM_CCOL_SCATTER_STORE_FWD(Z0FH,Z0LH,ZIDX,PFH,PLH,CADDR,CCS,CVSKIP,CTEMP) \ GEMM_CCOL_SCATTER_STORE_FWD(Z1FH,Z1LH,ZIDX,PFH,PLH,CADDR,CCS,CVSKIP,CTEMP) \ GEMM_CCOL_SCATTER_STORE_FWD(Z2FH,Z2LH,ZIDX,PFH,PLH,CADDR,CCS,CVSKIP,CTEMP) \ GEMM_CCOL_SCATTER_STORE_FWD(Z3FH,Z3LH,ZIDX,PFH,PLH,CADDR,CCS,CVSKIP,CTEMP) \ GEMM_CCOL_SCATTER_STORE_FWD(Z4FH,Z4LH,ZIDX,PFH,PLH,CADDR,CCS,CVSKIP,CTEMP) #define GEMM_C_FMAD_LOAD_UKER_G(Z0FH,Z1FH,Z2FH,Z3FH,Z4FH,Z0LH,Z1LH,Z2LH,Z3LH,Z4LH,PFH,PLH,C0FH,C1FH,C2FH,C3FH,C4FH,C0LH,C1LH,C2LH,C3LH,C4LH,ZSCALE,ZIDX,CADDR,CCS,CVSKIP,CTEMP) \ GEMM_CCOL_FMAD(Z0FH,Z0LH,PFH,PLH,C0FH,C0LH,ZSCALE) \ GEMM_CCOL_GATHER_LOAD_FWD(C0FH,C0LH,ZIDX,PFH,PLH,CADDR,CCS,CVSKIP,CTEMP) \ GEMM_CCOL_FMAD(Z1FH,Z1LH,PFH,PLH,C1FH,C1LH,ZSCALE) \ GEMM_CCOL_GATHER_LOAD_FWD(C1FH,C1LH,ZIDX,PFH,PLH,CADDR,CCS,CVSKIP,CTEMP) \ GEMM_CCOL_FMAD(Z2FH,Z2LH,PFH,PLH,C2FH,C2LH,ZSCALE) \ GEMM_CCOL_GATHER_LOAD_FWD(C2FH,C2LH,ZIDX,PFH,PLH,CADDR,CCS,CVSKIP,CTEMP) \ GEMM_CCOL_FMAD(Z3FH,Z3LH,PFH,PLH,C3FH,C3LH,ZSCALE) \ GEMM_CCOL_GATHER_LOAD_FWD(C3FH,C3LH,ZIDX,PFH,PLH,CADDR,CCS,CVSKIP,CTEMP) \ GEMM_CCOL_FMAD(Z4FH,Z4LH,PFH,PLH,C4FH,C4LH,ZSCALE) \ GEMM_CCOL_GATHER_LOAD_FWD(C4FH,C4LH,ZIDX,PFH,PLH,CADDR,CCS,CVSKIP,CTEMP) blis-0.9.0/kernels/armsve/3/armsve_asm_2vx10cmplx.h000066400000000000000000000163001422157504600220730ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2020, The University of Tokyo 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #define GEMM_2VX10CMPLX_MKER_LOOP_PLAIN_C_1(C0Re,C1Re,C2Re,C3Re,C4Re,C5Re,C6Re,C7Re,C8Re,C9Re,C0Im,C1Im,C2Im,C3Im,C4Im,C5Im,C6Im,C7Im,C8Im,C9Im,PT,AColRe,AColIm,BV0,BV1,BV2,BV3,BV4,BV5,BV6,BV7,BAddr,BRSBit) \ GEMM_FMLA2_LD1R(C0Re,C0Im,PT,AColRe,AColIm,BV0,BAddr,16) \ GEMM_FMLA2_LD1R(C1Re,C1Im,PT,AColRe,AColIm,BV1,BAddr,18) \ GEMM_FMLA2_LD1R(C2Re,C2Im,PT,AColRe,AColIm,BV2,BAddr,1) \ GEMM_FMLA2_LD1R(C3Re,C3Im,PT,AColRe,AColIm,BV3,BAddr,3) \ GEMM_FMLA2_LD1R(C4Re,C4Im,PT,AColRe,AColIm,BV4,BAddr,5) \ GEMM_FMLA2_LD1R(C5Re,C5Im,PT,AColRe,AColIm,BV5,BAddr,7) \ GEMM_FMLA2_LD1R(C6Re,C6Im,PT,AColRe,AColIm,BV6,BAddr,9) \ GEMM_FMLA2_LD1R(C7Re,C7Im,PT,AColRe,AColIm,BV7,BAddr,11) \ GEMM_FMLA2_LD1R(C8Re,C8Im,PT,AColRe,AColIm,BV0,BAddr,13) \ GEMM_FMLA2_LD1R(C9Re,C9Im,PT,AColRe,AColIm,BV1,BAddr,15) \ \ GEMM_FMLX2_LD1R(C0Im,C0Re,PT,AColRe,AColIm,BV2,BAddr,17) \ GEMM_FMLX2_LD1R(C1Im,C1Re,PT,AColRe,AColIm,BV3,BAddr,19) \ " add "#BAddr", "#BRSBit", "#BAddr" \n\t" /* B address forward */ \ GEMM_FMLX2_LD1R(C2Im,C2Re,PT,AColRe,AColIm,BV4,BAddr,0) \ GEMM_FMLX2_LD1R(C3Im,C3Re,PT,AColRe,AColIm,BV5,BAddr,2) \ GEMM_FMLX2_LD1R(C4Im,C4Re,PT,AColRe,AColIm,BV6,BAddr,4) \ GEMM_FMLX2_LD1R(C5Im,C5Re,PT,AColRe,AColIm,BV7,BAddr,6) \ GEMM_FMLX2_LD1R(C6Im,C6Re,PT,AColRe,AColIm,BV0,BAddr,8) \ GEMM_FMLX2_LD1R(C7Im,C7Re,PT,AColRe,AColIm,BV1,BAddr,10) \ GEMM_FMLX2_LD1R(C8Im,C8Re,PT,AColRe,AColIm,BV2,BAddr,12) \ GEMM_FMLX2_LD1R(C9Im,C9Re,PT,AColRe,AColIm,BV3,BAddr,14) #define GEMM_2VX10CMPLX_MKER_LOOP_PLAIN_C_2(C0Re,C1Re,C2Re,C3Re,C4Re,C5Re,C6Re,C7Re,C8Re,C9Re,C0Im,C1Im,C2Im,C3Im,C4Im,C5Im,C6Im,C7Im,C8Im,C9Im,PT,AColRe,AColIm,BV0,BV1,BV2,BV3,BV4,BV5,BV6,BV7,BAddr,BRSBit) \ GEMM_2VX10CMPLX_MKER_LOOP_PLAIN_C_1(C0Re,C1Re,C2Re,C3Re,C4Re,C5Re,C6Re,C7Re,C8Re,C9Re,C0Im,C1Im,C2Im,C3Im,C4Im,C5Im,C6Im,C7Im,C8Im,C9Im,PT,AColRe,AColIm,BV4,BV5,BV6,BV7,BV0,BV1,BV2,BV3,BAddr,BRSBit) #define GEMM_2VX10CMPLX_MKER_LOOP_PLAIN_C_1_RESIDUAL(C0Re,C1Re,C2Re,C3Re,C4Re,C5Re,C6Re,C7Re,C8Re,C9Re,C0Im,C1Im,C2Im,C3Im,C4Im,C5Im,C6Im,C7Im,C8Im,C9Im,PT,AColRe,AColIm,BV0,BV1,BV2,BV3,BV4,BV5,BV6,BV7,BAddr,BRSBit) \ GEMM_FMLA2_LD1R(C0Re,C0Im,PT,AColRe,AColIm,BV0,BAddr,16) \ GEMM_FMLA2_LD1R(C1Re,C1Im,PT,AColRe,AColIm,BV1,BAddr,18) \ GEMM_FMLA2_LD1R(C2Re,C2Im,PT,AColRe,AColIm,BV2,BAddr,1) \ GEMM_FMLA2_LD1R(C3Re,C3Im,PT,AColRe,AColIm,BV3,BAddr,3) \ GEMM_FMLA2_LD1R(C4Re,C4Im,PT,AColRe,AColIm,BV4,BAddr,5) \ GEMM_FMLA2_LD1R(C5Re,C5Im,PT,AColRe,AColIm,BV5,BAddr,7) \ GEMM_FMLA2_LD1R(C6Re,C6Im,PT,AColRe,AColIm,BV6,BAddr,9) \ GEMM_FMLA2_LD1R(C7Re,C7Im,PT,AColRe,AColIm,BV7,BAddr,11) \ GEMM_FMLA2_LD1R(C8Re,C8Im,PT,AColRe,AColIm,BV0,BAddr,13) \ GEMM_FMLA2_LD1R(C9Re,C9Im,PT,AColRe,AColIm,BV1,BAddr,15) \ \ GEMM_FMLX2_LD1R(C0Im,C0Re,PT,AColRe,AColIm,BV2,BAddr,17) \ GEMM_FMLX2_LD1R(C1Im,C1Re,PT,AColRe,AColIm,BV3,BAddr,19) \ " add "#BAddr", "#BRSBit", "#BAddr" \n\t" /* B address forward */ \ GEMM_FMLX2(C2Im,C2Re,PT,AColRe,AColIm,BV4) \ GEMM_FMLX2(C3Im,C3Re,PT,AColRe,AColIm,BV5) \ GEMM_FMLX2(C4Im,C4Re,PT,AColRe,AColIm,BV6) \ GEMM_FMLX2(C5Im,C5Re,PT,AColRe,AColIm,BV7) \ GEMM_FMLX2(C6Im,C6Re,PT,AColRe,AColIm,BV0) \ GEMM_FMLX2(C7Im,C7Re,PT,AColRe,AColIm,BV1) \ GEMM_FMLX2(C8Im,C8Re,PT,AColRe,AColIm,BV2) \ GEMM_FMLX2(C9Im,C9Re,PT,AColRe,AColIm,BV3) #define GEMM_2VX10CMPLX_MKER_LOOP_PLAIN_C_2_RESIDUAL(C0Re,C1Re,C2Re,C3Re,C4Re,C5Re,C6Re,C7Re,C8Re,C9Re,C0Im,C1Im,C2Im,C3Im,C4Im,C5Im,C6Im,C7Im,C8Im,C9Im,PT,AColRe,AColIm,BV0,BV1,BV2,BV3,BV4,BV5,BV6,BV7,BAddr,BRSBit) \ GEMM_2VX10CMPLX_MKER_LOOP_PLAIN_C_1_RESIDUAL(C0Re,C1Re,C2Re,C3Re,C4Re,C5Re,C6Re,C7Re,C8Re,C9Re,C0Im,C1Im,C2Im,C3Im,C4Im,C5Im,C6Im,C7Im,C8Im,C9Im,PT,AColRe,AColIm,BV4,BV5,BV6,BV7,BV0,BV1,BV2,BV3,BAddr,BRSBit) #define CLEAR_COL20(Z00,Z01,Z02,Z03,Z04,Z05,Z06,Z07,Z08,Z09,Z10,Z11,Z12,Z13,Z14,Z15,Z16,Z17,Z18,Z19) \ CLEAR_COL4(Z00,Z01,Z02,Z03) \ CLEAR_COL4(Z04,Z05,Z06,Z07) \ CLEAR_COL4(Z08,Z09,Z10,Z11) \ CLEAR_COL4(Z12,Z13,Z14,Z15) \ CLEAR_COL4(Z16,Z17,Z18,Z19) // Moving is always .d. // Never use .DT here! #define MOV_COL2(ZD0Re,ZD0Im,ZD1Re,ZD1Im,Z0Re,Z0Im,Z1Re,Z1Im) \ " mov "#ZD0Re".d, "#Z0Re".d \n\t" \ " mov "#ZD0Im".d, "#Z0Im".d \n\t" \ " mov "#ZD1Re".d, "#Z1Re".d \n\t" \ " mov "#ZD1Im".d, "#Z1Im".d \n\t" #define GEMM_FMULCMPLX_COL2(ZD0Re,ZD0Im,ZD1Re,ZD1Im,PT,Z0Re,Z0Im,Z1Re,Z1Im,ZFactorRe,ZFactorIm) \ FMUL_COL2(ZD0Re,ZD0Im,Z0Re,Z0Im,ZFactorRe) \ FMUL_COL2(ZD1Re,ZD1Im,Z1Re,Z1Im,ZFactorRe) \ GEMM_FMLX2(ZD0Im,ZD0Re,PT,Z0Re,Z0Im,ZFactorIm) \ GEMM_FMLX2(ZD1Im,ZD1Re,PT,Z1Re,Z1Im,ZFactorIm) #define GEMM_FMLACMPLX_COL2(ZD0Re,ZD0Im,ZD1Re,ZD1Im,PT,Z0Re,Z0Im,Z1Re,Z1Im,ZFactorRe,ZFactorIm) \ GEMM_FMLACMPLX(ZD0Re,ZD0Im,PT,Z0Re,Z0Im,ZFactorRe,ZFactorIm) \ GEMM_FMLACMPLX(ZD1Re,ZD1Im,PT,Z1Re,Z1Im,ZFactorRe,ZFactorIm) #define GEMM_CCMPLX_LOAD_COL2_C(Z0Re,Z0Im,Z1Re,Z1Im,PT,CAddr,CCS) \ GEMM_CCOLCMPLX_CONTIGUOUS_LOAD_FWD(Z0Re,Z0Im,PT,CAddr,CCS) \ GEMM_CCOLCMPLX_CONTIGUOUS_LOAD_FWD(Z1Re,Z1Im,PT,CAddr,CCS) #define GEMM_CCMPLX_STORE_COL2_C(Z0Re,Z0Im,Z1Re,Z1Im,PT,CAddr,CCS) \ GEMM_CCOLCMPLX_CONTIGUOUS_STORE_FWD(Z0Re,Z0Im,PT,CAddr,CCS) \ GEMM_CCOLCMPLX_CONTIGUOUS_STORE_FWD(Z1Re,Z1Im,PT,CAddr,CCS) #define GEMM_CCMPLX_LOAD_COL2_G(Z0Re,Z0Im,Z1Re,Z1Im,PT,ZIndex,CAddr,CCS,CTemp) \ GEMM_CCOLCMPLX_GATHER_LOAD_FWD(Z0Re,Z0Im,ZIndex,PT,PT,CAddr,CCS,CTemp) \ GEMM_CCOLCMPLX_GATHER_LOAD_FWD(Z1Re,Z1Im,ZIndex,PT,PT,CAddr,CCS,CTemp) #define GEMM_CCMPLX_STORE_COL2_G(Z0Re,Z0Im,Z1Re,Z1Im,PT,ZIndex,CAddr,CCS,CTemp) \ GEMM_CCOLCMPLX_SCATTER_STORE_FWD(Z0Re,Z0Im,ZIndex,PT,PT,CAddr,CCS,CTemp) \ GEMM_CCOLCMPLX_SCATTER_STORE_FWD(Z1Re,Z1Im,ZIndex,PT,PT,CAddr,CCS,CTemp) blis-0.9.0/kernels/armsve/3/armsve_asm_macros.h000066400000000000000000000141341422157504600214360ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2020, The University of Tokyo 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // Clang's label requirements. #if defined(__clang__) #define LABEL(str) " L" #str"%=: \n\t" #define BEQ(str) "b.eq L" #str"%= \n\t" #define BNE(str) "b.ne L" #str"%= \n\t" #define BRANCH(str) "b L" #str"%= \n\t" #else #define LABEL(str) " ." #str": \n\t" #define BEQ(str) "b.eq ." #str" \n\t" #define BNE(str) "b.ne ." #str" \n\t" #define BRANCH(str) "b ." #str" \n\t" #endif #define CLEAR_COL2(Z0,Z1) \ " dup "#Z0"."DT", #0 \n\t" \ " dup "#Z1"."DT", #0 \n\t" #define CLEAR_COL4(Z0,Z1,Z2,Z3) \ CLEAR_COL2(Z0,Z1) \ CLEAR_COL2(Z2,Z3) #define SCALE_COL2(Z0,Z1,ZFACTOR) \ " fmul "#Z0"."DT", "#Z0"."DT", "#ZFACTOR"."DT" \n\t" \ " fmul "#Z1"."DT", "#Z1"."DT", "#ZFACTOR"."DT" \n\t" \ #define SCALE_COL4(Z0,Z1,Z2,Z3,ZFACTOR) \ SCALE_COL2(Z0,Z1,ZFACTOR) \ SCALE_COL2(Z2,Z3,ZFACTOR) // Prefetch or not. #define PREFETCH_CONTIGUOUS_noprfm(LV,PROP,ADDR,SHIFT) #define PREFETCH_CONTIGUOUS_prfm(LV,PROP,ADDR,SHIFT) \ " prfm PLD"#LV""#PROP", ["#ADDR", "#SHIFT"] \n\t" #define GEMM_FMLA2(CCOLFH,CCOLLH,PT,ACOLFH,ACOLLH,BV) \ " fmla "#CCOLFH"."DT", "#PT"/m, "#ACOLFH"."DT", "#BV"."DT" \n\t" /* A Row 0 :VL */ \ " fmla "#CCOLLH"."DT", "#PT"/m, "#ACOLLH"."DT", "#BV"."DT" \n\t" /* A Row VL:2VL */ #define GEMM_FMLA2_LD1R(CCOLFH,CCOLLH,PT,ACOLFH,ACOLLH,BV,BADDR,NSHIFT) \ GEMM_FMLA2(CCOLFH,CCOLLH,PT,ACOLFH,ACOLLH,BV) \ " "LD1R" "#BV"."DT", "#PT"/z, ["#BADDR", #"#NSHIFT"*"SZ"]\n\t" #define GEMM_FMLA2_LD1R_G_ELMFWD(CCOLFH,CCOLLH,PT,ACOLFH,ACOLLH,BV,BELMADDR,BCSBIT) \ GEMM_FMLA2(CCOLFH,CCOLLH,PT,ACOLFH,ACOLLH,BV) \ " "LD1R" "#BV"."DT", "#PT"/z, ["#BELMADDR"] \n\t" /* Load B */ \ " add "#BELMADDR", "#BELMADDR", "#BCSBIT" \n\t" /* Forward B element */ #define GEMM_ACOL_CONTIGUOUS_LOAD(ZFH,ZLH,PFH,PLH,AADDR) \ " "LD1" "#ZFH"."DT", "#PFH"/z, ["#AADDR"] \n\t" \ " "LD1" "#ZLH"."DT", "#PLH"/z, ["#AADDR", #1, mul vl]\n\t" #define GEMM_ACOL_GATHER_LOAD(ZFH,ZLH,ZIDX,PFH,PLH,AADDR,AVSKIP,ATEMP) \ " "LD1" "#ZFH"."DT", "#PFH"/z, ["#AADDR", "#ZIDX"."DT", "OFFS"]\n\t" \ " add "#ATEMP", "#AADDR", "#AVSKIP" \n\t" \ " "LD1" "#ZLH"."DT", "#PLH"/z, ["#ATEMP", "#ZIDX"."DT", "OFFS"]\n\t" // Prefetch or not. #define GEMM_ACOL_GATHER_noprfm(LV,PROP,ZIDX,PFH,PLH,AADDR,AVSKIP,ATEMP) #define GEMM_ACOL_GATHER_prfm(LV,PROP,ZIDX,PFH,PLH,AADDR,AVSKIP,ATEMP) \ " "PRFG" PLD"#LV""#PROP", "#PFH", ["#AADDR", "#ZIDX"."DT", "OFFS"] \n\t" \ " add "#ATEMP", "#AADDR", "#AVSKIP" \n\t" \ " "PRFG" PLD"#LV""#PROP", "#PLH", ["#ATEMP", "#ZIDX"."DT", "OFFS"] \n\t" #define GEMMSUP_ACOL_PREFETCH_NEXT_LOAD_C(ZFH,ZLH,PFH,PLH,AADDR,A4KS,ACS,ATEMP,PREFMODE) \ " add "#ATEMP", "#AADDR", "#A4KS" \n\t" \ " add "#AADDR", "#AADDR", "#ACS" \n\t" /* Forward A's address to the next column. */ \ GEMM_ACOL_CONTIGUOUS_LOAD(ZFH,ZLH,PFH,PLH,AADDR) \ PREFETCH_CONTIGUOUS_ ##PREFMODE(L1,STRM,ATEMP,0) #define GEMMSUP_ACOL_PREFETCH_NEXT_LOAD_G(ZFH,ZLH,ZIDX,PFH,PLH,AADDR,A4KS,APS,ACS,AVSKIP,ATEMP,PREFMODEL1,PREFMODEL2) \ " add "#ATEMP", "#AADDR", "#A4KS" \n\t" \ GEMM_ACOL_GATHER_ ##PREFMODEL1(L1,STRM,ZIDX,PFH,PLH,ATEMP,AVSKIP,ATEMP) \ " add "#ATEMP", "#AADDR", "#APS" \n\t" \ GEMM_ACOL_GATHER_ ##PREFMODEL2(L2,STRM,ZIDX,PFH,PLH,ATEMP,AVSKIP,ATEMP) \ " add "#AADDR", "#AADDR", "#ACS" \n\t" /* Forward A's address to the next column. */ \ GEMM_ACOL_GATHER_LOAD(ZFH,ZLH,ZIDX,PFH,PLH,AADDR,AVSKIP,ATEMP) #define GEMM_CCOL_CONTIGUOUS_LOAD_FWD(ZFH,ZLH,PFH,PLH,CADDR,CCS) \ GEMM_ACOL_CONTIGUOUS_LOAD(ZFH,ZLH,PFH,PLH,CADDR) \ " add "#CADDR", "#CADDR", "#CCS" \n\t" /* Forward C address (load) to next column. */ #define GEMM_CCOL_CONTIGUOUS_STORE_FWD(ZFH,ZLH,PFH,PLH,CADDR,CCS) \ " "ST1" "#ZFH"."DT", "#PFH", ["#CADDR"] \n\t" \ " "ST1" "#ZLH"."DT", "#PLH", ["#CADDR", #1, mul vl] \n\t" \ " add "#CADDR", "#CADDR", "#CCS" \n\t" /* Forward C address (store) to next column. */ #define GEMM_CCOL_FMAD(ZFH,ZLH,PFH,PLH,CFH,CLH,ZSCALE) \ " fmad "#ZFH"."DT", "#PFH"/m, "#ZSCALE"."DT", "#CFH"."DT" \n\t" \ " fmad "#ZLH"."DT", "#PLH"/m, "#ZSCALE"."DT", "#CLH"."DT" \n\t" #define GEMM_CCOL_GATHER_LOAD_FWD(ZFH,ZLH,ZIDX,PFH,PLH,CADDR,CCS,CVSKIP,CTEMP) \ GEMM_ACOL_GATHER_LOAD(ZFH,ZLH,ZIDX,PFH,PLH,CADDR,CVSKIP,CTEMP) \ " add "#CADDR", "#CADDR", "#CCS" \n\t" #define GEMM_CCOL_SCATTER_STORE_FWD(ZFH,ZLH,ZIDX,PFH,PLH,CADDR,CCS,CVSKIP,CTEMP) \ " "ST1" "#ZFH"."DT", "#PFH", ["#CADDR", "#ZIDX"."DT", "OFFS"]\n\t" \ " add "#CTEMP", "#CADDR", "#CVSKIP" \n\t" \ " "ST1" "#ZLH"."DT", "#PLH", ["#CTEMP", "#ZIDX"."DT", "OFFS"]\n\t" \ " add "#CADDR", "#CADDR", "#CCS" \n\t" blis-0.9.0/kernels/armsve/3/armsve_asm_macros_cmplx.h000066400000000000000000000100731422157504600226370ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2020, The University of Tokyo 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "armsve_asm_macros.h" #define FMUL_COL2(ZD0,ZD1,Z0,Z1,ZFACTOR) \ " fmul "#ZD0"."DT", "#Z0"."DT", "#ZFACTOR"."DT" \n\t" \ " fmul "#ZD1"."DT", "#Z1"."DT", "#ZFACTOR"."DT" \n\t" \ #define GEMM_FMLX2(CCOLFH,CCOLLH,PT,ACOLFH,ACOLLH,BV) \ " fmla "#CCOLFH"."DT", "#PT"/m, "#ACOLFH"."DT", "#BV"."DT" \n\t" \ " fmls "#CCOLLH"."DT", "#PT"/m, "#ACOLLH"."DT", "#BV"."DT" \n\t" #define GEMM_FMLX2_LD1R(CCOLFH,CCOLLH,PT,ACOLFH,ACOLLH,BV,BADDR,NSHIFT) \ GEMM_FMLX2(CCOLFH,CCOLLH,PT,ACOLFH,ACOLLH,BV) \ " "LD1R" "#BV"."DT", "#PT"/z, ["#BADDR", #"#NSHIFT"*"SZ"]\n\t" #define GEMM_FMULCMPLX(ZDRe,ZDIm,PT,Z0Re,Z0Im,Z1Re,Z1Im) \ FMUL_COL2(ZDRe,ZDIm,Z0Re,Z0Im,Z1Re) \ GEMM_FMLX2(ZDIm,ZDRe,PT,Z0Re,Z0Im,Z1Im) #define GEMM_FMLACMPLX(ZDRe,ZDIm,PT,Z0Re,Z0Im,Z1Re,Z1Im) \ GEMM_FMLA2(ZDRe,ZDIm,PT,Z0Re,Z0Im,Z1Re) \ GEMM_FMLX2(ZDIm,ZDRe,PT,Z0Re,Z0Im,Z1Im) #define GEMM_ACOLCMPLX_CONTIGUOUS_LOAD(ZRe,ZIm,PT,AAddr) \ " "LD2" {"#ZRe"."DT", "#ZIm"."DT"}, "#PT"/z, ["#AAddr"] \n\t" #define GEMM_ACOLCMPLX_CONTIGUOUS_STORE(ZRe,ZIm,PT,AAddr) \ " "ST2" {"#ZRe"."DT", "#ZIm"."DT"}, "#PT", ["#AAddr"] \n\t" #define GEMM_ACOLCMPLX_CONTIGUOUS_LOAD_FWD(ZRe,ZIm,PT,AAddr,ACS) \ GEMM_ACOLCMPLX_CONTIGUOUS_LOAD(ZRe,ZIm,PT,AAddr) \ " add "#AAddr", "#AAddr", "#ACS" \n\t" /* Forward A address (load) to next column. */ #define GEMM_CCOLCMPLX_CONTIGUOUS_LOAD_FWD(ZRe,ZIm,PT,CAddr,CCS) \ GEMM_ACOLCMPLX_CONTIGUOUS_LOAD_FWD(ZRe,ZIm,PT,CAddr,CCS) #define GEMM_ACOLCMPLX_CONTIGUOUS_STORE_FWD(ZRe,ZIm,PT,AAddr,ACS) \ GEMM_ACOLCMPLX_CONTIGUOUS_STORE(ZRe,ZIm,PT,AAddr) \ " add "#AAddr", "#AAddr", "#ACS" \n\t" /* Forward A address (load) to next column. */ #define GEMM_CCOLCMPLX_CONTIGUOUS_STORE_FWD(ZRe,ZIm,PT,CAddr,CCS) \ GEMM_ACOLCMPLX_CONTIGUOUS_STORE_FWD(ZRe,ZIm,PT,CAddr,CCS) #define GEMM_CCOLCMPLX_GATHER_LOAD_FWD(ZRe,ZIm,ZIndex,PRe,PIm,CAddr,CCS,CTemp) \ " add "#CTemp", "#CAddr", #"SZ" \n\t" /* Imaginary skip */ \ " "LD1" "#ZRe"."DT", "#PRe"/z, ["#CAddr", "#ZIndex"."DT", "OFFS"]\n\t" \ " "LD1" "#ZIm"."DT", "#PRe"/z, ["#CTemp", "#ZIndex"."DT", "OFFS"]\n\t" \ " add "#CAddr", "#CAddr", "#CCS" \n\t" #define GEMM_CCOLCMPLX_SCATTER_STORE_FWD(ZRe,ZIm,ZIndex,PRe,PIm,CAddr,CCS,CTemp) \ " add "#CTemp", "#CAddr", #"SZ" \n\t" /* Imaginary skip */ \ " "ST1" "#ZRe"."DT", "#PRe", ["#CAddr", "#ZIndex"."DT", "OFFS"]\n\t" \ " "ST1" "#ZIm"."DT", "#PRe", ["#CTemp", "#ZIndex"."DT", "OFFS"]\n\t" \ " add "#CAddr", "#CAddr", "#CCS" \n\t" blis-0.9.0/kernels/armsve/3/armsve_asm_macros_dcomplex.h000066400000000000000000000037171422157504600233360ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2020, The University of Tokyo 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // Specify to use double precision. #define DT "d" #define LD1 "ld1d" #define ST1 "st1d" #define LD2 "ld2d" #define ST2 "st2d" #define LD1R "ld1rd" #define PRFG "prfd" #define SZ "8" #define OFFS "lsl #3" // Include macros. #include "armsve_asm_macros_cmplx.h" blis-0.9.0/kernels/armsve/3/armsve_asm_macros_double.h000066400000000000000000000036371422157504600227760ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2020, The University of Tokyo 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // Specify to use double precision. #define DT "d" #define LD1 "ld1d" #define ST1 "st1d" #define LD1R "ld1rd" #define PRFG "prfd" #define SZ "8" #define OFFS "lsl #3" // Include macros. #include "armsve_asm_macros.h" blis-0.9.0/kernels/armsve/3/armsve_asm_macros_scomplex.h000066400000000000000000000037201422157504600233470ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2020, The University of Tokyo 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // Specify to use single precision. #define DT "s" #define LD1 "ld1w" #define ST1 "st1w" #define LD2 "ld2w" #define ST2 "st2w" #define LD1R "ld1rw" #define PRFG "prfw" #define SZ "4" #define OFFS "uxtw #2" // Include macros. #include "armsve_asm_macros_cmplx.h" blis-0.9.0/kernels/armsve/3/armsve_asm_macros_single.h000066400000000000000000000036401422157504600227770ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2020, The University of Tokyo 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // Specify to use single precision. #define DT "s" #define LD1 "ld1w" #define ST1 "st1w" #define LD1R "ld1rw" #define PRFG "prfw" #define SZ "4" #define OFFS "uxtw #2" // Include macros. #include "armsve_asm_macros.h" blis-0.9.0/kernels/armsve/3/bli_armsve_utils.c000066400000000000000000000072601422157504600212750ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2019, Forschunszentrum Juelich Copyright (C) 2020, The University of Tokyo 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" dim_t bli_vl_bytes_armsve(void) { \ uint64_t vl = 0; __asm__ ( " mov x0, xzr \n\t" " incb x0 \n\t" " mov %[vl], x0 \n\t" : [vl] "=r" (vl) : : "x0" ); return vl; } #define EXPANDMAC_BLKSZ_ARMSVE(ch, S_Data) \ void PASTEMAC(ch, _blksz_armsve) (dim_t *m_r_, dim_t *n_r_, \ dim_t *k_c_, dim_t *m_c_, dim_t *n_c_) \ { \ dim_t W_L1 = bli_env_get_var("BLIS_SVE_W_L1", W_L1_SVE_DEFAULT); \ dim_t N_L1 = bli_env_get_var("BLIS_SVE_N_L1", N_L1_SVE_DEFAULT); \ dim_t C_L1 = bli_env_get_var("BLIS_SVE_C_L1", C_L1_SVE_DEFAULT); \ dim_t W_L2 = bli_env_get_var("BLIS_SVE_W_L2", W_L2_SVE_DEFAULT); \ dim_t N_L2 = bli_env_get_var("BLIS_SVE_N_L2", N_L2_SVE_DEFAULT); \ dim_t C_L2 = bli_env_get_var("BLIS_SVE_C_L2", C_L2_SVE_DEFAULT); \ dim_t W_L3 = bli_env_get_var("BLIS_SVE_W_L3", W_L3_SVE_DEFAULT); \ dim_t N_L3 = bli_env_get_var("BLIS_SVE_N_L3", N_L3_SVE_DEFAULT); \ dim_t C_L3 = bli_env_get_var("BLIS_SVE_C_L3", C_L3_SVE_DEFAULT); \ \ dim_t vl_b = bli_vl_bytes_armsve(); \ dim_t vl = vl_b / S_Data; \ dim_t m_r = 2 * vl; \ dim_t n_r = 10; \ \ dim_t k_c = (dim_t)( floor((W_L1 - 1.0)/(1.0 + (double)n_r/m_r)) * N_L1 * C_L1 ) \ / (n_r * S_Data); \ \ dim_t C_Ac = W_L2 - 1 - ceil( (2.0 * k_c * n_r * S_Data)/(C_L2 * N_L2) ); \ dim_t m_c = C_Ac * (N_L2 * C_L2)/(k_c * S_Data); \ m_c -= m_c % m_r; \ \ dim_t C_Bc = W_L3 - 1 - ceil( (2.0 * k_c * m_c * S_Data)/(C_L3 * N_L3) ); \ dim_t n_c = C_Bc * (N_L3 * C_L3)/(k_c * S_Data); \ n_c -= n_c % n_r; \ \ /* Ensure non-zero block sizes. */ \ m_c = bli_max(m_c, m_r); \ n_c = bli_max(n_c, n_r); \ k_c = bli_max(k_c, 128); \ \ *m_r_ = m_r; \ *n_r_ = n_r; \ *k_c_ = k_c; \ *m_c_ = m_c; \ *n_c_ = n_c; \ } EXPANDMAC_BLKSZ_ARMSVE( s, 4 ) EXPANDMAC_BLKSZ_ARMSVE( d, 8 ) EXPANDMAC_BLKSZ_ARMSVE( c, 8 ) EXPANDMAC_BLKSZ_ARMSVE( z, 16 ) blis-0.9.0/kernels/armsve/3/bli_armsve_utils.h000066400000000000000000000042051422157504600212760ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2019, Forschunszentrum Juelich Copyright (C) 2020, The University of Tokyo 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" dim_t bli_vl_bytes_armsve(void); void bli_s_blksz_armsve(dim_t *m_r_, dim_t *n_r_, dim_t *k_c_, dim_t *m_c_, dim_t *n_c_); void bli_d_blksz_armsve(dim_t *m_r_, dim_t *n_r_, dim_t *k_c_, dim_t *m_c_, dim_t *n_c_); void bli_c_blksz_armsve(dim_t *m_r_, dim_t *n_r_, dim_t *k_c_, dim_t *m_c_, dim_t *n_c_); void bli_z_blksz_armsve(dim_t *m_r_, dim_t *n_r_, dim_t *k_c_, dim_t *m_c_, dim_t *n_c_); blis-0.9.0/kernels/armsve/3/bli_gemm_armsve_asm_c2vx10_unindexed.c000066400000000000000000000374571422157504600251030ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2019, Forschunszentrum Juelich Copyright (C) 2020, The University of Tokyo 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // Single-precision composite instructions. #include "armsve_asm_macros_scomplex.h" // 2vx10 microkernels. #include "armsve_asm_2vx10cmplx.h" void bli_cgemm_armsve_asm_2vx10_unindexed ( dim_t m, dim_t n, dim_t k, scomplex* restrict alpha, scomplex* restrict a, scomplex* restrict b, scomplex* restrict beta, scomplex* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { void* a_next = bli_auxinfo_next_a( data ); void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_mker = k / 4; uint64_t k_left = k % 4; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; uint64_t info = 0; GEMM_UKR_SETUP_CT( c, m, 10, false ); __asm__ volatile ( " whilelo p0.s, xzr, %12 \n\t" // " ldr x0, %[a] \n\t" // " ldr x1, %[b] \n\t" " mov x2, xzr \n\t" " incw x2, ALL, MUL #1 \n\t" // Column-skip of A. " mov x3, #10 \n\t" // Row-skip of B. " \n\t" // " ldr x2, %[c] \n\t" // " ldr x3, %[rs_c] \n\t" // Row-skip of C. // " ldr x4, %[cs_c] \n\t" // Column-skip of C. #ifdef _A64FX " mov x16, 0x1 \n\t" // Tag A address. " lsl x16, x16, #56 \n\t" " orr %0, %0, x16 \n\t" " mov x16, 0x2 \n\t" // Tag B address. " lsl x16, x16, #56 \n\t" " orr %1, %1, x16 \n\t" " mov x16, 0x3 \n\t" // Tag C address. " lsl x16, x16, #56 \n\t" " orr %2, %2, x16 \n\t" #endif " \n\t" " mov x16, #8 \n\t" // Multiply some address skips by sizeof(scomplex). " madd x2, x16, x2, xzr \n\t" // cs_a " madd x3, x16, x3, xzr \n\t" // rs_b " madd %4, x16, %4, xzr \n\t" // cs_c " \n\t" // " ldr x5, %[k_mker] \n\t" // Number of loops. // " ldr x6, %[k_left] \n\t" " \n\t" LABEL(LOAD_ABC) " cmp %5, #0 \n\t" // Don't preload if no microkernel there. BEQ(END_CCOL_PRFM) " \n\t" " ld1rw z20.s, p0/z, [%1, 4*0] \n\t" // Load B's real 8/10, no imaginary. " ld1rw z21.s, p0/z, [%1, 4*2] \n\t" " ld1rw z22.s, p0/z, [%1, 4*4] \n\t" " ld1rw z23.s, p0/z, [%1, 4*6] \n\t" " ld1rw z24.s, p0/z, [%1, 4*8] \n\t" " ld1rw z25.s, p0/z, [%1, 4*10] \n\t" " ld1rw z26.s, p0/z, [%1, 4*12] \n\t" " ld1rw z27.s, p0/z, [%1, 4*14] \n\t" " \n\t" GEMM_ACOLCMPLX_CONTIGUOUS_LOAD_FWD(z28,z29,p0,%0,x2) " \n\t" LABEL(CCOL_PRFM) // " cmp %3, #1 \n\t" // BNE(END_CCOL_PRFM) // Do not prefetch for generic C storage. " mov x16, %2 \n\t" " prfm PLDL1KEEP, [x16] \n\t" " add x16, x16, %4 \n\t" " prfm PLDL1KEEP, [x16] \n\t" " add x16, x16, %4 \n\t" " prfm PLDL1KEEP, [x16] \n\t" " add x16, x16, %4 \n\t" " prfm PLDL1KEEP, [x16] \n\t" " add x16, x16, %4 \n\t" " prfm PLDL1KEEP, [x16] \n\t" " add x16, x16, %4 \n\t" " prfm PLDL1KEEP, [x16] \n\t" " add x16, x16, %4 \n\t" " prfm PLDL1KEEP, [x16] \n\t" " add x16, x16, %4 \n\t" " prfm PLDL1KEEP, [x16] \n\t" " add x16, x16, %4 \n\t" " prfm PLDL1KEEP, [x16] \n\t" " add x16, x16, %4 \n\t" " prfm PLDL1KEEP, [x16] \n\t" LABEL(END_CCOL_PRFM) " \n\t" CLEAR_COL20(z0,z1,z2,z3,z4,z5,z6,z7,z8,z9,z10,z11,z12,z13,z14,z15,z16,z17,z18,z19) " \n\t" " cmp %5, #0 \n\t" // If no 4-microkernel can be applied. BEQ(K_LEFT_LOOP) " \n\t" LABEL(K_MKER_LOOP) " \n\t" GEMM_ACOLCMPLX_CONTIGUOUS_LOAD_FWD(z30,z31,p0,%0,x2) GEMM_2VX10CMPLX_MKER_LOOP_PLAIN_C_1(z0,z2,z4,z6,z8,z10,z12,z14,z16,z18,z1,z3,z5,z7,z9,z11,z13,z15,z17,z19,p0,z28,z29,z20,z21,z22,z23,z24,z25,z26,z27,%1,x3) " \n\t" GEMM_ACOLCMPLX_CONTIGUOUS_LOAD_FWD(z28,z29,p0,%0,x2) GEMM_2VX10CMPLX_MKER_LOOP_PLAIN_C_2(z0,z2,z4,z6,z8,z10,z12,z14,z16,z18,z1,z3,z5,z7,z9,z11,z13,z15,z17,z19,p0,z30,z31,z20,z21,z22,z23,z24,z25,z26,z27,%1,x3) " \n\t" GEMM_ACOLCMPLX_CONTIGUOUS_LOAD_FWD(z30,z31,p0,%0,x2) GEMM_2VX10CMPLX_MKER_LOOP_PLAIN_C_1(z0,z2,z4,z6,z8,z10,z12,z14,z16,z18,z1,z3,z5,z7,z9,z11,z13,z15,z17,z19,p0,z28,z29,z20,z21,z22,z23,z24,z25,z26,z27,%1,x3) " \n\t" " subs %5, %5, #1 \n\t" // Decrease counter before final replica. BEQ(FIN_MKER_LOOP) // Branch early to avoid reading excess mem. " \n\t" GEMM_ACOLCMPLX_CONTIGUOUS_LOAD_FWD(z28,z29,p0,%0,x2) GEMM_2VX10CMPLX_MKER_LOOP_PLAIN_C_2(z0,z2,z4,z6,z8,z10,z12,z14,z16,z18,z1,z3,z5,z7,z9,z11,z13,z15,z17,z19,p0,z30,z31,z20,z21,z22,z23,z24,z25,z26,z27,%1,x3) BRANCH(K_MKER_LOOP) " \n\t" LABEL(FIN_MKER_LOOP) GEMM_2VX10CMPLX_MKER_LOOP_PLAIN_C_2_RESIDUAL(z0,z2,z4,z6,z8,z10,z12,z14,z16,z18,z1,z3,z5,z7,z9,z11,z13,z15,z17,z19,p0,z30,z31,z20,z21,z22,z23,z24,z25,z26,z27,%1,x3) " \n\t" LABEL(K_LEFT_LOOP) " cmp %6, #0 \n\t" // End of execution. BEQ(WRITE_MEM_PREP) " \n\t" GEMM_ACOLCMPLX_CONTIGUOUS_LOAD_FWD(z28,z29,p0,%0,x2) " ld1rw z20.s, p0/z, [%1, 4*0] \n\t" // Load B's real 8/10, no imaginary. " ld1rw z21.s, p0/z, [%1, 4*2] \n\t" " ld1rw z22.s, p0/z, [%1, 4*4] \n\t" " ld1rw z23.s, p0/z, [%1, 4*6] \n\t" " ld1rw z24.s, p0/z, [%1, 4*8] \n\t" " ld1rw z25.s, p0/z, [%1, 4*10] \n\t" " ld1rw z26.s, p0/z, [%1, 4*12] \n\t" " ld1rw z27.s, p0/z, [%1, 4*14] \n\t" GEMM_2VX10CMPLX_MKER_LOOP_PLAIN_C_1_RESIDUAL(z0,z2,z4,z6,z8,z10,z12,z14,z16,z18,z1,z3,z5,z7,z9,z11,z13,z15,z17,z19,p0,z28,z29,z20,z21,z22,z23,z24,z25,z26,z27,%1,x3) " sub %6, %6, #1 \n\t" BRANCH(K_LEFT_LOOP) " \n\t" LABEL(WRITE_MEM_PREP) " \n\t" // " ldr x7, %[alpha] \n\t" // Load alpha & beta (address). // " ldr x8, %[beta] \n\t" " ld1rw z28.s, p0/z, [%7] \n\t" // Real(alpha). " ld1rw z29.s, p0/z, [%7, 4] \n\t" // Imag(alpha). " ld1rw z30.s, p0/z, [%8] \n\t" // Real(beta). " ld1rw z31.s, p0/z, [%8, 4] \n\t" // Imag(beta). " \n\t" LABEL(PREFETCH_ABNEXT) // " ldr x9, %[a_next] \n\t" // " ldr x10, %[b_next] \n\t" #ifdef _A64FX " mov x16, 0x1 \n\t" // Tag A address. " lsl x16, x16, #56 \n\t" " orr %9, %9, x16 \n\t" " mov x16, 0x2 \n\t" // Tag B address. " lsl x16, x16, #56 \n\t" " orr %10, %10, x16 \n\t" #endif " prfm PLDL1STRM, [%9] \n\t" " prfm PLDL1STRM, [%9, 256*1] \n\t" " prfm PLDL1STRM, [%10] \n\t" " prfm PLDL1STRM, [%10, 256*1] \n\t" " \n\t" LABEL(WRITE_MEM) " fmov s27, #1.0 \n\t" " fcmp s29, #0.0 \n\t" // Whether Imag(alpha) == 0. " fccmp s28, s27, 0, eq \n\t" // Whether Real(alpha) == 1. BEQ(UNIT_ALPHA) " \n\t" GEMM_FMULCMPLX_COL2(z20,z21,z22,z23,p0,z0 ,z1 ,z2 ,z3 ,z28,z29) GEMM_FMULCMPLX_COL2(z24,z25,z26,z27,p0,z4 ,z5 ,z6 ,z7 ,z28,z29) GEMM_FMULCMPLX_COL2(z0 ,z1 ,z2 ,z3 ,p0,z8, z9, z10,z11,z28,z29) GEMM_FMULCMPLX_COL2(z4 ,z5 ,z6 ,z7 ,p0,z12,z13,z14,z15,z28,z29) GEMM_FMULCMPLX_COL2(z8 ,z9 ,z10,z11,p0,z16,z17,z18,z19,z28,z29) BRANCH(WRITE_MEM_EXEC) " \n\t" LABEL(UNIT_ALPHA) MOV_COL2(z20,z21,z22,z23,z0 ,z1 ,z2 ,z3 ) MOV_COL2(z24,z25,z26,z27,z4 ,z5 ,z6 ,z7 ) MOV_COL2(z0 ,z1 ,z2 ,z3 ,z8, z9, z10,z11) MOV_COL2(z4 ,z5 ,z6 ,z7 ,z12,z13,z14,z15) MOV_COL2(z8 ,z9 ,z10,z11,z16,z17,z18,z19) " \n\t" LABEL(WRITE_MEM_EXEC) " mov x9, %2 \n\t" // C address for loading. " \n\t" // C address for storing is %2 itself. // " cmp %3, #1 \n\t" // BNE(WRITE_MEM_G) " \n\t" LABEL(WRITE_MEM_C) " fmov s29, wzr \n\t" " fcmp s31, #0.0 \n\t" // Whether Imag(beta) == 0. " fccmp s30, s29, 0, eq \n\t" // Whether Real(beta) == 0. BEQ(ZERO_BETA_C_0_1_2_3) GEMM_CCMPLX_LOAD_COL2_C(z12,z13,z14,z15,p0,x9,%4) GEMM_CCMPLX_LOAD_COL2_C(z16,z17,z18,z19,p0,x9,%4) GEMM_FMLACMPLX_COL2(z20,z21,z22,z23,p0,z12,z13,z14,z15,z30,z31) GEMM_FMLACMPLX_COL2(z24,z25,z26,z27,p0,z16,z17,z18,z19,z30,z31) LABEL(ZERO_BETA_C_0_1_2_3) GEMM_CCMPLX_STORE_COL2_C(z20,z21,z22,z23,p0,%2,%4) GEMM_CCMPLX_STORE_COL2_C(z24,z25,z26,z27,p0,%2,%4) " \n\t" BEQ(ZERO_BETA_C_4_5_6_7_8_9) GEMM_CCMPLX_LOAD_COL2_C(z12,z13,z14,z15,p0,x9,%4) GEMM_CCMPLX_LOAD_COL2_C(z16,z17,z18,z19,p0,x9,%4) GEMM_CCMPLX_LOAD_COL2_C(z20,z21,z22,z23,p0,x9,%4) GEMM_FMLACMPLX_COL2(z0 ,z1 ,z2 ,z3 ,p0,z12,z13,z14,z15,z30,z31) GEMM_FMLACMPLX_COL2(z4 ,z5 ,z6 ,z7 ,p0,z16,z17,z18,z19,z30,z31) GEMM_FMLACMPLX_COL2(z8 ,z9 ,z10,z11,p0,z20,z21,z22,z23,z30,z31) LABEL(ZERO_BETA_C_4_5_6_7_8_9) GEMM_CCMPLX_STORE_COL2_C(z0 ,z1 ,z2 ,z3 ,p0,%2,%4) GEMM_CCMPLX_STORE_COL2_C(z4 ,z5 ,z6 ,z7 ,p0,%2,%4) GEMM_CCMPLX_STORE_COL2_C(z8 ,z9 ,z10,z11,p0,%2,%4) // BRANCH(END_WRITE_MEM) // " \n\t" // LABEL(WRITE_MEM_G) // " add %3, %3, %3 \n\t" // Skips passed to index is multiplied by 2, // " mov x3, %3 \n\t" // s.t. 2*sizeof(float) = 2*4 = 8. // " index z28.s, wzr, w3 \n\t" // " fmov s29, wzr \n\t" // " fcmp s31, #0.0 \n\t" // Whether Imag(beta) == 0. // " fccmp s30, s29, 0, eq \n\t" // Whether Real(beta) == 0. // BEQ(ZERO_BETA_G_0_1_2_3) // GEMM_CCMPLX_LOAD_COL2_G(z12,z13,z14,z15,p0,z28,x9,%4,x16) // GEMM_CCMPLX_LOAD_COL2_G(z16,z17,z18,z19,p0,z28,x9,%4,x16) // GEMM_FMLACMPLX_COL2(z20,z21,z22,z23,p0,z12,z13,z14,z15,z30,z31) // GEMM_FMLACMPLX_COL2(z24,z25,z26,z27,p0,z16,z17,z18,z19,z30,z31) // LABEL(ZERO_BETA_G_0_1_2_3) // GEMM_CCMPLX_STORE_COL2_G(z20,z21,z22,z23,p0,z28,%2,%4,x16) // GEMM_CCMPLX_STORE_COL2_G(z24,z25,z26,z27,p0,z28,%2,%4,x16) // " \n\t" // BEQ(ZERO_BETA_G_4_5_6_7_8_9) // GEMM_CCMPLX_LOAD_COL2_G(z12,z13,z14,z15,p0,z28,x9,%4,x16) // GEMM_CCMPLX_LOAD_COL2_G(z16,z17,z18,z19,p0,z28,x9,%4,x16) // GEMM_CCMPLX_LOAD_COL2_G(z20,z21,z22,z23,p0,z28,x9,%4,x16) // GEMM_FMLACMPLX_COL2(z0 ,z1 ,z2 ,z3 ,p0,z12,z13,z14,z15,z30,z31) // GEMM_FMLACMPLX_COL2(z4 ,z5 ,z6 ,z7 ,p0,z16,z17,z18,z19,z30,z31) // GEMM_FMLACMPLX_COL2(z8 ,z9 ,z10,z11,p0,z20,z21,z22,z23,z30,z31) // LABEL(ZERO_BETA_G_4_5_6_7_8_9) // GEMM_CCMPLX_STORE_COL2_G(z0 ,z1 ,z2 ,z3 ,p0,z28,%2,%4,x16) // GEMM_CCMPLX_STORE_COL2_G(z4 ,z5 ,z6 ,z7 ,p0,z28,%2,%4,x16) // GEMM_CCMPLX_STORE_COL2_G(z8 ,z9 ,z10,z11,p0,z28,%2,%4,x16) // " \n\t" // LABEL(END_WRITE_MEM) // BRANCH(END_EXEC) " \n\t" LABEL(END_EXEC) " mov %11, #0 \n\t" // Return normal. : "+r" (a), // %0 "+r" (b), // %1 "+r" (c), // %2 "+r" (rs_c), // %3 "+r" (cs_c), // %4 "+r" (k_mker), // %5 "+r" (k_left), // %6 "+r" (alpha), // %7 "+r" (beta), // %8 "+r" (a_next), // %9 "+r" (b_next), // %10 "=r" (info) // %11 : "r" (m) // %12 : "x2","x3","x9","x16", "z0","z1","z2","z3","z4","z5","z6","z7", "z8","z9","z10","z11","z12","z13","z14","z15", "z16","z17","z18","z19", "z20","z21","z22","z23", "z24","z25","z26","z27", "z28","z29","z30","z31" ); GEMM_UKR_FLUSH_CT( c ); } blis-0.9.0/kernels/armsve/3/bli_gemm_armsve_asm_d2vx10_unindexed.c000066400000000000000000000376051422157504600250770ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2019, Forschunszentrum Juelich Copyright (C) 2020, The University of Tokyo 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // Double-precision composite instructions. #include "armsve_asm_macros_double.h" // 2vx10 microkernels. #include "armsve_asm_2vx10.h" void bli_dgemm_armsve_asm_2vx10_unindexed ( dim_t m, dim_t n, dim_t k, double* restrict alpha, double* restrict a, double* restrict b, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { void* a_next = bli_auxinfo_next_a( data ); void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_mker = k / 4; uint64_t k_left = k % 4; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; GEMM_UKR_SETUP_CT( d, m, 10, false ); __asm__ volatile ( " mov x0, xzr \n\t" " ldr x1, %[m] \n\t" " whilelo p0.d, x0, x1 \n\t" " incd x0 \n\t" " whilelo p1.d, x0, x1 \n\t" " \n\t" " ldr x0, %[a] \n\t" " ldr x1, %[b] \n\t" " mov x2, xzr \n\t" " incd x2, ALL, MUL #2 \n\t" // Column-skip of A. " mov x3, #10 \n\t" // Row-skip of B. " \n\t" " ldr x5, %[c] \n\t" // " ldr x6, %[rs_c] \n\t" // Row-skip of C. " ldr x7, %[cs_c] \n\t" // Column-skip of C. #ifdef _A64FX " mov x8, 0x3 \n\t" // Tag C address. " lsl x8, x8, #56 \n\t" " orr x5, x5, x8 \n\t" " mov x8, 0x2 \n\t" // Tag B address. " lsl x8, x8, #56 \n\t" " orr x1, x1, x8 \n\t" " mov x8, 0x1 \n\t" // Tag A address. " lsl x8, x8, #56 \n\t" " orr x0, x0, x8 \n\t" #endif " \n\t" " mov x8, #8 \n\t" // Multiply some address skips by sizeof(double). " madd x2, x8, x2, xzr \n\t" // cs_a " madd x3, x8, x3, xzr \n\t" // rs_b " madd x7, x8, x7, xzr \n\t" // cs_c " \n\t" " ldr x4, %[k_mker] \n\t" // Number of loops. " ldr x8, %[k_left] \n\t" " \n\t" LABEL(LOAD_ABC) " cmp x4, #0 \n\t" // Don't preload if no microkernel there. BEQ(END_CCOL_PRFM) " ld1rd z20.d, p0/z, [x1] \n\t" // Load 8/10 of first B row. " ld1rd z21.d, p0/z, [x1, 8] \n\t" " ld1rd z22.d, p0/z, [x1, 16] \n\t" " ld1rd z23.d, p0/z, [x1, 24] \n\t" " ld1rd z24.d, p0/z, [x1, 32] \n\t" " ld1rd z25.d, p0/z, [x1, 40] \n\t" " ld1rd z26.d, p0/z, [x1, 48] \n\t" " ld1rd z27.d, p0/z, [x1, 56] \n\t" " \n\t" GEMM_ACOL_CONTIGUOUS_LOAD(z28,z29,p0,p1,x0) " \n\t" LABEL(CCOL_PRFM) // " cmp x6, #1 \n\t" // BNE(END_CCOL_PRFM) // Do not prefetch for generic C storage. " mov x16, x5 \n\t" " prfm PLDL1KEEP, [x16] \n\t" " add x16, x16, x7 \n\t" " prfm PLDL1KEEP, [x16] \n\t" " add x16, x16, x7 \n\t" " prfm PLDL1KEEP, [x16] \n\t" " add x16, x16, x7 \n\t" " prfm PLDL1KEEP, [x16] \n\t" " add x16, x16, x7 \n\t" " prfm PLDL1KEEP, [x16] \n\t" " add x16, x16, x7 \n\t" " prfm PLDL1KEEP, [x16] \n\t" " add x16, x16, x7 \n\t" " prfm PLDL1KEEP, [x16] \n\t" " add x16, x16, x7 \n\t" " prfm PLDL1KEEP, [x16] \n\t" " add x16, x16, x7 \n\t" " prfm PLDL1KEEP, [x16] \n\t" " add x16, x16, x7 \n\t" " prfm PLDL1KEEP, [x16] \n\t" LABEL(END_CCOL_PRFM) " \n\t" CLEAR_COL20(z0,z1,z2,z3,z4,z5,z6,z7,z8,z9,z10,z11,z12,z13,z14,z15,z16,z17,z18,z19) " \n\t" " cmp x4, #0 \n\t" // If no 4-microkernel can be applied BEQ(K_LEFT_LOOP) " \n\t" LABEL(K_MKER_LOOP) " \n\t" " add x0, x0, x2 \n\t" // Forward A's address to the next column. GEMM_ACOL_CONTIGUOUS_LOAD(z30,z31,p0,p1,x0) GEMM_2VX10_MKER_LOOP_PLAIN_C_1(z0,z2,z4,z6,z8,z10,z12,z14,z16,z18,z1,z3,z5,z7,z9,z11,z13,z15,z17,z19,p0,z28,z29,z20,z21,z22,z23,z24,z25,z26,z27,x1,x3) " \n\t" " add x0, x0, x2 \n\t" // Forward A's address to the next column. GEMM_ACOL_CONTIGUOUS_LOAD(z28,z29,p0,p1,x0) GEMM_2VX10_MKER_LOOP_PLAIN_C_2(z0,z2,z4,z6,z8,z10,z12,z14,z16,z18,z1,z3,z5,z7,z9,z11,z13,z15,z17,z19,p0,z30,z31,z20,z21,z22,z23,z24,z25,z26,z27,x1,x3) " \n\t" " add x0, x0, x2 \n\t" // Forward A's address to the next column. GEMM_ACOL_CONTIGUOUS_LOAD(z30,z31,p0,p1,x0) GEMM_2VX10_MKER_LOOP_PLAIN_C_3(z0,z2,z4,z6,z8,z10,z12,z14,z16,z18,z1,z3,z5,z7,z9,z11,z13,z15,z17,z19,p0,z28,z29,z20,z21,z22,z23,z24,z25,z26,z27,x1,x3) " \n\t" " subs x4, x4, #1 \n\t" // Decrease counter before final replica. BEQ(FIN_MKER_LOOP) // Branch early to avoid reading excess mem. " \n\t" " add x0, x0, x2 \n\t" // Forward A's address to the next column. GEMM_ACOL_CONTIGUOUS_LOAD(z28,z29,p0,p1,x0) GEMM_2VX10_MKER_LOOP_PLAIN_C_4(z0,z2,z4,z6,z8,z10,z12,z14,z16,z18,z1,z3,z5,z7,z9,z11,z13,z15,z17,z19,p0,z30,z31,z20,z21,z22,z23,z24,z25,z26,z27,x1,x3) BRANCH(K_MKER_LOOP) " \n\t" LABEL(FIN_MKER_LOOP) GEMM_2VX10_MKER_LOOP_PLAIN_C_4_RESIDUAL(z0,z2,z4,z6,z8,z10,z12,z14,z16,z18,z1,z3,z5,z7,z9,z11,z13,z15,z17,z19,p0,z30,z31,z20,z21,z22,z23,z24,z25,z26,z27,x1,x3) " add x0, x0, x2 \n\t" // Forward A to fill the blank. " \n\t" LABEL(K_LEFT_LOOP) " cmp x8, #0 \n\t" // End of execution. BEQ(WRITE_MEM_PREP) " \n\t" GEMM_ACOL_CONTIGUOUS_LOAD(z30,z31,p0,p1,x0) " ld1rd z20.d, p0/z, [x1] \n\t" // Load 8/10 of first B row. " ld1rd z21.d, p0/z, [x1, 8] \n\t" " ld1rd z22.d, p0/z, [x1, 16] \n\t" " ld1rd z23.d, p0/z, [x1, 24] \n\t" " ld1rd z24.d, p0/z, [x1, 32] \n\t" " ld1rd z25.d, p0/z, [x1, 40] \n\t" " ld1rd z26.d, p0/z, [x1, 48] \n\t" " ld1rd z27.d, p0/z, [x1, 56] \n\t" " ld1rd z28.d, p0/z, [x1, 64] \n\t" " ld1rd z29.d, p0/z, [x1, 72] \n\t" GEMM_FMLA2(z0,z1,p0,z30,z31,z20) GEMM_FMLA2(z2,z3,p0,z30,z31,z21) GEMM_FMLA2(z4,z5,p0,z30,z31,z22) GEMM_FMLA2(z6,z7,p0,z30,z31,z23) GEMM_FMLA2(z8,z9,p0,z30,z31,z24) GEMM_FMLA2(z10,z11,p0,z30,z31,z25) GEMM_FMLA2(z12,z13,p0,z30,z31,z26) GEMM_FMLA2(z14,z15,p0,z30,z31,z27) GEMM_FMLA2(z16,z17,p0,z30,z31,z28) GEMM_FMLA2(z18,z19,p0,z30,z31,z29) " add x0, x0, x2 \n\t" // Forward A. " add x1, x1, x3 \n\t" // Forward B. " sub x8, x8, #1 \n\t" BRANCH(K_LEFT_LOOP) " \n\t" LABEL(WRITE_MEM_PREP) " \n\t" " ldr x4, %[alpha] \n\t" // Load alpha & beta (address). " ldr x8, %[beta] \n\t" " ldr x4, [x4] \n\t" // Load alpha & beta (value). " ldr x8, [x8] \n\t" " dup z30.d, x4 \n\t" // Broadcast alpha & beta into vectors. " dup z31.d, x8 \n\t" " fmov d28, #1.0 \n\t" // Prepare FP 1.0. " fmov x16, d28 \n\t" " \n\t" LABEL(PREFETCH_ABNEXT) " ldr x0, %[a_next] \n\t" " ldr x1, %[b_next] \n\t" #ifdef _A64FX " mov x8, 0x2 \n\t" // Tag B address. " lsl x8, x8, #56 \n\t" " orr x1, x1, x8 \n\t" " mov x8, 0x1 \n\t" // Tag A address. " lsl x8, x8, #56 \n\t" " orr x0, x0, x8 \n\t" #endif " prfm PLDL1STRM, [x0] \n\t" " prfm PLDL1STRM, [x0, 256*1] \n\t" // " prfm PLDL2KEEP, [x0, 256*2] \n\t" // " prfm PLDL2KEEP, [x0, 256*3] \n\t" // " prfm PLDL2KEEP, [x0, 256*4] \n\t" // " prfm PLDL2KEEP, [x0, 256*5] \n\t" // " prfm PLDL2KEEP, [x0, 256*6] \n\t" // " prfm PLDL2KEEP, [x0, 256*7] \n\t" // " prfm PLDL2KEEP, [x0, 256*8] \n\t" // " prfm PLDL2KEEP, [x0, 256*9] \n\t" // " prfm PLDL2KEEP, [x0, 256*10] \n\t" // " prfm PLDL2KEEP, [x0, 256*11] \n\t" // " prfm PLDL2KEEP, [x0, 256*12] \n\t" // " prfm PLDL2KEEP, [x0, 256*13] \n\t" // " prfm PLDL2KEEP, [x0, 256*14] \n\t" // " prfm PLDL2KEEP, [x0, 256*15] \n\t" " prfm PLDL1STRM, [x1] \n\t" " prfm PLDL1STRM, [x1, 256*1] \n\t" // " prfm PLDL2KEEP, [x1, 256*2] \n\t" // " prfm PLDL2KEEP, [x1, 256*3] \n\t" // " prfm PLDL2KEEP, [x1, 256*4] \n\t" // " prfm PLDL2KEEP, [x1, 256*5] \n\t" // " prfm PLDL2KEEP, [x1, 256*6] \n\t" // " prfm PLDL2KEEP, [x1, 256*7] \n\t" // " prfm PLDL2KEEP, [x1, 256*8] \n\t" // " prfm PLDL2KEEP, [x1, 256*9] \n\t" " \n\t" " mov x9, x5 \n\t" // C address for loading. " \n\t" // C address for storing is x5 itself. // " cmp x6, #1 \n\t" // Preload first half of C for contiguous case. // BNE(WRITE_MEM) GEMM_C_LOAD_UKER_C(z20,z22,z24,z26,z28,z21,z23,z25,z27,z29,p0,p1,x9,x7) " \n\t" LABEL(WRITE_MEM) " \n\t" " cmp x16, x4 \n\t" BEQ(UNIT_ALPHA) " \n\t" SCALE_COL20(z0,z1,z2,z3,z4,z5,z6,z7,z8,z9,z10,z11,z12,z13,z14,z15,z16,z17,z18,z19,z30) " \n\t" LABEL(UNIT_ALPHA) // " cmp x6, #1 \n\t" // BNE(WRITE_MEM_G) " \n\t" LABEL(WRITE_MEM_C) " \n\t" // Available scratch: Z[20-30]. " \n\t" // Here used scratch: Z[20-29]. " fcmp d31, #0.0 \n\t" // Skip loading if *beta == 0 to override NaN. BEQ(BETA_ZERO_C) // First half of C is already loaded in this case. // GEMM_C_FMAD_LOAD_UKER_C(z20,z22,z24,z26,z28,z21,z23,z25,z27,z29,p0,p1,z0,z2,z4,z6,z8,z1,z3,z5,z7,z9,z31,x9,x7) GEMM_C_FMLA_UKER(z0,z2,z4,z6,z8,z1,z3,z5,z7,z9,p0,z20,z22,z24,z26,z28,z21,z23,z25,z27,z29,z31) GEMM_C_LOAD_UKER_C(z20,z22,z24,z26,z28,z21,z23,z25,z27,z29,p0,p1,x9,x7) GEMM_C_FMLA_UKER(z10,z12,z14,z16,z18,z11,z13,z15,z17,z19,p0,z20,z22,z24,z26,z28,z21,z23,z25,z27,z29,z31) " \n\t" LABEL(BETA_ZERO_C) GEMM_C_STORE_UKER_C(z0,z2,z4,z6,z8,z1,z3,z5,z7,z9,p0,p1,x5,x7) GEMM_C_STORE_UKER_C(z10,z12,z14,z16,z18,z11,z13,z15,z17,z19,p0,p1,x5,x7) // BRANCH(END_WRITE_MEM) // " \n\t" // LABEL(END_WRITE_MEM) // BRANCH(END_EXEC) // " \n\t" // LABEL(END_ERROR) // " mov x0, #1 \n\t" // Return error. LABEL(END_EXEC) " mov x0, #0 \n\t" // Return normal. : : [m] "m" (m), [a] "m" (a), [b] "m" (b), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c), [k_mker] "m" (k_mker), [k_left] "m" (k_left), [alpha] "m" (alpha), [beta] "m" (beta), [a_next] "m" (a_next), [b_next] "m" (b_next) : "x0","x1","x2","x3","x4","x5","x6","x7","x8", "x9","x16", "z0","z1","z2","z3","z4","z5","z6","z7", "z8","z9","z10","z11","z12","z13","z14","z15", "z16","z17","z18","z19", "z20","z21","z22","z23", "z24","z25","z26","z27", "z28","z29","z30","z31" ); GEMM_UKR_FLUSH_CT( d ); } blis-0.9.0/kernels/armsve/3/bli_gemm_armsve_asm_s2vx10_unindexed.c000066400000000000000000000360361422157504600251130ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2020, The University of Tokyo Copyright (C) 2019, Forschunszentrum Juelich 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // Single-precision composite instructions. #include "armsve_asm_macros_single.h" // 2vx10 microkernels. #include "armsve_asm_2vx10.h" void bli_sgemm_armsve_asm_2vx10_unindexed ( dim_t m, dim_t n, dim_t k, float* restrict alpha, float* restrict a, float* restrict b, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { void* a_next = bli_auxinfo_next_a( data ); void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_mker = k / 4; uint64_t k_left = k % 4; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; GEMM_UKR_SETUP_CT( s, m, 10, false ); __asm__ volatile ( " mov x0, xzr \n\t" " ldr x1, %[m] \n\t" " whilelo p0.s, x0, x1 \n\t" " incw x0 \n\t" " whilelo p1.s, x0, x1 \n\t" " \n\t" " ldr x0, %[a] \n\t" " ldr x1, %[b] \n\t" " mov x2, xzr \n\t" " incw x2, ALL, MUL #2 \n\t" // Column-skip of A. " mov x3, #10 \n\t" // Row-skip of B. " \n\t" " ldr x5, %[c] \n\t" // " ldr x6, %[rs_c] \n\t" // Row-skip of C. " ldr x7, %[cs_c] \n\t" // Column-skip of C. #ifdef _A64FX " mov x8, 0x3 \n\t" // Tag C address. " lsl x8, x8, #56 \n\t" " orr x5, x5, x8 \n\t" " mov x8, 0x2 \n\t" // Tag B address. " lsl x8, x8, #56 \n\t" " orr x1, x1, x8 \n\t" " mov x8, 0x1 \n\t" // Tag A address. " lsl x8, x8, #56 \n\t" " orr x0, x0, x8 \n\t" #endif " \n\t" " mov x8, #4 \n\t" // Multiply some address skips by sizeof(float). " madd x2, x8, x2, xzr \n\t" // cs_a " madd x3, x8, x3, xzr \n\t" // rs_b " madd x7, x8, x7, xzr \n\t" // cs_c " \n\t" " ldr x4, %[k_mker] \n\t" // Number of loops. " ldr x8, %[k_left] \n\t" " \n\t" LABEL(LOAD_ABC) " cmp x4, #0 \n\t" // Don't preload if no microkernel there. BEQ(END_CCOL_PRFM) " ld1rw z20.s, p0/z, [x1] \n\t" // Load 8/10 of first B row. " ld1rw z21.s, p0/z, [x1, 4] \n\t" " ld1rw z22.s, p0/z, [x1, 8] \n\t" " ld1rw z23.s, p0/z, [x1, 12] \n\t" " ld1rw z24.s, p0/z, [x1, 16] \n\t" " ld1rw z25.s, p0/z, [x1, 20] \n\t" " ld1rw z26.s, p0/z, [x1, 24] \n\t" " ld1rw z27.s, p0/z, [x1, 28] \n\t" " \n\t" GEMM_ACOL_CONTIGUOUS_LOAD(z28,z29,p0,p1,x0) " \n\t" LABEL(CCOL_PRFM) // " cmp x6, #1 \n\t" // BNE(END_CCOL_PRFM) // Do not prefetch for generic C storage. " mov x16, x5 \n\t" " prfm PLDL1STRM, [x16] \n\t" " add x16, x16, x7 \n\t" " prfm PLDL1STRM, [x16] \n\t" " add x16, x16, x7 \n\t" " prfm PLDL1STRM, [x16] \n\t" " add x16, x16, x7 \n\t" " prfm PLDL1STRM, [x16] \n\t" " add x16, x16, x7 \n\t" " prfm PLDL1STRM, [x16] \n\t" " add x16, x16, x7 \n\t" " prfm PLDL1STRM, [x16] \n\t" " add x16, x16, x7 \n\t" " prfm PLDL1STRM, [x16] \n\t" " add x16, x16, x7 \n\t" " prfm PLDL1STRM, [x16] \n\t" " add x16, x16, x7 \n\t" " prfm PLDL1STRM, [x16] \n\t" " add x16, x16, x7 \n\t" " prfm PLDL1STRM, [x16] \n\t" LABEL(END_CCOL_PRFM) " \n\t" CLEAR_COL20(z0,z1,z2,z3,z4,z5,z6,z7,z8,z9,z10,z11,z12,z13,z14,z15,z16,z17,z18,z19) " \n\t" " cmp x4, #0 \n\t" // If no 4-microkernel can be applied BEQ(K_LEFT_LOOP) " \n\t" LABEL(K_MKER_LOOP) " \n\t" " add x0, x0, x2 \n\t" // Forward A's address to the next column. GEMM_ACOL_CONTIGUOUS_LOAD(z30,z31,p0,p1,x0) GEMM_2VX10_MKER_LOOP_PLAIN_C_1(z0,z2,z4,z6,z8,z10,z12,z14,z16,z18,z1,z3,z5,z7,z9,z11,z13,z15,z17,z19,p0,z28,z29,z20,z21,z22,z23,z24,z25,z26,z27,x1,x3) " \n\t" " add x0, x0, x2 \n\t" // Forward A's address to the next column. GEMM_ACOL_CONTIGUOUS_LOAD(z28,z29,p0,p1,x0) GEMM_2VX10_MKER_LOOP_PLAIN_C_2(z0,z2,z4,z6,z8,z10,z12,z14,z16,z18,z1,z3,z5,z7,z9,z11,z13,z15,z17,z19,p0,z30,z31,z20,z21,z22,z23,z24,z25,z26,z27,x1,x3) " \n\t" " add x0, x0, x2 \n\t" // Forward A's address to the next column. GEMM_ACOL_CONTIGUOUS_LOAD(z30,z31,p0,p1,x0) GEMM_2VX10_MKER_LOOP_PLAIN_C_3(z0,z2,z4,z6,z8,z10,z12,z14,z16,z18,z1,z3,z5,z7,z9,z11,z13,z15,z17,z19,p0,z28,z29,z20,z21,z22,z23,z24,z25,z26,z27,x1,x3) " \n\t" " subs x4, x4, #1 \n\t" // Decrease counter before final replica. BEQ(FIN_MKER_LOOP) // Branch early to avoid reading excess mem. " \n\t" " add x0, x0, x2 \n\t" // Forward A's address to the next column. GEMM_ACOL_CONTIGUOUS_LOAD(z28,z29,p0,p1,x0) GEMM_2VX10_MKER_LOOP_PLAIN_C_4(z0,z2,z4,z6,z8,z10,z12,z14,z16,z18,z1,z3,z5,z7,z9,z11,z13,z15,z17,z19,p0,z30,z31,z20,z21,z22,z23,z24,z25,z26,z27,x1,x3) BRANCH(K_MKER_LOOP) " \n\t" LABEL(FIN_MKER_LOOP) GEMM_2VX10_MKER_LOOP_PLAIN_C_4_RESIDUAL(z0,z2,z4,z6,z8,z10,z12,z14,z16,z18,z1,z3,z5,z7,z9,z11,z13,z15,z17,z19,p0,z30,z31,z20,z21,z22,z23,z24,z25,z26,z27,x1,x3) " add x0, x0, x2 \n\t" // Forward A to fill the blank. " \n\t" LABEL(K_LEFT_LOOP) " cmp x8, #0 \n\t" // End of execution. BEQ(WRITE_MEM_PREP) " \n\t" GEMM_ACOL_CONTIGUOUS_LOAD(z30,z31,p0,p1,x0) " ld1rw z20.s, p0/z, [x1] \n\t" // Load 8/10 of first B row. " ld1rw z21.s, p0/z, [x1, 4] \n\t" " ld1rw z22.s, p0/z, [x1, 8] \n\t" " ld1rw z23.s, p0/z, [x1, 12] \n\t" " ld1rw z24.s, p0/z, [x1, 16] \n\t" " ld1rw z25.s, p0/z, [x1, 20] \n\t" " ld1rw z26.s, p0/z, [x1, 24] \n\t" " ld1rw z27.s, p0/z, [x1, 28] \n\t" " ld1rw z28.s, p0/z, [x1, 32] \n\t" " ld1rw z29.s, p0/z, [x1, 36] \n\t" GEMM_FMLA2(z0,z1,p0,z30,z31,z20) GEMM_FMLA2(z2,z3,p0,z30,z31,z21) GEMM_FMLA2(z4,z5,p0,z30,z31,z22) GEMM_FMLA2(z6,z7,p0,z30,z31,z23) GEMM_FMLA2(z8,z9,p0,z30,z31,z24) GEMM_FMLA2(z10,z11,p0,z30,z31,z25) GEMM_FMLA2(z12,z13,p0,z30,z31,z26) GEMM_FMLA2(z14,z15,p0,z30,z31,z27) GEMM_FMLA2(z16,z17,p0,z30,z31,z28) GEMM_FMLA2(z18,z19,p0,z30,z31,z29) " add x0, x0, x2 \n\t" // Forward A. " add x1, x1, x3 \n\t" // Forward B. " sub x8, x8, #1 \n\t" BRANCH(K_LEFT_LOOP) " \n\t" LABEL(WRITE_MEM_PREP) " \n\t" " ldr x4, %[alpha] \n\t" // Load alpha & beta (address). " ldr x8, %[beta] \n\t" " ldr w4, [x4] \n\t" // Load alpha & beta (value). " ldr w8, [x8] \n\t" " dup z30.s, w4 \n\t" // Broadcast alpha & beta into vectors. " dup z31.s, w8 \n\t" " \n\t" LABEL(PREFETCH_ABNEXT) " ldr x0, %[a_next] \n\t" " ldr x1, %[b_next] \n\t" " prfm PLDL2KEEP, [x0] \n\t" " prfm PLDL2KEEP, [x0, 256*1] \n\t" " prfm PLDL2KEEP, [x0, 256*2] \n\t" " prfm PLDL2KEEP, [x0, 256*3] \n\t" " prfm PLDL2KEEP, [x0, 256*4] \n\t" " prfm PLDL2KEEP, [x0, 256*5] \n\t" " prfm PLDL2KEEP, [x0, 256*6] \n\t" " prfm PLDL2KEEP, [x0, 256*7] \n\t" " prfm PLDL2KEEP, [x0, 256*8] \n\t" " prfm PLDL2KEEP, [x0, 256*9] \n\t" " prfm PLDL2KEEP, [x0, 256*10] \n\t" " prfm PLDL2KEEP, [x0, 256*11] \n\t" " prfm PLDL2KEEP, [x0, 256*12] \n\t" " prfm PLDL2KEEP, [x0, 256*13] \n\t" " prfm PLDL2KEEP, [x0, 256*14] \n\t" " prfm PLDL2KEEP, [x0, 256*15] \n\t" " prfm PLDL2KEEP, [x1] \n\t" " prfm PLDL2KEEP, [x1, 256*1] \n\t" " prfm PLDL2KEEP, [x1, 256*2] \n\t" " prfm PLDL2KEEP, [x1, 256*3] \n\t" " prfm PLDL2KEEP, [x1, 256*4] \n\t" " prfm PLDL2KEEP, [x1, 256*5] \n\t" " prfm PLDL2KEEP, [x1, 256*6] \n\t" " prfm PLDL2KEEP, [x1, 256*7] \n\t" " prfm PLDL2KEEP, [x1, 256*8] \n\t" " prfm PLDL2KEEP, [x1, 256*9] \n\t" " \n\t" LABEL(WRITE_MEM) " \n\t" " fmov s28, #1.0 \n\t" " fmov w16, s28 \n\t" " cmp w16, w4 \n\t" BEQ(UNIT_ALPHA) " \n\t" SCALE_COL20(z0,z1,z2,z3,z4,z5,z6,z7,z8,z9,z10,z11,z12,z13,z14,z15,z16,z17,z18,z19,z30) " \n\t" LABEL(UNIT_ALPHA) " mov x9, x5 \n\t" // C address for loading. " \n\t" // C address for storing is x5 itself. // " cmp x6, #1 \n\t" // BNE(WRITE_MEM_G) " \n\t" LABEL(WRITE_MEM_C) " \n\t" // Available scratch: Z[20-30]. " \n\t" // Here used scratch: Z[20-29]. " fcmp s31, #0.0 \n\t" BEQ(BETA_ZERO_C) GEMM_C_LOAD_UKER_C(z20,z22,z24,z26,z28,z21,z23,z25,z27,z29,p0,p1,x9,x7) GEMM_C_FMLA_UKER(z0,z2,z4,z6,z8,z1,z3,z5,z7,z9,p0,z20,z22,z24,z26,z28,z21,z23,z25,z27,z29,z31) GEMM_C_LOAD_UKER_C(z20,z22,z24,z26,z28,z21,z23,z25,z27,z29,p0,p1,x9,x7) GEMM_C_FMLA_UKER(z10,z12,z14,z16,z18,z11,z13,z15,z17,z19,p0,z20,z22,z24,z26,z28,z21,z23,z25,z27,z29,z31) " \n\t" LABEL(BETA_ZERO_C) GEMM_C_STORE_UKER_C(z0,z2,z4,z6,z8,z1,z3,z5,z7,z9,p0,p1,x5,x7) GEMM_C_STORE_UKER_C(z10,z12,z14,z16,z18,z11,z13,z15,z17,z19,p0,p1,x5,x7) // BRANCH(END_WRITE_MEM) // " \n\t" // LABEL(END_WRITE_MEM) // BRANCH(END_EXEC) // " \n\t" // LABEL(END_ERROR) // " mov x0, #1 \n\t" // Return error. LABEL(END_EXEC) " mov x0, #0 \n\t" // Return normal. : : [m] "m" (m), [a] "m" (a), [b] "m" (b), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c), [k_mker] "m" (k_mker), [k_left] "m" (k_left), [alpha] "m" (alpha), [beta] "m" (beta), [a_next] "m" (a_next), [b_next] "m" (b_next) : "x0","x1","x2","x3","x4","x5","x6","x7","x8", "x9","x16", "z0","z1","z2","z3","z4","z5","z6","z7", "z8","z9","z10","z11","z12","z13","z14","z15", "z16","z17","z18","z19", "z20","z21","z22","z23", "z24","z25","z26","z27", "z28","z29","z30","z31" ); GEMM_UKR_FLUSH_CT( s ); } blis-0.9.0/kernels/armsve/3/bli_gemm_armsve_asm_z2vx10_unindexed.c000066400000000000000000000373711422157504600251250ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2019, Forschunszentrum Juelich Copyright (C) 2020, The University of Tokyo 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // Double-precision composite instructions. #include "armsve_asm_macros_dcomplex.h" // 2vx10 microkernels. #include "armsve_asm_2vx10cmplx.h" void bli_zgemm_armsve_asm_2vx10_unindexed ( dim_t m, dim_t n, dim_t k, dcomplex* restrict alpha, dcomplex* restrict a, dcomplex* restrict b, dcomplex* restrict beta, dcomplex* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { void* a_next = bli_auxinfo_next_a( data ); void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_mker = k / 4; uint64_t k_left = k % 4; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; uint64_t info = 0; GEMM_UKR_SETUP_CT( z, m, 10, false ); __asm__ volatile ( " whilelo p0.d, xzr, %12 \n\t" // " ldr x0, %[a] \n\t" // " ldr x1, %[b] \n\t" " mov x2, xzr \n\t" " incd x2, ALL, MUL #1 \n\t" // Column-skip of A. " mov x3, #10 \n\t" // Row-skip of B. " \n\t" // " ldr x2, %[c] \n\t" // " ldr x3, %[rs_c] \n\t" // Row-skip of C. // " ldr x4, %[cs_c] \n\t" // Column-skip of C. #ifdef _A64FX " mov x16, 0x1 \n\t" // Tag A address. " lsl x16, x16, #56 \n\t" " orr %0, %0, x16 \n\t" " mov x16, 0x2 \n\t" // Tag B address. " lsl x16, x16, #56 \n\t" " orr %1, %1, x16 \n\t" " mov x16, 0x3 \n\t" // Tag C address. " lsl x16, x16, #56 \n\t" " orr %2, %2, x16 \n\t" #endif " \n\t" " mov x16, #16 \n\t" // Multiply some address skips by sizeof(dcomplex). " madd x2, x16, x2, xzr \n\t" // cs_a " madd x3, x16, x3, xzr \n\t" // rs_b " madd %4, x16, %4, xzr \n\t" // cs_c " \n\t" // " ldr x5, %[k_mker] \n\t" // Number of loops. // " ldr x6, %[k_left] \n\t" " \n\t" LABEL(LOAD_ABC) " cmp %5, #0 \n\t" // Don't preload if no microkernel there. BEQ(END_CCOL_PRFM) " \n\t" " ld1rd z20.d, p0/z, [%1, 8*0] \n\t" // Load B's real 8/10, no imaginary. " ld1rd z21.d, p0/z, [%1, 8*2] \n\t" " ld1rd z22.d, p0/z, [%1, 8*4] \n\t" " ld1rd z23.d, p0/z, [%1, 8*6] \n\t" " ld1rd z24.d, p0/z, [%1, 8*8] \n\t" " ld1rd z25.d, p0/z, [%1, 8*10] \n\t" " ld1rd z26.d, p0/z, [%1, 8*12] \n\t" " ld1rd z27.d, p0/z, [%1, 8*14] \n\t" " \n\t" GEMM_ACOLCMPLX_CONTIGUOUS_LOAD_FWD(z28,z29,p0,%0,x2) " \n\t" LABEL(CCOL_PRFM) // " cmp %3, #1 \n\t" // BNE(END_CCOL_PRFM) // Do not prefetch for generic C storage. " mov x16, %2 \n\t" " prfm PLDL1KEEP, [x16] \n\t" " add x16, x16, %4 \n\t" " prfm PLDL1KEEP, [x16] \n\t" " add x16, x16, %4 \n\t" " prfm PLDL1KEEP, [x16] \n\t" " add x16, x16, %4 \n\t" " prfm PLDL1KEEP, [x16] \n\t" " add x16, x16, %4 \n\t" " prfm PLDL1KEEP, [x16] \n\t" " add x16, x16, %4 \n\t" " prfm PLDL1KEEP, [x16] \n\t" " add x16, x16, %4 \n\t" " prfm PLDL1KEEP, [x16] \n\t" " add x16, x16, %4 \n\t" " prfm PLDL1KEEP, [x16] \n\t" " add x16, x16, %4 \n\t" " prfm PLDL1KEEP, [x16] \n\t" " add x16, x16, %4 \n\t" " prfm PLDL1KEEP, [x16] \n\t" LABEL(END_CCOL_PRFM) " \n\t" CLEAR_COL20(z0,z1,z2,z3,z4,z5,z6,z7,z8,z9,z10,z11,z12,z13,z14,z15,z16,z17,z18,z19) " \n\t" " cmp %5, #0 \n\t" // If no 4-microkernel can be applied. BEQ(K_LEFT_LOOP) " \n\t" LABEL(K_MKER_LOOP) " \n\t" GEMM_ACOLCMPLX_CONTIGUOUS_LOAD_FWD(z30,z31,p0,%0,x2) GEMM_2VX10CMPLX_MKER_LOOP_PLAIN_C_1(z0,z2,z4,z6,z8,z10,z12,z14,z16,z18,z1,z3,z5,z7,z9,z11,z13,z15,z17,z19,p0,z28,z29,z20,z21,z22,z23,z24,z25,z26,z27,%1,x3) " \n\t" GEMM_ACOLCMPLX_CONTIGUOUS_LOAD_FWD(z28,z29,p0,%0,x2) GEMM_2VX10CMPLX_MKER_LOOP_PLAIN_C_2(z0,z2,z4,z6,z8,z10,z12,z14,z16,z18,z1,z3,z5,z7,z9,z11,z13,z15,z17,z19,p0,z30,z31,z20,z21,z22,z23,z24,z25,z26,z27,%1,x3) " \n\t" GEMM_ACOLCMPLX_CONTIGUOUS_LOAD_FWD(z30,z31,p0,%0,x2) GEMM_2VX10CMPLX_MKER_LOOP_PLAIN_C_1(z0,z2,z4,z6,z8,z10,z12,z14,z16,z18,z1,z3,z5,z7,z9,z11,z13,z15,z17,z19,p0,z28,z29,z20,z21,z22,z23,z24,z25,z26,z27,%1,x3) " \n\t" " subs %5, %5, #1 \n\t" // Decrease counter before final replica. BEQ(FIN_MKER_LOOP) // Branch early to avoid reading excess mem. " \n\t" GEMM_ACOLCMPLX_CONTIGUOUS_LOAD_FWD(z28,z29,p0,%0,x2) GEMM_2VX10CMPLX_MKER_LOOP_PLAIN_C_2(z0,z2,z4,z6,z8,z10,z12,z14,z16,z18,z1,z3,z5,z7,z9,z11,z13,z15,z17,z19,p0,z30,z31,z20,z21,z22,z23,z24,z25,z26,z27,%1,x3) BRANCH(K_MKER_LOOP) " \n\t" LABEL(FIN_MKER_LOOP) GEMM_2VX10CMPLX_MKER_LOOP_PLAIN_C_2_RESIDUAL(z0,z2,z4,z6,z8,z10,z12,z14,z16,z18,z1,z3,z5,z7,z9,z11,z13,z15,z17,z19,p0,z30,z31,z20,z21,z22,z23,z24,z25,z26,z27,%1,x3) " \n\t" LABEL(K_LEFT_LOOP) " cmp %6, #0 \n\t" // End of execution. BEQ(WRITE_MEM_PREP) " \n\t" GEMM_ACOLCMPLX_CONTIGUOUS_LOAD_FWD(z28,z29,p0,%0,x2) " ld1rd z20.d, p0/z, [%1, 8*0] \n\t" // Load B's real 8/10, no imaginary. " ld1rd z21.d, p0/z, [%1, 8*2] \n\t" " ld1rd z22.d, p0/z, [%1, 8*4] \n\t" " ld1rd z23.d, p0/z, [%1, 8*6] \n\t" " ld1rd z24.d, p0/z, [%1, 8*8] \n\t" " ld1rd z25.d, p0/z, [%1, 8*10] \n\t" " ld1rd z26.d, p0/z, [%1, 8*12] \n\t" " ld1rd z27.d, p0/z, [%1, 8*14] \n\t" GEMM_2VX10CMPLX_MKER_LOOP_PLAIN_C_1_RESIDUAL(z0,z2,z4,z6,z8,z10,z12,z14,z16,z18,z1,z3,z5,z7,z9,z11,z13,z15,z17,z19,p0,z28,z29,z20,z21,z22,z23,z24,z25,z26,z27,%1,x3) " sub %6, %6, #1 \n\t" BRANCH(K_LEFT_LOOP) " \n\t" LABEL(WRITE_MEM_PREP) " \n\t" // " ldr x7, %[alpha] \n\t" // Load alpha & beta (address). // " ldr x8, %[beta] \n\t" " ld1rd z28.d, p0/z, [%7] \n\t" // Real(alpha). " ld1rd z29.d, p0/z, [%7, 8] \n\t" // Imag(alpha). " ld1rd z30.d, p0/z, [%8] \n\t" // Real(beta). " ld1rd z31.d, p0/z, [%8, 8] \n\t" // Imag(beta). " \n\t" LABEL(PREFETCH_ABNEXT) // " ldr x9, %[a_next] \n\t" // " ldr x10, %[b_next] \n\t" #ifdef _A64FX " mov x16, 0x1 \n\t" // Tag A address. " lsl x16, x16, #56 \n\t" " orr %9, %9, x16 \n\t" " mov x16, 0x2 \n\t" // Tag B address. " lsl x16, x16, #56 \n\t" " orr %10, %10, x16 \n\t" #endif " prfm PLDL1STRM, [%9] \n\t" " prfm PLDL1STRM, [%9, 256*1] \n\t" " prfm PLDL1STRM, [%10] \n\t" " prfm PLDL1STRM, [%10, 256*1] \n\t" " \n\t" LABEL(WRITE_MEM) " fmov d27, #1.0 \n\t" " fcmp d29, #0.0 \n\t" // Whether Imag(alpha) == 0. " fccmp d28, d27, 0, eq \n\t" // Whether Real(alpha) == 1. BEQ(UNIT_ALPHA) " \n\t" GEMM_FMULCMPLX_COL2(z20,z21,z22,z23,p0,z0 ,z1 ,z2 ,z3 ,z28,z29) GEMM_FMULCMPLX_COL2(z24,z25,z26,z27,p0,z4 ,z5 ,z6 ,z7 ,z28,z29) GEMM_FMULCMPLX_COL2(z0 ,z1 ,z2 ,z3 ,p0,z8, z9, z10,z11,z28,z29) GEMM_FMULCMPLX_COL2(z4 ,z5 ,z6 ,z7 ,p0,z12,z13,z14,z15,z28,z29) GEMM_FMULCMPLX_COL2(z8 ,z9 ,z10,z11,p0,z16,z17,z18,z19,z28,z29) BRANCH(WRITE_MEM_EXEC) " \n\t" LABEL(UNIT_ALPHA) MOV_COL2(z20,z21,z22,z23,z0 ,z1 ,z2 ,z3 ) MOV_COL2(z24,z25,z26,z27,z4 ,z5 ,z6 ,z7 ) MOV_COL2(z0 ,z1 ,z2 ,z3 ,z8, z9, z10,z11) MOV_COL2(z4 ,z5 ,z6 ,z7 ,z12,z13,z14,z15) MOV_COL2(z8 ,z9 ,z10,z11,z16,z17,z18,z19) " \n\t" LABEL(WRITE_MEM_EXEC) " mov x9, %2 \n\t" // C address for loading. " \n\t" // C address for storing is %2 itself. // " cmp %3, #1 \n\t" // BNE(WRITE_MEM_G) " \n\t" LABEL(WRITE_MEM_C) " fmov d29, xzr \n\t" " fcmp d31, #0.0 \n\t" // Whether Imag(beta) == 0. " fccmp d30, d29, 0, eq \n\t" // Whether Real(beta) == 0. BEQ(ZERO_BETA_C_0_1_2_3) GEMM_CCMPLX_LOAD_COL2_C(z12,z13,z14,z15,p0,x9,%4) GEMM_CCMPLX_LOAD_COL2_C(z16,z17,z18,z19,p0,x9,%4) GEMM_FMLACMPLX_COL2(z20,z21,z22,z23,p0,z12,z13,z14,z15,z30,z31) GEMM_FMLACMPLX_COL2(z24,z25,z26,z27,p0,z16,z17,z18,z19,z30,z31) LABEL(ZERO_BETA_C_0_1_2_3) GEMM_CCMPLX_STORE_COL2_C(z20,z21,z22,z23,p0,%2,%4) GEMM_CCMPLX_STORE_COL2_C(z24,z25,z26,z27,p0,%2,%4) " \n\t" BEQ(ZERO_BETA_C_4_5_6_7_8_9) GEMM_CCMPLX_LOAD_COL2_C(z12,z13,z14,z15,p0,x9,%4) GEMM_CCMPLX_LOAD_COL2_C(z16,z17,z18,z19,p0,x9,%4) GEMM_CCMPLX_LOAD_COL2_C(z20,z21,z22,z23,p0,x9,%4) GEMM_FMLACMPLX_COL2(z0 ,z1 ,z2 ,z3 ,p0,z12,z13,z14,z15,z30,z31) GEMM_FMLACMPLX_COL2(z4 ,z5 ,z6 ,z7 ,p0,z16,z17,z18,z19,z30,z31) GEMM_FMLACMPLX_COL2(z8 ,z9 ,z10,z11,p0,z20,z21,z22,z23,z30,z31) LABEL(ZERO_BETA_C_4_5_6_7_8_9) GEMM_CCMPLX_STORE_COL2_C(z0 ,z1 ,z2 ,z3 ,p0,%2,%4) GEMM_CCMPLX_STORE_COL2_C(z4 ,z5 ,z6 ,z7 ,p0,%2,%4) GEMM_CCMPLX_STORE_COL2_C(z8 ,z9 ,z10,z11,p0,%2,%4) // BRANCH(END_WRITE_MEM) // " \n\t" // LABEL(WRITE_MEM_G) // " add %3, %3, %3 \n\t" // Skips passed to index is multiplied by 2, // " index z28.d, xzr, %3 \n\t" // s.t. 2*sizeof(double) = 2*8 = 16. // " fmov d29, xzr \n\t" // " fcmp d31, #0.0 \n\t" // Whether Imag(beta) == 0. // " fccmp d30, d29, 0, eq \n\t" // Whether Real(beta) == 0. // BEQ(ZERO_BETA_G_0_1_2_3) // GEMM_CCMPLX_LOAD_COL2_G(z12,z13,z14,z15,p0,z28,x9,%4,x16) // GEMM_CCMPLX_LOAD_COL2_G(z16,z17,z18,z19,p0,z28,x9,%4,x16) // GEMM_FMLACMPLX_COL2(z20,z21,z22,z23,p0,z12,z13,z14,z15,z30,z31) // GEMM_FMLACMPLX_COL2(z24,z25,z26,z27,p0,z16,z17,z18,z19,z30,z31) // LABEL(ZERO_BETA_G_0_1_2_3) // GEMM_CCMPLX_STORE_COL2_G(z20,z21,z22,z23,p0,z28,%2,%4,x16) // GEMM_CCMPLX_STORE_COL2_G(z24,z25,z26,z27,p0,z28,%2,%4,x16) // " \n\t" // BEQ(ZERO_BETA_G_4_5_6_7_8_9) // GEMM_CCMPLX_LOAD_COL2_G(z12,z13,z14,z15,p0,z28,x9,%4,x16) // GEMM_CCMPLX_LOAD_COL2_G(z16,z17,z18,z19,p0,z28,x9,%4,x16) // GEMM_CCMPLX_LOAD_COL2_G(z20,z21,z22,z23,p0,z28,x9,%4,x16) // GEMM_FMLACMPLX_COL2(z0 ,z1 ,z2 ,z3 ,p0,z12,z13,z14,z15,z30,z31) // GEMM_FMLACMPLX_COL2(z4 ,z5 ,z6 ,z7 ,p0,z16,z17,z18,z19,z30,z31) // GEMM_FMLACMPLX_COL2(z8 ,z9 ,z10,z11,p0,z20,z21,z22,z23,z30,z31) // LABEL(ZERO_BETA_G_4_5_6_7_8_9) // GEMM_CCMPLX_STORE_COL2_G(z0 ,z1 ,z2 ,z3 ,p0,z28,%2,%4,x16) // GEMM_CCMPLX_STORE_COL2_G(z4 ,z5 ,z6 ,z7 ,p0,z28,%2,%4,x16) // GEMM_CCMPLX_STORE_COL2_G(z8 ,z9 ,z10,z11,p0,z28,%2,%4,x16) // " \n\t" // LABEL(END_WRITE_MEM) // BRANCH(END_EXEC) // " \n\t" LABEL(END_EXEC) " mov %11, #0 \n\t" // Return normal. : "+r" (a), // %0 "+r" (b), // %1 "+r" (c), // %2 "+r" (rs_c), // %3 "+r" (cs_c), // %4 "+r" (k_mker), // %5 "+r" (k_left), // %6 "+r" (alpha), // %7 "+r" (beta), // %8 "+r" (a_next), // %9 "+r" (b_next), // %10 "=r" (info) // %11 : "r" (m) // %12 : "x2","x3","x9","x16", "z0","z1","z2","z3","z4","z5","z6","z7", "z8","z9","z10","z11","z12","z13","z14","z15", "z16","z17","z18","z19", "z20","z21","z22","z23", "z24","z25","z26","z27", "z28","z29","z30","z31" ); GEMM_UKR_FLUSH_CT( z ); } blis-0.9.0/kernels/armsve/3/old/000077500000000000000000000000001422157504600163375ustar00rootroot00000000000000blis-0.9.0/kernels/armsve/3/old/armsve_asm_2vx7cmplx.h000066400000000000000000000174111422157504600226030ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2020, The University of Tokyo 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #define GEMM_2VX7CMPLX_MKER_LOOP_PLAIN_C(C0Re,C1Re,C2Re,C3Re,C4Re,C5Re,C6Re,C0Im,C1Im,C2Im,C3Im,C4Im,C5Im,C6Im,PT,AColRe,AColIm,B0Re,B1Re,B2Re,B3Re,B4Re,B5Re,B6Re,B0Im,B1Im,B2Im,B3Im,B4Im,B5Im,B6Im,BAddr,BRSBit) \ GEMM_FMLA2_LD1R(C0Re,C0Im,PT,AColRe,AColIm,B0Re,BAddr,0) \ GEMM_FMLA2_LD1R(C1Re,C1Im,PT,AColRe,AColIm,B1Re,BAddr,2) \ GEMM_FMLA2_LD1R(C2Re,C2Im,PT,AColRe,AColIm,B2Re,BAddr,4) \ GEMM_FMLA2_LD1R(C3Re,C3Im,PT,AColRe,AColIm,B3Re,BAddr,6) \ GEMM_FMLA2_LD1R(C4Re,C4Im,PT,AColRe,AColIm,B4Re,BAddr,8) \ GEMM_FMLA2_LD1R(C5Re,C5Im,PT,AColRe,AColIm,B5Re,BAddr,10) \ GEMM_FMLA2_LD1R(C6Re,C6Im,PT,AColRe,AColIm,B6Re,BAddr,12) \ GEMM_FMLX2_LD1R(C0Im,C0Re,PT,AColRe,AColIm,B0Im,BAddr,1) \ GEMM_FMLX2_LD1R(C1Im,C1Re,PT,AColRe,AColIm,B1Im,BAddr,3) \ GEMM_FMLX2_LD1R(C2Im,C2Re,PT,AColRe,AColIm,B2Im,BAddr,5) \ GEMM_FMLX2_LD1R(C3Im,C3Re,PT,AColRe,AColIm,B3Im,BAddr,7) \ GEMM_FMLX2_LD1R(C4Im,C4Re,PT,AColRe,AColIm,B4Im,BAddr,9) \ GEMM_FMLX2_LD1R(C5Im,C5Re,PT,AColRe,AColIm,B5Im,BAddr,11) \ GEMM_FMLX2_LD1R(C6Im,C6Re,PT,AColRe,AColIm,B6Im,BAddr,13) \ " add "#BAddr", "#BRSBit", "#BAddr" \n\t" #define GEMM_2VX7CMPLX_MKER_LOOP_PLAIN_C_RESIDUAL(C0Re,C1Re,C2Re,C3Re,C4Re,C5Re,C6Re,C0Im,C1Im,C2Im,C3Im,C4Im,C5Im,C6Im,PT,AColRe,AColIm,B0Re,B1Re,B2Re,B3Re,B4Re,B5Re,B6Re,B0Im,B1Im,B2Im,B3Im,B4Im,B5Im,B6Im,BAddr,BRSBit) \ GEMM_FMLA2(C0Re,C0Im,PT,AColRe,AColIm,B0Re) \ GEMM_FMLA2(C1Re,C1Im,PT,AColRe,AColIm,B1Re) \ GEMM_FMLA2(C2Re,C2Im,PT,AColRe,AColIm,B2Re) \ GEMM_FMLA2(C3Re,C3Im,PT,AColRe,AColIm,B3Re) \ GEMM_FMLA2(C4Re,C4Im,PT,AColRe,AColIm,B4Re) \ GEMM_FMLA2(C5Re,C5Im,PT,AColRe,AColIm,B5Re) \ GEMM_FMLA2(C6Re,C6Im,PT,AColRe,AColIm,B6Re) \ GEMM_FMLX2(C0Im,C0Re,PT,AColRe,AColIm,B0Im) \ GEMM_FMLX2(C1Im,C1Re,PT,AColRe,AColIm,B1Im) \ GEMM_FMLX2(C2Im,C2Re,PT,AColRe,AColIm,B2Im) \ GEMM_FMLX2(C3Im,C3Re,PT,AColRe,AColIm,B3Im) \ GEMM_FMLX2(C4Im,C4Re,PT,AColRe,AColIm,B4Im) \ GEMM_FMLX2(C5Im,C5Re,PT,AColRe,AColIm,B5Im) \ GEMM_FMLX2(C6Im,C6Re,PT,AColRe,AColIm,B6Im) #define CLEAR_COL14(Z00,Z01,Z02,Z03,Z04,Z05,Z06,Z07,Z08,Z09,Z10,Z11,Z12,Z13) \ CLEAR_COL4(Z00,Z01,Z02,Z03) \ CLEAR_COL4(Z04,Z05,Z06,Z07) \ CLEAR_COL4(Z08,Z09,Z10,Z11) \ CLEAR_COL2(Z12,Z13) #define GEMM_FMULCMPLX_COL7(ZD0Re,ZD0Im,ZD1Re,ZD1Im,ZD2Re,ZD2Im,ZD3Re,ZD3Im,ZD4Re,ZD4Im,ZD5Re,ZD5Im,ZD6Re,ZD6Im,PT,Z0Re,Z0Im,Z1Re,Z1Im,Z2Re,Z2Im,Z3Re,Z3Im,Z4Re,Z4Im,Z5Re,Z5Im,Z6Re,Z6Im,ZFactorRe,ZFactorIm) \ FMUL_COL2(ZD0Re,ZD0Im,Z0Re,Z0Im,ZFactorRe) \ FMUL_COL2(ZD1Re,ZD1Im,Z1Re,Z1Im,ZFactorRe) \ FMUL_COL2(ZD2Re,ZD2Im,Z2Re,Z2Im,ZFactorRe) \ FMUL_COL2(ZD3Re,ZD3Im,Z3Re,Z3Im,ZFactorRe) \ FMUL_COL2(ZD4Re,ZD4Im,Z4Re,Z4Im,ZFactorRe) \ FMUL_COL2(ZD5Re,ZD5Im,Z5Re,Z5Im,ZFactorRe) \ FMUL_COL2(ZD6Re,ZD6Im,Z6Re,Z6Im,ZFactorRe) \ GEMM_FMLX2(ZD0Im,ZD0Re,PT,Z0Re,Z0Im,ZFactorIm) \ GEMM_FMLX2(ZD1Im,ZD1Re,PT,Z1Re,Z1Im,ZFactorIm) \ GEMM_FMLX2(ZD2Im,ZD2Re,PT,Z2Re,Z2Im,ZFactorIm) \ GEMM_FMLX2(ZD3Im,ZD3Re,PT,Z3Re,Z3Im,ZFactorIm) \ GEMM_FMLX2(ZD4Im,ZD4Re,PT,Z4Re,Z4Im,ZFactorIm) \ GEMM_FMLX2(ZD5Im,ZD5Re,PT,Z5Re,Z5Im,ZFactorIm) \ GEMM_FMLX2(ZD6Im,ZD6Re,PT,Z6Re,Z6Im,ZFactorIm) #define GEMM_FMLACMPLX_COL7(ZD0Re,ZD0Im,ZD1Re,ZD1Im,ZD2Re,ZD2Im,ZD3Re,ZD3Im,ZD4Re,ZD4Im,ZD5Re,ZD5Im,ZD6Re,ZD6Im,PT,Z0Re,Z0Im,Z1Re,Z1Im,Z2Re,Z2Im,Z3Re,Z3Im,Z4Re,Z4Im,Z5Re,Z5Im,Z6Re,Z6Im,ZFactorRe,ZFactorIm) \ GEMM_FMLACMPLX(ZD0Re,ZD0Im,PT,Z0Re,Z0Im,ZFactorRe,ZFactorIm) \ GEMM_FMLACMPLX(ZD1Re,ZD1Im,PT,Z1Re,Z1Im,ZFactorRe,ZFactorIm) \ GEMM_FMLACMPLX(ZD2Re,ZD2Im,PT,Z2Re,Z2Im,ZFactorRe,ZFactorIm) \ GEMM_FMLACMPLX(ZD3Re,ZD3Im,PT,Z3Re,Z3Im,ZFactorRe,ZFactorIm) \ GEMM_FMLACMPLX(ZD4Re,ZD4Im,PT,Z4Re,Z4Im,ZFactorRe,ZFactorIm) \ GEMM_FMLACMPLX(ZD5Re,ZD5Im,PT,Z5Re,Z5Im,ZFactorRe,ZFactorIm) \ GEMM_FMLACMPLX(ZD6Re,ZD6Im,PT,Z6Re,Z6Im,ZFactorRe,ZFactorIm) #define GEMM_CCMPLX_LOAD_COL7_C(Z0Re,Z0Im,Z1Re,Z1Im,Z2Re,Z2Im,Z3Re,Z3Im,Z4Re,Z4Im,Z5Re,Z5Im,Z6Re,Z6Im,PT,CAddr,CCS) \ GEMM_CCOLCMPLX_CONTIGUOUS_LOAD_FWD(Z0Re,Z0Im,PT,CAddr,CCS) \ GEMM_CCOLCMPLX_CONTIGUOUS_LOAD_FWD(Z1Re,Z1Im,PT,CAddr,CCS) \ GEMM_CCOLCMPLX_CONTIGUOUS_LOAD_FWD(Z2Re,Z2Im,PT,CAddr,CCS) \ GEMM_CCOLCMPLX_CONTIGUOUS_LOAD_FWD(Z3Re,Z3Im,PT,CAddr,CCS) \ GEMM_CCOLCMPLX_CONTIGUOUS_LOAD_FWD(Z4Re,Z4Im,PT,CAddr,CCS) \ GEMM_CCOLCMPLX_CONTIGUOUS_LOAD_FWD(Z5Re,Z5Im,PT,CAddr,CCS) \ GEMM_CCOLCMPLX_CONTIGUOUS_LOAD_FWD(Z6Re,Z6Im,PT,CAddr,CCS) #define GEMM_CCMPLX_STORE_COL7_C(Z0Re,Z0Im,Z1Re,Z1Im,Z2Re,Z2Im,Z3Re,Z3Im,Z4Re,Z4Im,Z5Re,Z5Im,Z6Re,Z6Im,PT,CAddr,CCS) \ GEMM_CCOLCMPLX_CONTIGUOUS_STORE_FWD(Z0Re,Z0Im,PT,CAddr,CCS) \ GEMM_CCOLCMPLX_CONTIGUOUS_STORE_FWD(Z1Re,Z1Im,PT,CAddr,CCS) \ GEMM_CCOLCMPLX_CONTIGUOUS_STORE_FWD(Z2Re,Z2Im,PT,CAddr,CCS) \ GEMM_CCOLCMPLX_CONTIGUOUS_STORE_FWD(Z3Re,Z3Im,PT,CAddr,CCS) \ GEMM_CCOLCMPLX_CONTIGUOUS_STORE_FWD(Z4Re,Z4Im,PT,CAddr,CCS) \ GEMM_CCOLCMPLX_CONTIGUOUS_STORE_FWD(Z5Re,Z5Im,PT,CAddr,CCS) \ GEMM_CCOLCMPLX_CONTIGUOUS_STORE_FWD(Z6Re,Z6Im,PT,CAddr,CCS) #define GEMM_CCMPLX_LOAD_COL7_G(Z0Re,Z0Im,Z1Re,Z1Im,Z2Re,Z2Im,Z3Re,Z3Im,Z4Re,Z4Im,Z5Re,Z5Im,Z6Re,Z6Im,PT,ZIndex,CAddr,CCS,CTemp) \ GEMM_CCOLCMPLX_GATHER_LOAD_FWD(Z0Re,Z0Im,ZIndex,PT,PT,CAddr,CCS,CTemp) \ GEMM_CCOLCMPLX_GATHER_LOAD_FWD(Z1Re,Z1Im,ZIndex,PT,PT,CAddr,CCS,CTemp) \ GEMM_CCOLCMPLX_GATHER_LOAD_FWD(Z2Re,Z2Im,ZIndex,PT,PT,CAddr,CCS,CTemp) \ GEMM_CCOLCMPLX_GATHER_LOAD_FWD(Z3Re,Z3Im,ZIndex,PT,PT,CAddr,CCS,CTemp) \ GEMM_CCOLCMPLX_GATHER_LOAD_FWD(Z4Re,Z4Im,ZIndex,PT,PT,CAddr,CCS,CTemp) \ GEMM_CCOLCMPLX_GATHER_LOAD_FWD(Z5Re,Z5Im,ZIndex,PT,PT,CAddr,CCS,CTemp) \ GEMM_CCOLCMPLX_GATHER_LOAD_FWD(Z6Re,Z6Im,ZIndex,PT,PT,CAddr,CCS,CTemp) #define GEMM_CCMPLX_STORE_COL7_G(Z0Re,Z0Im,Z1Re,Z1Im,Z2Re,Z2Im,Z3Re,Z3Im,Z4Re,Z4Im,Z5Re,Z5Im,Z6Re,Z6Im,PT,ZIndex,CAddr,CCS,CTemp) \ GEMM_CCOLCMPLX_SCATTER_STORE_FWD(Z0Re,Z0Im,ZIndex,PT,PT,CAddr,CCS,CTemp) \ GEMM_CCOLCMPLX_SCATTER_STORE_FWD(Z1Re,Z1Im,ZIndex,PT,PT,CAddr,CCS,CTemp) \ GEMM_CCOLCMPLX_SCATTER_STORE_FWD(Z2Re,Z2Im,ZIndex,PT,PT,CAddr,CCS,CTemp) \ GEMM_CCOLCMPLX_SCATTER_STORE_FWD(Z3Re,Z3Im,ZIndex,PT,PT,CAddr,CCS,CTemp) \ GEMM_CCOLCMPLX_SCATTER_STORE_FWD(Z4Re,Z4Im,ZIndex,PT,PT,CAddr,CCS,CTemp) \ GEMM_CCOLCMPLX_SCATTER_STORE_FWD(Z5Re,Z5Im,ZIndex,PT,PT,CAddr,CCS,CTemp) \ GEMM_CCOLCMPLX_SCATTER_STORE_FWD(Z6Re,Z6Im,ZIndex,PT,PT,CAddr,CCS,CTemp) blis-0.9.0/kernels/armsve/3/old/armsve_asm_2vx8cmplx.h000066400000000000000000000153751422157504600226130ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2020, The University of Tokyo 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #define GEMM_2VX8CMPLX_MKER_LOOP_PLAIN_C_1(C0Re,C1Re,C2Re,C3Re,C4Re,C5Re,C6Re,C7Re,C0Im,C1Im,C2Im,C3Im,C4Im,C5Im,C6Im,C7Im,PT,AColRe,AColIm,BV0,BV1,BV2,BV3,BV4,BV5,BV6,BV7,BV8,BV9,BV10,BV11,BAddr,BRSBit) \ GEMM_FMLA2_LD1R(C0Re,C0Im,PT,AColRe,AColIm,BV0,BAddr,9) \ GEMM_FMLA2_LD1R(C1Re,C1Im,PT,AColRe,AColIm,BV1,BAddr,11) \ GEMM_FMLA2_LD1R(C2Re,C2Im,PT,AColRe,AColIm,BV2,BAddr,13) \ GEMM_FMLA2_LD1R(C3Re,C3Im,PT,AColRe,AColIm,BV3,BAddr,15) \ " add "#BAddr", "#BRSBit", "#BAddr" \n\t" /* B address forward */ \ GEMM_FMLA2_LD1R(C4Re,C4Im,PT,AColRe,AColIm,BV4,BAddr,0) \ GEMM_FMLA2_LD1R(C5Re,C5Im,PT,AColRe,AColIm,BV5,BAddr,2) \ GEMM_FMLA2_LD1R(C6Re,C6Im,PT,AColRe,AColIm,BV6,BAddr,4) \ GEMM_FMLA2_LD1R(C7Re,C7Im,PT,AColRe,AColIm,BV7,BAddr,6) \ \ GEMM_FMLX2_LD1R(C0Im,C0Re,PT,AColRe,AColIm,BV8,BAddr,8) \ GEMM_FMLX2_LD1R(C1Im,C1Re,PT,AColRe,AColIm,BV9,BAddr,10) \ GEMM_FMLX2_LD1R(C2Im,C2Re,PT,AColRe,AColIm,BV10,BAddr,12) \ GEMM_FMLX2_LD1R(C3Im,C3Re,PT,AColRe,AColIm,BV11,BAddr,14) \ GEMM_FMLX2_LD1R(C4Im,C4Re,PT,AColRe,AColIm,BV0,BAddr,1) \ GEMM_FMLX2_LD1R(C5Im,C5Re,PT,AColRe,AColIm,BV1,BAddr,3) \ GEMM_FMLX2_LD1R(C6Im,C6Re,PT,AColRe,AColIm,BV2,BAddr,5) \ GEMM_FMLX2_LD1R(C7Im,C7Re,PT,AColRe,AColIm,BV3,BAddr,7) #define GEMM_2VX8CMPLX_MKER_LOOP_PLAIN_C_2(C0Re,C1Re,C2Re,C3Re,C4Re,C5Re,C6Re,C7Re,C0Im,C1Im,C2Im,C3Im,C4Im,C5Im,C6Im,C7Im,PT,AColRe,AColIm,BV0,BV1,BV2,BV3,BV4,BV5,BV6,BV7,BV8,BV9,BV10,BV11,BAddr,BRSBit) \ GEMM_2VX8CMPLX_MKER_LOOP_PLAIN_C_1(C0Re,C1Re,C2Re,C3Re,C4Re,C5Re,C6Re,C7Re,C0Im,C1Im,C2Im,C3Im,C4Im,C5Im,C6Im,C7Im,PT,AColRe,AColIm,BV4,BV5,BV6,BV7,BV8,BV9,BV10,BV11,BV0,BV1,BV2,BV3,BAddr,BRSBit) #define GEMM_2VX8CMPLX_MKER_LOOP_PLAIN_C_3(C0Re,C1Re,C2Re,C3Re,C4Re,C5Re,C6Re,C7Re,C0Im,C1Im,C2Im,C3Im,C4Im,C5Im,C6Im,C7Im,PT,AColRe,AColIm,BV0,BV1,BV2,BV3,BV4,BV5,BV6,BV7,BV8,BV9,BV10,BV11,BAddr,BRSBit) \ GEMM_2VX8CMPLX_MKER_LOOP_PLAIN_C_1(C0Re,C1Re,C2Re,C3Re,C4Re,C5Re,C6Re,C7Re,C0Im,C1Im,C2Im,C3Im,C4Im,C5Im,C6Im,C7Im,PT,AColRe,AColIm,BV8,BV9,BV10,BV11,BV0,BV1,BV2,BV3,BV4,BV5,BV6,BV7,BAddr,BRSBit) #define GEMM_2VX8CMPLX_MKER_LOOP_PLAIN_C_1_RESIDUAL(C0Re,C1Re,C2Re,C3Re,C4Re,C5Re,C6Re,C7Re,C0Im,C1Im,C2Im,C3Im,C4Im,C5Im,C6Im,C7Im,PT,AColRe,AColIm,BV0,BV1,BV2,BV3,BV4,BV5,BV6,BV7,BV8,BV9,BV10,BV11,BAddr,BRSBit) \ GEMM_FMLA2_LD1R(C0Re,C0Im,PT,AColRe,AColIm,BV0,BAddr,9) \ GEMM_FMLA2_LD1R(C1Re,C1Im,PT,AColRe,AColIm,BV1,BAddr,11) \ GEMM_FMLA2_LD1R(C2Re,C2Im,PT,AColRe,AColIm,BV2,BAddr,13) \ GEMM_FMLA2_LD1R(C3Re,C3Im,PT,AColRe,AColIm,BV3,BAddr,15) \ " add "#BAddr", "#BRSBit", "#BAddr" \n\t" /* B address forward */ \ GEMM_FMLA2(C4Re,C4Im,PT,AColRe,AColIm,BV4) \ GEMM_FMLA2(C5Re,C5Im,PT,AColRe,AColIm,BV5) \ GEMM_FMLA2(C6Re,C6Im,PT,AColRe,AColIm,BV6) \ GEMM_FMLA2(C7Re,C7Im,PT,AColRe,AColIm,BV7) \ \ GEMM_FMLX2(C0Im,C0Re,PT,AColRe,AColIm,BV8) \ GEMM_FMLX2(C1Im,C1Re,PT,AColRe,AColIm,BV9) \ GEMM_FMLX2(C2Im,C2Re,PT,AColRe,AColIm,BV10) \ GEMM_FMLX2(C3Im,C3Re,PT,AColRe,AColIm,BV11) \ GEMM_FMLX2(C4Im,C4Re,PT,AColRe,AColIm,BV0) \ GEMM_FMLX2(C5Im,C5Re,PT,AColRe,AColIm,BV1) \ GEMM_FMLX2(C6Im,C6Re,PT,AColRe,AColIm,BV2) \ GEMM_FMLX2(C7Im,C7Re,PT,AColRe,AColIm,BV3) #define GEMM_2VX8CMPLX_MKER_LOOP_PLAIN_C_3_RESIDUAL(C0Re,C1Re,C2Re,C3Re,C4Re,C5Re,C6Re,C7Re,C0Im,C1Im,C2Im,C3Im,C4Im,C5Im,C6Im,C7Im,PT,AColRe,AColIm,BV0,BV1,BV2,BV3,BV4,BV5,BV6,BV7,BV8,BV9,BV10,BV11,BAddr,BRSBit) \ GEMM_2VX8CMPLX_MKER_LOOP_PLAIN_C_1_RESIDUAL(C0Re,C1Re,C2Re,C3Re,C4Re,C5Re,C6Re,C7Re,C0Im,C1Im,C2Im,C3Im,C4Im,C5Im,C6Im,C7Im,PT,AColRe,AColIm,BV8,BV9,BV10,BV11,BV0,BV1,BV2,BV3,BV4,BV5,BV6,BV7,BAddr,BRSBit) #define CLEAR_COL16(Z00,Z01,Z02,Z03,Z04,Z05,Z06,Z07,Z08,Z09,Z10,Z11,Z12,Z13,Z14,Z15) \ CLEAR_COL4(Z00,Z01,Z02,Z03) \ CLEAR_COL4(Z04,Z05,Z06,Z07) \ CLEAR_COL4(Z08,Z09,Z10,Z11) \ CLEAR_COL4(Z12,Z13,Z14,Z15) #define GEMM_FMULCMPLX_COL2(ZD0Re,ZD0Im,ZD1Re,ZD1Im,PT,Z0Re,Z0Im,Z1Re,Z1Im,ZFactorRe,ZFactorIm) \ FMUL_COL2(ZD0Re,ZD0Im,Z0Re,Z0Im,ZFactorRe) \ FMUL_COL2(ZD1Re,ZD1Im,Z1Re,Z1Im,ZFactorRe) \ GEMM_FMLX2(ZD0Im,ZD0Re,PT,Z0Re,Z0Im,ZFactorIm) \ GEMM_FMLX2(ZD1Im,ZD1Re,PT,Z1Re,Z1Im,ZFactorIm) #define GEMM_FMLACMPLX_COL2(ZD0Re,ZD0Im,ZD1Re,ZD1Im,PT,Z0Re,Z0Im,Z1Re,Z1Im,ZFactorRe,ZFactorIm) \ GEMM_FMLACMPLX(ZD0Re,ZD0Im,PT,Z0Re,Z0Im,ZFactorRe,ZFactorIm) \ GEMM_FMLACMPLX(ZD1Re,ZD1Im,PT,Z1Re,Z1Im,ZFactorRe,ZFactorIm) #define GEMM_CCMPLX_LOAD_COL2_C(Z0Re,Z0Im,Z1Re,Z1Im,PT,CAddr,CCS) \ GEMM_CCOLCMPLX_CONTIGUOUS_LOAD_FWD(Z0Re,Z0Im,PT,CAddr,CCS) \ GEMM_CCOLCMPLX_CONTIGUOUS_LOAD_FWD(Z1Re,Z1Im,PT,CAddr,CCS) #define GEMM_CCMPLX_STORE_COL2_C(Z0Re,Z0Im,Z1Re,Z1Im,PT,CAddr,CCS) \ GEMM_CCOLCMPLX_CONTIGUOUS_STORE_FWD(Z0Re,Z0Im,PT,CAddr,CCS) \ GEMM_CCOLCMPLX_CONTIGUOUS_STORE_FWD(Z1Re,Z1Im,PT,CAddr,CCS) #define GEMM_CCMPLX_LOAD_COL2_G(Z0Re,Z0Im,Z1Re,Z1Im,PT,ZIndex,CAddr,CCS,CTemp) \ GEMM_CCOLCMPLX_GATHER_LOAD_FWD(Z0Re,Z0Im,ZIndex,PT,PT,CAddr,CCS,CTemp) \ GEMM_CCOLCMPLX_GATHER_LOAD_FWD(Z1Re,Z1Im,ZIndex,PT,PT,CAddr,CCS,CTemp) #define GEMM_CCMPLX_STORE_COL2_G(Z0Re,Z0Im,Z1Re,Z1Im,PT,ZIndex,CAddr,CCS,CTemp) \ GEMM_CCOLCMPLX_SCATTER_STORE_FWD(Z0Re,Z0Im,ZIndex,PT,PT,CAddr,CCS,CTemp) \ GEMM_CCOLCMPLX_SCATTER_STORE_FWD(Z1Re,Z1Im,ZIndex,PT,PT,CAddr,CCS,CTemp) blis-0.9.0/kernels/armsve/3/old/armsve_asm_macros_half.h000066400000000000000000000036421422157504600232100ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2020, The University of Tokyo 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // Specify to use half precision. #define DT "h" #define LD1 "ld1h" #define ST1 "st1h" #define LD1R "ld1rh" #define PRFG "prfh" #define SZ "2" // #define OFFS UNSUPPORTED // Include macros. #include "armsve_asm_macros.h" blis-0.9.0/kernels/armsve/3/old/bli_gemm_armsve256_asm_d8x8.c000066400000000000000000001471201422157504600236100ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2020, Linaro Limited 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" /* o 8x8 Double precision micro-kernel o Runnable on ARMv8a with SVE 256 feature, compiled with aarch64 GCC. o Tested on qemu-aarch64 and armie for SVE. Preconditions: - to use this kernel, SVE with vector length of 256 bits is a must. April 2020. */ void bli_dgemm_armsve256_asm_8x8 ( dim_t k0, double* restrict alpha, double* restrict a, double* restrict b, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { void* a_next = bli_auxinfo_next_a( data ); void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; __asm__ volatile ( " \n\t" " ldr x0,%[aaddr] \n\t" // Load address of A " ldr x1,%[baddr] \n\t" // Load address of B " ldr x2,%[caddr] \n\t" // Load address of C " \n\t" " ldr x3,%[a_next] \n\t" // Move pointer " ldr x4,%[b_next] \n\t" // Move pointer " \n\t" " ldr x5,%[k_iter] \n\t" // Init guard (k_iter) " ldr x6,%[k_left] \n\t" // Init guard (k_iter) " \n\t" " ldr x7,%[alpha] \n\t" // Alpha address " ldr x8,%[beta] \n\t" // Beta address " \n\t" " ldr x9,%[cs_c] \n\t" // Load cs_c " lsl x10,x9,#3 \n\t" // cs_c * sizeof(double) " \n\t" " ldr x13,%[rs_c] \n\t" // Load rs_c. " lsl x14,x13,#3 \n\t" // rs_c * sizeof(double). " \n\t" " add x20,x2,x10 \n\t" //Load address Column 1 of C " add x21,x20,x10 \n\t" //Load address Column 2 of C " add x22,x21,x10 \n\t" //Load address Column 3 of C " add x23,x22,x10 \n\t" //Load address Column 4 of C " add x24,x23,x10 \n\t" //Load address Column 5 of C " add x25,x24,x10 \n\t" //Load address Column 6 of C " add x26,x25,x10 \n\t" //Load address Column 7 of C " \n\t" " prfm pldl1keep,[x2] \n\t" // Prefetch c. " prfm pldl1keep,[x20] \n\t" // Prefetch c. " prfm pldl1keep,[x21] \n\t" // Prefetch c. " prfm pldl1keep,[x22] \n\t" // Prefetch c. " prfm pldl1keep,[x23] \n\t" // Prefetch c. " prfm pldl1keep,[x24] \n\t" // Prefetch c. " prfm pldl1keep,[x25] \n\t" // Prefetch c. " prfm pldl1keep,[x26] \n\t" // Prefetch c. " \n\t" " ldr z0, [x0] \n\t" // Load a " ldr z1, [x0, #1, MUL VL] \n\t" " \n\t" " ptrue p0.d, all \n\t" " ld1rqd {z2.d}, p0/z, [x1] \n\t" // load b( l,0:1 ) " ld1rqd {z3.d}, p0/z, [x1, #16] \n\t" // load b( l,2:3 ) " ld1rqd {z4.d}, p0/z, [x1, #32] \n\t" // load b( l,4:5 ) " ld1rqd {z5.d}, p0/z, [x1, #48] \n\t" // load b( l,6:7 ) " \n\t" " \n\t" // PRFM, the following prefetch on [x1] and [x0] " \n\t" // is for b rows 4..7 and a columns 4..7. " \n\t" // both of them will be used in next iteration " \n\t" // of k_iter (unrolled per 4 loops) " \n\t" " dup z16.d, #0 \n\t" // Vector for accummulating column 0 " prfm PLDL1KEEP, [x1, #256] \n\t" // prefetch b row no.4 " dup z17.d, #0 \n\t" // Vector for accummulating column 0 " prfm PLDL1KEEP, [x1, #320] \n\t" // prefetch b row no.5 " dup z18.d, #0 \n\t" // Vector for accummulating column 1 " prfm PLDL1KEEP, [x1, #384] \n\t" // prefetch b row no.6 " dup z19.d, #0 \n\t" // Vector for accummulating column 1 " prfm PLDL1KEEP, [x1, #448] \n\t" // preftech b row no.7 " dup z20.d, #0 \n\t" // Vector for accummulating column 2 " dup z21.d, #0 \n\t" // Vector for accummulating column 2 " \n\t" " dup z22.d, #0 \n\t" // Vector for accummulating column 3 " prfm PLDL1KEEP, [x0, #256] \n\t" // prefetch a col. no.4 " dup z23.d, #0 \n\t" // Vector for accummulating column 3 " prfm PLDL1KEEP, [x0, #320] \n\t" // prefetch a col. no.5 " dup z24.d, #0 \n\t" // Vector for accummulating column 4 " prfm PLDL1KEEP, [x0, #384] \n\t" // prefetch a col. no.6 " dup z25.d, #0 \n\t" // Vector for accummulating column 4 " prfm PLDL1KEEP, [x0, #448] \n\t" // prefetch a col. no.7 " dup z26.d, #0 \n\t" // Vector for accummulating column 5 " dup z27.d, #0 \n\t" // Vector for accummulating column 5 " \n\t" " dup z28.d, #0 \n\t" // Vector for accummulating column 6 " dup z29.d, #0 \n\t" // Vector for accummulating column 6 " dup z30.d, #0 \n\t" // Vector for accummulating column 7 " dup z31.d, #0 \n\t" // Vector for accummulating column 7 " \n\t" " \n\t" " cmp x5,#0 \n\t" // If k_iter == 0, jump to k_left. " beq .DCONSIDERKLEFT \n\t" " \n\t" " add x0, x0, #64 \n\t" //update address of A " add x1, x1, #64 \n\t" //update address of B " \n\t" " cmp x5,1 \n\t" // If there is just one k_iter, jump to that one. " beq .DLASTITER \n\t" // (as loop is do-while-like). " \n\t" " DLOOP: \n\t" // Body " \n\t" " fmla z16.d, z0.d, z2.d[0] \n\t" // Accummulate c(0:3,0)+=a(0:3,l)*b(l,0) " prfm PLDL1KEEP, [x1, #448] \n\t" // prefetch b row no.8, 512-64=448 " fmla z17.d, z1.d, z2.d[0] \n\t" // Accummulate c(4:7,0)+=a(4:7,l)*b(l,0) " prfm PLDL1KEEP, [x1, #512] \n\t" // prefetch b row no.9 " fmla z18.d, z0.d, z2.d[1] \n\t" // Accummulate c(0:3,1)+=a(0:3,l)*b(l,1) " prfm PLDL1KEEP, [x1, #576] \n\t" // prefetch b row no.10 " \n\t" " fmla z19.d, z1.d, z2.d[1] \n\t" // Accummulate c(4:7,1)+=a(4:7,l)*b(l,1) " fmla z20.d, z0.d, z3.d[0] \n\t" // Accummulate c(0:3,2)+=a(0:3,l)*b(l,2) " ldr z6, [x0] \n\t" // Load a( 0:3,l ) " \n\t" " fmla z21.d, z1.d, z3.d[0] \n\t" // Accummulate c(4:7,2)+=a(4:7,l)*b(l,2) " fmla z22.d, z0.d, z3.d[1] \n\t" // Accummulate c(0:3,3)+=a(0:3,l)*b(l,3) " ldr z7, [x0, #1, MUL VL] \n\t" // load a( 4:7,l ) " \n\t" " fmla z23.d, z1.d, z3.d[1] \n\t" // Accummulate c(4:7,3)+=a(4:7,l)*b(l,3) " fmla z24.d, z0.d, z4.d[0] \n\t" // Accummulate c(0:3,4)+=a(0:3,l)*b(l,4) " ld1rqd {z2.d}, p0/z, [x1] \n\t" // load b( l,0:1 ) " \n\t" " fmla z25.d, z1.d, z4.d[0] \n\t" // Accummulate c(4:7,4)+=a(4:7,l)*b(l,4) " fmla z26.d, z0.d, z4.d[1] \n\t" // Accummulate c(0:3,5)+=a(0:3,l)*b(l,5) " fmla z27.d, z1.d, z4.d[1] \n\t" // Accummulate c(4:7,5)+=a(0:3,l)*b(l,5) " ld1rqd {z3.d}, p0/z, [x1, #16] \n\t" // load b( l,2:3 ) " \n\t" " fmla z28.d, z0.d, z5.d[0] \n\t" // Accummulate c(0:3,6)+=a(0:3,l)*b(l,6) " fmla z29.d, z1.d, z5.d[0] \n\t" // Accummulate c(4:7,6)+=a(0:3,l)*b(l,6) " ld1rqd {z4.d}, p0/z, [x1, #32] \n\t" // load b( l,4:5 ) " \n\t" " fmla z30.d, z0.d, z5.d[1] \n\t" // Accummulate c(0:3,7)+=a(0:3,l)*b(l,7) " fmla z31.d, z1.d, z5.d[1] \n\t" // Accummulate c(4:7,7)+=a(0:3,l)*b(l,7) " ld1rqd {z5.d}, p0/z, [x1, #48] \n\t" // load b( l,6:7 ) " \n\t" " \n\t" // End it 1 " \n\t" " fmla z16.d, z6.d, z2.d[0] \n\t" // Accummulate c(0:3,0)+=a(0:3,l)*b(l,0) " prfm PLDL1KEEP, [x1, #640] \n\t" // prefetch b row no.11 " fmla z17.d, z7.d, z2.d[0] \n\t" // Accummulate c(4:7,0)+=a(4:7,l)*b(l,0) " prfm PLDL1KEEP, [x0, #448] \n\t" // prefetch a col. no.8 " fmla z18.d, z6.d, z2.d[1] \n\t" // Accummulate c(0:3,1)+=a(0:3,l)*b(l,1) " prfm PLDL1KEEP, [x0, #512] \n\t" // prefetch a col. no.9 " \n\t" " fmla z19.d, z7.d, z2.d[1] \n\t" // Accummulate c(4:7,1)+=a(4:7,l)*b(l,1) " fmla z20.d, z6.d, z3.d[0] \n\t" // Accummulate c(0:3,2)+=a(0:3,l)*b(l,2) " ldr z0, [x0, #2, MUL VL] \n\t" // Load a( 0:3,l ) " \n\t" " fmla z21.d, z7.d, z3.d[0] \n\t" // Accummulate c(4:7,2)+=a(4:7,l)*b(l,2) " fmla z22.d, z6.d, z3.d[1] \n\t" // Accummulate c(0:3,3)+=a(0:3,l)*b(l,3) " ldr z1, [x0, #3, MUL VL] \n\t" // load a( 4:7,l ) " \n\t" " fmla z23.d, z7.d, z3.d[1] \n\t" // Accummulate c(4:7,3)+=a(4:7,l)*b(l,3) " fmla z24.d, z6.d, z4.d[0] \n\t" // Accummulate c(0:3,4)+=a(0:3,l)*b(l,4) " ld1rqd {z2.d}, p0/z, [x1, #64] \n\t" // load b( l,0:1 ) " \n\t" " fmla z25.d, z7.d, z4.d[0] \n\t" // Accummulate c(4:7,4)+=a(4:7,l)*b(l,4) " fmla z26.d, z6.d, z4.d[1] \n\t" // Accummulate c(0:3,5)+=a(0:3,l)*b(l,5) " fmla z27.d, z7.d, z4.d[1] \n\t" // Accummulate c(4:7,5)+=a(0:3,l)*b(l,5) " ld1rqd {z3.d}, p0/z, [x1, #80] \n\t" // load b( l,2:3 ) " \n\t" " fmla z28.d, z6.d, z5.d[0] \n\t" // Accummulate c(0:3,6)+=a(0:3,l)*b(l,6) " fmla z29.d, z7.d, z5.d[0] \n\t" // Accummulate c(4:7,6)+=a(0:3,l)*b(l,6) " ld1rqd {z4.d}, p0/z, [x1, #96] \n\t" // load b( l,4:5 ) " \n\t" " fmla z30.d, z6.d, z5.d[1] \n\t" // Accummulate c(0:3,7)+=a(0:3,l)*b(l,7) " fmla z31.d, z7.d, z5.d[1] \n\t" // Accummulate c(4:7,7)+=a(0:3,l)*b(l,7) " ld1rqd {z5.d}, p0/z, [x1, #112] \n\t" // load b( l,6:7 ) " \n\t" " \n\t" " \n\t" //End it 2 " \n\t" " fmla z16.d, z0.d, z2.d[0] \n\t" // Accummulate c(0:3,0)+=a(0:3,l)*b(l,0) " prfm PLDL1KEEP, [x0, #576] \n\t" // prefetch a col. no.10 " fmla z17.d, z1.d, z2.d[0] \n\t" // Accummulate c(4:7,0)+=a(4:7,l)*b(l,0) " prfm PLDL1KEEP, [x0, #640] \n\t" // prefetch a col. no.11 " \n\t" " fmla z18.d, z0.d, z2.d[1] \n\t" // Accummulate c(0:3,1)+=a(0:3,l)*b(l,1) " \n\t" " add x1, x1, #128 \n\t" // because immediate in 'ldr1rqd' must be " \n\t" // in range -128 to 112 " \n\t" " fmla z19.d, z1.d, z2.d[1] \n\t" // Accummulate c(4:7,1)+=a(4:7,l)*b(l,1) " fmla z20.d, z0.d, z3.d[0] \n\t" // Accummulate c(0:3,2)+=a(0:3,l)*b(l,2) " ldr z6, [x0, #4, MUL VL] \n\t" // Load a( 0:3,l ) " \n\t" " fmla z21.d, z1.d, z3.d[0] \n\t" // Accummulate c(4:7,2)+=a(4:7,l)*b(l,2) " fmla z22.d, z0.d, z3.d[1] \n\t" // Accummulate c(0:3,3)+=a(0:3,l)*b(l,3) " ldr z7, [x0, #5, MUL VL] \n\t" // load a( 4:7,l ) " \n\t" " fmla z23.d, z1.d, z3.d[1] \n\t" // Accummulate c(4:7,3)+=a(4:7,l)*b(l,3) " fmla z24.d, z0.d, z4.d[0] \n\t" // Accummulate c(0:3,4)+=a(0:3,l)*b(l,4) " ld1rqd {z2.d}, p0/z, [x1, #0] \n\t" // load b( l,0:1 ) " \n\t" " fmla z25.d, z1.d, z4.d[0] \n\t" // Accummulate c(4:7,4)+=a(4:7,l)*b(l,4) " fmla z26.d, z0.d, z4.d[1] \n\t" // Accummulate c(0:3,5)+=a(0:3,l)*b(l,5) " fmla z27.d, z1.d, z4.d[1] \n\t" // Accummulate c(4:7,5)+=a(0:3,l)*b(l,5) " ld1rqd {z3.d}, p0/z, [x1, #16] \n\t" // load b( l,2:3 ) " \n\t" " fmla z28.d, z0.d, z5.d[0] \n\t" // Accummulate c(0:3,6)+=a(0:3,l)*b(l,6) " fmla z29.d, z1.d, z5.d[0] \n\t" // Accummulate c(4:7,6)+=a(0:3,l)*b(l,6) " ld1rqd {z4.d}, p0/z, [x1, #32] \n\t" // load b( l,4:5 ) " \n\t" " fmla z30.d, z0.d, z5.d[1] \n\t" // Accummulate c(0:3,7)+=a(0:3,l)*b(l,7) " fmla z31.d, z1.d, z5.d[1] \n\t" // Accummulate c(4:7,7)+=a(0:3,l)*b(l,7) " ld1rqd {z5.d}, p0/z, [x1, #48] \n\t" // load b( l,6:7 ) " \n\t" " \n\t" // End it 3 " \n\t" " fmla z16.d, z6.d, z2.d[0] \n\t" // Accummulate c(0:3,0)+=a(0:3,l)*b(l,0) " fmla z17.d, z7.d, z2.d[0] \n\t" // Accummulate c(4:7,0)+=a(4:7,l)*b(l,0) " fmla z18.d, z6.d, z2.d[1] \n\t" // Accummulate c(0:3,1)+=a(0:3,l)*b(l,1) " ldr z0, [x0, #6, MUL VL] \n\t" // Load a( 0:3,l ) " \n\t" " fmla z19.d, z7.d, z2.d[1] \n\t" // Accummulate c(4:7,1)+=a(4:7,l)*b(l,1) " fmla z20.d, z6.d, z3.d[0] \n\t" // Accummulate c(0:3,2)+=a(0:3,l)*b(l,2) " fmla z21.d, z7.d, z3.d[0] \n\t" // Accummulate c(4:7,2)+=a(4:7,l)*b(l,2) " ldr z1, [x0, #7, MUL VL] \n\t" // load a( 4:7,l ) " \n\t" " fmla z22.d, z6.d, z3.d[1] \n\t" // Accummulate c(0:3,3)+=a(0:3,l)*b(l,3) " fmla z23.d, z7.d, z3.d[1] \n\t" // Accummulate c(4:7,3)+=a(4:7,l)*b(l,3) " fmla z24.d, z6.d, z4.d[0] \n\t" // Accummulate c(0:3,4)+=a(0:3,l)*b(l,4) " ld1rqd {z2.d}, p0/z, [x1, #64] \n\t" // load b( l,0:1 ) " \n\t" " fmla z25.d, z7.d, z4.d[0] \n\t" // Accummulate c(4:7,4)+=a(4:7,l)*b(l,4) " fmla z26.d, z6.d, z4.d[1] \n\t" // Accummulate c(0:3,5)+=a(0:3,l)*b(l,5) " fmla z27.d, z7.d, z4.d[1] \n\t" // Accummulate c(4:7,5)+=a(0:3,l)*b(l,5) " ld1rqd {z3.d}, p0/z, [x1, #80] \n\t" // load b( l,2:3 ) " \n\t" " fmla z28.d, z6.d, z5.d[0] \n\t" // Accummulate c(0:3,6)+=a(0:3,l)*b(l,6) " fmla z29.d, z7.d, z5.d[0] \n\t" // Accummulate c(4:7,6)+=a(0:3,l)*b(l,6) " ld1rqd {z4.d}, p0/z, [x1, #96] \n\t" // load b( l,4:5 ) " \n\t" " fmla z30.d, z6.d, z5.d[1] \n\t" // Accummulate c(0:3,7)+=a(0:3,l)*b(l,7) " fmla z31.d, z7.d, z5.d[1] \n\t" // Accummulate c(4:7,7)+=a(0:3,l)*b(l,7) " ld1rqd {z5.d}, p0/z, [x1, #112] \n\t" // load b( l,6:7 ) " \n\t" " \n\t" //End it 4 " add x0, x0, #256 \n\t" " add x1, x1, #128 \n\t" " \n\t" " sub x5,x5,1 \n\t" // i-=1 " cmp x5,1 \n\t" // Iterate again if we are not in k_iter == 1. " bne DLOOP \n\t" " \n\t" ".DLASTITER: \n\t" " \n\t" " fmla z16.d, z0.d, z2.d[0] \n\t" // Accummulate c(0:3,0)+=a(0:3,l)*b(l,0) " fmla z17.d, z1.d, z2.d[0] \n\t" // Accummulate c(4:7,0)+=a(4:7,l)*b(l,0) " fmla z18.d, z0.d, z2.d[1] \n\t" // Accummulate c(0:3,1)+=a(0:3,l)*b(l,1) " ldr z6, [x0] \n\t" // Load a( 0:3,l ) " \n\t" " fmla z19.d, z1.d, z2.d[1] \n\t" // Accummulate c(4:7,1)+=a(4:7,l)*b(l,1) " fmla z20.d, z0.d, z3.d[0] \n\t" // Accummulate c(0:3,2)+=a(0:3,l)*b(l,2) " fmla z21.d, z1.d, z3.d[0] \n\t" // Accummulate c(4:7,2)+=a(4:7,l)*b(l,2) " ldr z7, [x0, #1, MUL VL] \n\t" // load a( 4:7,l ) " \n\t" " fmla z22.d, z0.d, z3.d[1] \n\t" // Accummulate c(0:3,3)+=a(0:3,l)*b(l,3) " fmla z23.d, z1.d, z3.d[1] \n\t" // Accummulate c(4:7,3)+=a(4:7,l)*b(l,3) " fmla z24.d, z0.d, z4.d[0] \n\t" // Accummulate c(0:3,4)+=a(0:3,l)*b(l,4) " ld1rqd {z2.d}, p0/z, [x1] \n\t" // load b( l,0:1 ) " \n\t" " fmla z25.d, z1.d, z4.d[0] \n\t" // Accummulate c(4:7,4)+=a(4:7,l)*b(l,4) " fmla z26.d, z0.d, z4.d[1] \n\t" // Accummulate c(0:3,5)+=a(0:3,l)*b(l,5) " fmla z27.d, z1.d, z4.d[1] \n\t" // Accummulate c(4:7,5)+=a(0:3,l)*b(l,5) " ld1rqd {z3.d}, p0/z, [x1, #16] \n\t" // load b( l,2:3 ) " \n\t" " fmla z28.d, z0.d, z5.d[0] \n\t" // Accummulate c(0:3,6)+=a(0:3,l)*b(l,6) " fmla z29.d, z1.d, z5.d[0] \n\t" // Accummulate c(4:7,6)+=a(0:3,l)*b(l,6) " ld1rqd {z4.d}, p0/z, [x1, #32] \n\t" // load b( l,4:5 ) " \n\t" " fmla z30.d, z0.d, z5.d[1] \n\t" // Accummulate c(0:3,7)+=a(0:3,l)*b(l,7) " fmla z31.d, z1.d, z5.d[1] \n\t" // Accummulate c(4:7,7)+=a(0:3,l)*b(l,7) " ld1rqd {z5.d}, p0/z, [x1, #48] \n\t" // load b( l,6:7 ) " \n\t" " \n\t" // End it 1 " \n\t" " fmla z16.d, z6.d, z2.d[0] \n\t" // Accummulate c(0:3,0)+=a(0:3,l)*b(l,0) " fmla z17.d, z7.d, z2.d[0] \n\t" // Accummulate c(4:7,0)+=a(4:7,l)*b(l,0) " fmla z18.d, z6.d, z2.d[1] \n\t" // Accummulate c(0:3,1)+=a(0:3,l)*b(l,1) " ldr z0, [x0, #2, MUL VL] \n\t" // Load a( 0:3,l ) " \n\t" " fmla z19.d, z7.d, z2.d[1] \n\t" // Accummulate c(4:7,1)+=a(4:7,l)*b(l,1) " fmla z20.d, z6.d, z3.d[0] \n\t" // Accummulate c(0:3,2)+=a(0:3,l)*b(l,2) " fmla z21.d, z7.d, z3.d[0] \n\t" // Accummulate c(4:7,2)+=a(4:7,l)*b(l,2) " ldr z1, [x0, #3, MUL VL] \n\t" // load a( 4:7,l ) " \n\t" " fmla z22.d, z6.d, z3.d[1] \n\t" // Accummulate c(0:3,3)+=a(0:3,l)*b(l,3) " fmla z23.d, z7.d, z3.d[1] \n\t" // Accummulate c(4:7,3)+=a(4:7,l)*b(l,3) " fmla z24.d, z6.d, z4.d[0] \n\t" // Accummulate c(0:3,4)+=a(0:3,l)*b(l,4) " ld1rqd {z2.d}, p0/z, [x1, #64] \n\t" // load b( l,0:1 ) " \n\t" " fmla z25.d, z7.d, z4.d[0] \n\t" // Accummulate c(4:7,4)+=a(4:7,l)*b(l,4) " fmla z26.d, z6.d, z4.d[1] \n\t" // Accummulate c(0:3,5)+=a(0:3,l)*b(l,5) " fmla z27.d, z7.d, z4.d[1] \n\t" // Accummulate c(4:7,5)+=a(0:3,l)*b(l,5) " ld1rqd {z3.d}, p0/z, [x1, #80] \n\t" // load b( l,2:3 ) " \n\t" " fmla z28.d, z6.d, z5.d[0] \n\t" // Accummulate c(0:3,6)+=a(0:3,l)*b(l,6) " fmla z29.d, z7.d, z5.d[0] \n\t" // Accummulate c(4:7,6)+=a(0:3,l)*b(l,6) " ld1rqd {z4.d}, p0/z, [x1, #96] \n\t" // load b( l,4:5 ) " \n\t" " fmla z30.d, z6.d, z5.d[1] \n\t" // Accummulate c(0:3,7)+=a(0:3,l)*b(l,7) " fmla z31.d, z7.d, z5.d[1] \n\t" // Accummulate c(4:7,7)+=a(0:3,l)*b(l,7) " ld1rqd {z5.d}, p0/z, [x1, #112] \n\t" // load b( l,6:7 ) " \n\t" " \n\t" " \n\t" //End it 2 " \n\t" " fmla z16.d, z0.d, z2.d[0] \n\t" // Accummulate c(0:3,0)+=a(0:3,l)*b(l,0) " fmla z17.d, z1.d, z2.d[0] \n\t" // Accummulate c(4:7,0)+=a(4:7,l)*b(l,0) " fmla z18.d, z0.d, z2.d[1] \n\t" // Accummulate c(0:3,1)+=a(0:3,l)*b(l,1) " ldr z6, [x0, #4, MUL VL] \n\t" // Load a( 0:3,l ) " \n\t" " fmla z19.d, z1.d, z2.d[1] \n\t" // Accummulate c(4:7,1)+=a(4:7,l)*b(l,1) " fmla z20.d, z0.d, z3.d[0] \n\t" // Accummulate c(0:3,2)+=a(0:3,l)*b(l,2) " fmla z21.d, z1.d, z3.d[0] \n\t" // Accummulate c(4:7,2)+=a(4:7,l)*b(l,2) " ldr z7, [x0, #5, MUL VL] \n\t" // load a( 4:7,l ) " \n\t" " fmla z22.d, z0.d, z3.d[1] \n\t" // Accummulate c(0:3,3)+=a(0:3,l)*b(l,3) " add x1, x1, #128 \n\t" // because immediate in 'ldr1rqd' must be " \n\t" // in range -128 to 112 " fmla z23.d, z1.d, z3.d[1] \n\t" // Accummulate c(4:7,3)+=a(4:7,l)*b(l,3) " fmla z24.d, z0.d, z4.d[0] \n\t" // Accummulate c(0:3,4)+=a(0:3,l)*b(l,4) " ld1rqd {z2.d}, p0/z, [x1, #0] \n\t" // load b( l,0:1 ) " \n\t" " fmla z25.d, z1.d, z4.d[0] \n\t" // Accummulate c(4:7,4)+=a(4:7,l)*b(l,4) " fmla z26.d, z0.d, z4.d[1] \n\t" // Accummulate c(0:3,5)+=a(0:3,l)*b(l,5) " fmla z27.d, z1.d, z4.d[1] \n\t" // Accummulate c(4:7,5)+=a(0:3,l)*b(l,5) " ld1rqd {z3.d}, p0/z, [x1, #16] \n\t" // load b( l,2:3 ) " \n\t" " fmla z28.d, z0.d, z5.d[0] \n\t" // Accummulate c(0:3,6)+=a(0:3,l)*b(l,6) " fmla z29.d, z1.d, z5.d[0] \n\t" // Accummulate c(4:7,6)+=a(0:3,l)*b(l,6) " ld1rqd {z4.d}, p0/z, [x1, #32] \n\t" // load b( l,4:5 ) " \n\t" " fmla z30.d, z0.d, z5.d[1] \n\t" // Accummulate c(0:3,7)+=a(0:3,l)*b(l,7) " fmla z31.d, z1.d, z5.d[1] \n\t" // Accummulate c(4:7,7)+=a(0:3,l)*b(l,7) " ld1rqd {z5.d}, p0/z, [x1, #48] \n\t" // load b( l,6:7 ) " \n\t" " \n\t" // End it 3 " \n\t" " fmla z16.d, z6.d, z2.d[0] \n\t" // Accummulate c(0:3,0)+=a(0:3,l)*b(l,0) " fmla z17.d, z7.d, z2.d[0] \n\t" // Accummulate c(4:7,0)+=a(4:7,l)*b(l,0) " \n\t" " fmla z18.d, z6.d, z2.d[1] \n\t" // Accummulate c(0:3,1)+=a(0:3,l)*b(l,1) " fmla z19.d, z7.d, z2.d[1] \n\t" // Accummulate c(4:7,1)+=a(4:7,l)*b(l,1) " \n\t" " fmla z20.d, z6.d, z3.d[0] \n\t" // Accummulate c(0:3,2)+=a(0:3,l)*b(l,2) " fmla z21.d, z7.d, z3.d[0] \n\t" // Accummulate c(4:7,2)+=a(4:7,l)*b(l,2) " \n\t" " fmla z22.d, z6.d, z3.d[1] \n\t" // Accummulate c(0:3,3)+=a(0:3,l)*b(l,3) " fmla z23.d, z7.d, z3.d[1] \n\t" // Accummulate c(4:7,3)+=a(4:7,l)*b(l,3) " \n\t" " fmla z24.d, z6.d, z4.d[0] \n\t" // Accummulate c(0:3,4)+=a(0:3,l)*b(l,4) " fmla z25.d, z7.d, z4.d[0] \n\t" // Accummulate c(4:7,4)+=a(4:7,l)*b(l,4) " \n\t" " fmla z26.d, z6.d, z4.d[1] \n\t" // Accummulate c(0:3,5)+=a(0:3,l)*b(l,5) " fmla z27.d, z7.d, z4.d[1] \n\t" // Accummulate c(4:7,5)+=a(0:3,l)*b(l,5) " add x1, x1, #64 \n\t" " \n\t" " fmla z28.d, z6.d, z5.d[0] \n\t" // Accummulate c(0:3,6)+=a(0:3,l)*b(l,6) " fmla z29.d, z7.d, z5.d[0] \n\t" // Accummulate c(4:7,6)+=a(0:3,l)*b(l,6) " \n\t" " fmla z30.d, z6.d, z5.d[1] \n\t" // Accummulate c(0:3,7)+=a(0:3,l)*b(l,7) " fmla z31.d, z7.d, z5.d[1] \n\t" // Accummulate c(4:7,7)+=a(0:3,l)*b(l,7) " \n\t" " \n\t" //End it 4 " add x0, x0, #192 \n\t" " \n\t" " .DCONSIDERKLEFT: \n\t" " cmp x6,0 \n\t" // If k_left == 0, we are done. " beq .DPOSTACCUM \n\t" // else, we enter the k_left loop. " \n\t" ".DLOOPKLEFT: \n\t" " \n\t" " ldr z0, [x0] \n\t" // Load a " ldr z1, [x0, #1, MUL VL] \n\t" " add x0, x0, #64 \n\t" " \n\t" " ld1rqd {z2.d}, p0/z, [x1] \n\t" // load b( l,0:1 ) " ld1rqd {z3.d}, p0/z, [x1, #16] \n\t" // load b( l,2:3 ) " ld1rqd {z4.d}, p0/z, [x1, #32] \n\t" // load b( l,4:5 ) " ld1rqd {z5.d}, p0/z, [x1, #48] \n\t" // load b( l,6:7 ) " add x1, x1, #64 \n\t" " \n\t" " sub x6,x6,1 \n\t" " \n\t" " fmla z16.d, z0.d, z2.d[0] \n\t" // Accummulate c(0:3,0)+=a(0:3,l)*b(l,0) " fmla z17.d, z1.d, z2.d[0] \n\t" // Accummulate c(4:7,0)+=a(4:7,l)*b(l,0) " \n\t" " fmla z18.d, z0.d, z2.d[1] \n\t" // Accummulate c(0:3,1)+=a(0:3,l)*b(l,1) " fmla z19.d, z1.d, z2.d[1] \n\t" // Accummulate c(4:7,1)+=a(4:7,l)*b(l,1) " \n\t" " fmla z20.d, z0.d, z3.d[0] \n\t" // Accummulate c(0:3,2)+=a(0:3,l)*b(l,2) " fmla z21.d, z1.d, z3.d[0] \n\t" // Accummulate c(4:7,2)+=a(4:7,l)*b(l,2) " \n\t" " fmla z22.d, z0.d, z3.d[1] \n\t" // Accummulate c(0:3,3)+=a(0:3,l)*b(l,3) " fmla z23.d, z1.d, z3.d[1] \n\t" // Accummulate c(4:7,3)+=a(4:7,l)*b(l,3) " \n\t" " fmla z24.d, z0.d, z4.d[0] \n\t" // Accummulate c(0:3,4)+=a(0:3,l)*b(l,4) " fmla z25.d, z1.d, z4.d[0] \n\t" // Accummulate c(4:7,4)+=a(4:7,l)*b(l,4) " \n\t" " fmla z26.d, z0.d, z4.d[1] \n\t" // Accummulate c(0:3,5)+=a(0:3,l)*b(l,5) " fmla z27.d, z1.d, z4.d[1] \n\t" // Accummulate c(4:7,5)+=a(0:3,l)*b(l,5) " \n\t" " fmla z28.d, z0.d, z5.d[0] \n\t" // Accummulate c(0:3,6)+=a(0:3,l)*b(l,6) " fmla z29.d, z1.d, z5.d[0] \n\t" // Accummulate c(4:7,6)+=a(0:3,l)*b(l,6) " \n\t" " fmla z30.d, z0.d, z5.d[1] \n\t" // Accummulate c(0:3,7)+=a(0:3,l)*b(l,7) " fmla z31.d, z1.d, z5.d[1] \n\t" // Accummulate c(4:7,7)+=a(0:3,l)*b(l,7) " \n\t" " cmp x6,0 \n\t" // Iterate again. " bne .DLOOPKLEFT \n\t" // if i!=0. " \n\t" " .DPOSTACCUM: \n\t" " \n\t" " ld1rd {z6.d}, p0/z, [x7] \n\t" // Load alpha. " ld1rd {z7.d}, p0/z, [x8] \n\t" // Load beta " \n\t" " cmp x13,#1 \n\t" // If rs_c != 1 (column-major) " bne .DGENSTORED \n\t" " \n\t" " .DCOLSTORED: \n\t" // C is column-major. " \n\t" " dup z0.d, #0 \n\t" " dup z1.d, #0 \n\t" " dup z2.d, #0 \n\t" " dup z3.d, #0 \n\t" " \n\t" " fcmp d7,#0.0 \n\t" " beq .DBETAZEROCOLSTOREDS1 \n\t" // Taking care of the beta==0 case. " \n\t" " ldr z0, [x2] \n\t" //Load column 0 of C " ldr z1, [x2, #1, MUL VL] \n\t" " \n\t" " ldr z2, [x20] \n\t" //Load column 1 of C " ldr z3, [x20, #1, MUL VL] \n\t" " \n\t" " fmul z0.d, z0.d, z7.d \n\t" // Scale by beta " fmul z1.d, z1.d, z7.d \n\t" // Scale by beta " fmul z2.d, z2.d, z7.d \n\t" // Scale by beta " fmul z3.d, z3.d, z7.d \n\t" // Scale by beta " \n\t" " .DBETAZEROCOLSTOREDS1: \n\t" " \n\t" " fmla z0.d, z16.d, z6.d[0] \n\t" // Scale by alpha " fmla z1.d, z17.d, z6.d[0] \n\t" // Scale by alpha " fmla z2.d, z18.d, z6.d[0] \n\t" // Scale by alpha " fmla z3.d, z19.d, z6.d[0] \n\t" // Scale by alpha " \n\t" " str z0, [x2] \n\t" //Store column 0 of C " str z1, [x2, #1, MUL VL] \n\t" " \n\t" " str z2, [x20] \n\t" //Store column 1 of C " str z3, [x20, #1, MUL VL] \n\t" " \n\t" " dup z8.d, #0 \n\t" " dup z9.d, #0 \n\t" " dup z10.d, #0 \n\t" " dup z11.d, #0 \n\t" " \n\t" " fcmp d7,#0.0 \n\t" " beq .DBETAZEROCOLSTOREDS2 \n\t" // Taking care of the beta==0 case. " \n\t" " ldr z8, [x21] \n\t" //Load column 2 of C " ldr z9, [x21, #1, MUL VL] \n\t" " \n\t" " ldr z10, [x22] \n\t" //Load column 3 of C " ldr z11, [x22, #1, MUL VL] \n\t" " \n\t" " fmul z8.d, z8.d, z7.d \n\t" // Scale by beta " fmul z9.d, z9.d, z7.d \n\t" // Scale by beta " fmul z10.d, z10.d, z7.d \n\t" // Scale by beta " fmul z11.d, z11.d, z7.d \n\t" // Scale by beta " \n\t" " .DBETAZEROCOLSTOREDS2: \n\t" " \n\t" " fmla z8.d, z20.d, z6.d[0] \n\t" // Scale by alpha " fmla z9.d, z21.d, z6.d[0] \n\t" // Scale by alpha " fmla z10.d, z22.d, z6.d[0] \n\t" // Scale by alpha " fmla z11.d, z23.d, z6.d[0] \n\t" // Scale by alpha " \n\t" " str z8, [x21] \n\t" //Store column 2 of C " str z9, [x21, #1, MUL VL] \n\t" " \n\t" " str z10, [x22] \n\t" //Store column 3 of C " str z11, [x22, #1, MUL VL] \n\t" " \n\t" " dup z0.d, #0 \n\t" " dup z1.d, #0 \n\t" " dup z2.d, #0 \n\t" " dup z3.d, #0 \n\t" " \n\t" " fcmp d7,#0.0 \n\t" " beq .DBETAZEROCOLSTOREDS3 \n\t" // Taking care of the beta==0 case. " \n\t" " ldr z0, [x23] \n\t" //Load column 4 of C " ldr z1, [x23, #1, MUL VL] \n\t" " \n\t" " ldr z2, [x24] \n\t" //Load column 5 of C " ldr z3, [x24, #1, MUL VL] \n\t" " \n\t" " fmul z0.d, z0.d, z7.d \n\t" // Scale by beta " fmul z1.d, z1.d, z7.d \n\t" // Scale by beta " fmul z2.d, z2.d, z7.d \n\t" // Scale by beta " fmul z3.d, z3.d, z7.d \n\t" // Scale by beta " \n\t" " .DBETAZEROCOLSTOREDS3: \n\t" " \n\t" " fmla z0.d, z24.d, z6.d[0] \n\t" // Scale by alpha " fmla z1.d, z25.d, z6.d[0] \n\t" // Scale by alpha " fmla z2.d, z26.d, z6.d[0] \n\t" // Scale by alpha " fmla z3.d, z27.d, z6.d[0] \n\t" // Scale by alpha " \n\t" " str z0, [x23] \n\t" //Store column 4 of C " str z1, [x23, #1, MUL VL] \n\t" " \n\t" " str z2, [x24] \n\t" //Store column 5 of C " str z3, [x24, #1, MUL VL] \n\t" " \n\t" " dup z8.d, #0 \n\t" " dup z9.d, #0 \n\t" " dup z10.d, #0 \n\t" " dup z11.d, #0 \n\t" " \n\t" " fcmp d7,#0.0 \n\t" " beq .DBETAZEROCOLSTOREDS4 \n\t" // Taking care of the beta==0 case. " \n\t" " ldr z8, [x25] \n\t" //Load column 6 of C " ldr z9, [x25, #1, MUL VL] \n\t" " \n\t" " ldr z10, [x26] \n\t" //Load column 7 of C " ldr z11, [x26, #1, MUL VL] \n\t" " \n\t" " fmul z8.d, z8.d, z7.d \n\t" // Scale by beta " fmul z9.d, z9.d, z7.d \n\t" // Scale by beta " fmul z10.d, z10.d, z7.d \n\t" // Scale by beta " fmul z11.d, z11.d, z7.d \n\t" // Scale by beta " \n\t" " .DBETAZEROCOLSTOREDS4: \n\t" " \n\t" " prfm pldl2keep,[x3] \n\t" " prfm pldl2keep,[x4] \n\t" " \n\t" " fmla z8.d, z28.d, z6.d[0] \n\t" // Scale by alpha " fmla z9.d, z29.d, z6.d[0] \n\t" // Scale by alpha " fmla z10.d, z30.d, z6.d[0] \n\t" // Scale by alpha " fmla z11.d, z31.d, z6.d[0] \n\t" // Scale by alpha " \n\t" " str z8, [x25] \n\t" //Store column 6 of C " str z9, [x25, #1, MUL VL] \n\t" " \n\t" " str z10, [x26] \n\t" //Store column 7 of C " str z11, [x26, #1, MUL VL] \n\t" " \n\t" " b .DEND \n\t" " \n\t" " .DGENSTORED: \n\t" // C is general-stride stored. " \n\t" " \n\t" // x14 is row-stride in number of bytes. " lsl x15,x14,#2 \n\t" // x15 is 4-row-stride, which is the address offset " \n\t" // btw c(4,*) and c(0,*) " index z4.d, xzr, x14 \n\t" // z4 is address offsets of four contiguous elements " \n\t" // in a column. such as c( 0:3,* ). " \n\t" // z4 is used as vector index for gather/scatter " \n\t" // loading/storing from column of *c " \n\t" " \n\t" // C's each column's address: " \n\t" // x2, x20, x21, x22, x23, x24, x25, x26: are addresses of c(0,0:7) " \n\t" // x5, x6, x7, x8, x16, x17, x18, x19: are addresses of c(4,0:7) " add x5, x15, x2 \n\t" // x5 is address of c(4,0) " add x6, x15, x20 \n\t" // x6 is address of c(4,1) " add x7, x15, x21 \n\t" // x7 is address of c(4,2) " add x8, x15, x22 \n\t" // x8 is address of c(4,3) " add x16, x15, x23 \n\t" // x16 is address of c(4,4) " add x17, x15, x24 \n\t" // x17 is address of c(4,5) " add x18, x15, x25 \n\t" // x18 is address of c(4,6) " add x19, x15, x26 \n\t" // x19 is address of c(4,7) " \n\t" " dup z0.d, #0 \n\t" // C column 0, 1 " dup z1.d, #0 \n\t" " dup z2.d, #0 \n\t" " dup z3.d, #0 \n\t" " \n\t" " fcmp d7,#0.0 \n\t" " beq .DBETAZEROGENSTOREDS1 \n\t" // Taking care of the beta==0 case. " \n\t" " \n\t" // x2 is address of c(0,0) " \n\t" // x5 is address of c(4,0) " \n\t" // x20 is address of c(0,1) " \n\t" // x6 is address of c(4,1) " ld1d {z0.d}, p0/z, [x2, z4.d] \n\t" // Load c( 0:3,0 ) into z0 " ld1d {z1.d}, p0/z, [x5, z4.d] \n\t" // Load c( 4:7,0 ) into z1 " ld1d {z2.d}, p0/z, [x20, z4.d] \n\t" // Load c( 0:3,1 ) into z2 " ld1d {z3.d}, p0/z, [x6 , z4.d] \n\t" // Load c( 4:7,1 ) into z3 " \n\t" " fmul z0.d, z0.d, z7.d \n\t" // Scale by beta " fmul z1.d, z1.d, z7.d \n\t" // Scale by beta " fmul z2.d, z2.d, z7.d \n\t" // Scale by beta " fmul z3.d, z3.d, z7.d \n\t" // Scale by beta " \n\t" " .DBETAZEROGENSTOREDS1: \n\t" " \n\t" " fmla z0.d, z16.d, z6.d[0] \n\t" // Scale by alpha " fmla z1.d, z17.d, z6.d[0] \n\t" // Scale by alpha " fmla z2.d, z18.d, z6.d[0] \n\t" // Scale by alpha " fmla z3.d, z19.d, z6.d[0] \n\t" // Scale by alpha " \n\t" " st1d {z0.d}, p0, [x2 , z4.d] \n\t" // Store c( 0:3,0 ) <- z0 " st1d {z1.d}, p0, [x5 , z4.d] \n\t" // Store c( 4:7,0 ) <- z1 " st1d {z2.d}, p0, [x20, z4.d] \n\t" // Store c( 0:3,1 ) <- z2 " st1d {z3.d}, p0, [x6 , z4.d] \n\t" // Store c( 4:7,1 ) <- z3 " \n\t" " \n\t" " \n\t" " dup z8.d, #0 \n\t" // C column 2, 3 " dup z9.d, #0 \n\t" " dup z10.d, #0 \n\t" " dup z11.d, #0 \n\t" " \n\t" " fcmp d7,#0.0 \n\t" " beq .DBETAZEROGENSTOREDS2 \n\t" // Taking care of the beta==0 case. " \n\t" " \n\t" // x21 is address of c(0,2) " \n\t" // x7 is address of c(4,2) " \n\t" // x22 is address of c(0,3) " \n\t" // x8 is address of c(4,3) " ld1d {z8.d}, p0/z, [x21, z4.d] \n\t" // Load c( 0:3,2 ) into z8 " ld1d {z9.d}, p0/z, [x7 , z4.d] \n\t" // Load c( 4:7,2 ) into z9 " ld1d {z10.d}, p0/z, [x22, z4.d] \n\t" // Load c( 0:3,3 ) into z10 " ld1d {z11.d}, p0/z, [x8 , z4.d] \n\t" // Load c( 4:7,3 ) into z11 " \n\t" " fmul z8.d, z8.d, z7.d \n\t" // Scale by beta " fmul z9.d, z9.d, z7.d \n\t" // Scale by beta " fmul z10.d, z10.d, z7.d \n\t" // Scale by beta " fmul z11.d, z11.d, z7.d \n\t" // Scale by beta " \n\t" " .DBETAZEROGENSTOREDS2: \n\t" " \n\t" " fmla z8.d, z20.d, z6.d[0] \n\t" // Scale by alpha " fmla z9.d, z21.d, z6.d[0] \n\t" // Scale by alpha " fmla z10.d, z22.d, z6.d[0] \n\t" // Scale by alpha " fmla z11.d, z23.d, z6.d[0] \n\t" // Scale by alpha " \n\t" " st1d {z8.d}, p0, [x21, z4.d] \n\t" // Store c( 0:3,2 ) <- z8 " st1d {z9.d}, p0, [x7 , z4.d] \n\t" // Store c( 4:7,2 ) <- z9 " st1d {z10.d}, p0, [x22, z4.d] \n\t" // Store c( 0:3,3 ) <- z10 " st1d {z11.d}, p0, [x8 , z4.d] \n\t" // Store c( 4:7,3 ) <- z11 " \n\t" " dup z0.d, #0 \n\t" // C column 4, 5 " dup z1.d, #0 \n\t" " dup z2.d, #0 \n\t" " dup z3.d, #0 \n\t" " \n\t" " fcmp d7,#0.0 \n\t" " beq .DBETAZEROGENSTOREDS3 \n\t" // Taking care of the beta==0 case. " \n\t" " \n\t" // x23 is address of c(0,4) " \n\t" // x16 is address of c(4,4) " \n\t" // x24 is address of c(0,5) " \n\t" // x17 is address of c(4,5) " ld1d {z0.d}, p0/z, [x23, z4.d] \n\t" // Load c( 0:3,4 ) into z0 " ld1d {z1.d}, p0/z, [x16, z4.d] \n\t" // Load c( 4:7,4 ) into z1 " ld1d {z2.d}, p0/z, [x24, z4.d] \n\t" // Load c( 0:3,5 ) into z2 " ld1d {z3.d}, p0/z, [x17, z4.d] \n\t" // Load c( 4:7,5 ) into z3 " \n\t" " fmul z0.d, z0.d, z7.d \n\t" // Scale by beta " fmul z1.d, z1.d, z7.d \n\t" // Scale by beta " fmul z2.d, z2.d, z7.d \n\t" // Scale by beta " fmul z3.d, z3.d, z7.d \n\t" // Scale by beta " \n\t" " .DBETAZEROGENSTOREDS3: \n\t" " \n\t" " fmla z0.d, z24.d, z6.d[0] \n\t" // Scale by alpha " fmla z1.d, z25.d, z6.d[0] \n\t" // Scale by alpha " fmla z2.d, z26.d, z6.d[0] \n\t" // Scale by alpha " fmla z3.d, z27.d, z6.d[0] \n\t" // Scale by alpha " \n\t" " st1d {z0.d}, p0, [x23, z4.d] \n\t" // Store c( 0:3,4 ) <- z0 " st1d {z1.d}, p0, [x16, z4.d] \n\t" // Store c( 4:7,4 ) <- z1 " st1d {z2.d}, p0, [x24, z4.d] \n\t" // Store c( 0:3,5 ) <- z2 " st1d {z3.d}, p0, [x17, z4.d] \n\t" // Store c( 4:7,5 ) <- z3 " \n\t" " dup z8.d, #0 \n\t" // C column 6, 7 " dup z9.d, #0 \n\t" " dup z10.d, #0 \n\t" " dup z11.d, #0 \n\t" " \n\t" " fcmp d7,#0.0 \n\t" " beq .DBETAZEROGENSTOREDS4 \n\t" // Taking care of the beta==0 case. " \n\t" " \n\t" // x25 is address of c(0,6) " \n\t" // x18 is address of c(4,6) " \n\t" // x26 is address of c(0,7) " \n\t" // x19 is address of c(4,7) " ld1d {z8.d}, p0/z, [x25, z4.d] \n\t" // Load c( 0:3,6 ) into z8 " ld1d {z9.d}, p0/z, [x18, z4.d] \n\t" // Load c( 4:7,6 ) into z9 " ld1d {z10.d}, p0/z, [x26, z4.d] \n\t" // Load c( 0:3,7 ) into z10 " ld1d {z11.d}, p0/z, [x19, z4.d] \n\t" // Load c( 4:7,7 ) into z11 " \n\t" " fmul z8.d, z8.d, z7.d \n\t" // Scale by beta " fmul z9.d, z9.d, z7.d \n\t" // Scale by beta " fmul z10.d, z10.d, z7.d \n\t" // Scale by beta " fmul z11.d, z11.d, z7.d \n\t" // Scale by beta " \n\t" " .DBETAZEROGENSTOREDS4: \n\t" " \n\t" " fmla z8.d, z28.d, z6.d[0] \n\t" // Scale by alpha " fmla z9.d, z29.d, z6.d[0] \n\t" // Scale by alpha " fmla z10.d, z30.d, z6.d[0] \n\t" // Scale by alpha " fmla z11.d, z31.d, z6.d[0] \n\t" // Scale by alpha " \n\t" " st1d {z8.d}, p0, [x25, z4.d] \n\t" // Store c( 0:3,6 ) <- z8 " st1d {z9.d}, p0, [x18, z4.d] \n\t" // Store c( 4:7,6 ) <- z9 " st1d {z10.d}, p0, [x26, z4.d] \n\t" // Store c( 0:3,7 ) <- z10 " st1d {z11.d}, p0, [x19, z4.d] \n\t" // Store c( 4:7,7 ) <- z11 " \n\t" " .DEND: \n\t" // Done! " \n\t" :// output operands (none) :// input operands [aaddr] "m" (a), // 0 [baddr] "m" (b), // 1 [caddr] "m" (c), // 2 [k_iter] "m" (k_iter), // 3 [k_left] "m" (k_left), // 4 [alpha] "m" (alpha), // 5 [beta] "m" (beta), // 6 [rs_c] "m" (rs_c), // 6 [cs_c] "m" (cs_c), // 7 [a_next] "m" (a_next), // 8 [b_next] "m" (b_next) // 9 :// Register clobber list "x0","x1","x2","x3", "x4","x5","x6", "x7","x8","x9", "x10","x11","x12","x13","x14","x15","x16","x17","x18","x19", "x20","x21","x22","x23","x24","x25","x26", "x27", "v0","v1","v2", "v3","v4","v5", "v6","v7","v8", "v9","v10","v11", "v12","v13","v14", "v15","v16","v17","v18","v19", "v20","v21","v22","v23", "v24","v25","v26","v27", "v28","v29","v30","v31" ); } blis-0.9.0/kernels/armsve/3/old/bli_gemm_armsve_asm_sh2vx10_unindexed.c000066400000000000000000000445441422157504600260440ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2020, The University of Tokyo Copyright (C) 2019, Forschunszentrum Juelich 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // Half-precision composite instructions. #include "armsve_asm_macros_half.h" // 2vx10 microkernels. #include "armsve_asm_2vx10.h" // Gather-load / scatter-store instruction for half-precision // needs being defined separately. #undef GEMM_CCOL_GATHER_LOAD_FWD #undef GEMM_CCOL_SCATTER_STORE_FWD #define GEMM_CCOL_GATHER_LOAD_FWD(ZFH,ZLH,ZIDX2,PT,CRS2,CADDR,CCS,CVSKIP,CTEMP) \ " add x28, "#CADDR", "#CRS2" \n\t" \ " ld1h z31.s, "#PT"/z, ["#CADDR", "#ZIDX2".s, uxtw #1] \n\t" \ " ld1h "#ZFH".s, "#PT"/z, [x28, "#ZIDX2".s, uxtw #1] \n\t" \ " revh "#ZFH".s, "#PT"/m, "#ZFH".s \n\t" \ " fadd "#ZFH".h, "#ZFH".h, z31.h \n\t" \ " add "#CTEMP", "#CADDR", "#CVSKIP" \n\t" \ " add x28, "#CTEMP", "#CRS2" \n\t" \ " ld1h z31.s, "#PT"/z, ["#CTEMP", "#ZIDX2".s, uxtw #1] \n\t" \ " ld1h "#ZLH".s, "#PT"/z, [x28, "#ZIDX2".s, uxtw #1] \n\t" \ " revh "#ZLH".s, "#PT"/m, "#ZLH".s \n\t" \ " fadd "#ZLH".h, "#ZLH".h, z31.h \n\t" \ " add "#CADDR", "#CADDR", "#CCS" \n\t" #define GEMM_CCOL_SCATTER_STORE_FWD(ZFH,ZLH,ZIDX2,PT,CRS2,CADDR,CCS,CVSKIP,CTEMP) \ " add x28, "#CADDR", "#CRS2" \n\t" \ " st1h "#ZFH".s, "#PT", ["#CADDR", "#ZIDX2".s, uxtw #1] \n\t" \ " revh "#ZFH".s, "#PT"/m, "#ZFH".s \n\t" \ " st1h "#ZFH".s, "#PT", [x28, "#ZIDX2".s, uxtw #1] \n\t" \ " add "#CTEMP", "#CADDR", "#CVSKIP" \n\t" \ " add x28, "#CTEMP", "#CRS2" \n\t" \ " st1h "#ZLH".s, "#PT", ["#CTEMP", "#ZIDX2".s, uxtw #1] \n\t" \ " revh "#ZLH".s, "#PT"/m, "#ZLH".s \n\t" \ " st1h "#ZLH".s, "#PT", [x28, "#ZIDX2".s, uxtw #1] \n\t" \ " add "#CADDR", "#CADDR", "#CCS" \n\t" void bli_shgemm_armsve_asm_2vx10_unindexed ( dim_t k0, void* restrict alpha, void* restrict a, void* restrict b, void* restrict beta, void* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { void* a_next = bli_auxinfo_next_a( data ); void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_mker = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; __asm__ volatile ( " ldr x0, %[a] \n\t" " ldr x1, %[b] \n\t" " mov x2, xzr \n\t" " inch x2, ALL, MUL #2 \n\t" // Column-skip of A. " mov x3, #10 \n\t" // Row-skip of B. " \n\t" " ldr x5, %[c] \n\t" " ldr x6, %[rs_c] \n\t" // Row-skip of C. " ldr x7, %[cs_c] \n\t" // Column-skip of C. #ifdef _A64FX " mov x8, 0x3 \n\t" // Tag C address. " lsl x8, x8, #56 \n\t" " orr x5, x5, x8 \n\t" " mov x8, 0x2 \n\t" // Tag B address. " lsl x8, x8, #56 \n\t" " orr x1, x1, x8 \n\t" " mov x8, 0x1 \n\t" // Tag A address. " lsl x8, x8, #56 \n\t" " orr x0, x0, x8 \n\t" #endif " \n\t" " mov x8, #2 \n\t" // Multiply some address skips by sizeof(float16_t). " madd x2, x8, x2, xzr \n\t" // cs_a " madd x3, x8, x3, xzr \n\t" // rs_b " madd x7, x8, x7, xzr \n\t" // cs_c " ptrue p0.b \n\t" " \n\t" " ldr x4, %[k_mker] \n\t" // Number of loops. " ldr x8, %[k_left] \n\t" " \n\t" " LOAD_ABC: \n\t" " cmp x4, #0 \n\t" // Don't preload if no microkernel there. " b.eq END_CCOL_PRFM \n\t" " ld1rh z20.h, p0/z, [x1] \n\t" // Load 8/10 of first B row. " ld1rh z21.h, p0/z, [x1, 2] \n\t" " ld1rh z22.h, p0/z, [x1, 4] \n\t" " ld1rh z23.h, p0/z, [x1, 6] \n\t" " ld1rh z24.h, p0/z, [x1, 8] \n\t" " ld1rh z25.h, p0/z, [x1, 10] \n\t" " ld1rh z26.h, p0/z, [x1, 12] \n\t" " ld1rh z27.h, p0/z, [x1, 14] \n\t" " \n\t" GEMM_ACOL_CONTIGUOUS_LOAD(z28,z29,p0,p0,x0) " \n\t" " CCOL_PRFM: \n\t" " cmp x6, #1 \n\t" " b.ne END_CCOL_PRFM \n\t" // Do not prefetch for generic C storage. " mov x16, x5 \n\t" " prfm PLDL1STRM, [x16] \n\t" " add x16, x16, x7 \n\t" " prfm PLDL1STRM, [x16] \n\t" " add x16, x16, x7 \n\t" " prfm PLDL1STRM, [x16] \n\t" " add x16, x16, x7 \n\t" " prfm PLDL1STRM, [x16] \n\t" " add x16, x16, x7 \n\t" " prfm PLDL1STRM, [x16] \n\t" " add x16, x16, x7 \n\t" " prfm PLDL1STRM, [x16] \n\t" " add x16, x16, x7 \n\t" " prfm PLDL1STRM, [x16] \n\t" " add x16, x16, x7 \n\t" " prfm PLDL1STRM, [x16] \n\t" " add x16, x16, x7 \n\t" " prfm PLDL1STRM, [x16] \n\t" " add x16, x16, x7 \n\t" " prfm PLDL1STRM, [x16] \n\t" " END_CCOL_PRFM: \n\t" " \n\t" CLEAR_COL20(z0,z1,z2,z3,z4,z5,z6,z7,z8,z9,z10,z11,z12,z13,z14,z15,z16,z17,z18,z19) " \n\t" " cmp x4, #0 \n\t" // If no 4-microkernel can be applied " b.eq K_LEFT_LOOP \n\t" " \n\t" " K_MKER_LOOP: \n\t" " \n\t" " add x0, x0, x2 \n\t" // Forward A's address to the next column. GEMM_ACOL_CONTIGUOUS_LOAD(z30,z31,p0,p0,x0) GEMM_2VX10_MKER_LOOP_PLAIN_C_1(z0,z2,z4,z6,z8,z10,z12,z14,z16,z18,z1,z3,z5,z7,z9,z11,z13,z15,z17,z19,p0,z28,z29,z20,z21,z22,z23,z24,z25,z26,z27,x1,x3) " \n\t" " add x0, x0, x2 \n\t" // Forward A's address to the next column. GEMM_ACOL_CONTIGUOUS_LOAD(z28,z29,p0,p0,x0) GEMM_2VX10_MKER_LOOP_PLAIN_C_2(z0,z2,z4,z6,z8,z10,z12,z14,z16,z18,z1,z3,z5,z7,z9,z11,z13,z15,z17,z19,p0,z30,z31,z20,z21,z22,z23,z24,z25,z26,z27,x1,x3) " \n\t" " add x0, x0, x2 \n\t" // Forward A's address to the next column. GEMM_ACOL_CONTIGUOUS_LOAD(z30,z31,p0,p0,x0) GEMM_2VX10_MKER_LOOP_PLAIN_C_3(z0,z2,z4,z6,z8,z10,z12,z14,z16,z18,z1,z3,z5,z7,z9,z11,z13,z15,z17,z19,p0,z28,z29,z20,z21,z22,z23,z24,z25,z26,z27,x1,x3) " \n\t" " subs x4, x4, #1 \n\t" // Decrease counter before final replica. " b.eq FIN_MKER_LOOP \n\t" // Branch early to avoid reading excess mem. " \n\t" " add x0, x0, x2 \n\t" // Forward A's address to the next column. GEMM_ACOL_CONTIGUOUS_LOAD(z28,z29,p0,p0,x0) GEMM_2VX10_MKER_LOOP_PLAIN_C_4(z0,z2,z4,z6,z8,z10,z12,z14,z16,z18,z1,z3,z5,z7,z9,z11,z13,z15,z17,z19,p0,z30,z31,z20,z21,z22,z23,z24,z25,z26,z27,x1,x3) " b K_MKER_LOOP \n\t" " \n\t" " FIN_MKER_LOOP: \n\t" GEMM_2VX10_MKER_LOOP_PLAIN_C_4_RESIDUAL(z0,z2,z4,z6,z8,z10,z12,z14,z16,z18,z1,z3,z5,z7,z9,z11,z13,z15,z17,z19,p0,z30,z31,z20,z21,z22,z23,z24,z25,z26,z27,x1,x3) " add x0, x0, x2 \n\t" // Forward A to fill the blank. " \n\t" " K_LEFT_LOOP: \n\t" " cmp x8, #0 \n\t" // End of execution. " b.eq WRITE_MEM_PREP \n\t" " \n\t" GEMM_ACOL_CONTIGUOUS_LOAD(z30,z31,p0,p0,x0) " ld1rh z20.h, p0/z, [x1] \n\t" // Load 8/10 of first B row. " ld1rh z21.h, p0/z, [x1, 2] \n\t" " ld1rh z22.h, p0/z, [x1, 4] \n\t" " ld1rh z23.h, p0/z, [x1, 6] \n\t" " ld1rh z24.h, p0/z, [x1, 8] \n\t" " ld1rh z25.h, p0/z, [x1, 10] \n\t" " ld1rh z26.h, p0/z, [x1, 12] \n\t" " ld1rh z27.h, p0/z, [x1, 14] \n\t" " ld1rh z28.h, p0/z, [x1, 16] \n\t" " ld1rh z29.h, p0/z, [x1, 18] \n\t" GEMM_FMLA2(z0,z1,p0,z30,z31,z20) GEMM_FMLA2(z2,z3,p0,z30,z31,z21) GEMM_FMLA2(z4,z5,p0,z30,z31,z22) GEMM_FMLA2(z6,z7,p0,z30,z31,z23) GEMM_FMLA2(z8,z9,p0,z30,z31,z24) GEMM_FMLA2(z10,z11,p0,z30,z31,z25) GEMM_FMLA2(z12,z13,p0,z30,z31,z26) GEMM_FMLA2(z14,z15,p0,z30,z31,z27) GEMM_FMLA2(z16,z17,p0,z30,z31,z28) GEMM_FMLA2(z18,z19,p0,z30,z31,z29) " add x0, x0, x2 \n\t" // Forward A. " add x1, x1, x3 \n\t" // Forward B. " sub x8, x8, #1 \n\t" " b K_LEFT_LOOP \n\t" // Next column / row. " \n\t" " WRITE_MEM_PREP: \n\t" " \n\t" " ldr x4, %[alpha] \n\t" // Load alpha & beta (address). " ldr x8, %[beta] \n\t" " ld1rh z30.h, p0/z, [x4] \n\t" // Load alpha & beta into vectors. " ld1rh z31.h, p0/z, [x8] \n\t" " fmov w4, h28 \n\t" // Copy alpha & beta to GP registers. " fmov w8, h29 \n\t" " \n\t" " PREFETCH_ABNEXT: \n\t" " ldr x0, %[a_next] \n\t" " ldr x1, %[b_next] \n\t" " prfm PLDL2KEEP, [x0] \n\t" " prfm PLDL2KEEP, [x0, 256*1] \n\t" " prfm PLDL2KEEP, [x0, 256*2] \n\t" " prfm PLDL2KEEP, [x0, 256*3] \n\t" " prfm PLDL2KEEP, [x0, 256*4] \n\t" " prfm PLDL2KEEP, [x0, 256*5] \n\t" " prfm PLDL2KEEP, [x0, 256*6] \n\t" " prfm PLDL2KEEP, [x0, 256*7] \n\t" " prfm PLDL2KEEP, [x0, 256*8] \n\t" " prfm PLDL2KEEP, [x0, 256*9] \n\t" " prfm PLDL2KEEP, [x0, 256*10] \n\t" " prfm PLDL2KEEP, [x0, 256*11] \n\t" " prfm PLDL2KEEP, [x0, 256*12] \n\t" " prfm PLDL2KEEP, [x0, 256*13] \n\t" " prfm PLDL2KEEP, [x0, 256*14] \n\t" " prfm PLDL2KEEP, [x0, 256*15] \n\t" " prfm PLDL2KEEP, [x1] \n\t" " prfm PLDL2KEEP, [x1, 256*1] \n\t" " prfm PLDL2KEEP, [x1, 256*2] \n\t" " prfm PLDL2KEEP, [x1, 256*3] \n\t" " prfm PLDL2KEEP, [x1, 256*4] \n\t" " prfm PLDL2KEEP, [x1, 256*5] \n\t" " prfm PLDL2KEEP, [x1, 256*6] \n\t" " prfm PLDL2KEEP, [x1, 256*7] \n\t" " prfm PLDL2KEEP, [x1, 256*8] \n\t" " prfm PLDL2KEEP, [x1, 256*9] \n\t" " \n\t" " WRITE_MEM: \n\t" " \n\t" " fmov h28, #1.0 \n\t" " fmov w16, h28 \n\t" " cmp w16, w4 \n\t" " b.eq UNIT_ALPHA \n\t" " \n\t" SCALE_COL20(z0,z1,z2,z3,z4,z5,z6,z7,z8,z9,z10,z11,z12,z13,z14,z15,z16,z17,z18,z19,z30) " \n\t" " UNIT_ALPHA: \n\t" " mov x9, x5 \n\t" // C address for loading. " \n\t" // C address for storing is x5 itself. " cmp x6, #1 \n\t" " b.ne WRITE_MEM_G \n\t" " \n\t" " WRITE_MEM_C: \n\t" // Available scratch: Z[20-30]. " \n\t" // Here used scratch: Z[20-29]. GEMM_C_LOAD_UKER_C(z20,z22,z24,z26,z28,z21,z23,z25,z27,z29,p0,p0,x9,x7) GEMM_C_FMAD_UKER(z20,z22,z24,z26,z28,z21,z23,z25,z27,z29,p0,p0,z0,z2,z4,z6,z8,z1,z3,z5,z7,z9,z31) GEMM_C_LOAD_UKER_C(z0,z2,z4,z6,z8,z1,z3,z5,z7,z9,p0,p0,x9,x7) " \n\t" GEMM_C_STORE_UKER_C(z20,z22,z24,z26,z28,z21,z23,z25,z27,z29,p0,p0,x5,x7) GEMM_C_FMAD_UKER(z0,z2,z4,z6,z8,z1,z3,z5,z7,z9,p0,p0,z10,z12,z14,z16,z18,z11,z13,z15,z17,z19,z31) GEMM_C_STORE_UKER_C(z0,z2,z4,z6,z8,z1,z3,z5,z7,z9,p0,p0,x5,x7) " b END_WRITE_MEM \n\t" " \n\t" " WRITE_MEM_G: \n\t" // Available scratch: Z[20-30]. " \n\t" // Here used scratch: Z[20-30] - Z30 as index. " mov x10, xzr \n\t" " incb x10 \n\t" " madd x10, x10, x6, xzr \n\t" // C-column's logical 1-vector skip. " mov x28, #2 \n\t" " madd x6, x28, x6, xzr \n\t" // Double index skip for half-precision case. " index z30.s, wzr, w6 \n\t" // Skips passed to index is not multiplied by 8. GEMM_C_LOAD_UKER_G(z20,z22,z24,z26,z28,z21,z23,z25,z27,z29,z30,p0,x6,x9,x7,x10,x16) " dup z31.h, w8 \n\t" // Restore beta destroyed by loading. GEMM_C_FMAD_UKER(z20,z22,z24,z26,z28,z21,z23,z25,z27,z29,p0,p0,z0,z2,z4,z6,z8,z1,z3,z5,z7,z9,z31) GEMM_C_LOAD_UKER_G(z0,z2,z4,z6,z8,z1,z3,z5,z7,z9,z30,p0,x6,x9,x7,x10,x16) " \n\t" " dup z31.h, w8 \n\t" // Restore beta destroyed by loading. GEMM_C_STORE_UKER_G(z20,z22,z24,z26,z28,z21,z23,z25,z27,z29,z30,p0,x6,x5,x7,x10,x16) GEMM_C_FMAD_UKER(z0,z2,z4,z6,z8,z1,z3,z5,z7,z9,p0,p0,z10,z12,z14,z16,z18,z11,z13,z15,z17,z19,z31) GEMM_C_STORE_UKER_G(z0,z2,z4,z6,z8,z1,z3,z5,z7,z9,z30,p0,x6,x5,x7,x10,x16) " \n\t" " END_WRITE_MEM: \n\t" " b END_EXEC \n\t" " \n\t" " END_ERROR: \n\t" " mov x0, #1 \n\t" // Return error. " END_EXEC: \n\t" " mov x0, #0 \n\t" // Return normal. : : [a] "m" (a), [b] "m" (b), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c), [k_mker] "m" (k_mker), [k_left] "m" (k_left), [alpha] "m" (alpha), [beta] "m" (beta), [a_next] "m" (a_next), [b_next] "m" (b_next) : "x0","x1","x2","x3","x4","x5","x6","x7","x8", "x9","x16","x10","x28", "z0","z1","z2","z3","z4","z5","z6","z7", "z8","z9","z10","z11","z12","z13","z14","z15", "z16","z17","z18","z19", "z20","z21","z22","z23", "z24","z25","z26","z27", "z28","z29","z30","z31" ); } blis-0.9.0/kernels/armsve/3/old/bli_gemm_armsve_asm_z2vx7_unindexed.c000066400000000000000000000345271422157504600256310ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2019, Forschunszentrum Juelich Copyright (C) 2020, The University of Tokyo 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // Double-precision composite instructions. #include "armsve_asm_macros_dcomplex.h" // 2vx7 microkernels. #include "armsve_asm_2vx7cmplx.h" void bli_zgemm_armsve_asm_2vx7_unindexed ( dim_t m, dim_t n, dim_t k, dcomplex* restrict alpha, dcomplex* restrict a, dcomplex* restrict b, dcomplex* restrict beta, dcomplex* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { void* a_next = bli_auxinfo_next_a( data ); void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_mker = k / 4; uint64_t k_left = k % 4; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; uint64_t info = 0; uint64_t mr = bli_vl_bytes_armsve() * 2 / 16; GEMM_UKR_SETUP_CT( z, mr, 7, false ); __asm__ volatile ( // " ldr x0, %[a] \n\t" // " ldr x1, %[b] \n\t" " mov x2, xzr \n\t" " incd x2, ALL, MUL #1 \n\t" // Column-skip of A. " mov x3, #7 \n\t" // Row-skip of B. " \n\t" // " ldr x2, %[c] \n\t" // " ldr x3, %[rs_c] \n\t" // Row-skip of C. // " ldr x4, %[cs_c] \n\t" // Column-skip of C. #ifdef _A64FX " mov x16, 0x1 \n\t" // Tag A address. " lsl x16, x16, #56 \n\t" " orr %0, %0, x16 \n\t" " mov x16, 0x2 \n\t" // Tag B address. " lsl x16, x16, #56 \n\t" " orr %1, %1, x16 \n\t" " mov x16, 0x3 \n\t" // Tag C address. " lsl x16, x16, #56 \n\t" " orr %2, %2, x16 \n\t" #endif " \n\t" " mov x16, #16 \n\t" // Multiply some address skips by sizeof(dcomplex). " madd x2, x16, x2, xzr \n\t" // cs_a " madd x3, x16, x3, xzr \n\t" // rs_b " madd %4, x16, %4, xzr \n\t" // cs_c " ptrue p0.d \n\t" " \n\t" // " ldr x5, %[k_mker] \n\t" // Number of loops. // " ldr x6, %[k_left] \n\t" " \n\t" " LOAD_ABC: \n\t" " cmp %5, #0 \n\t" // Don't preload if no microkernel there. " b.eq END_CCOL_PRFM \n\t" " \n\t" GEMM_ACOLCMPLX_CONTIGUOUS_LOAD_FWD(z28,z29,p0,%0,x2) " \n\t" " ld1rd z14.d, p0/z, [%1, 8*0] \n\t" // Load B's real & imaginary. " ld1rd z15.d, p0/z, [%1, 8*2] \n\t" " ld1rd z16.d, p0/z, [%1, 8*4] \n\t" " ld1rd z17.d, p0/z, [%1, 8*6] \n\t" " ld1rd z18.d, p0/z, [%1, 8*8] \n\t" " ld1rd z19.d, p0/z, [%1, 8*10] \n\t" " ld1rd z20.d, p0/z, [%1, 8*12] \n\t" " ld1rd z21.d, p0/z, [%1, 8*1] \n\t" " ld1rd z22.d, p0/z, [%1, 8*3] \n\t" " ld1rd z23.d, p0/z, [%1, 8*5] \n\t" " ld1rd z24.d, p0/z, [%1, 8*7] \n\t" " ld1rd z25.d, p0/z, [%1, 8*9] \n\t" " ld1rd z26.d, p0/z, [%1, 8*11] \n\t" " ld1rd z27.d, p0/z, [%1, 8*13] \n\t" " add %1, %1, x3 \n\t" " \n\t" " CCOL_PRFM: \n\t" " cmp %3, #1 \n\t" " b.ne END_CCOL_PRFM \n\t" // Do not prefetch for generic C storage. " mov x16, %2 \n\t" " prfm PLDL1KEEP, [x16] \n\t" " add x16, x16, %4 \n\t" " prfm PLDL1KEEP, [x16] \n\t" " add x16, x16, %4 \n\t" " prfm PLDL1KEEP, [x16] \n\t" " add x16, x16, %4 \n\t" " prfm PLDL1KEEP, [x16] \n\t" " add x16, x16, %4 \n\t" " prfm PLDL1KEEP, [x16] \n\t" " add x16, x16, %4 \n\t" " prfm PLDL1KEEP, [x16] \n\t" " add x16, x16, %4 \n\t" " prfm PLDL1KEEP, [x16] \n\t" " END_CCOL_PRFM: \n\t" " \n\t" CLEAR_COL14(z0,z1,z2,z3,z4,z5,z6,z7,z8,z9,z10,z11,z12,z13) " \n\t" " cmp %5, #0 \n\t" // If no 4-microkernel can be applied " b.eq K_LEFT_LOOP \n\t" " \n\t" " K_MKER_LOOP: \n\t" " \n\t" GEMM_ACOLCMPLX_CONTIGUOUS_LOAD_FWD(z30,z31,p0,%0,x2) GEMM_2VX7CMPLX_MKER_LOOP_PLAIN_C(z0,z2,z4,z6,z8,z10,z12,z1,z3,z5,z7,z9,z11,z13,p0,z28,z29,z14,z15,z16,z17,z18,z19,z20,z21,z22,z23,z24,z25,z26,z27,%1,x3) " \n\t" GEMM_ACOLCMPLX_CONTIGUOUS_LOAD_FWD(z28,z29,p0,%0,x2) GEMM_2VX7CMPLX_MKER_LOOP_PLAIN_C(z0,z2,z4,z6,z8,z10,z12,z1,z3,z5,z7,z9,z11,z13,p0,z30,z31,z14,z15,z16,z17,z18,z19,z20,z21,z22,z23,z24,z25,z26,z27,%1,x3) " \n\t" GEMM_ACOLCMPLX_CONTIGUOUS_LOAD_FWD(z30,z31,p0,%0,x2) GEMM_2VX7CMPLX_MKER_LOOP_PLAIN_C(z0,z2,z4,z6,z8,z10,z12,z1,z3,z5,z7,z9,z11,z13,p0,z28,z29,z14,z15,z16,z17,z18,z19,z20,z21,z22,z23,z24,z25,z26,z27,%1,x3) " \n\t" " subs %5, %5, #1 \n\t" // Decrease counter before final replica. " b.eq FIN_MKER_LOOP \n\t" // Branch early to avoid reading excess mem. " \n\t" GEMM_ACOLCMPLX_CONTIGUOUS_LOAD_FWD(z28,z29,p0,%0,x2) GEMM_2VX7CMPLX_MKER_LOOP_PLAIN_C(z0,z2,z4,z6,z8,z10,z12,z1,z3,z5,z7,z9,z11,z13,p0,z30,z31,z14,z15,z16,z17,z18,z19,z20,z21,z22,z23,z24,z25,z26,z27,%1,x3) " b K_MKER_LOOP \n\t" " \n\t" " FIN_MKER_LOOP: \n\t" GEMM_2VX7CMPLX_MKER_LOOP_PLAIN_C_RESIDUAL(z0,z2,z4,z6,z8,z10,z12,z1,z3,z5,z7,z9,z11,z13,p0,z30,z31,z14,z15,z16,z17,z18,z19,z20,z21,z22,z23,z24,z25,z26,z27,%1,x3) " \n\t" " K_LEFT_LOOP: \n\t" " cmp %6, #0 \n\t" // End of execution. " b.eq WRITE_MEM_PREP \n\t" " \n\t" GEMM_ACOLCMPLX_CONTIGUOUS_LOAD_FWD(z28,z29,p0,%0,x2) " ld1rd z14.d, p0/z, [%1, 8*0] \n\t" " ld1rd z15.d, p0/z, [%1, 8*2] \n\t" " ld1rd z16.d, p0/z, [%1, 8*4] \n\t" " ld1rd z17.d, p0/z, [%1, 8*6] \n\t" " ld1rd z18.d, p0/z, [%1, 8*8] \n\t" " ld1rd z19.d, p0/z, [%1, 8*10] \n\t" " ld1rd z20.d, p0/z, [%1, 8*12] \n\t" " ld1rd z21.d, p0/z, [%1, 8*1] \n\t" " ld1rd z22.d, p0/z, [%1, 8*3] \n\t" " ld1rd z23.d, p0/z, [%1, 8*5] \n\t" " ld1rd z24.d, p0/z, [%1, 8*7] \n\t" " ld1rd z25.d, p0/z, [%1, 8*9] \n\t" " ld1rd z26.d, p0/z, [%1, 8*11] \n\t" " ld1rd z27.d, p0/z, [%1, 8*13] \n\t" " add %1, %1, x3 \n\t" GEMM_2VX7CMPLX_MKER_LOOP_PLAIN_C_RESIDUAL(z0,z2,z4,z6,z8,z10,z12,z1,z3,z5,z7,z9,z11,z13,p0,z28,z29,z14,z15,z16,z17,z18,z19,z20,z21,z22,z23,z24,z25,z26,z27,%1,x3) " sub %6, %6, #1 \n\t" " b K_LEFT_LOOP \n\t" // Next column / row. " \n\t" " WRITE_MEM_PREP: \n\t" " \n\t" // " ldr x7, %[alpha] \n\t" // Load alpha & beta (address). // " ldr x8, %[beta] \n\t" " ld1rd z28.d, p0/z, [%7] \n\t" // Real(alpha). " ld1rd z29.d, p0/z, [%7, 8] \n\t" // Imag(alpha). " ld1rd z30.d, p0/z, [%8] \n\t" // Real(beta). " ld1rd z31.d, p0/z, [%8, 8] \n\t" // Imag(beta). " \n\t" " PREFETCH_ABNEXT: \n\t" // " ldr x9, %[a_next] \n\t" // " ldr x10, %[b_next] \n\t" #ifdef _A64FX " mov x16, 0x1 \n\t" // Tag A address. " lsl x16, x16, #56 \n\t" " orr %9, %9, x16 \n\t" " mov x16, 0x2 \n\t" // Tag B address. " lsl x16, x16, #56 \n\t" " orr %10, %10, x16 \n\t" #endif " prfm PLDL1STRM, [%9] \n\t" " prfm PLDL1STRM, [%9, 256*1] \n\t" " prfm PLDL1STRM, [%10] \n\t" " prfm PLDL1STRM, [%10, 256*1] \n\t" " \n\t" " WRITE_MEM: \n\t" " \n\t" GEMM_FMULCMPLX_COL7(z14,z15,z16,z17,z18,z19,z20,z21,z22,z23,z24,z25,z26,z27,p0,z0,z1,z2,z3,z4,z5,z6,z7,z8,z9,z10,z11,z12,z13,z28,z29) " \n\t" " UNIT_ALPHA: \n\t" " mov x9, %2 \n\t" // C address for loading. " \n\t" // C address for storing is %2 itself. " cmp %3, #1 \n\t" " b.ne WRITE_MEM_G \n\t" " \n\t" " WRITE_MEM_C: \n\t" GEMM_CCMPLX_LOAD_COL7_C(z0,z1,z2,z3,z4,z5,z6,z7,z8,z9,z10,z11,z12,z13,p0,x9,%4) GEMM_FMLACMPLX_COL7(z14,z15,z16,z17,z18,z19,z20,z21,z22,z23,z24,z25,z26,z27,p0,z0,z1,z2,z3,z4,z5,z6,z7,z8,z9,z10,z11,z12,z13,z30,z31) GEMM_CCMPLX_STORE_COL7_C(z14,z15,z16,z17,z18,z19,z20,z21,z22,z23,z24,z25,z26,z27,p0,%2,%4) " b END_WRITE_MEM \n\t" " \n\t" " WRITE_MEM_G: \n\t" " add %3, %3, %3 \n\t" // Skips passed to index is multiplied by 2, " index z28.d, xzr, %3 \n\t" // s.t. 2*sizeof(double) = 2*8 = 16. GEMM_CCMPLX_LOAD_COL7_G(z0,z1,z2,z3,z4,z5,z6,z7,z8,z9,z10,z11,z12,z13,p0,z28,x9,%4,x16) GEMM_FMLACMPLX_COL7(z14,z15,z16,z17,z18,z19,z20,z21,z22,z23,z24,z25,z26,z27,p0,z0,z1,z2,z3,z4,z5,z6,z7,z8,z9,z10,z11,z12,z13,z30,z31) GEMM_CCMPLX_STORE_COL7_G(z14,z15,z16,z17,z18,z19,z20,z21,z22,z23,z24,z25,z26,z27,p0,z28,%2,%4,x16) " \n\t" " END_WRITE_MEM: \n\t" " b END_EXEC \n\t" " \n\t" " END_EXEC: \n\t" " mov %11, #0 \n\t" // Return normal. : "+r" (a), // %0 "+r" (b), // %1 "+r" (c), // %2 "+r" (rs_c), // %3 "+r" (cs_c), // %4 "+r" (k_mker), // %5 "+r" (k_left), // %6 "+r" (alpha), // %7 "+r" (beta), // %8 "+r" (a_next), // %9 "+r" (b_next), // %10 "=r" (info) // %11 : : "x2","x3","x9","x16", "z0","z1","z2","z3","z4","z5","z6","z7", "z8","z9","z10","z11","z12","z13","z14","z15", "z16","z17","z18","z19", "z20","z21","z22","z23", "z24","z25","z26","z27", "z28","z29","z30","z31" ); GEMM_UKR_FLUSH_CT( z ); } blis-0.9.0/kernels/armsve/3/old/bli_gemm_armsve_asm_z2vx8_unindexed.c000066400000000000000000000372511422157504600256270ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2019, Forschunszentrum Juelich Copyright (C) 2020, The University of Tokyo 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // Double-precision composite instructions. #include "armsve_asm_macros_dcomplex.h" // 2vx8 microkernels. #include "armsve_asm_2vx8cmplx.h" void bli_zgemm_armsve_asm_2vx8_unindexed ( dim_t m, dim_t n, dim_t k, dcomplex* restrict alpha, dcomplex* restrict a, dcomplex* restrict b, dcomplex* restrict beta, dcomplex* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { void* a_next = bli_auxinfo_next_a( data ); void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_mker = k / 6; uint64_t k_left = k % 6; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; uint64_t info = 0; uint64_t mr = bli_vl_bytes_armsve() * 2 / 16; GEMM_UKR_SETUP_CT( z, mr, 8, false ); __asm__ volatile ( // " ldr x0, %[a] \n\t" // " ldr x1, %[b] \n\t" " mov x2, xzr \n\t" " incd x2, ALL, MUL #1 \n\t" // Column-skip of A. " mov x3, #8 \n\t" // Row-skip of B. " \n\t" // " ldr x2, %[c] \n\t" // " ldr x3, %[rs_c] \n\t" // Row-skip of C. // " ldr x4, %[cs_c] \n\t" // Column-skip of C. #ifdef _A64FX " mov x16, 0x1 \n\t" // Tag A address. " lsl x16, x16, #56 \n\t" " orr %0, %0, x16 \n\t" " mov x16, 0x2 \n\t" // Tag B address. " lsl x16, x16, #56 \n\t" " orr %1, %1, x16 \n\t" " mov x16, 0x3 \n\t" // Tag C address. " lsl x16, x16, #56 \n\t" " orr %2, %2, x16 \n\t" #endif " \n\t" " mov x16, #16 \n\t" // Multiply some address skips by sizeof(dcomplex). " madd x2, x16, x2, xzr \n\t" // cs_a " madd x3, x16, x3, xzr \n\t" // rs_b " madd %4, x16, %4, xzr \n\t" // cs_c " ptrue p0.d \n\t" " \n\t" // " ldr x5, %[k_mker] \n\t" // Number of loops. // " ldr x6, %[k_left] \n\t" " \n\t" " LOAD_ABC: \n\t" " cmp %5, #0 \n\t" // Don't preload if no microkernel there. " b.eq END_CCOL_PRFM \n\t" " \n\t" " ld1rd z20.d, p0/z, [%1, 8*0] \n\t" // Load B's real & half of imaginary. " ld1rd z21.d, p0/z, [%1, 8*2] \n\t" " ld1rd z22.d, p0/z, [%1, 8*4] \n\t" " ld1rd z23.d, p0/z, [%1, 8*6] \n\t" " ld1rd z24.d, p0/z, [%1, 8*8] \n\t" " ld1rd z25.d, p0/z, [%1, 8*10] \n\t" " ld1rd z26.d, p0/z, [%1, 8*12] \n\t" " ld1rd z27.d, p0/z, [%1, 8*14] \n\t" " ld1rd z28.d, p0/z, [%1, 8*1] \n\t" " ld1rd z29.d, p0/z, [%1, 8*3] \n\t" " ld1rd z30.d, p0/z, [%1, 8*5] \n\t" " ld1rd z31.d, p0/z, [%1, 8*7] \n\t" " \n\t" GEMM_ACOLCMPLX_CONTIGUOUS_LOAD_FWD(z16,z17,p0,%0,x2) " \n\t" " CCOL_PRFM: \n\t" " cmp %3, #1 \n\t" " b.ne END_CCOL_PRFM \n\t" // Do not prefetch for generic C storage. " mov x16, %2 \n\t" " prfm PLDL1KEEP, [x16] \n\t" " add x16, x16, %4 \n\t" " prfm PLDL1KEEP, [x16] \n\t" " add x16, x16, %4 \n\t" " prfm PLDL1KEEP, [x16] \n\t" " add x16, x16, %4 \n\t" " prfm PLDL1KEEP, [x16] \n\t" " add x16, x16, %4 \n\t" " prfm PLDL1KEEP, [x16] \n\t" " add x16, x16, %4 \n\t" " prfm PLDL1KEEP, [x16] \n\t" " add x16, x16, %4 \n\t" " prfm PLDL1KEEP, [x16] \n\t" " add x16, x16, %4 \n\t" " prfm PLDL1KEEP, [x16] \n\t" " END_CCOL_PRFM: \n\t" " \n\t" CLEAR_COL16(z0,z1,z2,z3,z4,z5,z6,z7,z8,z9,z10,z11,z12,z13,z14,z15) " \n\t" " cmp %5, #0 \n\t" // If no 6-microkernel can be applied " b.eq K_LEFT_LOOP \n\t" " \n\t" " K_MKER_LOOP: \n\t" " \n\t" GEMM_ACOLCMPLX_CONTIGUOUS_LOAD_FWD(z18,z19,p0,%0,x2) GEMM_2VX8CMPLX_MKER_LOOP_PLAIN_C_1(z0,z2,z4,z6,z8,z10,z12,z14,z1,z3,z5,z7,z9,z11,z13,z15,p0,z16,z17,z20,z21,z22,z23,z24,z25,z26,z27,z28,z29,z30,z31,%1,x3) " \n\t" GEMM_ACOLCMPLX_CONTIGUOUS_LOAD_FWD(z16,z17,p0,%0,x2) GEMM_2VX8CMPLX_MKER_LOOP_PLAIN_C_2(z0,z2,z4,z6,z8,z10,z12,z14,z1,z3,z5,z7,z9,z11,z13,z15,p0,z18,z19,z20,z21,z22,z23,z24,z25,z26,z27,z28,z29,z30,z31,%1,x3) " \n\t" GEMM_ACOLCMPLX_CONTIGUOUS_LOAD_FWD(z18,z19,p0,%0,x2) GEMM_2VX8CMPLX_MKER_LOOP_PLAIN_C_3(z0,z2,z4,z6,z8,z10,z12,z14,z1,z3,z5,z7,z9,z11,z13,z15,p0,z16,z17,z20,z21,z22,z23,z24,z25,z26,z27,z28,z29,z30,z31,%1,x3) " \n\t" GEMM_ACOLCMPLX_CONTIGUOUS_LOAD_FWD(z16,z17,p0,%0,x2) GEMM_2VX8CMPLX_MKER_LOOP_PLAIN_C_1(z0,z2,z4,z6,z8,z10,z12,z14,z1,z3,z5,z7,z9,z11,z13,z15,p0,z18,z19,z20,z21,z22,z23,z24,z25,z26,z27,z28,z29,z30,z31,%1,x3) " \n\t" GEMM_ACOLCMPLX_CONTIGUOUS_LOAD_FWD(z18,z19,p0,%0,x2) GEMM_2VX8CMPLX_MKER_LOOP_PLAIN_C_2(z0,z2,z4,z6,z8,z10,z12,z14,z1,z3,z5,z7,z9,z11,z13,z15,p0,z16,z17,z20,z21,z22,z23,z24,z25,z26,z27,z28,z29,z30,z31,%1,x3) " \n\t" " subs %5, %5, #1 \n\t" // Decrease counter before final replica. " b.eq FIN_MKER_LOOP \n\t" // Branch early to avoid reading excess mem. " \n\t" GEMM_ACOLCMPLX_CONTIGUOUS_LOAD_FWD(z16,z17,p0,%0,x2) GEMM_2VX8CMPLX_MKER_LOOP_PLAIN_C_3(z0,z2,z4,z6,z8,z10,z12,z14,z1,z3,z5,z7,z9,z11,z13,z15,p0,z18,z19,z20,z21,z22,z23,z24,z25,z26,z27,z28,z29,z30,z31,%1,x3) " b K_MKER_LOOP \n\t" " \n\t" " FIN_MKER_LOOP: \n\t" GEMM_2VX8CMPLX_MKER_LOOP_PLAIN_C_3_RESIDUAL(z0,z2,z4,z6,z8,z10,z12,z14,z1,z3,z5,z7,z9,z11,z13,z15,p0,z18,z19,z20,z21,z22,z23,z24,z25,z26,z27,z28,z29,z30,z31,%1,x3) " \n\t" " K_LEFT_LOOP: \n\t" " cmp %6, #0 \n\t" // End of execution. " b.eq WRITE_MEM_PREP \n\t" " \n\t" GEMM_ACOLCMPLX_CONTIGUOUS_LOAD_FWD(z16,z17,p0,%0,x2) " ld1rd z20.d, p0/z, [%1, 8*0] \n\t" // Reload B's real & half of imaginary. " ld1rd z21.d, p0/z, [%1, 8*2] \n\t" " ld1rd z22.d, p0/z, [%1, 8*4] \n\t" " ld1rd z23.d, p0/z, [%1, 8*6] \n\t" " ld1rd z24.d, p0/z, [%1, 8*8] \n\t" " ld1rd z25.d, p0/z, [%1, 8*10] \n\t" " ld1rd z26.d, p0/z, [%1, 8*12] \n\t" " ld1rd z27.d, p0/z, [%1, 8*14] \n\t" " ld1rd z28.d, p0/z, [%1, 8*1] \n\t" " ld1rd z29.d, p0/z, [%1, 8*3] \n\t" " ld1rd z30.d, p0/z, [%1, 8*5] \n\t" " ld1rd z31.d, p0/z, [%1, 8*7] \n\t" GEMM_2VX8CMPLX_MKER_LOOP_PLAIN_C_1_RESIDUAL(z0,z2,z4,z6,z8,z10,z12,z14,z1,z3,z5,z7,z9,z11,z13,z15,p0,z16,z17,z20,z21,z22,z23,z24,z25,z26,z27,z28,z29,z30,z31,%1,x3) " sub %6, %6, #1 \n\t" " b K_LEFT_LOOP \n\t" // Next column / row. " \n\t" " WRITE_MEM_PREP: \n\t" " \n\t" // " ldr x7, %[alpha] \n\t" // Load alpha & beta (address). // " ldr x8, %[beta] \n\t" " ld1rd z16.d, p0/z, [%7] \n\t" // Real(alpha). " ld1rd z17.d, p0/z, [%7, 8] \n\t" // Imag(alpha). " ld1rd z18.d, p0/z, [%8] \n\t" // Real(beta). " ld1rd z19.d, p0/z, [%8, 8] \n\t" // Imag(beta). " \n\t" " PREFETCH_ABNEXT: \n\t" // " ldr x9, %[a_next] \n\t" // " ldr x10, %[b_next] \n\t" #ifdef _A64FX " mov x16, 0x1 \n\t" // Tag A address. " lsl x16, x16, #56 \n\t" " orr %9, %9, x16 \n\t" " mov x16, 0x2 \n\t" // Tag B address. " lsl x16, x16, #56 \n\t" " orr %10, %10, x16 \n\t" #endif " prfm PLDL1STRM, [%9] \n\t" " prfm PLDL1STRM, [%9, 256*1] \n\t" " prfm PLDL1STRM, [%10] \n\t" " prfm PLDL1STRM, [%10, 256*1] \n\t" " \n\t" " WRITE_MEM: \n\t" " \n\t" GEMM_FMULCMPLX_COL2(z20,z21,z22,z23,p0,z0 ,z1 ,z2 ,z3 ,z16,z17) GEMM_FMULCMPLX_COL2(z0 ,z1 ,z2 ,z3 ,p0,z4 ,z5 ,z6 ,z7 ,z16,z17) GEMM_FMULCMPLX_COL2(z4 ,z5 ,z6 ,z7 ,p0,z8 ,z9 ,z10,z11,z16,z17) GEMM_FMULCMPLX_COL2(z8 ,z9 ,z10,z11,p0,z12,z13,z14,z15,z16,z17) " \n\t" " UNIT_ALPHA: \n\t" " mov x9, %2 \n\t" // C address for loading. " \n\t" // C address for storing is %2 itself. " cmp %3, #1 \n\t" " b.ne WRITE_MEM_G \n\t" " \n\t" " WRITE_MEM_C: \n\t" GEMM_CCMPLX_LOAD_COL2_C(z12,z13,z14,z15,p0,x9,%4) GEMM_CCMPLX_LOAD_COL2_C(z24,z25,z26,z27,p0,x9,%4) GEMM_FMLACMPLX_COL2(z20,z21,z22,z23,p0,z12,z13,z14,z15,z18,z19) GEMM_FMLACMPLX_COL2(z0 ,z1 ,z2 ,z3 ,p0,z24,z25,z26,z27,z18,z19) GEMM_CCMPLX_STORE_COL2_C(z20,z21,z22,z23,p0,%2,%4) GEMM_CCMPLX_STORE_COL2_C(z0 ,z1 ,z2 ,z3 ,p0,%2,%4) " \n\t" GEMM_CCMPLX_LOAD_COL2_C(z12,z13,z14,z15,p0,x9,%4) GEMM_CCMPLX_LOAD_COL2_C(z24,z25,z26,z27,p0,x9,%4) GEMM_FMLACMPLX_COL2(z4 ,z5 ,z6 ,z7 ,p0,z12,z13,z14,z15,z18,z19) GEMM_FMLACMPLX_COL2(z8 ,z9 ,z10,z11,p0,z24,z25,z26,z27,z18,z19) GEMM_CCMPLX_STORE_COL2_C(z4 ,z5 ,z6 ,z7 ,p0,%2,%4) GEMM_CCMPLX_STORE_COL2_C(z8 ,z9 ,z10,z11,p0,%2,%4) " b END_WRITE_MEM \n\t" " \n\t" " WRITE_MEM_G: \n\t" " add %3, %3, %3 \n\t" // Skips passed to index is multiplied by 2, " index z16.d, xzr, %3 \n\t" // s.t. 2*sizeof(double) = 2*8 = 16. GEMM_CCMPLX_LOAD_COL2_G(z12,z13,z14,z15,p0,z16,x9,%4,x16) GEMM_CCMPLX_LOAD_COL2_G(z24,z25,z26,z27,p0,z16,x9,%4,x16) GEMM_FMLACMPLX_COL2(z20,z21,z22,z23,p0,z12,z13,z14,z15,z18,z19) GEMM_FMLACMPLX_COL2(z0 ,z1 ,z2 ,z3 ,p0,z24,z25,z26,z27,z18,z19) GEMM_CCMPLX_STORE_COL2_G(z20,z21,z22,z23,p0,z16,%2,%4,x16) GEMM_CCMPLX_STORE_COL2_G(z0 ,z1 ,z2 ,z3 ,p0,z16,%2,%4,x16) " \n\t" GEMM_CCMPLX_LOAD_COL2_G(z12,z13,z14,z15,p0,z16,x9,%4,x16) GEMM_CCMPLX_LOAD_COL2_G(z24,z25,z26,z27,p0,z16,x9,%4,x16) GEMM_FMLACMPLX_COL2(z4 ,z5 ,z6 ,z7 ,p0,z12,z13,z14,z15,z18,z19) GEMM_FMLACMPLX_COL2(z8 ,z9 ,z10,z11,p0,z24,z25,z26,z27,z18,z19) GEMM_CCMPLX_STORE_COL2_G(z4 ,z5 ,z6 ,z7 ,p0,z16,%2,%4,x16) GEMM_CCMPLX_STORE_COL2_G(z8 ,z9 ,z10,z11,p0,z16,%2,%4,x16) " \n\t" " END_WRITE_MEM: \n\t" " b END_EXEC \n\t" " \n\t" " END_EXEC: \n\t" " mov %11, #0 \n\t" // Return normal. : "+r" (a), // %0 "+r" (b), // %1 "+r" (c), // %2 "+r" (rs_c), // %3 "+r" (cs_c), // %4 "+r" (k_mker), // %5 "+r" (k_left), // %6 "+r" (alpha), // %7 "+r" (beta), // %8 "+r" (a_next), // %9 "+r" (b_next), // %10 "=r" (info) // %11 : : "x2","x3","x9","x16", "z0","z1","z2","z3","z4","z5","z6","z7", "z8","z9","z10","z11","z12","z13","z14","z15", "z16","z17","z18","z19", "z20","z21","z22","z23", "z24","z25","z26","z27", "z28","z29","z30","z31" ); GEMM_UKR_FLUSH_CT( z ); } blis-0.9.0/kernels/armsve/3/old/sup/000077500000000000000000000000001422157504600171465ustar00rootroot00000000000000blis-0.9.0/kernels/armsve/3/old/sup/bli_gemmsup_armsve_ref.c000066400000000000000000000311441422157504600240310ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // Separate instantiation for ArmSVE reference kernels. // Temporary workaround. Will be removed after upstream has switched to a better way // of exposing gemmsup interface. // // -- Row storage case --------------------------------------------------------- // #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, arch, suf ) \ \ void PASTEMAC3(ch,opname,arch,suf) \ ( \ conj_t conja, \ conj_t conjb, \ dim_t m, \ dim_t n, \ dim_t k, \ ctype* restrict alpha, \ ctype* restrict a, inc_t rs_a, inc_t cs_a, \ ctype* restrict b, inc_t rs_b, inc_t cs_b, \ ctype* restrict beta, \ ctype* restrict c, inc_t rs_c, inc_t cs_c, \ auxinfo_t* restrict data, \ cntx_t* restrict cntx \ ) \ { \ /* NOTE: This microkernel can actually handle arbitrarily large values of m, n, and k. */ \ \ if ( bli_is_noconj( conja ) && bli_is_noconj( conjb ) ) \ { \ /* Traverse c by rows. */ \ for ( dim_t i = 0; i < m; ++i ) \ { \ ctype* restrict ci = &c[ i*rs_c ]; \ ctype* restrict ai = &a[ i*rs_a ]; \ \ for ( dim_t j = 0; j < n; ++j ) \ { \ ctype* restrict cij = &ci[ j*cs_c ]; \ ctype* restrict bj = &b [ j*cs_b ]; \ ctype ab; \ \ PASTEMAC(ch,set0s)( ab ); \ \ /* Perform a dot product to update the (i,j) element of c. */ \ for ( dim_t l = 0; l < k; ++l ) \ { \ ctype* restrict aij = &ai[ l*cs_a ]; \ ctype* restrict bij = &bj[ l*rs_b ]; \ \ PASTEMAC(ch,dots)( *aij, *bij, ab ); \ } \ \ /* If beta is one, add ab into c. If beta is zero, overwrite c with the result in ab. Otherwise, scale by beta and accumulate ab to c. */ \ if ( PASTEMAC(ch,eq1)( *beta ) ) \ { \ PASTEMAC(ch,axpys)( *alpha, ab, *cij ); \ } \ else if ( PASTEMAC(ch,eq0)( *beta ) ) \ { \ PASTEMAC(ch,scal2s)( *alpha, ab, *cij ); \ } \ else \ { \ PASTEMAC(ch,axpbys)( *alpha, ab, *beta, *cij ); \ } \ } \ } \ } \ else if ( bli_is_noconj( conja ) && bli_is_conj( conjb ) ) \ { \ /* Traverse c by rows. */ \ for ( dim_t i = 0; i < m; ++i ) \ { \ ctype* restrict ci = &c[ i*rs_c ]; \ ctype* restrict ai = &a[ i*rs_a ]; \ \ for ( dim_t j = 0; j < n; ++j ) \ { \ ctype* restrict cij = &ci[ j*cs_c ]; \ ctype* restrict bj = &b [ j*cs_b ]; \ ctype ab; \ \ PASTEMAC(ch,set0s)( ab ); \ \ /* Perform a dot product to update the (i,j) element of c. */ \ for ( dim_t l = 0; l < k; ++l ) \ { \ ctype* restrict aij = &ai[ l*cs_a ]; \ ctype* restrict bij = &bj[ l*rs_b ]; \ \ PASTEMAC(ch,axpyjs)( *aij, *bij, ab ); \ } \ \ /* If beta is one, add ab into c. If beta is zero, overwrite c with the result in ab. Otherwise, scale by beta and accumulate ab to c. */ \ if ( PASTEMAC(ch,eq1)( *beta ) ) \ { \ PASTEMAC(ch,axpys)( *alpha, ab, *cij ); \ } \ else if ( PASTEMAC(ch,eq0)( *beta ) ) \ { \ PASTEMAC(ch,scal2s)( *alpha, ab, *cij ); \ } \ else \ { \ PASTEMAC(ch,axpbys)( *alpha, ab, *beta, *cij ); \ } \ } \ } \ } \ else if ( bli_is_conj( conja ) && bli_is_noconj( conjb ) ) \ { \ /* Traverse c by rows. */ \ for ( dim_t i = 0; i < m; ++i ) \ { \ ctype* restrict ci = &c[ i*rs_c ]; \ ctype* restrict ai = &a[ i*rs_a ]; \ \ for ( dim_t j = 0; j < n; ++j ) \ { \ ctype* restrict cij = &ci[ j*cs_c ]; \ ctype* restrict bj = &b [ j*cs_b ]; \ ctype ab; \ \ PASTEMAC(ch,set0s)( ab ); \ \ /* Perform a dot product to update the (i,j) element of c. */ \ for ( dim_t l = 0; l < k; ++l ) \ { \ ctype* restrict aij = &ai[ l*cs_a ]; \ ctype* restrict bij = &bj[ l*rs_b ]; \ \ PASTEMAC(ch,dotjs)( *aij, *bij, ab ); \ } \ \ /* If beta is one, add ab into c. If beta is zero, overwrite c with the result in ab. Otherwise, scale by beta and accumulate ab to c. */ \ if ( PASTEMAC(ch,eq1)( *beta ) ) \ { \ PASTEMAC(ch,axpys)( *alpha, ab, *cij ); \ } \ else if ( PASTEMAC(ch,eq0)( *beta ) ) \ { \ PASTEMAC(ch,scal2s)( *alpha, ab, *cij ); \ } \ else \ { \ PASTEMAC(ch,axpbys)( *alpha, ab, *beta, *cij ); \ } \ } \ } \ } \ else /* if ( bli_is_conj( conja ) && bli_is_conj( conjb ) ) */ \ { \ /* Traverse c by rows. */ \ for ( dim_t i = 0; i < m; ++i ) \ { \ ctype* restrict ci = &c[ i*rs_c ]; \ ctype* restrict ai = &a[ i*rs_a ]; \ \ for ( dim_t j = 0; j < n; ++j ) \ { \ ctype* restrict cij = &ci[ j*cs_c ]; \ ctype* restrict bj = &b [ j*cs_b ]; \ ctype ab; \ \ PASTEMAC(ch,set0s)( ab ); \ \ /* Perform a dot product to update the (i,j) element of c. */ \ for ( dim_t l = 0; l < k; ++l ) \ { \ ctype* restrict aij = &ai[ l*cs_a ]; \ ctype* restrict bij = &bj[ l*rs_b ]; \ \ PASTEMAC(ch,dots)( *aij, *bij, ab ); \ } \ \ /* Conjugate the result to simulate conj(a^T) * conj(b). */ \ PASTEMAC(ch,conjs)( ab ); \ \ /* If beta is one, add ab into c. If beta is zero, overwrite c with the result in ab. Otherwise, scale by beta and accumulate ab to c. */ \ if ( PASTEMAC(ch,eq1)( *beta ) ) \ { \ PASTEMAC(ch,axpys)( *alpha, ab, *cij ); \ } \ else if ( PASTEMAC(ch,eq0)( *beta ) ) \ { \ PASTEMAC(ch,scal2s)( *alpha, ab, *cij ); \ } \ else \ { \ PASTEMAC(ch,axpbys)( *alpha, ab, *beta, *cij ); \ } \ } \ } \ } \ } INSERT_GENTFUNC_BASIC2( gemmsup_r, _armsve, _ref2 ) // // -- Column storage case ------------------------------------------------------ // #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, arch, suf ) \ \ void PASTEMAC3(ch,opname,arch,suf) \ ( \ conj_t conja, \ conj_t conjb, \ dim_t m, \ dim_t n, \ dim_t k, \ ctype* restrict alpha, \ ctype* restrict a, inc_t rs_a, inc_t cs_a, \ ctype* restrict b, inc_t rs_b, inc_t cs_b, \ ctype* restrict beta, \ ctype* restrict c, inc_t rs_c, inc_t cs_c, \ auxinfo_t* restrict data, \ cntx_t* restrict cntx \ ) \ { \ /* NOTE: This microkernel can actually handle arbitrarily large values of m, n, and k. */ \ \ if ( bli_is_noconj( conja ) && bli_is_noconj( conjb ) ) \ { \ /* Traverse c by columns. */ \ for ( dim_t j = 0; j < n; ++j ) \ { \ ctype* restrict cj = &c[ j*cs_c ]; \ ctype* restrict bj = &b[ j*cs_b ]; \ \ for ( dim_t i = 0; i < m; ++i ) \ { \ ctype* restrict cij = &cj[ i*rs_c ]; \ ctype* restrict ai = &a [ i*rs_a ]; \ ctype ab; \ \ PASTEMAC(ch,set0s)( ab ); \ \ /* Perform a dot product to update the (i,j) element of c. */ \ for ( dim_t l = 0; l < k; ++l ) \ { \ ctype* restrict aij = &ai[ l*cs_a ]; \ ctype* restrict bij = &bj[ l*rs_b ]; \ \ PASTEMAC(ch,dots)( *aij, *bij, ab ); \ } \ \ /* If beta is one, add ab into c. If beta is zero, overwrite c with the result in ab. Otherwise, scale by beta and accumulate ab to c. */ \ if ( PASTEMAC(ch,eq1)( *beta ) ) \ { \ PASTEMAC(ch,axpys)( *alpha, ab, *cij ); \ } \ else if ( PASTEMAC(ch,eq0)( *beta ) ) \ { \ PASTEMAC(ch,scal2s)( *alpha, ab, *cij ); \ } \ else \ { \ PASTEMAC(ch,axpbys)( *alpha, ab, *beta, *cij ); \ } \ } \ } \ } \ else if ( bli_is_noconj( conja ) && bli_is_conj( conjb ) ) \ { \ /* Traverse c by columns. */ \ for ( dim_t j = 0; j < n; ++j ) \ { \ ctype* restrict cj = &c[ j*cs_c ]; \ ctype* restrict bj = &b[ j*cs_b ]; \ \ for ( dim_t i = 0; i < m; ++i ) \ { \ ctype* restrict cij = &cj[ i*rs_c ]; \ ctype* restrict ai = &a [ i*rs_a ]; \ ctype ab; \ \ PASTEMAC(ch,set0s)( ab ); \ \ /* Perform a dot product to update the (i,j) element of c. */ \ for ( dim_t l = 0; l < k; ++l ) \ { \ ctype* restrict aij = &ai[ l*cs_a ]; \ ctype* restrict bij = &bj[ l*rs_b ]; \ \ PASTEMAC(ch,axpyjs)( *aij, *bij, ab ); \ } \ \ /* If beta is one, add ab into c. If beta is zero, overwrite c with the result in ab. Otherwise, scale by beta and accumulate ab to c. */ \ if ( PASTEMAC(ch,eq1)( *beta ) ) \ { \ PASTEMAC(ch,axpys)( *alpha, ab, *cij ); \ } \ else if ( PASTEMAC(ch,eq0)( *beta ) ) \ { \ PASTEMAC(ch,scal2s)( *alpha, ab, *cij ); \ } \ else \ { \ PASTEMAC(ch,axpbys)( *alpha, ab, *beta, *cij ); \ } \ } \ } \ } \ else if ( bli_is_conj( conja ) && bli_is_noconj( conjb ) ) \ { \ /* Traverse c by columns. */ \ for ( dim_t j = 0; j < n; ++j ) \ { \ ctype* restrict cj = &c[ j*cs_c ]; \ ctype* restrict bj = &b[ j*cs_b ]; \ \ for ( dim_t i = 0; i < m; ++i ) \ { \ ctype* restrict cij = &cj[ i*rs_c ]; \ ctype* restrict ai = &a [ i*rs_a ]; \ ctype ab; \ \ PASTEMAC(ch,set0s)( ab ); \ \ /* Perform a dot product to update the (i,j) element of c. */ \ for ( dim_t l = 0; l < k; ++l ) \ { \ ctype* restrict aij = &ai[ l*cs_a ]; \ ctype* restrict bij = &bj[ l*rs_b ]; \ \ PASTEMAC(ch,dotjs)( *aij, *bij, ab ); \ } \ \ /* If beta is one, add ab into c. If beta is zero, overwrite c with the result in ab. Otherwise, scale by beta and accumulate ab to c. */ \ if ( PASTEMAC(ch,eq1)( *beta ) ) \ { \ PASTEMAC(ch,axpys)( *alpha, ab, *cij ); \ } \ else if ( PASTEMAC(ch,eq0)( *beta ) ) \ { \ PASTEMAC(ch,scal2s)( *alpha, ab, *cij ); \ } \ else \ { \ PASTEMAC(ch,axpbys)( *alpha, ab, *beta, *cij ); \ } \ } \ } \ } \ else /* if ( bli_is_conj( conja ) && bli_is_conj( conjb ) ) */ \ { \ /* Traverse c by columns. */ \ for ( dim_t j = 0; j < n; ++j ) \ { \ ctype* restrict cj = &c[ j*cs_c ]; \ ctype* restrict bj = &b[ j*cs_b ]; \ \ for ( dim_t i = 0; i < m; ++i ) \ { \ ctype* restrict cij = &cj[ i*rs_c ]; \ ctype* restrict ai = &a [ i*rs_a ]; \ ctype ab; \ \ PASTEMAC(ch,set0s)( ab ); \ \ /* Perform a dot product to update the (i,j) element of c. */ \ for ( dim_t l = 0; l < k; ++l ) \ { \ ctype* restrict aij = &ai[ l*cs_a ]; \ ctype* restrict bij = &bj[ l*rs_b ]; \ \ PASTEMAC(ch,dots)( *aij, *bij, ab ); \ } \ \ /* Conjugate the result to simulate conj(a^T) * conj(b). */ \ PASTEMAC(ch,conjs)( ab ); \ \ /* If beta is one, add ab into c. If beta is zero, overwrite c with the result in ab. Otherwise, scale by beta and accumulate ab to c. */ \ if ( PASTEMAC(ch,eq1)( *beta ) ) \ { \ PASTEMAC(ch,axpys)( *alpha, ab, *cij ); \ } \ else if ( PASTEMAC(ch,eq0)( *beta ) ) \ { \ PASTEMAC(ch,scal2s)( *alpha, ab, *cij ); \ } \ else \ { \ PASTEMAC(ch,axpbys)( *alpha, ab, *beta, *cij ); \ } \ } \ } \ } \ } INSERT_GENTFUNC_BASIC2( gemmsup_c, _armsve, _ref2 ) blis-0.9.0/kernels/armsve/3/old/sup/bli_gemmsup_cv_armsve_asm_d2vx10_unindexed.c000066400000000000000000000624301422157504600276760ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2020, The University of Tokyo 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include // Double-precision composite instructions. #include "../armsve_asm_macros_double.h" // 2vx10 microkernels. #include "../armsve_asm_2vx10.h" // Prototype reference kernel. GEMMSUP_KER_PROT( double, d, gemmsup_c_armsve_ref2 ) void __attribute__ ((noinline,optimize(0))) bli_dgemmsup_cv_armsve_2vx10_unindexed ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { static int called = 0; if ( !called ) { fprintf(stderr, "rv called.\n"); called = 1; } // c*c requires A to be stored in columns. assert( rs_a0 == 1 ); dim_t n0_mker = n0 / 10; dim_t n0_left = n0 % 10; if ( n0_left ) { // A[:, ::] // B[::, n0_mker*10:n0] // C[: , n0_mker*10:n0] double *ai = a; double *bi = b + n0_mker * 10 * cs_b0; double *ci = c + n0_mker * 10 * cs_c0; bli_dgemmsup_c_armsve_ref2 ( conja, conjb, m0, n0_left, k0, alpha, ai, rs_a0, cs_a0, bi, rs_b0, cs_b0, beta, ci, rs_c0, cs_c0, data, cntx ); } // Return if it's a pure edge case. if ( !n0_mker ) return; // Determine VL. uint64_t vlen2; __asm__ ( " mov x0, xzr \n\t" " incd x0, ALL, MUL #2 \n\t" " mov %[vlen2], x0 \n\t" : [vlen2] "=r" (vlen2) : : "x0" ); uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // uint64_t rs_a = 1; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t k_mker = k0 / 4; uint64_t k_left = k0 % 4; uint64_t n_mker = n0_mker; dim_t m0_mker = m0 / vlen2; dim_t m0_left = m0 % vlen2; if ( m0_left ) { // Edge case on A side can be handled with one more (predicated) loop. m0_mker++; } else m0_left = vlen2; // uint64_t ps_a = bli_auxinfo_ps_a( data ); uint64_t ps_b = bli_auxinfo_ps_b( data ); for ( dim_t im0_mker = 0; im0_mker < m0_mker; ++im0_mker ) { uint64_t m_curr = vlen2; if ( im0_mker == m0_mker - 1 ) { // Last m-loop. Maybe unnecessary. m_curr = m0_left; } double *ai = a + im0_mker * vlen2 * rs_a0; double *bi = b; double *ci = c + im0_mker * vlen2 * rs_c0; void* a_next = bli_auxinfo_next_a( data ); void* b_next = bli_auxinfo_next_b( data ); __asm__ volatile ( " ldr x0, %[bi] \n\t" " ldr x1, %[rs_b] \n\t" // Row-skip of B. " ldr x2, %[cs_b] \n\t" // Column-skip of B (element skip of B[l, :]). " ldr x3, %[ps_b] \n\t" // Panel-skip (10*k) of B. " ldr x4, %[cs_a] \n\t" // Column-Skip of A. " \n\t" // Element skip of A[:, l] is guaranteed to be 1. " ldr x5, %[ci] \n\t" " ldr x6, %[rs_c] \n\t" // Row-skip of C. " ldr x7, %[cs_c] \n\t" // Column-skip of C. #ifdef _A64FX " mov x16, 0x1 \n\t" // Tag C address. " lsl x16, x16, #56 \n\t" " orr x5, x5, x16 \n\t" " mov x16, 0x2 \n\t" // Tag B address. " lsl x16, x16, #56 \n\t" " orr x0, x0, x16 \n\t" #endif " \n\t" " mov x8, #8 \n\t" // Multiply some address skips by sizeof(double). " madd x1, x8, x1, xzr \n\t" // rs_b " madd x2, x8, x2, xzr \n\t" // cs_b " madd x3, x8, x3, xzr \n\t" // ps_b " madd x4, x8, x4, xzr \n\t" // cs_a " madd x7, x8, x7, xzr \n\t" // cs_c " mov x8, #4 \n\t" " madd x15, x8, x4, xzr \n\t" // Logical K=4 microkernel skip for A. " \n\t" #ifdef _A64FX " mov x16, 0x20 \n\t" // Higher 6bit for Control#2: " lsl x16, x16, #58 \n\t" // Valid|Strong|Strong|NoAlloc|Load|Strong " orr x16, x16, x4 \n\t" // Stride. " msr S3_3_C11_C6_2, x16 \n\t" // Write system register. #endif " \n\t" " ldr x8, %[m_curr] \n\t" // Size of first dimension. " mov x9, xzr \n\t" " incd x9 \n\t" " ptrue p0.d \n\t" " whilelo p1.d, xzr, x8 \n\t" " whilelo p2.d, x9, x8 \n\t" " \n\t" " ldr x8, %[n_mker] \n\t" // Number of N-loops. " \n\t" " ldr x20, %[ai] \n\t" // Parameters to be reloaded " ldr x21, %[k_mker] \n\t" // within each millikernel loop. " ldr x22, %[k_left] \n\t" " ldr x23, %[alpha] \n\t" " ldr x24, %[beta] \n\t" " ldr x25, %[a_next] \n\t" " ldr x26, %[b_next] \n\t" " ldr x23, [x23] \n\t" // Directly load alpha and beta. " ldr x24, [x24] \n\t" " \n\t" " MILLIKER_MLOOP: \n\t" " \n\t" " mov x11, x0 \n\t" // B's address. // " ldr x10, %[ai] \n\t" // A's address. " mov x10, x20 \n\t" // " ldr x12, %[k_mker] \n\t" " mov x12, x21 \n\t" // " ldr x13, %[k_left] \n\t" " mov x13, x22 \n\t" #ifdef _A64FX " mov x16, 0x3 \n\t" // Tag A address. " lsl x16, x16, #56 \n\t" " orr x10, x10, x16 \n\t" " mov x16, 0xa \n\t" // Control#2 for A address. " lsl x16, x16, #60 \n\t" " orr x10, x10, x16 \n\t" #endif " \n\t" " cmp x12, #0 \n\t" // Don't preload if no microkernel there. " b.eq END_CCOL_PRFM \n\t" " \n\t" " mov x14, x11 \n\t" " ld1rd z20.d, p0/z, [x14] \n\t" // Load 8/10 of first B row. " add x14, x14, x2 \n\t" " ld1rd z21.d, p0/z, [x14] \n\t" " add x14, x14, x2 \n\t" " ld1rd z22.d, p0/z, [x14] \n\t" " add x14, x14, x2 \n\t" " ld1rd z23.d, p0/z, [x14] \n\t" " add x14, x14, x2 \n\t" " ld1rd z24.d, p0/z, [x14] \n\t" " add x14, x14, x2 \n\t" " ld1rd z25.d, p0/z, [x14] \n\t" " add x14, x14, x2 \n\t" " ld1rd z26.d, p0/z, [x14] \n\t" " add x14, x14, x2 \n\t" " ld1rd z27.d, p0/z, [x14] \n\t" " add x14, x14, x2 \n\t" " prfm PLDL1KEEP, [x14] \n\t" // And prefetch the 2/10 left. " add x14, x14, x2 \n\t" " prfm PLDL1KEEP, [x14] \n\t" " sub x14, x14, x2 \n\t" // Restore x14 to load edge. " \n\t" GEMM_ACOL_CONTIGUOUS_LOAD(z28,z29,p1,p2,x10) " add x16, x10, x4 \n\t" " prfm PLDL1STRM, [x16] \n\t" // Prefetch 3/4 of A. " add x16, x10, x4 \n\t" " prfm PLDL1STRM, [x16] \n\t" " add x16, x10, x4 \n\t" " prfm PLDL1STRM, [x16] \n\t" " \n\t" " CCOL_PRFM: \n\t" " cmp x6, #1 \n\t" " b.ne END_CCOL_PRFM \n\t" // Do not prefetch for generic C storage. " mov x16, x5 \n\t" " prfm PLDL1STRM, [x16] \n\t" " add x16, x16, x7 \n\t" " prfm PLDL1STRM, [x16] \n\t" " add x16, x16, x7 \n\t" " prfm PLDL1STRM, [x16] \n\t" " add x16, x16, x7 \n\t" " prfm PLDL1STRM, [x16] \n\t" " add x16, x16, x7 \n\t" " prfm PLDL1STRM, [x16] \n\t" " add x16, x16, x7 \n\t" " prfm PLDL1STRM, [x16] \n\t" " add x16, x16, x7 \n\t" " prfm PLDL1STRM, [x16] \n\t" " add x16, x16, x7 \n\t" " prfm PLDL1STRM, [x16] \n\t" " add x16, x16, x7 \n\t" " prfm PLDL1STRM, [x16] \n\t" " add x16, x16, x7 \n\t" " prfm PLDL1STRM, [x16] \n\t" " END_CCOL_PRFM: \n\t" " \n\t" CLEAR_COL20(z0,z1,z2,z3,z4,z5,z6,z7,z8,z9,z10,z11,z12,z13,z14,z15,z16,z17,z18,z19) " \n\t" " cmp x12, #0 \n\t" // If no 4-microkernel can be applied " b.eq K_LEFT_LOOP \n\t" " \n\t" " K_MKER_LOOP: \n\t" " \n\t" GEMMSUP_ACOL_PREFETCH_NEXT_LOAD_C(z30,z31,p1,p2,x10,x15,x4,x16,noprfm) GEMM_2VX10_MKER_LOOP_PLAIN_G_1(z0,z2,z4,z6,z8,z10,z12,z14,z16,z18,z1,z3,z5,z7,z9,z11,z13,z15,z17,z19,p0,z28,z29,z20,z21,z22,z23,z24,z25,z26,z27,x11,x14,x1,x2) " \n\t" GEMMSUP_ACOL_PREFETCH_NEXT_LOAD_C(z28,z29,p1,p2,x10,x15,x4,x16,noprfm) GEMM_2VX10_MKER_LOOP_PLAIN_G_2(z0,z2,z4,z6,z8,z10,z12,z14,z16,z18,z1,z3,z5,z7,z9,z11,z13,z15,z17,z19,p0,z30,z31,z20,z21,z22,z23,z24,z25,z26,z27,x11,x14,x1,x2) " \n\t" GEMMSUP_ACOL_PREFETCH_NEXT_LOAD_C(z30,z31,p1,p2,x10,x15,x4,x16,noprfm) GEMM_2VX10_MKER_LOOP_PLAIN_G_3(z0,z2,z4,z6,z8,z10,z12,z14,z16,z18,z1,z3,z5,z7,z9,z11,z13,z15,z17,z19,p0,z28,z29,z20,z21,z22,z23,z24,z25,z26,z27,x11,x14,x1,x2) " \n\t" " subs x12, x12, #1 \n\t" // Decrease counter before final replica. " b.eq FIN_MKER_LOOP \n\t" // Branch early to avoid reading excess mem. " \n\t" GEMMSUP_ACOL_PREFETCH_NEXT_LOAD_C(z28,z29,p1,p2,x10,x15,x4,x16,noprfm) GEMM_2VX10_MKER_LOOP_PLAIN_G_4(z0,z2,z4,z6,z8,z10,z12,z14,z16,z18,z1,z3,z5,z7,z9,z11,z13,z15,z17,z19,p0,z30,z31,z20,z21,z22,z23,z24,z25,z26,z27,x11,x14,x1,x2) " b K_MKER_LOOP \n\t" " \n\t" " FIN_MKER_LOOP: \n\t" GEMM_2VX10_MKER_LOOP_PLAIN_G_4_RESIDUAL(z0,z2,z4,z6,z8,z10,z12,z14,z16,z18,z1,z3,z5,z7,z9,z11,z13,z15,z17,z19,p0,z30,z31,z20,z21,z22,z23,z24,z25,z26,z27,x11,x14,x1,x2) " add x10, x10, x4 \n\t" // Forward A to fill the blank. " \n\t" " K_LEFT_LOOP: \n\t" " cmp x13, #0 \n\t" // End of execution. " b.eq WRITE_MEM_PREP \n\t" " \n\t" GEMM_ACOL_CONTIGUOUS_LOAD(z30,z31,p1,p2,x10) " mov x14, x11 \n\t" " ld1rd z20.d, p0/z, [x14] \n\t" // Load 10/10 B. " add x14, x14, x2 \n\t" " ld1rd z21.d, p0/z, [x14] \n\t" " add x14, x14, x2 \n\t" " ld1rd z22.d, p0/z, [x14] \n\t" " add x14, x14, x2 \n\t" " ld1rd z23.d, p0/z, [x14] \n\t" " add x14, x14, x2 \n\t" " ld1rd z24.d, p0/z, [x14] \n\t" " add x14, x14, x2 \n\t" " ld1rd z25.d, p0/z, [x14] \n\t" " add x14, x14, x2 \n\t" " ld1rd z26.d, p0/z, [x14] \n\t" " add x14, x14, x2 \n\t" " ld1rd z27.d, p0/z, [x14] \n\t" " add x14, x14, x2 \n\t" " ld1rd z28.d, p0/z, [x14] \n\t" " add x14, x14, x2 \n\t" " ld1rd z29.d, p0/z, [x14] \n\t" GEMM_FMLA2(z0,z1,p0,z30,z31,z20) GEMM_FMLA2(z2,z3,p0,z30,z31,z21) GEMM_FMLA2(z4,z5,p0,z30,z31,z22) GEMM_FMLA2(z6,z7,p0,z30,z31,z23) GEMM_FMLA2(z8,z9,p0,z30,z31,z24) GEMM_FMLA2(z10,z11,p0,z30,z31,z25) GEMM_FMLA2(z12,z13,p0,z30,z31,z26) GEMM_FMLA2(z14,z15,p0,z30,z31,z27) GEMM_FMLA2(z16,z17,p0,z30,z31,z28) GEMM_FMLA2(z18,z19,p0,z30,z31,z29) " add x10, x10, x4 \n\t" // Forward A. " add x11, x11, x1 \n\t" // Forward B. " sub x13, x13, #1 \n\t" " b K_LEFT_LOOP \n\t" // Next column / row. " \n\t" " WRITE_MEM_PREP: \n\t" " \n\t" // " ldr x10, %[ai] \n\t" " mov x10, x20 \n\t" " add x11, x0, x3 \n\t" " dup z30.d, x23 \n\t" // Broadcast alpha & beta into vectors. " dup z31.d, x24 \n\t" " \n\t" " cmp x8, #1 \n\t" " b.eq PREFETCH_ABNEXT \n\t" " prfm PLDL1STRM, [x10] \n\t" " prfm PLDL1KEEP, [x11] \n\t" " add x11, x11, x2 \n\t" " prfm PLDL1KEEP, [x11] \n\t" " add x11, x11, x2 \n\t" " prfm PLDL1KEEP, [x11] \n\t" " add x11, x11, x2 \n\t" " prfm PLDL1KEEP, [x11] \n\t" " add x11, x11, x2 \n\t" " prfm PLDL1KEEP, [x11] \n\t" " add x11, x11, x2 \n\t" " prfm PLDL1KEEP, [x11] \n\t" " add x11, x11, x2 \n\t" " prfm PLDL1KEEP, [x11] \n\t" " add x11, x11, x2 \n\t" " prfm PLDL1KEEP, [x11] \n\t" " add x11, x11, x2 \n\t" " prfm PLDL1KEEP, [x11] \n\t" " add x11, x11, x2 \n\t" " prfm PLDL1KEEP, [x11] \n\t" " b WRITE_MEM \n\t" " \n\t" " PREFETCH_ABNEXT: \n\t" // " ldr x1, %[a_next] \n\t" // Final Millikernel loop, x1 and x2 not needed. " mov x1, x25 \n\t" // " ldr x2, %[b_next] \n\t" " mov x2, x26 \n\t" " prfm PLDL2KEEP, [x1] \n\t" " prfm PLDL2KEEP, [x1, 256*1] \n\t" " prfm PLDL2KEEP, [x1, 256*2] \n\t" " prfm PLDL2KEEP, [x1, 256*3] \n\t" " prfm PLDL2KEEP, [x1, 256*4] \n\t" " prfm PLDL2KEEP, [x1, 256*5] \n\t" " prfm PLDL2KEEP, [x1, 256*6] \n\t" " prfm PLDL2KEEP, [x1, 256*7] \n\t" " prfm PLDL2KEEP, [x1, 256*8] \n\t" " prfm PLDL2KEEP, [x1, 256*9] \n\t" " prfm PLDL2KEEP, [x1, 256*10] \n\t" " prfm PLDL2KEEP, [x1, 256*11] \n\t" " prfm PLDL2KEEP, [x1, 256*12] \n\t" " prfm PLDL2KEEP, [x1, 256*13] \n\t" " prfm PLDL2KEEP, [x1, 256*14] \n\t" " prfm PLDL2KEEP, [x1, 256*15] \n\t" " prfm PLDL2KEEP, [x2] \n\t" " prfm PLDL2KEEP, [x2, 256*1] \n\t" " prfm PLDL2KEEP, [x2, 256*2] \n\t" " prfm PLDL2KEEP, [x2, 256*3] \n\t" " prfm PLDL2KEEP, [x2, 256*4] \n\t" " prfm PLDL2KEEP, [x2, 256*5] \n\t" " prfm PLDL2KEEP, [x2, 256*6] \n\t" " prfm PLDL2KEEP, [x2, 256*7] \n\t" " prfm PLDL2KEEP, [x2, 256*8] \n\t" " prfm PLDL2KEEP, [x2, 256*9] \n\t" " \n\t" " WRITE_MEM: \n\t" " \n\t" " fmov d28, #1.0 \n\t" " fmov x16, d28 \n\t" " cmp x16, x23 \n\t" " b.eq UNIT_ALPHA \n\t" " \n\t" SCALE_COL20(z0,z1,z2,z3,z4,z5,z6,z7,z8,z9,z10,z11,z12,z13,z14,z15,z16,z17,z18,z19,z30) " \n\t" " UNIT_ALPHA: \n\t" " mov x9, x5 \n\t" // C address for loading. " \n\t" // C address for storing is x5 itself. " cmp x6, #1 \n\t" " b.ne WRITE_MEM_G \n\t" " \n\t" " WRITE_MEM_C: \n\t" // Available scratch: Z[20-30]. " \n\t" // Here used scratch: Z[20-29]. " mov x13, xzr \n\t" // C-column's physical 1-vector skip. " incb x13 \n\t" GEMM_C_LOAD_UKER_C(z20,z22,z24,z26,z28,z21,z23,z25,z27,z29,p1,p2,x9,x7) GEMM_C_FMAD_UKER(z20,z22,z24,z26,z28,z21,z23,z25,z27,z29,p1,p2,z0,z2,z4,z6,z8,z1,z3,z5,z7,z9,z31) GEMM_C_LOAD_UKER_C(z0,z2,z4,z6,z8,z1,z3,z5,z7,z9,p1,p2,x9,x7) " \n\t" GEMM_C_STORE_UKER_C(z20,z22,z24,z26,z28,z21,z23,z25,z27,z29,p1,p2,x5,x7) GEMM_C_FMAD_UKER(z0,z2,z4,z6,z8,z1,z3,z5,z7,z9,p1,p2,z10,z12,z14,z16,z18,z11,z13,z15,z17,z19,z31) GEMM_C_STORE_UKER_C(z0,z2,z4,z6,z8,z1,z3,z5,z7,z9,p1,p2,x5,x7) " b END_WRITE_MEM \n\t" " \n\t" " WRITE_MEM_G: \n\t" // Available scratch: Z[20-30]. " \n\t" // Here used scratch: Z[20-30] - Z30 as index. " mov x12, xzr \n\t" " incb x12 \n\t" " madd x13, x12, x6, xzr \n\t" // C-column's logical 1-vector skip. " index z30.d, xzr, x6 \n\t" // Skips passed to index is not multiplied by 8. GEMM_C_LOAD_UKER_G(z20,z22,z24,z26,z28,z21,z23,z25,z27,z29,z30,p1,p2,x9,x7,x13,x16) GEMM_C_FMAD_UKER(z20,z22,z24,z26,z28,z21,z23,z25,z27,z29,p1,p2,z0,z2,z4,z6,z8,z1,z3,z5,z7,z9,z31) GEMM_C_LOAD_UKER_G(z0,z2,z4,z6,z8,z1,z3,z5,z7,z9,z30,p1,p2,x9,x7,x13,x16) " \n\t" GEMM_C_STORE_UKER_G(z20,z22,z24,z26,z28,z21,z23,z25,z27,z29,z30,p1,p2,x5,x7,x13,x16) GEMM_C_FMAD_UKER(z0,z2,z4,z6,z8,z1,z3,z5,z7,z9,p1,p2,z10,z12,z14,z16,z18,z11,z13,z15,z17,z19,z31) GEMM_C_STORE_UKER_G(z0,z2,z4,z6,z8,z1,z3,z5,z7,z9,z30,p1,p2,x5,x7,x13,x16) " \n\t" " END_WRITE_MEM: \n\t" " subs x8, x8, #1 \n\t" " b.eq END_EXEC \n\t" " \n\t" // Address of C already forwarded to next column. " add x0, x0, x3 \n\t" // Forward B's base address to the next logic panel. " b MILLIKER_MLOOP \n\t" " \n\t" " END_ERROR: \n\t" " mov x0, #1 \n\t" // Return error. " END_EXEC: \n\t" " mov x0, #0 \n\t" // Return normal. : : [bi] "m" (bi), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [ps_b] "m" (ps_b), [cs_a] "m" (cs_a), [ci] "m" (ci), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c), [m_curr] "m" (m_curr), [n_mker] "m" (n_mker), [ai] "m" (ai), [k_mker] "m" (k_mker), [k_left] "m" (k_left), [alpha] "m" (alpha), [beta] "m" (beta), [a_next] "m" (a_next), [b_next] "m" (b_next) : "x0","x1","x2","x3","x4","x5","x6","x7","x8", "x9","x10","x11","x12","x13","x14","x15","x16","x17", "x20","x21","x22","x23","x24","x25","x26", "z0","z1","z2","z3","z4","z5","z6","z7", "z8","z9","z10","z11","z12","z13","z14","z15", "z16","z17","z18","z19", "z20","z21","z22","z23", "z24","z25","z26","z27", "z28","z29","z30","z31" ); } } void bli_dgemmsup_rv_armsve_10x2v_unindexed ( conj_t conjat, conj_t conjbt, dim_t m0t, dim_t n0t, dim_t k0, double* restrict alpha, double* restrict at, inc_t rs_at0, inc_t cs_at0, double* restrict bt, inc_t rs_bt0, inc_t cs_bt0, double* restrict beta, double* restrict ct, inc_t rs_ct0, inc_t cs_ct0, auxinfo_t* restrict datat, cntx_t* restrict cntx ) { auxinfo_t data; bli_auxinfo_set_next_a( bli_auxinfo_next_b( datat ), &data ); bli_auxinfo_set_next_b( bli_auxinfo_next_a( datat ), &data ); bli_auxinfo_set_ps_a( bli_auxinfo_ps_b( datat ), &data ); bli_auxinfo_set_ps_b( bli_auxinfo_ps_a( datat ), &data ); bli_dgemmsup_cv_armsve_2vx10_unindexed ( conjbt, conjat, n0t, m0t, k0, alpha, bt, cs_bt0, rs_bt0, at, cs_at0, rs_at0, beta, ct, cs_ct0, rs_ct0, &data, cntx ); } blis-0.9.0/kernels/armsve/3/old/sup/bli_gemmsup_rv_armsve_asm_d2vx10_unindexed.c000066400000000000000000000500221422157504600277070ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2020, The University of Tokyo 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include // Double-precision composite instructions. #include "../armsve_asm_macros_double.h" // 2vx10 microkernels. #include "../armsve_asm_2vx10.h" // Prototype reference kernel. GEMMSUP_KER_PROT( double, d, gemmsup_r_armsve_ref2 ) void __attribute__ ((optimize(0))) bli_dgemmsup_rv_armsve_2vx10_unindexed ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { static int called = 0; if ( !called ) { fprintf(stderr, "rv called.\n"); called = 1; } // r*r requires B to be stored in rows. assert(cs_b0 == 1); dim_t n0_mker = n0 / 10; dim_t n0_left = n0 % 10; if ( n0_left ) { // A[:, ::] // B[::, n0_mker*10:n0] // C[: , n0_mker*10:n0] double *ai = a; double *bi = b + n0_mker * 10 * cs_b0; double *ci = c + n0_mker * 10 * cs_c0; bli_dgemmsup_r_armsve_ref2 ( conja, conjb, m0, n0_left, k0, alpha, ai, rs_a0, cs_a0, bi, rs_b0, cs_b0, beta, ci, rs_c0, cs_c0, data, cntx ); } // Return if it's a pure edge case. if ( !n0_mker ) return; // Determine VL. uint64_t vlen2; __asm__ ( " mov x0, xzr \n\t" " incd x0, ALL, MUL #2 \n\t" " mov %[vlen2], x0 \n\t" : [vlen2] "=r" (vlen2) : : "x0" ); uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; // uint64_t cs_b = 1; uint64_t k_mker = k0 / 4; uint64_t k_left = k0 % 4; uint64_t m_mker = m0 / vlen2; uint64_t m_left = m0 % vlen2; if ( m_left ) { // Edge case on A side can be handled with one more (predicated) loop. m_mker++; } else m_left = vlen2; uint64_t ps_a = bli_auxinfo_ps_a( data ); // uint64_t ps_b = bli_auxinfo_ps_b( data ); for ( dim_t in0_mker = 0; in0_mker < n0_mker; ++in0_mker ) { double *ai = a; double *bi = b + in0_mker * 10 * cs_b0; double *ci = c + in0_mker * 10 * cs_c0; void* a_next = bli_auxinfo_next_a( data ); void* b_next = bli_auxinfo_next_b( data ); __asm__ volatile ( " ldr x0, %[ai] \n\t" " ldr x1, %[rs_a] \n\t" // Row-skip of A (element skip of A[:, l]). " ldr x2, %[cs_a] \n\t" // Column-skip of A. " ldr x3, %[ps_a] \n\t" // Panel-skip (vlen2*k) of A. " ldr x4, %[rs_b] \n\t" // Row-Skip of B. " \n\t" // Element skip of B[l, :] is guaranteed to be 1. " ldr x5, %[ci] \n\t" " ldr x6, %[rs_c] \n\t" // Row-skip of C. " ldr x7, %[cs_c] \n\t" // Column-skip of C. #ifdef _A64FX " mov x16, 0x1 \n\t" // Tag C address. " lsl x16, x16, #56 \n\t" " orr x5, x5, x16 \n\t" " mov x16, 0x2 \n\t" // Tag A address. " lsl x16, x16, #56 \n\t" " orr x0, x0, x16 \n\t" #endif " \n\t" " mov x8, #8 \n\t" // Multiply some address skips by sizeof(double). " madd x2, x8, x2, xzr \n\t" // cs_a " madd x3, x8, x3, xzr \n\t" // ps_a " madd x4, x8, x4, xzr \n\t" // rs_b " madd x7, x8, x7, xzr \n\t" // cs_c " mov x8, xzr \n\t" " incb x8 \n\t" " madd x14, x8, x1, xzr \n\t" // A-column's logical 1-vector skip. " mov x8, #4 \n\t" " madd x15, x8, x2, xzr \n\t" // Logical K=4 microkernel skip for A. // " mov x8, #4 \n\t" // " madd x17, x8, x4, xzr \n\t" // Logical K=4 microkernel skip for B. " \n\t" " ldr x8, %[m_mker] \n\t" // Number of M-loops. " ptrue p0.d \n\t" " ptrue p1.d \n\t" " ptrue p2.d \n\t" " \n\t" " MILLIKER_MLOOP: \n\t" " \n\t" " cmp x8, #1 \n\t" " b.ne UKER_BEGIN \n\t" " \n\t" " ldr x10, %[m_left] \n\t" // Final (incomplete) millikernel loop. " mov x11, xzr \n\t" " incd x11 \n\t" " whilelo p1.d, xzr, x10 \n\t" // Overwrite p1/p2. " whilelo p2.d, x11, x10 \n\t" " \n\t" " UKER_BEGIN: \n\t" " mov x10, x0 \n\t" // A's address. " ldr x11, %[bi] \n\t" // B's address. " ldr x12, %[k_mker] \n\t" " ldr x13, %[k_left] \n\t" #ifdef _A64FX " mov x16, 0x3 \n\t" // Tag B address. " lsl x16, x16, #56 \n\t" " orr x11, x11, x16 \n\t" #endif " \n\t" " mov x16, x11 \n\t" // Prefetch first kernel of B. " prfm PLDL1KEEP, [x16] \n\t" " add x16, x16, x4 \n\t" " prfm PLDL1KEEP, [x16] \n\t" " add x16, x16, x4 \n\t" " prfm PLDL1KEEP, [x16] \n\t" " add x16, x16, x4 \n\t" " prfm PLDL1KEEP, [x16] \n\t" " \n\t" " ld1rd z20.d, p0/z, [x11] \n\t" // (Partial) first B row. " ld1rd z21.d, p0/z, [x11, #8] \n\t" " ld1rd z22.d, p0/z, [x11, #16] \n\t" " ld1rd z23.d, p0/z, [x11, #24] \n\t" " ld1rd z24.d, p0/z, [x11, #32] \n\t" " ld1rd z25.d, p0/z, [x11, #40] \n\t" " ld1rd z26.d, p0/z, [x11, #48] \n\t" " ld1rd z27.d, p0/z, [x11, #56] \n\t" " \n\t" " index z29.d, xzr, x1 \n\t" // First A column. " \n\t" // Skips passed to index is not multiplied by 8. GEMM_ACOL_GATHER_LOAD(z28,z29,z29,p1,p2,x10,x14,x16) " \n\t" CLEAR_COL20(z0,z1,z2,z3,z4,z5,z6,z7,z8,z9,z10,z11,z12,z13,z14,z15,z16,z17,z18,z19) " \n\t" " cmp x12, #0 \n\t" // If no 4-microkernel can be applied " b.eq K_LEFT_LOOP \n\t" " \n\t" " K_MKER_LOOP: \n\t" // Unroll the 4-loop. " \n\t" " index z31.d, xzr, x1 \n\t" GEMMSUP_ACOL_PREFETCH_NEXT_LOAD_G(z30,z31,z31,p1,p2,x10,x15,x3,x2,x14,x16,noprfm,noprfm) GEMM_2VX10_MKER_LOOP_PLAIN_C_1(z0,z2,z4,z6,z8,z10,z12,z14,z16,z18,z1,z3,z5,z7,z9,z11,z13,z15,z17,z19,p0,z28,z29,z20,z21,z22,z23,z24,z25,z26,z27,x11,x4) " \n\t" " index z29.d, xzr, x1 \n\t" GEMMSUP_ACOL_PREFETCH_NEXT_LOAD_G(z28,z29,z29,p1,p2,x10,x15,x3,x2,x14,x16,noprfm,noprfm) GEMM_2VX10_MKER_LOOP_PLAIN_C_2(z0,z2,z4,z6,z8,z10,z12,z14,z16,z18,z1,z3,z5,z7,z9,z11,z13,z15,z17,z19,p0,z30,z31,z20,z21,z22,z23,z24,z25,z26,z27,x11,x4) " \n\t" " index z31.d, xzr, x1 \n\t" GEMMSUP_ACOL_PREFETCH_NEXT_LOAD_G(z30,z31,z31,p1,p2,x10,x15,x3,x2,x14,x16,noprfm,noprfm) GEMM_2VX10_MKER_LOOP_PLAIN_C_3(z0,z2,z4,z6,z8,z10,z12,z14,z16,z18,z1,z3,z5,z7,z9,z11,z13,z15,z17,z19,p0,z28,z29,z20,z21,z22,z23,z24,z25,z26,z27,x11,x4) " \n\t" " subs x12, x12, #1 \n\t" // Decrease counter before final replica. " b.eq FIN_MKER_LOOP \n\t" // Branch early to avoid reading excess mem. " \n\t" " index z29.d, xzr, x1 \n\t" GEMMSUP_ACOL_PREFETCH_NEXT_LOAD_G(z28,z29,z29,p1,p2,x10,x15,x3,x2,x14,x16,noprfm,noprfm) GEMM_2VX10_MKER_LOOP_PLAIN_C_4(z0,z2,z4,z6,z8,z10,z12,z14,z16,z18,z1,z3,z5,z7,z9,z11,z13,z15,z17,z19,p0,z30,z31,z20,z21,z22,z23,z24,z25,z26,z27,x11,x4) " b K_MKER_LOOP \n\t" " \n\t" " FIN_MKER_LOOP: \n\t" GEMM_2VX10_MKER_LOOP_PLAIN_C_4_RESIDUAL(z0,z2,z4,z6,z8,z10,z12,z14,z16,z18,z1,z3,z5,z7,z9,z11,z13,z15,z17,z19,p0,z30,z31,z20,z21,z22,z23,z24,z25,z26,z27,x11,x4) " add x10, x10, x2 \n\t" // Forward A to fill the blank. " \n\t" " K_LEFT_LOOP: \n\t" " cmp x13, #0 \n\t" " b.eq WRITE_MEM_PREP \n\t" " \n\t" " index z31.d, xzr, x1 \n\t" GEMM_ACOL_GATHER_LOAD(z30,z31,z31,p1,p2,x10,x14,x16) " ld1rd z20.d, p0/z, [x11] \n\t" " ld1rd z21.d, p0/z, [x11, #8] \n\t" " ld1rd z22.d, p0/z, [x11, #16] \n\t" " ld1rd z23.d, p0/z, [x11, #24] \n\t" " ld1rd z24.d, p0/z, [x11, #32] \n\t" " ld1rd z25.d, p0/z, [x11, #40] \n\t" " ld1rd z26.d, p0/z, [x11, #48] \n\t" " ld1rd z27.d, p0/z, [x11, #56] \n\t" " ld1rd z28.d, p0/z, [x11, #64] \n\t" " ld1rd z29.d, p0/z, [x11, #72] \n\t" GEMM_FMLA2(z0,z1,p0,z30,z31,z20) GEMM_FMLA2(z2,z3,p0,z30,z31,z21) GEMM_FMLA2(z4,z5,p0,z30,z31,z22) GEMM_FMLA2(z6,z7,p0,z30,z31,z23) GEMM_FMLA2(z8,z9,p0,z30,z31,z24) GEMM_FMLA2(z10,z11,p0,z30,z31,z25) GEMM_FMLA2(z12,z13,p0,z30,z31,z26) GEMM_FMLA2(z14,z15,p0,z30,z31,z27) GEMM_FMLA2(z16,z17,p0,z30,z31,z28) GEMM_FMLA2(z18,z19,p0,z30,z31,z29) " add x10, x10, x2 \n\t" // Forward A. " add x11, x11, x4 \n\t" // Forward B. " sub x13, x13, #1 \n\t" " b K_LEFT_LOOP \n\t" // Next column / row. " \n\t" " WRITE_MEM_PREP: \n\t" " \n\t" " ldr x11, %[bi] \n\t" " ldr x12, %[alpha] \n\t" // Load alpha & beta. " ldr x13, %[beta] \n\t" " ld1rd z30.d, p0/z, [x12] \n\t" " ld1rd z31.d, p0/z, [x13] \n\t" " ldr x12, [x12] \n\t" " \n\t" " cmp x8, #1 \n\t" " b.eq PREFETCH_ABNEXT \n\t" " prfm PLDL2STRM, [x11] \n\t" " b WRITE_MEM \n\t" " \n\t" " PREFETCH_ABNEXT: \n\t" " ldr x1, %[a_next] \n\t" // Final Millikernel loop, x1 and x2 not needed. " ldr x2, %[b_next] \n\t" " prfm PLDL2KEEP, [x1] \n\t" " prfm PLDL2KEEP, [x1, 256*1] \n\t" " prfm PLDL2KEEP, [x1, 256*2] \n\t" " prfm PLDL2KEEP, [x1, 256*3] \n\t" " prfm PLDL2KEEP, [x1, 256*4] \n\t" " prfm PLDL2KEEP, [x1, 256*5] \n\t" " prfm PLDL2KEEP, [x1, 256*6] \n\t" " prfm PLDL2KEEP, [x1, 256*7] \n\t" " prfm PLDL2KEEP, [x1, 256*8] \n\t" " prfm PLDL2KEEP, [x1, 256*9] \n\t" " prfm PLDL2KEEP, [x1, 256*10] \n\t" " prfm PLDL2KEEP, [x1, 256*11] \n\t" " prfm PLDL2KEEP, [x1, 256*12] \n\t" " prfm PLDL2KEEP, [x1, 256*13] \n\t" " prfm PLDL2KEEP, [x1, 256*14] \n\t" " prfm PLDL2KEEP, [x1, 256*15] \n\t" " prfm PLDL2KEEP, [x2] \n\t" " prfm PLDL2KEEP, [x2, 256*1] \n\t" " prfm PLDL2KEEP, [x2, 256*2] \n\t" " prfm PLDL2KEEP, [x2, 256*3] \n\t" " prfm PLDL2KEEP, [x2, 256*4] \n\t" " prfm PLDL2KEEP, [x2, 256*5] \n\t" " prfm PLDL2KEEP, [x2, 256*6] \n\t" " prfm PLDL2KEEP, [x2, 256*7] \n\t" " prfm PLDL2KEEP, [x2, 256*8] \n\t" " prfm PLDL2KEEP, [x2, 256*9] \n\t" " \n\t" " WRITE_MEM: \n\t" " \n\t" " fmov d28, #1.0 \n\t" " fmov x16, d28 \n\t" " cmp x16, x12 \n\t" " b.eq UNIT_ALPHA \n\t" " \n\t" SCALE_COL20(z0,z1,z2,z3,z4,z5,z6,z7,z8,z9,z10,z11,z12,z13,z14,z15,z16,z17,z18,z19,z30) " \n\t" " UNIT_ALPHA: \n\t" " mov x9, x5 \n\t" // C address for loading. " mov x10, x5 \n\t" // C address for storing. " cmp x6, #1 \n\t" " b.ne WRITE_MEM_G \n\t" " \n\t" " WRITE_MEM_C: \n\t" // Available scratch: Z[20-30]. " \n\t" // Here used scratch: Z[20-29]. " mov x13, xzr \n\t" // C-column's physical 1-vector skip. " incb x13 \n\t" GEMM_C_LOAD_UKER_C(z20,z22,z24,z26,z28,z21,z23,z25,z27,z29,p1,p2,x9,x7) GEMM_C_FMAD_UKER(z20,z22,z24,z26,z28,z21,z23,z25,z27,z29,p1,p2,z0,z2,z4,z6,z8,z1,z3,z5,z7,z9,z31) GEMM_C_LOAD_UKER_C(z0,z2,z4,z6,z8,z1,z3,z5,z7,z9,p1,p2,x9,x7) " \n\t" GEMM_C_STORE_UKER_C(z20,z22,z24,z26,z28,z21,z23,z25,z27,z29,p1,p2,x10,x7) GEMM_C_FMAD_UKER(z0,z2,z4,z6,z8,z1,z3,z5,z7,z9,p1,p2,z10,z12,z14,z16,z18,z11,z13,z15,z17,z19,z31) GEMM_C_STORE_UKER_C(z0,z2,z4,z6,z8,z1,z3,z5,z7,z9,p1,p2,x10,x7) " b END_WRITE_MEM \n\t" " \n\t" " WRITE_MEM_G: \n\t" // Available scratch: Z[20-30]. " \n\t" // Here used scratch: Z[20-30] - Z30 as index. " mov x12, xzr \n\t" " incb x12 \n\t" " madd x13, x12, x6, xzr \n\t" // C-column's logical 1-vector skip. " index z30.d, xzr, x6 \n\t" // Skips passed to index is not multiplied by 8. GEMM_C_LOAD_UKER_G(z20,z22,z24,z26,z28,z21,z23,z25,z27,z29,z30,p1,p2,x9,x7,x13,x16) GEMM_C_FMAD_UKER(z20,z22,z24,z26,z28,z21,z23,z25,z27,z29,p1,p2,z0,z2,z4,z6,z8,z1,z3,z5,z7,z9,z31) GEMM_C_LOAD_UKER_G(z0,z2,z4,z6,z8,z1,z3,z5,z7,z9,z30,p1,p2,x9,x7,x13,x16) " \n\t" GEMM_C_STORE_UKER_G(z20,z22,z24,z26,z28,z21,z23,z25,z27,z29,z30,p1,p2,x10,x7,x13,x16) GEMM_C_FMAD_UKER(z0,z2,z4,z6,z8,z1,z3,z5,z7,z9,p1,p2,z10,z12,z14,z16,z18,z11,z13,z15,z17,z19,z31) GEMM_C_STORE_UKER_G(z0,z2,z4,z6,z8,z1,z3,z5,z7,z9,z30,p1,p2,x10,x7,x13,x16) " \n\t" " END_WRITE_MEM: \n\t" " subs x8, x8, #1 \n\t" " b.eq END_EXEC \n\t" " \n\t" " add x0, x0, x3 \n\t" // Forward A's base address to the next logic panel. " add x5, x5, x13 \n\t" // Forward C's base address to the next logic panel. " add x5, x5, x13 \n\t" " b MILLIKER_MLOOP \n\t" " \n\t" " END_ERROR: \n\t" " mov x0, #1 \n\t" // Return error. " END_EXEC: \n\t" " mov x0, #0 \n\t" // Return normal. : : [ai] "m" (ai), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [ps_a] "m" (ps_a), [rs_b] "m" (rs_b), [ci] "m" (ci), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c), [m_mker] "m" (m_mker), [m_left] "m" (m_left), [bi] "m" (bi), [k_mker] "m" (k_mker), [k_left] "m" (k_left), [alpha] "m" (alpha), [beta] "m" (beta), [a_next] "m" (a_next), [b_next] "m" (b_next) : "x0","x1","x2","x3","x4","x5","x6","x7","x8", "x9","x10","x11","x12","x13","x14","x15","x16",//"x17", "z0","z1","z2","z3","z4","z5","z6","z7", "z8","z9","z10","z11","z12","z13","z14","z15", "z16","z17","z18","z19", "z20","z21","z22","z23", "z24","z25","z26","z27", "z28","z29","z30","z31" ); } } blis-0.9.0/kernels/armsve/bli_kernels_armsve.h000066400000000000000000000051401422157504600214360ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "./3/bli_armsve_utils.h" // GEMM_UKR_PROT( double, d, gemm_armsve256_asm_8x8 ) GEMM_UKR_PROT( double, d, gemm_armsve_asm_2vx10_unindexed ) GEMM_UKR_PROT( float, s, gemm_armsve_asm_2vx10_unindexed ) GEMM_UKR_PROT( scomplex, c, gemm_armsve_asm_2vx10_unindexed ) GEMM_UKR_PROT( dcomplex, z, gemm_armsve_asm_2vx10_unindexed ) // GEMM_UKR_PROT( dcomplex, z, gemm_armsve_asm_2vx8_unindexed ) // GEMM_UKR_PROT( dcomplex, z, gemm_armsve_asm_2vx7_unindexed ) //GEMMSUP_KER_PROT( double, d, gemmsup_rv_armsve_2vx10_unindexed ) //GEMMSUP_KER_PROT( double, d, gemmsup_cv_armsve_2vx10_unindexed ) //GEMMSUP_KER_PROT( double, d, gemmsup_rv_armsve_10x2v_unindexed ) // Use SVE intrinsics only for referred cases. #if !defined(BLIS_FAMILY_A64FX) PACKM_KER_PROT( double, d, packm_armsve256_int_8xk ) PACKM_KER_PROT( double, d, packm_armsve512_int_12xk ) #endif PACKM_KER_PROT( double, d, packm_armsve512_asm_16xk ) PACKM_KER_PROT( double, d, packm_armsve512_asm_10xk ) blis-0.9.0/kernels/armv7a/000077500000000000000000000000001422157504600153175ustar00rootroot00000000000000blis-0.9.0/kernels/armv7a/3/000077500000000000000000000000001422157504600154615ustar00rootroot00000000000000blis-0.9.0/kernels/armv7a/3/bli_cgemm_armv7a_asm_2x2.S000066400000000000000000000233231422157504600223360ustar00rootroot00000000000000 #define REALNAME bli_cgemm_armv7a_ker_2x2 #define STACKSIZE 256 #define K r0 #define PTR_ALPHA r1 #define OLD_A r2 #define OLD_B r3 #define PTR_BETA [fp, #0 ] #define OLD_C [fp, #4 ] #define OLD_RSC [fp, #8 ] #define OLD_CSC [fp, #12 ] #define AUX [fp, #16 ] /****************************************************** * [fp, #-128] - [fp, #-64] is reserved * for store and restore of floating point * register *******************************************************/ #define L r2 #define AO r5 #define BO r6 #define CO1 r7 #define CO2 r8 #define A_PRE 96 #define B_PRE 96 #define C_PRE 0 /************************************************************************************** * Macro definitions **************************************************************************************/ #define FMAC_BR fnmacs #define FMAC_BI fmacs #define NN 1 #if defined(NN) || defined(NT) || defined(TN) || defined(TT) #define FADD_R fsubs #define FADD_I fadds #define FMAC_R1 fnmacs #define FMAC_R2 fnmacs #define FMAC_I1 fmacs #define FMAC_I2 fnmacs #elif defined(CN) || defined(CT) #define FADD_R fadds #define FADD_I fsubs #define FMAC_R1 fmacs #define FMAC_R2 fmacs #define FMAC_I1 fnmacs #define FMAC_I2 fmacs #elif defined(NC) || defined(TC) #define FADD_R fadds #define FADD_I fsubs #define FMAC_R1 fmacs #define FMAC_R2 fnmacs #define FMAC_I1 fmacs #define FMAC_I2 fmacs #else #define FADD_R fsubs #define FADD_I fadds #define FMAC_R1 fnmacs #define FMAC_R2 fmacs #define FMAC_I1 fnmacs #define FMAC_I2 fnmacs #endif .macro INIT2x2 vsub.f32 s16 , s16 , s16 vmov.f32 s17, s16 vmov.f32 s18, s16 vmov.f32 s19, s16 vmov.f32 s20, s16 vmov.f32 s21, s16 vmov.f32 s22, s16 vmov.f32 s23, s16 vmov.f32 s24, s16 vmov.f32 s25, s16 vmov.f32 s26, s16 vmov.f32 s27, s16 vmov.f32 s28, s16 vmov.f32 s29, s16 vmov.f32 s30, s16 vmov.f32 s31, s16 .endm .macro KERNEL2x2_I pld [ AO , #A_PRE ] pld [ BO , #B_PRE ] flds s0 , [ AO ] flds s1 , [ AO, #4 ] flds s8 , [ BO ] flds s9 , [ BO, #4 ] fmuls s16 , s0, s8 flds s2 , [ AO, #8 ] fmuls s24 , s1, s9 flds s3 , [ AO, #12 ] fmuls s17 , s0, s9 flds s10, [ BO, #8 ] fmuls s25 , s1, s8 flds s11, [ BO, #12 ] fmuls s18 , s2, s8 add BO , BO, #16 fmuls s26 , s3, s9 add AO , AO, #16 fmuls s19 , s2, s9 pld [ BO , #B_PRE ] fmuls s27 , s3, s8 pld [ AO , #A_PRE ] fmuls s20 , s0, s10 flds s4 , [ AO, #0 ] fmuls s28 , s1, s11 flds s5 , [ AO, #4 ] fmuls s21 , s0, s11 flds s12, [ BO ] fmuls s29 , s1, s10 flds s13, [ BO, #4 ] fmuls s22 , s2, s10 flds s6 , [ AO, #8 ] fmuls s30 , s3, s11 flds s7 , [ AO, #12 ] fmuls s23 , s2, s11 flds s14, [ BO, #8 ] fmuls s31 , s3, s10 flds s15, [ BO, #12 ] add BO , BO, #16 add AO , AO, #16 .endm .macro KERNEL2x2_M1 pld [ AO , #A_PRE ] fmacs s16 , s0, s8 pld [ BO , #B_PRE ] fmacs s24 , s1, s9 flds s4 , [ AO, #0 ] fmacs s17 , s0, s9 flds s5 , [ AO, #4 ] fmacs s25 , s1, s8 flds s12, [ BO ] fmacs s18 , s2, s8 flds s13, [ BO, #4 ] fmacs s26 , s3, s9 flds s6 , [ AO, #8 ] fmacs s19 , s2, s9 flds s7 , [ AO, #12 ] fmacs s27 , s3, s8 fmacs s20 , s0, s10 flds s14, [ BO, #8 ] fmacs s28 , s1, s11 fmacs s21 , s0, s11 flds s15, [ BO, #12 ] fmacs s29 , s1, s10 fmacs s22 , s2, s10 add BO , BO, #16 fmacs s30 , s3, s11 fmacs s23 , s2, s11 add AO , AO, #16 fmacs s31 , s3, s10 .endm .macro KERNEL2x2_M2 fmacs s16 , s4, s12 fmacs s24 , s5, s13 flds s0 , [ AO, #0 ] fmacs s17 , s4, s13 flds s1 , [ AO, #4 ] fmacs s25 , s5, s12 fmacs s18 , s6, s12 flds s8 , [ BO ] fmacs s26 , s7, s13 flds s9 , [ BO, #4 ] fmacs s19 , s6, s13 fmacs s27 , s7, s12 flds s2 , [ AO, #8 ] fmacs s20 , s4, s14 flds s3 , [ AO, #12 ] fmacs s28 , s5, s15 fmacs s21 , s4, s15 flds s10, [ BO, #8 ] fmacs s29 , s5, s14 flds s11, [ BO, #12 ] fmacs s22 , s6, s14 fmacs s30 , s7, s15 add BO , BO, #16 fmacs s23 , s6, s15 add AO , AO, #16 fmacs s31 , s7, s14 .endm .macro KERNEL2x2_E fmacs s16 , s4, s12 fmacs s24 , s5, s13 fmacs s17 , s4, s13 fmacs s25 , s5, s12 fmacs s18 , s6, s12 fmacs s26 , s7, s13 fmacs s19 , s6, s13 fmacs s27 , s7, s12 fmacs s20 , s4, s14 fmacs s28 , s5, s15 fmacs s21 , s4, s15 fmacs s29 , s5, s14 fmacs s22 , s6, s14 fmacs s30 , s7, s15 fmacs s23 , s6, s15 fmacs s31 , s7, s14 .endm .macro KERNEL2x2_SUB flds s0 , [ AO ] flds s1 , [ AO, #4 ] flds s8 , [ BO ] flds s9 , [ BO, #4 ] fmacs s16 , s0, s8 flds s2 , [ AO, #8 ] fmacs s24 , s1, s9 flds s3 , [ AO, #12 ] fmacs s17 , s0, s9 flds s10, [ BO, #8 ] fmacs s25 , s1, s8 flds s11, [ BO, #12 ] fmacs s18 , s2, s8 fmacs s26 , s3, s9 fmacs s19 , s2, s9 fmacs s27 , s3, s8 fmacs s20 , s0, s10 fmacs s28 , s1, s11 fmacs s21 , s0, s11 fmacs s29 , s1, s10 fmacs s22 , s2, s10 add BO , BO, #16 fmacs s30 , s3, s11 fmacs s23 , s2, s11 add AO , AO, #16 fmacs s31 , s3, s10 .endm .macro SAVE2x2 ldr r3, OLD_RSC // Row stride size lsl r3, r3, #3 // multiply with size of complex float flds s0, [ PTR_ALPHA ] // load real part of alpha flds s1, [ PTR_ALPHA, #4 ] // load imag part of alpha ldr r4, PTR_BETA flds s2, [ r4 ] // load real part of beta flds s3, [ r4, #4 ] // load imag part of beta // Add/Sub the real and the imag parts FADD_R s16, s24 , s16 FADD_I s17, s25 , s17 FADD_R s18, s26 , s18 FADD_I s19, s27 , s19 FADD_R s20, s28 , s20 FADD_I s21, s29 , s21 FADD_R s22, s30 , s22 FADD_I s23, s31 , s23 mov r4, CO1 // save pointer fldmias CO1, { s4 - s5 } // read real and imag part from C add CO1, CO1, r3 mov r2, CO2 // save pointer fldmias CO2, { s8 - s9 } // read real and imag part from C add CO2, CO2, r3 fmuls s24, s4, s2 // multiply Beta-real with C-real fmuls s25, s5, s2 // multiply Beta-real with C-imag fmuls s28, s8, s2 // multiply Beta-real with C-real fmuls s29, s9, s2 // multiply Beta-real with C-imag FMAC_BR s24, s3, s5 // multiply beta-imag with C-imag and add FMAC_BI s25, s3, s4 // multiply beta-imag with C-real and add FMAC_BR s28, s3, s9 // multiply beta-imag with C-imag and add FMAC_BI s29, s3, s8 // multiply beta-imag with C-real and add FMAC_R1 s24 , s0 , s16 FMAC_I1 s25 , s0 , s17 FMAC_R2 s24 , s1 , s17 FMAC_I2 s25 , s1 , s16 FMAC_R1 s28 , s0 , s20 FMAC_I1 s29 , s0 , s21 FMAC_R2 s28 , s1 , s21 FMAC_I2 s29 , s1 , s20 fldmias CO1, { s4 - s5 } // read real and imag part from C fldmias CO2, { s8 - s9 } // read real and imag part from C fmuls s26, s4, s2 // multiply Beta-real with C-real fmuls s27, s5, s2 // multiply Beta-real with C-imag fmuls s30, s8, s2 // multiply Beta-real with C-real fmuls s31, s9, s2 // multiply Beta-real with C-imag FMAC_BR s26, s3, s5 // multiply beta-imag with C-imag and add FMAC_BI s27, s3, s4 // multiply beta-imag with C-real and add FMAC_BR s30, s3, s9 // multiply beta-imag with C-imag and add FMAC_BI s31, s3, s8 // multiply beta-imag with C-real and add FMAC_R1 s26 , s0 , s18 FMAC_I1 s27 , s0 , s19 FMAC_R2 s26 , s1 , s19 FMAC_I2 s27 , s1 , s18 FMAC_R1 s30, s0 , s22 FMAC_I1 s31, s0 , s23 FMAC_R2 s30, s1 , s23 FMAC_I2 s31, s1 , s22 mov CO1, r4 // restore pointer mov CO2, r2 // restore pointer fstmias CO1, { s24 - s25 } fstmias CO2, { s28 - s29 } add CO1, CO1, r3 add CO2, CO2, r3 fstmias CO1, { s26 - s27 } fstmias CO2, { s30 - s31 } .endm /************************************************************************************** * End of macro definitions **************************************************************************************/ .arm .global REALNAME .func REALNAME REALNAME: push {r4 - r9, fp} // save register add fp, sp, #28 // add number of saved register multiplied by size of int sub sp, sp, #STACKSIZE // reserve stack mov AO, OLD_A // pointer matrix A mov BO, OLD_B // pointer matrix B sub r3, fp, #128 vstm r3, { s8 - s31} // store floating point registers ldr r2, OLD_C // pointer matrix C ldr r3, OLD_CSC // Col stride size of C lsl r3, r3, #3 // multiply with size of complex float mov CO1, r2 // first line of C add CO2, CO1, r3 // second line of C pld [ CO1, #C_PRE ] // prefetch the lines of C pld [ CO2, #C_PRE ] // prefetch the lines of C cgemm_kernel_L2_M2_20: asrs L , K, #3 // L = K / 8 cmp L , #2 blt cgemm_kernel_L2_M2_32 KERNEL2x2_I KERNEL2x2_M2 KERNEL2x2_M1 KERNEL2x2_M2 KERNEL2x2_M1 KERNEL2x2_M2 KERNEL2x2_M1 KERNEL2x2_M2 subs L, L, #2 ble cgemm_kernel_L2_M2_22a .align 5 cgemm_kernel_L2_M2_22: KERNEL2x2_M1 KERNEL2x2_M2 KERNEL2x2_M1 KERNEL2x2_M2 KERNEL2x2_M1 KERNEL2x2_M2 KERNEL2x2_M1 KERNEL2x2_M2 subs L, L, #1 bgt cgemm_kernel_L2_M2_22 cgemm_kernel_L2_M2_22a: KERNEL2x2_M1 KERNEL2x2_M2 KERNEL2x2_M1 KERNEL2x2_M2 KERNEL2x2_M1 KERNEL2x2_M2 KERNEL2x2_M1 KERNEL2x2_E b cgemm_kernel_L2_M2_44 cgemm_kernel_L2_M2_32: tst L, #1 ble cgemm_kernel_L2_M2_40 KERNEL2x2_I KERNEL2x2_M2 KERNEL2x2_M1 KERNEL2x2_M2 KERNEL2x2_M1 KERNEL2x2_M2 KERNEL2x2_M1 KERNEL2x2_E b cgemm_kernel_L2_M2_44 cgemm_kernel_L2_M2_40: INIT2x2 cgemm_kernel_L2_M2_44: ands L , K, #7 // L = K % 8 ble cgemm_kernel_L2_M2_100 cgemm_kernel_L2_M2_46: KERNEL2x2_SUB subs L, L, #1 bne cgemm_kernel_L2_M2_46 cgemm_kernel_L2_M2_100: SAVE2x2 cgemm_kernel_L999: sub r3, fp, #128 vldm r3, { s8 - s31} // restore floating point registers sub sp, fp, #28 pop {r4 - r9, fp} bx lr blis-0.9.0/kernels/armv7a/3/bli_dgemm_armv7a_asm_4x4.S000066400000000000000000000270251422157504600223460ustar00rootroot00000000000000 #define REALNAME bli_dgemm_armv7a_ker_4x4 #define STACKSIZE 256 #define K r0 #define PTR_ALPHA r1 #define OLD_A r2 #define OLD_B r3 #define PTR_BETA [fp, #0 ] #define OLD_C [fp, #4 ] #define OLD_RSC [fp, #8 ] #define OLD_CSC [fp, #12 ] #define AUX [fp, #16 ] /****************************************************** * [fp, #-128] - [fp, #-64] is reserved * for store and restore of floating point * register *******************************************************/ #define L r2 #define AO r5 #define BO r6 #define CO1 r7 #define CO2 r8 #define CO3 r9 #define CO4 r12 #define A_PRE 96 #define B_PRE 96 #define C_PRE 0 /************************************************************************************** * Macro definitions **************************************************************************************/ .macro INIT4x4 vsub.f64 d16 , d16 , d16 vmov.f64 d17, d16 vmov.f64 d18, d16 vmov.f64 d19, d16 vmov.f64 d20, d16 vmov.f64 d21, d16 vmov.f64 d22, d16 vmov.f64 d23, d16 vmov.f64 d24, d16 vmov.f64 d25, d16 vmov.f64 d26, d16 vmov.f64 d27, d16 vmov.f64 d28, d16 vmov.f64 d29, d16 vmov.f64 d30, d16 vmov.f64 d31, d16 .endm .macro KERNEL4x4_I pld [ BO , #B_PRE ] fldd d8 , [ BO ] fldd d0 , [ AO ] pld [ AO , #A_PRE ] fldd d1 , [ AO, #8 ] fmuld d16 , d0, d8 fldd d2 , [ AO, #16 ] fmuld d17 , d1, d8 fldd d3 , [ AO, #24 ] fmuld d18 , d2, d8 fldd d9 , [ BO, #8 ] fmuld d19 , d3, d8 fldd d10, [ BO, #16 ] fmuld d20 , d0, d9 fldd d11, [ BO, #24 ] fmuld d21 , d1, d9 add BO , BO, #32 add AO , AO, #32 fmuld d22 , d2, d9 pld [ BO , #B_PRE ] fldd d12, [ BO ] fmuld d23 , d3, d9 pld [ AO , #A_PRE ] fldd d4 , [ AO, #0 ] fmuld d24 , d0, d10 fldd d5 , [ AO, #8 ] fmuld d25 , d1, d10 fldd d6 , [ AO, #16 ] fmuld d26 , d2, d10 fldd d7 , [ AO, #24 ] fmuld d27 , d3, d10 fldd d13, [ BO, #8 ] fmuld d28 , d0, d11 fldd d14, [ BO, #16 ] fmuld d29 , d1, d11 fldd d15, [ BO, #24 ] fmuld d30 , d2, d11 fmuld d31 , d3, d11 .endm .macro KERNEL4x4_M2 fmacd d16 , d4, d12 pld [ AO , #A_PRE+32 ] fmacd d17 , d5, d12 fldd d0 , [ AO , #32 ] fmacd d18 , d6, d12 pld [ BO , #B_PRE+32 ] fmacd d19 , d7, d12 fldd d8 , [ BO , #32 ] fmacd d20 , d4, d13 fldd d1 , [ AO, #40 ] fmacd d21 , d5, d13 fldd d2 , [ AO, #48 ] fmacd d22 , d6, d13 fldd d3 , [ AO, #56 ] fmacd d23 , d7, d13 fmacd d24 , d4, d14 fmacd d25 , d5, d14 fldd d9 , [ BO, #40 ] fmacd d26 , d6, d14 fldd d10, [ BO, #48 ] fmacd d27 , d7, d14 fldd d11, [ BO, #56 ] fmacd d28 , d4, d15 fmacd d29 , d5, d15 add AO , AO, #64 fmacd d30 , d6, d15 add BO , BO, #64 fmacd d31 , d7, d15 .endm .macro KERNEL4x4_M1 fmacd d16 , d0, d8 pld [ AO , #A_PRE ] fmacd d17 , d1, d8 fldd d4 , [ AO ] fmacd d18 , d2, d8 pld [ BO , #B_PRE ] fmacd d19 , d3, d8 fldd d12, [ BO ] fmacd d20 , d0, d9 fldd d5 , [ AO, #8 ] fmacd d21 , d1, d9 fldd d6 , [ AO, #16 ] fmacd d22 , d2, d9 fldd d7 , [ AO, #24 ] fmacd d23 , d3, d9 fmacd d24 , d0, d10 fmacd d25 , d1, d10 fldd d13, [ BO, #8 ] fmacd d26 , d2, d10 fldd d14, [ BO, #16 ] fmacd d27 , d3, d10 fldd d15, [ BO, #24 ] fmacd d28 , d0, d11 fmacd d29 , d1, d11 fmacd d30 , d2, d11 fmacd d31 , d3, d11 .endm .macro KERNEL4x4_E fmacd d16 , d4, d12 fmacd d17 , d5, d12 add BO , BO, #32 fmacd d18 , d6, d12 add AO , AO, #32 fmacd d19 , d7, d12 fmacd d20 , d4, d13 fmacd d21 , d5, d13 fmacd d22 , d6, d13 fmacd d23 , d7, d13 fmacd d24 , d4, d14 fmacd d25 , d5, d14 fmacd d26 , d6, d14 fmacd d27 , d7, d14 fmacd d28 , d4, d15 fmacd d29 , d5, d15 fmacd d30 , d6, d15 fmacd d31 , d7, d15 .endm .macro KERNEL4x4_SUB fldd d8 , [ BO ] pld [ BO , #B_PRE ] fldd d0 , [ AO ] pld [ AO , #A_PRE ] fldd d1 , [ AO, #8 ] fmacd d16 , d0, d8 fldd d2 , [ AO, #16 ] fmacd d17 , d1, d8 fldd d3 , [ AO, #24 ] fmacd d18 , d2, d8 fldd d9 , [ BO, #8 ] fmacd d19 , d3, d8 fldd d10, [ BO, #16 ] fmacd d20 , d0, d9 fldd d11, [ BO, #24 ] fmacd d21 , d1, d9 fmacd d22 , d2, d9 fmacd d23 , d3, d9 fmacd d24 , d0, d10 fmacd d25 , d1, d10 fmacd d26 , d2, d10 fmacd d27 , d3, d10 fmacd d28 , d0, d11 fmacd d29 , d1, d11 add AO , AO, #32 fmacd d30 , d2, d11 add BO , BO, #32 fmacd d31 , d3, d11 .endm .macro SAVE4x4 ldr r3, OLD_RSC // Row stride size lsl r3, r3, #3 // multiply with size of double fldd d0, [ PTR_ALPHA ] // load alpha ldr r4, PTR_BETA fldd d1, [ r4 ] // load beta //----------------------------------------------------------- mov r2, CO1 // save pointer mov r4, CO2 // save pointer fldd d8, [ CO1 ] // load value from C fldd d12, [ CO2 ] // load value from C fmuld d8, d8, d1 // multiply with beta add CO1, CO1, r3 // compute next pointer fmacd d8, d0, d16 // multiply sum with alpha and add to value of C add CO2, CO2, r3 // compute next pointer fldd d9, [ CO1 ] // load value from C fldd d13, [ CO2 ] // load value from C fmuld d9, d9, d1 // multiply with beta add CO1, CO1, r3 // compute next pointer fmacd d9, d0, d17 // multiply sum with alpha and add to value of C add CO2, CO2, r3 // compute next pointer fldd d10, [ CO1 ] // load value from C fldd d14, [ CO2 ] // load value from C fmuld d10, d10, d1 // multiply with beta add CO1, CO1, r3 // compute next pointer fmacd d10, d0, d18 // multiply sum with alpha and add to value of C add CO2, CO2, r3 // compute next pointer fldd d11, [ CO1 ] // load value from C fldd d15, [ CO2 ] // load value from C fmuld d11, d11, d1 // multiply with beta mov CO1, r2 // restore pointer fmacd d11, d0, d19 // multiply sum with alpha and add to value of C mov CO2, r4 // restore pointer fstd d8, [ CO1 ] // store value in C add CO1 , CO1, r3 // compute next pointer fstd d9, [ CO1 ] // store value in C add CO1 , CO1, r3 // compute next pointer fstd d10, [ CO1 ] // store value in C add CO1 , CO1, r3 // compute next pointer fstd d11, [ CO1 ] // store value in C //----------------------------------------------------------- mov r2, CO3 // save pointer fldd d8, [ CO3 ] // load value from C fmuld d12, d12, d1 // multiply with beta add CO3, CO3, r3 // compute next pointer fmacd d12, d0, d20 // multiply sum with alpha and add to value of C fldd d9, [ CO3 ] // load value from C fmuld d13, d13, d1 // multiply with beta add CO3, CO3, r3 // compute next pointer fmacd d13, d0, d21 // multiply sum with alpha and add to value of C fldd d10, [ CO3 ] // load value from C fmuld d14, d14, d1 // multiply with beta add CO3, CO3, r3 // compute next pointer fmacd d14, d0, d22 // multiply sum with alpha and add to value of C fldd d11, [ CO3 ] // load value from C fmuld d15, d15, d1 // multiply with beta mov CO3, r2 // restore pointer fmacd d15, d0, d23 // multiply sum with alpha and add to value of C fstd d12, [ CO2 ] // store value in C add CO2 , CO2, r3 // compute next pointer fstd d13, [ CO2 ] // store value in C add CO2 , CO2, r3 // compute next pointer fstd d14, [ CO2 ] // store value in C add CO2 , CO2, r3 // compute next pointer fstd d15, [ CO2 ] // store value in C //----------------------------------------------------------- mov r4, CO4 // save pointer fldd d12, [ CO4 ] // load value from C fmuld d8, d8, d1 // multiply with beta add CO4, CO4, r3 // compute next pointer fmacd d8, d0, d24 // multiply sum with alpha and add to value of C fldd d13, [ CO4 ] // load value from C fmuld d9, d9, d1 // multiply with beta add CO4, CO4, r3 // compute next pointer fmacd d9, d0, d25 // multiply sum with alpha and add to value of C fldd d14, [ CO4 ] // load value from C fmuld d10, d10, d1 // multiply with beta add CO4, CO4, r3 // compute next pointer fmacd d10, d0, d26 // multiply sum with alpha and add to value of C fldd d15, [ CO4 ] // load value from C fmuld d11, d11, d1 // multiply with beta mov CO4, r4 // restore pointer fmacd d11, d0, d27 // multiply sum with alpha and add to value of C //----------------------------------------------------------- fstd d8, [ CO3 ] // store value in C fmuld d12, d12, d1 // multiply with beta add CO3 , CO3, r3 // compute next pointer fmacd d12, d0, d28 // multiply sum with alpha and add to value of C fstd d9, [ CO3 ] // store value in C fmuld d13, d13, d1 // multiply with beta add CO3 , CO3, r3 // compute next pointer fmacd d13, d0, d29 // multiply sum with alpha and add to value of C fstd d10, [ CO3 ] // store value in C fmuld d14, d14, d1 // multiply with beta add CO3 , CO3, r3 // compute next pointer fmacd d14, d0, d30 // multiply sum with alpha and add to value of C fstd d11, [ CO3 ] // store value in C fmuld d15, d15, d1 // multiply with beta fstd d12, [ CO4 ] // store value in C fmacd d15, d0, d31 // multiply sum with alpha and add to value of C add CO4 , CO4, r3 // compute next pointer fstd d13, [ CO4 ] // store value in C add CO4 , CO4, r3 // compute next pointer fstd d14, [ CO4 ] // store value in C add CO4 , CO4, r3 // compute next pointer fstd d15, [ CO4 ] // store value in C .endm /************************************************************************************** * End of macro definitions **************************************************************************************/ .arm .global REALNAME .func REALNAME REALNAME: push {r4 - r9, fp} // save register add fp, sp, #28 // add number of saved register multiplied by size of int sub sp, sp, #STACKSIZE // reserve stack mov AO, OLD_A // pointer matrix A mov BO, OLD_B // pointer matrix B sub r3, fp, #128 vstm r3, { d8 - d15} // store floating point registers ldr r2, OLD_C // pointer matrix C ldr r3, OLD_CSC // Col stride size of C lsl r3, r3, #3 // multiply with size of double mov CO1, r2 // first line of C add CO2, CO1, r3 // second line of C add CO3, CO2, r3 // third line of C add CO4, CO3, r3 // fourth line of C pld [ CO1, #C_PRE ] // prefetch the lines of C pld [ CO2, #C_PRE ] // prefetch the lines of C pld [ CO3, #C_PRE ] // prefetch the lines of C pld [ CO3, #C_PRE ] // prefetch the lines of C dgemm_kernel_L4_M4_20: asrs L , K, #3 // L = K / 8 cmp L , #2 blt dgemm_kernel_L4_M4_32 KERNEL4x4_I KERNEL4x4_M2 KERNEL4x4_M1 KERNEL4x4_M2 KERNEL4x4_M1 KERNEL4x4_M2 KERNEL4x4_M1 KERNEL4x4_M2 subs L, L, #2 ble dgemm_kernel_L4_M4_22a .align 5 dgemm_kernel_L4_M4_22: KERNEL4x4_M1 KERNEL4x4_M2 KERNEL4x4_M1 KERNEL4x4_M2 KERNEL4x4_M1 KERNEL4x4_M2 KERNEL4x4_M1 KERNEL4x4_M2 subs L, L, #1 bgt dgemm_kernel_L4_M4_22 dgemm_kernel_L4_M4_22a: KERNEL4x4_M1 KERNEL4x4_M2 KERNEL4x4_M1 KERNEL4x4_M2 KERNEL4x4_M1 KERNEL4x4_M2 KERNEL4x4_M1 KERNEL4x4_E b dgemm_kernel_L4_M4_44 dgemm_kernel_L4_M4_32: tst L, #1 ble dgemm_kernel_L4_M4_40 KERNEL4x4_I KERNEL4x4_M2 KERNEL4x4_M1 KERNEL4x4_M2 KERNEL4x4_M1 KERNEL4x4_M2 KERNEL4x4_M1 KERNEL4x4_E b dgemm_kernel_L4_M4_44 dgemm_kernel_L4_M4_40: INIT4x4 dgemm_kernel_L4_M4_44: ands L , K, #7 // L = K % 8 ble dgemm_kernel_L4_M4_100 dgemm_kernel_L4_M4_46: KERNEL4x4_SUB subs L, L, #1 bne dgemm_kernel_L4_M4_46 dgemm_kernel_L4_M4_100: SAVE4x4 dgemm_kernel_L999: sub r3, fp, #128 vldm r3, { d8 - d15} // restore floating point registers sub sp, fp, #28 pop {r4 - r9, fp} bx lr blis-0.9.0/kernels/armv7a/3/bli_gemm_armv7a_asm_d4x4.c000066400000000000000000000126021422157504600223610ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" extern void bli_sgemm_armv7a_ker_4x4 ( uint32_t k, float* restrict alpha, float* restrict a, float* restrict b, float* restrict beta, float* restrict c, uint32_t rs_c, uint32_t cs_c, auxinfo_t* restrict data ); void bli_sgemm_armv7a_asm_4x4 ( dim_t m, dim_t n, dim_t k, float* restrict alpha, float* restrict a, float* restrict b, float* restrict beta, float* restrict c, inc_t rs_c, inc_t cs_c, auxinfo_t* restrict data, cntx_t* restrict cntx ) { // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. GEMM_UKR_SETUP_CT_ANY( s, 4, 4, false ); bli_sgemm_armv7a_ker_4x4( k, alpha, a, b, beta, c, rs_c, cs_c, data ); GEMM_UKR_FLUSH_CT( s ); } extern void bli_dgemm_armv7a_ker_4x4 ( uint32_t k, double* restrict alpha, double* restrict a, double* restrict b, double* restrict beta, double* restrict c, uint32_t rs_c, uint32_t cs_c, auxinfo_t* restrict data ); void bli_dgemm_armv7a_asm_4x4 ( dim_t m, dim_t n, dim_t k, double* restrict alpha, double* restrict a, double* restrict b, double* restrict beta, double* restrict c, inc_t rs_c, inc_t cs_c, auxinfo_t* restrict data, cntx_t* restrict cntx ) { // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. GEMM_UKR_SETUP_CT_ANY( d, 4, 4, false ); bli_dgemm_armv7a_ker_4x4( k, alpha, a, b, beta, c, rs_c, cs_c, data ); GEMM_UKR_FLUSH_CT( d ); } extern void bli_cgemm_armv7a_ker_2x2 ( uint32_t k, scomplex* restrict alpha, scomplex* restrict a, scomplex* restrict b, scomplex* restrict beta, scomplex* restrict c, uint32_t rs_c, uint32_t cs_c, auxinfo_t* restrict data ); void bli_cgemm_armv7a_asm_2x2 ( dim_t m, dim_t n, dim_t k, scomplex* restrict alpha, scomplex* restrict a, scomplex* restrict b, scomplex* restrict beta, scomplex* restrict c, inc_t rs_c, inc_t cs_c, auxinfo_t* restrict data, cntx_t* restrict cntx ) { // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. GEMM_UKR_SETUP_CT_ANY( c, 2, 2, false ); bli_cgemm_armv7a_ker_2x2( k, alpha, a, b, beta, c, rs_c, cs_c, data ); GEMM_UKR_FLUSH_CT( c ); } extern void bli_zgemm_armv7a_ker_2x2 ( uint32_t k, dcomplex* restrict alpha, dcomplex* restrict a, dcomplex* restrict b, dcomplex* restrict beta, dcomplex* restrict c, uint32_t rs_c, uint32_t cs_c, auxinfo_t* restrict data ); void bli_zgemm_armv7a_asm_2x2 ( dim_t m, dim_t n, dim_t k, dcomplex* restrict alpha, dcomplex* restrict a, dcomplex* restrict b, dcomplex* restrict beta, dcomplex* restrict c, inc_t rs_c, inc_t cs_c, auxinfo_t* restrict data, cntx_t* restrict cntx ) { // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. GEMM_UKR_SETUP_CT_ANY( z, 2, 2, false ); bli_zgemm_armv7a_ker_2x2( k, alpha, a, b, beta, c, rs_c, cs_c, data ); GEMM_UKR_FLUSH_CT( z ); } blis-0.9.0/kernels/armv7a/3/bli_gemm_armv7a_int_d4x4.c000066400000000000000000000302561422157504600224000ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "arm_neon.h" void bli_sgemm_armv7a_int_4x4 ( dim_t m, dim_t n, dim_t k, float* restrict alpha, float* restrict a, float* restrict b, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint32_t k_iter = k / 4; uint32_t k_left = k % 4; uint32_t rs_c = rs_c0; uint32_t cs_c = cs_c0; uint32_t i; GEMM_UKR_SETUP_CT( s, 4, 4, false ); void* a_next = bli_auxinfo_next_a( data ); void* b_next = bli_auxinfo_next_b( data ); float32x4_t alphav; alphav = vmovq_n_f32( *alpha ); float32x4_t av1; float32x4_t av2; float32x4_t av3; float32x4_t av4; float32x4_t bv1; float32x4_t bv2; float32x4_t bv3; float32x4_t bv4; // Vector for column 0 float32x4_t cv0; // Vector for column 1 float32x4_t cv1; // Vector for column 2 float32x4_t cv2; // Vector for column 3 float32x4_t cv3; if ( *beta != 0.0F ) { // Load column 0 cv0 = vld1q_f32( c + 0*cs_c ); // Load column 1 cv1 = vld1q_f32( c + 1*cs_c ); // Load column 2 cv2 = vld1q_f32( c + 2*cs_c ); // Load column 3 cv3 = vld1q_f32( c + 3*cs_c ); } else { cv0 = vmovq_n_f32( 0.0 ); cv1 = vmovq_n_f32( 0.0 ); cv2 = vmovq_n_f32( 0.0 ); cv3 = vmovq_n_f32( 0.0 ); } // Vector for accummulating column 0 float32x4_t abv0; // Initialize vector to 0.0 abv0 = vmovq_n_f32( 0.0 ); // Vector for accummulating column 1 float32x4_t abv1; // Initialize vector to 0.0 abv1 = vmovq_n_f32( 0.0 ); // Vector for accummulating column 2 float32x4_t abv2; // Initialize vector to 0.0 abv2 = vmovq_n_f32( 0.0 ); // Vector for accummulating column 3 float32x4_t abv3; // Initialize vector to 0.0 abv3 = vmovq_n_f32( 0.0 ); for ( i = 0; i < k_iter; ++i ) { // Begin iter 0 av1 = vld1q_f32( a ); __builtin_prefetch( a + 224 ); __builtin_prefetch( b + 224 ); bv1 = vld1q_f32( b ); abv0 = vmlaq_lane_f32( abv0, av1, vget_low_f32(bv1), 0 ); abv1 = vmlaq_lane_f32( abv1, av1, vget_low_f32(bv1), 1 ); abv2 = vmlaq_lane_f32( abv2, av1, vget_high_f32(bv1), 0 ); abv3 = vmlaq_lane_f32( abv3, av1, vget_high_f32(bv1), 1 ); av2 = vld1q_f32( a+4 ); //__builtin_prefetch( a + 116 ); //__builtin_prefetch( b + 116 ); bv2 = vld1q_f32( b+4 ); abv0 = vmlaq_lane_f32( abv0, av2, vget_low_f32(bv2), 0 ); abv1 = vmlaq_lane_f32( abv1, av2, vget_low_f32(bv2), 1 ); abv2 = vmlaq_lane_f32( abv2, av2, vget_high_f32(bv2), 0 ); abv3 = vmlaq_lane_f32( abv3, av2, vget_high_f32(bv2), 1 ); av3 = vld1q_f32( a+8 ); //__builtin_prefetch( a + 120 ); //__builtin_prefetch( b + 120 ); bv3 = vld1q_f32( b+8 ); abv0 = vmlaq_lane_f32( abv0, av3, vget_low_f32(bv3), 0 ); abv1 = vmlaq_lane_f32( abv1, av3, vget_low_f32(bv3), 1 ); abv2 = vmlaq_lane_f32( abv2, av3, vget_high_f32(bv3), 0 ); abv3 = vmlaq_lane_f32( abv3, av3, vget_high_f32(bv3), 1 ); av4 = vld1q_f32( a+12); //__builtin_prefetch( a + 124 ); //__builtin_prefetch( b + 124 ); bv4 = vld1q_f32( b+12); abv0 = vmlaq_lane_f32( abv0, av4, vget_low_f32(bv4), 0 ); abv1 = vmlaq_lane_f32( abv1, av4, vget_low_f32(bv4), 1 ); abv2 = vmlaq_lane_f32( abv2, av4, vget_high_f32(bv4), 0 ); abv3 = vmlaq_lane_f32( abv3, av4, vget_high_f32(bv4), 1 ); a += 16; b += 16; } for ( i = 0; i < k_left; ++i ) { av1 = vld1q_f32( a ); __builtin_prefetch( a + 112 ); __builtin_prefetch( b + 112 ); bv1 = vld1q_f32( b ); abv0 = vmlaq_lane_f32( abv0, av1, vget_low_f32(bv1), 0 ); abv1 = vmlaq_lane_f32( abv1, av1, vget_low_f32(bv1), 1 ); abv2 = vmlaq_lane_f32( abv2, av1, vget_high_f32(bv1), 0 ); abv3 = vmlaq_lane_f32( abv3, av1, vget_high_f32(bv1), 1 ); a += 4; b += 4; } __builtin_prefetch( a_next ); __builtin_prefetch( b_next ); if ( *beta != 0.0F ) { // Multiply C by beta and then accumulate alpha * A * B. cv0 = vmulq_n_f32( cv0, *beta ); cv1 = vmulq_n_f32( cv1, *beta ); cv2 = vmulq_n_f32( cv2, *beta ); cv3 = vmulq_n_f32( cv3, *beta ); cv0 = vmlaq_f32( cv0, abv0, alphav ); cv1 = vmlaq_f32( cv1, abv1, alphav ); cv2 = vmlaq_f32( cv2, abv2, alphav ); cv3 = vmlaq_f32( cv3, abv3, alphav ); } else { // Since beta = 0, skip straight to accumulating alpha * A * B. // Note: C (cv?) was initialized to zero above. cv0 = vmlaq_f32( cv0, abv0, alphav ); cv1 = vmlaq_f32( cv1, abv1, alphav ); cv2 = vmlaq_f32( cv2, abv2, alphav ); cv3 = vmlaq_f32( cv3, abv3, alphav ); } // Store column 0 vst1q_f32( c + 0*cs_c, cv0 ); // Store column 1 vst1q_f32( c + 1*cs_c, cv1 ); // Store column 2 vst1q_f32( c + 2*cs_c, cv2 ); // Store column 3 vst1q_f32( c + 3*cs_c, cv3 ); GEMM_UKR_FLUSH_CT( s ); } void bli_dgemm_armv7a_int_4x4 ( dim_t m, dim_t n, dim_t k, double* restrict alpha, double* restrict a, double* restrict b, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. //uint32_t k_iter = k0 / 4; uint32_t k_left = k % 4; uint32_t rs_c = rs_c0; uint32_t cs_c = cs_c0; uint32_t i; GEMM_UKR_SETUP_CT_ANY( d, 4, 4, false ); //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); register double a0; register double a1; register double a2; register double a3; register double A0; register double A1; register double A2; register double A3; double b0, b1, b2, b3; double B0, B1, B2, B3; double ab00, ab01, ab02, ab03; double ab10, ab11, ab12, ab13; double ab20, ab21, ab22, ab23; double ab30, ab31, ab32, ab33; double* restrict c00, * restrict c01, * restrict c02, * restrict c03; double* restrict c10, * restrict c11, * restrict c12, * restrict c13; double* restrict c20, * restrict c21, * restrict c22, * restrict c23; double* restrict c30, * restrict c31, * restrict c32, * restrict c33; double* restrict ap = a; double* restrict bp = b; double* restrict Ap = a + 4; double* restrict Bp = b + 4; c00 = (c + 0*rs_c + 0*cs_c); c10 = (c + 1*rs_c + 0*cs_c); c20 = (c + 2*rs_c + 0*cs_c); c30 = (c + 3*rs_c + 0*cs_c); c01 = (c + 0*rs_c + 1*cs_c); c11 = (c + 1*rs_c + 1*cs_c); c21 = (c + 2*rs_c + 1*cs_c); c31 = (c + 3*rs_c + 1*cs_c); c02 = (c + 0*rs_c + 2*cs_c); c12 = (c + 1*rs_c + 2*cs_c); c22 = (c + 2*rs_c + 2*cs_c); c32 = (c + 3*rs_c + 2*cs_c); c03 = (c + 0*rs_c + 3*cs_c); c13 = (c + 1*rs_c + 3*cs_c); c23 = (c + 2*rs_c + 3*cs_c); c33 = (c + 3*rs_c + 3*cs_c); ab00 = 0.0; ab10 = 0.0; ab20 = 0.0; ab30 = 0.0; ab01 = 0.0; ab11 = 0.0; ab21 = 0.0; ab31 = 0.0; ab02 = 0.0; ab12 = 0.0; ab22 = 0.0; ab32 = 0.0; ab03 = 0.0; ab13 = 0.0; ab23 = 0.0; ab33 = 0.0; A0 = *(Ap + 0); A1 = *(Ap + 1); A2 = *(Ap + 2); A3 = *(Ap + 3); a0 = *(ap + 0); a1 = *(ap + 1); a2 = *(ap + 2); B0 = *(Bp + 0); B1 = *(Bp + 1); B2 = *(Bp + 2); B3 = *(Bp + 3); b0 = *(bp + 0); b1 = *(bp + 1); b2 = *(bp + 2); double *Aplast = (Ap + 4*(k-k_left)); //for ( i = 0; i < k_iter; ++i ) // Unroll by factor 4. for ( ; Ap != Aplast ; ) // Unroll by factor 4. { /* Prefetch */ //__asm__ ("pld\t[%0],#100\n\t" : :"r"(Ap) : ); __builtin_prefetch( ap + 112 ); __builtin_prefetch( Ap + 112 ); __builtin_prefetch( bp + 112 ); __builtin_prefetch( Bp + 112 ); // Iteration 0. ab00 += A0 * B0; a3 = *(ap + 3); ab10 += A1 * B0; b3 = *(bp + 3); ab20 += A2 * B0; ab30 += A3 * B0; ab01 += A0 * B1; ab11 += A1 * B1; B0 = *(Bp + 8); // Prefetch. ab21 += A2 * B1; ab31 += A3 * B1; ab02 += A0 * B2; B1 = *(Bp + 9); ab12 += A1 * B2; ab22 += A2 * B2; ab32 += A3 * B2; B2 = *(Bp + 10); ab03 += A0 * B3; A0 = *(Ap + 8); // Prefetch. ab13 += A1 * B3; A1 = *(Ap + 9); // Prefetch. ab23 += A2 * B3; ab33 += A3 * B3; A2 = *(Ap + 10); // Prefetch. // Iteration 1. //__asm__ ("pld\t[%0],#200\n\t" : :"r"(Ap) : ); ab00 += a0 * b0; ab10 += a1 * b0; A3 = *(Ap + 11); // Prefetch. ab20 += a2 * b0; ab30 += a3 * b0; B3 = *(Bp + 11); ab01 += a0 * b1; b0 = *(bp + 8); ab11 += a1 * b1; ab21 += a2 * b1; ab31 += a3 * b1; b1 = *(bp + 9); ab02 += a0 * b2; ab12 += a1 * b2; ab22 += a2 * b2; ab32 += a3 * b2; b2 = *(bp + 10); ab03 += a0 * b3; a0 = *(ap + 8); ab13 += a1 * b3; a1 = *(ap + 9); ab23 += a2 * b3; a2 = *(ap + 10); ab33 += a3 * b3; //a3 = *(ap + 11); ap += 8; Ap += 8; bp += 8; Bp += 8; } for ( i = 0; i < k_left; ++i ) { a0 = *(ap + 0); a1 = *(ap + 1); a2 = *(ap + 2); a3 = *(ap + 3); b0 = *(bp + 0); b1 = *(bp + 1); b2 = *(bp + 2); b3 = *(bp + 3); ab00 += a0 * b0; ab10 += a1 * b0; ab20 += a2 * b0; ab30 += a3 * b0; ab01 += a0 * b1; ab11 += a1 * b1; ab21 += a2 * b1; ab31 += a3 * b1; ab02 += a0 * b2; ab12 += a1 * b2; ab22 += a2 * b2; ab32 += a3 * b2; ab03 += a0 * b3; ab13 += a1 * b3; ab23 += a2 * b3; ab33 += a3 * b3; ap += 4; bp += 4; } if ( *beta == 0.0 ) { *c00 = ab00 * *alpha; *c10 = ab10 * *alpha; *c20 = ab20 * *alpha; *c30 = ab30 * *alpha; *c01 = ab01 * *alpha; *c11 = ab11 * *alpha; *c21 = ab21 * *alpha; *c31 = ab31 * *alpha; *c02 = ab02 * *alpha; *c12 = ab12 * *alpha; *c22 = ab22 * *alpha; *c32 = ab32 * *alpha; *c03 = ab03 * *alpha; *c13 = ab13 * *alpha; *c23 = ab23 * *alpha; *c33 = ab33 * *alpha; } else { *c00 = *c00 * *beta; *c10 = *c10 * *beta; *c20 = *c20 * *beta; *c30 = *c30 * *beta; *c01 = *c01 * *beta; *c11 = *c11 * *beta; *c21 = *c21 * *beta; *c31 = *c31 * *beta; *c02 = *c02 * *beta; *c12 = *c12 * *beta; *c22 = *c22 * *beta; *c32 = *c32 * *beta; *c03 = *c03 * *beta; *c13 = *c13 * *beta; *c23 = *c23 * *beta; *c33 = *c33 * *beta; *c00 += ab00 * *alpha; *c10 += ab10 * *alpha; *c20 += ab20 * *alpha; *c30 += ab30 * *alpha; *c01 += ab01 * *alpha; *c11 += ab11 * *alpha; *c21 += ab21 * *alpha; *c31 += ab31 * *alpha; *c02 += ab02 * *alpha; *c12 += ab12 * *alpha; *c22 += ab22 * *alpha; *c32 += ab32 * *alpha; *c03 += ab03 * *alpha; *c13 += ab13 * *alpha; *c23 += ab23 * *alpha; *c33 += ab33 * *alpha; } GEMM_UKR_FLUSH_CT( d ); } blis-0.9.0/kernels/armv7a/3/bli_sgemm_armv7a_asm_4x4.S000066400000000000000000000260351422157504600223650ustar00rootroot00000000000000 #define REALNAME bli_sgemm_armv7a_ker_4x4 #define STACKSIZE 256 #define K r0 #define PTR_ALPHA r1 #define OLD_A r2 #define OLD_B r3 #define PTR_BETA [fp, #0 ] #define OLD_C [fp, #4 ] #define OLD_RSC [fp, #8 ] #define OLD_CSC [fp, #12 ] #define AUX [fp, #16 ] /****************************************************** * [fp, #-128] - [fp, #-64] is reserved * for store and restore of floating point * register *******************************************************/ #define L r2 #define AO r5 #define BO r6 #define CO1 r7 #define CO2 r8 #define CO3 r9 #define CO4 r12 #define A_PRE 96 #define B_PRE 96 #define C_PRE 0 /************************************************************************************** * Macro definitions **************************************************************************************/ .macro INIT4x4 vsub.f32 s16 , s16 , s16 vmov.f32 s17, s16 vmov.f32 s18, s16 vmov.f32 s19, s16 vmov.f32 s20, s16 vmov.f32 s21, s16 vmov.f32 s22, s16 vmov.f32 s23, s16 vmov.f32 s24, s16 vmov.f32 s25, s16 vmov.f32 s26, s16 vmov.f32 s27, s16 vmov.f32 s28, s16 vmov.f32 s29, s16 vmov.f32 s30, s16 vmov.f32 s31, s16 .endm .macro KERNEL4x4_I pld [ AO , #A_PRE ] fldmias AO!, { s0 - s1 } pld [ BO , #B_PRE ] fldmias BO!, { s8 - s9 } fmuls s16 , s0, s8 fldmias AO!, { s2 - s3 } fmuls s17 , s1, s8 fmuls s18 , s2, s8 fldmias BO!, { s10 - s11 } fmuls s19 , s3, s8 fmuls s20 , s0, s9 fldmias AO!, { s4 - s5 } fmuls s21 , s1, s9 fmuls s22 , s2, s9 fldmias AO!, { s6 - s7 } fmuls s23 , s3, s9 fmuls s24 , s0, s10 fldmias BO!, { s12 - s13 } fmuls s25 , s1, s10 fmuls s26 , s2, s10 fldmias BO!, { s14 - s15 } fmuls s27 , s3, s10 fmuls s28 , s0, s11 fmuls s29 , s1, s11 fmuls s30 , s2, s11 fmuls s31 , s3, s11 .endm .macro KERNEL4x4_M2 pld [ AO , #A_PRE ] fmacs s16 , s4, s12 fmacs s17 , s5, s12 fldmias AO!, { s0 - s3 } fmacs s18 , s6, s12 pld [ BO , #B_PRE ] fmacs s19 , s7, s12 fmacs s20 , s4, s13 fldmias BO!, { s8 - s11 } fmacs s21 , s5, s13 fmacs s22 , s6, s13 //fldmias AO!, { s2 - s3 } fmacs s23 , s7, s13 fmacs s24 , s4, s14 //fldmias BO!, { s10 - s11 } fmacs s25 , s5, s14 fmacs s26 , s6, s14 fmacs s27 , s7, s14 fmacs s28 , s4, s15 fmacs s29 , s5, s15 fmacs s30 , s6, s15 fmacs s31 , s7, s15 .endm .macro KERNEL4x4_M1 fmacs s16 , s0, s8 fldmias AO!, { s4 - s7 } fmacs s17 , s1, s8 fmacs s18 , s2, s8 fldmias BO!, { s12 - s15 } //fldmias AO!, { s6 - s7 } fmacs s19 , s3, s8 fmacs s20 , s0, s9 fmacs s21 , s1, s9 fmacs s22 , s2, s9 //fldmias BO!, { s14 - s15 } fmacs s23 , s3, s9 fmacs s24 , s0, s10 fmacs s25 , s1, s10 fmacs s26 , s2, s10 fmacs s27 , s3, s10 fmacs s28 , s0, s11 fmacs s29 , s1, s11 fmacs s30 , s2, s11 fmacs s31 , s3, s11 .endm .macro KERNEL4x4_E fmacs s16 , s4, s12 fmacs s17 , s5, s12 fmacs s18 , s6, s12 fmacs s19 , s7, s12 fmacs s20 , s4, s13 fmacs s21 , s5, s13 fmacs s22 , s6, s13 fmacs s23 , s7, s13 fmacs s24 , s4, s14 fmacs s25 , s5, s14 fmacs s26 , s6, s14 fmacs s27 , s7, s14 fmacs s28 , s4, s15 fmacs s29 , s5, s15 fmacs s30 , s6, s15 fmacs s31 , s7, s15 .endm .macro KERNEL4x4_SUB flds s8 , [ BO ] flds s0 , [ AO ] flds s1 , [ AO, #4 ] fmacs s16 , s0, s8 flds s2 , [ AO, #8 ] fmacs s17 , s1, s8 flds s3 , [ AO, #12 ] fmacs s18 , s2, s8 flds s9 , [ BO, #4 ] fmacs s19 , s3, s8 flds s10, [ BO, #8 ] fmacs s20 , s0, s9 flds s11, [ BO, #12 ] fmacs s21 , s1, s9 fmacs s22 , s2, s9 fmacs s23 , s3, s9 fmacs s24 , s0, s10 fmacs s25 , s1, s10 fmacs s26 , s2, s10 fmacs s27 , s3, s10 fmacs s28 , s0, s11 fmacs s29 , s1, s11 add AO , AO, #16 fmacs s30 , s2, s11 add BO , BO, #16 fmacs s31 , s3, s11 .endm .macro SAVE4x4 ldr r3, OLD_RSC // Row stride size lsl r3, r3, #2 // multiply with size of float flds s0, [ PTR_ALPHA ] // load alpha ldr r4, PTR_BETA flds s1, [ r4 ] // load beta //----------------------------------------------------------- mov r2, CO1 // save pointer mov r4, CO2 // save pointer flds s8, [ CO1 ] // load value from C flds s12, [ CO2 ] // load value from C fmuls s8, s8, s1 // multiply with beta add CO1, CO1, r3 // compute next pointer fmacs s8, s0, s16 // multiply sum with alpha and add to value of C add CO2, CO2, r3 // compute next pointer flds s9, [ CO1 ] // load value from C flds s13, [ CO2 ] // load value from C fmuls s9, s9, s1 // multiply with beta add CO1, CO1, r3 // compute next pointer fmacs s9, s0, s17 // multiply sum with alpha and add to value of C add CO2, CO2, r3 // compute next pointer flds s10, [ CO1 ] // load value from C flds s14, [ CO2 ] // load value from C fmuls s10, s10, s1 // multiply with beta add CO1, CO1, r3 // compute next pointer fmacs s10, s0, s18 // multiply sum with alpha and add to value of C add CO2, CO2, r3 // compute next pointer flds s11, [ CO1 ] // load value from C flds s15, [ CO2 ] // load value from C fmuls s11, s11, s1 // multiply with beta mov CO1, r2 // restore pointer fmacs s11, s0, s19 // multiply sum with alpha and add to value of C mov CO2, r4 // restore pointer fsts s8, [ CO1 ] // store value in C add CO1 , CO1, r3 // compute next pointer fsts s9, [ CO1 ] // store value in C add CO1 , CO1, r3 // compute next pointer fsts s10, [ CO1 ] // store value in C add CO1 , CO1, r3 // compute next pointer fsts s11, [ CO1 ] // store value in C //----------------------------------------------------------- mov r2, CO3 // save pointer flds s8, [ CO3 ] // load value from C fmuls s12, s12, s1 // multiply with beta add CO3, CO3, r3 // compute next pointer fmacs s12, s0, s20 // multiply sum with alpha and add to value of C flds s9, [ CO3 ] // load value from C fmuls s13, s13, s1 // multiply with beta add CO3, CO3, r3 // compute next pointer fmacs s13, s0, s21 // multiply sum with alpha and add to value of C flds s10, [ CO3 ] // load value from C fmuls s14, s14, s1 // multiply with beta add CO3, CO3, r3 // compute next pointer fmacs s14, s0, s22 // multiply sum with alpha and add to value of C flds s11, [ CO3 ] // load value from C fmuls s15, s15, s1 // multiply with beta mov CO3, r2 // restore pointer fmacs s15, s0, s23 // multiply sum with alpha and add to value of C fsts s12, [ CO2 ] // store value in C add CO2 , CO2, r3 // compute next pointer fsts s13, [ CO2 ] // store value in C add CO2 , CO2, r3 // compute next pointer fsts s14, [ CO2 ] // store value in C add CO2 , CO2, r3 // compute next pointer fsts s15, [ CO2 ] // store value in C //----------------------------------------------------------- mov r4, CO4 // save pointer flds s12, [ CO4 ] // load value from C fmuls s8, s8, s1 // multiply with beta add CO4, CO4, r3 // compute next pointer fmacs s8, s0, s24 // multiply sum with alpha and add to value of C flds s13, [ CO4 ] // load value from C fmuls s9, s9, s1 // multiply with beta add CO4, CO4, r3 // compute next pointer fmacs s9, s0, s25 // multiply sum with alpha and add to value of C flds s14, [ CO4 ] // load value from C fmuls s10, s10, s1 // multiply with beta add CO4, CO4, r3 // compute next pointer fmacs s10, s0, s26 // multiply sum with alpha and add to value of C flds s15, [ CO4 ] // load value from C fmuls s11, s11, s1 // multiply with beta mov CO4, r4 // restore pointer fmacs s11, s0, s27 // multiply sum with alpha and add to value of C //----------------------------------------------------------- fsts s8, [ CO3 ] // store value in C fmuls s12, s12, s1 // multiply with beta add CO3 , CO3, r3 // compute next pointer fmacs s12, s0, s28 // multiply sum with alpha and add to value of C fsts s9, [ CO3 ] // store value in C fmuls s13, s13, s1 // multiply with beta add CO3 , CO3, r3 // compute next pointer fmacs s13, s0, s29 // multiply sum with alpha and add to value of C fsts s10, [ CO3 ] // store value in C fmuls s14, s14, s1 // multiply with beta add CO3 , CO3, r3 // compute next pointer fmacs s14, s0, s30 // multiply sum with alpha and add to value of C fsts s11, [ CO3 ] // store value in C fmuls s15, s15, s1 // multiply with beta fsts s12, [ CO4 ] // store value in C fmacs s15, s0, s31 // multiply sum with alpha and add to value of C add CO4 , CO4, r3 // compute next pointer fsts s13, [ CO4 ] // store value in C add CO4 , CO4, r3 // compute next pointer fsts s14, [ CO4 ] // store value in C add CO4 , CO4, r3 // compute next pointer fsts s15, [ CO4 ] // store value in C .endm /************************************************************************************** * End of macro definitions **************************************************************************************/ .arm .global REALNAME .func REALNAME REALNAME: push {r4 - r9, fp} // save register add fp, sp, #28 // add number of saved register multiplied by size of int sub sp, sp, #STACKSIZE // reserve stack mov AO, OLD_A // pointer matrix A mov BO, OLD_B // pointer matrix B sub r3, fp, #128 vstm r3, { s8 - s31 } // store floating point registers ldr r2, OLD_C // pointer matrix C ldr r3, OLD_CSC // Col stride size of C lsl r3, r3, #2 // multiply with size of float mov CO1, r2 // first line of C add CO2, CO1, r3 // second line of C add CO3, CO2, r3 // third line of C add CO4, CO3, r3 // fourth line of C pld [ CO1, #C_PRE ] // prefetch the lines of C pld [ CO2, #C_PRE ] // prefetch the lines of C pld [ CO3, #C_PRE ] // prefetch the lines of C pld [ CO3, #C_PRE ] // prefetch the lines of C sgemm_kernel_L4_M4_20: asrs L , K, #3 // L = K / 8 cmp L , #2 blt sgemm_kernel_L4_M4_32 KERNEL4x4_I KERNEL4x4_M2 KERNEL4x4_M1 KERNEL4x4_M2 KERNEL4x4_M1 KERNEL4x4_M2 KERNEL4x4_M1 KERNEL4x4_M2 subs L, L, #2 ble sgemm_kernel_L4_M4_22a .align 5 sgemm_kernel_L4_M4_22: KERNEL4x4_M1 KERNEL4x4_M2 KERNEL4x4_M1 KERNEL4x4_M2 KERNEL4x4_M1 KERNEL4x4_M2 KERNEL4x4_M1 KERNEL4x4_M2 subs L, L, #1 bgt sgemm_kernel_L4_M4_22 sgemm_kernel_L4_M4_22a: KERNEL4x4_M1 KERNEL4x4_M2 KERNEL4x4_M1 KERNEL4x4_M2 KERNEL4x4_M1 KERNEL4x4_M2 KERNEL4x4_M1 KERNEL4x4_E b sgemm_kernel_L4_M4_44 sgemm_kernel_L4_M4_32: tst L, #1 ble sgemm_kernel_L4_M4_40 KERNEL4x4_I KERNEL4x4_M2 KERNEL4x4_M1 KERNEL4x4_M2 KERNEL4x4_M1 KERNEL4x4_M2 KERNEL4x4_M1 KERNEL4x4_E b sgemm_kernel_L4_M4_44 sgemm_kernel_L4_M4_40: INIT4x4 sgemm_kernel_L4_M4_44: ands L , K, #7 // L = K % 8 ble sgemm_kernel_L4_M4_100 sgemm_kernel_L4_M4_46: KERNEL4x4_SUB subs L, L, #1 bne sgemm_kernel_L4_M4_46 sgemm_kernel_L4_M4_100: SAVE4x4 sgemm_kernel_L999: sub r3, fp, #128 vldm r3, { s8 - s31 } // restore floating point registers sub sp, fp, #28 pop {r4 - r9, fp} bx lr blis-0.9.0/kernels/armv7a/3/bli_zgemm_armv7a_asm_2x2.S000066400000000000000000000234631422157504600223720ustar00rootroot00000000000000 #define REALNAME bli_zgemm_armv7a_ker_2x2 #define STACKSIZE 256 #define K r0 #define PTR_ALPHA r1 #define OLD_A r2 #define OLD_B r3 #define PTR_BETA [fp, #0 ] #define OLD_C [fp, #4 ] #define OLD_RSC [fp, #8 ] #define OLD_CSC [fp, #12 ] #define AUX [fp, #16 ] /****************************************************** * [fp, #-128] - [fp, #-64] is reserved * for store and restore of floating point * register *******************************************************/ #define L r2 #define AO r5 #define BO r6 #define CO1 r7 #define CO2 r8 #define A_PRE 96 #define B_PRE 96 #define C_PRE 0 /************************************************************************************** * Macro definitions **************************************************************************************/ #define FMAC_BR fnmacd #define FMAC_BI fmacd #define NN 1 #if defined(NN) || defined(NT) || defined(TN) || defined(TT) #define FADD_R fsubd #define FADD_I faddd #define FMAC_R1 fnmacd #define FMAC_R2 fnmacd #define FMAC_I1 fmacd #define FMAC_I2 fnmacd #elif defined(CN) || defined(CT) #define FADD_R faddd #define FADD_I fsubd #define FMAC_R1 fmacd #define FMAC_R2 fmacd #define FMAC_I1 fnmacd #define FMAC_I2 fmacd #elif defined(NC) || defined(TC) #define FADD_R faddd #define FADD_I fsubd #define FMAC_R1 fmacd #define FMAC_R2 fnmacd #define FMAC_I1 fmacd #define FMAC_I2 fmacd #else #define FADD_R fsubd #define FADD_I faddd #define FMAC_R1 fnmacd #define FMAC_R2 fmacd #define FMAC_I1 fnmacd #define FMAC_I2 fnmacd #endif .macro INIT2x2 vsub.f64 d16 , d16 , d16 vmov.f64 d17, d16 vmov.f64 d18, d16 vmov.f64 d19, d16 vmov.f64 d20, d16 vmov.f64 d21, d16 vmov.f64 d22, d16 vmov.f64 d23, d16 vmov.f64 d24, d16 vmov.f64 d25, d16 vmov.f64 d26, d16 vmov.f64 d27, d16 vmov.f64 d28, d16 vmov.f64 d29, d16 vmov.f64 d30, d16 vmov.f64 d31, d16 .endm .macro KERNEL2x2_I pld [ AO , #A_PRE ] pld [ BO , #B_PRE ] fldd d0 , [ AO ] fldd d1 , [ AO, #8 ] fldd d8 , [ BO ] fldd d9 , [ BO, #8 ] fmuld d16 , d0, d8 fldd d2 , [ AO, #16 ] fmuld d24 , d1, d9 fldd d3 , [ AO, #24 ] fmuld d17 , d0, d9 fldd d10, [ BO, #16 ] fmuld d25 , d1, d8 fldd d11, [ BO, #24 ] fmuld d18 , d2, d8 add BO , BO, #32 fmuld d26 , d3, d9 add AO , AO, #32 fmuld d19 , d2, d9 pld [ BO , #B_PRE ] fmuld d27 , d3, d8 pld [ AO , #A_PRE ] fmuld d20 , d0, d10 fldd d4 , [ AO, #0 ] fmuld d28 , d1, d11 fldd d5 , [ AO, #8 ] fmuld d21 , d0, d11 fldd d12, [ BO ] fmuld d29 , d1, d10 fldd d13, [ BO, #8 ] fmuld d22 , d2, d10 fldd d6 , [ AO, #16 ] fmuld d30 , d3, d11 fldd d7 , [ AO, #24 ] fmuld d23 , d2, d11 fldd d14, [ BO, #16 ] fmuld d31 , d3, d10 fldd d15, [ BO, #24 ] add BO , BO, #32 add AO , AO, #32 .endm .macro KERNEL2x2_M1 pld [ AO , #A_PRE ] fmacd d16 , d0, d8 pld [ BO , #B_PRE ] fmacd d24 , d1, d9 fldd d4 , [ AO, #0 ] fmacd d17 , d0, d9 fldd d5 , [ AO, #8 ] fmacd d25 , d1, d8 fldd d12, [ BO ] fmacd d18 , d2, d8 fldd d13, [ BO, #8 ] fmacd d26 , d3, d9 fldd d6 , [ AO, #16 ] fmacd d19 , d2, d9 fldd d7 , [ AO, #24 ] fmacd d27 , d3, d8 fmacd d20 , d0, d10 fldd d14, [ BO, #16 ] fmacd d28 , d1, d11 fmacd d21 , d0, d11 fldd d15, [ BO, #24 ] fmacd d29 , d1, d10 fmacd d22 , d2, d10 add BO , BO, #32 fmacd d30 , d3, d11 fmacd d23 , d2, d11 add AO , AO, #32 fmacd d31 , d3, d10 .endm .macro KERNEL2x2_M2 pld [ AO , #A_PRE ] fmacd d16 , d4, d12 pld [ BO , #B_PRE ] fmacd d24 , d5, d13 fldd d0 , [ AO, #0 ] fmacd d17 , d4, d13 fldd d1 , [ AO, #8 ] fmacd d25 , d5, d12 fmacd d18 , d6, d12 fldd d8 , [ BO ] fmacd d26 , d7, d13 fldd d9 , [ BO, #8 ] fmacd d19 , d6, d13 fmacd d27 , d7, d12 fldd d2 , [ AO, #16 ] fmacd d20 , d4, d14 fldd d3 , [ AO, #24 ] fmacd d28 , d5, d15 fmacd d21 , d4, d15 fldd d10, [ BO, #16 ] fmacd d29 , d5, d14 fldd d11, [ BO, #24 ] fmacd d22 , d6, d14 fmacd d30 , d7, d15 add BO , BO, #32 fmacd d23 , d6, d15 add AO , AO, #32 fmacd d31 , d7, d14 .endm .macro KERNEL2x2_E fmacd d16 , d4, d12 fmacd d24 , d5, d13 fmacd d17 , d4, d13 fmacd d25 , d5, d12 fmacd d18 , d6, d12 fmacd d26 , d7, d13 fmacd d19 , d6, d13 fmacd d27 , d7, d12 fmacd d20 , d4, d14 fmacd d28 , d5, d15 fmacd d21 , d4, d15 fmacd d29 , d5, d14 fmacd d22 , d6, d14 fmacd d30 , d7, d15 fmacd d23 , d6, d15 fmacd d31 , d7, d14 .endm .macro KERNEL2x2_SUB pld [ AO , #A_PRE ] pld [ BO , #B_PRE ] fldd d0 , [ AO ] fldd d1 , [ AO, #8 ] fldd d8 , [ BO ] fldd d9 , [ BO, #8 ] fmacd d16 , d0, d8 fldd d2 , [ AO, #16 ] fmacd d24 , d1, d9 fldd d3 , [ AO, #24 ] fmacd d17 , d0, d9 fldd d10, [ BO, #16 ] fmacd d25 , d1, d8 fldd d11, [ BO, #24 ] fmacd d18 , d2, d8 fmacd d26 , d3, d9 fmacd d19 , d2, d9 fmacd d27 , d3, d8 fmacd d20 , d0, d10 fmacd d28 , d1, d11 fmacd d21 , d0, d11 fmacd d29 , d1, d10 fmacd d22 , d2, d10 add BO , BO, #32 fmacd d30 , d3, d11 fmacd d23 , d2, d11 add AO , AO, #32 fmacd d31 , d3, d10 .endm .macro SAVE2x2 ldr r3, OLD_RSC // Row stride size lsl r3, r3, #4 // multiply with size of complex double fldd d0, [ PTR_ALPHA ] // load real part of alpha fldd d1, [ PTR_ALPHA, #8 ] // load imag part of alpha ldr r4, PTR_BETA fldd d2, [ r4 ] // load real part of beta fldd d3, [ r4, #8 ] // load imag part of beta // Add/Sub the real and the imag parts FADD_R d16, d24 , d16 FADD_I d17, d25 , d17 FADD_R d18, d26 , d18 FADD_I d19, d27 , d19 FADD_R d20, d28 , d20 FADD_I d21, d29 , d21 FADD_R d22, d30 , d22 FADD_I d23, d31 , d23 mov r4, CO1 // save pointer fldmiad CO1, { d4 - d5 } // read real and imag part from C add CO1, CO1, r3 mov r2, CO2 // save pointer fldmiad CO2, { d8 - d9 } // read real and imag part from C add CO2, CO2, r3 fmuld d24, d4, d2 // multiply Beta-real with C-real fmuld d25, d5, d2 // multiply Beta-real with C-imag fmuld d28, d8, d2 // multiply Beta-real with C-real fmuld d29, d9, d2 // multiply Beta-real with C-imag FMAC_BR d24, d3, d5 // multiply beta-imag with C-imag and add FMAC_BI d25, d3, d4 // multiply beta-imag with C-real and add FMAC_BR d28, d3, d9 // multiply beta-imag with C-imag and add FMAC_BI d29, d3, d8 // multiply beta-imag with C-real and add FMAC_R1 d24 , d0 , d16 FMAC_I1 d25 , d0 , d17 FMAC_R2 d24 , d1 , d17 FMAC_I2 d25 , d1 , d16 FMAC_R1 d28 , d0 , d20 FMAC_I1 d29 , d0 , d21 FMAC_R2 d28 , d1 , d21 FMAC_I2 d29 , d1 , d20 fldmiad CO1, { d4 - d5 } // read real and imag part from C fldmiad CO2, { d8 - d9 } // read real and imag part from C fmuld d26, d4, d2 // multiply Beta-real with C-real fmuld d27, d5, d2 // multiply Beta-real with C-imag fmuld d30, d8, d2 // multiply Beta-real with C-real fmuld d31, d9, d2 // multiply Beta-real with C-imag FMAC_BR d26, d3, d5 // multiply beta-imag with C-imag and add FMAC_BI d27, d3, d4 // multiply beta-imag with C-real and add FMAC_BR d30, d3, d9 // multiply beta-imag with C-imag and add FMAC_BI d31, d3, d8 // multiply beta-imag with C-real and add FMAC_R1 d26 , d0 , d18 FMAC_I1 d27 , d0 , d19 FMAC_R2 d26 , d1 , d19 FMAC_I2 d27 , d1 , d18 FMAC_R1 d30, d0 , d22 FMAC_I1 d31, d0 , d23 FMAC_R2 d30, d1 , d23 FMAC_I2 d31, d1 , d22 mov CO1, r4 // restore pointer mov CO2, r2 // restore pointer fstmiad CO1, { d24 - d25 } fstmiad CO2, { d28 - d29 } add CO1, CO1, r3 add CO2, CO2, r3 fstmiad CO1, { d26 - d27 } fstmiad CO2, { d30 - d31 } .endm /************************************************************************************** * End of macro definitions **************************************************************************************/ .arm .global REALNAME .func REALNAME REALNAME: push {r4 - r9, fp} // save register add fp, sp, #28 // add number of saved register multiplied by size of int sub sp, sp, #STACKSIZE // reserve stack mov AO, OLD_A // pointer matrix A mov BO, OLD_B // pointer matrix B sub r3, fp, #128 vstm r3, { d8 - d15} // store floating point registers ldr r2, OLD_C // pointer matrix C ldr r3, OLD_CSC // Col stride size of C lsl r3, r3, #4 // multiply with size of complex double mov CO1, r2 // first line of C add CO2, CO1, r3 // second line of C pld [ CO1, #C_PRE ] // prefetch the lines of C pld [ CO2, #C_PRE ] // prefetch the lines of C zgemm_kernel_L2_M2_20: asrs L , K, #3 // L = K / 8 cmp L , #2 blt zgemm_kernel_L2_M2_32 KERNEL2x2_I KERNEL2x2_M2 KERNEL2x2_M1 KERNEL2x2_M2 KERNEL2x2_M1 KERNEL2x2_M2 KERNEL2x2_M1 KERNEL2x2_M2 subs L, L, #2 ble zgemm_kernel_L2_M2_22a .align 5 zgemm_kernel_L2_M2_22: KERNEL2x2_M1 KERNEL2x2_M2 KERNEL2x2_M1 KERNEL2x2_M2 KERNEL2x2_M1 KERNEL2x2_M2 KERNEL2x2_M1 KERNEL2x2_M2 subs L, L, #1 bgt zgemm_kernel_L2_M2_22 zgemm_kernel_L2_M2_22a: KERNEL2x2_M1 KERNEL2x2_M2 KERNEL2x2_M1 KERNEL2x2_M2 KERNEL2x2_M1 KERNEL2x2_M2 KERNEL2x2_M1 KERNEL2x2_E b zgemm_kernel_L2_M2_44 zgemm_kernel_L2_M2_32: tst L, #1 ble zgemm_kernel_L2_M2_40 KERNEL2x2_I KERNEL2x2_M2 KERNEL2x2_M1 KERNEL2x2_M2 KERNEL2x2_M1 KERNEL2x2_M2 KERNEL2x2_M1 KERNEL2x2_E b zgemm_kernel_L2_M2_44 zgemm_kernel_L2_M2_40: INIT2x2 zgemm_kernel_L2_M2_44: ands L , K, #7 // L = K % 8 ble zgemm_kernel_L2_M2_100 zgemm_kernel_L2_M2_46: KERNEL2x2_SUB subs L, L, #1 bne zgemm_kernel_L2_M2_46 zgemm_kernel_L2_M2_100: SAVE2x2 zgemm_kernel_L999: sub r3, fp, #128 vldm r3, { d8 - d15} // restore floating point registers sub sp, fp, #28 pop {r4 - r9, fp} bx lr blis-0.9.0/kernels/armv7a/bli_kernels_armv7a.h000066400000000000000000000036661422157504600212510ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ GEMM_UKR_PROT( float, s, gemm_armv7a_asm_4x4 ) GEMM_UKR_PROT( double, d, gemm_armv7a_asm_4x4 ) GEMM_UKR_PROT( scomplex, c, gemm_armv7a_asm_2x2 ) GEMM_UKR_PROT( dcomplex, z, gemm_armv7a_asm_2x2 ) GEMM_UKR_PROT( float, s, gemm_armv7a_int_4x4 ) GEMM_UKR_PROT( double, d, gemm_armv7a_int_4x4 ) blis-0.9.0/kernels/armv8a/000077500000000000000000000000001422157504600153205ustar00rootroot00000000000000blis-0.9.0/kernels/armv8a/1m/000077500000000000000000000000001422157504600156355ustar00rootroot00000000000000blis-0.9.0/kernels/armv8a/1m/bli_packm_armv8a_int_d6xk.c000066400000000000000000000246211422157504600230130ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2020, Linaro Limited 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include #if defined(__clang__) #define PRAGMA_NOUNROLL _Pragma("nounroll") #define PRAGMA_UNROLL_2 _Pragma("unroll 2") #elif defined(__GNUC__) #define PRAGMA_NOUNROLL _Pragma("GCC unroll 1") #define PRAGMA_UNROLL_2 _Pragma("GCC unroll 2") #else #define PRAGMA_NOUNROLL #define PRAGMA_UNROLL_2 #endif void bli_dpackm_armv8a_int_6xk ( conj_t conja, pack_t schema, dim_t cdim0, dim_t k0, dim_t k0_max, double* restrict kappa, double* restrict a, inc_t inca0, inc_t lda0, double* restrict p, inc_t ldp0, cntx_t* restrict cntx ) { // This is the panel dimension assumed by the packm kernel. const dim_t mnr = 6; // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 2; uint64_t k_left = k0 % 2; double* a_loc = a; double* p_loc = p; // NOTE: For the purposes of the comments in this packm kernel, we // interpret inca and lda as rs_a and cs_a, respectively, and similarly // interpret ldp as cs_p (with rs_p implicitly unit). Thus, when reading // this packm kernel, you should think of the operation as packing an // m x n micropanel, where m and n are tiny and large, respectively, and // where elements of each column of the packed matrix P are contiguous. // (This packm kernel can still be used to pack micropanels of matrix B // in a gemm operation.) const uint64_t inca = inca0; const uint64_t lda = lda0; const uint64_t ldp = ldp0; const bool gs = ( inca0 != 1 && lda0 != 1 ); // NOTE: If/when this kernel ever supports scaling by kappa within the // assembly region, this constraint should be lifted. const bool unitk = bli_deq1( *kappa ); // ------------------------------------------------------------------------- if ( cdim0 == mnr && !gs ) { if ( unitk ) { if ( inca == 1 ) { // No need to use k-loops here. // Simply let compiler to expand loops. PRAGMA_UNROLL_2 for ( dim_t ik = k_iter * 2 + k_left; ik > 0; --ik ) { float64x2_t v0 = vld1q_f64( a_loc + 0 ); float64x2_t v1 = vld1q_f64( a_loc + 2 ); float64x2_t v2 = vld1q_f64( a_loc + 4 ); vst1q_f64( p_loc + 0, v0 ); vst1q_f64( p_loc + 2, v1 ); vst1q_f64( p_loc + 4, v2 ); a_loc += lda; p_loc += ldp; } } else // if ( lda == 1 ) { float64x2_t v0 = (float64x2_t)vdupq_n_u64( 0 ); float64x2_t v1 = (float64x2_t)vdupq_n_u64( 0 ); float64x2_t v2 = (float64x2_t)vdupq_n_u64( 0 ); float64x2_t v3 = (float64x2_t)vdupq_n_u64( 0 ); float64x2_t v4 = (float64x2_t)vdupq_n_u64( 0 ); float64x2_t v5 = (float64x2_t)vdupq_n_u64( 0 ); PRAGMA_NOUNROLL for ( ; k_iter > 0; --k_iter ) { v0 = vld1q_f64( a_loc + inca * 0 ); v1 = vld1q_f64( a_loc + inca * 1 ); v2 = vld1q_f64( a_loc + inca * 2 ); v3 = vld1q_f64( a_loc + inca * 3 ); v4 = vld1q_f64( a_loc + inca * 4 ); v5 = vld1q_f64( a_loc + inca * 5 ); // In-register transpose. float64x2_t vd0_1 = vtrn1q_f64( v0, v1 ); float64x2_t vd1_1 = vtrn1q_f64( v2, v3 ); float64x2_t vd2_1 = vtrn1q_f64( v4, v5 ); float64x2_t vd0_2 = vtrn2q_f64( v0, v1 ); float64x2_t vd1_2 = vtrn2q_f64( v2, v3 ); float64x2_t vd2_2 = vtrn2q_f64( v4, v5 ); vst1q_f64( p_loc + 0, vd0_1 ); vst1q_f64( p_loc + 2, vd1_1 ); vst1q_f64( p_loc + 4, vd2_1 ); p_loc += ldp; vst1q_f64( p_loc + 0, vd0_2 ); vst1q_f64( p_loc + 2, vd1_2 ); vst1q_f64( p_loc + 4, vd2_2 ); p_loc += ldp; a_loc += 2 * lda; // 2; } for ( ; k_left > 0; --k_left ) { v0 = vld1q_lane_f64( a_loc + inca * 0, v0, 0 ); v0 = vld1q_lane_f64( a_loc + inca * 1, v0, 1 ); v1 = vld1q_lane_f64( a_loc + inca * 2, v1, 0 ); v1 = vld1q_lane_f64( a_loc + inca * 3, v1, 1 ); v2 = vld1q_lane_f64( a_loc + inca * 4, v2, 0 ); v2 = vld1q_lane_f64( a_loc + inca * 5, v2, 1 ); vst1q_f64( p_loc + 0, v0 ); vst1q_f64( p_loc + 2, v1 ); vst1q_f64( p_loc + 4, v2 ); p_loc += ldp; a_loc += lda; // 1; } } } else // if ( !unitk ) { float64x2_t vkappa = vld1q_dup_f64( kappa ); if ( inca == 1 ) { // No need to use k-loops here. // Simply let compiler to expand loops. PRAGMA_UNROLL_2 for ( dim_t ik = k_iter * 2 + k_left; ik > 0; --ik ) { float64x2_t v0 = vld1q_f64( a_loc + 0 ); float64x2_t v1 = vld1q_f64( a_loc + 2 ); float64x2_t v2 = vld1q_f64( a_loc + 4 ); // Scale by kappa. v0 = vmulq_f64( v0, vkappa ); v1 = vmulq_f64( v1, vkappa ); v2 = vmulq_f64( v2, vkappa ); vst1q_f64( p_loc + 0, v0 ); vst1q_f64( p_loc + 2, v1 ); vst1q_f64( p_loc + 4, v2 ); a_loc += lda; p_loc += ldp; } } else // if ( lda == 1 ) { float64x2_t v0 = (float64x2_t)vdupq_n_u64( 0 ); float64x2_t v1 = (float64x2_t)vdupq_n_u64( 0 ); float64x2_t v2 = (float64x2_t)vdupq_n_u64( 0 ); float64x2_t v3 = (float64x2_t)vdupq_n_u64( 0 ); float64x2_t v4 = (float64x2_t)vdupq_n_u64( 0 ); float64x2_t v5 = (float64x2_t)vdupq_n_u64( 0 ); PRAGMA_NOUNROLL for ( ; k_iter > 0; --k_iter ) { v0 = vld1q_f64( a_loc + inca * 0 ); v1 = vld1q_f64( a_loc + inca * 1 ); v2 = vld1q_f64( a_loc + inca * 2 ); v3 = vld1q_f64( a_loc + inca * 3 ); v4 = vld1q_f64( a_loc + inca * 4 ); v5 = vld1q_f64( a_loc + inca * 5 ); // Scale by kappa. v0 = vmulq_f64( v0, vkappa ); v1 = vmulq_f64( v1, vkappa ); v2 = vmulq_f64( v2, vkappa ); v3 = vmulq_f64( v3, vkappa ); v4 = vmulq_f64( v4, vkappa ); v5 = vmulq_f64( v5, vkappa ); // In-register transpose. float64x2_t vd0_1 = vtrn1q_f64( v0, v1 ); float64x2_t vd1_1 = vtrn1q_f64( v2, v3 ); float64x2_t vd2_1 = vtrn1q_f64( v4, v5 ); float64x2_t vd0_2 = vtrn2q_f64( v0, v1 ); float64x2_t vd1_2 = vtrn2q_f64( v2, v3 ); float64x2_t vd2_2 = vtrn2q_f64( v4, v5 ); vst1q_f64( p_loc + 0, vd0_1 ); vst1q_f64( p_loc + 2, vd1_1 ); vst1q_f64( p_loc + 4, vd2_1 ); p_loc += ldp; vst1q_f64( p_loc + 0, vd0_2 ); vst1q_f64( p_loc + 2, vd1_2 ); vst1q_f64( p_loc + 4, vd2_2 ); p_loc += ldp; a_loc += 2 * lda; // 2; } for ( ; k_left > 0; --k_left ) { v0 = vld1q_lane_f64( a_loc + inca * 0, v0, 0 ); v0 = vld1q_lane_f64( a_loc + inca * 1, v0, 1 ); v1 = vld1q_lane_f64( a_loc + inca * 2, v1, 0 ); v1 = vld1q_lane_f64( a_loc + inca * 3, v1, 1 ); v2 = vld1q_lane_f64( a_loc + inca * 4, v2, 0 ); v2 = vld1q_lane_f64( a_loc + inca * 5, v2, 1 ); // Scale by kappa. v0 = vmulq_f64( v0, vkappa ); v1 = vmulq_f64( v1, vkappa ); v2 = vmulq_f64( v2, vkappa ); vst1q_f64( p_loc + 0, v0 ); vst1q_f64( p_loc + 2, v1 ); vst1q_f64( p_loc + 4, v2 ); p_loc += ldp; a_loc += lda; // 1; } } } } else // if ( cdim0 < mnr || gs ) { PASTEMAC(dscal2m,BLIS_TAPI_EX_SUF) ( 0, BLIS_NONUNIT_DIAG, BLIS_DENSE, ( trans_t )conja, cdim0, k0, kappa, a, inca0, lda0, p, 1, ldp0, cntx, NULL ); if ( cdim0 < mnr ) { // Handle zero-filling along the "long" edge of the micropanel. const dim_t i = cdim0; const dim_t m_edge = mnr - cdim0; const dim_t n_edge = k0_max; double* restrict p_edge = p + (i )*1; bli_dset0s_mxn ( m_edge, n_edge, p_edge, 1, ldp ); } } //bli_dfprintm( stdout, "packm 6xk ker: a_packed", cdim0, k0_max, p, 1, ldp0, "%5.2f", "" ); if ( k0 < k0_max ) { // Handle zero-filling along the "short" (far) edge of the micropanel. const dim_t j = k0; const dim_t m_edge = mnr; const dim_t n_edge = k0_max - k0; double* restrict p_edge = p + (j )*ldp; bli_dset0s_mxn ( m_edge, n_edge, p_edge, 1, ldp ); } } blis-0.9.0/kernels/armv8a/1m/bli_packm_armv8a_int_d8xk.c000066400000000000000000000274431422157504600230220ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2020, Linaro Limited 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include #if defined(__clang__) #define PRAGMA_NOUNROLL _Pragma("nounroll") #define PRAGMA_UNROLL_2 _Pragma("unroll 2") #elif defined(__GNUC__) #define PRAGMA_NOUNROLL _Pragma("GCC unroll 1") #define PRAGMA_UNROLL_2 _Pragma("GCC unroll 2") #else #define PRAGMA_NOUNROLL #define PRAGMA_UNROLL_2 #endif void bli_dpackm_armv8a_int_8xk ( conj_t conja, pack_t schema, dim_t cdim0, dim_t k0, dim_t k0_max, double* restrict kappa, double* restrict a, inc_t inca0, inc_t lda0, double* restrict p, inc_t ldp0, cntx_t* restrict cntx ) { // This is the panel dimension assumed by the packm kernel. const dim_t mnr = 8; // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 2; uint64_t k_left = k0 % 2; double* a_loc = a; double* p_loc = p; // NOTE: For the purposes of the comments in this packm kernel, we // interpret inca and lda as rs_a and cs_a, respectively, and similarly // interpret ldp as cs_p (with rs_p implicitly unit). Thus, when reading // this packm kernel, you should think of the operation as packing an // m x n micropanel, where m and n are tiny and large, respectively, and // where elements of each column of the packed matrix P are contiguous. // (This packm kernel can still be used to pack micropanels of matrix B // in a gemm operation.) const uint64_t inca = inca0; const uint64_t lda = lda0; const uint64_t ldp = ldp0; const bool gs = ( inca0 != 1 && lda0 != 1 ); // NOTE: If/when this kernel ever supports scaling by kappa within the // assembly region, this constraint should be lifted. const bool unitk = bli_deq1( *kappa ); // ------------------------------------------------------------------------- if ( cdim0 == mnr && !gs ) { if ( unitk ) { if ( inca == 1 ) { // No need to use k-loops here. // Simply let compiler to expand loops. PRAGMA_UNROLL_2 for ( dim_t ik = k_iter * 2 + k_left; ik > 0; --ik ) { float64x2_t v0 = vld1q_f64( a_loc + 0 ); float64x2_t v1 = vld1q_f64( a_loc + 2 ); float64x2_t v2 = vld1q_f64( a_loc + 4 ); float64x2_t v3 = vld1q_f64( a_loc + 6 ); vst1q_f64( p_loc + 0, v0 ); vst1q_f64( p_loc + 2, v1 ); vst1q_f64( p_loc + 4, v2 ); vst1q_f64( p_loc + 6, v3 ); a_loc += lda; p_loc += ldp; } } else // if ( lda == 1 ) { float64x2_t v0 = (float64x2_t)vdupq_n_u64( 0 ); float64x2_t v1 = (float64x2_t)vdupq_n_u64( 0 ); float64x2_t v2 = (float64x2_t)vdupq_n_u64( 0 ); float64x2_t v3 = (float64x2_t)vdupq_n_u64( 0 ); float64x2_t v4 = (float64x2_t)vdupq_n_u64( 0 ); float64x2_t v5 = (float64x2_t)vdupq_n_u64( 0 ); float64x2_t v6 = (float64x2_t)vdupq_n_u64( 0 ); float64x2_t v7 = (float64x2_t)vdupq_n_u64( 0 ); PRAGMA_NOUNROLL for ( ; k_iter > 0; --k_iter ) { v0 = vld1q_f64( a_loc + inca * 0 ); v1 = vld1q_f64( a_loc + inca * 1 ); v2 = vld1q_f64( a_loc + inca * 2 ); v3 = vld1q_f64( a_loc + inca * 3 ); v4 = vld1q_f64( a_loc + inca * 4 ); v5 = vld1q_f64( a_loc + inca * 5 ); v6 = vld1q_f64( a_loc + inca * 6 ); v7 = vld1q_f64( a_loc + inca * 7 ); // In-register transpose. float64x2_t vd0_1 = vtrn1q_f64( v0, v1 ); float64x2_t vd1_1 = vtrn1q_f64( v2, v3 ); float64x2_t vd2_1 = vtrn1q_f64( v4, v5 ); float64x2_t vd3_1 = vtrn1q_f64( v6, v7 ); float64x2_t vd0_2 = vtrn2q_f64( v0, v1 ); float64x2_t vd1_2 = vtrn2q_f64( v2, v3 ); float64x2_t vd2_2 = vtrn2q_f64( v4, v5 ); float64x2_t vd3_2 = vtrn2q_f64( v6, v7 ); vst1q_f64( p_loc + 0, vd0_1 ); vst1q_f64( p_loc + 2, vd1_1 ); vst1q_f64( p_loc + 4, vd2_1 ); vst1q_f64( p_loc + 6, vd3_1 ); p_loc += ldp; vst1q_f64( p_loc + 0, vd0_2 ); vst1q_f64( p_loc + 2, vd1_2 ); vst1q_f64( p_loc + 4, vd2_2 ); vst1q_f64( p_loc + 6, vd3_2 ); p_loc += ldp; a_loc += 2 * lda; // 2; } for ( ; k_left > 0; --k_left ) { v0 = vld1q_lane_f64( a_loc + inca * 0, v0, 0 ); v0 = vld1q_lane_f64( a_loc + inca * 1, v0, 1 ); v1 = vld1q_lane_f64( a_loc + inca * 2, v1, 0 ); v1 = vld1q_lane_f64( a_loc + inca * 3, v1, 1 ); v2 = vld1q_lane_f64( a_loc + inca * 4, v2, 0 ); v2 = vld1q_lane_f64( a_loc + inca * 5, v2, 1 ); v3 = vld1q_lane_f64( a_loc + inca * 6, v3, 0 ); v3 = vld1q_lane_f64( a_loc + inca * 7, v3, 1 ); vst1q_f64( p_loc + 0, v0 ); vst1q_f64( p_loc + 2, v1 ); vst1q_f64( p_loc + 4, v2 ); vst1q_f64( p_loc + 6, v3 ); p_loc += ldp; a_loc += lda; // 1; } } } else // if ( !unitk ) { float64x2_t vkappa = vld1q_dup_f64( kappa ); if ( inca == 1 ) { // No need to use k-loops here. // Simply let compiler to expand loops. PRAGMA_UNROLL_2 for ( dim_t ik = k_iter * 2 + k_left; ik > 0; --ik ) { float64x2_t v0 = vld1q_f64( a_loc + 0 ); float64x2_t v1 = vld1q_f64( a_loc + 2 ); float64x2_t v2 = vld1q_f64( a_loc + 4 ); float64x2_t v3 = vld1q_f64( a_loc + 6 ); // Scale by kappa. v0 = vmulq_f64( v0, vkappa ); v1 = vmulq_f64( v1, vkappa ); v2 = vmulq_f64( v2, vkappa ); v3 = vmulq_f64( v3, vkappa ); vst1q_f64( p_loc + 0, v0 ); vst1q_f64( p_loc + 2, v1 ); vst1q_f64( p_loc + 4, v2 ); vst1q_f64( p_loc + 6, v3 ); a_loc += lda; p_loc += ldp; } } else // if ( lda == 1 ) { float64x2_t v0 = (float64x2_t)vdupq_n_u64( 0 ); float64x2_t v1 = (float64x2_t)vdupq_n_u64( 0 ); float64x2_t v2 = (float64x2_t)vdupq_n_u64( 0 ); float64x2_t v3 = (float64x2_t)vdupq_n_u64( 0 ); float64x2_t v4 = (float64x2_t)vdupq_n_u64( 0 ); float64x2_t v5 = (float64x2_t)vdupq_n_u64( 0 ); float64x2_t v6 = (float64x2_t)vdupq_n_u64( 0 ); float64x2_t v7 = (float64x2_t)vdupq_n_u64( 0 ); PRAGMA_NOUNROLL for ( ; k_iter > 0; --k_iter ) { v0 = vld1q_f64( a_loc + inca * 0 ); v1 = vld1q_f64( a_loc + inca * 1 ); v2 = vld1q_f64( a_loc + inca * 2 ); v3 = vld1q_f64( a_loc + inca * 3 ); v4 = vld1q_f64( a_loc + inca * 4 ); v5 = vld1q_f64( a_loc + inca * 5 ); v6 = vld1q_f64( a_loc + inca * 6 ); v7 = vld1q_f64( a_loc + inca * 7 ); // Scale by kappa. v0 = vmulq_f64( v0, vkappa ); v1 = vmulq_f64( v1, vkappa ); v2 = vmulq_f64( v2, vkappa ); v3 = vmulq_f64( v3, vkappa ); v4 = vmulq_f64( v4, vkappa ); v5 = vmulq_f64( v5, vkappa ); v6 = vmulq_f64( v6, vkappa ); v7 = vmulq_f64( v7, vkappa ); // In-register transpose. float64x2_t vd0_1 = vtrn1q_f64( v0, v1 ); float64x2_t vd1_1 = vtrn1q_f64( v2, v3 ); float64x2_t vd2_1 = vtrn1q_f64( v4, v5 ); float64x2_t vd3_1 = vtrn1q_f64( v6, v7 ); float64x2_t vd0_2 = vtrn2q_f64( v0, v1 ); float64x2_t vd1_2 = vtrn2q_f64( v2, v3 ); float64x2_t vd2_2 = vtrn2q_f64( v4, v5 ); float64x2_t vd3_2 = vtrn2q_f64( v6, v7 ); vst1q_f64( p_loc + 0, vd0_1 ); vst1q_f64( p_loc + 2, vd1_1 ); vst1q_f64( p_loc + 4, vd2_1 ); vst1q_f64( p_loc + 6, vd3_1 ); p_loc += ldp; vst1q_f64( p_loc + 0, vd0_2 ); vst1q_f64( p_loc + 2, vd1_2 ); vst1q_f64( p_loc + 4, vd2_2 ); vst1q_f64( p_loc + 6, vd3_2 ); p_loc += ldp; a_loc += 2 * lda; // 2; } for ( ; k_left > 0; --k_left ) { v0 = vld1q_lane_f64( a_loc + inca * 0, v0, 0 ); v0 = vld1q_lane_f64( a_loc + inca * 1, v0, 1 ); v1 = vld1q_lane_f64( a_loc + inca * 2, v1, 0 ); v1 = vld1q_lane_f64( a_loc + inca * 3, v1, 1 ); v2 = vld1q_lane_f64( a_loc + inca * 4, v2, 0 ); v2 = vld1q_lane_f64( a_loc + inca * 5, v2, 1 ); v3 = vld1q_lane_f64( a_loc + inca * 6, v3, 0 ); v3 = vld1q_lane_f64( a_loc + inca * 7, v3, 1 ); // Scale by kappa. v0 = vmulq_f64( v0, vkappa ); v1 = vmulq_f64( v1, vkappa ); v2 = vmulq_f64( v2, vkappa ); v3 = vmulq_f64( v3, vkappa ); vst1q_f64( p_loc + 0, v0 ); vst1q_f64( p_loc + 2, v1 ); vst1q_f64( p_loc + 4, v2 ); vst1q_f64( p_loc + 6, v3 ); p_loc += ldp; a_loc += lda; // 1; } } } } else // if ( cdim0 < mnr || gs ) { PASTEMAC(dscal2m,BLIS_TAPI_EX_SUF) ( 0, BLIS_NONUNIT_DIAG, BLIS_DENSE, ( trans_t )conja, cdim0, k0, kappa, a, inca0, lda0, p, 1, ldp0, cntx, NULL ); if ( cdim0 < mnr ) { // Handle zero-filling along the "long" edge of the micropanel. const dim_t i = cdim0; const dim_t m_edge = mnr - cdim0; const dim_t n_edge = k0_max; double* restrict p_edge = p + (i )*1; bli_dset0s_mxn ( m_edge, n_edge, p_edge, 1, ldp ); } } //bli_dfprintm( stdout, "packm 8xk ker: a_packed", cdim0, k0_max, p, 1, ldp0, "%5.2f", "" ); if ( k0 < k0_max ) { // Handle zero-filling along the "short" (far) edge of the micropanel. const dim_t j = k0; const dim_t m_edge = mnr; const dim_t n_edge = k0_max - k0; double* restrict p_edge = p + (j )*ldp; bli_dset0s_mxn ( m_edge, n_edge, p_edge, 1, ldp ); } } blis-0.9.0/kernels/armv8a/1m/bli_packm_armv8a_int_s12xk.c000066400000000000000000000371251422157504600231120ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2020, Linaro Limited 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include #if defined(__clang__) #define PRAGMA_NOUNROLL _Pragma("nounroll") #define PRAGMA_UNROLL_2 _Pragma("unroll 2") #elif defined(__GNUC__) #define PRAGMA_NOUNROLL _Pragma("GCC unroll 1") #define PRAGMA_UNROLL_2 _Pragma("GCC unroll 2") #else #define PRAGMA_NOUNROLL #define PRAGMA_UNROLL_2 #endif void bli_spackm_armv8a_int_12xk ( conj_t conja, pack_t schema, dim_t cdim0, dim_t k0, dim_t k0_max, float* restrict kappa, float* restrict a, inc_t inca0, inc_t lda0, float* restrict p, inc_t ldp0, cntx_t* restrict cntx ) { // This is the panel dimension assumed by the packm kernel. const dim_t mnr = 12; // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; float* a_loc = a; float* p_loc = p; // NOTE: For the purposes of the comments in this packm kernel, we // interpret inca and lda as rs_a and cs_a, respectively, and similarly // interpret ldp as cs_p (with rs_p implicitly unit). Thus, when reading // this packm kernel, you should think of the operation as packing an // m x n micropanel, where m and n are tiny and large, respectively, and // where elements of each column of the packed matrix P are contiguous. // (This packm kernel can still be used to pack micropanels of matrix B // in a gemm operation.) const uint64_t inca = inca0; const uint64_t lda = lda0; const uint64_t ldp = ldp0; const bool gs = ( inca0 != 1 && lda0 != 1 ); // NOTE: If/when this kernel ever supports scaling by kappa within the // assembly region, this constraint should be lifted. const bool unitk = bli_seq1( *kappa ); // ------------------------------------------------------------------------- if ( cdim0 == mnr && !gs ) { if ( unitk ) { if ( inca == 1 ) { // No need to use k-loops here. // Simply let compiler to expand loops. PRAGMA_UNROLL_2 for ( dim_t ik = k_iter * 4 + k_left; ik > 0; --ik ) { float32x4_t v0 = vld1q_f32( a_loc + 0 ); float32x4_t v1 = vld1q_f32( a_loc + 4 ); float32x4_t v2 = vld1q_f32( a_loc + 8 ); vst1q_f32( p_loc + 0, v0 ); vst1q_f32( p_loc + 4, v1 ); vst1q_f32( p_loc + 8, v2 ); a_loc += lda; p_loc += ldp; } } else // if ( lda == 1 ) { float32x4_t v0 = (float32x4_t)vdupq_n_u32( 0 ); float32x4_t v1 = (float32x4_t)vdupq_n_u32( 0 ); float32x4_t v2 = (float32x4_t)vdupq_n_u32( 0 ); float32x4_t v3 = (float32x4_t)vdupq_n_u32( 0 ); float32x4_t v4 = (float32x4_t)vdupq_n_u32( 0 ); float32x4_t v5 = (float32x4_t)vdupq_n_u32( 0 ); float32x4_t v6 = (float32x4_t)vdupq_n_u32( 0 ); float32x4_t v7 = (float32x4_t)vdupq_n_u32( 0 ); float32x4_t v8 = (float32x4_t)vdupq_n_u32( 0 ); float32x4_t v9 = (float32x4_t)vdupq_n_u32( 0 ); float32x4_t v10 = (float32x4_t)vdupq_n_u32( 0 ); float32x4_t v11 = (float32x4_t)vdupq_n_u32( 0 ); float32x4_t vt0; float32x4_t vt1; float32x4_t vt2; float32x4_t vt3; PRAGMA_NOUNROLL for ( ; k_iter > 0; --k_iter ) { v0 = vld1q_f32( a_loc + inca * 0 ); v1 = vld1q_f32( a_loc + inca * 1 ); v2 = vld1q_f32( a_loc + inca * 2 ); v3 = vld1q_f32( a_loc + inca * 3 ); v4 = vld1q_f32( a_loc + inca * 4 ); v5 = vld1q_f32( a_loc + inca * 5 ); v6 = vld1q_f32( a_loc + inca * 6 ); v7 = vld1q_f32( a_loc + inca * 7 ); v8 = vld1q_f32( a_loc + inca * 8 ); v9 = vld1q_f32( a_loc + inca * 9 ); v10 = vld1q_f32( a_loc + inca * 10 ); v11 = vld1q_f32( a_loc + inca * 11 ); // In-register transpose. // // Column 0-3 vt0 = vtrn1q_f32( v0, v1 ); vt1 = vtrn2q_f32( v0, v1 ); vt2 = vtrn1q_f32( v2, v3 ); vt3 = vtrn2q_f32( v2, v3 ); v0 = (float32x4_t)vtrn1q_f64( (float64x2_t)vt0, (float64x2_t)vt2 ); v1 = (float32x4_t)vtrn1q_f64( (float64x2_t)vt1, (float64x2_t)vt3 ); v2 = (float32x4_t)vtrn2q_f64( (float64x2_t)vt0, (float64x2_t)vt2 ); v3 = (float32x4_t)vtrn2q_f64( (float64x2_t)vt1, (float64x2_t)vt3 ); // Column 4-7 vt0 = vtrn1q_f32( v4, v5 ); vt1 = vtrn2q_f32( v4, v5 ); vt2 = vtrn1q_f32( v6, v7 ); vt3 = vtrn2q_f32( v6, v7 ); v4 = (float32x4_t)vtrn1q_f64( (float64x2_t)vt0, (float64x2_t)vt2 ); v5 = (float32x4_t)vtrn1q_f64( (float64x2_t)vt1, (float64x2_t)vt3 ); v6 = (float32x4_t)vtrn2q_f64( (float64x2_t)vt0, (float64x2_t)vt2 ); v7 = (float32x4_t)vtrn2q_f64( (float64x2_t)vt1, (float64x2_t)vt3 ); // Column 8-11 vt0 = vtrn1q_f32( v8, v9 ); vt1 = vtrn2q_f32( v8, v9 ); vt2 = vtrn1q_f32( v10, v11 ); vt3 = vtrn2q_f32( v10, v11 ); v8 = (float32x4_t)vtrn1q_f64( (float64x2_t)vt0, (float64x2_t)vt2 ); v9 = (float32x4_t)vtrn1q_f64( (float64x2_t)vt1, (float64x2_t)vt3 ); v10 = (float32x4_t)vtrn2q_f64( (float64x2_t)vt0, (float64x2_t)vt2 ); v11 = (float32x4_t)vtrn2q_f64( (float64x2_t)vt1, (float64x2_t)vt3 ); vst1q_f32( p_loc + 0, v0 ); vst1q_f32( p_loc + 4, v4 ); vst1q_f32( p_loc + 8, v8 ); p_loc += ldp; vst1q_f32( p_loc + 0, v1 ); vst1q_f32( p_loc + 4, v5 ); vst1q_f32( p_loc + 8, v9 ); p_loc += ldp; vst1q_f32( p_loc + 0, v2 ); vst1q_f32( p_loc + 4, v6 ); vst1q_f32( p_loc + 8, v10 ); p_loc += ldp; vst1q_f32( p_loc + 0, v3 ); vst1q_f32( p_loc + 4, v7 ); vst1q_f32( p_loc + 8, v11 ); p_loc += ldp; a_loc += 4 * lda; // 4; } for ( ; k_left > 0; --k_left ) { v0 = vld1q_lane_f32( a_loc + inca * 0 , v0, 0 ); v0 = vld1q_lane_f32( a_loc + inca * 1 , v0, 1 ); v0 = vld1q_lane_f32( a_loc + inca * 2 , v0, 2 ); v0 = vld1q_lane_f32( a_loc + inca * 3 , v0, 3 ); v1 = vld1q_lane_f32( a_loc + inca * 4 , v1, 0 ); v1 = vld1q_lane_f32( a_loc + inca * 5 , v1, 1 ); v1 = vld1q_lane_f32( a_loc + inca * 6 , v1, 2 ); v1 = vld1q_lane_f32( a_loc + inca * 7 , v1, 3 ); v2 = vld1q_lane_f32( a_loc + inca * 8 , v2, 0 ); v2 = vld1q_lane_f32( a_loc + inca * 9 , v2, 1 ); v2 = vld1q_lane_f32( a_loc + inca * 10, v2, 2 ); v2 = vld1q_lane_f32( a_loc + inca * 11, v2, 3 ); vst1q_f32( p_loc + 0, v0 ); vst1q_f32( p_loc + 4, v1 ); vst1q_f32( p_loc + 8, v2 ); p_loc += ldp; a_loc += lda; // 1; } } } else // if ( !unitk ) { float32x4_t vkappa = vld1q_dup_f32( kappa ); if ( inca == 1 ) { // No need to use k-loops here. // Simply let compiler to expand loops. PRAGMA_UNROLL_2 for ( dim_t ik = k_iter * 4 + k_left; ik > 0; --ik ) { float32x4_t v0 = vld1q_f32( a_loc + 0 ); float32x4_t v1 = vld1q_f32( a_loc + 4 ); float32x4_t v2 = vld1q_f32( a_loc + 8 ); // Scale by kappa. v0 = vmulq_f32( v0, vkappa ); v1 = vmulq_f32( v1, vkappa ); v2 = vmulq_f32( v2, vkappa ); vst1q_f32( p_loc + 0, v0 ); vst1q_f32( p_loc + 4, v1 ); vst1q_f32( p_loc + 8, v2 ); a_loc += lda; p_loc += ldp; } } else // if ( lda == 1 ) { float32x4_t v0 = (float32x4_t)vdupq_n_u32( 0 ); float32x4_t v1 = (float32x4_t)vdupq_n_u32( 0 ); float32x4_t v2 = (float32x4_t)vdupq_n_u32( 0 ); float32x4_t v3 = (float32x4_t)vdupq_n_u32( 0 ); float32x4_t v4 = (float32x4_t)vdupq_n_u32( 0 ); float32x4_t v5 = (float32x4_t)vdupq_n_u32( 0 ); float32x4_t v6 = (float32x4_t)vdupq_n_u32( 0 ); float32x4_t v7 = (float32x4_t)vdupq_n_u32( 0 ); float32x4_t v8 = (float32x4_t)vdupq_n_u32( 0 ); float32x4_t v9 = (float32x4_t)vdupq_n_u32( 0 ); float32x4_t v10 = (float32x4_t)vdupq_n_u32( 0 ); float32x4_t v11 = (float32x4_t)vdupq_n_u32( 0 ); float32x4_t vt0; float32x4_t vt1; float32x4_t vt2; float32x4_t vt3; PRAGMA_NOUNROLL for ( ; k_iter > 0; --k_iter ) { v0 = vld1q_f32( a_loc + inca * 0 ); v1 = vld1q_f32( a_loc + inca * 1 ); v2 = vld1q_f32( a_loc + inca * 2 ); v3 = vld1q_f32( a_loc + inca * 3 ); v4 = vld1q_f32( a_loc + inca * 4 ); v5 = vld1q_f32( a_loc + inca * 5 ); v6 = vld1q_f32( a_loc + inca * 6 ); v7 = vld1q_f32( a_loc + inca * 7 ); v8 = vld1q_f32( a_loc + inca * 8 ); v9 = vld1q_f32( a_loc + inca * 9 ); v10 = vld1q_f32( a_loc + inca * 10 ); v11 = vld1q_f32( a_loc + inca * 11 ); // Scale by kappa. v0 = vmulq_f32( v0, vkappa ); v1 = vmulq_f32( v1, vkappa ); v2 = vmulq_f32( v2, vkappa ); v3 = vmulq_f32( v3, vkappa ); v4 = vmulq_f32( v4, vkappa ); v5 = vmulq_f32( v5, vkappa ); v6 = vmulq_f32( v6, vkappa ); v7 = vmulq_f32( v7, vkappa ); v8 = vmulq_f32( v8, vkappa ); v9 = vmulq_f32( v9, vkappa ); v10 = vmulq_f32( v10, vkappa ); v11 = vmulq_f32( v11, vkappa ); // In-register transpose. // // Column 0-3 vt0 = vtrn1q_f32( v0, v1 ); vt1 = vtrn2q_f32( v0, v1 ); vt2 = vtrn1q_f32( v2, v3 ); vt3 = vtrn2q_f32( v2, v3 ); v0 = (float32x4_t)vtrn1q_f64( (float64x2_t)vt0, (float64x2_t)vt2 ); v1 = (float32x4_t)vtrn1q_f64( (float64x2_t)vt1, (float64x2_t)vt3 ); v2 = (float32x4_t)vtrn2q_f64( (float64x2_t)vt0, (float64x2_t)vt2 ); v3 = (float32x4_t)vtrn2q_f64( (float64x2_t)vt1, (float64x2_t)vt3 ); // Column 4-7 vt0 = vtrn1q_f32( v4, v5 ); vt1 = vtrn2q_f32( v4, v5 ); vt2 = vtrn1q_f32( v6, v7 ); vt3 = vtrn2q_f32( v6, v7 ); v4 = (float32x4_t)vtrn1q_f64( (float64x2_t)vt0, (float64x2_t)vt2 ); v5 = (float32x4_t)vtrn1q_f64( (float64x2_t)vt1, (float64x2_t)vt3 ); v6 = (float32x4_t)vtrn2q_f64( (float64x2_t)vt0, (float64x2_t)vt2 ); v7 = (float32x4_t)vtrn2q_f64( (float64x2_t)vt1, (float64x2_t)vt3 ); // Column 8-11 vt0 = vtrn1q_f32( v8, v9 ); vt1 = vtrn2q_f32( v8, v9 ); vt2 = vtrn1q_f32( v10, v11 ); vt3 = vtrn2q_f32( v10, v11 ); v8 = (float32x4_t)vtrn1q_f64( (float64x2_t)vt0, (float64x2_t)vt2 ); v9 = (float32x4_t)vtrn1q_f64( (float64x2_t)vt1, (float64x2_t)vt3 ); v10 = (float32x4_t)vtrn2q_f64( (float64x2_t)vt0, (float64x2_t)vt2 ); v11 = (float32x4_t)vtrn2q_f64( (float64x2_t)vt1, (float64x2_t)vt3 ); vst1q_f32( p_loc + 0, v0 ); vst1q_f32( p_loc + 4, v4 ); vst1q_f32( p_loc + 8, v8 ); p_loc += ldp; vst1q_f32( p_loc + 0, v1 ); vst1q_f32( p_loc + 4, v5 ); vst1q_f32( p_loc + 8, v9 ); p_loc += ldp; vst1q_f32( p_loc + 0, v2 ); vst1q_f32( p_loc + 4, v6 ); vst1q_f32( p_loc + 8, v10 ); p_loc += ldp; vst1q_f32( p_loc + 0, v3 ); vst1q_f32( p_loc + 4, v7 ); vst1q_f32( p_loc + 8, v11 ); p_loc += ldp; a_loc += 4 * lda; // 4; } for ( ; k_left > 0; --k_left ) { v0 = vld1q_lane_f32( a_loc + inca * 0 , v0, 0 ); v0 = vld1q_lane_f32( a_loc + inca * 1 , v0, 1 ); v0 = vld1q_lane_f32( a_loc + inca * 2 , v0, 2 ); v0 = vld1q_lane_f32( a_loc + inca * 3 , v0, 3 ); v1 = vld1q_lane_f32( a_loc + inca * 4 , v1, 0 ); v1 = vld1q_lane_f32( a_loc + inca * 5 , v1, 1 ); v1 = vld1q_lane_f32( a_loc + inca * 6 , v1, 2 ); v1 = vld1q_lane_f32( a_loc + inca * 7 , v1, 3 ); v2 = vld1q_lane_f32( a_loc + inca * 8 , v2, 0 ); v2 = vld1q_lane_f32( a_loc + inca * 9 , v2, 1 ); v2 = vld1q_lane_f32( a_loc + inca * 10, v2, 2 ); v2 = vld1q_lane_f32( a_loc + inca * 11, v2, 3 ); // Scale by kappa. v0 = vmulq_f32( v0, vkappa ); v1 = vmulq_f32( v1, vkappa ); v2 = vmulq_f32( v2, vkappa ); vst1q_f32( p_loc + 0, v0 ); vst1q_f32( p_loc + 4, v1 ); vst1q_f32( p_loc + 8, v2 ); p_loc += ldp; a_loc += lda; // 1; } } } } else // if ( cdim0 < mnr || gs ) { PASTEMAC(sscal2m,BLIS_TAPI_EX_SUF) ( 0, BLIS_NONUNIT_DIAG, BLIS_DENSE, ( trans_t )conja, cdim0, k0, kappa, a, inca0, lda0, p, 1, ldp0, cntx, NULL ); if ( cdim0 < mnr ) { // Handle zero-filling along the "long" edge of the micropanel. const dim_t i = cdim0; const dim_t m_edge = mnr - cdim0; const dim_t n_edge = k0_max; float* restrict p_edge = p + (i )*1; bli_sset0s_mxn ( m_edge, n_edge, p_edge, 1, ldp ); } } if ( k0 < k0_max ) { // Handle zero-filling along the "short" (far) edge of the micropanel. const dim_t j = k0; const dim_t m_edge = mnr; const dim_t n_edge = k0_max - k0; float* restrict p_edge = p + (j )*ldp; bli_sset0s_mxn ( m_edge, n_edge, p_edge, 1, ldp ); } } blis-0.9.0/kernels/armv8a/1m/bli_packm_armv8a_int_s8xk.c000066400000000000000000000307771422157504600230450ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2020, Linaro Limited 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include #if defined(__clang__) #define PRAGMA_NOUNROLL _Pragma("nounroll") #define PRAGMA_UNROLL_4 _Pragma("unroll 4") #elif defined(__GNUC__) #define PRAGMA_NOUNROLL _Pragma("GCC unroll 1") #define PRAGMA_UNROLL_4 _Pragma("GCC unroll 4") #else #define PRAGMA_NOUNROLL #define PRAGMA_UNROLL_4 #endif void bli_spackm_armv8a_int_8xk ( conj_t conja, pack_t schema, dim_t cdim0, dim_t k0, dim_t k0_max, float* restrict kappa, float* restrict a, inc_t inca0, inc_t lda0, float* restrict p, inc_t ldp0, cntx_t* restrict cntx ) { // This is the panel dimension assumed by the packm kernel. const dim_t mnr = 8; // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; float* a_loc = a; float* p_loc = p; // NOTE: For the purposes of the comments in this packm kernel, we // interpret inca and lda as rs_a and cs_a, respectively, and similarly // interpret ldp as cs_p (with rs_p implicitly unit). Thus, when reading // this packm kernel, you should think of the operation as packing an // m x n micropanel, where m and n are tiny and large, respectively, and // where elements of each column of the packed matrix P are contiguous. // (This packm kernel can still be used to pack micropanels of matrix B // in a gemm operation.) const uint64_t inca = inca0; const uint64_t lda = lda0; const uint64_t ldp = ldp0; const bool gs = ( inca0 != 1 && lda0 != 1 ); // NOTE: If/when this kernel ever supports scaling by kappa within the // assembly region, this constraint should be lifted. const bool unitk = bli_seq1( *kappa ); // ------------------------------------------------------------------------- if ( cdim0 == mnr && !gs ) { if ( unitk ) { if ( inca == 1 ) { // No need to use k-loops here. // Simply let compiler to expand loops. PRAGMA_UNROLL_4 for ( dim_t ik = k_iter * 4 + k_left; ik > 0; --ik ) { float32x4_t v0 = vld1q_f32( a_loc + 0 ); float32x4_t v1 = vld1q_f32( a_loc + 4 ); vst1q_f32( p_loc + 0, v0 ); vst1q_f32( p_loc + 4, v1 ); a_loc += lda; p_loc += ldp; } } else // if ( lda == 1 ) { float32x4_t v0 = (float32x4_t)vdupq_n_u32( 0 ); float32x4_t v1 = (float32x4_t)vdupq_n_u32( 0 ); float32x4_t v2 = (float32x4_t)vdupq_n_u32( 0 ); float32x4_t v3 = (float32x4_t)vdupq_n_u32( 0 ); float32x4_t v4 = (float32x4_t)vdupq_n_u32( 0 ); float32x4_t v5 = (float32x4_t)vdupq_n_u32( 0 ); float32x4_t v6 = (float32x4_t)vdupq_n_u32( 0 ); float32x4_t v7 = (float32x4_t)vdupq_n_u32( 0 ); float32x4_t vt0; float32x4_t vt1; float32x4_t vt2; float32x4_t vt3; PRAGMA_NOUNROLL for ( ; k_iter > 0; --k_iter ) { v0 = vld1q_f32( a_loc + inca * 0 ); v1 = vld1q_f32( a_loc + inca * 1 ); v2 = vld1q_f32( a_loc + inca * 2 ); v3 = vld1q_f32( a_loc + inca * 3 ); v4 = vld1q_f32( a_loc + inca * 4 ); v5 = vld1q_f32( a_loc + inca * 5 ); v6 = vld1q_f32( a_loc + inca * 6 ); v7 = vld1q_f32( a_loc + inca * 7 ); // In-register transpose. // // Column 0-3 vt0 = vtrn1q_f32( v0, v1 ); vt1 = vtrn2q_f32( v0, v1 ); vt2 = vtrn1q_f32( v2, v3 ); vt3 = vtrn2q_f32( v2, v3 ); v0 = (float32x4_t)vtrn1q_f64( (float64x2_t)vt0, (float64x2_t)vt2 ); v1 = (float32x4_t)vtrn1q_f64( (float64x2_t)vt1, (float64x2_t)vt3 ); v2 = (float32x4_t)vtrn2q_f64( (float64x2_t)vt0, (float64x2_t)vt2 ); v3 = (float32x4_t)vtrn2q_f64( (float64x2_t)vt1, (float64x2_t)vt3 ); // Column 4-7 vt0 = vtrn1q_f32( v4, v5 ); vt1 = vtrn2q_f32( v4, v5 ); vt2 = vtrn1q_f32( v6, v7 ); vt3 = vtrn2q_f32( v6, v7 ); v4 = (float32x4_t)vtrn1q_f64( (float64x2_t)vt0, (float64x2_t)vt2 ); v5 = (float32x4_t)vtrn1q_f64( (float64x2_t)vt1, (float64x2_t)vt3 ); v6 = (float32x4_t)vtrn2q_f64( (float64x2_t)vt0, (float64x2_t)vt2 ); v7 = (float32x4_t)vtrn2q_f64( (float64x2_t)vt1, (float64x2_t)vt3 ); vst1q_f32( p_loc + 0, v0 ); vst1q_f32( p_loc + 4, v4 ); p_loc += ldp; vst1q_f32( p_loc + 0, v1 ); vst1q_f32( p_loc + 4, v5 ); p_loc += ldp; vst1q_f32( p_loc + 0, v2 ); vst1q_f32( p_loc + 4, v6 ); p_loc += ldp; vst1q_f32( p_loc + 0, v3 ); vst1q_f32( p_loc + 4, v7 ); p_loc += ldp; a_loc += 4 * lda; // 4; } for ( ; k_left > 0; --k_left ) { v0 = vld1q_lane_f32( a_loc + inca * 0 , v0, 0 ); v0 = vld1q_lane_f32( a_loc + inca * 1 , v0, 1 ); v0 = vld1q_lane_f32( a_loc + inca * 2 , v0, 2 ); v0 = vld1q_lane_f32( a_loc + inca * 3 , v0, 3 ); v1 = vld1q_lane_f32( a_loc + inca * 4 , v1, 0 ); v1 = vld1q_lane_f32( a_loc + inca * 5 , v1, 1 ); v1 = vld1q_lane_f32( a_loc + inca * 6 , v1, 2 ); v1 = vld1q_lane_f32( a_loc + inca * 7 , v1, 3 ); vst1q_f32( p_loc + 0, v0 ); vst1q_f32( p_loc + 4, v1 ); p_loc += ldp; a_loc += lda; // 1; } } } else // if ( !unitk ) { float32x4_t vkappa = vld1q_dup_f32( kappa ); if ( inca == 1 ) { // No need to use k-loops here. // Simply let compiler to expand loops. PRAGMA_UNROLL_4 for ( dim_t ik = k_iter * 4 + k_left; ik > 0; --ik ) { float32x4_t v0 = vld1q_f32( a_loc + 0 ); float32x4_t v1 = vld1q_f32( a_loc + 4 ); // Scale by kappa. v0 = vmulq_f32( v0, vkappa ); v1 = vmulq_f32( v1, vkappa ); vst1q_f32( p_loc + 0, v0 ); vst1q_f32( p_loc + 4, v1 ); a_loc += lda; p_loc += ldp; } } else // if ( lda == 1 ) { float32x4_t v0 = (float32x4_t)vdupq_n_u32( 0 ); float32x4_t v1 = (float32x4_t)vdupq_n_u32( 0 ); float32x4_t v2 = (float32x4_t)vdupq_n_u32( 0 ); float32x4_t v3 = (float32x4_t)vdupq_n_u32( 0 ); float32x4_t v4 = (float32x4_t)vdupq_n_u32( 0 ); float32x4_t v5 = (float32x4_t)vdupq_n_u32( 0 ); float32x4_t v6 = (float32x4_t)vdupq_n_u32( 0 ); float32x4_t v7 = (float32x4_t)vdupq_n_u32( 0 ); float32x4_t vt0; float32x4_t vt1; float32x4_t vt2; float32x4_t vt3; PRAGMA_NOUNROLL for ( ; k_iter > 0; --k_iter ) { v0 = vld1q_f32( a_loc + inca * 0 ); v1 = vld1q_f32( a_loc + inca * 1 ); v2 = vld1q_f32( a_loc + inca * 2 ); v3 = vld1q_f32( a_loc + inca * 3 ); v4 = vld1q_f32( a_loc + inca * 4 ); v5 = vld1q_f32( a_loc + inca * 5 ); v6 = vld1q_f32( a_loc + inca * 6 ); v7 = vld1q_f32( a_loc + inca * 7 ); // Scale by kappa. v0 = vmulq_f32( v0, vkappa ); v1 = vmulq_f32( v1, vkappa ); v2 = vmulq_f32( v2, vkappa ); v3 = vmulq_f32( v3, vkappa ); v4 = vmulq_f32( v4, vkappa ); v5 = vmulq_f32( v5, vkappa ); v6 = vmulq_f32( v6, vkappa ); v7 = vmulq_f32( v7, vkappa ); // In-register transpose. // // Column 0-3 vt0 = vtrn1q_f32( v0, v1 ); vt1 = vtrn2q_f32( v0, v1 ); vt2 = vtrn1q_f32( v2, v3 ); vt3 = vtrn2q_f32( v2, v3 ); v0 = (float32x4_t)vtrn1q_f64( (float64x2_t)vt0, (float64x2_t)vt2 ); v1 = (float32x4_t)vtrn1q_f64( (float64x2_t)vt1, (float64x2_t)vt3 ); v2 = (float32x4_t)vtrn2q_f64( (float64x2_t)vt0, (float64x2_t)vt2 ); v3 = (float32x4_t)vtrn2q_f64( (float64x2_t)vt1, (float64x2_t)vt3 ); // Column 4-7 vt0 = vtrn1q_f32( v4, v5 ); vt1 = vtrn2q_f32( v4, v5 ); vt2 = vtrn1q_f32( v6, v7 ); vt3 = vtrn2q_f32( v6, v7 ); v4 = (float32x4_t)vtrn1q_f64( (float64x2_t)vt0, (float64x2_t)vt2 ); v5 = (float32x4_t)vtrn1q_f64( (float64x2_t)vt1, (float64x2_t)vt3 ); v6 = (float32x4_t)vtrn2q_f64( (float64x2_t)vt0, (float64x2_t)vt2 ); v7 = (float32x4_t)vtrn2q_f64( (float64x2_t)vt1, (float64x2_t)vt3 ); vst1q_f32( p_loc + 0, v0 ); vst1q_f32( p_loc + 4, v4 ); p_loc += ldp; vst1q_f32( p_loc + 0, v1 ); vst1q_f32( p_loc + 4, v5 ); p_loc += ldp; vst1q_f32( p_loc + 0, v2 ); vst1q_f32( p_loc + 4, v6 ); p_loc += ldp; vst1q_f32( p_loc + 0, v3 ); vst1q_f32( p_loc + 4, v7 ); p_loc += ldp; a_loc += 4 * lda; // 4; } for ( ; k_left > 0; --k_left ) { v0 = vld1q_lane_f32( a_loc + inca * 0 , v0, 0 ); v0 = vld1q_lane_f32( a_loc + inca * 1 , v0, 1 ); v0 = vld1q_lane_f32( a_loc + inca * 2 , v0, 2 ); v0 = vld1q_lane_f32( a_loc + inca * 3 , v0, 3 ); v1 = vld1q_lane_f32( a_loc + inca * 4 , v1, 0 ); v1 = vld1q_lane_f32( a_loc + inca * 5 , v1, 1 ); v1 = vld1q_lane_f32( a_loc + inca * 6 , v1, 2 ); v1 = vld1q_lane_f32( a_loc + inca * 7 , v1, 3 ); // Scale by kappa. v0 = vmulq_f32( v0, vkappa ); v1 = vmulq_f32( v1, vkappa ); vst1q_f32( p_loc + 0, v0 ); vst1q_f32( p_loc + 4, v1 ); p_loc += ldp; a_loc += lda; // 1; } } } } else // if ( cdim0 < mnr || gs ) { PASTEMAC(sscal2m,BLIS_TAPI_EX_SUF) ( 0, BLIS_NONUNIT_DIAG, BLIS_DENSE, ( trans_t )conja, cdim0, k0, kappa, a, inca0, lda0, p, 1, ldp0, cntx, NULL ); if ( cdim0 < mnr ) { // Handle zero-filling along the "long" edge of the micropanel. const dim_t i = cdim0; const dim_t m_edge = mnr - cdim0; const dim_t n_edge = k0_max; float* restrict p_edge = p + (i )*1; bli_sset0s_mxn ( m_edge, n_edge, p_edge, 1, ldp ); } } if ( k0 < k0_max ) { // Handle zero-filling along the "short" (far) edge of the micropanel. const dim_t j = k0; const dim_t m_edge = mnr; const dim_t n_edge = k0_max - k0; float* restrict p_edge = p + (j )*ldp; bli_sset0s_mxn ( m_edge, n_edge, p_edge, 1, ldp ); } } blis-0.9.0/kernels/armv8a/3/000077500000000000000000000000001422157504600154625ustar00rootroot00000000000000blis-0.9.0/kernels/armv8a/3/armv8a_asm_d2x2.h000066400000000000000000000042231422157504600205310ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2021, The University of Tokyo 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ /* C A B * || <- | * -- * || | * * or: * C B * A * -- <- | -- * -- | */ #define DGEMM_2X2_NANOKERNEL(C0,C1,A,B) \ " fmla v"#C0".2d, v"#A".2d, v"#B".d[0] \n\t" \ " fmla v"#C1".2d, v"#A".2d, v"#B".d[1] \n\t" #define SGEMM_4X4_NANOKERNEL(C0,C1,C2,C3,A,B) \ " fmla v"#C0".4s, v"#A".4s, v"#B".s[0] \n\t" \ " fmla v"#C1".4s, v"#A".4s, v"#B".s[1] \n\t" \ " fmla v"#C2".4s, v"#A".4s, v"#B".s[2] \n\t" \ " fmla v"#C3".4s, v"#A".4s, v"#B".s[3] \n\t" blis-0.9.0/kernels/armv8a/3/armv8a_asm_utils.h000066400000000000000000000101331422157504600211070ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2021, The University of Tokyo 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // Apple/Clang's local label requirements. #if defined(__APPLE__) || defined(__clang__) #define LABEL(str) " L" #str"%=: \n\t" #define BEQ(str) "b.eq L" #str"%= \n\t" #define BNE(str) "b.ne L" #str"%= \n\t" #define BRANCH(str) "b L" #str"%= \n\t" #else #define LABEL(str) " ." #str": \n\t" #define BEQ(str) "b.eq ." #str" \n\t" #define BNE(str) "b.ne ." #str" \n\t" #define BRANCH(str) "b ." #str" \n\t" #endif // Clear vectors. #define CLEAR1V(V) \ " dup v"#V".2d, xzr \n\t" #define CLEAR2V(V0,V1) \ CLEAR1V(V0) \ CLEAR1V(V1) #define CLEAR4V(V0,V1,V2,V3) \ CLEAR2V(V0,V1) \ CLEAR2V(V2,V3) #define CLEAR8V(V0,V1,V2,V3,V4,V5,V6,V7) \ CLEAR4V(V0,V1,V2,V3) \ CLEAR4V(V4,V5,V6,V7) // Scale vectors. #define DSCALE1V(V,A,IDX) \ " fmul v"#V".2d, v"#V".2d, v"#A".d["#IDX"] \n\t" #define DSCALE2V(V0,V1,A,IDX) \ DSCALE1V(V0,A,IDX) \ DSCALE1V(V1,A,IDX) #define DSCALE4V(V0,V1,V2,V3,A,IDX) \ DSCALE2V(V0,V1,A,IDX) \ DSCALE2V(V2,V3,A,IDX) #define DSCALE8V(V0,V1,V2,V3,V4,V5,V6,V7,A,IDX) \ DSCALE4V(V0,V1,V2,V3,A,IDX) \ DSCALE4V(V4,V5,V6,V7,A,IDX) // Scale-accumulate. #define DSCALEA1V(D,S,A,IDX) \ " fmla v"#D".2d, v"#S".2d, v"#A".d["#IDX"] \n\t" #define DSCALEA2V(D0,D1,S0,S1,A,IDX) \ DSCALEA1V(D0,S0,A,IDX) \ DSCALEA1V(D1,S1,A,IDX) #define DSCALEA4V(D0,D1,D2,D3,S0,S1,S2,S3,A,IDX) \ DSCALEA2V(D0,D1,S0,S1,A,IDX) \ DSCALEA2V(D2,D3,S2,S3,A,IDX) #define DSCALEA8V(D0,D1,D2,D3,D4,D5,D6,D7,S0,S1,S2,S3,S4,S5,S6,S7,A,IDX) \ DSCALEA4V(D0,D1,D2,D3,S0,S1,S2,S3,A,IDX) \ DSCALEA4V(D4,D5,D6,D7,S4,S5,S6,S7,A,IDX) // Load one line. #define DLOAD1V(V,ADDR,SHIFT) \ " ldr q"#V", ["#ADDR", #"#SHIFT"] \n\t" #define DLOAD2V(V0,V1,ADDR,SHIFT) \ DLOAD1V(V0,ADDR,SHIFT) \ DLOAD1V(V1,ADDR,SHIFT+16) #define DLOAD4V(V0,V1,V2,V3,ADDR,SHIFT) \ DLOAD2V(V0,V1,ADDR,SHIFT) \ DLOAD2V(V2,V3,ADDR,SHIFT+32) // Generic: load one line. #define DLOAD1V_GATHER_ELMFWD(V,ADDR,INC) \ " ld1 {v"#V".d}[0], ["#ADDR"], "#INC" \n\t" \ " ld1 {v"#V".d}[1], ["#ADDR"], "#INC" \n\t" // Store one line. #define DSTORE1V(V,ADDR,SHIFT) \ " str q"#V", ["#ADDR", #"#SHIFT"] \n\t" #define DSTORE2V(V0,V1,ADDR,SHIFT) \ DSTORE1V(V0,ADDR,SHIFT) \ DSTORE1V(V1,ADDR,SHIFT+16) #define DSTORE4V(V0,V1,V2,V3,ADDR,SHIFT) \ DSTORE2V(V0,V1,ADDR,SHIFT) \ DSTORE2V(V2,V3,ADDR,SHIFT+32) // Generic: store one line. #define DSTORE1V_SCATTER_ELMFWD(V,ADDR,INC) \ " st1 {v"#V".d}[0], ["#ADDR"], "#INC" \n\t" \ " st1 {v"#V".d}[1], ["#ADDR"], "#INC" \n\t" blis-0.9.0/kernels/armv8a/3/bli_gemm_armv8a_asm_d6x8.c000066400000000000000000002474251422157504600224060ustar00rootroot00000000000000 /* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "armv8a_asm_utils.h" /* o 4x4 Single precision micro-kernel fully functional. o Runnable on ARMv8, compiled with aarch64 GCC. o Use it together with the armv8 BLIS configuration. o Tested on Juno board. Around 7.3 GFLOPS @ 1.1 GHz. December 2014. * UPDATE NOVEMBER 2015 * Micro-kernel changed to 8x12 * Tested on Juno Board. Around 8.1 GFLOPS, 1 x A57 core @ 1.1 GHz. * Tested on Juno Board. Around 15.9 GFLOPS, 2 x A57 cores @ 1.1 GHz. * Tested on Juno board. Around 3.1 GFLOPS, 1 x A53 core @ 850 MHz. * Tested on Juno board. Around 12 GFLOPS, 4 x A53 cores @ 850 MHz. */ void bli_sgemm_armv8a_asm_8x12 ( dim_t m, dim_t n, dim_t k, float* restrict alpha, float* restrict a, float* restrict b, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { void* a_next = bli_auxinfo_next_a( data ); void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k / 4; uint64_t k_left = k % 4; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; GEMM_UKR_SETUP_CT( s, 8, 12, false ); __asm__ volatile ( " \n\t" " \n\t" " ldr x0,%[aaddr] \n\t" // Load address of A. " ldr x1,%[baddr] \n\t" // Load address of B. " ldr x2,%[caddr] \n\t" // Load address of C. " \n\t" " ldr x5,%[k_iter] \n\t" // Number of unrolled iterations (k_iter). " ldr x6,%[k_left] \n\t" // Number of remaining iterations (k_left). " \n\t" " ldr x10,%[cs_c] \n\t" // Load cs_c. " lsl x10,x10,#2 \n\t" // cs_c * sizeof(float) -- AUX. " \n\t" // " ldr x14,%[rs_c] \n\t" // Load rs_c. // " lsl x14,x14,#2 \n\t" // rs_c * sizeof(float). " \n\t" " add x16,x2,x10 \n\t" //Load address Column 1 of C " add x17,x16,x10 \n\t" //Load address Column 2 of C " add x19,x17,x10 \n\t" //Load address Column 3 of C " add x20,x19,x10 \n\t" //Load address Column 4 of C " add x21,x20,x10 \n\t" //Load address Column 5 of C " add x22,x21,x10 \n\t" //Load address Column 6 of C " add x23,x22,x10 \n\t" //Load address Column 7 of C " add x24,x23,x10 \n\t" //Load address Column 8 of C " add x25,x24,x10 \n\t" //Load address Column 9 of C " add x26,x25,x10 \n\t" //Load address Column 10 of C " add x27,x26,x10 \n\t" //Load address Column 11 of C " \n\t" " prfm pldl1keep,[x2] \n\t" // Prefetch c. " prfm pldl1keep,[x16] \n\t" // Prefetch c. " prfm pldl1keep,[x17] \n\t" // Prefetch c. " prfm pldl1keep,[x19] \n\t" // Prefetch c. " prfm pldl1keep,[x20] \n\t" // Prefetch c. " prfm pldl1keep,[x21] \n\t" // Prefetch c. " prfm pldl1keep,[x22] \n\t" // Prefetch c. " prfm pldl1keep,[x23] \n\t" // Prefetch c. " prfm pldl1keep,[x24] \n\t" // Prefetch c. " prfm pldl1keep,[x25] \n\t" // Prefetch c. " prfm pldl1keep,[x26] \n\t" // Prefetch c. " prfm pldl1keep,[x27] \n\t" // Prefetch c. " \n\t" " dup v8.4s, wzr \n\t" // Vector for accummulating column 0 " prfm PLDL1KEEP, [x1, #192] \n\t" " dup v9.4s, wzr \n\t" // Vector for accummulating column 0 " prfm PLDL1KEEP, [x1, #256] \n\t" " dup v10.4s, wzr \n\t" // Vector for accummulating column 1 " prfm PLDL1KEEP, [x1, #320] \n\t" " dup v11.4s, wzr \n\t" // Vector for accummulating column 1 " dup v12.4s, wzr \n\t" // Vector for accummulating column 2 " dup v13.4s, wzr \n\t" // Vector for accummulating column 2 " \n\t" " dup v14.4s, wzr \n\t" // Vector for accummulating column 3 " prfm PLDL1KEEP, [x0, #128] \n\t" " dup v15.4s, wzr \n\t" // Vector for accummulating column 3 " prfm PLDL1KEEP, [x0, #192] \n\t" " dup v16.4s, wzr \n\t" // Vector for accummulating column 4 " dup v17.4s, wzr \n\t" // Vector for accummulating column 4 " dup v18.4s, wzr \n\t" // Vector for accummulating column 5 " dup v19.4s, wzr \n\t" // Vector for accummulating column 5 " \n\t" " dup v20.4s, wzr \n\t" // Vector for accummulating column 6 " dup v21.4s, wzr \n\t" // Vector for accummulating column 6 " dup v22.4s, wzr \n\t" // Vector for accummulating column 7 " dup v23.4s, wzr \n\t" // Vector for accummulating column 7 " dup v24.4s, wzr \n\t" // Vector for accummulating column 8 " dup v25.4s, wzr \n\t" // Vector for accummulating column 8 " \n\t" " dup v26.4s, wzr \n\t" // Vector for accummulating column 9 " dup v27.4s, wzr \n\t" // Vector for accummulating column 9 " dup v28.4s, wzr \n\t" // Vector for accummulating column 10 " dup v29.4s, wzr \n\t" // Vector for accummulating column 10 " dup v30.4s, wzr \n\t" // Vector for accummulating column 11 " dup v31.4s, wzr \n\t" // Vector for accummulating column 11 " \n\t" " cmp x5,#0 \n\t" // If k_iter == 0, jump to k_left. BEQ(SCONSIDERKLEFT) " \n\t" " ldr q0, [x0] \n\t" " ldr q1, [x0, #16] \n\t" // Load a " \n\t" " ldr q2, [x1] \n\t" // Load b " ldr q3, [x1, #16] \n\t" " ldr q4, [x1, #32] \n\t" " \n\t" " add x0, x0, #32 \n\t" //update address of A " add x1, x1, #48 \n\t" //update address of B " \n\t" " cmp x5,1 \n\t" // If there is just one k_iter, jump to that one. BEQ(SLASTITER) // (as loop is do-while-like). " \n\t" LABEL(SLOOPKITER) // Body of the k_iter loop. " \n\t" " ldr q5, [x0] \n\t" " fmla v8.4s, v0.4s,v2.s[0] \n\t" // Accummulate. " fmla v9.4s, v1.4s,v2.s[0] \n\t" // Accummulate. " ldr q6, [x0, #16] \n\t" " fmla v10.4s,v0.4s,v2.s[1] \n\t" // Accummulate. " fmla v11.4s,v1.4s,v2.s[1] \n\t" // Accummulate. " fmla v12.4s,v0.4s,v2.s[2] \n\t" // Accummulate. " fmla v13.4s,v1.4s,v2.s[2] \n\t" // Accummulate. " fmla v14.4s,v0.4s,v2.s[3] \n\t" // Accummulate. " fmla v15.4s,v1.4s,v2.s[3] \n\t" // Accummulate. " ldr q2, [x1] \n\t" " \n\t" " fmla v16.4s,v0.4s,v3.s[0] \n\t" // Accummulate. " prfm PLDL1KEEP, [x1, #336] \n\t" " fmla v17.4s,v1.4s,v3.s[0] \n\t" // Accummulate. " prfm PLDL1KEEP, [x1, #400] \n\t" " fmla v18.4s,v0.4s,v3.s[1] \n\t" // Accummulate. " fmla v19.4s,v1.4s,v3.s[1] \n\t" // Accummulate. " prfm PLDL1KEEP, [x1, #464] \n\t" " fmla v20.4s,v0.4s,v3.s[2] \n\t" // Accummulate. " fmla v21.4s,v1.4s,v3.s[2] \n\t" // Accummulate. " fmla v22.4s,v0.4s,v3.s[3] \n\t" // Accummulate. " fmla v23.4s,v1.4s,v3.s[3] \n\t" // Accummulate. " \n\t" " fmla v24.4s,v0.4s,v4.s[0] \n\t" // Accummulate. " fmla v26.4s,v0.4s,v4.s[1] \n\t" // Accummulate. " fmla v28.4s,v0.4s,v4.s[2] \n\t" // Accummulate. " fmla v30.4s,v0.4s,v4.s[3] \n\t" // Accummulate. " ldr q3, [x1, #16] \n\t" " \n\t" " fmla v25.4s,v1.4s,v4.s[0] \n\t" // Accummulate. " fmla v27.4s,v1.4s,v4.s[1] \n\t" // Accummulate. " fmla v29.4s,v1.4s,v4.s[2] \n\t" // Accummulate. " fmla v31.4s,v1.4s,v4.s[3] \n\t" // Accummulate. " ldr q4, [x1, #32] \n\t" " \n\t" //End It 1 " \n\t" " ldr q0, [x0, #32] \n\t" " fmla v8.4s,v5.4s,v2.s[0] \n\t" // Accummulate. " fmla v9.4s,v6.4s,v2.s[0] \n\t" // Accummulate. " ldr q1, [x0, #48] \n\t" " fmla v10.4s,v5.4s,v2.s[1] \n\t" // Accummulate. " fmla v11.4s,v6.4s,v2.s[1] \n\t" // Accummulate. " fmla v12.4s,v5.4s,v2.s[2] \n\t" // Accummulate. " fmla v13.4s,v6.4s,v2.s[2] \n\t" // Accummulate. " fmla v14.4s,v5.4s,v2.s[3] \n\t" // Accummulate. " fmla v15.4s,v6.4s,v2.s[3] \n\t" // Accummulate. " ldr q2, [x1, #48] \n\t" " \n\t" " fmla v16.4s,v5.4s,v3.s[0] \n\t" // Accummulate. " prfm PLDL1KEEP, [x0, #224] \n\t" " fmla v17.4s,v6.4s,v3.s[0] \n\t" // Accummulate. " prfm PLDL1KEEP, [x0, #288] \n\t" " fmla v18.4s,v5.4s,v3.s[1] \n\t" // Accummulate. " fmla v19.4s,v6.4s,v3.s[1] \n\t" // Accummulate. " fmla v20.4s,v5.4s,v3.s[2] \n\t" // Accummulate. " fmla v21.4s,v6.4s,v3.s[2] \n\t" // Accummulate. " fmla v22.4s,v5.4s,v3.s[3] \n\t" // Accummulate. " fmla v23.4s,v6.4s,v3.s[3] \n\t" // Accummulate. " \n\t" " fmla v24.4s,v5.4s,v4.s[0] \n\t" // Accummulate. " fmla v26.4s,v5.4s,v4.s[1] \n\t" // Accummulate. " fmla v28.4s,v5.4s,v4.s[2] \n\t" // Accummulate. " fmla v30.4s,v5.4s,v4.s[3] \n\t" // Accummulate. " ldr q3, [x1, #64] \n\t" " \n\t" " fmla v25.4s,v6.4s,v4.s[0] \n\t" // Accummulate. " fmla v27.4s,v6.4s,v4.s[1] \n\t" // Accummulate. " fmla v29.4s,v6.4s,v4.s[2] \n\t" // Accummulate. " fmla v31.4s,v6.4s,v4.s[3] \n\t" // Accummulate. " ldr q4, [x1, #80] \n\t" " \n\t" //End It 2 " \n\t" " ldr q5, [x0, #64] \n\t" " fmla v8.4s,v0.4s,v2.s[0] \n\t" // Accummulate. " fmla v9.4s,v1.4s,v2.s[0] \n\t" // Accummulate. " ldr q6, [x0, #80] \n\t" " fmla v10.4s,v0.4s,v2.s[1] \n\t" // Accummulate. " fmla v11.4s,v1.4s,v2.s[1] \n\t" // Accummulate. " fmla v12.4s,v0.4s,v2.s[2] \n\t" // Accummulate. " fmla v13.4s,v1.4s,v2.s[2] \n\t" // Accummulate. " fmla v14.4s,v0.4s,v2.s[3] \n\t" // Accummulate. " fmla v15.4s,v1.4s,v2.s[3] \n\t" // Accummulate. " ldr q2, [x1, #96] \n\t" " \n\t" " fmla v16.4s,v0.4s,v3.s[0] \n\t" // Accummulate. " fmla v17.4s,v1.4s,v3.s[0] \n\t" // Accummulate. " fmla v18.4s,v0.4s,v3.s[1] \n\t" // Accummulate. " fmla v19.4s,v1.4s,v3.s[1] \n\t" // Accummulate. " fmla v20.4s,v0.4s,v3.s[2] \n\t" // Accummulate. " fmla v21.4s,v1.4s,v3.s[2] \n\t" // Accummulate. " fmla v22.4s,v0.4s,v3.s[3] \n\t" // Accummulate. " fmla v23.4s,v1.4s,v3.s[3] \n\t" // Accummulate. " \n\t" " fmla v24.4s,v0.4s,v4.s[0] \n\t" // Accummulate. " fmla v26.4s,v0.4s,v4.s[1] \n\t" // Accummulate. " fmla v28.4s,v0.4s,v4.s[2] \n\t" // Accummulate. " fmla v30.4s,v0.4s,v4.s[3] \n\t" // Accummulate. " ldr q3, [x1, #112] \n\t" " \n\t" " fmla v25.4s,v1.4s,v4.s[0] \n\t" // Accummulate. " fmla v27.4s,v1.4s,v4.s[1] \n\t" // Accummulate. " fmla v29.4s,v1.4s,v4.s[2] \n\t" // Accummulate. " fmla v31.4s,v1.4s,v4.s[3] \n\t" // Accummulate. " ldr q4, [x1, #128] \n\t" " \n\t" //End It 3 " \n\t" " ldr q0, [x0, #96] \n\t" " fmla v8.4s,v5.4s,v2.s[0] \n\t" // Accummulate. " fmla v9.4s,v6.4s,v2.s[0] \n\t" // Accummulate. " ldr q1, [x0, #112] \n\t" " fmla v10.4s,v5.4s,v2.s[1] \n\t" // Accummulate. " fmla v11.4s,v6.4s,v2.s[1] \n\t" // Accummulate. " fmla v12.4s,v5.4s,v2.s[2] \n\t" // Accummulate. " fmla v13.4s,v6.4s,v2.s[2] \n\t" // Accummulate. " fmla v14.4s,v5.4s,v2.s[3] \n\t" // Accummulate. " fmla v15.4s,v6.4s,v2.s[3] \n\t" // Accummulate. " ldr q2, [x1, #144] \n\t" " \n\t" " fmla v16.4s,v5.4s,v3.s[0] \n\t" // Accummulate. " fmla v17.4s,v6.4s,v3.s[0] \n\t" // Accummulate. " fmla v18.4s,v5.4s,v3.s[1] \n\t" // Accummulate. " fmla v19.4s,v6.4s,v3.s[1] \n\t" // Accummulate. " fmla v20.4s,v5.4s,v3.s[2] \n\t" // Accummulate. " fmla v21.4s,v6.4s,v3.s[2] \n\t" // Accummulate. " fmla v22.4s,v5.4s,v3.s[3] \n\t" // Accummulate. " fmla v23.4s,v6.4s,v3.s[3] \n\t" // Accummulate. " \n\t" " fmla v24.4s,v5.4s,v4.s[0] \n\t" // Accummulate. " fmla v26.4s,v5.4s,v4.s[1] \n\t" // Accummulate. " fmla v28.4s,v5.4s,v4.s[2] \n\t" // Accummulate. " fmla v30.4s,v5.4s,v4.s[3] \n\t" // Accummulate. " ldr q3, [x1, #160] \n\t" " \n\t" " fmla v25.4s,v6.4s,v4.s[0] \n\t" // Accummulate. " fmla v27.4s,v6.4s,v4.s[1] \n\t" // Accummulate. " fmla v29.4s,v6.4s,v4.s[2] \n\t" // Accummulate. " fmla v31.4s,v6.4s,v4.s[3] \n\t" // Accummulate. " ldr q4, [x1, #176] \n\t" " add x1, x1, #192 \n\t" " add x0, x0, #128 \n\t" " \n\t" //End It 4 " sub x5,x5,1 \n\t" // i-=1. " cmp x5,1 \n\t" // Iterate again if we are not in k_iter == 1. BNE(SLOOPKITER) " \n\t" LABEL(SLASTITER) // Last iteration of k_iter loop. " \n\t" " \n\t" " ldr q5, [x0] \n\t" " fmla v8.4s,v0.4s,v2.s[0] \n\t" // Accummulate. " fmla v9.4s,v1.4s,v2.s[0] \n\t" // Accummulate. " ldr q6, [x0, #16] \n\t" " fmla v10.4s,v0.4s,v2.s[1] \n\t" // Accummulate. " fmla v11.4s,v1.4s,v2.s[1] \n\t" // Accummulate. " fmla v12.4s,v0.4s,v2.s[2] \n\t" // Accummulate. " fmla v13.4s,v1.4s,v2.s[2] \n\t" // Accummulate. " fmla v14.4s,v0.4s,v2.s[3] \n\t" // Accummulate. " fmla v15.4s,v1.4s,v2.s[3] \n\t" // Accummulate. " ldr q2, [x1] \n\t" " \n\t" " fmla v16.4s,v0.4s,v3.s[0] \n\t" // Accummulate. " fmla v17.4s,v1.4s,v3.s[0] \n\t" // Accummulate. " fmla v18.4s,v0.4s,v3.s[1] \n\t" // Accummulate. " fmla v19.4s,v1.4s,v3.s[1] \n\t" // Accummulate. " fmla v20.4s,v0.4s,v3.s[2] \n\t" // Accummulate. " fmla v21.4s,v1.4s,v3.s[2] \n\t" // Accummulate. " fmla v22.4s,v0.4s,v3.s[3] \n\t" // Accummulate. " fmla v23.4s,v1.4s,v3.s[3] \n\t" // Accummulate. " \n\t" " fmla v24.4s,v0.4s,v4.s[0] \n\t" // Accummulate. " fmla v26.4s,v0.4s,v4.s[1] \n\t" // Accummulate. " fmla v28.4s,v0.4s,v4.s[2] \n\t" // Accummulate. " fmla v30.4s,v0.4s,v4.s[3] \n\t" // Accummulate. " ldr q3, [x1, #16] \n\t" " \n\t" " fmla v25.4s,v1.4s,v4.s[0] \n\t" // Accummulate. " fmla v27.4s,v1.4s,v4.s[1] \n\t" // Accummulate. " fmla v29.4s,v1.4s,v4.s[2] \n\t" // Accummulate. " fmla v31.4s,v1.4s,v4.s[3] \n\t" // Accummulate. " ldr q4, [x1, #32] \n\t" " \n\t" //End It 1 " \n\t" " ldr q0, [x0, #32] \n\t" " fmla v8.4s,v5.4s,v2.s[0] \n\t" // Accummulate. " fmla v9.4s,v6.4s,v2.s[0] \n\t" // Accummulate. " ldr q1, [x0, #48] \n\t" " fmla v10.4s,v5.4s,v2.s[1] \n\t" // Accummulate. " fmla v11.4s,v6.4s,v2.s[1] \n\t" // Accummulate. " fmla v12.4s,v5.4s,v2.s[2] \n\t" // Accummulate. " fmla v13.4s,v6.4s,v2.s[2] \n\t" // Accummulate. " fmla v14.4s,v5.4s,v2.s[3] \n\t" // Accummulate. " fmla v15.4s,v6.4s,v2.s[3] \n\t" // Accummulate. " ldr q2, [x1, #48] \n\t" " \n\t" " fmla v16.4s,v5.4s,v3.s[0] \n\t" // Accummulate. " fmla v17.4s,v6.4s,v3.s[0] \n\t" // Accummulate. " fmla v18.4s,v5.4s,v3.s[1] \n\t" // Accummulate. " fmla v19.4s,v6.4s,v3.s[1] \n\t" // Accummulate. " fmla v20.4s,v5.4s,v3.s[2] \n\t" // Accummulate. " fmla v21.4s,v6.4s,v3.s[2] \n\t" // Accummulate. " fmla v22.4s,v5.4s,v3.s[3] \n\t" // Accummulate. " fmla v23.4s,v6.4s,v3.s[3] \n\t" // Accummulate. " \n\t" " fmla v24.4s,v5.4s,v4.s[0] \n\t" // Accummulate. " fmla v26.4s,v5.4s,v4.s[1] \n\t" // Accummulate. " fmla v28.4s,v5.4s,v4.s[2] \n\t" // Accummulate. " fmla v30.4s,v5.4s,v4.s[3] \n\t" // Accummulate. " ldr q3, [x1, #64] \n\t" " \n\t" " fmla v25.4s,v6.4s,v4.s[0] \n\t" // Accummulate. " fmla v27.4s,v6.4s,v4.s[1] \n\t" // Accummulate. " fmla v29.4s,v6.4s,v4.s[2] \n\t" // Accummulate. " fmla v31.4s,v6.4s,v4.s[3] \n\t" // Accummulate. " ldr q4, [x1, #80] \n\t" " \n\t" //End It 2 " \n\t" " ldr q5, [x0, #64] \n\t" " fmla v8.4s,v0.4s,v2.s[0] \n\t" // Accummulate. " fmla v9.4s,v1.4s,v2.s[0] \n\t" // Accummulate. " ldr q6, [x0, #80] \n\t" " fmla v10.4s,v0.4s,v2.s[1] \n\t" // Accummulate. " fmla v11.4s,v1.4s,v2.s[1] \n\t" // Accummulate. " fmla v12.4s,v0.4s,v2.s[2] \n\t" // Accummulate. " fmla v13.4s,v1.4s,v2.s[2] \n\t" // Accummulate. " fmla v14.4s,v0.4s,v2.s[3] \n\t" // Accummulate. " fmla v15.4s,v1.4s,v2.s[3] \n\t" // Accummulate. " ldr q2, [x1, #96] \n\t" " \n\t" " fmla v16.4s,v0.4s,v3.s[0] \n\t" // Accummulate. " fmla v17.4s,v1.4s,v3.s[0] \n\t" // Accummulate. " fmla v18.4s,v0.4s,v3.s[1] \n\t" // Accummulate. " fmla v19.4s,v1.4s,v3.s[1] \n\t" // Accummulate. " fmla v20.4s,v0.4s,v3.s[2] \n\t" // Accummulate. " fmla v21.4s,v1.4s,v3.s[2] \n\t" // Accummulate. " fmla v22.4s,v0.4s,v3.s[3] \n\t" // Accummulate. " fmla v23.4s,v1.4s,v3.s[3] \n\t" // Accummulate. " \n\t" " fmla v24.4s,v0.4s,v4.s[0] \n\t" // Accummulate. " fmla v26.4s,v0.4s,v4.s[1] \n\t" // Accummulate. " fmla v28.4s,v0.4s,v4.s[2] \n\t" // Accummulate. " fmla v30.4s,v0.4s,v4.s[3] \n\t" // Accummulate. " ldr q3, [x1, #112] \n\t" " \n\t" " fmla v25.4s,v1.4s,v4.s[0] \n\t" // Accummulate. " fmla v27.4s,v1.4s,v4.s[1] \n\t" // Accummulate. " fmla v29.4s,v1.4s,v4.s[2] \n\t" // Accummulate. " fmla v31.4s,v1.4s,v4.s[3] \n\t" // Accummulate. " ldr q4, [x1, #128] \n\t" " \n\t" //End It 3 " \n\t" " fmla v8.4s,v5.4s,v2.s[0] \n\t" // Accummulate. " fmla v9.4s,v6.4s,v2.s[0] \n\t" // Accummulate. " fmla v10.4s,v5.4s,v2.s[1] \n\t" // Accummulate. " fmla v11.4s,v6.4s,v2.s[1] \n\t" // Accummulate. " fmla v12.4s,v5.4s,v2.s[2] \n\t" // Accummulate. " fmla v13.4s,v6.4s,v2.s[2] \n\t" // Accummulate. " fmla v14.4s,v5.4s,v2.s[3] \n\t" // Accummulate. " fmla v15.4s,v6.4s,v2.s[3] \n\t" // Accummulate. " \n\t" " fmla v16.4s,v5.4s,v3.s[0] \n\t" // Accummulate. " fmla v17.4s,v6.4s,v3.s[0] \n\t" // Accummulate. " fmla v18.4s,v5.4s,v3.s[1] \n\t" // Accummulate. " fmla v19.4s,v6.4s,v3.s[1] \n\t" // Accummulate. " fmla v20.4s,v5.4s,v3.s[2] \n\t" // Accummulate. " fmla v21.4s,v6.4s,v3.s[2] \n\t" // Accummulate. " fmla v22.4s,v5.4s,v3.s[3] \n\t" // Accummulate. " fmla v23.4s,v6.4s,v3.s[3] \n\t" // Accummulate. " \n\t" " fmla v24.4s,v5.4s,v4.s[0] \n\t" // Accummulate. " fmla v26.4s,v5.4s,v4.s[1] \n\t" // Accummulate. " fmla v28.4s,v5.4s,v4.s[2] \n\t" // Accummulate. " fmla v30.4s,v5.4s,v4.s[3] \n\t" // Accummulate. " \n\t" " fmla v25.4s,v6.4s,v4.s[0] \n\t" // Accummulate. " fmla v27.4s,v6.4s,v4.s[1] \n\t" // Accummulate. " fmla v29.4s,v6.4s,v4.s[2] \n\t" // Accummulate. " fmla v31.4s,v6.4s,v4.s[3] \n\t" // Accummulate. " add x1, x1, #144 \n\t" " add x0, x0, #96 \n\t" " \n\t" //End It 4 " \n\t" LABEL(SCONSIDERKLEFT) " cmp x6,0 \n\t" // If k_left == 0, we are done. BEQ(SPOSTACCUM) // else, we enter the k_left loop. " \n\t" LABEL(SLOOPKLEFT) // Body of the left iterations " \n\t" " ldr q0, [x0],#16 \n\t" " ldr q1, [x0],#16 \n\t" // Load a " \n\t" " ldr q2, [x1],#16 \n\t" // Load b " ldr q3, [x1],#16 \n\t" " ldr q4, [x1],#16 \n\t" " \n\t" " sub x6,x6,1 \n\t" // i = i-1. " \n\t" " fmla v8.4s,v0.4s,v2.s[0] \n\t" // Accummulate. " fmla v9.4s,v1.4s,v2.s[0] \n\t" // Accummulate. " fmla v10.4s,v0.4s,v2.s[1] \n\t" // Accummulate. " fmla v11.4s,v1.4s,v2.s[1] \n\t" // Accummulate. " fmla v12.4s,v0.4s,v2.s[2] \n\t" // Accummulate. " fmla v13.4s,v1.4s,v2.s[2] \n\t" // Accummulate. " fmla v14.4s,v0.4s,v2.s[3] \n\t" // Accummulate. " fmla v15.4s,v1.4s,v2.s[3] \n\t" // Accummulate. " \n\t" " fmla v16.4s,v0.4s,v3.s[0] \n\t" // Accummulate. " fmla v17.4s,v1.4s,v3.s[0] \n\t" // Accummulate. " fmla v18.4s,v0.4s,v3.s[1] \n\t" // Accummulate. " fmla v19.4s,v1.4s,v3.s[1] \n\t" // Accummulate. " fmla v20.4s,v0.4s,v3.s[2] \n\t" // Accummulate. " fmla v21.4s,v1.4s,v3.s[2] \n\t" // Accummulate. " fmla v22.4s,v0.4s,v3.s[3] \n\t" // Accummulate. " fmla v23.4s,v1.4s,v3.s[3] \n\t" // Accummulate. " \n\t" " fmla v24.4s,v0.4s,v4.s[0] \n\t" // Accummulate. " fmla v26.4s,v0.4s,v4.s[1] \n\t" // Accummulate. " fmla v28.4s,v0.4s,v4.s[2] \n\t" // Accummulate. " fmla v30.4s,v0.4s,v4.s[3] \n\t" // Accummulate. " fmla v25.4s,v1.4s,v4.s[0] \n\t" // Accummulate. " fmla v27.4s,v1.4s,v4.s[1] \n\t" // Accummulate. " fmla v29.4s,v1.4s,v4.s[2] \n\t" // Accummulate. " fmla v31.4s,v1.4s,v4.s[3] \n\t" // Accummulate. " \n\t" " cmp x6,0 \n\t" // Iterate again. BNE(SLOOPKLEFT) // if i!=0. " \n\t" LABEL(SPOSTACCUM) " \n\t" " ldr x0,%[alpha] \n\t" // Alpha address. " ldr x1,%[beta] \n\t" // Beta address. " \n\t" " ld1r {v6.4s},[x0] \n\t" // Load alpha. " ld1r {v7.4s},[x1] \n\t" // Load beta " \n\t" " ldr x0,%[a_next] \n\t" // Pointer to next block of A. " ldr x1,%[b_next] \n\t" // Pointer to next pointer of B. " \n\t" LABEL(SCOLSTORED) // C is column-major. " \n\t" " dup v0.4s, wzr \n\t" " dup v1.4s, wzr \n\t" " dup v2.4s, wzr \n\t" " dup v3.4s, wzr \n\t" " dup v4.4s, wzr \n\t" " dup v5.4s, wzr \n\t" " \n\t" " fcmp s7,#0.0 \n\t" BEQ(SBETAZEROCOLSTOREDS1) // Taking care of the beta==0 case. " \n\t" " ldr q0, [x2] \n\t" //Load column 0 of C " ldr q1, [x2, #16] \n\t" " ldr q2, [x16] \n\t" //Load column 1 of C " ldr q3, [x16, #16] \n\t" " ldr q4, [x17] \n\t" //Load column 2 of C " ldr q5, [x17, #16] \n\t" " \n\t" " fmul v0.4s,v0.4s,v7.s[0] \n\t" // Scale by beta " fmul v1.4s,v1.4s,v7.s[0] \n\t" // Scale by beta " fmul v2.4s,v2.4s,v7.s[0] \n\t" // Scale by beta " fmul v3.4s,v3.4s,v7.s[0] \n\t" // Scale by beta " fmul v4.4s,v4.4s,v7.s[0] \n\t" // Scale by beta " fmul v5.4s,v5.4s,v7.s[0] \n\t" // Scale by beta " \n\t" LABEL(SBETAZEROCOLSTOREDS1) " \n\t" " fmla v0.4s,v8.4s,v6.s[0] \n\t" // Scale by alpha " fmla v1.4s,v9.4s,v6.s[0] \n\t" // Scale by alpha " fmla v2.4s,v10.4s,v6.s[0] \n\t" // Scale by alpha " fmla v3.4s,v11.4s,v6.s[0] \n\t" // Scale by alpha " fmla v4.4s,v12.4s,v6.s[0] \n\t" // Scale by alpha " fmla v5.4s,v13.4s,v6.s[0] \n\t" // Scale by alpha " \n\t" " str q0, [x2] \n\t" //Store column 0 of C " str q1, [x2, #16] \n\t" " str q2, [x16] \n\t" //Store column 1 of C " str q3, [x16, #16] \n\t" " str q4, [x17] \n\t" //Store column 2 of C " str q5, [x17, #16] \n\t" " \n\t" " dup v8.4s, wzr \n\t" " dup v9.4s, wzr \n\t" " dup v10.4s, wzr \n\t" " dup v11.4s, wzr \n\t" " dup v12.4s, wzr \n\t" " dup v13.4s, wzr \n\t" " \n\t" " fcmp s7,#0.0 \n\t" BEQ(SBETAZEROCOLSTOREDS2) // Taking care of the beta==0 case. " \n\t" " ldr q8, [x19] \n\t" //Load column 3 of C " ldr q9, [x19, #16] \n\t" " ldr q10, [x20] \n\t" //Load column 4 of C " ldr q11, [x20, #16] \n\t" " ldr q12, [x21] \n\t" //Load column 5 of C " ldr q13, [x21, #16] \n\t" " \n\t" " fmul v8.4s, v8.4s, v7.s[0] \n\t" // Scale by beta " fmul v9.4s, v9.4s, v7.s[0] \n\t" // Scale by beta " fmul v10.4s,v10.4s,v7.s[0] \n\t" // Scale by beta " fmul v11.4s,v11.4s,v7.s[0] \n\t" // Scale by beta " fmul v12.4s,v12.4s,v7.s[0] \n\t" // Scale by beta " fmul v13.4s,v13.4s,v7.s[0] \n\t" // Scale by beta " \n\t" LABEL(SBETAZEROCOLSTOREDS2) " \n\t" " fmla v8.4s, v14.4s,v6.s[0] \n\t" // Scale by alpha " fmla v9.4s, v15.4s,v6.s[0] \n\t" // Scale by alpha " fmla v10.4s,v16.4s,v6.s[0] \n\t" // Scale by alpha " fmla v11.4s,v17.4s,v6.s[0] \n\t" // Scale by alpha " fmla v12.4s,v18.4s,v6.s[0] \n\t" // Scale by alpha " fmla v13.4s,v19.4s,v6.s[0] \n\t" // Scale by alpha " \n\t" " str q8, [x19] \n\t" //Store column 3 of C " str q9, [x19, #16] \n\t" " str q10, [x20] \n\t" //Store column 4 of C " str q11, [x20, #16] \n\t" " str q12, [x21] \n\t" //Store column 5 of C " str q13, [x21, #16] \n\t" " \n\t" " dup v0.4s, wzr \n\t" " dup v1.4s, wzr \n\t" " dup v2.4s, wzr \n\t" " dup v3.4s, wzr \n\t" " dup v4.4s, wzr \n\t" " dup v5.4s, wzr \n\t" " \n\t" " fcmp s7,#0.0 \n\t" BEQ(SBETAZEROCOLSTOREDS3) // Taking care of the beta==0 case. " \n\t" " ldr q0, [x22] \n\t" //Load column 6 of C " ldr q1, [x22, #16] \n\t" " ldr q2, [x23] \n\t" //Load column 7 of C " ldr q3, [x23, #16] \n\t" " ldr q4, [x24] \n\t" //Load column 8 of C " ldr q5, [x24, #16] \n\t" " \n\t" " fmul v0.4s,v0.4s,v7.s[0] \n\t" // Scale by beta " fmul v1.4s,v1.4s,v7.s[0] \n\t" // Scale by beta " fmul v2.4s,v2.4s,v7.s[0] \n\t" // Scale by beta " fmul v3.4s,v3.4s,v7.s[0] \n\t" // Scale by beta " fmul v4.4s,v4.4s,v7.s[0] \n\t" // Scale by beta " fmul v5.4s,v5.4s,v7.s[0] \n\t" // Scale by beta " \n\t" LABEL(SBETAZEROCOLSTOREDS3) " \n\t" " fmla v0.4s,v20.4s,v6.s[0] \n\t" // Scale by alpha " fmla v1.4s,v21.4s,v6.s[0] \n\t" // Scale by alpha " fmla v2.4s,v22.4s,v6.s[0] \n\t" // Scale by alpha " fmla v3.4s,v23.4s,v6.s[0] \n\t" // Scale by alpha " fmla v4.4s,v24.4s,v6.s[0] \n\t" // Scale by alpha " fmla v5.4s,v25.4s,v6.s[0] \n\t" // Scale by alpha " \n\t" " str q0, [x22] \n\t" //Store column 6 of C " str q1, [x22, #16] \n\t" " str q2, [x23] \n\t" //Store column 7 of C " str q3, [x23, #16] \n\t" " str q4, [x24] \n\t" //Store column 8 of C " str q5, [x24, #16] \n\t" " \n\t" " dup v8.4s, wzr \n\t" " dup v9.4s, wzr \n\t" " dup v10.4s, wzr \n\t" " dup v11.4s, wzr \n\t" " dup v12.4s, wzr \n\t" " dup v13.4s, wzr \n\t" " \n\t" " fcmp s7,#0.0 \n\t" BEQ(SBETAZEROCOLSTOREDS4) // Taking care of the beta==0 case. " \n\t" " ldr q8, [x25] \n\t" //Load column 9 of C " ldr q9, [x25, #16] \n\t" " ldr q10, [x26] \n\t" //Load column 10 of C " ldr q11, [x26, #16] \n\t" " ldr q12, [x27] \n\t" //Load column 11 of C " ldr q13, [x27, #16] \n\t" " \n\t" " fmul v8.4s, v8.4s, v7.s[0] \n\t" // Scale by beta " fmul v9.4s, v9.4s, v7.s[0] \n\t" // Scale by beta " fmul v10.4s,v10.4s,v7.s[0] \n\t" // Scale by beta " fmul v11.4s,v11.4s,v7.s[0] \n\t" // Scale by beta " fmul v12.4s,v12.4s,v7.s[0] \n\t" // Scale by beta " fmul v13.4s,v13.4s,v7.s[0] \n\t" // Scale by beta " \n\t" LABEL(SBETAZEROCOLSTOREDS4) " \n\t" " prfm pldl2keep,[x0] \n\t" " prfm pldl2keep,[x1] \n\t" " \n\t" " fmla v8.4s, v26.4s,v6.s[0] \n\t" // Scale by alpha " fmla v9.4s, v27.4s,v6.s[0] \n\t" // Scale by alpha " fmla v10.4s,v28.4s,v6.s[0] \n\t" // Scale by alpha " fmla v11.4s,v29.4s,v6.s[0] \n\t" // Scale by alpha " fmla v12.4s,v30.4s,v6.s[0] \n\t" // Scale by alpha " fmla v13.4s,v31.4s,v6.s[0] \n\t" // Scale by alpha " \n\t" " str q8, [x25] \n\t" //Store column 9 of C " str q9, [x25, #16] \n\t" " str q10, [x26] \n\t" //Store column 10 of C " str q11, [x26, #16] \n\t" " str q12, [x27] \n\t" //Store column 11 of C " str q13, [x27, #16] \n\t" " \n\t" " \n\t" // BRANCH(SEND) // Done. // LABEL(SEND) // Done! " \n\t" :// output operands (none) :// input operands [aaddr] "m" (a), // 0 [baddr] "m" (b), // 1 [caddr] "m" (c), // 2 [k_iter] "m" (k_iter), // 3 [k_left] "m" (k_left), // 4 [alpha] "m" (alpha), // 5 [beta] "m" (beta), // 6 [rs_c] "m" (rs_c), // 7 [cs_c] "m" (cs_c), // 8 [a_next] "m" (a_next), // 9 [b_next] "m" (b_next) // 10 :// Register clobber list "x0", "x1", "x2", "x5", "x6", "x10", "x16","x17","x19","x20", "x21","x22","x23","x24", "x25","x26","x27", "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", "v10","v11", "v12","v13","v14","v15", "v16","v17","v18","v19", "v20","v21","v22","v23", "v24","v25","v26","v27", "v28","v29","v30","v31" ); GEMM_UKR_FLUSH_CT( s ); } /* o 4x4 Double precision micro-kernel NOT fully functional yet. o Runnable on ARMv8, compiled with aarch64 GCC. o Use it together with the armv8 BLIS configuration. o Tested on Juno board. Around 3 GFLOPS @ 1.1 GHz. December 2014. * UPDATE OCTOBER 2015: Now is fully functional. * Tested on Juno board. Around 5.6 GFLOPS, 2 A57 cores @ 1.1 GHz. * Tested on Juno board. Around 4 GFLOPS, 4 A53 cores @ 850 MHz. * UPDATE NOVEMBER 2015 * Micro-kernel changed to 6x8 * Tested on Juno Board. Around 4 GFLOPS, 1 x A57 core @ 1.1 GHz. * Tested on Juno Board. Around 7.6 GFLOPS, 2 x A57 cores @ 1.1 GHz. * Tested on Juno board. Around 1.5 GFLOPS, 1 x A53 core @ 850 MHz. * Tested on Juno board. Around 5.5 GFLOPS, 4 x A53 cores @ 850 MHz. */ void bli_dgemm_armv8a_asm_6x8 ( dim_t m, dim_t n, dim_t k, double* restrict alpha, double* restrict a, double* restrict b, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { void* a_next = bli_auxinfo_next_a( data ); void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k / 4; uint64_t k_left = k % 4; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; GEMM_UKR_SETUP_CT( d, 6, 8, false ); __asm__ volatile ( " \n\t" " ldr x0,%[aaddr] \n\t" // Load address of A " ldr x1,%[baddr] \n\t" // Load address of B " ldr x2,%[caddr] \n\t" // Load address of C " \n\t" " ldr x5,%[k_iter] \n\t" // Init guard (k_iter) " ldr x6,%[k_left] \n\t" // Init guard (k_iter) " \n\t" " ldr x10,%[cs_c] \n\t" // Load cs_c " lsl x10,x10,#3 \n\t" // cs_c * sizeof(double) " \n\t" // " ldr x14,%[rs_c] \n\t" // Load rs_c. // " lsl x14,x14,#3 \n\t" // rs_c * sizeof(double). " \n\t" " add x20,x2,x10 \n\t" //Load address Column 1 of C " add x21,x20,x10 \n\t" //Load address Column 2 of C " add x22,x21,x10 \n\t" //Load address Column 3 of C " add x23,x22,x10 \n\t" //Load address Column 4 of C " add x24,x23,x10 \n\t" //Load address Column 5 of C " add x25,x24,x10 \n\t" //Load address Column 6 of C " add x26,x25,x10 \n\t" //Load address Column 7 of C " \n\t" " prfm pldl1keep,[x2] \n\t" // Prefetch c. " prfm pldl1keep,[x20] \n\t" // Prefetch c. " prfm pldl1keep,[x21] \n\t" // Prefetch c. " prfm pldl1keep,[x22] \n\t" // Prefetch c. " prfm pldl1keep,[x23] \n\t" // Prefetch c. " prfm pldl1keep,[x24] \n\t" // Prefetch c. " prfm pldl1keep,[x25] \n\t" // Prefetch c. " prfm pldl1keep,[x26] \n\t" // Prefetch c. " \n\t" " dup v8.2d, xzr \n\t" // Vector for accummulating column 0 " prfm PLDL1KEEP, [x1, #256] \n\t" " dup v9.2d, xzr \n\t" // Vector for accummulating column 0 " prfm PLDL1KEEP, [x1, #320] \n\t" " dup v10.2d, xzr \n\t" // Vector for accummulating column 0 " prfm PLDL1KEEP, [x1, #384] \n\t" " dup v11.2d, xzr \n\t" // Vector for accummulating column 1 " prfm PLDL1KEEP, [x1, #448] \n\t" " dup v12.2d, xzr \n\t" // Vector for accummulating column 1 " dup v13.2d, xzr \n\t" // Vector for accummulating column 1 " \n\t" " dup v14.2d, xzr \n\t" // Vector for accummulating column 2 " prfm PLDL1KEEP, [x0, #192] \n\t" " dup v15.2d, xzr \n\t" // Vector for accummulating column 2 " prfm PLDL1KEEP, [x0, #256] \n\t" " dup v16.2d, xzr \n\t" // Vector for accummulating column 2 " prfm PLDL1KEEP, [x0, #320] \n\t" " dup v17.2d, xzr \n\t" // Vector for accummulating column 3 " dup v18.2d, xzr \n\t" // Vector for accummulating column 3 " dup v19.2d, xzr \n\t" // Vector for accummulating column 3 " \n\t" " dup v20.2d, xzr \n\t" // Vector for accummulating column 4 " dup v21.2d, xzr \n\t" // Vector for accummulating column 4 " dup v22.2d, xzr \n\t" // Vector for accummulating column 4 " dup v23.2d, xzr \n\t" // Vector for accummulating column 5 " dup v24.2d, xzr \n\t" // Vector for accummulating column 5 " dup v25.2d, xzr \n\t" // Vector for accummulating column 5 " \n\t" " dup v26.2d, xzr \n\t" // Vector for accummulating column 6 " dup v27.2d, xzr \n\t" // Vector for accummulating column 6 " dup v28.2d, xzr \n\t" // Vector for accummulating column 6 " dup v29.2d, xzr \n\t" // Vector for accummulating column 7 " dup v30.2d, xzr \n\t" // Vector for accummulating column 7 " dup v31.2d, xzr \n\t" // Vector for accummulating column 7 " \n\t" " \n\t" " cmp x5,#0 \n\t" // If k_iter == 0, jump to k_left. BEQ(DCONSIDERKLEFT) " \n\t" " ldr q0, [x0] \n\t" // Load a " ldr q1, [x0, #16] \n\t" " ldr q2, [x0, #32] \n\t" " \n\t" " ldr q3, [x1] \n\t" // Load b " ldr q4, [x1, #16] \n\t" " ldr q5, [x1, #32] \n\t" " ldr q6, [x1, #48] \n\t" " \n\t" " add x0, x0, #48 \n\t" //update address of A " add x1, x1, #64 \n\t" //update address of B " \n\t" " cmp x5,1 \n\t" // If there is just one k_iter, jump to that one. BEQ(DLASTITER) // (as loop is do-while-like). " \n\t" LABEL(DLOOP) // Body " \n\t" " fmla v8.2d ,v0.2d,v3.d[0] \n\t" // Accummulate " prfm PLDL1KEEP, [x1, #448] \n\t" //512-64=448 " fmla v9.2d ,v1.2d,v3.d[0] \n\t" // Accummulate " prfm PLDL1KEEP, [x1, #512] \n\t" " fmla v10.2d,v2.2d,v3.d[0] \n\t" // Accummulate " prfm PLDL1KEEP, [x1, #576] \n\t" " \n\t" " fmla v11.2d,v0.2d,v3.d[1] \n\t" // Accummulate " fmla v12.2d,v1.2d,v3.d[1] \n\t" // Accummulate " fmla v13.2d,v2.2d,v3.d[1] \n\t" // Accummulate " \n\t" " fmla v14.2d,v0.2d,v4.d[0] \n\t" // Accummulate " fmla v15.2d,v1.2d,v4.d[0] \n\t" // Accummulate " fmla v16.2d,v2.2d,v4.d[0] \n\t" // Accummulate " ldr q3, [x1] \n\t" " \n\t" " fmla v17.2d,v0.2d,v4.d[1] \n\t" // Accummulate " fmla v18.2d,v1.2d,v4.d[1] \n\t" // Accummulate " fmla v19.2d,v2.2d,v4.d[1] \n\t" // Accummulate " ldr q7, [x0, #32] \n\t" " \n\t" " fmla v20.2d,v0.2d,v5.d[0] \n\t" // Accummulate " fmla v21.2d,v1.2d,v5.d[0] \n\t" // Accummulate " fmla v22.2d,v2.2d,v5.d[0] \n\t" // Accummulate " ldr q4, [x1, #16] \n\t" " \n\t" " fmla v23.2d,v0.2d,v5.d[1] \n\t" // Accummulate " fmla v24.2d,v1.2d,v5.d[1] \n\t" // Accummulate " fmla v25.2d,v2.2d,v5.d[1] \n\t" // Accummulate " ldr q5, [x1, #32] \n\t" " \n\t" " fmla v26.2d,v0.2d,v6.d[0] \n\t" // Accummulate " fmla v29.2d,v0.2d,v6.d[1] \n\t" // Accummulate " ldr q0, [x0] \n\t" " \n\t" " fmla v27.2d,v1.2d,v6.d[0] \n\t" // Accummulate " fmla v30.2d,v1.2d,v6.d[1] \n\t" // Accummulate " ldr q1, [x0, #16] \n\t" " \n\t" " fmla v28.2d,v2.2d,v6.d[0] \n\t" // Accummulate " fmla v31.2d,v2.2d,v6.d[1] \n\t" // Accummulate " ldr q6, [x1, #48] \n\t" " \n\t" // End it 1 " fmla v8.2d ,v0.2d,v3.d[0] \n\t" // Accummulate " prfm PLDL1KEEP, [x1, #640] \n\t" " fmla v9.2d ,v1.2d,v3.d[0] \n\t" // Accummulate " prfm PLDL1KEEP, [x0, #336] \n\t" " fmla v10.2d,v7.2d,v3.d[0] \n\t" // Accummulate " prfm PLDL1KEEP, [x0, #400] \n\t" " \n\t" " fmla v11.2d,v0.2d,v3.d[1] \n\t" // Accummulate " fmla v12.2d,v1.2d,v3.d[1] \n\t" // Accummulate " fmla v13.2d,v7.2d,v3.d[1] \n\t" // Accummulate " \n\t" " fmla v14.2d,v0.2d,v4.d[0] \n\t" // Accummulate " fmla v15.2d,v1.2d,v4.d[0] \n\t" // Accummulate " fmla v16.2d,v7.2d,v4.d[0] \n\t" // Accummulate " ldr q3, [x1, #64] \n\t" " \n\t" " fmla v17.2d,v0.2d,v4.d[1] \n\t" // Accummulate " fmla v18.2d,v1.2d,v4.d[1] \n\t" // Accummulate " fmla v19.2d,v7.2d,v4.d[1] \n\t" // Accummulate " ldr q2, [x0, #80] \n\t" " \n\t" " fmla v20.2d,v0.2d,v5.d[0] \n\t" // Accummulate " fmla v21.2d,v1.2d,v5.d[0] \n\t" // Accummulate " fmla v22.2d,v7.2d,v5.d[0] \n\t" // Accummulate " ldr q4, [x1, #80] \n\t" " \n\t" " fmla v23.2d,v0.2d,v5.d[1] \n\t" // Accummulate " fmla v24.2d,v1.2d,v5.d[1] \n\t" // Accummulate " fmla v25.2d,v7.2d,v5.d[1] \n\t" // Accummulate " ldr q5, [x1, #96] \n\t" " \n\t" " fmla v26.2d,v0.2d,v6.d[0] \n\t" // Accummulate " fmla v29.2d,v0.2d,v6.d[1] \n\t" // Accummulate " ldr q0, [x0, #48] \n\t" " \n\t" " fmla v27.2d,v1.2d,v6.d[0] \n\t" // Accummulate " fmla v30.2d,v1.2d,v6.d[1] \n\t" // Accummulate " ldr q1, [x0, #64] \n\t" " \n\t" " fmla v28.2d,v7.2d,v6.d[0] \n\t" // Accummulate " fmla v31.2d,v7.2d,v6.d[1] \n\t" // Accummulate " ldr q6, [x1, #112] \n\t" " \n\t" //End it 2 " fmla v8.2d ,v0.2d,v3.d[0] \n\t" // Accummulate " prfm PLDL1KEEP, [x0, #464] \n\t" " fmla v9.2d ,v1.2d,v3.d[0] \n\t" // Accummulate " fmla v10.2d,v2.2d,v3.d[0] \n\t" // Accummulate " \n\t" " fmla v11.2d,v0.2d,v3.d[1] \n\t" // Accummulate " fmla v12.2d,v1.2d,v3.d[1] \n\t" // Accummulate " fmla v13.2d,v2.2d,v3.d[1] \n\t" // Accummulate " \n\t" " fmla v14.2d,v0.2d,v4.d[0] \n\t" // Accummulate " fmla v15.2d,v1.2d,v4.d[0] \n\t" // Accummulate " fmla v16.2d,v2.2d,v4.d[0] \n\t" // Accummulate " ldr q3, [x1, #128] \n\t" " \n\t" " fmla v17.2d,v0.2d,v4.d[1] \n\t" // Accummulate " fmla v18.2d,v1.2d,v4.d[1] \n\t" // Accummulate " fmla v19.2d,v2.2d,v4.d[1] \n\t" // Accummulate " ldr q7, [x0, #128] \n\t" " \n\t" " fmla v20.2d,v0.2d,v5.d[0] \n\t" // Accummulate " fmla v21.2d,v1.2d,v5.d[0] \n\t" // Accummulate " fmla v22.2d,v2.2d,v5.d[0] \n\t" // Accummulate " ldr q4, [x1, #144] \n\t" " \n\t" " fmla v23.2d,v0.2d,v5.d[1] \n\t" // Accummulate " fmla v24.2d,v1.2d,v5.d[1] \n\t" // Accummulate " fmla v25.2d,v2.2d,v5.d[1] \n\t" // Accummulate " ldr q5, [x1, #160] \n\t" " \n\t" " fmla v26.2d,v0.2d,v6.d[0] \n\t" // Accummulate " fmla v29.2d,v0.2d,v6.d[1] \n\t" // Accummulate " ldr q0, [x0, #96] \n\t" " \n\t" " fmla v27.2d,v1.2d,v6.d[0] \n\t" // Accummulate " fmla v30.2d,v1.2d,v6.d[1] \n\t" // Accummulate " ldr q1, [x0, #112] \n\t" " \n\t" " fmla v28.2d,v2.2d,v6.d[0] \n\t" // Accummulate " fmla v31.2d,v2.2d,v6.d[1] \n\t" // Accummulate " ldr q6, [x1, #176] \n\t" " \n\t" // End it 3 " fmla v8.2d ,v0.2d,v3.d[0] \n\t" // Accummulate " fmla v9.2d ,v1.2d,v3.d[0] \n\t" // Accummulate " fmla v10.2d,v7.2d,v3.d[0] \n\t" // Accummulate " \n\t" " fmla v11.2d,v0.2d,v3.d[1] \n\t" // Accummulate " fmla v12.2d,v1.2d,v3.d[1] \n\t" // Accummulate " fmla v13.2d,v7.2d,v3.d[1] \n\t" // Accummulate " ldr q3, [x1, #192] \n\t" " \n\t" " fmla v14.2d,v0.2d,v4.d[0] \n\t" // Accummulate " fmla v15.2d,v1.2d,v4.d[0] \n\t" // Accummulate " fmla v16.2d,v7.2d,v4.d[0] \n\t" // Accummulate " ldr q2, [x0, #176] \n\t" " \n\t" " fmla v17.2d,v0.2d,v4.d[1] \n\t" // Accummulate " fmla v18.2d,v1.2d,v4.d[1] \n\t" // Accummulate " fmla v19.2d,v7.2d,v4.d[1] \n\t" // Accummulate " ldr q4, [x1, #208] \n\t" " \n\t" " fmla v20.2d,v0.2d,v5.d[0] \n\t" // Accummulate " fmla v21.2d,v1.2d,v5.d[0] \n\t" // Accummulate " fmla v22.2d,v7.2d,v5.d[0] \n\t" // Accummulate " \n\t" " fmla v23.2d,v0.2d,v5.d[1] \n\t" // Accummulate " fmla v24.2d,v1.2d,v5.d[1] \n\t" // Accummulate " fmla v25.2d,v7.2d,v5.d[1] \n\t" // Accummulate " ldr q5, [x1, #224] \n\t" " \n\t" " fmla v26.2d,v0.2d,v6.d[0] \n\t" // Accummulate " fmla v29.2d,v0.2d,v6.d[1] \n\t" // Accummulate " ldr q0, [x0, #144] \n\t" " \n\t" " fmla v27.2d,v1.2d,v6.d[0] \n\t" // Accummulate " fmla v30.2d,v1.2d,v6.d[1] \n\t" // Accummulate " ldr q1, [x0, #160] \n\t" " \n\t" " fmla v28.2d,v7.2d,v6.d[0] \n\t" // Accummulate " fmla v31.2d,v7.2d,v6.d[1] \n\t" // Accummulate " ldr q6, [x1, #240] \n\t" " \n\t" //End it 4 " add x0, x0, #192 \n\t" " add x1, x1, #256 \n\t" " \n\t" " sub x5,x5,1 \n\t" // i-=1 " cmp x5,1 \n\t" // Iterate again if we are not in k_iter == 1. BNE(DLOOP) " \n\t" LABEL(DLASTITER) " \n\t" " fmla v8.2d ,v0.2d,v3.d[0] \n\t" // Accummulate " fmla v9.2d ,v1.2d,v3.d[0] \n\t" // Accummulate " fmla v10.2d,v2.2d,v3.d[0] \n\t" // Accummulate " \n\t" " fmla v11.2d,v0.2d,v3.d[1] \n\t" // Accummulate " fmla v12.2d,v1.2d,v3.d[1] \n\t" // Accummulate " fmla v13.2d,v2.2d,v3.d[1] \n\t" // Accummulate " ldr q3, [x1] \n\t" " \n\t" " fmla v14.2d,v0.2d,v4.d[0] \n\t" // Accummulate " fmla v15.2d,v1.2d,v4.d[0] \n\t" // Accummulate " fmla v16.2d,v2.2d,v4.d[0] \n\t" // Accummulate " ldr q7, [x0, #32] \n\t" " \n\t" " fmla v17.2d,v0.2d,v4.d[1] \n\t" // Accummulate " fmla v18.2d,v1.2d,v4.d[1] \n\t" // Accummulate " fmla v19.2d,v2.2d,v4.d[1] \n\t" // Accummulate " ldr q4, [x1, #16] \n\t" " \n\t" " fmla v20.2d,v0.2d,v5.d[0] \n\t" // Accummulate " fmla v21.2d,v1.2d,v5.d[0] \n\t" // Accummulate " fmla v22.2d,v2.2d,v5.d[0] \n\t" // Accummulate " \n\t" " fmla v23.2d,v0.2d,v5.d[1] \n\t" // Accummulate " fmla v24.2d,v1.2d,v5.d[1] \n\t" // Accummulate " fmla v25.2d,v2.2d,v5.d[1] \n\t" // Accummulate " ldr q5, [x1, #32] \n\t" " \n\t" " fmla v26.2d,v0.2d,v6.d[0] \n\t" // Accummulate " fmla v29.2d,v0.2d,v6.d[1] \n\t" // Accummulate " ldr q0, [x0] \n\t" " \n\t" " fmla v27.2d,v1.2d,v6.d[0] \n\t" // Accummulate " fmla v30.2d,v1.2d,v6.d[1] \n\t" // Accummulate " ldr q1, [x0, #16] \n\t" " \n\t" " fmla v28.2d,v2.2d,v6.d[0] \n\t" // Accummulate " fmla v31.2d,v2.2d,v6.d[1] \n\t" // Accummulate " ldr q6, [x1, #48] \n\t" " \n\t" // End it 1 " fmla v8.2d ,v0.2d,v3.d[0] \n\t" // Accummulate " fmla v9.2d ,v1.2d,v3.d[0] \n\t" // Accummulate " fmla v10.2d,v7.2d,v3.d[0] \n\t" // Accummulate " \n\t" " fmla v11.2d,v0.2d,v3.d[1] \n\t" // Accummulate " fmla v12.2d,v1.2d,v3.d[1] \n\t" // Accummulate " fmla v13.2d,v7.2d,v3.d[1] \n\t" // Accummulate " ldr q3, [x1, #64] \n\t" " \n\t" " fmla v14.2d,v0.2d,v4.d[0] \n\t" // Accummulate " fmla v15.2d,v1.2d,v4.d[0] \n\t" // Accummulate " fmla v16.2d,v7.2d,v4.d[0] \n\t" // Accummulate " ldr q2, [x0, #80] \n\t" " \n\t" " fmla v17.2d,v0.2d,v4.d[1] \n\t" // Accummulate " fmla v18.2d,v1.2d,v4.d[1] \n\t" // Accummulate " fmla v19.2d,v7.2d,v4.d[1] \n\t" // Accummulate " ldr q4, [x1, #80] \n\t" " \n\t" " fmla v20.2d,v0.2d,v5.d[0] \n\t" // Accummulate " fmla v21.2d,v1.2d,v5.d[0] \n\t" // Accummulate " fmla v22.2d,v7.2d,v5.d[0] \n\t" // Accummulate " \n\t" " fmla v23.2d,v0.2d,v5.d[1] \n\t" // Accummulate " fmla v24.2d,v1.2d,v5.d[1] \n\t" // Accummulate " fmla v25.2d,v7.2d,v5.d[1] \n\t" // Accummulate " ldr q5, [x1, #96] \n\t" " \n\t" " fmla v26.2d,v0.2d,v6.d[0] \n\t" // Accummulate " fmla v29.2d,v0.2d,v6.d[1] \n\t" // Accummulate " ldr q0, [x0, #48] \n\t" " \n\t" " fmla v27.2d,v1.2d,v6.d[0] \n\t" // Accummulate " fmla v30.2d,v1.2d,v6.d[1] \n\t" // Accummulate " ldr q1, [x0, #64] \n\t" " \n\t" " fmla v28.2d,v7.2d,v6.d[0] \n\t" // Accummulate " fmla v31.2d,v7.2d,v6.d[1] \n\t" // Accummulate " ldr q6, [x1, #112] \n\t" " \n\t" //End it 2 " fmla v8.2d ,v0.2d,v3.d[0] \n\t" // Accummulate " fmla v9.2d ,v1.2d,v3.d[0] \n\t" // Accummulate " fmla v10.2d,v2.2d,v3.d[0] \n\t" // Accummulate " \n\t" " fmla v11.2d,v0.2d,v3.d[1] \n\t" // Accummulate " fmla v12.2d,v1.2d,v3.d[1] \n\t" // Accummulate " fmla v13.2d,v2.2d,v3.d[1] \n\t" // Accummulate " ldr q3, [x1, #128] \n\t" " \n\t" " fmla v14.2d,v0.2d,v4.d[0] \n\t" // Accummulate " fmla v15.2d,v1.2d,v4.d[0] \n\t" // Accummulate " fmla v16.2d,v2.2d,v4.d[0] \n\t" // Accummulate " ldr q7, [x0, #128] \n\t" " \n\t" " fmla v17.2d,v0.2d,v4.d[1] \n\t" // Accummulate " fmla v18.2d,v1.2d,v4.d[1] \n\t" // Accummulate " fmla v19.2d,v2.2d,v4.d[1] \n\t" // Accummulate " ldr q4, [x1, #144] \n\t" " \n\t" " fmla v20.2d,v0.2d,v5.d[0] \n\t" // Accummulate " fmla v21.2d,v1.2d,v5.d[0] \n\t" // Accummulate " fmla v22.2d,v2.2d,v5.d[0] \n\t" // Accummulate " \n\t" " fmla v23.2d,v0.2d,v5.d[1] \n\t" // Accummulate " fmla v24.2d,v1.2d,v5.d[1] \n\t" // Accummulate " fmla v25.2d,v2.2d,v5.d[1] \n\t" // Accummulate " ldr q5, [x1, #160] \n\t" " \n\t" " fmla v26.2d,v0.2d,v6.d[0] \n\t" // Accummulate " fmla v29.2d,v0.2d,v6.d[1] \n\t" // Accummulate " ldr q0, [x0, #96] \n\t" " \n\t" " fmla v27.2d,v1.2d,v6.d[0] \n\t" // Accummulate " fmla v30.2d,v1.2d,v6.d[1] \n\t" // Accummulate " ldr q1, [x0, #112] \n\t" " \n\t" " fmla v28.2d,v2.2d,v6.d[0] \n\t" // Accummulate " fmla v31.2d,v2.2d,v6.d[1] \n\t" // Accummulate " ldr q6, [x1, #176] \n\t" " \n\t" // End it 3 " fmla v8.2d ,v0.2d,v3.d[0] \n\t" // Accummulate " fmla v9.2d ,v1.2d,v3.d[0] \n\t" // Accummulate " fmla v10.2d,v7.2d,v3.d[0] \n\t" // Accummulate " \n\t" " fmla v11.2d,v0.2d,v3.d[1] \n\t" // Accummulate " fmla v12.2d,v1.2d,v3.d[1] \n\t" // Accummulate " fmla v13.2d,v7.2d,v3.d[1] \n\t" // Accummulate " \n\t" " fmla v14.2d,v0.2d,v4.d[0] \n\t" // Accummulate " fmla v15.2d,v1.2d,v4.d[0] \n\t" // Accummulate " fmla v16.2d,v7.2d,v4.d[0] \n\t" // Accummulate " \n\t" " fmla v17.2d,v0.2d,v4.d[1] \n\t" // Accummulate " fmla v18.2d,v1.2d,v4.d[1] \n\t" // Accummulate " fmla v19.2d,v7.2d,v4.d[1] \n\t" // Accummulate " \n\t" " fmla v20.2d,v0.2d,v5.d[0] \n\t" // Accummulate " fmla v21.2d,v1.2d,v5.d[0] \n\t" // Accummulate " fmla v22.2d,v7.2d,v5.d[0] \n\t" // Accummulate " \n\t" " fmla v23.2d,v0.2d,v5.d[1] \n\t" // Accummulate " fmla v24.2d,v1.2d,v5.d[1] \n\t" // Accummulate " fmla v25.2d,v7.2d,v5.d[1] \n\t" // Accummulate " \n\t" " fmla v26.2d,v0.2d,v6.d[0] \n\t" // Accummulate " add x1, x1, #192 \n\t" " fmla v29.2d,v0.2d,v6.d[1] \n\t" // Accummulate " \n\t" " fmla v27.2d,v1.2d,v6.d[0] \n\t" // Accummulate " fmla v30.2d,v1.2d,v6.d[1] \n\t" // Accummulate " \n\t" " fmla v28.2d,v7.2d,v6.d[0] \n\t" // Accummulate " fmla v31.2d,v7.2d,v6.d[1] \n\t" // Accummulate " \n\t" //End it 4 " add x0, x0, #144 \n\t" " \n\t" LABEL(DCONSIDERKLEFT) " cmp x6,0 \n\t" // If k_left == 0, we are done. BEQ(DPOSTACCUM) // else, we enter the k_left loop. " \n\t" LABEL(DLOOPKLEFT) " \n\t" " ldr q0, [x0],#16 \n\t" " ldr q1, [x0],#16 \n\t" // Load a " ldr q2, [x0],#16 \n\t" " \n\t" " ldr q3, [x1],#16 \n\t" // Load b " ldr q4, [x1],#16 \n\t" " ldr q5, [x1],#16 \n\t" " ldr q6, [x1],#16 \n\t" " \n\t" " sub x6,x6,1 \n\t" " \n\t" " fmla v8.2d ,v0.2d,v3.d[0] \n\t" // Accummulate " fmla v9.2d ,v1.2d,v3.d[0] \n\t" // Accummulate " fmla v10.2d,v2.2d,v3.d[0] \n\t" // Accummulate " \n\t" " fmla v11.2d,v0.2d,v3.d[1] \n\t" // Accummulate " fmla v12.2d,v1.2d,v3.d[1] \n\t" // Accummulate " fmla v13.2d,v2.2d,v3.d[1] \n\t" // Accummulate " \n\t" " fmla v14.2d,v0.2d,v4.d[0] \n\t" // Accummulate " fmla v15.2d,v1.2d,v4.d[0] \n\t" // Accummulate " fmla v16.2d,v2.2d,v4.d[0] \n\t" // Accummulate " \n\t" " fmla v17.2d,v0.2d,v4.d[1] \n\t" // Accummulate " fmla v18.2d,v1.2d,v4.d[1] \n\t" // Accummulate " fmla v19.2d,v2.2d,v4.d[1] \n\t" // Accummulate " \n\t" " fmla v20.2d,v0.2d,v5.d[0] \n\t" // Accummulate " fmla v21.2d,v1.2d,v5.d[0] \n\t" // Accummulate " fmla v22.2d,v2.2d,v5.d[0] \n\t" // Accummulate " \n\t" " fmla v23.2d,v0.2d,v5.d[1] \n\t" // Accummulate " fmla v24.2d,v1.2d,v5.d[1] \n\t" // Accummulate " fmla v25.2d,v2.2d,v5.d[1] \n\t" // Accummulate " \n\t" " fmla v26.2d,v0.2d,v6.d[0] \n\t" // Accummulate " fmla v29.2d,v0.2d,v6.d[1] \n\t" // Accummulate " \n\t" " fmla v27.2d,v1.2d,v6.d[0] \n\t" // Accummulate " fmla v30.2d,v1.2d,v6.d[1] \n\t" // Accummulate " \n\t" " fmla v28.2d,v2.2d,v6.d[0] \n\t" // Accummulate " fmla v31.2d,v2.2d,v6.d[1] \n\t" // Accummulate " \n\t" " cmp x6,0 \n\t" // Iterate again. BNE(DLOOPKLEFT) // if i!=0. " \n\t" LABEL(DPOSTACCUM) " \n\t" " ldr x0,%[alpha] \n\t" // Alpha address " ldr x1,%[beta] \n\t" // Beta address " \n\t" " ld1r {v6.2d},[x0] \n\t" // Load alpha. " ld1r {v7.2d},[x1] \n\t" // Load beta " \n\t" " ldr x0,%[a_next] \n\t" // Next A address for later use. " ldr x1,%[b_next] \n\t" // Next B address for later use. " \n\t" LABEL(DCOLSTORED) // C is column-major. " \n\t" " dup v0.2d, xzr \n\t" " dup v1.2d, xzr \n\t" " dup v2.2d, xzr \n\t" " dup v3.2d, xzr \n\t" " dup v4.2d, xzr \n\t" " dup v5.2d, xzr \n\t" " \n\t" " fcmp d7,#0.0 \n\t" BEQ(DBETAZEROCOLSTOREDS1) // Taking care of the beta==0 case. " \n\t" " ldr q0, [x2] \n\t" //Load column 0 of C " ldr q1, [x2, #16] \n\t" " ldr q2, [x2, #32] \n\t" " \n\t" " ldr q3, [x20] \n\t" //Load column 1 of C " ldr q4, [x20, #16] \n\t" " ldr q5, [x20, #32] \n\t" " \n\t" " fmul v0.2d,v0.2d,v7.d[0] \n\t" // Scale by beta " fmul v1.2d,v1.2d,v7.d[0] \n\t" // Scale by beta " fmul v2.2d,v2.2d,v7.d[0] \n\t" // Scale by beta " fmul v3.2d,v3.2d,v7.d[0] \n\t" // Scale by beta " fmul v4.2d,v4.2d,v7.d[0] \n\t" // Scale by beta " fmul v5.2d,v5.2d,v7.d[0] \n\t" // Scale by beta " \n\t" LABEL(DBETAZEROCOLSTOREDS1) " \n\t" " fmla v0.2d,v8.2d,v6.d[0] \n\t" // Scale by alpha " fmla v1.2d,v9.2d,v6.d[0] \n\t" // Scale by alpha " fmla v2.2d,v10.2d,v6.d[0] \n\t" // Scale by alpha " fmla v3.2d,v11.2d,v6.d[0] \n\t" // Scale by alpha " fmla v4.2d,v12.2d,v6.d[0] \n\t" // Scale by alpha " fmla v5.2d,v13.2d,v6.d[0] \n\t" // Scale by alpha " \n\t" " str q0, [x2] \n\t" //Store column 0 of C " str q1, [x2, #16] \n\t" " str q2, [x2, #32] \n\t" " \n\t" " str q3, [x20] \n\t" //Store column 1 of C " str q4, [x20, #16] \n\t" " str q5, [x20, #32] \n\t" " \n\t" " dup v8.2d, xzr \n\t" " dup v9.2d, xzr \n\t" " dup v10.2d, xzr \n\t" " dup v11.2d, xzr \n\t" " dup v12.2d, xzr \n\t" " dup v13.2d, xzr \n\t" " \n\t" " fcmp d7,#0.0 \n\t" BEQ(DBETAZEROCOLSTOREDS2) // Taking care of the beta==0 case. " \n\t" " ldr q8, [x21] \n\t" //Load column 2 of C " ldr q9, [x21, #16] \n\t" " ldr q10, [x21, #32] \n\t" " \n\t" " ldr q11, [x22] \n\t" //Load column 3 of C " ldr q12, [x22, #16] \n\t" " ldr q13, [x22, #32] \n\t" " \n\t" " fmul v8.2d, v8.2d, v7.d[0] \n\t" // Scale by beta " fmul v9.2d, v9.2d, v7.d[0] \n\t" // Scale by beta " fmul v10.2d,v10.2d,v7.d[0] \n\t" // Scale by beta " fmul v11.2d,v11.2d,v7.d[0] \n\t" // Scale by beta " fmul v12.2d,v12.2d,v7.d[0] \n\t" // Scale by beta " fmul v13.2d,v13.2d,v7.d[0] \n\t" // Scale by beta " \n\t" LABEL(DBETAZEROCOLSTOREDS2) " \n\t" " fmla v8.2d, v14.2d,v6.d[0] \n\t" // Scale by alpha " fmla v9.2d, v15.2d,v6.d[0] \n\t" // Scale by alpha " fmla v10.2d,v16.2d,v6.d[0] \n\t" // Scale by alpha " fmla v11.2d,v17.2d,v6.d[0] \n\t" // Scale by alpha " fmla v12.2d,v18.2d,v6.d[0] \n\t" // Scale by alpha " fmla v13.2d,v19.2d,v6.d[0] \n\t" // Scale by alpha " \n\t" " str q8, [x21] \n\t" //Store column 2 of C " str q9, [x21, #16] \n\t" " str q10, [x21, #32] \n\t" " \n\t" " str q11, [x22] \n\t" //Store column 3 of C " str q12, [x22, #16] \n\t" " str q13, [x22, #32] \n\t" " \n\t" " dup v0.2d, xzr \n\t" " dup v1.2d, xzr \n\t" " dup v2.2d, xzr \n\t" " dup v3.2d, xzr \n\t" " dup v4.2d, xzr \n\t" " dup v5.2d, xzr \n\t" " \n\t" " fcmp d7,#0.0 \n\t" BEQ(DBETAZEROCOLSTOREDS3) // Taking care of the beta==0 case. " \n\t" " ldr q0, [x23] \n\t" //Load column 4 of C " ldr q1, [x23, #16] \n\t" " ldr q2, [x23, #32] \n\t" " \n\t" " ldr q3, [x24] \n\t" //Load column 5 of C " ldr q4, [x24, #16] \n\t" " ldr q5, [x24, #32] \n\t" " \n\t" " fmul v0.2d,v0.2d,v7.d[0] \n\t" // Scale by beta " fmul v1.2d,v1.2d,v7.d[0] \n\t" // Scale by beta " fmul v2.2d,v2.2d,v7.d[0] \n\t" // Scale by beta " fmul v3.2d,v3.2d,v7.d[0] \n\t" // Scale by beta " fmul v4.2d,v4.2d,v7.d[0] \n\t" // Scale by beta " fmul v5.2d,v5.2d,v7.d[0] \n\t" // Scale by beta " \n\t" LABEL(DBETAZEROCOLSTOREDS3) " \n\t" " fmla v0.2d,v20.2d,v6.d[0] \n\t" // Scale by alpha " fmla v1.2d,v21.2d,v6.d[0] \n\t" // Scale by alpha " fmla v2.2d,v22.2d,v6.d[0] \n\t" // Scale by alpha " fmla v3.2d,v23.2d,v6.d[0] \n\t" // Scale by alpha " fmla v4.2d,v24.2d,v6.d[0] \n\t" // Scale by alpha " fmla v5.2d,v25.2d,v6.d[0] \n\t" // Scale by alpha " \n\t" " str q0, [x23] \n\t" //Store column 4 of C " str q1, [x23, #16] \n\t" " str q2, [x23, #32] \n\t" " \n\t" " str q3, [x24] \n\t" //Store column 5 of C " str q4, [x24, #16] \n\t" " str q5, [x24, #32] \n\t" " \n\t" " dup v8.2d, xzr \n\t" " dup v9.2d, xzr \n\t" " dup v10.2d, xzr \n\t" " dup v11.2d, xzr \n\t" " dup v12.2d, xzr \n\t" " dup v13.2d, xzr \n\t" " \n\t" " fcmp d7,#0.0 \n\t" BEQ(DBETAZEROCOLSTOREDS4) // Taking care of the beta==0 case. " \n\t" " ldr q8, [x25] \n\t" //Load column 6 of C " ldr q9, [x25, #16] \n\t" " ldr q10, [x25, #32] \n\t" " \n\t" " ldr q11, [x26] \n\t" //Load column 7 of C " ldr q12, [x26, #16] \n\t" " ldr q13, [x26, #32] \n\t" " \n\t" " fmul v8.2d, v8.2d, v7.d[0] \n\t" // Scale by beta " fmul v9.2d, v9.2d, v7.d[0] \n\t" // Scale by beta " fmul v10.2d,v10.2d,v7.d[0] \n\t" // Scale by beta " fmul v11.2d,v11.2d,v7.d[0] \n\t" // Scale by beta " fmul v12.2d,v12.2d,v7.d[0] \n\t" // Scale by beta " fmul v13.2d,v13.2d,v7.d[0] \n\t" // Scale by beta " \n\t" LABEL(DBETAZEROCOLSTOREDS4) " \n\t" " prfm pldl2keep,[x0] \n\t" " prfm pldl2keep,[x1] \n\t" " \n\t" " fmla v8.2d, v26.2d,v6.d[0] \n\t" // Scale by alpha " fmla v9.2d, v27.2d,v6.d[0] \n\t" // Scale by alpha " fmla v10.2d,v28.2d,v6.d[0] \n\t" // Scale by alpha " fmla v11.2d,v29.2d,v6.d[0] \n\t" // Scale by alpha " fmla v12.2d,v30.2d,v6.d[0] \n\t" // Scale by alpha " fmla v13.2d,v31.2d,v6.d[0] \n\t" // Scale by alpha " \n\t" " str q8, [x25] \n\t" //Store column 6 of C " str q9, [x25, #16] \n\t" " str q10, [x25, #32] \n\t" " \n\t" " str q11, [x26] \n\t" //Store column 7 of C " str q12, [x26, #16] \n\t" " str q13, [x26, #32] \n\t" " \n\t" // BRANCH(DEND) // LABEL(DEND) // Done! " \n\t" :// output operands (none) :// input operands [aaddr] "m" (a), // 0 [baddr] "m" (b), // 1 [caddr] "m" (c), // 2 [k_iter] "m" (k_iter), // 3 [k_left] "m" (k_left), // 4 [alpha] "m" (alpha), // 5 [beta] "m" (beta), // 6 [rs_c] "m" (rs_c), // 6 [cs_c] "m" (cs_c), // 7 [a_next] "m" (a_next), // 8 [b_next] "m" (b_next) // 9 :// Register clobber list "x0","x1","x2", "x5","x6","x10", "x16","x17","x20", "x21","x22","x23", "x24","x25","x26","x27", "v0","v1","v2", "v3","v4","v5", "v6","v7","v8", "v9","v10","v11", "v12","v13","v14", "v15","v16","v17","v18","v19", "v20","v21","v22","v23", "v24","v25","v26","v27", "v28","v29","v30","v31" ); GEMM_UKR_FLUSH_CT( d ); } #if 0 void bli_cgemm_armv8a_opt_4x4 ( dim_t m, dim_t n, dim_t k, scomplex* restrict alpha, scomplex* restrict a, scomplex* restrict b, scomplex* restrict beta, scomplex* restrict c, inc_t rs_c, inc_t cs_c, auxinfo_t* restrict data, cntx_t* restrict cntx ) { } void bli_zgemm_armv8a_opt_4x4 ( dim_t m, dim_t n, dim_t k, dcomplex* restrict alpha, dcomplex* restrict a, dcomplex* restrict b, dcomplex* restrict beta, dcomplex* restrict c, inc_t rs_c, inc_t cs_c, auxinfo_t* restrict data, cntx_t* restrict cntx ) { } #endif blis-0.9.0/kernels/armv8a/3/old/000077500000000000000000000000001422157504600162405ustar00rootroot00000000000000blis-0.9.0/kernels/armv8a/3/old/bli_gemm_armv8a_asm_d4x4.c000066400000000000000000000260331422157504600231440ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2021, The University of Tokyo 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "assert.h" // Label locality & misc. #include "armv8a_asm_utils.h" // Nanokernel operations. #include "armv8a_asm_d2x2.h" #define DGEMM_4X4_MKER_LOOP_PLAIN(C00,C10,C01,C11,C02,C12,C03,C13,A0,A1,B0,B1) \ DGEMM_2X2_NANOKERNEL(C00,C01,A0,B0) \ DGEMM_2X2_NANOKERNEL(C10,C11,A1,B0) \ DGEMM_2X2_NANOKERNEL(C02,C03,A0,B1) \ DGEMM_2X2_NANOKERNEL(C12,C13,A1,B1) // For contiguous storage of C. #define DLOADC_2V_C_FWD(C0,C1,CADDR,CSHIFT,LDC) \ DLOAD2V(C0,C1,CADDR,CSHIFT) \ " add "#CADDR", "#CADDR", "#LDC" \n\t" #define DSTOREC_2V_C_FWD(C0,C1,CADDR,CSHIFT,LDC) \ DSTORE2V(C0,C1,CADDR,CSHIFT) \ " add "#CADDR", "#CADDR", "#LDC" \n\t" void bli_dgemm_armv8a_asm_4x4 ( dim_t k0, double* restrict alpha, double* restrict a, double* restrict b, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { void* a_next = bli_auxinfo_next_a( data ); void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_mker = k0 / 6; uint64_t k_left = k0 % 6; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; __asm__ volatile ( " ldr x0, %[a] \n\t" " ldr x1, %[b] \n\t" " mov x2, #4 \n\t" // Column-skip of A. " mov x3, #4 \n\t" // Row-skip of B. " \n\t" " ldr x5, %[c] \n\t" " ldr x6, %[rs_c] \n\t" // Row-skip of C. " ldr x7, %[cs_c] \n\t" // Column-skip of C. " \n\t" " mov x8, #8 \n\t" // Multiply some address skips by sizeof(double). " madd x2, x8, x2, xzr \n\t" // cs_a " madd x3, x8, x3, xzr \n\t" // rs_b " madd x7, x8, x7, xzr \n\t" // cs_c " \n\t" " ldr x4, %[k_mker] \n\t" // Number of loops. " ldr x8, %[k_left] \n\t" " \n\t" // Storage scheme: // V[ 0:7 ] <- C // V[ 8:19] <- B // V[20:31] <- A // Under this scheme, the following is defined: #define DGEMM_4X4_MKER_LOOP_PLAIN_LOC(A0,A1,B0,B1) \ DGEMM_4X4_MKER_LOOP_PLAIN(0,1,2,3,4,5,6,7,A0,A1,B0,B1) // TODO: Prefetch C. // Load from memory. LABEL(LOAD_ABC) " \n\t" // No-microkernel early return is a must " cmp x4, #0 \n\t" // to avoid out-of-boundary read. BEQ(CLEAR_CCOLS) " \n\t" " ldr q20, [x0, #16*0] \n\t" " ldr q21, [x0, #16*1] \n\t" " ldr q22, [x0, #16*2] \n\t" " ldr q23, [x0, #16*3] \n\t" " ldr q24, [x0, #16*4] \n\t" " ldr q25, [x0, #16*5] \n\t" " add x0, x0, x2 \n\t" " add x0, x0, x2 \n\t" " add x0, x0, x2 \n\t" " ldr q26, [x0, #16*0] \n\t" " ldr q27, [x0, #16*1] \n\t" " ldr q28, [x0, #16*2] \n\t" " ldr q29, [x0, #16*3] \n\t" " ldr q30, [x0, #16*4] \n\t" " ldr q31, [x0, #16*5] \n\t" " add x0, x0, x2 \n\t" " add x0, x0, x2 \n\t" " add x0, x0, x2 \n\t" " \n\t" " ldr q8, [x1, #16*0] \n\t" " ldr q9, [x1, #16*1] \n\t" " ldr q10, [x1, #16*2] \n\t" " ldr q11, [x1, #16*3] \n\t" " ldr q12, [x1, #16*4] \n\t" " ldr q13, [x1, #16*5] \n\t" " add x1, x1, x3 \n\t" " add x1, x1, x3 \n\t" " add x1, x1, x3 \n\t" " ldr q14, [x1, #16*0] \n\t" " ldr q15, [x1, #16*1] \n\t" " ldr q16, [x1, #16*2] \n\t" " ldr q17, [x1, #16*3] \n\t" " ldr q18, [x1, #16*4] \n\t" " ldr q19, [x1, #16*5] \n\t" " add x1, x1, x3 \n\t" " add x1, x1, x3 \n\t" " add x1, x1, x3 \n\t" " \n\t" LABEL(CLEAR_CCOLS) CLEAR8V(0,1,2,3,4,5,6,7) // No-microkernel early return, once again. BEQ(K_LEFT_LOOP) // // Microkernel is defined here as: #define DGEMM_4X4_MKER_LOOP_PLAIN_LOC_FWD(A0,A1,B0,B1) \ DGEMM_4X4_MKER_LOOP_PLAIN_LOC(A0,A1,B0,B1) \ "ldr q"#A0", [x0, #16*0] \n\t" \ "ldr q"#A1", [x0, #16*1] \n\t" \ "add x0, x0, x2 \n\t" \ "ldr q"#B0", [x1, #16*0] \n\t" \ "ldr q"#B1", [x1, #16*1] \n\t" \ "add x1, x1, x3 \n\t" // Start microkernel loop. LABEL(K_MKER_LOOP) " \n\t" // Decrease counter before final replica. " subs x4, x4, #1 \n\t" // Branch early to avoid reading excess mem. BEQ(FIN_MKER_LOOP) DGEMM_4X4_MKER_LOOP_PLAIN_LOC_FWD(20,21,8,9) DGEMM_4X4_MKER_LOOP_PLAIN_LOC_FWD(22,23,10,11) DGEMM_4X4_MKER_LOOP_PLAIN_LOC_FWD(24,25,12,13) DGEMM_4X4_MKER_LOOP_PLAIN_LOC_FWD(26,27,14,15) DGEMM_4X4_MKER_LOOP_PLAIN_LOC_FWD(28,29,16,17) DGEMM_4X4_MKER_LOOP_PLAIN_LOC_FWD(30,31,18,19) BRANCH(K_MKER_LOOP) // // Final microkernel loop. LABEL(FIN_MKER_LOOP) DGEMM_4X4_MKER_LOOP_PLAIN_LOC(20,21,8,9) DGEMM_4X4_MKER_LOOP_PLAIN_LOC(22,23,10,11) DGEMM_4X4_MKER_LOOP_PLAIN_LOC(24,25,12,13) DGEMM_4X4_MKER_LOOP_PLAIN_LOC(26,27,14,15) DGEMM_4X4_MKER_LOOP_PLAIN_LOC(28,29,16,17) DGEMM_4X4_MKER_LOOP_PLAIN_LOC(30,31,18,19) // // Loops left behind microkernels. LABEL(K_LEFT_LOOP) " cmp x8, #0 \n\t" // End of exec. BEQ(WRITE_MEM_PREP) " ldr q20, [x0, #16*0] \n\t" " ldr q21, [x0, #16*1] \n\t" " add x0, x0, x2 \n\t" " ldr q8, [x1, #16*0] \n\t" " ldr q9, [x1, #16*1] \n\t" " add x1, x1, x3 \n\t" " sub x8, x8, #1 \n\t" DGEMM_4X4_MKER_LOOP_PLAIN_LOC(20,21,8,9) BRANCH(K_LEFT_LOOP) // // Scale and write to memory. LABEL(WRITE_MEM_PREP) " ldr x4, %[alpha] \n\t" // Load alpha & beta (address). " ldr x8, %[beta] \n\t" " ldr d8, [x4] \n\t" // Load alpha & beta (value). " ldr d9, [x8] \n\t" " \n\t" LABEL(PREFETCH_ABNEXT) " ldr x0, %[a_next] \n\t" " ldr x1, %[b_next] \n\t" " prfm PLDL1STRM, [x0, 64*0] \n\t" // Do not know cache line size, " prfm PLDL1STRM, [x0, 64*1] \n\t" // issue some number of prfm instructions " prfm PLDL1STRM, [x0, 64*2] \n\t" // to try to activate hardware prefetcher. " prfm PLDL1STRM, [x1, 64*0] \n\t" " prfm PLDL1STRM, [x1, 64*1] \n\t" " prfm PLDL1STRM, [x1, 64*3] \n\t" " \n\t" " mov x9, x5 \n\t" // C address for loading. " \n\t" // C address for storing is x5 itself. " cmp x6, #1 \n\t" // Check for generic storage. BNE(WRITE_MEM_G) // // Contiguous C-storage. LABEL(WRITE_MEM_C) DLOADC_2V_C_FWD(10,11,x9,0,x7) DLOADC_2V_C_FWD(12,13,x9,0,x7) DLOADC_2V_C_FWD(14,15,x9,0,x7) DLOADC_2V_C_FWD(16,17,x9,0,x7) DSCALE8V(10,11,12,13,14,15,16,17,9,0) DSCALEA8V(10,11,12,13,14,15,16,17,0,1,2,3,4,5,6,7,8,0) DSTOREC_2V_C_FWD(10,11,x5,0,x7) DSTOREC_2V_C_FWD(12,13,x5,0,x7) DSTOREC_2V_C_FWD(14,15,x5,0,x7) DSTOREC_2V_C_FWD(16,17,x5,0,x7) BRANCH(END_WRITE_MEM) // // Generic-strided C-storage. LABEL(WRITE_MEM_G) // TODO: Implement. LABEL(END_WRITE_MEM) : : [a] "m" (a), [b] "m" (b), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c), [k_mker] "m" (k_mker), [k_left] "m" (k_left), [alpha] "m" (alpha), [beta] "m" (beta), [a_next] "m" (a_next), [b_next] "m" (b_next) : "x0","x1","x2","x3","x4","x5","x6","x7","x8", "x9","x16", "v0","v1","v2","v3","v4","v5","v6","v7", "v8","v9","v10","v11","v12","v13","v14","v15", "v16","v17","v18","v19", "v20","v21","v22","v23", "v24","v25","v26","v27", "v28","v29","v30","v31" ); } blis-0.9.0/kernels/armv8a/3/old/bli_gemm_armv8a_asm_d6x8r.c000066400000000000000000000346021422157504600233350ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2021, The University of Tokyo 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // Label locality & misc. #include "armv8a_asm_utils.h" // Nanokernel operations. #include "armv8a_asm_d2x2.h" /* Order of row-major DGEMM_6x8's execution in 2x2 blocks: * * +---+ +---+ +---+ +---+ * | 0 | | 1 | | 6 | | 7 | * +---+ +---+ +---+ +---+ * +---+ +---+ +---+ +---+ * | 2 | | 3 | | 8 | | 9 | * +---+ +---+ +---+ +---+ * +---+ +---+ +---+ +---+ * | 4 | | 5 | | 10| | 11| * +---+ +---+ +---+ +---+ * */ #define DGEMM_6X8_MKER_LOOP_PLAIN(C00,C01,C02,C03,C10,C11,C12,C13,C20,C21,C22,C23,C30,C31,C32,C33,C40,C41,C42,C43,C50,C51,C52,C53,A0,A1,A2,B0,B1,B2,B3,AADDR,ASHIFT,BADDR,BSHIFT,LOADNEXT) \ DGEMM_2X2_NANOKERNEL(C00,C10,B0,A0) \ DGEMM_2X2_NANOKERNEL(C01,C11,B1,A0) \ DGEMM_2X2_NANOKERNEL(C20,C30,B0,A1) \ DGEMM_2X2_NANOKERNEL(C21,C31,B1,A1) \ DGEMM_2X2_NANOKERNEL(C40,C50,B0,A2) \ DGEMM_2X2_NANOKERNEL(C41,C51,B1,A2) \ DGEMM_LOAD2V_ ##LOADNEXT (B0,B1,BADDR,BSHIFT) \ DGEMM_2X2_NANOKERNEL(C02,C12,B2,A0) \ DGEMM_2X2_NANOKERNEL(C03,C13,B3,A0) \ DGEMM_LOAD1V_ ##LOADNEXT (A0,AADDR,ASHIFT) \ DGEMM_2X2_NANOKERNEL(C22,C32,B2,A1) \ DGEMM_2X2_NANOKERNEL(C23,C33,B3,A1) \ DGEMM_LOAD1V_ ##LOADNEXT (A1,AADDR,ASHIFT+16) \ DGEMM_2X2_NANOKERNEL(C42,C52,B2,A2) \ DGEMM_2X2_NANOKERNEL(C43,C53,B3,A2) // Interleaving load or not. #define DGEMM_LOAD1V_noload(V1,ADDR,IMM) #define DGEMM_LOAD1V_load(V1,ADDR,IMM) \ " ldr q"#V1", ["#ADDR", #"#IMM"] \n\t" #define DGEMM_LOAD2V_noload(V1,V2,ADDR,IMM) #define DGEMM_LOAD2V_load(V1,V2,ADDR,IMM) \ DGEMM_LOAD1V_load(V1,ADDR,IMM) \ DGEMM_LOAD1V_load(V2,ADDR,IMM+16) // For contiguous storage of C. #define DLOADC_4V_R_FWD(C0,C1,C2,C3,CADDR,CSHIFT,RSC) \ DLOAD4V(C0,C1,C2,C3,CADDR,CSHIFT) \ " add "#CADDR", "#CADDR", "#RSC" \n\t" #define DSTOREC_4V_R_FWD(C0,C1,C2,C3,CADDR,CSHIFT,RSC) \ DSTORE4V(C0,C1,C2,C3,CADDR,CSHIFT) \ " add "#CADDR", "#CADDR", "#RSC" \n\t" #define DPRFMC_FWD(CADDR,RSC) \ " prfm PLDL1KEEP, ["#CADDR"] \n\t" \ " add "#CADDR", "#CADDR", "#RSC" \n\t" // For scattered storage of C. #define DLOADC_GATHER_4V_R_FWD(C0,C1,C2,C3,CADDR,CELEM,CSC,RSC) \ " mov "#CELEM", "#CADDR" \n\t" \ DLOAD1V_GATHER_ELMFWD(C0,CELEM,CSC) \ DLOAD1V_GATHER_ELMFWD(C1,CELEM,CSC) \ DLOAD1V_GATHER_ELMFWD(C2,CELEM,CSC) \ DLOAD1V_GATHER_ELMFWD(C3,CELEM,CSC) \ " add "#CADDR", "#CADDR", "#RSC" \n\t" #define DSTOREC_SCATTER_4V_R_FWD(C0,C1,C2,C3,CADDR,CELEM,CSC,RSC) \ " mov "#CELEM", "#CADDR" \n\t" \ DSTORE1V_SCATTER_ELMFWD(C0,CELEM,CSC) \ DSTORE1V_SCATTER_ELMFWD(C1,CELEM,CSC) \ DSTORE1V_SCATTER_ELMFWD(C2,CELEM,CSC) \ DSTORE1V_SCATTER_ELMFWD(C3,CELEM,CSC) \ " add "#CADDR", "#CADDR", "#RSC" \n\t" void bli_dgemm_armv8a_asm_6x8r ( dim_t k0, double* restrict alpha, double* restrict a, double* restrict b, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { void* a_next = bli_auxinfo_next_a( data ); void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_mker = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; __asm__ volatile ( " ldr x0, %[a] \n\t" " ldr x1, %[b] \n\t" " mov x2, #6 \n\t" // Column-skip of A. " mov x3, #8 \n\t" // Row-skip of B. " \n\t" " ldr x5, %[c] \n\t" " ldr x6, %[rs_c] \n\t" // Row-skip of C. " ldr x7, %[cs_c] \n\t" // Column-skip of C. " \n\t" " \n\t" // Multiply some address skips by sizeof(double). " lsl x2, x2, #3 \n\t" // cs_a " lsl x3, x3, #3 \n\t" // rs_b " lsl x6, x6, #3 \n\t" // rs_c " lsl x7, x7, #3 \n\t" // cs_c " \n\t" " mov x9, x5 \n\t" " cmp x7, #8 \n\t" // Do not prefetch C for generic strided. BNE(C_PREFETCH_END) DPRFMC_FWD(x9,x6) DPRFMC_FWD(x9,x6) DPRFMC_FWD(x9,x6) DPRFMC_FWD(x9,x6) DPRFMC_FWD(x9,x6) DPRFMC_FWD(x9,x6) LABEL(C_PREFETCH_END) " \n\t" " ldr x4, %[k_mker] \n\t" // Number of loops. " ldr x8, %[k_left] \n\t" " \n\t" // Storage scheme: // V[ 0:23] <- C // V[24:27] <- A // V[28:31] <- B // Under this scheme, the following is defined: #define DGEMM_6X8_MKER_LOOP_PLAIN_LOC(A0,A1,A2,B0,B1,B2,B3,AADDR,ASHIFT,BADDR,BSHIFT,LOADNEXT) \ DGEMM_6X8_MKER_LOOP_PLAIN(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,A0,A1,A2,B0,B1,B2,B3,AADDR,ASHIFT,BADDR,BSHIFT,LOADNEXT) // Load from memory. LABEL(LOAD_ABC) " \n\t" // No-microkernel early return is a must " cmp x4, #0 \n\t" // to avoid out-of-boundary read. BEQ(CLEAR_CCOLS) " \n\t" " ldr q24, [x0, #16*0] \n\t" // Load A. " ldr q25, [x0, #16*1] \n\t" " ldr q26, [x0, #16*2] \n\t" " add x0, x0, x2 \n\t" " ldr q27, [x0, #16*0] \n\t" " \n\t" " ldr q28, [x1, #16*0] \n\t" // Load B. " ldr q29, [x1, #16*1] \n\t" " ldr q30, [x1, #16*2] \n\t" " ldr q31, [x1, #16*3] \n\t" " add x1, x1, x3 \n\t" LABEL(CLEAR_CCOLS) CLEAR8V(0,1,2,3,4,5,6,7) CLEAR8V(8,9,10,11,12,13,14,15) CLEAR8V(16,17,18,19,20,21,22,23) // No-microkernel early return, once again. BEQ(K_LEFT_LOOP) // // Microkernel is defined here as: #define DGEMM_6X8_MKER_LOOP_PLAIN_LOC_FWD(A0,A1,A2,B0,B1,B2,B3) \ DGEMM_6X8_MKER_LOOP_PLAIN_LOC(A0,A1,A2,B0,B1,B2,B3,x0,1*16,x1,0,load) \ "add x0, x0, x2 \n\t" \ "ldr q"#A2", [x0, #16*0] \n\t" \ "ldr q"#B2", [x1, #16*2] \n\t" \ "ldr q"#B3", [x1, #16*3] \n\t" \ "add x1, x1, x3 \n\t" // Start microkernel loop. LABEL(K_MKER_LOOP) DGEMM_6X8_MKER_LOOP_PLAIN_LOC_FWD(24,25,26,28,29,30,31) DGEMM_6X8_MKER_LOOP_PLAIN_LOC_FWD(27,24,25,28,29,30,31) " \n\t" // Decrease counter before final replica. " subs x4, x4, #1 \n\t" // Branch early to avoid reading excess mem. BEQ(FIN_MKER_LOOP) DGEMM_6X8_MKER_LOOP_PLAIN_LOC_FWD(26,27,24,28,29,30,31) DGEMM_6X8_MKER_LOOP_PLAIN_LOC_FWD(25,26,27,28,29,30,31) BRANCH(K_MKER_LOOP) // // Final microkernel loop. LABEL(FIN_MKER_LOOP) DGEMM_6X8_MKER_LOOP_PLAIN_LOC(26,27,24,28,29,30,31,x0,1*16,x1,0,load) " add x0, x0, x2 \n\t" " ldr q30, [x1, #16*2] \n\t" " ldr q31, [x1, #16*3] \n\t" " add x1, x1, x3 \n\t" DGEMM_6X8_MKER_LOOP_PLAIN_LOC(25,26,27,28,29,30,31,xzr,-1,xzr,-1,noload) // // Loops left behind microkernels. LABEL(K_LEFT_LOOP) " cmp x8, #0 \n\t" // End of exec. BEQ(WRITE_MEM_PREP) " ldr q24, [x0, #16*0] \n\t" // Load A col. " ldr q25, [x0, #16*1] \n\t" " ldr q26, [x0, #16*2] \n\t" " add x0, x0, x2 \n\t" " ldr q28, [x1, #16*0] \n\t" // Load B row. " ldr q29, [x1, #16*1] \n\t" " ldr q30, [x1, #16*2] \n\t" " ldr q31, [x1, #16*3] \n\t" " add x1, x1, x3 \n\t" " sub x8, x8, #1 \n\t" DGEMM_6X8_MKER_LOOP_PLAIN_LOC(24,25,26,28,29,30,31,xzr,-1,xzr,-1,noload) BRANCH(K_LEFT_LOOP) // // Scale and write to memory. LABEL(WRITE_MEM_PREP) " ldr x4, %[alpha] \n\t" // Load alpha & beta (address). " ldr x8, %[beta] \n\t" " ld1r {v24.2d}, [x4] \n\t" // Load alpha & beta. " ld1r {v25.2d}, [x8] \n\t" " \n\t" LABEL(PREFETCH_ABNEXT) " ldr x0, %[a_next] \n\t" " ldr x1, %[b_next] \n\t" " prfm PLDL1STRM, [x0, 64*0] \n\t" // Do not know cache line size, " prfm PLDL1STRM, [x0, 64*1] \n\t" // issue some number of prfm instructions " prfm PLDL1STRM, [x0, 64*2] \n\t" // to try to activate hardware prefetcher. " prfm PLDL1STRM, [x1, 64*0] \n\t" " prfm PLDL1STRM, [x1, 64*1] \n\t" " prfm PLDL1STRM, [x1, 64*3] \n\t" " \n\t" " fmov d26, #1.0 \n\t" " fcmp d24, d26 \n\t" BEQ(UNIT_ALPHA) DSCALE8V(0,1,2,3,4,5,6,7,24,0) DSCALE8V(8,9,10,11,12,13,14,15,24,0) DSCALE8V(16,17,18,19,20,21,22,23,24,0) LABEL(UNIT_ALPHA) " \n\t" " mov x9, x5 \n\t" // C address for loading. " \n\t" // C address for storing is x5 itself. " cmp x7, #8 \n\t" // Check for generic storage. BNE(WRITE_MEM_G) // // Contiguous C-storage. LABEL(WRITE_MEM_R) " fcmp d25, #0.0 \n\t" // Sets conditional flag whether *beta == 0. " \n\t" // This conditional flag will be used " \n\t" // multiple times for skipping load. // Row 0: BEQ(ZERO_BETA_R_0) DLOADC_4V_R_FWD(26,27,28,29,x9,0,x6) DSCALEA4V(0,1,2,3,26,27,28,29,25,0) LABEL(ZERO_BETA_R_0) DSTOREC_4V_R_FWD(0,1,2,3,x5,0,x6) // Row 1 & 2: BEQ(ZERO_BETA_R_1_2) DLOADC_4V_R_FWD(26,27,28,29,x9,0,x6) DLOADC_4V_R_FWD(0,1,2,3,x9,0,x6) DSCALEA8V(4,5,6,7,8,9,10,11,26,27,28,29,0,1,2,3,25,0) LABEL(ZERO_BETA_R_1_2) DSTOREC_4V_R_FWD(4,5,6,7,x5,0,x6) DSTOREC_4V_R_FWD(8,9,10,11,x5,0,x6) // Row 3 & 4 & 5: BEQ(ZERO_BETA_R_3_4_5) DLOADC_4V_R_FWD(0,1,2,3,x9,0,x6) DLOADC_4V_R_FWD(4,5,6,7,x9,0,x6) DLOADC_4V_R_FWD(8,9,10,11,x9,0,x6) DSCALEA8V(12,13,14,15,16,17,18,19,0,1,2,3,4,5,6,7,25,0) DSCALEA4V(20,21,22,23,8,9,10,11,25,0) LABEL(ZERO_BETA_R_3_4_5) DSTOREC_4V_R_FWD(12,13,14,15,x5,0,x6) DSTOREC_4V_R_FWD(16,17,18,19,x5,0,x6) DSTOREC_4V_R_FWD(20,21,22,23,x5,0,x6) BRANCH(END_WRITE_MEM) // // Generic-strided C-storage. LABEL(WRITE_MEM_G) " fcmp d25, #0.0 \n\t" // Sets conditional flag whether *beta == 0. " \n\t" // Row 0: BEQ(ZERO_BETA_G_0) DLOADC_GATHER_4V_R_FWD(26,27,28,29,x9,x0,x7,x6) DSCALEA4V(0,1,2,3,26,27,28,29,25,0) LABEL(ZERO_BETA_G_0) DSTOREC_SCATTER_4V_R_FWD(0,1,2,3,x5,x1,x7,x6) // Row 1 & 2: BEQ(ZERO_BETA_G_1_2) DLOADC_GATHER_4V_R_FWD(26,27,28,29,x9,x0,x7,x6) DLOADC_GATHER_4V_R_FWD(0,1,2,3,x9,x0,x7,x6) DSCALEA8V(4,5,6,7,8,9,10,11,26,27,28,29,0,1,2,3,25,0) LABEL(ZERO_BETA_G_1_2) DSTOREC_SCATTER_4V_R_FWD(4,5,6,7,x5,x1,x7,x6) DSTOREC_SCATTER_4V_R_FWD(8,9,10,11,x5,x1,x7,x6) // Row 3 & 4 & 5: BEQ(ZERO_BETA_G_3_4_5) DLOADC_GATHER_4V_R_FWD(0,1,2,3,x9,x0,x7,x6) DLOADC_GATHER_4V_R_FWD(4,5,6,7,x9,x0,x7,x6) DLOADC_GATHER_4V_R_FWD(8,9,10,11,x9,x0,x7,x6) DSCALEA8V(12,13,14,15,16,17,18,19,0,1,2,3,4,5,6,7,25,0) DSCALEA4V(20,21,22,23,8,9,10,11,25,0) LABEL(ZERO_BETA_G_3_4_5) DSTOREC_SCATTER_4V_R_FWD(12,13,14,15,x5,x1,x7,x6) DSTOREC_SCATTER_4V_R_FWD(16,17,18,19,x5,x1,x7,x6) DSTOREC_SCATTER_4V_R_FWD(20,21,22,23,x5,x1,x7,x6) LABEL(END_WRITE_MEM) : : [a] "m" (a), [b] "m" (b), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c), [k_mker] "m" (k_mker), [k_left] "m" (k_left), [alpha] "m" (alpha), [beta] "m" (beta), [a_next] "m" (a_next), [b_next] "m" (b_next) : "x0","x1","x2","x3","x4","x5","x6","x7","x8","x9", "v0","v1","v2","v3","v4","v5","v6","v7", "v8","v9","v10","v11","v12","v13","v14","v15", "v16","v17","v18","v19", "v20","v21","v22","v23", "v24","v25","v26","v27", "v28","v29","v30","v31" ); } blis-0.9.0/kernels/armv8a/3/old/bli_gemm_armv8a_asm_d8x4.c000066400000000000000000000274231422157504600231540ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2021, The University of Tokyo 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "assert.h" // Label locality & misc. #include "armv8a_asm_utils.h" // Nanokernel operations. #include "armv8a_asm_d2x2.h" /* Order of DGEMM_8x4's execution in 2x2 blocks: * * +---+ +---+ * | 0 | | 2 | * +---+ +---+ * +---+ +---+ * | 1 | | 3 | * +---+ +---+ * +---+ +---+ * | 4 | | 6 | * +---+ +---+ * +---+ +---+ * | 5 | | 7 | * +---+ +---+ * */ #define DGEMM_8X4_MKER_LOOP_PLAIN(C00,C10,C20,C30,C01,C11,C21,C31,C02,C12,C22,C32,C03,C13,C23,C33,A0,A1,A2,A3,B0,B1,AADDR,ASHIFT,BADDR,BSHIFT,LOADNEXT) \ DGEMM_2X2_NANOKERNEL(C00,C01,A0,B0) \ DGEMM_2X2_NANOKERNEL(C10,C11,A1,B0) \ DGEMM_2X2_NANOKERNEL(C02,C03,A0,B1) \ DGEMM_2X2_NANOKERNEL(C12,C13,A1,B1) \ DGEMM_LOAD2V_ ##LOADNEXT (A0,A1,AADDR,ASHIFT) \ DGEMM_2X2_NANOKERNEL(C20,C21,A2,B0) \ DGEMM_2X2_NANOKERNEL(C30,C31,A3,B0) \ DGEMM_LOAD1V_ ##LOADNEXT (B0,BADDR,BSHIFT) \ DGEMM_2X2_NANOKERNEL(C22,C23,A2,B1) \ DGEMM_2X2_NANOKERNEL(C32,C33,A3,B1) // Interleaving load or not. #define DGEMM_LOAD1V_noload(V1,ADDR,IMM) #define DGEMM_LOAD1V_load(V1,ADDR,IMM) \ " ldr q"#V1", ["#ADDR", #"#IMM"] \n\t" #define DGEMM_LOAD2V_noload(V1,V2,ADDR,IMM) #define DGEMM_LOAD2V_load(V1,V2,ADDR,IMM) \ DGEMM_LOAD1V_load(V1,ADDR,IMM) \ DGEMM_LOAD1V_load(V2,ADDR,IMM+16) // For contiguous storage of C. #define DLOADC_4V_C_FWD(C0,C1,C2,C3,CADDR,CSHIFT,LDC) \ DLOAD4V(C0,C1,C2,C3,CADDR,CSHIFT) \ " add "#CADDR", "#CADDR", "#LDC" \n\t" #define DSTOREC_4V_C_FWD(C0,C1,C2,C3,CADDR,CSHIFT,LDC) \ DSTORE4V(C0,C1,C2,C3,CADDR,CSHIFT) \ " add "#CADDR", "#CADDR", "#LDC" \n\t" void bli_dgemm_armv8a_asm_8x4 ( dim_t k0, double* restrict alpha, double* restrict a, double* restrict b, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { void* a_next = bli_auxinfo_next_a( data ); void* b_next = bli_auxinfo_next_b( data ); // This kernel is a WIP. // I have no generic stride support at this moment. assert( rs_c0 == 1 ); // if ( rs_c0 != 1 ) return ; // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_mker = k0 / 6; uint64_t k_left = k0 % 6; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; __asm__ volatile ( " ldr x0, %[a] \n\t" " ldr x1, %[b] \n\t" " mov x2, #8 \n\t" // Column-skip of A. " mov x3, #4 \n\t" // Row-skip of B. " \n\t" " ldr x5, %[c] \n\t" " ldr x6, %[rs_c] \n\t" // Row-skip of C. " ldr x7, %[cs_c] \n\t" // Column-skip of C. " \n\t" " mov x8, #8 \n\t" // Multiply some address skips by sizeof(double). " madd x2, x8, x2, xzr \n\t" // cs_a " madd x3, x8, x3, xzr \n\t" // rs_b " madd x7, x8, x7, xzr \n\t" // cs_c " \n\t" " ldr x4, %[k_mker] \n\t" // Number of loops. " ldr x8, %[k_left] \n\t" " \n\t" // Storage scheme: // V[ 0:15] <- C // V[16:21] <- B // V[22:29] <- A // Under this scheme, the following is defined: #define DGEMM_8X4_MKER_LOOP_PLAIN_LOC(A0,A1,A2,A3,B0,B1,AADDR,ASHIFT,BADDR,BSHIFT,LOADNEXT) \ DGEMM_8X4_MKER_LOOP_PLAIN(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,A0,A1,A2,A3,B0,B1,AADDR,ASHIFT,BADDR,BSHIFT,LOADNEXT) // TODO: Prefetch C. // Load from memory. LABEL(LOAD_ABC) " \n\t" // No-microkernel early return is a must " cmp x4, #0 \n\t" // to avoid out-of-boundary read. BEQ(CLEAR_CCOLS) " \n\t" " ldr q22, [x0, #16*0] \n\t" " ldr q23, [x0, #16*1] \n\t" " ldr q24, [x0, #16*2] \n\t" " ldr q25, [x0, #16*3] \n\t" " add x0, x0, x2 \n\t" " ldr q26, [x0, #16*0] \n\t" " ldr q27, [x0, #16*1] \n\t" " ldr q28, [x0, #16*2] \n\t" " ldr q29, [x0, #16*3] \n\t" " add x0, x0, x2 \n\t" " \n\t" " ldr q16, [x1, #16*0] \n\t" " ldr q17, [x1, #16*1] \n\t" " add x1, x1, x3 \n\t" " ldr q18, [x1, #16*0] \n\t" " ldr q19, [x1, #16*1] \n\t" " add x1, x1, x3 \n\t" " ldr q20, [x1, #16*0] \n\t" " ldr q21, [x1, #16*1] \n\t" " add x1, x1, x3 \n\t" " \n\t" LABEL(CLEAR_CCOLS) CLEAR8V(0,1,2,3,4,5,6,7) CLEAR8V(8,9,10,11,12,13,14,15) // No-microkernel early return, once again. BEQ(K_LEFT_LOOP) // // Microkernel is defined here as: #define DGEMM_8X4_MKER_LOOP_PLAIN_LOC_FWD(A0,A1,A2,A3,B0,B1) \ DGEMM_8X4_MKER_LOOP_PLAIN_LOC(A0,A1,A2,A3,B0,B1,x0,0,x1,0,load) \ "ldr q"#B1", [x1, #16*1] \n\t" \ "ldr q"#A2", [x0, #16*2] \n\t" \ "ldr q"#A3", [x0, #16*3] \n\t" \ "add x1, x1, x3 \n\t" \ "add x0, x0, x2 \n\t" // Start microkernel loop. LABEL(K_MKER_LOOP) DGEMM_8X4_MKER_LOOP_PLAIN_LOC_FWD(22,23,24,25,16,17) DGEMM_8X4_MKER_LOOP_PLAIN_LOC_FWD(26,27,28,29,18,19) DGEMM_8X4_MKER_LOOP_PLAIN_LOC_FWD(22,23,24,25,20,21) " \n\t" // Decrease counter before final replica. " subs x4, x4, #1 \n\t" // Branch early to avoid reading excess mem. BEQ(FIN_MKER_LOOP) DGEMM_8X4_MKER_LOOP_PLAIN_LOC_FWD(26,27,28,29,16,17) DGEMM_8X4_MKER_LOOP_PLAIN_LOC_FWD(22,23,24,25,18,19) DGEMM_8X4_MKER_LOOP_PLAIN_LOC_FWD(26,27,28,29,20,21) BRANCH(K_MKER_LOOP) // // Final microkernel loop. LABEL(FIN_MKER_LOOP) DGEMM_8X4_MKER_LOOP_PLAIN_LOC(26,27,28,29,16,17,x0,0,x1,0,noload) " ldr q26, [x0, #16*0] \n\t" " ldr q27, [x0, #16*1] \n\t" " ldr q28, [x0, #16*2] \n\t" " ldr q29, [x0, #16*3] \n\t" " add x0, x0, x2 \n\t" DGEMM_8X4_MKER_LOOP_PLAIN_LOC(22,23,24,25,18,19,xzr,-1,xzr,-1,noload) DGEMM_8X4_MKER_LOOP_PLAIN_LOC(26,27,28,29,20,21,xzr,-1,xzr,-1,noload) // // Loops left behind microkernels. LABEL(K_LEFT_LOOP) " cmp x8, #0 \n\t" // End of exec. BEQ(WRITE_MEM_PREP) " ldr q22, [x0, #16*0] \n\t" // Load A col. " ldr q23, [x0, #16*1] \n\t" " ldr q24, [x0, #16*2] \n\t" " ldr q25, [x0, #16*3] \n\t" " add x0, x0, x2 \n\t" " ldr q16, [x1, #16*0] \n\t" // Load B col. " ldr q17, [x1, #16*1] \n\t" " add x1, x1, x3 \n\t" " sub x8, x8, #1 \n\t" DGEMM_8X4_MKER_LOOP_PLAIN_LOC(22,23,24,25,16,17,xzr,-1,xzr,-1,noload) BRANCH(K_LEFT_LOOP) // // Scale and write to memory. LABEL(WRITE_MEM_PREP) " ldr x4, %[alpha] \n\t" // Load alpha & beta (address). " ldr x8, %[beta] \n\t" " ldr d16, [x4] \n\t" // Load alpha & beta (value). " ldr d17, [x8] \n\t" " \n\t" LABEL(PREFETCH_ABNEXT) " ldr x0, %[a_next] \n\t" " ldr x1, %[b_next] \n\t" " prfm PLDL1STRM, [x0, 64*0] \n\t" // Do not know cache line size, " prfm PLDL1STRM, [x0, 64*1] \n\t" // issue some number of prfm instructions " prfm PLDL1STRM, [x0, 64*2] \n\t" // to try to activate hardware prefetcher. " prfm PLDL1STRM, [x1, 64*0] \n\t" " prfm PLDL1STRM, [x1, 64*1] \n\t" " prfm PLDL1STRM, [x1, 64*3] \n\t" " \n\t" " mov x9, x5 \n\t" // C address for loading. " \n\t" // C address for storing is x5 itself. " cmp x6, #1 \n\t" // Check for generic storage. BNE(WRITE_MEM_G) // // Contiguous C-storage. LABEL(WRITE_MEM_C) DLOADC_4V_C_FWD(20,21,22,23,x9,0,x7) DLOADC_4V_C_FWD(24,25,26,27,x9,0,x7) DSCALE8V(20,21,22,23,24,25,26,27,17,0) DSCALEA8V(20,21,22,23,24,25,26,27,0,1,2,3,4,5,6,7,16,0) // DLOADC_4V_C_FWD(0,1,2,3,x9,0,x7) DLOADC_4V_C_FWD(4,5,6,7,x9,0,x7) DSCALE8V(0,1,2,3,4,5,6,7,17,0) DSCALEA8V(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,0) // DSTOREC_4V_C_FWD(20,21,22,23,x5,0,x7) DSTOREC_4V_C_FWD(24,25,26,27,x5,0,x7) DSTOREC_4V_C_FWD(0,1,2,3,x5,0,x7) DSTOREC_4V_C_FWD(4,5,6,7,x5,0,x7) BRANCH(END_WRITE_MEM) // // Generic-strided C-storage. LABEL(WRITE_MEM_G) // TODO: Implement. LABEL(END_WRITE_MEM) : : [a] "m" (a), [b] "m" (b), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c), [k_mker] "m" (k_mker), [k_left] "m" (k_left), [alpha] "m" (alpha), [beta] "m" (beta), [a_next] "m" (a_next), [b_next] "m" (b_next) : "x0","x1","x2","x3","x4","x5","x6","x7","x8", "x9","x16", "v0","v1","v2","v3","v4","v5","v6","v7", "v8","v9","v10","v11","v12","v13","v14","v15", "v16","v17","v18","v19", "v20","v21","v22","v23", "v24","v25","v26","v27", "v28","v29","v30","v31" ); } blis-0.9.0/kernels/armv8a/3/sup/000077500000000000000000000000001422157504600162715ustar00rootroot00000000000000blis-0.9.0/kernels/armv8a/3/sup/bli_gemmsup_armv8a_ref.c000066400000000000000000000311451422157504600230560ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // Separate instantiation for Armv8-A reference kernels. // Temporary workaround. Will be removed after upstream has switched to a better way // of exposing gemmsup interface. // // -- Row storage case --------------------------------------------------------- // #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, arch, suf ) \ \ void PASTEMAC3(ch,opname,arch,suf) \ ( \ conj_t conja, \ conj_t conjb, \ dim_t m, \ dim_t n, \ dim_t k, \ ctype* restrict alpha, \ ctype* restrict a, inc_t rs_a, inc_t cs_a, \ ctype* restrict b, inc_t rs_b, inc_t cs_b, \ ctype* restrict beta, \ ctype* restrict c, inc_t rs_c, inc_t cs_c, \ auxinfo_t* restrict data, \ cntx_t* restrict cntx \ ) \ { \ /* NOTE: This microkernel can actually handle arbitrarily large values of m, n, and k. */ \ \ if ( bli_is_noconj( conja ) && bli_is_noconj( conjb ) ) \ { \ /* Traverse c by rows. */ \ for ( dim_t i = 0; i < m; ++i ) \ { \ ctype* restrict ci = &c[ i*rs_c ]; \ ctype* restrict ai = &a[ i*rs_a ]; \ \ for ( dim_t j = 0; j < n; ++j ) \ { \ ctype* restrict cij = &ci[ j*cs_c ]; \ ctype* restrict bj = &b [ j*cs_b ]; \ ctype ab; \ \ PASTEMAC(ch,set0s)( ab ); \ \ /* Perform a dot product to update the (i,j) element of c. */ \ for ( dim_t l = 0; l < k; ++l ) \ { \ ctype* restrict aij = &ai[ l*cs_a ]; \ ctype* restrict bij = &bj[ l*rs_b ]; \ \ PASTEMAC(ch,dots)( *aij, *bij, ab ); \ } \ \ /* If beta is one, add ab into c. If beta is zero, overwrite c with the result in ab. Otherwise, scale by beta and accumulate ab to c. */ \ if ( PASTEMAC(ch,eq1)( *beta ) ) \ { \ PASTEMAC(ch,axpys)( *alpha, ab, *cij ); \ } \ else if ( PASTEMAC(ch,eq0)( *beta ) ) \ { \ PASTEMAC(ch,scal2s)( *alpha, ab, *cij ); \ } \ else \ { \ PASTEMAC(ch,axpbys)( *alpha, ab, *beta, *cij ); \ } \ } \ } \ } \ else if ( bli_is_noconj( conja ) && bli_is_conj( conjb ) ) \ { \ /* Traverse c by rows. */ \ for ( dim_t i = 0; i < m; ++i ) \ { \ ctype* restrict ci = &c[ i*rs_c ]; \ ctype* restrict ai = &a[ i*rs_a ]; \ \ for ( dim_t j = 0; j < n; ++j ) \ { \ ctype* restrict cij = &ci[ j*cs_c ]; \ ctype* restrict bj = &b [ j*cs_b ]; \ ctype ab; \ \ PASTEMAC(ch,set0s)( ab ); \ \ /* Perform a dot product to update the (i,j) element of c. */ \ for ( dim_t l = 0; l < k; ++l ) \ { \ ctype* restrict aij = &ai[ l*cs_a ]; \ ctype* restrict bij = &bj[ l*rs_b ]; \ \ PASTEMAC(ch,axpyjs)( *aij, *bij, ab ); \ } \ \ /* If beta is one, add ab into c. If beta is zero, overwrite c with the result in ab. Otherwise, scale by beta and accumulate ab to c. */ \ if ( PASTEMAC(ch,eq1)( *beta ) ) \ { \ PASTEMAC(ch,axpys)( *alpha, ab, *cij ); \ } \ else if ( PASTEMAC(ch,eq0)( *beta ) ) \ { \ PASTEMAC(ch,scal2s)( *alpha, ab, *cij ); \ } \ else \ { \ PASTEMAC(ch,axpbys)( *alpha, ab, *beta, *cij ); \ } \ } \ } \ } \ else if ( bli_is_conj( conja ) && bli_is_noconj( conjb ) ) \ { \ /* Traverse c by rows. */ \ for ( dim_t i = 0; i < m; ++i ) \ { \ ctype* restrict ci = &c[ i*rs_c ]; \ ctype* restrict ai = &a[ i*rs_a ]; \ \ for ( dim_t j = 0; j < n; ++j ) \ { \ ctype* restrict cij = &ci[ j*cs_c ]; \ ctype* restrict bj = &b [ j*cs_b ]; \ ctype ab; \ \ PASTEMAC(ch,set0s)( ab ); \ \ /* Perform a dot product to update the (i,j) element of c. */ \ for ( dim_t l = 0; l < k; ++l ) \ { \ ctype* restrict aij = &ai[ l*cs_a ]; \ ctype* restrict bij = &bj[ l*rs_b ]; \ \ PASTEMAC(ch,dotjs)( *aij, *bij, ab ); \ } \ \ /* If beta is one, add ab into c. If beta is zero, overwrite c with the result in ab. Otherwise, scale by beta and accumulate ab to c. */ \ if ( PASTEMAC(ch,eq1)( *beta ) ) \ { \ PASTEMAC(ch,axpys)( *alpha, ab, *cij ); \ } \ else if ( PASTEMAC(ch,eq0)( *beta ) ) \ { \ PASTEMAC(ch,scal2s)( *alpha, ab, *cij ); \ } \ else \ { \ PASTEMAC(ch,axpbys)( *alpha, ab, *beta, *cij ); \ } \ } \ } \ } \ else /* if ( bli_is_conj( conja ) && bli_is_conj( conjb ) ) */ \ { \ /* Traverse c by rows. */ \ for ( dim_t i = 0; i < m; ++i ) \ { \ ctype* restrict ci = &c[ i*rs_c ]; \ ctype* restrict ai = &a[ i*rs_a ]; \ \ for ( dim_t j = 0; j < n; ++j ) \ { \ ctype* restrict cij = &ci[ j*cs_c ]; \ ctype* restrict bj = &b [ j*cs_b ]; \ ctype ab; \ \ PASTEMAC(ch,set0s)( ab ); \ \ /* Perform a dot product to update the (i,j) element of c. */ \ for ( dim_t l = 0; l < k; ++l ) \ { \ ctype* restrict aij = &ai[ l*cs_a ]; \ ctype* restrict bij = &bj[ l*rs_b ]; \ \ PASTEMAC(ch,dots)( *aij, *bij, ab ); \ } \ \ /* Conjugate the result to simulate conj(a^T) * conj(b). */ \ PASTEMAC(ch,conjs)( ab ); \ \ /* If beta is one, add ab into c. If beta is zero, overwrite c with the result in ab. Otherwise, scale by beta and accumulate ab to c. */ \ if ( PASTEMAC(ch,eq1)( *beta ) ) \ { \ PASTEMAC(ch,axpys)( *alpha, ab, *cij ); \ } \ else if ( PASTEMAC(ch,eq0)( *beta ) ) \ { \ PASTEMAC(ch,scal2s)( *alpha, ab, *cij ); \ } \ else \ { \ PASTEMAC(ch,axpbys)( *alpha, ab, *beta, *cij ); \ } \ } \ } \ } \ } INSERT_GENTFUNC_BASIC2( gemmsup_r, _armv8a, _ref2 ) // // -- Column storage case ------------------------------------------------------ // #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, arch, suf ) \ \ void PASTEMAC3(ch,opname,arch,suf) \ ( \ conj_t conja, \ conj_t conjb, \ dim_t m, \ dim_t n, \ dim_t k, \ ctype* restrict alpha, \ ctype* restrict a, inc_t rs_a, inc_t cs_a, \ ctype* restrict b, inc_t rs_b, inc_t cs_b, \ ctype* restrict beta, \ ctype* restrict c, inc_t rs_c, inc_t cs_c, \ auxinfo_t* restrict data, \ cntx_t* restrict cntx \ ) \ { \ /* NOTE: This microkernel can actually handle arbitrarily large values of m, n, and k. */ \ \ if ( bli_is_noconj( conja ) && bli_is_noconj( conjb ) ) \ { \ /* Traverse c by columns. */ \ for ( dim_t j = 0; j < n; ++j ) \ { \ ctype* restrict cj = &c[ j*cs_c ]; \ ctype* restrict bj = &b[ j*cs_b ]; \ \ for ( dim_t i = 0; i < m; ++i ) \ { \ ctype* restrict cij = &cj[ i*rs_c ]; \ ctype* restrict ai = &a [ i*rs_a ]; \ ctype ab; \ \ PASTEMAC(ch,set0s)( ab ); \ \ /* Perform a dot product to update the (i,j) element of c. */ \ for ( dim_t l = 0; l < k; ++l ) \ { \ ctype* restrict aij = &ai[ l*cs_a ]; \ ctype* restrict bij = &bj[ l*rs_b ]; \ \ PASTEMAC(ch,dots)( *aij, *bij, ab ); \ } \ \ /* If beta is one, add ab into c. If beta is zero, overwrite c with the result in ab. Otherwise, scale by beta and accumulate ab to c. */ \ if ( PASTEMAC(ch,eq1)( *beta ) ) \ { \ PASTEMAC(ch,axpys)( *alpha, ab, *cij ); \ } \ else if ( PASTEMAC(ch,eq0)( *beta ) ) \ { \ PASTEMAC(ch,scal2s)( *alpha, ab, *cij ); \ } \ else \ { \ PASTEMAC(ch,axpbys)( *alpha, ab, *beta, *cij ); \ } \ } \ } \ } \ else if ( bli_is_noconj( conja ) && bli_is_conj( conjb ) ) \ { \ /* Traverse c by columns. */ \ for ( dim_t j = 0; j < n; ++j ) \ { \ ctype* restrict cj = &c[ j*cs_c ]; \ ctype* restrict bj = &b[ j*cs_b ]; \ \ for ( dim_t i = 0; i < m; ++i ) \ { \ ctype* restrict cij = &cj[ i*rs_c ]; \ ctype* restrict ai = &a [ i*rs_a ]; \ ctype ab; \ \ PASTEMAC(ch,set0s)( ab ); \ \ /* Perform a dot product to update the (i,j) element of c. */ \ for ( dim_t l = 0; l < k; ++l ) \ { \ ctype* restrict aij = &ai[ l*cs_a ]; \ ctype* restrict bij = &bj[ l*rs_b ]; \ \ PASTEMAC(ch,axpyjs)( *aij, *bij, ab ); \ } \ \ /* If beta is one, add ab into c. If beta is zero, overwrite c with the result in ab. Otherwise, scale by beta and accumulate ab to c. */ \ if ( PASTEMAC(ch,eq1)( *beta ) ) \ { \ PASTEMAC(ch,axpys)( *alpha, ab, *cij ); \ } \ else if ( PASTEMAC(ch,eq0)( *beta ) ) \ { \ PASTEMAC(ch,scal2s)( *alpha, ab, *cij ); \ } \ else \ { \ PASTEMAC(ch,axpbys)( *alpha, ab, *beta, *cij ); \ } \ } \ } \ } \ else if ( bli_is_conj( conja ) && bli_is_noconj( conjb ) ) \ { \ /* Traverse c by columns. */ \ for ( dim_t j = 0; j < n; ++j ) \ { \ ctype* restrict cj = &c[ j*cs_c ]; \ ctype* restrict bj = &b[ j*cs_b ]; \ \ for ( dim_t i = 0; i < m; ++i ) \ { \ ctype* restrict cij = &cj[ i*rs_c ]; \ ctype* restrict ai = &a [ i*rs_a ]; \ ctype ab; \ \ PASTEMAC(ch,set0s)( ab ); \ \ /* Perform a dot product to update the (i,j) element of c. */ \ for ( dim_t l = 0; l < k; ++l ) \ { \ ctype* restrict aij = &ai[ l*cs_a ]; \ ctype* restrict bij = &bj[ l*rs_b ]; \ \ PASTEMAC(ch,dotjs)( *aij, *bij, ab ); \ } \ \ /* If beta is one, add ab into c. If beta is zero, overwrite c with the result in ab. Otherwise, scale by beta and accumulate ab to c. */ \ if ( PASTEMAC(ch,eq1)( *beta ) ) \ { \ PASTEMAC(ch,axpys)( *alpha, ab, *cij ); \ } \ else if ( PASTEMAC(ch,eq0)( *beta ) ) \ { \ PASTEMAC(ch,scal2s)( *alpha, ab, *cij ); \ } \ else \ { \ PASTEMAC(ch,axpbys)( *alpha, ab, *beta, *cij ); \ } \ } \ } \ } \ else /* if ( bli_is_conj( conja ) && bli_is_conj( conjb ) ) */ \ { \ /* Traverse c by columns. */ \ for ( dim_t j = 0; j < n; ++j ) \ { \ ctype* restrict cj = &c[ j*cs_c ]; \ ctype* restrict bj = &b[ j*cs_b ]; \ \ for ( dim_t i = 0; i < m; ++i ) \ { \ ctype* restrict cij = &cj[ i*rs_c ]; \ ctype* restrict ai = &a [ i*rs_a ]; \ ctype ab; \ \ PASTEMAC(ch,set0s)( ab ); \ \ /* Perform a dot product to update the (i,j) element of c. */ \ for ( dim_t l = 0; l < k; ++l ) \ { \ ctype* restrict aij = &ai[ l*cs_a ]; \ ctype* restrict bij = &bj[ l*rs_b ]; \ \ PASTEMAC(ch,dots)( *aij, *bij, ab ); \ } \ \ /* Conjugate the result to simulate conj(a^T) * conj(b). */ \ PASTEMAC(ch,conjs)( ab ); \ \ /* If beta is one, add ab into c. If beta is zero, overwrite c with the result in ab. Otherwise, scale by beta and accumulate ab to c. */ \ if ( PASTEMAC(ch,eq1)( *beta ) ) \ { \ PASTEMAC(ch,axpys)( *alpha, ab, *cij ); \ } \ else if ( PASTEMAC(ch,eq0)( *beta ) ) \ { \ PASTEMAC(ch,scal2s)( *alpha, ab, *cij ); \ } \ else \ { \ PASTEMAC(ch,axpbys)( *alpha, ab, *beta, *cij ); \ } \ } \ } \ } \ } INSERT_GENTFUNC_BASIC2( gemmsup_c, _armv8a, _ref2 ) blis-0.9.0/kernels/armv8a/3/sup/bli_gemmsup_rd_armv8a_asm_d6x8m.c000066400000000000000000000471731422157504600246050ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2021, The University of Tokyo 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "assert.h" GEMMSUP_KER_PROT( double, d, gemmsup_r_armv8a_ref2 ) // Label locality & misc. #include "../armv8a_asm_utils.h" #define DGEMM_3X1X2_NKER_SUBLOOP(C0,C1,C2,A0,A1,A2,B) \ " fmla v"#C0".2d, v"#A0".2d, v"#B".2d \n\t" \ " fmla v"#C1".2d, v"#A1".2d, v"#B".2d \n\t" \ " fmla v"#C2".2d, v"#A2".2d, v"#B".2d \n\t" #define DGEMM_3X8X2_K_MKER_LOOP_PLAIN(C00,C01,C02,C03,C04,C05,C06,C07,C10,C11,C12,C13,C14,C15,C16,C17,C20,C21,C22,C23,C24,C25,C26,C27,A0,A1,A2,B0,B1,B2,B3,BADDR,BELEMADDR,BELEMST,LOADNEXT) \ /* Always load before forwarding to the next line. */ \ DGEMM_3X1X2_NKER_SUBLOOP(C00,C10,C20,A0,A1,A2,B0) \ DGEMM_LOAD1V_K_load(B0,BELEMADDR,BELEMST) \ DGEMM_3X1X2_NKER_SUBLOOP(C01,C11,C21,A0,A1,A2,B1) \ DGEMM_LOAD1V_K_load(B1,BELEMADDR,BELEMST) \ DGEMM_3X1X2_NKER_SUBLOOP(C02,C12,C22,A0,A1,A2,B2) \ DGEMM_LOAD1V_K_load(B2,BELEMADDR,BELEMST) \ DGEMM_3X1X2_NKER_SUBLOOP(C03,C13,C23,A0,A1,A2,B3) \ DGEMM_LOAD1V_K_load(B3,BELEMADDR,BELEMST) \ \ " add "#BADDR", "#BADDR", #16 \n\t" \ " mov "#BELEMADDR", "#BADDR" \n\t" \ DGEMM_3X1X2_NKER_SUBLOOP(C04,C14,C24,A0,A1,A2,B0) \ DGEMM_LOAD1V_K_ ##LOADNEXT (B0,BELEMADDR,BELEMST) \ DGEMM_3X1X2_NKER_SUBLOOP(C05,C15,C25,A0,A1,A2,B1) \ DGEMM_LOAD1V_K_ ##LOADNEXT (B1,BELEMADDR,BELEMST) \ DGEMM_3X1X2_NKER_SUBLOOP(C06,C16,C26,A0,A1,A2,B2) \ DGEMM_LOAD1V_K_ ##LOADNEXT (B2,BELEMADDR,BELEMST) \ DGEMM_3X1X2_NKER_SUBLOOP(C07,C17,C27,A0,A1,A2,B3) \ DGEMM_LOAD1V_K_ ##LOADNEXT (B3,BELEMADDR,BELEMST) #define DGEMM_LOAD1V_K_noload(V,ELEMADDR,ELEMST) #define DGEMM_LOAD1V_K_load(V,ELEMADDR,ELEMST) \ " ldr q"#V", [ "#ELEMADDR" ] \n\t" \ " add "#ELEMADDR", "#ELEMADDR", "#ELEMST" \n\t" // For row-storage of C. #define DLOADC_4V_R_FWD(C0,C1,C2,C3,CADDR,CSHIFT,RSC) \ DLOAD4V(C0,C1,C2,C3,CADDR,CSHIFT) \ " add "#CADDR", "#CADDR", "#RSC" \n\t" #define DSTOREC_4V_R_FWD(C0,C1,C2,C3,CADDR,CSHIFT,RSC) \ DSTORE4V(C0,C1,C2,C3,CADDR,CSHIFT) \ " add "#CADDR", "#CADDR", "#RSC" \n\t" // For column-storage of C. #define DLOADC_1V_1ELM_C_FWD(C0,CSCALAR,CIDX,CADDR,CSHIFT,CSC) \ DLOAD1V(C0,CADDR,CSHIFT) \ " add "#CADDR", "#CADDR", #"#CSHIFT"+16 \n\t" \ " ld1 {v"#CSCALAR".d}["#CIDX"], ["#CADDR"] \n\t" \ " sub "#CADDR", "#CADDR", #"#CSHIFT"+16 \n\t" \ " add "#CADDR", "#CADDR", "#CSC" \n\t" #define DSTOREC_1V_1ELM_C_FWD(C0,CSCALAR,CIDX,CADDR,CSHIFT,CSC) \ DSTORE1V(C0,CADDR,CSHIFT) \ " add "#CADDR", "#CADDR", #"#CSHIFT"+16 \n\t" \ " st1 {v"#CSCALAR".d}["#CIDX"], ["#CADDR"] \n\t" \ " sub "#CADDR", "#CADDR", #"#CSHIFT"+16 \n\t" \ " add "#CADDR", "#CADDR", "#CSC" \n\t" #define DSCALE12V(V0,V1,V2,V3,V4,V5,V6,V7,V8,V9,V10,V11,A,IDX) \ DSCALE4V(V0,V1,V2,V3,A,IDX) \ DSCALE4V(V4,V5,V6,V7,A,IDX) \ DSCALE4V(V8,V9,V10,V11,A,IDX) #define DSCALEA12V(D0,D1,D2,D3,D4,D5,D6,D7,D8,D9,D10,D11,S0,S1,S2,S3,S4,S5,S6,S7,S8,S9,S10,S11,A,IDX) \ DSCALEA4V(D0,D1,D2,D3,S0,S1,S2,S3,A,IDX) \ DSCALEA4V(D4,D5,D6,D7,S4,S5,S6,S7,A,IDX) \ DSCALEA4V(D8,D9,D10,D11,S8,S9,S10,S11,A,IDX) #define DPRFMC_FWD(CADDR,DLONGC) \ " prfm PLDL1KEEP, ["#CADDR"] \n\t" \ " add "#CADDR", "#CADDR", "#DLONGC" \n\t" void bli_dgemmsup_rd_armv8a_asm_6x8m ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { if ( n0 != 8 ) { if ( n0 < 8 ) { for ( ; n0 >= 4; n0 -= 4 ) { dim_t m = m0; double *a_loc = a; double *c_loc = c; for ( ; m >= 3; m -= 3 ) { bli_dgemmsup_rd_armv8a_asm_3x4 ( conja, conjb, 3, 4, k0, alpha, a_loc, rs_a0, cs_a0, b, rs_b0, cs_b0, beta, c_loc, rs_c0, cs_c0, data, cntx ); a_loc += 3 * rs_a0; c_loc += 3 * rs_c0; } if ( m > 0 ) { bli_dgemmsup_rd_armv8a_int_3x4 ( conja, conjb, m, 4, k0, alpha, a_loc, rs_a0, cs_a0, b, rs_b0, cs_b0, beta, c_loc, rs_c0, cs_c0, data, cntx ); } b += 4 * cs_b0; c += 4 * cs_c0; } for ( ; m0 > 0; m0 -= 3 ) { dim_t m_loc = ( m0 < 3 ) ? m0 : 3; bli_dgemmsup_rd_armv8a_int_3x4 ( conja, conjb, m_loc, n0, k0, alpha, a, rs_a0, cs_a0, b, rs_b0, cs_b0, beta, c, rs_c0, cs_c0, data, cntx ); a += 3 * rs_a0; c += 3 * rs_c0; } } else { assert( FALSE ); } return; } // LLVM has very bad routing ability for inline asm. // Limit number of registers in case of Clang compilation. #ifndef __clang__ void* a_next = bli_auxinfo_next_a( data ); void* b_next = bli_auxinfo_next_b( data ); #endif // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_mker = k0 / 4; uint64_t k_left = k0 % 4; int64_t m_iter = m0 / 3; int64_t m_left = m0 % 3; uint64_t rs_a = rs_a0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; assert( cs_a0 == 1 ); assert( rs_b0 == 1 ); if ( m_iter == 0 ) goto consider_edge_cases; __asm__ volatile ( " ldr x10, %[a] \n\t" " ldr x13, %[c] \n\t" " ldr x12, %[m_iter] \n\t" " ldr x2, %[rs_a] \n\t" // Row-skip of A. " ldr x3, %[cs_b] \n\t" // Column-skip of B. " \n\t" " ldr x6, %[rs_c] \n\t" // Row-skip of C. " ldr x7, %[cs_c] \n\t" // Column-skip of C. " \n\t" " \n\t" // Multiply some address skips by sizeof(double). " lsl x2, x2, #3 \n\t" // rs_a " lsl x3, x3, #3 \n\t" // cs_b " lsl x6, x6, #3 \n\t" // rs_c " lsl x7, x7, #3 \n\t" // cs_c " \n\t" " mov x1, x5 \n\t" " cmp x7, #8 \n\t" // Prefetch column-strided C. BEQ(C_PREFETCH_COLS) DPRFMC_FWD(x1,x6) DPRFMC_FWD(x1,x6) DPRFMC_FWD(x1,x6) DPRFMC_FWD(x1,x6) DPRFMC_FWD(x1,x6) DPRFMC_FWD(x1,x6) BRANCH(C_PREFETCH_END) LABEL(C_PREFETCH_COLS) DPRFMC_FWD(x1,x7) DPRFMC_FWD(x1,x7) DPRFMC_FWD(x1,x7) DPRFMC_FWD(x1,x7) DPRFMC_FWD(x1,x7) DPRFMC_FWD(x1,x7) DPRFMC_FWD(x1,x7) DPRFMC_FWD(x1,x7) LABEL(C_PREFETCH_END) // // Millikernel. LABEL(MILLIKER_MLOOP) " \n\t" " mov x0, x10 \n\t" // Parameters to be reloaded " mov x5, x13 \n\t" // within each millikernel loop. " ldr x1, %[b] \n\t" " ldr x4, %[k_mker] \n\t" " ldr x8, %[k_left] \n\t" " \n\t" // Storage scheme: // V[ 0:23] <- C // V[24:26] <- A // V[28:31] <- B // V[ 27 ] <- Not used. // Under this scheme, the following is defined: #define DGEMM_3X8X2_K_MKER_LOOP_PLAIN_LOC(A0,A1,A2,B0,B1,B2,B3,BADDR,BELEMADDR,BELEMST,LOADNEXT) \ DGEMM_3X8X2_K_MKER_LOOP_PLAIN(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,A0,A1,A2,B0,B1,B2,B3,BADDR,BELEMADDR,BELEMST,LOADNEXT) // Load from memory. LABEL(LOAD_ABC) " \n\t" // No-microkernel early return is a must " cmp x4, #0 \n\t" // to avoid out-of-boundary read. BEQ(CLEAR_CCOLS) " \n\t" " mov x11, x1 \n\t" // Load B. " ldr q28, [x11] \n\t" " add x11, x11, x3 \n\t" " ldr q29, [x11] \n\t" " add x11, x11, x3 \n\t" " ldr q30, [x11] \n\t" " add x11, x11, x3 \n\t" " ldr q31, [x11] \n\t" " add x11, x11, x3 \n\t" " \n\t" " mov x14, x0 \n\t" // Load A. " ldr q24, [x14] \n\t" " add x14, x14, x2 \n\t" " ldr q25, [x14] \n\t" " add x14, x14, x2 \n\t" " ldr q26, [x14] \n\t" // " add x14, x14, x2 \n\t" " add x0, x0, #16 \n\t" LABEL(CLEAR_CCOLS) CLEAR8V(0,1,2,3,4,5,6,7) CLEAR8V(8,9,10,11,12,13,14,15) CLEAR8V(16,17,18,19,20,21,22,23) // No-microkernel early return, once again. BEQ(K_LEFT_LOOP) // // Microkernel is defined here as: #define DGEMM_3X8X2_K_MKER_LOOP_PLAIN_LOC_FWD(A0,A1,A2,B0,B1,B2,B3) \ DGEMM_3X8X2_K_MKER_LOOP_PLAIN_LOC(A0,A1,A2,B0,B1,B2,B3,x1,x11,x3,load) \ "mov x14, x0 \n\t" \ "ldr q24, [x14] \n\t" \ "add x14, x14, x2 \n\t" \ "ldr q25, [x14] \n\t" \ "add x14, x14, x2 \n\t" \ "ldr q26, [x14] \n\t" \ /*"add x14, x14, x2 \n\t"*/ \ "add x0, x0, #16 \n\t" // Start microkernel loop. LABEL(K_MKER_LOOP) DGEMM_3X8X2_K_MKER_LOOP_PLAIN_LOC_FWD(24,25,26,28,29,30,31) " \n\t" // Decrease counter before final replica. " subs x4, x4, #1 \n\t" // Branch early to avoid reading excess mem. BEQ(FIN_MKER_LOOP) DGEMM_3X8X2_K_MKER_LOOP_PLAIN_LOC_FWD(24,25,26,28,29,30,31) BRANCH(K_MKER_LOOP) // // Final microkernel loop. LABEL(FIN_MKER_LOOP) DGEMM_3X8X2_K_MKER_LOOP_PLAIN_LOC(24,25,26,28,29,30,31,x1,x11,x3,noload) // // If major kernel is executed, // an additional depth-summation is required. " faddp v0.2d, v0.2d, v1.2d \n\t" // Line 0. " faddp v1.2d, v2.2d, v3.2d \n\t" " faddp v2.2d, v4.2d, v5.2d \n\t" " faddp v3.2d, v6.2d, v7.2d \n\t" " faddp v4.2d, v8.2d, v9.2d \n\t" // Line 1. " faddp v5.2d, v10.2d, v11.2d \n\t" " faddp v6.2d, v12.2d, v13.2d \n\t" " faddp v7.2d, v14.2d, v15.2d \n\t" " faddp v8.2d, v16.2d, v17.2d \n\t" // Line 2. " faddp v9.2d, v18.2d, v19.2d \n\t" " faddp v10.2d, v20.2d, v21.2d \n\t" " faddp v11.2d, v22.2d, v23.2d \n\t" " \n\t" // Loops left behind microkernels. LABEL(K_LEFT_LOOP) " cmp x8, #0 \n\t" // End of exec. BEQ(WRITE_MEM_PREP) " mov x11, x1 \n\t" // Load B row. " ld1 {v28.d}[0], [x11], x3 \n\t" " ld1 {v28.d}[1], [x11], x3 \n\t" " ld1 {v29.d}[0], [x11], x3 \n\t" " ld1 {v29.d}[1], [x11], x3 \n\t" " ld1 {v30.d}[0], [x11], x3 \n\t" " ld1 {v30.d}[1], [x11], x3 \n\t" " ld1 {v31.d}[0], [x11], x3 \n\t" " ld1 {v31.d}[1], [x11], x3 \n\t" " add x1, x1, #8 \n\t" " mov x14, x0 \n\t" // Load A column. " ld1 {v24.d}[0], [x14], x2 \n\t" " ld1 {v24.d}[1], [x14], x2 \n\t" " ld1 {v25.d}[0], [x14], x2 \n\t" " add x0, x0, #8 \n\t" " fmla v0.2d, v28.2d, v24.d[0] \n\t" " fmla v1.2d, v29.2d, v24.d[0] \n\t" " fmla v2.2d, v30.2d, v24.d[0] \n\t" " fmla v3.2d, v31.2d, v24.d[0] \n\t" " fmla v4.2d, v28.2d, v24.d[1] \n\t" " fmla v5.2d, v29.2d, v24.d[1] \n\t" " fmla v6.2d, v30.2d, v24.d[1] \n\t" " fmla v7.2d, v31.2d, v24.d[1] \n\t" " fmla v8.2d, v28.2d, v25.d[0] \n\t" " fmla v9.2d, v29.2d, v25.d[0] \n\t" " fmla v10.2d, v30.2d, v25.d[0] \n\t" " fmla v11.2d, v31.2d, v25.d[0] \n\t" " sub x8, x8, #1 \n\t" BRANCH(K_LEFT_LOOP) // // Scale and write to memory. LABEL(WRITE_MEM_PREP) " ldr x4, %[alpha] \n\t" // Load alpha & beta (address). " ldr x8, %[beta] \n\t" " ld1r {v30.2d}, [x4] \n\t" // Load alpha & beta (value). " ld1r {v31.2d}, [x8] \n\t" " \n\t" " fmov d28, #1.0 \n\t" // Don't scale for unit alpha. " fcmp d30, d28 \n\t" BEQ(UNIT_ALPHA) DSCALE12V(0,1,2,3,4,5,6,7,8,9,10,11,30,0) LABEL(UNIT_ALPHA) " \n\t" " mov x1, x5 \n\t" // C address for loading. " \n\t" // C address for storing is x5 itself. " cmp x7, #8 \n\t" // Check for column-storage. BNE(WRITE_MEM_C) // // C storage in rows. LABEL(WRITE_MEM_R) " fcmp d31, #0.0 \n\t" // Don't load for zero beta. BEQ(ZERO_BETA_R) DLOADC_4V_R_FWD(12,13,14,15,x1,0,x6) DLOADC_4V_R_FWD(16,17,18,19,x1,0,x6) DLOADC_4V_R_FWD(20,21,22,23,x1,0,x6) DSCALEA12V(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,31,0) LABEL(ZERO_BETA_R) #ifndef __clang__ " cmp x12, #1 \n\t" BRANCH(PRFM_END_R) " prfm PLDL1KEEP, [%[a_next], #16*0] \n\t" " prfm PLDL1KEEP, [%[a_next], #16*1] \n\t" " prfm PLDL1STRM, [%[b_next], #16*0] \n\t" " prfm PLDL1STRM, [%[b_next], #16*1] \n\t" LABEL(PRFM_END_R) #endif DSTOREC_4V_R_FWD(0,1,2,3,x5,0,x6) DSTOREC_4V_R_FWD(4,5,6,7,x5,0,x6) DSTOREC_4V_R_FWD(8,9,10,11,x5,0,x6) BRANCH(END_WRITE_MEM) // // C storage in columns. LABEL(WRITE_MEM_C) " trn1 v12.2d, v0.2d, v4.2d \n\t" " trn2 v13.2d, v0.2d, v4.2d \n\t" " trn1 v14.2d, v1.2d, v5.2d \n\t" " trn2 v15.2d, v1.2d, v5.2d \n\t" " trn1 v16.2d, v2.2d, v6.2d \n\t" " trn2 v17.2d, v2.2d, v6.2d \n\t" " trn1 v18.2d, v3.2d, v7.2d \n\t" " trn2 v19.2d, v3.2d, v7.2d \n\t" " fcmp d31, #0.0 \n\t" // Don't load for zero beta. BEQ(ZERO_BETA_C) DLOADC_1V_1ELM_C_FWD(0,20,0,x1,0,x7) DLOADC_1V_1ELM_C_FWD(1,20,1,x1,0,x7) DLOADC_1V_1ELM_C_FWD(2,21,0,x1,0,x7) DLOADC_1V_1ELM_C_FWD(3,21,1,x1,0,x7) DLOADC_1V_1ELM_C_FWD(4,22,0,x1,0,x7) DLOADC_1V_1ELM_C_FWD(5,22,1,x1,0,x7) DLOADC_1V_1ELM_C_FWD(6,23,0,x1,0,x7) DLOADC_1V_1ELM_C_FWD(7,23,1,x1,0,x7) DSCALEA12V(12,13,14,15,16,17,18,19,8,9,10,11,0,1,2,3,4,5,6,7,20,21,22,23,31,0) LABEL(ZERO_BETA_C) #ifndef __clang__ " cmp x12, #1 \n\t" BRANCH(PRFM_END_C) " prfm PLDL1KEEP, [%[a_next], #16*0] \n\t" " prfm PLDL1KEEP, [%[a_next], #16*1] \n\t" " prfm PLDL1STRM, [%[b_next], #16*0] \n\t" " prfm PLDL1STRM, [%[b_next], #16*1] \n\t" LABEL(PRFM_END_C) #endif DSTOREC_1V_1ELM_C_FWD(12,8,0,x5,0,x7) DSTOREC_1V_1ELM_C_FWD(13,8,1,x5,0,x7) DSTOREC_1V_1ELM_C_FWD(14,9,0,x5,0,x7) DSTOREC_1V_1ELM_C_FWD(15,9,1,x5,0,x7) DSTOREC_1V_1ELM_C_FWD(16,10,0,x5,0,x7) DSTOREC_1V_1ELM_C_FWD(17,10,1,x5,0,x7) DSTOREC_1V_1ELM_C_FWD(18,11,0,x5,0,x7) DSTOREC_1V_1ELM_C_FWD(19,11,1,x5,0,x7) // // End of this microkernel. LABEL(END_WRITE_MEM) " \n\t" " subs x12, x12, #1 \n\t" BEQ(END_EXEC) " \n\t" " mov x8, #3 \n\t" " madd x13, x6, x8, x13 \n\t" // Forward C's base address to the next logic panel. " madd x10, x2, x8, x10 \n\t" // Forward A's base address to the next logic panel. BRANCH(MILLIKER_MLOOP) // // End of execution. LABEL(END_EXEC) : : [a] "m" (a), [b] "m" (b), [c] "m" (c), [rs_a] "m" (rs_a), [cs_b] "m" (cs_b), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c), // In Clang, even "m"-passed parameter takes 1 register. // Have to disable prefetching to pass compilation. #ifndef __clang__ [a_next] "r" (a_next), [b_next] "r" (b_next), #endif [m_iter] "m" (m_iter), [k_mker] "m" (k_mker), [k_left] "m" (k_left), [alpha] "m" (alpha), [beta] "m" (beta) : "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10","x11","x12","x13","x14", "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", "v10","v11","v12","v13","v14","v15", "v16","v17","v18","v19","v20","v21","v22","v23", "v24","v25","v26","v27","v28","v29","v30","v31" ); consider_edge_cases: // TODO: Implement optimized kernel for this. // // Forward address. a = a + m_iter * 3 * rs_a; c = c + m_iter * 3 * rs_c; for ( ; m_left > 0; m_left -= 2 ) { dim_t m_loc = ( m_left < 2 ) ? m_left : 2; bli_dgemmsup_rd_armv8a_int_2x8 ( conja, conjb, m_loc, 8, k0, alpha, a, rs_a0, cs_a0, b, rs_b0, cs_b0, beta, c, rs_c0, cs_c0, data, cntx ); a += 2 * rs_a0; c += 2 * rs_c0; } } blis-0.9.0/kernels/armv8a/3/sup/bli_gemmsup_rd_armv8a_asm_d6x8n.c000066400000000000000000000530571422157504600246040ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2021, The University of Tokyo 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "assert.h" GEMMSUP_KER_PROT( double, d, gemmsup_r_armv8a_ref2 ) // Label locality & misc. #include "../armv8a_asm_utils.h" #define DGEMM_1X4X2_NKER_SUBLOOP(C0,C1,C2,C3,A,B0,B1,B2,B3) \ " fmla v"#C0".2d, v"#A".2d, v"#B0".2d \n\t" \ " fmla v"#C1".2d, v"#A".2d, v"#B1".2d \n\t" \ " fmla v"#C2".2d, v"#A".2d, v"#B2".2d \n\t" \ " fmla v"#C3".2d, v"#A".2d, v"#B3".2d \n\t" #define DGEMM_6X4X2_K_MKER_LOOP_PLAIN(C00,C01,C02,C03,C10,C11,C12,C13,C20,C21,C22,C23,C30,C31,C32,C33,C40,C41,C42,C43,C50,C51,C52,C53,A0,A1,A2,A3,B0,B1,B2,B3,AADDR,AELEMADDR,AELEMST,LOADNEXT) \ /* Always load before forwarding to the next line. */ \ DGEMM_1X4X2_NKER_SUBLOOP(C00,C01,C02,C03,A0,B0,B1,B2,B3) \ DGEMM_LOAD1V_K_load(A0,AELEMADDR,AELEMST) \ DGEMM_1X4X2_NKER_SUBLOOP(C10,C11,C12,C13,A1,B0,B1,B2,B3) \ DGEMM_LOAD1V_K_load(A1,AELEMADDR,AELEMST) \ " add "#AADDR", "#AADDR", #16 \n\t" \ " mov "#AELEMADDR", "#AADDR" \n\t" \ DGEMM_1X4X2_NKER_SUBLOOP(C20,C21,C22,C23,A2,B0,B1,B2,B3) \ DGEMM_LOAD1V_K_load(A2,AELEMADDR,AELEMST) \ DGEMM_1X4X2_NKER_SUBLOOP(C30,C31,C32,C33,A3,B0,B1,B2,B3) \ DGEMM_LOAD1V_K_load(A3,AELEMADDR,AELEMST) \ \ DGEMM_1X4X2_NKER_SUBLOOP(C40,C41,C42,C43,A0,B0,B1,B2,B3) \ DGEMM_LOAD1V_K_ ##LOADNEXT (A0,AELEMADDR,AELEMST) \ DGEMM_1X4X2_NKER_SUBLOOP(C50,C51,C52,C53,A1,B0,B1,B2,B3) \ DGEMM_LOAD1V_K_ ##LOADNEXT (A1,AELEMADDR,AELEMST) #define DGEMM_LOAD1V_K_noload(V,ELEMADDR,ELEMST) #define DGEMM_LOAD1V_K_load(V,ELEMADDR,ELEMST) \ " ldr q"#V", [ "#ELEMADDR" ] \n\t" \ " add "#ELEMADDR", "#ELEMADDR", "#ELEMST" \n\t" // For row-storage of C. #define DLOADC_2V_R_FWD(C0,C1,CADDR,CSHIFT,RSC) \ DLOAD2V(C0,C1,CADDR,CSHIFT) \ " add "#CADDR", "#CADDR", "#RSC" \n\t" #define DSTOREC_2V_R_FWD(C0,C1,CADDR,CSHIFT,RSC) \ DSTORE2V(C0,C1,CADDR,CSHIFT) \ " add "#CADDR", "#CADDR", "#RSC" \n\t" // For column-storage of C. #define DLOADC_3V_C_FWD(C0,C1,C2,CADDR,CSHIFT,CSC) \ DLOAD2V(C0,C1,CADDR,CSHIFT) \ DLOAD1V(C2,CADDR,CSHIFT+32) \ " add "#CADDR", "#CADDR", "#CSC" \n\t" #define DSTOREC_3V_C_FWD(C0,C1,C2,CADDR,CSHIFT,CSC) \ DSTORE2V(C0,C1,CADDR,CSHIFT) \ DSTORE1V(C2,CADDR,CSHIFT+32) \ " add "#CADDR", "#CADDR", "#CSC" \n\t" #define DSCALE12V(V0,V1,V2,V3,V4,V5,V6,V7,V8,V9,V10,V11,A,IDX) \ DSCALE4V(V0,V1,V2,V3,A,IDX) \ DSCALE4V(V4,V5,V6,V7,A,IDX) \ DSCALE4V(V8,V9,V10,V11,A,IDX) #define DSCALEA12V(D0,D1,D2,D3,D4,D5,D6,D7,D8,D9,D10,D11,S0,S1,S2,S3,S4,S5,S6,S7,S8,S9,S10,S11,A,IDX) \ DSCALEA4V(D0,D1,D2,D3,S0,S1,S2,S3,A,IDX) \ DSCALEA4V(D4,D5,D6,D7,S4,S5,S6,S7,A,IDX) \ DSCALEA4V(D8,D9,D10,D11,S8,S9,S10,S11,A,IDX) #define DPRFMC_FWD(CADDR,DLONGC) \ " prfm PLDL1KEEP, ["#CADDR"] \n\t" \ " add "#CADDR", "#CADDR", "#DLONGC" \n\t" void bli_dgemmsup_rd_armv8a_asm_6x8n ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { if ( m0 != 6 ) { if ( m0 < 6 ) { if ( m0 == 5 ) { // 3xk calls. dim_t n = n0; double *b_loc = b; double *c_loc = c; for ( ; n >= 4; n -= 4 ) { bli_dgemmsup_rd_armv8a_asm_3x4 ( conja, conjb, 3, 4, k0, alpha, a, rs_a0, cs_a0, b_loc, rs_b0, cs_b0, beta, c_loc, rs_c0, cs_c0, data, cntx ); b_loc += 4 * cs_b0; c_loc += 4 * cs_c0; } if ( n > 0 ) { bli_dgemmsup_rd_armv8a_int_3x4 ( conja, conjb, 3, n, k0, alpha, a, rs_a0, cs_a0, b_loc, rs_b0, cs_b0, beta, c_loc, rs_c0, cs_c0, data, cntx ); } a += 3 * rs_a0; c += 3 * rs_c0; // 2xk calls. for ( ; n0 > 0; n0 -= 8 ) { dim_t n_loc = ( n0 < 8 ) ? n0 : 8; bli_dgemmsup_rd_armv8a_int_2x8 ( conja, conjb, 2, n_loc, k0, alpha, a, rs_a0, cs_a0, b, rs_b0, cs_b0, beta, c, rs_c0, cs_c0, data, cntx ); b += 8 * cs_b0; c += 8 * cs_c0; } return; } else if ( m0 == 4 ) { for ( ; n0 > 0; n0 -= 8 ) { dim_t n_loc = ( n0 < 8 ) ? n0 : 8; bli_dgemmsup_rd_armv8a_int_2x8 ( conja, conjb, 2, n_loc, k0, alpha, a, rs_a0, cs_a0, b, rs_b0, cs_b0, beta, c, rs_c0, cs_c0, data, cntx ); bli_dgemmsup_rd_armv8a_int_2x8 ( conja, conjb, 2, n_loc, k0, alpha, a + 2 * rs_a0, rs_a0, cs_a0, b, rs_b0, cs_b0, beta, c + 2 * rs_c0, rs_c0, cs_c0, data, cntx ); b += 8 * cs_b0; c += 8 * cs_c0; } } else if ( m0 == 3 ) { for ( ; n0 >= 4; n0 -= 4 ) { bli_dgemmsup_rd_armv8a_asm_3x4 ( conja, conjb, 3, 4, k0, alpha, a, rs_a0, cs_a0, b, rs_b0, cs_b0, beta, c, rs_c0, cs_c0, data, cntx ); b += 4 * cs_b0; c += 4 * cs_c0; } if ( n0 > 0 ) { bli_dgemmsup_rd_armv8a_int_3x4 ( conja, conjb, 3, n0, k0, alpha, a, rs_a0, cs_a0, b, rs_b0, cs_b0, beta, c, rs_c0, cs_c0, data, cntx ); } } else // m0 == 2 or 1. { for ( ; n0 > 0; n0 -= 8 ) { dim_t n_loc = ( n0 < 8 ) ? n0 : 8; bli_dgemmsup_rd_armv8a_int_2x8 ( conja, conjb, m0, n_loc, k0, alpha, a, rs_a0, cs_a0, b, rs_b0, cs_b0, beta, c, rs_c0, cs_c0, data, cntx ); b += 8 * cs_b0; c += 8 * cs_c0; } } } else { assert( FALSE ); } return; } // LLVM has very bad routing ability for inline asm. // Limit number of registers in case of Clang compilation. #ifndef __clang__ void* a_next = bli_auxinfo_next_a( data ); void* b_next = bli_auxinfo_next_b( data ); #endif // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_mker = k0 / 4; uint64_t k_left = k0 % 4; int64_t n_iter = n0 / 4; int64_t n_left = n0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; assert( cs_a0 == 1 ); assert( rs_b0 == 1 ); if ( n_iter == 0 ) goto consider_edge_cases; __asm__ volatile ( " ldr x10, %[b] \n\t" " ldr x13, %[c] \n\t" " ldr x12, %[n_iter] \n\t" " ldr x2, %[rs_a] \n\t" // Row-skip of A. " ldr x3, %[cs_b] \n\t" // Column-skip of B. " \n\t" " ldr x6, %[rs_c] \n\t" // Row-skip of C. " ldr x7, %[cs_c] \n\t" // Column-skip of C. " \n\t" " \n\t" // Multiply some address skips by sizeof(double). " lsl x2, x2, #3 \n\t" // rs_a " lsl x3, x3, #3 \n\t" // cs_b " lsl x6, x6, #3 \n\t" // rs_c " lsl x7, x7, #3 \n\t" // cs_c " \n\t" " mov x1, x5 \n\t" " cmp x7, #8 \n\t" // Prefetch column-strided C. BEQ(C_PREFETCH_COLS) DPRFMC_FWD(x1,x6) DPRFMC_FWD(x1,x6) DPRFMC_FWD(x1,x6) DPRFMC_FWD(x1,x6) DPRFMC_FWD(x1,x6) DPRFMC_FWD(x1,x6) BRANCH(C_PREFETCH_END) LABEL(C_PREFETCH_COLS) DPRFMC_FWD(x1,x7) DPRFMC_FWD(x1,x7) DPRFMC_FWD(x1,x7) DPRFMC_FWD(x1,x7) DPRFMC_FWD(x1,x7) DPRFMC_FWD(x1,x7) DPRFMC_FWD(x1,x7) DPRFMC_FWD(x1,x7) LABEL(C_PREFETCH_END) // // Millikernel. LABEL(MILLIKER_MLOOP) " \n\t" " mov x1, x10 \n\t" // Parameters to be reloaded " mov x5, x13 \n\t" // within each millikernel loop. " ldr x0, %[a] \n\t" " ldr x4, %[k_mker] \n\t" " ldr x8, %[k_left] \n\t" " \n\t" // Storage scheme: // V[ 0:23] <- C // V[24:27] <- A // V[28:31] <- B // Under this scheme, the following is defined: #define DGEMM_6X4X2_K_MKER_LOOP_PLAIN_LOC(A0,A1,A2,A3,B0,B1,B2,B3,AADDR,AELEMADDR,AELEMST,LOADNEXT) \ DGEMM_6X4X2_K_MKER_LOOP_PLAIN(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,A0,A1,A2,A3,B0,B1,B2,B3,AADDR,AELEMADDR,AELEMST,LOADNEXT) // Load from memory. LABEL(LOAD_ABC) " \n\t" // No-microkernel early return is a must " cmp x4, #0 \n\t" // to avoid out-of-boundary read. BEQ(CLEAR_CCOLS) " \n\t" " mov x11, x1 \n\t" // Load B. " ldr q28, [x11] \n\t" " add x11, x11, x3 \n\t" " ldr q29, [x11] \n\t" " add x11, x11, x3 \n\t" " ldr q30, [x11] \n\t" " add x11, x11, x3 \n\t" " ldr q31, [x11] \n\t" // " add x11, x11, x3 \n\t" " add x1, x1, #16 \n\t" " \n\t" " mov x14, x0 \n\t" // Load A. " ldr q24, [x14] \n\t" " add x14, x14, x2 \n\t" " ldr q25, [x14] \n\t" " add x14, x14, x2 \n\t" " ldr q26, [x14] \n\t" " add x14, x14, x2 \n\t" " ldr q27, [x14] \n\t" " add x14, x14, x2 \n\t" LABEL(CLEAR_CCOLS) CLEAR8V(0,1,2,3,4,5,6,7) CLEAR8V(8,9,10,11,12,13,14,15) CLEAR8V(16,17,18,19,20,21,22,23) // No-microkernel early return, once again. BEQ(K_LEFT_LOOP) // // Microkernel is defined here as: #define DGEMM_6X4X2_K_MKER_LOOP_PLAIN_LOC_FWD(A0,A1,A2,A3,B0,B1,B2,B3) \ DGEMM_6X4X2_K_MKER_LOOP_PLAIN_LOC(A0,A1,A2,A3,B0,B1,B2,B3,x0,x14,x2,load) \ /* A already loaded and forwarded. Process B only. */ \ "mov x11, x1 \n\t" \ "ldr q28, [x11] \n\t" \ "add x11, x11, x3 \n\t" \ "ldr q29, [x11] \n\t" \ "add x11, x11, x3 \n\t" \ "ldr q30, [x11] \n\t" \ "add x11, x11, x3 \n\t" \ "ldr q31, [x11] \n\t" \ /*"add x11, x11, x3 \n\t"*/ \ "add x1, x1, #16 \n\t" // Start microkernel loop. LABEL(K_MKER_LOOP) DGEMM_6X4X2_K_MKER_LOOP_PLAIN_LOC_FWD(24,25,26,27,28,29,30,31) " \n\t" // Decrease counter before final replica. " subs x4, x4, #1 \n\t" // Branch early to avoid reading excess mem. BEQ(FIN_MKER_LOOP) DGEMM_6X4X2_K_MKER_LOOP_PLAIN_LOC_FWD(26,27,24,25,28,29,30,31) BRANCH(K_MKER_LOOP) // // Final microkernel loop. LABEL(FIN_MKER_LOOP) DGEMM_6X4X2_K_MKER_LOOP_PLAIN_LOC(26,27,24,25,28,29,30,31,x0,x14,x2,noload) // // If major kernel is executed, // an additional depth-summation is required. " faddp v0.2d, v0.2d, v1.2d \n\t" // Line 0. " faddp v1.2d, v2.2d, v3.2d \n\t" " faddp v2.2d, v4.2d, v5.2d \n\t" // Line 1. " faddp v3.2d, v6.2d, v7.2d \n\t" " faddp v4.2d, v8.2d, v9.2d \n\t" // Line 2. " faddp v5.2d, v10.2d, v11.2d \n\t" " faddp v6.2d, v12.2d, v13.2d \n\t" // Line 3. " faddp v7.2d, v14.2d, v15.2d \n\t" " faddp v8.2d, v16.2d, v17.2d \n\t" // Line 4. " faddp v9.2d, v18.2d, v19.2d \n\t" " faddp v10.2d, v20.2d, v21.2d \n\t" // Line 5. " faddp v11.2d, v22.2d, v23.2d \n\t" " \n\t" // Loops left behind microkernels. LABEL(K_LEFT_LOOP) " cmp x8, #0 \n\t" // End of exec. BEQ(WRITE_MEM_PREP) " mov x11, x1 \n\t" // Load B row. " ld1 {v28.d}[0], [x11], x3 \n\t" " ld1 {v28.d}[1], [x11], x3 \n\t" " ld1 {v29.d}[0], [x11], x3 \n\t" " ld1 {v29.d}[1], [x11], x3 \n\t" " add x1, x1, #8 \n\t" " mov x14, x0 \n\t" // Load A column. " ld1 {v24.d}[0], [x14], x2 \n\t" " ld1 {v24.d}[1], [x14], x2 \n\t" " ld1 {v25.d}[0], [x14], x2 \n\t" " ld1 {v25.d}[1], [x14], x2 \n\t" " ld1 {v26.d}[0], [x14], x2 \n\t" " ld1 {v26.d}[1], [x14], x2 \n\t" " add x0, x0, #8 \n\t" " fmla v0.2d, v28.2d, v24.d[0] \n\t" " fmla v1.2d, v29.2d, v24.d[0] \n\t" " fmla v2.2d, v28.2d, v24.d[1] \n\t" " fmla v3.2d, v29.2d, v24.d[1] \n\t" " fmla v4.2d, v28.2d, v25.d[0] \n\t" " fmla v5.2d, v29.2d, v25.d[0] \n\t" " fmla v6.2d, v28.2d, v25.d[1] \n\t" " fmla v7.2d, v29.2d, v25.d[1] \n\t" " fmla v8.2d, v28.2d, v26.d[0] \n\t" " fmla v9.2d, v29.2d, v26.d[0] \n\t" " fmla v10.2d, v28.2d, v26.d[1] \n\t" " fmla v11.2d, v29.2d, v26.d[1] \n\t" " sub x8, x8, #1 \n\t" BRANCH(K_LEFT_LOOP) // // Scale and write to memory. LABEL(WRITE_MEM_PREP) " ldr x4, %[alpha] \n\t" // Load alpha & beta (address). " ldr x8, %[beta] \n\t" " ld1r {v30.2d}, [x4] \n\t" // Load alpha & beta (value). " ld1r {v31.2d}, [x8] \n\t" " \n\t" " fmov d28, #1.0 \n\t" // Don't scale for unit alpha. " fcmp d30, d28 \n\t" BEQ(UNIT_ALPHA) DSCALE12V(0,1,2,3,4,5,6,7,8,9,10,11,30,0) LABEL(UNIT_ALPHA) " \n\t" " mov x1, x5 \n\t" // C address for loading. " \n\t" // C address for storing is x5 itself. " cmp x7, #8 \n\t" // Check for column-storage. BNE(WRITE_MEM_C) // // C storage in rows. LABEL(WRITE_MEM_R) " fcmp d31, #0.0 \n\t" // Don't load for zero beta. BEQ(ZERO_BETA_R) DLOADC_2V_R_FWD(12,13,x1,0,x6) DLOADC_2V_R_FWD(14,15,x1,0,x6) DLOADC_2V_R_FWD(16,17,x1,0,x6) DLOADC_2V_R_FWD(18,19,x1,0,x6) DLOADC_2V_R_FWD(20,21,x1,0,x6) DLOADC_2V_R_FWD(22,23,x1,0,x6) DSCALEA12V(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,31,0) LABEL(ZERO_BETA_R) #ifndef __clang__ " cmp x12, #1 \n\t" BRANCH(PRFM_END_R) " prfm PLDL1KEEP, [%[a_next], #16*0] \n\t" " prfm PLDL1KEEP, [%[a_next], #16*1] \n\t" " prfm PLDL1STRM, [%[b_next], #16*0] \n\t" " prfm PLDL1STRM, [%[b_next], #16*1] \n\t" LABEL(PRFM_END_R) #endif DSTOREC_2V_R_FWD(0,1,x5,0,x6) DSTOREC_2V_R_FWD(2,3,x5,0,x6) DSTOREC_2V_R_FWD(4,5,x5,0,x6) DSTOREC_2V_R_FWD(6,7,x5,0,x6) DSTOREC_2V_R_FWD(8,9,x5,0,x6) DSTOREC_2V_R_FWD(10,11,x5,0,x6) BRANCH(END_WRITE_MEM) // // C storage in columns. LABEL(WRITE_MEM_C) " trn1 v12.2d, v0.2d, v2.2d \n\t" " trn1 v13.2d, v4.2d, v6.2d \n\t" " trn1 v14.2d, v8.2d, v10.2d \n\t" " trn2 v15.2d, v0.2d, v2.2d \n\t" " trn2 v16.2d, v4.2d, v6.2d \n\t" " trn2 v17.2d, v8.2d, v10.2d \n\t" " trn1 v18.2d, v1.2d, v3.2d \n\t" " trn1 v19.2d, v5.2d, v7.2d \n\t" " trn1 v20.2d, v9.2d, v11.2d \n\t" " trn2 v21.2d, v1.2d, v3.2d \n\t" " trn2 v22.2d, v5.2d, v7.2d \n\t" " trn2 v23.2d, v9.2d, v11.2d \n\t" " fcmp d31, #0.0 \n\t" // Don't load for zero beta. BEQ(ZERO_BETA_C) DLOADC_3V_C_FWD(0,1,2,x1,0,x7) DLOADC_3V_C_FWD(3,4,5,x1,0,x7) DLOADC_3V_C_FWD(6,7,8,x1,0,x7) DLOADC_3V_C_FWD(9,10,11,x1,0,x7) DSCALEA12V(12,13,14,15,16,17,18,19,20,21,22,23,0,1,2,3,4,5,6,7,8,9,10,11,31,0) LABEL(ZERO_BETA_C) #ifndef __clang__ " cmp x12, #1 \n\t" BRANCH(PRFM_END_C) " prfm PLDL1KEEP, [%[a_next], #16*0] \n\t" " prfm PLDL1KEEP, [%[a_next], #16*1] \n\t" " prfm PLDL1STRM, [%[b_next], #16*0] \n\t" " prfm PLDL1STRM, [%[b_next], #16*1] \n\t" LABEL(PRFM_END_C) #endif DSTOREC_3V_C_FWD(12,13,14,x5,0,x7) DSTOREC_3V_C_FWD(15,16,17,x5,0,x7) DSTOREC_3V_C_FWD(18,19,20,x5,0,x7) DSTOREC_3V_C_FWD(21,22,23,x5,0,x7) // // End of this microkernel. LABEL(END_WRITE_MEM) " \n\t" " subs x12, x12, #1 \n\t" BEQ(END_EXEC) " \n\t" " mov x8, #4 \n\t" " madd x13, x7, x8, x13 \n\t" // Forward C's base address to the next logic panel. " madd x10, x3, x8, x10 \n\t" // Forward B's base address to the next logic panel. BRANCH(MILLIKER_MLOOP) // // End of execution. LABEL(END_EXEC) : : [a] "m" (a), [b] "m" (b), [c] "m" (c), [rs_a] "m" (rs_a), [cs_b] "m" (cs_b), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c), // In Clang, even "m"-passed parameter takes 1 register. // Have to disable prefetching to pass compilation. #ifndef __clang__ [a_next] "r" (a_next), [b_next] "r" (b_next), #endif [n_iter] "m" (n_iter), [k_mker] "m" (k_mker), [k_left] "m" (k_left), [alpha] "m" (alpha), [beta] "m" (beta) : "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10","x11","x12","x13","x14", "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", "v10","v11","v12","v13","v14","v15", "v16","v17","v18","v19","v20","v21","v22","v23", "v24","v25","v26","v27","v28","v29","v30","v31" ); consider_edge_cases: // TODO: Implement optimized kernel for this. // // Forward address. b = b + n_iter * 4 * cs_b; c = c + n_iter * 4 * cs_c; if ( n_left >= 3 ) { bli_dgemmsup_rd_armv8a_asm_6x3 ( conja, conjb, 6, 3, k0, alpha, a, rs_a0, cs_a0, b, rs_b0, cs_b0, beta, c, rs_c0, cs_c0, data, cntx ); b = b + 3 * cs_b; c = c + 3 * cs_c; n_left -= 3; } if ( n_left ) { // n_left < 3; // // Slice in rows. bli_dgemmsup_rd_armv8a_int_3x4 ( conja, conjb, 3, n_left, k0, alpha, a, rs_a0, cs_a0, b, rs_b0, cs_b0, beta, c, rs_c0, cs_c0, data, cntx ); a = a + 3 * rs_a; c = c + 3 * rs_c; bli_dgemmsup_rd_armv8a_int_3x4 ( conja, conjb, 3, n_left, k0, alpha, a, rs_a0, cs_a0, b, rs_b0, cs_b0, beta, c, rs_c0, cs_c0, data, cntx ); } } blis-0.9.0/kernels/armv8a/3/sup/bli_gemmsup_rv_armv8a_asm_d4x8m.c000066400000000000000000000441511422157504600246160ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "assert.h" GEMMSUP_KER_PROT( double, d, gemmsup_r_armv8a_ref2 ) // Label locality & misc. #include "../armv8a_asm_utils.h" // Nanokernel operations. #include "../armv8a_asm_d2x2.h" /* * +---+ +---+ +---+ +---+ * | 0 | | 2 | | 4 | | 6 | * +---+ +---+ +---+ +---+ * +---+ +---+ +---+ +---+ * | 1 | | 3 | | 5 | | 7 | * +---+ +---+ +---+ +---+ */ #define DGEMM_4X8_MKER_LOOP_PLAIN(C00,C01,C02,C03,C10,C11,C12,C13,C20,C21,C22,C23,C30,C31,C32,C33,A0,A1,B0,B1,B2,B3,BADDR,BSHIFT0,BSHIFT1,BSHIFT2,LOADNEXT) \ DGEMM_2X2_NANOKERNEL(C00,C10,B0,A0) \ DGEMM_2X2_NANOKERNEL(C20,C30,B0,A1) \ DGEMM_LOAD1V_ ##LOADNEXT (B0,BADDR,BSHIFT0) \ DGEMM_2X2_NANOKERNEL(C01,C11,B1,A0) \ DGEMM_2X2_NANOKERNEL(C21,C31,B1,A1) \ DGEMM_LOAD1V_ ##LOADNEXT (B1,BADDR,BSHIFT1) \ DGEMM_2X2_NANOKERNEL(C02,C12,B2,A0) \ DGEMM_2X2_NANOKERNEL(C22,C32,B2,A1) \ DGEMM_LOAD1V_ ##LOADNEXT (B2,BADDR,BSHIFT2) \ DGEMM_2X2_NANOKERNEL(C03,C13,B3,A0) \ DGEMM_2X2_NANOKERNEL(C23,C33,B3,A1) // Interleaving load or not. #define DGEMM_LOAD1V_noload(V1,ADDR,IMM) #define DGEMM_LOAD1V_load(V1,ADDR,IMM) \ " ldr q"#V1", ["#ADDR", #"#IMM"] \n\t" // Prefetch C in the long direction. #define DPRFMC_FWD(CADDR,DLONGC) \ " prfm PLDL1KEEP, ["#CADDR"] \n\t" \ " add "#CADDR", "#CADDR", "#DLONGC" \n\t" #define DLOADC_4V_R_FWD(C0,C1,C2,C3,CADDR,CSHIFT,RSC) \ DLOAD4V(C0,C1,C2,C3,CADDR,CSHIFT) \ " add "#CADDR", "#CADDR", "#RSC" \n\t" #define DSTOREC_4V_R_FWD(C0,C1,C2,C3,CADDR,CSHIFT,RSC) \ DSTORE4V(C0,C1,C2,C3,CADDR,CSHIFT) \ " add "#CADDR", "#CADDR", "#RSC" \n\t" #define DLOADC_4V_C_FWD(C00,C10,C01,C11,CADDR,CSHIFT,CSC) \ DLOAD2V(C00,C10,CADDR,CSHIFT) \ " add "#CADDR", "#CADDR", "#CSC" \n\t" \ DLOAD2V(C01,C11,CADDR,CSHIFT) \ " add "#CADDR", "#CADDR", "#CSC" \n\t" #define DSTOREC_4V_C_FWD(C00,C10,C01,C11,CADDR,CSHIFT,CSC) \ DSTORE2V(C00,C10,CADDR,CSHIFT) \ " add "#CADDR", "#CADDR", "#CSC" \n\t" \ DSTORE2V(C01,C11,CADDR,CSHIFT) \ " add "#CADDR", "#CADDR", "#CSC" \n\t" /* * 4x8 dgemmsup kernel with extending 1st dimension. * * Recommanded usage case: * o 16 < (L1 cache latency) * (Num. FPU) < 25. * o L1 cache has a bandwidth not too low (true in most cases). * o (FMLA latency) * (Num. FPU) < 32 cycles (true in almost all cases). */ void bli_dgemmsup_rv_armv8a_asm_4x8m ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { // Fixme: This uker has no dispatching for unalighed sizes. // Currently it only serves as a dispatch target for other kernels // and cannot be registered in configurations. assert( n0 == 8 ); // LLVM has very bad routing ability for inline asm. // Limit number of registers in case of Clang compilation. #ifndef __clang__ void* a_next = bli_auxinfo_next_a( data ); void* b_next = bli_auxinfo_next_b( data ); #endif uint64_t ps_a = bli_auxinfo_ps_a( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_mker = k0 / 4; uint64_t k_left = k0 % 4; int64_t m_iter = m0 / 4; int64_t m_left = m0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // uint64_t cs_b = cs_b0; assert( cs_b0 == 1 ); if ( m_iter == 0 ) goto consider_edge_cases; __asm__ volatile ( " ldr x10, %[a] \n\t" " ldr x13, %[c] \n\t" " ldr x12, %[m_iter] \n\t" " ldr x11, %[ps_a] \n\t" // Panel-skip of A. " ldr x9, %[rs_a] \n\t" // Row-skip of A. " ldr x2, %[cs_a] \n\t" // Column-skip of A. " ldr x3, %[rs_b] \n\t" // Row-skip of B. " \n\t" " ldr x6, %[rs_c] \n\t" // Row-skip of C. " ldr x7, %[cs_c] \n\t" // Column-skip of C. " \n\t" " \n\t" // Multiply some address skips by sizeof(double). " lsl x11, x11, #3 \n\t" // ps_a " lsl x9, x9, #3 \n\t" // rs_a " lsl x2, x2, #3 \n\t" // cs_a " lsl x3, x3, #3 \n\t" // rs_b " lsl x6, x6, #3 \n\t" // rs_c " lsl x7, x7, #3 \n\t" // cs_c " \n\t" " mov x1, x5 \n\t" " cmp x7, #8 \n\t" // Prefetch column-strided C. BEQ(C_PREFETCH_COLS) // This prefetch will not cover further mker perts. Skip. // // DPRFMC_FWD(x1,x6) // DPRFMC_FWD(x1,x6) // DPRFMC_FWD(x1,x6) // DPRFMC_FWD(x1,x6) BRANCH(C_PREFETCH_END) LABEL(C_PREFETCH_COLS) DPRFMC_FWD(x1,x7) DPRFMC_FWD(x1,x7) DPRFMC_FWD(x1,x7) DPRFMC_FWD(x1,x7) DPRFMC_FWD(x1,x7) DPRFMC_FWD(x1,x7) DPRFMC_FWD(x1,x7) DPRFMC_FWD(x1,x7) LABEL(C_PREFETCH_END) // // Millikernel. LABEL(MILLIKER_MLOOP) " \n\t" " mov x0, x10 \n\t" // Parameters to be reloaded " mov x5, x13 \n\t" // within each millikernel loop. " ldr x1, %[b] \n\t" " ldr x4, %[k_mker] \n\t" " ldr x8, %[k_left] \n\t" " \n\t" // Storage scheme: // V[ 0:15] <- C // V[16:23] <- A; Allowed latency: 48 cycles / # of FPUs. // V[24:31] <- B; Allowed latency: 28 cycles / # of FPUs. // Under this scheme, the following is defined: #define DGEMM_4X8_MKER_LOOP_PLAIN_LOC(A0,A1,B0,B1,B2,B3,BADDR,BSHIFT0,BSHIFT1,BSHIFT2,LOADNEXT) \ DGEMM_4X8_MKER_LOOP_PLAIN(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,A0,A1,B0,B1,B2,B3,BADDR,BSHIFT0,BSHIFT1,BSHIFT2,LOADNEXT) LABEL(LOAD_ABC) " \n\t" // No-microkernel early return is a must " cmp x4, #0 \n\t" // to avoid out-of-boundary read. BEQ(CLEAR_CCOLS) " \n\t" " mov x14, x0 \n\t" // Load A. " ld1 {v16.d}[0], [x14], x9 \n\t" " ld1 {v16.d}[1], [x14], x9 \n\t" " ld1 {v17.d}[0], [x14], x9 \n\t" " ld1 {v17.d}[1], [x14], x9 \n\t" " add x0, x0, x2 \n\t" " mov x14, x0 \n\t" " ld1 {v18.d}[0], [x14], x9 \n\t" " ld1 {v18.d}[1], [x14], x9 \n\t" " ld1 {v19.d}[0], [x14], x9 \n\t" " ld1 {v19.d}[1], [x14], x9 \n\t" " add x0, x0, x2 \n\t" " mov x14, x0 \n\t" " ld1 {v20.d}[0], [x14], x9 \n\t" " ld1 {v20.d}[1], [x14], x9 \n\t" " ld1 {v21.d}[0], [x14], x9 \n\t" " ld1 {v21.d}[1], [x14], x9 \n\t" " add x0, x0, x2 \n\t" " mov x14, x0 \n\t" " ld1 {v22.d}[0], [x14], x9 \n\t" " ld1 {v22.d}[1], [x14], x9 \n\t" " ld1 {v23.d}[0], [x14], x9 \n\t" " ld1 {v23.d}[1], [x14], x9 \n\t" " add x0, x0, x2 \n\t" " \n\t" " ldr q24, [x1, #16*0] \n\t" // Load B. " ldr q25, [x1, #16*1] \n\t" " ldr q26, [x1, #16*2] \n\t" " ldr q27, [x1, #16*3] \n\t" " add x1, x1, x3 \n\t" " ldr q28, [x1, #16*0] \n\t" " ldr q29, [x1, #16*1] \n\t" " ldr q30, [x1, #16*2] \n\t" " ldr q31, [x1, #16*3] \n\t" " add x1, x1, x3 \n\t" LABEL(CLEAR_CCOLS) CLEAR8V(0,1,2,3,4,5,6,7) CLEAR8V(8,9,10,11,12,13,14,15) // No-microkernel early return, once again. BEQ(K_LEFT_LOOP) // // Microkernel is defined here as: #define DGEMM_4X8_MKER_LOOP_PLAIN_LOC_FWD(A0,A1,B0,B1,B2,B3) \ DGEMM_4X8_MKER_LOOP_PLAIN_LOC(A0,A1,B0,B1,B2,B3,x1,0,16*1,16*2,load) \ "ldr q"#B3", [x1, #16*3] \n\t" \ "mov x14, x0 \n\t" \ "ld1 {v"#A0".d}[0], [x14], x9 \n\t" \ "ld1 {v"#A0".d}[1], [x14], x9 \n\t" \ "ld1 {v"#A1".d}[0], [x14], x9 \n\t" \ "ld1 {v"#A1".d}[1], [x14], x9 \n\t" \ "add x0, x0, x2 \n\t" \ "add x1, x1, x3 \n\t" // Start microkernel loop. LABEL(K_MKER_LOOP) " \n\t" // Decrease counter before final replica. " subs x4, x4, #1 \n\t" // Branch early to avoid reading excess mem. BEQ(FIN_MKER_LOOP) DGEMM_4X8_MKER_LOOP_PLAIN_LOC_FWD(16,17,24,25,26,27) DGEMM_4X8_MKER_LOOP_PLAIN_LOC_FWD(18,19,28,29,30,31) DGEMM_4X8_MKER_LOOP_PLAIN_LOC_FWD(20,21,24,25,26,27) DGEMM_4X8_MKER_LOOP_PLAIN_LOC_FWD(22,23,28,29,30,31) BRANCH(K_MKER_LOOP) // // Final microkernel loop. LABEL(FIN_MKER_LOOP) DGEMM_4X8_MKER_LOOP_PLAIN_LOC(16,17,24,25,26,27,x1,0,16*1,16*2,load) " ldr q27, [x1, #16*3] \n\t" " add x1, x1, x3 \n\t" DGEMM_4X8_MKER_LOOP_PLAIN_LOC(18,19,28,29,30,31,x1,0,16*1,16*2,load) " ldr q31, [x1, #16*3] \n\t" " add x1, x1, x3 \n\t" DGEMM_4X8_MKER_LOOP_PLAIN_LOC(20,21,24,25,26,27,xzr,-1,-1,-1,noload) DGEMM_4X8_MKER_LOOP_PLAIN_LOC(22,23,28,29,30,31,xzr,-1,-1,-1,noload) // // Loops left behind microkernels. LABEL(K_LEFT_LOOP) " cmp x8, #0 \n\t" // End of exec. BEQ(WRITE_MEM_PREP) " mov x14, x0 \n\t" // Load A col. " ld1 {v16.d}[0], [x14], x9 \n\t" " ld1 {v16.d}[1], [x14], x9 \n\t" " ld1 {v17.d}[0], [x14], x9 \n\t" " ld1 {v17.d}[1], [x14], x9 \n\t" " add x0, x0, x2 \n\t" " ldr q24, [x1, #16*0] \n\t" // Load B row. " ldr q25, [x1, #16*1] \n\t" " ldr q26, [x1, #16*2] \n\t" " ldr q27, [x1, #16*3] \n\t" " add x1, x1, x3 \n\t" " sub x8, x8, #1 \n\t" DGEMM_4X8_MKER_LOOP_PLAIN_LOC(16,17,24,25,26,27,xzr,-1,-1,-1,noload) BRANCH(K_LEFT_LOOP) // // Scale and write to memory. LABEL(WRITE_MEM_PREP) " ldr x4, %[alpha] \n\t" // Load alpha & beta (address). " ldr x8, %[beta] \n\t" " \n\t" " mov x1, x5 \n\t" // C address for loading. " \n\t" // C address for storing is x5 itself. " cmp x7, #8 \n\t" // Check for column-storage. BNE(WRITE_MEM_C) // // C storage in rows. LABEL(WRITE_MEM_R) " ld1r {v16.2d}, [x4] \n\t" // Load alpha & beta. " ld1r {v17.2d}, [x8] \n\t" " fcmp d17, #0.0 \n\t" DSCALE8V(0,1,2,3,4,5,6,7,16,0) DSCALE8V(8,9,10,11,12,13,14,15,16,0) BEQ(ZERO_BETA_R) DLOADC_4V_R_FWD(20,21,22,23,x1,0,x6) DLOADC_4V_R_FWD(24,25,26,27,x1,0,x6) DSCALEA8V(0,1,2,3,4,5,6,7,20,21,22,23,24,25,26,27,17,0) // DLOADC_4V_R_FWD(20,21,22,23,x1,0,x6) DLOADC_4V_R_FWD(24,25,26,27,x1,0,x6) DSCALEA8V(8,9,10,11,12,13,14,15,20,21,22,23,24,25,26,27,17,0) LABEL(ZERO_BETA_R) #ifndef __clang__ " cmp x12, #1 \n\t" BRANCH(PRFM_END_R) " prfm PLDL1KEEP, [%[a_next], #16*0] \n\t" " prfm PLDL1KEEP, [%[a_next], #16*1] \n\t" " prfm PLDL1STRM, [%[b_next], #16*0] \n\t" " prfm PLDL1STRM, [%[b_next], #16*1] \n\t" LABEL(PRFM_END_R) #endif // DSTOREC_4V_R_FWD(0,1,2,3,x5,0,x6) DSTOREC_4V_R_FWD(4,5,6,7,x5,0,x6) DSTOREC_4V_R_FWD(8,9,10,11,x5,0,x6) DSTOREC_4V_R_FWD(12,13,14,15,x5,0,x6) BRANCH(END_WRITE_MEM) // // C storage in columns. LABEL(WRITE_MEM_C) // In-register transpose. " trn1 v16.2d, v0.2d, v4.2d \n\t" // Column 0. " trn1 v17.2d, v8.2d, v12.2d \n\t" " trn2 v18.2d, v0.2d, v4.2d \n\t" // Column 1. " trn2 v19.2d, v8.2d, v12.2d \n\t" " trn1 v20.2d, v1.2d, v5.2d \n\t" // Column 2. " trn1 v21.2d, v9.2d, v13.2d \n\t" " trn2 v22.2d, v1.2d, v5.2d \n\t" // Column 3. " trn2 v23.2d, v9.2d, v13.2d \n\t" " trn1 v24.2d, v2.2d, v6.2d \n\t" // Column 4. " trn1 v25.2d, v10.2d, v14.2d \n\t" " trn2 v26.2d, v2.2d, v6.2d \n\t" // Column 5. " trn2 v27.2d, v10.2d, v14.2d \n\t" " trn1 v28.2d, v3.2d, v7.2d \n\t" // Column 6. " trn1 v29.2d, v11.2d, v15.2d \n\t" " trn2 v30.2d, v3.2d, v7.2d \n\t" // Column 7. " trn2 v31.2d, v11.2d, v15.2d \n\t" " ld1r {v14.2d}, [x4] \n\t" // Load alpha & beta. " ld1r {v15.2d}, [x8] \n\t" DSCALE8V(16,17,18,19,20,21,22,23,14,0) DSCALE8V(24,25,26,27,28,29,30,31,14,0) DLOADC_4V_C_FWD(0,1,2,3,x1,0,x7) DLOADC_4V_C_FWD(4,5,6,7,x1,0,x7) DSCALEA8V(16,17,18,19,20,21,22,23,0,1,2,3,4,5,6,7,15,0) // DLOADC_4V_C_FWD(0,1,2,3,x1,0,x7) DLOADC_4V_C_FWD(4,5,6,7,x1,0,x7) DSCALEA8V(24,25,26,27,28,29,30,31,0,1,2,3,4,5,6,7,15,0) #ifndef __clang__ " cmp x12, #1 \n\t" BRANCH(PRFM_END_C) " prfm PLDL1KEEP, [%[a_next], #16*0] \n\t" " prfm PLDL1KEEP, [%[a_next], #16*1] \n\t" " prfm PLDL1STRM, [%[b_next], #16*0] \n\t" " prfm PLDL1STRM, [%[b_next], #16*1] \n\t" LABEL(PRFM_END_C) #endif // DSTOREC_4V_C_FWD(16,17,18,19,x5,0,x7) DSTOREC_4V_C_FWD(20,21,22,23,x5,0,x7) DSTOREC_4V_C_FWD(24,25,26,27,x5,0,x7) DSTOREC_4V_C_FWD(28,29,30,31,x5,0,x7) // // End of this microkernel. LABEL(END_WRITE_MEM) " \n\t" " subs x12, x12, #1 \n\t" BEQ(END_EXEC) " \n\t" " mov x8, #4 \n\t" " madd x13, x6, x8, x13 \n\t" // Forward C's base address to the next logic panel. " add x10, x10, x11 \n\t" // Forward A's base address to the next logic panel. BRANCH(MILLIKER_MLOOP) // // End of execution. LABEL(END_EXEC) : : [a] "m" (a), [b] "m" (b), [c] "m" (c), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [ps_a] "m" (ps_a), [rs_b] "m" (rs_b), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c), // In Clang, even "m"-passed parameter takes 1 register. // Have to disable prefetching to pass compilation. #ifndef __clang__ [a_next] "r" (a_next), [b_next] "r" (b_next), #endif [m_iter] "m" (m_iter), [k_mker] "m" (k_mker), [k_left] "m" (k_left), [alpha] "m" (alpha), [beta] "m" (beta) : "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10","x11","x12","x13","x14", "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", "v10","v11","v12","v13","v14","v15", "v16","v17","v18","v19","v20","v21","v22","v23", "v24","v25","v26","v27","v28","v29","v30","v31" ); consider_edge_cases: // TODO: Implement optimized kernel for this. // // Forward address. a = a + m_iter * ps_a; c = c + m_iter * 4 * rs_c; if ( m_left ) { bli_dgemmsup_r_armv8a_ref2 ( conja, conjb, m_left, 8, k0, alpha, a, rs_a0, cs_a0, b, rs_b0, cs_b0, beta, c, rs_c0, cs_c0, data, cntx ); } } blis-0.9.0/kernels/armv8a/3/sup/bli_gemmsup_rv_armv8a_asm_d4x8n.c000066400000000000000000000444011422157504600246150ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "assert.h" GEMMSUP_KER_PROT( double, d, gemmsup_r_armv8a_ref2 ) // Label locality & misc. #include "../armv8a_asm_utils.h" // Nanokernel operations. #include "../armv8a_asm_d2x2.h" /* * +---+ +---+ +---+ +---+ * | 0 | | 2 | | 4 | | 6 | * +---+ +---+ +---+ +---+ * +---+ +---+ +---+ +---+ * | 1 | | 3 | | 5 | | 7 | * +---+ +---+ +---+ +---+ */ #define DGEMM_4X8_MKER_LOOP_PLAIN(C00,C01,C02,C03,C10,C11,C12,C13,C20,C21,C22,C23,C30,C31,C32,C33,A0,A1,B0,B1,B2,B3,BADDR,BSHIFT0,BSHIFT1,BSHIFT2,LOADNEXT) \ DGEMM_2X2_NANOKERNEL(C00,C10,B0,A0) \ DGEMM_2X2_NANOKERNEL(C20,C30,B0,A1) \ DGEMM_LOAD1V_ ##LOADNEXT (B0,BADDR,BSHIFT0) \ DGEMM_2X2_NANOKERNEL(C01,C11,B1,A0) \ DGEMM_2X2_NANOKERNEL(C21,C31,B1,A1) \ DGEMM_LOAD1V_ ##LOADNEXT (B1,BADDR,BSHIFT1) \ DGEMM_2X2_NANOKERNEL(C02,C12,B2,A0) \ DGEMM_2X2_NANOKERNEL(C22,C32,B2,A1) \ DGEMM_LOAD1V_ ##LOADNEXT (B2,BADDR,BSHIFT2) \ DGEMM_2X2_NANOKERNEL(C03,C13,B3,A0) \ DGEMM_2X2_NANOKERNEL(C23,C33,B3,A1) // Interleaving load or not. #define DGEMM_LOAD1V_noload(V1,ADDR,IMM) #define DGEMM_LOAD1V_load(V1,ADDR,IMM) \ " ldr q"#V1", ["#ADDR", #"#IMM"] \n\t" // Prefetch C in the long direction. #define DPRFMC_FWD(CADDR,DLONGC) \ " prfm PLDL1KEEP, ["#CADDR"] \n\t" \ " add "#CADDR", "#CADDR", "#DLONGC" \n\t" #define DLOADC_4V_R_FWD(C0,C1,C2,C3,CADDR,CSHIFT,RSC) \ DLOAD4V(C0,C1,C2,C3,CADDR,CSHIFT) \ " add "#CADDR", "#CADDR", "#RSC" \n\t" #define DSTOREC_4V_R_FWD(C0,C1,C2,C3,CADDR,CSHIFT,RSC) \ DSTORE4V(C0,C1,C2,C3,CADDR,CSHIFT) \ " add "#CADDR", "#CADDR", "#RSC" \n\t" #define DLOADC_4V_C_FWD(C00,C10,C01,C11,CADDR,CSHIFT,CSC) \ DLOAD2V(C00,C10,CADDR,CSHIFT) \ " add "#CADDR", "#CADDR", "#CSC" \n\t" \ DLOAD2V(C01,C11,CADDR,CSHIFT) \ " add "#CADDR", "#CADDR", "#CSC" \n\t" #define DSTOREC_4V_C_FWD(C00,C10,C01,C11,CADDR,CSHIFT,CSC) \ DSTORE2V(C00,C10,CADDR,CSHIFT) \ " add "#CADDR", "#CADDR", "#CSC" \n\t" \ DSTORE2V(C01,C11,CADDR,CSHIFT) \ " add "#CADDR", "#CADDR", "#CSC" \n\t" /* * 4x8 dgemmsup kernel with extending 2nd dimension. * * Recommanded usage case: * o 16 < (L1 cache latency) * (Num. FPU) < 25. * o L1 cache has a bandwidth not too low (true in most cases). * o (FMLA latency) * (Num. FPU) < 32 cycles (true in almost all cases). */ void bli_dgemmsup_rv_armv8a_asm_4x8n ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { // Fixme: This uker has no dispatching for unalighed sizes. // Currently it only serves as a dispatch target for other kernels // and cannot be registered in configurations. assert( m0 == 4 ); // LLVM has very bad routing ability for inline asm. // Limit number of registers in case of Clang compilation. #ifndef __clang__ void* a_next = bli_auxinfo_next_a( data ); void* b_next = bli_auxinfo_next_b( data ); #endif uint64_t ps_b = bli_auxinfo_ps_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_mker = k0 / 4; uint64_t k_left = k0 % 4; int64_t n_iter = n0 / 8; int64_t n_left = n0 % 8; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // uint64_t cs_b = cs_b0; assert( cs_b0 == 1 ); if ( n_iter == 0 ) goto consider_edge_cases; __asm__ volatile ( " ldr x10, %[b] \n\t" " ldr x13, %[c] \n\t" " ldr x12, %[n_iter] \n\t" " ldr x11, %[ps_b] \n\t" // Panel-skip of B. " ldr x3, %[rs_b] \n\t" // Row-skip of B. " ldr x9, %[rs_a] \n\t" // Row-skip of A. " ldr x2, %[cs_a] \n\t" // Column-skip of A. " \n\t" " ldr x6, %[rs_c] \n\t" // Row-skip of C. " ldr x7, %[cs_c] \n\t" // Column-skip of C. " \n\t" " \n\t" // Multiply some address skips by sizeof(double). " lsl x11, x11, #3 \n\t" // ps_b " lsl x9, x9, #3 \n\t" // rs_a " lsl x2, x2, #3 \n\t" // cs_a " lsl x3, x3, #3 \n\t" // rs_b " lsl x6, x6, #3 \n\t" // rs_c " lsl x7, x7, #3 \n\t" // cs_c " \n\t" " mov x1, x5 \n\t" " cmp x7, #8 \n\t" // Prefetch column-strided C. BEQ(C_PREFETCH_COLS) DPRFMC_FWD(x1,x6) DPRFMC_FWD(x1,x6) DPRFMC_FWD(x1,x6) DPRFMC_FWD(x1,x6) BRANCH(C_PREFETCH_END) LABEL(C_PREFETCH_COLS) // This prefetch will not cover further mker perts. Skip. // // DPRFMC_FWD(x1,x7) // DPRFMC_FWD(x1,x7) // DPRFMC_FWD(x1,x7) // DPRFMC_FWD(x1,x7) // DPRFMC_FWD(x1,x7) // DPRFMC_FWD(x1,x7) // DPRFMC_FWD(x1,x7) // DPRFMC_FWD(x1,x7) LABEL(C_PREFETCH_END) // // Millikernel. LABEL(MILLIKER_MLOOP) " \n\t" " mov x1, x10 \n\t" // Parameters to be reloaded " mov x5, x13 \n\t" // within each millikernel loop. " ldr x0, %[a] \n\t" " ldr x4, %[k_mker] \n\t" " ldr x8, %[k_left] \n\t" " \n\t" // Storage scheme: // V[ 0:15] <- C // V[16:23] <- A; Allowed latency: 48 cycles / # of FPUs. // V[24:31] <- B; Allowed latency: 28 cycles / # of FPUs. // Under this scheme, the following is defined: #define DGEMM_4X8_MKER_LOOP_PLAIN_LOC(A0,A1,B0,B1,B2,B3,BADDR,BSHIFT0,BSHIFT1,BSHIFT2,LOADNEXT) \ DGEMM_4X8_MKER_LOOP_PLAIN(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,A0,A1,B0,B1,B2,B3,BADDR,BSHIFT0,BSHIFT1,BSHIFT2,LOADNEXT) LABEL(LOAD_ABC) " \n\t" // No-microkernel early return is a must " cmp x4, #0 \n\t" // to avoid out-of-boundary read. BEQ(CLEAR_CCOLS) " \n\t" " ldr q24, [x1, #16*0] \n\t" // Load B first. " ldr q25, [x1, #16*1] \n\t" " ldr q26, [x1, #16*2] \n\t" " ldr q27, [x1, #16*3] \n\t" " add x1, x1, x3 \n\t" " ldr q28, [x1, #16*0] \n\t" " ldr q29, [x1, #16*1] \n\t" " ldr q30, [x1, #16*2] \n\t" " ldr q31, [x1, #16*3] \n\t" " add x1, x1, x3 \n\t" " \n\t" " mov x14, x0 \n\t" // Load A. " ld1 {v16.d}[0], [x14], x9 \n\t" // We want A to be kept in L1. " ld1 {v16.d}[1], [x14], x9 \n\t" " ld1 {v17.d}[0], [x14], x9 \n\t" " ld1 {v17.d}[1], [x14], x9 \n\t" " add x0, x0, x2 \n\t" " mov x14, x0 \n\t" " ld1 {v18.d}[0], [x14], x9 \n\t" " ld1 {v18.d}[1], [x14], x9 \n\t" " ld1 {v19.d}[0], [x14], x9 \n\t" " ld1 {v19.d}[1], [x14], x9 \n\t" " add x0, x0, x2 \n\t" " mov x14, x0 \n\t" " ld1 {v20.d}[0], [x14], x9 \n\t" " ld1 {v20.d}[1], [x14], x9 \n\t" " ld1 {v21.d}[0], [x14], x9 \n\t" " ld1 {v21.d}[1], [x14], x9 \n\t" " add x0, x0, x2 \n\t" " mov x14, x0 \n\t" " ld1 {v22.d}[0], [x14], x9 \n\t" " ld1 {v22.d}[1], [x14], x9 \n\t" " ld1 {v23.d}[0], [x14], x9 \n\t" " ld1 {v23.d}[1], [x14], x9 \n\t" " add x0, x0, x2 \n\t" LABEL(CLEAR_CCOLS) CLEAR8V(0,1,2,3,4,5,6,7) CLEAR8V(8,9,10,11,12,13,14,15) // No-microkernel early return, once again. BEQ(K_LEFT_LOOP) // // Microkernel is defined here as: #define DGEMM_4X8_MKER_LOOP_PLAIN_LOC_FWD(A0,A1,B0,B1,B2,B3) \ DGEMM_4X8_MKER_LOOP_PLAIN_LOC(A0,A1,B0,B1,B2,B3,x1,0,16*1,16*2,load) \ "ldr q"#B3", [x1, #16*3] \n\t" \ "mov x14, x0 \n\t" \ "ld1 {v"#A0".d}[0], [x14], x9 \n\t" \ "ld1 {v"#A0".d}[1], [x14], x9 \n\t" \ "ld1 {v"#A1".d}[0], [x14], x9 \n\t" \ "ld1 {v"#A1".d}[1], [x14], x9 \n\t" \ "add x0, x0, x2 \n\t" \ "add x1, x1, x3 \n\t" // Start microkernel loop. LABEL(K_MKER_LOOP) " \n\t" // Decrease counter before final replica. " subs x4, x4, #1 \n\t" // Branch early to avoid reading excess mem. BEQ(FIN_MKER_LOOP) DGEMM_4X8_MKER_LOOP_PLAIN_LOC_FWD(16,17,24,25,26,27) DGEMM_4X8_MKER_LOOP_PLAIN_LOC_FWD(18,19,28,29,30,31) DGEMM_4X8_MKER_LOOP_PLAIN_LOC_FWD(20,21,24,25,26,27) DGEMM_4X8_MKER_LOOP_PLAIN_LOC_FWD(22,23,28,29,30,31) BRANCH(K_MKER_LOOP) // // Final microkernel loop. LABEL(FIN_MKER_LOOP) DGEMM_4X8_MKER_LOOP_PLAIN_LOC(16,17,24,25,26,27,x1,0,16*1,16*2,load) " ldr q27, [x1, #16*3] \n\t" " add x1, x1, x3 \n\t" DGEMM_4X8_MKER_LOOP_PLAIN_LOC(18,19,28,29,30,31,x1,0,16*1,16*2,load) " ldr q31, [x1, #16*3] \n\t" " add x1, x1, x3 \n\t" DGEMM_4X8_MKER_LOOP_PLAIN_LOC(20,21,24,25,26,27,xzr,-1,-1,-1,noload) DGEMM_4X8_MKER_LOOP_PLAIN_LOC(22,23,28,29,30,31,xzr,-1,-1,-1,noload) // // Loops left behind microkernels. LABEL(K_LEFT_LOOP) " cmp x8, #0 \n\t" // End of exec. BEQ(WRITE_MEM_PREP) " ldr q24, [x1, #16*0] \n\t" // Load B row. " ldr q25, [x1, #16*1] \n\t" " ldr q26, [x1, #16*2] \n\t" " ldr q27, [x1, #16*3] \n\t" " add x1, x1, x3 \n\t" " mov x14, x0 \n\t" // Load A col. " ld1 {v16.d}[0], [x14], x9 \n\t" " ld1 {v16.d}[1], [x14], x9 \n\t" " ld1 {v17.d}[0], [x14], x9 \n\t" " ld1 {v17.d}[1], [x14], x9 \n\t" " add x0, x0, x2 \n\t" " sub x8, x8, #1 \n\t" DGEMM_4X8_MKER_LOOP_PLAIN_LOC(16,17,24,25,26,27,xzr,-1,-1,-1,noload) BRANCH(K_LEFT_LOOP) // // Scale and write to memory. LABEL(WRITE_MEM_PREP) " ldr x4, %[alpha] \n\t" // Load alpha & beta (address). " ldr x8, %[beta] \n\t" " \n\t" " mov x1, x5 \n\t" // C address for loading. " \n\t" // C address for storing is x5 itself. " cmp x7, #8 \n\t" // Check for column-storage. BNE(WRITE_MEM_C) // // C storage in rows. LABEL(WRITE_MEM_R) " ld1r {v16.2d}, [x4] \n\t" // Load alpha & beta. " ld1r {v17.2d}, [x8] \n\t" " fcmp d17, #0.0 \n\t" DSCALE8V(0,1,2,3,4,5,6,7,16,0) DSCALE8V(8,9,10,11,12,13,14,15,16,0) BEQ(ZERO_BETA_R) DLOADC_4V_R_FWD(20,21,22,23,x1,0,x6) DLOADC_4V_R_FWD(24,25,26,27,x1,0,x6) DSCALEA8V(0,1,2,3,4,5,6,7,20,21,22,23,24,25,26,27,17,0) // DLOADC_4V_R_FWD(20,21,22,23,x1,0,x6) DLOADC_4V_R_FWD(24,25,26,27,x1,0,x6) DSCALEA8V(8,9,10,11,12,13,14,15,20,21,22,23,24,25,26,27,17,0) LABEL(ZERO_BETA_R) #ifndef __clang__ " cmp x12, #1 \n\t" BRANCH(PRFM_END_R) " prfm PLDL1KEEP, [%[a_next], #16*0] \n\t" " prfm PLDL1KEEP, [%[a_next], #16*1] \n\t" " prfm PLDL1STRM, [%[b_next], #16*0] \n\t" " prfm PLDL1STRM, [%[b_next], #16*1] \n\t" LABEL(PRFM_END_R) #endif // DSTOREC_4V_R_FWD(0,1,2,3,x5,0,x6) DSTOREC_4V_R_FWD(4,5,6,7,x5,0,x6) DSTOREC_4V_R_FWD(8,9,10,11,x5,0,x6) DSTOREC_4V_R_FWD(12,13,14,15,x5,0,x6) BRANCH(END_WRITE_MEM) // // C storage in columns. LABEL(WRITE_MEM_C) // In-register transpose. " trn1 v16.2d, v0.2d, v4.2d \n\t" // Column 0. " trn1 v17.2d, v8.2d, v12.2d \n\t" " trn2 v18.2d, v0.2d, v4.2d \n\t" // Column 1. " trn2 v19.2d, v8.2d, v12.2d \n\t" " trn1 v20.2d, v1.2d, v5.2d \n\t" // Column 2. " trn1 v21.2d, v9.2d, v13.2d \n\t" " trn2 v22.2d, v1.2d, v5.2d \n\t" // Column 3. " trn2 v23.2d, v9.2d, v13.2d \n\t" " trn1 v24.2d, v2.2d, v6.2d \n\t" // Column 4. " trn1 v25.2d, v10.2d, v14.2d \n\t" " trn2 v26.2d, v2.2d, v6.2d \n\t" // Column 5. " trn2 v27.2d, v10.2d, v14.2d \n\t" " trn1 v28.2d, v3.2d, v7.2d \n\t" // Column 6. " trn1 v29.2d, v11.2d, v15.2d \n\t" " trn2 v30.2d, v3.2d, v7.2d \n\t" // Column 7. " trn2 v31.2d, v11.2d, v15.2d \n\t" " ld1r {v14.2d}, [x4] \n\t" // Load alpha & beta. " ld1r {v15.2d}, [x8] \n\t" DSCALE8V(16,17,18,19,20,21,22,23,14,0) DSCALE8V(24,25,26,27,28,29,30,31,14,0) DLOADC_4V_C_FWD(0,1,2,3,x1,0,x7) DLOADC_4V_C_FWD(4,5,6,7,x1,0,x7) DSCALEA8V(16,17,18,19,20,21,22,23,0,1,2,3,4,5,6,7,15,0) // DLOADC_4V_C_FWD(0,1,2,3,x1,0,x7) DLOADC_4V_C_FWD(4,5,6,7,x1,0,x7) DSCALEA8V(24,25,26,27,28,29,30,31,0,1,2,3,4,5,6,7,15,0) #ifndef __clang__ " cmp x12, #1 \n\t" BRANCH(PRFM_END_C) " prfm PLDL1KEEP, [%[a_next], #16*0] \n\t" " prfm PLDL1KEEP, [%[a_next], #16*1] \n\t" " prfm PLDL1STRM, [%[b_next], #16*0] \n\t" " prfm PLDL1STRM, [%[b_next], #16*1] \n\t" LABEL(PRFM_END_C) #endif // DSTOREC_4V_C_FWD(16,17,18,19,x5,0,x7) DSTOREC_4V_C_FWD(20,21,22,23,x5,0,x7) DSTOREC_4V_C_FWD(24,25,26,27,x5,0,x7) DSTOREC_4V_C_FWD(28,29,30,31,x5,0,x7) // // End of this microkernel. LABEL(END_WRITE_MEM) " \n\t" " subs x12, x12, #1 \n\t" BEQ(END_EXEC) " \n\t" " mov x8, #8 \n\t" " madd x13, x7, x8, x13 \n\t" // Forward C's base address to the next logic panel. " add x10, x10, x11 \n\t" // Forward B's base address to the next logic panel. BRANCH(MILLIKER_MLOOP) // // End of execution. LABEL(END_EXEC) : : [a] "m" (a), [b] "m" (b), [c] "m" (c), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [ps_b] "m" (ps_b), [rs_b] "m" (rs_b), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c), // In Clang, even "m"-passed parameter takes 1 register. // Have to disable prefetching to pass compilation. #ifndef __clang__ [a_next] "r" (a_next), [b_next] "r" (b_next), #endif [n_iter] "m" (n_iter), [k_mker] "m" (k_mker), [k_left] "m" (k_left), [alpha] "m" (alpha), [beta] "m" (beta) : "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10","x11","x12","x13","x14", "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", "v10","v11","v12","v13","v14","v15", "v16","v17","v18","v19","v20","v21","v22","v23", "v24","v25","v26","v27","v28","v29","v30","v31" ); consider_edge_cases: // TODO: Implement optimized kernel for this. // // Forward address. b = b + n_iter * ps_b; c = c + n_iter * 8 * cs_c; if ( n_left ) { auxinfo_t data_d6x4mn = *data; bli_auxinfo_set_ps_b( 4 * cs_b0, &data_d6x4mn ); bli_dgemmsup_rv_armv8a_int_6x4mn ( conja, conjb, 4, n_left, k0, alpha, a, rs_a0, cs_a0, b, rs_b0, cs_b0, beta, c, rs_c0, cs_c0, &data_d6x4mn, cntx ); } } blis-0.9.0/kernels/armv8a/3/sup/bli_gemmsup_rv_armv8a_asm_d6x8m.c000066400000000000000000000516411422157504600246220ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2021, The University of Tokyo 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "assert.h" GEMMSUP_KER_PROT( double, d, gemmsup_r_armv8a_ref2 ) // Label locality & misc. #include "../armv8a_asm_utils.h" // Nanokernel operations. #include "../armv8a_asm_d2x2.h" /* Order of row-major DGEMM_6x8's execution in 2x2 blocks: * * +---+ +---+ +---+ +---+ * | 0 | | 1 | | 6 | | 7 | * +---+ +---+ +---+ +---+ * +---+ +---+ +---+ +---+ * | 2 | | 3 | | 8 | | 9 | * +---+ +---+ +---+ +---+ * +---+ +---+ +---+ +---+ * | 4 | | 5 | | 10| | 11| * +---+ +---+ +---+ +---+ * */ #define DGEMM_6X8_MKER_LOOP_PLAIN(C00,C01,C02,C03,C10,C11,C12,C13,C20,C21,C22,C23,C30,C31,C32,C33,C40,C41,C42,C43,C50,C51,C52,C53,A0,A1,A2,B0,B1,B2,B3,AELEMADDR,AELEMST,BADDR,BSHIFT,LOADNEXT) \ DGEMM_2X2_NANOKERNEL(C00,C10,B0,A0) \ DGEMM_2X2_NANOKERNEL(C01,C11,B1,A0) \ DGEMM_2X2_NANOKERNEL(C20,C30,B0,A1) \ DGEMM_2X2_NANOKERNEL(C21,C31,B1,A1) \ DGEMM_2X2_NANOKERNEL(C40,C50,B0,A2) \ DGEMM_2X2_NANOKERNEL(C41,C51,B1,A2) \ DGEMM_LOAD2V_ ##LOADNEXT (B0,B1,BADDR,BSHIFT) \ DGEMM_2X2_NANOKERNEL(C02,C12,B2,A0) \ DGEMM_2X2_NANOKERNEL(C03,C13,B3,A0) \ DGEMM_LOAD1V_G_ ##LOADNEXT (A0,AELEMADDR,AELEMST) \ DGEMM_2X2_NANOKERNEL(C22,C32,B2,A1) \ DGEMM_2X2_NANOKERNEL(C23,C33,B3,A1) \ DGEMM_LOAD1V_G_ ##LOADNEXT (A1,AELEMADDR,AELEMST) \ DGEMM_2X2_NANOKERNEL(C42,C52,B2,A2) \ DGEMM_2X2_NANOKERNEL(C43,C53,B3,A2) // Interleaving load or not. #define DGEMM_LOAD1V_noload(V1,ADDR,IMM) #define DGEMM_LOAD1V_load(V1,ADDR,IMM) \ " ldr q"#V1", ["#ADDR", #"#IMM"] \n\t" #define DGEMM_LOAD2V_noload(V1,V2,ADDR,IMM) #define DGEMM_LOAD2V_load(V1,V2,ADDR,IMM) \ DGEMM_LOAD1V_load(V1,ADDR,IMM) \ DGEMM_LOAD1V_load(V2,ADDR,IMM+16) #define DGEMM_LOAD1V_G_noload(V1,ADDR,ST) #define DGEMM_LOAD1V_G_load(V1,ADDR,ST) \ " ld1 {v"#V1".d}[0], ["#ADDR"], "#ST" \n\t" \ " ld1 {v"#V1".d}[1], ["#ADDR"], "#ST" \n\t" // Prefetch C in the long direction. #define DPRFMC_FWD(CADDR,DLONGC) \ " prfm PLDL1KEEP, ["#CADDR"] \n\t" \ " add "#CADDR", "#CADDR", "#DLONGC" \n\t" // For row-storage of C. #define DLOADC_4V_R_FWD(C0,C1,C2,C3,CADDR,CSHIFT,RSC) \ DLOAD4V(C0,C1,C2,C3,CADDR,CSHIFT) \ " add "#CADDR", "#CADDR", "#RSC" \n\t" #define DSTOREC_4V_R_FWD(C0,C1,C2,C3,CADDR,CSHIFT,RSC) \ DSTORE4V(C0,C1,C2,C3,CADDR,CSHIFT) \ " add "#CADDR", "#CADDR", "#RSC" \n\t" // For column-storage of C. #define DLOADC_3V_C_FWD(C0,C1,C2,CADDR,CSHIFT,CSC) \ DLOAD2V(C0,C1,CADDR,CSHIFT) \ DLOAD1V(C2,CADDR,CSHIFT+32) \ " add "#CADDR", "#CADDR", "#CSC" \n\t" #define DSTOREC_3V_C_FWD(C0,C1,C2,CADDR,CSHIFT,CSC) \ DSTORE2V(C0,C1,CADDR,CSHIFT) \ DSTORE1V(C2,CADDR,CSHIFT+32) \ " add "#CADDR", "#CADDR", "#CSC" \n\t" #define DSCALE6V(V0,V1,V2,V3,V4,V5,A,IDX) \ DSCALE4V(V0,V1,V2,V3,A,IDX) \ DSCALE2V(V4,V5,A,IDX) #define DSCALEA6V(D0,D1,D2,D3,D4,D5,S0,S1,S2,S3,S4,S5,A,IDX) \ DSCALEA4V(D0,D1,D2,D3,S0,S1,S2,S3,A,IDX) \ DSCALEA2V(D4,D5,S4,S5,A,IDX) /* * 6x8 dgemmsup kernel with extending 1st dimension. * * Recommanded usage case: (L1 cache latency) * (Num. FPU) < 17 cycles. * * Calls 4x8 for edge cases. */ void bli_dgemmsup_rv_armv8a_asm_6x8m ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { if ( n0 != 8 ) { if ( n0 < 8 ) { for ( ; n0 >= 4; n0 -= 4 ) { dgemmsup_ker_ft ukr_fp; auxinfo_t data_d8xkm = *data; if ( bli_auxinfo_ps_a( data ) == 6 * rs_a0 ) { // Use 8x4 Asm kernel for the unpacked case. bli_auxinfo_set_ps_a( 8 * rs_a0, &data_d8xkm ); ukr_fp = bli_dgemmsup_rv_armv8a_asm_8x4m; } else { // Cannot change dimension for m when A is packed. ukr_fp = bli_dgemmsup_rv_armv8a_int_6x4mn; } ukr_fp ( conja, conjb, m0, 4, k0, alpha, a, rs_a0, cs_a0, b, rs_b0, cs_b0, beta, c, rs_c0, cs_c0, &data_d8xkm, cntx ); b += 4 * cs_b0; c += 4 * cs_c0; } if ( n0 > 0 ) { bli_dgemmsup_rv_armv8a_int_6x4mn ( conja, conjb, m0, n0, k0, alpha, a, rs_a0, cs_a0, b, rs_b0, cs_b0, beta, c, rs_c0, cs_c0, data, cntx ); } } else { assert( FALSE ); } return; } // LLVM has very bad routing ability for inline asm. // Limit number of registers in case of Clang compilation. #ifndef __clang__ void* a_next = bli_auxinfo_next_a( data ); void* b_next = bli_auxinfo_next_b( data ); #endif uint64_t ps_a = bli_auxinfo_ps_a( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_mker = k0 / 4; uint64_t k_left = k0 % 4; int64_t m_iter = m0 / 6; int64_t m_left = m0 % 6; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // uint64_t cs_b = cs_b0; assert( cs_b0 == 1 ); if ( m_iter == 0 ) goto consider_edge_cases; __asm__ volatile ( " ldr x10, %[a] \n\t" " ldr x13, %[c] \n\t" " ldr x12, %[m_iter] \n\t" " ldr x11, %[ps_a] \n\t" // Panel-skip of A. " ldr x9, %[rs_a] \n\t" // Row-skip of A. " ldr x2, %[cs_a] \n\t" // Column-skip of A. " ldr x3, %[rs_b] \n\t" // Row-skip of B. " \n\t" " ldr x6, %[rs_c] \n\t" // Row-skip of C. " ldr x7, %[cs_c] \n\t" // Column-skip of C. " \n\t" " \n\t" // Multiply some address skips by sizeof(double). " lsl x11, x11, #3 \n\t" // ps_a " lsl x9, x9, #3 \n\t" // rs_a " lsl x2, x2, #3 \n\t" // cs_a " lsl x3, x3, #3 \n\t" // rs_b " lsl x6, x6, #3 \n\t" // rs_c " lsl x7, x7, #3 \n\t" // cs_c " \n\t" " mov x1, x5 \n\t" " cmp x7, #8 \n\t" // Prefetch column-strided C. BEQ(C_PREFETCH_COLS) // This prefetch will not cover further mker perts. Skip. // // DPRFMC_FWD(x1,x6) // DPRFMC_FWD(x1,x6) // DPRFMC_FWD(x1,x6) // DPRFMC_FWD(x1,x6) // DPRFMC_FWD(x1,x6) // DPRFMC_FWD(x1,x6) BRANCH(C_PREFETCH_END) LABEL(C_PREFETCH_COLS) DPRFMC_FWD(x1,x7) DPRFMC_FWD(x1,x7) DPRFMC_FWD(x1,x7) DPRFMC_FWD(x1,x7) DPRFMC_FWD(x1,x7) DPRFMC_FWD(x1,x7) DPRFMC_FWD(x1,x7) DPRFMC_FWD(x1,x7) LABEL(C_PREFETCH_END) // // Millikernel. LABEL(MILLIKER_MLOOP) " \n\t" " mov x0, x10 \n\t" // Parameters to be reloaded " mov x5, x13 \n\t" // within each millikernel loop. " ldr x1, %[b] \n\t" " ldr x4, %[k_mker] \n\t" " ldr x8, %[k_left] \n\t" " \n\t" // Storage scheme: // V[ 0:23] <- C // V[24:27] <- A // V[28:31] <- B // Under this scheme, the following is defined: #define DGEMM_6X8_MKER_LOOP_PLAIN_LOC(A0,A1,A2,B0,B1,B2,B3,AELEMADDR,AELEMST,BADDR,BSHIFT,LOADNEXT) \ DGEMM_6X8_MKER_LOOP_PLAIN(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,A0,A1,A2,B0,B1,B2,B3,AELEMADDR,AELEMST,BADDR,BSHIFT,LOADNEXT) // Load from memory. LABEL(LOAD_ABC) " \n\t" // No-microkernel early return is a must " cmp x4, #0 \n\t" // to avoid out-of-boundary read. BEQ(CLEAR_CCOLS) " \n\t" " mov x14, x0 \n\t" // Load A. " ld1 {v24.d}[0], [x14], x9 \n\t" " ld1 {v24.d}[1], [x14], x9 \n\t" " ld1 {v25.d}[0], [x14], x9 \n\t" " ld1 {v25.d}[1], [x14], x9 \n\t" " ld1 {v26.d}[0], [x14], x9 \n\t" " ld1 {v26.d}[1], [x14], x9 \n\t" " add x0, x0, x2 \n\t" " mov x14, x0 \n\t" " ld1 {v27.d}[0], [x14], x9 \n\t" " ld1 {v27.d}[1], [x14], x9 \n\t" " \n\t" " ldr q28, [x1, #16*0] \n\t" // Load B. " ldr q29, [x1, #16*1] \n\t" " ldr q30, [x1, #16*2] \n\t" " ldr q31, [x1, #16*3] \n\t" " add x1, x1, x3 \n\t" LABEL(CLEAR_CCOLS) CLEAR8V(0,1,2,3,4,5,6,7) CLEAR8V(8,9,10,11,12,13,14,15) CLEAR8V(16,17,18,19,20,21,22,23) // No-microkernel early return, once again. BEQ(K_LEFT_LOOP) // // Microkernel is defined here as: #define DGEMM_6X8_MKER_LOOP_PLAIN_LOC_FWD(A0,A1,A2,B0,B1,B2,B3) \ DGEMM_6X8_MKER_LOOP_PLAIN_LOC(A0,A1,A2,B0,B1,B2,B3,x14,x9,x1,0,load) \ "add x0, x0, x2 \n\t" \ "mov x14, x0 \n\t" \ "ld1 {v"#A2".d}[0], [x14], x9 \n\t" \ "ld1 {v"#A2".d}[1], [x14], x9 \n\t" \ "ldr q"#B2", [x1, #16*2] \n\t" \ "ldr q"#B3", [x1, #16*3] \n\t" \ "add x1, x1, x3 \n\t" // Start microkernel loop. LABEL(K_MKER_LOOP) DGEMM_6X8_MKER_LOOP_PLAIN_LOC_FWD(24,25,26,28,29,30,31) DGEMM_6X8_MKER_LOOP_PLAIN_LOC_FWD(27,24,25,28,29,30,31) " \n\t" // Decrease counter before final replica. " subs x4, x4, #1 \n\t" // Branch early to avoid reading excess mem. BEQ(FIN_MKER_LOOP) DGEMM_6X8_MKER_LOOP_PLAIN_LOC_FWD(26,27,24,28,29,30,31) DGEMM_6X8_MKER_LOOP_PLAIN_LOC_FWD(25,26,27,28,29,30,31) BRANCH(K_MKER_LOOP) // // Final microkernel loop. LABEL(FIN_MKER_LOOP) DGEMM_6X8_MKER_LOOP_PLAIN_LOC(26,27,24,28,29,30,31,x14,x9,x1,0,load) " add x0, x0, x2 \n\t" " ldr q30, [x1, #16*2] \n\t" " ldr q31, [x1, #16*3] \n\t" " add x1, x1, x3 \n\t" DGEMM_6X8_MKER_LOOP_PLAIN_LOC(25,26,27,28,29,30,31,xzr,-1,xzr,-1,noload) // // Loops left behind microkernels. LABEL(K_LEFT_LOOP) " cmp x8, #0 \n\t" // End of exec. BEQ(WRITE_MEM_PREP) " mov x14, x0 \n\t" " ld1 {v24.d}[0], [x14], x9 \n\t" // Load A col. " ld1 {v24.d}[1], [x14], x9 \n\t" " ld1 {v25.d}[0], [x14], x9 \n\t" " ld1 {v25.d}[1], [x14], x9 \n\t" " ld1 {v26.d}[0], [x14], x9 \n\t" " ld1 {v26.d}[1], [x14], x9 \n\t" " add x0, x0, x2 \n\t" " ldr q28, [x1, #16*0] \n\t" // Load B row. " ldr q29, [x1, #16*1] \n\t" " ldr q30, [x1, #16*2] \n\t" " ldr q31, [x1, #16*3] \n\t" " add x1, x1, x3 \n\t" " sub x8, x8, #1 \n\t" DGEMM_6X8_MKER_LOOP_PLAIN_LOC(24,25,26,28,29,30,31,xzr,-1,xzr,-1,noload) BRANCH(K_LEFT_LOOP) // // Scale and write to memory. LABEL(WRITE_MEM_PREP) " ldr x4, %[alpha] \n\t" // Load alpha & beta (address). " ldr x8, %[beta] \n\t" " \n\t" " mov x1, x5 \n\t" // C address for loading. " \n\t" // C address for storing is x5 itself. " cmp x7, #8 \n\t" // Check for column-storage. BNE(WRITE_MEM_C) // // C storage in rows. LABEL(WRITE_MEM_R) " ld1r {v24.2d}, [x4] \n\t" // Load alpha & beta. " ld1r {v25.2d}, [x8] \n\t" " fmov d26, #1.0 \n\t" " fcmp d24, d26 \n\t" BEQ(UNIT_ALPHA_R) DSCALE8V(0,1,2,3,4,5,6,7,24,0) DSCALE8V(8,9,10,11,12,13,14,15,24,0) DSCALE8V(16,17,18,19,20,21,22,23,24,0) LABEL(UNIT_ALPHA_R) " fcmp d25, #0.0 \n\t" BEQ(ZERO_BETA_R_1) DLOADC_4V_R_FWD(26,27,28,29,x1,0,x6) DSCALEA4V(0,1,2,3,26,27,28,29,25,0) DLOADC_4V_R_FWD(26,27,28,29,x1,0,x6) DSCALEA4V(4,5,6,7,26,27,28,29,25,0) LABEL(ZERO_BETA_R_1) DSTOREC_4V_R_FWD(0,1,2,3,x5,0,x6) BEQ(ZERO_BETA_R_2) DLOADC_4V_R_FWD(26,27,28,29,x1,0,x6) DLOADC_4V_R_FWD(0,1,2,3,x1,0,x6) DSCALEA8V(8,9,10,11,12,13,14,15,26,27,28,29,0,1,2,3,25,0) DLOADC_4V_R_FWD(26,27,28,29,x1,0,x6) DLOADC_4V_R_FWD(0,1,2,3,x1,0,x6) DSCALEA8V(16,17,18,19,20,21,22,23,26,27,28,29,0,1,2,3,25,0) LABEL(ZERO_BETA_R_2) #ifndef __clang__ " cmp x12, #1 \n\t" BRANCH(PRFM_END_R) " prfm PLDL1KEEP, [%[a_next], #16*0] \n\t" " prfm PLDL1KEEP, [%[a_next], #16*1] \n\t" " prfm PLDL1STRM, [%[b_next], #16*0] \n\t" " prfm PLDL1STRM, [%[b_next], #16*1] \n\t" LABEL(PRFM_END_R) #endif DSTOREC_4V_R_FWD(4,5,6,7,x5,0,x6) DSTOREC_4V_R_FWD(8,9,10,11,x5,0,x6) DSTOREC_4V_R_FWD(12,13,14,15,x5,0,x6) DSTOREC_4V_R_FWD(16,17,18,19,x5,0,x6) DSTOREC_4V_R_FWD(20,21,22,23,x5,0,x6) BRANCH(END_WRITE_MEM) // // C storage in columns. LABEL(WRITE_MEM_C) // In-register transpose, // do transposition in row-order. " trn1 v24.2d, v0.2d, v4.2d \n\t" // Row 0-1. " trn2 v25.2d, v0.2d, v4.2d \n\t" " trn1 v26.2d, v1.2d, v5.2d \n\t" " trn2 v27.2d, v1.2d, v5.2d \n\t" " trn1 v28.2d, v2.2d, v6.2d \n\t" " trn2 v29.2d, v2.2d, v6.2d \n\t" " trn1 v30.2d, v3.2d, v7.2d \n\t" " trn2 v31.2d, v3.2d, v7.2d \n\t" " \n\t" " trn1 v0.2d, v8.2d, v12.2d \n\t" // Row 2-3. " trn2 v1.2d, v8.2d, v12.2d \n\t" " trn1 v2.2d, v9.2d, v13.2d \n\t" " trn2 v3.2d, v9.2d, v13.2d \n\t" " trn1 v4.2d, v10.2d, v14.2d \n\t" " trn2 v5.2d, v10.2d, v14.2d \n\t" " trn1 v6.2d, v11.2d, v15.2d \n\t" " trn2 v7.2d, v11.2d, v15.2d \n\t" " \n\t" " trn1 v8.2d, v16.2d, v20.2d \n\t" // Row 4-5. " trn2 v9.2d, v16.2d, v20.2d \n\t" " trn1 v10.2d, v17.2d, v21.2d \n\t" // AMARI " trn2 v11.2d, v17.2d, v21.2d \n\t" // AMARI " trn1 v12.2d, v18.2d, v22.2d \n\t" // AMARI " trn2 v13.2d, v18.2d, v22.2d \n\t" // AMARI " trn1 v14.2d, v19.2d, v23.2d \n\t" // AMARI " trn2 v15.2d, v19.2d, v23.2d \n\t" // AMARI " \n\t" " ld1r {v16.2d}, [x4] \n\t" // Load alpha & beta. " ld1r {v17.2d}, [x8] \n\t" " fmov d18, #1.0 \n\t" " fcmp d16, d18 \n\t" BEQ(UNIT_ALPHA_C) DSCALE8V(24,25,26,27,28,29,30,31,16,0) DSCALE8V(0,1,2,3,4,5,6,7,16,0) DSCALE8V(8,9,10,11,12,13,14,15,16,0) LABEL(UNIT_ALPHA_C) " fcmp d17, #0.0 \n\t" BEQ(ZERO_BETA_C_1) DLOADC_3V_C_FWD(18,19,20,x1,0,x7) DLOADC_3V_C_FWD(21,22,23,x1,0,x7) DSCALEA6V(24,0,8,25,1,9,18,19,20,21,22,23,17,0) LABEL(ZERO_BETA_C_1) DSTOREC_3V_C_FWD(24,0,8,x5,0,x7) DSTOREC_3V_C_FWD(25,1,9,x5,0,x7) BEQ(ZERO_BETA_C_2) DLOADC_3V_C_FWD(18,19,20,x1,0,x7) DLOADC_3V_C_FWD(21,22,23,x1,0,x7) DLOADC_3V_C_FWD(24,0,8,x1,0,x7) DLOADC_3V_C_FWD(25,1,9,x1,0,x7) DSCALEA6V(26,2,10,27,3,11,18,19,20,21,22,23,17,0) DSCALEA6V(28,4,12,29,5,13,24,0,8,25,1,9,17,0) LABEL(ZERO_BETA_C_2) #ifndef __clang__ " cmp x12, #1 \n\t" BRANCH(PRFM_END_C) " prfm PLDL1KEEP, [%[a_next], #16*0] \n\t" " prfm PLDL1KEEP, [%[a_next], #16*1] \n\t" " prfm PLDL1STRM, [%[b_next], #16*0] \n\t" " prfm PLDL1STRM, [%[b_next], #16*1] \n\t" LABEL(PRFM_END_C) " fcmp d17, #0.0 \n\t" // Not the end. Reset branching reg. #endif DSTOREC_3V_C_FWD(26,2,10,x5,0,x7) DSTOREC_3V_C_FWD(27,3,11,x5,0,x7) BEQ(ZERO_BETA_C_3) DLOADC_3V_C_FWD(18,19,20,x1,0,x7) DLOADC_3V_C_FWD(21,22,23,x1,0,x7) DSCALEA6V(30,6,14,31,7,15,18,19,20,21,22,23,17,0) LABEL(ZERO_BETA_C_3) DSTOREC_3V_C_FWD(28,4,12,x5,0,x7) DSTOREC_3V_C_FWD(29,5,13,x5,0,x7) DSTOREC_3V_C_FWD(30,6,14,x5,0,x7) DSTOREC_3V_C_FWD(31,7,15,x5,0,x7) // // End of this microkernel. LABEL(END_WRITE_MEM) " \n\t" " subs x12, x12, #1 \n\t" BEQ(END_EXEC) " \n\t" " mov x8, #6 \n\t" " madd x13, x6, x8, x13 \n\t" // Forward C's base address to the next logic panel. " add x10, x10, x11 \n\t" // Forward A's base address to the next logic panel. BRANCH(MILLIKER_MLOOP) // // End of execution. LABEL(END_EXEC) : : [a] "m" (a), [b] "m" (b), [c] "m" (c), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [ps_a] "m" (ps_a), [rs_b] "m" (rs_b), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c), // In Clang, even "m"-passed parameter takes 1 register. // Have to disable prefetching to pass compilation. #ifndef __clang__ [a_next] "r" (a_next), [b_next] "r" (b_next), #endif [m_iter] "m" (m_iter), [k_mker] "m" (k_mker), [k_left] "m" (k_left), [alpha] "m" (alpha), [beta] "m" (beta) : "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10","x11","x12","x13","x14", "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", "v10","v11","v12","v13","v14","v15", "v16","v17","v18","v19","v20","v21","v22","v23", "v24","v25","v26","v27","v28","v29","v30","v31" ); consider_edge_cases: // Forward address. a = a + m_iter * ps_a; c = c + m_iter * 6 * rs_c; #if 1 auxinfo_t data_d6x4mn = *data; bli_auxinfo_set_ps_b( 4 * cs_b0, &data_d6x4mn ); bli_dgemmsup_rv_armv8a_int_6x4mn ( conja, conjb, m_left, 8, k0, alpha, a, rs_a0, cs_a0, b, rs_b0, cs_b0, beta, c, rs_c0, cs_c0, &data_d6x4mn, cntx ); #else if ( m_left >= 4 ) { // Calls 4x8m with only 1 outermost loop. // As only 1 outermost loop is called, // ps_a needs not being set here. // bli_dgemmsup_rv_armv8a_asm_4x8m ( conja, conjb, 4, 8, k0, alpha, a, rs_a0, cs_a0, b, rs_b0, cs_b0, beta, c, rs_c0, cs_c0, data, cntx ); m_left -= 4; a = a + 4 * rs_a; c = c + 4 * rs_c; } if ( m_left ) { bli_dgemmsup_r_armv8a_ref2 ( conja, conjb, m_left, 8, k0, alpha, a, rs_a0, cs_a0, b, rs_b0, cs_b0, beta, c, rs_c0, cs_c0, data, cntx ); } #endif } blis-0.9.0/kernels/armv8a/3/sup/bli_gemmsup_rv_armv8a_asm_d6x8n.c000066400000000000000000000502571422157504600246250ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2021, The University of Tokyo 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "assert.h" GEMMSUP_KER_PROT( double, d, gemmsup_r_armv8a_ref2 ) // Label locality & misc. #include "../armv8a_asm_utils.h" // Nanokernel operations. #include "../armv8a_asm_d2x2.h" /* Order of row-major DGEMM_6x8's execution in 2x2 blocks: * * +---+ +---+ +---+ +---+ * | 0 | | 1 | | 6 | | 7 | * +---+ +---+ +---+ +---+ * +---+ +---+ +---+ +---+ * | 2 | | 3 | | 8 | | 9 | * +---+ +---+ +---+ +---+ * +---+ +---+ +---+ +---+ * | 4 | | 5 | | 10| | 11| * +---+ +---+ +---+ +---+ * */ #define DGEMM_6X8_MKER_LOOP_PLAIN(C00,C01,C02,C03,C10,C11,C12,C13,C20,C21,C22,C23,C30,C31,C32,C33,C40,C41,C42,C43,C50,C51,C52,C53,A0,A1,A2,B0,B1,B2,B3,AELEMADDR,AELEMST,BADDR,BSHIFT,LOADNEXT) \ DGEMM_2X2_NANOKERNEL(C00,C10,B0,A0) \ DGEMM_2X2_NANOKERNEL(C01,C11,B1,A0) \ DGEMM_2X2_NANOKERNEL(C20,C30,B0,A1) \ DGEMM_2X2_NANOKERNEL(C21,C31,B1,A1) \ DGEMM_2X2_NANOKERNEL(C40,C50,B0,A2) \ DGEMM_2X2_NANOKERNEL(C41,C51,B1,A2) \ DGEMM_LOAD2V_ ##LOADNEXT (B0,B1,BADDR,BSHIFT) \ DGEMM_2X2_NANOKERNEL(C02,C12,B2,A0) \ DGEMM_2X2_NANOKERNEL(C03,C13,B3,A0) \ DGEMM_LOAD1V_G_ ##LOADNEXT (A0,AELEMADDR,AELEMST) \ DGEMM_2X2_NANOKERNEL(C22,C32,B2,A1) \ DGEMM_2X2_NANOKERNEL(C23,C33,B3,A1) \ DGEMM_LOAD1V_G_ ##LOADNEXT (A1,AELEMADDR,AELEMST) \ DGEMM_2X2_NANOKERNEL(C42,C52,B2,A2) \ DGEMM_2X2_NANOKERNEL(C43,C53,B3,A2) // Interleaving load or not. #define DGEMM_LOAD1V_noload(V1,ADDR,IMM) #define DGEMM_LOAD1V_load(V1,ADDR,IMM) \ " ldr q"#V1", ["#ADDR", #"#IMM"] \n\t" #define DGEMM_LOAD2V_noload(V1,V2,ADDR,IMM) #define DGEMM_LOAD2V_load(V1,V2,ADDR,IMM) \ DGEMM_LOAD1V_load(V1,ADDR,IMM) \ DGEMM_LOAD1V_load(V2,ADDR,IMM+16) #define DGEMM_LOAD1V_G_noload(V1,ADDR,ST) #define DGEMM_LOAD1V_G_load(V1,ADDR,ST) \ " ld1 {v"#V1".d}[0], ["#ADDR"], "#ST" \n\t" \ " ld1 {v"#V1".d}[1], ["#ADDR"], "#ST" \n\t" // Prefetch C in the long direction. #define DPRFMC_FWD(CADDR,DLONGC) \ " prfm PLDL1KEEP, ["#CADDR"] \n\t" \ " add "#CADDR", "#CADDR", "#DLONGC" \n\t" // For row-storage of C. #define DLOADC_4V_R_FWD(C0,C1,C2,C3,CADDR,CSHIFT,RSC) \ DLOAD4V(C0,C1,C2,C3,CADDR,CSHIFT) \ " add "#CADDR", "#CADDR", "#RSC" \n\t" #define DSTOREC_4V_R_FWD(C0,C1,C2,C3,CADDR,CSHIFT,RSC) \ DSTORE4V(C0,C1,C2,C3,CADDR,CSHIFT) \ " add "#CADDR", "#CADDR", "#RSC" \n\t" // For column-storage of C. #define DLOADC_3V_C_FWD(C0,C1,C2,CADDR,CSHIFT,CSC) \ DLOAD2V(C0,C1,CADDR,CSHIFT) \ DLOAD1V(C2,CADDR,CSHIFT+32) \ " add "#CADDR", "#CADDR", "#CSC" \n\t" #define DSTOREC_3V_C_FWD(C0,C1,C2,CADDR,CSHIFT,CSC) \ DSTORE2V(C0,C1,CADDR,CSHIFT) \ DSTORE1V(C2,CADDR,CSHIFT+32) \ " add "#CADDR", "#CADDR", "#CSC" \n\t" #define DSCALE6V(V0,V1,V2,V3,V4,V5,A,IDX) \ DSCALE4V(V0,V1,V2,V3,A,IDX) \ DSCALE2V(V4,V5,A,IDX) #define DSCALEA6V(D0,D1,D2,D3,D4,D5,S0,S1,S2,S3,S4,S5,A,IDX) \ DSCALEA4V(D0,D1,D2,D3,S0,S1,S2,S3,A,IDX) \ DSCALEA2V(D4,D5,S4,S5,A,IDX) /* * 6x8 dgemmsup kernel with extending 2nd dimension. * * Recommanded usage case: (L1 cache latency) * (Num. FPU) < 17 cycles. * * Calls 4x8n for edge cases. */ void bli_dgemmsup_rv_armv8a_asm_6x8n ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { if ( m0 != 6 ) { // 5 = 4 + 1; // 4; // while ( m0 >= 4 ) { bli_dgemmsup_rv_armv8a_asm_4x8n ( conja, conjb, 4, n0, k0, alpha, a, rs_a0, cs_a0, b, rs_b0, cs_b0, beta, c, rs_c0, cs_c0, data, cntx ); m0 -= 4; a += 4 * rs_a0; c += 4 * rs_c0; } // 3, 2, 1; // if ( m0 > 0 ) { bli_dgemmsup_rv_armv8a_int_3x8mn ( conja, conjb, m0, n0, k0, alpha, a, rs_a0, cs_a0, b, rs_b0, cs_b0, beta, c, rs_c0, cs_c0, data, cntx ); } return; } // LLVM has very bad routing ability for inline asm. // Limit number of registers in case of Clang compilation. #ifndef __clang__ void* a_next = bli_auxinfo_next_a( data ); void* b_next = bli_auxinfo_next_b( data ); #endif uint64_t ps_b = bli_auxinfo_ps_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_mker = k0 / 4; uint64_t k_left = k0 % 4; int64_t n_iter = n0 / 8; int64_t n_left = n0 % 8; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // uint64_t cs_b = cs_b0; assert( cs_b0 == 1 ); if ( n_iter == 0 ) goto consider_edge_cases; __asm__ volatile ( " ldr x10, %[b] \n\t" " ldr x13, %[c] \n\t" " ldr x12, %[n_iter] \n\t" " ldr x11, %[ps_b] \n\t" // Panel-skip of B. " ldr x3, %[rs_b] \n\t" // Row-skip of B. " ldr x9, %[rs_a] \n\t" // Row-skip of A. " ldr x2, %[cs_a] \n\t" // Column-skip of A. " \n\t" " ldr x6, %[rs_c] \n\t" // Row-skip of C. " ldr x7, %[cs_c] \n\t" // Column-skip of C. " \n\t" " \n\t" // Multiply some address skips by sizeof(double). " lsl x11, x11, #3 \n\t" // ps_b " lsl x9, x9, #3 \n\t" // rs_a " lsl x2, x2, #3 \n\t" // cs_a " lsl x3, x3, #3 \n\t" // rs_b " lsl x6, x6, #3 \n\t" // rs_c " lsl x7, x7, #3 \n\t" // cs_c " \n\t" " mov x1, x5 \n\t" " cmp x7, #8 \n\t" // Prefetch column-strided C. BEQ(C_PREFETCH_COLS) DPRFMC_FWD(x1,x6) DPRFMC_FWD(x1,x6) DPRFMC_FWD(x1,x6) DPRFMC_FWD(x1,x6) DPRFMC_FWD(x1,x6) DPRFMC_FWD(x1,x6) BRANCH(C_PREFETCH_END) LABEL(C_PREFETCH_COLS) // This prefetch will not cover further mker perts. Skip. // // DPRFMC_FWD(x1,x7) // DPRFMC_FWD(x1,x7) // DPRFMC_FWD(x1,x7) // DPRFMC_FWD(x1,x7) // DPRFMC_FWD(x1,x7) // DPRFMC_FWD(x1,x7) // DPRFMC_FWD(x1,x7) // DPRFMC_FWD(x1,x7) LABEL(C_PREFETCH_END) // // Millikernel. LABEL(MILLIKER_MLOOP) " \n\t" " mov x1, x10 \n\t" // Parameters to be reloaded " mov x5, x13 \n\t" // within each millikernel loop. " ldr x0, %[a] \n\t" " ldr x4, %[k_mker] \n\t" " ldr x8, %[k_left] \n\t" " \n\t" // Storage scheme: // V[ 0:23] <- C // V[24:27] <- A // V[28:31] <- B // Under this scheme, the following is defined: #define DGEMM_6X8_MKER_LOOP_PLAIN_LOC(A0,A1,A2,B0,B1,B2,B3,AELEMADDR,AELEMST,BADDR,BSHIFT,LOADNEXT) \ DGEMM_6X8_MKER_LOOP_PLAIN(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,A0,A1,A2,B0,B1,B2,B3,AELEMADDR,AELEMST,BADDR,BSHIFT,LOADNEXT) // Load from memory. LABEL(LOAD_ABC) " \n\t" // No-microkernel early return is a must " cmp x4, #0 \n\t" // to avoid out-of-boundary read. BEQ(CLEAR_CCOLS) " \n\t" " ldr q28, [x1, #16*0] \n\t" // Load B first. " ldr q29, [x1, #16*1] \n\t" " ldr q30, [x1, #16*2] \n\t" " ldr q31, [x1, #16*3] \n\t" " add x1, x1, x3 \n\t" " \n\t" " mov x14, x0 \n\t" // Load A. " ld1 {v24.d}[0], [x14], x9 \n\t" // We want A to be kept in L1. " ld1 {v24.d}[1], [x14], x9 \n\t" " ld1 {v25.d}[0], [x14], x9 \n\t" " ld1 {v25.d}[1], [x14], x9 \n\t" " ld1 {v26.d}[0], [x14], x9 \n\t" " ld1 {v26.d}[1], [x14], x9 \n\t" " add x0, x0, x2 \n\t" " mov x14, x0 \n\t" " ld1 {v27.d}[0], [x14], x9 \n\t" " ld1 {v27.d}[1], [x14], x9 \n\t" LABEL(CLEAR_CCOLS) CLEAR8V(0,1,2,3,4,5,6,7) CLEAR8V(8,9,10,11,12,13,14,15) CLEAR8V(16,17,18,19,20,21,22,23) // No-microkernel early return, once again. BEQ(K_LEFT_LOOP) // // Microkernel is defined here as: #define DGEMM_6X8_MKER_LOOP_PLAIN_LOC_FWD(A0,A1,A2,B0,B1,B2,B3) \ DGEMM_6X8_MKER_LOOP_PLAIN_LOC(A0,A1,A2,B0,B1,B2,B3,x14,x9,x1,0,load) \ "add x0, x0, x2 \n\t" \ "mov x14, x0 \n\t" \ "ld1 {v"#A2".d}[0], [x14], x9 \n\t" \ "ld1 {v"#A2".d}[1], [x14], x9 \n\t" \ "ldr q"#B2", [x1, #16*2] \n\t" \ "ldr q"#B3", [x1, #16*3] \n\t" \ "add x1, x1, x3 \n\t" // Start microkernel loop. LABEL(K_MKER_LOOP) DGEMM_6X8_MKER_LOOP_PLAIN_LOC_FWD(24,25,26,28,29,30,31) DGEMM_6X8_MKER_LOOP_PLAIN_LOC_FWD(27,24,25,28,29,30,31) " \n\t" // Decrease counter before final replica. " subs x4, x4, #1 \n\t" // Branch early to avoid reading excess mem. BEQ(FIN_MKER_LOOP) DGEMM_6X8_MKER_LOOP_PLAIN_LOC_FWD(26,27,24,28,29,30,31) DGEMM_6X8_MKER_LOOP_PLAIN_LOC_FWD(25,26,27,28,29,30,31) BRANCH(K_MKER_LOOP) // // Final microkernel loop. LABEL(FIN_MKER_LOOP) DGEMM_6X8_MKER_LOOP_PLAIN_LOC(26,27,24,28,29,30,31,x14,x9,x1,0,load) " add x0, x0, x2 \n\t" " ldr q30, [x1, #16*2] \n\t" " ldr q31, [x1, #16*3] \n\t" " add x1, x1, x3 \n\t" DGEMM_6X8_MKER_LOOP_PLAIN_LOC(25,26,27,28,29,30,31,xzr,-1,xzr,-1,noload) // // Loops left behind microkernels. LABEL(K_LEFT_LOOP) " cmp x8, #0 \n\t" // End of exec. BEQ(WRITE_MEM_PREP) " ldr q28, [x1, #16*0] \n\t" // Load B row. " ldr q29, [x1, #16*1] \n\t" " ldr q30, [x1, #16*2] \n\t" " ldr q31, [x1, #16*3] \n\t" " add x1, x1, x3 \n\t" " mov x14, x0 \n\t" " ld1 {v24.d}[0], [x14], x9 \n\t" // Load A col. " ld1 {v24.d}[1], [x14], x9 \n\t" " ld1 {v25.d}[0], [x14], x9 \n\t" " ld1 {v25.d}[1], [x14], x9 \n\t" " ld1 {v26.d}[0], [x14], x9 \n\t" " ld1 {v26.d}[1], [x14], x9 \n\t" " add x0, x0, x2 \n\t" " sub x8, x8, #1 \n\t" DGEMM_6X8_MKER_LOOP_PLAIN_LOC(24,25,26,28,29,30,31,xzr,-1,xzr,-1,noload) BRANCH(K_LEFT_LOOP) // // Scale and write to memory. LABEL(WRITE_MEM_PREP) " ldr x4, %[alpha] \n\t" // Load alpha & beta (address). " ldr x8, %[beta] \n\t" " \n\t" " mov x1, x5 \n\t" // C address for loading. " \n\t" // C address for storing is x5 itself. " cmp x7, #8 \n\t" // Check for column-storage. BNE(WRITE_MEM_C) // // C storage in rows. LABEL(WRITE_MEM_R) " ld1r {v24.2d}, [x4] \n\t" // Load alpha & beta. " ld1r {v25.2d}, [x8] \n\t" " fmov d26, #1.0 \n\t" " fcmp d24, d26 \n\t" BEQ(UNIT_ALPHA_R) DSCALE8V(0,1,2,3,4,5,6,7,24,0) DSCALE8V(8,9,10,11,12,13,14,15,24,0) DSCALE8V(16,17,18,19,20,21,22,23,24,0) LABEL(UNIT_ALPHA_R) " fcmp d25, #0.0 \n\t" BEQ(ZERO_BETA_R_1) DLOADC_4V_R_FWD(26,27,28,29,x1,0,x6) DSCALEA4V(0,1,2,3,26,27,28,29,25,0) DLOADC_4V_R_FWD(26,27,28,29,x1,0,x6) DSCALEA4V(4,5,6,7,26,27,28,29,25,0) LABEL(ZERO_BETA_R_1) DSTOREC_4V_R_FWD(0,1,2,3,x5,0,x6) BEQ(ZERO_BETA_R_2) DLOADC_4V_R_FWD(26,27,28,29,x1,0,x6) DLOADC_4V_R_FWD(0,1,2,3,x1,0,x6) DSCALEA8V(8,9,10,11,12,13,14,15,26,27,28,29,0,1,2,3,25,0) DLOADC_4V_R_FWD(26,27,28,29,x1,0,x6) DLOADC_4V_R_FWD(0,1,2,3,x1,0,x6) DSCALEA8V(16,17,18,19,20,21,22,23,26,27,28,29,0,1,2,3,25,0) LABEL(ZERO_BETA_R_2) #ifndef __clang__ " cmp x12, #1 \n\t" BRANCH(PRFM_END_R) " prfm PLDL1KEEP, [%[a_next], #16*0] \n\t" " prfm PLDL1KEEP, [%[a_next], #16*1] \n\t" " prfm PLDL1STRM, [%[b_next], #16*0] \n\t" " prfm PLDL1STRM, [%[b_next], #16*1] \n\t" LABEL(PRFM_END_R) #endif DSTOREC_4V_R_FWD(4,5,6,7,x5,0,x6) DSTOREC_4V_R_FWD(8,9,10,11,x5,0,x6) DSTOREC_4V_R_FWD(12,13,14,15,x5,0,x6) DSTOREC_4V_R_FWD(16,17,18,19,x5,0,x6) DSTOREC_4V_R_FWD(20,21,22,23,x5,0,x6) BRANCH(END_WRITE_MEM) // // C storage in columns. LABEL(WRITE_MEM_C) // In-register transpose, // do transposition in row-order. " trn1 v24.2d, v0.2d, v4.2d \n\t" // Row 0-1. " trn2 v25.2d, v0.2d, v4.2d \n\t" " trn1 v26.2d, v1.2d, v5.2d \n\t" " trn2 v27.2d, v1.2d, v5.2d \n\t" " trn1 v28.2d, v2.2d, v6.2d \n\t" " trn2 v29.2d, v2.2d, v6.2d \n\t" " trn1 v30.2d, v3.2d, v7.2d \n\t" " trn2 v31.2d, v3.2d, v7.2d \n\t" " \n\t" " trn1 v0.2d, v8.2d, v12.2d \n\t" // Row 2-3. " trn2 v1.2d, v8.2d, v12.2d \n\t" " trn1 v2.2d, v9.2d, v13.2d \n\t" " trn2 v3.2d, v9.2d, v13.2d \n\t" " trn1 v4.2d, v10.2d, v14.2d \n\t" " trn2 v5.2d, v10.2d, v14.2d \n\t" " trn1 v6.2d, v11.2d, v15.2d \n\t" " trn2 v7.2d, v11.2d, v15.2d \n\t" " \n\t" " trn1 v8.2d, v16.2d, v20.2d \n\t" // Row 4-5. " trn2 v9.2d, v16.2d, v20.2d \n\t" " trn1 v10.2d, v17.2d, v21.2d \n\t" // AMARI " trn2 v11.2d, v17.2d, v21.2d \n\t" // AMARI " trn1 v12.2d, v18.2d, v22.2d \n\t" // AMARI " trn2 v13.2d, v18.2d, v22.2d \n\t" // AMARI " trn1 v14.2d, v19.2d, v23.2d \n\t" // AMARI " trn2 v15.2d, v19.2d, v23.2d \n\t" // AMARI " \n\t" " ld1r {v16.2d}, [x4] \n\t" // Load alpha & beta. " ld1r {v17.2d}, [x8] \n\t" " fmov d18, #1.0 \n\t" " fcmp d16, d18 \n\t" BEQ(UNIT_ALPHA_C) DSCALE8V(24,25,26,27,28,29,30,31,16,0) DSCALE8V(0,1,2,3,4,5,6,7,16,0) DSCALE8V(8,9,10,11,12,13,14,15,16,0) LABEL(UNIT_ALPHA_C) " fcmp d17, #0.0 \n\t" BEQ(ZERO_BETA_C_1) DLOADC_3V_C_FWD(18,19,20,x1,0,x7) DLOADC_3V_C_FWD(21,22,23,x1,0,x7) DSCALEA6V(24,0,8,25,1,9,18,19,20,21,22,23,17,0) LABEL(ZERO_BETA_C_1) DSTOREC_3V_C_FWD(24,0,8,x5,0,x7) DSTOREC_3V_C_FWD(25,1,9,x5,0,x7) BEQ(ZERO_BETA_C_2) DLOADC_3V_C_FWD(18,19,20,x1,0,x7) DLOADC_3V_C_FWD(21,22,23,x1,0,x7) DLOADC_3V_C_FWD(24,0,8,x1,0,x7) DLOADC_3V_C_FWD(25,1,9,x1,0,x7) DSCALEA6V(26,2,10,27,3,11,18,19,20,21,22,23,17,0) DSCALEA6V(28,4,12,29,5,13,24,0,8,25,1,9,17,0) LABEL(ZERO_BETA_C_2) #ifndef __clang__ " cmp x12, #1 \n\t" BRANCH(PRFM_END_C) " prfm PLDL1KEEP, [%[a_next], #16*0] \n\t" " prfm PLDL1KEEP, [%[a_next], #16*1] \n\t" " prfm PLDL1STRM, [%[b_next], #16*0] \n\t" " prfm PLDL1STRM, [%[b_next], #16*1] \n\t" LABEL(PRFM_END_C) " fcmp d17, #0.0 \n\t" // Not the end. Reset branching reg. #endif DSTOREC_3V_C_FWD(26,2,10,x5,0,x7) DSTOREC_3V_C_FWD(27,3,11,x5,0,x7) BEQ(ZERO_BETA_C_3) DLOADC_3V_C_FWD(18,19,20,x1,0,x7) DLOADC_3V_C_FWD(21,22,23,x1,0,x7) DSCALEA6V(30,6,14,31,7,15,18,19,20,21,22,23,17,0) LABEL(ZERO_BETA_C_3) DSTOREC_3V_C_FWD(28,4,12,x5,0,x7) DSTOREC_3V_C_FWD(29,5,13,x5,0,x7) DSTOREC_3V_C_FWD(30,6,14,x5,0,x7) DSTOREC_3V_C_FWD(31,7,15,x5,0,x7) // // End of this microkernel. LABEL(END_WRITE_MEM) " \n\t" " subs x12, x12, #1 \n\t" BEQ(END_EXEC) " \n\t" " mov x8, #8 \n\t" " madd x13, x7, x8, x13 \n\t" // Forward C's base address to the next logic panel. " add x10, x10, x11 \n\t" // Forward B's base address to the next logic panel. BRANCH(MILLIKER_MLOOP) // // End of execution. LABEL(END_EXEC) : : [a] "m" (a), [b] "m" (b), [c] "m" (c), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [ps_b] "m" (ps_b), [rs_b] "m" (rs_b), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c), // In Clang, even "m"-passed parameter takes 1 register. // Have to disable prefetching to pass compilation. #ifndef __clang__ [a_next] "r" (a_next), [b_next] "r" (b_next), #endif [n_iter] "m" (n_iter), [k_mker] "m" (k_mker), [k_left] "m" (k_left), [alpha] "m" (alpha), [beta] "m" (beta) : "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10","x11","x12","x13","x14", "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", "v10","v11","v12","v13","v14","v15", "v16","v17","v18","v19","v20","v21","v22","v23", "v24","v25","v26","v27","v28","v29","v30","v31" ); consider_edge_cases: // Forward address. b = b + n_iter * ps_b; c = c + n_iter * 8 * cs_c; if ( n_left ) { // Set panel stride to unpacked mode. // Only 1 millikernel w.r.t. 6x8 is executed. auxinfo_t data_d6x4mn = *data; bli_auxinfo_set_ps_b( 4 * cs_b0, &data_d6x4mn ); // bli_dgemmsup_rv_armv8a_int_6x4mn ( conja, conjb, 6, n_left, k0, alpha, a, rs_a0, cs_a0, b, rs_b0, cs_b0, beta, c, rs_c0, cs_c0, &data_d6x4mn, cntx ); } } blis-0.9.0/kernels/armv8a/3/sup/bli_gemmsup_rv_armv8a_asm_d8x4m.c000066400000000000000000000424301422157504600246140ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "assert.h" GEMMSUP_KER_PROT( double, d, gemmsup_r_armv8a_ref2 ) // Label locality & misc. #include "../armv8a_asm_utils.h" // Nanokernel operations. #include "../armv8a_asm_d2x2.h" /* * +---+ +---+ * | 0 | | 4 | * +---+ +---+ * +---+ +---+ * | 1 | | 5 | * +---+ +---+ * +---+ +---+ * | 2 | | 6 | * +---+ +---+ * +---+ +---+ * | 3 | | 7 | * +---+ +---+ * */ #define DGEMM_8X4_MKER_LOOP_PLAIN(C00,C10,C20,C30,C01,C11,C21,C31,C02,C12,C22,C32,C03,C13,C23,C33,A0,A1,A2,A3,B0,B1,BADDR,BSHIFT,LOADNEXT) \ DGEMM_2X2_NANOKERNEL(C00,C01,A0,B0) \ DGEMM_2X2_NANOKERNEL(C10,C11,A1,B0) \ DGEMM_2X2_NANOKERNEL(C20,C21,A2,B0) \ DGEMM_2X2_NANOKERNEL(C30,C31,A3,B0) \ DGEMM_LOAD1V_ ##LOADNEXT (B0,BADDR,BSHIFT) \ DGEMM_2X2_NANOKERNEL(C02,C03,A0,B1) \ DGEMM_2X2_NANOKERNEL(C12,C13,A1,B1) \ DGEMM_2X2_NANOKERNEL(C22,C23,A2,B1) \ DGEMM_2X2_NANOKERNEL(C32,C33,A3,B1) // Interleaving load or not. #define DGEMM_LOAD1V_noload(V1,ADDR,IMM) #define DGEMM_LOAD1V_load(V1,ADDR,IMM) \ " ldr q"#V1", ["#ADDR", #"#IMM"] \n\t" #define DLOADC_4V_C_FWD(C0,C1,C2,C3,CADDR,CSHIFT,LDC) \ DLOAD4V(C0,C1,C2,C3,CADDR,CSHIFT) \ " add "#CADDR", "#CADDR", "#LDC" \n\t" #define DSTOREC_4V_C_FWD(C0,C1,C2,C3,CADDR,CSHIFT,LDC) \ DSTORE4V(C0,C1,C2,C3,CADDR,CSHIFT) \ " add "#CADDR", "#CADDR", "#LDC" \n\t" #define DLOADC_4V_R_FWD(C00,C01,C10,C11,CADDR,CSHIFT,RSC) \ DLOAD2V(C00,C01,CADDR,CSHIFT) \ " add "#CADDR", "#CADDR", "#RSC" \n\t" \ DLOAD2V(C10,C11,CADDR,CSHIFT) \ " add "#CADDR", "#CADDR", "#RSC" \n\t" #define DSTOREC_4V_R_FWD(C00,C01,C10,C11,CADDR,CSHIFT,RSC) \ DSTORE2V(C00,C01,CADDR,CSHIFT) \ " add "#CADDR", "#CADDR", "#RSC" \n\t" \ DSTORE2V(C10,C11,CADDR,CSHIFT) \ " add "#CADDR", "#CADDR", "#RSC" \n\t" /* * 8x4 kernel for dgemmsup. * * R-dimension too short. * Not recommanded for use. */ void bli_dgemmsup_rv_armv8a_asm_8x4m ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { // Fixme: This uker has no dispatching for unalighed sizes. // Currently it only serves as a dispatch target for other kernels // and cannot be registered in configurations. assert( n0 == 4 ); void* a_next = bli_auxinfo_next_a( data ); void* b_next = bli_auxinfo_next_b( data ); uint64_t ps_a = bli_auxinfo_ps_a( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_mker = k0 / 6; uint64_t k_left = k0 % 6; int64_t m_iter = m0 / 8; int64_t m_left = m0 % 8; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // uint64_t cs_b = cs_b0; assert( cs_b0 == 1 ); if ( m_iter == 0 ) goto consider_edge_cases; __asm__ volatile ( " ldr x10, %[a] \n\t" " ldr x13, %[c] \n\t" " ldr x12, %[m_iter] \n\t" " ldr x11, %[ps_a] \n\t" // Panel-skip of A. " ldr x2, %[cs_a] \n\t" // Column-skip of A. " ldr x9, %[rs_a] \n\t" // Row-skip of A. " ldr x3, %[rs_b] \n\t" // Row-skip of B. " \n\t" " ldr x6, %[rs_c] \n\t" // Row-skip of C. " ldr x7, %[cs_c] \n\t" // Column-skip of C. " \n\t" " \n\t" // Multiply some address skips by sizeof(double). " lsl x11, x11, #3 \n\t" // ps_a " lsl x9, x9, #3 \n\t" // rs_a " lsl x2, x2, #3 \n\t" // cs_a " lsl x3, x3, #3 \n\t" // rs_b " lsl x6, x6, #3 \n\t" // rs_c " lsl x7, x7, #3 \n\t" // cs_c " \n\t" LABEL(MILLIKER_MLOOP) " \n\t" " mov x0, x10 \n\t" // Parameters to be reloaded " mov x5, x13 \n\t" // within each millikernel loop. " ldr x1, %[b] \n\t" " ldr x4, %[k_mker] \n\t" " ldr x8, %[k_left] \n\t" " \n\t" // Storage scheme: // V[ 0:15] <- C // V[16:19] <- B; Allowed latency: 24 cycles / # of FPUs. // V[20:31] <- A; Allowed latency: 32 cycles / # of FPUs. // Under this scheme, the following is defined: #define DGEMM_8X4_MKER_LOOP_PLAIN_LOC(A0,A1,A2,A3,B0,B1,BADDR,BSHIFT,LOADNEXT) \ DGEMM_8X4_MKER_LOOP_PLAIN(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,A0,A1,A2,A3,B0,B1,BADDR,BSHIFT,LOADNEXT) LABEL(LOAD_ABC) " \n\t" // No-microkernel early return is a must " cmp x4, #0 \n\t" // to avoid out-of-boundary read. BEQ(CLEAR_CCOLS) " \n\t" " mov x14, x0 \n\t" " ld1 {v20.d}[0], [x14], x9 \n\t" " ld1 {v20.d}[1], [x14], x9 \n\t" " ld1 {v21.d}[0], [x14], x9 \n\t" " ld1 {v21.d}[1], [x14], x9 \n\t" " ld1 {v22.d}[0], [x14], x9 \n\t" " ld1 {v22.d}[1], [x14], x9 \n\t" " ld1 {v23.d}[0], [x14], x9 \n\t" " ld1 {v23.d}[1], [x14], x9 \n\t" " add x0, x0, x2 \n\t" " mov x14, x0 \n\t" " ld1 {v24.d}[0], [x14], x9 \n\t" " ld1 {v24.d}[1], [x14], x9 \n\t" " ld1 {v25.d}[0], [x14], x9 \n\t" " ld1 {v25.d}[1], [x14], x9 \n\t" " ld1 {v26.d}[0], [x14], x9 \n\t" " ld1 {v26.d}[1], [x14], x9 \n\t" " ld1 {v27.d}[0], [x14], x9 \n\t" " ld1 {v27.d}[1], [x14], x9 \n\t" " add x0, x0, x2 \n\t" " mov x14, x0 \n\t" " ld1 {v28.d}[0], [x14], x9 \n\t" " ld1 {v28.d}[1], [x14], x9 \n\t" " ld1 {v29.d}[0], [x14], x9 \n\t" " ld1 {v29.d}[1], [x14], x9 \n\t" " ld1 {v30.d}[0], [x14], x9 \n\t" " ld1 {v30.d}[1], [x14], x9 \n\t" " ld1 {v31.d}[0], [x14], x9 \n\t" " ld1 {v31.d}[1], [x14], x9 \n\t" " add x0, x0, x2 \n\t" " \n\t" " ldr q16, [x1, #16*0] \n\t" " ldr q17, [x1, #16*1] \n\t" " add x1, x1, x3 \n\t" " ldr q18, [x1, #16*0] \n\t" " ldr q19, [x1, #16*1] \n\t" " add x1, x1, x3 \n\t" LABEL(CLEAR_CCOLS) CLEAR8V(0,1,2,3,4,5,6,7) CLEAR8V(8,9,10,11,12,13,14,15) // No-microkernel early return, once again. BEQ(K_LEFT_LOOP) // // Microkernel is defined here as: #define DGEMM_8X4_MKER_LOOP_PLAIN_LOC_FWD(A0,A1,A2,A3,B0,B1) \ DGEMM_8X4_MKER_LOOP_PLAIN_LOC(A0,A1,A2,A3,B0,B1,x1,0,load) \ "mov x14, x0 \n\t" \ "ld1 {v"#A0".d}[0], [x14], x9 \n\t" \ "ld1 {v"#A0".d}[1], [x14], x9 \n\t" \ "ld1 {v"#A1".d}[0], [x14], x9 \n\t" \ "ld1 {v"#A1".d}[1], [x14], x9 \n\t" \ "ld1 {v"#A2".d}[0], [x14], x9 \n\t" \ "ld1 {v"#A2".d}[1], [x14], x9 \n\t" \ "ld1 {v"#A3".d}[0], [x14], x9 \n\t" \ "ld1 {v"#A3".d}[1], [x14], x9 \n\t" \ "ldr q"#B1", [x1, #16*1] \n\t" \ "add x1, x1, x3 \n\t" \ "add x0, x0, x2 \n\t" // Start microkernel loop. LABEL(K_MKER_LOOP) DGEMM_8X4_MKER_LOOP_PLAIN_LOC_FWD(20,21,22,23,16,17) DGEMM_8X4_MKER_LOOP_PLAIN_LOC_FWD(24,25,26,27,18,19) DGEMM_8X4_MKER_LOOP_PLAIN_LOC_FWD(28,29,30,31,16,17) " \n\t" // Decrease counter before final replica. " subs x4, x4, #1 \n\t" // Branch early to avoid reading excess mem. BEQ(FIN_MKER_LOOP) DGEMM_8X4_MKER_LOOP_PLAIN_LOC_FWD(20,21,22,23,18,19) DGEMM_8X4_MKER_LOOP_PLAIN_LOC_FWD(24,25,26,27,16,17) DGEMM_8X4_MKER_LOOP_PLAIN_LOC_FWD(28,29,30,31,18,19) BRANCH(K_MKER_LOOP) // // Final microkernel loop. LABEL(FIN_MKER_LOOP) DGEMM_8X4_MKER_LOOP_PLAIN_LOC(20,21,22,23,18,19,x1,0,load) " ldr q19, [x1, #16*1] \n\t" " add x1, x1, x3 \n\t" DGEMM_8X4_MKER_LOOP_PLAIN_LOC(24,25,26,27,16,17,xzr,-1,noload) DGEMM_8X4_MKER_LOOP_PLAIN_LOC(28,29,30,31,18,19,xzr,-1,noload) // // Loops left behind microkernels. LABEL(K_LEFT_LOOP) " cmp x8, #0 \n\t" // End of exec. BEQ(WRITE_MEM_PREP) " mov x14, x0 \n\t" " ld1 {v20.d}[0], [x14], x9 \n\t" // Load A col. " ld1 {v20.d}[1], [x14], x9 \n\t" " ld1 {v21.d}[0], [x14], x9 \n\t" " ld1 {v21.d}[1], [x14], x9 \n\t" " ld1 {v22.d}[0], [x14], x9 \n\t" " ld1 {v22.d}[1], [x14], x9 \n\t" " ld1 {v23.d}[0], [x14], x9 \n\t" " ld1 {v23.d}[1], [x14], x9 \n\t" " add x0, x0, x2 \n\t" " ldr q16, [x1, #16*0] \n\t" // Load B col. " ldr q17, [x1, #16*1] \n\t" " add x1, x1, x3 \n\t" " sub x8, x8, #1 \n\t" DGEMM_8X4_MKER_LOOP_PLAIN_LOC(20,21,22,23,16,17,xzr,-1,noload) BRANCH(K_LEFT_LOOP) // // Scale and write to memory. LABEL(WRITE_MEM_PREP) " ldr x4, %[alpha] \n\t" // Load alpha & beta (address). " ldr x8, %[beta] \n\t" " ld1r {v16.2d}, [x4] \n\t" // Load alpha & beta (value). " ld1r {v17.2d}, [x8] \n\t" " fmov d18, #1.0 \n\t" " fcmp d16, d18 \n\t" BEQ(UNIT_ALPHA) DSCALE8V(0,1,2,3,4,5,6,7,16,0) DSCALE8V(8,9,10,11,12,13,14,15,16,0) LABEL(UNIT_ALPHA) " \n\t" " mov x1, x5 \n\t" // C address for loading. " \n\t" // C address for storing is x5 itself. " cmp x6, #8 \n\t" // Check for row-storage. BNE(WRITE_MEM_R) // // C storage in columns. LABEL(WRITE_MEM_C) " fcmp d17, #0.0 \n\t" BEQ(ZERO_BETA_C) DLOADC_4V_C_FWD(20,21,22,23,x1,0,x7) DLOADC_4V_C_FWD(24,25,26,27,x1,0,x7) DSCALEA8V(0,1,2,3,4,5,6,7,20,21,22,23,24,25,26,27,17,0) // DLOADC_4V_C_FWD(20,21,22,23,x1,0,x7) DLOADC_4V_C_FWD(24,25,26,27,x1,0,x7) DSCALEA8V(8,9,10,11,12,13,14,15,20,21,22,23,24,25,26,27,17,0) LABEL(ZERO_BETA_C) // DSTOREC_4V_C_FWD(0,1,2,3,x5,0,x7) DSTOREC_4V_C_FWD(4,5,6,7,x5,0,x7) DSTOREC_4V_C_FWD(8,9,10,11,x5,0,x7) DSTOREC_4V_C_FWD(12,13,14,15,x5,0,x7) BRANCH(END_WRITE_MEM) // // C storage in rows. LABEL(WRITE_MEM_R) // In-register transpose. " trn1 v16.2d, v0.2d, v4.2d \n\t" // Row 0. " trn1 v17.2d, v8.2d, v12.2d \n\t" " trn2 v18.2d, v0.2d, v4.2d \n\t" // Row 1. " trn2 v19.2d, v8.2d, v12.2d \n\t" " trn1 v20.2d, v1.2d, v5.2d \n\t" // Row 2. " trn1 v21.2d, v9.2d, v13.2d \n\t" " trn2 v22.2d, v1.2d, v5.2d \n\t" // Row 3. " trn2 v23.2d, v9.2d, v13.2d \n\t" " trn1 v24.2d, v2.2d, v6.2d \n\t" // Row 4. " trn1 v25.2d, v10.2d, v14.2d \n\t" " trn2 v26.2d, v2.2d, v6.2d \n\t" // Row 5. " trn2 v27.2d, v10.2d, v14.2d \n\t" " trn1 v28.2d, v3.2d, v7.2d \n\t" // Row 6. " trn1 v29.2d, v11.2d, v15.2d \n\t" " trn2 v30.2d, v3.2d, v7.2d \n\t" // Row 7. " trn2 v31.2d, v11.2d, v15.2d \n\t" // " ld1r {v14.2d}, [x4] \n\t" // Reload alpha & beta (value). " ld1r {v15.2d}, [x8] \n\t" " fcmp d15, #0.0 \n\t" BEQ(ZERO_BETA_R) DLOADC_4V_R_FWD(0,1,2,3,x1,0,x6) DLOADC_4V_R_FWD(4,5,6,7,x1,0,x6) DSCALEA8V(16,17,18,19,20,21,22,23,0,1,2,3,4,5,6,7,15,0) // DLOADC_4V_R_FWD(0,1,2,3,x1,0,x6) DLOADC_4V_R_FWD(4,5,6,7,x1,0,x6) DSCALEA8V(24,25,26,27,28,29,30,31,0,1,2,3,4,5,6,7,15,0) LABEL(ZERO_BETA_R) // DSTOREC_4V_R_FWD(16,17,18,19,x5,0,x6) DSTOREC_4V_R_FWD(20,21,22,23,x5,0,x6) DSTOREC_4V_R_FWD(24,25,26,27,x5,0,x6) DSTOREC_4V_R_FWD(28,29,30,31,x5,0,x6) // // End of this microkernel. LABEL(END_WRITE_MEM) " \n\t" " subs x12, x12, #1 \n\t" BEQ(END_EXEC) " \n\t" " mov x8, #8 \n\t" " madd x13, x6, x8, x13 \n\t" // Forward C's base address to the next logic panel. " add x10, x10, x11 \n\t" // Forward A's base address to the next logic panel. BRANCH(MILLIKER_MLOOP) // // End of execution. LABEL(END_EXEC) : : [a] "m" (a), [b] "m" (b), [c] "m" (c), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [ps_a] "m" (ps_a), [rs_b] "m" (rs_b), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c), [m_iter] "m" (m_iter), [k_mker] "m" (k_mker), [k_left] "m" (k_left), [alpha] "m" (alpha), [beta] "m" (beta) : "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10","x11","x12","x13","x14", "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", "v10","v11","v12","v13","v14","v15", "v16","v17","v18","v19","v20","v21","v22","v23", "v24","v25","v26","v27","v28","v29","v30","v31" ); consider_edge_cases: a = a + m_iter * ps_a; c = c + m_iter * 8 * rs_c; // Edge case is within 1 millikernel loop of THIS kernel. // Regarding the 6x?m kernel, the panel stride should be always local. auxinfo_t data_6xkm = *data; bli_auxinfo_set_ps_a( 6 * rs_a, &data_6xkm ); if ( m_left ) { bli_dgemmsup_rv_armv8a_int_6x4mn ( conja, conjb, m_left, 4, k0, alpha, a, rs_a0, cs_a0, b, rs_b0, cs_b0, beta, c, rs_c0, cs_c0, &data_6xkm, cntx ); } // Issue prefetch instructions only after // execution is done. __asm__ ( " mov x0, %[a_next] \n\t" " mov x1, %[b_next] \n\t" " prfm PLDL1STRM, [x0, #16*0] \n\t" " prfm PLDL1STRM, [x0, #16*1] \n\t" " prfm PLDL1STRM, [x0, #16*2] \n\t" " prfm PLDL1KEEP, [x1, #16*0] \n\t" " prfm PLDL1KEEP, [x1, #16*1] \n\t" " prfm PLDL1KEEP, [x1, #16*2] \n\t" : : [a_next] "r" (a_next), [b_next] "r" (b_next) : "x0", "x1" ); } blis-0.9.0/kernels/armv8a/3/sup/d3x4/000077500000000000000000000000001422157504600170535ustar00rootroot00000000000000blis-0.9.0/kernels/armv8a/3/sup/d3x4/bli_gemmsup_rd_armv8a_asm_d3x4.c000066400000000000000000000313731422157504600251760ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2021, The University of Tokyo 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // Supplimentary fixed-size gemmsup. #include "blis.h" #include "assert.h" // Label locality & misc. #include "../../armv8a_asm_utils.h" #define DGEMM_3X1X2_NKER_SUBLOOP(C0,C1,C2,A0,A1,A2,B) \ " fmla v"#C0".2d, v"#A0".2d, v"#B".2d \n\t" \ " fmla v"#C1".2d, v"#A1".2d, v"#B".2d \n\t" \ " fmla v"#C2".2d, v"#A2".2d, v"#B".2d \n\t" #define DGEMM_3X4X2_K_MKER_LOOP_PLAIN(C00,C01,C02,C03,C10,C11,C12,C13,C20,C21,C22,C23,A0,A1,A2,B0,B1,B2,B3) \ DGEMM_3X1X2_NKER_SUBLOOP(C00,C10,C20,A0,A1,A2,B0) \ DGEMM_3X1X2_NKER_SUBLOOP(C01,C11,C21,A0,A1,A2,B1) \ DGEMM_3X1X2_NKER_SUBLOOP(C02,C12,C22,A0,A1,A2,B2) \ DGEMM_3X1X2_NKER_SUBLOOP(C03,C13,C23,A0,A1,A2,B3) // For row-storage of C. #define DLOADC_2V_R_FWD(C0,C1,CADDR,CSHIFT,RSC) \ DLOAD2V(C0,C1,CADDR,CSHIFT) \ " add "#CADDR", "#CADDR", "#RSC" \n\t" #define DSTOREC_2V_R_FWD(C0,C1,CADDR,CSHIFT,RSC) \ DSTORE2V(C0,C1,CADDR,CSHIFT) \ " add "#CADDR", "#CADDR", "#RSC" \n\t" // For column-storage of C. #define DLOADC_1V_1ELM_C_FWD(C0,CSCALAR,CIDX,CADDR,CSHIFT,CSC) \ DLOAD1V(C0,CADDR,CSHIFT) \ " add "#CADDR", "#CADDR", #"#CSHIFT"+16 \n\t" \ " ld1 {v"#CSCALAR".d}["#CIDX"], ["#CADDR"] \n\t" \ " sub "#CADDR", "#CADDR", #"#CSHIFT"+16 \n\t" \ " add "#CADDR", "#CADDR", "#CSC" \n\t" #define DSTOREC_1V_1ELM_C_FWD(C0,CSCALAR,CIDX,CADDR,CSHIFT,CSC) \ DSTORE1V(C0,CADDR,CSHIFT) \ " add "#CADDR", "#CADDR", #"#CSHIFT"+16 \n\t" \ " st1 {v"#CSCALAR".d}["#CIDX"], ["#CADDR"] \n\t" \ " sub "#CADDR", "#CADDR", #"#CSHIFT"+16 \n\t" \ " add "#CADDR", "#CADDR", "#CSC" \n\t" #define DSCALE6V(V0,V1,V2,V3,V4,V5,A,IDX) \ DSCALE4V(V0,V1,V2,V3,A,IDX) \ DSCALE2V(V4,V5,A,IDX) #define DSCALEA6V(D0,D1,D2,D3,D4,D5,S0,S1,S2,S3,S4,S5,A,IDX) \ DSCALEA4V(D0,D1,D2,D3,S0,S1,S2,S3,A,IDX) \ DSCALEA2V(D4,D5,S4,S5,A,IDX) void bli_dgemmsup_rd_armv8a_asm_3x4 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { assert( m0 == 3 ); assert( n0 == 4 ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_mker = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; assert( cs_a0 == 1 ); assert( rs_b0 == 1 ); __asm__ volatile ( " ldr x0, %[a] \n\t" " ldr x1, %[b] \n\t" " ldr x2, %[rs_a] \n\t" // Row-skip of A. " ldr x3, %[cs_b] \n\t" // Column-skip of B. " \n\t" " ldr x5, %[c] \n\t" " ldr x6, %[rs_c] \n\t" // Row-skip of C. " ldr x7, %[cs_c] \n\t" // Column-skip of C. " \n\t" " \n\t" // Multiply some address skips by sizeof(double). " lsl x2, x2, #3 \n\t" // rs_a " lsl x3, x3, #3 \n\t" // cs_b " lsl x6, x6, #3 \n\t" // rs_c " lsl x7, x7, #3 \n\t" // cs_c " \n\t" " ldr x4, %[k_mker] \n\t" " ldr x8, %[k_left] \n\t" " \n\t" // Storage scheme: // V[ 0:11] <- C // V[12:14] <- A // V[16:19] <- B // Under this scheme, the following is defined: #define DGEMM_3X4X2_K_MKER_LOOP_PLAIN_LOC(A0,A1,A2,B0,B1,B2,B3) \ DGEMM_3X4X2_K_MKER_LOOP_PLAIN(0,1,2,3,4,5,6,7,8,9,10,11,A0,A1,A2,B0,B1,B2,B3) // Load from memory. LABEL(LOAD_ABC) " \n\t" // No-microkernel early return is a must " cmp x4, #0 \n\t" // to avoid out-of-boundary read. BEQ(CLEAR_CCOLS) " \n\t" " mov x11, x1 \n\t" // Load B. " ldr q16, [x11] \n\t" " add x11, x11, x3 \n\t" " ldr q17, [x11] \n\t" " add x11, x11, x3 \n\t" " ldr q18, [x11] \n\t" " add x11, x11, x3 \n\t" " ldr q19, [x11] \n\t" " add x1, x1, #16 \n\t" " \n\t" " mov x14, x0 \n\t" // Load A. " ldr q12, [x14] \n\t" " add x14, x14, x2 \n\t" " ldr q13, [x14] \n\t" " add x14, x14, x2 \n\t" " ldr q14, [x14] \n\t" " add x0, x0, #16 \n\t" LABEL(CLEAR_CCOLS) CLEAR8V(0,1,2,3,4,5,6,7) CLEAR4V(8,9,10,11) // No-microkernel early return, once again. BEQ(K_LEFT_LOOP) // // Microkernel is defined here as: #define DGEMM_3X4X2_K_MKER_LOOP_PLAIN_LOC_FWD(A0,A1,A2,B0,B1,B2,B3) \ DGEMM_3X4X2_K_MKER_LOOP_PLAIN_LOC(A0,A1,A2,B0,B1,B2,B3) \ "mov x11, x1 \n\t" \ "ldr q"#B0", [x11] \n\t" \ "add x11, x11, x3 \n\t" \ "ldr q"#B1", [x11] \n\t" \ "add x11, x11, x3 \n\t" \ "ldr q"#B2", [x11] \n\t" \ "add x11, x11, x3 \n\t" \ "ldr q"#B3", [x11] \n\t" \ "add x1, x1, #16 \n\t" \ "mov x14, x0 \n\t" \ "ldr q"#A0", [x14] \n\t" \ "add x14, x14, x2 \n\t" \ "ldr q"#A1", [x14] \n\t" \ "add x14, x14, x2 \n\t" \ "ldr q"#A2", [x14] \n\t" \ "add x0, x0, #16 \n\t" // Start microkernel loop. LABEL(K_MKER_LOOP) DGEMM_3X4X2_K_MKER_LOOP_PLAIN_LOC_FWD(12,13,14,16,17,18,19) " \n\t" // Decrease counter before final replica. " subs x4, x4, #1 \n\t" // Branch early to avoid reading excess mem. BEQ(FIN_MKER_LOOP) DGEMM_3X4X2_K_MKER_LOOP_PLAIN_LOC_FWD(12,13,14,16,17,18,19) BRANCH(K_MKER_LOOP) // // Final microkernel loop. LABEL(FIN_MKER_LOOP) DGEMM_3X4X2_K_MKER_LOOP_PLAIN_LOC(12,13,14,16,17,18,19) // // If major kernel is executed, // an additional depth-summation is required. " faddp v0.2d, v0.2d, v1.2d \n\t" // Line 0. " faddp v1.2d, v2.2d, v3.2d \n\t" " faddp v2.2d, v4.2d, v5.2d \n\t" // Line 1. " faddp v3.2d, v6.2d, v7.2d \n\t" " faddp v4.2d, v8.2d, v9.2d \n\t" // Line 2. " faddp v5.2d, v10.2d, v11.2d \n\t" " \n\t" // Loops left behind microkernels. LABEL(K_LEFT_LOOP) " cmp x8, #0 \n\t" // End of exec. BEQ(WRITE_MEM_PREP) " mov x11, x1 \n\t" // Load B row. " ld1 {v28.d}[0], [x11], x3 \n\t" " ld1 {v28.d}[1], [x11], x3 \n\t" " ld1 {v29.d}[0], [x11], x3 \n\t" " ld1 {v29.d}[1], [x11], x3 \n\t" " add x1, x1, #8 \n\t" " mov x14, x0 \n\t" // Load A column. " ld1 {v24.d}[0], [x14], x2 \n\t" " ld1 {v24.d}[1], [x14], x2 \n\t" " ld1 {v25.d}[0], [x14], x2 \n\t" " add x0, x0, #8 \n\t" " fmla v0.2d, v28.2d, v24.d[0] \n\t" " fmla v1.2d, v29.2d, v24.d[0] \n\t" " fmla v2.2d, v28.2d, v24.d[1] \n\t" " fmla v3.2d, v29.2d, v24.d[1] \n\t" " fmla v4.2d, v28.2d, v25.d[0] \n\t" " fmla v5.2d, v29.2d, v25.d[0] \n\t" " sub x8, x8, #1 \n\t" BRANCH(K_LEFT_LOOP) // // Scale and write to memory. LABEL(WRITE_MEM_PREP) " ldr x4, %[alpha] \n\t" // Load alpha & beta (address). " ldr x8, %[beta] \n\t" " ld1r {v30.2d}, [x4] \n\t" // Load alpha & beta (value). " ld1r {v31.2d}, [x8] \n\t" DSCALE6V(0,1,2,3,4,5,30,0) " \n\t" " mov x9, x5 \n\t" // C address for loading. " \n\t" // C address for storing is x5 itself. " cmp x7, #8 \n\t" // Check for column-storage. BNE(WRITE_MEM_C) // // C storage in rows. LABEL(WRITE_MEM_R) " fcmp d31, #0.0 \n\t" BEQ(ZERO_BETA_R) DLOADC_2V_R_FWD(12,13,x9,0,x6) DLOADC_2V_R_FWD(14,15,x9,0,x6) DLOADC_2V_R_FWD(16,17,x9,0,x6) DSCALEA6V(0,1,2,3,4,5,12,13,14,15,16,17,31,0) LABEL(ZERO_BETA_R) DSTOREC_2V_R_FWD(0,1,x5,0,x6) DSTOREC_2V_R_FWD(2,3,x5,0,x6) DSTOREC_2V_R_FWD(4,5,x5,0,x6) BRANCH(END_WRITE_MEM) // // C storage in columns. LABEL(WRITE_MEM_C) " trn1 v6.2d, v0.2d, v2.2d \n\t" " trn2 v7.2d, v0.2d, v2.2d \n\t" " trn1 v8.2d, v1.2d, v3.2d \n\t" " trn2 v9.2d, v1.2d, v3.2d \n\t" " fcmp d31, #0.0 \n\t" BEQ(ZERO_BETA_C) DLOADC_1V_1ELM_C_FWD(12,20,0,x9,0,x7) DLOADC_1V_1ELM_C_FWD(13,20,1,x9,0,x7) DLOADC_1V_1ELM_C_FWD(14,21,0,x9,0,x7) DLOADC_1V_1ELM_C_FWD(15,21,1,x9,0,x7) DSCALEA6V(6,7,8,9,4,5,12,13,14,15,20,21,31,0) LABEL(ZERO_BETA_C) DSTOREC_1V_1ELM_C_FWD(6,4,0,x5,0,x7) DSTOREC_1V_1ELM_C_FWD(7,4,1,x5,0,x7) DSTOREC_1V_1ELM_C_FWD(8,5,0,x5,0,x7) DSTOREC_1V_1ELM_C_FWD(9,5,1,x5,0,x7) // // End of this microkernel. LABEL(END_WRITE_MEM) // // End of execution. LABEL(END_EXEC) : : [a] "m" (a), [b] "m" (b), [c] "m" (c), [rs_a] "m" (rs_a), [cs_b] "m" (cs_b), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c), [k_mker] "m" (k_mker), [k_left] "m" (k_left), [alpha] "m" (alpha), [beta] "m" (beta) : "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10","x11","x12","x13","x14", "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", "v10","v11","v12","v13","v14","v15", "v16","v17","v18","v19","v20","v21","v22","v23", "v24","v25","v26","v27","v28","v29","v30","v31" ); } blis-0.9.0/kernels/armv8a/3/sup/d3x4/bli_gemmsup_rd_armv8a_asm_d6x3.c000066400000000000000000000367051422157504600252040ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2021, The University of Tokyo 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // Supplimentary fixed-size gemmsup. #include "blis.h" #include "assert.h" // Label locality & misc. #include "../../armv8a_asm_utils.h" #define DGEMM_1X3X2_NKER_SUBLOOP(C0,C1,C2,A,B0,B1,B2) \ " fmla v"#C0".2d, v"#A".2d, v"#B0".2d \n\t" \ " fmla v"#C1".2d, v"#A".2d, v"#B1".2d \n\t" \ " fmla v"#C2".2d, v"#A".2d, v"#B2".2d \n\t" #define DGEMM_6X3X2_K_MKER_LOOP_PLAIN(C00,C01,C02,C10,C11,C12,C20,C21,C22,C30,C31,C32,C40,C41,C42,C50,C51,C52,A0,A1,A2,A3,A4,A5,B0,B1,B2,AADDR,AELEMADDR,AELEMST,LOAD0,LOAD1) \ DGEMM_1X3X2_NKER_SUBLOOP(C00,C01,C02,A0,B0,B1,B2) \ DGEMM_LOAD1V_K_ ##LOAD0 (A0,AELEMADDR,AELEMST) \ DGEMM_1X3X2_NKER_SUBLOOP(C10,C11,C12,A1,B0,B1,B2) \ DGEMM_LOAD1V_K_ ##LOAD0 (A1,AELEMADDR,AELEMST) \ DGEMM_1X3X2_NKER_SUBLOOP(C20,C21,C22,A2,B0,B1,B2) \ DGEMM_LOAD1V_K_ ##LOAD0 (A2,AELEMADDR,AELEMST) \ DGEMM_1X3X2_NKER_SUBLOOP(C30,C31,C32,A3,B0,B1,B2) \ DGEMM_LOAD1V_K_ ##LOAD0 (A3,AELEMADDR,AELEMST) \ DGEMM_FWDA_K_ ##LOAD0 (AADDR) \ " mov "#AELEMADDR", "#AADDR" \n\t" \ DGEMM_1X3X2_NKER_SUBLOOP(C40,C41,C42,A4,B0,B1,B2) \ DGEMM_LOAD1V_K_ ##LOAD1 (A4,AELEMADDR,AELEMST) \ DGEMM_1X3X2_NKER_SUBLOOP(C50,C51,C52,A5,B0,B1,B2) \ DGEMM_LOAD1V_K_ ##LOAD1 (A5,AELEMADDR,AELEMST) #define DGEMM_LOAD1V_K_noload(V,ELEMADDR,ELEMST) #define DGEMM_LOAD1V_K_load(V,ELEMADDR,ELEMST) \ " ldr q"#V", [ "#ELEMADDR" ] \n\t" \ " add "#ELEMADDR", "#ELEMADDR", "#ELEMST" \n\t" #define DGEMM_FWDA_K_noload(ADDR) #define DGEMM_FWDA_K_load(ADDR) \ " add "#ADDR", "#ADDR", #16 \n\t" // For row-storage of C. #define DLOADC_1V_1ELM_R_FWD(C0,CSCALAR,CIDX,CADDR,CSHIFT,RSC) \ DLOAD1V(C0,CADDR,CSHIFT) \ " add "#CADDR", "#CADDR", #"#CSHIFT"+16 \n\t" \ " ld1 {v"#CSCALAR".d}["#CIDX"], ["#CADDR"] \n\t" \ " sub "#CADDR", "#CADDR", #"#CSHIFT"+16 \n\t" \ " add "#CADDR", "#CADDR", "#RSC" \n\t" #define DSTOREC_1V_1ELM_R_FWD(C0,CSCALAR,CIDX,CADDR,CSHIFT,RSC) \ DSTORE1V(C0,CADDR,CSHIFT) \ " add "#CADDR", "#CADDR", #"#CSHIFT"+16 \n\t" \ " st1 {v"#CSCALAR".d}["#CIDX"], ["#CADDR"] \n\t" \ " sub "#CADDR", "#CADDR", #"#CSHIFT"+16 \n\t" \ " add "#CADDR", "#CADDR", "#RSC" \n\t" // For column-storage of C. #define DLOADC_3V_C_FWD(C0,C1,C2,CADDR,CSHIFT,CSC) \ DLOAD2V(C0,C1,CADDR,CSHIFT) \ DLOAD1V(C2,CADDR,CSHIFT+32) \ " add "#CADDR", "#CADDR", "#CSC" \n\t" #define DSTOREC_3V_C_FWD(C0,C1,C2,CADDR,CSHIFT,CSC) \ DSTORE2V(C0,C1,CADDR,CSHIFT) \ DSTORE1V(C2,CADDR,CSHIFT+32) \ " add "#CADDR", "#CADDR", "#CSC" \n\t" #define DSCALE9V(V0,V1,V2,V3,V4,V5,V6,V7,V8,A,IDX) \ DSCALE4V(V0,V1,V2,V3,A,IDX) \ DSCALE4V(V4,V5,V6,V7,A,IDX) \ DSCALE1V(V8,A,IDX) #define DSCALEA9V(D0,D1,D2,D3,D4,D5,D6,D7,D8,S0,S1,S2,S3,S4,S5,S6,S7,S8,A,IDX) \ DSCALEA4V(D0,D1,D2,D3,S0,S1,S2,S3,A,IDX) \ DSCALEA4V(D4,D5,D6,D7,S4,S5,S6,S7,A,IDX) \ DSCALEA1V(D8,S8,A,IDX) void bli_dgemmsup_rd_armv8a_asm_6x3 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { assert( m0 == 6 ); assert( n0 == 3 ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_mker = k0 / 8; uint64_t k_left = k0 % 8; uint64_t rs_a = rs_a0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; assert( cs_a0 == 1 ); assert( rs_b0 == 1 ); __asm__ volatile ( " ldr x0, %[a] \n\t" " ldr x1, %[b] \n\t" " ldr x2, %[rs_a] \n\t" // Row-skip of A. " ldr x3, %[cs_b] \n\t" // Column-skip of B. " \n\t" " ldr x5, %[c] \n\t" " ldr x6, %[rs_c] \n\t" // Row-skip of C. " ldr x7, %[cs_c] \n\t" // Column-skip of C. " \n\t" " \n\t" // Multiply some address skips by sizeof(double). " lsl x2, x2, #3 \n\t" // rs_a " lsl x3, x3, #3 \n\t" // cs_b " lsl x6, x6, #3 \n\t" // rs_c " lsl x7, x7, #3 \n\t" // cs_c " \n\t" " ldr x4, %[k_mker] \n\t" " ldr x8, %[k_left] \n\t" " \n\t" // Storage scheme: // V[ 0:17] <- C // V[18:23] <- B // V[24:31] <- A // Under this scheme, the following is defined: #define DGEMM_6X3X2_K_MKER_LOOP_PLAIN_LOC(A0,A1,A2,A3,A4,A5,B0,B1,B2,AADDR,AELEMADDR,AELEMST,LOAD0,LOAD1) \ DGEMM_6X3X2_K_MKER_LOOP_PLAIN(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,A0,A1,A2,A3,A4,A5,B0,B1,B2,AADDR,AELEMADDR,AELEMST,LOAD0,LOAD1) // Load from memory. LABEL(LOAD_ABC) " \n\t" // No-microkernel early return is a must " cmp x4, #0 \n\t" // to avoid out-of-boundary read. BEQ(CLEAR_CCOLS) " \n\t" " mov x14, x0 \n\t" // Load A. " ldr q24, [x14] \n\t" " add x14, x14, x2 \n\t" " ldr q25, [x14] \n\t" " add x14, x14, x2 \n\t" " ldr q26, [x14] \n\t" " add x14, x14, x2 \n\t" " ldr q27, [x14] \n\t" " add x14, x14, x2 \n\t" " ldr q28, [x14] \n\t" " add x14, x14, x2 \n\t" " ldr q29, [x14] \n\t" " add x0, x0, #16 \n\t" " mov x14, x0 \n\t" " ldr q30, [x14] \n\t" " add x14, x14, x2 \n\t" " ldr q31, [x14] \n\t" " add x14, x14, x2 \n\t" " \n\t" " mov x11, x1 \n\t" // Load B. " ldr q18, [x11] \n\t" " add x11, x11, x3 \n\t" " ldr q19, [x11] \n\t" " add x11, x11, x3 \n\t" " ldr q20, [x11] \n\t" " add x1, x1, #16 \n\t" " mov x11, x1 \n\t" " ldr q21, [x11] \n\t" " add x11, x11, x3 \n\t" " ldr q22, [x11] \n\t" " add x11, x11, x3 \n\t" " ldr q23, [x11] \n\t" " add x1, x1, #16 \n\t" LABEL(CLEAR_CCOLS) CLEAR8V(0,1,2,3,4,5,6,7) CLEAR8V(8,9,10,11,12,13,14,15) CLEAR2V(16,17) // No-microkernel early return, once again. BEQ(K_LEFT_LOOP) // // Microkernel is defined here as: #define DGEMM_6X3X2_K_MKER_LOOP_PLAIN_LOC_FWD(A0,A1,A2,A3,A4,A5,B0,B1,B2) \ DGEMM_6X3X2_K_MKER_LOOP_PLAIN_LOC(A0,A1,A2,A3,A4,A5,B0,B1,B2,x0,x14,x2,load,load) \ "mov x11, x1 \n\t" \ "ldr q"#B0", [x11] \n\t" \ "add x11, x11, x3 \n\t" \ "ldr q"#B1", [x11] \n\t" \ "add x11, x11, x3 \n\t" \ "ldr q"#B2", [x11] \n\t" \ "add x1, x1, #16 \n\t" \ // Start microkernel loop. LABEL(K_MKER_LOOP) DGEMM_6X3X2_K_MKER_LOOP_PLAIN_LOC_FWD(24,25,26,27,28,29,18,19,20) DGEMM_6X3X2_K_MKER_LOOP_PLAIN_LOC_FWD(30,31,24,25,26,27,21,22,23) " \n\t" // Decrease counter before final replica. " subs x4, x4, #1 \n\t" // Branch early to avoid reading excess mem. BEQ(FIN_MKER_LOOP) DGEMM_6X3X2_K_MKER_LOOP_PLAIN_LOC_FWD(28,29,30,31,24,25,18,19,20) DGEMM_6X3X2_K_MKER_LOOP_PLAIN_LOC_FWD(26,27,28,29,30,31,21,22,23) BRANCH(K_MKER_LOOP) // // Final microkernel loop. LABEL(FIN_MKER_LOOP) DGEMM_6X3X2_K_MKER_LOOP_PLAIN_LOC(28,29,30,31,24,25,18,19,20,x0,x14,x2,load,noload) DGEMM_6X3X2_K_MKER_LOOP_PLAIN_LOC(26,27,28,29,30,31,21,22,23,xzr,xzr,xzr,noload,noload) // // If major kernel is executed, // an additional depth-summation is required. " faddp v0.2d, v0.2d, v3.2d \n\t" // Column 0 Prt 0. " faddp v1.2d, v1.2d, v4.2d \n\t" // Column 1 Prt 0. " faddp v2.2d, v2.2d, v5.2d \n\t" // Column 2 Prt 0. " faddp v3.2d, v6.2d, v9.2d \n\t" // Column 0 Prt 1. " faddp v4.2d, v7.2d, v10.2d \n\t" // Column 1 Prt 1. " faddp v5.2d, v8.2d, v11.2d \n\t" // Column 2 Prt 1. " faddp v6.2d, v12.2d, v15.2d \n\t" // Column 0 Prt 2. " faddp v7.2d, v13.2d, v16.2d \n\t" // Column 1 Prt 2. " faddp v8.2d, v14.2d, v17.2d \n\t" // Column 2 Prt 2. " \n\t" // Loops left behind microkernels. LABEL(K_LEFT_LOOP) " cmp x8, #0 \n\t" // End of exec. BEQ(WRITE_MEM_PREP) " mov x14, x0 \n\t" // Load A column. " ld1 {v24.d}[0], [x14], x2 \n\t" " ld1 {v24.d}[1], [x14], x2 \n\t" " ld1 {v25.d}[0], [x14], x2 \n\t" " ld1 {v25.d}[1], [x14], x2 \n\t" " ld1 {v26.d}[0], [x14], x2 \n\t" " ld1 {v26.d}[1], [x14], x2 \n\t" " add x0, x0, #8 \n\t" " mov x11, x1 \n\t" // Load B row. " ld1 {v28.d}[0], [x11], x3 \n\t" " ld1 {v28.d}[1], [x11], x3 \n\t" " ld1 {v29.d}[0], [x11], x3 \n\t" " add x1, x1, #8 \n\t" " fmla v0.2d, v24.2d, v28.d[0] \n\t" " fmla v3.2d, v25.2d, v28.d[0] \n\t" " fmla v6.2d, v26.2d, v28.d[0] \n\t" " fmla v1.2d, v24.2d, v28.d[1] \n\t" " fmla v4.2d, v25.2d, v28.d[1] \n\t" " fmla v7.2d, v26.2d, v28.d[1] \n\t" " fmla v2.2d, v24.2d, v29.d[0] \n\t" " fmla v5.2d, v25.2d, v29.d[0] \n\t" " fmla v8.2d, v26.2d, v29.d[0] \n\t" " sub x8, x8, #1 \n\t" BRANCH(K_LEFT_LOOP) // // Scale and write to memory. LABEL(WRITE_MEM_PREP) " ldr x4, %[alpha] \n\t" // Load alpha & beta (address). " ldr x8, %[beta] \n\t" " ld1r {v30.2d}, [x4] \n\t" // Load alpha & beta (value). " ld1r {v31.2d}, [x8] \n\t" DSCALE9V(0,1,2,3,4,5,6,7,8,30,0) " \n\t" " mov x9, x5 \n\t" // C address for loading. " \n\t" // C address for storing is x5 itself. " cmp x7, #8 \n\t" // Check for column-storage. BNE(WRITE_MEM_C) // // C storage in rows. LABEL(WRITE_MEM_R) " trn1 v20.2d, v0.2d, v1.2d \n\t" " trn2 v21.2d, v0.2d, v1.2d \n\t" " trn1 v22.2d, v3.2d, v4.2d \n\t" " trn2 v23.2d, v3.2d, v4.2d \n\t" " trn1 v24.2d, v6.2d, v7.2d \n\t" " trn2 v25.2d, v6.2d, v7.2d \n\t" " fcmp d31, #0.0 \n\t" BEQ(ZERO_BETA_R) DLOADC_1V_1ELM_R_FWD(10,26,0,x9,0,x6) DLOADC_1V_1ELM_R_FWD(11,26,1,x9,0,x6) DLOADC_1V_1ELM_R_FWD(12,27,0,x9,0,x6) DLOADC_1V_1ELM_R_FWD(13,27,1,x9,0,x6) DLOADC_1V_1ELM_R_FWD(14,28,0,x9,0,x6) DLOADC_1V_1ELM_R_FWD(15,28,1,x9,0,x6) DSCALEA9V(20,21,22,23,24,25,2,5,8,10,11,12,13,14,15,26,27,28,31,0) LABEL(ZERO_BETA_R) DSTOREC_1V_1ELM_R_FWD(20,2,0,x5,0,x6) DSTOREC_1V_1ELM_R_FWD(21,2,1,x5,0,x6) DSTOREC_1V_1ELM_R_FWD(22,5,0,x5,0,x6) DSTOREC_1V_1ELM_R_FWD(23,5,1,x5,0,x6) DSTOREC_1V_1ELM_R_FWD(24,8,0,x5,0,x6) DSTOREC_1V_1ELM_R_FWD(25,8,1,x5,0,x6) BRANCH(END_WRITE_MEM) // // C storage in columns. LABEL(WRITE_MEM_C) " fcmp d31, #0.0 \n\t" BEQ(ZERO_BETA_C) DLOADC_3V_C_FWD(12,15,18,x9,0,x7) DLOADC_3V_C_FWD(13,16,19,x9,0,x7) DLOADC_3V_C_FWD(14,17,20,x9,0,x7) DSCALEA9V(0,1,2,3,4,5,6,7,8,12,13,14,15,16,17,18,19,20,31,0) LABEL(ZERO_BETA_C) DSTOREC_3V_C_FWD(0,3,6,x5,0,x7) DSTOREC_3V_C_FWD(1,4,7,x5,0,x7) DSTOREC_3V_C_FWD(2,5,8,x5,0,x7) // // End of this microkernel. LABEL(END_WRITE_MEM) // // End of execution. LABEL(END_EXEC) : : [a] "m" (a), [b] "m" (b), [c] "m" (c), [rs_a] "m" (rs_a), [cs_b] "m" (cs_b), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c), [k_mker] "m" (k_mker), [k_left] "m" (k_left), [alpha] "m" (alpha), [beta] "m" (beta) : "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10","x11","x12","x13","x14", "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", "v10","v11","v12","v13","v14","v15", "v16","v17","v18","v19","v20","v21","v22","v23", "v24","v25","v26","v27","v28","v29","v30","v31" ); } blis-0.9.0/kernels/armv8a/3/sup/d3x4/bli_gemmsup_rd_armv8a_int_d2x8.c000066400000000000000000000351631422157504600252140ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2021, The University of Tokyo 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // Supplimentary dynamic-size gemmsup. #include "blis.h" #include "assert.h" #include #if defined(__clang__) #define PRAGMA_NOUNROLL _Pragma("nounroll") #define PRAGMA_UNROLL _Pragma("unroll") #elif defined(__GNUC__) #define PRAGMA_NOUNROLL _Pragma("GCC unroll 1") #define PRAGMA_UNROLL _Pragma("GCC unroll 2") #else #define PRAGMA_NOUNROLL #define PRAGMA_UNROLL #endif /* * As these kernels requires num. of vregs about half of the total 32, * it should be all right to implement w/ intrinsics. * * c.f. https://www.youtube.com/watch?v=R2hQOVjRwVE . */ void bli_dgemmsup_rd_armv8a_int_2x8 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a, inc_t cs_a, double* restrict b, inc_t rs_b, inc_t cs_b, double* restrict beta, double* restrict c, inc_t rs_c, inc_t cs_c, auxinfo_t* restrict data, cntx_t* restrict cntx ) { assert( m0 <= 2 ); assert( n0 <= 8 ); double *a_loc = a; double *b_loc = b; double *c_loc = c; uint64_t k_mker = k0 / 2; uint64_t k_left = k0 % 2; uint64_t b_iszr = ( *beta == 0.0 ); assert( cs_a == 1 ); assert( rs_b == 1 ); // Registers used to store a 2x8x2 block of C (summing the last dimension). // Total: 22 specified. float64x2_t vc_00, vc_01, vc_02, vc_03, vc_04, vc_05, vc_06, vc_07; float64x2_t vc_10, vc_11, vc_12, vc_13, vc_14, vc_15, vc_16, vc_17; float64x2_t va_0, va_1; float64x2_t vb_0, vb_1, vb_2, vb_3; vc_00 = (float64x2_t)vdupq_n_f64( 0 ); vc_01 = (float64x2_t)vdupq_n_f64( 0 ); vc_02 = (float64x2_t)vdupq_n_f64( 0 ); vc_03 = (float64x2_t)vdupq_n_f64( 0 ); vc_04 = (float64x2_t)vdupq_n_f64( 0 ); vc_05 = (float64x2_t)vdupq_n_f64( 0 ); vc_06 = (float64x2_t)vdupq_n_f64( 0 ); vc_07 = (float64x2_t)vdupq_n_f64( 0 ); vc_10 = (float64x2_t)vdupq_n_f64( 0 ); vc_11 = (float64x2_t)vdupq_n_f64( 0 ); vc_12 = (float64x2_t)vdupq_n_f64( 0 ); vc_13 = (float64x2_t)vdupq_n_f64( 0 ); vc_14 = (float64x2_t)vdupq_n_f64( 0 ); vc_15 = (float64x2_t)vdupq_n_f64( 0 ); vc_16 = (float64x2_t)vdupq_n_f64( 0 ); vc_17 = (float64x2_t)vdupq_n_f64( 0 ); PRAGMA_UNROLL for ( ; k_mker > 0; --k_mker ) { // if ( m0 > 0 ) va_0 = vld1q_f64( a_loc + rs_a * 0 ); if ( m0 > 1 ) va_1 = vld1q_f64( a_loc + rs_a * 1 ); // if ( n0 > 0 ) vb_0 = vld1q_f64( b_loc + cs_b * 0 ); if ( n0 > 1 ) vb_1 = vld1q_f64( b_loc + cs_b * 1 ); if ( n0 > 2 ) vb_2 = vld1q_f64( b_loc + cs_b * 2 ); if ( n0 > 3 ) vb_3 = vld1q_f64( b_loc + cs_b * 3 ); vc_00 = vfmaq_f64( vc_00, va_0, vb_0 ); vc_01 = vfmaq_f64( vc_01, va_0, vb_1 ); vc_02 = vfmaq_f64( vc_02, va_0, vb_2 ); vc_03 = vfmaq_f64( vc_03, va_0, vb_3 ); if ( m0 > 1 ) { vc_10 = vfmaq_f64( vc_10, va_1, vb_0 ); vc_11 = vfmaq_f64( vc_11, va_1, vb_1 ); vc_12 = vfmaq_f64( vc_12, va_1, vb_2 ); vc_13 = vfmaq_f64( vc_13, va_1, vb_3 ); } if ( n0 > 4 ) { vb_0 = vld1q_f64( b_loc + cs_b * 4 ); if ( n0 > 5 ) vb_1 = vld1q_f64( b_loc + cs_b * 5 ); if ( n0 > 6 ) vb_2 = vld1q_f64( b_loc + cs_b * 6 ); if ( n0 > 7 ) vb_3 = vld1q_f64( b_loc + cs_b * 7 ); vc_04 = vfmaq_f64( vc_04, va_0, vb_0 ); vc_05 = vfmaq_f64( vc_05, va_0, vb_1 ); if ( n0 > 6 ) { vc_06 = vfmaq_f64( vc_06, va_0, vb_2 ); vc_07 = vfmaq_f64( vc_07, va_0, vb_3 ); } if ( m0 > 1 ) { vc_14 = vfmaq_f64( vc_14, va_1, vb_0 ); vc_15 = vfmaq_f64( vc_15, va_1, vb_1 ); if ( n0 > 6 ) { vc_16 = vfmaq_f64( vc_16, va_1, vb_2 ); vc_17 = vfmaq_f64( vc_17, va_1, vb_3 ); } } } a_loc += 2; b_loc += 2; } // Pay no care for O(1) details. va_0 = (float64x2_t)vdupq_n_f64( 0 ); va_1 = (float64x2_t)vdupq_n_f64( 0 ); vb_0 = (float64x2_t)vdupq_n_f64( 0 ); vb_1 = (float64x2_t)vdupq_n_f64( 0 ); vb_2 = (float64x2_t)vdupq_n_f64( 0 ); vb_3 = (float64x2_t)vdupq_n_f64( 0 ); PRAGMA_NOUNROLL for ( ; k_left > 0; --k_left ) { // if ( m0 > 0 ) va_0 = vld1q_lane_f64( a_loc + rs_a * 0, va_0, 0 ); if ( m0 > 1 ) va_1 = vld1q_lane_f64( a_loc + rs_a * 1, va_1, 0 ); // if ( n0 > 0 ) vb_0 = vld1q_lane_f64( b_loc + cs_b * 0, vb_0, 0 ); if ( n0 > 1 ) vb_1 = vld1q_lane_f64( b_loc + cs_b * 1, vb_1, 0 ); if ( n0 > 2 ) vb_2 = vld1q_lane_f64( b_loc + cs_b * 2, vb_2, 0 ); if ( n0 > 3 ) vb_3 = vld1q_lane_f64( b_loc + cs_b * 3, vb_3, 0 ); vc_00 = vfmaq_f64( vc_00, va_0, vb_0 ); vc_01 = vfmaq_f64( vc_01, va_0, vb_1 ); vc_02 = vfmaq_f64( vc_02, va_0, vb_2 ); vc_03 = vfmaq_f64( vc_03, va_0, vb_3 ); vc_10 = vfmaq_f64( vc_10, va_1, vb_0 ); vc_11 = vfmaq_f64( vc_11, va_1, vb_1 ); vc_12 = vfmaq_f64( vc_12, va_1, vb_2 ); vc_13 = vfmaq_f64( vc_13, va_1, vb_3 ); if ( n0 > 4 ) vb_0 = vld1q_lane_f64( b_loc + cs_b * 4, vb_0, 0 ); if ( n0 > 5 ) vb_1 = vld1q_lane_f64( b_loc + cs_b * 5, vb_1, 0 ); if ( n0 > 6 ) vb_2 = vld1q_lane_f64( b_loc + cs_b * 6, vb_2, 0 ); if ( n0 > 7 ) vb_3 = vld1q_lane_f64( b_loc + cs_b * 7, vb_3, 0 ); vc_04 = vfmaq_f64( vc_04, va_0, vb_0 ); vc_05 = vfmaq_f64( vc_05, va_0, vb_1 ); vc_06 = vfmaq_f64( vc_06, va_0, vb_2 ); vc_07 = vfmaq_f64( vc_07, va_0, vb_3 ); vc_14 = vfmaq_f64( vc_14, va_1, vb_0 ); vc_15 = vfmaq_f64( vc_15, va_1, vb_1 ); vc_16 = vfmaq_f64( vc_16, va_1, vb_2 ); vc_17 = vfmaq_f64( vc_17, va_1, vb_3 ); a_loc += 1; b_loc += 1; } // Load alpha and beta. // Note that here vb is used for alpha, in contrast to other kernels. vb_0 = vld1q_dup_f64( alpha ); va_0 = vld1q_dup_f64( beta ); // Scale. vc_00 = vmulq_f64( vc_00, vb_0 ); vc_01 = vmulq_f64( vc_01, vb_0 ); vc_02 = vmulq_f64( vc_02, vb_0 ); vc_03 = vmulq_f64( vc_03, vb_0 ); vc_04 = vmulq_f64( vc_04, vb_0 ); vc_05 = vmulq_f64( vc_05, vb_0 ); vc_06 = vmulq_f64( vc_06, vb_0 ); vc_07 = vmulq_f64( vc_07, vb_0 ); vc_10 = vmulq_f64( vc_10, vb_0 ); vc_11 = vmulq_f64( vc_11, vb_0 ); vc_12 = vmulq_f64( vc_12, vb_0 ); vc_13 = vmulq_f64( vc_13, vb_0 ); vc_14 = vmulq_f64( vc_14, vb_0 ); vc_15 = vmulq_f64( vc_15, vb_0 ); vc_16 = vmulq_f64( vc_16, vb_0 ); vc_17 = vmulq_f64( vc_17, vb_0 ); if ( cs_c == 1 ) { // Row-storage. vc_00 = vpaddq_f64( vc_00, vc_01 ); vc_02 = vpaddq_f64( vc_02, vc_03 ); vc_04 = vpaddq_f64( vc_04, vc_05 ); vc_06 = vpaddq_f64( vc_06, vc_07 ); vc_10 = vpaddq_f64( vc_10, vc_11 ); vc_12 = vpaddq_f64( vc_12, vc_13 ); vc_14 = vpaddq_f64( vc_14, vc_15 ); vc_16 = vpaddq_f64( vc_16, vc_17 ); if ( n0 > 1 ) vb_0 = vld1q_f64 ( c_loc + 0 * rs_c + 0 ); else if ( n0 > 0 ) vb_0 = vld1q_lane_f64( c_loc + 0 * rs_c + 0, vb_0, 0 ); if ( n0 > 3 ) vb_1 = vld1q_f64 ( c_loc + 0 * rs_c + 2 ); else if ( n0 > 2 ) vb_1 = vld1q_lane_f64( c_loc + 0 * rs_c + 2, vb_1, 0 ); if ( n0 > 5 ) vb_2 = vld1q_f64 ( c_loc + 0 * rs_c + 4 ); else if ( n0 > 4 ) vb_2 = vld1q_lane_f64( c_loc + 0 * rs_c + 4, vb_2, 0 ); if ( n0 > 7 ) vb_3 = vld1q_f64 ( c_loc + 0 * rs_c + 6 ); else if ( n0 > 6 ) vb_3 = vld1q_lane_f64( c_loc + 0 * rs_c + 6, vb_3, 0 ); if ( !b_iszr ) { vc_00 = vfmaq_f64( vc_00, va_0, vb_0 ); vc_02 = vfmaq_f64( vc_02, va_0, vb_1 ); vc_04 = vfmaq_f64( vc_04, va_0, vb_2 ); vc_06 = vfmaq_f64( vc_06, va_0, vb_3 ); } if ( n0 > 1 ) vst1q_f64 ( c_loc + 0 * rs_c + 0, vc_00 ); else if ( n0 > 0 ) vst1q_lane_f64( c_loc + 0 * rs_c + 0, vc_00, 0 ); if ( n0 > 3 ) vst1q_f64 ( c_loc + 0 * rs_c + 2, vc_02 ); else if ( n0 > 2 ) vst1q_lane_f64( c_loc + 0 * rs_c + 2, vc_02, 0 ); if ( n0 > 5 ) vst1q_f64 ( c_loc + 0 * rs_c + 4, vc_04 ); else if ( n0 > 4 ) vst1q_lane_f64( c_loc + 0 * rs_c + 4, vc_04, 0 ); if ( n0 > 7 ) vst1q_f64 ( c_loc + 0 * rs_c + 6, vc_06 ); else if ( n0 > 6 ) vst1q_lane_f64( c_loc + 0 * rs_c + 6, vc_06, 0 ); if ( m0 > 1 ) { if ( n0 > 1 ) vb_0 = vld1q_f64 ( c_loc + 1 * rs_c + 0 ); else if ( n0 > 0 ) vb_0 = vld1q_lane_f64( c_loc + 1 * rs_c + 0, vb_0, 0 ); if ( n0 > 3 ) vb_1 = vld1q_f64 ( c_loc + 1 * rs_c + 2 ); else if ( n0 > 2 ) vb_1 = vld1q_lane_f64( c_loc + 1 * rs_c + 2, vb_1, 0 ); if ( n0 > 5 ) vb_2 = vld1q_f64 ( c_loc + 1 * rs_c + 4 ); else if ( n0 > 4 ) vb_2 = vld1q_lane_f64( c_loc + 1 * rs_c + 4, vb_2, 0 ); if ( n0 > 7 ) vb_3 = vld1q_f64 ( c_loc + 1 * rs_c + 6 ); else if ( n0 > 6 ) vb_3 = vld1q_lane_f64( c_loc + 1 * rs_c + 6, vb_3, 0 ); if ( !b_iszr ) { vc_10 = vfmaq_f64( vc_10, va_0, vb_0 ); vc_12 = vfmaq_f64( vc_12, va_0, vb_1 ); vc_14 = vfmaq_f64( vc_14, va_0, vb_2 ); vc_16 = vfmaq_f64( vc_16, va_0, vb_3 ); } if ( n0 > 1 ) vst1q_f64 ( c_loc + 1 * rs_c + 0, vc_10 ); else if ( n0 > 0 ) vst1q_lane_f64( c_loc + 1 * rs_c + 0, vc_10, 0 ); if ( n0 > 3 ) vst1q_f64 ( c_loc + 1 * rs_c + 2, vc_12 ); else if ( n0 > 2 ) vst1q_lane_f64( c_loc + 1 * rs_c + 2, vc_12, 0 ); if ( n0 > 5 ) vst1q_f64 ( c_loc + 1 * rs_c + 4, vc_14 ); else if ( n0 > 4 ) vst1q_lane_f64( c_loc + 1 * rs_c + 4, vc_14, 0 ); if ( n0 > 7 ) vst1q_f64 ( c_loc + 1 * rs_c + 6, vc_16 ); else if ( n0 > 6 ) vst1q_lane_f64( c_loc + 1 * rs_c + 6, vc_16, 0 ); } } else { // Column-storage. vc_00 = vpaddq_f64( vc_00, vc_10 ); vc_01 = vpaddq_f64( vc_01, vc_11 ); vc_02 = vpaddq_f64( vc_02, vc_12 ); vc_03 = vpaddq_f64( vc_03, vc_13 ); vc_04 = vpaddq_f64( vc_04, vc_14 ); vc_05 = vpaddq_f64( vc_05, vc_15 ); vc_06 = vpaddq_f64( vc_06, vc_16 ); vc_07 = vpaddq_f64( vc_07, vc_17 ); if ( m0 > 1 ) { // if ( n0 > 0 ) vb_0 = vld1q_f64( c_loc + 0 + 0 * cs_c ); if ( n0 > 1 ) vb_1 = vld1q_f64( c_loc + 0 + 1 * cs_c ); if ( n0 > 2 ) vb_2 = vld1q_f64( c_loc + 0 + 2 * cs_c ); if ( n0 > 3 ) vb_3 = vld1q_f64( c_loc + 0 + 3 * cs_c ); if ( !b_iszr ) { vc_00 = vfmaq_f64( vc_00, va_0, vb_0 ); vc_01 = vfmaq_f64( vc_01, va_0, vb_1 ); vc_02 = vfmaq_f64( vc_02, va_0, vb_2 ); vc_03 = vfmaq_f64( vc_03, va_0, vb_3 ); } vst1q_f64( c_loc + 0 + 0 * cs_c, vc_00 ); if ( n0 > 1 ) vst1q_f64( c_loc + 0 + 1 * cs_c, vc_01 ); if ( n0 > 2 ) vst1q_f64( c_loc + 0 + 2 * cs_c, vc_02 ); if ( n0 > 3 ) vst1q_f64( c_loc + 0 + 3 * cs_c, vc_03 ); if ( n0 > 4 ) vb_0 = vld1q_f64( c_loc + 0 + 4 * cs_c ); if ( n0 > 5 ) vb_1 = vld1q_f64( c_loc + 0 + 5 * cs_c ); if ( n0 > 6 ) vb_2 = vld1q_f64( c_loc + 0 + 6 * cs_c ); if ( n0 > 7 ) vb_3 = vld1q_f64( c_loc + 0 + 7 * cs_c ); if ( !b_iszr ) { vc_04 = vfmaq_f64( vc_04, va_0, vb_0 ); vc_05 = vfmaq_f64( vc_05, va_0, vb_1 ); vc_06 = vfmaq_f64( vc_06, va_0, vb_2 ); vc_07 = vfmaq_f64( vc_07, va_0, vb_3 ); } if ( n0 > 4 ) vst1q_f64( c_loc + 0 + 4 * cs_c, vc_04 ); if ( n0 > 5 ) vst1q_f64( c_loc + 0 + 5 * cs_c, vc_05 ); if ( n0 > 6 ) vst1q_f64( c_loc + 0 + 6 * cs_c, vc_06 ); if ( n0 > 7 ) vst1q_f64( c_loc + 0 + 7 * cs_c, vc_07 ); } else { // if ( n0 > 0 ) vb_0 = vld1q_lane_f64( c_loc + 0 + 0 * cs_c, vb_0, 0 ); if ( n0 > 1 ) vb_1 = vld1q_lane_f64( c_loc + 0 + 1 * cs_c, vb_1, 0 ); if ( n0 > 2 ) vb_2 = vld1q_lane_f64( c_loc + 0 + 2 * cs_c, vb_2, 0 ); if ( n0 > 3 ) vb_3 = vld1q_lane_f64( c_loc + 0 + 3 * cs_c, vb_3, 0 ); if ( !b_iszr ) { vc_00 = vfmaq_f64( vc_00, va_0, vb_0 ); vc_01 = vfmaq_f64( vc_01, va_0, vb_1 ); vc_02 = vfmaq_f64( vc_02, va_0, vb_2 ); vc_03 = vfmaq_f64( vc_03, va_0, vb_3 ); } vst1q_lane_f64( c_loc + 0 + 0 * cs_c, vc_00, 0 ); if ( n0 > 1 ) vst1q_lane_f64( c_loc + 0 + 1 * cs_c, vc_01, 0 ); if ( n0 > 2 ) vst1q_lane_f64( c_loc + 0 + 2 * cs_c, vc_02, 0 ); if ( n0 > 3 ) vst1q_lane_f64( c_loc + 0 + 3 * cs_c, vc_03, 0 ); if ( n0 > 4 ) vb_0 = vld1q_lane_f64( c_loc + 0 + 4 * cs_c, vb_0, 0 ); if ( n0 > 5 ) vb_1 = vld1q_lane_f64( c_loc + 0 + 5 * cs_c, vb_1, 0 ); if ( n0 > 6 ) vb_2 = vld1q_lane_f64( c_loc + 0 + 6 * cs_c, vb_2, 0 ); if ( n0 > 7 ) vb_3 = vld1q_lane_f64( c_loc + 0 + 7 * cs_c, vb_3, 0 ); if ( !b_iszr ) { vc_04 = vfmaq_f64( vc_04, va_0, vb_0 ); vc_05 = vfmaq_f64( vc_05, va_0, vb_1 ); vc_06 = vfmaq_f64( vc_06, va_0, vb_2 ); vc_07 = vfmaq_f64( vc_07, va_0, vb_3 ); } if ( n0 > 4 ) vst1q_lane_f64( c_loc + 0 + 4 * cs_c, vc_04, 0 ); if ( n0 > 5 ) vst1q_lane_f64( c_loc + 0 + 5 * cs_c, vc_05, 0 ); if ( n0 > 6 ) vst1q_lane_f64( c_loc + 0 + 6 * cs_c, vc_06, 0 ); if ( n0 > 7 ) vst1q_lane_f64( c_loc + 0 + 7 * cs_c, vc_07, 0 ); } } } blis-0.9.0/kernels/armv8a/3/sup/d3x4/bli_gemmsup_rd_armv8a_int_d3x4.c000066400000000000000000000275341422157504600252140ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2021, The University of Tokyo 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // Supplimentary dynamic-size gemmsup. #include "blis.h" #include "assert.h" #include #if defined(__clang__) #define PRAGMA_NOUNROLL _Pragma("nounroll") #define PRAGMA_UNROLL _Pragma("unroll") #elif defined(__GNUC__) #define PRAGMA_NOUNROLL _Pragma("GCC unroll 1") #define PRAGMA_UNROLL _Pragma("GCC unroll 2") #else #define PRAGMA_NOUNROLL #define PRAGMA_UNROLL #endif /* * As these kernels requires num. of vregs about half of the total 32, * it should be all right to implement w/ intrinsics. * * c.f. https://www.youtube.com/watch?v=R2hQOVjRwVE . */ void bli_dgemmsup_rd_armv8a_int_3x4 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a, inc_t cs_a, double* restrict b, inc_t rs_b, inc_t cs_b, double* restrict beta, double* restrict c, inc_t rs_c, inc_t cs_c, auxinfo_t* restrict data, cntx_t* restrict cntx ) { // if ( m0 == 3 && n0 == 4 ) // { // // Use fixed-size version if it is full 3x4. // bli_dgemmsup_rd_armv8a_asm_3x4 // ( // conja, conjb, m0, n0, k0, // alpha, a, rs_a, cs_a, b, rs_b, cs_b, // beta, c, rs_c, cs_c, data, cntx // ); // return; // } assert( m0 <= 3 ); assert( n0 <= 4 ); double *a_loc = a; double *b_loc = b; double *c_loc = c; uint64_t k_mker = k0 / 2; uint64_t k_left = k0 % 2; uint64_t b_iszr = ( *beta == 0.0 ); assert( cs_a == 1 ); assert( rs_b == 1 ); // Registers used to store a 3x4x2 block of C (summing the last dimension). float64x2_t vc_00, vc_01, vc_02, vc_03; float64x2_t vc_10, vc_11, vc_12, vc_13; float64x2_t vc_20, vc_21, vc_22, vc_23; float64x2_t va_0, va_1, va_2; float64x2_t vb_0, vb_1, vb_2, vb_3; vc_00 = (float64x2_t)vdupq_n_f64( 0 ); vc_01 = (float64x2_t)vdupq_n_f64( 0 ); vc_02 = (float64x2_t)vdupq_n_f64( 0 ); vc_03 = (float64x2_t)vdupq_n_f64( 0 ); vc_10 = (float64x2_t)vdupq_n_f64( 0 ); vc_11 = (float64x2_t)vdupq_n_f64( 0 ); vc_12 = (float64x2_t)vdupq_n_f64( 0 ); vc_13 = (float64x2_t)vdupq_n_f64( 0 ); vc_20 = (float64x2_t)vdupq_n_f64( 0 ); vc_21 = (float64x2_t)vdupq_n_f64( 0 ); vc_22 = (float64x2_t)vdupq_n_f64( 0 ); vc_23 = (float64x2_t)vdupq_n_f64( 0 ); PRAGMA_UNROLL for ( ; k_mker > 0; --k_mker ) { // if ( m0 > 0 ) va_0 = vld1q_f64( a_loc + rs_a * 0 ); if ( m0 > 1 ) va_1 = vld1q_f64( a_loc + rs_a * 1 ); if ( m0 > 2 ) va_2 = vld1q_f64( a_loc + rs_a * 2 ); // if ( n0 > 0 ) vb_0 = vld1q_f64( b_loc + cs_b * 0 ); if ( n0 > 1 ) vb_1 = vld1q_f64( b_loc + cs_b * 1 ); if ( n0 > 2 ) vb_2 = vld1q_f64( b_loc + cs_b * 2 ); if ( n0 > 3 ) vb_3 = vld1q_f64( b_loc + cs_b * 3 ); a_loc += 2; b_loc += 2; // 1-column case. if ( n0 == 1 ) { vc_00 = vfmaq_f64( vc_00, va_0, vb_0 ); vc_10 = vfmaq_f64( vc_10, va_1, vb_0 ); vc_20 = vfmaq_f64( vc_20, va_2, vb_0 ); continue; } vc_00 = vfmaq_f64( vc_00, va_0, vb_0 ); vc_01 = vfmaq_f64( vc_01, va_0, vb_1 ); vc_02 = vfmaq_f64( vc_02, va_0, vb_2 ); vc_03 = vfmaq_f64( vc_03, va_0, vb_3 ); if ( m0 > 1 ) { vc_10 = vfmaq_f64( vc_10, va_1, vb_0 ); vc_11 = vfmaq_f64( vc_11, va_1, vb_1 ); vc_12 = vfmaq_f64( vc_12, va_1, vb_2 ); vc_13 = vfmaq_f64( vc_13, va_1, vb_3 ); } if ( m0 > 2 ) { vc_20 = vfmaq_f64( vc_20, va_2, vb_0 ); vc_21 = vfmaq_f64( vc_21, va_2, vb_1 ); vc_22 = vfmaq_f64( vc_22, va_2, vb_2 ); vc_23 = vfmaq_f64( vc_23, va_2, vb_3 ); } } // Pay no care for O(1) details. va_0 = (float64x2_t)vdupq_n_f64( 0 ); va_1 = (float64x2_t)vdupq_n_f64( 0 ); va_2 = (float64x2_t)vdupq_n_f64( 0 ); vb_0 = (float64x2_t)vdupq_n_f64( 0 ); vb_1 = (float64x2_t)vdupq_n_f64( 0 ); vb_2 = (float64x2_t)vdupq_n_f64( 0 ); vb_3 = (float64x2_t)vdupq_n_f64( 0 ); PRAGMA_NOUNROLL for ( ; k_left > 0; --k_left ) { // if ( m0 > 0 ) va_0 = vld1q_lane_f64( a_loc + rs_a * 0, va_0, 0 ); if ( m0 > 1 ) va_1 = vld1q_lane_f64( a_loc + rs_a * 1, va_1, 0 ); if ( m0 > 2 ) va_2 = vld1q_lane_f64( a_loc + rs_a * 2, va_2, 0 ); // if ( n0 > 0 ) vb_0 = vld1q_lane_f64( b_loc + cs_b * 0, vb_0, 0 ); if ( n0 > 1 ) vb_1 = vld1q_lane_f64( b_loc + cs_b * 1, vb_1, 0 ); if ( n0 > 2 ) vb_2 = vld1q_lane_f64( b_loc + cs_b * 2, vb_2, 0 ); if ( n0 > 3 ) vb_3 = vld1q_lane_f64( b_loc + cs_b * 3, vb_3, 0 ); vc_00 = vfmaq_f64( vc_00, va_0, vb_0 ); vc_01 = vfmaq_f64( vc_01, va_0, vb_1 ); vc_02 = vfmaq_f64( vc_02, va_0, vb_2 ); vc_03 = vfmaq_f64( vc_03, va_0, vb_3 ); vc_10 = vfmaq_f64( vc_10, va_1, vb_0 ); vc_11 = vfmaq_f64( vc_11, va_1, vb_1 ); vc_12 = vfmaq_f64( vc_12, va_1, vb_2 ); vc_13 = vfmaq_f64( vc_13, va_1, vb_3 ); vc_20 = vfmaq_f64( vc_20, va_2, vb_0 ); vc_21 = vfmaq_f64( vc_21, va_2, vb_1 ); vc_22 = vfmaq_f64( vc_22, va_2, vb_2 ); vc_23 = vfmaq_f64( vc_23, va_2, vb_3 ); a_loc += 1; b_loc += 1; } // Reduce. vc_00 = vpaddq_f64( vc_00, vc_01 ); vc_02 = vpaddq_f64( vc_02, vc_03 ); vc_10 = vpaddq_f64( vc_10, vc_11 ); vc_12 = vpaddq_f64( vc_12, vc_13 ); vc_20 = vpaddq_f64( vc_20, vc_21 ); vc_22 = vpaddq_f64( vc_22, vc_23 ); // Load alpha and beta. va_0 = vld1q_dup_f64( alpha ); vb_0 = vld1q_dup_f64( beta ); // Scale. vc_00 = vmulq_f64( vc_00, va_0 ); vc_02 = vmulq_f64( vc_02, va_0 ); vc_10 = vmulq_f64( vc_10, va_0 ); vc_12 = vmulq_f64( vc_12, va_0 ); vc_20 = vmulq_f64( vc_20, va_0 ); vc_22 = vmulq_f64( vc_22, va_0 ); if ( cs_c == 1 ) { // Row-storage. // if ( m0 > 0 ) { if ( n0 > 1 ) va_0 = vld1q_f64 ( c_loc + 0 * rs_c + 0 ); else if ( n0 > 0 ) va_0 = vld1q_lane_f64( c_loc + 0 * rs_c + 0, va_0, 0 ); if ( n0 > 3 ) va_1 = vld1q_f64 ( c_loc + 0 * rs_c + 2 ); else if ( n0 > 2 ) va_1 = vld1q_lane_f64( c_loc + 0 * rs_c + 2, va_1, 0 ); if ( !b_iszr ) { vc_00 = vfmaq_f64( vc_00, va_0, vb_0 ); vc_02 = vfmaq_f64( vc_02, va_1, vb_0 ); } if ( n0 > 1 ) vst1q_f64 ( c_loc + 0 * rs_c + 0, vc_00 ); else if ( n0 > 0 ) vst1q_lane_f64( c_loc + 0 * rs_c + 0, vc_00, 0 ); if ( n0 > 3 ) vst1q_f64 ( c_loc + 0 * rs_c + 2, vc_02 ); else if ( n0 > 2 ) vst1q_lane_f64( c_loc + 0 * rs_c + 2, vc_02, 0 ); } if ( m0 > 1 ) { if ( n0 > 1 ) va_0 = vld1q_f64 ( c_loc + 1 * rs_c + 0 ); else if ( n0 > 0 ) va_0 = vld1q_lane_f64( c_loc + 1 * rs_c + 0, va_0, 0 ); if ( n0 > 3 ) va_1 = vld1q_f64 ( c_loc + 1 * rs_c + 2 ); else if ( n0 > 2 ) va_1 = vld1q_lane_f64( c_loc + 1 * rs_c + 2, va_1, 0 ); if ( !b_iszr ) { vc_10 = vfmaq_f64( vc_10, va_0, vb_0 ); vc_12 = vfmaq_f64( vc_12, va_1, vb_0 ); } if ( n0 > 1 ) vst1q_f64 ( c_loc + 1 * rs_c + 0, vc_10 ); else if ( n0 > 0 ) vst1q_lane_f64( c_loc + 1 * rs_c + 0, vc_10, 0 ); if ( n0 > 3 ) vst1q_f64 ( c_loc + 1 * rs_c + 2, vc_12 ); else if ( n0 > 2 ) vst1q_lane_f64( c_loc + 1 * rs_c + 2, vc_12, 0 ); } if ( m0 > 2 ) { if ( n0 > 1 ) va_0 = vld1q_f64 ( c_loc + 2 * rs_c + 0 ); else if ( n0 > 0 ) va_0 = vld1q_lane_f64( c_loc + 2 * rs_c + 0, va_0, 0 ); if ( n0 > 3 ) va_1 = vld1q_f64 ( c_loc + 2 * rs_c + 2 ); else if ( n0 > 2 ) va_1 = vld1q_lane_f64( c_loc + 2 * rs_c + 2, va_1, 0 ); if ( !b_iszr ) { vc_20 = vfmaq_f64( vc_20, va_0, vb_0 ); vc_22 = vfmaq_f64( vc_22, va_1, vb_0 ); } if ( n0 > 1 ) vst1q_f64 ( c_loc + 2 * rs_c + 0, vc_20 ); else if ( n0 > 0 ) vst1q_lane_f64( c_loc + 2 * rs_c + 0, vc_20, 0 ); if ( n0 > 3 ) vst1q_f64 ( c_loc + 2 * rs_c + 2, vc_22 ); else if ( n0 > 2 ) vst1q_lane_f64( c_loc + 2 * rs_c + 2, vc_22, 0 ); } } else { // Column-storage. if ( m0 > 0 ) va_0 = vld1q_lane_f64( c_loc + 0 + 0 * cs_c, va_0, 0 ); if ( m0 > 1 ) va_1 = vld1q_lane_f64( c_loc + 1 + 0 * cs_c, va_1, 0 ); if ( m0 > 2 ) va_2 = vld1q_lane_f64( c_loc + 2 + 0 * cs_c, va_2, 0 ); if ( n0 > 1 ) { if ( m0 > 0 ) va_0 = vld1q_lane_f64( c_loc + 0 + 1 * cs_c, va_0, 1 ); if ( m0 > 1 ) va_1 = vld1q_lane_f64( c_loc + 1 + 1 * cs_c, va_1, 1 ); if ( m0 > 2 ) va_2 = vld1q_lane_f64( c_loc + 2 + 1 * cs_c, va_2, 1 ); } if ( !b_iszr ) { vc_00 = vfmaq_f64( vc_00, va_0, vb_0 ); vc_10 = vfmaq_f64( vc_10, va_1, vb_0 ); vc_20 = vfmaq_f64( vc_20, va_2, vb_0 ); } if ( m0 > 0 ) vst1q_lane_f64( c_loc + 0 + 0 * cs_c, vc_00, 0 ); if ( m0 > 1 ) vst1q_lane_f64( c_loc + 1 + 0 * cs_c, vc_10, 0 ); if ( m0 > 2 ) vst1q_lane_f64( c_loc + 2 + 0 * cs_c, vc_20, 0 ); if ( n0 > 1 ) { if ( m0 > 0 ) vst1q_lane_f64( c_loc + 0 + 1 * cs_c, vc_00, 1 ); if ( m0 > 1 ) vst1q_lane_f64( c_loc + 1 + 1 * cs_c, vc_10, 1 ); if ( m0 > 2 ) vst1q_lane_f64( c_loc + 2 + 1 * cs_c, vc_20, 1 ); } if ( n0 > 2 ) { if ( m0 > 0 ) va_0 = vld1q_lane_f64( c_loc + 0 + 2 * cs_c, va_0, 0 ); if ( m0 > 1 ) va_1 = vld1q_lane_f64( c_loc + 1 + 2 * cs_c, va_1, 0 ); if ( m0 > 2 ) va_2 = vld1q_lane_f64( c_loc + 2 + 2 * cs_c, va_2, 0 ); } if ( n0 > 3 ) { if ( m0 > 0 ) va_0 = vld1q_lane_f64( c_loc + 0 + 3 * cs_c, va_0, 1 ); if ( m0 > 1 ) va_1 = vld1q_lane_f64( c_loc + 1 + 3 * cs_c, va_1, 1 ); if ( m0 > 2 ) va_2 = vld1q_lane_f64( c_loc + 2 + 3 * cs_c, va_2, 1 ); } if ( !b_iszr ) { vc_02 = vfmaq_f64( vc_02, va_0, vb_0 ); vc_12 = vfmaq_f64( vc_12, va_1, vb_0 ); vc_22 = vfmaq_f64( vc_22, va_2, vb_0 ); } if ( n0 > 2 ) { if ( m0 > 0 ) vst1q_lane_f64( c_loc + 0 + 2 * cs_c, vc_02, 0 ); if ( m0 > 1 ) vst1q_lane_f64( c_loc + 1 + 2 * cs_c, vc_12, 0 ); if ( m0 > 2 ) vst1q_lane_f64( c_loc + 2 + 2 * cs_c, vc_22, 0 ); } if ( n0 > 3 ) { if ( m0 > 0 ) vst1q_lane_f64( c_loc + 0 + 3 * cs_c, vc_02, 1 ); if ( m0 > 1 ) vst1q_lane_f64( c_loc + 1 + 3 * cs_c, vc_12, 1 ); if ( m0 > 2 ) vst1q_lane_f64( c_loc + 2 + 3 * cs_c, vc_22, 1 ); } } } blis-0.9.0/kernels/armv8a/3/sup/d6x4/000077500000000000000000000000001422157504600170565ustar00rootroot00000000000000blis-0.9.0/kernels/armv8a/3/sup/d6x4/bli_gemmsup_rv_armv8a_int_d3x8mn.c000066400000000000000000000400511422157504600255650ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2021, The University of Tokyo 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // Supplimentary dynamic-size gemmsup. #include "blis.h" #include "assert.h" #include #if defined(__clang__) #define PRAGMA_NOUNROLL _Pragma("nounroll") #define PRAGMA_UNROLL _Pragma("unroll") #elif defined(__GNUC__) #define PRAGMA_NOUNROLL _Pragma("GCC unroll 1") #define PRAGMA_UNROLL _Pragma("GCC unroll 2") #else #define PRAGMA_NOUNROLL #define PRAGMA_UNROLL #endif /* * As these kernels requires num. of vregs about half of the total 32, * it should be all right to implement w/ intrinsics. * * c.f. https://www.youtube.com/watch?v=R2hQOVjRwVE . */ void bli_dgemmsup_rv_armv8a_int_3x8mn ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a0, inc_t rs_a, inc_t cs_a, double* restrict b0, inc_t rs_b, inc_t cs_b, double* restrict beta, double* restrict c0, inc_t rs_c, inc_t cs_c, auxinfo_t* restrict data, cntx_t* restrict cntx ) { // Unlike the rd case, this rv case does not impose restriction upon // maximal m & n. double *a_loc; double *b_loc, *b_in; double *c_loc, *c_in; dim_t n; dim_t k; uint64_t ps_a = bli_auxinfo_ps_a( data ); uint64_t ps_b = bli_auxinfo_ps_b( data ); uint64_t b_iszr = ( *beta == 0.0 ); assert( cs_b == 1 ); // Registers used to store a 3x8 block of C. float64x2_t vc_00, vc_01, vc_02, vc_03; float64x2_t vc_10, vc_11, vc_12, vc_13; float64x2_t vc_20, vc_21, vc_22, vc_23; float64x2_t va_0, va_1; float64x2_t vb_0, vb_1, vb_2, vb_3; PRAGMA_NOUNROLL for ( ; m0 > 0; m0 -= 3 ) { n = n0; b_in = b0; c_in = c0; PRAGMA_NOUNROLL for ( ; n > 0; n -= 8 ) { a_loc = a0; b_loc = b_in; c_loc = c_in; k = k0; vc_00 = (float64x2_t)vdupq_n_f64( 0 ); vc_01 = (float64x2_t)vdupq_n_f64( 0 ); vc_02 = (float64x2_t)vdupq_n_f64( 0 ); vc_03 = (float64x2_t)vdupq_n_f64( 0 ); vc_10 = (float64x2_t)vdupq_n_f64( 0 ); vc_11 = (float64x2_t)vdupq_n_f64( 0 ); vc_12 = (float64x2_t)vdupq_n_f64( 0 ); vc_13 = (float64x2_t)vdupq_n_f64( 0 ); vc_20 = (float64x2_t)vdupq_n_f64( 0 ); vc_21 = (float64x2_t)vdupq_n_f64( 0 ); vc_22 = (float64x2_t)vdupq_n_f64( 0 ); vc_23 = (float64x2_t)vdupq_n_f64( 0 ); PRAGMA_UNROLL for ( ; k > 0; --k ) { // A columns. // if ( m0 > 0 ) va_0 = vld1q_lane_f64( a_loc + rs_a * 0, va_0, 0 ); if ( m0 > 1 ) va_0 = vld1q_lane_f64( a_loc + rs_a * 1, va_0, 1 ); if ( m0 > 2 ) va_1 = vld1q_lane_f64( a_loc + rs_a * 2, va_1, 0 ); // B rows. if ( n > 1 ) vb_0 = vld1q_f64 ( b_loc + 0 ); else vb_0 = vld1q_lane_f64( b_loc + 0, vb_0, 0 ); if ( n > 3 ) vb_1 = vld1q_f64 ( b_loc + 2 ); else if ( n > 2 ) vb_1 = vld1q_lane_f64( b_loc + 2, vb_1, 0 ); if ( n > 5 ) vb_2 = vld1q_f64 ( b_loc + 4 ); else if ( n > 4 ) vb_2 = vld1q_lane_f64( b_loc + 4, vb_2, 0 ); if ( n > 7 ) vb_3 = vld1q_f64 ( b_loc + 6 ); else if ( n > 6 ) vb_3 = vld1q_lane_f64( b_loc + 6, vb_3, 0 ); a_loc += cs_a; b_loc += rs_b; // if ( m0 > 0 ) { vc_00 = vfmaq_laneq_f64( vc_00, vb_0, va_0, 0 ); vc_01 = vfmaq_laneq_f64( vc_01, vb_1, va_0, 0 ); vc_02 = vfmaq_laneq_f64( vc_02, vb_2, va_0, 0 ); vc_03 = vfmaq_laneq_f64( vc_03, vb_3, va_0, 0 ); } if ( m0 > 1 ) { vc_10 = vfmaq_laneq_f64( vc_10, vb_0, va_0, 1 ); vc_11 = vfmaq_laneq_f64( vc_11, vb_1, va_0, 1 ); vc_12 = vfmaq_laneq_f64( vc_12, vb_2, va_0, 1 ); vc_13 = vfmaq_laneq_f64( vc_13, vb_3, va_0, 1 ); } if ( m0 > 2 ) { vc_20 = vfmaq_laneq_f64( vc_20, vb_0, va_1, 0 ); vc_21 = vfmaq_laneq_f64( vc_21, vb_1, va_1, 0 ); vc_22 = vfmaq_laneq_f64( vc_22, vb_2, va_1, 0 ); vc_23 = vfmaq_laneq_f64( vc_23, vb_3, va_1, 0 ); } } // Load alpha and beta. // Note that here vb is used for alpha, in contrast to other kernels. vb_0 = vld1q_dup_f64( alpha ); va_0 = vld1q_dup_f64( beta ); // Scale. vc_00 = vmulq_f64( vc_00, vb_0 ); vc_01 = vmulq_f64( vc_01, vb_0 ); vc_02 = vmulq_f64( vc_02, vb_0 ); vc_03 = vmulq_f64( vc_03, vb_0 ); vc_10 = vmulq_f64( vc_10, vb_0 ); vc_11 = vmulq_f64( vc_11, vb_0 ); vc_12 = vmulq_f64( vc_12, vb_0 ); vc_13 = vmulq_f64( vc_13, vb_0 ); vc_20 = vmulq_f64( vc_20, vb_0 ); vc_21 = vmulq_f64( vc_21, vb_0 ); vc_22 = vmulq_f64( vc_22, vb_0 ); vc_23 = vmulq_f64( vc_23, vb_0 ); if ( cs_c == 1 ) { // Store in rows. // // if ( m0 > 0 ) { // Load. if ( n > 1 ) vb_0 = vld1q_f64 ( c_loc + 0 * rs_c + 0 ); else vb_0 = vld1q_lane_f64( c_loc + 0 * rs_c + 0, vb_0, 0 ); if ( n > 3 ) vb_1 = vld1q_f64 ( c_loc + 0 * rs_c + 2 ); else if ( n > 2 ) vb_1 = vld1q_lane_f64( c_loc + 0 * rs_c + 2, vb_1, 0 ); if ( n > 5 ) vb_2 = vld1q_f64 ( c_loc + 0 * rs_c + 4 ); else if ( n > 4 ) vb_2 = vld1q_lane_f64( c_loc + 0 * rs_c + 4, vb_2, 0 ); if ( n > 7 ) vb_3 = vld1q_f64 ( c_loc + 0 * rs_c + 6 ); else if ( n > 6 ) vb_3 = vld1q_lane_f64( c_loc + 0 * rs_c + 6, vb_3, 0 ); // Scale. if ( !b_iszr ) { vc_00 = vfmaq_f64( vc_00, vb_0, va_0 ); vc_01 = vfmaq_f64( vc_01, vb_1, va_0 ); vc_02 = vfmaq_f64( vc_02, vb_2, va_0 ); vc_03 = vfmaq_f64( vc_03, vb_3, va_0 ); } // Store. if ( n > 1 ) vst1q_f64 ( c_loc + 0 * rs_c + 0, vc_00 ); else vst1q_lane_f64( c_loc + 0 * rs_c + 0, vc_00, 0 ); if ( n > 3 ) vst1q_f64 ( c_loc + 0 * rs_c + 2, vc_01 ); else if ( n > 2 ) vst1q_lane_f64( c_loc + 0 * rs_c + 2, vc_01, 0 ); if ( n > 5 ) vst1q_f64 ( c_loc + 0 * rs_c + 4, vc_02 ); else if ( n > 4 ) vst1q_lane_f64( c_loc + 0 * rs_c + 4, vc_02, 0 ); if ( n > 7 ) vst1q_f64 ( c_loc + 0 * rs_c + 6, vc_03 ); else if ( n > 6 ) vst1q_lane_f64( c_loc + 0 * rs_c + 6, vc_03, 0 ); } if ( m0 > 1 ) { // Load. if ( n > 1 ) vb_0 = vld1q_f64 ( c_loc + 1 * rs_c + 0 ); else vb_0 = vld1q_lane_f64( c_loc + 1 * rs_c + 0, vb_0, 0 ); if ( n > 3 ) vb_1 = vld1q_f64 ( c_loc + 1 * rs_c + 2 ); else if ( n > 2 ) vb_1 = vld1q_lane_f64( c_loc + 1 * rs_c + 2, vb_1, 0 ); if ( n > 5 ) vb_2 = vld1q_f64 ( c_loc + 1 * rs_c + 4 ); else if ( n > 4 ) vb_2 = vld1q_lane_f64( c_loc + 1 * rs_c + 4, vb_2, 0 ); if ( n > 7 ) vb_3 = vld1q_f64 ( c_loc + 1 * rs_c + 6 ); else if ( n > 6 ) vb_3 = vld1q_lane_f64( c_loc + 1 * rs_c + 6, vb_3, 0 ); // Scale. if ( !b_iszr ) { vc_10 = vfmaq_f64( vc_10, vb_0, va_0 ); vc_11 = vfmaq_f64( vc_11, vb_1, va_0 ); vc_12 = vfmaq_f64( vc_12, vb_2, va_0 ); vc_13 = vfmaq_f64( vc_13, vb_3, va_0 ); } // Store. if ( n > 1 ) vst1q_f64 ( c_loc + 1 * rs_c + 0, vc_10 ); else vst1q_lane_f64( c_loc + 1 * rs_c + 0, vc_10, 0 ); if ( n > 3 ) vst1q_f64 ( c_loc + 1 * rs_c + 2, vc_11 ); else if ( n > 2 ) vst1q_lane_f64( c_loc + 1 * rs_c + 2, vc_11, 0 ); if ( n > 5 ) vst1q_f64 ( c_loc + 1 * rs_c + 4, vc_12 ); else if ( n > 4 ) vst1q_lane_f64( c_loc + 1 * rs_c + 4, vc_12, 0 ); if ( n > 7 ) vst1q_f64 ( c_loc + 1 * rs_c + 6, vc_13 ); else if ( n > 6 ) vst1q_lane_f64( c_loc + 1 * rs_c + 6, vc_13, 0 ); } if ( m0 > 2 ) { // Load. if ( n > 1 ) vb_0 = vld1q_f64 ( c_loc + 2 * rs_c + 0 ); else vb_0 = vld1q_lane_f64( c_loc + 2 * rs_c + 0, vb_0, 0 ); if ( n > 3 ) vb_1 = vld1q_f64 ( c_loc + 2 * rs_c + 2 ); else if ( n > 2 ) vb_1 = vld1q_lane_f64( c_loc + 2 * rs_c + 2, vb_1, 0 ); if ( n > 5 ) vb_2 = vld1q_f64 ( c_loc + 2 * rs_c + 4 ); else if ( n > 4 ) vb_2 = vld1q_lane_f64( c_loc + 2 * rs_c + 4, vb_2, 0 ); if ( n > 7 ) vb_3 = vld1q_f64 ( c_loc + 2 * rs_c + 6 ); else if ( n > 6 ) vb_3 = vld1q_lane_f64( c_loc + 2 * rs_c + 6, vb_3, 0 ); // Scale. if ( !b_iszr ) { vc_20 = vfmaq_f64( vc_20, vb_0, va_0 ); vc_21 = vfmaq_f64( vc_21, vb_1, va_0 ); vc_22 = vfmaq_f64( vc_22, vb_2, va_0 ); vc_23 = vfmaq_f64( vc_23, vb_3, va_0 ); } // Store. if ( n > 1 ) vst1q_f64 ( c_loc + 2 * rs_c + 0, vc_20 ); else vst1q_lane_f64( c_loc + 2 * rs_c + 0, vc_20, 0 ); if ( n > 3 ) vst1q_f64 ( c_loc + 2 * rs_c + 2, vc_21 ); else if ( n > 2 ) vst1q_lane_f64( c_loc + 2 * rs_c + 2, vc_21, 0 ); if ( n > 5 ) vst1q_f64 ( c_loc + 2 * rs_c + 4, vc_22 ); else if ( n > 4 ) vst1q_lane_f64( c_loc + 2 * rs_c + 4, vc_22, 0 ); if ( n > 7 ) vst1q_f64 ( c_loc + 2 * rs_c + 6, vc_23 ); else if ( n > 6 ) vst1q_lane_f64( c_loc + 2 * rs_c + 6, vc_23, 0 ); } } else { // Store in columns. // No in-reg transpose here. // // if ( m0 > 0 ) { // Load. if ( n > 0 ) vb_0 = vld1q_lane_f64( c_loc + 0 + 0 * cs_c, vb_0, 0 ); if ( n > 1 ) vb_0 = vld1q_lane_f64( c_loc + 0 + 1 * cs_c, vb_0, 1 ); if ( n > 2 ) vb_1 = vld1q_lane_f64( c_loc + 0 + 2 * cs_c, vb_1, 0 ); if ( n > 3 ) vb_1 = vld1q_lane_f64( c_loc + 0 + 3 * cs_c, vb_1, 1 ); if ( n > 4 ) vb_2 = vld1q_lane_f64( c_loc + 0 + 4 * cs_c, vb_2, 0 ); if ( n > 5 ) vb_2 = vld1q_lane_f64( c_loc + 0 + 5 * cs_c, vb_2, 1 ); if ( n > 6 ) vb_3 = vld1q_lane_f64( c_loc + 0 + 6 * cs_c, vb_3, 0 ); if ( n > 7 ) vb_3 = vld1q_lane_f64( c_loc + 0 + 7 * cs_c, vb_3, 1 ); // Scale. if ( !b_iszr ) { vc_00 = vfmaq_f64( vc_00, vb_0, va_0 ); vc_01 = vfmaq_f64( vc_01, vb_1, va_0 ); vc_02 = vfmaq_f64( vc_02, vb_2, va_0 ); vc_03 = vfmaq_f64( vc_03, vb_3, va_0 ); } // Store. if ( n > 0 ) vst1q_lane_f64( c_loc + 0 + 0 * cs_c, vc_00, 0 ); if ( n > 1 ) vst1q_lane_f64( c_loc + 0 + 1 * cs_c, vc_00, 1 ); if ( n > 2 ) vst1q_lane_f64( c_loc + 0 + 2 * cs_c, vc_01, 0 ); if ( n > 3 ) vst1q_lane_f64( c_loc + 0 + 3 * cs_c, vc_01, 1 ); if ( n > 4 ) vst1q_lane_f64( c_loc + 0 + 4 * cs_c, vc_02, 0 ); if ( n > 5 ) vst1q_lane_f64( c_loc + 0 + 5 * cs_c, vc_02, 1 ); if ( n > 6 ) vst1q_lane_f64( c_loc + 0 + 6 * cs_c, vc_03, 0 ); if ( n > 7 ) vst1q_lane_f64( c_loc + 0 + 7 * cs_c, vc_03, 1 ); } if ( m0 > 1 ) { // Load. if ( n > 0 ) vb_0 = vld1q_lane_f64( c_loc + 1 + 0 * cs_c, vb_0, 0 ); if ( n > 1 ) vb_0 = vld1q_lane_f64( c_loc + 1 + 1 * cs_c, vb_0, 1 ); if ( n > 2 ) vb_1 = vld1q_lane_f64( c_loc + 1 + 2 * cs_c, vb_1, 0 ); if ( n > 3 ) vb_1 = vld1q_lane_f64( c_loc + 1 + 3 * cs_c, vb_1, 1 ); if ( n > 4 ) vb_2 = vld1q_lane_f64( c_loc + 1 + 4 * cs_c, vb_2, 0 ); if ( n > 5 ) vb_2 = vld1q_lane_f64( c_loc + 1 + 5 * cs_c, vb_2, 1 ); if ( n > 6 ) vb_3 = vld1q_lane_f64( c_loc + 1 + 6 * cs_c, vb_3, 0 ); if ( n > 7 ) vb_3 = vld1q_lane_f64( c_loc + 1 + 7 * cs_c, vb_3, 1 ); // Scale. if ( !b_iszr ) { vc_10 = vfmaq_f64( vc_10, vb_0, va_0 ); vc_11 = vfmaq_f64( vc_11, vb_1, va_0 ); vc_12 = vfmaq_f64( vc_12, vb_2, va_0 ); vc_13 = vfmaq_f64( vc_13, vb_3, va_0 ); } // Store. if ( n > 0 ) vst1q_lane_f64( c_loc + 1 + 0 * cs_c, vc_10, 0 ); if ( n > 1 ) vst1q_lane_f64( c_loc + 1 + 1 * cs_c, vc_10, 1 ); if ( n > 2 ) vst1q_lane_f64( c_loc + 1 + 2 * cs_c, vc_11, 0 ); if ( n > 3 ) vst1q_lane_f64( c_loc + 1 + 3 * cs_c, vc_11, 1 ); if ( n > 4 ) vst1q_lane_f64( c_loc + 1 + 4 * cs_c, vc_12, 0 ); if ( n > 5 ) vst1q_lane_f64( c_loc + 1 + 5 * cs_c, vc_12, 1 ); if ( n > 6 ) vst1q_lane_f64( c_loc + 1 + 6 * cs_c, vc_13, 0 ); if ( n > 7 ) vst1q_lane_f64( c_loc + 1 + 7 * cs_c, vc_13, 1 ); } if ( m0 > 2 ) { // Load. if ( n > 0 ) vb_0 = vld1q_lane_f64( c_loc + 2 + 0 * cs_c, vb_0, 0 ); if ( n > 1 ) vb_0 = vld1q_lane_f64( c_loc + 2 + 1 * cs_c, vb_0, 1 ); if ( n > 2 ) vb_1 = vld1q_lane_f64( c_loc + 2 + 2 * cs_c, vb_1, 0 ); if ( n > 3 ) vb_1 = vld1q_lane_f64( c_loc + 2 + 3 * cs_c, vb_1, 1 ); if ( n > 4 ) vb_2 = vld1q_lane_f64( c_loc + 2 + 4 * cs_c, vb_2, 0 ); if ( n > 5 ) vb_2 = vld1q_lane_f64( c_loc + 2 + 5 * cs_c, vb_2, 1 ); if ( n > 6 ) vb_3 = vld1q_lane_f64( c_loc + 2 + 6 * cs_c, vb_3, 0 ); if ( n > 7 ) vb_3 = vld1q_lane_f64( c_loc + 2 + 7 * cs_c, vb_3, 1 ); // Scale. if ( !b_iszr ) { vc_20 = vfmaq_f64( vc_20, vb_0, va_0 ); vc_21 = vfmaq_f64( vc_21, vb_1, va_0 ); vc_22 = vfmaq_f64( vc_22, vb_2, va_0 ); vc_23 = vfmaq_f64( vc_23, vb_3, va_0 ); } // Store. if ( n > 0 ) vst1q_lane_f64( c_loc + 2 + 0 * cs_c, vc_20, 0 ); if ( n > 1 ) vst1q_lane_f64( c_loc + 2 + 1 * cs_c, vc_20, 1 ); if ( n > 2 ) vst1q_lane_f64( c_loc + 2 + 2 * cs_c, vc_21, 0 ); if ( n > 3 ) vst1q_lane_f64( c_loc + 2 + 3 * cs_c, vc_21, 1 ); if ( n > 4 ) vst1q_lane_f64( c_loc + 2 + 4 * cs_c, vc_22, 0 ); if ( n > 5 ) vst1q_lane_f64( c_loc + 2 + 5 * cs_c, vc_22, 1 ); if ( n > 6 ) vst1q_lane_f64( c_loc + 2 + 6 * cs_c, vc_23, 0 ); if ( n > 7 ) vst1q_lane_f64( c_loc + 2 + 7 * cs_c, vc_23, 1 ); } } b_in += ps_b; c_in += 8 * cs_c; } a0 += ps_a; c0 += 3 * rs_c; } } blis-0.9.0/kernels/armv8a/3/sup/d6x4/bli_gemmsup_rv_armv8a_int_d6x4mn.c000066400000000000000000000447151422157504600255770ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2021, The University of Tokyo 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // Supplimentary dynamic-size gemmsup. #include "blis.h" #include "assert.h" #include #if defined(__clang__) #define PRAGMA_NOUNROLL _Pragma("nounroll") #define PRAGMA_UNROLL _Pragma("unroll") #elif defined(__GNUC__) #define PRAGMA_NOUNROLL _Pragma("GCC unroll 1") #define PRAGMA_UNROLL _Pragma("GCC unroll 2") #else #define PRAGMA_NOUNROLL #define PRAGMA_UNROLL #endif /* * As these kernels requires num. of vregs about half of the total 32, * it should be all right to implement w/ intrinsics. * * c.f. https://www.youtube.com/watch?v=R2hQOVjRwVE . */ void bli_dgemmsup_rv_armv8a_int_6x4mn ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a0, inc_t rs_a, inc_t cs_a, double* restrict b0, inc_t rs_b, inc_t cs_b, double* restrict beta, double* restrict c0, inc_t rs_c, inc_t cs_c, auxinfo_t* restrict data, cntx_t* restrict cntx ) { // Unlike the rd case, this rv case does not impose restriction upon // maximal m & n. double *a_loc; double *b_loc, *b_in; double *c_loc, *c_in; dim_t n; dim_t k; uint64_t ps_a = bli_auxinfo_ps_a( data ); uint64_t ps_b = bli_auxinfo_ps_b( data ); uint64_t b_iszr = ( *beta == 0.0 ); assert( cs_b == 1 ); // Registers used to store a 6x4 block of C. float64x2_t vc_00, vc_01; float64x2_t vc_10, vc_11; float64x2_t vc_20, vc_21; float64x2_t vc_30, vc_31; float64x2_t vc_40, vc_41; float64x2_t vc_50, vc_51; float64x2_t va_0, va_1, va_2; float64x2_t vb_0, vb_1; PRAGMA_NOUNROLL for ( ; m0 > 0; m0 -= 6 ) { n = n0; b_in = b0; c_in = c0; PRAGMA_NOUNROLL for ( ; n > 0; n -= 4 ) { a_loc = a0; b_loc = b_in; c_loc = c_in; k = k0; vc_00 = (float64x2_t)vdupq_n_f64( 0 ); vc_01 = (float64x2_t)vdupq_n_f64( 0 ); vc_10 = (float64x2_t)vdupq_n_f64( 0 ); vc_11 = (float64x2_t)vdupq_n_f64( 0 ); vc_20 = (float64x2_t)vdupq_n_f64( 0 ); vc_21 = (float64x2_t)vdupq_n_f64( 0 ); vc_30 = (float64x2_t)vdupq_n_f64( 0 ); vc_31 = (float64x2_t)vdupq_n_f64( 0 ); vc_40 = (float64x2_t)vdupq_n_f64( 0 ); vc_41 = (float64x2_t)vdupq_n_f64( 0 ); vc_50 = (float64x2_t)vdupq_n_f64( 0 ); vc_51 = (float64x2_t)vdupq_n_f64( 0 ); PRAGMA_UNROLL for ( ; k > 0; --k ) { // A columns. // if ( m0 > 0 ) va_0 = vld1q_lane_f64( a_loc + rs_a * 0, va_0, 0 ); if ( m0 > 1 ) va_0 = vld1q_lane_f64( a_loc + rs_a * 1, va_0, 1 ); if ( m0 > 2 ) va_1 = vld1q_lane_f64( a_loc + rs_a * 2, va_1, 0 ); if ( m0 > 3 ) va_1 = vld1q_lane_f64( a_loc + rs_a * 3, va_1, 1 ); if ( m0 > 4 ) va_2 = vld1q_lane_f64( a_loc + rs_a * 4, va_2, 0 ); if ( m0 > 5 ) va_2 = vld1q_lane_f64( a_loc + rs_a * 5, va_2, 1 ); // B rows. if ( n > 1 ) vb_0 = vld1q_f64 ( b_loc + 0 ); else vb_0 = vld1q_lane_f64( b_loc + 0, vb_0, 0 ); if ( n > 3 ) vb_1 = vld1q_f64 ( b_loc + 2 ); else if ( n > 2 ) vb_1 = vld1q_lane_f64( b_loc + 2, vb_1, 0 ); a_loc += cs_a; b_loc += rs_b; // One or two-column case. if ( n <= 2 ) { // if ( m0 > 0 ) { vc_00 = vfmaq_laneq_f64( vc_00, vb_0, va_0, 0 ); vc_10 = vfmaq_laneq_f64( vc_10, vb_0, va_0, 1 ); vc_20 = vfmaq_laneq_f64( vc_20, vb_0, va_1, 0 ); } if ( m0 > 3 ) { vc_30 = vfmaq_laneq_f64( vc_30, vb_0, va_1, 1 ); vc_40 = vfmaq_laneq_f64( vc_40, vb_0, va_2, 0 ); vc_50 = vfmaq_laneq_f64( vc_50, vb_0, va_2, 1 ); } continue; } // Three or four-column case. Moderately decrease num. of FMLA instructions // according to m and n. // if ( m0 > 0 ) { vc_00 = vfmaq_laneq_f64( vc_00, vb_0, va_0, 0 ); vc_01 = vfmaq_laneq_f64( vc_01, vb_1, va_0, 0 ); vc_10 = vfmaq_laneq_f64( vc_10, vb_0, va_0, 1 ); vc_11 = vfmaq_laneq_f64( vc_11, vb_1, va_0, 1 ); } if ( m0 > 2 ) { vc_20 = vfmaq_laneq_f64( vc_20, vb_0, va_1, 0 ); vc_21 = vfmaq_laneq_f64( vc_21, vb_1, va_1, 0 ); vc_30 = vfmaq_laneq_f64( vc_30, vb_0, va_1, 1 ); vc_31 = vfmaq_laneq_f64( vc_31, vb_1, va_1, 1 ); } if ( m0 > 4 ) { vc_40 = vfmaq_laneq_f64( vc_40, vb_0, va_2, 0 ); vc_41 = vfmaq_laneq_f64( vc_41, vb_1, va_2, 0 ); vc_50 = vfmaq_laneq_f64( vc_50, vb_0, va_2, 1 ); vc_51 = vfmaq_laneq_f64( vc_51, vb_1, va_2, 1 ); } } // Load alpha and beta. va_0 = vld1q_dup_f64( alpha ); vb_0 = vld1q_dup_f64( beta ); // Scale. vc_00 = vmulq_f64( vc_00, va_0 ); vc_01 = vmulq_f64( vc_01, va_0 ); vc_10 = vmulq_f64( vc_10, va_0 ); vc_11 = vmulq_f64( vc_11, va_0 ); vc_20 = vmulq_f64( vc_20, va_0 ); vc_21 = vmulq_f64( vc_21, va_0 ); vc_30 = vmulq_f64( vc_30, va_0 ); vc_31 = vmulq_f64( vc_31, va_0 ); vc_40 = vmulq_f64( vc_40, va_0 ); vc_41 = vmulq_f64( vc_41, va_0 ); vc_50 = vmulq_f64( vc_50, va_0 ); vc_51 = vmulq_f64( vc_51, va_0 ); if ( cs_c == 1 ) { // Store in rows. // if ( m0 > 0 ) { // Load. if ( n > 1 ) va_0 = vld1q_f64 ( c_loc + 0 * rs_c + 0 ); else va_0 = vld1q_lane_f64( c_loc + 0 * rs_c + 0, va_0, 0 ); if ( n > 3 ) va_1 = vld1q_f64 ( c_loc + 0 * rs_c + 2 ); else if ( n > 2 ) va_1 = vld1q_lane_f64( c_loc + 0 * rs_c + 2, va_1, 0 ); // Scale. if ( !b_iszr ) { vc_00 = vfmaq_f64( vc_00, va_0, vb_0 ); vc_01 = vfmaq_f64( vc_01, va_1, vb_0 ); } // Store. if ( n > 1 ) vst1q_f64 ( c_loc + 0 * rs_c + 0, vc_00 ); else vst1q_lane_f64( c_loc + 0 * rs_c + 0, vc_00, 0 ); if ( n > 3 ) vst1q_f64 ( c_loc + 0 * rs_c + 2, vc_01 ); else if ( n > 2 ) vst1q_lane_f64( c_loc + 0 * rs_c + 2, vc_01, 0 ); } if ( m0 > 1 ) { // Load. if ( n > 1 ) va_0 = vld1q_f64 ( c_loc + 1 * rs_c + 0 ); else va_0 = vld1q_lane_f64( c_loc + 1 * rs_c + 0, va_0, 0 ); if ( n > 3 ) va_1 = vld1q_f64 ( c_loc + 1 * rs_c + 2 ); else if ( n > 2 ) va_1 = vld1q_lane_f64( c_loc + 1 * rs_c + 2, va_1, 0 ); // Scale. if ( !b_iszr ) { vc_10 = vfmaq_f64( vc_10, va_0, vb_0 ); vc_11 = vfmaq_f64( vc_11, va_1, vb_0 ); } // Store. if ( n > 1 ) vst1q_f64 ( c_loc + 1 * rs_c + 0, vc_10 ); else vst1q_lane_f64( c_loc + 1 * rs_c + 0, vc_10, 0 ); if ( n > 3 ) vst1q_f64 ( c_loc + 1 * rs_c + 2, vc_11 ); else if ( n > 2 ) vst1q_lane_f64( c_loc + 1 * rs_c + 2, vc_11, 0 ); } if ( m0 > 2 ) { // Load. if ( n > 1 ) va_0 = vld1q_f64 ( c_loc + 2 * rs_c + 0 ); else va_0 = vld1q_lane_f64( c_loc + 2 * rs_c + 0, va_0, 0 ); if ( n > 3 ) va_1 = vld1q_f64 ( c_loc + 2 * rs_c + 2 ); else if ( n > 2 ) va_1 = vld1q_lane_f64( c_loc + 2 * rs_c + 2, va_1, 0 ); // Scale. if ( !b_iszr ) { vc_20 = vfmaq_f64( vc_20, va_0, vb_0 ); vc_21 = vfmaq_f64( vc_21, va_1, vb_0 ); } // Store. if ( n > 1 ) vst1q_f64 ( c_loc + 2 * rs_c + 0, vc_20 ); else vst1q_lane_f64( c_loc + 2 * rs_c + 0, vc_20, 0 ); if ( n > 3 ) vst1q_f64 ( c_loc + 2 * rs_c + 2, vc_21 ); else if ( n > 2 ) vst1q_lane_f64( c_loc + 2 * rs_c + 2, vc_21, 0 ); } if ( m0 > 3 ) { // Load. if ( n > 1 ) va_0 = vld1q_f64 ( c_loc + 3 * rs_c + 0 ); else va_0 = vld1q_lane_f64( c_loc + 3 * rs_c + 0, va_0, 0 ); if ( n > 3 ) va_1 = vld1q_f64 ( c_loc + 3 * rs_c + 2 ); else if ( n > 2 ) va_1 = vld1q_lane_f64( c_loc + 3 * rs_c + 2, va_1, 0 ); // Scale. if ( !b_iszr ) { vc_30 = vfmaq_f64( vc_30, va_0, vb_0 ); vc_31 = vfmaq_f64( vc_31, va_1, vb_0 ); } // Store. if ( n > 1 ) vst1q_f64 ( c_loc + 3 * rs_c + 0, vc_30 ); else vst1q_lane_f64( c_loc + 3 * rs_c + 0, vc_30, 0 ); if ( n > 3 ) vst1q_f64 ( c_loc + 3 * rs_c + 2, vc_31 ); else if ( n > 2 ) vst1q_lane_f64( c_loc + 3 * rs_c + 2, vc_31, 0 ); } if ( m0 > 4 ) { // Load. if ( n > 1 ) va_0 = vld1q_f64 ( c_loc + 4 * rs_c + 0 ); else va_0 = vld1q_lane_f64( c_loc + 4 * rs_c + 0, va_0, 0 ); if ( n > 3 ) va_1 = vld1q_f64 ( c_loc + 4 * rs_c + 2 ); else if ( n > 2 ) va_1 = vld1q_lane_f64( c_loc + 4 * rs_c + 2, va_1, 0 ); // Scale. if ( !b_iszr ) { vc_40 = vfmaq_f64( vc_40, va_0, vb_0 ); vc_41 = vfmaq_f64( vc_41, va_1, vb_0 ); } // Store. if ( n > 1 ) vst1q_f64 ( c_loc + 4 * rs_c + 0, vc_40 ); else vst1q_lane_f64( c_loc + 4 * rs_c + 0, vc_40, 0 ); if ( n > 3 ) vst1q_f64 ( c_loc + 4 * rs_c + 2, vc_41 ); else if ( n > 2 ) vst1q_lane_f64( c_loc + 4 * rs_c + 2, vc_41, 0 ); } if ( m0 > 5 ) { // Load. if ( n > 1 ) va_0 = vld1q_f64 ( c_loc + 5 * rs_c + 0 ); else va_0 = vld1q_lane_f64( c_loc + 5 * rs_c + 0, va_0, 0 ); if ( n > 3 ) va_1 = vld1q_f64 ( c_loc + 5 * rs_c + 2 ); else if ( n > 2 ) va_1 = vld1q_lane_f64( c_loc + 5 * rs_c + 2, va_1, 0 ); // Scale. if ( !b_iszr ) { vc_50 = vfmaq_f64( vc_50, va_0, vb_0 ); vc_51 = vfmaq_f64( vc_51, va_1, vb_0 ); } // Store. if ( n > 1 ) vst1q_f64 ( c_loc + 5 * rs_c + 0, vc_50 ); else vst1q_lane_f64( c_loc + 5 * rs_c + 0, vc_50, 0 ); if ( n > 3 ) vst1q_f64 ( c_loc + 5 * rs_c + 2, vc_51 ); else if ( n > 2 ) vst1q_lane_f64( c_loc + 5 * rs_c + 2, vc_51, 0 ); } } else { // Store in columns. // Rename some vectors. #define VCOL0 va_0 #define VCOL1 va_1 #define VCOL2 va_2 #define VCOL3 vb_1 #define VTMP0 vc_00 #define VTMP1 vc_01 #define VTMP2 vc_10 #define VTMP3 vc_11 // if ( m0 > 0 ) { VCOL0 = vtrn1q_f64(vc_00, vc_10); VCOL1 = vtrn2q_f64(vc_00, vc_10); VCOL2 = vtrn1q_f64(vc_01, vc_11); VCOL3 = vtrn2q_f64(vc_01, vc_11); if ( m0 > 1 ) { if ( n > 0 ) VTMP0 = vld1q_f64( c_loc + 0 * cs_c + 0 ); if ( n > 1 ) VTMP1 = vld1q_f64( c_loc + 1 * cs_c + 0 ); if ( n > 2 ) VTMP2 = vld1q_f64( c_loc + 2 * cs_c + 0 ); if ( n > 3 ) VTMP3 = vld1q_f64( c_loc + 3 * cs_c + 0 ); if ( !b_iszr ) { VCOL0 = vfmaq_f64( VCOL0, VTMP0, vb_0 ); VCOL1 = vfmaq_f64( VCOL1, VTMP1, vb_0 ); VCOL2 = vfmaq_f64( VCOL2, VTMP2, vb_0 ); VCOL3 = vfmaq_f64( VCOL3, VTMP3, vb_0 ); } if ( n > 0 ) vst1q_f64( c_loc + 0 * cs_c + 0, VCOL0 ); if ( n > 1 ) vst1q_f64( c_loc + 1 * cs_c + 0, VCOL1 ); if ( n > 2 ) vst1q_f64( c_loc + 2 * cs_c + 0, VCOL2 ); if ( n > 3 ) vst1q_f64( c_loc + 3 * cs_c + 0, VCOL3 ); } else { if ( n > 0 ) VTMP0 = vld1q_lane_f64( c_loc + 0 * cs_c + 0, VTMP0, 0 ); if ( n > 1 ) VTMP1 = vld1q_lane_f64( c_loc + 1 * cs_c + 0, VTMP1, 0 ); if ( n > 2 ) VTMP2 = vld1q_lane_f64( c_loc + 2 * cs_c + 0, VTMP2, 0 ); if ( n > 3 ) VTMP3 = vld1q_lane_f64( c_loc + 3 * cs_c + 0, VTMP3, 0 ); if ( !b_iszr ) { VCOL0 = vfmaq_f64( VCOL0, VTMP0, vb_0 ); VCOL1 = vfmaq_f64( VCOL1, VTMP1, vb_0 ); VCOL2 = vfmaq_f64( VCOL2, VTMP2, vb_0 ); VCOL3 = vfmaq_f64( VCOL3, VTMP3, vb_0 ); } if ( n > 0 ) vst1q_lane_f64( c_loc + 0 * cs_c + 0, VCOL0, 0 ); if ( n > 1 ) vst1q_lane_f64( c_loc + 1 * cs_c + 0, VCOL1, 0 ); if ( n > 2 ) vst1q_lane_f64( c_loc + 2 * cs_c + 0, VCOL2, 0 ); if ( n > 3 ) vst1q_lane_f64( c_loc + 3 * cs_c + 0, VCOL3, 0 ); } } if ( m0 > 2 ) { VCOL0 = vtrn1q_f64(vc_20, vc_30); VCOL1 = vtrn2q_f64(vc_20, vc_30); VCOL2 = vtrn1q_f64(vc_21, vc_31); VCOL3 = vtrn2q_f64(vc_21, vc_31); if ( m0 > 3 ) { if ( n > 0 ) VTMP0 = vld1q_f64( c_loc + 0 * cs_c + 2 ); if ( n > 1 ) VTMP1 = vld1q_f64( c_loc + 1 * cs_c + 2 ); if ( n > 2 ) VTMP2 = vld1q_f64( c_loc + 2 * cs_c + 2 ); if ( n > 3 ) VTMP3 = vld1q_f64( c_loc + 3 * cs_c + 2 ); if ( !b_iszr ) { VCOL0 = vfmaq_f64( VCOL0, VTMP0, vb_0 ); VCOL1 = vfmaq_f64( VCOL1, VTMP1, vb_0 ); VCOL2 = vfmaq_f64( VCOL2, VTMP2, vb_0 ); VCOL3 = vfmaq_f64( VCOL3, VTMP3, vb_0 ); } if ( n > 0 ) vst1q_f64( c_loc + 0 * cs_c + 2, VCOL0 ); if ( n > 1 ) vst1q_f64( c_loc + 1 * cs_c + 2, VCOL1 ); if ( n > 2 ) vst1q_f64( c_loc + 2 * cs_c + 2, VCOL2 ); if ( n > 3 ) vst1q_f64( c_loc + 3 * cs_c + 2, VCOL3 ); } else { if ( n > 0 ) VTMP0 = vld1q_lane_f64( c_loc + 0 * cs_c + 2, VTMP0, 0 ); if ( n > 1 ) VTMP1 = vld1q_lane_f64( c_loc + 1 * cs_c + 2, VTMP1, 0 ); if ( n > 2 ) VTMP2 = vld1q_lane_f64( c_loc + 2 * cs_c + 2, VTMP2, 0 ); if ( n > 3 ) VTMP3 = vld1q_lane_f64( c_loc + 3 * cs_c + 2, VTMP3, 0 ); if ( !b_iszr ) { VCOL0 = vfmaq_f64( VCOL0, VTMP0, vb_0 ); VCOL1 = vfmaq_f64( VCOL1, VTMP1, vb_0 ); VCOL2 = vfmaq_f64( VCOL2, VTMP2, vb_0 ); VCOL3 = vfmaq_f64( VCOL3, VTMP3, vb_0 ); } if ( n > 0 ) vst1q_lane_f64( c_loc + 0 * cs_c + 2, VCOL0, 0 ); if ( n > 1 ) vst1q_lane_f64( c_loc + 1 * cs_c + 2, VCOL1, 0 ); if ( n > 2 ) vst1q_lane_f64( c_loc + 2 * cs_c + 2, VCOL2, 0 ); if ( n > 3 ) vst1q_lane_f64( c_loc + 3 * cs_c + 2, VCOL3, 0 ); } } if ( m0 > 4 ) { VCOL0 = vtrn1q_f64(vc_40, vc_50); VCOL1 = vtrn2q_f64(vc_40, vc_50); VCOL2 = vtrn1q_f64(vc_41, vc_51); VCOL3 = vtrn2q_f64(vc_41, vc_51); if ( m0 > 5 ) { if ( n > 0 ) VTMP0 = vld1q_f64( c_loc + 0 * cs_c + 4 ); if ( n > 1 ) VTMP1 = vld1q_f64( c_loc + 1 * cs_c + 4 ); if ( n > 2 ) VTMP2 = vld1q_f64( c_loc + 2 * cs_c + 4 ); if ( n > 3 ) VTMP3 = vld1q_f64( c_loc + 3 * cs_c + 4 ); if ( !b_iszr ) { VCOL0 = vfmaq_f64( VCOL0, VTMP0, vb_0 ); VCOL1 = vfmaq_f64( VCOL1, VTMP1, vb_0 ); VCOL2 = vfmaq_f64( VCOL2, VTMP2, vb_0 ); VCOL3 = vfmaq_f64( VCOL3, VTMP3, vb_0 ); } if ( n > 0 ) vst1q_f64( c_loc + 0 * cs_c + 4, VCOL0 ); if ( n > 1 ) vst1q_f64( c_loc + 1 * cs_c + 4, VCOL1 ); if ( n > 2 ) vst1q_f64( c_loc + 2 * cs_c + 4, VCOL2 ); if ( n > 3 ) vst1q_f64( c_loc + 3 * cs_c + 4, VCOL3 ); } else { if ( n > 0 ) VTMP0 = vld1q_lane_f64( c_loc + 0 * cs_c + 4, VTMP0, 0 ); if ( n > 1 ) VTMP1 = vld1q_lane_f64( c_loc + 1 * cs_c + 4, VTMP1, 0 ); if ( n > 2 ) VTMP2 = vld1q_lane_f64( c_loc + 2 * cs_c + 4, VTMP2, 0 ); if ( n > 3 ) VTMP3 = vld1q_lane_f64( c_loc + 3 * cs_c + 4, VTMP3, 0 ); if ( !b_iszr ) { VCOL0 = vfmaq_f64( VCOL0, VTMP0, vb_0 ); VCOL1 = vfmaq_f64( VCOL1, VTMP1, vb_0 ); VCOL2 = vfmaq_f64( VCOL2, VTMP2, vb_0 ); VCOL3 = vfmaq_f64( VCOL3, VTMP3, vb_0 ); } if ( n > 0 ) vst1q_lane_f64( c_loc + 0 * cs_c + 4, VCOL0, 0 ); if ( n > 1 ) vst1q_lane_f64( c_loc + 1 * cs_c + 4, VCOL1, 0 ); if ( n > 2 ) vst1q_lane_f64( c_loc + 2 * cs_c + 4, VCOL2, 0 ); if ( n > 3 ) vst1q_lane_f64( c_loc + 3 * cs_c + 4, VCOL3, 0 ); } } } b_in += ps_b; c_in += 4 * cs_c; } a0 += ps_a; c0 += 6 * rs_c; } } blis-0.9.0/kernels/armv8a/bli_kernels_armv8a.h000066400000000000000000000055561422157504600212530ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ PACKM_KER_PROT( float, s, packm_armv8a_int_8xk ) PACKM_KER_PROT( float, s, packm_armv8a_int_12xk ) PACKM_KER_PROT( double, d, packm_armv8a_int_6xk ) PACKM_KER_PROT( double, d, packm_armv8a_int_8xk ) GEMM_UKR_PROT( float, s, gemm_armv8a_asm_8x12 ) GEMM_UKR_PROT( double, d, gemm_armv8a_asm_6x8 ) // GEMM_UKR_PROT( double, d, gemm_armv8a_asm_6x8r ) // GEMM_UKR_PROT( double, d, gemm_armv8a_asm_8x4 ) // GEMM_UKR_PROT( double, d, gemm_armv8a_asm_4x4 ) GEMMSUP_KER_PROT( double, d, gemmsup_rd_armv8a_asm_6x8n ) GEMMSUP_KER_PROT( double, d, gemmsup_rd_armv8a_asm_6x8m ) GEMMSUP_KER_PROT( double, d, gemmsup_rv_armv8a_asm_6x8n ) GEMMSUP_KER_PROT( double, d, gemmsup_rv_armv8a_asm_6x8m ) GEMMSUP_KER_PROT( double, d, gemmsup_rv_armv8a_asm_4x8n ) GEMMSUP_KER_PROT( double, d, gemmsup_rv_armv8a_asm_4x8m ) GEMMSUP_KER_PROT( double, d, gemmsup_rv_armv8a_asm_8x4m ) GEMMSUP_KER_PROT( double, d, gemmsup_rd_armv8a_int_2x8 ) GEMMSUP_KER_PROT( double, d, gemmsup_rd_armv8a_int_3x4 ) GEMMSUP_KER_PROT( double, d, gemmsup_rd_armv8a_asm_3x4 ) GEMMSUP_KER_PROT( double, d, gemmsup_rd_armv8a_asm_6x3 ) GEMMSUP_KER_PROT( double, d, gemmsup_rv_armv8a_int_6x4mn ) GEMMSUP_KER_PROT( double, d, gemmsup_rv_armv8a_int_3x8mn ) blis-0.9.0/kernels/bgq/000077500000000000000000000000001422157504600146735ustar00rootroot00000000000000blis-0.9.0/kernels/bgq/1/000077500000000000000000000000001422157504600150335ustar00rootroot00000000000000blis-0.9.0/kernels/bgq/1/bli_axpyv_bgq_int.c000066400000000000000000000056201422157504600207020ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_daxpyv_bgq_int ( conj_t conjx, dim_t n, double* restrict alpha, double* restrict x, inc_t incx, double* restrict y, inc_t incy, cntx_t* restrict cntx ) { if ( bli_zero_dim1( n ) ) return; // If there is anything that would interfere with our use of aligned // vector loads/stores, call the reference implementation. bool use_ref = FALSE; if ( incx != 1 || incy != 1 || bli_is_unaligned_to( ( siz_t )x, 32 ) || bli_is_unaligned_to( ( siz_t )y, 32 ) ) { use_ref = TRUE; } // Call the reference implementation if needed. if ( use_ref == TRUE ) { BLIS_DAXPYV_KERNEL_REF( conjx, n, alpha, x, incx, y, incy, cntx ); return; } dim_t n_run = n / 4; dim_t n_left = n % 4; vector4double xv, yv, zv; vector4double alphav = vec_lds( 0 * sizeof(double), (double*)alpha ); #pragma omp parallel for for ( dim_t i = 0; i < n_run; i++ ) { xv = vec_lda( 0 * sizeof(double), &x[i*4] ); yv = vec_lda( 0 * sizeof(double), &y[i*4] ); zv = vec_madd( alphav, xv, yv ); vec_sta( zv, 0 * sizeof(double), &y[i*4] ); } for ( dim_t i = 0; i < n_left; i++ ) { y[4*n_run + i] += *alpha * x[4*n_run + i]; } } blis-0.9.0/kernels/bgq/1/bli_dotv_bgq_int.c000066400000000000000000000064641422157504600205160ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_ddotv_bgq_int ( conj_t conjx, conj_t conjy, dim_t n, double* restrict x, inc_t incx, double* restrict y, inc_t incy, double* restrict rho, cntx_t* restrict cntx ) { bool use_ref = FALSE; // If the vector lengths are zero, set rho to zero and return. if ( bli_zero_dim1( n ) ) { PASTEMAC(d,set0s)( *rho ); return; } // If there is anything that would interfere with our use of aligned // vector loads/stores, call the reference implementation. if ( incx != 1 || incy != 1 || bli_is_unaligned_to( ( siz_t )x, 32 ) || bli_is_unaligned_to( ( siz_t )y, 32 ) ) use_ref = TRUE; // Call the reference implementation if needed. if ( use_ref ) { BLIS_DDOTV_KERNEL_REF( conjx, conjy, n, x, incx, y, incy, rho, cntx ); return; } dim_t n_run = n / 4; dim_t n_left = n % 4; double rhos = 0.0; #pragma omp parallel reduction(+:rhos) { dim_t n_threads; dim_t t_id = omp_get_thread_num(); n_threads = omp_get_num_threads(); vector4double rhov = vec_splats( 0.0 ); vector4double xv, yv; for ( dim_t i = t_id; i < n_run; i += n_threads ) { xv = vec_lda( 0 * sizeof(double), &x[i*4] ); yv = vec_lda( 0 * sizeof(double), &y[i*4] ); rhov = vec_madd( xv, yv, rhov ); } rhos += vec_extract( rhov, 0 ); rhos += vec_extract( rhov, 1 ); rhos += vec_extract( rhov, 2 ); rhos += vec_extract( rhov, 3 ); } for ( dim_t i = 0; i < n_left; i++ ) { rhos += x[4*n_run + i] * y[4*n_run + i]; } *rho = rhos; } blis-0.9.0/kernels/bgq/1f/000077500000000000000000000000001422157504600152015ustar00rootroot00000000000000blis-0.9.0/kernels/bgq/1f/bli_axpyf_bgq_int.c000066400000000000000000000126611422157504600210330ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_daxpyf_bgq_int ( conj_t conja, conj_t conjx, dim_t m, dim_t b_n, double* restrict alpha, double* restrict a, inc_t inca, inc_t lda, double* restrict x, inc_t incx, double* restrict y, inc_t incy, cntx_t* restrict cntx ) { const dim_t fusefac = 8; if ( bli_zero_dim2( m, b_n ) ) return; bool use_ref = FALSE; // printf("%d\t%d\t%d\t%d\t%d\t%d\t%d\n", b_n, fusefac, inca, incx, incy, bli_is_unaligned_to( ( siz_t )a, 32 ), bli_is_unaligned_to( ( siz_t )y, 32)); // If there is anything that would interfere with our use of aligned // vector loads/stores, call the reference implementation. if ( ( b_n < fusefac) || inca != 1 || incx != 1 || incy != 1 || bli_is_unaligned_to( ( siz_t )a, 32 ) || bli_is_unaligned_to( ( siz_t )y, 32 ) ) use_ref = TRUE; // Call the reference implementation if needed. if ( use_ref == TRUE ) { // printf("%d\t%d\t%d\t%d\t%d\t%d\n", fusefac, inca, incx, incy, bli_is_unaligned_to( ( siz_t )a, 32 ), bli_is_unaligned_to( ( siz_t )y, 32)); // printf("DEFAULTING TO REFERENCE IMPLEMENTATION\n"); BLIS_DAXPYF_KERNEL_REF( conja, conjx, m, b_n, alpha, a, inca, lda, x, incx, y, incy, cntx ); return; } dim_t m_run = m / 4; dim_t m_left = m % 4; double * a0 = a + 0*lda; double * a1 = a + 1*lda; double * a2 = a + 2*lda; double * a3 = a + 3*lda; double * a4 = a + 4*lda; double * a5 = a + 5*lda; double * a6 = a + 6*lda; double * a7 = a + 7*lda; double * y0 = y; double chi0 = *(x + 0*incx); double chi1 = *(x + 1*incx); double chi2 = *(x + 2*incx); double chi3 = *(x + 3*incx); double chi4 = *(x + 4*incx); double chi5 = *(x + 5*incx); double chi6 = *(x + 6*incx); double chi7 = *(x + 7*incx); PASTEMAC2(d,d,scals)( *alpha, chi0 ); PASTEMAC2(d,d,scals)( *alpha, chi1 ); PASTEMAC2(d,d,scals)( *alpha, chi2 ); PASTEMAC2(d,d,scals)( *alpha, chi3 ); PASTEMAC2(d,d,scals)( *alpha, chi4 ); PASTEMAC2(d,d,scals)( *alpha, chi5 ); PASTEMAC2(d,d,scals)( *alpha, chi6 ); PASTEMAC2(d,d,scals)( *alpha, chi7 ); vector4double a0v, a1v, a2v, a3v, a4v, a5v, a6v, a7v; vector4double yv; vector4double chi0v, chi1v, chi2v, chi3v, chi4v, chi5v, chi6v, chi7v; chi0v = vec_splats( chi0 ); chi1v = vec_splats( chi1 ); chi2v = vec_splats( chi2 ); chi3v = vec_splats( chi3 ); chi4v = vec_splats( chi4 ); chi5v = vec_splats( chi5 ); chi6v = vec_splats( chi6 ); chi7v = vec_splats( chi7 ); for ( dim_t i = 0; i < m_run; i += 1 ) { yv = vec_lda( 0 * sizeof(double), &y0[i*4]); a0v = vec_lda( 0 * sizeof(double), &a0[i*4]); a1v = vec_lda( 0 * sizeof(double), &a1[i*4]); a2v = vec_lda( 0 * sizeof(double), &a2[i*4]); a3v = vec_lda( 0 * sizeof(double), &a3[i*4]); a4v = vec_lda( 0 * sizeof(double), &a4[i*4]); a5v = vec_lda( 0 * sizeof(double), &a5[i*4]); a6v = vec_lda( 0 * sizeof(double), &a6[i*4]); a7v = vec_lda( 0 * sizeof(double), &a7[i*4]); yv = vec_madd( chi0v, a0v, yv ); yv = vec_madd( chi1v, a1v, yv ); yv = vec_madd( chi2v, a2v, yv ); yv = vec_madd( chi3v, a3v, yv ); yv = vec_madd( chi4v, a4v, yv ); yv = vec_madd( chi5v, a5v, yv ); yv = vec_madd( chi6v, a6v, yv ); yv = vec_madd( chi7v, a7v, yv ); vec_sta( yv, 0 * sizeof(double), &y0[i*4]); } for ( dim_t i = 0; i < m_left; ++i ) { y0[4*m_run + i] += chi0 * a0[4*m_run + i] + chi1 * a1[4*m_run + i] + chi2 * a2[4*m_run + i] + chi3 * a3[4*m_run + i] + chi4 * a4[4*m_run + i] + chi5 * a5[4*m_run + i] + chi6 * a6[4*m_run + i] + chi7 * a7[4*m_run + i]; } } blis-0.9.0/kernels/bgq/3/000077500000000000000000000000001422157504600150355ustar00rootroot00000000000000blis-0.9.0/kernels/bgq/3/bli_gemm_bgq_int_8x8.c000066400000000000000000000326721422157504600212000ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 UNIVERSITY OF TEXAS 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. */ #include "blis.h" #undef restrict #include #include /* * Here is dgemm kernel for QPX. * Instruction mix was divined by a statement in an email from John Gunnels when asked about the peak performance with a single thread: * "Achievable peak can either be: * 1) 12.8 GF 8 FMAs cycle * 1.6 GHz * 2) 8.53 GF Takes intoo account the instruction mix in DGEMM and the fact that you can only do an FMA or a load/store in a single cycle with just one thread * 3) 7.58 GF (2) + the fact that we can only issue 8 instructions in 9 cycles with one thread" * * Which I have taken to mean: 8.53 GFLOPS implies on average 5.33 flops/cycle. * I know the kernel John uses is 8x8, so 16 flops per loop iteration. * Thus there must be 24 total instructions per iteration because 16/24 = 5.33. * * Here, we have 6 loads per iteration. These are executed on a different pipeline from FMAs so * we could (maybe) theoretically hit 100% of peak with this instruction mix */ void bli_dgemm_bgq_int_8x8 ( dim_t m, dim_t n, dim_t k, double* restrict alpha, double* restrict a, double* restrict b, double* restrict beta, double* restrict c, inc_t rs_c, inc_t cs_c, auxinfo_t* restrict data, cntx_t* restrict cntx ) { GEMM_UKR_SETUP_CT_ANY( d, 8, 8, false ); //Registers for storing C. //4 4x4 subblocks of C, c00, c01, c10, c11 //4 registers per subblock: a, b, c, d //There is an excel file that details which register ends up storing what vector4double c00a = vec_splats( 0.0 ); vector4double c00b = vec_splats( 0.0 ); vector4double c00c = vec_splats( 0.0 ); vector4double c00d = vec_splats( 0.0 ); vector4double c01a = vec_splats( 0.0 ); vector4double c01b = vec_splats( 0.0 ); vector4double c01c = vec_splats( 0.0 ); vector4double c01d = vec_splats( 0.0 ); vector4double c10a = vec_splats( 0.0 ); vector4double c10b = vec_splats( 0.0 ); vector4double c10c = vec_splats( 0.0 ); vector4double c10d = vec_splats( 0.0 ); vector4double c11a = vec_splats( 0.0 ); vector4double c11b = vec_splats( 0.0 ); vector4double c11c = vec_splats( 0.0 ); vector4double c11d = vec_splats( 0.0 ); vector4double b0a, b1a; vector4double b0b, b1b; vector4double a0, a1; for( dim_t i = 0; i < k; i++ ) { b0a = vec_ld2a( 0 * sizeof(double), &b[8*i] ); b0b = vec_ld2a( 2 * sizeof(double), &b[8*i] ); b1a = vec_ld2a( 4 * sizeof(double), &b[8*i] ); b1b = vec_ld2a( 6 * sizeof(double), &b[8*i] ); a0 = vec_lda ( 0 * sizeof(double), &a[8*i] ); a1 = vec_lda ( 4 * sizeof(double), &a[8*i] ); c00a = vec_xmadd ( b0a, a0, c00a ); c00b = vec_xxmadd( a0, b0a, c00b ); c00c = vec_xmadd ( b0b, a0, c00c ); c00d = vec_xxmadd( a0, b0b, c00d ); c01a = vec_xmadd ( b1a, a0, c01a ); c01b = vec_xxmadd( a0, b1a, c01b ); c01c = vec_xmadd ( b1b, a0, c01c ); c01d = vec_xxmadd( a0, b1b, c01d ); c10a = vec_xmadd ( b0a, a1, c10a ); c10b = vec_xxmadd( a1, b0a, c10b ); c10c = vec_xmadd ( b0b, a1, c10c ); c10d = vec_xxmadd( a1, b0b, c10d ); c11a = vec_xmadd ( b1a, a1, c11a ); c11b = vec_xxmadd( a1, b1a, c11b ); c11c = vec_xmadd ( b1b, a1, c11c ); c11d = vec_xxmadd( a1, b1b, c11d ); } // Create patterns for permuting Cb and Cd vector4double pattern = vec_gpci( 01032 ); vector4double AB; vector4double C = vec_splats( 0.0 ); vector4double betav = vec_lds( 0, ( double* )beta ); vector4double alphav = vec_lds( 0, ( double* )alpha ); double ct; //Macro to update 4 elements of C in a column. //REG is the register holding those 4 elements //ADDR is the address to write them to //OFFSET is the number of rows from ADDR to write to #define UPDATE( REG, ADDR, OFFSET ) \ { \ ct = *(ADDR + (OFFSET + 0) * rs_c); \ C = vec_insert( ct, C, 0 ); \ ct = *(ADDR + (OFFSET + 1) * rs_c); \ C = vec_insert( ct, C, 1 ); \ ct = *(ADDR + (OFFSET + 2) * rs_c); \ C = vec_insert( ct, C, 2 ); \ ct = *(ADDR + (OFFSET + 3) * rs_c); \ C = vec_insert( ct, C, 3 ); \ \ AB = vec_mul( REG, alphav ); \ AB = vec_madd( C, betav, AB); \ \ ct = vec_extract( AB, 0 ); \ *(ADDR + (OFFSET + 0) * rs_c) = ct; \ ct = vec_extract( AB, 1 ); \ *(ADDR + (OFFSET + 1) * rs_c) = ct; \ ct = vec_extract( AB, 2 ); \ *(ADDR + (OFFSET + 2) * rs_c) = ct; \ ct = vec_extract( AB, 3 ); \ *(ADDR + (OFFSET + 3) * rs_c) = ct; \ } //Update c00 and c10 sub-blocks UPDATE( c00a, c, 0 ); UPDATE( c10a, c, 4 ); c = c + cs_c; AB = vec_perm( c00b, c00b, pattern ); UPDATE( AB, c, 0 ); AB = vec_perm( c10b, c10b, pattern ); UPDATE( AB, c, 4 ); c = c + cs_c; UPDATE( c00c, c, 0 ); UPDATE( c10c, c, 4 ); c = c + cs_c; AB = vec_perm( c00d, c00d, pattern ); UPDATE( AB, c, 0 ); AB = vec_perm( c10d, c10d, pattern ); UPDATE( AB, c, 4 ); //Update c01 and c11 sub-blocks c = c + cs_c; UPDATE( c01a, c, 0 ); UPDATE( c11a, c, 4 ); c = c + cs_c; AB = vec_perm( c01b, c01b, pattern ); UPDATE( AB, c, 0 ); AB = vec_perm( c11b, c11b, pattern ); UPDATE( AB, c, 4 ); c = c + cs_c; UPDATE( c01c, c, 0 ); UPDATE( c11c, c, 4 ); c = c + cs_c; AB = vec_perm( c01d, c01d, pattern ); UPDATE( AB, c, 0 ); AB = vec_perm( c11d, c11d, pattern ); UPDATE( AB, c, 4 ); GEMM_UKR_FLUSH_CT( d ); } void printvec(vector4double v) { double a = vec_extract(v, 0); double b = vec_extract(v, 1); double c = vec_extract(v, 2); double d = vec_extract(v, 3); printf("%4.3f\t%4.3f\t%4.3f\t%4.3f\n", a, b, c, d); } void bli_zgemm_bgq_int_4x4 ( dim_t m, dim_t n, dim_t k, dcomplex* restrict alpha, dcomplex* restrict a, dcomplex* restrict b, dcomplex* restrict beta, dcomplex* restrict c, inc_t rs_c, inc_t cs_c, auxinfo_t* restrict data, cntx_t* restrict cntx ) { GEMM_UKR_SETUP_CT_ANY( z, 4, 4, false ); double* a_d = ( double* )a; double* b_d = ( double* )b; double* c_d = ( double* )c; //Registers for storing C. //2 2x4 subblocks of C, c0, and c1 //Each sub-block has 4 columns, 0, 1, 2, 3 //Each column has 2 partial sum, a and b, and contains 2 complex numbers. vector4double c00a = vec_splats( 0.0 ); vector4double c00b = vec_splats( 0.0 ); vector4double c01a = vec_splats( 0.0 ); vector4double c01b = vec_splats( 0.0 ); vector4double c02a = vec_splats( 0.0 ); vector4double c02b = vec_splats( 0.0 ); vector4double c03a = vec_splats( 0.0 ); vector4double c03b = vec_splats( 0.0 ); vector4double c10a = vec_splats( 0.0 ); vector4double c10b = vec_splats( 0.0 ); vector4double c11a = vec_splats( 0.0 ); vector4double c11b = vec_splats( 0.0 ); vector4double c12a = vec_splats( 0.0 ); vector4double c12b = vec_splats( 0.0 ); vector4double c13a = vec_splats( 0.0 ); vector4double c13b = vec_splats( 0.0 ); vector4double b0, b1, b2, b3; vector4double a0, a1; for( dim_t i = 0; i < k; i++ ) { b0 = vec_ld2a( 0 * sizeof(double), &b_d[8*i] ); b1 = vec_ld2a( 2 * sizeof(double), &b_d[8*i] ); b2 = vec_ld2a( 4 * sizeof(double), &b_d[8*i] ); b3 = vec_ld2a( 6 * sizeof(double), &b_d[8*i] ); a0 = vec_lda ( 0 * sizeof(double), &a_d[8*i] ); a1 = vec_lda ( 4 * sizeof(double), &a_d[8*i] ); c00a = vec_xmadd ( b0, a0, c00a ); c00b = vec_xxcpnmadd( a0, b0, c00b ); c01a = vec_xmadd ( b1, a0, c01a ); c01b = vec_xxcpnmadd( a0, b1, c01b ); c02a = vec_xmadd ( b2, a0, c02a ); c02b = vec_xxcpnmadd( a0, b2, c02b ); c03a = vec_xmadd ( b3, a0, c03a ); c03b = vec_xxcpnmadd( a0, b3, c03b ); c10a = vec_xmadd ( b0, a1, c10a ); c10b = vec_xxcpnmadd( a1, b0, c10b ); c11a = vec_xmadd ( b1, a1, c11a ); c11b = vec_xxcpnmadd( a1, b1, c11b ); c12a = vec_xmadd ( b2, a1, c12a ); c12b = vec_xxcpnmadd( a1, b2, c12b ); c13a = vec_xmadd ( b3, a1, c13a ); c13b = vec_xxcpnmadd( a1, b3, c13b ); } // Create patterns for permuting the "b" parts of each vector vector4double pattern = vec_gpci( 01032 ); vector4double zed = vec_splats( 0.0 ); vector4double AB; vector4double C = vec_splats( 0.0 ); vector4double C1 = vec_splats( 0.0 ); vector4double C2 = vec_splats( 0.0 ); double alphar = bli_zreal( *alpha ); double alphai = bli_zimag( *alpha ); double betar = bli_zreal( *beta ); double betai = bli_zimag( *beta ); vector4double alphav = vec_splats( 0.0 ); vector4double betav = vec_splats( 0.0 ); alphav = vec_insert( alphar, alphav, 0); alphav = vec_insert( alphai, alphav, 1); alphav = vec_insert( alphar, alphav, 2); alphav = vec_insert( alphai, alphav, 3); betav = vec_insert( betar, betav, 0); betav = vec_insert( betai, betav, 1); betav = vec_insert( betar, betav, 2); betav = vec_insert( betai, betav, 3); double ct; //Macro to update 2 elements of C in a column. //REG1 is the register holding the first partial sum of those 2 elements //REG2 is the register holding the second partial sum of those 2 elements //ADDR is the address to write them to //OFFSET is the number of rows from ADDR to write to #define ZUPDATE( REG1, REG2, ADDR, OFFSET ) \ { \ ct = *(ADDR + (OFFSET + 0) * rs_c); \ C = vec_insert( ct, C, 0 ); \ ct = *(ADDR + (OFFSET + 0) * rs_c + 1); \ C = vec_insert( ct, C, 1 ); \ ct = *(ADDR + (OFFSET + 2) * rs_c); \ C = vec_insert( ct, C, 2 ); \ ct = *(ADDR + (OFFSET + 2) * rs_c + 1); \ C = vec_insert( ct, C, 3 ); \ \ AB = vec_sub(REG1, REG2 ); \ \ /* Scale by alpha */ \ REG1 = vec_xmadd( alphav, AB, zed ); \ REG2 = vec_xxcpnmadd( AB, alphav, zed ); \ AB = vec_sub(REG1, REG2 ); \ \ \ /* Scale by beta */ \ REG1 = vec_xmadd( betav, C, zed ); \ REG2 = vec_xxcpnmadd( C, betav, zed ); \ C = vec_sub(REG1, REG2 ); \ \ /* Add AB to C */ \ C = vec_add( AB, C ); \ \ ct = vec_extract( C, 0 ); \ *(ADDR + (OFFSET + 0) * rs_c) = ct; \ ct = vec_extract( C, 1 ); \ *(ADDR + (OFFSET + 0) * rs_c + 1) = ct; \ ct = vec_extract( C, 2 ); \ *(ADDR + (OFFSET + 2) * rs_c) = ct; \ ct = vec_extract( C, 3 ); \ *(ADDR + (OFFSET + 2) * rs_c + 1) = ct; \ } ZUPDATE( c00a, c00b, c_d, 0 ); ZUPDATE( c10a, c10b, c_d, 4 ); c_d += 2*cs_c; ZUPDATE( c01a, c01b, c_d, 0 ); ZUPDATE( c11a, c11b, c_d, 4 ); c_d += 2*cs_c; ZUPDATE( c02a, c02b, c_d, 0 ); ZUPDATE( c12a, c12b, c_d, 4 ); c_d += 2*cs_c; ZUPDATE( c03a, c03b, c_d, 0 ); ZUPDATE( c13a, c13b, c_d, 4 ); GEMM_UKR_FLUSH_CT( z ); } blis-0.9.0/kernels/bgq/bli_kernels_bgq.h000066400000000000000000000035561422157504600201770ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ GEMM_UKR_PROT( double, d, gemm_bgq_int_8x8 ) GEMM_UKR_PROT( dcomplex, z, gemm_bgq_int_4x4 ) AXPYF_KER_PROT( double, d, axpyf_bgq_int ) AXPYV_KER_PROT( double, d, axpyv_bgq_int ) DOTV_KER_PROT( double, d, dotv_bgq_int ) blis-0.9.0/kernels/bulldozer/000077500000000000000000000000001422157504600161245ustar00rootroot00000000000000blis-0.9.0/kernels/bulldozer/3/000077500000000000000000000000001422157504600162665ustar00rootroot00000000000000blis-0.9.0/kernels/bulldozer/3/bli_gemm_bulldozer_asm_d4x6_fma4.c000066400000000000000000001450371422157504600247150ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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 The University of Texas 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define BLIS_ASM_SYNTAX_ATT #include "bli_x86_asm_macros.h" #define GROUP_YMM_BY_4 \ vmovaps(ymm15, ymm7)\ vshufps(imm(0xe4), ymm13, ymm15, ymm15)\ vshufps(imm(0xe4), ymm7, ymm13, ymm13)\ \ vmovaps(ymm11, ymm7)\ vshufps(imm(0xe4), ymm9, ymm11, ymm11)\ vshufps(imm(0xe4), ymm7, ymm9, ymm9)\ \ vmovaps(ymm14, ymm7)\ vshufps(imm(0xe4), ymm12, ymm14, ymm14)\ vshufps(imm(0xe4), ymm7, ymm12, ymm12)\ \ vmovaps(ymm10, ymm7)\ vshufps(imm(0xe4), ymm8, ymm10, ymm10)\ vshufps(imm(0xe4), ymm7, ymm8, ymm8)\ \ vmovaps(ymm15, ymm7)\ vperm2f128(imm(0x12), ymm15, ymm11, ymm15)\ vperm2f128(imm(0x30), ymm7, ymm11, ymm11)\ \ vmovaps(ymm13, ymm7)\ vperm2f128(imm(0x12), ymm13, ymm9, ymm13)\ vperm2f128(imm(0x30), ymm7, ymm9, ymm9)\ \ vmovaps(ymm14, ymm7)\ vperm2f128(imm(0x12), ymm14, ymm10, ymm14)\ vperm2f128(imm(0x30), ymm7, ymm10, ymm10)\ \ vmovaps(ymm12, ymm7)\ vperm2f128(imm(0x12), ymm12, ymm8, ymm12)\ vperm2f128(imm(0x30), ymm7, ymm8, ymm8) #define STORE_SS \ vextractf128(imm(1), ymm0, xmm2)\ vmovss(xmm0, mem(rcx))\ vpermilps(imm(0x39), xmm0, xmm1)\ vmovss(xmm1, mem(rcx, rsi, 1))\ vpermilps(imm(0x39), xmm1, xmm0)\ vmovss(xmm0, mem(rcx, r12, 1))\ vpermilps(imm(0x39), xmm0, xmm1)\ vmovss(xmm1, mem(rcx, r13, 1))\ vmovss(xmm2, mem(rdx))\ vpermilps(imm(0x39), xmm2, xmm3)\ vmovss(xmm3, mem(rdx, rsi, 1))\ vpermilps(imm(0x39), xmm3, xmm2)\ vmovss(xmm2, mem(rdx, r12, 1))\ vpermilps(imm(0x39), xmm2, xmm3)\ vmovss(xmm3, mem(rdx, r13, 1))\ void bli_sgemm_bulldozer_asm_8x8_fma4 ( dim_t m, dim_t n, dim_t k, float* restrict alpha, float* restrict a, float* restrict b, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k / 4; uint64_t k_left = k % 4; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; GEMM_UKR_SETUP_CT_ALIGNED( s, 8, 8, false, 32 ); begin_asm() mov(var(a), rax) // load address of a. mov(var(b), rbx) // load address of b. vmovaps(mem(rax, 0*32), ymm0) // initialize loop by pre-loading vmovsldup(mem(rbx, 0*32), ymm2) // elements of a and b. vpermilps(imm(0x4e), ymm2, ymm3) mov(var(c), rcx) // load address of c mov(var(cs_c), rdi) // load cs_c lea(mem(, rdi, 4), rdi) // cs_c *= sizeof(float) lea(mem(rcx, rdi, 4), r10) // load address of c + 4*cs_c; lea(mem(rdi, rdi, 2), r14) // r14 = 3*cs_c; prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rdi, 1, 7*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rdi, 2, 7*8)) // prefetch c + 2*cs_c prefetch(0, mem(rcx, r14, 1, 7*8)) // prefetch c + 3*cs_c prefetch(0, mem(r10, 7*8)) // prefetch c + 4*cs_c prefetch(0, mem(r10, rdi, 1, 7*8)) // prefetch c + 5*cs_c prefetch(0, mem(r10, rdi, 2, 7*8)) // prefetch c + 6*cs_c prefetch(0, mem(r10, r14, 1, 7*8)) // prefetch c + 7*cs_c vxorps(ymm8, ymm8, ymm8) vxorps(ymm9, ymm9, ymm9) vxorps(ymm10, ymm10, ymm10) vxorps(ymm11, ymm11, ymm11) vxorps(ymm12, ymm12, ymm12) vxorps(ymm13, ymm13, ymm13) vxorps(ymm14, ymm14, ymm14) vxorps(ymm15, ymm15, ymm15) mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // iteration 0 prefetch(0, mem(rax, 16*32)) vfmaddps(ymm15, ymm0, ymm2, ymm15) vperm2f128(imm(0x03), ymm2, ymm2, ymm4) vmovshdup(mem(rbx, 0*32), ymm2) vfmaddps(ymm13, ymm0, ymm3, ymm13) vperm2f128(imm(0x03), ymm3, ymm3, ymm5) vmovaps(mem(rax, 1*32), ymm1) vpermilps(imm(0x4e), ymm2, ymm3) vfmaddps(ymm11, ymm0, ymm4, ymm11) vfmaddps(ymm9, ymm0, ymm5, ymm9) vfmaddps(ymm14, ymm0, ymm2, ymm14) vperm2f128(imm(0x03), ymm2, ymm2, ymm4) vmovsldup(mem(rbx, 1*32), ymm2) vfmaddps(ymm12, ymm0, ymm3, ymm12) vperm2f128(imm(0x03), ymm3, ymm3, ymm5) vpermilps(imm(0x4e), ymm2, ymm3) vfmaddps(ymm10, ymm0, ymm4, ymm10) vfmaddps(ymm8, ymm0, ymm5, ymm8) // iteration 1 vfmaddps(ymm15, ymm1, ymm2, ymm15) vperm2f128(imm(0x03), ymm2, ymm2, ymm4) vmovshdup(mem(rbx, 1*32), ymm2) vfmaddps(ymm13, ymm1, ymm3, ymm13) vperm2f128(imm(0x03), ymm3, ymm3, ymm5) vmovaps(mem(rax, 2*32), ymm0) vpermilps(imm(0x4e), ymm2, ymm3) vfmaddps(ymm11, ymm1, ymm4, ymm11) vfmaddps(ymm9, ymm1, ymm5, ymm9) vfmaddps(ymm14, ymm1, ymm2, ymm14) vperm2f128(imm(0x03), ymm2, ymm2, ymm4) vmovsldup(mem(rbx, 2*32), ymm2) vfmaddps(ymm12, ymm1, ymm3, ymm12) vperm2f128(imm(0x03), ymm3, ymm3, ymm5) vpermilps(imm(0x4e), ymm2, ymm3) vfmaddps(ymm10, ymm1, ymm4, ymm10) vfmaddps(ymm8, ymm1, ymm5, ymm8) // iteration 2 prefetch(0, mem(rax, 18*32)) vfmaddps(ymm15, ymm0, ymm2, ymm15) vperm2f128(imm(0x03), ymm2, ymm2, ymm4) vmovshdup(mem(rbx, 2*32), ymm2) vfmaddps(ymm13, ymm0, ymm3, ymm13) vperm2f128(imm(0x03), ymm3, ymm3, ymm5) vmovaps(mem(rax, 3*32), ymm1) add(imm(4*8*4), rax) // a += 4*8 (unroll x mr) vpermilps(imm(0x4e), ymm2, ymm3) vfmaddps(ymm11, ymm0, ymm4, ymm11) vfmaddps(ymm9, ymm0, ymm5, ymm9) vfmaddps(ymm14, ymm0, ymm2, ymm14) vperm2f128(imm(0x03), ymm2, ymm2, ymm4) vmovsldup(mem(rbx, 3*32), ymm2) vfmaddps(ymm12, ymm0, ymm3, ymm12) vperm2f128(imm(0x03), ymm3, ymm3, ymm5) vpermilps(imm(0x4e), ymm2, ymm3) vfmaddps(ymm10, ymm0, ymm4, ymm10) vfmaddps(ymm8, ymm0, ymm5, ymm8) // iteration 3 vfmaddps(ymm15, ymm1, ymm2, ymm15) vperm2f128(imm(0x03), ymm2, ymm2, ymm4) vmovshdup(mem(rbx, 3*32), ymm2) add(imm(4*8*4), rbx) // b += 4*8 (unroll x nr) vfmaddps(ymm13, ymm1, ymm3, ymm13) vperm2f128(imm(0x03), ymm3, ymm3, ymm5) vmovaps(mem(rax, 0*32), ymm0) vpermilps(imm(0x4e), ymm2, ymm3) vfmaddps(ymm11, ymm1, ymm4, ymm11) vfmaddps(ymm9, ymm1, ymm5, ymm9) vfmaddps(ymm14, ymm1, ymm2, ymm14) vperm2f128(imm(0x03), ymm2, ymm2, ymm4) vmovsldup(mem(rbx, 0*32), ymm2) vfmaddps(ymm12, ymm1, ymm3, ymm12) vperm2f128(imm(0x03), ymm3, ymm3, ymm5) vpermilps(imm(0x4e), ymm2, ymm3) vfmaddps(ymm10, ymm1, ymm4, ymm10) vfmaddps(ymm8, ymm1, ymm5, ymm8) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP prefetch(0, mem(rax, 16*32)) vfmaddps(ymm15, ymm0, ymm2, ymm15) vperm2f128(imm(0x3), ymm2, ymm2, ymm4) vmovshdup(mem(rbx, 0*32), ymm2) vfmaddps(ymm13, ymm0, ymm3, ymm13) vperm2f128(imm(0x3), ymm3, ymm3, ymm5) vmovaps(mem(rax, 1*32), ymm1) add(imm(8*1*4), rax) // a += 8 (1 x mr) vpermilps(imm(0x4e), ymm2, ymm3) vfmaddps(ymm11, ymm0, ymm4, ymm11) vfmaddps(ymm9, ymm0, ymm5, ymm9) vfmaddps(ymm14, ymm0, ymm2, ymm14) vperm2f128(imm(0x3), ymm2, ymm2, ymm4) vmovsldup(mem(rbx, 1*32), ymm2) add(imm(8*1*4), rbx) // b += 8 (1 x nr) vfmaddps(ymm12, ymm0, ymm3, ymm12) vperm2f128(imm(0x3), ymm3, ymm3, ymm5) vpermilps(imm(0x4e), ymm2, ymm3) vfmaddps(ymm10, ymm0, ymm4, ymm10) vfmaddps(ymm8, ymm0, ymm5, ymm8) vmovaps(ymm1, ymm0) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) // ymm15: ymm13: ymm11: ymm9: // ( ab00 ( ab02 ( ab04 ( ab06 // ab10 ab12 ab14 ab16 // ab22 ab20 ab26 ab24 // ab32 ab30 ab36 ab34 // ab44 ab46 ab40 ab42 // ab54 ab56 ab50 ab52 // ab66 ab64 ab62 ab60 // ab76 ) ab74 ) ab72 ) ab70 ) // ymm14: ymm12: ymm10: ymm8: // ( ab01 ( ab03 ( ab05 ( ab07 // ab11 ab13 ab15 ab17 // ab23 ab21 ab27 ab25 // ab33 ab31 ab37 ab35 // ab45 ab47 ab41 ab43 // ab55 ab57 ab51 ab53 // ab67 ab65 ab63 ab61 // ab77 ) ab75 ) ab73 ) ab71 ) GROUP_YMM_BY_4 // ymm15: ymm13: ymm11: ymm9: // ( ab00 ( ab02 ( ab04 ( ab06 // ab10 ab12 ab14 ab16 // ab20 ab22 ab24 ab26 // ab30 ab32 ab34 ab36 // ab44 ab46 ab40 ab42 // ab54 ab56 ab50 ab52 // ab64 ab66 ab60 ab62 // ab74 ) ab76 ) ab70 ) ab72 ) // ymm14: ymm12: ymm10: ymm8: // ( ab01 ( ab03 ( ab05 ( ab07 // ab11 ab13 ab15 ab17 // ab21 ab23 ab25 ab27 // ab31 ab33 ab35 ab37 // ab45 ab47 ab41 ab43 // ab55 ab57 ab51 ab53 // ab65 ab67 ab61 ab63 // ab75 ) ab77 ) ab71 ) ab73 ) // ymm15: ymm13: ymm11: ymm9: // ( ab00 ( ab02 ( ab04 ( ab06 // ab10 ab12 ab14 ab16 // ab20 ab22 ab24 ab26 // ab30 ab32 ab34 ab36 // ab40 ab42 ab44 ab46 // ab50 ab52 ab54 ab56 // ab60 ab62 ab64 ab66 // ab70 ) ab72 ) ab74 ) ab76 ) // ymm14: ymm12: ymm10: ymm8: // ( ab01 ( ab03 ( ab05 ( ab07 // ab11 ab13 ab15 ab17 // ab21 ab23 ab25 ab27 // ab31 ab33 ab35 ab37 // ab41 ab43 ab45 ab47 // ab51 ab53 ab55 ab57 // ab61 ab63 ab65 ab67 // ab71 ) ab73 ) ab75 ) ab77 ) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), ymm0) // load alpha and duplicate vbroadcastss(mem(rbx), ymm4) // load beta and duplicate vmulps(ymm0, ymm8, ymm8) // scale by alpha vmulps(ymm0, ymm9, ymm9) vmulps(ymm0, ymm10, ymm10) vmulps(ymm0, ymm11, ymm11) vmulps(ymm0, ymm12, ymm12) vmulps(ymm0, ymm13, ymm13) vmulps(ymm0, ymm14, ymm14) vmulps(ymm0, ymm15, ymm15) // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm4) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case vmovaps(mem(rcx), ymm0) // load c00:c70, //vmulps(ymm4, ymm0, ymm0) // scale by beta, //vaddps(ymm15, ymm0, ymm0) // add the gemm result, vfmaddps(ymm15, ymm0, ymm4, ymm0) // scale by beta and add the gemm result, vmovaps(ymm0, mem(rcx)) // and store back to memory. add(rdi, rcx) // c += cs_c; vmovaps(mem(rcx), ymm1) // load c01:c71, //vmulps(ymm4, ymm1, ymm1) // scale by beta, //vaddps(ymm14, ymm1, ymm1) // add the gemm result, vfmaddps(ymm14, ymm1, ymm4, ymm1) // scale by beta and add the gemm result, vmovaps(ymm1, mem(rcx)) // and store back to memory. add(rdi, rcx) // c += cs_c; vmovaps(mem(rcx), ymm0) // load c02:c72, //vmulps(ymm4, ymm0, ymm0) // scale by beta, //vaddps(ymm13, ymm0, ymm0) // add the gemm result, vfmaddps(ymm13, ymm0, ymm4, ymm0) // scale by beta and add the gemm result, vmovaps(ymm0, mem(rcx)) // and store back to memory. add(rdi, rcx) // c += cs_c; vmovaps(mem(rcx), ymm1) // load c03:c73, //vmulps(ymm4, ymm1, ymm1) // scale by beta, //vaddps(ymm12, ymm1, ymm1) // add the gemm result, vfmaddps(ymm12, ymm1, ymm4, ymm1) // scale by beta and add the gemm result, vmovaps(ymm1, mem(rcx)) // and store back to memory. add(rdi, rcx) // c += cs_c; vmovaps(mem(rcx), ymm0) // load c04:c74, //vmulps(ymm4, ymm0, ymm0) // scale by beta, //vaddps(ymm11, ymm0, ymm0) // add the gemm result, vfmaddps(ymm11, ymm0, ymm4, ymm0) // scale by beta and add the gemm result, vmovaps(ymm0, mem(rcx)) // and store back to memory. add(rdi, rcx) // c += cs_c; vmovaps(mem(rcx), ymm1) // load c05:c75, //vmulps(ymm4, ymm1, ymm1) // scale by beta, //vaddps(ymm10, ymm1, ymm1) // add the gemm result, vfmaddps(ymm10, ymm1, ymm4, ymm1) // scale by beta and add the gemm result, vmovaps(ymm1, mem(rcx)) // and store back to memory. add(rdi, rcx) // c += cs_c; vmovaps(mem(rcx), ymm0) // load c06:c76, //vmulps(ymm4, ymm0, ymm0) // scale by beta, //vaddps(ymm9, ymm0, ymm0) // add the gemm result, vfmaddps(ymm9, ymm0, ymm4, ymm0) // scale by beta and add the gemm result, vmovaps(ymm0, mem(rcx)) // and store back to memory. add(rdi, rcx) // c += cs_c; vmovaps(mem(rcx), ymm1) // load c07:c77, //vmulps(ymm4, ymm1, ymm1) // scale by beta, //vaddps(ymm8, ymm1, ymm1) // add the gemm result, vfmaddps(ymm8, ymm1, ymm4, ymm1) // scale by beta and add the gemm result, vmovaps(ymm1, mem(rcx)) // and store back to memory. jmp(.SDONE) // jump to end. label(.SBETAZERO) vmovaps(ymm15, mem(rcx)) // and store back to memory. add(rdi, rcx) // c += cs_c; vmovaps(ymm14, mem(rcx)) // and store back to memory. add(rdi, rcx) // c += cs_c; vmovaps(ymm13, mem(rcx)) // and store back to memory. add(rdi, rcx) // c += cs_c; vmovaps(ymm12, mem(rcx)) // and store back to memory. add(rdi, rcx) // c += cs_c; vmovaps(ymm11, mem(rcx)) // and store back to memory. add(rdi, rcx) // c += cs_c; vmovaps(ymm10, mem(rcx)) // and store back to memory. add(rdi, rcx) // c += cs_c; vmovaps(ymm9, mem(rcx)) // and store back to memory. add(rdi, rcx) // c += cs_c; vmovaps(ymm8, mem(rcx)) // and store back to memory. label(.SDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), // 0 [k_left] "m" (k_left), // 1 [a] "m" (a), // 2 [b] "m" (b), // 3 [alpha] "m" (alpha), // 4 [beta] "m" (beta), // 5 [c] "m" (c), // 6 [rs_c] "m" (rs_c), // 7 [cs_c] "m" (cs_c)/*, // 8 [b_next] "m" (b_next), // 9 [a_next] "m" (a_next)*/ // 10 : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) GEMM_UKR_FLUSH_CT( s ); } #undef KERNEL4x6_1 #undef KERNEL4x6_2 #undef KERNEL4x6_3 #undef KERNEL4x6_4 #define KERNEL4x6_1(xx) \ ALIGN4\ vmovddup(mem(rax, -8*8), xmm0)\ vfmaddpd(xmm4, xmm1, xmm0, xmm4)\ vfmaddpd(xmm5, xmm2, xmm0, xmm5)\ vfmaddpd(xmm6, xmm3, xmm0, xmm6)\ vmovddup(mem(rax, -7*8), xmm0)\ vfmaddpd(xmm7, xmm1, xmm0, xmm7)\ prefetch(0, mem(rax, 128))\ vfmaddpd(xmm8, xmm2, xmm0, xmm8)\ vfmaddpd(xmm9, xmm3, xmm0, xmm9)\ vmovddup(mem(rax, -6*8), xmm0)\ vfmaddpd(xmm10, xmm1, xmm0, xmm10)\ vfmaddpd(xmm11, xmm2, xmm0, xmm11)\ vfmaddpd(xmm12, xmm3, xmm0, xmm12)\ vmovddup(mem(rax, -5*8), xmm0)\ vfmaddpd(xmm13, xmm1, xmm0, xmm13)\ vmovaps(mem(rbx, -6*8), xmm1)\ vfmaddpd(xmm14, xmm2, xmm0, xmm14)\ vmovaps(mem(rbx, -4*8), xmm2)\ vfmaddpd(xmm15, xmm3, xmm0, xmm15)\ vmovaps(mem(rbx, -2*8), xmm3) #define KERNEL4x6_2(xx) \ vmovddup(mem(rax, -4*8), xmm0)\ vfmaddpd(xmm4, xmm1, xmm0, xmm4)\ prefetch(0, mem(rax, 192))\ vfmaddpd(xmm5, xmm2, xmm0, xmm5)\ vfmaddpd(xmm6, xmm3, xmm0, xmm6)\ vmovddup(mem(rax, -3*8), xmm0)\ vfmaddpd(xmm7, xmm1, xmm0, xmm7)\ vfmaddpd(xmm8, xmm2, xmm0, xmm8)\ vfmaddpd(xmm9, xmm3, xmm0, xmm9)\ vmovddup(mem(rax, -2*8), xmm0)\ vfmaddpd(xmm10, xmm1, xmm0, xmm10)\ vfmaddpd(xmm11, xmm2, xmm0, xmm11)\ vfmaddpd(xmm12, xmm3, xmm0, xmm12)\ vmovddup(mem(rax, -1*8), xmm0)\ vfmaddpd(xmm13, xmm1, xmm0, xmm13)\ vmovaps(mem(rbx, 0*8), xmm1)\ vfmaddpd(xmm14, xmm2, xmm0, xmm14)\ vmovaps(mem(rbx, 2*8), xmm2)\ vfmaddpd(xmm15, xmm3, xmm0, xmm15)\ vmovaps(mem(rbx, 4*8), xmm3)\ #define KERNEL4x6_3(xx) \ vmovddup(mem(rax, 0*8), xmm0)\ vfmaddpd(xmm4, xmm1, xmm0, xmm4)\ vfmaddpd(xmm5, xmm2, xmm0, xmm5)\ vfmaddpd(xmm6, xmm3, xmm0, xmm6)\ vmovddup(mem(rax, 1*8), xmm0)\ vfmaddpd(xmm7, xmm1, xmm0, xmm7)\ prefetch(0, mem(rax, 224))\ vfmaddpd(xmm8, xmm2, xmm0, xmm8)\ vfmaddpd(xmm9, xmm3, xmm0, xmm9)\ vmovddup(mem(rax, 2*8), xmm0)\ vfmaddpd(xmm10, xmm1, xmm0, xmm10)\ vfmaddpd(xmm11, xmm2, xmm0, xmm11)\ vfmaddpd(xmm12, xmm3, xmm0, xmm12)\ vmovddup(mem(rax, 3*8), xmm0)\ vfmaddpd(xmm13, xmm1, xmm0, xmm13)\ vmovaps(mem(rbx, 6*8), xmm1)\ vfmaddpd(xmm14, xmm2, xmm0, xmm14)\ vmovaps(mem(rbx, 8*8), xmm2)\ vfmaddpd(xmm15, xmm3, xmm0, xmm15)\ vmovaps(mem(rbx, 10*8), xmm3) #define KERNEL4x6_4(xx) \ vmovddup(mem(rax, 4*8), xmm0)\ vfmaddpd(xmm4, xmm1, xmm0, xmm4)\ prefetch(0, mem(rax, 224))\ vfmaddpd(xmm5, xmm2, xmm0, xmm5)\ vfmaddpd(xmm6, xmm3, xmm0, xmm6)\ vmovddup(mem(rax, 5*8), xmm0)\ vfmaddpd(xmm7, xmm1, xmm0, xmm7)\ vfmaddpd(xmm8, xmm2, xmm0, xmm8)\ vfmaddpd(xmm9, xmm3, xmm0, xmm9)\ vmovddup(mem(rax, 6*8), xmm0)\ vfmaddpd(xmm10, xmm1, xmm0, xmm10)\ vfmaddpd(xmm11, xmm2, xmm0, xmm11)\ vfmaddpd(xmm12, xmm3, xmm0, xmm12)\ vmovddup(mem(rax, 7*8), xmm0)\ vfmaddpd(xmm13, xmm1, xmm0, xmm13)\ vmovaps(mem(rbx, 12*8), xmm1)\ vfmaddpd(xmm14, xmm2, xmm0, xmm14)\ vmovaps(mem(rbx, 14*8), xmm2)\ vfmaddpd(xmm15, xmm3, xmm0, xmm15)\ add(imm(16*8), rax)\ vmovaps(mem(rbx, 16*8), xmm3)\ add(imm(24*8), rbx) void bli_dgemm_bulldozer_asm_4x6_fma4 ( dim_t m, dim_t n, dim_t k, double* restrict alpha, double* restrict a, double* restrict b, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k / 12; uint64_t k_left = k % 12; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; GEMM_UKR_SETUP_CT_ANY( d, 4, 6, false ); begin_asm() vzeroall() mov(var(b), rbx) // load address of b. mov(var(a), rax) // load address of a. prefetch(0, mem(rax, 64)) vmovaps(mem(rbx, 0*8), xmm1) vmovaps(mem(rbx, 2*8), xmm2) vmovaps(mem(rbx, 4*8), xmm3) add(imm(12*8), rbx) add(imm(8*8), rax) mov(var(k_iter), rsi) // i = k_iter; notice var(k_iter) not $0 test(rsi, rsi) je(.CONSIDERKLEFT) ALIGN32 label(.LOOPKITER) // MAIN LOOP KERNEL4x6_1(xx) KERNEL4x6_2(xx) KERNEL4x6_3(xx) KERNEL4x6_4(xx) KERNEL4x6_1(xx) KERNEL4x6_2(xx) KERNEL4x6_3(xx) KERNEL4x6_4(xx) KERNEL4x6_1(xx) KERNEL4x6_2(xx) KERNEL4x6_3(xx) KERNEL4x6_4(xx) dec(rsi) jne(.LOOPKITER) label(.CONSIDERKLEFT) mov(var(k_left), rsi) test(rsi, rsi) label(.LOOPKLEFT) je(.POSTACCUM) KERNEL4x6_1(xx) add(imm(6*8), rbx) add(imm(4*8), rax) dec(rsi) jmp(.LOOPKLEFT) // iterate again if i != 0. label(.POSTACCUM) mov(var(rs_c), rsi) // load cs_c mov(var(cs_c), rdi) // load rs_c vmovddup(mem(var(alpha)), xmm2) //load alpha vmovddup(mem(var(beta)), xmm3) //load beta mov(var(c), rcx) // load address of c sal(imm(3), rsi) // cs_c *= sizeof(double) sal(imm(3), rdi) // rs_c *= sizeof(double) lea(mem(rcx, rdi, 2), rdx) vmovlpd(mem(rcx), xmm0, xmm0) vmovlpd(mem(rdx), xmm1, xmm1) vmovhpd(mem(rcx, rdi, 1), xmm0, xmm0) vmovhpd(mem(rdx, rdi, 1), xmm1, xmm1) lea(mem(rdx, rdi, 2), r8) vmulpd(xmm2, xmm4, xmm4) // scale by alpha, vmulpd(xmm2, xmm5, xmm5) // scale by alpha, vfmaddpd(xmm4, xmm0, xmm3, xmm4) // scale by beta, and add the gemm result vmovlpd(mem(r8), xmm0, xmm0) vfmaddpd(xmm5, xmm1, xmm3, xmm5) // scale by beta, and add the gemm result vmovhpd(mem(r8, rdi, 1), xmm0, xmm0) vmovlpd(xmm4, mem(rcx)) // and store back to memory. vmovlpd(xmm5, mem(rdx)) // and store back to memory. vmovhpd(xmm4, mem(rcx, rdi, 1)) add(rsi, rcx) vmovhpd(xmm5, mem(rdx, rdi, 1)) add(rsi, rdx) vmulpd(xmm2, xmm6, xmm6) // scale by alpha, vfmaddpd(xmm6, xmm0, xmm3, xmm6) // scale by beta, and add the gemm result vmovlpd(xmm6, mem(r8)) // and store back to memory. vmovhpd(xmm6, mem(r8, rdi, 1)) add(rsi, r8) vmovlpd(mem(rcx), xmm0, xmm0) vmovlpd(mem(rdx), xmm1, xmm1) vmovlpd(mem(r8), xmm4, xmm4) vmovhpd(mem(rcx, rdi, 1), xmm0, xmm0) vmovhpd(mem(rdx, rdi, 1), xmm1, xmm1) vmovhpd(mem(r8, rdi, 1), xmm4, xmm4) vmulpd(xmm2, xmm7, xmm7) // scale by alpha, vmulpd(xmm2, xmm8, xmm8) // scale by alpha, vmulpd(xmm2, xmm9, xmm9) // scale by alpha, vfmaddpd(xmm7, xmm0, xmm3, xmm7) // scale by beta, and add the gemm result vfmaddpd(xmm8, xmm1, xmm3, xmm8) // scale by beta, and add the gemm result vfmaddpd(xmm9, xmm4, xmm3, xmm9) // scale by beta, and add the gemm result vmovlpd(xmm7, mem(rcx)) // and store back to memory. vmovlpd(xmm8, mem(rdx)) // and store back to memory. vmovlpd(xmm9, mem(r8)) // and store back to memory. vmovhpd(xmm7, mem(rcx, rdi, 1)) add(rsi, rcx) vmovhpd(xmm8, mem(rdx, rdi, 1)) add(rsi, rdx) vmovhpd(xmm9, mem(r8, rdi, 1)) add(rsi, r8) vmovlpd(mem(rcx), xmm0, xmm0) vmovlpd(mem(rdx), xmm1, xmm1) vmovlpd(mem(r8), xmm4, xmm4) vmovhpd(mem(rcx, rdi, 1), xmm0, xmm0) vmovhpd(mem(rdx, rdi, 1), xmm1, xmm1) vmovhpd(mem(r8, rdi, 1), xmm4, xmm4) vmulpd(xmm2, xmm10, xmm10) // scale by alpha, vmulpd(xmm2, xmm11, xmm11) // scale by alpha, vmulpd(xmm2, xmm12, xmm12) // scale by alpha, vfmaddpd(xmm10, xmm0, xmm3, xmm10) // scale by beta, and add the gemm result vfmaddpd(xmm11, xmm1, xmm3, xmm11) // scale by beta, and add the gemm result vfmaddpd(xmm12, xmm4, xmm3, xmm12) // scale by beta, and add the gemm result vmovlpd(xmm10, mem(rcx)) // and store back to memory. vmovlpd(xmm11, mem(rdx)) // and store back to memory. vmovlpd(xmm12, mem(r8)) // and store back to memory. vmovhpd(xmm10, mem(rcx, rdi, 1)) add(rsi, rcx) vmovhpd(xmm11, mem(rdx, rdi, 1)) add(rsi, rdx) vmovhpd(xmm12, mem(r8, rdi, 1)) add(rsi, r8) vmovlpd(mem(rcx), xmm0, xmm0) vmovlpd(mem(rdx), xmm1, xmm1) vmovlpd(mem(r8), xmm4, xmm4) vmovhpd(mem(rcx, rdi, 1), xmm0, xmm0) vmovhpd(mem(rdx, rdi, 1), xmm1, xmm1) vmovhpd(mem(r8, rdi, 1), xmm4, xmm4) vmulpd(xmm2, xmm13, xmm13) // scale by alpha, vmulpd(xmm2, xmm14, xmm14) // scale by alpha, vmulpd(xmm2, xmm15, xmm15) // scale by alpha, vfmaddpd(xmm13, xmm0, xmm3, xmm13) // scale by beta, and add the gemm result vfmaddpd(xmm14, xmm1, xmm3, xmm14) // scale by beta, and add the gemm result vfmaddpd(xmm15, xmm4, xmm3, xmm15) // scale by beta, and add the gemm result vmovlpd(xmm13, mem(rcx)) // and store back to memory. vmovlpd(xmm14, mem(rdx)) // and store back to memory. vmovlpd(xmm15, mem(r8)) // and store back to memory. vmovhpd(xmm13, mem(rcx, rdi, 1)) vmovhpd(xmm14, mem(rdx, rdi, 1)) vmovhpd(xmm15, mem(r8, rdi, 1)) end_asm( : // output operands (none) : // input operands [k_iter] "r" (k_iter), // 0 [k_left] "r" (k_left), // 1 [a] "r" (a), // 2 [b] "r" (b), // 3 [alpha] "r" (alpha), // 4 [beta] "r" (beta), // 5 [c] "r" (c), // 6 [rs_c] "m" (rs_c), // 7 [cs_c] "m" (cs_c)/*, // 8 [b_next] "m" (b_next), // 9 [a_next] "m" (a_next)*/ // 10 : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) GEMM_UKR_FLUSH_CT( d ); } //The parameter "i" is the iteration number, i.e. the B values to read #define MADD_TO_YMM(i) \ vfmaddps(ymm15, ymm0, ymm2, ymm15)\ vperm2f128(imm(0x3), ymm2, ymm2, ymm4)\ vfmaddps(ymm13, ymm0, ymm3, ymm13)\ vperm2f128(imm(0x3), ymm3, ymm3, ymm5)\ vfmaddps(ymm14, ymm1, ymm2, ymm14)\ vmovshdup(mem(rbx, i*32), ymm2)\ vfmaddps(ymm12, ymm1, ymm3, ymm12)\ vpermilps(imm(0x4e), ymm2, ymm3)\ vfmaddps(ymm11, ymm0, ymm4, ymm11)\ vfmaddps(ymm9, ymm0, ymm5, ymm9)\ vpermilps(imm(0xb1), ymm0, ymm0)\ vfmaddps(ymm10, ymm1, ymm4, ymm10)\ vperm2f128(imm(0x3), ymm2, ymm2, ymm4)\ vfmaddps(ymm8, ymm1, ymm5, ymm8)\ vperm2f128(imm(0x3), ymm3, ymm3, ymm5)\ void bli_cgemm_bulldozer_asm_8x4_fma4 ( dim_t m, dim_t n, dim_t k, scomplex* restrict alpha, scomplex* restrict a, scomplex* restrict b, scomplex* restrict beta, scomplex* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k / 4; uint64_t k_left = k % 4; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; GEMM_UKR_SETUP_CT_ALIGNED( c, 8, 4, false, 32 ); begin_asm() mov(var(a), rax) // load address of a. mov(var(b), rbx) // load address of b. mov(var(b_next), r15) // load address of b_next. //mov(var(a_next), r14) // load address of a_next. sub(imm(4*64), r15) vmovaps(mem(rax, 0*32), ymm0) // initialize loop by pre-loading vmovsldup(mem(rbx, 0*32), ymm2) vpermilps(imm(0x4e), ymm2, ymm3) mov(var(c), rcx) // load address of c mov(var(cs_c), rdi) // load cs_c lea(mem(, rdi, 8), rdi) // cs_c *= sizeof(scomplex) lea(mem(rcx, rdi, 2), r10) // load address of c + 2*cs_c; prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rdi, 1, 3*8)) // prefetch c + 1*cs_c prefetch(0, mem(r10, 3*8)) // prefetch c + 2*cs_c prefetch(0, mem(r10, rdi, 1, 3*8)) // prefetch c + 3*cs_c vxorps(ymm8, ymm8, ymm8) vxorps(ymm9, ymm9, ymm9) vxorps(ymm10, ymm10, ymm10) vxorps(ymm11, ymm11, ymm11) vxorps(ymm12, ymm12, ymm12) vxorps(ymm13, ymm13, ymm13) vxorps(ymm14, ymm14, ymm14) vxorps(ymm15, ymm15, ymm15) mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.CCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.CLOOPKITER) // MAIN LOOP add(imm(4*4*8), r15) // b_next += 4*4 (unroll x nr) // iteration 0 prefetch(0, mem(rax, 8*32)) vmovaps(mem(rax, 1*32), ymm1) MADD_TO_YMM(0) vpermilps(imm(0xb1), ymm1, ymm1) vmulps(ymm0, ymm2, ymm6) vaddsubps(ymm6, ymm15, ymm15) vmulps(ymm0, ymm3, ymm7) vaddsubps(ymm7, ymm13, ymm13) vmulps(ymm1, ymm2, ymm6) vmovsldup(mem(rbx, 1*32), ymm2) vmulps(ymm1, ymm3, ymm7) vpermilps(imm(0x4e), ymm2, ymm3) vaddsubps(ymm6, ymm14, ymm14) vaddsubps(ymm7, ymm12, ymm12) vmulps(ymm0, ymm4, ymm6) vmulps(ymm0, ymm5, ymm7) vmovaps(mem(rax, 2*32), ymm0) vaddsubps(ymm6, ymm11, ymm11) vaddsubps(ymm7, ymm9, ymm9) vmulps(ymm1, ymm4, ymm6) vmulps(ymm1, ymm5, ymm7) vaddsubps(ymm6, ymm10, ymm10) vaddsubps(ymm7, ymm8, ymm8) // iteration 1 prefetch(0, mem(rax, 10*32)) vmovaps(mem(rax, 3*32), ymm1) MADD_TO_YMM(1) vpermilps(imm(0xb1), ymm1, ymm1) vmulps(ymm0, ymm2, ymm6) vmulps(ymm0, ymm3, ymm7) vaddsubps(ymm6, ymm15, ymm15) vaddsubps(ymm7, ymm13, ymm13) vmulps(ymm1, ymm2, ymm6) vmovsldup(mem(rbx, 2*32), ymm2) vmulps(ymm1, ymm3, ymm7) vpermilps(imm(0x4e), ymm2, ymm3) vaddsubps(ymm6, ymm14, ymm14) vaddsubps(ymm7, ymm12, ymm12) vmulps(ymm0, ymm4, ymm6) vmulps(ymm0, ymm5, ymm7) vmovaps(mem(rax, 4*32), ymm0) vaddsubps(ymm6, ymm11, ymm11) vaddsubps(ymm7, ymm9, ymm9) vmulps(ymm1, ymm4, ymm6) vmulps(ymm1, ymm5, ymm7) vaddsubps(ymm6, ymm10, ymm10) vaddsubps(ymm7, ymm8, ymm8) // iteration 2 prefetch(0, mem(rax, 12*32)) vmovaps(mem(rax, 5*32), ymm1) MADD_TO_YMM(2) prefetch(0, mem(r15, 2*32)) // prefetch b_next[2*4] vpermilps(imm(0xb1), ymm1, ymm1) vmulps(ymm0, ymm2, ymm6) vmulps(ymm0, ymm3, ymm7) vaddsubps(ymm6, ymm15, ymm15) vaddsubps(ymm7, ymm13, ymm13) vmulps(ymm1, ymm2, ymm6) vmovsldup(mem(rbx, 3*32), ymm2) vmulps(ymm1, ymm3, ymm7) vpermilps(imm(0x4e), ymm2, ymm3) vaddsubps(ymm6, ymm14, ymm14) vaddsubps(ymm7, ymm12, ymm12) vmulps(ymm0, ymm4, ymm6) vmulps(ymm0, ymm5, ymm7) vmovaps(mem(rax, 6*32), ymm0) vaddsubps(ymm6, ymm11, ymm11) vaddsubps(ymm7, ymm9, ymm9) vmulps(ymm1, ymm4, ymm6) vmulps(ymm1, ymm5, ymm7) vaddsubps(ymm6, ymm10, ymm10) vaddsubps(ymm7, ymm8, ymm8) // iteration 3 prefetch(0, mem(rax, 14*32)) vmovaps(mem(rax, 7*32), ymm1) MADD_TO_YMM(3) vpermilps(imm(0xb1), ymm1, ymm1) vmulps(ymm0, ymm2, ymm6) vmulps(ymm0, ymm3, ymm7) vaddsubps(ymm6, ymm15, ymm15) vaddsubps(ymm7, ymm13, ymm13) vmulps(ymm1, ymm2, ymm6) vmovsldup(mem(rbx, 4*32), ymm2) vmulps(ymm1, ymm3, ymm7) vpermilps(imm(0x4e), ymm2, ymm3) vaddsubps(ymm6, ymm14, ymm14) vaddsubps(ymm7, ymm12, ymm12) vmulps(ymm0, ymm4, ymm6) vmulps(ymm0, ymm5, ymm7) vmovaps(mem(rax, 8*32), ymm0) vaddsubps(ymm6, ymm11, ymm11) vaddsubps(ymm7, ymm9, ymm9) vmulps(ymm1, ymm4, ymm6) vmulps(ymm1, ymm5, ymm7) vaddsubps(ymm6, ymm10, ymm10) vaddsubps(ymm7, ymm8, ymm8) add(imm(8*4*8), rax) // a += 8*4 (unroll x mr) add(imm(4*4*8), rbx) // b += 4*4 (unroll x nr) dec(rsi) // i -= 1; jne(.CLOOPKITER) // iterate again if i != 0. label(.CCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.CPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.CLOOPKLEFT) // EDGE LOOP // iteration 0 prefetch(0, mem(rax, 8*32)) vmovaps(mem(rax, 1*32), ymm1) MADD_TO_YMM(0) vpermilps(imm(0xb1), ymm1, ymm1) vmulps(ymm0, ymm2, ymm6) vmulps(ymm0, ymm3, ymm7) vaddsubps(ymm6, ymm15, ymm15) vaddsubps(ymm7, ymm13, ymm13) vmulps(ymm1, ymm2, ymm6) vmovsldup(mem(rbx, 1*32), ymm2) vmulps(ymm1, ymm3, ymm7) vpermilps(imm(0x4e), ymm2, ymm3) vaddsubps(ymm6, ymm14, ymm14) vaddsubps(ymm7, ymm12, ymm12) vmulps(ymm0, ymm4, ymm6) vmulps(ymm0, ymm5, ymm7) vmovaps(mem(rax, 2*32), ymm0) vaddsubps(ymm6, ymm11, ymm11) vaddsubps(ymm7, ymm9, ymm9) vmulps(ymm1, ymm4, ymm6) vmulps(ymm1, ymm5, ymm7) vaddsubps(ymm6, ymm10, ymm10) vaddsubps(ymm7, ymm8, ymm8) add(imm(8*1*8), rax) // a += 8 (1 x mr) add(imm(4*1*8), rbx) // b += 4 (1 x nr) dec(rsi) // i -= 1; jne(.CLOOPKLEFT) // iterate again if i != 0. label(.CPOSTACCUM) // ymm15: ymm13: ymm11: ymm9: // ( ab00 ( ab01 ( ab02 ( ab03 // ab10 ab11 ab12 ab13 // ab21 ab20 ab23 ab22 // ab31 ab30 ab33 ab32 // ab42 ab43 ab40 ab41 // ab52 ab53 ab50 ab51 // ab63 ab62 ab61 ab60 // ab73 ) ab72 ) ab71 ) ab70 ) // ymm14: ymm12: ymm10: ymm8: // ( ab80 ( ab81 ( ab82 ( ab83 // ab90 ab91 ab92 ab93 // aba1 aba0 aba3 aba2 // abb1 abb0 abb3 abb2 // abc2 abc3 abc0 abc1 // abd2 abd3 abd0 abd1 // abe3 abe2 abe1 abe0 // abf3 abf2 abf1 abf0 ) GROUP_YMM_BY_4 // ymm15: ymm13: ymm11: ymm9: // ( ab00 ( ab01 ( ab02 ( ab03 // ab10 ab11 ab12 ab13 // ab20 ab21 ab22 ab23 // ab30 ab31 ab32 ab33 // ab42 ab43 ab40 ab41 // ab52 ab53 ab50 ab51 // ab62 ab63 ab60 ab61 // ab72 ) ab73 ) ab70 ) ab71 ) // ymm14: ymm12: ymm10: ymm8: // ( ab80 ( ab81 ( ab82 ( ab83 // ab90 ab91 ab92 ab93 // aba0 aba1 aba2 aba3 // abb0 abb1 abb2 abb3 // abc2 abc3 abc0 abc1 // abd2 abd3 abd0 abd1 // abe2 abe3 abe0 abe1 // abf2 ) abf3 ) abf0 ) abf1 ) // ymm15: ymm13: ymm11: ymm9: // ( ab00 ( ab01 ( ab02 ( ab03 // ab10 ab11 ab12 ab13 // ab20 ab21 ab22 ab23 // ab30 ab31 ab32 ab33 // ab40 ab41 ab42 ab43 // ab50 ab51 ab52 ab53 // ab60 ab61 ab62 ab63 // ab70 ) ab71 ) ab72 ) ab73 ) // ymm14: ymm12: ymm10: ymm8: // ( ab80 ( ab81 ( ab82 ( ab83 // ab90 ab91 ab92 ab93 // aba0 aba1 aba2 aba3 // abb0 abb1 abb2 abb3 // abc0 abc1 abc2 abc3 // abd0 abd1 abd2 abd3 // abe0 abe1 abe2 abe3 // abf0 ) abf1 ) abf2 ) abf3 ) // scale by alpha mov(var(alpha), rax) // load address of alpha vbroadcastss(mem(rax), ymm7) // load alpha_r and duplicate vbroadcastss(mem(rax, 4), ymm6) // load alpha_i and duplicate vpermilps(imm(0xb1), ymm15, ymm3) vmulps(ymm7, ymm15, ymm15) vmulps(ymm6, ymm3, ymm3) vaddsubps(ymm3, ymm15, ymm15) vpermilps(imm(0xb1), ymm14, ymm2) vmulps(ymm7, ymm14, ymm14) vmulps(ymm6, ymm2, ymm2) vaddsubps(ymm2, ymm14, ymm14) vpermilps(imm(0xb1), ymm13, ymm1) vmulps(ymm7, ymm13, ymm13) vmulps(ymm6, ymm1, ymm1) vaddsubps(ymm1, ymm13, ymm13) vpermilps(imm(0xb1), ymm12, ymm0) vmulps(ymm7, ymm12, ymm12) vmulps(ymm6, ymm0, ymm0) vaddsubps(ymm0, ymm12, ymm12) vpermilps(imm(0xb1), ymm11, ymm3) vmulps(ymm7, ymm11, ymm11) vmulps(ymm6, ymm3, ymm3) vaddsubps(ymm3, ymm11, ymm11) vpermilps(imm(0xb1), ymm10, ymm2) vmulps(ymm7, ymm10, ymm10) vmulps(ymm6, ymm2, ymm2) vaddsubps(ymm2, ymm10, ymm10) vpermilps(imm(0xb1), ymm9, ymm1) vmulps(ymm7, ymm9, ymm9) vmulps(ymm6, ymm1, ymm1) vaddsubps(ymm1, ymm9, ymm9) vpermilps(imm(0xb1), ymm8, ymm0) vmulps(ymm7, ymm8, ymm8) vmulps(ymm6, ymm0, ymm0) vaddsubps(ymm0, ymm8, ymm8) mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rbx), ymm7) // load beta_r and duplicate vbroadcastss(mem(rbx, 4), ymm6) // load beta_i and duplicate // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm7) // set ZF if beta_r == 0. sete(r8b) // r8b = ( ZF == 1 ? 1 : 0 ); vucomiss(xmm0, xmm6) // set ZF if beta_i == 0. sete(r9b) // r9b = ( ZF == 1 ? 1 : 0 ); and(r8b, r9b) // set ZF if r8b & r9b == 1. jne(.CBETAZERO) // if ZF = 0, jump to beta == 0 case // update c00:c70 vmovaps(mem(rcx), ymm0) // load c00:c70 into ymm0 vpermilps(imm(0xb1), ymm0, ymm2) // scale ymm0 by beta vmulps(ymm7, ymm0, ymm0) vmulps(ymm6, ymm2, ymm2) vaddsubps(ymm2, ymm0, ymm0) vaddps(ymm15, ymm0, ymm0) // add the gemm result to ymm0 vmovaps(ymm0, mem(rcx)) // store c00:c70 // update c80:cf0 vmovaps(mem(rcx,32), ymm0) // load c80:f0 into ymm0 vpermilps(imm(0xb1), ymm0, ymm2) // scale ymm0 by beta vmulps(ymm7, ymm0, ymm0) vmulps(ymm6, ymm2, ymm2) vaddsubps(ymm2, ymm0, ymm0) vaddps(ymm14, ymm0, ymm0) // add the gemm result to ymm0 vmovaps(ymm0, mem(rcx,32)) // store c80:cf0 add(rdi, rcx) // c += cs_c; // update c00:c70 vmovaps(mem(rcx), ymm0) // load c01:c71 into ymm0 vpermilps(imm(0xb1), ymm0, ymm2) // scale ymm0 by beta vmulps(ymm7, ymm0, ymm0) vmulps(ymm6, ymm2, ymm2) vaddsubps(ymm2, ymm0, ymm0) vaddps(ymm13, ymm0, ymm0) // add the gemm result to ymm0 vmovaps(ymm0, mem(rcx)) // store c01:c71 // update c81:cf1 vmovaps(mem(rcx,32), ymm0) // load c81:f1 into ymm0 vpermilps(imm(0xb1), ymm0, ymm2) // scale ymm0 by beta vmulps(ymm7, ymm0, ymm0) vmulps(ymm6, ymm2, ymm2) vaddsubps(ymm2, ymm0, ymm0) vaddps(ymm12, ymm0, ymm0) // add the gemm result to ymm0 vmovaps(ymm0, mem(rcx,32)) // store c81:cf1 add(rdi, rcx) // c += cs_c; // update c02:c72 vmovaps(mem(rcx), ymm0) // load c02:c72 into ymm0 vpermilps(imm(0xb1), ymm0, ymm2) // scale ymm0 by beta vmulps(ymm7, ymm0, ymm0) vmulps(ymm6, ymm2, ymm2) vaddsubps(ymm2, ymm0, ymm0) vaddps(ymm11, ymm0, ymm0) // add the gemm result to ymm0 vmovaps(ymm0, mem(rcx)) // store c02:c72 // update c82:cf2 vmovaps(mem(rcx,32), ymm0) // load c82:f2 into ymm0 vpermilps(imm(0xb1), ymm0, ymm2) // scale ymm0 by beta vmulps(ymm7, ymm0, ymm0) vmulps(ymm6, ymm2, ymm2) vaddsubps(ymm2, ymm0, ymm0) vaddps(ymm10, ymm0, ymm0) // add the gemm result to ymm0 vmovaps(ymm0, mem(rcx,32)) // store c82:cf2 add(rdi, rcx) // c += cs_c; // update c03:c73 vmovaps(mem(rcx), ymm0) // load c03:c73 into ymm0 vpermilps(imm(0xb1), ymm0, ymm2) // scale ymm0 by beta vmulps(ymm7, ymm0, ymm0) vmulps(ymm6, ymm2, ymm2) vaddsubps(ymm2, ymm0, ymm0) vaddps(ymm9, ymm0, ymm0) // add the gemm result to ymm0 vmovaps(ymm0, mem(rcx)) // store c03:c73 // update c83:cf3 vmovaps(mem(rcx,32), ymm0) // load c83:f3 into ymm0 vpermilps(imm(0xb1), ymm0, ymm2) // scale ymm0 by beta vmulps(ymm7, ymm0, ymm0) vmulps(ymm6, ymm2, ymm2) vaddsubps(ymm2, ymm0, ymm0) vaddps(ymm8, ymm0, ymm0) // add the gemm result to ymm0 vmovaps(ymm0, mem(rcx,32)) // store c83:cf3 //add(rdi, rcx) // c += cs_c; jmp(.CDONE) // jump to end. label(.CBETAZERO) vmovaps(ymm15, mem(rcx)) // store c00:c70 vmovaps(ymm14, mem(rcx,32)) // store c80:cf0 add(rdi, rcx) // c += cs_c; vmovaps(ymm13, mem(rcx)) // store c01:c71 vmovaps(ymm12, mem(rcx,32)) // store c81:cf1 add(rdi, rcx) // c += cs_c; vmovaps(ymm11, mem(rcx)) // store c02:c72 vmovaps(ymm10, mem(rcx,32)) // store c82:cf2 add(rdi, rcx) // c += cs_c; vmovaps(ymm9, mem(rcx)) // store c03:c73 vmovaps(ymm8, mem(rcx,32)) // store c83:cf3 add(rdi, rcx) // c += cs_c; label(.CDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), // 0 [k_left] "m" (k_left), // 1 [a] "m" (a), // 2 [b] "m" (b), // 3 [alpha] "m" (alpha), // 4 [beta] "m" (beta), // 5 [c] "m" (c), // 6 [rs_c] "m" (rs_c), // 7 [cs_c] "m" (cs_c), // 8 [b_next] "m" (b_next)/*, // 9 [a_next] "m" (a_next)*/ // 10 : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "ymm0", "ymm1", "ymm2", "ymm3", "ymm4", "ymm5", "ymm6", "ymm7", "ymm8", "ymm9", "ymm10", "ymm11", "ymm12", "ymm13", "ymm14", "ymm15", "memory" ) GEMM_UKR_FLUSH_CT( c ); } #define MADDSUBPD_TO_YMM \ vfmaddpd(ymm13, ymm0, ymm4, ymm13)\ vfmaddpd(ymm9, ymm0, ymm5, ymm9)\ vpermilpd(imm(0x5), ymm0, ymm0)\ \ vfmaddpd(ymm12, ymm1, ymm4, ymm12)\ vperm2f128(imm(0x3), ymm2, ymm2, ymm4)\ vfmaddpd(ymm8, ymm1, ymm5, ymm8)\ vperm2f128(imm(0x3), ymm3, ymm3, ymm5)\ \ vpermilpd(imm(0x5), ymm1, ymm1)\ vmulpd(ymm0, ymm2, ymm6)\ vmulpd(ymm0, ymm3, ymm7)\ vaddsubpd(ymm6, ymm15, ymm15)\ vaddsubpd(ymm7, ymm11, ymm11)\ \ #define Z_ALPHA(i, j) \ vpermilpd(imm(0x5), ymm(i), ymm(j))\ vmulpd(ymm7, ymm(i), ymm(i))\ vmulpd(ymm6, ymm(j), ymm(j))\ vaddsubpd(ymm(j), ymm(i), ymm(i))\ void bli_zgemm_bulldozer_asm_4x4_fma4 ( dim_t m, dim_t n, dim_t k, dcomplex* restrict alpha, dcomplex* restrict a, dcomplex* restrict b, dcomplex* restrict beta, dcomplex* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k / 4; uint64_t k_left = k % 4; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; GEMM_UKR_SETUP_CT_ALIGNED( z, 4, 4, false, 32 ); begin_asm() mov(var(a), rax) // load address of a. mov(var(b), rbx) // load address of b. //mov(var(b_next), r15) // load address of b_next. //mov(var(a_next), r14) // load address of a_next. vmovapd(mem(rax, 0*32), ymm0) // initialize loop by pre-loading vmovddup(mem(rbx, 0+0*32), ymm2) vmovddup(mem(rbx, 0+1*32), ymm3) mov(var(c), rcx) // load address of c mov(var(cs_c), rdi) // load cs_c lea(mem(, rdi, 8), rdi) // cs_c *= sizeof(dcomplex) lea(mem(, rdi, 2), rdi) lea(mem(rcx, rdi, 2), r10) // load address of c + 2*cs_c; prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rdi, 1, 3*8)) // prefetch c + 1*cs_c prefetch(0, mem(r10, 3*8)) // prefetch c + 2*cs_c prefetch(0, mem(r10, rdi, 1, 3*8)) // prefetch c + 3*cs_c vxorpd(ymm8, ymm8, ymm8) vxorpd(ymm9, ymm9, ymm9) vxorpd(ymm10, ymm10, ymm10) vxorpd(ymm11, ymm11, ymm11) vxorpd(ymm12, ymm12, ymm12) vxorpd(ymm13, ymm13, ymm13) vxorpd(ymm14, ymm14, ymm14) vxorpd(ymm15, ymm15, ymm15) mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.ZCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.ZLOOPKITER) // MAIN LOOP // iteration 0 vmovapd(mem(rax, 1*32), ymm1) vfmaddpd(ymm15, ymm0, ymm2, ymm15) vperm2f128(imm(0x3), ymm2, ymm2, ymm4) vfmaddpd(ymm11, ymm0, ymm3, ymm11) vperm2f128(imm(0x3), ymm3, ymm3, ymm5) prefetch(0, mem(rax, 16*32)) vfmaddpd(ymm14, ymm1, ymm2, ymm14) vmovddup(mem(rbx, 8+0*32), ymm2) vfmaddpd(ymm10, ymm1, ymm3, ymm10) vmovddup(mem(rbx, 8+1*32), ymm3) MADDSUBPD_TO_YMM vmulpd(ymm1, ymm2, ymm6) vmovddup(mem(rbx, 0+2*32), ymm2) vmulpd(ymm1, ymm3, ymm7) vmovddup(mem(rbx, 0+3*32), ymm3) vaddsubpd(ymm6, ymm14, ymm14) vaddsubpd(ymm7, ymm10, ymm10) vmulpd(ymm0, ymm4, ymm6) vmulpd(ymm0, ymm5, ymm7) vmovapd(mem(rax, 2*32), ymm0) vaddsubpd(ymm6, ymm13, ymm13) vaddsubpd(ymm7, ymm9, ymm9) vmulpd(ymm1, ymm4, ymm6) vmulpd(ymm1, ymm5, ymm7) vaddsubpd(ymm6, ymm12, ymm12) vaddsubpd(ymm7, ymm8, ymm8) // iteration 1 vmovapd(mem(rax, 3*32), ymm1) vfmaddpd(ymm15, ymm0, ymm2, ymm15) vperm2f128(imm(0x3), ymm2, ymm2, ymm4) vfmaddpd(ymm11, ymm0, ymm3, ymm11) vperm2f128(imm(0x3), ymm3, ymm3, ymm5) prefetch(0, mem(rax, 18*32)) vfmaddpd(ymm14, ymm1, ymm2, ymm14) vmovddup(mem(rbx, 8+2*32), ymm2) vfmaddpd(ymm10, ymm1, ymm3, ymm10) vmovddup(mem(rbx, 8+3*32), ymm3) MADDSUBPD_TO_YMM vmulpd(ymm1, ymm2, ymm6) vmovddup(mem(rbx, 0+4*32), ymm2) vmulpd(ymm1, ymm3, ymm7) vmovddup(mem(rbx, 0+5*32), ymm3) vaddsubpd(ymm6, ymm14, ymm14) vaddsubpd(ymm7, ymm10, ymm10) vmulpd(ymm0, ymm4, ymm6) vmulpd(ymm0, ymm5, ymm7) vmovapd(mem(rax, 4*32), ymm0) vaddsubpd(ymm6, ymm13, ymm13) vaddsubpd(ymm7, ymm9, ymm9) vmulpd(ymm1, ymm4, ymm6) vmulpd(ymm1, ymm5, ymm7) vaddsubpd(ymm6, ymm12, ymm12) vaddsubpd(ymm7, ymm8, ymm8) // iteration 2 vmovapd(mem(rax, 5*32), ymm1) vfmaddpd(ymm15, ymm0, ymm2, ymm15) vperm2f128(imm(0x3), ymm2, ymm2, ymm4) vfmaddpd(ymm11, ymm0, ymm3, ymm11) vperm2f128(imm(0x3), ymm3, ymm3, ymm5) prefetch(0, mem(rax, 20*32)) vfmaddpd(ymm14, ymm1, ymm2, ymm14) vmovddup(mem(rbx, 8+4*32), ymm2) vfmaddpd(ymm10, ymm1, ymm3, ymm10) vmovddup(mem(rbx, 8+5*32), ymm3) MADDSUBPD_TO_YMM vmulpd(ymm1, ymm2, ymm6) vmovddup(mem(rbx, 0+6*32), ymm2) vmulpd(ymm1, ymm3, ymm7) vmovddup(mem(rbx, 0+7*32), ymm3) vaddsubpd(ymm6, ymm14, ymm14) vaddsubpd(ymm7, ymm10, ymm10) vmulpd(ymm0, ymm4, ymm6) vmulpd(ymm0, ymm5, ymm7) vmovapd(mem(rax, 6*32), ymm0) vaddsubpd(ymm6, ymm13, ymm13) vaddsubpd(ymm7, ymm9, ymm9) vmulpd(ymm1, ymm4, ymm6) vmulpd(ymm1, ymm5, ymm7) vaddsubpd(ymm6, ymm12, ymm12) vaddsubpd(ymm7, ymm8, ymm8) // iteration 3 vmovapd(mem(rax, 7*32), ymm1) vfmaddpd(ymm15, ymm0, ymm2, ymm15) vperm2f128(imm(0x3), ymm2, ymm2, ymm4) vfmaddpd(ymm11, ymm0, ymm3, ymm11) vperm2f128(imm(0x3), ymm3, ymm3, ymm5) prefetch(0, mem(rax, 22*32)) vfmaddpd(ymm14, ymm1, ymm2, ymm14) vmovddup(mem(rbx, 8+6*32), ymm2) vfmaddpd(ymm10, ymm1, ymm3, ymm10) vmovddup(mem(rbx, 8+7*32), ymm3) MADDSUBPD_TO_YMM vmulpd(ymm1, ymm2, ymm6) vmovddup(mem(rbx, 0+8*32), ymm2) vmulpd(ymm1, ymm3, ymm7) vmovddup(mem(rbx, 0+9*32), ymm3) vaddsubpd(ymm6, ymm14, ymm14) vaddsubpd(ymm7, ymm10, ymm10) vmulpd(ymm0, ymm4, ymm6) vmulpd(ymm0, ymm5, ymm7) vmovapd(mem(rax, 8*32), ymm0) vaddsubpd(ymm6, ymm13, ymm13) vaddsubpd(ymm7, ymm9, ymm9) vmulpd(ymm1, ymm4, ymm6) vmulpd(ymm1, ymm5, ymm7) vaddsubpd(ymm6, ymm12, ymm12) vaddsubpd(ymm7, ymm8, ymm8) add(imm(4*4*16), rbx) // b += 4*4 (unroll x nr) add(imm(4*4*16), rax) // a += 4*4 (unroll x mr) dec(rsi) // i -= 1; jne(.ZLOOPKITER) // iterate again if i != 0. label(.ZCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.ZPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.ZLOOPKLEFT) // EDGE LOOP // iteration 0 vmovapd(mem(rax, 1*32), ymm1) vfmaddpd(ymm15, ymm0, ymm2, ymm15) vperm2f128(imm(0x3), ymm2, ymm2, ymm4) vfmaddpd(ymm11, ymm0, ymm3, ymm11) vperm2f128(imm(0x3), ymm3, ymm3, ymm5) prefetch(0, mem(rax, 16*32)) vfmaddpd(ymm14, ymm1, ymm2, ymm14) vmovddup(mem(rbx, 8+0*32), ymm2) vfmaddpd(ymm10, ymm1, ymm3, ymm10) vmovddup(mem(rbx, 8+1*32), ymm3) MADDSUBPD_TO_YMM vmulpd(ymm1, ymm2, ymm6) vmovddup(mem(rbx, 0+2*32), ymm2) vmulpd(ymm1, ymm3, ymm7) vmovddup(mem(rbx, 0+3*32), ymm3) vaddsubpd(ymm6, ymm14, ymm14) vaddsubpd(ymm7, ymm10, ymm10) vmulpd(ymm0, ymm4, ymm6) vmulpd(ymm0, ymm5, ymm7) vmovapd(mem(rax, 2*32), ymm0) vaddsubpd(ymm6, ymm13, ymm13) vaddsubpd(ymm7, ymm9, ymm9) vmulpd(ymm1, ymm4, ymm6) vmulpd(ymm1, ymm5, ymm7) vaddsubpd(ymm6, ymm12, ymm12) vaddsubpd(ymm7, ymm8, ymm8) add(imm(4*1*16), rax) // a += 4 (1 x mr) add(imm(4*1*16), rbx) // b += 4 (1 x nr) dec(rsi) // i -= 1; jne(.ZLOOPKLEFT) // iterate again if i != 0. label(.ZPOSTACCUM) // ymm15: ymm13: ymm11: ymm9: // ( ab00 ( ab01 ( ab02 ( ab03 // ab10 ab11 ab12 ab13 // ab21 ab20 ab23 ab22 // ab31 ) ab30 ) ab33 ) ab32 ) // ymm14: ymm12: ymm10: ymm8: // ( ab40 ( ab41 ( ab42 ( ab43 // ab50 ab51 ab52 ab53 // ab61 ab60 ab63 ab62 // ab71 ) ab70 ) ab73 ) ab72 ) vmovapd(ymm15, ymm7) vperm2f128(imm(0x12), ymm15, ymm13, ymm15) vperm2f128(imm(0x30), ymm7, ymm13, ymm13) vmovapd(ymm11, ymm7) vperm2f128(imm(0x12), ymm11, ymm9, ymm11) vperm2f128(imm(0x30), ymm7, ymm9, ymm9) vmovapd(ymm14, ymm7) vperm2f128(imm(0x12), ymm14, ymm12, ymm14) vperm2f128(imm(0x30), ymm7, ymm12, ymm12) vmovapd(ymm10, ymm7) vperm2f128(imm(0x12), ymm10, ymm8, ymm10) vperm2f128(imm(0x30), ymm7, ymm8, ymm8) // ymm15: ymm13: ymm11: ymm9: // ( ab00 ( ab01 ( ab02 ( ab03 // ab10 ab11 ab12 ab13 // ab20 ab21 ab22 ab23 // ab30 ) ab31 ) ab32 ) ab33 ) // ymm14: ymm12: ymm10: ymm8: // ( ab40 ( ab41 ( ab42 ( ab43 // ab50 ab51 ab52 ab53 // ab60 ab61 ab62 ab63 // ab70 ) ab71 ) ab72 ) ab73 ) // scale by alpha mov(var(alpha), rax) // load address of alpha vbroadcastsd(mem(rax), ymm7) // load alpha_r and duplicate vbroadcastsd(mem(rax, 8), ymm6) // load alpha_i and duplicate Z_ALPHA(15, 3) Z_ALPHA(14, 2) Z_ALPHA(13, 1) Z_ALPHA(12, 0) Z_ALPHA(11, 3) Z_ALPHA(10, 2) Z_ALPHA(9, 1) Z_ALPHA(8, 0) mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rbx), ymm7) // load beta_r and duplicate vbroadcastsd(mem(rbx, 8), ymm6) // load beta_i and duplicate // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm7) // set ZF if beta_r == 0. sete(r8b) // r8b = ( ZF == 1 ? 1 : 0 ); vucomisd(xmm0, xmm6) // set ZF if beta_i == 0. sete(r9b) // r9b = ( ZF == 1 ? 1 : 0 ); and(r8b, r9b) // set ZF if r8b & r9b == 1. jne(.ZBETAZERO) // if ZF = 0, jump to beta == 0 case // update c00:c30 vmovapd(mem(rcx), ymm0) // load c00:c30 into ymm0 Z_ALPHA(0, 2) // scale ymm0 by beta vaddpd(ymm15, ymm0, ymm0) // add the gemm result to ymm0 vmovapd(ymm0, mem(rcx)) // store c00:c30 // update c40:c70 vmovapd(mem(rcx,32), ymm0) // load c40:c70 into ymm0 Z_ALPHA(0, 2) // scale ymm0 by beta vaddpd(ymm14, ymm0, ymm0) // add the gemm result to ymm0 vmovapd(ymm0, mem(rcx,32)) // store c40:c70 add(rdi, rcx) // c += cs_c; // update c01:c31 vmovapd(mem(rcx), ymm0) // load c01:c31 into ymm0 Z_ALPHA(0, 2) // scale ymm0 by beta vaddpd(ymm13, ymm0, ymm0) // add the gemm result to ymm0 vmovapd(ymm0, mem(rcx)) // store c01:c31 // update c41:c71 vmovapd(mem(rcx,32), ymm0) // load c41:c71 into ymm0 Z_ALPHA(0, 2) // scale ymm0 by beta vaddpd(ymm12, ymm0, ymm0) // add the gemm result to ymm0 vmovapd(ymm0, mem(rcx,32)) // store c41:c71 add(rdi, rcx) // c += cs_c; // update c02:c32 vmovapd(mem(rcx), ymm0) // load c02:c32 into ymm0 Z_ALPHA(0, 2) // scale ymm0 by beta vaddpd(ymm11, ymm0, ymm0) // add the gemm result to ymm0 vmovapd(ymm0, mem(rcx)) // store c02:c32 // update c42:c72 vmovapd(mem(rcx,32), ymm0) // load c42:c72 into ymm0 Z_ALPHA(0, 2) // scale ymm0 by beta vaddpd(ymm10, ymm0, ymm0) // add the gemm result to ymm0 vmovapd(ymm0, mem(rcx,32)) // store c42:c72 add(rdi, rcx) // c += cs_c; // update c03:c33 vmovapd(mem(rcx), ymm0) // load c03:c33 into ymm0 Z_ALPHA(0, 2) // scale ymm0 by beta vaddpd(ymm9, ymm0, ymm0) // add the gemm result to ymm0 vmovapd(ymm0, mem(rcx)) // store c03:c33 // update c43:c73 vmovapd(mem(rcx,32), ymm0) // load c43:c73 into ymm0 Z_ALPHA(0, 2) // scale ymm0 by beta vaddpd(ymm8, ymm0, ymm0) // add the gemm result to ymm0 vmovapd(ymm0, mem(rcx,32)) // store c43:c73 add(rdi, rcx) // c += cs_c; jmp(.ZDONE) // jump to end. label(.ZBETAZERO) vmovapd(ymm15, mem(rcx)) // store c00:c30 vmovapd(ymm14, mem(rcx,32)) // store c40:c70 add(rdi, rcx) // c += cs_c; vmovapd(ymm13, mem(rcx)) // store c01:c31 vmovapd(ymm12, mem(rcx,32)) // store c41:c71 add(rdi, rcx) // c += cs_c; vmovapd(ymm11, mem(rcx)) // store c02:c32 vmovapd(ymm10, mem(rcx,32)) // store c42:c72 add(rdi, rcx) // c += cs_c; vmovapd(ymm9, mem(rcx)) // store c03:c33 vmovapd(ymm8, mem(rcx,32)) // store c43:c73 //add(rdi, rcx) // c += cs_c; label(.ZDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), // 0 [k_left] "m" (k_left), // 1 [a] "m" (a), // 2 [b] "m" (b), // 3 [alpha] "m" (alpha), // 4 [beta] "m" (beta), // 5 [c] "m" (c), // 6 [rs_c] "m" (rs_c), // 7 [cs_c] "m" (cs_c)/*, // 8 [b_next] "m" (b_next), // 9 [a_next] "m" (a_next)*/ // 10 : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "ymm0", "ymm1", "ymm2", "ymm3", "ymm4", "ymm5", "ymm6", "ymm7", "ymm8", "ymm9", "ymm10", "ymm11", "ymm12", "ymm13", "ymm14", "ymm15", "memory" ) GEMM_UKR_FLUSH_CT( z ); } blis-0.9.0/kernels/bulldozer/bli_kernels_bulldozer.h000066400000000000000000000035621422157504600226560ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ GEMM_UKR_PROT( float, s, gemm_bulldozer_asm_8x8_fma4 ) GEMM_UKR_PROT( double, d, gemm_bulldozer_asm_4x6_fma4 ) GEMM_UKR_PROT( scomplex, c, gemm_bulldozer_asm_8x4_fma4 ) GEMM_UKR_PROT( dcomplex, z, gemm_bulldozer_asm_4x4_fma4 ) blis-0.9.0/kernels/generic/000077500000000000000000000000001422157504600155365ustar00rootroot00000000000000blis-0.9.0/kernels/generic/generic.txt000066400000000000000000000012441422157504600177140ustar00rootroot00000000000000 generic.txt ----------- This file in 'kernels/generic' exists only to force 'git' to track what would otherwise be an empty directory. Having this empty directory is necessary because the 'generic' singleton family is defined in the configuration registry as: generic: generic which implies that the 'generic' sub-configuration depends on the 'generic' kernel set (because there were no complementary kernel sets specified via '/'). Thus, we need there to be a kernel set named 'generic', but we don't actually refer to any such kernels in BLIS. In other words, this file is simply a workaround to a quirk in the syntax and semantics of the config_registry file. -FGVZ blis-0.9.0/kernels/haswell/000077500000000000000000000000001422157504600155615ustar00rootroot00000000000000blis-0.9.0/kernels/haswell/1m/000077500000000000000000000000001422157504600160765ustar00rootroot00000000000000blis-0.9.0/kernels/haswell/1m/bli_packm_haswell_asm_c3xk.c000066400000000000000000000274651422157504600235100ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2019 - 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define BLIS_ASM_SYNTAX_ATT #include "bli_x86_asm_macros.h" // Prototype reference packm kernels. PACKM_KER_PROT( scomplex, c, packm_3xk_haswell_ref ) void bli_cpackm_haswell_asm_3xk ( conj_t conja, pack_t schema, dim_t cdim0, dim_t k0, dim_t k0_max, scomplex* restrict kappa, scomplex* restrict a, inc_t inca0, inc_t lda0, scomplex* restrict p, inc_t ldp0, cntx_t* restrict cntx ) { #if 0 bli_cpackm_3xk_haswell_ref ( conja, schema, cdim0, k0, k0_max, kappa, a, inca0, lda0, p, ldp0, cntx ); return; #endif // This is the panel dimension assumed by the packm kernel. const dim_t mnr = 3; // This is the "packing" dimension assumed by the packm kernel. // This should be equal to ldp. //const dim_t packmnr = 6; // Define a local copy of 1.0 so we can test for unit kappa. float one_l = 1.0; float* restrict one = &one_l; // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. const uint64_t k_iter = k0 / 4; #if 1 const uint64_t k_left = k0 % 4; #else const uint64_t k_left = k0; #endif // NOTE: For the purposes of the comments in this packm kernel, we // interpret inca and lda as rs_a and cs_a, respectively, and similarly // interpret ldp as cs_p (with rs_p implicitly unit). Thus, when reading // this packm kernel, you should think of the operation as packing an // m x n micropanel, where m and n are tiny and large, respectively, and // where elements of each column of the packed matrix P are contiguous. // (This packm kernel can still be used to pack micropanels of matrix B // in a gemm operation.) const uint64_t inca = inca0; const uint64_t lda = lda0; const uint64_t ldp = ldp0; const bool gs = ( inca0 != 1 && lda0 != 1 ); // NOTE: If/when this kernel ever supports scaling by kappa within the // assembly region, this constraint should be lifted. const bool unitk = bli_ceq1( *kappa ); // ------------------------------------------------------------------------- if ( cdim0 == mnr && !gs && !conja && unitk ) { begin_asm() mov(var(a), rax) // load address of a. mov(var(inca), r8) // load inca mov(var(lda), r10) // load lda lea(mem(, r8, 8), r8) // inca *= sizeof(scomplex) lea(mem(, r10, 8), r10) // lda *= sizeof(scomplex) mov(var(p), rbx) // load address of p. lea(mem( , r10, 4), r14) // r14 = 4*lda mov(var(one), rdx) // load address of 1.0 constant vbroadcastss(mem(rdx, 0), ymm1) // load 1.0 and duplicate vxorps(ymm0, ymm0, ymm0) // set ymm0 to 0.0. mov(var(kappa), rcx) // load address of kappa vbroadcastss(mem(rcx, 0), ymm10) // load kappa_r and duplicate vbroadcastss(mem(rcx, 4), ymm11) // load kappa_i and duplicate // now branch on kappa == 1.0 vucomiss(xmm1, xmm10) // set ZF if kappa_r == 1.0. sete(r12b) // r12b = ( ZF == 1 ? 1 : 0 ); vucomiss(xmm0, xmm11) // set ZF if kappa_i == 0.0. sete(r13b) // r13b = ( ZF == 1 ? 1 : 0 ); and(r12b, r13b) // set ZF if r12b & r13b == 1. jne(.CKAPPAUNIT) // if ZF = 1, jump to beta == 0 case label(.CKAPPANONU) cmp(imm(8), r8) // set ZF if (8*inca) == 8. jz(.CCOLNONU) // jump to column storage case // -- kappa non-unit, row storage on A ------------------------------------- label(.CROWNONU) jmp(.CDONE) // jump to end. // -- kappa non-unit, column storage on A ---------------------------------- label(.CCOLNONU) jmp(.CDONE) // jump to end. label(.CKAPPAUNIT) cmp(imm(8), r8) // set ZF if (8*inca) == 8. jz(.CCOLUNIT) // jump to column storage case // -- kappa unit, row storage on A ----------------------------------------- label(.CROWUNIT) //lea(mem(r8, r8, 2), r12) // r12 = 3*inca //lea(mem(r12, r8, 2), rcx) // rcx = 5*inca //lea(mem(r12, r8, 4), rdx) // rdx = 7*inca mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.CCONKLEFTROWU) // if i == 0, jump to code that // contains the k_left loop. label(.CKITERROWU) // MAIN LOOP (k_iter) vmovupd(mem(rax, 0), ymm0) vmovupd(mem(rax, r8, 1, 0), ymm2) vmovupd(mem(rax, r8, 2, 0), ymm4) add(r14, rax) // a += 4*lda; vunpcklpd(ymm2, ymm0, ymm10) vunpckhpd(ymm2, ymm0, ymm11) vunpcklpd(ymm6, ymm4, ymm12) vunpckhpd(ymm6, ymm4, ymm13) vinsertf128(imm(0x1), xmm12, ymm10, ymm0) vinsertf128(imm(0x1), xmm13, ymm11, ymm2) vperm2f128(imm(0x31), ymm12, ymm10, ymm4) vperm2f128(imm(0x31), ymm13, ymm11, ymm6) vextractf128(imm(0x1), ymm0, xmm1) vextractf128(imm(0x1), ymm2, xmm3) vextractf128(imm(0x1), ymm4, xmm5) vextractf128(imm(0x1), ymm6, xmm7) vmovupd(xmm0, mem(rbx, 0*24)) vmovupd(xmm2, mem(rbx, 1*24)) vmovupd(xmm4, mem(rbx, 2*24)) vmovupd(xmm6, mem(rbx, 3*24)) vmovsd(xmm1, mem(rbx, 0*24+16)) vmovsd(xmm3, mem(rbx, 1*24+16)) vmovsd(xmm5, mem(rbx, 2*24+16)) vmovsd(xmm7, mem(rbx, 3*24+16)) add(imm(4*3*8), rbx) // p += 4*ldp = 4*3; dec(rsi) // i -= 1; jne(.CKITERROWU) // iterate again if i != 0. label(.CCONKLEFTROWU) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.CDONE) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.CKLEFTROWU) // EDGE LOOP (k_left) vmovsd(mem(rax, 0), xmm0) vmovsd(mem(rax, r8, 1, 0), xmm2) vmovsd(mem(rax, r8, 2, 0), xmm4) add(r10, rax) // a += lda; vmovsd(xmm0, mem(rbx, 0*8)) vmovsd(xmm2, mem(rbx, 1*8)) vmovsd(xmm4, mem(rbx, 2*8)) add(imm(3*8), rbx) // p += ldp = 3; dec(rsi) // i -= 1; jne(.CKLEFTROWU) // iterate again if i != 0. jmp(.CDONE) // jump to end. // -- kappa unit, column storage on A -------------------------------------- label(.CCOLUNIT) lea(mem(r10, r10, 2), r13) // r13 = 3*lda mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.CCONKLEFTCOLU) // if i == 0, jump to code that // contains the k_left loop. label(.CKITERCOLU) // MAIN LOOP (k_iter) vmovupd(mem(rax, 0), xmm0) vmovsd( mem(rax, 16), xmm1) vmovupd(xmm0, mem(rbx, 0*24+ 0)) vmovsd( xmm1, mem(rbx, 0*24+16)) vmovupd(mem(rax, r10, 1, 0), xmm2) vmovsd( mem(rax, r10, 1, 16), xmm3) vmovupd(xmm2, mem(rbx, 1*24+ 0)) vmovsd( xmm3, mem(rbx, 1*24+16)) vmovupd(mem(rax, r10, 2, 0), xmm4) vmovsd( mem(rax, r10, 2, 16), xmm5) vmovupd(xmm4, mem(rbx, 2*24+ 0)) vmovsd( xmm5, mem(rbx, 2*24+16)) vmovupd(mem(rax, r13, 1, 0), xmm6) vmovsd( mem(rax, r13, 1, 16), xmm7) add(r14, rax) // a += 4*lda; vmovupd(xmm6, mem(rbx, 3*24+ 0)) vmovsd( xmm7, mem(rbx, 3*24+16)) add(imm(4*3*8), rbx) // p += 4*ldp = 4*3; dec(rsi) // i -= 1; jne(.CKITERCOLU) // iterate again if i != 0. label(.CCONKLEFTCOLU) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.CDONE) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.CKLEFTCOLU) // EDGE LOOP (k_left) vmovupd(mem(rax, 0), xmm0) vmovsd( mem(rax, 16), xmm1) add(r10, rax) // a += lda; vmovupd(xmm0, mem(rbx, 0*24+ 0)) vmovsd( xmm1, mem(rbx, 0*24+16)) add(imm(3*8), rbx) // p += ldp = 3; dec(rsi) // i -= 1; jne(.CKLEFTCOLU) // iterate again if i != 0. //jmp(.CDONE) // jump to end. label(.CDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [inca] "m" (inca), [lda] "m" (lda), [p] "m" (p), [ldp] "m" (ldp), [kappa] "m" (kappa), [one] "m" (one) : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", /*"r9",*/ "r10", /*"r11",*/ "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } else // if ( cdim0 < mnr || gs || bli_does_conj( conja ) || !unitk ) { PASTEMAC(cscal2m,BLIS_TAPI_EX_SUF) ( 0, BLIS_NONUNIT_DIAG, BLIS_DENSE, ( trans_t )conja, cdim0, k0, kappa, a, inca0, lda0, p, 1, ldp0, cntx, NULL ); if ( cdim0 < mnr ) { // Handle zero-filling along the "long" edge of the micropanel. const dim_t i = cdim0; const dim_t m_edge = mnr - cdim0; const dim_t n_edge = k0_max; scomplex* restrict p_edge = p + (i )*1; bli_cset0s_mxn ( m_edge, n_edge, p_edge, 1, ldp ); } } //bli_dfprintm( stdout, "packm 6xk ker: a_packed", cdim0, k0_max, p, 1, ldp0, "%5.2f", "" ); if ( k0 < k0_max ) { // Handle zero-filling along the "short" (far) edge of the micropanel. const dim_t j = k0; const dim_t m_edge = mnr; const dim_t n_edge = k0_max - k0; scomplex* restrict p_edge = p + (j )*ldp; bli_cset0s_mxn ( m_edge, n_edge, p_edge, 1, ldp ); } } blis-0.9.0/kernels/haswell/1m/bli_packm_haswell_asm_c8xk.c000066400000000000000000000305611422157504600235040ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2019 - 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define BLIS_ASM_SYNTAX_ATT #include "bli_x86_asm_macros.h" // Prototype reference packm kernels. PACKM_KER_PROT( scomplex, c, packm_8xk_haswell_ref ) void bli_cpackm_haswell_asm_8xk ( conj_t conja, pack_t schema, dim_t cdim0, dim_t k0, dim_t k0_max, scomplex* restrict kappa, scomplex* restrict a, inc_t inca0, inc_t lda0, scomplex* restrict p, inc_t ldp0, cntx_t* restrict cntx ) { #if 0 bli_cpackm_8xk_haswell_ref ( conja, schema, cdim0, k0, k0_max, kappa, a, inca0, lda0, p, ldp0, cntx ); return; #endif // This is the panel dimension assumed by the packm kernel. const dim_t mnr = 8; // This is the "packing" dimension assumed by the packm kernel. // This should be equal to ldp. //const dim_t packmnr = 8; // Define a local copy of 1.0 so we can test for unit kappa. float one_l = 1.0; float* restrict one = &one_l; // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. const uint64_t k_iter = k0 / 4; #if 1 const uint64_t k_left = k0 % 4; #else const uint64_t k_left = k0; #endif // NOTE: For the purposes of the comments in this packm kernel, we // interpret inca and lda as rs_a and cs_a, respectively, and similarly // interpret ldp as cs_p (with rs_p implicitly unit). Thus, when reading // this packm kernel, you should think of the operation as packing an // m x n micropanel, where m and n are tiny and large, respectively, and // where elements of each column of the packed matrix P are contiguous. // (This packm kernel can still be used to pack micropanels of matrix B // in a gemm operation.) const uint64_t inca = inca0; const uint64_t lda = lda0; const uint64_t ldp = ldp0; const bool gs = ( inca0 != 1 && lda0 != 1 ); // NOTE: If/when this kernel ever supports scaling by kappa within the // assembly region, this constraint should be lifted. const bool unitk = bli_ceq1( *kappa ); // ------------------------------------------------------------------------- if ( cdim0 == mnr && !gs && !conja && unitk ) { begin_asm() mov(var(a), rax) // load address of a. mov(var(inca), r8) // load inca mov(var(lda), r10) // load lda lea(mem(, r8, 8), r8) // inca *= sizeof(scomplex) lea(mem(, r10, 8), r10) // lda *= sizeof(scomplex) mov(var(p), rbx) // load address of p. lea(mem( , r10, 4), r14) // r14 = 4*lda mov(var(one), rdx) // load address of 1.0 constant vbroadcastss(mem(rdx, 0), ymm1) // load 1.0 and duplicate vxorps(ymm0, ymm0, ymm0) // set ymm0 to 0.0. mov(var(kappa), rcx) // load address of kappa vbroadcastss(mem(rcx, 0), ymm10) // load kappa_r and duplicate vbroadcastss(mem(rcx, 4), ymm11) // load kappa_i and duplicate // now branch on kappa == 1.0 vucomiss(xmm1, xmm10) // set ZF if kappa_r == 1.0. sete(r12b) // r12b = ( ZF == 1 ? 1 : 0 ); vucomiss(xmm0, xmm11) // set ZF if kappa_i == 0.0. sete(r13b) // r13b = ( ZF == 1 ? 1 : 0 ); and(r12b, r13b) // set ZF if r12b & r13b == 1. jne(.CKAPPAUNIT) // if ZF = 1, jump to beta == 0 case label(.CKAPPANONU) cmp(imm(8), r8) // set ZF if (8*inca) == 8. jz(.CCOLNONU) // jump to column storage case // -- kappa non-unit, row storage on A ------------------------------------- label(.CROWNONU) jmp(.CDONE) // jump to end. // -- kappa non-unit, column storage on A ---------------------------------- label(.CCOLNONU) jmp(.CDONE) // jump to end. label(.CKAPPAUNIT) cmp(imm(8), r8) // set ZF if (8*inca) == 8. jz(.CCOLUNIT) // jump to column storage case // -- kappa unit, row storage on A ----------------------------------------- label(.CROWUNIT) lea(mem(r8, r8, 2), r12) // r12 = 3*inca lea(mem(r12, r8, 2), rcx) // rcx = 5*inca lea(mem(r12, r8, 4), rdx) // rdx = 7*inca mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.CCONKLEFTROWU) // if i == 0, jump to code that // contains the k_left loop. label(.CKITERROWU) // MAIN LOOP (k_iter) vmovupd(mem(rax, 0), ymm0) vmovupd(mem(rax, r8, 1, 0), ymm2) vmovupd(mem(rax, r8, 2, 0), ymm4) vmovupd(mem(rax, r12, 1, 0), ymm6) vunpcklpd(ymm2, ymm0, ymm10) vunpckhpd(ymm2, ymm0, ymm11) vunpcklpd(ymm6, ymm4, ymm12) vunpckhpd(ymm6, ymm4, ymm13) vinsertf128(imm(0x1), xmm12, ymm10, ymm0) vinsertf128(imm(0x1), xmm13, ymm11, ymm2) vperm2f128(imm(0x31), ymm12, ymm10, ymm4) vperm2f128(imm(0x31), ymm13, ymm11, ymm6) vmovupd(ymm0, mem(rbx, 0*64)) vmovupd(ymm2, mem(rbx, 1*64)) vmovupd(ymm4, mem(rbx, 2*64)) vmovupd(ymm6, mem(rbx, 3*64)) vmovupd(mem(rax, r8, 4, 0), ymm1) vmovupd(mem(rax, rcx, 1, 0), ymm3) vmovupd(mem(rax, r12, 2, 0), ymm5) vmovupd(mem(rax, rdx, 1, 0), ymm7) add(r14, rax) // a += 4*lda; vunpcklpd(ymm3, ymm1, ymm10) vunpckhpd(ymm3, ymm1, ymm11) vunpcklpd(ymm7, ymm5, ymm12) vunpckhpd(ymm7, ymm5, ymm13) vinsertf128(imm(0x1), xmm12, ymm10, ymm1) vinsertf128(imm(0x1), xmm13, ymm11, ymm3) vperm2f128(imm(0x31), ymm12, ymm10, ymm5) vperm2f128(imm(0x31), ymm13, ymm11, ymm7) vmovupd(ymm1, mem(rbx, 0*64+32)) vmovupd(ymm3, mem(rbx, 1*64+32)) vmovupd(ymm5, mem(rbx, 2*64+32)) vmovupd(ymm7, mem(rbx, 3*64+32)) add(imm(4*8*8), rbx) // p += 4*ldp = 4*8; dec(rsi) // i -= 1; jne(.CKITERROWU) // iterate again if i != 0. label(.CCONKLEFTROWU) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.CDONE) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.CKLEFTROWU) // EDGE LOOP (k_left) vmovsd(mem(rax, 0), xmm0) vmovsd(mem(rax, r8, 1, 0), xmm2) vmovsd(mem(rax, r8, 2, 0), xmm4) vmovsd(mem(rax, r12, 1, 0), xmm6) vmovsd(mem(rax, r8, 4, 0), xmm1) vmovsd(mem(rax, rcx, 1, 0), xmm3) vmovsd(mem(rax, r12, 2, 0), xmm5) vmovsd(mem(rax, rdx, 1, 0), xmm7) add(r10, rax) // a += lda; vmovsd(xmm0, mem(rbx, 0*8)) vmovsd(xmm2, mem(rbx, 1*8)) vmovsd(xmm4, mem(rbx, 2*8)) vmovsd(xmm6, mem(rbx, 3*8)) vmovsd(xmm1, mem(rbx, 4*8)) vmovsd(xmm3, mem(rbx, 5*8)) vmovsd(xmm5, mem(rbx, 6*8)) vmovsd(xmm7, mem(rbx, 7*8)) add(imm(8*8), rbx) // p += ldp = 8; dec(rsi) // i -= 1; jne(.CKLEFTROWU) // iterate again if i != 0. jmp(.CDONE) // jump to end. // -- kappa unit, column storage on A -------------------------------------- label(.CCOLUNIT) lea(mem(r10, r10, 2), r13) // r13 = 3*lda mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.CCONKLEFTCOLU) // if i == 0, jump to code that // contains the k_left loop. label(.CKITERCOLU) // MAIN LOOP (k_iter) vmovupd(mem(rax, 0), ymm0) vmovupd(mem(rax, 32), ymm1) vmovupd(ymm0, mem(rbx, 0*64+ 0)) vmovupd(ymm1, mem(rbx, 0*64+32)) vmovupd(mem(rax, r10, 1, 0), ymm2) vmovupd(mem(rax, r10, 1, 32), ymm3) vmovupd(ymm2, mem(rbx, 1*64+ 0)) vmovupd(ymm3, mem(rbx, 1*64+32)) vmovupd(mem(rax, r10, 2, 0), ymm4) vmovupd(mem(rax, r10, 2, 32), ymm5) vmovupd(ymm4, mem(rbx, 2*64+ 0)) vmovupd(ymm5, mem(rbx, 2*64+32)) vmovupd(mem(rax, r13, 1, 0), ymm6) vmovupd(mem(rax, r13, 1, 32), ymm7) add(r14, rax) // a += 4*lda; vmovupd(ymm6, mem(rbx, 3*64+ 0)) vmovupd(ymm7, mem(rbx, 3*64+32)) add(imm(4*8*8), rbx) // p += 4*ldp = 4*8; dec(rsi) // i -= 1; jne(.CKITERCOLU) // iterate again if i != 0. label(.CCONKLEFTCOLU) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.CDONE) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.CKLEFTCOLU) // EDGE LOOP (k_left) vmovupd(mem(rax, 0), ymm0) vmovupd(mem(rax, 32), ymm1) add(r10, rax) // a += lda; vmovupd(ymm0, mem(rbx, 0*64+ 0)) vmovupd(ymm1, mem(rbx, 0*64+32)) add(imm(8*8), rbx) // p += ldp = 8; dec(rsi) // i -= 1; jne(.CKLEFTCOLU) // iterate again if i != 0. //jmp(.CDONE) // jump to end. label(.CDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [inca] "m" (inca), [lda] "m" (lda), [p] "m" (p), [ldp] "m" (ldp), [kappa] "m" (kappa), [one] "m" (one) : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", /*"r9",*/ "r10", /*"r11",*/ "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } else // if ( cdim0 < mnr || gs || bli_does_conj( conja ) || !unitk ) { PASTEMAC(cscal2m,BLIS_TAPI_EX_SUF) ( 0, BLIS_NONUNIT_DIAG, BLIS_DENSE, ( trans_t )conja, cdim0, k0, kappa, a, inca0, lda0, p, 1, ldp0, cntx, NULL ); if ( cdim0 < mnr ) { // Handle zero-filling along the "long" edge of the micropanel. const dim_t i = cdim0; const dim_t m_edge = mnr - cdim0; const dim_t n_edge = k0_max; scomplex* restrict p_edge = p + (i )*1; bli_cset0s_mxn ( m_edge, n_edge, p_edge, 1, ldp ); } } if ( k0 < k0_max ) { // Handle zero-filling along the "short" (far) edge of the micropanel. const dim_t j = k0; const dim_t m_edge = mnr; const dim_t n_edge = k0_max - k0; scomplex* restrict p_edge = p + (j )*ldp; bli_cset0s_mxn ( m_edge, n_edge, p_edge, 1, ldp ); } } blis-0.9.0/kernels/haswell/1m/bli_packm_haswell_asm_d6xk.c000066400000000000000000000272321422157504600235040ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2019 - 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define BLIS_ASM_SYNTAX_ATT #include "bli_x86_asm_macros.h" // Prototype reference packm kernels. PACKM_KER_PROT( double, d, packm_6xk_haswell_ref ) void bli_dpackm_haswell_asm_6xk ( conj_t conja, pack_t schema, dim_t cdim0, dim_t k0, dim_t k0_max, double* restrict kappa, double* restrict a, inc_t inca0, inc_t lda0, double* restrict p, inc_t ldp0, cntx_t* restrict cntx ) { #if 0 bli_dpackm_6xk_haswell_ref ( conja, schema, cdim0, k0, k0_max, kappa, a, inca0, lda0, p, ldp0, cntx ); return; #endif // This is the panel dimension assumed by the packm kernel. const dim_t mnr = 6; // This is the "packing" dimension assumed by the packm kernel. // This should be equal to ldp. //const dim_t packmnr = 6; // Define a local copy of 1.0 so we can test for unit kappa. double one_l = 1.0; double* restrict one = &one_l; // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. const uint64_t k_iter = k0 / 4; #if 1 const uint64_t k_left = k0 % 4; #else const uint64_t k_left = k0; #endif // NOTE: For the purposes of the comments in this packm kernel, we // interpret inca and lda as rs_a and cs_a, respectively, and similarly // interpret ldp as cs_p (with rs_p implicitly unit). Thus, when reading // this packm kernel, you should think of the operation as packing an // m x n micropanel, where m and n are tiny and large, respectively, and // where elements of each column of the packed matrix P are contiguous. // (This packm kernel can still be used to pack micropanels of matrix B // in a gemm operation.) const uint64_t inca = inca0; const uint64_t lda = lda0; const uint64_t ldp = ldp0; const bool gs = ( inca0 != 1 && lda0 != 1 ); // NOTE: If/when this kernel ever supports scaling by kappa within the // assembly region, this constraint should be lifted. const bool unitk = bli_deq1( *kappa ); // ------------------------------------------------------------------------- if ( cdim0 == mnr && !gs && unitk ) { begin_asm() mov(var(a), rax) // load address of a. mov(var(inca), r8) // load inca mov(var(lda), r10) // load lda lea(mem(, r8, 8), r8) // inca *= sizeof(double) lea(mem(, r10, 8), r10) // lda *= sizeof(double) mov(var(p), rbx) // load address of p. lea(mem( , r10, 4), r14) // r14 = 4*lda mov(var(one), rdx) // load address of 1.0 constant vmovsd(mem(rdx), xmm1) // load 1.0 mov(var(kappa), rcx) // load address of kappa vmovsd(mem(rcx), xmm0) // load kappa // now branch on kappa == 1.0 vucomisd(xmm0, xmm1) // set ZF if kappa == 1.0 je(.DKAPPAUNIT) // if ZF = 1, jump to beta == 0 case label(.DKAPPANONU) cmp(imm(8), r8) // set ZF if (8*inca) == 8. jz(.DCOLNONU) // jump to column storage case // -- kappa non-unit, row storage on A ------------------------------------- label(.DROWNONU) jmp(.DDONE) // jump to end. // -- kappa non-unit, column storage on A ---------------------------------- label(.DCOLNONU) jmp(.DDONE) // jump to end. label(.DKAPPAUNIT) cmp(imm(8), r8) // set ZF if (8*inca) == 8. jz(.DCOLUNIT) // jump to column storage case // -- kappa unit, row storage on A ----------------------------------------- label(.DROWUNIT) lea(mem(r8, r8, 2), r12) // r12 = 3*inca lea(mem(r12, r8, 2), rcx) // rcx = 5*inca //lea(mem(r12, r8, 4), rdx) // rdx = 7*inca mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.DCONKLEFTROWU) // if i == 0, jump to code that // contains the k_left loop. label(.DKITERROWU) // MAIN LOOP (k_iter) vmovupd(mem(rax, 0), ymm0) vmovupd(mem(rax, r8, 1, 0), ymm2) vmovupd(mem(rax, r8, 2, 0), ymm4) vmovupd(mem(rax, r12, 1, 0), ymm6) vunpcklpd(ymm2, ymm0, ymm10) vunpckhpd(ymm2, ymm0, ymm11) vunpcklpd(ymm6, ymm4, ymm12) vunpckhpd(ymm6, ymm4, ymm13) vinsertf128(imm(0x1), xmm12, ymm10, ymm0) vinsertf128(imm(0x1), xmm13, ymm11, ymm2) vperm2f128(imm(0x31), ymm12, ymm10, ymm4) vperm2f128(imm(0x31), ymm13, ymm11, ymm6) vmovupd(ymm0, mem(rbx, 0*48)) vmovupd(ymm2, mem(rbx, 1*48)) vmovupd(ymm4, mem(rbx, 2*48)) vmovupd(ymm6, mem(rbx, 3*48)) vmovupd(mem(rax, r8, 4, 0), ymm1) vmovupd(mem(rax, rcx, 1, 0), ymm3) add(r14, rax) // a += 4*lda; vunpcklpd(ymm3, ymm1, ymm10) vunpckhpd(ymm3, ymm1, ymm11) vextractf128(imm(0x1), ymm10, xmm12) vextractf128(imm(0x1), ymm11, xmm13) vmovupd(xmm10, mem(rbx, 0*48+32)) vmovupd(xmm11, mem(rbx, 1*48+32)) vmovupd(xmm12, mem(rbx, 2*48+32)) vmovupd(xmm13, mem(rbx, 3*48+32)) add(imm(4*6*8), rbx) // p += 4*ldp = 4*6; dec(rsi) // i -= 1; jne(.DKITERROWU) // iterate again if i != 0. label(.DCONKLEFTROWU) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.DDONE) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.DKLEFTROWU) // EDGE LOOP (k_left) vmovsd(mem(rax, 0), xmm0) vmovsd(mem(rax, r8, 1, 0), xmm2) vmovsd(mem(rax, r8, 2, 0), xmm4) vmovsd(mem(rax, r12, 1, 0), xmm6) vmovsd(mem(rax, r8, 4, 0), xmm1) vmovsd(mem(rax, rcx, 1, 0), xmm3) add(r10, rax) // a += lda; vmovsd(xmm0, mem(rbx, 0*8)) vmovsd(xmm2, mem(rbx, 1*8)) vmovsd(xmm4, mem(rbx, 2*8)) vmovsd(xmm6, mem(rbx, 3*8)) vmovsd(xmm1, mem(rbx, 4*8)) vmovsd(xmm3, mem(rbx, 5*8)) add(imm(6*8), rbx) // p += ldp = 6; dec(rsi) // i -= 1; jne(.DKLEFTROWU) // iterate again if i != 0. jmp(.DDONE) // jump to end. // -- kappa unit, column storage on A -------------------------------------- label(.DCOLUNIT) lea(mem(r10, r10, 2), r13) // r13 = 3*lda mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.DCONKLEFTCOLU) // if i == 0, jump to code that // contains the k_left loop. label(.DKITERCOLU) // MAIN LOOP (k_iter) vmovupd(mem(rax, 0), ymm0) vmovupd(mem(rax, 32), xmm1) vmovupd(ymm0, mem(rbx, 0*48+ 0)) vmovupd(xmm1, mem(rbx, 0*48+32)) vmovupd(mem(rax, r10, 1, 0), ymm2) vmovupd(mem(rax, r10, 1, 32), xmm3) vmovupd(ymm2, mem(rbx, 1*48+ 0)) vmovupd(xmm3, mem(rbx, 1*48+32)) vmovupd(mem(rax, r10, 2, 0), ymm4) vmovupd(mem(rax, r10, 2, 32), xmm5) vmovupd(ymm4, mem(rbx, 2*48+ 0)) vmovupd(xmm5, mem(rbx, 2*48+32)) vmovupd(mem(rax, r13, 1, 0), ymm6) vmovupd(mem(rax, r13, 1, 32), xmm7) add(r14, rax) // a += 4*lda; vmovupd(ymm6, mem(rbx, 3*48+ 0)) vmovupd(xmm7, mem(rbx, 3*48+32)) add(imm(4*6*8), rbx) // p += 4*ldp = 4*6; dec(rsi) // i -= 1; jne(.DKITERCOLU) // iterate again if i != 0. label(.DCONKLEFTCOLU) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.DDONE) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.DKLEFTCOLU) // EDGE LOOP (k_left) vmovupd(mem(rax, 0), ymm0) vmovupd(mem(rax, 32), xmm1) add(r10, rax) // a += lda; vmovupd(ymm0, mem(rbx, 0*48+ 0)) vmovupd(xmm1, mem(rbx, 0*48+32)) add(imm(6*8), rbx) // p += ldp = 6; dec(rsi) // i -= 1; jne(.DKLEFTCOLU) // iterate again if i != 0. //jmp(.DDONE) // jump to end. label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [inca] "m" (inca), [lda] "m" (lda), [p] "m" (p), [ldp] "m" (ldp), [kappa] "m" (kappa), [one] "m" (one) : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", /*"r9",*/ "r10", /*"r11",*/ "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } else // if ( cdim0 < mnr || gs || !unitk ) { PASTEMAC(dscal2m,BLIS_TAPI_EX_SUF) ( 0, BLIS_NONUNIT_DIAG, BLIS_DENSE, ( trans_t )conja, cdim0, k0, kappa, a, inca0, lda0, p, 1, ldp0, cntx, NULL ); if ( cdim0 < mnr ) { // Handle zero-filling along the "long" edge of the micropanel. const dim_t i = cdim0; const dim_t m_edge = mnr - cdim0; const dim_t n_edge = k0_max; double* restrict p_edge = p + (i )*1; bli_dset0s_mxn ( m_edge, n_edge, p_edge, 1, ldp ); } } //bli_dfprintm( stdout, "packm 6xk ker: a_packed", cdim0, k0_max, p, 1, ldp0, "%5.2f", "" ); if ( k0 < k0_max ) { // Handle zero-filling along the "short" (far) edge of the micropanel. const dim_t j = k0; const dim_t m_edge = mnr; const dim_t n_edge = k0_max - k0; double* restrict p_edge = p + (j )*ldp; bli_dset0s_mxn ( m_edge, n_edge, p_edge, 1, ldp ); } } blis-0.9.0/kernels/haswell/1m/bli_packm_haswell_asm_d8xk.c000066400000000000000000000276441422157504600235150ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2019 - 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define BLIS_ASM_SYNTAX_ATT #include "bli_x86_asm_macros.h" // Prototype reference packm kernels. PACKM_KER_PROT( double, d, packm_8xk_haswell_ref ) void bli_dpackm_haswell_asm_8xk ( conj_t conja, pack_t schema, dim_t cdim0, dim_t k0, dim_t k0_max, double* restrict kappa, double* restrict a, inc_t inca0, inc_t lda0, double* restrict p, inc_t ldp0, cntx_t* restrict cntx ) { #if 0 bli_dpackm_8xk_haswell_ref ( conja, schema, cdim0, k0, k0_max, kappa, a, inca0, lda0, p, ldp0, cntx ); return; #endif // This is the panel dimension assumed by the packm kernel. const dim_t mnr = 8; // This is the "packing" dimension assumed by the packm kernel. // This should be equal to ldp. //const dim_t packmnr = 8; // Define a local copy of 1.0 so we can test for unit kappa. double one_l = 1.0; double* restrict one = &one_l; // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. const uint64_t k_iter = k0 / 4; #if 1 const uint64_t k_left = k0 % 4; #else const uint64_t k_left = k0; #endif // NOTE: For the purposes of the comments in this packm kernel, we // interpret inca and lda as rs_a and cs_a, respectively, and similarly // interpret ldp as cs_p (with rs_p implicitly unit). Thus, when reading // this packm kernel, you should think of the operation as packing an // m x n micropanel, where m and n are tiny and large, respectively, and // where elements of each column of the packed matrix P are contiguous. // (This packm kernel can still be used to pack micropanels of matrix B // in a gemm operation.) const uint64_t inca = inca0; const uint64_t lda = lda0; const uint64_t ldp = ldp0; const bool gs = ( inca0 != 1 && lda0 != 1 ); // NOTE: If/when this kernel ever supports scaling by kappa within the // assembly region, this constraint should be lifted. const bool unitk = bli_deq1( *kappa ); // ------------------------------------------------------------------------- if ( cdim0 == mnr && !gs && unitk ) { begin_asm() mov(var(a), rax) // load address of a. mov(var(inca), r8) // load inca mov(var(lda), r10) // load lda lea(mem(, r8, 8), r8) // inca *= sizeof(double) lea(mem(, r10, 8), r10) // lda *= sizeof(double) mov(var(p), rbx) // load address of p. lea(mem( , r10, 4), r14) // r14 = 4*lda mov(var(one), rdx) // load address of 1.0 constant vmovsd(mem(rdx), xmm1) // load 1.0 mov(var(kappa), rcx) // load address of kappa vmovsd(mem(rcx), xmm0) // load kappa // now branch on kappa == 1.0 vucomisd(xmm0, xmm1) // set ZF if kappa == 1.0 je(.DKAPPAUNIT) // if ZF = 1, jump to beta == 0 case label(.DKAPPANONU) cmp(imm(8), r8) // set ZF if (8*inca) == 8. jz(.DCOLNONU) // jump to column storage case // -- kappa non-unit, row storage on A ------------------------------------- label(.DROWNONU) jmp(.DDONE) // jump to end. // -- kappa non-unit, column storage on A ---------------------------------- label(.DCOLNONU) jmp(.DDONE) // jump to end. label(.DKAPPAUNIT) cmp(imm(8), r8) // set ZF if (8*inca) == 8. jz(.DCOLUNIT) // jump to column storage case // -- kappa unit, row storage on A ----------------------------------------- label(.DROWUNIT) lea(mem(r8, r8, 2), r12) // r12 = 3*inca lea(mem(r12, r8, 2), rcx) // rcx = 5*inca lea(mem(r12, r8, 4), rdx) // rdx = 7*inca mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.DCONKLEFTROWU) // if i == 0, jump to code that // contains the k_left loop. label(.DKITERROWU) // MAIN LOOP (k_iter) vmovupd(mem(rax, 0), ymm0) vmovupd(mem(rax, r8, 1, 0), ymm2) vmovupd(mem(rax, r8, 2, 0), ymm4) vmovupd(mem(rax, r12, 1, 0), ymm6) vunpcklpd(ymm2, ymm0, ymm10) vunpckhpd(ymm2, ymm0, ymm11) vunpcklpd(ymm6, ymm4, ymm12) vunpckhpd(ymm6, ymm4, ymm13) vinsertf128(imm(0x1), xmm12, ymm10, ymm0) vinsertf128(imm(0x1), xmm13, ymm11, ymm2) vperm2f128(imm(0x31), ymm12, ymm10, ymm4) vperm2f128(imm(0x31), ymm13, ymm11, ymm6) vmovupd(ymm0, mem(rbx, 0*64)) vmovupd(ymm2, mem(rbx, 1*64)) vmovupd(ymm4, mem(rbx, 2*64)) vmovupd(ymm6, mem(rbx, 3*64)) vmovupd(mem(rax, r8, 4, 0), ymm1) vmovupd(mem(rax, rcx, 1, 0), ymm3) vmovupd(mem(rax, r12, 2, 0), ymm5) vmovupd(mem(rax, rdx, 1, 0), ymm7) add(r14, rax) // a += 4*lda; vunpcklpd(ymm3, ymm1, ymm10) vunpckhpd(ymm3, ymm1, ymm11) vunpcklpd(ymm7, ymm5, ymm12) vunpckhpd(ymm7, ymm5, ymm13) vinsertf128(imm(0x1), xmm12, ymm10, ymm1) vinsertf128(imm(0x1), xmm13, ymm11, ymm3) vperm2f128(imm(0x31), ymm12, ymm10, ymm5) vperm2f128(imm(0x31), ymm13, ymm11, ymm7) vmovupd(ymm1, mem(rbx, 0*64+32)) vmovupd(ymm3, mem(rbx, 1*64+32)) vmovupd(ymm5, mem(rbx, 2*64+32)) vmovupd(ymm7, mem(rbx, 3*64+32)) add(imm(4*8*8), rbx) // p += 4*ldp = 4*8; dec(rsi) // i -= 1; jne(.DKITERROWU) // iterate again if i != 0. label(.DCONKLEFTROWU) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.DDONE) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.DKLEFTROWU) // EDGE LOOP (k_left) vmovsd(mem(rax, 0), xmm0) vmovsd(mem(rax, r8, 1, 0), xmm2) vmovsd(mem(rax, r8, 2, 0), xmm4) vmovsd(mem(rax, r12, 1, 0), xmm6) vmovsd(mem(rax, r8, 4, 0), xmm1) vmovsd(mem(rax, rcx, 1, 0), xmm3) vmovsd(mem(rax, r12, 2, 0), xmm5) vmovsd(mem(rax, rdx, 1, 0), xmm7) add(r10, rax) // a += lda; vmovsd(xmm0, mem(rbx, 0*8)) vmovsd(xmm2, mem(rbx, 1*8)) vmovsd(xmm4, mem(rbx, 2*8)) vmovsd(xmm6, mem(rbx, 3*8)) vmovsd(xmm1, mem(rbx, 4*8)) vmovsd(xmm3, mem(rbx, 5*8)) vmovsd(xmm5, mem(rbx, 6*8)) vmovsd(xmm7, mem(rbx, 7*8)) add(imm(8*8), rbx) // p += ldp = 8; dec(rsi) // i -= 1; jne(.DKLEFTROWU) // iterate again if i != 0. jmp(.DDONE) // jump to end. // -- kappa unit, column storage on A -------------------------------------- label(.DCOLUNIT) lea(mem(r10, r10, 2), r13) // r13 = 3*lda mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.DCONKLEFTCOLU) // if i == 0, jump to code that // contains the k_left loop. label(.DKITERCOLU) // MAIN LOOP (k_iter) vmovupd(mem(rax, 0), ymm0) vmovupd(mem(rax, 32), ymm1) vmovupd(ymm0, mem(rbx, 0*64+ 0)) vmovupd(ymm1, mem(rbx, 0*64+32)) vmovupd(mem(rax, r10, 1, 0), ymm2) vmovupd(mem(rax, r10, 1, 32), ymm3) vmovupd(ymm2, mem(rbx, 1*64+ 0)) vmovupd(ymm3, mem(rbx, 1*64+32)) vmovupd(mem(rax, r10, 2, 0), ymm4) vmovupd(mem(rax, r10, 2, 32), ymm5) vmovupd(ymm4, mem(rbx, 2*64+ 0)) vmovupd(ymm5, mem(rbx, 2*64+32)) vmovupd(mem(rax, r13, 1, 0), ymm6) vmovupd(mem(rax, r13, 1, 32), ymm7) add(r14, rax) // a += 4*lda; vmovupd(ymm6, mem(rbx, 3*64+ 0)) vmovupd(ymm7, mem(rbx, 3*64+32)) add(imm(4*8*8), rbx) // p += 4*ldp = 4*8; dec(rsi) // i -= 1; jne(.DKITERCOLU) // iterate again if i != 0. label(.DCONKLEFTCOLU) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.DDONE) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.DKLEFTCOLU) // EDGE LOOP (k_left) vmovupd(mem(rax, 0), ymm0) vmovupd(mem(rax, 32), ymm1) add(r10, rax) // a += lda; vmovupd(ymm0, mem(rbx, 0*64+ 0)) vmovupd(ymm1, mem(rbx, 0*64+32)) add(imm(8*8), rbx) // p += ldp = 8; dec(rsi) // i -= 1; jne(.DKLEFTCOLU) // iterate again if i != 0. //jmp(.DDONE) // jump to end. label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [inca] "m" (inca), [lda] "m" (lda), [p] "m" (p), [ldp] "m" (ldp), [kappa] "m" (kappa), [one] "m" (one) : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", /*"r9",*/ "r10", /*"r11",*/ "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } else // if ( cdim0 < mnr || gs || !unitk ) { PASTEMAC(dscal2m,BLIS_TAPI_EX_SUF) ( 0, BLIS_NONUNIT_DIAG, BLIS_DENSE, ( trans_t )conja, cdim0, k0, kappa, a, inca0, lda0, p, 1, ldp0, cntx, NULL ); if ( cdim0 < mnr ) { // Handle zero-filling along the "long" edge of the micropanel. const dim_t i = cdim0; const dim_t m_edge = mnr - cdim0; const dim_t n_edge = k0_max; double* restrict p_edge = p + (i )*1; bli_dset0s_mxn ( m_edge, n_edge, p_edge, 1, ldp ); } } if ( k0 < k0_max ) { // Handle zero-filling along the "short" (far) edge of the micropanel. const dim_t j = k0; const dim_t m_edge = mnr; const dim_t n_edge = k0_max - k0; double* restrict p_edge = p + (j )*ldp; bli_dset0s_mxn ( m_edge, n_edge, p_edge, 1, ldp ); } } blis-0.9.0/kernels/haswell/1m/bli_packm_haswell_asm_s16xk.c000066400000000000000000000426121422157504600236030ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2019 - 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define BLIS_ASM_SYNTAX_ATT #include "bli_x86_asm_macros.h" // Prototype reference packm kernels. PACKM_KER_PROT( double, d, packm_16xk_haswell_ref ) void bli_spackm_haswell_asm_16xk ( conj_t conja, pack_t schema, dim_t cdim0, dim_t k0, dim_t k0_max, float* restrict kappa, float* restrict a, inc_t inca0, inc_t lda0, float* restrict p, inc_t ldp0, cntx_t* restrict cntx ) { #if 0 bli_spackm_16xk_haswell_ref ( conja, schema, cdim0, k0, k0_max, kappa, a, inca0, lda0, p, ldp0, cntx ); return; #endif // This is the panel dimension assumed by the packm kernel. const dim_t mnr = 16; // This is the "packing" dimension assumed by the packm kernel. // This should be equal to ldp. //const dim_t packmnr = 8; // Define a local copy of 1.0 so we can test for unit kappa. float one_l = 1.0; float* restrict one = &one_l; // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. const uint64_t k_iter = k0 / 8; #if 1 const uint64_t k_left = k0 % 8; #else const uint64_t k_left = k0; #endif // NOTE: For the purposes of the comments in this packm kernel, we // interpret inca and lda as rs_a and cs_a, respectively, and similarly // interpret ldp as cs_p (with rs_p implicitly unit). Thus, when reading // this packm kernel, you should think of the operation as packing an // m x n micropanel, where m and n are tiny and large, respectively, and // where elements of each column of the packed matrix P are contiguous. // (This packm kernel can still be used to pack micropanels of matrix B // in a gemm operation.) const uint64_t inca = inca0; const uint64_t lda = lda0; const uint64_t ldp = ldp0; const bool gs = ( inca0 != 1 && lda0 != 1 ); // NOTE: If/when this kernel ever supports scaling by kappa within the // assembly region, this constraint should be lifted. const bool unitk = bli_seq1( *kappa ); // ------------------------------------------------------------------------- if ( cdim0 == mnr && !gs && unitk ) { begin_asm() mov(var(a), rax) // load address of a. mov(var(inca), r8) // load inca mov(var(lda), r10) // load lda lea(mem(, r8, 4), r8) // inca *= sizeof(float) lea(mem(, r10, 4), r10) // lda *= sizeof(float) mov(var(p), rbx) // load address of p. lea(mem( , r10, 8), r14) // r14 = 8*lda mov(var(one), rdx) // load address of 1.0 constant vmovss(mem(rdx), xmm1) // load 1.0 mov(var(kappa), rcx) // load address of kappa vmovss(mem(rcx), xmm0) // load kappa // now branch on kappa == 1.0 vucomiss(xmm0, xmm1) // set ZF if kappa == 1.0 je(.SKAPPAUNIT) // if ZF = 1, jump to beta == 0 case label(.SKAPPANONU) cmp(imm(4), r8) // set ZF if (4*inca) == 4. jz(.SCOLNONU) // jump to column storage case // -- kappa non-unit, row storage on A ------------------------------------- label(.SROWNONU) jmp(.SDONE) // jump to end. // -- kappa non-unit, column storage on A ---------------------------------- label(.SCOLNONU) jmp(.SDONE) // jump to end. label(.SKAPPAUNIT) cmp(imm(4), r8) // set ZF if (4*inca) == 4. jz(.SCOLUNIT) // jump to column storage case // -- kappa unit, row storage on A ----------------------------------------- label(.SROWUNIT) lea(mem(r8, r8, 2), r13) // r13 = 3*inca lea(mem(r13, r8, 2), r15) // r15 = 5*inca lea(mem(r13, r8, 4), rdx) // rdx = 7*inca mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONKLEFTROWU) // if i == 0, jump to code that // contains the k_left loop. label(.SKITERROWU) // MAIN LOOP (k_iter) mov(rax, r12) // r12 = rax mov(rbx, rcx) // rcx = rbx // begin IO on rows 0-3 vmovups(mem(r12, 0), ymm4) vmovups(mem(r12, r8, 1, 0), ymm6) vmovups(mem(r12, r8, 2, 0), ymm8) vmovups(mem(r12, r13, 1, 0), ymm10) vunpcklps(ymm6, ymm4, ymm0) vunpcklps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx, 0*64)) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, 4*64)) // store ( gamma04..gamma34 ) vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx, 1*64)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, 5*64)) // store ( gamma05..gamma35 ) vunpckhps(ymm6, ymm4, ymm0) vunpckhps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx, 2*64)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, 6*64)) // store ( gamma06..gamma36 ) vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx, 3*64)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, 7*64)) // store ( gamma07..gamma37 ) lea(mem(r12, r8, 4), r12) // r12 += 4*inca add(imm(4*4), rcx) // rcx += 4; // begin IO on rows 4-7 vmovups(mem(r12, 0), ymm4) vmovups(mem(r12, r8, 1, 0), ymm6) vmovups(mem(r12, r8, 2, 0), ymm8) vmovups(mem(r12, r13, 1, 0), ymm10) vunpcklps(ymm6, ymm4, ymm0) vunpcklps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx, 0*64)) // store ( gamma40..gamma70 ) vmovups(xmm2, mem(rcx, 4*64)) // store ( gamma44..gamma74 ) vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx, 1*64)) // store ( gamma41..gamma71 ) vmovups(xmm2, mem(rcx, 5*64)) // store ( gamma45..gamma75 ) vunpckhps(ymm6, ymm4, ymm0) vunpckhps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx, 2*64)) // store ( gamma42..gamma72 ) vmovups(xmm2, mem(rcx, 6*64)) // store ( gamma46..gamma76 ) vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx, 3*64)) // store ( gamma43..gamma73 ) vmovups(xmm2, mem(rcx, 7*64)) // store ( gamma47..gamma77 ) lea(mem(r12, r8, 4), r12) // r12 += 4*inca add(imm(4*4), rcx) // rcx += 4; // begin IO on rows 8-11 vmovups(mem(r12, 0), ymm4) vmovups(mem(r12, r8, 1, 0), ymm6) vmovups(mem(r12, r8, 2, 0), ymm8) vmovups(mem(r12, r13, 1, 0), ymm10) vunpcklps(ymm6, ymm4, ymm0) vunpcklps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx, 0*64)) // store ( gamma80..gammaB0 ) vmovups(xmm2, mem(rcx, 4*64)) // store ( gamma84..gammaB4 ) vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx, 1*64)) // store ( gamma81..gammaB1 ) vmovups(xmm2, mem(rcx, 5*64)) // store ( gamma85..gammaB5 ) vunpckhps(ymm6, ymm4, ymm0) vunpckhps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx, 2*64)) // store ( gamma82..gammaB2 ) vmovups(xmm2, mem(rcx, 6*64)) // store ( gamma86..gammaB6 ) vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx, 3*64)) // store ( gamma83..gammaB3 ) vmovups(xmm2, mem(rcx, 7*64)) // store ( gamma87..gammaB7 ) lea(mem(r12, r8, 4), r12) // r12 += 4*inca add(imm(4*4), rcx) // rcx += 4; // begin IO on rows 12-15 vmovups(mem(r12, 0), ymm4) vmovups(mem(r12, r8, 1, 0), ymm6) vmovups(mem(r12, r8, 2, 0), ymm8) vmovups(mem(r12, r13, 1, 0), ymm10) vunpcklps(ymm6, ymm4, ymm0) vunpcklps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx, 0*64)) // store ( gammaC0..gammaF0 ) vmovups(xmm2, mem(rcx, 4*64)) // store ( gammaC4..gammaF4 ) vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx, 1*64)) // store ( gammaC1..gammaF1 ) vmovups(xmm2, mem(rcx, 5*64)) // store ( gammaC5..gammaF5 ) vunpckhps(ymm6, ymm4, ymm0) vunpckhps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx, 2*64)) // store ( gammaC2..gammaF2 ) vmovups(xmm2, mem(rcx, 6*64)) // store ( gammaC6..gammaF6 ) vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx, 3*64)) // store ( gammaC3..gammaF3 ) vmovups(xmm2, mem(rcx, 7*64)) // store ( gammaC7..gammaF7 ) add(r14, rax) // a += 8*lda; add(imm(8*16*4), rbx) // p += 8*ldp = 8*16; dec(rsi) // i -= 1; jne(.SKITERROWU) // iterate again if i != 0. label(.SCONKLEFTROWU) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SDONE) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SKLEFTROWU) // EDGE LOOP (k_left) vmovss(mem(rax, 0), xmm0) vmovss(mem(rax, r8, 1, 0), xmm2) vmovss(mem(rax, r8, 2, 0), xmm4) vmovss(mem(rax, r13, 1, 0), xmm6) vmovss(mem(rax, r8, 4, 0), xmm1) vmovss(mem(rax, r15, 1, 0), xmm3) vmovss(mem(rax, r13, 2, 0), xmm5) vmovss(mem(rax, rdx, 1, 0), xmm7) vmovss(xmm0, mem(rbx, 0*4)) vmovss(xmm2, mem(rbx, 1*4)) vmovss(xmm4, mem(rbx, 2*4)) vmovss(xmm6, mem(rbx, 3*4)) vmovss(xmm1, mem(rbx, 4*4)) vmovss(xmm3, mem(rbx, 5*4)) vmovss(xmm5, mem(rbx, 6*4)) vmovss(xmm7, mem(rbx, 7*4)) lea(mem(rax, r8, 8), r12) // r12 = a + 8*inca vmovss(mem(r12, 0), xmm0) vmovss(mem(r12, r8, 1, 0), xmm2) vmovss(mem(r12, r8, 2, 0), xmm4) vmovss(mem(r12, r13, 1, 0), xmm6) vmovss(mem(r12, r8, 4, 0), xmm1) vmovss(mem(r12, r15, 1, 0), xmm3) vmovss(mem(r12, r13, 2, 0), xmm5) vmovss(mem(r12, rdx, 1, 0), xmm7) add(r10, rax) // a += lda; vmovss(xmm0, mem(rbx, 8*4)) vmovss(xmm2, mem(rbx, 9*4)) vmovss(xmm4, mem(rbx, 10*4)) vmovss(xmm6, mem(rbx, 11*4)) vmovss(xmm1, mem(rbx, 12*4)) vmovss(xmm3, mem(rbx, 13*4)) vmovss(xmm5, mem(rbx, 14*4)) vmovss(xmm7, mem(rbx, 15*4)) add(imm(16*4), rbx) // p += ldp = 16; dec(rsi) // i -= 1; jne(.SKLEFTROWU) // iterate again if i != 0. jmp(.SDONE) // jump to end. // -- kappa unit, column storage on A -------------------------------------- label(.SCOLUNIT) lea(mem(r10, r10, 2), r13) // r13 = 3*lda lea(mem(r13, r10, 2), r15) // r15 = 5*lda lea(mem(r13, r10, 4), rdx) // rdx = 7*lda mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONKLEFTCOLU) // if i == 0, jump to code that // contains the k_left loop. label(.SKITERCOLU) // MAIN LOOP (k_iter) vmovups(mem(rax, 0), ymm0) vmovups(mem(rax, 32), ymm1) vmovups(ymm0, mem(rbx, 0*64+ 0)) vmovups(ymm1, mem(rbx, 0*64+32)) vmovups(mem(rax, r10, 1, 0), ymm2) vmovups(mem(rax, r10, 1, 32), ymm3) vmovups(ymm2, mem(rbx, 1*64+ 0)) vmovups(ymm3, mem(rbx, 1*64+32)) vmovups(mem(rax, r10, 2, 0), ymm4) vmovups(mem(rax, r10, 2, 32), ymm5) vmovups(ymm4, mem(rbx, 2*64+ 0)) vmovups(ymm5, mem(rbx, 2*64+32)) vmovups(mem(rax, r13, 1, 0), ymm6) vmovups(mem(rax, r13, 1, 32), ymm7) vmovups(ymm6, mem(rbx, 3*64+ 0)) vmovups(ymm7, mem(rbx, 3*64+32)) vmovups(mem(rax, r10, 4, 0), ymm8) vmovups(mem(rax, r10, 4, 32), ymm9) vmovups(ymm8, mem(rbx, 4*64+ 0)) vmovups(ymm9, mem(rbx, 4*64+32)) vmovups(mem(rax, r15, 1, 0), ymm10) vmovups(mem(rax, r15, 1, 32), ymm11) vmovups(ymm10, mem(rbx, 5*64+ 0)) vmovups(ymm11, mem(rbx, 5*64+32)) vmovups(mem(rax, r13, 2, 0), ymm12) vmovups(mem(rax, r13, 2, 32), ymm13) vmovups(ymm12, mem(rbx, 6*64+ 0)) vmovups(ymm13, mem(rbx, 6*64+32)) vmovups(mem(rax, rdx, 1, 0), ymm14) vmovups(mem(rax, rdx, 1, 32), ymm15) add(r14, rax) // a += 8*lda; vmovups(ymm14, mem(rbx, 7*64+ 0)) vmovups(ymm15, mem(rbx, 7*64+32)) add(imm(8*16*4), rbx) // p += 8*ldp = 8*16; dec(rsi) // i -= 1; jne(.SKITERCOLU) // iterate again if i != 0. label(.SCONKLEFTCOLU) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SDONE) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SKLEFTCOLU) // EDGE LOOP (k_left) vmovups(mem(rax, 0), ymm0) vmovups(mem(rax, 32), ymm1) add(r10, rax) // a += lda; vmovups(ymm0, mem(rbx, 0*64+ 0)) vmovups(ymm1, mem(rbx, 0*64+32)) add(imm(16*4), rbx) // p += ldp = 16; dec(rsi) // i -= 1; jne(.SKLEFTCOLU) // iterate again if i != 0. //jmp(.SDONE) // jump to end. label(.SDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [inca] "m" (inca), [lda] "m" (lda), [p] "m" (p), [ldp] "m" (ldp), [kappa] "m" (kappa), [one] "m" (one) : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", /*"r9",*/ "r10", /*"r11",*/ "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } else // if ( cdim0 < mnr || gs || !unitk ) { PASTEMAC(sscal2m,BLIS_TAPI_EX_SUF) ( 0, BLIS_NONUNIT_DIAG, BLIS_DENSE, ( trans_t )conja, cdim0, k0, kappa, a, inca0, lda0, p, 1, ldp0, cntx, NULL ); if ( cdim0 < mnr ) { // Handle zero-filling along the "long" edge of the micropanel. const dim_t i = cdim0; const dim_t m_edge = mnr - cdim0; const dim_t n_edge = k0_max; float* restrict p_edge = p + (i )*1; bli_sset0s_mxn ( m_edge, n_edge, p_edge, 1, ldp ); } } if ( k0 < k0_max ) { // Handle zero-filling along the "short" (far) edge of the micropanel. const dim_t j = k0; const dim_t m_edge = mnr; const dim_t n_edge = k0_max - k0; float* restrict p_edge = p + (j )*ldp; bli_sset0s_mxn ( m_edge, n_edge, p_edge, 1, ldp ); } } blis-0.9.0/kernels/haswell/1m/bli_packm_haswell_asm_s6xk.c000066400000000000000000000325521422157504600235240ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2019 - 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define BLIS_ASM_SYNTAX_ATT #include "bli_x86_asm_macros.h" // Prototype reference packm kernels. PACKM_KER_PROT( double, d, packm_6xk_haswell_ref ) void bli_spackm_haswell_asm_6xk ( conj_t conja, pack_t schema, dim_t cdim0, dim_t k0, dim_t k0_max, float* restrict kappa, float* restrict a, inc_t inca0, inc_t lda0, float* restrict p, inc_t ldp0, cntx_t* restrict cntx ) { #if 0 bli_spackm_6xk_haswell_ref ( conja, schema, cdim0, k0, k0_max, kappa, a, inca0, lda0, p, ldp0, cntx ); return; #endif // This is the panel dimension assumed by the packm kernel. const dim_t mnr = 6; // This is the "packing" dimension assumed by the packm kernel. // This should be equal to ldp. //const dim_t packmnr = 8; // Define a local copy of 1.0 so we can test for unit kappa. float one_l = 1.0; float* restrict one = &one_l; // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. const uint64_t k_iter = k0 / 8; #if 1 const uint64_t k_left = k0 % 8; #else const uint64_t k_left = k0; #endif // NOTE: For the purposes of the comments in this packm kernel, we // interpret inca and lda as rs_a and cs_a, respectively, and similarly // interpret ldp as cs_p (with rs_p implicitly unit). Thus, when reading // this packm kernel, you should think of the operation as packing an // m x n micropanel, where m and n are tiny and large, respectively, and // where elements of each column of the packed matrix P are contiguous. // (This packm kernel can still be used to pack micropanels of matrix B // in a gemm operation.) const uint64_t inca = inca0; const uint64_t lda = lda0; const uint64_t ldp = ldp0; const bool gs = ( inca0 != 1 && lda0 != 1 ); // NOTE: If/when this kernel ever supports scaling by kappa within the // assembly region, this constraint should be lifted. const bool unitk = bli_seq1( *kappa ); // ------------------------------------------------------------------------- if ( cdim0 == mnr && !gs && unitk ) { begin_asm() mov(var(a), rax) // load address of a. mov(var(inca), r8) // load inca mov(var(lda), r10) // load lda lea(mem(, r8, 4), r8) // inca *= sizeof(float) lea(mem(, r10, 4), r10) // lda *= sizeof(float) mov(var(p), rbx) // load address of p. lea(mem( , r10, 8), r14) // r14 = 8*lda mov(var(one), rdx) // load address of 1.0 constant vmovss(mem(rdx), xmm1) // load 1.0 mov(var(kappa), rcx) // load address of kappa vmovss(mem(rcx), xmm0) // load kappa // now branch on kappa == 1.0 vucomiss(xmm0, xmm1) // set ZF if kappa == 1.0 je(.SKAPPAUNIT) // if ZF = 1, jump to beta == 0 case label(.SKAPPANONU) cmp(imm(4), r8) // set ZF if (4*inca) == 4. jz(.SCOLNONU) // jump to column storage case // -- kappa non-unit, row storage on A ------------------------------------- label(.SROWNONU) jmp(.SDONE) // jump to end. // -- kappa non-unit, column storage on A ---------------------------------- label(.SCOLNONU) jmp(.SDONE) // jump to end. label(.SKAPPAUNIT) cmp(imm(4), r8) // set ZF if (4*inca) == 4. jz(.SCOLUNIT) // jump to column storage case // -- kappa unit, row storage on A ----------------------------------------- label(.SROWUNIT) lea(mem(r8, r8, 2), r13) // r13 = 3*inca lea(mem(r13, r8, 2), r15) // r15 = 5*inca //lea(mem(r13, r8, 4), rdx) // rdx = 7*inca mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONKLEFTROWU) // if i == 0, jump to code that // contains the k_left loop. label(.SKITERROWU) // MAIN LOOP (k_iter) // begin IO on rows 0-3 vmovups(mem(rax, 0), ymm4) vmovups(mem(rax, r8, 1, 0), ymm6) vmovups(mem(rax, r8, 2, 0), ymm8) vmovups(mem(rax, r13, 1, 0), ymm10) vunpcklps(ymm6, ymm4, ymm0) vunpcklps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rbx, 0*24)) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rbx, 4*24)) // store ( gamma04..gamma34 ) vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rbx, 1*24)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rbx, 5*24)) // store ( gamma05..gamma35 ) vunpckhps(ymm6, ymm4, ymm0) vunpckhps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rbx, 2*24)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rbx, 6*24)) // store ( gamma06..gamma36 ) vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rbx, 3*24)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rbx, 7*24)) // store ( gamma07..gamma37 ) // begin IO on rows 4-5 vmovups(mem(rax, r8, 4, 0), ymm12) vmovups(mem(rax, r15, 1, 0), ymm14) vunpcklps(ymm14, ymm12, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(xmm0, mem(rbx, 0*24+16)) // store ( gamma40..gamma50 ) vmovhpd(xmm0, mem(rbx, 1*24+16)) // store ( gamma41..gamma51 ) vmovlpd(xmm2, mem(rbx, 4*24+16)) // store ( gamma44..gamma54 ) vmovhpd(xmm2, mem(rbx, 5*24+16)) // store ( gamma45..gamma55 ) vunpckhps(ymm14, ymm12, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(xmm0, mem(rbx, 2*24+16)) // store ( gamma42..gamma52 ) vmovhpd(xmm0, mem(rbx, 3*24+16)) // store ( gamma43..gamma53 ) vmovlpd(xmm2, mem(rbx, 6*24+16)) // store ( gamma46..gamma56 ) vmovhpd(xmm2, mem(rbx, 7*24+16)) // store ( gamma47..gamma57 ) add(r14, rax) // a += 8*lda; add(imm(8*6*4), rbx) // p += 8*ldp = 8*6; dec(rsi) // i -= 1; jne(.SKITERROWU) // iterate again if i != 0. label(.SCONKLEFTROWU) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SDONE) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SKLEFTROWU) // EDGE LOOP (k_left) vmovss(mem(rax, 0), xmm0) vmovss(mem(rax, r8, 1, 0), xmm2) vmovss(mem(rax, r8, 2, 0), xmm4) vmovss(mem(rax, r13, 1, 0), xmm6) vmovss(mem(rax, r8, 4, 0), xmm1) vmovss(mem(rax, r15, 1, 0), xmm3) vmovss(xmm0, mem(rbx, 0*4)) vmovss(xmm2, mem(rbx, 1*4)) vmovss(xmm4, mem(rbx, 2*4)) vmovss(xmm6, mem(rbx, 3*4)) vmovss(xmm1, mem(rbx, 4*4)) vmovss(xmm3, mem(rbx, 5*4)) add(r10, rax) // a += lda; add(imm(6*4), rbx) // p += ldp = 6; dec(rsi) // i -= 1; jne(.SKLEFTROWU) // iterate again if i != 0. jmp(.SDONE) // jump to end. // -- kappa unit, column storage on A -------------------------------------- label(.SCOLUNIT) lea(mem(r10, r10, 2), r13) // r13 = 3*lda lea(mem(r13, r10, 2), r15) // r15 = 5*lda lea(mem(r13, r10, 4), rdx) // rdx = 7*lda mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONKLEFTCOLU) // if i == 0, jump to code that // contains the k_left loop. label(.SKITERCOLU) // MAIN LOOP (k_iter) vmovups(mem(rax, 0), xmm0) vmovsd( mem(rax, 16), xmm1) vmovups(xmm0, mem(rbx, 0*24+ 0)) vmovsd( xmm1, mem(rbx, 0*24+16)) vmovups(mem(rax, r10, 1, 0), xmm2) vmovsd( mem(rax, r10, 1, 16), xmm3) vmovups(xmm2, mem(rbx, 1*24+ 0)) vmovsd( xmm3, mem(rbx, 1*24+16)) vmovups(mem(rax, r10, 2, 0), xmm4) vmovsd( mem(rax, r10, 2, 16), xmm5) vmovups(xmm4, mem(rbx, 2*24+ 0)) vmovsd( xmm5, mem(rbx, 2*24+16)) vmovups(mem(rax, r13, 1, 0), xmm6) vmovsd( mem(rax, r13, 1, 16), xmm7) vmovups(xmm6, mem(rbx, 3*24+ 0)) vmovsd( xmm7, mem(rbx, 3*24+16)) vmovups(mem(rax, r10, 4, 0), xmm8) vmovsd( mem(rax, r10, 4, 16), xmm9) vmovups(xmm8, mem(rbx, 4*24+ 0)) vmovsd( xmm9, mem(rbx, 4*24+16)) vmovups(mem(rax, r15, 1, 0), xmm10) vmovsd( mem(rax, r15, 1, 16), xmm11) vmovups(xmm10, mem(rbx, 5*24+ 0)) vmovsd( xmm11, mem(rbx, 5*24+16)) vmovups(mem(rax, r13, 2, 0), xmm12) vmovsd( mem(rax, r13, 2, 16), xmm13) vmovups(xmm12, mem(rbx, 6*24+ 0)) vmovsd( xmm13, mem(rbx, 6*24+16)) vmovups(mem(rax, rdx, 1, 0), xmm14) vmovsd( mem(rax, rdx, 1, 16), xmm15) vmovups(xmm14, mem(rbx, 7*24+ 0)) vmovsd( xmm15, mem(rbx, 7*24+16)) add(r14, rax) // a += 8*lda; add(imm(8*6*4), rbx) // p += 8*ldp = 8*6; dec(rsi) // i -= 1; jne(.SKITERCOLU) // iterate again if i != 0. label(.SCONKLEFTCOLU) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SDONE) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SKLEFTCOLU) // EDGE LOOP (k_left) vmovups(mem(rax, 0), xmm0) vmovsd( mem(rax, 16), xmm1) add(r10, rax) // a += lda; vmovups(xmm0, mem(rbx, 0*24+ 0)) vmovsd( xmm1, mem(rbx, 0*24+16)) add(imm(6*4), rbx) // p += ldp = 6; dec(rsi) // i -= 1; jne(.SKLEFTCOLU) // iterate again if i != 0. //jmp(.SDONE) // jump to end. label(.SDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [inca] "m" (inca), [lda] "m" (lda), [p] "m" (p), [ldp] "m" (ldp), [kappa] "m" (kappa), [one] "m" (one) : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", /*"r9",*/ "r10", /*"r11",*/ "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } else // if ( cdim0 < mnr || gs || !unitk ) { PASTEMAC(sscal2m,BLIS_TAPI_EX_SUF) ( 0, BLIS_NONUNIT_DIAG, BLIS_DENSE, ( trans_t )conja, cdim0, k0, kappa, a, inca0, lda0, p, 1, ldp0, cntx, NULL ); if ( cdim0 < mnr ) { // Handle zero-filling along the "long" edge of the micropanel. const dim_t i = cdim0; const dim_t m_edge = mnr - cdim0; const dim_t n_edge = k0_max; float* restrict p_edge = p + (i )*1; bli_sset0s_mxn ( m_edge, n_edge, p_edge, 1, ldp ); } } if ( k0 < k0_max ) { // Handle zero-filling along the "short" (far) edge of the micropanel. const dim_t j = k0; const dim_t m_edge = mnr; const dim_t n_edge = k0_max - k0; float* restrict p_edge = p + (j )*ldp; bli_sset0s_mxn ( m_edge, n_edge, p_edge, 1, ldp ); } } blis-0.9.0/kernels/haswell/1m/bli_packm_haswell_asm_z3xk.c000066400000000000000000000276161422157504600235350ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2019 - 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define BLIS_ASM_SYNTAX_ATT #include "bli_x86_asm_macros.h" // Prototype reference packm kernels. PACKM_KER_PROT( dcomplex, z, packm_3xk_haswell_ref ) void bli_zpackm_haswell_asm_3xk ( conj_t conja, pack_t schema, dim_t cdim0, dim_t k0, dim_t k0_max, dcomplex* restrict kappa, dcomplex* restrict a, inc_t inca0, inc_t lda0, dcomplex* restrict p, inc_t ldp0, cntx_t* restrict cntx ) { #if 0 bli_zpackm_3xk_haswell_ref ( conja, schema, cdim0, k0, k0_max, kappa, a, inca0, lda0, p, ldp0, cntx ); return; #endif // This is the panel dimension assumed by the packm kernel. const dim_t mnr = 3; // This is the "packing" dimension assumed by the packm kernel. // This should be equal to ldp. //const dim_t packmnr = 8; // Define a local copy of 1.0 so we can test for unit kappa. double one_l = 1.0; double* restrict one = &one_l; // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. const uint64_t k_iter = k0 / 4; #if 1 const uint64_t k_left = k0 % 4; #else const uint64_t k_left = k0; #endif // NOTE: For the purposes of the comments in this packm kernel, we // interpret inca and lda as rs_a and cs_a, respectively, and similarly // interpret ldp as cs_p (with rs_p implicitly unit). Thus, when reading // this packm kernel, you should think of the operation as packing an // m x n micropanel, where m and n are tiny and large, respectively, and // where elements of each column of the packed matrix P are contiguous. // (This packm kernel can still be used to pack micropanels of matrix B // in a gemm operation.) const uint64_t inca = inca0; const uint64_t lda = lda0; const uint64_t ldp = ldp0; const bool gs = ( inca0 != 1 && lda0 != 1 ); // NOTE: If/when this kernel ever supports scaling by kappa within the // assembly region, this constraint should be lifted. const bool unitk = bli_zeq1( *kappa ); // ------------------------------------------------------------------------- if ( cdim0 == mnr && !gs && !conja && unitk ) { begin_asm() mov(var(a), rax) // load address of a. mov(var(inca), r8) // load inca mov(var(lda), r10) // load lda lea(mem( , r8, 2), r8) lea(mem( , r8, 8), r8) // inca *= sizeof(dcomplex) lea(mem( , r10, 2), r10) lea(mem( , r10, 8), r10) // lda *= sizeof(dcomplex) mov(var(p), rbx) // load address of p. lea(mem( , r10, 4), r14) // r14 = 4*lda mov(var(one), rdx) // load address of 1.0 constant vbroadcastsd(mem(rdx, 0), ymm1) // load 1.0 and duplicate vxorpd(ymm0, ymm0, ymm0) // set ymm0 to 0.0. mov(var(kappa), rcx) // load address of kappa vbroadcastsd(mem(rcx, 0), ymm10) // load kappa_r and duplicate vbroadcastsd(mem(rcx, 8), ymm11) // load kappa_i and duplicate // now branch on kappa == 1.0 vucomisd(xmm1, xmm10) // set ZF if kappa_r == 1.0. sete(r12b) // r12b = ( ZF == 1 ? 1 : 0 ); vucomisd(xmm0, xmm11) // set ZF if kappa_i == 0.0. sete(r13b) // r13b = ( ZF == 1 ? 1 : 0 ); and(r12b, r13b) // set ZF if r12b & r13b == 1. jne(.ZKAPPAUNIT) // if ZF = 1, jump to beta == 0 case label(.ZKAPPANONU) cmp(imm(16), r8) // set ZF if (16*inca) == 16. jz(.ZCOLNONU) // jump to column storage case // -- kappa non-unit, row storage on A ------------------------------------- label(.ZROWNONU) jmp(.ZDONE) // jump to end. // -- kappa non-unit, column storage on A ---------------------------------- label(.ZCOLNONU) jmp(.ZDONE) // jump to end. label(.ZKAPPAUNIT) cmp(imm(16), r8) // set ZF if (16*inca) == 16. jz(.ZCOLUNIT) // jump to column storage case // -- kappa unit, row storage on A ----------------------------------------- label(.ZROWUNIT) //lea(mem(r8, r8, 2), r12) // r12 = 3*inca //lea(mem(r12, r8, 2), rcx) // rcx = 5*inca //lea(mem(r12, r8, 4), rdx) // rdx = 7*inca mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.ZCONKLEFTROWU) // if i == 0, jump to code that // contains the k_left loop. label(.ZKITERROWU) // MAIN LOOP (k_iter) vmovupd(mem(rax, 0), ymm8) vmovupd(mem(rax, r8, 1, 0), ymm10) vmovupd(mem(rax, r8, 2, 0), ymm12) vextractf128(imm(0x1), ymm8, xmm9) vextractf128(imm(0x1), ymm10, xmm11) vextractf128(imm(0x1), ymm12, xmm13) vmovupd(xmm8, mem(rbx, 0*16+0*48)) vmovupd(xmm10, mem(rbx, 1*16+0*48)) vmovupd(xmm12, mem(rbx, 2*16+0*48)) vmovupd(xmm9, mem(rbx, 0*16+1*48)) vmovupd(xmm11, mem(rbx, 1*16+1*48)) vmovupd(xmm13, mem(rbx, 2*16+1*48)) vmovupd(mem(rax, 32), ymm8) vmovupd(mem(rax, r8, 1, 32), ymm10) vmovupd(mem(rax, r8, 2, 32), ymm12) add(r14, rax) // a += 4*lda; vextractf128(imm(0x1), ymm8, xmm9) vextractf128(imm(0x1), ymm10, xmm11) vextractf128(imm(0x1), ymm12, xmm13) vmovupd(xmm8, mem(rbx, 0*16+2*48)) vmovupd(xmm10, mem(rbx, 1*16+2*48)) vmovupd(xmm12, mem(rbx, 2*16+2*48)) vmovupd(xmm9, mem(rbx, 0*16+3*48)) vmovupd(xmm11, mem(rbx, 1*16+3*48)) vmovupd(xmm13, mem(rbx, 2*16+3*48)) add(imm(4*3*16), rbx) // p += 4*ldp = 4*3; dec(rsi) // i -= 1; jne(.ZKITERROWU) // iterate again if i != 0. label(.ZCONKLEFTROWU) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.ZDONE) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.ZKLEFTROWU) // EDGE LOOP (k_left) vmovups(mem(rax, 0), xmm0) vmovups(mem(rax, r8, 1, 0), xmm2) vmovups(mem(rax, r8, 2, 0), xmm4) add(r10, rax) // a += lda; vmovups(xmm0, mem(rbx, 0*16+0*48)) vmovups(xmm2, mem(rbx, 1*16+0*48)) vmovups(xmm4, mem(rbx, 2*16+0*48)) add(imm(3*16), rbx) // p += ldp = 4; dec(rsi) // i -= 1; jne(.ZKLEFTROWU) // iterate again if i != 0. jmp(.ZDONE) // jump to end. // -- kappa unit, column storage on A -------------------------------------- label(.ZCOLUNIT) lea(mem(r10, r10, 2), r13) // r13 = 3*lda mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.ZCONKLEFTCOLU) // if i == 0, jump to code that // contains the k_left loop. label(.ZKITERCOLU) // MAIN LOOP (k_iter) vmovupd(mem(rax, 0), ymm0) vmovupd(mem(rax, 32), xmm1) vmovupd(ymm0, mem(rbx, 0*48+ 0)) vmovupd(xmm1, mem(rbx, 0*48+32)) vmovupd(mem(rax, r10, 1, 0), ymm2) vmovupd(mem(rax, r10, 1, 32), xmm3) vmovupd(ymm2, mem(rbx, 1*48+ 0)) vmovupd(xmm3, mem(rbx, 1*48+32)) vmovupd(mem(rax, r10, 2, 0), ymm4) vmovupd(mem(rax, r10, 2, 32), xmm5) vmovupd(ymm4, mem(rbx, 2*48+ 0)) vmovupd(xmm5, mem(rbx, 2*48+32)) vmovupd(mem(rax, r13, 1, 0), ymm6) vmovupd(mem(rax, r13, 1, 32), xmm7) add(r14, rax) // a += 4*lda; vmovupd(ymm6, mem(rbx, 3*48+ 0)) vmovupd(xmm7, mem(rbx, 3*48+32)) add(imm(4*3*16), rbx) // p += 4*ldp = 4*3; dec(rsi) // i -= 1; jne(.ZKITERCOLU) // iterate again if i != 0. label(.ZCONKLEFTCOLU) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.ZDONE) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.ZKLEFTCOLU) // EDGE LOOP (k_left) vmovupd(mem(rax, 0), ymm0) vmovupd(mem(rax, 32), xmm1) add(r10, rax) // a += lda; vmovupd(ymm0, mem(rbx, 0*48+ 0)) vmovupd(xmm1, mem(rbx, 0*48+32)) add(imm(3*16), rbx) // p += ldp = 3; dec(rsi) // i -= 1; jne(.ZKLEFTCOLU) // iterate again if i != 0. //jmp(.ZDONE) // jump to end. label(.ZDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [inca] "m" (inca), [lda] "m" (lda), [p] "m" (p), [ldp] "m" (ldp), [kappa] "m" (kappa), [one] "m" (one) : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", /*"r9",*/ "r10", /*"r11",*/ "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } else // if ( cdim0 < mnr || gs || bli_does_conj( conja ) || !unitk ) { PASTEMAC(zscal2m,BLIS_TAPI_EX_SUF) ( 0, BLIS_NONUNIT_DIAG, BLIS_DENSE, ( trans_t )conja, cdim0, k0, kappa, a, inca0, lda0, p, 1, ldp0, cntx, NULL ); if ( cdim0 < mnr ) { // Handle zero-filling along the "long" edge of the micropanel. const dim_t i = cdim0; const dim_t m_edge = mnr - cdim0; const dim_t n_edge = k0_max; dcomplex* restrict p_edge = p + (i )*1; bli_zset0s_mxn ( m_edge, n_edge, p_edge, 1, ldp ); } } if ( k0 < k0_max ) { // Handle zero-filling along the "short" (far) edge of the micropanel. const dim_t j = k0; const dim_t m_edge = mnr; const dim_t n_edge = k0_max - k0; dcomplex* restrict p_edge = p + (j )*ldp; bli_zset0s_mxn ( m_edge, n_edge, p_edge, 1, ldp ); } } blis-0.9.0/kernels/haswell/1m/bli_packm_haswell_asm_z4xk.c000066400000000000000000000304141422157504600235240ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2019 - 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define BLIS_ASM_SYNTAX_ATT #include "bli_x86_asm_macros.h" // Prototype reference packm kernels. PACKM_KER_PROT( dcomplex, z, packm_4xk_haswell_ref ) void bli_zpackm_haswell_asm_4xk ( conj_t conja, pack_t schema, dim_t cdim0, dim_t k0, dim_t k0_max, dcomplex* restrict kappa, dcomplex* restrict a, inc_t inca0, inc_t lda0, dcomplex* restrict p, inc_t ldp0, cntx_t* restrict cntx ) { #if 0 bli_zpackm_4xk_haswell_ref ( conja, schema, cdim0, k0, k0_max, kappa, a, inca0, lda0, p, ldp0, cntx ); return; #endif // This is the panel dimension assumed by the packm kernel. const dim_t mnr = 4; // This is the "packing" dimension assumed by the packm kernel. // This should be equal to ldp. //const dim_t packmnr = 8; // Define a local copy of 1.0 so we can test for unit kappa. double one_l = 1.0; double* restrict one = &one_l; // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. const uint64_t k_iter = k0 / 4; #if 1 const uint64_t k_left = k0 % 4; #else const uint64_t k_left = k0; #endif // NOTE: For the purposes of the comments in this packm kernel, we // interpret inca and lda as rs_a and cs_a, respectively, and similarly // interpret ldp as cs_p (with rs_p implicitly unit). Thus, when reading // this packm kernel, you should think of the operation as packing an // m x n micropanel, where m and n are tiny and large, respectively, and // where elements of each column of the packed matrix P are contiguous. // (This packm kernel can still be used to pack micropanels of matrix B // in a gemm operation.) const uint64_t inca = inca0; const uint64_t lda = lda0; const uint64_t ldp = ldp0; const bool gs = ( inca0 != 1 && lda0 != 1 ); // NOTE: If/when this kernel ever supports scaling by kappa within the // assembly region, this constraint should be lifted. const bool unitk = bli_zeq1( *kappa ); // ------------------------------------------------------------------------- if ( cdim0 == mnr && !gs && !conja && unitk ) { begin_asm() mov(var(a), rax) // load address of a. mov(var(inca), r8) // load inca mov(var(lda), r10) // load lda lea(mem( , r8, 2), r8) lea(mem( , r8, 8), r8) // inca *= sizeof(dcomplex) lea(mem( , r10, 2), r10) lea(mem( , r10, 8), r10) // lda *= sizeof(dcomplex) mov(var(p), rbx) // load address of p. lea(mem( , r10, 4), r14) // r14 = 4*lda mov(var(one), rdx) // load address of 1.0 constant vbroadcastsd(mem(rdx, 0), ymm1) // load 1.0 and duplicate vxorpd(ymm0, ymm0, ymm0) // set ymm0 to 0.0. mov(var(kappa), rcx) // load address of kappa vbroadcastsd(mem(rcx, 0), ymm10) // load kappa_r and duplicate vbroadcastsd(mem(rcx, 8), ymm11) // load kappa_i and duplicate // now branch on kappa == 1.0 vucomisd(xmm1, xmm10) // set ZF if kappa_r == 1.0. sete(r12b) // r12b = ( ZF == 1 ? 1 : 0 ); vucomisd(xmm0, xmm11) // set ZF if kappa_i == 0.0. sete(r13b) // r13b = ( ZF == 1 ? 1 : 0 ); and(r12b, r13b) // set ZF if r12b & r13b == 1. jne(.ZKAPPAUNIT) // if ZF = 1, jump to kappa == 1.0 case label(.ZKAPPANONU) cmp(imm(16), r8) // set ZF if (16*inca) == 16. jz(.ZCOLNONU) // jump to column storage case // -- kappa non-unit, row storage on A ------------------------------------- label(.ZROWNONU) jmp(.ZDONE) // jump to end. // -- kappa non-unit, column storage on A ---------------------------------- label(.ZCOLNONU) jmp(.ZDONE) // jump to end. label(.ZKAPPAUNIT) cmp(imm(16), r8) // set ZF if (16*inca) == 16. jz(.ZCOLUNIT) // jump to column storage case // -- kappa unit, row storage on A ----------------------------------------- label(.ZROWUNIT) lea(mem(r8, r8, 2), r12) // r12 = 3*inca //lea(mem(r12, r8, 2), rcx) // rcx = 5*inca //lea(mem(r12, r8, 4), rdx) // rdx = 7*inca mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.ZCONKLEFTROWU) // if i == 0, jump to code that // contains the k_left loop. label(.ZKITERROWU) // MAIN LOOP (k_iter) vmovupd(mem(rax, 0), ymm8) vmovupd(mem(rax, r8, 1, 0), ymm10) vmovupd(mem(rax, r8, 2, 0), ymm12) vmovupd(mem(rax, r12, 1, 0), ymm14) vextractf128(imm(0x1), ymm8, xmm9) vextractf128(imm(0x1), ymm10, xmm11) vextractf128(imm(0x1), ymm12, xmm13) vextractf128(imm(0x1), ymm14, xmm15) vmovupd(xmm8, mem(rbx, 0*16+0*64)) vmovupd(xmm10, mem(rbx, 1*16+0*64)) vmovupd(xmm12, mem(rbx, 2*16+0*64)) vmovupd(xmm14, mem(rbx, 3*16+0*64)) vmovupd(xmm9, mem(rbx, 0*16+1*64)) vmovupd(xmm11, mem(rbx, 1*16+1*64)) vmovupd(xmm13, mem(rbx, 2*16+1*64)) vmovupd(xmm15, mem(rbx, 3*16+1*64)) vmovupd(mem(rax, 32), ymm8) vmovupd(mem(rax, r8, 1, 32), ymm10) vmovupd(mem(rax, r8, 2, 32), ymm12) vmovupd(mem(rax, r12, 1, 32), ymm14) add(r14, rax) // a += 4*lda; vextractf128(imm(0x1), ymm8, xmm9) vextractf128(imm(0x1), ymm10, xmm11) vextractf128(imm(0x1), ymm12, xmm13) vextractf128(imm(0x1), ymm14, xmm15) vmovupd(xmm8, mem(rbx, 0*16+2*64)) vmovupd(xmm10, mem(rbx, 1*16+2*64)) vmovupd(xmm12, mem(rbx, 2*16+2*64)) vmovupd(xmm14, mem(rbx, 3*16+2*64)) vmovupd(xmm9, mem(rbx, 0*16+3*64)) vmovupd(xmm11, mem(rbx, 1*16+3*64)) vmovupd(xmm13, mem(rbx, 2*16+3*64)) vmovupd(xmm15, mem(rbx, 3*16+3*64)) add(imm(4*4*16), rbx) // p += 4*ldp = 4*4; dec(rsi) // i -= 1; jne(.ZKITERROWU) // iterate again if i != 0. label(.ZCONKLEFTROWU) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.ZDONE) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.ZKLEFTROWU) // EDGE LOOP (k_left) vmovups(mem(rax, 0), xmm0) vmovups(mem(rax, r8, 1, 0), xmm2) vmovups(mem(rax, r8, 2, 0), xmm4) vmovups(mem(rax, r12, 1, 0), xmm6) add(r10, rax) // a += lda; vmovups(xmm0, mem(rbx, 0*16+0*64)) vmovups(xmm2, mem(rbx, 1*16+0*64)) vmovups(xmm4, mem(rbx, 2*16+0*64)) vmovups(xmm6, mem(rbx, 3*16+0*64)) add(imm(4*16), rbx) // p += ldp = 4; dec(rsi) // i -= 1; jne(.ZKLEFTROWU) // iterate again if i != 0. jmp(.ZDONE) // jump to end. // -- kappa unit, column storage on A -------------------------------------- label(.ZCOLUNIT) lea(mem(r10, r10, 2), r13) // r13 = 3*lda mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.ZCONKLEFTCOLU) // if i == 0, jump to code that // contains the k_left loop. label(.ZKITERCOLU) // MAIN LOOP (k_iter) vmovupd(mem(rax, 0), ymm0) vmovupd(mem(rax, 32), ymm1) vmovupd(ymm0, mem(rbx, 0*64+ 0)) vmovupd(ymm1, mem(rbx, 0*64+32)) vmovupd(mem(rax, r10, 1, 0), ymm2) vmovupd(mem(rax, r10, 1, 32), ymm3) vmovupd(ymm2, mem(rbx, 1*64+ 0)) vmovupd(ymm3, mem(rbx, 1*64+32)) vmovupd(mem(rax, r10, 2, 0), ymm4) vmovupd(mem(rax, r10, 2, 32), ymm5) vmovupd(ymm4, mem(rbx, 2*64+ 0)) vmovupd(ymm5, mem(rbx, 2*64+32)) vmovupd(mem(rax, r13, 1, 0), ymm6) vmovupd(mem(rax, r13, 1, 32), ymm7) add(r14, rax) // a += 4*lda; vmovupd(ymm6, mem(rbx, 3*64+ 0)) vmovupd(ymm7, mem(rbx, 3*64+32)) add(imm(4*4*16), rbx) // p += 4*ldp = 4*4; dec(rsi) // i -= 1; jne(.ZKITERCOLU) // iterate again if i != 0. label(.ZCONKLEFTCOLU) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.ZDONE) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.ZKLEFTCOLU) // EDGE LOOP (k_left) vmovupd(mem(rax, 0), ymm0) vmovupd(mem(rax, 32), ymm1) add(r10, rax) // a += lda; vmovupd(ymm0, mem(rbx, 0*64+ 0)) vmovupd(ymm1, mem(rbx, 0*64+32)) add(imm(4*16), rbx) // p += ldp = 4; dec(rsi) // i -= 1; jne(.ZKLEFTCOLU) // iterate again if i != 0. //jmp(.ZDONE) // jump to end. label(.ZDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [inca] "m" (inca), [lda] "m" (lda), [p] "m" (p), [ldp] "m" (ldp), [kappa] "m" (kappa), [one] "m" (one) : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", /*"r9",*/ "r10", /*"r11",*/ "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } else // if ( cdim0 < mnr || gs || bli_does_conj( conja ) || !unitk ) { PASTEMAC(zscal2m,BLIS_TAPI_EX_SUF) ( 0, BLIS_NONUNIT_DIAG, BLIS_DENSE, ( trans_t )conja, cdim0, k0, kappa, a, inca0, lda0, p, 1, ldp0, cntx, NULL ); if ( cdim0 < mnr ) { // Handle zero-filling along the "long" edge of the micropanel. const dim_t i = cdim0; const dim_t m_edge = mnr - cdim0; const dim_t n_edge = k0_max; dcomplex* restrict p_edge = p + (i )*1; bli_zset0s_mxn ( m_edge, n_edge, p_edge, 1, ldp ); } } if ( k0 < k0_max ) { // Handle zero-filling along the "short" (far) edge of the micropanel. const dim_t j = k0; const dim_t m_edge = mnr; const dim_t n_edge = k0_max - k0; dcomplex* restrict p_edge = p + (j )*ldp; bli_zset0s_mxn ( m_edge, n_edge, p_edge, 1, ldp ); } } blis-0.9.0/kernels/haswell/3/000077500000000000000000000000001422157504600157235ustar00rootroot00000000000000blis-0.9.0/kernels/haswell/3/bli_gemm_haswell_asm_d6x8.c000066400000000000000000001567551422157504600231150ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define BLIS_ASM_SYNTAX_ATT #include "bli_x86_asm_macros.h" #define SGEMM_INPUT_GS_BETA_NZ \ vmovlps(mem(rcx), xmm0, xmm0) \ vmovhps(mem(rcx, rsi, 1), xmm0, xmm0) \ vmovlps(mem(rcx, rsi, 2), xmm1, xmm1) \ vmovhps(mem(rcx, r13, 1), xmm1, xmm1) \ vshufps(imm(0x88), xmm1, xmm0, xmm0) \ vmovlps(mem(rcx, rsi, 4), xmm2, xmm2) \ vmovhps(mem(rcx, r15, 1), xmm2, xmm2) \ /* We can't use vmovhps for loading the last element becauase that might result in reading beyond valid memory. (vmov[lh]psd load pairs of adjacent floats at a time.) So we need to use vmovss instead. But since we're limited to using ymm0 through ymm2 (ymm3 contains beta and ymm4 through ymm15 contain the microtile) and due to the way vmovss zeros out all bits above 31, we have to load element 7 before element 6. */ \ vmovss(mem(rcx, r10, 1), xmm1) \ vpermilps(imm(0xcf), xmm1, xmm1) \ vmovlps(mem(rcx, r13, 2), xmm1, xmm1) \ /*vmovhps(mem(rcx, r10, 1), xmm1, xmm1)*/ \ vshufps(imm(0x88), xmm1, xmm2, xmm2) \ vperm2f128(imm(0x20), ymm2, ymm0, ymm0) #define SGEMM_OUTPUT_GS_BETA_NZ \ vextractf128(imm(1), ymm0, xmm2) \ vmovss(xmm0, mem(rcx)) \ vpermilps(imm(0x39), xmm0, xmm1) \ vmovss(xmm1, mem(rcx, rsi, 1)) \ vpermilps(imm(0x39), xmm1, xmm0) \ vmovss(xmm0, mem(rcx, rsi, 2)) \ vpermilps(imm(0x39), xmm0, xmm1) \ vmovss(xmm1, mem(rcx, r13, 1)) \ vmovss(xmm2, mem(rcx, rsi, 4)) \ vpermilps(imm(0x39), xmm2, xmm1) \ vmovss(xmm1, mem(rcx, r15, 1)) \ vpermilps(imm(0x39), xmm1, xmm2) \ vmovss(xmm2, mem(rcx, r13, 2)) \ vpermilps(imm(0x39), xmm2, xmm1) \ vmovss(xmm1, mem(rcx, r10, 1)) void bli_sgemm_haswell_asm_6x16 ( dim_t m, dim_t n, dim_t k, float* restrict alpha, float* restrict a, float* restrict b, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k / 4; uint64_t k_left = k % 4; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; GEMM_UKR_SETUP_CT_AMBI( s, 6, 16, true ); begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(b), rbx) // load address of b. //mov(%9, r15) // load address of b_next. add(imm(32*4), rbx) // initialize loop by pre-loading vmovaps(mem(rbx, -4*32), ymm0) vmovaps(mem(rbx, -3*32), ymm1) mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLPREFETCH) // jump to column prefetch case lea(mem(rdi, rdi, 2), r13) // r13 = 3*rs_c; lea(mem(rcx, r13, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 7*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 7*8)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 7*8)) // prefetch c + 3*rs_c prefetch(0, mem(rdx, rdi, 1, 7*8)) // prefetch c + 4*rs_c prefetch(0, mem(rdx, rdi, 2, 7*8)) // prefetch c + 5*rs_c jmp(.SPREFETCHDONE) label(.SCOLPREFETCH) lea(mem(rsi, rsi, 2), r13) // r13 = 3*cs_c; lea(mem(rcx, r13, 1), rdx) // rdx = c + 3*cs_c; prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 7*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 7*8)) // prefetch c + 2*cs_c prefetch(0, mem(rdx, 7*8)) // prefetch c + 3*cs_c prefetch(0, mem(rdx, rsi, 1, 7*8)) // prefetch c + 4*cs_c prefetch(0, mem(rdx, rsi, 2, 7*8)) // prefetch c + 5*cs_c prefetch(0, mem(rdx, r13, 1, 7*8)) // prefetch c + 6*cs_c prefetch(0, mem(rdx, rsi, 4, 7*8)) // prefetch c + 7*cs_c lea(mem(rcx, rsi, 8), r14) // r14 = c + 8*cs_c; lea(mem(r14, r13, 1), rdx) // rdx = c + 11*cs_c; prefetch(0, mem(r14, 7*8)) // prefetch c + 8*cs_c prefetch(0, mem(r14, rsi, 1, 7*8)) // prefetch c + 9*cs_c prefetch(0, mem(r14, rsi, 2, 7*8)) // prefetch c + 10*cs_c prefetch(0, mem(rdx, 7*8)) // prefetch c + 11*cs_c prefetch(0, mem(rdx, rsi, 1, 7*8)) // prefetch c + 12*cs_c prefetch(0, mem(rdx, rsi, 2, 7*8)) // prefetch c + 13*cs_c prefetch(0, mem(rdx, r13, 1, 7*8)) // prefetch c + 14*cs_c prefetch(0, mem(rdx, rsi, 4, 7*8)) // prefetch c + 15*cs_c label(.SPREFETCHDONE) mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // iteration 0 prefetch(0, mem(rax, 64*4)) vbroadcastss(mem(rax, 0*4), ymm2) vbroadcastss(mem(rax, 1*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, 2*4), ymm2) vbroadcastss(mem(rax, 3*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, 4*4), ymm2) vbroadcastss(mem(rax, 5*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) vmovaps(mem(rbx, -2*32), ymm0) vmovaps(mem(rbx, -1*32), ymm1) // iteration 1 vbroadcastss(mem(rax, 6*4), ymm2) vbroadcastss(mem(rax, 7*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, 8*4), ymm2) vbroadcastss(mem(rax, 9*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, 10*4), ymm2) vbroadcastss(mem(rax, 11*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) vmovaps(mem(rbx, 0*32), ymm0) vmovaps(mem(rbx, 1*32), ymm1) // iteration 2 prefetch(0, mem(rax, 76*4)) vbroadcastss(mem(rax, 12*4), ymm2) vbroadcastss(mem(rax, 13*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, 14*4), ymm2) vbroadcastss(mem(rax, 15*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, 16*4), ymm2) vbroadcastss(mem(rax, 17*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) vmovaps(mem(rbx, 2*32), ymm0) vmovaps(mem(rbx, 3*32), ymm1) // iteration 3 vbroadcastss(mem(rax, 18*4), ymm2) vbroadcastss(mem(rax, 19*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, 20*4), ymm2) vbroadcastss(mem(rax, 21*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, 22*4), ymm2) vbroadcastss(mem(rax, 23*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) add(imm(4*6*4), rax) // a += 4*6 (unroll x mr) add(imm(4*16*4), rbx) // b += 4*16 (unroll x nr) vmovaps(mem(rbx, -4*32), ymm0) vmovaps(mem(rbx, -3*32), ymm1) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP prefetch(0, mem(rax, 64*4)) vbroadcastss(mem(rax, 0*4), ymm2) vbroadcastss(mem(rax, 1*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, 2*4), ymm2) vbroadcastss(mem(rax, 3*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, 4*4), ymm2) vbroadcastss(mem(rax, 5*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) add(imm(1*6*4), rax) // a += 1*6 (unroll x mr) add(imm(1*16*4), rbx) // b += 1*16 (unroll x nr) vmovaps(mem(rbx, -4*32), ymm0) vmovaps(mem(rbx, -3*32), ymm1) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), ymm0) // load alpha and duplicate vbroadcastss(mem(rbx), ymm3) // load beta and duplicate vmulps(ymm0, ymm4, ymm4) // scale by alpha vmulps(ymm0, ymm5, ymm5) vmulps(ymm0, ymm6, ymm6) vmulps(ymm0, ymm7, ymm7) vmulps(ymm0, ymm8, ymm8) vmulps(ymm0, ymm9, ymm9) vmulps(ymm0, ymm10, ymm10) vmulps(ymm0, ymm11, ymm11) vmulps(ymm0, ymm12, ymm12) vmulps(ymm0, ymm13, ymm13) vmulps(ymm0, ymm14, ymm14) vmulps(ymm0, ymm15, ymm15) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) lea(mem(rcx, rsi, 8), rdx) // load address of c + 8*cs_c; lea(mem(rcx, rdi, 4), r14) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), r13) // r13 = 3*cs_c; lea(mem(rsi, rsi, 4), r15) // r15 = 5*cs_c; lea(mem(r13, rsi, 4), r10) // r10 = 7*cs_c; // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (4*cs_c) == 4. jz(.SCOLSTORED) // jump to column storage case vfmadd231ps(mem(rcx), ymm3, ymm4) vmovups(ymm4, mem(rcx)) vfmadd231ps(mem(rcx,32), ymm3, ymm5) vmovups(ymm5, mem(rcx,32)) add(rdi, rcx) vfmadd231ps(mem(rcx), ymm3, ymm6) vmovups(ymm6, mem(rcx)) vfmadd231ps(mem(rcx,32), ymm3, ymm7) vmovups(ymm7, mem(rcx,32)) add(rdi, rcx) vfmadd231ps(mem(rcx), ymm3, ymm8) vmovups(ymm8, mem(rcx)) vfmadd231ps(mem(rcx,32), ymm3, ymm9) vmovups(ymm9, mem(rcx,32)) add(rdi, rcx) vfmadd231ps(mem(rcx), ymm3, ymm10) vmovups(ymm10, mem(rcx)) vfmadd231ps(mem(rcx,32), ymm3, ymm11) vmovups(ymm11, mem(rcx,32)) add(rdi, rcx) vfmadd231ps(mem(rcx), ymm3, ymm12) vmovups(ymm12, mem(rcx)) vfmadd231ps(mem(rcx,32), ymm3, ymm13) vmovups(ymm13, mem(rcx,32)) add(rdi, rcx) vfmadd231ps(mem(rcx), ymm3, ymm14) vmovups(ymm14, mem(rcx)) vfmadd231ps(mem(rcx,32), ymm3, ymm15) vmovups(ymm15, mem(rcx,32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORED) vunpcklps(ymm6, ymm4, ymm0) vunpcklps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx), xmm3, xmm0) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm0, mem(rcx)) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx, rsi, 1), xmm3, xmm1) vfmadd231ps(mem(rcx, r15, 1), xmm3, xmm2) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, r15, 1)) // store ( gamma05..gamma35 ) vunpckhps(ymm6, ymm4, ymm0) vunpckhps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx, rsi, 2), xmm3, xmm0) vfmadd231ps(mem(rcx, r13, 2), xmm3, xmm2) vmovups(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, r13, 2)) // store ( gamma06..gamma36 ) vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx, r13, 1), xmm3, xmm1) vfmadd231ps(mem(rcx, r10, 1), xmm3, xmm2) vmovups(xmm1, mem(rcx, r13, 1)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, r10, 1)) // store ( gamma07..gamma37 ) lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vunpcklps(ymm14, ymm12, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(mem(r14), xmm1, xmm1) vmovhpd(mem(r14, rsi, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(r14)) // store ( gamma40..gamma50 ) vmovhpd(xmm0, mem(r14, rsi, 1)) // store ( gamma41..gamma51 ) vmovlpd(mem(r14, rsi, 4), xmm1, xmm1) vmovhpd(mem(r14, r15, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm2) vmovlpd(xmm2, mem(r14, rsi, 4)) // store ( gamma44..gamma54 ) vmovhpd(xmm2, mem(r14, r15, 1)) // store ( gamma45..gamma55 ) vunpckhps(ymm14, ymm12, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(mem(r14, rsi, 2), xmm1, xmm1) vmovhpd(mem(r14, r13, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(r14, rsi, 2)) // store ( gamma42..gamma52 ) vmovhpd(xmm0, mem(r14, r13, 1)) // store ( gamma43..gamma53 ) vmovlpd(mem(r14, r13, 2), xmm1, xmm1) vmovhpd(mem(r14, r10, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm2) vmovlpd(xmm2, mem(r14, r13, 2)) // store ( gamma46..gamma56 ) vmovhpd(xmm2, mem(r14, r10, 1)) // store ( gamma47..gamma57 ) lea(mem(r14, rsi, 8), r14) // r14 += 8*cs_c vunpcklps(ymm7, ymm5, ymm0) vunpcklps(ymm11, ymm9, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx), xmm3, xmm0) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm0, mem(rcx)) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx, rsi, 1), xmm3, xmm1) vfmadd231ps(mem(rcx, r15, 1), xmm3, xmm2) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, r15, 1)) // store ( gamma05..gamma35 ) vunpckhps(ymm7, ymm5, ymm0) vunpckhps(ymm11, ymm9, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx, rsi, 2), xmm3, xmm0) vfmadd231ps(mem(rcx, r13, 2), xmm3, xmm2) vmovups(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, r13, 2)) // store ( gamma06..gamma36 ) vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx, r13, 1), xmm3, xmm1) vfmadd231ps(mem(rcx, r10, 1), xmm3, xmm2) vmovups(xmm1, mem(rcx, r13, 1)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, r10, 1)) // store ( gamma07..gamma37 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vunpcklps(ymm15, ymm13, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(mem(r14), xmm1, xmm1) vmovhpd(mem(r14, rsi, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(r14)) // store ( gamma40..gamma50 ) vmovhpd(xmm0, mem(r14, rsi, 1)) // store ( gamma41..gamma51 ) vmovlpd(mem(r14, rsi, 4), xmm1, xmm1) vmovhpd(mem(r14, r15, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm2) vmovlpd(xmm2, mem(r14, rsi, 4)) // store ( gamma44..gamma54 ) vmovhpd(xmm2, mem(r14, r15, 1)) // store ( gamma45..gamma55 ) vunpckhps(ymm15, ymm13, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(mem(r14, rsi, 2), xmm1, xmm1) vmovhpd(mem(r14, r13, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(r14, rsi, 2)) // store ( gamma42..gamma52 ) vmovhpd(xmm0, mem(r14, r13, 1)) // store ( gamma43..gamma53 ) vmovlpd(mem(r14, r13, 2), xmm1, xmm1) vmovhpd(mem(r14, r10, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm2) vmovlpd(xmm2, mem(r14, r13, 2)) // store ( gamma46..gamma56 ) vmovhpd(xmm2, mem(r14, r10, 1)) // store ( gamma47..gamma57 ) //lea(mem(r14, rsi, 8), r14) // r14 += 8*cs_c jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (4*cs_c) == 4. jz(.SCOLSTORBZ) // jump to column storage case vmovups(ymm4, mem(rcx)) vmovups(ymm5, mem(rcx,32)) add(rdi, rcx) vmovups(ymm6, mem(rcx)) vmovups(ymm7, mem(rcx,32)) add(rdi, rcx) vmovups(ymm8, mem(rcx)) vmovups(ymm9, mem(rcx,32)) add(rdi, rcx) vmovups(ymm10, mem(rcx)) vmovups(ymm11, mem(rcx,32)) add(rdi, rcx) vmovups(ymm12, mem(rcx)) vmovups(ymm13, mem(rcx,32)) add(rdi, rcx) vmovups(ymm14, mem(rcx)) vmovups(ymm15, mem(rcx,32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) vunpcklps(ymm6, ymm4, ymm0) vunpcklps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx)) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, r15, 1)) // store ( gamma05..gamma35 ) vunpckhps(ymm6, ymm4, ymm0) vunpckhps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, r13, 2)) // store ( gamma06..gamma36 ) vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx, r13, 1)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, r10, 1)) // store ( gamma07..gamma37 ) lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vunpcklps(ymm14, ymm12, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(xmm0, mem(r14)) // store ( gamma40..gamma50 ) vmovhpd(xmm0, mem(r14, rsi, 1)) // store ( gamma41..gamma51 ) vmovlpd(xmm2, mem(r14, rsi, 4)) // store ( gamma44..gamma54 ) vmovhpd(xmm2, mem(r14, r15, 1)) // store ( gamma45..gamma55 ) vunpckhps(ymm14, ymm12, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(xmm0, mem(r14, rsi, 2)) // store ( gamma42..gamma52 ) vmovhpd(xmm0, mem(r14, r13, 1)) // store ( gamma43..gamma53 ) vmovlpd(xmm2, mem(r14, r13, 2)) // store ( gamma46..gamma56 ) vmovhpd(xmm2, mem(r14, r10, 1)) // store ( gamma47..gamma57 ) lea(mem(r14, rsi, 8), r14) // r14 += 8*cs_c vunpcklps(ymm7, ymm5, ymm0) vunpcklps(ymm11, ymm9, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx)) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, r15, 1)) // store ( gamma05..gamma35 ) vunpckhps(ymm7, ymm5, ymm0) vunpckhps(ymm11, ymm9, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, r13, 2)) // store ( gamma06..gamma36 ) vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx, r13, 1)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, r10, 1)) // store ( gamma07..gamma37 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vunpcklps(ymm15, ymm13, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(xmm0, mem(r14)) // store ( gamma40..gamma50 ) vmovhpd(xmm0, mem(r14, rsi, 1)) // store ( gamma41..gamma51 ) vmovlpd(xmm2, mem(r14, rsi, 4)) // store ( gamma44..gamma54 ) vmovhpd(xmm2, mem(r14, r15, 1)) // store ( gamma45..gamma55 ) vunpckhps(ymm15, ymm13, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(xmm0, mem(r14, rsi, 2)) // store ( gamma42..gamma52 ) vmovhpd(xmm0, mem(r14, r13, 1)) // store ( gamma43..gamma53 ) vmovlpd(xmm2, mem(r14, r13, 2)) // store ( gamma46..gamma56 ) vmovhpd(xmm2, mem(r14, r10, 1)) // store ( gamma47..gamma57 ) //lea(mem(r14, rsi, 8), r14) // r14 += 8*cs_ label(.SDONE) vzeroupper() end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), // 0 [k_left] "m" (k_left), // 1 [a] "m" (a), // 2 [b] "m" (b), // 3 [alpha] "m" (alpha), // 4 [beta] "m" (beta), // 5 [c] "m" (c), // 6 [rs_c] "m" (rs_c), // 7 [cs_c] "m" (cs_c)/*, // 8 [b_next] "m" (b_next), // 9 [a_next] "m" (a_next)*/ // 10 : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) GEMM_UKR_FLUSH_CT( s ); } #define DGEMM_INPUT_GS_BETA_NZ \ vmovlpd(mem(rcx), xmm0, xmm0) \ vmovhpd(mem(rcx, rsi, 1), xmm0, xmm0) \ vmovlpd(mem(rcx, rsi, 2), xmm1, xmm1) \ vmovhpd(mem(rcx, r13, 1), xmm1, xmm1) \ vperm2f128(imm(0x20), ymm1, ymm0, ymm0) /*\ vmovlpd(mem(rcx, rsi, 4), xmm2, xmm2) \ vmovhpd(mem(rcx, r15, 1), xmm2, xmm2) \ vmovlpd(mem(rcx, r13, 2), xmm1, xmm1) \ vmovhpd(mem(rcx, r10, 1), xmm1, xmm1) \ vperm2f128(imm(0x20), ymm1, ymm2, ymm2)*/ #define DGEMM_OUTPUT_GS_BETA_NZ \ vextractf128(imm(1), ymm0, xmm1) \ vmovlpd(xmm0, mem(rcx)) \ vmovhpd(xmm0, mem(rcx, rsi, 1)) \ vmovlpd(xmm1, mem(rcx, rsi, 2)) \ vmovhpd(xmm1, mem(rcx, r13, 1)) /*\ vextractf128(imm(1), ymm2, xmm1) \ vmovlpd(xmm2, mem(rcx, rsi, 4)) \ vmovhpd(xmm2, mem(rcx, r15, 1)) \ vmovlpd(xmm1, mem(rcx, r13, 2)) \ vmovhpd(xmm1, mem(rcx, r10, 1))*/ void bli_dgemm_haswell_asm_6x8 ( dim_t m, dim_t n, dim_t k, double* restrict alpha, double* restrict a, double* restrict b, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k / 4; uint64_t k_left = k % 4; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; GEMM_UKR_SETUP_CT_AMBI( d, 6, 8, true ); begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(b), rbx) // load address of b. //mov(%9, r15) // load address of b_next. add(imm(32*4), rbx) // initialize loop by pre-loading vmovapd(mem(rbx, -4*32), ymm0) vmovapd(mem(rbx, -3*32), ymm1) mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // cs_c *= sizeof(double) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLPREFETCH) // jump to column prefetch case lea(mem(rdi, rdi, 2), r13) // r13 = 3*rs_c; lea(mem(rcx, r13, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 7*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 7*8)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 7*8)) // prefetch c + 3*rs_c prefetch(0, mem(rdx, rdi, 1, 7*8)) // prefetch c + 4*rs_c prefetch(0, mem(rdx, rdi, 2, 7*8)) // prefetch c + 5*rs_c jmp(.DPREFETCHDONE) label(.DCOLPREFETCH) lea(mem(rsi, rsi, 2), r13) // r13 = 3*cs_c; lea(mem(rcx, r13, 1), rdx) // rdx = c + 3*cs_c; prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 7*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 7*8)) // prefetch c + 2*cs_c prefetch(0, mem(rdx, 7*8)) // prefetch c + 3*cs_c prefetch(0, mem(rdx, rsi, 1, 7*8)) // prefetch c + 4*cs_c prefetch(0, mem(rdx, rsi, 2, 7*8)) // prefetch c + 5*cs_c prefetch(0, mem(rdx, r13, 1, 7*8)) // prefetch c + 6*cs_c prefetch(0, mem(rdx, rsi, 4, 7*8)) // prefetch c + 7*cs_c label(.DPREFETCHDONE) mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.DLOOPKITER) // MAIN LOOP // iteration 0 prefetch(0, mem(rax, 64*8)) vbroadcastsd(mem(rax, 0*8), ymm2) vbroadcastsd(mem(rax, 1*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, 2*8), ymm2) vbroadcastsd(mem(rax, 3*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, 4*8), ymm2) vbroadcastsd(mem(rax, 5*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) vmovapd(mem(rbx, -2*32), ymm0) vmovapd(mem(rbx, -1*32), ymm1) // iteration 1 prefetch(0, mem(rax, 72*8)) vbroadcastsd(mem(rax, 6*8), ymm2) vbroadcastsd(mem(rax, 7*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, 8*8), ymm2) vbroadcastsd(mem(rax, 9*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, 10*8), ymm2) vbroadcastsd(mem(rax, 11*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) vmovapd(mem(rbx, 0*32), ymm0) vmovapd(mem(rbx, 1*32), ymm1) // iteration 2 prefetch(0, mem(rax, 80*8)) vbroadcastsd(mem(rax, 12*8), ymm2) vbroadcastsd(mem(rax, 13*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, 14*8), ymm2) vbroadcastsd(mem(rax, 15*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, 16*8), ymm2) vbroadcastsd(mem(rax, 17*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) vmovapd(mem(rbx, 2*32), ymm0) vmovapd(mem(rbx, 3*32), ymm1) // iteration 3 vbroadcastsd(mem(rax, 18*8), ymm2) vbroadcastsd(mem(rax, 19*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, 20*8), ymm2) vbroadcastsd(mem(rax, 21*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, 22*8), ymm2) vbroadcastsd(mem(rax, 23*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) add(imm(4*6*8), rax) // a += 4*6 (unroll x mr) add(imm(4*8*8), rbx) // b += 4*8 (unroll x nr) vmovapd(mem(rbx, -4*32), ymm0) vmovapd(mem(rbx, -3*32), ymm1) dec(rsi) // i -= 1; jne(.DLOOPKITER) // iterate again if i != 0. label(.DCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.DLOOPKLEFT) // EDGE LOOP prefetch(0, mem(rax, 64*8)) vbroadcastsd(mem(rax, 0*8), ymm2) vbroadcastsd(mem(rax, 1*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, 2*8), ymm2) vbroadcastsd(mem(rax, 3*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, 4*8), ymm2) vbroadcastsd(mem(rax, 5*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) add(imm(1*6*8), rax) // a += 1*6 (unroll x mr) add(imm(1*8*8), rbx) // b += 1*8 (unroll x nr) vmovapd(mem(rbx, -4*32), ymm0) vmovapd(mem(rbx, -3*32), ymm1) dec(rsi) // i -= 1; jne(.DLOOPKLEFT) // iterate again if i != 0. label(.DPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(ymm0, ymm5, ymm5) vmulpd(ymm0, ymm6, ymm6) vmulpd(ymm0, ymm7, ymm7) vmulpd(ymm0, ymm8, ymm8) vmulpd(ymm0, ymm9, ymm9) vmulpd(ymm0, ymm10, ymm10) vmulpd(ymm0, ymm11, ymm11) vmulpd(ymm0, ymm12, ymm12) vmulpd(ymm0, ymm13, ymm13) vmulpd(ymm0, ymm14, ymm14) vmulpd(ymm0, ymm15, ymm15) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; lea(mem(rcx, rdi, 4), r14) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), r13) // r13 = 3*cs_c; //lea(mem(rsi, rsi, 4), r15) // r15 = 5*cs_c; //lea(mem(r13, rsi, 4), r10) // r10 = 7*cs_c; // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORED) // jump to column storage case vfmadd231pd(mem(rcx), ymm3, ymm4) vmovupd(ymm4, mem(rcx)) vfmadd231pd(mem(rcx,32), ymm3, ymm5) vmovupd(ymm5, mem(rcx,32)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm6) vmovupd(ymm6, mem(rcx)) vfmadd231pd(mem(rcx,32), ymm3, ymm7) vmovupd(ymm7, mem(rcx,32)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm8) vmovupd(ymm8, mem(rcx)) vfmadd231pd(mem(rcx,32), ymm3, ymm9) vmovupd(ymm9, mem(rcx,32)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm10) vmovupd(ymm10, mem(rcx)) vfmadd231pd(mem(rcx,32), ymm3, ymm11) vmovupd(ymm11, mem(rcx,32)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm12) vmovupd(ymm12, mem(rcx)) vfmadd231pd(mem(rcx,32), ymm3, ymm13) vmovupd(ymm13, mem(rcx,32)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm14) vmovupd(ymm14, mem(rcx)) vfmadd231pd(mem(rcx,32), ymm3, ymm15) vmovupd(ymm15, mem(rcx,32)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORED) vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vunpcklpd(ymm10, ymm8, ymm2) vunpckhpd(ymm10, ymm8, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vperm2f128(imm(0x31), ymm2, ymm0, ymm8) vperm2f128(imm(0x31), ymm3, ymm1, ymm10) vbroadcastsd(mem(rbx), ymm3) vfmadd231pd(mem(rcx), ymm3, ymm4) vfmadd231pd(mem(rcx, rsi, 1), ymm3, ymm6) vfmadd231pd(mem(rcx, rsi, 2), ymm3, ymm8) vfmadd231pd(mem(rcx, r13, 1), ymm3, ymm10) vmovupd(ymm4, mem(rcx)) vmovupd(ymm6, mem(rcx, rsi, 1)) vmovupd(ymm8, mem(rcx, rsi, 2)) vmovupd(ymm10, mem(rcx, r13, 1)) lea(mem(rcx, rsi, 4), rcx) vunpcklpd(ymm14, ymm12, ymm0) vunpckhpd(ymm14, ymm12, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vextractf128(imm(0x1), ymm1, xmm4) vfmadd231pd(mem(r14), xmm3, xmm0) vfmadd231pd(mem(r14, rsi, 1), xmm3, xmm1) vfmadd231pd(mem(r14, rsi, 2), xmm3, xmm2) vfmadd231pd(mem(r14, r13, 1), xmm3, xmm4) vmovupd(xmm0, mem(r14)) vmovupd(xmm1, mem(r14, rsi, 1)) vmovupd(xmm2, mem(r14, rsi, 2)) vmovupd(xmm4, mem(r14, r13, 1)) lea(mem(r14, rsi, 4), r14) vunpcklpd(ymm7, ymm5, ymm0) vunpckhpd(ymm7, ymm5, ymm1) vunpcklpd(ymm11, ymm9, ymm2) vunpckhpd(ymm11, ymm9, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm5) vinsertf128(imm(0x1), xmm3, ymm1, ymm7) vperm2f128(imm(0x31), ymm2, ymm0, ymm9) vperm2f128(imm(0x31), ymm3, ymm1, ymm11) vbroadcastsd(mem(rbx), ymm3) vfmadd231pd(mem(rcx), ymm3, ymm5) vfmadd231pd(mem(rcx, rsi, 1), ymm3, ymm7) vfmadd231pd(mem(rcx, rsi, 2), ymm3, ymm9) vfmadd231pd(mem(rcx, r13, 1), ymm3, ymm11) vmovupd(ymm5, mem(rcx)) vmovupd(ymm7, mem(rcx, rsi, 1)) vmovupd(ymm9, mem(rcx, rsi, 2)) vmovupd(ymm11, mem(rcx, r13, 1)) //lea(mem(rcx, rsi, 4), rcx) vunpcklpd(ymm15, ymm13, ymm0) vunpckhpd(ymm15, ymm13, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vextractf128(imm(0x1), ymm1, xmm4) vfmadd231pd(mem(r14), xmm3, xmm0) vfmadd231pd(mem(r14, rsi, 1), xmm3, xmm1) vfmadd231pd(mem(r14, rsi, 2), xmm3, xmm2) vfmadd231pd(mem(r14, r13, 1), xmm3, xmm4) vmovupd(xmm0, mem(r14)) vmovupd(xmm1, mem(r14, rsi, 1)) vmovupd(xmm2, mem(r14, rsi, 2)) vmovupd(xmm4, mem(r14, r13, 1)) //lea(mem(r14, rsi, 4), r14) jmp(.DDONE) // jump to end. label(.DBETAZERO) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORBZ) // jump to column storage case vmovupd(ymm4, mem(rcx)) vmovupd(ymm5, mem(rcx,32)) add(rdi, rcx) vmovupd(ymm6, mem(rcx)) vmovupd(ymm7, mem(rcx,32)) add(rdi, rcx) vmovupd(ymm8, mem(rcx)) vmovupd(ymm9, mem(rcx,32)) add(rdi, rcx) vmovupd(ymm10, mem(rcx)) vmovupd(ymm11, mem(rcx,32)) add(rdi, rcx) vmovupd(ymm12, mem(rcx)) vmovupd(ymm13, mem(rcx,32)) add(rdi, rcx) vmovupd(ymm14, mem(rcx)) vmovupd(ymm15, mem(rcx,32)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORBZ) vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vunpcklpd(ymm10, ymm8, ymm2) vunpckhpd(ymm10, ymm8, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vperm2f128(imm(0x31), ymm2, ymm0, ymm8) vperm2f128(imm(0x31), ymm3, ymm1, ymm10) vmovupd(ymm4, mem(rcx)) vmovupd(ymm6, mem(rcx, rsi, 1)) vmovupd(ymm8, mem(rcx, rsi, 2)) vmovupd(ymm10, mem(rcx, r13, 1)) lea(mem(rcx, rsi, 4), rcx) vunpcklpd(ymm14, ymm12, ymm0) vunpckhpd(ymm14, ymm12, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vextractf128(imm(0x1), ymm1, xmm4) vmovupd(xmm0, mem(r14)) vmovupd(xmm1, mem(r14, rsi, 1)) vmovupd(xmm2, mem(r14, rsi, 2)) vmovupd(xmm4, mem(r14, r13, 1)) lea(mem(r14, rsi, 4), r14) vunpcklpd(ymm7, ymm5, ymm0) vunpckhpd(ymm7, ymm5, ymm1) vunpcklpd(ymm11, ymm9, ymm2) vunpckhpd(ymm11, ymm9, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm5) vinsertf128(imm(0x1), xmm3, ymm1, ymm7) vperm2f128(imm(0x31), ymm2, ymm0, ymm9) vperm2f128(imm(0x31), ymm3, ymm1, ymm11) vmovupd(ymm5, mem(rcx)) vmovupd(ymm7, mem(rcx, rsi, 1)) vmovupd(ymm9, mem(rcx, rsi, 2)) vmovupd(ymm11, mem(rcx, r13, 1)) //lea(mem(rcx, rsi, 4), rcx) vunpcklpd(ymm15, ymm13, ymm0) vunpckhpd(ymm15, ymm13, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vextractf128(imm(0x1), ymm1, xmm4) vmovupd(xmm0, mem(r14)) vmovupd(xmm1, mem(r14, rsi, 1)) vmovupd(xmm2, mem(r14, rsi, 2)) vmovupd(xmm4, mem(r14, r13, 1)) //lea(mem(r14, rsi, 4), r14) label(.DDONE) vzeroupper() end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), // 0 [k_left] "m" (k_left), // 1 [a] "m" (a), // 2 [b] "m" (b), // 3 [alpha] "m" (alpha), // 4 [beta] "m" (beta), // 5 [c] "m" (c), // 6 [rs_c] "m" (rs_c), // 7 [cs_c] "m" (cs_c)/*, // 8 [b_next] "m" (b_next), // 9 [a_next] "m" (a_next)*/ // 10 : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) GEMM_UKR_FLUSH_CT( d ); } #define CGEMM_INPUT_SCALE_RS_BETA_NZ(where) \ vmovups(where, ymm0) \ vpermilps(imm(0xb1), ymm0, ymm3) \ vmulps(ymm1, ymm0, ymm0) \ vmulps(ymm2, ymm3, ymm3) \ vaddsubps(ymm3, ymm0, ymm0) void bli_cgemm_haswell_asm_3x8 ( dim_t m, dim_t n, dim_t k, scomplex* restrict alpha, scomplex* restrict a, scomplex* restrict b, scomplex* restrict beta, scomplex* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k / 4; uint64_t k_left = k % 4; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; GEMM_UKR_SETUP_CT( c, 3, 8, true ); begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(b), rbx) // load address of b. //mov(%9, r15) // load address of b_next. add(imm(32*4), rbx) // initialize loop by pre-loading vmovaps(mem(rbx, -4*32), ymm0) vmovaps(mem(rbx, -3*32), ymm1) mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(scomplex) lea(mem(rcx, rdi, 1), r11) // r11 = c + 1*rs_c; lea(mem(rcx, rdi, 2), r12) // r12 = c + 2*rs_c; prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c prefetch(0, mem(r11, 7*8)) // prefetch c + 1*rs_c prefetch(0, mem(r12, 7*8)) // prefetch c + 2*rs_c mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.CCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.CLOOPKITER) // MAIN LOOP // iteration 0 prefetch(0, mem(rax, 32*8)) vbroadcastss(mem(rax, 0*4), ymm2) vbroadcastss(mem(rax, 1*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, 2*4), ymm2) vbroadcastss(mem(rax, 3*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, 4*4), ymm2) vbroadcastss(mem(rax, 5*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) vmovaps(mem(rbx, -2*32), ymm0) vmovaps(mem(rbx, -1*32), ymm1) // iteration 1 vbroadcastss(mem(rax, 6*4), ymm2) vbroadcastss(mem(rax, 7*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, 8*4), ymm2) vbroadcastss(mem(rax, 9*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, 10*4), ymm2) vbroadcastss(mem(rax, 11*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) vmovaps(mem(rbx, 0*32), ymm0) vmovaps(mem(rbx, 1*32), ymm1) // iteration 2 prefetch(0, mem(rax, 38*8)) vbroadcastss(mem(rax, 12*4), ymm2) vbroadcastss(mem(rax, 13*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, 14*4), ymm2) vbroadcastss(mem(rax, 15*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, 16*4), ymm2) vbroadcastss(mem(rax, 17*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) vmovaps(mem(rbx, 2*32), ymm0) vmovaps(mem(rbx, 3*32), ymm1) // iteration 3 vbroadcastss(mem(rax, 18*4), ymm2) vbroadcastss(mem(rax, 19*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, 20*4), ymm2) vbroadcastss(mem(rax, 21*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, 22*4), ymm2) vbroadcastss(mem(rax, 23*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) add(imm(4*3*8), rax) // a += 4*3 (unroll x mr) add(imm(4*8*8), rbx) // b += 4*8 (unroll x nr) vmovaps(mem(rbx, -4*32), ymm0) vmovaps(mem(rbx, -3*32), ymm1) dec(rsi) // i -= 1; jne(.CLOOPKITER) // iterate again if i != 0. label(.CCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.CPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.CLOOPKLEFT) // EDGE LOOP prefetch(0, mem(rax, 32*8)) vbroadcastss(mem(rax, 0*4), ymm2) vbroadcastss(mem(rax, 1*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, 2*4), ymm2) vbroadcastss(mem(rax, 3*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, 4*4), ymm2) vbroadcastss(mem(rax, 5*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) add(imm(1*3*8), rax) // a += 1*3 (unroll x mr) add(imm(1*8*8), rbx) // b += 1*8 (unroll x nr) vmovaps(mem(rbx, -4*32), ymm0) vmovaps(mem(rbx, -3*32), ymm1) dec(rsi) // i -= 1; jne(.CLOOPKLEFT) // iterate again if i != 0. label(.CPOSTACCUM) // permute even and odd elements // of ymm6/7, ymm10/11, ymm/14/15 vpermilps(imm(0xb1), ymm6, ymm6) vpermilps(imm(0xb1), ymm7, ymm7) vpermilps(imm(0xb1), ymm10, ymm10) vpermilps(imm(0xb1), ymm11, ymm11) vpermilps(imm(0xb1), ymm14, ymm14) vpermilps(imm(0xb1), ymm15, ymm15) // subtract/add even/odd elements vaddsubps(ymm6, ymm4, ymm4) vaddsubps(ymm7, ymm5, ymm5) vaddsubps(ymm10, ymm8, ymm8) vaddsubps(ymm11, ymm9, ymm9) vaddsubps(ymm14, ymm12, ymm12) vaddsubps(ymm15, ymm13, ymm13) mov(var(alpha), rax) // load address of alpha vbroadcastss(mem(rax), ymm0) // load alpha_r and duplicate vbroadcastss(mem(rax, 4), ymm1) // load alpha_i and duplicate vpermilps(imm(0xb1), ymm4, ymm3) vmulps(ymm0, ymm4, ymm4) vmulps(ymm1, ymm3, ymm3) vaddsubps(ymm3, ymm4, ymm4) vpermilps(imm(0xb1), ymm5, ymm3) vmulps(ymm0, ymm5, ymm5) vmulps(ymm1, ymm3, ymm3) vaddsubps(ymm3, ymm5, ymm5) vpermilps(imm(0xb1), ymm8, ymm3) vmulps(ymm0, ymm8, ymm8) vmulps(ymm1, ymm3, ymm3) vaddsubps(ymm3, ymm8, ymm8) vpermilps(imm(0xb1), ymm9, ymm3) vmulps(ymm0, ymm9, ymm9) vmulps(ymm1, ymm3, ymm3) vaddsubps(ymm3, ymm9, ymm9) vpermilps(imm(0xb1), ymm12, ymm3) vmulps(ymm0, ymm12, ymm12) vmulps(ymm1, ymm3, ymm3) vaddsubps(ymm3, ymm12, ymm12) vpermilps(imm(0xb1), ymm13, ymm3) vmulps(ymm0, ymm13, ymm13) vmulps(ymm1, ymm3, ymm3) vaddsubps(ymm3, ymm13, ymm13) mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rbx), ymm1) // load beta_r and duplicate vbroadcastss(mem(rbx, 4), ymm2) // load beta_i and duplicate // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm1) // set ZF if beta_r == 0. sete(r8b) // r8b = ( ZF == 1 ? 1 : 0 ); vucomiss(xmm0, xmm2) // set ZF if beta_i == 0. sete(r9b) // r9b = ( ZF == 1 ? 1 : 0 ); and(r8b, r9b) // set ZF if r8b & r9b == 1. jne(.CBETAZERO) // if ZF = 1, jump to beta == 0 case CGEMM_INPUT_SCALE_RS_BETA_NZ(mem(rcx)) vaddps(ymm4, ymm0, ymm0) vmovups(ymm0, mem(rcx)) CGEMM_INPUT_SCALE_RS_BETA_NZ(mem(rcx,32)) vaddps(ymm5, ymm0, ymm0) vmovups(ymm0, mem(rcx,32)) CGEMM_INPUT_SCALE_RS_BETA_NZ(mem(r11)) vaddps(ymm8, ymm0, ymm0) vmovups(ymm0, mem(r11)) CGEMM_INPUT_SCALE_RS_BETA_NZ(mem(r11,32)) vaddps(ymm9, ymm0, ymm0) vmovups(ymm0, mem(r11,32)) CGEMM_INPUT_SCALE_RS_BETA_NZ(mem(r12)) vaddps(ymm12, ymm0, ymm0) vmovups(ymm0, mem(r12)) CGEMM_INPUT_SCALE_RS_BETA_NZ(mem(r12,32)) vaddps(ymm13, ymm0, ymm0) vmovups(ymm0, mem(r12,32)) jmp(.CDONE) // jump to end. label(.CBETAZERO) vmovups(ymm4, mem(rcx)) vmovups(ymm5, mem(rcx,32)) vmovups(ymm8, mem(r11)) vmovups(ymm9, mem(r11,32)) vmovups(ymm12, mem(r12)) vmovups(ymm13, mem(r12,32)) label(.CDONE) vzeroupper() end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), // 0 [k_left] "m" (k_left), // 1 [a] "m" (a), // 2 [b] "m" (b), // 3 [alpha] "m" (alpha), // 4 [beta] "m" (beta), // 5 [c] "m" (c), // 6 [rs_c] "m" (rs_c), // 7 [cs_c] "m" (cs_c)/*, // 8 [b_next] "m" (b_next), // 9 [a_next] "m" (a_next)*/ // 10 : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) GEMM_UKR_FLUSH_CT( c ); } #define ZGEMM_INPUT_SCALE_RS_BETA_NZ(where) \ vmovupd(where, ymm0) \ vpermilpd(imm(0x5), ymm0, ymm3) \ vmulpd(ymm1, ymm0, ymm0) \ vmulpd(ymm2, ymm3, ymm3) \ vaddsubpd(ymm3, ymm0, ymm0) void bli_zgemm_haswell_asm_3x4 ( dim_t m, dim_t n, dim_t k, dcomplex* restrict alpha, dcomplex* restrict a, dcomplex* restrict b, dcomplex* restrict beta, dcomplex* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k / 4; uint64_t k_left = k % 4; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; GEMM_UKR_SETUP_CT( z, 3, 4, true ); begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(b), rbx) // load address of b. //mov(%9, r15) // load address of b_next. add(imm(32*4), rbx) // initialize loop by pre-loading vmovapd(mem(rbx, -4*32), ymm0) vmovapd(mem(rbx, -3*32), ymm1) mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(dcomplex) lea(mem(, rdi, 2), rdi) lea(mem(rcx, rdi, 1), r11) // r11 = c + 1*rs_c; lea(mem(rcx, rdi, 2), r12) // r12 = c + 2*rs_c; prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c prefetch(0, mem(r11, 7*8)) // prefetch c + 1*rs_c prefetch(0, mem(r12, 7*8)) // prefetch c + 2*rs_c mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.ZCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.ZLOOPKITER) // MAIN LOOP // iteration 0 prefetch(0, mem(rax, 32*16)) vbroadcastsd(mem(rax, 0*8), ymm2) vbroadcastsd(mem(rax, 1*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, 2*8), ymm2) vbroadcastsd(mem(rax, 3*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, 4*8), ymm2) vbroadcastsd(mem(rax, 5*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) vmovapd(mem(rbx, -2*32), ymm0) vmovapd(mem(rbx, -1*32), ymm1) // iteration 1 prefetch(0, mem(rax, 36*16)) vbroadcastsd(mem(rax, 6*8), ymm2) vbroadcastsd(mem(rax, 7*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, 8*8), ymm2) vbroadcastsd(mem(rax, 9*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, 10*8), ymm2) vbroadcastsd(mem(rax, 11*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) vmovapd(mem(rbx, 0*32), ymm0) vmovapd(mem(rbx, 1*32), ymm1) // iteration 2 prefetch(0, mem(rax, 40*16)) vbroadcastsd(mem(rax, 12*8), ymm2) vbroadcastsd(mem(rax, 13*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, 14*8), ymm2) vbroadcastsd(mem(rax, 15*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, 16*8), ymm2) vbroadcastsd(mem(rax, 17*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) vmovapd(mem(rbx, 2*32), ymm0) vmovapd(mem(rbx, 3*32), ymm1) // iteration 3 vbroadcastsd(mem(rax, 18*8), ymm2) vbroadcastsd(mem(rax, 19*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, 20*8), ymm2) vbroadcastsd(mem(rax, 21*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, 22*8), ymm2) vbroadcastsd(mem(rax, 23*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) add(imm(4*3*16), rax) // a += 4*3 (unroll x mr) add(imm(4*4*16), rbx) // b += 4*4 (unroll x nr) vmovapd(mem(rbx, -4*32), ymm0) vmovapd(mem(rbx, -3*32), ymm1) dec(rsi) // i -= 1; jne(.ZLOOPKITER) // iterate again if i != 0. label(.ZCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.ZPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.ZLOOPKLEFT) // EDGE LOOP prefetch(0, mem(rax, 32*16)) vbroadcastsd(mem(rax, 0*8), ymm2) vbroadcastsd(mem(rax, 1*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, 2*8), ymm2) vbroadcastsd(mem(rax, 3*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, 4*8), ymm2) vbroadcastsd(mem(rax, 5*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) add(imm(1*3*16), rax) // a += 1*3 (unroll x mr) add(imm(1*4*16), rbx) // b += 1*4 (unroll x nr) vmovapd(mem(rbx, -4*32), ymm0) vmovapd(mem(rbx, -3*32), ymm1) dec(rsi) // i -= 1; jne(.ZLOOPKLEFT) // iterate again if i != 0. label(.ZPOSTACCUM) // permute even and odd elements // of ymm6/7, ymm10/11, ymm/14/15 vpermilpd(imm(0x5), ymm6, ymm6) vpermilpd(imm(0x5), ymm7, ymm7) vpermilpd(imm(0x5), ymm10, ymm10) vpermilpd(imm(0x5), ymm11, ymm11) vpermilpd(imm(0x5), ymm14, ymm14) vpermilpd(imm(0x5), ymm15, ymm15) // subtract/add even/odd elements vaddsubpd(ymm6, ymm4, ymm4) vaddsubpd(ymm7, ymm5, ymm5) vaddsubpd(ymm10, ymm8, ymm8) vaddsubpd(ymm11, ymm9, ymm9) vaddsubpd(ymm14, ymm12, ymm12) vaddsubpd(ymm15, ymm13, ymm13) mov(var(alpha), rax) // load address of alpha vbroadcastsd(mem(rax), ymm0) // load alpha_r and duplicate vbroadcastsd(mem(rax, 8), ymm1) // load alpha_i and duplicate vpermilpd(imm(0x5), ymm4, ymm3) vmulpd(ymm0, ymm4, ymm4) vmulpd(ymm1, ymm3, ymm3) vaddsubpd(ymm3, ymm4, ymm4) vpermilpd(imm(0x5), ymm5, ymm3) vmulpd(ymm0, ymm5, ymm5) vmulpd(ymm1, ymm3, ymm3) vaddsubpd(ymm3, ymm5, ymm5) vpermilpd(imm(0x5), ymm8, ymm3) vmulpd(ymm0, ymm8, ymm8) vmulpd(ymm1, ymm3, ymm3) vaddsubpd(ymm3, ymm8, ymm8) vpermilpd(imm(0x5), ymm9, ymm3) vmulpd(ymm0, ymm9, ymm9) vmulpd(ymm1, ymm3, ymm3) vaddsubpd(ymm3, ymm9, ymm9) vpermilpd(imm(0x5), ymm12, ymm3) vmulpd(ymm0, ymm12, ymm12) vmulpd(ymm1, ymm3, ymm3) vaddsubpd(ymm3, ymm12, ymm12) vpermilpd(imm(0x5), ymm13, ymm3) vmulpd(ymm0, ymm13, ymm13) vmulpd(ymm1, ymm3, ymm3) vaddsubpd(ymm3, ymm13, ymm13) mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rbx), ymm1) // load beta_r and duplicate vbroadcastsd(mem(rbx, 8), ymm2) // load beta_i and duplicate // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm1) // set ZF if beta_r == 0. sete(r8b) // r8b = ( ZF == 1 ? 1 : 0 ); vucomisd(xmm0, xmm2) // set ZF if beta_i == 0. sete(r9b) // r9b = ( ZF == 1 ? 1 : 0 ); and(r8b, r9b) // set ZF if r8b & r9b == 1. jne(.ZBETAZERO) // if ZF = 1, jump to beta == 0 case ZGEMM_INPUT_SCALE_RS_BETA_NZ(mem(rcx)) vaddpd(ymm4, ymm0, ymm0) vmovupd(ymm0, mem(rcx)) ZGEMM_INPUT_SCALE_RS_BETA_NZ(mem(rcx,32)) vaddpd(ymm5, ymm0, ymm0) vmovupd(ymm0, mem(rcx,32)) ZGEMM_INPUT_SCALE_RS_BETA_NZ(mem(r11)) vaddpd(ymm8, ymm0, ymm0) vmovupd(ymm0, mem(r11)) ZGEMM_INPUT_SCALE_RS_BETA_NZ(mem(r11,32)) vaddpd(ymm9, ymm0, ymm0) vmovupd(ymm0, mem(r11,32)) ZGEMM_INPUT_SCALE_RS_BETA_NZ(mem(r12)) vaddpd(ymm12, ymm0, ymm0) vmovupd(ymm0, mem(r12)) ZGEMM_INPUT_SCALE_RS_BETA_NZ(mem(r12,32)) vaddpd(ymm13, ymm0, ymm0) vmovupd(ymm0, mem(r12,32)) jmp(.ZDONE) // jump to end. label(.ZBETAZERO) vmovupd(ymm4, mem(rcx)) vmovupd(ymm5, mem(rcx,32)) vmovupd(ymm8, mem(r11)) vmovupd(ymm9, mem(r11,32)) vmovupd(ymm12, mem(r12)) vmovupd(ymm13, mem(r12,32)) label(.ZDONE) vzeroupper() end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), // 0 [k_left] "m" (k_left), // 1 [a] "m" (a), // 2 [b] "m" (b), // 3 [alpha] "m" (alpha), // 4 [beta] "m" (beta), // 5 [c] "m" (c), // 6 [rs_c] "m" (rs_c), // 7 [cs_c] "m" (cs_c)/*, // 8 [b_next] "m" (b_next), // 9 [a_next] "m" (a_next)*/ // 10 : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) GEMM_UKR_FLUSH_CT( z ); } blis-0.9.0/kernels/haswell/3/bli_gemm_haswell_asm_d8x6.c000066400000000000000000001167141422157504600231040ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define BLIS_ASM_SYNTAX_ATT #include "bli_x86_asm_macros.h" #define SGEMM_INPUT_GS_BETA_NZ \ vmovlps(mem(rcx), xmm0, xmm0) \ vmovhps(mem(rcx, rsi, 1), xmm0, xmm0) \ vmovlps(mem(rcx, rsi, 2), xmm1, xmm1) \ vmovhps(mem(rcx, r13, 1), xmm1, xmm1) \ vshufps(imm(0x88), xmm1, xmm0, xmm0) \ vmovlps(mem(rcx, rsi, 4), xmm2, xmm2) \ vmovhps(mem(rcx, r15, 1), xmm2, xmm2) \ /* We can't use vmovhps for loading the last element becauase that might result in reading beyond valid memory. (vmov[lh]psd load pairs of adjacent floats at a time.) So we need to use vmovss instead. But since we're limited to using ymm0 through ymm2 (ymm3 contains beta and ymm4 through ymm15 contain the microtile) and due to the way vmovss zeros out all bits above 31, we have to load element 7 before element 6. */ \ vmovss(mem(rcx, r10, 1), xmm1) \ vpermilps(imm(0xcf), xmm1, xmm1) \ vmovlps(mem(rcx, r13, 2), xmm1, xmm1) \ /*vmovhps(mem(rcx, r10, 1), xmm1, xmm1)*/ \ vshufps(imm(0x88), xmm1, xmm2, xmm2) \ vperm2f128(imm(0x20), ymm2, ymm0, ymm0) #define SGEMM_OUTPUT_GS_BETA_NZ \ vextractf128(imm(1), ymm0, xmm2) \ vmovss(xmm0, mem(rcx)) \ vpermilps(imm(0x39), xmm0, xmm1) \ vmovss(xmm1, mem(rcx, rsi, 1)) \ vpermilps(imm(0x39), xmm1, xmm0) \ vmovss(xmm0, mem(rcx, rsi, 2)) \ vpermilps(imm(0x39), xmm0, xmm1) \ vmovss(xmm1, mem(rcx, r13, 1)) \ vmovss(xmm2, mem(rcx, rsi, 4)) \ vpermilps(imm(0x39), xmm2, xmm1) \ vmovss(xmm1, mem(rcx, r15, 1)) \ vpermilps(imm(0x39), xmm1, xmm2) \ vmovss(xmm2, mem(rcx, r13, 2)) \ vpermilps(imm(0x39), xmm2, xmm1) \ vmovss(xmm1, mem(rcx, r10, 1)) void bli_sgemm_haswell_asm_16x6 ( dim_t m, dim_t n, dim_t k, float* restrict alpha, float* restrict a, float* restrict b, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k / 4; uint64_t k_left = k % 4; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; GEMM_UKR_SETUP_CT( s, 16, 6, false ); begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(b), rbx) // load address of b. //mov(%9, r15) // load address of b_next. add(imm(32*4), rax) // initialize loop by pre-loading vmovaps(mem(rax, -4*32), ymm0) vmovaps(mem(rax, -3*32), ymm1) mov(var(c), rcx) // load address of c mov(var(cs_c), rdi) // load cs_c lea(mem(, rdi, 4), rdi) // cs_c *= sizeof(float) lea(mem(rdi, rdi, 2), r13) // r13 = 3*cs_c; lea(mem(rcx, r13, 1), rdx) // rdx = c + 3*cs_c; prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rdi, 1, 7*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rdi, 2, 7*8)) // prefetch c + 2*cs_c prefetch(0, mem(rdx, 7*8)) // prefetch c + 3*cs_c prefetch(0, mem(rdx, rdi, 1, 7*8)) // prefetch c + 4*cs_c prefetch(0, mem(rdx, rdi, 2, 7*8)) // prefetch c + 5*cs_c mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // iteration 0 prefetch(0, mem(rax, 128*4)) vbroadcastss(mem(rbx, 0*4), ymm2) vbroadcastss(mem(rbx, 1*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rbx, 2*4), ymm2) vbroadcastss(mem(rbx, 3*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rbx, 4*4), ymm2) vbroadcastss(mem(rbx, 5*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) vmovaps(mem(rax, -2*32), ymm0) vmovaps(mem(rax, -1*32), ymm1) // iteration 1 vbroadcastss(mem(rbx, 6*4), ymm2) vbroadcastss(mem(rbx, 7*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rbx, 8*4), ymm2) vbroadcastss(mem(rbx, 9*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rbx, 10*4), ymm2) vbroadcastss(mem(rbx, 11*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) vmovaps(mem(rax, 0*32), ymm0) vmovaps(mem(rax, 1*32), ymm1) // iteration 2 prefetch(0, mem(rax, 152*4)) vbroadcastss(mem(rbx, 12*4), ymm2) vbroadcastss(mem(rbx, 13*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rbx, 14*4), ymm2) vbroadcastss(mem(rbx, 15*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rbx, 16*4), ymm2) vbroadcastss(mem(rbx, 17*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) vmovaps(mem(rax, 2*32), ymm0) vmovaps(mem(rax, 3*32), ymm1) // iteration 3 vbroadcastss(mem(rbx, 18*4), ymm2) vbroadcastss(mem(rbx, 19*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rbx, 20*4), ymm2) vbroadcastss(mem(rbx, 21*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rbx, 22*4), ymm2) vbroadcastss(mem(rbx, 23*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) add(imm(4*16*4), rax) // a += 4*16 (unroll x mr) add(imm(4*6*4), rbx) // b += 4*6 (unroll x nr) vmovaps(mem(rax, -4*32), ymm0) vmovaps(mem(rax, -3*32), ymm1) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP prefetch(0, mem(rax, 128*4)) vbroadcastss(mem(rbx, 0*4), ymm2) vbroadcastss(mem(rbx, 1*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rbx, 2*4), ymm2) vbroadcastss(mem(rbx, 3*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rbx, 4*4), ymm2) vbroadcastss(mem(rbx, 5*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) add(imm(1*16*4), rax) // a += 1*16 (unroll x mr) add(imm(1*6*4), rbx) // b += 1*6 (unroll x nr) vmovaps(mem(rax, -4*32), ymm0) vmovaps(mem(rax, -3*32), ymm1) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), ymm0) // load alpha and duplicate vbroadcastss(mem(rbx), ymm3) // load beta and duplicate vmulps(ymm0, ymm4, ymm4) // scale by alpha vmulps(ymm0, ymm5, ymm5) vmulps(ymm0, ymm6, ymm6) vmulps(ymm0, ymm7, ymm7) vmulps(ymm0, ymm8, ymm8) vmulps(ymm0, ymm9, ymm9) vmulps(ymm0, ymm10, ymm10) vmulps(ymm0, ymm11, ymm11) vmulps(ymm0, ymm12, ymm12) vmulps(ymm0, ymm13, ymm13) vmulps(ymm0, ymm14, ymm14) vmulps(ymm0, ymm15, ymm15) // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case vfmadd231ps(mem(rcx), ymm3, ymm4) vmovups(ymm4, mem(rcx)) vfmadd231ps(mem(rcx,32), ymm3, ymm5) vmovups(ymm5, mem(rcx,32)) add(rdi, rcx) vfmadd231ps(mem(rcx), ymm3, ymm6) vmovups(ymm6, mem(rcx)) vfmadd231ps(mem(rcx,32), ymm3, ymm7) vmovups(ymm7, mem(rcx,32)) add(rdi, rcx) vfmadd231ps(mem(rcx), ymm3, ymm8) vmovups(ymm8, mem(rcx)) vfmadd231ps(mem(rcx,32), ymm3, ymm9) vmovups(ymm9, mem(rcx,32)) add(rdi, rcx) vfmadd231ps(mem(rcx), ymm3, ymm10) vmovups(ymm10, mem(rcx)) vfmadd231ps(mem(rcx,32), ymm3, ymm11) vmovups(ymm11, mem(rcx,32)) add(rdi, rcx) vfmadd231ps(mem(rcx), ymm3, ymm12) vmovups(ymm12, mem(rcx)) vfmadd231ps(mem(rcx,32), ymm3, ymm13) vmovups(ymm13, mem(rcx,32)) add(rdi, rcx) vfmadd231ps(mem(rcx), ymm3, ymm14) vmovups(ymm14, mem(rcx)) vfmadd231ps(mem(rcx,32), ymm3, ymm15) vmovups(ymm15, mem(rcx,32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SBETAZERO) vmovups(ymm4, mem(rcx)) vmovups(ymm5, mem(rcx,32)) add(rdi, rcx) vmovups(ymm6, mem(rcx)) vmovups(ymm7, mem(rcx,32)) add(rdi, rcx) vmovups(ymm8, mem(rcx)) vmovups(ymm9, mem(rcx,32)) add(rdi, rcx) vmovups(ymm10, mem(rcx)) vmovups(ymm11, mem(rcx,32)) add(rdi, rcx) vmovups(ymm12, mem(rcx)) vmovups(ymm13, mem(rcx,32)) add(rdi, rcx) vmovups(ymm14, mem(rcx)) vmovups(ymm15, mem(rcx,32)) //add(rdi, rcx) label(.SDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), // 0 [k_left] "m" (k_left), // 1 [a] "m" (a), // 2 [b] "m" (b), // 3 [alpha] "m" (alpha), // 4 [beta] "m" (beta), // 5 [c] "m" (c), // 6 [rs_c] "m" (rs_c), // 7 [cs_c] "m" (cs_c)/*, // 8 [b_next] "m" (b_next), // 9 [a_next] "m" (a_next)*/ // 10 : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) GEMM_UKR_FLUSH_CT( s ); } #define DGEMM_INPUT_GS_BETA_NZ \ vmovlpd(mem(rcx), xmm0, xmm0) \ vmovhpd(mem(rcx, rsi, 1), xmm0, xmm0) \ vmovlpd(mem(rcx, rsi, 2), xmm1, xmm1) \ vmovhpd(mem(rcx, r13, 1), xmm1, xmm1) \ vperm2f128(imm(0x20), ymm1, ymm0, ymm0) /*\ vmovlpd(mem(rcx, rsi, 4), xmm2, xmm2) \ vmovhpd(mem(rcx, r15, 1), xmm2, xmm2) \ vmovlpd(mem(rcx, r13, 2), xmm1, xmm1) \ vmovhpd(mem(rcx, r10, 1), xmm1, xmm1) \ vperm2f128(imm(0x20), ymm1, ymm2, ymm2)*/ #define DGEMM_OUTPUT_GS_BETA_NZ \ vextractf128(imm(1), ymm0, xmm1) \ vmovlpd(xmm0, mem(rcx)) \ vmovhpd(xmm0, mem(rcx, rsi, 1)) \ vmovlpd(xmm1, mem(rcx, rsi, 2)) \ vmovhpd(xmm1, mem(rcx, r13, 1)) /*\ vextractf128(imm(1), ymm2, xmm1) \ vmovlpd(xmm2, mem(rcx, rsi, 4)) \ vmovhpd(xmm2, mem(rcx, r15, 1)) \ vmovlpd(xmm1, mem(rcx, r13, 2)) \ vmovhpd(xmm1, mem(rcx, r10, 1))*/ void bli_dgemm_haswell_asm_8x6 ( dim_t m, dim_t n, dim_t k, double* restrict alpha, double* restrict a, double* restrict b, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k / 4; uint64_t k_left = k % 4; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; GEMM_UKR_SETUP_CT( d, 8, 6, false ); begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(b), rbx) // load address of b. //mov(%9, r15) // load address of b_next. add(imm(32*4), rax) // initialize loop by pre-loading vmovapd(mem(rax, -4*32), ymm0) vmovapd(mem(rax, -3*32), ymm1) mov(var(c), rcx) // load address of c mov(var(cs_c), rdi) // load cs_c lea(mem(, rdi, 8), rdi) // cs_c *= sizeof(double) lea(mem(rdi, rdi, 2), r13) // r13 = 3*cs_c; lea(mem(rcx, r13, 1), rdx) // rdx = c + 3*cs_c; prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rdi, 1, 7*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rdi, 2, 7*8)) // prefetch c + 2*cs_c prefetch(0, mem(rdx, 7*8)) // prefetch c + 3*cs_c prefetch(0, mem(rdx, rdi, 1, 7*8)) // prefetch c + 4*cs_c prefetch(0, mem(rdx, rdi, 2, 7*8)) // prefetch c + 5*cs_c mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.DLOOPKITER) // MAIN LOOP // iteration 0 prefetch(0, mem(rax, 64*8)) vbroadcastsd(mem(rbx, 0*8), ymm2) vbroadcastsd(mem(rbx, 1*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rbx, 2*8), ymm2) vbroadcastsd(mem(rbx, 3*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rbx, 4*8), ymm2) vbroadcastsd(mem(rbx, 5*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) vmovapd(mem(rax, -2*32), ymm0) vmovapd(mem(rax, -1*32), ymm1) // iteration 1 vbroadcastsd(mem(rbx, 6*8), ymm2) vbroadcastsd(mem(rbx, 7*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rbx, 8*8), ymm2) vbroadcastsd(mem(rbx, 9*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rbx, 10*8), ymm2) vbroadcastsd(mem(rbx, 11*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) vmovapd(mem(rax, 0*32), ymm0) vmovapd(mem(rax, 1*32), ymm1) // iteration 2 prefetch(0, mem(rax, 76*8)) vbroadcastsd(mem(rbx, 12*8), ymm2) vbroadcastsd(mem(rbx, 13*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rbx, 14*8), ymm2) vbroadcastsd(mem(rbx, 15*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rbx, 16*8), ymm2) vbroadcastsd(mem(rbx, 17*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) vmovapd(mem(rax, 2*32), ymm0) vmovapd(mem(rax, 3*32), ymm1) // iteration 3 vbroadcastsd(mem(rbx, 18*8), ymm2) vbroadcastsd(mem(rbx, 19*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rbx, 20*8), ymm2) vbroadcastsd(mem(rbx, 21*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rbx, 22*8), ymm2) vbroadcastsd(mem(rbx, 23*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) add(imm(4*8*8), rax) // a += 4*8 (unroll x mr) add(imm(4*6*8), rbx) // b += 4*6 (unroll x nr) vmovapd(mem(rax, -4*32), ymm0) vmovapd(mem(rax, -3*32), ymm1) dec(rsi) // i -= 1; jne(.DLOOPKITER) // iterate again if i != 0. label(.DCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.DLOOPKLEFT) // EDGE LOOP prefetch(0, mem(rax, 64*8)) vbroadcastsd(mem(rbx, 0*8), ymm2) vbroadcastsd(mem(rbx, 1*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rbx, 2*8), ymm2) vbroadcastsd(mem(rbx, 3*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rbx, 4*8), ymm2) vbroadcastsd(mem(rbx, 5*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) add(imm(1*8*8), rax) // a += 1*8 (unroll x mr) add(imm(1*6*8), rbx) // b += 1*6 (unroll x nr) vmovapd(mem(rax, -4*32), ymm0) vmovapd(mem(rax, -3*32), ymm1) dec(rsi) // i -= 1; jne(.DLOOPKLEFT) // iterate again if i != 0. label(.DPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(ymm0, ymm5, ymm5) vmulpd(ymm0, ymm6, ymm6) vmulpd(ymm0, ymm7, ymm7) vmulpd(ymm0, ymm8, ymm8) vmulpd(ymm0, ymm9, ymm9) vmulpd(ymm0, ymm10, ymm10) vmulpd(ymm0, ymm11, ymm11) vmulpd(ymm0, ymm12, ymm12) vmulpd(ymm0, ymm13, ymm13) vmulpd(ymm0, ymm14, ymm14) vmulpd(ymm0, ymm15, ymm15) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case vfmadd231pd(mem(rcx), ymm3, ymm4) vmovupd(ymm4, mem(rcx)) vfmadd231pd(mem(rcx,32), ymm3, ymm5) vmovupd(ymm5, mem(rcx,32)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm6) vmovupd(ymm6, mem(rcx)) vfmadd231pd(mem(rcx,32), ymm3, ymm7) vmovupd(ymm7, mem(rcx,32)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm8) vmovupd(ymm8, mem(rcx)) vfmadd231pd(mem(rcx,32), ymm3, ymm9) vmovupd(ymm9, mem(rcx,32)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm10) vmovupd(ymm10, mem(rcx)) vfmadd231pd(mem(rcx,32), ymm3, ymm11) vmovupd(ymm11, mem(rcx,32)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm12) vmovupd(ymm12, mem(rcx)) vfmadd231pd(mem(rcx,32), ymm3, ymm13) vmovupd(ymm13, mem(rcx,32)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm14) vmovupd(ymm14, mem(rcx)) vfmadd231pd(mem(rcx,32), ymm3, ymm15) vmovupd(ymm15, mem(rcx,32)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) vmovupd(ymm4, mem(rcx)) vmovupd(ymm5, mem(rcx,32)) add(rdi, rcx) vmovupd(ymm6, mem(rcx)) vmovupd(ymm7, mem(rcx,32)) add(rdi, rcx) vmovupd(ymm8, mem(rcx)) vmovupd(ymm9, mem(rcx,32)) add(rdi, rcx) vmovupd(ymm10, mem(rcx)) vmovupd(ymm11, mem(rcx,32)) add(rdi, rcx) vmovupd(ymm12, mem(rcx)) vmovupd(ymm13, mem(rcx,32)) add(rdi, rcx) vmovupd(ymm14, mem(rcx)) vmovupd(ymm15, mem(rcx,32)) //add(rdi, rcx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), // 0 [k_left] "m" (k_left), // 1 [a] "m" (a), // 2 [b] "m" (b), // 3 [alpha] "m" (alpha), // 4 [beta] "m" (beta), // 5 [c] "m" (c), // 6 [rs_c] "m" (rs_c), // 7 [cs_c] "m" (cs_c)/*, // 8 [b_next] "m" (b_next), // 9 [a_next] "m" (a_next)*/ // 10 : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) GEMM_UKR_FLUSH_CT( d ); } #define CGEMM_INPUT_SCALE_CS_BETA_NZ(where) \ vmovups(where, ymm0) \ vpermilps(imm(0xb1), ymm0, ymm3) \ vmulps(ymm1, ymm0, ymm0) \ vmulps(ymm2, ymm3, ymm3) \ vaddsubps(ymm3, ymm0, ymm0) void bli_cgemm_haswell_asm_8x3 ( dim_t m, dim_t n, dim_t k, scomplex* restrict alpha, scomplex* restrict a, scomplex* restrict b, scomplex* restrict beta, scomplex* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k / 4; uint64_t k_left = k % 4; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; GEMM_UKR_SETUP_CT( c, 8, 3, false ); begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(b), rbx) // load address of b. //mov(%9, r15) // load address of b_next. add(imm(32*4), rax) // initialize loop by pre-loading vmovaps(mem(rax, -4*32), ymm0) vmovaps(mem(rax, -3*32), ymm1) mov(var(c), rcx) // load address of c mov(var(cs_c), rdi) // load cs_c lea(mem(, rdi, 8), rdi) // cs_c *= sizeof(scomplex) lea(mem(rcx, rdi, 1), r11) // r11 = c + 1*cs_c; lea(mem(rcx, rdi, 2), r12) // r12 = c + 2*cs_c; prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*cs_c prefetch(0, mem(r11, 7*8)) // prefetch c + 1*cs_c prefetch(0, mem(r12, 7*8)) // prefetch c + 2*cs_c mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.CCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.CLOOPKITER) // MAIN LOOP // iteration 0 prefetch(0, mem(rax, 32*8)) vbroadcastss(mem(rbx, 0*4), ymm2) vbroadcastss(mem(rbx, 1*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rbx, 2*4), ymm2) vbroadcastss(mem(rbx, 3*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rbx, 4*4), ymm2) vbroadcastss(mem(rbx, 5*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) vmovaps(mem(rax, -2*32), ymm0) vmovaps(mem(rax, -1*32), ymm1) // iteration 1 vbroadcastss(mem(rbx, 6*4), ymm2) vbroadcastss(mem(rbx, 7*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rbx, 8*4), ymm2) vbroadcastss(mem(rbx, 9*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rbx, 10*4), ymm2) vbroadcastss(mem(rbx, 11*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) vmovaps(mem(rax, 0*32), ymm0) vmovaps(mem(rax, 1*32), ymm1) // iteration 2 prefetch(0, mem(rax, 38*8)) vbroadcastss(mem(rbx, 12*4), ymm2) vbroadcastss(mem(rbx, 13*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rbx, 14*4), ymm2) vbroadcastss(mem(rbx, 15*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rbx, 16*4), ymm2) vbroadcastss(mem(rbx, 17*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) vmovaps(mem(rax, 2*32), ymm0) vmovaps(mem(rax, 3*32), ymm1) // iteration 3 vbroadcastss(mem(rbx, 18*4), ymm2) vbroadcastss(mem(rbx, 19*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rbx, 20*4), ymm2) vbroadcastss(mem(rbx, 21*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rbx, 22*4), ymm2) vbroadcastss(mem(rbx, 23*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) add(imm(4*8*8), rax) // a += 4*8 (unroll x mr) add(imm(4*3*8), rbx) // b += 4*3 (unroll x nr) vmovaps(mem(rax, -4*32), ymm0) vmovaps(mem(rax, -3*32), ymm1) dec(rsi) // i -= 1; jne(.CLOOPKITER) // iterate again if i != 0. label(.CCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.CPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.CLOOPKLEFT) // EDGE LOOP prefetch(0, mem(rax, 32*8)) vbroadcastss(mem(rbx, 0*4), ymm2) vbroadcastss(mem(rbx, 1*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rbx, 2*4), ymm2) vbroadcastss(mem(rbx, 3*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rbx, 4*4), ymm2) vbroadcastss(mem(rbx, 5*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) add(imm(1*8*8), rax) // a += 1*8 (unroll x mr) add(imm(1*3*8), rbx) // b += 1*3 (unroll x nr) vmovaps(mem(rax, -4*32), ymm0) vmovaps(mem(rax, -3*32), ymm1) dec(rsi) // i -= 1; jne(.CLOOPKLEFT) // iterate again if i != 0. label(.CPOSTACCUM) // permute even and odd elements // of ymm6/7, ymm10/11, ymm/14/15 vpermilps(imm(0xb1), ymm6, ymm6) vpermilps(imm(0xb1), ymm7, ymm7) vpermilps(imm(0xb1), ymm10, ymm10) vpermilps(imm(0xb1), ymm11, ymm11) vpermilps(imm(0xb1), ymm14, ymm14) vpermilps(imm(0xb1), ymm15, ymm15) // subtract/add even/odd elements vaddsubps(ymm6, ymm4, ymm4) vaddsubps(ymm7, ymm5, ymm5) vaddsubps(ymm10, ymm8, ymm8) vaddsubps(ymm11, ymm9, ymm9) vaddsubps(ymm14, ymm12, ymm12) vaddsubps(ymm15, ymm13, ymm13) mov(var(alpha), rax) // load address of alpha vbroadcastss(mem(rax), ymm0) // load alpha_r and duplicate vbroadcastss(mem(rax, 4), ymm1) // load alpha_i and duplicate vpermilps(imm(0xb1), ymm4, ymm3) vmulps(ymm0, ymm4, ymm4) vmulps(ymm1, ymm3, ymm3) vaddsubps(ymm3, ymm4, ymm4) vpermilps(imm(0xb1), ymm5, ymm3) vmulps(ymm0, ymm5, ymm5) vmulps(ymm1, ymm3, ymm3) vaddsubps(ymm3, ymm5, ymm5) vpermilps(imm(0xb1), ymm8, ymm3) vmulps(ymm0, ymm8, ymm8) vmulps(ymm1, ymm3, ymm3) vaddsubps(ymm3, ymm8, ymm8) vpermilps(imm(0xb1), ymm9, ymm3) vmulps(ymm0, ymm9, ymm9) vmulps(ymm1, ymm3, ymm3) vaddsubps(ymm3, ymm9, ymm9) vpermilps(imm(0xb1), ymm12, ymm3) vmulps(ymm0, ymm12, ymm12) vmulps(ymm1, ymm3, ymm3) vaddsubps(ymm3, ymm12, ymm12) vpermilps(imm(0xb1), ymm13, ymm3) vmulps(ymm0, ymm13, ymm13) vmulps(ymm1, ymm3, ymm3) vaddsubps(ymm3, ymm13, ymm13) mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rbx), ymm1) // load beta_r and duplicate vbroadcastss(mem(rbx, 4), ymm2) // load beta_i and duplicate // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm1) // set ZF if beta_r == 0. sete(r8b) // r8b = ( ZF == 1 ? 1 : 0 ); vucomiss(xmm0, xmm2) // set ZF if beta_i == 0. sete(r9b) // r9b = ( ZF == 1 ? 1 : 0 ); and(r8b, r9b) // set ZF if r8b & r9b == 1. jne(.CBETAZERO) // if ZF = 1, jump to beta == 0 case CGEMM_INPUT_SCALE_CS_BETA_NZ(mem(rcx)) vaddps(ymm4, ymm0, ymm0) vmovups(ymm0, mem(rcx)) CGEMM_INPUT_SCALE_CS_BETA_NZ(mem(rcx,32)) vaddps(ymm5, ymm0, ymm0) vmovups(ymm0, mem(rcx,32)) CGEMM_INPUT_SCALE_CS_BETA_NZ(mem(r11)) vaddps(ymm8, ymm0, ymm0) vmovups(ymm0, mem(r11)) CGEMM_INPUT_SCALE_CS_BETA_NZ(mem(r11,32)) vaddps(ymm9, ymm0, ymm0) vmovups(ymm0, mem(r11,32)) CGEMM_INPUT_SCALE_CS_BETA_NZ(mem(r12)) vaddps(ymm12, ymm0, ymm0) vmovups(ymm0, mem(r12)) CGEMM_INPUT_SCALE_CS_BETA_NZ(mem(r12,32)) vaddps(ymm13, ymm0, ymm0) vmovups(ymm0, mem(r12,32)) jmp(.CDONE) // jump to end. label(.CBETAZERO) vmovups(ymm4, mem(rcx)) vmovups(ymm5, mem(rcx,32)) vmovups(ymm8, mem(r11)) vmovups(ymm9, mem(r11,32)) vmovups(ymm12, mem(r12)) vmovups(ymm13, mem(r12,32)) label(.CDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), // 0 [k_left] "m" (k_left), // 1 [a] "m" (a), // 2 [b] "m" (b), // 3 [alpha] "m" (alpha), // 4 [beta] "m" (beta), // 5 [c] "m" (c), // 6 [rs_c] "m" (rs_c), // 7 [cs_c] "m" (cs_c)/*, // 8 [b_next] "m" (b_next), // 9 [a_next] "m" (a_next)*/ // 10 : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) GEMM_UKR_FLUSH_CT( c ); } #define ZGEMM_INPUT_SCALE_CS_BETA_NZ(where) \ vmovups(where, ymm0) \ vpermilpd(imm(0x5), ymm0, ymm3) \ vmulpd(ymm1, ymm0, ymm0) \ vmulpd(ymm2, ymm3, ymm3) \ vaddsubpd(ymm3, ymm0, ymm0) void bli_zgemm_haswell_asm_4x3 ( dim_t m, dim_t n, dim_t k, dcomplex* restrict alpha, dcomplex* restrict a, dcomplex* restrict b, dcomplex* restrict beta, dcomplex* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k / 4; uint64_t k_left = k % 4; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; GEMM_UKR_SETUP_CT( z, 4, 3, false ); begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(b), rbx) // load address of b. //mov(%9, r15) // load address of b_next. add(imm(32*4), rax) // initialize loop by pre-loading vmovapd(mem(rax, -4*32), ymm0) vmovapd(mem(rax, -3*32), ymm1) mov(var(c), rcx) // load address of c mov(var(cs_c), rdi) // load cs_c lea(mem(, rdi, 8), rdi) // cs_c *= sizeof(dcomplex) lea(mem(, rdi, 2), rdi) lea(mem(rcx, rdi, 1), r11) // r11 = c + 1*cs_c; lea(mem(rcx, rdi, 2), r12) // r12 = c + 2*cs_c; prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*cs_c prefetch(0, mem(r11, 7*8)) // prefetch c + 1*cs_c prefetch(0, mem(r12, 7*8)) // prefetch c + 2*cs_c mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.ZCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.ZLOOPKITER) // MAIN LOOP // iteration 0 prefetch(0, mem(rax, 32*16)) vbroadcastsd(mem(rbx, 0*8), ymm2) vbroadcastsd(mem(rbx, 1*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rbx, 2*8), ymm2) vbroadcastsd(mem(rbx, 3*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rbx, 4*8), ymm2) vbroadcastsd(mem(rbx, 5*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) vmovapd(mem(rax, -2*32), ymm0) vmovapd(mem(rax, -1*32), ymm1) // iteration 1 vbroadcastsd(mem(rbx, 6*8), ymm2) vbroadcastsd(mem(rbx, 7*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rbx, 8*8), ymm2) vbroadcastsd(mem(rbx, 9*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rbx, 10*8), ymm2) vbroadcastsd(mem(rbx, 11*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) vmovapd(mem(rax, 0*32), ymm0) vmovapd(mem(rax, 1*32), ymm1) // iteration 2 prefetch(0, mem(rax, 38*16)) vbroadcastsd(mem(rbx, 12*8), ymm2) vbroadcastsd(mem(rbx, 13*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rbx, 14*8), ymm2) vbroadcastsd(mem(rbx, 15*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rbx, 16*8), ymm2) vbroadcastsd(mem(rbx, 17*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) vmovapd(mem(rax, 2*32), ymm0) vmovapd(mem(rax, 3*32), ymm1) // iteration 3 vbroadcastsd(mem(rbx, 18*8), ymm2) vbroadcastsd(mem(rbx, 19*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rbx, 20*8), ymm2) vbroadcastsd(mem(rbx, 21*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rbx, 22*8), ymm2) vbroadcastsd(mem(rbx, 23*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) add(imm(4*4*16), rax) // a += 4*4 (unroll x mr) add(imm(4*3*16), rbx) // b += 4*3 (unroll x nr) vmovapd(mem(rax, -4*32), ymm0) vmovapd(mem(rax, -3*32), ymm1) dec(rsi) // i -= 1; jne(.ZLOOPKITER) // iterate again if i != 0. label(.ZCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.ZPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.ZLOOPKLEFT) // EDGE LOOP prefetch(0, mem(rax, 32*16)) vbroadcastsd(mem(rbx, 0*8), ymm2) vbroadcastsd(mem(rbx, 1*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rbx, 2*8), ymm2) vbroadcastsd(mem(rbx, 3*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rbx, 4*8), ymm2) vbroadcastsd(mem(rbx, 5*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) add(imm(1*4*16), rax) // a += 1*4 (unroll x mr) add(imm(1*3*16), rbx) // b += 1*3 (unroll x nr) vmovapd(mem(rax, -4*32), ymm0) vmovapd(mem(rax, -3*32), ymm1) dec(rsi) // i -= 1; jne(.ZLOOPKLEFT) // iterate again if i != 0. label(.ZPOSTACCUM) // permute even and odd elements // of ymm6/7, ymm10/11, ymm/14/15 vpermilpd(imm(0x5), ymm6, ymm6) vpermilpd(imm(0x5), ymm7, ymm7) vpermilpd(imm(0x5), ymm10, ymm10) vpermilpd(imm(0x5), ymm11, ymm11) vpermilpd(imm(0x5), ymm14, ymm14) vpermilpd(imm(0x5), ymm15, ymm15) // subtract/add even/odd elements vaddsubpd(ymm6, ymm4, ymm4) vaddsubpd(ymm7, ymm5, ymm5) vaddsubpd(ymm10, ymm8, ymm8) vaddsubpd(ymm11, ymm9, ymm9) vaddsubpd(ymm14, ymm12, ymm12) vaddsubpd(ymm15, ymm13, ymm13) mov(var(alpha), rax) // load address of alpha vbroadcastsd(mem(rax), ymm0) // load alpha_r and duplicate vbroadcastsd(mem(rax, 8), ymm1) // load alpha_i and duplicate vpermilpd(imm(0x5), ymm4, ymm3) vmulpd(ymm0, ymm4, ymm4) vmulpd(ymm1, ymm3, ymm3) vaddsubpd(ymm3, ymm4, ymm4) vpermilpd(imm(0x5), ymm5, ymm3) vmulpd(ymm0, ymm5, ymm5) vmulpd(ymm1, ymm3, ymm3) vaddsubpd(ymm3, ymm5, ymm5) vpermilpd(imm(0x5), ymm8, ymm3) vmulpd(ymm0, ymm8, ymm8) vmulpd(ymm1, ymm3, ymm3) vaddsubpd(ymm3, ymm8, ymm8) vpermilpd(imm(0x5), ymm9, ymm3) vmulpd(ymm0, ymm9, ymm9) vmulpd(ymm1, ymm3, ymm3) vaddsubpd(ymm3, ymm9, ymm9) vpermilpd(imm(0x5), ymm12, ymm3) vmulpd(ymm0, ymm12, ymm12) vmulpd(ymm1, ymm3, ymm3) vaddsubpd(ymm3, ymm12, ymm12) vpermilpd(imm(0x5), ymm13, ymm3) vmulpd(ymm0, ymm13, ymm13) vmulpd(ymm1, ymm3, ymm3) vaddsubpd(ymm3, ymm13, ymm13) mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rbx), ymm1) // load beta_r and duplicate vbroadcastsd(mem(rbx, 8), ymm2) // load beta_i and duplicate // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm1) // set ZF if beta_r == 0. sete(r8b) // r8b = ( ZF == 1 ? 1 : 0 ); vucomisd(xmm0, xmm2) // set ZF if beta_i == 0. sete(r9b) // r9b = ( ZF == 1 ? 1 : 0 ); and(r8b, r9b) // set ZF if r8b & r9b == 1. jne(.ZBETAZERO) // if ZF = 1, jump to beta == 0 case ZGEMM_INPUT_SCALE_CS_BETA_NZ(mem(rcx)) vaddpd(ymm4, ymm0, ymm0) vmovupd(ymm0, mem(rcx)) ZGEMM_INPUT_SCALE_CS_BETA_NZ(mem(rcx,32)) vaddpd(ymm5, ymm0, ymm0) vmovupd(ymm0, mem(rcx,32)) ZGEMM_INPUT_SCALE_CS_BETA_NZ(mem(r11)) vaddpd(ymm8, ymm0, ymm0) vmovupd(ymm0, mem(r11)) ZGEMM_INPUT_SCALE_CS_BETA_NZ(mem(r11,32)) vaddpd(ymm9, ymm0, ymm0) vmovupd(ymm0, mem(r11,32)) ZGEMM_INPUT_SCALE_CS_BETA_NZ(mem(r12)) vaddpd(ymm12, ymm0, ymm0) vmovupd(ymm0, mem(r12)) ZGEMM_INPUT_SCALE_CS_BETA_NZ(mem(r12,32)) vaddpd(ymm13, ymm0, ymm0) vmovupd(ymm0, mem(r12,32)) jmp(.ZDONE) // jump to end. label(.ZBETAZERO) vmovupd(ymm4, mem(rcx)) vmovupd(ymm5, mem(rcx,32)) vmovupd(ymm8, mem(r11)) vmovupd(ymm9, mem(r11,32)) vmovupd(ymm12, mem(r12)) vmovupd(ymm13, mem(r12,32)) label(.ZDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), // 0 [k_left] "m" (k_left), // 1 [a] "m" (a), // 2 [b] "m" (b), // 3 [alpha] "m" (alpha), // 4 [beta] "m" (beta), // 5 [c] "m" (c), // 6 [rs_c] "m" (rs_c), // 7 [cs_c] "m" (cs_c)/*, // 8 [b_next] "m" (b_next), // 9 [a_next] "m" (a_next)*/ // 10 : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) GEMM_UKR_FLUSH_CT( z ); } blis-0.9.0/kernels/haswell/3/bli_gemmtrsm_l_haswell_asm_d6x8.c000066400000000000000000001215331422157504600243200ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define BLIS_ASM_SYNTAX_ATT #include "bli_x86_asm_macros.h" #define SGEMM_OUTPUT_GS_BETA_NZ \ vextractf128(imm(1), ymm0, xmm2) \ vmovss(xmm0, mem(rcx)) \ vpermilps(imm(0x39), xmm0, xmm1) \ vmovss(xmm1, mem(rcx, rsi, 1)) \ vpermilps(imm(0x39), xmm1, xmm0) \ vmovss(xmm0, mem(rcx, rsi, 2)) \ vpermilps(imm(0x39), xmm0, xmm1) \ vmovss(xmm1, mem(rcx, r13, 1)) \ vmovss(xmm2, mem(rcx, rsi, 4)) \ vpermilps(imm(0x39), xmm2, xmm1) \ vmovss(xmm1, mem(rcx, r15, 1)) \ vpermilps(imm(0x39), xmm1, xmm2) \ vmovss(xmm2, mem(rcx, r13, 2)) \ vpermilps(imm(0x39), xmm2, xmm1) \ vmovss(xmm1, mem(rcx, r10, 1)) void bli_sgemmtrsm_l_haswell_asm_6x16 ( dim_t m, dim_t n, dim_t k0, float* restrict alpha, float* restrict a10, float* restrict a11, float* restrict b01, float* restrict b11, float* restrict c11, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; float* beta = bli_sm1; GEMMTRSM_UKR_SETUP_CT_ANY( s, 6, 16, true ); begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a10), rax) // load address of a. mov(var(b01), rbx) // load address of b. add(imm(32*4), rbx) // initialize loop by pre-loading vmovaps(mem(rbx, -4*32), ymm0) vmovaps(mem(rbx, -3*32), ymm1) mov(var(b11), rcx) // load address of b11 mov(imm(16), rdi) // set rs_b = PACKNR = 16 lea(mem(, rdi, 4), rdi) // rs_b *= sizeof(float) // NOTE: c11, rs_c, and cs_c aren't // needed for a while, but we load // them now to avoid stalling later. mov(var(c11), r8) // load address of c11 mov(var(rs_c), r9) // load rs_c lea(mem(, r9 , 4), r9) // rs_c *= sizeof(float) mov(var(k_left)0, r10) // load cs_c lea(mem(, r10, 4), r10) // cs_c *= sizeof(float) mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // iteration 0 prefetch(0, mem(rax, 64*4)) vbroadcastss(mem(rax, 0*4), ymm2) vbroadcastss(mem(rax, 1*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, 2*4), ymm2) vbroadcastss(mem(rax, 3*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, 4*4), ymm2) vbroadcastss(mem(rax, 5*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) vmovaps(mem(rbx, -2*32), ymm0) vmovaps(mem(rbx, -1*32), ymm1) // iteration 1 vbroadcastss(mem(rax, 6*4), ymm2) vbroadcastss(mem(rax, 7*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, 8*4), ymm2) vbroadcastss(mem(rax, 9*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, 10*4), ymm2) vbroadcastss(mem(rax, 11*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) vmovaps(mem(rbx, 0*32), ymm0) vmovaps(mem(rbx, 1*32), ymm1) // iteration 2 prefetch(0, mem(rax, 76*4)) vbroadcastss(mem(rax, 12*4), ymm2) vbroadcastss(mem(rax, 13*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, 14*4), ymm2) vbroadcastss(mem(rax, 15*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, 16*4), ymm2) vbroadcastss(mem(rax, 17*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) vmovaps(mem(rbx, 2*32), ymm0) vmovaps(mem(rbx, 3*32), ymm1) // iteration 3 vbroadcastss(mem(rax, 18*4), ymm2) vbroadcastss(mem(rax, 19*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, 20*4), ymm2) vbroadcastss(mem(rax, 21*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, 22*4), ymm2) vbroadcastss(mem(rax, 23*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) add(imm(4*6*4), rax) // a += 4*6 (unroll x mr) add(imm(4*16*4), rbx) // b += 4*16 (unroll x nr) vmovaps(mem(rbx, -4*32), ymm0) vmovaps(mem(rbx, -3*32), ymm1) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP prefetch(0, mem(rax, 64*4)) vbroadcastss(mem(rax, 0*4), ymm2) vbroadcastss(mem(rax, 1*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, 2*4), ymm2) vbroadcastss(mem(rax, 3*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, 4*4), ymm2) vbroadcastss(mem(rax, 5*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) add(imm(1*6*4), rax) // a += 1*6 (unroll x mr) add(imm(1*16*4), rbx) // b += 1*16 (unroll x nr) vmovaps(mem(rbx, -4*32), ymm0) vmovaps(mem(rbx, -3*32), ymm1) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) // ymm4..ymm15 = -a10 * b01 mov(var(alpha), rbx) // load address of alpha vbroadcastss(mem(rbx), ymm3) // load alpha and duplicate mov(imm(1), rsi) // load cs_b = 1 lea(mem(, rsi, 4), rsi) // cs_b *= sizeof(float) lea(mem(rcx, rsi, 8), rdx) // load address of b11 + 8*cs_b mov(rcx, r11) // save rcx = b11 for later mov(rdx, r14) // save rdx = b11+8*cs_b for later // b11 := alpha * b11 - a10 * b01 vfmsub231ps(mem(rcx), ymm3, ymm4) add(rdi, rcx) vfmsub231ps(mem(rdx), ymm3, ymm5) add(rdi, rdx) vfmsub231ps(mem(rcx), ymm3, ymm6) add(rdi, rcx) vfmsub231ps(mem(rdx), ymm3, ymm7) add(rdi, rdx) vfmsub231ps(mem(rcx), ymm3, ymm8) add(rdi, rcx) vfmsub231ps(mem(rdx), ymm3, ymm9) add(rdi, rdx) vfmsub231ps(mem(rcx), ymm3, ymm10) add(rdi, rcx) vfmsub231ps(mem(rdx), ymm3, ymm11) add(rdi, rdx) vfmsub231ps(mem(rcx), ymm3, ymm12) add(rdi, rcx) vfmsub231ps(mem(rdx), ymm3, ymm13) add(rdi, rdx) vfmsub231ps(mem(rcx), ymm3, ymm14) //add(rdi, rcx) vfmsub231ps(mem(rdx), ymm3, ymm15) //add(rdi, rdx) // prefetch c11 #if 0 mov(r8, rcx) // load address of c11 from r8 // Note: r9 = rs_c * sizeof(float) lea(mem(r9 , r9 , 2), r13) // r13 = 3*rs_c; lea(mem(rcx, r13, 1), rdx) // rdx = c11 + 3*rs_c; prefetch(0, mem(rcx, 0*8)) // prefetch c11 + 0*rs_c prefetch(0, mem(rcx, r9, 1, 0*8)) // prefetch c11 + 1*rs_c prefetch(0, mem(rcx, r9 , 2, 0*8)) // prefetch c11 + 2*rs_c prefetch(0, mem(rdx, 0*8)) // prefetch c11 + 3*rs_c prefetch(0, mem(rdx, r9, 1, 0*8)) // prefetch c11 + 4*rs_c prefetch(0, mem(rdx, r9 , 2, 0*8)) // prefetch c11 + 5*rs_c #endif // trsm computation begins here // Note: contents of b11 are stored as // ymm4 ymm5 = ( beta00..07 ) ( beta08..0F ) // ymm6 ymm7 = ( beta10..17 ) ( beta18..1F ) // ymm8 ymm9 = ( beta20..27 ) ( beta28..2F ) // ymm10 ymm11 = ( beta30..37 ) ( beta38..3F ) // ymm12 ymm13 = ( beta40..47 ) ( beta48..4F ) // ymm14 ymm15 = ( beta50..57 ) ( beta58..5F ) mov(var(a11), rax) // load address of a11 mov(r11, rcx) // recall address of b11 mov(r14, rdx) // recall address of b11+8*cs_b // Note: rdi = rs_b // iteration 0 ------------- vbroadcastss(mem(0+0*6)*4(rax), ymm0) // ymm0 = (1/alpha00) #ifdef BLIS_ENABLE_TRSM_PREINVERSION vmulps(ymm0, ymm4, ymm4) // ymm4 *= (1/alpha00) vmulps(ymm0, ymm5, ymm5) // ymm5 *= (1/alpha00) #else vdivps(ymm0, ymm4, ymm4) // ymm4 /= alpha00 vdivps(ymm0, ymm5, ymm5) // ymm5 /= alpha00 #endif vmovups(ymm4, mem(rcx)) // store ( beta00..beta07 ) = ymm4 vmovups(ymm5, mem(rdx)) // store ( beta08..beta0F ) = ymm5 add(rdi, rcx) // rcx += rs_b add(rdi, rdx) // rdx += rs_b // iteration 1 ------------- vbroadcastss(mem(1+0*6)*4(rax), ymm0) // ymm0 = alpha10 vbroadcastss(mem(1+1*6)*4(rax), ymm1) // ymm1 = (1/alpha11) vmulps(ymm0, ymm4, ymm2) // ymm2 = alpha10 * ymm4 vmulps(ymm0, ymm5, ymm3) // ymm3 = alpha10 * ymm5 vsubps(ymm2, ymm6, ymm6) // ymm6 -= ymm2 vsubps(ymm3, ymm7, ymm7) // ymm7 -= ymm3 #ifdef BLIS_ENABLE_TRSM_PREINVERSION vmulps(ymm1, ymm6, ymm6) // ymm6 *= (1/alpha11) vmulps(ymm1, ymm7, ymm7) // ymm7 *= (1/alpha11) #else vdivps(ymm1, ymm6, ymm6) // ymm6 /= alpha11 vdivps(ymm1, ymm7, ymm7) // ymm7 /= alpha11 #endif vmovups(ymm6, mem(rcx)) // store ( beta10..beta17 ) = ymm6 vmovups(ymm7, mem(rdx)) // store ( beta18..beta1F ) = ymm7 add(rdi, rcx) // rcx += rs_b add(rdi, rdx) // rdx += rs_b // iteration 2 ------------- vbroadcastss(mem(2+0*6)*4(rax), ymm0) // ymm0 = alpha20 vbroadcastss(mem(2+1*6)*4(rax), ymm1) // ymm1 = alpha21 vmulps(ymm0, ymm4, ymm2) // ymm2 = alpha20 * ymm4 vmulps(ymm0, ymm5, ymm3) // ymm3 = alpha20 * ymm5 vbroadcastss(mem(2+2*6)*4(rax), ymm0) // ymm0 = (1/alpha22) vfmadd231ps(ymm1, ymm6, ymm2) // ymm2 += alpha21 * ymm6 vfmadd231ps(ymm1, ymm7, ymm3) // ymm3 += alpha21 * ymm7 vsubps(ymm2, ymm8, ymm8) // ymm8 -= ymm2 vsubps(ymm3, ymm9, ymm9) // ymm9 -= ymm3 #ifdef BLIS_ENABLE_TRSM_PREINVERSION vmulps(ymm0, ymm8, ymm8) // ymm8 *= (1/alpha22) vmulps(ymm0, ymm9, ymm9) // ymm9 *= (1/alpha22) #else vdivps(ymm0, ymm8, ymm8) // ymm8 /= alpha22 vdivps(ymm0, ymm9, ymm9) // ymm9 /= alpha22 #endif vmovups(ymm8, mem(rcx)) // store ( beta20..beta27 ) = ymm8 vmovups(ymm9, mem(rdx)) // store ( beta28..beta2F ) = ymm9 add(rdi, rcx) // rcx += rs_b add(rdi, rdx) // rdx += rs_b // iteration 3 ------------- vbroadcastss(mem(3+0*6)*4(rax), ymm0) // ymm0 = alpha30 vbroadcastss(mem(3+1*6)*4(rax), ymm1) // ymm1 = alpha31 vmulps(ymm0, ymm4, ymm2) // ymm2 = alpha30 * ymm4 vmulps(ymm0, ymm5, ymm3) // ymm3 = alpha30 * ymm5 vbroadcastss(mem(3+2*6)*4(rax), ymm0) // ymm0 = alpha32 vfmadd231ps(ymm1, ymm6, ymm2) // ymm2 += alpha31 * ymm6 vfmadd231ps(ymm1, ymm7, ymm3) // ymm3 += alpha31 * ymm7 vbroadcastss(mem(3+3*6)*4(rax), ymm1) // ymm0 = (1/alpha33) vfmadd231ps(ymm0, ymm8, ymm2) // ymm2 += alpha32 * ymm8 vfmadd231ps(ymm0, ymm9, ymm3) // ymm3 += alpha32 * ymm9 vsubps(ymm2, ymm10, ymm10) // ymm10 -= ymm2 vsubps(ymm3, ymm11, ymm11) // ymm11 -= ymm3 #ifdef BLIS_ENABLE_TRSM_PREINVERSION vmulps(ymm1, ymm10, ymm10) // ymm10 *= (1/alpha33) vmulps(ymm1, ymm11, ymm11) // ymm11 *= (1/alpha33) #else vdivps(ymm1, ymm10, ymm10) // ymm10 /= alpha33 vdivps(ymm1, ymm11, ymm11) // ymm11 /= alpha33 #endif vmovups(ymm10, mem(rcx)) // store ( beta30..beta37 ) = ymm10 vmovups(ymm11, mem(rdx)) // store ( beta38..beta3F ) = ymm11 add(rdi, rcx) // rcx += rs_b add(rdi, rdx) // rdx += rs_b // iteration 4 ------------- vbroadcastss(mem(4+0*6)*4(rax), ymm0) // ymm0 = alpha40 vbroadcastss(mem(4+1*6)*4(rax), ymm1) // ymm1 = alpha41 vmulps(ymm0, ymm4, ymm2) // ymm2 = alpha40 * ymm4 vmulps(ymm0, ymm5, ymm3) // ymm3 = alpha40 * ymm5 vbroadcastss(mem(4+2*6)*4(rax), ymm0) // ymm0 = alpha42 vfmadd231ps(ymm1, ymm6, ymm2) // ymm2 += alpha41 * ymm6 vfmadd231ps(ymm1, ymm7, ymm3) // ymm3 += alpha41 * ymm7 vbroadcastss(mem(4+3*6)*4(rax), ymm1) // ymm1 = alpha43 vfmadd231ps(ymm0, ymm8, ymm2) // ymm2 += alpha42 * ymm8 vfmadd231ps(ymm0, ymm9, ymm3) // ymm3 += alpha42 * ymm9 vbroadcastss(mem(4+4*6)*4(rax), ymm0) // ymm0 = (1/alpha44) vfmadd231ps(ymm1, ymm10, ymm2) // ymm2 += alpha43 * ymm10 vfmadd231ps(ymm1, ymm11, ymm3) // ymm3 += alpha43 * ymm11 vsubps(ymm2, ymm12, ymm12) // ymm12 -= ymm2 vsubps(ymm3, ymm13, ymm13) // ymm13 -= ymm3 #ifdef BLIS_ENABLE_TRSM_PREINVERSION vmulps(ymm0, ymm12, ymm12) // ymm12 *= (1/alpha44) vmulps(ymm0, ymm13, ymm13) // ymm13 *= (1/alpha44) #else vdivps(ymm0, ymm12, ymm12) // ymm12 /= alpha44 vdivps(ymm0, ymm13, ymm13) // ymm13 /= alpha44 #endif vmovups(ymm12, mem(rcx)) // store ( beta40..beta47 ) = ymm12 vmovups(ymm13, mem(rdx)) // store ( beta48..beta4F ) = ymm13 add(rdi, rcx) // rcx += rs_b add(rdi, rdx) // rdx += rs_b // iteration 5 ------------- vbroadcastss(mem(5+0*6)*4(rax), ymm0) // ymm0 = alpha50 vbroadcastss(mem(5+1*6)*4(rax), ymm1) // ymm1 = alpha51 vmulps(ymm0, ymm4, ymm2) // ymm2 = alpha50 * ymm4 vmulps(ymm0, ymm5, ymm3) // ymm3 = alpha50 * ymm5 vbroadcastss(mem(5+2*6)*4(rax), ymm0) // ymm0 = alpha52 vfmadd231ps(ymm1, ymm6, ymm2) // ymm2 += alpha51 * ymm6 vfmadd231ps(ymm1, ymm7, ymm3) // ymm3 += alpha51 * ymm7 vbroadcastss(mem(5+3*6)*4(rax), ymm1) // ymm1 = alpha53 vfmadd231ps(ymm0, ymm8, ymm2) // ymm2 += alpha52 * ymm8 vfmadd231ps(ymm0, ymm9, ymm3) // ymm3 += alpha52 * ymm9 vbroadcastss(mem(5+4*6)*4(rax), ymm0) // ymm0 = alpha54 vfmadd231ps(ymm1, ymm10, ymm2) // ymm2 += alpha53 * ymm10 vfmadd231ps(ymm1, ymm11, ymm3) // ymm3 += alpha53 * ymm11 vbroadcastss(mem(5+5*6)*4(rax), ymm1) // ymm1 = (1/alpha55) vfmadd231ps(ymm0, ymm12, ymm2) // ymm2 += alpha54 * ymm12 vfmadd231ps(ymm0, ymm13, ymm3) // ymm3 += alpha54 * ymm13 vsubps(ymm2, ymm14, ymm14) // ymm14 -= ymm2 vsubps(ymm3, ymm15, ymm15) // ymm15 -= ymm3 #ifdef BLIS_ENABLE_TRSM_PREINVERSION vmulps(ymm1, ymm14, ymm14) // ymm14 *= (1/alpha55) vmulps(ymm1, ymm15, ymm15) // ymm15 *= (1/alpha55) #else vdivps(ymm1, ymm14, ymm14) // ymm14 /= alpha55 vdivps(ymm1, ymm15, ymm15) // ymm15 /= alpha55 #endif vmovups(ymm14, mem(rcx)) // store ( beta50..beta57 ) = ymm14 vmovups(ymm15, mem(rdx)) // store ( beta58..beta5F ) = ymm15 add(rdi, rcx) // rcx += rs_b add(rdi, rdx) // rdx += rs_b mov(r8, rcx) // load address of c11 from r8 mov(r9, rdi) // load rs_c (in bytes) from r9 mov(r10, rsi) // load cs_c (in bytes) from r10 lea(mem(rcx, rsi, 8), rdx) // load address of c11 + 8*cs_c; lea(mem(rcx, rdi, 4), r14) // load address of c11 + 4*rs_c; // These are used in the macros below. lea(mem(rsi, rsi, 2), r13) // r13 = 3*cs_c; lea(mem(rsi, rsi, 4), r15) // r15 = 5*cs_c; lea(mem(r13, rsi, 4), r10) // r10 = 7*cs_c; cmp(imm(4), rsi) // set ZF if (4*cs_c) == 4. jz(.SROWSTORED) // jump to row storage case cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORED) // jump to column storage case // if neither row- or column- // stored, use general case. label(.SGENSTORED) vmovaps(ymm4, ymm0) SGEMM_OUTPUT_GS_BETA_NZ add(rdi, rcx) // c11 += rs_c; vmovaps(ymm6, ymm0) SGEMM_OUTPUT_GS_BETA_NZ add(rdi, rcx) // c11 += rs_c; vmovaps(ymm8, ymm0) SGEMM_OUTPUT_GS_BETA_NZ add(rdi, rcx) // c11 += rs_c; vmovaps(ymm10, ymm0) SGEMM_OUTPUT_GS_BETA_NZ add(rdi, rcx) // c11 += rs_c; vmovaps(ymm12, ymm0) SGEMM_OUTPUT_GS_BETA_NZ add(rdi, rcx) // c11 += rs_c; vmovaps(ymm14, ymm0) SGEMM_OUTPUT_GS_BETA_NZ mov(rdx, rcx) // rcx = c11 + 8*cs_c vmovaps(ymm5, ymm0) SGEMM_OUTPUT_GS_BETA_NZ add(rdi, rcx) // c11 += rs_c; vmovaps(ymm7, ymm0) SGEMM_OUTPUT_GS_BETA_NZ add(rdi, rcx) // c11 += rs_c; vmovaps(ymm9, ymm0) SGEMM_OUTPUT_GS_BETA_NZ add(rdi, rcx) // c11 += rs_c; vmovaps(ymm11, ymm0) SGEMM_OUTPUT_GS_BETA_NZ add(rdi, rcx) // c11 += rs_c; vmovaps(ymm13, ymm0) SGEMM_OUTPUT_GS_BETA_NZ add(rdi, rcx) // c11 += rs_c; vmovaps(ymm15, ymm0) SGEMM_OUTPUT_GS_BETA_NZ jmp(.SDONE) label(.SROWSTORED) vmovups(ymm4, mem(rcx)) add(rdi, rcx) vmovups(ymm5, mem(rdx)) add(rdi, rdx) vmovups(ymm6, mem(rcx)) add(rdi, rcx) vmovups(ymm7, mem(rdx)) add(rdi, rdx) vmovups(ymm8, mem(rcx)) add(rdi, rcx) vmovups(ymm9, mem(rdx)) add(rdi, rdx) vmovups(ymm10, mem(rcx)) add(rdi, rcx) vmovups(ymm11, mem(rdx)) add(rdi, rdx) vmovups(ymm12, mem(rcx)) add(rdi, rcx) vmovups(ymm13, mem(rdx)) add(rdi, rdx) vmovups(ymm14, mem(rcx)) //add(rdi, rcx) vmovups(ymm15, mem(rdx)) //add(rdi, rdx) jmp(.SDONE) label(.SCOLSTORED) vunpcklps(ymm6, ymm4, ymm0) vunpcklps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vextractf128(imm(0x1), ymm1, xmm3) vmovups(xmm0, mem(rcx)) // store ( gamma00..gamma30 ) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) vmovups(xmm3, mem(rcx, r15, 1)) // store ( gamma05..gamma35 ) vunpckhps(ymm6, ymm4, ymm0) vunpckhps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vextractf128(imm(0x1), ymm1, xmm3) vmovups(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma32 ) vmovups(xmm1, mem(rcx, r13, 1)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, r13, 2)) // store ( gamma06..gamma36 ) vmovups(xmm3, mem(rcx, r10, 1)) // store ( gamma07..gamma37 ) lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vunpcklps(ymm14, ymm12, ymm0) vunpckhps(ymm14, ymm12, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vextractf128(imm(0x1), ymm1, xmm3) vmovlpd(xmm0, mem(r14)) // store ( gamma40..gamma50 ) vmovhpd(xmm0, mem(r14, rsi, 1)) // store ( gamma41..gamma51 ) vmovlpd(xmm1, mem(r14, rsi, 2)) // store ( gamma42..gamma52 ) vmovhpd(xmm1, mem(r14, r13, 1)) // store ( gamma43..gamma53 ) vmovlpd(xmm2, mem(r14, rsi, 4)) // store ( gamma44..gamma54 ) vmovhpd(xmm2, mem(r14, r15, 1)) // store ( gamma45..gamma55 ) vmovlpd(xmm3, mem(r14, r13, 2)) // store ( gamma46..gamma56 ) vmovhpd(xmm3, mem(r14, r10, 1)) // store ( gamma47..gamma57 ) lea(mem(r14, rsi, 8), r14) // r14 += 8*cs_c vunpcklps(ymm7, ymm5, ymm0) vunpcklps(ymm11, ymm9, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vextractf128(imm(0x1), ymm1, xmm3) vmovups(xmm0, mem(rcx)) // store ( gamma08..gamma38 ) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma09..gamma39 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma0C..gamma3C ) vmovups(xmm3, mem(rcx, r15, 1)) // store ( gamma0D..gamma3D ) vunpckhps(ymm7, ymm5, ymm0) vunpckhps(ymm11, ymm9, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vextractf128(imm(0x1), ymm1, xmm3) vmovups(xmm0, mem(rcx, rsi, 2)) // store ( gamma0A..gamma3A ) vmovups(xmm1, mem(rcx, r13, 1)) // store ( gamma0B..gamma3B ) vmovups(xmm2, mem(rcx, r13, 2)) // store ( gamma0E..gamma3E ) vmovups(xmm3, mem(rcx, r10, 1)) // store ( gamma0F..gamma3F ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vunpcklps(ymm15, ymm13, ymm0) vunpckhps(ymm15, ymm13, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vextractf128(imm(0x1), ymm1, xmm3) vmovlpd(xmm0, mem(r14)) // store ( gamma48..gamma58 ) vmovhpd(xmm0, mem(r14, rsi, 1)) // store ( gamma49..gamma59 ) vmovlpd(xmm1, mem(r14, rsi, 2)) // store ( gamma4A..gamma5A ) vmovhpd(xmm1, mem(r14, r13, 1)) // store ( gamma4B..gamma5B ) vmovlpd(xmm2, mem(r14, rsi, 4)) // store ( gamma4C..gamma5C ) vmovhpd(xmm2, mem(r14, r15, 1)) // store ( gamma4D..gamma5D ) vmovlpd(xmm3, mem(r14, r13, 2)) // store ( gamma4E..gamma5E ) vmovhpd(xmm3, mem(r14, r10, 1)) // store ( gamma4F..gamma5F ) //lea(mem(r14, rsi, 8), r14) // r14 += 8*cs_c label(.SDONE) vzeroupper() end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), // 0 [k_left] "m" (k_left), // 1 [a10] "m" (a10), // 2 [b01] "m" (b01), // 3 [beta] "m" (beta), // 4 [alpha] "m" (alpha), // 5 [a11] "m" (a11), // 6 [b11] "m" (b11), // 7 [c11] "m" (c11), // 8 [rs_c] "m" (rs_c), // 9 [cs_c] "m" (cs_c) // 10 : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) GEMMTRSM_UKR_FLUSH_CT( s ); } #define DGEMM_OUTPUT_GS_BETA_NZ \ vextractf128(imm(1), ymm0, xmm1) \ vmovlpd(xmm0, mem(rcx)) \ vmovhpd(xmm0, mem(rcx, rsi, 1)) \ vmovlpd(xmm1, mem(rcx, rsi, 2)) \ vmovhpd(xmm1, mem(rcx, r13, 1)) /*\ vextractf128(imm(1), ymm2, xmm1) \ vmovlpd(xmm2, mem(rcx, rsi, 4)) \ vmovhpd(xmm2, mem(rcx, r15, 1)) \ vmovlpd(xmm1, mem(rcx, r13, 2)) \ vmovhpd(xmm1, mem(rcx, r10, 1))*/ void bli_dgemmtrsm_l_haswell_asm_6x8 ( dim_t m, dim_t n, dim_t k0, double* restrict alpha, double* restrict a10, double* restrict a11, double* restrict b01, double* restrict b11, double* restrict c11, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; double* beta = bli_dm1; GEMMTRSM_UKR_SETUP_CT_ANY( d, 6, 8, true ); begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a10), rax) // load address of a. mov(var(b01), rbx) // load address of b. add(imm(32*4), rbx) // initialize loop by pre-loading vmovapd(mem(rbx, -4*32), ymm0) vmovapd(mem(rbx, -3*32), ymm1) mov(var(b11), rcx) // load address of b11 mov(imm(8), rdi) // set rs_b = PACKNR = 8 lea(mem(, rdi, 8), rdi) // rs_b *= sizeof(double) // NOTE: c11, rs_c, and cs_c aren't // needed for a while, but we load // them now to avoid stalling later. mov(var(c11), r8) // load address of c11 mov(var(rs_c), r9) // load rs_c lea(mem(, r9 , 8), r9) // rs_c *= sizeof(double) mov(var(k_left)0, r10) // load cs_c lea(mem(, r10, 8), r10) // cs_c *= sizeof(double) mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.DLOOPKITER) // MAIN LOOP // iteration 0 prefetch(0, mem(rax, 64*8)) vbroadcastsd(mem(rax, 0*8), ymm2) vbroadcastsd(mem(rax, 1*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, 2*8), ymm2) vbroadcastsd(mem(rax, 3*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, 4*8), ymm2) vbroadcastsd(mem(rax, 5*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) vmovapd(mem(rbx, -2*32), ymm0) vmovapd(mem(rbx, -1*32), ymm1) // iteration 1 prefetch(0, mem(rax, 72*8)) vbroadcastsd(mem(rax, 6*8), ymm2) vbroadcastsd(mem(rax, 7*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, 8*8), ymm2) vbroadcastsd(mem(rax, 9*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, 10*8), ymm2) vbroadcastsd(mem(rax, 11*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) vmovapd(mem(rbx, 0*32), ymm0) vmovapd(mem(rbx, 1*32), ymm1) // iteration 2 prefetch(0, mem(rax, 80*8)) vbroadcastsd(mem(rax, 12*8), ymm2) vbroadcastsd(mem(rax, 13*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, 14*8), ymm2) vbroadcastsd(mem(rax, 15*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, 16*8), ymm2) vbroadcastsd(mem(rax, 17*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) vmovapd(mem(rbx, 2*32), ymm0) vmovapd(mem(rbx, 3*32), ymm1) // iteration 3 vbroadcastsd(mem(rax, 18*8), ymm2) vbroadcastsd(mem(rax, 19*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, 20*8), ymm2) vbroadcastsd(mem(rax, 21*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, 22*8), ymm2) vbroadcastsd(mem(rax, 23*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) add(imm(4*6*8), rax) // a += 4*6 (unroll x mr) add(imm(4*8*8), rbx) // b += 4*8 (unroll x nr) vmovapd(mem(rbx, -4*32), ymm0) vmovapd(mem(rbx, -3*32), ymm1) dec(rsi) // i -= 1; jne(.DLOOPKITER) // iterate again if i != 0. label(.DCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.DLOOPKLEFT) // EDGE LOOP prefetch(0, mem(rax, 64*8)) vbroadcastsd(mem(rax, 0*8), ymm2) vbroadcastsd(mem(rax, 1*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, 2*8), ymm2) vbroadcastsd(mem(rax, 3*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, 4*8), ymm2) vbroadcastsd(mem(rax, 5*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) add(imm(1*6*8), rax) // a += 1*6 (unroll x mr) add(imm(1*8*8), rbx) // b += 1*8 (unroll x nr) vmovapd(mem(rbx, -4*32), ymm0) vmovapd(mem(rbx, -3*32), ymm1) dec(rsi) // i -= 1; jne(.DLOOPKLEFT) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4..ymm15 = -a10 * b01 mov(var(alpha), rbx) // load address of alpha vbroadcastsd(mem(rbx), ymm3) // load alpha and duplicate mov(imm(1), rsi) // set cs_b = 1 lea(mem(, rsi, 8), rsi) // cs_b *= sizeof(double) lea(mem(rcx, rsi, 4), rdx) // load address of b11 + 4*cs_b mov(rcx, r11) // save rcx = b11 for later mov(rdx, r14) // save rdx = b11+4*cs_b for later // b11 := alpha * b11 - a10 * b01 vfmsub231pd(mem(rcx), ymm3, ymm4) add(rdi, rcx) vfmsub231pd(mem(rdx), ymm3, ymm5) add(rdi, rdx) vfmsub231pd(mem(rcx), ymm3, ymm6) add(rdi, rcx) vfmsub231pd(mem(rdx), ymm3, ymm7) add(rdi, rdx) vfmsub231pd(mem(rcx), ymm3, ymm8) add(rdi, rcx) vfmsub231pd(mem(rdx), ymm3, ymm9) add(rdi, rdx) vfmsub231pd(mem(rcx), ymm3, ymm10) add(rdi, rcx) vfmsub231pd(mem(rdx), ymm3, ymm11) add(rdi, rdx) vfmsub231pd(mem(rcx), ymm3, ymm12) add(rdi, rcx) vfmsub231pd(mem(rdx), ymm3, ymm13) add(rdi, rdx) vfmsub231pd(mem(rcx), ymm3, ymm14) //add(rdi, rcx) vfmsub231pd(mem(rdx), ymm3, ymm15) //add(rdi, rdx) // prefetch c11 #if 0 mov(r8, rcx) // load address of c11 from r8 // Note: r9 = rs_c * sizeof(double) lea(mem(r9 , r9 , 2), r13) // r13 = 3*rs_c; lea(mem(rcx, r13, 1), rdx) // rdx = c11 + 3*rs_c; prefetch(0, mem(rcx, 7*8)) // prefetch c11 + 0*rs_c prefetch(0, mem(rcx, r9, 1, 7*8)) // prefetch c11 + 1*rs_c prefetch(0, mem(rcx, r9 , 2, 7*8)) // prefetch c11 + 2*rs_c prefetch(0, mem(rdx, 7*8)) // prefetch c11 + 3*rs_c prefetch(0, mem(rdx, r9, 1, 7*8)) // prefetch c11 + 4*rs_c prefetch(0, mem(rdx, r9 , 2, 7*8)) // prefetch c11 + 5*rs_c #endif // trsm computation begins here // Note: contents of b11 are stored as // ymm4 ymm5 = ( beta00..03 ) ( beta04..07 ) // ymm6 ymm7 = ( beta10..13 ) ( beta14..17 ) // ymm8 ymm9 = ( beta20..23 ) ( beta24..27 ) // ymm10 ymm11 = ( beta30..33 ) ( beta34..37 ) // ymm12 ymm13 = ( beta40..43 ) ( beta44..47 ) // ymm14 ymm15 = ( beta50..53 ) ( beta54..57 ) mov(var(a11), rax) // load address of a11 mov(r11, rcx) // recall address of b11 mov(r14, rdx) // recall address of b11+4*cs_b // Note: rdi = rs_b // iteration 0 ------------- vbroadcastsd(mem(0+0*6)*8(rax), ymm0) // ymm0 = (1/alpha00) #ifdef BLIS_ENABLE_TRSM_PREINVERSION vmulpd(ymm0, ymm4, ymm4) // ymm4 *= (1/alpha00) vmulpd(ymm0, ymm5, ymm5) // ymm5 *= (1/alpha00) #else vdivpd(ymm0, ymm4, ymm4) // ymm4 /= alpha00 vdivpd(ymm0, ymm5, ymm5) // ymm5 /= alpha00 #endif vmovupd(ymm4, mem(rcx)) // store ( beta00..beta03 ) = ymm4 vmovupd(ymm5, mem(rdx)) // store ( beta04..beta07 ) = ymm5 add(rdi, rcx) // rcx += rs_b add(rdi, rdx) // rdx += rs_b // iteration 1 ------------- vbroadcastsd(mem(1+0*6)*8(rax), ymm0) // ymm0 = alpha10 vbroadcastsd(mem(1+1*6)*8(rax), ymm1) // ymm1 = (1/alpha11) vmulpd(ymm0, ymm4, ymm2) // ymm2 = alpha10 * ymm4 vmulpd(ymm0, ymm5, ymm3) // ymm3 = alpha10 * ymm5 vsubpd(ymm2, ymm6, ymm6) // ymm6 -= ymm2 vsubpd(ymm3, ymm7, ymm7) // ymm7 -= ymm3 #ifdef BLIS_ENABLE_TRSM_PREINVERSION vmulpd(ymm1, ymm6, ymm6) // ymm6 *= (1/alpha11) vmulpd(ymm1, ymm7, ymm7) // ymm7 *= (1/alpha11) #else vdivpd(ymm1, ymm6, ymm6) // ymm6 /= alpha11 vdivpd(ymm1, ymm7, ymm7) // ymm7 /= alpha11 #endif vmovupd(ymm6, mem(rcx)) // store ( beta10..beta13 ) = ymm6 vmovupd(ymm7, mem(rdx)) // store ( beta14..beta17 ) = ymm7 add(rdi, rcx) // rcx += rs_b add(rdi, rdx) // rdx += rs_b // iteration 2 ------------- vbroadcastsd(mem(2+0*6)*8(rax), ymm0) // ymm0 = alpha20 vbroadcastsd(mem(2+1*6)*8(rax), ymm1) // ymm1 = alpha21 vmulpd(ymm0, ymm4, ymm2) // ymm2 = alpha20 * ymm4 vmulpd(ymm0, ymm5, ymm3) // ymm3 = alpha20 * ymm5 vbroadcastsd(mem(2+2*6)*8(rax), ymm0) // ymm0 = (1/alpha22) vfmadd231pd(ymm1, ymm6, ymm2) // ymm2 += alpha21 * ymm6 vfmadd231pd(ymm1, ymm7, ymm3) // ymm3 += alpha21 * ymm7 vsubpd(ymm2, ymm8, ymm8) // ymm8 -= ymm2 vsubpd(ymm3, ymm9, ymm9) // ymm9 -= ymm3 #ifdef BLIS_ENABLE_TRSM_PREINVERSION vmulpd(ymm0, ymm8, ymm8) // ymm8 *= (1/alpha22) vmulpd(ymm0, ymm9, ymm9) // ymm9 *= (1/alpha22) #else vdivpd(ymm0, ymm8, ymm8) // ymm8 /= alpha22 vdivpd(ymm0, ymm9, ymm9) // ymm9 /= alpha22 #endif vmovupd(ymm8, mem(rcx)) // store ( beta20..beta23 ) = ymm8 vmovupd(ymm9, mem(rdx)) // store ( beta24..beta27 ) = ymm9 add(rdi, rcx) // rcx += rs_b add(rdi, rdx) // rdx += rs_b // iteration 3 ------------- vbroadcastsd(mem(3+0*6)*8(rax), ymm0) // ymm0 = alpha30 vbroadcastsd(mem(3+1*6)*8(rax), ymm1) // ymm1 = alpha31 vmulpd(ymm0, ymm4, ymm2) // ymm2 = alpha30 * ymm4 vmulpd(ymm0, ymm5, ymm3) // ymm3 = alpha30 * ymm5 vbroadcastsd(mem(3+2*6)*8(rax), ymm0) // ymm0 = alpha32 vfmadd231pd(ymm1, ymm6, ymm2) // ymm2 += alpha31 * ymm6 vfmadd231pd(ymm1, ymm7, ymm3) // ymm3 += alpha31 * ymm7 vbroadcastsd(mem(3+3*6)*8(rax), ymm1) // ymm1 = (1/alpha33) vfmadd231pd(ymm0, ymm8, ymm2) // ymm2 += alpha32 * ymm8 vfmadd231pd(ymm0, ymm9, ymm3) // ymm3 += alpha32 * ymm9 vsubpd(ymm2, ymm10, ymm10) // ymm10 -= ymm2 vsubpd(ymm3, ymm11, ymm11) // ymm11 -= ymm3 #ifdef BLIS_ENABLE_TRSM_PREINVERSION vmulpd(ymm1, ymm10, ymm10) // ymm10 *= (1/alpha33) vmulpd(ymm1, ymm11, ymm11) // ymm11 *= (1/alpha33) #else vdivpd(ymm1, ymm10, ymm10) // ymm10 /= alpha33 vdivpd(ymm1, ymm11, ymm11) // ymm11 /= alpha33 #endif vmovupd(ymm10, mem(rcx)) // store ( beta30..beta33 ) = ymm10 vmovupd(ymm11, mem(rdx)) // store ( beta34..beta37 ) = ymm11 add(rdi, rcx) // rcx += rs_b add(rdi, rdx) // rdx += rs_b // iteration 4 ------------- vbroadcastsd(mem(4+0*6)*8(rax), ymm0) // ymm0 = alpha40 vbroadcastsd(mem(4+1*6)*8(rax), ymm1) // ymm1 = alpha41 vmulpd(ymm0, ymm4, ymm2) // ymm2 = alpha40 * ymm4 vmulpd(ymm0, ymm5, ymm3) // ymm3 = alpha40 * ymm5 vbroadcastsd(mem(4+2*6)*8(rax), ymm0) // ymm0 = alpha42 vfmadd231pd(ymm1, ymm6, ymm2) // ymm2 += alpha41 * ymm6 vfmadd231pd(ymm1, ymm7, ymm3) // ymm3 += alpha41 * ymm7 vbroadcastsd(mem(4+3*6)*8(rax), ymm1) // ymm1 = alpha43 vfmadd231pd(ymm0, ymm8, ymm2) // ymm2 += alpha42 * ymm8 vfmadd231pd(ymm0, ymm9, ymm3) // ymm3 += alpha42 * ymm9 vbroadcastsd(mem(4+4*6)*8(rax), ymm0) // ymm4 = (1/alpha44) vfmadd231pd(ymm1, ymm10, ymm2) // ymm2 += alpha43 * ymm10 vfmadd231pd(ymm1, ymm11, ymm3) // ymm3 += alpha43 * ymm11 vsubpd(ymm2, ymm12, ymm12) // ymm12 -= ymm2 vsubpd(ymm3, ymm13, ymm13) // ymm13 -= ymm3 #ifdef BLIS_ENABLE_TRSM_PREINVERSION vmulpd(ymm0, ymm12, ymm12) // ymm12 *= (1/alpha44) vmulpd(ymm0, ymm13, ymm13) // ymm13 *= (1/alpha44) #else vdivpd(ymm0, ymm12, ymm12) // ymm12 /= alpha44 vdivpd(ymm0, ymm13, ymm13) // ymm13 /= alpha44 #endif vmovupd(ymm12, mem(rcx)) // store ( beta40..beta43 ) = ymm12 vmovupd(ymm13, mem(rdx)) // store ( beta44..beta47 ) = ymm13 add(rdi, rcx) // rcx += rs_b add(rdi, rdx) // rdx += rs_b // iteration 5 ------------- vbroadcastsd(mem(5+0*6)*8(rax), ymm0) // ymm0 = alpha50 vbroadcastsd(mem(5+1*6)*8(rax), ymm1) // ymm1 = alpha51 vmulpd(ymm0, ymm4, ymm2) // ymm2 = alpha50 * ymm4 vmulpd(ymm0, ymm5, ymm3) // ymm3 = alpha50 * ymm5 vbroadcastsd(mem(5+2*6)*8(rax), ymm0) // ymm0 = alpha52 vfmadd231pd(ymm1, ymm6, ymm2) // ymm2 += alpha51 * ymm6 vfmadd231pd(ymm1, ymm7, ymm3) // ymm3 += alpha51 * ymm7 vbroadcastsd(mem(5+3*6)*8(rax), ymm1) // ymm1 = alpha53 vfmadd231pd(ymm0, ymm8, ymm2) // ymm2 += alpha52 * ymm8 vfmadd231pd(ymm0, ymm9, ymm3) // ymm3 += alpha52 * ymm9 vbroadcastsd(mem(5+4*6)*8(rax), ymm0) // ymm0 = alpha54 vfmadd231pd(ymm1, ymm10, ymm2) // ymm2 += alpha53 * ymm10 vfmadd231pd(ymm1, ymm11, ymm3) // ymm3 += alpha53 * ymm11 vbroadcastsd(mem(5+5*6)*8(rax), ymm1) // ymm1 = (1/alpha55) vfmadd231pd(ymm0, ymm12, ymm2) // ymm2 += alpha54 * ymm12 vfmadd231pd(ymm0, ymm13, ymm3) // ymm3 += alpha54 * ymm13 vsubpd(ymm2, ymm14, ymm14) // ymm14 -= ymm2 vsubpd(ymm3, ymm15, ymm15) // ymm15 -= ymm3 #ifdef BLIS_ENABLE_TRSM_PREINVERSION vmulpd(ymm1, ymm14, ymm14) // ymm14 *= (1/alpha55) vmulpd(ymm1, ymm15, ymm15) // ymm15 *= (1/alpha55) #else vdivpd(ymm1, ymm14, ymm14) // ymm14 /= alpha55 vdivpd(ymm1, ymm15, ymm15) // ymm15 /= alpha55 #endif vmovupd(ymm14, mem(rcx)) // store ( beta50..beta53 ) = ymm14 vmovupd(ymm15, mem(rdx)) // store ( beta54..beta57 ) = ymm15 add(rdi, rcx) // rcx += rs_b add(rdi, rdx) // rdx += rs_b mov(r8, rcx) // load address of c11 from r8 mov(r9, rdi) // load rs_c (in bytes) from r9 mov(r10, rsi) // load cs_c (in bytes) from r10 lea(mem(rcx, rsi, 4), rdx) // load address of c11 + 4*cs_c; lea(mem(rcx, rdi, 4), r14) // load address of c11 + 4*rs_c; // These are used in the macros below. lea(mem(rsi, rsi, 2), r13) // r13 = 3*cs_c; //lea(mem(rsi, rsi, 4), r15) // r15 = 5*cs_c; //lea(mem(r13, rsi, 4), r10) // r10 = 7*cs_c; cmp(imm(8), rsi) // set ZF if (8*cs_c) == 8. jz(.DROWSTORED) // jump to row storage case cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORED) // jump to column storage case // if neither row- or column- // stored, use general case. label(.DGENSTORED) vmovapd(ymm4, ymm0) DGEMM_OUTPUT_GS_BETA_NZ add(rdi, rcx) // c11 += rs_c; vmovapd(ymm6, ymm0) DGEMM_OUTPUT_GS_BETA_NZ add(rdi, rcx) // c11 += rs_c; vmovapd(ymm8, ymm0) DGEMM_OUTPUT_GS_BETA_NZ add(rdi, rcx) // c11 += rs_c; vmovapd(ymm10, ymm0) DGEMM_OUTPUT_GS_BETA_NZ add(rdi, rcx) // c11 += rs_c; vmovapd(ymm12, ymm0) DGEMM_OUTPUT_GS_BETA_NZ add(rdi, rcx) // c11 += rs_c; vmovapd(ymm14, ymm0) DGEMM_OUTPUT_GS_BETA_NZ mov(rdx, rcx) // rcx = c11 + 4*cs_c vmovapd(ymm5, ymm0) DGEMM_OUTPUT_GS_BETA_NZ add(rdi, rcx) // c11 += rs_c; vmovapd(ymm7, ymm0) DGEMM_OUTPUT_GS_BETA_NZ add(rdi, rcx) // c11 += rs_c; vmovapd(ymm9, ymm0) DGEMM_OUTPUT_GS_BETA_NZ add(rdi, rcx) // c11 += rs_c; vmovapd(ymm11, ymm0) DGEMM_OUTPUT_GS_BETA_NZ add(rdi, rcx) // c11 += rs_c; vmovapd(ymm13, ymm0) DGEMM_OUTPUT_GS_BETA_NZ add(rdi, rcx) // c11 += rs_c; vmovapd(ymm15, ymm0) DGEMM_OUTPUT_GS_BETA_NZ jmp(.DDONE) label(.DROWSTORED) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vmovupd(ymm5, mem(rdx)) add(rdi, rdx) vmovupd(ymm6, mem(rcx)) add(rdi, rcx) vmovupd(ymm7, mem(rdx)) add(rdi, rdx) vmovupd(ymm8, mem(rcx)) add(rdi, rcx) vmovupd(ymm9, mem(rdx)) add(rdi, rdx) vmovupd(ymm10, mem(rcx)) add(rdi, rcx) vmovupd(ymm11, mem(rdx)) add(rdi, rdx) vmovupd(ymm12, mem(rcx)) add(rdi, rcx) vmovupd(ymm13, mem(rdx)) add(rdi, rdx) vmovupd(ymm14, mem(rcx)) //add(rdi, rcx) vmovupd(ymm15, mem(rdx)) //add(rdi, rdx) jmp(.DDONE) label(.DCOLSTORED) vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vunpcklpd(ymm10, ymm8, ymm2) vunpckhpd(ymm10, ymm8, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vperm2f128(imm(0x31), ymm2, ymm0, ymm8) vperm2f128(imm(0x31), ymm3, ymm1, ymm10) vmovupd(ymm4, mem(rcx)) vmovupd(ymm6, mem(rcx, rsi, 1)) vmovupd(ymm8, mem(rcx, rsi, 2)) vmovupd(ymm10, mem(rcx, r13, 1)) lea(mem(rcx, rsi, 4), rcx) vunpcklpd(ymm14, ymm12, ymm0) vunpckhpd(ymm14, ymm12, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vextractf128(imm(0x1), ymm1, xmm3) vmovupd(xmm0, mem(r14)) vmovupd(xmm1, mem(r14, rsi, 1)) vmovupd(xmm2, mem(r14, rsi, 2)) vmovupd(xmm3, mem(r14, r13, 1)) lea(mem(r14, rsi, 4), r14) vunpcklpd(ymm7, ymm5, ymm0) vunpckhpd(ymm7, ymm5, ymm1) vunpcklpd(ymm11, ymm9, ymm2) vunpckhpd(ymm11, ymm9, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm5) vinsertf128(imm(0x1), xmm3, ymm1, ymm7) vperm2f128(imm(0x31), ymm2, ymm0, ymm9) vperm2f128(imm(0x31), ymm3, ymm1, ymm11) vmovupd(ymm5, mem(rcx)) vmovupd(ymm7, mem(rcx, rsi, 1)) vmovupd(ymm9, mem(rcx, rsi, 2)) vmovupd(ymm11, mem(rcx, r13, 1)) //lea(mem(rcx, rsi, 4), rcx) vunpcklpd(ymm15, ymm13, ymm0) vunpckhpd(ymm15, ymm13, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vextractf128(imm(0x1), ymm1, xmm3) vmovupd(xmm0, mem(r14)) vmovupd(xmm1, mem(r14, rsi, 1)) vmovupd(xmm2, mem(r14, rsi, 2)) vmovupd(xmm3, mem(r14, r13, 1)) //lea(mem(r14, rsi, 4), r14) label(.DDONE) vzeroupper() end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), // 0 [k_left] "m" (k_left), // 1 [a10] "m" (a10), // 2 [b01] "m" (b01), // 3 [beta] "m" (beta), // 4 [alpha] "m" (alpha), // 5 [a11] "m" (a11), // 6 [b11] "m" (b11), // 7 [c11] "m" (c11), // 8 [rs_c] "m" (rs_c), // 9 [cs_c] "m" (cs_c) // 10 : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) GEMMTRSM_UKR_FLUSH_CT( d ); } blis-0.9.0/kernels/haswell/3/bli_gemmtrsm_u_haswell_asm_d6x8.c000066400000000000000000001223121422157504600243250ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define BLIS_ASM_SYNTAX_ATT #include "bli_x86_asm_macros.h" #define SGEMM_OUTPUT_GS_BETA_NZ \ vextractf128(imm(1), ymm0, xmm2) \ vmovss(xmm0, mem(rcx)) \ vpermilps(imm(0x39), xmm0, xmm1) \ vmovss(xmm1, mem(rcx, rsi, 1)) \ vpermilps(imm(0x39), xmm1, xmm0) \ vmovss(xmm0, mem(rcx, rsi, 2)) \ vpermilps(imm(0x39), xmm0, xmm1) \ vmovss(xmm1, mem(rcx, r13, 1)) \ vmovss(xmm2, mem(rcx, rsi, 4)) \ vpermilps(imm(0x39), xmm2, xmm1) \ vmovss(xmm1, mem(rcx, r15, 1)) \ vpermilps(imm(0x39), xmm1, xmm2) \ vmovss(xmm2, mem(rcx, r13, 2)) \ vpermilps(imm(0x39), xmm2, xmm1) \ vmovss(xmm1, mem(rcx, r10, 1)) void bli_sgemmtrsm_u_haswell_asm_6x16 ( dim_t m, dim_t n, dim_t k0, float* restrict alpha, float* restrict a10, float* restrict a11, float* restrict b01, float* restrict b11, float* restrict c11, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; float* beta = bli_sm1; GEMMTRSM_UKR_SETUP_CT_ANY( s, 6, 16, true ); begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a10), rax) // load address of a. mov(var(b01), rbx) // load address of b. add(imm(32*4), rbx) // initialize loop by pre-loading vmovaps(mem(rbx, -4*32), ymm0) vmovaps(mem(rbx, -3*32), ymm1) mov(var(b11), rcx) // load address of b11 mov(imm(16), rdi) // set rs_b = PACKNR = 16 lea(mem(, rdi, 4), rdi) // rs_b *= sizeof(float) // NOTE: c11, rs_c, and cs_c aren't // needed for a while, but we load // them now to avoid stalling later. mov(var(c11), r8) // load address of c11 mov(var(rs_c), r9) // load rs_c lea(mem(, r9 , 4), r9) // rs_c *= sizeof(float) mov(var(k_left)0, r10) // load cs_c lea(mem(, r10, 4), r10) // cs_c *= sizeof(float) mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // iteration 0 prefetch(0, mem(rax, 64*4)) vbroadcastss(mem(rax, 0*4), ymm2) vbroadcastss(mem(rax, 1*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, 2*4), ymm2) vbroadcastss(mem(rax, 3*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, 4*4), ymm2) vbroadcastss(mem(rax, 5*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) vmovaps(mem(rbx, -2*32), ymm0) vmovaps(mem(rbx, -1*32), ymm1) // iteration 1 vbroadcastss(mem(rax, 6*4), ymm2) vbroadcastss(mem(rax, 7*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, 8*4), ymm2) vbroadcastss(mem(rax, 9*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, 10*4), ymm2) vbroadcastss(mem(rax, 11*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) vmovaps(mem(rbx, 0*32), ymm0) vmovaps(mem(rbx, 1*32), ymm1) // iteration 2 prefetch(0, mem(rax, 76*4)) vbroadcastss(mem(rax, 12*4), ymm2) vbroadcastss(mem(rax, 13*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, 14*4), ymm2) vbroadcastss(mem(rax, 15*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, 16*4), ymm2) vbroadcastss(mem(rax, 17*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) vmovaps(mem(rbx, 2*32), ymm0) vmovaps(mem(rbx, 3*32), ymm1) // iteration 3 vbroadcastss(mem(rax, 18*4), ymm2) vbroadcastss(mem(rax, 19*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, 20*4), ymm2) vbroadcastss(mem(rax, 21*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, 22*4), ymm2) vbroadcastss(mem(rax, 23*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) add(imm(4*6*4), rax) // a += 4*6 (unroll x mr) add(imm(4*16*4), rbx) // b += 4*16 (unroll x nr) vmovaps(mem(rbx, -4*32), ymm0) vmovaps(mem(rbx, -3*32), ymm1) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP prefetch(0, mem(rax, 64*4)) vbroadcastss(mem(rax, 0*4), ymm2) vbroadcastss(mem(rax, 1*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, 2*4), ymm2) vbroadcastss(mem(rax, 3*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, 4*4), ymm2) vbroadcastss(mem(rax, 5*4), ymm3) vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) add(imm(1*6*4), rax) // a += 1*6 (unroll x mr) add(imm(1*16*4), rbx) // b += 1*16 (unroll x nr) vmovaps(mem(rbx, -4*32), ymm0) vmovaps(mem(rbx, -3*32), ymm1) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) // ymm4..ymm15 = -a10 * b01 mov(var(alpha), rbx) // load address of alpha vbroadcastss(mem(rbx), ymm3) // load alpha and duplicate mov(imm(1), rsi) // load cs_b = 1 lea(mem(, rsi, 4), rsi) // cs_b *= sizeof(float) lea(mem(rcx, rsi, 8), rdx) // load address of b11 + 8*cs_b mov(rcx, r11) // save rcx = b11 for later mov(rdx, r14) // save rdx = b11+8*cs_b for later // b11 := alpha * b11 - a10 * b01 vfmsub231ps(mem(rcx), ymm3, ymm4) add(rdi, rcx) vfmsub231ps(mem(rdx), ymm3, ymm5) add(rdi, rdx) vfmsub231ps(mem(rcx), ymm3, ymm6) add(rdi, rcx) vfmsub231ps(mem(rdx), ymm3, ymm7) add(rdi, rdx) vfmsub231ps(mem(rcx), ymm3, ymm8) add(rdi, rcx) vfmsub231ps(mem(rdx), ymm3, ymm9) add(rdi, rdx) vfmsub231ps(mem(rcx), ymm3, ymm10) add(rdi, rcx) vfmsub231ps(mem(rdx), ymm3, ymm11) add(rdi, rdx) vfmsub231ps(mem(rcx), ymm3, ymm12) add(rdi, rcx) vfmsub231ps(mem(rdx), ymm3, ymm13) add(rdi, rdx) vfmsub231ps(mem(rcx), ymm3, ymm14) //add(rdi, rcx) vfmsub231ps(mem(rdx), ymm3, ymm15) //add(rdi, rdx) // prefetch c11 #if 0 mov(r8, rcx) // load address of c11 from r8 // Note: r9 = rs_c * sizeof(float) lea(mem(r9 , r9 , 2), r13) // r13 = 3*rs_c; lea(mem(rcx, r13, 1), rdx) // rdx = c11 + 3*rs_c; prefetch(0, mem(rcx, 0*8)) // prefetch c11 + 0*rs_c prefetch(0, mem(rcx, r9, 1, 0*8)) // prefetch c11 + 1*rs_c prefetch(0, mem(rcx, r9 , 2, 0*8)) // prefetch c11 + 2*rs_c prefetch(0, mem(rdx, 0*8)) // prefetch c11 + 3*rs_c prefetch(0, mem(rdx, r9, 1, 0*8)) // prefetch c11 + 4*rs_c prefetch(0, mem(rdx, r9 , 2, 0*8)) // prefetch c11 + 5*rs_c #endif // trsm computation begins here // Note: contents of b11 are stored as // ymm4 ymm5 = ( beta00..07 ) ( beta08..0F ) // ymm6 ymm7 = ( beta10..17 ) ( beta18..1F ) // ymm8 ymm9 = ( beta20..27 ) ( beta28..2F ) // ymm10 ymm11 = ( beta30..37 ) ( beta38..3F ) // ymm12 ymm13 = ( beta40..47 ) ( beta48..4F ) // ymm14 ymm15 = ( beta50..57 ) ( beta58..5F ) mov(var(a11), rax) // load address of a11 mov(r11, rcx) // recall address of b11 mov(r14, rdx) // recall address of b11+8*cs_b lea(mem(rcx, rdi, 4), rcx) // rcx = b11 + (6-1)*rs_b lea(mem(rcx, rdi, 1), rcx) lea(mem(rdx, rdi, 4), rdx) // rdx = b11 + (6-1)*rs_b + 8*cs_b lea(mem(rdx, rdi, 1), rdx) // iteration 0 ------------- vbroadcastss(mem(5+5*6)*4(rax), ymm0) // ymm0 = (1/alpha55) #ifdef BLIS_ENABLE_TRSM_PREINVERSION vmulps(ymm0, ymm14, ymm14) // ymm14 *= (1/alpha55) vmulps(ymm0, ymm15, ymm15) // ymm15 *= (1/alpha55) #else vdivps(ymm0, ymm14, ymm14) // ymm14 /= alpha55 vdivps(ymm0, ymm15, ymm15) // ymm15 /= alpha55 #endif vmovups(ymm14, mem(rcx)) // store ( beta50..beta57 ) = ymm14 vmovups(ymm15, mem(rdx)) // store ( beta58..beta5F ) = ymm15 sub(rdi, rcx) // rcx -= rs_b sub(rdi, rdx) // rdx -= rs_b // iteration 1 ------------- vbroadcastss(mem(4+5*6)*4(rax), ymm0) // ymm0 = alpha45 vbroadcastss(mem(4+4*6)*4(rax), ymm1) // ymm1 = (1/alpha44) vmulps(ymm0, ymm14, ymm2) // ymm2 = alpha45 * ymm14 vmulps(ymm0, ymm15, ymm3) // ymm3 = alpha45 * ymm15 vsubps(ymm2, ymm12, ymm12) // ymm12 -= ymm2 vsubps(ymm3, ymm13, ymm13) // ymm13 -= ymm3 #ifdef BLIS_ENABLE_TRSM_PREINVERSION vmulps(ymm1, ymm12, ymm12) // ymm12 *= (1/alpha44) vmulps(ymm1, ymm13, ymm13) // ymm13 *= (1/alpha44) #else vdivps(ymm1, ymm12, ymm12) // ymm12 /= alpha44 vdivps(ymm1, ymm13, ymm13) // ymm13 /= alpha44 #endif vmovups(ymm12, mem(rcx)) // store ( beta40..beta47 ) = ymm12 vmovups(ymm13, mem(rdx)) // store ( beta48..beta4F ) = ymm13 sub(rdi, rcx) // rcx -= rs_b sub(rdi, rdx) // rdx -= rs_b // iteration 2 ------------- vbroadcastss(mem(3+5*6)*4(rax), ymm0) // ymm0 = alpha35 vbroadcastss(mem(3+4*6)*4(rax), ymm1) // ymm1 = alpha34 vmulps(ymm0, ymm14, ymm2) // ymm2 = alpha35 * ymm14 vmulps(ymm0, ymm15, ymm3) // ymm3 = alpha35 * ymm15 vbroadcastss(mem(3+3*6)*4(rax), ymm0) // ymm0 = (1/alpha33) vfmadd231ps(ymm1, ymm12, ymm2) // ymm2 += alpha34 * ymm12 vfmadd231ps(ymm1, ymm13, ymm3) // ymm3 += alpha34 * ymm13 vsubps(ymm2, ymm10, ymm10) // ymm10 -= ymm2 vsubps(ymm3, ymm11, ymm11) // ymm11 -= ymm3 #ifdef BLIS_ENABLE_TRSM_PREINVERSION vmulps(ymm0, ymm10, ymm10) // ymm10 *= (1/alpha33) vmulps(ymm0, ymm11, ymm11) // ymm11 *= (1/alpha33) #else vdivps(ymm0, ymm10, ymm10) // ymm10 /= alpha33 vdivps(ymm0, ymm11, ymm11) // ymm11 /= alpha33 #endif vmovups(ymm10, mem(rcx)) // store ( beta30..beta37 ) = ymm10 vmovups(ymm11, mem(rdx)) // store ( beta38..beta3F ) = ymm11 sub(rdi, rcx) // rcx -= rs_b sub(rdi, rdx) // rdx -= rs_b // iteration 3 ------------- vbroadcastss(mem(2+5*6)*4(rax), ymm0) // ymm0 = alpha25 vbroadcastss(mem(2+4*6)*4(rax), ymm1) // ymm1 = alpha24 vmulps(ymm0, ymm14, ymm2) // ymm2 = alpha25 * ymm14 vmulps(ymm0, ymm15, ymm3) // ymm3 = alpha25 * ymm15 vbroadcastss(mem(2+3*6)*4(rax), ymm0) // ymm0 = alpha23 vfmadd231ps(ymm1, ymm12, ymm2) // ymm2 += alpha24 * ymm12 vfmadd231ps(ymm1, ymm13, ymm3) // ymm3 += alpha24 * ymm13 vbroadcastss(mem(2+2*6)*4(rax), ymm1) // ymm1 = (1/alpha22) vfmadd231ps(ymm0, ymm10, ymm2) // ymm2 += alpha23 * ymm10 vfmadd231ps(ymm0, ymm11, ymm3) // ymm3 += alpha23 * ymm11 vsubps(ymm2, ymm8, ymm8) // ymm8 -= ymm2 vsubps(ymm3, ymm9, ymm9) // ymm9 -= ymm3 #ifdef BLIS_ENABLE_TRSM_PREINVERSION vmulps(ymm1, ymm8, ymm8) // ymm8 *= (1/alpha22) vmulps(ymm1, ymm9, ymm9) // ymm9 *= (1/alpha22) #else vdivps(ymm1, ymm8, ymm8) // ymm8 /= alpha22 vdivps(ymm1, ymm9, ymm9) // ymm9 /= alpha22 #endif vmovups(ymm8, mem(rcx)) // store ( beta20..beta27 ) = ymm8 vmovups(ymm9, mem(rdx)) // store ( beta28..beta2F ) = ymm9 sub(rdi, rcx) // rcx -= rs_b sub(rdi, rdx) // rdx -= rs_b // iteration 4 ------------- vbroadcastss(mem(1+5*6)*4(rax), ymm0) // ymm0 = alpha15 vbroadcastss(mem(1+4*6)*4(rax), ymm1) // ymm1 = alpha14 vmulps(ymm0, ymm14, ymm2) // ymm2 = alpha15 * ymm14 vmulps(ymm0, ymm15, ymm3) // ymm3 = alpha15 * ymm15 vbroadcastss(mem(1+3*6)*4(rax), ymm0) // ymm0 = alpha13 vfmadd231ps(ymm1, ymm12, ymm2) // ymm2 += alpha14 * ymm12 vfmadd231ps(ymm1, ymm13, ymm3) // ymm3 += alpha14 * ymm13 vbroadcastss(mem(1+2*6)*4(rax), ymm1) // ymm1 = alpha12 vfmadd231ps(ymm0, ymm10, ymm2) // ymm2 += alpha13 * ymm10 vfmadd231ps(ymm0, ymm11, ymm3) // ymm3 += alpha13 * ymm11 vbroadcastss(mem(1+1*6)*4(rax), ymm0) // ymm4 = (1/alpha11) vfmadd231ps(ymm1, ymm8, ymm2) // ymm2 += alpha12 * ymm8 vfmadd231ps(ymm1, ymm9, ymm3) // ymm3 += alpha12 * ymm9 vsubps(ymm2, ymm6, ymm6) // ymm6 -= ymm2 vsubps(ymm3, ymm7, ymm7) // ymm7 -= ymm3 #ifdef BLIS_ENABLE_TRSM_PREINVERSION vmulps(ymm0, ymm6, ymm6) // ymm6 *= (1/alpha11) vmulps(ymm0, ymm7, ymm7) // ymm7 *= (1/alpha11) #else vdivps(ymm0, ymm6, ymm6) // ymm6 /= alpha11 vdivps(ymm0, ymm7, ymm7) // ymm7 /= alpha11 #endif vmovups(ymm6, mem(rcx)) // store ( beta10..beta17 ) = ymm6 vmovups(ymm7, mem(rdx)) // store ( beta18..beta1F ) = ymm7 sub(rdi, rcx) // rcx -= rs_b sub(rdi, rdx) // rdx -= rs_b // iteration 5 ------------- vbroadcastss(mem(0+5*6)*4(rax), ymm0) // ymm0 = alpha05 vbroadcastss(mem(0+4*6)*4(rax), ymm1) // ymm1 = alpha04 vmulps(ymm0, ymm14, ymm2) // ymm2 = alpha05 * ymm14 vmulps(ymm0, ymm15, ymm3) // ymm3 = alpha05 * ymm15 vbroadcastss(mem(0+3*6)*4(rax), ymm0) // ymm0 = alpha03 vfmadd231ps(ymm1, ymm12, ymm2) // ymm2 += alpha04 * ymm12 vfmadd231ps(ymm1, ymm13, ymm3) // ymm3 += alpha04 * ymm13 vbroadcastss(mem(0+2*6)*4(rax), ymm1) // ymm1 = alpha02 vfmadd231ps(ymm0, ymm10, ymm2) // ymm2 += alpha03 * ymm10 vfmadd231ps(ymm0, ymm11, ymm3) // ymm3 += alpha03 * ymm11 vbroadcastss(mem(0+1*6)*4(rax), ymm0) // ymm0 = alpha01 vfmadd231ps(ymm1, ymm8, ymm2) // ymm2 += alpha02 * ymm8 vfmadd231ps(ymm1, ymm9, ymm3) // ymm3 += alpha02 * ymm9 vbroadcastss(mem(0+0*6)*4(rax), ymm1) // ymm1 = (1/alpha00) vfmadd231ps(ymm0, ymm6, ymm2) // ymm2 += alpha01 * ymm6 vfmadd231ps(ymm0, ymm7, ymm3) // ymm3 += alpha01 * ymm7 vsubps(ymm2, ymm4, ymm4) // ymm4 -= ymm2 vsubps(ymm3, ymm5, ymm5) // ymm5 -= ymm3 #ifdef BLIS_ENABLE_TRSM_PREINVERSION vmulps(ymm1, ymm4, ymm4) // ymm4 *= (1/alpha00) vmulps(ymm1, ymm5, ymm5) // ymm5 *= (1/alpha00) #else vdivps(ymm1, ymm4, ymm4) // ymm4 /= alpha00 vdivps(ymm1, ymm5, ymm5) // ymm5 /= alpha00 #endif vmovups(ymm4, mem(rcx)) // store ( beta00..beta07 ) = ymm4 vmovups(ymm5, mem(rdx)) // store ( beta08..beta0F ) = ymm5 sub(rdi, rcx) // rcx -= rs_b sub(rdi, rdx) // rdx -= rs_b mov(r8, rcx) // load address of c11 from r8 mov(r9, rdi) // load rs_c (in bytes) from r9 mov(r10, rsi) // load cs_c (in bytes) from r10 lea(mem(rcx, rsi, 8), rdx) // load address of c11 + 8*cs_c; lea(mem(rcx, rdi, 4), r14) // load address of c11 + 4*rs_c; // These are used in the macros below. lea(mem(rsi, rsi, 2), r13) // r13 = 3*cs_c; lea(mem(rsi, rsi, 4), r15) // r15 = 5*cs_c; lea(mem(r13, rsi, 4), r10) // r10 = 7*cs_c; cmp(imm(4), rsi) // set ZF if (4*cs_c) == 4. jz(.SROWSTORED) // jump to row storage case cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORED) // jump to column storage case // if neither row- or column- // stored, use general case. label(.SGENSTORED) vmovaps(ymm4, ymm0) SGEMM_OUTPUT_GS_BETA_NZ add(rdi, rcx) // c11 += rs_c; vmovaps(ymm6, ymm0) SGEMM_OUTPUT_GS_BETA_NZ add(rdi, rcx) // c11 += rs_c; vmovaps(ymm8, ymm0) SGEMM_OUTPUT_GS_BETA_NZ add(rdi, rcx) // c11 += rs_c; vmovaps(ymm10, ymm0) SGEMM_OUTPUT_GS_BETA_NZ add(rdi, rcx) // c11 += rs_c; vmovaps(ymm12, ymm0) SGEMM_OUTPUT_GS_BETA_NZ add(rdi, rcx) // c11 += rs_c; vmovaps(ymm14, ymm0) SGEMM_OUTPUT_GS_BETA_NZ mov(rdx, rcx) // rcx = c11 + 8*cs_c vmovaps(ymm5, ymm0) SGEMM_OUTPUT_GS_BETA_NZ add(rdi, rcx) // c11 += rs_c; vmovaps(ymm7, ymm0) SGEMM_OUTPUT_GS_BETA_NZ add(rdi, rcx) // c11 += rs_c; vmovaps(ymm9, ymm0) SGEMM_OUTPUT_GS_BETA_NZ add(rdi, rcx) // c11 += rs_c; vmovaps(ymm11, ymm0) SGEMM_OUTPUT_GS_BETA_NZ add(rdi, rcx) // c11 += rs_c; vmovaps(ymm13, ymm0) SGEMM_OUTPUT_GS_BETA_NZ add(rdi, rcx) // c11 += rs_c; vmovaps(ymm15, ymm0) SGEMM_OUTPUT_GS_BETA_NZ jmp(.SDONE) label(.SROWSTORED) vmovups(ymm4, mem(rcx)) add(rdi, rcx) vmovups(ymm5, mem(rdx)) add(rdi, rdx) vmovups(ymm6, mem(rcx)) add(rdi, rcx) vmovups(ymm7, mem(rdx)) add(rdi, rdx) vmovups(ymm8, mem(rcx)) add(rdi, rcx) vmovups(ymm9, mem(rdx)) add(rdi, rdx) vmovups(ymm10, mem(rcx)) add(rdi, rcx) vmovups(ymm11, mem(rdx)) add(rdi, rdx) vmovups(ymm12, mem(rcx)) add(rdi, rcx) vmovups(ymm13, mem(rdx)) add(rdi, rdx) vmovups(ymm14, mem(rcx)) //add(rdi, rcx) vmovups(ymm15, mem(rdx)) //add(rdi, rdx) jmp(.SDONE) label(.SCOLSTORED) vunpcklps(ymm6, ymm4, ymm0) vunpcklps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vextractf128(imm(0x1), ymm1, xmm3) vmovups(xmm0, mem(rcx)) // store ( gamma00..gamma30 ) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) vmovups(xmm3, mem(rcx, r15, 1)) // store ( gamma05..gamma35 ) vunpckhps(ymm6, ymm4, ymm0) vunpckhps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vextractf128(imm(0x1), ymm1, xmm3) vmovups(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma32 ) vmovups(xmm1, mem(rcx, r13, 1)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, r13, 2)) // store ( gamma06..gamma36 ) vmovups(xmm3, mem(rcx, r10, 1)) // store ( gamma07..gamma37 ) lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vunpcklps(ymm14, ymm12, ymm0) vunpckhps(ymm14, ymm12, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vextractf128(imm(0x1), ymm1, xmm3) vmovlpd(xmm0, mem(r14)) // store ( gamma40..gamma50 ) vmovhpd(xmm0, mem(r14, rsi, 1)) // store ( gamma41..gamma51 ) vmovlpd(xmm1, mem(r14, rsi, 2)) // store ( gamma42..gamma52 ) vmovhpd(xmm1, mem(r14, r13, 1)) // store ( gamma43..gamma53 ) vmovlpd(xmm2, mem(r14, rsi, 4)) // store ( gamma44..gamma54 ) vmovhpd(xmm2, mem(r14, r15, 1)) // store ( gamma45..gamma55 ) vmovlpd(xmm3, mem(r14, r13, 2)) // store ( gamma46..gamma56 ) vmovhpd(xmm3, mem(r14, r10, 1)) // store ( gamma47..gamma57 ) lea(mem(r14, rsi, 8), r14) // r14 += 8*cs_c vunpcklps(ymm7, ymm5, ymm0) vunpcklps(ymm11, ymm9, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vextractf128(imm(0x1), ymm1, xmm3) vmovups(xmm0, mem(rcx)) // store ( gamma08..gamma38 ) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma09..gamma39 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma0C..gamma3C ) vmovups(xmm3, mem(rcx, r15, 1)) // store ( gamma0D..gamma3D ) vunpckhps(ymm7, ymm5, ymm0) vunpckhps(ymm11, ymm9, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vextractf128(imm(0x1), ymm1, xmm3) vmovups(xmm0, mem(rcx, rsi, 2)) // store ( gamma0A..gamma3A ) vmovups(xmm1, mem(rcx, r13, 1)) // store ( gamma0B..gamma3B ) vmovups(xmm2, mem(rcx, r13, 2)) // store ( gamma0E..gamma3E ) vmovups(xmm3, mem(rcx, r10, 1)) // store ( gamma0F..gamma3F ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vunpcklps(ymm15, ymm13, ymm0) vunpckhps(ymm15, ymm13, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vextractf128(imm(0x1), ymm1, xmm3) vmovlpd(xmm0, mem(r14)) // store ( gamma48..gamma58 ) vmovhpd(xmm0, mem(r14, rsi, 1)) // store ( gamma49..gamma59 ) vmovlpd(xmm1, mem(r14, rsi, 2)) // store ( gamma4A..gamma5A ) vmovhpd(xmm1, mem(r14, r13, 1)) // store ( gamma4B..gamma5B ) vmovlpd(xmm2, mem(r14, rsi, 4)) // store ( gamma4C..gamma5C ) vmovhpd(xmm2, mem(r14, r15, 1)) // store ( gamma4D..gamma5D ) vmovlpd(xmm3, mem(r14, r13, 2)) // store ( gamma4E..gamma5E ) vmovhpd(xmm3, mem(r14, r10, 1)) // store ( gamma4F..gamma5F ) //lea(mem(r14, rsi, 8), r14) // r14 += 8*cs_c label(.SDONE) vzeroupper() end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), // 0 [k_left] "m" (k_left), // 1 [a10] "m" (a10), // 2 [b01] "m" (b01), // 3 [beta] "m" (beta), // 4 [alpha] "m" (alpha), // 5 [a11] "m" (a11), // 6 [b11] "m" (b11), // 7 [c11] "m" (c11), // 8 [rs_c] "m" (rs_c), // 9 [cs_c] "m" (cs_c) // 10 : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) GEMMTRSM_UKR_FLUSH_CT( s ); } #define DGEMM_OUTPUT_GS_BETA_NZ \ vextractf128(imm(1), ymm0, xmm1) \ vmovlpd(xmm0, mem(rcx)) \ vmovhpd(xmm0, mem(rcx, rsi, 1)) \ vmovlpd(xmm1, mem(rcx, rsi, 2)) \ vmovhpd(xmm1, mem(rcx, r13, 1)) /*\ vextractf128(imm(1), ymm2, xmm1) \ vmovlpd(xmm2, mem(rcx, rsi, 4)) \ vmovhpd(xmm2, mem(rcx, r15, 1)) \ vmovlpd(xmm1, mem(rcx, r13, 2)) \ vmovhpd(xmm1, mem(rcx, r10, 1))*/ void bli_dgemmtrsm_u_haswell_asm_6x8 ( dim_t m, dim_t n, dim_t k0, double* restrict alpha, double* restrict a10, double* restrict a11, double* restrict b01, double* restrict b11, double* restrict c11, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; double* beta = bli_dm1; GEMMTRSM_UKR_SETUP_CT_ANY( d, 6, 8, true ); begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a10), rax) // load address of a. mov(var(b01), rbx) // load address of b. add(imm(32*4), rbx) // initialize loop by pre-loading vmovapd(mem(rbx, -4*32), ymm0) vmovapd(mem(rbx, -3*32), ymm1) mov(var(b11), rcx) // load address of b11 mov(imm(8), rdi) // set rs_b = PACKNR = 8 lea(mem(, rdi, 8), rdi) // rs_b *= sizeof(double) // NOTE: c11, rs_c, and cs_c aren't // needed for a while, but we load // them now to avoid stalling later. mov(var(c11), r8) // load address of c11 mov(var(rs_c), r9) // load rs_c lea(mem(, r9 , 8), r9) // rs_c *= sizeof(double) mov(var(k_left)0, r10) // load cs_c lea(mem(, r10, 8), r10) // cs_c *= sizeof(double) mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.DLOOPKITER) // MAIN LOOP // iteration 0 prefetch(0, mem(rax, 64*8)) vbroadcastsd(mem(rax, 0*8), ymm2) vbroadcastsd(mem(rax, 1*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, 2*8), ymm2) vbroadcastsd(mem(rax, 3*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, 4*8), ymm2) vbroadcastsd(mem(rax, 5*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) vmovapd(mem(rbx, -2*32), ymm0) vmovapd(mem(rbx, -1*32), ymm1) // iteration 1 prefetch(0, mem(rax, 72*8)) vbroadcastsd(mem(rax, 6*8), ymm2) vbroadcastsd(mem(rax, 7*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, 8*8), ymm2) vbroadcastsd(mem(rax, 9*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, 10*8), ymm2) vbroadcastsd(mem(rax, 11*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) vmovapd(mem(rbx, 0*32), ymm0) vmovapd(mem(rbx, 1*32), ymm1) // iteration 2 prefetch(0, mem(rax, 80*8)) vbroadcastsd(mem(rax, 12*8), ymm2) vbroadcastsd(mem(rax, 13*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, 14*8), ymm2) vbroadcastsd(mem(rax, 15*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, 16*8), ymm2) vbroadcastsd(mem(rax, 17*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) vmovapd(mem(rbx, 2*32), ymm0) vmovapd(mem(rbx, 3*32), ymm1) // iteration 3 vbroadcastsd(mem(rax, 18*8), ymm2) vbroadcastsd(mem(rax, 19*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, 20*8), ymm2) vbroadcastsd(mem(rax, 21*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, 22*8), ymm2) vbroadcastsd(mem(rax, 23*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) add(imm(4*6*8), rax) // a += 4*6 (unroll x mr) add(imm(4*8*8), rbx) // b += 4*8 (unroll x nr) vmovapd(mem(rbx, -4*32), ymm0) vmovapd(mem(rbx, -3*32), ymm1) dec(rsi) // i -= 1; jne(.DLOOPKITER) // iterate again if i != 0. label(.DCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.DLOOPKLEFT) // EDGE LOOP prefetch(0, mem(rax, 64*8)) vbroadcastsd(mem(rax, 0*8), ymm2) vbroadcastsd(mem(rax, 1*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, 2*8), ymm2) vbroadcastsd(mem(rax, 3*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, 4*8), ymm2) vbroadcastsd(mem(rax, 5*8), ymm3) vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) add(imm(1*6*8), rax) // a += 1*6 (unroll x mr) add(imm(1*8*8), rbx) // b += 1*8 (unroll x nr) vmovapd(mem(rbx, -4*32), ymm0) vmovapd(mem(rbx, -3*32), ymm1) dec(rsi) // i -= 1; jne(.DLOOPKLEFT) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4..ymm15 = -a10 * b01 mov(var(alpha), rbx) // load address of alpha vbroadcastsd(mem(rbx), ymm3) // load alpha and duplicate mov(imm(1), rsi) // set cs_b = 1 lea(mem(, rsi, 8), rsi) // cs_b *= sizeof(double) lea(mem(rcx, rsi, 4), rdx) // load address of b11 + 4*cs_b mov(rcx, r11) // save rcx = b11 for later mov(rdx, r14) // save rdx = b11+4*cs_b for later // b11 := alpha * b11 - a10 * b01 vfmsub231pd(mem(rcx), ymm3, ymm4) add(rdi, rcx) vfmsub231pd(mem(rdx), ymm3, ymm5) add(rdi, rdx) vfmsub231pd(mem(rcx), ymm3, ymm6) add(rdi, rcx) vfmsub231pd(mem(rdx), ymm3, ymm7) add(rdi, rdx) vfmsub231pd(mem(rcx), ymm3, ymm8) add(rdi, rcx) vfmsub231pd(mem(rdx), ymm3, ymm9) add(rdi, rdx) vfmsub231pd(mem(rcx), ymm3, ymm10) add(rdi, rcx) vfmsub231pd(mem(rdx), ymm3, ymm11) add(rdi, rdx) vfmsub231pd(mem(rcx), ymm3, ymm12) add(rdi, rcx) vfmsub231pd(mem(rdx), ymm3, ymm13) add(rdi, rdx) vfmsub231pd(mem(rcx), ymm3, ymm14) //add(rdi, rcx) vfmsub231pd(mem(rdx), ymm3, ymm15) //add(rdi, rdx) // prefetch c11 #if 0 mov(r8, rcx) // load address of c11 from r8 // Note: r9 = rs_c * sizeof(double) lea(mem(r9 , r9 , 2), r13) // r13 = 3*rs_c; lea(mem(rcx, r13, 1), rdx) // rdx = c11 + 3*rs_c; prefetch(0, mem(rcx, 7*8)) // prefetch c11 + 0*rs_c prefetch(0, mem(rcx, r9, 1, 7*8)) // prefetch c11 + 1*rs_c prefetch(0, mem(rcx, r9 , 2, 7*8)) // prefetch c11 + 2*rs_c prefetch(0, mem(rdx, 7*8)) // prefetch c11 + 3*rs_c prefetch(0, mem(rdx, r9, 1, 7*8)) // prefetch c11 + 4*rs_c prefetch(0, mem(rdx, r9 , 2, 7*8)) // prefetch c11 + 5*rs_c #endif // trsm computation begins here // Note: contents of b11 are stored as // ymm4 ymm5 = ( beta00..03 ) ( beta04..07 ) // ymm6 ymm7 = ( beta10..13 ) ( beta14..17 ) // ymm8 ymm9 = ( beta20..23 ) ( beta24..27 ) // ymm10 ymm11 = ( beta30..33 ) ( beta34..37 ) // ymm12 ymm13 = ( beta40..43 ) ( beta44..47 ) // ymm14 ymm15 = ( beta50..53 ) ( beta54..57 ) mov(var(a11), rax) // load address of a11 mov(r11, rcx) // recall address of b11 mov(r14, rdx) // recall address of b11+4*cs_b lea(mem(rcx, rdi, 4), rcx) // rcx = b11 + (6-1)*rs_b lea(mem(rcx, rdi, 1), rcx) lea(mem(rdx, rdi, 4), rdx) // rdx = b11 + (6-1)*rs_b + 4*cs_b lea(mem(rdx, rdi, 1), rdx) // iteration 0 ------------- vbroadcastsd(mem(5+5*6)*8(rax), ymm0) // ymm0 = (1/alpha55) #ifdef BLIS_ENABLE_TRSM_PREINVERSION vmulpd(ymm0, ymm14, ymm14) // ymm14 *= (1/alpha55) vmulpd(ymm0, ymm15, ymm15) // ymm15 *= (1/alpha55) #else vdivpd(ymm0, ymm14, ymm14) // ymm14 /= alpha55 vdivpd(ymm0, ymm15, ymm15) // ymm15 /= alpha55 #endif vmovupd(ymm14, mem(rcx)) // store ( beta50..beta53 ) = ymm14 vmovupd(ymm15, mem(rdx)) // store ( beta54..beta57 ) = ymm15 sub(rdi, rcx) // rcx -= rs_b sub(rdi, rdx) // rdx -= rs_b // iteration 1 ------------- vbroadcastsd(mem(4+5*6)*8(rax), ymm0) // ymm0 = alpha45 vbroadcastsd(mem(4+4*6)*8(rax), ymm1) // ymm1 = (1/alpha44) vmulpd(ymm0, ymm14, ymm2) // ymm2 = alpha45 * ymm14 vmulpd(ymm0, ymm15, ymm3) // ymm3 = alpha45 * ymm15 vsubpd(ymm2, ymm12, ymm12) // ymm12 -= ymm2 vsubpd(ymm3, ymm13, ymm13) // ymm13 -= ymm3 #ifdef BLIS_ENABLE_TRSM_PREINVERSION vmulpd(ymm1, ymm12, ymm12) // ymm12 *= (1/alpha44) vmulpd(ymm1, ymm13, ymm13) // ymm13 *= (1/alpha44) #else vdivpd(ymm1, ymm12, ymm12) // ymm12 /= alpha44 vdivpd(ymm1, ymm13, ymm13) // ymm13 /= alpha44 #endif vmovupd(ymm12, mem(rcx)) // store ( beta40..beta43 ) = ymm12 vmovupd(ymm13, mem(rdx)) // store ( beta44..beta47 ) = ymm13 sub(rdi, rcx) // rcx -= rs_b sub(rdi, rdx) // rdx -= rs_b // iteration 2 ------------- vbroadcastsd(mem(3+5*6)*8(rax), ymm0) // ymm0 = alpha35 vbroadcastsd(mem(3+4*6)*8(rax), ymm1) // ymm1 = alpha34 vmulpd(ymm0, ymm14, ymm2) // ymm2 = alpha35 * ymm14 vmulpd(ymm0, ymm15, ymm3) // ymm3 = alpha35 * ymm15 vbroadcastsd(mem(3+3*6)*8(rax), ymm0) // ymm0 = (1/alpha33) vfmadd231pd(ymm1, ymm12, ymm2) // ymm2 += alpha34 * ymm12 vfmadd231pd(ymm1, ymm13, ymm3) // ymm3 += alpha34 * ymm13 vsubpd(ymm2, ymm10, ymm10) // ymm10 -= ymm2 vsubpd(ymm3, ymm11, ymm11) // ymm11 -= ymm3 #ifdef BLIS_ENABLE_TRSM_PREINVERSION vmulpd(ymm0, ymm10, ymm10) // ymm10 *= (1/alpha33) vmulpd(ymm0, ymm11, ymm11) // ymm11 *= (1/alpha33) #else vdivpd(ymm0, ymm10, ymm10) // ymm10 /= alpha33 vdivpd(ymm0, ymm11, ymm11) // ymm11 /= alpha33 #endif vmovupd(ymm10, mem(rcx)) // store ( beta30..beta33 ) = ymm10 vmovupd(ymm11, mem(rdx)) // store ( beta34..beta37 ) = ymm11 sub(rdi, rcx) // rcx -= rs_b sub(rdi, rdx) // rdx -= rs_b // iteration 3 ------------- vbroadcastsd(mem(2+5*6)*8(rax), ymm0) // ymm0 = alpha25 vbroadcastsd(mem(2+4*6)*8(rax), ymm1) // ymm1 = alpha24 vmulpd(ymm0, ymm14, ymm2) // ymm2 = alpha25 * ymm14 vmulpd(ymm0, ymm15, ymm3) // ymm3 = alpha25 * ymm15 vbroadcastsd(mem(2+3*6)*8(rax), ymm0) // ymm0 = alpha23 vfmadd231pd(ymm1, ymm12, ymm2) // ymm2 += alpha24 * ymm12 vfmadd231pd(ymm1, ymm13, ymm3) // ymm3 += alpha24 * ymm13 vbroadcastsd(mem(2+2*6)*8(rax), ymm1) // ymm1 = (1/alpha22) vfmadd231pd(ymm0, ymm10, ymm2) // ymm2 += alpha23 * ymm10 vfmadd231pd(ymm0, ymm11, ymm3) // ymm3 += alpha23 * ymm11 vsubpd(ymm2, ymm8, ymm8) // ymm8 -= ymm2 vsubpd(ymm3, ymm9, ymm9) // ymm9 -= ymm3 #ifdef BLIS_ENABLE_TRSM_PREINVERSION vmulpd(ymm1, ymm8, ymm8) // ymm8 *= (1/alpha22) vmulpd(ymm1, ymm9, ymm9) // ymm9 *= (1/alpha22) #else vdivpd(ymm1, ymm8, ymm8) // ymm8 /= alpha22 vdivpd(ymm1, ymm9, ymm9) // ymm9 /= alpha22 #endif vmovupd(ymm8, mem(rcx)) // store ( beta20..beta23 ) = ymm8 vmovupd(ymm9, mem(rdx)) // store ( beta24..beta27 ) = ymm9 sub(rdi, rcx) // rcx -= rs_b sub(rdi, rdx) // rdx -= rs_b // iteration 4 ------------- vbroadcastsd(mem(1+5*6)*8(rax), ymm0) // ymm0 = alpha15 vbroadcastsd(mem(1+4*6)*8(rax), ymm1) // ymm1 = alpha14 vmulpd(ymm0, ymm14, ymm2) // ymm2 = alpha15 * ymm14 vmulpd(ymm0, ymm15, ymm3) // ymm3 = alpha15 * ymm15 vbroadcastsd(mem(1+3*6)*8(rax), ymm0) // ymm0 = alpha13 vfmadd231pd(ymm1, ymm12, ymm2) // ymm2 += alpha14 * ymm12 vfmadd231pd(ymm1, ymm13, ymm3) // ymm3 += alpha14 * ymm13 vbroadcastsd(mem(1+2*6)*8(rax), ymm1) // ymm1 = alpha12 vfmadd231pd(ymm0, ymm10, ymm2) // ymm2 += alpha13 * ymm10 vfmadd231pd(ymm0, ymm11, ymm3) // ymm3 += alpha13 * ymm11 vbroadcastsd(mem(1+1*6)*8(rax), ymm0) // ymm4 = (1/alpha11) vfmadd231pd(ymm1, ymm8, ymm2) // ymm2 += alpha12 * ymm8 vfmadd231pd(ymm1, ymm9, ymm3) // ymm3 += alpha12 * ymm9 vsubpd(ymm2, ymm6, ymm6) // ymm6 -= ymm2 vsubpd(ymm3, ymm7, ymm7) // ymm7 -= ymm3 #ifdef BLIS_ENABLE_TRSM_PREINVERSION vmulpd(ymm0, ymm6, ymm6) // ymm6 *= (1/alpha11) vmulpd(ymm0, ymm7, ymm7) // ymm7 *= (1/alpha11) #else vdivpd(ymm0, ymm6, ymm6) // ymm6 /= alpha11 vdivpd(ymm0, ymm7, ymm7) // ymm7 /= alpha11 #endif vmovupd(ymm6, mem(rcx)) // store ( beta10..beta13 ) = ymm6 vmovupd(ymm7, mem(rdx)) // store ( beta14..beta17 ) = ymm7 sub(rdi, rcx) // rcx -= rs_b sub(rdi, rdx) // rdx -= rs_b // iteration 5 ------------- vbroadcastsd(mem(0+5*6)*8(rax), ymm0) // ymm0 = alpha05 vbroadcastsd(mem(0+4*6)*8(rax), ymm1) // ymm1 = alpha04 vmulpd(ymm0, ymm14, ymm2) // ymm2 = alpha05 * ymm14 vmulpd(ymm0, ymm15, ymm3) // ymm3 = alpha05 * ymm15 vbroadcastsd(mem(0+3*6)*8(rax), ymm0) // ymm0 = alpha03 vfmadd231pd(ymm1, ymm12, ymm2) // ymm2 += alpha04 * ymm12 vfmadd231pd(ymm1, ymm13, ymm3) // ymm3 += alpha04 * ymm13 vbroadcastsd(mem(0+2*6)*8(rax), ymm1) // ymm1 = alpha02 vfmadd231pd(ymm0, ymm10, ymm2) // ymm2 += alpha03 * ymm10 vfmadd231pd(ymm0, ymm11, ymm3) // ymm3 += alpha03 * ymm11 vbroadcastsd(mem(0+1*6)*8(rax), ymm0) // ymm0 = alpha01 vfmadd231pd(ymm1, ymm8, ymm2) // ymm2 += alpha02 * ymm8 vfmadd231pd(ymm1, ymm9, ymm3) // ymm3 += alpha02 * ymm9 vbroadcastsd(mem(0+0*6)*8(rax), ymm1) // ymm1 = (1/alpha00) vfmadd231pd(ymm0, ymm6, ymm2) // ymm2 += alpha01 * ymm6 vfmadd231pd(ymm0, ymm7, ymm3) // ymm3 += alpha01 * ymm7 vsubpd(ymm2, ymm4, ymm4) // ymm4 -= ymm2 vsubpd(ymm3, ymm5, ymm5) // ymm5 -= ymm3 #ifdef BLIS_ENABLE_TRSM_PREINVERSION vmulpd(ymm1, ymm4, ymm4) // ymm4 *= (1/alpha00) vmulpd(ymm1, ymm5, ymm5) // ymm5 *= (1/alpha00) #else vdivpd(ymm1, ymm4, ymm4) // ymm4 /= alpha00 vdivpd(ymm1, ymm5, ymm5) // ymm5 /= alpha00 #endif vmovupd(ymm4, mem(rcx)) // store ( beta00..beta03 ) = ymm4 vmovupd(ymm5, mem(rdx)) // store ( beta04..beta07 ) = ymm5 sub(rdi, rcx) // rcx -= rs_b sub(rdi, rdx) // rdx -= rs_b mov(r8, rcx) // load address of c11 from r8 mov(r9, rdi) // load rs_c (in bytes) from r9 mov(r10, rsi) // load cs_c (in bytes) from r10 lea(mem(rcx, rsi, 4), rdx) // load address of c11 + 4*cs_c; lea(mem(rcx, rdi, 4), r14) // load address of c11 + 4*rs_c; // These are used in the macros below. lea(mem(rsi, rsi, 2), r13) // r13 = 3*cs_c; //lea(mem(rsi, rsi, 4), r15) // r15 = 5*cs_c; //lea(mem(r13, rsi, 4), r10) // r10 = 7*cs_c; cmp(imm(8), rsi) // set ZF if (8*cs_c) == 8. jz(.DROWSTORED) // jump to row storage case cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORED) // jump to column storage case // if neither row- or column- // stored, use general case. label(.DGENSTORED) vmovapd(ymm4, ymm0) DGEMM_OUTPUT_GS_BETA_NZ add(rdi, rcx) // c11 += rs_c; vmovapd(ymm6, ymm0) DGEMM_OUTPUT_GS_BETA_NZ add(rdi, rcx) // c11 += rs_c; vmovapd(ymm8, ymm0) DGEMM_OUTPUT_GS_BETA_NZ add(rdi, rcx) // c11 += rs_c; vmovapd(ymm10, ymm0) DGEMM_OUTPUT_GS_BETA_NZ add(rdi, rcx) // c11 += rs_c; vmovapd(ymm12, ymm0) DGEMM_OUTPUT_GS_BETA_NZ add(rdi, rcx) // c11 += rs_c; vmovapd(ymm14, ymm0) DGEMM_OUTPUT_GS_BETA_NZ mov(rdx, rcx) // rcx = c11 + 4*cs_c vmovapd(ymm5, ymm0) DGEMM_OUTPUT_GS_BETA_NZ add(rdi, rcx) // c11 += rs_c; vmovapd(ymm7, ymm0) DGEMM_OUTPUT_GS_BETA_NZ add(rdi, rcx) // c11 += rs_c; vmovapd(ymm9, ymm0) DGEMM_OUTPUT_GS_BETA_NZ add(rdi, rcx) // c11 += rs_c; vmovapd(ymm11, ymm0) DGEMM_OUTPUT_GS_BETA_NZ add(rdi, rcx) // c11 += rs_c; vmovapd(ymm13, ymm0) DGEMM_OUTPUT_GS_BETA_NZ add(rdi, rcx) // c11 += rs_c; vmovapd(ymm15, ymm0) DGEMM_OUTPUT_GS_BETA_NZ jmp(.DDONE) label(.DROWSTORED) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vmovupd(ymm5, mem(rdx)) add(rdi, rdx) vmovupd(ymm6, mem(rcx)) add(rdi, rcx) vmovupd(ymm7, mem(rdx)) add(rdi, rdx) vmovupd(ymm8, mem(rcx)) add(rdi, rcx) vmovupd(ymm9, mem(rdx)) add(rdi, rdx) vmovupd(ymm10, mem(rcx)) add(rdi, rcx) vmovupd(ymm11, mem(rdx)) add(rdi, rdx) vmovupd(ymm12, mem(rcx)) add(rdi, rcx) vmovupd(ymm13, mem(rdx)) add(rdi, rdx) vmovupd(ymm14, mem(rcx)) //add(rdi, rcx) vmovupd(ymm15, mem(rdx)) //add(rdi, rdx) jmp(.DDONE) label(.DCOLSTORED) vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vunpcklpd(ymm10, ymm8, ymm2) vunpckhpd(ymm10, ymm8, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vperm2f128(imm(0x31), ymm2, ymm0, ymm8) vperm2f128(imm(0x31), ymm3, ymm1, ymm10) vmovupd(ymm4, mem(rcx)) vmovupd(ymm6, mem(rcx, rsi, 1)) vmovupd(ymm8, mem(rcx, rsi, 2)) vmovupd(ymm10, mem(rcx, r13, 1)) lea(mem(rcx, rsi, 4), rcx) vunpcklpd(ymm14, ymm12, ymm0) vunpckhpd(ymm14, ymm12, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vextractf128(imm(0x1), ymm1, xmm3) vmovupd(xmm0, mem(r14)) vmovupd(xmm1, mem(r14, rsi, 1)) vmovupd(xmm2, mem(r14, rsi, 2)) vmovupd(xmm3, mem(r14, r13, 1)) lea(mem(r14, rsi, 4), r14) vunpcklpd(ymm7, ymm5, ymm0) vunpckhpd(ymm7, ymm5, ymm1) vunpcklpd(ymm11, ymm9, ymm2) vunpckhpd(ymm11, ymm9, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm5) vinsertf128(imm(0x1), xmm3, ymm1, ymm7) vperm2f128(imm(0x31), ymm2, ymm0, ymm9) vperm2f128(imm(0x31), ymm3, ymm1, ymm11) vmovupd(ymm5, mem(rcx)) vmovupd(ymm7, mem(rcx, rsi, 1)) vmovupd(ymm9, mem(rcx, rsi, 2)) vmovupd(ymm11, mem(rcx, r13, 1)) //lea(mem(rcx, rsi, 4), rcx) vunpcklpd(ymm15, ymm13, ymm0) vunpckhpd(ymm15, ymm13, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vextractf128(imm(0x1), ymm1, xmm3) vmovupd(xmm0, mem(r14)) vmovupd(xmm1, mem(r14, rsi, 1)) vmovupd(xmm2, mem(r14, rsi, 2)) vmovupd(xmm3, mem(r14, r13, 1)) //lea(mem(r14, rsi, 4), r14) label(.DDONE) vzeroupper() end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), // 0 [k_left] "m" (k_left), // 1 [a10] "m" (a10), // 2 [b01] "m" (b01), // 3 [beta] "m" (beta), // 4 [alpha] "m" (alpha), // 5 [a11] "m" (a11), // 6 [b11] "m" (b11), // 7 [c11] "m" (c11), // 8 [rs_c] "m" (rs_c), // 9 [cs_c] "m" (cs_c) // 10 : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) GEMMTRSM_UKR_FLUSH_CT( d ); } blis-0.9.0/kernels/haswell/3/old/000077500000000000000000000000001422157504600165015ustar00rootroot00000000000000blis-0.9.0/kernels/haswell/3/old/bli_gemm_haswell_asm_d12x4.c000066400000000000000000002063101422157504600237230ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define SGEMM_INPUT_GS_BETA_NZ \ "vmovlps (%%rcx ), %%xmm0, %%xmm0 \n\t" \ "vmovhps (%%rcx,%%rsi,1), %%xmm0, %%xmm0 \n\t" \ "vmovlps (%%rcx,%%rsi,2), %%xmm1, %%xmm1 \n\t" \ "vmovhps (%%rcx,%%r13 ), %%xmm1, %%xmm1 \n\t" \ "vshufps $0x88, %%xmm1, %%xmm0, %%xmm0 \n\t" \ "vmovlps (%%rcx,%%rsi,4), %%xmm2, %%xmm2 \n\t" \ "vmovhps (%%rcx,%%r15 ), %%xmm2, %%xmm2 \n\t" \ /* We can't use vmovhps for loading the last element becauase that might result in reading beyond valid memory. (vmov[lh]psd load pairs of adjacent floats at a time.) So we need to use vmovss instead. But since we're limited to using ymm0 through ymm2 (ymm3 contains beta and ymm4 through ymm15 contain the microtile) and due to the way vmovss zeros out all bits above 31, we have to load element 7 before element 6. */ \ "vmovss (%%rcx,%%r10 ), %%xmm1 \n\t" \ "vpermilps $0xcf, %%xmm1, %%xmm1 \n\t" \ "vmovlps (%%rcx,%%r13,2), %%xmm1, %%xmm1 \n\t" \ /*"vmovhps (%%rcx,%%r10 ), %%xmm1, %%xmm1 \n\t"*/ \ "vshufps $0x88, %%xmm1, %%xmm2, %%xmm2 \n\t" \ "vperm2f128 $0x20, %%ymm2, %%ymm0, %%ymm0 \n\t" #define SGEMM_OUTPUT_GS_BETA_NZ \ "vextractf128 $1, %%ymm0, %%xmm2 \n\t" \ "vmovss %%xmm0, (%%rcx ) \n\t" \ "vpermilps $0x39, %%xmm0, %%xmm1 \n\t" \ "vmovss %%xmm1, (%%rcx,%%rsi,1) \n\t" \ "vpermilps $0x39, %%xmm1, %%xmm0 \n\t" \ "vmovss %%xmm0, (%%rcx,%%rsi,2) \n\t" \ "vpermilps $0x39, %%xmm0, %%xmm1 \n\t" \ "vmovss %%xmm1, (%%rcx,%%r13 ) \n\t" \ "vmovss %%xmm2, (%%rcx,%%rsi,4) \n\t" \ "vpermilps $0x39, %%xmm2, %%xmm1 \n\t" \ "vmovss %%xmm1, (%%rcx,%%r15 ) \n\t" \ "vpermilps $0x39, %%xmm1, %%xmm2 \n\t" \ "vmovss %%xmm2, (%%rcx,%%r13,2) \n\t" \ "vpermilps $0x39, %%xmm2, %%xmm1 \n\t" \ "vmovss %%xmm1, (%%rcx,%%r10 ) \n\t" void bli_sgemm_haswell_asm_24x4 ( dim_t k0, float* restrict alpha, float* restrict a, float* restrict b, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; __asm__ volatile ( " \n\t" "vzeroall \n\t" // zero all xmm/ymm registers. " \n\t" " \n\t" "movq %2, %%rax \n\t" // load address of a. "movq %3, %%rbx \n\t" // load address of b. //"movq %9, %%r15 \n\t" // load address of b_next. " \n\t" " \n\t" // initialize loop by pre-loading "vmovaps 0 * 32(%%rax), %%ymm0 \n\t" "vmovaps 1 * 32(%%rax), %%ymm1 \n\t" "vmovaps 2 * 32(%%rax), %%ymm2 \n\t" " \n\t" "movq %6, %%rcx \n\t" // load address of c "movq %8, %%rdi \n\t" // load cs_c "leaq (,%%rdi,4), %%rdi \n\t" // cs_c *= sizeof(float) " \n\t" "leaq (%%rdi,%%rdi,2), %%r13 \n\t" // r13 = 3*cs_c; "prefetcht0 7 * 4(%%rcx) \n\t" // prefetch c + 0*cs_c "prefetcht0 7 * 4(%%rcx,%%rdi) \n\t" // prefetch c + 1*cs_c "prefetcht0 7 * 4(%%rcx,%%rdi,2) \n\t" // prefetch c + 2*cs_c "prefetcht0 7 * 4(%%rcx,%%r13) \n\t" // prefetch c + 3*cs_c " \n\t" " \n\t" " \n\t" " \n\t" "movq %0, %%rsi \n\t" // i = k_iter; "testq %%rsi, %%rsi \n\t" // check i via logical AND. "je .SCONSIDKLEFT \n\t" // if i == 0, jump to code that " \n\t" // contains the k_left loop. " \n\t" " \n\t" ".SLOOPKITER: \n\t" // MAIN LOOP " \n\t" " \n\t" " \n\t" // iteration 0 "prefetcht0 16 * 32(%%rax) \n\t" " \n\t" "vbroadcastss 0 * 4(%%rbx), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm4 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm5 \n\t" "vfmadd231ps %%ymm2, %%ymm3, %%ymm6 \n\t" " \n\t" "vbroadcastss 1 * 4(%%rbx), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm7 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm8 \n\t" "vfmadd231ps %%ymm2, %%ymm3, %%ymm9 \n\t" " \n\t" "vbroadcastss 2 * 4(%%rbx), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm10 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm11 \n\t" "vfmadd231ps %%ymm2, %%ymm3, %%ymm12 \n\t" " \n\t" "vbroadcastss 3 * 4(%%rbx), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm13 \n\t" "vmovaps 3 * 32(%%rax), %%ymm0 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm14 \n\t" "vmovaps 4 * 32(%%rax), %%ymm1 \n\t" "vfmadd231ps %%ymm2, %%ymm3, %%ymm15 \n\t" "vmovaps 5 * 32(%%rax), %%ymm2 \n\t" " \n\t" " \n\t" " \n\t" " \n\t" // iteration 1 "vbroadcastss 4 * 4(%%rbx), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm4 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm5 \n\t" "vfmadd231ps %%ymm2, %%ymm3, %%ymm6 \n\t" " \n\t" "vbroadcastss 5 * 4(%%rbx), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm7 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm8 \n\t" "vfmadd231ps %%ymm2, %%ymm3, %%ymm9 \n\t" " \n\t" "vbroadcastss 6 * 4(%%rbx), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm10 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm11 \n\t" "vfmadd231ps %%ymm2, %%ymm3, %%ymm12 \n\t" " \n\t" "vbroadcastss 7 * 4(%%rbx), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm13 \n\t" "vmovaps 6 * 32(%%rax), %%ymm0 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm14 \n\t" "vmovaps 7 * 32(%%rax), %%ymm1 \n\t" "vfmadd231ps %%ymm2, %%ymm3, %%ymm15 \n\t" "vmovaps 8 * 32(%%rax), %%ymm2 \n\t" " \n\t" " \n\t" " \n\t" " \n\t" // iteration 2 "prefetcht0 22 * 32(%%rax) \n\t" " \n\t" "vbroadcastss 8 * 4(%%rbx), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm4 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm5 \n\t" "vfmadd231ps %%ymm2, %%ymm3, %%ymm6 \n\t" " \n\t" "vbroadcastss 9 * 4(%%rbx), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm7 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm8 \n\t" "vfmadd231ps %%ymm2, %%ymm3, %%ymm9 \n\t" " \n\t" "vbroadcastss 10 * 4(%%rbx), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm10 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm11 \n\t" "vfmadd231ps %%ymm2, %%ymm3, %%ymm12 \n\t" " \n\t" "vbroadcastss 11 * 4(%%rbx), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm13 \n\t" "vmovaps 9 * 32(%%rax), %%ymm0 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm14 \n\t" "vmovaps 10 * 32(%%rax), %%ymm1 \n\t" "vfmadd231ps %%ymm2, %%ymm3, %%ymm15 \n\t" "vmovaps 11 * 32(%%rax), %%ymm2 \n\t" " \n\t" " \n\t" " \n\t" " \n\t" // iteration 3 "vbroadcastss 12 * 4(%%rbx), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm4 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm5 \n\t" "vfmadd231ps %%ymm2, %%ymm3, %%ymm6 \n\t" " \n\t" "vbroadcastss 13 * 4(%%rbx), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm7 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm8 \n\t" "vfmadd231ps %%ymm2, %%ymm3, %%ymm9 \n\t" " \n\t" "vbroadcastss 14 * 4(%%rbx), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm10 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm11 \n\t" "vfmadd231ps %%ymm2, %%ymm3, %%ymm12 \n\t" " \n\t" "vbroadcastss 15 * 4(%%rbx), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm13 \n\t" "vmovaps 12 * 32(%%rax), %%ymm0 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm14 \n\t" "vmovaps 13 * 32(%%rax), %%ymm1 \n\t" "vfmadd231ps %%ymm2, %%ymm3, %%ymm15 \n\t" "vmovaps 14 * 32(%%rax), %%ymm2 \n\t" " \n\t" " \n\t" " \n\t" "addq $4 * 24 * 4, %%rax \n\t" // a += 4*24 (unroll x mr) "addq $4 * 4 * 4, %%rbx \n\t" // b += 4*4 (unroll x nr) " \n\t" " \n\t" "decq %%rsi \n\t" // i -= 1; "jne .SLOOPKITER \n\t" // iterate again if i != 0. " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" ".SCONSIDKLEFT: \n\t" " \n\t" "movq %1, %%rsi \n\t" // i = k_left; "testq %%rsi, %%rsi \n\t" // check i via logical AND. "je .SPOSTACCUM \n\t" // if i == 0, we're done; jump to end. " \n\t" // else, we prepare to enter k_left loop. " \n\t" " \n\t" ".SLOOPKLEFT: \n\t" // EDGE LOOP " \n\t" "prefetcht0 16 * 32(%%rax) \n\t" " \n\t" "vbroadcastss 0 * 4(%%rbx), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm4 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm5 \n\t" "vfmadd231ps %%ymm2, %%ymm3, %%ymm6 \n\t" " \n\t" "vbroadcastss 1 * 4(%%rbx), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm7 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm8 \n\t" "vfmadd231ps %%ymm2, %%ymm3, %%ymm9 \n\t" " \n\t" "vbroadcastss 2 * 4(%%rbx), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm10 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm11 \n\t" "vfmadd231ps %%ymm2, %%ymm3, %%ymm12 \n\t" " \n\t" "vbroadcastss 3 * 4(%%rbx), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm13 \n\t" "vmovaps 3 * 32(%%rax), %%ymm0 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm14 \n\t" "vmovaps 4 * 32(%%rax), %%ymm1 \n\t" "vfmadd231ps %%ymm2, %%ymm3, %%ymm15 \n\t" "vmovaps 5 * 32(%%rax), %%ymm2 \n\t" " \n\t" " \n\t" " \n\t" "addq $1 * 24 * 4, %%rax \n\t" // a += 1*24 (unroll x mr) "addq $1 * 4 * 4, %%rbx \n\t" // b += 1*4 (unroll x nr) " \n\t" " \n\t" "decq %%rsi \n\t" // i -= 1; "jne .SLOOPKLEFT \n\t" // iterate again if i != 0. " \n\t" " \n\t" " \n\t" ".SPOSTACCUM: \n\t" " \n\t" " \n\t" " \n\t" " \n\t" "movq %4, %%rax \n\t" // load address of alpha "movq %5, %%rbx \n\t" // load address of beta "vbroadcastss (%%rax), %%ymm0 \n\t" // load alpha and duplicate "vbroadcastss (%%rbx), %%ymm3 \n\t" // load beta and duplicate " \n\t" "vmulps %%ymm0, %%ymm4, %%ymm4 \n\t" // scale by alpha "vmulps %%ymm0, %%ymm5, %%ymm5 \n\t" "vmulps %%ymm0, %%ymm6, %%ymm6 \n\t" "vmulps %%ymm0, %%ymm7, %%ymm7 \n\t" "vmulps %%ymm0, %%ymm8, %%ymm8 \n\t" "vmulps %%ymm0, %%ymm9, %%ymm9 \n\t" "vmulps %%ymm0, %%ymm10, %%ymm10 \n\t" "vmulps %%ymm0, %%ymm11, %%ymm11 \n\t" "vmulps %%ymm0, %%ymm12, %%ymm12 \n\t" "vmulps %%ymm0, %%ymm13, %%ymm13 \n\t" "vmulps %%ymm0, %%ymm14, %%ymm14 \n\t" "vmulps %%ymm0, %%ymm15, %%ymm15 \n\t" " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" "movq %7, %%rsi \n\t" // load rs_c "leaq (,%%rsi,4), %%rsi \n\t" // rsi = rs_c * sizeof(float) " \n\t" "leaq (%%rcx,%%rsi,8), %%rdx \n\t" // rdx = c + 8*rs_c; "leaq (%%rdx,%%rsi,8), %%r12 \n\t" // r12 = c + 16*rs_c; " \n\t" "leaq (%%rsi,%%rsi,2), %%r13 \n\t" // r13 = 3*rs_c; "leaq (%%rsi,%%rsi,4), %%r15 \n\t" // r15 = 5*rs_c; "leaq (%%r13,%%rsi,4), %%r10 \n\t" // r10 = 7*rs_c; " \n\t" " \n\t" " \n\t" " \n\t" // determine if " \n\t" // c % 32 == 0, AND " \n\t" // 8*cs_c % 32 == 0, AND " \n\t" // rs_c == 1 " \n\t" // ie: aligned, ldim aligned, and " \n\t" // column-stored " \n\t" "cmpq $4, %%rsi \n\t" // set ZF if (4*rs_c) == 4. "sete %%bl \n\t" // bl = ( ZF == 1 ? 1 : 0 ); "testq $31, %%rcx \n\t" // set ZF if c & 32 is zero. "setz %%bh \n\t" // bh = ( ZF == 0 ? 1 : 0 ); "testq $31, %%rdi \n\t" // set ZF if (4*cs_c) & 32 is zero. "setz %%al \n\t" // al = ( ZF == 0 ? 1 : 0 ); " \n\t" // and(bl,bh) followed by " \n\t" // and(bh,al) will reveal result " \n\t" " \n\t" // now avoid loading C if beta == 0 " \n\t" "vxorps %%ymm0, %%ymm0, %%ymm0 \n\t" // set ymm0 to zero. "vucomiss %%xmm0, %%xmm3 \n\t" // set ZF if beta == 0. "je .SBETAZERO \n\t" // if ZF = 1, jump to beta == 0 case " \n\t" " \n\t" " \n\t" // check if aligned/column-stored "andb %%bl, %%bh \n\t" // set ZF if bl & bh == 1. "andb %%bh, %%al \n\t" // set ZF if bh & al == 1. "jne .SCOLSTORED \n\t" // jump to column storage case " \n\t" " \n\t" " \n\t" ".SGENSTORED: \n\t" " \n\t" " \n\t" SGEMM_INPUT_GS_BETA_NZ "vfmadd213ps %%ymm4, %%ymm3, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" SGEMM_INPUT_GS_BETA_NZ "vfmadd213ps %%ymm7, %%ymm3, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" SGEMM_INPUT_GS_BETA_NZ "vfmadd213ps %%ymm10, %%ymm3, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" SGEMM_INPUT_GS_BETA_NZ "vfmadd213ps %%ymm13, %%ymm3, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ //"addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" "movq %%rdx, %%rcx \n\t" // rcx = c + 8*rs_c " \n\t" " \n\t" SGEMM_INPUT_GS_BETA_NZ "vfmadd213ps %%ymm5, %%ymm3, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" SGEMM_INPUT_GS_BETA_NZ "vfmadd213ps %%ymm8, %%ymm3, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" SGEMM_INPUT_GS_BETA_NZ "vfmadd213ps %%ymm11, %%ymm3, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" SGEMM_INPUT_GS_BETA_NZ "vfmadd213ps %%ymm14, %%ymm3, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ //"addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" "movq %%r12, %%rcx \n\t" // rcx = c + 16*rs_c " \n\t" " \n\t" SGEMM_INPUT_GS_BETA_NZ "vfmadd213ps %%ymm6, %%ymm3, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" SGEMM_INPUT_GS_BETA_NZ "vfmadd213ps %%ymm9, %%ymm3, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" SGEMM_INPUT_GS_BETA_NZ "vfmadd213ps %%ymm12, %%ymm3, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" SGEMM_INPUT_GS_BETA_NZ "vfmadd213ps %%ymm15, %%ymm3, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ //"addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" "jmp .SDONE \n\t" // jump to end. " \n\t" " \n\t" " \n\t" ".SCOLSTORED: \n\t" " \n\t" " \n\t" "vmovaps (%%rcx), %%ymm0 \n\t" "vfmadd213ps %%ymm4, %%ymm3, %%ymm0 \n\t" "vmovaps %%ymm0, (%%rcx) \n\t" "addq %%rdi, %%rcx \n\t" "vmovaps (%%rdx), %%ymm1 \n\t" "vfmadd213ps %%ymm5, %%ymm3, %%ymm1 \n\t" "vmovaps %%ymm1, (%%rdx) \n\t" "addq %%rdi, %%rdx \n\t" "vmovaps (%%r12), %%ymm2 \n\t" "vfmadd213ps %%ymm6, %%ymm3, %%ymm2 \n\t" "vmovaps %%ymm2, (%%r12) \n\t" "addq %%rdi, %%r12 \n\t" " \n\t" " \n\t" "vmovaps (%%rcx), %%ymm0 \n\t" "vfmadd213ps %%ymm7, %%ymm3, %%ymm0 \n\t" "vmovaps %%ymm0, (%%rcx) \n\t" "addq %%rdi, %%rcx \n\t" "vmovaps (%%rdx), %%ymm1 \n\t" "vfmadd213ps %%ymm8, %%ymm3, %%ymm1 \n\t" "vmovaps %%ymm1, (%%rdx) \n\t" "addq %%rdi, %%rdx \n\t" "vmovaps (%%r12), %%ymm2 \n\t" "vfmadd213ps %%ymm9, %%ymm3, %%ymm2 \n\t" "vmovaps %%ymm2, (%%r12) \n\t" "addq %%rdi, %%r12 \n\t" " \n\t" " \n\t" "vmovaps (%%rcx), %%ymm0 \n\t" "vfmadd213ps %%ymm10, %%ymm3, %%ymm0 \n\t" "vmovaps %%ymm0, (%%rcx) \n\t" "addq %%rdi, %%rcx \n\t" "vmovaps (%%rdx), %%ymm1 \n\t" "vfmadd213ps %%ymm11, %%ymm3, %%ymm1 \n\t" "vmovaps %%ymm1, (%%rdx) \n\t" "addq %%rdi, %%rdx \n\t" "vmovaps (%%r12), %%ymm2 \n\t" "vfmadd213ps %%ymm12, %%ymm3, %%ymm2 \n\t" "vmovaps %%ymm2, (%%r12) \n\t" "addq %%rdi, %%r12 \n\t" " \n\t" " \n\t" "vmovaps (%%rcx), %%ymm0 \n\t" "vfmadd213ps %%ymm13, %%ymm3, %%ymm0 \n\t" "vmovaps %%ymm0, (%%rcx) \n\t" "addq %%rdi, %%rcx \n\t" "vmovaps (%%rdx), %%ymm1 \n\t" "vfmadd213ps %%ymm14, %%ymm3, %%ymm1 \n\t" "vmovaps %%ymm1, (%%rdx) \n\t" "addq %%rdi, %%rdx \n\t" "vmovaps (%%r12), %%ymm2 \n\t" "vfmadd213ps %%ymm15, %%ymm3, %%ymm2 \n\t" "vmovaps %%ymm2, (%%r12) \n\t" "addq %%rdi, %%r12 \n\t" " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" "jmp .SDONE \n\t" // jump to end. " \n\t" " \n\t" " \n\t" ".SBETAZERO: \n\t" " \n\t" // check if aligned/column-stored "andb %%bl, %%bh \n\t" // set ZF if bl & bh == 1. "andb %%bh, %%al \n\t" // set ZF if bh & al == 1. "jne .SCOLSTORBZ \n\t" // jump to column storage case " \n\t" " \n\t" " \n\t" ".SGENSTORBZ: \n\t" " \n\t" " \n\t" "vmovaps %%ymm4, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" "vmovaps %%ymm7, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" "vmovaps %%ymm10, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" "vmovaps %%ymm13, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ //"addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" "movq %%rdx, %%rcx \n\t" // rcx = c + 8*rs_c " \n\t" " \n\t" "vmovaps %%ymm5, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" "vmovaps %%ymm8, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" "vmovaps %%ymm11, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" "vmovaps %%ymm14, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ //"addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" "movq %%r12, %%rcx \n\t" // rcx = c + 16*rs_c " \n\t" " \n\t" "vmovaps %%ymm6, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" "vmovaps %%ymm9, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" "vmovaps %%ymm12, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" "vmovaps %%ymm15, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ //"addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" "jmp .SDONE \n\t" // jump to end. " \n\t" " \n\t" " \n\t" ".SCOLSTORBZ: \n\t" " \n\t" " \n\t" "vmovaps %%ymm4, (%%rcx) \n\t" "addq %%rdi, %%rcx \n\t" "vmovaps %%ymm5, (%%rdx) \n\t" "addq %%rdi, %%rdx \n\t" "vmovaps %%ymm6, (%%r12) \n\t" "addq %%rdi, %%r12 \n\t" " \n\t" "vmovaps %%ymm7, (%%rcx) \n\t" "addq %%rdi, %%rcx \n\t" "vmovaps %%ymm8, (%%rdx) \n\t" "addq %%rdi, %%rdx \n\t" "vmovaps %%ymm9, (%%r12) \n\t" "addq %%rdi, %%r12 \n\t" " \n\t" "vmovaps %%ymm10, (%%rcx) \n\t" "addq %%rdi, %%rcx \n\t" "vmovaps %%ymm11, (%%rdx) \n\t" "addq %%rdi, %%rdx \n\t" "vmovaps %%ymm12, (%%r12) \n\t" "addq %%rdi, %%r12 \n\t" " \n\t" "vmovaps %%ymm13, (%%rcx) \n\t" //"addq %%rdi, %%rcx \n\t" "vmovaps %%ymm14, (%%rdx) \n\t" //"addq %%rdi, %%rdx \n\t" "vmovaps %%ymm15, (%%r12) \n\t" //"addq %%rdi, %%r12 \n\t" " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" ".SDONE: \n\t" " \n\t" "vzeroupper \n\t" " \n\t" : // output operands (none) : // input operands "m" (k_iter), // 0 "m" (k_left), // 1 "m" (a), // 2 "m" (b), // 3 "m" (alpha), // 4 "m" (beta), // 5 "m" (c), // 6 "m" (rs_c), // 7 "m" (cs_c)/*, // 8 "m" (b_next), // 9 "m" (a_next)*/ // 10 : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ); } #define DGEMM_INPUT_GS_BETA_NZ \ "vmovlpd (%%rcx ), %%xmm0, %%xmm0 \n\t" \ "vmovhpd (%%rcx,%%rsi,1), %%xmm0, %%xmm0 \n\t" \ "vmovlpd (%%rcx,%%rsi,2), %%xmm1, %%xmm1 \n\t" \ "vmovhpd (%%rcx,%%r13 ), %%xmm1, %%xmm1 \n\t" \ "vperm2f128 $0x20, %%ymm1, %%ymm0, %%ymm0 \n\t" /*\ "vmovlps (%%rcx,%%rsi,4), %%xmm2, %%xmm2 \n\t" \ "vmovhps (%%rcx,%%r15 ), %%xmm2, %%xmm2 \n\t" \ "vmovlps (%%rcx,%%r13,2), %%xmm1, %%xmm1 \n\t" \ "vmovhps (%%rcx,%%r10 ), %%xmm1, %%xmm1 \n\t" \ "vperm2f128 $0x20, %%ymm1, %%ymm2, %%ymm2 \n\t"*/ #define DGEMM_OUTPUT_GS_BETA_NZ \ "vextractf128 $1, %%ymm0, %%xmm1 \n\t" \ "vmovlpd %%xmm0, (%%rcx ) \n\t" \ "vmovhpd %%xmm0, (%%rcx,%%rsi ) \n\t" \ "vmovlpd %%xmm1, (%%rcx,%%rsi,2) \n\t" \ "vmovhpd %%xmm1, (%%rcx,%%r13 ) \n\t" /*\ "vextractf128 $1, %%ymm2, %%xmm1 \n\t" \ "vmovlpd %%xmm2, (%%rcx,%%rsi,4) \n\t" \ "vmovhpd %%xmm2, (%%rcx,%%r15 ) \n\t" \ "vmovlpd %%xmm1, (%%rcx,%%r13,2) \n\t" \ "vmovhpd %%xmm1, (%%rcx,%%r10 ) \n\t"*/ void bli_dgemm_haswell_asm_12x4 ( dim_t k0, double* restrict alpha, double* restrict a, double* restrict b, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; __asm__ volatile ( " \n\t" "vzeroall \n\t" // zero all xmm/ymm registers. " \n\t" " \n\t" "movq %2, %%rax \n\t" // load address of a. "movq %3, %%rbx \n\t" // load address of b. //"movq %9, %%r15 \n\t" // load address of b_next. " \n\t" " \n\t" // initialize loop by pre-loading "vmovapd 0 * 32(%%rax), %%ymm0 \n\t" "vmovapd 1 * 32(%%rax), %%ymm1 \n\t" "vmovapd 2 * 32(%%rax), %%ymm2 \n\t" " \n\t" "movq %6, %%rcx \n\t" // load address of c "movq %8, %%rdi \n\t" // load cs_c "leaq (,%%rdi,8), %%rdi \n\t" // cs_c *= sizeof(double) " \n\t" "leaq (%%rdi,%%rdi,2), %%r13 \n\t" // r13 = 3*cs_c; "prefetcht0 7 * 8(%%rcx) \n\t" // prefetch c + 0*cs_c "prefetcht0 7 * 8(%%rcx,%%rdi) \n\t" // prefetch c + 1*cs_c "prefetcht0 7 * 8(%%rcx,%%rdi,2) \n\t" // prefetch c + 2*cs_c "prefetcht0 7 * 8(%%rcx,%%r13) \n\t" // prefetch c + 3*cs_c " \n\t" " \n\t" " \n\t" " \n\t" "movq %0, %%rsi \n\t" // i = k_iter; "testq %%rsi, %%rsi \n\t" // check i via logical AND. "je .DCONSIDKLEFT \n\t" // if i == 0, jump to code that " \n\t" // contains the k_left loop. " \n\t" " \n\t" ".DLOOPKITER: \n\t" // MAIN LOOP " \n\t" " \n\t" " \n\t" // iteration 0 "prefetcht0 16 * 32(%%rax) \n\t" " \n\t" "vbroadcastsd 0 * 8(%%rbx), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm4 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm5 \n\t" "vfmadd231pd %%ymm2, %%ymm3, %%ymm6 \n\t" " \n\t" "vbroadcastsd 1 * 8(%%rbx), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm7 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm8 \n\t" "vfmadd231pd %%ymm2, %%ymm3, %%ymm9 \n\t" " \n\t" "vbroadcastsd 2 * 8(%%rbx), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm10 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm11 \n\t" "vfmadd231pd %%ymm2, %%ymm3, %%ymm12 \n\t" " \n\t" "vbroadcastsd 3 * 8(%%rbx), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm13 \n\t" "vmovapd 3 * 32(%%rax), %%ymm0 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm14 \n\t" "vmovapd 4 * 32(%%rax), %%ymm1 \n\t" "vfmadd231pd %%ymm2, %%ymm3, %%ymm15 \n\t" "vmovapd 5 * 32(%%rax), %%ymm2 \n\t" " \n\t" " \n\t" " \n\t" " \n\t" // iteration 1 "vbroadcastsd 4 * 8(%%rbx), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm4 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm5 \n\t" "vfmadd231pd %%ymm2, %%ymm3, %%ymm6 \n\t" " \n\t" "vbroadcastsd 5 * 8(%%rbx), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm7 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm8 \n\t" "vfmadd231pd %%ymm2, %%ymm3, %%ymm9 \n\t" " \n\t" "vbroadcastsd 6 * 8(%%rbx), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm10 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm11 \n\t" "vfmadd231pd %%ymm2, %%ymm3, %%ymm12 \n\t" " \n\t" "vbroadcastsd 7 * 8(%%rbx), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm13 \n\t" "vmovapd 6 * 32(%%rax), %%ymm0 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm14 \n\t" "vmovapd 7 * 32(%%rax), %%ymm1 \n\t" "vfmadd231pd %%ymm2, %%ymm3, %%ymm15 \n\t" "vmovapd 8 * 32(%%rax), %%ymm2 \n\t" " \n\t" " \n\t" " \n\t" " \n\t" // iteration 2 "prefetcht0 22 * 32(%%rax) \n\t" " \n\t" "vbroadcastsd 8 * 8(%%rbx), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm4 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm5 \n\t" "vfmadd231pd %%ymm2, %%ymm3, %%ymm6 \n\t" " \n\t" "vbroadcastsd 9 * 8(%%rbx), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm7 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm8 \n\t" "vfmadd231pd %%ymm2, %%ymm3, %%ymm9 \n\t" " \n\t" "vbroadcastsd 10 * 8(%%rbx), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm10 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm11 \n\t" "vfmadd231pd %%ymm2, %%ymm3, %%ymm12 \n\t" " \n\t" "vbroadcastsd 11 * 8(%%rbx), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm13 \n\t" "vmovapd 9 * 32(%%rax), %%ymm0 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm14 \n\t" "vmovapd 10 * 32(%%rax), %%ymm1 \n\t" "vfmadd231pd %%ymm2, %%ymm3, %%ymm15 \n\t" "vmovapd 11 * 32(%%rax), %%ymm2 \n\t" " \n\t" " \n\t" " \n\t" " \n\t" // iteration 3 "vbroadcastsd 12 * 8(%%rbx), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm4 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm5 \n\t" "vfmadd231pd %%ymm2, %%ymm3, %%ymm6 \n\t" " \n\t" "vbroadcastsd 13 * 8(%%rbx), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm7 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm8 \n\t" "vfmadd231pd %%ymm2, %%ymm3, %%ymm9 \n\t" " \n\t" "vbroadcastsd 14 * 8(%%rbx), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm10 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm11 \n\t" "vfmadd231pd %%ymm2, %%ymm3, %%ymm12 \n\t" " \n\t" "vbroadcastsd 15 * 8(%%rbx), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm13 \n\t" "vmovapd 12 * 32(%%rax), %%ymm0 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm14 \n\t" "vmovapd 13 * 32(%%rax), %%ymm1 \n\t" "vfmadd231pd %%ymm2, %%ymm3, %%ymm15 \n\t" "vmovapd 14 * 32(%%rax), %%ymm2 \n\t" " \n\t" " \n\t" " \n\t" "addq $4 * 12 * 8, %%rax \n\t" // a += 4*12 (unroll x mr) "addq $4 * 4 * 8, %%rbx \n\t" // b += 4*4 (unroll x nr) " \n\t" " \n\t" "decq %%rsi \n\t" // i -= 1; "jne .DLOOPKITER \n\t" // iterate again if i != 0. " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" ".DCONSIDKLEFT: \n\t" " \n\t" "movq %1, %%rsi \n\t" // i = k_left; "testq %%rsi, %%rsi \n\t" // check i via logical AND. "je .DPOSTACCUM \n\t" // if i == 0, we're done; jump to end. " \n\t" // else, we prepare to enter k_left loop. " \n\t" " \n\t" ".DLOOPKLEFT: \n\t" // EDGE LOOP " \n\t" "prefetcht0 16 * 32(%%rax) \n\t" " \n\t" "vbroadcastsd 0 * 8(%%rbx), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm4 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm5 \n\t" "vfmadd231pd %%ymm2, %%ymm3, %%ymm6 \n\t" " \n\t" "vbroadcastsd 1 * 8(%%rbx), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm7 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm8 \n\t" "vfmadd231pd %%ymm2, %%ymm3, %%ymm9 \n\t" " \n\t" "vbroadcastsd 2 * 8(%%rbx), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm10 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm11 \n\t" "vfmadd231pd %%ymm2, %%ymm3, %%ymm12 \n\t" " \n\t" "vbroadcastsd 3 * 8(%%rbx), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm13 \n\t" "vmovapd 3 * 32(%%rax), %%ymm0 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm14 \n\t" "vmovapd 4 * 32(%%rax), %%ymm1 \n\t" "vfmadd231pd %%ymm2, %%ymm3, %%ymm15 \n\t" "vmovapd 5 * 32(%%rax), %%ymm2 \n\t" " \n\t" " \n\t" " \n\t" "addq $1 * 12 * 8, %%rax \n\t" // a += 1*12 (unroll x mr) "addq $1 * 4 * 8, %%rbx \n\t" // b += 1*4 (unroll x nr) " \n\t" " \n\t" "decq %%rsi \n\t" // i -= 1; "jne .DLOOPKLEFT \n\t" // iterate again if i != 0. " \n\t" " \n\t" " \n\t" ".DPOSTACCUM: \n\t" " \n\t" " \n\t" " \n\t" " \n\t" "movq %4, %%rax \n\t" // load address of alpha "movq %5, %%rbx \n\t" // load address of beta "vbroadcastsd (%%rax), %%ymm0 \n\t" // load alpha and duplicate "vbroadcastsd (%%rbx), %%ymm3 \n\t" // load beta and duplicate " \n\t" "vmulpd %%ymm0, %%ymm4, %%ymm4 \n\t" // scale by alpha "vmulpd %%ymm0, %%ymm5, %%ymm5 \n\t" "vmulpd %%ymm0, %%ymm6, %%ymm6 \n\t" "vmulpd %%ymm0, %%ymm7, %%ymm7 \n\t" "vmulpd %%ymm0, %%ymm8, %%ymm8 \n\t" "vmulpd %%ymm0, %%ymm9, %%ymm9 \n\t" "vmulpd %%ymm0, %%ymm10, %%ymm10 \n\t" "vmulpd %%ymm0, %%ymm11, %%ymm11 \n\t" "vmulpd %%ymm0, %%ymm12, %%ymm12 \n\t" "vmulpd %%ymm0, %%ymm13, %%ymm13 \n\t" "vmulpd %%ymm0, %%ymm14, %%ymm14 \n\t" "vmulpd %%ymm0, %%ymm15, %%ymm15 \n\t" " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" "movq %7, %%rsi \n\t" // load rs_c "leaq (,%%rsi,8), %%rsi \n\t" // rsi = rs_c * sizeof(double) " \n\t" "leaq (%%rcx,%%rsi,4), %%rdx \n\t" // rdx = c + 4*rs_c; "leaq (%%rcx,%%rsi,8), %%r12 \n\t" // r12 = c + 8*rs_c; " \n\t" "leaq (%%rsi,%%rsi,2), %%r13 \n\t" // r13 = 3*rs_c; //"leaq (%%rsi,%%rsi,4), %%r15 \n\t" // r15 = 5*rs_c; //"leaq (%%r13,%%rsi,4), %%r10 \n\t" // r10 = 7*rs_c; " \n\t" " \n\t" " \n\t" " \n\t" // determine if " \n\t" // c % 32 == 0, AND " \n\t" // 8*cs_c % 32 == 0, AND " \n\t" // rs_c == 1 " \n\t" // ie: aligned, ldim aligned, and " \n\t" // column-stored " \n\t" "cmpq $8, %%rsi \n\t" // set ZF if (8*rs_c) == 8. "sete %%bl \n\t" // bl = ( ZF == 1 ? 1 : 0 ); "testq $31, %%rcx \n\t" // set ZF if c & 32 is zero. "setz %%bh \n\t" // bh = ( ZF == 0 ? 1 : 0 ); "testq $31, %%rdi \n\t" // set ZF if (8*cs_c) & 32 is zero. "setz %%al \n\t" // al = ( ZF == 0 ? 1 : 0 ); " \n\t" // and(bl,bh) followed by " \n\t" // and(bh,al) will reveal result " \n\t" " \n\t" // now avoid loading C if beta == 0 " \n\t" "vxorpd %%ymm0, %%ymm0, %%ymm0 \n\t" // set ymm0 to zero. "vucomisd %%xmm0, %%xmm3 \n\t" // set ZF if beta == 0. "je .DBETAZERO \n\t" // if ZF = 1, jump to beta == 0 case " \n\t" " \n\t" " \n\t" // check if aligned/column-stored "andb %%bl, %%bh \n\t" // set ZF if bl & bh == 1. "andb %%bh, %%al \n\t" // set ZF if bh & al == 1. "jne .DCOLSTORED \n\t" // jump to column storage case " \n\t" " \n\t" " \n\t" ".DGENSTORED: \n\t" " \n\t" " \n\t" DGEMM_INPUT_GS_BETA_NZ "vfmadd213pd %%ymm4, %%ymm3, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" DGEMM_INPUT_GS_BETA_NZ "vfmadd213pd %%ymm7, %%ymm3, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" DGEMM_INPUT_GS_BETA_NZ "vfmadd213pd %%ymm10, %%ymm3, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" DGEMM_INPUT_GS_BETA_NZ "vfmadd213pd %%ymm13, %%ymm3, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ //"addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" "movq %%rdx, %%rcx \n\t" // rcx = c + 4*rs_c " \n\t" " \n\t" DGEMM_INPUT_GS_BETA_NZ "vfmadd213pd %%ymm5, %%ymm3, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" DGEMM_INPUT_GS_BETA_NZ "vfmadd213pd %%ymm8, %%ymm3, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" DGEMM_INPUT_GS_BETA_NZ "vfmadd213pd %%ymm11, %%ymm3, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" DGEMM_INPUT_GS_BETA_NZ "vfmadd213pd %%ymm14, %%ymm3, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ //"addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" "movq %%r12, %%rcx \n\t" // rcx = c + 8*rs_c " \n\t" " \n\t" DGEMM_INPUT_GS_BETA_NZ "vfmadd213pd %%ymm6, %%ymm3, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" DGEMM_INPUT_GS_BETA_NZ "vfmadd213pd %%ymm9, %%ymm3, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" DGEMM_INPUT_GS_BETA_NZ "vfmadd213pd %%ymm12, %%ymm3, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" DGEMM_INPUT_GS_BETA_NZ "vfmadd213pd %%ymm15, %%ymm3, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ //"addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" "jmp .DDONE \n\t" // jump to end. " \n\t" " \n\t" " \n\t" ".DCOLSTORED: \n\t" " \n\t" " \n\t" "vmovapd (%%rcx), %%ymm0 \n\t" "vfmadd213pd %%ymm4, %%ymm3, %%ymm0 \n\t" "vmovapd %%ymm0, (%%rcx) \n\t" "addq %%rdi, %%rcx \n\t" "vmovapd (%%rdx), %%ymm1 \n\t" "vfmadd213pd %%ymm5, %%ymm3, %%ymm1 \n\t" "vmovapd %%ymm1, (%%rdx) \n\t" "addq %%rdi, %%rdx \n\t" "vmovapd (%%r12), %%ymm2 \n\t" "vfmadd213pd %%ymm6, %%ymm3, %%ymm2 \n\t" "vmovapd %%ymm2, (%%r12) \n\t" "addq %%rdi, %%r12 \n\t" " \n\t" " \n\t" "vmovapd (%%rcx), %%ymm0 \n\t" "vfmadd213pd %%ymm7, %%ymm3, %%ymm0 \n\t" "vmovapd %%ymm0, (%%rcx) \n\t" "addq %%rdi, %%rcx \n\t" "vmovapd (%%rdx), %%ymm1 \n\t" "vfmadd213pd %%ymm8, %%ymm3, %%ymm1 \n\t" "vmovapd %%ymm1, (%%rdx) \n\t" "addq %%rdi, %%rdx \n\t" "vmovapd (%%r12), %%ymm2 \n\t" "vfmadd213pd %%ymm9, %%ymm3, %%ymm2 \n\t" "vmovapd %%ymm2, (%%r12) \n\t" "addq %%rdi, %%r12 \n\t" " \n\t" " \n\t" "vmovapd (%%rcx), %%ymm0 \n\t" "vfmadd213pd %%ymm10, %%ymm3, %%ymm0 \n\t" "vmovapd %%ymm0, (%%rcx) \n\t" "addq %%rdi, %%rcx \n\t" "vmovapd (%%rdx), %%ymm1 \n\t" "vfmadd213pd %%ymm11, %%ymm3, %%ymm1 \n\t" "vmovapd %%ymm1, (%%rdx) \n\t" "addq %%rdi, %%rdx \n\t" "vmovapd (%%r12), %%ymm2 \n\t" "vfmadd213pd %%ymm12, %%ymm3, %%ymm2 \n\t" "vmovapd %%ymm2, (%%r12) \n\t" "addq %%rdi, %%r12 \n\t" " \n\t" " \n\t" "vmovapd (%%rcx), %%ymm0 \n\t" "vfmadd213pd %%ymm13, %%ymm3, %%ymm0 \n\t" "vmovapd %%ymm0, (%%rcx) \n\t" "addq %%rdi, %%rcx \n\t" "vmovapd (%%rdx), %%ymm1 \n\t" "vfmadd213pd %%ymm14, %%ymm3, %%ymm1 \n\t" "vmovapd %%ymm1, (%%rdx) \n\t" "addq %%rdi, %%rdx \n\t" "vmovapd (%%r12), %%ymm2 \n\t" "vfmadd213pd %%ymm15, %%ymm3, %%ymm2 \n\t" "vmovapd %%ymm2, (%%r12) \n\t" "addq %%rdi, %%r12 \n\t" " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" "jmp .DDONE \n\t" // jump to end. " \n\t" " \n\t" " \n\t" ".DBETAZERO: \n\t" " \n\t" // check if aligned/column-stored "andb %%bl, %%bh \n\t" // set ZF if bl & bh == 1. "andb %%bh, %%al \n\t" // set ZF if bh & al == 1. "jne .DCOLSTORBZ \n\t" // jump to column storage case " \n\t" " \n\t" " \n\t" ".DGENSTORBZ: \n\t" " \n\t" " \n\t" "vmovapd %%ymm4, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" "vmovapd %%ymm7, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" "vmovapd %%ymm10, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" "vmovapd %%ymm13, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ //"addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" "movq %%rdx, %%rcx \n\t" // rcx = c + 4*rs_c " \n\t" " \n\t" "vmovapd %%ymm5, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" "vmovapd %%ymm8, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" "vmovapd %%ymm11, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" "vmovapd %%ymm14, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ //"addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" "movq %%r12, %%rcx \n\t" // rcx = c + 8*rs_c " \n\t" " \n\t" "vmovapd %%ymm6, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" "vmovapd %%ymm9, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" "vmovapd %%ymm12, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" "vmovapd %%ymm15, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ //"addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" "jmp .DDONE \n\t" // jump to end. " \n\t" " \n\t" " \n\t" ".DCOLSTORBZ: \n\t" " \n\t" " \n\t" "vmovapd %%ymm4, (%%rcx) \n\t" "addq %%rdi, %%rcx \n\t" "vmovapd %%ymm5, (%%rdx) \n\t" "addq %%rdi, %%rdx \n\t" "vmovapd %%ymm6, (%%r12) \n\t" "addq %%rdi, %%r12 \n\t" " \n\t" "vmovapd %%ymm7, (%%rcx) \n\t" "addq %%rdi, %%rcx \n\t" "vmovapd %%ymm8, (%%rdx) \n\t" "addq %%rdi, %%rdx \n\t" "vmovapd %%ymm9, (%%r12) \n\t" "addq %%rdi, %%r12 \n\t" " \n\t" "vmovapd %%ymm10, (%%rcx) \n\t" "addq %%rdi, %%rcx \n\t" "vmovapd %%ymm11, (%%rdx) \n\t" "addq %%rdi, %%rdx \n\t" "vmovapd %%ymm12, (%%r12) \n\t" "addq %%rdi, %%r12 \n\t" " \n\t" "vmovapd %%ymm13, (%%rcx) \n\t" //"addq %%rdi, %%rcx \n\t" "vmovapd %%ymm14, (%%rdx) \n\t" //"addq %%rdi, %%rdx \n\t" "vmovapd %%ymm15, (%%r12) \n\t" //"addq %%rdi, %%r12 \n\t" " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" ".DDONE: \n\t" " \n\t" "vzeroupper \n\t" " \n\t" : // output operands (none) : // input operands "m" (k_iter), // 0 "m" (k_left), // 1 "m" (a), // 2 "m" (b), // 3 "m" (alpha), // 4 "m" (beta), // 5 "m" (c), // 6 "m" (rs_c), // 7 "m" (cs_c)/*, // 8 "m" (b_next), // 9 "m" (a_next)*/ // 10 : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ); } #if 0 void bli_cgemm_haswell_asm_ ( dim_t k0, scomplex* restrict alpha, scomplex* restrict a, scomplex* restrict b, scomplex* restrict beta, scomplex* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; } void bli_zgemm_haswell_asm_ ( dim_t k0, dcomplex* restrict alpha, dcomplex* restrict a, dcomplex* restrict b, dcomplex* restrict beta, dcomplex* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; } #endif blis-0.9.0/kernels/haswell/3/old/bli_gemm_haswell_asm_d4x12.c000066400000000000000000001755501422157504600237360ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define SGEMM_INPUT_GS_BETA_NZ \ "vmovlps (%%rcx ), %%xmm0, %%xmm0 \n\t" \ "vmovhps (%%rcx,%%rsi,1), %%xmm0, %%xmm0 \n\t" \ "vmovlps (%%rcx,%%rsi,2), %%xmm1, %%xmm1 \n\t" \ "vmovhps (%%rcx,%%r13 ), %%xmm1, %%xmm1 \n\t" \ "vshufps $0x88, %%xmm1, %%xmm0, %%xmm0 \n\t" \ "vmovlps (%%rcx,%%rsi,4), %%xmm2, %%xmm2 \n\t" \ "vmovhps (%%rcx,%%r15 ), %%xmm2, %%xmm2 \n\t" \ /* We can't use vmovhps for loading the last element becauase that might result in reading beyond valid memory. (vmov[lh]psd load pairs of adjacent floats at a time.) So we need to use vmovss instead. But since we're limited to using ymm0 through ymm2 (ymm3 contains beta and ymm4 through ymm15 contain the microtile) and due to the way vmovss zeros out all bits above 31, we have to load element 7 before element 6. */ \ "vmovss (%%rcx,%%r10 ), %%xmm1 \n\t" \ "vpermilps $0xcf, %%xmm1, %%xmm1 \n\t" \ "vmovlps (%%rcx,%%r13,2), %%xmm1, %%xmm1 \n\t" \ /*"vmovhps (%%rcx,%%r10 ), %%xmm1, %%xmm1 \n\t"*/ \ "vshufps $0x88, %%xmm1, %%xmm2, %%xmm2 \n\t" \ "vperm2f128 $0x20, %%ymm2, %%ymm0, %%ymm0 \n\t" #define SGEMM_OUTPUT_GS_BETA_NZ \ "vextractf128 $1, %%ymm0, %%xmm2 \n\t" \ "vmovss %%xmm0, (%%rcx ) \n\t" \ "vpermilps $0x39, %%xmm0, %%xmm1 \n\t" \ "vmovss %%xmm1, (%%rcx,%%rsi,1) \n\t" \ "vpermilps $0x39, %%xmm1, %%xmm0 \n\t" \ "vmovss %%xmm0, (%%rcx,%%rsi,2) \n\t" \ "vpermilps $0x39, %%xmm0, %%xmm1 \n\t" \ "vmovss %%xmm1, (%%rcx,%%r13 ) \n\t" \ "vmovss %%xmm2, (%%rcx,%%rsi,4) \n\t" \ "vpermilps $0x39, %%xmm2, %%xmm1 \n\t" \ "vmovss %%xmm1, (%%rcx,%%r15 ) \n\t" \ "vpermilps $0x39, %%xmm1, %%xmm2 \n\t" \ "vmovss %%xmm2, (%%rcx,%%r13,2) \n\t" \ "vpermilps $0x39, %%xmm2, %%xmm1 \n\t" \ "vmovss %%xmm1, (%%rcx,%%r10 ) \n\t" void bli_sgemm_haswell_asm_4x24 ( dim_t k0, float* restrict alpha, float* restrict a, float* restrict b, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; __asm__ volatile ( " \n\t" "vzeroall \n\t" // zero all xmm/ymm registers. " \n\t" " \n\t" "movq %2, %%rax \n\t" // load address of a. "movq %3, %%rbx \n\t" // load address of b. //"movq %9, %%r15 \n\t" // load address of b_next. " \n\t" " \n\t" // initialize loop by pre-loading "vmovaps 0 * 32(%%rbx), %%ymm0 \n\t" "vmovaps 1 * 32(%%rbx), %%ymm1 \n\t" "vmovaps 2 * 32(%%rbx), %%ymm2 \n\t" " \n\t" "movq %6, %%rcx \n\t" // load address of c "movq %7, %%rdi \n\t" // load rs_c "leaq (,%%rdi,4), %%rdi \n\t" // rs_c *= sizeof(float) " \n\t" "leaq (%%rdi,%%rdi,2), %%r13 \n\t" // r13 = 3*rs_c; "prefetcht0 7 * 4(%%rcx) \n\t" // prefetch c + 0*rs_c "prefetcht0 7 * 4(%%rcx,%%rdi) \n\t" // prefetch c + 1*rs_c "prefetcht0 7 * 4(%%rcx,%%rdi,2) \n\t" // prefetch c + 2*rs_c "prefetcht0 7 * 4(%%rcx,%%r13) \n\t" // prefetch c + 3*rs_c " \n\t" " \n\t" " \n\t" " \n\t" "movq %0, %%rsi \n\t" // i = k_iter; "testq %%rsi, %%rsi \n\t" // check i via logical AND. "je .SCONSIDKLEFT \n\t" // if i == 0, jump to code that " \n\t" // contains the k_left loop. " \n\t" " \n\t" ".SLOOPKITER: \n\t" // MAIN LOOP " \n\t" " \n\t" " \n\t" // iteration 0 "prefetcht0 16 * 32(%%rax) \n\t" " \n\t" "vbroadcastss 0 * 4(%%rax), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm4 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm5 \n\t" "vfmadd231ps %%ymm2, %%ymm3, %%ymm6 \n\t" " \n\t" "vbroadcastss 1 * 4(%%rax), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm7 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm8 \n\t" "vfmadd231ps %%ymm2, %%ymm3, %%ymm9 \n\t" " \n\t" "vbroadcastss 2 * 4(%%rax), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm10 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm11 \n\t" "vfmadd231ps %%ymm2, %%ymm3, %%ymm12 \n\t" " \n\t" "vbroadcastss 3 * 4(%%rax), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm13 \n\t" "vmovaps 3 * 32(%%rbx), %%ymm0 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm14 \n\t" "vmovaps 4 * 32(%%rbx), %%ymm1 \n\t" "vfmadd231ps %%ymm2, %%ymm3, %%ymm15 \n\t" "vmovaps 5 * 32(%%rbx), %%ymm2 \n\t" " \n\t" " \n\t" " \n\t" " \n\t" // iteration 1 "vbroadcastss 4 * 4(%%rax), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm4 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm5 \n\t" "vfmadd231ps %%ymm2, %%ymm3, %%ymm6 \n\t" " \n\t" "vbroadcastss 5 * 4(%%rax), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm7 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm8 \n\t" "vfmadd231ps %%ymm2, %%ymm3, %%ymm9 \n\t" " \n\t" "vbroadcastss 6 * 4(%%rax), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm10 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm11 \n\t" "vfmadd231ps %%ymm2, %%ymm3, %%ymm12 \n\t" " \n\t" "vbroadcastss 7 * 4(%%rax), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm13 \n\t" "vmovaps 6 * 32(%%rbx), %%ymm0 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm14 \n\t" "vmovaps 7 * 32(%%rbx), %%ymm1 \n\t" "vfmadd231ps %%ymm2, %%ymm3, %%ymm15 \n\t" "vmovaps 8 * 32(%%rbx), %%ymm2 \n\t" " \n\t" " \n\t" " \n\t" " \n\t" // iteration 2 "prefetcht0 22 * 32(%%rax) \n\t" " \n\t" "vbroadcastss 8 * 4(%%rax), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm4 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm5 \n\t" "vfmadd231ps %%ymm2, %%ymm3, %%ymm6 \n\t" " \n\t" "vbroadcastss 9 * 4(%%rax), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm7 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm8 \n\t" "vfmadd231ps %%ymm2, %%ymm3, %%ymm9 \n\t" " \n\t" "vbroadcastss 10 * 4(%%rax), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm10 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm11 \n\t" "vfmadd231ps %%ymm2, %%ymm3, %%ymm12 \n\t" " \n\t" "vbroadcastss 11 * 4(%%rax), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm13 \n\t" "vmovaps 9 * 32(%%rbx), %%ymm0 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm14 \n\t" "vmovaps 10 * 32(%%rbx), %%ymm1 \n\t" "vfmadd231ps %%ymm2, %%ymm3, %%ymm15 \n\t" "vmovaps 11 * 32(%%rbx), %%ymm2 \n\t" " \n\t" " \n\t" " \n\t" " \n\t" // iteration 3 "vbroadcastss 12 * 4(%%rax), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm4 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm5 \n\t" "vfmadd231ps %%ymm2, %%ymm3, %%ymm6 \n\t" " \n\t" "vbroadcastss 13 * 4(%%rax), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm7 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm8 \n\t" "vfmadd231ps %%ymm2, %%ymm3, %%ymm9 \n\t" " \n\t" "vbroadcastss 14 * 4(%%rax), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm10 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm11 \n\t" "vfmadd231ps %%ymm2, %%ymm3, %%ymm12 \n\t" " \n\t" "vbroadcastss 15 * 4(%%rax), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm13 \n\t" "vmovaps 12 * 32(%%rbx), %%ymm0 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm14 \n\t" "vmovaps 13 * 32(%%rbx), %%ymm1 \n\t" "vfmadd231ps %%ymm2, %%ymm3, %%ymm15 \n\t" "vmovaps 14 * 32(%%rbx), %%ymm2 \n\t" " \n\t" " \n\t" " \n\t" "addq $4 * 4 * 4, %%rax \n\t" // a += 4*4 (unroll x mr) "addq $4 * 24 * 4, %%rbx \n\t" // b += 4*24 (unroll x nr) " \n\t" " \n\t" "decq %%rsi \n\t" // i -= 1; "jne .SLOOPKITER \n\t" // iterate again if i != 0. " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" ".SCONSIDKLEFT: \n\t" " \n\t" "movq %1, %%rsi \n\t" // i = k_left; "testq %%rsi, %%rsi \n\t" // check i via logical AND. "je .SPOSTACCUM \n\t" // if i == 0, we're done; jump to end. " \n\t" // else, we prepare to enter k_left loop. " \n\t" " \n\t" ".SLOOPKLEFT: \n\t" // EDGE LOOP " \n\t" "prefetcht0 16 * 32(%%rax) \n\t" " \n\t" "vbroadcastss 0 * 4(%%rax), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm4 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm5 \n\t" "vfmadd231ps %%ymm2, %%ymm3, %%ymm6 \n\t" " \n\t" "vbroadcastss 1 * 4(%%rax), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm7 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm8 \n\t" "vfmadd231ps %%ymm2, %%ymm3, %%ymm9 \n\t" " \n\t" "vbroadcastss 2 * 4(%%rax), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm10 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm11 \n\t" "vfmadd231ps %%ymm2, %%ymm3, %%ymm12 \n\t" " \n\t" "vbroadcastss 3 * 4(%%rax), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm13 \n\t" "vmovaps 3 * 32(%%rbx), %%ymm0 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm14 \n\t" "vmovaps 4 * 32(%%rbx), %%ymm1 \n\t" "vfmadd231ps %%ymm2, %%ymm3, %%ymm15 \n\t" "vmovaps 5 * 32(%%rbx), %%ymm2 \n\t" " \n\t" " \n\t" " \n\t" "addq $1 * 4 * 4, %%rax \n\t" // a += 1*4 (unroll x mr) "addq $1 * 24 * 4, %%rbx \n\t" // b += 1*24 (unroll x nr) " \n\t" " \n\t" "decq %%rsi \n\t" // i -= 1; "jne .SLOOPKLEFT \n\t" // iterate again if i != 0. " \n\t" " \n\t" " \n\t" ".SPOSTACCUM: \n\t" " \n\t" " \n\t" " \n\t" " \n\t" "movq %4, %%rax \n\t" // load address of alpha "movq %5, %%rbx \n\t" // load address of beta "vbroadcastss (%%rax), %%ymm0 \n\t" // load alpha and duplicate "vbroadcastss (%%rbx), %%ymm3 \n\t" // load beta and duplicate " \n\t" "vmulps %%ymm0, %%ymm4, %%ymm4 \n\t" // scale by alpha "vmulps %%ymm0, %%ymm5, %%ymm5 \n\t" "vmulps %%ymm0, %%ymm6, %%ymm6 \n\t" "vmulps %%ymm0, %%ymm7, %%ymm7 \n\t" "vmulps %%ymm0, %%ymm8, %%ymm8 \n\t" "vmulps %%ymm0, %%ymm9, %%ymm9 \n\t" "vmulps %%ymm0, %%ymm10, %%ymm10 \n\t" "vmulps %%ymm0, %%ymm11, %%ymm11 \n\t" "vmulps %%ymm0, %%ymm12, %%ymm12 \n\t" "vmulps %%ymm0, %%ymm13, %%ymm13 \n\t" "vmulps %%ymm0, %%ymm14, %%ymm14 \n\t" "vmulps %%ymm0, %%ymm15, %%ymm15 \n\t" " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" "movq %8, %%rsi \n\t" // load cs_c "leaq (,%%rsi,4), %%rsi \n\t" // rsi = cs_c * sizeof(float) " \n\t" "leaq (%%rcx,%%rsi,8), %%rdx \n\t" // rdx = c + 8*cs_c; "leaq (%%rdx,%%rsi,8), %%r12 \n\t" // r12 = c + 16*cs_c; " \n\t" "leaq (%%rsi,%%rsi,2), %%r13 \n\t" // r13 = 3*cs_c; "leaq (%%rsi,%%rsi,4), %%r15 \n\t" // r15 = 5*cs_c; "leaq (%%r13,%%rsi,4), %%r10 \n\t" // r10 = 7*cs_c; " \n\t" " \n\t" " \n\t" // now avoid loading C if beta == 0 " \n\t" "vxorps %%ymm0, %%ymm0, %%ymm0 \n\t" // set ymm0 to zero. "vucomiss %%xmm0, %%xmm3 \n\t" // set ZF if beta == 0. "je .SBETAZERO \n\t" // if ZF = 1, jump to beta == 0 case " \n\t" " \n\t" "cmpq $4, %%rsi \n\t" // set ZF if (4*cs_c) == 4. "jz .SROWSTORED \n\t" // jump to row storage case " \n\t" " \n\t" " \n\t" ".SGENSTORED: \n\t" " \n\t" " \n\t" SGEMM_INPUT_GS_BETA_NZ "vfmadd213ps %%ymm4, %%ymm3, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" SGEMM_INPUT_GS_BETA_NZ "vfmadd213ps %%ymm7, %%ymm3, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" SGEMM_INPUT_GS_BETA_NZ "vfmadd213ps %%ymm10, %%ymm3, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" SGEMM_INPUT_GS_BETA_NZ "vfmadd213ps %%ymm13, %%ymm3, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ //"addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" "movq %%rdx, %%rcx \n\t" // rcx = c + 8*cs_c " \n\t" " \n\t" SGEMM_INPUT_GS_BETA_NZ "vfmadd213ps %%ymm5, %%ymm3, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" SGEMM_INPUT_GS_BETA_NZ "vfmadd213ps %%ymm8, %%ymm3, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" SGEMM_INPUT_GS_BETA_NZ "vfmadd213ps %%ymm11, %%ymm3, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" SGEMM_INPUT_GS_BETA_NZ "vfmadd213ps %%ymm14, %%ymm3, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ //"addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" "movq %%r12, %%rcx \n\t" // rcx = c + 16*cs_c " \n\t" " \n\t" SGEMM_INPUT_GS_BETA_NZ "vfmadd213ps %%ymm6, %%ymm3, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" SGEMM_INPUT_GS_BETA_NZ "vfmadd213ps %%ymm9, %%ymm3, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" SGEMM_INPUT_GS_BETA_NZ "vfmadd213ps %%ymm12, %%ymm3, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" SGEMM_INPUT_GS_BETA_NZ "vfmadd213ps %%ymm15, %%ymm3, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ //"addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" "jmp .SDONE \n\t" // jump to end. " \n\t" " \n\t" " \n\t" ".SROWSTORED: \n\t" " \n\t" " \n\t" "vfmadd231ps (%%rcx), %%ymm3, %%ymm4 \n\t" "vmovups %%ymm4, (%%rcx) \n\t" "addq %%rdi, %%rcx \n\t" "vfmadd231ps (%%rdx), %%ymm3, %%ymm5 \n\t" "vmovups %%ymm5, (%%rdx) \n\t" "addq %%rdi, %%rdx \n\t" "vfmadd231ps (%%r12), %%ymm3, %%ymm6 \n\t" "vmovups %%ymm6, (%%r12) \n\t" "addq %%rdi, %%r12 \n\t" " \n\t" " \n\t" "vfmadd231ps (%%rcx), %%ymm3, %%ymm7 \n\t" "vmovups %%ymm7, (%%rcx) \n\t" "addq %%rdi, %%rcx \n\t" "vfmadd231ps (%%rdx), %%ymm3, %%ymm8 \n\t" "vmovups %%ymm8, (%%rdx) \n\t" "addq %%rdi, %%rdx \n\t" "vfmadd231ps (%%r12), %%ymm3, %%ymm9 \n\t" "vmovups %%ymm9, (%%r12) \n\t" "addq %%rdi, %%r12 \n\t" " \n\t" " \n\t" "vfmadd231ps (%%rcx), %%ymm3, %%ymm10 \n\t" "vmovups %%ymm10, (%%rcx) \n\t" "addq %%rdi, %%rcx \n\t" "vfmadd231ps (%%rdx), %%ymm3, %%ymm11 \n\t" "vmovups %%ymm11, (%%rdx) \n\t" "addq %%rdi, %%rdx \n\t" "vfmadd231ps (%%r12), %%ymm3, %%ymm12 \n\t" "vmovups %%ymm12, (%%r12) \n\t" "addq %%rdi, %%r12 \n\t" " \n\t" " \n\t" "vfmadd231ps (%%rcx), %%ymm3, %%ymm13 \n\t" "vmovups %%ymm13, (%%rcx) \n\t" //"addq %%rdi, %%rcx \n\t" "vfmadd231ps (%%rdx), %%ymm3, %%ymm14 \n\t" "vmovups %%ymm14, (%%rdx) \n\t" //"addq %%rdi, %%rdx \n\t" "vfmadd231ps (%%r12), %%ymm3, %%ymm15 \n\t" "vmovups %%ymm15, (%%r12) \n\t" //"addq %%rdi, %%r12 \n\t" " \n\t" " \n\t" " \n\t" "jmp .SDONE \n\t" // jump to end. " \n\t" " \n\t" " \n\t" ".SBETAZERO: \n\t" " \n\t" "cmpq $4, %%rsi \n\t" // set ZF if (4*cs_c) == 4. "jz .SROWSTORBZ \n\t" // jump to row storage case " \n\t" " \n\t" " \n\t" ".SGENSTORBZ: \n\t" " \n\t" " \n\t" "vmovaps %%ymm4, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" "vmovaps %%ymm7, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" "vmovaps %%ymm10, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" "vmovaps %%ymm13, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ //"addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" "movq %%rdx, %%rcx \n\t" // rcx = c + 8*cs_c " \n\t" " \n\t" "vmovaps %%ymm5, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" "vmovaps %%ymm8, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" "vmovaps %%ymm11, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" "vmovaps %%ymm14, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ //"addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" "movq %%r12, %%rcx \n\t" // rcx = c + 16*cs_c " \n\t" " \n\t" "vmovaps %%ymm6, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" "vmovaps %%ymm9, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" "vmovaps %%ymm12, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" "vmovaps %%ymm15, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ //"addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" "jmp .SDONE \n\t" // jump to end. " \n\t" " \n\t" " \n\t" ".SROWSTORBZ: \n\t" " \n\t" " \n\t" "vmovups %%ymm4, (%%rcx) \n\t" "addq %%rdi, %%rcx \n\t" "vmovups %%ymm5, (%%rdx) \n\t" "addq %%rdi, %%rdx \n\t" "vmovups %%ymm6, (%%r12) \n\t" "addq %%rdi, %%r12 \n\t" " \n\t" "vmovups %%ymm7, (%%rcx) \n\t" "addq %%rdi, %%rcx \n\t" "vmovups %%ymm8, (%%rdx) \n\t" "addq %%rdi, %%rdx \n\t" "vmovups %%ymm9, (%%r12) \n\t" "addq %%rdi, %%r12 \n\t" " \n\t" "vmovups %%ymm10, (%%rcx) \n\t" "addq %%rdi, %%rcx \n\t" "vmovups %%ymm11, (%%rdx) \n\t" "addq %%rdi, %%rdx \n\t" "vmovups %%ymm12, (%%r12) \n\t" "addq %%rdi, %%r12 \n\t" " \n\t" "vmovups %%ymm13, (%%rcx) \n\t" //"addq %%rdi, %%rcx \n\t" "vmovups %%ymm14, (%%rdx) \n\t" //"addq %%rdi, %%rdx \n\t" "vmovups %%ymm15, (%%r12) \n\t" //"addq %%rdi, %%r12 \n\t" " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" ".SDONE: \n\t" " \n\t" "vzeroupper \n\t" " \n\t" : // output operands (none) : // input operands "m" (k_iter), // 0 "m" (k_left), // 1 "m" (a), // 2 "m" (b), // 3 "m" (alpha), // 4 "m" (beta), // 5 "m" (c), // 6 "m" (rs_c), // 7 "m" (cs_c)/*, // 8 "m" (b_next), // 9 "m" (a_next)*/ // 10 : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ); } #define DGEMM_INPUT_GS_BETA_NZ \ "vmovlpd (%%rcx ), %%xmm0, %%xmm0 \n\t" \ "vmovhpd (%%rcx,%%rsi,1), %%xmm0, %%xmm0 \n\t" \ "vmovlpd (%%rcx,%%rsi,2), %%xmm1, %%xmm1 \n\t" \ "vmovhpd (%%rcx,%%r13 ), %%xmm1, %%xmm1 \n\t" \ "vperm2f128 $0x20, %%ymm1, %%ymm0, %%ymm0 \n\t" /*\ "vmovlps (%%rcx,%%rsi,4), %%xmm2, %%xmm2 \n\t" \ "vmovhps (%%rcx,%%r15 ), %%xmm2, %%xmm2 \n\t" \ "vmovlps (%%rcx,%%r13,2), %%xmm1, %%xmm1 \n\t" \ "vmovhps (%%rcx,%%r10 ), %%xmm1, %%xmm1 \n\t" \ "vperm2f128 $0x20, %%ymm1, %%ymm2, %%ymm2 \n\t"*/ #define DGEMM_OUTPUT_GS_BETA_NZ \ "vextractf128 $1, %%ymm0, %%xmm1 \n\t" \ "vmovlpd %%xmm0, (%%rcx ) \n\t" \ "vmovhpd %%xmm0, (%%rcx,%%rsi ) \n\t" \ "vmovlpd %%xmm1, (%%rcx,%%rsi,2) \n\t" \ "vmovhpd %%xmm1, (%%rcx,%%r13 ) \n\t" /*\ "vextractf128 $1, %%ymm2, %%xmm1 \n\t" \ "vmovlpd %%xmm2, (%%rcx,%%rsi,4) \n\t" \ "vmovhpd %%xmm2, (%%rcx,%%r15 ) \n\t" \ "vmovlpd %%xmm1, (%%rcx,%%r13,2) \n\t" \ "vmovhpd %%xmm1, (%%rcx,%%r10 ) \n\t"*/ void bli_dgemm_haswell_asm_4x12 ( dim_t k0, double* restrict alpha, double* restrict a, double* restrict b, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; __asm__ volatile ( " \n\t" "vzeroall \n\t" // zero all xmm/ymm registers. " \n\t" " \n\t" "movq %2, %%rax \n\t" // load address of a. "movq %3, %%rbx \n\t" // load address of b. //"movq %9, %%r15 \n\t" // load address of b_next. " \n\t" " \n\t" // initialize loop by pre-loading "vmovapd 0 * 32(%%rbx), %%ymm0 \n\t" "vmovapd 1 * 32(%%rbx), %%ymm1 \n\t" "vmovapd 2 * 32(%%rbx), %%ymm2 \n\t" " \n\t" "movq %6, %%rcx \n\t" // load address of c "movq %7, %%rdi \n\t" // load rs_c "leaq (,%%rdi,8), %%rdi \n\t" // rs_c *= sizeof(double) " \n\t" "leaq (%%rdi,%%rdi,2), %%r13 \n\t" // r13 = 3*rs_c; "prefetcht0 7 * 8(%%rcx) \n\t" // prefetch c + 0*rs_c "prefetcht0 7 * 8(%%rcx,%%rdi) \n\t" // prefetch c + 1*rs_c "prefetcht0 7 * 8(%%rcx,%%rdi,2) \n\t" // prefetch c + 2*rs_c "prefetcht0 7 * 8(%%rcx,%%r13) \n\t" // prefetch c + 3*rs_c " \n\t" " \n\t" " \n\t" " \n\t" "movq %0, %%rsi \n\t" // i = k_iter; "testq %%rsi, %%rsi \n\t" // check i via logical AND. "je .DCONSIDKLEFT \n\t" // if i == 0, jump to code that " \n\t" // contains the k_left loop. " \n\t" " \n\t" ".DLOOPKITER: \n\t" // MAIN LOOP " \n\t" " \n\t" " \n\t" // iteration 0 "prefetcht0 16 * 32(%%rax) \n\t" " \n\t" "vbroadcastsd 0 * 8(%%rax), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm4 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm5 \n\t" "vfmadd231pd %%ymm2, %%ymm3, %%ymm6 \n\t" " \n\t" "vbroadcastsd 1 * 8(%%rax), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm7 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm8 \n\t" "vfmadd231pd %%ymm2, %%ymm3, %%ymm9 \n\t" " \n\t" "vbroadcastsd 2 * 8(%%rax), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm10 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm11 \n\t" "vfmadd231pd %%ymm2, %%ymm3, %%ymm12 \n\t" " \n\t" "vbroadcastsd 3 * 8(%%rax), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm13 \n\t" "vmovapd 3 * 32(%%rbx), %%ymm0 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm14 \n\t" "vmovapd 4 * 32(%%rbx), %%ymm1 \n\t" "vfmadd231pd %%ymm2, %%ymm3, %%ymm15 \n\t" "vmovapd 5 * 32(%%rbx), %%ymm2 \n\t" " \n\t" " \n\t" " \n\t" " \n\t" // iteration 1 "vbroadcastsd 4 * 8(%%rax), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm4 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm5 \n\t" "vfmadd231pd %%ymm2, %%ymm3, %%ymm6 \n\t" " \n\t" "vbroadcastsd 5 * 8(%%rax), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm7 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm8 \n\t" "vfmadd231pd %%ymm2, %%ymm3, %%ymm9 \n\t" " \n\t" "vbroadcastsd 6 * 8(%%rax), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm10 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm11 \n\t" "vfmadd231pd %%ymm2, %%ymm3, %%ymm12 \n\t" " \n\t" "vbroadcastsd 7 * 8(%%rax), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm13 \n\t" "vmovapd 6 * 32(%%rbx), %%ymm0 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm14 \n\t" "vmovapd 7 * 32(%%rbx), %%ymm1 \n\t" "vfmadd231pd %%ymm2, %%ymm3, %%ymm15 \n\t" "vmovapd 8 * 32(%%rbx), %%ymm2 \n\t" " \n\t" " \n\t" " \n\t" " \n\t" // iteration 2 "prefetcht0 22 * 32(%%rax) \n\t" " \n\t" "vbroadcastsd 8 * 8(%%rax), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm4 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm5 \n\t" "vfmadd231pd %%ymm2, %%ymm3, %%ymm6 \n\t" " \n\t" "vbroadcastsd 9 * 8(%%rax), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm7 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm8 \n\t" "vfmadd231pd %%ymm2, %%ymm3, %%ymm9 \n\t" " \n\t" "vbroadcastsd 10 * 8(%%rax), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm10 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm11 \n\t" "vfmadd231pd %%ymm2, %%ymm3, %%ymm12 \n\t" " \n\t" "vbroadcastsd 11 * 8(%%rax), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm13 \n\t" "vmovapd 9 * 32(%%rbx), %%ymm0 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm14 \n\t" "vmovapd 10 * 32(%%rbx), %%ymm1 \n\t" "vfmadd231pd %%ymm2, %%ymm3, %%ymm15 \n\t" "vmovapd 11 * 32(%%rbx), %%ymm2 \n\t" " \n\t" " \n\t" " \n\t" " \n\t" // iteration 3 "vbroadcastsd 12 * 8(%%rax), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm4 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm5 \n\t" "vfmadd231pd %%ymm2, %%ymm3, %%ymm6 \n\t" " \n\t" "vbroadcastsd 13 * 8(%%rax), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm7 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm8 \n\t" "vfmadd231pd %%ymm2, %%ymm3, %%ymm9 \n\t" " \n\t" "vbroadcastsd 14 * 8(%%rax), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm10 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm11 \n\t" "vfmadd231pd %%ymm2, %%ymm3, %%ymm12 \n\t" " \n\t" "vbroadcastsd 15 * 8(%%rax), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm13 \n\t" "vmovapd 12 * 32(%%rbx), %%ymm0 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm14 \n\t" "vmovapd 13 * 32(%%rbx), %%ymm1 \n\t" "vfmadd231pd %%ymm2, %%ymm3, %%ymm15 \n\t" "vmovapd 14 * 32(%%rbx), %%ymm2 \n\t" " \n\t" " \n\t" " \n\t" "addq $4 * 4 * 8, %%rax \n\t" // a += 4*4 (unroll x mr) "addq $4 * 12 * 8, %%rbx \n\t" // b += 4*12 (unroll x nr) " \n\t" " \n\t" "decq %%rsi \n\t" // i -= 1; "jne .DLOOPKITER \n\t" // iterate again if i != 0. " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" ".DCONSIDKLEFT: \n\t" " \n\t" "movq %1, %%rsi \n\t" // i = k_left; "testq %%rsi, %%rsi \n\t" // check i via logical AND. "je .DPOSTACCUM \n\t" // if i == 0, we're done; jump to end. " \n\t" // else, we prepare to enter k_left loop. " \n\t" " \n\t" ".DLOOPKLEFT: \n\t" // EDGE LOOP " \n\t" "prefetcht0 16 * 32(%%rax) \n\t" " \n\t" "vbroadcastsd 0 * 8(%%rax), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm4 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm5 \n\t" "vfmadd231pd %%ymm2, %%ymm3, %%ymm6 \n\t" " \n\t" "vbroadcastsd 1 * 8(%%rax), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm7 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm8 \n\t" "vfmadd231pd %%ymm2, %%ymm3, %%ymm9 \n\t" " \n\t" "vbroadcastsd 2 * 8(%%rax), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm10 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm11 \n\t" "vfmadd231pd %%ymm2, %%ymm3, %%ymm12 \n\t" " \n\t" "vbroadcastsd 3 * 8(%%rax), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm13 \n\t" "vmovapd 3 * 32(%%rbx), %%ymm0 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm14 \n\t" "vmovapd 4 * 32(%%rbx), %%ymm1 \n\t" "vfmadd231pd %%ymm2, %%ymm3, %%ymm15 \n\t" "vmovapd 5 * 32(%%rbx), %%ymm2 \n\t" " \n\t" " \n\t" " \n\t" "addq $1 * 4 * 8, %%rax \n\t" // a += 1*4 (unroll x mr) "addq $1 * 12 * 8, %%rbx \n\t" // b += 1*12 (unroll x nr) " \n\t" " \n\t" "decq %%rsi \n\t" // i -= 1; "jne .DLOOPKLEFT \n\t" // iterate again if i != 0. " \n\t" " \n\t" " \n\t" ".DPOSTACCUM: \n\t" " \n\t" " \n\t" " \n\t" " \n\t" "movq %4, %%rax \n\t" // load address of alpha "movq %5, %%rbx \n\t" // load address of beta "vbroadcastsd (%%rax), %%ymm0 \n\t" // load alpha and duplicate "vbroadcastsd (%%rbx), %%ymm3 \n\t" // load beta and duplicate " \n\t" "vmulpd %%ymm0, %%ymm4, %%ymm4 \n\t" // scale by alpha "vmulpd %%ymm0, %%ymm5, %%ymm5 \n\t" "vmulpd %%ymm0, %%ymm6, %%ymm6 \n\t" "vmulpd %%ymm0, %%ymm7, %%ymm7 \n\t" "vmulpd %%ymm0, %%ymm8, %%ymm8 \n\t" "vmulpd %%ymm0, %%ymm9, %%ymm9 \n\t" "vmulpd %%ymm0, %%ymm10, %%ymm10 \n\t" "vmulpd %%ymm0, %%ymm11, %%ymm11 \n\t" "vmulpd %%ymm0, %%ymm12, %%ymm12 \n\t" "vmulpd %%ymm0, %%ymm13, %%ymm13 \n\t" "vmulpd %%ymm0, %%ymm14, %%ymm14 \n\t" "vmulpd %%ymm0, %%ymm15, %%ymm15 \n\t" " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" "movq %8, %%rsi \n\t" // load cs_c "leaq (,%%rsi,8), %%rsi \n\t" // rsi = cs_c * sizeof(double) " \n\t" "leaq (%%rcx,%%rsi,4), %%rdx \n\t" // rdx = c + 4*cs_c; "leaq (%%rcx,%%rsi,8), %%r12 \n\t" // r12 = c + 8*cs_c; " \n\t" "leaq (%%rsi,%%rsi,2), %%r13 \n\t" // r13 = 3*cs_c; //"leaq (%%rsi,%%rsi,4), %%r15 \n\t" // r15 = 5*cs_c; //"leaq (%%r13,%%rsi,4), %%r10 \n\t" // r10 = 7*cs_c; " \n\t" " \n\t" " \n\t" " \n\t" // now avoid loading C if beta == 0 " \n\t" "vxorpd %%ymm0, %%ymm0, %%ymm0 \n\t" // set ymm0 to zero. "vucomisd %%xmm0, %%xmm3 \n\t" // set ZF if beta == 0. "je .DBETAZERO \n\t" // if ZF = 1, jump to beta == 0 case " \n\t" " \n\t" "cmpq $8, %%rsi \n\t" // set ZF if (8*cs_c) == 8. "jz .DROWSTORED \n\t" // jump to row storage case " \n\t" " \n\t" " \n\t" ".DGENSTORED: \n\t" " \n\t" " \n\t" DGEMM_INPUT_GS_BETA_NZ "vfmadd213pd %%ymm4, %%ymm3, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" DGEMM_INPUT_GS_BETA_NZ "vfmadd213pd %%ymm7, %%ymm3, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" DGEMM_INPUT_GS_BETA_NZ "vfmadd213pd %%ymm10, %%ymm3, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" DGEMM_INPUT_GS_BETA_NZ "vfmadd213pd %%ymm13, %%ymm3, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ //"addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" "movq %%rdx, %%rcx \n\t" // rcx = c + 4*cs_c " \n\t" " \n\t" DGEMM_INPUT_GS_BETA_NZ "vfmadd213pd %%ymm5, %%ymm3, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" DGEMM_INPUT_GS_BETA_NZ "vfmadd213pd %%ymm8, %%ymm3, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" DGEMM_INPUT_GS_BETA_NZ "vfmadd213pd %%ymm11, %%ymm3, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" DGEMM_INPUT_GS_BETA_NZ "vfmadd213pd %%ymm14, %%ymm3, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ //"addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" "movq %%r12, %%rcx \n\t" // rcx = c + 8*cs_c " \n\t" " \n\t" DGEMM_INPUT_GS_BETA_NZ "vfmadd213pd %%ymm6, %%ymm3, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" DGEMM_INPUT_GS_BETA_NZ "vfmadd213pd %%ymm9, %%ymm3, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" DGEMM_INPUT_GS_BETA_NZ "vfmadd213pd %%ymm12, %%ymm3, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" DGEMM_INPUT_GS_BETA_NZ "vfmadd213pd %%ymm15, %%ymm3, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ //"addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" "jmp .DDONE \n\t" // jump to end. " \n\t" " \n\t" " \n\t" ".DROWSTORED: \n\t" " \n\t" " \n\t" "vfmadd231pd (%%rcx), %%ymm3, %%ymm4 \n\t" "vmovupd %%ymm4, (%%rcx) \n\t" "addq %%rdi, %%rcx \n\t" "vfmadd231pd (%%rdx), %%ymm3, %%ymm5 \n\t" "vmovupd %%ymm5, (%%rdx) \n\t" "addq %%rdi, %%rdx \n\t" "vfmadd231pd (%%r12), %%ymm3, %%ymm6 \n\t" "vmovupd %%ymm6, (%%r12) \n\t" "addq %%rdi, %%r12 \n\t" " \n\t" " \n\t" "vfmadd231pd (%%rcx), %%ymm3, %%ymm7 \n\t" "vmovupd %%ymm7, (%%rcx) \n\t" "addq %%rdi, %%rcx \n\t" "vfmadd231pd (%%rdx), %%ymm3, %%ymm8 \n\t" "vmovupd %%ymm8, (%%rdx) \n\t" "addq %%rdi, %%rdx \n\t" "vfmadd231pd (%%r12), %%ymm3, %%ymm9 \n\t" "vmovupd %%ymm9, (%%r12) \n\t" "addq %%rdi, %%r12 \n\t" " \n\t" " \n\t" "vfmadd231pd (%%rcx), %%ymm3, %%ymm10 \n\t" "vmovupd %%ymm10, (%%rcx) \n\t" "addq %%rdi, %%rcx \n\t" "vfmadd231pd (%%rdx), %%ymm3, %%ymm11 \n\t" "vmovupd %%ymm11, (%%rdx) \n\t" "addq %%rdi, %%rdx \n\t" "vfmadd231pd (%%r12), %%ymm3, %%ymm12 \n\t" "vmovupd %%ymm12, (%%r12) \n\t" "addq %%rdi, %%r12 \n\t" " \n\t" " \n\t" "vfmadd231pd (%%rcx), %%ymm3, %%ymm13 \n\t" "vmovupd %%ymm13, (%%rcx) \n\t" //"addq %%rdi, %%rcx \n\t" "vfmadd231pd (%%rdx), %%ymm3, %%ymm14 \n\t" "vmovupd %%ymm14, (%%rdx) \n\t" //"addq %%rdi, %%rdx \n\t" "vfmadd231pd (%%r12), %%ymm3, %%ymm15 \n\t" "vmovupd %%ymm15, (%%r12) \n\t" //"addq %%rdi, %%r12 \n\t" " \n\t" " \n\t" " \n\t" "jmp .DDONE \n\t" // jump to end. " \n\t" " \n\t" " \n\t" ".DBETAZERO: \n\t" " \n\t" // check if aligned/column-stored "cmpq $8, %%rsi \n\t" // set ZF if (8*cs_c) == 8. "jz .DROWSTORBZ \n\t" // jump to row storage case " \n\t" " \n\t" " \n\t" ".DGENSTORBZ: \n\t" " \n\t" " \n\t" "vmovapd %%ymm4, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" "vmovapd %%ymm7, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" "vmovapd %%ymm10, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" "vmovapd %%ymm13, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ //"addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" "movq %%rdx, %%rcx \n\t" // rcx = c + 4*cs_c " \n\t" " \n\t" "vmovapd %%ymm5, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" "vmovapd %%ymm8, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" "vmovapd %%ymm11, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" "vmovapd %%ymm14, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ //"addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" "movq %%r12, %%rcx \n\t" // rcx = c + 8*cs_c " \n\t" " \n\t" "vmovapd %%ymm6, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" "vmovapd %%ymm9, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" "vmovapd %%ymm12, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" "vmovapd %%ymm15, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ //"addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" "jmp .DDONE \n\t" // jump to end. " \n\t" " \n\t" " \n\t" ".DROWSTORBZ: \n\t" " \n\t" " \n\t" "vmovupd %%ymm4, (%%rcx) \n\t" "addq %%rdi, %%rcx \n\t" "vmovupd %%ymm5, (%%rdx) \n\t" "addq %%rdi, %%rdx \n\t" "vmovupd %%ymm6, (%%r12) \n\t" "addq %%rdi, %%r12 \n\t" " \n\t" "vmovupd %%ymm7, (%%rcx) \n\t" "addq %%rdi, %%rcx \n\t" "vmovupd %%ymm8, (%%rdx) \n\t" "addq %%rdi, %%rdx \n\t" "vmovupd %%ymm9, (%%r12) \n\t" "addq %%rdi, %%r12 \n\t" " \n\t" "vmovupd %%ymm10, (%%rcx) \n\t" "addq %%rdi, %%rcx \n\t" "vmovupd %%ymm11, (%%rdx) \n\t" "addq %%rdi, %%rdx \n\t" "vmovupd %%ymm12, (%%r12) \n\t" "addq %%rdi, %%r12 \n\t" " \n\t" "vmovupd %%ymm13, (%%rcx) \n\t" //"addq %%rdi, %%rcx \n\t" "vmovupd %%ymm14, (%%rdx) \n\t" //"addq %%rdi, %%rdx \n\t" "vmovupd %%ymm15, (%%r12) \n\t" //"addq %%rdi, %%r12 \n\t" " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" ".DDONE: \n\t" " \n\t" "vzeroupper \n\t" " \n\t" : // output operands (none) : // input operands "m" (k_iter), // 0 "m" (k_left), // 1 "m" (a), // 2 "m" (b), // 3 "m" (alpha), // 4 "m" (beta), // 5 "m" (c), // 6 "m" (rs_c), // 7 "m" (cs_c)/*, // 8 "m" (b_next), // 9 "m" (a_next)*/ // 10 : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ); } #if 0 void bli_cgemm_haswell_asm_ ( dim_t k0, scomplex* restrict alpha, scomplex* restrict a, scomplex* restrict b, scomplex* restrict beta, scomplex* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; } void bli_zgemm_haswell_asm_ ( dim_t k0, dcomplex* restrict alpha, dcomplex* restrict a, dcomplex* restrict b, dcomplex* restrict beta, dcomplex* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; } #endif blis-0.9.0/kernels/haswell/3/old/bli_gemm_haswell_asm_d6x8.c000066400000000000000000003420721422157504600236600ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define SGEMM_INPUT_GS_BETA_NZ \ "vmovlps (%%rcx ), %%xmm0, %%xmm0 \n\t" \ "vmovhps (%%rcx,%%rsi,1), %%xmm0, %%xmm0 \n\t" \ "vmovlps (%%rcx,%%rsi,2), %%xmm1, %%xmm1 \n\t" \ "vmovhps (%%rcx,%%r13 ), %%xmm1, %%xmm1 \n\t" \ "vshufps $0x88, %%xmm1, %%xmm0, %%xmm0 \n\t" \ "vmovlps (%%rcx,%%rsi,4), %%xmm2, %%xmm2 \n\t" \ "vmovhps (%%rcx,%%r15 ), %%xmm2, %%xmm2 \n\t" \ /* We can't use vmovhps for loading the last element becauase that might result in reading beyond valid memory. (vmov[lh]psd load pairs of adjacent floats at a time.) So we need to use vmovss instead. But since we're limited to using ymm0 through ymm2 (ymm3 contains beta and ymm4 through ymm15 contain the microtile) and due to the way vmovss zeros out all bits above 31, we have to load element 7 before element 6. */ \ "vmovss (%%rcx,%%r10 ), %%xmm1 \n\t" \ "vpermilps $0xcf, %%xmm1, %%xmm1 \n\t" \ "vmovlps (%%rcx,%%r13,2), %%xmm1, %%xmm1 \n\t" \ /*"vmovhps (%%rcx,%%r10 ), %%xmm1, %%xmm1 \n\t"*/ \ "vshufps $0x88, %%xmm1, %%xmm2, %%xmm2 \n\t" \ "vperm2f128 $0x20, %%ymm2, %%ymm0, %%ymm0 \n\t" #define SGEMM_OUTPUT_GS_BETA_NZ \ "vextractf128 $1, %%ymm0, %%xmm2 \n\t" \ "vmovss %%xmm0, (%%rcx ) \n\t" \ "vpermilps $0x39, %%xmm0, %%xmm1 \n\t" \ "vmovss %%xmm1, (%%rcx,%%rsi,1) \n\t" \ "vpermilps $0x39, %%xmm1, %%xmm0 \n\t" \ "vmovss %%xmm0, (%%rcx,%%rsi,2) \n\t" \ "vpermilps $0x39, %%xmm0, %%xmm1 \n\t" \ "vmovss %%xmm1, (%%rcx,%%r13 ) \n\t" \ "vmovss %%xmm2, (%%rcx,%%rsi,4) \n\t" \ "vpermilps $0x39, %%xmm2, %%xmm1 \n\t" \ "vmovss %%xmm1, (%%rcx,%%r15 ) \n\t" \ "vpermilps $0x39, %%xmm1, %%xmm2 \n\t" \ "vmovss %%xmm2, (%%rcx,%%r13,2) \n\t" \ "vpermilps $0x39, %%xmm2, %%xmm1 \n\t" \ "vmovss %%xmm1, (%%rcx,%%r10 ) \n\t" void bli_sgemm_haswell_asm_6x16 ( dim_t k0, float* restrict alpha, float* restrict a, float* restrict b, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; __asm__ volatile ( " \n\t" "vzeroall \n\t" // zero all xmm/ymm registers. " \n\t" " \n\t" "movq %2, %%rax \n\t" // load address of a. "movq %3, %%rbx \n\t" // load address of b. //"movq %9, %%r15 \n\t" // load address of b_next. " \n\t" "addq $32 * 4, %%rbx \n\t" " \n\t" // initialize loop by pre-loading "vmovaps -4 * 32(%%rbx), %%ymm0 \n\t" "vmovaps -3 * 32(%%rbx), %%ymm1 \n\t" " \n\t" "movq %6, %%rcx \n\t" // load address of c "movq %7, %%rdi \n\t" // load rs_c "leaq (,%%rdi,4), %%rdi \n\t" // rs_c *= sizeof(float) " \n\t" "leaq (%%rdi,%%rdi,2), %%r13 \n\t" // r13 = 3*rs_c; "leaq (%%rcx,%%r13,1), %%rdx \n\t" // rdx = c + 3*rs_c; "prefetcht0 7 * 8(%%rcx) \n\t" // prefetch c + 0*rs_c "prefetcht0 7 * 8(%%rcx,%%rdi) \n\t" // prefetch c + 1*rs_c "prefetcht0 7 * 8(%%rcx,%%rdi,2) \n\t" // prefetch c + 2*rs_c "prefetcht0 7 * 8(%%rdx) \n\t" // prefetch c + 3*rs_c "prefetcht0 7 * 8(%%rdx,%%rdi) \n\t" // prefetch c + 4*rs_c "prefetcht0 7 * 8(%%rdx,%%rdi,2) \n\t" // prefetch c + 5*rs_c " \n\t" " \n\t" " \n\t" " \n\t" "movq %0, %%rsi \n\t" // i = k_iter; "testq %%rsi, %%rsi \n\t" // check i via logical AND. "je .SCONSIDKLEFT \n\t" // if i == 0, jump to code that " \n\t" // contains the k_left loop. " \n\t" " \n\t" ".SLOOPKITER: \n\t" // MAIN LOOP " \n\t" " \n\t" " \n\t" // iteration 0 "prefetcht0 64 * 4(%%rax) \n\t" " \n\t" "vbroadcastss 0 * 4(%%rax), %%ymm2 \n\t" "vbroadcastss 1 * 4(%%rax), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm2, %%ymm4 \n\t" "vfmadd231ps %%ymm1, %%ymm2, %%ymm5 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm6 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm7 \n\t" " \n\t" "vbroadcastss 2 * 4(%%rax), %%ymm2 \n\t" "vbroadcastss 3 * 4(%%rax), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm2, %%ymm8 \n\t" "vfmadd231ps %%ymm1, %%ymm2, %%ymm9 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm10 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm11 \n\t" " \n\t" "vbroadcastss 4 * 4(%%rax), %%ymm2 \n\t" "vbroadcastss 5 * 4(%%rax), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm2, %%ymm12 \n\t" "vfmadd231ps %%ymm1, %%ymm2, %%ymm13 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm14 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm15 \n\t" " \n\t" "vmovaps -2 * 32(%%rbx), %%ymm0 \n\t" "vmovaps -1 * 32(%%rbx), %%ymm1 \n\t" " \n\t" " \n\t" // iteration 1 "vbroadcastss 6 * 4(%%rax), %%ymm2 \n\t" "vbroadcastss 7 * 4(%%rax), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm2, %%ymm4 \n\t" "vfmadd231ps %%ymm1, %%ymm2, %%ymm5 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm6 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm7 \n\t" " \n\t" "vbroadcastss 8 * 4(%%rax), %%ymm2 \n\t" "vbroadcastss 9 * 4(%%rax), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm2, %%ymm8 \n\t" "vfmadd231ps %%ymm1, %%ymm2, %%ymm9 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm10 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm11 \n\t" " \n\t" "vbroadcastss 10 * 4(%%rax), %%ymm2 \n\t" "vbroadcastss 11 * 4(%%rax), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm2, %%ymm12 \n\t" "vfmadd231ps %%ymm1, %%ymm2, %%ymm13 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm14 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm15 \n\t" " \n\t" "vmovaps 0 * 32(%%rbx), %%ymm0 \n\t" "vmovaps 1 * 32(%%rbx), %%ymm1 \n\t" " \n\t" " \n\t" // iteration 2 "prefetcht0 76 * 4(%%rax) \n\t" " \n\t" "vbroadcastss 12 * 4(%%rax), %%ymm2 \n\t" "vbroadcastss 13 * 4(%%rax), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm2, %%ymm4 \n\t" "vfmadd231ps %%ymm1, %%ymm2, %%ymm5 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm6 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm7 \n\t" " \n\t" "vbroadcastss 14 * 4(%%rax), %%ymm2 \n\t" "vbroadcastss 15 * 4(%%rax), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm2, %%ymm8 \n\t" "vfmadd231ps %%ymm1, %%ymm2, %%ymm9 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm10 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm11 \n\t" " \n\t" "vbroadcastss 16 * 4(%%rax), %%ymm2 \n\t" "vbroadcastss 17 * 4(%%rax), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm2, %%ymm12 \n\t" "vfmadd231ps %%ymm1, %%ymm2, %%ymm13 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm14 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm15 \n\t" " \n\t" "vmovaps 2 * 32(%%rbx), %%ymm0 \n\t" "vmovaps 3 * 32(%%rbx), %%ymm1 \n\t" " \n\t" " \n\t" // iteration 3 "vbroadcastss 18 * 4(%%rax), %%ymm2 \n\t" "vbroadcastss 19 * 4(%%rax), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm2, %%ymm4 \n\t" "vfmadd231ps %%ymm1, %%ymm2, %%ymm5 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm6 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm7 \n\t" " \n\t" "vbroadcastss 20 * 4(%%rax), %%ymm2 \n\t" "vbroadcastss 21 * 4(%%rax), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm2, %%ymm8 \n\t" "vfmadd231ps %%ymm1, %%ymm2, %%ymm9 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm10 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm11 \n\t" " \n\t" "vbroadcastss 22 * 4(%%rax), %%ymm2 \n\t" "vbroadcastss 23 * 4(%%rax), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm2, %%ymm12 \n\t" "vfmadd231ps %%ymm1, %%ymm2, %%ymm13 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm14 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm15 \n\t" " \n\t" "addq $4 * 6 * 4, %%rax \n\t" // a += 4*6 (unroll x mr) "addq $4 * 16 * 4, %%rbx \n\t" // b += 4*16 (unroll x nr) " \n\t" "vmovaps -4 * 32(%%rbx), %%ymm0 \n\t" "vmovaps -3 * 32(%%rbx), %%ymm1 \n\t" " \n\t" " \n\t" "decq %%rsi \n\t" // i -= 1; "jne .SLOOPKITER \n\t" // iterate again if i != 0. " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" ".SCONSIDKLEFT: \n\t" " \n\t" "movq %1, %%rsi \n\t" // i = k_left; "testq %%rsi, %%rsi \n\t" // check i via logical AND. "je .SPOSTACCUM \n\t" // if i == 0, we're done; jump to end. " \n\t" // else, we prepare to enter k_left loop. " \n\t" " \n\t" ".SLOOPKLEFT: \n\t" // EDGE LOOP " \n\t" "prefetcht0 64 * 4(%%rax) \n\t" " \n\t" "vbroadcastss 0 * 4(%%rax), %%ymm2 \n\t" "vbroadcastss 1 * 4(%%rax), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm2, %%ymm4 \n\t" "vfmadd231ps %%ymm1, %%ymm2, %%ymm5 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm6 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm7 \n\t" " \n\t" "vbroadcastss 2 * 4(%%rax), %%ymm2 \n\t" "vbroadcastss 3 * 4(%%rax), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm2, %%ymm8 \n\t" "vfmadd231ps %%ymm1, %%ymm2, %%ymm9 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm10 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm11 \n\t" " \n\t" "vbroadcastss 4 * 4(%%rax), %%ymm2 \n\t" "vbroadcastss 5 * 4(%%rax), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm2, %%ymm12 \n\t" "vfmadd231ps %%ymm1, %%ymm2, %%ymm13 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm14 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm15 \n\t" " \n\t" "addq $1 * 6 * 4, %%rax \n\t" // a += 1*6 (unroll x mr) "addq $1 * 16 * 4, %%rbx \n\t" // b += 1*16 (unroll x nr) " \n\t" "vmovaps -4 * 32(%%rbx), %%ymm0 \n\t" "vmovaps -3 * 32(%%rbx), %%ymm1 \n\t" " \n\t" " \n\t" "decq %%rsi \n\t" // i -= 1; "jne .SLOOPKLEFT \n\t" // iterate again if i != 0. " \n\t" " \n\t" " \n\t" ".SPOSTACCUM: \n\t" " \n\t" " \n\t" " \n\t" " \n\t" "movq %4, %%rax \n\t" // load address of alpha "movq %5, %%rbx \n\t" // load address of beta "vbroadcastss (%%rax), %%ymm0 \n\t" // load alpha and duplicate "vbroadcastss (%%rbx), %%ymm3 \n\t" // load beta and duplicate " \n\t" "vmulps %%ymm0, %%ymm4, %%ymm4 \n\t" // scale by alpha "vmulps %%ymm0, %%ymm5, %%ymm5 \n\t" "vmulps %%ymm0, %%ymm6, %%ymm6 \n\t" "vmulps %%ymm0, %%ymm7, %%ymm7 \n\t" "vmulps %%ymm0, %%ymm8, %%ymm8 \n\t" "vmulps %%ymm0, %%ymm9, %%ymm9 \n\t" "vmulps %%ymm0, %%ymm10, %%ymm10 \n\t" "vmulps %%ymm0, %%ymm11, %%ymm11 \n\t" "vmulps %%ymm0, %%ymm12, %%ymm12 \n\t" "vmulps %%ymm0, %%ymm13, %%ymm13 \n\t" "vmulps %%ymm0, %%ymm14, %%ymm14 \n\t" "vmulps %%ymm0, %%ymm15, %%ymm15 \n\t" " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" "movq %8, %%rsi \n\t" // load cs_c "leaq (,%%rsi,4), %%rsi \n\t" // rsi = cs_c * sizeof(float) " \n\t" "leaq (%%rcx,%%rsi,8), %%rdx \n\t" // load address of c + 8*cs_c; " \n\t" "leaq (%%rsi,%%rsi,2), %%r13 \n\t" // r13 = 3*cs_c; "leaq (%%rsi,%%rsi,4), %%r15 \n\t" // r15 = 5*cs_c; "leaq (%%r13,%%rsi,4), %%r10 \n\t" // r10 = 7*cs_c; " \n\t" " \n\t" " \n\t" // now avoid loading C if beta == 0 " \n\t" "vxorps %%ymm0, %%ymm0, %%ymm0 \n\t" // set ymm0 to zero. "vucomiss %%xmm0, %%xmm3 \n\t" // set ZF if beta == 0. "je .SBETAZERO \n\t" // if ZF = 1, jump to beta == 0 case " \n\t" " \n\t" "cmpq $4, %%rsi \n\t" // set ZF if (4*cs_c) == 4. "jz .SROWSTORED \n\t" // jump to row storage case " \n\t" " \n\t" " \n\t" ".SGENSTORED: \n\t" " \n\t" " \n\t" SGEMM_INPUT_GS_BETA_NZ "vfmadd213ps %%ymm4, %%ymm3, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" SGEMM_INPUT_GS_BETA_NZ "vfmadd213ps %%ymm6, %%ymm3, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" SGEMM_INPUT_GS_BETA_NZ "vfmadd213ps %%ymm8, %%ymm3, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" SGEMM_INPUT_GS_BETA_NZ "vfmadd213ps %%ymm10, %%ymm3, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" SGEMM_INPUT_GS_BETA_NZ "vfmadd213ps %%ymm12, %%ymm3, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" SGEMM_INPUT_GS_BETA_NZ "vfmadd213ps %%ymm14, %%ymm3, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ //"addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" "movq %%rdx, %%rcx \n\t" // rcx = c + 8*cs_c " \n\t" " \n\t" SGEMM_INPUT_GS_BETA_NZ "vfmadd213ps %%ymm5, %%ymm3, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" SGEMM_INPUT_GS_BETA_NZ "vfmadd213ps %%ymm7, %%ymm3, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" SGEMM_INPUT_GS_BETA_NZ "vfmadd213ps %%ymm9, %%ymm3, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" SGEMM_INPUT_GS_BETA_NZ "vfmadd213ps %%ymm11, %%ymm3, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" SGEMM_INPUT_GS_BETA_NZ "vfmadd213ps %%ymm13, %%ymm3, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" SGEMM_INPUT_GS_BETA_NZ "vfmadd213ps %%ymm15, %%ymm3, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ //"addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" " \n\t" "jmp .SDONE \n\t" // jump to end. " \n\t" " \n\t" " \n\t" ".SROWSTORED: \n\t" " \n\t" " \n\t" "vfmadd231ps (%%rcx), %%ymm3, %%ymm4 \n\t" "vmovups %%ymm4, (%%rcx) \n\t" "addq %%rdi, %%rcx \n\t" "vfmadd231ps (%%rdx), %%ymm3, %%ymm5 \n\t" "vmovups %%ymm5, (%%rdx) \n\t" "addq %%rdi, %%rdx \n\t" " \n\t" " \n\t" "vfmadd231ps (%%rcx), %%ymm3, %%ymm6 \n\t" "vmovups %%ymm6, (%%rcx) \n\t" "addq %%rdi, %%rcx \n\t" "vfmadd231ps (%%rdx), %%ymm3, %%ymm7 \n\t" "vmovups %%ymm7, (%%rdx) \n\t" "addq %%rdi, %%rdx \n\t" " \n\t" " \n\t" "vfmadd231ps (%%rcx), %%ymm3, %%ymm8 \n\t" "vmovups %%ymm8, (%%rcx) \n\t" "addq %%rdi, %%rcx \n\t" "vfmadd231ps (%%rdx), %%ymm3, %%ymm9 \n\t" "vmovups %%ymm9, (%%rdx) \n\t" "addq %%rdi, %%rdx \n\t" " \n\t" " \n\t" "vfmadd231ps (%%rcx), %%ymm3, %%ymm10 \n\t" "vmovups %%ymm10, (%%rcx) \n\t" "addq %%rdi, %%rcx \n\t" "vfmadd231ps (%%rdx), %%ymm3, %%ymm11 \n\t" "vmovups %%ymm11, (%%rdx) \n\t" "addq %%rdi, %%rdx \n\t" " \n\t" " \n\t" "vfmadd231ps (%%rcx), %%ymm3, %%ymm12 \n\t" "vmovups %%ymm12, (%%rcx) \n\t" "addq %%rdi, %%rcx \n\t" "vfmadd231ps (%%rdx), %%ymm3, %%ymm13 \n\t" "vmovups %%ymm13, (%%rdx) \n\t" "addq %%rdi, %%rdx \n\t" " \n\t" " \n\t" "vfmadd231ps (%%rcx), %%ymm3, %%ymm14 \n\t" "vmovups %%ymm14, (%%rcx) \n\t" //"addq %%rdi, %%rcx \n\t" "vfmadd231ps (%%rdx), %%ymm3, %%ymm15 \n\t" "vmovups %%ymm15, (%%rdx) \n\t" //"addq %%rdi, %%rdx \n\t" " \n\t" " \n\t" " \n\t" "jmp .SDONE \n\t" // jump to end. " \n\t" " \n\t" " \n\t" ".SBETAZERO: \n\t" " \n\t" "cmpq $4, %%rsi \n\t" // set ZF if (4*cs_c) == 4. "jz .SROWSTORBZ \n\t" // jump to row storage case " \n\t" " \n\t" " \n\t" ".SGENSTORBZ: \n\t" " \n\t" " \n\t" "vmovaps %%ymm4, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" "vmovaps %%ymm6, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" "vmovaps %%ymm8, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" "vmovaps %%ymm10, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" "vmovaps %%ymm12, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" "vmovaps %%ymm14, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ //"addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" "movq %%rdx, %%rcx \n\t" // rcx = c + 8*cs_c " \n\t" " \n\t" "vmovaps %%ymm5, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" "vmovaps %%ymm7, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" "vmovaps %%ymm9, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" "vmovaps %%ymm11, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" "vmovaps %%ymm13, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" "vmovaps %%ymm15, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ //"addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" " \n\t" "jmp .SDONE \n\t" // jump to end. " \n\t" " \n\t" " \n\t" ".SROWSTORBZ: \n\t" " \n\t" " \n\t" "vmovups %%ymm4, (%%rcx) \n\t" "addq %%rdi, %%rcx \n\t" "vmovups %%ymm5, (%%rdx) \n\t" "addq %%rdi, %%rdx \n\t" " \n\t" "vmovups %%ymm6, (%%rcx) \n\t" "addq %%rdi, %%rcx \n\t" "vmovups %%ymm7, (%%rdx) \n\t" "addq %%rdi, %%rdx \n\t" " \n\t" " \n\t" "vmovups %%ymm8, (%%rcx) \n\t" "addq %%rdi, %%rcx \n\t" "vmovups %%ymm9, (%%rdx) \n\t" "addq %%rdi, %%rdx \n\t" " \n\t" " \n\t" "vmovups %%ymm10, (%%rcx) \n\t" "addq %%rdi, %%rcx \n\t" "vmovups %%ymm11, (%%rdx) \n\t" "addq %%rdi, %%rdx \n\t" " \n\t" " \n\t" "vmovups %%ymm12, (%%rcx) \n\t" "addq %%rdi, %%rcx \n\t" "vmovups %%ymm13, (%%rdx) \n\t" "addq %%rdi, %%rdx \n\t" " \n\t" " \n\t" "vmovups %%ymm14, (%%rcx) \n\t" //"addq %%rdi, %%rcx \n\t" "vmovups %%ymm15, (%%rdx) \n\t" //"addq %%rdi, %%rdx \n\t" " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" ".SDONE: \n\t" " \n\t" "vzeroupper \n\t" " \n\t" : // output operands (none) : // input operands "m" (k_iter), // 0 "m" (k_left), // 1 "m" (a), // 2 "m" (b), // 3 "m" (alpha), // 4 "m" (beta), // 5 "m" (c), // 6 "m" (rs_c), // 7 "m" (cs_c)/*, // 8 "m" (b_next), // 9 "m" (a_next)*/ // 10 : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ); } #define DGEMM_INPUT_GS_BETA_NZ \ "vmovlpd (%%rcx ), %%xmm0, %%xmm0 \n\t" \ "vmovhpd (%%rcx,%%rsi,1), %%xmm0, %%xmm0 \n\t" \ "vmovlpd (%%rcx,%%rsi,2), %%xmm1, %%xmm1 \n\t" \ "vmovhpd (%%rcx,%%r13 ), %%xmm1, %%xmm1 \n\t" \ "vperm2f128 $0x20, %%ymm1, %%ymm0, %%ymm0 \n\t" /*\ "vmovlpd (%%rcx,%%rsi,4), %%xmm2, %%xmm2 \n\t" \ "vmovhpd (%%rcx,%%r15 ), %%xmm2, %%xmm2 \n\t" \ "vmovlpd (%%rcx,%%r13,2), %%xmm1, %%xmm1 \n\t" \ "vmovhpd (%%rcx,%%r10 ), %%xmm1, %%xmm1 \n\t" \ "vperm2f128 $0x20, %%ymm1, %%ymm2, %%ymm2 \n\t"*/ #define DGEMM_OUTPUT_GS_BETA_NZ \ "vextractf128 $1, %%ymm0, %%xmm1 \n\t" \ "vmovlpd %%xmm0, (%%rcx ) \n\t" \ "vmovhpd %%xmm0, (%%rcx,%%rsi ) \n\t" \ "vmovlpd %%xmm1, (%%rcx,%%rsi,2) \n\t" \ "vmovhpd %%xmm1, (%%rcx,%%r13 ) \n\t" /*\ "vextractf128 $1, %%ymm2, %%xmm1 \n\t" \ "vmovlpd %%xmm2, (%%rcx,%%rsi,4) \n\t" \ "vmovhpd %%xmm2, (%%rcx,%%r15 ) \n\t" \ "vmovlpd %%xmm1, (%%rcx,%%r13,2) \n\t" \ "vmovhpd %%xmm1, (%%rcx,%%r10 ) \n\t"*/ void bli_dgemm_haswell_asm_6x8 ( dim_t k0, double* restrict alpha, double* restrict a, double* restrict b, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; __asm__ volatile ( " \n\t" "vzeroall \n\t" // zero all xmm/ymm registers. " \n\t" " \n\t" "movq %2, %%rax \n\t" // load address of a. "movq %3, %%rbx \n\t" // load address of b. //"movq %9, %%r15 \n\t" // load address of b_next. " \n\t" "addq $32 * 4, %%rbx \n\t" " \n\t" // initialize loop by pre-loading "vmovapd -4 * 32(%%rbx), %%ymm0 \n\t" "vmovapd -3 * 32(%%rbx), %%ymm1 \n\t" " \n\t" "movq %6, %%rcx \n\t" // load address of c "movq %7, %%rdi \n\t" // load rs_c "leaq (,%%rdi,8), %%rdi \n\t" // rs_c *= sizeof(double) " \n\t" "leaq (%%rdi,%%rdi,2), %%r13 \n\t" // r13 = 3*rs_c; "leaq (%%rcx,%%r13,1), %%rdx \n\t" // rdx = c + 3*rs_c; "prefetcht0 7 * 8(%%rcx) \n\t" // prefetch c + 0*rs_c "prefetcht0 7 * 8(%%rcx,%%rdi) \n\t" // prefetch c + 1*rs_c "prefetcht0 7 * 8(%%rcx,%%rdi,2) \n\t" // prefetch c + 2*rs_c "prefetcht0 7 * 8(%%rdx) \n\t" // prefetch c + 3*rs_c "prefetcht0 7 * 8(%%rdx,%%rdi) \n\t" // prefetch c + 4*rs_c "prefetcht0 7 * 8(%%rdx,%%rdi,2) \n\t" // prefetch c + 5*rs_c " \n\t" " \n\t" " \n\t" " \n\t" "movq %0, %%rsi \n\t" // i = k_iter; "testq %%rsi, %%rsi \n\t" // check i via logical AND. "je .DCONSIDKLEFT \n\t" // if i == 0, jump to code that " \n\t" // contains the k_left loop. " \n\t" " \n\t" ".DLOOPKITER: \n\t" // MAIN LOOP " \n\t" " \n\t" " \n\t" // iteration 0 "prefetcht0 64 * 8(%%rax) \n\t" " \n\t" "vbroadcastsd 0 * 8(%%rax), %%ymm2 \n\t" "vbroadcastsd 1 * 8(%%rax), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm2, %%ymm4 \n\t" "vfmadd231pd %%ymm1, %%ymm2, %%ymm5 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm6 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm7 \n\t" " \n\t" "vbroadcastsd 2 * 8(%%rax), %%ymm2 \n\t" "vbroadcastsd 3 * 8(%%rax), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm2, %%ymm8 \n\t" "vfmadd231pd %%ymm1, %%ymm2, %%ymm9 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm10 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm11 \n\t" " \n\t" "vbroadcastsd 4 * 8(%%rax), %%ymm2 \n\t" "vbroadcastsd 5 * 8(%%rax), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm2, %%ymm12 \n\t" "vfmadd231pd %%ymm1, %%ymm2, %%ymm13 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm14 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm15 \n\t" " \n\t" "vmovapd -2 * 32(%%rbx), %%ymm0 \n\t" "vmovapd -1 * 32(%%rbx), %%ymm1 \n\t" " \n\t" " \n\t" // iteration 1 "vbroadcastsd 6 * 8(%%rax), %%ymm2 \n\t" "vbroadcastsd 7 * 8(%%rax), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm2, %%ymm4 \n\t" "vfmadd231pd %%ymm1, %%ymm2, %%ymm5 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm6 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm7 \n\t" " \n\t" "vbroadcastsd 8 * 8(%%rax), %%ymm2 \n\t" "vbroadcastsd 9 * 8(%%rax), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm2, %%ymm8 \n\t" "vfmadd231pd %%ymm1, %%ymm2, %%ymm9 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm10 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm11 \n\t" " \n\t" "vbroadcastsd 10 * 8(%%rax), %%ymm2 \n\t" "vbroadcastsd 11 * 8(%%rax), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm2, %%ymm12 \n\t" "vfmadd231pd %%ymm1, %%ymm2, %%ymm13 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm14 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm15 \n\t" " \n\t" "vmovapd 0 * 32(%%rbx), %%ymm0 \n\t" "vmovapd 1 * 32(%%rbx), %%ymm1 \n\t" " \n\t" " \n\t" // iteration 2 "prefetcht0 76 * 8(%%rax) \n\t" " \n\t" "vbroadcastsd 12 * 8(%%rax), %%ymm2 \n\t" "vbroadcastsd 13 * 8(%%rax), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm2, %%ymm4 \n\t" "vfmadd231pd %%ymm1, %%ymm2, %%ymm5 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm6 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm7 \n\t" " \n\t" "vbroadcastsd 14 * 8(%%rax), %%ymm2 \n\t" "vbroadcastsd 15 * 8(%%rax), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm2, %%ymm8 \n\t" "vfmadd231pd %%ymm1, %%ymm2, %%ymm9 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm10 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm11 \n\t" " \n\t" "vbroadcastsd 16 * 8(%%rax), %%ymm2 \n\t" "vbroadcastsd 17 * 8(%%rax), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm2, %%ymm12 \n\t" "vfmadd231pd %%ymm1, %%ymm2, %%ymm13 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm14 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm15 \n\t" " \n\t" "vmovapd 2 * 32(%%rbx), %%ymm0 \n\t" "vmovapd 3 * 32(%%rbx), %%ymm1 \n\t" " \n\t" " \n\t" // iteration 3 "vbroadcastsd 18 * 8(%%rax), %%ymm2 \n\t" "vbroadcastsd 19 * 8(%%rax), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm2, %%ymm4 \n\t" "vfmadd231pd %%ymm1, %%ymm2, %%ymm5 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm6 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm7 \n\t" " \n\t" "vbroadcastsd 20 * 8(%%rax), %%ymm2 \n\t" "vbroadcastsd 21 * 8(%%rax), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm2, %%ymm8 \n\t" "vfmadd231pd %%ymm1, %%ymm2, %%ymm9 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm10 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm11 \n\t" " \n\t" "vbroadcastsd 22 * 8(%%rax), %%ymm2 \n\t" "vbroadcastsd 23 * 8(%%rax), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm2, %%ymm12 \n\t" "vfmadd231pd %%ymm1, %%ymm2, %%ymm13 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm14 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm15 \n\t" " \n\t" "addq $4 * 6 * 8, %%rax \n\t" // a += 4*6 (unroll x mr) "addq $4 * 8 * 8, %%rbx \n\t" // b += 4*8 (unroll x nr) " \n\t" "vmovapd -4 * 32(%%rbx), %%ymm0 \n\t" "vmovapd -3 * 32(%%rbx), %%ymm1 \n\t" " \n\t" " \n\t" "decq %%rsi \n\t" // i -= 1; "jne .DLOOPKITER \n\t" // iterate again if i != 0. " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" ".DCONSIDKLEFT: \n\t" " \n\t" "movq %1, %%rsi \n\t" // i = k_left; "testq %%rsi, %%rsi \n\t" // check i via logical AND. "je .DPOSTACCUM \n\t" // if i == 0, we're done; jump to end. " \n\t" // else, we prepare to enter k_left loop. " \n\t" " \n\t" ".DLOOPKLEFT: \n\t" // EDGE LOOP " \n\t" "prefetcht0 64 * 8(%%rax) \n\t" " \n\t" "vbroadcastsd 0 * 8(%%rax), %%ymm2 \n\t" "vbroadcastsd 1 * 8(%%rax), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm2, %%ymm4 \n\t" "vfmadd231pd %%ymm1, %%ymm2, %%ymm5 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm6 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm7 \n\t" " \n\t" "vbroadcastsd 2 * 8(%%rax), %%ymm2 \n\t" "vbroadcastsd 3 * 8(%%rax), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm2, %%ymm8 \n\t" "vfmadd231pd %%ymm1, %%ymm2, %%ymm9 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm10 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm11 \n\t" " \n\t" "vbroadcastsd 4 * 8(%%rax), %%ymm2 \n\t" "vbroadcastsd 5 * 8(%%rax), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm2, %%ymm12 \n\t" "vfmadd231pd %%ymm1, %%ymm2, %%ymm13 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm14 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm15 \n\t" " \n\t" "addq $1 * 6 * 8, %%rax \n\t" // a += 1*6 (unroll x mr) "addq $1 * 8 * 8, %%rbx \n\t" // b += 1*8 (unroll x nr) " \n\t" "vmovapd -4 * 32(%%rbx), %%ymm0 \n\t" "vmovapd -3 * 32(%%rbx), %%ymm1 \n\t" " \n\t" " \n\t" "decq %%rsi \n\t" // i -= 1; "jne .DLOOPKLEFT \n\t" // iterate again if i != 0. " \n\t" " \n\t" " \n\t" ".DPOSTACCUM: \n\t" " \n\t" " \n\t" " \n\t" " \n\t" "movq %4, %%rax \n\t" // load address of alpha "movq %5, %%rbx \n\t" // load address of beta "vbroadcastsd (%%rax), %%ymm0 \n\t" // load alpha and duplicate "vbroadcastsd (%%rbx), %%ymm3 \n\t" // load beta and duplicate " \n\t" "vmulpd %%ymm0, %%ymm4, %%ymm4 \n\t" // scale by alpha "vmulpd %%ymm0, %%ymm5, %%ymm5 \n\t" "vmulpd %%ymm0, %%ymm6, %%ymm6 \n\t" "vmulpd %%ymm0, %%ymm7, %%ymm7 \n\t" "vmulpd %%ymm0, %%ymm8, %%ymm8 \n\t" "vmulpd %%ymm0, %%ymm9, %%ymm9 \n\t" "vmulpd %%ymm0, %%ymm10, %%ymm10 \n\t" "vmulpd %%ymm0, %%ymm11, %%ymm11 \n\t" "vmulpd %%ymm0, %%ymm12, %%ymm12 \n\t" "vmulpd %%ymm0, %%ymm13, %%ymm13 \n\t" "vmulpd %%ymm0, %%ymm14, %%ymm14 \n\t" "vmulpd %%ymm0, %%ymm15, %%ymm15 \n\t" " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" "movq %8, %%rsi \n\t" // load cs_c "leaq (,%%rsi,8), %%rsi \n\t" // rsi = cs_c * sizeof(double) " \n\t" "leaq (%%rcx,%%rsi,4), %%rdx \n\t" // load address of c + 4*cs_c; " \n\t" "leaq (%%rsi,%%rsi,2), %%r13 \n\t" // r13 = 3*cs_c; //"leaq (%%rsi,%%rsi,4), %%r15 \n\t" // r15 = 5*cs_c; //"leaq (%%r13,%%rsi,4), %%r10 \n\t" // r10 = 7*cs_c; " \n\t" " \n\t" " \n\t" // now avoid loading C if beta == 0 " \n\t" "vxorpd %%ymm0, %%ymm0, %%ymm0 \n\t" // set ymm0 to zero. "vucomisd %%xmm0, %%xmm3 \n\t" // set ZF if beta == 0. "je .DBETAZERO \n\t" // if ZF = 1, jump to beta == 0 case " \n\t" " \n\t" "cmpq $8, %%rsi \n\t" // set ZF if (8*cs_c) == 8. "jz .DROWSTORED \n\t" // jump to row storage case " \n\t" " \n\t" " \n\t" ".DGENSTORED: \n\t" " \n\t" " \n\t" DGEMM_INPUT_GS_BETA_NZ "vfmadd213pd %%ymm4, %%ymm3, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" DGEMM_INPUT_GS_BETA_NZ "vfmadd213pd %%ymm6, %%ymm3, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" DGEMM_INPUT_GS_BETA_NZ "vfmadd213pd %%ymm8, %%ymm3, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" DGEMM_INPUT_GS_BETA_NZ "vfmadd213pd %%ymm10, %%ymm3, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" DGEMM_INPUT_GS_BETA_NZ "vfmadd213pd %%ymm12, %%ymm3, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" DGEMM_INPUT_GS_BETA_NZ "vfmadd213pd %%ymm14, %%ymm3, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ " \n\t" " \n\t" "movq %%rdx, %%rcx \n\t" // rcx = c + 4*cs_c " \n\t" " \n\t" DGEMM_INPUT_GS_BETA_NZ "vfmadd213pd %%ymm5, %%ymm3, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" DGEMM_INPUT_GS_BETA_NZ "vfmadd213pd %%ymm7, %%ymm3, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" DGEMM_INPUT_GS_BETA_NZ "vfmadd213pd %%ymm9, %%ymm3, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" DGEMM_INPUT_GS_BETA_NZ "vfmadd213pd %%ymm11, %%ymm3, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" DGEMM_INPUT_GS_BETA_NZ "vfmadd213pd %%ymm13, %%ymm3, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" DGEMM_INPUT_GS_BETA_NZ "vfmadd213pd %%ymm15, %%ymm3, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ " \n\t" " \n\t" " \n\t" "jmp .DDONE \n\t" // jump to end. " \n\t" " \n\t" " \n\t" ".DROWSTORED: \n\t" " \n\t" " \n\t" "vfmadd231pd (%%rcx), %%ymm3, %%ymm4 \n\t" "vmovupd %%ymm4, (%%rcx) \n\t" "addq %%rdi, %%rcx \n\t" "vfmadd231pd (%%rdx), %%ymm3, %%ymm5 \n\t" "vmovupd %%ymm5, (%%rdx) \n\t" "addq %%rdi, %%rdx \n\t" " \n\t" " \n\t" "vfmadd231pd (%%rcx), %%ymm3, %%ymm6 \n\t" "vmovupd %%ymm6, (%%rcx) \n\t" "addq %%rdi, %%rcx \n\t" "vfmadd231pd (%%rdx), %%ymm3, %%ymm7 \n\t" "vmovupd %%ymm7, (%%rdx) \n\t" "addq %%rdi, %%rdx \n\t" " \n\t" " \n\t" "vfmadd231pd (%%rcx), %%ymm3, %%ymm8 \n\t" "vmovupd %%ymm8, (%%rcx) \n\t" "addq %%rdi, %%rcx \n\t" "vfmadd231pd (%%rdx), %%ymm3, %%ymm9 \n\t" "vmovupd %%ymm9, (%%rdx) \n\t" "addq %%rdi, %%rdx \n\t" " \n\t" " \n\t" "vfmadd231pd (%%rcx), %%ymm3, %%ymm10 \n\t" "vmovupd %%ymm10, (%%rcx) \n\t" "addq %%rdi, %%rcx \n\t" "vfmadd231pd (%%rdx), %%ymm3, %%ymm11 \n\t" "vmovupd %%ymm11, (%%rdx) \n\t" "addq %%rdi, %%rdx \n\t" " \n\t" " \n\t" "vfmadd231pd (%%rcx), %%ymm3, %%ymm12 \n\t" "vmovupd %%ymm12, (%%rcx) \n\t" "addq %%rdi, %%rcx \n\t" "vfmadd231pd (%%rdx), %%ymm3, %%ymm13 \n\t" "vmovupd %%ymm13, (%%rdx) \n\t" "addq %%rdi, %%rdx \n\t" " \n\t" " \n\t" "vfmadd231pd (%%rcx), %%ymm3, %%ymm14 \n\t" "vmovupd %%ymm14, (%%rcx) \n\t" //"addq %%rdi, %%rcx \n\t" "vfmadd231pd (%%rdx), %%ymm3, %%ymm15 \n\t" "vmovupd %%ymm15, (%%rdx) \n\t" //"addq %%rdi, %%rdx \n\t" " \n\t" " \n\t" " \n\t" "jmp .DDONE \n\t" // jump to end. " \n\t" " \n\t" " \n\t" ".DBETAZERO: \n\t" " \n\t" "cmpq $8, %%rsi \n\t" // set ZF if (8*cs_c) == 8. "jz .DROWSTORBZ \n\t" // jump to row storage case " \n\t" " \n\t" " \n\t" ".DGENSTORBZ: \n\t" " \n\t" " \n\t" "vmovapd %%ymm4, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" "vmovapd %%ymm6, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" "vmovapd %%ymm8, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" "vmovapd %%ymm10, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" "vmovapd %%ymm12, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" "vmovapd %%ymm14, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ " \n\t" " \n\t" "movq %%rdx, %%rcx \n\t" // rcx = c + 4*cs_c " \n\t" " \n\t" "vmovapd %%ymm5, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" "vmovapd %%ymm7, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" "vmovapd %%ymm9, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" "vmovapd %%ymm11, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" "vmovapd %%ymm13, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += rs_c; " \n\t" " \n\t" "vmovapd %%ymm15, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ " \n\t" " \n\t" " \n\t" "jmp .DDONE \n\t" // jump to end. " \n\t" " \n\t" " \n\t" ".DROWSTORBZ: \n\t" " \n\t" " \n\t" "vmovupd %%ymm4, (%%rcx) \n\t" "addq %%rdi, %%rcx \n\t" "vmovupd %%ymm5, (%%rdx) \n\t" "addq %%rdi, %%rdx \n\t" " \n\t" "vmovupd %%ymm6, (%%rcx) \n\t" "addq %%rdi, %%rcx \n\t" "vmovupd %%ymm7, (%%rdx) \n\t" "addq %%rdi, %%rdx \n\t" " \n\t" " \n\t" "vmovupd %%ymm8, (%%rcx) \n\t" "addq %%rdi, %%rcx \n\t" "vmovupd %%ymm9, (%%rdx) \n\t" "addq %%rdi, %%rdx \n\t" " \n\t" " \n\t" "vmovupd %%ymm10, (%%rcx) \n\t" "addq %%rdi, %%rcx \n\t" "vmovupd %%ymm11, (%%rdx) \n\t" "addq %%rdi, %%rdx \n\t" " \n\t" " \n\t" "vmovupd %%ymm12, (%%rcx) \n\t" "addq %%rdi, %%rcx \n\t" "vmovupd %%ymm13, (%%rdx) \n\t" "addq %%rdi, %%rdx \n\t" " \n\t" " \n\t" "vmovupd %%ymm14, (%%rcx) \n\t" //"addq %%rdi, %%rcx \n\t" "vmovupd %%ymm15, (%%rdx) \n\t" //"addq %%rdi, %%rdx \n\t" " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" ".DDONE: \n\t" " \n\t" "vzeroupper \n\t" " \n\t" : // output operands (none) : // input operands "m" (k_iter), // 0 "m" (k_left), // 1 "m" (a), // 2 "m" (b), // 3 "m" (alpha), // 4 "m" (beta), // 5 "m" (c), // 6 "m" (rs_c), // 7 "m" (cs_c)/*, // 8 "m" (b_next), // 9 "m" (a_next)*/ // 10 : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ); } // assumes beta.r, beta.i have been broadcast into ymm1, ymm2. // outputs to ymm0 #define CGEMM_INPUT_SCALE_GS_BETA_NZ \ "vmovlpd (%%rcx ), %%xmm0, %%xmm0 \n\t" \ "vmovhpd (%%rcx,%%rsi,1), %%xmm0, %%xmm0 \n\t" \ "vmovlpd (%%rcx,%%rsi,2), %%xmm3, %%xmm3 \n\t" \ "vmovhpd (%%rcx,%%r13 ), %%xmm3, %%xmm3 \n\t" \ "vinsertf128 $1, %%xmm3, %%ymm0, %%ymm0 \n\t" \ "vpermilps $0xb1, %%ymm0, %%ymm3 \n\t" \ "vmulps %%ymm1, %%ymm0, %%ymm0 \n\t" \ "vmulps %%ymm2, %%ymm3, %%ymm3 \n\t" \ "vaddsubps %%ymm3, %%ymm0, %%ymm0 \n\t" // assumes values to output are in ymm0 #define CGEMM_OUTPUT_GS \ "vextractf128 $1, %%ymm0, %%xmm3 \n\t" \ "vmovlpd %%xmm0, (%%rcx ) \n\t" \ "vmovhpd %%xmm0, (%%rcx,%%rsi,1) \n\t" \ "vmovlpd %%xmm3, (%%rcx,%%rsi,2) \n\t" \ "vmovhpd %%xmm3, (%%rcx,%%r13 ) \n\t" #define CGEMM_INPUT_SCALE_RS_BETA_NZ \ "vmovups (%%rcx), %%ymm0 \n\t" \ "vpermilps $0xb1, %%ymm0, %%ymm3 \n\t" \ "vmulps %%ymm1, %%ymm0, %%ymm0 \n\t" \ "vmulps %%ymm2, %%ymm3, %%ymm3 \n\t" \ "vaddsubps %%ymm3, %%ymm0, %%ymm0 \n\t" #define CGEMM_OUTPUT_RS \ "vmovups %%ymm0, (%%rcx) \n\t" \ void bli_cgemm_haswell_asm_3x8 ( dim_t k0, scomplex* restrict alpha, scomplex* restrict a, scomplex* restrict b, scomplex* restrict beta, scomplex* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; __asm__ volatile ( " \n\t" "vzeroall \n\t" // zero all xmm/ymm registers. " \n\t" " \n\t" "movq %2, %%rax \n\t" // load address of a. "movq %3, %%rbx \n\t" // load address of b. //"movq %9, %%r15 \n\t" // load address of b_next. " \n\t" "addq $32 * 4, %%rbx \n\t" " \n\t" // initialize loop by pre-loading "vmovaps -4 * 32(%%rbx), %%ymm0 \n\t" "vmovaps -3 * 32(%%rbx), %%ymm1 \n\t" " \n\t" "movq %6, %%rcx \n\t" // load address of c "movq %7, %%rdi \n\t" // load rs_c "leaq (,%%rdi,8), %%rdi \n\t" // rs_c *= sizeof(scomplex) " \n\t" "leaq (%%rcx,%%rdi,1), %%r11 \n\t" // r11 = c + 1*rs_c; "leaq (%%rcx,%%rdi,2), %%r12 \n\t" // r12 = c + 2*rs_c; " \n\t" "prefetcht0 7 * 8(%%rcx) \n\t" // prefetch c + 0*rs_c "prefetcht0 7 * 8(%%r11) \n\t" // prefetch c + 1*rs_c "prefetcht0 7 * 8(%%r12) \n\t" // prefetch c + 2*rs_c " \n\t" " \n\t" " \n\t" " \n\t" "movq %0, %%rsi \n\t" // i = k_iter; "testq %%rsi, %%rsi \n\t" // check i via logical AND. "je .CCONSIDKLEFT \n\t" // if i == 0, jump to code that " \n\t" // contains the k_left loop. " \n\t" " \n\t" ".CLOOPKITER: \n\t" // MAIN LOOP " \n\t" " \n\t" " \n\t" // iteration 0 "prefetcht0 32 * 8(%%rax) \n\t" " \n\t" "vbroadcastss 0 * 4(%%rax), %%ymm2 \n\t" "vbroadcastss 1 * 4(%%rax), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm2, %%ymm4 \n\t" "vfmadd231ps %%ymm1, %%ymm2, %%ymm5 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm6 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm7 \n\t" " \n\t" "vbroadcastss 2 * 4(%%rax), %%ymm2 \n\t" "vbroadcastss 3 * 4(%%rax), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm2, %%ymm8 \n\t" "vfmadd231ps %%ymm1, %%ymm2, %%ymm9 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm10 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm11 \n\t" " \n\t" "vbroadcastss 4 * 4(%%rax), %%ymm2 \n\t" "vbroadcastss 5 * 4(%%rax), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm2, %%ymm12 \n\t" "vfmadd231ps %%ymm1, %%ymm2, %%ymm13 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm14 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm15 \n\t" " \n\t" "vmovaps -2 * 32(%%rbx), %%ymm0 \n\t" "vmovaps -1 * 32(%%rbx), %%ymm1 \n\t" " \n\t" " \n\t" // iteration 1 "vbroadcastss 6 * 4(%%rax), %%ymm2 \n\t" "vbroadcastss 7 * 4(%%rax), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm2, %%ymm4 \n\t" "vfmadd231ps %%ymm1, %%ymm2, %%ymm5 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm6 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm7 \n\t" " \n\t" "vbroadcastss 8 * 4(%%rax), %%ymm2 \n\t" "vbroadcastss 9 * 4(%%rax), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm2, %%ymm8 \n\t" "vfmadd231ps %%ymm1, %%ymm2, %%ymm9 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm10 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm11 \n\t" " \n\t" "vbroadcastss 10 * 4(%%rax), %%ymm2 \n\t" "vbroadcastss 11 * 4(%%rax), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm2, %%ymm12 \n\t" "vfmadd231ps %%ymm1, %%ymm2, %%ymm13 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm14 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm15 \n\t" " \n\t" "vmovaps 0 * 32(%%rbx), %%ymm0 \n\t" "vmovaps 1 * 32(%%rbx), %%ymm1 \n\t" " \n\t" " \n\t" // iteration 2 "prefetcht0 38 * 8(%%rax) \n\t" " \n\t" "vbroadcastss 12 * 4(%%rax), %%ymm2 \n\t" "vbroadcastss 13 * 4(%%rax), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm2, %%ymm4 \n\t" "vfmadd231ps %%ymm1, %%ymm2, %%ymm5 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm6 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm7 \n\t" " \n\t" "vbroadcastss 14 * 4(%%rax), %%ymm2 \n\t" "vbroadcastss 15 * 4(%%rax), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm2, %%ymm8 \n\t" "vfmadd231ps %%ymm1, %%ymm2, %%ymm9 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm10 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm11 \n\t" " \n\t" "vbroadcastss 16 * 4(%%rax), %%ymm2 \n\t" "vbroadcastss 17 * 4(%%rax), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm2, %%ymm12 \n\t" "vfmadd231ps %%ymm1, %%ymm2, %%ymm13 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm14 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm15 \n\t" " \n\t" "vmovaps 2 * 32(%%rbx), %%ymm0 \n\t" "vmovaps 3 * 32(%%rbx), %%ymm1 \n\t" " \n\t" " \n\t" // iteration 3 "vbroadcastss 18 * 4(%%rax), %%ymm2 \n\t" "vbroadcastss 19 * 4(%%rax), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm2, %%ymm4 \n\t" "vfmadd231ps %%ymm1, %%ymm2, %%ymm5 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm6 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm7 \n\t" " \n\t" "vbroadcastss 20 * 4(%%rax), %%ymm2 \n\t" "vbroadcastss 21 * 4(%%rax), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm2, %%ymm8 \n\t" "vfmadd231ps %%ymm1, %%ymm2, %%ymm9 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm10 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm11 \n\t" " \n\t" "vbroadcastss 22 * 4(%%rax), %%ymm2 \n\t" "vbroadcastss 23 * 4(%%rax), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm2, %%ymm12 \n\t" "vfmadd231ps %%ymm1, %%ymm2, %%ymm13 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm14 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm15 \n\t" " \n\t" "addq $4 * 3 * 8, %%rax \n\t" // a += 4*3 (unroll x mr) "addq $4 * 8 * 8, %%rbx \n\t" // b += 4*8 (unroll x nr) " \n\t" "vmovaps -4 * 32(%%rbx), %%ymm0 \n\t" "vmovaps -3 * 32(%%rbx), %%ymm1 \n\t" " \n\t" " \n\t" "decq %%rsi \n\t" // i -= 1; "jne .CLOOPKITER \n\t" // iterate again if i != 0. " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" ".CCONSIDKLEFT: \n\t" " \n\t" "movq %1, %%rsi \n\t" // i = k_left; "testq %%rsi, %%rsi \n\t" // check i via logical AND. "je .CPOSTACCUM \n\t" // if i == 0, we're done; jump to end. " \n\t" // else, we prepare to enter k_left loop. " \n\t" " \n\t" ".CLOOPKLEFT: \n\t" // EDGE LOOP " \n\t" "prefetcht0 32 * 8(%%rax) \n\t" " \n\t" "vbroadcastss 0 * 4(%%rax), %%ymm2 \n\t" "vbroadcastss 1 * 4(%%rax), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm2, %%ymm4 \n\t" "vfmadd231ps %%ymm1, %%ymm2, %%ymm5 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm6 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm7 \n\t" " \n\t" "vbroadcastss 2 * 4(%%rax), %%ymm2 \n\t" "vbroadcastss 3 * 4(%%rax), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm2, %%ymm8 \n\t" "vfmadd231ps %%ymm1, %%ymm2, %%ymm9 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm10 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm11 \n\t" " \n\t" "vbroadcastss 4 * 4(%%rax), %%ymm2 \n\t" "vbroadcastss 5 * 4(%%rax), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm2, %%ymm12 \n\t" "vfmadd231ps %%ymm1, %%ymm2, %%ymm13 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm14 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm15 \n\t" " \n\t" "addq $1 * 3 * 8, %%rax \n\t" // a += 1*3 (unroll x mr) "addq $1 * 8 * 8, %%rbx \n\t" // b += 1*8 (unroll x nr) " \n\t" "vmovaps -4 * 32(%%rbx), %%ymm0 \n\t" "vmovaps -3 * 32(%%rbx), %%ymm1 \n\t" " \n\t" " \n\t" "decq %%rsi \n\t" // i -= 1; "jne .CLOOPKLEFT \n\t" // iterate again if i != 0. " \n\t" " \n\t" " \n\t" ".CPOSTACCUM: \n\t" " \n\t" " \n\t" " \n\t" // permute even and odd elements " \n\t" // of ymm6/7, ymm10/11, ymm/14/15 "vpermilps $0xb1, %%ymm6, %%ymm6 \n\t" "vpermilps $0xb1, %%ymm7, %%ymm7 \n\t" "vpermilps $0xb1, %%ymm10, %%ymm10 \n\t" "vpermilps $0xb1, %%ymm11, %%ymm11 \n\t" "vpermilps $0xb1, %%ymm14, %%ymm14 \n\t" "vpermilps $0xb1, %%ymm15, %%ymm15 \n\t" " \n\t" " \n\t" " \n\t" // subtract/add even/odd elements "vaddsubps %%ymm6, %%ymm4, %%ymm4 \n\t" "vaddsubps %%ymm7, %%ymm5, %%ymm5 \n\t" " \n\t" "vaddsubps %%ymm10, %%ymm8, %%ymm8 \n\t" "vaddsubps %%ymm11, %%ymm9, %%ymm9 \n\t" " \n\t" "vaddsubps %%ymm14, %%ymm12, %%ymm12 \n\t" "vaddsubps %%ymm15, %%ymm13, %%ymm13 \n\t" " \n\t" " \n\t" " \n\t" " \n\t" "movq %4, %%rax \n\t" // load address of alpha "vbroadcastss (%%rax), %%ymm0 \n\t" // load alpha_r and duplicate "vbroadcastss 4(%%rax), %%ymm1 \n\t" // load alpha_i and duplicate " \n\t" " \n\t" "vpermilps $0xb1, %%ymm4, %%ymm3 \n\t" "vmulps %%ymm0, %%ymm4, %%ymm4 \n\t" "vmulps %%ymm1, %%ymm3, %%ymm3 \n\t" "vaddsubps %%ymm3, %%ymm4, %%ymm4 \n\t" " \n\t" "vpermilps $0xb1, %%ymm5, %%ymm3 \n\t" "vmulps %%ymm0, %%ymm5, %%ymm5 \n\t" "vmulps %%ymm1, %%ymm3, %%ymm3 \n\t" "vaddsubps %%ymm3, %%ymm5, %%ymm5 \n\t" " \n\t" " \n\t" "vpermilps $0xb1, %%ymm8, %%ymm3 \n\t" "vmulps %%ymm0, %%ymm8, %%ymm8 \n\t" "vmulps %%ymm1, %%ymm3, %%ymm3 \n\t" "vaddsubps %%ymm3, %%ymm8, %%ymm8 \n\t" " \n\t" "vpermilps $0xb1, %%ymm9, %%ymm3 \n\t" "vmulps %%ymm0, %%ymm9, %%ymm9 \n\t" "vmulps %%ymm1, %%ymm3, %%ymm3 \n\t" "vaddsubps %%ymm3, %%ymm9, %%ymm9 \n\t" " \n\t" " \n\t" "vpermilps $0xb1, %%ymm12, %%ymm3 \n\t" "vmulps %%ymm0, %%ymm12, %%ymm12 \n\t" "vmulps %%ymm1, %%ymm3, %%ymm3 \n\t" "vaddsubps %%ymm3, %%ymm12, %%ymm12 \n\t" " \n\t" "vpermilps $0xb1, %%ymm13, %%ymm3 \n\t" "vmulps %%ymm0, %%ymm13, %%ymm13 \n\t" "vmulps %%ymm1, %%ymm3, %%ymm3 \n\t" "vaddsubps %%ymm3, %%ymm13, %%ymm13 \n\t" " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" "movq %5, %%rbx \n\t" // load address of beta "vbroadcastss (%%rbx), %%ymm1 \n\t" // load beta_r and duplicate "vbroadcastss 4(%%rbx), %%ymm2 \n\t" // load beta_i and duplicate " \n\t" " \n\t" " \n\t" " \n\t" "movq %8, %%rsi \n\t" // load cs_c "leaq (,%%rsi,8), %%rsi \n\t" // rsi = cs_c * sizeof(scomplex) "leaq (,%%rsi,4), %%rdx \n\t" // rdx = 4*cs_c; "leaq (%%rsi,%%rsi,2), %%r13 \n\t" // r13 = 3*cs_c; " \n\t" " \n\t" " \n\t" " \n\t" // now avoid loading C if beta == 0 "vxorps %%ymm0, %%ymm0, %%ymm0 \n\t" // set ymm0 to zero. "vucomiss %%xmm0, %%xmm1 \n\t" // set ZF if beta_r == 0. "sete %%r8b \n\t" // r8b = ( ZF == 1 ? 1 : 0 ); "vucomiss %%xmm0, %%xmm2 \n\t" // set ZF if beta_i == 0. "sete %%r9b \n\t" // r9b = ( ZF == 1 ? 1 : 0 ); "andb %%r8b, %%r9b \n\t" // set ZF if r8b & r9b == 1. "jne .CBETAZERO \n\t" // if ZF = 1, jump to beta == 0 case " \n\t" " \n\t" "cmpq $8, %%rsi \n\t" // set ZF if (8*cs_c) == 8. "jz .CROWSTORED \n\t" // jump to row storage case " \n\t" " \n\t" " \n\t" ".CGENSTORED: \n\t" " \n\t" " \n\t" CGEMM_INPUT_SCALE_GS_BETA_NZ "vaddps %%ymm4, %%ymm0, %%ymm0 \n\t" CGEMM_OUTPUT_GS "addq %%rdx, %%rcx \n\t" // c += 4*cs_c; " \n\t" " \n\t" CGEMM_INPUT_SCALE_GS_BETA_NZ "vaddps %%ymm5, %%ymm0, %%ymm0 \n\t" CGEMM_OUTPUT_GS "movq %%r11, %%rcx \n\t" // rcx = c + 1*rs_c " \n\t" " \n\t" " \n\t" CGEMM_INPUT_SCALE_GS_BETA_NZ "vaddps %%ymm8, %%ymm0, %%ymm0 \n\t" CGEMM_OUTPUT_GS "addq %%rdx, %%rcx \n\t" // c += 4*cs_c; " \n\t" " \n\t" CGEMM_INPUT_SCALE_GS_BETA_NZ "vaddps %%ymm9, %%ymm0, %%ymm0 \n\t" CGEMM_OUTPUT_GS "movq %%r12, %%rcx \n\t" // rcx = c + 2*rs_c " \n\t" " \n\t" " \n\t" CGEMM_INPUT_SCALE_GS_BETA_NZ "vaddps %%ymm12, %%ymm0, %%ymm0 \n\t" CGEMM_OUTPUT_GS "addq %%rdx, %%rcx \n\t" // c += 4*cs_c; " \n\t" " \n\t" CGEMM_INPUT_SCALE_GS_BETA_NZ "vaddps %%ymm13, %%ymm0, %%ymm0 \n\t" CGEMM_OUTPUT_GS " \n\t" " \n\t" " \n\t" "jmp .CDONE \n\t" // jump to end. " \n\t" " \n\t" " \n\t" ".CROWSTORED: \n\t" " \n\t" " \n\t" CGEMM_INPUT_SCALE_RS_BETA_NZ "vaddps %%ymm4, %%ymm0, %%ymm0 \n\t" CGEMM_OUTPUT_RS "addq %%rdx, %%rcx \n\t" // c += 4*cs_c; " \n\t" " \n\t" CGEMM_INPUT_SCALE_RS_BETA_NZ "vaddps %%ymm5, %%ymm0, %%ymm0 \n\t" CGEMM_OUTPUT_RS "movq %%r11, %%rcx \n\t" // rcx = c + 1*rs_c " \n\t" " \n\t" " \n\t" CGEMM_INPUT_SCALE_RS_BETA_NZ "vaddps %%ymm8, %%ymm0, %%ymm0 \n\t" CGEMM_OUTPUT_RS "addq %%rdx, %%rcx \n\t" // c += 4*cs_c; " \n\t" " \n\t" CGEMM_INPUT_SCALE_RS_BETA_NZ "vaddps %%ymm9, %%ymm0, %%ymm0 \n\t" CGEMM_OUTPUT_RS "movq %%r12, %%rcx \n\t" // rcx = c + 2*rs_c " \n\t" " \n\t" " \n\t" CGEMM_INPUT_SCALE_RS_BETA_NZ "vaddps %%ymm12, %%ymm0, %%ymm0 \n\t" CGEMM_OUTPUT_RS "addq %%rdx, %%rcx \n\t" // c += 4*cs_c; " \n\t" " \n\t" CGEMM_INPUT_SCALE_RS_BETA_NZ "vaddps %%ymm13, %%ymm0, %%ymm0 \n\t" CGEMM_OUTPUT_RS " \n\t" " \n\t" " \n\t" "jmp .CDONE \n\t" // jump to end. " \n\t" " \n\t" " \n\t" ".CBETAZERO: \n\t" " \n\t" "cmpq $8, %%rsi \n\t" // set ZF if (8*cs_c) == 8. "jz .CROWSTORBZ \n\t" // jump to row storage case " \n\t" " \n\t" " \n\t" ".CGENSTORBZ: \n\t" " \n\t" " \n\t" "vmovaps %%ymm4, %%ymm0 \n\t" CGEMM_OUTPUT_GS "addq %%rdx, %%rcx \n\t" // c += 2*cs_c; " \n\t" " \n\t" "vmovaps %%ymm5, %%ymm0 \n\t" CGEMM_OUTPUT_GS "movq %%r11, %%rcx \n\t" // rcx = c + 1*rs_c " \n\t" " \n\t" " \n\t" "vmovaps %%ymm8, %%ymm0 \n\t" CGEMM_OUTPUT_GS "addq %%rdx, %%rcx \n\t" // c += 2*cs_c; " \n\t" " \n\t" "vmovaps %%ymm9, %%ymm0 \n\t" CGEMM_OUTPUT_GS "movq %%r12, %%rcx \n\t" // rcx = c + 2*rs_c " \n\t" " \n\t" " \n\t" "vmovaps %%ymm12, %%ymm0 \n\t" CGEMM_OUTPUT_GS "addq %%rdx, %%rcx \n\t" // c += 2*cs_c; " \n\t" " \n\t" "vmovaps %%ymm13, %%ymm0 \n\t" CGEMM_OUTPUT_GS " \n\t" " \n\t" " \n\t" "jmp .CDONE \n\t" // jump to end. " \n\t" " \n\t" " \n\t" ".CROWSTORBZ: \n\t" " \n\t" " \n\t" "vmovups %%ymm4, (%%rcx) \n\t" "vmovups %%ymm5, (%%rcx,%%rdx,1) \n\t" " \n\t" "vmovups %%ymm8, (%%r11) \n\t" "vmovups %%ymm9, (%%r11,%%rdx,1) \n\t" " \n\t" "vmovups %%ymm12, (%%r12) \n\t" "vmovups %%ymm13, (%%r12,%%rdx,1) \n\t" " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" ".CDONE: \n\t" " \n\t" "vzeroupper \n\t" " \n\t" : // output operands (none) : // input operands "m" (k_iter), // 0 "m" (k_left), // 1 "m" (a), // 2 "m" (b), // 3 "m" (alpha), // 4 "m" (beta), // 5 "m" (c), // 6 "m" (rs_c), // 7 "m" (cs_c)/*, // 8 "m" (b_next), // 9 "m" (a_next)*/ // 10 : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ); } // assumes beta.r, beta.i have been broadcast into ymm1, ymm2. // outputs to ymm0 #define ZGEMM_INPUT_SCALE_GS_BETA_NZ \ "vmovupd (%%rcx), %%xmm0 \n\t" \ "vmovupd (%%rcx,%%rsi), %%xmm3 \n\t" \ "vinsertf128 $1, %%xmm3, %%ymm0, %%ymm0 \n\t" \ "vpermilpd $0x5, %%ymm0, %%ymm3 \n\t" \ "vmulpd %%ymm1, %%ymm0, %%ymm0 \n\t" \ "vmulpd %%ymm2, %%ymm3, %%ymm3 \n\t" \ "vaddsubpd %%ymm3, %%ymm0, %%ymm0 \n\t" // assumes values to output are in ymm0 #define ZGEMM_OUTPUT_GS \ "vextractf128 $1, %%ymm0, %%xmm3 \n\t" \ "vmovupd %%xmm0, (%%rcx) \n\t" \ "vmovupd %%xmm3, (%%rcx,%%rsi ) \n\t" \ #define ZGEMM_INPUT_SCALE_RS_BETA_NZ \ "vmovupd (%%rcx), %%ymm0 \n\t" \ "vpermilpd $0x5, %%ymm0, %%ymm3 \n\t" \ "vmulpd %%ymm1, %%ymm0, %%ymm0 \n\t" \ "vmulpd %%ymm2, %%ymm3, %%ymm3 \n\t" \ "vaddsubpd %%ymm3, %%ymm0, %%ymm0 \n\t" #define ZGEMM_OUTPUT_RS \ "vmovupd %%ymm0, (%%rcx) \n\t" \ void bli_zgemm_haswell_asm_3x4 ( dim_t k0, dcomplex* restrict alpha, dcomplex* restrict a, dcomplex* restrict b, dcomplex* restrict beta, dcomplex* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; __asm__ volatile ( " \n\t" "vzeroall \n\t" // zero all xmm/ymm registers. " \n\t" " \n\t" "movq %2, %%rax \n\t" // load address of a. "movq %3, %%rbx \n\t" // load address of b. //"movq %9, %%r15 \n\t" // load address of b_next. " \n\t" "addq $32 * 4, %%rbx \n\t" " \n\t" // initialize loop by pre-loading "vmovapd -4 * 32(%%rbx), %%ymm0 \n\t" "vmovapd -3 * 32(%%rbx), %%ymm1 \n\t" " \n\t" "movq %6, %%rcx \n\t" // load address of c "movq %7, %%rdi \n\t" // load rs_c "leaq (,%%rdi,8), %%rdi \n\t" // rs_c *= sizeof(dcomplex) "leaq (,%%rdi,2), %%rdi \n\t" " \n\t" "leaq (%%rcx,%%rdi,1), %%r11 \n\t" // r11 = c + 1*rs_c; "leaq (%%rcx,%%rdi,2), %%r12 \n\t" // r12 = c + 2*rs_c; " \n\t" "prefetcht0 7 * 8(%%rcx) \n\t" // prefetch c + 0*rs_c "prefetcht0 7 * 8(%%r11) \n\t" // prefetch c + 1*rs_c "prefetcht0 7 * 8(%%r12) \n\t" // prefetch c + 2*rs_c " \n\t" " \n\t" " \n\t" " \n\t" "movq %0, %%rsi \n\t" // i = k_iter; "testq %%rsi, %%rsi \n\t" // check i via logical AND. "je .ZCONSIDKLEFT \n\t" // if i == 0, jump to code that " \n\t" // contains the k_left loop. " \n\t" " \n\t" ".ZLOOPKITER: \n\t" // MAIN LOOP " \n\t" " \n\t" " \n\t" // iteration 0 "prefetcht0 32 * 16(%%rax) \n\t" " \n\t" "vbroadcastsd 0 * 8(%%rax), %%ymm2 \n\t" "vbroadcastsd 1 * 8(%%rax), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm2, %%ymm4 \n\t" "vfmadd231pd %%ymm1, %%ymm2, %%ymm5 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm6 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm7 \n\t" " \n\t" "vbroadcastsd 2 * 8(%%rax), %%ymm2 \n\t" "vbroadcastsd 3 * 8(%%rax), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm2, %%ymm8 \n\t" "vfmadd231pd %%ymm1, %%ymm2, %%ymm9 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm10 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm11 \n\t" " \n\t" "vbroadcastsd 4 * 8(%%rax), %%ymm2 \n\t" "vbroadcastsd 5 * 8(%%rax), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm2, %%ymm12 \n\t" "vfmadd231pd %%ymm1, %%ymm2, %%ymm13 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm14 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm15 \n\t" " \n\t" "vmovapd -2 * 32(%%rbx), %%ymm0 \n\t" "vmovapd -1 * 32(%%rbx), %%ymm1 \n\t" " \n\t" " \n\t" // iteration 1 "vbroadcastsd 6 * 8(%%rax), %%ymm2 \n\t" "vbroadcastsd 7 * 8(%%rax), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm2, %%ymm4 \n\t" "vfmadd231pd %%ymm1, %%ymm2, %%ymm5 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm6 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm7 \n\t" " \n\t" "vbroadcastsd 8 * 8(%%rax), %%ymm2 \n\t" "vbroadcastsd 9 * 8(%%rax), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm2, %%ymm8 \n\t" "vfmadd231pd %%ymm1, %%ymm2, %%ymm9 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm10 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm11 \n\t" " \n\t" "vbroadcastsd 10 * 8(%%rax), %%ymm2 \n\t" "vbroadcastsd 11 * 8(%%rax), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm2, %%ymm12 \n\t" "vfmadd231pd %%ymm1, %%ymm2, %%ymm13 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm14 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm15 \n\t" " \n\t" "vmovapd 0 * 32(%%rbx), %%ymm0 \n\t" "vmovapd 1 * 32(%%rbx), %%ymm1 \n\t" " \n\t" " \n\t" // iteration 2 "prefetcht0 38 * 16(%%rax) \n\t" " \n\t" "vbroadcastsd 12 * 8(%%rax), %%ymm2 \n\t" "vbroadcastsd 13 * 8(%%rax), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm2, %%ymm4 \n\t" "vfmadd231pd %%ymm1, %%ymm2, %%ymm5 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm6 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm7 \n\t" " \n\t" "vbroadcastsd 14 * 8(%%rax), %%ymm2 \n\t" "vbroadcastsd 15 * 8(%%rax), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm2, %%ymm8 \n\t" "vfmadd231pd %%ymm1, %%ymm2, %%ymm9 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm10 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm11 \n\t" " \n\t" "vbroadcastsd 16 * 8(%%rax), %%ymm2 \n\t" "vbroadcastsd 17 * 8(%%rax), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm2, %%ymm12 \n\t" "vfmadd231pd %%ymm1, %%ymm2, %%ymm13 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm14 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm15 \n\t" " \n\t" "vmovapd 2 * 32(%%rbx), %%ymm0 \n\t" "vmovapd 3 * 32(%%rbx), %%ymm1 \n\t" " \n\t" " \n\t" // iteration 3 "vbroadcastsd 18 * 8(%%rax), %%ymm2 \n\t" "vbroadcastsd 19 * 8(%%rax), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm2, %%ymm4 \n\t" "vfmadd231pd %%ymm1, %%ymm2, %%ymm5 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm6 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm7 \n\t" " \n\t" "vbroadcastsd 20 * 8(%%rax), %%ymm2 \n\t" "vbroadcastsd 21 * 8(%%rax), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm2, %%ymm8 \n\t" "vfmadd231pd %%ymm1, %%ymm2, %%ymm9 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm10 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm11 \n\t" " \n\t" "vbroadcastsd 22 * 8(%%rax), %%ymm2 \n\t" "vbroadcastsd 23 * 8(%%rax), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm2, %%ymm12 \n\t" "vfmadd231pd %%ymm1, %%ymm2, %%ymm13 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm14 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm15 \n\t" " \n\t" "addq $4 * 3 * 16, %%rax \n\t" // a += 4*3 (unroll x mr) "addq $4 * 4 * 16, %%rbx \n\t" // b += 4*4 (unroll x nr) " \n\t" "vmovapd -4 * 32(%%rbx), %%ymm0 \n\t" "vmovapd -3 * 32(%%rbx), %%ymm1 \n\t" " \n\t" " \n\t" "decq %%rsi \n\t" // i -= 1; "jne .ZLOOPKITER \n\t" // iterate again if i != 0. " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" ".ZCONSIDKLEFT: \n\t" " \n\t" "movq %1, %%rsi \n\t" // i = k_left; "testq %%rsi, %%rsi \n\t" // check i via logical AND. "je .ZPOSTACCUM \n\t" // if i == 0, we're done; jump to end. " \n\t" // else, we prepare to enter k_left loop. " \n\t" " \n\t" ".ZLOOPKLEFT: \n\t" // EDGE LOOP " \n\t" "prefetcht0 32 * 16(%%rax) \n\t" " \n\t" "vbroadcastsd 0 * 8(%%rax), %%ymm2 \n\t" "vbroadcastsd 1 * 8(%%rax), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm2, %%ymm4 \n\t" "vfmadd231pd %%ymm1, %%ymm2, %%ymm5 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm6 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm7 \n\t" " \n\t" "vbroadcastsd 2 * 8(%%rax), %%ymm2 \n\t" "vbroadcastsd 3 * 8(%%rax), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm2, %%ymm8 \n\t" "vfmadd231pd %%ymm1, %%ymm2, %%ymm9 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm10 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm11 \n\t" " \n\t" "vbroadcastsd 4 * 8(%%rax), %%ymm2 \n\t" "vbroadcastsd 5 * 8(%%rax), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm2, %%ymm12 \n\t" "vfmadd231pd %%ymm1, %%ymm2, %%ymm13 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm14 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm15 \n\t" " \n\t" "addq $1 * 3 * 16, %%rax \n\t" // a += 1*3 (unroll x mr) "addq $1 * 4 * 16, %%rbx \n\t" // b += 1*4 (unroll x nr) " \n\t" "vmovapd -4 * 32(%%rbx), %%ymm0 \n\t" "vmovapd -3 * 32(%%rbx), %%ymm1 \n\t" " \n\t" " \n\t" "decq %%rsi \n\t" // i -= 1; "jne .ZLOOPKLEFT \n\t" // iterate again if i != 0. " \n\t" " \n\t" " \n\t" ".ZPOSTACCUM: \n\t" " \n\t" " \n\t" // permute even and odd elements " \n\t" // of ymm6/7, ymm10/11, ymm/14/15 "vpermilpd $0x5, %%ymm6, %%ymm6 \n\t" "vpermilpd $0x5, %%ymm7, %%ymm7 \n\t" "vpermilpd $0x5, %%ymm10, %%ymm10 \n\t" "vpermilpd $0x5, %%ymm11, %%ymm11 \n\t" "vpermilpd $0x5, %%ymm14, %%ymm14 \n\t" "vpermilpd $0x5, %%ymm15, %%ymm15 \n\t" " \n\t" " \n\t" " \n\t" // subtract/add even/odd elements "vaddsubpd %%ymm6, %%ymm4, %%ymm4 \n\t" "vaddsubpd %%ymm7, %%ymm5, %%ymm5 \n\t" " \n\t" "vaddsubpd %%ymm10, %%ymm8, %%ymm8 \n\t" "vaddsubpd %%ymm11, %%ymm9, %%ymm9 \n\t" " \n\t" "vaddsubpd %%ymm14, %%ymm12, %%ymm12 \n\t" "vaddsubpd %%ymm15, %%ymm13, %%ymm13 \n\t" " \n\t" " \n\t" " \n\t" " \n\t" "movq %4, %%rax \n\t" // load address of alpha "vbroadcastsd (%%rax), %%ymm0 \n\t" // load alpha_r and duplicate "vbroadcastsd 8(%%rax), %%ymm1 \n\t" // load alpha_i and duplicate " \n\t" " \n\t" "vpermilpd $0x5, %%ymm4, %%ymm3 \n\t" "vmulpd %%ymm0, %%ymm4, %%ymm4 \n\t" "vmulpd %%ymm1, %%ymm3, %%ymm3 \n\t" "vaddsubpd %%ymm3, %%ymm4, %%ymm4 \n\t" " \n\t" "vpermilpd $0x5, %%ymm5, %%ymm3 \n\t" "vmulpd %%ymm0, %%ymm5, %%ymm5 \n\t" "vmulpd %%ymm1, %%ymm3, %%ymm3 \n\t" "vaddsubpd %%ymm3, %%ymm5, %%ymm5 \n\t" " \n\t" " \n\t" "vpermilpd $0x5, %%ymm8, %%ymm3 \n\t" "vmulpd %%ymm0, %%ymm8, %%ymm8 \n\t" "vmulpd %%ymm1, %%ymm3, %%ymm3 \n\t" "vaddsubpd %%ymm3, %%ymm8, %%ymm8 \n\t" " \n\t" "vpermilpd $0x5, %%ymm9, %%ymm3 \n\t" "vmulpd %%ymm0, %%ymm9, %%ymm9 \n\t" "vmulpd %%ymm1, %%ymm3, %%ymm3 \n\t" "vaddsubpd %%ymm3, %%ymm9, %%ymm9 \n\t" " \n\t" " \n\t" "vpermilpd $0x5, %%ymm12, %%ymm3 \n\t" "vmulpd %%ymm0, %%ymm12, %%ymm12 \n\t" "vmulpd %%ymm1, %%ymm3, %%ymm3 \n\t" "vaddsubpd %%ymm3, %%ymm12, %%ymm12 \n\t" " \n\t" "vpermilpd $0x5, %%ymm13, %%ymm3 \n\t" "vmulpd %%ymm0, %%ymm13, %%ymm13 \n\t" "vmulpd %%ymm1, %%ymm3, %%ymm3 \n\t" "vaddsubpd %%ymm3, %%ymm13, %%ymm13 \n\t" " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" "movq %5, %%rbx \n\t" // load address of beta "vbroadcastsd (%%rbx), %%ymm1 \n\t" // load beta_r and duplicate "vbroadcastsd 8(%%rbx), %%ymm2 \n\t" // load beta_i and duplicate " \n\t" " \n\t" " \n\t" " \n\t" "movq %8, %%rsi \n\t" // load cs_c "leaq (,%%rsi,8), %%rsi \n\t" // rsi = cs_c * sizeof(dcomplex) "leaq (,%%rsi,2), %%rsi \n\t" "leaq (,%%rsi,2), %%rdx \n\t" // rdx = 2*cs_c; " \n\t" " \n\t" " \n\t" " \n\t" // now avoid loading C if beta == 0 "vxorpd %%ymm0, %%ymm0, %%ymm0 \n\t" // set ymm0 to zero. "vucomisd %%xmm0, %%xmm1 \n\t" // set ZF if beta_r == 0. "sete %%r8b \n\t" // r8b = ( ZF == 1 ? 1 : 0 ); "vucomisd %%xmm0, %%xmm2 \n\t" // set ZF if beta_i == 0. "sete %%r9b \n\t" // r9b = ( ZF == 1 ? 1 : 0 ); "andb %%r8b, %%r9b \n\t" // set ZF if r8b & r9b == 1. "jne .ZBETAZERO \n\t" // if ZF = 1, jump to beta == 0 case " \n\t" " \n\t" "cmpq $16, %%rsi \n\t" // set ZF if (16*cs_c) == 16. "jz .ZROWSTORED \n\t" // jump to row storage case " \n\t" " \n\t" " \n\t" ".ZGENSTORED: \n\t" " \n\t" " \n\t" ZGEMM_INPUT_SCALE_GS_BETA_NZ "vaddpd %%ymm4, %%ymm0, %%ymm0 \n\t" ZGEMM_OUTPUT_GS "addq %%rdx, %%rcx \n\t" // c += 2*cs_c; " \n\t" " \n\t" ZGEMM_INPUT_SCALE_GS_BETA_NZ "vaddpd %%ymm5, %%ymm0, %%ymm0 \n\t" ZGEMM_OUTPUT_GS "movq %%r11, %%rcx \n\t" // rcx = c + 1*rs_c " \n\t" " \n\t" " \n\t" ZGEMM_INPUT_SCALE_GS_BETA_NZ "vaddpd %%ymm8, %%ymm0, %%ymm0 \n\t" ZGEMM_OUTPUT_GS "addq %%rdx, %%rcx \n\t" // c += 2*cs_c; " \n\t" " \n\t" ZGEMM_INPUT_SCALE_GS_BETA_NZ "vaddpd %%ymm9, %%ymm0, %%ymm0 \n\t" ZGEMM_OUTPUT_GS "movq %%r12, %%rcx \n\t" // rcx = c + 2*rs_c " \n\t" " \n\t" " \n\t" ZGEMM_INPUT_SCALE_GS_BETA_NZ "vaddpd %%ymm12, %%ymm0, %%ymm0 \n\t" ZGEMM_OUTPUT_GS "addq %%rdx, %%rcx \n\t" // c += 2*cs_c; " \n\t" " \n\t" ZGEMM_INPUT_SCALE_GS_BETA_NZ "vaddpd %%ymm13, %%ymm0, %%ymm0 \n\t" ZGEMM_OUTPUT_GS " \n\t" " \n\t" " \n\t" "jmp .ZDONE \n\t" // jump to end. " \n\t" " \n\t" " \n\t" ".ZROWSTORED: \n\t" " \n\t" " \n\t" ZGEMM_INPUT_SCALE_RS_BETA_NZ "vaddpd %%ymm4, %%ymm0, %%ymm0 \n\t" ZGEMM_OUTPUT_RS "addq %%rdx, %%rcx \n\t" // c += 2*cs_c; " \n\t" " \n\t" ZGEMM_INPUT_SCALE_RS_BETA_NZ "vaddpd %%ymm5, %%ymm0, %%ymm0 \n\t" ZGEMM_OUTPUT_RS "movq %%r11, %%rcx \n\t" // rcx = c + 1*rs_c " \n\t" " \n\t" " \n\t" ZGEMM_INPUT_SCALE_RS_BETA_NZ "vaddpd %%ymm8, %%ymm0, %%ymm0 \n\t" ZGEMM_OUTPUT_RS "addq %%rdx, %%rcx \n\t" // c += 2*cs_c; " \n\t" " \n\t" ZGEMM_INPUT_SCALE_RS_BETA_NZ "vaddpd %%ymm9, %%ymm0, %%ymm0 \n\t" ZGEMM_OUTPUT_RS "movq %%r12, %%rcx \n\t" // rcx = c + 2*rs_c " \n\t" " \n\t" " \n\t" ZGEMM_INPUT_SCALE_RS_BETA_NZ "vaddpd %%ymm12, %%ymm0, %%ymm0 \n\t" ZGEMM_OUTPUT_RS "addq %%rdx, %%rcx \n\t" // c += 2*cs_c; " \n\t" " \n\t" ZGEMM_INPUT_SCALE_RS_BETA_NZ "vaddpd %%ymm13, %%ymm0, %%ymm0 \n\t" ZGEMM_OUTPUT_RS " \n\t" " \n\t" " \n\t" "jmp .ZDONE \n\t" // jump to end. " \n\t" " \n\t" " \n\t" ".ZBETAZERO: \n\t" " \n\t" "cmpq $16, %%rsi \n\t" // set ZF if (16*cs_c) == 16. "jz .ZROWSTORBZ \n\t" // jump to row storage case " \n\t" " \n\t" " \n\t" ".ZGENSTORBZ: \n\t" " \n\t" " \n\t" "vmovapd %%ymm4, %%ymm0 \n\t" ZGEMM_OUTPUT_GS "addq %%rdx, %%rcx \n\t" // c += 2*cs_c; " \n\t" " \n\t" "vmovapd %%ymm5, %%ymm0 \n\t" ZGEMM_OUTPUT_GS "movq %%r11, %%rcx \n\t" // rcx = c + 1*rs_c " \n\t" " \n\t" " \n\t" "vmovapd %%ymm8, %%ymm0 \n\t" ZGEMM_OUTPUT_GS "addq %%rdx, %%rcx \n\t" // c += 2*cs_c; " \n\t" " \n\t" "vmovapd %%ymm9, %%ymm0 \n\t" ZGEMM_OUTPUT_GS "movq %%r12, %%rcx \n\t" // rcx = c + 2*rs_c " \n\t" " \n\t" " \n\t" "vmovapd %%ymm12, %%ymm0 \n\t" ZGEMM_OUTPUT_GS "addq %%rdx, %%rcx \n\t" // c += 2*cs_c; " \n\t" " \n\t" "vmovapd %%ymm13, %%ymm0 \n\t" ZGEMM_OUTPUT_GS " \n\t" " \n\t" " \n\t" "jmp .ZDONE \n\t" // jump to end. " \n\t" " \n\t" " \n\t" ".ZROWSTORBZ: \n\t" " \n\t" " \n\t" "vmovupd %%ymm4, (%%rcx) \n\t" "vmovupd %%ymm5, (%%rcx,%%rdx,1) \n\t" " \n\t" "vmovupd %%ymm8, (%%r11) \n\t" "vmovupd %%ymm9, (%%r11,%%rdx,1) \n\t" " \n\t" "vmovupd %%ymm12, (%%r12) \n\t" "vmovupd %%ymm13, (%%r12,%%rdx,1) \n\t" " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" ".ZDONE: \n\t" " \n\t" "vzeroupper \n\t" " \n\t" : // output operands (none) : // input operands "m" (k_iter), // 0 "m" (k_left), // 1 "m" (a), // 2 "m" (b), // 3 "m" (alpha), // 4 "m" (beta), // 5 "m" (c), // 6 "m" (rs_c), // 7 "m" (cs_c)/*, // 8 "m" (b_next), // 9 "m" (a_next)*/ // 10 : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ); } blis-0.9.0/kernels/haswell/3/old/bli_gemm_haswell_asm_d8x6.c000066400000000000000000003426731422157504600236670ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define SGEMM_INPUT_GS_BETA_NZ \ "vmovlps (%%rcx ), %%xmm0, %%xmm0 \n\t" \ "vmovhps (%%rcx,%%rsi,1), %%xmm0, %%xmm0 \n\t" \ "vmovlps (%%rcx,%%rsi,2), %%xmm1, %%xmm1 \n\t" \ "vmovhps (%%rcx,%%r13 ), %%xmm1, %%xmm1 \n\t" \ "vshufps $0x88, %%xmm1, %%xmm0, %%xmm0 \n\t" \ "vmovlps (%%rcx,%%rsi,4), %%xmm2, %%xmm2 \n\t" \ "vmovhps (%%rcx,%%r15 ), %%xmm2, %%xmm2 \n\t" \ /* We can't use vmovhps for loading the last element becauase that might result in reading beyond valid memory. (vmov[lh]psd load pairs of adjacent floats at a time.) So we need to use vmovss instead. But since we're limited to using ymm0 through ymm2 (ymm3 contains beta and ymm4 through ymm15 contain the microtile) and due to the way vmovss zeros out all bits above 31, we have to load element 7 before element 6. */ \ "vmovss (%%rcx,%%r10 ), %%xmm1 \n\t" \ "vpermilps $0xcf, %%xmm1, %%xmm1 \n\t" \ "vmovlps (%%rcx,%%r13,2), %%xmm1, %%xmm1 \n\t" \ /*"vmovhps (%%rcx,%%r10 ), %%xmm1, %%xmm1 \n\t"*/ \ "vshufps $0x88, %%xmm1, %%xmm2, %%xmm2 \n\t" \ "vperm2f128 $0x20, %%ymm2, %%ymm0, %%ymm0 \n\t" #define SGEMM_OUTPUT_GS_BETA_NZ \ "vextractf128 $1, %%ymm0, %%xmm2 \n\t" \ "vmovss %%xmm0, (%%rcx ) \n\t" \ "vpermilps $0x39, %%xmm0, %%xmm1 \n\t" \ "vmovss %%xmm1, (%%rcx,%%rsi,1) \n\t" \ "vpermilps $0x39, %%xmm1, %%xmm0 \n\t" \ "vmovss %%xmm0, (%%rcx,%%rsi,2) \n\t" \ "vpermilps $0x39, %%xmm0, %%xmm1 \n\t" \ "vmovss %%xmm1, (%%rcx,%%r13 ) \n\t" \ "vmovss %%xmm2, (%%rcx,%%rsi,4) \n\t" \ "vpermilps $0x39, %%xmm2, %%xmm1 \n\t" \ "vmovss %%xmm1, (%%rcx,%%r15 ) \n\t" \ "vpermilps $0x39, %%xmm1, %%xmm2 \n\t" \ "vmovss %%xmm2, (%%rcx,%%r13,2) \n\t" \ "vpermilps $0x39, %%xmm2, %%xmm1 \n\t" \ "vmovss %%xmm1, (%%rcx,%%r10 ) \n\t" void bli_sgemm_haswell_asm_16x6 ( dim_t k0, float* restrict alpha, float* restrict a, float* restrict b, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; __asm__ volatile ( " \n\t" "vzeroall \n\t" // zero all xmm/ymm registers. " \n\t" " \n\t" "movq %2, %%rax \n\t" // load address of a. "movq %3, %%rbx \n\t" // load address of b. //"movq %9, %%r15 \n\t" // load address of b_next. " \n\t" "addq $32 * 4, %%rax \n\t" " \n\t" // initialize loop by pre-loading "vmovaps -4 * 32(%%rax), %%ymm0 \n\t" "vmovaps -3 * 32(%%rax), %%ymm1 \n\t" " \n\t" "movq %6, %%rcx \n\t" // load address of c "movq %8, %%rdi \n\t" // load cs_c "leaq (,%%rdi,4), %%rdi \n\t" // cs_c *= sizeof(float) " \n\t" "leaq (%%rdi,%%rdi,2), %%r13 \n\t" // r13 = 3*cs_c; "leaq (%%rcx,%%r13,1), %%rdx \n\t" // rdx = c + 3*cs_c; "prefetcht0 7 * 8(%%rcx) \n\t" // prefetch c + 0*cs_c "prefetcht0 7 * 8(%%rcx,%%rdi) \n\t" // prefetch c + 1*cs_c "prefetcht0 7 * 8(%%rcx,%%rdi,2) \n\t" // prefetch c + 2*cs_c "prefetcht0 7 * 8(%%rdx) \n\t" // prefetch c + 3*cs_c "prefetcht0 7 * 8(%%rdx,%%rdi) \n\t" // prefetch c + 4*cs_c "prefetcht0 7 * 8(%%rdx,%%rdi,2) \n\t" // prefetch c + 5*cs_c " \n\t" " \n\t" " \n\t" " \n\t" "movq %0, %%rsi \n\t" // i = k_iter; "testq %%rsi, %%rsi \n\t" // check i via logical AND. "je .SCONSIDKLEFT \n\t" // if i == 0, jump to code that " \n\t" // contains the k_left loop. " \n\t" " \n\t" ".SLOOPKITER: \n\t" // MAIN LOOP " \n\t" " \n\t" " \n\t" // iteration 0 "prefetcht0 128 * 4(%%rax) \n\t" " \n\t" "vbroadcastss 0 * 4(%%rbx), %%ymm2 \n\t" "vbroadcastss 1 * 4(%%rbx), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm2, %%ymm4 \n\t" "vfmadd231ps %%ymm1, %%ymm2, %%ymm5 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm6 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm7 \n\t" " \n\t" "vbroadcastss 2 * 4(%%rbx), %%ymm2 \n\t" "vbroadcastss 3 * 4(%%rbx), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm2, %%ymm8 \n\t" "vfmadd231ps %%ymm1, %%ymm2, %%ymm9 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm10 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm11 \n\t" " \n\t" "vbroadcastss 4 * 4(%%rbx), %%ymm2 \n\t" "vbroadcastss 5 * 4(%%rbx), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm2, %%ymm12 \n\t" "vfmadd231ps %%ymm1, %%ymm2, %%ymm13 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm14 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm15 \n\t" " \n\t" "vmovaps -2 * 32(%%rax), %%ymm0 \n\t" "vmovaps -1 * 32(%%rax), %%ymm1 \n\t" " \n\t" " \n\t" // iteration 1 "vbroadcastss 6 * 4(%%rbx), %%ymm2 \n\t" "vbroadcastss 7 * 4(%%rbx), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm2, %%ymm4 \n\t" "vfmadd231ps %%ymm1, %%ymm2, %%ymm5 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm6 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm7 \n\t" " \n\t" "vbroadcastss 8 * 4(%%rbx), %%ymm2 \n\t" "vbroadcastss 9 * 4(%%rbx), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm2, %%ymm8 \n\t" "vfmadd231ps %%ymm1, %%ymm2, %%ymm9 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm10 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm11 \n\t" " \n\t" "vbroadcastss 10 * 4(%%rbx), %%ymm2 \n\t" "vbroadcastss 11 * 4(%%rbx), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm2, %%ymm12 \n\t" "vfmadd231ps %%ymm1, %%ymm2, %%ymm13 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm14 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm15 \n\t" " \n\t" "vmovaps 0 * 32(%%rax), %%ymm0 \n\t" "vmovaps 1 * 32(%%rax), %%ymm1 \n\t" " \n\t" " \n\t" // iteration 2 "prefetcht0 152 * 4(%%rax) \n\t" " \n\t" "vbroadcastss 12 * 4(%%rbx), %%ymm2 \n\t" "vbroadcastss 13 * 4(%%rbx), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm2, %%ymm4 \n\t" "vfmadd231ps %%ymm1, %%ymm2, %%ymm5 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm6 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm7 \n\t" " \n\t" "vbroadcastss 14 * 4(%%rbx), %%ymm2 \n\t" "vbroadcastss 15 * 4(%%rbx), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm2, %%ymm8 \n\t" "vfmadd231ps %%ymm1, %%ymm2, %%ymm9 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm10 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm11 \n\t" " \n\t" "vbroadcastss 16 * 4(%%rbx), %%ymm2 \n\t" "vbroadcastss 17 * 4(%%rbx), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm2, %%ymm12 \n\t" "vfmadd231ps %%ymm1, %%ymm2, %%ymm13 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm14 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm15 \n\t" " \n\t" "vmovaps 2 * 32(%%rax), %%ymm0 \n\t" "vmovaps 3 * 32(%%rax), %%ymm1 \n\t" " \n\t" " \n\t" // iteration 3 "vbroadcastss 18 * 4(%%rbx), %%ymm2 \n\t" "vbroadcastss 19 * 4(%%rbx), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm2, %%ymm4 \n\t" "vfmadd231ps %%ymm1, %%ymm2, %%ymm5 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm6 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm7 \n\t" " \n\t" "vbroadcastss 20 * 4(%%rbx), %%ymm2 \n\t" "vbroadcastss 21 * 4(%%rbx), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm2, %%ymm8 \n\t" "vfmadd231ps %%ymm1, %%ymm2, %%ymm9 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm10 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm11 \n\t" " \n\t" "vbroadcastss 22 * 4(%%rbx), %%ymm2 \n\t" "vbroadcastss 23 * 4(%%rbx), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm2, %%ymm12 \n\t" "vfmadd231ps %%ymm1, %%ymm2, %%ymm13 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm14 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm15 \n\t" " \n\t" "addq $4 * 16 * 4, %%rax \n\t" // a += 4*16 (unroll x mr) "addq $4 * 6 * 4, %%rbx \n\t" // b += 4*6 (unroll x nr) " \n\t" "vmovaps -4 * 32(%%rax), %%ymm0 \n\t" "vmovaps -3 * 32(%%rax), %%ymm1 \n\t" " \n\t" " \n\t" "decq %%rsi \n\t" // i -= 1; "jne .SLOOPKITER \n\t" // iterate again if i != 0. " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" ".SCONSIDKLEFT: \n\t" " \n\t" "movq %1, %%rsi \n\t" // i = k_left; "testq %%rsi, %%rsi \n\t" // check i via logical AND. "je .SPOSTACCUM \n\t" // if i == 0, we're done; jump to end. " \n\t" // else, we prepare to enter k_left loop. " \n\t" " \n\t" ".SLOOPKLEFT: \n\t" // EDGE LOOP " \n\t" "prefetcht0 128 * 4(%%rax) \n\t" " \n\t" "vbroadcastss 0 * 4(%%rbx), %%ymm2 \n\t" "vbroadcastss 1 * 4(%%rbx), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm2, %%ymm4 \n\t" "vfmadd231ps %%ymm1, %%ymm2, %%ymm5 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm6 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm7 \n\t" " \n\t" "vbroadcastss 2 * 4(%%rbx), %%ymm2 \n\t" "vbroadcastss 3 * 4(%%rbx), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm2, %%ymm8 \n\t" "vfmadd231ps %%ymm1, %%ymm2, %%ymm9 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm10 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm11 \n\t" " \n\t" "vbroadcastss 4 * 4(%%rbx), %%ymm2 \n\t" "vbroadcastss 5 * 4(%%rbx), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm2, %%ymm12 \n\t" "vfmadd231ps %%ymm1, %%ymm2, %%ymm13 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm14 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm15 \n\t" " \n\t" "addq $1 * 16 * 4, %%rax \n\t" // a += 1*16 (unroll x mr) "addq $1 * 6 * 4, %%rbx \n\t" // b += 1*6 (unroll x nr) " \n\t" "vmovaps -4 * 32(%%rax), %%ymm0 \n\t" "vmovaps -3 * 32(%%rax), %%ymm1 \n\t" " \n\t" " \n\t" "decq %%rsi \n\t" // i -= 1; "jne .SLOOPKLEFT \n\t" // iterate again if i != 0. " \n\t" " \n\t" " \n\t" ".SPOSTACCUM: \n\t" " \n\t" " \n\t" " \n\t" " \n\t" "movq %4, %%rax \n\t" // load address of alpha "movq %5, %%rbx \n\t" // load address of beta "vbroadcastss (%%rax), %%ymm0 \n\t" // load alpha and duplicate "vbroadcastss (%%rbx), %%ymm3 \n\t" // load beta and duplicate " \n\t" "vmulps %%ymm0, %%ymm4, %%ymm4 \n\t" // scale by alpha "vmulps %%ymm0, %%ymm5, %%ymm5 \n\t" "vmulps %%ymm0, %%ymm6, %%ymm6 \n\t" "vmulps %%ymm0, %%ymm7, %%ymm7 \n\t" "vmulps %%ymm0, %%ymm8, %%ymm8 \n\t" "vmulps %%ymm0, %%ymm9, %%ymm9 \n\t" "vmulps %%ymm0, %%ymm10, %%ymm10 \n\t" "vmulps %%ymm0, %%ymm11, %%ymm11 \n\t" "vmulps %%ymm0, %%ymm12, %%ymm12 \n\t" "vmulps %%ymm0, %%ymm13, %%ymm13 \n\t" "vmulps %%ymm0, %%ymm14, %%ymm14 \n\t" "vmulps %%ymm0, %%ymm15, %%ymm15 \n\t" " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" "movq %7, %%rsi \n\t" // load rs_c "leaq (,%%rsi,4), %%rsi \n\t" // rsi = rs_c * sizeof(float) " \n\t" "leaq (%%rcx,%%rsi,8), %%rdx \n\t" // load address of c + 8*rs_c; " \n\t" "leaq (%%rsi,%%rsi,2), %%r13 \n\t" // r13 = 3*rs_c; "leaq (%%rsi,%%rsi,4), %%r15 \n\t" // r15 = 5*rs_c; "leaq (%%r13,%%rsi,4), %%r10 \n\t" // r10 = 7*rs_c; " \n\t" " \n\t" " \n\t" // now avoid loading C if beta == 0 " \n\t" "vxorps %%ymm0, %%ymm0, %%ymm0 \n\t" // set ymm0 to zero. "vucomiss %%xmm0, %%xmm3 \n\t" // set ZF if beta == 0. "je .SBETAZERO \n\t" // if ZF = 1, jump to beta == 0 case " \n\t" " \n\t" "cmpq $4, %%rsi \n\t" // set ZF if (4*rs_c) == 4. "jz .SCOLSTORED \n\t" // jump to column storage case " \n\t" " \n\t" " \n\t" ".SGENSTORED: \n\t" " \n\t" " \n\t" SGEMM_INPUT_GS_BETA_NZ "vfmadd213ps %%ymm4, %%ymm3, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" SGEMM_INPUT_GS_BETA_NZ "vfmadd213ps %%ymm6, %%ymm3, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" SGEMM_INPUT_GS_BETA_NZ "vfmadd213ps %%ymm8, %%ymm3, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" SGEMM_INPUT_GS_BETA_NZ "vfmadd213ps %%ymm10, %%ymm3, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" SGEMM_INPUT_GS_BETA_NZ "vfmadd213ps %%ymm12, %%ymm3, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" SGEMM_INPUT_GS_BETA_NZ "vfmadd213ps %%ymm14, %%ymm3, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ //"addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" "movq %%rdx, %%rcx \n\t" // rcx = c + 8*rs_c " \n\t" " \n\t" SGEMM_INPUT_GS_BETA_NZ "vfmadd213ps %%ymm5, %%ymm3, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" SGEMM_INPUT_GS_BETA_NZ "vfmadd213ps %%ymm7, %%ymm3, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" SGEMM_INPUT_GS_BETA_NZ "vfmadd213ps %%ymm9, %%ymm3, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" SGEMM_INPUT_GS_BETA_NZ "vfmadd213ps %%ymm11, %%ymm3, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" SGEMM_INPUT_GS_BETA_NZ "vfmadd213ps %%ymm13, %%ymm3, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" SGEMM_INPUT_GS_BETA_NZ "vfmadd213ps %%ymm15, %%ymm3, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ //"addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" " \n\t" "jmp .SDONE \n\t" // jump to end. " \n\t" " \n\t" " \n\t" ".SCOLSTORED: \n\t" " \n\t" " \n\t" "vfmadd231ps (%%rcx), %%ymm3, %%ymm4 \n\t" "vmovups %%ymm4, (%%rcx) \n\t" "addq %%rdi, %%rcx \n\t" "vfmadd231ps (%%rdx), %%ymm3, %%ymm5 \n\t" "vmovups %%ymm5, (%%rdx) \n\t" "addq %%rdi, %%rdx \n\t" " \n\t" " \n\t" "vfmadd231ps (%%rcx), %%ymm3, %%ymm6 \n\t" "vmovups %%ymm6, (%%rcx) \n\t" "addq %%rdi, %%rcx \n\t" "vfmadd231ps (%%rdx), %%ymm3, %%ymm7 \n\t" "vmovups %%ymm7, (%%rdx) \n\t" "addq %%rdi, %%rdx \n\t" " \n\t" " \n\t" "vfmadd231ps (%%rcx), %%ymm3, %%ymm8 \n\t" "vmovups %%ymm8, (%%rcx) \n\t" "addq %%rdi, %%rcx \n\t" "vfmadd231ps (%%rdx), %%ymm3, %%ymm9 \n\t" "vmovups %%ymm9, (%%rdx) \n\t" "addq %%rdi, %%rdx \n\t" " \n\t" " \n\t" "vfmadd231ps (%%rcx), %%ymm3, %%ymm10 \n\t" "vmovups %%ymm10, (%%rcx) \n\t" "addq %%rdi, %%rcx \n\t" "vfmadd231ps (%%rdx), %%ymm3, %%ymm11 \n\t" "vmovups %%ymm11, (%%rdx) \n\t" "addq %%rdi, %%rdx \n\t" " \n\t" " \n\t" "vfmadd231ps (%%rcx), %%ymm3, %%ymm12 \n\t" "vmovups %%ymm12, (%%rcx) \n\t" "addq %%rdi, %%rcx \n\t" "vfmadd231ps (%%rdx), %%ymm3, %%ymm13 \n\t" "vmovups %%ymm13, (%%rdx) \n\t" "addq %%rdi, %%rdx \n\t" " \n\t" " \n\t" "vfmadd231ps (%%rcx), %%ymm3, %%ymm14 \n\t" "vmovups %%ymm14, (%%rcx) \n\t" //"addq %%rdi, %%rcx \n\t" "vfmadd231ps (%%rdx), %%ymm3, %%ymm15 \n\t" "vmovups %%ymm15, (%%rdx) \n\t" //"addq %%rdi, %%rdx \n\t" " \n\t" " \n\t" " \n\t" " \n\t" "jmp .SDONE \n\t" // jump to end. " \n\t" " \n\t" " \n\t" ".SBETAZERO: \n\t" " \n\t" "cmpq $4, %%rsi \n\t" // set ZF if (4*rs_c) == 4. "jz .SCOLSTORBZ \n\t" // jump to column storage case " \n\t" " \n\t" " \n\t" ".SGENSTORBZ: \n\t" " \n\t" " \n\t" "vmovaps %%ymm4, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" "vmovaps %%ymm6, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" "vmovaps %%ymm8, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" "vmovaps %%ymm10, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" "vmovaps %%ymm12, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" "vmovaps %%ymm14, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ //"addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" "movq %%rdx, %%rcx \n\t" // rcx = c + 8*rs_c " \n\t" " \n\t" "vmovaps %%ymm5, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" "vmovaps %%ymm7, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" "vmovaps %%ymm9, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" "vmovaps %%ymm11, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" "vmovaps %%ymm13, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" "vmovaps %%ymm15, %%ymm0 \n\t" SGEMM_OUTPUT_GS_BETA_NZ //"addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" " \n\t" "jmp .SDONE \n\t" // jump to end. " \n\t" " \n\t" " \n\t" ".SCOLSTORBZ: \n\t" " \n\t" " \n\t" "vmovups %%ymm4, (%%rcx) \n\t" "addq %%rdi, %%rcx \n\t" "vmovups %%ymm5, (%%rdx) \n\t" "addq %%rdi, %%rdx \n\t" " \n\t" "vmovups %%ymm6, (%%rcx) \n\t" "addq %%rdi, %%rcx \n\t" "vmovups %%ymm7, (%%rdx) \n\t" "addq %%rdi, %%rdx \n\t" " \n\t" " \n\t" "vmovups %%ymm8, (%%rcx) \n\t" "addq %%rdi, %%rcx \n\t" "vmovups %%ymm9, (%%rdx) \n\t" "addq %%rdi, %%rdx \n\t" " \n\t" " \n\t" "vmovups %%ymm10, (%%rcx) \n\t" "addq %%rdi, %%rcx \n\t" "vmovups %%ymm11, (%%rdx) \n\t" "addq %%rdi, %%rdx \n\t" " \n\t" " \n\t" "vmovups %%ymm12, (%%rcx) \n\t" "addq %%rdi, %%rcx \n\t" "vmovups %%ymm13, (%%rdx) \n\t" "addq %%rdi, %%rdx \n\t" " \n\t" " \n\t" "vmovups %%ymm14, (%%rcx) \n\t" //"addq %%rdi, %%rcx \n\t" "vmovups %%ymm15, (%%rdx) \n\t" //"addq %%rdi, %%rdx \n\t" " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" ".SDONE: \n\t" " \n\t" "vzeroupper \n\t" " \n\t" : // output operands (none) : // input operands "m" (k_iter), // 0 "m" (k_left), // 1 "m" (a), // 2 "m" (b), // 3 "m" (alpha), // 4 "m" (beta), // 5 "m" (c), // 6 "m" (rs_c), // 7 "m" (cs_c)/*, // 8 "m" (b_next), // 9 "m" (a_next)*/ // 10 : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ); } #define DGEMM_INPUT_GS_BETA_NZ \ "vmovlpd (%%rcx ), %%xmm0, %%xmm0 \n\t" \ "vmovhpd (%%rcx,%%rsi,1), %%xmm0, %%xmm0 \n\t" \ "vmovlpd (%%rcx,%%rsi,2), %%xmm1, %%xmm1 \n\t" \ "vmovhpd (%%rcx,%%r13 ), %%xmm1, %%xmm1 \n\t" \ "vperm2f128 $0x20, %%ymm1, %%ymm0, %%ymm0 \n\t" /*\ "vmovlpd (%%rcx,%%rsi,4), %%xmm2, %%xmm2 \n\t" \ "vmovhpd (%%rcx,%%r15 ), %%xmm2, %%xmm2 \n\t" \ "vmovlpd (%%rcx,%%r13,2), %%xmm1, %%xmm1 \n\t" \ "vmovhpd (%%rcx,%%r10 ), %%xmm1, %%xmm1 \n\t" \ "vperm2f128 $0x20, %%ymm1, %%ymm2, %%ymm2 \n\t"*/ #define DGEMM_OUTPUT_GS_BETA_NZ \ "vextractf128 $1, %%ymm0, %%xmm1 \n\t" \ "vmovlpd %%xmm0, (%%rcx ) \n\t" \ "vmovhpd %%xmm0, (%%rcx,%%rsi ) \n\t" \ "vmovlpd %%xmm1, (%%rcx,%%rsi,2) \n\t" \ "vmovhpd %%xmm1, (%%rcx,%%r13 ) \n\t" /*\ "vextractf128 $1, %%ymm2, %%xmm1 \n\t" \ "vmovlpd %%xmm2, (%%rcx,%%rsi,4) \n\t" \ "vmovhpd %%xmm2, (%%rcx,%%r15 ) \n\t" \ "vmovlpd %%xmm1, (%%rcx,%%r13,2) \n\t" \ "vmovhpd %%xmm1, (%%rcx,%%r10 ) \n\t"*/ void bli_dgemm_haswell_asm_8x6 ( dim_t k0, double* restrict alpha, double* restrict a, double* restrict b, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; __asm__ volatile ( " \n\t" "vzeroall \n\t" // zero all xmm/ymm registers. " \n\t" " \n\t" "movq %2, %%rax \n\t" // load address of a. "movq %3, %%rbx \n\t" // load address of b. //"movq %9, %%r15 \n\t" // load address of b_next. " \n\t" "addq $32 * 4, %%rax \n\t" " \n\t" // initialize loop by pre-loading "vmovapd -4 * 32(%%rax), %%ymm0 \n\t" "vmovapd -3 * 32(%%rax), %%ymm1 \n\t" " \n\t" "movq %6, %%rcx \n\t" // load address of c "movq %8, %%rdi \n\t" // load cs_c "leaq (,%%rdi,8), %%rdi \n\t" // cs_c *= sizeof(double) " \n\t" "leaq (%%rdi,%%rdi,2), %%r13 \n\t" // r13 = 3*cs_c; "leaq (%%rcx,%%r13,1), %%rdx \n\t" // rdx = c + 3*cs_c; "prefetcht0 7 * 8(%%rcx) \n\t" // prefetch c + 0*cs_c "prefetcht0 7 * 8(%%rcx,%%rdi) \n\t" // prefetch c + 1*cs_c "prefetcht0 7 * 8(%%rcx,%%rdi,2) \n\t" // prefetch c + 2*cs_c "prefetcht0 7 * 8(%%rdx) \n\t" // prefetch c + 3*cs_c "prefetcht0 7 * 8(%%rdx,%%rdi) \n\t" // prefetch c + 4*cs_c "prefetcht0 7 * 8(%%rdx,%%rdi,2) \n\t" // prefetch c + 5*cs_c " \n\t" " \n\t" " \n\t" " \n\t" "movq %0, %%rsi \n\t" // i = k_iter; "testq %%rsi, %%rsi \n\t" // check i via logical AND. "je .DCONSIDKLEFT \n\t" // if i == 0, jump to code that " \n\t" // contains the k_left loop. " \n\t" " \n\t" ".DLOOPKITER: \n\t" // MAIN LOOP " \n\t" " \n\t" " \n\t" // iteration 0 "prefetcht0 64 * 8(%%rax) \n\t" " \n\t" "vbroadcastsd 0 * 8(%%rbx), %%ymm2 \n\t" "vbroadcastsd 1 * 8(%%rbx), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm2, %%ymm4 \n\t" "vfmadd231pd %%ymm1, %%ymm2, %%ymm5 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm6 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm7 \n\t" " \n\t" "vbroadcastsd 2 * 8(%%rbx), %%ymm2 \n\t" "vbroadcastsd 3 * 8(%%rbx), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm2, %%ymm8 \n\t" "vfmadd231pd %%ymm1, %%ymm2, %%ymm9 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm10 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm11 \n\t" " \n\t" "vbroadcastsd 4 * 8(%%rbx), %%ymm2 \n\t" "vbroadcastsd 5 * 8(%%rbx), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm2, %%ymm12 \n\t" "vfmadd231pd %%ymm1, %%ymm2, %%ymm13 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm14 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm15 \n\t" " \n\t" "vmovapd -2 * 32(%%rax), %%ymm0 \n\t" "vmovapd -1 * 32(%%rax), %%ymm1 \n\t" " \n\t" " \n\t" // iteration 1 "vbroadcastsd 6 * 8(%%rbx), %%ymm2 \n\t" "vbroadcastsd 7 * 8(%%rbx), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm2, %%ymm4 \n\t" "vfmadd231pd %%ymm1, %%ymm2, %%ymm5 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm6 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm7 \n\t" " \n\t" "vbroadcastsd 8 * 8(%%rbx), %%ymm2 \n\t" "vbroadcastsd 9 * 8(%%rbx), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm2, %%ymm8 \n\t" "vfmadd231pd %%ymm1, %%ymm2, %%ymm9 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm10 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm11 \n\t" " \n\t" "vbroadcastsd 10 * 8(%%rbx), %%ymm2 \n\t" "vbroadcastsd 11 * 8(%%rbx), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm2, %%ymm12 \n\t" "vfmadd231pd %%ymm1, %%ymm2, %%ymm13 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm14 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm15 \n\t" " \n\t" "vmovapd 0 * 32(%%rax), %%ymm0 \n\t" "vmovapd 1 * 32(%%rax), %%ymm1 \n\t" " \n\t" " \n\t" // iteration 2 "prefetcht0 76 * 8(%%rax) \n\t" " \n\t" "vbroadcastsd 12 * 8(%%rbx), %%ymm2 \n\t" "vbroadcastsd 13 * 8(%%rbx), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm2, %%ymm4 \n\t" "vfmadd231pd %%ymm1, %%ymm2, %%ymm5 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm6 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm7 \n\t" " \n\t" "vbroadcastsd 14 * 8(%%rbx), %%ymm2 \n\t" "vbroadcastsd 15 * 8(%%rbx), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm2, %%ymm8 \n\t" "vfmadd231pd %%ymm1, %%ymm2, %%ymm9 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm10 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm11 \n\t" " \n\t" "vbroadcastsd 16 * 8(%%rbx), %%ymm2 \n\t" "vbroadcastsd 17 * 8(%%rbx), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm2, %%ymm12 \n\t" "vfmadd231pd %%ymm1, %%ymm2, %%ymm13 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm14 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm15 \n\t" " \n\t" "vmovapd 2 * 32(%%rax), %%ymm0 \n\t" "vmovapd 3 * 32(%%rax), %%ymm1 \n\t" " \n\t" " \n\t" // iteration 3 "vbroadcastsd 18 * 8(%%rbx), %%ymm2 \n\t" "vbroadcastsd 19 * 8(%%rbx), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm2, %%ymm4 \n\t" "vfmadd231pd %%ymm1, %%ymm2, %%ymm5 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm6 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm7 \n\t" " \n\t" "vbroadcastsd 20 * 8(%%rbx), %%ymm2 \n\t" "vbroadcastsd 21 * 8(%%rbx), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm2, %%ymm8 \n\t" "vfmadd231pd %%ymm1, %%ymm2, %%ymm9 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm10 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm11 \n\t" " \n\t" "vbroadcastsd 22 * 8(%%rbx), %%ymm2 \n\t" "vbroadcastsd 23 * 8(%%rbx), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm2, %%ymm12 \n\t" "vfmadd231pd %%ymm1, %%ymm2, %%ymm13 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm14 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm15 \n\t" " \n\t" "addq $4 * 8 * 8, %%rax \n\t" // a += 4*8 (unroll x mr) "addq $4 * 6 * 8, %%rbx \n\t" // b += 4*6 (unroll x nr) " \n\t" "vmovapd -4 * 32(%%rax), %%ymm0 \n\t" "vmovapd -3 * 32(%%rax), %%ymm1 \n\t" " \n\t" " \n\t" "decq %%rsi \n\t" // i -= 1; "jne .DLOOPKITER \n\t" // iterate again if i != 0. " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" ".DCONSIDKLEFT: \n\t" " \n\t" "movq %1, %%rsi \n\t" // i = k_left; "testq %%rsi, %%rsi \n\t" // check i via logical AND. "je .DPOSTACCUM \n\t" // if i == 0, we're done; jump to end. " \n\t" // else, we prepare to enter k_left loop. " \n\t" " \n\t" ".DLOOPKLEFT: \n\t" // EDGE LOOP " \n\t" "prefetcht0 64 * 8(%%rax) \n\t" " \n\t" "vbroadcastsd 0 * 8(%%rbx), %%ymm2 \n\t" "vbroadcastsd 1 * 8(%%rbx), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm2, %%ymm4 \n\t" "vfmadd231pd %%ymm1, %%ymm2, %%ymm5 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm6 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm7 \n\t" " \n\t" "vbroadcastsd 2 * 8(%%rbx), %%ymm2 \n\t" "vbroadcastsd 3 * 8(%%rbx), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm2, %%ymm8 \n\t" "vfmadd231pd %%ymm1, %%ymm2, %%ymm9 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm10 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm11 \n\t" " \n\t" "vbroadcastsd 4 * 8(%%rbx), %%ymm2 \n\t" "vbroadcastsd 5 * 8(%%rbx), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm2, %%ymm12 \n\t" "vfmadd231pd %%ymm1, %%ymm2, %%ymm13 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm14 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm15 \n\t" " \n\t" "addq $1 * 8 * 8, %%rax \n\t" // a += 1*8 (unroll x mr) "addq $1 * 6 * 8, %%rbx \n\t" // b += 1*6 (unroll x nr) " \n\t" "vmovapd -4 * 32(%%rax), %%ymm0 \n\t" "vmovapd -3 * 32(%%rax), %%ymm1 \n\t" " \n\t" " \n\t" "decq %%rsi \n\t" // i -= 1; "jne .DLOOPKLEFT \n\t" // iterate again if i != 0. " \n\t" " \n\t" " \n\t" ".DPOSTACCUM: \n\t" " \n\t" " \n\t" " \n\t" " \n\t" "movq %4, %%rax \n\t" // load address of alpha "movq %5, %%rbx \n\t" // load address of beta "vbroadcastsd (%%rax), %%ymm0 \n\t" // load alpha and duplicate "vbroadcastsd (%%rbx), %%ymm3 \n\t" // load beta and duplicate " \n\t" "vmulpd %%ymm0, %%ymm4, %%ymm4 \n\t" // scale by alpha "vmulpd %%ymm0, %%ymm5, %%ymm5 \n\t" "vmulpd %%ymm0, %%ymm6, %%ymm6 \n\t" "vmulpd %%ymm0, %%ymm7, %%ymm7 \n\t" "vmulpd %%ymm0, %%ymm8, %%ymm8 \n\t" "vmulpd %%ymm0, %%ymm9, %%ymm9 \n\t" "vmulpd %%ymm0, %%ymm10, %%ymm10 \n\t" "vmulpd %%ymm0, %%ymm11, %%ymm11 \n\t" "vmulpd %%ymm0, %%ymm12, %%ymm12 \n\t" "vmulpd %%ymm0, %%ymm13, %%ymm13 \n\t" "vmulpd %%ymm0, %%ymm14, %%ymm14 \n\t" "vmulpd %%ymm0, %%ymm15, %%ymm15 \n\t" " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" "movq %7, %%rsi \n\t" // load rs_c "leaq (,%%rsi,8), %%rsi \n\t" // rsi = rs_c * sizeof(double) " \n\t" "leaq (%%rcx,%%rsi,4), %%rdx \n\t" // load address of c + 4*rs_c; " \n\t" "leaq (%%rsi,%%rsi,2), %%r13 \n\t" // r13 = 3*rs_c; //"leaq (%%rsi,%%rsi,4), %%r15 \n\t" // r15 = 5*rs_c; //"leaq (%%r13,%%rsi,4), %%r10 \n\t" // r10 = 7*rs_c; " \n\t" " \n\t" " \n\t" // now avoid loading C if beta == 0 " \n\t" "vxorpd %%ymm0, %%ymm0, %%ymm0 \n\t" // set ymm0 to zero. "vucomisd %%xmm0, %%xmm3 \n\t" // set ZF if beta == 0. "je .DBETAZERO \n\t" // if ZF = 1, jump to beta == 0 case " \n\t" " \n\t" "cmpq $8, %%rsi \n\t" // set ZF if (8*rs_c) == 8. "jz .DCOLSTORED \n\t" // jump to column storage case " \n\t" " \n\t" " \n\t" ".DGENSTORED: \n\t" " \n\t" " \n\t" DGEMM_INPUT_GS_BETA_NZ "vfmadd213pd %%ymm4, %%ymm3, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" DGEMM_INPUT_GS_BETA_NZ "vfmadd213pd %%ymm6, %%ymm3, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" DGEMM_INPUT_GS_BETA_NZ "vfmadd213pd %%ymm8, %%ymm3, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" DGEMM_INPUT_GS_BETA_NZ "vfmadd213pd %%ymm10, %%ymm3, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" DGEMM_INPUT_GS_BETA_NZ "vfmadd213pd %%ymm12, %%ymm3, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" DGEMM_INPUT_GS_BETA_NZ "vfmadd213pd %%ymm14, %%ymm3, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ //"addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" "movq %%rdx, %%rcx \n\t" // rcx = c + 4*rs_c " \n\t" " \n\t" DGEMM_INPUT_GS_BETA_NZ "vfmadd213pd %%ymm5, %%ymm3, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" DGEMM_INPUT_GS_BETA_NZ "vfmadd213pd %%ymm7, %%ymm3, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" DGEMM_INPUT_GS_BETA_NZ "vfmadd213pd %%ymm9, %%ymm3, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" DGEMM_INPUT_GS_BETA_NZ "vfmadd213pd %%ymm11, %%ymm3, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" DGEMM_INPUT_GS_BETA_NZ "vfmadd213pd %%ymm13, %%ymm3, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" DGEMM_INPUT_GS_BETA_NZ "vfmadd213pd %%ymm15, %%ymm3, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ //"addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" " \n\t" "jmp .DDONE \n\t" // jump to end. " \n\t" " \n\t" " \n\t" ".DCOLSTORED: \n\t" " \n\t" " \n\t" "vfmadd231pd (%%rcx), %%ymm3, %%ymm4 \n\t" "vmovupd %%ymm4, (%%rcx) \n\t" "addq %%rdi, %%rcx \n\t" "vfmadd231pd (%%rdx), %%ymm3, %%ymm5 \n\t" "vmovupd %%ymm5, (%%rdx) \n\t" "addq %%rdi, %%rdx \n\t" " \n\t" " \n\t" "vfmadd231pd (%%rcx), %%ymm3, %%ymm6 \n\t" "vmovupd %%ymm6, (%%rcx) \n\t" "addq %%rdi, %%rcx \n\t" "vfmadd231pd (%%rdx), %%ymm3, %%ymm7 \n\t" "vmovupd %%ymm7, (%%rdx) \n\t" "addq %%rdi, %%rdx \n\t" " \n\t" " \n\t" "vfmadd231pd (%%rcx), %%ymm3, %%ymm8 \n\t" "vmovupd %%ymm8, (%%rcx) \n\t" "addq %%rdi, %%rcx \n\t" "vfmadd231pd (%%rdx), %%ymm3, %%ymm9 \n\t" "vmovupd %%ymm9, (%%rdx) \n\t" "addq %%rdi, %%rdx \n\t" " \n\t" " \n\t" "vfmadd231pd (%%rcx), %%ymm3, %%ymm10 \n\t" "vmovupd %%ymm10, (%%rcx) \n\t" "addq %%rdi, %%rcx \n\t" "vfmadd231pd (%%rdx), %%ymm3, %%ymm11 \n\t" "vmovupd %%ymm11, (%%rdx) \n\t" "addq %%rdi, %%rdx \n\t" " \n\t" " \n\t" "vfmadd231pd (%%rcx), %%ymm3, %%ymm12 \n\t" "vmovupd %%ymm12, (%%rcx) \n\t" "addq %%rdi, %%rcx \n\t" "vfmadd231pd (%%rdx), %%ymm3, %%ymm13 \n\t" "vmovupd %%ymm13, (%%rdx) \n\t" "addq %%rdi, %%rdx \n\t" " \n\t" " \n\t" "vfmadd231pd (%%rcx), %%ymm3, %%ymm14 \n\t" "vmovupd %%ymm14, (%%rcx) \n\t" //"addq %%rdi, %%rcx \n\t" "vfmadd231pd (%%rdx), %%ymm3, %%ymm15 \n\t" "vmovupd %%ymm15, (%%rdx) \n\t" //"addq %%rdi, %%rdx \n\t" " \n\t" " \n\t" " \n\t" "jmp .DDONE \n\t" // jump to end. " \n\t" " \n\t" " \n\t" ".DBETAZERO: \n\t" " \n\t" "cmpq $8, %%rsi \n\t" // set ZF if (8*rs_c) == 8. "jz .DCOLSTORBZ \n\t" // jump to column storage case " \n\t" " \n\t" " \n\t" ".DGENSTORBZ: \n\t" " \n\t" " \n\t" "vmovapd %%ymm4, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" "vmovapd %%ymm6, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" "vmovapd %%ymm8, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" "vmovapd %%ymm10, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" "vmovapd %%ymm12, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" "vmovapd %%ymm14, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ //"addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" "movq %%rdx, %%rcx \n\t" // rcx = c + 4*rs_c " \n\t" " \n\t" "vmovapd %%ymm5, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" "vmovapd %%ymm7, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" "vmovapd %%ymm9, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" "vmovapd %%ymm11, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" "vmovapd %%ymm13, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ "addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" "vmovapd %%ymm15, %%ymm0 \n\t" DGEMM_OUTPUT_GS_BETA_NZ //"addq %%rdi, %%rcx \n\t" // c += cs_c; " \n\t" " \n\t" " \n\t" "jmp .DDONE \n\t" // jump to end. " \n\t" " \n\t" " \n\t" ".DCOLSTORBZ: \n\t" " \n\t" " \n\t" "vmovupd %%ymm4, (%%rcx) \n\t" "addq %%rdi, %%rcx \n\t" "vmovupd %%ymm5, (%%rdx) \n\t" "addq %%rdi, %%rdx \n\t" " \n\t" "vmovupd %%ymm6, (%%rcx) \n\t" "addq %%rdi, %%rcx \n\t" "vmovupd %%ymm7, (%%rdx) \n\t" "addq %%rdi, %%rdx \n\t" " \n\t" " \n\t" "vmovupd %%ymm8, (%%rcx) \n\t" "addq %%rdi, %%rcx \n\t" "vmovupd %%ymm9, (%%rdx) \n\t" "addq %%rdi, %%rdx \n\t" " \n\t" " \n\t" "vmovupd %%ymm10, (%%rcx) \n\t" "addq %%rdi, %%rcx \n\t" "vmovupd %%ymm11, (%%rdx) \n\t" "addq %%rdi, %%rdx \n\t" " \n\t" " \n\t" "vmovupd %%ymm12, (%%rcx) \n\t" "addq %%rdi, %%rcx \n\t" "vmovupd %%ymm13, (%%rdx) \n\t" "addq %%rdi, %%rdx \n\t" " \n\t" " \n\t" "vmovupd %%ymm14, (%%rcx) \n\t" //"addq %%rdi, %%rcx \n\t" "vmovupd %%ymm15, (%%rdx) \n\t" //"addq %%rdi, %%rdx \n\t" " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" ".DDONE: \n\t" " \n\t" "vzeroupper \n\t" " \n\t" : // output operands (none) : // input operands "m" (k_iter), // 0 "m" (k_left), // 1 "m" (a), // 2 "m" (b), // 3 "m" (alpha), // 4 "m" (beta), // 5 "m" (c), // 6 "m" (rs_c), // 7 "m" (cs_c)/*, // 8 "m" (b_next), // 9 "m" (a_next)*/ // 10 : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ); } // assumes beta.r, beta.i have been broadcast into ymm1, ymm2. // outputs to ymm0 #define CGEMM_INPUT_SCALE_GS_BETA_NZ \ "vmovlpd (%%rcx ), %%xmm0, %%xmm0 \n\t" \ "vmovhpd (%%rcx,%%rsi,1), %%xmm0, %%xmm0 \n\t" \ "vmovlpd (%%rcx,%%rsi,2), %%xmm3, %%xmm3 \n\t" \ "vmovhpd (%%rcx,%%r13 ), %%xmm3, %%xmm3 \n\t" \ "vinsertf128 $1, %%xmm3, %%ymm0, %%ymm0 \n\t" \ "vpermilps $0xb1, %%ymm0, %%ymm3 \n\t" \ "vmulps %%ymm1, %%ymm0, %%ymm0 \n\t" \ "vmulps %%ymm2, %%ymm3, %%ymm3 \n\t" \ "vaddsubps %%ymm3, %%ymm0, %%ymm0 \n\t" // assumes values to output are in ymm0 #define CGEMM_OUTPUT_GS \ "vextractf128 $1, %%ymm0, %%xmm3 \n\t" \ "vmovlpd %%xmm0, (%%rcx ) \n\t" \ "vmovhpd %%xmm0, (%%rcx,%%rsi,1) \n\t" \ "vmovlpd %%xmm3, (%%rcx,%%rsi,2) \n\t" \ "vmovhpd %%xmm3, (%%rcx,%%r13 ) \n\t" #define CGEMM_INPUT_SCALE_CS_BETA_NZ \ "vmovups (%%rcx), %%ymm0 \n\t" \ "vpermilps $0xb1, %%ymm0, %%ymm3 \n\t" \ "vmulps %%ymm1, %%ymm0, %%ymm0 \n\t" \ "vmulps %%ymm2, %%ymm3, %%ymm3 \n\t" \ "vaddsubps %%ymm3, %%ymm0, %%ymm0 \n\t" #define CGEMM_OUTPUT_CS \ "vmovups %%ymm0, (%%rcx) \n\t" \ void bli_cgemm_haswell_asm_8x3 ( dim_t k0, scomplex* restrict alpha, scomplex* restrict a, scomplex* restrict b, scomplex* restrict beta, scomplex* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; __asm__ volatile ( " \n\t" "vzeroall \n\t" // zero all xmm/ymm registers. " \n\t" " \n\t" "movq %2, %%rax \n\t" // load address of a. "movq %3, %%rbx \n\t" // load address of b. //"movq %9, %%r15 \n\t" // load address of b_next. " \n\t" "addq $32 * 4, %%rax \n\t" " \n\t" // initialize loop by pre-loading "vmovaps -4 * 32(%%rax), %%ymm0 \n\t" "vmovaps -3 * 32(%%rax), %%ymm1 \n\t" " \n\t" "movq %6, %%rcx \n\t" // load address of c "movq %8, %%rdi \n\t" // load cs_c "leaq (,%%rdi,8), %%rdi \n\t" // cs_c *= sizeof(scomplex) " \n\t" "leaq (%%rcx,%%rdi,1), %%r11 \n\t" // r11 = c + 1*cs_c; "leaq (%%rcx,%%rdi,2), %%r12 \n\t" // r12 = c + 2*cs_c; " \n\t" "prefetcht0 7 * 8(%%rcx) \n\t" // prefetch c + 0*cs_c "prefetcht0 7 * 8(%%r11) \n\t" // prefetch c + 1*cs_c "prefetcht0 7 * 8(%%r12) \n\t" // prefetch c + 2*cs_c " \n\t" " \n\t" " \n\t" " \n\t" "movq %0, %%rsi \n\t" // i = k_iter; "testq %%rsi, %%rsi \n\t" // check i via logical AND. "je .CCONSIDKLEFT \n\t" // if i == 0, jump to code that " \n\t" // contains the k_left loop. " \n\t" " \n\t" ".CLOOPKITER: \n\t" // MAIN LOOP " \n\t" " \n\t" " \n\t" // iteration 0 "prefetcht0 32 * 8(%%rax) \n\t" " \n\t" "vbroadcastss 0 * 4(%%rbx), %%ymm2 \n\t" "vbroadcastss 1 * 4(%%rbx), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm2, %%ymm4 \n\t" "vfmadd231ps %%ymm1, %%ymm2, %%ymm5 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm6 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm7 \n\t" " \n\t" "vbroadcastss 2 * 4(%%rbx), %%ymm2 \n\t" "vbroadcastss 3 * 4(%%rbx), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm2, %%ymm8 \n\t" "vfmadd231ps %%ymm1, %%ymm2, %%ymm9 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm10 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm11 \n\t" " \n\t" "vbroadcastss 4 * 4(%%rbx), %%ymm2 \n\t" "vbroadcastss 5 * 4(%%rbx), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm2, %%ymm12 \n\t" "vfmadd231ps %%ymm1, %%ymm2, %%ymm13 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm14 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm15 \n\t" " \n\t" "vmovaps -2 * 32(%%rax), %%ymm0 \n\t" "vmovaps -1 * 32(%%rax), %%ymm1 \n\t" " \n\t" " \n\t" // iteration 1 "vbroadcastss 6 * 4(%%rbx), %%ymm2 \n\t" "vbroadcastss 7 * 4(%%rbx), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm2, %%ymm4 \n\t" "vfmadd231ps %%ymm1, %%ymm2, %%ymm5 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm6 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm7 \n\t" " \n\t" "vbroadcastss 8 * 4(%%rbx), %%ymm2 \n\t" "vbroadcastss 9 * 4(%%rbx), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm2, %%ymm8 \n\t" "vfmadd231ps %%ymm1, %%ymm2, %%ymm9 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm10 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm11 \n\t" " \n\t" "vbroadcastss 10 * 4(%%rbx), %%ymm2 \n\t" "vbroadcastss 11 * 4(%%rbx), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm2, %%ymm12 \n\t" "vfmadd231ps %%ymm1, %%ymm2, %%ymm13 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm14 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm15 \n\t" " \n\t" "vmovaps 0 * 32(%%rax), %%ymm0 \n\t" "vmovaps 1 * 32(%%rax), %%ymm1 \n\t" " \n\t" " \n\t" // iteration 2 "prefetcht0 38 * 8(%%rax) \n\t" " \n\t" "vbroadcastss 12 * 4(%%rbx), %%ymm2 \n\t" "vbroadcastss 13 * 4(%%rbx), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm2, %%ymm4 \n\t" "vfmadd231ps %%ymm1, %%ymm2, %%ymm5 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm6 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm7 \n\t" " \n\t" "vbroadcastss 14 * 4(%%rbx), %%ymm2 \n\t" "vbroadcastss 15 * 4(%%rbx), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm2, %%ymm8 \n\t" "vfmadd231ps %%ymm1, %%ymm2, %%ymm9 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm10 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm11 \n\t" " \n\t" "vbroadcastss 16 * 4(%%rbx), %%ymm2 \n\t" "vbroadcastss 17 * 4(%%rbx), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm2, %%ymm12 \n\t" "vfmadd231ps %%ymm1, %%ymm2, %%ymm13 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm14 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm15 \n\t" " \n\t" "vmovaps 2 * 32(%%rax), %%ymm0 \n\t" "vmovaps 3 * 32(%%rax), %%ymm1 \n\t" " \n\t" " \n\t" // iteration 3 "vbroadcastss 18 * 4(%%rbx), %%ymm2 \n\t" "vbroadcastss 19 * 4(%%rbx), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm2, %%ymm4 \n\t" "vfmadd231ps %%ymm1, %%ymm2, %%ymm5 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm6 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm7 \n\t" " \n\t" "vbroadcastss 20 * 4(%%rbx), %%ymm2 \n\t" "vbroadcastss 21 * 4(%%rbx), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm2, %%ymm8 \n\t" "vfmadd231ps %%ymm1, %%ymm2, %%ymm9 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm10 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm11 \n\t" " \n\t" "vbroadcastss 22 * 4(%%rbx), %%ymm2 \n\t" "vbroadcastss 23 * 4(%%rbx), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm2, %%ymm12 \n\t" "vfmadd231ps %%ymm1, %%ymm2, %%ymm13 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm14 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm15 \n\t" " \n\t" "addq $4 * 8 * 8, %%rax \n\t" // a += 4*8 (unroll x mr) "addq $4 * 3 * 8, %%rbx \n\t" // b += 4*3 (unroll x nr) " \n\t" "vmovaps -4 * 32(%%rax), %%ymm0 \n\t" "vmovaps -3 * 32(%%rax), %%ymm1 \n\t" " \n\t" " \n\t" "decq %%rsi \n\t" // i -= 1; "jne .CLOOPKITER \n\t" // iterate again if i != 0. " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" ".CCONSIDKLEFT: \n\t" " \n\t" "movq %1, %%rsi \n\t" // i = k_left; "testq %%rsi, %%rsi \n\t" // check i via logical AND. "je .CPOSTACCUM \n\t" // if i == 0, we're done; jump to end. " \n\t" // else, we prepare to enter k_left loop. " \n\t" " \n\t" ".CLOOPKLEFT: \n\t" // EDGE LOOP " \n\t" "prefetcht0 32 * 8(%%rax) \n\t" " \n\t" "vbroadcastss 0 * 4(%%rbx), %%ymm2 \n\t" "vbroadcastss 1 * 4(%%rbx), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm2, %%ymm4 \n\t" "vfmadd231ps %%ymm1, %%ymm2, %%ymm5 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm6 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm7 \n\t" " \n\t" "vbroadcastss 2 * 4(%%rbx), %%ymm2 \n\t" "vbroadcastss 3 * 4(%%rbx), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm2, %%ymm8 \n\t" "vfmadd231ps %%ymm1, %%ymm2, %%ymm9 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm10 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm11 \n\t" " \n\t" "vbroadcastss 4 * 4(%%rbx), %%ymm2 \n\t" "vbroadcastss 5 * 4(%%rbx), %%ymm3 \n\t" "vfmadd231ps %%ymm0, %%ymm2, %%ymm12 \n\t" "vfmadd231ps %%ymm1, %%ymm2, %%ymm13 \n\t" "vfmadd231ps %%ymm0, %%ymm3, %%ymm14 \n\t" "vfmadd231ps %%ymm1, %%ymm3, %%ymm15 \n\t" " \n\t" "addq $1 * 8 * 8, %%rax \n\t" // a += 1*8 (unroll x mr) "addq $1 * 3 * 8, %%rbx \n\t" // b += 1*3 (unroll x nr) " \n\t" "vmovaps -4 * 32(%%rax), %%ymm0 \n\t" "vmovaps -3 * 32(%%rax), %%ymm1 \n\t" " \n\t" " \n\t" "decq %%rsi \n\t" // i -= 1; "jne .CLOOPKLEFT \n\t" // iterate again if i != 0. " \n\t" " \n\t" " \n\t" ".CPOSTACCUM: \n\t" " \n\t" " \n\t" " \n\t" // permute even and odd elements " \n\t" // of ymm6/7, ymm10/11, ymm/14/15 "vpermilps $0xb1, %%ymm6, %%ymm6 \n\t" "vpermilps $0xb1, %%ymm7, %%ymm7 \n\t" "vpermilps $0xb1, %%ymm10, %%ymm10 \n\t" "vpermilps $0xb1, %%ymm11, %%ymm11 \n\t" "vpermilps $0xb1, %%ymm14, %%ymm14 \n\t" "vpermilps $0xb1, %%ymm15, %%ymm15 \n\t" " \n\t" " \n\t" " \n\t" // subtract/add even/odd elements "vaddsubps %%ymm6, %%ymm4, %%ymm4 \n\t" "vaddsubps %%ymm7, %%ymm5, %%ymm5 \n\t" " \n\t" "vaddsubps %%ymm10, %%ymm8, %%ymm8 \n\t" "vaddsubps %%ymm11, %%ymm9, %%ymm9 \n\t" " \n\t" "vaddsubps %%ymm14, %%ymm12, %%ymm12 \n\t" "vaddsubps %%ymm15, %%ymm13, %%ymm13 \n\t" " \n\t" " \n\t" " \n\t" " \n\t" "movq %4, %%rax \n\t" // load address of alpha "vbroadcastss (%%rax), %%ymm0 \n\t" // load alpha_r and duplicate "vbroadcastss 4(%%rax), %%ymm1 \n\t" // load alpha_i and duplicate " \n\t" " \n\t" "vpermilps $0xb1, %%ymm4, %%ymm3 \n\t" "vmulps %%ymm0, %%ymm4, %%ymm4 \n\t" "vmulps %%ymm1, %%ymm3, %%ymm3 \n\t" "vaddsubps %%ymm3, %%ymm4, %%ymm4 \n\t" " \n\t" "vpermilps $0xb1, %%ymm5, %%ymm3 \n\t" "vmulps %%ymm0, %%ymm5, %%ymm5 \n\t" "vmulps %%ymm1, %%ymm3, %%ymm3 \n\t" "vaddsubps %%ymm3, %%ymm5, %%ymm5 \n\t" " \n\t" " \n\t" "vpermilps $0xb1, %%ymm8, %%ymm3 \n\t" "vmulps %%ymm0, %%ymm8, %%ymm8 \n\t" "vmulps %%ymm1, %%ymm3, %%ymm3 \n\t" "vaddsubps %%ymm3, %%ymm8, %%ymm8 \n\t" " \n\t" "vpermilps $0xb1, %%ymm9, %%ymm3 \n\t" "vmulps %%ymm0, %%ymm9, %%ymm9 \n\t" "vmulps %%ymm1, %%ymm3, %%ymm3 \n\t" "vaddsubps %%ymm3, %%ymm9, %%ymm9 \n\t" " \n\t" " \n\t" "vpermilps $0xb1, %%ymm12, %%ymm3 \n\t" "vmulps %%ymm0, %%ymm12, %%ymm12 \n\t" "vmulps %%ymm1, %%ymm3, %%ymm3 \n\t" "vaddsubps %%ymm3, %%ymm12, %%ymm12 \n\t" " \n\t" "vpermilps $0xb1, %%ymm13, %%ymm3 \n\t" "vmulps %%ymm0, %%ymm13, %%ymm13 \n\t" "vmulps %%ymm1, %%ymm3, %%ymm3 \n\t" "vaddsubps %%ymm3, %%ymm13, %%ymm13 \n\t" " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" "movq %5, %%rbx \n\t" // load address of beta "vbroadcastss (%%rbx), %%ymm1 \n\t" // load beta_r and duplicate "vbroadcastss 4(%%rbx), %%ymm2 \n\t" // load beta_i and duplicate " \n\t" " \n\t" " \n\t" " \n\t" "movq %7, %%rsi \n\t" // load rs_c "leaq (,%%rsi,8), %%rsi \n\t" // rsi = rs_c * sizeof(scomplex) "leaq (,%%rsi,4), %%rdx \n\t" // rdx = 4*rs_c; "leaq (%%rsi,%%rsi,2), %%r13 \n\t" // r13 = 3*rs_c; " \n\t" " \n\t" " \n\t" " \n\t" // now avoid loading C if beta == 0 "vxorps %%ymm0, %%ymm0, %%ymm0 \n\t" // set ymm0 to zero. "vucomiss %%xmm0, %%xmm1 \n\t" // set ZF if beta_r == 0. "sete %%r8b \n\t" // r8b = ( ZF == 1 ? 1 : 0 ); "vucomiss %%xmm0, %%xmm2 \n\t" // set ZF if beta_i == 0. "sete %%r9b \n\t" // r9b = ( ZF == 1 ? 1 : 0 ); "andb %%r8b, %%r9b \n\t" // set ZF if r8b & r9b == 1. "jne .CBETAZERO \n\t" // if ZF = 1, jump to beta == 0 case " \n\t" " \n\t" "cmpq $8, %%rsi \n\t" // set ZF if (8*cs_c) == 8. "jz .CCOLSTORED \n\t" // jump to row storage case " \n\t" " \n\t" " \n\t" ".CGENSTORED: \n\t" " \n\t" " \n\t" CGEMM_INPUT_SCALE_GS_BETA_NZ "vaddps %%ymm4, %%ymm0, %%ymm0 \n\t" CGEMM_OUTPUT_GS "addq %%rdx, %%rcx \n\t" // c += 4*rs_c; " \n\t" " \n\t" CGEMM_INPUT_SCALE_GS_BETA_NZ "vaddps %%ymm5, %%ymm0, %%ymm0 \n\t" CGEMM_OUTPUT_GS "movq %%r11, %%rcx \n\t" // rcx = c + 1*cs_c " \n\t" " \n\t" " \n\t" CGEMM_INPUT_SCALE_GS_BETA_NZ "vaddps %%ymm8, %%ymm0, %%ymm0 \n\t" CGEMM_OUTPUT_GS "addq %%rdx, %%rcx \n\t" // c += 4*rs_c; " \n\t" " \n\t" CGEMM_INPUT_SCALE_GS_BETA_NZ "vaddps %%ymm9, %%ymm0, %%ymm0 \n\t" CGEMM_OUTPUT_GS "movq %%r12, %%rcx \n\t" // rcx = c + 2*cs_c " \n\t" " \n\t" " \n\t" CGEMM_INPUT_SCALE_GS_BETA_NZ "vaddps %%ymm12, %%ymm0, %%ymm0 \n\t" CGEMM_OUTPUT_GS "addq %%rdx, %%rcx \n\t" // c += 4*rs_c; " \n\t" " \n\t" CGEMM_INPUT_SCALE_GS_BETA_NZ "vaddps %%ymm13, %%ymm0, %%ymm0 \n\t" CGEMM_OUTPUT_GS " \n\t" " \n\t" " \n\t" "jmp .CDONE \n\t" // jump to end. " \n\t" " \n\t" " \n\t" ".CCOLSTORED: \n\t" " \n\t" " \n\t" CGEMM_INPUT_SCALE_CS_BETA_NZ "vaddps %%ymm4, %%ymm0, %%ymm0 \n\t" CGEMM_OUTPUT_CS "addq %%rdx, %%rcx \n\t" // c += 4*rs_c; " \n\t" " \n\t" CGEMM_INPUT_SCALE_CS_BETA_NZ "vaddps %%ymm5, %%ymm0, %%ymm0 \n\t" CGEMM_OUTPUT_CS "movq %%r11, %%rcx \n\t" // rcx = c + 1*cs_c " \n\t" " \n\t" " \n\t" CGEMM_INPUT_SCALE_CS_BETA_NZ "vaddps %%ymm8, %%ymm0, %%ymm0 \n\t" CGEMM_OUTPUT_CS "addq %%rdx, %%rcx \n\t" // c += 4*rs_c; " \n\t" " \n\t" CGEMM_INPUT_SCALE_CS_BETA_NZ "vaddps %%ymm9, %%ymm0, %%ymm0 \n\t" CGEMM_OUTPUT_CS "movq %%r12, %%rcx \n\t" // rcx = c + 2*cs_c " \n\t" " \n\t" " \n\t" CGEMM_INPUT_SCALE_CS_BETA_NZ "vaddps %%ymm12, %%ymm0, %%ymm0 \n\t" CGEMM_OUTPUT_CS "addq %%rdx, %%rcx \n\t" // c += 4*rs_c; " \n\t" " \n\t" CGEMM_INPUT_SCALE_CS_BETA_NZ "vaddps %%ymm13, %%ymm0, %%ymm0 \n\t" CGEMM_OUTPUT_CS " \n\t" " \n\t" " \n\t" "jmp .CDONE \n\t" // jump to end. " \n\t" " \n\t" " \n\t" ".CBETAZERO: \n\t" " \n\t" "cmpq $8, %%rsi \n\t" // set ZF if (8*rs_c) == 8. "jz .CCOLSTORBZ \n\t" // jump to row storage case " \n\t" " \n\t" " \n\t" ".CGENSTORBZ: \n\t" " \n\t" " \n\t" "vmovaps %%ymm4, %%ymm0 \n\t" CGEMM_OUTPUT_GS "addq %%rdx, %%rcx \n\t" // c += 4*rs_c; " \n\t" " \n\t" "vmovaps %%ymm5, %%ymm0 \n\t" CGEMM_OUTPUT_GS "movq %%r11, %%rcx \n\t" // rcx = c + 1*cs_c " \n\t" " \n\t" " \n\t" "vmovaps %%ymm8, %%ymm0 \n\t" CGEMM_OUTPUT_GS "addq %%rdx, %%rcx \n\t" // c += 4*rs_c; " \n\t" " \n\t" "vmovaps %%ymm9, %%ymm0 \n\t" CGEMM_OUTPUT_GS "movq %%r12, %%rcx \n\t" // rcx = c + 2*cs_c " \n\t" " \n\t" " \n\t" "vmovaps %%ymm12, %%ymm0 \n\t" CGEMM_OUTPUT_GS "addq %%rdx, %%rcx \n\t" // c += 4*rs_c; " \n\t" " \n\t" "vmovaps %%ymm13, %%ymm0 \n\t" CGEMM_OUTPUT_GS " \n\t" " \n\t" " \n\t" "jmp .CDONE \n\t" // jump to end. " \n\t" " \n\t" " \n\t" ".CCOLSTORBZ: \n\t" " \n\t" " \n\t" "vmovups %%ymm4, (%%rcx) \n\t" "vmovups %%ymm5, (%%rcx,%%rdx,1) \n\t" " \n\t" "vmovups %%ymm8, (%%r11) \n\t" "vmovups %%ymm9, (%%r11,%%rdx,1) \n\t" " \n\t" "vmovups %%ymm12, (%%r12) \n\t" "vmovups %%ymm13, (%%r12,%%rdx,1) \n\t" " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" ".CDONE: \n\t" " \n\t" "vzeroupper \n\t" " \n\t" : // output operands (none) : // input operands "m" (k_iter), // 0 "m" (k_left), // 1 "m" (a), // 2 "m" (b), // 3 "m" (alpha), // 4 "m" (beta), // 5 "m" (c), // 6 "m" (rs_c), // 7 "m" (cs_c)/*, // 8 "m" (b_next), // 9 "m" (a_next)*/ // 10 : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ); } // assumes beta.r, beta.i have been broadcast into ymm1, ymm2. // outputs to ymm0 #define ZGEMM_INPUT_SCALE_GS_BETA_NZ \ "vmovupd (%%rcx), %%xmm0 \n\t" \ "vmovupd (%%rcx,%%rsi), %%xmm3 \n\t" \ "vinsertf128 $1, %%xmm3, %%ymm0, %%ymm0 \n\t" \ "vpermilpd $0x5, %%ymm0, %%ymm3 \n\t" \ "vmulpd %%ymm1, %%ymm0, %%ymm0 \n\t" \ "vmulpd %%ymm2, %%ymm3, %%ymm3 \n\t" \ "vaddsubpd %%ymm3, %%ymm0, %%ymm0 \n\t" // assumes values to output are in ymm0 #define ZGEMM_OUTPUT_GS \ "vextractf128 $1, %%ymm0, %%xmm3 \n\t" \ "vmovupd %%xmm0, (%%rcx) \n\t" \ "vmovupd %%xmm3, (%%rcx,%%rsi ) \n\t" \ #define ZGEMM_INPUT_SCALE_CS_BETA_NZ \ "vmovups (%%rcx), %%ymm0 \n\t" \ "vpermilpd $0x5, %%ymm0, %%ymm3 \n\t" \ "vmulpd %%ymm1, %%ymm0, %%ymm0 \n\t" \ "vmulpd %%ymm2, %%ymm3, %%ymm3 \n\t" \ "vaddsubpd %%ymm3, %%ymm0, %%ymm0 \n\t" #define ZGEMM_OUTPUT_CS \ "vmovupd %%ymm0, (%%rcx) \n\t" \ void bli_zgemm_haswell_asm_4x3 ( dim_t k0, dcomplex* restrict alpha, dcomplex* restrict a, dcomplex* restrict b, dcomplex* restrict beta, dcomplex* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; __asm__ volatile ( " \n\t" "vzeroall \n\t" // zero all xmm/ymm registers. " \n\t" " \n\t" "movq %2, %%rax \n\t" // load address of a. "movq %3, %%rbx \n\t" // load address of b. //"movq %9, %%r15 \n\t" // load address of b_next. " \n\t" "addq $32 * 4, %%rax \n\t" " \n\t" // initialize loop by pre-loading "vmovapd -4 * 32(%%rax), %%ymm0 \n\t" "vmovapd -3 * 32(%%rax), %%ymm1 \n\t" " \n\t" "movq %6, %%rcx \n\t" // load address of c "movq %8, %%rdi \n\t" // load cs_c "leaq (,%%rdi,8), %%rdi \n\t" // cs_c *= sizeof(dcomplex) "leaq (,%%rdi,2), %%rdi \n\t" " \n\t" "leaq (%%rcx,%%rdi,1), %%r11 \n\t" // r11 = c + 1*cs_c; "leaq (%%rcx,%%rdi,2), %%r12 \n\t" // r12 = c + 2*cs_c; " \n\t" "prefetcht0 7 * 8(%%rcx) \n\t" // prefetch c + 0*cs_c "prefetcht0 7 * 8(%%r11) \n\t" // prefetch c + 1*cs_c "prefetcht0 7 * 8(%%r12) \n\t" // prefetch c + 2*cs_c " \n\t" " \n\t" " \n\t" " \n\t" "movq %0, %%rsi \n\t" // i = k_iter; "testq %%rsi, %%rsi \n\t" // check i via logical AND. "je .ZCONSIDKLEFT \n\t" // if i == 0, jump to code that " \n\t" // contains the k_left loop. " \n\t" " \n\t" ".ZLOOPKITER: \n\t" // MAIN LOOP " \n\t" " \n\t" " \n\t" // iteration 0 "prefetcht0 32 * 16(%%rax) \n\t" " \n\t" "vbroadcastsd 0 * 8(%%rbx), %%ymm2 \n\t" "vbroadcastsd 1 * 8(%%rbx), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm2, %%ymm4 \n\t" "vfmadd231pd %%ymm1, %%ymm2, %%ymm5 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm6 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm7 \n\t" " \n\t" "vbroadcastsd 2 * 8(%%rbx), %%ymm2 \n\t" "vbroadcastsd 3 * 8(%%rbx), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm2, %%ymm8 \n\t" "vfmadd231pd %%ymm1, %%ymm2, %%ymm9 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm10 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm11 \n\t" " \n\t" "vbroadcastsd 4 * 8(%%rbx), %%ymm2 \n\t" "vbroadcastsd 5 * 8(%%rbx), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm2, %%ymm12 \n\t" "vfmadd231pd %%ymm1, %%ymm2, %%ymm13 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm14 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm15 \n\t" " \n\t" "vmovapd -2 * 32(%%rax), %%ymm0 \n\t" "vmovapd -1 * 32(%%rax), %%ymm1 \n\t" " \n\t" " \n\t" // iteration 1 "vbroadcastsd 6 * 8(%%rbx), %%ymm2 \n\t" "vbroadcastsd 7 * 8(%%rbx), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm2, %%ymm4 \n\t" "vfmadd231pd %%ymm1, %%ymm2, %%ymm5 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm6 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm7 \n\t" " \n\t" "vbroadcastsd 8 * 8(%%rbx), %%ymm2 \n\t" "vbroadcastsd 9 * 8(%%rbx), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm2, %%ymm8 \n\t" "vfmadd231pd %%ymm1, %%ymm2, %%ymm9 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm10 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm11 \n\t" " \n\t" "vbroadcastsd 10 * 8(%%rbx), %%ymm2 \n\t" "vbroadcastsd 11 * 8(%%rbx), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm2, %%ymm12 \n\t" "vfmadd231pd %%ymm1, %%ymm2, %%ymm13 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm14 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm15 \n\t" " \n\t" "vmovapd 0 * 32(%%rax), %%ymm0 \n\t" "vmovapd 1 * 32(%%rax), %%ymm1 \n\t" " \n\t" " \n\t" // iteration 2 "prefetcht0 38 * 16(%%rax) \n\t" " \n\t" "vbroadcastsd 12 * 8(%%rbx), %%ymm2 \n\t" "vbroadcastsd 13 * 8(%%rbx), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm2, %%ymm4 \n\t" "vfmadd231pd %%ymm1, %%ymm2, %%ymm5 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm6 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm7 \n\t" " \n\t" "vbroadcastsd 14 * 8(%%rbx), %%ymm2 \n\t" "vbroadcastsd 15 * 8(%%rbx), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm2, %%ymm8 \n\t" "vfmadd231pd %%ymm1, %%ymm2, %%ymm9 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm10 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm11 \n\t" " \n\t" "vbroadcastsd 16 * 8(%%rbx), %%ymm2 \n\t" "vbroadcastsd 17 * 8(%%rbx), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm2, %%ymm12 \n\t" "vfmadd231pd %%ymm1, %%ymm2, %%ymm13 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm14 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm15 \n\t" " \n\t" "vmovapd 2 * 32(%%rax), %%ymm0 \n\t" "vmovapd 3 * 32(%%rax), %%ymm1 \n\t" " \n\t" " \n\t" // iteration 3 "vbroadcastsd 18 * 8(%%rbx), %%ymm2 \n\t" "vbroadcastsd 19 * 8(%%rbx), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm2, %%ymm4 \n\t" "vfmadd231pd %%ymm1, %%ymm2, %%ymm5 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm6 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm7 \n\t" " \n\t" "vbroadcastsd 20 * 8(%%rbx), %%ymm2 \n\t" "vbroadcastsd 21 * 8(%%rbx), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm2, %%ymm8 \n\t" "vfmadd231pd %%ymm1, %%ymm2, %%ymm9 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm10 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm11 \n\t" " \n\t" "vbroadcastsd 22 * 8(%%rbx), %%ymm2 \n\t" "vbroadcastsd 23 * 8(%%rbx), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm2, %%ymm12 \n\t" "vfmadd231pd %%ymm1, %%ymm2, %%ymm13 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm14 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm15 \n\t" " \n\t" "addq $4 * 4 * 16, %%rax \n\t" // a += 4*4 (unroll x mr) "addq $4 * 3 * 16, %%rbx \n\t" // b += 4*3 (unroll x nr) " \n\t" "vmovapd -4 * 32(%%rax), %%ymm0 \n\t" "vmovapd -3 * 32(%%rax), %%ymm1 \n\t" " \n\t" " \n\t" "decq %%rsi \n\t" // i -= 1; "jne .ZLOOPKITER \n\t" // iterate again if i != 0. " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" ".ZCONSIDKLEFT: \n\t" " \n\t" "movq %1, %%rsi \n\t" // i = k_left; "testq %%rsi, %%rsi \n\t" // check i via logical AND. "je .ZPOSTACCUM \n\t" // if i == 0, we're done; jump to end. " \n\t" // else, we prepare to enter k_left loop. " \n\t" " \n\t" ".ZLOOPKLEFT: \n\t" // EDGE LOOP " \n\t" "prefetcht0 32 * 16(%%rax) \n\t" " \n\t" "vbroadcastsd 0 * 8(%%rbx), %%ymm2 \n\t" "vbroadcastsd 1 * 8(%%rbx), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm2, %%ymm4 \n\t" "vfmadd231pd %%ymm1, %%ymm2, %%ymm5 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm6 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm7 \n\t" " \n\t" "vbroadcastsd 2 * 8(%%rbx), %%ymm2 \n\t" "vbroadcastsd 3 * 8(%%rbx), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm2, %%ymm8 \n\t" "vfmadd231pd %%ymm1, %%ymm2, %%ymm9 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm10 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm11 \n\t" " \n\t" "vbroadcastsd 4 * 8(%%rbx), %%ymm2 \n\t" "vbroadcastsd 5 * 8(%%rbx), %%ymm3 \n\t" "vfmadd231pd %%ymm0, %%ymm2, %%ymm12 \n\t" "vfmadd231pd %%ymm1, %%ymm2, %%ymm13 \n\t" "vfmadd231pd %%ymm0, %%ymm3, %%ymm14 \n\t" "vfmadd231pd %%ymm1, %%ymm3, %%ymm15 \n\t" " \n\t" "addq $1 * 4 * 16, %%rax \n\t" // a += 1*4 (unroll x mr) "addq $1 * 3 * 16, %%rbx \n\t" // b += 1*3 (unroll x nr) " \n\t" "vmovapd -4 * 32(%%rax), %%ymm0 \n\t" "vmovapd -3 * 32(%%rax), %%ymm1 \n\t" " \n\t" " \n\t" "decq %%rsi \n\t" // i -= 1; "jne .ZLOOPKLEFT \n\t" // iterate again if i != 0. " \n\t" " \n\t" " \n\t" ".ZPOSTACCUM: \n\t" " \n\t" " \n\t" // permute even and odd elements " \n\t" // of ymm6/7, ymm10/11, ymm/14/15 "vpermilpd $0x5, %%ymm6, %%ymm6 \n\t" "vpermilpd $0x5, %%ymm7, %%ymm7 \n\t" "vpermilpd $0x5, %%ymm10, %%ymm10 \n\t" "vpermilpd $0x5, %%ymm11, %%ymm11 \n\t" "vpermilpd $0x5, %%ymm14, %%ymm14 \n\t" "vpermilpd $0x5, %%ymm15, %%ymm15 \n\t" " \n\t" " \n\t" " \n\t" // subtract/add even/odd elements "vaddsubpd %%ymm6, %%ymm4, %%ymm4 \n\t" "vaddsubpd %%ymm7, %%ymm5, %%ymm5 \n\t" " \n\t" "vaddsubpd %%ymm10, %%ymm8, %%ymm8 \n\t" "vaddsubpd %%ymm11, %%ymm9, %%ymm9 \n\t" " \n\t" "vaddsubpd %%ymm14, %%ymm12, %%ymm12 \n\t" "vaddsubpd %%ymm15, %%ymm13, %%ymm13 \n\t" " \n\t" " \n\t" " \n\t" " \n\t" "movq %4, %%rax \n\t" // load address of alpha "vbroadcastsd (%%rax), %%ymm0 \n\t" // load alpha_r and duplicate "vbroadcastsd 8(%%rax), %%ymm1 \n\t" // load alpha_i and duplicate " \n\t" " \n\t" "vpermilpd $0x5, %%ymm4, %%ymm3 \n\t" "vmulpd %%ymm0, %%ymm4, %%ymm4 \n\t" "vmulpd %%ymm1, %%ymm3, %%ymm3 \n\t" "vaddsubpd %%ymm3, %%ymm4, %%ymm4 \n\t" " \n\t" "vpermilpd $0x5, %%ymm5, %%ymm3 \n\t" "vmulpd %%ymm0, %%ymm5, %%ymm5 \n\t" "vmulpd %%ymm1, %%ymm3, %%ymm3 \n\t" "vaddsubpd %%ymm3, %%ymm5, %%ymm5 \n\t" " \n\t" " \n\t" "vpermilpd $0x5, %%ymm8, %%ymm3 \n\t" "vmulpd %%ymm0, %%ymm8, %%ymm8 \n\t" "vmulpd %%ymm1, %%ymm3, %%ymm3 \n\t" "vaddsubpd %%ymm3, %%ymm8, %%ymm8 \n\t" " \n\t" "vpermilpd $0x5, %%ymm9, %%ymm3 \n\t" "vmulpd %%ymm0, %%ymm9, %%ymm9 \n\t" "vmulpd %%ymm1, %%ymm3, %%ymm3 \n\t" "vaddsubpd %%ymm3, %%ymm9, %%ymm9 \n\t" " \n\t" " \n\t" "vpermilpd $0x5, %%ymm12, %%ymm3 \n\t" "vmulpd %%ymm0, %%ymm12, %%ymm12 \n\t" "vmulpd %%ymm1, %%ymm3, %%ymm3 \n\t" "vaddsubpd %%ymm3, %%ymm12, %%ymm12 \n\t" " \n\t" "vpermilpd $0x5, %%ymm13, %%ymm3 \n\t" "vmulpd %%ymm0, %%ymm13, %%ymm13 \n\t" "vmulpd %%ymm1, %%ymm3, %%ymm3 \n\t" "vaddsubpd %%ymm3, %%ymm13, %%ymm13 \n\t" " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" "movq %5, %%rbx \n\t" // load address of beta "vbroadcastsd (%%rbx), %%ymm1 \n\t" // load beta_r and duplicate "vbroadcastsd 8(%%rbx), %%ymm2 \n\t" // load beta_i and duplicate " \n\t" " \n\t" " \n\t" " \n\t" "movq %7, %%rsi \n\t" // load rs_c "leaq (,%%rsi,8), %%rsi \n\t" // rsi = rs_c * sizeof(dcomplex) "leaq (,%%rsi,2), %%rsi \n\t" "leaq (,%%rsi,2), %%rdx \n\t" // rdx = 2*rs_c; " \n\t" " \n\t" " \n\t" " \n\t" // now avoid loading C if beta == 0 "vxorpd %%ymm0, %%ymm0, %%ymm0 \n\t" // set ymm0 to zero. "vucomisd %%xmm0, %%xmm1 \n\t" // set ZF if beta_r == 0. "sete %%r8b \n\t" // r8b = ( ZF == 1 ? 1 : 0 ); "vucomisd %%xmm0, %%xmm2 \n\t" // set ZF if beta_i == 0. "sete %%r9b \n\t" // r9b = ( ZF == 1 ? 1 : 0 ); "andb %%r8b, %%r9b \n\t" // set ZF if r8b & r9b == 1. "jne .ZBETAZERO \n\t" // if ZF = 1, jump to beta == 0 case " \n\t" " \n\t" "cmpq $16, %%rsi \n\t" // set ZF if (16*rs_c) == 16. "jz .ZCOLSTORED \n\t" // jump to row storage case " \n\t" " \n\t" " \n\t" ".ZGENSTORED: \n\t" " \n\t" " \n\t" ZGEMM_INPUT_SCALE_GS_BETA_NZ "vaddpd %%ymm4, %%ymm0, %%ymm0 \n\t" ZGEMM_OUTPUT_GS "addq %%rdx, %%rcx \n\t" // c += 2*rs_c; " \n\t" " \n\t" ZGEMM_INPUT_SCALE_GS_BETA_NZ "vaddpd %%ymm5, %%ymm0, %%ymm0 \n\t" ZGEMM_OUTPUT_GS "movq %%r11, %%rcx \n\t" // rcx = c + 1*cs_c " \n\t" " \n\t" " \n\t" ZGEMM_INPUT_SCALE_GS_BETA_NZ "vaddpd %%ymm8, %%ymm0, %%ymm0 \n\t" ZGEMM_OUTPUT_GS "addq %%rdx, %%rcx \n\t" // c += 2*rs_c; " \n\t" " \n\t" ZGEMM_INPUT_SCALE_GS_BETA_NZ "vaddpd %%ymm9, %%ymm0, %%ymm0 \n\t" ZGEMM_OUTPUT_GS "movq %%r12, %%rcx \n\t" // rcx = c + 2*cs_c " \n\t" " \n\t" " \n\t" ZGEMM_INPUT_SCALE_GS_BETA_NZ "vaddpd %%ymm12, %%ymm0, %%ymm0 \n\t" ZGEMM_OUTPUT_GS "addq %%rdx, %%rcx \n\t" // c += 2*rs_c; " \n\t" " \n\t" ZGEMM_INPUT_SCALE_GS_BETA_NZ "vaddpd %%ymm13, %%ymm0, %%ymm0 \n\t" ZGEMM_OUTPUT_GS " \n\t" " \n\t" " \n\t" "jmp .ZDONE \n\t" // jump to end. " \n\t" " \n\t" " \n\t" ".ZCOLSTORED: \n\t" " \n\t" " \n\t" ZGEMM_INPUT_SCALE_CS_BETA_NZ "vaddpd %%ymm4, %%ymm0, %%ymm0 \n\t" ZGEMM_OUTPUT_CS "addq %%rdx, %%rcx \n\t" // c += 2*rs_c; " \n\t" " \n\t" ZGEMM_INPUT_SCALE_CS_BETA_NZ "vaddpd %%ymm5, %%ymm0, %%ymm0 \n\t" ZGEMM_OUTPUT_CS "movq %%r11, %%rcx \n\t" // rcx = c + 1*cs_c " \n\t" " \n\t" " \n\t" ZGEMM_INPUT_SCALE_CS_BETA_NZ "vaddpd %%ymm8, %%ymm0, %%ymm0 \n\t" ZGEMM_OUTPUT_CS "addq %%rdx, %%rcx \n\t" // c += 2*rs_c; " \n\t" " \n\t" ZGEMM_INPUT_SCALE_CS_BETA_NZ "vaddpd %%ymm9, %%ymm0, %%ymm0 \n\t" ZGEMM_OUTPUT_CS "movq %%r12, %%rcx \n\t" // rcx = c + 2*cs_c " \n\t" " \n\t" " \n\t" ZGEMM_INPUT_SCALE_CS_BETA_NZ "vaddpd %%ymm12, %%ymm0, %%ymm0 \n\t" ZGEMM_OUTPUT_CS "addq %%rdx, %%rcx \n\t" // c += 2*rs_c; " \n\t" " \n\t" ZGEMM_INPUT_SCALE_CS_BETA_NZ "vaddpd %%ymm13, %%ymm0, %%ymm0 \n\t" ZGEMM_OUTPUT_CS " \n\t" " \n\t" " \n\t" "jmp .ZDONE \n\t" // jump to end. " \n\t" " \n\t" " \n\t" ".ZBETAZERO: \n\t" " \n\t" "cmpq $16, %%rsi \n\t" // set ZF if (16*rs_c) == 16. "jz .ZCOLSTORBZ \n\t" // jump to row storage case " \n\t" " \n\t" " \n\t" ".ZGENSTORBZ: \n\t" " \n\t" " \n\t" "vmovapd %%ymm4, %%ymm0 \n\t" ZGEMM_OUTPUT_GS "addq %%rdx, %%rcx \n\t" // c += 2*rs_c; " \n\t" " \n\t" "vmovapd %%ymm5, %%ymm0 \n\t" ZGEMM_OUTPUT_GS "movq %%r11, %%rcx \n\t" // rcx = c + 1*cs_c " \n\t" " \n\t" " \n\t" "vmovapd %%ymm8, %%ymm0 \n\t" ZGEMM_OUTPUT_GS "addq %%rdx, %%rcx \n\t" // c += 2*rs_c; " \n\t" " \n\t" "vmovapd %%ymm9, %%ymm0 \n\t" ZGEMM_OUTPUT_GS "movq %%r12, %%rcx \n\t" // rcx = c + 2*cs_c " \n\t" " \n\t" " \n\t" "vmovapd %%ymm12, %%ymm0 \n\t" ZGEMM_OUTPUT_GS "addq %%rdx, %%rcx \n\t" // c += 2*rs_c; " \n\t" " \n\t" "vmovapd %%ymm13, %%ymm0 \n\t" ZGEMM_OUTPUT_GS " \n\t" " \n\t" " \n\t" "jmp .ZDONE \n\t" // jump to end. " \n\t" " \n\t" " \n\t" ".ZCOLSTORBZ: \n\t" " \n\t" " \n\t" "vmovupd %%ymm4, (%%rcx) \n\t" "vmovupd %%ymm5, (%%rcx,%%rdx,1) \n\t" " \n\t" "vmovupd %%ymm8, (%%r11) \n\t" "vmovupd %%ymm9, (%%r11,%%rdx,1) \n\t" " \n\t" "vmovupd %%ymm12, (%%r12) \n\t" "vmovupd %%ymm13, (%%r12,%%rdx,1) \n\t" " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" " \n\t" ".ZDONE: \n\t" " \n\t" "vzeroupper \n\t" " \n\t" : // output operands (none) : // input operands "m" (k_iter), // 0 "m" (k_left), // 1 "m" (a), // 2 "m" (b), // 3 "m" (alpha), // 4 "m" (beta), // 5 "m" (c), // 6 "m" (rs_c), // 7 "m" (cs_c)/*, // 8 "m" (b_next), // 9 "m" (a_next)*/ // 10 : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ); } blis-0.9.0/kernels/haswell/3/sup/000077500000000000000000000000001422157504600165325ustar00rootroot00000000000000blis-0.9.0/kernels/haswell/3/sup/bli_gemmsup_rd_haswell_asm_d6x8m.c000066400000000000000000001462351422157504600253060ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define BLIS_ASM_SYNTAX_ATT #include "bli_x86_asm_macros.h" /* rrc: -------- ------ | | | | | | | | -------- ------ | | | | | | | | -------- += ------ ... | | | | | | | | -------- ------ | | | | | | | | -------- ------ : -------- ------ : Assumptions: - C is row-stored and B is column-stored; - A is row-stored; - m0 and n0 are at most MR and NR, respectively. Therefore, this (r)ow-preferential microkernel is well-suited for a dot-product-based accumulation that performs vector loads from both A and B. NOTE: These kernels implicitly support column-oriented IO, implemented via an a high-level transposition of the entire operation. A and B will effectively remain row- and column-stored, respectively, but C will then effectively appear column-stored. Thus, this kernel may be used for both rrc and crc cases. */ // Prototype reference microkernels. GEMMSUP_KER_PROT( double, d, gemmsup_r_haswell_ref ) void bli_dgemmsup_rd_haswell_asm_6x8m ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { uint64_t n_left = n0 % 8; // First check whether this is a edge case in the n dimension. If so, // dispatch other 6x?m kernels, as needed. if ( n_left ) { double* restrict cij = c; double* restrict bj = b; double* restrict ai = a; if ( 4 <= n_left ) { const dim_t nr_cur = 4; bli_dgemmsup_rd_haswell_asm_6x4m ( conja, conjb, m0, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 2 <= n_left ) { const dim_t nr_cur = 2; bli_dgemmsup_rd_haswell_asm_6x2m ( conja, conjb, m0, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 1 == n_left ) { #if 0 const dim_t nr_cur = 1; bli_dgemmsup_r_haswell_ref ( conja, conjb, m0, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); #else bli_dgemv_ex ( BLIS_NO_TRANSPOSE, conjb, m0, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, beta, cij, rs_c0, cntx, NULL ); #endif } return; } //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t m_iter = m0 / 3; uint64_t m_left = m0 % 3; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; if ( m_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. //mov(var(a), r14) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a //mov(var(b), rdx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b lea(mem(r8, r8, 2), r10) // r10 = 3*rs_a //mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) // r12 = rcx = c // r14 = rax = a // rdx = rbx = b // r9 = m dim index ii // r15 = n dim index jj mov(imm(0), r15) // jj = 0; label(.DLOOP3X4J) // LOOP OVER jj = [ 0 1 ... ] mov(var(a), r14) // load address of a mov(var(b), rdx) // load address of b mov(var(c), r12) // load address of c lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(imm(1*8), rsi) // rsi *= cs_c*sizeof(double) = 1*8 lea(mem(r12, rsi, 1), r12) // r12 = c + 4*jj*cs_c; lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(r11, rsi) // rsi *= cs_b; lea(mem(rdx, rsi, 1), rdx) // rbx = b + 4*jj*cs_b; mov(var(m_iter), r9) // ii = m_iter; label(.DLOOP3X4I) // LOOP OVER ii = [ m_iter ... 1 0 ] #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm5, ymm5, ymm5) vxorpd(ymm6, ymm6, ymm6) vxorpd(ymm7, ymm7, ymm7) vxorpd(ymm8, ymm8, ymm8) vxorpd(ymm9, ymm9, ymm9) vxorpd(ymm10, ymm10, ymm10) vxorpd(ymm11, ymm11, ymm11) vxorpd(ymm12, ymm12, ymm12) vxorpd(ymm13, ymm13, ymm13) vxorpd(ymm14, ymm14, ymm14) vxorpd(ymm15, ymm15, ymm15) #endif lea(mem(r12), rcx) // rcx = c_iijj; lea(mem(r14), rax) // rax = a_ii; lea(mem(rdx), rbx) // rbx = b_jj; #if 1 //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 3*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 3*8)) // prefetch c + 2*rs_c #endif lea(mem(r8, r8, 4), rbp) // rbp = 5*rs_a mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*rs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*rs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*rs_a #endif vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 1 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*rs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*rs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*rs_a #endif vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 3 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) #if 1 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*rs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*rs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*rs_a #endif vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rax ), xmm0) vmovsd(mem(rax, r8, 1), xmm1) vmovsd(mem(rax, r8, 2), xmm2) add(imm(1*8), rax) // a += 1*cs_a = 1*8; vmovsd(mem(rbx ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovsd(mem(rbx, r11, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovsd(mem(rbx, r11, 2), xmm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovsd(mem(rbx, r13, 1), xmm3) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 // ymm5 ymm8 ymm11 ymm14 // ymm6 ymm9 ymm12 ymm15 vhaddpd( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm4 ) // xmm4[0] = sum(ymm4); xmm4[1] = sum(ymm7) // xmm4[2] = sum(ymm10); xmm4[3] = sum(ymm13) vhaddpd( ymm8, ymm5, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm14, ymm11, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm5 ) // xmm5[0] = sum(ymm5); xmm5[1] = sum(ymm8) // xmm5[2] = sum(ymm11); xmm5[3] = sum(ymm14) vhaddpd( ymm9, ymm6, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm15, ymm12, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm6 ) // xmm6[0] = sum(ymm6); xmm6[1] = sum(ymm9) // xmm6[2] = sum(ymm12); xmm6[3] = sum(ymm15) //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(ymm0, ymm5, ymm5) vmulpd(ymm0, ymm6, ymm6) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), ymm3, ymm4) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm5) vmovupd(ymm5, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm6) vmovupd(ymm6, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vmovupd(ymm5, mem(rcx)) add(rdi, rcx) vmovupd(ymm6, mem(rcx)) //add(rdi, rcx) label(.DDONE) lea(mem(r12, rdi, 2), r12) // lea(mem(r12, rdi, 1), r12) // c_ii = r12 += 3*rs_c lea(mem(r14, r8, 2), r14) // lea(mem(r14, r8, 1), r14) // a_ii = r14 += 3*rs_a dec(r9) // ii -= 1; jne(.DLOOP3X4I) // iterate again if ii != 0. add(imm(4), r15) // jj += 4; cmp(imm(8), r15) // compare jj to 8 jl(.DLOOP3X4J) // if jj < 8, jump to beginning // of jj loop; otherwise, loop ends. label(.DRETURN) end_asm( : // output operands (none) : // input operands [m_iter] "m" (m_iter), [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the m dimension, if they exist. if ( m_left ) { const dim_t nr_cur = 8; const dim_t i_edge = m0 - ( dim_t )m_left; double* restrict cij = c + i_edge*rs_c; double* restrict bj = b; double* restrict ai = a + i_edge*rs_a; if ( 2 == m_left ) { const dim_t mr_cur = 2; bli_dgemmsup_rd_haswell_asm_2x8 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); //cij += mr_cur*rs_c0; ai += mr_cur*rs_a0; m_left -= mr_cur; } if ( 1 == m_left ) { const dim_t mr_cur = 1; bli_dgemmsup_rd_haswell_asm_1x8 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); } } } void bli_dgemmsup_rd_haswell_asm_6x4m ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t m_iter = m0 / 3; uint64_t m_left = m0 % 3; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; if ( m_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), r14) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rdx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b lea(mem(r8, r8, 2), r10) // r10 = 3*rs_a mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) // r12 = rcx = c // r14 = rax = a // rdx = rbx = b // r9 = m dim index ii // r15 = n dim index jj mov(var(m_iter), r9) // ii = m_iter; label(.DLOOP3X4I) // LOOP OVER ii = [ m_iter .. 1 0 ] #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm5, ymm5, ymm5) vxorpd(ymm6, ymm6, ymm6) vxorpd(ymm7, ymm7, ymm7) vxorpd(ymm8, ymm8, ymm8) vxorpd(ymm9, ymm9, ymm9) vxorpd(ymm10, ymm10, ymm10) vxorpd(ymm11, ymm11, ymm11) vxorpd(ymm12, ymm12, ymm12) vxorpd(ymm13, ymm13, ymm13) vxorpd(ymm14, ymm14, ymm14) vxorpd(ymm15, ymm15, ymm15) #endif lea(mem(r12), rcx) // rcx = c + 3*ii*rs_c; lea(mem(r14), rax) // rax = a + 3*ii*rs_a; lea(mem(rdx), rbx) // rbx = b; #if 1 //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 3*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 3*8)) // prefetch c + 2*rs_c #endif lea(mem(r8, r8, 4), rbp) // rbp = 5*rs_a mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*rs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*rs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*rs_a #endif vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 1 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*rs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*rs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*rs_a #endif vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 3 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) #if 1 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*rs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*rs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*rs_a #endif vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rax ), xmm0) vmovsd(mem(rax, r8, 1), xmm1) vmovsd(mem(rax, r8, 2), xmm2) add(imm(1*8), rax) // a += 1*cs_a = 1*8; vmovsd(mem(rbx ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovsd(mem(rbx, r11, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovsd(mem(rbx, r11, 2), xmm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovsd(mem(rbx, r13, 1), xmm3) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 // ymm5 ymm8 ymm11 ymm14 // ymm6 ymm9 ymm12 ymm15 vhaddpd( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm4 ) // ymm4[0] = sum(ymm4); ymm4[1] = sum(ymm7) // ymm4[2] = sum(ymm10); ymm4[3] = sum(ymm13) vhaddpd( ymm8, ymm5, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm14, ymm11, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm5 ) // ymm5[0] = sum(ymm5); ymm5[1] = sum(ymm8) // ymm5[2] = sum(ymm11); ymm5[3] = sum(ymm14) vhaddpd( ymm9, ymm6, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm15, ymm12, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm6 ) // ymm6[0] = sum(ymm6); ymm6[1] = sum(ymm9) // ymm6[2] = sum(ymm12); ymm6[3] = sum(ymm15) //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(ymm0, ymm5, ymm5) vmulpd(ymm0, ymm6, ymm6) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), ymm3, ymm4) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm5) vmovupd(ymm5, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm6) vmovupd(ymm6, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vmovupd(ymm5, mem(rcx)) add(rdi, rcx) vmovupd(ymm6, mem(rcx)) //add(rdi, rcx) label(.DDONE) lea(mem(r12, rdi, 2), r12) // lea(mem(r12, rdi, 1), r12) // c_ii = r12 += 3*rs_c lea(mem(r14, r8, 2), r14) // lea(mem(r14, r8, 1), r14) // a_ii = r14 += 3*rs_a dec(r9) // ii -= 1; jne(.DLOOP3X4I) // iterate again if ii != 0. label(.DRETURN) end_asm( : // output operands (none) : // input operands [m_iter] "m" (m_iter), [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the m dimension, if they exist. if ( m_left ) { const dim_t nr_cur = 4; const dim_t i_edge = m0 - ( dim_t )m_left; double* restrict cij = c + i_edge*rs_c; double* restrict bj = b; double* restrict ai = a + i_edge*rs_a; if ( 2 == m_left ) { const dim_t mr_cur = 2; bli_dgemmsup_rd_haswell_asm_2x4 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); //cij += mr_cur*rs_c0; ai += mr_cur*rs_a0; m_left -= mr_cur; } if ( 1 == m_left ) { const dim_t mr_cur = 1; bli_dgemmsup_rd_haswell_asm_1x4 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); } } } void bli_dgemmsup_rd_haswell_asm_6x2m ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t m_iter = m0 / 6; uint64_t m_left = m0 % 6; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; if ( m_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), r14) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rdx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) //lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b //lea(mem(r8, r8, 2), r10) // r10 = 3*rs_a mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) // r12 = rcx = c // r14 = rax = a // rdx = rbx = b // r9 = m dim index ii mov(var(m_iter), r9) // ii = m_iter; label(.DLOOP3X4I) // LOOP OVER ii = [ m_iter ... 1 0 ] #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm5, ymm5, ymm5) vxorpd(ymm6, ymm6, ymm6) vxorpd(ymm7, ymm7, ymm7) vxorpd(ymm8, ymm8, ymm8) vxorpd(ymm9, ymm9, ymm9) vxorpd(ymm10, ymm10, ymm10) vxorpd(ymm11, ymm11, ymm11) vxorpd(ymm12, ymm12, ymm12) vxorpd(ymm13, ymm13, ymm13) vxorpd(ymm14, ymm14, ymm14) vxorpd(ymm15, ymm15, ymm15) #endif lea(mem(r12), rcx) // rcx = c_ii; lea(mem(r14), rax) // rax = a_ii; lea(mem(rdx), rbx) // rbx = b; #if 1 //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) lea(mem(rcx, rdi, 2), r10) // lea(mem(r10, rdi, 1), r10) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 1*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 1*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 1*8)) // prefetch c + 2*rs_c prefetch(0, mem(r10, 1*8)) // prefetch c + 3*rs_c prefetch(0, mem(r10, rdi, 1, 1*8)) // prefetch c + 4*rs_c prefetch(0, mem(r10, rdi, 2, 1*8)) // prefetch c + 5*rs_c #endif mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*rs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*rs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*rs_a #endif vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovupd(mem(rax, r8, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) vmovupd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rax, r8, 4), ymm3) vfmadd231pd(ymm0, ymm3, ymm12) vfmadd231pd(ymm1, ymm3, ymm13) vmovupd(mem(rax, r15, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) // ---------------------------------- iteration 1 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovupd(mem(rax, r8, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) vmovupd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rax, r8, 4), ymm3) vfmadd231pd(ymm0, ymm3, ymm12) vfmadd231pd(ymm1, ymm3, ymm13) vmovupd(mem(rax, r15, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) // ---------------------------------- iteration 2 #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*rs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*rs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*rs_a #endif vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovupd(mem(rax, r8, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) vmovupd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rax, r8, 4), ymm3) vfmadd231pd(ymm0, ymm3, ymm12) vfmadd231pd(ymm1, ymm3, ymm13) vmovupd(mem(rax, r15, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) // ---------------------------------- iteration 3 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovupd(mem(rax, r8, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) vmovupd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rax, r8, 4), ymm3) vfmadd231pd(ymm0, ymm3, ymm12) vfmadd231pd(ymm1, ymm3, ymm13) vmovupd(mem(rax, r15, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*rs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*rs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*rs_a #endif vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovupd(mem(rax, r8, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) vmovupd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rax, r8, 4), ymm3) vfmadd231pd(ymm0, ymm3, ymm12) vfmadd231pd(ymm1, ymm3, ymm13) vmovupd(mem(rax, r15, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rbx ), xmm0) vmovsd(mem(rbx, r11, 1), xmm1) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vmovsd(mem(rax ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovsd(mem(rax, r8, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovsd(mem(rax, r8, 2), xmm3) vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) vmovsd(mem(rax, r13, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovsd(mem(rax, r8, 4), xmm3) vfmadd231pd(ymm0, ymm3, ymm12) vfmadd231pd(ymm1, ymm3, ymm13) vmovsd(mem(rax, r15, 1), xmm3) add(imm(1*8), rax) // a += 1*cs_a = 1*8; vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm5 // ymm6 ymm7 // ymm8 ymm9 // ymm10 ymm11 // ymm12 ymm13 // ymm14 ymm15 vhaddpd( ymm5, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm4 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm5) vhaddpd( ymm7, ymm6, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm6 ) vhaddpd( ymm9, ymm8, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm8 ) vhaddpd( ymm11, ymm10, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm10 ) vhaddpd( ymm13, ymm12, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm12 ) vhaddpd( ymm15, ymm14, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm14 ) // xmm4[0:1] = sum(ymm4) sum(ymm5) // xmm6[0:1] = sum(ymm6) sum(ymm7) // xmm8[0:1] = sum(ymm8) sum(ymm9) // xmm10[0:1] = sum(ymm10) sum(ymm11) // xmm12[0:1] = sum(ymm12) sum(ymm13) // xmm14[0:1] = sum(ymm14) sum(ymm15) //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(xmm0, xmm4, xmm4) // scale by alpha vmulpd(xmm0, xmm6, xmm6) vmulpd(xmm0, xmm8, xmm8) vmulpd(xmm0, xmm10, xmm10) vmulpd(xmm0, xmm12, xmm12) vmulpd(xmm0, xmm14, xmm14) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), xmm3, xmm4) vmovupd(xmm4, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), xmm3, xmm6) vmovupd(xmm6, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), xmm3, xmm8) vmovupd(xmm8, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), xmm3, xmm10) vmovupd(xmm10, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), xmm3, xmm12) vmovupd(xmm12, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), xmm3, xmm14) vmovupd(xmm14, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(xmm4, mem(rcx)) add(rdi, rcx) vmovupd(xmm6, mem(rcx)) add(rdi, rcx) vmovupd(xmm8, mem(rcx)) add(rdi, rcx) vmovupd(xmm10, mem(rcx)) add(rdi, rcx) vmovupd(xmm12, mem(rcx)) add(rdi, rcx) vmovupd(xmm14, mem(rcx)) //add(rdi, rcx) label(.DDONE) lea(mem(r12, rdi, 4), r12) // lea(mem(r12, rdi, 2), r12) // c_ii = r12 += 6*rs_c lea(mem(r14, r8, 4), r14) // lea(mem(r14, r8, 2), r14) // a_ii = r14 += 6*rs_a dec(r9) // ii -= 1; jne(.DLOOP3X4I) // iterate again if ii != 0. label(.DRETURN) end_asm( : // output operands (none) : // input operands [m_iter] "m" (m_iter), [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the m dimension, if they exist. if ( m_left ) { const dim_t nr_cur = 2; const dim_t i_edge = m0 - ( dim_t )m_left; double* restrict cij = c + i_edge*rs_c; double* restrict bj = b; double* restrict ai = a + i_edge*rs_a; if ( 3 <= m_left ) { const dim_t mr_cur = 3; bli_dgemmsup_rd_haswell_asm_3x2 //bli_dgemmsup_r_haswell_ref ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += mr_cur*rs_c0; ai += mr_cur*rs_a0; m_left -= mr_cur; } if ( 2 <= m_left ) { const dim_t mr_cur = 2; bli_dgemmsup_rd_haswell_asm_2x2 //bli_dgemmsup_r_haswell_ref ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += mr_cur*rs_c0; ai += mr_cur*rs_a0; m_left -= mr_cur; } if ( 1 == m_left ) { const dim_t mr_cur = 1; bli_dgemmsup_rd_haswell_asm_1x2 //bli_dgemmsup_r_haswell_ref ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); } } } blis-0.9.0/kernels/haswell/3/sup/bli_gemmsup_rd_haswell_asm_d6x8n.c000066400000000000000000001747261422157504600253150ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define BLIS_ASM_SYNTAX_ATT #include "bli_x86_asm_macros.h" /* rrc: -------- ------ | | | | | | | | -------- ------ | | | | | | | | -------- += ------ ... | | | | | | | | -------- ------ | | | | | | | | -------- ------ : -------- ------ : Assumptions: - C is row-stored and B is column-stored; - A is row-stored; - m0 and n0 are at most MR and NR, respectively. Therefore, this (r)ow-preferential microkernel is well-suited for a dot-product-based accumulation that performs vector loads from both A and B. NOTE: These kernels implicitly support column-oriented IO, implemented via an a high-level transposition of the entire operation. A and B will effectively remain row- and column-stored, respectively, but C will then effectively appear column-stored. Thus, this kernel may be used for both rrc and crc cases. */ // Prototype reference microkernels. GEMMSUP_KER_PROT( double, d, gemmsup_r_haswell_ref ) void bli_dgemmsup_rd_haswell_asm_6x8n ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { uint64_t m_left = m0 % 6; // First check whether this is a edge case in the n dimension. If so, // dispatch other ?x8m kernels, as needed. if ( m_left ) { double* restrict cij = c; double* restrict bj = b; double* restrict ai = a; #if 1 // We add special handling for slightly inflated MR blocksizes // at edge cases, up to a maximum of 9. if ( 6 < m0 ) { dgemmsup_ker_ft ker_fp1 = NULL; dgemmsup_ker_ft ker_fp2 = NULL; dim_t mr1, mr2; // These kernels don't make any attempt to optimize the cases of // inflated MR blocksizes because they don't benefit from the // load balancing that the "rv" kernels do. That is, if m0 = 7, // there is no benefit to executing that case as 4x8n followed // by 3x8n because 4x8n isn't implemented, and more generally // because these kernels are implemented as loops over their // true blocksizes, which are MR=3 NR=4. if ( m0 == 7 ) { mr1 = 6; mr2 = 1; ker_fp1 = bli_dgemmsup_rd_haswell_asm_6x8n; ker_fp2 = bli_dgemmsup_rd_haswell_asm_1x8n; } else if ( m0 == 8 ) { mr1 = 6; mr2 = 2; ker_fp1 = bli_dgemmsup_rd_haswell_asm_6x8n; ker_fp2 = bli_dgemmsup_rd_haswell_asm_2x8n; } else // if ( m0 == 9 ) { mr1 = 6; mr2 = 3; ker_fp1 = bli_dgemmsup_rd_haswell_asm_6x8n; ker_fp2 = bli_dgemmsup_rd_haswell_asm_3x8n; } ker_fp1 ( conja, conjb, mr1, n0, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += mr1*rs_c0; ai += mr1*rs_a0; ker_fp2 ( conja, conjb, mr2, n0, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); return; } #endif if ( 3 <= m_left ) { const dim_t mr_cur = 3; bli_dgemmsup_rd_haswell_asm_3x8n //bli_dgemmsup_r_haswell_ref ( conja, conjb, mr_cur, n0, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += mr_cur*rs_c0; ai += mr_cur*rs_a0; m_left -= mr_cur; } if ( 2 <= m_left ) { const dim_t mr_cur = 2; bli_dgemmsup_rd_haswell_asm_2x8n //bli_dgemmsup_r_haswell_ref ( conja, conjb, mr_cur, n0, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += mr_cur*rs_c0; ai += mr_cur*rs_a0; m_left -= mr_cur; } if ( 1 == m_left ) { #if 1 const dim_t mr_cur = 1; bli_dgemmsup_rd_haswell_asm_1x8n //bli_dgemmsup_r_haswell_ref ( conja, conjb, mr_cur, n0, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); #else bli_dgemv_ex ( BLIS_TRANSPOSE, conja, k0, n0, alpha, bj, rs_b0, cs_b0, ai, cs_a0, beta, cij, cs_c0, cntx, NULL ); #endif } return; } //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t n_iter = n0 / 4; uint64_t n_left = n0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; if ( n_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. //mov(var(a), rdx) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a //mov(var(b), r14) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b //lea(mem(r8, r8, 2), r10) // r10 = 3*rs_a //mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) // r12 = rcx = c // rdx = rax = a // r14 = rbx = b // r9 = m dim index ii // r15 = n dim index jj mov(imm(0), r9) // ii = 0; label(.DLOOP3X4I) // LOOP OVER ii = [ 0 1 ... ] mov(var(a), rdx) // load address of a mov(var(b), r14) // load address of b mov(var(c), r12) // load address of c lea(mem( , r9, 1), rsi) // rsi = r9 = 3*ii; imul(rdi, rsi) // rsi *= rs_c lea(mem(r12, rsi, 1), r12) // r12 = c + 3*ii*rs_c; lea(mem( , r9, 1), rsi) // rsi = r9 = 3*ii; imul(r8, rsi) // rsi *= rs_a; lea(mem(rdx, rsi, 1), rdx) // rax = a + 3*ii*rs_a; mov(var(n_iter), r15) // jj = n_iter; label(.DLOOP3X4J) // LOOP OVER jj = [ n_iter ... 1 0 ] #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm5, ymm5, ymm5) vxorpd(ymm6, ymm6, ymm6) vxorpd(ymm7, ymm7, ymm7) vxorpd(ymm8, ymm8, ymm8) vxorpd(ymm9, ymm9, ymm9) vxorpd(ymm10, ymm10, ymm10) vxorpd(ymm11, ymm11, ymm11) vxorpd(ymm12, ymm12, ymm12) vxorpd(ymm13, ymm13, ymm13) vxorpd(ymm14, ymm14, ymm14) vxorpd(ymm15, ymm15, ymm15) #endif lea(mem(r12), rcx) // rcx = c_iijj; lea(mem(rdx), rax) // rax = a_ii; lea(mem(r14), rbx) // rbx = b_jj; #if 1 //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 3*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 3*8)) // prefetch c + 2*rs_c #endif //lea(mem(r8, r8, 4), rbp) // rbp = 5*rs_a lea(mem(rbx, r11, 4), r10) // r10 = rbx + 4*cs_b mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(r10, 0*8)) // prefetch rbx + 4*cs_b prefetch(0, mem(r10, r11, 1, 0*8)) // prefetch rbx + 5*cs_b #endif vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 1 #if 1 prefetch(0, mem(r10, r11, 2, 0*8)) // prefetch rbx + 6*cs_b prefetch(0, mem(r10, r13, 1, 0*8)) // prefetch rbx + 7*cs_b #endif vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(r10, 8*8)) // prefetch rbx + 4*cs_b + 8*rs_b prefetch(0, mem(r10, r11, 1, 8*8)) // prefetch rbx + 5*cs_b + 8*rs_b #endif vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 3 #if 1 prefetch(0, mem(r10, r11, 2, 8*8)) // prefetch rbx + 6*cs_b + 8*rs_b prefetch(0, mem(r10, r13, 1, 8*8)) // prefetch rbx + 7*cs_b + 8*rs_b add(imm(16*8), r10) // r10 += 8*rs_b = 8*8; #endif vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rax ), xmm0) vmovsd(mem(rax, r8, 1), xmm1) vmovsd(mem(rax, r8, 2), xmm2) add(imm(1*8), rax) // a += 1*cs_a = 1*8; vmovsd(mem(rbx ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovsd(mem(rbx, r11, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovsd(mem(rbx, r11, 2), xmm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovsd(mem(rbx, r13, 1), xmm3) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 // ymm5 ymm8 ymm11 ymm14 // ymm6 ymm9 ymm12 ymm15 vhaddpd( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm4 ) // ymm4[0] = sum(ymm4); ymm4[1] = sum(ymm7) // ymm4[2] = sum(ymm10); ymm4[3] = sum(ymm13) vhaddpd( ymm8, ymm5, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm14, ymm11, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm5 ) // ymm5[0] = sum(ymm5); ymm5[1] = sum(ymm8) // ymm5[2] = sum(ymm11); ymm5[3] = sum(ymm14) vhaddpd( ymm9, ymm6, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm15, ymm12, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm6 ) // ymm6[0] = sum(ymm6); ymm6[1] = sum(ymm9) // ymm6[2] = sum(ymm12); ymm6[3] = sum(ymm15) //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(ymm0, ymm5, ymm5) vmulpd(ymm0, ymm6, ymm6) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), ymm3, ymm4) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm5) vmovupd(ymm5, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm6) vmovupd(ymm6, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vmovupd(ymm5, mem(rcx)) add(rdi, rcx) vmovupd(ymm6, mem(rcx)) //add(rdi, rcx) label(.DDONE) add(imm(4*8), r12) // c_jj = r12 += 4*cs_c lea(mem(r14, r11, 4), r14) // b_jj = r14 += 4*cs_b dec(r15) // jj -= 1; jne(.DLOOP3X4J) // iterate again if jj != 0. add(imm(3), r9) // ii += 3; cmp(imm(6), r9) // compare ii to 6 jl(.DLOOP3X4I) // if ii < 6, jump to beginning // of ii loop; otherwise, loop ends. label(.DRETURN) end_asm( : // output operands (none) : // input operands [n_iter] "m" (n_iter), [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the n dimension, if they exist. if ( n_left ) { const dim_t mr_cur = 6; const dim_t j_edge = n0 - ( dim_t )n_left; double* restrict cij = c + j_edge*cs_c; double* restrict ai = a; double* restrict bj = b + j_edge*cs_b; if ( 2 <= n_left ) { const dim_t nr_cur = 2; bli_dgemmsup_rd_haswell_asm_6x2 //bli_dgemmsup_r_haswell_ref ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 1 == n_left ) { #if 1 const dim_t nr_cur = 1; bli_dgemmsup_rd_haswell_asm_6x1 //bli_dgemmsup_r_haswell_ref ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); #else bli_dgemv_ex ( BLIS_NO_TRANSPOSE, conjb, mr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, beta, cij, rs_c0, cntx, NULL ); #endif } } } void bli_dgemmsup_rd_haswell_asm_3x8n ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t n_iter = n0 / 4; uint64_t n_left = n0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; if ( n_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), rdx) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), r14) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b //lea(mem(r8, r8, 2), r10) // r10 = 3*rs_a mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) // r12 = rcx = c // rdx = rax = a // r14 = rbx = b // r9 = unused // r15 = n dim index jj mov(var(n_iter), r15) // jj = n_iter; label(.DLOOP3X4J) // LOOP OVER jj = [ n_iter ... 1 0 ] #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm5, ymm5, ymm5) vxorpd(ymm6, ymm6, ymm6) vxorpd(ymm7, ymm7, ymm7) vxorpd(ymm8, ymm8, ymm8) vxorpd(ymm9, ymm9, ymm9) vxorpd(ymm10, ymm10, ymm10) vxorpd(ymm11, ymm11, ymm11) vxorpd(ymm12, ymm12, ymm12) vxorpd(ymm13, ymm13, ymm13) vxorpd(ymm14, ymm14, ymm14) vxorpd(ymm15, ymm15, ymm15) #endif lea(mem(r12), rcx) // rcx = c_iijj; lea(mem(rdx), rax) // rax = a_ii; lea(mem(r14), rbx) // rbx = b_jj; #if 1 //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 3*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 3*8)) // prefetch c + 2*rs_c #endif //lea(mem(r8, r8, 4), rbp) // rbp = 5*rs_a lea(mem(rbx, r11, 4), r10) // r10 = rbx + 4*cs_b mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(r10, 0*8)) // prefetch rbx + 4*cs_b prefetch(0, mem(r10, r11, 1, 0*8)) // prefetch rbx + 5*cs_b #endif vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 1 #if 1 prefetch(0, mem(r10, r11, 2, 0*8)) // prefetch rbx + 6*cs_b prefetch(0, mem(r10, r13, 1, 0*8)) // prefetch rbx + 7*cs_b #endif vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(r10, 8*8)) // prefetch rbx + 4*cs_b + 8*rs_b prefetch(0, mem(r10, r11, 1, 8*8)) // prefetch rbx + 5*cs_b + 8*rs_b #endif vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 3 #if 1 prefetch(0, mem(r10, r11, 2, 8*8)) // prefetch rbx + 6*cs_b + 8*rs_b prefetch(0, mem(r10, r13, 1, 8*8)) // prefetch rbx + 7*cs_b + 8*rs_b add(imm(16*8), r10) // r10 += 8*rs_b = 8*8; #endif vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rax ), xmm0) vmovsd(mem(rax, r8, 1), xmm1) vmovsd(mem(rax, r8, 2), xmm2) add(imm(1*8), rax) // a += 1*cs_a = 1*8; vmovsd(mem(rbx ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovsd(mem(rbx, r11, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovsd(mem(rbx, r11, 2), xmm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovsd(mem(rbx, r13, 1), xmm3) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 // ymm5 ymm8 ymm11 ymm14 // ymm6 ymm9 ymm12 ymm15 vhaddpd( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm4 ) // ymm4[0] = sum(ymm4); ymm4[1] = sum(ymm7) // ymm4[2] = sum(ymm10); ymm4[3] = sum(ymm13) vhaddpd( ymm8, ymm5, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm14, ymm11, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm5 ) // ymm5[0] = sum(ymm5); ymm5[1] = sum(ymm8) // ymm5[2] = sum(ymm11); ymm5[3] = sum(ymm14) vhaddpd( ymm9, ymm6, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm15, ymm12, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm6 ) // ymm6[0] = sum(ymm6); ymm6[1] = sum(ymm9) // ymm6[2] = sum(ymm12); ymm6[3] = sum(ymm15) //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(ymm0, ymm5, ymm5) vmulpd(ymm0, ymm6, ymm6) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), ymm3, ymm4) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm5) vmovupd(ymm5, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm6) vmovupd(ymm6, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vmovupd(ymm5, mem(rcx)) add(rdi, rcx) vmovupd(ymm6, mem(rcx)) //add(rdi, rcx) label(.DDONE) add(imm(4*8), r12) // c_jj = r12 += 4*cs_c lea(mem(r14, r11, 4), r14) // b_jj = r14 += 4*cs_b dec(r15) // jj -= 1; jne(.DLOOP3X4J) // iterate again if jj != 0. label(.DRETURN) end_asm( : // output operands (none) : // input operands [n_iter] "m" (n_iter), [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the n dimension, if they exist. if ( n_left ) { const dim_t mr_cur = 3; const dim_t j_edge = n0 - ( dim_t )n_left; double* restrict cij = c + j_edge*cs_c; double* restrict ai = a; double* restrict bj = b + j_edge*cs_b; if ( 2 <= n_left ) { const dim_t nr_cur = 2; bli_dgemmsup_rd_haswell_asm_3x2 //bli_dgemmsup_r_haswell_ref ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 1 == n_left ) { #if 1 const dim_t nr_cur = 1; bli_dgemmsup_rd_haswell_asm_3x1 //bli_dgemmsup_r_haswell_ref_3x1 //bli_dgemmsup_r_haswell_ref ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); #else bli_dgemv_ex ( BLIS_NO_TRANSPOSE, conjb, mr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, beta, cij, rs_c0, cntx, NULL ); #endif } } } void bli_dgemmsup_rd_haswell_asm_2x8n ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t n_iter = n0 / 4; uint64_t n_left = n0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; if ( n_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), rdx) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), r14) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b //lea(mem(r8, r8, 2), r10) // r10 = 3*rs_a mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) // r12 = rcx = c // rdx = rax = a // r14 = rbx = b // r9 = unused // r15 = n dim index jj mov(var(n_iter), r15) // jj = n_iter; label(.DLOOP3X4J) // LOOP OVER jj = [ n_iter ... 1 0 ] #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm5, ymm5, ymm5) vxorpd(ymm7, ymm7, ymm7) vxorpd(ymm8, ymm8, ymm8) vxorpd(ymm10, ymm10, ymm10) vxorpd(ymm11, ymm11, ymm11) vxorpd(ymm13, ymm13, ymm13) vxorpd(ymm14, ymm14, ymm14) #endif lea(mem(r12), rcx) // rcx = c_iijj; lea(mem(rdx), rax) // rax = a_ii; lea(mem(r14), rbx) // rbx = b_jj; #if 1 //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 3*8)) // prefetch c + 1*rs_c #endif //lea(mem(r8, r8, 4), rbp) // rbp = 5*rs_a lea(mem(rbx, r11, 4), r10) // r10 = rbx + 4*cs_b mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(r10, 0*8)) // prefetch rbx + 4*cs_b prefetch(0, mem(r10, r11, 1, 0*8)) // prefetch rbx + 5*cs_b #endif vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) // ---------------------------------- iteration 1 #if 1 prefetch(0, mem(r10, r11, 2, 0*8)) // prefetch rbx + 6*cs_b prefetch(0, mem(r10, r13, 1, 0*8)) // prefetch rbx + 7*cs_b #endif vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(r10, 8*8)) // prefetch rbx + 4*cs_b + 8*rs_b prefetch(0, mem(r10, r11, 1, 8*8)) // prefetch rbx + 5*cs_b + 8*rs_b #endif vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) // ---------------------------------- iteration 3 #if 1 prefetch(0, mem(r10, r11, 2, 8*8)) // prefetch rbx + 6*cs_b + 8*rs_b prefetch(0, mem(r10, r13, 1, 8*8)) // prefetch rbx + 7*cs_b + 8*rs_b add(imm(16*8), r10) // r10 += 8*rs_b = 8*8; #endif vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rax ), xmm0) vmovsd(mem(rax, r8, 1), xmm1) add(imm(1*8), rax) // a += 1*cs_a = 1*8; vmovsd(mem(rbx ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovsd(mem(rbx, r11, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovsd(mem(rbx, r11, 2), xmm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovsd(mem(rbx, r13, 1), xmm3) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 // ymm5 ymm8 ymm11 ymm14 vhaddpd( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm4 ) // ymm4[0] = sum(ymm4); ymm4[1] = sum(ymm7) // ymm4[2] = sum(ymm10); ymm4[3] = sum(ymm13) vhaddpd( ymm8, ymm5, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm14, ymm11, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm5 ) // ymm5[0] = sum(ymm5); ymm5[1] = sum(ymm8) // ymm5[2] = sum(ymm11); ymm5[3] = sum(ymm14) //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(ymm0, ymm5, ymm5) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), ymm3, ymm4) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm5) vmovupd(ymm5, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vmovupd(ymm5, mem(rcx)) //add(rdi, rcx) label(.DDONE) add(imm(4*8), r12) // c_jj = r12 += 4*cs_c lea(mem(r14, r11, 4), r14) // b_jj = r14 += 4*cs_b dec(r15) // jj -= 1; jne(.DLOOP3X4J) // iterate again if jj != 0. label(.DRETURN) end_asm( : // output operands (none) : // input operands [n_iter] "m" (n_iter), [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the n dimension, if they exist. if ( n_left ) { const dim_t mr_cur = 2; const dim_t j_edge = n0 - ( dim_t )n_left; double* restrict cij = c + j_edge*cs_c; double* restrict ai = a; double* restrict bj = b + j_edge*cs_b; if ( 2 <= n_left ) { const dim_t nr_cur = 2; bli_dgemmsup_rd_haswell_asm_2x2 //bli_dgemmsup_r_haswell_ref ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 1 == n_left ) { #if 1 const dim_t nr_cur = 1; bli_dgemmsup_rd_haswell_asm_2x1 //bli_dgemmsup_r_haswell_ref ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); #else bli_dgemv_ex ( BLIS_NO_TRANSPOSE, conjb, mr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, beta, cij, rs_c0, cntx, NULL ); #endif } } } void bli_dgemmsup_rd_haswell_asm_1x8n ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t n_iter = n0 / 4; uint64_t n_left = n0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; if ( n_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), rdx) // load address of a. //mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a //lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), r14) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b //lea(mem(r8, r8, 2), r10) // r10 = 3*rs_a mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) // r12 = rcx = c // rdx = rax = a // r14 = rbx = b // r9 = unused // r15 = n dim index jj mov(var(n_iter), r15) // jj = n_iter; label(.DLOOP3X4J) // LOOP OVER jj = [ n_iter ... 1 0 ] #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm7, ymm7, ymm7) vxorpd(ymm10, ymm10, ymm10) vxorpd(ymm13, ymm13, ymm13) #endif lea(mem(r12), rcx) // rcx = c_iijj; lea(mem(rdx), rax) // rax = a_ii; lea(mem(r14), rbx) // rbx = b_jj; #if 1 //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c #endif //lea(mem(r8, r8, 4), rbp) // rbp = 5*rs_a lea(mem(rbx, r11, 4), r10) // r10 = rbx + 4*cs_b mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(r10, 0*8)) // prefetch rbx + 4*cs_b prefetch(0, mem(r10, r11, 1, 0*8)) // prefetch rbx + 5*cs_b #endif vmovupd(mem(rax ), ymm0) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) // ---------------------------------- iteration 1 #if 1 prefetch(0, mem(r10, r11, 2, 0*8)) // prefetch rbx + 6*cs_b prefetch(0, mem(r10, r13, 1, 0*8)) // prefetch rbx + 7*cs_b #endif vmovupd(mem(rax ), ymm0) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(r10, 8*8)) // prefetch rbx + 4*cs_b + 8*rs_b prefetch(0, mem(r10, r11, 1, 8*8)) // prefetch rbx + 5*cs_b + 8*rs_b #endif vmovupd(mem(rax ), ymm0) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) // ---------------------------------- iteration 3 #if 1 prefetch(0, mem(r10, r11, 2, 8*8)) // prefetch rbx + 6*cs_b + 8*rs_b prefetch(0, mem(r10, r13, 1, 8*8)) // prefetch rbx + 7*cs_b + 8*rs_b add(imm(16*8), r10) // r10 += 8*rs_b = 8*8; #endif vmovupd(mem(rax ), ymm0) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) vmovupd(mem(rax ), ymm0) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rax ), xmm0) add(imm(1*8), rax) // a += 1*cs_a = 1*8; vmovsd(mem(rbx ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovsd(mem(rbx, r11, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovsd(mem(rbx, r11, 2), xmm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovsd(mem(rbx, r13, 1), xmm3) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vfmadd231pd(ymm0, ymm3, ymm13) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 vhaddpd( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm4 ) // ymm4[0] = sum(ymm4); ymm4[1] = sum(ymm7) // ymm4[2] = sum(ymm10); ymm4[3] = sum(ymm13) //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), ymm3, ymm4) vmovupd(ymm4, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx)) //add(rdi, rcx) label(.DDONE) add(imm(4*8), r12) // c_jj = r12 += 4*cs_c lea(mem(r14, r11, 4), r14) // b_jj = r14 += 4*cs_b dec(r15) // jj -= 1; jne(.DLOOP3X4J) // iterate again if jj != 0. label(.DRETURN) end_asm( : // output operands (none) : // input operands [n_iter] "m" (n_iter), [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the n dimension, if they exist. if ( n_left ) { const dim_t mr_cur = 1; const dim_t j_edge = n0 - ( dim_t )n_left; double* restrict cij = c + j_edge*cs_c; double* restrict ai = a; double* restrict bj = b + j_edge*cs_b; if ( 2 <= n_left ) { const dim_t nr_cur = 2; bli_dgemmsup_rd_haswell_asm_1x2 //bli_dgemmsup_r_haswell_ref ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 1 == n_left ) { #if 1 const dim_t nr_cur = 1; bli_dgemmsup_rd_haswell_asm_1x1 //bli_dgemmsup_r_haswell_ref ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); #else bli_ddotxv_ex ( conja, conjb, k0, alpha, ai, cs_a0, bj, rs_b0, beta, cij, cntx, NULL ); #endif } } } blis-0.9.0/kernels/haswell/3/sup/bli_gemmsup_rd_haswell_asm_s6x16m.c000066400000000000000000002527511422157504600254050ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define BLIS_ASM_SYNTAX_ATT #include "bli_x86_asm_macros.h" /* rrc: -------- ------ | | | | | | | | -------- ------ | | | | | | | | -------- += ------ ... | | | | | | | | -------- ------ | | | | | | | | -------- ------ : -------- ------ : Assumptions: - C is row-stored and B is column-stored; - A is row-stored; - m0 and n0 are at most MR and NR, respectively. Therefore, this (r)ow-preferential microkernel is well-suited for a dot-product-based accumulation that performs vector loads from both A and B. NOTE: These kernels implicitly support column-oriented IO, implemented via an a high-level transposition of the entire operation. A and B will effectively remain row- and column-stored, respectively, but C will then effectively appear column-stored. Thus, this kernel may be used for both rrc and crc cases. */ // Prototype reference microkernels. GEMMSUP_KER_PROT( float, s, gemmsup_r_haswell_ref ) void bli_sgemmsup_rd_haswell_asm_6x16m ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { uint64_t n_left = n0 % 16; // First check whether this is a edge case in the n dimension. If so, // dispatch other 6x?m kernels, as needed. if ( n_left ) { float* restrict cij = c; float* restrict bj = b; float* restrict ai = a; if ( 12 <= n_left ) { const dim_t nr_cur = 12; bli_sgemmsup_rd_haswell_asm_6x12m ( conja, conjb, m0, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 8 <= n_left ) { const dim_t nr_cur = 8; bli_sgemmsup_rd_haswell_asm_6x8m ( conja, conjb, m0, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 4 <= n_left ) { const dim_t nr_cur = 4; bli_sgemmsup_rd_haswell_asm_6x4m ( conja, conjb, m0, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 2 <= n_left ) { const dim_t nr_cur = 2; bli_sgemmsup_rd_haswell_asm_6x2m ( conja, conjb, m0, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 1 == n_left ) { #if 0 const dim_t nr_cur = 1; bli_sgemmsup_r_haswell_ref ( conja, conjb, m0, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); #else bli_sgemv_ex ( BLIS_NO_TRANSPOSE, conjb, m0, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, beta, cij, rs_c0, cntx, NULL ); #endif } return; } //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter32 = k0 / 32; uint64_t k_left32 = k0 % 32; uint64_t k_iter8 = k_left32 / 8; uint64_t k_left1 = k_left32 % 8; uint64_t m_iter = m0 / 3; uint64_t m_left = m0 % 3; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; if ( m_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. //mov(var(a), r14) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) //lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a //mov(var(b), rdx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b lea(mem(r8, r8, 2), r10) // r10 = 3*rs_a //mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) // r12 = rcx = c // r14 = rax = a // rdx = rbx = b // r9 = m dim index ii // r15 = n dim index jj mov(imm(0), r15) // jj = 0; label(.SLOOP3X4J) // LOOP OVER jj = [ 0 1 ... ] mov(var(a), r14) // load address of a mov(var(b), rdx) // load address of b mov(var(c), r12) // load address of c lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(imm(1*4), rsi) // rsi *= cs_c*sizeof(float) = 1*4 lea(mem(r12, rsi, 1), r12) // r12 = c + 4*jj*cs_c; lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(r11, rsi) // rsi *= cs_b; lea(mem(rdx, rsi, 1), rdx) // rbx = b + 4*jj*cs_b; mov(var(m_iter), r9) // ii = m_iter; label(.SLOOP3X4I) // LOOP OVER ii = [ m_iter ... 1 0 ] #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorps ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorps(ymm4, ymm4, ymm4) vxorps(ymm5, ymm5, ymm5) vxorps(ymm6, ymm6, ymm6) vxorps(ymm7, ymm7, ymm7) vxorps(ymm8, ymm8, ymm8) vxorps(ymm9, ymm9, ymm9) vxorps(ymm10, ymm10, ymm10) vxorps(ymm11, ymm11, ymm11) vxorps(ymm12, ymm12, ymm12) vxorps(ymm13, ymm13, ymm13) vxorps(ymm14, ymm14, ymm14) vxorps(ymm15, ymm15, ymm15) #endif lea(mem(r12), rcx) // rcx = c_iijj; lea(mem(r14), rax) // rax = a_ii; lea(mem(rdx), rbx) // rbx = b_jj; #if 1 //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) prefetch(0, mem(rcx, 1*4)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 1*4)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 1*4)) // prefetch c + 2*rs_c #endif lea(mem(r8, r8, 4), rbp) // rbp = 5*rs_a mov(var(k_iter32), rsi) // i = k_iter32; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKITER8) // if i == 0, jump to code that // contains the k_iter8 loop. label(.SLOOPKITER32) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*rs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*rs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*rs_a #endif vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) vmovups(mem(rax, r8, 2), ymm2) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) // ---------------------------------- iteration 1 vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) vmovups(mem(rax, r8, 2), ymm2) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*rs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*rs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*rs_a #endif vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) vmovups(mem(rax, r8, 2), ymm2) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) // ---------------------------------- iteration 3 vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) vmovups(mem(rax, r8, 2), ymm2) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.SLOOPKITER32) // iterate again if i != 0. label(.SCONSIDKITER8) mov(var(k_iter8), rsi) // i = k_iter8; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter8 loop. label(.SLOOPKITER8) // EDGE LOOP (ymm) #if 1 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*rs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*rs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*rs_a #endif vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) vmovups(mem(rax, r8, 2), ymm2) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.SLOOPKITER8) // iterate again if i != 0. label(.SCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.SLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovss(mem(rax ), xmm0) vmovss(mem(rax, r8, 1), xmm1) vmovss(mem(rax, r8, 2), xmm2) add(imm(1*4), rax) // a += 1*cs_a = 1*4; vmovss(mem(rbx ), xmm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovss(mem(rbx, r11, 1), xmm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovss(mem(rbx, r11, 2), xmm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovss(mem(rbx, r13, 1), xmm3) add(imm(1*4), rbx) // b += 1*rs_b = 1*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.SLOOPKLEFT1) // iterate again if i != 0. label(.SPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 // ymm5 ymm8 ymm11 ymm14 // ymm6 ymm9 ymm12 ymm15 vhaddps( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vhaddps( xmm1, xmm0, xmm0 ) vpermilps(imm(0xd8), xmm0, xmm0) vhaddps( xmm0, xmm0, xmm0 ) vhaddps( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm3 ) vhaddps( xmm3, xmm2, xmm2 ) vpermilps(imm(0xd8), xmm2, xmm2) vhaddps( xmm2, xmm2, xmm2 ) vshufps(imm(0x44), xmm2, xmm0, xmm4) // xmm4[0] = sum(ymm4); xmm4[1] = sum(ymm7) // xmm4[2] = sum(ymm10); xmm4[3] = sum(ymm13) vhaddps( ymm8, ymm5, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vhaddps( xmm1, xmm0, xmm0 ) vpermilps(imm(0xd8), xmm0, xmm0) vhaddps( xmm0, xmm0, xmm0 ) vhaddps( ymm14, ymm11, ymm2 ) vextractf128(imm(1), ymm2, xmm3 ) vhaddps( xmm3, xmm2, xmm2 ) vpermilps(imm(0xd8), xmm2, xmm2) vhaddps( xmm2, xmm2, xmm2 ) vshufps(imm(0x44), xmm2, xmm0, xmm5) // xmm5[0] = sum(ymm5); xmm5[1] = sum(ymm8) // xmm5[2] = sum(ymm11); xmm5[3] = sum(ymm14) vhaddps( ymm9, ymm6, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vhaddps( xmm1, xmm0, xmm0 ) vpermilps(imm(0xd8), xmm0, xmm0) vhaddps( xmm0, xmm0, xmm0 ) vhaddps( ymm15, ymm12, ymm2 ) vextractf128(imm(1), ymm2, xmm3 ) vhaddps( xmm3, xmm2, xmm2 ) vpermilps(imm(0xd8), xmm2, xmm2) vhaddps( xmm2, xmm2, xmm2 ) vshufps(imm(0x44), xmm2, xmm0, xmm6) // xmm6[0] = sum(ymm6); xmm6[1] = sum(ymm9) // xmm6[2] = sum(ymm12); xmm6[3] = sum(ymm15) //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), xmm0) // load alpha and duplicate vbroadcastss(mem(rbx), xmm3) // load beta and duplicate vmulps(xmm0, xmm4, xmm4) // scale by alpha vmulps(xmm0, xmm5, xmm5) vmulps(xmm0, xmm6, xmm6) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case label(.SROWSTORED) vfmadd231ps(mem(rcx), xmm3, xmm4) vmovups(xmm4, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), xmm3, xmm5) vmovups(xmm5, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), xmm3, xmm6) vmovups(xmm6, mem(rcx)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SBETAZERO) label(.SROWSTORBZ) vmovups(xmm4, mem(rcx)) add(rdi, rcx) vmovups(xmm5, mem(rcx)) add(rdi, rcx) vmovups(xmm6, mem(rcx)) //add(rdi, rcx) label(.SDONE) lea(mem(r12, rdi, 2), r12) // lea(mem(r12, rdi, 1), r12) // c_ii = r12 += 3*rs_c lea(mem(r14, r8, 2), r14) // lea(mem(r14, r8, 1), r14) // a_ii = r14 += 3*rs_a dec(r9) // ii -= 1; jne(.SLOOP3X4I) // iterate again if ii != 0. add(imm(4), r15) // jj += 4; cmp(imm(16), r15) // compare jj to 16 jl(.SLOOP3X4J) // if jj < 16, jump to beginning // of jj loop; otherwise, loop ends. label(.SRETURN) end_asm( : // output operands (none) : // input operands [m_iter] "m" (m_iter), [k_iter32] "m" (k_iter32), [k_iter8] "m" (k_iter8), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the m dimension, if they exist. if ( m_left ) { const dim_t nr_cur = 16; const dim_t i_edge = m0 - ( dim_t )m_left; float* restrict cij = c + i_edge*rs_c; float* restrict bj = b; float* restrict ai = a + i_edge*rs_a; if ( 2 == m_left ) { const dim_t mr_cur = 2; bli_sgemmsup_rd_haswell_asm_2x16 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); //cij += mr_cur*rs_c0; ai += mr_cur*rs_a0; m_left -= mr_cur; } if ( 1 == m_left ) { const dim_t mr_cur = 1; bli_sgemmsup_rd_haswell_asm_1x16 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); } } } void bli_sgemmsup_rd_haswell_asm_6x12m ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter32 = k0 / 32; uint64_t k_left32 = k0 % 32; uint64_t k_iter8 = k_left32 / 8; uint64_t k_left1 = k_left32 % 8; uint64_t m_iter = m0 / 3; uint64_t m_left = m0 % 3; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; if ( m_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. //mov(var(a), r14) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) //lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a //mov(var(b), rdx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b lea(mem(r8, r8, 2), r10) // r10 = 3*rs_a //mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) // r12 = rcx = c // r14 = rax = a // rdx = rbx = b // r9 = m dim index ii // r15 = n dim index jj mov(imm(0), r15) // jj = 0; label(.SLOOP3X4J) // LOOP OVER jj = [ 0 1 ... ] mov(var(a), r14) // load address of a mov(var(b), rdx) // load address of b mov(var(c), r12) // load address of c lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(imm(1*4), rsi) // rsi *= cs_c*sizeof(float) = 1*4 lea(mem(r12, rsi, 1), r12) // r12 = c + 4*jj*cs_c; lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(r11, rsi) // rsi *= cs_b; lea(mem(rdx, rsi, 1), rdx) // rbx = b + 4*jj*cs_b; mov(var(m_iter), r9) // ii = m_iter; label(.SLOOP3X4I) // LOOP OVER ii = [ m_iter ... 1 0 ] #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorps ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorps(ymm4, ymm4, ymm4) vxorps(ymm5, ymm5, ymm5) vxorps(ymm6, ymm6, ymm6) vxorps(ymm7, ymm7, ymm7) vxorps(ymm8, ymm8, ymm8) vxorps(ymm9, ymm9, ymm9) vxorps(ymm10, ymm10, ymm10) vxorps(ymm11, ymm11, ymm11) vxorps(ymm12, ymm12, ymm12) vxorps(ymm13, ymm13, ymm13) vxorps(ymm14, ymm14, ymm14) vxorps(ymm15, ymm15, ymm15) #endif lea(mem(r12), rcx) // rcx = c_iijj; lea(mem(r14), rax) // rax = a_ii; lea(mem(rdx), rbx) // rbx = b_jj; #if 1 //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) prefetch(0, mem(rcx, 1*4)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 1*4)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 1*4)) // prefetch c + 2*rs_c #endif lea(mem(r8, r8, 4), rbp) // rbp = 5*rs_a mov(var(k_iter32), rsi) // i = k_iter32; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKITER8) // if i == 0, jump to code that // contains the k_iter8 loop. label(.SLOOPKITER32) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*rs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*rs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*rs_a #endif vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) vmovups(mem(rax, r8, 2), ymm2) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) // ---------------------------------- iteration 1 vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) vmovups(mem(rax, r8, 2), ymm2) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*rs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*rs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*rs_a #endif vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) vmovups(mem(rax, r8, 2), ymm2) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) // ---------------------------------- iteration 3 vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) vmovups(mem(rax, r8, 2), ymm2) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.SLOOPKITER32) // iterate again if i != 0. label(.SCONSIDKITER8) mov(var(k_iter8), rsi) // i = k_iter8; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter8 loop. label(.SLOOPKITER8) // EDGE LOOP (ymm) #if 1 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*rs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*rs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*rs_a #endif vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) vmovups(mem(rax, r8, 2), ymm2) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.SLOOPKITER8) // iterate again if i != 0. label(.SCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.SLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovss(mem(rax ), xmm0) vmovss(mem(rax, r8, 1), xmm1) vmovss(mem(rax, r8, 2), xmm2) add(imm(1*4), rax) // a += 1*cs_a = 1*4; vmovss(mem(rbx ), xmm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovss(mem(rbx, r11, 1), xmm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovss(mem(rbx, r11, 2), xmm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovss(mem(rbx, r13, 1), xmm3) add(imm(1*4), rbx) // b += 1*rs_b = 1*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.SLOOPKLEFT1) // iterate again if i != 0. label(.SPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 // ymm5 ymm8 ymm11 ymm14 // ymm6 ymm9 ymm12 ymm15 vhaddps( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vhaddps( xmm1, xmm0, xmm0 ) vpermilps(imm(0xd8), xmm0, xmm0) vhaddps( xmm0, xmm0, xmm0 ) vhaddps( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm3 ) vhaddps( xmm3, xmm2, xmm2 ) vpermilps(imm(0xd8), xmm2, xmm2) vhaddps( xmm2, xmm2, xmm2 ) vshufps(imm(0x44), xmm2, xmm0, xmm4) // xmm4[0] = sum(ymm4); xmm4[1] = sum(ymm7) // xmm4[2] = sum(ymm10); xmm4[3] = sum(ymm13) vhaddps( ymm8, ymm5, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vhaddps( xmm1, xmm0, xmm0 ) vpermilps(imm(0xd8), xmm0, xmm0) vhaddps( xmm0, xmm0, xmm0 ) vhaddps( ymm14, ymm11, ymm2 ) vextractf128(imm(1), ymm2, xmm3 ) vhaddps( xmm3, xmm2, xmm2 ) vpermilps(imm(0xd8), xmm2, xmm2) vhaddps( xmm2, xmm2, xmm2 ) vshufps(imm(0x44), xmm2, xmm0, xmm5) // xmm5[0] = sum(ymm5); xmm5[1] = sum(ymm8) // xmm5[2] = sum(ymm11); xmm5[3] = sum(ymm14) vhaddps( ymm9, ymm6, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vhaddps( xmm1, xmm0, xmm0 ) vpermilps(imm(0xd8), xmm0, xmm0) vhaddps( xmm0, xmm0, xmm0 ) vhaddps( ymm15, ymm12, ymm2 ) vextractf128(imm(1), ymm2, xmm3 ) vhaddps( xmm3, xmm2, xmm2 ) vpermilps(imm(0xd8), xmm2, xmm2) vhaddps( xmm2, xmm2, xmm2 ) vshufps(imm(0x44), xmm2, xmm0, xmm6) // xmm6[0] = sum(ymm6); xmm6[1] = sum(ymm9) // xmm6[2] = sum(ymm12); xmm6[3] = sum(ymm15) //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), xmm0) // load alpha and duplicate vbroadcastss(mem(rbx), xmm3) // load beta and duplicate vmulps(xmm0, xmm4, xmm4) // scale by alpha vmulps(xmm0, xmm5, xmm5) vmulps(xmm0, xmm6, xmm6) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case label(.SROWSTORED) vfmadd231ps(mem(rcx), xmm3, xmm4) vmovups(xmm4, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), xmm3, xmm5) vmovups(xmm5, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), xmm3, xmm6) vmovups(xmm6, mem(rcx)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SBETAZERO) label(.SROWSTORBZ) vmovups(xmm4, mem(rcx)) add(rdi, rcx) vmovups(xmm5, mem(rcx)) add(rdi, rcx) vmovups(xmm6, mem(rcx)) //add(rdi, rcx) label(.SDONE) lea(mem(r12, rdi, 2), r12) // lea(mem(r12, rdi, 1), r12) // c_ii = r12 += 3*rs_c lea(mem(r14, r8, 2), r14) // lea(mem(r14, r8, 1), r14) // a_ii = r14 += 3*rs_a dec(r9) // ii -= 1; jne(.SLOOP3X4I) // iterate again if ii != 0. add(imm(4), r15) // jj += 4; cmp(imm(12), r15) // compare jj to 12 jl(.SLOOP3X4J) // if jj < 12, jump to beginning // of jj loop; otherwise, loop ends. label(.SRETURN) end_asm( : // output operands (none) : // input operands [m_iter] "m" (m_iter), [k_iter32] "m" (k_iter32), [k_iter8] "m" (k_iter8), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the m dimension, if they exist. if ( m_left ) { const dim_t nr_cur = 12; const dim_t i_edge = m0 - ( dim_t )m_left; float* restrict cij = c + i_edge*rs_c; float* restrict bj = b; float* restrict ai = a + i_edge*rs_a; if ( 2 == m_left ) { const dim_t mr_cur = 2; bli_sgemmsup_rd_haswell_asm_2x12 //bli_sgemmsup_r_haswell_ref ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); //cij += mr_cur*rs_c0; ai += mr_cur*rs_a0; m_left -= mr_cur; } if ( 1 == m_left ) { const dim_t mr_cur = 1; bli_sgemmsup_rd_haswell_asm_1x12 //bli_sgemmsup_r_haswell_ref ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); } } } void bli_sgemmsup_rd_haswell_asm_6x8m ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter32 = k0 / 32; uint64_t k_left32 = k0 % 32; uint64_t k_iter8 = k_left32 / 8; uint64_t k_left1 = k_left32 % 8; uint64_t m_iter = m0 / 3; uint64_t m_left = m0 % 3; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; if ( m_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. //mov(var(a), r14) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) //lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a //mov(var(b), rdx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b lea(mem(r8, r8, 2), r10) // r10 = 3*rs_a //mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) // r12 = rcx = c // r14 = rax = a // rdx = rbx = b // r9 = m dim index ii // r15 = n dim index jj mov(imm(0), r15) // jj = 0; label(.SLOOP3X4J) // LOOP OVER jj = [ 0 1 ... ] mov(var(a), r14) // load address of a mov(var(b), rdx) // load address of b mov(var(c), r12) // load address of c lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(imm(1*4), rsi) // rsi *= cs_c*sizeof(float) = 1*4 lea(mem(r12, rsi, 1), r12) // r12 = c + 4*jj*cs_c; lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(r11, rsi) // rsi *= cs_b; lea(mem(rdx, rsi, 1), rdx) // rbx = b + 4*jj*cs_b; mov(var(m_iter), r9) // ii = m_iter; label(.SLOOP3X4I) // LOOP OVER ii = [ m_iter ... 1 0 ] #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorps ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorps(ymm4, ymm4, ymm4) vxorps(ymm5, ymm5, ymm5) vxorps(ymm6, ymm6, ymm6) vxorps(ymm7, ymm7, ymm7) vxorps(ymm8, ymm8, ymm8) vxorps(ymm9, ymm9, ymm9) vxorps(ymm10, ymm10, ymm10) vxorps(ymm11, ymm11, ymm11) vxorps(ymm12, ymm12, ymm12) vxorps(ymm13, ymm13, ymm13) vxorps(ymm14, ymm14, ymm14) vxorps(ymm15, ymm15, ymm15) #endif lea(mem(r12), rcx) // rcx = c_iijj; lea(mem(r14), rax) // rax = a_ii; lea(mem(rdx), rbx) // rbx = b_jj; #if 1 //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) prefetch(0, mem(rcx, 1*4)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 1*4)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 1*4)) // prefetch c + 2*rs_c #endif lea(mem(r8, r8, 4), rbp) // rbp = 5*rs_a mov(var(k_iter32), rsi) // i = k_iter32; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKITER8) // if i == 0, jump to code that // contains the k_iter8 loop. label(.SLOOPKITER32) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*rs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*rs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*rs_a #endif vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) vmovups(mem(rax, r8, 2), ymm2) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) // ---------------------------------- iteration 1 vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) vmovups(mem(rax, r8, 2), ymm2) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*rs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*rs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*rs_a #endif vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) vmovups(mem(rax, r8, 2), ymm2) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) // ---------------------------------- iteration 3 vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) vmovups(mem(rax, r8, 2), ymm2) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.SLOOPKITER32) // iterate again if i != 0. label(.SCONSIDKITER8) mov(var(k_iter8), rsi) // i = k_iter8; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter8 loop. label(.SLOOPKITER8) // EDGE LOOP (ymm) #if 1 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*rs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*rs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*rs_a #endif vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) vmovups(mem(rax, r8, 2), ymm2) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.SLOOPKITER8) // iterate again if i != 0. label(.SCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.SLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovss(mem(rax ), xmm0) vmovss(mem(rax, r8, 1), xmm1) vmovss(mem(rax, r8, 2), xmm2) add(imm(1*4), rax) // a += 1*cs_a = 1*4; vmovss(mem(rbx ), xmm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovss(mem(rbx, r11, 1), xmm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovss(mem(rbx, r11, 2), xmm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovss(mem(rbx, r13, 1), xmm3) add(imm(1*4), rbx) // b += 1*rs_b = 1*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.SLOOPKLEFT1) // iterate again if i != 0. label(.SPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 // ymm5 ymm8 ymm11 ymm14 // ymm6 ymm9 ymm12 ymm15 vhaddps( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vhaddps( xmm1, xmm0, xmm0 ) vpermilps(imm(0xd8), xmm0, xmm0) vhaddps( xmm0, xmm0, xmm0 ) vhaddps( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm3 ) vhaddps( xmm3, xmm2, xmm2 ) vpermilps(imm(0xd8), xmm2, xmm2) vhaddps( xmm2, xmm2, xmm2 ) vshufps(imm(0x44), xmm2, xmm0, xmm4) // xmm4[0] = sum(ymm4); xmm4[1] = sum(ymm7) // xmm4[2] = sum(ymm10); xmm4[3] = sum(ymm13) vhaddps( ymm8, ymm5, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vhaddps( xmm1, xmm0, xmm0 ) vpermilps(imm(0xd8), xmm0, xmm0) vhaddps( xmm0, xmm0, xmm0 ) vhaddps( ymm14, ymm11, ymm2 ) vextractf128(imm(1), ymm2, xmm3 ) vhaddps( xmm3, xmm2, xmm2 ) vpermilps(imm(0xd8), xmm2, xmm2) vhaddps( xmm2, xmm2, xmm2 ) vshufps(imm(0x44), xmm2, xmm0, xmm5) // xmm5[0] = sum(ymm5); xmm5[1] = sum(ymm8) // xmm5[2] = sum(ymm11); xmm5[3] = sum(ymm14) vhaddps( ymm9, ymm6, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vhaddps( xmm1, xmm0, xmm0 ) vpermilps(imm(0xd8), xmm0, xmm0) vhaddps( xmm0, xmm0, xmm0 ) vhaddps( ymm15, ymm12, ymm2 ) vextractf128(imm(1), ymm2, xmm3 ) vhaddps( xmm3, xmm2, xmm2 ) vpermilps(imm(0xd8), xmm2, xmm2) vhaddps( xmm2, xmm2, xmm2 ) vshufps(imm(0x44), xmm2, xmm0, xmm6) // xmm6[0] = sum(ymm6); xmm6[1] = sum(ymm9) // xmm6[2] = sum(ymm12); xmm6[3] = sum(ymm15) //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), xmm0) // load alpha and duplicate vbroadcastss(mem(rbx), xmm3) // load beta and duplicate vmulps(xmm0, xmm4, xmm4) // scale by alpha vmulps(xmm0, xmm5, xmm5) vmulps(xmm0, xmm6, xmm6) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case label(.SROWSTORED) vfmadd231ps(mem(rcx), xmm3, xmm4) vmovups(xmm4, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), xmm3, xmm5) vmovups(xmm5, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), xmm3, xmm6) vmovups(xmm6, mem(rcx)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SBETAZERO) label(.SROWSTORBZ) vmovups(xmm4, mem(rcx)) add(rdi, rcx) vmovups(xmm5, mem(rcx)) add(rdi, rcx) vmovups(xmm6, mem(rcx)) //add(rdi, rcx) label(.SDONE) lea(mem(r12, rdi, 2), r12) // lea(mem(r12, rdi, 1), r12) // c_ii = r12 += 3*rs_c lea(mem(r14, r8, 2), r14) // lea(mem(r14, r8, 1), r14) // a_ii = r14 += 3*rs_a dec(r9) // ii -= 1; jne(.SLOOP3X4I) // iterate again if ii != 0. add(imm(4), r15) // jj += 4; cmp(imm(8), r15) // compare jj to 8 jl(.SLOOP3X4J) // if jj < 8, jump to beginning // of jj loop; otherwise, loop ends. label(.SRETURN) end_asm( : // output operands (none) : // input operands [m_iter] "m" (m_iter), [k_iter32] "m" (k_iter32), [k_iter8] "m" (k_iter8), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the m dimension, if they exist. if ( m_left ) { const dim_t nr_cur = 8; const dim_t i_edge = m0 - ( dim_t )m_left; float* restrict cij = c + i_edge*rs_c; float* restrict bj = b; float* restrict ai = a + i_edge*rs_a; if ( 2 == m_left ) { const dim_t mr_cur = 2; bli_sgemmsup_rd_haswell_asm_2x8 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); //cij += mr_cur*rs_c0; ai += mr_cur*rs_a0; m_left -= mr_cur; } if ( 1 == m_left ) { const dim_t mr_cur = 1; bli_sgemmsup_rd_haswell_asm_1x8 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); } } } void bli_sgemmsup_rd_haswell_asm_6x4m ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter32 = k0 / 32; uint64_t k_left32 = k0 % 32; uint64_t k_iter8 = k_left32 / 8; uint64_t k_left1 = k_left32 % 8; uint64_t m_iter = m0 / 3; uint64_t m_left = m0 % 3; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; if ( m_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), r14) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) //lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rdx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b lea(mem(r8, r8, 2), r10) // r10 = 3*rs_a mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) // r12 = rcx = c // r14 = rax = a // rdx = rbx = b // r9 = m dim index ii // r15 = n dim index jj mov(var(m_iter), r9) // ii = m_iter; label(.SLOOP3X4I) // LOOP OVER ii = [ m_iter ... 1 0 ] #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorps ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorps(ymm4, ymm4, ymm4) vxorps(ymm5, ymm5, ymm5) vxorps(ymm6, ymm6, ymm6) vxorps(ymm7, ymm7, ymm7) vxorps(ymm8, ymm8, ymm8) vxorps(ymm9, ymm9, ymm9) vxorps(ymm10, ymm10, ymm10) vxorps(ymm11, ymm11, ymm11) vxorps(ymm12, ymm12, ymm12) vxorps(ymm13, ymm13, ymm13) vxorps(ymm14, ymm14, ymm14) vxorps(ymm15, ymm15, ymm15) #endif lea(mem(r12), rcx) // rcx = c_ii; lea(mem(r14), rax) // rax = a_ii; lea(mem(rdx), rbx) // rbx = b; #if 1 //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) prefetch(0, mem(rcx, 1*4)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 1*4)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 1*4)) // prefetch c + 2*rs_c #endif lea(mem(r8, r8, 4), rbp) // rbp = 5*rs_a mov(var(k_iter32), rsi) // i = k_iter32; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKITER8) // if i == 0, jump to code that // contains the k_iter8 loop. label(.SLOOPKITER32) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*rs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*rs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*rs_a #endif vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) vmovups(mem(rax, r8, 2), ymm2) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) // ---------------------------------- iteration 1 vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) vmovups(mem(rax, r8, 2), ymm2) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*rs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*rs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*rs_a #endif vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) vmovups(mem(rax, r8, 2), ymm2) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) // ---------------------------------- iteration 3 vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) vmovups(mem(rax, r8, 2), ymm2) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.SLOOPKITER32) // iterate again if i != 0. label(.SCONSIDKITER8) mov(var(k_iter8), rsi) // i = k_iter8; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter8 loop. label(.SLOOPKITER8) // EDGE LOOP (ymm) #if 1 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*rs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*rs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*rs_a #endif vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) vmovups(mem(rax, r8, 2), ymm2) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.SLOOPKITER8) // iterate again if i != 0. label(.SCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.SLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovss(mem(rax ), xmm0) vmovss(mem(rax, r8, 1), xmm1) vmovss(mem(rax, r8, 2), xmm2) add(imm(1*4), rax) // a += 1*cs_a = 1*4; vmovss(mem(rbx ), xmm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovss(mem(rbx, r11, 1), xmm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovss(mem(rbx, r11, 2), xmm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovss(mem(rbx, r13, 1), xmm3) add(imm(1*4), rbx) // b += 1*rs_b = 1*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.SLOOPKLEFT1) // iterate again if i != 0. label(.SPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 // ymm5 ymm8 ymm11 ymm14 // ymm6 ymm9 ymm12 ymm15 vhaddps( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vhaddps( xmm1, xmm0, xmm0 ) vpermilps(imm(0xd8), xmm0, xmm0) vhaddps( xmm0, xmm0, xmm0 ) vhaddps( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm3 ) vhaddps( xmm3, xmm2, xmm2 ) vpermilps(imm(0xd8), xmm2, xmm2) vhaddps( xmm2, xmm2, xmm2 ) vshufps(imm(0x44), xmm2, xmm0, xmm4) // xmm4[0] = sum(ymm4); xmm4[1] = sum(ymm7) // xmm4[2] = sum(ymm10); xmm4[3] = sum(ymm13) vhaddps( ymm8, ymm5, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vhaddps( xmm1, xmm0, xmm0 ) vpermilps(imm(0xd8), xmm0, xmm0) vhaddps( xmm0, xmm0, xmm0 ) vhaddps( ymm14, ymm11, ymm2 ) vextractf128(imm(1), ymm2, xmm3 ) vhaddps( xmm3, xmm2, xmm2 ) vpermilps(imm(0xd8), xmm2, xmm2) vhaddps( xmm2, xmm2, xmm2 ) vshufps(imm(0x44), xmm2, xmm0, xmm5) // xmm5[0] = sum(ymm5); xmm5[1] = sum(ymm8) // xmm5[2] = sum(ymm11); xmm5[3] = sum(ymm14) vhaddps( ymm9, ymm6, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vhaddps( xmm1, xmm0, xmm0 ) vpermilps(imm(0xd8), xmm0, xmm0) vhaddps( xmm0, xmm0, xmm0 ) vhaddps( ymm15, ymm12, ymm2 ) vextractf128(imm(1), ymm2, xmm3 ) vhaddps( xmm3, xmm2, xmm2 ) vpermilps(imm(0xd8), xmm2, xmm2) vhaddps( xmm2, xmm2, xmm2 ) vshufps(imm(0x44), xmm2, xmm0, xmm6) // xmm6[0] = sum(ymm6); xmm6[1] = sum(ymm9) // xmm6[2] = sum(ymm12); xmm6[3] = sum(ymm15) //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), xmm0) // load alpha and duplicate vbroadcastss(mem(rbx), xmm3) // load beta and duplicate vmulps(xmm0, xmm4, xmm4) // scale by alpha vmulps(xmm0, xmm5, xmm5) vmulps(xmm0, xmm6, xmm6) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case label(.SROWSTORED) vfmadd231ps(mem(rcx), xmm3, xmm4) vmovups(xmm4, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), xmm3, xmm5) vmovups(xmm5, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), xmm3, xmm6) vmovups(xmm6, mem(rcx)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SBETAZERO) label(.SROWSTORBZ) vmovups(xmm4, mem(rcx)) add(rdi, rcx) vmovups(xmm5, mem(rcx)) add(rdi, rcx) vmovups(xmm6, mem(rcx)) //add(rdi, rcx) label(.SDONE) lea(mem(r12, rdi, 2), r12) // lea(mem(r12, rdi, 1), r12) // c_ii = r12 += 3*rs_c lea(mem(r14, r8, 2), r14) // lea(mem(r14, r8, 1), r14) // a_ii = r14 += 3*rs_a dec(r9) // ii -= 1; jne(.SLOOP3X4I) // iterate again if ii != 0. label(.SRETURN) end_asm( : // output operands (none) : // input operands [m_iter] "m" (m_iter), [k_iter32] "m" (k_iter32), [k_iter8] "m" (k_iter8), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the m dimension, if they exist. if ( m_left ) { const dim_t nr_cur = 4; const dim_t i_edge = m0 - ( dim_t )m_left; float* restrict cij = c + i_edge*rs_c; float* restrict bj = b; float* restrict ai = a + i_edge*rs_a; if ( 2 == m_left ) { const dim_t mr_cur = 2; bli_sgemmsup_rd_haswell_asm_2x4 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); //cij += mr_cur*rs_c0; ai += mr_cur*rs_a0; m_left -= mr_cur; } if ( 1 == m_left ) { const dim_t mr_cur = 1; bli_sgemmsup_rd_haswell_asm_1x4 //bli_sgemmsup_r_haswell_ref ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); } } } void bli_sgemmsup_rd_haswell_asm_6x2m ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter32 = k0 / 32; uint64_t k_left32 = k0 % 32; uint64_t k_iter8 = k_left32 / 8; uint64_t k_left1 = k_left32 % 8; uint64_t m_iter = m0 / 6; uint64_t m_left = m0 % 6; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; if ( m_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), r14) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) //lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rdx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) //lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b //lea(mem(r8, r8, 2), r10) // r10 = 3*rs_a mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) // r12 = rcx = c // r14 = rax = a // rdx = rbx = b // r9 = m dim index ii mov(var(m_iter), r9) // ii = m_iter; label(.SLOOP3X4I) // LOOP OVER ii = [ m_iter ... 1 0 ] #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorps ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorps(ymm4, ymm4, ymm4) vxorps(ymm5, ymm5, ymm5) vxorps(ymm6, ymm6, ymm6) vxorps(ymm7, ymm7, ymm7) vxorps(ymm8, ymm8, ymm8) vxorps(ymm9, ymm9, ymm9) vxorps(ymm10, ymm10, ymm10) vxorps(ymm11, ymm11, ymm11) vxorps(ymm12, ymm12, ymm12) vxorps(ymm13, ymm13, ymm13) vxorps(ymm14, ymm14, ymm14) vxorps(ymm15, ymm15, ymm15) #endif lea(mem(r12), rcx) // rcx = c_ii; lea(mem(r14), rax) // rax = a_ii; lea(mem(rdx), rbx) // rbx = b; #if 1 //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) lea(mem(rcx, rdi, 2), r10) // lea(mem(r10, rdi, 1), r10) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 1*4)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 1*4)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 1*4)) // prefetch c + 2*rs_c prefetch(0, mem(r10, 1*4)) // prefetch c + 3*rs_c prefetch(0, mem(r10, rdi, 1, 1*4)) // prefetch c + 4*rs_c prefetch(0, mem(r10, rdi, 2, 1*4)) // prefetch c + 5*rs_c #endif mov(var(k_iter32), rsi) // i = k_iter32; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKITER8) // if i == 0, jump to code that // contains the k_iter8 loop. label(.SLOOPKITER32) // MAIN LOOP // ---------------------------------- iteration 0 #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*rs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*rs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*rs_a #endif vmovups(mem(rbx ), ymm0) vmovups(mem(rbx, r11, 1), ymm1) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vmovups(mem(rax ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovups(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vmovups(mem(rax, r8, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm8) vfmadd231ps(ymm1, ymm3, ymm9) vmovups(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vmovups(mem(rax, r8, 4), ymm3) vfmadd231ps(ymm0, ymm3, ymm12) vfmadd231ps(ymm1, ymm3, ymm13) vmovups(mem(rax, r15, 1), ymm3) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) // ---------------------------------- iteration 1 vmovups(mem(rbx ), ymm0) vmovups(mem(rbx, r11, 1), ymm1) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vmovups(mem(rax ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovups(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vmovups(mem(rax, r8, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm8) vfmadd231ps(ymm1, ymm3, ymm9) vmovups(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vmovups(mem(rax, r8, 4), ymm3) vfmadd231ps(ymm0, ymm3, ymm12) vfmadd231ps(ymm1, ymm3, ymm13) vmovups(mem(rax, r15, 1), ymm3) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) // ---------------------------------- iteration 2 #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*rs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*rs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*rs_a #endif vmovups(mem(rbx ), ymm0) vmovups(mem(rbx, r11, 1), ymm1) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vmovups(mem(rax ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovups(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vmovups(mem(rax, r8, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm8) vfmadd231ps(ymm1, ymm3, ymm9) vmovups(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vmovups(mem(rax, r8, 4), ymm3) vfmadd231ps(ymm0, ymm3, ymm12) vfmadd231ps(ymm1, ymm3, ymm13) vmovups(mem(rax, r15, 1), ymm3) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) // ---------------------------------- iteration 3 vmovups(mem(rbx ), ymm0) vmovups(mem(rbx, r11, 1), ymm1) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vmovups(mem(rax ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovups(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vmovups(mem(rax, r8, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm8) vfmadd231ps(ymm1, ymm3, ymm9) vmovups(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vmovups(mem(rax, r8, 4), ymm3) vfmadd231ps(ymm0, ymm3, ymm12) vfmadd231ps(ymm1, ymm3, ymm13) vmovups(mem(rax, r15, 1), ymm3) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) dec(rsi) // i -= 1; jne(.SLOOPKITER32) // iterate again if i != 0. label(.SCONSIDKITER8) mov(var(k_iter8), rsi) // i = k_iter8; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter8 loop. label(.SLOOPKITER8) // EDGE LOOP (ymm) #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*rs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*rs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*rs_a #endif vmovups(mem(rbx ), ymm0) vmovups(mem(rbx, r11, 1), ymm1) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vmovups(mem(rax ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovups(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vmovups(mem(rax, r8, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm8) vfmadd231ps(ymm1, ymm3, ymm9) vmovups(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vmovups(mem(rax, r8, 4), ymm3) vfmadd231ps(ymm0, ymm3, ymm12) vfmadd231ps(ymm1, ymm3, ymm13) vmovups(mem(rax, r15, 1), ymm3) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) dec(rsi) // i -= 1; jne(.SLOOPKITER8) // iterate again if i != 0. label(.SCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.SLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovss(mem(rbx ), xmm0) vmovss(mem(rbx, r11, 1), xmm1) add(imm(1*4), rbx) // b += 8*rs_b = 8*4; vmovss(mem(rax ), xmm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovss(mem(rax, r8, 1), xmm3) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vmovss(mem(rax, r8, 2), xmm3) vfmadd231ps(ymm0, ymm3, ymm8) vfmadd231ps(ymm1, ymm3, ymm9) vmovss(mem(rax, r13, 1), xmm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vmovss(mem(rax, r8, 4), xmm3) vfmadd231ps(ymm0, ymm3, ymm12) vfmadd231ps(ymm1, ymm3, ymm13) vmovss(mem(rax, r15, 1), xmm3) add(imm(1*4), rax) // a += 8*cs_a = 8*4; vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) dec(rsi) // i -= 1; jne(.SLOOPKLEFT1) // iterate again if i != 0. label(.SPOSTACCUM) // ymm4 ymm5 // ymm6 ymm7 // ymm8 ymm9 // ymm10 ymm11 // ymm12 ymm13 // ymm14 ymm15 vhaddps( ymm5, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vhaddps( xmm1, xmm0, xmm0 ) vpermilps(imm(0xd8), xmm0, xmm0) vhaddps( xmm0, xmm0, xmm4 ) vhaddps( ymm7, ymm6, ymm2 ) vextractf128(imm(1), ymm2, xmm3 ) vhaddps( xmm3, xmm2, xmm2 ) vpermilps(imm(0xd8), xmm2, xmm2) vhaddps( xmm2, xmm2, xmm6 ) vhaddps( ymm9, ymm8, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vhaddps( xmm1, xmm0, xmm0 ) vpermilps(imm(0xd8), xmm0, xmm0) vhaddps( xmm0, xmm0, xmm8 ) vhaddps( ymm11, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm3 ) vhaddps( xmm3, xmm2, xmm2 ) vpermilps(imm(0xd8), xmm2, xmm2) vhaddps( xmm2, xmm2, xmm10 ) vhaddps( ymm13, ymm12, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vhaddps( xmm1, xmm0, xmm0 ) vpermilps(imm(0xd8), xmm0, xmm0) vhaddps( xmm0, xmm0, xmm12 ) vhaddps( ymm15, ymm14, ymm2 ) vextractf128(imm(1), ymm2, xmm3 ) vhaddps( xmm3, xmm2, xmm2 ) vpermilps(imm(0xd8), xmm2, xmm2) vhaddps( xmm2, xmm2, xmm14 ) // xmm4[0:1] = sum(ymm4) sum(ymm5) // xmm6[0:1] = sum(ymm6) sum(ymm7) // xmm8[0:1] = sum(ymm8) sum(ymm9) // xmm10[0:1] = sum(ymm10) sum(ymm11) // xmm12[0:1] = sum(ymm12) sum(ymm13) // xmm14[0:1] = sum(ymm14) sum(ymm15) //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), xmm0) // load alpha and duplicate vbroadcastss(mem(rbx), xmm3) // load beta and duplicate vmulps(xmm0, xmm4, xmm4) // scale by alpha vmulps(xmm0, xmm6, xmm6) vmulps(xmm0, xmm8, xmm8) vmulps(xmm0, xmm10, xmm10) vmulps(xmm0, xmm12, xmm12) vmulps(xmm0, xmm14, xmm14) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case label(.SROWSTORED) vmovsd(mem(rcx), xmm0) vfmadd231ps(xmm0, xmm3, xmm4) vmovsd(xmm4, mem(rcx)) add(rdi, rcx) vmovsd(mem(rcx), xmm0) vfmadd231ps(xmm0, xmm3, xmm6) vmovsd(xmm6, mem(rcx)) add(rdi, rcx) vmovsd(mem(rcx), xmm0) vfmadd231ps(xmm0, xmm3, xmm8) vmovsd(xmm8, mem(rcx)) add(rdi, rcx) vmovsd(mem(rcx), xmm0) vfmadd231ps(xmm0, xmm3, xmm10) vmovsd(xmm10, mem(rcx)) add(rdi, rcx) vmovsd(mem(rcx), xmm0) vfmadd231ps(xmm0, xmm3, xmm12) vmovsd(xmm12, mem(rcx)) add(rdi, rcx) vmovsd(mem(rcx), xmm0) vfmadd231ps(xmm0, xmm3, xmm14) vmovsd(xmm14, mem(rcx)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SBETAZERO) label(.SROWSTORBZ) vmovsd(xmm4, mem(rcx)) add(rdi, rcx) vmovsd(xmm6, mem(rcx)) add(rdi, rcx) vmovsd(xmm8, mem(rcx)) add(rdi, rcx) vmovsd(xmm10, mem(rcx)) add(rdi, rcx) vmovsd(xmm12, mem(rcx)) add(rdi, rcx) vmovsd(xmm14, mem(rcx)) //add(rdi, rcx) label(.SDONE) lea(mem(r12, rdi, 4), r12) // lea(mem(r12, rdi, 2), r12) // c_ii = r12 += 6*rs_c lea(mem(r14, r8, 4), r14) // lea(mem(r14, r8, 2), r14) // a_ii = r14 += 6*rs_a dec(r9) // ii -= 1; jne(.SLOOP3X4I) // iterate again if ii != 0. label(.SRETURN) end_asm( : // output operands (none) : // input operands [m_iter] "m" (m_iter), [k_iter32] "m" (k_iter32), [k_iter8] "m" (k_iter8), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the m dimension, if they exist. if ( m_left ) { const dim_t nr_cur = 2; const dim_t i_edge = m0 - ( dim_t )m_left; float* restrict cij = c + i_edge*rs_c; float* restrict bj = b; float* restrict ai = a + i_edge*rs_a; if ( 3 <= m_left ) { const dim_t mr_cur = 3; bli_sgemmsup_rd_haswell_asm_3x2 //bli_sgemmsup_r_haswell_ref ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += mr_cur*rs_c0; ai += mr_cur*rs_a0; m_left -= mr_cur; } if ( 2 <= m_left ) { const dim_t mr_cur = 2; bli_sgemmsup_rd_haswell_asm_2x2 //bli_sgemmsup_r_haswell_ref ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += mr_cur*rs_c0; ai += mr_cur*rs_a0; m_left -= mr_cur; } if ( 1 == m_left ) { const dim_t mr_cur = 1; bli_sgemmsup_rd_haswell_asm_1x2 //bli_sgemmsup_r_haswell_ref ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); } } } blis-0.9.0/kernels/haswell/3/sup/bli_gemmsup_rd_haswell_asm_s6x16n.c000066400000000000000000001766231422157504600254110ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define BLIS_ASM_SYNTAX_ATT #include "bli_x86_asm_macros.h" /* rrc: -------- ------ | | | | | | | | -------- ------ | | | | | | | | -------- += ------ ... | | | | | | | | -------- ------ | | | | | | | | -------- ------ : -------- ------ : Assumptions: - C is row-stored and B is column-stored; - A is row-stored; - m0 and n0 are at most MR and NR, respectively. Therefore, this (r)ow-preferential microkernel is well-suited for a dot-product-based accumulation that performs vector loads from both A and B. NOTE: These kernels implicitly support column-oriented IO, implemented via an a high-level transposition of the entire operation. A and B will effectively remain row- and column-stored, respectively, but C will then effectively appear column-stored. Thus, this kernel may be used for both rrc and crc cases. */ // Prototype reference microkernels. GEMMSUP_KER_PROT( float, s, gemmsup_r_haswell_ref ) void bli_sgemmsup_rd_haswell_asm_6x16n ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { uint64_t m_left = m0 % 6; // First check whether this is a edge case in the n dimension. If so, // dispatch other ?x8m kernels, as needed. if ( m_left ) { float* restrict cij = c; float* restrict bj = b; float* restrict ai = a; #if 1 // We add special handling for slightly inflated MR blocksizes // at edge cases, up to a maximum of 9. if ( 6 < m0 ) { sgemmsup_ker_ft ker_fp1 = NULL; sgemmsup_ker_ft ker_fp2 = NULL; dim_t mr1, mr2; // These kernels don't make any attempt to optimize the cases of // inflated MR blocksizes because they don't benefit from the // load balancing that the "rv" kernels do. That is, if m0 = 7, // there is no benefit to executing that case as 4x16n followed // by 3x16n because 4x16n isn't implemented, and more generally // because these kernels are implemented as loops over their // true blocksizes, which are MR=3 NR=4. if ( m0 == 7 ) { mr1 = 6; mr2 = 1; ker_fp1 = bli_sgemmsup_rd_haswell_asm_6x16n; ker_fp2 = bli_sgemmsup_rd_haswell_asm_1x16n; } else if ( m0 == 8 ) { mr1 = 6; mr2 = 2; ker_fp1 = bli_sgemmsup_rd_haswell_asm_6x16n; ker_fp2 = bli_sgemmsup_rd_haswell_asm_2x16n; } else // if ( m0 == 9 ) { mr1 = 6; mr2 = 3; ker_fp1 = bli_sgemmsup_rd_haswell_asm_6x16n; ker_fp2 = bli_sgemmsup_rd_haswell_asm_3x16n; } ker_fp1 ( conja, conjb, mr1, n0, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += mr1*rs_c0; ai += mr1*rs_a0; ker_fp2 ( conja, conjb, mr2, n0, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); return; } #endif if ( 3 <= m_left ) { const dim_t mr_cur = 3; bli_sgemmsup_rd_haswell_asm_3x16n //bli_sgemmsup_r_haswell_ref ( conja, conjb, mr_cur, n0, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += mr_cur*rs_c0; ai += mr_cur*rs_a0; m_left -= mr_cur; } if ( 2 <= m_left ) { const dim_t mr_cur = 2; bli_sgemmsup_rd_haswell_asm_2x16n //bli_sgemmsup_r_haswell_ref ( conja, conjb, mr_cur, n0, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += mr_cur*rs_c0; ai += mr_cur*rs_a0; m_left -= mr_cur; } if ( 1 == m_left ) { #if 1 const dim_t mr_cur = 1; bli_sgemmsup_rd_haswell_asm_1x16n //bli_sgemmsup_r_haswell_ref ( conja, conjb, mr_cur, n0, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); #else bli_sgemv_ex ( BLIS_TRANSPOSE, conja, k0, n0, alpha, bj, rs_b0, cs_b0, ai, cs_a0, beta, cij, cs_c0, cntx, NULL ); #endif } return; } //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter32 = k0 / 32; uint64_t k_left32 = k0 % 32; uint64_t k_iter8 = k_left32 / 8; uint64_t k_left1 = k_left32 % 8; uint64_t n_iter = n0 / 4; uint64_t n_left = n0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; if ( n_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), rdx) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) //lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a //mov(var(b), r14) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b //mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) // r12 = rcx = c // rdx = rax = a // r14 = rbx = b // r9 = m dim index ii // r15 = n dim index jj mov(imm(0), r9) // ii = 0; label(.SLOOP3X4I) // LOOP OVER ii = [ 0 1 ... ] mov(var(b), r14) // load address of b mov(var(c), r12) // load address of c //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) lea(mem( , r9, 1), rsi) // rsi = r9 = 3*ii; imul(rdi, rsi) // rsi *= rs_c lea(mem(r12, rsi, 1), r12) // r12 = c + 3*ii*rs_c; lea(mem( , r9, 1), rsi) // rsi = r9 = 3*ii; imul(r8, rsi) // rsi *= rs_a; lea(mem(rdx, rsi, 1), rdx) // rax = a + 3*ii*rs_a; mov(var(n_iter), r15) // jj = n_iter; label(.SLOOP3X4J) // LOOP OVER jj = [ n_iter ... 1 0 ] #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorps ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorps(ymm4, ymm4, ymm4) vxorps(ymm5, ymm5, ymm5) vxorps(ymm6, ymm6, ymm6) vxorps(ymm7, ymm7, ymm7) vxorps(ymm8, ymm8, ymm8) vxorps(ymm9, ymm9, ymm9) vxorps(ymm10, ymm10, ymm10) vxorps(ymm11, ymm11, ymm11) vxorps(ymm12, ymm12, ymm12) vxorps(ymm13, ymm13, ymm13) vxorps(ymm14, ymm14, ymm14) vxorps(ymm15, ymm15, ymm15) #endif lea(mem(r12), rcx) // rcx = c_iijj; lea(mem(rdx), rax) // rax = a_ii; lea(mem(r14), rbx) // rbx = b_jj; #if 1 //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) prefetch(0, mem(rcx, 1*4)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 1*4)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 1*4)) // prefetch c + 2*rs_c #endif //lea(mem(r8, r8, 4), rbp) // rbp = 5*rs_a lea(mem(rbx, r11, 4), r10) // r10 = rbx + 4*cs_b mov(var(k_iter32), rsi) // i = k_iter32; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKITER8) // if i == 0, jump to code that // contains the k_iter8 loop. label(.SLOOPKITER32) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(r10, 0*8)) // prefetch rbx + 4*cs_b prefetch(0, mem(r10, r11, 1, 0*8)) // prefetch rbx + 5*cs_b #endif vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) vmovups(mem(rax, r8, 2), ymm2) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) // ---------------------------------- iteration 1 #if 1 prefetch(0, mem(r10, r11, 2, 0*8)) // prefetch rbx + 6*cs_b prefetch(0, mem(r10, r13, 1, 0*8)) // prefetch rbx + 7*cs_b #endif vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) vmovups(mem(rax, r8, 2), ymm2) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(r10, 8*8)) // prefetch rbx + 4*cs_b + 8*rs_b prefetch(0, mem(r10, r11, 1, 8*8)) // prefetch rbx + 5*cs_b + 8*rs_b #endif vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) vmovups(mem(rax, r8, 2), ymm2) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) // ---------------------------------- iteration 3 #if 1 prefetch(0, mem(r10, r11, 2, 8*8)) // prefetch rbx + 6*cs_b + 8*rs_b prefetch(0, mem(r10, r13, 1, 8*8)) // prefetch rbx + 7*cs_b + 8*rs_b add(imm(32*4), r10) // r10 += 32*rs_b = 32*4; #endif vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) vmovups(mem(rax, r8, 2), ymm2) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.SLOOPKITER32) // iterate again if i != 0. label(.SCONSIDKITER8) mov(var(k_iter8), rsi) // i = k_iter8; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter8 loop. label(.SLOOPKITER8) // EDGE LOOP (ymm) vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) vmovups(mem(rax, r8, 2), ymm2) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.SLOOPKITER8) // iterate again if i != 0. label(.SCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.SLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovss(mem(rax ), xmm0) vmovss(mem(rax, r8, 1), xmm1) vmovss(mem(rax, r8, 2), xmm2) add(imm(1*4), rax) // a += 1*cs_a = 1*4; vmovss(mem(rbx ), xmm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovss(mem(rbx, r11, 1), xmm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovss(mem(rbx, r11, 2), xmm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovss(mem(rbx, r13, 1), xmm3) add(imm(1*4), rbx) // b += 1*rs_b = 1*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.SLOOPKLEFT1) // iterate again if i != 0. label(.SPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 // ymm5 ymm8 ymm11 ymm14 // ymm6 ymm9 ymm12 ymm15 vhaddps( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vhaddps( xmm1, xmm0, xmm0 ) vpermilps(imm(0xd8), xmm0, xmm0) vhaddps( xmm0, xmm0, xmm0 ) vhaddps( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm3 ) vhaddps( xmm3, xmm2, xmm2 ) vpermilps(imm(0xd8), xmm2, xmm2) vhaddps( xmm2, xmm2, xmm2 ) vshufps(imm(0x44), xmm2, xmm0, xmm4) // xmm4[0] = sum(ymm4); xmm4[1] = sum(ymm7) // xmm4[2] = sum(ymm10); xmm4[3] = sum(ymm13) vhaddps( ymm8, ymm5, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vhaddps( xmm1, xmm0, xmm0 ) vpermilps(imm(0xd8), xmm0, xmm0) vhaddps( xmm0, xmm0, xmm0 ) vhaddps( ymm14, ymm11, ymm2 ) vextractf128(imm(1), ymm2, xmm3 ) vhaddps( xmm3, xmm2, xmm2 ) vpermilps(imm(0xd8), xmm2, xmm2) vhaddps( xmm2, xmm2, xmm2 ) vshufps(imm(0x44), xmm2, xmm0, xmm5) // xmm5[0] = sum(ymm5); xmm5[1] = sum(ymm8) // xmm5[2] = sum(ymm11); xmm5[3] = sum(ymm14) vhaddps( ymm9, ymm6, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vhaddps( xmm1, xmm0, xmm0 ) vpermilps(imm(0xd8), xmm0, xmm0) vhaddps( xmm0, xmm0, xmm0 ) vhaddps( ymm15, ymm12, ymm2 ) vextractf128(imm(1), ymm2, xmm3 ) vhaddps( xmm3, xmm2, xmm2 ) vpermilps(imm(0xd8), xmm2, xmm2) vhaddps( xmm2, xmm2, xmm2 ) vshufps(imm(0x44), xmm2, xmm0, xmm6) // xmm6[0] = sum(ymm6); xmm6[1] = sum(ymm9) // xmm6[2] = sum(ymm12); xmm6[3] = sum(ymm15) //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), xmm0) // load alpha and duplicate vbroadcastss(mem(rbx), xmm3) // load beta and duplicate vmulps(xmm0, xmm4, xmm4) // scale by alpha vmulps(xmm0, xmm5, xmm5) vmulps(xmm0, xmm6, xmm6) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case label(.SROWSTORED) vfmadd231ps(mem(rcx), xmm3, xmm4) vmovups(xmm4, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), xmm3, xmm5) vmovups(xmm5, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), xmm3, xmm6) vmovups(xmm6, mem(rcx)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SBETAZERO) label(.SROWSTORBZ) vmovups(xmm4, mem(rcx)) add(rdi, rcx) vmovups(xmm5, mem(rcx)) add(rdi, rcx) vmovups(xmm6, mem(rcx)) //add(rdi, rcx) label(.SDONE) add(imm(4*4), r12) // c_jj = r12 += 4*cs_c lea(mem(r14, r11, 4), r14) // b_jj = r14 += 4*cs_b dec(r15) // jj -= 1; jne(.SLOOP3X4J) // iterate again if jj != 0. add(imm(3), r9) // ii += 3; cmp(imm(6), r9) // compare jj to 6 jl(.SLOOP3X4I) // if ii < 6, jump to beginning // of ii loop; otherwise, loop ends. label(.SRETURN) end_asm( : // output operands (none) : // input operands [n_iter] "m" (n_iter), [k_iter32] "m" (k_iter32), [k_iter8] "m" (k_iter8), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the n dimension, if they exist. if ( n_left ) { const dim_t mr_cur = 6; const dim_t j_edge = n0 - ( dim_t )n_left; float* restrict cij = c + j_edge*cs_c; float* restrict ai = a; float* restrict bj = b + j_edge*cs_b; if ( 2 <= n_left ) { const dim_t nr_cur = 2; bli_sgemmsup_rd_haswell_asm_6x2 //bli_sgemmsup_r_haswell_ref ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 1 == n_left ) { #if 1 const dim_t nr_cur = 1; bli_sgemmsup_rd_haswell_asm_6x1 //bli_sgemmsup_r_haswell_ref ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); #else bli_sgemv_ex ( BLIS_NO_TRANSPOSE, conjb, mr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, beta, cij, rs_c0, cntx, NULL ); #endif } } } void bli_sgemmsup_rd_haswell_asm_3x16n ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter32 = k0 / 32; uint64_t k_left32 = k0 % 32; uint64_t k_iter8 = k_left32 / 8; uint64_t k_left1 = k_left32 % 8; uint64_t n_iter = n0 / 4; uint64_t n_left = n0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; if ( n_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), rdx) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) //lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), r14) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) // r12 = rcx = c // rdx = rax = a // r14 = rbx = b // r9 = unused // r15 = n dim index jj mov(var(n_iter), r15) // jj = n_iter; label(.SLOOP3X4J) // LOOP OVER jj = [ n_iter ... 1 0 ] #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorps ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorps(ymm4, ymm4, ymm4) vxorps(ymm5, ymm5, ymm5) vxorps(ymm6, ymm6, ymm6) vxorps(ymm7, ymm7, ymm7) vxorps(ymm8, ymm8, ymm8) vxorps(ymm9, ymm9, ymm9) vxorps(ymm10, ymm10, ymm10) vxorps(ymm11, ymm11, ymm11) vxorps(ymm12, ymm12, ymm12) vxorps(ymm13, ymm13, ymm13) vxorps(ymm14, ymm14, ymm14) vxorps(ymm15, ymm15, ymm15) #endif lea(mem(r12), rcx) // rcx = c_iijj; lea(mem(rdx), rax) // rax = a_ii; lea(mem(r14), rbx) // rbx = b_jj; #if 1 //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) prefetch(0, mem(rcx, 1*4)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 1*4)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 1*4)) // prefetch c + 2*rs_c #endif //lea(mem(r8, r8, 4), rbp) // rbp = 5*rs_a lea(mem(rbx, r11, 4), r10) // r10 = rbx + 4*cs_b mov(var(k_iter32), rsi) // i = k_iter32; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKITER8) // if i == 0, jump to code that // contains the k_iter8 loop. label(.SLOOPKITER32) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(r10, 0*8)) // prefetch rbx + 4*cs_b prefetch(0, mem(r10, r11, 1, 0*8)) // prefetch rbx + 5*cs_b #endif vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) vmovups(mem(rax, r8, 2), ymm2) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) // ---------------------------------- iteration 1 #if 1 prefetch(0, mem(r10, r11, 2, 0*8)) // prefetch rbx + 6*cs_b prefetch(0, mem(r10, r13, 1, 0*8)) // prefetch rbx + 7*cs_b #endif vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) vmovups(mem(rax, r8, 2), ymm2) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(r10, 8*8)) // prefetch rbx + 4*cs_b + 8*rs_b prefetch(0, mem(r10, r11, 1, 8*8)) // prefetch rbx + 5*cs_b + 8*rs_b #endif vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) vmovups(mem(rax, r8, 2), ymm2) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) // ---------------------------------- iteration 3 #if 1 prefetch(0, mem(r10, r11, 2, 8*8)) // prefetch rbx + 6*cs_b + 8*rs_b prefetch(0, mem(r10, r13, 1, 8*8)) // prefetch rbx + 7*cs_b + 8*rs_b add(imm(32*4), r10) // r10 += 32*rs_b = 32*4; #endif vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) vmovups(mem(rax, r8, 2), ymm2) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.SLOOPKITER32) // iterate again if i != 0. label(.SCONSIDKITER8) mov(var(k_iter8), rsi) // i = k_iter8; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter8 loop. label(.SLOOPKITER8) // EDGE LOOP (ymm) vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) vmovups(mem(rax, r8, 2), ymm2) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.SLOOPKITER8) // iterate again if i != 0. label(.SCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.SLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovss(mem(rax ), xmm0) vmovss(mem(rax, r8, 1), xmm1) vmovss(mem(rax, r8, 2), xmm2) add(imm(1*4), rax) // a += 1*cs_a = 1*4; vmovss(mem(rbx ), xmm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovss(mem(rbx, r11, 1), xmm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovss(mem(rbx, r11, 2), xmm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovss(mem(rbx, r13, 1), xmm3) add(imm(1*4), rbx) // b += 1*rs_b = 1*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.SLOOPKLEFT1) // iterate again if i != 0. label(.SPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 // ymm5 ymm8 ymm11 ymm14 // ymm6 ymm9 ymm12 ymm15 vhaddps( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vhaddps( xmm1, xmm0, xmm0 ) vpermilps(imm(0xd8), xmm0, xmm0) vhaddps( xmm0, xmm0, xmm0 ) vhaddps( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm3 ) vhaddps( xmm3, xmm2, xmm2 ) vpermilps(imm(0xd8), xmm2, xmm2) vhaddps( xmm2, xmm2, xmm2 ) vshufps(imm(0x44), xmm2, xmm0, xmm4) // xmm4[0] = sum(ymm4); xmm4[1] = sum(ymm7) // xmm4[2] = sum(ymm10); xmm4[3] = sum(ymm13) vhaddps( ymm8, ymm5, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vhaddps( xmm1, xmm0, xmm0 ) vpermilps(imm(0xd8), xmm0, xmm0) vhaddps( xmm0, xmm0, xmm0 ) vhaddps( ymm14, ymm11, ymm2 ) vextractf128(imm(1), ymm2, xmm3 ) vhaddps( xmm3, xmm2, xmm2 ) vpermilps(imm(0xd8), xmm2, xmm2) vhaddps( xmm2, xmm2, xmm2 ) vshufps(imm(0x44), xmm2, xmm0, xmm5) // xmm5[0] = sum(ymm5); xmm5[1] = sum(ymm8) // xmm5[2] = sum(ymm11); xmm5[3] = sum(ymm14) vhaddps( ymm9, ymm6, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vhaddps( xmm1, xmm0, xmm0 ) vpermilps(imm(0xd8), xmm0, xmm0) vhaddps( xmm0, xmm0, xmm0 ) vhaddps( ymm15, ymm12, ymm2 ) vextractf128(imm(1), ymm2, xmm3 ) vhaddps( xmm3, xmm2, xmm2 ) vpermilps(imm(0xd8), xmm2, xmm2) vhaddps( xmm2, xmm2, xmm2 ) vshufps(imm(0x44), xmm2, xmm0, xmm6) // xmm6[0] = sum(ymm6); xmm6[1] = sum(ymm9) // xmm6[2] = sum(ymm12); xmm6[3] = sum(ymm15) //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), xmm0) // load alpha and duplicate vbroadcastss(mem(rbx), xmm3) // load beta and duplicate vmulps(xmm0, xmm4, xmm4) // scale by alpha vmulps(xmm0, xmm5, xmm5) vmulps(xmm0, xmm6, xmm6) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case label(.SROWSTORED) vfmadd231ps(mem(rcx), xmm3, xmm4) vmovups(xmm4, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), xmm3, xmm5) vmovups(xmm5, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), xmm3, xmm6) vmovups(xmm6, mem(rcx)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SBETAZERO) label(.SROWSTORBZ) vmovups(xmm4, mem(rcx)) add(rdi, rcx) vmovups(xmm5, mem(rcx)) add(rdi, rcx) vmovups(xmm6, mem(rcx)) //add(rdi, rcx) label(.SDONE) add(imm(4*4), r12) // c_jj = r12 += 4*cs_c lea(mem(r14, r11, 4), r14) // b_jj = r14 += 4*cs_b dec(r15) // jj -= 1; jne(.SLOOP3X4J) // iterate again if jj != 0. label(.SRETURN) end_asm( : // output operands (none) : // input operands [n_iter] "m" (n_iter), [k_iter32] "m" (k_iter32), [k_iter8] "m" (k_iter8), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the n dimension, if they exist. if ( n_left ) { const dim_t mr_cur = 3; const dim_t j_edge = n0 - ( dim_t )n_left; float* restrict cij = c + j_edge*cs_c; float* restrict ai = a; float* restrict bj = b + j_edge*cs_b; if ( 2 <= n_left ) { const dim_t nr_cur = 2; bli_sgemmsup_rd_haswell_asm_3x2 //bli_sgemmsup_r_haswell_ref ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 1 == n_left ) { #if 1 const dim_t nr_cur = 1; bli_sgemmsup_rd_haswell_asm_3x1 //bli_sgemmsup_r_haswell_ref_3x1 //bli_sgemmsup_r_haswell_ref ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); #else bli_sgemv_ex ( BLIS_NO_TRANSPOSE, conjb, mr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, beta, cij, rs_c0, cntx, NULL ); #endif } } } void bli_sgemmsup_rd_haswell_asm_2x16n ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter32 = k0 / 32; uint64_t k_left32 = k0 % 32; uint64_t k_iter8 = k_left32 / 8; uint64_t k_left1 = k_left32 % 8; uint64_t n_iter = n0 / 4; uint64_t n_left = n0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; if ( n_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), rdx) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) //lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), r14) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) // r12 = rcx = c // rdx = rax = a // r14 = rbx = b // r9 = unused // r15 = n dim index jj mov(var(n_iter), r15) // jj = n_iter; label(.SLOOP3X4J) // LOOP OVER jj = [ n_iter ... 1 0 ] #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorps ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorps(ymm4, ymm4, ymm4) vxorps(ymm5, ymm5, ymm5) vxorps(ymm7, ymm7, ymm7) vxorps(ymm8, ymm8, ymm8) vxorps(ymm10, ymm10, ymm10) vxorps(ymm11, ymm11, ymm11) vxorps(ymm13, ymm13, ymm13) vxorps(ymm14, ymm14, ymm14) #endif lea(mem(r12), rcx) // rcx = c_iijj; lea(mem(rdx), rax) // rax = a_ii; lea(mem(r14), rbx) // rbx = b_jj; #if 1 //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) prefetch(0, mem(rcx, 1*4)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 1*4)) // prefetch c + 1*rs_c #endif //lea(mem(r8, r8, 4), rbp) // rbp = 5*rs_a lea(mem(rbx, r11, 4), r10) // r10 = rbx + 4*cs_b mov(var(k_iter32), rsi) // i = k_iter32; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKITER8) // if i == 0, jump to code that // contains the k_iter8 loop. label(.SLOOPKITER32) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(r10, 0*8)) // prefetch rbx + 4*cs_b prefetch(0, mem(r10, r11, 1, 0*8)) // prefetch rbx + 5*cs_b #endif vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) // ---------------------------------- iteration 1 #if 1 prefetch(0, mem(r10, r11, 2, 0*8)) // prefetch rbx + 6*cs_b prefetch(0, mem(r10, r13, 1, 0*8)) // prefetch rbx + 7*cs_b #endif vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(r10, 8*8)) // prefetch rbx + 4*cs_b + 8*rs_b prefetch(0, mem(r10, r11, 1, 8*8)) // prefetch rbx + 5*cs_b + 8*rs_b #endif vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) // ---------------------------------- iteration 3 #if 1 prefetch(0, mem(r10, r11, 2, 8*8)) // prefetch rbx + 6*cs_b + 8*rs_b prefetch(0, mem(r10, r13, 1, 8*8)) // prefetch rbx + 7*cs_b + 8*rs_b add(imm(32*4), r10) // r10 += 32*rs_b = 32*4; #endif vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) dec(rsi) // i -= 1; jne(.SLOOPKITER32) // iterate again if i != 0. label(.SCONSIDKITER8) mov(var(k_iter8), rsi) // i = k_iter8; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter8 loop. label(.SLOOPKITER8) // EDGE LOOP (ymm) vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) dec(rsi) // i -= 1; jne(.SLOOPKITER8) // iterate again if i != 0. label(.SCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.SLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovss(mem(rax ), xmm0) vmovss(mem(rax, r8, 1), xmm1) add(imm(1*4), rax) // a += 1*cs_a = 1*4; vmovss(mem(rbx ), xmm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovss(mem(rbx, r11, 1), xmm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vmovss(mem(rbx, r11, 2), xmm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vmovss(mem(rbx, r13, 1), xmm3) add(imm(1*4), rbx) // b += 1*rs_b = 1*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) dec(rsi) // i -= 1; jne(.SLOOPKLEFT1) // iterate again if i != 0. label(.SPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 // ymm5 ymm8 ymm11 ymm14 vhaddps( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vhaddps( xmm1, xmm0, xmm0 ) vpermilps(imm(0xd8), xmm0, xmm0) vhaddps( xmm0, xmm0, xmm0 ) vhaddps( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm3 ) vhaddps( xmm3, xmm2, xmm2 ) vpermilps(imm(0xd8), xmm2, xmm2) vhaddps( xmm2, xmm2, xmm2 ) vshufps(imm(0x44), xmm2, xmm0, xmm4) // xmm4[0] = sum(ymm4); xmm4[1] = sum(ymm7) // xmm4[2] = sum(ymm10); xmm4[3] = sum(ymm13) vhaddps( ymm8, ymm5, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vhaddps( xmm1, xmm0, xmm0 ) vpermilps(imm(0xd8), xmm0, xmm0) vhaddps( xmm0, xmm0, xmm0 ) vhaddps( ymm14, ymm11, ymm2 ) vextractf128(imm(1), ymm2, xmm3 ) vhaddps( xmm3, xmm2, xmm2 ) vpermilps(imm(0xd8), xmm2, xmm2) vhaddps( xmm2, xmm2, xmm2 ) vshufps(imm(0x44), xmm2, xmm0, xmm5) // xmm5[0] = sum(ymm5); xmm5[1] = sum(ymm8) // xmm5[2] = sum(ymm11); xmm5[3] = sum(ymm14) //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), xmm0) // load alpha and duplicate vbroadcastss(mem(rbx), xmm3) // load beta and duplicate vmulps(xmm0, xmm4, xmm4) // scale by alpha vmulps(xmm0, xmm5, xmm5) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case label(.SROWSTORED) vfmadd231ps(mem(rcx), xmm3, xmm4) vmovups(xmm4, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), xmm3, xmm5) vmovups(xmm5, mem(rcx)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SBETAZERO) label(.SROWSTORBZ) vmovups(xmm4, mem(rcx)) add(rdi, rcx) vmovups(xmm5, mem(rcx)) //add(rdi, rcx) label(.SDONE) add(imm(4*4), r12) // c_jj = r12 += 4*cs_c lea(mem(r14, r11, 4), r14) // b_jj = r14 += 4*cs_b dec(r15) // jj -= 1; jne(.SLOOP3X4J) // iterate again if jj != 0. label(.SRETURN) end_asm( : // output operands (none) : // input operands [n_iter] "m" (n_iter), [k_iter32] "m" (k_iter32), [k_iter8] "m" (k_iter8), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the n dimension, if they exist. if ( n_left ) { const dim_t mr_cur = 2; const dim_t j_edge = n0 - ( dim_t )n_left; float* restrict cij = c + j_edge*cs_c; float* restrict ai = a; float* restrict bj = b + j_edge*cs_b; if ( 2 <= n_left ) { const dim_t nr_cur = 2; bli_sgemmsup_rd_haswell_asm_2x2 //bli_sgemmsup_r_haswell_ref ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 1 == n_left ) { #if 1 const dim_t nr_cur = 1; bli_sgemmsup_rd_haswell_asm_2x1 //bli_sgemmsup_r_haswell_ref ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); #else bli_sgemv_ex ( BLIS_NO_TRANSPOSE, conjb, mr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, beta, cij, rs_c0, cntx, NULL ); #endif } } } void bli_sgemmsup_rd_haswell_asm_1x16n ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter32 = k0 / 32; uint64_t k_left32 = k0 % 32; uint64_t k_iter8 = k_left32 / 8; uint64_t k_left1 = k_left32 % 8; uint64_t n_iter = n0 / 4; uint64_t n_left = n0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; if ( n_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), rdx) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) //lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), r14) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) // r12 = rcx = c // rdx = rax = a // r14 = rbx = b // r9 = unused // r15 = n dim index jj mov(var(n_iter), r15) // jj = n_iter; label(.SLOOP3X4J) // LOOP OVER jj = [ n_iter ... 1 0 ] #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorps ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorps(ymm4, ymm4, ymm4) vxorps(ymm7, ymm7, ymm7) vxorps(ymm10, ymm10, ymm10) vxorps(ymm13, ymm13, ymm13) #endif lea(mem(r12), rcx) // rcx = c_iijj; lea(mem(rdx), rax) // rax = a_ii; lea(mem(r14), rbx) // rbx = b_jj; #if 1 //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) prefetch(0, mem(rcx, 1*4)) // prefetch c + 0*rs_c #endif //lea(mem(r8, r8, 4), rbp) // rbp = 5*rs_a lea(mem(rbx, r11, 4), r10) // r10 = rbx + 4*cs_b mov(var(k_iter32), rsi) // i = k_iter32; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKITER8) // if i == 0, jump to code that // contains the k_iter8 loop. label(.SLOOPKITER32) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(r10, 0*8)) // prefetch rbx + 4*cs_b prefetch(0, mem(r10, r11, 1, 0*8)) // prefetch rbx + 5*cs_b #endif vmovups(mem(rax ), ymm0) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) // ---------------------------------- iteration 1 #if 1 prefetch(0, mem(r10, r11, 2, 0*8)) // prefetch rbx + 6*cs_b prefetch(0, mem(r10, r13, 1, 0*8)) // prefetch rbx + 7*cs_b #endif vmovups(mem(rax ), ymm0) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(r10, 8*8)) // prefetch rbx + 4*cs_b + 8*rs_b prefetch(0, mem(r10, r11, 1, 8*8)) // prefetch rbx + 5*cs_b + 8*rs_b #endif vmovups(mem(rax ), ymm0) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) // ---------------------------------- iteration 3 #if 1 prefetch(0, mem(r10, r11, 2, 8*8)) // prefetch rbx + 6*cs_b + 8*rs_b prefetch(0, mem(r10, r13, 1, 8*8)) // prefetch rbx + 7*cs_b + 8*rs_b add(imm(32*4), r10) // r10 += 32*rs_b = 32*4; #endif vmovups(mem(rax ), ymm0) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) dec(rsi) // i -= 1; jne(.SLOOPKITER32) // iterate again if i != 0. label(.SCONSIDKITER8) mov(var(k_iter8), rsi) // i = k_iter8; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter8 loop. label(.SLOOPKITER8) // EDGE LOOP (ymm) vmovups(mem(rax ), ymm0) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) dec(rsi) // i -= 1; jne(.SLOOPKITER8) // iterate again if i != 0. label(.SCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.SLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovss(mem(rax ), xmm0) vmovss(mem(rax, r8, 1), xmm1) add(imm(1*4), rax) // a += 1*cs_a = 1*4; vmovss(mem(rbx ), xmm3) vfmadd231ps(ymm0, ymm3, ymm4) vmovss(mem(rbx, r11, 1), xmm3) vfmadd231ps(ymm0, ymm3, ymm7) vmovss(mem(rbx, r11, 2), xmm3) vfmadd231ps(ymm0, ymm3, ymm10) vmovss(mem(rbx, r13, 1), xmm3) add(imm(1*4), rbx) // b += 1*rs_b = 1*4; vfmadd231ps(ymm0, ymm3, ymm13) dec(rsi) // i -= 1; jne(.SLOOPKLEFT1) // iterate again if i != 0. label(.SPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 vhaddps( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vhaddps( xmm1, xmm0, xmm0 ) vpermilps(imm(0xd8), xmm0, xmm0) vhaddps( xmm0, xmm0, xmm0 ) vhaddps( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm3 ) vhaddps( xmm3, xmm2, xmm2 ) vpermilps(imm(0xd8), xmm2, xmm2) vhaddps( xmm2, xmm2, xmm2 ) vshufps(imm(0x44), xmm2, xmm0, xmm4) // xmm4[0] = sum(ymm4); xmm4[1] = sum(ymm7) // xmm4[2] = sum(ymm10); xmm4[3] = sum(ymm13) //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), xmm0) // load alpha and duplicate vbroadcastss(mem(rbx), xmm3) // load beta and duplicate vmulps(xmm0, xmm4, xmm4) // scale by alpha //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case label(.SROWSTORED) vfmadd231ps(mem(rcx), xmm3, xmm4) vmovups(xmm4, mem(rcx)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SBETAZERO) label(.SROWSTORBZ) vmovups(xmm4, mem(rcx)) //add(rdi, rcx) label(.SDONE) add(imm(4*4), r12) // c_jj = r12 += 4*cs_c lea(mem(r14, r11, 4), r14) // b_jj = r14 += 4*cs_b dec(r15) // jj -= 1; jne(.SLOOP3X4J) // iterate again if jj != 0. label(.SRETURN) end_asm( : // output operands (none) : // input operands [n_iter] "m" (n_iter), [k_iter32] "m" (k_iter32), [k_iter8] "m" (k_iter8), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the n dimension, if they exist. if ( n_left ) { const dim_t mr_cur = 1; const dim_t j_edge = n0 - ( dim_t )n_left; float* restrict cij = c + j_edge*cs_c; float* restrict ai = a; float* restrict bj = b + j_edge*cs_b; if ( 2 <= n_left ) { const dim_t nr_cur = 2; bli_sgemmsup_rd_haswell_asm_1x2 //bli_sgemmsup_r_haswell_ref ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 1 == n_left ) { #if 1 const dim_t nr_cur = 1; bli_sgemmsup_rd_haswell_asm_1x1 //bli_sgemmsup_r_haswell_ref ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); #else bli_sdotxv_ex ( conja, conjb, k0, alpha, ai, cs_a0, bj, rs_b0, beta, cij, cntx, NULL ); #endif } } } blis-0.9.0/kernels/haswell/3/sup/bli_gemmsup_rv_haswell_asm_d6x8m.c000066400000000000000000002407661422157504600253340ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define BLIS_ASM_SYNTAX_ATT #include "bli_x86_asm_macros.h" /* rrr: -------- ------ -------- -------- ------ -------- -------- += ------ ... -------- -------- ------ -------- -------- ------ : -------- ------ : rcr: -------- | | | | -------- -------- | | | | -------- -------- += | | | | ... -------- -------- | | | | -------- -------- | | | | : -------- | | | | : Assumptions: - B is row-stored; - A is row- or column-stored; - m0 and n0 are at most MR and NR, respectively. Therefore, this (r)ow-preferential kernel is well-suited for contiguous (v)ector loads on B and single-element broadcasts from A. NOTE: These kernels explicitly support column-oriented IO, implemented via an in-register transpose. And thus they also support the crr and ccr cases, though only crr is ever utilized (because ccr is handled by transposing the operation and executing rcr, which does not incur the cost of the in-register transpose). crr: | | | | | | | | ------ -------- | | | | | | | | ------ -------- | | | | | | | | += ------ ... -------- | | | | | | | | ------ -------- | | | | | | | | ------ : | | | | | | | | ------ : */ // Prototype reference microkernels. GEMMSUP_KER_PROT( double, d, gemmsup_r_haswell_ref ) void bli_dgemmsup_rv_haswell_asm_6x8m ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { uint64_t n_left = n0 % 8; // First check whether this is a edge case in the n dimension. If so, // dispatch other 6x?m kernels, as needed. if ( n_left ) { double* restrict cij = c; double* restrict bj = b; double* restrict ai = a; if ( 6 <= n_left ) { const dim_t nr_cur = 6; bli_dgemmsup_rv_haswell_asm_6x6m ( conja, conjb, m0, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 4 <= n_left ) { const dim_t nr_cur = 4; bli_dgemmsup_rv_haswell_asm_6x4m ( conja, conjb, m0, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 2 <= n_left ) { const dim_t nr_cur = 2; bli_dgemmsup_rv_haswell_asm_6x2m ( conja, conjb, m0, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 1 == n_left ) { #if 0 const dim_t nr_cur = 1; bli_dgemmsup_r_haswell_ref ( conja, conjb, m0, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); #else dim_t ps_a0 = bli_auxinfo_ps_a( data ); if ( ps_a0 == 6 * rs_a0 ) { // Since A is not packed, we can use one gemv. bli_dgemv_ex ( BLIS_NO_TRANSPOSE, conjb, m0, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, beta, cij, rs_c0, cntx, NULL ); } else { const dim_t mr = 6; // Since A is packed into row panels, we must use a loop over // gemv. dim_t m_iter = ( m0 + mr - 1 ) / mr; dim_t m_left = m0 % mr; double* restrict ai_ii = ai; double* restrict cij_ii = cij; for ( dim_t ii = 0; ii < m_iter; ii += 1 ) { dim_t mr_cur = ( bli_is_not_edge_f( ii, m_iter, m_left ) ? mr : m_left ); bli_dgemv_ex ( BLIS_NO_TRANSPOSE, conjb, mr_cur, k0, alpha, ai_ii, rs_a0, cs_a0, bj, rs_b0, beta, cij_ii, rs_c0, cntx, NULL ); cij_ii += mr*rs_c0; ai_ii += ps_a0; } } #endif } return; } //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t m_iter = m0 / 6; uint64_t m_left = m0 % 6; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // Query the panel stride of A and convert it to units of bytes. uint64_t ps_a = bli_auxinfo_ps_a( data ); uint64_t ps_a8 = ps_a * sizeof( double ); if ( m_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), r14) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a //mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) //lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) // During preamble and loops: // r12 = rcx = c // r14 = rax = a // read rbx from var(b) near beginning of loop // r11 = m dim index ii mov(var(m_iter), r11) // ii = m_iter; label(.DLOOP6X8I) // LOOP OVER ii = [ m_iter ... 1 0 ] #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm5, ymm5, ymm5) vxorpd(ymm6, ymm6, ymm6) vxorpd(ymm7, ymm7, ymm7) vxorpd(ymm8, ymm8, ymm8) vxorpd(ymm9, ymm9, ymm9) vxorpd(ymm10, ymm10, ymm10) vxorpd(ymm11, ymm11, ymm11) vxorpd(ymm12, ymm12, ymm12) vxorpd(ymm13, ymm13, ymm13) vxorpd(ymm14, ymm14, ymm14) vxorpd(ymm15, ymm15, ymm15) #endif mov(var(b), rbx) // load address of b. //mov(r12, rcx) // reset rcx to current utile of c. mov(r14, rax) // reset rax to current upanel of a. cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLPFETCH) // jump to column storage case label(.DROWPFETCH) // row-stored prefetching on c lea(mem(r12, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(r12, 7*8)) // prefetch c + 0*rs_c prefetch(0, mem(r12, rdi, 1, 7*8)) // prefetch c + 1*rs_c prefetch(0, mem(r12, rdi, 2, 7*8)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 7*8)) // prefetch c + 3*rs_c prefetch(0, mem(rdx, rdi, 1, 7*8)) // prefetch c + 4*rs_c prefetch(0, mem(rdx, rdi, 2, 7*8)) // prefetch c + 5*rs_c jmp(.DPOSTPFETCH) // jump to end of prefetching c label(.DCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 8), rsi) // cs_c *= sizeof(double) lea(mem(r12, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; prefetch(0, mem(r12, 5*8)) // prefetch c + 0*cs_c prefetch(0, mem(r12, rsi, 1, 5*8)) // prefetch c + 1*cs_c prefetch(0, mem(r12, rsi, 2, 5*8)) // prefetch c + 2*cs_c prefetch(0, mem(rdx, 5*8)) // prefetch c + 3*cs_c prefetch(0, mem(rdx, rsi, 1, 5*8)) // prefetch c + 4*cs_c prefetch(0, mem(rdx, rsi, 2, 5*8)) // prefetch c + 5*cs_c lea(mem(rdx, rsi, 2), rdx) // rdx = c + 5*cs_c; prefetch(0, mem(rdx, rsi, 1, 5*8)) // prefetch c + 6*cs_c prefetch(0, mem(rdx, rsi, 2, 5*8)) // prefetch c + 7*cs_c label(.DPOSTPFETCH) // done prefetching c #if 1 mov(var(ps_a8), rdx) // load ps_a8 lea(mem(rax, rdx, 1), rdx) // rdx = a + ps_a8 lea(mem(r9, r9, 2), rcx) // rcx = 3*cs_a; // use rcx, rdx for prefetching lines // from next upanel of a. #else lea(mem(rax, r8, 4), rdx) // use rdx for prefetching lines lea(mem(rdx, r8, 2), rdx) // from next upanel of a. lea(mem(r9, r9, 2), rcx) // rcx = 3*cs_a; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.DLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, 5*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, r8, 4), ymm2) vbroadcastsd(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, r9, 1, 5*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, r8, 4), ymm2) vbroadcastsd(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) // ---------------------------------- iteration 2 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, r9, 2, 5*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, r8, 4), ymm2) vbroadcastsd(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) // ---------------------------------- iteration 3 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, rcx, 1, 5*8)) lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, r8, 4), ymm2) vbroadcastsd(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKITER) // iterate again if i != 0. label(.DCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.DLOOPKLEFT) // EDGE LOOP #if 1 prefetch(0, mem(rdx, 5*8)) add(r9, rdx) #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, r8, 4), ymm2) vbroadcastsd(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKLEFT) // iterate again if i != 0. label(.DPOSTACCUM) mov(r12, rcx) // reset rcx to current utile of c. mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(ymm0, ymm5, ymm5) vmulpd(ymm0, ymm6, ymm6) vmulpd(ymm0, ymm7, ymm7) vmulpd(ymm0, ymm8, ymm8) vmulpd(ymm0, ymm9, ymm9) vmulpd(ymm0, ymm10, ymm10) vmulpd(ymm0, ymm11, ymm11) vmulpd(ymm0, ymm12, ymm12) vmulpd(ymm0, ymm13, ymm13) vmulpd(ymm0, ymm14, ymm14) vmulpd(ymm0, ymm15, ymm15) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORED) // jump to column storage case label(.DROWSTORED) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm4) vmovupd(ymm4, mem(rcx, 0*32)) vfmadd231pd(mem(rcx, 1*32), ymm3, ymm5) vmovupd(ymm5, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm6) vmovupd(ymm6, mem(rcx, 0*32)) vfmadd231pd(mem(rcx, 1*32), ymm3, ymm7) vmovupd(ymm7, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm8) vmovupd(ymm8, mem(rcx, 0*32)) vfmadd231pd(mem(rcx, 1*32), ymm3, ymm9) vmovupd(ymm9, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm10) vmovupd(ymm10, mem(rcx, 0*32)) vfmadd231pd(mem(rcx, 1*32), ymm3, ymm11) vmovupd(ymm11, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm12) vmovupd(ymm12, mem(rcx, 0*32)) vfmadd231pd(mem(rcx, 1*32), ymm3, ymm13) vmovupd(ymm13, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm14) vmovupd(ymm14, mem(rcx, 0*32)) vfmadd231pd(mem(rcx, 1*32), ymm3, ymm15) vmovupd(ymm15, mem(rcx, 1*32)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORED) // begin I/O on columns 0-3 vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vunpcklpd(ymm10, ymm8, ymm2) vunpckhpd(ymm10, ymm8, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vperm2f128(imm(0x31), ymm2, ymm0, ymm8) vperm2f128(imm(0x31), ymm3, ymm1, ymm10) vbroadcastsd(mem(rbx), ymm3) vfmadd231pd(mem(rcx ), ymm3, ymm4) vfmadd231pd(mem(rcx, rsi, 1), ymm3, ymm6) vfmadd231pd(mem(rcx, rsi, 2), ymm3, ymm8) vfmadd231pd(mem(rcx, rax, 1), ymm3, ymm10) vmovupd(ymm4, mem(rcx )) vmovupd(ymm6, mem(rcx, rsi, 1)) vmovupd(ymm8, mem(rcx, rsi, 2)) vmovupd(ymm10, mem(rcx, rax, 1)) lea(mem(rcx, rsi, 4), rcx) vunpcklpd(ymm14, ymm12, ymm0) vunpckhpd(ymm14, ymm12, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vextractf128(imm(0x1), ymm1, xmm4) vfmadd231pd(mem(rdx ), xmm3, xmm0) vfmadd231pd(mem(rdx, rsi, 1), xmm3, xmm1) vfmadd231pd(mem(rdx, rsi, 2), xmm3, xmm2) vfmadd231pd(mem(rdx, rax, 1), xmm3, xmm4) vmovupd(xmm0, mem(rdx )) vmovupd(xmm1, mem(rdx, rsi, 1)) vmovupd(xmm2, mem(rdx, rsi, 2)) vmovupd(xmm4, mem(rdx, rax, 1)) lea(mem(rdx, rsi, 4), rdx) // begin I/O on columns 4-7 vunpcklpd(ymm7, ymm5, ymm0) vunpckhpd(ymm7, ymm5, ymm1) vunpcklpd(ymm11, ymm9, ymm2) vunpckhpd(ymm11, ymm9, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm5) vinsertf128(imm(0x1), xmm3, ymm1, ymm7) vperm2f128(imm(0x31), ymm2, ymm0, ymm9) vperm2f128(imm(0x31), ymm3, ymm1, ymm11) vbroadcastsd(mem(rbx), ymm3) vfmadd231pd(mem(rcx ), ymm3, ymm5) vfmadd231pd(mem(rcx, rsi, 1), ymm3, ymm7) vfmadd231pd(mem(rcx, rsi, 2), ymm3, ymm9) vfmadd231pd(mem(rcx, rax, 1), ymm3, ymm11) vmovupd(ymm5, mem(rcx )) vmovupd(ymm7, mem(rcx, rsi, 1)) vmovupd(ymm9, mem(rcx, rsi, 2)) vmovupd(ymm11, mem(rcx, rax, 1)) //lea(mem(rcx, rsi, 4), rcx) vunpcklpd(ymm15, ymm13, ymm0) vunpckhpd(ymm15, ymm13, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vextractf128(imm(0x1), ymm1, xmm4) vfmadd231pd(mem(rdx ), xmm3, xmm0) vfmadd231pd(mem(rdx, rsi, 1), xmm3, xmm1) vfmadd231pd(mem(rdx, rsi, 2), xmm3, xmm2) vfmadd231pd(mem(rdx, rax, 1), xmm3, xmm4) vmovupd(xmm0, mem(rdx )) vmovupd(xmm1, mem(rdx, rsi, 1)) vmovupd(xmm2, mem(rdx, rsi, 2)) vmovupd(xmm4, mem(rdx, rax, 1)) //lea(mem(rdx, rsi, 4), rdx) jmp(.DDONE) // jump to end. label(.DBETAZERO) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORBZ) // jump to column storage case label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx, 0*32)) vmovupd(ymm5, mem(rcx, 1*32)) add(rdi, rcx) vmovupd(ymm6, mem(rcx, 0*32)) vmovupd(ymm7, mem(rcx, 1*32)) add(rdi, rcx) vmovupd(ymm8, mem(rcx, 0*32)) vmovupd(ymm9, mem(rcx, 1*32)) add(rdi, rcx) vmovupd(ymm10, mem(rcx, 0*32)) vmovupd(ymm11, mem(rcx, 1*32)) add(rdi, rcx) vmovupd(ymm12, mem(rcx, 0*32)) vmovupd(ymm13, mem(rcx, 1*32)) add(rdi, rcx) vmovupd(ymm14, mem(rcx, 0*32)) vmovupd(ymm15, mem(rcx, 1*32)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORBZ) // begin I/O on columns 0-3 vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vunpcklpd(ymm10, ymm8, ymm2) vunpckhpd(ymm10, ymm8, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vperm2f128(imm(0x31), ymm2, ymm0, ymm8) vperm2f128(imm(0x31), ymm3, ymm1, ymm10) vmovupd(ymm4, mem(rcx )) vmovupd(ymm6, mem(rcx, rsi, 1)) vmovupd(ymm8, mem(rcx, rsi, 2)) vmovupd(ymm10, mem(rcx, rax, 1)) lea(mem(rcx, rsi, 4), rcx) vunpcklpd(ymm14, ymm12, ymm0) vunpckhpd(ymm14, ymm12, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vextractf128(imm(0x1), ymm1, xmm4) vmovupd(xmm0, mem(rdx )) vmovupd(xmm1, mem(rdx, rsi, 1)) vmovupd(xmm2, mem(rdx, rsi, 2)) vmovupd(xmm4, mem(rdx, rax, 1)) lea(mem(rdx, rsi, 4), rdx) // begin I/O on columns 4-7 vunpcklpd(ymm7, ymm5, ymm0) vunpckhpd(ymm7, ymm5, ymm1) vunpcklpd(ymm11, ymm9, ymm2) vunpckhpd(ymm11, ymm9, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm5) vinsertf128(imm(0x1), xmm3, ymm1, ymm7) vperm2f128(imm(0x31), ymm2, ymm0, ymm9) vperm2f128(imm(0x31), ymm3, ymm1, ymm11) vmovupd(ymm5, mem(rcx )) vmovupd(ymm7, mem(rcx, rsi, 1)) vmovupd(ymm9, mem(rcx, rsi, 2)) vmovupd(ymm11, mem(rcx, rax, 1)) //lea(mem(rcx, rsi, 4), rcx) vunpcklpd(ymm15, ymm13, ymm0) vunpckhpd(ymm15, ymm13, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vextractf128(imm(0x1), ymm1, xmm4) vmovupd(xmm0, mem(rdx )) vmovupd(xmm1, mem(rdx, rsi, 1)) vmovupd(xmm2, mem(rdx, rsi, 2)) vmovupd(xmm4, mem(rdx, rax, 1)) //lea(mem(rdx, rsi, 4), rdx) label(.DDONE) lea(mem(r12, rdi, 4), r12) // lea(mem(r12, rdi, 2), r12) // c_ii = r12 += 6*rs_c //lea(mem(r14, r8, 4), r14) // //lea(mem(r14, r8, 2), r14) // a_ii = r14 += 6*rs_a mov(var(ps_a8), rax) // load ps_a8 lea(mem(r14, rax, 1), r14) // a_ii = r14 += ps_a8 dec(r11) // ii -= 1; jne(.DLOOP6X8I) // iterate again if ii != 0. label(.DRETURN) end_asm( : // output operands (none) : // input operands [m_iter] "m" (m_iter), [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [ps_a8] "m" (ps_a8), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the m dimension, if they exist. if ( m_left ) { const dim_t nr_cur = 8; const dim_t i_edge = m0 - ( dim_t )m_left; double* restrict cij = c + i_edge*rs_c; //double* restrict ai = a + i_edge*rs_a; //double* restrict ai = a + ( i_edge / 6 ) * ps_a; double* restrict ai = a + m_iter * ps_a; double* restrict bj = b; #if 0 // We add special handling for slightly inflated MR blocksizes // at edge cases, up to a maximum of 9. if ( 6 < m_left ) { dgemmsup_ker_ft ker_fp1 = NULL; dgemmsup_ker_ft ker_fp2 = NULL; dim_t mr1, mr2; if ( m_left == 7 ) { mr1 = 4; mr2 = 3; ker_fp1 = bli_dgemmsup_rv_haswell_asm_4x8; ker_fp2 = bli_dgemmsup_rv_haswell_asm_3x8; } else if ( m_left == 8 ) { mr1 = 4; mr2 = 4; ker_fp1 = bli_dgemmsup_rv_haswell_asm_4x8; ker_fp2 = bli_dgemmsup_rv_haswell_asm_4x8; } else // if ( m_left == 9 ) { mr1 = 4; mr2 = 5; ker_fp1 = bli_dgemmsup_rv_haswell_asm_4x8; ker_fp2 = bli_dgemmsup_rv_haswell_asm_5x8; } ker_fp1 ( conja, conjb, mr1, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += mr1*rs_c0; ai += mr1*rs_a0; ker_fp2 ( conja, conjb, mr2, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); return; } #endif dgemmsup_ker_ft ker_fps[6] = { NULL, bli_dgemmsup_rv_haswell_asm_1x8, bli_dgemmsup_rv_haswell_asm_2x8, bli_dgemmsup_rv_haswell_asm_3x8, bli_dgemmsup_rv_haswell_asm_4x8, bli_dgemmsup_rv_haswell_asm_5x8 }; dgemmsup_ker_ft ker_fp = ker_fps[ m_left ]; ker_fp ( conja, conjb, m_left, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); return; } } void bli_dgemmsup_rv_haswell_asm_6x6m ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t m_iter = m0 / 6; uint64_t m_left = m0 % 6; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // Query the panel stride of A and convert it to units of bytes. uint64_t ps_a = bli_auxinfo_ps_a( data ); uint64_t ps_a8 = ps_a * sizeof( double ); if ( m_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), r14) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a //mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) //lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) // During preamble and loops: // r12 = rcx = c // r14 = rax = a // read rbx from var(b) near beginning of loop // r11 = m dim index ii mov(var(m_iter), r11) // ii = m_iter; label(.DLOOP6X8I) // LOOP OVER ii = [ m_iter ... 1 0 ] #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm1, ymm1, ymm1) // zero ymm1 since we only use the lower vxorpd(ymm4, ymm4, ymm4) // half (xmm1), and nans/infs may slow us vxorpd(ymm5, ymm5, ymm5) // down. vxorpd(ymm6, ymm6, ymm6) vxorpd(ymm7, ymm7, ymm7) vxorpd(ymm8, ymm8, ymm8) vxorpd(ymm9, ymm9, ymm9) vxorpd(ymm10, ymm10, ymm10) vxorpd(ymm11, ymm11, ymm11) vxorpd(ymm12, ymm12, ymm12) vxorpd(ymm13, ymm13, ymm13) vxorpd(ymm14, ymm14, ymm14) vxorpd(ymm15, ymm15, ymm15) #endif mov(var(b), rbx) // load address of b. //mov(r12, rcx) // reset rcx to current utile of c. mov(r14, rax) // reset rax to current upanel of a. cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLPFETCH) // jump to column storage case label(.DROWPFETCH) // row-stored prefetching on c lea(mem(r12, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(r12, 5*8)) // prefetch c + 0*rs_c prefetch(0, mem(r12, rdi, 1, 5*8)) // prefetch c + 1*rs_c prefetch(0, mem(r12, rdi, 2, 5*8)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 5*8)) // prefetch c + 3*rs_c prefetch(0, mem(rdx, rdi, 1, 5*8)) // prefetch c + 4*rs_c prefetch(0, mem(rdx, rdi, 2, 5*8)) // prefetch c + 5*rs_c jmp(.DPOSTPFETCH) // jump to end of prefetching c label(.DCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 8), rsi) // cs_c *= sizeof(double) lea(mem(r12, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; prefetch(0, mem(r12, 5*8)) // prefetch c + 0*cs_c prefetch(0, mem(r12, rsi, 1, 5*8)) // prefetch c + 1*cs_c prefetch(0, mem(r12, rsi, 2, 5*8)) // prefetch c + 2*cs_c prefetch(0, mem(rdx, 5*8)) // prefetch c + 3*cs_c prefetch(0, mem(rdx, rsi, 1, 5*8)) // prefetch c + 4*cs_c prefetch(0, mem(rdx, rsi, 2, 5*8)) // prefetch c + 5*cs_c label(.DPOSTPFETCH) // done prefetching c #if 1 mov(var(ps_a8), rdx) // load ps_a8 lea(mem(rax, rdx, 1), rdx) // rdx = a + ps_a8 lea(mem(r9, r9, 2), rcx) // rcx = 3*cs_a; // use rcx, rdx for prefetching lines // from next upanel of a. #else lea(mem(rax, r8, 4), rdx) // use rdx for prefetching lines lea(mem(rdx, r8, 2), rdx) // from next upanel of a. lea(mem(r9, r9, 2), rcx) // rcx = 3*cs_a; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.DLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, 5*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, r8, 4), ymm2) vbroadcastsd(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, r9, 1, 5*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, r8, 4), ymm2) vbroadcastsd(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) // ---------------------------------- iteration 2 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, r9, 2, 5*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, r8, 4), ymm2) vbroadcastsd(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) // ---------------------------------- iteration 3 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, rcx, 1, 5*8)) lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, r8, 4), ymm2) vbroadcastsd(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKITER) // iterate again if i != 0. label(.DCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.DLOOPKLEFT) // EDGE LOOP #if 1 prefetch(0, mem(rdx, 5*8)) add(r9, rdx) #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, r8, 4), ymm2) vbroadcastsd(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKLEFT) // iterate again if i != 0. label(.DPOSTACCUM) mov(r12, rcx) // reset rcx to current utile of c. mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(xmm0, xmm5, xmm5) vmulpd(ymm0, ymm6, ymm6) vmulpd(xmm0, xmm7, xmm7) vmulpd(ymm0, ymm8, ymm8) vmulpd(xmm0, xmm9, xmm9) vmulpd(ymm0, ymm10, ymm10) vmulpd(xmm0, xmm11, xmm11) vmulpd(ymm0, ymm12, ymm12) vmulpd(xmm0, xmm13, xmm13) vmulpd(ymm0, ymm14, ymm14) vmulpd(xmm0, xmm15, xmm15) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORED) // jump to column storage case label(.DROWSTORED) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm4) vmovupd(ymm4, mem(rcx, 0*32)) vfmadd231pd(mem(rcx, 1*32), xmm3, xmm5) vmovupd(xmm5, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm6) vmovupd(ymm6, mem(rcx, 0*32)) vfmadd231pd(mem(rcx, 1*32), xmm3, xmm7) vmovupd(xmm7, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm8) vmovupd(ymm8, mem(rcx, 0*32)) vfmadd231pd(mem(rcx, 1*32), xmm3, xmm9) vmovupd(xmm9, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm10) vmovupd(ymm10, mem(rcx, 0*32)) vfmadd231pd(mem(rcx, 1*32), xmm3, xmm11) vmovupd(xmm11, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm12) vmovupd(ymm12, mem(rcx, 0*32)) vfmadd231pd(mem(rcx, 1*32), xmm3, xmm13) vmovupd(xmm13, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm14) vmovupd(ymm14, mem(rcx, 0*32)) vfmadd231pd(mem(rcx, 1*32), xmm3, xmm15) vmovupd(xmm15, mem(rcx, 1*32)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORED) // begin I/O on columns 0-3 vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vunpcklpd(ymm10, ymm8, ymm2) vunpckhpd(ymm10, ymm8, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vperm2f128(imm(0x31), ymm2, ymm0, ymm8) vperm2f128(imm(0x31), ymm3, ymm1, ymm10) vbroadcastsd(mem(rbx), ymm3) vfmadd231pd(mem(rcx ), ymm3, ymm4) vfmadd231pd(mem(rcx, rsi, 1), ymm3, ymm6) vfmadd231pd(mem(rcx, rsi, 2), ymm3, ymm8) vfmadd231pd(mem(rcx, rax, 1), ymm3, ymm10) vmovupd(ymm4, mem(rcx )) vmovupd(ymm6, mem(rcx, rsi, 1)) vmovupd(ymm8, mem(rcx, rsi, 2)) vmovupd(ymm10, mem(rcx, rax, 1)) lea(mem(rcx, rsi, 4), rcx) vunpcklpd(ymm14, ymm12, ymm0) vunpckhpd(ymm14, ymm12, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vextractf128(imm(0x1), ymm1, xmm4) vfmadd231pd(mem(rdx ), xmm3, xmm0) vfmadd231pd(mem(rdx, rsi, 1), xmm3, xmm1) vfmadd231pd(mem(rdx, rsi, 2), xmm3, xmm2) vfmadd231pd(mem(rdx, rax, 1), xmm3, xmm4) vmovupd(xmm0, mem(rdx )) vmovupd(xmm1, mem(rdx, rsi, 1)) vmovupd(xmm2, mem(rdx, rsi, 2)) vmovupd(xmm4, mem(rdx, rax, 1)) lea(mem(rdx, rsi, 4), rdx) // begin I/O on columns 4-5 vunpcklpd(ymm7, ymm5, ymm0) vunpckhpd(ymm7, ymm5, ymm1) vunpcklpd(ymm11, ymm9, ymm2) vunpckhpd(ymm11, ymm9, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm5) vinsertf128(imm(0x1), xmm3, ymm1, ymm7) vbroadcastsd(mem(rbx), ymm3) vfmadd231pd(mem(rcx ), ymm3, ymm5) vfmadd231pd(mem(rcx, rsi, 1), ymm3, ymm7) vmovupd(ymm5, mem(rcx )) vmovupd(ymm7, mem(rcx, rsi, 1)) //lea(mem(rcx, rsi, 4), rcx) vunpcklpd(ymm15, ymm13, ymm0) vunpckhpd(ymm15, ymm13, ymm1) vfmadd231pd(mem(rdx ), xmm3, xmm0) vfmadd231pd(mem(rdx, rsi, 1), xmm3, xmm1) vmovupd(xmm0, mem(rdx )) vmovupd(xmm1, mem(rdx, rsi, 1)) //lea(mem(rdx, rsi, 4), rdx) jmp(.DDONE) // jump to end. label(.DBETAZERO) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORBZ) // jump to column storage case label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx, 0*32)) vmovupd(xmm5, mem(rcx, 1*32)) add(rdi, rcx) vmovupd(ymm6, mem(rcx, 0*32)) vmovupd(xmm7, mem(rcx, 1*32)) add(rdi, rcx) vmovupd(ymm8, mem(rcx, 0*32)) vmovupd(xmm9, mem(rcx, 1*32)) add(rdi, rcx) vmovupd(ymm10, mem(rcx, 0*32)) vmovupd(xmm11, mem(rcx, 1*32)) add(rdi, rcx) vmovupd(ymm12, mem(rcx, 0*32)) vmovupd(xmm13, mem(rcx, 1*32)) add(rdi, rcx) vmovupd(ymm14, mem(rcx, 0*32)) vmovupd(xmm15, mem(rcx, 1*32)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORBZ) // begin I/O on columns 0-3 vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vunpcklpd(ymm10, ymm8, ymm2) vunpckhpd(ymm10, ymm8, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vperm2f128(imm(0x31), ymm2, ymm0, ymm8) vperm2f128(imm(0x31), ymm3, ymm1, ymm10) vmovupd(ymm4, mem(rcx )) vmovupd(ymm6, mem(rcx, rsi, 1)) vmovupd(ymm8, mem(rcx, rsi, 2)) vmovupd(ymm10, mem(rcx, rax, 1)) lea(mem(rcx, rsi, 4), rcx) vunpcklpd(ymm14, ymm12, ymm0) vunpckhpd(ymm14, ymm12, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vextractf128(imm(0x1), ymm1, xmm4) vmovupd(xmm0, mem(rdx )) vmovupd(xmm1, mem(rdx, rsi, 1)) vmovupd(xmm2, mem(rdx, rsi, 2)) vmovupd(xmm4, mem(rdx, rax, 1)) lea(mem(rdx, rsi, 4), rdx) // begin I/O on columns 4-5 vunpcklpd(ymm7, ymm5, ymm0) vunpckhpd(ymm7, ymm5, ymm1) vunpcklpd(ymm11, ymm9, ymm2) vunpckhpd(ymm11, ymm9, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm5) vinsertf128(imm(0x1), xmm3, ymm1, ymm7) vmovupd(ymm5, mem(rcx )) vmovupd(ymm7, mem(rcx, rsi, 1)) //lea(mem(rcx, rsi, 4), rcx) vunpcklpd(ymm15, ymm13, ymm0) vunpckhpd(ymm15, ymm13, ymm1) vmovupd(xmm0, mem(rdx )) vmovupd(xmm1, mem(rdx, rsi, 1)) //lea(mem(rdx, rsi, 4), rdx) label(.DDONE) lea(mem(r12, rdi, 4), r12) // lea(mem(r12, rdi, 2), r12) // c_ii = r12 += 6*rs_c //lea(mem(r14, r8, 4), r14) // //lea(mem(r14, r8, 2), r14) // a_ii = r14 += 6*rs_a mov(var(ps_a8), rax) // load ps_a8 lea(mem(r14, rax, 1), r14) // a_ii = r14 += ps_a8 dec(r11) // ii -= 1; jne(.DLOOP6X8I) // iterate again if ii != 0. label(.DRETURN) end_asm( : // output operands (none) : // input operands [m_iter] "m" (m_iter), [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [ps_a8] "m" (ps_a8), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the m dimension, if they exist. if ( m_left ) { const dim_t nr_cur = 6; const dim_t i_edge = m0 - ( dim_t )m_left; double* restrict cij = c + i_edge*rs_c; //double* restrict ai = a + i_edge*rs_a; //double* restrict ai = a + ( i_edge / 6 ) * ps_a; double* restrict ai = a + m_iter * ps_a; double* restrict bj = b; #if 0 // We add special handling for slightly inflated MR blocksizes // at edge cases, up to a maximum of 9. if ( 6 < m_left ) { dgemmsup_ker_ft ker_fp1 = NULL; dgemmsup_ker_ft ker_fp2 = NULL; dim_t mr1, mr2; if ( m_left == 7 ) { mr1 = 4; mr2 = 3; ker_fp1 = bli_dgemmsup_rv_haswell_asm_4x6; ker_fp2 = bli_dgemmsup_rv_haswell_asm_3x6; } else if ( m_left == 8 ) { mr1 = 4; mr2 = 4; ker_fp1 = bli_dgemmsup_rv_haswell_asm_4x6; ker_fp2 = bli_dgemmsup_rv_haswell_asm_4x6; } else // if ( m_left == 9 ) { mr1 = 4; mr2 = 5; ker_fp1 = bli_dgemmsup_rv_haswell_asm_4x6; ker_fp2 = bli_dgemmsup_rv_haswell_asm_5x6; } ker_fp1 ( conja, conjb, mr1, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += mr1*rs_c0; ai += mr1*rs_a0; ker_fp2 ( conja, conjb, mr2, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); return; } #endif dgemmsup_ker_ft ker_fps[6] = { NULL, bli_dgemmsup_rv_haswell_asm_1x6, bli_dgemmsup_rv_haswell_asm_2x6, bli_dgemmsup_rv_haswell_asm_3x6, bli_dgemmsup_rv_haswell_asm_4x6, bli_dgemmsup_rv_haswell_asm_5x6 }; dgemmsup_ker_ft ker_fp = ker_fps[ m_left ]; ker_fp ( conja, conjb, m_left, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); return; } } void bli_dgemmsup_rv_haswell_asm_6x4m ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t m_iter = m0 / 6; uint64_t m_left = m0 % 6; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // Query the panel stride of A and convert it to units of bytes. uint64_t ps_a = bli_auxinfo_ps_a( data ); uint64_t ps_a8 = ps_a * sizeof( double ); if ( m_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), r14) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a //mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) //lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) // During preamble and loops: // r12 = rcx = c // r14 = rax = a // read rbx from var(b) near beginning of loop // r11 = m dim index ii mov(var(m_iter), r11) // ii = m_iter; label(.DLOOP6X4I) // LOOP OVER ii = [ m_iter ... 1 0 ] #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm6, ymm6, ymm6) vxorpd(ymm8, ymm8, ymm8) vxorpd(ymm10, ymm10, ymm10) vxorpd(ymm12, ymm12, ymm12) vxorpd(ymm14, ymm14, ymm14) #endif mov(var(b), rbx) // load address of b. //mov(r12, rcx) // reset rcx to current utile of c. mov(r14, rax) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLPFETCH) // jump to column storage case label(.DROWPFETCH) // row-stored prefetching on c lea(mem(r12, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(r12, 3*8)) // prefetch c + 0*rs_c prefetch(0, mem(r12, rdi, 1, 3*8)) // prefetch c + 1*rs_c prefetch(0, mem(r12, rdi, 2, 3*8)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 3*8)) // prefetch c + 3*rs_c prefetch(0, mem(rdx, rdi, 1, 3*8)) // prefetch c + 4*rs_c prefetch(0, mem(rdx, rdi, 2, 3*8)) // prefetch c + 5*rs_c jmp(.DPOSTPFETCH) // jump to end of prefetching c label(.DCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 8), rsi) // cs_c *= sizeof(double) lea(mem(r12, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; prefetch(0, mem(r12, 5*8)) // prefetch c + 0*cs_c prefetch(0, mem(r12, rsi, 1, 5*8)) // prefetch c + 1*cs_c prefetch(0, mem(r12, rsi, 2, 5*8)) // prefetch c + 2*cs_c prefetch(0, mem(rdx, 5*8)) // prefetch c + 3*cs_c label(.DPOSTPFETCH) // done prefetching c #if 1 mov(var(ps_a8), rdx) // load ps_a8 lea(mem(rax, rdx, 1), rdx) // rdx = a + ps_a8 lea(mem(r9, r9, 2), rcx) // rcx = 3*cs_a; // use rcx, rdx for prefetching lines // from next upanel of a. #else lea(mem(rax, r8, 4), rdx) // use rdx for prefetching lines lea(mem(rdx, r8, 2), rdx) // from next upanel of a. lea(mem(r9, r9, 2), rcx) // rcx = 3*cs_a; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.DLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, 5*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm0, ymm3, ymm6) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm0, ymm3, ymm10) vbroadcastsd(mem(rax, r8, 4), ymm2) vbroadcastsd(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm0, ymm3, ymm14) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, r9, 1, 5*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm0, ymm3, ymm6) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm0, ymm3, ymm10) vbroadcastsd(mem(rax, r8, 4), ymm2) vbroadcastsd(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm0, ymm3, ymm14) // ---------------------------------- iteration 2 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, r9, 2, 5*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm0, ymm3, ymm6) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm0, ymm3, ymm10) vbroadcastsd(mem(rax, r8, 4), ymm2) vbroadcastsd(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm0, ymm3, ymm14) // ---------------------------------- iteration 3 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, rcx, 1, 5*8)) lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; #endif vmovupd(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm0, ymm3, ymm6) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm0, ymm3, ymm10) vbroadcastsd(mem(rax, r8, 4), ymm2) vbroadcastsd(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm0, ymm3, ymm14) dec(rsi) // i -= 1; jne(.DLOOPKITER) // iterate again if i != 0. label(.DCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.DLOOPKLEFT) // EDGE LOOP #if 1 prefetch(0, mem(rdx, 5*8)) add(r9, rdx) #endif vmovupd(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm0, ymm3, ymm6) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm0, ymm3, ymm10) vbroadcastsd(mem(rax, r8, 4), ymm2) vbroadcastsd(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm0, ymm3, ymm14) dec(rsi) // i -= 1; jne(.DLOOPKLEFT) // iterate again if i != 0. label(.DPOSTACCUM) mov(r12, rcx) // reset rcx to current utile of c. mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(ymm0, ymm6, ymm6) vmulpd(ymm0, ymm8, ymm8) vmulpd(ymm0, ymm10, ymm10) vmulpd(ymm0, ymm12, ymm12) vmulpd(ymm0, ymm14, ymm14) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORED) // jump to column storage case label(.DROWSTORED) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm4) vmovupd(ymm4, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm6) vmovupd(ymm6, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm8) vmovupd(ymm8, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm10) vmovupd(ymm10, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm12) vmovupd(ymm12, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm14) vmovupd(ymm14, mem(rcx, 0*32)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORED) // begin I/O on columns 0-3 vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vunpcklpd(ymm10, ymm8, ymm2) vunpckhpd(ymm10, ymm8, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vperm2f128(imm(0x31), ymm2, ymm0, ymm8) vperm2f128(imm(0x31), ymm3, ymm1, ymm10) vbroadcastsd(mem(rbx), ymm3) vfmadd231pd(mem(rcx ), ymm3, ymm4) vfmadd231pd(mem(rcx, rsi, 1), ymm3, ymm6) vfmadd231pd(mem(rcx, rsi, 2), ymm3, ymm8) vfmadd231pd(mem(rcx, rax, 1), ymm3, ymm10) vmovupd(ymm4, mem(rcx )) vmovupd(ymm6, mem(rcx, rsi, 1)) vmovupd(ymm8, mem(rcx, rsi, 2)) vmovupd(ymm10, mem(rcx, rax, 1)) //lea(mem(rcx, rsi, 4), rcx) vunpcklpd(ymm14, ymm12, ymm0) vunpckhpd(ymm14, ymm12, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vextractf128(imm(0x1), ymm1, xmm4) vfmadd231pd(mem(rdx ), xmm3, xmm0) vfmadd231pd(mem(rdx, rsi, 1), xmm3, xmm1) vfmadd231pd(mem(rdx, rsi, 2), xmm3, xmm2) vfmadd231pd(mem(rdx, rax, 1), xmm3, xmm4) vmovupd(xmm0, mem(rdx )) vmovupd(xmm1, mem(rdx, rsi, 1)) vmovupd(xmm2, mem(rdx, rsi, 2)) vmovupd(xmm4, mem(rdx, rax, 1)) //lea(mem(rdx, rsi, 4), rdx) jmp(.DDONE) // jump to end. label(.DBETAZERO) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORBZ) // jump to column storage case label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx, 0*32)) add(rdi, rcx) vmovupd(ymm6, mem(rcx, 0*32)) add(rdi, rcx) vmovupd(ymm8, mem(rcx, 0*32)) add(rdi, rcx) vmovupd(ymm10, mem(rcx, 0*32)) add(rdi, rcx) vmovupd(ymm12, mem(rcx, 0*32)) add(rdi, rcx) vmovupd(ymm14, mem(rcx, 0*32)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORBZ) // begin I/O on columns 0-3 vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vunpcklpd(ymm10, ymm8, ymm2) vunpckhpd(ymm10, ymm8, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vperm2f128(imm(0x31), ymm2, ymm0, ymm8) vperm2f128(imm(0x31), ymm3, ymm1, ymm10) vmovupd(ymm4, mem(rcx )) vmovupd(ymm6, mem(rcx, rsi, 1)) vmovupd(ymm8, mem(rcx, rsi, 2)) vmovupd(ymm10, mem(rcx, rax, 1)) //lea(mem(rcx, rsi, 4), rcx) vunpcklpd(ymm14, ymm12, ymm0) vunpckhpd(ymm14, ymm12, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vextractf128(imm(0x1), ymm1, xmm4) vmovupd(xmm0, mem(rdx )) vmovupd(xmm1, mem(rdx, rsi, 1)) vmovupd(xmm2, mem(rdx, rsi, 2)) vmovupd(xmm4, mem(rdx, rax, 1)) //lea(mem(rdx, rsi, 4), rdx) label(.DDONE) lea(mem(r12, rdi, 4), r12) // lea(mem(r12, rdi, 2), r12) // c_ii = r12 += 6*rs_c //lea(mem(r14, r8, 4), r14) // //lea(mem(r14, r8, 2), r14) // a_ii = r14 += 6*rs_a mov(var(ps_a8), rax) // load ps_a8 lea(mem(r14, rax, 1), r14) // a_ii = r14 += ps_a8 dec(r11) // ii -= 1; jne(.DLOOP6X4I) // iterate again if ii != 0. label(.DRETURN) end_asm( : // output operands (none) : // input operands [m_iter] "m" (m_iter), [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [ps_a8] "m" (ps_a8), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the m dimension, if they exist. if ( m_left ) { const dim_t nr_cur = 4; const dim_t i_edge = m0 - ( dim_t )m_left; double* restrict cij = c + i_edge*rs_c; //double* restrict ai = a + i_edge*rs_a; //double* restrict ai = a + ( i_edge / 6 ) * ps_a; double* restrict ai = a + m_iter * ps_a; double* restrict bj = b; #if 0 // We add special handling for slightly inflated MR blocksizes // at edge cases, up to a maximum of 9. if ( 6 < m_left ) { dgemmsup_ker_ft ker_fp1 = NULL; dgemmsup_ker_ft ker_fp2 = NULL; dim_t mr1, mr2; if ( m_left == 7 ) { mr1 = 4; mr2 = 3; ker_fp1 = bli_dgemmsup_rv_haswell_asm_4x4; ker_fp2 = bli_dgemmsup_rv_haswell_asm_3x4; } else if ( m_left == 8 ) { mr1 = 4; mr2 = 4; ker_fp1 = bli_dgemmsup_rv_haswell_asm_4x4; ker_fp2 = bli_dgemmsup_rv_haswell_asm_4x4; } else // if ( m_left == 9 ) { mr1 = 4; mr2 = 5; ker_fp1 = bli_dgemmsup_rv_haswell_asm_4x4; ker_fp2 = bli_dgemmsup_rv_haswell_asm_5x4; } ker_fp1 ( conja, conjb, mr1, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += mr1*rs_c0; ai += mr1*rs_a0; ker_fp2 ( conja, conjb, mr2, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); return; } #endif dgemmsup_ker_ft ker_fps[6] = { NULL, bli_dgemmsup_rv_haswell_asm_1x4, bli_dgemmsup_rv_haswell_asm_2x4, bli_dgemmsup_rv_haswell_asm_3x4, bli_dgemmsup_rv_haswell_asm_4x4, bli_dgemmsup_rv_haswell_asm_5x4 }; dgemmsup_ker_ft ker_fp = ker_fps[ m_left ]; ker_fp ( conja, conjb, m_left, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); return; } } void bli_dgemmsup_rv_haswell_asm_6x2m ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t m_iter = m0 / 6; uint64_t m_left = m0 % 6; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // Query the panel stride of A and convert it to units of bytes. uint64_t ps_a = bli_auxinfo_ps_a( data ); uint64_t ps_a8 = ps_a * sizeof( double ); if ( m_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), r14) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a //mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) //lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) // During preamble and loops: // r12 = rcx = c // r14 = rax = a // read rbx from var(b) near beginning of loop // r11 = m dim index ii mov(var(m_iter), r11) // ii = m_iter; label(.DLOOP6X2I) // LOOP OVER ii = [ m_iter ... 1 0 ] #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(xmm4, xmm4, xmm4) vxorpd(xmm6, xmm6, xmm6) vxorpd(xmm8, xmm8, xmm8) vxorpd(xmm10, xmm10, xmm10) vxorpd(xmm12, xmm12, xmm12) vxorpd(xmm14, xmm14, xmm14) #endif mov(var(b), rbx) // load address of b. //mov(r12, rcx) // reset rcx to current utile of c. mov(r14, rax) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLPFETCH) // jump to column storage case label(.DROWPFETCH) // row-stored prefetching on c lea(mem(r12, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(r12, 1*8)) // prefetch c + 0*rs_c prefetch(0, mem(r12, rdi, 1, 1*8)) // prefetch c + 1*rs_c prefetch(0, mem(r12, rdi, 2, 1*8)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 1*8)) // prefetch c + 3*rs_c prefetch(0, mem(rdx, rdi, 1, 1*8)) // prefetch c + 4*rs_c prefetch(0, mem(rdx, rdi, 2, 1*8)) // prefetch c + 5*rs_c jmp(.DPOSTPFETCH) // jump to end of prefetching c label(.DCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 8), rsi) // cs_c *= sizeof(double) prefetch(0, mem(r12, 5*8)) // prefetch c + 0*cs_c prefetch(0, mem(r12, rsi, 1, 5*8)) // prefetch c + 1*cs_c label(.DPOSTPFETCH) // done prefetching c #if 1 mov(var(ps_a8), rdx) // load ps_a8 lea(mem(rax, rdx, 1), rdx) // rdx = a + ps_a8 lea(mem(r9, r9, 2), rcx) // rcx = 3*cs_a; // use rcx, rdx for prefetching lines // from next upanel of a. #else lea(mem(rax, r8, 4), rdx) // use rdx for prefetching lines lea(mem(rdx, r8, 2), rdx) // from next upanel of a. lea(mem(r9, r9, 2), rcx) // rcx = 3*cs_a; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.DLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, 5*8)) #endif vmovupd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(xmm0, xmm2, xmm4) vfmadd231pd(xmm0, xmm3, xmm6) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(xmm0, xmm2, xmm8) vfmadd231pd(xmm0, xmm3, xmm10) vbroadcastsd(mem(rax, r8, 4), ymm2) vbroadcastsd(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(xmm0, xmm2, xmm12) vfmadd231pd(xmm0, xmm3, xmm14) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, r9, 1, 5*8)) #endif vmovupd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(xmm0, xmm2, xmm4) vfmadd231pd(xmm0, xmm3, xmm6) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(xmm0, xmm2, xmm8) vfmadd231pd(xmm0, xmm3, xmm10) vbroadcastsd(mem(rax, r8, 4), ymm2) vbroadcastsd(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(xmm0, xmm2, xmm12) vfmadd231pd(xmm0, xmm3, xmm14) // ---------------------------------- iteration 2 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, r9, 2, 5*8)) #endif vmovupd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(xmm0, xmm2, xmm4) vfmadd231pd(xmm0, xmm3, xmm6) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(xmm0, xmm2, xmm8) vfmadd231pd(xmm0, xmm3, xmm10) vbroadcastsd(mem(rax, r8, 4), ymm2) vbroadcastsd(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(xmm0, xmm2, xmm12) vfmadd231pd(xmm0, xmm3, xmm14) // ---------------------------------- iteration 3 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, rcx, 1, 5*8)) lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; #endif vmovupd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(xmm0, xmm2, xmm4) vfmadd231pd(xmm0, xmm3, xmm6) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(xmm0, xmm2, xmm8) vfmadd231pd(xmm0, xmm3, xmm10) vbroadcastsd(mem(rax, r8, 4), ymm2) vbroadcastsd(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(xmm0, xmm2, xmm12) vfmadd231pd(xmm0, xmm3, xmm14) dec(rsi) // i -= 1; jne(.DLOOPKITER) // iterate again if i != 0. label(.DCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.DLOOPKLEFT) // EDGE LOOP #if 1 prefetch(0, mem(rdx, 5*8)) add(r9, rdx) #endif vmovupd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(xmm0, xmm2, xmm4) vfmadd231pd(xmm0, xmm3, xmm6) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(xmm0, xmm2, xmm8) vfmadd231pd(xmm0, xmm3, xmm10) vbroadcastsd(mem(rax, r8, 4), ymm2) vbroadcastsd(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(xmm0, xmm2, xmm12) vfmadd231pd(xmm0, xmm3, xmm14) dec(rsi) // i -= 1; jne(.DLOOPKLEFT) // iterate again if i != 0. label(.DPOSTACCUM) mov(r12, rcx) // reset rcx to current utile of c. mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(xmm0, xmm4, xmm4) // scale by alpha vmulpd(xmm0, xmm6, xmm6) vmulpd(xmm0, xmm8, xmm8) vmulpd(xmm0, xmm10, xmm10) vmulpd(xmm0, xmm12, xmm12) vmulpd(xmm0, xmm14, xmm14) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; //lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORED) // jump to column storage case label(.DROWSTORED) vfmadd231pd(mem(rcx, 0*32), xmm3, xmm4) vmovupd(xmm4, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), xmm3, xmm6) vmovupd(xmm6, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), xmm3, xmm8) vmovupd(xmm8, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), xmm3, xmm10) vmovupd(xmm10, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), xmm3, xmm12) vmovupd(xmm12, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), xmm3, xmm14) vmovupd(xmm14, mem(rcx, 0*32)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORED) // begin I/O on columns 0-3 vunpcklpd(xmm6, xmm4, xmm0) vunpckhpd(xmm6, xmm4, xmm1) vunpcklpd(xmm10, xmm8, xmm2) vunpckhpd(xmm10, xmm8, xmm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vbroadcastsd(mem(rbx), ymm3) vfmadd231pd(mem(rcx ), ymm3, ymm4) vfmadd231pd(mem(rcx, rsi, 1), ymm3, ymm6) vmovupd(ymm4, mem(rcx )) vmovupd(ymm6, mem(rcx, rsi, 1)) //lea(mem(rcx, rsi, 4), rcx) vunpcklpd(xmm14, xmm12, xmm0) vunpckhpd(xmm14, xmm12, xmm1) vfmadd231pd(mem(rdx ), xmm3, xmm0) vfmadd231pd(mem(rdx, rsi, 1), xmm3, xmm1) vmovupd(xmm0, mem(rdx )) vmovupd(xmm1, mem(rdx, rsi, 1)) //lea(mem(rdx, rsi, 4), rdx) jmp(.DDONE) // jump to end. label(.DBETAZERO) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORBZ) // jump to column storage case label(.DROWSTORBZ) vmovupd(xmm4, mem(rcx, 0*32)) add(rdi, rcx) vmovupd(xmm6, mem(rcx, 0*32)) add(rdi, rcx) vmovupd(xmm8, mem(rcx, 0*32)) add(rdi, rcx) vmovupd(xmm10, mem(rcx, 0*32)) add(rdi, rcx) vmovupd(xmm12, mem(rcx, 0*32)) add(rdi, rcx) vmovupd(xmm14, mem(rcx, 0*32)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORBZ) // begin I/O on columns 0-3 vunpcklpd(xmm6, xmm4, xmm0) vunpckhpd(xmm6, xmm4, xmm1) vunpcklpd(xmm10, xmm8, xmm2) vunpckhpd(xmm10, xmm8, xmm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vmovupd(ymm4, mem(rcx )) vmovupd(ymm6, mem(rcx, rsi, 1)) //lea(mem(rcx, rsi, 4), rcx) vunpcklpd(xmm14, xmm12, xmm0) vunpckhpd(xmm14, xmm12, xmm1) vmovupd(xmm0, mem(rdx )) vmovupd(xmm1, mem(rdx, rsi, 1)) //lea(mem(rdx, rsi, 4), rdx) label(.DDONE) lea(mem(r12, rdi, 4), r12) // lea(mem(r12, rdi, 2), r12) // c_ii = r12 += 6*rs_c //lea(mem(r14, r8, 4), r14) // //lea(mem(r14, r8, 2), r14) // a_ii = r14 += 6*rs_a mov(var(ps_a8), rax) // load ps_a8 lea(mem(r14, rax, 1), r14) // a_ii = r14 += ps_a8 dec(r11) // ii -= 1; jne(.DLOOP6X2I) // iterate again if ii != 0. label(.DRETURN) end_asm( : // output operands (none) : // input operands [m_iter] "m" (m_iter), [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [ps_a8] "m" (ps_a8), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the m dimension, if they exist. if ( m_left ) { const dim_t nr_cur = 2; const dim_t i_edge = m0 - ( dim_t )m_left; double* restrict cij = c + i_edge*rs_c; //double* restrict ai = a + i_edge*rs_a; //double* restrict ai = a + ( i_edge / 6 ) * ps_a; double* restrict ai = a + m_iter * ps_a; double* restrict bj = b; #if 0 // We add special handling for slightly inflated MR blocksizes // at edge cases, up to a maximum of 9. if ( 6 < m_left ) { dgemmsup_ker_ft ker_fp1 = NULL; dgemmsup_ker_ft ker_fp2 = NULL; dim_t mr1, mr2; if ( m_left == 7 ) { mr1 = 4; mr2 = 3; ker_fp1 = bli_dgemmsup_rv_haswell_asm_4x2; ker_fp2 = bli_dgemmsup_rv_haswell_asm_3x2; } else if ( m_left == 8 ) { mr1 = 4; mr2 = 4; ker_fp1 = bli_dgemmsup_rv_haswell_asm_4x2; ker_fp2 = bli_dgemmsup_rv_haswell_asm_4x2; } else // if ( m_left == 9 ) { mr1 = 4; mr2 = 5; ker_fp1 = bli_dgemmsup_rv_haswell_asm_4x2; ker_fp2 = bli_dgemmsup_rv_haswell_asm_5x2; } ker_fp1 ( conja, conjb, mr1, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += mr1*rs_c0; ai += mr1*rs_a0; ker_fp2 ( conja, conjb, mr2, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); return; } #endif dgemmsup_ker_ft ker_fps[6] = { NULL, bli_dgemmsup_rv_haswell_asm_1x2, bli_dgemmsup_rv_haswell_asm_2x2, bli_dgemmsup_rv_haswell_asm_3x2, bli_dgemmsup_rv_haswell_asm_4x2, bli_dgemmsup_rv_haswell_asm_5x2 }; dgemmsup_ker_ft ker_fp = ker_fps[ m_left ]; ker_fp ( conja, conjb, m_left, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); return; } } blis-0.9.0/kernels/haswell/3/sup/bli_gemmsup_rv_haswell_asm_d6x8n.c000066400000000000000000003363321422157504600253300ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define BLIS_ASM_SYNTAX_ATT #include "bli_x86_asm_macros.h" /* rrr: -------- ------ -------- -------- ------ -------- -------- += ------ ... -------- -------- ------ -------- -------- ------ : -------- ------ : rcr: -------- | | | | -------- -------- | | | | -------- -------- += | | | | ... -------- -------- | | | | -------- -------- | | | | : -------- | | | | : Assumptions: - B is row-stored; - A is row- or column-stored; - m0 and n0 are at most MR and NR, respectively. Therefore, this (r)ow-preferential kernel is well-suited for contiguous (v)ector loads on B and single-element broadcasts from A. NOTE: These kernels explicitly support column-oriented IO, implemented via an in-register transpose. And thus they also support the crr and ccr cases, though only crr is ever utilized (because ccr is handled by transposing the operation and executing rcr, which does not incur the cost of the in-register transpose). crr: | | | | | | | | ------ -------- | | | | | | | | ------ -------- | | | | | | | | += ------ ... -------- | | | | | | | | ------ -------- | | | | | | | | ------ : | | | | | | | | ------ : */ // Prototype reference microkernels. GEMMSUP_KER_PROT( double, d, gemmsup_r_haswell_ref ) void bli_dgemmsup_rv_haswell_asm_6x8n ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { uint64_t m_left = m0 % 6; // First check whether this is a edge case in the m dimension. If so, // dispatch other ?x8m kernels, as needed. if ( m_left ) { double* restrict cij = c; double* restrict bj = b; double* restrict ai = a; #if 1 // We add special handling for slightly inflated MR blocksizes // at edge cases, up to a maximum of 9. if ( 6 < m0 ) { dgemmsup_ker_ft ker_fp1 = NULL; dgemmsup_ker_ft ker_fp2 = NULL; dim_t mr1, mr2; if ( m0 == 7 ) { mr1 = 4; mr2 = 3; ker_fp1 = bli_dgemmsup_rv_haswell_asm_4x8n; ker_fp2 = bli_dgemmsup_rv_haswell_asm_3x8n; } else if ( m0 == 8 ) { mr1 = 4; mr2 = 4; ker_fp1 = bli_dgemmsup_rv_haswell_asm_4x8n; ker_fp2 = bli_dgemmsup_rv_haswell_asm_4x8n; } else // if ( m0 == 9 ) { mr1 = 4; mr2 = 5; ker_fp1 = bli_dgemmsup_rv_haswell_asm_4x8n; ker_fp2 = bli_dgemmsup_rv_haswell_asm_5x8n; } ker_fp1 ( conja, conjb, mr1, n0, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += mr1*rs_c0; ai += mr1*rs_a0; ker_fp2 ( conja, conjb, mr2, n0, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); return; } #endif dgemmsup_ker_ft ker_fps[6] = { NULL, bli_dgemmsup_rv_haswell_asm_1x8n, bli_dgemmsup_rv_haswell_asm_2x8n, bli_dgemmsup_rv_haswell_asm_3x8n, bli_dgemmsup_rv_haswell_asm_4x8n, bli_dgemmsup_rv_haswell_asm_5x8n }; dgemmsup_ker_ft ker_fp = ker_fps[ m_left ]; ker_fp ( conja, conjb, m_left, n0, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); return; } //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t n_iter = n0 / 8; uint64_t n_left = n0 % 8; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // Query the panel stride of B and convert it to units of bytes. uint64_t ps_b = bli_auxinfo_ps_b( data ); uint64_t ps_b8 = ps_b * sizeof( double ); if ( n_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. //mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), r14) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) //lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) // During preamble and loops: // r12 = rcx = c // r14 = rbx = b // read rax from var(a) near beginning of loop // r11 = m dim index ii mov(var(n_iter), r11) // jj = n_iter; label(.DLOOP6X8J) // LOOP OVER jj = [ n_iter ... 1 0 ] #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm5, ymm5, ymm5) vxorpd(ymm6, ymm6, ymm6) vxorpd(ymm7, ymm7, ymm7) vxorpd(ymm8, ymm8, ymm8) vxorpd(ymm9, ymm9, ymm9) vxorpd(ymm10, ymm10, ymm10) vxorpd(ymm11, ymm11, ymm11) vxorpd(ymm12, ymm12, ymm12) vxorpd(ymm13, ymm13, ymm13) vxorpd(ymm14, ymm14, ymm14) vxorpd(ymm15, ymm15, ymm15) #endif mov(var(a), rax) // load address of a. //mov(r12, rcx) // reset rcx to current utile of c. mov(r14, rbx) // reset rbx to current upanel of b. cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLPFETCH) // jump to column storage case label(.DROWPFETCH) // row-stored prefetching on c lea(mem(r12, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(r12, 7*8)) // prefetch c + 0*rs_c prefetch(0, mem(r12, rdi, 1, 7*8)) // prefetch c + 1*rs_c prefetch(0, mem(r12, rdi, 2, 7*8)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 7*8)) // prefetch c + 3*rs_c prefetch(0, mem(rdx, rdi, 1, 7*8)) // prefetch c + 4*rs_c prefetch(0, mem(rdx, rdi, 2, 7*8)) // prefetch c + 5*rs_c jmp(.DPOSTPFETCH) // jump to end of prefetching c label(.DCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 8), rsi) // cs_c *= sizeof(double) lea(mem(r12, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; prefetch(0, mem(r12, 5*8)) // prefetch c + 0*cs_c prefetch(0, mem(r12, rsi, 1, 5*8)) // prefetch c + 1*cs_c prefetch(0, mem(r12, rsi, 2, 5*8)) // prefetch c + 2*cs_c prefetch(0, mem(rdx, 5*8)) // prefetch c + 3*cs_c prefetch(0, mem(rdx, rsi, 1, 5*8)) // prefetch c + 4*cs_c prefetch(0, mem(rdx, rsi, 2, 5*8)) // prefetch c + 5*cs_c lea(mem(rdx, rsi, 2), rdx) // rdx = c + 5*cs_c; prefetch(0, mem(rdx, rsi, 1, 5*8)) // prefetch c + 6*cs_c prefetch(0, mem(rdx, rsi, 2, 5*8)) // prefetch c + 7*cs_c label(.DPOSTPFETCH) // done prefetching c #if 1 mov(var(ps_b8), rdx) // load ps_b8 lea(mem(rbx, rdx, 1), rdx) // rdx = b + ps_b8 lea(mem(r10, r10, 2), rcx) // rcx = 3*rs_b; // use rcx, rdx for prefetching lines // from next upanel of b. #else lea(mem(rbx, r8, 8), rdx) // use rdx for prefetching lines lea(mem(rdx, r8, 8), rdx) // from next upanel of b. lea(mem(r10, r10, 2), rcx) // rcx = 3*rs_b; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.DLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, 5*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, r8, 4), ymm2) vbroadcastsd(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, r10, 1, 5*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, r8, 4), ymm2) vbroadcastsd(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) // ---------------------------------- iteration 2 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, r10, 2, 5*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, r8, 4), ymm2) vbroadcastsd(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) // ---------------------------------- iteration 3 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, rcx, 1, 5*8)) lea(mem(rdx, r10, 4), rdx) // b_prefetch += 4*rs_b; #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, r8, 4), ymm2) vbroadcastsd(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKITER) // iterate again if i != 0. label(.DCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.DLOOPKLEFT) // EDGE LOOP #if 1 prefetch(0, mem(rdx, 5*8)) add(r10, rdx) // b_prefetch += rs_b; #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, r8, 4), ymm2) vbroadcastsd(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKLEFT) // iterate again if i != 0. label(.DPOSTACCUM) mov(r12, rcx) // reset rcx to current utile of c. mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(ymm0, ymm5, ymm5) vmulpd(ymm0, ymm6, ymm6) vmulpd(ymm0, ymm7, ymm7) vmulpd(ymm0, ymm8, ymm8) vmulpd(ymm0, ymm9, ymm9) vmulpd(ymm0, ymm10, ymm10) vmulpd(ymm0, ymm11, ymm11) vmulpd(ymm0, ymm12, ymm12) vmulpd(ymm0, ymm13, ymm13) vmulpd(ymm0, ymm14, ymm14) vmulpd(ymm0, ymm15, ymm15) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORED) // jump to column storage case label(.DROWSTORED) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm4) vmovupd(ymm4, mem(rcx, 0*32)) vfmadd231pd(mem(rcx, 1*32), ymm3, ymm5) vmovupd(ymm5, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm6) vmovupd(ymm6, mem(rcx, 0*32)) vfmadd231pd(mem(rcx, 1*32), ymm3, ymm7) vmovupd(ymm7, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm8) vmovupd(ymm8, mem(rcx, 0*32)) vfmadd231pd(mem(rcx, 1*32), ymm3, ymm9) vmovupd(ymm9, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm10) vmovupd(ymm10, mem(rcx, 0*32)) vfmadd231pd(mem(rcx, 1*32), ymm3, ymm11) vmovupd(ymm11, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm12) vmovupd(ymm12, mem(rcx, 0*32)) vfmadd231pd(mem(rcx, 1*32), ymm3, ymm13) vmovupd(ymm13, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm14) vmovupd(ymm14, mem(rcx, 0*32)) vfmadd231pd(mem(rcx, 1*32), ymm3, ymm15) vmovupd(ymm15, mem(rcx, 1*32)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORED) // begin I/O on columns 0-3 vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vunpcklpd(ymm10, ymm8, ymm2) vunpckhpd(ymm10, ymm8, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vperm2f128(imm(0x31), ymm2, ymm0, ymm8) vperm2f128(imm(0x31), ymm3, ymm1, ymm10) vbroadcastsd(mem(rbx), ymm3) vfmadd231pd(mem(rcx ), ymm3, ymm4) vfmadd231pd(mem(rcx, rsi, 1), ymm3, ymm6) vfmadd231pd(mem(rcx, rsi, 2), ymm3, ymm8) vfmadd231pd(mem(rcx, rax, 1), ymm3, ymm10) vmovupd(ymm4, mem(rcx )) vmovupd(ymm6, mem(rcx, rsi, 1)) vmovupd(ymm8, mem(rcx, rsi, 2)) vmovupd(ymm10, mem(rcx, rax, 1)) lea(mem(rcx, rsi, 4), rcx) vunpcklpd(ymm14, ymm12, ymm0) vunpckhpd(ymm14, ymm12, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vextractf128(imm(0x1), ymm1, xmm4) vfmadd231pd(mem(rdx ), xmm3, xmm0) vfmadd231pd(mem(rdx, rsi, 1), xmm3, xmm1) vfmadd231pd(mem(rdx, rsi, 2), xmm3, xmm2) vfmadd231pd(mem(rdx, rax, 1), xmm3, xmm4) vmovupd(xmm0, mem(rdx )) vmovupd(xmm1, mem(rdx, rsi, 1)) vmovupd(xmm2, mem(rdx, rsi, 2)) vmovupd(xmm4, mem(rdx, rax, 1)) lea(mem(rdx, rsi, 4), rdx) // begin I/O on columns 4-7 vunpcklpd(ymm7, ymm5, ymm0) vunpckhpd(ymm7, ymm5, ymm1) vunpcklpd(ymm11, ymm9, ymm2) vunpckhpd(ymm11, ymm9, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm5) vinsertf128(imm(0x1), xmm3, ymm1, ymm7) vperm2f128(imm(0x31), ymm2, ymm0, ymm9) vperm2f128(imm(0x31), ymm3, ymm1, ymm11) vbroadcastsd(mem(rbx), ymm3) vfmadd231pd(mem(rcx ), ymm3, ymm5) vfmadd231pd(mem(rcx, rsi, 1), ymm3, ymm7) vfmadd231pd(mem(rcx, rsi, 2), ymm3, ymm9) vfmadd231pd(mem(rcx, rax, 1), ymm3, ymm11) vmovupd(ymm5, mem(rcx )) vmovupd(ymm7, mem(rcx, rsi, 1)) vmovupd(ymm9, mem(rcx, rsi, 2)) vmovupd(ymm11, mem(rcx, rax, 1)) //lea(mem(rcx, rsi, 4), rcx) vunpcklpd(ymm15, ymm13, ymm0) vunpckhpd(ymm15, ymm13, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vextractf128(imm(0x1), ymm1, xmm4) vfmadd231pd(mem(rdx ), xmm3, xmm0) vfmadd231pd(mem(rdx, rsi, 1), xmm3, xmm1) vfmadd231pd(mem(rdx, rsi, 2), xmm3, xmm2) vfmadd231pd(mem(rdx, rax, 1), xmm3, xmm4) vmovupd(xmm0, mem(rdx )) vmovupd(xmm1, mem(rdx, rsi, 1)) vmovupd(xmm2, mem(rdx, rsi, 2)) vmovupd(xmm4, mem(rdx, rax, 1)) //lea(mem(rdx, rsi, 4), rdx) jmp(.DDONE) // jump to end. label(.DBETAZERO) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORBZ) // jump to column storage case label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx, 0*32)) vmovupd(ymm5, mem(rcx, 1*32)) add(rdi, rcx) vmovupd(ymm6, mem(rcx, 0*32)) vmovupd(ymm7, mem(rcx, 1*32)) add(rdi, rcx) vmovupd(ymm8, mem(rcx, 0*32)) vmovupd(ymm9, mem(rcx, 1*32)) add(rdi, rcx) vmovupd(ymm10, mem(rcx, 0*32)) vmovupd(ymm11, mem(rcx, 1*32)) add(rdi, rcx) vmovupd(ymm12, mem(rcx, 0*32)) vmovupd(ymm13, mem(rcx, 1*32)) add(rdi, rcx) vmovupd(ymm14, mem(rcx, 0*32)) vmovupd(ymm15, mem(rcx, 1*32)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORBZ) // begin I/O on columns 0-3 vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vunpcklpd(ymm10, ymm8, ymm2) vunpckhpd(ymm10, ymm8, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vperm2f128(imm(0x31), ymm2, ymm0, ymm8) vperm2f128(imm(0x31), ymm3, ymm1, ymm10) vmovupd(ymm4, mem(rcx )) vmovupd(ymm6, mem(rcx, rsi, 1)) vmovupd(ymm8, mem(rcx, rsi, 2)) vmovupd(ymm10, mem(rcx, rax, 1)) lea(mem(rcx, rsi, 4), rcx) vunpcklpd(ymm14, ymm12, ymm0) vunpckhpd(ymm14, ymm12, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vextractf128(imm(0x1), ymm1, xmm4) vmovupd(xmm0, mem(rdx )) vmovupd(xmm1, mem(rdx, rsi, 1)) vmovupd(xmm2, mem(rdx, rsi, 2)) vmovupd(xmm4, mem(rdx, rax, 1)) lea(mem(rdx, rsi, 4), rdx) // begin I/O on columns 4-7 vunpcklpd(ymm7, ymm5, ymm0) vunpckhpd(ymm7, ymm5, ymm1) vunpcklpd(ymm11, ymm9, ymm2) vunpckhpd(ymm11, ymm9, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm5) vinsertf128(imm(0x1), xmm3, ymm1, ymm7) vperm2f128(imm(0x31), ymm2, ymm0, ymm9) vperm2f128(imm(0x31), ymm3, ymm1, ymm11) vmovupd(ymm5, mem(rcx )) vmovupd(ymm7, mem(rcx, rsi, 1)) vmovupd(ymm9, mem(rcx, rsi, 2)) vmovupd(ymm11, mem(rcx, rax, 1)) //lea(mem(rcx, rsi, 4), rcx) vunpcklpd(ymm15, ymm13, ymm0) vunpckhpd(ymm15, ymm13, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vextractf128(imm(0x1), ymm1, xmm4) vmovupd(xmm0, mem(rdx )) vmovupd(xmm1, mem(rdx, rsi, 1)) vmovupd(xmm2, mem(rdx, rsi, 2)) vmovupd(xmm4, mem(rdx, rax, 1)) //lea(mem(rdx, rsi, 4), rdx) label(.DDONE) lea(mem(r12, rsi, 8), r12) // c_jj = r12 += 8*cs_c //add(imm(8*8), r14) // b_jj = r14 += 8*cs_b mov(var(ps_b8), rbx) // load ps_b8 lea(mem(r14, rbx, 1), r14) // b_jj = r14 += ps_b8 dec(r11) // jj -= 1; jne(.DLOOP6X8J) // iterate again if jj != 0. label(.DRETURN) end_asm( : // output operands (none) : // input operands [n_iter] "m" (n_iter), [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [ps_b8] "m" (ps_b8), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the m dimension, if they exist. if ( n_left ) { const dim_t mr_cur = 6; const dim_t j_edge = n0 - ( dim_t )n_left; double* restrict cij = c + j_edge*cs_c; double* restrict ai = a; //double* restrict bj = b + j_edge*cs_b; //double* restrict bj = b + ( j_edge / 8 ) * ps_b; double* restrict bj = b + n_iter * ps_b; if ( 6 <= n_left ) { const dim_t nr_cur = 6; bli_dgemmsup_rv_haswell_asm_6x6 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 4 <= n_left ) { const dim_t nr_cur = 4; bli_dgemmsup_rv_haswell_asm_6x4 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 2 <= n_left ) { const dim_t nr_cur = 2; bli_dgemmsup_rv_haswell_asm_6x2 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 1 == n_left ) { #if 1 const dim_t nr_cur = 1; bli_dgemmsup_r_haswell_ref_6x1 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); #else bli_dgemv_ex ( BLIS_NO_TRANSPOSE, conjb, m0, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, beta, cij, rs_c0, cntx, NULL ); #endif } } } void bli_dgemmsup_rv_haswell_asm_5x8n ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t n_iter = n0 / 8; uint64_t n_left = n0 % 8; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // Query the panel stride of B and convert it to units of bytes. uint64_t ps_b = bli_auxinfo_ps_b( data ); uint64_t ps_b8 = ps_b * sizeof( double ); if ( n_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. //mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), r14) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) //lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) // During preamble and loops: // r12 = rcx = c // r14 = rbx = b // read rax from var(a) near beginning of loop // r11 = m dim index ii mov(var(n_iter), r11) // jj = n_iter; label(.DLOOP6X8J) // LOOP OVER jj = [ n_iter ... 1 0 ] #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm5, ymm5, ymm5) vxorpd(ymm6, ymm6, ymm6) vxorpd(ymm7, ymm7, ymm7) vxorpd(ymm8, ymm8, ymm8) vxorpd(ymm9, ymm9, ymm9) vxorpd(ymm10, ymm10, ymm10) vxorpd(ymm11, ymm11, ymm11) vxorpd(ymm12, ymm12, ymm12) vxorpd(ymm13, ymm13, ymm13) #endif mov(var(a), rax) // load address of a. //mov(r12, rcx) // reset rcx to current utile of c. mov(r14, rbx) // reset rbx to current upanel of b. cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLPFETCH) // jump to column storage case label(.DROWPFETCH) // row-stored prefetching on c lea(mem(r12, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(r12, 7*8)) // prefetch c + 0*rs_c prefetch(0, mem(r12, rdi, 1, 7*8)) // prefetch c + 1*rs_c prefetch(0, mem(r12, rdi, 2, 7*8)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 7*8)) // prefetch c + 3*rs_c prefetch(0, mem(rdx, rdi, 1, 7*8)) // prefetch c + 4*rs_c jmp(.DPOSTPFETCH) // jump to end of prefetching c label(.DCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 8), rsi) // cs_c *= sizeof(double) lea(mem(r12, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; prefetch(0, mem(r12, 4*8)) // prefetch c + 0*cs_c prefetch(0, mem(r12, rsi, 1, 4*8)) // prefetch c + 1*cs_c prefetch(0, mem(r12, rsi, 2, 4*8)) // prefetch c + 2*cs_c prefetch(0, mem(rdx, 4*8)) // prefetch c + 3*cs_c prefetch(0, mem(rdx, rsi, 1, 4*8)) // prefetch c + 4*cs_c prefetch(0, mem(rdx, rsi, 2, 4*8)) // prefetch c + 5*cs_c lea(mem(rdx, rsi, 2), rdx) // rdx = c + 5*cs_c; prefetch(0, mem(rdx, rsi, 1, 4*8)) // prefetch c + 6*cs_c prefetch(0, mem(rdx, rsi, 2, 4*8)) // prefetch c + 7*cs_c label(.DPOSTPFETCH) // done prefetching c #if 1 mov(var(ps_b8), rdx) // load ps_b8 lea(mem(rbx, rdx, 1), rdx) // rdx = b + ps_b8 lea(mem(r10, r10, 2), rcx) // rcx = 3*rs_b; // use rcx, rdx for prefetching lines // from next upanel of b. #else lea(mem(rbx, r8, 8), rdx) // use rdx for prefetching lines lea(mem(rdx, r8, 8), rdx) // from next upanel of b. lea(mem(r10, r10, 2), rcx) // rcx = 3*rs_b; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.DLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, 5*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, r10, 1, 5*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) // ---------------------------------- iteration 2 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, r10, 2, 5*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) // ---------------------------------- iteration 3 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, rcx, 1, 5*8)) lea(mem(rdx, r10, 4), rdx) // b_prefetch += 4*rs_b; #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) dec(rsi) // i -= 1; jne(.DLOOPKITER) // iterate again if i != 0. label(.DCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.DLOOPKLEFT) // EDGE LOOP #if 1 prefetch(0, mem(rdx, 5*8)) add(r10, rdx) // b_prefetch += rs_b; #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) dec(rsi) // i -= 1; jne(.DLOOPKLEFT) // iterate again if i != 0. label(.DPOSTACCUM) mov(r12, rcx) // reset rcx to current utile of c. mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(ymm0, ymm5, ymm5) vmulpd(ymm0, ymm6, ymm6) vmulpd(ymm0, ymm7, ymm7) vmulpd(ymm0, ymm8, ymm8) vmulpd(ymm0, ymm9, ymm9) vmulpd(ymm0, ymm10, ymm10) vmulpd(ymm0, ymm11, ymm11) vmulpd(ymm0, ymm12, ymm12) vmulpd(ymm0, ymm13, ymm13) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORED) // jump to column storage case label(.DROWSTORED) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm4) vmovupd(ymm4, mem(rcx, 0*32)) vfmadd231pd(mem(rcx, 1*32), ymm3, ymm5) vmovupd(ymm5, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm6) vmovupd(ymm6, mem(rcx, 0*32)) vfmadd231pd(mem(rcx, 1*32), ymm3, ymm7) vmovupd(ymm7, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm8) vmovupd(ymm8, mem(rcx, 0*32)) vfmadd231pd(mem(rcx, 1*32), ymm3, ymm9) vmovupd(ymm9, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm10) vmovupd(ymm10, mem(rcx, 0*32)) vfmadd231pd(mem(rcx, 1*32), ymm3, ymm11) vmovupd(ymm11, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm12) vmovupd(ymm12, mem(rcx, 0*32)) vfmadd231pd(mem(rcx, 1*32), ymm3, ymm13) vmovupd(ymm13, mem(rcx, 1*32)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORED) // begin I/O on columns 0-3 vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vunpcklpd(ymm10, ymm8, ymm2) vunpckhpd(ymm10, ymm8, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vperm2f128(imm(0x31), ymm2, ymm0, ymm8) vperm2f128(imm(0x31), ymm3, ymm1, ymm10) vbroadcastsd(mem(rbx), ymm3) vfmadd231pd(mem(rcx ), ymm3, ymm4) vfmadd231pd(mem(rcx, rsi, 1), ymm3, ymm6) vfmadd231pd(mem(rcx, rsi, 2), ymm3, ymm8) vfmadd231pd(mem(rcx, rax, 1), ymm3, ymm10) vmovupd(ymm4, mem(rcx )) vmovupd(ymm6, mem(rcx, rsi, 1)) vmovupd(ymm8, mem(rcx, rsi, 2)) vmovupd(ymm10, mem(rcx, rax, 1)) lea(mem(rcx, rsi, 4), rcx) vmovlpd(mem(rdx ), xmm0, xmm0) vmovhpd(mem(rdx, rsi, 1), xmm0, xmm0) vmovlpd(mem(rdx, rsi, 2), xmm1, xmm1) vmovhpd(mem(rdx, rax, 1), xmm1, xmm1) vperm2f128(imm(0x20), ymm1, ymm0, ymm0) vfmadd213pd(ymm12, ymm3, ymm0) vextractf128(imm(1), ymm0, xmm1) vmovlpd(xmm0, mem(rdx )) vmovhpd(xmm0, mem(rdx, rsi, 1)) vmovlpd(xmm1, mem(rdx, rsi, 2)) vmovhpd(xmm1, mem(rdx, rax, 1)) lea(mem(rdx, rsi, 4), rdx) // begin I/O on columns 4-7 vunpcklpd(ymm7, ymm5, ymm0) vunpckhpd(ymm7, ymm5, ymm1) vunpcklpd(ymm11, ymm9, ymm2) vunpckhpd(ymm11, ymm9, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm5) vinsertf128(imm(0x1), xmm3, ymm1, ymm7) vperm2f128(imm(0x31), ymm2, ymm0, ymm9) vperm2f128(imm(0x31), ymm3, ymm1, ymm11) vbroadcastsd(mem(rbx), ymm3) vfmadd231pd(mem(rcx ), ymm3, ymm5) vfmadd231pd(mem(rcx, rsi, 1), ymm3, ymm7) vfmadd231pd(mem(rcx, rsi, 2), ymm3, ymm9) vfmadd231pd(mem(rcx, rax, 1), ymm3, ymm11) vmovupd(ymm5, mem(rcx )) vmovupd(ymm7, mem(rcx, rsi, 1)) vmovupd(ymm9, mem(rcx, rsi, 2)) vmovupd(ymm11, mem(rcx, rax, 1)) //lea(mem(rcx, rsi, 4), rcx) vmovlpd(mem(rdx ), xmm0, xmm0) vmovhpd(mem(rdx, rsi, 1), xmm0, xmm0) vmovlpd(mem(rdx, rsi, 2), xmm1, xmm1) vmovhpd(mem(rdx, rax, 1), xmm1, xmm1) vperm2f128(imm(0x20), ymm1, ymm0, ymm0) vfmadd213pd(ymm13, ymm3, ymm0) vextractf128(imm(1), ymm0, xmm1) vmovlpd(xmm0, mem(rdx )) vmovhpd(xmm0, mem(rdx, rsi, 1)) vmovlpd(xmm1, mem(rdx, rsi, 2)) vmovhpd(xmm1, mem(rdx, rax, 1)) //lea(mem(rdx, rsi, 4), rdx) jmp(.DDONE) // jump to end. label(.DBETAZERO) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORBZ) // jump to column storage case label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx, 0*32)) vmovupd(ymm5, mem(rcx, 1*32)) add(rdi, rcx) vmovupd(ymm6, mem(rcx, 0*32)) vmovupd(ymm7, mem(rcx, 1*32)) add(rdi, rcx) vmovupd(ymm8, mem(rcx, 0*32)) vmovupd(ymm9, mem(rcx, 1*32)) add(rdi, rcx) vmovupd(ymm10, mem(rcx, 0*32)) vmovupd(ymm11, mem(rcx, 1*32)) add(rdi, rcx) vmovupd(ymm12, mem(rcx, 0*32)) vmovupd(ymm13, mem(rcx, 1*32)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORBZ) // begin I/O on columns 0-3 vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vunpcklpd(ymm10, ymm8, ymm2) vunpckhpd(ymm10, ymm8, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vperm2f128(imm(0x31), ymm2, ymm0, ymm8) vperm2f128(imm(0x31), ymm3, ymm1, ymm10) vmovupd(ymm4, mem(rcx )) vmovupd(ymm6, mem(rcx, rsi, 1)) vmovupd(ymm8, mem(rcx, rsi, 2)) vmovupd(ymm10, mem(rcx, rax, 1)) lea(mem(rcx, rsi, 4), rcx) vmovupd(ymm12, ymm0) vextractf128(imm(1), ymm0, xmm1) vmovlpd(xmm0, mem(rdx )) vmovhpd(xmm0, mem(rdx, rsi, 1)) vmovlpd(xmm1, mem(rdx, rsi, 2)) vmovhpd(xmm1, mem(rdx, rax, 1)) lea(mem(rdx, rsi, 4), rdx) // begin I/O on columns 4-7 vunpcklpd(ymm7, ymm5, ymm0) vunpckhpd(ymm7, ymm5, ymm1) vunpcklpd(ymm11, ymm9, ymm2) vunpckhpd(ymm11, ymm9, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm5) vinsertf128(imm(0x1), xmm3, ymm1, ymm7) vperm2f128(imm(0x31), ymm2, ymm0, ymm9) vperm2f128(imm(0x31), ymm3, ymm1, ymm11) vmovupd(ymm5, mem(rcx )) vmovupd(ymm7, mem(rcx, rsi, 1)) vmovupd(ymm9, mem(rcx, rsi, 2)) vmovupd(ymm11, mem(rcx, rax, 1)) //lea(mem(rcx, rsi, 4), rcx) vmovupd(ymm13, ymm0) vextractf128(imm(1), ymm0, xmm1) vmovlpd(xmm0, mem(rdx )) vmovhpd(xmm0, mem(rdx, rsi, 1)) vmovlpd(xmm1, mem(rdx, rsi, 2)) vmovhpd(xmm1, mem(rdx, rax, 1)) //lea(mem(rdx, rsi, 4), rdx) label(.DDONE) lea(mem(r12, rsi, 8), r12) // c_jj = r12 += 8*cs_c //add(imm(8*8), r14) // b_jj = r14 += 8*cs_b mov(var(ps_b8), rbx) // load ps_b8 lea(mem(r14, rbx, 1), r14) // b_jj = r14 += ps_b8 dec(r11) // jj -= 1; jne(.DLOOP6X8J) // iterate again if jj != 0. label(.DRETURN) end_asm( : // output operands (none) : // input operands [n_iter] "m" (n_iter), [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [ps_b8] "m" (ps_b8), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the m dimension, if they exist. if ( n_left ) { const dim_t mr_cur = 5; const dim_t j_edge = n0 - ( dim_t )n_left; double* restrict cij = c + j_edge*cs_c; double* restrict ai = a; //double* restrict bj = b + j_edge*cs_b; //double* restrict bj = b + ( j_edge / 8 ) * ps_b; double* restrict bj = b + n_iter * ps_b; if ( 6 <= n_left ) { const dim_t nr_cur = 6; bli_dgemmsup_rv_haswell_asm_5x6 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 4 <= n_left ) { const dim_t nr_cur = 4; bli_dgemmsup_rv_haswell_asm_5x4 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 2 <= n_left ) { const dim_t nr_cur = 2; bli_dgemmsup_rv_haswell_asm_5x2 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 1 == n_left ) { #if 1 const dim_t nr_cur = 1; bli_dgemmsup_r_haswell_ref_5x1 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); #else bli_dgemv_ex ( BLIS_NO_TRANSPOSE, conjb, m0, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, beta, cij, rs_c0, cntx, NULL ); #endif } } } void bli_dgemmsup_rv_haswell_asm_4x8n ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t n_iter = n0 / 8; uint64_t n_left = n0 % 8; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // Query the panel stride of B and convert it to units of bytes. uint64_t ps_b = bli_auxinfo_ps_b( data ); uint64_t ps_b8 = ps_b * sizeof( double ); if ( n_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. //mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), r14) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) //lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) // During preamble and loops: // r12 = rcx = c // r14 = rbx = b // read rax from var(a) near beginning of loop // r11 = m dim index ii mov(var(n_iter), r11) // jj = n_iter; label(.DLOOP4X8J) // LOOP OVER jj = [ n_iter ... 1 0 ] #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm5, ymm5, ymm5) vxorpd(ymm6, ymm6, ymm6) vxorpd(ymm7, ymm7, ymm7) vxorpd(ymm8, ymm8, ymm8) vxorpd(ymm9, ymm9, ymm9) vxorpd(ymm10, ymm10, ymm10) vxorpd(ymm11, ymm11, ymm11) #endif mov(var(a), rax) // load address of a. //mov(r12, rcx) // reset rcx to current utile of c. mov(r14, rbx) // reset rbx to current upanel of b. cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLPFETCH) // jump to column storage case label(.DROWPFETCH) // row-stored prefetching on c lea(mem(r12, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(r12, 7*8)) // prefetch c + 0*rs_c prefetch(0, mem(r12, rdi, 1, 7*8)) // prefetch c + 1*rs_c prefetch(0, mem(r12, rdi, 2, 7*8)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 7*8)) // prefetch c + 3*rs_c jmp(.DPOSTPFETCH) // jump to end of prefetching c label(.DCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 8), rsi) // cs_c *= sizeof(double) lea(mem(r12, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; prefetch(0, mem(r12, 3*8)) // prefetch c + 0*cs_c prefetch(0, mem(r12, rsi, 1, 3*8)) // prefetch c + 1*cs_c prefetch(0, mem(r12, rsi, 2, 3*8)) // prefetch c + 2*cs_c prefetch(0, mem(rdx, 3*8)) // prefetch c + 3*cs_c prefetch(0, mem(rdx, rsi, 1, 3*8)) // prefetch c + 4*cs_c prefetch(0, mem(rdx, rsi, 2, 3*8)) // prefetch c + 5*cs_c lea(mem(rdx, rsi, 2), rdx) // rdx = c + 5*cs_c; prefetch(0, mem(rdx, rsi, 1, 3*8)) // prefetch c + 6*cs_c prefetch(0, mem(rdx, rsi, 2, 3*8)) // prefetch c + 7*cs_c label(.DPOSTPFETCH) // done prefetching c #if 1 mov(var(ps_b8), rdx) // load ps_b8 lea(mem(rbx, rdx, 1), rdx) // rdx = b + ps_b8 lea(mem(r10, r10, 2), rcx) // rcx = 3*rs_b; // use rcx, rdx for prefetching lines // from next upanel of b. #else lea(mem(rbx, r8, 8), rdx) // use rdx for prefetching lines lea(mem(rdx, r8, 8), rdx) // from next upanel of b. lea(mem(r10, r10, 2), rcx) // rcx = 3*rs_b; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.DLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, 5*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, r10, 1, 5*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) // ---------------------------------- iteration 2 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, r10, 2, 5*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) // ---------------------------------- iteration 3 #if 1 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, rcx, 1, 5*8)) lea(mem(rdx, r10, 4), rdx) // b_prefetch += 4*rs_b; #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) dec(rsi) // i -= 1; jne(.DLOOPKITER) // iterate again if i != 0. label(.DCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.DLOOPKLEFT) // EDGE LOOP #if 1 prefetch(0, mem(rdx, 5*8)) add(r10, rdx) // b_prefetch += rs_b; #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) dec(rsi) // i -= 1; jne(.DLOOPKLEFT) // iterate again if i != 0. label(.DPOSTACCUM) mov(r12, rcx) // reset rcx to current utile of c. mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(ymm0, ymm5, ymm5) vmulpd(ymm0, ymm6, ymm6) vmulpd(ymm0, ymm7, ymm7) vmulpd(ymm0, ymm8, ymm8) vmulpd(ymm0, ymm9, ymm9) vmulpd(ymm0, ymm10, ymm10) vmulpd(ymm0, ymm11, ymm11) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; //lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORED) // jump to column storage case label(.DROWSTORED) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm4) vmovupd(ymm4, mem(rcx, 0*32)) vfmadd231pd(mem(rcx, 1*32), ymm3, ymm5) vmovupd(ymm5, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm6) vmovupd(ymm6, mem(rcx, 0*32)) vfmadd231pd(mem(rcx, 1*32), ymm3, ymm7) vmovupd(ymm7, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm8) vmovupd(ymm8, mem(rcx, 0*32)) vfmadd231pd(mem(rcx, 1*32), ymm3, ymm9) vmovupd(ymm9, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm10) vmovupd(ymm10, mem(rcx, 0*32)) vfmadd231pd(mem(rcx, 1*32), ymm3, ymm11) vmovupd(ymm11, mem(rcx, 1*32)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORED) // begin I/O on columns 0-3 vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vunpcklpd(ymm10, ymm8, ymm2) vunpckhpd(ymm10, ymm8, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vperm2f128(imm(0x31), ymm2, ymm0, ymm8) vperm2f128(imm(0x31), ymm3, ymm1, ymm10) vbroadcastsd(mem(rbx), ymm3) vfmadd231pd(mem(rcx ), ymm3, ymm4) vfmadd231pd(mem(rcx, rsi, 1), ymm3, ymm6) vfmadd231pd(mem(rcx, rsi, 2), ymm3, ymm8) vfmadd231pd(mem(rcx, rax, 1), ymm3, ymm10) vmovupd(ymm4, mem(rcx )) vmovupd(ymm6, mem(rcx, rsi, 1)) vmovupd(ymm8, mem(rcx, rsi, 2)) vmovupd(ymm10, mem(rcx, rax, 1)) lea(mem(rcx, rsi, 4), rcx) // begin I/O on columns 4-7 vunpcklpd(ymm7, ymm5, ymm0) vunpckhpd(ymm7, ymm5, ymm1) vunpcklpd(ymm11, ymm9, ymm2) vunpckhpd(ymm11, ymm9, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm5) vinsertf128(imm(0x1), xmm3, ymm1, ymm7) vperm2f128(imm(0x31), ymm2, ymm0, ymm9) vperm2f128(imm(0x31), ymm3, ymm1, ymm11) vbroadcastsd(mem(rbx), ymm3) vfmadd231pd(mem(rcx ), ymm3, ymm5) vfmadd231pd(mem(rcx, rsi, 1), ymm3, ymm7) vfmadd231pd(mem(rcx, rsi, 2), ymm3, ymm9) vfmadd231pd(mem(rcx, rax, 1), ymm3, ymm11) vmovupd(ymm5, mem(rcx )) vmovupd(ymm7, mem(rcx, rsi, 1)) vmovupd(ymm9, mem(rcx, rsi, 2)) vmovupd(ymm11, mem(rcx, rax, 1)) //lea(mem(rcx, rsi, 4), rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORBZ) // jump to column storage case label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx, 0*32)) vmovupd(ymm5, mem(rcx, 1*32)) add(rdi, rcx) vmovupd(ymm6, mem(rcx, 0*32)) vmovupd(ymm7, mem(rcx, 1*32)) add(rdi, rcx) vmovupd(ymm8, mem(rcx, 0*32)) vmovupd(ymm9, mem(rcx, 1*32)) add(rdi, rcx) vmovupd(ymm10, mem(rcx, 0*32)) vmovupd(ymm11, mem(rcx, 1*32)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORBZ) // begin I/O on columns 0-3 vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vunpcklpd(ymm10, ymm8, ymm2) vunpckhpd(ymm10, ymm8, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vperm2f128(imm(0x31), ymm2, ymm0, ymm8) vperm2f128(imm(0x31), ymm3, ymm1, ymm10) vmovupd(ymm4, mem(rcx )) vmovupd(ymm6, mem(rcx, rsi, 1)) vmovupd(ymm8, mem(rcx, rsi, 2)) vmovupd(ymm10, mem(rcx, rax, 1)) lea(mem(rcx, rsi, 4), rcx) // begin I/O on columns 4-7 vunpcklpd(ymm7, ymm5, ymm0) vunpckhpd(ymm7, ymm5, ymm1) vunpcklpd(ymm11, ymm9, ymm2) vunpckhpd(ymm11, ymm9, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm5) vinsertf128(imm(0x1), xmm3, ymm1, ymm7) vperm2f128(imm(0x31), ymm2, ymm0, ymm9) vperm2f128(imm(0x31), ymm3, ymm1, ymm11) vmovupd(ymm5, mem(rcx )) vmovupd(ymm7, mem(rcx, rsi, 1)) vmovupd(ymm9, mem(rcx, rsi, 2)) vmovupd(ymm11, mem(rcx, rax, 1)) //lea(mem(rcx, rsi, 4), rcx) label(.DDONE) lea(mem(r12, rsi, 8), r12) // c_jj = r12 += 8*cs_c //add(imm(8*8), r14) // b_jj = r14 += 8*cs_b mov(var(ps_b8), rbx) // load ps_b8 lea(mem(r14, rbx, 1), r14) // b_jj = r14 += ps_b8 dec(r11) // jj -= 1; jne(.DLOOP4X8J) // iterate again if jj != 0. label(.DRETURN) end_asm( : // output operands (none) : // input operands [n_iter] "m" (n_iter), [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [ps_b8] "m" (ps_b8), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the m dimension, if they exist. if ( n_left ) { const dim_t mr_cur = 4; const dim_t j_edge = n0 - ( dim_t )n_left; double* restrict cij = c + j_edge*cs_c; double* restrict ai = a; //double* restrict bj = b + j_edge*cs_b; //double* restrict bj = b + ( j_edge / 8 ) * ps_b; double* restrict bj = b + n_iter * ps_b; if ( 6 <= n_left ) { const dim_t nr_cur = 6; bli_dgemmsup_rv_haswell_asm_4x6 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 4 <= n_left ) { const dim_t nr_cur = 4; bli_dgemmsup_rv_haswell_asm_4x4 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 2 <= n_left ) { const dim_t nr_cur = 2; bli_dgemmsup_rv_haswell_asm_4x2 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 1 == n_left ) { const dim_t nr_cur = 1; bli_dgemmsup_r_haswell_ref_4x1 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); } } } void bli_dgemmsup_rv_haswell_asm_3x8n ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t n_iter = n0 / 8; uint64_t n_left = n0 % 8; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // Query the panel stride of B and convert it to units of bytes. uint64_t ps_b = bli_auxinfo_ps_b( data ); uint64_t ps_b8 = ps_b * sizeof( double ); if ( n_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. //mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), r14) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) //lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) // During preamble and loops: // r12 = rcx = c // r14 = rbx = b // read rax from var(a) near beginning of loop // r11 = m dim index ii mov(var(n_iter), r11) // jj = n_iter; label(.DLOOP4X8J) // LOOP OVER jj = [ n_iter ... 1 0 ] #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm5, ymm5, ymm5) vxorpd(ymm6, ymm6, ymm6) vxorpd(ymm7, ymm7, ymm7) vxorpd(ymm8, ymm8, ymm8) vxorpd(ymm9, ymm9, ymm9) vxorpd(ymm10, ymm10, ymm10) vxorpd(ymm11, ymm11, ymm11) vxorpd(ymm12, ymm12, ymm12) vxorpd(ymm13, ymm13, ymm13) vxorpd(ymm14, ymm14, ymm14) vxorpd(ymm15, ymm15, ymm15) #endif mov(var(a), rax) // load address of a. //mov(r12, rcx) // reset rcx to current utile of c. mov(r14, rbx) // reset rbx to current upanel of b. cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLPFETCH) // jump to column storage case label(.DROWPFETCH) // row-stored prefetching on c //lea(mem(r12, rdi, 2), rdx) // //lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(r12, 7*8)) // prefetch c + 0*rs_c prefetch(0, mem(r12, rdi, 1, 7*8)) // prefetch c + 1*rs_c prefetch(0, mem(r12, rdi, 2, 7*8)) // prefetch c + 2*rs_c jmp(.DPOSTPFETCH) // jump to end of prefetching c label(.DCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 8), rsi) // cs_c *= sizeof(double) lea(mem(r12, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; prefetch(0, mem(r12, 2*8)) // prefetch c + 0*cs_c prefetch(0, mem(r12, rsi, 1, 2*8)) // prefetch c + 1*cs_c prefetch(0, mem(r12, rsi, 2, 2*8)) // prefetch c + 2*cs_c prefetch(0, mem(rdx, 2*8)) // prefetch c + 3*cs_c prefetch(0, mem(rdx, rsi, 1, 2*8)) // prefetch c + 4*cs_c prefetch(0, mem(rdx, rsi, 2, 2*8)) // prefetch c + 5*cs_c lea(mem(rdx, rsi, 2), rdx) // rdx = c + 5*cs_c; prefetch(0, mem(rdx, rsi, 1, 2*8)) // prefetch c + 6*cs_c prefetch(0, mem(rdx, rsi, 2, 2*8)) // prefetch c + 7*cs_c label(.DPOSTPFETCH) // done prefetching c #if 1 mov(var(ps_b8), rdx) // load ps_b8 lea(mem(rbx, rdx, 1), rdx) // rdx = b + ps_b8 lea(mem(r10, r10, 2), rcx) // rcx = 3*rs_b; // use rcx, rdx for prefetching lines // from next upanel of b. #else lea(mem(rbx, r8, 8), rdx) // use rdx for prefetching lines lea(mem(rdx, r8, 8), rdx) // from next upanel of b. lea(mem(r10, r10, 2), rcx) // rcx = 3*rs_b; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.DLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, 5*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, r10, 1, 5*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) // ---------------------------------- iteration 2 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, r10, 2, 5*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) // ---------------------------------- iteration 3 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, rcx, 1, 5*8)) lea(mem(rdx, r10, 4), rdx) // b_prefetch += 4*rs_b; #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) dec(rsi) // i -= 1; jne(.DLOOPKITER) // iterate again if i != 0. label(.DCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.DLOOPKLEFT) // EDGE LOOP #if 1 prefetch(0, mem(rdx, 5*8)) add(r10, rdx) // b_prefetch += rs_b; #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) dec(rsi) // i -= 1; jne(.DLOOPKLEFT) // iterate again if i != 0. label(.DPOSTACCUM) mov(r12, rcx) // reset rcx to current utile of c. mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(ymm0, ymm5, ymm5) vmulpd(ymm0, ymm6, ymm6) vmulpd(ymm0, ymm7, ymm7) vmulpd(ymm0, ymm8, ymm8) vmulpd(ymm0, ymm9, ymm9) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; lea(mem(rcx, rdi, 2), rdx) // load address of c + 2*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORED) // jump to column storage case label(.DROWSTORED) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm4) vmovupd(ymm4, mem(rcx, 0*32)) vfmadd231pd(mem(rcx, 1*32), ymm3, ymm5) vmovupd(ymm5, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm6) vmovupd(ymm6, mem(rcx, 0*32)) vfmadd231pd(mem(rcx, 1*32), ymm3, ymm7) vmovupd(ymm7, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm8) vmovupd(ymm8, mem(rcx, 0*32)) vfmadd231pd(mem(rcx, 1*32), ymm3, ymm9) vmovupd(ymm9, mem(rcx, 1*32)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORED) // begin I/O on columns 0-3 vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vunpcklpd(ymm10, ymm8, ymm2) vunpckhpd(ymm10, ymm8, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vperm2f128(imm(0x31), ymm2, ymm0, ymm8) vperm2f128(imm(0x31), ymm3, ymm1, ymm10) vextractf128(imm(0x1), ymm4, xmm12) vextractf128(imm(0x1), ymm6, xmm13) vextractf128(imm(0x1), ymm8, xmm14) vextractf128(imm(0x1), ymm10, xmm15) vbroadcastsd(mem(rbx), ymm3) vfmadd231pd(mem(rcx ), xmm3, xmm4) vfmadd231pd(mem(rcx, rsi, 1), xmm3, xmm6) vfmadd231pd(mem(rcx, rsi, 2), xmm3, xmm8) vfmadd231pd(mem(rcx, rax, 1), xmm3, xmm10) vmovupd(xmm4, mem(rcx )) vmovupd(xmm6, mem(rcx, rsi, 1)) vmovupd(xmm8, mem(rcx, rsi, 2)) vmovupd(xmm10, mem(rcx, rax, 1)) lea(mem(rcx, rsi, 4), rcx) vfmadd231sd(mem(rdx ), xmm3, xmm12) vfmadd231sd(mem(rdx, rsi, 1), xmm3, xmm13) vfmadd231sd(mem(rdx, rsi, 2), xmm3, xmm14) vfmadd231sd(mem(rdx, rax, 1), xmm3, xmm15) vmovsd(xmm12, mem(rdx )) vmovsd(xmm13, mem(rdx, rsi, 1)) vmovsd(xmm14, mem(rdx, rsi, 2)) vmovsd(xmm15, mem(rdx, rax, 1)) lea(mem(rdx, rsi, 4), rdx) // begin I/O on columns 4-7 vunpcklpd(ymm7, ymm5, ymm0) vunpckhpd(ymm7, ymm5, ymm1) vunpcklpd(ymm11, ymm9, ymm2) vunpckhpd(ymm11, ymm9, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm5) vinsertf128(imm(0x1), xmm3, ymm1, ymm7) vperm2f128(imm(0x31), ymm2, ymm0, ymm9) vperm2f128(imm(0x31), ymm3, ymm1, ymm11) vextractf128(imm(0x1), ymm5, xmm12) vextractf128(imm(0x1), ymm7, xmm13) vextractf128(imm(0x1), ymm9, xmm14) vextractf128(imm(0x1), ymm11, xmm15) vbroadcastsd(mem(rbx), ymm3) vfmadd231pd(mem(rcx ), xmm3, xmm5) vfmadd231pd(mem(rcx, rsi, 1), xmm3, xmm7) vfmadd231pd(mem(rcx, rsi, 2), xmm3, xmm9) vfmadd231pd(mem(rcx, rax, 1), xmm3, xmm11) vmovupd(xmm5, mem(rcx )) vmovupd(xmm7, mem(rcx, rsi, 1)) vmovupd(xmm9, mem(rcx, rsi, 2)) vmovupd(xmm11, mem(rcx, rax, 1)) //lea(mem(rcx, rsi, 4), rcx) vfmadd231sd(mem(rdx ), xmm3, xmm12) vfmadd231sd(mem(rdx, rsi, 1), xmm3, xmm13) vfmadd231sd(mem(rdx, rsi, 2), xmm3, xmm14) vfmadd231sd(mem(rdx, rax, 1), xmm3, xmm15) vmovsd(xmm12, mem(rdx )) vmovsd(xmm13, mem(rdx, rsi, 1)) vmovsd(xmm14, mem(rdx, rsi, 2)) vmovsd(xmm15, mem(rdx, rax, 1)) //lea(mem(rdx, rsi, 4), rdx) jmp(.DDONE) // jump to end. label(.DBETAZERO) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORBZ) // jump to column storage case label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx, 0*32)) vmovupd(ymm5, mem(rcx, 1*32)) add(rdi, rcx) vmovupd(ymm6, mem(rcx, 0*32)) vmovupd(ymm7, mem(rcx, 1*32)) add(rdi, rcx) vmovupd(ymm8, mem(rcx, 0*32)) vmovupd(ymm9, mem(rcx, 1*32)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORBZ) // begin I/O on columns 0-3 vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vunpcklpd(ymm10, ymm8, ymm2) vunpckhpd(ymm10, ymm8, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vperm2f128(imm(0x31), ymm2, ymm0, ymm8) vperm2f128(imm(0x31), ymm3, ymm1, ymm10) vextractf128(imm(0x1), ymm4, xmm12) vextractf128(imm(0x1), ymm6, xmm13) vextractf128(imm(0x1), ymm8, xmm14) vextractf128(imm(0x1), ymm10, xmm15) vmovupd(xmm4, mem(rcx )) vmovupd(xmm6, mem(rcx, rsi, 1)) vmovupd(xmm8, mem(rcx, rsi, 2)) vmovupd(xmm10, mem(rcx, rax, 1)) lea(mem(rcx, rsi, 4), rcx) vmovsd(xmm12, mem(rdx )) vmovsd(xmm13, mem(rdx, rsi, 1)) vmovsd(xmm14, mem(rdx, rsi, 2)) vmovsd(xmm15, mem(rdx, rax, 1)) lea(mem(rdx, rsi, 4), rdx) // begin I/O on columns 4-7 vunpcklpd(ymm7, ymm5, ymm0) vunpckhpd(ymm7, ymm5, ymm1) vunpcklpd(ymm11, ymm9, ymm2) vunpckhpd(ymm11, ymm9, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm5) vinsertf128(imm(0x1), xmm3, ymm1, ymm7) vperm2f128(imm(0x31), ymm2, ymm0, ymm9) vperm2f128(imm(0x31), ymm3, ymm1, ymm11) vextractf128(imm(0x1), ymm5, xmm12) vextractf128(imm(0x1), ymm7, xmm13) vextractf128(imm(0x1), ymm9, xmm14) vextractf128(imm(0x1), ymm11, xmm15) vmovupd(xmm5, mem(rcx )) vmovupd(xmm7, mem(rcx, rsi, 1)) vmovupd(xmm9, mem(rcx, rsi, 2)) vmovupd(xmm11, mem(rcx, rax, 1)) //lea(mem(rcx, rsi, 4), rcx) vmovsd(xmm12, mem(rdx )) vmovsd(xmm13, mem(rdx, rsi, 1)) vmovsd(xmm14, mem(rdx, rsi, 2)) vmovsd(xmm15, mem(rdx, rax, 1)) //lea(mem(rdx, rsi, 4), rdx) label(.DDONE) lea(mem(r12, rsi, 8), r12) // c_jj = r12 += 8*cs_c //add(imm(8*8), r14) // b_jj = r14 += 8*cs_b mov(var(ps_b8), rbx) // load ps_b8 lea(mem(r14, rbx, 1), r14) // b_jj = r14 += ps_b8 dec(r11) // jj -= 1; jne(.DLOOP4X8J) // iterate again if jj != 0. label(.DRETURN) end_asm( : // output operands (none) : // input operands [n_iter] "m" (n_iter), [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [ps_b8] "m" (ps_b8), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the m dimension, if they exist. if ( n_left ) { const dim_t mr_cur = 3; const dim_t j_edge = n0 - ( dim_t )n_left; double* restrict cij = c + j_edge*cs_c; double* restrict ai = a; //double* restrict bj = b + j_edge*cs_b; //double* restrict bj = b + ( j_edge / 8 ) * ps_b; double* restrict bj = b + n_iter * ps_b; if ( 6 <= n_left ) { const dim_t nr_cur = 6; bli_dgemmsup_rv_haswell_asm_3x6 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 4 <= n_left ) { const dim_t nr_cur = 4; bli_dgemmsup_rv_haswell_asm_3x4 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 2 <= n_left ) { const dim_t nr_cur = 2; bli_dgemmsup_rv_haswell_asm_3x2 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 1 == n_left ) { const dim_t nr_cur = 1; bli_dgemmsup_r_haswell_ref_3x1 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); } } } void bli_dgemmsup_rv_haswell_asm_2x8n ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t n_iter = n0 / 8; uint64_t n_left = n0 % 8; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // Query the panel stride of B and convert it to units of bytes. uint64_t ps_b = bli_auxinfo_ps_b( data ); uint64_t ps_b8 = ps_b * sizeof( double ); if ( n_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. //mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), r14) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) //lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) // During preamble and loops: // r12 = rcx = c // r14 = rbx = b // read rax from var(a) near beginning of loop // r11 = m dim index ii mov(var(n_iter), r11) // jj = n_iter; label(.DLOOP2X8J) // LOOP OVER jj = [ n_iter ... 1 0 ] #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm5, ymm5, ymm5) vxorpd(ymm6, ymm6, ymm6) vxorpd(ymm7, ymm7, ymm7) #endif mov(var(a), rax) // load address of a. //mov(r12, rcx) // reset rcx to current utile of c. mov(r14, rbx) // reset rbx to current upanel of b. cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLPFETCH) // jump to column storage case label(.DROWPFETCH) // row-stored prefetching on c //lea(mem(r12, rdi, 2), rdx) // //lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(r12, 7*8)) // prefetch c + 0*rs_c prefetch(0, mem(r12, rdi, 1, 7*8)) // prefetch c + 1*rs_c jmp(.DPOSTPFETCH) // jump to end of prefetching c label(.DCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 8), rsi) // cs_c *= sizeof(double) lea(mem(r12, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; prefetch(0, mem(r12, 1*8)) // prefetch c + 0*cs_c prefetch(0, mem(r12, rsi, 1, 1*8)) // prefetch c + 1*cs_c prefetch(0, mem(r12, rsi, 2, 1*8)) // prefetch c + 2*cs_c prefetch(0, mem(rdx, 1*8)) // prefetch c + 3*cs_c prefetch(0, mem(rdx, rsi, 1, 1*8)) // prefetch c + 4*cs_c prefetch(0, mem(rdx, rsi, 2, 1*8)) // prefetch c + 5*cs_c lea(mem(rdx, rsi, 2), rdx) // rdx = c + 5*cs_c; prefetch(0, mem(rdx, rsi, 1, 1*8)) // prefetch c + 6*cs_c prefetch(0, mem(rdx, rsi, 2, 1*8)) // prefetch c + 7*cs_c label(.DPOSTPFETCH) // done prefetching c #if 1 mov(var(ps_b8), rdx) // load ps_b8 lea(mem(rbx, rdx, 1), rdx) // rdx = b + ps_b8 lea(mem(r10, r10, 2), rcx) // rcx = 3*rs_b; // use rcx, rdx for prefetching lines // from next upanel of b. #else lea(mem(rbx, r8, 8), rdx) // use rdx for prefetching lines lea(mem(rdx, r8, 8), rdx) // from next upanel of b. lea(mem(r10, r10, 2), rcx) // rcx = 3*rs_b; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.DLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, 5*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, r10, 1, 5*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) // ---------------------------------- iteration 2 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, r10, 2, 5*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) // ---------------------------------- iteration 3 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, rcx, 1, 5*8)) lea(mem(rdx, r10, 4), rdx) // b_prefetch += 4*rs_b; #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) dec(rsi) // i -= 1; jne(.DLOOPKITER) // iterate again if i != 0. label(.DCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.DLOOPKLEFT) // EDGE LOOP #if 1 prefetch(0, mem(rdx, 5*8)) add(r10, rdx) // b_prefetch += rs_b; #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) dec(rsi) // i -= 1; jne(.DLOOPKLEFT) // iterate again if i != 0. label(.DPOSTACCUM) mov(r12, rcx) // reset rcx to current utile of c. mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(ymm0, ymm5, ymm5) vmulpd(ymm0, ymm6, ymm6) vmulpd(ymm0, ymm7, ymm7) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; //lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORED) // jump to column storage case label(.DROWSTORED) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm4) vmovupd(ymm4, mem(rcx, 0*32)) vfmadd231pd(mem(rcx, 1*32), ymm3, ymm5) vmovupd(ymm5, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm6) vmovupd(ymm6, mem(rcx, 0*32)) vfmadd231pd(mem(rcx, 1*32), ymm3, ymm7) vmovupd(ymm7, mem(rcx, 1*32)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORED) // begin I/O on columns 0-3 vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vextractf128(imm(0x1), ymm1, xmm4) vfmadd231pd(mem(rcx ), xmm3, xmm0) vfmadd231pd(mem(rcx, rsi, 1), xmm3, xmm1) vfmadd231pd(mem(rcx, rsi, 2), xmm3, xmm2) vfmadd231pd(mem(rcx, rax, 1), xmm3, xmm4) vmovupd(xmm0, mem(rcx )) vmovupd(xmm1, mem(rcx, rsi, 1)) vmovupd(xmm2, mem(rcx, rsi, 2)) vmovupd(xmm4, mem(rcx, rax, 1)) lea(mem(rcx, rsi, 4), rcx) // begin I/O on columns 4-7 vunpcklpd(ymm7, ymm5, ymm0) vunpckhpd(ymm7, ymm5, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vextractf128(imm(0x1), ymm1, xmm4) vfmadd231pd(mem(rcx ), xmm3, xmm0) vfmadd231pd(mem(rcx, rsi, 1), xmm3, xmm1) vfmadd231pd(mem(rcx, rsi, 2), xmm3, xmm2) vfmadd231pd(mem(rcx, rax, 1), xmm3, xmm4) vmovupd(xmm0, mem(rcx )) vmovupd(xmm1, mem(rcx, rsi, 1)) vmovupd(xmm2, mem(rcx, rsi, 2)) vmovupd(xmm4, mem(rcx, rax, 1)) //lea(mem(rcx, rsi, 4), rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORBZ) // jump to column storage case label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx, 0*32)) vmovupd(ymm5, mem(rcx, 1*32)) add(rdi, rcx) vmovupd(ymm6, mem(rcx, 0*32)) vmovupd(ymm7, mem(rcx, 1*32)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORBZ) // begin I/O on columns 0-3 vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vextractf128(imm(0x1), ymm1, xmm4) vmovupd(xmm0, mem(rcx )) vmovupd(xmm1, mem(rcx, rsi, 1)) vmovupd(xmm2, mem(rcx, rsi, 2)) vmovupd(xmm4, mem(rcx, rax, 1)) lea(mem(rcx, rsi, 4), rcx) // begin I/O on columns 4-7 vunpcklpd(ymm7, ymm5, ymm0) vunpckhpd(ymm7, ymm5, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vextractf128(imm(0x1), ymm1, xmm4) vmovupd(xmm0, mem(rcx )) vmovupd(xmm1, mem(rcx, rsi, 1)) vmovupd(xmm2, mem(rcx, rsi, 2)) vmovupd(xmm4, mem(rcx, rax, 1)) //lea(mem(rcx, rsi, 4), rcx) label(.DDONE) lea(mem(r12, rsi, 8), r12) // c_jj = r12 += 8*cs_c //add(imm(8*8), r14) // b_jj = r14 += 8*cs_b mov(var(ps_b8), rbx) // load ps_b8 lea(mem(r14, rbx, 1), r14) // b_jj = r14 += ps_b8 dec(r11) // jj -= 1; jne(.DLOOP2X8J) // iterate again if jj != 0. label(.DRETURN) end_asm( : // output operands (none) : // input operands [n_iter] "m" (n_iter), [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [ps_b8] "m" (ps_b8), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the m dimension, if they exist. if ( n_left ) { const dim_t mr_cur = 2; const dim_t j_edge = n0 - ( dim_t )n_left; double* restrict cij = c + j_edge*cs_c; double* restrict ai = a; //double* restrict bj = b + j_edge*cs_b; //double* restrict bj = b + ( j_edge / 8 ) * ps_b; double* restrict bj = b + n_iter * ps_b; if ( 6 <= n_left ) { const dim_t nr_cur = 6; bli_dgemmsup_rv_haswell_asm_2x6 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 4 <= n_left ) { const dim_t nr_cur = 4; bli_dgemmsup_rv_haswell_asm_2x4 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 2 <= n_left ) { const dim_t nr_cur = 2; bli_dgemmsup_rv_haswell_asm_2x2 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 1 == n_left ) { const dim_t nr_cur = 1; bli_dgemmsup_r_haswell_ref_2x1 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); } } } void bli_dgemmsup_rv_haswell_asm_1x8n ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t n_iter = n0 / 8; uint64_t n_left = n0 % 8; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // Query the panel stride of B and convert it to units of bytes. uint64_t ps_b = bli_auxinfo_ps_b( data ); uint64_t ps_b8 = ps_b * sizeof( double ); if ( n_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. //mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), r14) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) //lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) // During preamble and loops: // r12 = rcx = c // r14 = rbx = b // read rax from var(a) near beginning of loop // r11 = m dim index ii mov(var(n_iter), r11) // jj = n_iter; label(.DLOOP1X8J) // LOOP OVER jj = [ n_iter ... 1 0 ] #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm5, ymm5, ymm5) #endif mov(var(a), rax) // load address of a. //mov(r12, rcx) // reset rcx to current utile of c. mov(r14, rbx) // reset rbx to current upanel of b. cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLPFETCH) // jump to column storage case label(.DROWPFETCH) // row-stored prefetching on c //lea(mem(r12, rdi, 2), rdx) // //lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(r12, 7*8)) // prefetch c + 0*rs_c jmp(.DPOSTPFETCH) // jump to end of prefetching c label(.DCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 8), rsi) // cs_c *= sizeof(double) lea(mem(r12, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; prefetch(0, mem(r12, 0*8)) // prefetch c + 0*cs_c prefetch(0, mem(r12, rsi, 1, 0*8)) // prefetch c + 1*cs_c prefetch(0, mem(r12, rsi, 2, 0*8)) // prefetch c + 2*cs_c prefetch(0, mem(rdx, 0*8)) // prefetch c + 3*cs_c prefetch(0, mem(rdx, rsi, 1, 0*8)) // prefetch c + 4*cs_c prefetch(0, mem(rdx, rsi, 2, 0*8)) // prefetch c + 5*cs_c lea(mem(rdx, rsi, 2), rdx) // rdx = c + 5*cs_c; prefetch(0, mem(rdx, rsi, 1, 0*8)) // prefetch c + 6*cs_c prefetch(0, mem(rdx, rsi, 2, 0*8)) // prefetch c + 7*cs_c label(.DPOSTPFETCH) // done prefetching c #if 1 mov(var(ps_b8), rdx) // load ps_b8 lea(mem(rbx, rdx, 1), rdx) // rdx = b + ps_b8 lea(mem(r10, r10, 2), rcx) // rcx = 3*rs_b; // use rcx, rdx for prefetching lines // from next upanel of b. #else lea(mem(rbx, r8, 8), rdx) // use rdx for prefetching lines lea(mem(rdx, r8, 8), rdx) // from next upanel of b. lea(mem(r10, r10, 2), rcx) // rcx = 3*rs_b; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.DLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, 5*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) // ---------------------------------- iteration 1 #if 1 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, r10, 1, 5*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, r10, 2, 5*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) // ---------------------------------- iteration 3 #if 1 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, rcx, 1, 5*8)) lea(mem(rdx, r10, 4), rdx) // b_prefetch += 4*rs_b; #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) dec(rsi) // i -= 1; jne(.DLOOPKITER) // iterate again if i != 0. label(.DCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.DLOOPKLEFT) // EDGE LOOP #if 1 prefetch(0, mem(rdx, 5*8)) add(r10, rdx) // b_prefetch += rs_b; #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) dec(rsi) // i -= 1; jne(.DLOOPKLEFT) // iterate again if i != 0. label(.DPOSTACCUM) mov(r12, rcx) // reset rcx to current utile of c. mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(ymm0, ymm5, ymm5) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; //lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORED) // jump to column storage case label(.DROWSTORED) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm4) vmovupd(ymm4, mem(rcx, 0*32)) vfmadd231pd(mem(rcx, 1*32), ymm3, ymm5) vmovupd(ymm5, mem(rcx, 1*32)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORED) // begin I/O on columns 0-3 vmovlpd(mem(rcx ), xmm0, xmm0) vmovhpd(mem(rcx, rsi, 1), xmm0, xmm0) vmovlpd(mem(rcx, rsi, 2), xmm1, xmm1) vmovhpd(mem(rcx, rax, 1), xmm1, xmm1) vperm2f128(imm(0x20), ymm1, ymm0, ymm0) vfmadd213pd(ymm4, ymm3, ymm0) vextractf128(imm(1), ymm0, xmm1) vmovlpd(xmm0, mem(rcx )) vmovhpd(xmm0, mem(rcx, rsi, 1)) vmovlpd(xmm1, mem(rcx, rsi, 2)) vmovhpd(xmm1, mem(rcx, rax, 1)) lea(mem(rcx, rsi, 4), rcx) // begin I/O on columns 4-7 vmovlpd(mem(rcx ), xmm0, xmm0) vmovhpd(mem(rcx, rsi, 1), xmm0, xmm0) vmovlpd(mem(rcx, rsi, 2), xmm1, xmm1) vmovhpd(mem(rcx, rax, 1), xmm1, xmm1) vperm2f128(imm(0x20), ymm1, ymm0, ymm0) vfmadd213pd(ymm5, ymm3, ymm0) vextractf128(imm(1), ymm0, xmm1) vmovlpd(xmm0, mem(rcx )) vmovhpd(xmm0, mem(rcx, rsi, 1)) vmovlpd(xmm1, mem(rcx, rsi, 2)) vmovhpd(xmm1, mem(rcx, rax, 1)) //lea(mem(rcx, rsi, 4), rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORBZ) // jump to column storage case label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx, 0*32)) vmovupd(ymm5, mem(rcx, 1*32)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORBZ) // begin I/O on columns 0-3 vmovupd(ymm4, ymm0) vextractf128(imm(1), ymm0, xmm1) vmovlpd(xmm0, mem(rcx )) vmovhpd(xmm0, mem(rcx, rsi, 1)) vmovlpd(xmm1, mem(rcx, rsi, 2)) vmovhpd(xmm1, mem(rcx, rax, 1)) lea(mem(rcx, rsi, 4), rcx) // begin I/O on columns 4-7 vmovupd(ymm5, ymm0) vextractf128(imm(1), ymm0, xmm1) vmovlpd(xmm0, mem(rcx )) vmovhpd(xmm0, mem(rcx, rsi, 1)) vmovlpd(xmm1, mem(rcx, rsi, 2)) vmovhpd(xmm1, mem(rcx, rax, 1)) //lea(mem(rcx, rsi, 4), rcx) label(.DDONE) lea(mem(r12, rsi, 8), r12) // c_jj = r12 += 8*cs_c //add(imm(8*8), r14) // b_jj = r14 += 8*cs_b mov(var(ps_b8), rbx) // load ps_b8 lea(mem(r14, rbx, 1), r14) // b_jj = r14 += ps_b8 dec(r11) // jj -= 1; jne(.DLOOP1X8J) // iterate again if jj != 0. label(.DRETURN) end_asm( : // output operands (none) : // input operands [n_iter] "m" (n_iter), [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [ps_b8] "m" (ps_b8), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the m dimension, if they exist. if ( n_left ) { const dim_t mr_cur = 1; const dim_t j_edge = n0 - ( dim_t )n_left; double* restrict cij = c + j_edge*cs_c; double* restrict ai = a; //double* restrict bj = b + j_edge*cs_b; //double* restrict bj = b + ( j_edge / 8 ) * ps_b; double* restrict bj = b + n_iter * ps_b; if ( 6 <= n_left ) { const dim_t nr_cur = 6; bli_dgemmsup_rv_haswell_asm_1x6 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 4 <= n_left ) { const dim_t nr_cur = 4; bli_dgemmsup_rv_haswell_asm_1x4 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 2 <= n_left ) { const dim_t nr_cur = 2; bli_dgemmsup_rv_haswell_asm_1x2 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 1 == n_left ) { #if 1 const dim_t nr_cur = 1; bli_dgemmsup_r_haswell_ref_1x1 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); #else bli_ddotxv_ex ( conja, conjb, k0, alpha, ai, cs_a0, bj, rs_b0, beta, cij, cntx, NULL ); #endif } } } blis-0.9.0/kernels/haswell/3/sup/bli_gemmsup_rv_haswell_asm_s6x16m.c000066400000000000000000004101631422157504600254200ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define BLIS_ASM_SYNTAX_ATT #include "bli_x86_asm_macros.h" /* rrr: -------- ------ -------- -------- ------ -------- -------- += ------ ... -------- -------- ------ -------- -------- ------ : -------- ------ : rcr: -------- | | | | -------- -------- | | | | -------- -------- += | | | | ... -------- -------- | | | | -------- -------- | | | | : -------- | | | | : Assumptions: - B is row-stored; - A is row- or column-stored; - m0 and n0 are at most MR and NR, respectively. Therefore, this (r)ow-preferential kernel is well-suited for contiguous (v)ector loads on B and single-element broadcasts from A. NOTE: These kernels explicitly support column-oriented IO, implemented via an in-register transpose. And thus they also support the crr and ccr cases, though only crr is ever utilized (because ccr is handled by transposing the operation and executing rcr, which does not incur the cost of the in-register transpose). crr: | | | | | | | | ------ -------- | | | | | | | | ------ -------- | | | | | | | | += ------ ... -------- | | | | | | | | ------ -------- | | | | | | | | ------ : | | | | | | | | ------ : */ // Prototype reference microkernels. GEMMSUP_KER_PROT( float, s, gemmsup_r_haswell_ref ) void bli_sgemmsup_rv_haswell_asm_6x16m ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { uint64_t n_left = n0 % 16; // First check whether this is a edge case in the n dimension. If so, // dispatch other 6x?m kernels, as needed. if ( n_left ) { float* restrict cij = c; float* restrict bj = b; float* restrict ai = a; if ( 12 <= n_left ) { const dim_t nr_cur = 12; bli_sgemmsup_rv_haswell_asm_6x12m ( conja, conjb, m0, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 8 <= n_left ) { const dim_t nr_cur = 8; bli_sgemmsup_rv_haswell_asm_6x8m ( conja, conjb, m0, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 6 <= n_left ) { const dim_t nr_cur = 6; bli_sgemmsup_rv_haswell_asm_6x6m ( conja, conjb, m0, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 4 <= n_left ) { const dim_t nr_cur = 4; bli_sgemmsup_rv_haswell_asm_6x4m ( conja, conjb, m0, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 2 <= n_left ) { const dim_t nr_cur = 2; bli_sgemmsup_rv_haswell_asm_6x2m ( conja, conjb, m0, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 1 == n_left ) { #if 0 const dim_t nr_cur = 1; bli_sgemmsup_r_haswell_ref ( conja, conjb, m0, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); #else dim_t ps_a0 = bli_auxinfo_ps_a( data ); if ( ps_a0 == 6 * rs_a0 ) { // Since A is not packed, we can use one gemv. bli_sgemv_ex ( BLIS_NO_TRANSPOSE, conjb, m0, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, beta, cij, rs_c0, cntx, NULL ); } else { const dim_t mr = 6; // Since A is packed into row panels, we must use a loop over // gemv. dim_t m_iter = ( m0 + mr - 1 ) / mr; dim_t m_left = m0 % mr; float* restrict ai_ii = ai; float* restrict cij_ii = cij; for ( dim_t ii = 0; ii < m_iter; ii += 1 ) { dim_t mr_cur = ( bli_is_not_edge_f( ii, m_iter, m_left ) ? mr : m_left ); bli_sgemv_ex ( BLIS_NO_TRANSPOSE, conjb, mr_cur, k0, alpha, ai_ii, rs_a0, cs_a0, bj, rs_b0, beta, cij_ii, rs_c0, cntx, NULL ); cij_ii += mr*rs_c0; ai_ii += ps_a0; } } } return; #endif } //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t m_iter = m0 / 6; uint64_t m_left = m0 % 6; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // Query the panel stride of A and convert it to units of bytes. uint64_t ps_a = bli_auxinfo_ps_a( data ); uint64_t ps_a4 = ps_a * sizeof( float ); if ( m_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), r14) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a //mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) //lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) // During preamble and loops: // r12 = rcx = c // r14 = rax = a // read rbx from var(b) near beginning of loop // r11 = m dim index ii mov(var(m_iter), r11) // ii = m_iter; label(.SLOOP6X8I) // LOOP OVER ii = [ m_iter ... 1 0 ] #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorps ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorps(ymm4, ymm4, ymm4) vxorps(ymm5, ymm5, ymm5) vxorps(ymm6, ymm6, ymm6) vxorps(ymm7, ymm7, ymm7) vxorps(ymm8, ymm8, ymm8) vxorps(ymm9, ymm9, ymm9) vxorps(ymm10, ymm10, ymm10) vxorps(ymm11, ymm11, ymm11) vxorps(ymm12, ymm12, ymm12) vxorps(ymm13, ymm13, ymm13) vxorps(ymm14, ymm14, ymm14) vxorps(ymm15, ymm15, ymm15) #endif mov(var(b), rbx) // load address of b. //mov(r12, rcx) // reset rcx to current utile of c. mov(r14, rax) // reset rax to current upanel of a. cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored prefetching on c lea(mem(r12, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(r12, 15*4)) // prefetch c + 0*rs_c prefetch(0, mem(r12, rdi, 1,15*4)) // prefetch c + 1*rs_c prefetch(0, mem(r12, rdi, 2,15*4)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 15*4)) // prefetch c + 3*rs_c prefetch(0, mem(rdx, rdi, 1,15*4)) // prefetch c + 4*rs_c prefetch(0, mem(rdx, rdi, 2,15*4)) // prefetch c + 5*rs_c jmp(.SPOSTPFETCH) // jump to end of prefetching c label(.SCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) lea(mem(rsi, rsi, 2), rcx) // rcx = 3*cs_c; prefetch(0, mem(r12, 5*4)) // prefetch c + 0*cs_c prefetch(0, mem(r12, rsi, 1, 5*4)) // prefetch c + 1*cs_c prefetch(0, mem(r12, rsi, 2, 5*4)) // prefetch c + 2*cs_c prefetch(0, mem(r12, rcx, 1, 5*4)) // prefetch c + 3*cs_c prefetch(0, mem(r12, rsi, 4, 5*4)) // prefetch c + 4*cs_c lea(mem(r12, rsi, 4), rdx) // rdx = c + 4*cs_c; prefetch(0, mem(rdx, rsi, 1, 5*4)) // prefetch c + 5*cs_c prefetch(0, mem(rdx, rsi, 2, 5*4)) // prefetch c + 6*cs_c prefetch(0, mem(rdx, rcx, 1, 5*4)) // prefetch c + 7*cs_c prefetch(0, mem(rdx, rsi, 4, 5*4)) // prefetch c + 8*cs_c lea(mem(r12, rsi, 8), rdx) // rdx = c + 8*cs_c; prefetch(0, mem(rdx, rsi, 1, 5*4)) // prefetch c + 9*cs_c prefetch(0, mem(rdx, rsi, 2, 5*4)) // prefetch c + 10*cs_c prefetch(0, mem(rdx, rcx, 1, 5*4)) // prefetch c + 11*cs_c prefetch(0, mem(rdx, rsi, 4, 5*4)) // prefetch c + 12*cs_c lea(mem(r12, rcx, 4), rdx) // rdx = c + 12*cs_c; prefetch(0, mem(rdx, rsi, 1, 5*4)) // prefetch c + 13*cs_c prefetch(0, mem(rdx, rsi, 2, 5*4)) // prefetch c + 14*cs_c prefetch(0, mem(rdx, rcx, 1, 5*4)) // prefetch c + 15*cs_c label(.SPOSTPFETCH) // done prefetching c #if 1 mov(var(ps_a4), rdx) // load ps_a4 lea(mem(rax, rdx, 1), rdx) // rdx = a + ps_a4 lea(mem(r9, r9, 2), rcx) // rcx = 3*cs_a; // use rcx, rdx for prefetching lines // from next upanel of a. #else lea(mem(rax, r8, 4), rdx) // use rdx for prefetching lines lea(mem(rdx, r8, 2), rdx) // from next upanel of a. lea(mem(r9, r9, 2), rcx) // rcx = 3*cs_a; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, 5*8)) #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, r8, 4), ymm2) vbroadcastss(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, r9, 1, 5*8)) #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, r8, 4), ymm2) vbroadcastss(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) // ---------------------------------- iteration 2 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, r9, 2, 5*8)) #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, r8, 4), ymm2) vbroadcastss(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) // ---------------------------------- iteration 3 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, rcx, 1, 5*8)) lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, r8, 4), ymm2) vbroadcastss(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP #if 1 prefetch(0, mem(rdx, 5*8)) add(r9, rdx) #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, r8, 4), ymm2) vbroadcastss(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(r12, rcx) // reset rcx to current utile of c. mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), ymm0) // load alpha and duplicate vbroadcastss(mem(rbx), ymm3) // load beta and duplicate vmulps(ymm0, ymm4, ymm4) // scale by alpha vmulps(ymm0, ymm5, ymm5) vmulps(ymm0, ymm6, ymm6) vmulps(ymm0, ymm7, ymm7) vmulps(ymm0, ymm8, ymm8) vmulps(ymm0, ymm9, ymm9) vmulps(ymm0, ymm10, ymm10) vmulps(ymm0, ymm11, ymm11) vmulps(ymm0, ymm12, ymm12) vmulps(ymm0, ymm13, ymm13) vmulps(ymm0, ymm14, ymm14) vmulps(ymm0, ymm15, ymm15) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; lea(mem(rsi, rsi, 4), rbx) // rbx = 5*cs_c; lea(mem(rax, rsi, 4), rbp) // rbp = 7*cs_c; // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm4) vmovups(ymm4, mem(rcx, 0*32)) vfmadd231ps(mem(rcx, 1*32), ymm3, ymm5) vmovups(ymm5, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm6) vmovups(ymm6, mem(rcx, 0*32)) vfmadd231ps(mem(rcx, 1*32), ymm3, ymm7) vmovups(ymm7, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm8) vmovups(ymm8, mem(rcx, 0*32)) vfmadd231ps(mem(rcx, 1*32), ymm3, ymm9) vmovups(ymm9, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm10) vmovups(ymm10, mem(rcx, 0*32)) vfmadd231ps(mem(rcx, 1*32), ymm3, ymm11) vmovups(ymm11, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm12) vmovups(ymm12, mem(rcx, 0*32)) vfmadd231ps(mem(rcx, 1*32), ymm3, ymm13) vmovups(ymm13, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm14) vmovups(ymm14, mem(rcx, 0*32)) vfmadd231ps(mem(rcx, 1*32), ymm3, ymm15) vmovups(ymm15, mem(rcx, 1*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORED) // begin I/O on columns 0-7 vunpcklps(ymm6, ymm4, ymm0) vunpcklps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx ), xmm3, xmm0) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm0, mem(rcx )) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx, rsi, 1), xmm3, xmm1) vfmadd231ps(mem(rcx, rbx, 1), xmm3, xmm2) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rbx, 1)) // store ( gamma05..gamma35 ) vunpckhps(ymm6, ymm4, ymm0) vunpckhps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx, rsi, 2), xmm3, xmm0) vfmadd231ps(mem(rcx, rax, 2), xmm3, xmm2) vmovups(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, rax, 2)) // store ( gamma06..gamma36 ) vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx, rax, 1), xmm3, xmm1) vfmadd231ps(mem(rcx, rbp, 1), xmm3, xmm2) vmovups(xmm1, mem(rcx, rax, 1)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, rbp, 1)) // store ( gamma07..gamma37 ) lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vunpcklps(ymm14, ymm12, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(mem(rdx ), xmm1, xmm1) vmovhpd(mem(rdx, rsi, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(rdx )) // store ( gamma40..gamma50 ) vmovhpd(xmm0, mem(rdx, rsi, 1)) // store ( gamma41..gamma51 ) vmovlpd(mem(rdx, rsi, 4), xmm1, xmm1) vmovhpd(mem(rdx, rbx, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm2) vmovlpd(xmm2, mem(rdx, rsi, 4)) // store ( gamma44..gamma54 ) vmovhpd(xmm2, mem(rdx, rbx, 1)) // store ( gamma45..gamma55 ) vunpckhps(ymm14, ymm12, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(mem(rdx, rsi, 2), xmm1, xmm1) vmovhpd(mem(rdx, rax, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(rdx, rsi, 2)) // store ( gamma42..gamma52 ) vmovhpd(xmm0, mem(rdx, rax, 1)) // store ( gamma43..gamma53 ) vmovlpd(mem(rdx, rax, 2), xmm1, xmm1) vmovhpd(mem(rdx, rbp, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm2) vmovlpd(xmm2, mem(rdx, rax, 2)) // store ( gamma46..gamma56 ) vmovhpd(xmm2, mem(rdx, rbp, 1)) // store ( gamma47..gamma57 ) lea(mem(rdx, rsi, 8), rdx) // rdx += 8*cs_c // begin I/O on columns 8-15 vunpcklps(ymm7, ymm5, ymm0) vunpcklps(ymm11, ymm9, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx ), xmm3, xmm0) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm0, mem(rcx )) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx, rsi, 1), xmm3, xmm1) vfmadd231ps(mem(rcx, rbx, 1), xmm3, xmm2) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rbx, 1)) // store ( gamma05..gamma35 ) vunpckhps(ymm7, ymm5, ymm0) vunpckhps(ymm11, ymm9, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx, rsi, 2), xmm3, xmm0) vfmadd231ps(mem(rcx, rax, 2), xmm3, xmm2) vmovups(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, rax, 2)) // store ( gamma06..gamma36 ) vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx, rax, 1), xmm3, xmm1) vfmadd231ps(mem(rcx, rbp, 1), xmm3, xmm2) vmovups(xmm1, mem(rcx, rax, 1)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, rbp, 1)) // store ( gamma07..gamma37 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vunpcklps(ymm15, ymm13, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(mem(rdx ), xmm1, xmm1) vmovhpd(mem(rdx, rsi, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(rdx )) // store ( gamma40..gamma50 ) vmovhpd(xmm0, mem(rdx, rsi, 1)) // store ( gamma41..gamma51 ) vmovlpd(mem(rdx, rsi, 4), xmm1, xmm1) vmovhpd(mem(rdx, rbx, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm2) vmovlpd(xmm2, mem(rdx, rsi, 4)) // store ( gamma44..gamma54 ) vmovhpd(xmm2, mem(rdx, rbx, 1)) // store ( gamma45..gamma55 ) vunpckhps(ymm15, ymm13, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(mem(rdx, rsi, 2), xmm1, xmm1) vmovhpd(mem(rdx, rax, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(rdx, rsi, 2)) // store ( gamma42..gamma52 ) vmovhpd(xmm0, mem(rdx, rax, 1)) // store ( gamma43..gamma53 ) vmovlpd(mem(rdx, rax, 2), xmm1, xmm1) vmovhpd(mem(rdx, rbp, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm2) vmovlpd(xmm2, mem(rdx, rax, 2)) // store ( gamma46..gamma56 ) vmovhpd(xmm2, mem(rdx, rbp, 1)) // store ( gamma47..gamma57 ) //lea(mem(rdx, rsi, 8), rdx) // rdx += 8*cs_c jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovups(ymm4, mem(rcx, 0*32)) vmovups(ymm5, mem(rcx, 1*32)) add(rdi, rcx) vmovups(ymm6, mem(rcx, 0*32)) vmovups(ymm7, mem(rcx, 1*32)) add(rdi, rcx) vmovups(ymm8, mem(rcx, 0*32)) vmovups(ymm9, mem(rcx, 1*32)) add(rdi, rcx) vmovups(ymm10, mem(rcx, 0*32)) vmovups(ymm11, mem(rcx, 1*32)) add(rdi, rcx) vmovups(ymm12, mem(rcx, 0*32)) vmovups(ymm13, mem(rcx, 1*32)) add(rdi, rcx) vmovups(ymm14, mem(rcx, 0*32)) vmovups(ymm15, mem(rcx, 1*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) // begin I/O on columns 0-7 vunpcklps(ymm6, ymm4, ymm0) vunpcklps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx )) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rbx, 1)) // store ( gamma05..gamma35 ) vunpckhps(ymm6, ymm4, ymm0) vunpckhps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, rax, 2)) // store ( gamma06..gamma36 ) vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx, rax, 1)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, rbp, 1)) // store ( gamma07..gamma37 ) lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vunpcklps(ymm14, ymm12, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(xmm0, mem(rdx )) // store ( gamma40..gamma50 ) vmovhpd(xmm0, mem(rdx, rsi, 1)) // store ( gamma41..gamma51 ) vmovlpd(xmm2, mem(rdx, rsi, 4)) // store ( gamma44..gamma54 ) vmovhpd(xmm2, mem(rdx, rbx, 1)) // store ( gamma45..gamma55 ) vunpckhps(ymm14, ymm12, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(xmm0, mem(rdx, rsi, 2)) // store ( gamma42..gamma52 ) vmovhpd(xmm0, mem(rdx, rax, 1)) // store ( gamma43..gamma53 ) vmovlpd(xmm2, mem(rdx, rax, 2)) // store ( gamma46..gamma56 ) vmovhpd(xmm2, mem(rdx, rbp, 1)) // store ( gamma47..gamma57 ) lea(mem(rdx, rsi, 8), rdx) // rdx += 8*cs_c // begin I/O on columns 8-15 vunpcklps(ymm7, ymm5, ymm0) vunpcklps(ymm11, ymm9, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx )) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rbx, 1)) // store ( gamma05..gamma35 ) vunpckhps(ymm7, ymm5, ymm0) vunpckhps(ymm11, ymm9, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, rax, 2)) // store ( gamma06..gamma36 ) vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx, rax, 1)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, rbp, 1)) // store ( gamma07..gamma37 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vunpcklps(ymm15, ymm13, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(xmm0, mem(rdx )) // store ( gamma40..gamma50 ) vmovhpd(xmm0, mem(rdx, rsi, 1)) // store ( gamma41..gamma51 ) vmovlpd(xmm2, mem(rdx, rsi, 4)) // store ( gamma44..gamma54 ) vmovhpd(xmm2, mem(rdx, rbx, 1)) // store ( gamma45..gamma55 ) vunpckhps(ymm15, ymm13, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(xmm0, mem(rdx, rsi, 2)) // store ( gamma42..gamma52 ) vmovhpd(xmm0, mem(rdx, rax, 1)) // store ( gamma43..gamma53 ) vmovlpd(xmm2, mem(rdx, rax, 2)) // store ( gamma46..gamma56 ) vmovhpd(xmm2, mem(rdx, rbp, 1)) // store ( gamma47..gamma57 ) //lea(mem(rdx, rsi, 8), rdx) // rdx += 8*cs_c label(.SDONE) lea(mem(r12, rdi, 4), r12) // lea(mem(r12, rdi, 2), r12) // c_ii = r12 += 6*rs_c //lea(mem(r14, r8, 4), r14) // //lea(mem(r14, r8, 2), r14) // a_ii = r14 += 6*rs_a mov(var(ps_a4), rax) // load ps_a4 lea(mem(r14, rax, 1), r14) // a_ii = r14 += ps_a4 dec(r11) // ii -= 1; jne(.SLOOP6X8I) // iterate again if ii != 0. label(.SRETURN) end_asm( : // output operands (none) : // input operands [m_iter] "m" (m_iter), [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [ps_a4] "m" (ps_a4), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the m dimension, if they exist. if ( m_left ) { const dim_t nr_cur = 16; const dim_t i_edge = m0 - ( dim_t )m_left; float* restrict cij = c + i_edge*rs_c; //float* restrict ai = a + i_edge*rs_a; //float* restrict ai = a + ( i_edge / 6 ) * ps_a; float* restrict ai = a + m_iter * ps_a; float* restrict bj = b; #if 0 // We add special handling for slightly inflated MR blocksizes // at edge cases, up to a maximum of 9. if ( 6 < m_left ) { sgemmsup_ker_ft ker_fp1 = NULL; sgemmsup_ker_ft ker_fp2 = NULL; dim_t mr1, mr2; if ( m_left == 7 ) { mr1 = 4; mr2 = 3; ker_fp1 = bli_sgemmsup_rv_haswell_asm_4x16; ker_fp2 = bli_sgemmsup_rv_haswell_asm_3x16; } else if ( m_left == 8 ) { mr1 = 4; mr2 = 4; ker_fp1 = bli_sgemmsup_rv_haswell_asm_4x16; ker_fp2 = bli_sgemmsup_rv_haswell_asm_4x16; } else // if ( m_left == 9 ) { mr1 = 4; mr2 = 5; ker_fp1 = bli_sgemmsup_rv_haswell_asm_4x16; ker_fp2 = bli_sgemmsup_rv_haswell_asm_5x16; } ker_fp1 ( conja, conjb, mr1, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += mr1*rs_c0; ai += mr1*rs_a0; ker_fp2 ( conja, conjb, mr2, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); return; } #endif sgemmsup_ker_ft ker_fps[6] = { NULL, bli_sgemmsup_rv_haswell_asm_1x16, bli_sgemmsup_rv_haswell_asm_2x16, bli_sgemmsup_rv_haswell_asm_3x16, bli_sgemmsup_rv_haswell_asm_4x16, bli_sgemmsup_rv_haswell_asm_5x16 }; sgemmsup_ker_ft ker_fp = ker_fps[ m_left ]; ker_fp ( conja, conjb, m_left, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); return; } } void bli_sgemmsup_rv_haswell_asm_6x12m ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t m_iter = m0 / 6; uint64_t m_left = m0 % 6; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // Query the panel stride of A and convert it to units of bytes. uint64_t ps_a = bli_auxinfo_ps_a( data ); uint64_t ps_a4 = ps_a * sizeof( float ); if ( m_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), r14) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a //mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) //lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) // During preamble and loops: // r12 = rcx = c // r14 = rax = a // read rbx from var(b) near beginning of loop // r11 = m dim index ii mov(var(m_iter), r11) // ii = m_iter; label(.SLOOP6X8I) // LOOP OVER ii = [ m_iter ... 1 0 ] #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorps ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorps(ymm4, ymm4, ymm4) vxorps(ymm5, ymm5, ymm5) vxorps(ymm6, ymm6, ymm6) vxorps(ymm7, ymm7, ymm7) vxorps(ymm8, ymm8, ymm8) vxorps(ymm9, ymm9, ymm9) vxorps(ymm10, ymm10, ymm10) vxorps(ymm11, ymm11, ymm11) vxorps(ymm12, ymm12, ymm12) vxorps(ymm13, ymm13, ymm13) vxorps(ymm14, ymm14, ymm14) vxorps(ymm15, ymm15, ymm15) #endif mov(var(b), rbx) // load address of b. //mov(r12, rcx) // reset rcx to current utile of c. mov(r14, rax) // reset rax to current upanel of a. cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored prefetching on c lea(mem(r12, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(r12, 11*4)) // prefetch c + 0*rs_c prefetch(0, mem(r12, rdi, 1,11*4)) // prefetch c + 1*rs_c prefetch(0, mem(r12, rdi, 2,11*4)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 11*4)) // prefetch c + 3*rs_c prefetch(0, mem(rdx, rdi, 1,11*4)) // prefetch c + 4*rs_c prefetch(0, mem(rdx, rdi, 2,11*4)) // prefetch c + 5*rs_c jmp(.SPOSTPFETCH) // jump to end of prefetching c label(.SCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) lea(mem(rsi, rsi, 2), rcx) // rcx = 3*cs_c; prefetch(0, mem(r12, 5*4)) // prefetch c + 0*cs_c prefetch(0, mem(r12, rsi, 1, 5*4)) // prefetch c + 1*cs_c prefetch(0, mem(r12, rsi, 2, 5*4)) // prefetch c + 2*cs_c prefetch(0, mem(r12, rcx, 1, 5*4)) // prefetch c + 3*cs_c prefetch(0, mem(r12, rsi, 4, 5*4)) // prefetch c + 4*cs_c lea(mem(r12, rsi, 4), rdx) // rdx = c + 4*cs_c; prefetch(0, mem(rdx, rsi, 1, 5*4)) // prefetch c + 5*cs_c prefetch(0, mem(rdx, rsi, 2, 5*4)) // prefetch c + 6*cs_c prefetch(0, mem(rdx, rcx, 1, 5*4)) // prefetch c + 7*cs_c prefetch(0, mem(rdx, rsi, 4, 5*4)) // prefetch c + 8*cs_c lea(mem(r12, rsi, 8), rdx) // rdx = c + 8*cs_c; prefetch(0, mem(rdx, rsi, 1, 5*4)) // prefetch c + 9*cs_c prefetch(0, mem(rdx, rsi, 2, 5*4)) // prefetch c + 10*cs_c prefetch(0, mem(rdx, rcx, 1, 5*4)) // prefetch c + 11*cs_c label(.SPOSTPFETCH) // done prefetching c #if 1 mov(var(ps_a4), rdx) // load ps_a4 lea(mem(rax, rdx, 1), rdx) // rdx = a + ps_a4 lea(mem(r9, r9, 2), rcx) // rcx = 3*cs_a; // use rcx, rdx for prefetching lines // from next upanel of a. #else lea(mem(rax, r8, 4), rdx) // use rdx for prefetching lines lea(mem(rdx, r8, 2), rdx) // from next upanel of a. lea(mem(r9, r9, 2), rcx) // rcx = 3*cs_a; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, 5*8)) #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, r8, 4), ymm2) vbroadcastss(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, r9, 1, 5*8)) #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, r8, 4), ymm2) vbroadcastss(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) // ---------------------------------- iteration 2 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, r9, 2, 5*8)) #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, r8, 4), ymm2) vbroadcastss(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) // ---------------------------------- iteration 3 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, rcx, 1, 5*8)) lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, r8, 4), ymm2) vbroadcastss(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP #if 1 prefetch(0, mem(rdx, 5*8)) add(r9, rdx) #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, r8, 4), ymm2) vbroadcastss(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(r12, rcx) // reset rcx to current utile of c. mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), ymm0) // load alpha and duplicate vbroadcastss(mem(rbx), ymm3) // load beta and duplicate vmulps(ymm0, ymm4, ymm4) // scale by alpha vmulps(xmm0, xmm5, xmm5) vmulps(ymm0, ymm6, ymm6) vmulps(xmm0, xmm7, xmm7) vmulps(ymm0, ymm8, ymm8) vmulps(xmm0, xmm9, xmm9) vmulps(ymm0, ymm10, ymm10) vmulps(xmm0, xmm11, xmm11) vmulps(ymm0, ymm12, ymm12) vmulps(xmm0, xmm13, xmm13) vmulps(ymm0, ymm14, ymm14) vmulps(xmm0, xmm15, xmm15) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; lea(mem(rsi, rsi, 4), rbx) // rbx = 5*cs_c; lea(mem(rax, rsi, 4), rbp) // rbp = 7*cs_c; // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm4) vmovups(ymm4, mem(rcx, 0*32)) vfmadd231ps(mem(rcx, 1*32), xmm3, xmm5) vmovups(xmm5, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm6) vmovups(ymm6, mem(rcx, 0*32)) vfmadd231ps(mem(rcx, 1*32), xmm3, xmm7) vmovups(xmm7, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm8) vmovups(ymm8, mem(rcx, 0*32)) vfmadd231ps(mem(rcx, 1*32), xmm3, xmm9) vmovups(xmm9, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm10) vmovups(ymm10, mem(rcx, 0*32)) vfmadd231ps(mem(rcx, 1*32), xmm3, xmm11) vmovups(xmm11, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm12) vmovups(ymm12, mem(rcx, 0*32)) vfmadd231ps(mem(rcx, 1*32), xmm3, xmm13) vmovups(xmm13, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm14) vmovups(ymm14, mem(rcx, 0*32)) vfmadd231ps(mem(rcx, 1*32), xmm3, xmm15) vmovups(xmm15, mem(rcx, 1*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORED) // begin I/O on columns 0-7 vunpcklps(ymm6, ymm4, ymm0) vunpcklps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx ), xmm3, xmm0) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm0, mem(rcx )) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx, rsi, 1), xmm3, xmm1) vfmadd231ps(mem(rcx, rbx, 1), xmm3, xmm2) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rbx, 1)) // store ( gamma05..gamma35 ) vunpckhps(ymm6, ymm4, ymm0) vunpckhps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx, rsi, 2), xmm3, xmm0) vfmadd231ps(mem(rcx, rax, 2), xmm3, xmm2) vmovups(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, rax, 2)) // store ( gamma06..gamma36 ) vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx, rax, 1), xmm3, xmm1) vfmadd231ps(mem(rcx, rbp, 1), xmm3, xmm2) vmovups(xmm1, mem(rcx, rax, 1)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, rbp, 1)) // store ( gamma07..gamma37 ) lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vunpcklps(ymm14, ymm12, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(mem(rdx ), xmm1, xmm1) vmovhpd(mem(rdx, rsi, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(rdx )) // store ( gamma40..gamma50 ) vmovhpd(xmm0, mem(rdx, rsi, 1)) // store ( gamma41..gamma51 ) vmovlpd(mem(rdx, rsi, 4), xmm1, xmm1) vmovhpd(mem(rdx, rbx, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm2) vmovlpd(xmm2, mem(rdx, rsi, 4)) // store ( gamma44..gamma54 ) vmovhpd(xmm2, mem(rdx, rbx, 1)) // store ( gamma45..gamma55 ) vunpckhps(ymm14, ymm12, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(mem(rdx, rsi, 2), xmm1, xmm1) vmovhpd(mem(rdx, rax, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(rdx, rsi, 2)) // store ( gamma42..gamma52 ) vmovhpd(xmm0, mem(rdx, rax, 1)) // store ( gamma43..gamma53 ) vmovlpd(mem(rdx, rax, 2), xmm1, xmm1) vmovhpd(mem(rdx, rbp, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm2) vmovlpd(xmm2, mem(rdx, rax, 2)) // store ( gamma46..gamma56 ) vmovhpd(xmm2, mem(rdx, rbp, 1)) // store ( gamma47..gamma57 ) lea(mem(rdx, rsi, 8), rdx) // rdx += 8*cs_c // begin I/O on columns 8-11 vunpcklps(ymm7, ymm5, ymm0) vunpcklps(ymm11, ymm9, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vfmadd231ps(mem(rcx ), xmm3, xmm0) vmovups(xmm0, mem(rcx )) // store ( gamma00..gamma30 ) vfmadd231ps(mem(rcx, rsi, 1), xmm3, xmm1) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) vunpckhps(ymm7, ymm5, ymm0) vunpckhps(ymm11, ymm9, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vfmadd231ps(mem(rcx, rsi, 2), xmm3, xmm0) vmovups(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma32 ) vfmadd231ps(mem(rcx, rax, 1), xmm3, xmm1) vmovups(xmm1, mem(rcx, rax, 1)) // store ( gamma03..gamma33 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vunpcklps(ymm15, ymm13, ymm0) vmovlpd(mem(rdx ), xmm1, xmm1) vmovhpd(mem(rdx, rsi, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(rdx )) // store ( gamma40..gamma50 ) vmovhpd(xmm0, mem(rdx, rsi, 1)) // store ( gamma41..gamma51 ) vunpckhps(ymm15, ymm13, ymm0) vmovlpd(mem(rdx, rsi, 2), xmm1, xmm1) vmovhpd(mem(rdx, rax, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(rdx, rsi, 2)) // store ( gamma42..gamma52 ) vmovhpd(xmm0, mem(rdx, rax, 1)) // store ( gamma43..gamma53 ) //lea(mem(rdx, rsi, 8), rdx) // rdx += 8*cs_c jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovups(ymm4, mem(rcx, 0*32)) vmovups(xmm5, mem(rcx, 1*32)) add(rdi, rcx) vmovups(ymm6, mem(rcx, 0*32)) vmovups(xmm7, mem(rcx, 1*32)) add(rdi, rcx) vmovups(ymm8, mem(rcx, 0*32)) vmovups(xmm9, mem(rcx, 1*32)) add(rdi, rcx) vmovups(ymm10, mem(rcx, 0*32)) vmovups(xmm11, mem(rcx, 1*32)) add(rdi, rcx) vmovups(ymm12, mem(rcx, 0*32)) vmovups(xmm13, mem(rcx, 1*32)) add(rdi, rcx) vmovups(ymm14, mem(rcx, 0*32)) vmovups(xmm15, mem(rcx, 1*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) // begin I/O on columns 0-7 vunpcklps(ymm6, ymm4, ymm0) vunpcklps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx )) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rbx, 1)) // store ( gamma05..gamma35 ) vunpckhps(ymm6, ymm4, ymm0) vunpckhps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, rax, 2)) // store ( gamma06..gamma36 ) vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx, rax, 1)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, rbp, 1)) // store ( gamma07..gamma37 ) lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vunpcklps(ymm14, ymm12, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(xmm0, mem(rdx )) // store ( gamma40..gamma50 ) vmovhpd(xmm0, mem(rdx, rsi, 1)) // store ( gamma41..gamma51 ) vmovlpd(xmm2, mem(rdx, rsi, 4)) // store ( gamma44..gamma54 ) vmovhpd(xmm2, mem(rdx, rbx, 1)) // store ( gamma45..gamma55 ) vunpckhps(ymm14, ymm12, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(xmm0, mem(rdx, rsi, 2)) // store ( gamma42..gamma52 ) vmovhpd(xmm0, mem(rdx, rax, 1)) // store ( gamma43..gamma53 ) vmovlpd(xmm2, mem(rdx, rax, 2)) // store ( gamma46..gamma56 ) vmovhpd(xmm2, mem(rdx, rbp, 1)) // store ( gamma47..gamma57 ) lea(mem(rdx, rsi, 8), rdx) // rdx += 8*cs_c // begin I/O on columns 8-11 vunpcklps(ymm7, ymm5, ymm0) vunpcklps(ymm11, ymm9, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vmovups(xmm0, mem(rcx )) // store ( gamma00..gamma30 ) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) vunpckhps(ymm7, ymm5, ymm0) vunpckhps(ymm11, ymm9, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vmovups(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma32 ) vmovups(xmm1, mem(rcx, rax, 1)) // store ( gamma03..gamma33 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vunpcklps(ymm15, ymm13, ymm0) vmovlpd(xmm0, mem(rdx )) // store ( gamma40..gamma50 ) vmovhpd(xmm0, mem(rdx, rsi, 1)) // store ( gamma41..gamma51 ) vunpckhps(ymm15, ymm13, ymm0) vmovlpd(xmm0, mem(rdx, rsi, 2)) // store ( gamma42..gamma52 ) vmovhpd(xmm0, mem(rdx, rax, 1)) // store ( gamma43..gamma53 ) //lea(mem(rdx, rsi, 8), rdx) // rdx += 8*cs_c label(.SDONE) lea(mem(r12, rdi, 4), r12) // lea(mem(r12, rdi, 2), r12) // c_ii = r12 += 6*rs_c //lea(mem(r14, r8, 4), r14) // //lea(mem(r14, r8, 2), r14) // a_ii = r14 += 6*rs_a mov(var(ps_a4), rax) // load ps_a4 lea(mem(r14, rax, 1), r14) // a_ii = r14 += ps_a4 dec(r11) // ii -= 1; jne(.SLOOP6X8I) // iterate again if ii != 0. label(.SRETURN) end_asm( : // output operands (none) : // input operands [m_iter] "m" (m_iter), [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [ps_a4] "m" (ps_a4), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the m dimension, if they exist. if ( m_left ) { const dim_t nr_cur = 12; const dim_t i_edge = m0 - ( dim_t )m_left; float* restrict cij = c + i_edge*rs_c; //float* restrict ai = a + i_edge*rs_a; //float* restrict ai = a + ( i_edge / 6 ) * ps_a; float* restrict ai = a + m_iter * ps_a; float* restrict bj = b; #if 0 // We add special handling for slightly inflated MR blocksizes // at edge cases, up to a maximum of 9. if ( 6 < m_left ) { sgemmsup_ker_ft ker_fp1 = NULL; sgemmsup_ker_ft ker_fp2 = NULL; dim_t mr1, mr2; if ( m_left == 7 ) { mr1 = 4; mr2 = 3; ker_fp1 = bli_sgemmsup_rv_haswell_asm_4x16; ker_fp2 = bli_sgemmsup_rv_haswell_asm_3x16; } else if ( m_left == 8 ) { mr1 = 4; mr2 = 4; ker_fp1 = bli_sgemmsup_rv_haswell_asm_4x16; ker_fp2 = bli_sgemmsup_rv_haswell_asm_4x16; } else // if ( m_left == 9 ) { mr1 = 4; mr2 = 5; ker_fp1 = bli_sgemmsup_rv_haswell_asm_4x16; ker_fp2 = bli_sgemmsup_rv_haswell_asm_5x16; } ker_fp1 ( conja, conjb, mr1, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += mr1*rs_c0; ai += mr1*rs_a0; ker_fp2 ( conja, conjb, mr2, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); return; } #endif sgemmsup_ker_ft ker_fps[6] = { NULL, bli_sgemmsup_rv_haswell_asm_1x12, bli_sgemmsup_rv_haswell_asm_2x12, bli_sgemmsup_rv_haswell_asm_3x12, bli_sgemmsup_rv_haswell_asm_4x12, bli_sgemmsup_rv_haswell_asm_5x12 }; sgemmsup_ker_ft ker_fp = ker_fps[ m_left ]; ker_fp ( conja, conjb, m_left, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); return; } } void bli_sgemmsup_rv_haswell_asm_6x8m ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t m_iter = m0 / 6; uint64_t m_left = m0 % 6; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // Query the panel stride of A and convert it to units of bytes. uint64_t ps_a = bli_auxinfo_ps_a( data ); uint64_t ps_a4 = ps_a * sizeof( float ); if ( m_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), r14) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a //mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) //lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) // During preamble and loops: // r12 = rcx = c // r14 = rax = a // read rbx from var(b) near beginning of loop // r11 = m dim index ii mov(var(m_iter), r11) // ii = m_iter; label(.SLOOP6X8I) // LOOP OVER ii = [ m_iter ... 1 0 ] #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorps ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorps(ymm4, ymm4, ymm4) vxorps(ymm6, ymm6, ymm6) vxorps(ymm8, ymm8, ymm8) vxorps(ymm10, ymm10, ymm10) vxorps(ymm12, ymm12, ymm12) vxorps(ymm14, ymm14, ymm14) #endif mov(var(b), rbx) // load address of b. //mov(r12, rcx) // reset rcx to current utile of c. mov(r14, rax) // reset rax to current upanel of a. cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored prefetching on c lea(mem(r12, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(r12, 7*4)) // prefetch c + 0*rs_c prefetch(0, mem(r12, rdi, 1, 7*4)) // prefetch c + 1*rs_c prefetch(0, mem(r12, rdi, 2, 7*4)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 7*4)) // prefetch c + 3*rs_c prefetch(0, mem(rdx, rdi, 1, 7*4)) // prefetch c + 4*rs_c prefetch(0, mem(rdx, rdi, 2, 7*4)) // prefetch c + 5*rs_c jmp(.SPOSTPFETCH) // jump to end of prefetching c label(.SCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) lea(mem(rsi, rsi, 2), rcx) // rcx = 3*cs_c; prefetch(0, mem(r12, 5*4)) // prefetch c + 0*cs_c prefetch(0, mem(r12, rsi, 1, 5*4)) // prefetch c + 1*cs_c prefetch(0, mem(r12, rsi, 2, 5*4)) // prefetch c + 2*cs_c prefetch(0, mem(r12, rcx, 1, 5*4)) // prefetch c + 3*cs_c prefetch(0, mem(r12, rsi, 4, 5*4)) // prefetch c + 4*cs_c lea(mem(r12, rsi, 4), rdx) // rdx = c + 4*cs_c; prefetch(0, mem(rdx, rsi, 1, 5*4)) // prefetch c + 5*cs_c prefetch(0, mem(rdx, rsi, 2, 5*4)) // prefetch c + 6*cs_c prefetch(0, mem(rdx, rcx, 1, 5*4)) // prefetch c + 7*cs_c label(.SPOSTPFETCH) // done prefetching c #if 1 mov(var(ps_a4), rdx) // load ps_a4 lea(mem(rax, rdx, 1), rdx) // rdx = a + ps_a4 lea(mem(r9, r9, 2), rcx) // rcx = 3*cs_a; // use rcx, rdx for prefetching lines // from next upanel of a. #else lea(mem(rax, r8, 4), rdx) // use rdx for prefetching lines lea(mem(rdx, r8, 2), rdx) // from next upanel of a. lea(mem(r9, r9, 2), rcx) // rcx = 3*cs_a; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, 5*8)) #endif vmovups(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm0, ymm3, ymm10) vbroadcastss(mem(rax, r8, 4), ymm2) vbroadcastss(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm0, ymm3, ymm14) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, r9, 1, 5*8)) #endif vmovups(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm0, ymm3, ymm10) vbroadcastss(mem(rax, r8, 4), ymm2) vbroadcastss(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm0, ymm3, ymm14) // ---------------------------------- iteration 2 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, r9, 2, 5*8)) #endif vmovups(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm0, ymm3, ymm10) vbroadcastss(mem(rax, r8, 4), ymm2) vbroadcastss(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm0, ymm3, ymm14) // ---------------------------------- iteration 3 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, rcx, 1, 5*8)) lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; #endif vmovups(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm0, ymm3, ymm10) vbroadcastss(mem(rax, r8, 4), ymm2) vbroadcastss(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm0, ymm3, ymm14) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP #if 1 prefetch(0, mem(rdx, 5*8)) add(r9, rdx) #endif vmovups(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm0, ymm3, ymm10) vbroadcastss(mem(rax, r8, 4), ymm2) vbroadcastss(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm0, ymm3, ymm14) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(r12, rcx) // reset rcx to current utile of c. mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), ymm0) // load alpha and duplicate vbroadcastss(mem(rbx), ymm3) // load beta and duplicate vmulps(ymm0, ymm4, ymm4) // scale by alpha vmulps(ymm0, ymm6, ymm6) vmulps(ymm0, ymm8, ymm8) vmulps(ymm0, ymm10, ymm10) vmulps(ymm0, ymm12, ymm12) vmulps(ymm0, ymm14, ymm14) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; lea(mem(rsi, rsi, 4), rbx) // rbx = 5*cs_c; lea(mem(rax, rsi, 4), rbp) // rbp = 7*cs_c; // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm4) vmovups(ymm4, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm6) vmovups(ymm6, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm8) vmovups(ymm8, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm10) vmovups(ymm10, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm12) vmovups(ymm12, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm14) vmovups(ymm14, mem(rcx, 0*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORED) // begin I/O on columns 0-7 vunpcklps(ymm6, ymm4, ymm0) vunpcklps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx ), xmm3, xmm0) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm0, mem(rcx )) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx, rsi, 1), xmm3, xmm1) vfmadd231ps(mem(rcx, rbx, 1), xmm3, xmm2) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rbx, 1)) // store ( gamma05..gamma35 ) vunpckhps(ymm6, ymm4, ymm0) vunpckhps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx, rsi, 2), xmm3, xmm0) vfmadd231ps(mem(rcx, rax, 2), xmm3, xmm2) vmovups(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, rax, 2)) // store ( gamma06..gamma36 ) vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx, rax, 1), xmm3, xmm1) vfmadd231ps(mem(rcx, rbp, 1), xmm3, xmm2) vmovups(xmm1, mem(rcx, rax, 1)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, rbp, 1)) // store ( gamma07..gamma37 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vunpcklps(ymm14, ymm12, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(mem(rdx ), xmm1, xmm1) vmovhpd(mem(rdx, rsi, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(rdx )) // store ( gamma40..gamma50 ) vmovhpd(xmm0, mem(rdx, rsi, 1)) // store ( gamma41..gamma51 ) vmovlpd(mem(rdx, rsi, 4), xmm1, xmm1) vmovhpd(mem(rdx, rbx, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm2) vmovlpd(xmm2, mem(rdx, rsi, 4)) // store ( gamma44..gamma54 ) vmovhpd(xmm2, mem(rdx, rbx, 1)) // store ( gamma45..gamma55 ) vunpckhps(ymm14, ymm12, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(mem(rdx, rsi, 2), xmm1, xmm1) vmovhpd(mem(rdx, rax, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(rdx, rsi, 2)) // store ( gamma42..gamma52 ) vmovhpd(xmm0, mem(rdx, rax, 1)) // store ( gamma43..gamma53 ) vmovlpd(mem(rdx, rax, 2), xmm1, xmm1) vmovhpd(mem(rdx, rbp, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm2) vmovlpd(xmm2, mem(rdx, rax, 2)) // store ( gamma46..gamma56 ) vmovhpd(xmm2, mem(rdx, rbp, 1)) // store ( gamma47..gamma57 ) //lea(mem(rdx, rsi, 8), rdx) // rdx += 8*cs_c jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovups(ymm4, mem(rcx, 0*32)) add(rdi, rcx) vmovups(ymm6, mem(rcx, 0*32)) add(rdi, rcx) vmovups(ymm8, mem(rcx, 0*32)) add(rdi, rcx) vmovups(ymm10, mem(rcx, 0*32)) add(rdi, rcx) vmovups(ymm12, mem(rcx, 0*32)) add(rdi, rcx) vmovups(ymm14, mem(rcx, 0*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) // begin I/O on columns 0-7 vunpcklps(ymm6, ymm4, ymm0) vunpcklps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx )) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rbx, 1)) // store ( gamma05..gamma35 ) vunpckhps(ymm6, ymm4, ymm0) vunpckhps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, rax, 2)) // store ( gamma06..gamma36 ) vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx, rax, 1)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, rbp, 1)) // store ( gamma07..gamma37 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vunpcklps(ymm14, ymm12, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(xmm0, mem(rdx )) // store ( gamma40..gamma50 ) vmovhpd(xmm0, mem(rdx, rsi, 1)) // store ( gamma41..gamma51 ) vmovlpd(xmm2, mem(rdx, rsi, 4)) // store ( gamma44..gamma54 ) vmovhpd(xmm2, mem(rdx, rbx, 1)) // store ( gamma45..gamma55 ) vunpckhps(ymm14, ymm12, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(xmm0, mem(rdx, rsi, 2)) // store ( gamma42..gamma52 ) vmovhpd(xmm0, mem(rdx, rax, 1)) // store ( gamma43..gamma53 ) vmovlpd(xmm2, mem(rdx, rax, 2)) // store ( gamma46..gamma56 ) vmovhpd(xmm2, mem(rdx, rbp, 1)) // store ( gamma47..gamma57 ) //lea(mem(rdx, rsi, 8), rdx) // rdx += 8*cs_c label(.SDONE) lea(mem(r12, rdi, 4), r12) // lea(mem(r12, rdi, 2), r12) // c_ii = r12 += 6*rs_c //lea(mem(r14, r8, 4), r14) // //lea(mem(r14, r8, 2), r14) // a_ii = r14 += 6*rs_a mov(var(ps_a4), rax) // load ps_a4 lea(mem(r14, rax, 1), r14) // a_ii = r14 += ps_a4 dec(r11) // ii -= 1; jne(.SLOOP6X8I) // iterate again if ii != 0. label(.SRETURN) end_asm( : // output operands (none) : // input operands [m_iter] "m" (m_iter), [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [ps_a4] "m" (ps_a4), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the m dimension, if they exist. if ( m_left ) { const dim_t nr_cur = 8; const dim_t i_edge = m0 - ( dim_t )m_left; float* restrict cij = c + i_edge*rs_c; //float* restrict ai = a + i_edge*rs_a; //float* restrict ai = a + ( i_edge / 6 ) * ps_a; float* restrict ai = a + m_iter * ps_a; float* restrict bj = b; #if 0 // We add special handling for slightly inflated MR blocksizes // at edge cases, up to a maximum of 9. if ( 6 < m_left ) { sgemmsup_ker_ft ker_fp1 = NULL; sgemmsup_ker_ft ker_fp2 = NULL; dim_t mr1, mr2; if ( m_left == 7 ) { mr1 = 4; mr2 = 3; ker_fp1 = bli_sgemmsup_rv_haswell_asm_4x8; ker_fp2 = bli_sgemmsup_rv_haswell_asm_3x8; } else if ( m_left == 8 ) { mr1 = 4; mr2 = 4; ker_fp1 = bli_sgemmsup_rv_haswell_asm_4x8; ker_fp2 = bli_sgemmsup_rv_haswell_asm_4x8; } else // if ( m_left == 9 ) { mr1 = 4; mr2 = 5; ker_fp1 = bli_sgemmsup_rv_haswell_asm_4x8; ker_fp2 = bli_sgemmsup_rv_haswell_asm_5x8; } ker_fp1 ( conja, conjb, mr1, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += mr1*rs_c0; ai += mr1*rs_a0; ker_fp2 ( conja, conjb, mr2, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); return; } #endif sgemmsup_ker_ft ker_fps[6] = { NULL, bli_sgemmsup_rv_haswell_asm_1x8, bli_sgemmsup_rv_haswell_asm_2x8, bli_sgemmsup_rv_haswell_asm_3x8, bli_sgemmsup_rv_haswell_asm_4x8, bli_sgemmsup_rv_haswell_asm_5x8 }; sgemmsup_ker_ft ker_fp = ker_fps[ m_left ]; ker_fp ( conja, conjb, m_left, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); return; } } void bli_sgemmsup_rv_haswell_asm_6x6m ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t m_iter = m0 / 6; uint64_t m_left = m0 % 6; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // Query the panel stride of A and convert it to units of bytes. uint64_t ps_a = bli_auxinfo_ps_a( data ); uint64_t ps_a4 = ps_a * sizeof( float ); if ( m_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), r14) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a //mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) //lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) // During preamble and loops: // r12 = rcx = c // r14 = rax = a // read rbx from var(b) near beginning of loop // r11 = m dim index ii mov(var(m_iter), r11) // ii = m_iter; label(.SLOOP6X8I) // LOOP OVER ii = [ m_iter ... 1 0 ] #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorps ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorps(ymm4, ymm4, ymm4) vxorps(ymm6, ymm6, ymm6) vxorps(ymm8, ymm8, ymm8) vxorps(ymm10, ymm10, ymm10) vxorps(ymm12, ymm12, ymm12) vxorps(ymm14, ymm14, ymm14) #endif mov(var(b), rbx) // load address of b. //mov(r12, rcx) // reset rcx to current utile of c. mov(r14, rax) // reset rax to current upanel of a. cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored prefetching on c lea(mem(r12, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(r12, 5*4)) // prefetch c + 0*rs_c prefetch(0, mem(r12, rdi, 1, 5*4)) // prefetch c + 1*rs_c prefetch(0, mem(r12, rdi, 2, 5*4)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 5*4)) // prefetch c + 3*rs_c prefetch(0, mem(rdx, rdi, 1, 5*4)) // prefetch c + 4*rs_c prefetch(0, mem(rdx, rdi, 2, 5*4)) // prefetch c + 5*rs_c jmp(.SPOSTPFETCH) // jump to end of prefetching c label(.SCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) lea(mem(rsi, rsi, 2), rcx) // rcx = 3*cs_c; prefetch(0, mem(r12, 5*4)) // prefetch c + 0*cs_c prefetch(0, mem(r12, rsi, 1, 5*4)) // prefetch c + 1*cs_c prefetch(0, mem(r12, rsi, 2, 5*4)) // prefetch c + 2*cs_c prefetch(0, mem(r12, rcx, 1, 5*4)) // prefetch c + 3*cs_c prefetch(0, mem(r12, rsi, 4, 5*4)) // prefetch c + 4*cs_c lea(mem(r12, rsi, 4), rdx) // rdx = c + 4*cs_c; prefetch(0, mem(rdx, rsi, 1, 5*4)) // prefetch c + 5*cs_c label(.SPOSTPFETCH) // done prefetching c #if 1 mov(var(ps_a4), rdx) // load ps_a4 lea(mem(rax, rdx, 1), rdx) // rdx = a + ps_a4 lea(mem(r9, r9, 2), rcx) // rcx = 3*cs_a; // use rcx, rdx for prefetching lines // from next upanel of a. #else lea(mem(rax, r8, 4), rdx) // use rdx for prefetching lines lea(mem(rdx, r8, 2), rdx) // from next upanel of a. lea(mem(r9, r9, 2), rcx) // rcx = 3*cs_a; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, 5*8)) #endif vmovups(mem(rbx, 0*4), xmm0) vmovsd(mem(rbx, 4*4), xmm1) vinsertf128(imm(0x1), xmm1, ymm0, ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm0, ymm3, ymm10) vbroadcastss(mem(rax, r8, 4), ymm2) vbroadcastss(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm0, ymm3, ymm14) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, r9, 1, 5*8)) #endif vmovups(mem(rbx, 0*4), xmm0) vmovsd(mem(rbx, 4*4), xmm1) vinsertf128(imm(0x1), xmm1, ymm0, ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm0, ymm3, ymm10) vbroadcastss(mem(rax, r8, 4), ymm2) vbroadcastss(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm0, ymm3, ymm14) // ---------------------------------- iteration 2 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, r9, 2, 5*8)) #endif vmovups(mem(rbx, 0*4), xmm0) vmovsd(mem(rbx, 4*4), xmm1) vinsertf128(imm(0x1), xmm1, ymm0, ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm0, ymm3, ymm10) vbroadcastss(mem(rax, r8, 4), ymm2) vbroadcastss(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm0, ymm3, ymm14) // ---------------------------------- iteration 3 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, rcx, 1, 5*8)) lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; #endif vmovups(mem(rbx, 0*4), xmm0) vmovsd(mem(rbx, 4*4), xmm1) vinsertf128(imm(0x1), xmm1, ymm0, ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm0, ymm3, ymm10) vbroadcastss(mem(rax, r8, 4), ymm2) vbroadcastss(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm0, ymm3, ymm14) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP #if 1 prefetch(0, mem(rdx, 5*8)) add(r9, rdx) #endif vmovups(mem(rbx, 0*4), xmm0) vmovsd(mem(rbx, 4*4), xmm1) vinsertf128(imm(0x1), xmm1, ymm0, ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm0, ymm3, ymm10) vbroadcastss(mem(rax, r8, 4), ymm2) vbroadcastss(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm0, ymm3, ymm14) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(r12, rcx) // reset rcx to current utile of c. mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), ymm0) // load alpha and duplicate vbroadcastss(mem(rbx), ymm3) // load beta and duplicate vmulps(ymm0, ymm4, ymm4) // scale by alpha vmulps(ymm0, ymm6, ymm6) vmulps(ymm0, ymm8, ymm8) vmulps(ymm0, ymm10, ymm10) vmulps(ymm0, ymm12, ymm12) vmulps(ymm0, ymm14, ymm14) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; lea(mem(rsi, rsi, 4), rbx) // rbx = 5*cs_c; //lea(mem(rax, rsi, 4), rbp) // rbp = 7*cs_c; // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set xmm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vextractf128(imm(0x1), ymm4, xmm5) vfmadd231ps(mem(rcx, 0*4), xmm3, xmm4) vmovups(xmm4, mem(rcx, 0*4)) vmovsd(mem(rcx, 4*4), xmm1) vfmadd231ps(xmm1, xmm3, xmm5) vmovsd(xmm5, mem(rcx, 4*4)) add(rdi, rcx) vextractf128(imm(0x1), ymm6, xmm7) vfmadd231ps(mem(rcx, 0*4), xmm3, xmm6) vmovups(xmm6, mem(rcx, 0*4)) vmovsd(mem(rcx, 4*4), xmm1) vfmadd231ps(xmm1, xmm3, xmm7) vmovsd(xmm7, mem(rcx, 4*4)) add(rdi, rcx) vextractf128(imm(0x1), ymm8, xmm9) vfmadd231ps(mem(rcx, 0*4), xmm3, xmm8) vmovups(xmm8, mem(rcx, 0*4)) vmovsd(mem(rcx, 4*4), xmm1) vfmadd231ps(xmm1, xmm3, xmm9) vmovsd(xmm9, mem(rcx, 4*4)) add(rdi, rcx) vextractf128(imm(0x1), ymm10, xmm11) vfmadd231ps(mem(rcx, 0*4), xmm3, xmm10) vmovups(xmm10, mem(rcx, 0*4)) vmovsd(mem(rcx, 4*4), xmm1) vfmadd231ps(xmm1, xmm3, xmm11) vmovsd(xmm11, mem(rcx, 4*4)) add(rdi, rcx) vextractf128(imm(0x1), ymm12, xmm13) vfmadd231ps(mem(rcx, 0*4), xmm3, xmm12) vmovups(xmm12, mem(rcx, 0*4)) vmovsd(mem(rcx, 4*4), xmm1) vfmadd231ps(xmm1, xmm3, xmm13) vmovsd(xmm13, mem(rcx, 4*4)) add(rdi, rcx) vextractf128(imm(0x1), ymm14, xmm15) vfmadd231ps(mem(rcx, 0*4), xmm3, xmm14) vmovups(xmm14, mem(rcx, 0*4)) vmovsd(mem(rcx, 4*4), xmm1) vfmadd231ps(xmm1, xmm3, xmm15) vmovsd(xmm15, mem(rcx, 4*4)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORED) // begin I/O on columns 0-5 vunpcklps(ymm6, ymm4, ymm0) vunpcklps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx ), xmm3, xmm0) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm0, mem(rcx )) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx, rsi, 1), xmm3, xmm1) vfmadd231ps(mem(rcx, rbx, 1), xmm3, xmm2) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rbx, 1)) // store ( gamma05..gamma35 ) vunpckhps(ymm6, ymm4, ymm0) vunpckhps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vfmadd231ps(mem(rcx, rsi, 2), xmm3, xmm0) vmovups(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma32 ) vfmadd231ps(mem(rcx, rax, 1), xmm3, xmm1) vmovups(xmm1, mem(rcx, rax, 1)) // store ( gamma03..gamma33 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vunpcklps(ymm14, ymm12, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(mem(rdx ), xmm1, xmm1) vmovhpd(mem(rdx, rsi, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(rdx )) // store ( gamma40..gamma50 ) vmovhpd(xmm0, mem(rdx, rsi, 1)) // store ( gamma41..gamma51 ) vmovlpd(mem(rdx, rsi, 4), xmm1, xmm1) vmovhpd(mem(rdx, rbx, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm2) vmovlpd(xmm2, mem(rdx, rsi, 4)) // store ( gamma44..gamma54 ) vmovhpd(xmm2, mem(rdx, rbx, 1)) // store ( gamma45..gamma55 ) vunpckhps(ymm14, ymm12, ymm0) vmovlpd(mem(rdx, rsi, 2), xmm1, xmm1) vmovhpd(mem(rdx, rax, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(rdx, rsi, 2)) // store ( gamma42..gamma52 ) vmovhpd(xmm0, mem(rdx, rax, 1)) // store ( gamma43..gamma53 ) //lea(mem(rdx, rsi, 8), rdx) // rdx += 8*cs_c jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vextractf128(imm(0x1), ymm4, xmm5) vmovups(xmm4, mem(rcx, 0*4)) vmovsd(xmm5, mem(rcx, 4*4)) add(rdi, rcx) vextractf128(imm(0x1), ymm6, xmm7) vmovups(xmm6, mem(rcx, 0*4)) vmovsd(xmm7, mem(rcx, 4*4)) add(rdi, rcx) vextractf128(imm(0x1), ymm8, xmm9) vmovups(xmm8, mem(rcx, 0*4)) vmovsd(xmm9, mem(rcx, 4*4)) add(rdi, rcx) vextractf128(imm(0x1), ymm10, xmm11) vmovups(xmm10, mem(rcx, 0*4)) vmovsd(xmm11, mem(rcx, 4*4)) add(rdi, rcx) vextractf128(imm(0x1), ymm12, xmm13) vmovups(xmm12, mem(rcx, 0*4)) vmovsd(xmm13, mem(rcx, 4*4)) add(rdi, rcx) vextractf128(imm(0x1), ymm14, xmm15) vmovups(xmm14, mem(rcx, 0*4)) vmovsd(xmm15, mem(rcx, 4*4)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) // begin I/O on columns 0-5 vunpcklps(ymm6, ymm4, ymm0) vunpcklps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx )) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rbx, 1)) // store ( gamma05..gamma35 ) vunpckhps(ymm6, ymm4, ymm0) vunpckhps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vmovups(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma32 ) vmovups(xmm1, mem(rcx, rax, 1)) // store ( gamma03..gamma33 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vunpcklps(ymm14, ymm12, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(xmm0, mem(rdx )) // store ( gamma40..gamma50 ) vmovhpd(xmm0, mem(rdx, rsi, 1)) // store ( gamma41..gamma51 ) vmovlpd(xmm2, mem(rdx, rsi, 4)) // store ( gamma44..gamma54 ) vmovhpd(xmm2, mem(rdx, rbx, 1)) // store ( gamma45..gamma55 ) vunpckhps(ymm14, ymm12, ymm0) vmovlpd(xmm0, mem(rdx, rsi, 2)) // store ( gamma42..gamma52 ) vmovhpd(xmm0, mem(rdx, rax, 1)) // store ( gamma43..gamma53 ) //lea(mem(rdx, rsi, 8), rdx) // rdx += 8*cs_c label(.SDONE) lea(mem(r12, rdi, 4), r12) // lea(mem(r12, rdi, 2), r12) // c_ii = r12 += 6*rs_c //lea(mem(r14, r8, 4), r14) // //lea(mem(r14, r8, 2), r14) // a_ii = r14 += 6*rs_a mov(var(ps_a4), rax) // load ps_a4 lea(mem(r14, rax, 1), r14) // a_ii = r14 += ps_a4 dec(r11) // ii -= 1; jne(.SLOOP6X8I) // iterate again if ii != 0. label(.SRETURN) end_asm( : // output operands (none) : // input operands [m_iter] "m" (m_iter), [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [ps_a4] "m" (ps_a4), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the m dimension, if they exist. if ( m_left ) { const dim_t nr_cur = 6; const dim_t i_edge = m0 - ( dim_t )m_left; float* restrict cij = c + i_edge*rs_c; //float* restrict ai = a + i_edge*rs_a; //float* restrict ai = a + ( i_edge / 6 ) * ps_a; float* restrict ai = a + m_iter * ps_a; float* restrict bj = b; #if 0 // We add special handling for slightly inflated MR blocksizes // at edge cases, up to a maximum of 9. if ( 6 < m_left ) { sgemmsup_ker_ft ker_fp1 = NULL; sgemmsup_ker_ft ker_fp2 = NULL; dim_t mr1, mr2; if ( m_left == 7 ) { mr1 = 4; mr2 = 3; ker_fp1 = bli_sgemmsup_rv_haswell_asm_4x6; ker_fp2 = bli_sgemmsup_rv_haswell_asm_3x6; } else if ( m_left == 8 ) { mr1 = 4; mr2 = 4; ker_fp1 = bli_sgemmsup_rv_haswell_asm_4x6; ker_fp2 = bli_sgemmsup_rv_haswell_asm_4x6; } else // if ( m_left == 9 ) { mr1 = 4; mr2 = 5; ker_fp1 = bli_sgemmsup_rv_haswell_asm_4x6; ker_fp2 = bli_sgemmsup_rv_haswell_asm_5x6; } ker_fp1 ( conja, conjb, mr1, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += mr1*rs_c0; ai += mr1*rs_a0; ker_fp2 ( conja, conjb, mr2, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); return; } #endif sgemmsup_ker_ft ker_fps[6] = { NULL, bli_sgemmsup_rv_haswell_asm_1x6, bli_sgemmsup_rv_haswell_asm_2x6, bli_sgemmsup_rv_haswell_asm_3x6, bli_sgemmsup_rv_haswell_asm_4x6, bli_sgemmsup_rv_haswell_asm_5x6 }; sgemmsup_ker_ft ker_fp = ker_fps[ m_left ]; ker_fp ( conja, conjb, m_left, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); return; } } void bli_sgemmsup_rv_haswell_asm_6x4m ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t m_iter = m0 / 6; uint64_t m_left = m0 % 6; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // Query the panel stride of A and convert it to units of bytes. uint64_t ps_a = bli_auxinfo_ps_a( data ); uint64_t ps_a4 = ps_a * sizeof( float ); if ( m_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), r14) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a //mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) //lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) // During preamble and loops: // r12 = rcx = c // r14 = rax = a // read rbx from var(b) near beginning of loop // r11 = m dim index ii mov(var(m_iter), r11) // ii = m_iter; label(.SLOOP6X8I) // LOOP OVER ii = [ m_iter ... 1 0 ] #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorps ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorps(ymm4, ymm4, ymm4) vxorps(ymm6, ymm6, ymm6) vxorps(ymm8, ymm8, ymm8) vxorps(ymm10, ymm10, ymm10) vxorps(ymm12, ymm12, ymm12) vxorps(ymm14, ymm14, ymm14) #endif mov(var(b), rbx) // load address of b. //mov(r12, rcx) // reset rcx to current utile of c. mov(r14, rax) // reset rax to current upanel of a. cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored prefetching on c lea(mem(r12, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(r12, 3*4)) // prefetch c + 0*rs_c prefetch(0, mem(r12, rdi, 1, 3*4)) // prefetch c + 1*rs_c prefetch(0, mem(r12, rdi, 2, 3*4)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 3*4)) // prefetch c + 3*rs_c prefetch(0, mem(rdx, rdi, 1, 3*4)) // prefetch c + 4*rs_c prefetch(0, mem(rdx, rdi, 2, 3*4)) // prefetch c + 5*rs_c jmp(.SPOSTPFETCH) // jump to end of prefetching c label(.SCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) lea(mem(rsi, rsi, 2), rcx) // rcx = 3*cs_c; prefetch(0, mem(r12, 5*4)) // prefetch c + 0*cs_c prefetch(0, mem(r12, rsi, 1, 5*4)) // prefetch c + 1*cs_c prefetch(0, mem(r12, rsi, 2, 5*4)) // prefetch c + 2*cs_c prefetch(0, mem(r12, rcx, 1, 5*4)) // prefetch c + 3*cs_c label(.SPOSTPFETCH) // done prefetching c #if 1 mov(var(ps_a4), rdx) // load ps_a4 lea(mem(rax, rdx, 1), rdx) // rdx = a + ps_a4 lea(mem(r9, r9, 2), rcx) // rcx = 3*cs_a; // use rcx, rdx for prefetching lines // from next upanel of a. #else lea(mem(rax, r8, 4), rdx) // use rdx for prefetching lines lea(mem(rdx, r8, 2), rdx) // from next upanel of a. lea(mem(r9, r9, 2), rcx) // rcx = 3*cs_a; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, 5*8)) #endif vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) vbroadcastss(mem(rax, r13, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm8) vfmadd231ps(xmm0, xmm3, xmm10) vbroadcastss(mem(rax, r8, 4), xmm2) vbroadcastss(mem(rax, r15, 1), xmm3) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm12) vfmadd231ps(xmm0, xmm3, xmm14) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, r9, 1, 5*8)) #endif vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) vbroadcastss(mem(rax, r13, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm8) vfmadd231ps(xmm0, xmm3, xmm10) vbroadcastss(mem(rax, r8, 4), xmm2) vbroadcastss(mem(rax, r15, 1), xmm3) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm12) vfmadd231ps(xmm0, xmm3, xmm14) // ---------------------------------- iteration 2 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, r9, 2, 5*8)) #endif vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) vbroadcastss(mem(rax, r13, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm8) vfmadd231ps(xmm0, xmm3, xmm10) vbroadcastss(mem(rax, r8, 4), xmm2) vbroadcastss(mem(rax, r15, 1), xmm3) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm12) vfmadd231ps(xmm0, xmm3, xmm14) // ---------------------------------- iteration 3 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, rcx, 1, 5*8)) lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; #endif vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) vbroadcastss(mem(rax, r13, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm8) vfmadd231ps(xmm0, xmm3, xmm10) vbroadcastss(mem(rax, r8, 4), xmm2) vbroadcastss(mem(rax, r15, 1), xmm3) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm12) vfmadd231ps(xmm0, xmm3, xmm14) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP #if 1 prefetch(0, mem(rdx, 5*8)) add(r9, rdx) #endif vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) vbroadcastss(mem(rax, r13, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm8) vfmadd231ps(xmm0, xmm3, xmm10) vbroadcastss(mem(rax, r8, 4), xmm2) vbroadcastss(mem(rax, r15, 1), xmm3) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm12) vfmadd231ps(xmm0, xmm3, xmm14) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(r12, rcx) // reset rcx to current utile of c. mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), xmm0) // load alpha and duplicate vbroadcastss(mem(rbx), xmm3) // load beta and duplicate vmulps(xmm0, xmm4, xmm4) // scale by alpha vmulps(xmm0, xmm6, xmm6) vmulps(xmm0, xmm8, xmm8) vmulps(xmm0, xmm10, xmm10) vmulps(xmm0, xmm12, xmm12) vmulps(xmm0, xmm14, xmm14) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; //lea(mem(rsi, rsi, 4), rbx) // rbx = 5*cs_c; //lea(mem(rax, rsi, 4), rbp) // rbp = 7*cs_c; // now avoid loading C if beta == 0 vxorps(xmm0, xmm0, xmm0) // set xmm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vfmadd231ps(mem(rcx, 0*32), xmm3, xmm4) vmovups(xmm4, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), xmm3, xmm6) vmovups(xmm6, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), xmm3, xmm8) vmovups(xmm8, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), xmm3, xmm10) vmovups(xmm10, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), xmm3, xmm12) vmovups(xmm12, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), xmm3, xmm14) vmovups(xmm14, mem(rcx, 0*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORED) // begin I/O on columns 0-3 vunpcklps(xmm6, xmm4, xmm0) vunpcklps(xmm10, xmm8, xmm1) vshufps(imm(0x4e), xmm1, xmm0, xmm2) vblendps(imm(0xcc), xmm2, xmm0, xmm0) vblendps(imm(0x33), xmm2, xmm1, xmm1) vfmadd231ps(mem(rcx ), xmm3, xmm0) vmovups(xmm0, mem(rcx )) // store ( gamma00..gamma30 ) vfmadd231ps(mem(rcx, rsi, 1), xmm3, xmm1) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) vunpckhps(xmm6, xmm4, xmm0) vunpckhps(xmm10, xmm8, xmm1) vshufps(imm(0x4e), xmm1, xmm0, xmm2) vblendps(imm(0xcc), xmm2, xmm0, xmm0) vblendps(imm(0x33), xmm2, xmm1, xmm1) vfmadd231ps(mem(rcx, rsi, 2), xmm3, xmm0) vmovups(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma32 ) vfmadd231ps(mem(rcx, rax, 1), xmm3, xmm1) vmovups(xmm1, mem(rcx, rax, 1)) // store ( gamma03..gamma33 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vunpcklps(xmm14, xmm12, xmm0) vmovlpd(mem(rdx ), xmm1, xmm1) vmovhpd(mem(rdx, rsi, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(rdx )) // store ( gamma40..gamma50 ) vmovhpd(xmm0, mem(rdx, rsi, 1)) // store ( gamma41..gamma51 ) vunpckhps(xmm14, xmm12, xmm0) vmovlpd(mem(rdx, rsi, 2), xmm1, xmm1) vmovhpd(mem(rdx, rax, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(rdx, rsi, 2)) // store ( gamma42..gamma52 ) vmovhpd(xmm0, mem(rdx, rax, 1)) // store ( gamma43..gamma53 ) //lea(mem(rdx, rsi, 8), rdx) // rdx += 8*cs_c jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovups(xmm4, mem(rcx, 0*32)) add(rdi, rcx) vmovups(xmm6, mem(rcx, 0*32)) add(rdi, rcx) vmovups(xmm8, mem(rcx, 0*32)) add(rdi, rcx) vmovups(xmm10, mem(rcx, 0*32)) add(rdi, rcx) vmovups(xmm12, mem(rcx, 0*32)) add(rdi, rcx) vmovups(xmm14, mem(rcx, 0*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) // begin I/O on columns 0-3 vunpcklps(ymm6, ymm4, ymm0) vunpcklps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vmovups(xmm0, mem(rcx )) // store ( gamma00..gamma30 ) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) vunpckhps(ymm6, ymm4, ymm0) vunpckhps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vmovups(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma32 ) vmovups(xmm1, mem(rcx, rax, 1)) // store ( gamma03..gamma33 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vunpcklps(ymm14, ymm12, ymm0) vmovlpd(xmm0, mem(rdx )) // store ( gamma40..gamma50 ) vmovhpd(xmm0, mem(rdx, rsi, 1)) // store ( gamma41..gamma51 ) vunpckhps(ymm14, ymm12, ymm0) vmovlpd(xmm0, mem(rdx, rsi, 2)) // store ( gamma42..gamma52 ) vmovhpd(xmm0, mem(rdx, rax, 1)) // store ( gamma43..gamma53 ) //lea(mem(rdx, rsi, 8), rdx) // rdx += 8*cs_c label(.SDONE) lea(mem(r12, rdi, 4), r12) // lea(mem(r12, rdi, 2), r12) // c_ii = r12 += 6*rs_c //lea(mem(r14, r8, 4), r14) // //lea(mem(r14, r8, 2), r14) // a_ii = r14 += 6*rs_a mov(var(ps_a4), rax) // load ps_a4 lea(mem(r14, rax, 1), r14) // a_ii = r14 += ps_a4 dec(r11) // ii -= 1; jne(.SLOOP6X8I) // iterate again if ii != 0. label(.SRETURN) end_asm( : // output operands (none) : // input operands [m_iter] "m" (m_iter), [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [ps_a4] "m" (ps_a4), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the m dimension, if they exist. if ( m_left ) { const dim_t nr_cur = 4; const dim_t i_edge = m0 - ( dim_t )m_left; float* restrict cij = c + i_edge*rs_c; //float* restrict ai = a + i_edge*rs_a; //float* restrict ai = a + ( i_edge / 6 ) * ps_a; float* restrict ai = a + m_iter * ps_a; float* restrict bj = b; #if 0 // We add special handling for slightly inflated MR blocksizes // at edge cases, up to a maximum of 9. if ( 6 < m_left ) { sgemmsup_ker_ft ker_fp1 = NULL; sgemmsup_ker_ft ker_fp2 = NULL; dim_t mr1, mr2; if ( m_left == 7 ) { mr1 = 4; mr2 = 3; ker_fp1 = bli_sgemmsup_rv_haswell_asm_4x4; ker_fp2 = bli_sgemmsup_rv_haswell_asm_3x4; } else if ( m_left == 8 ) { mr1 = 4; mr2 = 4; ker_fp1 = bli_sgemmsup_rv_haswell_asm_4x4; ker_fp2 = bli_sgemmsup_rv_haswell_asm_4x4; } else // if ( m_left == 9 ) { mr1 = 4; mr2 = 5; ker_fp1 = bli_sgemmsup_rv_haswell_asm_4x4; ker_fp2 = bli_sgemmsup_rv_haswell_asm_5x4; } ker_fp1 ( conja, conjb, mr1, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += mr1*rs_c0; ai += mr1*rs_a0; ker_fp2 ( conja, conjb, mr2, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); return; } #endif sgemmsup_ker_ft ker_fps[6] = { NULL, bli_sgemmsup_rv_haswell_asm_1x4, bli_sgemmsup_rv_haswell_asm_2x4, bli_sgemmsup_rv_haswell_asm_3x4, bli_sgemmsup_rv_haswell_asm_4x4, bli_sgemmsup_rv_haswell_asm_5x4 }; sgemmsup_ker_ft ker_fp = ker_fps[ m_left ]; ker_fp ( conja, conjb, m_left, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); return; } } void bli_sgemmsup_rv_haswell_asm_6x2m ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t m_iter = m0 / 6; uint64_t m_left = m0 % 6; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // Query the panel stride of A and convert it to units of bytes. uint64_t ps_a = bli_auxinfo_ps_a( data ); uint64_t ps_a4 = ps_a * sizeof( float ); if ( m_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), r14) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a //mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) //lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) // During preamble and loops: // r12 = rcx = c // r14 = rax = a // read rbx from var(b) near beginning of loop // r11 = m dim index ii mov(var(m_iter), r11) // ii = m_iter; label(.SLOOP6X8I) // LOOP OVER ii = [ m_iter ... 1 0 ] #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorps ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorps(ymm4, ymm4, ymm4) vxorps(ymm6, ymm6, ymm6) vxorps(ymm8, ymm8, ymm8) vxorps(ymm10, ymm10, ymm10) vxorps(ymm12, ymm12, ymm12) vxorps(ymm14, ymm14, ymm14) #endif mov(var(b), rbx) // load address of b. //mov(r12, rcx) // reset rcx to current utile of c. mov(r14, rax) // reset rax to current upanel of a. cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored prefetching on c lea(mem(r12, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(r12, 1*4)) // prefetch c + 0*rs_c prefetch(0, mem(r12, rdi, 1, 1*4)) // prefetch c + 1*rs_c prefetch(0, mem(r12, rdi, 2, 1*4)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 1*4)) // prefetch c + 3*rs_c prefetch(0, mem(rdx, rdi, 1, 1*4)) // prefetch c + 4*rs_c prefetch(0, mem(rdx, rdi, 2, 1*4)) // prefetch c + 5*rs_c jmp(.SPOSTPFETCH) // jump to end of prefetching c label(.SCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) //lea(mem(rsi, rsi, 2), rcx) // rcx = 3*cs_c; prefetch(0, mem(r12, 5*4)) // prefetch c + 0*cs_c prefetch(0, mem(r12, rsi, 1, 5*4)) // prefetch c + 1*cs_c label(.SPOSTPFETCH) // done prefetching c #if 1 mov(var(ps_a4), rdx) // load ps_a4 lea(mem(rax, rdx, 1), rdx) // rdx = a + ps_a4 lea(mem(r9, r9, 2), rcx) // rcx = 3*cs_a; // use rcx, rdx for prefetching lines // from next upanel of a. #else lea(mem(rax, r8, 4), rdx) // use rdx for prefetching lines lea(mem(rdx, r8, 2), rdx) // from next upanel of a. lea(mem(r9, r9, 2), rcx) // rcx = 3*cs_a; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, 5*8)) #endif vmovsd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) vbroadcastss(mem(rax, r13, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm8) vfmadd231ps(xmm0, xmm3, xmm10) vbroadcastss(mem(rax, r8, 4), xmm2) vbroadcastss(mem(rax, r15, 1), xmm3) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm12) vfmadd231ps(xmm0, xmm3, xmm14) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, r9, 1, 5*8)) #endif vmovsd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) vbroadcastss(mem(rax, r13, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm8) vfmadd231ps(xmm0, xmm3, xmm10) vbroadcastss(mem(rax, r8, 4), xmm2) vbroadcastss(mem(rax, r15, 1), xmm3) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm12) vfmadd231ps(xmm0, xmm3, xmm14) // ---------------------------------- iteration 2 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, r9, 2, 5*8)) #endif vmovsd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) vbroadcastss(mem(rax, r13, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm8) vfmadd231ps(xmm0, xmm3, xmm10) vbroadcastss(mem(rax, r8, 4), xmm2) vbroadcastss(mem(rax, r15, 1), xmm3) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm12) vfmadd231ps(xmm0, xmm3, xmm14) // ---------------------------------- iteration 3 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, rcx, 1, 5*8)) lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; #endif vmovsd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) vbroadcastss(mem(rax, r13, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm8) vfmadd231ps(xmm0, xmm3, xmm10) vbroadcastss(mem(rax, r8, 4), xmm2) vbroadcastss(mem(rax, r15, 1), xmm3) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm12) vfmadd231ps(xmm0, xmm3, xmm14) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP #if 1 prefetch(0, mem(rdx, 5*8)) add(r9, rdx) #endif vmovsd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) vbroadcastss(mem(rax, r13, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm8) vfmadd231ps(xmm0, xmm3, xmm10) vbroadcastss(mem(rax, r8, 4), xmm2) vbroadcastss(mem(rax, r15, 1), xmm3) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm12) vfmadd231ps(xmm0, xmm3, xmm14) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(r12, rcx) // reset rcx to current utile of c. mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), xmm0) // load alpha and duplicate vbroadcastss(mem(rbx), xmm3) // load beta and duplicate vmulps(xmm0, xmm4, xmm4) // scale by alpha vmulps(xmm0, xmm6, xmm6) vmulps(xmm0, xmm8, xmm8) vmulps(xmm0, xmm10, xmm10) vmulps(xmm0, xmm12, xmm12) vmulps(xmm0, xmm14, xmm14) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; //lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; //lea(mem(rsi, rsi, 4), rbx) // rbx = 5*cs_c; //lea(mem(rax, rsi, 4), rbp) // rbp = 7*cs_c; // now avoid loading C if beta == 0 vxorps(xmm0, xmm0, xmm0) // set xmm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vfmadd231ps(mem(rcx, 0*32), xmm3, xmm4) vmovsd(xmm4, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), xmm3, xmm6) vmovsd(xmm6, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), xmm3, xmm8) vmovsd(xmm8, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), xmm3, xmm10) vmovsd(xmm10, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), xmm3, xmm12) vmovsd(xmm12, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), xmm3, xmm14) vmovsd(xmm14, mem(rcx, 0*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORED) // begin I/O on columns 0-1 vunpcklps(xmm6, xmm4, xmm0) vunpcklps(xmm10, xmm8, xmm1) vshufps(imm(0x4e), xmm1, xmm0, xmm2) vblendps(imm(0xcc), xmm2, xmm0, xmm0) vblendps(imm(0x33), xmm2, xmm1, xmm1) vfmadd231ps(mem(rcx ), xmm3, xmm0) vmovups(xmm0, mem(rcx )) // store ( gamma00..gamma30 ) vfmadd231ps(mem(rcx, rsi, 1), xmm3, xmm1) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vunpcklps(xmm14, xmm12, xmm0) vmovlpd(mem(rdx ), xmm1, xmm1) vmovhpd(mem(rdx, rsi, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(rdx )) // store ( gamma40..gamma50 ) vmovhpd(xmm0, mem(rdx, rsi, 1)) // store ( gamma41..gamma51 ) //lea(mem(rdx, rsi, 8), rdx) // rdx += 8*cs_c jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovsd(xmm4, mem(rcx, 0*32)) add(rdi, rcx) vmovsd(xmm6, mem(rcx, 0*32)) add(rdi, rcx) vmovsd(xmm8, mem(rcx, 0*32)) add(rdi, rcx) vmovsd(xmm10, mem(rcx, 0*32)) add(rdi, rcx) vmovsd(xmm12, mem(rcx, 0*32)) add(rdi, rcx) vmovsd(xmm14, mem(rcx, 0*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) // begin I/O on columns 0-3 vunpcklps(ymm6, ymm4, ymm0) vunpcklps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vmovups(xmm0, mem(rcx )) // store ( gamma00..gamma30 ) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vunpcklps(ymm14, ymm12, ymm0) vmovlpd(xmm0, mem(rdx )) // store ( gamma40..gamma50 ) vmovhpd(xmm0, mem(rdx, rsi, 1)) // store ( gamma41..gamma51 ) //lea(mem(rdx, rsi, 8), rdx) // rdx += 8*cs_c label(.SDONE) lea(mem(r12, rdi, 4), r12) // lea(mem(r12, rdi, 2), r12) // c_ii = r12 += 6*rs_c //lea(mem(r14, r8, 4), r14) // //lea(mem(r14, r8, 2), r14) // a_ii = r14 += 6*rs_a mov(var(ps_a4), rax) // load ps_a4 lea(mem(r14, rax, 1), r14) // a_ii = r14 += ps_a4 dec(r11) // ii -= 1; jne(.SLOOP6X8I) // iterate again if ii != 0. label(.SRETURN) end_asm( : // output operands (none) : // input operands [m_iter] "m" (m_iter), [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [ps_a4] "m" (ps_a4), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the m dimension, if they exist. if ( m_left ) { const dim_t nr_cur = 2; const dim_t i_edge = m0 - ( dim_t )m_left; float* restrict cij = c + i_edge*rs_c; //float* restrict ai = a + i_edge*rs_a; //float* restrict ai = a + ( i_edge / 6 ) * ps_a; float* restrict ai = a + m_iter * ps_a; float* restrict bj = b; #if 0 // We add special handling for slightly inflated MR blocksizes // at edge cases, up to a maximum of 9. if ( 6 < m_left ) { sgemmsup_ker_ft ker_fp1 = NULL; sgemmsup_ker_ft ker_fp2 = NULL; dim_t mr1, mr2; if ( m_left == 7 ) { mr1 = 4; mr2 = 3; ker_fp1 = bli_sgemmsup_rv_haswell_asm_4x16; ker_fp2 = bli_sgemmsup_rv_haswell_asm_3x16; } else if ( m_left == 8 ) { mr1 = 4; mr2 = 4; ker_fp1 = bli_sgemmsup_rv_haswell_asm_4x16; ker_fp2 = bli_sgemmsup_rv_haswell_asm_4x16; } else // if ( m_left == 9 ) { mr1 = 4; mr2 = 5; ker_fp1 = bli_sgemmsup_rv_haswell_asm_4x16; ker_fp2 = bli_sgemmsup_rv_haswell_asm_5x16; } ker_fp1 ( conja, conjb, mr1, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += mr1*rs_c0; ai += mr1*rs_a0; ker_fp2 ( conja, conjb, mr2, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); return; } #endif sgemmsup_ker_ft ker_fps[6] = { NULL, bli_sgemmsup_rv_haswell_asm_1x2, bli_sgemmsup_rv_haswell_asm_2x2, bli_sgemmsup_rv_haswell_asm_3x2, bli_sgemmsup_rv_haswell_asm_4x2, bli_sgemmsup_rv_haswell_asm_5x2 }; sgemmsup_ker_ft ker_fp = ker_fps[ m_left ]; ker_fp ( conja, conjb, m_left, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); return; } } blis-0.9.0/kernels/haswell/3/sup/bli_gemmsup_rv_haswell_asm_s6x16n.c000066400000000000000000004334401422157504600254240ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define BLIS_ASM_SYNTAX_ATT #include "bli_x86_asm_macros.h" /* rrr: -------- ------ -------- -------- ------ -------- -------- += ------ ... -------- -------- ------ -------- -------- ------ : -------- ------ : rcr: -------- | | | | -------- -------- | | | | -------- -------- += | | | | ... -------- -------- | | | | -------- -------- | | | | : -------- | | | | : Assumptions: - B is row-stored; - A is row- or column-stored; - m0 and n0 are at most MR and NR, respectively. Therefore, this (r)ow-preferential kernel is well-suited for contiguous (v)ector loads on B and single-element broadcasts from A. NOTE: These kernels explicitly support column-oriented IO, implemented via an in-register transpose. And thus they also support the crr and ccr cases, though only crr is ever utilized (because ccr is handled by transposing the operation and executing rcr, which does not incur the cost of the in-register transpose). crr: | | | | | | | | ------ -------- | | | | | | | | ------ -------- | | | | | | | | += ------ ... -------- | | | | | | | | ------ -------- | | | | | | | | ------ : | | | | | | | | ------ : */ // Prototype reference microkernels. GEMMSUP_KER_PROT( float, s, gemmsup_r_haswell_ref ) void bli_sgemmsup_rv_haswell_asm_6x16n ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { uint64_t m_left = m0 % 6; // First check whether this is a edge case in the m dimension. If so, // dispatch other ?x8m kernels, as needed. if ( m_left ) { float* restrict cij = c; float* restrict bj = b; float* restrict ai = a; #if 1 // We add special handling for slightly inflated MR blocksizes // at edge cases, up to a maximum of 9. if ( 6 < m0 ) { sgemmsup_ker_ft ker_fp1 = NULL; sgemmsup_ker_ft ker_fp2 = NULL; dim_t mr1, mr2; if ( m0 == 7 ) { mr1 = 4; mr2 = 3; ker_fp1 = bli_sgemmsup_rv_haswell_asm_4x16n; ker_fp2 = bli_sgemmsup_rv_haswell_asm_3x16n; } else if ( m0 == 8 ) { mr1 = 4; mr2 = 4; ker_fp1 = bli_sgemmsup_rv_haswell_asm_4x16n; ker_fp2 = bli_sgemmsup_rv_haswell_asm_4x16n; } else // if ( m0 == 9 ) { mr1 = 4; mr2 = 5; ker_fp1 = bli_sgemmsup_rv_haswell_asm_4x16n; ker_fp2 = bli_sgemmsup_rv_haswell_asm_5x16n; } ker_fp1 ( conja, conjb, mr1, n0, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += mr1*rs_c0; ai += mr1*rs_a0; ker_fp2 ( conja, conjb, mr2, n0, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); return; } #endif sgemmsup_ker_ft ker_fps[6] = { NULL, bli_sgemmsup_rv_haswell_asm_1x16n, bli_sgemmsup_rv_haswell_asm_2x16n, bli_sgemmsup_rv_haswell_asm_3x16n, bli_sgemmsup_rv_haswell_asm_4x16n, bli_sgemmsup_rv_haswell_asm_5x16n }; sgemmsup_ker_ft ker_fp = ker_fps[ m_left ]; ker_fp ( conja, conjb, m_left, n0, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); return; } //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t n_iter = n0 / 16; uint64_t n_left = n0 % 16; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // Query the panel stride of B and convert it to units of bytes. uint64_t ps_b = bli_auxinfo_ps_b( data ); uint64_t ps_b4 = ps_b * sizeof( float ); if ( n_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. //mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), r14) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) //lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) // During preamble and loops: // r12 = rcx = c // r14 = rbx = b // read rax from var(a) near beginning of loop // r11 = m dim index ii mov(var(n_iter), r11) // jj = n_iter; label(.SLOOP6X8J) // LOOP OVER jj = [ n_iter ... 1 0 ] #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorps ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorps(ymm4, ymm4, ymm4) vxorps(ymm5, ymm5, ymm5) vxorps(ymm6, ymm6, ymm6) vxorps(ymm7, ymm7, ymm7) vxorps(ymm8, ymm8, ymm8) vxorps(ymm9, ymm9, ymm9) vxorps(ymm10, ymm10, ymm10) vxorps(ymm11, ymm11, ymm11) vxorps(ymm12, ymm12, ymm12) vxorps(ymm13, ymm13, ymm13) vxorps(ymm14, ymm14, ymm14) vxorps(ymm15, ymm15, ymm15) #endif mov(var(a), rax) // load address of a. //mov(r12, rcx) // reset rcx to current utile of c. mov(r14, rbx) // reset rbx to current upanel of b. cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored prefetching on c lea(mem(r12, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(r12, 15*4)) // prefetch c + 0*rs_c prefetch(0, mem(r12, rdi, 1,15*4)) // prefetch c + 1*rs_c prefetch(0, mem(r12, rdi, 2,15*4)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 15*4)) // prefetch c + 3*rs_c prefetch(0, mem(rdx, rdi, 1,15*4)) // prefetch c + 4*rs_c prefetch(0, mem(rdx, rdi, 2,15*4)) // prefetch c + 5*rs_c jmp(.SPOSTPFETCH) // jump to end of prefetching c label(.SCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) lea(mem(rsi, rsi, 2), rcx) // rcx = 3*cs_c; prefetch(0, mem(r12, 5*4)) // prefetch c + 0*cs_c prefetch(0, mem(r12, rsi, 1, 5*4)) // prefetch c + 1*cs_c prefetch(0, mem(r12, rsi, 2, 5*4)) // prefetch c + 2*cs_c prefetch(0, mem(r12, rcx, 1, 5*4)) // prefetch c + 3*cs_c prefetch(0, mem(r12, rsi, 4, 5*4)) // prefetch c + 4*cs_c lea(mem(r12, rsi, 4), rdx) // rdx = c + 4*cs_c; prefetch(0, mem(rdx, rsi, 1, 5*4)) // prefetch c + 5*cs_c prefetch(0, mem(rdx, rsi, 2, 5*4)) // prefetch c + 6*cs_c prefetch(0, mem(rdx, rcx, 1, 5*4)) // prefetch c + 7*cs_c prefetch(0, mem(rdx, rsi, 4, 5*4)) // prefetch c + 8*cs_c lea(mem(r12, rsi, 8), rdx) // rdx = c + 8*cs_c; prefetch(0, mem(rdx, rsi, 1, 5*4)) // prefetch c + 9*cs_c prefetch(0, mem(rdx, rsi, 2, 5*4)) // prefetch c + 10*cs_c prefetch(0, mem(rdx, rcx, 1, 5*4)) // prefetch c + 11*cs_c prefetch(0, mem(rdx, rsi, 4, 5*4)) // prefetch c + 12*cs_c lea(mem(r12, rcx, 4), rdx) // rdx = c + 12*cs_c; prefetch(0, mem(rdx, rsi, 1, 5*4)) // prefetch c + 13*cs_c prefetch(0, mem(rdx, rsi, 2, 5*4)) // prefetch c + 14*cs_c prefetch(0, mem(rdx, rcx, 1, 5*4)) // prefetch c + 15*cs_c label(.SPOSTPFETCH) // done prefetching c #if 1 mov(var(ps_b4), rdx) // load ps_b4 lea(mem(rbx, rdx, 1), rdx) // rdx = a + ps_b4 lea(mem(r10, r10, 2), rcx) // rcx = 3*rs_b; // use rcx, rdx for prefetching lines // from next upanel of b. #else lea(mem(rbx, r8, 8), rdx) // use rdx for prefetching lines lea(mem(rdx, r8, 8), rdx) // from next upanel of b. lea(mem(r10, r10, 2), rcx) // rcx = 3*rs_b; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, 5*8)) #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, r8, 4), ymm2) vbroadcastss(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, r10, 1, 5*8)) #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, r8, 4), ymm2) vbroadcastss(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) // ---------------------------------- iteration 2 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, r10, 2, 5*8)) #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, r8, 4), ymm2) vbroadcastss(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) // ---------------------------------- iteration 3 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, rcx, 1, 5*8)) lea(mem(rdx, r10, 4), rdx) // b_prefetch += 4*rs_b; #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, r8, 4), ymm2) vbroadcastss(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP #if 1 prefetch(0, mem(rdx, 5*8)) add(r10, rdx) #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, r8, 4), ymm2) vbroadcastss(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(r12, rcx) // reset rcx to current utile of c. mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), ymm0) // load alpha and duplicate vbroadcastss(mem(rbx), ymm3) // load beta and duplicate vmulps(ymm0, ymm4, ymm4) // scale by alpha vmulps(ymm0, ymm5, ymm5) vmulps(ymm0, ymm6, ymm6) vmulps(ymm0, ymm7, ymm7) vmulps(ymm0, ymm8, ymm8) vmulps(ymm0, ymm9, ymm9) vmulps(ymm0, ymm10, ymm10) vmulps(ymm0, ymm11, ymm11) vmulps(ymm0, ymm12, ymm12) vmulps(ymm0, ymm13, ymm13) vmulps(ymm0, ymm14, ymm14) vmulps(ymm0, ymm15, ymm15) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; lea(mem(rsi, rsi, 4), rbx) // rbx = 5*cs_c; lea(mem(rax, rsi, 4), rbp) // rbp = 7*cs_c; // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm4) vmovups(ymm4, mem(rcx, 0*32)) vfmadd231ps(mem(rcx, 1*32), ymm3, ymm5) vmovups(ymm5, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm6) vmovups(ymm6, mem(rcx, 0*32)) vfmadd231ps(mem(rcx, 1*32), ymm3, ymm7) vmovups(ymm7, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm8) vmovups(ymm8, mem(rcx, 0*32)) vfmadd231ps(mem(rcx, 1*32), ymm3, ymm9) vmovups(ymm9, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm10) vmovups(ymm10, mem(rcx, 0*32)) vfmadd231ps(mem(rcx, 1*32), ymm3, ymm11) vmovups(ymm11, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm12) vmovups(ymm12, mem(rcx, 0*32)) vfmadd231ps(mem(rcx, 1*32), ymm3, ymm13) vmovups(ymm13, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm14) vmovups(ymm14, mem(rcx, 0*32)) vfmadd231ps(mem(rcx, 1*32), ymm3, ymm15) vmovups(ymm15, mem(rcx, 1*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORED) // begin I/O on columns 0-7 vunpcklps(ymm6, ymm4, ymm0) vunpcklps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx ), xmm3, xmm0) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm0, mem(rcx )) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx, rsi, 1), xmm3, xmm1) vfmadd231ps(mem(rcx, rbx, 1), xmm3, xmm2) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rbx, 1)) // store ( gamma05..gamma35 ) vunpckhps(ymm6, ymm4, ymm0) vunpckhps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx, rsi, 2), xmm3, xmm0) vfmadd231ps(mem(rcx, rax, 2), xmm3, xmm2) vmovups(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, rax, 2)) // store ( gamma06..gamma36 ) vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx, rax, 1), xmm3, xmm1) vfmadd231ps(mem(rcx, rbp, 1), xmm3, xmm2) vmovups(xmm1, mem(rcx, rax, 1)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, rbp, 1)) // store ( gamma07..gamma37 ) lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vunpcklps(ymm14, ymm12, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(mem(rdx ), xmm1, xmm1) vmovhpd(mem(rdx, rsi, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(rdx )) // store ( gamma40..gamma50 ) vmovhpd(xmm0, mem(rdx, rsi, 1)) // store ( gamma41..gamma51 ) vmovlpd(mem(rdx, rsi, 4), xmm1, xmm1) vmovhpd(mem(rdx, rbx, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm2) vmovlpd(xmm2, mem(rdx, rsi, 4)) // store ( gamma44..gamma54 ) vmovhpd(xmm2, mem(rdx, rbx, 1)) // store ( gamma45..gamma55 ) vunpckhps(ymm14, ymm12, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(mem(rdx, rsi, 2), xmm1, xmm1) vmovhpd(mem(rdx, rax, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(rdx, rsi, 2)) // store ( gamma42..gamma52 ) vmovhpd(xmm0, mem(rdx, rax, 1)) // store ( gamma43..gamma53 ) vmovlpd(mem(rdx, rax, 2), xmm1, xmm1) vmovhpd(mem(rdx, rbp, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm2) vmovlpd(xmm2, mem(rdx, rax, 2)) // store ( gamma46..gamma56 ) vmovhpd(xmm2, mem(rdx, rbp, 1)) // store ( gamma47..gamma57 ) lea(mem(rdx, rsi, 8), rdx) // rdx += 8*cs_c // begin I/O on columns 8-15 vunpcklps(ymm7, ymm5, ymm0) vunpcklps(ymm11, ymm9, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx ), xmm3, xmm0) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm0, mem(rcx )) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx, rsi, 1), xmm3, xmm1) vfmadd231ps(mem(rcx, rbx, 1), xmm3, xmm2) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rbx, 1)) // store ( gamma05..gamma35 ) vunpckhps(ymm7, ymm5, ymm0) vunpckhps(ymm11, ymm9, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx, rsi, 2), xmm3, xmm0) vfmadd231ps(mem(rcx, rax, 2), xmm3, xmm2) vmovups(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, rax, 2)) // store ( gamma06..gamma36 ) vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx, rax, 1), xmm3, xmm1) vfmadd231ps(mem(rcx, rbp, 1), xmm3, xmm2) vmovups(xmm1, mem(rcx, rax, 1)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, rbp, 1)) // store ( gamma07..gamma37 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vunpcklps(ymm15, ymm13, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(mem(rdx ), xmm1, xmm1) vmovhpd(mem(rdx, rsi, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(rdx )) // store ( gamma40..gamma50 ) vmovhpd(xmm0, mem(rdx, rsi, 1)) // store ( gamma41..gamma51 ) vmovlpd(mem(rdx, rsi, 4), xmm1, xmm1) vmovhpd(mem(rdx, rbx, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm2) vmovlpd(xmm2, mem(rdx, rsi, 4)) // store ( gamma44..gamma54 ) vmovhpd(xmm2, mem(rdx, rbx, 1)) // store ( gamma45..gamma55 ) vunpckhps(ymm15, ymm13, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(mem(rdx, rsi, 2), xmm1, xmm1) vmovhpd(mem(rdx, rax, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(rdx, rsi, 2)) // store ( gamma42..gamma52 ) vmovhpd(xmm0, mem(rdx, rax, 1)) // store ( gamma43..gamma53 ) vmovlpd(mem(rdx, rax, 2), xmm1, xmm1) vmovhpd(mem(rdx, rbp, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm2) vmovlpd(xmm2, mem(rdx, rax, 2)) // store ( gamma46..gamma56 ) vmovhpd(xmm2, mem(rdx, rbp, 1)) // store ( gamma47..gamma57 ) //lea(mem(rdx, rsi, 8), rdx) // rdx += 8*cs_c jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovups(ymm4, mem(rcx, 0*32)) vmovups(ymm5, mem(rcx, 1*32)) add(rdi, rcx) vmovups(ymm6, mem(rcx, 0*32)) vmovups(ymm7, mem(rcx, 1*32)) add(rdi, rcx) vmovups(ymm8, mem(rcx, 0*32)) vmovups(ymm9, mem(rcx, 1*32)) add(rdi, rcx) vmovups(ymm10, mem(rcx, 0*32)) vmovups(ymm11, mem(rcx, 1*32)) add(rdi, rcx) vmovups(ymm12, mem(rcx, 0*32)) vmovups(ymm13, mem(rcx, 1*32)) add(rdi, rcx) vmovups(ymm14, mem(rcx, 0*32)) vmovups(ymm15, mem(rcx, 1*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) // begin I/O on columns 0-7 vunpcklps(ymm6, ymm4, ymm0) vunpcklps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx )) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rbx, 1)) // store ( gamma05..gamma35 ) vunpckhps(ymm6, ymm4, ymm0) vunpckhps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, rax, 2)) // store ( gamma06..gamma36 ) vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx, rax, 1)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, rbp, 1)) // store ( gamma07..gamma37 ) lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vunpcklps(ymm14, ymm12, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(xmm0, mem(rdx )) // store ( gamma40..gamma50 ) vmovhpd(xmm0, mem(rdx, rsi, 1)) // store ( gamma41..gamma51 ) vmovlpd(xmm2, mem(rdx, rsi, 4)) // store ( gamma44..gamma54 ) vmovhpd(xmm2, mem(rdx, rbx, 1)) // store ( gamma45..gamma55 ) vunpckhps(ymm14, ymm12, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(xmm0, mem(rdx, rsi, 2)) // store ( gamma42..gamma52 ) vmovhpd(xmm0, mem(rdx, rax, 1)) // store ( gamma43..gamma53 ) vmovlpd(xmm2, mem(rdx, rax, 2)) // store ( gamma46..gamma56 ) vmovhpd(xmm2, mem(rdx, rbp, 1)) // store ( gamma47..gamma57 ) lea(mem(rdx, rsi, 8), rdx) // rdx += 8*cs_c // begin I/O on columns 8-15 vunpcklps(ymm7, ymm5, ymm0) vunpcklps(ymm11, ymm9, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx )) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rbx, 1)) // store ( gamma05..gamma35 ) vunpckhps(ymm7, ymm5, ymm0) vunpckhps(ymm11, ymm9, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, rax, 2)) // store ( gamma06..gamma36 ) vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx, rax, 1)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, rbp, 1)) // store ( gamma07..gamma37 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vunpcklps(ymm15, ymm13, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(xmm0, mem(rdx )) // store ( gamma40..gamma50 ) vmovhpd(xmm0, mem(rdx, rsi, 1)) // store ( gamma41..gamma51 ) vmovlpd(xmm2, mem(rdx, rsi, 4)) // store ( gamma44..gamma54 ) vmovhpd(xmm2, mem(rdx, rbx, 1)) // store ( gamma45..gamma55 ) vunpckhps(ymm15, ymm13, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(xmm0, mem(rdx, rsi, 2)) // store ( gamma42..gamma52 ) vmovhpd(xmm0, mem(rdx, rax, 1)) // store ( gamma43..gamma53 ) vmovlpd(xmm2, mem(rdx, rax, 2)) // store ( gamma46..gamma56 ) vmovhpd(xmm2, mem(rdx, rbp, 1)) // store ( gamma47..gamma57 ) //lea(mem(rdx, rsi, 8), rdx) // rdx += 8*cs_c label(.SDONE) lea(mem(r12, rsi, 8), r12) // lea(mem(r12, rsi, 8), r12) // c_jj = r12 += 16*cs_c //add(imm(8*8), r14) // b_jj = r14 += 8*cs_b mov(var(ps_b4), rbx) // load ps_b4 lea(mem(r14, rbx, 1), r14) // b_jj = r14 += ps_b4 dec(r11) // jj -= 1; jne(.SLOOP6X8J) // iterate again if jj != 0. label(.SRETURN) end_asm( : // output operands (none) : // input operands [n_iter] "m" (n_iter), [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [ps_b4] "m" (ps_b4), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the m dimension, if they exist. if ( n_left ) { const dim_t mr_cur = 6; const dim_t j_edge = n0 - ( dim_t )n_left; float* restrict cij = c + j_edge*cs_c; float* restrict ai = a; //float* restrict bj = b + j_edge*cs_b; //float* restrict bj = b + ( j_edge / 8 ) * ps_b; float* restrict bj = b + n_iter * ps_b; if ( 12 <= n_left ) { const dim_t nr_cur = 12; bli_sgemmsup_rv_haswell_asm_6x12 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 8 <= n_left ) { const dim_t nr_cur = 8; bli_sgemmsup_rv_haswell_asm_6x8 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 6 <= n_left ) { const dim_t nr_cur = 6; bli_sgemmsup_rv_haswell_asm_6x6 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 4 <= n_left ) { const dim_t nr_cur = 4; bli_sgemmsup_rv_haswell_asm_6x4 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 2 <= n_left ) { const dim_t nr_cur = 2; bli_sgemmsup_rv_haswell_asm_6x2 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 1 == n_left ) { #if 1 const dim_t nr_cur = 1; bli_sgemmsup_r_haswell_ref_6x1 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); #else bli_sgemv_ex ( BLIS_NO_TRANSPOSE, conjb, m0, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, beta, cij, rs_c0, cntx, NULL ); #endif } } } void bli_sgemmsup_rv_haswell_asm_5x16n ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t n_iter = n0 / 16; uint64_t n_left = n0 % 16; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // Query the panel stride of B and convert it to units of bytes. uint64_t ps_b = bli_auxinfo_ps_b( data ); uint64_t ps_b4 = ps_b * sizeof( float ); if ( n_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. //mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), r14) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) //lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) // During preamble and loops: // r12 = rcx = c // r14 = rbx = b // read rax from var(a) near beginning of loop // r11 = m dim index ii mov(var(n_iter), r11) // jj = n_iter; label(.SLOOP6X8J) // LOOP OVER jj = [ n_iter ... 1 0 ] #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorps ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorps(ymm4, ymm4, ymm4) vxorps(ymm5, ymm5, ymm5) vxorps(ymm6, ymm6, ymm6) vxorps(ymm7, ymm7, ymm7) vxorps(ymm8, ymm8, ymm8) vxorps(ymm9, ymm9, ymm9) vxorps(ymm10, ymm10, ymm10) vxorps(ymm11, ymm11, ymm11) vxorps(ymm12, ymm12, ymm12) vxorps(ymm13, ymm13, ymm13) #endif mov(var(a), rax) // load address of a. //mov(r12, rcx) // reset rcx to current utile of c. mov(r14, rbx) // reset rbx to current upanel of b. cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored prefetching on c lea(mem(r12, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(r12, 15*4)) // prefetch c + 0*rs_c prefetch(0, mem(r12, rdi, 1,15*4)) // prefetch c + 1*rs_c prefetch(0, mem(r12, rdi, 2,15*4)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 15*4)) // prefetch c + 3*rs_c prefetch(0, mem(rdx, rdi, 1,15*4)) // prefetch c + 4*rs_c jmp(.SPOSTPFETCH) // jump to end of prefetching c label(.SCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) lea(mem(rsi, rsi, 2), rcx) // rcx = 3*cs_c; prefetch(0, mem(r12, 4*4)) // prefetch c + 0*cs_c prefetch(0, mem(r12, rsi, 1, 4*4)) // prefetch c + 1*cs_c prefetch(0, mem(r12, rsi, 2, 4*4)) // prefetch c + 2*cs_c prefetch(0, mem(r12, rcx, 1, 4*4)) // prefetch c + 3*cs_c prefetch(0, mem(r12, rsi, 4, 4*4)) // prefetch c + 4*cs_c lea(mem(r12, rsi, 4), rdx) // rdx = c + 4*cs_c; prefetch(0, mem(rdx, rsi, 1, 4*4)) // prefetch c + 5*cs_c prefetch(0, mem(rdx, rsi, 2, 4*4)) // prefetch c + 6*cs_c prefetch(0, mem(rdx, rcx, 1, 4*4)) // prefetch c + 7*cs_c prefetch(0, mem(rdx, rsi, 4, 4*4)) // prefetch c + 8*cs_c lea(mem(r12, rsi, 8), rdx) // rdx = c + 8*cs_c; prefetch(0, mem(rdx, rsi, 1, 4*4)) // prefetch c + 9*cs_c prefetch(0, mem(rdx, rsi, 2, 4*4)) // prefetch c + 10*cs_c prefetch(0, mem(rdx, rcx, 1, 4*4)) // prefetch c + 11*cs_c prefetch(0, mem(rdx, rsi, 4, 4*4)) // prefetch c + 12*cs_c lea(mem(r12, rcx, 4), rdx) // rdx = c + 12*cs_c; prefetch(0, mem(rdx, rsi, 1, 4*4)) // prefetch c + 13*cs_c prefetch(0, mem(rdx, rsi, 2, 4*4)) // prefetch c + 14*cs_c prefetch(0, mem(rdx, rcx, 1, 4*4)) // prefetch c + 15*cs_c label(.SPOSTPFETCH) // done prefetching c #if 1 mov(var(ps_b4), rdx) // load ps_b4 lea(mem(rbx, rdx, 1), rdx) // rdx = a + ps_b4 lea(mem(r10, r10, 2), rcx) // rcx = 3*rs_b; // use rcx, rdx for prefetching lines // from next upanel of b. #else lea(mem(rbx, r8, 8), rdx) // use rdx for prefetching lines lea(mem(rdx, r8, 8), rdx) // from next upanel of b. lea(mem(r10, r10, 2), rcx) // rcx = 3*rs_b; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, 5*8)) #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, r10, 1, 5*8)) #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) // ---------------------------------- iteration 2 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, r10, 2, 5*8)) #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) // ---------------------------------- iteration 3 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, rcx, 1, 5*8)) lea(mem(rdx, r10, 4), rdx) // b_prefetch += 4*rs_b; #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP #if 1 prefetch(0, mem(rdx, 5*8)) add(r10, rdx) #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(r12, rcx) // reset rcx to current utile of c. mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), ymm0) // load alpha and duplicate vbroadcastss(mem(rbx), ymm3) // load beta and duplicate vmulps(ymm0, ymm4, ymm4) // scale by alpha vmulps(ymm0, ymm5, ymm5) vmulps(ymm0, ymm6, ymm6) vmulps(ymm0, ymm7, ymm7) vmulps(ymm0, ymm8, ymm8) vmulps(ymm0, ymm9, ymm9) vmulps(ymm0, ymm10, ymm10) vmulps(ymm0, ymm11, ymm11) vmulps(ymm0, ymm12, ymm12) vmulps(ymm0, ymm13, ymm13) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; lea(mem(rsi, rsi, 4), rbx) // rbx = 5*cs_c; lea(mem(rax, rsi, 4), rbp) // rbp = 7*cs_c; // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm4) vmovups(ymm4, mem(rcx, 0*32)) vfmadd231ps(mem(rcx, 1*32), ymm3, ymm5) vmovups(ymm5, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm6) vmovups(ymm6, mem(rcx, 0*32)) vfmadd231ps(mem(rcx, 1*32), ymm3, ymm7) vmovups(ymm7, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm8) vmovups(ymm8, mem(rcx, 0*32)) vfmadd231ps(mem(rcx, 1*32), ymm3, ymm9) vmovups(ymm9, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm10) vmovups(ymm10, mem(rcx, 0*32)) vfmadd231ps(mem(rcx, 1*32), ymm3, ymm11) vmovups(ymm11, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm12) vmovups(ymm12, mem(rcx, 0*32)) vfmadd231ps(mem(rcx, 1*32), ymm3, ymm13) vmovups(ymm13, mem(rcx, 1*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORED) // begin I/O on columns 0-7 vunpcklps(ymm6, ymm4, ymm0) vunpcklps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx ), xmm3, xmm0) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm0, mem(rcx )) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx, rsi, 1), xmm3, xmm1) vfmadd231ps(mem(rcx, rbx, 1), xmm3, xmm2) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rbx, 1)) // store ( gamma05..gamma35 ) vunpckhps(ymm6, ymm4, ymm0) vunpckhps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx, rsi, 2), xmm3, xmm0) vfmadd231ps(mem(rcx, rax, 2), xmm3, xmm2) vmovups(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, rax, 2)) // store ( gamma06..gamma36 ) vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx, rax, 1), xmm3, xmm1) vfmadd231ps(mem(rcx, rbp, 1), xmm3, xmm2) vmovups(xmm1, mem(rcx, rax, 1)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, rbp, 1)) // store ( gamma07..gamma37 ) lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vmovups(ymm12, ymm0) vextractf128(imm(0x1), ymm0, xmm8) vpermilps(imm(0xe4), xmm0, xmm2) vpermilps(imm(0x39), xmm0, xmm4) vmovss(mem(rdx ), xmm1) vmovss(mem(rdx, rsi, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rdx )) // store ( gamma40 ) vmovss(xmm4, mem(rdx, rsi, 1)) // store ( gamma41 ) vpermilps(imm(0x4e), xmm0, xmm2) vpermilps(imm(0x93), xmm0, xmm4) vmovss(mem(rdx, rsi, 2), xmm1) vmovss(mem(rdx, rax, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rdx, rsi, 2)) // store ( gamma42 ) vmovss(xmm4, mem(rdx, rax, 1)) // store ( gamma43 ) vpermilps(imm(0xe4), xmm8, xmm2) vpermilps(imm(0x39), xmm8, xmm4) vmovss(mem(rdx, rsi, 4), xmm1) vmovss(mem(rdx, rbx, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rdx, rsi, 4)) // store ( gamma44 ) vmovss(xmm4, mem(rdx, rbx, 1)) // store ( gamma45 ) vpermilps(imm(0x4e), xmm8, xmm2) vpermilps(imm(0x93), xmm8, xmm4) vmovss(mem(rdx, rax, 2), xmm1) vmovss(mem(rdx, rbp, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rdx, rax, 2)) // store ( gamma46 ) vmovss(xmm4, mem(rdx, rbp, 1)) // store ( gamma47 ) lea(mem(rdx, rsi, 8), rdx) // rdx += 8*cs_c // begin I/O on columns 8-15 vunpcklps(ymm7, ymm5, ymm0) vunpcklps(ymm11, ymm9, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx ), xmm3, xmm0) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm0, mem(rcx )) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx, rsi, 1), xmm3, xmm1) vfmadd231ps(mem(rcx, rbx, 1), xmm3, xmm2) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rbx, 1)) // store ( gamma05..gamma35 ) vunpckhps(ymm7, ymm5, ymm0) vunpckhps(ymm11, ymm9, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx, rsi, 2), xmm3, xmm0) vfmadd231ps(mem(rcx, rax, 2), xmm3, xmm2) vmovups(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, rax, 2)) // store ( gamma06..gamma36 ) vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx, rax, 1), xmm3, xmm1) vfmadd231ps(mem(rcx, rbp, 1), xmm3, xmm2) vmovups(xmm1, mem(rcx, rax, 1)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, rbp, 1)) // store ( gamma07..gamma37 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vmovups(ymm13, ymm0) vextractf128(imm(0x1), ymm0, xmm8) vpermilps(imm(0xe4), xmm0, xmm2) vpermilps(imm(0x39), xmm0, xmm4) vmovss(mem(rdx ), xmm1) vmovss(mem(rdx, rsi, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rdx )) // store ( gamma40 ) vmovss(xmm4, mem(rdx, rsi, 1)) // store ( gamma41 ) vpermilps(imm(0x4e), xmm0, xmm2) vpermilps(imm(0x93), xmm0, xmm4) vmovss(mem(rdx, rsi, 2), xmm1) vmovss(mem(rdx, rax, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rdx, rsi, 2)) // store ( gamma42 ) vmovss(xmm4, mem(rdx, rax, 1)) // store ( gamma43 ) vpermilps(imm(0xe4), xmm8, xmm2) vpermilps(imm(0x39), xmm8, xmm4) vmovss(mem(rdx, rsi, 4), xmm1) vmovss(mem(rdx, rbx, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rdx, rsi, 4)) // store ( gamma44 ) vmovss(xmm4, mem(rdx, rbx, 1)) // store ( gamma45 ) vpermilps(imm(0x4e), xmm8, xmm2) vpermilps(imm(0x93), xmm8, xmm4) vmovss(mem(rdx, rax, 2), xmm1) vmovss(mem(rdx, rbp, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rdx, rax, 2)) // store ( gamma46 ) vmovss(xmm4, mem(rdx, rbp, 1)) // store ( gamma47 ) //lea(mem(rdx, rsi, 8), rdx) // rdx += 8*cs_c jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovups(ymm4, mem(rcx, 0*32)) vmovups(ymm5, mem(rcx, 1*32)) add(rdi, rcx) vmovups(ymm6, mem(rcx, 0*32)) vmovups(ymm7, mem(rcx, 1*32)) add(rdi, rcx) vmovups(ymm8, mem(rcx, 0*32)) vmovups(ymm9, mem(rcx, 1*32)) add(rdi, rcx) vmovups(ymm10, mem(rcx, 0*32)) vmovups(ymm11, mem(rcx, 1*32)) add(rdi, rcx) vmovups(ymm12, mem(rcx, 0*32)) vmovups(ymm13, mem(rcx, 1*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) // begin I/O on columns 0-7 vunpcklps(ymm6, ymm4, ymm0) vunpcklps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx )) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rbx, 1)) // store ( gamma05..gamma35 ) vunpckhps(ymm6, ymm4, ymm0) vunpckhps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, rax, 2)) // store ( gamma06..gamma36 ) vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx, rax, 1)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, rbp, 1)) // store ( gamma07..gamma37 ) lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vmovups(ymm12, ymm0) vextractf128(imm(0x1), ymm0, xmm8) vpermilps(imm(0xe4), xmm0, xmm2) vpermilps(imm(0x39), xmm0, xmm4) vmovss(xmm2, mem(rdx )) // store ( gamma40 ) vmovss(xmm4, mem(rdx, rsi, 1)) // store ( gamma41 ) vpermilps(imm(0x4e), xmm0, xmm2) vpermilps(imm(0x93), xmm0, xmm4) vmovss(xmm2, mem(rdx, rsi, 2)) // store ( gamma42 ) vmovss(xmm4, mem(rdx, rax, 1)) // store ( gamma43 ) vpermilps(imm(0xe4), xmm8, xmm2) vpermilps(imm(0x39), xmm8, xmm4) vmovss(xmm2, mem(rdx, rsi, 4)) // store ( gamma44 ) vmovss(xmm4, mem(rdx, rbx, 1)) // store ( gamma45 ) vpermilps(imm(0x4e), xmm8, xmm2) vpermilps(imm(0x93), xmm8, xmm4) vmovss(xmm2, mem(rdx, rax, 2)) // store ( gamma46 ) vmovss(xmm4, mem(rdx, rbp, 1)) // store ( gamma47 ) lea(mem(rdx, rsi, 8), rdx) // rdx += 8*cs_c // begin I/O on columns 8-15 vunpcklps(ymm7, ymm5, ymm0) vunpcklps(ymm11, ymm9, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx )) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rbx, 1)) // store ( gamma05..gamma35 ) vunpckhps(ymm7, ymm5, ymm0) vunpckhps(ymm11, ymm9, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, rax, 2)) // store ( gamma06..gamma36 ) vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx, rax, 1)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, rbp, 1)) // store ( gamma07..gamma37 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vmovups(ymm13, ymm0) vextractf128(imm(0x1), ymm0, xmm8) vpermilps(imm(0xe4), xmm0, xmm2) vpermilps(imm(0x39), xmm0, xmm4) vmovss(xmm2, mem(rdx )) // store ( gamma40 ) vmovss(xmm4, mem(rdx, rsi, 1)) // store ( gamma41 ) vpermilps(imm(0x4e), xmm0, xmm2) vpermilps(imm(0x93), xmm0, xmm4) vmovss(xmm2, mem(rdx, rsi, 2)) // store ( gamma42 ) vmovss(xmm4, mem(rdx, rax, 1)) // store ( gamma43 ) vpermilps(imm(0xe4), xmm8, xmm2) vpermilps(imm(0x39), xmm8, xmm4) vmovss(xmm2, mem(rdx, rsi, 4)) // store ( gamma44 ) vmovss(xmm4, mem(rdx, rbx, 1)) // store ( gamma45 ) vpermilps(imm(0x4e), xmm8, xmm2) vpermilps(imm(0x93), xmm8, xmm4) vmovss(xmm2, mem(rdx, rax, 2)) // store ( gamma46 ) vmovss(xmm4, mem(rdx, rbp, 1)) // store ( gamma47 ) //lea(mem(rdx, rsi, 8), rdx) // rdx += 8*cs_c label(.SDONE) lea(mem(r12, rsi, 8), r12) // lea(mem(r12, rsi, 8), r12) // c_jj = r12 += 16*cs_c //add(imm(8*8), r14) // b_jj = r14 += 8*cs_b mov(var(ps_b4), rbx) // load ps_b4 lea(mem(r14, rbx, 1), r14) // b_jj = r14 += ps_b4 dec(r11) // jj -= 1; jne(.SLOOP6X8J) // iterate again if jj != 0. label(.SRETURN) end_asm( : // output operands (none) : // input operands [n_iter] "m" (n_iter), [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [ps_b4] "m" (ps_b4), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the m dimension, if they exist. if ( n_left ) { const dim_t mr_cur = 5; const dim_t j_edge = n0 - ( dim_t )n_left; float* restrict cij = c + j_edge*cs_c; float* restrict ai = a; //float* restrict bj = b + j_edge*cs_b; //float* restrict bj = b + ( j_edge / 8 ) * ps_b; float* restrict bj = b + n_iter * ps_b; if ( 12 <= n_left ) { const dim_t nr_cur = 12; bli_sgemmsup_rv_haswell_asm_5x12 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 8 <= n_left ) { const dim_t nr_cur = 8; bli_sgemmsup_rv_haswell_asm_5x8 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 6 <= n_left ) { const dim_t nr_cur = 6; bli_sgemmsup_rv_haswell_asm_5x6 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 4 <= n_left ) { const dim_t nr_cur = 4; bli_sgemmsup_rv_haswell_asm_5x4 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 2 <= n_left ) { const dim_t nr_cur = 2; bli_sgemmsup_rv_haswell_asm_5x2 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 1 == n_left ) { #if 1 const dim_t nr_cur = 1; bli_sgemmsup_r_haswell_ref_5x1 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); #else bli_sgemv_ex ( BLIS_NO_TRANSPOSE, conjb, m0, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, beta, cij, rs_c0, cntx, NULL ); #endif } } } void bli_sgemmsup_rv_haswell_asm_4x16n ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t n_iter = n0 / 16; uint64_t n_left = n0 % 16; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // Query the panel stride of B and convert it to units of bytes. uint64_t ps_b = bli_auxinfo_ps_b( data ); uint64_t ps_b4 = ps_b * sizeof( float ); if ( n_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. //mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), r14) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) //lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) // During preamble and loops: // r12 = rcx = c // r14 = rbx = b // read rax from var(a) near beginning of loop // r11 = m dim index ii mov(var(n_iter), r11) // jj = n_iter; label(.SLOOP6X8J) // LOOP OVER jj = [ n_iter ... 1 0 ] #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorps ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorps(ymm4, ymm4, ymm4) vxorps(ymm5, ymm5, ymm5) vxorps(ymm6, ymm6, ymm6) vxorps(ymm7, ymm7, ymm7) vxorps(ymm8, ymm8, ymm8) vxorps(ymm9, ymm9, ymm9) vxorps(ymm10, ymm10, ymm10) vxorps(ymm11, ymm11, ymm11) #endif mov(var(a), rax) // load address of a. //mov(r12, rcx) // reset rcx to current utile of c. mov(r14, rbx) // reset rbx to current upanel of b. cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored prefetching on c lea(mem(r12, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(r12, 15*4)) // prefetch c + 0*rs_c prefetch(0, mem(r12, rdi, 1,15*4)) // prefetch c + 1*rs_c prefetch(0, mem(r12, rdi, 2,15*4)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 15*4)) // prefetch c + 3*rs_c jmp(.SPOSTPFETCH) // jump to end of prefetching c label(.SCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) lea(mem(rsi, rsi, 2), rcx) // rcx = 3*cs_c; prefetch(0, mem(r12, 3*4)) // prefetch c + 0*cs_c prefetch(0, mem(r12, rsi, 1, 3*4)) // prefetch c + 1*cs_c prefetch(0, mem(r12, rsi, 2, 3*4)) // prefetch c + 2*cs_c prefetch(0, mem(r12, rcx, 1, 3*4)) // prefetch c + 3*cs_c prefetch(0, mem(r12, rsi, 4, 3*4)) // prefetch c + 4*cs_c lea(mem(r12, rsi, 4), rdx) // rdx = c + 4*cs_c; prefetch(0, mem(rdx, rsi, 1, 3*4)) // prefetch c + 5*cs_c prefetch(0, mem(rdx, rsi, 2, 3*4)) // prefetch c + 6*cs_c prefetch(0, mem(rdx, rcx, 1, 3*4)) // prefetch c + 7*cs_c prefetch(0, mem(rdx, rsi, 4, 3*4)) // prefetch c + 8*cs_c lea(mem(r12, rsi, 8), rdx) // rdx = c + 8*cs_c; prefetch(0, mem(rdx, rsi, 1, 3*4)) // prefetch c + 9*cs_c prefetch(0, mem(rdx, rsi, 2, 3*4)) // prefetch c + 10*cs_c prefetch(0, mem(rdx, rcx, 1, 3*4)) // prefetch c + 11*cs_c prefetch(0, mem(rdx, rsi, 4, 3*4)) // prefetch c + 12*cs_c lea(mem(r12, rcx, 4), rdx) // rdx = c + 12*cs_c; prefetch(0, mem(rdx, rsi, 1, 3*4)) // prefetch c + 13*cs_c prefetch(0, mem(rdx, rsi, 2, 3*4)) // prefetch c + 14*cs_c prefetch(0, mem(rdx, rcx, 1, 3*4)) // prefetch c + 15*cs_c label(.SPOSTPFETCH) // done prefetching c #if 1 mov(var(ps_b4), rdx) // load ps_b4 lea(mem(rbx, rdx, 1), rdx) // rdx = a + ps_b4 lea(mem(r10, r10, 2), rcx) // rcx = 3*rs_b; // use rcx, rdx for prefetching lines // from next upanel of b. #else lea(mem(rbx, r8, 8), rdx) // use rdx for prefetching lines lea(mem(rdx, r8, 8), rdx) // from next upanel of b. lea(mem(r10, r10, 2), rcx) // rcx = 3*rs_b; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, 5*8)) #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, r10, 1, 5*8)) #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) // ---------------------------------- iteration 2 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, r10, 2, 5*8)) #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) // ---------------------------------- iteration 3 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, rcx, 1, 5*8)) lea(mem(rdx, r10, 4), rdx) // b_prefetch += 4*rs_b; #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP #if 1 prefetch(0, mem(rdx, 5*8)) add(r10, rdx) #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(r12, rcx) // reset rcx to current utile of c. mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), ymm0) // load alpha and duplicate vbroadcastss(mem(rbx), ymm3) // load beta and duplicate vmulps(ymm0, ymm4, ymm4) // scale by alpha vmulps(ymm0, ymm5, ymm5) vmulps(ymm0, ymm6, ymm6) vmulps(ymm0, ymm7, ymm7) vmulps(ymm0, ymm8, ymm8) vmulps(ymm0, ymm9, ymm9) vmulps(ymm0, ymm10, ymm10) vmulps(ymm0, ymm11, ymm11) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; //lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; lea(mem(rsi, rsi, 4), rbx) // rbx = 5*cs_c; lea(mem(rax, rsi, 4), rbp) // rbp = 7*cs_c; // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm4) vmovups(ymm4, mem(rcx, 0*32)) vfmadd231ps(mem(rcx, 1*32), ymm3, ymm5) vmovups(ymm5, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm6) vmovups(ymm6, mem(rcx, 0*32)) vfmadd231ps(mem(rcx, 1*32), ymm3, ymm7) vmovups(ymm7, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm8) vmovups(ymm8, mem(rcx, 0*32)) vfmadd231ps(mem(rcx, 1*32), ymm3, ymm9) vmovups(ymm9, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm10) vmovups(ymm10, mem(rcx, 0*32)) vfmadd231ps(mem(rcx, 1*32), ymm3, ymm11) vmovups(ymm11, mem(rcx, 1*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORED) // begin I/O on columns 0-7 vunpcklps(ymm6, ymm4, ymm0) vunpcklps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx ), xmm3, xmm0) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm0, mem(rcx )) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx, rsi, 1), xmm3, xmm1) vfmadd231ps(mem(rcx, rbx, 1), xmm3, xmm2) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rbx, 1)) // store ( gamma05..gamma35 ) vunpckhps(ymm6, ymm4, ymm0) vunpckhps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx, rsi, 2), xmm3, xmm0) vfmadd231ps(mem(rcx, rax, 2), xmm3, xmm2) vmovups(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, rax, 2)) // store ( gamma06..gamma36 ) vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx, rax, 1), xmm3, xmm1) vfmadd231ps(mem(rcx, rbp, 1), xmm3, xmm2) vmovups(xmm1, mem(rcx, rax, 1)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, rbp, 1)) // store ( gamma07..gamma37 ) lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c // begin I/O on columns 8-15 vunpcklps(ymm7, ymm5, ymm0) vunpcklps(ymm11, ymm9, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx ), xmm3, xmm0) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm0, mem(rcx )) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx, rsi, 1), xmm3, xmm1) vfmadd231ps(mem(rcx, rbx, 1), xmm3, xmm2) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rbx, 1)) // store ( gamma05..gamma35 ) vunpckhps(ymm7, ymm5, ymm0) vunpckhps(ymm11, ymm9, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx, rsi, 2), xmm3, xmm0) vfmadd231ps(mem(rcx, rax, 2), xmm3, xmm2) vmovups(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, rax, 2)) // store ( gamma06..gamma36 ) vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx, rax, 1), xmm3, xmm1) vfmadd231ps(mem(rcx, rbp, 1), xmm3, xmm2) vmovups(xmm1, mem(rcx, rax, 1)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, rbp, 1)) // store ( gamma07..gamma37 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovups(ymm4, mem(rcx, 0*32)) vmovups(ymm5, mem(rcx, 1*32)) add(rdi, rcx) vmovups(ymm6, mem(rcx, 0*32)) vmovups(ymm7, mem(rcx, 1*32)) add(rdi, rcx) vmovups(ymm8, mem(rcx, 0*32)) vmovups(ymm9, mem(rcx, 1*32)) add(rdi, rcx) vmovups(ymm10, mem(rcx, 0*32)) vmovups(ymm11, mem(rcx, 1*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) // begin I/O on columns 0-7 vunpcklps(ymm6, ymm4, ymm0) vunpcklps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx )) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rbx, 1)) // store ( gamma05..gamma35 ) vunpckhps(ymm6, ymm4, ymm0) vunpckhps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, rax, 2)) // store ( gamma06..gamma36 ) vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx, rax, 1)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, rbp, 1)) // store ( gamma07..gamma37 ) lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c // begin I/O on columns 8-15 vunpcklps(ymm7, ymm5, ymm0) vunpcklps(ymm11, ymm9, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx )) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rbx, 1)) // store ( gamma05..gamma35 ) vunpckhps(ymm7, ymm5, ymm0) vunpckhps(ymm11, ymm9, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, rax, 2)) // store ( gamma06..gamma36 ) vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx, rax, 1)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, rbp, 1)) // store ( gamma07..gamma37 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c label(.SDONE) lea(mem(r12, rsi, 8), r12) // lea(mem(r12, rsi, 8), r12) // c_jj = r12 += 16*cs_c //add(imm(8*8), r14) // b_jj = r14 += 8*cs_b mov(var(ps_b4), rbx) // load ps_b4 lea(mem(r14, rbx, 1), r14) // b_jj = r14 += ps_b4 dec(r11) // jj -= 1; jne(.SLOOP6X8J) // iterate again if jj != 0. label(.SRETURN) end_asm( : // output operands (none) : // input operands [n_iter] "m" (n_iter), [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [ps_b4] "m" (ps_b4), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the m dimension, if they exist. if ( n_left ) { const dim_t mr_cur = 4; const dim_t j_edge = n0 - ( dim_t )n_left; float* restrict cij = c + j_edge*cs_c; float* restrict ai = a; //float* restrict bj = b + j_edge*cs_b; //float* restrict bj = b + ( j_edge / 8 ) * ps_b; float* restrict bj = b + n_iter * ps_b; if ( 12 <= n_left ) { const dim_t nr_cur = 12; bli_sgemmsup_rv_haswell_asm_4x12 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 8 <= n_left ) { const dim_t nr_cur = 8; bli_sgemmsup_rv_haswell_asm_4x8 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 6 <= n_left ) { const dim_t nr_cur = 6; bli_sgemmsup_rv_haswell_asm_4x6 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 4 <= n_left ) { const dim_t nr_cur = 4; bli_sgemmsup_rv_haswell_asm_4x4 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 2 <= n_left ) { const dim_t nr_cur = 2; bli_sgemmsup_rv_haswell_asm_4x2 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 1 == n_left ) { #if 1 const dim_t nr_cur = 1; bli_sgemmsup_r_haswell_ref_4x1 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); #else bli_dgemv_ex ( BLIS_NO_TRANSPOSE, conjb, m0, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, beta, cij, rs_c0, cntx, NULL ); #endif } } } void bli_sgemmsup_rv_haswell_asm_3x16n ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t n_iter = n0 / 16; uint64_t n_left = n0 % 16; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // Query the panel stride of B and convert it to units of bytes. uint64_t ps_b = bli_auxinfo_ps_b( data ); uint64_t ps_b4 = ps_b * sizeof( float ); if ( n_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. //mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), r14) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) //lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) // During preamble and loops: // r12 = rcx = c // r14 = rbx = b // read rax from var(a) near beginning of loop // r11 = m dim index ii mov(var(n_iter), r11) // jj = n_iter; label(.SLOOP6X8J) // LOOP OVER jj = [ n_iter ... 1 0 ] #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorps ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorps(ymm4, ymm4, ymm4) vxorps(ymm5, ymm5, ymm5) vxorps(ymm6, ymm6, ymm6) vxorps(ymm7, ymm7, ymm7) vxorps(ymm8, ymm8, ymm8) vxorps(ymm9, ymm9, ymm9) vxorps(ymm10, ymm10, ymm10) vxorps(ymm11, ymm11, ymm11) vxorps(ymm12, ymm12, ymm12) vxorps(ymm13, ymm13, ymm13) vxorps(ymm14, ymm14, ymm14) vxorps(ymm15, ymm15, ymm15) #endif mov(var(a), rax) // load address of a. //mov(r12, rcx) // reset rcx to current utile of c. mov(r14, rbx) // reset rbx to current upanel of b. cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored prefetching on c //lea(mem(r12, rdi, 2), rdx) // //lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(r12, 15*4)) // prefetch c + 0*rs_c prefetch(0, mem(r12, rdi, 1,15*4)) // prefetch c + 1*rs_c prefetch(0, mem(r12, rdi, 2,15*4)) // prefetch c + 2*rs_c jmp(.SPOSTPFETCH) // jump to end of prefetching c label(.SCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) lea(mem(rsi, rsi, 2), rcx) // rcx = 3*cs_c; prefetch(0, mem(r12, 2*4)) // prefetch c + 0*cs_c prefetch(0, mem(r12, rsi, 1, 2*4)) // prefetch c + 1*cs_c prefetch(0, mem(r12, rsi, 2, 2*4)) // prefetch c + 2*cs_c prefetch(0, mem(r12, rcx, 1, 2*4)) // prefetch c + 3*cs_c prefetch(0, mem(r12, rsi, 4, 2*4)) // prefetch c + 4*cs_c lea(mem(r12, rsi, 4), rdx) // rdx = c + 4*cs_c; prefetch(0, mem(rdx, rsi, 1, 2*4)) // prefetch c + 5*cs_c prefetch(0, mem(rdx, rsi, 2, 2*4)) // prefetch c + 6*cs_c prefetch(0, mem(rdx, rcx, 1, 2*4)) // prefetch c + 7*cs_c prefetch(0, mem(rdx, rsi, 4, 2*4)) // prefetch c + 8*cs_c lea(mem(r12, rsi, 8), rdx) // rdx = c + 8*cs_c; prefetch(0, mem(rdx, rsi, 1, 2*4)) // prefetch c + 9*cs_c prefetch(0, mem(rdx, rsi, 2, 2*4)) // prefetch c + 10*cs_c prefetch(0, mem(rdx, rcx, 1, 2*4)) // prefetch c + 11*cs_c prefetch(0, mem(rdx, rsi, 4, 2*4)) // prefetch c + 12*cs_c lea(mem(r12, rcx, 4), rdx) // rdx = c + 12*cs_c; prefetch(0, mem(rdx, rsi, 1, 2*4)) // prefetch c + 13*cs_c prefetch(0, mem(rdx, rsi, 2, 2*4)) // prefetch c + 14*cs_c prefetch(0, mem(rdx, rcx, 1, 2*4)) // prefetch c + 15*cs_c label(.SPOSTPFETCH) // done prefetching c #if 1 mov(var(ps_b4), rdx) // load ps_b4 lea(mem(rbx, rdx, 1), rdx) // rdx = a + ps_b4 lea(mem(r10, r10, 2), rcx) // rcx = 3*rs_b; // use rcx, rdx for prefetching lines // from next upanel of b. #else lea(mem(rbx, r8, 8), rdx) // use rdx for prefetching lines lea(mem(rdx, r8, 8), rdx) // from next upanel of b. lea(mem(r10, r10, 2), rcx) // rcx = 3*rs_b; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, 5*8)) #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, r10, 1, 5*8)) #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) // ---------------------------------- iteration 2 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, r10, 2, 5*8)) #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) // ---------------------------------- iteration 3 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, rcx, 1, 5*8)) lea(mem(rdx, r10, 4), rdx) // b_prefetch += 4*rs_b; #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP #if 1 prefetch(0, mem(rdx, 5*8)) add(r10, rdx) #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(r12, rcx) // reset rcx to current utile of c. mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), ymm0) // load alpha and duplicate vbroadcastss(mem(rbx), ymm3) // load beta and duplicate vmulps(ymm0, ymm4, ymm4) // scale by alpha vmulps(ymm0, ymm5, ymm5) vmulps(ymm0, ymm6, ymm6) vmulps(ymm0, ymm7, ymm7) vmulps(ymm0, ymm8, ymm8) vmulps(ymm0, ymm9, ymm9) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; lea(mem(rcx, rdi, 2), rdx) // load address of c + 2*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; lea(mem(rsi, rsi, 4), rbx) // rbx = 5*cs_c; lea(mem(rax, rsi, 4), rbp) // rbp = 7*cs_c; // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm4) vmovups(ymm4, mem(rcx, 0*32)) vfmadd231ps(mem(rcx, 1*32), ymm3, ymm5) vmovups(ymm5, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm6) vmovups(ymm6, mem(rcx, 0*32)) vfmadd231ps(mem(rcx, 1*32), ymm3, ymm7) vmovups(ymm7, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm8) vmovups(ymm8, mem(rcx, 0*32)) vfmadd231ps(mem(rcx, 1*32), ymm3, ymm9) vmovups(ymm9, mem(rcx, 1*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORED) // begin I/O on columns 0-7 vunpcklps(ymm6, ymm4, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(mem(rcx ), xmm1, xmm1) vmovhpd(mem(rcx, rsi, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(rcx )) // store ( gamma00..gamma10 ) vmovhpd(xmm0, mem(rcx, rsi, 1)) // store ( gamma01..gamma11 ) vmovlpd(mem(rcx, rsi, 4), xmm1, xmm1) vmovhpd(mem(rcx, rbx, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm2) vmovlpd(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma14 ) vmovhpd(xmm2, mem(rcx, rbx, 1)) // store ( gamma05..gamma15 ) vunpckhps(ymm6, ymm4, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(mem(rcx, rsi, 2), xmm1, xmm1) vmovhpd(mem(rcx, rax, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma12 ) vmovhpd(xmm0, mem(rcx, rax, 1)) // store ( gamma03..gamma13 ) vmovlpd(mem(rcx, rax, 2), xmm1, xmm1) vmovhpd(mem(rcx, rbp, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm2) vmovlpd(xmm2, mem(rcx, rax, 2)) // store ( gamma06..gamma16 ) vmovhpd(xmm2, mem(rcx, rbp, 1)) // store ( gamma07..gamma17 ) lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vmovups(ymm8, ymm0) vextractf128(imm(0x1), ymm0, xmm8) vpermilps(imm(0xe4), xmm0, xmm2) vpermilps(imm(0x39), xmm0, xmm4) vmovss(mem(rdx ), xmm1) vmovss(mem(rdx, rsi, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rdx )) // store ( gamma40 ) vmovss(xmm4, mem(rdx, rsi, 1)) // store ( gamma41 ) vpermilps(imm(0x4e), xmm0, xmm2) vpermilps(imm(0x93), xmm0, xmm4) vmovss(mem(rdx, rsi, 2), xmm1) vmovss(mem(rdx, rax, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rdx, rsi, 2)) // store ( gamma42 ) vmovss(xmm4, mem(rdx, rax, 1)) // store ( gamma43 ) vpermilps(imm(0xe4), xmm8, xmm2) vpermilps(imm(0x39), xmm8, xmm4) vmovss(mem(rdx, rsi, 4), xmm1) vmovss(mem(rdx, rbx, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rdx, rsi, 4)) // store ( gamma44 ) vmovss(xmm4, mem(rdx, rbx, 1)) // store ( gamma45 ) vpermilps(imm(0x4e), xmm8, xmm2) vpermilps(imm(0x93), xmm8, xmm4) vmovss(mem(rdx, rax, 2), xmm1) vmovss(mem(rdx, rbp, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rdx, rax, 2)) // store ( gamma46 ) vmovss(xmm4, mem(rdx, rbp, 1)) // store ( gamma47 ) lea(mem(rdx, rsi, 8), rdx) // rdx += 8*cs_c // begin I/O on columns 8-15 vunpcklps(ymm7, ymm5, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(mem(rcx ), xmm1, xmm1) vmovhpd(mem(rcx, rsi, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(rcx )) // store ( gamma00..gamma10 ) vmovhpd(xmm0, mem(rcx, rsi, 1)) // store ( gamma01..gamma11 ) vmovlpd(mem(rcx, rsi, 4), xmm1, xmm1) vmovhpd(mem(rcx, rbx, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm2) vmovlpd(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma14 ) vmovhpd(xmm2, mem(rcx, rbx, 1)) // store ( gamma05..gamma15 ) vunpckhps(ymm7, ymm5, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(mem(rcx, rsi, 2), xmm1, xmm1) vmovhpd(mem(rcx, rax, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma12 ) vmovhpd(xmm0, mem(rcx, rax, 1)) // store ( gamma03..gamma13 ) vmovlpd(mem(rcx, rax, 2), xmm1, xmm1) vmovhpd(mem(rcx, rbp, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm2) vmovlpd(xmm2, mem(rcx, rax, 2)) // store ( gamma06..gamma16 ) vmovhpd(xmm2, mem(rcx, rbp, 1)) // store ( gamma07..gamma17 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vmovups(ymm9, ymm0) vextractf128(imm(0x1), ymm0, xmm8) vpermilps(imm(0xe4), xmm0, xmm2) vpermilps(imm(0x39), xmm0, xmm4) vmovss(mem(rdx ), xmm1) vmovss(mem(rdx, rsi, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rdx )) // store ( gamma40 ) vmovss(xmm4, mem(rdx, rsi, 1)) // store ( gamma41 ) vpermilps(imm(0x4e), xmm0, xmm2) vpermilps(imm(0x93), xmm0, xmm4) vmovss(mem(rdx, rsi, 2), xmm1) vmovss(mem(rdx, rax, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rdx, rsi, 2)) // store ( gamma42 ) vmovss(xmm4, mem(rdx, rax, 1)) // store ( gamma43 ) vpermilps(imm(0xe4), xmm8, xmm2) vpermilps(imm(0x39), xmm8, xmm4) vmovss(mem(rdx, rsi, 4), xmm1) vmovss(mem(rdx, rbx, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rdx, rsi, 4)) // store ( gamma44 ) vmovss(xmm4, mem(rdx, rbx, 1)) // store ( gamma45 ) vpermilps(imm(0x4e), xmm8, xmm2) vpermilps(imm(0x93), xmm8, xmm4) vmovss(mem(rdx, rax, 2), xmm1) vmovss(mem(rdx, rbp, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rdx, rax, 2)) // store ( gamma46 ) vmovss(xmm4, mem(rdx, rbp, 1)) // store ( gamma47 ) //lea(mem(rdx, rsi, 8), rdx) // rdx += 8*cs_c jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovups(ymm4, mem(rcx, 0*32)) vmovups(ymm5, mem(rcx, 1*32)) add(rdi, rcx) vmovups(ymm6, mem(rcx, 0*32)) vmovups(ymm7, mem(rcx, 1*32)) add(rdi, rcx) vmovups(ymm8, mem(rcx, 0*32)) vmovups(ymm9, mem(rcx, 1*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) // begin I/O on columns 0-7 vunpcklps(ymm6, ymm4, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(xmm0, mem(rcx )) // store ( gamma00..gamma10 ) vmovhpd(xmm0, mem(rcx, rsi, 1)) // store ( gamma01..gamma11 ) vmovlpd(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma14 ) vmovhpd(xmm2, mem(rcx, rbx, 1)) // store ( gamma05..gamma15 ) vunpckhps(ymm6, ymm4, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma12 ) vmovhpd(xmm0, mem(rcx, rax, 1)) // store ( gamma03..gamma13 ) vmovlpd(xmm2, mem(rcx, rax, 2)) // store ( gamma06..gamma16 ) vmovhpd(xmm2, mem(rcx, rbp, 1)) // store ( gamma07..gamma17 ) lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vmovups(ymm8, ymm0) vextractf128(imm(0x1), ymm0, xmm8) vpermilps(imm(0xe4), xmm0, xmm2) vpermilps(imm(0x39), xmm0, xmm4) vmovss(xmm2, mem(rdx )) // store ( gamma40 ) vmovss(xmm4, mem(rdx, rsi, 1)) // store ( gamma41 ) vpermilps(imm(0x4e), xmm0, xmm2) vpermilps(imm(0x93), xmm0, xmm4) vmovss(xmm2, mem(rdx, rsi, 2)) // store ( gamma42 ) vmovss(xmm4, mem(rdx, rax, 1)) // store ( gamma43 ) vpermilps(imm(0xe4), xmm8, xmm2) vpermilps(imm(0x39), xmm8, xmm4) vmovss(xmm2, mem(rdx, rsi, 4)) // store ( gamma44 ) vmovss(xmm4, mem(rdx, rbx, 1)) // store ( gamma45 ) vpermilps(imm(0x4e), xmm8, xmm2) vpermilps(imm(0x93), xmm8, xmm4) vmovss(xmm2, mem(rdx, rax, 2)) // store ( gamma46 ) vmovss(xmm4, mem(rdx, rbp, 1)) // store ( gamma47 ) lea(mem(rdx, rsi, 8), rdx) // rdx += 8*cs_c // begin I/O on columns 8-15 vunpcklps(ymm7, ymm5, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(xmm0, mem(rcx )) // store ( gamma00..gamma10 ) vmovhpd(xmm0, mem(rcx, rsi, 1)) // store ( gamma01..gamma11 ) vmovlpd(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma14 ) vmovhpd(xmm2, mem(rcx, rbx, 1)) // store ( gamma05..gamma15 ) vunpckhps(ymm7, ymm5, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma12 ) vmovhpd(xmm0, mem(rcx, rax, 1)) // store ( gamma03..gamma13 ) vmovlpd(xmm2, mem(rcx, rax, 2)) // store ( gamma06..gamma16 ) vmovhpd(xmm2, mem(rcx, rbp, 1)) // store ( gamma07..gamma17 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vmovups(ymm9, ymm0) vextractf128(imm(0x1), ymm0, xmm8) vpermilps(imm(0xe4), xmm0, xmm2) vpermilps(imm(0x39), xmm0, xmm4) vmovss(xmm2, mem(rdx )) // store ( gamma40 ) vmovss(xmm4, mem(rdx, rsi, 1)) // store ( gamma41 ) vpermilps(imm(0x4e), xmm0, xmm2) vpermilps(imm(0x93), xmm0, xmm4) vmovss(xmm2, mem(rdx, rsi, 2)) // store ( gamma42 ) vmovss(xmm4, mem(rdx, rax, 1)) // store ( gamma43 ) vpermilps(imm(0xe4), xmm8, xmm2) vpermilps(imm(0x39), xmm8, xmm4) vmovss(xmm2, mem(rdx, rsi, 4)) // store ( gamma44 ) vmovss(xmm4, mem(rdx, rbx, 1)) // store ( gamma45 ) vpermilps(imm(0x4e), xmm8, xmm2) vpermilps(imm(0x93), xmm8, xmm4) vmovss(xmm2, mem(rdx, rax, 2)) // store ( gamma46 ) vmovss(xmm4, mem(rdx, rbp, 1)) // store ( gamma47 ) //lea(mem(rcx, rsi, 4), rcx) label(.SDONE) lea(mem(r12, rsi, 8), r12) // lea(mem(r12, rsi, 8), r12) // c_jj = r12 += 16*cs_c //add(imm(8*8), r14) // b_jj = r14 += 8*cs_b mov(var(ps_b4), rbx) // load ps_b4 lea(mem(r14, rbx, 1), r14) // b_jj = r14 += ps_b4 dec(r11) // jj -= 1; jne(.SLOOP6X8J) // iterate again if jj != 0. label(.SRETURN) end_asm( : // output operands (none) : // input operands [n_iter] "m" (n_iter), [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [ps_b4] "m" (ps_b4), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the m dimension, if they exist. if ( n_left ) { const dim_t mr_cur = 3; const dim_t j_edge = n0 - ( dim_t )n_left; float* restrict cij = c + j_edge*cs_c; float* restrict ai = a; //float* restrict bj = b + j_edge*cs_b; //float* restrict bj = b + ( j_edge / 8 ) * ps_b; float* restrict bj = b + n_iter * ps_b; if ( 12 <= n_left ) { const dim_t nr_cur = 12; bli_sgemmsup_rv_haswell_asm_3x12 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 8 <= n_left ) { const dim_t nr_cur = 8; bli_sgemmsup_rv_haswell_asm_3x8 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 6 <= n_left ) { const dim_t nr_cur = 6; bli_sgemmsup_rv_haswell_asm_3x6 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 4 <= n_left ) { const dim_t nr_cur = 4; bli_sgemmsup_rv_haswell_asm_3x4 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 2 <= n_left ) { const dim_t nr_cur = 2; bli_sgemmsup_rv_haswell_asm_3x2 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 1 == n_left ) { #if 1 const dim_t nr_cur = 1; bli_sgemmsup_r_haswell_ref_3x1 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); #else bli_dgemv_ex ( BLIS_NO_TRANSPOSE, conjb, m0, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, beta, cij, rs_c0, cntx, NULL ); #endif } } } void bli_sgemmsup_rv_haswell_asm_2x16n ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t n_iter = n0 / 16; uint64_t n_left = n0 % 16; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // Query the panel stride of B and convert it to units of bytes. uint64_t ps_b = bli_auxinfo_ps_b( data ); uint64_t ps_b4 = ps_b * sizeof( float ); if ( n_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. //mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), r14) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) //lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) // During preamble and loops: // r12 = rcx = c // r14 = rbx = b // read rax from var(a) near beginning of loop // r11 = m dim index ii mov(var(n_iter), r11) // jj = n_iter; label(.SLOOP6X8J) // LOOP OVER jj = [ n_iter ... 1 0 ] #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorps ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorps(ymm4, ymm4, ymm4) vxorps(ymm5, ymm5, ymm5) vxorps(ymm6, ymm6, ymm6) vxorps(ymm7, ymm7, ymm7) #endif mov(var(a), rax) // load address of a. //mov(r12, rcx) // reset rcx to current utile of c. mov(r14, rbx) // reset rbx to current upanel of b. cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored prefetching on c //lea(mem(r12, rdi, 2), rdx) // //lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(r12, 15*4)) // prefetch c + 0*rs_c prefetch(0, mem(r12, rdi, 1,15*4)) // prefetch c + 1*rs_c jmp(.SPOSTPFETCH) // jump to end of prefetching c label(.SCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) lea(mem(rsi, rsi, 2), rcx) // rcx = 3*cs_c; prefetch(0, mem(r12, 1*4)) // prefetch c + 0*cs_c prefetch(0, mem(r12, rsi, 1, 1*4)) // prefetch c + 1*cs_c prefetch(0, mem(r12, rsi, 2, 1*4)) // prefetch c + 2*cs_c prefetch(0, mem(r12, rcx, 1, 1*4)) // prefetch c + 3*cs_c prefetch(0, mem(r12, rsi, 4, 1*4)) // prefetch c + 4*cs_c lea(mem(r12, rsi, 4), rdx) // rdx = c + 4*cs_c; prefetch(0, mem(rdx, rsi, 1, 1*4)) // prefetch c + 5*cs_c prefetch(0, mem(rdx, rsi, 2, 1*4)) // prefetch c + 6*cs_c prefetch(0, mem(rdx, rcx, 1, 1*4)) // prefetch c + 7*cs_c prefetch(0, mem(rdx, rsi, 4, 1*4)) // prefetch c + 8*cs_c lea(mem(r12, rsi, 8), rdx) // rdx = c + 8*cs_c; prefetch(0, mem(rdx, rsi, 1, 1*4)) // prefetch c + 9*cs_c prefetch(0, mem(rdx, rsi, 2, 1*4)) // prefetch c + 10*cs_c prefetch(0, mem(rdx, rcx, 1, 1*4)) // prefetch c + 11*cs_c prefetch(0, mem(rdx, rsi, 4, 1*4)) // prefetch c + 12*cs_c lea(mem(r12, rcx, 4), rdx) // rdx = c + 12*cs_c; prefetch(0, mem(rdx, rsi, 1, 1*4)) // prefetch c + 13*cs_c prefetch(0, mem(rdx, rsi, 2, 1*4)) // prefetch c + 14*cs_c prefetch(0, mem(rdx, rcx, 1, 1*4)) // prefetch c + 15*cs_c label(.SPOSTPFETCH) // done prefetching c #if 1 mov(var(ps_b4), rdx) // load ps_b4 lea(mem(rbx, rdx, 1), rdx) // rdx = a + ps_b4 lea(mem(r10, r10, 2), rcx) // rcx = 3*rs_b; // use rcx, rdx for prefetching lines // from next upanel of b. #else lea(mem(rbx, r8, 8), rdx) // use rdx for prefetching lines lea(mem(rdx, r8, 8), rdx) // from next upanel of b. lea(mem(r10, r10, 2), rcx) // rcx = 3*rs_b; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, 5*8)) #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, r10, 1, 5*8)) #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) // ---------------------------------- iteration 2 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, r10, 2, 5*8)) #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) // ---------------------------------- iteration 3 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, rcx, 1, 5*8)) lea(mem(rdx, r10, 4), rdx) // b_prefetch += 4*rs_b; #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP #if 1 prefetch(0, mem(rdx, 5*8)) add(r10, rdx) #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(r12, rcx) // reset rcx to current utile of c. mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), ymm0) // load alpha and duplicate vbroadcastss(mem(rbx), ymm3) // load beta and duplicate vmulps(ymm0, ymm4, ymm4) // scale by alpha vmulps(ymm0, ymm5, ymm5) vmulps(ymm0, ymm6, ymm6) vmulps(ymm0, ymm7, ymm7) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; //lea(mem(rcx, rdi, 2), rdx) // load address of c + 2*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; lea(mem(rsi, rsi, 4), rbx) // rbx = 5*cs_c; lea(mem(rax, rsi, 4), rbp) // rbp = 7*cs_c; // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm4) vmovups(ymm4, mem(rcx, 0*32)) vfmadd231ps(mem(rcx, 1*32), ymm3, ymm5) vmovups(ymm5, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm6) vmovups(ymm6, mem(rcx, 0*32)) vfmadd231ps(mem(rcx, 1*32), ymm3, ymm7) vmovups(ymm7, mem(rcx, 1*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORED) // begin I/O on columns 0-7 vunpcklps(ymm6, ymm4, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(mem(rcx ), xmm1, xmm1) vmovhpd(mem(rcx, rsi, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(rcx )) // store ( gamma00..gamma10 ) vmovhpd(xmm0, mem(rcx, rsi, 1)) // store ( gamma01..gamma11 ) vmovlpd(mem(rcx, rsi, 4), xmm1, xmm1) vmovhpd(mem(rcx, rbx, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm2) vmovlpd(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma14 ) vmovhpd(xmm2, mem(rcx, rbx, 1)) // store ( gamma05..gamma15 ) vunpckhps(ymm6, ymm4, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(mem(rcx, rsi, 2), xmm1, xmm1) vmovhpd(mem(rcx, rax, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma12 ) vmovhpd(xmm0, mem(rcx, rax, 1)) // store ( gamma03..gamma13 ) vmovlpd(mem(rcx, rax, 2), xmm1, xmm1) vmovhpd(mem(rcx, rbp, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm2) vmovlpd(xmm2, mem(rcx, rax, 2)) // store ( gamma06..gamma16 ) vmovhpd(xmm2, mem(rcx, rbp, 1)) // store ( gamma07..gamma17 ) lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c // begin I/O on columns 8-15 vunpcklps(ymm7, ymm5, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(mem(rcx ), xmm1, xmm1) vmovhpd(mem(rcx, rsi, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(rcx )) // store ( gamma00..gamma10 ) vmovhpd(xmm0, mem(rcx, rsi, 1)) // store ( gamma01..gamma11 ) vmovlpd(mem(rcx, rsi, 4), xmm1, xmm1) vmovhpd(mem(rcx, rbx, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm2) vmovlpd(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma14 ) vmovhpd(xmm2, mem(rcx, rbx, 1)) // store ( gamma05..gamma15 ) vunpckhps(ymm7, ymm5, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(mem(rcx, rsi, 2), xmm1, xmm1) vmovhpd(mem(rcx, rax, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma12 ) vmovhpd(xmm0, mem(rcx, rax, 1)) // store ( gamma03..gamma13 ) vmovlpd(mem(rcx, rax, 2), xmm1, xmm1) vmovhpd(mem(rcx, rbp, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm2) vmovlpd(xmm2, mem(rcx, rax, 2)) // store ( gamma06..gamma16 ) vmovhpd(xmm2, mem(rcx, rbp, 1)) // store ( gamma07..gamma17 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovups(ymm4, mem(rcx, 0*32)) vmovups(ymm5, mem(rcx, 1*32)) add(rdi, rcx) vmovups(ymm6, mem(rcx, 0*32)) vmovups(ymm7, mem(rcx, 1*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) // begin I/O on columns 0-7 vunpcklps(ymm6, ymm4, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(xmm0, mem(rcx )) // store ( gamma00..gamma10 ) vmovhpd(xmm0, mem(rcx, rsi, 1)) // store ( gamma01..gamma11 ) vmovlpd(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma14 ) vmovhpd(xmm2, mem(rcx, rbx, 1)) // store ( gamma05..gamma15 ) vunpckhps(ymm6, ymm4, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma12 ) vmovhpd(xmm0, mem(rcx, rax, 1)) // store ( gamma03..gamma13 ) vmovlpd(xmm2, mem(rcx, rax, 2)) // store ( gamma06..gamma16 ) vmovhpd(xmm2, mem(rcx, rbp, 1)) // store ( gamma07..gamma17 ) lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c // begin I/O on columns 8-15 vunpcklps(ymm7, ymm5, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(xmm0, mem(rcx )) // store ( gamma00..gamma10 ) vmovhpd(xmm0, mem(rcx, rsi, 1)) // store ( gamma01..gamma11 ) vmovlpd(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma14 ) vmovhpd(xmm2, mem(rcx, rbx, 1)) // store ( gamma05..gamma15 ) vunpckhps(ymm7, ymm5, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma12 ) vmovhpd(xmm0, mem(rcx, rax, 1)) // store ( gamma03..gamma13 ) vmovlpd(xmm2, mem(rcx, rax, 2)) // store ( gamma06..gamma16 ) vmovhpd(xmm2, mem(rcx, rbp, 1)) // store ( gamma07..gamma17 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c label(.SDONE) lea(mem(r12, rsi, 8), r12) // lea(mem(r12, rsi, 8), r12) // c_jj = r12 += 16*cs_c //add(imm(8*8), r14) // b_jj = r14 += 8*cs_b mov(var(ps_b4), rbx) // load ps_b4 lea(mem(r14, rbx, 1), r14) // b_jj = r14 += ps_b4 dec(r11) // jj -= 1; jne(.SLOOP6X8J) // iterate again if jj != 0. label(.SRETURN) end_asm( : // output operands (none) : // input operands [n_iter] "m" (n_iter), [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [ps_b4] "m" (ps_b4), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the m dimension, if they exist. if ( n_left ) { const dim_t mr_cur = 2; const dim_t j_edge = n0 - ( dim_t )n_left; float* restrict cij = c + j_edge*cs_c; float* restrict ai = a; //float* restrict bj = b + j_edge*cs_b; //float* restrict bj = b + ( j_edge / 8 ) * ps_b; float* restrict bj = b + n_iter * ps_b; if ( 12 <= n_left ) { const dim_t nr_cur = 12; bli_sgemmsup_rv_haswell_asm_2x12 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 8 <= n_left ) { const dim_t nr_cur = 8; bli_sgemmsup_rv_haswell_asm_2x8 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 6 <= n_left ) { const dim_t nr_cur = 6; bli_sgemmsup_rv_haswell_asm_2x6 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 4 <= n_left ) { const dim_t nr_cur = 4; bli_sgemmsup_rv_haswell_asm_2x4 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 2 <= n_left ) { const dim_t nr_cur = 2; bli_sgemmsup_rv_haswell_asm_2x2 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 1 == n_left ) { #if 1 const dim_t nr_cur = 1; bli_sgemmsup_r_haswell_ref_2x1 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); #else bli_dgemv_ex ( BLIS_NO_TRANSPOSE, conjb, m0, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, beta, cij, rs_c0, cntx, NULL ); #endif } } } void bli_sgemmsup_rv_haswell_asm_1x16n ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t n_iter = n0 / 16; uint64_t n_left = n0 % 16; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // Query the panel stride of B and convert it to units of bytes. uint64_t ps_b = bli_auxinfo_ps_b( data ); uint64_t ps_b4 = ps_b * sizeof( float ); if ( n_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. //mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), r14) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) //lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) // During preamble and loops: // r12 = rcx = c // r14 = rbx = b // read rax from var(a) near beginning of loop // r11 = m dim index ii mov(var(n_iter), r11) // jj = n_iter; label(.SLOOP6X8J) // LOOP OVER jj = [ n_iter ... 1 0 ] #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorps ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorps(ymm4, ymm4, ymm4) vxorps(ymm5, ymm5, ymm5) #endif mov(var(a), rax) // load address of a. //mov(r12, rcx) // reset rcx to current utile of c. mov(r14, rbx) // reset rbx to current upanel of b. cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored prefetching on c //lea(mem(r12, rdi, 2), rdx) // //lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(r12, 15*4)) // prefetch c + 0*rs_c jmp(.SPOSTPFETCH) // jump to end of prefetching c label(.SCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) lea(mem(rsi, rsi, 2), rcx) // rcx = 3*cs_c; prefetch(0, mem(r12, 0*4)) // prefetch c + 0*cs_c prefetch(0, mem(r12, rsi, 1, 0*4)) // prefetch c + 1*cs_c prefetch(0, mem(r12, rsi, 2, 0*4)) // prefetch c + 2*cs_c prefetch(0, mem(r12, rcx, 1, 0*4)) // prefetch c + 3*cs_c prefetch(0, mem(r12, rsi, 4, 0*4)) // prefetch c + 4*cs_c lea(mem(r12, rsi, 4), rdx) // rdx = c + 4*cs_c; prefetch(0, mem(rdx, rsi, 1, 0*4)) // prefetch c + 5*cs_c prefetch(0, mem(rdx, rsi, 2, 0*4)) // prefetch c + 6*cs_c prefetch(0, mem(rdx, rcx, 1, 0*4)) // prefetch c + 7*cs_c prefetch(0, mem(rdx, rsi, 4, 0*4)) // prefetch c + 8*cs_c lea(mem(r12, rsi, 8), rdx) // rdx = c + 8*cs_c; prefetch(0, mem(rdx, rsi, 1, 0*4)) // prefetch c + 9*cs_c prefetch(0, mem(rdx, rsi, 2, 0*4)) // prefetch c + 10*cs_c prefetch(0, mem(rdx, rcx, 1, 0*4)) // prefetch c + 11*cs_c prefetch(0, mem(rdx, rsi, 4, 0*4)) // prefetch c + 12*cs_c lea(mem(r12, rcx, 4), rdx) // rdx = c + 12*cs_c; prefetch(0, mem(rdx, rsi, 1, 0*4)) // prefetch c + 13*cs_c prefetch(0, mem(rdx, rsi, 2, 0*4)) // prefetch c + 14*cs_c prefetch(0, mem(rdx, rcx, 1, 0*4)) // prefetch c + 15*cs_c label(.SPOSTPFETCH) // done prefetching c #if 1 mov(var(ps_b4), rdx) // load ps_b4 lea(mem(rbx, rdx, 1), rdx) // rdx = a + ps_b4 lea(mem(r10, r10, 2), rcx) // rcx = 3*rs_b; // use rcx, rdx for prefetching lines // from next upanel of b. #else lea(mem(rbx, r8, 8), rdx) // use rdx for prefetching lines lea(mem(rdx, r8, 8), rdx) // from next upanel of b. lea(mem(r10, r10, 2), rcx) // rcx = 3*rs_b; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, 5*8)) #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, r10, 1, 5*8)) #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) // ---------------------------------- iteration 2 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, r10, 2, 5*8)) #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) // ---------------------------------- iteration 3 #if 0 prefetch(0, mem(rdx, 5*8)) #else prefetch(0, mem(rdx, rcx, 1, 5*8)) lea(mem(rdx, r10, 4), rdx) // b_prefetch += 4*rs_b; #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP #if 1 prefetch(0, mem(rdx, 5*8)) add(r10, rdx) #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(r12, rcx) // reset rcx to current utile of c. mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), ymm0) // load alpha and duplicate vbroadcastss(mem(rbx), ymm3) // load beta and duplicate vmulps(ymm0, ymm4, ymm4) // scale by alpha vmulps(ymm0, ymm5, ymm5) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; //lea(mem(rcx, rdi, 2), rdx) // load address of c + 2*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; lea(mem(rsi, rsi, 4), rbx) // rbx = 5*cs_c; lea(mem(rax, rsi, 4), rbp) // rbp = 7*cs_c; // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm4) vmovups(ymm4, mem(rcx, 0*32)) vfmadd231ps(mem(rcx, 1*32), ymm3, ymm5) vmovups(ymm5, mem(rcx, 1*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORED) // begin I/O on columns 0-7 vmovups(ymm4, ymm0) vextractf128(imm(0x1), ymm0, xmm8) vpermilps(imm(0xe4), xmm0, xmm2) vpermilps(imm(0x39), xmm0, xmm4) vmovss(mem(rcx ), xmm1) vmovss(mem(rcx, rsi, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rcx )) // store ( gamma40 ) vmovss(xmm4, mem(rcx, rsi, 1)) // store ( gamma41 ) vpermilps(imm(0x4e), xmm0, xmm2) vpermilps(imm(0x93), xmm0, xmm4) vmovss(mem(rcx, rsi, 2), xmm1) vmovss(mem(rcx, rax, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rcx, rsi, 2)) // store ( gamma42 ) vmovss(xmm4, mem(rcx, rax, 1)) // store ( gamma43 ) vpermilps(imm(0xe4), xmm8, xmm2) vpermilps(imm(0x39), xmm8, xmm4) vmovss(mem(rcx, rsi, 4), xmm1) vmovss(mem(rcx, rbx, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rcx, rsi, 4)) // store ( gamma44 ) vmovss(xmm4, mem(rcx, rbx, 1)) // store ( gamma45 ) vpermilps(imm(0x4e), xmm8, xmm2) vpermilps(imm(0x93), xmm8, xmm4) vmovss(mem(rcx, rax, 2), xmm1) vmovss(mem(rcx, rbp, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rcx, rax, 2)) // store ( gamma46 ) vmovss(xmm4, mem(rcx, rbp, 1)) // store ( gamma47 ) lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c // begin I/O on columns 8-15 vmovups(ymm5, ymm0) vextractf128(imm(0x1), ymm0, xmm8) vpermilps(imm(0xe4), xmm0, xmm2) vpermilps(imm(0x39), xmm0, xmm4) vmovss(mem(rcx ), xmm1) vmovss(mem(rcx, rsi, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rcx )) // store ( gamma40 ) vmovss(xmm4, mem(rcx, rsi, 1)) // store ( gamma41 ) vpermilps(imm(0x4e), xmm0, xmm2) vpermilps(imm(0x93), xmm0, xmm4) vmovss(mem(rcx, rsi, 2), xmm1) vmovss(mem(rcx, rax, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rcx, rsi, 2)) // store ( gamma42 ) vmovss(xmm4, mem(rcx, rax, 1)) // store ( gamma43 ) vpermilps(imm(0xe4), xmm8, xmm2) vpermilps(imm(0x39), xmm8, xmm4) vmovss(mem(rcx, rsi, 4), xmm1) vmovss(mem(rcx, rbx, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rcx, rsi, 4)) // store ( gamma44 ) vmovss(xmm4, mem(rcx, rbx, 1)) // store ( gamma45 ) vpermilps(imm(0x4e), xmm8, xmm2) vpermilps(imm(0x93), xmm8, xmm4) vmovss(mem(rcx, rax, 2), xmm1) vmovss(mem(rcx, rbp, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rcx, rax, 2)) // store ( gamma46 ) vmovss(xmm4, mem(rcx, rbp, 1)) // store ( gamma47 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovups(ymm4, mem(rcx, 0*32)) vmovups(ymm5, mem(rcx, 1*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) // begin I/O on columns 0-7 vmovups(ymm4, ymm0) vextractf128(imm(0x1), ymm0, xmm8) vpermilps(imm(0xe4), xmm0, xmm2) vpermilps(imm(0x39), xmm0, xmm4) vmovss(xmm2, mem(rcx )) // store ( gamma40 ) vmovss(xmm4, mem(rcx, rsi, 1)) // store ( gamma41 ) vpermilps(imm(0x4e), xmm0, xmm2) vpermilps(imm(0x93), xmm0, xmm4) vmovss(xmm2, mem(rcx, rsi, 2)) // store ( gamma42 ) vmovss(xmm4, mem(rcx, rax, 1)) // store ( gamma43 ) vpermilps(imm(0xe4), xmm8, xmm2) vpermilps(imm(0x39), xmm8, xmm4) vmovss(xmm2, mem(rcx, rsi, 4)) // store ( gamma44 ) vmovss(xmm4, mem(rcx, rbx, 1)) // store ( gamma45 ) vpermilps(imm(0x4e), xmm8, xmm2) vpermilps(imm(0x93), xmm8, xmm4) vmovss(xmm2, mem(rcx, rax, 2)) // store ( gamma46 ) vmovss(xmm4, mem(rcx, rbp, 1)) // store ( gamma47 ) lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c // begin I/O on columns 8-15 vmovups(ymm5, ymm0) vextractf128(imm(0x1), ymm0, xmm8) vpermilps(imm(0xe4), xmm0, xmm2) vpermilps(imm(0x39), xmm0, xmm4) vmovss(xmm2, mem(rcx )) // store ( gamma40 ) vmovss(xmm4, mem(rcx, rsi, 1)) // store ( gamma41 ) vpermilps(imm(0x4e), xmm0, xmm2) vpermilps(imm(0x93), xmm0, xmm4) vmovss(xmm2, mem(rcx, rsi, 2)) // store ( gamma42 ) vmovss(xmm4, mem(rcx, rax, 1)) // store ( gamma43 ) vpermilps(imm(0xe4), xmm8, xmm2) vpermilps(imm(0x39), xmm8, xmm4) vmovss(xmm2, mem(rcx, rsi, 4)) // store ( gamma44 ) vmovss(xmm4, mem(rcx, rbx, 1)) // store ( gamma45 ) vpermilps(imm(0x4e), xmm8, xmm2) vpermilps(imm(0x93), xmm8, xmm4) vmovss(xmm2, mem(rcx, rax, 2)) // store ( gamma46 ) vmovss(xmm4, mem(rcx, rbp, 1)) // store ( gamma47 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c label(.SDONE) lea(mem(r12, rsi, 8), r12) // lea(mem(r12, rsi, 8), r12) // c_jj = r12 += 16*cs_c //add(imm(8*8), r14) // b_jj = r14 += 8*cs_b mov(var(ps_b4), rbx) // load ps_b4 lea(mem(r14, rbx, 1), r14) // b_jj = r14 += ps_b4 dec(r11) // jj -= 1; jne(.SLOOP6X8J) // iterate again if jj != 0. label(.SRETURN) end_asm( : // output operands (none) : // input operands [n_iter] "m" (n_iter), [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [ps_b4] "m" (ps_b4), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the m dimension, if they exist. if ( n_left ) { const dim_t mr_cur = 1; const dim_t j_edge = n0 - ( dim_t )n_left; float* restrict cij = c + j_edge*cs_c; float* restrict ai = a; //float* restrict bj = b + j_edge*cs_b; //float* restrict bj = b + ( j_edge / 8 ) * ps_b; float* restrict bj = b + n_iter * ps_b; if ( 12 <= n_left ) { const dim_t nr_cur = 12; bli_sgemmsup_rv_haswell_asm_1x12 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 8 <= n_left ) { const dim_t nr_cur = 8; bli_sgemmsup_rv_haswell_asm_1x8 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 6 <= n_left ) { const dim_t nr_cur = 6; bli_sgemmsup_rv_haswell_asm_1x6 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 4 <= n_left ) { const dim_t nr_cur = 4; bli_sgemmsup_rv_haswell_asm_1x4 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 2 <= n_left ) { const dim_t nr_cur = 2; bli_sgemmsup_rv_haswell_asm_1x2 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 1 == n_left ) { #if 1 const dim_t nr_cur = 1; bli_sgemmsup_r_haswell_ref_1x1 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); #else bli_dgemv_ex ( BLIS_NO_TRANSPOSE, conjb, m0, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, beta, cij, rs_c0, cntx, NULL ); #endif } } } blis-0.9.0/kernels/haswell/3/sup/d6x8/000077500000000000000000000000001422157504600173235ustar00rootroot00000000000000blis-0.9.0/kernels/haswell/3/sup/d6x8/bli_gemmsup_r_haswell_ref_dMx1.c000066400000000000000000000133431422157504600255630ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define BLIS_ASM_SYNTAX_ATT #include "bli_x86_asm_macros.h" /* rrr: -------- ------ -------- -------- ------ -------- -------- += ------ ... -------- -------- ------ -------- -------- ------ : -------- ------ : rcr: -------- | | | | -------- -------- | | | | -------- -------- += | | | | ... -------- -------- | | | | -------- -------- | | | | : -------- | | | | : Assumptions: - B is row-stored; - A is row- or column-stored; - m0 and n0 are at most MR and NR, respectively. Therefore, this (r)ow-preferential kernel is well-suited for contiguous (v)ector loads on B and single-element broadcasts from A. NOTE: These kernels explicitly support column-oriented IO, implemented via an in-register transpose. And thus they also support the crr and ccr cases, though only crr is ever utilized (because ccr is handled by transposing the operation and executing rcr, which does not incur the cost of the in-register transpose). crr: | | | | | | | | ------ -------- | | | | | | | | ------ -------- | | | | | | | | += ------ ... -------- | | | | | | | | ------ -------- | | | | | | | | ------ : | | | | | | | | ------ : */ // Prototype reference microkernels. GEMMSUP_KER_PROT( double, d, gemmsup_r_haswell_ref ) // NOTE: Normally, for any "?x1" kernel, we would call the reference kernel. // However, at least one other subconfiguration (zen) uses this kernel set, so // we need to be able to call a set of "?x1" kernels that we know will actually // exist regardless of which subconfiguration these kernels were used by. Thus, // the compromise employed here is to inline the reference kernel so it gets // compiled as part of the haswell kernel set, and hence can unconditionally be // called by other kernels within that kernel set. #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, mdim ) \ \ void PASTEMAC(ch,opname) \ ( \ conj_t conja, \ conj_t conjb, \ dim_t m, \ dim_t n, \ dim_t k, \ ctype* restrict alpha, \ ctype* restrict a, inc_t rs_a, inc_t cs_a, \ ctype* restrict b, inc_t rs_b, inc_t cs_b, \ ctype* restrict beta, \ ctype* restrict c, inc_t rs_c, inc_t cs_c, \ auxinfo_t* restrict data, \ cntx_t* restrict cntx \ ) \ { \ for ( dim_t i = 0; i < mdim; ++i ) \ { \ ctype* restrict ci = &c[ i*rs_c ]; \ ctype* restrict ai = &a[ i*rs_a ]; \ \ /* for ( dim_t j = 0; j < 1; ++j ) */ \ { \ ctype* restrict cij = ci /*[ j*cs_c ]*/ ; \ ctype* restrict bj = b /*[ j*cs_b ]*/ ; \ ctype ab; \ \ PASTEMAC(ch,set0s)( ab ); \ \ /* Perform a dot product to update the (i,j) element of c. */ \ for ( dim_t l = 0; l < k; ++l ) \ { \ ctype* restrict aij = &ai[ l*cs_a ]; \ ctype* restrict bij = &bj[ l*rs_b ]; \ \ PASTEMAC(ch,dots)( *aij, *bij, ab ); \ } \ \ /* If beta is one, add ab into c. If beta is zero, overwrite c with the result in ab. Otherwise, scale by beta and accumulate ab to c. */ \ if ( PASTEMAC(ch,eq1)( *beta ) ) \ { \ PASTEMAC(ch,axpys)( *alpha, ab, *cij ); \ } \ else if ( PASTEMAC(d,eq0)( *beta ) ) \ { \ PASTEMAC(ch,scal2s)( *alpha, ab, *cij ); \ } \ else \ { \ PASTEMAC(ch,axpbys)( *alpha, ab, *beta, *cij ); \ } \ } \ } \ } GENTFUNC( double, d, gemmsup_r_haswell_ref_6x1, 6 ) GENTFUNC( double, d, gemmsup_r_haswell_ref_5x1, 5 ) GENTFUNC( double, d, gemmsup_r_haswell_ref_4x1, 4 ) GENTFUNC( double, d, gemmsup_r_haswell_ref_3x1, 3 ) GENTFUNC( double, d, gemmsup_r_haswell_ref_2x1, 2 ) GENTFUNC( double, d, gemmsup_r_haswell_ref_1x1, 1 ) blis-0.9.0/kernels/haswell/3/sup/d6x8/bli_gemmsup_rd_haswell_asm_dMx1.c000066400000000000000000001304661422157504600257410ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define BLIS_ASM_SYNTAX_ATT #include "bli_x86_asm_macros.h" /* rrc: -------- ------ | | | | | | | | -------- ------ | | | | | | | | -------- += ------ ... | | | | | | | | -------- ------ | | | | | | | | -------- ------ : -------- ------ : Assumptions: - C is row-stored and B is column-stored; - A is row-stored; - m0 and n0 are at most MR and NR, respectively. Therefore, this (r)ow-preferential microkernel is well-suited for a dot-product-based accumulation that performs vector loads from both A and B. */ // Prototype reference microkernels. GEMMSUP_KER_PROT( double, d, gemmsup_r_haswell_ref ) void bli_dgemmsup_rd_haswell_asm_6x1 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; //uint64_t m_iter = m0 / 3; //uint64_t m_left = m0 % 3; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. //mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) //lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) //lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b //lea(mem(r8, r8, 2), r10) // r10 = 3*rs_a mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) // r12 = rcx = c // r14 = rax = a // rdx = rbx = b #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm6, ymm6, ymm6) vxorpd(ymm8, ymm8, ymm8) vxorpd(ymm10, ymm10, ymm10) vxorpd(ymm12, ymm12, ymm12) vxorpd(ymm14, ymm14, ymm14) #endif //lea(mem(r12), rcx) // rcx = c_ii; //lea(mem(r14), rax) // rax = a_ii; //lea(mem(rdx), rbx) // rbx = b; #if 1 //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) lea(mem(rcx, rdi, 2), r10) // lea(mem(r10, rdi, 1), r10) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 1*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 1*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 1*8)) // prefetch c + 2*rs_c prefetch(0, mem(r10, 1*8)) // prefetch c + 3*rs_c prefetch(0, mem(r10, rdi, 1, 1*8)) // prefetch c + 4*rs_c prefetch(0, mem(r10, rdi, 2, 1*8)) // prefetch c + 5*rs_c #endif mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovupd(mem(rbx ), ymm0) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vmovupd(mem(rax, r8, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm8) vmovupd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovupd(mem(rax, r8, 4), ymm3) vfmadd231pd(ymm0, ymm3, ymm12) vmovupd(mem(rax, r15, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm14) // ---------------------------------- iteration 1 vmovupd(mem(rbx ), ymm0) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vmovupd(mem(rax, r8, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm8) vmovupd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovupd(mem(rax, r8, 4), ymm3) vfmadd231pd(ymm0, ymm3, ymm12) vmovupd(mem(rax, r15, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm14) // ---------------------------------- iteration 2 #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovupd(mem(rbx ), ymm0) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vmovupd(mem(rax, r8, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm8) vmovupd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovupd(mem(rax, r8, 4), ymm3) vfmadd231pd(ymm0, ymm3, ymm12) vmovupd(mem(rax, r15, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm14) // ---------------------------------- iteration 3 vmovupd(mem(rbx ), ymm0) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vmovupd(mem(rax, r8, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm8) vmovupd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovupd(mem(rax, r8, 4), ymm3) vfmadd231pd(ymm0, ymm3, ymm12) vmovupd(mem(rax, r15, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm14) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovupd(mem(rbx ), ymm0) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vmovupd(mem(rax, r8, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm8) vmovupd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovupd(mem(rax, r8, 4), ymm3) vfmadd231pd(ymm0, ymm3, ymm12) vmovupd(mem(rax, r15, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm14) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rbx ), xmm0) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vmovsd(mem(rax ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovsd(mem(rax, r8, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm6) vmovsd(mem(rax, r8, 2), xmm3) vfmadd231pd(ymm0, ymm3, ymm8) vmovsd(mem(rax, r13, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovsd(mem(rax, r8, 4), xmm3) vfmadd231pd(ymm0, ymm3, ymm12) vmovsd(mem(rax, r15, 1), xmm3) add(imm(1*8), rax) // a += 1*cs_a = 1*8; vfmadd231pd(ymm0, ymm3, ymm14) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 // ymm6 // ymm8 // ymm10 // ymm12 // ymm14 vhaddpd( ymm4, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm4 ) vhaddpd( ymm6, ymm6, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm6 ) vhaddpd( ymm8, ymm8, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm8 ) vhaddpd( ymm10, ymm10, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm10 ) vhaddpd( ymm12, ymm12, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm12 ) vhaddpd( ymm14, ymm14, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm14 ) // xmm4[0] = sum(ymm4) // xmm6[0] = sum(ymm6) // xmm8[0] = sum(ymm8) // xmm10[0] = sum(ymm10) // xmm12[0] = sum(ymm12) // xmm14[0] = sum(ymm14) //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(double) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(xmm0, xmm4, xmm4) // scale by alpha vmulpd(xmm0, xmm6, xmm6) vmulpd(xmm0, xmm8, xmm8) vmulpd(xmm0, xmm10, xmm10) vmulpd(xmm0, xmm12, xmm12) vmulpd(xmm0, xmm14, xmm14) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vmovsd(mem(rcx), xmm0) vfmadd231pd(xmm0, xmm3, xmm4) vmovsd(xmm4, mem(rcx)) add(rdi, rcx) vmovsd(mem(rcx), xmm0) vfmadd231pd(xmm0, xmm3, xmm6) vmovsd(xmm6, mem(rcx)) add(rdi, rcx) vmovsd(mem(rcx), xmm0) vfmadd231pd(xmm0, xmm3, xmm8) vmovsd(xmm8, mem(rcx)) add(rdi, rcx) vmovsd(mem(rcx), xmm0) vfmadd231pd(xmm0, xmm3, xmm10) vmovsd(xmm10, mem(rcx)) add(rdi, rcx) vmovsd(mem(rcx), xmm0) vfmadd231pd(xmm0, xmm3, xmm12) vmovsd(xmm12, mem(rcx)) add(rdi, rcx) vmovsd(mem(rcx), xmm0) vfmadd231pd(xmm0, xmm3, xmm14) vmovsd(xmm14, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovsd(xmm4, mem(rcx)) add(rdi, rcx) vmovsd(xmm6, mem(rcx)) add(rdi, rcx) vmovsd(xmm8, mem(rcx)) add(rdi, rcx) vmovsd(xmm10, mem(rcx)) add(rdi, rcx) vmovsd(xmm12, mem(rcx)) add(rdi, rcx) vmovsd(xmm14, mem(rcx)) //add(rdi, rcx) label(.DDONE) label(.DRETURN) end_asm( : // output operands (none) : // input operands [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rd_haswell_asm_3x1 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; //uint64_t m_iter = m0 / 3; //uint64_t m_left = m0 % 3; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. //mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) //lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) //lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b //lea(mem(r8, r8, 2), r10) // r10 = 3*rs_a mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) // r12 = rcx = c // r14 = rax = a // rdx = rbx = b #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm6, ymm6, ymm6) vxorpd(ymm8, ymm8, ymm8) #endif //lea(mem(r12), rcx) // rcx = c_ii; //lea(mem(r14), rax) // rax = a_ii; //lea(mem(rdx), rbx) // rbx = b; #if 1 //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) //lea(mem(rcx, rdi, 2), r10) // //lea(mem(r10, rdi, 1), r10) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 1*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 1*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 1*8)) // prefetch c + 2*rs_c #endif mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovupd(mem(rbx ), ymm0) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vmovupd(mem(rax, r8, 2), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm8) // ---------------------------------- iteration 1 vmovupd(mem(rbx ), ymm0) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vmovupd(mem(rax, r8, 2), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm8) // ---------------------------------- iteration 2 #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovupd(mem(rbx ), ymm0) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vmovupd(mem(rax, r8, 2), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm8) // ---------------------------------- iteration 3 vmovupd(mem(rbx ), ymm0) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vmovupd(mem(rax, r8, 2), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm8) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovupd(mem(rbx ), ymm0) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vmovupd(mem(rax, r8, 2), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm8) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rbx ), xmm0) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vmovsd(mem(rax ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovsd(mem(rax, r8, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm6) vmovsd(mem(rax, r8, 2), xmm3) add(imm(1*8), rax) // a += 1*cs_a = 1*8; vfmadd231pd(ymm0, ymm3, ymm8) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 // ymm6 // ymm8 vhaddpd( ymm4, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm4 ) vhaddpd( ymm6, ymm6, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm6 ) vhaddpd( ymm8, ymm8, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm8 ) // xmm4[0] = sum(ymm4) // xmm6[0] = sum(ymm6) // xmm8[0] = sum(ymm8) //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(double) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(xmm0, xmm4, xmm4) // scale by alpha vmulpd(xmm0, xmm6, xmm6) vmulpd(xmm0, xmm8, xmm8) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vmovsd(mem(rcx), xmm0) vfmadd231pd(xmm0, xmm3, xmm4) vmovsd(xmm4, mem(rcx)) add(rdi, rcx) vmovsd(mem(rcx), xmm0) vfmadd231pd(xmm0, xmm3, xmm6) vmovsd(xmm6, mem(rcx)) add(rdi, rcx) vmovsd(mem(rcx), xmm0) vfmadd231pd(xmm0, xmm3, xmm8) vmovsd(xmm8, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovsd(xmm4, mem(rcx)) add(rdi, rcx) vmovsd(xmm6, mem(rcx)) add(rdi, rcx) vmovsd(xmm8, mem(rcx)) //add(rdi, rcx) label(.DDONE) label(.DRETURN) end_asm( : // output operands (none) : // input operands [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rd_haswell_asm_2x1 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; //uint64_t m_iter = m0 / 3; //uint64_t m_left = m0 % 3; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. //mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) //lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) //lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b //lea(mem(r8, r8, 2), r10) // r10 = 3*rs_a mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) // r12 = rcx = c // r14 = rax = a // rdx = rbx = b #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm6, ymm6, ymm6) #endif //lea(mem(r12), rcx) // rcx = c_ii; //lea(mem(r14), rax) // rax = a_ii; //lea(mem(rdx), rbx) // rbx = b; #if 1 //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) //lea(mem(rcx, rdi, 2), r10) // //lea(mem(r10, rdi, 1), r10) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 1*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 1*8)) // prefetch c + 1*rs_c #endif mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovupd(mem(rbx ), ymm0) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rax, r8, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm6) // ---------------------------------- iteration 1 vmovupd(mem(rbx ), ymm0) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rax, r8, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm6) // ---------------------------------- iteration 2 #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovupd(mem(rbx ), ymm0) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rax, r8, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm6) // ---------------------------------- iteration 3 vmovupd(mem(rbx ), ymm0) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rax, r8, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm6) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovupd(mem(rbx ), ymm0) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rax, r8, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm6) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rbx ), xmm0) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vmovsd(mem(rax ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovsd(mem(rax, r8, 1), xmm3) add(imm(1*8), rax) // a += 1*cs_a = 1*8; vfmadd231pd(ymm0, ymm3, ymm6) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 // ymm6 vhaddpd( ymm4, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm4 ) vhaddpd( ymm6, ymm6, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm6 ) // xmm4[0] = sum(ymm4) // xmm6[0] = sum(ymm6) //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(double) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(xmm0, xmm4, xmm4) // scale by alpha vmulpd(xmm0, xmm6, xmm6) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vmovsd(mem(rcx), xmm0) vfmadd231pd(xmm0, xmm3, xmm4) vmovsd(xmm4, mem(rcx)) add(rdi, rcx) vmovsd(mem(rcx), xmm0) vfmadd231pd(xmm0, xmm3, xmm6) vmovsd(xmm6, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovsd(xmm4, mem(rcx)) add(rdi, rcx) vmovsd(xmm6, mem(rcx)) //add(rdi, rcx) label(.DDONE) label(.DRETURN) end_asm( : // output operands (none) : // input operands [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rd_haswell_asm_1x1 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; //uint64_t m_iter = m0 / 3; //uint64_t m_left = m0 % 3; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. //mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) //lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) //lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b //lea(mem(r8, r8, 2), r10) // r10 = 3*rs_a mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) // r12 = rcx = c // r14 = rax = a // rdx = rbx = b #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) #endif //lea(mem(r12), rcx) // rcx = c_ii; //lea(mem(r14), rax) // rax = a_ii; //lea(mem(rdx), rbx) // rbx = b; #if 1 //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) //lea(mem(rcx, rdi, 2), r10) // //lea(mem(r10, rdi, 1), r10) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 1*8)) // prefetch c + 0*rs_c #endif mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovupd(mem(rbx ), ymm0) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm4) // ---------------------------------- iteration 1 vmovupd(mem(rbx ), ymm0) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm4) // ---------------------------------- iteration 2 #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovupd(mem(rbx ), ymm0) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm4) // ---------------------------------- iteration 3 vmovupd(mem(rbx ), ymm0) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm4) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovupd(mem(rbx ), ymm0) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm4) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rbx ), xmm0) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vmovsd(mem(rax ), xmm3) add(imm(1*8), rax) // a += 1*cs_a = 1*8; vfmadd231pd(ymm0, ymm3, ymm4) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 vhaddpd( ymm4, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm4 ) // xmm4[0] = sum(ymm4) //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(double) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(xmm0, xmm4, xmm4) // scale by alpha //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vmovsd(mem(rcx), xmm0) vfmadd231pd(xmm0, xmm3, xmm4) vmovsd(xmm4, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovsd(xmm4, mem(rcx)) //add(rdi, rcx) label(.DDONE) label(.DRETURN) end_asm( : // output operands (none) : // input operands [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } blis-0.9.0/kernels/haswell/3/sup/d6x8/bli_gemmsup_rd_haswell_asm_dMx2.c000066400000000000000000001375531422157504600257460ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define BLIS_ASM_SYNTAX_ATT #include "bli_x86_asm_macros.h" /* rrc: -------- ------ | | | | | | | | -------- ------ | | | | | | | | -------- += ------ ... | | | | | | | | -------- ------ | | | | | | | | -------- ------ : -------- ------ : Assumptions: - C is row-stored and B is column-stored; - A is row-stored; - m0 and n0 are at most MR and NR, respectively. Therefore, this (r)ow-preferential microkernel is well-suited for a dot-product-based accumulation that performs vector loads from both A and B. */ // Prototype reference microkernels. GEMMSUP_KER_PROT( double, d, gemmsup_r_haswell_ref ) void bli_dgemmsup_rd_haswell_asm_6x2 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; //uint64_t m_iter = m0 / 6; //uint64_t m_left = m0 % 6; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) //lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b //lea(mem(r8, r8, 2), r10) // r10 = 3*rs_a mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) // r12 = rcx = c // r14 = rax = a // rdx = rbx = b #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm5, ymm5, ymm5) vxorpd(ymm6, ymm6, ymm6) vxorpd(ymm7, ymm7, ymm7) vxorpd(ymm8, ymm8, ymm8) vxorpd(ymm9, ymm9, ymm9) vxorpd(ymm10, ymm10, ymm10) vxorpd(ymm11, ymm11, ymm11) vxorpd(ymm12, ymm12, ymm12) vxorpd(ymm13, ymm13, ymm13) vxorpd(ymm14, ymm14, ymm14) vxorpd(ymm15, ymm15, ymm15) #endif //lea(mem(r12), rcx) // rcx = c_ii; //lea(mem(r14), rax) // rax = a_ii; //lea(mem(rdx), rbx) // rbx = b; #if 1 //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) lea(mem(rcx, rdi, 2), r10) // lea(mem(r10, rdi, 1), r10) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 1*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 1*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 1*8)) // prefetch c + 2*rs_c prefetch(0, mem(r10, 1*8)) // prefetch c + 3*rs_c prefetch(0, mem(r10, rdi, 1, 1*8)) // prefetch c + 4*rs_c prefetch(0, mem(r10, rdi, 2, 1*8)) // prefetch c + 5*rs_c #endif mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovupd(mem(rax, r8, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) vmovupd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rax, r8, 4), ymm3) vfmadd231pd(ymm0, ymm3, ymm12) vfmadd231pd(ymm1, ymm3, ymm13) vmovupd(mem(rax, r15, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) // ---------------------------------- iteration 1 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovupd(mem(rax, r8, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) vmovupd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rax, r8, 4), ymm3) vfmadd231pd(ymm0, ymm3, ymm12) vfmadd231pd(ymm1, ymm3, ymm13) vmovupd(mem(rax, r15, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) // ---------------------------------- iteration 2 #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovupd(mem(rax, r8, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) vmovupd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rax, r8, 4), ymm3) vfmadd231pd(ymm0, ymm3, ymm12) vfmadd231pd(ymm1, ymm3, ymm13) vmovupd(mem(rax, r15, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) // ---------------------------------- iteration 3 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovupd(mem(rax, r8, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) vmovupd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rax, r8, 4), ymm3) vfmadd231pd(ymm0, ymm3, ymm12) vfmadd231pd(ymm1, ymm3, ymm13) vmovupd(mem(rax, r15, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovupd(mem(rax, r8, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) vmovupd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rax, r8, 4), ymm3) vfmadd231pd(ymm0, ymm3, ymm12) vfmadd231pd(ymm1, ymm3, ymm13) vmovupd(mem(rax, r15, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rbx ), xmm0) vmovsd(mem(rbx, r11, 1), xmm1) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vmovsd(mem(rax ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovsd(mem(rax, r8, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovsd(mem(rax, r8, 2), xmm3) vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) vmovsd(mem(rax, r13, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovsd(mem(rax, r8, 4), xmm3) vfmadd231pd(ymm0, ymm3, ymm12) vfmadd231pd(ymm1, ymm3, ymm13) vmovsd(mem(rax, r15, 1), xmm3) add(imm(1*8), rax) // a += 1*cs_a = 1*8; vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm5 // ymm6 ymm7 // ymm8 ymm9 // ymm10 ymm11 // ymm12 ymm13 // ymm14 ymm15 vhaddpd( ymm5, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm4 ) vhaddpd( ymm7, ymm6, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm6 ) vhaddpd( ymm9, ymm8, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm8 ) vhaddpd( ymm11, ymm10, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm10 ) vhaddpd( ymm13, ymm12, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm12 ) vhaddpd( ymm15, ymm14, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm14 ) // xmm4[0:1] = sum(ymm4) sum(ymm5) // xmm6[0:1] = sum(ymm6) sum(ymm7) // xmm8[0:1] = sum(ymm8) sum(ymm9) // xmm10[0:1] = sum(ymm10) sum(ymm11) // xmm12[0:1] = sum(ymm12) sum(ymm13) // xmm14[0:1] = sum(ymm14) sum(ymm15) //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(xmm0, xmm4, xmm4) // scale by alpha vmulpd(xmm0, xmm6, xmm6) vmulpd(xmm0, xmm8, xmm8) vmulpd(xmm0, xmm10, xmm10) vmulpd(xmm0, xmm12, xmm12) vmulpd(xmm0, xmm14, xmm14) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), xmm3, xmm4) vmovupd(xmm4, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), xmm3, xmm6) vmovupd(xmm6, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), xmm3, xmm8) vmovupd(xmm8, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), xmm3, xmm10) vmovupd(xmm10, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), xmm3, xmm12) vmovupd(xmm12, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), xmm3, xmm14) vmovupd(xmm14, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(xmm4, mem(rcx)) add(rdi, rcx) vmovupd(xmm6, mem(rcx)) add(rdi, rcx) vmovupd(xmm8, mem(rcx)) add(rdi, rcx) vmovupd(xmm10, mem(rcx)) add(rdi, rcx) vmovupd(xmm12, mem(rcx)) add(rdi, rcx) vmovupd(xmm14, mem(rcx)) //add(rdi, rcx) label(.DDONE) label(.DRETURN) end_asm( : // output operands (none) : // input operands [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rd_haswell_asm_3x2 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; //uint64_t m_iter = m0 / 6; //uint64_t m_left = m0 % 6; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) //lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b //lea(mem(r8, r8, 2), r10) // r10 = 3*rs_a mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) // r12 = rcx = c // r14 = rax = a // rdx = rbx = b #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm5, ymm5, ymm5) vxorpd(ymm6, ymm6, ymm6) vxorpd(ymm7, ymm7, ymm7) vxorpd(ymm8, ymm8, ymm8) vxorpd(ymm9, ymm9, ymm9) #endif //lea(mem(r12), rcx) // rcx = c_ii; //lea(mem(r14), rax) // rax = a_ii; //lea(mem(rdx), rbx) // rbx = b; #if 1 //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) //lea(mem(rcx, rdi, 2), r10) // //lea(mem(r10, rdi, 1), r10) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 1*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 1*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 1*8)) // prefetch c + 2*rs_c #endif mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovupd(mem(rax, r8, 2), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) // ---------------------------------- iteration 1 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovupd(mem(rax, r8, 2), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) // ---------------------------------- iteration 2 #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovupd(mem(rax, r8, 2), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) // ---------------------------------- iteration 3 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovupd(mem(rax, r8, 2), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovupd(mem(rax, r8, 2), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rbx ), xmm0) vmovsd(mem(rbx, r11, 1), xmm1) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vmovsd(mem(rax ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovsd(mem(rax, r8, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovsd(mem(rax, r8, 2), xmm3) add(imm(1*8), rax) // a += 1*cs_a = 1*8; vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm5 // ymm6 ymm7 // ymm8 ymm9 vhaddpd( ymm5, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm4 ) vhaddpd( ymm7, ymm6, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm6 ) vhaddpd( ymm9, ymm8, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm8 ) // xmm4[0:1] = sum(ymm4) sum(ymm5) // xmm6[0:1] = sum(ymm6) sum(ymm7) // xmm8[0:1] = sum(ymm8) sum(ymm9) //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(xmm0, xmm4, xmm4) // scale by alpha vmulpd(xmm0, xmm6, xmm6) vmulpd(xmm0, xmm8, xmm8) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), xmm3, xmm4) vmovupd(xmm4, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), xmm3, xmm6) vmovupd(xmm6, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), xmm3, xmm8) vmovupd(xmm8, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(xmm4, mem(rcx)) add(rdi, rcx) vmovupd(xmm6, mem(rcx)) add(rdi, rcx) vmovupd(xmm8, mem(rcx)) //add(rdi, rcx) label(.DDONE) label(.DRETURN) end_asm( : // output operands (none) : // input operands [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rd_haswell_asm_2x2 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; //uint64_t m_iter = m0 / 6; //uint64_t m_left = m0 % 6; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) //lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b //lea(mem(r8, r8, 2), r10) // r10 = 3*rs_a mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) // r12 = rcx = c // r14 = rax = a // rdx = rbx = b #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm5, ymm5, ymm5) vxorpd(ymm6, ymm6, ymm6) vxorpd(ymm7, ymm7, ymm7) #endif //lea(mem(r12), rcx) // rcx = c_ii; //lea(mem(r14), rax) // rax = a_ii; //lea(mem(rdx), rbx) // rbx = b; #if 1 //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) //lea(mem(rcx, rdi, 2), r10) // //lea(mem(r10, rdi, 1), r10) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 1*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 1*8)) // prefetch c + 1*rs_c #endif mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) // ---------------------------------- iteration 1 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) // ---------------------------------- iteration 2 #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) // ---------------------------------- iteration 3 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rbx ), xmm0) vmovsd(mem(rbx, r11, 1), xmm1) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vmovsd(mem(rax ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovsd(mem(rax, r8, 1), xmm3) add(imm(1*8), rax) // a += 1*cs_a = 1*8; vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm5 // ymm6 ymm7 vhaddpd( ymm5, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm4 ) vhaddpd( ymm7, ymm6, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm6 ) // xmm4[0:1] = sum(ymm4) sum(ymm5) // xmm6[0:1] = sum(ymm6) sum(ymm7) //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(xmm0, xmm4, xmm4) // scale by alpha vmulpd(xmm0, xmm6, xmm6) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), xmm3, xmm4) vmovupd(xmm4, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), xmm3, xmm6) vmovupd(xmm6, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(xmm4, mem(rcx)) add(rdi, rcx) vmovupd(xmm6, mem(rcx)) //add(rdi, rcx) label(.DDONE) label(.DRETURN) end_asm( : // output operands (none) : // input operands [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rd_haswell_asm_1x2 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; //uint64_t m_iter = m0 / 6; //uint64_t m_left = m0 % 6; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) //lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b //lea(mem(r8, r8, 2), r10) // r10 = 3*rs_a mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) // r12 = rcx = c // r14 = rax = a // rdx = rbx = b #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm5, ymm5, ymm5) #endif //lea(mem(r12), rcx) // rcx = c_ii; //lea(mem(r14), rax) // rax = a_ii; //lea(mem(rdx), rbx) // rbx = b; #if 1 //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) //lea(mem(rcx, rdi, 2), r10) // //lea(mem(r10, rdi, 1), r10) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 1*8)) // prefetch c + 0*rs_c #endif mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) // ---------------------------------- iteration 1 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) // ---------------------------------- iteration 2 #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) // ---------------------------------- iteration 3 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rbx ), xmm0) vmovsd(mem(rbx, r11, 1), xmm1) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vmovsd(mem(rax ), xmm3) add(imm(1*8), rax) // a += 1*cs_a = 1*8; vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm5 vhaddpd( ymm5, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm4 ) // xmm4[0:1] = sum(ymm4) sum(ymm5) //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(xmm0, xmm4, xmm4) // scale by alpha //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), xmm3, xmm4) vmovupd(xmm4, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(xmm4, mem(rcx)) //add(rdi, rcx) label(.DDONE) label(.DRETURN) end_asm( : // output operands (none) : // input operands [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } blis-0.9.0/kernels/haswell/3/sup/d6x8/bli_gemmsup_rd_haswell_asm_dMx4.c000066400000000000000000001131611422157504600257350ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define BLIS_ASM_SYNTAX_ATT #include "bli_x86_asm_macros.h" /* rrc: -------- ------ | | | | | | | | -------- ------ | | | | | | | | -------- += ------ ... | | | | | | | | -------- ------ | | | | | | | | -------- ------ : -------- ------ : Assumptions: - C is row-stored and B is column-stored; - A is row-stored; - m0 and n0 are at most MR and NR, respectively. Therefore, this (r)ow-preferential microkernel is well-suited for a dot-product-based accumulation that performs vector loads from both A and B. */ // Prototype reference microkernels. GEMMSUP_KER_PROT( double, d, gemmsup_r_haswell_ref ) void bli_dgemmsup_rd_haswell_asm_6x4 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t m_iter = m0 / 3; //uint64_t m_left = m0 % 3; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), r14) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rdx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b lea(mem(r8, r8, 2), r10) // r10 = 3*rs_a mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) // r12 = rcx = c // r14 = rax = a // rdx = rbx = b // r9 = m dim index ii mov(var(m_iter), r9) // ii = m_iter; label(.DLOOP3X4I) // LOOP OVER ii = [ m_iter .. 1 0 ] #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm5, ymm5, ymm5) vxorpd(ymm6, ymm6, ymm6) vxorpd(ymm7, ymm7, ymm7) vxorpd(ymm8, ymm8, ymm8) vxorpd(ymm9, ymm9, ymm9) vxorpd(ymm10, ymm10, ymm10) vxorpd(ymm11, ymm11, ymm11) vxorpd(ymm12, ymm12, ymm12) vxorpd(ymm13, ymm13, ymm13) vxorpd(ymm14, ymm14, ymm14) vxorpd(ymm15, ymm15, ymm15) #endif lea(mem(r12), rcx) // rcx = c_ii; lea(mem(r14), rax) // rax = a_ii; lea(mem(rdx), rbx) // rbx = b; #if 1 //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 3*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 3*8)) // prefetch c + 2*rs_c #endif lea(mem(r8, r8, 4), rbp) // rbp = 5*rs_a mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 1 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 2 #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 3 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rax ), xmm0) vmovsd(mem(rax, r8, 1), xmm1) vmovsd(mem(rax, r8, 2), xmm2) add(imm(1*8), rax) // a += 1*cs_a = 1*8; vmovsd(mem(rbx ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovsd(mem(rbx, r11, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovsd(mem(rbx, r11, 2), xmm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovsd(mem(rbx, r13, 1), xmm3) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 // ymm5 ymm8 ymm11 ymm14 // ymm6 ymm9 ymm12 ymm15 vhaddpd( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm4 ) vhaddpd( ymm8, ymm5, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm14, ymm11, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm5 ) vhaddpd( ymm9, ymm6, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm15, ymm12, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm6 ) // xmm4[0:3] = sum(ymm4) sum(ymm7) sum(ymm10) sum(ymm13) // xmm5[0:3] = sum(ymm5) sum(ymm8) sum(ymm11) sum(ymm14) // xmm6[0:3] = sum(ymm6) sum(ymm9) sum(ymm12) sum(ymm15) //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(ymm0, ymm5, ymm5) vmulpd(ymm0, ymm6, ymm6) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), ymm3, ymm4) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm5) vmovupd(ymm5, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm6) vmovupd(ymm6, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vmovupd(ymm5, mem(rcx)) add(rdi, rcx) vmovupd(ymm6, mem(rcx)) //add(rdi, rcx) label(.DDONE) lea(mem(r12, rdi, 2), r12) // lea(mem(r12, rdi, 1), r12) // c_ii = r12 += 3*rs_c lea(mem(r14, r8, 2), r14) // lea(mem(r14, r8, 1), r14) // a_ii = r14 += 3*rs_a dec(r9) // ii -= 1; jne(.DLOOP3X4I) // iterate again if ii != 0. label(.DRETURN) end_asm( : // output operands (none) : // input operands [m_iter] "m" (m_iter), [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rd_haswell_asm_2x4 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b //lea(mem(r8, r8, 2), r10) // r10 = 3*rs_a mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) // r12 = rcx = c // r14 = rax = a // rdx = rbx = b #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm5, ymm5, ymm5) vxorpd(ymm7, ymm7, ymm7) vxorpd(ymm8, ymm8, ymm8) vxorpd(ymm10, ymm10, ymm10) vxorpd(ymm11, ymm11, ymm11) vxorpd(ymm13, ymm13, ymm13) vxorpd(ymm14, ymm14, ymm14) #endif //lea(mem(r12), rcx) // rcx = c; //lea(mem(r14), rax) // rax = a; //lea(mem(rdx), rbx) // rbx = b; #if 1 //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 3*8)) // prefetch c + 1*rs_c #endif mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a #endif vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) // ---------------------------------- iteration 1 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) // ---------------------------------- iteration 2 #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a #endif vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) // ---------------------------------- iteration 3 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a #endif vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rax ), xmm0) vmovsd(mem(rax, r8, 1), xmm1) add(imm(1*8), rax) // a += 1*cs_a = 1*8; vmovsd(mem(rbx ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovsd(mem(rbx, r11, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovsd(mem(rbx, r11, 2), xmm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovsd(mem(rbx, r13, 1), xmm3) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 // ymm5 ymm8 ymm11 ymm14 vhaddpd( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm4 ) vhaddpd( ymm8, ymm5, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm14, ymm11, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm5 ) // xmm4[0:3] = sum(ymm4) sum(ymm7) sum(ymm10) sum(ymm13) // xmm5[0:3] = sum(ymm5) sum(ymm8) sum(ymm11) sum(ymm14) //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(ymm0, ymm5, ymm5) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), ymm3, ymm4) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm5) vmovupd(ymm5, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vmovupd(ymm5, mem(rcx)) //add(rdi, rcx) label(.DDONE) label(.DRETURN) end_asm( : // output operands (none) : // input operands [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rd_haswell_asm_1x4 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b //lea(mem(r8, r8, 2), r10) // r10 = 3*rs_a mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) // r12 = rcx = c // r14 = rax = a // rdx = rbx = b #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm7, ymm7, ymm7) vxorpd(ymm10, ymm10, ymm10) vxorpd(ymm13, ymm13, ymm13) #endif //lea(mem(r12), rcx) // rcx = c; //lea(mem(r14), rax) // rax = a; //lea(mem(rdx), rbx) // rbx = b; #if 1 //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c //prefetch(0, mem(rcx, rdi, 1, 3*8)) // prefetch c + 1*rs_c #endif mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a #endif vmovupd(mem(rax ), ymm0) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) // ---------------------------------- iteration 1 vmovupd(mem(rax ), ymm0) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) // ---------------------------------- iteration 2 #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a #endif vmovupd(mem(rax ), ymm0) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) // ---------------------------------- iteration 3 vmovupd(mem(rax ), ymm0) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a #endif vmovupd(mem(rax ), ymm0) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rax ), xmm0) add(imm(1*8), rax) // a += 1*cs_a = 1*8; vmovsd(mem(rbx ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovsd(mem(rbx, r11, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovsd(mem(rbx, r11, 2), xmm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovsd(mem(rbx, r13, 1), xmm3) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vfmadd231pd(ymm0, ymm3, ymm13) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 vhaddpd( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm4 ) // xmm4[0:3] = sum(ymm4) sum(ymm7) sum(ymm10) sum(ymm13) //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), ymm3, ymm4) vmovupd(ymm4, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx)) //add(rdi, rcx) label(.DDONE) label(.DRETURN) end_asm( : // output operands (none) : // input operands [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } blis-0.9.0/kernels/haswell/3/sup/d6x8/bli_gemmsup_rd_haswell_asm_dMx8.c000066400000000000000000001261351422157504600257460ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define BLIS_ASM_SYNTAX_ATT #include "bli_x86_asm_macros.h" /* rrc: -------- ------ | | | | | | | | -------- ------ | | | | | | | | -------- += ------ ... | | | | | | | | -------- ------ | | | | | | | | -------- ------ : -------- ------ : Assumptions: - C is row-stored and B is column-stored; - A is row-stored; - m0 and n0 are at most MR and NR, respectively. Therefore, this (r)ow-preferential microkernel is well-suited for a dot-product-based accumulation that performs vector loads from both A and B. */ // Prototype reference microkernels. GEMMSUP_KER_PROT( double, d, gemmsup_r_haswell_ref ) void bli_dgemmsup_rd_haswell_asm_6x8 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { uint64_t n_left = n0 % 8; // First check whether this is a edge case in the n dimension. If so, // dispatch other 6x?m kernels, as needed. if ( n_left ) { double* restrict cij = c; double* restrict bj = b; double* restrict ai = a; if ( 4 <= n_left ) { const dim_t nr_cur = 4; bli_dgemmsup_rd_haswell_asm_6x4 //bli_dgemmsup_r_haswell_ref ( conja, conjb, m0, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 2 <= n_left ) { const dim_t nr_cur = 2; bli_dgemmsup_rd_haswell_asm_6x2 //bli_dgemmsup_r_haswell_ref ( conja, conjb, m0, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 1 == n_left ) { #if 1 const dim_t nr_cur = 1; bli_dgemmsup_rd_haswell_asm_6x1 //bli_dgemmsup_r_haswell_ref ( conja, conjb, m0, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); #else bli_dgemv_ex ( BLIS_NO_TRANSPOSE, conjb, m0, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, beta, cij, rs_c0, cntx, NULL ); #endif } return; } //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t m_iter = m0 / 3; uint64_t m_left = m0 % 3; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; if ( m_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. //mov(var(a), r14) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a //mov(var(b), rdx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b lea(mem(r8, r8, 2), r10) // r10 = 3*rs_a //mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) // r12 = rcx = c // r14 = rax = a // rdx = rbx = b // r9 = m dim index ii // r15 = n dim index jj mov(imm(0), r15) // jj = 0; label(.DLOOP3X4J) // LOOP OVER jj = [ 0 1 ... ] mov(var(a), r14) // load address of a mov(var(b), rdx) // load address of b mov(var(c), r12) // load address of c lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(imm(1*8), rsi) // rsi *= cs_c*sizeof(double) = 1*8 lea(mem(r12, rsi, 1), r12) // r12 = c + 4*jj*cs_c; lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(r11, rsi) // rsi *= cs_b; lea(mem(rdx, rsi, 1), rdx) // rbx = b + 4*jj*cs_b; mov(var(m_iter), r9) // ii = m_iter; label(.DLOOP3X4I) // LOOP OVER ii = [ m_iter ... 1 0 ] #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm5, ymm5, ymm5) vxorpd(ymm6, ymm6, ymm6) vxorpd(ymm7, ymm7, ymm7) vxorpd(ymm8, ymm8, ymm8) vxorpd(ymm9, ymm9, ymm9) vxorpd(ymm10, ymm10, ymm10) vxorpd(ymm11, ymm11, ymm11) vxorpd(ymm12, ymm12, ymm12) vxorpd(ymm13, ymm13, ymm13) vxorpd(ymm14, ymm14, ymm14) vxorpd(ymm15, ymm15, ymm15) #endif lea(mem(r12), rcx) // rcx = c_iijj; lea(mem(r14), rax) // rax = a_ii; lea(mem(rdx), rbx) // rbx = b_jj; #if 1 //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 3*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 3*8)) // prefetch c + 2*rs_c #endif lea(mem(r8, r8, 4), rbp) // rbp = 5*rs_a mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 1 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 2 #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 3 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rax ), xmm0) vmovsd(mem(rax, r8, 1), xmm1) vmovsd(mem(rax, r8, 2), xmm2) add(imm(1*8), rax) // a += 1*cs_a = 1*8; vmovsd(mem(rbx ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovsd(mem(rbx, r11, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovsd(mem(rbx, r11, 2), xmm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovsd(mem(rbx, r13, 1), xmm3) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 // ymm5 ymm8 ymm11 ymm14 // ymm6 ymm9 ymm12 ymm15 vhaddpd( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm4 ) // xmm4[0] = sum(ymm4); xmm4[1] = sum(ymm7) // xmm4[2] = sum(ymm10); xmm4[3] = sum(ymm13) vhaddpd( ymm8, ymm5, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm14, ymm11, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm5 ) // xmm5[0] = sum(ymm5); xmm5[1] = sum(ymm8) // xmm5[2] = sum(ymm11); xmm5[3] = sum(ymm14) vhaddpd( ymm9, ymm6, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm15, ymm12, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm6 ) // xmm6[0] = sum(ymm6); xmm6[1] = sum(ymm9) // xmm6[2] = sum(ymm12); xmm6[3] = sum(ymm15) //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(ymm0, ymm5, ymm5) vmulpd(ymm0, ymm6, ymm6) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), ymm3, ymm4) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm5) vmovupd(ymm5, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm6) vmovupd(ymm6, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vmovupd(ymm5, mem(rcx)) add(rdi, rcx) vmovupd(ymm6, mem(rcx)) //add(rdi, rcx) label(.DDONE) lea(mem(r12, rdi, 2), r12) // lea(mem(r12, rdi, 1), r12) // c_ii = r12 += 3*rs_c lea(mem(r14, r8, 2), r14) // lea(mem(r14, r8, 1), r14) // a_ii = r14 += 3*rs_a dec(r9) // ii -= 1; jne(.DLOOP3X4I) // iterate again if ii != 0. add(imm(4), r15) // jj += 4; cmp(imm(8), r15) // compare jj to 8 jl(.DLOOP3X4J) // if jj < 8, jump to beginning // of jj loop; otherwise, loop ends. label(.DRETURN) end_asm( : // output operands (none) : // input operands [m_iter] "m" (m_iter), [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the m dimension, if they exist. if ( m_left ) { const dim_t nr_cur = 8; const dim_t i_edge = m0 - ( dim_t )m_left; double* restrict cij = c + i_edge*rs_c; double* restrict bj = b; double* restrict ai = a + i_edge*rs_a; if ( 2 == m_left ) { const dim_t mr_cur = 2; bli_dgemmsup_rd_haswell_asm_2x8 //bli_dgemmsup_r_haswell_ref ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); //cij += mr_cur*rs_c0; ai += mr_cur*rs_a0; m_left -= mr_cur; } if ( 1 == m_left ) { const dim_t mr_cur = 1; bli_dgemmsup_rd_haswell_asm_1x8 //bli_dgemmsup_r_haswell_ref ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); } } } void bli_dgemmsup_rd_haswell_asm_2x8 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), r14) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rdx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b //lea(mem(r8, r8, 2), r10) // r10 = 3*rs_a mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) // r12 = rcx = c // r14 = rax = a // rdx = rbx = b // r9 = unused // r15 = n dim index jj mov(imm(0), r15) // jj = 0; label(.DLOOP3X4J) // LOOP OVER jj = [ 0 1 ... ] #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm5, ymm5, ymm5) vxorpd(ymm7, ymm7, ymm7) vxorpd(ymm8, ymm8, ymm8) vxorpd(ymm10, ymm10, ymm10) vxorpd(ymm11, ymm11, ymm11) vxorpd(ymm13, ymm13, ymm13) vxorpd(ymm14, ymm14, ymm14) #endif lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(imm(1*8), rsi) // rsi *= cs_c*sizeof(double) = 1*8 lea(mem(r12, rsi, 1), rcx) // rcx = c + 4*jj*cs_c; lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(r11, rsi) // rsi *= cs_b; lea(mem(rdx, rsi, 1), rbx) // rbx = b + 4*jj*cs_b; lea(mem(r14), rax) // rax = a; #if 1 //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 3*8)) // prefetch c + 1*rs_c #endif mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) // ---------------------------------- iteration 1 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) // ---------------------------------- iteration 2 #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) // ---------------------------------- iteration 3 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rax ), xmm0) vmovsd(mem(rax, r8, 1), xmm1) add(imm(1*8), rax) // a += 1*cs_a = 1*8; vmovsd(mem(rbx ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovsd(mem(rbx, r11, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovsd(mem(rbx, r11, 2), xmm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovsd(mem(rbx, r13, 1), xmm3) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 // ymm5 ymm8 ymm11 ymm14 vhaddpd( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm4 ) // xmm4[0] = sum(ymm4); xmm4[1] = sum(ymm7) // xmm4[2] = sum(ymm10); xmm4[3] = sum(ymm13) vhaddpd( ymm8, ymm5, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm14, ymm11, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm5 ) // xmm5[0] = sum(ymm5); xmm5[1] = sum(ymm8) // xmm5[2] = sum(ymm11); xmm5[3] = sum(ymm14) //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(ymm0, ymm5, ymm5) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), ymm3, ymm4) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm5) vmovupd(ymm5, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vmovupd(ymm5, mem(rcx)) //add(rdi, rcx) label(.DDONE) add(imm(4), r15) // jj += 4; cmp(imm(8), r15) // compare jj to 8 jl(.DLOOP3X4J) // if jj < 8, jump to beginning // of jj loop; otherwise, loop ends. label(.DRETURN) end_asm( : // output operands (none) : // input operands [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rd_haswell_asm_1x8 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), r14) // load address of a. //mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a //lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rdx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b //lea(mem(r8, r8, 2), r10) // r10 = 3*rs_a mov(var(c), r12) // load address of c //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) // r12 = rcx = c // r14 = rax = a // rdx = rbx = b // r9 = m dim index ii // r15 = n dim index jj mov(imm(0), r15) // jj = 0; label(.DLOOP3X4J) // LOOP OVER jj = [ 0 1 ... ] #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm7, ymm7, ymm7) vxorpd(ymm10, ymm10, ymm10) vxorpd(ymm13, ymm13, ymm13) #endif lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(imm(1*8), rsi) // rsi *= cs_c*sizeof(double) = 1*8 lea(mem(r12, rsi, 1), rcx) // rcx = c + 4*jj*cs_c; lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(r11, rsi) // rsi *= cs_b; lea(mem(rdx, rsi, 1), rbx) // rbx = b + 4*jj*cs_b; lea(mem(r14), rax) // rax = a; #if 1 //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c #endif mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovupd(mem(rax ), ymm0) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) // ---------------------------------- iteration 1 vmovupd(mem(rax ), ymm0) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) // ---------------------------------- iteration 2 #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovupd(mem(rax ), ymm0) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) // ---------------------------------- iteration 3 vmovupd(mem(rax ), ymm0) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovupd(mem(rax ), ymm0) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rax ), xmm0) add(imm(1*8), rax) // a += 1*cs_a = 1*8; vmovsd(mem(rbx ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovsd(mem(rbx, r11, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovsd(mem(rbx, r11, 2), xmm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovsd(mem(rbx, r13, 1), xmm3) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vfmadd231pd(ymm0, ymm3, ymm13) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 vhaddpd( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm4 ) // xmm4[0] = sum(ymm4); xmm4[1] = sum(ymm7) // xmm4[2] = sum(ymm10); xmm4[3] = sum(ymm13) //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), ymm3, ymm4) vmovupd(ymm4, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx)) //add(rdi, rcx) label(.DDONE) add(imm(4), r15) // jj += 4; cmp(imm(8), r15) // compare jj to 8 jl(.DLOOP3X4J) // if jj < 8, jump to beginning // of jj loop; otherwise, loop ends. label(.DRETURN) end_asm( : // output operands (none) : // input operands [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } blis-0.9.0/kernels/haswell/3/sup/d6x8/bli_gemmsup_rv_haswell_asm_dMx2.c000066400000000000000000002016621422157504600257610ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define BLIS_ASM_SYNTAX_ATT #include "bli_x86_asm_macros.h" /* rrr: -------- ------ -------- -------- ------ -------- -------- += ------ ... -------- -------- ------ -------- -------- ------ : -------- ------ : rcr: -------- | | | | -------- -------- | | | | -------- -------- += | | | | ... -------- -------- | | | | -------- -------- | | | | : -------- | | | | : Assumptions: - B is row-stored; - A is row- or column-stored; - m0 and n0 are at most MR and NR, respectively. Therefore, this (r)ow-preferential kernel is well-suited for contiguous (v)ector loads on B and single-element broadcasts from A. NOTE: These kernels explicitly support column-oriented IO, implemented via an in-register transpose. And thus they also support the crr and ccr cases, though only crr is ever utilized (because ccr is handled by transposing the operation and executing rcr, which does not incur the cost of the in-register transpose). crr: | | | | | | | | ------ -------- | | | | | | | | ------ -------- | | | | | | | | += ------ ... -------- | | | | | | | | ------ -------- | | | | | | | | ------ : | | | | | | | | ------ : */ // Prototype reference microkernels. GEMMSUP_KER_PROT( double, d, gemmsup_r_haswell_ref ) void bli_dgemmsup_rv_haswell_asm_6x2 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) //lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLPFETCH) // jump to column storage case label(.DROWPFETCH) // row-stored prefetching on c lea(mem(rcx, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 1*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 1*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 1*8)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 1*8)) // prefetch c + 3*rs_c prefetch(0, mem(rdx, rdi, 1, 1*8)) // prefetch c + 4*rs_c prefetch(0, mem(rdx, rdi, 2, 1*8)) // prefetch c + 5*rs_c jmp(.DPOSTPFETCH) // jump to end of prefetching c label(.DCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 8), rsi) // cs_c *= sizeof(double) //lea(mem(rsi, rsi, 2), rbp) // rbp = 3*cs_c; prefetch(0, mem(rcx, 5*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 5*8)) // prefetch c + 1*cs_c label(.DPOSTPFETCH) // done prefetching c #if 1 lea(mem(rax, r9, 8), rdx) // lea(mem(rdx, r9, 8), rdx) // rdx = a + 16*cs_a; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.DLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(rdx, 5*8)) #endif vmovupd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(xmm0, xmm2, xmm4) vfmadd231pd(xmm0, xmm3, xmm6) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(xmm0, xmm2, xmm8) vfmadd231pd(xmm0, xmm3, xmm10) vbroadcastsd(mem(rax, r8, 4), ymm2) vbroadcastsd(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(xmm0, xmm2, xmm12) vfmadd231pd(xmm0, xmm3, xmm14) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, r9, 1, 5*8)) #endif vmovupd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(xmm0, xmm2, xmm4) vfmadd231pd(xmm0, xmm3, xmm6) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(xmm0, xmm2, xmm8) vfmadd231pd(xmm0, xmm3, xmm10) vbroadcastsd(mem(rax, r8, 4), ymm2) vbroadcastsd(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(xmm0, xmm2, xmm12) vfmadd231pd(xmm0, xmm3, xmm14) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(rdx, 5*8)) #endif vmovupd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(xmm0, xmm2, xmm4) vfmadd231pd(xmm0, xmm3, xmm6) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(xmm0, xmm2, xmm8) vfmadd231pd(xmm0, xmm3, xmm10) vbroadcastsd(mem(rax, r8, 4), ymm2) vbroadcastsd(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(xmm0, xmm2, xmm12) vfmadd231pd(xmm0, xmm3, xmm14) // ---------------------------------- iteration 3 #if 1 lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; #endif vmovupd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(xmm0, xmm2, xmm4) vfmadd231pd(xmm0, xmm3, xmm6) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(xmm0, xmm2, xmm8) vfmadd231pd(xmm0, xmm3, xmm10) vbroadcastsd(mem(rax, r8, 4), ymm2) vbroadcastsd(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(xmm0, xmm2, xmm12) vfmadd231pd(xmm0, xmm3, xmm14) dec(rsi) // i -= 1; jne(.DLOOPKITER) // iterate again if i != 0. label(.DCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.DLOOPKLEFT) // EDGE LOOP #if 0 prefetch(0, mem(rdx, 5*8)) add(r9, rdx) #endif vmovupd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(xmm0, xmm2, xmm4) vfmadd231pd(xmm0, xmm3, xmm6) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(xmm0, xmm2, xmm8) vfmadd231pd(xmm0, xmm3, xmm10) vbroadcastsd(mem(rax, r8, 4), ymm2) vbroadcastsd(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(xmm0, xmm2, xmm12) vfmadd231pd(xmm0, xmm3, xmm14) dec(rsi) // i -= 1; jne(.DLOOPKLEFT) // iterate again if i != 0. label(.DPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(xmm0, xmm4, xmm4) // scale by alpha vmulpd(xmm0, xmm6, xmm6) vmulpd(xmm0, xmm8, xmm8) vmulpd(xmm0, xmm10, xmm10) vmulpd(xmm0, xmm12, xmm12) vmulpd(xmm0, xmm14, xmm14) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; //lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORED) // jump to column storage case label(.DROWSTORED) vfmadd231pd(mem(rcx, 0*32), xmm3, xmm4) vmovupd(xmm4, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), xmm3, xmm6) vmovupd(xmm6, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), xmm3, xmm8) vmovupd(xmm8, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), xmm3, xmm10) vmovupd(xmm10, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), xmm3, xmm12) vmovupd(xmm12, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), xmm3, xmm14) vmovupd(xmm14, mem(rcx, 0*32)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORED) // begin I/O on columns 0-1 vunpcklpd(xmm6, xmm4, xmm0) vunpckhpd(xmm6, xmm4, xmm1) vunpcklpd(xmm10, xmm8, xmm2) vunpckhpd(xmm10, xmm8, xmm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vbroadcastsd(mem(rbx), ymm3) vfmadd231pd(mem(rcx ), ymm3, ymm4) vfmadd231pd(mem(rcx, rsi, 1), ymm3, ymm6) vmovupd(ymm4, mem(rcx )) vmovupd(ymm6, mem(rcx, rsi, 1)) //lea(mem(rcx, rsi, 4), rcx) vunpcklpd(xmm14, xmm12, xmm0) vunpckhpd(xmm14, xmm12, xmm1) vfmadd231pd(mem(rdx ), xmm3, xmm0) vfmadd231pd(mem(rdx, rsi, 1), xmm3, xmm1) vmovupd(xmm0, mem(rdx )) vmovupd(xmm1, mem(rdx, rsi, 1)) //lea(mem(rdx, rsi, 4), rdx) jmp(.DDONE) // jump to end. label(.DBETAZERO) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORBZ) // jump to column storage case label(.DROWSTORBZ) vmovupd(xmm4, mem(rcx, 0*32)) add(rdi, rcx) vmovupd(xmm6, mem(rcx, 0*32)) add(rdi, rcx) vmovupd(xmm8, mem(rcx, 0*32)) add(rdi, rcx) vmovupd(xmm10, mem(rcx, 0*32)) add(rdi, rcx) vmovupd(xmm12, mem(rcx, 0*32)) add(rdi, rcx) vmovupd(xmm14, mem(rcx, 0*32)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORBZ) // begin I/O on columns 0-1 vunpcklpd(xmm6, xmm4, xmm0) vunpckhpd(xmm6, xmm4, xmm1) vunpcklpd(xmm10, xmm8, xmm2) vunpckhpd(xmm10, xmm8, xmm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vmovupd(ymm4, mem(rcx)) vmovupd(ymm6, mem(rcx, rsi, 1)) //lea(mem(rcx, rsi, 4), rcx) vunpcklpd(xmm14, xmm12, xmm0) vunpckhpd(xmm14, xmm12, xmm1) vmovupd(xmm0, mem(rdx)) vmovupd(xmm1, mem(rdx, rsi, 1)) //lea(mem(rdx, rsi, 4), rdx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rv_haswell_asm_5x2 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) //lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLPFETCH) // jump to column storage case label(.DROWPFETCH) // row-stored prefetching on c lea(mem(rcx, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 1*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 1*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 1*8)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 1*8)) // prefetch c + 3*rs_c prefetch(0, mem(rdx, rdi, 1, 1*8)) // prefetch c + 4*rs_c jmp(.DPOSTPFETCH) // jump to end of prefetching c label(.DCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 8), rsi) // cs_c *= sizeof(double) //lea(mem(rsi, rsi, 2), rbp) // rbp = 3*cs_c; prefetch(0, mem(rcx, 4*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 4*8)) // prefetch c + 1*cs_c label(.DPOSTPFETCH) // done prefetching c #if 1 lea(mem(rax, r9, 8), rdx) // lea(mem(rdx, r9, 8), rdx) // rdx = a + 16*cs_a; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.DLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(rdx, 5*8)) #endif vmovupd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(xmm0, xmm2, xmm4) vfmadd231pd(xmm0, xmm3, xmm6) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(xmm0, xmm2, xmm8) vfmadd231pd(xmm0, xmm3, xmm10) vbroadcastsd(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(xmm0, xmm2, xmm12) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, r9, 1, 5*8)) #endif vmovupd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(xmm0, xmm2, xmm4) vfmadd231pd(xmm0, xmm3, xmm6) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(xmm0, xmm2, xmm8) vfmadd231pd(xmm0, xmm3, xmm10) vbroadcastsd(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(xmm0, xmm2, xmm12) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(rdx, r9, 2, 5*8)) #endif vmovupd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(xmm0, xmm2, xmm4) vfmadd231pd(xmm0, xmm3, xmm6) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(xmm0, xmm2, xmm8) vfmadd231pd(xmm0, xmm3, xmm10) vbroadcastsd(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(xmm0, xmm2, xmm12) // ---------------------------------- iteration 3 #if 1 lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; #endif vmovupd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(xmm0, xmm2, xmm4) vfmadd231pd(xmm0, xmm3, xmm6) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(xmm0, xmm2, xmm8) vfmadd231pd(xmm0, xmm3, xmm10) vbroadcastsd(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(xmm0, xmm2, xmm12) dec(rsi) // i -= 1; jne(.DLOOPKITER) // iterate again if i != 0. label(.DCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.DLOOPKLEFT) // EDGE LOOP #if 0 prefetch(0, mem(rdx, 5*8)) add(r9, rdx) #endif vmovupd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(xmm0, xmm2, xmm4) vfmadd231pd(xmm0, xmm3, xmm6) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(xmm0, xmm2, xmm8) vfmadd231pd(xmm0, xmm3, xmm10) vbroadcastsd(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(xmm0, xmm2, xmm12) dec(rsi) // i -= 1; jne(.DLOOPKLEFT) // iterate again if i != 0. label(.DPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(xmm0, xmm4, xmm4) // scale by alpha vmulpd(xmm0, xmm6, xmm6) vmulpd(xmm0, xmm8, xmm8) vmulpd(xmm0, xmm10, xmm10) vmulpd(xmm0, xmm12, xmm12) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; //lea(mem(rsi, rsi, 2), rax) // r13 = 3*cs_c; // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORED) // jump to column storage case label(.DROWSTORED) vfmadd231pd(mem(rcx, 0*32), xmm3, xmm4) vmovupd(xmm4, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), xmm3, xmm6) vmovupd(xmm6, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), xmm3, xmm8) vmovupd(xmm8, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), xmm3, xmm10) vmovupd(xmm10, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), xmm3, xmm12) vmovupd(xmm12, mem(rcx, 0*32)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORED) // begin I/O on columns 0-1 vunpcklpd(xmm6, xmm4, xmm0) vunpckhpd(xmm6, xmm4, xmm1) vunpcklpd(xmm10, xmm8, xmm2) vunpckhpd(xmm10, xmm8, xmm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vbroadcastsd(mem(rbx), ymm3) vfmadd231pd(mem(rcx ), ymm3, ymm4) vfmadd231pd(mem(rcx, rsi, 1), ymm3, ymm6) vmovupd(ymm4, mem(rcx )) vmovupd(ymm6, mem(rcx, rsi, 1)) //lea(mem(rcx, rsi, 4), rcx) vmovlpd(mem(rdx ), xmm0, xmm0) vmovhpd(mem(rdx, rsi, 1), xmm0, xmm0) vfmadd213pd(xmm12, xmm3, xmm0) vmovlpd(xmm0, mem(rdx )) vmovhpd(xmm0, mem(rdx, rsi, 1)) //lea(mem(rdx, rsi, 4), rdx) jmp(.DDONE) // jump to end. label(.DBETAZERO) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORBZ) // jump to column storage case label(.DROWSTORBZ) vmovupd(xmm4, mem(rcx, 0*32)) add(rdi, rcx) vmovupd(xmm6, mem(rcx, 0*32)) add(rdi, rcx) vmovupd(xmm8, mem(rcx, 0*32)) add(rdi, rcx) vmovupd(xmm10, mem(rcx, 0*32)) add(rdi, rcx) vmovupd(xmm12, mem(rcx, 0*32)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORBZ) // begin I/O on columns 0-1 vunpcklpd(xmm6, xmm4, xmm0) vunpckhpd(xmm6, xmm4, xmm1) vunpcklpd(xmm10, xmm8, xmm2) vunpckhpd(xmm10, xmm8, xmm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vmovupd(ymm4, mem(rcx )) vmovupd(ymm6, mem(rcx, rsi, 1)) //lea(mem(rcx, rsi, 4), rcx) vmovupd(xmm12, xmm0) vmovlpd(xmm0, mem(rdx )) vmovhpd(xmm0, mem(rdx, rsi, 1)) //lea(mem(rdx, rsi, 4), rdx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rv_haswell_asm_4x2 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) //lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLPFETCH) // jump to column storage case label(.DROWPFETCH) // row-stored prefetching on c lea(mem(rcx, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 1*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 1*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 1*8)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 1*8)) // prefetch c + 3*rs_c jmp(.DPOSTPFETCH) // jump to end of prefetching c label(.DCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 8), rsi) // cs_c *= sizeof(double) //lea(mem(rsi, rsi, 2), rbp) // rbp = 3*cs_c; prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 3*8)) // prefetch c + 1*cs_c label(.DPOSTPFETCH) // done prefetching c #if 1 lea(mem(rax, r9, 8), rdx) // lea(mem(rdx, r9, 8), rdx) // rdx = a + 16*cs_a; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.DLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(rdx, 5*8)) #endif vmovupd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(xmm0, xmm2, xmm4) vfmadd231pd(xmm0, xmm3, xmm6) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(xmm0, xmm2, xmm8) vfmadd231pd(xmm0, xmm3, xmm10) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, r9, 1, 5*8)) #endif vmovupd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(xmm0, xmm2, xmm4) vfmadd231pd(xmm0, xmm3, xmm6) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(xmm0, xmm2, xmm8) vfmadd231pd(xmm0, xmm3, xmm10) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(rdx, r9, 2, 5*8)) #endif vmovupd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(xmm0, xmm2, xmm4) vfmadd231pd(xmm0, xmm3, xmm6) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(xmm0, xmm2, xmm8) vfmadd231pd(xmm0, xmm3, xmm10) // ---------------------------------- iteration 3 #if 1 lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; #endif vmovupd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(xmm0, xmm2, xmm4) vfmadd231pd(xmm0, xmm3, xmm6) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(xmm0, xmm2, xmm8) vfmadd231pd(xmm0, xmm3, xmm10) dec(rsi) // i -= 1; jne(.DLOOPKITER) // iterate again if i != 0. label(.DCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.DLOOPKLEFT) // EDGE LOOP #if 0 prefetch(0, mem(rdx, 5*8)) add(r9, rdx) #endif vmovupd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(xmm0, xmm2, xmm4) vfmadd231pd(xmm0, xmm3, xmm6) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(xmm0, xmm2, xmm8) vfmadd231pd(xmm0, xmm3, xmm10) dec(rsi) // i -= 1; jne(.DLOOPKLEFT) // iterate again if i != 0. label(.DPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(xmm0, xmm4, xmm4) // scale by alpha vmulpd(xmm0, xmm6, xmm6) vmulpd(xmm0, xmm8, xmm8) vmulpd(xmm0, xmm10, xmm10) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; //lea(mem(rcx, rdi, 4), r14) // load address of c + 4*rs_c; //lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORED) // jump to column storage case label(.DROWSTORED) vfmadd231pd(mem(rcx, 0*32), xmm3, xmm4) vmovupd(xmm4, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), xmm3, xmm6) vmovupd(xmm6, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), xmm3, xmm8) vmovupd(xmm8, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), xmm3, xmm10) vmovupd(xmm10, mem(rcx, 0*32)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORED) // begin I/O on columns 0-1 vunpcklpd(xmm6, xmm4, xmm0) vunpckhpd(xmm6, xmm4, xmm1) vunpcklpd(xmm10, xmm8, xmm2) vunpckhpd(xmm10, xmm8, xmm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vbroadcastsd(mem(rbx), ymm3) vfmadd231pd(mem(rcx ), ymm3, ymm4) vfmadd231pd(mem(rcx, rsi, 1), ymm3, ymm6) vmovupd(ymm4, mem(rcx )) vmovupd(ymm6, mem(rcx, rsi, 1)) //lea(mem(rcx, rsi, 4), rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORBZ) // jump to column storage case label(.DROWSTORBZ) vmovupd(xmm4, mem(rcx, 0*32)) add(rdi, rcx) vmovupd(xmm6, mem(rcx, 0*32)) add(rdi, rcx) vmovupd(xmm8, mem(rcx, 0*32)) add(rdi, rcx) vmovupd(xmm10, mem(rcx, 0*32)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORBZ) // begin I/O on columns 0-1 vunpcklpd(xmm6, xmm4, xmm0) vunpckhpd(xmm6, xmm4, xmm1) vunpcklpd(xmm10, xmm8, xmm2) vunpckhpd(xmm10, xmm8, xmm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vmovupd(ymm4, mem(rcx )) vmovupd(ymm6, mem(rcx, rsi, 1)) //lea(mem(rcx, rsi, 4), rcx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rv_haswell_asm_3x2 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) //lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLPFETCH) // jump to column storage case label(.DROWPFETCH) // row-stored prefetching on c //lea(mem(rcx, rdi, 2), rdx) // //lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 1*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 1*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 1*8)) // prefetch c + 2*rs_c jmp(.DPOSTPFETCH) // jump to end of prefetching c label(.DCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 8), rsi) // cs_c *= sizeof(double) //lea(mem(rsi, rsi, 2), rbp) // rbp = 3*cs_c; prefetch(0, mem(rcx, 2*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 2*8)) // prefetch c + 1*cs_c label(.DPOSTPFETCH) // done prefetching c #if 1 lea(mem(rax, r9, 8), rdx) // lea(mem(rdx, r9, 8), rdx) // rdx = a + 16*cs_a; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.DLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(rdx, 5*8)) #endif vmovupd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(xmm0, xmm2, xmm4) vfmadd231pd(xmm0, xmm3, xmm6) vbroadcastsd(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(xmm0, xmm2, xmm8) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, r9, 1, 5*8)) #endif vmovupd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(xmm0, xmm2, xmm4) vfmadd231pd(xmm0, xmm3, xmm6) vbroadcastsd(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(xmm0, xmm2, xmm8) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(rdx, r9, 2, 5*8)) #endif vmovupd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(xmm0, xmm2, xmm4) vfmadd231pd(xmm0, xmm3, xmm6) vbroadcastsd(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(xmm0, xmm2, xmm8) // ---------------------------------- iteration 3 #if 1 lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; #endif vmovupd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(xmm0, xmm2, xmm4) vfmadd231pd(xmm0, xmm3, xmm6) vbroadcastsd(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(xmm0, xmm2, xmm8) dec(rsi) // i -= 1; jne(.DLOOPKITER) // iterate again if i != 0. label(.DCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.DLOOPKLEFT) // EDGE LOOP #if 0 prefetch(0, mem(rdx, 5*8)) add(r9, rdx) #endif vmovupd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(xmm0, xmm2, xmm4) vfmadd231pd(xmm0, xmm3, xmm6) vbroadcastsd(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(xmm0, xmm2, xmm8) dec(rsi) // i -= 1; jne(.DLOOPKLEFT) // iterate again if i != 0. label(.DPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(xmm0, xmm4, xmm4) // scale by alpha vmulpd(xmm0, xmm6, xmm6) vmulpd(xmm0, xmm8, xmm8) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; lea(mem(rcx, rdi, 2), rdx) // load address of c + 2*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORED) // jump to column storage case label(.DROWSTORED) vfmadd231pd(mem(rcx, 0*32), xmm3, xmm4) vmovupd(xmm4, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), xmm3, xmm6) vmovupd(xmm6, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), xmm3, xmm8) vmovupd(xmm8, mem(rcx, 0*32)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORED) // begin I/O on columns 0-1 vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vunpcklpd(ymm10, ymm8, ymm2) vunpckhpd(ymm10, ymm8, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vextractf128(imm(0x1), ymm4, xmm12) vextractf128(imm(0x1), ymm6, xmm13) vbroadcastsd(mem(rbx), ymm3) vfmadd231pd(mem(rcx), xmm3, xmm4) vfmadd231pd(mem(rcx, rsi, 1), xmm3, xmm6) vmovupd(xmm4, mem(rcx )) vmovupd(xmm6, mem(rcx, rsi, 1)) //lea(mem(rcx, rsi, 4), rcx) vfmadd231sd(mem(rdx), xmm3, xmm12) vfmadd231sd(mem(rdx, rsi, 1), xmm3, xmm13) vmovsd(xmm12, mem(rdx )) vmovsd(xmm13, mem(rdx, rsi, 1)) //lea(mem(rdx, rsi, 4), rdx) jmp(.DDONE) // jump to end. label(.DBETAZERO) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORBZ) // jump to column storage case label(.DROWSTORBZ) vmovupd(xmm4, mem(rcx, 0*32)) add(rdi, rcx) vmovupd(xmm6, mem(rcx, 0*32)) add(rdi, rcx) vmovupd(xmm8, mem(rcx, 0*32)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORBZ) // begin I/O on columns 0-1 vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vunpcklpd(ymm10, ymm8, ymm2) vunpckhpd(ymm10, ymm8, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vextractf128(imm(0x1), ymm4, xmm12) vextractf128(imm(0x1), ymm6, xmm13) vmovupd(xmm4, mem(rcx )) vmovupd(xmm6, mem(rcx, rsi, 1)) //lea(mem(rcx, rsi, 4), rcx) vmovsd(xmm12, mem(rdx )) vmovsd(xmm13, mem(rdx, rsi, 1)) //lea(mem(rdx, rsi, 4), rdx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rv_haswell_asm_2x2 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) //lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLPFETCH) // jump to column storage case label(.DROWPFETCH) // row-stored prefetching on c //lea(mem(rcx, rdi, 2), rdx) // //lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 1*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 1*8)) // prefetch c + 1*rs_c jmp(.DPOSTPFETCH) // jump to end of prefetching c label(.DCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 8), rsi) // cs_c *= sizeof(double) //lea(mem(rsi, rsi, 2), rbp) // rbp = 3*cs_c; prefetch(0, mem(rcx, 1*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 1*8)) // prefetch c + 1*cs_c label(.DPOSTPFETCH) // done prefetching c #if 1 lea(mem(rax, r9, 8), rdx) // lea(mem(rdx, r9, 8), rdx) // rdx = a + 16*cs_a; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.DLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(rdx, 5*8)) #endif vmovupd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(xmm0, xmm2, xmm4) vfmadd231pd(xmm0, xmm3, xmm6) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, r9, 1, 5*8)) #endif vmovupd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(xmm0, xmm2, xmm4) vfmadd231pd(xmm0, xmm3, xmm6) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(rdx, r9, 2, 5*8)) #endif vmovupd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(xmm0, xmm2, xmm4) vfmadd231pd(xmm0, xmm3, xmm6) // ---------------------------------- iteration 3 #if 1 lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; #endif vmovupd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(xmm0, xmm2, xmm4) vfmadd231pd(xmm0, xmm3, xmm6) dec(rsi) // i -= 1; jne(.DLOOPKITER) // iterate again if i != 0. label(.DCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.DLOOPKLEFT) // EDGE LOOP #if 0 prefetch(0, mem(rdx, 5*8)) add(r9, rdx) #endif vmovupd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(xmm0, xmm2, xmm4) vfmadd231pd(xmm0, xmm3, xmm6) dec(rsi) // i -= 1; jne(.DLOOPKLEFT) // iterate again if i != 0. label(.DPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(xmm0, xmm4, xmm4) // scale by alpha vmulpd(xmm0, xmm6, xmm6) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; //lea(mem(rcx, rdi, 4), r14) // load address of c + 4*rs_c; //lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORED) // jump to column storage case label(.DROWSTORED) vfmadd231pd(mem(rcx, 0*32), xmm3, xmm4) vmovupd(xmm4, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), xmm3, xmm6) vmovupd(xmm6, mem(rcx, 0*32)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORED) // begin I/O on columns 0-1 vunpcklpd(xmm6, xmm4, xmm0) vunpckhpd(xmm6, xmm4, xmm1) vfmadd231pd(mem(rcx ), xmm3, xmm0) vfmadd231pd(mem(rcx, rsi, 1), xmm3, xmm1) vmovupd(xmm0, mem(rcx )) vmovupd(xmm1, mem(rcx, rsi, 1)) //lea(mem(rcx, rsi, 4), rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORBZ) // jump to column storage case label(.DROWSTORBZ) vmovupd(xmm4, mem(rcx, 0*32)) add(rdi, rcx) vmovupd(xmm6, mem(rcx, 0*32)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORBZ) vunpcklpd(xmm6, xmm4, xmm0) vunpckhpd(xmm6, xmm4, xmm1) vmovupd(xmm0, mem(rcx )) vmovupd(xmm1, mem(rcx, rsi, 1)) //lea(mem(rcx, rsi, 4), rcx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rv_haswell_asm_1x2 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) //lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLPFETCH) // jump to column storage case label(.DROWPFETCH) // row-stored prefetching on c //lea(mem(rcx, rdi, 2), rdx) // //lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 1*8)) // prefetch c + 0*rs_c jmp(.DPOSTPFETCH) // jump to end of prefetching c label(.DCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 8), rsi) // cs_c *= sizeof(double) //lea(mem(rsi, rsi, 2), rbp) // rbp = 3*cs_c; prefetch(0, mem(rcx, 0*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 0*8)) // prefetch c + 1*cs_c label(.DPOSTPFETCH) // done prefetching c #if 1 lea(mem(rax, r9, 8), rdx) // lea(mem(rdx, r9, 8), rdx) // rdx = a + 16*cs_a; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.DLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(rdx, 5*8)) #endif vmovupd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(xmm0, xmm2, xmm4) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, r9, 1, 5*8)) #endif vmovupd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(xmm0, xmm2, xmm4) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(rdx, r9, 2, 5*8)) #endif vmovupd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(xmm0, xmm2, xmm4) // ---------------------------------- iteration 3 #if 1 lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; #endif vmovupd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(xmm0, xmm2, xmm4) dec(rsi) // i -= 1; jne(.DLOOPKITER) // iterate again if i != 0. label(.DCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.DLOOPKLEFT) // EDGE LOOP #if 0 prefetch(0, mem(rdx, 5*8)) add(r9, rdx) #endif vmovupd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(xmm0, xmm2, xmm4) dec(rsi) // i -= 1; jne(.DLOOPKLEFT) // iterate again if i != 0. label(.DPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(xmm0, xmm4, xmm4) // scale by alpha mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; //lea(mem(rcx, rdi, 4), r14) // load address of c + 4*rs_c; //lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORED) // jump to column storage case label(.DROWSTORED) vfmadd231pd(mem(rcx, 0*32), xmm3, xmm4) vmovupd(xmm4, mem(rcx, 0*32)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORED) // begin I/O on columns 0-1 vmovlpd(mem(rcx ), xmm0, xmm0) vmovhpd(mem(rcx, rsi, 1), xmm0, xmm0) vfmadd213pd(xmm4, xmm3, xmm0) vmovlpd(xmm0, mem(rcx )) vmovhpd(xmm0, mem(rcx, rsi, 1)) //lea(mem(rcx, rsi, 4), rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORBZ) // jump to column storage case label(.DROWSTORBZ) vmovupd(xmm4, mem(rcx, 0*32)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORBZ) // begin I/O on columns 0-1 vmovlpd(xmm4, mem(rcx )) vmovhpd(xmm4, mem(rcx, rsi, 1)) //lea(mem(rcx, rsi, 4), rcx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } blis-0.9.0/kernels/haswell/3/sup/d6x8/bli_gemmsup_rv_haswell_asm_dMx4.c000066400000000000000000002116531422157504600257640ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define BLIS_ASM_SYNTAX_ATT #include "bli_x86_asm_macros.h" /* rrr: -------- ------ -------- -------- ------ -------- -------- += ------ ... -------- -------- ------ -------- -------- ------ : -------- ------ : rcr: -------- | | | | -------- -------- | | | | -------- -------- += | | | | ... -------- -------- | | | | -------- -------- | | | | : -------- | | | | : Assumptions: - B is row-stored; - A is row- or column-stored; - m0 and n0 are at most MR and NR, respectively. Therefore, this (r)ow-preferential kernel is well-suited for contiguous (v)ector loads on B and single-element broadcasts from A. NOTE: These kernels explicitly support column-oriented IO, implemented via an in-register transpose. And thus they also support the crr and ccr cases, though only crr is ever utilized (because ccr is handled by transposing the operation and executing rcr, which does not incur the cost of the in-register transpose). crr: | | | | | | | | ------ -------- | | | | | | | | ------ -------- | | | | | | | | += ------ ... -------- | | | | | | | | ------ -------- | | | | | | | | ------ : | | | | | | | | ------ : */ // Prototype reference microkernels. GEMMSUP_KER_PROT( double, d, gemmsup_r_haswell_ref ) void bli_dgemmsup_rv_haswell_asm_6x4 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) //lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLPFETCH) // jump to column storage case label(.DROWPFETCH) // row-stored prefetching on c lea(mem(rcx, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 3*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 3*8)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 3*8)) // prefetch c + 3*rs_c prefetch(0, mem(rdx, rdi, 1, 3*8)) // prefetch c + 4*rs_c prefetch(0, mem(rdx, rdi, 2, 3*8)) // prefetch c + 5*rs_c jmp(.DPOSTPFETCH) // jump to end of prefetching c label(.DCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 8), rsi) // cs_c *= sizeof(double) lea(mem(rsi, rsi, 2), rbp) // rbp = 3*cs_c; prefetch(0, mem(rcx, 5*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 5*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 5*8)) // prefetch c + 2*cs_c prefetch(0, mem(rcx, rbp, 1, 5*8)) // prefetch c + 3*cs_c label(.DPOSTPFETCH) // done prefetching c #if 1 lea(mem(rax, r9, 8), rdx) // lea(mem(rdx, r9, 8), rdx) // rdx = a + 16*cs_a; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.DLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(rdx, 5*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm0, ymm3, ymm6) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm0, ymm3, ymm10) vbroadcastsd(mem(rax, r8, 4), ymm2) vbroadcastsd(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm0, ymm3, ymm14) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, r9, 1, 5*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm0, ymm3, ymm6) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm0, ymm3, ymm10) vbroadcastsd(mem(rax, r8, 4), ymm2) vbroadcastsd(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm0, ymm3, ymm14) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(rdx, r9, 2, 5*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm0, ymm3, ymm6) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm0, ymm3, ymm10) vbroadcastsd(mem(rax, r8, 4), ymm2) vbroadcastsd(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm0, ymm3, ymm14) // ---------------------------------- iteration 3 #if 1 lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; #endif vmovupd(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm0, ymm3, ymm6) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm0, ymm3, ymm10) vbroadcastsd(mem(rax, r8, 4), ymm2) vbroadcastsd(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm0, ymm3, ymm14) dec(rsi) // i -= 1; jne(.DLOOPKITER) // iterate again if i != 0. label(.DCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.DLOOPKLEFT) // EDGE LOOP #if 0 prefetch(0, mem(rdx, 5*8)) add(r9, rdx) #endif vmovupd(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm0, ymm3, ymm6) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm0, ymm3, ymm10) vbroadcastsd(mem(rax, r8, 4), ymm2) vbroadcastsd(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm0, ymm3, ymm14) dec(rsi) // i -= 1; jne(.DLOOPKLEFT) // iterate again if i != 0. label(.DPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(ymm0, ymm6, ymm6) vmulpd(ymm0, ymm8, ymm8) vmulpd(ymm0, ymm10, ymm10) vmulpd(ymm0, ymm12, ymm12) vmulpd(ymm0, ymm14, ymm14) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORED) // jump to column storage case label(.DROWSTORED) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm4) vmovupd(ymm4, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm6) vmovupd(ymm6, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm8) vmovupd(ymm8, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm10) vmovupd(ymm10, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm12) vmovupd(ymm12, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm14) vmovupd(ymm14, mem(rcx, 0*32)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORED) // begin I/O on columns 0-3 vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vunpcklpd(ymm10, ymm8, ymm2) vunpckhpd(ymm10, ymm8, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vperm2f128(imm(0x31), ymm2, ymm0, ymm8) vperm2f128(imm(0x31), ymm3, ymm1, ymm10) vbroadcastsd(mem(rbx), ymm3) vfmadd231pd(mem(rcx ), ymm3, ymm4) vfmadd231pd(mem(rcx, rsi, 1), ymm3, ymm6) vfmadd231pd(mem(rcx, rsi, 2), ymm3, ymm8) vfmadd231pd(mem(rcx, rax, 1), ymm3, ymm10) vmovupd(ymm4, mem(rcx )) vmovupd(ymm6, mem(rcx, rsi, 1)) vmovupd(ymm8, mem(rcx, rsi, 2)) vmovupd(ymm10, mem(rcx, rax, 1)) //lea(mem(rcx, rsi, 4), rcx) vunpcklpd(ymm14, ymm12, ymm0) vunpckhpd(ymm14, ymm12, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vextractf128(imm(0x1), ymm1, xmm4) vfmadd231pd(mem(rdx ), xmm3, xmm0) vfmadd231pd(mem(rdx, rsi, 1), xmm3, xmm1) vfmadd231pd(mem(rdx, rsi, 2), xmm3, xmm2) vfmadd231pd(mem(rdx, rax, 1), xmm3, xmm4) vmovupd(xmm0, mem(rdx )) vmovupd(xmm1, mem(rdx, rsi, 1)) vmovupd(xmm2, mem(rdx, rsi, 2)) vmovupd(xmm4, mem(rdx, rax, 1)) //lea(mem(rdx, rsi, 4), rdx) jmp(.DDONE) // jump to end. label(.DBETAZERO) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORBZ) // jump to column storage case label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx, 0*32)) add(rdi, rcx) vmovupd(ymm6, mem(rcx, 0*32)) add(rdi, rcx) vmovupd(ymm8, mem(rcx, 0*32)) add(rdi, rcx) vmovupd(ymm10, mem(rcx, 0*32)) add(rdi, rcx) vmovupd(ymm12, mem(rcx, 0*32)) add(rdi, rcx) vmovupd(ymm14, mem(rcx, 0*32)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORBZ) // begin I/O on columns 0-3 vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vunpcklpd(ymm10, ymm8, ymm2) vunpckhpd(ymm10, ymm8, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vperm2f128(imm(0x31), ymm2, ymm0, ymm8) vperm2f128(imm(0x31), ymm3, ymm1, ymm10) vmovupd(ymm4, mem(rcx )) vmovupd(ymm6, mem(rcx, rsi, 1)) vmovupd(ymm8, mem(rcx, rsi, 2)) vmovupd(ymm10, mem(rcx, rax, 1)) //lea(mem(rcx, rsi, 4), rcx) vunpcklpd(ymm14, ymm12, ymm0) vunpckhpd(ymm14, ymm12, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vextractf128(imm(0x1), ymm1, xmm4) vmovupd(xmm0, mem(rdx )) vmovupd(xmm1, mem(rdx, rsi, 1)) vmovupd(xmm2, mem(rdx, rsi, 2)) vmovupd(xmm4, mem(rdx, rax, 1)) //lea(mem(rdx, rsi, 4), rdx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rv_haswell_asm_5x4 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) //lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLPFETCH) // jump to column storage case label(.DROWPFETCH) // row-stored prefetching on c lea(mem(rcx, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 3*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 3*8)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 3*8)) // prefetch c + 3*rs_c prefetch(0, mem(rdx, rdi, 1, 3*8)) // prefetch c + 4*rs_c jmp(.DPOSTPFETCH) // jump to end of prefetching c label(.DCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 8), rsi) // cs_c *= sizeof(double) lea(mem(rsi, rsi, 2), rbp) // rbp = 3*cs_c; prefetch(0, mem(rcx, 4*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 4*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 4*8)) // prefetch c + 2*cs_c prefetch(0, mem(rcx, rbp, 1, 4*8)) // prefetch c + 3*cs_c label(.DPOSTPFETCH) // done prefetching c #if 1 lea(mem(rax, r9, 8), rdx) // lea(mem(rdx, r9, 8), rdx) // rdx = a + 16*cs_a; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.DLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(rdx, 4*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm0, ymm3, ymm6) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm0, ymm3, ymm10) vbroadcastsd(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, r9, 1, 4*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm0, ymm3, ymm6) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm0, ymm3, ymm10) vbroadcastsd(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(rdx, r9, 2, 4*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm0, ymm3, ymm6) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm0, ymm3, ymm10) vbroadcastsd(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) // ---------------------------------- iteration 3 #if 1 lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; #endif vmovupd(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm0, ymm3, ymm6) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm0, ymm3, ymm10) vbroadcastsd(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) dec(rsi) // i -= 1; jne(.DLOOPKITER) // iterate again if i != 0. label(.DCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.DLOOPKLEFT) // EDGE LOOP #if 0 prefetch(0, mem(rdx, 5*8)) add(r9, rdx) #endif vmovupd(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm0, ymm3, ymm6) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm0, ymm3, ymm10) vbroadcastsd(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) dec(rsi) // i -= 1; jne(.DLOOPKLEFT) // iterate again if i != 0. label(.DPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(ymm0, ymm6, ymm6) vmulpd(ymm0, ymm8, ymm8) vmulpd(ymm0, ymm10, ymm10) vmulpd(ymm0, ymm12, ymm12) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORED) // jump to column storage case label(.DROWSTORED) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm4) vmovupd(ymm4, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm6) vmovupd(ymm6, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm8) vmovupd(ymm8, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm10) vmovupd(ymm10, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm12) vmovupd(ymm12, mem(rcx, 0*32)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORED) // begin I/O on columns 0-3 vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vunpcklpd(ymm10, ymm8, ymm2) vunpckhpd(ymm10, ymm8, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vperm2f128(imm(0x31), ymm2, ymm0, ymm8) vperm2f128(imm(0x31), ymm3, ymm1, ymm10) vbroadcastsd(mem(rbx), ymm3) vfmadd231pd(mem(rcx ), ymm3, ymm4) vfmadd231pd(mem(rcx, rsi, 1), ymm3, ymm6) vfmadd231pd(mem(rcx, rsi, 2), ymm3, ymm8) vfmadd231pd(mem(rcx, rax, 1), ymm3, ymm10) vmovupd(ymm4, mem(rcx )) vmovupd(ymm6, mem(rcx, rsi, 1)) vmovupd(ymm8, mem(rcx, rsi, 2)) vmovupd(ymm10, mem(rcx, rax, 1)) //lea(mem(rcx, rsi, 4), rcx) vmovlpd(mem(rdx ), xmm0, xmm0) vmovhpd(mem(rdx, rsi, 1), xmm0, xmm0) vmovlpd(mem(rdx, rsi, 2), xmm1, xmm1) vmovhpd(mem(rdx, rax, 1), xmm1, xmm1) vperm2f128(imm(0x20), ymm1, ymm0, ymm0) vfmadd213pd(ymm12, ymm3, ymm0) vextractf128(imm(1), ymm0, xmm1) vmovlpd(xmm0, mem(rdx )) vmovhpd(xmm0, mem(rdx, rsi, 1)) vmovlpd(xmm1, mem(rdx, rsi, 2)) vmovhpd(xmm1, mem(rdx, rax, 1)) //lea(mem(rdx, rsi, 4), rdx) jmp(.DDONE) // jump to end. label(.DBETAZERO) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORBZ) // jump to column storage case label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx, 0*32)) add(rdi, rcx) vmovupd(ymm6, mem(rcx, 0*32)) add(rdi, rcx) vmovupd(ymm8, mem(rcx, 0*32)) add(rdi, rcx) vmovupd(ymm10, mem(rcx, 0*32)) add(rdi, rcx) vmovupd(ymm12, mem(rcx, 0*32)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORBZ) // begin I/O on columns 0-3 vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vunpcklpd(ymm10, ymm8, ymm2) vunpckhpd(ymm10, ymm8, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vperm2f128(imm(0x31), ymm2, ymm0, ymm8) vperm2f128(imm(0x31), ymm3, ymm1, ymm10) vmovupd(ymm4, mem(rcx )) vmovupd(ymm6, mem(rcx, rsi, 1)) vmovupd(ymm8, mem(rcx, rsi, 2)) vmovupd(ymm10, mem(rcx, rax, 1)) //lea(mem(rcx, rsi, 4), rcx) vmovupd(ymm12, ymm0) vextractf128(imm(1), ymm0, xmm1) vmovlpd(xmm0, mem(rdx )) vmovhpd(xmm0, mem(rdx, rsi, 1)) vmovlpd(xmm1, mem(rdx, rsi, 2)) vmovhpd(xmm1, mem(rdx, rax, 1)) //lea(mem(rdx, rsi, 4), rdx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rv_haswell_asm_4x4 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) //lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLPFETCH) // jump to column storage case label(.DROWPFETCH) // row-stored prefetching on c lea(mem(rcx, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 3*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 3*8)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 3*8)) // prefetch c + 3*rs_c jmp(.DPOSTPFETCH) // jump to end of prefetching c label(.DCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 8), rsi) // cs_c *= sizeof(double) lea(mem(rsi, rsi, 2), rbp) // rbp = 3*cs_c; prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 3*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 3*8)) // prefetch c + 2*cs_c prefetch(0, mem(rcx, rbp, 1, 3*8)) // prefetch c + 3*cs_c label(.DPOSTPFETCH) // done prefetching c #if 1 lea(mem(rax, r9, 8), rdx) // lea(mem(rdx, r9, 8), rdx) // rdx = a + 16*cs_a; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.DLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(rdx, 4*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm0, ymm3, ymm6) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm0, ymm3, ymm10) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, r9, 1, 4*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm0, ymm3, ymm6) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm0, ymm3, ymm10) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(rdx, r9, 2, 4*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm0, ymm3, ymm6) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm0, ymm3, ymm10) // ---------------------------------- iteration 3 #if 1 lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; #endif vmovupd(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm0, ymm3, ymm6) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm0, ymm3, ymm10) dec(rsi) // i -= 1; jne(.DLOOPKITER) // iterate again if i != 0. label(.DCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.DLOOPKLEFT) // EDGE LOOP #if 0 prefetch(0, mem(rdx, 5*8)) add(r9, rdx) #endif vmovupd(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm0, ymm3, ymm6) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm0, ymm3, ymm10) dec(rsi) // i -= 1; jne(.DLOOPKLEFT) // iterate again if i != 0. label(.DPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(ymm0, ymm6, ymm6) vmulpd(ymm0, ymm8, ymm8) vmulpd(ymm0, ymm10, ymm10) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; //lea(mem(rcx, rdi, 4), r14) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORED) // jump to column storage case label(.DROWSTORED) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm4) vmovupd(ymm4, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm6) vmovupd(ymm6, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm8) vmovupd(ymm8, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm10) vmovupd(ymm10, mem(rcx, 0*32)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORED) // begin I/O on columns 0-3 vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vunpcklpd(ymm10, ymm8, ymm2) vunpckhpd(ymm10, ymm8, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vperm2f128(imm(0x31), ymm2, ymm0, ymm8) vperm2f128(imm(0x31), ymm3, ymm1, ymm10) vbroadcastsd(mem(rbx), ymm3) vfmadd231pd(mem(rcx ), ymm3, ymm4) vfmadd231pd(mem(rcx, rsi, 1), ymm3, ymm6) vfmadd231pd(mem(rcx, rsi, 2), ymm3, ymm8) vfmadd231pd(mem(rcx, rax, 1), ymm3, ymm10) vmovupd(ymm4, mem(rcx )) vmovupd(ymm6, mem(rcx, rsi, 1)) vmovupd(ymm8, mem(rcx, rsi, 2)) vmovupd(ymm10, mem(rcx, rax, 1)) //lea(mem(rcx, rsi, 4), rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORBZ) // jump to column storage case label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx, 0*32)) add(rdi, rcx) vmovupd(ymm6, mem(rcx, 0*32)) add(rdi, rcx) vmovupd(ymm8, mem(rcx, 0*32)) add(rdi, rcx) vmovupd(ymm10, mem(rcx, 0*32)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORBZ) // begin I/O on columns 0-3 vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vunpcklpd(ymm10, ymm8, ymm2) vunpckhpd(ymm10, ymm8, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vperm2f128(imm(0x31), ymm2, ymm0, ymm8) vperm2f128(imm(0x31), ymm3, ymm1, ymm10) vmovupd(ymm4, mem(rcx )) vmovupd(ymm6, mem(rcx, rsi, 1)) vmovupd(ymm8, mem(rcx, rsi, 2)) vmovupd(ymm10, mem(rcx, rax, 1)) //lea(mem(rcx, rsi, 4), rcx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rv_haswell_asm_3x4 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) //lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLPFETCH) // jump to column storage case label(.DROWPFETCH) // row-stored prefetching on c //lea(mem(rcx, rdi, 2), rdx) // //lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 3*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 3*8)) // prefetch c + 2*rs_c jmp(.DPOSTPFETCH) // jump to end of prefetching c label(.DCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 8), rsi) // cs_c *= sizeof(double) lea(mem(rsi, rsi, 2), rbp) // rbp = 3*cs_c; prefetch(0, mem(rcx, 2*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 2*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 2*8)) // prefetch c + 2*cs_c prefetch(0, mem(rcx, rbp, 1, 2*8)) // prefetch c + 3*cs_c label(.DPOSTPFETCH) // done prefetching c #if 1 lea(mem(rax, r9, 8), rdx) // lea(mem(rdx, r9, 8), rdx) // rdx = a + 16*cs_a; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.DLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(rdx, 4*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm0, ymm3, ymm6) vbroadcastsd(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm8) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, r9, 1, 4*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm0, ymm3, ymm6) vbroadcastsd(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm8) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(rdx, r9, 2, 4*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm0, ymm3, ymm6) vbroadcastsd(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm8) // ---------------------------------- iteration 3 #if 1 lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; #endif vmovupd(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm0, ymm3, ymm6) vbroadcastsd(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm8) dec(rsi) // i -= 1; jne(.DLOOPKITER) // iterate again if i != 0. label(.DCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.DLOOPKLEFT) // EDGE LOOP #if 0 prefetch(0, mem(rdx, 5*8)) add(r9, rdx) #endif vmovupd(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm0, ymm3, ymm6) vbroadcastsd(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm8) dec(rsi) // i -= 1; jne(.DLOOPKLEFT) // iterate again if i != 0. label(.DPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(ymm0, ymm6, ymm6) vmulpd(ymm0, ymm8, ymm8) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; lea(mem(rcx, rdi, 2), rdx) // load address of c + 2*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORED) // jump to column storage case label(.DROWSTORED) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm4) vmovupd(ymm4, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm6) vmovupd(ymm6, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm8) vmovupd(ymm8, mem(rcx, 0*32)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORED) // begin I/O on columns 0-3 vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vunpcklpd(ymm10, ymm8, ymm2) vunpckhpd(ymm10, ymm8, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vperm2f128(imm(0x31), ymm2, ymm0, ymm8) vperm2f128(imm(0x31), ymm3, ymm1, ymm10) vextractf128(imm(0x1), ymm4, xmm12) vextractf128(imm(0x1), ymm6, xmm13) vextractf128(imm(0x1), ymm8, xmm14) vextractf128(imm(0x1), ymm10, xmm15) vbroadcastsd(mem(rbx), ymm3) vfmadd231pd(mem(rcx ), xmm3, xmm4) vfmadd231pd(mem(rcx, rsi, 1), xmm3, xmm6) vfmadd231pd(mem(rcx, rsi, 2), xmm3, xmm8) vfmadd231pd(mem(rcx, rax, 1), xmm3, xmm10) vmovupd(xmm4, mem(rcx )) vmovupd(xmm6, mem(rcx, rsi, 1)) vmovupd(xmm8, mem(rcx, rsi, 2)) vmovupd(xmm10, mem(rcx, rax, 1)) //lea(mem(rcx, rsi, 4), rcx) vfmadd231sd(mem(rdx ), xmm3, xmm12) vfmadd231sd(mem(rdx, rsi, 1), xmm3, xmm13) vfmadd231sd(mem(rdx, rsi, 2), xmm3, xmm14) vfmadd231sd(mem(rdx, rax, 1), xmm3, xmm15) vmovsd(xmm12, mem(rdx )) vmovsd(xmm13, mem(rdx, rsi, 1)) vmovsd(xmm14, mem(rdx, rsi, 2)) vmovsd(xmm15, mem(rdx, rax, 1)) //lea(mem(rdx, rsi, 4), rdx) jmp(.DDONE) // jump to end. label(.DBETAZERO) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORBZ) // jump to column storage case label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx, 0*32)) add(rdi, rcx) vmovupd(ymm6, mem(rcx, 0*32)) add(rdi, rcx) vmovupd(ymm8, mem(rcx, 0*32)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORBZ) // begin I/O on columns 0-3 vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vunpcklpd(ymm10, ymm8, ymm2) vunpckhpd(ymm10, ymm8, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vperm2f128(imm(0x31), ymm2, ymm0, ymm8) vperm2f128(imm(0x31), ymm3, ymm1, ymm10) vextractf128(imm(0x1), ymm4, xmm12) vextractf128(imm(0x1), ymm6, xmm13) vextractf128(imm(0x1), ymm8, xmm14) vextractf128(imm(0x1), ymm10, xmm15) vmovupd(xmm4, mem(rcx )) vmovupd(xmm6, mem(rcx, rsi, 1)) vmovupd(xmm8, mem(rcx, rsi, 2)) vmovupd(xmm10, mem(rcx, rax, 1)) //lea(mem(rcx, rsi, 4), rcx) vmovsd(xmm12, mem(rdx )) vmovsd(xmm13, mem(rdx, rsi, 1)) vmovsd(xmm14, mem(rdx, rsi, 2)) vmovsd(xmm15, mem(rdx, rax, 1)) //lea(mem(rdx, rsi, 4), rdx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rv_haswell_asm_2x4 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) //lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLPFETCH) // jump to column storage case label(.DROWPFETCH) // row-stored prefetching on c //lea(mem(rcx, rdi, 2), rdx) // //lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 3*8)) // prefetch c + 1*rs_c jmp(.DPOSTPFETCH) // jump to end of prefetching c label(.DCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 8), rsi) // cs_c *= sizeof(double) lea(mem(rsi, rsi, 2), rbp) // rbp = 3*cs_c; prefetch(0, mem(rcx, 1*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 1*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 1*8)) // prefetch c + 2*cs_c prefetch(0, mem(rcx, rbp, 1, 1*8)) // prefetch c + 3*cs_c label(.DPOSTPFETCH) // done prefetching c #if 1 lea(mem(rax, r9, 8), rdx) // lea(mem(rdx, r9, 8), rdx) // rdx = a + 16*cs_a; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.DLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(rdx, 4*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm0, ymm3, ymm6) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, r9, 1, 4*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm0, ymm3, ymm6) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(rdx, r9, 2, 4*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm0, ymm3, ymm6) // ---------------------------------- iteration 3 #if 1 lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; #endif vmovupd(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm0, ymm3, ymm6) dec(rsi) // i -= 1; jne(.DLOOPKITER) // iterate again if i != 0. label(.DCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.DLOOPKLEFT) // EDGE LOOP #if 0 prefetch(0, mem(rdx, 5*8)) add(r9, rdx) #endif vmovupd(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm0, ymm3, ymm6) dec(rsi) // i -= 1; jne(.DLOOPKLEFT) // iterate again if i != 0. label(.DPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(ymm0, ymm6, ymm6) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; //lea(mem(rcx, rdi, 4), r14) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORED) // jump to column storage case label(.DROWSTORED) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm4) vmovupd(ymm4, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm6) vmovupd(ymm6, mem(rcx, 0*32)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORED) // begin I/O on columns 0-3 vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vextractf128(imm(0x1), ymm1, xmm4) vfmadd231pd(mem(rcx ), xmm3, xmm0) vfmadd231pd(mem(rcx, rsi, 1), xmm3, xmm1) vfmadd231pd(mem(rcx, rsi, 2), xmm3, xmm2) vfmadd231pd(mem(rcx, rax, 1), xmm3, xmm4) vmovupd(xmm0, mem(rcx )) vmovupd(xmm1, mem(rcx, rsi, 1)) vmovupd(xmm2, mem(rcx, rsi, 2)) vmovupd(xmm4, mem(rcx, rax, 1)) //lea(mem(rcx, rsi, 4), rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORBZ) // jump to column storage case label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx, 0*32)) add(rdi, rcx) vmovupd(ymm6, mem(rcx, 0*32)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORBZ) // begin I/O on columns 0-3 vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vextractf128(imm(0x1), ymm1, xmm4) vmovupd(xmm0, mem(rcx )) vmovupd(xmm1, mem(rcx, rsi, 1)) vmovupd(xmm2, mem(rcx, rsi, 2)) vmovupd(xmm4, mem(rcx, rax, 1)) //lea(mem(rcx, rsi, 4), rcx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rv_haswell_asm_1x4 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) //lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLPFETCH) // jump to column storage case label(.DROWPFETCH) // row-stored prefetching on c //lea(mem(rcx, rdi, 2), rdx) // //lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c jmp(.DPOSTPFETCH) // jump to end of prefetching c label(.DCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 8), rsi) // cs_c *= sizeof(double) lea(mem(rsi, rsi, 2), rbp) // rbp = 3*cs_c; prefetch(0, mem(rcx, 0*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 0*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 0*8)) // prefetch c + 2*cs_c prefetch(0, mem(rcx, rbp, 1, 0*8)) // prefetch c + 3*cs_c label(.DPOSTPFETCH) // done prefetching c #if 1 lea(mem(rax, r9, 8), rdx) // lea(mem(rdx, r9, 8), rdx) // rdx = a + 16*cs_a; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.DLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(rdx, 4*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm4) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, r9, 1, 4*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm4) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(rdx, r9, 2, 4*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm4) // ---------------------------------- iteration 3 #if 1 lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; #endif vmovupd(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm4) dec(rsi) // i -= 1; jne(.DLOOPKITER) // iterate again if i != 0. label(.DCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.DLOOPKLEFT) // EDGE LOOP #if 0 prefetch(0, mem(rdx, 5*8)) add(r9, rdx) #endif vmovupd(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm4) dec(rsi) // i -= 1; jne(.DLOOPKLEFT) // iterate again if i != 0. label(.DPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; //lea(mem(rcx, rdi, 4), r14) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORED) // jump to column storage case label(.DROWSTORED) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm4) vmovupd(ymm4, mem(rcx, 0*32)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORED) // begin I/O on columns 0-3 vmovlpd(mem(rcx ), xmm0, xmm0) vmovhpd(mem(rcx, rsi, 1), xmm0, xmm0) vmovlpd(mem(rcx, rsi, 2), xmm1, xmm1) vmovhpd(mem(rcx, rax, 1), xmm1, xmm1) vperm2f128(imm(0x20), ymm1, ymm0, ymm0) vfmadd213pd(ymm4, ymm3, ymm0) vextractf128(imm(1), ymm0, xmm1) vmovlpd(xmm0, mem(rcx )) vmovhpd(xmm0, mem(rcx, rsi, 1)) vmovlpd(xmm1, mem(rcx, rsi, 2)) vmovhpd(xmm1, mem(rcx, rax, 1)) //lea(mem(rcx, rsi, 4), rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORBZ) // jump to column storage case label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx, 0*32)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORBZ) // begin I/O on columns 0-3 vmovupd(ymm4, ymm0) vextractf128(imm(1), ymm0, xmm1) vmovlpd(xmm0, mem(rcx )) vmovhpd(xmm0, mem(rcx, rsi, 1)) vmovlpd(xmm1, mem(rcx, rsi, 2)) vmovhpd(xmm1, mem(rcx, rax, 1)) //lea(mem(rcx, rsi, 4), rcx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } blis-0.9.0/kernels/haswell/3/sup/d6x8/bli_gemmsup_rv_haswell_asm_dMx6.c000066400000000000000000002455111422157504600257660ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define BLIS_ASM_SYNTAX_ATT #include "bli_x86_asm_macros.h" /* rrr: -------- ------ -------- -------- ------ -------- -------- += ------ ... -------- -------- ------ -------- -------- ------ : -------- ------ : rcr: -------- | | | | -------- -------- | | | | -------- -------- += | | | | ... -------- -------- | | | | -------- -------- | | | | : -------- | | | | : Assumptions: - B is row-stored; - A is row- or column-stored; - m0 and n0 are at most MR and NR, respectively. Therefore, this (r)ow-preferential kernel is well-suited for contiguous (v)ector loads on B and single-element broadcasts from A. NOTE: These kernels explicitly support column-oriented IO, implemented via an in-register transpose. And thus they also support the crr and ccr cases, though only crr is ever utilized (because ccr is handled by transposing the operation and executing rcr, which does not incur the cost of the in-register transpose). crr: | | | | | | | | ------ -------- | | | | | | | | ------ -------- | | | | | | | | += ------ ... -------- | | | | | | | | ------ -------- | | | | | | | | ------ : | | | | | | | | ------ : */ // Prototype reference microkernels. GEMMSUP_KER_PROT( double, d, gemmsup_r_haswell_ref ) void bli_dgemmsup_rv_haswell_asm_6x6 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) //lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLPFETCH) // jump to column storage case label(.DROWPFETCH) // row-stored prefetching on c lea(mem(rcx, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 5*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 5*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 5*8)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 5*8)) // prefetch c + 3*rs_c prefetch(0, mem(rdx, rdi, 1, 5*8)) // prefetch c + 4*rs_c prefetch(0, mem(rdx, rdi, 2, 5*8)) // prefetch c + 5*rs_c jmp(.DPOSTPFETCH) // jump to end of prefetching c label(.DCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 8), rsi) // cs_c *= sizeof(double) lea(mem(rcx, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; prefetch(0, mem(rcx, 5*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 5*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 5*8)) // prefetch c + 2*cs_c prefetch(0, mem(rdx, 5*8)) // prefetch c + 3*cs_c prefetch(0, mem(rdx, rsi, 1, 5*8)) // prefetch c + 4*cs_c prefetch(0, mem(rdx, rsi, 2, 5*8)) // prefetch c + 5*cs_c label(.DPOSTPFETCH) // done prefetching c #if 1 lea(mem(rax, r9, 8), rdx) // lea(mem(rdx, r9, 8), rdx) // rdx = a + 16*cs_a; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.DLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(rdx, 5*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, r8, 4), ymm2) vbroadcastsd(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, r9, 1, 5*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, r8, 4), ymm2) vbroadcastsd(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(rdx, r9, 2, 5*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, r8, 4), ymm2) vbroadcastsd(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) // ---------------------------------- iteration 3 #if 1 lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, r8, 4), ymm2) vbroadcastsd(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKITER) // iterate again if i != 0. label(.DCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.DLOOPKLEFT) // EDGE LOOP #if 0 prefetch(0, mem(rdx, 5*8)) add(r9, rdx) #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, r8, 4), ymm2) vbroadcastsd(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKLEFT) // iterate again if i != 0. label(.DPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(xmm0, xmm5, xmm5) vmulpd(ymm0, ymm6, ymm6) vmulpd(xmm0, xmm7, xmm7) vmulpd(ymm0, ymm8, ymm8) vmulpd(xmm0, xmm9, xmm9) vmulpd(ymm0, ymm10, ymm10) vmulpd(xmm0, xmm11, xmm11) vmulpd(ymm0, ymm12, ymm12) vmulpd(xmm0, xmm13, xmm13) vmulpd(ymm0, ymm14, ymm14) vmulpd(xmm0, xmm15, xmm15) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORED) // jump to column storage case label(.DROWSTORED) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm4) vmovupd(ymm4, mem(rcx, 0*32)) vfmadd231pd(mem(rcx, 1*32), xmm3, xmm5) vmovupd(xmm5, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm6) vmovupd(ymm6, mem(rcx, 0*32)) vfmadd231pd(mem(rcx, 1*32), xmm3, xmm7) vmovupd(xmm7, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm8) vmovupd(ymm8, mem(rcx, 0*32)) vfmadd231pd(mem(rcx, 1*32), xmm3, xmm9) vmovupd(xmm9, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm10) vmovupd(ymm10, mem(rcx, 0*32)) vfmadd231pd(mem(rcx, 1*32), xmm3, xmm11) vmovupd(xmm11, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm12) vmovupd(ymm12, mem(rcx, 0*32)) vfmadd231pd(mem(rcx, 1*32), xmm3, xmm13) vmovupd(xmm13, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm14) vmovupd(ymm14, mem(rcx, 0*32)) vfmadd231pd(mem(rcx, 1*32), xmm3, xmm15) vmovupd(xmm15, mem(rcx, 1*32)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORED) // begin I/O on columns 0-3 vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vunpcklpd(ymm10, ymm8, ymm2) vunpckhpd(ymm10, ymm8, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vperm2f128(imm(0x31), ymm2, ymm0, ymm8) vperm2f128(imm(0x31), ymm3, ymm1, ymm10) vbroadcastsd(mem(rbx), ymm3) vfmadd231pd(mem(rcx ), ymm3, ymm4) vfmadd231pd(mem(rcx, rsi, 1), ymm3, ymm6) vfmadd231pd(mem(rcx, rsi, 2), ymm3, ymm8) vfmadd231pd(mem(rcx, rax, 1), ymm3, ymm10) vmovupd(ymm4, mem(rcx )) vmovupd(ymm6, mem(rcx, rsi, 1)) vmovupd(ymm8, mem(rcx, rsi, 2)) vmovupd(ymm10, mem(rcx, rax, 1)) lea(mem(rcx, rsi, 4), rcx) vunpcklpd(ymm14, ymm12, ymm0) vunpckhpd(ymm14, ymm12, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vextractf128(imm(0x1), ymm1, xmm4) vfmadd231pd(mem(rdx ), xmm3, xmm0) vfmadd231pd(mem(rdx, rsi, 1), xmm3, xmm1) vfmadd231pd(mem(rdx, rsi, 2), xmm3, xmm2) vfmadd231pd(mem(rdx, rax, 1), xmm3, xmm4) vmovupd(xmm0, mem(rdx )) vmovupd(xmm1, mem(rdx, rsi, 1)) vmovupd(xmm2, mem(rdx, rsi, 2)) vmovupd(xmm4, mem(rdx, rax, 1)) lea(mem(rdx, rsi, 4), rdx) // begin I/O on columns 4-5 vunpcklpd(ymm7, ymm5, ymm0) vunpckhpd(ymm7, ymm5, ymm1) vunpcklpd(ymm11, ymm9, ymm2) vunpckhpd(ymm11, ymm9, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm5) vinsertf128(imm(0x1), xmm3, ymm1, ymm7) vbroadcastsd(mem(rbx), ymm3) vfmadd231pd(mem(rcx ), ymm3, ymm5) vfmadd231pd(mem(rcx, rsi, 1), ymm3, ymm7) vmovupd(ymm5, mem(rcx )) vmovupd(ymm7, mem(rcx, rsi, 1)) //lea(mem(rcx, rsi, 4), rcx) vunpcklpd(ymm15, ymm13, ymm0) vunpckhpd(ymm15, ymm13, ymm1) vfmadd231pd(mem(rdx ), xmm3, xmm0) vfmadd231pd(mem(rdx, rsi, 1), xmm3, xmm1) vmovupd(xmm0, mem(rdx )) vmovupd(xmm1, mem(rdx, rsi, 1)) //lea(mem(rdx, rsi, 4), rdx) jmp(.DDONE) // jump to end. label(.DBETAZERO) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORBZ) // jump to column storage case label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx, 0*32)) vmovupd(xmm5, mem(rcx, 1*32)) add(rdi, rcx) vmovupd(ymm6, mem(rcx, 0*32)) vmovupd(xmm7, mem(rcx, 1*32)) add(rdi, rcx) vmovupd(ymm8, mem(rcx, 0*32)) vmovupd(xmm9, mem(rcx, 1*32)) add(rdi, rcx) vmovupd(ymm10, mem(rcx, 0*32)) vmovupd(xmm11, mem(rcx, 1*32)) add(rdi, rcx) vmovupd(ymm12, mem(rcx, 0*32)) vmovupd(xmm13, mem(rcx, 1*32)) add(rdi, rcx) vmovupd(ymm14, mem(rcx, 0*32)) vmovupd(xmm15, mem(rcx, 1*32)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORBZ) // begin I/O on columns 0-3 vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vunpcklpd(ymm10, ymm8, ymm2) vunpckhpd(ymm10, ymm8, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vperm2f128(imm(0x31), ymm2, ymm0, ymm8) vperm2f128(imm(0x31), ymm3, ymm1, ymm10) vmovupd(ymm4, mem(rcx )) vmovupd(ymm6, mem(rcx, rsi, 1)) vmovupd(ymm8, mem(rcx, rsi, 2)) vmovupd(ymm10, mem(rcx, rax, 1)) lea(mem(rcx, rsi, 4), rcx) vunpcklpd(ymm14, ymm12, ymm0) vunpckhpd(ymm14, ymm12, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vextractf128(imm(0x1), ymm1, xmm4) vmovupd(xmm0, mem(rdx )) vmovupd(xmm1, mem(rdx, rsi, 1)) vmovupd(xmm2, mem(rdx, rsi, 2)) vmovupd(xmm4, mem(rdx, rax, 1)) lea(mem(rdx, rsi, 4), rdx) // begin I/O on columns 4-5 vunpcklpd(ymm7, ymm5, ymm0) vunpckhpd(ymm7, ymm5, ymm1) vunpcklpd(ymm11, ymm9, ymm2) vunpckhpd(ymm11, ymm9, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm5) vinsertf128(imm(0x1), xmm3, ymm1, ymm7) vmovupd(ymm5, mem(rcx)) vmovupd(ymm7, mem(rcx, rsi, 1)) //lea(mem(rcx, rsi, 4), rcx) vunpcklpd(ymm15, ymm13, ymm0) vunpckhpd(ymm15, ymm13, ymm1) vmovupd(xmm0, mem(rdx)) vmovupd(xmm1, mem(rdx, rsi, 1)) //lea(mem(rdx, rsi, 4), rdx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rv_haswell_asm_5x6 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) //lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLPFETCH) // jump to column storage case label(.DROWPFETCH) // row-stored prefetching on c lea(mem(rcx, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 5*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 5*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 5*8)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 5*8)) // prefetch c + 3*rs_c prefetch(0, mem(rdx, rdi, 1, 5*8)) // prefetch c + 4*rs_c jmp(.DPOSTPFETCH) // jump to end of prefetching c label(.DCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 8), rsi) // cs_c *= sizeof(double) lea(mem(rcx, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; prefetch(0, mem(rcx, 4*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 4*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 4*8)) // prefetch c + 2*cs_c prefetch(0, mem(rdx, 4*8)) // prefetch c + 3*cs_c prefetch(0, mem(rdx, rsi, 1, 4*8)) // prefetch c + 4*cs_c prefetch(0, mem(rdx, rsi, 2, 4*8)) // prefetch c + 5*cs_c label(.DPOSTPFETCH) // done prefetching c #if 1 lea(mem(rax, r9, 8), rdx) // lea(mem(rdx, r9, 8), rdx) // rdx = a + 16*cs_a; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.DLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(rdx, 4*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, r9, 1, 4*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(rdx, r9, 2, 4*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) // ---------------------------------- iteration 3 #if 1 lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) dec(rsi) // i -= 1; jne(.DLOOPKITER) // iterate again if i != 0. label(.DCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.DLOOPKLEFT) // EDGE LOOP #if 0 prefetch(0, mem(rdx, 5*8)) add(r9, rdx) #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) dec(rsi) // i -= 1; jne(.DLOOPKLEFT) // iterate again if i != 0. label(.DPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(xmm0, xmm5, xmm5) vmulpd(ymm0, ymm6, ymm6) vmulpd(xmm0, xmm7, xmm7) vmulpd(ymm0, ymm8, ymm8) vmulpd(xmm0, xmm9, xmm9) vmulpd(ymm0, ymm10, ymm10) vmulpd(xmm0, xmm11, xmm11) vmulpd(ymm0, ymm12, ymm12) vmulpd(xmm0, xmm13, xmm13) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORED) // jump to column storage case label(.DROWSTORED) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm4) vmovupd(ymm4, mem(rcx, 0*32)) vfmadd231pd(mem(rcx, 1*32), xmm3, xmm5) vmovupd(xmm5, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm6) vmovupd(ymm6, mem(rcx, 0*32)) vfmadd231pd(mem(rcx, 1*32), xmm3, xmm7) vmovupd(xmm7, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm8) vmovupd(ymm8, mem(rcx, 0*32)) vfmadd231pd(mem(rcx, 1*32), xmm3, xmm9) vmovupd(xmm9, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm10) vmovupd(ymm10, mem(rcx, 0*32)) vfmadd231pd(mem(rcx, 1*32), xmm3, xmm11) vmovupd(xmm11, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm12) vmovupd(ymm12, mem(rcx, 0*32)) vfmadd231pd(mem(rcx, 1*32), xmm3, xmm13) vmovupd(xmm13, mem(rcx, 1*32)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORED) // begin I/O on columns 0-3 vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vunpcklpd(ymm10, ymm8, ymm2) vunpckhpd(ymm10, ymm8, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vperm2f128(imm(0x31), ymm2, ymm0, ymm8) vperm2f128(imm(0x31), ymm3, ymm1, ymm10) vbroadcastsd(mem(rbx), ymm3) vfmadd231pd(mem(rcx ), ymm3, ymm4) vfmadd231pd(mem(rcx, rsi, 1), ymm3, ymm6) vfmadd231pd(mem(rcx, rsi, 2), ymm3, ymm8) vfmadd231pd(mem(rcx, rax, 1), ymm3, ymm10) vmovupd(ymm4, mem(rcx )) vmovupd(ymm6, mem(rcx, rsi, 1)) vmovupd(ymm8, mem(rcx, rsi, 2)) vmovupd(ymm10, mem(rcx, rax, 1)) lea(mem(rcx, rsi, 4), rcx) vmovlpd(mem(rdx ), xmm0, xmm0) vmovhpd(mem(rdx, rsi, 1), xmm0, xmm0) vmovlpd(mem(rdx, rsi, 2), xmm1, xmm1) vmovhpd(mem(rdx, rax, 1), xmm1, xmm1) vperm2f128(imm(0x20), ymm1, ymm0, ymm0) vfmadd213pd(ymm12, ymm3, ymm0) vextractf128(imm(1), ymm0, xmm1) vmovlpd(xmm0, mem(rdx )) vmovhpd(xmm0, mem(rdx, rsi, 1)) vmovlpd(xmm1, mem(rdx, rsi, 2)) vmovhpd(xmm1, mem(rdx, rax, 1)) lea(mem(rdx, rsi, 4), rdx) // begin I/O on columns 4-5 vunpcklpd(ymm7, ymm5, ymm0) vunpckhpd(ymm7, ymm5, ymm1) vunpcklpd(ymm11, ymm9, ymm2) vunpckhpd(ymm11, ymm9, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm5) vinsertf128(imm(0x1), xmm3, ymm1, ymm7) vbroadcastsd(mem(rbx), ymm3) vfmadd231pd(mem(rcx ), ymm3, ymm5) vfmadd231pd(mem(rcx, rsi, 1), ymm3, ymm7) vmovupd(ymm5, mem(rcx )) vmovupd(ymm7, mem(rcx, rsi, 1)) //lea(mem(rcx, rsi, 4), rcx) vmovlpd(mem(rdx ), xmm0, xmm0) vmovhpd(mem(rdx, rsi, 1), xmm0, xmm0) vfmadd213pd(xmm13, xmm3, xmm0) vmovlpd(xmm0, mem(rdx )) vmovhpd(xmm0, mem(rdx, rsi, 1)) //lea(mem(rdx, rsi, 4), rdx) jmp(.DDONE) // jump to end. label(.DBETAZERO) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORBZ) // jump to column storage case label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx, 0*32)) vmovupd(xmm5, mem(rcx, 1*32)) add(rdi, rcx) vmovupd(ymm6, mem(rcx, 0*32)) vmovupd(xmm7, mem(rcx, 1*32)) add(rdi, rcx) vmovupd(ymm8, mem(rcx, 0*32)) vmovupd(xmm9, mem(rcx, 1*32)) add(rdi, rcx) vmovupd(ymm10, mem(rcx, 0*32)) vmovupd(xmm11, mem(rcx, 1*32)) add(rdi, rcx) vmovupd(ymm12, mem(rcx, 0*32)) vmovupd(xmm13, mem(rcx, 1*32)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORBZ) // begin I/O on columns 0-3 vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vunpcklpd(ymm10, ymm8, ymm2) vunpckhpd(ymm10, ymm8, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vperm2f128(imm(0x31), ymm2, ymm0, ymm8) vperm2f128(imm(0x31), ymm3, ymm1, ymm10) vmovupd(ymm4, mem(rcx )) vmovupd(ymm6, mem(rcx, rsi, 1)) vmovupd(ymm8, mem(rcx, rsi, 2)) vmovupd(ymm10, mem(rcx, rax, 1)) lea(mem(rcx, rsi, 4), rcx) vmovupd(ymm12, ymm0) vextractf128(imm(1), ymm0, xmm1) vmovlpd(xmm0, mem(rdx )) vmovhpd(xmm0, mem(rdx, rsi, 1)) vmovlpd(xmm1, mem(rdx, rsi, 2)) vmovhpd(xmm1, mem(rdx, rax, 1)) lea(mem(rdx, rsi, 4), rdx) // begin I/O on columns 4-5 vunpcklpd(ymm7, ymm5, ymm0) vunpckhpd(ymm7, ymm5, ymm1) vunpcklpd(ymm11, ymm9, ymm2) vunpckhpd(ymm11, ymm9, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm5) vinsertf128(imm(0x1), xmm3, ymm1, ymm7) vmovupd(ymm5, mem(rcx )) vmovupd(ymm7, mem(rcx, rsi, 1)) //lea(mem(rcx, rsi, 4), rcx) vmovupd(ymm13, ymm0) vmovlpd(xmm0, mem(rdx )) vmovhpd(xmm0, mem(rdx, rsi, 1)) //lea(mem(rdx, rsi, 4), rdx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rv_haswell_asm_4x6 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) //lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLPFETCH) // jump to column storage case label(.DROWPFETCH) // row-stored prefetching on c lea(mem(rcx, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 5*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 5*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 5*8)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 5*8)) // prefetch c + 3*rs_c jmp(.DPOSTPFETCH) // jump to end of prefetching c label(.DCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 8), rsi) // cs_c *= sizeof(double) lea(mem(rcx, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 3*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 3*8)) // prefetch c + 2*cs_c prefetch(0, mem(rdx, 3*8)) // prefetch c + 3*cs_c prefetch(0, mem(rdx, rsi, 1, 3*8)) // prefetch c + 4*cs_c prefetch(0, mem(rdx, rsi, 2, 3*8)) // prefetch c + 5*cs_c label(.DPOSTPFETCH) // done prefetching c #if 1 lea(mem(rax, r9, 8), rdx) // lea(mem(rdx, r9, 8), rdx) // rdx = a + 16*cs_a; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.DLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(rdx, 4*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, r9, 1, 4*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(rdx, r9, 2, 4*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) // ---------------------------------- iteration 3 #if 1 lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) dec(rsi) // i -= 1; jne(.DLOOPKITER) // iterate again if i != 0. label(.DCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.DLOOPKLEFT) // EDGE LOOP #if 0 prefetch(0, mem(rdx, 5*8)) add(r9, rdx) #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) dec(rsi) // i -= 1; jne(.DLOOPKLEFT) // iterate again if i != 0. label(.DPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(xmm0, xmm5, xmm5) vmulpd(ymm0, ymm6, ymm6) vmulpd(xmm0, xmm7, xmm7) vmulpd(ymm0, ymm8, ymm8) vmulpd(xmm0, xmm9, xmm9) vmulpd(ymm0, ymm10, ymm10) vmulpd(xmm0, xmm11, xmm11) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; //lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORED) // jump to column storage case label(.DROWSTORED) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm4) vmovupd(ymm4, mem(rcx, 0*32)) vfmadd231pd(mem(rcx, 1*32), xmm3, xmm5) vmovupd(xmm5, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm6) vmovupd(ymm6, mem(rcx, 0*32)) vfmadd231pd(mem(rcx, 1*32), xmm3, xmm7) vmovupd(xmm7, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm8) vmovupd(ymm8, mem(rcx, 0*32)) vfmadd231pd(mem(rcx, 1*32), xmm3, xmm9) vmovupd(xmm9, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm10) vmovupd(ymm10, mem(rcx, 0*32)) vfmadd231pd(mem(rcx, 1*32), xmm3, xmm11) vmovupd(xmm11, mem(rcx, 1*32)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORED) // begin I/O on columns 0-3 vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vunpcklpd(ymm10, ymm8, ymm2) vunpckhpd(ymm10, ymm8, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vperm2f128(imm(0x31), ymm2, ymm0, ymm8) vperm2f128(imm(0x31), ymm3, ymm1, ymm10) vbroadcastsd(mem(rbx), ymm3) vfmadd231pd(mem(rcx ), ymm3, ymm4) vfmadd231pd(mem(rcx, rsi, 1), ymm3, ymm6) vfmadd231pd(mem(rcx, rsi, 2), ymm3, ymm8) vfmadd231pd(mem(rcx, rax, 1), ymm3, ymm10) vmovupd(ymm4, mem(rcx )) vmovupd(ymm6, mem(rcx, rsi, 1)) vmovupd(ymm8, mem(rcx, rsi, 2)) vmovupd(ymm10, mem(rcx, rax, 1)) lea(mem(rcx, rsi, 4), rcx) // begin I/O on columns 4-5 vunpcklpd(ymm7, ymm5, ymm0) vunpckhpd(ymm7, ymm5, ymm1) vunpcklpd(ymm11, ymm9, ymm2) vunpckhpd(ymm11, ymm9, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm5) vinsertf128(imm(0x1), xmm3, ymm1, ymm7) vbroadcastsd(mem(rbx), ymm3) vfmadd231pd(mem(rcx ), ymm3, ymm5) vfmadd231pd(mem(rcx, rsi, 1), ymm3, ymm7) vmovupd(ymm5, mem(rcx )) vmovupd(ymm7, mem(rcx, rsi, 1)) //lea(mem(rcx, rsi, 4), rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORBZ) // jump to column storage case label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx, 0*32)) vmovupd(xmm5, mem(rcx, 1*32)) add(rdi, rcx) vmovupd(ymm6, mem(rcx, 0*32)) vmovupd(xmm7, mem(rcx, 1*32)) add(rdi, rcx) vmovupd(ymm8, mem(rcx, 0*32)) vmovupd(xmm9, mem(rcx, 1*32)) add(rdi, rcx) vmovupd(ymm10, mem(rcx, 0*32)) vmovupd(xmm11, mem(rcx, 1*32)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORBZ) // begin I/O on columns 0-3 vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vunpcklpd(ymm10, ymm8, ymm2) vunpckhpd(ymm10, ymm8, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vperm2f128(imm(0x31), ymm2, ymm0, ymm8) vperm2f128(imm(0x31), ymm3, ymm1, ymm10) vmovupd(ymm4, mem(rcx )) vmovupd(ymm6, mem(rcx, rsi, 1)) vmovupd(ymm8, mem(rcx, rsi, 2)) vmovupd(ymm10, mem(rcx, rax, 1)) lea(mem(rcx, rsi, 4), rcx) // begin I/O on columns 4-5 vunpcklpd(ymm7, ymm5, ymm0) vunpckhpd(ymm7, ymm5, ymm1) vunpcklpd(ymm11, ymm9, ymm2) vunpckhpd(ymm11, ymm9, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm5) vinsertf128(imm(0x1), xmm3, ymm1, ymm7) vmovupd(ymm5, mem(rcx )) vmovupd(ymm7, mem(rcx, rsi, 1)) //lea(mem(rcx, rsi, 4), rcx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rv_haswell_asm_3x6 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) //lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLPFETCH) // jump to column storage case label(.DROWPFETCH) // row-stored prefetching on c //lea(mem(rcx, rdi, 2), rdx) // //lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 5*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 5*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 5*8)) // prefetch c + 2*rs_c jmp(.DPOSTPFETCH) // jump to end of prefetching c label(.DCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 8), rsi) // cs_c *= sizeof(double) lea(mem(rcx, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; prefetch(0, mem(rcx, 2*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 2*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 2*8)) // prefetch c + 2*cs_c prefetch(0, mem(rdx, 2*8)) // prefetch c + 3*cs_c prefetch(0, mem(rdx, rsi, 1, 2*8)) // prefetch c + 4*cs_c prefetch(0, mem(rdx, rsi, 2, 2*8)) // prefetch c + 5*cs_c label(.DPOSTPFETCH) // done prefetching c #if 1 lea(mem(rax, r9, 8), rdx) // lea(mem(rdx, r9, 8), rdx) // rdx = a + 16*cs_a; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.DLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(rdx, 4*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, r9, 1, 4*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(rdx, r9, 2, 4*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) // ---------------------------------- iteration 3 #if 1 lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) dec(rsi) // i -= 1; jne(.DLOOPKITER) // iterate again if i != 0. label(.DCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.DLOOPKLEFT) // EDGE LOOP #if 0 prefetch(0, mem(rdx, 5*8)) add(r9, rdx) #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) dec(rsi) // i -= 1; jne(.DLOOPKLEFT) // iterate again if i != 0. label(.DPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(xmm0, xmm5, xmm5) vmulpd(ymm0, ymm6, ymm6) vmulpd(xmm0, xmm7, xmm7) vmulpd(ymm0, ymm8, ymm8) vmulpd(xmm0, xmm9, xmm9) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; lea(mem(rcx, rdi, 2), rdx) // load address of c + 2*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORED) // jump to column storage case label(.DROWSTORED) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm4) vmovupd(ymm4, mem(rcx, 0*32)) vfmadd231pd(mem(rcx, 1*32), xmm3, xmm5) vmovupd(xmm5, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm6) vmovupd(ymm6, mem(rcx, 0*32)) vfmadd231pd(mem(rcx, 1*32), xmm3, xmm7) vmovupd(xmm7, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm8) vmovupd(ymm8, mem(rcx, 0*32)) vfmadd231pd(mem(rcx, 1*32), xmm3, xmm9) vmovupd(xmm9, mem(rcx, 1*32)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORED) // begin I/O on columns 0-3 vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vunpcklpd(ymm10, ymm8, ymm2) vunpckhpd(ymm10, ymm8, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vperm2f128(imm(0x31), ymm2, ymm0, ymm8) vperm2f128(imm(0x31), ymm3, ymm1, ymm10) vextractf128(imm(0x1), ymm4, xmm12) vextractf128(imm(0x1), ymm6, xmm13) vextractf128(imm(0x1), ymm8, xmm14) vextractf128(imm(0x1), ymm10, xmm15) vbroadcastsd(mem(rbx), ymm3) vfmadd231pd(mem(rcx ), xmm3, xmm4) vfmadd231pd(mem(rcx, rsi, 1), xmm3, xmm6) vfmadd231pd(mem(rcx, rsi, 2), xmm3, xmm8) vfmadd231pd(mem(rcx, rax, 1), xmm3, xmm10) vmovupd(xmm4, mem(rcx )) vmovupd(xmm6, mem(rcx, rsi, 1)) vmovupd(xmm8, mem(rcx, rsi, 2)) vmovupd(xmm10, mem(rcx, rax, 1)) lea(mem(rcx, rsi, 4), rcx) vfmadd231sd(mem(rdx ), xmm3, xmm12) vfmadd231sd(mem(rdx, rsi, 1), xmm3, xmm13) vfmadd231sd(mem(rdx, rsi, 2), xmm3, xmm14) vfmadd231sd(mem(rdx, rax, 1), xmm3, xmm15) vmovsd(xmm12, mem(rdx )) vmovsd(xmm13, mem(rdx, rsi, 1)) vmovsd(xmm14, mem(rdx, rsi, 2)) vmovsd(xmm15, mem(rdx, rax, 1)) lea(mem(rdx, rsi, 4), rdx) // begin I/O on columns 4-5 vunpcklpd(ymm7, ymm5, ymm0) vunpckhpd(ymm7, ymm5, ymm1) vunpcklpd(ymm11, ymm9, ymm2) vunpckhpd(ymm11, ymm9, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm5) vinsertf128(imm(0x1), xmm3, ymm1, ymm7) //vperm2f128(imm(0x31), ymm2, ymm0, ymm9) //vperm2f128(imm(0x31), ymm3, ymm1, ymm11) vextractf128(imm(0x1), ymm5, xmm12) vextractf128(imm(0x1), ymm7, xmm13) vbroadcastsd(mem(rbx), ymm3) vfmadd231pd(mem(rcx ), xmm3, xmm5) vfmadd231pd(mem(rcx, rsi, 1), xmm3, xmm7) //vfmadd231pd(mem(rcx, rsi, 2), xmm3, xmm9) //vfmadd231pd(mem(rcx, rax, 1), xmm3, xmm11) vmovupd(xmm5, mem(rcx )) vmovupd(xmm7, mem(rcx, rsi, 1)) //lea(mem(rcx, rsi, 4), rcx) vfmadd231sd(mem(rdx ), xmm3, xmm12) vfmadd231sd(mem(rdx, rsi, 1), xmm3, xmm13) vmovsd(xmm12, mem(rdx )) vmovsd(xmm13, mem(rdx, rsi, 1)) //lea(mem(rdx, rsi, 4), rdx) jmp(.DDONE) // jump to end. label(.DBETAZERO) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORBZ) // jump to column storage case label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx, 0*32)) vmovupd(xmm5, mem(rcx, 1*32)) add(rdi, rcx) vmovupd(ymm6, mem(rcx, 0*32)) vmovupd(xmm7, mem(rcx, 1*32)) add(rdi, rcx) vmovupd(ymm8, mem(rcx, 0*32)) vmovupd(xmm9, mem(rcx, 1*32)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORBZ) // begin I/O on columns 0-3 vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vunpcklpd(ymm10, ymm8, ymm2) vunpckhpd(ymm10, ymm8, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vperm2f128(imm(0x31), ymm2, ymm0, ymm8) vperm2f128(imm(0x31), ymm3, ymm1, ymm10) vextractf128(imm(0x1), ymm4, xmm12) vextractf128(imm(0x1), ymm6, xmm13) vextractf128(imm(0x1), ymm8, xmm14) vextractf128(imm(0x1), ymm10, xmm15) vmovupd(xmm4, mem(rcx )) vmovupd(xmm6, mem(rcx, rsi, 1)) vmovupd(xmm8, mem(rcx, rsi, 2)) vmovupd(xmm10, mem(rcx, rax, 1)) lea(mem(rcx, rsi, 4), rcx) vmovsd(xmm12, mem(rdx )) vmovsd(xmm13, mem(rdx, rsi, 1)) vmovsd(xmm14, mem(rdx, rsi, 2)) vmovsd(xmm15, mem(rdx, rax, 1)) lea(mem(rdx, rsi, 4), rdx) // begin I/O on columns 4-5 vunpcklpd(ymm7, ymm5, ymm0) vunpckhpd(ymm7, ymm5, ymm1) vunpcklpd(ymm11, ymm9, ymm2) vunpckhpd(ymm11, ymm9, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm5) vinsertf128(imm(0x1), xmm3, ymm1, ymm7) vextractf128(imm(0x1), ymm5, xmm12) vextractf128(imm(0x1), ymm7, xmm13) vmovupd(xmm5, mem(rcx )) vmovupd(xmm7, mem(rcx, rsi, 1)) //lea(mem(rcx, rsi, 4), rcx) vmovsd(xmm12, mem(rdx )) vmovsd(xmm13, mem(rdx, rsi, 1)) //lea(mem(rdx, rsi, 4), rdx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rv_haswell_asm_2x6 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) //lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLPFETCH) // jump to column storage case label(.DROWPFETCH) // row-stored prefetching on c //lea(mem(rcx, rdi, 2), rdx) // //lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 5*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 5*8)) // prefetch c + 1*rs_c jmp(.DPOSTPFETCH) // jump to end of prefetching c label(.DCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 8), rsi) // cs_c *= sizeof(double) lea(mem(rcx, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; prefetch(0, mem(rcx, 1*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 1*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 1*8)) // prefetch c + 2*cs_c prefetch(0, mem(rdx, 1*8)) // prefetch c + 3*cs_c prefetch(0, mem(rdx, rsi, 1, 1*8)) // prefetch c + 4*cs_c prefetch(0, mem(rdx, rsi, 2, 1*8)) // prefetch c + 5*cs_c label(.DPOSTPFETCH) // done prefetching c #if 1 lea(mem(rax, r9, 8), rdx) // lea(mem(rdx, r9, 8), rdx) // rdx = a + 16*cs_a; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.DLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(rdx, 4*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, r9, 1, 4*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(rdx, r9, 2, 4*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) // ---------------------------------- iteration 3 #if 1 lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) dec(rsi) // i -= 1; jne(.DLOOPKITER) // iterate again if i != 0. label(.DCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.DLOOPKLEFT) // EDGE LOOP #if 0 prefetch(0, mem(rdx, 5*8)) add(r9, rdx) #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) dec(rsi) // i -= 1; jne(.DLOOPKLEFT) // iterate again if i != 0. label(.DPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(xmm0, xmm5, xmm5) vmulpd(ymm0, ymm6, ymm6) vmulpd(xmm0, xmm7, xmm7) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; //lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORED) // jump to column storage case label(.DROWSTORED) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm4) vmovupd(ymm4, mem(rcx, 0*32)) vfmadd231pd(mem(rcx, 1*32), xmm3, xmm5) vmovupd(xmm5, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm6) vmovupd(ymm6, mem(rcx, 0*32)) vfmadd231pd(mem(rcx, 1*32), xmm3, xmm7) vmovupd(xmm7, mem(rcx, 1*32)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORED) // begin I/O on columns 0-3 vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vunpcklpd(ymm10, ymm8, ymm2) vunpckhpd(ymm10, ymm8, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vperm2f128(imm(0x31), ymm2, ymm0, ymm8) vperm2f128(imm(0x31), ymm3, ymm1, ymm10) vbroadcastsd(mem(rbx), ymm3) vfmadd231pd(mem(rcx ), xmm3, xmm4) vfmadd231pd(mem(rcx, rsi, 1), xmm3, xmm6) vfmadd231pd(mem(rcx, rsi, 2), xmm3, xmm8) vfmadd231pd(mem(rcx, rax, 1), xmm3, xmm10) vmovupd(xmm4, mem(rcx )) vmovupd(xmm6, mem(rcx, rsi, 1)) vmovupd(xmm8, mem(rcx, rsi, 2)) vmovupd(xmm10, mem(rcx, rax, 1)) lea(mem(rcx, rsi, 4), rcx) // begin I/O on columns 4-5 vunpcklpd(ymm7, ymm5, ymm0) vunpckhpd(ymm7, ymm5, ymm1) vunpcklpd(ymm11, ymm9, ymm2) vunpckhpd(ymm11, ymm9, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm5) vinsertf128(imm(0x1), xmm3, ymm1, ymm7) vbroadcastsd(mem(rbx), ymm3) vfmadd231pd(mem(rcx ), xmm3, xmm5) vfmadd231pd(mem(rcx, rsi, 1), xmm3, xmm7) vmovupd(xmm5, mem(rcx )) vmovupd(xmm7, mem(rcx, rsi, 1)) //lea(mem(rcx, rsi, 4), rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORBZ) // jump to column storage case label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx, 0*32)) vmovupd(xmm5, mem(rcx, 1*32)) add(rdi, rcx) vmovupd(ymm6, mem(rcx, 0*32)) vmovupd(xmm7, mem(rcx, 1*32)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORBZ) // begin I/O on columns 0-3 vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vunpcklpd(ymm10, ymm8, ymm2) vunpckhpd(ymm10, ymm8, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vperm2f128(imm(0x31), ymm2, ymm0, ymm8) vperm2f128(imm(0x31), ymm3, ymm1, ymm10) vmovupd(xmm4, mem(rcx )) vmovupd(xmm6, mem(rcx, rsi, 1)) vmovupd(xmm8, mem(rcx, rsi, 2)) vmovupd(xmm10, mem(rcx, rax, 1)) lea(mem(rcx, rsi, 4), rcx) // begin I/O on columns 4-5 vunpcklpd(ymm7, ymm5, ymm0) vunpckhpd(ymm7, ymm5, ymm1) vunpcklpd(ymm11, ymm9, ymm2) vunpckhpd(ymm11, ymm9, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm5) vinsertf128(imm(0x1), xmm3, ymm1, ymm7) vmovupd(xmm5, mem(rcx )) vmovupd(xmm7, mem(rcx, rsi, 1)) //lea(mem(rcx, rsi, 4), rcx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rv_haswell_asm_1x6 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) //lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLPFETCH) // jump to column storage case label(.DROWPFETCH) // row-stored prefetching on c //lea(mem(rcx, rdi, 2), rdx) // //lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 5*8)) // prefetch c + 0*rs_c jmp(.DPOSTPFETCH) // jump to end of prefetching c label(.DCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 8), rsi) // cs_c *= sizeof(double) lea(mem(rcx, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; prefetch(0, mem(rcx, 0*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 0*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 0*8)) // prefetch c + 2*cs_c prefetch(0, mem(rdx, 0*8)) // prefetch c + 3*cs_c prefetch(0, mem(rdx, rsi, 1, 0*8)) // prefetch c + 4*cs_c prefetch(0, mem(rdx, rsi, 2, 0*8)) // prefetch c + 5*cs_c label(.DPOSTPFETCH) // done prefetching c #if 1 lea(mem(rax, r9, 8), rdx) // lea(mem(rdx, r9, 8), rdx) // rdx = a + 16*cs_a; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.DLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(rdx, 4*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, r9, 1, 4*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(rdx, r9, 2, 4*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) // ---------------------------------- iteration 3 #if 1 lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) dec(rsi) // i -= 1; jne(.DLOOPKITER) // iterate again if i != 0. label(.DCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.DLOOPKLEFT) // EDGE LOOP #if 0 prefetch(0, mem(rdx, 5*8)) add(r9, rdx) #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) dec(rsi) // i -= 1; jne(.DLOOPKLEFT) // iterate again if i != 0. label(.DPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(xmm0, xmm5, xmm5) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; //lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORED) // jump to column storage case label(.DROWSTORED) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm4) vmovupd(ymm4, mem(rcx, 0*32)) vfmadd231pd(mem(rcx, 1*32), xmm3, xmm5) vmovupd(xmm5, mem(rcx, 1*32)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORED) // begin I/O on columns 0-3 vmovlpd(mem(rcx ), xmm0, xmm0) vmovhpd(mem(rcx, rsi, 1), xmm0, xmm0) vmovlpd(mem(rcx, rsi, 2), xmm1, xmm1) vmovhpd(mem(rcx, rax, 1), xmm1, xmm1) vperm2f128(imm(0x20), ymm1, ymm0, ymm0) vfmadd213pd(ymm4, ymm3, ymm0) vextractf128(imm(1), ymm0, xmm1) vmovlpd(xmm0, mem(rcx )) vmovhpd(xmm0, mem(rcx, rsi, 1)) vmovlpd(xmm1, mem(rcx, rsi, 2)) vmovhpd(xmm1, mem(rcx, rax, 1)) lea(mem(rcx, rsi, 4), rcx) // begin I/O on columns 4-5 vmovlpd(mem(rcx ), xmm0, xmm0) vmovhpd(mem(rcx, rsi, 1), xmm0, xmm0) vfmadd213pd(xmm5, xmm3, xmm0) vmovlpd(xmm0, mem(rcx )) vmovhpd(xmm0, mem(rcx, rsi, 1)) //lea(mem(rcx, rsi, 4), rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORBZ) // jump to column storage case label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx, 0*32)) vmovupd(xmm5, mem(rcx, 1*32)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORBZ) // begin I/O on columns 0-3 vmovupd(ymm4, ymm0) vextractf128(imm(1), ymm0, xmm1) vmovlpd(xmm0, mem(rcx )) vmovhpd(xmm0, mem(rcx, rsi, 1)) vmovlpd(xmm1, mem(rcx, rsi, 2)) vmovhpd(xmm1, mem(rcx, rax, 1)) lea(mem(rcx, rsi, 4), rcx) // begin I/O on columns 4-5 vmovupd(xmm5, xmm0) vmovlpd(xmm0, mem(rcx )) vmovhpd(xmm0, mem(rcx, rsi, 1)) //lea(mem(rcx, rsi, 4), rcx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } blis-0.9.0/kernels/haswell/3/sup/d6x8/bli_gemmsup_rv_haswell_asm_dMx8.c000066400000000000000000002621671422157504600257760ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define BLIS_ASM_SYNTAX_ATT #include "bli_x86_asm_macros.h" /* rrr: -------- ------ -------- -------- ------ -------- -------- += ------ ... -------- -------- ------ -------- -------- ------ : -------- ------ : rcr: -------- | | | | -------- -------- | | | | -------- -------- += | | | | ... -------- -------- | | | | -------- -------- | | | | : -------- | | | | : Assumptions: - B is row-stored; - A is row- or column-stored; - m0 and n0 are at most MR and NR, respectively. Therefore, this (r)ow-preferential kernel is well-suited for contiguous (v)ector loads on B and single-element broadcasts from A. NOTE: These kernels explicitly support column-oriented IO, implemented via an in-register transpose. And thus they also support the crr and ccr cases, though only crr is ever utilized (because ccr is handled by transposing the operation and executing rcr, which does not incur the cost of the in-register transpose). crr: | | | | | | | | ------ -------- | | | | | | | | ------ -------- | | | | | | | | += ------ ... -------- | | | | | | | | ------ -------- | | | | | | | | ------ : | | | | | | | | ------ : */ // Prototype reference microkernels. GEMMSUP_KER_PROT( double, d, gemmsup_r_haswell_ref ) // Define parameters and variables for edge case kernel map. #define NUM_MR 4 #define NUM_NR 4 #define FUNCPTR_T dgemmsup_ker_ft static dim_t mrs[NUM_MR] = { 6, 4, 2, 1 }; static dim_t nrs[NUM_NR] = { 8, 4, 2, 1 }; static FUNCPTR_T kmap[NUM_MR][NUM_NR] = { /* 8 4 2 1 */ /* 6 */ { bli_dgemmsup_rv_haswell_asm_6x8, bli_dgemmsup_rv_haswell_asm_6x4, bli_dgemmsup_rv_haswell_asm_6x2, bli_dgemmsup_r_haswell_ref_6x1 }, /* 4 */ { bli_dgemmsup_rv_haswell_asm_4x8, bli_dgemmsup_rv_haswell_asm_4x4, bli_dgemmsup_rv_haswell_asm_4x2, bli_dgemmsup_r_haswell_ref_4x1 }, /* 2 */ { bli_dgemmsup_rv_haswell_asm_2x8, bli_dgemmsup_rv_haswell_asm_2x4, bli_dgemmsup_rv_haswell_asm_2x2, bli_dgemmsup_r_haswell_ref_2x1 }, /* 1 */ { bli_dgemmsup_rv_haswell_asm_1x8, bli_dgemmsup_rv_haswell_asm_1x4, bli_dgemmsup_rv_haswell_asm_1x2, bli_dgemmsup_r_haswell_ref_1x1 }, }; void bli_dgemmsup_rv_haswell_asm_6x8 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { #if 0 bli_dgemmsup_r_haswell_ref ( conja, conjb, m0, n0, k0, alpha, a, rs_a0, cs_a0, b, rs_b0, cs_b0, beta, c, rs_c0, cs_c0, data, cntx ); return; #endif // Use a reference kernel if this is an edge case in the m or n // dimensions. if ( m0 < 6 || n0 < 8 ) { #if 0 bli_dgemmsup_r_haswell_ref ( conja, conjb, m0, n0, k0, alpha, a, rs_a0, cs_a0, b, rs_b0, cs_b0, beta, c, rs_c0, cs_c0, data, cntx ); return; #endif dim_t n_left = n0; double* restrict cj = c; double* restrict bj = b; // Iterate across columns (corresponding to elements of nrs) until // n_left is zero. for ( dim_t j = 0; n_left != 0; ++j ) { const dim_t nr_cur = nrs[ j ]; // Once we find the value of nrs that is less than (or equal to) // n_left, we use the kernels in that column. if ( nr_cur <= n_left ) { dim_t m_left = m0; double* restrict cij = cj; double* restrict ai = a; // Iterate down the current column (corresponding to elements // of mrs) until m_left is zero. for ( dim_t i = 0; m_left != 0; ++i ) { const dim_t mr_cur = mrs[ i ]; // Once we find the value of mrs that is less than (or equal // to) m_left, we select that kernel. if ( mr_cur <= m_left ) { FUNCPTR_T ker_fp = kmap[i][j]; //printf( "executing %d x %d sup kernel.\n", (int)mr_cur, (int)nr_cur ); // Call the kernel using current mrs and nrs values. ker_fp ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); // Advance C and A pointers by the mrs and nrs we just // used, and decrement m_left. cij += mr_cur*rs_c0; ai += mr_cur*rs_a0; m_left -= mr_cur; } } // Advance C and B pointers by the mrs and nrs we just used, and // decrement n_left. cj += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } } return; } //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) //lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLPFETCH) // jump to column storage case label(.DROWPFETCH) // row-stored prefetching on c lea(mem(rcx, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 7*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 7*8)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 7*8)) // prefetch c + 3*rs_c prefetch(0, mem(rdx, rdi, 1, 7*8)) // prefetch c + 4*rs_c prefetch(0, mem(rdx, rdi, 2, 7*8)) // prefetch c + 5*rs_c jmp(.DPOSTPFETCH) // jump to end of prefetching c label(.DCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 8), rsi) // cs_c *= sizeof(double) lea(mem(rcx, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; prefetch(0, mem(rcx, 4*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 4*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 4*8)) // prefetch c + 2*cs_c prefetch(0, mem(rdx, 4*8)) // prefetch c + 3*cs_c prefetch(0, mem(rdx, rsi, 1, 4*8)) // prefetch c + 4*cs_c prefetch(0, mem(rdx, rsi, 2, 4*8)) // prefetch c + 5*cs_c lea(mem(rdx, rsi, 2), rdx) // rdx = c + 5*cs_c; prefetch(0, mem(rdx, rsi, 1, 4*8)) // prefetch c + 6*cs_c prefetch(0, mem(rdx, rsi, 2, 4*8)) // prefetch c + 7*cs_c label(.DPOSTPFETCH) // done prefetching c #if 1 lea(mem(rax, r9, 8), rdx) // lea(mem(rdx, r9, 8), rdx) // rdx = a + 16*cs_a; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.DLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(rdx, 5*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, r8, 4), ymm2) vbroadcastsd(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, r9, 1, 5*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, r8, 4), ymm2) vbroadcastsd(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(rdx, r9, 2, 5*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, r8, 4), ymm2) vbroadcastsd(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) // ---------------------------------- iteration 3 #if 1 lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, r8, 4), ymm2) vbroadcastsd(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKITER) // iterate again if i != 0. label(.DCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.DLOOPKLEFT) // EDGE LOOP #if 0 prefetch(0, mem(rdx, 5*8)) add(r9, rdx) #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, r8, 4), ymm2) vbroadcastsd(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKLEFT) // iterate again if i != 0. label(.DPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(ymm0, ymm5, ymm5) vmulpd(ymm0, ymm6, ymm6) vmulpd(ymm0, ymm7, ymm7) vmulpd(ymm0, ymm8, ymm8) vmulpd(ymm0, ymm9, ymm9) vmulpd(ymm0, ymm10, ymm10) vmulpd(ymm0, ymm11, ymm11) vmulpd(ymm0, ymm12, ymm12) vmulpd(ymm0, ymm13, ymm13) vmulpd(ymm0, ymm14, ymm14) vmulpd(ymm0, ymm15, ymm15) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORED) // jump to column storage case label(.DROWSTORED) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm4) vmovupd(ymm4, mem(rcx, 0*32)) vfmadd231pd(mem(rcx, 1*32), ymm3, ymm5) vmovupd(ymm5, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm6) vmovupd(ymm6, mem(rcx, 0*32)) vfmadd231pd(mem(rcx, 1*32), ymm3, ymm7) vmovupd(ymm7, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm8) vmovupd(ymm8, mem(rcx, 0*32)) vfmadd231pd(mem(rcx, 1*32), ymm3, ymm9) vmovupd(ymm9, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm10) vmovupd(ymm10, mem(rcx, 0*32)) vfmadd231pd(mem(rcx, 1*32), ymm3, ymm11) vmovupd(ymm11, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm12) vmovupd(ymm12, mem(rcx, 0*32)) vfmadd231pd(mem(rcx, 1*32), ymm3, ymm13) vmovupd(ymm13, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm14) vmovupd(ymm14, mem(rcx, 0*32)) vfmadd231pd(mem(rcx, 1*32), ymm3, ymm15) vmovupd(ymm15, mem(rcx, 1*32)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORED) // begin I/O on columns 0-3 vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vunpcklpd(ymm10, ymm8, ymm2) vunpckhpd(ymm10, ymm8, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vperm2f128(imm(0x31), ymm2, ymm0, ymm8) vperm2f128(imm(0x31), ymm3, ymm1, ymm10) vbroadcastsd(mem(rbx), ymm3) vfmadd231pd(mem(rcx ), ymm3, ymm4) vfmadd231pd(mem(rcx, rsi, 1), ymm3, ymm6) vfmadd231pd(mem(rcx, rsi, 2), ymm3, ymm8) vfmadd231pd(mem(rcx, rax, 1), ymm3, ymm10) vmovupd(ymm4, mem(rcx )) vmovupd(ymm6, mem(rcx, rsi, 1)) vmovupd(ymm8, mem(rcx, rsi, 2)) vmovupd(ymm10, mem(rcx, rax, 1)) lea(mem(rcx, rsi, 4), rcx) vunpcklpd(ymm14, ymm12, ymm0) vunpckhpd(ymm14, ymm12, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vextractf128(imm(0x1), ymm1, xmm4) vfmadd231pd(mem(rdx ), xmm3, xmm0) vfmadd231pd(mem(rdx, rsi, 1), xmm3, xmm1) vfmadd231pd(mem(rdx, rsi, 2), xmm3, xmm2) vfmadd231pd(mem(rdx, rax, 1), xmm3, xmm4) vmovupd(xmm0, mem(rdx )) vmovupd(xmm1, mem(rdx, rsi, 1)) vmovupd(xmm2, mem(rdx, rsi, 2)) vmovupd(xmm4, mem(rdx, rax, 1)) lea(mem(rdx, rsi, 4), rdx) // begin I/O on columns 4-7 vunpcklpd(ymm7, ymm5, ymm0) vunpckhpd(ymm7, ymm5, ymm1) vunpcklpd(ymm11, ymm9, ymm2) vunpckhpd(ymm11, ymm9, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm5) vinsertf128(imm(0x1), xmm3, ymm1, ymm7) vperm2f128(imm(0x31), ymm2, ymm0, ymm9) vperm2f128(imm(0x31), ymm3, ymm1, ymm11) vbroadcastsd(mem(rbx), ymm3) vfmadd231pd(mem(rcx ), ymm3, ymm5) vfmadd231pd(mem(rcx, rsi, 1), ymm3, ymm7) vfmadd231pd(mem(rcx, rsi, 2), ymm3, ymm9) vfmadd231pd(mem(rcx, rax, 1), ymm3, ymm11) vmovupd(ymm5, mem(rcx )) vmovupd(ymm7, mem(rcx, rsi, 1)) vmovupd(ymm9, mem(rcx, rsi, 2)) vmovupd(ymm11, mem(rcx, rax, 1)) //lea(mem(rcx, rsi, 4), rcx) vunpcklpd(ymm15, ymm13, ymm0) vunpckhpd(ymm15, ymm13, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vextractf128(imm(0x1), ymm1, xmm4) vfmadd231pd(mem(rdx ), xmm3, xmm0) vfmadd231pd(mem(rdx, rsi, 1), xmm3, xmm1) vfmadd231pd(mem(rdx, rsi, 2), xmm3, xmm2) vfmadd231pd(mem(rdx, rax, 1), xmm3, xmm4) vmovupd(xmm0, mem(rdx )) vmovupd(xmm1, mem(rdx, rsi, 1)) vmovupd(xmm2, mem(rdx, rsi, 2)) vmovupd(xmm4, mem(rdx, rax, 1)) //lea(mem(rdx, rsi, 4), rdx) jmp(.DDONE) // jump to end. label(.DBETAZERO) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORBZ) // jump to column storage case label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx, 0*32)) vmovupd(ymm5, mem(rcx, 1*32)) add(rdi, rcx) vmovupd(ymm6, mem(rcx, 0*32)) vmovupd(ymm7, mem(rcx, 1*32)) add(rdi, rcx) vmovupd(ymm8, mem(rcx, 0*32)) vmovupd(ymm9, mem(rcx, 1*32)) add(rdi, rcx) vmovupd(ymm10, mem(rcx, 0*32)) vmovupd(ymm11, mem(rcx, 1*32)) add(rdi, rcx) vmovupd(ymm12, mem(rcx, 0*32)) vmovupd(ymm13, mem(rcx, 1*32)) add(rdi, rcx) vmovupd(ymm14, mem(rcx, 0*32)) vmovupd(ymm15, mem(rcx, 1*32)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORBZ) // begin I/O on columns 0-3 vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vunpcklpd(ymm10, ymm8, ymm2) vunpckhpd(ymm10, ymm8, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vperm2f128(imm(0x31), ymm2, ymm0, ymm8) vperm2f128(imm(0x31), ymm3, ymm1, ymm10) vmovupd(ymm4, mem(rcx )) vmovupd(ymm6, mem(rcx, rsi, 1)) vmovupd(ymm8, mem(rcx, rsi, 2)) vmovupd(ymm10, mem(rcx, rax, 1)) lea(mem(rcx, rsi, 4), rcx) vunpcklpd(ymm14, ymm12, ymm0) vunpckhpd(ymm14, ymm12, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vextractf128(imm(0x1), ymm1, xmm4) vmovupd(xmm0, mem(rdx )) vmovupd(xmm1, mem(rdx, rsi, 1)) vmovupd(xmm2, mem(rdx, rsi, 2)) vmovupd(xmm4, mem(rdx, rax, 1)) lea(mem(rdx, rsi, 4), rdx) // begin I/O on columns 4-7 vunpcklpd(ymm7, ymm5, ymm0) vunpckhpd(ymm7, ymm5, ymm1) vunpcklpd(ymm11, ymm9, ymm2) vunpckhpd(ymm11, ymm9, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm5) vinsertf128(imm(0x1), xmm3, ymm1, ymm7) vperm2f128(imm(0x31), ymm2, ymm0, ymm9) vperm2f128(imm(0x31), ymm3, ymm1, ymm11) vmovupd(ymm5, mem(rcx )) vmovupd(ymm7, mem(rcx, rsi, 1)) vmovupd(ymm9, mem(rcx, rsi, 2)) vmovupd(ymm11, mem(rcx, rax, 1)) //lea(mem(rcx, rsi, 4), rcx) vunpcklpd(ymm15, ymm13, ymm0) vunpckhpd(ymm15, ymm13, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vextractf128(imm(0x1), ymm1, xmm4) vmovupd(xmm0, mem(rdx )) vmovupd(xmm1, mem(rdx, rsi, 1)) vmovupd(xmm2, mem(rdx, rsi, 2)) vmovupd(xmm4, mem(rdx, rax, 1)) //lea(mem(rdx, rsi, 4), rdx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rv_haswell_asm_5x8 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) //lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLPFETCH) // jump to column storage case label(.DROWPFETCH) // row-stored prefetching on c lea(mem(rcx, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 7*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 7*8)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 7*8)) // prefetch c + 3*rs_c prefetch(0, mem(rdx, rdi, 1, 7*8)) // prefetch c + 4*rs_c jmp(.DPOSTPFETCH) // jump to end of prefetching c label(.DCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 8), rsi) // cs_c *= sizeof(double) lea(mem(rcx, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; prefetch(0, mem(rcx, 4*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 4*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 4*8)) // prefetch c + 2*cs_c prefetch(0, mem(rdx, 4*8)) // prefetch c + 3*cs_c prefetch(0, mem(rdx, rsi, 1, 4*8)) // prefetch c + 4*cs_c prefetch(0, mem(rdx, rsi, 2, 4*8)) // prefetch c + 5*cs_c lea(mem(rdx, rsi, 2), rdx) // rdx = c + 5*cs_c; prefetch(0, mem(rdx, rsi, 1, 4*8)) // prefetch c + 6*cs_c prefetch(0, mem(rdx, rsi, 2, 4*8)) // prefetch c + 7*cs_c label(.DPOSTPFETCH) // done prefetching c #if 1 lea(mem(rax, r9, 8), rdx) // lea(mem(rdx, r9, 8), rdx) // rdx = a + 16*cs_a; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.DLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(rdx, 4*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, r9, 1, 4*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(rdx, r9, 2, 4*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) // ---------------------------------- iteration 3 #if 1 lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) dec(rsi) // i -= 1; jne(.DLOOPKITER) // iterate again if i != 0. label(.DCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.DLOOPKLEFT) // EDGE LOOP #if 0 prefetch(0, mem(rdx, 5*8)) add(r9, rdx) #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) dec(rsi) // i -= 1; jne(.DLOOPKLEFT) // iterate again if i != 0. label(.DPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(ymm0, ymm5, ymm5) vmulpd(ymm0, ymm6, ymm6) vmulpd(ymm0, ymm7, ymm7) vmulpd(ymm0, ymm8, ymm8) vmulpd(ymm0, ymm9, ymm9) vmulpd(ymm0, ymm10, ymm10) vmulpd(ymm0, ymm11, ymm11) vmulpd(ymm0, ymm12, ymm12) vmulpd(ymm0, ymm13, ymm13) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORED) // jump to column storage case label(.DROWSTORED) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm4) vmovupd(ymm4, mem(rcx, 0*32)) vfmadd231pd(mem(rcx, 1*32), ymm3, ymm5) vmovupd(ymm5, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm6) vmovupd(ymm6, mem(rcx, 0*32)) vfmadd231pd(mem(rcx, 1*32), ymm3, ymm7) vmovupd(ymm7, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm8) vmovupd(ymm8, mem(rcx, 0*32)) vfmadd231pd(mem(rcx, 1*32), ymm3, ymm9) vmovupd(ymm9, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm10) vmovupd(ymm10, mem(rcx, 0*32)) vfmadd231pd(mem(rcx, 1*32), ymm3, ymm11) vmovupd(ymm11, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm12) vmovupd(ymm12, mem(rcx, 0*32)) vfmadd231pd(mem(rcx, 1*32), ymm3, ymm13) vmovupd(ymm13, mem(rcx, 1*32)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORED) // begin I/O on columns 0-3 vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vunpcklpd(ymm10, ymm8, ymm2) vunpckhpd(ymm10, ymm8, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vperm2f128(imm(0x31), ymm2, ymm0, ymm8) vperm2f128(imm(0x31), ymm3, ymm1, ymm10) vbroadcastsd(mem(rbx), ymm3) vfmadd231pd(mem(rcx ), ymm3, ymm4) vfmadd231pd(mem(rcx, rsi, 1), ymm3, ymm6) vfmadd231pd(mem(rcx, rsi, 2), ymm3, ymm8) vfmadd231pd(mem(rcx, rax, 1), ymm3, ymm10) vmovupd(ymm4, mem(rcx )) vmovupd(ymm6, mem(rcx, rsi, 1)) vmovupd(ymm8, mem(rcx, rsi, 2)) vmovupd(ymm10, mem(rcx, rax, 1)) lea(mem(rcx, rsi, 4), rcx) vmovlpd(mem(rdx ), xmm0, xmm0) vmovhpd(mem(rdx, rsi, 1), xmm0, xmm0) vmovlpd(mem(rdx, rsi, 2), xmm1, xmm1) vmovhpd(mem(rdx, rax, 1), xmm1, xmm1) vperm2f128(imm(0x20), ymm1, ymm0, ymm0) vfmadd213pd(ymm12, ymm3, ymm0) vextractf128(imm(1), ymm0, xmm1) vmovlpd(xmm0, mem(rdx )) vmovhpd(xmm0, mem(rdx, rsi, 1)) vmovlpd(xmm1, mem(rdx, rsi, 2)) vmovhpd(xmm1, mem(rdx, rax, 1)) lea(mem(rdx, rsi, 4), rdx) // begin I/O on columns 4-7 vunpcklpd(ymm7, ymm5, ymm0) vunpckhpd(ymm7, ymm5, ymm1) vunpcklpd(ymm11, ymm9, ymm2) vunpckhpd(ymm11, ymm9, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm5) vinsertf128(imm(0x1), xmm3, ymm1, ymm7) vperm2f128(imm(0x31), ymm2, ymm0, ymm9) vperm2f128(imm(0x31), ymm3, ymm1, ymm11) vbroadcastsd(mem(rbx), ymm3) vfmadd231pd(mem(rcx ), ymm3, ymm5) vfmadd231pd(mem(rcx, rsi, 1), ymm3, ymm7) vfmadd231pd(mem(rcx, rsi, 2), ymm3, ymm9) vfmadd231pd(mem(rcx, rax, 1), ymm3, ymm11) vmovupd(ymm5, mem(rcx )) vmovupd(ymm7, mem(rcx, rsi, 1)) vmovupd(ymm9, mem(rcx, rsi, 2)) vmovupd(ymm11, mem(rcx, rax, 1)) //lea(mem(rcx, rsi, 4), rcx) vmovlpd(mem(rdx ), xmm0, xmm0) vmovhpd(mem(rdx, rsi, 1), xmm0, xmm0) vmovlpd(mem(rdx, rsi, 2), xmm1, xmm1) vmovhpd(mem(rdx, rax, 1), xmm1, xmm1) vperm2f128(imm(0x20), ymm1, ymm0, ymm0) vfmadd213pd(ymm13, ymm3, ymm0) vextractf128(imm(1), ymm0, xmm1) vmovlpd(xmm0, mem(rdx )) vmovhpd(xmm0, mem(rdx, rsi, 1)) vmovlpd(xmm1, mem(rdx, rsi, 2)) vmovhpd(xmm1, mem(rdx, rax, 1)) //lea(mem(rdx, rsi, 4), rdx) jmp(.DDONE) // jump to end. label(.DBETAZERO) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORBZ) // jump to column storage case label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx, 0*32)) vmovupd(ymm5, mem(rcx, 1*32)) add(rdi, rcx) vmovupd(ymm6, mem(rcx, 0*32)) vmovupd(ymm7, mem(rcx, 1*32)) add(rdi, rcx) vmovupd(ymm8, mem(rcx, 0*32)) vmovupd(ymm9, mem(rcx, 1*32)) add(rdi, rcx) vmovupd(ymm10, mem(rcx, 0*32)) vmovupd(ymm11, mem(rcx, 1*32)) add(rdi, rcx) vmovupd(ymm12, mem(rcx, 0*32)) vmovupd(ymm13, mem(rcx, 1*32)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORBZ) // begin I/O on columns 0-3 vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vunpcklpd(ymm10, ymm8, ymm2) vunpckhpd(ymm10, ymm8, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vperm2f128(imm(0x31), ymm2, ymm0, ymm8) vperm2f128(imm(0x31), ymm3, ymm1, ymm10) vmovupd(ymm4, mem(rcx )) vmovupd(ymm6, mem(rcx, rsi, 1)) vmovupd(ymm8, mem(rcx, rsi, 2)) vmovupd(ymm10, mem(rcx, rax, 1)) lea(mem(rcx, rsi, 4), rcx) vmovupd(ymm12, ymm0) vextractf128(imm(1), ymm0, xmm1) vmovlpd(xmm0, mem(rdx )) vmovhpd(xmm0, mem(rdx, rsi, 1)) vmovlpd(xmm1, mem(rdx, rsi, 2)) vmovhpd(xmm1, mem(rdx, rax, 1)) lea(mem(rdx, rsi, 4), rdx) // begin I/O on columns 4-7 vunpcklpd(ymm7, ymm5, ymm0) vunpckhpd(ymm7, ymm5, ymm1) vunpcklpd(ymm11, ymm9, ymm2) vunpckhpd(ymm11, ymm9, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm5) vinsertf128(imm(0x1), xmm3, ymm1, ymm7) vperm2f128(imm(0x31), ymm2, ymm0, ymm9) vperm2f128(imm(0x31), ymm3, ymm1, ymm11) vmovupd(ymm5, mem(rcx )) vmovupd(ymm7, mem(rcx, rsi, 1)) vmovupd(ymm9, mem(rcx, rsi, 2)) vmovupd(ymm11, mem(rcx, rax, 1)) //lea(mem(rcx, rsi, 4), rcx) vmovupd(ymm13, ymm0) vextractf128(imm(1), ymm0, xmm1) vmovlpd(xmm0, mem(rdx )) vmovhpd(xmm0, mem(rdx, rsi, 1)) vmovlpd(xmm1, mem(rdx, rsi, 2)) vmovhpd(xmm1, mem(rdx, rax, 1)) //lea(mem(rdx, rsi, 4), rdx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rv_haswell_asm_4x8 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) //lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLPFETCH) // jump to column storage case label(.DROWPFETCH) // row-stored prefetching on c lea(mem(rcx, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 7*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 7*8)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 7*8)) // prefetch c + 3*rs_c jmp(.DPOSTPFETCH) // jump to end of prefetching c label(.DCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 8), rsi) // cs_c *= sizeof(double) lea(mem(rcx, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 3*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 3*8)) // prefetch c + 2*cs_c prefetch(0, mem(rdx, 3*8)) // prefetch c + 3*cs_c prefetch(0, mem(rdx, rsi, 1, 3*8)) // prefetch c + 4*cs_c prefetch(0, mem(rdx, rsi, 2, 3*8)) // prefetch c + 5*cs_c lea(mem(rdx, rsi, 2), rdx) // rdx = c + 5*cs_c; prefetch(0, mem(rdx, rsi, 1, 3*8)) // prefetch c + 6*cs_c prefetch(0, mem(rdx, rsi, 2, 3*8)) // prefetch c + 7*cs_c label(.DPOSTPFETCH) // done prefetching c #if 1 lea(mem(rax, r9, 8), rdx) // lea(mem(rdx, r9, 8), rdx) // rdx = a + 16*cs_a; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.DLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(rdx, 4*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, r9, 1, 4*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(rdx, r9, 2, 4*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) // ---------------------------------- iteration 3 #if 1 lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) dec(rsi) // i -= 1; jne(.DLOOPKITER) // iterate again if i != 0. label(.DCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.DLOOPKLEFT) // EDGE LOOP #if 0 prefetch(0, mem(rdx, 5*8)) add(r9, rdx) #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) dec(rsi) // i -= 1; jne(.DLOOPKLEFT) // iterate again if i != 0. label(.DPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(ymm0, ymm5, ymm5) vmulpd(ymm0, ymm6, ymm6) vmulpd(ymm0, ymm7, ymm7) vmulpd(ymm0, ymm8, ymm8) vmulpd(ymm0, ymm9, ymm9) vmulpd(ymm0, ymm10, ymm10) vmulpd(ymm0, ymm11, ymm11) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; //lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORED) // jump to column storage case label(.DROWSTORED) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm4) vmovupd(ymm4, mem(rcx, 0*32)) vfmadd231pd(mem(rcx, 1*32), ymm3, ymm5) vmovupd(ymm5, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm6) vmovupd(ymm6, mem(rcx, 0*32)) vfmadd231pd(mem(rcx, 1*32), ymm3, ymm7) vmovupd(ymm7, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm8) vmovupd(ymm8, mem(rcx, 0*32)) vfmadd231pd(mem(rcx, 1*32), ymm3, ymm9) vmovupd(ymm9, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm10) vmovupd(ymm10, mem(rcx, 0*32)) vfmadd231pd(mem(rcx, 1*32), ymm3, ymm11) vmovupd(ymm11, mem(rcx, 1*32)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORED) // begin I/O on columns 0-3 vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vunpcklpd(ymm10, ymm8, ymm2) vunpckhpd(ymm10, ymm8, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vperm2f128(imm(0x31), ymm2, ymm0, ymm8) vperm2f128(imm(0x31), ymm3, ymm1, ymm10) vbroadcastsd(mem(rbx), ymm3) vfmadd231pd(mem(rcx ), ymm3, ymm4) vfmadd231pd(mem(rcx, rsi, 1), ymm3, ymm6) vfmadd231pd(mem(rcx, rsi, 2), ymm3, ymm8) vfmadd231pd(mem(rcx, rax, 1), ymm3, ymm10) vmovupd(ymm4, mem(rcx )) vmovupd(ymm6, mem(rcx, rsi, 1)) vmovupd(ymm8, mem(rcx, rsi, 2)) vmovupd(ymm10, mem(rcx, rax, 1)) lea(mem(rcx, rsi, 4), rcx) // begin I/O on columns 4-7 vunpcklpd(ymm7, ymm5, ymm0) vunpckhpd(ymm7, ymm5, ymm1) vunpcklpd(ymm11, ymm9, ymm2) vunpckhpd(ymm11, ymm9, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm5) vinsertf128(imm(0x1), xmm3, ymm1, ymm7) vperm2f128(imm(0x31), ymm2, ymm0, ymm9) vperm2f128(imm(0x31), ymm3, ymm1, ymm11) vbroadcastsd(mem(rbx), ymm3) vfmadd231pd(mem(rcx ), ymm3, ymm5) vfmadd231pd(mem(rcx, rsi, 1), ymm3, ymm7) vfmadd231pd(mem(rcx, rsi, 2), ymm3, ymm9) vfmadd231pd(mem(rcx, rax, 1), ymm3, ymm11) vmovupd(ymm5, mem(rcx )) vmovupd(ymm7, mem(rcx, rsi, 1)) vmovupd(ymm9, mem(rcx, rsi, 2)) vmovupd(ymm11, mem(rcx, rax, 1)) //lea(mem(rcx, rsi, 4), rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORBZ) // jump to column storage case label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx, 0*32)) vmovupd(ymm5, mem(rcx, 1*32)) add(rdi, rcx) vmovupd(ymm6, mem(rcx, 0*32)) vmovupd(ymm7, mem(rcx, 1*32)) add(rdi, rcx) vmovupd(ymm8, mem(rcx, 0*32)) vmovupd(ymm9, mem(rcx, 1*32)) add(rdi, rcx) vmovupd(ymm10, mem(rcx, 0*32)) vmovupd(ymm11, mem(rcx, 1*32)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORBZ) // begin I/O on columns 0-3 vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vunpcklpd(ymm10, ymm8, ymm2) vunpckhpd(ymm10, ymm8, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vperm2f128(imm(0x31), ymm2, ymm0, ymm8) vperm2f128(imm(0x31), ymm3, ymm1, ymm10) vmovupd(ymm4, mem(rcx )) vmovupd(ymm6, mem(rcx, rsi, 1)) vmovupd(ymm8, mem(rcx, rsi, 2)) vmovupd(ymm10, mem(rcx, rax, 1)) lea(mem(rcx, rsi, 4), rcx) // begin I/O on columns 4-7 vunpcklpd(ymm7, ymm5, ymm0) vunpckhpd(ymm7, ymm5, ymm1) vunpcklpd(ymm11, ymm9, ymm2) vunpckhpd(ymm11, ymm9, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm5) vinsertf128(imm(0x1), xmm3, ymm1, ymm7) vperm2f128(imm(0x31), ymm2, ymm0, ymm9) vperm2f128(imm(0x31), ymm3, ymm1, ymm11) vmovupd(ymm5, mem(rcx )) vmovupd(ymm7, mem(rcx, rsi, 1)) vmovupd(ymm9, mem(rcx, rsi, 2)) vmovupd(ymm11, mem(rcx, rax, 1)) //lea(mem(rcx, rsi, 4), rcx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rv_haswell_asm_3x8 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) //lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLPFETCH) // jump to column storage case label(.DROWPFETCH) // row-stored prefetching on c //lea(mem(rcx, rdi, 2), rdx) // //lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 7*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 7*8)) // prefetch c + 2*rs_c jmp(.DPOSTPFETCH) // jump to end of prefetching c label(.DCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 8), rsi) // cs_c *= sizeof(double) lea(mem(rcx, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; prefetch(0, mem(rcx, 2*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 2*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 2*8)) // prefetch c + 2*cs_c prefetch(0, mem(rdx, 2*8)) // prefetch c + 3*cs_c prefetch(0, mem(rdx, rsi, 1, 2*8)) // prefetch c + 4*cs_c prefetch(0, mem(rdx, rsi, 2, 2*8)) // prefetch c + 5*cs_c lea(mem(rdx, rsi, 2), rdx) // rdx = c + 5*cs_c; prefetch(0, mem(rdx, rsi, 1, 2*8)) // prefetch c + 6*cs_c prefetch(0, mem(rdx, rsi, 2, 2*8)) // prefetch c + 7*cs_c label(.DPOSTPFETCH) // done prefetching c #if 1 lea(mem(rax, r9, 8), rdx) // lea(mem(rdx, r9, 8), rdx) // rdx = a + 16*cs_a; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.DLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(rdx, 4*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, r9, 1, 4*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(rdx, r9, 2, 4*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) // ---------------------------------- iteration 3 #if 1 lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) dec(rsi) // i -= 1; jne(.DLOOPKITER) // iterate again if i != 0. label(.DCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.DLOOPKLEFT) // EDGE LOOP #if 0 prefetch(0, mem(rdx, 5*8)) add(r9, rdx) #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) dec(rsi) // i -= 1; jne(.DLOOPKLEFT) // iterate again if i != 0. label(.DPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(ymm0, ymm5, ymm5) vmulpd(ymm0, ymm6, ymm6) vmulpd(ymm0, ymm7, ymm7) vmulpd(ymm0, ymm8, ymm8) vmulpd(ymm0, ymm9, ymm9) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; lea(mem(rcx, rdi, 2), rdx) // load address of c + 2*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORED) // jump to column storage case label(.DROWSTORED) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm4) vmovupd(ymm4, mem(rcx, 0*32)) vfmadd231pd(mem(rcx, 1*32), ymm3, ymm5) vmovupd(ymm5, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm6) vmovupd(ymm6, mem(rcx, 0*32)) vfmadd231pd(mem(rcx, 1*32), ymm3, ymm7) vmovupd(ymm7, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm8) vmovupd(ymm8, mem(rcx, 0*32)) vfmadd231pd(mem(rcx, 1*32), ymm3, ymm9) vmovupd(ymm9, mem(rcx, 1*32)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORED) // begin I/O on columns 0-3 vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vunpcklpd(ymm10, ymm8, ymm2) vunpckhpd(ymm10, ymm8, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vperm2f128(imm(0x31), ymm2, ymm0, ymm8) vperm2f128(imm(0x31), ymm3, ymm1, ymm10) vextractf128(imm(0x1), ymm4, xmm12) vextractf128(imm(0x1), ymm6, xmm13) vextractf128(imm(0x1), ymm8, xmm14) vextractf128(imm(0x1), ymm10, xmm15) vbroadcastsd(mem(rbx), ymm3) vfmadd231pd(mem(rcx ), xmm3, xmm4) vfmadd231pd(mem(rcx, rsi, 1), xmm3, xmm6) vfmadd231pd(mem(rcx, rsi, 2), xmm3, xmm8) vfmadd231pd(mem(rcx, rax, 1), xmm3, xmm10) vmovupd(xmm4, mem(rcx )) vmovupd(xmm6, mem(rcx, rsi, 1)) vmovupd(xmm8, mem(rcx, rsi, 2)) vmovupd(xmm10, mem(rcx, rax, 1)) lea(mem(rcx, rsi, 4), rcx) vfmadd231sd(mem(rdx ), xmm3, xmm12) vfmadd231sd(mem(rdx, rsi, 1), xmm3, xmm13) vfmadd231sd(mem(rdx, rsi, 2), xmm3, xmm14) vfmadd231sd(mem(rdx, rax, 1), xmm3, xmm15) vmovsd(xmm12, mem(rdx )) vmovsd(xmm13, mem(rdx, rsi, 1)) vmovsd(xmm14, mem(rdx, rsi, 2)) vmovsd(xmm15, mem(rdx, rax, 1)) lea(mem(rdx, rsi, 4), rdx) // begin I/O on columns 4-7 vunpcklpd(ymm7, ymm5, ymm0) vunpckhpd(ymm7, ymm5, ymm1) vunpcklpd(ymm11, ymm9, ymm2) vunpckhpd(ymm11, ymm9, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm5) vinsertf128(imm(0x1), xmm3, ymm1, ymm7) vperm2f128(imm(0x31), ymm2, ymm0, ymm9) vperm2f128(imm(0x31), ymm3, ymm1, ymm11) vextractf128(imm(0x1), ymm5, xmm12) vextractf128(imm(0x1), ymm7, xmm13) vextractf128(imm(0x1), ymm9, xmm14) vextractf128(imm(0x1), ymm11, xmm15) vbroadcastsd(mem(rbx), ymm3) vfmadd231pd(mem(rcx ), xmm3, xmm5) vfmadd231pd(mem(rcx, rsi, 1), xmm3, xmm7) vfmadd231pd(mem(rcx, rsi, 2), xmm3, xmm9) vfmadd231pd(mem(rcx, rax, 1), xmm3, xmm11) vmovupd(xmm5, mem(rcx )) vmovupd(xmm7, mem(rcx, rsi, 1)) vmovupd(xmm9, mem(rcx, rsi, 2)) vmovupd(xmm11, mem(rcx, rax, 1)) //lea(mem(rcx, rsi, 4), rcx) vfmadd231sd(mem(rdx ), xmm3, xmm12) vfmadd231sd(mem(rdx, rsi, 1), xmm3, xmm13) vfmadd231sd(mem(rdx, rsi, 2), xmm3, xmm14) vfmadd231sd(mem(rdx, rax, 1), xmm3, xmm15) vmovsd(xmm12, mem(rdx )) vmovsd(xmm13, mem(rdx, rsi, 1)) vmovsd(xmm14, mem(rdx, rsi, 2)) vmovsd(xmm15, mem(rdx, rax, 1)) //lea(mem(rdx, rsi, 4), rdx) jmp(.DDONE) // jump to end. label(.DBETAZERO) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORBZ) // jump to column storage case label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx, 0*32)) vmovupd(ymm5, mem(rcx, 1*32)) add(rdi, rcx) vmovupd(ymm6, mem(rcx, 0*32)) vmovupd(ymm7, mem(rcx, 1*32)) add(rdi, rcx) vmovupd(ymm8, mem(rcx, 0*32)) vmovupd(ymm9, mem(rcx, 1*32)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORBZ) // begin I/O on columns 0-3 vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vunpcklpd(ymm10, ymm8, ymm2) vunpckhpd(ymm10, ymm8, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vperm2f128(imm(0x31), ymm2, ymm0, ymm8) vperm2f128(imm(0x31), ymm3, ymm1, ymm10) vextractf128(imm(0x1), ymm4, xmm12) vextractf128(imm(0x1), ymm6, xmm13) vextractf128(imm(0x1), ymm8, xmm14) vextractf128(imm(0x1), ymm10, xmm15) vmovupd(xmm4, mem(rcx )) vmovupd(xmm6, mem(rcx, rsi, 1)) vmovupd(xmm8, mem(rcx, rsi, 2)) vmovupd(xmm10, mem(rcx, rax, 1)) lea(mem(rcx, rsi, 4), rcx) vmovsd(xmm12, mem(rdx )) vmovsd(xmm13, mem(rdx, rsi, 1)) vmovsd(xmm14, mem(rdx, rsi, 2)) vmovsd(xmm15, mem(rdx, rax, 1)) lea(mem(rdx, rsi, 4), rdx) // begin I/O on columns 4-7 vunpcklpd(ymm7, ymm5, ymm0) vunpckhpd(ymm7, ymm5, ymm1) vunpcklpd(ymm11, ymm9, ymm2) vunpckhpd(ymm11, ymm9, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm5) vinsertf128(imm(0x1), xmm3, ymm1, ymm7) vperm2f128(imm(0x31), ymm2, ymm0, ymm9) vperm2f128(imm(0x31), ymm3, ymm1, ymm11) vextractf128(imm(0x1), ymm5, xmm12) vextractf128(imm(0x1), ymm7, xmm13) vextractf128(imm(0x1), ymm9, xmm14) vextractf128(imm(0x1), ymm11, xmm15) vmovupd(xmm5, mem(rcx )) vmovupd(xmm7, mem(rcx, rsi, 1)) vmovupd(xmm9, mem(rcx, rsi, 2)) vmovupd(xmm11, mem(rcx, rax, 1)) //lea(mem(rcx, rsi, 4), rcx) vmovsd(xmm12, mem(rdx )) vmovsd(xmm13, mem(rdx, rsi, 1)) vmovsd(xmm14, mem(rdx, rsi, 2)) vmovsd(xmm15, mem(rdx, rax, 1)) //lea(mem(rdx, rsi, 4), rdx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi","rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rv_haswell_asm_2x8 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) //lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLPFETCH) // jump to column storage case label(.DROWPFETCH) // row-stored prefetching on c //lea(mem(rcx, rdi, 2), rdx) // //lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 7*8)) // prefetch c + 1*rs_c jmp(.DPOSTPFETCH) // jump to end of prefetching c label(.DCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 8), rsi) // cs_c *= sizeof(double) lea(mem(rcx, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; prefetch(0, mem(rcx, 1*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 1*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 1*8)) // prefetch c + 2*cs_c prefetch(0, mem(rdx, 1*8)) // prefetch c + 3*cs_c prefetch(0, mem(rdx, rsi, 1, 1*8)) // prefetch c + 4*cs_c prefetch(0, mem(rdx, rsi, 2, 1*8)) // prefetch c + 5*cs_c lea(mem(rdx, rsi, 2), rdx) // rdx = c + 5*cs_c; prefetch(0, mem(rdx, rsi, 1, 1*8)) // prefetch c + 6*cs_c prefetch(0, mem(rdx, rsi, 2, 1*8)) // prefetch c + 7*cs_c label(.DPOSTPFETCH) // done prefetching c #if 1 lea(mem(rax, r9, 8), rdx) // lea(mem(rdx, r9, 8), rdx) // rdx = a + 16*cs_a; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.DLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(rdx, 4*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, r9, 1, 4*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(rdx, r9, 2, 4*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) // ---------------------------------- iteration 3 #if 1 lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) dec(rsi) // i -= 1; jne(.DLOOPKITER) // iterate again if i != 0. label(.DCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.DLOOPKLEFT) // EDGE LOOP #if 0 prefetch(0, mem(rdx, 5*8)) add(r9, rdx) #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) dec(rsi) // i -= 1; jne(.DLOOPKLEFT) // iterate again if i != 0. label(.DPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(ymm0, ymm5, ymm5) vmulpd(ymm0, ymm6, ymm6) vmulpd(ymm0, ymm7, ymm7) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; //lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORED) // jump to column storage case label(.DROWSTORED) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm4) vmovupd(ymm4, mem(rcx, 0*32)) vfmadd231pd(mem(rcx, 1*32), ymm3, ymm5) vmovupd(ymm5, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm6) vmovupd(ymm6, mem(rcx, 0*32)) vfmadd231pd(mem(rcx, 1*32), ymm3, ymm7) vmovupd(ymm7, mem(rcx, 1*32)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORED) // begin I/O on columns 0-3 vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vextractf128(imm(0x1), ymm1, xmm4) vfmadd231pd(mem(rcx ), xmm3, xmm0) vfmadd231pd(mem(rcx, rsi, 1), xmm3, xmm1) vfmadd231pd(mem(rcx, rsi, 2), xmm3, xmm2) vfmadd231pd(mem(rcx, rax, 1), xmm3, xmm4) vmovupd(xmm0, mem(rcx )) vmovupd(xmm1, mem(rcx, rsi, 1)) vmovupd(xmm2, mem(rcx, rsi, 2)) vmovupd(xmm4, mem(rcx, rax, 1)) lea(mem(rcx, rsi, 4), rcx) // begin I/O on columns 4-7 vunpcklpd(ymm7, ymm5, ymm0) vunpckhpd(ymm7, ymm5, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vextractf128(imm(0x1), ymm1, xmm4) vfmadd231pd(mem(rcx ), xmm3, xmm0) vfmadd231pd(mem(rcx, rsi, 1), xmm3, xmm1) vfmadd231pd(mem(rcx, rsi, 2), xmm3, xmm2) vfmadd231pd(mem(rcx, rax, 1), xmm3, xmm4) vmovupd(xmm0, mem(rcx )) vmovupd(xmm1, mem(rcx, rsi, 1)) vmovupd(xmm2, mem(rcx, rsi, 2)) vmovupd(xmm4, mem(rcx, rax, 1)) //lea(mem(rcx, rsi, 4), rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORBZ) // jump to column storage case label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx, 0*32)) vmovupd(ymm5, mem(rcx, 1*32)) add(rdi, rcx) vmovupd(ymm6, mem(rcx, 0*32)) vmovupd(ymm7, mem(rcx, 1*32)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORBZ) // begin I/O on columns 0-3 vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vextractf128(imm(0x1), ymm1, xmm4) vmovupd(xmm0, mem(rcx )) vmovupd(xmm1, mem(rcx, rsi, 1)) vmovupd(xmm2, mem(rcx, rsi, 2)) vmovupd(xmm4, mem(rcx, rax, 1)) lea(mem(rcx, rsi, 4), rcx) // begin I/O on columns 4-7 vunpcklpd(ymm7, ymm5, ymm0) vunpckhpd(ymm7, ymm5, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vextractf128(imm(0x1), ymm1, xmm4) vmovupd(xmm0, mem(rcx )) vmovupd(xmm1, mem(rcx, rsi, 1)) vmovupd(xmm2, mem(rcx, rsi, 2)) vmovupd(xmm4, mem(rcx, rax, 1)) //lea(mem(rcx, rsi, 4), rcx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi","rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rv_haswell_asm_1x8 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) //lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLPFETCH) // jump to column storage case label(.DROWPFETCH) // row-stored prefetching on c //lea(mem(rcx, rdi, 2), rdx) // //lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c jmp(.DPOSTPFETCH) // jump to end of prefetching c label(.DCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 8), rsi) // cs_c *= sizeof(double) lea(mem(rcx, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; prefetch(0, mem(rcx, 0*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 0*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 0*8)) // prefetch c + 2*cs_c prefetch(0, mem(rdx, 0*8)) // prefetch c + 3*cs_c prefetch(0, mem(rdx, rsi, 1, 0*8)) // prefetch c + 4*cs_c prefetch(0, mem(rdx, rsi, 2, 0*8)) // prefetch c + 5*cs_c lea(mem(rdx, rsi, 2), rdx) // rdx = c + 5*cs_c; prefetch(0, mem(rdx, rsi, 1, 0*8)) // prefetch c + 6*cs_c prefetch(0, mem(rdx, rsi, 2, 0*8)) // prefetch c + 7*cs_c label(.DPOSTPFETCH) // done prefetching c #if 1 lea(mem(rax, r9, 8), rdx) // lea(mem(rdx, r9, 8), rdx) // rdx = a + 16*cs_a; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.DLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(rdx, 4*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, r9, 1, 4*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(rdx, r9, 2, 4*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) // ---------------------------------- iteration 3 #if 1 lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) dec(rsi) // i -= 1; jne(.DLOOPKITER) // iterate again if i != 0. label(.DCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.DLOOPKLEFT) // EDGE LOOP #if 0 prefetch(0, mem(rdx, 5*8)) add(r9, rdx) #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) dec(rsi) // i -= 1; jne(.DLOOPKLEFT) // iterate again if i != 0. label(.DPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(ymm0, ymm5, ymm5) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; //lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORED) // jump to column storage case label(.DROWSTORED) vfmadd231pd(mem(rcx, 0*32), ymm3, ymm4) vmovupd(ymm4, mem(rcx, 0*32)) vfmadd231pd(mem(rcx, 1*32), ymm3, ymm5) vmovupd(ymm5, mem(rcx, 1*32)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORED) // begin I/O on columns 0-3 vmovlpd(mem(rcx ), xmm0, xmm0) vmovhpd(mem(rcx, rsi, 1), xmm0, xmm0) vmovlpd(mem(rcx, rsi, 2), xmm1, xmm1) vmovhpd(mem(rcx, rax, 1), xmm1, xmm1) vperm2f128(imm(0x20), ymm1, ymm0, ymm0) vfmadd213pd(ymm4, ymm3, ymm0) vextractf128(imm(1), ymm0, xmm1) vmovlpd(xmm0, mem(rcx )) vmovhpd(xmm0, mem(rcx, rsi, 1)) vmovlpd(xmm1, mem(rcx, rsi, 2)) vmovhpd(xmm1, mem(rcx, rax, 1)) lea(mem(rcx, rsi, 4), rcx) // begin I/O on columns 4-7 vmovlpd(mem(rcx ), xmm0, xmm0) vmovhpd(mem(rcx, rsi, 1), xmm0, xmm0) vmovlpd(mem(rcx, rsi, 2), xmm1, xmm1) vmovhpd(mem(rcx, rax, 1), xmm1, xmm1) vperm2f128(imm(0x20), ymm1, ymm0, ymm0) vfmadd213pd(ymm5, ymm3, ymm0) vextractf128(imm(1), ymm0, xmm1) vmovlpd(xmm0, mem(rcx )) vmovhpd(xmm0, mem(rcx, rsi, 1)) vmovlpd(xmm1, mem(rcx, rsi, 2)) vmovhpd(xmm1, mem(rcx, rax, 1)) //lea(mem(rcx, rsi, 4), rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORBZ) // jump to column storage case label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx, 0*32)) vmovupd(ymm5, mem(rcx, 1*32)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORBZ) // begin I/O on columns 0-3 vmovupd(ymm4, ymm0) vextractf128(imm(1), ymm0, xmm1) vmovlpd(xmm0, mem(rcx )) vmovhpd(xmm0, mem(rcx, rsi, 1)) vmovlpd(xmm1, mem(rcx, rsi, 2)) vmovhpd(xmm1, mem(rcx, rax, 1)) lea(mem(rcx, rsi, 4), rcx) // begin I/O on columns 4-7 vmovupd(ymm5, ymm0) vextractf128(imm(1), ymm0, xmm1) vmovlpd(xmm0, mem(rcx )) vmovhpd(xmm0, mem(rcx, rsi, 1)) vmovlpd(xmm1, mem(rcx, rsi, 2)) vmovhpd(xmm1, mem(rcx, rax, 1)) //lea(mem(rcx, rsi, 4), rcx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi","rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } blis-0.9.0/kernels/haswell/3/sup/d6x8/old/000077500000000000000000000000001422157504600201015ustar00rootroot00000000000000blis-0.9.0/kernels/haswell/3/sup/d6x8/old/bli_gemmsup_rd_haswell_asm_d6x8.c000066400000000000000000003606271422157504600265030ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define BLIS_ASM_SYNTAX_ATT #include "bli_x86_asm_macros.h" /* rrc: -------- ------ | | | | | | | | -------- ------ | | | | | | | | -------- += ------ ... | | | | | | | | -------- ------ | | | | | | | | -------- ------ : -------- ------ : Assumptions: - C is row-stored and B is column-stored; - A is row-stored; - m0 and n0 are at most MR and NR, respectively. Therefore, this (r)ow-preferential microkernel is well-suited for a dot-product-based accumulation that performs vector loads from both A and B. */ // Prototype reference microkernels. GEMMSUP_KER_PROT( double, d, gemmsup_r_haswell_ref ) #if 0 // Define parameters and variables for edge case kernel map. #define NUM_MR 4 #define NUM_NR 4 #define FUNCPTR_T dgemmsup_ker_ft static dim_t mrs[NUM_MR] = { 6, 3, 2, 1 }; static dim_t nrs[NUM_NR] = { 8, 4, 2, 1 }; static FUNCPTR_T kmap[NUM_MR][NUM_NR] = { /* 8 4 2 1 */ /* 6 */ { bli_dgemmsup_rd_haswell_asm_6x8m, bli_dgemmsup_rd_haswell_asm_6x4m, bli_dgemmsup_rd_haswell_asm_6x2m, bli_dgemmsup_r_haswell_ref_6x1 }, /* 3 */ { bli_dgemmsup_rd_haswell_asm_3x8m, bli_dgemmsup_rd_haswell_asm_3x4m, bli_dgemmsup_rd_haswell_asm_3x2m, bli_dgemmsup_r_haswell_ref_3x1 }, /* 2 */ { bli_dgemmsup_rd_haswell_asm_2x8m, bli_dgemmsup_rd_haswell_asm_2x4m, bli_dgemmsup_rd_haswell_asm_2x2m, bli_dgemmsup_r_haswell_ref_2x1 }, /* 1 */ { bli_dgemmsup_rd_haswell_asm_1x8m, bli_dgemmsup_rd_haswell_asm_1x4m, bli_dgemmsup_rd_haswell_asm_1x2m, bli_dgemmsup_r_haswell_ref_1x1 } }; #endif void bli_dgemmsup_rd_haswell_asm_6x8 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { uint64_t n_left = n0 % 8; // First check whether this is a edge case in the n dimension. If so, // dispatch other 6x?m kernels, as needed. if ( n_left ) { double* restrict cij = c; double* restrict bj = b; double* restrict ai = a; if ( 4 <= n_left ) { const dim_t nr_cur = 4; bli_dgemmsup_rd_haswell_asm_6x4 ( conja, conjb, m0, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 2 <= n_left ) { const dim_t nr_cur = 2; bli_dgemmsup_rd_haswell_asm_6x2 ( conja, conjb, m0, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 1 == n_left ) { #if 0 const dim_t nr_cur = 1; bli_dgemmsup_r_haswell_ref ( conja, conjb, m0, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); #else bli_dgemv_ex ( BLIS_NO_TRANSPOSE, conjb, m0, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, beta, cij, rs_c0, cntx, NULL ); #endif } return; } //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t m_iter = m0 / 3; uint64_t m_left = m0 % 3; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; if ( m_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. //mov(var(a), r14) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rdx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b lea(mem(r8, r8, 2), r10) // r10 = 3*rs_a //mov(var(c), r12) // load address of c //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) // r12 = rcx = c // r14 = rax = a // rdx = rbx = b // r9 = m dim index ii // r15 = n dim index jj mov(imm(0), r15) // jj = 0; label(.DLOOP3X4J) // LOOP OVER jj = [ 0 1 ... ] mov(var(a), r14) // load address of a mov(var(c), r12) // load address of c lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(imm(1*8), rsi) // rsi *= cs_c*sizeof(double) = 1*8 lea(mem(r12, rsi, 1), r12) // r12 = c + 4*jj*cs_c; lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(r11, rsi) // rsi *= cs_b; lea(mem(rdx, rsi, 1), rdx) // rbx = b + 4*jj*cs_b; mov(var(m_iter), r9) // ii = m_iter; label(.DLOOP3X4I) // LOOP OVER ii = [ m_iter ... 1 0 ] #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm5, ymm5, ymm5) vxorpd(ymm6, ymm6, ymm6) vxorpd(ymm7, ymm7, ymm7) vxorpd(ymm8, ymm8, ymm8) vxorpd(ymm9, ymm9, ymm9) vxorpd(ymm10, ymm10, ymm10) vxorpd(ymm11, ymm11, ymm11) vxorpd(ymm12, ymm12, ymm12) vxorpd(ymm13, ymm13, ymm13) vxorpd(ymm14, ymm14, ymm14) vxorpd(ymm15, ymm15, ymm15) #endif lea(mem(r12), rcx) // rcx = c_iijj; lea(mem(r14), rax) // rax = a_ii; lea(mem(rdx), rbx) // rbx = b_jj; #if 1 mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 3*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 3*8)) // prefetch c + 2*rs_c #endif lea(mem(r8, r8, 4), rdi) // rdi = 5*rs_a mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rdi, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 1 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 2 #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rdi, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 3 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rdi, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rax ), xmm0) vmovsd(mem(rax, r8, 1), xmm1) vmovsd(mem(rax, r8, 2), xmm2) add(imm(1*8), rax) // a += 1*cs_a = 1*8; vmovsd(mem(rbx ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovsd(mem(rbx, r11, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovsd(mem(rbx, r11, 2), xmm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovsd(mem(rbx, r13, 1), xmm3) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 // ymm5 ymm8 ymm11 ymm14 // ymm6 ymm9 ymm12 ymm15 vhaddpd( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm7) vhaddpd( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) // xmm2[0] = sum(ymm10); xmm2[1] = sum(ymm13) vperm2f128(imm(0x20), ymm2, ymm0, ymm4 ) vhaddpd( ymm8, ymm5, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm14, ymm11, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm5 ) vhaddpd( ymm9, ymm6, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm15, ymm12, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm6 ) // ymm4 = sum(ymm4) sum(ymm7) sum(ymm10) sum(ymm13) // ymm5 = sum(ymm5) sum(ymm8) sum(ymm11) sum(ymm14) // ymm6 = sum(ymm6) sum(ymm9) sum(ymm12) sum(ymm15) mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(ymm0, ymm5, ymm5) vmulpd(ymm0, ymm6, ymm6) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), ymm3, ymm4) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm5) vmovupd(ymm5, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm6) vmovupd(ymm6, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vmovupd(ymm5, mem(rcx)) add(rdi, rcx) vmovupd(ymm6, mem(rcx)) //add(rdi, rcx) label(.DDONE) lea(mem(r12, rdi, 2), r12) // lea(mem(r12, rdi, 1), r12) // c_ii = r12 += 3*rs_c lea(mem(r14, r8, 2), r14) // lea(mem(r14, r8, 1), r14) // a_ii = r14 += 3*rs_a dec(r9) // ii -= 1; jne(.DLOOP3X4I) // iterate again if ii != 0. add(imm(4), r15) // jj += 4; cmp(imm(4), r15) // compare jj to 4 jle(.DLOOP3X4J) // if jj <= 4, jump to beginning // of jj loop; otherwise, loop ends. label(.DRETURN) end_asm( : // output operands (none) : // input operands [m_iter] "m" (m_iter), [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the m dimension, if they exist. if ( m_left ) { const dim_t nr_cur = 8; const dim_t i_edge = m0 - ( dim_t )m_left; double* restrict cij = c + i_edge*rs_c; double* restrict bj = b; double* restrict ai = a + i_edge*rs_a; if ( 2 == m_left ) { const dim_t mr_cur = 2; bli_dgemmsup_rd_haswell_asm_2x8 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); //cij += mr_cur*rs_c0; ai += mr_cur*rs_a0; m_left -= mr_cur; } if ( 1 == m_left ) { const dim_t mr_cur = 1; bli_dgemmsup_rd_haswell_asm_1x8 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); } } } void bli_dgemmsup_rd_haswell_asm_2x8 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), r14) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rdx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b //lea(mem(r8, r8, 2), r10) // r10 = 3*rs_a mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) // r12 = rcx = c // r14 = rax = a // rdx = rbx = b // r9 = unused // r15 = n dim index jj // r10 = unused mov(imm(0), r15) // jj = 0; label(.DLOOP3X4J) // LOOP OVER jj = [ 0 1 ... ] #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm5, ymm5, ymm5) vxorpd(ymm7, ymm7, ymm7) vxorpd(ymm8, ymm8, ymm8) vxorpd(ymm10, ymm10, ymm10) vxorpd(ymm11, ymm11, ymm11) vxorpd(ymm13, ymm13, ymm13) vxorpd(ymm14, ymm14, ymm14) #endif lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(imm(1*8), rsi) // rsi *= cs_c*sizeof(double) = 1*8 lea(mem(r12, rsi, 1), rcx) // rcx = c + 4*jj*cs_c; lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(r11, rsi) // rsi *= cs_b; lea(mem(rdx, rsi, 1), rbx) // rbx = b + 4*jj*cs_b; lea(mem(r14), rax) // rax = a; #if 0 prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 7*8)) // prefetch c + 1*rs_c #else prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 3*8)) // prefetch c + 1*rs_c #endif mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) // ---------------------------------- iteration 1 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) // ---------------------------------- iteration 2 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) // ---------------------------------- iteration 3 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rax ), xmm0) vmovsd(mem(rax, r8, 1), xmm1) add(imm(1*8), rax) // a += 1*cs_a = 1*8; vmovsd(mem(rbx ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovsd(mem(rbx, r11, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovsd(mem(rbx, r11, 2), xmm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovsd(mem(rbx, r13, 1), xmm3) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 // ymm5 ymm8 ymm11 ymm14 vhaddpd( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm7) vhaddpd( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) // xmm2[0] = sum(ymm10); xmm2[1] = sum(ymm13) vperm2f128(imm(0x20), ymm2, ymm0, ymm4 ) vhaddpd( ymm8, ymm5, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm14, ymm11, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm5 ) // ymm4 = sum(ymm4) sum(ymm7) sum(ymm10) sum(ymm13) // ymm5 = sum(ymm5) sum(ymm8) sum(ymm11) sum(ymm14) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(ymm0, ymm5, ymm5) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), ymm3, ymm4) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm5) vmovupd(ymm5, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vmovupd(ymm5, mem(rcx)) //add(rdi, rcx) label(.DDONE) add(imm(4), r15) // jj += 4; cmp(imm(4), r15) // compare jj to 4 jle(.DLOOP3X4J) // if jj <= 4, jump to beginning // of jj loop; otherwise, loop ends. label(.DRETURN) end_asm( : // output operands (none) : // input operands [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rd_haswell_asm_1x8 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), r14) // load address of a. //mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a //lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rdx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b mov(var(c), r12) // load address of c //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) // r12 = rcx = c // r14 = rax = a // rdx = rbx = b // r9 = m dim index ii // r15 = n dim index jj mov(imm(0), r15) // jj = 0; label(.DLOOP3X4J) // LOOP OVER jj = [ 0 1 ... ] #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm7, ymm7, ymm7) vxorpd(ymm10, ymm10, ymm10) vxorpd(ymm13, ymm13, ymm13) #endif lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(imm(1*8), rsi) // rsi *= cs_c*sizeof(double) = 1*8 lea(mem(r12, rsi, 1), rcx) // rcx = c + 4*jj*cs_c; lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(r11, rsi) // rsi *= cs_b; lea(mem(rdx, rsi, 1), rbx) // rbx = b + 4*jj*cs_b; lea(mem(r14), rax) // rax = a; #if 0 prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c #else prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c #endif mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rax ), ymm0) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) // ---------------------------------- iteration 1 vmovupd(mem(rax ), ymm0) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) // ---------------------------------- iteration 2 vmovupd(mem(rax ), ymm0) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) // ---------------------------------- iteration 3 vmovupd(mem(rax ), ymm0) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) vmovupd(mem(rax ), ymm0) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rax ), xmm0) add(imm(1*8), rax) // a += 1*cs_a = 1*8; vmovsd(mem(rbx ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovsd(mem(rbx, r11, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovsd(mem(rbx, r11, 2), xmm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovsd(mem(rbx, r13, 1), xmm3) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vfmadd231pd(ymm0, ymm3, ymm13) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 vhaddpd( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm7) vhaddpd( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) // xmm2[0] = sum(ymm10); xmm2[1] = sum(ymm13) vperm2f128(imm(0x20), ymm2, ymm0, ymm4 ) // ymm4 = sum(ymm4) sum(ymm7) sum(ymm10) sum(ymm13) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), ymm3, ymm4) vmovupd(ymm4, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx)) //add(rdi, rcx) label(.DDONE) add(imm(4), r15) // jj += 4; cmp(imm(4), r15) // compare jj to 4 jle(.DLOOP3X4J) // if jj <= 4, jump to beginning // of jj loop; otherwise, loop ends. label(.DRETURN) end_asm( : // output operands (none) : // input operands [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rd_haswell_asm_6x4 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t m_iter = m0 / 3; uint64_t m_left = m0 % 3; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; if ( m_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), r14) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rdx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b lea(mem(r8, r8, 2), r10) // r10 = 3*rs_a mov(var(c), r12) // load address of c //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) // r12 = rcx = c // r14 = rax = a // rdx = rbx = b // r9 = m dim index ii // r15 = n dim index jj mov(var(m_iter), r9) // ii = m_iter; label(.DLOOP3X4I) // LOOP OVER ii = [ m_iter .. 1 0 ] #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm5, ymm5, ymm5) vxorpd(ymm6, ymm6, ymm6) vxorpd(ymm7, ymm7, ymm7) vxorpd(ymm8, ymm8, ymm8) vxorpd(ymm9, ymm9, ymm9) vxorpd(ymm10, ymm10, ymm10) vxorpd(ymm11, ymm11, ymm11) vxorpd(ymm12, ymm12, ymm12) vxorpd(ymm13, ymm13, ymm13) vxorpd(ymm14, ymm14, ymm14) vxorpd(ymm15, ymm15, ymm15) #endif lea(mem(r12), rcx) // rcx = c + 3*ii*rs_c; lea(mem(r14), rax) // rax = a + 3*ii*rs_a; lea(mem(rdx), rbx) // rbx = b; #if 1 mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 3*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 3*8)) // prefetch c + 2*rs_c #endif lea(mem(r8, r8, 4), rdi) // rdi = 5*rs_a mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rdi, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 1 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 2 #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rdi, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 3 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rax ), xmm0) vmovsd(mem(rax, r8, 1), xmm1) vmovsd(mem(rax, r8, 2), xmm2) add(imm(1*8), rax) // a += 1*cs_a = 1*8; vmovsd(mem(rbx ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovsd(mem(rbx, r11, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovsd(mem(rbx, r11, 2), xmm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovsd(mem(rbx, r13, 1), xmm3) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 // ymm5 ymm8 ymm11 ymm14 // ymm6 ymm9 ymm12 ymm15 vhaddpd( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm7) vhaddpd( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) // xmm2[0] = sum(ymm10); xmm2[1] = sum(ymm13) vperm2f128(imm(0x20), ymm2, ymm0, ymm4 ) vhaddpd( ymm8, ymm5, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm14, ymm11, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm5 ) vhaddpd( ymm9, ymm6, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm15, ymm12, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm6 ) // ymm4 = sum(ymm4) sum(ymm7) sum(ymm10) sum(ymm13) // ymm5 = sum(ymm5) sum(ymm8) sum(ymm11) sum(ymm14) // ymm6 = sum(ymm6) sum(ymm9) sum(ymm12) sum(ymm15) mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(ymm0, ymm5, ymm5) vmulpd(ymm0, ymm6, ymm6) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), ymm3, ymm4) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm5) vmovupd(ymm5, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm6) vmovupd(ymm6, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vmovupd(ymm5, mem(rcx)) add(rdi, rcx) vmovupd(ymm6, mem(rcx)) //add(rdi, rcx) label(.DDONE) lea(mem(r12, rdi, 2), r12) // lea(mem(r12, rdi, 1), r12) // c_ii = r12 += 3*rs_c lea(mem(r14, r8, 2), r14) // lea(mem(r14, r8, 1), r14) // a_ii = r14 += 3*rs_a dec(r9) // ii -= 1; jne(.DLOOP3X4I) // iterate again if ii != 0. label(.DRETURN) end_asm( : // output operands (none) : // input operands [m_iter] "m" (m_iter), [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the m dimension, if they exist. if ( m_left ) { const dim_t nr_cur = 4; const dim_t i_edge = m0 - ( dim_t )m_left; double* restrict cij = c + i_edge*rs_c; double* restrict bj = b; double* restrict ai = a + i_edge*rs_a; if ( 2 == m_left ) { const dim_t mr_cur = 2; bli_dgemmsup_rd_haswell_asm_2x4 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); //cij += mr_cur*rs_c0; ai += mr_cur*rs_a0; m_left -= mr_cur; } if ( 1 == m_left ) { const dim_t mr_cur = 1; bli_dgemmsup_rd_haswell_asm_1x4 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); } } } void bli_dgemmsup_rd_haswell_asm_2x4 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm5, ymm5, ymm5) vxorpd(ymm7, ymm7, ymm7) vxorpd(ymm8, ymm8, ymm8) vxorpd(ymm10, ymm10, ymm10) vxorpd(ymm11, ymm11, ymm11) vxorpd(ymm13, ymm13, ymm13) vxorpd(ymm14, ymm14, ymm14) #endif mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 3*8)) // prefetch c + 1*rs_c mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) // ---------------------------------- iteration 1 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) // ---------------------------------- iteration 2 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) // ---------------------------------- iteration 3 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rax ), xmm0) vmovsd(mem(rax, r8, 1), xmm1) add(imm(1*8), rax) // a += 1*cs_a = 1*8; vmovsd(mem(rbx ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovsd(mem(rbx, r11, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovsd(mem(rbx, r11, 2), xmm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovsd(mem(rbx, r13, 1), xmm3) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 // ymm5 ymm8 ymm11 ymm14 vhaddpd( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm7) vhaddpd( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) // xmm2[0] = sum(ymm10); xmm2[1] = sum(ymm13) vperm2f128(imm(0x20), ymm2, ymm0, ymm4 ) vhaddpd( ymm8, ymm5, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm14, ymm11, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm5 ) // ymm4 = sum(ymm4) sum(ymm7) sum(ymm10) sum(ymm13) // ymm5 = sum(ymm5) sum(ymm8) sum(ymm11) sum(ymm14) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(ymm0, ymm5, ymm5) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), ymm3, ymm4) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm5) vmovupd(ymm5, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vmovupd(ymm5, mem(rcx)) //add(rdi, rcx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rd_haswell_asm_1x4 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; /* rrc: -------- -- -- -- | | | | -------- -- -- -- ... | | | | -------- += -- -- -- | | | | -------- | | | | -------- : -------- : */ // ------------------------------------------------------------------------- begin_asm() #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm7, ymm7, ymm7) vxorpd(ymm10, ymm10, ymm10) vxorpd(ymm13, ymm13, ymm13) #endif mov(var(a), rax) // load address of a. //mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a //lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b mov(var(c), rcx) // load address of c //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rax ), ymm0) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) // ---------------------------------- iteration 1 vmovupd(mem(rax ), ymm0) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) // ---------------------------------- iteration 2 vmovupd(mem(rax ), ymm0) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) // ---------------------------------- iteration 3 vmovupd(mem(rax ), ymm0) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) vmovupd(mem(rax ), ymm0) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rax ), xmm0) add(imm(1*8), rax) // a += 1*cs_a = 1*8; vmovsd(mem(rbx ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovsd(mem(rbx, r11, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovsd(mem(rbx, r11, 2), xmm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovsd(mem(rbx, r13, 1), xmm3) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vfmadd231pd(ymm0, ymm3, ymm13) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 vhaddpd( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm7) vhaddpd( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) // xmm2[0] = sum(ymm10); xmm2[1] = sum(ymm13) vperm2f128(imm(0x20), ymm2, ymm0, ymm4 ) // ymm4 = sum(ymm4) sum(ymm7) sum(ymm10) sum(ymm13) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), ymm3, ymm4) vmovupd(ymm4, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx)) //add(rdi, rcx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rd_haswell_asm_6x2 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t m_iter = m0 / 6; uint64_t m_left = m0 % 6; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; if ( m_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), r14) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rdx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) //lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) // r12 = rcx = c // r14 = rax = a // rdx = rbx = b // r9 = m dim index ii mov(var(m_iter), r9) // ii = m_iter; label(.DLOOP3X4I) // LOOP OVER ii = [ m_iter ... 1 0 ] #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm5, ymm5, ymm5) vxorpd(ymm6, ymm6, ymm6) vxorpd(ymm7, ymm7, ymm7) vxorpd(ymm8, ymm8, ymm8) vxorpd(ymm9, ymm9, ymm9) vxorpd(ymm10, ymm10, ymm10) vxorpd(ymm11, ymm11, ymm11) vxorpd(ymm12, ymm12, ymm12) vxorpd(ymm13, ymm13, ymm13) vxorpd(ymm14, ymm14, ymm14) vxorpd(ymm15, ymm15, ymm15) #endif lea(mem(r12), rcx) // rcx = c + 6*ii*rs_c; lea(mem(r14), rax) // rax = a + 6*ii*rs_a; lea(mem(rdx), rbx) // rbx = b; lea(mem(rcx, rdi, 2), r10) // lea(mem(r10, rdi, 1), r10) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 1*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 1*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 1*8)) // prefetch c + 2*rs_c prefetch(0, mem(r10, 1*8)) // prefetch c + 3*rs_c prefetch(0, mem(r10, rdi, 1, 1*8)) // prefetch c + 4*rs_c prefetch(0, mem(r10, rdi, 2, 1*8)) // prefetch c + 5*rs_c mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovupd(mem(rax, r8, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) vmovupd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rax, r8, 4), ymm3) vfmadd231pd(ymm0, ymm3, ymm12) vfmadd231pd(ymm1, ymm3, ymm13) vmovupd(mem(rax, r15, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) // ---------------------------------- iteration 1 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovupd(mem(rax, r8, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) vmovupd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rax, r8, 4), ymm3) vfmadd231pd(ymm0, ymm3, ymm12) vfmadd231pd(ymm1, ymm3, ymm13) vmovupd(mem(rax, r15, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) // ---------------------------------- iteration 2 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovupd(mem(rax, r8, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) vmovupd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rax, r8, 4), ymm3) vfmadd231pd(ymm0, ymm3, ymm12) vfmadd231pd(ymm1, ymm3, ymm13) vmovupd(mem(rax, r15, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) // ---------------------------------- iteration 3 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovupd(mem(rax, r8, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) vmovupd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rax, r8, 4), ymm3) vfmadd231pd(ymm0, ymm3, ymm12) vfmadd231pd(ymm1, ymm3, ymm13) vmovupd(mem(rax, r15, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovupd(mem(rax, r8, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) vmovupd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rax, r8, 4), ymm3) vfmadd231pd(ymm0, ymm3, ymm12) vfmadd231pd(ymm1, ymm3, ymm13) vmovupd(mem(rax, r15, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rbx ), xmm0) vmovsd(mem(rbx, r11, 1), xmm1) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vmovsd(mem(rax ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovsd(mem(rax, r8, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovsd(mem(rax, r8, 2), xmm3) vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) vmovsd(mem(rax, r13, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovsd(mem(rax, r8, 4), xmm3) vfmadd231pd(ymm0, ymm3, ymm12) vfmadd231pd(ymm1, ymm3, ymm13) vmovsd(mem(rax, r15, 1), xmm3) add(imm(1*8), rax) // a += 1*cs_a = 1*8; vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm5 // ymm6 ymm7 // ymm8 ymm9 // ymm10 ymm11 // ymm12 ymm13 // ymm14 ymm15 vhaddpd( ymm5, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm4 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm5) vhaddpd( ymm7, ymm6, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm6 ) vhaddpd( ymm9, ymm8, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm8 ) vhaddpd( ymm11, ymm10, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm10 ) vhaddpd( ymm13, ymm12, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm12 ) vhaddpd( ymm15, ymm14, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm14 ) // xmm4 = sum(ymm4) sum(ymm5) // xmm6 = sum(ymm6) sum(ymm7) // xmm8 = sum(ymm8) sum(ymm9) // xmm10 = sum(ymm10) sum(ymm11) // xmm12 = sum(ymm12) sum(ymm13) // xmm14 = sum(ymm14) sum(ymm15) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(xmm0, xmm4, xmm4) // scale by alpha vmulpd(xmm0, xmm6, xmm6) vmulpd(xmm0, xmm8, xmm8) vmulpd(xmm0, xmm10, xmm10) vmulpd(xmm0, xmm12, xmm12) vmulpd(xmm0, xmm14, xmm14) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), xmm3, xmm4) vmovupd(xmm4, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), xmm3, xmm6) vmovupd(xmm6, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), xmm3, xmm8) vmovupd(xmm8, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), xmm3, xmm10) vmovupd(xmm10, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), xmm3, xmm12) vmovupd(xmm12, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), xmm3, xmm14) vmovupd(xmm14, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(xmm4, mem(rcx)) add(rdi, rcx) vmovupd(xmm6, mem(rcx)) add(rdi, rcx) vmovupd(xmm8, mem(rcx)) add(rdi, rcx) vmovupd(xmm10, mem(rcx)) add(rdi, rcx) vmovupd(xmm12, mem(rcx)) add(rdi, rcx) vmovupd(xmm14, mem(rcx)) //add(rdi, rcx) label(.DDONE) lea(mem(r12, rdi, 4), r12) // lea(mem(r12, rdi, 2), r12) // c_ii = r12 += 6*rs_c lea(mem(r14, r8, 4), r14) // lea(mem(r14, r8, 2), r14) // a_ii = r14 += 6*rs_a dec(r9) // ii -= 1; jne(.DLOOP3X4I) // iterate again if ii != 0. label(.DRETURN) end_asm( : // output operands (none) : // input operands [m_iter] "m" (m_iter), [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the m dimension, if they exist. if ( m_left ) { const dim_t nr_cur = 2; const dim_t i_edge = m0 - ( dim_t )m_left; double* restrict cij = c + i_edge*rs_c; double* restrict bj = b; double* restrict ai = a + i_edge*rs_a; if ( 3 <= m_left ) { const dim_t mr_cur = 3; bli_dgemmsup_rd_haswell_asm_3x2 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += mr_cur*rs_c0; ai += mr_cur*rs_a0; m_left -= mr_cur; } if ( 2 <= m_left ) { const dim_t mr_cur = 2; bli_dgemmsup_rd_haswell_asm_2x2 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += mr_cur*rs_c0; ai += mr_cur*rs_a0; m_left -= mr_cur; } if ( 1 == m_left ) { const dim_t mr_cur = 1; bli_dgemmsup_rd_haswell_asm_1x2 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); } } } void bli_dgemmsup_rd_haswell_asm_3x2 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; /* rrc: -------- -- -- -- | | -------- -- -- -- ... | | -------- += -- -- -- | | -------- -- -- -- | | -------- -- -- -- : -------- -- -- -- : */ // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) //lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b // initialize loop by pre-loading // a column of a. mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) //lea(mem(rcx, rdi, 2), rdx) // //lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 7*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 7*8)) // prefetch c + 2*rs_c mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovupd(mem(rax, r8, 2), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) // ---------------------------------- iteration 1 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovupd(mem(rax, r8, 2), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) // ---------------------------------- iteration 2 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovupd(mem(rax, r8, 2), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) // ---------------------------------- iteration 3 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovupd(mem(rax, r8, 2), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovupd(mem(rax, r8, 2), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rbx ), xmm0) vmovsd(mem(rbx, r11, 1), xmm1) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vmovsd(mem(rax ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovsd(mem(rax, r8, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovsd(mem(rax, r8, 2), xmm3) add(imm(1*8), rax) // a += 1*cs_a = 1*8; vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm5 // ymm6 ymm7 // ymm8 ymm9 vhaddpd( ymm5, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm4 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm5) vhaddpd( ymm7, ymm6, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm6 ) vhaddpd( ymm9, ymm8, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm8 ) // xmm4 = sum(ymm4) sum(ymm5) // xmm6 = sum(ymm6) sum(ymm7) // xmm8 = sum(ymm8) sum(ymm9) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(xmm0, xmm4, xmm4) // scale by alpha vmulpd(xmm0, xmm6, xmm6) vmulpd(xmm0, xmm8, xmm8) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), xmm3, xmm4) vmovupd(xmm4, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), xmm3, xmm6) vmovupd(xmm6, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), xmm3, xmm8) vmovupd(xmm8, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(xmm4, mem(rcx)) add(rdi, rcx) vmovupd(xmm6, mem(rcx)) add(rdi, rcx) vmovupd(xmm8, mem(rcx)) //add(rdi, rcx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rd_haswell_asm_2x2 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; /* rrc: -------- -- -- -- | | -------- -- -- -- ... | | -------- += -- -- -- | | -------- -- -- -- | | -------- -- -- -- : -------- -- -- -- : */ // ------------------------------------------------------------------------- begin_asm() #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm5, ymm5, ymm5) vxorpd(ymm6, ymm6, ymm6) vxorpd(ymm7, ymm7, ymm7) #endif mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) //lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b // initialize loop by pre-loading // a column of a. mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) //lea(mem(rcx, rdi, 2), rdx) // //lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 1*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 1*8)) // prefetch c + 1*rs_c mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) // ---------------------------------- iteration 1 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) // ---------------------------------- iteration 2 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) // ---------------------------------- iteration 3 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rbx ), xmm0) vmovsd(mem(rbx, r11, 1), xmm1) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vmovsd(mem(rax ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovsd(mem(rax, r8, 1), xmm3) add(imm(1*8), rax) // a += 1*cs_a = 1*8; vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm5 // ymm6 ymm7 vhaddpd( ymm5, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm4 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm5) vhaddpd( ymm7, ymm6, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm6 ) // xmm4 = sum(ymm4) sum(ymm5) // xmm6 = sum(ymm6) sum(ymm7) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(xmm0, xmm4, xmm4) // scale by alpha vmulpd(xmm0, xmm6, xmm6) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), xmm3, xmm4) vmovupd(xmm4, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), xmm3, xmm6) vmovupd(xmm6, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(xmm4, mem(rcx)) add(rdi, rcx) vmovupd(xmm6, mem(rcx)) //add(rdi, rcx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rd_haswell_asm_1x2 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; /* rrc: -------- -- -- -- | | -------- -- -- -- ... | | -------- += -- -- -- | | -------- -- -- -- | | -------- -- -- -- : -------- -- -- -- : */ // ------------------------------------------------------------------------- begin_asm() #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm5, ymm5, ymm5) #endif mov(var(a), rax) // load address of a. //mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a //lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) //lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b // initialize loop by pre-loading // a column of a. mov(var(c), rcx) // load address of c //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) //lea(mem(rcx, rdi, 2), rdx) // //lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 1*8)) // prefetch c + 0*rs_c mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) // ---------------------------------- iteration 1 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) // ---------------------------------- iteration 2 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) // ---------------------------------- iteration 3 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rbx ), xmm0) vmovsd(mem(rbx, r11, 1), xmm1) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vmovsd(mem(rax ), xmm3) add(imm(1*8), rax) // a += 1*cs_a = 1*8; vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm5 vhaddpd( ymm5, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm4 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm5) // xmm4 = sum(ymm4) sum(ymm5) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(xmm0, xmm4, xmm4) // scale by alpha //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), xmm3, xmm4) vmovupd(xmm4, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(xmm4, mem(rcx)) //add(rdi, rcx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } blis-0.9.0/kernels/haswell/3/sup/d6x8/old/bli_gemmsup_rv_haswell_asm_d6x8.c000066400000000000000000011227511422157504600265200ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define BLIS_ASM_SYNTAX_ATT #include "bli_x86_asm_macros.h" /* rrr: -------- ------ -------- -------- ------ -------- -------- += ------ ... -------- -------- ------ -------- -------- ------ : -------- ------ : rcr: -------- | | | | -------- -------- | | | | -------- -------- += | | | | ... -------- -------- | | | | -------- -------- | | | | : -------- | | | | : Assumptions: - B is row-stored; - A is row- or column-stored; - m0 and n0 are at most MR and NR, respectively. Therefore, this (r)ow-preferential kernel is well-suited for contiguous (v)ector loads on B and single-element broadcasts from A. NOTE: These kernels explicitly support column-oriented IO, implemented via an in-register transpose. And thus they also support the crr and ccr cases, though only crr is ever utilized (because ccr is handled by transposing the operation and executing rcr, which does not incur the cost of the in-register transpose). crr: | | | | | | | | ------ -------- | | | | | | | | ------ -------- | | | | | | | | += ------ ... -------- | | | | | | | | ------ -------- | | | | | | | | ------ : | | | | | | | | ------ : */ // Prototype reference microkernels. GEMMSUP_KER_PROT( double, d, gemmsup_r_haswell_ref ) // Define parameters and variables for edge case kernel map. #define NUM_MR 4 #define NUM_NR 4 #define FUNCPTR_T dgemmsup_ker_ft static dim_t mrs[NUM_MR] = { 6, 4, 2, 1 }; static dim_t nrs[NUM_NR] = { 8, 4, 2, 1 }; static FUNCPTR_T kmap[NUM_MR][NUM_NR] = { /* 8 4 2 1 */ /* 6 */ { bli_dgemmsup_rv_haswell_asm_6x8, bli_dgemmsup_rv_haswell_asm_6x4, bli_dgemmsup_rv_haswell_asm_6x2, bli_dgemmsup_r_haswell_ref_6x1 }, /* 4 */ { bli_dgemmsup_rv_haswell_asm_4x8, bli_dgemmsup_rv_haswell_asm_4x4, bli_dgemmsup_rv_haswell_asm_4x2, bli_dgemmsup_r_haswell_ref_4x1 }, /* 2 */ { bli_dgemmsup_rv_haswell_asm_2x8, bli_dgemmsup_rv_haswell_asm_2x4, bli_dgemmsup_rv_haswell_asm_2x2, bli_dgemmsup_r_haswell_ref_2x1 }, /* 1 */ { bli_dgemmsup_rv_haswell_asm_1x8, bli_dgemmsup_rv_haswell_asm_1x4, bli_dgemmsup_rv_haswell_asm_1x2, bli_dgemmsup_r_haswell_ref_1x1 }, }; void bli_dgemmsup_rv_haswell_asm_6x8 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { #if 0 bli_dgemmsup_r_haswell_ref ( conja, conjb, m0, n0, k0, alpha, a, rs_a0, cs_a0, b, rs_b0, cs_b0, beta, c, rs_c0, cs_c0, data, cntx ); return; #endif // Use a reference kernel if this is an edge case in the m or n // dimensions. if ( m0 < 6 || n0 < 8 ) { #if 0 bli_dgemmsup_r_haswell_ref ( conja, conjb, m0, n0, k0, alpha, a, rs_a0, cs_a0, b, rs_b0, cs_b0, beta, c, rs_c0, cs_c0, data, cntx ); return; #endif dim_t n_left = n0; double* restrict cj = c; double* restrict bj = b; // Iterate across columns (corresponding to elements of nrs) until // n_left is zero. for ( dim_t j = 0; n_left != 0; ++j ) { const dim_t nr_cur = nrs[ j ]; // Once we find the value of nrs that is less than (or equal to) // n_left, we use the kernels in that column. if ( nr_cur <= n_left ) { dim_t m_left = m0; double* restrict cij = cj; double* restrict ai = a; // Iterate down the current column (corresponding to elements // of mrs) until m_left is zero. for ( dim_t i = 0; m_left != 0; ++i ) { const dim_t mr_cur = mrs[ i ]; // Once we find the value of mrs that is less than (or equal // to) m_left, we select that kernel. if ( mr_cur <= m_left ) { FUNCPTR_T ker_fp = kmap[i][j]; //printf( "executing %d x %d sup kernel.\n", (int)mr_cur, (int)nr_cur ); // Call the kernel using current mrs and nrs values. ker_fp ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); // Advance C and A pointers by the mrs and nrs we just // used, and decrement m_left. cij += mr_cur*rs_c0; ai += mr_cur*rs_a0; m_left -= mr_cur; } } // Advance C and B pointers by the mrs and nrs we just used, and // decrement n_left. cj += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } } return; } //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) //lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) #if 0 lea(mem(rcx, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 7*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 7*8)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 7*8)) // prefetch c + 3*rs_c prefetch(0, mem(rdx, rdi, 1, 7*8)) // prefetch c + 4*rs_c prefetch(0, mem(rdx, rdi, 2, 7*8)) // prefetch c + 5*rs_c #else cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLPFETCH) // jump to column storage case label(.DROWPFETCH) // row-stored prefetching on c lea(mem(rcx, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 7*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 7*8)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 7*8)) // prefetch c + 3*rs_c prefetch(0, mem(rdx, rdi, 1, 7*8)) // prefetch c + 4*rs_c prefetch(0, mem(rdx, rdi, 2, 7*8)) // prefetch c + 5*rs_c jmp(.DPOSTPFETCH) // jump to end of prefetching c label(.DCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 8), rsi) // cs_c *= sizeof(double) lea(mem(rcx, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; prefetch(0, mem(rcx, 4*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 4*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 4*8)) // prefetch c + 2*cs_c prefetch(0, mem(rdx, 4*8)) // prefetch c + 3*cs_c prefetch(0, mem(rdx, rsi, 1, 4*8)) // prefetch c + 4*cs_c prefetch(0, mem(rdx, rsi, 2, 4*8)) // prefetch c + 5*cs_c lea(mem(rdx, rsi, 2), rdx) // rdx = c + 5*cs_c; prefetch(0, mem(rdx, rsi, 1, 4*8)) // prefetch c + 6*cs_c prefetch(0, mem(rdx, rsi, 2, 4*8)) // prefetch c + 7*cs_c label(.DPOSTPFETCH) // done prefetching c #endif #if 1 lea(mem(rax, r9, 8), rdx) // lea(mem(rdx, r9, 8), rdx) // rdx = a + 16*cs_a; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.DLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(rdx, 5*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, r8, 4), ymm2) vbroadcastsd(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, r9, 1, 5*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, r8, 4), ymm2) vbroadcastsd(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(rdx, r9, 2, 5*8)) #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, r8, 4), ymm2) vbroadcastsd(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) // ---------------------------------- iteration 3 #if 1 lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; #endif vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, r8, 4), ymm2) vbroadcastsd(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKITER) // iterate again if i != 0. label(.DCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.DLOOPKLEFT) // EDGE LOOP vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, r8, 4), ymm2) vbroadcastsd(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKLEFT) // iterate again if i != 0. label(.DPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(ymm0, ymm5, ymm5) vmulpd(ymm0, ymm6, ymm6) vmulpd(ymm0, ymm7, ymm7) vmulpd(ymm0, ymm8, ymm8) vmulpd(ymm0, ymm9, ymm9) vmulpd(ymm0, ymm10, ymm10) vmulpd(ymm0, ymm11, ymm11) vmulpd(ymm0, ymm12, ymm12) vmulpd(ymm0, ymm13, ymm13) vmulpd(ymm0, ymm14, ymm14) vmulpd(ymm0, ymm15, ymm15) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORED) // jump to column storage case label(.DROWSTORED) vfmadd231pd(mem(rcx), ymm3, ymm4) vmovupd(ymm4, mem(rcx)) vfmadd231pd(mem(rcx, rsi, 4), ymm3, ymm5) vmovupd(ymm5, mem(rcx, rsi, 4)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm6) vmovupd(ymm6, mem(rcx)) vfmadd231pd(mem(rcx, rsi, 4), ymm3, ymm7) vmovupd(ymm7, mem(rcx, rsi, 4)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm8) vmovupd(ymm8, mem(rcx)) vfmadd231pd(mem(rcx, rsi, 4), ymm3, ymm9) vmovupd(ymm9, mem(rcx, rsi, 4)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm10) vmovupd(ymm10, mem(rcx)) vfmadd231pd(mem(rcx, rsi, 4), ymm3, ymm11) vmovupd(ymm11, mem(rcx, rsi, 4)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm12) vmovupd(ymm12, mem(rcx)) vfmadd231pd(mem(rcx, rsi, 4), ymm3, ymm13) vmovupd(ymm13, mem(rcx, rsi, 4)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm14) vmovupd(ymm14, mem(rcx)) vfmadd231pd(mem(rcx, rsi, 4), ymm3, ymm15) vmovupd(ymm15, mem(rcx, rsi, 4)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORED) vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vunpcklpd(ymm10, ymm8, ymm2) vunpckhpd(ymm10, ymm8, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vperm2f128(imm(0x31), ymm2, ymm0, ymm8) vperm2f128(imm(0x31), ymm3, ymm1, ymm10) vbroadcastsd(mem(rbx), ymm3) vfmadd231pd(mem(rcx), ymm3, ymm4) vfmadd231pd(mem(rcx, rsi, 1), ymm3, ymm6) vfmadd231pd(mem(rcx, rsi, 2), ymm3, ymm8) vfmadd231pd(mem(rcx, rax, 1), ymm3, ymm10) vmovupd(ymm4, mem(rcx)) vmovupd(ymm6, mem(rcx, rsi, 1)) vmovupd(ymm8, mem(rcx, rsi, 2)) vmovupd(ymm10, mem(rcx, rax, 1)) lea(mem(rcx, rsi, 4), rcx) vunpcklpd(ymm14, ymm12, ymm0) vunpckhpd(ymm14, ymm12, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vextractf128(imm(0x1), ymm1, xmm4) vfmadd231pd(mem(rdx), xmm3, xmm0) vfmadd231pd(mem(rdx, rsi, 1), xmm3, xmm1) vfmadd231pd(mem(rdx, rsi, 2), xmm3, xmm2) vfmadd231pd(mem(rdx, rax, 1), xmm3, xmm4) vmovupd(xmm0, mem(rdx)) vmovupd(xmm1, mem(rdx, rsi, 1)) vmovupd(xmm2, mem(rdx, rsi, 2)) vmovupd(xmm4, mem(rdx, rax, 1)) lea(mem(rdx, rsi, 4), rdx) vunpcklpd(ymm7, ymm5, ymm0) vunpckhpd(ymm7, ymm5, ymm1) vunpcklpd(ymm11, ymm9, ymm2) vunpckhpd(ymm11, ymm9, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm5) vinsertf128(imm(0x1), xmm3, ymm1, ymm7) vperm2f128(imm(0x31), ymm2, ymm0, ymm9) vperm2f128(imm(0x31), ymm3, ymm1, ymm11) vbroadcastsd(mem(rbx), ymm3) vfmadd231pd(mem(rcx), ymm3, ymm5) vfmadd231pd(mem(rcx, rsi, 1), ymm3, ymm7) vfmadd231pd(mem(rcx, rsi, 2), ymm3, ymm9) vfmadd231pd(mem(rcx, rax, 1), ymm3, ymm11) vmovupd(ymm5, mem(rcx)) vmovupd(ymm7, mem(rcx, rsi, 1)) vmovupd(ymm9, mem(rcx, rsi, 2)) vmovupd(ymm11, mem(rcx, rax, 1)) //lea(mem(rcx, rsi, 4), rcx) vunpcklpd(ymm15, ymm13, ymm0) vunpckhpd(ymm15, ymm13, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vextractf128(imm(0x1), ymm1, xmm4) vfmadd231pd(mem(rdx), xmm3, xmm0) vfmadd231pd(mem(rdx, rsi, 1), xmm3, xmm1) vfmadd231pd(mem(rdx, rsi, 2), xmm3, xmm2) vfmadd231pd(mem(rdx, rax, 1), xmm3, xmm4) vmovupd(xmm0, mem(rdx)) vmovupd(xmm1, mem(rdx, rsi, 1)) vmovupd(xmm2, mem(rdx, rsi, 2)) vmovupd(xmm4, mem(rdx, rax, 1)) //lea(mem(rdx, rsi, 4), rdx) jmp(.DDONE) // jump to end. label(.DBETAZERO) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORBZ) // jump to column storage case label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx)) vmovupd(ymm5, mem(rcx, rsi, 4)) add(rdi, rcx) vmovupd(ymm6, mem(rcx)) vmovupd(ymm7, mem(rcx, rsi, 4)) add(rdi, rcx) vmovupd(ymm8, mem(rcx)) vmovupd(ymm9, mem(rcx, rsi, 4)) add(rdi, rcx) vmovupd(ymm10, mem(rcx)) vmovupd(ymm11, mem(rcx, rsi, 4)) add(rdi, rcx) vmovupd(ymm12, mem(rcx)) vmovupd(ymm13, mem(rcx, rsi, 4)) add(rdi, rcx) vmovupd(ymm14, mem(rcx)) vmovupd(ymm15, mem(rcx, rsi, 4)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORBZ) vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vunpcklpd(ymm10, ymm8, ymm2) vunpckhpd(ymm10, ymm8, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vperm2f128(imm(0x31), ymm2, ymm0, ymm8) vperm2f128(imm(0x31), ymm3, ymm1, ymm10) vmovupd(ymm4, mem(rcx)) vmovupd(ymm6, mem(rcx, rsi, 1)) vmovupd(ymm8, mem(rcx, rsi, 2)) vmovupd(ymm10, mem(rcx, rax, 1)) lea(mem(rcx, rsi, 4), rcx) vunpcklpd(ymm14, ymm12, ymm0) vunpckhpd(ymm14, ymm12, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vextractf128(imm(0x1), ymm1, xmm4) vmovupd(xmm0, mem(rdx)) vmovupd(xmm1, mem(rdx, rsi, 1)) vmovupd(xmm2, mem(rdx, rsi, 2)) vmovupd(xmm4, mem(rdx, rax, 1)) lea(mem(rdx, rsi, 4), rdx) vunpcklpd(ymm7, ymm5, ymm0) vunpckhpd(ymm7, ymm5, ymm1) vunpcklpd(ymm11, ymm9, ymm2) vunpckhpd(ymm11, ymm9, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm5) vinsertf128(imm(0x1), xmm3, ymm1, ymm7) vperm2f128(imm(0x31), ymm2, ymm0, ymm9) vperm2f128(imm(0x31), ymm3, ymm1, ymm11) vmovupd(ymm5, mem(rcx)) vmovupd(ymm7, mem(rcx, rsi, 1)) vmovupd(ymm9, mem(rcx, rsi, 2)) vmovupd(ymm11, mem(rcx, rax, 1)) //lea(mem(rcx, rsi, 4), rcx) vunpcklpd(ymm15, ymm13, ymm0) vunpckhpd(ymm15, ymm13, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vextractf128(imm(0x1), ymm1, xmm4) vmovupd(xmm0, mem(rdx)) vmovupd(xmm1, mem(rdx, rsi, 1)) vmovupd(xmm2, mem(rdx, rsi, 2)) vmovupd(xmm4, mem(rdx, rax, 1)) //lea(mem(rdx, rsi, 4), rdx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rv_haswell_asm_5x8 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) //lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLPFETCH) // jump to column storage case label(.DROWPFETCH) // row-stored prefetching on c lea(mem(rcx, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 7*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 7*8)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 7*8)) // prefetch c + 3*rs_c prefetch(0, mem(rdx, rdi, 1, 7*8)) // prefetch c + 4*rs_c jmp(.DPOSTPFETCH) // jump to end of prefetching c label(.DCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 8), rsi) // cs_c *= sizeof(double) lea(mem(rcx, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; prefetch(0, mem(rcx, 4*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 4*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 4*8)) // prefetch c + 2*cs_c prefetch(0, mem(rdx, 4*8)) // prefetch c + 3*cs_c prefetch(0, mem(rdx, rsi, 1, 4*8)) // prefetch c + 4*cs_c prefetch(0, mem(rdx, rsi, 2, 4*8)) // prefetch c + 5*cs_c lea(mem(rdx, rsi, 2), rdx) // rdx = c + 5*cs_c; prefetch(0, mem(rdx, rsi, 1, 4*8)) // prefetch c + 6*cs_c prefetch(0, mem(rdx, rsi, 2, 4*8)) // prefetch c + 7*cs_c label(.DPOSTPFETCH) // done prefetching c mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.DLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) // ---------------------------------- iteration 1 vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) // ---------------------------------- iteration 2 vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) // ---------------------------------- iteration 3 vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) dec(rsi) // i -= 1; jne(.DLOOPKITER) // iterate again if i != 0. label(.DCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.DLOOPKLEFT) // EDGE LOOP vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) dec(rsi) // i -= 1; jne(.DLOOPKLEFT) // iterate again if i != 0. label(.DPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(ymm0, ymm5, ymm5) vmulpd(ymm0, ymm6, ymm6) vmulpd(ymm0, ymm7, ymm7) vmulpd(ymm0, ymm8, ymm8) vmulpd(ymm0, ymm9, ymm9) vmulpd(ymm0, ymm10, ymm10) vmulpd(ymm0, ymm11, ymm11) vmulpd(ymm0, ymm12, ymm12) vmulpd(ymm0, ymm13, ymm13) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORED) // jump to column storage case label(.DROWSTORED) vfmadd231pd(mem(rcx), ymm3, ymm4) vmovupd(ymm4, mem(rcx)) vfmadd231pd(mem(rcx, rsi, 4), ymm3, ymm5) vmovupd(ymm5, mem(rcx, rsi, 4)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm6) vmovupd(ymm6, mem(rcx)) vfmadd231pd(mem(rcx, rsi, 4), ymm3, ymm7) vmovupd(ymm7, mem(rcx, rsi, 4)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm8) vmovupd(ymm8, mem(rcx)) vfmadd231pd(mem(rcx, rsi, 4), ymm3, ymm9) vmovupd(ymm9, mem(rcx, rsi, 4)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm10) vmovupd(ymm10, mem(rcx)) vfmadd231pd(mem(rcx, rsi, 4), ymm3, ymm11) vmovupd(ymm11, mem(rcx, rsi, 4)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm12) vmovupd(ymm12, mem(rcx)) vfmadd231pd(mem(rcx, rsi, 4), ymm3, ymm13) vmovupd(ymm13, mem(rcx, rsi, 4)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORED) vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vunpcklpd(ymm10, ymm8, ymm2) vunpckhpd(ymm10, ymm8, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vperm2f128(imm(0x31), ymm2, ymm0, ymm8) vperm2f128(imm(0x31), ymm3, ymm1, ymm10) vbroadcastsd(mem(rbx), ymm3) vfmadd231pd(mem(rcx), ymm3, ymm4) vfmadd231pd(mem(rcx, rsi, 1), ymm3, ymm6) vfmadd231pd(mem(rcx, rsi, 2), ymm3, ymm8) vfmadd231pd(mem(rcx, rax, 1), ymm3, ymm10) vmovupd(ymm4, mem(rcx)) vmovupd(ymm6, mem(rcx, rsi, 1)) vmovupd(ymm8, mem(rcx, rsi, 2)) vmovupd(ymm10, mem(rcx, rax, 1)) lea(mem(rcx, rsi, 4), rcx) #if 0 vunpcklpd(ymm14, ymm12, ymm0) vunpckhpd(ymm14, ymm12, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vextractf128(imm(0x1), ymm1, xmm4) vfmadd231pd(mem(rdx), xmm3, xmm0) vfmadd231pd(mem(rdx, rsi, 1), xmm3, xmm1) vfmadd231pd(mem(rdx, rsi, 2), xmm3, xmm2) vfmadd231pd(mem(rdx, rax, 1), xmm3, xmm4) vmovupd(xmm0, mem(rdx)) vmovupd(xmm1, mem(rdx, rsi, 1)) vmovupd(xmm2, mem(rdx, rsi, 2)) vmovupd(xmm4, mem(rdx, rax, 1)) #else vmovlpd(mem(rdx), xmm0, xmm0) vmovhpd(mem(rdx, rsi, 1), xmm0, xmm0) vmovlpd(mem(rdx, rsi, 2), xmm1, xmm1) vmovhpd(mem(rdx, rax, 1), xmm1, xmm1) vperm2f128(imm(0x20), ymm1, ymm0, ymm0) vfmadd213pd(ymm12, ymm3, ymm0) vextractf128(imm(1), ymm0, xmm1) vmovlpd(xmm0, mem(rdx)) vmovhpd(xmm0, mem(rdx, rsi, 1)) vmovlpd(xmm1, mem(rdx, rsi, 2)) vmovhpd(xmm1, mem(rdx, rax, 1)) #endif lea(mem(rdx, rsi, 4), rdx) vunpcklpd(ymm7, ymm5, ymm0) vunpckhpd(ymm7, ymm5, ymm1) vunpcklpd(ymm11, ymm9, ymm2) vunpckhpd(ymm11, ymm9, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm5) vinsertf128(imm(0x1), xmm3, ymm1, ymm7) vperm2f128(imm(0x31), ymm2, ymm0, ymm9) vperm2f128(imm(0x31), ymm3, ymm1, ymm11) vbroadcastsd(mem(rbx), ymm3) vfmadd231pd(mem(rcx), ymm3, ymm5) vfmadd231pd(mem(rcx, rsi, 1), ymm3, ymm7) vfmadd231pd(mem(rcx, rsi, 2), ymm3, ymm9) vfmadd231pd(mem(rcx, rax, 1), ymm3, ymm11) vmovupd(ymm5, mem(rcx)) vmovupd(ymm7, mem(rcx, rsi, 1)) vmovupd(ymm9, mem(rcx, rsi, 2)) vmovupd(ymm11, mem(rcx, rax, 1)) //lea(mem(rcx, rsi, 4), rcx) #if 0 vunpcklpd(ymm15, ymm13, ymm0) vunpckhpd(ymm15, ymm13, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vextractf128(imm(0x1), ymm1, xmm4) vfmadd231pd(mem(rdx), xmm3, xmm0) vfmadd231pd(mem(rdx, rsi, 1), xmm3, xmm1) vfmadd231pd(mem(rdx, rsi, 2), xmm3, xmm2) vfmadd231pd(mem(rdx, rax, 1), xmm3, xmm4) vmovupd(xmm0, mem(rdx)) vmovupd(xmm1, mem(rdx, rsi, 1)) vmovupd(xmm2, mem(rdx, rsi, 2)) vmovupd(xmm4, mem(rdx, rax, 1)) #else vmovlpd(mem(rdx), xmm0, xmm0) vmovhpd(mem(rdx, rsi, 1), xmm0, xmm0) vmovlpd(mem(rdx, rsi, 2), xmm1, xmm1) vmovhpd(mem(rdx, rax, 1), xmm1, xmm1) vperm2f128(imm(0x20), ymm1, ymm0, ymm0) vfmadd213pd(ymm13, ymm3, ymm0) vextractf128(imm(1), ymm0, xmm1) vmovlpd(xmm0, mem(rdx)) vmovhpd(xmm0, mem(rdx, rsi, 1)) vmovlpd(xmm1, mem(rdx, rsi, 2)) vmovhpd(xmm1, mem(rdx, rax, 1)) #endif //lea(mem(rdx, rsi, 4), rdx) jmp(.DDONE) // jump to end. label(.DBETAZERO) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORBZ) // jump to column storage case label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx)) vmovupd(ymm5, mem(rcx, rsi, 4)) add(rdi, rcx) vmovupd(ymm6, mem(rcx)) vmovupd(ymm7, mem(rcx, rsi, 4)) add(rdi, rcx) vmovupd(ymm8, mem(rcx)) vmovupd(ymm9, mem(rcx, rsi, 4)) add(rdi, rcx) vmovupd(ymm10, mem(rcx)) vmovupd(ymm11, mem(rcx, rsi, 4)) add(rdi, rcx) vmovupd(ymm12, mem(rcx)) vmovupd(ymm13, mem(rcx, rsi, 4)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORBZ) vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vunpcklpd(ymm10, ymm8, ymm2) vunpckhpd(ymm10, ymm8, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vperm2f128(imm(0x31), ymm2, ymm0, ymm8) vperm2f128(imm(0x31), ymm3, ymm1, ymm10) vmovupd(ymm4, mem(rcx)) vmovupd(ymm6, mem(rcx, rsi, 1)) vmovupd(ymm8, mem(rcx, rsi, 2)) vmovupd(ymm10, mem(rcx, rax, 1)) lea(mem(rcx, rsi, 4), rcx) #if 0 vunpcklpd(ymm14, ymm12, ymm0) vunpckhpd(ymm14, ymm12, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vextractf128(imm(0x1), ymm1, xmm4) vmovupd(xmm0, mem(rdx)) vmovupd(xmm1, mem(rdx, rsi, 1)) vmovupd(xmm2, mem(rdx, rsi, 2)) vmovupd(xmm4, mem(rdx, rax, 1)) #else vmovupd(ymm12, ymm0) vextractf128(imm(1), ymm0, xmm1) vmovlpd(xmm0, mem(rcx)) vmovhpd(xmm0, mem(rcx, rsi, 1)) vmovlpd(xmm1, mem(rcx, rsi, 2)) vmovhpd(xmm1, mem(rcx, rax, 1)) #endif lea(mem(rdx, rsi, 4), rdx) vunpcklpd(ymm7, ymm5, ymm0) vunpckhpd(ymm7, ymm5, ymm1) vunpcklpd(ymm11, ymm9, ymm2) vunpckhpd(ymm11, ymm9, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm5) vinsertf128(imm(0x1), xmm3, ymm1, ymm7) vperm2f128(imm(0x31), ymm2, ymm0, ymm9) vperm2f128(imm(0x31), ymm3, ymm1, ymm11) vmovupd(ymm5, mem(rcx)) vmovupd(ymm7, mem(rcx, rsi, 1)) vmovupd(ymm9, mem(rcx, rsi, 2)) vmovupd(ymm11, mem(rcx, rax, 1)) //lea(mem(rcx, rsi, 4), rcx) #if 0 vunpcklpd(ymm15, ymm13, ymm0) vunpckhpd(ymm15, ymm13, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vextractf128(imm(0x1), ymm1, xmm4) vmovupd(xmm0, mem(rdx)) vmovupd(xmm1, mem(rdx, rsi, 1)) vmovupd(xmm2, mem(rdx, rsi, 2)) vmovupd(xmm4, mem(rdx, rax, 1)) #else vmovupd(ymm13, ymm0) vextractf128(imm(1), ymm0, xmm1) vmovlpd(xmm0, mem(rdx)) vmovhpd(xmm0, mem(rdx, rsi, 1)) vmovlpd(xmm1, mem(rdx, rsi, 2)) vmovhpd(xmm1, mem(rdx, rax, 1)) #endif //lea(mem(rdx, rsi, 4), rdx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rv_haswell_asm_4x8 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) //lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) #if 0 lea(mem(rcx, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 7*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 7*8)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 7*8)) // prefetch c + 3*rs_c #else cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLPFETCH) // jump to column storage case label(.DROWPFETCH) // row-stored prefetching on c lea(mem(rcx, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 7*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 7*8)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 7*8)) // prefetch c + 3*rs_c jmp(.DPOSTPFETCH) // jump to end of prefetching c label(.DCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 8), rsi) // cs_c *= sizeof(double) lea(mem(rcx, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 3*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 3*8)) // prefetch c + 2*cs_c prefetch(0, mem(rdx, 3*8)) // prefetch c + 3*cs_c prefetch(0, mem(rdx, rsi, 1, 3*8)) // prefetch c + 4*cs_c prefetch(0, mem(rdx, rsi, 2, 3*8)) // prefetch c + 5*cs_c lea(mem(rdx, rsi, 2), rdx) // rdx = c + 5*cs_c; prefetch(0, mem(rdx, rsi, 1, 3*8)) // prefetch c + 6*cs_c prefetch(0, mem(rdx, rsi, 2, 3*8)) // prefetch c + 7*cs_c label(.DPOSTPFETCH) // done prefetching c #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.DLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) // ---------------------------------- iteration 1 vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) // ---------------------------------- iteration 2 vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) // ---------------------------------- iteration 3 vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) dec(rsi) // i -= 1; jne(.DLOOPKITER) // iterate again if i != 0. label(.DCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.DLOOPKLEFT) // EDGE LOOP vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) dec(rsi) // i -= 1; jne(.DLOOPKLEFT) // iterate again if i != 0. label(.DPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(ymm0, ymm5, ymm5) vmulpd(ymm0, ymm6, ymm6) vmulpd(ymm0, ymm7, ymm7) vmulpd(ymm0, ymm8, ymm8) vmulpd(ymm0, ymm9, ymm9) vmulpd(ymm0, ymm10, ymm10) vmulpd(ymm0, ymm11, ymm11) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; //lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORED) // jump to column storage case label(.DROWSTORED) vfmadd231pd(mem(rcx), ymm3, ymm4) vmovupd(ymm4, mem(rcx)) vfmadd231pd(mem(rcx, rsi, 4), ymm3, ymm5) vmovupd(ymm5, mem(rcx, rsi, 4)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm6) vmovupd(ymm6, mem(rcx)) vfmadd231pd(mem(rcx, rsi, 4), ymm3, ymm7) vmovupd(ymm7, mem(rcx, rsi, 4)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm8) vmovupd(ymm8, mem(rcx)) vfmadd231pd(mem(rcx, rsi, 4), ymm3, ymm9) vmovupd(ymm9, mem(rcx, rsi, 4)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm10) vmovupd(ymm10, mem(rcx)) vfmadd231pd(mem(rcx, rsi, 4), ymm3, ymm11) vmovupd(ymm11, mem(rcx, rsi, 4)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORED) vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vunpcklpd(ymm10, ymm8, ymm2) vunpckhpd(ymm10, ymm8, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vperm2f128(imm(0x31), ymm2, ymm0, ymm8) vperm2f128(imm(0x31), ymm3, ymm1, ymm10) vbroadcastsd(mem(rbx), ymm3) vfmadd231pd(mem(rcx), ymm3, ymm4) vfmadd231pd(mem(rcx, rsi, 1), ymm3, ymm6) vfmadd231pd(mem(rcx, rsi, 2), ymm3, ymm8) vfmadd231pd(mem(rcx, rax, 1), ymm3, ymm10) vmovupd(ymm4, mem(rcx)) vmovupd(ymm6, mem(rcx, rsi, 1)) vmovupd(ymm8, mem(rcx, rsi, 2)) vmovupd(ymm10, mem(rcx, rax, 1)) lea(mem(rcx, rsi, 4), rcx) vunpcklpd(ymm7, ymm5, ymm0) vunpckhpd(ymm7, ymm5, ymm1) vunpcklpd(ymm11, ymm9, ymm2) vunpckhpd(ymm11, ymm9, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm5) vinsertf128(imm(0x1), xmm3, ymm1, ymm7) vperm2f128(imm(0x31), ymm2, ymm0, ymm9) vperm2f128(imm(0x31), ymm3, ymm1, ymm11) vbroadcastsd(mem(rbx), ymm3) vfmadd231pd(mem(rcx), ymm3, ymm5) vfmadd231pd(mem(rcx, rsi, 1), ymm3, ymm7) vfmadd231pd(mem(rcx, rsi, 2), ymm3, ymm9) vfmadd231pd(mem(rcx, rax, 1), ymm3, ymm11) vmovupd(ymm5, mem(rcx)) vmovupd(ymm7, mem(rcx, rsi, 1)) vmovupd(ymm9, mem(rcx, rsi, 2)) vmovupd(ymm11, mem(rcx, rax, 1)) //lea(mem(rcx, rsi, 4), rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORBZ) // jump to column storage case label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx)) vmovupd(ymm5, mem(rcx, rsi, 4)) add(rdi, rcx) vmovupd(ymm6, mem(rcx)) vmovupd(ymm7, mem(rcx, rsi, 4)) add(rdi, rcx) vmovupd(ymm8, mem(rcx)) vmovupd(ymm9, mem(rcx, rsi, 4)) add(rdi, rcx) vmovupd(ymm10, mem(rcx)) vmovupd(ymm11, mem(rcx, rsi, 4)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORBZ) vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vunpcklpd(ymm10, ymm8, ymm2) vunpckhpd(ymm10, ymm8, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vperm2f128(imm(0x31), ymm2, ymm0, ymm8) vperm2f128(imm(0x31), ymm3, ymm1, ymm10) vmovupd(ymm4, mem(rcx)) vmovupd(ymm6, mem(rcx, rsi, 1)) vmovupd(ymm8, mem(rcx, rsi, 2)) vmovupd(ymm10, mem(rcx, rax, 1)) lea(mem(rcx, rsi, 4), rcx) vunpcklpd(ymm7, ymm5, ymm0) vunpckhpd(ymm7, ymm5, ymm1) vunpcklpd(ymm11, ymm9, ymm2) vunpckhpd(ymm11, ymm9, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm5) vinsertf128(imm(0x1), xmm3, ymm1, ymm7) vperm2f128(imm(0x31), ymm2, ymm0, ymm9) vperm2f128(imm(0x31), ymm3, ymm1, ymm11) vmovupd(ymm5, mem(rcx)) vmovupd(ymm7, mem(rcx, rsi, 1)) vmovupd(ymm9, mem(rcx, rsi, 2)) vmovupd(ymm11, mem(rcx, rax, 1)) //lea(mem(rcx, rsi, 4), rcx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rv_haswell_asm_3x8 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) //lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) #if 0 lea(mem(rcx, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 7*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 7*8)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 7*8)) // prefetch c + 3*rs_c #else cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLPFETCH) // jump to column storage case label(.DROWPFETCH) // row-stored prefetching on c //lea(mem(rcx, rdi, 2), rdx) // //lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 7*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 7*8)) // prefetch c + 2*rs_c jmp(.DPOSTPFETCH) // jump to end of prefetching c label(.DCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 8), rsi) // cs_c *= sizeof(double) lea(mem(rcx, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; prefetch(0, mem(rcx, 2*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 2*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 2*8)) // prefetch c + 2*cs_c prefetch(0, mem(rdx, 2*8)) // prefetch c + 3*cs_c prefetch(0, mem(rdx, rsi, 1, 2*8)) // prefetch c + 4*cs_c prefetch(0, mem(rdx, rsi, 2, 2*8)) // prefetch c + 5*cs_c lea(mem(rdx, rsi, 2), rdx) // rdx = c + 5*cs_c; prefetch(0, mem(rdx, rsi, 1, 2*8)) // prefetch c + 6*cs_c prefetch(0, mem(rdx, rsi, 2, 2*8)) // prefetch c + 7*cs_c label(.DPOSTPFETCH) // done prefetching c #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.DLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) // ---------------------------------- iteration 1 vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) // ---------------------------------- iteration 2 vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) // ---------------------------------- iteration 3 vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) dec(rsi) // i -= 1; jne(.DLOOPKITER) // iterate again if i != 0. label(.DCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.DLOOPKLEFT) // EDGE LOOP vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) dec(rsi) // i -= 1; jne(.DLOOPKLEFT) // iterate again if i != 0. label(.DPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(ymm0, ymm5, ymm5) vmulpd(ymm0, ymm6, ymm6) vmulpd(ymm0, ymm7, ymm7) vmulpd(ymm0, ymm8, ymm8) vmulpd(ymm0, ymm9, ymm9) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; lea(mem(rcx, rdi, 2), rdx) // load address of c + 2*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORED) // jump to column storage case label(.DROWSTORED) vfmadd231pd(mem(rcx), ymm3, ymm4) vmovupd(ymm4, mem(rcx)) vfmadd231pd(mem(rcx, rsi, 4), ymm3, ymm5) vmovupd(ymm5, mem(rcx, rsi, 4)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm6) vmovupd(ymm6, mem(rcx)) vfmadd231pd(mem(rcx, rsi, 4), ymm3, ymm7) vmovupd(ymm7, mem(rcx, rsi, 4)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm8) vmovupd(ymm8, mem(rcx)) vfmadd231pd(mem(rcx, rsi, 4), ymm3, ymm9) vmovupd(ymm9, mem(rcx, rsi, 4)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORED) vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vunpcklpd(ymm10, ymm8, ymm2) vunpckhpd(ymm10, ymm8, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vperm2f128(imm(0x31), ymm2, ymm0, ymm8) vperm2f128(imm(0x31), ymm3, ymm1, ymm10) vextractf128(imm(0x1), ymm4, xmm12) vextractf128(imm(0x1), ymm6, xmm13) vextractf128(imm(0x1), ymm8, xmm14) vextractf128(imm(0x1), ymm10, xmm15) vbroadcastsd(mem(rbx), ymm3) vfmadd231pd(mem(rcx), xmm3, xmm4) vfmadd231pd(mem(rcx, rsi, 1), xmm3, xmm6) vfmadd231pd(mem(rcx, rsi, 2), xmm3, xmm8) vfmadd231pd(mem(rcx, rax, 1), xmm3, xmm10) vmovupd(xmm4, mem(rcx)) vmovupd(xmm6, mem(rcx, rsi, 1)) vmovupd(xmm8, mem(rcx, rsi, 2)) vmovupd(xmm10, mem(rcx, rax, 1)) lea(mem(rcx, rsi, 4), rcx) vfmadd231sd(mem(rdx), xmm3, xmm12) vfmadd231sd(mem(rdx, rsi, 1), xmm3, xmm13) vfmadd231sd(mem(rdx, rsi, 2), xmm3, xmm14) vfmadd231sd(mem(rdx, rax, 1), xmm3, xmm15) vmovsd(xmm12, mem(rdx)) vmovsd(xmm13, mem(rdx, rsi, 1)) vmovsd(xmm14, mem(rdx, rsi, 2)) vmovsd(xmm15, mem(rdx, rax, 1)) lea(mem(rdx, rsi, 4), rdx) vunpcklpd(ymm7, ymm5, ymm0) vunpckhpd(ymm7, ymm5, ymm1) vunpcklpd(ymm11, ymm9, ymm2) vunpckhpd(ymm11, ymm9, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm5) vinsertf128(imm(0x1), xmm3, ymm1, ymm7) vperm2f128(imm(0x31), ymm2, ymm0, ymm9) vperm2f128(imm(0x31), ymm3, ymm1, ymm11) vextractf128(imm(0x1), ymm5, xmm12) vextractf128(imm(0x1), ymm7, xmm13) vextractf128(imm(0x1), ymm9, xmm14) vextractf128(imm(0x1), ymm11, xmm15) vbroadcastsd(mem(rbx), ymm3) vfmadd231pd(mem(rcx), xmm3, xmm5) vfmadd231pd(mem(rcx, rsi, 1), xmm3, xmm7) vfmadd231pd(mem(rcx, rsi, 2), xmm3, xmm9) vfmadd231pd(mem(rcx, rax, 1), xmm3, xmm11) vmovupd(xmm5, mem(rcx)) vmovupd(xmm7, mem(rcx, rsi, 1)) vmovupd(xmm9, mem(rcx, rsi, 2)) vmovupd(xmm11, mem(rcx, rax, 1)) //lea(mem(rcx, rsi, 4), rcx) vfmadd231sd(mem(rdx), xmm3, xmm12) vfmadd231sd(mem(rdx, rsi, 1), xmm3, xmm13) vfmadd231sd(mem(rdx, rsi, 2), xmm3, xmm14) vfmadd231sd(mem(rdx, rax, 1), xmm3, xmm15) vmovsd(xmm12, mem(rdx)) vmovsd(xmm13, mem(rdx, rsi, 1)) vmovsd(xmm14, mem(rdx, rsi, 2)) vmovsd(xmm15, mem(rdx, rax, 1)) //lea(mem(rdx, rsi, 4), rdx) jmp(.DDONE) // jump to end. label(.DBETAZERO) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORBZ) // jump to column storage case label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx)) vmovupd(ymm5, mem(rcx, rsi, 4)) add(rdi, rcx) vmovupd(ymm6, mem(rcx)) vmovupd(ymm7, mem(rcx, rsi, 4)) add(rdi, rcx) vmovupd(ymm8, mem(rcx)) vmovupd(ymm9, mem(rcx, rsi, 4)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORBZ) vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vunpcklpd(ymm10, ymm8, ymm2) vunpckhpd(ymm10, ymm8, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vperm2f128(imm(0x31), ymm2, ymm0, ymm8) vperm2f128(imm(0x31), ymm3, ymm1, ymm10) vextractf128(imm(0x1), ymm4, xmm12) vextractf128(imm(0x1), ymm6, xmm13) vextractf128(imm(0x1), ymm8, xmm14) vextractf128(imm(0x1), ymm10, xmm15) vmovupd(xmm4, mem(rcx)) vmovupd(xmm6, mem(rcx, rsi, 1)) vmovupd(xmm8, mem(rcx, rsi, 2)) vmovupd(xmm10, mem(rcx, rax, 1)) lea(mem(rcx, rsi, 4), rcx) vmovsd(xmm12, mem(rdx)) vmovsd(xmm13, mem(rdx, rsi, 1)) vmovsd(xmm14, mem(rdx, rsi, 2)) vmovsd(xmm15, mem(rdx, rax, 1)) lea(mem(rdx, rsi, 4), rdx) vunpcklpd(ymm7, ymm5, ymm0) vunpckhpd(ymm7, ymm5, ymm1) vunpcklpd(ymm11, ymm9, ymm2) vunpckhpd(ymm11, ymm9, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm5) vinsertf128(imm(0x1), xmm3, ymm1, ymm7) vperm2f128(imm(0x31), ymm2, ymm0, ymm9) vperm2f128(imm(0x31), ymm3, ymm1, ymm11) vextractf128(imm(0x1), ymm5, xmm12) vextractf128(imm(0x1), ymm7, xmm13) vextractf128(imm(0x1), ymm9, xmm14) vextractf128(imm(0x1), ymm11, xmm15) vmovupd(xmm5, mem(rcx)) vmovupd(xmm7, mem(rcx, rsi, 1)) vmovupd(xmm9, mem(rcx, rsi, 2)) vmovupd(xmm11, mem(rcx, rax, 1)) //lea(mem(rcx, rsi, 4), rcx) vmovsd(xmm12, mem(rdx)) vmovsd(xmm13, mem(rdx, rsi, 1)) vmovsd(xmm14, mem(rdx, rsi, 2)) vmovsd(xmm15, mem(rdx, rax, 1)) //lea(mem(rdx, rsi, 4), rdx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rv_haswell_asm_2x8 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) //lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) #if 0 //lea(mem(rcx, rdi, 2), rdx) // //lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 7*8)) // prefetch c + 1*rs_c #else cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLPFETCH) // jump to column storage case label(.DROWPFETCH) // row-stored prefetching on c //lea(mem(rcx, rdi, 2), rdx) // //lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 7*8)) // prefetch c + 1*rs_c jmp(.DPOSTPFETCH) // jump to end of prefetching c label(.DCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 8), rsi) // cs_c *= sizeof(double) lea(mem(rcx, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; prefetch(0, mem(rcx, 1*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 1*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 1*8)) // prefetch c + 2*cs_c prefetch(0, mem(rdx, 1*8)) // prefetch c + 3*cs_c prefetch(0, mem(rdx, rsi, 1, 1*8)) // prefetch c + 4*cs_c prefetch(0, mem(rdx, rsi, 2, 1*8)) // prefetch c + 5*cs_c lea(mem(rdx, rsi, 2), rdx) // rdx = c + 5*cs_c; prefetch(0, mem(rdx, rsi, 1, 1*8)) // prefetch c + 6*cs_c prefetch(0, mem(rdx, rsi, 2, 1*8)) // prefetch c + 7*cs_c label(.DPOSTPFETCH) // done prefetching c #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.DLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) // ---------------------------------- iteration 1 vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) // ---------------------------------- iteration 2 vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) // ---------------------------------- iteration 3 vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) dec(rsi) // i -= 1; jne(.DLOOPKITER) // iterate again if i != 0. label(.DCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.DLOOPKLEFT) // EDGE LOOP vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) dec(rsi) // i -= 1; jne(.DLOOPKLEFT) // iterate again if i != 0. label(.DPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(ymm0, ymm5, ymm5) vmulpd(ymm0, ymm6, ymm6) vmulpd(ymm0, ymm7, ymm7) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; //lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORED) // jump to column storage case label(.DROWSTORED) vfmadd231pd(mem(rcx), ymm3, ymm4) vmovupd(ymm4, mem(rcx)) vfmadd231pd(mem(rcx, rsi, 4), ymm3, ymm5) vmovupd(ymm5, mem(rcx, rsi, 4)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm6) vmovupd(ymm6, mem(rcx)) vfmadd231pd(mem(rcx, rsi, 4), ymm3, ymm7) vmovupd(ymm7, mem(rcx, rsi, 4)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORED) vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vextractf128(imm(0x1), ymm1, xmm4) vfmadd231pd(mem(rcx), xmm3, xmm0) vfmadd231pd(mem(rcx, rsi, 1), xmm3, xmm1) vfmadd231pd(mem(rcx, rsi, 2), xmm3, xmm2) vfmadd231pd(mem(rcx, rax, 1), xmm3, xmm4) vmovupd(xmm0, mem(rcx)) vmovupd(xmm1, mem(rcx, rsi, 1)) vmovupd(xmm2, mem(rcx, rsi, 2)) vmovupd(xmm4, mem(rcx, rax, 1)) lea(mem(rcx, rsi, 4), rcx) vunpcklpd(ymm7, ymm5, ymm0) vunpckhpd(ymm7, ymm5, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vextractf128(imm(0x1), ymm1, xmm4) vfmadd231pd(mem(rcx), xmm3, xmm0) vfmadd231pd(mem(rcx, rsi, 1), xmm3, xmm1) vfmadd231pd(mem(rcx, rsi, 2), xmm3, xmm2) vfmadd231pd(mem(rcx, rax, 1), xmm3, xmm4) vmovupd(xmm0, mem(rcx)) vmovupd(xmm1, mem(rcx, rsi, 1)) vmovupd(xmm2, mem(rcx, rsi, 2)) vmovupd(xmm4, mem(rcx, rax, 1)) //lea(mem(rcx, rsi, 4), rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORBZ) // jump to column storage case label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx)) vmovupd(ymm5, mem(rcx, rsi, 4)) add(rdi, rcx) vmovupd(ymm6, mem(rcx)) vmovupd(ymm7, mem(rcx, rsi, 4)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORBZ) vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vextractf128(imm(0x1), ymm1, xmm4) vmovupd(xmm0, mem(rcx)) vmovupd(xmm1, mem(rcx, rsi, 1)) vmovupd(xmm2, mem(rcx, rsi, 2)) vmovupd(xmm4, mem(rcx, rax, 1)) lea(mem(rcx, rsi, 4), rcx) vunpcklpd(ymm7, ymm5, ymm0) vunpckhpd(ymm7, ymm5, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vextractf128(imm(0x1), ymm1, xmm4) vmovupd(xmm0, mem(rcx)) vmovupd(xmm1, mem(rcx, rsi, 1)) vmovupd(xmm2, mem(rcx, rsi, 2)) vmovupd(xmm4, mem(rcx, rax, 1)) //lea(mem(rcx, rsi, 4), rcx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rv_haswell_asm_1x8 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) //lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) #if 0 //lea(mem(rcx, rdi, 2), rdx) // //lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c #else cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLPFETCH) // jump to column storage case label(.DROWPFETCH) // row-stored prefetching on c //lea(mem(rcx, rdi, 2), rdx) // //lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c jmp(.DPOSTPFETCH) // jump to end of prefetching c label(.DCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 8), rsi) // cs_c *= sizeof(double) lea(mem(rcx, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; prefetch(0, mem(rcx, 0*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 0*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 0*8)) // prefetch c + 2*cs_c prefetch(0, mem(rdx, 0*8)) // prefetch c + 3*cs_c prefetch(0, mem(rdx, rsi, 1, 0*8)) // prefetch c + 4*cs_c prefetch(0, mem(rdx, rsi, 2, 0*8)) // prefetch c + 5*cs_c lea(mem(rdx, rsi, 2), rdx) // rdx = c + 5*cs_c; prefetch(0, mem(rdx, rsi, 1, 0*8)) // prefetch c + 6*cs_c prefetch(0, mem(rdx, rsi, 2, 0*8)) // prefetch c + 7*cs_c label(.DPOSTPFETCH) // done prefetching c #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.DLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) // ---------------------------------- iteration 1 vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) // ---------------------------------- iteration 2 vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) // ---------------------------------- iteration 3 vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) dec(rsi) // i -= 1; jne(.DLOOPKITER) // iterate again if i != 0. label(.DCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.DLOOPKLEFT) // EDGE LOOP vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) dec(rsi) // i -= 1; jne(.DLOOPKLEFT) // iterate again if i != 0. label(.DPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(ymm0, ymm5, ymm5) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; //lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORED) // jump to column storage case label(.DROWSTORED) vfmadd231pd(mem(rcx), ymm3, ymm4) vmovupd(ymm4, mem(rcx)) vfmadd231pd(mem(rcx, rsi, 4), ymm3, ymm5) vmovupd(ymm5, mem(rcx, rsi, 4)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORED) vmovlpd(mem(rcx), xmm0, xmm0) vmovhpd(mem(rcx, rsi, 1), xmm0, xmm0) vmovlpd(mem(rcx, rsi, 2), xmm1, xmm1) vmovhpd(mem(rcx, rax, 1), xmm1, xmm1) vperm2f128(imm(0x20), ymm1, ymm0, ymm0) vfmadd213pd(ymm4, ymm3, ymm0) vextractf128(imm(1), ymm0, xmm1) vmovlpd(xmm0, mem(rcx)) vmovhpd(xmm0, mem(rcx, rsi, 1)) vmovlpd(xmm1, mem(rcx, rsi, 2)) vmovhpd(xmm1, mem(rcx, rax, 1)) lea(mem(rcx, rsi, 4), rcx) vmovlpd(mem(rcx), xmm0, xmm0) vmovhpd(mem(rcx, rsi, 1), xmm0, xmm0) vmovlpd(mem(rcx, rsi, 2), xmm1, xmm1) vmovhpd(mem(rcx, rax, 1), xmm1, xmm1) vperm2f128(imm(0x20), ymm1, ymm0, ymm0) vfmadd213pd(ymm5, ymm3, ymm0) vextractf128(imm(1), ymm0, xmm1) vmovlpd(xmm0, mem(rcx)) vmovhpd(xmm0, mem(rcx, rsi, 1)) vmovlpd(xmm1, mem(rcx, rsi, 2)) vmovhpd(xmm1, mem(rcx, rax, 1)) //lea(mem(rcx, rsi, 4), rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORBZ) // jump to column storage case label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx)) vmovupd(ymm5, mem(rcx, rsi, 4)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORBZ) vmovupd(ymm4, ymm0) vextractf128(imm(1), ymm0, xmm1) vmovlpd(xmm0, mem(rcx)) vmovhpd(xmm0, mem(rcx, rsi, 1)) vmovlpd(xmm1, mem(rcx, rsi, 2)) vmovhpd(xmm1, mem(rcx, rax, 1)) lea(mem(rcx, rsi, 4), rcx) vmovupd(ymm5, ymm0) vextractf128(imm(1), ymm0, xmm1) vmovlpd(xmm0, mem(rcx)) vmovhpd(xmm0, mem(rcx, rsi, 1)) vmovlpd(xmm1, mem(rcx, rsi, 2)) vmovhpd(xmm1, mem(rcx, rax, 1)) //lea(mem(rcx, rsi, 4), rcx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rv_haswell_asm_6x6 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) //lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLPFETCH) // jump to column storage case label(.DROWPFETCH) // row-stored prefetching on c lea(mem(rcx, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 5*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 5*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 5*8)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 5*8)) // prefetch c + 3*rs_c prefetch(0, mem(rdx, rdi, 1, 5*8)) // prefetch c + 4*rs_c prefetch(0, mem(rdx, rdi, 2, 5*8)) // prefetch c + 5*rs_c jmp(.DPOSTPFETCH) // jump to end of prefetching c label(.DCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 8), rsi) // cs_c *= sizeof(double) lea(mem(rcx, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; prefetch(0, mem(rcx, 5*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 5*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 5*8)) // prefetch c + 2*cs_c prefetch(0, mem(rdx, 5*8)) // prefetch c + 3*cs_c prefetch(0, mem(rdx, rsi, 1, 5*8)) // prefetch c + 4*cs_c prefetch(0, mem(rdx, rsi, 2, 5*8)) // prefetch c + 5*cs_c label(.DPOSTPFETCH) // done prefetching c mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.DLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, r8, 4), ymm2) vbroadcastsd(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) // ---------------------------------- iteration 1 vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, r8, 4), ymm2) vbroadcastsd(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) // ---------------------------------- iteration 2 vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, r8, 4), ymm2) vbroadcastsd(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) // ---------------------------------- iteration 3 vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, r8, 4), ymm2) vbroadcastsd(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKITER) // iterate again if i != 0. label(.DCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.DLOOPKLEFT) // EDGE LOOP vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, r8, 4), ymm2) vbroadcastsd(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKLEFT) // iterate again if i != 0. label(.DPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(xmm0, xmm5, xmm5) vmulpd(ymm0, ymm6, ymm6) vmulpd(xmm0, xmm7, xmm7) vmulpd(ymm0, ymm8, ymm8) vmulpd(xmm0, xmm9, xmm9) vmulpd(ymm0, ymm10, ymm10) vmulpd(xmm0, xmm11, xmm11) vmulpd(ymm0, ymm12, ymm12) vmulpd(xmm0, xmm13, xmm13) vmulpd(ymm0, ymm14, ymm14) vmulpd(xmm0, xmm15, xmm15) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORED) // jump to column storage case label(.DROWSTORED) vfmadd231pd(mem(rcx), ymm3, ymm4) vmovupd(ymm4, mem(rcx)) vfmadd231pd(mem(rcx, rsi, 4), xmm3, xmm5) vmovupd(xmm5, mem(rcx, rsi, 4)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm6) vmovupd(ymm6, mem(rcx)) vfmadd231pd(mem(rcx, rsi, 4), xmm3, xmm7) vmovupd(xmm7, mem(rcx, rsi, 4)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm8) vmovupd(ymm8, mem(rcx)) vfmadd231pd(mem(rcx, rsi, 4), xmm3, xmm9) vmovupd(xmm9, mem(rcx, rsi, 4)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm10) vmovupd(ymm10, mem(rcx)) vfmadd231pd(mem(rcx, rsi, 4), xmm3, xmm11) vmovupd(xmm11, mem(rcx, rsi, 4)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm12) vmovupd(ymm12, mem(rcx)) vfmadd231pd(mem(rcx, rsi, 4), xmm3, xmm13) vmovupd(xmm13, mem(rcx, rsi, 4)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm14) vmovupd(ymm14, mem(rcx)) vfmadd231pd(mem(rcx, rsi, 4), xmm3, xmm15) vmovupd(xmm15, mem(rcx, rsi, 4)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORED) vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vunpcklpd(ymm10, ymm8, ymm2) vunpckhpd(ymm10, ymm8, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vperm2f128(imm(0x31), ymm2, ymm0, ymm8) vperm2f128(imm(0x31), ymm3, ymm1, ymm10) vbroadcastsd(mem(rbx), ymm3) vfmadd231pd(mem(rcx), ymm3, ymm4) vfmadd231pd(mem(rcx, rsi, 1), ymm3, ymm6) vfmadd231pd(mem(rcx, rsi, 2), ymm3, ymm8) vfmadd231pd(mem(rcx, rax, 1), ymm3, ymm10) vmovupd(ymm4, mem(rcx)) vmovupd(ymm6, mem(rcx, rsi, 1)) vmovupd(ymm8, mem(rcx, rsi, 2)) vmovupd(ymm10, mem(rcx, rax, 1)) lea(mem(rcx, rsi, 4), rcx) vunpcklpd(ymm14, ymm12, ymm0) vunpckhpd(ymm14, ymm12, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vextractf128(imm(0x1), ymm1, xmm4) vfmadd231pd(mem(rdx), xmm3, xmm0) vfmadd231pd(mem(rdx, rsi, 1), xmm3, xmm1) vfmadd231pd(mem(rdx, rsi, 2), xmm3, xmm2) vfmadd231pd(mem(rdx, rax, 1), xmm3, xmm4) vmovupd(xmm0, mem(rdx)) vmovupd(xmm1, mem(rdx, rsi, 1)) vmovupd(xmm2, mem(rdx, rsi, 2)) vmovupd(xmm4, mem(rdx, rax, 1)) lea(mem(rdx, rsi, 4), rdx) vunpcklpd(ymm7, ymm5, ymm0) vunpckhpd(ymm7, ymm5, ymm1) vunpcklpd(ymm11, ymm9, ymm2) vunpckhpd(ymm11, ymm9, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm5) vinsertf128(imm(0x1), xmm3, ymm1, ymm7) //vperm2f128(imm(0x31), ymm2, ymm0, ymm9) //vperm2f128(imm(0x31), ymm3, ymm1, ymm11) vbroadcastsd(mem(rbx), ymm3) vfmadd231pd(mem(rcx), ymm3, ymm5) vfmadd231pd(mem(rcx, rsi, 1), ymm3, ymm7) //vfmadd231pd(mem(rcx, rsi, 2), ymm3, ymm9) //vfmadd231pd(mem(rcx, rax, 1), ymm3, ymm11) vmovupd(ymm5, mem(rcx)) vmovupd(ymm7, mem(rcx, rsi, 1)) //vmovupd(ymm9, mem(rcx, rsi, 2)) //vmovupd(ymm11, mem(rcx, rax, 1)) //lea(mem(rcx, rsi, 4), rcx) vunpcklpd(ymm15, ymm13, ymm0) vunpckhpd(ymm15, ymm13, ymm1) //vextractf128(imm(0x1), ymm0, xmm2) //vextractf128(imm(0x1), ymm1, xmm4) vfmadd231pd(mem(rdx), xmm3, xmm0) vfmadd231pd(mem(rdx, rsi, 1), xmm3, xmm1) //vfmadd231pd(mem(rdx, rsi, 2), xmm3, xmm2) //vfmadd231pd(mem(rdx, rax, 1), xmm3, xmm4) vmovupd(xmm0, mem(rdx)) vmovupd(xmm1, mem(rdx, rsi, 1)) //vmovupd(xmm2, mem(rdx, rsi, 2)) //vmovupd(xmm4, mem(rdx, rax, 1)) //lea(mem(rdx, rsi, 4), rdx) jmp(.DDONE) // jump to end. label(.DBETAZERO) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORBZ) // jump to column storage case label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx)) vmovupd(xmm5, mem(rcx, rsi, 4)) add(rdi, rcx) vmovupd(ymm6, mem(rcx)) vmovupd(xmm7, mem(rcx, rsi, 4)) add(rdi, rcx) vmovupd(ymm8, mem(rcx)) vmovupd(xmm9, mem(rcx, rsi, 4)) add(rdi, rcx) vmovupd(ymm10, mem(rcx)) vmovupd(xmm11, mem(rcx, rsi, 4)) add(rdi, rcx) vmovupd(ymm12, mem(rcx)) vmovupd(xmm13, mem(rcx, rsi, 4)) add(rdi, rcx) vmovupd(ymm14, mem(rcx)) vmovupd(xmm15, mem(rcx, rsi, 4)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORBZ) vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vunpcklpd(ymm10, ymm8, ymm2) vunpckhpd(ymm10, ymm8, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vperm2f128(imm(0x31), ymm2, ymm0, ymm8) vperm2f128(imm(0x31), ymm3, ymm1, ymm10) vmovupd(ymm4, mem(rcx)) vmovupd(ymm6, mem(rcx, rsi, 1)) vmovupd(ymm8, mem(rcx, rsi, 2)) vmovupd(ymm10, mem(rcx, rax, 1)) lea(mem(rcx, rsi, 4), rcx) vunpcklpd(ymm14, ymm12, ymm0) vunpckhpd(ymm14, ymm12, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vextractf128(imm(0x1), ymm1, xmm4) vmovupd(xmm0, mem(rdx)) vmovupd(xmm1, mem(rdx, rsi, 1)) vmovupd(xmm2, mem(rdx, rsi, 2)) vmovupd(xmm4, mem(rdx, rax, 1)) lea(mem(rdx, rsi, 4), rdx) vunpcklpd(ymm7, ymm5, ymm0) vunpckhpd(ymm7, ymm5, ymm1) vunpcklpd(ymm11, ymm9, ymm2) vunpckhpd(ymm11, ymm9, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm5) vinsertf128(imm(0x1), xmm3, ymm1, ymm7) //vperm2f128(imm(0x31), ymm2, ymm0, ymm9) //vperm2f128(imm(0x31), ymm3, ymm1, ymm11) vmovupd(ymm5, mem(rcx)) vmovupd(ymm7, mem(rcx, rsi, 1)) //vmovupd(ymm9, mem(rcx, rsi, 2)) //vmovupd(ymm11, mem(rcx, rax, 1)) //lea(mem(rcx, rsi, 4), rcx) vunpcklpd(ymm15, ymm13, ymm0) vunpckhpd(ymm15, ymm13, ymm1) //vextractf128(imm(0x1), ymm0, xmm2) //vextractf128(imm(0x1), ymm1, xmm4) vmovupd(xmm0, mem(rdx)) vmovupd(xmm1, mem(rdx, rsi, 1)) //vmovupd(xmm2, mem(rdx, rsi, 2)) //vmovupd(xmm4, mem(rdx, rax, 1)) //lea(mem(rdx, rsi, 4), rdx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rv_haswell_asm_5x6 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) //lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLPFETCH) // jump to column storage case label(.DROWPFETCH) // row-stored prefetching on c lea(mem(rcx, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 5*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 5*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 5*8)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 5*8)) // prefetch c + 3*rs_c prefetch(0, mem(rdx, rdi, 1, 5*8)) // prefetch c + 4*rs_c jmp(.DPOSTPFETCH) // jump to end of prefetching c label(.DCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 8), rsi) // cs_c *= sizeof(double) lea(mem(rcx, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; prefetch(0, mem(rcx, 4*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 4*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 4*8)) // prefetch c + 2*cs_c prefetch(0, mem(rdx, 4*8)) // prefetch c + 3*cs_c prefetch(0, mem(rdx, rsi, 1, 4*8)) // prefetch c + 4*cs_c prefetch(0, mem(rdx, rsi, 2, 4*8)) // prefetch c + 5*cs_c label(.DPOSTPFETCH) // done prefetching c mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.DLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) // ---------------------------------- iteration 1 vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) // ---------------------------------- iteration 2 vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) // ---------------------------------- iteration 3 vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) dec(rsi) // i -= 1; jne(.DLOOPKITER) // iterate again if i != 0. label(.DCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.DLOOPKLEFT) // EDGE LOOP vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) dec(rsi) // i -= 1; jne(.DLOOPKLEFT) // iterate again if i != 0. label(.DPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(xmm0, xmm5, xmm5) vmulpd(ymm0, ymm6, ymm6) vmulpd(xmm0, xmm7, xmm7) vmulpd(ymm0, ymm8, ymm8) vmulpd(xmm0, xmm9, xmm9) vmulpd(ymm0, ymm10, ymm10) vmulpd(xmm0, xmm11, xmm11) vmulpd(ymm0, ymm12, ymm12) vmulpd(xmm0, xmm13, xmm13) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORED) // jump to column storage case label(.DROWSTORED) vfmadd231pd(mem(rcx), ymm3, ymm4) vmovupd(ymm4, mem(rcx)) vfmadd231pd(mem(rcx, rsi, 4), xmm3, xmm5) vmovupd(xmm5, mem(rcx, rsi, 4)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm6) vmovupd(ymm6, mem(rcx)) vfmadd231pd(mem(rcx, rsi, 4), xmm3, xmm7) vmovupd(xmm7, mem(rcx, rsi, 4)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm8) vmovupd(ymm8, mem(rcx)) vfmadd231pd(mem(rcx, rsi, 4), xmm3, xmm9) vmovupd(xmm9, mem(rcx, rsi, 4)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm10) vmovupd(ymm10, mem(rcx)) vfmadd231pd(mem(rcx, rsi, 4), xmm3, xmm11) vmovupd(xmm11, mem(rcx, rsi, 4)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm12) vmovupd(ymm12, mem(rcx)) vfmadd231pd(mem(rcx, rsi, 4), xmm3, xmm13) vmovupd(xmm13, mem(rcx, rsi, 4)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORED) vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vunpcklpd(ymm10, ymm8, ymm2) vunpckhpd(ymm10, ymm8, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vperm2f128(imm(0x31), ymm2, ymm0, ymm8) vperm2f128(imm(0x31), ymm3, ymm1, ymm10) vbroadcastsd(mem(rbx), ymm3) vfmadd231pd(mem(rcx), ymm3, ymm4) vfmadd231pd(mem(rcx, rsi, 1), ymm3, ymm6) vfmadd231pd(mem(rcx, rsi, 2), ymm3, ymm8) vfmadd231pd(mem(rcx, rax, 1), ymm3, ymm10) vmovupd(ymm4, mem(rcx)) vmovupd(ymm6, mem(rcx, rsi, 1)) vmovupd(ymm8, mem(rcx, rsi, 2)) vmovupd(ymm10, mem(rcx, rax, 1)) lea(mem(rcx, rsi, 4), rcx) #if 0 vunpcklpd(ymm14, ymm12, ymm0) vunpckhpd(ymm14, ymm12, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vextractf128(imm(0x1), ymm1, xmm4) vfmadd231pd(mem(rdx), xmm3, xmm0) vfmadd231pd(mem(rdx, rsi, 1), xmm3, xmm1) vfmadd231pd(mem(rdx, rsi, 2), xmm3, xmm2) vfmadd231pd(mem(rdx, rax, 1), xmm3, xmm4) vmovupd(xmm0, mem(rdx)) vmovupd(xmm1, mem(rdx, rsi, 1)) vmovupd(xmm2, mem(rdx, rsi, 2)) vmovupd(xmm4, mem(rdx, rax, 1)) #else vmovlpd(mem(rdx), xmm0, xmm0) vmovhpd(mem(rdx, rsi, 1), xmm0, xmm0) vmovlpd(mem(rdx, rsi, 2), xmm1, xmm1) vmovhpd(mem(rdx, rax, 1), xmm1, xmm1) vperm2f128(imm(0x20), ymm1, ymm0, ymm0) vfmadd213pd(ymm12, ymm3, ymm0) vextractf128(imm(1), ymm0, xmm1) vmovlpd(xmm0, mem(rdx)) vmovhpd(xmm0, mem(rdx, rsi, 1)) vmovlpd(xmm1, mem(rdx, rsi, 2)) vmovhpd(xmm1, mem(rdx, rax, 1)) #endif lea(mem(rdx, rsi, 4), rdx) vunpcklpd(ymm7, ymm5, ymm0) vunpckhpd(ymm7, ymm5, ymm1) vunpcklpd(ymm11, ymm9, ymm2) vunpckhpd(ymm11, ymm9, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm5) vinsertf128(imm(0x1), xmm3, ymm1, ymm7) //vperm2f128(imm(0x31), ymm2, ymm0, ymm9) //vperm2f128(imm(0x31), ymm3, ymm1, ymm11) vbroadcastsd(mem(rbx), ymm3) vfmadd231pd(mem(rcx), ymm3, ymm5) vfmadd231pd(mem(rcx, rsi, 1), ymm3, ymm7) //vfmadd231pd(mem(rcx, rsi, 2), ymm3, ymm9) //vfmadd231pd(mem(rcx, rax, 1), ymm3, ymm11) vmovupd(ymm5, mem(rcx)) vmovupd(ymm7, mem(rcx, rsi, 1)) //vmovupd(ymm9, mem(rcx, rsi, 2)) //vmovupd(ymm11, mem(rcx, rax, 1)) //lea(mem(rcx, rsi, 4), rcx) #if 0 vunpcklpd(ymm15, ymm13, ymm0) vunpckhpd(ymm15, ymm13, ymm1) //vextractf128(imm(0x1), ymm0, xmm2) //vextractf128(imm(0x1), ymm1, xmm4) vfmadd231pd(mem(rdx), xmm3, xmm0) vfmadd231pd(mem(rdx, rsi, 1), xmm3, xmm1) //vfmadd231pd(mem(rdx, rsi, 2), xmm3, xmm2) //vfmadd231pd(mem(rdx, rax, 1), xmm3, xmm4) vmovupd(xmm0, mem(rdx)) vmovupd(xmm1, mem(rdx, rsi, 1)) //vmovupd(xmm2, mem(rdx, rsi, 2)) //vmovupd(xmm4, mem(rdx, rax, 1)) #else vmovlpd(mem(rdx), xmm0, xmm0) vmovhpd(mem(rdx, rsi, 1), xmm0, xmm0) //vmovlpd(mem(rdx, rsi, 2), xmm1, xmm1) //vmovhpd(mem(rdx, rax, 1), xmm1, xmm1) //vperm2f128(imm(0x20), ymm1, ymm0, ymm0) vfmadd213pd(xmm13, xmm3, xmm0) //vextractf128(imm(1), ymm0, xmm1) vmovlpd(xmm0, mem(rdx)) vmovhpd(xmm0, mem(rdx, rsi, 1)) //vmovlpd(xmm1, mem(rdx, rsi, 2)) //vmovhpd(xmm1, mem(rdx, rax, 1)) #endif //lea(mem(rdx, rsi, 4), rdx) jmp(.DDONE) // jump to end. label(.DBETAZERO) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORBZ) // jump to column storage case label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx)) vmovupd(xmm5, mem(rcx, rsi, 4)) add(rdi, rcx) vmovupd(ymm6, mem(rcx)) vmovupd(xmm7, mem(rcx, rsi, 4)) add(rdi, rcx) vmovupd(ymm8, mem(rcx)) vmovupd(xmm9, mem(rcx, rsi, 4)) add(rdi, rcx) vmovupd(ymm10, mem(rcx)) vmovupd(xmm11, mem(rcx, rsi, 4)) add(rdi, rcx) vmovupd(ymm12, mem(rcx)) vmovupd(xmm13, mem(rcx, rsi, 4)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORBZ) vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vunpcklpd(ymm10, ymm8, ymm2) vunpckhpd(ymm10, ymm8, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vperm2f128(imm(0x31), ymm2, ymm0, ymm8) vperm2f128(imm(0x31), ymm3, ymm1, ymm10) vmovupd(ymm4, mem(rcx)) vmovupd(ymm6, mem(rcx, rsi, 1)) vmovupd(ymm8, mem(rcx, rsi, 2)) vmovupd(ymm10, mem(rcx, rax, 1)) lea(mem(rcx, rsi, 4), rcx) #if 0 vunpcklpd(ymm14, ymm12, ymm0) vunpckhpd(ymm14, ymm12, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vextractf128(imm(0x1), ymm1, xmm4) vmovupd(xmm0, mem(rdx)) vmovupd(xmm1, mem(rdx, rsi, 1)) vmovupd(xmm2, mem(rdx, rsi, 2)) vmovupd(xmm4, mem(rdx, rax, 1)) #else vmovupd(ymm12, ymm0) vextractf128(imm(1), ymm0, xmm1) vmovlpd(xmm0, mem(rdx)) vmovhpd(xmm0, mem(rdx, rsi, 1)) vmovlpd(xmm1, mem(rdx, rsi, 2)) vmovhpd(xmm1, mem(rdx, rax, 1)) #endif lea(mem(rdx, rsi, 4), rdx) vunpcklpd(ymm7, ymm5, ymm0) vunpckhpd(ymm7, ymm5, ymm1) vunpcklpd(ymm11, ymm9, ymm2) vunpckhpd(ymm11, ymm9, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm5) vinsertf128(imm(0x1), xmm3, ymm1, ymm7) //vperm2f128(imm(0x31), ymm2, ymm0, ymm9) //vperm2f128(imm(0x31), ymm3, ymm1, ymm11) vmovupd(ymm5, mem(rcx)) vmovupd(ymm7, mem(rcx, rsi, 1)) //vmovupd(ymm9, mem(rcx, rsi, 2)) //vmovupd(ymm11, mem(rcx, rax, 1)) //lea(mem(rcx, rsi, 4), rcx) #if 0 vunpcklpd(ymm15, ymm13, ymm0) vunpckhpd(ymm15, ymm13, ymm1) //vextractf128(imm(0x1), ymm0, xmm2) //vextractf128(imm(0x1), ymm1, xmm4) vmovupd(xmm0, mem(rdx)) vmovupd(xmm1, mem(rdx, rsi, 1)) //vmovupd(xmm2, mem(rdx, rsi, 2)) //vmovupd(xmm4, mem(rdx, rax, 1)) #else vmovupd(ymm13, ymm0) //vextractf128(imm(1), ymm0, xmm1) vmovlpd(xmm0, mem(rdx)) vmovhpd(xmm0, mem(rdx, rsi, 1)) //vmovlpd(xmm1, mem(rdx, rsi, 2)) //vmovhpd(xmm1, mem(rdx, rax, 1)) #endif //lea(mem(rdx, rsi, 4), rdx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rv_haswell_asm_4x6 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) //lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLPFETCH) // jump to column storage case label(.DROWPFETCH) // row-stored prefetching on c lea(mem(rcx, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 5*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 5*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 5*8)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 5*8)) // prefetch c + 3*rs_c jmp(.DPOSTPFETCH) // jump to end of prefetching c label(.DCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 8), rsi) // cs_c *= sizeof(double) lea(mem(rcx, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 3*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 3*8)) // prefetch c + 2*cs_c prefetch(0, mem(rdx, 3*8)) // prefetch c + 3*cs_c prefetch(0, mem(rdx, rsi, 1, 3*8)) // prefetch c + 4*cs_c prefetch(0, mem(rdx, rsi, 2, 3*8)) // prefetch c + 5*cs_c label(.DPOSTPFETCH) // done prefetching c mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.DLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) // ---------------------------------- iteration 1 vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) // ---------------------------------- iteration 2 vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) // ---------------------------------- iteration 3 vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) dec(rsi) // i -= 1; jne(.DLOOPKITER) // iterate again if i != 0. label(.DCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.DLOOPKLEFT) // EDGE LOOP vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) dec(rsi) // i -= 1; jne(.DLOOPKLEFT) // iterate again if i != 0. label(.DPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(xmm0, xmm5, xmm5) vmulpd(ymm0, ymm6, ymm6) vmulpd(xmm0, xmm7, xmm7) vmulpd(ymm0, ymm8, ymm8) vmulpd(xmm0, xmm9, xmm9) vmulpd(ymm0, ymm10, ymm10) vmulpd(xmm0, xmm11, xmm11) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; //lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORED) // jump to column storage case label(.DROWSTORED) vfmadd231pd(mem(rcx), ymm3, ymm4) vmovupd(ymm4, mem(rcx)) vfmadd231pd(mem(rcx, rsi, 4), xmm3, xmm5) vmovupd(xmm5, mem(rcx, rsi, 4)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm6) vmovupd(ymm6, mem(rcx)) vfmadd231pd(mem(rcx, rsi, 4), xmm3, xmm7) vmovupd(xmm7, mem(rcx, rsi, 4)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm8) vmovupd(ymm8, mem(rcx)) vfmadd231pd(mem(rcx, rsi, 4), xmm3, xmm9) vmovupd(xmm9, mem(rcx, rsi, 4)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm10) vmovupd(ymm10, mem(rcx)) vfmadd231pd(mem(rcx, rsi, 4), xmm3, xmm11) vmovupd(xmm11, mem(rcx, rsi, 4)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORED) vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vunpcklpd(ymm10, ymm8, ymm2) vunpckhpd(ymm10, ymm8, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vperm2f128(imm(0x31), ymm2, ymm0, ymm8) vperm2f128(imm(0x31), ymm3, ymm1, ymm10) vbroadcastsd(mem(rbx), ymm3) vfmadd231pd(mem(rcx), ymm3, ymm4) vfmadd231pd(mem(rcx, rsi, 1), ymm3, ymm6) vfmadd231pd(mem(rcx, rsi, 2), ymm3, ymm8) vfmadd231pd(mem(rcx, rax, 1), ymm3, ymm10) vmovupd(ymm4, mem(rcx)) vmovupd(ymm6, mem(rcx, rsi, 1)) vmovupd(ymm8, mem(rcx, rsi, 2)) vmovupd(ymm10, mem(rcx, rax, 1)) lea(mem(rcx, rsi, 4), rcx) vunpcklpd(ymm7, ymm5, ymm0) vunpckhpd(ymm7, ymm5, ymm1) vunpcklpd(ymm11, ymm9, ymm2) vunpckhpd(ymm11, ymm9, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm5) vinsertf128(imm(0x1), xmm3, ymm1, ymm7) //vperm2f128(imm(0x31), ymm2, ymm0, ymm9) //vperm2f128(imm(0x31), ymm3, ymm1, ymm11) vbroadcastsd(mem(rbx), ymm3) vfmadd231pd(mem(rcx), ymm3, ymm5) vfmadd231pd(mem(rcx, rsi, 1), ymm3, ymm7) //vfmadd231pd(mem(rcx, rsi, 2), ymm3, ymm9) //vfmadd231pd(mem(rcx, rax, 1), ymm3, ymm11) vmovupd(ymm5, mem(rcx)) vmovupd(ymm7, mem(rcx, rsi, 1)) //vmovupd(ymm9, mem(rcx, rsi, 2)) //vmovupd(ymm11, mem(rcx, rax, 1)) //lea(mem(rcx, rsi, 4), rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORBZ) // jump to column storage case label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx)) vmovupd(xmm5, mem(rcx, rsi, 4)) add(rdi, rcx) vmovupd(ymm6, mem(rcx)) vmovupd(xmm7, mem(rcx, rsi, 4)) add(rdi, rcx) vmovupd(ymm8, mem(rcx)) vmovupd(xmm9, mem(rcx, rsi, 4)) add(rdi, rcx) vmovupd(ymm10, mem(rcx)) vmovupd(xmm11, mem(rcx, rsi, 4)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORBZ) vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vunpcklpd(ymm10, ymm8, ymm2) vunpckhpd(ymm10, ymm8, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vperm2f128(imm(0x31), ymm2, ymm0, ymm8) vperm2f128(imm(0x31), ymm3, ymm1, ymm10) vmovupd(ymm4, mem(rcx)) vmovupd(ymm6, mem(rcx, rsi, 1)) vmovupd(ymm8, mem(rcx, rsi, 2)) vmovupd(ymm10, mem(rcx, rax, 1)) lea(mem(rcx, rsi, 4), rcx) vunpcklpd(ymm7, ymm5, ymm0) vunpckhpd(ymm7, ymm5, ymm1) vunpcklpd(ymm11, ymm9, ymm2) vunpckhpd(ymm11, ymm9, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm5) vinsertf128(imm(0x1), xmm3, ymm1, ymm7) //vperm2f128(imm(0x31), ymm2, ymm0, ymm9) //vperm2f128(imm(0x31), ymm3, ymm1, ymm11) vmovupd(ymm5, mem(rcx)) vmovupd(ymm7, mem(rcx, rsi, 1)) //vmovupd(ymm9, mem(rcx, rsi, 2)) //vmovupd(ymm11, mem(rcx, rax, 1)) //lea(mem(rcx, rsi, 4), rcx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rv_haswell_asm_3x6 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) //lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) #if 0 lea(mem(rcx, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 7*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 7*8)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 7*8)) // prefetch c + 3*rs_c #else cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLPFETCH) // jump to column storage case label(.DROWPFETCH) // row-stored prefetching on c //lea(mem(rcx, rdi, 2), rdx) // //lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 5*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 5*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 5*8)) // prefetch c + 2*rs_c jmp(.DPOSTPFETCH) // jump to end of prefetching c label(.DCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 8), rsi) // cs_c *= sizeof(double) lea(mem(rcx, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; prefetch(0, mem(rcx, 2*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 2*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 2*8)) // prefetch c + 2*cs_c prefetch(0, mem(rdx, 2*8)) // prefetch c + 3*cs_c prefetch(0, mem(rdx, rsi, 1, 2*8)) // prefetch c + 4*cs_c prefetch(0, mem(rdx, rsi, 2, 2*8)) // prefetch c + 5*cs_c label(.DPOSTPFETCH) // done prefetching c #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.DLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) // ---------------------------------- iteration 1 vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) // ---------------------------------- iteration 2 vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) // ---------------------------------- iteration 3 vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) dec(rsi) // i -= 1; jne(.DLOOPKITER) // iterate again if i != 0. label(.DCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.DLOOPKLEFT) // EDGE LOOP vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) dec(rsi) // i -= 1; jne(.DLOOPKLEFT) // iterate again if i != 0. label(.DPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(xmm0, xmm5, xmm5) vmulpd(ymm0, ymm6, ymm6) vmulpd(xmm0, xmm7, xmm7) vmulpd(ymm0, ymm8, ymm8) vmulpd(xmm0, xmm9, xmm9) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; lea(mem(rcx, rdi, 2), rdx) // load address of c + 2*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORED) // jump to column storage case label(.DROWSTORED) vfmadd231pd(mem(rcx), ymm3, ymm4) vmovupd(ymm4, mem(rcx)) vfmadd231pd(mem(rcx, rsi, 4), xmm3, xmm5) vmovupd(xmm5, mem(rcx, rsi, 4)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm6) vmovupd(ymm6, mem(rcx)) vfmadd231pd(mem(rcx, rsi, 4), xmm3, xmm7) vmovupd(xmm7, mem(rcx, rsi, 4)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm8) vmovupd(ymm8, mem(rcx)) vfmadd231pd(mem(rcx, rsi, 4), xmm3, xmm9) vmovupd(xmm9, mem(rcx, rsi, 4)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORED) vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vunpcklpd(ymm10, ymm8, ymm2) vunpckhpd(ymm10, ymm8, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vperm2f128(imm(0x31), ymm2, ymm0, ymm8) vperm2f128(imm(0x31), ymm3, ymm1, ymm10) vextractf128(imm(0x1), ymm4, xmm12) vextractf128(imm(0x1), ymm6, xmm13) vextractf128(imm(0x1), ymm8, xmm14) vextractf128(imm(0x1), ymm10, xmm15) vbroadcastsd(mem(rbx), ymm3) vfmadd231pd(mem(rcx), xmm3, xmm4) vfmadd231pd(mem(rcx, rsi, 1), xmm3, xmm6) vfmadd231pd(mem(rcx, rsi, 2), xmm3, xmm8) vfmadd231pd(mem(rcx, rax, 1), xmm3, xmm10) vmovupd(xmm4, mem(rcx)) vmovupd(xmm6, mem(rcx, rsi, 1)) vmovupd(xmm8, mem(rcx, rsi, 2)) vmovupd(xmm10, mem(rcx, rax, 1)) lea(mem(rcx, rsi, 4), rcx) vfmadd231sd(mem(rdx), xmm3, xmm12) vfmadd231sd(mem(rdx, rsi, 1), xmm3, xmm13) vfmadd231sd(mem(rdx, rsi, 2), xmm3, xmm14) vfmadd231sd(mem(rdx, rax, 1), xmm3, xmm15) vmovsd(xmm12, mem(rdx)) vmovsd(xmm13, mem(rdx, rsi, 1)) vmovsd(xmm14, mem(rdx, rsi, 2)) vmovsd(xmm15, mem(rdx, rax, 1)) lea(mem(rdx, rsi, 4), rdx) vunpcklpd(ymm7, ymm5, ymm0) vunpckhpd(ymm7, ymm5, ymm1) vunpcklpd(ymm11, ymm9, ymm2) vunpckhpd(ymm11, ymm9, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm5) vinsertf128(imm(0x1), xmm3, ymm1, ymm7) vperm2f128(imm(0x31), ymm2, ymm0, ymm9) vperm2f128(imm(0x31), ymm3, ymm1, ymm11) vextractf128(imm(0x1), ymm5, xmm12) vextractf128(imm(0x1), ymm7, xmm13) //vextractf128(imm(0x1), ymm9, xmm14) //vextractf128(imm(0x1), ymm11, xmm15) vbroadcastsd(mem(rbx), ymm3) vfmadd231pd(mem(rcx), xmm3, xmm5) vfmadd231pd(mem(rcx, rsi, 1), xmm3, xmm7) vfmadd231pd(mem(rcx, rsi, 2), xmm3, xmm9) vfmadd231pd(mem(rcx, rax, 1), xmm3, xmm11) vmovupd(xmm5, mem(rcx)) vmovupd(xmm7, mem(rcx, rsi, 1)) //vmovupd(xmm9, mem(rcx, rsi, 2)) //vmovupd(xmm11, mem(rcx, rax, 1)) //lea(mem(rcx, rsi, 4), rcx) vfmadd231sd(mem(rdx), xmm3, xmm12) vfmadd231sd(mem(rdx, rsi, 1), xmm3, xmm13) //vfmadd231sd(mem(rdx, rsi, 2), xmm3, xmm14) //vfmadd231sd(mem(rdx, rax, 1), xmm3, xmm15) vmovsd(xmm12, mem(rdx)) vmovsd(xmm13, mem(rdx, rsi, 1)) //vmovsd(xmm14, mem(rdx, rsi, 2)) //vmovsd(xmm15, mem(rdx, rax, 1)) //lea(mem(rdx, rsi, 4), rdx) jmp(.DDONE) // jump to end. label(.DBETAZERO) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORBZ) // jump to column storage case label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx)) vmovupd(xmm5, mem(rcx, rsi, 4)) add(rdi, rcx) vmovupd(ymm6, mem(rcx)) vmovupd(xmm7, mem(rcx, rsi, 4)) add(rdi, rcx) vmovupd(ymm8, mem(rcx)) vmovupd(xmm9, mem(rcx, rsi, 4)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORBZ) vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vunpcklpd(ymm10, ymm8, ymm2) vunpckhpd(ymm10, ymm8, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vperm2f128(imm(0x31), ymm2, ymm0, ymm8) vperm2f128(imm(0x31), ymm3, ymm1, ymm10) vextractf128(imm(0x1), ymm4, xmm12) vextractf128(imm(0x1), ymm6, xmm13) vextractf128(imm(0x1), ymm8, xmm14) vextractf128(imm(0x1), ymm10, xmm15) vmovupd(xmm4, mem(rcx)) vmovupd(xmm6, mem(rcx, rsi, 1)) vmovupd(xmm8, mem(rcx, rsi, 2)) vmovupd(xmm10, mem(rcx, rax, 1)) lea(mem(rcx, rsi, 4), rcx) vmovsd(xmm12, mem(rdx)) vmovsd(xmm13, mem(rdx, rsi, 1)) vmovsd(xmm14, mem(rdx, rsi, 2)) vmovsd(xmm15, mem(rdx, rax, 1)) lea(mem(rdx, rsi, 4), rdx) vunpcklpd(ymm7, ymm5, ymm0) vunpckhpd(ymm7, ymm5, ymm1) vunpcklpd(ymm11, ymm9, ymm2) vunpckhpd(ymm11, ymm9, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm5) vinsertf128(imm(0x1), xmm3, ymm1, ymm7) vperm2f128(imm(0x31), ymm2, ymm0, ymm9) vperm2f128(imm(0x31), ymm3, ymm1, ymm11) vextractf128(imm(0x1), ymm5, xmm12) vextractf128(imm(0x1), ymm7, xmm13) //vextractf128(imm(0x1), ymm9, xmm14) //vextractf128(imm(0x1), ymm11, xmm15) vmovupd(xmm5, mem(rcx)) vmovupd(xmm7, mem(rcx, rsi, 1)) //vmovupd(xmm9, mem(rcx, rsi, 2)) //vmovupd(xmm11, mem(rcx, rax, 1)) //lea(mem(rcx, rsi, 4), rcx) vmovsd(xmm12, mem(rdx)) vmovsd(xmm13, mem(rdx, rsi, 1)) //vmovsd(xmm14, mem(rdx, rsi, 2)) //vmovsd(xmm15, mem(rdx, rax, 1)) //lea(mem(rdx, rsi, 4), rdx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rv_haswell_asm_2x6 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) //lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLPFETCH) // jump to column storage case label(.DROWPFETCH) // row-stored prefetching on c //lea(mem(rcx, rdi, 2), rdx) // //lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 5*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 5*8)) // prefetch c + 1*rs_c jmp(.DPOSTPFETCH) // jump to end of prefetching c label(.DCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 8), rsi) // cs_c *= sizeof(double) lea(mem(rcx, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; prefetch(0, mem(rcx, 1*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 1*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 1*8)) // prefetch c + 2*cs_c prefetch(0, mem(rdx, 1*8)) // prefetch c + 3*cs_c prefetch(0, mem(rdx, rsi, 1, 1*8)) // prefetch c + 4*cs_c prefetch(0, mem(rdx, rsi, 2, 1*8)) // prefetch c + 5*cs_c label(.DPOSTPFETCH) // done prefetching c mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.DLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) // ---------------------------------- iteration 1 vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) // ---------------------------------- iteration 2 vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) // ---------------------------------- iteration 3 vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) dec(rsi) // i -= 1; jne(.DLOOPKITER) // iterate again if i != 0. label(.DCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.DLOOPKLEFT) // EDGE LOOP vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) dec(rsi) // i -= 1; jne(.DLOOPKLEFT) // iterate again if i != 0. label(.DPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(xmm0, xmm5, xmm5) vmulpd(ymm0, ymm6, ymm6) vmulpd(xmm0, xmm7, xmm7) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; //lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORED) // jump to column storage case label(.DROWSTORED) vfmadd231pd(mem(rcx), ymm3, ymm4) vmovupd(ymm4, mem(rcx)) vfmadd231pd(mem(rcx, rsi, 4), xmm3, xmm5) vmovupd(xmm5, mem(rcx, rsi, 4)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm6) vmovupd(ymm6, mem(rcx)) vfmadd231pd(mem(rcx, rsi, 4), xmm3, xmm7) vmovupd(xmm7, mem(rcx, rsi, 4)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORED) vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vunpcklpd(ymm10, ymm8, ymm2) vunpckhpd(ymm10, ymm8, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vperm2f128(imm(0x31), ymm2, ymm0, ymm8) vperm2f128(imm(0x31), ymm3, ymm1, ymm10) vbroadcastsd(mem(rbx), ymm3) vfmadd231pd(mem(rcx), xmm3, xmm4) vfmadd231pd(mem(rcx, rsi, 1), xmm3, xmm6) vfmadd231pd(mem(rcx, rsi, 2), xmm3, xmm8) vfmadd231pd(mem(rcx, rax, 1), xmm3, xmm10) vmovupd(xmm4, mem(rcx)) vmovupd(xmm6, mem(rcx, rsi, 1)) vmovupd(xmm8, mem(rcx, rsi, 2)) vmovupd(xmm10, mem(rcx, rax, 1)) lea(mem(rcx, rsi, 4), rcx) vunpcklpd(ymm7, ymm5, ymm0) vunpckhpd(ymm7, ymm5, ymm1) vunpcklpd(ymm11, ymm9, ymm2) vunpckhpd(ymm11, ymm9, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm5) vinsertf128(imm(0x1), xmm3, ymm1, ymm7) //vperm2f128(imm(0x31), ymm2, ymm0, ymm9) //vperm2f128(imm(0x31), ymm3, ymm1, ymm11) vbroadcastsd(mem(rbx), ymm3) vfmadd231pd(mem(rcx), xmm3, xmm5) vfmadd231pd(mem(rcx, rsi, 1), xmm3, xmm7) //vfmadd231pd(mem(rcx, rsi, 2), ymm3, ymm9) //vfmadd231pd(mem(rcx, rax, 1), ymm3, ymm11) vmovupd(xmm5, mem(rcx)) vmovupd(xmm7, mem(rcx, rsi, 1)) //vmovupd(ymm9, mem(rcx, rsi, 2)) //vmovupd(ymm11, mem(rcx, rax, 1)) //lea(mem(rcx, rsi, 4), rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORBZ) // jump to column storage case label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx)) vmovupd(xmm5, mem(rcx, rsi, 4)) add(rdi, rcx) vmovupd(ymm6, mem(rcx)) vmovupd(xmm7, mem(rcx, rsi, 4)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORBZ) vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vunpcklpd(ymm10, ymm8, ymm2) vunpckhpd(ymm10, ymm8, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vperm2f128(imm(0x31), ymm2, ymm0, ymm8) vperm2f128(imm(0x31), ymm3, ymm1, ymm10) vmovupd(xmm4, mem(rcx)) vmovupd(xmm6, mem(rcx, rsi, 1)) vmovupd(xmm8, mem(rcx, rsi, 2)) vmovupd(xmm10, mem(rcx, rax, 1)) lea(mem(rcx, rsi, 4), rcx) vunpcklpd(ymm7, ymm5, ymm0) vunpckhpd(ymm7, ymm5, ymm1) vunpcklpd(ymm11, ymm9, ymm2) vunpckhpd(ymm11, ymm9, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm5) vinsertf128(imm(0x1), xmm3, ymm1, ymm7) //vperm2f128(imm(0x31), ymm2, ymm0, ymm9) //vperm2f128(imm(0x31), ymm3, ymm1, ymm11) vmovupd(xmm5, mem(rcx)) vmovupd(xmm7, mem(rcx, rsi, 1)) //vmovupd(ymm9, mem(rcx, rsi, 2)) //vmovupd(ymm11, mem(rcx, rax, 1)) //lea(mem(rcx, rsi, 4), rcx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rv_haswell_asm_1x6 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) //lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) #if 1 prefetch(0, mem(rcx, 5*8)) // prefetch c + 0*rs_c #else cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLPFETCH) // jump to column storage case label(.DROWPFETCH) // row-stored prefetching on c //lea(mem(rcx, rdi, 2), rdx) // //lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 5*8)) // prefetch c + 0*rs_c jmp(.DPOSTPFETCH) // jump to end of prefetching c label(.DCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 8), rsi) // cs_c *= sizeof(double) lea(mem(rcx, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; prefetch(0, mem(rcx, 0*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 0*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 0*8)) // prefetch c + 2*cs_c prefetch(0, mem(rdx, 0*8)) // prefetch c + 3*cs_c prefetch(0, mem(rdx, rsi, 1, 0*8)) // prefetch c + 4*cs_c prefetch(0, mem(rdx, rsi, 2, 0*8)) // prefetch c + 5*cs_c label(.DPOSTPFETCH) // done prefetching c #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.DLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) // ---------------------------------- iteration 1 vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) // ---------------------------------- iteration 2 vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) // ---------------------------------- iteration 3 vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) dec(rsi) // i -= 1; jne(.DLOOPKITER) // iterate again if i != 0. label(.DCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.DLOOPKLEFT) // EDGE LOOP vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) dec(rsi) // i -= 1; jne(.DLOOPKLEFT) // iterate again if i != 0. label(.DPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(xmm0, xmm5, xmm5) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; //lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORED) // jump to column storage case label(.DROWSTORED) vfmadd231pd(mem(rcx), ymm3, ymm4) vmovupd(ymm4, mem(rcx)) vfmadd231pd(mem(rcx, rsi, 4), xmm3, xmm5) vmovupd(xmm5, mem(rcx, rsi, 4)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORED) vmovlpd(mem(rcx), xmm0, xmm0) vmovhpd(mem(rcx, rsi, 1), xmm0, xmm0) vmovlpd(mem(rcx, rsi, 2), xmm1, xmm1) vmovhpd(mem(rcx, rax, 1), xmm1, xmm1) vperm2f128(imm(0x20), ymm1, ymm0, ymm0) vfmadd213pd(ymm4, ymm3, ymm0) vextractf128(imm(1), ymm0, xmm1) vmovlpd(xmm0, mem(rcx)) vmovhpd(xmm0, mem(rcx, rsi, 1)) vmovlpd(xmm1, mem(rcx, rsi, 2)) vmovhpd(xmm1, mem(rcx, rax, 1)) lea(mem(rcx, rsi, 4), rcx) vmovlpd(mem(rcx), xmm0, xmm0) vmovhpd(mem(rcx, rsi, 1), xmm0, xmm0) //vmovlpd(mem(rcx, rsi, 2), xmm1, xmm1) //vmovhpd(mem(rcx, rax, 1), xmm1, xmm1) //vperm2f128(imm(0x20), ymm1, ymm0, ymm0) vfmadd213pd(xmm5, xmm3, xmm0) //vextractf128(imm(1), ymm0, xmm1) vmovlpd(xmm0, mem(rcx)) vmovhpd(xmm0, mem(rcx, rsi, 1)) //vmovlpd(xmm1, mem(rcx, rsi, 2)) //vmovhpd(xmm1, mem(rcx, rax, 1)) //lea(mem(rcx, rsi, 4), rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORBZ) // jump to column storage case label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx)) vmovupd(xmm5, mem(rcx, rsi, 4)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORBZ) vmovupd(ymm4, ymm0) vextractf128(imm(1), ymm0, xmm1) vmovlpd(xmm0, mem(rcx)) vmovhpd(xmm0, mem(rcx, rsi, 1)) vmovlpd(xmm1, mem(rcx, rsi, 2)) vmovhpd(xmm1, mem(rcx, rax, 1)) lea(mem(rcx, rsi, 4), rcx) vmovupd(xmm5, xmm0) //vextractf128(imm(1), ymm0, xmm1) vmovlpd(xmm0, mem(rcx)) vmovhpd(xmm0, mem(rcx, rsi, 1)) //vmovlpd(xmm1, mem(rcx, rsi, 2)) //vmovhpd(xmm1, mem(rcx, rax, 1)) //lea(mem(rcx, rsi, 4), rcx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rv_haswell_asm_6x4 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) //lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) #if 0 lea(mem(rcx, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 7*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 7*8)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 7*8)) // prefetch c + 3*rs_c prefetch(0, mem(rdx, rdi, 1, 7*8)) // prefetch c + 4*rs_c prefetch(0, mem(rdx, rdi, 2, 7*8)) // prefetch c + 5*rs_c #else cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLPFETCH) // jump to column storage case label(.DROWPFETCH) // row-stored prefetching on c lea(mem(rcx, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 3*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 3*8)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 3*8)) // prefetch c + 3*rs_c prefetch(0, mem(rdx, rdi, 1, 3*8)) // prefetch c + 4*rs_c prefetch(0, mem(rdx, rdi, 2, 3*8)) // prefetch c + 5*rs_c jmp(.DPOSTPFETCH) // jump to end of prefetching c label(.DCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 8), rsi) // cs_c *= sizeof(double) lea(mem(rcx, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; prefetch(0, mem(rcx, 5*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 5*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 5*8)) // prefetch c + 2*cs_c prefetch(0, mem(rdx, 5*8)) // prefetch c + 3*cs_c label(.DPOSTPFETCH) // done prefetching c #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.DLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm0, ymm3, ymm6) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm0, ymm3, ymm10) vbroadcastsd(mem(rax, r8, 4), ymm2) vbroadcastsd(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm0, ymm3, ymm14) // ---------------------------------- iteration 1 vmovupd(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm0, ymm3, ymm6) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm0, ymm3, ymm10) vbroadcastsd(mem(rax, r8, 4), ymm2) vbroadcastsd(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm0, ymm3, ymm14) // ---------------------------------- iteration 2 vmovupd(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm0, ymm3, ymm6) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm0, ymm3, ymm10) vbroadcastsd(mem(rax, r8, 4), ymm2) vbroadcastsd(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm0, ymm3, ymm14) // ---------------------------------- iteration 3 vmovupd(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm0, ymm3, ymm6) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm0, ymm3, ymm10) vbroadcastsd(mem(rax, r8, 4), ymm2) vbroadcastsd(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm0, ymm3, ymm14) dec(rsi) // i -= 1; jne(.DLOOPKITER) // iterate again if i != 0. label(.DCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.DLOOPKLEFT) // EDGE LOOP vmovupd(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm0, ymm3, ymm6) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm0, ymm3, ymm10) vbroadcastsd(mem(rax, r8, 4), ymm2) vbroadcastsd(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm0, ymm3, ymm14) dec(rsi) // i -= 1; jne(.DLOOPKLEFT) // iterate again if i != 0. label(.DPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(ymm0, ymm6, ymm6) vmulpd(ymm0, ymm8, ymm8) vmulpd(ymm0, ymm10, ymm10) vmulpd(ymm0, ymm12, ymm12) vmulpd(ymm0, ymm14, ymm14) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORED) // jump to column storage case label(.DROWSTORED) vfmadd231pd(mem(rcx), ymm3, ymm4) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm6) vmovupd(ymm6, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm8) vmovupd(ymm8, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm10) vmovupd(ymm10, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm12) vmovupd(ymm12, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm14) vmovupd(ymm14, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORED) vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vunpcklpd(ymm10, ymm8, ymm2) vunpckhpd(ymm10, ymm8, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vperm2f128(imm(0x31), ymm2, ymm0, ymm8) vperm2f128(imm(0x31), ymm3, ymm1, ymm10) vbroadcastsd(mem(rbx), ymm3) vfmadd231pd(mem(rcx), ymm3, ymm4) vfmadd231pd(mem(rcx, rsi, 1), ymm3, ymm6) vfmadd231pd(mem(rcx, rsi, 2), ymm3, ymm8) vfmadd231pd(mem(rcx, rax, 1), ymm3, ymm10) vmovupd(ymm4, mem(rcx)) vmovupd(ymm6, mem(rcx, rsi, 1)) vmovupd(ymm8, mem(rcx, rsi, 2)) vmovupd(ymm10, mem(rcx, rax, 1)) //lea(mem(rcx, rsi, 4), rcx) vunpcklpd(ymm14, ymm12, ymm0) vunpckhpd(ymm14, ymm12, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vextractf128(imm(0x1), ymm1, xmm4) vfmadd231pd(mem(rdx), xmm3, xmm0) vfmadd231pd(mem(rdx, rsi, 1), xmm3, xmm1) vfmadd231pd(mem(rdx, rsi, 2), xmm3, xmm2) vfmadd231pd(mem(rdx, rax, 1), xmm3, xmm4) vmovupd(xmm0, mem(rdx)) vmovupd(xmm1, mem(rdx, rsi, 1)) vmovupd(xmm2, mem(rdx, rsi, 2)) vmovupd(xmm4, mem(rdx, rax, 1)) //lea(mem(rdx, rsi, 4), rdx) jmp(.DDONE) // jump to end. label(.DBETAZERO) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORBZ) // jump to column storage case label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vmovupd(ymm6, mem(rcx)) add(rdi, rcx) vmovupd(ymm8, mem(rcx)) add(rdi, rcx) vmovupd(ymm10, mem(rcx)) add(rdi, rcx) vmovupd(ymm12, mem(rcx)) add(rdi, rcx) vmovupd(ymm14, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORBZ) vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vunpcklpd(ymm10, ymm8, ymm2) vunpckhpd(ymm10, ymm8, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vperm2f128(imm(0x31), ymm2, ymm0, ymm8) vperm2f128(imm(0x31), ymm3, ymm1, ymm10) vmovupd(ymm4, mem(rcx)) vmovupd(ymm6, mem(rcx, rsi, 1)) vmovupd(ymm8, mem(rcx, rsi, 2)) vmovupd(ymm10, mem(rcx, rax, 1)) //lea(mem(rcx, rsi, 4), rcx) vunpcklpd(ymm14, ymm12, ymm0) vunpckhpd(ymm14, ymm12, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vextractf128(imm(0x1), ymm1, xmm4) vmovupd(xmm0, mem(rdx)) vmovupd(xmm1, mem(rdx, rsi, 1)) vmovupd(xmm2, mem(rdx, rsi, 2)) vmovupd(xmm4, mem(rdx, rax, 1)) //lea(mem(rdx, rsi, 4), rdx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rv_haswell_asm_5x4 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) //lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) #if 0 lea(mem(rcx, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 7*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 7*8)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 7*8)) // prefetch c + 3*rs_c prefetch(0, mem(rdx, rdi, 1, 7*8)) // prefetch c + 4*rs_c prefetch(0, mem(rdx, rdi, 2, 7*8)) // prefetch c + 5*rs_c #else cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLPFETCH) // jump to column storage case label(.DROWPFETCH) // row-stored prefetching on c lea(mem(rcx, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 3*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 3*8)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 3*8)) // prefetch c + 3*rs_c prefetch(0, mem(rdx, rdi, 1, 3*8)) // prefetch c + 4*rs_c jmp(.DPOSTPFETCH) // jump to end of prefetching c label(.DCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 8), rsi) // cs_c *= sizeof(double) lea(mem(rcx, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; prefetch(0, mem(rcx, 4*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 4*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 4*8)) // prefetch c + 2*cs_c prefetch(0, mem(rdx, 4*8)) // prefetch c + 3*cs_c label(.DPOSTPFETCH) // done prefetching c #endif #if 0 lea(mem(rax, r9, 8), rdx) // use rdx for prefetching b. lea(mem(rdx, r9, 8), rdx) // rdx = b + 16*rs_b; #else #if 1 mov(r9, rsi) // rsi = rs_b; sal(imm(5), rsi) // rsi = 16*rs_b; lea(mem(rax, rsi, 1), rdx) // rdx = b + 16*rs_b; #endif #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.DLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm0, ymm3, ymm6) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm0, ymm3, ymm10) vbroadcastsd(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) // ---------------------------------- iteration 1 vmovupd(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm0, ymm3, ymm6) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm0, ymm3, ymm10) vbroadcastsd(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) // ---------------------------------- iteration 2 vmovupd(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm0, ymm3, ymm6) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm0, ymm3, ymm10) vbroadcastsd(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) // ---------------------------------- iteration 3 vmovupd(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm0, ymm3, ymm6) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm0, ymm3, ymm10) vbroadcastsd(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) dec(rsi) // i -= 1; jne(.DLOOPKITER) // iterate again if i != 0. label(.DCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.DLOOPKLEFT) // EDGE LOOP vmovupd(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm0, ymm3, ymm6) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm0, ymm3, ymm10) vbroadcastsd(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm12) dec(rsi) // i -= 1; jne(.DLOOPKLEFT) // iterate again if i != 0. label(.DPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(ymm0, ymm6, ymm6) vmulpd(ymm0, ymm8, ymm8) vmulpd(ymm0, ymm10, ymm10) vmulpd(ymm0, ymm12, ymm12) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORED) // jump to column storage case label(.DROWSTORED) vfmadd231pd(mem(rcx), ymm3, ymm4) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm6) vmovupd(ymm6, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm8) vmovupd(ymm8, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm10) vmovupd(ymm10, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm12) vmovupd(ymm12, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORED) vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vunpcklpd(ymm10, ymm8, ymm2) vunpckhpd(ymm10, ymm8, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vperm2f128(imm(0x31), ymm2, ymm0, ymm8) vperm2f128(imm(0x31), ymm3, ymm1, ymm10) vbroadcastsd(mem(rbx), ymm3) vfmadd231pd(mem(rcx), ymm3, ymm4) vfmadd231pd(mem(rcx, rsi, 1), ymm3, ymm6) vfmadd231pd(mem(rcx, rsi, 2), ymm3, ymm8) vfmadd231pd(mem(rcx, rax, 1), ymm3, ymm10) vmovupd(ymm4, mem(rcx)) vmovupd(ymm6, mem(rcx, rsi, 1)) vmovupd(ymm8, mem(rcx, rsi, 2)) vmovupd(ymm10, mem(rcx, rax, 1)) //lea(mem(rcx, rsi, 4), rcx) #if 0 vunpcklpd(ymm14, ymm12, ymm0) vunpckhpd(ymm14, ymm12, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vextractf128(imm(0x1), ymm1, xmm4) vfmadd231pd(mem(rdx), xmm3, xmm0) vfmadd231pd(mem(rdx, rsi, 1), xmm3, xmm1) vfmadd231pd(mem(rdx, rsi, 2), xmm3, xmm2) vfmadd231pd(mem(rdx, rax, 1), xmm3, xmm4) vmovupd(xmm0, mem(rdx)) vmovupd(xmm1, mem(rdx, rsi, 1)) vmovupd(xmm2, mem(rdx, rsi, 2)) vmovupd(xmm4, mem(rdx, rax, 1)) #else vmovlpd(mem(rdx), xmm0, xmm0) vmovhpd(mem(rdx, rsi, 1), xmm0, xmm0) vmovlpd(mem(rdx, rsi, 2), xmm1, xmm1) vmovhpd(mem(rdx, rax, 1), xmm1, xmm1) vperm2f128(imm(0x20), ymm1, ymm0, ymm0) vfmadd213pd(ymm12, ymm3, ymm0) vextractf128(imm(1), ymm0, xmm1) vmovlpd(xmm0, mem(rdx)) vmovhpd(xmm0, mem(rdx, rsi, 1)) vmovlpd(xmm1, mem(rdx, rsi, 2)) vmovhpd(xmm1, mem(rdx, rax, 1)) #endif //lea(mem(rdx, rsi, 4), rdx) jmp(.DDONE) // jump to end. label(.DBETAZERO) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORBZ) // jump to column storage case label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vmovupd(ymm6, mem(rcx)) add(rdi, rcx) vmovupd(ymm8, mem(rcx)) add(rdi, rcx) vmovupd(ymm10, mem(rcx)) add(rdi, rcx) vmovupd(ymm12, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORBZ) vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vunpcklpd(ymm10, ymm8, ymm2) vunpckhpd(ymm10, ymm8, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vperm2f128(imm(0x31), ymm2, ymm0, ymm8) vperm2f128(imm(0x31), ymm3, ymm1, ymm10) vmovupd(ymm4, mem(rcx)) vmovupd(ymm6, mem(rcx, rsi, 1)) vmovupd(ymm8, mem(rcx, rsi, 2)) vmovupd(ymm10, mem(rcx, rax, 1)) //lea(mem(rcx, rsi, 4), rcx) #if 0 vunpcklpd(ymm14, ymm12, ymm0) vunpckhpd(ymm14, ymm12, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vextractf128(imm(0x1), ymm1, xmm4) vmovupd(xmm0, mem(rdx)) vmovupd(xmm1, mem(rdx, rsi, 1)) vmovupd(xmm2, mem(rdx, rsi, 2)) vmovupd(xmm4, mem(rdx, rax, 1)) #else vmovupd(ymm12, ymm0) vextractf128(imm(1), ymm0, xmm1) vmovlpd(xmm0, mem(rdx)) vmovhpd(xmm0, mem(rdx, rsi, 1)) vmovlpd(xmm1, mem(rdx, rsi, 2)) vmovhpd(xmm1, mem(rdx, rax, 1)) #endif //lea(mem(rdx, rsi, 4), rdx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rv_haswell_asm_4x4 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) //lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) #if 0 lea(mem(rcx, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 3*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 3*8)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 3*8)) // prefetch c + 3*rs_c #else cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLPFETCH) // jump to column storage case label(.DROWPFETCH) // row-stored prefetching on c lea(mem(rcx, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 3*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 3*8)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 3*8)) // prefetch c + 3*rs_c jmp(.DPOSTPFETCH) // jump to end of prefetching c label(.DCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 8), rsi) // cs_c *= sizeof(double) lea(mem(rcx, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 3*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 3*8)) // prefetch c + 2*cs_c prefetch(0, mem(rdx, 3*8)) // prefetch c + 3*cs_c label(.DPOSTPFETCH) // done prefetching c #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.DLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm0, ymm3, ymm6) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm0, ymm3, ymm10) // ---------------------------------- iteration 1 vmovupd(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm0, ymm3, ymm6) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm0, ymm3, ymm10) // ---------------------------------- iteration 2 vmovupd(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm0, ymm3, ymm6) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm0, ymm3, ymm10) // ---------------------------------- iteration 3 vmovupd(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm0, ymm3, ymm6) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm0, ymm3, ymm10) dec(rsi) // i -= 1; jne(.DLOOPKITER) // iterate again if i != 0. label(.DCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.DLOOPKLEFT) // EDGE LOOP vmovupd(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm0, ymm3, ymm6) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm0, ymm3, ymm10) dec(rsi) // i -= 1; jne(.DLOOPKLEFT) // iterate again if i != 0. label(.DPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(ymm0, ymm6, ymm6) vmulpd(ymm0, ymm8, ymm8) vmulpd(ymm0, ymm10, ymm10) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; //lea(mem(rcx, rdi, 4), r14) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORED) // jump to column storage case label(.DROWSTORED) vfmadd231pd(mem(rcx), ymm3, ymm4) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm6) vmovupd(ymm6, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm8) vmovupd(ymm8, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm10) vmovupd(ymm10, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORED) vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vunpcklpd(ymm10, ymm8, ymm2) vunpckhpd(ymm10, ymm8, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vperm2f128(imm(0x31), ymm2, ymm0, ymm8) vperm2f128(imm(0x31), ymm3, ymm1, ymm10) vbroadcastsd(mem(rbx), ymm3) vfmadd231pd(mem(rcx), ymm3, ymm4) vfmadd231pd(mem(rcx, rsi, 1), ymm3, ymm6) vfmadd231pd(mem(rcx, rsi, 2), ymm3, ymm8) vfmadd231pd(mem(rcx, rax, 1), ymm3, ymm10) vmovupd(ymm4, mem(rcx)) vmovupd(ymm6, mem(rcx, rsi, 1)) vmovupd(ymm8, mem(rcx, rsi, 2)) vmovupd(ymm10, mem(rcx, rax, 1)) //lea(mem(rcx, rsi, 4), rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORBZ) // jump to column storage case label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vmovupd(ymm6, mem(rcx)) add(rdi, rcx) vmovupd(ymm8, mem(rcx)) add(rdi, rcx) vmovupd(ymm10, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORBZ) vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vunpcklpd(ymm10, ymm8, ymm2) vunpckhpd(ymm10, ymm8, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vperm2f128(imm(0x31), ymm2, ymm0, ymm8) vperm2f128(imm(0x31), ymm3, ymm1, ymm10) vmovupd(ymm4, mem(rcx)) vmovupd(ymm6, mem(rcx, rsi, 1)) vmovupd(ymm8, mem(rcx, rsi, 2)) vmovupd(ymm10, mem(rcx, rax, 1)) //lea(mem(rcx, rsi, 4), rcx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rv_haswell_asm_3x4 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) //lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) #if 0 lea(mem(rcx, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 7*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 7*8)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 7*8)) // prefetch c + 3*rs_c #else cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLPFETCH) // jump to column storage case label(.DROWPFETCH) // row-stored prefetching on c //lea(mem(rcx, rdi, 2), rdx) // //lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 3*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 3*8)) // prefetch c + 2*rs_c jmp(.DPOSTPFETCH) // jump to end of prefetching c label(.DCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 8), rsi) // cs_c *= sizeof(double) lea(mem(rcx, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; prefetch(0, mem(rcx, 2*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 2*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 2*8)) // prefetch c + 2*cs_c prefetch(0, mem(rdx, 2*8)) // prefetch c + 3*cs_c label(.DPOSTPFETCH) // done prefetching c #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.DLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm0, ymm3, ymm6) vbroadcastsd(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm8) // ---------------------------------- iteration 1 vmovupd(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm0, ymm3, ymm6) vbroadcastsd(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm8) // ---------------------------------- iteration 2 vmovupd(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm0, ymm3, ymm6) vbroadcastsd(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm8) // ---------------------------------- iteration 3 vmovupd(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm0, ymm3, ymm6) vbroadcastsd(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm8) dec(rsi) // i -= 1; jne(.DLOOPKITER) // iterate again if i != 0. label(.DCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.DLOOPKLEFT) // EDGE LOOP vmovupd(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm0, ymm3, ymm6) vbroadcastsd(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm8) dec(rsi) // i -= 1; jne(.DLOOPKLEFT) // iterate again if i != 0. label(.DPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(ymm0, ymm6, ymm6) vmulpd(ymm0, ymm8, ymm8) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; lea(mem(rcx, rdi, 2), rdx) // load address of c + 2*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORED) // jump to column storage case label(.DROWSTORED) vfmadd231pd(mem(rcx), ymm3, ymm4) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm6) vmovupd(ymm6, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm8) vmovupd(ymm8, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORED) vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vunpcklpd(ymm10, ymm8, ymm2) vunpckhpd(ymm10, ymm8, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vperm2f128(imm(0x31), ymm2, ymm0, ymm8) vperm2f128(imm(0x31), ymm3, ymm1, ymm10) vextractf128(imm(0x1), ymm4, xmm12) vextractf128(imm(0x1), ymm6, xmm13) vextractf128(imm(0x1), ymm8, xmm14) vextractf128(imm(0x1), ymm10, xmm15) vbroadcastsd(mem(rbx), ymm3) vfmadd231pd(mem(rcx), xmm3, xmm4) vfmadd231pd(mem(rcx, rsi, 1), xmm3, xmm6) vfmadd231pd(mem(rcx, rsi, 2), xmm3, xmm8) vfmadd231pd(mem(rcx, rax, 1), xmm3, xmm10) vmovupd(xmm4, mem(rcx)) vmovupd(xmm6, mem(rcx, rsi, 1)) vmovupd(xmm8, mem(rcx, rsi, 2)) vmovupd(xmm10, mem(rcx, rax, 1)) //lea(mem(rcx, rsi, 4), rcx) vfmadd231sd(mem(rdx), xmm3, xmm12) vfmadd231sd(mem(rdx, rsi, 1), xmm3, xmm13) vfmadd231sd(mem(rdx, rsi, 2), xmm3, xmm14) vfmadd231sd(mem(rdx, rax, 1), xmm3, xmm15) vmovsd(xmm12, mem(rdx)) vmovsd(xmm13, mem(rdx, rsi, 1)) vmovsd(xmm14, mem(rdx, rsi, 2)) vmovsd(xmm15, mem(rdx, rax, 1)) //lea(mem(rdx, rsi, 4), rdx) jmp(.DDONE) // jump to end. label(.DBETAZERO) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORBZ) // jump to column storage case label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vmovupd(ymm6, mem(rcx)) add(rdi, rcx) vmovupd(ymm8, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORBZ) vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vunpcklpd(ymm10, ymm8, ymm2) vunpckhpd(ymm10, ymm8, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vperm2f128(imm(0x31), ymm2, ymm0, ymm8) vperm2f128(imm(0x31), ymm3, ymm1, ymm10) vextractf128(imm(0x1), ymm4, xmm12) vextractf128(imm(0x1), ymm6, xmm13) vextractf128(imm(0x1), ymm8, xmm14) vextractf128(imm(0x1), ymm10, xmm15) vmovupd(xmm4, mem(rcx)) vmovupd(xmm6, mem(rcx, rsi, 1)) vmovupd(xmm8, mem(rcx, rsi, 2)) vmovupd(xmm10, mem(rcx, rax, 1)) //lea(mem(rcx, rsi, 4), rcx) vmovsd(xmm12, mem(rdx)) vmovsd(xmm13, mem(rdx, rsi, 1)) vmovsd(xmm14, mem(rdx, rsi, 2)) vmovsd(xmm15, mem(rdx, rax, 1)) //lea(mem(rdx, rsi, 4), rdx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rv_haswell_asm_2x4 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) //lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) #if 0 lea(mem(rcx, rdi, 2), rdx) // //lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 7*8)) // prefetch c + 1*rs_c #else cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLPFETCH) // jump to column storage case label(.DROWPFETCH) // row-stored prefetching on c //lea(mem(rcx, rdi, 2), rdx) // //lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 3*8)) // prefetch c + 1*rs_c jmp(.DPOSTPFETCH) // jump to end of prefetching c label(.DCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 8), rsi) // cs_c *= sizeof(double) lea(mem(rcx, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; prefetch(0, mem(rcx, 1*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 1*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 1*8)) // prefetch c + 2*cs_c prefetch(0, mem(rdx, 1*8)) // prefetch c + 3*cs_c label(.DPOSTPFETCH) // done prefetching c #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.DLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm0, ymm3, ymm6) // ---------------------------------- iteration 1 vmovupd(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm0, ymm3, ymm6) // ---------------------------------- iteration 2 vmovupd(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm0, ymm3, ymm6) // ---------------------------------- iteration 3 vmovupd(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm0, ymm3, ymm6) dec(rsi) // i -= 1; jne(.DLOOPKITER) // iterate again if i != 0. label(.DCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.DLOOPKLEFT) // EDGE LOOP vmovupd(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm0, ymm3, ymm6) dec(rsi) // i -= 1; jne(.DLOOPKLEFT) // iterate again if i != 0. label(.DPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(ymm0, ymm6, ymm6) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; //lea(mem(rcx, rdi, 4), r14) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORED) // jump to column storage case label(.DROWSTORED) vfmadd231pd(mem(rcx), ymm3, ymm4) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm6) vmovupd(ymm6, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORED) vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vextractf128(imm(0x1), ymm1, xmm4) vfmadd231pd(mem(rcx), xmm3, xmm0) vfmadd231pd(mem(rcx, rsi, 1), xmm3, xmm1) vfmadd231pd(mem(rcx, rsi, 2), xmm3, xmm2) vfmadd231pd(mem(rcx, rax, 1), xmm3, xmm4) vmovupd(xmm0, mem(rcx)) vmovupd(xmm1, mem(rcx, rsi, 1)) vmovupd(xmm2, mem(rcx, rsi, 2)) vmovupd(xmm4, mem(rcx, rax, 1)) //lea(mem(rcx, rsi, 4), rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORBZ) // jump to column storage case label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vmovupd(ymm6, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORBZ) vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vextractf128(imm(0x1), ymm1, xmm4) vmovupd(xmm0, mem(rcx)) vmovupd(xmm1, mem(rcx, rsi, 1)) vmovupd(xmm2, mem(rcx, rsi, 2)) vmovupd(xmm4, mem(rcx, rax, 1)) //lea(mem(rcx, rsi, 4), rcx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rv_haswell_asm_1x4 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) //lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) #if 0 lea(mem(rcx, rdi, 2), rdx) // //lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c #else cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLPFETCH) // jump to column storage case label(.DROWPFETCH) // row-stored prefetching on c //lea(mem(rcx, rdi, 2), rdx) // //lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c jmp(.DPOSTPFETCH) // jump to end of prefetching c label(.DCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 8), rsi) // cs_c *= sizeof(double) lea(mem(rcx, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; prefetch(0, mem(rcx, 0*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 0*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 0*8)) // prefetch c + 2*cs_c prefetch(0, mem(rdx, 0*8)) // prefetch c + 3*cs_c label(.DPOSTPFETCH) // done prefetching c #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.DLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm4) // ---------------------------------- iteration 1 vmovupd(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm4) // ---------------------------------- iteration 2 vmovupd(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm4) // ---------------------------------- iteration 3 vmovupd(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm4) dec(rsi) // i -= 1; jne(.DLOOPKITER) // iterate again if i != 0. label(.DCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.DLOOPKLEFT) // EDGE LOOP vmovupd(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(ymm0, ymm2, ymm4) dec(rsi) // i -= 1; jne(.DLOOPKLEFT) // iterate again if i != 0. label(.DPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; //lea(mem(rcx, rdi, 4), r14) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORED) // jump to column storage case label(.DROWSTORED) vfmadd231pd(mem(rcx), ymm3, ymm4) vmovupd(ymm4, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORED) vmovlpd(mem(rcx), xmm0, xmm0) vmovhpd(mem(rcx, rsi, 1), xmm0, xmm0) vmovlpd(mem(rcx, rsi, 2), xmm1, xmm1) vmovhpd(mem(rcx, rax, 1), xmm1, xmm1) vperm2f128(imm(0x20), ymm1, ymm0, ymm0) vfmadd213pd(ymm4, ymm3, ymm0) vextractf128(imm(1), ymm0, xmm1) vmovlpd(xmm0, mem(rcx)) vmovhpd(xmm0, mem(rcx, rsi, 1)) vmovlpd(xmm1, mem(rcx, rsi, 2)) vmovhpd(xmm1, mem(rcx, rax, 1)) //lea(mem(rcx, rsi, 4), rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORBZ) // jump to column storage case label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORBZ) vmovupd(ymm4, ymm0) vextractf128(imm(1), ymm0, xmm1) vmovlpd(xmm0, mem(rcx)) vmovhpd(xmm0, mem(rcx, rsi, 1)) vmovlpd(xmm1, mem(rcx, rsi, 2)) vmovhpd(xmm1, mem(rcx, rax, 1)) //lea(mem(rcx, rsi, 4), rcx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rv_haswell_asm_6x2 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) //lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) #if 0 lea(mem(rcx, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 7*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 7*8)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 7*8)) // prefetch c + 3*rs_c prefetch(0, mem(rdx, rdi, 1, 7*8)) // prefetch c + 4*rs_c prefetch(0, mem(rdx, rdi, 2, 7*8)) // prefetch c + 5*rs_c #else cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLPFETCH) // jump to column storage case label(.DROWPFETCH) // row-stored prefetching on c lea(mem(rcx, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 1*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 1*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 1*8)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 1*8)) // prefetch c + 3*rs_c prefetch(0, mem(rdx, rdi, 1, 1*8)) // prefetch c + 4*rs_c prefetch(0, mem(rdx, rdi, 2, 1*8)) // prefetch c + 5*rs_c jmp(.DPOSTPFETCH) // jump to end of prefetching c label(.DCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 8), rsi) // cs_c *= sizeof(double) //lea(mem(rcx, rsi, 2), rdx) // //lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; prefetch(0, mem(rcx, 5*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 5*8)) // prefetch c + 1*cs_c label(.DPOSTPFETCH) // done prefetching c #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.DLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(xmm0, xmm2, xmm4) vfmadd231pd(xmm0, xmm3, xmm6) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(xmm0, xmm2, xmm8) vfmadd231pd(xmm0, xmm3, xmm10) vbroadcastsd(mem(rax, r8, 4), ymm2) vbroadcastsd(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(xmm0, xmm2, xmm12) vfmadd231pd(xmm0, xmm3, xmm14) // ---------------------------------- iteration 1 vmovupd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(xmm0, xmm2, xmm4) vfmadd231pd(xmm0, xmm3, xmm6) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(xmm0, xmm2, xmm8) vfmadd231pd(xmm0, xmm3, xmm10) vbroadcastsd(mem(rax, r8, 4), ymm2) vbroadcastsd(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(xmm0, xmm2, xmm12) vfmadd231pd(xmm0, xmm3, xmm14) // ---------------------------------- iteration 2 vmovupd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(xmm0, xmm2, xmm4) vfmadd231pd(xmm0, xmm3, xmm6) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(xmm0, xmm2, xmm8) vfmadd231pd(xmm0, xmm3, xmm10) vbroadcastsd(mem(rax, r8, 4), ymm2) vbroadcastsd(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(xmm0, xmm2, xmm12) vfmadd231pd(xmm0, xmm3, xmm14) // ---------------------------------- iteration 3 vmovupd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(xmm0, xmm2, xmm4) vfmadd231pd(xmm0, xmm3, xmm6) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(xmm0, xmm2, xmm8) vfmadd231pd(xmm0, xmm3, xmm10) vbroadcastsd(mem(rax, r8, 4), ymm2) vbroadcastsd(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(xmm0, xmm2, xmm12) vfmadd231pd(xmm0, xmm3, xmm14) dec(rsi) // i -= 1; jne(.DLOOPKITER) // iterate again if i != 0. label(.DCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.DLOOPKLEFT) // EDGE LOOP vmovupd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(xmm0, xmm2, xmm4) vfmadd231pd(xmm0, xmm3, xmm6) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(xmm0, xmm2, xmm8) vfmadd231pd(xmm0, xmm3, xmm10) vbroadcastsd(mem(rax, r8, 4), ymm2) vbroadcastsd(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(xmm0, xmm2, xmm12) vfmadd231pd(xmm0, xmm3, xmm14) dec(rsi) // i -= 1; jne(.DLOOPKLEFT) // iterate again if i != 0. label(.DPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(xmm0, xmm4, xmm4) // scale by alpha vmulpd(xmm0, xmm6, xmm6) vmulpd(xmm0, xmm8, xmm8) vmulpd(xmm0, xmm10, xmm10) vmulpd(xmm0, xmm12, xmm12) vmulpd(xmm0, xmm14, xmm14) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; //lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORED) // jump to column storage case label(.DROWSTORED) vfmadd231pd(mem(rcx), xmm3, xmm4) vmovupd(xmm4, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), xmm3, xmm6) vmovupd(xmm6, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), xmm3, xmm8) vmovupd(xmm8, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), xmm3, xmm10) vmovupd(xmm10, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), xmm3, xmm12) vmovupd(xmm12, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), xmm3, xmm14) vmovupd(xmm14, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORED) vunpcklpd(xmm6, xmm4, xmm0) vunpckhpd(xmm6, xmm4, xmm1) vunpcklpd(xmm10, xmm8, xmm2) vunpckhpd(xmm10, xmm8, xmm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vbroadcastsd(mem(rbx), ymm3) vfmadd231pd(mem(rcx), ymm3, ymm4) vfmadd231pd(mem(rcx, rsi, 1), ymm3, ymm6) vmovupd(ymm4, mem(rcx)) vmovupd(ymm6, mem(rcx, rsi, 1)) //lea(mem(rcx, rsi, 4), rcx) vunpcklpd(xmm14, xmm12, xmm0) vunpckhpd(xmm14, xmm12, xmm1) vfmadd231pd(mem(rdx), xmm3, xmm0) vfmadd231pd(mem(rdx, rsi, 1), xmm3, xmm1) vmovupd(xmm0, mem(rdx)) vmovupd(xmm1, mem(rdx, rsi, 1)) //lea(mem(rdx, rsi, 4), rdx) jmp(.DDONE) // jump to end. label(.DBETAZERO) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORBZ) // jump to column storage case label(.DROWSTORBZ) vmovupd(xmm4, mem(rcx)) add(rdi, rcx) vmovupd(xmm6, mem(rcx)) add(rdi, rcx) vmovupd(xmm8, mem(rcx)) add(rdi, rcx) vmovupd(xmm10, mem(rcx)) add(rdi, rcx) vmovupd(xmm12, mem(rcx)) add(rdi, rcx) vmovupd(xmm14, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORBZ) vunpcklpd(xmm6, xmm4, xmm0) vunpckhpd(xmm6, xmm4, xmm1) vunpcklpd(xmm10, xmm8, xmm2) vunpckhpd(xmm10, xmm8, xmm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vmovupd(ymm4, mem(rcx)) vmovupd(ymm6, mem(rcx, rsi, 1)) //lea(mem(rcx, rsi, 4), rcx) vunpcklpd(xmm14, xmm12, xmm0) vunpckhpd(xmm14, xmm12, xmm1) vmovupd(xmm0, mem(rdx)) vmovupd(xmm1, mem(rdx, rsi, 1)) //lea(mem(rdx, rsi, 4), rdx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rv_haswell_asm_5x2 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) //lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) #if 0 lea(mem(rcx, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 7*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 7*8)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 7*8)) // prefetch c + 3*rs_c prefetch(0, mem(rdx, rdi, 1, 7*8)) // prefetch c + 4*rs_c prefetch(0, mem(rdx, rdi, 2, 7*8)) // prefetch c + 5*rs_c #else cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLPFETCH) // jump to column storage case label(.DROWPFETCH) // row-stored prefetching on c lea(mem(rcx, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 1*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 1*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 1*8)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 1*8)) // prefetch c + 3*rs_c prefetch(0, mem(rdx, rdi, 1, 1*8)) // prefetch c + 4*rs_c jmp(.DPOSTPFETCH) // jump to end of prefetching c label(.DCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 8), rsi) // cs_c *= sizeof(double) prefetch(0, mem(rcx, 4*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 4*8)) // prefetch c + 1*cs_c label(.DPOSTPFETCH) // done prefetching c #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.DLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(xmm0, xmm2, xmm4) vfmadd231pd(xmm0, xmm3, xmm6) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(xmm0, xmm2, xmm8) vfmadd231pd(xmm0, xmm3, xmm10) vbroadcastsd(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(xmm0, xmm2, xmm12) // ---------------------------------- iteration 1 vmovupd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(xmm0, xmm2, xmm4) vfmadd231pd(xmm0, xmm3, xmm6) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(xmm0, xmm2, xmm8) vfmadd231pd(xmm0, xmm3, xmm10) vbroadcastsd(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(xmm0, xmm2, xmm12) // ---------------------------------- iteration 2 vmovupd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(xmm0, xmm2, xmm4) vfmadd231pd(xmm0, xmm3, xmm6) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(xmm0, xmm2, xmm8) vfmadd231pd(xmm0, xmm3, xmm10) vbroadcastsd(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(xmm0, xmm2, xmm12) // ---------------------------------- iteration 3 vmovupd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(xmm0, xmm2, xmm4) vfmadd231pd(xmm0, xmm3, xmm6) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(xmm0, xmm2, xmm8) vfmadd231pd(xmm0, xmm3, xmm10) vbroadcastsd(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(xmm0, xmm2, xmm12) dec(rsi) // i -= 1; jne(.DLOOPKITER) // iterate again if i != 0. label(.DCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.DLOOPKLEFT) // EDGE LOOP vmovupd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(xmm0, xmm2, xmm4) vfmadd231pd(xmm0, xmm3, xmm6) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) vfmadd231pd(xmm0, xmm2, xmm8) vfmadd231pd(xmm0, xmm3, xmm10) vbroadcastsd(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(xmm0, xmm2, xmm12) dec(rsi) // i -= 1; jne(.DLOOPKLEFT) // iterate again if i != 0. label(.DPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(xmm0, xmm4, xmm4) // scale by alpha vmulpd(xmm0, xmm6, xmm6) vmulpd(xmm0, xmm8, xmm8) vmulpd(xmm0, xmm10, xmm10) vmulpd(xmm0, xmm12, xmm12) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; //lea(mem(rsi, rsi, 2), rax) // r13 = 3*cs_c; // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORED) // jump to column storage case label(.DROWSTORED) vfmadd231pd(mem(rcx), xmm3, xmm4) vmovupd(xmm4, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), xmm3, xmm6) vmovupd(xmm6, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), xmm3, xmm8) vmovupd(xmm8, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), xmm3, xmm10) vmovupd(xmm10, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), xmm3, xmm12) vmovupd(xmm12, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORED) vunpcklpd(xmm6, xmm4, xmm0) vunpckhpd(xmm6, xmm4, xmm1) vunpcklpd(xmm10, xmm8, xmm2) vunpckhpd(xmm10, xmm8, xmm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vbroadcastsd(mem(rbx), ymm3) vfmadd231pd(mem(rcx), ymm3, ymm4) vfmadd231pd(mem(rcx, rsi, 1), ymm3, ymm6) vmovupd(ymm4, mem(rcx)) vmovupd(ymm6, mem(rcx, rsi, 1)) //lea(mem(rcx, rsi, 4), rcx) #if 0 vunpcklpd(xmm14, xmm12, xmm0) vunpckhpd(xmm14, xmm12, xmm1) vfmadd231pd(mem(rdx), xmm3, xmm0) vfmadd231pd(mem(rdx, rsi, 1), xmm3, xmm1) vmovupd(xmm0, mem(rdx)) vmovupd(xmm1, mem(rdx, rsi, 1)) #else vmovlpd(mem(rdx), xmm0, xmm0) vmovhpd(mem(rdx, rsi, 1), xmm0, xmm0) vfmadd213pd(xmm12, xmm3, xmm0) vmovlpd(xmm0, mem(rdx)) vmovhpd(xmm0, mem(rdx, rsi, 1)) #endif //lea(mem(rdx, rsi, 4), rdx) jmp(.DDONE) // jump to end. label(.DBETAZERO) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORBZ) // jump to column storage case label(.DROWSTORBZ) vmovupd(xmm4, mem(rcx)) add(rdi, rcx) vmovupd(xmm6, mem(rcx)) add(rdi, rcx) vmovupd(xmm8, mem(rcx)) add(rdi, rcx) vmovupd(xmm10, mem(rcx)) add(rdi, rcx) vmovupd(xmm12, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORBZ) vunpcklpd(xmm6, xmm4, xmm0) vunpckhpd(xmm6, xmm4, xmm1) vunpcklpd(xmm10, xmm8, xmm2) vunpckhpd(xmm10, xmm8, xmm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vmovupd(ymm4, mem(rcx)) vmovupd(ymm6, mem(rcx, rsi, 1)) //lea(mem(rcx, rsi, 4), rcx) #if 0 vunpcklpd(xmm14, xmm12, xmm0) vunpckhpd(xmm14, xmm12, xmm1) vmovupd(xmm0, mem(rdx)) vmovupd(xmm1, mem(rdx, rsi, 1)) #else vmovupd(xmm12, xmm0) vmovlpd(xmm0, mem(rdx)) vmovhpd(xmm0, mem(rdx, rsi, 1)) #endif //lea(mem(rdx, rsi, 4), rdx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rv_haswell_asm_4x2 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) //lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) #if 0 lea(mem(rcx, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 7*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 7*8)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 7*8)) // prefetch c + 3*rs_c #else cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLPFETCH) // jump to column storage case label(.DROWPFETCH) // row-stored prefetching on c lea(mem(rcx, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 1*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 1*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 1*8)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 1*8)) // prefetch c + 3*rs_c jmp(.DPOSTPFETCH) // jump to end of prefetching c label(.DCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 8), rsi) // cs_c *= sizeof(double) lea(mem(rcx, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 3*8)) // prefetch c + 1*cs_c label(.DPOSTPFETCH) // done prefetching c #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.DLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(xmm0, xmm2, xmm4) vfmadd231pd(xmm0, xmm3, xmm6) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(xmm0, xmm2, xmm8) vfmadd231pd(xmm0, xmm3, xmm10) // ---------------------------------- iteration 1 vmovupd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(xmm0, xmm2, xmm4) vfmadd231pd(xmm0, xmm3, xmm6) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(xmm0, xmm2, xmm8) vfmadd231pd(xmm0, xmm3, xmm10) // ---------------------------------- iteration 2 vmovupd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(xmm0, xmm2, xmm4) vfmadd231pd(xmm0, xmm3, xmm6) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(xmm0, xmm2, xmm8) vfmadd231pd(xmm0, xmm3, xmm10) // ---------------------------------- iteration 3 vmovupd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(xmm0, xmm2, xmm4) vfmadd231pd(xmm0, xmm3, xmm6) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(xmm0, xmm2, xmm8) vfmadd231pd(xmm0, xmm3, xmm10) dec(rsi) // i -= 1; jne(.DLOOPKITER) // iterate again if i != 0. label(.DCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.DLOOPKLEFT) // EDGE LOOP vmovupd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(xmm0, xmm2, xmm4) vfmadd231pd(xmm0, xmm3, xmm6) vbroadcastsd(mem(rax, r8, 2), ymm2) vbroadcastsd(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(xmm0, xmm2, xmm8) vfmadd231pd(xmm0, xmm3, xmm10) dec(rsi) // i -= 1; jne(.DLOOPKLEFT) // iterate again if i != 0. label(.DPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(xmm0, xmm4, xmm4) // scale by alpha vmulpd(xmm0, xmm6, xmm6) vmulpd(xmm0, xmm8, xmm8) vmulpd(xmm0, xmm10, xmm10) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; //lea(mem(rcx, rdi, 4), r14) // load address of c + 4*rs_c; //lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORED) // jump to column storage case label(.DROWSTORED) vfmadd231pd(mem(rcx), xmm3, xmm4) vmovupd(xmm4, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), xmm3, xmm6) vmovupd(xmm6, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), xmm3, xmm8) vmovupd(xmm8, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), xmm3, xmm10) vmovupd(xmm10, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORED) vunpcklpd(xmm6, xmm4, xmm0) vunpckhpd(xmm6, xmm4, xmm1) vunpcklpd(xmm10, xmm8, xmm2) vunpckhpd(xmm10, xmm8, xmm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vbroadcastsd(mem(rbx), ymm3) vfmadd231pd(mem(rcx), ymm3, ymm4) vfmadd231pd(mem(rcx, rsi, 1), ymm3, ymm6) vmovupd(ymm4, mem(rcx)) vmovupd(ymm6, mem(rcx, rsi, 1)) //lea(mem(rcx, rsi, 4), rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORBZ) // jump to column storage case label(.DROWSTORBZ) vmovupd(xmm4, mem(rcx)) add(rdi, rcx) vmovupd(xmm6, mem(rcx)) add(rdi, rcx) vmovupd(xmm8, mem(rcx)) add(rdi, rcx) vmovupd(xmm10, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORBZ) vunpcklpd(xmm6, xmm4, xmm0) vunpckhpd(xmm6, xmm4, xmm1) vunpcklpd(xmm10, xmm8, xmm2) vunpckhpd(xmm10, xmm8, xmm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) vmovupd(ymm4, mem(rcx)) vmovupd(ymm6, mem(rcx, rsi, 1)) //lea(mem(rcx, rsi, 4), rcx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rv_haswell_asm_3x2 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) //lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) #if 0 lea(mem(rcx, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 7*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 7*8)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 7*8)) // prefetch c + 3*rs_c #else cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLPFETCH) // jump to column storage case label(.DROWPFETCH) // row-stored prefetching on c //lea(mem(rcx, rdi, 2), rdx) // //lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 1*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 1*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 1*8)) // prefetch c + 2*rs_c jmp(.DPOSTPFETCH) // jump to end of prefetching c label(.DCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 8), rsi) // cs_c *= sizeof(double) //lea(mem(rcx, rsi, 2), rdx) // //lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; prefetch(0, mem(rcx, 2*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 2*8)) // prefetch c + 1*cs_c label(.DPOSTPFETCH) // done prefetching c #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.DLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(xmm0, xmm2, xmm4) vfmadd231pd(xmm0, xmm3, xmm6) vbroadcastsd(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(xmm0, xmm2, xmm8) // ---------------------------------- iteration 1 vmovupd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(xmm0, xmm2, xmm4) vfmadd231pd(xmm0, xmm3, xmm6) vbroadcastsd(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(xmm0, xmm2, xmm8) // ---------------------------------- iteration 2 vmovupd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(xmm0, xmm2, xmm4) vfmadd231pd(xmm0, xmm3, xmm6) vbroadcastsd(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(xmm0, xmm2, xmm8) // ---------------------------------- iteration 3 vmovupd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(xmm0, xmm2, xmm4) vfmadd231pd(xmm0, xmm3, xmm6) vbroadcastsd(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(xmm0, xmm2, xmm8) dec(rsi) // i -= 1; jne(.DLOOPKITER) // iterate again if i != 0. label(.DCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.DLOOPKLEFT) // EDGE LOOP vmovupd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) vfmadd231pd(xmm0, xmm2, xmm4) vfmadd231pd(xmm0, xmm3, xmm6) vbroadcastsd(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(xmm0, xmm2, xmm8) dec(rsi) // i -= 1; jne(.DLOOPKLEFT) // iterate again if i != 0. label(.DPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(xmm0, xmm4, xmm4) // scale by alpha vmulpd(xmm0, xmm6, xmm6) vmulpd(xmm0, xmm8, xmm8) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; lea(mem(rcx, rdi, 2), rdx) // load address of c + 2*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORED) // jump to column storage case label(.DROWSTORED) vfmadd231pd(mem(rcx), xmm3, xmm4) vmovupd(xmm4, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), xmm3, xmm6) vmovupd(xmm6, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), xmm3, xmm8) vmovupd(xmm8, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORED) vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vunpcklpd(ymm10, ymm8, ymm2) vunpckhpd(ymm10, ymm8, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) //vperm2f128(imm(0x31), ymm2, ymm0, ymm8) //vperm2f128(imm(0x31), ymm3, ymm1, ymm10) vextractf128(imm(0x1), ymm4, xmm12) vextractf128(imm(0x1), ymm6, xmm13) //vextractf128(imm(0x1), ymm8, xmm14) //vextractf128(imm(0x1), ymm10, xmm15) vbroadcastsd(mem(rbx), ymm3) vfmadd231pd(mem(rcx), xmm3, xmm4) vfmadd231pd(mem(rcx, rsi, 1), xmm3, xmm6) //vfmadd231pd(mem(rcx, rsi, 2), xmm3, xmm8) //vfmadd231pd(mem(rcx, rax, 1), xmm3, xmm10) vmovupd(xmm4, mem(rcx)) vmovupd(xmm6, mem(rcx, rsi, 1)) //vmovupd(xmm8, mem(rcx, rsi, 2)) //vmovupd(xmm10, mem(rcx, rax, 1)) //lea(mem(rcx, rsi, 4), rcx) vfmadd231sd(mem(rdx), xmm3, xmm12) vfmadd231sd(mem(rdx, rsi, 1), xmm3, xmm13) //vfmadd231sd(mem(rdx, rsi, 2), xmm3, xmm14) //vfmadd231sd(mem(rdx, rax, 1), xmm3, xmm15) vmovsd(xmm12, mem(rdx)) vmovsd(xmm13, mem(rdx, rsi, 1)) //vmovsd(xmm14, mem(rdx, rsi, 2)) //vmovsd(xmm15, mem(rdx, rax, 1)) //lea(mem(rdx, rsi, 4), rdx) jmp(.DDONE) // jump to end. label(.DBETAZERO) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORBZ) // jump to column storage case label(.DROWSTORBZ) vmovupd(xmm4, mem(rcx)) add(rdi, rcx) vmovupd(xmm6, mem(rcx)) add(rdi, rcx) vmovupd(xmm8, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORBZ) vunpcklpd(ymm6, ymm4, ymm0) vunpckhpd(ymm6, ymm4, ymm1) vunpcklpd(ymm10, ymm8, ymm2) vunpckhpd(ymm10, ymm8, ymm3) vinsertf128(imm(0x1), xmm2, ymm0, ymm4) vinsertf128(imm(0x1), xmm3, ymm1, ymm6) //vperm2f128(imm(0x31), ymm2, ymm0, ymm8) //vperm2f128(imm(0x31), ymm3, ymm1, ymm10) vextractf128(imm(0x1), ymm4, xmm12) vextractf128(imm(0x1), ymm6, xmm13) //vextractf128(imm(0x1), ymm8, xmm14) //vextractf128(imm(0x1), ymm10, xmm15) vmovupd(xmm4, mem(rcx)) vmovupd(xmm6, mem(rcx, rsi, 1)) //vmovupd(xmm8, mem(rcx, rsi, 2)) //vmovupd(xmm10, mem(rcx, rax, 1)) //lea(mem(rcx, rsi, 4), rcx) vmovsd(xmm12, mem(rdx)) vmovsd(xmm13, mem(rdx, rsi, 1)) //vmovsd(xmm14, mem(rdx, rsi, 2)) //vmovsd(xmm15, mem(rdx, rax, 1)) //lea(mem(rdx, rsi, 4), rdx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rv_haswell_asm_2x2 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) //lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) #if 0 lea(mem(rcx, rdi, 2), rdx) // //lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 7*8)) // prefetch c + 1*rs_c #else cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLPFETCH) // jump to column storage case label(.DROWPFETCH) // row-stored prefetching on c //lea(mem(rcx, rdi, 2), rdx) // //lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 1*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 1*8)) // prefetch c + 1*rs_c jmp(.DPOSTPFETCH) // jump to end of prefetching c label(.DCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 8), rsi) // cs_c *= sizeof(double) //lea(mem(rcx, rsi, 2), rdx) // //lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; prefetch(0, mem(rcx, 1*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 1*8)) // prefetch c + 1*cs_c label(.DPOSTPFETCH) // done prefetching c #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.DLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(xmm0, xmm2, xmm4) vfmadd231pd(xmm0, xmm3, xmm6) // ---------------------------------- iteration 1 vmovupd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(xmm0, xmm2, xmm4) vfmadd231pd(xmm0, xmm3, xmm6) // ---------------------------------- iteration 2 vmovupd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(xmm0, xmm2, xmm4) vfmadd231pd(xmm0, xmm3, xmm6) // ---------------------------------- iteration 3 vmovupd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(xmm0, xmm2, xmm4) vfmadd231pd(xmm0, xmm3, xmm6) dec(rsi) // i -= 1; jne(.DLOOPKITER) // iterate again if i != 0. label(.DCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.DLOOPKLEFT) // EDGE LOOP vmovupd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vbroadcastsd(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231pd(xmm0, xmm2, xmm4) vfmadd231pd(xmm0, xmm3, xmm6) dec(rsi) // i -= 1; jne(.DLOOPKLEFT) // iterate again if i != 0. label(.DPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(xmm0, xmm4, xmm4) // scale by alpha vmulpd(xmm0, xmm6, xmm6) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; //lea(mem(rcx, rdi, 4), r14) // load address of c + 4*rs_c; //lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORED) // jump to column storage case label(.DROWSTORED) vfmadd231pd(mem(rcx), xmm3, xmm4) vmovupd(xmm4, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), xmm3, xmm6) vmovupd(xmm6, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORED) vunpcklpd(xmm6, xmm4, xmm0) vunpckhpd(xmm6, xmm4, xmm1) vfmadd231pd(mem(rcx), xmm3, xmm0) vfmadd231pd(mem(rcx, rsi, 1), xmm3, xmm1) vmovupd(xmm0, mem(rcx)) vmovupd(xmm1, mem(rcx, rsi, 1)) //lea(mem(rcx, rsi, 4), rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORBZ) // jump to column storage case label(.DROWSTORBZ) vmovupd(xmm4, mem(rcx)) add(rdi, rcx) vmovupd(xmm6, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORBZ) vunpcklpd(xmm6, xmm4, xmm0) vunpckhpd(xmm6, xmm4, xmm1) vmovupd(xmm0, mem(rcx)) vmovupd(xmm1, mem(rcx, rsi, 1)) //lea(mem(rcx, rsi, 4), rcx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rv_haswell_asm_1x2 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) //lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) #if 0 lea(mem(rcx, rdi, 2), rdx) // //lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c #else cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLPFETCH) // jump to column storage case label(.DROWPFETCH) // row-stored prefetching on c //lea(mem(rcx, rdi, 2), rdx) // //lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 1*8)) // prefetch c + 0*rs_c jmp(.DPOSTPFETCH) // jump to end of prefetching c label(.DCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 8), rsi) // cs_c *= sizeof(double) //lea(mem(rcx, rsi, 2), rdx) // //lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; prefetch(0, mem(rcx, 0*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 0*8)) // prefetch c + 1*cs_c label(.DPOSTPFETCH) // done prefetching c #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.DLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(xmm0, xmm2, xmm4) // ---------------------------------- iteration 1 vmovupd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(xmm0, xmm2, xmm4) // ---------------------------------- iteration 2 vmovupd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(xmm0, xmm2, xmm4) // ---------------------------------- iteration 3 vmovupd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(xmm0, xmm2, xmm4) dec(rsi) // i -= 1; jne(.DLOOPKITER) // iterate again if i != 0. label(.DCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.DLOOPKLEFT) // EDGE LOOP vmovupd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231pd(xmm0, xmm2, xmm4) dec(rsi) // i -= 1; jne(.DLOOPKLEFT) // iterate again if i != 0. label(.DPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(xmm0, xmm4, xmm4) // scale by alpha mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; //lea(mem(rcx, rdi, 4), r14) // load address of c + 4*rs_c; //lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORED) // jump to column storage case label(.DROWSTORED) vfmadd231pd(mem(rcx), xmm3, xmm4) vmovupd(xmm4, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORED) vmovlpd(mem(rcx), xmm0, xmm0) vmovhpd(mem(rcx, rsi, 1), xmm0, xmm0) vfmadd213pd(xmm4, xmm3, xmm0) vmovlpd(xmm0, mem(rcx)) vmovhpd(xmm0, mem(rcx, rsi, 1)) //lea(mem(rcx, rsi, 4), rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.DCOLSTORBZ) // jump to column storage case label(.DROWSTORBZ) vmovupd(xmm4, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DCOLSTORBZ) vmovlpd(xmm4, mem(rcx)) vmovhpd(xmm4, mem(rcx, rsi, 1)) //lea(mem(rcx, rsi, 4), rcx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } // ----------------------------------------------------------------------------- // NOTE: Normally, for any "?x1" kernel, we would call the reference kernel. // However, at least one other subconfiguration (zen) uses this kernel set, so // we need to be able to call a set of "?x1" kernels that we know will actually // exist regardless of which subconfiguration these kernels were used by. Thus, // the compromise employed here is to inline the reference kernel so it gets // compiled as part of the haswell kernel set, and hence can unconditionally be // called by other kernels within that kernel set. #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, mdim ) \ \ void PASTEMAC(ch,opname) \ ( \ conj_t conja, \ conj_t conjb, \ dim_t m, \ dim_t n, \ dim_t k, \ ctype* restrict alpha, \ ctype* restrict a, inc_t rs_a, inc_t cs_a, \ ctype* restrict b, inc_t rs_b, inc_t cs_b, \ ctype* restrict beta, \ ctype* restrict c, inc_t rs_c, inc_t cs_c, \ auxinfo_t* restrict data, \ cntx_t* restrict cntx \ ) \ { \ for ( dim_t i = 0; i < mdim; ++i ) \ { \ ctype* restrict ci = &c[ i*rs_c ]; \ ctype* restrict ai = &a[ i*rs_a ]; \ \ /* for ( dim_t j = 0; j < 1; ++j ) */ \ { \ ctype* restrict cij = ci /*[ j*cs_c ]*/ ; \ ctype* restrict bj = b /*[ j*cs_b ]*/ ; \ ctype ab; \ \ PASTEMAC(ch,set0s)( ab ); \ \ /* Perform a dot product to update the (i,j) element of c. */ \ for ( dim_t l = 0; l < k; ++l ) \ { \ ctype* restrict aij = &ai[ l*cs_a ]; \ ctype* restrict bij = &bj[ l*rs_b ]; \ \ PASTEMAC(ch,dots)( *aij, *bij, ab ); \ } \ \ /* If beta is one, add ab into c. If beta is zero, overwrite c with the result in ab. Otherwise, scale by beta and accumulate ab to c. */ \ if ( PASTEMAC(ch,eq1)( *beta ) ) \ { \ PASTEMAC(ch,axpys)( *alpha, ab, *cij ); \ } \ else if ( PASTEMAC(d,eq0)( *beta ) ) \ { \ PASTEMAC(ch,scal2s)( *alpha, ab, *cij ); \ } \ else \ { \ PASTEMAC(ch,axpbys)( *alpha, ab, *beta, *cij ); \ } \ } \ } \ } GENTFUNC( double, d, gemmsup_r_haswell_ref_6x1, 6 ) GENTFUNC( double, d, gemmsup_r_haswell_ref_5x1, 5 ) GENTFUNC( double, d, gemmsup_r_haswell_ref_4x1, 4 ) GENTFUNC( double, d, gemmsup_r_haswell_ref_3x1, 3 ) GENTFUNC( double, d, gemmsup_r_haswell_ref_2x1, 2 ) GENTFUNC( double, d, gemmsup_r_haswell_ref_1x1, 1 ) blis-0.9.0/kernels/haswell/3/sup/old/000077500000000000000000000000001422157504600173105ustar00rootroot00000000000000blis-0.9.0/kernels/haswell/3/sup/old/bli_gemmsup_rd_haswell_asm_d6x8.c000066400000000000000000004243301422157504600257020ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define BLIS_ASM_SYNTAX_ATT #include "bli_x86_asm_macros.h" /* rrc: -------- ------ | | | | | | | | -------- ------ | | | | | | | | -------- += ------ ... | | | | | | | | -------- ------ | | | | | | | | -------- ------ : -------- ------ : Assumptions: - C is row-stored and B is column-stored; - A is row-stored; - m0 and n0 are at most MR and NR, respectively. Therefore, this (r)ow-preferential microkernel is well-suited for a dot-product-based accumulation that performs vector loads from both A and B. */ // Prototype reference microkernels. GEMMSUP_KER_PROT( float, s, gemmsup_r_haswell_ref ) GEMMSUP_KER_PROT( double, d, gemmsup_r_haswell_ref ) GEMMSUP_KER_PROT( scomplex, c, gemmsup_r_haswell_ref ) GEMMSUP_KER_PROT( dcomplex, z, gemmsup_r_haswell_ref ) // Define parameters and variables for edge case kernel map. #define NUM_MR 4 #define NUM_NR 4 #define FUNCPTR_T dgemmsup_ker_ft static dim_t mrs[NUM_MR] = { 6, 3, 2, 1 }; static dim_t nrs[NUM_NR] = { 8, 4, 2, 1 }; static FUNCPTR_T kmap[NUM_MR][NUM_NR] = { /* 8 4 2 1 */ /* 6 */ { bli_dgemmsup_rd_haswell_asm_6x8, bli_dgemmsup_rd_haswell_asm_6x4, bli_dgemmsup_rd_haswell_asm_6x2, bli_dgemmsup_r_haswell_ref }, /* 3 */ { bli_dgemmsup_rd_haswell_asm_3x8, bli_dgemmsup_rd_haswell_asm_3x4, bli_dgemmsup_rd_haswell_asm_3x2, bli_dgemmsup_r_haswell_ref }, /* 2 */ { bli_dgemmsup_rd_haswell_asm_2x8, bli_dgemmsup_rd_haswell_asm_2x4, bli_dgemmsup_rd_haswell_asm_2x2, bli_dgemmsup_r_haswell_ref }, /* 1 */ { bli_dgemmsup_rd_haswell_asm_1x8, bli_dgemmsup_rd_haswell_asm_1x4, bli_dgemmsup_rd_haswell_asm_1x2, bli_dgemmsup_r_haswell_ref } }; void bli_dgemmsup_rd_haswell_asm_6x8 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { // Use a reference kernel if this is an edge case in the m or n // dimensions. if ( m0 < 6 || n0 < 8 ) { dim_t n_left = n0; double* restrict cj = c; double* restrict bj = b; // Iterate across columns (corresponding to elements of nrs) until // n_left is zero. for ( dim_t j = 0; n_left != 0; ++j ) { const dim_t nr_cur = nrs[ j ]; // Once we find the value of nrs that is less than (or equal to) // n_left, we use the kernels in that column. if ( nr_cur <= n_left ) { dim_t m_left = m0; double* restrict cij = cj; double* restrict ai = a; // Iterate down the current column (corresponding to elements // of mrs) until m_left is zero. for ( dim_t i = 0; m_left != 0; ++i ) { const dim_t mr_cur = mrs[ i ]; // Once we find the value of mrs that is less than (or equal // to) m_left, we select that kernel. if ( mr_cur <= m_left ) { FUNCPTR_T ker_fp = kmap[i][j]; //printf( "executing %d x %d sup kernel.\n", (int)mr_cur, (int)nr_cur ); // Call the kernel using current mrs and nrs values. ker_fp ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); // Advance C and A pointers by the mrs and nrs we just // used, and decrement m_left. cij += mr_cur*rs_c0; ai += mr_cur*rs_a0; m_left -= mr_cur; } } // Advance C and B pointers by the mrs and nrs we just used, and // decrement n_left. cj += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } } return; } //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), r12) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), r14) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b mov(var(c), r10) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) // r10 = rcx = c // r12 = rax = a // r14 = rbx = b // r9 = m dim index ii // r15 = n dim index jj #if 1 mov(imm(0), r9) // ii = 0; label(.DLOOP3X4I) // LOOP OVER ii = [ 0 1 ... ] lea(mem( , r9, 1), rsi) // rsi = r9 = 3*ii; imul(rdi, rsi) // rsi *= rs_c; lea(mem(r10, rsi, 1), rdx) // rdx = c_jj + 3*ii*rs_c; lea(mem( , r9, 1), rsi) // rsi = r9 = 3*ii; imul(r8, rsi) // rsi *= rs_a; lea(mem(r12, rsi, 1), r12) // rax = a + 3*ii*rs_a; mov(imm(0), r15) // jj = 0; label(.DLOOP3X4J) // LOOP OVER jj = [ 0 1 ... ] vzeroall() // zero all xmm/ymm registers. lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(imm(1*8), rsi) // rsi *= cs_c = 1*8 lea(mem(rdx, rsi, 1), rcx) // rcx = c + 4*jj*cs_c; lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(r11, rsi) // rsi *= cs_b; lea(mem(r14, rsi, 1), rbx) // rbx = b + 4*jj*cs_b; lea(mem( , r12, 1), rax) // rax = a_ii; #endif #if 0 prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 7*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 7*8)) // prefetch c + 2*rs_c #else prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 3*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 3*8)) // prefetch c + 2*rs_c #endif mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 1 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 2 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 3 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rax ), xmm0) vmovsd(mem(rax, r8, 1), xmm1) vmovsd(mem(rax, r8, 2), xmm2) add(imm(1*8), rax) // a += 1*cs_b = 1*8; vmovsd(mem(rbx ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovsd(mem(rbx, r11, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovsd(mem(rbx, r11, 2), xmm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovsd(mem(rbx, r13, 1), xmm3) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 // ymm5 ymm8 ymm11 ymm14 // ymm6 ymm9 ymm12 ymm15 vhaddpd( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm7) vhaddpd( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) // xmm2[0] = sum(ymm10); xmm2[1] = sum(ymm13) vperm2f128(imm(0x20), ymm2, ymm0, ymm4 ) vhaddpd( ymm8, ymm5, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm14, ymm11, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm5 ) vhaddpd( ymm9, ymm6, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm15, ymm12, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm6 ) // ymm4 = sum(ymm4) sum(ymm7) sum(ymm10) sum(ymm13) // ymm5 = sum(ymm5) sum(ymm8) sum(ymm11) sum(ymm14) // ymm6 = sum(ymm6) sum(ymm9) sum(ymm12) sum(ymm15) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(ymm0, ymm5, ymm5) vmulpd(ymm0, ymm6, ymm6) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), ymm3, ymm4) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm5) vmovupd(ymm5, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm6) vmovupd(ymm6, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vmovupd(ymm5, mem(rcx)) add(rdi, rcx) vmovupd(ymm6, mem(rcx)) //add(rdi, rcx) label(.DDONE) #if 1 add(imm(4), r15) // jj += 4; cmp(imm(4), r15) // compare jj to 4 jle(.DLOOP3X4J) // if jj <= 4, jump to beginning // of jj loop; otherwise, loop ends. add(imm(3), r9) // ii += 3; cmp(imm(3), r9) // compare ii to 3 jle(.DLOOP3X4I) // if ii <= 3, jump to beginning #endif label(.DRETURN) end_asm( : // output operands (none) : // input operands [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rd_haswell_asm_3x8 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), r12) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), r14) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b mov(var(c), r10) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) // r10 = rcx = c // r12 = rax = a // r14 = rbx = b // r9 = m dim index ii // r15 = n dim index jj mov(imm(0), r15) // jj = 0; label(.DLOOP3X4J) // LOOP OVER jj = [ 0 1 ... ] vzeroall() // zero all xmm/ymm registers. lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(imm(1*8), rsi) // rsi *= cs_c = 1*8 lea(mem(r10, rsi, 1), rcx) // rcx = c + 4*jj*cs_c; lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(r11, rsi) // rsi *= cs_b; lea(mem(r14, rsi, 1), rbx) // rbx = b + 4*jj*cs_b; lea(mem( , r12, 1), rax) // rax = a; prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 7*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 7*8)) // prefetch c + 2*rs_c mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 1 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 2 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 3 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rax ), xmm0) vmovsd(mem(rax, r8, 1), xmm1) vmovsd(mem(rax, r8, 2), xmm2) add(imm(1*8), rax) // a += 1*cs_b = 1*8; vmovsd(mem(rbx ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovsd(mem(rbx, r11, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovsd(mem(rbx, r11, 2), xmm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovsd(mem(rbx, r13, 1), xmm3) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 // ymm5 ymm8 ymm11 ymm14 // ymm6 ymm9 ymm12 ymm15 vhaddpd( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm7) vhaddpd( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) // xmm2[0] = sum(ymm10); xmm2[1] = sum(ymm13) vperm2f128(imm(0x20), ymm2, ymm0, ymm4 ) vhaddpd( ymm8, ymm5, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm14, ymm11, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm5 ) vhaddpd( ymm9, ymm6, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm15, ymm12, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm6 ) // ymm4 = sum(ymm4) sum(ymm7) sum(ymm10) sum(ymm13) // ymm5 = sum(ymm5) sum(ymm8) sum(ymm11) sum(ymm14) // ymm6 = sum(ymm6) sum(ymm9) sum(ymm12) sum(ymm15) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(ymm0, ymm5, ymm5) vmulpd(ymm0, ymm6, ymm6) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), ymm3, ymm4) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm5) vmovupd(ymm5, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm6) vmovupd(ymm6, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vmovupd(ymm5, mem(rcx)) add(rdi, rcx) vmovupd(ymm6, mem(rcx)) //add(rdi, rcx) label(.DDONE) add(imm(4), r15) // jj += 4; cmp(imm(4), r15) // compare jj to 4 jle(.DLOOP3X4J) // if jj <= 4, jump to beginning // of jj loop; otherwise, loop ends. label(.DRETURN) end_asm( : // output operands (none) : // input operands [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rd_haswell_asm_2x8 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { #if 0 bli_dgemmsup_r_haswell_ref ( conja, conjb, m0, n0, k0, alpha, a, rs_a0, cs_a0, b, rs_b0, cs_b0, beta, c, rs_c0, cs_c0, data, cntx ); return; #endif //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), r12) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), r14) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b mov(var(c), r10) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) // r10 = rcx = c // r12 = rax = a // r14 = rbx = b // r9 = m dim index ii // r15 = n dim index jj mov(imm(0), r15) // jj = 0; label(.DLOOP3X4J) // LOOP OVER jj = [ 0 1 ... ] vzeroall() // zero all xmm/ymm registers. lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(imm(1*8), rsi) // rsi *= cs_c = 1*8 lea(mem(r10, rsi, 1), rcx) // rcx = c + 4*jj*cs_c; lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(r11, rsi) // rsi *= cs_b; lea(mem(r14, rsi, 1), rbx) // rbx = b + 4*jj*cs_b; lea(mem( , r12, 1), rax) // rax = a; prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 7*8)) // prefetch c + 1*rs_c mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) // ---------------------------------- iteration 1 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) // ---------------------------------- iteration 2 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) // ---------------------------------- iteration 3 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rax ), xmm0) vmovsd(mem(rax, r8, 1), xmm1) add(imm(1*8), rax) // a += 1*cs_b = 1*8; vmovsd(mem(rbx ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovsd(mem(rbx, r11, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovsd(mem(rbx, r11, 2), xmm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovsd(mem(rbx, r13, 1), xmm3) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 // ymm5 ymm8 ymm11 ymm14 vhaddpd( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm7) vhaddpd( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) // xmm2[0] = sum(ymm10); xmm2[1] = sum(ymm13) vperm2f128(imm(0x20), ymm2, ymm0, ymm4 ) vhaddpd( ymm8, ymm5, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm14, ymm11, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm5 ) // ymm4 = sum(ymm4) sum(ymm7) sum(ymm10) sum(ymm13) // ymm5 = sum(ymm5) sum(ymm8) sum(ymm11) sum(ymm14) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(ymm0, ymm5, ymm5) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), ymm3, ymm4) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm5) vmovupd(ymm5, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vmovupd(ymm5, mem(rcx)) //add(rdi, rcx) label(.DDONE) add(imm(4), r15) // jj += 4; cmp(imm(4), r15) // compare jj to 4 jle(.DLOOP3X4J) // if jj <= 4, jump to beginning // of jj loop; otherwise, loop ends. label(.DRETURN) end_asm( : // output operands (none) : // input operands [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rd_haswell_asm_1x8 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { #if 0 bli_dgemmsup_r_haswell_ref ( conja, conjb, m0, n0, k0, alpha, a, rs_a0, cs_a0, b, rs_b0, cs_b0, beta, c, rs_c0, cs_c0, data, cntx ); return; #endif //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), r12) // load address of a. //mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), r14) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b mov(var(c), r10) // load address of c //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) // r10 = rcx = c // r12 = rax = a // r14 = rbx = b // r9 = m dim index ii // r15 = n dim index jj mov(imm(0), r15) // jj = 0; label(.DLOOP3X4J) // LOOP OVER jj = [ 0 1 ... ] vzeroall() // zero all xmm/ymm registers. lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(imm(1*8), rsi) // rsi *= cs_c = 1*8 lea(mem(r10, rsi, 1), rcx) // rcx = c + 4*jj*cs_c; lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(r11, rsi) // rsi *= cs_b; lea(mem(r14, rsi, 1), rbx) // rbx = b + 4*jj*cs_b; lea(mem( , r12, 1), rax) // rax = a; prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rax ), ymm0) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) // ---------------------------------- iteration 1 vmovupd(mem(rax ), ymm0) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) // ---------------------------------- iteration 2 vmovupd(mem(rax ), ymm0) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) // ---------------------------------- iteration 3 vmovupd(mem(rax ), ymm0) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) vmovupd(mem(rax ), ymm0) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rax ), xmm0) add(imm(1*8), rax) // a += 1*cs_b = 1*8; vmovsd(mem(rbx ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovsd(mem(rbx, r11, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovsd(mem(rbx, r11, 2), xmm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovsd(mem(rbx, r13, 1), xmm3) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vfmadd231pd(ymm0, ymm3, ymm13) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 vhaddpd( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm7) vhaddpd( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) // xmm2[0] = sum(ymm10); xmm2[1] = sum(ymm13) vperm2f128(imm(0x20), ymm2, ymm0, ymm4 ) // ymm4 = sum(ymm4) sum(ymm7) sum(ymm10) sum(ymm13) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), ymm3, ymm4) vmovupd(ymm4, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx)) //add(rdi, rcx) label(.DDONE) add(imm(4), r15) // jj += 4; cmp(imm(4), r15) // compare jj to 4 jle(.DLOOP3X4J) // if jj <= 4, jump to beginning // of jj loop; otherwise, loop ends. label(.DRETURN) end_asm( : // output operands (none) : // input operands [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rd_haswell_asm_6x4 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { #if 0 bli_dgemmsup_r_haswell_ref ( conja, conjb, m0, n0, k0, alpha, a, rs_a0, cs_a0, b, rs_b0, cs_b0, beta, c, rs_c0, cs_c0, data, cntx ); return; #endif //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), r12) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), r14) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b mov(var(c), r10) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) // r10 = rcx = c // r12 = rax = a // r14 = rbx = b // r9 = m dim index ii // r15 = n dim index jj mov(imm(0), r9) // ii = 0; label(.DLOOP3X4I) // LOOP OVER ii = [ 0 1 ... ] vzeroall() // zero all xmm/ymm registers. lea(mem( , r9, 1), rsi) // rsi = r9 = 3*ii; imul(rdi, rsi) // rsi *= rs_c; lea(mem(r10, rsi, 1), rcx) // rcx = c + 3*ii*rs_c; lea(mem( , r9, 1), rsi) // rsi = r9 = 3*ii; imul(r8, rsi) // rsi *= rs_a; lea(mem(r12, rsi, 1), rax) // rax = a + 3*ii*rs_a; lea(mem( , r14, 1), rbx) // rbx = b; prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 7*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 7*8)) // prefetch c + 2*rs_c mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 1 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 2 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 3 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rax ), xmm0) vmovsd(mem(rax, r8, 1), xmm1) vmovsd(mem(rax, r8, 2), xmm2) add(imm(1*8), rax) // a += 1*cs_b = 1*8; vmovsd(mem(rbx ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovsd(mem(rbx, r11, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovsd(mem(rbx, r11, 2), xmm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovsd(mem(rbx, r13, 1), xmm3) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 // ymm5 ymm8 ymm11 ymm14 // ymm6 ymm9 ymm12 ymm15 vhaddpd( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm7) vhaddpd( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) // xmm2[0] = sum(ymm10); xmm2[1] = sum(ymm13) vperm2f128(imm(0x20), ymm2, ymm0, ymm4 ) vhaddpd( ymm8, ymm5, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm14, ymm11, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm5 ) vhaddpd( ymm9, ymm6, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm15, ymm12, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm6 ) // ymm4 = sum(ymm4) sum(ymm7) sum(ymm10) sum(ymm13) // ymm5 = sum(ymm5) sum(ymm8) sum(ymm11) sum(ymm14) // ymm6 = sum(ymm6) sum(ymm9) sum(ymm12) sum(ymm15) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(ymm0, ymm5, ymm5) vmulpd(ymm0, ymm6, ymm6) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), ymm3, ymm4) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm5) vmovupd(ymm5, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm6) vmovupd(ymm6, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vmovupd(ymm5, mem(rcx)) add(rdi, rcx) vmovupd(ymm6, mem(rcx)) //add(rdi, rcx) label(.DDONE) add(imm(3), r9) // ii += 3; cmp(imm(3), r9) // compare ii to 3 jle(.DLOOP3X4I) // if ii <= 3, jump to beginning // of ii loop; otherwise, loop ends. label(.DRETURN) end_asm( : // output operands (none) : // input operands [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rd_haswell_asm_3x4 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { #if 0 bli_dgemmsup_r_haswell_ref ( conja, conjb, m0, n0, k0, alpha, a, rs_a0, cs_a0, b, rs_b0, cs_b0, beta, c, rs_c0, cs_c0, data, cntx ); return; #endif //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b // initialize loop by pre-loading // a column of a. mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 7*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 7*8)) // prefetch c + 2*rs_c mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 1 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 2 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 3 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rax ), xmm0) vmovsd(mem(rax, r8, 1), xmm1) vmovsd(mem(rax, r8, 2), xmm2) add(imm(1*8), rax) // a += 1*cs_b = 1*8; vmovsd(mem(rbx ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovsd(mem(rbx, r11, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovsd(mem(rbx, r11, 2), xmm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovsd(mem(rbx, r13, 1), xmm3) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 // ymm5 ymm8 ymm11 ymm14 // ymm6 ymm9 ymm12 ymm15 vhaddpd( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm7) vhaddpd( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) // xmm2[0] = sum(ymm10); xmm2[1] = sum(ymm13) vperm2f128(imm(0x20), ymm2, ymm0, ymm4 ) vhaddpd( ymm8, ymm5, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm14, ymm11, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm5 ) vhaddpd( ymm9, ymm6, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm15, ymm12, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm6 ) // ymm4 = sum(ymm4) sum(ymm7) sum(ymm10) sum(ymm13) // ymm5 = sum(ymm5) sum(ymm8) sum(ymm11) sum(ymm14) // ymm6 = sum(ymm6) sum(ymm9) sum(ymm12) sum(ymm15) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(ymm0, ymm5, ymm5) vmulpd(ymm0, ymm6, ymm6) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), ymm3, ymm4) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm5) vmovupd(ymm5, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm6) vmovupd(ymm6, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vmovupd(ymm5, mem(rcx)) add(rdi, rcx) vmovupd(ymm6, mem(rcx)) //add(rdi, rcx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rd_haswell_asm_2x4 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { #if 0 bli_dgemmsup_r_haswell_ref ( conja, conjb, m0, n0, k0, alpha, a, rs_a0, cs_a0, b, rs_b0, cs_b0, beta, c, rs_c0, cs_c0, data, cntx ); return; #endif //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b // initialize loop by pre-loading // a column of a. mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 7*8)) // prefetch c + 1*rs_c mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) // ---------------------------------- iteration 1 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) // ---------------------------------- iteration 2 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) // ---------------------------------- iteration 3 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rax ), xmm0) vmovsd(mem(rax, r8, 1), xmm1) add(imm(1*8), rax) // a += 1*cs_b = 1*8; vmovsd(mem(rbx ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovsd(mem(rbx, r11, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovsd(mem(rbx, r11, 2), xmm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovsd(mem(rbx, r13, 1), xmm3) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 // ymm5 ymm8 ymm11 ymm14 vhaddpd( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm7) vhaddpd( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) // xmm2[0] = sum(ymm10); xmm2[1] = sum(ymm13) vperm2f128(imm(0x20), ymm2, ymm0, ymm4 ) vhaddpd( ymm8, ymm5, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm14, ymm11, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm5 ) // ymm4 = sum(ymm4) sum(ymm7) sum(ymm10) sum(ymm13) // ymm5 = sum(ymm5) sum(ymm8) sum(ymm11) sum(ymm14) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(ymm0, ymm5, ymm5) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), ymm3, ymm4) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm5) vmovupd(ymm5, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vmovupd(ymm5, mem(rcx)) //add(rdi, rcx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rd_haswell_asm_1x4 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { #if 0 bli_dgemmsup_r_haswell_ref ( conja, conjb, m0, n0, k0, alpha, a, rs_a0, cs_a0, b, rs_b0, cs_b0, beta, c, rs_c0, cs_c0, data, cntx ); return; #endif //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; /* rrc: -------- -- -- -- | | | | -------- -- -- -- ... | | | | -------- += -- -- -- | | | | -------- | | | | -------- : -------- : */ // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b // initialize loop by pre-loading // a column of a. mov(var(c), rcx) // load address of c //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rax ), ymm0) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) // ---------------------------------- iteration 1 vmovupd(mem(rax ), ymm0) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) // ---------------------------------- iteration 2 vmovupd(mem(rax ), ymm0) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) // ---------------------------------- iteration 3 vmovupd(mem(rax ), ymm0) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) vmovupd(mem(rax ), ymm0) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rax ), xmm0) add(imm(1*8), rax) // a += 1*cs_b = 1*8; vmovsd(mem(rbx ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovsd(mem(rbx, r11, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovsd(mem(rbx, r11, 2), xmm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovsd(mem(rbx, r13, 1), xmm3) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vfmadd231pd(ymm0, ymm3, ymm13) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 vhaddpd( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm7) vhaddpd( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) // xmm2[0] = sum(ymm10); xmm2[1] = sum(ymm13) vperm2f128(imm(0x20), ymm2, ymm0, ymm4 ) // ymm4 = sum(ymm4) sum(ymm7) sum(ymm10) sum(ymm13) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), ymm3, ymm4) vmovupd(ymm4, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx)) //add(rdi, rcx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rd_haswell_asm_6x2 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { #if 0 bli_dgemmsup_r_haswell_ref ( conja, conjb, m0, n0, k0, alpha, a, rs_a0, cs_a0, b, rs_b0, cs_b0, beta, c, rs_c0, cs_c0, data, cntx ); return; #endif //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; /* rrc: -------- -- -- -- | | -------- -- -- -- ... | | -------- += -- -- -- | | -------- -- -- -- | | -------- -- -- -- : -------- -- -- -- : */ // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) //lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b // initialize loop by pre-loading // a column of a. mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) lea(mem(rcx, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 7*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 7*8)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 7*8)) // prefetch c + 3*rs_c prefetch(0, mem(rdx, rdi, 1, 7*8)) // prefetch c + 4*rs_c prefetch(0, mem(rdx, rdi, 2, 7*8)) // prefetch c + 5*rs_c mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovupd(mem(rax, r8, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) vmovupd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rax, r8, 4), ymm3) vfmadd231pd(ymm0, ymm3, ymm12) vfmadd231pd(ymm1, ymm3, ymm13) vmovupd(mem(rax, r15, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) // ---------------------------------- iteration 1 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovupd(mem(rax, r8, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) vmovupd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rax, r8, 4), ymm3) vfmadd231pd(ymm0, ymm3, ymm12) vfmadd231pd(ymm1, ymm3, ymm13) vmovupd(mem(rax, r15, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) // ---------------------------------- iteration 2 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovupd(mem(rax, r8, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) vmovupd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rax, r8, 4), ymm3) vfmadd231pd(ymm0, ymm3, ymm12) vfmadd231pd(ymm1, ymm3, ymm13) vmovupd(mem(rax, r15, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) // ---------------------------------- iteration 3 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovupd(mem(rax, r8, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) vmovupd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rax, r8, 4), ymm3) vfmadd231pd(ymm0, ymm3, ymm12) vfmadd231pd(ymm1, ymm3, ymm13) vmovupd(mem(rax, r15, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovupd(mem(rax, r8, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) vmovupd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rax, r8, 4), ymm3) vfmadd231pd(ymm0, ymm3, ymm12) vfmadd231pd(ymm1, ymm3, ymm13) vmovupd(mem(rax, r15, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rbx ), xmm0) vmovsd(mem(rbx, r11, 1), xmm1) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vmovsd(mem(rax ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovsd(mem(rax, r8, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovsd(mem(rax, r8, 2), xmm3) vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) vmovsd(mem(rax, r13, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovsd(mem(rax, r8, 4), xmm3) vfmadd231pd(ymm0, ymm3, ymm12) vfmadd231pd(ymm1, ymm3, ymm13) vmovsd(mem(rax, r15, 1), xmm3) add(imm(1*8), rax) // a += 1*cs_a = 1*8; vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm5 // ymm6 ymm7 // ymm8 ymm9 // ymm10 ymm11 // ymm12 ymm13 // ymm14 ymm15 vhaddpd( ymm5, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm4 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm5) vhaddpd( ymm7, ymm6, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm6 ) vhaddpd( ymm9, ymm8, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm8 ) vhaddpd( ymm11, ymm10, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm10 ) vhaddpd( ymm13, ymm12, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm12 ) vhaddpd( ymm15, ymm14, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm14 ) // xmm4 = sum(ymm4) sum(ymm5) // xmm6 = sum(ymm6) sum(ymm7) // xmm8 = sum(ymm8) sum(ymm9) // xmm10 = sum(ymm10) sum(ymm11) // xmm12 = sum(ymm12) sum(ymm13) // xmm14 = sum(ymm14) sum(ymm15) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(xmm0, xmm4, xmm4) // scale by alpha vmulpd(xmm0, xmm6, xmm6) vmulpd(xmm0, xmm8, xmm8) vmulpd(xmm0, xmm10, xmm10) vmulpd(xmm0, xmm12, xmm12) vmulpd(xmm0, xmm14, xmm14) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), xmm3, xmm4) vmovupd(xmm4, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), xmm3, xmm6) vmovupd(xmm6, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), xmm3, xmm8) vmovupd(xmm8, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), xmm3, xmm10) vmovupd(xmm10, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), xmm3, xmm12) vmovupd(xmm12, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), xmm3, xmm14) vmovupd(xmm14, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(xmm4, mem(rcx)) add(rdi, rcx) vmovupd(xmm6, mem(rcx)) add(rdi, rcx) vmovupd(xmm8, mem(rcx)) add(rdi, rcx) vmovupd(xmm10, mem(rcx)) add(rdi, rcx) vmovupd(xmm12, mem(rcx)) add(rdi, rcx) vmovupd(xmm14, mem(rcx)) //add(rdi, rcx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rd_haswell_asm_3x2 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { #if 0 bli_dgemmsup_r_haswell_ref ( conja, conjb, m0, n0, k0, alpha, a, rs_a0, cs_a0, b, rs_b0, cs_b0, beta, c, rs_c0, cs_c0, data, cntx ); return; #endif //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; /* rrc: -------- -- -- -- | | -------- -- -- -- ... | | -------- += -- -- -- | | -------- -- -- -- | | -------- -- -- -- : -------- -- -- -- : */ // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) //lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b // initialize loop by pre-loading // a column of a. mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) //lea(mem(rcx, rdi, 2), rdx) // //lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 7*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 7*8)) // prefetch c + 2*rs_c mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovupd(mem(rax, r8, 2), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) // ---------------------------------- iteration 1 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovupd(mem(rax, r8, 2), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) // ---------------------------------- iteration 2 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovupd(mem(rax, r8, 2), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) // ---------------------------------- iteration 3 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovupd(mem(rax, r8, 2), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovupd(mem(rax, r8, 2), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rbx ), xmm0) vmovsd(mem(rbx, r11, 1), xmm1) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vmovsd(mem(rax ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovsd(mem(rax, r8, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovsd(mem(rax, r8, 2), xmm3) add(imm(1*8), rax) // a += 1*cs_a = 1*8; vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm5 // ymm6 ymm7 // ymm8 ymm9 vhaddpd( ymm5, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm4 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm5) vhaddpd( ymm7, ymm6, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm6 ) vhaddpd( ymm9, ymm8, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm8 ) // xmm4 = sum(ymm4) sum(ymm5) // xmm6 = sum(ymm6) sum(ymm7) // xmm8 = sum(ymm8) sum(ymm9) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(xmm0, xmm4, xmm4) // scale by alpha vmulpd(xmm0, xmm6, xmm6) vmulpd(xmm0, xmm8, xmm8) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), xmm3, xmm4) vmovupd(xmm4, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), xmm3, xmm6) vmovupd(xmm6, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), xmm3, xmm8) vmovupd(xmm8, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(xmm4, mem(rcx)) add(rdi, rcx) vmovupd(xmm6, mem(rcx)) add(rdi, rcx) vmovupd(xmm8, mem(rcx)) //add(rdi, rcx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rd_haswell_asm_2x2 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { #if 0 bli_dgemmsup_r_haswell_ref ( conja, conjb, m0, n0, k0, alpha, a, rs_a0, cs_a0, b, rs_b0, cs_b0, beta, c, rs_c0, cs_c0, data, cntx ); return; #endif //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; /* rrc: -------- -- -- -- | | -------- -- -- -- ... | | -------- += -- -- -- | | -------- -- -- -- | | -------- -- -- -- : -------- -- -- -- : */ // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) //lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b // initialize loop by pre-loading // a column of a. mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) //lea(mem(rcx, rdi, 2), rdx) // //lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 7*8)) // prefetch c + 1*rs_c mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) // ---------------------------------- iteration 1 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) // ---------------------------------- iteration 2 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) // ---------------------------------- iteration 3 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rbx ), xmm0) vmovsd(mem(rbx, r11, 1), xmm1) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vmovsd(mem(rax ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovsd(mem(rax, r8, 1), xmm3) add(imm(1*8), rax) // a += 1*cs_a = 1*8; vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm5 // ymm6 ymm7 vhaddpd( ymm5, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm4 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm5) vhaddpd( ymm7, ymm6, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm6 ) // xmm4 = sum(ymm4) sum(ymm5) // xmm6 = sum(ymm6) sum(ymm7) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(xmm0, xmm4, xmm4) // scale by alpha vmulpd(xmm0, xmm6, xmm6) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), xmm3, xmm4) vmovupd(xmm4, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), xmm3, xmm6) vmovupd(xmm6, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(xmm4, mem(rcx)) add(rdi, rcx) vmovupd(xmm6, mem(rcx)) //add(rdi, rcx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rd_haswell_asm_1x2 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { #if 0 bli_dgemmsup_r_haswell_ref ( conja, conjb, m0, n0, k0, alpha, a, rs_a0, cs_a0, b, rs_b0, cs_b0, beta, c, rs_c0, cs_c0, data, cntx ); return; #endif //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; /* rrc: -------- -- -- -- | | -------- -- -- -- ... | | -------- += -- -- -- | | -------- -- -- -- | | -------- -- -- -- : -------- -- -- -- : */ // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. //mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a //lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) //lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b // initialize loop by pre-loading // a column of a. mov(var(c), rcx) // load address of c //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) //lea(mem(rcx, rdi, 2), rdx) // //lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) // ---------------------------------- iteration 1 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) // ---------------------------------- iteration 2 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) // ---------------------------------- iteration 3 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rbx ), xmm0) vmovsd(mem(rbx, r11, 1), xmm1) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vmovsd(mem(rax ), xmm3) add(imm(1*8), rax) // a += 1*cs_a = 1*8; vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm5 vhaddpd( ymm5, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm4 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm5) // xmm4 = sum(ymm4) sum(ymm5) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(xmm0, xmm4, xmm4) // scale by alpha //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), xmm3, xmm4) vmovupd(xmm4, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(xmm4, mem(rcx)) //add(rdi, rcx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } blis-0.9.0/kernels/haswell/3/sup/old/bli_gemmsup_rd_haswell_asm_d6x8m.c000066400000000000000000004443601422157504600260640ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define BLIS_ASM_SYNTAX_ATT #include "bli_x86_asm_macros.h" /* rrc: -------- ------ | | | | | | | | -------- ------ | | | | | | | | -------- += ------ ... | | | | | | | | -------- ------ | | | | | | | | -------- ------ : -------- ------ : Assumptions: - C is row-stored and B is column-stored; - A is row-stored; - m0 and n0 are at most MR and NR, respectively. Therefore, this (r)ow-preferential microkernel is well-suited for a dot-product-based accumulation that performs vector loads from both A and B. */ // Prototype reference microkernels. GEMMSUP_KER_PROT( float, s, gemmsup_r_haswell_ref ) GEMMSUP_KER_PROT( double, d, gemmsup_r_haswell_ref ) GEMMSUP_KER_PROT( scomplex, c, gemmsup_r_haswell_ref ) GEMMSUP_KER_PROT( dcomplex, z, gemmsup_r_haswell_ref ) // Define parameters and variables for edge case kernel map. #define NUM_MR 4 #define NUM_NR 4 #define FUNCPTR_T dgemmsup_ker_ft #if 0 static dim_t mrs[NUM_MR] = { 6, 3, 2, 1 }; static dim_t nrs[NUM_NR] = { 8, 4, 2, 1 }; static FUNCPTR_T kmap[NUM_MR][NUM_NR] = { /* 8 4 2 1 */ /* 6 */ { bli_dgemmsup_rd_haswell_asm_6x8m, bli_dgemmsup_rd_haswell_asm_6x4m, bli_dgemmsup_rd_haswell_asm_6x2m, bli_dgemmsup_r_haswell_ref }, /* 3 */ { bli_dgemmsup_rd_haswell_asm_3x8m, bli_dgemmsup_rd_haswell_asm_3x4m, bli_dgemmsup_rd_haswell_asm_3x2m, bli_dgemmsup_r_haswell_ref }, /* 2 */ { bli_dgemmsup_rd_haswell_asm_2x8m, bli_dgemmsup_rd_haswell_asm_2x4m, bli_dgemmsup_rd_haswell_asm_2x2m, bli_dgemmsup_r_haswell_ref }, /* 1 */ { bli_dgemmsup_rd_haswell_asm_1x8m, bli_dgemmsup_rd_haswell_asm_1x4m, bli_dgemmsup_rd_haswell_asm_1x2m, bli_dgemmsup_r_haswell_ref } }; #endif void bli_dgemmsup_rd_haswell_asm_6x8m ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { uint64_t n_left = n0 % 8; // First check whether this is a edge case in the n dimension. If so, // dispatch other 6x?m kernels, as needed. if ( n_left ) { double* restrict cij = c; double* restrict bj = b; double* restrict ai = a; if ( 4 <= n_left ) { const dim_t nr_cur = 4; bli_dgemmsup_rd_haswell_asm_6x4m ( conja, conjb, m0, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 2 <= n_left ) { const dim_t nr_cur = 2; bli_dgemmsup_rd_haswell_asm_6x2m ( conja, conjb, m0, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 1 == n_left ) { #if 0 const dim_t nr_cur = 1; bli_dgemmsup_r_haswell_ref ( conja, conjb, m0, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); #else bli_dgemv_ex ( BLIS_NO_TRANSPOSE, conjb, m0, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, beta, cij, rs_c0, cntx, NULL ); #endif } return; } //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t m_iter = m0 / 3; uint64_t m_left = m0 % 3; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; if ( m_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. //mov(var(a), r14) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rdx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b lea(mem(r8, r8, 2), r10) // r10 = 3*rs_a //mov(var(c), r12) // load address of c //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) // r12 = rcx = c // r14 = rax = a // rdx = rbx = b // r9 = m dim index ii // r15 = n dim index jj mov(imm(0), r15) // jj = 0; label(.DLOOP3X4J) // LOOP OVER jj = [ 0 1 ... ] mov(var(a), r14) // load address of a mov(var(c), r12) // load address of c lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(imm(1*8), rsi) // rsi *= cs_c = 1*8 lea(mem(r12, rsi, 1), r12) // r12 = c + 4*jj*cs_c; lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(r11, rsi) // rsi *= cs_b; lea(mem(rdx, rsi, 1), rdx) // rbx = b + 4*jj*cs_b; mov(var(m_iter), r9) // ii = m_iter; label(.DLOOP3X4I) // LOOP OVER ii = [ m_iter ... 1 0 ] #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm5, ymm5, ymm5) vxorpd(ymm6, ymm6, ymm6) vxorpd(ymm7, ymm7, ymm7) vxorpd(ymm8, ymm8, ymm8) vxorpd(ymm9, ymm9, ymm9) vxorpd(ymm10, ymm10, ymm10) vxorpd(ymm11, ymm11, ymm11) vxorpd(ymm12, ymm12, ymm12) vxorpd(ymm13, ymm13, ymm13) vxorpd(ymm14, ymm14, ymm14) vxorpd(ymm15, ymm15, ymm15) #endif lea(mem(r12), rcx) // rcx = c_iijj; lea(mem(r14), rax) // rax = a_ii; lea(mem(rdx), rbx) // rbx = b_jj; #if 0 mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 3*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 3*8)) // prefetch c + 2*rs_c #endif lea(mem(r8, r8, 4), rdi) // rdi = 5*rs_a mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rdi, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 1 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rdi, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 3 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) #if 1 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rdi, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rax ), xmm0) vmovsd(mem(rax, r8, 1), xmm1) vmovsd(mem(rax, r8, 2), xmm2) add(imm(1*8), rax) // a += 1*cs_b = 1*8; vmovsd(mem(rbx ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovsd(mem(rbx, r11, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovsd(mem(rbx, r11, 2), xmm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovsd(mem(rbx, r13, 1), xmm3) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 // ymm5 ymm8 ymm11 ymm14 // ymm6 ymm9 ymm12 ymm15 vhaddpd( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm7) vhaddpd( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) // xmm2[0] = sum(ymm10); xmm2[1] = sum(ymm13) vperm2f128(imm(0x20), ymm2, ymm0, ymm4 ) vhaddpd( ymm8, ymm5, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm14, ymm11, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm5 ) vhaddpd( ymm9, ymm6, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm15, ymm12, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm6 ) // ymm4 = sum(ymm4) sum(ymm7) sum(ymm10) sum(ymm13) // ymm5 = sum(ymm5) sum(ymm8) sum(ymm11) sum(ymm14) // ymm6 = sum(ymm6) sum(ymm9) sum(ymm12) sum(ymm15) mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(ymm0, ymm5, ymm5) vmulpd(ymm0, ymm6, ymm6) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), ymm3, ymm4) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm5) vmovupd(ymm5, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm6) vmovupd(ymm6, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vmovupd(ymm5, mem(rcx)) add(rdi, rcx) vmovupd(ymm6, mem(rcx)) //add(rdi, rcx) label(.DDONE) lea(mem(r12, rdi, 2), r12) // lea(mem(r12, rdi, 1), r12) // c_ii = r12 += 3*rs_c lea(mem(r14, r8, 2), r14) // lea(mem(r14, r8, 1), r14) // a_ii = r14 += 3*rs_a dec(r9) // ii -= 1; jne(.DLOOP3X4I) // iterate again if ii != 0. add(imm(4), r15) // jj += 4; cmp(imm(4), r15) // compare jj to 4 jle(.DLOOP3X4J) // if jj <= 4, jump to beginning // of jj loop; otherwise, loop ends. label(.DRETURN) end_asm( : // output operands (none) : // input operands [m_iter] "m" (m_iter), [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the m dimension, if they exist. if ( m_left ) { const dim_t nr_cur = 8; const dim_t i_edge = m0 - ( dim_t )m_left; double* restrict cij = c + i_edge*rs_c; double* restrict bj = b; double* restrict ai = a + i_edge*rs_a; if ( 2 == m_left ) { const dim_t mr_cur = 2; bli_dgemmsup_rd_haswell_asm_2x8m ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); //cij += mr_cur*rs_c0; ai += mr_cur*rs_a0; m_left -= mr_cur; } if ( 1 == m_left ) { const dim_t mr_cur = 1; bli_dgemmsup_rd_haswell_asm_1x8m ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); } } } void bli_dgemmsup_rd_haswell_asm_3x8m ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), r14) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rdx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) // r12 = rcx = c // r14 = rax = a // rdx = rbx = b // r9 = unused // r15 = n dim index jj // r10 = unused mov(imm(0), r15) // jj = 0; label(.DLOOP3X4J) // LOOP OVER jj = [ 0 1 ... ] #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm5, ymm5, ymm5) vxorpd(ymm6, ymm6, ymm6) vxorpd(ymm7, ymm7, ymm7) vxorpd(ymm8, ymm8, ymm8) vxorpd(ymm9, ymm9, ymm9) vxorpd(ymm10, ymm10, ymm10) vxorpd(ymm11, ymm11, ymm11) vxorpd(ymm12, ymm12, ymm12) vxorpd(ymm13, ymm13, ymm13) vxorpd(ymm14, ymm14, ymm14) vxorpd(ymm15, ymm15, ymm15) #endif lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(imm(1*8), rsi) // rsi *= cs_c = 1*8 lea(mem(r12, rsi, 1), rcx) // rcx = c + 4*jj*cs_c; lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(r11, rsi) // rsi *= cs_b; lea(mem(rdx, rsi, 1), rbx) // rbx = b + 4*jj*cs_b; lea(mem(r14), rax) // rax = a; #if 0 prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 7*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 7*8)) // prefetch c + 2*rs_c #else prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 3*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 3*8)) // prefetch c + 2*rs_c #endif mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 1 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 2 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 3 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rax ), xmm0) vmovsd(mem(rax, r8, 1), xmm1) vmovsd(mem(rax, r8, 2), xmm2) add(imm(1*8), rax) // a += 1*cs_b = 1*8; vmovsd(mem(rbx ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovsd(mem(rbx, r11, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovsd(mem(rbx, r11, 2), xmm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovsd(mem(rbx, r13, 1), xmm3) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 // ymm5 ymm8 ymm11 ymm14 // ymm6 ymm9 ymm12 ymm15 vhaddpd( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm7) vhaddpd( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) // xmm2[0] = sum(ymm10); xmm2[1] = sum(ymm13) vperm2f128(imm(0x20), ymm2, ymm0, ymm4 ) vhaddpd( ymm8, ymm5, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm14, ymm11, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm5 ) vhaddpd( ymm9, ymm6, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm15, ymm12, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm6 ) // ymm4 = sum(ymm4) sum(ymm7) sum(ymm10) sum(ymm13) // ymm5 = sum(ymm5) sum(ymm8) sum(ymm11) sum(ymm14) // ymm6 = sum(ymm6) sum(ymm9) sum(ymm12) sum(ymm15) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(ymm0, ymm5, ymm5) vmulpd(ymm0, ymm6, ymm6) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), ymm3, ymm4) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm5) vmovupd(ymm5, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm6) vmovupd(ymm6, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vmovupd(ymm5, mem(rcx)) add(rdi, rcx) vmovupd(ymm6, mem(rcx)) //add(rdi, rcx) label(.DDONE) add(imm(4), r15) // jj += 4; cmp(imm(4), r15) // compare jj to 4 jle(.DLOOP3X4J) // if jj <= 4, jump to beginning // of jj loop; otherwise, loop ends. label(.DRETURN) end_asm( : // output operands (none) : // input operands [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rd_haswell_asm_2x8m ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), r14) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rdx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) // r12 = rcx = c // r14 = rax = a // rdx = rbx = b // r9 = unused // r15 = n dim index jj // r10 = unused mov(imm(0), r15) // jj = 0; label(.DLOOP3X4J) // LOOP OVER jj = [ 0 1 ... ] #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm5, ymm5, ymm5) vxorpd(ymm7, ymm7, ymm7) vxorpd(ymm8, ymm8, ymm8) vxorpd(ymm10, ymm10, ymm10) vxorpd(ymm11, ymm11, ymm11) vxorpd(ymm13, ymm13, ymm13) vxorpd(ymm14, ymm14, ymm14) #endif lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(imm(1*8), rsi) // rsi *= cs_c = 1*8 lea(mem(r12, rsi, 1), rcx) // rcx = c + 4*jj*cs_c; lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(r11, rsi) // rsi *= cs_b; lea(mem(rdx, rsi, 1), rbx) // rbx = b + 4*jj*cs_b; lea(mem(r14), rax) // rax = a; #if 0 prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 7*8)) // prefetch c + 1*rs_c #else prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 3*8)) // prefetch c + 1*rs_c #endif mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) // ---------------------------------- iteration 1 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) // ---------------------------------- iteration 2 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) // ---------------------------------- iteration 3 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rax ), xmm0) vmovsd(mem(rax, r8, 1), xmm1) add(imm(1*8), rax) // a += 1*cs_b = 1*8; vmovsd(mem(rbx ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovsd(mem(rbx, r11, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovsd(mem(rbx, r11, 2), xmm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovsd(mem(rbx, r13, 1), xmm3) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 // ymm5 ymm8 ymm11 ymm14 vhaddpd( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm7) vhaddpd( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) // xmm2[0] = sum(ymm10); xmm2[1] = sum(ymm13) vperm2f128(imm(0x20), ymm2, ymm0, ymm4 ) vhaddpd( ymm8, ymm5, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm14, ymm11, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm5 ) // ymm4 = sum(ymm4) sum(ymm7) sum(ymm10) sum(ymm13) // ymm5 = sum(ymm5) sum(ymm8) sum(ymm11) sum(ymm14) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(ymm0, ymm5, ymm5) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), ymm3, ymm4) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm5) vmovupd(ymm5, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vmovupd(ymm5, mem(rcx)) //add(rdi, rcx) label(.DDONE) add(imm(4), r15) // jj += 4; cmp(imm(4), r15) // compare jj to 4 jle(.DLOOP3X4J) // if jj <= 4, jump to beginning // of jj loop; otherwise, loop ends. label(.DRETURN) end_asm( : // output operands (none) : // input operands [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rd_haswell_asm_1x8m ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), r14) // load address of a. //mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a //lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rdx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b mov(var(c), r12) // load address of c //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) // r12 = rcx = c // r14 = rax = a // rdx = rbx = b // r9 = m dim index ii // r15 = n dim index jj mov(imm(0), r15) // jj = 0; label(.DLOOP3X4J) // LOOP OVER jj = [ 0 1 ... ] #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm7, ymm7, ymm7) vxorpd(ymm10, ymm10, ymm10) vxorpd(ymm13, ymm13, ymm13) #endif lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(imm(1*8), rsi) // rsi *= cs_c = 1*8 lea(mem(r12, rsi, 1), rcx) // rcx = c + 4*jj*cs_c; lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(r11, rsi) // rsi *= cs_b; lea(mem(rdx, rsi, 1), rbx) // rbx = b + 4*jj*cs_b; lea(mem(r14), rax) // rax = a; #if 0 prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c #else prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c #endif mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rax ), ymm0) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) // ---------------------------------- iteration 1 vmovupd(mem(rax ), ymm0) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) // ---------------------------------- iteration 2 vmovupd(mem(rax ), ymm0) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) // ---------------------------------- iteration 3 vmovupd(mem(rax ), ymm0) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) vmovupd(mem(rax ), ymm0) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rax ), xmm0) add(imm(1*8), rax) // a += 1*cs_b = 1*8; vmovsd(mem(rbx ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovsd(mem(rbx, r11, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovsd(mem(rbx, r11, 2), xmm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovsd(mem(rbx, r13, 1), xmm3) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vfmadd231pd(ymm0, ymm3, ymm13) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 vhaddpd( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm7) vhaddpd( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) // xmm2[0] = sum(ymm10); xmm2[1] = sum(ymm13) vperm2f128(imm(0x20), ymm2, ymm0, ymm4 ) // ymm4 = sum(ymm4) sum(ymm7) sum(ymm10) sum(ymm13) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), ymm3, ymm4) vmovupd(ymm4, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx)) //add(rdi, rcx) label(.DDONE) add(imm(4), r15) // jj += 4; cmp(imm(4), r15) // compare jj to 4 jle(.DLOOP3X4J) // if jj <= 4, jump to beginning // of jj loop; otherwise, loop ends. label(.DRETURN) end_asm( : // output operands (none) : // input operands [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rd_haswell_asm_6x4m ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t m_iter = m0 / 3; uint64_t m_left = m0 % 3; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; if ( m_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), r14) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rdx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b lea(mem(r8, r8, 2), r10) // r10 = 3*rs_a mov(var(c), r12) // load address of c //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) // r12 = rcx = c // r14 = rax = a // rdx = rbx = b // r9 = m dim index ii // r15 = n dim index jj // r10 = unused mov(var(m_iter), r9) // ii = m_iter; label(.DLOOP3X4I) // LOOP OVER ii = [ m_iter .. 1 0 ] #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm5, ymm5, ymm5) vxorpd(ymm6, ymm6, ymm6) vxorpd(ymm7, ymm7, ymm7) vxorpd(ymm8, ymm8, ymm8) vxorpd(ymm9, ymm9, ymm9) vxorpd(ymm10, ymm10, ymm10) vxorpd(ymm11, ymm11, ymm11) vxorpd(ymm12, ymm12, ymm12) vxorpd(ymm13, ymm13, ymm13) vxorpd(ymm14, ymm14, ymm14) vxorpd(ymm15, ymm15, ymm15) #endif lea(mem(r12), rcx) // rcx = c + 3*ii*rs_c; lea(mem(r14), rax) // rax = a + 3*ii*rs_a; lea(mem(rdx), rbx) // rbx = b; #if 0 mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 3*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 3*8)) // prefetch c + 2*rs_c #endif lea(mem(r8, r8, 4), rdi) // rdi = 5*rs_a mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rdi, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 1 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rdi, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 3 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rax ), xmm0) vmovsd(mem(rax, r8, 1), xmm1) vmovsd(mem(rax, r8, 2), xmm2) add(imm(1*8), rax) // a += 1*cs_b = 1*8; vmovsd(mem(rbx ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovsd(mem(rbx, r11, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovsd(mem(rbx, r11, 2), xmm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovsd(mem(rbx, r13, 1), xmm3) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 // ymm5 ymm8 ymm11 ymm14 // ymm6 ymm9 ymm12 ymm15 vhaddpd( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm7) vhaddpd( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) // xmm2[0] = sum(ymm10); xmm2[1] = sum(ymm13) vperm2f128(imm(0x20), ymm2, ymm0, ymm4 ) vhaddpd( ymm8, ymm5, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm14, ymm11, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm5 ) vhaddpd( ymm9, ymm6, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm15, ymm12, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm6 ) // ymm4 = sum(ymm4) sum(ymm7) sum(ymm10) sum(ymm13) // ymm5 = sum(ymm5) sum(ymm8) sum(ymm11) sum(ymm14) // ymm6 = sum(ymm6) sum(ymm9) sum(ymm12) sum(ymm15) mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(ymm0, ymm5, ymm5) vmulpd(ymm0, ymm6, ymm6) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), ymm3, ymm4) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm5) vmovupd(ymm5, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm6) vmovupd(ymm6, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vmovupd(ymm5, mem(rcx)) add(rdi, rcx) vmovupd(ymm6, mem(rcx)) //add(rdi, rcx) label(.DDONE) lea(mem(r12, rdi, 2), r12) // lea(mem(r12, rdi, 1), r12) // c_ii = r12 += 3*rs_c lea(mem(r14, r8, 2), r14) // lea(mem(r14, r8, 1), r14) // a_ii = r14 += 3*rs_a dec(r9) // ii -= 1; jne(.DLOOP3X4I) // iterate again if ii != 0. label(.DRETURN) end_asm( : // output operands (none) : // input operands [m_iter] "m" (m_iter), [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the m dimension, if they exist. if ( m_left ) { const dim_t nr_cur = 4; const dim_t i_edge = m0 - ( dim_t )m_left; double* restrict cij = c + i_edge*rs_c; double* restrict bj = b; double* restrict ai = a + i_edge*rs_a; if ( 2 == m_left ) { const dim_t mr_cur = 2; bli_dgemmsup_rd_haswell_asm_2x4m ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); //cij += mr_cur*rs_c0; ai += mr_cur*rs_a0; m_left -= mr_cur; } if ( 1 == m_left ) { const dim_t mr_cur = 1; bli_dgemmsup_rd_haswell_asm_1x4m ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); } } } void bli_dgemmsup_rd_haswell_asm_3x4m ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm5, ymm5, ymm5) vxorpd(ymm6, ymm6, ymm6) vxorpd(ymm7, ymm7, ymm7) vxorpd(ymm8, ymm8, ymm8) vxorpd(ymm9, ymm9, ymm9) vxorpd(ymm10, ymm10, ymm10) vxorpd(ymm11, ymm11, ymm11) vxorpd(ymm12, ymm12, ymm12) vxorpd(ymm13, ymm13, ymm13) vxorpd(ymm14, ymm14, ymm14) vxorpd(ymm15, ymm15, ymm15) #endif mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 3*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 3*8)) // prefetch c + 2*rs_c mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 1 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 2 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 3 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rax ), xmm0) vmovsd(mem(rax, r8, 1), xmm1) vmovsd(mem(rax, r8, 2), xmm2) add(imm(1*8), rax) // a += 1*cs_b = 1*8; vmovsd(mem(rbx ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovsd(mem(rbx, r11, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovsd(mem(rbx, r11, 2), xmm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovsd(mem(rbx, r13, 1), xmm3) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 // ymm5 ymm8 ymm11 ymm14 // ymm6 ymm9 ymm12 ymm15 vhaddpd( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm7) vhaddpd( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) // xmm2[0] = sum(ymm10); xmm2[1] = sum(ymm13) vperm2f128(imm(0x20), ymm2, ymm0, ymm4 ) vhaddpd( ymm8, ymm5, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm14, ymm11, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm5 ) vhaddpd( ymm9, ymm6, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm15, ymm12, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm6 ) // ymm4 = sum(ymm4) sum(ymm7) sum(ymm10) sum(ymm13) // ymm5 = sum(ymm5) sum(ymm8) sum(ymm11) sum(ymm14) // ymm6 = sum(ymm6) sum(ymm9) sum(ymm12) sum(ymm15) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(ymm0, ymm5, ymm5) vmulpd(ymm0, ymm6, ymm6) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), ymm3, ymm4) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm5) vmovupd(ymm5, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm6) vmovupd(ymm6, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vmovupd(ymm5, mem(rcx)) add(rdi, rcx) vmovupd(ymm6, mem(rcx)) //add(rdi, rcx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rd_haswell_asm_2x4m ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm5, ymm5, ymm5) vxorpd(ymm7, ymm7, ymm7) vxorpd(ymm8, ymm8, ymm8) vxorpd(ymm10, ymm10, ymm10) vxorpd(ymm11, ymm11, ymm11) vxorpd(ymm13, ymm13, ymm13) vxorpd(ymm14, ymm14, ymm14) #endif mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 3*8)) // prefetch c + 1*rs_c mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) // ---------------------------------- iteration 1 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) // ---------------------------------- iteration 2 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) // ---------------------------------- iteration 3 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rax ), xmm0) vmovsd(mem(rax, r8, 1), xmm1) add(imm(1*8), rax) // a += 1*cs_b = 1*8; vmovsd(mem(rbx ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovsd(mem(rbx, r11, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovsd(mem(rbx, r11, 2), xmm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovsd(mem(rbx, r13, 1), xmm3) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 // ymm5 ymm8 ymm11 ymm14 vhaddpd( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm7) vhaddpd( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) // xmm2[0] = sum(ymm10); xmm2[1] = sum(ymm13) vperm2f128(imm(0x20), ymm2, ymm0, ymm4 ) vhaddpd( ymm8, ymm5, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm14, ymm11, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm5 ) // ymm4 = sum(ymm4) sum(ymm7) sum(ymm10) sum(ymm13) // ymm5 = sum(ymm5) sum(ymm8) sum(ymm11) sum(ymm14) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(ymm0, ymm5, ymm5) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), ymm3, ymm4) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm5) vmovupd(ymm5, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vmovupd(ymm5, mem(rcx)) //add(rdi, rcx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rd_haswell_asm_1x4m ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; /* rrc: -------- -- -- -- | | | | -------- -- -- -- ... | | | | -------- += -- -- -- | | | | -------- | | | | -------- : -------- : */ // ------------------------------------------------------------------------- begin_asm() #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm7, ymm7, ymm7) vxorpd(ymm10, ymm10, ymm10) vxorpd(ymm13, ymm13, ymm13) #endif mov(var(a), rax) // load address of a. //mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a //lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b mov(var(c), rcx) // load address of c //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rax ), ymm0) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) // ---------------------------------- iteration 1 vmovupd(mem(rax ), ymm0) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) // ---------------------------------- iteration 2 vmovupd(mem(rax ), ymm0) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) // ---------------------------------- iteration 3 vmovupd(mem(rax ), ymm0) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) vmovupd(mem(rax ), ymm0) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rax ), xmm0) add(imm(1*8), rax) // a += 1*cs_b = 1*8; vmovsd(mem(rbx ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovsd(mem(rbx, r11, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovsd(mem(rbx, r11, 2), xmm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovsd(mem(rbx, r13, 1), xmm3) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vfmadd231pd(ymm0, ymm3, ymm13) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 vhaddpd( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm7) vhaddpd( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) // xmm2[0] = sum(ymm10); xmm2[1] = sum(ymm13) vperm2f128(imm(0x20), ymm2, ymm0, ymm4 ) // ymm4 = sum(ymm4) sum(ymm7) sum(ymm10) sum(ymm13) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), ymm3, ymm4) vmovupd(ymm4, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx)) //add(rdi, rcx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rd_haswell_asm_6x2m ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t m_iter = m0 / 6; uint64_t m_left = m0 % 6; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; if ( m_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), r14) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rdx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) //lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) // r12 = rcx = c // r14 = rax = a // rdx = rbx = b // r9 = m dim index ii mov(var(m_iter), r9) // ii = m_iter; label(.DLOOP3X4I) // LOOP OVER ii = [ m_iter ... 1 0 ] #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm5, ymm5, ymm5) vxorpd(ymm6, ymm6, ymm6) vxorpd(ymm7, ymm7, ymm7) vxorpd(ymm8, ymm8, ymm8) vxorpd(ymm9, ymm9, ymm9) vxorpd(ymm10, ymm10, ymm10) vxorpd(ymm11, ymm11, ymm11) vxorpd(ymm12, ymm12, ymm12) vxorpd(ymm13, ymm13, ymm13) vxorpd(ymm14, ymm14, ymm14) vxorpd(ymm15, ymm15, ymm15) #endif lea(mem(r12), rcx) // rcx = c + 6*ii*rs_c; lea(mem(r14), rax) // rax = a + 6*ii*rs_a; lea(mem(rdx), rbx) // rbx = b; lea(mem(rcx, rdi, 2), r10) // lea(mem(r10, rdi, 1), r10) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 1*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 1*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 1*8)) // prefetch c + 2*rs_c prefetch(0, mem(r10, 1*8)) // prefetch c + 3*rs_c prefetch(0, mem(r10, rdi, 1, 1*8)) // prefetch c + 4*rs_c prefetch(0, mem(r10, rdi, 2, 1*8)) // prefetch c + 5*rs_c mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovupd(mem(rax, r8, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) vmovupd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rax, r8, 4), ymm3) vfmadd231pd(ymm0, ymm3, ymm12) vfmadd231pd(ymm1, ymm3, ymm13) vmovupd(mem(rax, r15, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) // ---------------------------------- iteration 1 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovupd(mem(rax, r8, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) vmovupd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rax, r8, 4), ymm3) vfmadd231pd(ymm0, ymm3, ymm12) vfmadd231pd(ymm1, ymm3, ymm13) vmovupd(mem(rax, r15, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) // ---------------------------------- iteration 2 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovupd(mem(rax, r8, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) vmovupd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rax, r8, 4), ymm3) vfmadd231pd(ymm0, ymm3, ymm12) vfmadd231pd(ymm1, ymm3, ymm13) vmovupd(mem(rax, r15, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) // ---------------------------------- iteration 3 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovupd(mem(rax, r8, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) vmovupd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rax, r8, 4), ymm3) vfmadd231pd(ymm0, ymm3, ymm12) vfmadd231pd(ymm1, ymm3, ymm13) vmovupd(mem(rax, r15, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovupd(mem(rax, r8, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) vmovupd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rax, r8, 4), ymm3) vfmadd231pd(ymm0, ymm3, ymm12) vfmadd231pd(ymm1, ymm3, ymm13) vmovupd(mem(rax, r15, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rbx ), xmm0) vmovsd(mem(rbx, r11, 1), xmm1) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vmovsd(mem(rax ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovsd(mem(rax, r8, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovsd(mem(rax, r8, 2), xmm3) vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) vmovsd(mem(rax, r13, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovsd(mem(rax, r8, 4), xmm3) vfmadd231pd(ymm0, ymm3, ymm12) vfmadd231pd(ymm1, ymm3, ymm13) vmovsd(mem(rax, r15, 1), xmm3) add(imm(1*8), rax) // a += 1*cs_a = 1*8; vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm5 // ymm6 ymm7 // ymm8 ymm9 // ymm10 ymm11 // ymm12 ymm13 // ymm14 ymm15 vhaddpd( ymm5, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm4 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm5) vhaddpd( ymm7, ymm6, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm6 ) vhaddpd( ymm9, ymm8, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm8 ) vhaddpd( ymm11, ymm10, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm10 ) vhaddpd( ymm13, ymm12, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm12 ) vhaddpd( ymm15, ymm14, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm14 ) // xmm4 = sum(ymm4) sum(ymm5) // xmm6 = sum(ymm6) sum(ymm7) // xmm8 = sum(ymm8) sum(ymm9) // xmm10 = sum(ymm10) sum(ymm11) // xmm12 = sum(ymm12) sum(ymm13) // xmm14 = sum(ymm14) sum(ymm15) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(xmm0, xmm4, xmm4) // scale by alpha vmulpd(xmm0, xmm6, xmm6) vmulpd(xmm0, xmm8, xmm8) vmulpd(xmm0, xmm10, xmm10) vmulpd(xmm0, xmm12, xmm12) vmulpd(xmm0, xmm14, xmm14) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), xmm3, xmm4) vmovupd(xmm4, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), xmm3, xmm6) vmovupd(xmm6, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), xmm3, xmm8) vmovupd(xmm8, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), xmm3, xmm10) vmovupd(xmm10, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), xmm3, xmm12) vmovupd(xmm12, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), xmm3, xmm14) vmovupd(xmm14, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(xmm4, mem(rcx)) add(rdi, rcx) vmovupd(xmm6, mem(rcx)) add(rdi, rcx) vmovupd(xmm8, mem(rcx)) add(rdi, rcx) vmovupd(xmm10, mem(rcx)) add(rdi, rcx) vmovupd(xmm12, mem(rcx)) add(rdi, rcx) vmovupd(xmm14, mem(rcx)) //add(rdi, rcx) label(.DDONE) lea(mem(r12, rdi, 4), r12) // lea(mem(r12, rdi, 2), r12) // c_ii = r12 += 6*rs_c lea(mem(r14, r8, 4), r14) // lea(mem(r14, r8, 2), r14) // a_ii = r14 += 6*rs_a dec(r9) // ii -= 1; jne(.DLOOP3X4I) // iterate again if ii != 0. label(.DRETURN) end_asm( : // output operands (none) : // input operands [m_iter] "m" (m_iter), [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the m dimension, if they exist. if ( m_left ) { const dim_t nr_cur = 2; const dim_t i_edge = m0 - ( dim_t )m_left; double* restrict cij = c + i_edge*rs_c; double* restrict bj = b; double* restrict ai = a + i_edge*rs_a; if ( 3 <= m_left ) { const dim_t mr_cur = 3; bli_dgemmsup_rd_haswell_asm_3x2m ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += mr_cur*rs_c0; ai += mr_cur*rs_a0; m_left -= mr_cur; } if ( 2 <= m_left ) { const dim_t mr_cur = 2; bli_dgemmsup_rd_haswell_asm_2x2m ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += mr_cur*rs_c0; ai += mr_cur*rs_a0; m_left -= mr_cur; } if ( 1 == m_left ) { const dim_t mr_cur = 1; bli_dgemmsup_rd_haswell_asm_1x2m ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); } } } void bli_dgemmsup_rd_haswell_asm_3x2m ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm5, ymm5, ymm5) vxorpd(ymm6, ymm6, ymm6) vxorpd(ymm7, ymm7, ymm7) vxorpd(ymm8, ymm8, ymm8) vxorpd(ymm9, ymm9, ymm9) #endif mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) //lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b // initialize loop by pre-loading // a column of a. mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) prefetch(0, mem(rcx, 1*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 1*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 1*8)) // prefetch c + 2*rs_c mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovupd(mem(rax, r8, 2), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) // ---------------------------------- iteration 1 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovupd(mem(rax, r8, 2), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) // ---------------------------------- iteration 2 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovupd(mem(rax, r8, 2), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) // ---------------------------------- iteration 3 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovupd(mem(rax, r8, 2), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovupd(mem(rax, r8, 2), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rbx ), xmm0) vmovsd(mem(rbx, r11, 1), xmm1) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vmovsd(mem(rax ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovsd(mem(rax, r8, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovsd(mem(rax, r8, 2), xmm3) add(imm(1*8), rax) // a += 1*cs_a = 1*8; vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm5 // ymm6 ymm7 // ymm8 ymm9 vhaddpd( ymm5, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm4 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm5) vhaddpd( ymm7, ymm6, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm6 ) vhaddpd( ymm9, ymm8, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm8 ) // xmm4 = sum(ymm4) sum(ymm5) // xmm6 = sum(ymm6) sum(ymm7) // xmm8 = sum(ymm8) sum(ymm9) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(xmm0, xmm4, xmm4) // scale by alpha vmulpd(xmm0, xmm6, xmm6) vmulpd(xmm0, xmm8, xmm8) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), xmm3, xmm4) vmovupd(xmm4, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), xmm3, xmm6) vmovupd(xmm6, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), xmm3, xmm8) vmovupd(xmm8, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(xmm4, mem(rcx)) add(rdi, rcx) vmovupd(xmm6, mem(rcx)) add(rdi, rcx) vmovupd(xmm8, mem(rcx)) //add(rdi, rcx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rd_haswell_asm_2x2m ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; /* rrc: -------- -- -- -- | | -------- -- -- -- ... | | -------- += -- -- -- | | -------- -- -- -- | | -------- -- -- -- : -------- -- -- -- : */ // ------------------------------------------------------------------------- begin_asm() #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm5, ymm5, ymm5) vxorpd(ymm6, ymm6, ymm6) vxorpd(ymm7, ymm7, ymm7) #endif mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) //lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b // initialize loop by pre-loading // a column of a. mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) //lea(mem(rcx, rdi, 2), rdx) // //lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 1*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 1*8)) // prefetch c + 1*rs_c mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) // ---------------------------------- iteration 1 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) // ---------------------------------- iteration 2 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) // ---------------------------------- iteration 3 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rbx ), xmm0) vmovsd(mem(rbx, r11, 1), xmm1) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vmovsd(mem(rax ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovsd(mem(rax, r8, 1), xmm3) add(imm(1*8), rax) // a += 1*cs_a = 1*8; vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm5 // ymm6 ymm7 vhaddpd( ymm5, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm4 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm5) vhaddpd( ymm7, ymm6, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm6 ) // xmm4 = sum(ymm4) sum(ymm5) // xmm6 = sum(ymm6) sum(ymm7) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(xmm0, xmm4, xmm4) // scale by alpha vmulpd(xmm0, xmm6, xmm6) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), xmm3, xmm4) vmovupd(xmm4, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), xmm3, xmm6) vmovupd(xmm6, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(xmm4, mem(rcx)) add(rdi, rcx) vmovupd(xmm6, mem(rcx)) //add(rdi, rcx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rd_haswell_asm_1x2m ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; /* rrc: -------- -- -- -- | | -------- -- -- -- ... | | -------- += -- -- -- | | -------- -- -- -- | | -------- -- -- -- : -------- -- -- -- : */ // ------------------------------------------------------------------------- begin_asm() #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm5, ymm5, ymm5) #endif mov(var(a), rax) // load address of a. //mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a //lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) //lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b // initialize loop by pre-loading // a column of a. mov(var(c), rcx) // load address of c //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) //lea(mem(rcx, rdi, 2), rdx) // //lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 1*8)) // prefetch c + 0*rs_c mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) // ---------------------------------- iteration 1 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) // ---------------------------------- iteration 2 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) // ---------------------------------- iteration 3 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rbx ), xmm0) vmovsd(mem(rbx, r11, 1), xmm1) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vmovsd(mem(rax ), xmm3) add(imm(1*8), rax) // a += 1*cs_a = 1*8; vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm5 vhaddpd( ymm5, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm4 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm5) // xmm4 = sum(ymm4) sum(ymm5) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(xmm0, xmm4, xmm4) // scale by alpha //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), xmm3, xmm4) vmovupd(xmm4, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(xmm4, mem(rcx)) //add(rdi, rcx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } blis-0.9.0/kernels/haswell/3/sup/old/bli_gemmsup_rd_haswell_asm_d6x8m.c.newji000066400000000000000000004465211422157504600272000ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define BLIS_ASM_SYNTAX_ATT #include "bli_x86_asm_macros.h" /* rrc: -------- ------ | | | | | | | | -------- ------ | | | | | | | | -------- += ------ ... | | | | | | | | -------- ------ | | | | | | | | -------- ------ : -------- ------ : Assumptions: - C is row-stored and B is column-stored; - A is row-stored; - m0 and n0 are at most MR and NR, respectively. Therefore, this (r)ow-preferential microkernel is well-suited for a dot-product-based accumulation that performs vector loads from both A and B. */ // Prototype reference microkernels. GEMMSUP_KER_PROT( float, s, gemmsup_r_haswell_ref ) GEMMSUP_KER_PROT( double, d, gemmsup_r_haswell_ref ) GEMMSUP_KER_PROT( scomplex, c, gemmsup_r_haswell_ref ) GEMMSUP_KER_PROT( dcomplex, z, gemmsup_r_haswell_ref ) // Define parameters and variables for edge case kernel map. #define NUM_MR 4 #define NUM_NR 4 #define FUNCPTR_T dgemmsup_ker_ft #if 0 static dim_t mrs[NUM_MR] = { 6, 3, 2, 1 }; static dim_t nrs[NUM_NR] = { 8, 4, 2, 1 }; static FUNCPTR_T kmap[NUM_MR][NUM_NR] = { /* 8 4 2 1 */ /* 6 */ { bli_dgemmsup_rd_haswell_asm_6x8m, bli_dgemmsup_rd_haswell_asm_6x4m, bli_dgemmsup_rd_haswell_asm_6x2m, bli_dgemmsup_r_haswell_ref }, /* 3 */ { bli_dgemmsup_rd_haswell_asm_3x8m, bli_dgemmsup_rd_haswell_asm_3x4m, bli_dgemmsup_rd_haswell_asm_3x2m, bli_dgemmsup_r_haswell_ref }, /* 2 */ { bli_dgemmsup_rd_haswell_asm_2x8m, bli_dgemmsup_rd_haswell_asm_2x4m, bli_dgemmsup_rd_haswell_asm_2x2m, bli_dgemmsup_r_haswell_ref }, /* 1 */ { bli_dgemmsup_rd_haswell_asm_1x8m, bli_dgemmsup_rd_haswell_asm_1x4m, bli_dgemmsup_rd_haswell_asm_1x2m, bli_dgemmsup_r_haswell_ref } }; #endif void bli_dgemmsup_rd_haswell_asm_6x8m ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { uint64_t n_left = n0 % 8; // First check whether this is a edge case in the n dimension. If so, // dispatch other 6x?m kernels, as needed. if ( n_left ) { double* restrict cij = c; double* restrict bj = b; double* restrict ai = a; if ( 4 <= n_left ) { const dim_t nr_cur = 4; bli_dgemmsup_rd_haswell_asm_6x4m ( conja, conjb, m0, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 2 <= n_left ) { const dim_t nr_cur = 2; bli_dgemmsup_rd_haswell_asm_6x2m ( conja, conjb, m0, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 1 == n_left ) { #if 0 const dim_t nr_cur = 1; bli_dgemmsup_r_haswell_ref ( conja, conjb, m0, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); #else bli_dgemv_ex ( BLIS_NO_TRANSPOSE, conjb, m0, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, beta, cij, rs_c0, cntx, NULL ); #endif } return; } //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t m_iter = m0 / 3; uint64_t m_left = m0 % 3; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; if ( m_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. //mov(var(a), r14) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rdx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b lea(mem(r8, r8, 2), r10) // r10 = 3*rs_a //mov(var(c), r12) // load address of c //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) // r12 = rcx = c // r14 = rax = a // rdx = rbx = b // r9 = m dim index ii // r15 = n dim index jj // r10 = unused mov(imm(0), r15) // jj = 0; label(.DLOOP3X4J) // LOOP OVER jj = [ 0 1 ... ] mov(var(a), r14) // load address of a mov(var(c), r12) // load address of c lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(imm(1*8), rsi) // rsi *= cs_c = 1*8 lea(mem(r12, rsi, 1), r12) // r12 = c + 4*jj*cs_c; lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(r11, rsi) // rsi *= cs_b; lea(mem(rdx, rsi, 1), rdx) // rbx = b + 4*jj*cs_b; mov(var(m_iter), r9) // ii = m_iter; label(.DLOOP3X4I) // LOOP OVER ii = [ m_iter ... 1 0 ] #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm5, ymm5, ymm5) vxorpd(ymm6, ymm6, ymm6) vxorpd(ymm7, ymm7, ymm7) vxorpd(ymm8, ymm8, ymm8) vxorpd(ymm9, ymm9, ymm9) vxorpd(ymm10, ymm10, ymm10) vxorpd(ymm11, ymm11, ymm11) vxorpd(ymm12, ymm12, ymm12) vxorpd(ymm13, ymm13, ymm13) vxorpd(ymm14, ymm14, ymm14) vxorpd(ymm15, ymm15, ymm15) #endif lea(mem(r12), rcx) // rcx = c_iijj; lea(mem(r14), rax) // rax = a_ii; lea(mem(rdx), rbx) // rbx = b_jj; #if 0 mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 3*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 3*8)) // prefetch c + 2*rs_c #endif lea(mem(r8, r8, 4), rdi) // rdi = 5*rs_a mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rdi, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 1 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rdi, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 3 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rax ), xmm0) vmovsd(mem(rax, r8, 1), xmm1) vmovsd(mem(rax, r8, 2), xmm2) add(imm(1*8), rax) // a += 1*cs_b = 1*8; vmovsd(mem(rbx ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovsd(mem(rbx, r11, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovsd(mem(rbx, r11, 2), xmm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovsd(mem(rbx, r13, 1), xmm3) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 // ymm5 ymm8 ymm11 ymm14 // ymm6 ymm9 ymm12 ymm15 vhaddpd( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm7) vhaddpd( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) // xmm2[0] = sum(ymm10); xmm2[1] = sum(ymm13) vperm2f128(imm(0x20), ymm2, ymm0, ymm4 ) vhaddpd( ymm8, ymm5, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm14, ymm11, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm5 ) vhaddpd( ymm9, ymm6, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm15, ymm12, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm6 ) // ymm4 = sum(ymm4) sum(ymm7) sum(ymm10) sum(ymm13) // ymm5 = sum(ymm5) sum(ymm8) sum(ymm11) sum(ymm14) // ymm6 = sum(ymm6) sum(ymm9) sum(ymm12) sum(ymm15) mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(ymm0, ymm5, ymm5) vmulpd(ymm0, ymm6, ymm6) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), ymm3, ymm4) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm5) vmovupd(ymm5, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm6) vmovupd(ymm6, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vmovupd(ymm5, mem(rcx)) add(rdi, rcx) vmovupd(ymm6, mem(rcx)) //add(rdi, rcx) label(.DDONE) lea(mem(r12, rdi, 2), r12) // lea(mem(r12, rdi, 1), r12) // c_ii = r12 += 3*rs_c lea(mem(r14, r8, 2), r14) // lea(mem(r14, r8, 1), r14) // a_ii = r14 += 3*rs_a dec(r9) // ii -= 1; jne(.DLOOP3X4I) // iterate again if ii != 0. add(imm(4), r15) // jj += 4; cmp(imm(4), r15) // compare jj to 4 jle(.DLOOP3X4J) // if jj <= 4, jump to beginning // of jj loop; otherwise, loop ends. label(.DRETURN) end_asm( : // output operands (none) : // input operands [m_iter] "m" (m_iter), [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the m dimension, if they exist. if ( m_left ) { const dim_t nr_cur = 8; const dim_t i_edge = m0 - ( dim_t )m_left; double* restrict cij = c + i_edge*rs_c; double* restrict bj = b; double* restrict ai = a + i_edge*rs_a; if ( 2 == m_left ) { const dim_t mr_cur = 2; bli_dgemmsup_rd_haswell_asm_2x8m ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); //cij += mr_cur*rs_c0; ai += mr_cur*rs_a0; m_left -= mr_cur; } if ( 1 == m_left ) { const dim_t mr_cur = 1; bli_dgemmsup_rd_haswell_asm_1x8m ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); } } } void bli_dgemmsup_rd_haswell_asm_3x8m ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { #if 0 bli_dgemmsup_r_haswell_ref ( conja, conjb, m0, n0, k0, alpha, a, rs_a0, cs_a0, b, rs_b0, cs_b0, beta, c, rs_c0, cs_c0, data, cntx ); return; #endif //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), r14) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rdx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) // r12 = rcx = c // r14 = rax = a // rdx = rbx = b // r9 = unused // r15 = n dim index jj // r10 = unused mov(imm(0), r15) // jj = 0; label(.DLOOP3X4J) // LOOP OVER jj = [ 0 1 ... ] #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm5, ymm5, ymm5) vxorpd(ymm6, ymm6, ymm6) vxorpd(ymm7, ymm7, ymm7) vxorpd(ymm8, ymm8, ymm8) vxorpd(ymm9, ymm9, ymm9) vxorpd(ymm10, ymm10, ymm10) vxorpd(ymm11, ymm11, ymm11) vxorpd(ymm12, ymm12, ymm12) vxorpd(ymm13, ymm13, ymm13) vxorpd(ymm14, ymm14, ymm14) vxorpd(ymm15, ymm15, ymm15) #endif lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(imm(1*8), rsi) // rsi *= cs_c = 1*8 lea(mem(r12, rsi, 1), rcx) // rcx = c + 4*jj*cs_c; lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(r11, rsi) // rsi *= cs_b; lea(mem(rdx, rsi, 1), rbx) // rbx = b + 4*jj*cs_b; lea(mem(r14), rax) // rax = a; #if 0 prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 7*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 7*8)) // prefetch c + 2*rs_c #else prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 3*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 3*8)) // prefetch c + 2*rs_c #endif mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 1 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 2 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 3 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rax ), xmm0) vmovsd(mem(rax, r8, 1), xmm1) vmovsd(mem(rax, r8, 2), xmm2) add(imm(1*8), rax) // a += 1*cs_b = 1*8; vmovsd(mem(rbx ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovsd(mem(rbx, r11, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovsd(mem(rbx, r11, 2), xmm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovsd(mem(rbx, r13, 1), xmm3) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 // ymm5 ymm8 ymm11 ymm14 // ymm6 ymm9 ymm12 ymm15 vhaddpd( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm7) vhaddpd( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) // xmm2[0] = sum(ymm10); xmm2[1] = sum(ymm13) vperm2f128(imm(0x20), ymm2, ymm0, ymm4 ) vhaddpd( ymm8, ymm5, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm14, ymm11, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm5 ) vhaddpd( ymm9, ymm6, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm15, ymm12, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm6 ) // ymm4 = sum(ymm4) sum(ymm7) sum(ymm10) sum(ymm13) // ymm5 = sum(ymm5) sum(ymm8) sum(ymm11) sum(ymm14) // ymm6 = sum(ymm6) sum(ymm9) sum(ymm12) sum(ymm15) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(ymm0, ymm5, ymm5) vmulpd(ymm0, ymm6, ymm6) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), ymm3, ymm4) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm5) vmovupd(ymm5, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm6) vmovupd(ymm6, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vmovupd(ymm5, mem(rcx)) add(rdi, rcx) vmovupd(ymm6, mem(rcx)) //add(rdi, rcx) label(.DDONE) add(imm(4), r15) // jj += 4; cmp(imm(4), r15) // compare jj to 4 jle(.DLOOP3X4J) // if jj <= 4, jump to beginning // of jj loop; otherwise, loop ends. label(.DRETURN) end_asm( : // output operands (none) : // input operands [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rd_haswell_asm_2x8m ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { #if 0 bli_dgemmsup_r_haswell_ref ( conja, conjb, m0, n0, k0, alpha, a, rs_a0, cs_a0, b, rs_b0, cs_b0, beta, c, rs_c0, cs_c0, data, cntx ); return; #endif //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), r14) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rdx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) // r12 = rcx = c // r14 = rax = a // rdx = rbx = b // r9 = unused // r15 = n dim index jj // r10 = unused mov(imm(0), r15) // jj = 0; label(.DLOOP3X4J) // LOOP OVER jj = [ 0 1 ... ] #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm5, ymm5, ymm5) vxorpd(ymm7, ymm7, ymm7) vxorpd(ymm8, ymm8, ymm8) vxorpd(ymm10, ymm10, ymm10) vxorpd(ymm11, ymm11, ymm11) vxorpd(ymm13, ymm13, ymm13) vxorpd(ymm14, ymm14, ymm14) #endif lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(imm(1*8), rsi) // rsi *= cs_c = 1*8 lea(mem(r12, rsi, 1), rcx) // rcx = c + 4*jj*cs_c; lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(r11, rsi) // rsi *= cs_b; lea(mem(rdx, rsi, 1), rbx) // rbx = b + 4*jj*cs_b; lea(mem(r14), rax) // rax = a; #if 0 prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 7*8)) // prefetch c + 1*rs_c #else prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 3*8)) // prefetch c + 1*rs_c #endif mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) // ---------------------------------- iteration 1 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) // ---------------------------------- iteration 2 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) // ---------------------------------- iteration 3 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rax ), xmm0) vmovsd(mem(rax, r8, 1), xmm1) add(imm(1*8), rax) // a += 1*cs_b = 1*8; vmovsd(mem(rbx ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovsd(mem(rbx, r11, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovsd(mem(rbx, r11, 2), xmm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovsd(mem(rbx, r13, 1), xmm3) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 // ymm5 ymm8 ymm11 ymm14 vhaddpd( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm7) vhaddpd( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) // xmm2[0] = sum(ymm10); xmm2[1] = sum(ymm13) vperm2f128(imm(0x20), ymm2, ymm0, ymm4 ) vhaddpd( ymm8, ymm5, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm14, ymm11, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm5 ) // ymm4 = sum(ymm4) sum(ymm7) sum(ymm10) sum(ymm13) // ymm5 = sum(ymm5) sum(ymm8) sum(ymm11) sum(ymm14) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(ymm0, ymm5, ymm5) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), ymm3, ymm4) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm5) vmovupd(ymm5, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vmovupd(ymm5, mem(rcx)) //add(rdi, rcx) label(.DDONE) add(imm(4), r15) // jj += 4; cmp(imm(4), r15) // compare jj to 4 jle(.DLOOP3X4J) // if jj <= 4, jump to beginning // of jj loop; otherwise, loop ends. label(.DRETURN) end_asm( : // output operands (none) : // input operands [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rd_haswell_asm_1x8m ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { #if 0 bli_dgemmsup_r_haswell_ref ( conja, conjb, m0, n0, k0, alpha, a, rs_a0, cs_a0, b, rs_b0, cs_b0, beta, c, rs_c0, cs_c0, data, cntx ); return; #endif //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), r14) // load address of a. //mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a //lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rdx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b mov(var(c), r12) // load address of c //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) // r12 = rcx = c // r14 = rax = a // rdx = rbx = b // r9 = m dim index ii // r15 = n dim index jj mov(imm(0), r15) // jj = 0; label(.DLOOP3X4J) // LOOP OVER jj = [ 0 1 ... ] #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm7, ymm7, ymm7) vxorpd(ymm10, ymm10, ymm10) vxorpd(ymm13, ymm13, ymm13) #endif lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(imm(1*8), rsi) // rsi *= cs_c = 1*8 lea(mem(r12, rsi, 1), rcx) // rcx = c + 4*jj*cs_c; lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(r11, rsi) // rsi *= cs_b; lea(mem(rdx, rsi, 1), rbx) // rbx = b + 4*jj*cs_b; lea(mem(r14), rax) // rax = a; #if 0 prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c #else prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c #endif mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rax ), ymm0) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) // ---------------------------------- iteration 1 vmovupd(mem(rax ), ymm0) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) // ---------------------------------- iteration 2 vmovupd(mem(rax ), ymm0) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) // ---------------------------------- iteration 3 vmovupd(mem(rax ), ymm0) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) vmovupd(mem(rax ), ymm0) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rax ), xmm0) add(imm(1*8), rax) // a += 1*cs_b = 1*8; vmovsd(mem(rbx ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovsd(mem(rbx, r11, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovsd(mem(rbx, r11, 2), xmm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovsd(mem(rbx, r13, 1), xmm3) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vfmadd231pd(ymm0, ymm3, ymm13) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 vhaddpd( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm7) vhaddpd( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) // xmm2[0] = sum(ymm10); xmm2[1] = sum(ymm13) vperm2f128(imm(0x20), ymm2, ymm0, ymm4 ) // ymm4 = sum(ymm4) sum(ymm7) sum(ymm10) sum(ymm13) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), ymm3, ymm4) vmovupd(ymm4, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx)) //add(rdi, rcx) label(.DDONE) add(imm(4), r15) // jj += 4; cmp(imm(4), r15) // compare jj to 4 jle(.DLOOP3X4J) // if jj <= 4, jump to beginning // of jj loop; otherwise, loop ends. label(.DRETURN) end_asm( : // output operands (none) : // input operands [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rd_haswell_asm_6x4m ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { #if 0 bli_dgemmsup_r_haswell_ref ( conja, conjb, m0, n0, k0, alpha, a, rs_a0, cs_a0, b, rs_b0, cs_b0, beta, c, rs_c0, cs_c0, data, cntx ); return; #endif //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t m_iter = m0 / 3; uint64_t m_left = m0 % 3; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; if ( m_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), r14) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rdx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) // r12 = rcx = c // r14 = rax = a // rdx = rbx = b // r9 = m dim index ii // r15 = n dim index jj // r10 = unused mov(var(m_iter), r9) // ii = m_iter; label(.DLOOP3X4I) // LOOP OVER ii = [ m_iter .. 1 0 ] #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm5, ymm5, ymm5) vxorpd(ymm6, ymm6, ymm6) vxorpd(ymm7, ymm7, ymm7) vxorpd(ymm8, ymm8, ymm8) vxorpd(ymm9, ymm9, ymm9) vxorpd(ymm10, ymm10, ymm10) vxorpd(ymm11, ymm11, ymm11) vxorpd(ymm12, ymm12, ymm12) vxorpd(ymm13, ymm13, ymm13) vxorpd(ymm14, ymm14, ymm14) vxorpd(ymm15, ymm15, ymm15) #endif lea(mem(r12), rcx) // rcx = c + 3*ii*rs_c; lea(mem(r14), rax) // rax = a + 3*ii*rs_a; lea(mem(rdx), rbx) // rbx = b; #if 0 prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 7*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 7*8)) // prefetch c + 2*rs_c #else prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 3*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 3*8)) // prefetch c + 2*rs_c #endif mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 1 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 2 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 3 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rax ), xmm0) vmovsd(mem(rax, r8, 1), xmm1) vmovsd(mem(rax, r8, 2), xmm2) add(imm(1*8), rax) // a += 1*cs_b = 1*8; vmovsd(mem(rbx ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovsd(mem(rbx, r11, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovsd(mem(rbx, r11, 2), xmm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovsd(mem(rbx, r13, 1), xmm3) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 // ymm5 ymm8 ymm11 ymm14 // ymm6 ymm9 ymm12 ymm15 vhaddpd( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm7) vhaddpd( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) // xmm2[0] = sum(ymm10); xmm2[1] = sum(ymm13) vperm2f128(imm(0x20), ymm2, ymm0, ymm4 ) vhaddpd( ymm8, ymm5, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm14, ymm11, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm5 ) vhaddpd( ymm9, ymm6, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm15, ymm12, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm6 ) // ymm4 = sum(ymm4) sum(ymm7) sum(ymm10) sum(ymm13) // ymm5 = sum(ymm5) sum(ymm8) sum(ymm11) sum(ymm14) // ymm6 = sum(ymm6) sum(ymm9) sum(ymm12) sum(ymm15) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(ymm0, ymm5, ymm5) vmulpd(ymm0, ymm6, ymm6) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), ymm3, ymm4) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm5) vmovupd(ymm5, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm6) vmovupd(ymm6, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vmovupd(ymm5, mem(rcx)) add(rdi, rcx) vmovupd(ymm6, mem(rcx)) //add(rdi, rcx) label(.DDONE) lea(mem(r12, rdi, 2), r12) // lea(mem(r12, rdi, 1), r12) // c_ii = r12 += 3*rs_c lea(mem(r14, r8, 2), r14) // lea(mem(r14, r8, 1), r14) // a_ii = r14 += 3*rs_a dec(r9) // ii -= 1; jne(.DLOOP3X4I) // iterate again if ii != 0. label(.DRETURN) end_asm( : // output operands (none) : // input operands [m_iter] "m" (m_iter), [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the m dimension, if they exist. if ( m_left ) { const dim_t nr_cur = 4; const dim_t i_edge = m0 - ( dim_t )m_left; double* restrict cij = c + i_edge*rs_c; double* restrict bj = b; double* restrict ai = a + i_edge*rs_a; if ( 2 == m_left ) { const dim_t mr_cur = 2; bli_dgemmsup_rd_haswell_asm_2x4m ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); //cij += mr_cur*rs_c0; ai += mr_cur*rs_a0; m_left -= mr_cur; } if ( 1 == m_left ) { const dim_t mr_cur = 1; bli_dgemmsup_rd_haswell_asm_1x4m ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); } } } void bli_dgemmsup_rd_haswell_asm_3x4m ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { #if 0 bli_dgemmsup_r_haswell_ref ( conja, conjb, m0, n0, k0, alpha, a, rs_a0, cs_a0, b, rs_b0, cs_b0, beta, c, rs_c0, cs_c0, data, cntx ); return; #endif //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm5, ymm5, ymm5) vxorpd(ymm6, ymm6, ymm6) vxorpd(ymm7, ymm7, ymm7) vxorpd(ymm8, ymm8, ymm8) vxorpd(ymm9, ymm9, ymm9) vxorpd(ymm10, ymm10, ymm10) vxorpd(ymm11, ymm11, ymm11) vxorpd(ymm12, ymm12, ymm12) vxorpd(ymm13, ymm13, ymm13) vxorpd(ymm14, ymm14, ymm14) vxorpd(ymm15, ymm15, ymm15) #endif mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 3*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 3*8)) // prefetch c + 2*rs_c mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 1 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 2 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 3 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rax ), xmm0) vmovsd(mem(rax, r8, 1), xmm1) vmovsd(mem(rax, r8, 2), xmm2) add(imm(1*8), rax) // a += 1*cs_b = 1*8; vmovsd(mem(rbx ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovsd(mem(rbx, r11, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovsd(mem(rbx, r11, 2), xmm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovsd(mem(rbx, r13, 1), xmm3) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 // ymm5 ymm8 ymm11 ymm14 // ymm6 ymm9 ymm12 ymm15 vhaddpd( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm7) vhaddpd( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) // xmm2[0] = sum(ymm10); xmm2[1] = sum(ymm13) vperm2f128(imm(0x20), ymm2, ymm0, ymm4 ) vhaddpd( ymm8, ymm5, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm14, ymm11, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm5 ) vhaddpd( ymm9, ymm6, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm15, ymm12, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm6 ) // ymm4 = sum(ymm4) sum(ymm7) sum(ymm10) sum(ymm13) // ymm5 = sum(ymm5) sum(ymm8) sum(ymm11) sum(ymm14) // ymm6 = sum(ymm6) sum(ymm9) sum(ymm12) sum(ymm15) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(ymm0, ymm5, ymm5) vmulpd(ymm0, ymm6, ymm6) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), ymm3, ymm4) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm5) vmovupd(ymm5, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm6) vmovupd(ymm6, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vmovupd(ymm5, mem(rcx)) add(rdi, rcx) vmovupd(ymm6, mem(rcx)) //add(rdi, rcx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rd_haswell_asm_2x4m ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { #if 0 bli_dgemmsup_r_haswell_ref ( conja, conjb, m0, n0, k0, alpha, a, rs_a0, cs_a0, b, rs_b0, cs_b0, beta, c, rs_c0, cs_c0, data, cntx ); return; #endif //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm5, ymm5, ymm5) vxorpd(ymm7, ymm7, ymm7) vxorpd(ymm8, ymm8, ymm8) vxorpd(ymm10, ymm10, ymm10) vxorpd(ymm11, ymm11, ymm11) vxorpd(ymm13, ymm13, ymm13) vxorpd(ymm14, ymm14, ymm14) #endif mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 3*8)) // prefetch c + 1*rs_c mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) // ---------------------------------- iteration 1 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) // ---------------------------------- iteration 2 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) // ---------------------------------- iteration 3 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rax ), xmm0) vmovsd(mem(rax, r8, 1), xmm1) add(imm(1*8), rax) // a += 1*cs_b = 1*8; vmovsd(mem(rbx ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovsd(mem(rbx, r11, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovsd(mem(rbx, r11, 2), xmm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovsd(mem(rbx, r13, 1), xmm3) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 // ymm5 ymm8 ymm11 ymm14 vhaddpd( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm7) vhaddpd( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) // xmm2[0] = sum(ymm10); xmm2[1] = sum(ymm13) vperm2f128(imm(0x20), ymm2, ymm0, ymm4 ) vhaddpd( ymm8, ymm5, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm14, ymm11, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm5 ) // ymm4 = sum(ymm4) sum(ymm7) sum(ymm10) sum(ymm13) // ymm5 = sum(ymm5) sum(ymm8) sum(ymm11) sum(ymm14) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(ymm0, ymm5, ymm5) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), ymm3, ymm4) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm5) vmovupd(ymm5, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vmovupd(ymm5, mem(rcx)) //add(rdi, rcx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rd_haswell_asm_1x4m ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { #if 0 bli_dgemmsup_r_haswell_ref ( conja, conjb, m0, n0, k0, alpha, a, rs_a0, cs_a0, b, rs_b0, cs_b0, beta, c, rs_c0, cs_c0, data, cntx ); return; #endif //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; /* rrc: -------- -- -- -- | | | | -------- -- -- -- ... | | | | -------- += -- -- -- | | | | -------- | | | | -------- : -------- : */ // ------------------------------------------------------------------------- begin_asm() #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm7, ymm7, ymm7) vxorpd(ymm10, ymm10, ymm10) vxorpd(ymm13, ymm13, ymm13) #endif mov(var(a), rax) // load address of a. //mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a //lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b mov(var(c), rcx) // load address of c //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rax ), ymm0) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) // ---------------------------------- iteration 1 vmovupd(mem(rax ), ymm0) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) // ---------------------------------- iteration 2 vmovupd(mem(rax ), ymm0) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) // ---------------------------------- iteration 3 vmovupd(mem(rax ), ymm0) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) vmovupd(mem(rax ), ymm0) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rax ), xmm0) add(imm(1*8), rax) // a += 1*cs_b = 1*8; vmovsd(mem(rbx ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovsd(mem(rbx, r11, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovsd(mem(rbx, r11, 2), xmm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovsd(mem(rbx, r13, 1), xmm3) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vfmadd231pd(ymm0, ymm3, ymm13) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 vhaddpd( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm7) vhaddpd( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) // xmm2[0] = sum(ymm10); xmm2[1] = sum(ymm13) vperm2f128(imm(0x20), ymm2, ymm0, ymm4 ) // ymm4 = sum(ymm4) sum(ymm7) sum(ymm10) sum(ymm13) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), ymm3, ymm4) vmovupd(ymm4, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx)) //add(rdi, rcx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rd_haswell_asm_6x2m ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { #if 0 bli_dgemmsup_r_haswell_ref ( conja, conjb, m0, n0, k0, alpha, a, rs_a0, cs_a0, b, rs_b0, cs_b0, beta, c, rs_c0, cs_c0, data, cntx ); return; #endif //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t m_iter = m0 / 6; uint64_t m_left = m0 % 6; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; if ( m_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), r14) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rdx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) //lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) // r12 = rcx = c // r14 = rax = a // rdx = rbx = b // r9 = m dim index ii mov(var(m_iter), r9) // ii = m_iter; label(.DLOOP3X4I) // LOOP OVER ii = [ m_iter ... 1 0 ] #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm5, ymm5, ymm5) vxorpd(ymm6, ymm6, ymm6) vxorpd(ymm7, ymm7, ymm7) vxorpd(ymm8, ymm8, ymm8) vxorpd(ymm9, ymm9, ymm9) vxorpd(ymm10, ymm10, ymm10) vxorpd(ymm11, ymm11, ymm11) vxorpd(ymm12, ymm12, ymm12) vxorpd(ymm13, ymm13, ymm13) vxorpd(ymm14, ymm14, ymm14) vxorpd(ymm15, ymm15, ymm15) #endif lea(mem(r12), rcx) // rcx = c + 6*ii*rs_c; lea(mem(r14), rax) // rax = a + 6*ii*rs_a; lea(mem(rdx), rbx) // rbx = b; lea(mem(rcx, rdi, 2), r10) // lea(mem(r10, rdi, 1), r10) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 3*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 3*8)) // prefetch c + 2*rs_c prefetch(0, mem(r10, 3*8)) // prefetch c + 3*rs_c prefetch(0, mem(r10, rdi, 1, 3*8)) // prefetch c + 4*rs_c prefetch(0, mem(r10, rdi, 2, 3*8)) // prefetch c + 5*rs_c mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovupd(mem(rax, r8, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) vmovupd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rax, r8, 4), ymm3) vfmadd231pd(ymm0, ymm3, ymm12) vfmadd231pd(ymm1, ymm3, ymm13) vmovupd(mem(rax, r15, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) // ---------------------------------- iteration 1 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovupd(mem(rax, r8, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) vmovupd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rax, r8, 4), ymm3) vfmadd231pd(ymm0, ymm3, ymm12) vfmadd231pd(ymm1, ymm3, ymm13) vmovupd(mem(rax, r15, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) // ---------------------------------- iteration 2 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovupd(mem(rax, r8, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) vmovupd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rax, r8, 4), ymm3) vfmadd231pd(ymm0, ymm3, ymm12) vfmadd231pd(ymm1, ymm3, ymm13) vmovupd(mem(rax, r15, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) // ---------------------------------- iteration 3 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovupd(mem(rax, r8, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) vmovupd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rax, r8, 4), ymm3) vfmadd231pd(ymm0, ymm3, ymm12) vfmadd231pd(ymm1, ymm3, ymm13) vmovupd(mem(rax, r15, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovupd(mem(rax, r8, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) vmovupd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rax, r8, 4), ymm3) vfmadd231pd(ymm0, ymm3, ymm12) vfmadd231pd(ymm1, ymm3, ymm13) vmovupd(mem(rax, r15, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rbx ), xmm0) vmovsd(mem(rbx, r11, 1), xmm1) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vmovsd(mem(rax ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovsd(mem(rax, r8, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovsd(mem(rax, r8, 2), xmm3) vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) vmovsd(mem(rax, r13, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovsd(mem(rax, r8, 4), xmm3) vfmadd231pd(ymm0, ymm3, ymm12) vfmadd231pd(ymm1, ymm3, ymm13) vmovsd(mem(rax, r15, 1), xmm3) add(imm(1*8), rax) // a += 1*cs_a = 1*8; vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm5 // ymm6 ymm7 // ymm8 ymm9 // ymm10 ymm11 // ymm12 ymm13 // ymm14 ymm15 vhaddpd( ymm5, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm4 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm5) vhaddpd( ymm7, ymm6, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm6 ) vhaddpd( ymm9, ymm8, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm8 ) vhaddpd( ymm11, ymm10, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm10 ) vhaddpd( ymm13, ymm12, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm12 ) vhaddpd( ymm15, ymm14, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm14 ) // xmm4 = sum(ymm4) sum(ymm5) // xmm6 = sum(ymm6) sum(ymm7) // xmm8 = sum(ymm8) sum(ymm9) // xmm10 = sum(ymm10) sum(ymm11) // xmm12 = sum(ymm12) sum(ymm13) // xmm14 = sum(ymm14) sum(ymm15) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(xmm0, xmm4, xmm4) // scale by alpha vmulpd(xmm0, xmm6, xmm6) vmulpd(xmm0, xmm8, xmm8) vmulpd(xmm0, xmm10, xmm10) vmulpd(xmm0, xmm12, xmm12) vmulpd(xmm0, xmm14, xmm14) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), xmm3, xmm4) vmovupd(xmm4, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), xmm3, xmm6) vmovupd(xmm6, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), xmm3, xmm8) vmovupd(xmm8, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), xmm3, xmm10) vmovupd(xmm10, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), xmm3, xmm12) vmovupd(xmm12, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), xmm3, xmm14) vmovupd(xmm14, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(xmm4, mem(rcx)) add(rdi, rcx) vmovupd(xmm6, mem(rcx)) add(rdi, rcx) vmovupd(xmm8, mem(rcx)) add(rdi, rcx) vmovupd(xmm10, mem(rcx)) add(rdi, rcx) vmovupd(xmm12, mem(rcx)) add(rdi, rcx) vmovupd(xmm14, mem(rcx)) //add(rdi, rcx) label(.DDONE) lea(mem(r12, rdi, 4), r12) // lea(mem(r12, rdi, 2), r12) // c_ii = r12 += 6*rs_c lea(mem(r14, r8, 4), r14) // lea(mem(r14, r8, 2), r14) // a_ii = r14 += 6*rs_a dec(r9) // ii -= 1; jne(.DLOOP3X4I) // iterate again if ii != 0. label(.DRETURN) end_asm( : // output operands (none) : // input operands [m_iter] "m" (m_iter), [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the m dimension, if they exist. if ( m_left ) { const dim_t nr_cur = 2; const dim_t i_edge = m0 - ( dim_t )m_left; double* restrict cij = c + i_edge*rs_c; double* restrict bj = b; double* restrict ai = a + i_edge*rs_a; if ( 3 <= m_left ) { const dim_t mr_cur = 3; bli_dgemmsup_rd_haswell_asm_3x2m ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += mr_cur*rs_c0; ai += mr_cur*rs_a0; m_left -= mr_cur; } if ( 2 <= m_left ) { const dim_t mr_cur = 2; bli_dgemmsup_rd_haswell_asm_2x2m ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += mr_cur*rs_c0; ai += mr_cur*rs_a0; m_left -= mr_cur; } if ( 1 == m_left ) { const dim_t mr_cur = 1; bli_dgemmsup_rd_haswell_asm_1x2m ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); } } } void bli_dgemmsup_rd_haswell_asm_3x2m ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { #if 0 bli_dgemmsup_r_haswell_ref ( conja, conjb, m0, n0, k0, alpha, a, rs_a0, cs_a0, b, rs_b0, cs_b0, beta, c, rs_c0, cs_c0, data, cntx ); return; #endif //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm5, ymm5, ymm5) vxorpd(ymm6, ymm6, ymm6) vxorpd(ymm7, ymm7, ymm7) vxorpd(ymm8, ymm8, ymm8) vxorpd(ymm9, ymm9, ymm9) #endif mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) //lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b // initialize loop by pre-loading // a column of a. mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) prefetch(0, mem(rcx, 1*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 1*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 1*8)) // prefetch c + 2*rs_c mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovupd(mem(rax, r8, 2), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) // ---------------------------------- iteration 1 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovupd(mem(rax, r8, 2), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) // ---------------------------------- iteration 2 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovupd(mem(rax, r8, 2), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) // ---------------------------------- iteration 3 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovupd(mem(rax, r8, 2), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovupd(mem(rax, r8, 2), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rbx ), xmm0) vmovsd(mem(rbx, r11, 1), xmm1) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vmovsd(mem(rax ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovsd(mem(rax, r8, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovsd(mem(rax, r8, 2), xmm3) add(imm(1*8), rax) // a += 1*cs_a = 1*8; vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm5 // ymm6 ymm7 // ymm8 ymm9 vhaddpd( ymm5, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm4 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm5) vhaddpd( ymm7, ymm6, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm6 ) vhaddpd( ymm9, ymm8, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm8 ) // xmm4 = sum(ymm4) sum(ymm5) // xmm6 = sum(ymm6) sum(ymm7) // xmm8 = sum(ymm8) sum(ymm9) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(xmm0, xmm4, xmm4) // scale by alpha vmulpd(xmm0, xmm6, xmm6) vmulpd(xmm0, xmm8, xmm8) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), xmm3, xmm4) vmovupd(xmm4, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), xmm3, xmm6) vmovupd(xmm6, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), xmm3, xmm8) vmovupd(xmm8, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(xmm4, mem(rcx)) add(rdi, rcx) vmovupd(xmm6, mem(rcx)) add(rdi, rcx) vmovupd(xmm8, mem(rcx)) //add(rdi, rcx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rd_haswell_asm_2x2m ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { #if 0 bli_dgemmsup_r_haswell_ref ( conja, conjb, m0, n0, k0, alpha, a, rs_a0, cs_a0, b, rs_b0, cs_b0, beta, c, rs_c0, cs_c0, data, cntx ); return; #endif //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; /* rrc: -------- -- -- -- | | -------- -- -- -- ... | | -------- += -- -- -- | | -------- -- -- -- | | -------- -- -- -- : -------- -- -- -- : */ // ------------------------------------------------------------------------- begin_asm() #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm5, ymm5, ymm5) vxorpd(ymm6, ymm6, ymm6) vxorpd(ymm7, ymm7, ymm7) #endif mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) //lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b // initialize loop by pre-loading // a column of a. mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) //lea(mem(rcx, rdi, 2), rdx) // //lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 1*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 1*8)) // prefetch c + 1*rs_c mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) // ---------------------------------- iteration 1 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) // ---------------------------------- iteration 2 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) // ---------------------------------- iteration 3 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rbx ), xmm0) vmovsd(mem(rbx, r11, 1), xmm1) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vmovsd(mem(rax ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovsd(mem(rax, r8, 1), xmm3) add(imm(1*8), rax) // a += 1*cs_a = 1*8; vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm5 // ymm6 ymm7 vhaddpd( ymm5, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm4 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm5) vhaddpd( ymm7, ymm6, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm6 ) // xmm4 = sum(ymm4) sum(ymm5) // xmm6 = sum(ymm6) sum(ymm7) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(xmm0, xmm4, xmm4) // scale by alpha vmulpd(xmm0, xmm6, xmm6) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), xmm3, xmm4) vmovupd(xmm4, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), xmm3, xmm6) vmovupd(xmm6, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(xmm4, mem(rcx)) add(rdi, rcx) vmovupd(xmm6, mem(rcx)) //add(rdi, rcx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rd_haswell_asm_1x2m ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { #if 0 bli_dgemmsup_r_haswell_ref ( conja, conjb, m0, n0, k0, alpha, a, rs_a0, cs_a0, b, rs_b0, cs_b0, beta, c, rs_c0, cs_c0, data, cntx ); return; #endif //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; /* rrc: -------- -- -- -- | | -------- -- -- -- ... | | -------- += -- -- -- | | -------- -- -- -- | | -------- -- -- -- : -------- -- -- -- : */ // ------------------------------------------------------------------------- begin_asm() #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm5, ymm5, ymm5) #endif mov(var(a), rax) // load address of a. //mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a //lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) //lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b // initialize loop by pre-loading // a column of a. mov(var(c), rcx) // load address of c //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) //lea(mem(rcx, rdi, 2), rdx) // //lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 1*8)) // prefetch c + 0*rs_c mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) // ---------------------------------- iteration 1 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) // ---------------------------------- iteration 2 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) // ---------------------------------- iteration 3 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rbx ), xmm0) vmovsd(mem(rbx, r11, 1), xmm1) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vmovsd(mem(rax ), xmm3) add(imm(1*8), rax) // a += 1*cs_a = 1*8; vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm5 vhaddpd( ymm5, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm4 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm5) // xmm4 = sum(ymm4) sum(ymm5) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(xmm0, xmm4, xmm4) // scale by alpha //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), xmm3, xmm4) vmovupd(xmm4, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(xmm4, mem(rcx)) //add(rdi, rcx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } blis-0.9.0/kernels/haswell/3/sup/old/bli_gemmsup_rd_haswell_asm_d6x8m.c.worksij000066400000000000000000004471741422157504600275610ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define BLIS_ASM_SYNTAX_ATT #include "bli_x86_asm_macros.h" /* rrc: -------- ------ | | | | | | | | -------- ------ | | | | | | | | -------- += ------ ... | | | | | | | | -------- ------ | | | | | | | | -------- ------ : -------- ------ : Assumptions: - C is row-stored and B is column-stored; - A is row-stored; - m0 and n0 are at most MR and NR, respectively. Therefore, this (r)ow-preferential microkernel is well-suited for a dot-product-based accumulation that performs vector loads from both A and B. */ // Prototype reference microkernels. GEMMSUP_KER_PROT( float, s, gemmsup_r_haswell_ref ) GEMMSUP_KER_PROT( double, d, gemmsup_r_haswell_ref ) GEMMSUP_KER_PROT( scomplex, c, gemmsup_r_haswell_ref ) GEMMSUP_KER_PROT( dcomplex, z, gemmsup_r_haswell_ref ) // Define parameters and variables for edge case kernel map. #define NUM_MR 4 #define NUM_NR 4 #define FUNCPTR_T dgemmsup_ker_ft #if 0 static dim_t mrs[NUM_MR] = { 6, 3, 2, 1 }; static dim_t nrs[NUM_NR] = { 8, 4, 2, 1 }; static FUNCPTR_T kmap[NUM_MR][NUM_NR] = { /* 8 4 2 1 */ /* 6 */ { bli_dgemmsup_rd_haswell_asm_6x8m, bli_dgemmsup_rd_haswell_asm_6x4m, bli_dgemmsup_rd_haswell_asm_6x2m, bli_dgemmsup_r_haswell_ref }, /* 3 */ { bli_dgemmsup_rd_haswell_asm_3x8m, bli_dgemmsup_rd_haswell_asm_3x4m, bli_dgemmsup_rd_haswell_asm_3x2m, bli_dgemmsup_r_haswell_ref }, /* 2 */ { bli_dgemmsup_rd_haswell_asm_2x8m, bli_dgemmsup_rd_haswell_asm_2x4m, bli_dgemmsup_rd_haswell_asm_2x2m, bli_dgemmsup_r_haswell_ref }, /* 1 */ { bli_dgemmsup_rd_haswell_asm_1x8m, bli_dgemmsup_rd_haswell_asm_1x4m, bli_dgemmsup_rd_haswell_asm_1x2m, bli_dgemmsup_r_haswell_ref } }; #endif void bli_dgemmsup_rd_haswell_asm_6x8m ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { uint64_t n_left = n0 % 8; // First check whether this is a edge case in the n dimension. If so, // dispatch other 6x?m kernels, as needed. if ( n_left ) { double* restrict cij = c; double* restrict bj = b; double* restrict ai = a; if ( 4 <= n_left ) { const dim_t nr_cur = 4; bli_dgemmsup_rd_haswell_asm_6x4m ( conja, conjb, m0, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 2 <= n_left ) { const dim_t nr_cur = 2; bli_dgemmsup_rd_haswell_asm_6x2m ( conja, conjb, m0, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 1 == n_left ) { #if 0 const dim_t nr_cur = 1; bli_dgemmsup_r_haswell_ref ( conja, conjb, m0, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); #else bli_dgemv_ex ( BLIS_NO_TRANSPOSE, conjb, m0, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, beta, cij, rs_c0, cntx, NULL ); #endif } return; } //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t m_iter = m0 / 3; uint64_t m_left = m0 % 3; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; if ( m_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), r14) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rdx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b lea(mem(r8, r8, 2), r10) // r10 = 3*rs_a mov(var(c), r12) // load address of c //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) // r12 = rcx = c // r14 = rax = a // rdx = rbx = b // r9 = m dim index ii // r15 = n dim index jj mov(var(m_iter), r9) // ii = m_iter; label(.DLOOP3X4I) // LOOP OVER ii = [ m_iter ... 1 0 ] mov(imm(0), r15) // jj = 0; label(.DLOOP3X4J) // LOOP OVER jj = [ 0 1 ... ] #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm5, ymm5, ymm5) vxorpd(ymm6, ymm6, ymm6) vxorpd(ymm7, ymm7, ymm7) vxorpd(ymm8, ymm8, ymm8) vxorpd(ymm9, ymm9, ymm9) vxorpd(ymm10, ymm10, ymm10) vxorpd(ymm11, ymm11, ymm11) vxorpd(ymm12, ymm12, ymm12) vxorpd(ymm13, ymm13, ymm13) vxorpd(ymm14, ymm14, ymm14) vxorpd(ymm15, ymm15, ymm15) #endif lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(imm(1*8), rsi) // rsi *= cs_c = 1*8 lea(mem(r12, rsi, 1), rcx) // rcx = c + 4*jj*cs_c; lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(r11, rsi) // rsi *= cs_b; lea(mem(rdx, rsi, 1), rbx) // rbx = b + 4*jj*cs_b; lea(mem(r14), rax) // rax = a_ii; #if 0 mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 3*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 3*8)) // prefetch c + 2*rs_c #endif lea(mem(r8, r8, 4), rdi) // rdi = 5*rs_a mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rdi, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 1 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rdi, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 3 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rax ), xmm0) vmovsd(mem(rax, r8, 1), xmm1) vmovsd(mem(rax, r8, 2), xmm2) add(imm(1*8), rax) // a += 1*cs_b = 1*8; vmovsd(mem(rbx ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovsd(mem(rbx, r11, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovsd(mem(rbx, r11, 2), xmm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovsd(mem(rbx, r13, 1), xmm3) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 // ymm5 ymm8 ymm11 ymm14 // ymm6 ymm9 ymm12 ymm15 vhaddpd( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm7) vhaddpd( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) // xmm2[0] = sum(ymm10); xmm2[1] = sum(ymm13) vperm2f128(imm(0x20), ymm2, ymm0, ymm4 ) vhaddpd( ymm8, ymm5, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm14, ymm11, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm5 ) vhaddpd( ymm9, ymm6, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm15, ymm12, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm6 ) // ymm4 = sum(ymm4) sum(ymm7) sum(ymm10) sum(ymm13) // ymm5 = sum(ymm5) sum(ymm8) sum(ymm11) sum(ymm14) // ymm6 = sum(ymm6) sum(ymm9) sum(ymm12) sum(ymm15) mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(ymm0, ymm5, ymm5) vmulpd(ymm0, ymm6, ymm6) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), ymm3, ymm4) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm5) vmovupd(ymm5, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm6) vmovupd(ymm6, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vmovupd(ymm5, mem(rcx)) add(rdi, rcx) vmovupd(ymm6, mem(rcx)) //add(rdi, rcx) label(.DDONE) add(imm(4), r15) // jj += 4; cmp(imm(4), r15) // compare jj to 4 jle(.DLOOP3X4J) // if jj <= 4, jump to beginning // of jj loop; otherwise, loop ends. lea(mem(r12, rdi, 2), r12) // lea(mem(r12, rdi, 1), r12) // c_ii = r12 += 3*rs_c lea(mem(r14, r8, 2), r14) // lea(mem(r14, r8, 1), r14) // a_ii = r14 += 3*rs_a dec(r9) // ii -= 1; jne(.DLOOP3X4I) // iterate again if ii != 0. label(.DRETURN) end_asm( : // output operands (none) : // input operands [m_iter] "m" (m_iter), [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the m dimension, if they exist. if ( m_left ) { const dim_t nr_cur = 8; const dim_t i_edge = m0 - ( dim_t )m_left; double* restrict cij = c + i_edge*rs_c; double* restrict bj = b; double* restrict ai = a + i_edge*rs_a; if ( 2 == m_left ) { const dim_t mr_cur = 2; bli_dgemmsup_rd_haswell_asm_2x8m ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); //cij += mr_cur*rs_c0; ai += mr_cur*rs_a0; m_left -= mr_cur; } if ( 1 == m_left ) { const dim_t mr_cur = 1; bli_dgemmsup_rd_haswell_asm_1x8m ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); } } } void bli_dgemmsup_rd_haswell_asm_3x8m ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { #if 0 bli_dgemmsup_r_haswell_ref ( conja, conjb, m0, n0, k0, alpha, a, rs_a0, cs_a0, b, rs_b0, cs_b0, beta, c, rs_c0, cs_c0, data, cntx ); return; #endif //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), r14) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rdx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) // r12 = rcx = c // r14 = rax = a // rdx = rbx = b // r9 = unused // r15 = n dim index jj // r10 = unused mov(imm(0), r15) // jj = 0; label(.DLOOP3X4J) // LOOP OVER jj = [ 0 1 ... ] #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm5, ymm5, ymm5) vxorpd(ymm6, ymm6, ymm6) vxorpd(ymm7, ymm7, ymm7) vxorpd(ymm8, ymm8, ymm8) vxorpd(ymm9, ymm9, ymm9) vxorpd(ymm10, ymm10, ymm10) vxorpd(ymm11, ymm11, ymm11) vxorpd(ymm12, ymm12, ymm12) vxorpd(ymm13, ymm13, ymm13) vxorpd(ymm14, ymm14, ymm14) vxorpd(ymm15, ymm15, ymm15) #endif lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(imm(1*8), rsi) // rsi *= cs_c = 1*8 lea(mem(r12, rsi, 1), rcx) // rcx = c + 4*jj*cs_c; lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(r11, rsi) // rsi *= cs_b; lea(mem(rdx, rsi, 1), rbx) // rbx = b + 4*jj*cs_b; lea(mem(r14), rax) // rax = a; #if 0 prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 7*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 7*8)) // prefetch c + 2*rs_c #else prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 3*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 3*8)) // prefetch c + 2*rs_c #endif mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 1 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 2 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 3 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rax ), xmm0) vmovsd(mem(rax, r8, 1), xmm1) vmovsd(mem(rax, r8, 2), xmm2) add(imm(1*8), rax) // a += 1*cs_b = 1*8; vmovsd(mem(rbx ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovsd(mem(rbx, r11, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovsd(mem(rbx, r11, 2), xmm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovsd(mem(rbx, r13, 1), xmm3) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 // ymm5 ymm8 ymm11 ymm14 // ymm6 ymm9 ymm12 ymm15 vhaddpd( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm7) vhaddpd( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) // xmm2[0] = sum(ymm10); xmm2[1] = sum(ymm13) vperm2f128(imm(0x20), ymm2, ymm0, ymm4 ) vhaddpd( ymm8, ymm5, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm14, ymm11, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm5 ) vhaddpd( ymm9, ymm6, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm15, ymm12, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm6 ) // ymm4 = sum(ymm4) sum(ymm7) sum(ymm10) sum(ymm13) // ymm5 = sum(ymm5) sum(ymm8) sum(ymm11) sum(ymm14) // ymm6 = sum(ymm6) sum(ymm9) sum(ymm12) sum(ymm15) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(ymm0, ymm5, ymm5) vmulpd(ymm0, ymm6, ymm6) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), ymm3, ymm4) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm5) vmovupd(ymm5, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm6) vmovupd(ymm6, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vmovupd(ymm5, mem(rcx)) add(rdi, rcx) vmovupd(ymm6, mem(rcx)) //add(rdi, rcx) label(.DDONE) add(imm(4), r15) // jj += 4; cmp(imm(4), r15) // compare jj to 4 jle(.DLOOP3X4J) // if jj <= 4, jump to beginning // of jj loop; otherwise, loop ends. label(.DRETURN) end_asm( : // output operands (none) : // input operands [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rd_haswell_asm_2x8m ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { #if 0 bli_dgemmsup_r_haswell_ref ( conja, conjb, m0, n0, k0, alpha, a, rs_a0, cs_a0, b, rs_b0, cs_b0, beta, c, rs_c0, cs_c0, data, cntx ); return; #endif //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), r14) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rdx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) // r12 = rcx = c // r14 = rax = a // rdx = rbx = b // r9 = unused // r15 = n dim index jj // r10 = unused mov(imm(0), r15) // jj = 0; label(.DLOOP3X4J) // LOOP OVER jj = [ 0 1 ... ] #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm5, ymm5, ymm5) vxorpd(ymm7, ymm7, ymm7) vxorpd(ymm8, ymm8, ymm8) vxorpd(ymm10, ymm10, ymm10) vxorpd(ymm11, ymm11, ymm11) vxorpd(ymm13, ymm13, ymm13) vxorpd(ymm14, ymm14, ymm14) #endif lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(imm(1*8), rsi) // rsi *= cs_c = 1*8 lea(mem(r12, rsi, 1), rcx) // rcx = c + 4*jj*cs_c; lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(r11, rsi) // rsi *= cs_b; lea(mem(rdx, rsi, 1), rbx) // rbx = b + 4*jj*cs_b; lea(mem(r14), rax) // rax = a; #if 0 prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 7*8)) // prefetch c + 1*rs_c #else prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 3*8)) // prefetch c + 1*rs_c #endif mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) // ---------------------------------- iteration 1 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) // ---------------------------------- iteration 2 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) // ---------------------------------- iteration 3 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rax ), xmm0) vmovsd(mem(rax, r8, 1), xmm1) add(imm(1*8), rax) // a += 1*cs_b = 1*8; vmovsd(mem(rbx ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovsd(mem(rbx, r11, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovsd(mem(rbx, r11, 2), xmm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovsd(mem(rbx, r13, 1), xmm3) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 // ymm5 ymm8 ymm11 ymm14 vhaddpd( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm7) vhaddpd( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) // xmm2[0] = sum(ymm10); xmm2[1] = sum(ymm13) vperm2f128(imm(0x20), ymm2, ymm0, ymm4 ) vhaddpd( ymm8, ymm5, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm14, ymm11, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm5 ) // ymm4 = sum(ymm4) sum(ymm7) sum(ymm10) sum(ymm13) // ymm5 = sum(ymm5) sum(ymm8) sum(ymm11) sum(ymm14) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(ymm0, ymm5, ymm5) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), ymm3, ymm4) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm5) vmovupd(ymm5, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vmovupd(ymm5, mem(rcx)) //add(rdi, rcx) label(.DDONE) add(imm(4), r15) // jj += 4; cmp(imm(4), r15) // compare jj to 4 jle(.DLOOP3X4J) // if jj <= 4, jump to beginning // of jj loop; otherwise, loop ends. label(.DRETURN) end_asm( : // output operands (none) : // input operands [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rd_haswell_asm_1x8m ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { #if 0 bli_dgemmsup_r_haswell_ref ( conja, conjb, m0, n0, k0, alpha, a, rs_a0, cs_a0, b, rs_b0, cs_b0, beta, c, rs_c0, cs_c0, data, cntx ); return; #endif //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), r14) // load address of a. //mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a //lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rdx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b mov(var(c), r12) // load address of c //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) // r12 = rcx = c // r14 = rax = a // rdx = rbx = b // r9 = m dim index ii // r15 = n dim index jj mov(imm(0), r15) // jj = 0; label(.DLOOP3X4J) // LOOP OVER jj = [ 0 1 ... ] #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm7, ymm7, ymm7) vxorpd(ymm10, ymm10, ymm10) vxorpd(ymm13, ymm13, ymm13) #endif lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(imm(1*8), rsi) // rsi *= cs_c = 1*8 lea(mem(r12, rsi, 1), rcx) // rcx = c + 4*jj*cs_c; lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(r11, rsi) // rsi *= cs_b; lea(mem(rdx, rsi, 1), rbx) // rbx = b + 4*jj*cs_b; lea(mem(r14), rax) // rax = a; #if 0 prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c #else prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c #endif mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rax ), ymm0) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) // ---------------------------------- iteration 1 vmovupd(mem(rax ), ymm0) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) // ---------------------------------- iteration 2 vmovupd(mem(rax ), ymm0) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) // ---------------------------------- iteration 3 vmovupd(mem(rax ), ymm0) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) vmovupd(mem(rax ), ymm0) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rax ), xmm0) add(imm(1*8), rax) // a += 1*cs_b = 1*8; vmovsd(mem(rbx ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovsd(mem(rbx, r11, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovsd(mem(rbx, r11, 2), xmm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovsd(mem(rbx, r13, 1), xmm3) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vfmadd231pd(ymm0, ymm3, ymm13) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 vhaddpd( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm7) vhaddpd( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) // xmm2[0] = sum(ymm10); xmm2[1] = sum(ymm13) vperm2f128(imm(0x20), ymm2, ymm0, ymm4 ) // ymm4 = sum(ymm4) sum(ymm7) sum(ymm10) sum(ymm13) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), ymm3, ymm4) vmovupd(ymm4, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx)) //add(rdi, rcx) label(.DDONE) add(imm(4), r15) // jj += 4; cmp(imm(4), r15) // compare jj to 4 jle(.DLOOP3X4J) // if jj <= 4, jump to beginning // of jj loop; otherwise, loop ends. label(.DRETURN) end_asm( : // output operands (none) : // input operands [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rd_haswell_asm_6x4m ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { #if 0 bli_dgemmsup_r_haswell_ref ( conja, conjb, m0, n0, k0, alpha, a, rs_a0, cs_a0, b, rs_b0, cs_b0, beta, c, rs_c0, cs_c0, data, cntx ); return; #endif //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t m_iter = m0 / 3; uint64_t m_left = m0 % 3; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; if ( m_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), r14) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rdx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b lea(mem(r8, r8, 2), r10) // r10 = 3*rs_a mov(var(c), r12) // load address of c //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) // r12 = rcx = c // r14 = rax = a // rdx = rbx = b // r9 = m dim index ii // r15 = n dim index jj // r10 = unused mov(var(m_iter), r9) // ii = m_iter; label(.DLOOP3X4I) // LOOP OVER ii = [ m_iter .. 1 0 ] #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm5, ymm5, ymm5) vxorpd(ymm6, ymm6, ymm6) vxorpd(ymm7, ymm7, ymm7) vxorpd(ymm8, ymm8, ymm8) vxorpd(ymm9, ymm9, ymm9) vxorpd(ymm10, ymm10, ymm10) vxorpd(ymm11, ymm11, ymm11) vxorpd(ymm12, ymm12, ymm12) vxorpd(ymm13, ymm13, ymm13) vxorpd(ymm14, ymm14, ymm14) vxorpd(ymm15, ymm15, ymm15) #endif lea(mem(r12), rcx) // rcx = c + 3*ii*rs_c; lea(mem(r14), rax) // rax = a + 3*ii*rs_a; lea(mem(rdx), rbx) // rbx = b; #if 0 mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 3*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 3*8)) // prefetch c + 2*rs_c #endif lea(mem(r8, r8, 4), rdi) // rdi = 5*rs_a mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rdi, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 1 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rdi, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 3 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rax ), xmm0) vmovsd(mem(rax, r8, 1), xmm1) vmovsd(mem(rax, r8, 2), xmm2) add(imm(1*8), rax) // a += 1*cs_b = 1*8; vmovsd(mem(rbx ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovsd(mem(rbx, r11, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovsd(mem(rbx, r11, 2), xmm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovsd(mem(rbx, r13, 1), xmm3) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 // ymm5 ymm8 ymm11 ymm14 // ymm6 ymm9 ymm12 ymm15 vhaddpd( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm7) vhaddpd( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) // xmm2[0] = sum(ymm10); xmm2[1] = sum(ymm13) vperm2f128(imm(0x20), ymm2, ymm0, ymm4 ) vhaddpd( ymm8, ymm5, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm14, ymm11, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm5 ) vhaddpd( ymm9, ymm6, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm15, ymm12, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm6 ) // ymm4 = sum(ymm4) sum(ymm7) sum(ymm10) sum(ymm13) // ymm5 = sum(ymm5) sum(ymm8) sum(ymm11) sum(ymm14) // ymm6 = sum(ymm6) sum(ymm9) sum(ymm12) sum(ymm15) mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(ymm0, ymm5, ymm5) vmulpd(ymm0, ymm6, ymm6) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), ymm3, ymm4) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm5) vmovupd(ymm5, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm6) vmovupd(ymm6, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vmovupd(ymm5, mem(rcx)) add(rdi, rcx) vmovupd(ymm6, mem(rcx)) //add(rdi, rcx) label(.DDONE) lea(mem(r12, rdi, 2), r12) // lea(mem(r12, rdi, 1), r12) // c_ii = r12 += 3*rs_c lea(mem(r14, r8, 2), r14) // lea(mem(r14, r8, 1), r14) // a_ii = r14 += 3*rs_a dec(r9) // ii -= 1; jne(.DLOOP3X4I) // iterate again if ii != 0. label(.DRETURN) end_asm( : // output operands (none) : // input operands [m_iter] "m" (m_iter), [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the m dimension, if they exist. if ( m_left ) { const dim_t nr_cur = 4; const dim_t i_edge = m0 - ( dim_t )m_left; double* restrict cij = c + i_edge*rs_c; double* restrict bj = b; double* restrict ai = a + i_edge*rs_a; if ( 2 == m_left ) { const dim_t mr_cur = 2; bli_dgemmsup_rd_haswell_asm_2x4m ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); //cij += mr_cur*rs_c0; ai += mr_cur*rs_a0; m_left -= mr_cur; } if ( 1 == m_left ) { const dim_t mr_cur = 1; bli_dgemmsup_rd_haswell_asm_1x4m ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); } } } void bli_dgemmsup_rd_haswell_asm_3x4m ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { #if 0 bli_dgemmsup_r_haswell_ref ( conja, conjb, m0, n0, k0, alpha, a, rs_a0, cs_a0, b, rs_b0, cs_b0, beta, c, rs_c0, cs_c0, data, cntx ); return; #endif //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm5, ymm5, ymm5) vxorpd(ymm6, ymm6, ymm6) vxorpd(ymm7, ymm7, ymm7) vxorpd(ymm8, ymm8, ymm8) vxorpd(ymm9, ymm9, ymm9) vxorpd(ymm10, ymm10, ymm10) vxorpd(ymm11, ymm11, ymm11) vxorpd(ymm12, ymm12, ymm12) vxorpd(ymm13, ymm13, ymm13) vxorpd(ymm14, ymm14, ymm14) vxorpd(ymm15, ymm15, ymm15) #endif mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 3*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 3*8)) // prefetch c + 2*rs_c mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 1 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 2 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 3 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rax ), xmm0) vmovsd(mem(rax, r8, 1), xmm1) vmovsd(mem(rax, r8, 2), xmm2) add(imm(1*8), rax) // a += 1*cs_b = 1*8; vmovsd(mem(rbx ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovsd(mem(rbx, r11, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovsd(mem(rbx, r11, 2), xmm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovsd(mem(rbx, r13, 1), xmm3) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 // ymm5 ymm8 ymm11 ymm14 // ymm6 ymm9 ymm12 ymm15 vhaddpd( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm7) vhaddpd( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) // xmm2[0] = sum(ymm10); xmm2[1] = sum(ymm13) vperm2f128(imm(0x20), ymm2, ymm0, ymm4 ) vhaddpd( ymm8, ymm5, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm14, ymm11, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm5 ) vhaddpd( ymm9, ymm6, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm15, ymm12, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm6 ) // ymm4 = sum(ymm4) sum(ymm7) sum(ymm10) sum(ymm13) // ymm5 = sum(ymm5) sum(ymm8) sum(ymm11) sum(ymm14) // ymm6 = sum(ymm6) sum(ymm9) sum(ymm12) sum(ymm15) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(ymm0, ymm5, ymm5) vmulpd(ymm0, ymm6, ymm6) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), ymm3, ymm4) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm5) vmovupd(ymm5, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm6) vmovupd(ymm6, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vmovupd(ymm5, mem(rcx)) add(rdi, rcx) vmovupd(ymm6, mem(rcx)) //add(rdi, rcx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rd_haswell_asm_2x4m ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { #if 0 bli_dgemmsup_r_haswell_ref ( conja, conjb, m0, n0, k0, alpha, a, rs_a0, cs_a0, b, rs_b0, cs_b0, beta, c, rs_c0, cs_c0, data, cntx ); return; #endif //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm5, ymm5, ymm5) vxorpd(ymm7, ymm7, ymm7) vxorpd(ymm8, ymm8, ymm8) vxorpd(ymm10, ymm10, ymm10) vxorpd(ymm11, ymm11, ymm11) vxorpd(ymm13, ymm13, ymm13) vxorpd(ymm14, ymm14, ymm14) #endif mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 3*8)) // prefetch c + 1*rs_c mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) // ---------------------------------- iteration 1 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) // ---------------------------------- iteration 2 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) // ---------------------------------- iteration 3 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rax ), xmm0) vmovsd(mem(rax, r8, 1), xmm1) add(imm(1*8), rax) // a += 1*cs_b = 1*8; vmovsd(mem(rbx ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovsd(mem(rbx, r11, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovsd(mem(rbx, r11, 2), xmm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovsd(mem(rbx, r13, 1), xmm3) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 // ymm5 ymm8 ymm11 ymm14 vhaddpd( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm7) vhaddpd( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) // xmm2[0] = sum(ymm10); xmm2[1] = sum(ymm13) vperm2f128(imm(0x20), ymm2, ymm0, ymm4 ) vhaddpd( ymm8, ymm5, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm14, ymm11, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm5 ) // ymm4 = sum(ymm4) sum(ymm7) sum(ymm10) sum(ymm13) // ymm5 = sum(ymm5) sum(ymm8) sum(ymm11) sum(ymm14) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(ymm0, ymm5, ymm5) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), ymm3, ymm4) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm5) vmovupd(ymm5, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vmovupd(ymm5, mem(rcx)) //add(rdi, rcx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rd_haswell_asm_1x4m ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { #if 0 bli_dgemmsup_r_haswell_ref ( conja, conjb, m0, n0, k0, alpha, a, rs_a0, cs_a0, b, rs_b0, cs_b0, beta, c, rs_c0, cs_c0, data, cntx ); return; #endif //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; /* rrc: -------- -- -- -- | | | | -------- -- -- -- ... | | | | -------- += -- -- -- | | | | -------- | | | | -------- : -------- : */ // ------------------------------------------------------------------------- begin_asm() #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm7, ymm7, ymm7) vxorpd(ymm10, ymm10, ymm10) vxorpd(ymm13, ymm13, ymm13) #endif mov(var(a), rax) // load address of a. //mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a //lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b mov(var(c), rcx) // load address of c //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rax ), ymm0) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) // ---------------------------------- iteration 1 vmovupd(mem(rax ), ymm0) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) // ---------------------------------- iteration 2 vmovupd(mem(rax ), ymm0) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) // ---------------------------------- iteration 3 vmovupd(mem(rax ), ymm0) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) vmovupd(mem(rax ), ymm0) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rax ), xmm0) add(imm(1*8), rax) // a += 1*cs_b = 1*8; vmovsd(mem(rbx ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovsd(mem(rbx, r11, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovsd(mem(rbx, r11, 2), xmm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovsd(mem(rbx, r13, 1), xmm3) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vfmadd231pd(ymm0, ymm3, ymm13) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 vhaddpd( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm7) vhaddpd( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) // xmm2[0] = sum(ymm10); xmm2[1] = sum(ymm13) vperm2f128(imm(0x20), ymm2, ymm0, ymm4 ) // ymm4 = sum(ymm4) sum(ymm7) sum(ymm10) sum(ymm13) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), ymm3, ymm4) vmovupd(ymm4, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx)) //add(rdi, rcx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rd_haswell_asm_6x2m ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { #if 0 bli_dgemmsup_r_haswell_ref ( conja, conjb, m0, n0, k0, alpha, a, rs_a0, cs_a0, b, rs_b0, cs_b0, beta, c, rs_c0, cs_c0, data, cntx ); return; #endif //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t m_iter = m0 / 6; uint64_t m_left = m0 % 6; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; if ( m_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), r14) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rdx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) //lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) // r12 = rcx = c // r14 = rax = a // rdx = rbx = b // r9 = m dim index ii mov(var(m_iter), r9) // ii = m_iter; label(.DLOOP3X4I) // LOOP OVER ii = [ m_iter ... 1 0 ] #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm5, ymm5, ymm5) vxorpd(ymm6, ymm6, ymm6) vxorpd(ymm7, ymm7, ymm7) vxorpd(ymm8, ymm8, ymm8) vxorpd(ymm9, ymm9, ymm9) vxorpd(ymm10, ymm10, ymm10) vxorpd(ymm11, ymm11, ymm11) vxorpd(ymm12, ymm12, ymm12) vxorpd(ymm13, ymm13, ymm13) vxorpd(ymm14, ymm14, ymm14) vxorpd(ymm15, ymm15, ymm15) #endif lea(mem(r12), rcx) // rcx = c + 6*ii*rs_c; lea(mem(r14), rax) // rax = a + 6*ii*rs_a; lea(mem(rdx), rbx) // rbx = b; lea(mem(rcx, rdi, 2), r10) // lea(mem(r10, rdi, 1), r10) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 3*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 3*8)) // prefetch c + 2*rs_c prefetch(0, mem(r10, 3*8)) // prefetch c + 3*rs_c prefetch(0, mem(r10, rdi, 1, 3*8)) // prefetch c + 4*rs_c prefetch(0, mem(r10, rdi, 2, 3*8)) // prefetch c + 5*rs_c mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovupd(mem(rax, r8, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) vmovupd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rax, r8, 4), ymm3) vfmadd231pd(ymm0, ymm3, ymm12) vfmadd231pd(ymm1, ymm3, ymm13) vmovupd(mem(rax, r15, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) // ---------------------------------- iteration 1 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovupd(mem(rax, r8, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) vmovupd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rax, r8, 4), ymm3) vfmadd231pd(ymm0, ymm3, ymm12) vfmadd231pd(ymm1, ymm3, ymm13) vmovupd(mem(rax, r15, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) // ---------------------------------- iteration 2 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovupd(mem(rax, r8, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) vmovupd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rax, r8, 4), ymm3) vfmadd231pd(ymm0, ymm3, ymm12) vfmadd231pd(ymm1, ymm3, ymm13) vmovupd(mem(rax, r15, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) // ---------------------------------- iteration 3 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovupd(mem(rax, r8, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) vmovupd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rax, r8, 4), ymm3) vfmadd231pd(ymm0, ymm3, ymm12) vfmadd231pd(ymm1, ymm3, ymm13) vmovupd(mem(rax, r15, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovupd(mem(rax, r8, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) vmovupd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rax, r8, 4), ymm3) vfmadd231pd(ymm0, ymm3, ymm12) vfmadd231pd(ymm1, ymm3, ymm13) vmovupd(mem(rax, r15, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rbx ), xmm0) vmovsd(mem(rbx, r11, 1), xmm1) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vmovsd(mem(rax ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovsd(mem(rax, r8, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovsd(mem(rax, r8, 2), xmm3) vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) vmovsd(mem(rax, r13, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovsd(mem(rax, r8, 4), xmm3) vfmadd231pd(ymm0, ymm3, ymm12) vfmadd231pd(ymm1, ymm3, ymm13) vmovsd(mem(rax, r15, 1), xmm3) add(imm(1*8), rax) // a += 1*cs_a = 1*8; vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm5 // ymm6 ymm7 // ymm8 ymm9 // ymm10 ymm11 // ymm12 ymm13 // ymm14 ymm15 vhaddpd( ymm5, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm4 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm5) vhaddpd( ymm7, ymm6, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm6 ) vhaddpd( ymm9, ymm8, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm8 ) vhaddpd( ymm11, ymm10, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm10 ) vhaddpd( ymm13, ymm12, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm12 ) vhaddpd( ymm15, ymm14, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm14 ) // xmm4 = sum(ymm4) sum(ymm5) // xmm6 = sum(ymm6) sum(ymm7) // xmm8 = sum(ymm8) sum(ymm9) // xmm10 = sum(ymm10) sum(ymm11) // xmm12 = sum(ymm12) sum(ymm13) // xmm14 = sum(ymm14) sum(ymm15) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(xmm0, xmm4, xmm4) // scale by alpha vmulpd(xmm0, xmm6, xmm6) vmulpd(xmm0, xmm8, xmm8) vmulpd(xmm0, xmm10, xmm10) vmulpd(xmm0, xmm12, xmm12) vmulpd(xmm0, xmm14, xmm14) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), xmm3, xmm4) vmovupd(xmm4, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), xmm3, xmm6) vmovupd(xmm6, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), xmm3, xmm8) vmovupd(xmm8, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), xmm3, xmm10) vmovupd(xmm10, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), xmm3, xmm12) vmovupd(xmm12, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), xmm3, xmm14) vmovupd(xmm14, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(xmm4, mem(rcx)) add(rdi, rcx) vmovupd(xmm6, mem(rcx)) add(rdi, rcx) vmovupd(xmm8, mem(rcx)) add(rdi, rcx) vmovupd(xmm10, mem(rcx)) add(rdi, rcx) vmovupd(xmm12, mem(rcx)) add(rdi, rcx) vmovupd(xmm14, mem(rcx)) //add(rdi, rcx) label(.DDONE) lea(mem(r12, rdi, 4), r12) // lea(mem(r12, rdi, 2), r12) // c_ii = r12 += 6*rs_c lea(mem(r14, r8, 4), r14) // lea(mem(r14, r8, 2), r14) // a_ii = r14 += 6*rs_a dec(r9) // ii -= 1; jne(.DLOOP3X4I) // iterate again if ii != 0. label(.DRETURN) end_asm( : // output operands (none) : // input operands [m_iter] "m" (m_iter), [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the m dimension, if they exist. if ( m_left ) { const dim_t nr_cur = 2; const dim_t i_edge = m0 - ( dim_t )m_left; double* restrict cij = c + i_edge*rs_c; double* restrict bj = b; double* restrict ai = a + i_edge*rs_a; if ( 3 <= m_left ) { const dim_t mr_cur = 3; bli_dgemmsup_rd_haswell_asm_3x2m ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += mr_cur*rs_c0; ai += mr_cur*rs_a0; m_left -= mr_cur; } if ( 2 <= m_left ) { const dim_t mr_cur = 2; bli_dgemmsup_rd_haswell_asm_2x2m ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += mr_cur*rs_c0; ai += mr_cur*rs_a0; m_left -= mr_cur; } if ( 1 == m_left ) { const dim_t mr_cur = 1; bli_dgemmsup_rd_haswell_asm_1x2m ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); } } } void bli_dgemmsup_rd_haswell_asm_3x2m ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { #if 0 bli_dgemmsup_r_haswell_ref ( conja, conjb, m0, n0, k0, alpha, a, rs_a0, cs_a0, b, rs_b0, cs_b0, beta, c, rs_c0, cs_c0, data, cntx ); return; #endif //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm5, ymm5, ymm5) vxorpd(ymm6, ymm6, ymm6) vxorpd(ymm7, ymm7, ymm7) vxorpd(ymm8, ymm8, ymm8) vxorpd(ymm9, ymm9, ymm9) #endif mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) //lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b // initialize loop by pre-loading // a column of a. mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) prefetch(0, mem(rcx, 1*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 1*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 1*8)) // prefetch c + 2*rs_c mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovupd(mem(rax, r8, 2), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) // ---------------------------------- iteration 1 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovupd(mem(rax, r8, 2), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) // ---------------------------------- iteration 2 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovupd(mem(rax, r8, 2), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) // ---------------------------------- iteration 3 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovupd(mem(rax, r8, 2), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovupd(mem(rax, r8, 2), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rbx ), xmm0) vmovsd(mem(rbx, r11, 1), xmm1) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vmovsd(mem(rax ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovsd(mem(rax, r8, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovsd(mem(rax, r8, 2), xmm3) add(imm(1*8), rax) // a += 1*cs_a = 1*8; vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm5 // ymm6 ymm7 // ymm8 ymm9 vhaddpd( ymm5, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm4 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm5) vhaddpd( ymm7, ymm6, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm6 ) vhaddpd( ymm9, ymm8, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm8 ) // xmm4 = sum(ymm4) sum(ymm5) // xmm6 = sum(ymm6) sum(ymm7) // xmm8 = sum(ymm8) sum(ymm9) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(xmm0, xmm4, xmm4) // scale by alpha vmulpd(xmm0, xmm6, xmm6) vmulpd(xmm0, xmm8, xmm8) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), xmm3, xmm4) vmovupd(xmm4, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), xmm3, xmm6) vmovupd(xmm6, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), xmm3, xmm8) vmovupd(xmm8, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(xmm4, mem(rcx)) add(rdi, rcx) vmovupd(xmm6, mem(rcx)) add(rdi, rcx) vmovupd(xmm8, mem(rcx)) //add(rdi, rcx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rd_haswell_asm_2x2m ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { #if 0 bli_dgemmsup_r_haswell_ref ( conja, conjb, m0, n0, k0, alpha, a, rs_a0, cs_a0, b, rs_b0, cs_b0, beta, c, rs_c0, cs_c0, data, cntx ); return; #endif //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; /* rrc: -------- -- -- -- | | -------- -- -- -- ... | | -------- += -- -- -- | | -------- -- -- -- | | -------- -- -- -- : -------- -- -- -- : */ // ------------------------------------------------------------------------- begin_asm() #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm5, ymm5, ymm5) vxorpd(ymm6, ymm6, ymm6) vxorpd(ymm7, ymm7, ymm7) #endif mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) //lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b // initialize loop by pre-loading // a column of a. mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) //lea(mem(rcx, rdi, 2), rdx) // //lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 1*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 1*8)) // prefetch c + 1*rs_c mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) // ---------------------------------- iteration 1 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) // ---------------------------------- iteration 2 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) // ---------------------------------- iteration 3 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rbx ), xmm0) vmovsd(mem(rbx, r11, 1), xmm1) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vmovsd(mem(rax ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovsd(mem(rax, r8, 1), xmm3) add(imm(1*8), rax) // a += 1*cs_a = 1*8; vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm5 // ymm6 ymm7 vhaddpd( ymm5, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm4 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm5) vhaddpd( ymm7, ymm6, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm6 ) // xmm4 = sum(ymm4) sum(ymm5) // xmm6 = sum(ymm6) sum(ymm7) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(xmm0, xmm4, xmm4) // scale by alpha vmulpd(xmm0, xmm6, xmm6) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), xmm3, xmm4) vmovupd(xmm4, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), xmm3, xmm6) vmovupd(xmm6, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(xmm4, mem(rcx)) add(rdi, rcx) vmovupd(xmm6, mem(rcx)) //add(rdi, rcx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rd_haswell_asm_1x2m ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { #if 0 bli_dgemmsup_r_haswell_ref ( conja, conjb, m0, n0, k0, alpha, a, rs_a0, cs_a0, b, rs_b0, cs_b0, beta, c, rs_c0, cs_c0, data, cntx ); return; #endif //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; /* rrc: -------- -- -- -- | | -------- -- -- -- ... | | -------- += -- -- -- | | -------- -- -- -- | | -------- -- -- -- : -------- -- -- -- : */ // ------------------------------------------------------------------------- begin_asm() #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm5, ymm5, ymm5) #endif mov(var(a), rax) // load address of a. //mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a //lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) //lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b // initialize loop by pre-loading // a column of a. mov(var(c), rcx) // load address of c //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) //lea(mem(rcx, rdi, 2), rdx) // //lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 1*8)) // prefetch c + 0*rs_c mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) // ---------------------------------- iteration 1 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) // ---------------------------------- iteration 2 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) // ---------------------------------- iteration 3 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rbx ), xmm0) vmovsd(mem(rbx, r11, 1), xmm1) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vmovsd(mem(rax ), xmm3) add(imm(1*8), rax) // a += 1*cs_a = 1*8; vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm5 vhaddpd( ymm5, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm4 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm5) // xmm4 = sum(ymm4) sum(ymm5) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(xmm0, xmm4, xmm4) // scale by alpha //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), xmm3, xmm4) vmovupd(xmm4, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(xmm4, mem(rcx)) //add(rdi, rcx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } blis-0.9.0/kernels/haswell/3/sup/old/bli_gemmsup_rd_haswell_asm_d6x8n.c000066400000000000000000004622051422157504600260630ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define BLIS_ASM_SYNTAX_ATT #include "bli_x86_asm_macros.h" /* rrc: -------- ------ | | | | | | | | -------- ------ | | | | | | | | -------- += ------ ... | | | | | | | | -------- ------ | | | | | | | | -------- ------ : -------- ------ : Assumptions: - C is row-stored and B is column-stored; - A is row-stored; - m0 and n0 are at most MR and NR, respectively. Therefore, this (r)ow-preferential microkernel is well-suited for a dot-product-based accumulation that performs vector loads from both A and B. */ // Prototype reference microkernels. GEMMSUP_KER_PROT( float, s, gemmsup_r_haswell_ref ) GEMMSUP_KER_PROT( double, d, gemmsup_r_haswell_ref ) GEMMSUP_KER_PROT( scomplex, c, gemmsup_r_haswell_ref ) GEMMSUP_KER_PROT( dcomplex, z, gemmsup_r_haswell_ref ) // Define parameters and variables for edge case kernel map. #define NUM_MR 4 #define NUM_NR 4 #define FUNCPTR_T dgemmsup_ker_ft #if 0 static dim_t mrs[NUM_MR] = { 6, 3, 2, 1 }; static dim_t nrs[NUM_NR] = { 8, 4, 2, 1 }; static FUNCPTR_T kmap[NUM_MR][NUM_NR] = { /* 8 4 2 1 */ /* 6 */ { bli_dgemmsup_rd_haswell_asm_6x8n, bli_dgemmsup_rd_haswell_asm_6x4n, bli_dgemmsup_rd_haswell_asm_6x2n, bli_dgemmsup_r_haswell_ref }, /* 3 */ { bli_dgemmsup_rd_haswell_asm_3x8n, bli_dgemmsup_rd_haswell_asm_3x4n, bli_dgemmsup_rd_haswell_asm_3x2n, bli_dgemmsup_r_haswell_ref }, /* 2 */ { bli_dgemmsup_rd_haswell_asm_2x8n, bli_dgemmsup_rd_haswell_asm_2x4n, bli_dgemmsup_rd_haswell_asm_2x2n, bli_dgemmsup_r_haswell_ref }, /* 1 */ { bli_dgemmsup_rd_haswell_asm_1x8n, bli_dgemmsup_rd_haswell_asm_1x4n, bli_dgemmsup_rd_haswell_asm_1x2n, bli_dgemmsup_r_haswell_ref } }; #endif void bli_dgemmsup_rd_haswell_asm_6x8n ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { #if 0 bli_dgemmsup_r_haswell_ref ( conja, conjb, m0, n0, k0, alpha, a, rs_a0, cs_a0, b, rs_b0, cs_b0, beta, c, rs_c0, cs_c0, data, cntx ); return; #endif uint64_t m_left = m0 % 6; // First check whether this is a edge case in the n dimension. If so, // dispatch other ?x8m kernels, as needed. if ( m_left ) { double* restrict cij = c; double* restrict bj = b; double* restrict ai = a; if ( 3 <= m_left ) { const dim_t mr_cur = 3; bli_dgemmsup_rd_haswell_asm_3x8n ( conja, conjb, mr_cur, n0, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += mr_cur*rs_c0; ai += mr_cur*rs_a0; m_left -= mr_cur; } if ( 2 <= m_left ) { const dim_t mr_cur = 2; bli_dgemmsup_rd_haswell_asm_2x8n ( conja, conjb, mr_cur, n0, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += mr_cur*rs_c0; ai += mr_cur*rs_a0; m_left -= mr_cur; } if ( 1 == m_left ) { #if 0 const dim_t mr_cur = 1; //bli_dgemmsup_r_haswell_ref bli_dgemmsup_rd_haswell_asm_1x8n ( conja, conjb, mr_cur, n0, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); #else bli_dgemv_ex ( BLIS_TRANSPOSE, conja, k0, n0, alpha, bj, rs_b0, cs_b0, ai, cs_a0, beta, cij, cs_c0, cntx, NULL ); #endif } return; } //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t n_iter = n0 / 4; uint64_t n_left = n0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; if ( n_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), rdx) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a //mov(var(b), r14) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b //mov(var(c), r12) // load address of c //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) // r12 = rcx = c // rdx = rax = a // r14 = rbx = b // r9 = m dim index ii // r15 = n dim index jj mov(imm(0), r9) // ii = 0; label(.DLOOP3X4I) // LOOP OVER ii = [ 0 1 ... ] mov(var(b), r14) // load address of b mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) lea(mem( , r9, 1), rsi) // rsi = r9 = 3*ii; imul(rdi, rsi) // rsi *= rs_c lea(mem(r12, rsi, 1), r12) // r12 = c + 3*ii*rs_c; lea(mem( , r9, 1), rsi) // rsi = r9 = 3*ii; imul(r8, rsi) // rsi *= rs_a; lea(mem(rdx, rsi, 1), rdx) // rax = a + 3*ii*rs_a; mov(var(n_iter), r15) // jj = n_iter; label(.DLOOP3X4J) // LOOP OVER jj = [ n_iter ... 1 0 ] #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm5, ymm5, ymm5) vxorpd(ymm6, ymm6, ymm6) vxorpd(ymm7, ymm7, ymm7) vxorpd(ymm8, ymm8, ymm8) vxorpd(ymm9, ymm9, ymm9) vxorpd(ymm10, ymm10, ymm10) vxorpd(ymm11, ymm11, ymm11) vxorpd(ymm12, ymm12, ymm12) vxorpd(ymm13, ymm13, ymm13) vxorpd(ymm14, ymm14, ymm14) vxorpd(ymm15, ymm15, ymm15) #endif lea(mem(r12), rcx) // rcx = c_iijj; lea(mem(rdx), rax) // rax = a_ii; lea(mem(r14), rbx) // rbx = b_jj; #if 1 mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 3*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 3*8)) // prefetch c + 2*rs_c #endif lea(mem(r11, r11, 2), rdi) // rdi = 3*cs_b lea(mem(rbx, r11, 4), r10) // r10 = rbx + 4*cs_b mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 #if 0 prefetch(0, mem(r10, 0*8)) // prefetch rbx + 4*cs_b prefetch(0, mem(r10, r11, 1, 0*8)) // prefetch rbx + 5*cs_b prefetch(0, mem(r10, r11, 2, 0*8)) // prefetch rbx + 6*cs_b prefetch(0, mem(r10, r13, 1, 0*8)) // prefetch rbx + 7*cs_b add(imm(8*8), r10) // r10 += 8*rs_b = 8*8; #else prefetch(0, mem(r10, 0*8)) // prefetch rbx + 4*cs_b prefetch(0, mem(r10, r11, 1, 0*8)) // prefetch rbx + 5*cs_b #endif vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 1 #if 1 prefetch(0, mem(r10, r11, 2, 0*8)) // prefetch rbx + 6*cs_b prefetch(0, mem(r10, r13, 1, 0*8)) // prefetch rbx + 7*cs_b #endif vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(r10, 8*8)) // prefetch rbx + 4*cs_b + 8*rs_b prefetch(0, mem(r10, r11, 1, 8*8)) // prefetch rbx + 5*cs_b + 8*rs_b #endif vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 3 #if 1 prefetch(0, mem(r10, r11, 2, 8*8)) // prefetch rbx + 6*cs_b + 8*rs_b prefetch(0, mem(r10, r13, 1, 8*8)) // prefetch rbx + 7*cs_b + 8*rs_b add(imm(16*8), r10) // r10 += 8*rs_b = 8*8; #endif vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rax ), xmm0) vmovsd(mem(rax, r8, 1), xmm1) vmovsd(mem(rax, r8, 2), xmm2) add(imm(1*8), rax) // a += 1*cs_b = 1*8; vmovsd(mem(rbx ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovsd(mem(rbx, r11, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovsd(mem(rbx, r11, 2), xmm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovsd(mem(rbx, r13, 1), xmm3) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 // ymm5 ymm8 ymm11 ymm14 // ymm6 ymm9 ymm12 ymm15 vhaddpd( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm7) vhaddpd( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) // xmm2[0] = sum(ymm10); xmm2[1] = sum(ymm13) vperm2f128(imm(0x20), ymm2, ymm0, ymm4 ) vhaddpd( ymm8, ymm5, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm14, ymm11, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm5 ) vhaddpd( ymm9, ymm6, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm15, ymm12, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm6 ) // ymm4 = sum(ymm4) sum(ymm7) sum(ymm10) sum(ymm13) // ymm5 = sum(ymm5) sum(ymm8) sum(ymm11) sum(ymm14) // ymm6 = sum(ymm6) sum(ymm9) sum(ymm12) sum(ymm15) mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(ymm0, ymm5, ymm5) vmulpd(ymm0, ymm6, ymm6) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), ymm3, ymm4) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm5) vmovupd(ymm5, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm6) vmovupd(ymm6, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vmovupd(ymm5, mem(rcx)) add(rdi, rcx) vmovupd(ymm6, mem(rcx)) //add(rdi, rcx) label(.DDONE) add(imm(4*8), r12) // c_jj = r12 += 4*cs_c lea(mem(r14, r11, 4), r14) // b_jj = r14 += 4*cs_b dec(r15) // jj -= 1; jne(.DLOOP3X4J) // iterate again if jj != 0. add(imm(3), r9) // ii += 3; cmp(imm(3), r9) // compare ii to 3 jle(.DLOOP3X4I) // if ii <= 3, jump to beginning // of ii loop; otherwise, loop ends. label(.DRETURN) end_asm( : // output operands (none) : // input operands [n_iter] "m" (n_iter), [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the m dimension, if they exist. if ( n_left ) { const dim_t mr_cur = 6; const dim_t j_edge = n0 - ( dim_t )n_left; double* restrict cij = c + j_edge*cs_c; double* restrict ai = a; double* restrict bj = b + j_edge*cs_b; if ( 2 <= n_left ) { const dim_t nr_cur = 2; bli_dgemmsup_rd_haswell_asm_6x2n ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 1 == n_left ) { #if 0 const dim_t nr_cur = 1; //bli_dgemmsup_rd_haswell_asm_6x1n bli_dgemmsup_r_haswell_ref ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); #else bli_dgemv_ex ( BLIS_NO_TRANSPOSE, conjb, mr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, beta, cij, rs_c0, cntx, NULL ); #endif } } } void bli_dgemmsup_rd_haswell_asm_3x8n ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { #if 0 bli_dgemmsup_r_haswell_ref ( conja, conjb, m0, n0, k0, alpha, a, rs_a0, cs_a0, b, rs_b0, cs_b0, beta, c, rs_c0, cs_c0, data, cntx ); return; #endif //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t n_iter = n0 / 4; uint64_t n_left = n0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; if ( n_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), rdx) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), r14) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b mov(var(c), r12) // load address of c //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) // r12 = rcx = c // rdx = rax = a // r14 = rbx = b // r9 = unused // r15 = n dim index jj mov(var(n_iter), r15) // jj = n_iter; label(.DLOOP3X4J) // LOOP OVER jj = [ n_iter ... 1 0 ] #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm5, ymm5, ymm5) vxorpd(ymm6, ymm6, ymm6) vxorpd(ymm7, ymm7, ymm7) vxorpd(ymm8, ymm8, ymm8) vxorpd(ymm9, ymm9, ymm9) vxorpd(ymm10, ymm10, ymm10) vxorpd(ymm11, ymm11, ymm11) vxorpd(ymm12, ymm12, ymm12) vxorpd(ymm13, ymm13, ymm13) vxorpd(ymm14, ymm14, ymm14) vxorpd(ymm15, ymm15, ymm15) #endif lea(mem(r12), rcx) // rcx = c_iijj; lea(mem(rdx), rax) // rax = a_ii; lea(mem(r14), rbx) // rbx = b_jj; #if 1 mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 3*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 3*8)) // prefetch c + 2*rs_c #endif lea(mem(r11, r11, 2), rdi) // rdi = 3*cs_b lea(mem(rbx, r11, 4), r10) // r10 = rbx + 4*cs_b mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 #if 0 prefetch(0, mem(r10, 0*8)) // prefetch rbx + 4*cs_b prefetch(0, mem(r10, r11, 1, 0*8)) // prefetch rbx + 5*cs_b prefetch(0, mem(r10, r11, 2, 0*8)) // prefetch rbx + 6*cs_b prefetch(0, mem(r10, r13, 1, 0*8)) // prefetch rbx + 7*cs_b add(imm(8*8), r10) // r10 += 8*rs_b = 8*8; #else prefetch(0, mem(r10, 0*8)) // prefetch rbx + 4*cs_b prefetch(0, mem(r10, r11, 1, 0*8)) // prefetch rbx + 5*cs_b #endif vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 1 #if 1 prefetch(0, mem(r10, r11, 2, 0*8)) // prefetch rbx + 6*cs_b prefetch(0, mem(r10, r13, 1, 0*8)) // prefetch rbx + 7*cs_b #endif vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(r10, 8*8)) // prefetch rbx + 4*cs_b + 8*rs_b prefetch(0, mem(r10, r11, 1, 8*8)) // prefetch rbx + 5*cs_b + 8*rs_b #endif vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 3 #if 1 prefetch(0, mem(r10, r11, 2, 8*8)) // prefetch rbx + 6*cs_b + 8*rs_b prefetch(0, mem(r10, r13, 1, 8*8)) // prefetch rbx + 7*cs_b + 8*rs_b add(imm(16*8), r10) // r10 += 8*rs_b = 8*8; #endif vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rax ), xmm0) vmovsd(mem(rax, r8, 1), xmm1) vmovsd(mem(rax, r8, 2), xmm2) add(imm(1*8), rax) // a += 1*cs_b = 1*8; vmovsd(mem(rbx ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovsd(mem(rbx, r11, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovsd(mem(rbx, r11, 2), xmm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovsd(mem(rbx, r13, 1), xmm3) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 // ymm5 ymm8 ymm11 ymm14 // ymm6 ymm9 ymm12 ymm15 vhaddpd( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm7) vhaddpd( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) // xmm2[0] = sum(ymm10); xmm2[1] = sum(ymm13) vperm2f128(imm(0x20), ymm2, ymm0, ymm4 ) vhaddpd( ymm8, ymm5, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm14, ymm11, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm5 ) vhaddpd( ymm9, ymm6, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm15, ymm12, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm6 ) // ymm4 = sum(ymm4) sum(ymm7) sum(ymm10) sum(ymm13) // ymm5 = sum(ymm5) sum(ymm8) sum(ymm11) sum(ymm14) // ymm6 = sum(ymm6) sum(ymm9) sum(ymm12) sum(ymm15) mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(ymm0, ymm5, ymm5) vmulpd(ymm0, ymm6, ymm6) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), ymm3, ymm4) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm5) vmovupd(ymm5, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm6) vmovupd(ymm6, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vmovupd(ymm5, mem(rcx)) add(rdi, rcx) vmovupd(ymm6, mem(rcx)) //add(rdi, rcx) label(.DDONE) add(imm(4*8), r12) // c_jj = r12 += 4*cs_c lea(mem(r14, r11, 4), r14) // b_jj = r14 += 4*cs_b dec(r15) // jj -= 1; jne(.DLOOP3X4J) // iterate again if jj != 0. label(.DRETURN) end_asm( : // output operands (none) : // input operands [n_iter] "m" (n_iter), [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the m dimension, if they exist. if ( n_left ) { const dim_t mr_cur = 3; const dim_t j_edge = n0 - ( dim_t )n_left; double* restrict cij = c + j_edge*cs_c; double* restrict ai = a; double* restrict bj = b + j_edge*cs_b; if ( 2 <= n_left ) { const dim_t nr_cur = 2; bli_dgemmsup_rd_haswell_asm_3x2n ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 1 == n_left ) { #if 0 const dim_t nr_cur = 1; //bli_dgemmsup_rd_haswell_asm_3x1n bli_dgemmsup_r_haswell_ref ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); #else bli_dgemv_ex ( BLIS_NO_TRANSPOSE, conjb, mr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, beta, cij, rs_c0, cntx, NULL ); #endif } } } void bli_dgemmsup_rd_haswell_asm_2x8n ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { #if 0 bli_dgemmsup_r_haswell_ref ( conja, conjb, m0, n0, k0, alpha, a, rs_a0, cs_a0, b, rs_b0, cs_b0, beta, c, rs_c0, cs_c0, data, cntx ); return; #endif //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t n_iter = n0 / 4; uint64_t n_left = n0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; if ( n_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), rdx) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), r14) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b mov(var(c), r12) // load address of c //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) // r12 = rcx = c // rdx = rax = a // r14 = rbx = b // r9 = unused // r15 = n dim index jj mov(var(n_iter), r15) // jj = n_iter; label(.DLOOP3X4J) // LOOP OVER jj = [ n_iter ... 1 0 ] #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm5, ymm5, ymm5) vxorpd(ymm7, ymm7, ymm7) vxorpd(ymm8, ymm8, ymm8) vxorpd(ymm10, ymm10, ymm10) vxorpd(ymm11, ymm11, ymm11) vxorpd(ymm13, ymm13, ymm13) vxorpd(ymm14, ymm14, ymm14) #endif lea(mem(r12), rcx) // rcx = c_iijj; lea(mem(rdx), rax) // rax = a_ii; lea(mem(r14), rbx) // rbx = b_jj; #if 1 mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 3*8)) // prefetch c + 1*rs_c #endif lea(mem(r11, r11, 2), rdi) // rdi = 3*cs_b lea(mem(rbx, r11, 4), r10) // r10 = rbx + 4*cs_b mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 #if 0 prefetch(0, mem(r10, 0*8)) // prefetch rbx + 4*cs_b prefetch(0, mem(r10, r11, 1, 0*8)) // prefetch rbx + 5*cs_b prefetch(0, mem(r10, r11, 2, 0*8)) // prefetch rbx + 6*cs_b prefetch(0, mem(r10, r13, 1, 0*8)) // prefetch rbx + 7*cs_b add(imm(8*8), r10) // r10 += 8*rs_b = 8*8; #else prefetch(0, mem(r10, 0*8)) // prefetch rbx + 4*cs_b prefetch(0, mem(r10, r11, 1, 0*8)) // prefetch rbx + 5*cs_b #endif vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) // ---------------------------------- iteration 1 #if 1 prefetch(0, mem(r10, r11, 2, 0*8)) // prefetch rbx + 6*cs_b prefetch(0, mem(r10, r13, 1, 0*8)) // prefetch rbx + 7*cs_b #endif vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(r10, 8*8)) // prefetch rbx + 4*cs_b + 8*rs_b prefetch(0, mem(r10, r11, 1, 8*8)) // prefetch rbx + 5*cs_b + 8*rs_b #endif vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) // ---------------------------------- iteration 3 #if 1 prefetch(0, mem(r10, r11, 2, 8*8)) // prefetch rbx + 6*cs_b + 8*rs_b prefetch(0, mem(r10, r13, 1, 8*8)) // prefetch rbx + 7*cs_b + 8*rs_b add(imm(16*8), r10) // r10 += 8*rs_b = 8*8; #endif vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rax ), xmm0) vmovsd(mem(rax, r8, 1), xmm1) add(imm(1*8), rax) // a += 1*cs_b = 1*8; vmovsd(mem(rbx ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovsd(mem(rbx, r11, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovsd(mem(rbx, r11, 2), xmm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovsd(mem(rbx, r13, 1), xmm3) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 // ymm5 ymm8 ymm11 ymm14 // ymm6 ymm9 ymm12 ymm15 vhaddpd( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm7) vhaddpd( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) // xmm2[0] = sum(ymm10); xmm2[1] = sum(ymm13) vperm2f128(imm(0x20), ymm2, ymm0, ymm4 ) vhaddpd( ymm8, ymm5, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm14, ymm11, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm5 ) // ymm4 = sum(ymm4) sum(ymm7) sum(ymm10) sum(ymm13) // ymm5 = sum(ymm5) sum(ymm8) sum(ymm11) sum(ymm14) mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(ymm0, ymm5, ymm5) vmulpd(ymm0, ymm6, ymm6) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), ymm3, ymm4) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm5) vmovupd(ymm5, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vmovupd(ymm5, mem(rcx)) //add(rdi, rcx) label(.DDONE) add(imm(4*8), r12) // c_jj = r12 += 4*cs_c lea(mem(r14, r11, 4), r14) // b_jj = r14 += 4*cs_b dec(r15) // jj -= 1; jne(.DLOOP3X4J) // iterate again if jj != 0. label(.DRETURN) end_asm( : // output operands (none) : // input operands [n_iter] "m" (n_iter), [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the m dimension, if they exist. if ( n_left ) { const dim_t mr_cur = 2; const dim_t j_edge = n0 - ( dim_t )n_left; double* restrict cij = c + j_edge*cs_c; double* restrict ai = a; double* restrict bj = b + j_edge*cs_b; if ( 2 <= n_left ) { const dim_t nr_cur = 2; bli_dgemmsup_rd_haswell_asm_2x2n ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 1 == n_left ) { #if 0 const dim_t nr_cur = 1; //bli_dgemmsup_rd_haswell_asm_2x1n bli_dgemmsup_r_haswell_ref ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); #else bli_dgemv_ex ( BLIS_NO_TRANSPOSE, conjb, mr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, beta, cij, rs_c0, cntx, NULL ); #endif } } } void bli_dgemmsup_rd_haswell_asm_1x8n ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { #if 0 bli_dgemmsup_r_haswell_ref ( conja, conjb, m0, n0, k0, alpha, a, rs_a0, cs_a0, b, rs_b0, cs_b0, beta, c, rs_c0, cs_c0, data, cntx ); return; #endif //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t n_iter = n0 / 4; uint64_t n_left = n0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; if ( n_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), rdx) // load address of a. //mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a //lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), r14) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b mov(var(c), r12) // load address of c //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) // r12 = rcx = c // rdx = rax = a // r14 = rbx = b // r9 = unused // r15 = n dim index jj mov(var(n_iter), r15) // jj = n_iter; label(.DLOOP3X4J) // LOOP OVER jj = [ n_iter ... 1 0 ] #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm7, ymm7, ymm7) vxorpd(ymm10, ymm10, ymm10) vxorpd(ymm13, ymm13, ymm13) #endif lea(mem(r12), rcx) // rcx = c_iijj; lea(mem(rdx), rax) // rax = a_ii; lea(mem(r14), rbx) // rbx = b_jj; #if 1 mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 3*8)) // prefetch c + 1*rs_c #endif lea(mem(r11, r11, 2), rdi) // rdi = 3*cs_b lea(mem(rbx, r11, 4), r10) // r10 = rbx + 4*cs_b mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 #if 0 prefetch(0, mem(r10, 0*8)) // prefetch rbx + 4*cs_b prefetch(0, mem(r10, r11, 1, 0*8)) // prefetch rbx + 5*cs_b prefetch(0, mem(r10, r11, 2, 0*8)) // prefetch rbx + 6*cs_b prefetch(0, mem(r10, r13, 1, 0*8)) // prefetch rbx + 7*cs_b add(imm(8*8), r10) // r10 += 8*rs_b = 8*8; #else prefetch(0, mem(r10, 0*8)) // prefetch rbx + 4*cs_b prefetch(0, mem(r10, r11, 1, 0*8)) // prefetch rbx + 5*cs_b #endif vmovupd(mem(rax ), ymm0) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) // ---------------------------------- iteration 1 #if 1 prefetch(0, mem(r10, r11, 2, 0*8)) // prefetch rbx + 6*cs_b prefetch(0, mem(r10, r13, 1, 0*8)) // prefetch rbx + 7*cs_b #endif vmovupd(mem(rax ), ymm0) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(r10, 8*8)) // prefetch rbx + 4*cs_b + 8*rs_b prefetch(0, mem(r10, r11, 1, 8*8)) // prefetch rbx + 5*cs_b + 8*rs_b #endif vmovupd(mem(rax ), ymm0) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) // ---------------------------------- iteration 3 #if 1 prefetch(0, mem(r10, r11, 2, 8*8)) // prefetch rbx + 6*cs_b + 8*rs_b prefetch(0, mem(r10, r13, 1, 8*8)) // prefetch rbx + 7*cs_b + 8*rs_b add(imm(16*8), r10) // r10 += 8*rs_b = 8*8; #endif vmovupd(mem(rax ), ymm0) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) vmovupd(mem(rax ), ymm0) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rax ), xmm0) add(imm(1*8), rax) // a += 1*cs_b = 1*8; vmovsd(mem(rbx ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovsd(mem(rbx, r11, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovsd(mem(rbx, r11, 2), xmm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovsd(mem(rbx, r13, 1), xmm3) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vfmadd231pd(ymm0, ymm3, ymm13) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 // ymm5 ymm8 ymm11 ymm14 // ymm6 ymm9 ymm12 ymm15 vhaddpd( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm7) vhaddpd( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) // xmm2[0] = sum(ymm10); xmm2[1] = sum(ymm13) vperm2f128(imm(0x20), ymm2, ymm0, ymm4 ) // ymm4 = sum(ymm4) sum(ymm7) sum(ymm10) sum(ymm13) mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), ymm3, ymm4) vmovupd(ymm4, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx)) //add(rdi, rcx) label(.DDONE) add(imm(4*8), r12) // c_jj = r12 += 4*cs_c lea(mem(r14, r11, 4), r14) // b_jj = r14 += 4*cs_b dec(r15) // jj -= 1; jne(.DLOOP3X4J) // iterate again if jj != 0. label(.DRETURN) end_asm( : // output operands (none) : // input operands [n_iter] "m" (n_iter), [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the m dimension, if they exist. if ( n_left ) { const dim_t mr_cur = 1; const dim_t j_edge = n0 - ( dim_t )n_left; double* restrict cij = c + j_edge*cs_c; double* restrict ai = a; double* restrict bj = b + j_edge*cs_b; if ( 2 <= n_left ) { const dim_t nr_cur = 2; bli_dgemmsup_rd_haswell_asm_1x2n ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 1 == n_left ) { #if 0 const dim_t nr_cur = 1; //bli_dgemmsup_rd_haswell_asm_1x1n bli_dgemmsup_r_haswell_ref ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); #else bli_ddotxv_ex ( conja, conjb, k0, alpha, ai, cs_a0, bj, rs_b0, beta, cij, cntx, NULL ); #endif } } } void bli_dgemmsup_rd_haswell_asm_6x4n ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { #if 0 bli_dgemmsup_r_haswell_ref ( conja, conjb, m0, n0, k0, alpha, a, rs_a0, cs_a0, b, rs_b0, cs_b0, beta, c, rs_c0, cs_c0, data, cntx ); return; #endif //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t m_iter = m0 / 3; uint64_t m_left = m0 % 3; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; if ( m_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), r14) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rdx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b lea(mem(r8, r8, 2), r10) // r10 = 3*rs_a mov(var(c), r12) // load address of c //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) // r12 = rcx = c // r14 = rax = a // rdx = rbx = b // r9 = m dim index ii // r15 = n dim index jj // r10 = unused mov(var(m_iter), r9) // ii = m_iter; label(.DLOOP3X4I) // LOOP OVER ii = [ m_iter .. 1 0 ] #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm5, ymm5, ymm5) vxorpd(ymm6, ymm6, ymm6) vxorpd(ymm7, ymm7, ymm7) vxorpd(ymm8, ymm8, ymm8) vxorpd(ymm9, ymm9, ymm9) vxorpd(ymm10, ymm10, ymm10) vxorpd(ymm11, ymm11, ymm11) vxorpd(ymm12, ymm12, ymm12) vxorpd(ymm13, ymm13, ymm13) vxorpd(ymm14, ymm14, ymm14) vxorpd(ymm15, ymm15, ymm15) #endif lea(mem(r12), rcx) // rcx = c + 3*ii*rs_c; lea(mem(r14), rax) // rax = a + 3*ii*rs_a; lea(mem(rdx), rbx) // rbx = b; #if 0 mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 3*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 3*8)) // prefetch c + 2*rs_c #endif lea(mem(r8, r8, 4), rdi) // rdi = 5*rs_a mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rdi, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 1 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rdi, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 3 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rax ), xmm0) vmovsd(mem(rax, r8, 1), xmm1) vmovsd(mem(rax, r8, 2), xmm2) add(imm(1*8), rax) // a += 1*cs_b = 1*8; vmovsd(mem(rbx ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovsd(mem(rbx, r11, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovsd(mem(rbx, r11, 2), xmm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovsd(mem(rbx, r13, 1), xmm3) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 // ymm5 ymm8 ymm11 ymm14 // ymm6 ymm9 ymm12 ymm15 vhaddpd( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm7) vhaddpd( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) // xmm2[0] = sum(ymm10); xmm2[1] = sum(ymm13) vperm2f128(imm(0x20), ymm2, ymm0, ymm4 ) vhaddpd( ymm8, ymm5, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm14, ymm11, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm5 ) vhaddpd( ymm9, ymm6, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm15, ymm12, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm6 ) // ymm4 = sum(ymm4) sum(ymm7) sum(ymm10) sum(ymm13) // ymm5 = sum(ymm5) sum(ymm8) sum(ymm11) sum(ymm14) // ymm6 = sum(ymm6) sum(ymm9) sum(ymm12) sum(ymm15) mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(ymm0, ymm5, ymm5) vmulpd(ymm0, ymm6, ymm6) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), ymm3, ymm4) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm5) vmovupd(ymm5, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm6) vmovupd(ymm6, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vmovupd(ymm5, mem(rcx)) add(rdi, rcx) vmovupd(ymm6, mem(rcx)) //add(rdi, rcx) label(.DDONE) lea(mem(r12, rdi, 2), r12) // lea(mem(r12, rdi, 1), r12) // c_ii = r12 += 3*rs_c lea(mem(r14, r8, 2), r14) // lea(mem(r14, r8, 1), r14) // a_ii = r14 += 3*rs_a dec(r9) // ii -= 1; jne(.DLOOP3X4I) // iterate again if ii != 0. label(.DRETURN) end_asm( : // output operands (none) : // input operands [m_iter] "m" (m_iter), [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the m dimension, if they exist. if ( m_left ) { const dim_t nr_cur = 4; const dim_t i_edge = m0 - ( dim_t )m_left; double* restrict cij = c + i_edge*rs_c; double* restrict bj = b; double* restrict ai = a + i_edge*rs_a; if ( 2 == m_left ) { const dim_t mr_cur = 2; bli_dgemmsup_rd_haswell_asm_2x4n ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); //cij += mr_cur*rs_c0; ai += mr_cur*rs_a0; m_left -= mr_cur; } if ( 1 == m_left ) { const dim_t mr_cur = 1; bli_dgemmsup_rd_haswell_asm_1x4n ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); } } } void bli_dgemmsup_rd_haswell_asm_3x4n ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { #if 0 bli_dgemmsup_r_haswell_ref ( conja, conjb, m0, n0, k0, alpha, a, rs_a0, cs_a0, b, rs_b0, cs_b0, beta, c, rs_c0, cs_c0, data, cntx ); return; #endif //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm5, ymm5, ymm5) vxorpd(ymm6, ymm6, ymm6) vxorpd(ymm7, ymm7, ymm7) vxorpd(ymm8, ymm8, ymm8) vxorpd(ymm9, ymm9, ymm9) vxorpd(ymm10, ymm10, ymm10) vxorpd(ymm11, ymm11, ymm11) vxorpd(ymm12, ymm12, ymm12) vxorpd(ymm13, ymm13, ymm13) vxorpd(ymm14, ymm14, ymm14) vxorpd(ymm15, ymm15, ymm15) #endif mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 3*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 3*8)) // prefetch c + 2*rs_c mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 1 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 2 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) // ---------------------------------- iteration 3 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) vmovupd(mem(rax, r8, 2), ymm2) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rax ), xmm0) vmovsd(mem(rax, r8, 1), xmm1) vmovsd(mem(rax, r8, 2), xmm2) add(imm(1*8), rax) // a += 1*cs_b = 1*8; vmovsd(mem(rbx ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vfmadd231pd(ymm2, ymm3, ymm6) vmovsd(mem(rbx, r11, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vfmadd231pd(ymm2, ymm3, ymm9) vmovsd(mem(rbx, r11, 2), xmm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vfmadd231pd(ymm2, ymm3, ymm12) vmovsd(mem(rbx, r13, 1), xmm3) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) vfmadd231pd(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 // ymm5 ymm8 ymm11 ymm14 // ymm6 ymm9 ymm12 ymm15 vhaddpd( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm7) vhaddpd( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) // xmm2[0] = sum(ymm10); xmm2[1] = sum(ymm13) vperm2f128(imm(0x20), ymm2, ymm0, ymm4 ) vhaddpd( ymm8, ymm5, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm14, ymm11, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm5 ) vhaddpd( ymm9, ymm6, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm15, ymm12, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm6 ) // ymm4 = sum(ymm4) sum(ymm7) sum(ymm10) sum(ymm13) // ymm5 = sum(ymm5) sum(ymm8) sum(ymm11) sum(ymm14) // ymm6 = sum(ymm6) sum(ymm9) sum(ymm12) sum(ymm15) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(ymm0, ymm5, ymm5) vmulpd(ymm0, ymm6, ymm6) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), ymm3, ymm4) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm5) vmovupd(ymm5, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm6) vmovupd(ymm6, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vmovupd(ymm5, mem(rcx)) add(rdi, rcx) vmovupd(ymm6, mem(rcx)) //add(rdi, rcx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rd_haswell_asm_2x4n ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { #if 0 bli_dgemmsup_r_haswell_ref ( conja, conjb, m0, n0, k0, alpha, a, rs_a0, cs_a0, b, rs_b0, cs_b0, beta, c, rs_c0, cs_c0, data, cntx ); return; #endif //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm5, ymm5, ymm5) vxorpd(ymm7, ymm7, ymm7) vxorpd(ymm8, ymm8, ymm8) vxorpd(ymm10, ymm10, ymm10) vxorpd(ymm11, ymm11, ymm11) vxorpd(ymm13, ymm13, ymm13) vxorpd(ymm14, ymm14, ymm14) #endif mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 3*8)) // prefetch c + 1*rs_c mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) // ---------------------------------- iteration 1 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) // ---------------------------------- iteration 2 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) // ---------------------------------- iteration 3 vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) vmovupd(mem(rax ), ymm0) vmovupd(mem(rax, r8, 1), ymm1) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rax ), xmm0) vmovsd(mem(rax, r8, 1), xmm1) add(imm(1*8), rax) // a += 1*cs_b = 1*8; vmovsd(mem(rbx ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovsd(mem(rbx, r11, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm7) vfmadd231pd(ymm1, ymm3, ymm8) vmovsd(mem(rbx, r11, 2), xmm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovsd(mem(rbx, r13, 1), xmm3) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vfmadd231pd(ymm0, ymm3, ymm13) vfmadd231pd(ymm1, ymm3, ymm14) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 // ymm5 ymm8 ymm11 ymm14 vhaddpd( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm7) vhaddpd( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) // xmm2[0] = sum(ymm10); xmm2[1] = sum(ymm13) vperm2f128(imm(0x20), ymm2, ymm0, ymm4 ) vhaddpd( ymm8, ymm5, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) vhaddpd( ymm14, ymm11, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) vperm2f128(imm(0x20), ymm2, ymm0, ymm5 ) // ymm4 = sum(ymm4) sum(ymm7) sum(ymm10) sum(ymm13) // ymm5 = sum(ymm5) sum(ymm8) sum(ymm11) sum(ymm14) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha vmulpd(ymm0, ymm5, ymm5) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), ymm3, ymm4) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), ymm3, ymm5) vmovupd(ymm5, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vmovupd(ymm5, mem(rcx)) //add(rdi, rcx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rd_haswell_asm_1x4n ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { #if 0 bli_dgemmsup_r_haswell_ref ( conja, conjb, m0, n0, k0, alpha, a, rs_a0, cs_a0, b, rs_b0, cs_b0, beta, c, rs_c0, cs_c0, data, cntx ); return; #endif //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; /* rrc: -------- -- -- -- | | | | -------- -- -- -- ... | | | | -------- += -- -- -- | | | | -------- | | | | -------- : -------- : */ // ------------------------------------------------------------------------- begin_asm() #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm7, ymm7, ymm7) vxorpd(ymm10, ymm10, ymm10) vxorpd(ymm13, ymm13, ymm13) #endif mov(var(a), rax) // load address of a. //mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a //lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b mov(var(c), rcx) // load address of c //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rax ), ymm0) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) // ---------------------------------- iteration 1 vmovupd(mem(rax ), ymm0) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) // ---------------------------------- iteration 2 vmovupd(mem(rax ), ymm0) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) // ---------------------------------- iteration 3 vmovupd(mem(rax ), ymm0) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) vmovupd(mem(rax ), ymm0) add(imm(4*8), rax) // a += 4*cs_b = 4*8; vmovupd(mem(rbx ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovupd(mem(rbx, r11, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovupd(mem(rbx, r11, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovupd(mem(rbx, r13, 1), ymm3) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vfmadd231pd(ymm0, ymm3, ymm13) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rax ), xmm0) add(imm(1*8), rax) // a += 1*cs_b = 1*8; vmovsd(mem(rbx ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vmovsd(mem(rbx, r11, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm7) vmovsd(mem(rbx, r11, 2), xmm3) vfmadd231pd(ymm0, ymm3, ymm10) vmovsd(mem(rbx, r13, 1), xmm3) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vfmadd231pd(ymm0, ymm3, ymm13) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 vhaddpd( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm0 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm7) vhaddpd( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddpd( xmm2, xmm1, xmm2 ) // xmm2[0] = sum(ymm10); xmm2[1] = sum(ymm13) vperm2f128(imm(0x20), ymm2, ymm0, ymm4 ) // ymm4 = sum(ymm4) sum(ymm7) sum(ymm10) sum(ymm13) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(ymm0, ymm4, ymm4) // scale by alpha //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), ymm3, ymm4) vmovupd(ymm4, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(ymm4, mem(rcx)) //add(rdi, rcx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rd_haswell_asm_6x2n ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { #if 0 bli_dgemmsup_r_haswell_ref ( conja, conjb, m0, n0, k0, alpha, a, rs_a0, cs_a0, b, rs_b0, cs_b0, beta, c, rs_c0, cs_c0, data, cntx ); return; #endif //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) //lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm5, ymm5, ymm5) vxorpd(ymm6, ymm6, ymm6) vxorpd(ymm7, ymm7, ymm7) vxorpd(ymm8, ymm8, ymm8) vxorpd(ymm9, ymm9, ymm9) vxorpd(ymm10, ymm10, ymm10) vxorpd(ymm11, ymm11, ymm11) vxorpd(ymm12, ymm12, ymm12) vxorpd(ymm13, ymm13, ymm13) vxorpd(ymm14, ymm14, ymm14) vxorpd(ymm15, ymm15, ymm15) #endif lea(mem(rcx, rdi, 2), r10) // lea(mem(r10, rdi, 1), r10) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 1*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 1*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 1*8)) // prefetch c + 2*rs_c prefetch(0, mem(r10, 1*8)) // prefetch c + 3*rs_c prefetch(0, mem(r10, rdi, 1, 1*8)) // prefetch c + 4*rs_c prefetch(0, mem(r10, rdi, 2, 1*8)) // prefetch c + 5*rs_c mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovupd(mem(rax, r8, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) vmovupd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rax, r8, 4), ymm3) vfmadd231pd(ymm0, ymm3, ymm12) vfmadd231pd(ymm1, ymm3, ymm13) vmovupd(mem(rax, r15, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) // ---------------------------------- iteration 1 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovupd(mem(rax, r8, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) vmovupd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rax, r8, 4), ymm3) vfmadd231pd(ymm0, ymm3, ymm12) vfmadd231pd(ymm1, ymm3, ymm13) vmovupd(mem(rax, r15, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) // ---------------------------------- iteration 2 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovupd(mem(rax, r8, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) vmovupd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rax, r8, 4), ymm3) vfmadd231pd(ymm0, ymm3, ymm12) vfmadd231pd(ymm1, ymm3, ymm13) vmovupd(mem(rax, r15, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) // ---------------------------------- iteration 3 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovupd(mem(rax, r8, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) vmovupd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rax, r8, 4), ymm3) vfmadd231pd(ymm0, ymm3, ymm12) vfmadd231pd(ymm1, ymm3, ymm13) vmovupd(mem(rax, r15, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovupd(mem(rax, r8, 2), ymm3) vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) vmovupd(mem(rax, r13, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovupd(mem(rax, r8, 4), ymm3) vfmadd231pd(ymm0, ymm3, ymm12) vfmadd231pd(ymm1, ymm3, ymm13) vmovupd(mem(rax, r15, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rbx ), xmm0) vmovsd(mem(rbx, r11, 1), xmm1) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vmovsd(mem(rax ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovsd(mem(rax, r8, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovsd(mem(rax, r8, 2), xmm3) vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) vmovsd(mem(rax, r13, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vmovsd(mem(rax, r8, 4), xmm3) vfmadd231pd(ymm0, ymm3, ymm12) vfmadd231pd(ymm1, ymm3, ymm13) vmovsd(mem(rax, r15, 1), xmm3) add(imm(1*8), rax) // a += 1*cs_a = 1*8; vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm5 // ymm6 ymm7 // ymm8 ymm9 // ymm10 ymm11 // ymm12 ymm13 // ymm14 ymm15 vhaddpd( ymm5, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm4 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm5) vhaddpd( ymm7, ymm6, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm6 ) vhaddpd( ymm9, ymm8, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm8 ) vhaddpd( ymm11, ymm10, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm10 ) vhaddpd( ymm13, ymm12, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm12 ) vhaddpd( ymm15, ymm14, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm14 ) // xmm4 = sum(ymm4) sum(ymm5) // xmm6 = sum(ymm6) sum(ymm7) // xmm8 = sum(ymm8) sum(ymm9) // xmm10 = sum(ymm10) sum(ymm11) // xmm12 = sum(ymm12) sum(ymm13) // xmm14 = sum(ymm14) sum(ymm15) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(xmm0, xmm4, xmm4) // scale by alpha vmulpd(xmm0, xmm6, xmm6) vmulpd(xmm0, xmm8, xmm8) vmulpd(xmm0, xmm10, xmm10) vmulpd(xmm0, xmm12, xmm12) vmulpd(xmm0, xmm14, xmm14) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), xmm3, xmm4) vmovupd(xmm4, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), xmm3, xmm6) vmovupd(xmm6, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), xmm3, xmm8) vmovupd(xmm8, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), xmm3, xmm10) vmovupd(xmm10, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), xmm3, xmm12) vmovupd(xmm12, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), xmm3, xmm14) vmovupd(xmm14, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(xmm4, mem(rcx)) add(rdi, rcx) vmovupd(xmm6, mem(rcx)) add(rdi, rcx) vmovupd(xmm8, mem(rcx)) add(rdi, rcx) vmovupd(xmm10, mem(rcx)) add(rdi, rcx) vmovupd(xmm12, mem(rcx)) add(rdi, rcx) vmovupd(xmm14, mem(rcx)) //add(rdi, rcx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rd_haswell_asm_3x2n ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { #if 0 bli_dgemmsup_r_haswell_ref ( conja, conjb, m0, n0, k0, alpha, a, rs_a0, cs_a0, b, rs_b0, cs_b0, beta, c, rs_c0, cs_c0, data, cntx ); return; #endif //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm5, ymm5, ymm5) vxorpd(ymm6, ymm6, ymm6) vxorpd(ymm7, ymm7, ymm7) vxorpd(ymm8, ymm8, ymm8) vxorpd(ymm9, ymm9, ymm9) #endif mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) //lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b // initialize loop by pre-loading // a column of a. mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) prefetch(0, mem(rcx, 1*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 1*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 1*8)) // prefetch c + 2*rs_c mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovupd(mem(rax, r8, 2), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) // ---------------------------------- iteration 1 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovupd(mem(rax, r8, 2), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) // ---------------------------------- iteration 2 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovupd(mem(rax, r8, 2), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) // ---------------------------------- iteration 3 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovupd(mem(rax, r8, 2), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovupd(mem(rax, r8, 2), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rbx ), xmm0) vmovsd(mem(rbx, r11, 1), xmm1) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vmovsd(mem(rax ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovsd(mem(rax, r8, 1), xmm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vmovsd(mem(rax, r8, 2), xmm3) add(imm(1*8), rax) // a += 1*cs_a = 1*8; vfmadd231pd(ymm0, ymm3, ymm8) vfmadd231pd(ymm1, ymm3, ymm9) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm5 // ymm6 ymm7 // ymm8 ymm9 vhaddpd( ymm5, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm4 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm5) vhaddpd( ymm7, ymm6, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm6 ) vhaddpd( ymm9, ymm8, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm8 ) // xmm4 = sum(ymm4) sum(ymm5) // xmm6 = sum(ymm6) sum(ymm7) // xmm8 = sum(ymm8) sum(ymm9) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(xmm0, xmm4, xmm4) // scale by alpha vmulpd(xmm0, xmm6, xmm6) vmulpd(xmm0, xmm8, xmm8) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), xmm3, xmm4) vmovupd(xmm4, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), xmm3, xmm6) vmovupd(xmm6, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), xmm3, xmm8) vmovupd(xmm8, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(xmm4, mem(rcx)) add(rdi, rcx) vmovupd(xmm6, mem(rcx)) add(rdi, rcx) vmovupd(xmm8, mem(rcx)) //add(rdi, rcx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rd_haswell_asm_2x2n ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { #if 0 bli_dgemmsup_r_haswell_ref ( conja, conjb, m0, n0, k0, alpha, a, rs_a0, cs_a0, b, rs_b0, cs_b0, beta, c, rs_c0, cs_c0, data, cntx ); return; #endif //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; /* rrc: -------- -- -- -- | | -------- -- -- -- ... | | -------- += -- -- -- | | -------- -- -- -- | | -------- -- -- -- : -------- -- -- -- : */ // ------------------------------------------------------------------------- begin_asm() #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm5, ymm5, ymm5) vxorpd(ymm6, ymm6, ymm6) vxorpd(ymm7, ymm7, ymm7) #endif mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) //lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b // initialize loop by pre-loading // a column of a. mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) //lea(mem(rcx, rdi, 2), rdx) // //lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 1*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 1*8)) // prefetch c + 1*rs_c mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) // ---------------------------------- iteration 1 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) // ---------------------------------- iteration 2 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) // ---------------------------------- iteration 3 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovupd(mem(rax, r8, 1), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rbx ), xmm0) vmovsd(mem(rbx, r11, 1), xmm1) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vmovsd(mem(rax ), xmm3) vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) vmovsd(mem(rax, r8, 1), xmm3) add(imm(1*8), rax) // a += 1*cs_a = 1*8; vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm5 // ymm6 ymm7 vhaddpd( ymm5, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm4 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm5) vhaddpd( ymm7, ymm6, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm6 ) // xmm4 = sum(ymm4) sum(ymm5) // xmm6 = sum(ymm6) sum(ymm7) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(xmm0, xmm4, xmm4) // scale by alpha vmulpd(xmm0, xmm6, xmm6) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), xmm3, xmm4) vmovupd(xmm4, mem(rcx)) add(rdi, rcx) vfmadd231pd(mem(rcx), xmm3, xmm6) vmovupd(xmm6, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(xmm4, mem(rcx)) add(rdi, rcx) vmovupd(xmm6, mem(rcx)) //add(rdi, rcx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_dgemmsup_rd_haswell_asm_1x2n ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, double* restrict alpha, double* restrict a, inc_t rs_a0, inc_t cs_a0, double* restrict b, inc_t rs_b0, inc_t cs_b0, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { #if 0 bli_dgemmsup_r_haswell_ref ( conja, conjb, m0, n0, k0, alpha, a, rs_a0, cs_a0, b, rs_b0, cs_b0, beta, c, rs_c0, cs_c0, data, cntx ); return; #endif //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter16 = k0 / 16; uint64_t k_left16 = k0 % 16; uint64_t k_iter4 = k_left16 / 4; uint64_t k_left1 = k_left16 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; /* rrc: -------- -- -- -- | | -------- -- -- -- ... | | -------- += -- -- -- | | -------- -- -- -- | | -------- -- -- -- : -------- -- -- -- : */ // ------------------------------------------------------------------------- begin_asm() #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorpd(ymm4, ymm4, ymm4) vxorpd(ymm5, ymm5, ymm5) #endif mov(var(a), rax) // load address of a. //mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a //lea(mem(, r8, 8), r8) // rs_a *= sizeof(double) //lea(mem(, r9, 8), r9) // cs_a *= sizeof(double) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 8), r10) // rs_b *= sizeof(double) lea(mem(, r11, 8), r11) // cs_b *= sizeof(double) //lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b // initialize loop by pre-loading // a column of a. mov(var(c), rcx) // load address of c //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(double) //lea(mem(rcx, rdi, 2), rdx) // //lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 1*8)) // prefetch c + 0*rs_c mov(var(k_iter16), rsi) // i = k_iter16; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKITER4) // if i == 0, jump to code that // contains the k_iter4 loop. label(.DLOOPKITER16) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) // ---------------------------------- iteration 1 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) // ---------------------------------- iteration 2 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) // ---------------------------------- iteration 3 vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) dec(rsi) // i -= 1; jne(.DLOOPKITER16) // iterate again if i != 0. label(.DCONSIDKITER4) mov(var(k_iter4), rsi) // i = k_iter4; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter4 loop. label(.DLOOPKITER4) // EDGE LOOP (ymm) vmovupd(mem(rbx ), ymm0) vmovupd(mem(rbx, r11, 1), ymm1) add(imm(4*8), rbx) // b += 4*rs_b = 4*8; vmovupd(mem(rax ), ymm3) add(imm(4*8), rax) // a += 4*cs_a = 4*8; vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) dec(rsi) // i -= 1; jne(.DLOOPKITER4) // iterate again if i != 0. label(.DCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.DLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovsd(mem(rbx ), xmm0) vmovsd(mem(rbx, r11, 1), xmm1) add(imm(1*8), rbx) // b += 1*rs_b = 1*8; vmovsd(mem(rax ), xmm3) add(imm(1*8), rax) // a += 1*cs_a = 1*8; vfmadd231pd(ymm0, ymm3, ymm4) vfmadd231pd(ymm1, ymm3, ymm5) dec(rsi) // i -= 1; jne(.DLOOPKLEFT1) // iterate again if i != 0. label(.DPOSTACCUM) // ymm4 ymm5 vhaddpd( ymm5, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddpd( xmm0, xmm1, xmm4 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm5) // xmm4 = sum(ymm4) sum(ymm5) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rax), ymm0) // load alpha and duplicate vbroadcastsd(mem(rbx), ymm3) // load beta and duplicate vmulpd(xmm0, xmm4, xmm4) // scale by alpha //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(double) // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case label(.DROWSTORED) vfmadd231pd(mem(rcx), xmm3, xmm4) vmovupd(xmm4, mem(rcx)) //add(rdi, rcx) jmp(.DDONE) // jump to end. label(.DBETAZERO) label(.DROWSTORBZ) vmovupd(xmm4, mem(rcx)) //add(rdi, rcx) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter16] "m" (k_iter16), [k_iter4] "m" (k_iter4), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } blis-0.9.0/kernels/haswell/3/sup/s6x16/000077500000000000000000000000001422157504600174215ustar00rootroot00000000000000blis-0.9.0/kernels/haswell/3/sup/s6x16/bli_gemmsup_r_haswell_ref_sMx1.c000066400000000000000000000167331422157504600257060ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define BLIS_ASM_SYNTAX_ATT #include "bli_x86_asm_macros.h" /* rrr: -------- ------ -------- -------- ------ -------- -------- += ------ ... -------- -------- ------ -------- -------- ------ : -------- ------ : rcr: -------- | | | | -------- -------- | | | | -------- -------- += | | | | ... -------- -------- | | | | -------- -------- | | | | : -------- | | | | : Assumptions: - B is row-stored; - A is row- or column-stored; - m0 and n0 are at most MR and NR, respectively. Therefore, this (r)ow-preferential kernel is well-suited for contiguous (v)ector loads on B and single-element broadcasts from A. NOTE: These kernels explicitly support column-oriented IO, implemented via an in-register transpose. And thus they also support the crr and ccr cases, though only crr is ever utilized (because ccr is handled by transposing the operation and executing rcr, which does not incur the cost of the in-register transpose). crr: | | | | | | | | ------ -------- | | | | | | | | ------ -------- | | | | | | | | += ------ ... -------- | | | | | | | | ------ -------- | | | | | | | | ------ : | | | | | | | | ------ : */ // Prototype reference microkernels. GEMMSUP_KER_PROT( float, s, gemmsup_r_haswell_ref ) // NOTE: Normally, for any "?x1" kernel, we would call the reference kernel. // However, at least one other subconfiguration (zen) uses this kernel set, so // we need to be able to call a set of "?x1" kernels that we know will actually // exist regardless of which subconfiguration these kernels were used by. Thus, // the compromise employed here is to inline the reference kernel so it gets // compiled as part of the haswell kernel set, and hence can unconditionally be // called by other kernels within that kernel set. #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, mdim ) \ \ void PASTEMAC(ch,opname) \ ( \ conj_t conja, \ conj_t conjb, \ dim_t m, \ dim_t n, \ dim_t k, \ ctype* restrict alpha, \ ctype* restrict a, inc_t rs_a, inc_t cs_a, \ ctype* restrict b, inc_t rs_b, inc_t cs_b, \ ctype* restrict beta, \ ctype* restrict c, inc_t rs_c, inc_t cs_c, \ auxinfo_t* restrict data, \ cntx_t* restrict cntx \ ) \ { \ for ( dim_t i = 0; i < mdim; ++i ) \ { \ ctype* restrict ci = &c[ i*rs_c ]; \ ctype* restrict ai = &a[ i*rs_a ]; \ \ /* for ( dim_t j = 0; j < 1; ++j ) */ \ { \ ctype* restrict cij = ci /*[ j*cs_c ]*/ ; \ ctype* restrict bj = b /*[ j*cs_b ]*/ ; \ ctype ab; \ \ PASTEMAC(ch,set0s)( ab ); \ \ /* Perform a dot product to update the (i,j) element of c. */ \ for ( dim_t l = 0; l < k; ++l ) \ { \ ctype* restrict aij = &ai[ l*cs_a ]; \ ctype* restrict bij = &bj[ l*rs_b ]; \ \ PASTEMAC(ch,dots)( *aij, *bij, ab ); \ } \ \ /* If beta is one, add ab into c. If beta is zero, overwrite c with the result in ab. Otherwise, scale by beta and accumulate ab to c. */ \ if ( PASTEMAC(ch,eq1)( *beta ) ) \ { \ PASTEMAC(ch,axpys)( *alpha, ab, *cij ); \ } \ else if ( PASTEMAC(d,eq0)( *beta ) ) \ { \ PASTEMAC(ch,scal2s)( *alpha, ab, *cij ); \ } \ else \ { \ PASTEMAC(ch,axpbys)( *alpha, ab, *beta, *cij ); \ } \ } \ } \ } GENTFUNC( float, s, gemmsup_r_haswell_ref_6x1, 6 ) GENTFUNC( float, s, gemmsup_r_haswell_ref_5x1, 5 ) GENTFUNC( float, s, gemmsup_r_haswell_ref_4x1, 4 ) GENTFUNC( float, s, gemmsup_r_haswell_ref_3x1, 3 ) GENTFUNC( float, s, gemmsup_r_haswell_ref_2x1, 2 ) GENTFUNC( float, s, gemmsup_r_haswell_ref_1x1, 1 ) // ----------------------------------------------------------------------------- #if 0 // Temporary definition of general-purpose sup kernel. #undef GENTFUNC #define GENTFUNC( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ conj_t conja, \ conj_t conjb, \ dim_t m, \ dim_t n, \ dim_t k, \ ctype* restrict alpha, \ ctype* restrict a, inc_t rs_a, inc_t cs_a, \ ctype* restrict b, inc_t rs_b, inc_t cs_b, \ ctype* restrict beta, \ ctype* restrict c, inc_t rs_c, inc_t cs_c, \ auxinfo_t* restrict data, \ cntx_t* restrict cntx \ ) \ { \ for ( dim_t i = 0; i < m; ++i ) \ { \ ctype* restrict ci = &c[ i*rs_c ]; \ ctype* restrict ai = &a[ i*rs_a ]; \ \ for ( dim_t j = 0; j < n; ++j ) \ { \ ctype* restrict cij = &ci[ j*cs_c ]; \ ctype* restrict bj = &b [ j*cs_b ]; \ ctype ab; \ \ PASTEMAC(ch,set0s)( ab ); \ \ /* Perform a dot product to update the (i,j) element of c. */ \ for ( dim_t l = 0; l < k; ++l ) \ { \ ctype* restrict aij = &ai[ l*cs_a ]; \ ctype* restrict bij = &bj[ l*rs_b ]; \ \ PASTEMAC(ch,dots)( *aij, *bij, ab ); \ } \ \ /* If beta is one, add ab into c. If beta is zero, overwrite c with the result in ab. Otherwise, scale by beta and accumulate ab to c. */ \ if ( PASTEMAC(ch,eq1)( *beta ) ) \ { \ PASTEMAC(ch,axpys)( *alpha, ab, *cij ); \ } \ else if ( PASTEMAC(d,eq0)( *beta ) ) \ { \ PASTEMAC(ch,scal2s)( *alpha, ab, *cij ); \ } \ else \ { \ PASTEMAC(ch,axpbys)( *alpha, ab, *beta, *cij ); \ } \ } \ } \ } GENTFUNC( float, s, gemmsup_r_haswell_ref ) #endif blis-0.9.0/kernels/haswell/3/sup/s6x16/bli_gemmsup_rd_haswell_asm_sMx1.c000066400000000000000000001326601422157504600260540ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define BLIS_ASM_SYNTAX_ATT #include "bli_x86_asm_macros.h" /* rrc: -------- ------ | | | | | | | | -------- ------ | | | | | | | | -------- += ------ ... | | | | | | | | -------- ------ | | | | | | | | -------- ------ : -------- ------ : Assumptions: - C is row-stored and B is column-stored; - A is row-stored; - m0 and n0 are at most MR and NR, respectively. Therefore, this (r)ow-preferential microkernel is well-suited for a dot-product-based accumulation that performs vector loads from both A and B. */ // Prototype reference microkernels. GEMMSUP_KER_PROT( float, s, gemmsup_r_haswell_ref ) void bli_sgemmsup_rd_haswell_asm_6x1 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter32 = k0 / 32; uint64_t k_left32 = k0 % 32; uint64_t k_iter8 = k_left32 / 8; uint64_t k_left1 = k_left32 % 8; //uint64_t m_iter = m0 / 3; //uint64_t m_left = m0 % 3; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) //lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. //mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) //lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) //lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b //lea(mem(r8, r8, 2), r10) // r10 = 3*rs_a mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) // r12 = rcx = c // r14 = rax = a // rdx = rbx = b #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorps ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorps(ymm4, ymm4, ymm4) vxorps(ymm6, ymm6, ymm6) vxorps(ymm8, ymm8, ymm8) vxorps(ymm10, ymm10, ymm10) vxorps(ymm12, ymm12, ymm12) vxorps(ymm14, ymm14, ymm14) #endif //lea(mem(r12), rcx) // rcx = c_ii; //lea(mem(r14), rax) // rax = a_ii; //lea(mem(rdx), rbx) // rbx = b; #if 1 //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) lea(mem(rcx, rdi, 2), r10) // lea(mem(r10, rdi, 1), r10) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 0*4)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 0*4)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 0*4)) // prefetch c + 2*rs_c prefetch(0, mem(r10, 0*4)) // prefetch c + 3*rs_c prefetch(0, mem(r10, rdi, 1, 0*4)) // prefetch c + 4*rs_c prefetch(0, mem(r10, rdi, 2, 0*4)) // prefetch c + 5*rs_c #endif mov(var(k_iter32), rsi) // i = k_iter32; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKITER8) // if i == 0, jump to code that // contains the k_iter8 loop. label(.SLOOPKITER32) // MAIN LOOP // ---------------------------------- iteration 0 #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovups(mem(rbx ), ymm0) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vmovups(mem(rax ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vmovups(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm6) vmovups(mem(rax, r8, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm8) vmovups(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vmovups(mem(rax, r8, 4), ymm3) vfmadd231ps(ymm0, ymm3, ymm12) vmovups(mem(rax, r15, 1), ymm3) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vfmadd231ps(ymm0, ymm3, ymm14) // ---------------------------------- iteration 1 vmovups(mem(rbx ), ymm0) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vmovups(mem(rax ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vmovups(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm6) vmovups(mem(rax, r8, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm8) vmovups(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vmovups(mem(rax, r8, 4), ymm3) vfmadd231ps(ymm0, ymm3, ymm12) vmovups(mem(rax, r15, 1), ymm3) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vfmadd231ps(ymm0, ymm3, ymm14) // ---------------------------------- iteration 2 #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovups(mem(rbx ), ymm0) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vmovups(mem(rax ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vmovups(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm6) vmovups(mem(rax, r8, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm8) vmovups(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vmovups(mem(rax, r8, 4), ymm3) vfmadd231ps(ymm0, ymm3, ymm12) vmovups(mem(rax, r15, 1), ymm3) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vfmadd231ps(ymm0, ymm3, ymm14) // ---------------------------------- iteration 3 vmovups(mem(rbx ), ymm0) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vmovups(mem(rax ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vmovups(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm6) vmovups(mem(rax, r8, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm8) vmovups(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vmovups(mem(rax, r8, 4), ymm3) vfmadd231ps(ymm0, ymm3, ymm12) vmovups(mem(rax, r15, 1), ymm3) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vfmadd231ps(ymm0, ymm3, ymm14) dec(rsi) // i -= 1; jne(.SLOOPKITER32) // iterate again if i != 0. label(.SCONSIDKITER8) mov(var(k_iter8), rsi) // i = k_iter8; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter8 loop. label(.SLOOPKITER8) // EDGE LOOP (ymm) #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovups(mem(rbx ), ymm0) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vmovups(mem(rax ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vmovups(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm6) vmovups(mem(rax, r8, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm8) vmovups(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vmovups(mem(rax, r8, 4), ymm3) vfmadd231ps(ymm0, ymm3, ymm12) vmovups(mem(rax, r15, 1), ymm3) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vfmadd231ps(ymm0, ymm3, ymm14) dec(rsi) // i -= 1; jne(.SLOOPKITER8) // iterate again if i != 0. label(.SCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.SLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovss(mem(rbx ), xmm0) add(imm(1*4), rbx) // b += 8*rs_b = 8*4; vmovss(mem(rax ), xmm3) vfmadd231ps(ymm0, ymm3, ymm4) vmovss(mem(rax, r8, 1), xmm3) vfmadd231ps(ymm0, ymm3, ymm6) vmovss(mem(rax, r8, 2), xmm3) vfmadd231ps(ymm0, ymm3, ymm8) vmovss(mem(rax, r13, 1), xmm3) vfmadd231ps(ymm0, ymm3, ymm10) vmovss(mem(rax, r8, 4), xmm3) vfmadd231ps(ymm0, ymm3, ymm12) vmovss(mem(rax, r15, 1), xmm3) add(imm(1*4), rax) // a += 8*cs_a = 8*4; vfmadd231ps(ymm0, ymm3, ymm14) dec(rsi) // i -= 1; jne(.SLOOPKLEFT1) // iterate again if i != 0. label(.SPOSTACCUM) // ymm4 // ymm6 // ymm8 // ymm10 // ymm12 // ymm14 vhaddps( ymm5, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vhaddps( xmm1, xmm0, xmm0 ) vpermilps(imm(0xd8), xmm0, xmm0) vhaddps( xmm0, xmm0, xmm4 ) vhaddps( ymm7, ymm6, ymm2 ) vextractf128(imm(1), ymm2, xmm3 ) vhaddps( xmm3, xmm2, xmm2 ) vpermilps(imm(0xd8), xmm2, xmm2) vhaddps( xmm2, xmm2, xmm6 ) vhaddps( ymm9, ymm8, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vhaddps( xmm1, xmm0, xmm0 ) vpermilps(imm(0xd8), xmm0, xmm0) vhaddps( xmm0, xmm0, xmm8 ) vhaddps( ymm11, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm3 ) vhaddps( xmm3, xmm2, xmm2 ) vpermilps(imm(0xd8), xmm2, xmm2) vhaddps( xmm2, xmm2, xmm10 ) vhaddps( ymm13, ymm12, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vhaddps( xmm1, xmm0, xmm0 ) vpermilps(imm(0xd8), xmm0, xmm0) vhaddps( xmm0, xmm0, xmm12 ) vhaddps( ymm15, ymm14, ymm2 ) vextractf128(imm(1), ymm2, xmm3 ) vhaddps( xmm3, xmm2, xmm2 ) vpermilps(imm(0xd8), xmm2, xmm2) vhaddps( xmm2, xmm2, xmm14 ) // xmm4[0] = sum(ymm4) // xmm6[0] = sum(ymm6) // xmm8[0] = sum(ymm8) // xmm10[0] = sum(ymm10) // xmm12[0] = sum(ymm12) // xmm14[0] = sum(ymm14) //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), xmm0) // load alpha and duplicate vbroadcastss(mem(rbx), xmm3) // load beta and duplicate vmulps(xmm0, xmm4, xmm4) // scale by alpha vmulps(xmm0, xmm6, xmm6) vmulps(xmm0, xmm8, xmm8) vmulps(xmm0, xmm10, xmm10) vmulps(xmm0, xmm12, xmm12) vmulps(xmm0, xmm14, xmm14) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(float) // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case label(.SROWSTORED) vmovss(mem(rcx), xmm0) vfmadd231ps(xmm0, xmm3, xmm4) vmovss(xmm4, mem(rcx)) add(rdi, rcx) vmovss(mem(rcx), xmm0) vfmadd231ps(xmm0, xmm3, xmm6) vmovss(xmm6, mem(rcx)) add(rdi, rcx) vmovss(mem(rcx), xmm0) vfmadd231ps(xmm0, xmm3, xmm8) vmovss(xmm8, mem(rcx)) add(rdi, rcx) vmovss(mem(rcx), xmm0) vfmadd231ps(xmm0, xmm3, xmm10) vmovss(xmm10, mem(rcx)) add(rdi, rcx) vmovss(mem(rcx), xmm0) vfmadd231ps(xmm0, xmm3, xmm12) vmovss(xmm12, mem(rcx)) add(rdi, rcx) vmovss(mem(rcx), xmm0) vfmadd231ps(xmm0, xmm3, xmm14) vmovss(xmm14, mem(rcx)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SBETAZERO) label(.SROWSTORBZ) vmovss(xmm4, mem(rcx)) add(rdi, rcx) vmovss(xmm6, mem(rcx)) add(rdi, rcx) vmovss(xmm8, mem(rcx)) add(rdi, rcx) vmovss(xmm10, mem(rcx)) add(rdi, rcx) vmovss(xmm12, mem(rcx)) add(rdi, rcx) vmovss(xmm14, mem(rcx)) //add(rdi, rcx) label(.SDONE) label(.SRETURN) end_asm( : // output operands (none) : // input operands [k_iter32] "m" (k_iter32), [k_iter8] "m" (k_iter8), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_sgemmsup_rd_haswell_asm_3x1 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter32 = k0 / 32; uint64_t k_left32 = k0 % 32; uint64_t k_iter8 = k_left32 / 8; uint64_t k_left1 = k_left32 % 8; //uint64_t m_iter = m0 / 3; //uint64_t m_left = m0 % 3; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) //lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. //mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) //lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) //lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b //lea(mem(r8, r8, 2), r10) // r10 = 3*rs_a mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) // r12 = rcx = c // r14 = rax = a // rdx = rbx = b #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorps ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorps(ymm4, ymm4, ymm4) vxorps(ymm6, ymm6, ymm6) vxorps(ymm8, ymm8, ymm8) #endif //lea(mem(r12), rcx) // rcx = c_ii; //lea(mem(r14), rax) // rax = a_ii; //lea(mem(rdx), rbx) // rbx = b; #if 1 //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) //lea(mem(rcx, rdi, 2), r10) // //lea(mem(r10, rdi, 1), r10) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 0*4)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 0*4)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 0*4)) // prefetch c + 2*rs_c #endif mov(var(k_iter32), rsi) // i = k_iter32; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKITER8) // if i == 0, jump to code that // contains the k_iter8 loop. label(.SLOOPKITER32) // MAIN LOOP // ---------------------------------- iteration 0 #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovups(mem(rbx ), ymm0) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vmovups(mem(rax ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vmovups(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm6) vmovups(mem(rax, r8, 2), ymm3) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vfmadd231ps(ymm0, ymm3, ymm8) // ---------------------------------- iteration 1 vmovups(mem(rbx ), ymm0) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vmovups(mem(rax ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vmovups(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm6) vmovups(mem(rax, r8, 2), ymm3) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vfmadd231ps(ymm0, ymm3, ymm8) // ---------------------------------- iteration 2 #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovups(mem(rbx ), ymm0) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vmovups(mem(rax ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vmovups(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm6) vmovups(mem(rax, r8, 2), ymm3) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vfmadd231ps(ymm0, ymm3, ymm8) // ---------------------------------- iteration 3 vmovups(mem(rbx ), ymm0) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vmovups(mem(rax ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vmovups(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm6) vmovups(mem(rax, r8, 2), ymm3) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vfmadd231ps(ymm0, ymm3, ymm8) dec(rsi) // i -= 1; jne(.SLOOPKITER32) // iterate again if i != 0. label(.SCONSIDKITER8) mov(var(k_iter8), rsi) // i = k_iter8; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter8 loop. label(.SLOOPKITER8) // EDGE LOOP (ymm) #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovups(mem(rbx ), ymm0) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vmovups(mem(rax ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vmovups(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm6) vmovups(mem(rax, r8, 2), ymm3) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vfmadd231ps(ymm0, ymm3, ymm8) dec(rsi) // i -= 1; jne(.SLOOPKITER8) // iterate again if i != 0. label(.SCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.SLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovss(mem(rbx ), xmm0) add(imm(1*4), rbx) // b += 8*rs_b = 8*4; vmovss(mem(rax ), xmm3) vfmadd231ps(ymm0, ymm3, ymm4) vmovss(mem(rax, r8, 1), xmm3) vfmadd231ps(ymm0, ymm3, ymm6) vmovss(mem(rax, r8, 2), xmm3) add(imm(1*4), rax) // a += 8*cs_a = 8*4; vfmadd231ps(ymm0, ymm3, ymm8) dec(rsi) // i -= 1; jne(.SLOOPKLEFT1) // iterate again if i != 0. label(.SPOSTACCUM) // ymm4 // ymm6 // ymm8 vhaddps( ymm5, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vhaddps( xmm1, xmm0, xmm0 ) vpermilps(imm(0xd8), xmm0, xmm0) vhaddps( xmm0, xmm0, xmm4 ) vhaddps( ymm7, ymm6, ymm2 ) vextractf128(imm(1), ymm2, xmm3 ) vhaddps( xmm3, xmm2, xmm2 ) vpermilps(imm(0xd8), xmm2, xmm2) vhaddps( xmm2, xmm2, xmm6 ) vhaddps( ymm9, ymm8, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vhaddps( xmm1, xmm0, xmm0 ) vpermilps(imm(0xd8), xmm0, xmm0) vhaddps( xmm0, xmm0, xmm8 ) // xmm4[0] = sum(ymm4) // xmm6[0] = sum(ymm6) // xmm8[0] = sum(ymm8) //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), xmm0) // load alpha and duplicate vbroadcastss(mem(rbx), xmm3) // load beta and duplicate vmulps(xmm0, xmm4, xmm4) // scale by alpha vmulps(xmm0, xmm6, xmm6) vmulps(xmm0, xmm8, xmm8) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(float) // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case label(.SROWSTORED) vmovss(mem(rcx), xmm0) vfmadd231ps(xmm0, xmm3, xmm4) vmovss(xmm4, mem(rcx)) add(rdi, rcx) vmovss(mem(rcx), xmm0) vfmadd231ps(xmm0, xmm3, xmm6) vmovss(xmm6, mem(rcx)) add(rdi, rcx) vmovss(mem(rcx), xmm0) vfmadd231ps(xmm0, xmm3, xmm8) vmovss(xmm8, mem(rcx)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SBETAZERO) label(.SROWSTORBZ) vmovss(xmm4, mem(rcx)) add(rdi, rcx) vmovss(xmm6, mem(rcx)) add(rdi, rcx) vmovss(xmm8, mem(rcx)) //add(rdi, rcx) label(.SDONE) label(.SRETURN) end_asm( : // output operands (none) : // input operands [k_iter32] "m" (k_iter32), [k_iter8] "m" (k_iter8), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_sgemmsup_rd_haswell_asm_2x1 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter32 = k0 / 32; uint64_t k_left32 = k0 % 32; uint64_t k_iter8 = k_left32 / 8; uint64_t k_left1 = k_left32 % 8; //uint64_t m_iter = m0 / 3; //uint64_t m_left = m0 % 3; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) //lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. //mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) //lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) //lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b //lea(mem(r8, r8, 2), r10) // r10 = 3*rs_a mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) // r12 = rcx = c // r14 = rax = a // rdx = rbx = b #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorps ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorps(ymm4, ymm4, ymm4) vxorps(ymm6, ymm6, ymm6) #endif //lea(mem(r12), rcx) // rcx = c_ii; //lea(mem(r14), rax) // rax = a_ii; //lea(mem(rdx), rbx) // rbx = b; #if 1 //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) //lea(mem(rcx, rdi, 2), r10) // //lea(mem(r10, rdi, 1), r10) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 0*4)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 0*4)) // prefetch c + 1*rs_c #endif mov(var(k_iter32), rsi) // i = k_iter32; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKITER8) // if i == 0, jump to code that // contains the k_iter8 loop. label(.SLOOPKITER32) // MAIN LOOP // ---------------------------------- iteration 0 #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovups(mem(rbx ), ymm0) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vmovups(mem(rax ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vmovups(mem(rax, r8, 1), ymm3) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vfmadd231ps(ymm0, ymm3, ymm6) // ---------------------------------- iteration 1 vmovups(mem(rbx ), ymm0) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vmovups(mem(rax ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vmovups(mem(rax, r8, 1), ymm3) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vfmadd231ps(ymm0, ymm3, ymm6) // ---------------------------------- iteration 2 #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovups(mem(rbx ), ymm0) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vmovups(mem(rax ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vmovups(mem(rax, r8, 1), ymm3) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vfmadd231ps(ymm0, ymm3, ymm6) // ---------------------------------- iteration 3 vmovups(mem(rbx ), ymm0) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vmovups(mem(rax ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vmovups(mem(rax, r8, 1), ymm3) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vfmadd231ps(ymm0, ymm3, ymm6) dec(rsi) // i -= 1; jne(.SLOOPKITER32) // iterate again if i != 0. label(.SCONSIDKITER8) mov(var(k_iter8), rsi) // i = k_iter8; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter8 loop. label(.SLOOPKITER8) // EDGE LOOP (ymm) #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovups(mem(rbx ), ymm0) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vmovups(mem(rax ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vmovups(mem(rax, r8, 1), ymm3) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vfmadd231ps(ymm0, ymm3, ymm6) dec(rsi) // i -= 1; jne(.SLOOPKITER8) // iterate again if i != 0. label(.SCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.SLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovss(mem(rbx ), xmm0) add(imm(1*4), rbx) // b += 8*rs_b = 8*4; vmovss(mem(rax ), xmm3) vfmadd231ps(ymm0, ymm3, ymm4) vmovss(mem(rax, r8, 1), xmm3) add(imm(1*4), rax) // a += 8*cs_a = 8*4; vfmadd231ps(ymm0, ymm3, ymm6) dec(rsi) // i -= 1; jne(.SLOOPKLEFT1) // iterate again if i != 0. label(.SPOSTACCUM) // ymm4 // ymm6 vhaddps( ymm5, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vhaddps( xmm1, xmm0, xmm0 ) vpermilps(imm(0xd8), xmm0, xmm0) vhaddps( xmm0, xmm0, xmm4 ) vhaddps( ymm7, ymm6, ymm2 ) vextractf128(imm(1), ymm2, xmm3 ) vhaddps( xmm3, xmm2, xmm2 ) vpermilps(imm(0xd8), xmm2, xmm2) vhaddps( xmm2, xmm2, xmm6 ) // xmm4[0] = sum(ymm4) // xmm6[0] = sum(ymm6) //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), xmm0) // load alpha and duplicate vbroadcastss(mem(rbx), xmm3) // load beta and duplicate vmulps(xmm0, xmm4, xmm4) // scale by alpha vmulps(xmm0, xmm6, xmm6) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(float) // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case label(.SROWSTORED) vmovss(mem(rcx), xmm0) vfmadd231ps(xmm0, xmm3, xmm4) vmovss(xmm4, mem(rcx)) add(rdi, rcx) vmovss(mem(rcx), xmm0) vfmadd231ps(xmm0, xmm3, xmm6) vmovss(xmm6, mem(rcx)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SBETAZERO) label(.SROWSTORBZ) vmovss(xmm4, mem(rcx)) add(rdi, rcx) vmovss(xmm6, mem(rcx)) //add(rdi, rcx) label(.SDONE) label(.SRETURN) end_asm( : // output operands (none) : // input operands [k_iter32] "m" (k_iter32), [k_iter8] "m" (k_iter8), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_sgemmsup_rd_haswell_asm_1x1 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter32 = k0 / 32; uint64_t k_left32 = k0 % 32; uint64_t k_iter8 = k_left32 / 8; uint64_t k_left1 = k_left32 % 8; //uint64_t m_iter = m0 / 3; //uint64_t m_left = m0 % 3; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) //lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. //mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) //lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) //lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b //lea(mem(r8, r8, 2), r10) // r10 = 3*rs_a mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) // r12 = rcx = c // r14 = rax = a // rdx = rbx = b #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorps ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorps(ymm4, ymm4, ymm4) #endif //lea(mem(r12), rcx) // rcx = c_ii; //lea(mem(r14), rax) // rax = a_ii; //lea(mem(rdx), rbx) // rbx = b; #if 1 //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) //lea(mem(rcx, rdi, 2), r10) // //lea(mem(r10, rdi, 1), r10) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 0*4)) // prefetch c + 0*rs_c #endif mov(var(k_iter32), rsi) // i = k_iter32; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKITER8) // if i == 0, jump to code that // contains the k_iter8 loop. label(.SLOOPKITER32) // MAIN LOOP // ---------------------------------- iteration 0 #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovups(mem(rbx ), ymm0) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vmovups(mem(rax ), ymm3) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vfmadd231ps(ymm0, ymm3, ymm4) // ---------------------------------- iteration 1 vmovups(mem(rbx ), ymm0) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vmovups(mem(rax ), ymm3) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vfmadd231ps(ymm0, ymm3, ymm4) // ---------------------------------- iteration 2 #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovups(mem(rbx ), ymm0) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vmovups(mem(rax ), ymm3) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vfmadd231ps(ymm0, ymm3, ymm4) // ---------------------------------- iteration 3 vmovups(mem(rbx ), ymm0) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vmovups(mem(rax ), ymm3) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vfmadd231ps(ymm0, ymm3, ymm4) dec(rsi) // i -= 1; jne(.SLOOPKITER32) // iterate again if i != 0. label(.SCONSIDKITER8) mov(var(k_iter8), rsi) // i = k_iter8; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter8 loop. label(.SLOOPKITER8) // EDGE LOOP (ymm) #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovups(mem(rbx ), ymm0) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vmovups(mem(rax ), ymm3) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vfmadd231ps(ymm0, ymm3, ymm4) dec(rsi) // i -= 1; jne(.SLOOPKITER8) // iterate again if i != 0. label(.SCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.SLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovss(mem(rbx ), xmm0) add(imm(1*4), rbx) // b += 8*rs_b = 8*4; vmovss(mem(rax ), xmm3) add(imm(1*4), rax) // a += 8*cs_a = 8*4; vfmadd231ps(ymm0, ymm3, ymm4) dec(rsi) // i -= 1; jne(.SLOOPKLEFT1) // iterate again if i != 0. label(.SPOSTACCUM) // ymm4 // ymm6 vhaddps( ymm5, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vhaddps( xmm1, xmm0, xmm0 ) vpermilps(imm(0xd8), xmm0, xmm0) vhaddps( xmm0, xmm0, xmm4 ) // xmm4[0] = sum(ymm4) // xmm6[0] = sum(ymm6) //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), xmm0) // load alpha and duplicate vbroadcastss(mem(rbx), xmm3) // load beta and duplicate vmulps(xmm0, xmm4, xmm4) // scale by alpha //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(float) // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case label(.SROWSTORED) vmovss(mem(rcx), xmm0) vfmadd231ps(xmm0, xmm3, xmm4) vmovss(xmm4, mem(rcx)) add(rdi, rcx) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SBETAZERO) label(.SROWSTORBZ) vmovss(xmm4, mem(rcx)) //add(rdi, rcx) label(.SDONE) label(.SRETURN) end_asm( : // output operands (none) : // input operands [k_iter32] "m" (k_iter32), [k_iter8] "m" (k_iter8), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } blis-0.9.0/kernels/haswell/3/sup/s6x16/bli_gemmsup_rd_haswell_asm_sMx12.c000066400000000000000000001221721422157504600261330ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define BLIS_ASM_SYNTAX_ATT #include "bli_x86_asm_macros.h" /* rrc: -------- ------ | | | | | | | | -------- ------ | | | | | | | | -------- += ------ ... | | | | | | | | -------- ------ | | | | | | | | -------- ------ : -------- ------ : Assumptions: - C is row-stored and B is column-stored; - A is row-stored; - m0 and n0 are at most MR and NR, respectively. Therefore, this (r)ow-preferential microkernel is well-suited for a dot-product-based accumulation that performs vector loads from both A and B. */ // Prototype reference microkernels. GEMMSUP_KER_PROT( float, s, gemmsup_r_haswell_ref ) void bli_sgemmsup_rd_haswell_asm_6x12 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter32 = k0 / 32; uint64_t k_left32 = k0 % 32; uint64_t k_iter8 = k_left32 / 8; uint64_t k_left1 = k_left32 % 8; uint64_t m_iter = m0 / 3; //uint64_t m_left = m0 % 3; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. //mov(var(a), r14) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) //lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a //mov(var(b), rdx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b lea(mem(r8, r8, 2), r10) // r10 = 3*rs_a //mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) // r12 = rcx = c // r14 = rax = a // rdx = rbx = b // r9 = m dim index ii // r15 = n dim index jj mov(imm(0), r15) // jj = 0; label(.SLOOP3X4J) // LOOP OVER jj = [ 0 1 ... ] mov(var(a), r14) // load address of a mov(var(b), rdx) // load address of b mov(var(c), r12) // load address of c lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(imm(1*4), rsi) // rsi *= cs_c*sizeof(float) = 1*4 lea(mem(r12, rsi, 1), r12) // r12 = c + 4*jj*cs_c; lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(r11, rsi) // rsi *= cs_b; lea(mem(rdx, rsi, 1), rdx) // rbx = b + 4*jj*cs_b; mov(var(m_iter), r9) // ii = m_iter; label(.SLOOP3X4I) // LOOP OVER ii = [ m_iter ... 1 0 ] #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorps ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorps(ymm4, ymm4, ymm4) vxorps(ymm5, ymm5, ymm5) vxorps(ymm6, ymm6, ymm6) vxorps(ymm7, ymm7, ymm7) vxorps(ymm8, ymm8, ymm8) vxorps(ymm9, ymm9, ymm9) vxorps(ymm10, ymm10, ymm10) vxorps(ymm11, ymm11, ymm11) vxorps(ymm12, ymm12, ymm12) vxorps(ymm13, ymm13, ymm13) vxorps(ymm14, ymm14, ymm14) vxorps(ymm15, ymm15, ymm15) #endif lea(mem(r12), rcx) // rcx = c_iijj; lea(mem(r14), rax) // rax = a_ii; lea(mem(rdx), rbx) // rbx = b_jj; #if 1 //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) prefetch(0, mem(rcx, 1*4)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 1*4)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 1*4)) // prefetch c + 2*rs_c #endif lea(mem(r8, r8, 4), rbp) // rbp = 5*rs_a mov(var(k_iter32), rsi) // i = k_iter32; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKITER8) // if i == 0, jump to code that // contains the k_iter8 loop. label(.SLOOPKITER32) // MAIN LOOP // ---------------------------------- iteration 0 #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) vmovups(mem(rax, r8, 2), ymm2) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) // ---------------------------------- iteration 1 vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) vmovups(mem(rax, r8, 2), ymm2) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) // ---------------------------------- iteration 2 #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) vmovups(mem(rax, r8, 2), ymm2) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) // ---------------------------------- iteration 3 vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) vmovups(mem(rax, r8, 2), ymm2) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.SLOOPKITER32) // iterate again if i != 0. label(.SCONSIDKITER8) mov(var(k_iter8), rsi) // i = k_iter8; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter8 loop. label(.SLOOPKITER8) // EDGE LOOP (ymm) #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) vmovups(mem(rax, r8, 2), ymm2) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.SLOOPKITER8) // iterate again if i != 0. label(.SCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.SLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovss(mem(rax ), xmm0) vmovss(mem(rax, r8, 1), xmm1) vmovss(mem(rax, r8, 2), xmm2) add(imm(1*4), rax) // a += 1*cs_a = 1*4; vmovss(mem(rbx ), xmm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovss(mem(rbx, r11, 1), xmm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovss(mem(rbx, r11, 2), xmm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovss(mem(rbx, r13, 1), xmm3) add(imm(1*4), rbx) // b += 1*rs_b = 1*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.SLOOPKLEFT1) // iterate again if i != 0. label(.SPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 // ymm5 ymm8 ymm11 ymm14 // ymm6 ymm9 ymm12 ymm15 vhaddps( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vhaddps( xmm1, xmm0, xmm0 ) vpermilps(imm(0xd8), xmm0, xmm0) vhaddps( xmm0, xmm0, xmm0 ) vhaddps( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm3 ) vhaddps( xmm3, xmm2, xmm2 ) vpermilps(imm(0xd8), xmm2, xmm2) vhaddps( xmm2, xmm2, xmm2 ) vshufps(imm(0x44), xmm2, xmm0, xmm4) // xmm4[0] = sum(ymm4); xmm4[1] = sum(ymm7) // xmm4[2] = sum(ymm10); xmm4[3] = sum(ymm13) vhaddps( ymm8, ymm5, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vhaddps( xmm1, xmm0, xmm0 ) vpermilps(imm(0xd8), xmm0, xmm0) vhaddps( xmm0, xmm0, xmm0 ) vhaddps( ymm14, ymm11, ymm2 ) vextractf128(imm(1), ymm2, xmm3 ) vhaddps( xmm3, xmm2, xmm2 ) vpermilps(imm(0xd8), xmm2, xmm2) vhaddps( xmm2, xmm2, xmm2 ) vshufps(imm(0x44), xmm2, xmm0, xmm5) // xmm5[0] = sum(ymm5); xmm5[1] = sum(ymm8) // xmm5[2] = sum(ymm11); xmm5[3] = sum(ymm14) vhaddps( ymm9, ymm6, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vhaddps( xmm1, xmm0, xmm0 ) vpermilps(imm(0xd8), xmm0, xmm0) vhaddps( xmm0, xmm0, xmm0 ) vhaddps( ymm15, ymm12, ymm2 ) vextractf128(imm(1), ymm2, xmm3 ) vhaddps( xmm3, xmm2, xmm2 ) vpermilps(imm(0xd8), xmm2, xmm2) vhaddps( xmm2, xmm2, xmm2 ) vshufps(imm(0x44), xmm2, xmm0, xmm6) // xmm6[0] = sum(ymm6); xmm6[1] = sum(ymm9) // xmm6[2] = sum(ymm12); xmm6[3] = sum(ymm15) //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), xmm0) // load alpha and duplicate vbroadcastss(mem(rbx), xmm3) // load beta and duplicate vmulps(xmm0, xmm4, xmm4) // scale by alpha vmulps(xmm0, xmm5, xmm5) vmulps(xmm0, xmm6, xmm6) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(float) // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case label(.SROWSTORED) vfmadd231ps(mem(rcx), xmm3, xmm4) vmovups(xmm4, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), xmm3, xmm5) vmovups(xmm5, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), xmm3, xmm6) vmovups(xmm6, mem(rcx)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SBETAZERO) label(.SROWSTORBZ) vmovups(xmm4, mem(rcx)) add(rdi, rcx) vmovups(xmm5, mem(rcx)) add(rdi, rcx) vmovups(xmm6, mem(rcx)) //add(rdi, rcx) label(.SDONE) lea(mem(r12, rdi, 2), r12) // lea(mem(r12, rdi, 1), r12) // c_ii = r12 += 3*rs_c lea(mem(r14, r8, 2), r14) // lea(mem(r14, r8, 1), r14) // a_ii = r14 += 3*rs_a dec(r9) // ii -= 1; jne(.SLOOP3X4I) // iterate again if ii != 0. add(imm(4), r15) // jj += 4; cmp(imm(12), r15) // compare jj to 12 jl(.SLOOP3X4J) // if jj < 12, jump to beginning // of jj loop; otherwise, loop ends. label(.SRETURN) end_asm( : // output operands (none) : // input operands [m_iter] "m" (m_iter), [k_iter32] "m" (k_iter32), [k_iter8] "m" (k_iter8), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_sgemmsup_rd_haswell_asm_2x12 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter32 = k0 / 32; uint64_t k_left32 = k0 % 32; uint64_t k_iter8 = k_left32 / 8; uint64_t k_left1 = k_left32 % 8; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), r14) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) //lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rdx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b //lea(mem(r8, r8, 2), r10) // r10 = 3*rs_a mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) // r12 = rcx = c // r14 = rax = a // rdx = rbx = b // r9 = m dim index ii // r15 = n dim index jj mov(imm(0), r15) // jj = 0; label(.SLOOP3X4J) // LOOP OVER jj = [ 0 1 ... ] #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorps ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorps(ymm4, ymm4, ymm4) vxorps(ymm5, ymm5, ymm5) vxorps(ymm7, ymm7, ymm7) vxorps(ymm8, ymm8, ymm8) vxorps(ymm10, ymm10, ymm10) vxorps(ymm11, ymm11, ymm11) vxorps(ymm13, ymm13, ymm13) vxorps(ymm14, ymm14, ymm14) #endif lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(imm(1*4), rsi) // rsi *= cs_c*sizeof(float) = 1*4 lea(mem(r12, rsi, 1), rcx) // rcx = c + 4*jj*cs_c; lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(r11, rsi) // rsi *= cs_b; lea(mem(rdx, rsi, 1), rbx) // rbx = b + 4*jj*cs_b; lea(mem(r14), rax) // rax = a; #if 1 //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) prefetch(0, mem(rcx, 1*4)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 1*4)) // prefetch c + 1*rs_c #endif mov(var(k_iter32), rsi) // i = k_iter32; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKITER8) // if i == 0, jump to code that // contains the k_iter8 loop. label(.SLOOPKITER32) // MAIN LOOP // ---------------------------------- iteration 0 #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a #endif vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) // ---------------------------------- iteration 1 vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) // ---------------------------------- iteration 2 #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a #endif vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) // ---------------------------------- iteration 3 vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) dec(rsi) // i -= 1; jne(.SLOOPKITER32) // iterate again if i != 0. label(.SCONSIDKITER8) mov(var(k_iter8), rsi) // i = k_iter8; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter8 loop. label(.SLOOPKITER8) // EDGE LOOP (ymm) #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a #endif vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) dec(rsi) // i -= 1; jne(.SLOOPKITER8) // iterate again if i != 0. label(.SCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.SLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovss(mem(rax ), xmm0) vmovss(mem(rax, r8, 1), xmm1) add(imm(1*4), rax) // a += 1*cs_a = 1*4; vmovss(mem(rbx ), xmm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovss(mem(rbx, r11, 1), xmm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vmovss(mem(rbx, r11, 2), xmm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vmovss(mem(rbx, r13, 1), xmm3) add(imm(1*4), rbx) // b += 1*rs_b = 1*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) dec(rsi) // i -= 1; jne(.SLOOPKLEFT1) // iterate again if i != 0. label(.SPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 // ymm5 ymm8 ymm11 ymm14 vhaddps( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vhaddps( xmm1, xmm0, xmm0 ) vpermilps(imm(0xd8), xmm0, xmm0) vhaddps( xmm0, xmm0, xmm0 ) vhaddps( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm3 ) vhaddps( xmm3, xmm2, xmm2 ) vpermilps(imm(0xd8), xmm2, xmm2) vhaddps( xmm2, xmm2, xmm2 ) vshufps(imm(0x44), xmm2, xmm0, xmm4) // xmm4[0] = sum(ymm4); xmm4[1] = sum(ymm7) // xmm4[2] = sum(ymm10); xmm4[3] = sum(ymm13) vhaddps( ymm8, ymm5, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vhaddps( xmm1, xmm0, xmm0 ) vpermilps(imm(0xd8), xmm0, xmm0) vhaddps( xmm0, xmm0, xmm0 ) vhaddps( ymm14, ymm11, ymm2 ) vextractf128(imm(1), ymm2, xmm3 ) vhaddps( xmm3, xmm2, xmm2 ) vpermilps(imm(0xd8), xmm2, xmm2) vhaddps( xmm2, xmm2, xmm2 ) vshufps(imm(0x44), xmm2, xmm0, xmm5) // xmm5[0] = sum(ymm5); xmm5[1] = sum(ymm8) // xmm5[2] = sum(ymm11); xmm5[3] = sum(ymm14) //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), xmm0) // load alpha and duplicate vbroadcastss(mem(rbx), xmm3) // load beta and duplicate vmulps(xmm0, xmm4, xmm4) // scale by alpha vmulps(xmm0, xmm5, xmm5) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(float) // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case label(.SROWSTORED) vfmadd231ps(mem(rcx), xmm3, xmm4) vmovups(xmm4, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), xmm3, xmm5) vmovups(xmm5, mem(rcx)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SBETAZERO) label(.SROWSTORBZ) vmovups(xmm4, mem(rcx)) add(rdi, rcx) vmovups(xmm5, mem(rcx)) //add(rdi, rcx) label(.SDONE) add(imm(4), r15) // jj += 4; cmp(imm(12), r15) // compare jj to 12 jl(.SLOOP3X4J) // if jj < 12, jump to beginning // of jj loop; otherwise, loop ends. label(.SRETURN) end_asm( : // output operands (none) : // input operands [k_iter32] "m" (k_iter32), [k_iter8] "m" (k_iter8), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_sgemmsup_rd_haswell_asm_1x12 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter32 = k0 / 32; uint64_t k_left32 = k0 % 32; uint64_t k_iter8 = k_left32 / 8; uint64_t k_left1 = k_left32 % 8; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), r14) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) //lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rdx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b //lea(mem(r8, r8, 2), r10) // r10 = 3*rs_a mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) // r12 = rcx = c // r14 = rax = a // rdx = rbx = b // r9 = m dim index ii // r15 = n dim index jj mov(imm(0), r15) // jj = 0; label(.SLOOP3X4J) // LOOP OVER jj = [ 0 1 ... ] #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorps ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorps(ymm4, ymm4, ymm4) vxorps(ymm7, ymm7, ymm7) vxorps(ymm10, ymm10, ymm10) vxorps(ymm13, ymm13, ymm13) #endif lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(imm(1*4), rsi) // rsi *= cs_c*sizeof(float) = 1*4 lea(mem(r12, rsi, 1), rcx) // rcx = c + 4*jj*cs_c; lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(r11, rsi) // rsi *= cs_b; lea(mem(rdx, rsi, 1), rbx) // rbx = b + 4*jj*cs_b; lea(mem(r14), rax) // rax = a; #if 1 //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) prefetch(0, mem(rcx, 1*4)) // prefetch c + 0*rs_c #endif mov(var(k_iter32), rsi) // i = k_iter32; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKITER8) // if i == 0, jump to code that // contains the k_iter8 loop. label(.SLOOPKITER32) // MAIN LOOP // ---------------------------------- iteration 0 #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a #endif vmovups(mem(rax ), ymm0) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) // ---------------------------------- iteration 1 vmovups(mem(rax ), ymm0) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) // ---------------------------------- iteration 2 #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a #endif vmovups(mem(rax ), ymm0) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) // ---------------------------------- iteration 3 vmovups(mem(rax ), ymm0) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) dec(rsi) // i -= 1; jne(.SLOOPKITER32) // iterate again if i != 0. label(.SCONSIDKITER8) mov(var(k_iter8), rsi) // i = k_iter8; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter8 loop. label(.SLOOPKITER8) // EDGE LOOP (ymm) #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a #endif vmovups(mem(rax ), ymm0) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) dec(rsi) // i -= 1; jne(.SLOOPKITER8) // iterate again if i != 0. label(.SCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.SLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovss(mem(rax ), xmm0) add(imm(1*4), rax) // a += 1*cs_a = 1*4; vmovss(mem(rbx ), xmm3) vfmadd231ps(ymm0, ymm3, ymm4) vmovss(mem(rbx, r11, 1), xmm3) vfmadd231ps(ymm0, ymm3, ymm7) vmovss(mem(rbx, r11, 2), xmm3) vfmadd231ps(ymm0, ymm3, ymm10) vmovss(mem(rbx, r13, 1), xmm3) add(imm(1*4), rbx) // b += 1*rs_b = 1*4; vfmadd231ps(ymm0, ymm3, ymm13) dec(rsi) // i -= 1; jne(.SLOOPKLEFT1) // iterate again if i != 0. label(.SPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 // ymm5 ymm8 ymm11 ymm14 vhaddps( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vhaddps( xmm1, xmm0, xmm0 ) vpermilps(imm(0xd8), xmm0, xmm0) vhaddps( xmm0, xmm0, xmm0 ) vhaddps( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm3 ) vhaddps( xmm3, xmm2, xmm2 ) vpermilps(imm(0xd8), xmm2, xmm2) vhaddps( xmm2, xmm2, xmm2 ) vshufps(imm(0x44), xmm2, xmm0, xmm4) // xmm4[0] = sum(ymm4); xmm4[1] = sum(ymm7) // xmm4[2] = sum(ymm10); xmm4[3] = sum(ymm13) //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), xmm0) // load alpha and duplicate vbroadcastss(mem(rbx), xmm3) // load beta and duplicate vmulps(xmm0, xmm4, xmm4) // scale by alpha //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(float) // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case label(.SROWSTORED) vfmadd231ps(mem(rcx), xmm3, xmm4) vmovups(xmm4, mem(rcx)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SBETAZERO) label(.SROWSTORBZ) vmovups(xmm4, mem(rcx)) //add(rdi, rcx) label(.SDONE) add(imm(4), r15) // jj += 4; cmp(imm(12), r15) // compare jj to 12 jl(.SLOOP3X4J) // if jj < 12, jump to beginning // of jj loop; otherwise, loop ends. label(.SRETURN) end_asm( : // output operands (none) : // input operands [k_iter32] "m" (k_iter32), [k_iter8] "m" (k_iter8), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } blis-0.9.0/kernels/haswell/3/sup/s6x16/bli_gemmsup_rd_haswell_asm_sMx16.c000066400000000000000000001301751422157504600261410ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define BLIS_ASM_SYNTAX_ATT #include "bli_x86_asm_macros.h" /* rrc: -------- ------ | | | | | | | | -------- ------ | | | | | | | | -------- += ------ ... | | | | | | | | -------- ------ | | | | | | | | -------- ------ : -------- ------ : Assumptions: - C is row-stored and B is column-stored; - A is row-stored; - m0 and n0 are at most MR and NR, respectively. Therefore, this (r)ow-preferential microkernel is well-suited for a dot-product-based accumulation that performs vector loads from both A and B. */ // Prototype reference microkernels. GEMMSUP_KER_PROT( float, s, gemmsup_r_haswell_ref ) void bli_sgemmsup_rd_haswell_asm_6x16 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { uint64_t n_left = n0 % 16; // First check whether this is a edge case in the n dimension. If so, // dispatch other 6x?m kernels, as needed. if ( n_left ) { float* restrict cij = c; float* restrict bj = b; float* restrict ai = a; if ( 8 <= n_left ) { const dim_t nr_cur = 8; bli_sgemmsup_rd_haswell_asm_6x8 //bli_sgemmsup_r_haswell_ref ( conja, conjb, m0, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 4 <= n_left ) { const dim_t nr_cur = 4; bli_sgemmsup_rd_haswell_asm_6x4 //bli_sgemmsup_r_haswell_ref ( conja, conjb, m0, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 2 <= n_left ) { const dim_t nr_cur = 2; bli_sgemmsup_rd_haswell_asm_6x2 //bli_sgemmsup_r_haswell_ref ( conja, conjb, m0, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 1 == n_left ) { #if 1 const dim_t nr_cur = 1; bli_sgemmsup_rd_haswell_asm_6x1 //bli_sgemmsup_r_haswell_ref ( conja, conjb, m0, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); #else bli_sgemv_ex ( BLIS_NO_TRANSPOSE, conjb, m0, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, beta, cij, rs_c0, cntx, NULL ); #endif } return; } //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter32 = k0 / 32; uint64_t k_left32 = k0 % 32; uint64_t k_iter8 = k_left32 / 8; uint64_t k_left1 = k_left32 % 8; uint64_t m_iter = m0 / 3; uint64_t m_left = m0 % 3; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; if ( m_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. //mov(var(a), r14) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) //lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a //mov(var(b), rdx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b lea(mem(r8, r8, 2), r10) // r10 = 3*rs_a //mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) // r12 = rcx = c // r14 = rax = a // rdx = rbx = b // r9 = m dim index ii // r15 = n dim index jj mov(imm(0), r15) // jj = 0; label(.SLOOP3X4J) // LOOP OVER jj = [ 0 1 ... ] mov(var(a), r14) // load address of a mov(var(b), rdx) // load address of b mov(var(c), r12) // load address of c lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(imm(1*4), rsi) // rsi *= cs_c*sizeof(float) = 1*4 lea(mem(r12, rsi, 1), r12) // r12 = c + 4*jj*cs_c; lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(r11, rsi) // rsi *= cs_b; lea(mem(rdx, rsi, 1), rdx) // rbx = b + 4*jj*cs_b; mov(var(m_iter), r9) // ii = m_iter; label(.SLOOP3X4I) // LOOP OVER ii = [ m_iter ... 1 0 ] #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorps ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorps(ymm4, ymm4, ymm4) vxorps(ymm5, ymm5, ymm5) vxorps(ymm6, ymm6, ymm6) vxorps(ymm7, ymm7, ymm7) vxorps(ymm8, ymm8, ymm8) vxorps(ymm9, ymm9, ymm9) vxorps(ymm10, ymm10, ymm10) vxorps(ymm11, ymm11, ymm11) vxorps(ymm12, ymm12, ymm12) vxorps(ymm13, ymm13, ymm13) vxorps(ymm14, ymm14, ymm14) vxorps(ymm15, ymm15, ymm15) #endif lea(mem(r12), rcx) // rcx = c_iijj; lea(mem(r14), rax) // rax = a_ii; lea(mem(rdx), rbx) // rbx = b_jj; #if 1 //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) prefetch(0, mem(rcx, 1*4)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 1*4)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 1*4)) // prefetch c + 2*rs_c #endif lea(mem(r8, r8, 4), rbp) // rbp = 5*rs_a mov(var(k_iter32), rsi) // i = k_iter32; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKITER8) // if i == 0, jump to code that // contains the k_iter8 loop. label(.SLOOPKITER32) // MAIN LOOP // ---------------------------------- iteration 0 #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) vmovups(mem(rax, r8, 2), ymm2) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) // ---------------------------------- iteration 1 vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) vmovups(mem(rax, r8, 2), ymm2) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) // ---------------------------------- iteration 2 #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) vmovups(mem(rax, r8, 2), ymm2) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) // ---------------------------------- iteration 3 vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) vmovups(mem(rax, r8, 2), ymm2) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.SLOOPKITER32) // iterate again if i != 0. label(.SCONSIDKITER8) mov(var(k_iter8), rsi) // i = k_iter8; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter8 loop. label(.SLOOPKITER8) // EDGE LOOP (ymm) #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) vmovups(mem(rax, r8, 2), ymm2) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.SLOOPKITER8) // iterate again if i != 0. label(.SCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.SLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovss(mem(rax ), xmm0) vmovss(mem(rax, r8, 1), xmm1) vmovss(mem(rax, r8, 2), xmm2) add(imm(1*4), rax) // a += 1*cs_a = 1*4; vmovss(mem(rbx ), xmm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovss(mem(rbx, r11, 1), xmm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovss(mem(rbx, r11, 2), xmm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovss(mem(rbx, r13, 1), xmm3) add(imm(1*4), rbx) // b += 1*rs_b = 1*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.SLOOPKLEFT1) // iterate again if i != 0. label(.SPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 // ymm5 ymm8 ymm11 ymm14 // ymm6 ymm9 ymm12 ymm15 vhaddps( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vhaddps( xmm1, xmm0, xmm0 ) vpermilps(imm(0xd8), xmm0, xmm0) vhaddps( xmm0, xmm0, xmm0 ) vhaddps( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm3 ) vhaddps( xmm3, xmm2, xmm2 ) vpermilps(imm(0xd8), xmm2, xmm2) vhaddps( xmm2, xmm2, xmm2 ) vshufps(imm(0x44), xmm2, xmm0, xmm4) // xmm4[0] = sum(ymm4); xmm4[1] = sum(ymm7) // xmm4[2] = sum(ymm10); xmm4[3] = sum(ymm13) vhaddps( ymm8, ymm5, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vhaddps( xmm1, xmm0, xmm0 ) vpermilps(imm(0xd8), xmm0, xmm0) vhaddps( xmm0, xmm0, xmm0 ) vhaddps( ymm14, ymm11, ymm2 ) vextractf128(imm(1), ymm2, xmm3 ) vhaddps( xmm3, xmm2, xmm2 ) vpermilps(imm(0xd8), xmm2, xmm2) vhaddps( xmm2, xmm2, xmm2 ) vshufps(imm(0x44), xmm2, xmm0, xmm5) // xmm5[0] = sum(ymm5); xmm5[1] = sum(ymm8) // xmm5[2] = sum(ymm11); xmm5[3] = sum(ymm14) vhaddps( ymm9, ymm6, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vhaddps( xmm1, xmm0, xmm0 ) vpermilps(imm(0xd8), xmm0, xmm0) vhaddps( xmm0, xmm0, xmm0 ) vhaddps( ymm15, ymm12, ymm2 ) vextractf128(imm(1), ymm2, xmm3 ) vhaddps( xmm3, xmm2, xmm2 ) vpermilps(imm(0xd8), xmm2, xmm2) vhaddps( xmm2, xmm2, xmm2 ) vshufps(imm(0x44), xmm2, xmm0, xmm6) // xmm6[0] = sum(ymm6); xmm6[1] = sum(ymm9) // xmm6[2] = sum(ymm12); xmm6[3] = sum(ymm15) //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), xmm0) // load alpha and duplicate vbroadcastss(mem(rbx), xmm3) // load beta and duplicate vmulps(xmm0, xmm4, xmm4) // scale by alpha vmulps(xmm0, xmm5, xmm5) vmulps(xmm0, xmm6, xmm6) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(float) // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case label(.SROWSTORED) vfmadd231ps(mem(rcx), xmm3, xmm4) vmovups(xmm4, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), xmm3, xmm5) vmovups(xmm5, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), xmm3, xmm6) vmovups(xmm6, mem(rcx)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SBETAZERO) label(.SROWSTORBZ) vmovups(xmm4, mem(rcx)) add(rdi, rcx) vmovups(xmm5, mem(rcx)) add(rdi, rcx) vmovups(xmm6, mem(rcx)) //add(rdi, rcx) label(.SDONE) lea(mem(r12, rdi, 2), r12) // lea(mem(r12, rdi, 1), r12) // c_ii = r12 += 3*rs_c lea(mem(r14, r8, 2), r14) // lea(mem(r14, r8, 1), r14) // a_ii = r14 += 3*rs_a dec(r9) // ii -= 1; jne(.SLOOP3X4I) // iterate again if ii != 0. add(imm(4), r15) // jj += 4; cmp(imm(16), r15) // compare jj to 16 jl(.SLOOP3X4J) // if jj < 16, jump to beginning // of jj loop; otherwise, loop ends. label(.SRETURN) end_asm( : // output operands (none) : // input operands [m_iter] "m" (m_iter), [k_iter32] "m" (k_iter32), [k_iter8] "m" (k_iter8), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the m dimension, if they exist. if ( m_left ) { const dim_t nr_cur = 16; const dim_t i_edge = m0 - ( dim_t )m_left; float* restrict cij = c + i_edge*rs_c; float* restrict bj = b; float* restrict ai = a + i_edge*rs_a; if ( 2 == m_left ) { const dim_t mr_cur = 2; bli_sgemmsup_rd_haswell_asm_2x16 //bli_sgemmsup_r_haswell_ref ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); //cij += mr_cur*rs_c0; ai += mr_cur*rs_a0; m_left -= mr_cur; } if ( 1 == m_left ) { const dim_t mr_cur = 1; bli_sgemmsup_rd_haswell_asm_1x16 //bli_sgemmsup_r_haswell_ref ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); } } } void bli_sgemmsup_rd_haswell_asm_2x16 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter32 = k0 / 32; uint64_t k_left32 = k0 % 32; uint64_t k_iter8 = k_left32 / 8; uint64_t k_left1 = k_left32 % 8; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), r14) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) //lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rdx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b //lea(mem(r8, r8, 2), r10) // r10 = 3*rs_a mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) // r12 = rcx = c // r14 = rax = a // rdx = rbx = b // r9 = m dim index ii // r15 = n dim index jj mov(imm(0), r15) // jj = 0; label(.SLOOP3X4J) // LOOP OVER jj = [ 0 1 ... ] #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorps ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorps(ymm4, ymm4, ymm4) vxorps(ymm5, ymm5, ymm5) vxorps(ymm7, ymm7, ymm7) vxorps(ymm8, ymm8, ymm8) vxorps(ymm10, ymm10, ymm10) vxorps(ymm11, ymm11, ymm11) vxorps(ymm13, ymm13, ymm13) vxorps(ymm14, ymm14, ymm14) #endif lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(imm(1*4), rsi) // rsi *= cs_c*sizeof(float) = 1*4 lea(mem(r12, rsi, 1), rcx) // rcx = c + 4*jj*cs_c; lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(r11, rsi) // rsi *= cs_b; lea(mem(rdx, rsi, 1), rbx) // rbx = b + 4*jj*cs_b; lea(mem(r14), rax) // rax = a; #if 1 //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) prefetch(0, mem(rcx, 1*4)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 1*4)) // prefetch c + 1*rs_c #endif mov(var(k_iter32), rsi) // i = k_iter32; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKITER8) // if i == 0, jump to code that // contains the k_iter8 loop. label(.SLOOPKITER32) // MAIN LOOP // ---------------------------------- iteration 0 #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) // ---------------------------------- iteration 1 vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) // ---------------------------------- iteration 2 #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) // ---------------------------------- iteration 3 vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) dec(rsi) // i -= 1; jne(.SLOOPKITER32) // iterate again if i != 0. label(.SCONSIDKITER8) mov(var(k_iter8), rsi) // i = k_iter8; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter8 loop. label(.SLOOPKITER8) // EDGE LOOP (ymm) #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) dec(rsi) // i -= 1; jne(.SLOOPKITER8) // iterate again if i != 0. label(.SCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.SLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovss(mem(rax ), xmm0) vmovss(mem(rax, r8, 1), xmm1) add(imm(1*4), rax) // a += 1*cs_a = 1*4; vmovss(mem(rbx ), xmm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovss(mem(rbx, r11, 1), xmm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vmovss(mem(rbx, r11, 2), xmm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vmovss(mem(rbx, r13, 1), xmm3) add(imm(1*4), rbx) // b += 1*rs_b = 1*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) dec(rsi) // i -= 1; jne(.SLOOPKLEFT1) // iterate again if i != 0. label(.SPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 // ymm5 ymm8 ymm11 ymm14 vhaddps( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vhaddps( xmm1, xmm0, xmm0 ) vpermilps(imm(0xd8), xmm0, xmm0) vhaddps( xmm0, xmm0, xmm0 ) vhaddps( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm3 ) vhaddps( xmm3, xmm2, xmm2 ) vpermilps(imm(0xd8), xmm2, xmm2) vhaddps( xmm2, xmm2, xmm2 ) vshufps(imm(0x44), xmm2, xmm0, xmm4) // xmm4[0] = sum(ymm4); xmm4[1] = sum(ymm7) // xmm4[2] = sum(ymm10); xmm4[3] = sum(ymm13) vhaddps( ymm8, ymm5, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vhaddps( xmm1, xmm0, xmm0 ) vpermilps(imm(0xd8), xmm0, xmm0) vhaddps( xmm0, xmm0, xmm0 ) vhaddps( ymm14, ymm11, ymm2 ) vextractf128(imm(1), ymm2, xmm3 ) vhaddps( xmm3, xmm2, xmm2 ) vpermilps(imm(0xd8), xmm2, xmm2) vhaddps( xmm2, xmm2, xmm2 ) vshufps(imm(0x44), xmm2, xmm0, xmm5) // xmm5[0] = sum(ymm5); xmm5[1] = sum(ymm8) // xmm5[2] = sum(ymm11); xmm5[3] = sum(ymm14) //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), xmm0) // load alpha and duplicate vbroadcastss(mem(rbx), xmm3) // load beta and duplicate vmulps(xmm0, xmm4, xmm4) // scale by alpha vmulps(xmm0, xmm5, xmm5) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(float) // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case label(.SROWSTORED) vfmadd231ps(mem(rcx), xmm3, xmm4) vmovups(xmm4, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), xmm3, xmm5) vmovups(xmm5, mem(rcx)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SBETAZERO) label(.SROWSTORBZ) vmovups(xmm4, mem(rcx)) add(rdi, rcx) vmovups(xmm5, mem(rcx)) //add(rdi, rcx) label(.SDONE) add(imm(4), r15) // jj += 4; cmp(imm(16), r15) // compare jj to 16 jl(.SLOOP3X4J) // if jj < 16, jump to beginning // of jj loop; otherwise, loop ends. label(.SRETURN) end_asm( : // output operands (none) : // input operands [k_iter32] "m" (k_iter32), [k_iter8] "m" (k_iter8), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_sgemmsup_rd_haswell_asm_1x16 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter32 = k0 / 32; uint64_t k_left32 = k0 % 32; uint64_t k_iter8 = k_left32 / 8; uint64_t k_left1 = k_left32 % 8; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), r14) // load address of a. //mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a //lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) //lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rdx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b //lea(mem(r8, r8, 2), r10) // r10 = 3*rs_a mov(var(c), r12) // load address of c //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) // r12 = rcx = c // r14 = rax = a // rdx = rbx = b // r9 = m dim index ii // r15 = n dim index jj mov(imm(0), r15) // jj = 0; label(.SLOOP3X4J) // LOOP OVER jj = [ 0 1 ... ] #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorps ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorps(ymm4, ymm4, ymm4) vxorps(ymm7, ymm7, ymm7) vxorps(ymm10, ymm10, ymm10) vxorps(ymm13, ymm13, ymm13) #endif lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(imm(1*4), rsi) // rsi *= cs_c*sizeof(float) = 1*4 lea(mem(r12, rsi, 1), rcx) // rcx = c + 4*jj*cs_c; lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(r11, rsi) // rsi *= cs_b; lea(mem(rdx, rsi, 1), rbx) // rbx = b + 4*jj*cs_b; lea(mem(r14), rax) // rax = a; #if 1 //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) prefetch(0, mem(rcx, 1*4)) // prefetch c + 0*rs_c #endif mov(var(k_iter32), rsi) // i = k_iter32; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKITER8) // if i == 0, jump to code that // contains the k_iter8 loop. label(.SLOOPKITER32) // MAIN LOOP // ---------------------------------- iteration 0 #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovups(mem(rax ), ymm0) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) // ---------------------------------- iteration 1 vmovups(mem(rax ), ymm0) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) // ---------------------------------- iteration 2 #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovups(mem(rax ), ymm0) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) // ---------------------------------- iteration 3 vmovups(mem(rax ), ymm0) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) dec(rsi) // i -= 1; jne(.SLOOPKITER32) // iterate again if i != 0. label(.SCONSIDKITER8) mov(var(k_iter8), rsi) // i = k_iter8; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter8 loop. label(.SLOOPKITER8) // EDGE LOOP (ymm) #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovups(mem(rax ), ymm0) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) dec(rsi) // i -= 1; jne(.SLOOPKITER8) // iterate again if i != 0. label(.SCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.SLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovss(mem(rax ), xmm0) add(imm(1*4), rax) // a += 1*cs_a = 1*4; vmovss(mem(rbx ), xmm3) vfmadd231ps(ymm0, ymm3, ymm4) vmovss(mem(rbx, r11, 1), xmm3) vfmadd231ps(ymm0, ymm3, ymm7) vmovss(mem(rbx, r11, 2), xmm3) vfmadd231ps(ymm0, ymm3, ymm10) vmovss(mem(rbx, r13, 1), xmm3) add(imm(1*4), rbx) // b += 1*rs_b = 1*4; vfmadd231ps(ymm0, ymm3, ymm13) dec(rsi) // i -= 1; jne(.SLOOPKLEFT1) // iterate again if i != 0. label(.SPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 vhaddps( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vhaddps( xmm1, xmm0, xmm0 ) vpermilps(imm(0xd8), xmm0, xmm0) vhaddps( xmm0, xmm0, xmm0 ) vhaddps( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm3 ) vhaddps( xmm3, xmm2, xmm2 ) vpermilps(imm(0xd8), xmm2, xmm2) vhaddps( xmm2, xmm2, xmm2 ) vshufps(imm(0x44), xmm2, xmm0, xmm4) // xmm4[0] = sum(ymm4); xmm4[1] = sum(ymm7) // xmm4[2] = sum(ymm10); xmm4[3] = sum(ymm13) //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), xmm0) // load alpha and duplicate vbroadcastss(mem(rbx), xmm3) // load beta and duplicate vmulps(xmm0, xmm4, xmm4) // scale by alpha //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(float) // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case label(.SROWSTORED) vfmadd231ps(mem(rcx), xmm3, xmm4) vmovups(xmm4, mem(rcx)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SBETAZERO) label(.SROWSTORBZ) vmovups(xmm4, mem(rcx)) //add(rdi, rcx) label(.SDONE) add(imm(4), r15) // jj += 4; cmp(imm(16), r15) // compare jj to 16 jl(.SLOOP3X4J) // if jj < 16, jump to beginning // of jj loop; otherwise, loop ends. label(.SRETURN) end_asm( : // output operands (none) : // input operands [k_iter32] "m" (k_iter32), [k_iter8] "m" (k_iter8), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } blis-0.9.0/kernels/haswell/3/sup/s6x16/bli_gemmsup_rd_haswell_asm_sMx2.c000066400000000000000000001415121422157504600260510ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define BLIS_ASM_SYNTAX_ATT #include "bli_x86_asm_macros.h" /* rrc: -------- ------ | | | | | | | | -------- ------ | | | | | | | | -------- += ------ ... | | | | | | | | -------- ------ | | | | | | | | -------- ------ : -------- ------ : Assumptions: - C is row-stored and B is column-stored; - A is row-stored; - m0 and n0 are at most MR and NR, respectively. Therefore, this (r)ow-preferential microkernel is well-suited for a dot-product-based accumulation that performs vector loads from both A and B. */ // Prototype reference microkernels. GEMMSUP_KER_PROT( float, s, gemmsup_r_haswell_ref ) void bli_sgemmsup_rd_haswell_asm_6x2 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter32 = k0 / 32; uint64_t k_left32 = k0 % 32; uint64_t k_iter8 = k_left32 / 8; uint64_t k_left1 = k_left32 % 8; //uint64_t m_iter = m0 / 3; //uint64_t m_left = m0 % 3; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) //lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) //lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b //lea(mem(r8, r8, 2), r10) // r10 = 3*rs_a mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) // r12 = rcx = c // r14 = rax = a // rdx = rbx = b #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorps ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorps(ymm4, ymm4, ymm4) vxorps(ymm5, ymm5, ymm5) vxorps(ymm6, ymm6, ymm6) vxorps(ymm7, ymm7, ymm7) vxorps(ymm8, ymm8, ymm8) vxorps(ymm9, ymm9, ymm9) vxorps(ymm10, ymm10, ymm10) vxorps(ymm11, ymm11, ymm11) vxorps(ymm12, ymm12, ymm12) vxorps(ymm13, ymm13, ymm13) vxorps(ymm14, ymm14, ymm14) vxorps(ymm15, ymm15, ymm15) #endif //lea(mem(r12), rcx) // rcx = c_ii; //lea(mem(r14), rax) // rax = a_ii; //lea(mem(rdx), rbx) // rbx = b; #if 1 //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) lea(mem(rcx, rdi, 2), r10) // lea(mem(r10, rdi, 1), r10) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 1*4)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 1*4)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 1*4)) // prefetch c + 2*rs_c prefetch(0, mem(r10, 1*4)) // prefetch c + 3*rs_c prefetch(0, mem(r10, rdi, 1, 1*4)) // prefetch c + 4*rs_c prefetch(0, mem(r10, rdi, 2, 1*4)) // prefetch c + 5*rs_c #endif mov(var(k_iter32), rsi) // i = k_iter32; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKITER8) // if i == 0, jump to code that // contains the k_iter8 loop. label(.SLOOPKITER32) // MAIN LOOP // ---------------------------------- iteration 0 #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovups(mem(rbx ), ymm0) vmovups(mem(rbx, r11, 1), ymm1) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vmovups(mem(rax ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovups(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vmovups(mem(rax, r8, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm8) vfmadd231ps(ymm1, ymm3, ymm9) vmovups(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vmovups(mem(rax, r8, 4), ymm3) vfmadd231ps(ymm0, ymm3, ymm12) vfmadd231ps(ymm1, ymm3, ymm13) vmovups(mem(rax, r15, 1), ymm3) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) // ---------------------------------- iteration 1 vmovups(mem(rbx ), ymm0) vmovups(mem(rbx, r11, 1), ymm1) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vmovups(mem(rax ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovups(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vmovups(mem(rax, r8, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm8) vfmadd231ps(ymm1, ymm3, ymm9) vmovups(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vmovups(mem(rax, r8, 4), ymm3) vfmadd231ps(ymm0, ymm3, ymm12) vfmadd231ps(ymm1, ymm3, ymm13) vmovups(mem(rax, r15, 1), ymm3) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) // ---------------------------------- iteration 2 #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovups(mem(rbx ), ymm0) vmovups(mem(rbx, r11, 1), ymm1) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vmovups(mem(rax ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovups(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vmovups(mem(rax, r8, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm8) vfmadd231ps(ymm1, ymm3, ymm9) vmovups(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vmovups(mem(rax, r8, 4), ymm3) vfmadd231ps(ymm0, ymm3, ymm12) vfmadd231ps(ymm1, ymm3, ymm13) vmovups(mem(rax, r15, 1), ymm3) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) // ---------------------------------- iteration 3 vmovups(mem(rbx ), ymm0) vmovups(mem(rbx, r11, 1), ymm1) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vmovups(mem(rax ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovups(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vmovups(mem(rax, r8, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm8) vfmadd231ps(ymm1, ymm3, ymm9) vmovups(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vmovups(mem(rax, r8, 4), ymm3) vfmadd231ps(ymm0, ymm3, ymm12) vfmadd231ps(ymm1, ymm3, ymm13) vmovups(mem(rax, r15, 1), ymm3) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) dec(rsi) // i -= 1; jne(.SLOOPKITER32) // iterate again if i != 0. label(.SCONSIDKITER8) mov(var(k_iter8), rsi) // i = k_iter8; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter8 loop. label(.SLOOPKITER8) // EDGE LOOP (ymm) #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovups(mem(rbx ), ymm0) vmovups(mem(rbx, r11, 1), ymm1) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vmovups(mem(rax ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovups(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vmovups(mem(rax, r8, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm8) vfmadd231ps(ymm1, ymm3, ymm9) vmovups(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vmovups(mem(rax, r8, 4), ymm3) vfmadd231ps(ymm0, ymm3, ymm12) vfmadd231ps(ymm1, ymm3, ymm13) vmovups(mem(rax, r15, 1), ymm3) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) dec(rsi) // i -= 1; jne(.SLOOPKITER8) // iterate again if i != 0. label(.SCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.SLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovss(mem(rbx ), xmm0) vmovss(mem(rbx, r11, 1), xmm1) add(imm(1*4), rbx) // b += 8*rs_b = 8*4; vmovss(mem(rax ), xmm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovss(mem(rax, r8, 1), xmm3) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vmovss(mem(rax, r8, 2), xmm3) vfmadd231ps(ymm0, ymm3, ymm8) vfmadd231ps(ymm1, ymm3, ymm9) vmovss(mem(rax, r13, 1), xmm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vmovss(mem(rax, r8, 4), xmm3) vfmadd231ps(ymm0, ymm3, ymm12) vfmadd231ps(ymm1, ymm3, ymm13) vmovss(mem(rax, r15, 1), xmm3) add(imm(1*4), rax) // a += 8*cs_a = 8*4; vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) dec(rsi) // i -= 1; jne(.SLOOPKLEFT1) // iterate again if i != 0. label(.SPOSTACCUM) // ymm4 ymm5 // ymm6 ymm7 // ymm8 ymm9 // ymm10 ymm11 // ymm12 ymm13 // ymm14 ymm15 vhaddps( ymm5, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vhaddps( xmm1, xmm0, xmm0 ) vpermilps(imm(0xd8), xmm0, xmm0) vhaddps( xmm0, xmm0, xmm4 ) vhaddps( ymm7, ymm6, ymm2 ) vextractf128(imm(1), ymm2, xmm3 ) vhaddps( xmm3, xmm2, xmm2 ) vpermilps(imm(0xd8), xmm2, xmm2) vhaddps( xmm2, xmm2, xmm6 ) vhaddps( ymm9, ymm8, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vhaddps( xmm1, xmm0, xmm0 ) vpermilps(imm(0xd8), xmm0, xmm0) vhaddps( xmm0, xmm0, xmm8 ) vhaddps( ymm11, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm3 ) vhaddps( xmm3, xmm2, xmm2 ) vpermilps(imm(0xd8), xmm2, xmm2) vhaddps( xmm2, xmm2, xmm10 ) vhaddps( ymm13, ymm12, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vhaddps( xmm1, xmm0, xmm0 ) vpermilps(imm(0xd8), xmm0, xmm0) vhaddps( xmm0, xmm0, xmm12 ) vhaddps( ymm15, ymm14, ymm2 ) vextractf128(imm(1), ymm2, xmm3 ) vhaddps( xmm3, xmm2, xmm2 ) vpermilps(imm(0xd8), xmm2, xmm2) vhaddps( xmm2, xmm2, xmm14 ) // xmm4[0:1] = sum(ymm4) sum(ymm5) // xmm6[0:1] = sum(ymm6) sum(ymm7) // xmm8[0:1] = sum(ymm8) sum(ymm9) // xmm10[0:1] = sum(ymm10) sum(ymm11) // xmm12[0:1] = sum(ymm12) sum(ymm13) // xmm14[0:1] = sum(ymm14) sum(ymm15) //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), xmm0) // load alpha and duplicate vbroadcastss(mem(rbx), xmm3) // load beta and duplicate vmulps(xmm0, xmm4, xmm4) // scale by alpha vmulps(xmm0, xmm6, xmm6) vmulps(xmm0, xmm8, xmm8) vmulps(xmm0, xmm10, xmm10) vmulps(xmm0, xmm12, xmm12) vmulps(xmm0, xmm14, xmm14) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(float) // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case label(.SROWSTORED) vmovsd(mem(rcx), xmm0) vfmadd231ps(xmm0, xmm3, xmm4) vmovsd(xmm4, mem(rcx)) add(rdi, rcx) vmovsd(mem(rcx), xmm0) vfmadd231ps(xmm0, xmm3, xmm6) vmovsd(xmm6, mem(rcx)) add(rdi, rcx) vmovsd(mem(rcx), xmm0) vfmadd231ps(xmm0, xmm3, xmm8) vmovsd(xmm8, mem(rcx)) add(rdi, rcx) vmovsd(mem(rcx), xmm0) vfmadd231ps(xmm0, xmm3, xmm10) vmovsd(xmm10, mem(rcx)) add(rdi, rcx) vmovsd(mem(rcx), xmm0) vfmadd231ps(xmm0, xmm3, xmm12) vmovsd(xmm12, mem(rcx)) add(rdi, rcx) vmovsd(mem(rcx), xmm0) vfmadd231ps(xmm0, xmm3, xmm14) vmovsd(xmm14, mem(rcx)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SBETAZERO) label(.SROWSTORBZ) vmovsd(xmm4, mem(rcx)) add(rdi, rcx) vmovsd(xmm6, mem(rcx)) add(rdi, rcx) vmovsd(xmm8, mem(rcx)) add(rdi, rcx) vmovsd(xmm10, mem(rcx)) add(rdi, rcx) vmovsd(xmm12, mem(rcx)) add(rdi, rcx) vmovsd(xmm14, mem(rcx)) //add(rdi, rcx) label(.SDONE) label(.SRETURN) end_asm( : // output operands (none) : // input operands [k_iter32] "m" (k_iter32), [k_iter8] "m" (k_iter8), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_sgemmsup_rd_haswell_asm_3x2 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter32 = k0 / 32; uint64_t k_left32 = k0 % 32; uint64_t k_iter8 = k_left32 / 8; uint64_t k_left1 = k_left32 % 8; //uint64_t m_iter = m0 / 3; //uint64_t m_left = m0 % 3; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) //lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) //lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b //lea(mem(r8, r8, 2), r10) // r10 = 3*rs_a mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) // r12 = rcx = c // r14 = rax = a // rdx = rbx = b #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorps ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorps(ymm4, ymm4, ymm4) vxorps(ymm5, ymm5, ymm5) vxorps(ymm6, ymm6, ymm6) vxorps(ymm7, ymm7, ymm7) vxorps(ymm8, ymm8, ymm8) vxorps(ymm9, ymm9, ymm9) #endif //lea(mem(r12), rcx) // rcx = c_ii; //lea(mem(r14), rax) // rax = a_ii; //lea(mem(rdx), rbx) // rbx = b; #if 1 //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) //lea(mem(rcx, rdi, 2), r10) // //lea(mem(r10, rdi, 1), r10) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 1*4)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 1*4)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 1*4)) // prefetch c + 2*rs_c #endif mov(var(k_iter32), rsi) // i = k_iter32; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKITER8) // if i == 0, jump to code that // contains the k_iter8 loop. label(.SLOOPKITER32) // MAIN LOOP // ---------------------------------- iteration 0 #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovups(mem(rbx ), ymm0) vmovups(mem(rbx, r11, 1), ymm1) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vmovups(mem(rax ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovups(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vmovups(mem(rax, r8, 2), ymm3) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vfmadd231ps(ymm0, ymm3, ymm8) vfmadd231ps(ymm1, ymm3, ymm9) // ---------------------------------- iteration 1 vmovups(mem(rbx ), ymm0) vmovups(mem(rbx, r11, 1), ymm1) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vmovups(mem(rax ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovups(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vmovups(mem(rax, r8, 2), ymm3) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vfmadd231ps(ymm0, ymm3, ymm8) vfmadd231ps(ymm1, ymm3, ymm9) // ---------------------------------- iteration 2 #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovups(mem(rbx ), ymm0) vmovups(mem(rbx, r11, 1), ymm1) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vmovups(mem(rax ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovups(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vmovups(mem(rax, r8, 2), ymm3) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vfmadd231ps(ymm0, ymm3, ymm8) vfmadd231ps(ymm1, ymm3, ymm9) // ---------------------------------- iteration 3 vmovups(mem(rbx ), ymm0) vmovups(mem(rbx, r11, 1), ymm1) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vmovups(mem(rax ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovups(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vmovups(mem(rax, r8, 2), ymm3) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vfmadd231ps(ymm0, ymm3, ymm8) vfmadd231ps(ymm1, ymm3, ymm9) dec(rsi) // i -= 1; jne(.SLOOPKITER32) // iterate again if i != 0. label(.SCONSIDKITER8) mov(var(k_iter8), rsi) // i = k_iter8; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter8 loop. label(.SLOOPKITER8) // EDGE LOOP (ymm) #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovups(mem(rbx ), ymm0) vmovups(mem(rbx, r11, 1), ymm1) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vmovups(mem(rax ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovups(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vmovups(mem(rax, r8, 2), ymm3) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vfmadd231ps(ymm0, ymm3, ymm8) vfmadd231ps(ymm1, ymm3, ymm9) dec(rsi) // i -= 1; jne(.SLOOPKITER8) // iterate again if i != 0. label(.SCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.SLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovss(mem(rbx ), xmm0) vmovss(mem(rbx, r11, 1), xmm1) add(imm(1*4), rbx) // b += 8*rs_b = 8*4; vmovss(mem(rax ), xmm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovss(mem(rax, r8, 1), xmm3) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vmovss(mem(rax, r8, 2), xmm3) add(imm(1*4), rax) // a += 8*cs_a = 8*4; vfmadd231ps(ymm0, ymm3, ymm8) vfmadd231ps(ymm1, ymm3, ymm9) dec(rsi) // i -= 1; jne(.SLOOPKLEFT1) // iterate again if i != 0. label(.SPOSTACCUM) // ymm4 ymm5 // ymm6 ymm7 // ymm8 ymm9 vhaddps( ymm5, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vhaddps( xmm1, xmm0, xmm0 ) vpermilps(imm(0xd8), xmm0, xmm0) vhaddps( xmm0, xmm0, xmm4 ) vhaddps( ymm7, ymm6, ymm2 ) vextractf128(imm(1), ymm2, xmm3 ) vhaddps( xmm3, xmm2, xmm2 ) vpermilps(imm(0xd8), xmm2, xmm2) vhaddps( xmm2, xmm2, xmm6 ) vhaddps( ymm9, ymm8, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vhaddps( xmm1, xmm0, xmm0 ) vpermilps(imm(0xd8), xmm0, xmm0) vhaddps( xmm0, xmm0, xmm8 ) // xmm4[0:1] = sum(ymm4) sum(ymm5) // xmm6[0:1] = sum(ymm6) sum(ymm7) // xmm8[0:1] = sum(ymm8) sum(ymm9) //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), xmm0) // load alpha and duplicate vbroadcastss(mem(rbx), xmm3) // load beta and duplicate vmulps(xmm0, xmm4, xmm4) // scale by alpha vmulps(xmm0, xmm6, xmm6) vmulps(xmm0, xmm8, xmm8) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(float) // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case label(.SROWSTORED) vmovsd(mem(rcx), xmm0) vfmadd231ps(xmm0, xmm3, xmm4) vmovsd(xmm4, mem(rcx)) add(rdi, rcx) vmovsd(mem(rcx), xmm0) vfmadd231ps(xmm0, xmm3, xmm6) vmovsd(xmm6, mem(rcx)) add(rdi, rcx) vmovsd(mem(rcx), xmm0) vfmadd231ps(xmm0, xmm3, xmm8) vmovsd(xmm8, mem(rcx)) add(rdi, rcx) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SBETAZERO) label(.SROWSTORBZ) vmovsd(xmm4, mem(rcx)) add(rdi, rcx) vmovsd(xmm6, mem(rcx)) add(rdi, rcx) vmovsd(xmm8, mem(rcx)) //add(rdi, rcx) label(.SDONE) label(.SRETURN) end_asm( : // output operands (none) : // input operands [k_iter32] "m" (k_iter32), [k_iter8] "m" (k_iter8), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_sgemmsup_rd_haswell_asm_2x2 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter32 = k0 / 32; uint64_t k_left32 = k0 % 32; uint64_t k_iter8 = k_left32 / 8; uint64_t k_left1 = k_left32 % 8; //uint64_t m_iter = m0 / 3; //uint64_t m_left = m0 % 3; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) //lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) //lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b //lea(mem(r8, r8, 2), r10) // r10 = 3*rs_a mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) // r12 = rcx = c // r14 = rax = a // rdx = rbx = b #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorps ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorps(ymm4, ymm4, ymm4) vxorps(ymm5, ymm5, ymm5) vxorps(ymm6, ymm6, ymm6) vxorps(ymm7, ymm7, ymm7) #endif //lea(mem(r12), rcx) // rcx = c_ii; //lea(mem(r14), rax) // rax = a_ii; //lea(mem(rdx), rbx) // rbx = b; #if 1 //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) //lea(mem(rcx, rdi, 2), r10) // //lea(mem(r10, rdi, 1), r10) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 1*4)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 1*4)) // prefetch c + 1*rs_c #endif mov(var(k_iter32), rsi) // i = k_iter32; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKITER8) // if i == 0, jump to code that // contains the k_iter8 loop. label(.SLOOPKITER32) // MAIN LOOP // ---------------------------------- iteration 0 #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovups(mem(rbx ), ymm0) vmovups(mem(rbx, r11, 1), ymm1) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vmovups(mem(rax ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovups(mem(rax, r8, 1), ymm3) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) // ---------------------------------- iteration 1 vmovups(mem(rbx ), ymm0) vmovups(mem(rbx, r11, 1), ymm1) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vmovups(mem(rax ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovups(mem(rax, r8, 1), ymm3) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) // ---------------------------------- iteration 2 #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovups(mem(rbx ), ymm0) vmovups(mem(rbx, r11, 1), ymm1) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vmovups(mem(rax ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovups(mem(rax, r8, 1), ymm3) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) // ---------------------------------- iteration 3 vmovups(mem(rbx ), ymm0) vmovups(mem(rbx, r11, 1), ymm1) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vmovups(mem(rax ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovups(mem(rax, r8, 1), ymm3) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) dec(rsi) // i -= 1; jne(.SLOOPKITER32) // iterate again if i != 0. label(.SCONSIDKITER8) mov(var(k_iter8), rsi) // i = k_iter8; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter8 loop. label(.SLOOPKITER8) // EDGE LOOP (ymm) #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovups(mem(rbx ), ymm0) vmovups(mem(rbx, r11, 1), ymm1) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vmovups(mem(rax ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovups(mem(rax, r8, 1), ymm3) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) dec(rsi) // i -= 1; jne(.SLOOPKITER8) // iterate again if i != 0. label(.SCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.SLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovss(mem(rbx ), xmm0) vmovss(mem(rbx, r11, 1), xmm1) add(imm(1*4), rbx) // b += 8*rs_b = 8*4; vmovss(mem(rax ), xmm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovss(mem(rax, r8, 1), xmm3) add(imm(1*4), rax) // a += 8*cs_a = 8*4; vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) dec(rsi) // i -= 1; jne(.SLOOPKLEFT1) // iterate again if i != 0. label(.SPOSTACCUM) // ymm4 ymm5 // ymm6 ymm7 vhaddps( ymm5, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vhaddps( xmm1, xmm0, xmm0 ) vpermilps(imm(0xd8), xmm0, xmm0) vhaddps( xmm0, xmm0, xmm4 ) vhaddps( ymm7, ymm6, ymm2 ) vextractf128(imm(1), ymm2, xmm3 ) vhaddps( xmm3, xmm2, xmm2 ) vpermilps(imm(0xd8), xmm2, xmm2) vhaddps( xmm2, xmm2, xmm6 ) // xmm4[0:1] = sum(ymm4) sum(ymm5) // xmm6[0:1] = sum(ymm6) sum(ymm7) //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), xmm0) // load alpha and duplicate vbroadcastss(mem(rbx), xmm3) // load beta and duplicate vmulps(xmm0, xmm4, xmm4) // scale by alpha vmulps(xmm0, xmm6, xmm6) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(float) // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case label(.SROWSTORED) vmovsd(mem(rcx), xmm0) vfmadd231ps(xmm0, xmm3, xmm4) vmovsd(xmm4, mem(rcx)) add(rdi, rcx) vmovsd(mem(rcx), xmm0) vfmadd231ps(xmm0, xmm3, xmm6) vmovsd(xmm6, mem(rcx)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SBETAZERO) label(.SROWSTORBZ) vmovsd(xmm4, mem(rcx)) add(rdi, rcx) vmovsd(xmm6, mem(rcx)) //add(rdi, rcx) label(.SDONE) label(.SRETURN) end_asm( : // output operands (none) : // input operands [k_iter32] "m" (k_iter32), [k_iter8] "m" (k_iter8), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_sgemmsup_rd_haswell_asm_1x2 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter32 = k0 / 32; uint64_t k_left32 = k0 % 32; uint64_t k_iter8 = k_left32 / 8; uint64_t k_left1 = k_left32 % 8; //uint64_t m_iter = m0 / 3; //uint64_t m_left = m0 % 3; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) //lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) //lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b //lea(mem(r8, r8, 2), r10) // r10 = 3*rs_a mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) // r12 = rcx = c // r14 = rax = a // rdx = rbx = b #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorps ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorps(ymm4, ymm4, ymm4) vxorps(ymm5, ymm5, ymm5) #endif //lea(mem(r12), rcx) // rcx = c_ii; //lea(mem(r14), rax) // rax = a_ii; //lea(mem(rdx), rbx) // rbx = b; #if 1 //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) //lea(mem(rcx, rdi, 2), r10) // //lea(mem(r10, rdi, 1), r10) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 1*4)) // prefetch c + 0*rs_c #endif mov(var(k_iter32), rsi) // i = k_iter32; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKITER8) // if i == 0, jump to code that // contains the k_iter8 loop. label(.SLOOPKITER32) // MAIN LOOP // ---------------------------------- iteration 0 #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovups(mem(rbx ), ymm0) vmovups(mem(rbx, r11, 1), ymm1) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vmovups(mem(rax ), ymm3) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) // ---------------------------------- iteration 1 vmovups(mem(rbx ), ymm0) vmovups(mem(rbx, r11, 1), ymm1) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vmovups(mem(rax ), ymm3) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) // ---------------------------------- iteration 2 #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovups(mem(rbx ), ymm0) vmovups(mem(rbx, r11, 1), ymm1) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vmovups(mem(rax ), ymm3) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) // ---------------------------------- iteration 3 vmovups(mem(rbx ), ymm0) vmovups(mem(rbx, r11, 1), ymm1) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vmovups(mem(rax ), ymm3) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) dec(rsi) // i -= 1; jne(.SLOOPKITER32) // iterate again if i != 0. label(.SCONSIDKITER8) mov(var(k_iter8), rsi) // i = k_iter8; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter8 loop. label(.SLOOPKITER8) // EDGE LOOP (ymm) #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovups(mem(rbx ), ymm0) vmovups(mem(rbx, r11, 1), ymm1) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vmovups(mem(rax ), ymm3) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) dec(rsi) // i -= 1; jne(.SLOOPKITER8) // iterate again if i != 0. label(.SCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.SLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovss(mem(rbx ), xmm0) vmovss(mem(rbx, r11, 1), xmm1) add(imm(1*4), rbx) // b += 8*rs_b = 8*4; vmovss(mem(rax ), xmm3) add(imm(1*4), rax) // a += 8*cs_a = 8*4; vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) dec(rsi) // i -= 1; jne(.SLOOPKLEFT1) // iterate again if i != 0. label(.SPOSTACCUM) // ymm4 ymm5 vhaddps( ymm5, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vhaddps( xmm1, xmm0, xmm0 ) vpermilps(imm(0xd8), xmm0, xmm0) vhaddps( xmm0, xmm0, xmm4 ) // xmm4[0:1] = sum(ymm4) sum(ymm5) //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), xmm0) // load alpha and duplicate vbroadcastss(mem(rbx), xmm3) // load beta and duplicate vmulps(xmm0, xmm4, xmm4) // scale by alpha //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(float) // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case label(.SROWSTORED) vmovsd(mem(rcx), xmm0) vfmadd231ps(xmm0, xmm3, xmm4) vmovsd(xmm4, mem(rcx)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SBETAZERO) label(.SROWSTORBZ) vmovsd(xmm4, mem(rcx)) //add(rdi, rcx) label(.SDONE) label(.SRETURN) end_asm( : // output operands (none) : // input operands [k_iter32] "m" (k_iter32), [k_iter8] "m" (k_iter8), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } blis-0.9.0/kernels/haswell/3/sup/s6x16/bli_gemmsup_rd_haswell_asm_sMx4.c000066400000000000000000001155211422157504600260540ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define BLIS_ASM_SYNTAX_ATT #include "bli_x86_asm_macros.h" /* rrc: -------- ------ | | | | | | | | -------- ------ | | | | | | | | -------- += ------ ... | | | | | | | | -------- ------ | | | | | | | | -------- ------ : -------- ------ : Assumptions: - C is row-stored and B is column-stored; - A is row-stored; - m0 and n0 are at most MR and NR, respectively. Therefore, this (r)ow-preferential microkernel is well-suited for a dot-product-based accumulation that performs vector loads from both A and B. */ // Prototype reference microkernels. GEMMSUP_KER_PROT( float, s, gemmsup_r_haswell_ref ) void bli_sgemmsup_rd_haswell_asm_6x4 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter32 = k0 / 32; uint64_t k_left32 = k0 % 32; uint64_t k_iter8 = k_left32 / 8; uint64_t k_left1 = k_left32 % 8; uint64_t m_iter = m0 / 3; //uint64_t m_left = m0 % 3; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), r14) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) //lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rdx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b lea(mem(r8, r8, 2), r10) // r10 = 3*rs_a mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) // r12 = rcx = c // r14 = rax = a // rdx = rbx = b // r9 = m dim index ii mov(var(m_iter), r9) // ii = m_iter; label(.SLOOP3X4I) // LOOP OVER ii = [ m_iter ... 1 0 ] #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorps ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorps(ymm4, ymm4, ymm4) vxorps(ymm5, ymm5, ymm5) vxorps(ymm6, ymm6, ymm6) vxorps(ymm7, ymm7, ymm7) vxorps(ymm8, ymm8, ymm8) vxorps(ymm9, ymm9, ymm9) vxorps(ymm10, ymm10, ymm10) vxorps(ymm11, ymm11, ymm11) vxorps(ymm12, ymm12, ymm12) vxorps(ymm13, ymm13, ymm13) vxorps(ymm14, ymm14, ymm14) vxorps(ymm15, ymm15, ymm15) #endif lea(mem(r12), rcx) // rcx = c_ii; lea(mem(r14), rax) // rax = a_ii; lea(mem(rdx), rbx) // rbx = b; #if 1 //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) prefetch(0, mem(rcx, 1*4)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 1*4)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 1*4)) // prefetch c + 2*rs_c #endif lea(mem(r8, r8, 4), rbp) // rbp = 5*rs_a mov(var(k_iter32), rsi) // i = k_iter32; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKITER8) // if i == 0, jump to code that // contains the k_iter8 loop. label(.SLOOPKITER32) // MAIN LOOP // ---------------------------------- iteration 0 #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) vmovups(mem(rax, r8, 2), ymm2) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) // ---------------------------------- iteration 1 vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) vmovups(mem(rax, r8, 2), ymm2) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) // ---------------------------------- iteration 2 #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) vmovups(mem(rax, r8, 2), ymm2) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) // ---------------------------------- iteration 3 vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) vmovups(mem(rax, r8, 2), ymm2) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.SLOOPKITER32) // iterate again if i != 0. label(.SCONSIDKITER8) mov(var(k_iter8), rsi) // i = k_iter8; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter8 loop. label(.SLOOPKITER8) // EDGE LOOP (ymm) #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) vmovups(mem(rax, r8, 2), ymm2) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.SLOOPKITER8) // iterate again if i != 0. label(.SCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.SLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovss(mem(rax ), xmm0) vmovss(mem(rax, r8, 1), xmm1) vmovss(mem(rax, r8, 2), xmm2) add(imm(1*4), rax) // a += 1*cs_a = 1*4; vmovss(mem(rbx ), xmm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovss(mem(rbx, r11, 1), xmm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovss(mem(rbx, r11, 2), xmm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovss(mem(rbx, r13, 1), xmm3) add(imm(1*4), rbx) // b += 1*rs_b = 1*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.SLOOPKLEFT1) // iterate again if i != 0. label(.SPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 // ymm5 ymm8 ymm11 ymm14 // ymm6 ymm9 ymm12 ymm15 vhaddps( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vhaddps( xmm1, xmm0, xmm0 ) vpermilps(imm(0xd8), xmm0, xmm0) vhaddps( xmm0, xmm0, xmm0 ) vhaddps( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm3 ) vhaddps( xmm3, xmm2, xmm2 ) vpermilps(imm(0xd8), xmm2, xmm2) vhaddps( xmm2, xmm2, xmm2 ) vshufps(imm(0x44), xmm2, xmm0, xmm4) // xmm4[0] = sum(ymm4); xmm4[1] = sum(ymm7) // xmm4[2] = sum(ymm10); xmm4[3] = sum(ymm13) vhaddps( ymm8, ymm5, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vhaddps( xmm1, xmm0, xmm0 ) vpermilps(imm(0xd8), xmm0, xmm0) vhaddps( xmm0, xmm0, xmm0 ) vhaddps( ymm14, ymm11, ymm2 ) vextractf128(imm(1), ymm2, xmm3 ) vhaddps( xmm3, xmm2, xmm2 ) vpermilps(imm(0xd8), xmm2, xmm2) vhaddps( xmm2, xmm2, xmm2 ) vshufps(imm(0x44), xmm2, xmm0, xmm5) // xmm5[0] = sum(ymm5); xmm5[1] = sum(ymm8) // xmm5[2] = sum(ymm11); xmm5[3] = sum(ymm14) vhaddps( ymm9, ymm6, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vhaddps( xmm1, xmm0, xmm0 ) vpermilps(imm(0xd8), xmm0, xmm0) vhaddps( xmm0, xmm0, xmm0 ) vhaddps( ymm15, ymm12, ymm2 ) vextractf128(imm(1), ymm2, xmm3 ) vhaddps( xmm3, xmm2, xmm2 ) vpermilps(imm(0xd8), xmm2, xmm2) vhaddps( xmm2, xmm2, xmm2 ) vshufps(imm(0x44), xmm2, xmm0, xmm6) // xmm6[0] = sum(ymm6); xmm6[1] = sum(ymm9) // xmm6[2] = sum(ymm12); xmm6[3] = sum(ymm15) //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), xmm0) // load alpha and duplicate vbroadcastss(mem(rbx), xmm3) // load beta and duplicate vmulps(xmm0, xmm4, xmm4) // scale by alpha vmulps(xmm0, xmm5, xmm5) vmulps(xmm0, xmm6, xmm6) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(float) // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case label(.SROWSTORED) vfmadd231ps(mem(rcx), xmm3, xmm4) vmovups(xmm4, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), xmm3, xmm5) vmovups(xmm5, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), xmm3, xmm6) vmovups(xmm6, mem(rcx)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SBETAZERO) label(.SROWSTORBZ) vmovups(xmm4, mem(rcx)) add(rdi, rcx) vmovups(xmm5, mem(rcx)) add(rdi, rcx) vmovups(xmm6, mem(rcx)) //add(rdi, rcx) label(.SDONE) lea(mem(r12, rdi, 2), r12) // lea(mem(r12, rdi, 1), r12) // c_ii = r12 += 3*rs_c lea(mem(r14, r8, 2), r14) // lea(mem(r14, r8, 1), r14) // a_ii = r14 += 3*rs_a dec(r9) // ii -= 1; jne(.SLOOP3X4I) // iterate again if ii != 0. label(.SRETURN) end_asm( : // output operands (none) : // input operands [m_iter] "m" (m_iter), [k_iter32] "m" (k_iter32), [k_iter8] "m" (k_iter8), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_sgemmsup_rd_haswell_asm_2x4 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter32 = k0 / 32; uint64_t k_left32 = k0 % 32; uint64_t k_iter8 = k_left32 / 8; uint64_t k_left1 = k_left32 % 8; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) //lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b //lea(mem(r8, r8, 2), r10) // r10 = 3*rs_a mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) // r12 = rcx = c // r14 = rax = a // rdx = rbx = b #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorps ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorps(ymm4, ymm4, ymm4) vxorps(ymm5, ymm5, ymm5) vxorps(ymm7, ymm7, ymm7) vxorps(ymm8, ymm8, ymm8) vxorps(ymm10, ymm10, ymm10) vxorps(ymm11, ymm11, ymm11) vxorps(ymm13, ymm13, ymm13) vxorps(ymm14, ymm14, ymm14) #endif //lea(mem(r12), rcx) // rcx = c; //lea(mem(r14), rax) // rax = a; //lea(mem(rdx), rbx) // rbx = b; #if 1 //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) prefetch(0, mem(rcx, 1*4)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 1*4)) // prefetch c + 1*rs_c #endif mov(var(k_iter32), rsi) // i = k_iter32; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKITER8) // if i == 0, jump to code that // contains the k_iter8 loop. label(.SLOOPKITER32) // MAIN LOOP // ---------------------------------- iteration 0 #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a #endif vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) // ---------------------------------- iteration 1 vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) // ---------------------------------- iteration 2 #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a #endif vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) // ---------------------------------- iteration 3 vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) dec(rsi) // i -= 1; jne(.SLOOPKITER32) // iterate again if i != 0. label(.SCONSIDKITER8) mov(var(k_iter8), rsi) // i = k_iter8; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter8 loop. label(.SLOOPKITER8) // EDGE LOOP (ymm) #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a #endif vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) dec(rsi) // i -= 1; jne(.SLOOPKITER8) // iterate again if i != 0. label(.SCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.SLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovss(mem(rax ), xmm0) vmovss(mem(rax, r8, 1), xmm1) add(imm(1*4), rax) // a += 1*cs_a = 1*4; vmovss(mem(rbx ), xmm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovss(mem(rbx, r11, 1), xmm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vmovss(mem(rbx, r11, 2), xmm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vmovss(mem(rbx, r13, 1), xmm3) add(imm(1*4), rbx) // b += 1*rs_b = 1*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) dec(rsi) // i -= 1; jne(.SLOOPKLEFT1) // iterate again if i != 0. label(.SPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 // ymm5 ymm8 ymm11 ymm14 vhaddps( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vhaddps( xmm1, xmm0, xmm0 ) vpermilps(imm(0xd8), xmm0, xmm0) vhaddps( xmm0, xmm0, xmm0 ) vhaddps( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm3 ) vhaddps( xmm3, xmm2, xmm2 ) vpermilps(imm(0xd8), xmm2, xmm2) vhaddps( xmm2, xmm2, xmm2 ) vshufps(imm(0x44), xmm2, xmm0, xmm4) // xmm4[0] = sum(ymm4); xmm4[1] = sum(ymm7) // xmm4[2] = sum(ymm10); xmm4[3] = sum(ymm13) vhaddps( ymm8, ymm5, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vhaddps( xmm1, xmm0, xmm0 ) vpermilps(imm(0xd8), xmm0, xmm0) vhaddps( xmm0, xmm0, xmm0 ) vhaddps( ymm14, ymm11, ymm2 ) vextractf128(imm(1), ymm2, xmm3 ) vhaddps( xmm3, xmm2, xmm2 ) vpermilps(imm(0xd8), xmm2, xmm2) vhaddps( xmm2, xmm2, xmm2 ) vshufps(imm(0x44), xmm2, xmm0, xmm5) // xmm5[0] = sum(ymm5); xmm5[1] = sum(ymm8) // xmm5[2] = sum(ymm11); xmm5[3] = sum(ymm14) //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), xmm0) // load alpha and duplicate vbroadcastss(mem(rbx), xmm3) // load beta and duplicate vmulps(xmm0, xmm4, xmm4) // scale by alpha vmulps(xmm0, xmm5, xmm5) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(float) // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case label(.SROWSTORED) vfmadd231ps(mem(rcx), xmm3, xmm4) vmovups(xmm4, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), xmm3, xmm5) vmovups(xmm5, mem(rcx)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SBETAZERO) label(.SROWSTORBZ) vmovups(xmm4, mem(rcx)) add(rdi, rcx) vmovups(xmm5, mem(rcx)) //add(rdi, rcx) label(.SDONE) label(.SRETURN) end_asm( : // output operands (none) : // input operands [k_iter32] "m" (k_iter32), [k_iter8] "m" (k_iter8), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_sgemmsup_rd_haswell_asm_1x4 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter32 = k0 / 32; uint64_t k_left32 = k0 % 32; uint64_t k_iter8 = k_left32 / 8; uint64_t k_left1 = k_left32 % 8; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) //lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b //lea(mem(r8, r8, 2), r10) // r10 = 3*rs_a mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) // r12 = rcx = c // r14 = rax = a // rdx = rbx = b #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorps ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorps(ymm4, ymm4, ymm4) vxorps(ymm7, ymm7, ymm7) vxorps(ymm10, ymm10, ymm10) vxorps(ymm13, ymm13, ymm13) #endif //lea(mem(r12), rcx) // rcx = c; //lea(mem(r14), rax) // rax = a; //lea(mem(rdx), rbx) // rbx = b; #if 1 //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) prefetch(0, mem(rcx, 1*4)) // prefetch c + 0*rs_c #endif mov(var(k_iter32), rsi) // i = k_iter32; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKITER8) // if i == 0, jump to code that // contains the k_iter8 loop. label(.SLOOPKITER32) // MAIN LOOP // ---------------------------------- iteration 0 #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a #endif vmovups(mem(rax ), ymm0) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) // ---------------------------------- iteration 1 vmovups(mem(rax ), ymm0) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) // ---------------------------------- iteration 2 #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a #endif vmovups(mem(rax ), ymm0) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) // ---------------------------------- iteration 3 vmovups(mem(rax ), ymm0) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) dec(rsi) // i -= 1; jne(.SLOOPKITER32) // iterate again if i != 0. label(.SCONSIDKITER8) mov(var(k_iter8), rsi) // i = k_iter8; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter8 loop. label(.SLOOPKITER8) // EDGE LOOP (ymm) #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a #endif vmovups(mem(rax ), ymm0) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) dec(rsi) // i -= 1; jne(.SLOOPKITER8) // iterate again if i != 0. label(.SCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.SLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovss(mem(rax ), xmm0) add(imm(1*4), rax) // a += 1*cs_a = 1*4; vmovss(mem(rbx ), xmm3) vfmadd231ps(ymm0, ymm3, ymm4) vmovss(mem(rbx, r11, 1), xmm3) vfmadd231ps(ymm0, ymm3, ymm7) vmovss(mem(rbx, r11, 2), xmm3) vfmadd231ps(ymm0, ymm3, ymm10) vmovss(mem(rbx, r13, 1), xmm3) add(imm(1*4), rbx) // b += 1*rs_b = 1*4; vfmadd231ps(ymm0, ymm3, ymm13) dec(rsi) // i -= 1; jne(.SLOOPKLEFT1) // iterate again if i != 0. label(.SPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 vhaddps( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vhaddps( xmm1, xmm0, xmm0 ) vpermilps(imm(0xd8), xmm0, xmm0) vhaddps( xmm0, xmm0, xmm0 ) vhaddps( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm3 ) vhaddps( xmm3, xmm2, xmm2 ) vpermilps(imm(0xd8), xmm2, xmm2) vhaddps( xmm2, xmm2, xmm2 ) vshufps(imm(0x44), xmm2, xmm0, xmm4) // xmm4[0] = sum(ymm4); xmm4[1] = sum(ymm7) // xmm4[2] = sum(ymm10); xmm4[3] = sum(ymm13) //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), xmm0) // load alpha and duplicate vbroadcastss(mem(rbx), xmm3) // load beta and duplicate vmulps(xmm0, xmm4, xmm4) // scale by alpha //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(float) // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case label(.SROWSTORED) vfmadd231ps(mem(rcx), xmm3, xmm4) vmovups(xmm4, mem(rcx)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SBETAZERO) label(.SROWSTORBZ) vmovups(xmm4, mem(rcx)) //add(rdi, rcx) label(.SDONE) label(.SRETURN) end_asm( : // output operands (none) : // input operands [k_iter32] "m" (k_iter32), [k_iter8] "m" (k_iter8), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } blis-0.9.0/kernels/haswell/3/sup/s6x16/bli_gemmsup_rd_haswell_asm_sMx8.c000066400000000000000000001221611422157504600260560ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define BLIS_ASM_SYNTAX_ATT #include "bli_x86_asm_macros.h" /* rrc: -------- ------ | | | | | | | | -------- ------ | | | | | | | | -------- += ------ ... | | | | | | | | -------- ------ | | | | | | | | -------- ------ : -------- ------ : Assumptions: - C is row-stored and B is column-stored; - A is row-stored; - m0 and n0 are at most MR and NR, respectively. Therefore, this (r)ow-preferential microkernel is well-suited for a dot-product-based accumulation that performs vector loads from both A and B. */ // Prototype reference microkernels. GEMMSUP_KER_PROT( float, s, gemmsup_r_haswell_ref ) void bli_sgemmsup_rd_haswell_asm_6x8 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter32 = k0 / 32; uint64_t k_left32 = k0 % 32; uint64_t k_iter8 = k_left32 / 8; uint64_t k_left1 = k_left32 % 8; uint64_t m_iter = m0 / 3; //uint64_t m_left = m0 % 3; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. //mov(var(a), r14) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) //lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a //mov(var(b), rdx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b lea(mem(r8, r8, 2), r10) // r10 = 3*rs_a //mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) // r12 = rcx = c // r14 = rax = a // rdx = rbx = b // r9 = m dim index ii // r15 = n dim index jj mov(imm(0), r15) // jj = 0; label(.SLOOP3X4J) // LOOP OVER jj = [ 0 1 ... ] mov(var(a), r14) // load address of a mov(var(b), rdx) // load address of b mov(var(c), r12) // load address of c lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(imm(1*4), rsi) // rsi *= cs_c*sizeof(float) = 1*4 lea(mem(r12, rsi, 1), r12) // r12 = c + 4*jj*cs_c; lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(r11, rsi) // rsi *= cs_b; lea(mem(rdx, rsi, 1), rdx) // rbx = b + 4*jj*cs_b; mov(var(m_iter), r9) // ii = m_iter; label(.SLOOP3X4I) // LOOP OVER ii = [ m_iter ... 1 0 ] #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorps ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorps(ymm4, ymm4, ymm4) vxorps(ymm5, ymm5, ymm5) vxorps(ymm6, ymm6, ymm6) vxorps(ymm7, ymm7, ymm7) vxorps(ymm8, ymm8, ymm8) vxorps(ymm9, ymm9, ymm9) vxorps(ymm10, ymm10, ymm10) vxorps(ymm11, ymm11, ymm11) vxorps(ymm12, ymm12, ymm12) vxorps(ymm13, ymm13, ymm13) vxorps(ymm14, ymm14, ymm14) vxorps(ymm15, ymm15, ymm15) #endif lea(mem(r12), rcx) // rcx = c_iijj; lea(mem(r14), rax) // rax = a_ii; lea(mem(rdx), rbx) // rbx = b_jj; #if 1 //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) prefetch(0, mem(rcx, 1*4)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 1*4)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 1*4)) // prefetch c + 2*rs_c #endif lea(mem(r8, r8, 4), rbp) // rbp = 5*rs_a mov(var(k_iter32), rsi) // i = k_iter32; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKITER8) // if i == 0, jump to code that // contains the k_iter8 loop. label(.SLOOPKITER32) // MAIN LOOP // ---------------------------------- iteration 0 #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) vmovups(mem(rax, r8, 2), ymm2) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) // ---------------------------------- iteration 1 vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) vmovups(mem(rax, r8, 2), ymm2) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) // ---------------------------------- iteration 2 #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) vmovups(mem(rax, r8, 2), ymm2) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) // ---------------------------------- iteration 3 vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) vmovups(mem(rax, r8, 2), ymm2) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.SLOOPKITER32) // iterate again if i != 0. label(.SCONSIDKITER8) mov(var(k_iter8), rsi) // i = k_iter8; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter8 loop. label(.SLOOPKITER8) // EDGE LOOP (ymm) #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rbp, 1, 0*8)) // prefetch rax + 5*cs_a #endif vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) vmovups(mem(rax, r8, 2), ymm2) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.SLOOPKITER8) // iterate again if i != 0. label(.SCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.SLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovss(mem(rax ), xmm0) vmovss(mem(rax, r8, 1), xmm1) vmovss(mem(rax, r8, 2), xmm2) add(imm(1*4), rax) // a += 1*cs_a = 1*4; vmovss(mem(rbx ), xmm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovss(mem(rbx, r11, 1), xmm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovss(mem(rbx, r11, 2), xmm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovss(mem(rbx, r13, 1), xmm3) add(imm(1*4), rbx) // b += 1*rs_b = 1*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.SLOOPKLEFT1) // iterate again if i != 0. label(.SPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 // ymm5 ymm8 ymm11 ymm14 // ymm6 ymm9 ymm12 ymm15 vhaddps( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vhaddps( xmm1, xmm0, xmm0 ) vpermilps(imm(0xd8), xmm0, xmm0) vhaddps( xmm0, xmm0, xmm0 ) vhaddps( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm3 ) vhaddps( xmm3, xmm2, xmm2 ) vpermilps(imm(0xd8), xmm2, xmm2) vhaddps( xmm2, xmm2, xmm2 ) vshufps(imm(0x44), xmm2, xmm0, xmm4) // xmm4[0] = sum(ymm4); xmm4[1] = sum(ymm7) // xmm4[2] = sum(ymm10); xmm4[3] = sum(ymm13) vhaddps( ymm8, ymm5, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vhaddps( xmm1, xmm0, xmm0 ) vpermilps(imm(0xd8), xmm0, xmm0) vhaddps( xmm0, xmm0, xmm0 ) vhaddps( ymm14, ymm11, ymm2 ) vextractf128(imm(1), ymm2, xmm3 ) vhaddps( xmm3, xmm2, xmm2 ) vpermilps(imm(0xd8), xmm2, xmm2) vhaddps( xmm2, xmm2, xmm2 ) vshufps(imm(0x44), xmm2, xmm0, xmm5) // xmm5[0] = sum(ymm5); xmm5[1] = sum(ymm8) // xmm5[2] = sum(ymm11); xmm5[3] = sum(ymm14) vhaddps( ymm9, ymm6, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vhaddps( xmm1, xmm0, xmm0 ) vpermilps(imm(0xd8), xmm0, xmm0) vhaddps( xmm0, xmm0, xmm0 ) vhaddps( ymm15, ymm12, ymm2 ) vextractf128(imm(1), ymm2, xmm3 ) vhaddps( xmm3, xmm2, xmm2 ) vpermilps(imm(0xd8), xmm2, xmm2) vhaddps( xmm2, xmm2, xmm2 ) vshufps(imm(0x44), xmm2, xmm0, xmm6) // xmm6[0] = sum(ymm6); xmm6[1] = sum(ymm9) // xmm6[2] = sum(ymm12); xmm6[3] = sum(ymm15) //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), xmm0) // load alpha and duplicate vbroadcastss(mem(rbx), xmm3) // load beta and duplicate vmulps(xmm0, xmm4, xmm4) // scale by alpha vmulps(xmm0, xmm5, xmm5) vmulps(xmm0, xmm6, xmm6) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(float) // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case label(.SROWSTORED) vfmadd231ps(mem(rcx), xmm3, xmm4) vmovups(xmm4, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), xmm3, xmm5) vmovups(xmm5, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), xmm3, xmm6) vmovups(xmm6, mem(rcx)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SBETAZERO) label(.SROWSTORBZ) vmovups(xmm4, mem(rcx)) add(rdi, rcx) vmovups(xmm5, mem(rcx)) add(rdi, rcx) vmovups(xmm6, mem(rcx)) //add(rdi, rcx) label(.SDONE) lea(mem(r12, rdi, 2), r12) // lea(mem(r12, rdi, 1), r12) // c_ii = r12 += 3*rs_c lea(mem(r14, r8, 2), r14) // lea(mem(r14, r8, 1), r14) // a_ii = r14 += 3*rs_a dec(r9) // ii -= 1; jne(.SLOOP3X4I) // iterate again if ii != 0. add(imm(4), r15) // jj += 4; cmp(imm(8), r15) // compare jj to 8 jl(.SLOOP3X4J) // if jj < 8, jump to beginning // of jj loop; otherwise, loop ends. label(.SRETURN) end_asm( : // output operands (none) : // input operands [m_iter] "m" (m_iter), [k_iter32] "m" (k_iter32), [k_iter8] "m" (k_iter8), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_sgemmsup_rd_haswell_asm_2x8 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter32 = k0 / 32; uint64_t k_left32 = k0 % 32; uint64_t k_iter8 = k_left32 / 8; uint64_t k_left1 = k_left32 % 8; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), r14) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) //lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rdx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b //lea(mem(r8, r8, 2), r10) // r10 = 3*rs_a mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) // r12 = rcx = c // r14 = rax = a // rdx = rbx = b // r9 = m dim index ii // r15 = n dim index jj mov(imm(0), r15) // jj = 0; label(.SLOOP3X4J) // LOOP OVER jj = [ 0 1 ... ] #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorps ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorps(ymm4, ymm4, ymm4) vxorps(ymm5, ymm5, ymm5) vxorps(ymm7, ymm7, ymm7) vxorps(ymm8, ymm8, ymm8) vxorps(ymm10, ymm10, ymm10) vxorps(ymm11, ymm11, ymm11) vxorps(ymm13, ymm13, ymm13) vxorps(ymm14, ymm14, ymm14) #endif lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(imm(1*4), rsi) // rsi *= cs_c*sizeof(float) = 1*4 lea(mem(r12, rsi, 1), rcx) // rcx = c + 4*jj*cs_c; lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(r11, rsi) // rsi *= cs_b; lea(mem(rdx, rsi, 1), rbx) // rbx = b + 4*jj*cs_b; lea(mem(r14), rax) // rax = a; #if 1 //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) prefetch(0, mem(rcx, 1*4)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 1*4)) // prefetch c + 1*rs_c #endif mov(var(k_iter32), rsi) // i = k_iter32; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKITER8) // if i == 0, jump to code that // contains the k_iter8 loop. label(.SLOOPKITER32) // MAIN LOOP // ---------------------------------- iteration 0 #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a #endif vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) // ---------------------------------- iteration 1 vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) // ---------------------------------- iteration 2 #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a #endif vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) // ---------------------------------- iteration 3 vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) dec(rsi) // i -= 1; jne(.SLOOPKITER32) // iterate again if i != 0. label(.SCONSIDKITER8) mov(var(k_iter8), rsi) // i = k_iter8; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter8 loop. label(.SLOOPKITER8) // EDGE LOOP (ymm) #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a #endif vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) dec(rsi) // i -= 1; jne(.SLOOPKITER8) // iterate again if i != 0. label(.SCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.SLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovss(mem(rax ), xmm0) vmovss(mem(rax, r8, 1), xmm1) add(imm(1*4), rax) // a += 1*cs_a = 1*4; vmovss(mem(rbx ), xmm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovss(mem(rbx, r11, 1), xmm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vmovss(mem(rbx, r11, 2), xmm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vmovss(mem(rbx, r13, 1), xmm3) add(imm(1*4), rbx) // b += 1*rs_b = 1*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) dec(rsi) // i -= 1; jne(.SLOOPKLEFT1) // iterate again if i != 0. label(.SPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 // ymm5 ymm8 ymm11 ymm14 vhaddps( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vhaddps( xmm1, xmm0, xmm0 ) vpermilps(imm(0xd8), xmm0, xmm0) vhaddps( xmm0, xmm0, xmm0 ) vhaddps( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm3 ) vhaddps( xmm3, xmm2, xmm2 ) vpermilps(imm(0xd8), xmm2, xmm2) vhaddps( xmm2, xmm2, xmm2 ) vshufps(imm(0x44), xmm2, xmm0, xmm4) // xmm4[0] = sum(ymm4); xmm4[1] = sum(ymm7) // xmm4[2] = sum(ymm10); xmm4[3] = sum(ymm13) vhaddps( ymm8, ymm5, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vhaddps( xmm1, xmm0, xmm0 ) vpermilps(imm(0xd8), xmm0, xmm0) vhaddps( xmm0, xmm0, xmm0 ) vhaddps( ymm14, ymm11, ymm2 ) vextractf128(imm(1), ymm2, xmm3 ) vhaddps( xmm3, xmm2, xmm2 ) vpermilps(imm(0xd8), xmm2, xmm2) vhaddps( xmm2, xmm2, xmm2 ) vshufps(imm(0x44), xmm2, xmm0, xmm5) // xmm5[0] = sum(ymm5); xmm5[1] = sum(ymm8) // xmm5[2] = sum(ymm11); xmm5[3] = sum(ymm14) //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), xmm0) // load alpha and duplicate vbroadcastss(mem(rbx), xmm3) // load beta and duplicate vmulps(xmm0, xmm4, xmm4) // scale by alpha vmulps(xmm0, xmm5, xmm5) //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(float) // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case label(.SROWSTORED) vfmadd231ps(mem(rcx), xmm3, xmm4) vmovups(xmm4, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), xmm3, xmm5) vmovups(xmm5, mem(rcx)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SBETAZERO) label(.SROWSTORBZ) vmovups(xmm4, mem(rcx)) add(rdi, rcx) vmovups(xmm5, mem(rcx)) //add(rdi, rcx) label(.SDONE) add(imm(4), r15) // jj += 4; cmp(imm(8), r15) // compare jj to 8 jl(.SLOOP3X4J) // if jj < 8, jump to beginning // of jj loop; otherwise, loop ends. label(.SRETURN) end_asm( : // output operands (none) : // input operands [k_iter32] "m" (k_iter32), [k_iter8] "m" (k_iter8), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_sgemmsup_rd_haswell_asm_1x8 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter32 = k0 / 32; uint64_t k_left32 = k0 % 32; uint64_t k_iter8 = k_left32 / 8; uint64_t k_left1 = k_left32 % 8; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(a), r14) // load address of a. mov(var(rs_a), r8) // load rs_a //mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) //lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rdx) // load address of b. //mov(var(rs_b), r10) // load rs_b mov(var(cs_b), r11) // load cs_b //lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b //lea(mem(r8, r8, 2), r10) // r10 = 3*rs_a mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) // r12 = rcx = c // r14 = rax = a // rdx = rbx = b // r9 = m dim index ii // r15 = n dim index jj mov(imm(0), r15) // jj = 0; label(.SLOOP3X4J) // LOOP OVER jj = [ 0 1 ... ] #if 0 vzeroall() // zero all xmm/ymm registers. #else // skylake can execute 3 vxorps ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorps(ymm4, ymm4, ymm4) vxorps(ymm7, ymm7, ymm7) vxorps(ymm10, ymm10, ymm10) vxorps(ymm13, ymm13, ymm13) #endif lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(imm(1*4), rsi) // rsi *= cs_c*sizeof(float) = 1*4 lea(mem(r12, rsi, 1), rcx) // rcx = c + 4*jj*cs_c; lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(r11, rsi) // rsi *= cs_b; lea(mem(rdx, rsi, 1), rbx) // rbx = b + 4*jj*cs_b; lea(mem(r14), rax) // rax = a; #if 1 //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) prefetch(0, mem(rcx, 1*4)) // prefetch c + 0*rs_c #endif mov(var(k_iter32), rsi) // i = k_iter32; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKITER8) // if i == 0, jump to code that // contains the k_iter8 loop. label(.SLOOPKITER32) // MAIN LOOP // ---------------------------------- iteration 0 #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a #endif vmovups(mem(rax ), ymm0) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) // ---------------------------------- iteration 1 vmovups(mem(rax ), ymm0) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) // ---------------------------------- iteration 2 #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a #endif vmovups(mem(rax ), ymm0) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) // ---------------------------------- iteration 3 vmovups(mem(rax ), ymm0) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) dec(rsi) // i -= 1; jne(.SLOOPKITER32) // iterate again if i != 0. label(.SCONSIDKITER8) mov(var(k_iter8), rsi) // i = k_iter8; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter8 loop. label(.SLOOPKITER8) // EDGE LOOP (ymm) #if 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a #endif vmovups(mem(rax ), ymm0) add(imm(8*4), rax) // a += 8*cs_a = 8*4; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 8*rs_b = 8*4; vfmadd231ps(ymm0, ymm3, ymm13) dec(rsi) // i -= 1; jne(.SLOOPKITER8) // iterate again if i != 0. label(.SCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.SLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovss(mem(rax ), xmm0) add(imm(1*4), rax) // a += 1*cs_a = 1*4; vmovss(mem(rbx ), xmm3) vfmadd231ps(ymm0, ymm3, ymm4) vmovss(mem(rbx, r11, 1), xmm3) vfmadd231ps(ymm0, ymm3, ymm7) vmovss(mem(rbx, r11, 2), xmm3) vfmadd231ps(ymm0, ymm3, ymm10) vmovss(mem(rbx, r13, 1), xmm3) add(imm(1*4), rbx) // b += 1*rs_b = 1*4; vfmadd231ps(ymm0, ymm3, ymm13) dec(rsi) // i -= 1; jne(.SLOOPKLEFT1) // iterate again if i != 0. label(.SPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 // ymm5 ymm8 ymm11 ymm14 vhaddps( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vhaddps( xmm1, xmm0, xmm0 ) vpermilps(imm(0xd8), xmm0, xmm0) vhaddps( xmm0, xmm0, xmm0 ) vhaddps( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm3 ) vhaddps( xmm3, xmm2, xmm2 ) vpermilps(imm(0xd8), xmm2, xmm2) vhaddps( xmm2, xmm2, xmm2 ) vshufps(imm(0x44), xmm2, xmm0, xmm4) // xmm4[0] = sum(ymm4); xmm4[1] = sum(ymm7) // xmm4[2] = sum(ymm10); xmm4[3] = sum(ymm13) //mov(var(rs_c), rdi) // load rs_c //lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), xmm0) // load alpha and duplicate vbroadcastss(mem(rbx), xmm3) // load beta and duplicate vmulps(xmm0, xmm4, xmm4) // scale by alpha //mov(var(cs_c), rsi) // load cs_c //lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(float) // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case label(.SROWSTORED) vfmadd231ps(mem(rcx), xmm3, xmm4) vmovups(xmm4, mem(rcx)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SBETAZERO) label(.SROWSTORBZ) vmovups(xmm4, mem(rcx)) //add(rdi, rcx) label(.SDONE) add(imm(4), r15) // jj += 4; cmp(imm(8), r15) // compare jj to 8 jl(.SLOOP3X4J) // if jj < 8, jump to beginning // of jj loop; otherwise, loop ends. label(.SRETURN) end_asm( : // output operands (none) : // input operands [k_iter32] "m" (k_iter32), [k_iter8] "m" (k_iter8), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } blis-0.9.0/kernels/haswell/3/sup/s6x16/bli_gemmsup_rv_haswell_asm_sMx12.c000066400000000000000000003150531422157504600261570ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define BLIS_ASM_SYNTAX_ATT #include "bli_x86_asm_macros.h" /* rrr: -------- ------ -------- -------- ------ -------- -------- += ------ ... -------- -------- ------ -------- -------- ------ : -------- ------ : rcr: -------- | | | | -------- -------- | | | | -------- -------- += | | | | ... -------- -------- | | | | -------- -------- | | | | : -------- | | | | : Assumptions: - B is row-stored; - A is row- or column-stored; - m0 and n0 are at most MR and NR, respectively. Therefore, this (r)ow-preferential kernel is well-suited for contiguous (v)ector loads on B and single-element broadcasts from A. NOTE: These kernels explicitly support column-oriented IO, implemented via an in-register transpose. And thus they also support the crr and ccr cases, though only crr is ever utilized (because ccr is handled by transposing the operation and executing rcr, which does not incur the cost of the in-register transpose). crr: | | | | | | | | ------ -------- | | | | | | | | ------ -------- | | | | | | | | += ------ ... -------- | | | | | | | | ------ -------- | | | | | | | | ------ : | | | | | | | | ------ : */ // Prototype reference microkernels. GEMMSUP_KER_PROT( float, s, gemmsup_r_haswell_ref ) void bli_sgemmsup_rv_haswell_asm_6x12 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) //lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored prefetching on c lea(mem(rcx, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 7*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 7*8)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 7*8)) // prefetch c + 3*rs_c prefetch(0, mem(rdx, rdi, 1, 7*8)) // prefetch c + 4*rs_c prefetch(0, mem(rdx, rdi, 2, 7*8)) // prefetch c + 5*rs_c jmp(.SPOSTPFETCH) // jump to end of prefetching c label(.SCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) lea(mem(rsi, rsi, 2), rbp) // rbp = 3*cs_c; prefetch(0, mem(rcx, 5*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 5*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 5*8)) // prefetch c + 2*cs_c prefetch(0, mem(rcx, rbp, 1, 5*8)) // prefetch c + 3*cs_c prefetch(0, mem(rcx, rsi, 4, 5*8)) // prefetch c + 4*cs_c lea(mem(rcx, rsi, 4), rdx) // rdx = c + 4*cs_c; prefetch(0, mem(rdx, rsi, 1, 5*8)) // prefetch c + 5*cs_c prefetch(0, mem(rdx, rsi, 2, 5*8)) // prefetch c + 6*cs_c prefetch(0, mem(rdx, rbp, 1, 5*8)) // prefetch c + 7*cs_c prefetch(0, mem(rdx, rsi, 4, 5*8)) // prefetch c + 8*cs_c lea(mem(rcx, rsi, 8), rdx) // rdx = c + 8*cs_c; prefetch(0, mem(rdx, rsi, 1, 5*8)) // prefetch c + 9*cs_c prefetch(0, mem(rdx, rsi, 2, 5*8)) // prefetch c + 10*cs_c prefetch(0, mem(rdx, rbp, 1, 5*8)) // prefetch c + 11*cs_c label(.SPOSTPFETCH) // done prefetching c #if 1 lea(mem(rax, r9, 8), rdx) // lea(mem(rdx, r9, 8), rdx) // rdx = a + 16*cs_a; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(rdx, 5*8)) #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, r8, 4), ymm2) vbroadcastss(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, r9, 1, 5*8)) #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, r8, 4), ymm2) vbroadcastss(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(rdx, r9, 2, 5*8)) #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, r8, 4), ymm2) vbroadcastss(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) // ---------------------------------- iteration 3 #if 1 lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, r8, 4), ymm2) vbroadcastss(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP #if 0 prefetch(0, mem(rdx, 5*8)) add(r9, rdx) #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, r8, 4), ymm2) vbroadcastss(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), ymm0) // load alpha and duplicate vbroadcastss(mem(rbx), ymm3) // load beta and duplicate vmulps(ymm0, ymm4, ymm4) // scale by alpha vmulps(xmm0, xmm5, xmm5) vmulps(ymm0, ymm6, ymm6) vmulps(xmm0, xmm7, xmm7) vmulps(ymm0, ymm8, ymm8) vmulps(xmm0, xmm9, xmm9) vmulps(ymm0, ymm10, ymm10) vmulps(xmm0, xmm11, xmm11) vmulps(ymm0, ymm12, ymm12) vmulps(xmm0, xmm13, xmm13) vmulps(ymm0, ymm14, ymm14) vmulps(xmm0, xmm15, xmm15) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; lea(mem(rsi, rsi, 4), rbx) // rbx = 5*cs_c; lea(mem(rax, rsi, 4), rbp) // rbp = 7*cs_c; // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm4) vmovups(ymm4, mem(rcx, 0*32)) vfmadd231ps(mem(rcx, 1*32), xmm3, xmm5) vmovups(xmm5, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm6) vmovups(ymm6, mem(rcx, 0*32)) vfmadd231ps(mem(rcx, 1*32), xmm3, xmm7) vmovups(xmm7, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm8) vmovups(ymm8, mem(rcx, 0*32)) vfmadd231ps(mem(rcx, 1*32), xmm3, xmm9) vmovups(xmm9, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm10) vmovups(ymm10, mem(rcx, 0*32)) vfmadd231ps(mem(rcx, 1*32), xmm3, xmm11) vmovups(xmm11, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm12) vmovups(ymm12, mem(rcx, 0*32)) vfmadd231ps(mem(rcx, 1*32), xmm3, xmm13) vmovups(xmm13, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm14) vmovups(ymm14, mem(rcx, 0*32)) vfmadd231ps(mem(rcx, 1*32), xmm3, xmm15) vmovups(xmm15, mem(rcx, 1*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORED) // begin I/O on columns 0-7 vunpcklps(ymm6, ymm4, ymm0) vunpcklps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx ), xmm3, xmm0) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm0, mem(rcx )) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx, rsi, 1), xmm3, xmm1) vfmadd231ps(mem(rcx, rbx, 1), xmm3, xmm2) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rbx, 1)) // store ( gamma05..gamma35 ) vunpckhps(ymm6, ymm4, ymm0) vunpckhps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx, rsi, 2), xmm3, xmm0) vfmadd231ps(mem(rcx, rax, 2), xmm3, xmm2) vmovups(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, rax, 2)) // store ( gamma06..gamma36 ) vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx, rax, 1), xmm3, xmm1) vfmadd231ps(mem(rcx, rbp, 1), xmm3, xmm2) vmovups(xmm1, mem(rcx, rax, 1)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, rbp, 1)) // store ( gamma07..gamma37 ) lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vunpcklps(ymm14, ymm12, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(mem(rdx ), xmm1, xmm1) vmovhpd(mem(rdx, rsi, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(rdx )) // store ( gamma40..gamma50 ) vmovhpd(xmm0, mem(rdx, rsi, 1)) // store ( gamma41..gamma51 ) vmovlpd(mem(rdx, rsi, 4), xmm1, xmm1) vmovhpd(mem(rdx, rbx, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm2) vmovlpd(xmm2, mem(rdx, rsi, 4)) // store ( gamma44..gamma54 ) vmovhpd(xmm2, mem(rdx, rbx, 1)) // store ( gamma45..gamma55 ) vunpckhps(ymm14, ymm12, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(mem(rdx, rsi, 2), xmm1, xmm1) vmovhpd(mem(rdx, rax, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(rdx, rsi, 2)) // store ( gamma42..gamma52 ) vmovhpd(xmm0, mem(rdx, rax, 1)) // store ( gamma43..gamma53 ) vmovlpd(mem(rdx, rax, 2), xmm1, xmm1) vmovhpd(mem(rdx, rbp, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm2) vmovlpd(xmm2, mem(rdx, rax, 2)) // store ( gamma46..gamma56 ) vmovhpd(xmm2, mem(rdx, rbp, 1)) // store ( gamma47..gamma57 ) lea(mem(rdx, rsi, 8), rdx) // rdx += 8*cs_c // begin I/O on columns 8-11 vunpcklps(ymm7, ymm5, ymm0) vunpcklps(ymm11, ymm9, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vfmadd231ps(mem(rcx ), xmm3, xmm0) vmovups(xmm0, mem(rcx )) // store ( gamma00..gamma30 ) vfmadd231ps(mem(rcx, rsi, 1), xmm3, xmm1) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) vunpckhps(ymm7, ymm5, ymm0) vunpckhps(ymm11, ymm9, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vfmadd231ps(mem(rcx, rsi, 2), xmm3, xmm0) vmovups(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma32 ) vfmadd231ps(mem(rcx, rax, 1), xmm3, xmm1) vmovups(xmm1, mem(rcx, rax, 1)) // store ( gamma03..gamma33 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vunpcklps(ymm15, ymm13, ymm0) vmovlpd(mem(rdx ), xmm1, xmm1) vmovhpd(mem(rdx, rsi, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(rdx )) // store ( gamma40..gamma50 ) vmovhpd(xmm0, mem(rdx, rsi, 1)) // store ( gamma41..gamma51 ) vunpckhps(ymm15, ymm13, ymm0) vmovlpd(mem(rdx, rsi, 2), xmm1, xmm1) vmovhpd(mem(rdx, rax, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(rdx, rsi, 2)) // store ( gamma42..gamma52 ) vmovhpd(xmm0, mem(rdx, rax, 1)) // store ( gamma43..gamma53 ) //lea(mem(rdx, rsi, 8), rdx) // rdx += 8*cs_c jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovups(ymm4, mem(rcx, 0*32)) vmovups(xmm5, mem(rcx, 1*32)) add(rdi, rcx) vmovups(ymm6, mem(rcx, 0*32)) vmovups(xmm7, mem(rcx, 1*32)) add(rdi, rcx) vmovups(ymm8, mem(rcx, 0*32)) vmovups(xmm9, mem(rcx, 1*32)) add(rdi, rcx) vmovups(ymm10, mem(rcx, 0*32)) vmovups(xmm11, mem(rcx, 1*32)) add(rdi, rcx) vmovups(ymm12, mem(rcx, 0*32)) vmovups(xmm13, mem(rcx, 1*32)) add(rdi, rcx) vmovups(ymm14, mem(rcx, 0*32)) vmovups(xmm15, mem(rcx, 1*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) // begin I/O on columns 0-7 vunpcklps(ymm6, ymm4, ymm0) vunpcklps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx )) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rbx, 1)) // store ( gamma05..gamma35 ) vunpckhps(ymm6, ymm4, ymm0) vunpckhps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, rax, 2)) // store ( gamma06..gamma36 ) vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx, rax, 1)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, rbp, 1)) // store ( gamma07..gamma37 ) lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vunpcklps(ymm14, ymm12, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(xmm0, mem(rdx )) // store ( gamma40..gamma50 ) vmovhpd(xmm0, mem(rdx, rsi, 1)) // store ( gamma41..gamma51 ) vmovlpd(xmm2, mem(rdx, rsi, 4)) // store ( gamma44..gamma54 ) vmovhpd(xmm2, mem(rdx, rbx, 1)) // store ( gamma45..gamma55 ) vunpckhps(ymm14, ymm12, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(xmm0, mem(rdx, rsi, 2)) // store ( gamma42..gamma52 ) vmovhpd(xmm0, mem(rdx, rax, 1)) // store ( gamma43..gamma53 ) vmovlpd(xmm2, mem(rdx, rax, 2)) // store ( gamma46..gamma56 ) vmovhpd(xmm2, mem(rdx, rbp, 1)) // store ( gamma47..gamma57 ) lea(mem(rdx, rsi, 8), rdx) // rdx += 8*cs_c // begin I/O on columns 8-11 vunpcklps(ymm7, ymm5, ymm0) vunpcklps(ymm11, ymm9, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vmovups(xmm0, mem(rcx )) // store ( gamma00..gamma30 ) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) vunpckhps(ymm7, ymm5, ymm0) vunpckhps(ymm11, ymm9, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vmovups(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma32 ) vmovups(xmm1, mem(rcx, rax, 1)) // store ( gamma03..gamma33 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vunpcklps(ymm15, ymm13, ymm0) vmovlpd(xmm0, mem(rdx )) // store ( gamma40..gamma50 ) vmovhpd(xmm0, mem(rdx, rsi, 1)) // store ( gamma41..gamma51 ) vunpckhps(ymm15, ymm13, ymm0) vmovlpd(xmm0, mem(rdx, rsi, 2)) // store ( gamma42..gamma52 ) vmovhpd(xmm0, mem(rdx, rax, 1)) // store ( gamma43..gamma53 ) //lea(mem(rdx, rsi, 8), rdx) // rdx += 8*cs_c label(.SDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_sgemmsup_rv_haswell_asm_5x12 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) //lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored prefetching on c lea(mem(rcx, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 7*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 7*8)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 7*8)) // prefetch c + 3*rs_c prefetch(0, mem(rdx, rdi, 1, 7*8)) // prefetch c + 4*rs_c jmp(.SPOSTPFETCH) // jump to end of prefetching c label(.SCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) lea(mem(rsi, rsi, 2), rbp) // rbp = 3*cs_c; prefetch(0, mem(rcx, 4*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 4*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 4*8)) // prefetch c + 2*cs_c prefetch(0, mem(rcx, rbp, 1, 4*8)) // prefetch c + 3*cs_c prefetch(0, mem(rcx, rsi, 4, 4*8)) // prefetch c + 4*cs_c lea(mem(rcx, rsi, 4), rdx) // rdx = c + 4*cs_c; prefetch(0, mem(rdx, rsi, 1, 4*8)) // prefetch c + 5*cs_c prefetch(0, mem(rdx, rsi, 2, 4*8)) // prefetch c + 6*cs_c prefetch(0, mem(rdx, rbp, 1, 4*8)) // prefetch c + 7*cs_c prefetch(0, mem(rdx, rsi, 4, 4*8)) // prefetch c + 8*cs_c lea(mem(rcx, rsi, 8), rdx) // rdx = c + 8*cs_c; prefetch(0, mem(rdx, rsi, 1, 4*8)) // prefetch c + 9*cs_c prefetch(0, mem(rdx, rsi, 2, 4*8)) // prefetch c + 10*cs_c prefetch(0, mem(rdx, rbp, 1, 4*8)) // prefetch c + 11*cs_c label(.SPOSTPFETCH) // done prefetching c #if 1 lea(mem(rax, r9, 8), rdx) // lea(mem(rdx, r9, 8), rdx) // rdx = a + 16*cs_a; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(rdx, 4*8)) #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, r9, 1, 4*8)) #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(rdx, r9, 2, 4*8)) #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) // ---------------------------------- iteration 3 #if 1 lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP #if 0 prefetch(0, mem(rdx, 5*8)) add(r9, rdx) #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), ymm0) // load alpha and duplicate vbroadcastss(mem(rbx), ymm3) // load beta and duplicate vmulps(ymm0, ymm4, ymm4) // scale by alpha vmulps(xmm0, xmm5, xmm5) vmulps(ymm0, ymm6, ymm6) vmulps(xmm0, xmm7, xmm7) vmulps(ymm0, ymm8, ymm8) vmulps(xmm0, xmm9, xmm9) vmulps(ymm0, ymm10, ymm10) vmulps(xmm0, xmm11, xmm11) vmulps(ymm0, ymm12, ymm12) vmulps(xmm0, xmm13, xmm13) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; lea(mem(rsi, rsi, 4), rbx) // rbx = 5*cs_c; lea(mem(rax, rsi, 4), rbp) // rbp = 7*cs_c; // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm4) vmovups(ymm4, mem(rcx, 0*32)) vfmadd231ps(mem(rcx, 1*32), xmm3, xmm5) vmovups(xmm5, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm6) vmovups(ymm6, mem(rcx, 0*32)) vfmadd231ps(mem(rcx, 1*32), xmm3, xmm7) vmovups(xmm7, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm8) vmovups(ymm8, mem(rcx, 0*32)) vfmadd231ps(mem(rcx, 1*32), xmm3, xmm9) vmovups(xmm9, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm10) vmovups(ymm10, mem(rcx, 0*32)) vfmadd231ps(mem(rcx, 1*32), xmm3, xmm11) vmovups(xmm11, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm12) vmovups(ymm12, mem(rcx, 0*32)) vfmadd231ps(mem(rcx, 1*32), xmm3, xmm13) vmovups(xmm13, mem(rcx, 1*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORED) // begin I/O on columns 0-7 vunpcklps(ymm6, ymm4, ymm0) vunpcklps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx ), xmm3, xmm0) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm0, mem(rcx )) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx, rsi, 1), xmm3, xmm1) vfmadd231ps(mem(rcx, rbx, 1), xmm3, xmm2) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rbx, 1)) // store ( gamma05..gamma35 ) vunpckhps(ymm6, ymm4, ymm0) vunpckhps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx, rsi, 2), xmm3, xmm0) vfmadd231ps(mem(rcx, rax, 2), xmm3, xmm2) vmovups(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, rax, 2)) // store ( gamma06..gamma36 ) vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx, rax, 1), xmm3, xmm1) vfmadd231ps(mem(rcx, rbp, 1), xmm3, xmm2) vmovups(xmm1, mem(rcx, rax, 1)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, rbp, 1)) // store ( gamma07..gamma37 ) lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vmovups(ymm12, ymm0) vextractf128(imm(0x1), ymm0, xmm8) vpermilps(imm(0xe4), xmm0, xmm2) vpermilps(imm(0x39), xmm0, xmm4) vmovss(mem(rdx ), xmm1) vmovss(mem(rdx, rsi, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rdx )) // store ( gamma40 ) vmovss(xmm4, mem(rdx, rsi, 1)) // store ( gamma41 ) vpermilps(imm(0x4e), xmm0, xmm2) vpermilps(imm(0x93), xmm0, xmm4) vmovss(mem(rdx, rsi, 2), xmm1) vmovss(mem(rdx, rax, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rdx, rsi, 2)) // store ( gamma42 ) vmovss(xmm4, mem(rdx, rax, 1)) // store ( gamma43 ) vpermilps(imm(0xe4), xmm8, xmm2) vpermilps(imm(0x39), xmm8, xmm4) vmovss(mem(rdx, rsi, 4), xmm1) vmovss(mem(rdx, rbx, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rdx, rsi, 4)) // store ( gamma44 ) vmovss(xmm4, mem(rdx, rbx, 1)) // store ( gamma45 ) vpermilps(imm(0x4e), xmm8, xmm2) vpermilps(imm(0x93), xmm8, xmm4) vmovss(mem(rdx, rax, 2), xmm1) vmovss(mem(rdx, rbp, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rdx, rax, 2)) // store ( gamma46 ) vmovss(xmm4, mem(rdx, rbp, 1)) // store ( gamma47 ) lea(mem(rdx, rsi, 8), rdx) // rdx += 8*cs_c // begin I/O on columns 8-11 vunpcklps(ymm7, ymm5, ymm0) vunpcklps(ymm11, ymm9, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vfmadd231ps(mem(rcx ), xmm3, xmm0) vmovups(xmm0, mem(rcx )) // store ( gamma00..gamma30 ) vfmadd231ps(mem(rcx, rsi, 1), xmm3, xmm1) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) vunpckhps(ymm7, ymm5, ymm0) vunpckhps(ymm11, ymm9, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vfmadd231ps(mem(rcx, rsi, 2), xmm3, xmm0) vmovups(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma32 ) vfmadd231ps(mem(rcx, rax, 1), xmm3, xmm1) vmovups(xmm1, mem(rcx, rax, 1)) // store ( gamma03..gamma33 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vmovups(ymm13, ymm0) vpermilps(imm(0xe4), xmm0, xmm2) vpermilps(imm(0x39), xmm0, xmm4) vmovss(mem(rdx ), xmm1) vmovss(mem(rdx, rsi, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rdx )) // store ( gamma40 ) vmovss(xmm4, mem(rdx, rsi, 1)) // store ( gamma41 ) vpermilps(imm(0x4e), xmm0, xmm2) vpermilps(imm(0x93), xmm0, xmm4) vmovss(mem(rdx, rsi, 2), xmm1) vmovss(mem(rdx, rax, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rdx, rsi, 2)) // store ( gamma42 ) vmovss(xmm4, mem(rdx, rax, 1)) // store ( gamma43 ) //lea(mem(rdx, rsi, 8), rdx) // rdx += 8*cs_c jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovups(ymm4, mem(rcx, 0*32)) vmovups(xmm5, mem(rcx, 1*32)) add(rdi, rcx) vmovups(ymm6, mem(rcx, 0*32)) vmovups(xmm7, mem(rcx, 1*32)) add(rdi, rcx) vmovups(ymm8, mem(rcx, 0*32)) vmovups(xmm9, mem(rcx, 1*32)) add(rdi, rcx) vmovups(ymm10, mem(rcx, 0*32)) vmovups(xmm11, mem(rcx, 1*32)) add(rdi, rcx) vmovups(ymm12, mem(rcx, 0*32)) vmovups(xmm13, mem(rcx, 1*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) // begin I/O on columns 0-7 vunpcklps(ymm6, ymm4, ymm0) vunpcklps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx )) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rbx, 1)) // store ( gamma05..gamma35 ) vunpckhps(ymm6, ymm4, ymm0) vunpckhps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, rax, 2)) // store ( gamma06..gamma36 ) vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx, rax, 1)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, rbp, 1)) // store ( gamma07..gamma37 ) lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vmovups(ymm12, ymm0) vextractf128(imm(0x1), ymm0, xmm8) vpermilps(imm(0xe4), xmm0, xmm2) vpermilps(imm(0x39), xmm0, xmm4) vmovss(xmm2, mem(rdx )) // store ( gamma40 ) vmovss(xmm4, mem(rdx, rsi, 1)) // store ( gamma41 ) vpermilps(imm(0x4e), xmm0, xmm2) vpermilps(imm(0x93), xmm0, xmm4) vmovss(xmm2, mem(rdx, rsi, 2)) // store ( gamma42 ) vmovss(xmm4, mem(rdx, rax, 1)) // store ( gamma43 ) vpermilps(imm(0xe4), xmm8, xmm2) vpermilps(imm(0x39), xmm8, xmm4) vmovss(xmm2, mem(rdx, rsi, 4)) // store ( gamma44 ) vmovss(xmm4, mem(rdx, rbx, 1)) // store ( gamma45 ) vpermilps(imm(0x4e), xmm8, xmm2) vpermilps(imm(0x93), xmm8, xmm4) vmovss(xmm2, mem(rdx, rax, 2)) // store ( gamma46 ) vmovss(xmm4, mem(rdx, rbp, 1)) // store ( gamma47 ) lea(mem(rdx, rsi, 8), rdx) // rdx += 8*cs_c // begin I/O on columns 8-11 vunpcklps(ymm7, ymm5, ymm0) vunpcklps(ymm11, ymm9, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vmovups(xmm0, mem(rcx )) // store ( gamma00..gamma30 ) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) vunpckhps(ymm7, ymm5, ymm0) vunpckhps(ymm11, ymm9, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vmovups(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma32 ) vmovups(xmm1, mem(rcx, rax, 1)) // store ( gamma03..gamma33 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vmovups(ymm13, ymm0) vpermilps(imm(0xe4), xmm0, xmm2) vpermilps(imm(0x39), xmm0, xmm4) vmovss(xmm2, mem(rdx )) // store ( gamma40 ) vmovss(xmm4, mem(rdx, rsi, 1)) // store ( gamma41 ) vpermilps(imm(0x4e), xmm0, xmm2) vpermilps(imm(0x93), xmm0, xmm4) vmovss(xmm2, mem(rdx, rsi, 2)) // store ( gamma42 ) vmovss(xmm4, mem(rdx, rax, 1)) // store ( gamma43 ) //lea(mem(rdx, rsi, 8), rdx) // rdx += 8*cs_c label(.SDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_sgemmsup_rv_haswell_asm_4x12 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) //lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored prefetching on c lea(mem(rcx, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 7*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 7*8)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 7*8)) // prefetch c + 3*rs_c jmp(.SPOSTPFETCH) // jump to end of prefetching c label(.SCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) lea(mem(rsi, rsi, 2), rbp) // rbp = 3*cs_c; prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 3*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 3*8)) // prefetch c + 2*cs_c prefetch(0, mem(rcx, rbp, 1, 3*8)) // prefetch c + 3*cs_c prefetch(0, mem(rcx, rsi, 4, 3*8)) // prefetch c + 4*cs_c lea(mem(rcx, rsi, 4), rdx) // rdx = c + 4*cs_c; prefetch(0, mem(rdx, rsi, 1, 3*8)) // prefetch c + 5*cs_c prefetch(0, mem(rdx, rsi, 2, 3*8)) // prefetch c + 6*cs_c prefetch(0, mem(rdx, rbp, 1, 3*8)) // prefetch c + 7*cs_c prefetch(0, mem(rdx, rsi, 4, 3*8)) // prefetch c + 8*cs_c lea(mem(rcx, rsi, 8), rdx) // rdx = c + 8*cs_c; prefetch(0, mem(rdx, rsi, 1, 3*8)) // prefetch c + 9*cs_c prefetch(0, mem(rdx, rsi, 2, 3*8)) // prefetch c + 10*cs_c prefetch(0, mem(rdx, rbp, 1, 3*8)) // prefetch c + 11*cs_c label(.SPOSTPFETCH) // done prefetching c #if 1 lea(mem(rax, r9, 8), rdx) // lea(mem(rdx, r9, 8), rdx) // rdx = a + 16*cs_a; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(rdx, 4*8)) #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, r9, 1, 4*8)) #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(rdx, r9, 2, 4*8)) #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) // ---------------------------------- iteration 3 #if 1 lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP #if 0 prefetch(0, mem(rdx, 5*8)) add(r9, rdx) #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), ymm0) // load alpha and duplicate vbroadcastss(mem(rbx), ymm3) // load beta and duplicate vmulps(ymm0, ymm4, ymm4) // scale by alpha vmulps(xmm0, xmm5, xmm5) vmulps(ymm0, ymm6, ymm6) vmulps(xmm0, xmm7, xmm7) vmulps(ymm0, ymm8, ymm8) vmulps(xmm0, xmm9, xmm9) vmulps(ymm0, ymm10, ymm10) vmulps(xmm0, xmm11, xmm11) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; //lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; lea(mem(rsi, rsi, 4), rbx) // rbx = 5*cs_c; lea(mem(rax, rsi, 4), rbp) // rbp = 7*cs_c; // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm4) vmovups(ymm4, mem(rcx, 0*32)) vfmadd231ps(mem(rcx, 1*32), xmm3, xmm5) vmovups(xmm5, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm6) vmovups(ymm6, mem(rcx, 0*32)) vfmadd231ps(mem(rcx, 1*32), xmm3, xmm7) vmovups(xmm7, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm8) vmovups(ymm8, mem(rcx, 0*32)) vfmadd231ps(mem(rcx, 1*32), xmm3, xmm9) vmovups(xmm9, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm10) vmovups(ymm10, mem(rcx, 0*32)) vfmadd231ps(mem(rcx, 1*32), xmm3, xmm11) vmovups(xmm11, mem(rcx, 1*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORED) // begin I/O on columns 0-7 vunpcklps(ymm6, ymm4, ymm0) vunpcklps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx ), xmm3, xmm0) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm0, mem(rcx )) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx, rsi, 1), xmm3, xmm1) vfmadd231ps(mem(rcx, rbx, 1), xmm3, xmm2) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rbx, 1)) // store ( gamma05..gamma35 ) vunpckhps(ymm6, ymm4, ymm0) vunpckhps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx, rsi, 2), xmm3, xmm0) vfmadd231ps(mem(rcx, rax, 2), xmm3, xmm2) vmovups(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, rax, 2)) // store ( gamma06..gamma36 ) vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx, rax, 1), xmm3, xmm1) vfmadd231ps(mem(rcx, rbp, 1), xmm3, xmm2) vmovups(xmm1, mem(rcx, rax, 1)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, rbp, 1)) // store ( gamma07..gamma37 ) lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c // begin I/O on columns 8-11 vunpcklps(ymm7, ymm5, ymm0) vunpcklps(ymm11, ymm9, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vfmadd231ps(mem(rcx ), xmm3, xmm0) vmovups(xmm0, mem(rcx )) // store ( gamma00..gamma30 ) vfmadd231ps(mem(rcx, rsi, 1), xmm3, xmm1) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) vunpckhps(ymm7, ymm5, ymm0) vunpckhps(ymm11, ymm9, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vfmadd231ps(mem(rcx, rsi, 2), xmm3, xmm0) vmovups(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma32 ) vfmadd231ps(mem(rcx, rax, 1), xmm3, xmm1) vmovups(xmm1, mem(rcx, rax, 1)) // store ( gamma03..gamma33 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (8*rs_c) == 8. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovups(ymm4, mem(rcx, 0*32)) vmovups(xmm5, mem(rcx, 1*32)) add(rdi, rcx) vmovups(ymm6, mem(rcx, 0*32)) vmovups(xmm7, mem(rcx, 1*32)) add(rdi, rcx) vmovups(ymm8, mem(rcx, 0*32)) vmovups(xmm9, mem(rcx, 1*32)) add(rdi, rcx) vmovups(ymm10, mem(rcx, 0*32)) vmovups(xmm11, mem(rcx, 1*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) // begin I/O on columns 0-7 vunpcklps(ymm6, ymm4, ymm0) vunpcklps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx )) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rbx, 1)) // store ( gamma05..gamma35 ) vunpckhps(ymm6, ymm4, ymm0) vunpckhps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, rax, 2)) // store ( gamma06..gamma36 ) vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx, rax, 1)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, rbp, 1)) // store ( gamma07..gamma37 ) lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c // begin I/O on columns 8-11 vunpcklps(ymm7, ymm5, ymm0) vunpcklps(ymm11, ymm9, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vmovups(xmm0, mem(rcx )) // store ( gamma00..gamma30 ) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) vunpckhps(ymm7, ymm5, ymm0) vunpckhps(ymm11, ymm9, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vmovups(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma32 ) vmovups(xmm1, mem(rcx, rax, 1)) // store ( gamma03..gamma33 ) //lea(mem(rcx, rsi, 4), rcx) label(.SDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_sgemmsup_rv_haswell_asm_3x12 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) //lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored prefetching on c //lea(mem(rcx, rdi, 2), rdx) // //lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 7*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 7*8)) // prefetch c + 2*rs_c jmp(.SPOSTPFETCH) // jump to end of prefetching c label(.SCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) lea(mem(rsi, rsi, 2), rbp) // rbp = 3*cs_c; prefetch(0, mem(rcx, 2*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 2*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 2*8)) // prefetch c + 2*cs_c prefetch(0, mem(rcx, rbp, 1, 2*8)) // prefetch c + 3*cs_c prefetch(0, mem(rcx, rsi, 4, 2*8)) // prefetch c + 4*cs_c lea(mem(rcx, rsi, 4), rdx) // rdx = c + 4*cs_c; prefetch(0, mem(rdx, rsi, 1, 2*8)) // prefetch c + 5*cs_c prefetch(0, mem(rdx, rsi, 2, 2*8)) // prefetch c + 6*cs_c prefetch(0, mem(rdx, rbp, 1, 2*8)) // prefetch c + 7*cs_c prefetch(0, mem(rdx, rsi, 4, 2*8)) // prefetch c + 8*cs_c lea(mem(rcx, rsi, 8), rdx) // rdx = c + 8*cs_c; prefetch(0, mem(rdx, rsi, 1, 2*8)) // prefetch c + 9*cs_c prefetch(0, mem(rdx, rsi, 2, 2*8)) // prefetch c + 10*cs_c prefetch(0, mem(rdx, rbp, 1, 2*8)) // prefetch c + 11*cs_c label(.SPOSTPFETCH) // done prefetching c #if 1 lea(mem(rax, r9, 8), rdx) // lea(mem(rdx, r9, 8), rdx) // rdx = a + 16*cs_a; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(rdx, 4*8)) #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, r9, 1, 4*8)) #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(rdx, r9, 2, 4*8)) #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) // ---------------------------------- iteration 3 #if 1 lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP #if 0 prefetch(0, mem(rdx, 5*8)) add(r9, rdx) #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), ymm0) // load alpha and duplicate vbroadcastss(mem(rbx), ymm3) // load beta and duplicate vmulps(ymm0, ymm4, ymm4) // scale by alpha vmulps(xmm0, xmm5, xmm5) vmulps(ymm0, ymm6, ymm6) vmulps(xmm0, xmm7, xmm7) vmulps(ymm0, ymm8, ymm8) vmulps(xmm0, xmm9, xmm9) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; lea(mem(rcx, rdi, 2), rdx) // load address of c + 2*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; lea(mem(rsi, rsi, 4), rbx) // rbx = 5*cs_c; lea(mem(rax, rsi, 4), rbp) // rbp = 7*cs_c; // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm4) vmovups(ymm4, mem(rcx, 0*32)) vfmadd231ps(mem(rcx, 1*32), xmm3, xmm5) vmovups(xmm5, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm6) vmovups(ymm6, mem(rcx, 0*32)) vfmadd231ps(mem(rcx, 1*32), xmm3, xmm7) vmovups(xmm7, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm8) vmovups(ymm8, mem(rcx, 0*32)) vfmadd231ps(mem(rcx, 1*32), xmm3, xmm9) vmovups(xmm9, mem(rcx, 1*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORED) // begin I/O on columns 0-7 vunpcklps(ymm6, ymm4, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(mem(rcx ), xmm1, xmm1) vmovhpd(mem(rcx, rsi, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(rcx )) // store ( gamma00..gamma10 ) vmovhpd(xmm0, mem(rcx, rsi, 1)) // store ( gamma01..gamma11 ) vmovlpd(mem(rcx, rsi, 4), xmm1, xmm1) vmovhpd(mem(rcx, rbx, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm2) vmovlpd(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma14 ) vmovhpd(xmm2, mem(rcx, rbx, 1)) // store ( gamma05..gamma15 ) vunpckhps(ymm6, ymm4, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(mem(rcx, rsi, 2), xmm1, xmm1) vmovhpd(mem(rcx, rax, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma12 ) vmovhpd(xmm0, mem(rcx, rax, 1)) // store ( gamma03..gamma13 ) vmovlpd(mem(rcx, rax, 2), xmm1, xmm1) vmovhpd(mem(rcx, rbp, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm2) vmovlpd(xmm2, mem(rcx, rax, 2)) // store ( gamma06..gamma16 ) vmovhpd(xmm2, mem(rcx, rbp, 1)) // store ( gamma07..gamma17 ) lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vmovups(ymm8, ymm0) vextractf128(imm(0x1), ymm0, xmm8) vpermilps(imm(0xe4), xmm0, xmm2) vpermilps(imm(0x39), xmm0, xmm4) vmovss(mem(rdx ), xmm1) vmovss(mem(rdx, rsi, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rdx )) // store ( gamma40 ) vmovss(xmm4, mem(rdx, rsi, 1)) // store ( gamma41 ) vpermilps(imm(0x4e), xmm0, xmm2) vpermilps(imm(0x93), xmm0, xmm4) vmovss(mem(rdx, rsi, 2), xmm1) vmovss(mem(rdx, rax, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rdx, rsi, 2)) // store ( gamma42 ) vmovss(xmm4, mem(rdx, rax, 1)) // store ( gamma43 ) vpermilps(imm(0xe4), xmm8, xmm2) vpermilps(imm(0x39), xmm8, xmm4) vmovss(mem(rdx, rsi, 4), xmm1) vmovss(mem(rdx, rbx, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rdx, rsi, 4)) // store ( gamma44 ) vmovss(xmm4, mem(rdx, rbx, 1)) // store ( gamma45 ) vpermilps(imm(0x4e), xmm8, xmm2) vpermilps(imm(0x93), xmm8, xmm4) vmovss(mem(rdx, rax, 2), xmm1) vmovss(mem(rdx, rbp, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rdx, rax, 2)) // store ( gamma46 ) vmovss(xmm4, mem(rdx, rbp, 1)) // store ( gamma47 ) lea(mem(rdx, rsi, 8), rdx) // rdx += 8*cs_c // begin I/O on columns 8-11 vunpcklps(ymm7, ymm5, ymm0) vmovlpd(mem(rcx ), xmm1, xmm1) vmovhpd(mem(rcx, rsi, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(rcx )) // store ( gamma00..gamma10 ) vmovhpd(xmm0, mem(rcx, rsi, 1)) // store ( gamma01..gamma11 ) vunpckhps(ymm7, ymm5, ymm0) vmovlpd(mem(rcx, rsi, 2), xmm1, xmm1) vmovhpd(mem(rcx, rax, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma12 ) vmovhpd(xmm0, mem(rcx, rax, 1)) // store ( gamma03..gamma13 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vmovups(ymm9, ymm0) vpermilps(imm(0xe4), xmm0, xmm2) vpermilps(imm(0x39), xmm0, xmm4) vmovss(mem(rdx ), xmm1) vmovss(mem(rdx, rsi, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rdx )) // store ( gamma40 ) vmovss(xmm4, mem(rdx, rsi, 1)) // store ( gamma41 ) vpermilps(imm(0x4e), xmm0, xmm2) vpermilps(imm(0x93), xmm0, xmm4) vmovss(mem(rdx, rsi, 2), xmm1) vmovss(mem(rdx, rax, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rdx, rsi, 2)) // store ( gamma42 ) vmovss(xmm4, mem(rdx, rax, 1)) // store ( gamma43 ) //lea(mem(rdx, rsi, 8), rdx) // rdx += 8*cs_c jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (8*rs_c) == 8. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovups(ymm4, mem(rcx, 0*32)) vmovups(xmm5, mem(rcx, 1*32)) add(rdi, rcx) vmovups(ymm6, mem(rcx, 0*32)) vmovups(xmm7, mem(rcx, 1*32)) add(rdi, rcx) vmovups(ymm8, mem(rcx, 0*32)) vmovups(xmm9, mem(rcx, 1*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) // begin I/O on columns 0-7 vunpcklps(ymm6, ymm4, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(xmm0, mem(rcx )) // store ( gamma00..gamma10 ) vmovhpd(xmm0, mem(rcx, rsi, 1)) // store ( gamma01..gamma11 ) vmovlpd(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma14 ) vmovhpd(xmm2, mem(rcx, rbx, 1)) // store ( gamma05..gamma15 ) vunpckhps(ymm6, ymm4, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma12 ) vmovhpd(xmm0, mem(rcx, rax, 1)) // store ( gamma03..gamma13 ) vmovlpd(xmm2, mem(rcx, rax, 2)) // store ( gamma06..gamma16 ) vmovhpd(xmm2, mem(rcx, rbp, 1)) // store ( gamma07..gamma17 ) lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vmovups(ymm8, ymm0) vextractf128(imm(0x1), ymm0, xmm8) vpermilps(imm(0xe4), xmm0, xmm2) vpermilps(imm(0x39), xmm0, xmm4) vmovss(xmm2, mem(rdx )) // store ( gamma40 ) vmovss(xmm4, mem(rdx, rsi, 1)) // store ( gamma41 ) vpermilps(imm(0x4e), xmm0, xmm2) vpermilps(imm(0x93), xmm0, xmm4) vmovss(xmm2, mem(rdx, rsi, 2)) // store ( gamma42 ) vmovss(xmm4, mem(rdx, rax, 1)) // store ( gamma43 ) vpermilps(imm(0xe4), xmm8, xmm2) vpermilps(imm(0x39), xmm8, xmm4) vmovss(xmm2, mem(rdx, rsi, 4)) // store ( gamma44 ) vmovss(xmm4, mem(rdx, rbx, 1)) // store ( gamma45 ) vpermilps(imm(0x4e), xmm8, xmm2) vpermilps(imm(0x93), xmm8, xmm4) vmovss(xmm2, mem(rdx, rax, 2)) // store ( gamma46 ) vmovss(xmm4, mem(rdx, rbp, 1)) // store ( gamma47 ) lea(mem(rdx, rsi, 8), rdx) // rdx += 8*cs_c // begin I/O on columns 8-11 vunpcklps(ymm7, ymm5, ymm0) vmovlpd(xmm0, mem(rcx )) // store ( gamma00..gamma10 ) vmovhpd(xmm0, mem(rcx, rsi, 1)) // store ( gamma01..gamma11 ) vunpckhps(ymm7, ymm5, ymm0) vmovlpd(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma12 ) vmovhpd(xmm0, mem(rcx, rax, 1)) // store ( gamma03..gamma13 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vmovups(ymm9, ymm0) vpermilps(imm(0xe4), xmm0, xmm2) vpermilps(imm(0x39), xmm0, xmm4) vmovss(xmm2, mem(rdx )) // store ( gamma40 ) vmovss(xmm4, mem(rdx, rsi, 1)) // store ( gamma41 ) vpermilps(imm(0x4e), xmm0, xmm2) vpermilps(imm(0x93), xmm0, xmm4) vmovss(xmm2, mem(rdx, rsi, 2)) // store ( gamma42 ) vmovss(xmm4, mem(rdx, rax, 1)) // store ( gamma43 ) //lea(mem(rcx, rsi, 4), rcx) label(.SDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_sgemmsup_rv_haswell_asm_2x12 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) //lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored prefetching on c //lea(mem(rcx, rdi, 2), rdx) // //lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 7*8)) // prefetch c + 1*rs_c jmp(.SPOSTPFETCH) // jump to end of prefetching c label(.SCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) lea(mem(rsi, rsi, 2), rbp) // rbp = 3*cs_c; prefetch(0, mem(rcx, 1*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 1*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 1*8)) // prefetch c + 2*cs_c prefetch(0, mem(rcx, rbp, 1, 1*8)) // prefetch c + 3*cs_c prefetch(0, mem(rcx, rsi, 4, 1*8)) // prefetch c + 4*cs_c lea(mem(rcx, rsi, 4), rdx) // rdx = c + 4*cs_c; prefetch(0, mem(rdx, rsi, 1, 1*8)) // prefetch c + 5*cs_c prefetch(0, mem(rdx, rsi, 2, 1*8)) // prefetch c + 6*cs_c prefetch(0, mem(rdx, rbp, 1, 1*8)) // prefetch c + 7*cs_c prefetch(0, mem(rdx, rsi, 4, 1*8)) // prefetch c + 8*cs_c lea(mem(rcx, rsi, 8), rdx) // rdx = c + 8*cs_c; prefetch(0, mem(rdx, rsi, 1, 1*8)) // prefetch c + 9*cs_c prefetch(0, mem(rdx, rsi, 2, 1*8)) // prefetch c + 10*cs_c prefetch(0, mem(rdx, rbp, 1, 1*8)) // prefetch c + 11*cs_c label(.SPOSTPFETCH) // done prefetching c #if 1 lea(mem(rax, r9, 8), rdx) // lea(mem(rdx, r9, 8), rdx) // rdx = a + 16*cs_a; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(rdx, 4*8)) #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, r9, 1, 4*8)) #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(rdx, r9, 2, 4*8)) #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) // ---------------------------------- iteration 3 #if 1 lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP #if 0 prefetch(0, mem(rdx, 5*8)) add(r9, rdx) #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), ymm0) // load alpha and duplicate vbroadcastss(mem(rbx), ymm3) // load beta and duplicate vmulps(ymm0, ymm4, ymm4) // scale by alpha vmulps(xmm0, xmm5, xmm5) vmulps(ymm0, ymm6, ymm6) vmulps(xmm0, xmm7, xmm7) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; //lea(mem(rcx, rdi, 2), rdx) // load address of c + 2*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; lea(mem(rsi, rsi, 4), rbx) // rbx = 5*cs_c; lea(mem(rax, rsi, 4), rbp) // rbp = 7*cs_c; // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm4) vmovups(ymm4, mem(rcx, 0*32)) vfmadd231ps(mem(rcx, 1*32), xmm3, xmm5) vmovups(xmm5, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm6) vmovups(ymm6, mem(rcx, 0*32)) vfmadd231ps(mem(rcx, 1*32), xmm3, xmm7) vmovups(xmm7, mem(rcx, 1*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORED) // begin I/O on columns 0-7 vunpcklps(ymm6, ymm4, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(mem(rcx ), xmm1, xmm1) vmovhpd(mem(rcx, rsi, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(rcx )) // store ( gamma00..gamma10 ) vmovhpd(xmm0, mem(rcx, rsi, 1)) // store ( gamma01..gamma11 ) vmovlpd(mem(rcx, rsi, 4), xmm1, xmm1) vmovhpd(mem(rcx, rbx, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm2) vmovlpd(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma14 ) vmovhpd(xmm2, mem(rcx, rbx, 1)) // store ( gamma05..gamma15 ) vunpckhps(ymm6, ymm4, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(mem(rcx, rsi, 2), xmm1, xmm1) vmovhpd(mem(rcx, rax, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma12 ) vmovhpd(xmm0, mem(rcx, rax, 1)) // store ( gamma03..gamma13 ) vmovlpd(mem(rcx, rax, 2), xmm1, xmm1) vmovhpd(mem(rcx, rbp, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm2) vmovlpd(xmm2, mem(rcx, rax, 2)) // store ( gamma06..gamma16 ) vmovhpd(xmm2, mem(rcx, rbp, 1)) // store ( gamma07..gamma17 ) lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c // begin I/O on columns 8-11 vunpcklps(ymm7, ymm5, ymm0) vmovlpd(mem(rcx ), xmm1, xmm1) vmovhpd(mem(rcx, rsi, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(rcx )) // store ( gamma00..gamma10 ) vmovhpd(xmm0, mem(rcx, rsi, 1)) // store ( gamma01..gamma11 ) vunpckhps(ymm7, ymm5, ymm0) vmovlpd(mem(rcx, rsi, 2), xmm1, xmm1) vmovhpd(mem(rcx, rax, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma12 ) vmovhpd(xmm0, mem(rcx, rax, 1)) // store ( gamma03..gamma13 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (8*rs_c) == 8. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovups(ymm4, mem(rcx, 0*32)) vmovups(xmm5, mem(rcx, 1*32)) add(rdi, rcx) vmovups(ymm6, mem(rcx, 0*32)) vmovups(xmm7, mem(rcx, 1*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) // begin I/O on columns 0-7 vunpcklps(ymm6, ymm4, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(xmm0, mem(rcx )) // store ( gamma00..gamma10 ) vmovhpd(xmm0, mem(rcx, rsi, 1)) // store ( gamma01..gamma11 ) vmovlpd(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma14 ) vmovhpd(xmm2, mem(rcx, rbx, 1)) // store ( gamma05..gamma15 ) vunpckhps(ymm6, ymm4, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma12 ) vmovhpd(xmm0, mem(rcx, rax, 1)) // store ( gamma03..gamma13 ) vmovlpd(xmm2, mem(rcx, rax, 2)) // store ( gamma06..gamma16 ) vmovhpd(xmm2, mem(rcx, rbp, 1)) // store ( gamma07..gamma17 ) lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c // begin I/O on columns 8-11 vunpcklps(ymm7, ymm5, ymm0) vmovlpd(xmm0, mem(rcx )) // store ( gamma00..gamma10 ) vmovhpd(xmm0, mem(rcx, rsi, 1)) // store ( gamma01..gamma11 ) vunpckhps(ymm7, ymm5, ymm0) vmovlpd(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma12 ) vmovhpd(xmm0, mem(rcx, rax, 1)) // store ( gamma03..gamma13 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c label(.SDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_sgemmsup_rv_haswell_asm_1x12 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) //lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored prefetching on c //lea(mem(rcx, rdi, 2), rdx) // //lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c jmp(.SPOSTPFETCH) // jump to end of prefetching c label(.SCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) lea(mem(rsi, rsi, 2), rbp) // rbp = 3*cs_c; prefetch(0, mem(rcx, 0*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 0*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 0*8)) // prefetch c + 2*cs_c prefetch(0, mem(rcx, rbp, 1, 0*8)) // prefetch c + 3*cs_c prefetch(0, mem(rcx, rsi, 4, 0*8)) // prefetch c + 4*cs_c lea(mem(rcx, rsi, 4), rdx) // rdx = c + 4*cs_c; prefetch(0, mem(rdx, rsi, 1, 0*8)) // prefetch c + 5*cs_c prefetch(0, mem(rdx, rsi, 2, 0*8)) // prefetch c + 6*cs_c prefetch(0, mem(rdx, rbp, 1, 0*8)) // prefetch c + 7*cs_c prefetch(0, mem(rdx, rsi, 4, 0*8)) // prefetch c + 8*cs_c lea(mem(rcx, rsi, 8), rdx) // rdx = c + 8*cs_c; prefetch(0, mem(rdx, rsi, 1, 0*8)) // prefetch c + 9*cs_c prefetch(0, mem(rdx, rsi, 2, 0*8)) // prefetch c + 10*cs_c prefetch(0, mem(rdx, rbp, 1, 0*8)) // prefetch c + 11*cs_c label(.SPOSTPFETCH) // done prefetching c #if 1 lea(mem(rax, r9, 8), rdx) // lea(mem(rdx, r9, 8), rdx) // rdx = a + 16*cs_a; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(rdx, 4*8)) #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, r9, 1, 4*8)) #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(rdx, r9, 2, 4*8)) #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) // ---------------------------------- iteration 3 #if 1 lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP #if 0 prefetch(0, mem(rdx, 5*8)) add(r9, rdx) #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), xmm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), ymm0) // load alpha and duplicate vbroadcastss(mem(rbx), ymm3) // load beta and duplicate vmulps(ymm0, ymm4, ymm4) // scale by alpha vmulps(xmm0, xmm5, xmm5) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; //lea(mem(rcx, rdi, 2), rdx) // load address of c + 2*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; lea(mem(rsi, rsi, 4), rbx) // rbx = 5*cs_c; lea(mem(rax, rsi, 4), rbp) // rbp = 7*cs_c; // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm4) vmovups(ymm4, mem(rcx, 0*32)) vfmadd231ps(mem(rcx, 1*32), xmm3, xmm5) vmovups(xmm5, mem(rcx, 1*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORED) // begin I/O on columns 0-7 vmovups(ymm4, ymm0) vextractf128(imm(0x1), ymm0, xmm8) vpermilps(imm(0xe4), xmm0, xmm2) vpermilps(imm(0x39), xmm0, xmm4) vmovss(mem(rcx ), xmm1) vmovss(mem(rcx, rsi, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rcx )) // store ( gamma40 ) vmovss(xmm4, mem(rcx, rsi, 1)) // store ( gamma41 ) vpermilps(imm(0x4e), xmm0, xmm2) vpermilps(imm(0x93), xmm0, xmm4) vmovss(mem(rcx, rsi, 2), xmm1) vmovss(mem(rcx, rax, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rcx, rsi, 2)) // store ( gamma42 ) vmovss(xmm4, mem(rcx, rax, 1)) // store ( gamma43 ) vpermilps(imm(0xe4), xmm8, xmm2) vpermilps(imm(0x39), xmm8, xmm4) vmovss(mem(rcx, rsi, 4), xmm1) vmovss(mem(rcx, rbx, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rcx, rsi, 4)) // store ( gamma44 ) vmovss(xmm4, mem(rcx, rbx, 1)) // store ( gamma45 ) vpermilps(imm(0x4e), xmm8, xmm2) vpermilps(imm(0x93), xmm8, xmm4) vmovss(mem(rcx, rax, 2), xmm1) vmovss(mem(rcx, rbp, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rcx, rax, 2)) // store ( gamma46 ) vmovss(xmm4, mem(rcx, rbp, 1)) // store ( gamma47 ) lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c // begin I/O on columns 8-11 vmovups(ymm5, ymm0) vpermilps(imm(0xe4), xmm0, xmm2) vpermilps(imm(0x39), xmm0, xmm4) vmovss(mem(rcx ), xmm1) vmovss(mem(rcx, rsi, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rcx )) // store ( gamma40 ) vmovss(xmm4, mem(rcx, rsi, 1)) // store ( gamma41 ) vpermilps(imm(0x4e), xmm0, xmm2) vpermilps(imm(0x93), xmm0, xmm4) vmovss(mem(rcx, rsi, 2), xmm1) vmovss(mem(rcx, rax, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rcx, rsi, 2)) // store ( gamma42 ) vmovss(xmm4, mem(rcx, rax, 1)) // store ( gamma43 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (8*rs_c) == 8. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovups(ymm4, mem(rcx, 0*32)) vmovups(xmm5, mem(rcx, 1*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) // begin I/O on columns 0-7 vmovups(ymm4, ymm0) vextractf128(imm(0x1), ymm0, xmm8) vpermilps(imm(0xe4), xmm0, xmm2) vpermilps(imm(0x39), xmm0, xmm4) vmovss(xmm2, mem(rcx )) // store ( gamma40 ) vmovss(xmm4, mem(rcx, rsi, 1)) // store ( gamma41 ) vpermilps(imm(0x4e), xmm0, xmm2) vpermilps(imm(0x93), xmm0, xmm4) vmovss(xmm2, mem(rcx, rsi, 2)) // store ( gamma42 ) vmovss(xmm4, mem(rcx, rax, 1)) // store ( gamma43 ) vpermilps(imm(0xe4), xmm8, xmm2) vpermilps(imm(0x39), xmm8, xmm4) vmovss(xmm2, mem(rcx, rsi, 4)) // store ( gamma44 ) vmovss(xmm4, mem(rcx, rbx, 1)) // store ( gamma45 ) vpermilps(imm(0x4e), xmm8, xmm2) vpermilps(imm(0x93), xmm8, xmm4) vmovss(xmm2, mem(rcx, rax, 2)) // store ( gamma46 ) vmovss(xmm4, mem(rcx, rbp, 1)) // store ( gamma47 ) lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c // begin I/O on columns 8-11 vmovups(ymm5, ymm0) vpermilps(imm(0xe4), xmm0, xmm2) vpermilps(imm(0x39), xmm0, xmm4) vmovss(xmm2, mem(rcx )) // store ( gamma40 ) vmovss(xmm4, mem(rcx, rsi, 1)) // store ( gamma41 ) vpermilps(imm(0x4e), xmm0, xmm2) vpermilps(imm(0x93), xmm0, xmm4) vmovss(xmm2, mem(rcx, rsi, 2)) // store ( gamma42 ) vmovss(xmm4, mem(rcx, rax, 1)) // store ( gamma43 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c label(.SDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } blis-0.9.0/kernels/haswell/3/sup/s6x16/bli_gemmsup_rv_haswell_asm_sMx16.c000066400000000000000000003501551422157504600261650ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define BLIS_ASM_SYNTAX_ATT #include "bli_x86_asm_macros.h" /* rrr: -------- ------ -------- -------- ------ -------- -------- += ------ ... -------- -------- ------ -------- -------- ------ : -------- ------ : rcr: -------- | | | | -------- -------- | | | | -------- -------- += | | | | ... -------- -------- | | | | -------- -------- | | | | : -------- | | | | : Assumptions: - B is row-stored; - A is row- or column-stored; - m0 and n0 are at most MR and NR, respectively. Therefore, this (r)ow-preferential kernel is well-suited for contiguous (v)ector loads on B and single-element broadcasts from A. NOTE: These kernels explicitly support column-oriented IO, implemented via an in-register transpose. And thus they also support the crr and ccr cases, though only crr is ever utilized (because ccr is handled by transposing the operation and executing rcr, which does not incur the cost of the in-register transpose). crr: | | | | | | | | ------ -------- | | | | | | | | ------ -------- | | | | | | | | += ------ ... -------- | | | | | | | | ------ -------- | | | | | | | | ------ : | | | | | | | | ------ : */ // Prototype reference microkernels. GEMMSUP_KER_PROT( float, s, gemmsup_r_haswell_ref ) // Define parameters and variables for edge case kernel map. #define NUM_MR 4 #define NUM_NR 6 #define FUNCPTR_T sgemmsup_ker_ft static dim_t mrs[NUM_MR] = { 6, 4, 2, 1 }; static dim_t nrs[NUM_NR] = { 16, 12, 8, 4, 2, 1 }; static FUNCPTR_T kmap[NUM_MR][NUM_NR] = { /* 16 12 8 4 2 1 */ /* 6 */ { bli_sgemmsup_rv_haswell_asm_6x16, bli_sgemmsup_rv_haswell_asm_6x12, bli_sgemmsup_rv_haswell_asm_6x8, bli_sgemmsup_rv_haswell_asm_6x4, bli_sgemmsup_rv_haswell_asm_6x2, bli_sgemmsup_r_haswell_ref_6x1 }, /* 4 */ { bli_sgemmsup_rv_haswell_asm_4x16, bli_sgemmsup_rv_haswell_asm_4x12, bli_sgemmsup_rv_haswell_asm_4x8, bli_sgemmsup_rv_haswell_asm_4x4, bli_sgemmsup_rv_haswell_asm_4x2, bli_sgemmsup_r_haswell_ref_4x1 }, /* 2 */ { bli_sgemmsup_rv_haswell_asm_2x16, bli_sgemmsup_rv_haswell_asm_2x12, bli_sgemmsup_rv_haswell_asm_2x8, bli_sgemmsup_rv_haswell_asm_2x4, bli_sgemmsup_rv_haswell_asm_2x2, bli_sgemmsup_r_haswell_ref_2x1 }, /* 1 */ { bli_sgemmsup_rv_haswell_asm_1x16, bli_sgemmsup_rv_haswell_asm_1x12, bli_sgemmsup_rv_haswell_asm_1x8, bli_sgemmsup_rv_haswell_asm_1x4, bli_sgemmsup_rv_haswell_asm_1x2, bli_sgemmsup_r_haswell_ref_1x1 } }; void bli_sgemmsup_rv_haswell_asm_6x16 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { #if 0 bli_sgemmsup_r_haswell_ref ( conja, conjb, m0, n0, k0, alpha, a, rs_a0, cs_a0, b, rs_b0, cs_b0, beta, c, rs_c0, cs_c0, data, cntx ); return; #endif // Use a reference kernel if this is an edge case in the m or n // dimensions. if ( m0 < 6 || n0 < 16 ) { #if 0 bli_sgemmsup_r_haswell_ref ( conja, conjb, m0, n0, k0, alpha, a, rs_a0, cs_a0, b, rs_b0, cs_b0, beta, c, rs_c0, cs_c0, data, cntx ); return; #endif dim_t n_left = n0; float* restrict cj = c; float* restrict bj = b; // Iterate across columns (corresponding to elements of nrs) until // n_left is zero. for ( dim_t j = 0; n_left != 0; ++j ) { const dim_t nr_cur = nrs[ j ]; // Once we find the value of nrs that is less than (or equal to) // n_left, we use the kernels in that column. if ( nr_cur <= n_left ) { dim_t m_left = m0; float* restrict cij = cj; float* restrict ai = a; // Iterate down the current column (corresponding to elements // of mrs) until m_left is zero. for ( dim_t i = 0; m_left != 0; ++i ) { const dim_t mr_cur = mrs[ i ]; // Once we find the value of mrs that is less than (or equal // to) m_left, we select that kernel. if ( mr_cur <= m_left ) { FUNCPTR_T ker_fp = kmap[i][j]; //printf( "executing %d x %d sup kernel.\n", (int)mr_cur, (int)nr_cur ); // Call the kernel using current mrs and nrs values. ker_fp ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); // Advance C and A pointers by the mrs and nrs we just // used, and decrement m_left. cij += mr_cur*rs_c0; ai += mr_cur*rs_a0; m_left -= mr_cur; } } // Advance C and B pointers by the mrs and nrs we just used, and // decrement n_left. cj += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } } return; } //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) //lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored prefetching on c lea(mem(rcx, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 7*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 7*8)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 7*8)) // prefetch c + 3*rs_c prefetch(0, mem(rdx, rdi, 1, 7*8)) // prefetch c + 4*rs_c prefetch(0, mem(rdx, rdi, 2, 7*8)) // prefetch c + 5*rs_c jmp(.SPOSTPFETCH) // jump to end of prefetching c label(.SCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) lea(mem(rsi, rsi, 2), rbp) // rbp = 3*cs_c; prefetch(0, mem(rcx, 5*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 5*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 5*8)) // prefetch c + 2*cs_c prefetch(0, mem(rcx, rbp, 1, 5*8)) // prefetch c + 3*cs_c prefetch(0, mem(rcx, rsi, 4, 5*8)) // prefetch c + 4*cs_c lea(mem(rcx, rsi, 4), rdx) // rdx = c + 4*cs_c; prefetch(0, mem(rdx, rsi, 1, 5*8)) // prefetch c + 5*cs_c prefetch(0, mem(rdx, rsi, 2, 5*8)) // prefetch c + 6*cs_c prefetch(0, mem(rdx, rbp, 1, 5*8)) // prefetch c + 7*cs_c prefetch(0, mem(rdx, rsi, 4, 5*8)) // prefetch c + 8*cs_c lea(mem(rcx, rsi, 8), rdx) // rdx = c + 8*cs_c; prefetch(0, mem(rdx, rsi, 1, 5*8)) // prefetch c + 9*cs_c prefetch(0, mem(rdx, rsi, 2, 5*8)) // prefetch c + 10*cs_c prefetch(0, mem(rdx, rbp, 1, 5*8)) // prefetch c + 11*cs_c prefetch(0, mem(rdx, rsi, 4, 5*8)) // prefetch c + 12*cs_c lea(mem(rcx, rcx, 4), rdx) // rdx = c + 12*cs_c; prefetch(0, mem(rdx, rsi, 1, 5*8)) // prefetch c + 13*cs_c prefetch(0, mem(rdx, rsi, 2, 5*8)) // prefetch c + 14*cs_c prefetch(0, mem(rdx, rbp, 1, 5*8)) // prefetch c + 15*cs_c label(.SPOSTPFETCH) // done prefetching c #if 1 lea(mem(rax, r9, 8), rdx) // lea(mem(rdx, r9, 8), rdx) // rdx = a + 16*cs_a; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(rdx, 5*8)) #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, r8, 4), ymm2) vbroadcastss(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, r9, 1, 5*8)) #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, r8, 4), ymm2) vbroadcastss(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(rdx, r9, 2, 5*8)) #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, r8, 4), ymm2) vbroadcastss(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) // ---------------------------------- iteration 3 #if 1 lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, r8, 4), ymm2) vbroadcastss(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP #if 0 prefetch(0, mem(rdx, 5*8)) add(r9, rdx) #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, r8, 4), ymm2) vbroadcastss(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), ymm0) // load alpha and duplicate vbroadcastss(mem(rbx), ymm3) // load beta and duplicate vmulps(ymm0, ymm4, ymm4) // scale by alpha vmulps(ymm0, ymm5, ymm5) vmulps(ymm0, ymm6, ymm6) vmulps(ymm0, ymm7, ymm7) vmulps(ymm0, ymm8, ymm8) vmulps(ymm0, ymm9, ymm9) vmulps(ymm0, ymm10, ymm10) vmulps(ymm0, ymm11, ymm11) vmulps(ymm0, ymm12, ymm12) vmulps(ymm0, ymm13, ymm13) vmulps(ymm0, ymm14, ymm14) vmulps(ymm0, ymm15, ymm15) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; lea(mem(rsi, rsi, 4), rbx) // rbx = 5*cs_c; lea(mem(rax, rsi, 4), rbp) // rbp = 7*cs_c; // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm4) vmovups(ymm4, mem(rcx, 0*32)) vfmadd231ps(mem(rcx, 1*32), ymm3, ymm5) vmovups(ymm5, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm6) vmovups(ymm6, mem(rcx, 0*32)) vfmadd231ps(mem(rcx, 1*32), ymm3, ymm7) vmovups(ymm7, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm8) vmovups(ymm8, mem(rcx, 0*32)) vfmadd231ps(mem(rcx, 1*32), ymm3, ymm9) vmovups(ymm9, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm10) vmovups(ymm10, mem(rcx, 0*32)) vfmadd231ps(mem(rcx, 1*32), ymm3, ymm11) vmovups(ymm11, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm12) vmovups(ymm12, mem(rcx, 0*32)) vfmadd231ps(mem(rcx, 1*32), ymm3, ymm13) vmovups(ymm13, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm14) vmovups(ymm14, mem(rcx, 0*32)) vfmadd231ps(mem(rcx, 1*32), ymm3, ymm15) vmovups(ymm15, mem(rcx, 1*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORED) // begin I/O on columns 0-7 vunpcklps(ymm6, ymm4, ymm0) vunpcklps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx ), xmm3, xmm0) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm0, mem(rcx )) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx, rsi, 1), xmm3, xmm1) vfmadd231ps(mem(rcx, rbx, 1), xmm3, xmm2) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rbx, 1)) // store ( gamma05..gamma35 ) vunpckhps(ymm6, ymm4, ymm0) vunpckhps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx, rsi, 2), xmm3, xmm0) vfmadd231ps(mem(rcx, rax, 2), xmm3, xmm2) vmovups(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, rax, 2)) // store ( gamma06..gamma36 ) vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx, rax, 1), xmm3, xmm1) vfmadd231ps(mem(rcx, rbp, 1), xmm3, xmm2) vmovups(xmm1, mem(rcx, rax, 1)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, rbp, 1)) // store ( gamma07..gamma37 ) lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vunpcklps(ymm14, ymm12, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(mem(rdx ), xmm1, xmm1) vmovhpd(mem(rdx, rsi, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(rdx )) // store ( gamma40..gamma50 ) vmovhpd(xmm0, mem(rdx, rsi, 1)) // store ( gamma41..gamma51 ) vmovlpd(mem(rdx, rsi, 4), xmm1, xmm1) vmovhpd(mem(rdx, rbx, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm2) vmovlpd(xmm2, mem(rdx, rsi, 4)) // store ( gamma44..gamma54 ) vmovhpd(xmm2, mem(rdx, rbx, 1)) // store ( gamma45..gamma55 ) vunpckhps(ymm14, ymm12, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(mem(rdx, rsi, 2), xmm1, xmm1) vmovhpd(mem(rdx, rax, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(rdx, rsi, 2)) // store ( gamma42..gamma52 ) vmovhpd(xmm0, mem(rdx, rax, 1)) // store ( gamma43..gamma53 ) vmovlpd(mem(rdx, rax, 2), xmm1, xmm1) vmovhpd(mem(rdx, rbp, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm2) vmovlpd(xmm2, mem(rdx, rax, 2)) // store ( gamma46..gamma56 ) vmovhpd(xmm2, mem(rdx, rbp, 1)) // store ( gamma47..gamma57 ) lea(mem(rdx, rsi, 8), rdx) // rdx += 8*cs_c // begin I/O on columns 8-15 vunpcklps(ymm7, ymm5, ymm0) vunpcklps(ymm11, ymm9, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx ), xmm3, xmm0) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm0, mem(rcx )) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx, rsi, 1), xmm3, xmm1) vfmadd231ps(mem(rcx, rbx, 1), xmm3, xmm2) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rbx, 1)) // store ( gamma05..gamma35 ) vunpckhps(ymm7, ymm5, ymm0) vunpckhps(ymm11, ymm9, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx, rsi, 2), xmm3, xmm0) vfmadd231ps(mem(rcx, rax, 2), xmm3, xmm2) vmovups(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, rax, 2)) // store ( gamma06..gamma36 ) vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx, rax, 1), xmm3, xmm1) vfmadd231ps(mem(rcx, rbp, 1), xmm3, xmm2) vmovups(xmm1, mem(rcx, rax, 1)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, rbp, 1)) // store ( gamma07..gamma37 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vunpcklps(ymm15, ymm13, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(mem(rdx ), xmm1, xmm1) vmovhpd(mem(rdx, rsi, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(rdx )) // store ( gamma40..gamma50 ) vmovhpd(xmm0, mem(rdx, rsi, 1)) // store ( gamma41..gamma51 ) vmovlpd(mem(rdx, rsi, 4), xmm1, xmm1) vmovhpd(mem(rdx, rbx, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm2) vmovlpd(xmm2, mem(rdx, rsi, 4)) // store ( gamma44..gamma54 ) vmovhpd(xmm2, mem(rdx, rbx, 1)) // store ( gamma45..gamma55 ) vunpckhps(ymm15, ymm13, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(mem(rdx, rsi, 2), xmm1, xmm1) vmovhpd(mem(rdx, rax, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(rdx, rsi, 2)) // store ( gamma42..gamma52 ) vmovhpd(xmm0, mem(rdx, rax, 1)) // store ( gamma43..gamma53 ) vmovlpd(mem(rdx, rax, 2), xmm1, xmm1) vmovhpd(mem(rdx, rbp, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm2) vmovlpd(xmm2, mem(rdx, rax, 2)) // store ( gamma46..gamma56 ) vmovhpd(xmm2, mem(rdx, rbp, 1)) // store ( gamma47..gamma57 ) //lea(mem(rdx, rsi, 8), rdx) // rdx += 8*cs_c jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovups(ymm4, mem(rcx, 0*32)) vmovups(ymm5, mem(rcx, 1*32)) add(rdi, rcx) vmovups(ymm6, mem(rcx, 0*32)) vmovups(ymm7, mem(rcx, 1*32)) add(rdi, rcx) vmovups(ymm8, mem(rcx, 0*32)) vmovups(ymm9, mem(rcx, 1*32)) add(rdi, rcx) vmovups(ymm10, mem(rcx, 0*32)) vmovups(ymm11, mem(rcx, 1*32)) add(rdi, rcx) vmovups(ymm12, mem(rcx, 0*32)) vmovups(ymm13, mem(rcx, 1*32)) add(rdi, rcx) vmovups(ymm14, mem(rcx, 0*32)) vmovups(ymm15, mem(rcx, 1*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) // begin I/O on columns 0-7 vunpcklps(ymm6, ymm4, ymm0) vunpcklps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx )) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rbx, 1)) // store ( gamma05..gamma35 ) vunpckhps(ymm6, ymm4, ymm0) vunpckhps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, rax, 2)) // store ( gamma06..gamma36 ) vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx, rax, 1)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, rbp, 1)) // store ( gamma07..gamma37 ) lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vunpcklps(ymm14, ymm12, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(xmm0, mem(rdx )) // store ( gamma40..gamma50 ) vmovhpd(xmm0, mem(rdx, rsi, 1)) // store ( gamma41..gamma51 ) vmovlpd(xmm2, mem(rdx, rsi, 4)) // store ( gamma44..gamma54 ) vmovhpd(xmm2, mem(rdx, rbx, 1)) // store ( gamma45..gamma55 ) vunpckhps(ymm14, ymm12, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(xmm0, mem(rdx, rsi, 2)) // store ( gamma42..gamma52 ) vmovhpd(xmm0, mem(rdx, rax, 1)) // store ( gamma43..gamma53 ) vmovlpd(xmm2, mem(rdx, rax, 2)) // store ( gamma46..gamma56 ) vmovhpd(xmm2, mem(rdx, rbp, 1)) // store ( gamma47..gamma57 ) lea(mem(rdx, rsi, 8), rdx) // rdx += 8*cs_c // begin I/O on columns 8-15 vunpcklps(ymm7, ymm5, ymm0) vunpcklps(ymm11, ymm9, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx )) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rbx, 1)) // store ( gamma05..gamma35 ) vunpckhps(ymm7, ymm5, ymm0) vunpckhps(ymm11, ymm9, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, rax, 2)) // store ( gamma06..gamma36 ) vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx, rax, 1)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, rbp, 1)) // store ( gamma07..gamma37 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vunpcklps(ymm15, ymm13, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(xmm0, mem(rdx )) // store ( gamma40..gamma50 ) vmovhpd(xmm0, mem(rdx, rsi, 1)) // store ( gamma41..gamma51 ) vmovlpd(xmm2, mem(rdx, rsi, 4)) // store ( gamma44..gamma54 ) vmovhpd(xmm2, mem(rdx, rbx, 1)) // store ( gamma45..gamma55 ) vunpckhps(ymm15, ymm13, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(xmm0, mem(rdx, rsi, 2)) // store ( gamma42..gamma52 ) vmovhpd(xmm0, mem(rdx, rax, 1)) // store ( gamma43..gamma53 ) vmovlpd(xmm2, mem(rdx, rax, 2)) // store ( gamma46..gamma56 ) vmovhpd(xmm2, mem(rdx, rbp, 1)) // store ( gamma47..gamma57 ) //lea(mem(rdx, rsi, 8), rdx) // rdx += 8*cs_c label(.SDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_sgemmsup_rv_haswell_asm_5x16 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) //lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored prefetching on c lea(mem(rcx, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 7*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 7*8)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 7*8)) // prefetch c + 3*rs_c prefetch(0, mem(rdx, rdi, 1, 7*8)) // prefetch c + 4*rs_c jmp(.SPOSTPFETCH) // jump to end of prefetching c label(.SCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) lea(mem(rsi, rsi, 2), rbp) // rbp = 3*cs_c; prefetch(0, mem(rcx, 4*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 4*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 4*8)) // prefetch c + 2*cs_c prefetch(0, mem(rcx, rbp, 1, 4*8)) // prefetch c + 3*cs_c prefetch(0, mem(rcx, rsi, 4, 4*8)) // prefetch c + 4*cs_c lea(mem(rcx, rsi, 4), rdx) // rdx = c + 4*cs_c; prefetch(0, mem(rdx, rsi, 1, 4*8)) // prefetch c + 5*cs_c prefetch(0, mem(rdx, rsi, 2, 4*8)) // prefetch c + 6*cs_c prefetch(0, mem(rdx, rbp, 1, 4*8)) // prefetch c + 7*cs_c prefetch(0, mem(rdx, rsi, 4, 4*8)) // prefetch c + 8*cs_c lea(mem(rcx, rsi, 8), rdx) // rdx = c + 8*cs_c; prefetch(0, mem(rdx, rsi, 1, 4*8)) // prefetch c + 9*cs_c prefetch(0, mem(rdx, rsi, 2, 4*8)) // prefetch c + 10*cs_c prefetch(0, mem(rdx, rbp, 1, 4*8)) // prefetch c + 11*cs_c prefetch(0, mem(rdx, rsi, 4, 4*8)) // prefetch c + 12*cs_c lea(mem(rcx, rcx, 4), rdx) // rdx = c + 12*cs_c; prefetch(0, mem(rdx, rsi, 1, 4*8)) // prefetch c + 13*cs_c prefetch(0, mem(rdx, rsi, 2, 4*8)) // prefetch c + 14*cs_c prefetch(0, mem(rdx, rbp, 1, 4*8)) // prefetch c + 15*cs_c label(.SPOSTPFETCH) // done prefetching c #if 1 lea(mem(rax, r9, 8), rdx) // lea(mem(rdx, r9, 8), rdx) // rdx = a + 16*cs_a; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(rdx, 4*8)) #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, r9, 1, 4*8)) #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(rdx, r9, 2, 4*8)) #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) // ---------------------------------- iteration 3 #if 1 lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP #if 0 prefetch(0, mem(rdx, 5*8)) add(r9, rdx) #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), ymm0) // load alpha and duplicate vbroadcastss(mem(rbx), ymm3) // load beta and duplicate vmulps(ymm0, ymm4, ymm4) // scale by alpha vmulps(ymm0, ymm5, ymm5) vmulps(ymm0, ymm6, ymm6) vmulps(ymm0, ymm7, ymm7) vmulps(ymm0, ymm8, ymm8) vmulps(ymm0, ymm9, ymm9) vmulps(ymm0, ymm10, ymm10) vmulps(ymm0, ymm11, ymm11) vmulps(ymm0, ymm12, ymm12) vmulps(ymm0, ymm13, ymm13) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; lea(mem(rsi, rsi, 4), rbx) // rbx = 5*cs_c; lea(mem(rax, rsi, 4), rbp) // rbp = 7*cs_c; // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm4) vmovups(ymm4, mem(rcx, 0*32)) vfmadd231ps(mem(rcx, 1*32), ymm3, ymm5) vmovups(ymm5, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm6) vmovups(ymm6, mem(rcx, 0*32)) vfmadd231ps(mem(rcx, 1*32), ymm3, ymm7) vmovups(ymm7, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm8) vmovups(ymm8, mem(rcx, 0*32)) vfmadd231ps(mem(rcx, 1*32), ymm3, ymm9) vmovups(ymm9, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm10) vmovups(ymm10, mem(rcx, 0*32)) vfmadd231ps(mem(rcx, 1*32), ymm3, ymm11) vmovups(ymm11, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm12) vmovups(ymm12, mem(rcx, 0*32)) vfmadd231ps(mem(rcx, 1*32), ymm3, ymm13) vmovups(ymm13, mem(rcx, 1*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORED) // begin I/O on columns 0-7 vunpcklps(ymm6, ymm4, ymm0) vunpcklps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx ), xmm3, xmm0) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm0, mem(rcx )) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx, rsi, 1), xmm3, xmm1) vfmadd231ps(mem(rcx, rbx, 1), xmm3, xmm2) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rbx, 1)) // store ( gamma05..gamma35 ) vunpckhps(ymm6, ymm4, ymm0) vunpckhps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx, rsi, 2), xmm3, xmm0) vfmadd231ps(mem(rcx, rax, 2), xmm3, xmm2) vmovups(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, rax, 2)) // store ( gamma06..gamma36 ) vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx, rax, 1), xmm3, xmm1) vfmadd231ps(mem(rcx, rbp, 1), xmm3, xmm2) vmovups(xmm1, mem(rcx, rax, 1)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, rbp, 1)) // store ( gamma07..gamma37 ) lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vmovups(ymm12, ymm0) vextractf128(imm(0x1), ymm0, xmm8) vpermilps(imm(0xe4), xmm0, xmm2) vpermilps(imm(0x39), xmm0, xmm4) vmovss(mem(rdx ), xmm1) vmovss(mem(rdx, rsi, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rdx )) // store ( gamma40 ) vmovss(xmm4, mem(rdx, rsi, 1)) // store ( gamma41 ) vpermilps(imm(0x4e), xmm0, xmm2) vpermilps(imm(0x93), xmm0, xmm4) vmovss(mem(rdx, rsi, 2), xmm1) vmovss(mem(rdx, rax, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rdx, rsi, 2)) // store ( gamma42 ) vmovss(xmm4, mem(rdx, rax, 1)) // store ( gamma43 ) vpermilps(imm(0xe4), xmm8, xmm2) vpermilps(imm(0x39), xmm8, xmm4) vmovss(mem(rdx, rsi, 4), xmm1) vmovss(mem(rdx, rbx, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rdx, rsi, 4)) // store ( gamma44 ) vmovss(xmm4, mem(rdx, rbx, 1)) // store ( gamma45 ) vpermilps(imm(0x4e), xmm8, xmm2) vpermilps(imm(0x93), xmm8, xmm4) vmovss(mem(rdx, rax, 2), xmm1) vmovss(mem(rdx, rbp, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rdx, rax, 2)) // store ( gamma46 ) vmovss(xmm4, mem(rdx, rbp, 1)) // store ( gamma47 ) lea(mem(rdx, rsi, 8), rdx) // rdx += 8*cs_c // begin I/O on columns 8-15 vunpcklps(ymm7, ymm5, ymm0) vunpcklps(ymm11, ymm9, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx ), xmm3, xmm0) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm0, mem(rcx )) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx, rsi, 1), xmm3, xmm1) vfmadd231ps(mem(rcx, rbx, 1), xmm3, xmm2) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rbx, 1)) // store ( gamma05..gamma35 ) vunpckhps(ymm7, ymm5, ymm0) vunpckhps(ymm11, ymm9, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx, rsi, 2), xmm3, xmm0) vfmadd231ps(mem(rcx, rax, 2), xmm3, xmm2) vmovups(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, rax, 2)) // store ( gamma06..gamma36 ) vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx, rax, 1), xmm3, xmm1) vfmadd231ps(mem(rcx, rbp, 1), xmm3, xmm2) vmovups(xmm1, mem(rcx, rax, 1)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, rbp, 1)) // store ( gamma07..gamma37 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vmovups(ymm13, ymm0) vextractf128(imm(0x1), ymm0, xmm8) vpermilps(imm(0xe4), xmm0, xmm2) vpermilps(imm(0x39), xmm0, xmm4) vmovss(mem(rdx ), xmm1) vmovss(mem(rdx, rsi, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rdx )) // store ( gamma40 ) vmovss(xmm4, mem(rdx, rsi, 1)) // store ( gamma41 ) vpermilps(imm(0x4e), xmm0, xmm2) vpermilps(imm(0x93), xmm0, xmm4) vmovss(mem(rdx, rsi, 2), xmm1) vmovss(mem(rdx, rax, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rdx, rsi, 2)) // store ( gamma42 ) vmovss(xmm4, mem(rdx, rax, 1)) // store ( gamma43 ) vpermilps(imm(0xe4), xmm8, xmm2) vpermilps(imm(0x39), xmm8, xmm4) vmovss(mem(rdx, rsi, 4), xmm1) vmovss(mem(rdx, rbx, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rdx, rsi, 4)) // store ( gamma44 ) vmovss(xmm4, mem(rdx, rbx, 1)) // store ( gamma45 ) vpermilps(imm(0x4e), xmm8, xmm2) vpermilps(imm(0x93), xmm8, xmm4) vmovss(mem(rdx, rax, 2), xmm1) vmovss(mem(rdx, rbp, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rdx, rax, 2)) // store ( gamma46 ) vmovss(xmm4, mem(rdx, rbp, 1)) // store ( gamma47 ) //lea(mem(rdx, rsi, 8), rdx) // rdx += 8*cs_c jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovups(ymm4, mem(rcx, 0*32)) vmovups(ymm5, mem(rcx, 1*32)) add(rdi, rcx) vmovups(ymm6, mem(rcx, 0*32)) vmovups(ymm7, mem(rcx, 1*32)) add(rdi, rcx) vmovups(ymm8, mem(rcx, 0*32)) vmovups(ymm9, mem(rcx, 1*32)) add(rdi, rcx) vmovups(ymm10, mem(rcx, 0*32)) vmovups(ymm11, mem(rcx, 1*32)) add(rdi, rcx) vmovups(ymm12, mem(rcx, 0*32)) vmovups(ymm13, mem(rcx, 1*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) // begin I/O on columns 0-7 vunpcklps(ymm6, ymm4, ymm0) vunpcklps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx )) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rbx, 1)) // store ( gamma05..gamma35 ) vunpckhps(ymm6, ymm4, ymm0) vunpckhps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, rax, 2)) // store ( gamma06..gamma36 ) vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx, rax, 1)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, rbp, 1)) // store ( gamma07..gamma37 ) lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vmovups(ymm12, ymm0) vextractf128(imm(0x1), ymm0, xmm8) vpermilps(imm(0xe4), xmm0, xmm2) vpermilps(imm(0x39), xmm0, xmm4) vmovss(xmm2, mem(rdx )) // store ( gamma40 ) vmovss(xmm4, mem(rdx, rsi, 1)) // store ( gamma41 ) vpermilps(imm(0x4e), xmm0, xmm2) vpermilps(imm(0x93), xmm0, xmm4) vmovss(xmm2, mem(rdx, rsi, 2)) // store ( gamma42 ) vmovss(xmm4, mem(rdx, rax, 1)) // store ( gamma43 ) vpermilps(imm(0xe4), xmm8, xmm2) vpermilps(imm(0x39), xmm8, xmm4) vmovss(xmm2, mem(rdx, rsi, 4)) // store ( gamma44 ) vmovss(xmm4, mem(rdx, rbx, 1)) // store ( gamma45 ) vpermilps(imm(0x4e), xmm8, xmm2) vpermilps(imm(0x93), xmm8, xmm4) vmovss(xmm2, mem(rdx, rax, 2)) // store ( gamma46 ) vmovss(xmm4, mem(rdx, rbp, 1)) // store ( gamma47 ) lea(mem(rdx, rsi, 8), rdx) // rdx += 8*cs_c // begin I/O on columns 8-15 vunpcklps(ymm7, ymm5, ymm0) vunpcklps(ymm11, ymm9, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx )) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rbx, 1)) // store ( gamma05..gamma35 ) vunpckhps(ymm7, ymm5, ymm0) vunpckhps(ymm11, ymm9, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, rax, 2)) // store ( gamma06..gamma36 ) vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx, rax, 1)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, rbp, 1)) // store ( gamma07..gamma37 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vmovups(ymm13, ymm0) vextractf128(imm(0x1), ymm0, xmm8) vpermilps(imm(0xe4), xmm0, xmm2) vpermilps(imm(0x39), xmm0, xmm4) vmovss(xmm2, mem(rdx )) // store ( gamma40 ) vmovss(xmm4, mem(rdx, rsi, 1)) // store ( gamma41 ) vpermilps(imm(0x4e), xmm0, xmm2) vpermilps(imm(0x93), xmm0, xmm4) vmovss(xmm2, mem(rdx, rsi, 2)) // store ( gamma42 ) vmovss(xmm4, mem(rdx, rax, 1)) // store ( gamma43 ) vpermilps(imm(0xe4), xmm8, xmm2) vpermilps(imm(0x39), xmm8, xmm4) vmovss(xmm2, mem(rdx, rsi, 4)) // store ( gamma44 ) vmovss(xmm4, mem(rdx, rbx, 1)) // store ( gamma45 ) vpermilps(imm(0x4e), xmm8, xmm2) vpermilps(imm(0x93), xmm8, xmm4) vmovss(xmm2, mem(rdx, rax, 2)) // store ( gamma46 ) vmovss(xmm4, mem(rdx, rbp, 1)) // store ( gamma47 ) //lea(mem(rdx, rsi, 8), rdx) // rdx += 8*cs_c label(.SDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_sgemmsup_rv_haswell_asm_4x16 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) //lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored prefetching on c lea(mem(rcx, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 7*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 7*8)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 7*8)) // prefetch c + 3*rs_c jmp(.SPOSTPFETCH) // jump to end of prefetching c label(.SCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) lea(mem(rsi, rsi, 2), rbp) // rbp = 3*cs_c; prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 3*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 3*8)) // prefetch c + 2*cs_c prefetch(0, mem(rcx, rbp, 1, 3*8)) // prefetch c + 3*cs_c prefetch(0, mem(rcx, rsi, 4, 3*8)) // prefetch c + 4*cs_c lea(mem(rcx, rsi, 4), rdx) // rdx = c + 4*cs_c; prefetch(0, mem(rdx, rsi, 1, 3*8)) // prefetch c + 5*cs_c prefetch(0, mem(rdx, rsi, 2, 3*8)) // prefetch c + 6*cs_c prefetch(0, mem(rdx, rbp, 1, 3*8)) // prefetch c + 7*cs_c prefetch(0, mem(rdx, rsi, 4, 3*8)) // prefetch c + 8*cs_c lea(mem(rcx, rsi, 8), rdx) // rdx = c + 8*cs_c; prefetch(0, mem(rdx, rsi, 1, 3*8)) // prefetch c + 9*cs_c prefetch(0, mem(rdx, rsi, 2, 3*8)) // prefetch c + 10*cs_c prefetch(0, mem(rdx, rbp, 1, 3*8)) // prefetch c + 11*cs_c prefetch(0, mem(rdx, rsi, 4, 3*8)) // prefetch c + 12*cs_c lea(mem(rcx, rcx, 4), rdx) // rdx = c + 12*cs_c; prefetch(0, mem(rdx, rsi, 1, 3*8)) // prefetch c + 13*cs_c prefetch(0, mem(rdx, rsi, 2, 3*8)) // prefetch c + 14*cs_c prefetch(0, mem(rdx, rbp, 1, 3*8)) // prefetch c + 15*cs_c label(.SPOSTPFETCH) // done prefetching c #if 1 lea(mem(rax, r9, 8), rdx) // lea(mem(rdx, r9, 8), rdx) // rdx = a + 16*cs_a; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(rdx, 4*8)) #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, r9, 1, 4*8)) #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(rdx, r9, 2, 4*8)) #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) // ---------------------------------- iteration 3 #if 1 lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP #if 0 prefetch(0, mem(rdx, 5*8)) add(r9, rdx) #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), ymm0) // load alpha and duplicate vbroadcastss(mem(rbx), ymm3) // load beta and duplicate vmulps(ymm0, ymm4, ymm4) // scale by alpha vmulps(ymm0, ymm5, ymm5) vmulps(ymm0, ymm6, ymm6) vmulps(ymm0, ymm7, ymm7) vmulps(ymm0, ymm8, ymm8) vmulps(ymm0, ymm9, ymm9) vmulps(ymm0, ymm10, ymm10) vmulps(ymm0, ymm11, ymm11) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; //lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; lea(mem(rsi, rsi, 4), rbx) // rbx = 5*cs_c; lea(mem(rax, rsi, 4), rbp) // rbp = 7*cs_c; // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm4) vmovups(ymm4, mem(rcx, 0*32)) vfmadd231ps(mem(rcx, 1*32), ymm3, ymm5) vmovups(ymm5, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm6) vmovups(ymm6, mem(rcx, 0*32)) vfmadd231ps(mem(rcx, 1*32), ymm3, ymm7) vmovups(ymm7, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm8) vmovups(ymm8, mem(rcx, 0*32)) vfmadd231ps(mem(rcx, 1*32), ymm3, ymm9) vmovups(ymm9, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm10) vmovups(ymm10, mem(rcx, 0*32)) vfmadd231ps(mem(rcx, 1*32), ymm3, ymm11) vmovups(ymm11, mem(rcx, 1*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORED) // begin I/O on columns 0-7 vunpcklps(ymm6, ymm4, ymm0) vunpcklps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx ), xmm3, xmm0) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm0, mem(rcx )) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx, rsi, 1), xmm3, xmm1) vfmadd231ps(mem(rcx, rbx, 1), xmm3, xmm2) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rbx, 1)) // store ( gamma05..gamma35 ) vunpckhps(ymm6, ymm4, ymm0) vunpckhps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx, rsi, 2), xmm3, xmm0) vfmadd231ps(mem(rcx, rax, 2), xmm3, xmm2) vmovups(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, rax, 2)) // store ( gamma06..gamma36 ) vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx, rax, 1), xmm3, xmm1) vfmadd231ps(mem(rcx, rbp, 1), xmm3, xmm2) vmovups(xmm1, mem(rcx, rax, 1)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, rbp, 1)) // store ( gamma07..gamma37 ) lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c // begin I/O on columns 8-15 vunpcklps(ymm7, ymm5, ymm0) vunpcklps(ymm11, ymm9, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx ), xmm3, xmm0) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm0, mem(rcx )) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx, rsi, 1), xmm3, xmm1) vfmadd231ps(mem(rcx, rbx, 1), xmm3, xmm2) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rbx, 1)) // store ( gamma05..gamma35 ) vunpckhps(ymm7, ymm5, ymm0) vunpckhps(ymm11, ymm9, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx, rsi, 2), xmm3, xmm0) vfmadd231ps(mem(rcx, rax, 2), xmm3, xmm2) vmovups(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, rax, 2)) // store ( gamma06..gamma36 ) vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx, rax, 1), xmm3, xmm1) vfmadd231ps(mem(rcx, rbp, 1), xmm3, xmm2) vmovups(xmm1, mem(rcx, rax, 1)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, rbp, 1)) // store ( gamma07..gamma37 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (8*rs_c) == 8. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovups(ymm4, mem(rcx, 0*32)) vmovups(ymm5, mem(rcx, 1*32)) add(rdi, rcx) vmovups(ymm6, mem(rcx, 0*32)) vmovups(ymm7, mem(rcx, 1*32)) add(rdi, rcx) vmovups(ymm8, mem(rcx, 0*32)) vmovups(ymm9, mem(rcx, 1*32)) add(rdi, rcx) vmovups(ymm10, mem(rcx, 0*32)) vmovups(ymm11, mem(rcx, 1*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) // begin I/O on columns 0-7 vunpcklps(ymm6, ymm4, ymm0) vunpcklps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx )) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rbx, 1)) // store ( gamma05..gamma35 ) vunpckhps(ymm6, ymm4, ymm0) vunpckhps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, rax, 2)) // store ( gamma06..gamma36 ) vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx, rax, 1)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, rbp, 1)) // store ( gamma07..gamma37 ) lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c // begin I/O on columns 8-15 vunpcklps(ymm7, ymm5, ymm0) vunpcklps(ymm11, ymm9, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx )) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rbx, 1)) // store ( gamma05..gamma35 ) vunpckhps(ymm7, ymm5, ymm0) vunpckhps(ymm11, ymm9, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, rax, 2)) // store ( gamma06..gamma36 ) vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx, rax, 1)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, rbp, 1)) // store ( gamma07..gamma37 ) //lea(mem(rcx, rsi, 4), rcx) label(.SDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_sgemmsup_rv_haswell_asm_3x16 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) //lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored prefetching on c //lea(mem(rcx, rdi, 2), rdx) // //lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 7*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 7*8)) // prefetch c + 2*rs_c jmp(.SPOSTPFETCH) // jump to end of prefetching c label(.SCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) lea(mem(rsi, rsi, 2), rbp) // rbp = 3*cs_c; prefetch(0, mem(rcx, 2*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 2*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 2*8)) // prefetch c + 2*cs_c prefetch(0, mem(rcx, rbp, 1, 2*8)) // prefetch c + 3*cs_c prefetch(0, mem(rcx, rsi, 4, 2*8)) // prefetch c + 4*cs_c lea(mem(rcx, rsi, 4), rdx) // rdx = c + 4*cs_c; prefetch(0, mem(rdx, rsi, 1, 2*8)) // prefetch c + 5*cs_c prefetch(0, mem(rdx, rsi, 2, 2*8)) // prefetch c + 6*cs_c prefetch(0, mem(rdx, rbp, 1, 2*8)) // prefetch c + 7*cs_c prefetch(0, mem(rdx, rsi, 4, 2*8)) // prefetch c + 8*cs_c lea(mem(rcx, rsi, 8), rdx) // rdx = c + 8*cs_c; prefetch(0, mem(rdx, rsi, 1, 2*8)) // prefetch c + 9*cs_c prefetch(0, mem(rdx, rsi, 2, 2*8)) // prefetch c + 10*cs_c prefetch(0, mem(rdx, rbp, 1, 2*8)) // prefetch c + 11*cs_c prefetch(0, mem(rdx, rsi, 4, 2*8)) // prefetch c + 12*cs_c lea(mem(rcx, rcx, 4), rdx) // rdx = c + 12*cs_c; prefetch(0, mem(rdx, rsi, 1, 2*8)) // prefetch c + 13*cs_c prefetch(0, mem(rdx, rsi, 2, 2*8)) // prefetch c + 14*cs_c prefetch(0, mem(rdx, rbp, 1, 2*8)) // prefetch c + 15*cs_c label(.SPOSTPFETCH) // done prefetching c #if 1 lea(mem(rax, r9, 8), rdx) // lea(mem(rdx, r9, 8), rdx) // rdx = a + 16*cs_a; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(rdx, 4*8)) #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, r9, 1, 4*8)) #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(rdx, r9, 2, 4*8)) #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) // ---------------------------------- iteration 3 #if 1 lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP #if 0 prefetch(0, mem(rdx, 5*8)) add(r9, rdx) #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), ymm0) // load alpha and duplicate vbroadcastss(mem(rbx), ymm3) // load beta and duplicate vmulps(ymm0, ymm4, ymm4) // scale by alpha vmulps(ymm0, ymm5, ymm5) vmulps(ymm0, ymm6, ymm6) vmulps(ymm0, ymm7, ymm7) vmulps(ymm0, ymm8, ymm8) vmulps(ymm0, ymm9, ymm9) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; lea(mem(rcx, rdi, 2), rdx) // load address of c + 2*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; lea(mem(rsi, rsi, 4), rbx) // rbx = 5*cs_c; lea(mem(rax, rsi, 4), rbp) // rbp = 7*cs_c; // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm4) vmovups(ymm4, mem(rcx, 0*32)) vfmadd231ps(mem(rcx, 1*32), ymm3, ymm5) vmovups(ymm5, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm6) vmovups(ymm6, mem(rcx, 0*32)) vfmadd231ps(mem(rcx, 1*32), ymm3, ymm7) vmovups(ymm7, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm8) vmovups(ymm8, mem(rcx, 0*32)) vfmadd231ps(mem(rcx, 1*32), ymm3, ymm9) vmovups(ymm9, mem(rcx, 1*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORED) // begin I/O on columns 0-7 vunpcklps(ymm6, ymm4, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(mem(rcx ), xmm1, xmm1) vmovhpd(mem(rcx, rsi, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(rcx )) // store ( gamma00..gamma10 ) vmovhpd(xmm0, mem(rcx, rsi, 1)) // store ( gamma01..gamma11 ) vmovlpd(mem(rcx, rsi, 4), xmm1, xmm1) vmovhpd(mem(rcx, rbx, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm2) vmovlpd(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma14 ) vmovhpd(xmm2, mem(rcx, rbx, 1)) // store ( gamma05..gamma15 ) vunpckhps(ymm6, ymm4, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(mem(rcx, rsi, 2), xmm1, xmm1) vmovhpd(mem(rcx, rax, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma12 ) vmovhpd(xmm0, mem(rcx, rax, 1)) // store ( gamma03..gamma13 ) vmovlpd(mem(rcx, rax, 2), xmm1, xmm1) vmovhpd(mem(rcx, rbp, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm2) vmovlpd(xmm2, mem(rcx, rax, 2)) // store ( gamma06..gamma16 ) vmovhpd(xmm2, mem(rcx, rbp, 1)) // store ( gamma07..gamma17 ) lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vmovups(ymm8, ymm0) vextractf128(imm(0x1), ymm0, xmm8) vpermilps(imm(0xe4), xmm0, xmm2) vpermilps(imm(0x39), xmm0, xmm4) vmovss(mem(rdx ), xmm1) vmovss(mem(rdx, rsi, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rdx )) // store ( gamma40 ) vmovss(xmm4, mem(rdx, rsi, 1)) // store ( gamma41 ) vpermilps(imm(0x4e), xmm0, xmm2) vpermilps(imm(0x93), xmm0, xmm4) vmovss(mem(rdx, rsi, 2), xmm1) vmovss(mem(rdx, rax, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rdx, rsi, 2)) // store ( gamma42 ) vmovss(xmm4, mem(rdx, rax, 1)) // store ( gamma43 ) vpermilps(imm(0xe4), xmm8, xmm2) vpermilps(imm(0x39), xmm8, xmm4) vmovss(mem(rdx, rsi, 4), xmm1) vmovss(mem(rdx, rbx, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rdx, rsi, 4)) // store ( gamma44 ) vmovss(xmm4, mem(rdx, rbx, 1)) // store ( gamma45 ) vpermilps(imm(0x4e), xmm8, xmm2) vpermilps(imm(0x93), xmm8, xmm4) vmovss(mem(rdx, rax, 2), xmm1) vmovss(mem(rdx, rbp, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rdx, rax, 2)) // store ( gamma46 ) vmovss(xmm4, mem(rdx, rbp, 1)) // store ( gamma47 ) lea(mem(rdx, rsi, 8), rdx) // rdx += 8*cs_c // begin I/O on columns 8-15 vunpcklps(ymm7, ymm5, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(mem(rcx ), xmm1, xmm1) vmovhpd(mem(rcx, rsi, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(rcx )) // store ( gamma00..gamma10 ) vmovhpd(xmm0, mem(rcx, rsi, 1)) // store ( gamma01..gamma11 ) vmovlpd(mem(rcx, rsi, 4), xmm1, xmm1) vmovhpd(mem(rcx, rbx, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm2) vmovlpd(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma14 ) vmovhpd(xmm2, mem(rcx, rbx, 1)) // store ( gamma05..gamma15 ) vunpckhps(ymm7, ymm5, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(mem(rcx, rsi, 2), xmm1, xmm1) vmovhpd(mem(rcx, rax, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma12 ) vmovhpd(xmm0, mem(rcx, rax, 1)) // store ( gamma03..gamma13 ) vmovlpd(mem(rcx, rax, 2), xmm1, xmm1) vmovhpd(mem(rcx, rbp, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm2) vmovlpd(xmm2, mem(rcx, rax, 2)) // store ( gamma06..gamma16 ) vmovhpd(xmm2, mem(rcx, rbp, 1)) // store ( gamma07..gamma17 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vmovups(ymm9, ymm0) vextractf128(imm(0x1), ymm0, xmm8) vpermilps(imm(0xe4), xmm0, xmm2) vpermilps(imm(0x39), xmm0, xmm4) vmovss(mem(rdx ), xmm1) vmovss(mem(rdx, rsi, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rdx )) // store ( gamma40 ) vmovss(xmm4, mem(rdx, rsi, 1)) // store ( gamma41 ) vpermilps(imm(0x4e), xmm0, xmm2) vpermilps(imm(0x93), xmm0, xmm4) vmovss(mem(rdx, rsi, 2), xmm1) vmovss(mem(rdx, rax, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rdx, rsi, 2)) // store ( gamma42 ) vmovss(xmm4, mem(rdx, rax, 1)) // store ( gamma43 ) vpermilps(imm(0xe4), xmm8, xmm2) vpermilps(imm(0x39), xmm8, xmm4) vmovss(mem(rdx, rsi, 4), xmm1) vmovss(mem(rdx, rbx, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rdx, rsi, 4)) // store ( gamma44 ) vmovss(xmm4, mem(rdx, rbx, 1)) // store ( gamma45 ) vpermilps(imm(0x4e), xmm8, xmm2) vpermilps(imm(0x93), xmm8, xmm4) vmovss(mem(rdx, rax, 2), xmm1) vmovss(mem(rdx, rbp, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rdx, rax, 2)) // store ( gamma46 ) vmovss(xmm4, mem(rdx, rbp, 1)) // store ( gamma47 ) //lea(mem(rdx, rsi, 8), rdx) // rdx += 8*cs_c jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (8*rs_c) == 8. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovups(ymm4, mem(rcx, 0*32)) vmovups(ymm5, mem(rcx, 1*32)) add(rdi, rcx) vmovups(ymm6, mem(rcx, 0*32)) vmovups(ymm7, mem(rcx, 1*32)) add(rdi, rcx) vmovups(ymm8, mem(rcx, 0*32)) vmovups(ymm9, mem(rcx, 1*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) // begin I/O on columns 0-7 vunpcklps(ymm6, ymm4, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(xmm0, mem(rcx )) // store ( gamma00..gamma10 ) vmovhpd(xmm0, mem(rcx, rsi, 1)) // store ( gamma01..gamma11 ) vmovlpd(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma14 ) vmovhpd(xmm2, mem(rcx, rbx, 1)) // store ( gamma05..gamma15 ) vunpckhps(ymm6, ymm4, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma12 ) vmovhpd(xmm0, mem(rcx, rax, 1)) // store ( gamma03..gamma13 ) vmovlpd(xmm2, mem(rcx, rax, 2)) // store ( gamma06..gamma16 ) vmovhpd(xmm2, mem(rcx, rbp, 1)) // store ( gamma07..gamma17 ) lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vmovups(ymm8, ymm0) vextractf128(imm(0x1), ymm0, xmm8) vpermilps(imm(0xe4), xmm0, xmm2) vpermilps(imm(0x39), xmm0, xmm4) vmovss(xmm2, mem(rdx )) // store ( gamma40 ) vmovss(xmm4, mem(rdx, rsi, 1)) // store ( gamma41 ) vpermilps(imm(0x4e), xmm0, xmm2) vpermilps(imm(0x93), xmm0, xmm4) vmovss(xmm2, mem(rdx, rsi, 2)) // store ( gamma42 ) vmovss(xmm4, mem(rdx, rax, 1)) // store ( gamma43 ) vpermilps(imm(0xe4), xmm8, xmm2) vpermilps(imm(0x39), xmm8, xmm4) vmovss(xmm2, mem(rdx, rsi, 4)) // store ( gamma44 ) vmovss(xmm4, mem(rdx, rbx, 1)) // store ( gamma45 ) vpermilps(imm(0x4e), xmm8, xmm2) vpermilps(imm(0x93), xmm8, xmm4) vmovss(xmm2, mem(rdx, rax, 2)) // store ( gamma46 ) vmovss(xmm4, mem(rdx, rbp, 1)) // store ( gamma47 ) lea(mem(rdx, rsi, 8), rdx) // rdx += 8*cs_c // begin I/O on columns 8-15 vunpcklps(ymm7, ymm5, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(xmm0, mem(rcx )) // store ( gamma00..gamma10 ) vmovhpd(xmm0, mem(rcx, rsi, 1)) // store ( gamma01..gamma11 ) vmovlpd(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma14 ) vmovhpd(xmm2, mem(rcx, rbx, 1)) // store ( gamma05..gamma15 ) vunpckhps(ymm7, ymm5, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma12 ) vmovhpd(xmm0, mem(rcx, rax, 1)) // store ( gamma03..gamma13 ) vmovlpd(xmm2, mem(rcx, rax, 2)) // store ( gamma06..gamma16 ) vmovhpd(xmm2, mem(rcx, rbp, 1)) // store ( gamma07..gamma17 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vmovups(ymm9, ymm0) vextractf128(imm(0x1), ymm0, xmm8) vpermilps(imm(0xe4), xmm0, xmm2) vpermilps(imm(0x39), xmm0, xmm4) vmovss(xmm2, mem(rdx )) // store ( gamma40 ) vmovss(xmm4, mem(rdx, rsi, 1)) // store ( gamma41 ) vpermilps(imm(0x4e), xmm0, xmm2) vpermilps(imm(0x93), xmm0, xmm4) vmovss(xmm2, mem(rdx, rsi, 2)) // store ( gamma42 ) vmovss(xmm4, mem(rdx, rax, 1)) // store ( gamma43 ) vpermilps(imm(0xe4), xmm8, xmm2) vpermilps(imm(0x39), xmm8, xmm4) vmovss(xmm2, mem(rdx, rsi, 4)) // store ( gamma44 ) vmovss(xmm4, mem(rdx, rbx, 1)) // store ( gamma45 ) vpermilps(imm(0x4e), xmm8, xmm2) vpermilps(imm(0x93), xmm8, xmm4) vmovss(xmm2, mem(rdx, rax, 2)) // store ( gamma46 ) vmovss(xmm4, mem(rdx, rbp, 1)) // store ( gamma47 ) //lea(mem(rcx, rsi, 4), rcx) label(.SDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_sgemmsup_rv_haswell_asm_2x16 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) //lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored prefetching on c //lea(mem(rcx, rdi, 2), rdx) // //lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 7*8)) // prefetch c + 1*rs_c jmp(.SPOSTPFETCH) // jump to end of prefetching c label(.SCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) lea(mem(rsi, rsi, 2), rbp) // rbp = 3*cs_c; prefetch(0, mem(rcx, 1*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 1*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 1*8)) // prefetch c + 2*cs_c prefetch(0, mem(rcx, rbp, 1, 1*8)) // prefetch c + 3*cs_c prefetch(0, mem(rcx, rsi, 4, 1*8)) // prefetch c + 4*cs_c lea(mem(rcx, rsi, 4), rdx) // rdx = c + 4*cs_c; prefetch(0, mem(rdx, rsi, 1, 1*8)) // prefetch c + 5*cs_c prefetch(0, mem(rdx, rsi, 2, 1*8)) // prefetch c + 6*cs_c prefetch(0, mem(rdx, rbp, 1, 1*8)) // prefetch c + 7*cs_c prefetch(0, mem(rdx, rsi, 4, 1*8)) // prefetch c + 8*cs_c lea(mem(rcx, rsi, 8), rdx) // rdx = c + 8*cs_c; prefetch(0, mem(rdx, rsi, 1, 1*8)) // prefetch c + 9*cs_c prefetch(0, mem(rdx, rsi, 2, 1*8)) // prefetch c + 10*cs_c prefetch(0, mem(rdx, rbp, 1, 1*8)) // prefetch c + 11*cs_c prefetch(0, mem(rdx, rsi, 4, 1*8)) // prefetch c + 12*cs_c lea(mem(rcx, rcx, 4), rdx) // rdx = c + 12*cs_c; prefetch(0, mem(rdx, rsi, 1, 1*8)) // prefetch c + 13*cs_c prefetch(0, mem(rdx, rsi, 2, 1*8)) // prefetch c + 14*cs_c prefetch(0, mem(rdx, rbp, 1, 1*8)) // prefetch c + 15*cs_c label(.SPOSTPFETCH) // done prefetching c #if 1 lea(mem(rax, r9, 8), rdx) // lea(mem(rdx, r9, 8), rdx) // rdx = a + 16*cs_a; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(rdx, 4*8)) #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, r9, 1, 4*8)) #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(rdx, r9, 2, 4*8)) #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) // ---------------------------------- iteration 3 #if 1 lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP #if 0 prefetch(0, mem(rdx, 5*8)) add(r9, rdx) #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), ymm0) // load alpha and duplicate vbroadcastss(mem(rbx), ymm3) // load beta and duplicate vmulps(ymm0, ymm4, ymm4) // scale by alpha vmulps(ymm0, ymm5, ymm5) vmulps(ymm0, ymm6, ymm6) vmulps(ymm0, ymm7, ymm7) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; //lea(mem(rcx, rdi, 2), rdx) // load address of c + 2*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; lea(mem(rsi, rsi, 4), rbx) // rbx = 5*cs_c; lea(mem(rax, rsi, 4), rbp) // rbp = 7*cs_c; // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm4) vmovups(ymm4, mem(rcx, 0*32)) vfmadd231ps(mem(rcx, 1*32), ymm3, ymm5) vmovups(ymm5, mem(rcx, 1*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm6) vmovups(ymm6, mem(rcx, 0*32)) vfmadd231ps(mem(rcx, 1*32), ymm3, ymm7) vmovups(ymm7, mem(rcx, 1*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORED) // begin I/O on columns 0-7 vunpcklps(ymm6, ymm4, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(mem(rcx ), xmm1, xmm1) vmovhpd(mem(rcx, rsi, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(rcx )) // store ( gamma00..gamma10 ) vmovhpd(xmm0, mem(rcx, rsi, 1)) // store ( gamma01..gamma11 ) vmovlpd(mem(rcx, rsi, 4), xmm1, xmm1) vmovhpd(mem(rcx, rbx, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm2) vmovlpd(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma14 ) vmovhpd(xmm2, mem(rcx, rbx, 1)) // store ( gamma05..gamma15 ) vunpckhps(ymm6, ymm4, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(mem(rcx, rsi, 2), xmm1, xmm1) vmovhpd(mem(rcx, rax, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma12 ) vmovhpd(xmm0, mem(rcx, rax, 1)) // store ( gamma03..gamma13 ) vmovlpd(mem(rcx, rax, 2), xmm1, xmm1) vmovhpd(mem(rcx, rbp, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm2) vmovlpd(xmm2, mem(rcx, rax, 2)) // store ( gamma06..gamma16 ) vmovhpd(xmm2, mem(rcx, rbp, 1)) // store ( gamma07..gamma17 ) lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c // begin I/O on columns 8-15 vunpcklps(ymm7, ymm5, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(mem(rcx ), xmm1, xmm1) vmovhpd(mem(rcx, rsi, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(rcx )) // store ( gamma00..gamma10 ) vmovhpd(xmm0, mem(rcx, rsi, 1)) // store ( gamma01..gamma11 ) vmovlpd(mem(rcx, rsi, 4), xmm1, xmm1) vmovhpd(mem(rcx, rbx, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm2) vmovlpd(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma14 ) vmovhpd(xmm2, mem(rcx, rbx, 1)) // store ( gamma05..gamma15 ) vunpckhps(ymm7, ymm5, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(mem(rcx, rsi, 2), xmm1, xmm1) vmovhpd(mem(rcx, rax, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma12 ) vmovhpd(xmm0, mem(rcx, rax, 1)) // store ( gamma03..gamma13 ) vmovlpd(mem(rcx, rax, 2), xmm1, xmm1) vmovhpd(mem(rcx, rbp, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm2) vmovlpd(xmm2, mem(rcx, rax, 2)) // store ( gamma06..gamma16 ) vmovhpd(xmm2, mem(rcx, rbp, 1)) // store ( gamma07..gamma17 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (8*rs_c) == 8. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovups(ymm4, mem(rcx, 0*32)) vmovups(ymm5, mem(rcx, 1*32)) add(rdi, rcx) vmovups(ymm6, mem(rcx, 0*32)) vmovups(ymm7, mem(rcx, 1*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) // begin I/O on columns 0-7 vunpcklps(ymm6, ymm4, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(xmm0, mem(rcx )) // store ( gamma00..gamma10 ) vmovhpd(xmm0, mem(rcx, rsi, 1)) // store ( gamma01..gamma11 ) vmovlpd(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma14 ) vmovhpd(xmm2, mem(rcx, rbx, 1)) // store ( gamma05..gamma15 ) vunpckhps(ymm6, ymm4, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma12 ) vmovhpd(xmm0, mem(rcx, rax, 1)) // store ( gamma03..gamma13 ) vmovlpd(xmm2, mem(rcx, rax, 2)) // store ( gamma06..gamma16 ) vmovhpd(xmm2, mem(rcx, rbp, 1)) // store ( gamma07..gamma17 ) lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c // begin I/O on columns 8-15 vunpcklps(ymm7, ymm5, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(xmm0, mem(rcx )) // store ( gamma00..gamma10 ) vmovhpd(xmm0, mem(rcx, rsi, 1)) // store ( gamma01..gamma11 ) vmovlpd(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma14 ) vmovhpd(xmm2, mem(rcx, rbx, 1)) // store ( gamma05..gamma15 ) vunpckhps(ymm7, ymm5, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma12 ) vmovhpd(xmm0, mem(rcx, rax, 1)) // store ( gamma03..gamma13 ) vmovlpd(xmm2, mem(rcx, rax, 2)) // store ( gamma06..gamma16 ) vmovhpd(xmm2, mem(rcx, rbp, 1)) // store ( gamma07..gamma17 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c label(.SDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_sgemmsup_rv_haswell_asm_1x16 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) //lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored prefetching on c //lea(mem(rcx, rdi, 2), rdx) // //lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c jmp(.SPOSTPFETCH) // jump to end of prefetching c label(.SCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) lea(mem(rsi, rsi, 2), rbp) // rbp = 3*cs_c; prefetch(0, mem(rcx, 0*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 0*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 0*8)) // prefetch c + 2*cs_c prefetch(0, mem(rcx, rbp, 1, 0*8)) // prefetch c + 3*cs_c prefetch(0, mem(rcx, rsi, 4, 0*8)) // prefetch c + 4*cs_c lea(mem(rcx, rsi, 4), rdx) // rdx = c + 4*cs_c; prefetch(0, mem(rdx, rsi, 1, 0*8)) // prefetch c + 5*cs_c prefetch(0, mem(rdx, rsi, 2, 0*8)) // prefetch c + 6*cs_c prefetch(0, mem(rdx, rbp, 1, 0*8)) // prefetch c + 7*cs_c prefetch(0, mem(rdx, rsi, 4, 0*8)) // prefetch c + 8*cs_c lea(mem(rcx, rsi, 8), rdx) // rdx = c + 8*cs_c; prefetch(0, mem(rdx, rsi, 1, 0*8)) // prefetch c + 9*cs_c prefetch(0, mem(rdx, rsi, 2, 0*8)) // prefetch c + 10*cs_c prefetch(0, mem(rdx, rbp, 1, 0*8)) // prefetch c + 11*cs_c prefetch(0, mem(rdx, rsi, 4, 0*8)) // prefetch c + 12*cs_c lea(mem(rcx, rcx, 4), rdx) // rdx = c + 12*cs_c; prefetch(0, mem(rdx, rsi, 1, 0*8)) // prefetch c + 13*cs_c prefetch(0, mem(rdx, rsi, 2, 0*8)) // prefetch c + 14*cs_c prefetch(0, mem(rdx, rbp, 1, 0*8)) // prefetch c + 15*cs_c label(.SPOSTPFETCH) // done prefetching c #if 1 lea(mem(rax, r9, 8), rdx) // lea(mem(rdx, r9, 8), rdx) // rdx = a + 16*cs_a; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(rdx, 4*8)) #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, r9, 1, 4*8)) #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(rdx, r9, 2, 4*8)) #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) // ---------------------------------- iteration 3 #if 1 lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP #if 0 prefetch(0, mem(rdx, 5*8)) add(r9, rdx) #endif vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), ymm0) // load alpha and duplicate vbroadcastss(mem(rbx), ymm3) // load beta and duplicate vmulps(ymm0, ymm4, ymm4) // scale by alpha vmulps(ymm0, ymm5, ymm5) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; //lea(mem(rcx, rdi, 2), rdx) // load address of c + 2*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; lea(mem(rsi, rsi, 4), rbx) // rbx = 5*cs_c; lea(mem(rax, rsi, 4), rbp) // rbp = 7*cs_c; // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm4) vmovups(ymm4, mem(rcx, 0*32)) vfmadd231ps(mem(rcx, 1*32), ymm3, ymm5) vmovups(ymm5, mem(rcx, 1*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORED) // begin I/O on columns 0-7 vmovups(ymm4, ymm0) vextractf128(imm(0x1), ymm0, xmm8) vpermilps(imm(0xe4), xmm0, xmm2) vpermilps(imm(0x39), xmm0, xmm4) vmovss(mem(rcx ), xmm1) vmovss(mem(rcx, rsi, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rcx )) // store ( gamma40 ) vmovss(xmm4, mem(rcx, rsi, 1)) // store ( gamma41 ) vpermilps(imm(0x4e), xmm0, xmm2) vpermilps(imm(0x93), xmm0, xmm4) vmovss(mem(rcx, rsi, 2), xmm1) vmovss(mem(rcx, rax, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rcx, rsi, 2)) // store ( gamma42 ) vmovss(xmm4, mem(rcx, rax, 1)) // store ( gamma43 ) vpermilps(imm(0xe4), xmm8, xmm2) vpermilps(imm(0x39), xmm8, xmm4) vmovss(mem(rcx, rsi, 4), xmm1) vmovss(mem(rcx, rbx, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rcx, rsi, 4)) // store ( gamma44 ) vmovss(xmm4, mem(rcx, rbx, 1)) // store ( gamma45 ) vpermilps(imm(0x4e), xmm8, xmm2) vpermilps(imm(0x93), xmm8, xmm4) vmovss(mem(rcx, rax, 2), xmm1) vmovss(mem(rcx, rbp, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rcx, rax, 2)) // store ( gamma46 ) vmovss(xmm4, mem(rcx, rbp, 1)) // store ( gamma47 ) lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c // begin I/O on columns 8-15 vmovups(ymm5, ymm0) vextractf128(imm(0x1), ymm0, xmm8) vpermilps(imm(0xe4), xmm0, xmm2) vpermilps(imm(0x39), xmm0, xmm4) vmovss(mem(rcx ), xmm1) vmovss(mem(rcx, rsi, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rcx )) // store ( gamma40 ) vmovss(xmm4, mem(rcx, rsi, 1)) // store ( gamma41 ) vpermilps(imm(0x4e), xmm0, xmm2) vpermilps(imm(0x93), xmm0, xmm4) vmovss(mem(rcx, rsi, 2), xmm1) vmovss(mem(rcx, rax, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rcx, rsi, 2)) // store ( gamma42 ) vmovss(xmm4, mem(rcx, rax, 1)) // store ( gamma43 ) vpermilps(imm(0xe4), xmm8, xmm2) vpermilps(imm(0x39), xmm8, xmm4) vmovss(mem(rcx, rsi, 4), xmm1) vmovss(mem(rcx, rbx, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rcx, rsi, 4)) // store ( gamma44 ) vmovss(xmm4, mem(rcx, rbx, 1)) // store ( gamma45 ) vpermilps(imm(0x4e), xmm8, xmm2) vpermilps(imm(0x93), xmm8, xmm4) vmovss(mem(rcx, rax, 2), xmm1) vmovss(mem(rcx, rbp, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rcx, rax, 2)) // store ( gamma46 ) vmovss(xmm4, mem(rcx, rbp, 1)) // store ( gamma47 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (8*rs_c) == 8. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovups(ymm4, mem(rcx, 0*32)) vmovups(ymm5, mem(rcx, 1*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) // begin I/O on columns 0-7 vmovups(ymm4, ymm0) vextractf128(imm(0x1), ymm0, xmm8) vpermilps(imm(0xe4), xmm0, xmm2) vpermilps(imm(0x39), xmm0, xmm4) vmovss(xmm2, mem(rcx )) // store ( gamma40 ) vmovss(xmm4, mem(rcx, rsi, 1)) // store ( gamma41 ) vpermilps(imm(0x4e), xmm0, xmm2) vpermilps(imm(0x93), xmm0, xmm4) vmovss(xmm2, mem(rcx, rsi, 2)) // store ( gamma42 ) vmovss(xmm4, mem(rcx, rax, 1)) // store ( gamma43 ) vpermilps(imm(0xe4), xmm8, xmm2) vpermilps(imm(0x39), xmm8, xmm4) vmovss(xmm2, mem(rcx, rsi, 4)) // store ( gamma44 ) vmovss(xmm4, mem(rcx, rbx, 1)) // store ( gamma45 ) vpermilps(imm(0x4e), xmm8, xmm2) vpermilps(imm(0x93), xmm8, xmm4) vmovss(xmm2, mem(rcx, rax, 2)) // store ( gamma46 ) vmovss(xmm4, mem(rcx, rbp, 1)) // store ( gamma47 ) lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c // begin I/O on columns 8-15 vmovups(ymm5, ymm0) vextractf128(imm(0x1), ymm0, xmm8) vpermilps(imm(0xe4), xmm0, xmm2) vpermilps(imm(0x39), xmm0, xmm4) vmovss(xmm2, mem(rcx )) // store ( gamma40 ) vmovss(xmm4, mem(rcx, rsi, 1)) // store ( gamma41 ) vpermilps(imm(0x4e), xmm0, xmm2) vpermilps(imm(0x93), xmm0, xmm4) vmovss(xmm2, mem(rcx, rsi, 2)) // store ( gamma42 ) vmovss(xmm4, mem(rcx, rax, 1)) // store ( gamma43 ) vpermilps(imm(0xe4), xmm8, xmm2) vpermilps(imm(0x39), xmm8, xmm4) vmovss(xmm2, mem(rcx, rsi, 4)) // store ( gamma44 ) vmovss(xmm4, mem(rcx, rbx, 1)) // store ( gamma45 ) vpermilps(imm(0x4e), xmm8, xmm2) vpermilps(imm(0x93), xmm8, xmm4) vmovss(xmm2, mem(rcx, rax, 2)) // store ( gamma46 ) vmovss(xmm4, mem(rcx, rbp, 1)) // store ( gamma47 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c label(.SDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } blis-0.9.0/kernels/haswell/3/sup/s6x16/bli_gemmsup_rv_haswell_asm_sMx2.c000066400000000000000000002055351422157504600261010ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define BLIS_ASM_SYNTAX_ATT #include "bli_x86_asm_macros.h" /* rrr: -------- ------ -------- -------- ------ -------- -------- += ------ ... -------- -------- ------ -------- -------- ------ : -------- ------ : rcr: -------- | | | | -------- -------- | | | | -------- -------- += | | | | ... -------- -------- | | | | -------- -------- | | | | : -------- | | | | : Assumptions: - B is row-stored; - A is row- or column-stored; - m0 and n0 are at most MR and NR, respectively. Therefore, this (r)ow-preferential kernel is well-suited for contiguous (v)ector loads on B and single-element broadcasts from A. NOTE: These kernels explicitly support column-oriented IO, implemented via an in-register transpose. And thus they also support the crr and ccr cases, though only crr is ever utilized (because ccr is handled by transposing the operation and executing rcr, which does not incur the cost of the in-register transpose). crr: | | | | | | | | ------ -------- | | | | | | | | ------ -------- | | | | | | | | += ------ ... -------- | | | | | | | | ------ -------- | | | | | | | | ------ : | | | | | | | | ------ : */ // Prototype reference microkernels. GEMMSUP_KER_PROT( float, s, gemmsup_r_haswell_ref ) void bli_sgemmsup_rv_haswell_asm_6x2 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) //lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored prefetching on c lea(mem(rcx, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 1*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 1*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 1*8)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 1*8)) // prefetch c + 3*rs_c prefetch(0, mem(rdx, rdi, 1, 1*8)) // prefetch c + 4*rs_c prefetch(0, mem(rdx, rdi, 2, 1*8)) // prefetch c + 5*rs_c jmp(.SPOSTPFETCH) // jump to end of prefetching c label(.SCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) //lea(mem(rsi, rsi, 2), rbp) // rbp = 3*cs_c; prefetch(0, mem(rcx, 5*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 5*8)) // prefetch c + 1*cs_c label(.SPOSTPFETCH) // done prefetching c #if 1 lea(mem(rax, r9, 8), rdx) // lea(mem(rdx, r9, 8), rdx) // rdx = a + 16*cs_a; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(rdx, 5*8)) #endif vmovsd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) vbroadcastss(mem(rax, r13, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm8) vfmadd231ps(xmm0, xmm3, xmm10) vbroadcastss(mem(rax, r8, 4), xmm2) vbroadcastss(mem(rax, r15, 1), xmm3) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm12) vfmadd231ps(xmm0, xmm3, xmm14) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, r9, 1, 5*8)) #endif vmovsd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) vbroadcastss(mem(rax, r13, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm8) vfmadd231ps(xmm0, xmm3, xmm10) vbroadcastss(mem(rax, r8, 4), xmm2) vbroadcastss(mem(rax, r15, 1), xmm3) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm12) vfmadd231ps(xmm0, xmm3, xmm14) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(rdx, r9, 2, 5*8)) #endif vmovsd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) vbroadcastss(mem(rax, r13, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm8) vfmadd231ps(xmm0, xmm3, xmm10) vbroadcastss(mem(rax, r8, 4), xmm2) vbroadcastss(mem(rax, r15, 1), xmm3) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm12) vfmadd231ps(xmm0, xmm3, xmm14) // ---------------------------------- iteration 3 #if 1 lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; #endif vmovsd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) vbroadcastss(mem(rax, r13, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm8) vfmadd231ps(xmm0, xmm3, xmm10) vbroadcastss(mem(rax, r8, 4), xmm2) vbroadcastss(mem(rax, r15, 1), xmm3) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm12) vfmadd231ps(xmm0, xmm3, xmm14) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP #if 0 prefetch(0, mem(rdx, 5*8)) add(r9, rdx) #endif vmovsd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) vbroadcastss(mem(rax, r13, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm8) vfmadd231ps(xmm0, xmm3, xmm10) vbroadcastss(mem(rax, r8, 4), xmm2) vbroadcastss(mem(rax, r15, 1), xmm3) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm12) vfmadd231ps(xmm0, xmm3, xmm14) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), xmm0) // load alpha and duplicate vbroadcastss(mem(rbx), xmm3) // load beta and duplicate vmulps(xmm0, xmm4, xmm4) // scale by alpha vmulps(xmm0, xmm6, xmm6) vmulps(xmm0, xmm8, xmm8) vmulps(xmm0, xmm10, xmm10) vmulps(xmm0, xmm12, xmm12) vmulps(xmm0, xmm14, xmm14) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; //lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; //lea(mem(rsi, rsi, 4), rbx) // rbx = 5*cs_c; //lea(mem(rax, rsi, 4), rbp) // rbp = 7*cs_c; // now avoid loading C if beta == 0 vxorps(xmm0, xmm0, xmm0) // set xmm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vfmadd231ps(mem(rcx, 0*32), xmm3, xmm4) vmovsd(xmm4, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), xmm3, xmm6) vmovsd(xmm6, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), xmm3, xmm8) vmovsd(xmm8, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), xmm3, xmm10) vmovsd(xmm10, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), xmm3, xmm12) vmovsd(xmm12, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), xmm3, xmm14) vmovsd(xmm14, mem(rcx, 0*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORED) // begin I/O on columns 0-1 vunpcklps(xmm6, xmm4, xmm0) vunpcklps(xmm10, xmm8, xmm1) vshufps(imm(0x4e), xmm1, xmm0, xmm2) vblendps(imm(0xcc), xmm2, xmm0, xmm0) vblendps(imm(0x33), xmm2, xmm1, xmm1) vfmadd231ps(mem(rcx ), xmm3, xmm0) vmovups(xmm0, mem(rcx )) // store ( gamma00..gamma30 ) vfmadd231ps(mem(rcx, rsi, 1), xmm3, xmm1) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vunpcklps(xmm14, xmm12, xmm0) vmovlpd(mem(rdx ), xmm1, xmm1) vmovhpd(mem(rdx, rsi, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(rdx )) // store ( gamma40..gamma50 ) vmovhpd(xmm0, mem(rdx, rsi, 1)) // store ( gamma41..gamma51 ) //lea(mem(rdx, rsi, 8), rdx) // rdx += 8*cs_c jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovsd(xmm4, mem(rcx, 0*32)) add(rdi, rcx) vmovsd(xmm6, mem(rcx, 0*32)) add(rdi, rcx) vmovsd(xmm8, mem(rcx, 0*32)) add(rdi, rcx) vmovsd(xmm10, mem(rcx, 0*32)) add(rdi, rcx) vmovsd(xmm12, mem(rcx, 0*32)) add(rdi, rcx) vmovsd(xmm14, mem(rcx, 0*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) // begin I/O on columns 0-1 vunpcklps(xmm6, xmm4, xmm0) vunpcklps(xmm10, xmm8, xmm1) vshufps(imm(0x4e), xmm1, xmm0, xmm2) vblendps(imm(0xcc), xmm2, xmm0, xmm0) vblendps(imm(0x33), xmm2, xmm1, xmm1) vmovups(xmm0, mem(rcx )) // store ( gamma00..gamma30 ) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vunpcklps(xmm14, xmm12, xmm0) vmovlpd(xmm0, mem(rdx )) // store ( gamma40..gamma50 ) vmovhpd(xmm0, mem(rdx, rsi, 1)) // store ( gamma41..gamma51 ) //lea(mem(rdx, rsi, 8), rdx) // rdx += 8*cs_c label(.SDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_sgemmsup_rv_haswell_asm_5x2 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) //lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored prefetching on c lea(mem(rcx, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 1*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 1*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 1*8)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 1*8)) // prefetch c + 3*rs_c prefetch(0, mem(rdx, rdi, 1, 1*8)) // prefetch c + 4*rs_c jmp(.SPOSTPFETCH) // jump to end of prefetching c label(.SCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) //lea(mem(rsi, rsi, 2), rbp) // rbp = 3*cs_c; prefetch(0, mem(rcx, 4*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 4*8)) // prefetch c + 1*cs_c label(.SPOSTPFETCH) // done prefetching c #if 1 lea(mem(rax, r9, 8), rdx) // lea(mem(rdx, r9, 8), rdx) // rdx = a + 16*cs_a; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(rdx, 5*8)) #endif vmovsd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) vbroadcastss(mem(rax, r13, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm8) vfmadd231ps(xmm0, xmm3, xmm10) vbroadcastss(mem(rax, r8, 4), xmm2) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm12) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, r9, 1, 5*8)) #endif vmovsd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) vbroadcastss(mem(rax, r13, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm8) vfmadd231ps(xmm0, xmm3, xmm10) vbroadcastss(mem(rax, r8, 4), xmm2) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm12) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(rdx, r9, 2, 5*8)) #endif vmovsd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) vbroadcastss(mem(rax, r13, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm8) vfmadd231ps(xmm0, xmm3, xmm10) vbroadcastss(mem(rax, r8, 4), xmm2) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm12) // ---------------------------------- iteration 3 #if 1 lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; #endif vmovsd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) vbroadcastss(mem(rax, r13, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm8) vfmadd231ps(xmm0, xmm3, xmm10) vbroadcastss(mem(rax, r8, 4), xmm2) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm12) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP #if 0 prefetch(0, mem(rdx, 5*8)) add(r9, rdx) #endif vmovsd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) vbroadcastss(mem(rax, r13, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm8) vfmadd231ps(xmm0, xmm3, xmm10) vbroadcastss(mem(rax, r8, 4), xmm2) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm12) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), xmm0) // load alpha and duplicate vbroadcastss(mem(rbx), xmm3) // load beta and duplicate vmulps(xmm0, xmm4, xmm4) // scale by alpha vmulps(xmm0, xmm6, xmm6) vmulps(xmm0, xmm8, xmm8) vmulps(xmm0, xmm10, xmm10) vmulps(xmm0, xmm12, xmm12) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; //lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; //lea(mem(rsi, rsi, 4), rbx) // rbx = 5*cs_c; //lea(mem(rax, rsi, 4), rbp) // rbp = 7*cs_c; // now avoid loading C if beta == 0 vxorps(xmm0, xmm0, xmm0) // set xmm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vfmadd231ps(mem(rcx, 0*32), xmm3, xmm4) vmovsd(xmm4, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), xmm3, xmm6) vmovsd(xmm6, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), xmm3, xmm8) vmovsd(xmm8, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), xmm3, xmm10) vmovsd(xmm10, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), xmm3, xmm12) vmovsd(xmm12, mem(rcx, 0*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORED) // begin I/O on columns 0-1 vunpcklps(xmm6, xmm4, xmm0) vunpcklps(xmm10, xmm8, xmm1) vshufps(imm(0x4e), xmm1, xmm0, xmm2) vblendps(imm(0xcc), xmm2, xmm0, xmm0) vblendps(imm(0x33), xmm2, xmm1, xmm1) vfmadd231ps(mem(rcx ), xmm3, xmm0) vmovups(xmm0, mem(rcx )) // store ( gamma00..gamma30 ) vfmadd231ps(mem(rcx, rsi, 1), xmm3, xmm1) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vmovups(xmm12, xmm0) vpermilps(imm(0xe4), xmm0, xmm2) vpermilps(imm(0x39), xmm0, xmm4) vmovss(mem(rdx ), xmm1) vmovss(mem(rdx, rsi, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rdx )) // store ( gamma40 ) vmovss(xmm4, mem(rdx, rsi, 1)) // store ( gamma41 ) //lea(mem(rdx, rsi, 8), rdx) // rdx += 8*cs_c jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovsd(xmm4, mem(rcx, 0*32)) add(rdi, rcx) vmovsd(xmm6, mem(rcx, 0*32)) add(rdi, rcx) vmovsd(xmm8, mem(rcx, 0*32)) add(rdi, rcx) vmovsd(xmm10, mem(rcx, 0*32)) add(rdi, rcx) vmovsd(xmm12, mem(rcx, 0*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) // begin I/O on columns 0-1 vunpcklps(xmm6, xmm4, xmm0) vunpcklps(xmm10, xmm8, xmm1) vshufps(imm(0x4e), xmm1, xmm0, xmm2) vblendps(imm(0xcc), xmm2, xmm0, xmm0) vblendps(imm(0x33), xmm2, xmm1, xmm1) vmovups(xmm0, mem(rcx )) // store ( gamma00..gamma30 ) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vmovups(xmm12, xmm0) vpermilps(imm(0xe4), xmm0, xmm2) vpermilps(imm(0x39), xmm0, xmm4) vmovss(xmm2, mem(rdx )) // store ( gamma40 ) vmovss(xmm4, mem(rdx, rsi, 1)) // store ( gamma41 ) //lea(mem(rdx, rsi, 8), rdx) // rdx += 8*cs_c label(.SDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_sgemmsup_rv_haswell_asm_4x2 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) //lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored prefetching on c lea(mem(rcx, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 1*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 1*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 1*8)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 1*8)) // prefetch c + 3*rs_c jmp(.SPOSTPFETCH) // jump to end of prefetching c label(.SCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) //lea(mem(rsi, rsi, 2), rbp) // rbp = 3*cs_c; prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 3*8)) // prefetch c + 1*cs_c label(.SPOSTPFETCH) // done prefetching c #if 1 lea(mem(rax, r9, 8), rdx) // lea(mem(rdx, r9, 8), rdx) // rdx = a + 16*cs_a; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(rdx, 5*8)) #endif vmovsd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) vbroadcastss(mem(rax, r13, 1), xmm3) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm8) vfmadd231ps(xmm0, xmm3, xmm10) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, r9, 1, 5*8)) #endif vmovsd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) vbroadcastss(mem(rax, r13, 1), xmm3) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm8) vfmadd231ps(xmm0, xmm3, xmm10) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(rdx, r9, 2, 5*8)) #endif vmovsd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) vbroadcastss(mem(rax, r13, 1), xmm3) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm8) vfmadd231ps(xmm0, xmm3, xmm10) // ---------------------------------- iteration 3 #if 1 lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; #endif vmovsd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) vbroadcastss(mem(rax, r13, 1), xmm3) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm8) vfmadd231ps(xmm0, xmm3, xmm10) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP #if 0 prefetch(0, mem(rdx, 5*8)) add(r9, rdx) #endif vmovsd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) vbroadcastss(mem(rax, r13, 1), xmm3) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm8) vfmadd231ps(xmm0, xmm3, xmm10) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), xmm0) // load alpha and duplicate vbroadcastss(mem(rbx), xmm3) // load beta and duplicate vmulps(xmm0, xmm4, xmm4) // scale by alpha vmulps(xmm0, xmm6, xmm6) vmulps(xmm0, xmm8, xmm8) vmulps(xmm0, xmm10, xmm10) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; //lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; //lea(mem(rsi, rsi, 4), rbx) // rbx = 5*cs_c; //lea(mem(rax, rsi, 4), rbp) // rbp = 7*cs_c; // now avoid loading C if beta == 0 vxorps(xmm0, xmm0, xmm0) // set xmm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vfmadd231ps(mem(rcx, 0*32), xmm3, xmm4) vmovsd(xmm4, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), xmm3, xmm6) vmovsd(xmm6, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), xmm3, xmm8) vmovsd(xmm8, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), xmm3, xmm10) vmovsd(xmm10, mem(rcx, 0*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORED) // begin I/O on columns 0-1 vunpcklps(xmm6, xmm4, xmm0) vunpcklps(xmm10, xmm8, xmm1) vshufps(imm(0x4e), xmm1, xmm0, xmm2) vblendps(imm(0xcc), xmm2, xmm0, xmm0) vblendps(imm(0x33), xmm2, xmm1, xmm1) vfmadd231ps(mem(rcx ), xmm3, xmm0) vmovups(xmm0, mem(rcx )) // store ( gamma00..gamma30 ) vfmadd231ps(mem(rcx, rsi, 1), xmm3, xmm1) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovsd(xmm4, mem(rcx, 0*32)) add(rdi, rcx) vmovsd(xmm6, mem(rcx, 0*32)) add(rdi, rcx) vmovsd(xmm8, mem(rcx, 0*32)) add(rdi, rcx) vmovsd(xmm10, mem(rcx, 0*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) // begin I/O on columns 0-1 vunpcklps(xmm6, xmm4, xmm0) vunpcklps(xmm10, xmm8, xmm1) vshufps(imm(0x4e), xmm1, xmm0, xmm2) vblendps(imm(0xcc), xmm2, xmm0, xmm0) vblendps(imm(0x33), xmm2, xmm1, xmm1) vmovups(xmm0, mem(rcx )) // store ( gamma00..gamma30 ) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c label(.SDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_sgemmsup_rv_haswell_asm_3x2 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) //lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored prefetching on c //lea(mem(rcx, rdi, 2), rdx) // //lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 1*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 1*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 1*8)) // prefetch c + 2*rs_c jmp(.SPOSTPFETCH) // jump to end of prefetching c label(.SCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) //lea(mem(rsi, rsi, 2), rbp) // rbp = 3*cs_c; prefetch(0, mem(rcx, 2*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 2*8)) // prefetch c + 1*cs_c label(.SPOSTPFETCH) // done prefetching c #if 1 lea(mem(rax, r9, 8), rdx) // lea(mem(rdx, r9, 8), rdx) // rdx = a + 16*cs_a; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(rdx, 5*8)) #endif vmovsd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm8) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, r9, 1, 5*8)) #endif vmovsd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm8) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(rdx, r9, 2, 5*8)) #endif vmovsd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm8) // ---------------------------------- iteration 3 #if 1 lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; #endif vmovsd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm8) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP #if 0 prefetch(0, mem(rdx, 5*8)) add(r9, rdx) #endif vmovsd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm8) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), xmm0) // load alpha and duplicate vbroadcastss(mem(rbx), xmm3) // load beta and duplicate vmulps(xmm0, xmm4, xmm4) // scale by alpha vmulps(xmm0, xmm6, xmm6) vmulps(xmm0, xmm8, xmm8) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; lea(mem(rcx, rdi, 2), rdx) // load address of c + 2*rs_c; //lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; //lea(mem(rsi, rsi, 4), rbx) // rbx = 5*cs_c; //lea(mem(rax, rsi, 4), rbp) // rbp = 7*cs_c; // now avoid loading C if beta == 0 vxorps(xmm0, xmm0, xmm0) // set xmm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vfmadd231ps(mem(rcx, 0*32), xmm3, xmm4) vmovsd(xmm4, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), xmm3, xmm6) vmovsd(xmm6, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), xmm3, xmm8) vmovsd(xmm8, mem(rcx, 0*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORED) // begin I/O on columns 0-1 vunpcklps(xmm6, xmm4, xmm0) vmovlpd(mem(rcx ), xmm1, xmm1) vmovhpd(mem(rcx, rsi, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(rcx )) // store ( gamma00..gamma10 ) vmovhpd(xmm0, mem(rcx, rsi, 1)) // store ( gamma01..gamma11 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vmovups(xmm8, xmm0) vpermilps(imm(0xe4), xmm0, xmm2) vpermilps(imm(0x39), xmm0, xmm4) vmovss(mem(rdx ), xmm1) vmovss(mem(rdx, rsi, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rdx )) // store ( gamma40 ) vmovss(xmm4, mem(rdx, rsi, 1)) // store ( gamma41 ) //lea(mem(rdx, rsi, 8), rdx) // rdx += 8*cs_c jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovsd(xmm4, mem(rcx, 0*32)) add(rdi, rcx) vmovsd(xmm6, mem(rcx, 0*32)) add(rdi, rcx) vmovsd(xmm8, mem(rcx, 0*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) // begin I/O on columns 0-1 vunpcklps(xmm6, xmm4, xmm0) vmovlpd(xmm0, mem(rcx )) // store ( gamma00..gamma10 ) vmovhpd(xmm0, mem(rcx, rsi, 1)) // store ( gamma01..gamma11 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vmovups(xmm8, xmm0) vpermilps(imm(0xe4), xmm0, xmm2) vpermilps(imm(0x39), xmm0, xmm4) vmovss(xmm2, mem(rdx )) // store ( gamma40 ) vmovss(xmm4, mem(rdx, rsi, 1)) // store ( gamma41 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c label(.SDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_sgemmsup_rv_haswell_asm_2x2 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) //lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored prefetching on c //lea(mem(rcx, rdi, 2), rdx) // //lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 1*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 1*8)) // prefetch c + 1*rs_c jmp(.SPOSTPFETCH) // jump to end of prefetching c label(.SCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) //lea(mem(rsi, rsi, 2), rbp) // rbp = 3*cs_c; prefetch(0, mem(rcx, 1*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 1*8)) // prefetch c + 1*cs_c label(.SPOSTPFETCH) // done prefetching c #if 1 lea(mem(rax, r9, 8), rdx) // lea(mem(rdx, r9, 8), rdx) // rdx = a + 16*cs_a; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(rdx, 5*8)) #endif vmovsd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, r9, 1, 5*8)) #endif vmovsd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(rdx, r9, 2, 5*8)) #endif vmovsd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) // ---------------------------------- iteration 3 #if 1 lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; #endif vmovsd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP #if 0 prefetch(0, mem(rdx, 5*8)) add(r9, rdx) #endif vmovsd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), xmm0) // load alpha and duplicate vbroadcastss(mem(rbx), xmm3) // load beta and duplicate vmulps(xmm0, xmm4, xmm4) // scale by alpha vmulps(xmm0, xmm6, xmm6) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; //lea(mem(rcx, rdi, 2), rdx) // load address of c + 4*rs_c; //lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; //lea(mem(rsi, rsi, 4), rbx) // rbx = 5*cs_c; //lea(mem(rax, rsi, 4), rbp) // rbp = 7*cs_c; // now avoid loading C if beta == 0 vxorps(xmm0, xmm0, xmm0) // set xmm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vfmadd231ps(mem(rcx, 0*32), xmm3, xmm4) vmovsd(xmm4, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), xmm3, xmm6) vmovsd(xmm6, mem(rcx, 0*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORED) // begin I/O on columns 0-1 vunpcklps(xmm6, xmm4, xmm0) vmovlpd(mem(rcx ), xmm1, xmm1) vmovhpd(mem(rcx, rsi, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(rcx )) // store ( gamma00..gamma10 ) vmovhpd(xmm0, mem(rcx, rsi, 1)) // store ( gamma01..gamma11 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovsd(xmm4, mem(rcx, 0*32)) add(rdi, rcx) vmovsd(xmm6, mem(rcx, 0*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) // begin I/O on columns 0-1 vunpcklps(xmm6, xmm4, xmm0) vmovlpd(xmm0, mem(rcx )) // store ( gamma00..gamma10 ) vmovhpd(xmm0, mem(rcx, rsi, 1)) // store ( gamma01..gamma11 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c label(.SDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_sgemmsup_rv_haswell_asm_1x2 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) //lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored prefetching on c //lea(mem(rcx, rdi, 2), rdx) // //lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 1*8)) // prefetch c + 0*rs_c jmp(.SPOSTPFETCH) // jump to end of prefetching c label(.SCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) //lea(mem(rsi, rsi, 2), rbp) // rbp = 3*cs_c; prefetch(0, mem(rcx, 0*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 0*8)) // prefetch c + 1*cs_c label(.SPOSTPFETCH) // done prefetching c #if 1 lea(mem(rax, r9, 8), rdx) // lea(mem(rdx, r9, 8), rdx) // rdx = a + 16*cs_a; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(rdx, 5*8)) #endif vmovsd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm4) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, r9, 1, 5*8)) #endif vmovsd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm4) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(rdx, r9, 2, 5*8)) #endif vmovsd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm4) // ---------------------------------- iteration 3 #if 1 lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; #endif vmovsd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm4) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP #if 0 prefetch(0, mem(rdx, 5*8)) add(r9, rdx) #endif vmovsd(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm4) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), xmm0) // load alpha and duplicate vbroadcastss(mem(rbx), xmm3) // load beta and duplicate vmulps(xmm0, xmm4, xmm4) // scale by alpha mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; //lea(mem(rcx, rdi, 2), rdx) // load address of c + 4*rs_c; //lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; //lea(mem(rsi, rsi, 4), rbx) // rbx = 5*cs_c; //lea(mem(rax, rsi, 4), rbp) // rbp = 7*cs_c; // now avoid loading C if beta == 0 vxorps(xmm0, xmm0, xmm0) // set xmm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vfmadd231ps(mem(rcx, 0*32), xmm3, xmm4) vmovsd(xmm4, mem(rcx, 0*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORED) // begin I/O on columns 0-1 vmovups(xmm4, xmm0) vpermilps(imm(0xe4), xmm0, xmm2) vpermilps(imm(0x39), xmm0, xmm4) vmovss(mem(rcx ), xmm1) vmovss(mem(rcx, rsi, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rcx )) // store ( gamma00 ) vmovss(xmm4, mem(rcx, rsi, 1)) // store ( gamma01 ) //lea(mem(rdx, rsi, 8), rdx) // rdx += 8*cs_c jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovsd(xmm4, mem(rcx, 0*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) // begin I/O on columns 0-1 vmovups(xmm4, xmm0) vpermilps(imm(0xe4), xmm0, xmm2) vpermilps(imm(0x39), xmm0, xmm4) vmovss(xmm2, mem(rcx )) // store ( gamma00 ) vmovss(xmm4, mem(rcx, rsi, 1)) // store ( gamma01 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c label(.SDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } blis-0.9.0/kernels/haswell/3/sup/s6x16/bli_gemmsup_rv_haswell_asm_sMx4.c000066400000000000000000002205211422157504600260730ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define BLIS_ASM_SYNTAX_ATT #include "bli_x86_asm_macros.h" /* rrr: -------- ------ -------- -------- ------ -------- -------- += ------ ... -------- -------- ------ -------- -------- ------ : -------- ------ : rcr: -------- | | | | -------- -------- | | | | -------- -------- += | | | | ... -------- -------- | | | | -------- -------- | | | | : -------- | | | | : Assumptions: - B is row-stored; - A is row- or column-stored; - m0 and n0 are at most MR and NR, respectively. Therefore, this (r)ow-preferential kernel is well-suited for contiguous (v)ector loads on B and single-element broadcasts from A. NOTE: These kernels explicitly support column-oriented IO, implemented via an in-register transpose. And thus they also support the crr and ccr cases, though only crr is ever utilized (because ccr is handled by transposing the operation and executing rcr, which does not incur the cost of the in-register transpose). crr: | | | | | | | | ------ -------- | | | | | | | | ------ -------- | | | | | | | | += ------ ... -------- | | | | | | | | ------ -------- | | | | | | | | ------ : | | | | | | | | ------ : */ // Prototype reference microkernels. GEMMSUP_KER_PROT( float, s, gemmsup_r_haswell_ref ) void bli_sgemmsup_rv_haswell_asm_6x4 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) //lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored prefetching on c lea(mem(rcx, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 3*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 3*8)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 3*8)) // prefetch c + 3*rs_c prefetch(0, mem(rdx, rdi, 1, 3*8)) // prefetch c + 4*rs_c prefetch(0, mem(rdx, rdi, 2, 3*8)) // prefetch c + 5*rs_c jmp(.SPOSTPFETCH) // jump to end of prefetching c label(.SCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) lea(mem(rsi, rsi, 2), rbp) // rbp = 3*cs_c; prefetch(0, mem(rcx, 5*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 5*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 5*8)) // prefetch c + 2*cs_c prefetch(0, mem(rcx, rbp, 1, 5*8)) // prefetch c + 3*cs_c label(.SPOSTPFETCH) // done prefetching c #if 1 lea(mem(rax, r9, 8), rdx) // lea(mem(rdx, r9, 8), rdx) // rdx = a + 16*cs_a; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(rdx, 5*8)) #endif vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) vbroadcastss(mem(rax, r13, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm8) vfmadd231ps(xmm0, xmm3, xmm10) vbroadcastss(mem(rax, r8, 4), xmm2) vbroadcastss(mem(rax, r15, 1), xmm3) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm12) vfmadd231ps(xmm0, xmm3, xmm14) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, r9, 1, 5*8)) #endif vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) vbroadcastss(mem(rax, r13, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm8) vfmadd231ps(xmm0, xmm3, xmm10) vbroadcastss(mem(rax, r8, 4), xmm2) vbroadcastss(mem(rax, r15, 1), xmm3) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm12) vfmadd231ps(xmm0, xmm3, xmm14) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(rdx, r9, 2, 5*8)) #endif vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) vbroadcastss(mem(rax, r13, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm8) vfmadd231ps(xmm0, xmm3, xmm10) vbroadcastss(mem(rax, r8, 4), xmm2) vbroadcastss(mem(rax, r15, 1), xmm3) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm12) vfmadd231ps(xmm0, xmm3, xmm14) // ---------------------------------- iteration 3 #if 1 lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; #endif vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) vbroadcastss(mem(rax, r13, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm8) vfmadd231ps(xmm0, xmm3, xmm10) vbroadcastss(mem(rax, r8, 4), xmm2) vbroadcastss(mem(rax, r15, 1), xmm3) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm12) vfmadd231ps(xmm0, xmm3, xmm14) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP #if 0 prefetch(0, mem(rdx, 5*8)) add(r9, rdx) #endif vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) vbroadcastss(mem(rax, r13, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm8) vfmadd231ps(xmm0, xmm3, xmm10) vbroadcastss(mem(rax, r8, 4), xmm2) vbroadcastss(mem(rax, r15, 1), xmm3) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm12) vfmadd231ps(xmm0, xmm3, xmm14) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), xmm0) // load alpha and duplicate vbroadcastss(mem(rbx), xmm3) // load beta and duplicate vmulps(xmm0, xmm4, xmm4) // scale by alpha vmulps(xmm0, xmm6, xmm6) vmulps(xmm0, xmm8, xmm8) vmulps(xmm0, xmm10, xmm10) vmulps(xmm0, xmm12, xmm12) vmulps(xmm0, xmm14, xmm14) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; lea(mem(rsi, rsi, 4), rbx) // rbx = 5*cs_c; lea(mem(rax, rsi, 4), rbp) // rbp = 7*cs_c; // now avoid loading C if beta == 0 vxorps(xmm0, xmm0, xmm0) // set xmm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vfmadd231ps(mem(rcx, 0*32), xmm3, xmm4) vmovups(xmm4, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), xmm3, xmm6) vmovups(xmm6, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), xmm3, xmm8) vmovups(xmm8, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), xmm3, xmm10) vmovups(xmm10, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), xmm3, xmm12) vmovups(xmm12, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), xmm3, xmm14) vmovups(xmm14, mem(rcx, 0*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORED) // begin I/O on columns 0-3 vunpcklps(xmm6, xmm4, xmm0) vunpcklps(xmm10, xmm8, xmm1) vshufps(imm(0x4e), xmm1, xmm0, xmm2) vblendps(imm(0xcc), xmm2, xmm0, xmm0) vblendps(imm(0x33), xmm2, xmm1, xmm1) vfmadd231ps(mem(rcx ), xmm3, xmm0) vmovups(xmm0, mem(rcx )) // store ( gamma00..gamma30 ) vfmadd231ps(mem(rcx, rsi, 1), xmm3, xmm1) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) vunpckhps(xmm6, xmm4, xmm0) vunpckhps(xmm10, xmm8, xmm1) vshufps(imm(0x4e), xmm1, xmm0, xmm2) vblendps(imm(0xcc), xmm2, xmm0, xmm0) vblendps(imm(0x33), xmm2, xmm1, xmm1) vfmadd231ps(mem(rcx, rsi, 2), xmm3, xmm0) vmovups(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma32 ) vfmadd231ps(mem(rcx, rax, 1), xmm3, xmm1) vmovups(xmm1, mem(rcx, rax, 1)) // store ( gamma03..gamma33 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vunpcklps(xmm14, xmm12, xmm0) vmovlpd(mem(rdx ), xmm1, xmm1) vmovhpd(mem(rdx, rsi, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(rdx )) // store ( gamma40..gamma50 ) vmovhpd(xmm0, mem(rdx, rsi, 1)) // store ( gamma41..gamma51 ) vunpckhps(xmm14, xmm12, xmm0) vmovlpd(mem(rdx, rsi, 2), xmm1, xmm1) vmovhpd(mem(rdx, rax, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(rdx, rsi, 2)) // store ( gamma42..gamma52 ) vmovhpd(xmm0, mem(rdx, rax, 1)) // store ( gamma43..gamma53 ) //lea(mem(rdx, rsi, 8), rdx) // rdx += 8*cs_c jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovups(xmm4, mem(rcx, 0*32)) add(rdi, rcx) vmovups(xmm6, mem(rcx, 0*32)) add(rdi, rcx) vmovups(xmm8, mem(rcx, 0*32)) add(rdi, rcx) vmovups(xmm10, mem(rcx, 0*32)) add(rdi, rcx) vmovups(xmm12, mem(rcx, 0*32)) add(rdi, rcx) vmovups(xmm14, mem(rcx, 0*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) // begin I/O on columns 0-3 vunpcklps(xmm6, xmm4, xmm0) vunpcklps(xmm10, xmm8, xmm1) vshufps(imm(0x4e), xmm1, xmm0, xmm2) vblendps(imm(0xcc), xmm2, xmm0, xmm0) vblendps(imm(0x33), xmm2, xmm1, xmm1) vmovups(xmm0, mem(rcx )) // store ( gamma00..gamma30 ) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) vunpckhps(xmm6, xmm4, xmm0) vunpckhps(xmm10, xmm8, xmm1) vshufps(imm(0x4e), xmm1, xmm0, xmm2) vblendps(imm(0xcc), xmm2, xmm0, xmm0) vblendps(imm(0x33), xmm2, xmm1, xmm1) vmovups(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma32 ) vmovups(xmm1, mem(rcx, rax, 1)) // store ( gamma03..gamma33 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vunpcklps(xmm14, xmm12, xmm0) vmovlpd(xmm0, mem(rdx )) // store ( gamma40..gamma50 ) vmovhpd(xmm0, mem(rdx, rsi, 1)) // store ( gamma41..gamma51 ) vunpckhps(xmm14, xmm12, xmm0) vmovlpd(xmm0, mem(rdx, rsi, 2)) // store ( gamma42..gamma52 ) vmovhpd(xmm0, mem(rdx, rax, 1)) // store ( gamma43..gamma53 ) //lea(mem(rdx, rsi, 8), rdx) // rdx += 8*cs_c label(.SDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_sgemmsup_rv_haswell_asm_5x4 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) //lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored prefetching on c lea(mem(rcx, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 3*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 3*8)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 3*8)) // prefetch c + 3*rs_c prefetch(0, mem(rdx, rdi, 1, 3*8)) // prefetch c + 4*rs_c jmp(.SPOSTPFETCH) // jump to end of prefetching c label(.SCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) lea(mem(rsi, rsi, 2), rbp) // rbp = 3*cs_c; prefetch(0, mem(rcx, 4*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 4*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 4*8)) // prefetch c + 2*cs_c prefetch(0, mem(rcx, rbp, 1, 4*8)) // prefetch c + 3*cs_c label(.SPOSTPFETCH) // done prefetching c #if 1 lea(mem(rax, r9, 8), rdx) // lea(mem(rdx, r9, 8), rdx) // rdx = a + 16*cs_a; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(rdx, 5*8)) #endif vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) vbroadcastss(mem(rax, r13, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm8) vfmadd231ps(xmm0, xmm3, xmm10) vbroadcastss(mem(rax, r8, 4), xmm2) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm12) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, r9, 1, 5*8)) #endif vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) vbroadcastss(mem(rax, r13, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm8) vfmadd231ps(xmm0, xmm3, xmm10) vbroadcastss(mem(rax, r8, 4), xmm2) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm12) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(rdx, r9, 2, 5*8)) #endif vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) vbroadcastss(mem(rax, r13, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm8) vfmadd231ps(xmm0, xmm3, xmm10) vbroadcastss(mem(rax, r8, 4), xmm2) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm12) // ---------------------------------- iteration 3 #if 1 lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; #endif vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) vbroadcastss(mem(rax, r13, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm8) vfmadd231ps(xmm0, xmm3, xmm10) vbroadcastss(mem(rax, r8, 4), xmm2) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm12) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP #if 0 prefetch(0, mem(rdx, 5*8)) add(r9, rdx) #endif vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) vbroadcastss(mem(rax, r13, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm8) vfmadd231ps(xmm0, xmm3, xmm10) vbroadcastss(mem(rax, r8, 4), xmm2) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm12) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), xmm0) // load alpha and duplicate vbroadcastss(mem(rbx), xmm3) // load beta and duplicate vmulps(xmm0, xmm4, xmm4) // scale by alpha vmulps(xmm0, xmm6, xmm6) vmulps(xmm0, xmm8, xmm8) vmulps(xmm0, xmm10, xmm10) vmulps(xmm0, xmm12, xmm12) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; lea(mem(rsi, rsi, 4), rbx) // rbx = 5*cs_c; lea(mem(rax, rsi, 4), rbp) // rbp = 7*cs_c; // now avoid loading C if beta == 0 vxorps(xmm0, xmm0, xmm0) // set xmm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vfmadd231ps(mem(rcx, 0*32), xmm3, xmm4) vmovups(xmm4, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), xmm3, xmm6) vmovups(xmm6, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), xmm3, xmm8) vmovups(xmm8, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), xmm3, xmm10) vmovups(xmm10, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), xmm3, xmm12) vmovups(xmm12, mem(rcx, 0*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORED) // begin I/O on columns 0-3 vunpcklps(xmm6, xmm4, xmm0) vunpcklps(xmm10, xmm8, xmm1) vshufps(imm(0x4e), xmm1, xmm0, xmm2) vblendps(imm(0xcc), xmm2, xmm0, xmm0) vblendps(imm(0x33), xmm2, xmm1, xmm1) vfmadd231ps(mem(rcx ), xmm3, xmm0) vmovups(xmm0, mem(rcx )) // store ( gamma00..gamma30 ) vfmadd231ps(mem(rcx, rsi, 1), xmm3, xmm1) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) vunpckhps(xmm6, xmm4, xmm0) vunpckhps(xmm10, xmm8, xmm1) vshufps(imm(0x4e), xmm1, xmm0, xmm2) vblendps(imm(0xcc), xmm2, xmm0, xmm0) vblendps(imm(0x33), xmm2, xmm1, xmm1) vfmadd231ps(mem(rcx, rsi, 2), xmm3, xmm0) vmovups(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma32 ) vfmadd231ps(mem(rcx, rax, 1), xmm3, xmm1) vmovups(xmm1, mem(rcx, rax, 1)) // store ( gamma03..gamma33 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vmovups(xmm12, xmm0) vpermilps(imm(0xe4), xmm0, xmm2) vpermilps(imm(0x39), xmm0, xmm4) vmovss(mem(rdx ), xmm1) vmovss(mem(rdx, rsi, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rdx )) // store ( gamma40 ) vmovss(xmm4, mem(rdx, rsi, 1)) // store ( gamma41 ) vpermilps(imm(0x4e), xmm0, xmm2) vpermilps(imm(0x93), xmm0, xmm4) vmovss(mem(rdx, rsi, 2), xmm1) vmovss(mem(rdx, rax, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rdx, rsi, 2)) // store ( gamma42 ) vmovss(xmm4, mem(rdx, rax, 1)) // store ( gamma43 ) //lea(mem(rdx, rsi, 8), rdx) // rdx += 8*cs_c jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovups(xmm4, mem(rcx, 0*32)) add(rdi, rcx) vmovups(xmm6, mem(rcx, 0*32)) add(rdi, rcx) vmovups(xmm8, mem(rcx, 0*32)) add(rdi, rcx) vmovups(xmm10, mem(rcx, 0*32)) add(rdi, rcx) vmovups(xmm12, mem(rcx, 0*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) // begin I/O on columns 0-3 vunpcklps(xmm6, xmm4, xmm0) vunpcklps(xmm10, xmm8, xmm1) vshufps(imm(0x4e), xmm1, xmm0, xmm2) vblendps(imm(0xcc), xmm2, xmm0, xmm0) vblendps(imm(0x33), xmm2, xmm1, xmm1) vmovups(xmm0, mem(rcx )) // store ( gamma00..gamma30 ) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) vunpckhps(xmm6, xmm4, xmm0) vunpckhps(xmm10, xmm8, xmm1) vshufps(imm(0x4e), xmm1, xmm0, xmm2) vblendps(imm(0xcc), xmm2, xmm0, xmm0) vblendps(imm(0x33), xmm2, xmm1, xmm1) vmovups(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma32 ) vmovups(xmm1, mem(rcx, rax, 1)) // store ( gamma03..gamma33 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vmovups(xmm12, xmm0) vpermilps(imm(0xe4), xmm0, xmm2) vpermilps(imm(0x39), xmm0, xmm4) vmovss(xmm2, mem(rdx )) // store ( gamma40 ) vmovss(xmm4, mem(rdx, rsi, 1)) // store ( gamma41 ) vpermilps(imm(0x4e), xmm0, xmm2) vpermilps(imm(0x93), xmm0, xmm4) vmovss(xmm2, mem(rdx, rsi, 2)) // store ( gamma42 ) vmovss(xmm4, mem(rdx, rax, 1)) // store ( gamma43 ) //lea(mem(rdx, rsi, 8), rdx) // rdx += 8*cs_c label(.SDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_sgemmsup_rv_haswell_asm_4x4 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) //lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored prefetching on c lea(mem(rcx, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 3*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 3*8)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 3*8)) // prefetch c + 3*rs_c jmp(.SPOSTPFETCH) // jump to end of prefetching c label(.SCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) lea(mem(rsi, rsi, 2), rbp) // rbp = 3*cs_c; prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 3*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 3*8)) // prefetch c + 2*cs_c prefetch(0, mem(rcx, rbp, 1, 3*8)) // prefetch c + 3*cs_c label(.SPOSTPFETCH) // done prefetching c #if 1 lea(mem(rax, r9, 8), rdx) // lea(mem(rdx, r9, 8), rdx) // rdx = a + 16*cs_a; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(rdx, 5*8)) #endif vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) vbroadcastss(mem(rax, r13, 1), xmm3) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm8) vfmadd231ps(xmm0, xmm3, xmm10) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, r9, 1, 5*8)) #endif vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) vbroadcastss(mem(rax, r13, 1), xmm3) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm8) vfmadd231ps(xmm0, xmm3, xmm10) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(rdx, r9, 2, 5*8)) #endif vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) vbroadcastss(mem(rax, r13, 1), xmm3) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm8) vfmadd231ps(xmm0, xmm3, xmm10) // ---------------------------------- iteration 3 #if 1 lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; #endif vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) vbroadcastss(mem(rax, r13, 1), xmm3) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm8) vfmadd231ps(xmm0, xmm3, xmm10) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP #if 0 prefetch(0, mem(rdx, 5*8)) add(r9, rdx) #endif vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) vbroadcastss(mem(rax, r13, 1), xmm3) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm8) vfmadd231ps(xmm0, xmm3, xmm10) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), xmm0) // load alpha and duplicate vbroadcastss(mem(rbx), xmm3) // load beta and duplicate vmulps(xmm0, xmm4, xmm4) // scale by alpha vmulps(xmm0, xmm6, xmm6) vmulps(xmm0, xmm8, xmm8) vmulps(xmm0, xmm10, xmm10) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; lea(mem(rsi, rsi, 4), rbx) // rbx = 5*cs_c; lea(mem(rax, rsi, 4), rbp) // rbp = 7*cs_c; // now avoid loading C if beta == 0 vxorps(xmm0, xmm0, xmm0) // set xmm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vfmadd231ps(mem(rcx, 0*32), xmm3, xmm4) vmovups(xmm4, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), xmm3, xmm6) vmovups(xmm6, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), xmm3, xmm8) vmovups(xmm8, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), xmm3, xmm10) vmovups(xmm10, mem(rcx, 0*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORED) // begin I/O on columns 0-3 vunpcklps(xmm6, xmm4, xmm0) vunpcklps(xmm10, xmm8, xmm1) vshufps(imm(0x4e), xmm1, xmm0, xmm2) vblendps(imm(0xcc), xmm2, xmm0, xmm0) vblendps(imm(0x33), xmm2, xmm1, xmm1) vfmadd231ps(mem(rcx ), xmm3, xmm0) vmovups(xmm0, mem(rcx )) // store ( gamma00..gamma30 ) vfmadd231ps(mem(rcx, rsi, 1), xmm3, xmm1) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) vunpckhps(xmm6, xmm4, xmm0) vunpckhps(xmm10, xmm8, xmm1) vshufps(imm(0x4e), xmm1, xmm0, xmm2) vblendps(imm(0xcc), xmm2, xmm0, xmm0) vblendps(imm(0x33), xmm2, xmm1, xmm1) vfmadd231ps(mem(rcx, rsi, 2), xmm3, xmm0) vmovups(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma32 ) vfmadd231ps(mem(rcx, rax, 1), xmm3, xmm1) vmovups(xmm1, mem(rcx, rax, 1)) // store ( gamma03..gamma33 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovups(xmm4, mem(rcx, 0*32)) add(rdi, rcx) vmovups(xmm6, mem(rcx, 0*32)) add(rdi, rcx) vmovups(xmm8, mem(rcx, 0*32)) add(rdi, rcx) vmovups(xmm10, mem(rcx, 0*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) // begin I/O on columns 0-3 vunpcklps(xmm6, xmm4, xmm0) vunpcklps(xmm10, xmm8, xmm1) vshufps(imm(0x4e), xmm1, xmm0, xmm2) vblendps(imm(0xcc), xmm2, xmm0, xmm0) vblendps(imm(0x33), xmm2, xmm1, xmm1) vmovups(xmm0, mem(rcx )) // store ( gamma00..gamma30 ) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) vunpckhps(xmm6, xmm4, xmm0) vunpckhps(xmm10, xmm8, xmm1) vshufps(imm(0x4e), xmm1, xmm0, xmm2) vblendps(imm(0xcc), xmm2, xmm0, xmm0) vblendps(imm(0x33), xmm2, xmm1, xmm1) vmovups(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma32 ) vmovups(xmm1, mem(rcx, rax, 1)) // store ( gamma03..gamma33 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c label(.SDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_sgemmsup_rv_haswell_asm_3x4 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) //lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored prefetching on c lea(mem(rcx, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 3*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 3*8)) // prefetch c + 2*rs_c jmp(.SPOSTPFETCH) // jump to end of prefetching c label(.SCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) lea(mem(rsi, rsi, 2), rbp) // rbp = 3*cs_c; prefetch(0, mem(rcx, 2*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 2*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 2*8)) // prefetch c + 2*cs_c prefetch(0, mem(rcx, rbp, 1, 2*8)) // prefetch c + 3*cs_c label(.SPOSTPFETCH) // done prefetching c #if 1 lea(mem(rax, r9, 8), rdx) // lea(mem(rdx, r9, 8), rdx) // rdx = a + 16*cs_a; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(rdx, 5*8)) #endif vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm8) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, r9, 1, 5*8)) #endif vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm8) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(rdx, r9, 2, 5*8)) #endif vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm8) // ---------------------------------- iteration 3 #if 1 lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; #endif vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm8) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP #if 0 prefetch(0, mem(rdx, 5*8)) add(r9, rdx) #endif vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm8) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), xmm0) // load alpha and duplicate vbroadcastss(mem(rbx), xmm3) // load beta and duplicate vmulps(xmm0, xmm4, xmm4) // scale by alpha vmulps(xmm0, xmm6, xmm6) vmulps(xmm0, xmm8, xmm8) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; lea(mem(rcx, rdi, 2), rdx) // load address of c + 2*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; lea(mem(rsi, rsi, 4), rbx) // rbx = 5*cs_c; lea(mem(rax, rsi, 4), rbp) // rbp = 7*cs_c; // now avoid loading C if beta == 0 vxorps(xmm0, xmm0, xmm0) // set xmm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vfmadd231ps(mem(rcx, 0*32), xmm3, xmm4) vmovups(xmm4, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), xmm3, xmm6) vmovups(xmm6, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), xmm3, xmm8) vmovups(xmm8, mem(rcx, 0*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORED) // begin I/O on columns 0-3 vunpcklps(xmm6, xmm4, xmm0) vmovlpd(mem(rcx ), xmm1, xmm1) vmovhpd(mem(rcx, rsi, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(rcx )) // store ( gamma00..gamma10 ) vmovhpd(xmm0, mem(rcx, rsi, 1)) // store ( gamma01..gamma11 ) vunpckhps(xmm6, xmm4, xmm0) vmovlpd(mem(rcx, rsi, 2), xmm1, xmm1) vmovhpd(mem(rcx, rax, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma12 ) vmovhpd(xmm0, mem(rcx, rax, 1)) // store ( gamma03..gamma13 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vmovups(xmm8, xmm0) vpermilps(imm(0xe4), xmm0, xmm2) vpermilps(imm(0x39), xmm0, xmm4) vmovss(mem(rdx ), xmm1) vmovss(mem(rdx, rsi, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rdx )) // store ( gamma20 ) vmovss(xmm4, mem(rdx, rsi, 1)) // store ( gamma21 ) vpermilps(imm(0x4e), xmm0, xmm2) vpermilps(imm(0x93), xmm0, xmm4) vmovss(mem(rdx, rsi, 2), xmm1) vmovss(mem(rdx, rax, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rdx, rsi, 2)) // store ( gamma22 ) vmovss(xmm4, mem(rdx, rax, 1)) // store ( gamma23 ) //lea(mem(rdx, rsi, 8), rdx) // rdx += 8*cs_c jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovups(xmm4, mem(rcx, 0*32)) add(rdi, rcx) vmovups(xmm6, mem(rcx, 0*32)) add(rdi, rcx) vmovups(xmm8, mem(rcx, 0*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) // begin I/O on columns 0-3 vunpcklps(xmm6, xmm4, xmm0) vmovlpd(xmm0, mem(rcx )) // store ( gamma00..gamma10 ) vmovhpd(xmm0, mem(rcx, rsi, 1)) // store ( gamma01..gamma11 ) vunpckhps(xmm6, xmm4, xmm0) vmovlpd(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma12 ) vmovhpd(xmm0, mem(rcx, rax, 1)) // store ( gamma03..gamma13 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vmovups(xmm8, xmm0) vpermilps(imm(0xe4), xmm0, xmm2) vpermilps(imm(0x39), xmm0, xmm4) vmovss(xmm2, mem(rdx )) // store ( gamma20 ) vmovss(xmm4, mem(rdx, rsi, 1)) // store ( gamma21 ) vpermilps(imm(0x4e), xmm0, xmm2) vpermilps(imm(0x93), xmm0, xmm4) vmovss(xmm2, mem(rdx, rsi, 2)) // store ( gamma22 ) vmovss(xmm4, mem(rdx, rax, 1)) // store ( gamma23 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c label(.SDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_sgemmsup_rv_haswell_asm_2x4 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) //lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored prefetching on c lea(mem(rcx, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 3*8)) // prefetch c + 1*rs_c jmp(.SPOSTPFETCH) // jump to end of prefetching c label(.SCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) lea(mem(rsi, rsi, 2), rbp) // rbp = 3*cs_c; prefetch(0, mem(rcx, 1*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 1*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 1*8)) // prefetch c + 2*cs_c prefetch(0, mem(rcx, rbp, 1, 1*8)) // prefetch c + 3*cs_c label(.SPOSTPFETCH) // done prefetching c #if 1 lea(mem(rax, r9, 8), rdx) // lea(mem(rdx, r9, 8), rdx) // rdx = a + 16*cs_a; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(rdx, 5*8)) #endif vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, r9, 1, 5*8)) #endif vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(rdx, r9, 2, 5*8)) #endif vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) // ---------------------------------- iteration 3 #if 1 lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; #endif vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP #if 0 prefetch(0, mem(rdx, 5*8)) add(r9, rdx) #endif vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), xmm0) // load alpha and duplicate vbroadcastss(mem(rbx), xmm3) // load beta and duplicate vmulps(xmm0, xmm4, xmm4) // scale by alpha vmulps(xmm0, xmm6, xmm6) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; //lea(mem(rcx, rdi, 2), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; lea(mem(rsi, rsi, 4), rbx) // rbx = 5*cs_c; lea(mem(rax, rsi, 4), rbp) // rbp = 7*cs_c; // now avoid loading C if beta == 0 vxorps(xmm0, xmm0, xmm0) // set xmm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vfmadd231ps(mem(rcx, 0*32), xmm3, xmm4) vmovups(xmm4, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), xmm3, xmm6) vmovups(xmm6, mem(rcx, 0*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORED) // begin I/O on columns 0-3 vunpcklps(xmm6, xmm4, xmm0) vmovlpd(mem(rcx ), xmm1, xmm1) vmovhpd(mem(rcx, rsi, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(rcx )) // store ( gamma00..gamma10 ) vmovhpd(xmm0, mem(rcx, rsi, 1)) // store ( gamma01..gamma11 ) vunpckhps(xmm6, xmm4, xmm0) vmovlpd(mem(rcx, rsi, 2), xmm1, xmm1) vmovhpd(mem(rcx, rax, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma12 ) vmovhpd(xmm0, mem(rcx, rax, 1)) // store ( gamma03..gamma13 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovups(xmm4, mem(rcx, 0*32)) add(rdi, rcx) vmovups(xmm6, mem(rcx, 0*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) // begin I/O on columns 0-3 vunpcklps(xmm6, xmm4, xmm0) vmovlpd(xmm0, mem(rcx )) // store ( gamma00..gamma10 ) vmovhpd(xmm0, mem(rcx, rsi, 1)) // store ( gamma01..gamma11 ) vunpckhps(xmm6, xmm4, xmm0) vmovlpd(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma12 ) vmovhpd(xmm0, mem(rcx, rax, 1)) // store ( gamma03..gamma13 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c label(.SDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_sgemmsup_rv_haswell_asm_1x4 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) //lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored prefetching on c lea(mem(rcx, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c jmp(.SPOSTPFETCH) // jump to end of prefetching c label(.SCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) lea(mem(rsi, rsi, 2), rbp) // rbp = 3*cs_c; prefetch(0, mem(rcx, 0*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 0*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 0*8)) // prefetch c + 2*cs_c prefetch(0, mem(rcx, rbp, 1, 0*8)) // prefetch c + 3*cs_c label(.SPOSTPFETCH) // done prefetching c #if 1 lea(mem(rax, r9, 8), rdx) // lea(mem(rdx, r9, 8), rdx) // rdx = a + 16*cs_a; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(rdx, 5*8)) #endif vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm4) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, r9, 1, 5*8)) #endif vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm4) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(rdx, r9, 2, 5*8)) #endif vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm4) // ---------------------------------- iteration 3 #if 1 lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; #endif vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm4) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP #if 0 prefetch(0, mem(rdx, 5*8)) add(r9, rdx) #endif vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm4) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), xmm0) // load alpha and duplicate vbroadcastss(mem(rbx), xmm3) // load beta and duplicate vmulps(xmm0, xmm4, xmm4) // scale by alpha mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; //lea(mem(rcx, rdi, 2), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; lea(mem(rsi, rsi, 4), rbx) // rbx = 5*cs_c; lea(mem(rax, rsi, 4), rbp) // rbp = 7*cs_c; // now avoid loading C if beta == 0 vxorps(xmm0, xmm0, xmm0) // set xmm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vfmadd231ps(mem(rcx, 0*32), xmm3, xmm4) vmovups(xmm4, mem(rcx, 0*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORED) // begin I/O on columns 0-3 vmovups(xmm4, xmm0) vpermilps(imm(0xe4), xmm0, xmm2) vpermilps(imm(0x39), xmm0, xmm4) vmovss(mem(rcx ), xmm1) vmovss(mem(rcx, rsi, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rcx )) // store ( gamma00 ) vmovss(xmm4, mem(rcx, rsi, 1)) // store ( gamma01 ) vpermilps(imm(0x4e), xmm0, xmm2) vpermilps(imm(0x93), xmm0, xmm4) vmovss(mem(rcx, rsi, 2), xmm1) vmovss(mem(rcx, rax, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rcx, rsi, 2)) // store ( gamma02 ) vmovss(xmm4, mem(rcx, rax, 1)) // store ( gamma03 ) //lea(mem(rdx, rsi, 8), rdx) // rdx += 8*cs_c jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovups(xmm4, mem(rcx, 0*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) // begin I/O on columns 0-3 vmovups(xmm4, xmm0) vpermilps(imm(0xe4), xmm0, xmm2) vpermilps(imm(0x39), xmm0, xmm4) vmovss(xmm2, mem(rcx )) // store ( gamma00 ) vmovss(xmm4, mem(rcx, rsi, 1)) // store ( gamma01 ) vpermilps(imm(0x4e), xmm0, xmm2) vpermilps(imm(0x93), xmm0, xmm4) vmovss(xmm2, mem(rcx, rsi, 2)) // store ( gamma02 ) vmovss(xmm4, mem(rcx, rax, 1)) // store ( gamma03 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c label(.SDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } blis-0.9.0/kernels/haswell/3/sup/s6x16/bli_gemmsup_rv_haswell_asm_sMx6.c000066400000000000000000002747221422157504600261110ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define BLIS_ASM_SYNTAX_ATT #include "bli_x86_asm_macros.h" /* rrr: -------- ------ -------- -------- ------ -------- -------- += ------ ... -------- -------- ------ -------- -------- ------ : -------- ------ : rcr: -------- | | | | -------- -------- | | | | -------- -------- += | | | | ... -------- -------- | | | | -------- -------- | | | | : -------- | | | | : Assumptions: - B is row-stored; - A is row- or column-stored; - m0 and n0 are at most MR and NR, respectively. Therefore, this (r)ow-preferential kernel is well-suited for contiguous (v)ector loads on B and single-element broadcasts from A. NOTE: These kernels explicitly support column-oriented IO, implemented via an in-register transpose. And thus they also support the crr and ccr cases, though only crr is ever utilized (because ccr is handled by transposing the operation and executing rcr, which does not incur the cost of the in-register transpose). crr: | | | | | | | | ------ -------- | | | | | | | | ------ -------- | | | | | | | | += ------ ... -------- | | | | | | | | ------ -------- | | | | | | | | ------ : | | | | | | | | ------ : */ // Prototype reference microkernels. GEMMSUP_KER_PROT( float, s, gemmsup_r_haswell_ref ) void bli_sgemmsup_rv_haswell_asm_6x6 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) //lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored prefetching on c lea(mem(rcx, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 5*4)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 5*4)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 5*4)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 5*4)) // prefetch c + 3*rs_c prefetch(0, mem(rdx, rdi, 1, 5*4)) // prefetch c + 4*rs_c prefetch(0, mem(rdx, rdi, 2, 5*4)) // prefetch c + 5*rs_c jmp(.SPOSTPFETCH) // jump to end of prefetching c label(.SCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) lea(mem(rsi, rsi, 2), rbp) // rbp = 3*cs_c; prefetch(0, mem(rcx, 5*4)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 5*4)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 5*4)) // prefetch c + 2*cs_c prefetch(0, mem(rcx, rbp, 1, 5*4)) // prefetch c + 3*cs_c prefetch(0, mem(rcx, rsi, 4, 5*4)) // prefetch c + 4*cs_c lea(mem(rcx, rsi, 4), rdx) // rdx = c + 4*cs_c; prefetch(0, mem(rdx, rsi, 1, 5*4)) // prefetch c + 5*cs_c label(.SPOSTPFETCH) // done prefetching c #if 1 lea(mem(rax, r9, 8), rdx) // lea(mem(rdx, r9, 8), rdx) // rdx = a + 16*cs_a; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(rdx, 5*8)) #endif vmovups(mem(rbx, 0*4), xmm0) vmovsd(mem(rbx, 4*4), xmm1) vinsertf128(imm(0x1), xmm1, ymm0, ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm0, ymm3, ymm10) vbroadcastss(mem(rax, r8, 4), ymm2) vbroadcastss(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm0, ymm3, ymm14) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, r9, 1, 5*8)) #endif vmovups(mem(rbx, 0*4), xmm0) vmovsd(mem(rbx, 4*4), xmm1) vinsertf128(imm(0x1), xmm1, ymm0, ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm0, ymm3, ymm10) vbroadcastss(mem(rax, r8, 4), ymm2) vbroadcastss(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm0, ymm3, ymm14) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(rdx, r9, 2, 5*8)) #endif vmovups(mem(rbx, 0*4), xmm0) vmovsd(mem(rbx, 4*4), xmm1) vinsertf128(imm(0x1), xmm1, ymm0, ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm0, ymm3, ymm10) vbroadcastss(mem(rax, r8, 4), ymm2) vbroadcastss(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm0, ymm3, ymm14) // ---------------------------------- iteration 3 #if 1 lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; #endif vmovups(mem(rbx, 0*4), xmm0) vmovsd(mem(rbx, 4*4), xmm1) vinsertf128(imm(0x1), xmm1, ymm0, ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm0, ymm3, ymm10) vbroadcastss(mem(rax, r8, 4), ymm2) vbroadcastss(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm0, ymm3, ymm14) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP #if 0 prefetch(0, mem(rdx, 5*8)) add(r9, rdx) #endif vmovups(mem(rbx, 0*4), xmm0) vmovsd(mem(rbx, 4*4), xmm1) vinsertf128(imm(0x1), xmm1, ymm0, ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm0, ymm3, ymm10) vbroadcastss(mem(rax, r8, 4), ymm2) vbroadcastss(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm0, ymm3, ymm14) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), ymm0) // load alpha and duplicate vbroadcastss(mem(rbx), ymm3) // load beta and duplicate vmulps(ymm0, ymm4, ymm4) // scale by alpha vmulps(ymm0, ymm6, ymm6) vmulps(ymm0, ymm8, ymm8) vmulps(ymm0, ymm10, ymm10) vmulps(ymm0, ymm12, ymm12) vmulps(ymm0, ymm14, ymm14) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; lea(mem(rsi, rsi, 4), rbx) // rbx = 5*cs_c; //lea(mem(rax, rsi, 4), rbp) // rbp = 7*cs_c; // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vextractf128(imm(0x1), ymm4, xmm5) vfmadd231ps(mem(rcx, 0*4), xmm3, xmm4) vmovups(xmm4, mem(rcx, 0*4)) vmovsd(mem(rcx, 4*4), xmm1) vfmadd231ps(xmm1, xmm3, xmm5) vmovsd(xmm5, mem(rcx, 4*4)) add(rdi, rcx) vextractf128(imm(0x1), ymm6, xmm7) vfmadd231ps(mem(rcx, 0*4), xmm3, xmm6) vmovups(xmm6, mem(rcx, 0*4)) vmovsd(mem(rcx, 4*4), xmm1) vfmadd231ps(xmm1, xmm3, xmm7) vmovsd(xmm7, mem(rcx, 4*4)) add(rdi, rcx) vextractf128(imm(0x1), ymm8, xmm9) vfmadd231ps(mem(rcx, 0*4), xmm3, xmm8) vmovups(xmm8, mem(rcx, 0*4)) vmovsd(mem(rcx, 4*4), xmm1) vfmadd231ps(xmm1, xmm3, xmm9) vmovsd(xmm9, mem(rcx, 4*4)) add(rdi, rcx) vextractf128(imm(0x1), ymm10, xmm11) vfmadd231ps(mem(rcx, 0*4), xmm3, xmm10) vmovups(xmm10, mem(rcx, 0*4)) vmovsd(mem(rcx, 4*4), xmm1) vfmadd231ps(xmm1, xmm3, xmm11) vmovsd(xmm11, mem(rcx, 4*4)) add(rdi, rcx) vextractf128(imm(0x1), ymm12, xmm13) vfmadd231ps(mem(rcx, 0*4), xmm3, xmm12) vmovups(xmm12, mem(rcx, 0*4)) vmovsd(mem(rcx, 4*4), xmm1) vfmadd231ps(xmm1, xmm3, xmm13) vmovsd(xmm13, mem(rcx, 4*4)) add(rdi, rcx) vextractf128(imm(0x1), ymm14, xmm15) vfmadd231ps(mem(rcx, 0*4), xmm3, xmm14) vmovups(xmm14, mem(rcx, 0*4)) vmovsd(mem(rcx, 4*4), xmm1) vfmadd231ps(xmm1, xmm3, xmm15) vmovsd(xmm15, mem(rcx, 4*4)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORED) // begin I/O on columns 0-5 vunpcklps(ymm6, ymm4, ymm0) vunpcklps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx ), xmm3, xmm0) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm0, mem(rcx )) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx, rsi, 1), xmm3, xmm1) vfmadd231ps(mem(rcx, rbx, 1), xmm3, xmm2) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rbx, 1)) // store ( gamma05..gamma35 ) vunpckhps(ymm6, ymm4, ymm0) vunpckhps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vfmadd231ps(mem(rcx, rsi, 2), xmm3, xmm0) vmovups(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma32 ) vfmadd231ps(mem(rcx, rax, 1), xmm3, xmm1) vmovups(xmm1, mem(rcx, rax, 1)) // store ( gamma03..gamma33 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vunpcklps(ymm14, ymm12, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(mem(rdx ), xmm1, xmm1) vmovhpd(mem(rdx, rsi, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(rdx )) // store ( gamma40..gamma50 ) vmovhpd(xmm0, mem(rdx, rsi, 1)) // store ( gamma41..gamma51 ) vmovlpd(mem(rdx, rsi, 4), xmm1, xmm1) vmovhpd(mem(rdx, rbx, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm2) vmovlpd(xmm2, mem(rdx, rsi, 4)) // store ( gamma44..gamma54 ) vmovhpd(xmm2, mem(rdx, rbx, 1)) // store ( gamma45..gamma55 ) vunpckhps(ymm14, ymm12, ymm0) vmovlpd(mem(rdx, rsi, 2), xmm1, xmm1) vmovhpd(mem(rdx, rax, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(rdx, rsi, 2)) // store ( gamma42..gamma52 ) vmovhpd(xmm0, mem(rdx, rax, 1)) // store ( gamma43..gamma53 ) //lea(mem(rdx, rsi, 8), rdx) // rdx += 8*cs_c jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vextractf128(imm(0x1), ymm4, xmm5) vmovups(xmm4, mem(rcx, 0*4)) vmovsd(xmm5, mem(rcx, 4*4)) add(rdi, rcx) vextractf128(imm(0x1), ymm6, xmm7) vmovups(xmm6, mem(rcx, 0*4)) vmovsd(xmm7, mem(rcx, 4*4)) add(rdi, rcx) vextractf128(imm(0x1), ymm8, xmm9) vmovups(xmm8, mem(rcx, 0*4)) vmovsd(xmm9, mem(rcx, 4*4)) add(rdi, rcx) vextractf128(imm(0x1), ymm10, xmm11) vmovups(xmm10, mem(rcx, 0*4)) vmovsd(xmm11, mem(rcx, 4*4)) add(rdi, rcx) vextractf128(imm(0x1), ymm12, xmm13) vmovups(xmm12, mem(rcx, 0*4)) vmovsd(xmm13, mem(rcx, 4*4)) add(rdi, rcx) vextractf128(imm(0x1), ymm14, xmm15) vmovups(xmm14, mem(rcx, 0*4)) vmovsd(xmm15, mem(rcx, 4*4)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) // begin I/O on columns 0-5 vunpcklps(ymm6, ymm4, ymm0) vunpcklps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx )) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rbx, 1)) // store ( gamma05..gamma35 ) vunpckhps(ymm6, ymm4, ymm0) vunpckhps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vmovups(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma32 ) vmovups(xmm1, mem(rcx, rax, 1)) // store ( gamma03..gamma33 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vunpcklps(ymm14, ymm12, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(xmm0, mem(rdx )) // store ( gamma40..gamma50 ) vmovhpd(xmm0, mem(rdx, rsi, 1)) // store ( gamma41..gamma51 ) vmovlpd(xmm2, mem(rdx, rsi, 4)) // store ( gamma44..gamma54 ) vmovhpd(xmm2, mem(rdx, rbx, 1)) // store ( gamma45..gamma55 ) vunpckhps(ymm14, ymm12, ymm0) vmovlpd(xmm0, mem(rdx, rsi, 2)) // store ( gamma42..gamma52 ) vmovhpd(xmm0, mem(rdx, rax, 1)) // store ( gamma43..gamma53 ) //lea(mem(rdx, rsi, 8), rdx) // rdx += 8*cs_c label(.SDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_sgemmsup_rv_haswell_asm_5x6 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) //lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored prefetching on c lea(mem(rcx, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 5*4)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 5*4)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 5*4)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 5*4)) // prefetch c + 3*rs_c prefetch(0, mem(rdx, rdi, 1, 5*4)) // prefetch c + 4*rs_c jmp(.SPOSTPFETCH) // jump to end of prefetching c label(.SCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) lea(mem(rsi, rsi, 2), rbp) // rbp = 3*cs_c; prefetch(0, mem(rcx, 4*4)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 4*4)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 4*4)) // prefetch c + 2*cs_c prefetch(0, mem(rcx, rbp, 1, 4*4)) // prefetch c + 3*cs_c prefetch(0, mem(rcx, rsi, 4, 4*4)) // prefetch c + 4*cs_c lea(mem(rcx, rsi, 4), rdx) // rdx = c + 4*cs_c; prefetch(0, mem(rdx, rsi, 1, 4*4)) // prefetch c + 5*cs_c label(.SPOSTPFETCH) // done prefetching c #if 1 lea(mem(rax, r9, 8), rdx) // lea(mem(rdx, r9, 8), rdx) // rdx = a + 16*cs_a; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(rdx, 5*8)) #endif vmovups(mem(rbx, 0*4), xmm0) vmovsd(mem(rbx, 4*4), xmm1) vinsertf128(imm(0x1), xmm1, ymm0, ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm0, ymm3, ymm10) vbroadcastss(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, r9, 1, 5*8)) #endif vmovups(mem(rbx, 0*4), xmm0) vmovsd(mem(rbx, 4*4), xmm1) vinsertf128(imm(0x1), xmm1, ymm0, ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm0, ymm3, ymm10) vbroadcastss(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(rdx, r9, 2, 5*8)) #endif vmovups(mem(rbx, 0*4), xmm0) vmovsd(mem(rbx, 4*4), xmm1) vinsertf128(imm(0x1), xmm1, ymm0, ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm0, ymm3, ymm10) vbroadcastss(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) // ---------------------------------- iteration 3 #if 1 lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; #endif vmovups(mem(rbx, 0*4), xmm0) vmovsd(mem(rbx, 4*4), xmm1) vinsertf128(imm(0x1), xmm1, ymm0, ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm0, ymm3, ymm10) vbroadcastss(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP #if 0 prefetch(0, mem(rdx, 5*8)) add(r9, rdx) #endif vmovups(mem(rbx, 0*4), xmm0) vmovsd(mem(rbx, 4*4), xmm1) vinsertf128(imm(0x1), xmm1, ymm0, ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm0, ymm3, ymm10) vbroadcastss(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), ymm0) // load alpha and duplicate vbroadcastss(mem(rbx), ymm3) // load beta and duplicate vmulps(ymm0, ymm4, ymm4) // scale by alpha vmulps(ymm0, ymm6, ymm6) vmulps(ymm0, ymm8, ymm8) vmulps(ymm0, ymm10, ymm10) vmulps(ymm0, ymm12, ymm12) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; lea(mem(rsi, rsi, 4), rbx) // rbx = 5*cs_c; //lea(mem(rax, rsi, 4), rbp) // rbp = 7*cs_c; // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vextractf128(imm(0x1), ymm4, xmm5) vfmadd231ps(mem(rcx, 0*4), xmm3, xmm4) vmovups(xmm4, mem(rcx, 0*4)) vmovsd(mem(rcx, 4*4), xmm1) vfmadd231ps(xmm1, xmm3, xmm5) vmovsd(xmm5, mem(rcx, 4*4)) add(rdi, rcx) vextractf128(imm(0x1), ymm6, xmm7) vfmadd231ps(mem(rcx, 0*4), xmm3, xmm6) vmovups(xmm6, mem(rcx, 0*4)) vmovsd(mem(rcx, 4*4), xmm1) vfmadd231ps(xmm1, xmm3, xmm7) vmovsd(xmm7, mem(rcx, 4*4)) add(rdi, rcx) vextractf128(imm(0x1), ymm8, xmm9) vfmadd231ps(mem(rcx, 0*4), xmm3, xmm8) vmovups(xmm8, mem(rcx, 0*4)) vmovsd(mem(rcx, 4*4), xmm1) vfmadd231ps(xmm1, xmm3, xmm9) vmovsd(xmm9, mem(rcx, 4*4)) add(rdi, rcx) vextractf128(imm(0x1), ymm10, xmm11) vfmadd231ps(mem(rcx, 0*4), xmm3, xmm10) vmovups(xmm10, mem(rcx, 0*4)) vmovsd(mem(rcx, 4*4), xmm1) vfmadd231ps(xmm1, xmm3, xmm11) vmovsd(xmm11, mem(rcx, 4*4)) add(rdi, rcx) vextractf128(imm(0x1), ymm12, xmm13) vfmadd231ps(mem(rcx, 0*4), xmm3, xmm12) vmovups(xmm12, mem(rcx, 0*4)) vmovsd(mem(rcx, 4*4), xmm1) vfmadd231ps(xmm1, xmm3, xmm13) vmovsd(xmm13, mem(rcx, 4*4)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORED) // begin I/O on columns 0-5 vunpcklps(ymm6, ymm4, ymm0) vunpcklps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx ), xmm3, xmm0) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm0, mem(rcx )) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx, rsi, 1), xmm3, xmm1) vfmadd231ps(mem(rcx, rbx, 1), xmm3, xmm2) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rbx, 1)) // store ( gamma05..gamma35 ) vunpckhps(ymm6, ymm4, ymm0) vunpckhps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vfmadd231ps(mem(rcx, rsi, 2), xmm3, xmm0) vmovups(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma32 ) vfmadd231ps(mem(rcx, rax, 1), xmm3, xmm1) vmovups(xmm1, mem(rcx, rax, 1)) // store ( gamma03..gamma33 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vmovups(ymm12, ymm0) vextractf128(imm(0x1), ymm0, xmm8) vpermilps(imm(0xe4), xmm0, xmm2) vpermilps(imm(0x39), xmm0, xmm4) vmovss(mem(rdx ), xmm1) vmovss(mem(rdx, rsi, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rdx )) // store ( gamma40 ) vmovss(xmm4, mem(rdx, rsi, 1)) // store ( gamma41 ) vpermilps(imm(0x4e), xmm0, xmm2) vpermilps(imm(0x93), xmm0, xmm4) vmovss(mem(rdx, rsi, 2), xmm1) vmovss(mem(rdx, rax, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rdx, rsi, 2)) // store ( gamma42 ) vmovss(xmm4, mem(rdx, rax, 1)) // store ( gamma43 ) vpermilps(imm(0xe4), xmm8, xmm2) vpermilps(imm(0x39), xmm8, xmm4) vmovss(mem(rdx, rsi, 4), xmm1) vmovss(mem(rdx, rbx, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rdx, rsi, 4)) // store ( gamma44 ) vmovss(xmm4, mem(rdx, rbx, 1)) // store ( gamma45 ) //lea(mem(rdx, rsi, 8), rdx) // rdx += 8*cs_c jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vextractf128(imm(0x1), ymm4, xmm5) vmovups(xmm4, mem(rcx, 0*4)) vmovsd(xmm5, mem(rcx, 4*4)) add(rdi, rcx) vextractf128(imm(0x1), ymm6, xmm7) vmovups(xmm6, mem(rcx, 0*4)) vmovsd(xmm7, mem(rcx, 4*4)) add(rdi, rcx) vextractf128(imm(0x1), ymm8, xmm9) vmovups(xmm8, mem(rcx, 0*4)) vmovsd(xmm9, mem(rcx, 4*4)) add(rdi, rcx) vextractf128(imm(0x1), ymm10, xmm11) vmovups(xmm10, mem(rcx, 0*4)) vmovsd(xmm11, mem(rcx, 4*4)) add(rdi, rcx) vextractf128(imm(0x1), ymm12, xmm13) vmovups(xmm12, mem(rcx, 0*4)) vmovsd(xmm13, mem(rcx, 4*4)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) // begin I/O on columns 0-5 vunpcklps(ymm6, ymm4, ymm0) vunpcklps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx )) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rbx, 1)) // store ( gamma05..gamma35 ) vunpckhps(ymm6, ymm4, ymm0) vunpckhps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vmovups(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma32 ) vmovups(xmm1, mem(rcx, rax, 1)) // store ( gamma03..gamma33 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vmovups(ymm12, ymm0) vextractf128(imm(0x1), ymm0, xmm8) vpermilps(imm(0xe4), xmm0, xmm2) vpermilps(imm(0x39), xmm0, xmm4) vmovss(xmm2, mem(rdx )) // store ( gamma40 ) vmovss(xmm4, mem(rdx, rsi, 1)) // store ( gamma41 ) vpermilps(imm(0x4e), xmm0, xmm2) vpermilps(imm(0x93), xmm0, xmm4) vmovss(xmm2, mem(rdx, rsi, 2)) // store ( gamma42 ) vmovss(xmm4, mem(rdx, rax, 1)) // store ( gamma43 ) vpermilps(imm(0xe4), xmm8, xmm2) vpermilps(imm(0x39), xmm8, xmm4) vmovss(xmm2, mem(rdx, rsi, 4)) // store ( gamma44 ) vmovss(xmm4, mem(rdx, rbx, 1)) // store ( gamma45 ) //lea(mem(rdx, rsi, 8), rdx) // rdx += 8*cs_c label(.SDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_sgemmsup_rv_haswell_asm_4x6 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) //lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored prefetching on c lea(mem(rcx, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 5*4)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 5*4)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 5*4)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 5*4)) // prefetch c + 3*rs_c jmp(.SPOSTPFETCH) // jump to end of prefetching c label(.SCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) lea(mem(rsi, rsi, 2), rbp) // rbp = 3*cs_c; prefetch(0, mem(rcx, 3*4)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 3*4)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 3*4)) // prefetch c + 2*cs_c prefetch(0, mem(rcx, rbp, 1, 3*4)) // prefetch c + 3*cs_c prefetch(0, mem(rcx, rsi, 4, 3*4)) // prefetch c + 4*cs_c lea(mem(rcx, rsi, 4), rdx) // rdx = c + 4*cs_c; prefetch(0, mem(rdx, rsi, 1, 3*4)) // prefetch c + 5*cs_c label(.SPOSTPFETCH) // done prefetching c #if 1 lea(mem(rax, r9, 8), rdx) // lea(mem(rdx, r9, 8), rdx) // rdx = a + 16*cs_a; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(rdx, 5*8)) #endif vmovups(mem(rbx, 0*4), xmm0) vmovsd(mem(rbx, 4*4), xmm1) vinsertf128(imm(0x1), xmm1, ymm0, ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm0, ymm3, ymm10) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, r9, 1, 5*8)) #endif vmovups(mem(rbx, 0*4), xmm0) vmovsd(mem(rbx, 4*4), xmm1) vinsertf128(imm(0x1), xmm1, ymm0, ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm0, ymm3, ymm10) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(rdx, r9, 2, 5*8)) #endif vmovups(mem(rbx, 0*4), xmm0) vmovsd(mem(rbx, 4*4), xmm1) vinsertf128(imm(0x1), xmm1, ymm0, ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm0, ymm3, ymm10) // ---------------------------------- iteration 3 #if 1 lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; #endif vmovups(mem(rbx, 0*4), xmm0) vmovsd(mem(rbx, 4*4), xmm1) vinsertf128(imm(0x1), xmm1, ymm0, ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm0, ymm3, ymm10) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP #if 0 prefetch(0, mem(rdx, 5*8)) add(r9, rdx) #endif vmovups(mem(rbx, 0*4), xmm0) vmovsd(mem(rbx, 4*4), xmm1) vinsertf128(imm(0x1), xmm1, ymm0, ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm0, ymm3, ymm10) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), ymm0) // load alpha and duplicate vbroadcastss(mem(rbx), ymm3) // load beta and duplicate vmulps(ymm0, ymm4, ymm4) // scale by alpha vmulps(ymm0, ymm6, ymm6) vmulps(ymm0, ymm8, ymm8) vmulps(ymm0, ymm10, ymm10) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; lea(mem(rsi, rsi, 4), rbx) // rbx = 5*cs_c; //lea(mem(rax, rsi, 4), rbp) // rbp = 7*cs_c; // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vextractf128(imm(0x1), ymm4, xmm5) vfmadd231ps(mem(rcx, 0*4), xmm3, xmm4) vmovups(xmm4, mem(rcx, 0*4)) vmovsd(mem(rcx, 4*4), xmm1) vfmadd231ps(xmm1, xmm3, xmm5) vmovsd(xmm5, mem(rcx, 4*4)) add(rdi, rcx) vextractf128(imm(0x1), ymm6, xmm7) vfmadd231ps(mem(rcx, 0*4), xmm3, xmm6) vmovups(xmm6, mem(rcx, 0*4)) vmovsd(mem(rcx, 4*4), xmm1) vfmadd231ps(xmm1, xmm3, xmm7) vmovsd(xmm7, mem(rcx, 4*4)) add(rdi, rcx) vextractf128(imm(0x1), ymm8, xmm9) vfmadd231ps(mem(rcx, 0*4), xmm3, xmm8) vmovups(xmm8, mem(rcx, 0*4)) vmovsd(mem(rcx, 4*4), xmm1) vfmadd231ps(xmm1, xmm3, xmm9) vmovsd(xmm9, mem(rcx, 4*4)) add(rdi, rcx) vextractf128(imm(0x1), ymm10, xmm11) vfmadd231ps(mem(rcx, 0*4), xmm3, xmm10) vmovups(xmm10, mem(rcx, 0*4)) vmovsd(mem(rcx, 4*4), xmm1) vfmadd231ps(xmm1, xmm3, xmm11) vmovsd(xmm11, mem(rcx, 4*4)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORED) // begin I/O on columns 0-5 vunpcklps(ymm6, ymm4, ymm0) vunpcklps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx ), xmm3, xmm0) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm0, mem(rcx )) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx, rsi, 1), xmm3, xmm1) vfmadd231ps(mem(rcx, rbx, 1), xmm3, xmm2) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rbx, 1)) // store ( gamma05..gamma35 ) vunpckhps(ymm6, ymm4, ymm0) vunpckhps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vfmadd231ps(mem(rcx, rsi, 2), xmm3, xmm0) vmovups(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma32 ) vfmadd231ps(mem(rcx, rax, 1), xmm3, xmm1) vmovups(xmm1, mem(rcx, rax, 1)) // store ( gamma03..gamma33 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vextractf128(imm(0x1), ymm4, xmm5) vmovups(xmm4, mem(rcx, 0*4)) vmovsd(xmm5, mem(rcx, 4*4)) add(rdi, rcx) vextractf128(imm(0x1), ymm6, xmm7) vmovups(xmm6, mem(rcx, 0*4)) vmovsd(xmm7, mem(rcx, 4*4)) add(rdi, rcx) vextractf128(imm(0x1), ymm8, xmm9) vmovups(xmm8, mem(rcx, 0*4)) vmovsd(xmm9, mem(rcx, 4*4)) add(rdi, rcx) vextractf128(imm(0x1), ymm10, xmm11) vmovups(xmm10, mem(rcx, 0*4)) vmovsd(xmm11, mem(rcx, 4*4)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) // begin I/O on columns 0-5 vunpcklps(ymm6, ymm4, ymm0) vunpcklps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx )) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rbx, 1)) // store ( gamma05..gamma35 ) vunpckhps(ymm6, ymm4, ymm0) vunpckhps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vmovups(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma32 ) vmovups(xmm1, mem(rcx, rax, 1)) // store ( gamma03..gamma33 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c label(.SDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_sgemmsup_rv_haswell_asm_3x6 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) //lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored prefetching on c lea(mem(rcx, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 5*4)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 5*4)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 5*4)) // prefetch c + 2*rs_c jmp(.SPOSTPFETCH) // jump to end of prefetching c label(.SCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) lea(mem(rsi, rsi, 2), rbp) // rbp = 3*cs_c; prefetch(0, mem(rcx, 2*4)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 2*4)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 2*4)) // prefetch c + 2*cs_c prefetch(0, mem(rcx, rbp, 1, 2*4)) // prefetch c + 3*cs_c prefetch(0, mem(rcx, rsi, 4, 2*4)) // prefetch c + 4*cs_c lea(mem(rcx, rsi, 4), rdx) // rdx = c + 4*cs_c; prefetch(0, mem(rdx, rsi, 1, 2*4)) // prefetch c + 5*cs_c label(.SPOSTPFETCH) // done prefetching c #if 1 lea(mem(rax, r9, 8), rdx) // lea(mem(rdx, r9, 8), rdx) // rdx = a + 16*cs_a; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(rdx, 5*8)) #endif vmovups(mem(rbx, 0*4), xmm0) vmovsd(mem(rbx, 4*4), xmm1) vinsertf128(imm(0x1), xmm1, ymm0, ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm8) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, r9, 1, 5*8)) #endif vmovups(mem(rbx, 0*4), xmm0) vmovsd(mem(rbx, 4*4), xmm1) vinsertf128(imm(0x1), xmm1, ymm0, ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm8) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(rdx, r9, 2, 5*8)) #endif vmovups(mem(rbx, 0*4), xmm0) vmovsd(mem(rbx, 4*4), xmm1) vinsertf128(imm(0x1), xmm1, ymm0, ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm8) // ---------------------------------- iteration 3 #if 1 lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; #endif vmovups(mem(rbx, 0*4), xmm0) vmovsd(mem(rbx, 4*4), xmm1) vinsertf128(imm(0x1), xmm1, ymm0, ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm8) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP #if 0 prefetch(0, mem(rdx, 5*8)) add(r9, rdx) #endif vmovups(mem(rbx, 0*4), xmm0) vmovsd(mem(rbx, 4*4), xmm1) vinsertf128(imm(0x1), xmm1, ymm0, ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm8) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), ymm0) // load alpha and duplicate vbroadcastss(mem(rbx), ymm3) // load beta and duplicate vmulps(ymm0, ymm4, ymm4) // scale by alpha vmulps(ymm0, ymm6, ymm6) vmulps(ymm0, ymm8, ymm8) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; lea(mem(rcx, rdi, 2), rdx) // load address of c + 2*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; lea(mem(rsi, rsi, 4), rbx) // rbx = 5*cs_c; //lea(mem(rax, rsi, 4), rbp) // rbp = 7*cs_c; // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vextractf128(imm(0x1), ymm4, xmm5) vfmadd231ps(mem(rcx, 0*4), xmm3, xmm4) vmovups(xmm4, mem(rcx, 0*4)) vmovsd(mem(rcx, 4*4), xmm1) vfmadd231ps(xmm1, xmm3, xmm5) vmovsd(xmm5, mem(rcx, 4*4)) add(rdi, rcx) vextractf128(imm(0x1), ymm6, xmm7) vfmadd231ps(mem(rcx, 0*4), xmm3, xmm6) vmovups(xmm6, mem(rcx, 0*4)) vmovsd(mem(rcx, 4*4), xmm1) vfmadd231ps(xmm1, xmm3, xmm7) vmovsd(xmm7, mem(rcx, 4*4)) add(rdi, rcx) vextractf128(imm(0x1), ymm8, xmm9) vfmadd231ps(mem(rcx, 0*4), xmm3, xmm8) vmovups(xmm8, mem(rcx, 0*4)) vmovsd(mem(rcx, 4*4), xmm1) vfmadd231ps(xmm1, xmm3, xmm9) vmovsd(xmm9, mem(rcx, 4*4)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORED) // begin I/O on columns 0-5 vunpcklps(ymm6, ymm4, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(mem(rcx ), xmm1, xmm1) vmovhpd(mem(rcx, rsi, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(rcx )) // store ( gamma00..gamma10 ) vmovhpd(xmm0, mem(rcx, rsi, 1)) // store ( gamma01..gamma11 ) vmovlpd(mem(rcx, rsi, 4), xmm1, xmm1) vmovhpd(mem(rcx, rbx, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm2) vmovlpd(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma14 ) vmovhpd(xmm2, mem(rcx, rbx, 1)) // store ( gamma05..gamma15 ) vunpckhps(ymm6, ymm4, ymm0) vmovlpd(mem(rcx, rsi, 2), xmm1, xmm1) vmovhpd(mem(rcx, rax, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma12 ) vmovhpd(xmm0, mem(rcx, rax, 1)) // store ( gamma03..gamma13 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vmovups(ymm8, ymm0) vextractf128(imm(0x1), ymm0, xmm8) vpermilps(imm(0xe4), xmm0, xmm2) vpermilps(imm(0x39), xmm0, xmm4) vmovss(mem(rdx ), xmm1) vmovss(mem(rdx, rsi, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rdx )) // store ( gamma40 ) vmovss(xmm4, mem(rdx, rsi, 1)) // store ( gamma41 ) vpermilps(imm(0x4e), xmm0, xmm2) vpermilps(imm(0x93), xmm0, xmm4) vmovss(mem(rdx, rsi, 2), xmm1) vmovss(mem(rdx, rax, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rdx, rsi, 2)) // store ( gamma42 ) vmovss(xmm4, mem(rdx, rax, 1)) // store ( gamma43 ) vpermilps(imm(0xe4), xmm8, xmm2) vpermilps(imm(0x39), xmm8, xmm4) vmovss(mem(rdx, rsi, 4), xmm1) vmovss(mem(rdx, rbx, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rdx, rsi, 4)) // store ( gamma44 ) vmovss(xmm4, mem(rdx, rbx, 1)) // store ( gamma45 ) //lea(mem(rdx, rsi, 8), rdx) // rdx += 8*cs_c jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vextractf128(imm(0x1), ymm4, xmm5) vmovups(xmm4, mem(rcx, 0*4)) vmovsd(xmm5, mem(rcx, 4*4)) add(rdi, rcx) vextractf128(imm(0x1), ymm6, xmm7) vmovups(xmm6, mem(rcx, 0*4)) vmovsd(xmm7, mem(rcx, 4*4)) add(rdi, rcx) vextractf128(imm(0x1), ymm8, xmm9) vmovups(xmm8, mem(rcx, 0*4)) vmovsd(xmm9, mem(rcx, 4*4)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) // begin I/O on columns 0-5 vunpcklps(ymm6, ymm4, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(xmm0, mem(rcx )) // store ( gamma00..gamma10 ) vmovhpd(xmm0, mem(rcx, rsi, 1)) // store ( gamma01..gamma11 ) vmovlpd(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma14 ) vmovhpd(xmm2, mem(rcx, rbx, 1)) // store ( gamma05..gamma15 ) vunpckhps(ymm6, ymm4, ymm0) vmovlpd(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma12 ) vmovhpd(xmm0, mem(rcx, rax, 1)) // store ( gamma03..gamma13 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vmovups(ymm8, ymm0) vextractf128(imm(0x1), ymm0, xmm8) vpermilps(imm(0xe4), xmm0, xmm2) vpermilps(imm(0x39), xmm0, xmm4) vmovss(xmm2, mem(rdx )) // store ( gamma40 ) vmovss(xmm4, mem(rdx, rsi, 1)) // store ( gamma41 ) vpermilps(imm(0x4e), xmm0, xmm2) vpermilps(imm(0x93), xmm0, xmm4) vmovss(xmm2, mem(rdx, rsi, 2)) // store ( gamma42 ) vmovss(xmm4, mem(rdx, rax, 1)) // store ( gamma43 ) vpermilps(imm(0xe4), xmm8, xmm2) vpermilps(imm(0x39), xmm8, xmm4) vmovss(xmm2, mem(rdx, rsi, 4)) // store ( gamma44 ) vmovss(xmm4, mem(rdx, rbx, 1)) // store ( gamma45 ) //lea(mem(rdx, rsi, 8), rdx) // rdx += 8*cs_c label(.SDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_sgemmsup_rv_haswell_asm_2x6 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) //lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored prefetching on c lea(mem(rcx, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 5*4)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 5*4)) // prefetch c + 1*rs_c jmp(.SPOSTPFETCH) // jump to end of prefetching c label(.SCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) lea(mem(rsi, rsi, 2), rbp) // rbp = 3*cs_c; prefetch(0, mem(rcx, 1*4)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 1*4)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 1*4)) // prefetch c + 2*cs_c prefetch(0, mem(rcx, rbp, 1, 1*4)) // prefetch c + 3*cs_c prefetch(0, mem(rcx, rsi, 4, 1*4)) // prefetch c + 4*cs_c lea(mem(rcx, rsi, 4), rdx) // rdx = c + 4*cs_c; prefetch(0, mem(rdx, rsi, 1, 1*4)) // prefetch c + 5*cs_c label(.SPOSTPFETCH) // done prefetching c #if 1 lea(mem(rax, r9, 8), rdx) // lea(mem(rdx, r9, 8), rdx) // rdx = a + 16*cs_a; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(rdx, 5*8)) #endif vmovups(mem(rbx, 0*4), xmm0) vmovsd(mem(rbx, 4*4), xmm1) vinsertf128(imm(0x1), xmm1, ymm0, ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, r9, 1, 5*8)) #endif vmovups(mem(rbx, 0*4), xmm0) vmovsd(mem(rbx, 4*4), xmm1) vinsertf128(imm(0x1), xmm1, ymm0, ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(rdx, r9, 2, 5*8)) #endif vmovups(mem(rbx, 0*4), xmm0) vmovsd(mem(rbx, 4*4), xmm1) vinsertf128(imm(0x1), xmm1, ymm0, ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) // ---------------------------------- iteration 3 #if 1 lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; #endif vmovups(mem(rbx, 0*4), xmm0) vmovsd(mem(rbx, 4*4), xmm1) vinsertf128(imm(0x1), xmm1, ymm0, ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP #if 0 prefetch(0, mem(rdx, 5*8)) add(r9, rdx) #endif vmovups(mem(rbx, 0*4), xmm0) vmovsd(mem(rbx, 4*4), xmm1) vinsertf128(imm(0x1), xmm1, ymm0, ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), ymm0) // load alpha and duplicate vbroadcastss(mem(rbx), ymm3) // load beta and duplicate vmulps(ymm0, ymm4, ymm4) // scale by alpha vmulps(ymm0, ymm6, ymm6) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; //lea(mem(rcx, rdi, 2), rdx) // load address of c + 2*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; lea(mem(rsi, rsi, 4), rbx) // rbx = 5*cs_c; //lea(mem(rax, rsi, 4), rbp) // rbp = 7*cs_c; // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vextractf128(imm(0x1), ymm4, xmm5) vfmadd231ps(mem(rcx, 0*4), xmm3, xmm4) vmovups(xmm4, mem(rcx, 0*4)) vmovsd(mem(rcx, 4*4), xmm1) vfmadd231ps(xmm1, xmm3, xmm5) vmovsd(xmm5, mem(rcx, 4*4)) add(rdi, rcx) vextractf128(imm(0x1), ymm6, xmm7) vfmadd231ps(mem(rcx, 0*4), xmm3, xmm6) vmovups(xmm6, mem(rcx, 0*4)) vmovsd(mem(rcx, 4*4), xmm1) vfmadd231ps(xmm1, xmm3, xmm7) vmovsd(xmm7, mem(rcx, 4*4)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORED) // begin I/O on columns 0-5 vunpcklps(ymm6, ymm4, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(mem(rcx ), xmm1, xmm1) vmovhpd(mem(rcx, rsi, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(rcx )) // store ( gamma00..gamma10 ) vmovhpd(xmm0, mem(rcx, rsi, 1)) // store ( gamma01..gamma11 ) vmovlpd(mem(rcx, rsi, 4), xmm1, xmm1) vmovhpd(mem(rcx, rbx, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm2) vmovlpd(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma14 ) vmovhpd(xmm2, mem(rcx, rbx, 1)) // store ( gamma05..gamma15 ) vunpckhps(ymm6, ymm4, ymm0) vmovlpd(mem(rcx, rsi, 2), xmm1, xmm1) vmovhpd(mem(rcx, rax, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma12 ) vmovhpd(xmm0, mem(rcx, rax, 1)) // store ( gamma03..gamma13 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vextractf128(imm(0x1), ymm4, xmm5) vmovups(xmm4, mem(rcx, 0*4)) vmovsd(xmm5, mem(rcx, 4*4)) add(rdi, rcx) vextractf128(imm(0x1), ymm6, xmm7) vmovups(xmm6, mem(rcx, 0*4)) vmovsd(xmm7, mem(rcx, 4*4)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) // begin I/O on columns 0-5 vunpcklps(ymm6, ymm4, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(xmm0, mem(rcx )) // store ( gamma00..gamma10 ) vmovhpd(xmm0, mem(rcx, rsi, 1)) // store ( gamma01..gamma11 ) vmovlpd(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma14 ) vmovhpd(xmm2, mem(rcx, rbx, 1)) // store ( gamma05..gamma15 ) vunpckhps(ymm6, ymm4, ymm0) vmovlpd(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma12 ) vmovhpd(xmm0, mem(rcx, rax, 1)) // store ( gamma03..gamma13 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c label(.SDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_sgemmsup_rv_haswell_asm_1x6 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) //lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored prefetching on c lea(mem(rcx, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 5*4)) // prefetch c + 0*rs_c jmp(.SPOSTPFETCH) // jump to end of prefetching c label(.SCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) lea(mem(rsi, rsi, 2), rbp) // rbp = 3*cs_c; prefetch(0, mem(rcx, 0*4)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 0*4)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 0*4)) // prefetch c + 2*cs_c prefetch(0, mem(rcx, rbp, 1, 0*4)) // prefetch c + 3*cs_c prefetch(0, mem(rcx, rsi, 4, 0*4)) // prefetch c + 4*cs_c lea(mem(rcx, rsi, 4), rdx) // rdx = c + 4*cs_c; prefetch(0, mem(rdx, rsi, 1, 0*4)) // prefetch c + 5*cs_c label(.SPOSTPFETCH) // done prefetching c #if 1 lea(mem(rax, r9, 8), rdx) // lea(mem(rdx, r9, 8), rdx) // rdx = a + 16*cs_a; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(rdx, 5*8)) #endif vmovups(mem(rbx, 0*4), xmm0) vmovsd(mem(rbx, 4*4), xmm1) vinsertf128(imm(0x1), xmm1, ymm0, ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, r9, 1, 5*8)) #endif vmovups(mem(rbx, 0*4), xmm0) vmovsd(mem(rbx, 4*4), xmm1) vinsertf128(imm(0x1), xmm1, ymm0, ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(rdx, r9, 2, 5*8)) #endif vmovups(mem(rbx, 0*4), xmm0) vmovsd(mem(rbx, 4*4), xmm1) vinsertf128(imm(0x1), xmm1, ymm0, ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) // ---------------------------------- iteration 3 #if 1 lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; #endif vmovups(mem(rbx, 0*4), xmm0) vmovsd(mem(rbx, 4*4), xmm1) vinsertf128(imm(0x1), xmm1, ymm0, ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP #if 0 prefetch(0, mem(rdx, 5*8)) add(r9, rdx) #endif vmovups(mem(rbx, 0*4), xmm0) vmovsd(mem(rbx, 4*4), xmm1) vinsertf128(imm(0x1), xmm1, ymm0, ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), ymm0) // load alpha and duplicate vbroadcastss(mem(rbx), ymm3) // load beta and duplicate vmulps(ymm0, ymm4, ymm4) // scale by alpha mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; //lea(mem(rcx, rdi, 2), rdx) // load address of c + 2*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; lea(mem(rsi, rsi, 4), rbx) // rbx = 5*cs_c; //lea(mem(rax, rsi, 4), rbp) // rbp = 7*cs_c; // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vextractf128(imm(0x1), ymm4, xmm5) vfmadd231ps(mem(rcx, 0*4), xmm3, xmm4) vmovups(xmm4, mem(rcx, 0*4)) vmovsd(mem(rcx, 4*4), xmm1) vfmadd231ps(xmm1, xmm3, xmm5) vmovsd(xmm5, mem(rcx, 4*4)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORED) // begin I/O on columns 0-5 vmovups(ymm4, ymm0) vextractf128(imm(0x1), ymm0, xmm8) vpermilps(imm(0xe4), xmm0, xmm2) vpermilps(imm(0x39), xmm0, xmm4) vmovss(mem(rcx ), xmm1) vmovss(mem(rcx, rsi, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rcx )) // store ( gamma40 ) vmovss(xmm4, mem(rcx, rsi, 1)) // store ( gamma41 ) vpermilps(imm(0x4e), xmm0, xmm2) vpermilps(imm(0x93), xmm0, xmm4) vmovss(mem(rcx, rsi, 2), xmm1) vmovss(mem(rcx, rax, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rcx, rsi, 2)) // store ( gamma42 ) vmovss(xmm4, mem(rcx, rax, 1)) // store ( gamma43 ) vpermilps(imm(0xe4), xmm8, xmm2) vpermilps(imm(0x39), xmm8, xmm4) vmovss(mem(rcx, rsi, 4), xmm1) vmovss(mem(rcx, rbx, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rcx, rsi, 4)) // store ( gamma44 ) vmovss(xmm4, mem(rcx, rbx, 1)) // store ( gamma45 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vextractf128(imm(0x1), ymm4, xmm5) vmovups(xmm4, mem(rcx, 0*4)) vmovsd(xmm5, mem(rcx, 4*4)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) // begin I/O on columns 0-7 vmovups(ymm4, ymm0) vextractf128(imm(0x1), ymm0, xmm8) vpermilps(imm(0xe4), xmm0, xmm2) vpermilps(imm(0x39), xmm0, xmm4) vmovss(xmm2, mem(rcx )) // store ( gamma40 ) vmovss(xmm4, mem(rcx, rsi, 1)) // store ( gamma41 ) vpermilps(imm(0x4e), xmm0, xmm2) vpermilps(imm(0x93), xmm0, xmm4) vmovss(xmm2, mem(rcx, rsi, 2)) // store ( gamma42 ) vmovss(xmm4, mem(rcx, rax, 1)) // store ( gamma43 ) vpermilps(imm(0xe4), xmm8, xmm2) vpermilps(imm(0x39), xmm8, xmm4) vmovss(xmm2, mem(rcx, rsi, 4)) // store ( gamma44 ) vmovss(xmm4, mem(rcx, rbx, 1)) // store ( gamma45 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c label(.SDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } #if 0 void bli_sgemmsup_rv_haswell_asm_1x6 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) //lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored prefetching on c //lea(mem(rcx, rdi, 2), rdx) // //lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c jmp(.SPOSTPFETCH) // jump to end of prefetching c label(.SCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) lea(mem(rsi, rsi, 2), rbp) // rbp = 3*cs_c; prefetch(0, mem(rcx, 0*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 0*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 0*8)) // prefetch c + 2*cs_c prefetch(0, mem(rcx, rbp, 1, 0*8)) // prefetch c + 3*cs_c prefetch(0, mem(rcx, rsi, 4, 0*8)) // prefetch c + 4*cs_c lea(mem(rcx, rsi, 4), rdx) // rdx = c + 4*cs_c; prefetch(0, mem(rdx, rsi, 1, 0*8)) // prefetch c + 5*cs_c prefetch(0, mem(rdx, rsi, 2, 0*8)) // prefetch c + 6*cs_c prefetch(0, mem(rdx, rbp, 1, 0*8)) // prefetch c + 7*cs_c label(.SPOSTPFETCH) // done prefetching c #if 1 lea(mem(rax, r9, 8), rdx) // lea(mem(rdx, r9, 8), rdx) // rdx = a + 16*cs_a; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(rdx, 4*8)) #endif vmovups(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, r9, 1, 4*8)) #endif vmovups(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(rdx, r9, 2, 4*8)) #endif vmovups(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) // ---------------------------------- iteration 3 #if 1 lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; #endif vmovups(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP #if 0 prefetch(0, mem(rdx, 5*8)) add(r9, rdx) #endif vmovups(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), ymm0) // load alpha and duplicate vbroadcastss(mem(rbx), ymm3) // load beta and duplicate vmulps(ymm0, ymm4, ymm4) // scale by alpha mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; //lea(mem(rcx, rdi, 2), rdx) // load address of c + 2*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; lea(mem(rsi, rsi, 4), rbx) // rbx = 5*cs_c; lea(mem(rax, rsi, 4), rbp) // rbp = 7*cs_c; // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm4) vmovups(ymm4, mem(rcx, 0*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORED) // begin I/O on columns 0-7 vmovups(ymm4, ymm0) vextractf128(imm(0x1), ymm0, xmm8) vpermilps(imm(0xe4), xmm0, xmm2) vpermilps(imm(0x39), xmm0, xmm4) vmovss(mem(rcx ), xmm1) vmovss(mem(rcx, rsi, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rcx )) // store ( gamma40 ) vmovss(xmm4, mem(rcx, rsi, 1)) // store ( gamma41 ) vpermilps(imm(0x4e), xmm0, xmm2) vpermilps(imm(0x93), xmm0, xmm4) vmovss(mem(rcx, rsi, 2), xmm1) vmovss(mem(rcx, rax, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rcx, rsi, 2)) // store ( gamma42 ) vmovss(xmm4, mem(rcx, rax, 1)) // store ( gamma43 ) vpermilps(imm(0xe4), xmm8, xmm2) vpermilps(imm(0x39), xmm8, xmm4) vmovss(mem(rcx, rsi, 4), xmm1) vmovss(mem(rcx, rbx, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rcx, rsi, 4)) // store ( gamma44 ) vmovss(xmm4, mem(rcx, rbx, 1)) // store ( gamma45 ) vpermilps(imm(0x4e), xmm8, xmm2) vpermilps(imm(0x93), xmm8, xmm4) vmovss(mem(rcx, rax, 2), xmm1) vmovss(mem(rcx, rbp, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rcx, rax, 2)) // store ( gamma46 ) vmovss(xmm4, mem(rcx, rbp, 1)) // store ( gamma47 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (8*rs_c) == 8. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovups(ymm4, mem(rcx, 0*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) // begin I/O on columns 0-7 vmovups(ymm4, ymm0) vextractf128(imm(0x1), ymm0, xmm8) vpermilps(imm(0xe4), xmm0, xmm2) vpermilps(imm(0x39), xmm0, xmm4) vmovss(xmm2, mem(rcx )) // store ( gamma40 ) vmovss(xmm4, mem(rcx, rsi, 1)) // store ( gamma41 ) vpermilps(imm(0x4e), xmm0, xmm2) vpermilps(imm(0x93), xmm0, xmm4) vmovss(xmm2, mem(rcx, rsi, 2)) // store ( gamma42 ) vmovss(xmm4, mem(rcx, rax, 1)) // store ( gamma43 ) vpermilps(imm(0xe4), xmm8, xmm2) vpermilps(imm(0x39), xmm8, xmm4) vmovss(xmm2, mem(rcx, rsi, 4)) // store ( gamma44 ) vmovss(xmm4, mem(rcx, rbx, 1)) // store ( gamma45 ) vpermilps(imm(0x4e), xmm8, xmm2) vpermilps(imm(0x93), xmm8, xmm4) vmovss(xmm2, mem(rcx, rax, 2)) // store ( gamma46 ) vmovss(xmm4, mem(rcx, rbp, 1)) // store ( gamma47 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c label(.SDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } #endif blis-0.9.0/kernels/haswell/3/sup/s6x16/bli_gemmsup_rv_haswell_asm_sMx8.c000066400000000000000000002452031422157504600261030ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define BLIS_ASM_SYNTAX_ATT #include "bli_x86_asm_macros.h" /* rrr: -------- ------ -------- -------- ------ -------- -------- += ------ ... -------- -------- ------ -------- -------- ------ : -------- ------ : rcr: -------- | | | | -------- -------- | | | | -------- -------- += | | | | ... -------- -------- | | | | -------- -------- | | | | : -------- | | | | : Assumptions: - B is row-stored; - A is row- or column-stored; - m0 and n0 are at most MR and NR, respectively. Therefore, this (r)ow-preferential kernel is well-suited for contiguous (v)ector loads on B and single-element broadcasts from A. NOTE: These kernels explicitly support column-oriented IO, implemented via an in-register transpose. And thus they also support the crr and ccr cases, though only crr is ever utilized (because ccr is handled by transposing the operation and executing rcr, which does not incur the cost of the in-register transpose). crr: | | | | | | | | ------ -------- | | | | | | | | ------ -------- | | | | | | | | += ------ ... -------- | | | | | | | | ------ -------- | | | | | | | | ------ : | | | | | | | | ------ : */ // Prototype reference microkernels. GEMMSUP_KER_PROT( float, s, gemmsup_r_haswell_ref ) void bli_sgemmsup_rv_haswell_asm_6x8 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) //lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored prefetching on c lea(mem(rcx, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 7*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 7*8)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 7*8)) // prefetch c + 3*rs_c prefetch(0, mem(rdx, rdi, 1, 7*8)) // prefetch c + 4*rs_c prefetch(0, mem(rdx, rdi, 2, 7*8)) // prefetch c + 5*rs_c jmp(.SPOSTPFETCH) // jump to end of prefetching c label(.SCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) lea(mem(rsi, rsi, 2), rbp) // rbp = 3*cs_c; prefetch(0, mem(rcx, 5*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 5*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 5*8)) // prefetch c + 2*cs_c prefetch(0, mem(rcx, rbp, 1, 5*8)) // prefetch c + 3*cs_c prefetch(0, mem(rcx, rsi, 4, 5*8)) // prefetch c + 4*cs_c lea(mem(rcx, rsi, 4), rdx) // rdx = c + 4*cs_c; prefetch(0, mem(rdx, rsi, 1, 5*8)) // prefetch c + 5*cs_c prefetch(0, mem(rdx, rsi, 2, 5*8)) // prefetch c + 6*cs_c prefetch(0, mem(rdx, rbp, 1, 5*8)) // prefetch c + 7*cs_c label(.SPOSTPFETCH) // done prefetching c #if 1 lea(mem(rax, r9, 8), rdx) // lea(mem(rdx, r9, 8), rdx) // rdx = a + 16*cs_a; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(rdx, 5*8)) #endif vmovups(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm0, ymm3, ymm10) vbroadcastss(mem(rax, r8, 4), ymm2) vbroadcastss(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm0, ymm3, ymm14) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, r9, 1, 5*8)) #endif vmovups(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm0, ymm3, ymm10) vbroadcastss(mem(rax, r8, 4), ymm2) vbroadcastss(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm0, ymm3, ymm14) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(rdx, r9, 2, 5*8)) #endif vmovups(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm0, ymm3, ymm10) vbroadcastss(mem(rax, r8, 4), ymm2) vbroadcastss(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm0, ymm3, ymm14) // ---------------------------------- iteration 3 #if 1 lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; #endif vmovups(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm0, ymm3, ymm10) vbroadcastss(mem(rax, r8, 4), ymm2) vbroadcastss(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm0, ymm3, ymm14) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP #if 0 prefetch(0, mem(rdx, 5*8)) add(r9, rdx) #endif vmovups(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm0, ymm3, ymm10) vbroadcastss(mem(rax, r8, 4), ymm2) vbroadcastss(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm0, ymm3, ymm14) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), ymm0) // load alpha and duplicate vbroadcastss(mem(rbx), ymm3) // load beta and duplicate vmulps(ymm0, ymm4, ymm4) // scale by alpha vmulps(ymm0, ymm6, ymm6) vmulps(ymm0, ymm8, ymm8) vmulps(ymm0, ymm10, ymm10) vmulps(ymm0, ymm12, ymm12) vmulps(ymm0, ymm14, ymm14) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; lea(mem(rsi, rsi, 4), rbx) // rbx = 5*cs_c; lea(mem(rax, rsi, 4), rbp) // rbp = 7*cs_c; // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm4) vmovups(ymm4, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm6) vmovups(ymm6, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm8) vmovups(ymm8, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm10) vmovups(ymm10, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm12) vmovups(ymm12, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm14) vmovups(ymm14, mem(rcx, 0*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORED) // begin I/O on columns 0-7 vunpcklps(ymm6, ymm4, ymm0) vunpcklps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx ), xmm3, xmm0) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm0, mem(rcx )) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx, rsi, 1), xmm3, xmm1) vfmadd231ps(mem(rcx, rbx, 1), xmm3, xmm2) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rbx, 1)) // store ( gamma05..gamma35 ) vunpckhps(ymm6, ymm4, ymm0) vunpckhps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx, rsi, 2), xmm3, xmm0) vfmadd231ps(mem(rcx, rax, 2), xmm3, xmm2) vmovups(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, rax, 2)) // store ( gamma06..gamma36 ) vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx, rax, 1), xmm3, xmm1) vfmadd231ps(mem(rcx, rbp, 1), xmm3, xmm2) vmovups(xmm1, mem(rcx, rax, 1)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, rbp, 1)) // store ( gamma07..gamma37 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vunpcklps(ymm14, ymm12, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(mem(rdx ), xmm1, xmm1) vmovhpd(mem(rdx, rsi, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(rdx )) // store ( gamma40..gamma50 ) vmovhpd(xmm0, mem(rdx, rsi, 1)) // store ( gamma41..gamma51 ) vmovlpd(mem(rdx, rsi, 4), xmm1, xmm1) vmovhpd(mem(rdx, rbx, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm2) vmovlpd(xmm2, mem(rdx, rsi, 4)) // store ( gamma44..gamma54 ) vmovhpd(xmm2, mem(rdx, rbx, 1)) // store ( gamma45..gamma55 ) vunpckhps(ymm14, ymm12, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(mem(rdx, rsi, 2), xmm1, xmm1) vmovhpd(mem(rdx, rax, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(rdx, rsi, 2)) // store ( gamma42..gamma52 ) vmovhpd(xmm0, mem(rdx, rax, 1)) // store ( gamma43..gamma53 ) vmovlpd(mem(rdx, rax, 2), xmm1, xmm1) vmovhpd(mem(rdx, rbp, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm2) vmovlpd(xmm2, mem(rdx, rax, 2)) // store ( gamma46..gamma56 ) vmovhpd(xmm2, mem(rdx, rbp, 1)) // store ( gamma47..gamma57 ) //lea(mem(rdx, rsi, 8), rdx) // rdx += 8*cs_c jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovups(ymm4, mem(rcx, 0*32)) add(rdi, rcx) vmovups(ymm6, mem(rcx, 0*32)) add(rdi, rcx) vmovups(ymm8, mem(rcx, 0*32)) add(rdi, rcx) vmovups(ymm10, mem(rcx, 0*32)) add(rdi, rcx) vmovups(ymm12, mem(rcx, 0*32)) add(rdi, rcx) vmovups(ymm14, mem(rcx, 0*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) // begin I/O on columns 0-7 vunpcklps(ymm6, ymm4, ymm0) vunpcklps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx )) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rbx, 1)) // store ( gamma05..gamma35 ) vunpckhps(ymm6, ymm4, ymm0) vunpckhps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, rax, 2)) // store ( gamma06..gamma36 ) vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx, rax, 1)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, rbp, 1)) // store ( gamma07..gamma37 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vunpcklps(ymm14, ymm12, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(xmm0, mem(rdx )) // store ( gamma40..gamma50 ) vmovhpd(xmm0, mem(rdx, rsi, 1)) // store ( gamma41..gamma51 ) vmovlpd(xmm2, mem(rdx, rsi, 4)) // store ( gamma44..gamma54 ) vmovhpd(xmm2, mem(rdx, rbx, 1)) // store ( gamma45..gamma55 ) vunpckhps(ymm14, ymm12, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(xmm0, mem(rdx, rsi, 2)) // store ( gamma42..gamma52 ) vmovhpd(xmm0, mem(rdx, rax, 1)) // store ( gamma43..gamma53 ) vmovlpd(xmm2, mem(rdx, rax, 2)) // store ( gamma46..gamma56 ) vmovhpd(xmm2, mem(rdx, rbp, 1)) // store ( gamma47..gamma57 ) //lea(mem(rdx, rsi, 8), rdx) // rdx += 8*cs_c label(.SDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_sgemmsup_rv_haswell_asm_5x8 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) //lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored prefetching on c lea(mem(rcx, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 7*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 7*8)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 7*8)) // prefetch c + 3*rs_c prefetch(0, mem(rdx, rdi, 1, 7*8)) // prefetch c + 4*rs_c jmp(.SPOSTPFETCH) // jump to end of prefetching c label(.SCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) lea(mem(rsi, rsi, 2), rbp) // rbp = 3*cs_c; prefetch(0, mem(rcx, 4*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 4*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 4*8)) // prefetch c + 2*cs_c prefetch(0, mem(rcx, rbp, 1, 4*8)) // prefetch c + 3*cs_c prefetch(0, mem(rcx, rsi, 4, 4*8)) // prefetch c + 4*cs_c lea(mem(rcx, rsi, 4), rdx) // rdx = c + 4*cs_c; prefetch(0, mem(rdx, rsi, 1, 4*8)) // prefetch c + 5*cs_c prefetch(0, mem(rdx, rsi, 2, 4*8)) // prefetch c + 6*cs_c prefetch(0, mem(rdx, rbp, 1, 4*8)) // prefetch c + 7*cs_c label(.SPOSTPFETCH) // done prefetching c #if 1 lea(mem(rax, r9, 8), rdx) // lea(mem(rdx, r9, 8), rdx) // rdx = a + 16*cs_a; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(rdx, 4*8)) #endif vmovups(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm0, ymm3, ymm10) vbroadcastss(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, r9, 1, 4*8)) #endif vmovups(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm0, ymm3, ymm10) vbroadcastss(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(rdx, r9, 2, 4*8)) #endif vmovups(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm0, ymm3, ymm10) vbroadcastss(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) // ---------------------------------- iteration 3 #if 1 lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; #endif vmovups(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm0, ymm3, ymm10) vbroadcastss(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP #if 0 prefetch(0, mem(rdx, 5*8)) add(r9, rdx) #endif vmovups(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm0, ymm3, ymm10) vbroadcastss(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), ymm0) // load alpha and duplicate vbroadcastss(mem(rbx), ymm3) // load beta and duplicate vmulps(ymm0, ymm4, ymm4) // scale by alpha vmulps(ymm0, ymm6, ymm6) vmulps(ymm0, ymm8, ymm8) vmulps(ymm0, ymm10, ymm10) vmulps(ymm0, ymm12, ymm12) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; lea(mem(rsi, rsi, 4), rbx) // rbx = 5*cs_c; lea(mem(rax, rsi, 4), rbp) // rbp = 7*cs_c; // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm4) vmovups(ymm4, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm6) vmovups(ymm6, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm8) vmovups(ymm8, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm10) vmovups(ymm10, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm12) vmovups(ymm12, mem(rcx, 0*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORED) // begin I/O on columns 0-7 vunpcklps(ymm6, ymm4, ymm0) vunpcklps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx ), xmm3, xmm0) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm0, mem(rcx )) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx, rsi, 1), xmm3, xmm1) vfmadd231ps(mem(rcx, rbx, 1), xmm3, xmm2) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rbx, 1)) // store ( gamma05..gamma35 ) vunpckhps(ymm6, ymm4, ymm0) vunpckhps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx, rsi, 2), xmm3, xmm0) vfmadd231ps(mem(rcx, rax, 2), xmm3, xmm2) vmovups(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, rax, 2)) // store ( gamma06..gamma36 ) vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx, rax, 1), xmm3, xmm1) vfmadd231ps(mem(rcx, rbp, 1), xmm3, xmm2) vmovups(xmm1, mem(rcx, rax, 1)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, rbp, 1)) // store ( gamma07..gamma37 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vmovups(ymm12, ymm0) vextractf128(imm(0x1), ymm0, xmm8) vpermilps(imm(0xe4), xmm0, xmm2) vpermilps(imm(0x39), xmm0, xmm4) vmovss(mem(rdx ), xmm1) vmovss(mem(rdx, rsi, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rdx )) // store ( gamma40 ) vmovss(xmm4, mem(rdx, rsi, 1)) // store ( gamma41 ) vpermilps(imm(0x4e), xmm0, xmm2) vpermilps(imm(0x93), xmm0, xmm4) vmovss(mem(rdx, rsi, 2), xmm1) vmovss(mem(rdx, rax, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rdx, rsi, 2)) // store ( gamma42 ) vmovss(xmm4, mem(rdx, rax, 1)) // store ( gamma43 ) vpermilps(imm(0xe4), xmm8, xmm2) vpermilps(imm(0x39), xmm8, xmm4) vmovss(mem(rdx, rsi, 4), xmm1) vmovss(mem(rdx, rbx, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rdx, rsi, 4)) // store ( gamma44 ) vmovss(xmm4, mem(rdx, rbx, 1)) // store ( gamma45 ) vpermilps(imm(0x4e), xmm8, xmm2) vpermilps(imm(0x93), xmm8, xmm4) vmovss(mem(rdx, rax, 2), xmm1) vmovss(mem(rdx, rbp, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rdx, rax, 2)) // store ( gamma46 ) vmovss(xmm4, mem(rdx, rbp, 1)) // store ( gamma47 ) //lea(mem(rdx, rsi, 8), rdx) // rdx += 8*cs_c jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovups(ymm4, mem(rcx, 0*32)) add(rdi, rcx) vmovups(ymm6, mem(rcx, 0*32)) add(rdi, rcx) vmovups(ymm8, mem(rcx, 0*32)) add(rdi, rcx) vmovups(ymm10, mem(rcx, 0*32)) add(rdi, rcx) vmovups(ymm12, mem(rcx, 0*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) // begin I/O on columns 0-7 vunpcklps(ymm6, ymm4, ymm0) vunpcklps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx )) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rbx, 1)) // store ( gamma05..gamma35 ) vunpckhps(ymm6, ymm4, ymm0) vunpckhps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, rax, 2)) // store ( gamma06..gamma36 ) vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx, rax, 1)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, rbp, 1)) // store ( gamma07..gamma37 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vmovups(ymm12, ymm0) vextractf128(imm(0x1), ymm0, xmm8) vpermilps(imm(0xe4), xmm0, xmm2) vpermilps(imm(0x39), xmm0, xmm4) vmovss(xmm2, mem(rdx )) // store ( gamma40 ) vmovss(xmm4, mem(rdx, rsi, 1)) // store ( gamma41 ) vpermilps(imm(0x4e), xmm0, xmm2) vpermilps(imm(0x93), xmm0, xmm4) vmovss(xmm2, mem(rdx, rsi, 2)) // store ( gamma42 ) vmovss(xmm4, mem(rdx, rax, 1)) // store ( gamma43 ) vpermilps(imm(0xe4), xmm8, xmm2) vpermilps(imm(0x39), xmm8, xmm4) vmovss(xmm2, mem(rdx, rsi, 4)) // store ( gamma44 ) vmovss(xmm4, mem(rdx, rbx, 1)) // store ( gamma45 ) vpermilps(imm(0x4e), xmm8, xmm2) vpermilps(imm(0x93), xmm8, xmm4) vmovss(xmm2, mem(rdx, rax, 2)) // store ( gamma46 ) vmovss(xmm4, mem(rdx, rbp, 1)) // store ( gamma47 ) //lea(mem(rdx, rsi, 8), rdx) // rdx += 8*cs_c label(.SDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_sgemmsup_rv_haswell_asm_4x8 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) //lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored prefetching on c lea(mem(rcx, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 7*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 7*8)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 7*8)) // prefetch c + 3*rs_c jmp(.SPOSTPFETCH) // jump to end of prefetching c label(.SCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) lea(mem(rsi, rsi, 2), rbp) // rbp = 3*cs_c; prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 3*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 3*8)) // prefetch c + 2*cs_c prefetch(0, mem(rcx, rbp, 1, 3*8)) // prefetch c + 3*cs_c prefetch(0, mem(rcx, rsi, 4, 3*8)) // prefetch c + 4*cs_c lea(mem(rcx, rsi, 4), rdx) // rdx = c + 4*cs_c; prefetch(0, mem(rdx, rsi, 1, 3*8)) // prefetch c + 5*cs_c prefetch(0, mem(rdx, rsi, 2, 3*8)) // prefetch c + 6*cs_c prefetch(0, mem(rdx, rbp, 1, 3*8)) // prefetch c + 7*cs_c label(.SPOSTPFETCH) // done prefetching c #if 1 lea(mem(rax, r9, 8), rdx) // lea(mem(rdx, r9, 8), rdx) // rdx = a + 16*cs_a; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(rdx, 4*8)) #endif vmovups(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm0, ymm3, ymm10) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, r9, 1, 4*8)) #endif vmovups(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm0, ymm3, ymm10) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(rdx, r9, 2, 4*8)) #endif vmovups(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm0, ymm3, ymm10) // ---------------------------------- iteration 3 #if 1 lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; #endif vmovups(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm0, ymm3, ymm10) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP #if 0 prefetch(0, mem(rdx, 5*8)) add(r9, rdx) #endif vmovups(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm0, ymm3, ymm10) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), ymm0) // load alpha and duplicate vbroadcastss(mem(rbx), ymm3) // load beta and duplicate vmulps(ymm0, ymm4, ymm4) // scale by alpha vmulps(ymm0, ymm6, ymm6) vmulps(ymm0, ymm8, ymm8) vmulps(ymm0, ymm10, ymm10) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; //lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; lea(mem(rsi, rsi, 4), rbx) // rbx = 5*cs_c; lea(mem(rax, rsi, 4), rbp) // rbp = 7*cs_c; // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm4) vmovups(ymm4, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm6) vmovups(ymm6, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm8) vmovups(ymm8, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm10) vmovups(ymm10, mem(rcx, 0*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORED) // begin I/O on columns 0-7 vunpcklps(ymm6, ymm4, ymm0) vunpcklps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx ), xmm3, xmm0) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm0, mem(rcx )) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx, rsi, 1), xmm3, xmm1) vfmadd231ps(mem(rcx, rbx, 1), xmm3, xmm2) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rbx, 1)) // store ( gamma05..gamma35 ) vunpckhps(ymm6, ymm4, ymm0) vunpckhps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx, rsi, 2), xmm3, xmm0) vfmadd231ps(mem(rcx, rax, 2), xmm3, xmm2) vmovups(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, rax, 2)) // store ( gamma06..gamma36 ) vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx, rax, 1), xmm3, xmm1) vfmadd231ps(mem(rcx, rbp, 1), xmm3, xmm2) vmovups(xmm1, mem(rcx, rax, 1)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, rbp, 1)) // store ( gamma07..gamma37 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (8*rs_c) == 8. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovups(ymm4, mem(rcx, 0*32)) add(rdi, rcx) vmovups(ymm6, mem(rcx, 0*32)) add(rdi, rcx) vmovups(ymm8, mem(rcx, 0*32)) add(rdi, rcx) vmovups(ymm10, mem(rcx, 0*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) // begin I/O on columns 0-7 vunpcklps(ymm6, ymm4, ymm0) vunpcklps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx )) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rbx, 1)) // store ( gamma05..gamma35 ) vunpckhps(ymm6, ymm4, ymm0) vunpckhps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, rax, 2)) // store ( gamma06..gamma36 ) vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx, rax, 1)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, rbp, 1)) // store ( gamma07..gamma37 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c label(.SDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_sgemmsup_rv_haswell_asm_3x8 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) //lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored prefetching on c //lea(mem(rcx, rdi, 2), rdx) // //lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 7*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 7*8)) // prefetch c + 2*rs_c jmp(.SPOSTPFETCH) // jump to end of prefetching c label(.SCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) lea(mem(rsi, rsi, 2), rbp) // rbp = 3*cs_c; prefetch(0, mem(rcx, 2*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 2*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 2*8)) // prefetch c + 2*cs_c prefetch(0, mem(rcx, rbp, 1, 2*8)) // prefetch c + 3*cs_c prefetch(0, mem(rcx, rsi, 4, 2*8)) // prefetch c + 4*cs_c lea(mem(rcx, rsi, 4), rdx) // rdx = c + 4*cs_c; prefetch(0, mem(rdx, rsi, 1, 2*8)) // prefetch c + 5*cs_c prefetch(0, mem(rdx, rsi, 2, 2*8)) // prefetch c + 6*cs_c prefetch(0, mem(rdx, rbp, 1, 2*8)) // prefetch c + 7*cs_c label(.SPOSTPFETCH) // done prefetching c #if 1 lea(mem(rax, r9, 8), rdx) // lea(mem(rdx, r9, 8), rdx) // rdx = a + 16*cs_a; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(rdx, 4*8)) #endif vmovups(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm8) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, r9, 1, 4*8)) #endif vmovups(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm8) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(rdx, r9, 2, 4*8)) #endif vmovups(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm8) // ---------------------------------- iteration 3 #if 1 lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; #endif vmovups(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm8) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP #if 0 prefetch(0, mem(rdx, 5*8)) add(r9, rdx) #endif vmovups(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm8) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), ymm0) // load alpha and duplicate vbroadcastss(mem(rbx), ymm3) // load beta and duplicate vmulps(ymm0, ymm4, ymm4) // scale by alpha vmulps(ymm0, ymm6, ymm6) vmulps(ymm0, ymm8, ymm8) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; lea(mem(rcx, rdi, 2), rdx) // load address of c + 2*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; lea(mem(rsi, rsi, 4), rbx) // rbx = 5*cs_c; lea(mem(rax, rsi, 4), rbp) // rbp = 7*cs_c; // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm4) vmovups(ymm4, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm6) vmovups(ymm6, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm8) vmovups(ymm8, mem(rcx, 0*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORED) // begin I/O on columns 0-7 vunpcklps(ymm6, ymm4, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(mem(rcx ), xmm1, xmm1) vmovhpd(mem(rcx, rsi, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(rcx )) // store ( gamma00..gamma10 ) vmovhpd(xmm0, mem(rcx, rsi, 1)) // store ( gamma01..gamma11 ) vmovlpd(mem(rcx, rsi, 4), xmm1, xmm1) vmovhpd(mem(rcx, rbx, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm2) vmovlpd(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma14 ) vmovhpd(xmm2, mem(rcx, rbx, 1)) // store ( gamma05..gamma15 ) vunpckhps(ymm6, ymm4, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(mem(rcx, rsi, 2), xmm1, xmm1) vmovhpd(mem(rcx, rax, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma12 ) vmovhpd(xmm0, mem(rcx, rax, 1)) // store ( gamma03..gamma13 ) vmovlpd(mem(rcx, rax, 2), xmm1, xmm1) vmovhpd(mem(rcx, rbp, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm2) vmovlpd(xmm2, mem(rcx, rax, 2)) // store ( gamma06..gamma16 ) vmovhpd(xmm2, mem(rcx, rbp, 1)) // store ( gamma07..gamma17 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vmovups(ymm8, ymm0) vextractf128(imm(0x1), ymm0, xmm8) vpermilps(imm(0xe4), xmm0, xmm2) vpermilps(imm(0x39), xmm0, xmm4) vmovss(mem(rdx ), xmm1) vmovss(mem(rdx, rsi, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rdx )) // store ( gamma40 ) vmovss(xmm4, mem(rdx, rsi, 1)) // store ( gamma41 ) vpermilps(imm(0x4e), xmm0, xmm2) vpermilps(imm(0x93), xmm0, xmm4) vmovss(mem(rdx, rsi, 2), xmm1) vmovss(mem(rdx, rax, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rdx, rsi, 2)) // store ( gamma42 ) vmovss(xmm4, mem(rdx, rax, 1)) // store ( gamma43 ) vpermilps(imm(0xe4), xmm8, xmm2) vpermilps(imm(0x39), xmm8, xmm4) vmovss(mem(rdx, rsi, 4), xmm1) vmovss(mem(rdx, rbx, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rdx, rsi, 4)) // store ( gamma44 ) vmovss(xmm4, mem(rdx, rbx, 1)) // store ( gamma45 ) vpermilps(imm(0x4e), xmm8, xmm2) vpermilps(imm(0x93), xmm8, xmm4) vmovss(mem(rdx, rax, 2), xmm1) vmovss(mem(rdx, rbp, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rdx, rax, 2)) // store ( gamma46 ) vmovss(xmm4, mem(rdx, rbp, 1)) // store ( gamma47 ) //lea(mem(rdx, rsi, 8), rdx) // rdx += 8*cs_c jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (8*rs_c) == 8. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovups(ymm4, mem(rcx, 0*32)) add(rdi, rcx) vmovups(ymm6, mem(rcx, 0*32)) add(rdi, rcx) vmovups(ymm8, mem(rcx, 0*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) // begin I/O on columns 0-7 vunpcklps(ymm6, ymm4, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(xmm0, mem(rcx )) // store ( gamma00..gamma10 ) vmovhpd(xmm0, mem(rcx, rsi, 1)) // store ( gamma01..gamma11 ) vmovlpd(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma14 ) vmovhpd(xmm2, mem(rcx, rbx, 1)) // store ( gamma05..gamma15 ) vunpckhps(ymm6, ymm4, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma12 ) vmovhpd(xmm0, mem(rcx, rax, 1)) // store ( gamma03..gamma13 ) vmovlpd(xmm2, mem(rcx, rax, 2)) // store ( gamma06..gamma16 ) vmovhpd(xmm2, mem(rcx, rbp, 1)) // store ( gamma07..gamma17 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vmovups(ymm8, ymm0) vextractf128(imm(0x1), ymm0, xmm8) vpermilps(imm(0xe4), xmm0, xmm2) vpermilps(imm(0x39), xmm0, xmm4) vmovss(xmm2, mem(rdx )) // store ( gamma40 ) vmovss(xmm4, mem(rdx, rsi, 1)) // store ( gamma41 ) vpermilps(imm(0x4e), xmm0, xmm2) vpermilps(imm(0x93), xmm0, xmm4) vmovss(xmm2, mem(rdx, rsi, 2)) // store ( gamma42 ) vmovss(xmm4, mem(rdx, rax, 1)) // store ( gamma43 ) vpermilps(imm(0xe4), xmm8, xmm2) vpermilps(imm(0x39), xmm8, xmm4) vmovss(xmm2, mem(rdx, rsi, 4)) // store ( gamma44 ) vmovss(xmm4, mem(rdx, rbx, 1)) // store ( gamma45 ) vpermilps(imm(0x4e), xmm8, xmm2) vpermilps(imm(0x93), xmm8, xmm4) vmovss(xmm2, mem(rdx, rax, 2)) // store ( gamma46 ) vmovss(xmm4, mem(rdx, rbp, 1)) // store ( gamma47 ) //lea(mem(rdx, rsi, 8), rdx) // rdx += 8*cs_c label(.SDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_sgemmsup_rv_haswell_asm_2x8 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) //lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored prefetching on c //lea(mem(rcx, rdi, 2), rdx) // //lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 7*8)) // prefetch c + 1*rs_c jmp(.SPOSTPFETCH) // jump to end of prefetching c label(.SCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) lea(mem(rsi, rsi, 2), rbp) // rbp = 3*cs_c; prefetch(0, mem(rcx, 1*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 1*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 1*8)) // prefetch c + 2*cs_c prefetch(0, mem(rcx, rbp, 1, 1*8)) // prefetch c + 3*cs_c prefetch(0, mem(rcx, rsi, 4, 1*8)) // prefetch c + 4*cs_c lea(mem(rcx, rsi, 4), rdx) // rdx = c + 4*cs_c; prefetch(0, mem(rdx, rsi, 1, 1*8)) // prefetch c + 5*cs_c prefetch(0, mem(rdx, rsi, 2, 1*8)) // prefetch c + 6*cs_c prefetch(0, mem(rdx, rbp, 1, 1*8)) // prefetch c + 7*cs_c label(.SPOSTPFETCH) // done prefetching c #if 1 lea(mem(rax, r9, 8), rdx) // lea(mem(rdx, r9, 8), rdx) // rdx = a + 16*cs_a; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(rdx, 4*8)) #endif vmovups(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, r9, 1, 4*8)) #endif vmovups(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(rdx, r9, 2, 4*8)) #endif vmovups(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) // ---------------------------------- iteration 3 #if 1 lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; #endif vmovups(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP #if 0 prefetch(0, mem(rdx, 5*8)) add(r9, rdx) #endif vmovups(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), ymm0) // load alpha and duplicate vbroadcastss(mem(rbx), ymm3) // load beta and duplicate vmulps(ymm0, ymm4, ymm4) // scale by alpha vmulps(ymm0, ymm6, ymm6) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; //lea(mem(rcx, rdi, 2), rdx) // load address of c + 2*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; lea(mem(rsi, rsi, 4), rbx) // rbx = 5*cs_c; lea(mem(rax, rsi, 4), rbp) // rbp = 7*cs_c; // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm4) vmovups(ymm4, mem(rcx, 0*32)) add(rdi, rcx) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm6) vmovups(ymm6, mem(rcx, 0*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORED) // begin I/O on columns 0-7 vunpcklps(ymm6, ymm4, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(mem(rcx ), xmm1, xmm1) vmovhpd(mem(rcx, rsi, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(rcx )) // store ( gamma00..gamma10 ) vmovhpd(xmm0, mem(rcx, rsi, 1)) // store ( gamma01..gamma11 ) vmovlpd(mem(rcx, rsi, 4), xmm1, xmm1) vmovhpd(mem(rcx, rbx, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm2) vmovlpd(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma14 ) vmovhpd(xmm2, mem(rcx, rbx, 1)) // store ( gamma05..gamma15 ) vunpckhps(ymm6, ymm4, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(mem(rcx, rsi, 2), xmm1, xmm1) vmovhpd(mem(rcx, rax, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma12 ) vmovhpd(xmm0, mem(rcx, rax, 1)) // store ( gamma03..gamma13 ) vmovlpd(mem(rcx, rax, 2), xmm1, xmm1) vmovhpd(mem(rcx, rbp, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm2) vmovlpd(xmm2, mem(rcx, rax, 2)) // store ( gamma06..gamma16 ) vmovhpd(xmm2, mem(rcx, rbp, 1)) // store ( gamma07..gamma17 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (8*rs_c) == 8. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovups(ymm4, mem(rcx, 0*32)) add(rdi, rcx) vmovups(ymm6, mem(rcx, 0*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) // begin I/O on columns 0-7 vunpcklps(ymm6, ymm4, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(xmm0, mem(rcx )) // store ( gamma00..gamma10 ) vmovhpd(xmm0, mem(rcx, rsi, 1)) // store ( gamma01..gamma11 ) vmovlpd(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma14 ) vmovhpd(xmm2, mem(rcx, rbx, 1)) // store ( gamma05..gamma15 ) vunpckhps(ymm6, ymm4, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(xmm0, mem(rcx, rsi, 2)) // store ( gamma02..gamma12 ) vmovhpd(xmm0, mem(rcx, rax, 1)) // store ( gamma03..gamma13 ) vmovlpd(xmm2, mem(rcx, rax, 2)) // store ( gamma06..gamma16 ) vmovhpd(xmm2, mem(rcx, rbp, 1)) // store ( gamma07..gamma17 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c label(.SDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_sgemmsup_rv_haswell_asm_1x8 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) //lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored prefetching on c //lea(mem(rcx, rdi, 2), rdx) // //lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c jmp(.SPOSTPFETCH) // jump to end of prefetching c label(.SCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) lea(mem(rsi, rsi, 2), rbp) // rbp = 3*cs_c; prefetch(0, mem(rcx, 0*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 0*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 0*8)) // prefetch c + 2*cs_c prefetch(0, mem(rcx, rbp, 1, 0*8)) // prefetch c + 3*cs_c prefetch(0, mem(rcx, rsi, 4, 0*8)) // prefetch c + 4*cs_c lea(mem(rcx, rsi, 4), rdx) // rdx = c + 4*cs_c; prefetch(0, mem(rdx, rsi, 1, 0*8)) // prefetch c + 5*cs_c prefetch(0, mem(rdx, rsi, 2, 0*8)) // prefetch c + 6*cs_c prefetch(0, mem(rdx, rbp, 1, 0*8)) // prefetch c + 7*cs_c label(.SPOSTPFETCH) // done prefetching c #if 1 lea(mem(rax, r9, 8), rdx) // lea(mem(rdx, r9, 8), rdx) // rdx = a + 16*cs_a; #endif mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 #if 1 prefetch(0, mem(rdx, 4*8)) #endif vmovups(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) // ---------------------------------- iteration 1 #if 0 prefetch(0, mem(rdx, r9, 1, 4*8)) #endif vmovups(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) // ---------------------------------- iteration 2 #if 1 prefetch(0, mem(rdx, r9, 2, 4*8)) #endif vmovups(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) // ---------------------------------- iteration 3 #if 1 lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; #endif vmovups(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP #if 0 prefetch(0, mem(rdx, 5*8)) add(r9, rdx) #endif vmovups(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), ymm0) // load alpha and duplicate vbroadcastss(mem(rbx), ymm3) // load beta and duplicate vmulps(ymm0, ymm4, ymm4) // scale by alpha mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; //lea(mem(rcx, rdi, 2), rdx) // load address of c + 2*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; lea(mem(rsi, rsi, 4), rbx) // rbx = 5*cs_c; lea(mem(rax, rsi, 4), rbp) // rbp = 7*cs_c; // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vfmadd231ps(mem(rcx, 0*32), ymm3, ymm4) vmovups(ymm4, mem(rcx, 0*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORED) // begin I/O on columns 0-7 vmovups(ymm4, ymm0) vextractf128(imm(0x1), ymm0, xmm8) vpermilps(imm(0xe4), xmm0, xmm2) vpermilps(imm(0x39), xmm0, xmm4) vmovss(mem(rcx ), xmm1) vmovss(mem(rcx, rsi, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rcx )) // store ( gamma40 ) vmovss(xmm4, mem(rcx, rsi, 1)) // store ( gamma41 ) vpermilps(imm(0x4e), xmm0, xmm2) vpermilps(imm(0x93), xmm0, xmm4) vmovss(mem(rcx, rsi, 2), xmm1) vmovss(mem(rcx, rax, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rcx, rsi, 2)) // store ( gamma42 ) vmovss(xmm4, mem(rcx, rax, 1)) // store ( gamma43 ) vpermilps(imm(0xe4), xmm8, xmm2) vpermilps(imm(0x39), xmm8, xmm4) vmovss(mem(rcx, rsi, 4), xmm1) vmovss(mem(rcx, rbx, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rcx, rsi, 4)) // store ( gamma44 ) vmovss(xmm4, mem(rcx, rbx, 1)) // store ( gamma45 ) vpermilps(imm(0x4e), xmm8, xmm2) vpermilps(imm(0x93), xmm8, xmm4) vmovss(mem(rcx, rax, 2), xmm1) vmovss(mem(rcx, rbp, 1), xmm6) vfmadd231ps(xmm1, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm2, mem(rcx, rax, 2)) // store ( gamma46 ) vmovss(xmm4, mem(rcx, rbp, 1)) // store ( gamma47 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (8*rs_c) == 8. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovups(ymm4, mem(rcx, 0*32)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) // begin I/O on columns 0-7 vmovups(ymm4, ymm0) vextractf128(imm(0x1), ymm0, xmm8) vpermilps(imm(0xe4), xmm0, xmm2) vpermilps(imm(0x39), xmm0, xmm4) vmovss(xmm2, mem(rcx )) // store ( gamma40 ) vmovss(xmm4, mem(rcx, rsi, 1)) // store ( gamma41 ) vpermilps(imm(0x4e), xmm0, xmm2) vpermilps(imm(0x93), xmm0, xmm4) vmovss(xmm2, mem(rcx, rsi, 2)) // store ( gamma42 ) vmovss(xmm4, mem(rcx, rax, 1)) // store ( gamma43 ) vpermilps(imm(0xe4), xmm8, xmm2) vpermilps(imm(0x39), xmm8, xmm4) vmovss(xmm2, mem(rcx, rsi, 4)) // store ( gamma44 ) vmovss(xmm4, mem(rcx, rbx, 1)) // store ( gamma45 ) vpermilps(imm(0x4e), xmm8, xmm2) vpermilps(imm(0x93), xmm8, xmm4) vmovss(xmm2, mem(rcx, rax, 2)) // store ( gamma46 ) vmovss(xmm4, mem(rcx, rbp, 1)) // store ( gamma47 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c label(.SDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } blis-0.9.0/kernels/haswell/bli_kernels_haswell.h000066400000000000000000000303651422157504600217510ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // -- level-1m ----------------------------------------------------------------- // packm (asm) PACKM_KER_PROT( float, s, packm_haswell_asm_6xk ) PACKM_KER_PROT( float, s, packm_haswell_asm_16xk ) PACKM_KER_PROT( double, d, packm_haswell_asm_6xk ) PACKM_KER_PROT( double, d, packm_haswell_asm_8xk ) PACKM_KER_PROT( scomplex, c, packm_haswell_asm_3xk ) PACKM_KER_PROT( scomplex, c, packm_haswell_asm_8xk ) PACKM_KER_PROT( dcomplex, z, packm_haswell_asm_3xk ) PACKM_KER_PROT( dcomplex, z, packm_haswell_asm_4xk ) // -- level-3 ------------------------------------------------------------------ // gemm (asm d6x8) GEMM_UKR_PROT( float, s, gemm_haswell_asm_6x16 ) GEMM_UKR_PROT( double, d, gemm_haswell_asm_6x8 ) GEMM_UKR_PROT( scomplex, c, gemm_haswell_asm_3x8 ) GEMM_UKR_PROT( dcomplex, z, gemm_haswell_asm_3x4 ) // gemm (asm d8x6) GEMM_UKR_PROT( float, s, gemm_haswell_asm_16x6 ) GEMM_UKR_PROT( double, d, gemm_haswell_asm_8x6 ) GEMM_UKR_PROT( scomplex, c, gemm_haswell_asm_8x3 ) GEMM_UKR_PROT( dcomplex, z, gemm_haswell_asm_4x3 ) // gemmtrsm_l (asm d6x8) GEMMTRSM_UKR_PROT( float, s, gemmtrsm_l_haswell_asm_6x16 ) GEMMTRSM_UKR_PROT( double, d, gemmtrsm_l_haswell_asm_6x8 ) // gemmtrsm_u (asm d6x8) GEMMTRSM_UKR_PROT( float, s, gemmtrsm_u_haswell_asm_6x16 ) GEMMTRSM_UKR_PROT( double, d, gemmtrsm_u_haswell_asm_6x8 ) // gemm (asm d8x6) //GEMM_UKR_PROT( float, s, gemm_haswell_asm_16x6 ) //GEMM_UKR_PROT( double, d, gemm_haswell_asm_8x6 ) //GEMM_UKR_PROT( scomplex, c, gemm_haswell_asm_8x3 ) //GEMM_UKR_PROT( dcomplex, z, gemm_haswell_asm_4x3 ) // -- level-3 sup -------------------------------------------------------------- // -- single real -- // gemmsup_r GEMMSUP_KER_PROT( float, s, gemmsup_r_haswell_ref_6x1 ) GEMMSUP_KER_PROT( float, s, gemmsup_r_haswell_ref_5x1 ) GEMMSUP_KER_PROT( float, s, gemmsup_r_haswell_ref_4x1 ) GEMMSUP_KER_PROT( float, s, gemmsup_r_haswell_ref_3x1 ) GEMMSUP_KER_PROT( float, s, gemmsup_r_haswell_ref_2x1 ) GEMMSUP_KER_PROT( float, s, gemmsup_r_haswell_ref_1x1 ) // gemmsup_rv GEMMSUP_KER_PROT( float, s, gemmsup_rv_haswell_asm_6x16 ) GEMMSUP_KER_PROT( float, s, gemmsup_rv_haswell_asm_5x16 ) GEMMSUP_KER_PROT( float, s, gemmsup_rv_haswell_asm_4x16 ) GEMMSUP_KER_PROT( float, s, gemmsup_rv_haswell_asm_3x16 ) GEMMSUP_KER_PROT( float, s, gemmsup_rv_haswell_asm_2x16 ) GEMMSUP_KER_PROT( float, s, gemmsup_rv_haswell_asm_1x16 ) GEMMSUP_KER_PROT( float, s, gemmsup_rv_haswell_asm_6x12 ) GEMMSUP_KER_PROT( float, s, gemmsup_rv_haswell_asm_5x12 ) GEMMSUP_KER_PROT( float, s, gemmsup_rv_haswell_asm_4x12 ) GEMMSUP_KER_PROT( float, s, gemmsup_rv_haswell_asm_3x12 ) GEMMSUP_KER_PROT( float, s, gemmsup_rv_haswell_asm_2x12 ) GEMMSUP_KER_PROT( float, s, gemmsup_rv_haswell_asm_1x12 ) GEMMSUP_KER_PROT( float, s, gemmsup_rv_haswell_asm_6x8 ) GEMMSUP_KER_PROT( float, s, gemmsup_rv_haswell_asm_5x8 ) GEMMSUP_KER_PROT( float, s, gemmsup_rv_haswell_asm_4x8 ) GEMMSUP_KER_PROT( float, s, gemmsup_rv_haswell_asm_3x8 ) GEMMSUP_KER_PROT( float, s, gemmsup_rv_haswell_asm_2x8 ) GEMMSUP_KER_PROT( float, s, gemmsup_rv_haswell_asm_1x8 ) GEMMSUP_KER_PROT( float, s, gemmsup_rv_haswell_asm_6x6 ) GEMMSUP_KER_PROT( float, s, gemmsup_rv_haswell_asm_5x6 ) GEMMSUP_KER_PROT( float, s, gemmsup_rv_haswell_asm_4x6 ) GEMMSUP_KER_PROT( float, s, gemmsup_rv_haswell_asm_3x6 ) GEMMSUP_KER_PROT( float, s, gemmsup_rv_haswell_asm_2x6 ) GEMMSUP_KER_PROT( float, s, gemmsup_rv_haswell_asm_1x6 ) GEMMSUP_KER_PROT( float, s, gemmsup_rv_haswell_asm_6x4 ) GEMMSUP_KER_PROT( float, s, gemmsup_rv_haswell_asm_5x4 ) GEMMSUP_KER_PROT( float, s, gemmsup_rv_haswell_asm_4x4 ) GEMMSUP_KER_PROT( float, s, gemmsup_rv_haswell_asm_3x4 ) GEMMSUP_KER_PROT( float, s, gemmsup_rv_haswell_asm_2x4 ) GEMMSUP_KER_PROT( float, s, gemmsup_rv_haswell_asm_1x4 ) GEMMSUP_KER_PROT( float, s, gemmsup_rv_haswell_asm_6x2 ) GEMMSUP_KER_PROT( float, s, gemmsup_rv_haswell_asm_5x2 ) GEMMSUP_KER_PROT( float, s, gemmsup_rv_haswell_asm_4x2 ) GEMMSUP_KER_PROT( float, s, gemmsup_rv_haswell_asm_3x2 ) GEMMSUP_KER_PROT( float, s, gemmsup_rv_haswell_asm_2x2 ) GEMMSUP_KER_PROT( float, s, gemmsup_rv_haswell_asm_1x2 ) // gemmsup_rv (mkernel in m dim) GEMMSUP_KER_PROT( float, s, gemmsup_rv_haswell_asm_6x16m ) GEMMSUP_KER_PROT( float, s, gemmsup_rv_haswell_asm_6x12m ) GEMMSUP_KER_PROT( float, s, gemmsup_rv_haswell_asm_6x8m ) GEMMSUP_KER_PROT( float, s, gemmsup_rv_haswell_asm_6x6m ) GEMMSUP_KER_PROT( float, s, gemmsup_rv_haswell_asm_6x4m ) GEMMSUP_KER_PROT( float, s, gemmsup_rv_haswell_asm_6x2m ) // gemmsup_rv (mkernel in n dim) GEMMSUP_KER_PROT( float, s, gemmsup_rv_haswell_asm_6x16n ) GEMMSUP_KER_PROT( float, s, gemmsup_rv_haswell_asm_5x16n ) GEMMSUP_KER_PROT( float, s, gemmsup_rv_haswell_asm_4x16n ) GEMMSUP_KER_PROT( float, s, gemmsup_rv_haswell_asm_3x16n ) GEMMSUP_KER_PROT( float, s, gemmsup_rv_haswell_asm_2x16n ) GEMMSUP_KER_PROT( float, s, gemmsup_rv_haswell_asm_1x16n ) // gemmsup_rd GEMMSUP_KER_PROT( float, s, gemmsup_rd_haswell_asm_6x16 ) GEMMSUP_KER_PROT( float, s, gemmsup_rd_haswell_asm_2x16 ) GEMMSUP_KER_PROT( float, s, gemmsup_rd_haswell_asm_1x16 ) GEMMSUP_KER_PROT( float, s, gemmsup_rd_haswell_asm_6x12 ) GEMMSUP_KER_PROT( float, s, gemmsup_rd_haswell_asm_2x12 ) GEMMSUP_KER_PROT( float, s, gemmsup_rd_haswell_asm_1x12 ) GEMMSUP_KER_PROT( float, s, gemmsup_rd_haswell_asm_6x8 ) GEMMSUP_KER_PROT( float, s, gemmsup_rd_haswell_asm_2x8 ) GEMMSUP_KER_PROT( float, s, gemmsup_rd_haswell_asm_1x8 ) GEMMSUP_KER_PROT( float, s, gemmsup_rd_haswell_asm_6x4 ) GEMMSUP_KER_PROT( float, s, gemmsup_rd_haswell_asm_2x4 ) GEMMSUP_KER_PROT( float, s, gemmsup_rd_haswell_asm_1x4 ) GEMMSUP_KER_PROT( float, s, gemmsup_rd_haswell_asm_6x2 ) GEMMSUP_KER_PROT( float, s, gemmsup_rd_haswell_asm_3x2 ) GEMMSUP_KER_PROT( float, s, gemmsup_rd_haswell_asm_2x2 ) GEMMSUP_KER_PROT( float, s, gemmsup_rd_haswell_asm_1x2 ) GEMMSUP_KER_PROT( float, s, gemmsup_rd_haswell_asm_6x1 ) GEMMSUP_KER_PROT( float, s, gemmsup_rd_haswell_asm_3x1 ) GEMMSUP_KER_PROT( float, s, gemmsup_rd_haswell_asm_2x1 ) GEMMSUP_KER_PROT( float, s, gemmsup_rd_haswell_asm_1x1 ) // gemmsup_rd (mkernel in m dim) GEMMSUP_KER_PROT( float, s, gemmsup_rd_haswell_asm_6x16m ) GEMMSUP_KER_PROT( float, s, gemmsup_rd_haswell_asm_6x12m ) GEMMSUP_KER_PROT( float, s, gemmsup_rd_haswell_asm_6x8m ) GEMMSUP_KER_PROT( float, s, gemmsup_rd_haswell_asm_6x4m ) GEMMSUP_KER_PROT( float, s, gemmsup_rd_haswell_asm_6x2m ) // gemmsup_rd (mkernel in n dim) GEMMSUP_KER_PROT( float, s, gemmsup_rd_haswell_asm_6x16n ) GEMMSUP_KER_PROT( float, s, gemmsup_rd_haswell_asm_3x16n ) GEMMSUP_KER_PROT( float, s, gemmsup_rd_haswell_asm_2x16n ) GEMMSUP_KER_PROT( float, s, gemmsup_rd_haswell_asm_1x16n ) // -- double real -- // gemmsup_r GEMMSUP_KER_PROT( double, d, gemmsup_r_haswell_ref_6x1 ) GEMMSUP_KER_PROT( double, d, gemmsup_r_haswell_ref_5x1 ) GEMMSUP_KER_PROT( double, d, gemmsup_r_haswell_ref_4x1 ) GEMMSUP_KER_PROT( double, d, gemmsup_r_haswell_ref_3x1 ) GEMMSUP_KER_PROT( double, d, gemmsup_r_haswell_ref_2x1 ) GEMMSUP_KER_PROT( double, d, gemmsup_r_haswell_ref_1x1 ) // gemmsup_rv GEMMSUP_KER_PROT( double, d, gemmsup_rv_haswell_asm_6x8 ) GEMMSUP_KER_PROT( double, d, gemmsup_rv_haswell_asm_5x8 ) GEMMSUP_KER_PROT( double, d, gemmsup_rv_haswell_asm_4x8 ) GEMMSUP_KER_PROT( double, d, gemmsup_rv_haswell_asm_3x8 ) GEMMSUP_KER_PROT( double, d, gemmsup_rv_haswell_asm_2x8 ) GEMMSUP_KER_PROT( double, d, gemmsup_rv_haswell_asm_1x8 ) GEMMSUP_KER_PROT( double, d, gemmsup_rv_haswell_asm_6x6 ) GEMMSUP_KER_PROT( double, d, gemmsup_rv_haswell_asm_5x6 ) GEMMSUP_KER_PROT( double, d, gemmsup_rv_haswell_asm_4x6 ) GEMMSUP_KER_PROT( double, d, gemmsup_rv_haswell_asm_3x6 ) GEMMSUP_KER_PROT( double, d, gemmsup_rv_haswell_asm_2x6 ) GEMMSUP_KER_PROT( double, d, gemmsup_rv_haswell_asm_1x6 ) GEMMSUP_KER_PROT( double, d, gemmsup_rv_haswell_asm_6x4 ) GEMMSUP_KER_PROT( double, d, gemmsup_rv_haswell_asm_5x4 ) GEMMSUP_KER_PROT( double, d, gemmsup_rv_haswell_asm_4x4 ) GEMMSUP_KER_PROT( double, d, gemmsup_rv_haswell_asm_3x4 ) GEMMSUP_KER_PROT( double, d, gemmsup_rv_haswell_asm_2x4 ) GEMMSUP_KER_PROT( double, d, gemmsup_rv_haswell_asm_1x4 ) GEMMSUP_KER_PROT( double, d, gemmsup_rv_haswell_asm_6x2 ) GEMMSUP_KER_PROT( double, d, gemmsup_rv_haswell_asm_5x2 ) GEMMSUP_KER_PROT( double, d, gemmsup_rv_haswell_asm_4x2 ) GEMMSUP_KER_PROT( double, d, gemmsup_rv_haswell_asm_3x2 ) GEMMSUP_KER_PROT( double, d, gemmsup_rv_haswell_asm_2x2 ) GEMMSUP_KER_PROT( double, d, gemmsup_rv_haswell_asm_1x2 ) // gemmsup_rv (mkernel in m dim) GEMMSUP_KER_PROT( double, d, gemmsup_rv_haswell_asm_6x8m ) GEMMSUP_KER_PROT( double, d, gemmsup_rv_haswell_asm_6x6m ) GEMMSUP_KER_PROT( double, d, gemmsup_rv_haswell_asm_6x4m ) GEMMSUP_KER_PROT( double, d, gemmsup_rv_haswell_asm_6x2m ) // gemmsup_rv (mkernel in n dim) GEMMSUP_KER_PROT( double, d, gemmsup_rv_haswell_asm_6x8n ) GEMMSUP_KER_PROT( double, d, gemmsup_rv_haswell_asm_5x8n ) GEMMSUP_KER_PROT( double, d, gemmsup_rv_haswell_asm_4x8n ) GEMMSUP_KER_PROT( double, d, gemmsup_rv_haswell_asm_3x8n ) GEMMSUP_KER_PROT( double, d, gemmsup_rv_haswell_asm_2x8n ) GEMMSUP_KER_PROT( double, d, gemmsup_rv_haswell_asm_1x8n ) // gemmsup_rd GEMMSUP_KER_PROT( double, d, gemmsup_rd_haswell_asm_6x8 ) GEMMSUP_KER_PROT( double, d, gemmsup_rd_haswell_asm_2x8 ) GEMMSUP_KER_PROT( double, d, gemmsup_rd_haswell_asm_1x8 ) GEMMSUP_KER_PROT( double, d, gemmsup_rd_haswell_asm_6x4 ) GEMMSUP_KER_PROT( double, d, gemmsup_rd_haswell_asm_2x4 ) GEMMSUP_KER_PROT( double, d, gemmsup_rd_haswell_asm_1x4 ) GEMMSUP_KER_PROT( double, d, gemmsup_rd_haswell_asm_6x2 ) GEMMSUP_KER_PROT( double, d, gemmsup_rd_haswell_asm_3x2 ) GEMMSUP_KER_PROT( double, d, gemmsup_rd_haswell_asm_2x2 ) GEMMSUP_KER_PROT( double, d, gemmsup_rd_haswell_asm_1x2 ) GEMMSUP_KER_PROT( double, d, gemmsup_rd_haswell_asm_6x1 ) GEMMSUP_KER_PROT( double, d, gemmsup_rd_haswell_asm_3x1 ) GEMMSUP_KER_PROT( double, d, gemmsup_rd_haswell_asm_2x1 ) GEMMSUP_KER_PROT( double, d, gemmsup_rd_haswell_asm_1x1 ) // gemmsup_rd (mkernel in m dim) GEMMSUP_KER_PROT( double, d, gemmsup_rd_haswell_asm_6x8m ) GEMMSUP_KER_PROT( double, d, gemmsup_rd_haswell_asm_6x4m ) GEMMSUP_KER_PROT( double, d, gemmsup_rd_haswell_asm_6x2m ) // gemmsup_rd (mkernel in n dim) GEMMSUP_KER_PROT( double, d, gemmsup_rd_haswell_asm_6x8n ) GEMMSUP_KER_PROT( double, d, gemmsup_rd_haswell_asm_3x8n ) GEMMSUP_KER_PROT( double, d, gemmsup_rd_haswell_asm_2x8n ) GEMMSUP_KER_PROT( double, d, gemmsup_rd_haswell_asm_1x8n ) blis-0.9.0/kernels/knc/000077500000000000000000000000001422157504600146755ustar00rootroot00000000000000blis-0.9.0/kernels/knc/3/000077500000000000000000000000001422157504600150375ustar00rootroot00000000000000blis-0.9.0/kernels/knc/3/bli_dgemm_knc_asm_30x8.c000066400000000000000000000510771422157504600214110ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 UNIVERSITY OF TEXAS 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. */ #include "blis.h" #include #define A_L1_PREFETCH_DIST 4 #define B_L1_PREFETCH_DIST 2 #define L2_PREFETCH_DIST 16 // Must be greater than 10, because of the way the loop is constructed. //Alternate code path uused if C is not row-major #define UPDATE_C_ROW_SCATTERED(REG1, NUM, BASE_DEST) \ { \ __asm kmov k3, ebx \ __asm GATHER##NUM: \ __asm vgatherdpd zmm31{k3}, [BASE_DEST + zmm30 * 8] \ __asm jknzd k3, GATHER##NUM \ \ __asm vmulpd REG1, REG1, 0[r12]{1to8} /*scale by alpha*/ \ __asm vfmadd132pd zmm31, REG1, 0[r13]{1to8} /*scale by beta, add in result*/\ __asm kmov k3, ebx \ \ __asm SCATTER##NUM: \ __asm vscatterdpd [BASE_DEST + zmm30 * 8]{k3}, zmm31 \ __asm jknzd k3, SCATTER##NUM \ __asm add BASE_DEST, r11 \ } //One iteration of the k_r loop. //Each iteration, we prefetch A into L1 and into L2 #define ONE_ITER_MAIN_LOOP(C_ADDR, COUNTER) \ {\ __asm vbroadcastf64x4 zmm30, 0[r15] \ __asm vmovapd zmm31, 0[rbx] \ \ __asm vfmadd231pd zmm0, zmm31, zmm30{aaaa} \ __asm vfmadd231pd zmm4, zmm31, 4*8[r15]{1to8} \ __asm vprefetch0 A_L1_PREFETCH_DIST*256[r15] \ __asm vfmadd231pd zmm5, zmm31, 5*8[r15]{1to8} \ __asm vprefetch0 A_L1_PREFETCH_DIST*256+64[r15] \ __asm vfmadd231pd zmm6, zmm31, 6*8[r15]{1to8} \ __asm vprefetch0 A_L1_PREFETCH_DIST*256+128[r15]\ __asm vfmadd231pd zmm7, zmm31, 7*8[r15]{1to8} \ __asm vprefetch0 A_L1_PREFETCH_DIST*256+192[r15]\ __asm vfmadd231pd zmm8, zmm31, 8*8[r15]{1to8} \ \ __asm vprefetch1 0[r15 + r14] \ __asm vfmadd231pd zmm9, zmm31, 9*8[r15]{1to8} \ __asm vfmadd231pd zmm1, zmm31, zmm30{bbbb} \ __asm vfmadd231pd zmm2, zmm31, zmm30{cccc} \ __asm vfmadd231pd zmm3, zmm31, zmm30{dddd} \ __asm vfmadd231pd zmm10, zmm31, 10*8[r15]{1to8} \ \ __asm vprefetch1 64[r15 + r14] \ __asm vfmadd231pd zmm11, zmm31, 11*8[r15]{1to8} \ __asm vfmadd231pd zmm12, zmm31, 12*8[r15]{1to8} \ __asm vfmadd231pd zmm13, zmm31, 13*8[r15]{1to8} \ __asm vfmadd231pd zmm14, zmm31, 14*8[r15]{1to8} \ __asm vfmadd231pd zmm15, zmm31, 15*8[r15]{1to8} \ \ __asm vprefetch1 2*64[r15 + r14] \ __asm vfmadd231pd zmm16, zmm31, 16*8[r15]{1to8} \ __asm vfmadd231pd zmm17, zmm31, 17*8[r15]{1to8} \ __asm vfmadd231pd zmm18, zmm31, 18*8[r15]{1to8} \ __asm vfmadd231pd zmm19, zmm31, 19*8[r15]{1to8} \ __asm vfmadd231pd zmm20, zmm31, 20*8[r15]{1to8} \ \ __asm vprefetch1 3*64[r15 + r14] \ __asm vfmadd231pd zmm21, zmm31, 21*8[r15]{1to8} \ __asm add r15, r12 \ __asm vfmadd231pd zmm22, zmm31, -10*8[r15]{1to8}\ __asm vfmadd231pd zmm23, zmm31, -9*8[r15]{1to8} \ __asm vfmadd231pd zmm24, zmm31, -8*8[r15]{1to8} \ __asm dec COUNTER \ __asm vfmadd231pd zmm25, zmm31, -7*8[r15]{1to8} \ \ \ __asm vprefetch1 0[rbx + r13] \ __asm vfmadd231pd zmm26, zmm31, -6*8[r15]{1to8} \ __asm vprefetch0 B_L1_PREFETCH_DIST*8*8[rbx] \ __asm vfmadd231pd zmm27, zmm31, -5*8[r15]{1to8} \ __asm add rbx, r9 \ __asm vfmadd231pd zmm28, zmm31, -4*8[r15]{1to8} \ __asm cmp COUNTER, 0 \ __asm vfmadd231pd zmm29, zmm31, -3*8[r15]{1to8} \ } //One iteration of the k_r loop. //Same as ONE_ITER_MAIN_LOOP, but additionally, we prefetch one line of C into the L2 cache //Current placement of this prefetch instruction is somewhat arbitrary. #define ONE_ITER_PC_L2(C_ADDR) \ {\ __asm vbroadcastf64x4 zmm30, 0[r15] \ __asm vmovapd zmm31, 0[rbx] \ \ __asm vfmadd231pd zmm0, zmm31, zmm30{aaaa} \ __asm vfmadd231pd zmm4, zmm31, 4*8[r15]{1to8} \ __asm vprefetch0 A_L1_PREFETCH_DIST*256[r15] \ __asm vfmadd231pd zmm5, zmm31, 5*8[r15]{1to8} \ __asm vprefetch0 A_L1_PREFETCH_DIST*256+64[r15] \ __asm vfmadd231pd zmm6, zmm31, 6*8[r15]{1to8} \ __asm vprefetch0 A_L1_PREFETCH_DIST*256+128[r15]\ __asm vfmadd231pd zmm7, zmm31, 7*8[r15]{1to8} \ __asm vprefetch0 A_L1_PREFETCH_DIST*256+192[r15]\ __asm vfmadd231pd zmm8, zmm31, 8*8[r15]{1to8} \ \ __asm vprefetch1 0[r15 + r14] \ __asm vfmadd231pd zmm9, zmm31, 9*8[r15]{1to8} \ __asm vfmadd231pd zmm1, zmm31, zmm30{bbbb} \ __asm vfmadd231pd zmm2, zmm31, zmm30{cccc} \ __asm vfmadd231pd zmm3, zmm31, zmm30{dddd} \ __asm vfmadd231pd zmm10, zmm31, 10*8[r15]{1to8} \ \ __asm vprefetch1 64[r15 + r14] \ __asm vfmadd231pd zmm11, zmm31, 11*8[r15]{1to8} \ __asm vprefetch1 0[C_ADDR] \ __asm vfmadd231pd zmm12, zmm31, 12*8[r15]{1to8} \ __asm vfmadd231pd zmm13, zmm31, 13*8[r15]{1to8} \ __asm vfmadd231pd zmm14, zmm31, 14*8[r15]{1to8} \ __asm vfmadd231pd zmm15, zmm31, 15*8[r15]{1to8} \ \ __asm vprefetch1 2*64[r15 + r14] \ __asm vfmadd231pd zmm16, zmm31, 16*8[r15]{1to8} \ __asm vfmadd231pd zmm17, zmm31, 17*8[r15]{1to8} \ __asm vfmadd231pd zmm18, zmm31, 18*8[r15]{1to8} \ __asm vfmadd231pd zmm19, zmm31, 19*8[r15]{1to8} \ __asm vfmadd231pd zmm20, zmm31, 20*8[r15]{1to8} \ \ __asm vprefetch1 3*64[r15 + r14] \ __asm vfmadd231pd zmm21, zmm31, 21*8[r15]{1to8} \ __asm add r15, r12 \ __asm vfmadd231pd zmm22, zmm31, -10*8[r15]{1to8}\ __asm vfmadd231pd zmm23, zmm31, -9*8[r15]{1to8} \ __asm add C_ADDR, r11 \ __asm vfmadd231pd zmm24, zmm31, -8*8[r15]{1to8} \ __asm dec r8 \ __asm vfmadd231pd zmm25, zmm31, -7*8[r15]{1to8} \ \ \ __asm vprefetch1 0[rbx + r13] \ __asm vfmadd231pd zmm26, zmm31, -6*8[r15]{1to8} \ __asm vprefetch0 B_L1_PREFETCH_DIST*8*8[rbx] \ __asm vfmadd231pd zmm27, zmm31, -5*8[r15]{1to8} \ __asm add rbx, r9 \ __asm vfmadd231pd zmm28, zmm31, -4*8[r15]{1to8} \ __asm cmp r8, 0 \ __asm vfmadd231pd zmm29, zmm31, -3*8[r15]{1to8} \ \ } //One iteration of the k_r loop. //Same as ONE_ITER_MAIN_LOOP, but additionally, we prefetch 3 cache lines of C into the L1 cache //Current placement of these prefetch instructions is somewhat arbitrary. #define ONE_ITER_PC_L1(C_ADDR) \ {\ __asm vbroadcastf64x4 zmm30, 0[r15] \ __asm vmovapd zmm31, 0[rbx] \ \ __asm vfmadd231pd zmm0, zmm31, zmm30{aaaa} \ __asm vfmadd231pd zmm4, zmm31, 4*8[r15]{1to8} \ __asm vprefetch0 A_L1_PREFETCH_DIST*256[r15] \ __asm vfmadd231pd zmm5, zmm31, 5*8[r15]{1to8} \ __asm vprefetch0 A_L1_PREFETCH_DIST*256+64[r15] \ __asm vfmadd231pd zmm6, zmm31, 6*8[r15]{1to8} \ __asm vprefetch0 A_L1_PREFETCH_DIST*256+128[r15]\ __asm vfmadd231pd zmm7, zmm31, 7*8[r15]{1to8} \ __asm vprefetch0 A_L1_PREFETCH_DIST*256+192[r15]\ __asm vfmadd231pd zmm8, zmm31, 8*8[r15]{1to8} \ \ __asm vprefetch1 0[r15 + r14] \ __asm vfmadd231pd zmm9, zmm31, 9*8[r15]{1to8} \ __asm vprefetch0 0[C_ADDR] \ __asm vfmadd231pd zmm1, zmm31, zmm30{bbbb} \ __asm add C_ADDR, r11 \ __asm vfmadd231pd zmm2, zmm31, zmm30{cccc} \ __asm vfmadd231pd zmm3, zmm31, zmm30{dddd} \ __asm vfmadd231pd zmm10, zmm31, 10*8[r15]{1to8} \ \ __asm vprefetch1 64[r15 + r14] \ __asm vfmadd231pd zmm11, zmm31, 11*8[r15]{1to8} \ __asm vprefetch0 0[C_ADDR] \ __asm vfmadd231pd zmm12, zmm31, 12*8[r15]{1to8} \ __asm add C_ADDR, r11 \ __asm vfmadd231pd zmm13, zmm31, 13*8[r15]{1to8} \ __asm vfmadd231pd zmm14, zmm31, 14*8[r15]{1to8} \ __asm vfmadd231pd zmm15, zmm31, 15*8[r15]{1to8} \ \ __asm vprefetch1 2*64[r15 + r14] \ __asm vfmadd231pd zmm16, zmm31, 16*8[r15]{1to8} \ __asm vprefetch0 0[C_ADDR] \ __asm vfmadd231pd zmm17, zmm31, 17*8[r15]{1to8} \ __asm add C_ADDR, r11 \ __asm vfmadd231pd zmm18, zmm31, 18*8[r15]{1to8} \ __asm vfmadd231pd zmm19, zmm31, 19*8[r15]{1to8} \ __asm vfmadd231pd zmm20, zmm31, 20*8[r15]{1to8} \ \ __asm vprefetch1 3*64[r15 + r14] \ __asm vfmadd231pd zmm21, zmm31, 21*8[r15]{1to8} \ __asm add r15, r12 \ __asm vfmadd231pd zmm22, zmm31, -10*8[r15]{1to8}\ __asm vfmadd231pd zmm23, zmm31, -9*8[r15]{1to8} \ __asm vfmadd231pd zmm24, zmm31, -8*8[r15]{1to8} \ __asm dec r8 \ __asm vfmadd231pd zmm25, zmm31, -7*8[r15]{1to8} \ \ \ __asm vprefetch1 0[rbx + r13] \ __asm vfmadd231pd zmm26, zmm31, -6*8[r15]{1to8} \ __asm vprefetch0 B_L1_PREFETCH_DIST*8*8[rbx] \ __asm vfmadd231pd zmm27, zmm31, -5*8[r15]{1to8} \ __asm add rbx, r9 \ __asm vfmadd231pd zmm28, zmm31, -4*8[r15]{1to8} \ __asm cmp r8, 0 \ __asm vfmadd231pd zmm29, zmm31, -3*8[r15]{1to8} \ \ } //This is an array used for the scattter/gather instructions. extern int offsets[16]; //#define MONITORS //#define LOOPMON void bli_dgemm_knc_asm_30x8 ( dim_t m, dim_t n, dim_t k, double* restrict alpha, double* restrict a, double* restrict b, double* restrict beta, double* restrict c, inc_t rs_c, inc_t cs_c, auxinfo_t* restrict data, cntx_t* restrict cntx ) { double * a_next = bli_auxinfo_next_a( data ); double * b_next = bli_auxinfo_next_b( data ); int * offsetPtr = &offsets[0]; uint64_t k64 = k; GEMM_UKR_SETUP_CT( d, 30, 8, true ); #ifdef MONITORS int toph, topl, both, botl, midl, midh, mid2l, mid2h; #endif #ifdef LOOPMON int tlooph, tloopl, blooph, bloopl; #endif __asm { #ifdef MONITORS rdtsc mov topl, eax mov toph, edx #endif vpxord zmm0, zmm0, zmm0 vmovaps zmm1, zmm0 //clear out registers vmovaps zmm2, zmm0 mov rsi, k64 //loop index vmovaps zmm3, zmm0 mov r11, rs_c //load row stride vmovaps zmm4, zmm0 sal r11, 3 //scale row stride vmovaps zmm5, zmm0 mov r15, a //load address of a vmovaps zmm6, zmm0 mov rbx, b //load address of b vmovaps zmm7, zmm0 vmovaps zmm8, zmm0 lea r10, [r11 + 2*r11 + 0] //r10 has 3 * r11 vmovaps zmm9, zmm0 vmovaps zmm10, zmm0 mov rdi, r11 vmovaps zmm11, zmm0 sal rdi, 2 //rdi has 4*r11 vmovaps zmm12, zmm0 mov rcx, c //load address of c for prefetching vmovaps zmm13, zmm0 vmovaps zmm14, zmm0 mov r8, k64 vmovaps zmm15, zmm0 vmovaps zmm16, zmm0 vmovaps zmm17, zmm0 mov r13, L2_PREFETCH_DIST*8*8 vmovaps zmm18, zmm0 mov r14, L2_PREFETCH_DIST*8*32 vmovaps zmm19, zmm0 vmovaps zmm20, zmm0 vmovaps zmm21, zmm0 vmovaps zmm22, zmm0 vmovaps zmm23, zmm0 sub r8, 30 + L2_PREFETCH_DIST //Check if we have over 40 operations to do. vmovaps zmm24, zmm0 mov r8, 30 vmovaps zmm25, zmm0 mov r9, 8*8 //amount to increment b* by each iteration vmovaps zmm26, zmm0 mov r12, 32*8 //amount to increment a* by each iteration vmovaps zmm27, zmm0 vmovaps zmm28, zmm0 vmovaps zmm29, zmm0 #ifdef MONITORS rdtsc mov midl, eax mov midh, edx #endif jle CONSIDER_UNDER_40 sub rsi, 30 + L2_PREFETCH_DIST //First 30 iterations LOOPREFECHCL2: ONE_ITER_PC_L2(rcx) jne LOOPREFECHCL2 mov rcx, c //Main Loop. LOOPMAIN: ONE_ITER_MAIN_LOOP(rcx, rsi) jne LOOPMAIN //Penultimate 22 iterations. //Break these off from the main loop to avoid prefetching extra shit. mov r14, a_next mov r13, b_next sub r14, r15 sub r13, rbx mov rsi, L2_PREFETCH_DIST-10 LOOPMAIN2: ONE_ITER_MAIN_LOOP(rcx, rsi) jne LOOPMAIN2 //Last 10 iterations mov r8, 10 LOOPREFETCHCL1: ONE_ITER_PC_L1(rcx) jne LOOPREFETCHCL1 jmp POSTACCUM //Alternate main loop, with no prefetching of C //Used when <= 40 iterations CONSIDER_UNDER_40: mov rsi, k64 test rsi, rsi je POSTACCUM LOOP_UNDER_40: ONE_ITER_MAIN_LOOP(rcx, rsi) jne LOOP_UNDER_40 POSTACCUM: #ifdef MONITORS rdtsc mov mid2l, eax mov mid2h, edx #endif mov r9, c //load address of c for update mov r12, alpha //load address of alpha mov r14, beta vbroadcastsd zmm31, 0[r14] vmulpd zmm0, zmm0, 0[r12]{1to8} vmulpd zmm1, zmm1, 0[r12]{1to8} vmulpd zmm2, zmm2, 0[r12]{1to8} vmulpd zmm3, zmm3, 0[r12]{1to8} vfmadd231pd zmm0, zmm31, [r9+0] vfmadd231pd zmm1, zmm31, [r9+r11+0] vfmadd231pd zmm2, zmm31, [r9+2*r11+0] vfmadd231pd zmm3, zmm31, [r9+r10+0] vmovapd [r9+0], zmm0 vmovapd [r9+r11+0], zmm1 vmovapd [r9+2*r11+0], zmm2 vmovapd [r9+r10+0], zmm3 add r9, rdi vmulpd zmm4, zmm4, 0[r12]{1to8} vmulpd zmm5, zmm5, 0[r12]{1to8} vmulpd zmm6, zmm6, 0[r12]{1to8} vmulpd zmm7, zmm7, 0[r12]{1to8} vfmadd231pd zmm4, zmm31, [r9+0] vfmadd231pd zmm5, zmm31, [r9+r11+0] vfmadd231pd zmm6, zmm31, [r9+2*r11+0] vfmadd231pd zmm7, zmm31, [r9+r10+0] vmovapd [r9+0], zmm4 vmovapd [r9+r11+0], zmm5 vmovapd [r9+2*r11+0], zmm6 vmovapd [r9+r10+0], zmm7 add r9, rdi vmulpd zmm8, zmm8, 0[r12]{1to8} vmulpd zmm9, zmm9, 0[r12]{1to8} vmulpd zmm10, zmm10, 0[r12]{1to8} vmulpd zmm11, zmm11, 0[r12]{1to8} vfmadd231pd zmm8, zmm31, [r9+0] vfmadd231pd zmm9, zmm31, [r9+r11+0] vfmadd231pd zmm10, zmm31, [r9+2*r11+0] vfmadd231pd zmm11, zmm31, [r9+r10+0] vmovapd [r9+0], zmm8 vmovapd [r9+r11+0], zmm9 vmovapd [r9+2*r11+0], zmm10 vmovapd [r9+r10+0], zmm11 add r9, rdi vmulpd zmm12, zmm12, 0[r12]{1to8} vmulpd zmm13, zmm13, 0[r12]{1to8} vmulpd zmm14, zmm14, 0[r12]{1to8} vmulpd zmm15, zmm15, 0[r12]{1to8} vfmadd231pd zmm12, zmm31, [r9+0] vfmadd231pd zmm13, zmm31, [r9+r11+0] vfmadd231pd zmm14, zmm31, [r9+2*r11+0] vfmadd231pd zmm15, zmm31, [r9+r10+0] vmovapd [r9+0], zmm12 vmovapd [r9+r11+0], zmm13 vmovapd [r9+2*r11+0], zmm14 vmovapd [r9+r10+0], zmm15 add r9, rdi vmulpd zmm16, zmm16, 0[r12]{1to8} vmulpd zmm17, zmm17, 0[r12]{1to8} vmulpd zmm18, zmm18, 0[r12]{1to8} vmulpd zmm19, zmm19, 0[r12]{1to8} vfmadd231pd zmm16, zmm31, [r9+0] vfmadd231pd zmm17, zmm31, [r9+r11+0] vfmadd231pd zmm18, zmm31, [r9+2*r11+0] vfmadd231pd zmm19, zmm31, [r9+r10+0] vmovapd [r9+0], zmm16 vmovapd [r9+r11+0], zmm17 vmovapd [r9+2*r11+0], zmm18 vmovapd [r9+r10+0], zmm19 add r9, rdi vmulpd zmm20, zmm20, 0[r12]{1to8} vmulpd zmm21, zmm21, 0[r12]{1to8} vmulpd zmm22, zmm22, 0[r12]{1to8} vmulpd zmm23, zmm23, 0[r12]{1to8} vfmadd231pd zmm20, zmm31, [r9+0] vfmadd231pd zmm21, zmm31, [r9+r11+0] vfmadd231pd zmm22, zmm31, [r9+2*r11+0] vfmadd231pd zmm23, zmm31, [r9+r10+0] vmovapd [r9+0], zmm20 vmovapd [r9+r11+0], zmm21 vmovapd [r9+2*r11+0], zmm22 vmovapd [r9+r10+0], zmm23 add r9, rdi vmulpd zmm24, zmm24, 0[r12]{1to8} vmulpd zmm25, zmm25, 0[r12]{1to8} vmulpd zmm26, zmm26, 0[r12]{1to8} vmulpd zmm27, zmm27, 0[r12]{1to8} vfmadd231pd zmm24, zmm31, [r9+0] vfmadd231pd zmm25, zmm31, [r9+r11+0] vfmadd231pd zmm26, zmm31, [r9+2*r11+0] vfmadd231pd zmm27, zmm31, [r9+r10+0] vmovapd [r9+0], zmm24 vmovapd [r9+r11+0], zmm25 vmovapd [r9+2*r11+0], zmm26 vmovapd [r9+r10+0], zmm27 add r9, rdi vmulpd zmm28, zmm28, 0[r12]{1to8} vmulpd zmm29, zmm29, 0[r12]{1to8} vfmadd231pd zmm28, zmm31, [r9+0] vfmadd231pd zmm29, zmm31, [r9+r11+0] vmovapd [r9+0], zmm28 vmovapd [r9+r11+0], zmm29 END: #ifdef MONITORS rdtsc mov botl, eax mov both, edx #endif } GEMM_UKR_FLUSH_CT( d ); #ifdef LOOPMON printf("looptime = \t%d\n", bloopl - tloopl); #endif #ifdef MONITORS dim_t top = ((dim_t)toph << 32) | topl; dim_t mid = ((dim_t)midh << 32) | midl; dim_t mid2 = ((dim_t)mid2h << 32) | mid2l; dim_t bot = ((dim_t)both << 32) | botl; printf("setup =\t%u\tmain loop =\t%u\tcleanup=\t%u\ttotal=\t%u\n", mid - top, mid2 - mid, bot - mid2, bot - top); #endif } blis-0.9.0/kernels/knc/3/bli_sgemm_knc_asm_30x16.c000066400000000000000000000514041422157504600215010ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 UNIVERSITY OF TEXAS 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. */ #include "blis.h" #include #define A_L1_PREFETCH_DIST 4 #define B_L1_PREFETCH_DIST 2 #define L2_PREFETCH_DIST 16 // Must be greater than 10, because of the way the loop is constructed. //Alternate code path uused if C is not row-major #define UPDATE_C_ROW_SCATTERED(REG1, NUM, BASE_DEST) \ { \ __asm kmov k3, ebx \ __asm GATHER##NUM: \ __asm vgatherdps zmm31{k3}, [BASE_DEST + zmm30 * 4] \ __asm jknzd k3, GATHER##NUM \ \ __asm vmulps REG1, REG1, 0[r12]{1to16} /*scale by alpha*/ \ __asm vfmadd132ps zmm31, REG1, 0[r13]{1to16} /*scale by beta, add in result*/\ __asm kmov k3, ebx \ \ __asm SCATTER##NUM: \ __asm vscatterdps [BASE_DEST + zmm30 * 4]{k3}, zmm31 \ __asm jknzd k3, SCATTER##NUM \ __asm add BASE_DEST, r11 \ } //One iteration of the k_r loop. //Each iteration, we prefetch A into L1 and into L2 #define ONE_ITER_MAIN_LOOP(C_ADDR, COUNTER) \ {\ __asm vbroadcastf32x4 zmm30, 0[r15] \ __asm vmovaps zmm31, 0[rbx] \ \ __asm vfmadd231ps zmm0, zmm31, zmm30{aaaa} \ __asm vfmadd231ps zmm4, zmm31, 4*4[r15]{1to16} \ __asm vprefetch0 A_L1_PREFETCH_DIST*256[r15] \ __asm vfmadd231ps zmm5, zmm31, 5*4[r15]{1to16} \ __asm vprefetch0 A_L1_PREFETCH_DIST*256+64[r15] \ __asm vfmadd231ps zmm6, zmm31, 6*4[r15]{1to16} \ __asm vprefetch0 A_L1_PREFETCH_DIST*256+128[r15]\ __asm vfmadd231ps zmm7, zmm31, 7*4[r15]{1to16} \ __asm vprefetch0 A_L1_PREFETCH_DIST*256+192[r15]\ __asm vfmadd231ps zmm8, zmm31, 8*4[r15]{1to16} \ \ __asm vprefetch1 0[r15 + r14] \ __asm vfmadd231ps zmm9, zmm31, 9*4[r15]{1to16} \ __asm vfmadd231ps zmm1, zmm31, zmm30{bbbb} \ __asm vfmadd231ps zmm2, zmm31, zmm30{cccc} \ __asm vfmadd231ps zmm3, zmm31, zmm30{dddd} \ __asm vfmadd231ps zmm10, zmm31, 10*4[r15]{1to16} \ \ __asm vprefetch1 64[r15 + r14] \ __asm vfmadd231ps zmm11, zmm31, 11*4[r15]{1to16} \ __asm vfmadd231ps zmm12, zmm31, 12*4[r15]{1to16} \ __asm vfmadd231ps zmm13, zmm31, 13*4[r15]{1to16} \ __asm vfmadd231ps zmm14, zmm31, 14*4[r15]{1to16} \ __asm vfmadd231ps zmm15, zmm31, 15*4[r15]{1to16} \ \ __asm vprefetch1 2*64[r15 + r14] \ __asm vfmadd231ps zmm16, zmm31, 16*4[r15]{1to16} \ __asm vfmadd231ps zmm17, zmm31, 17*4[r15]{1to16} \ __asm vfmadd231ps zmm18, zmm31, 18*4[r15]{1to16} \ __asm vfmadd231ps zmm19, zmm31, 19*4[r15]{1to16} \ __asm vfmadd231ps zmm20, zmm31, 20*4[r15]{1to16} \ \ __asm vprefetch1 3*64[r15 + r14] \ __asm vfmadd231ps zmm21, zmm31, 21*4[r15]{1to16} \ __asm add r15, r12 \ __asm vfmadd231ps zmm22, zmm31, -10*4[r15]{1to16}\ __asm vfmadd231ps zmm23, zmm31, -9*4[r15]{1to16} \ __asm vfmadd231ps zmm24, zmm31, -8*4[r15]{1to16} \ __asm dec COUNTER \ __asm vfmadd231ps zmm25, zmm31, -7*4[r15]{1to16} \ \ \ __asm vprefetch1 0[rbx + r13] \ __asm vfmadd231ps zmm26, zmm31, -6*4[r15]{1to16} \ __asm vprefetch0 B_L1_PREFETCH_DIST*16*4[rbx] \ __asm vfmadd231ps zmm27, zmm31, -5*4[r15]{1to16} \ __asm add rbx, r9 \ __asm vfmadd231ps zmm28, zmm31, -4*4[r15]{1to16} \ __asm cmp COUNTER, 0 \ __asm vfmadd231ps zmm29, zmm31, -3*4[r15]{1to16} \ } //One iteration of the k_r loop. //Same as ONE_ITER_MAIN_LOOP, but additionally, we prefetch one line of C into the L2 cache //Current placement of this prefetch instruction is somewhat arbitrary. #define ONE_ITER_PC_L2(C_ADDR) \ {\ __asm vbroadcastf32x4 zmm30, 0[r15] \ __asm vmovaps zmm31, 0[rbx] \ \ __asm vfmadd231ps zmm0, zmm31, zmm30{aaaa} \ __asm vfmadd231ps zmm4, zmm31, 4*4[r15]{1to16} \ __asm vprefetch0 A_L1_PREFETCH_DIST*256[r15] \ __asm vfmadd231ps zmm5, zmm31, 5*4[r15]{1to16} \ __asm vprefetch0 A_L1_PREFETCH_DIST*256+64[r15] \ __asm vfmadd231ps zmm6, zmm31, 6*4[r15]{1to16} \ __asm vprefetch0 A_L1_PREFETCH_DIST*256+128[r15]\ __asm vfmadd231ps zmm7, zmm31, 7*4[r15]{1to16} \ __asm vprefetch0 A_L1_PREFETCH_DIST*256+192[r15]\ __asm vfmadd231ps zmm8, zmm31, 8*4[r15]{1to16} \ \ __asm vprefetch1 0[r15 + r14] \ __asm vfmadd231ps zmm9, zmm31, 9*4[r15]{1to16} \ __asm vfmadd231ps zmm1, zmm31, zmm30{bbbb} \ __asm vfmadd231ps zmm2, zmm31, zmm30{cccc} \ __asm vfmadd231ps zmm3, zmm31, zmm30{dddd} \ __asm vfmadd231ps zmm10, zmm31, 10*4[r15]{1to16} \ \ __asm vprefetch1 64[r15 + r14] \ __asm vfmadd231ps zmm11, zmm31, 11*4[r15]{1to16} \ __asm vprefetch1 0[C_ADDR] \ __asm vfmadd231ps zmm12, zmm31, 12*4[r15]{1to16} \ __asm vfmadd231ps zmm13, zmm31, 13*4[r15]{1to16} \ __asm vfmadd231ps zmm14, zmm31, 14*4[r15]{1to16} \ __asm vfmadd231ps zmm15, zmm31, 15*4[r15]{1to16} \ \ __asm vprefetch1 2*64[r15 + r14] \ __asm vfmadd231ps zmm16, zmm31, 16*4[r15]{1to16} \ __asm vfmadd231ps zmm17, zmm31, 17*4[r15]{1to16} \ __asm vfmadd231ps zmm18, zmm31, 18*4[r15]{1to16} \ __asm vfmadd231ps zmm19, zmm31, 19*4[r15]{1to16} \ __asm vfmadd231ps zmm20, zmm31, 20*4[r15]{1to16} \ \ __asm vprefetch1 3*64[r15 + r14] \ __asm vfmadd231ps zmm21, zmm31, 21*4[r15]{1to16} \ __asm add r15, r12 \ __asm vfmadd231ps zmm22, zmm31, -10*4[r15]{1to16}\ __asm vfmadd231ps zmm23, zmm31, -9*4[r15]{1to16} \ __asm add C_ADDR, r11 \ __asm vfmadd231ps zmm24, zmm31, -8*4[r15]{1to16} \ __asm dec r8 \ __asm vfmadd231ps zmm25, zmm31, -7*4[r15]{1to16} \ \ \ __asm vprefetch1 0[rbx + r13] \ __asm vfmadd231ps zmm26, zmm31, -6*4[r15]{1to16} \ __asm vprefetch0 B_L1_PREFETCH_DIST*16*4[rbx] \ __asm vfmadd231ps zmm27, zmm31, -5*4[r15]{1to16} \ __asm add rbx, r9 \ __asm vfmadd231ps zmm28, zmm31, -4*4[r15]{1to16} \ __asm cmp r8, 0 \ __asm vfmadd231ps zmm29, zmm31, -3*4[r15]{1to16} \ \ } //One iteration of the k_r loop. //Same as ONE_ITER_MAIN_LOOP, but additionally, we prefetch 3 cache lines of C into the L1 cache //Current placement of these prefetch instructions is somewhat arbitrary. #define ONE_ITER_PC_L1(C_ADDR) \ {\ __asm vbroadcastf32x4 zmm30, 0[r15] \ __asm vmovaps zmm31, 0[rbx] \ \ __asm vfmadd231ps zmm0, zmm31, zmm30{aaaa} \ __asm vfmadd231ps zmm4, zmm31, 4*4[r15]{1to16} \ __asm vprefetch0 A_L1_PREFETCH_DIST*256[r15] \ __asm vfmadd231ps zmm5, zmm31, 5*4[r15]{1to16} \ __asm vprefetch0 A_L1_PREFETCH_DIST*256+64[r15] \ __asm vfmadd231ps zmm6, zmm31, 6*4[r15]{1to16} \ __asm vprefetch0 A_L1_PREFETCH_DIST*256+128[r15]\ __asm vfmadd231ps zmm7, zmm31, 7*4[r15]{1to16} \ __asm vprefetch0 A_L1_PREFETCH_DIST*256+192[r15]\ __asm vfmadd231ps zmm8, zmm31, 8*4[r15]{1to16} \ \ __asm vprefetch1 0[r15 + r14] \ __asm vfmadd231ps zmm9, zmm31, 9*4[r15]{1to16} \ __asm vprefetch0 0[C_ADDR] \ __asm vfmadd231ps zmm1, zmm31, zmm30{bbbb} \ __asm add C_ADDR, r11 \ __asm vfmadd231ps zmm2, zmm31, zmm30{cccc} \ __asm vfmadd231ps zmm3, zmm31, zmm30{dddd} \ __asm vfmadd231ps zmm10, zmm31, 10*4[r15]{1to16} \ \ __asm vprefetch1 64[r15 + r14] \ __asm vfmadd231ps zmm11, zmm31, 11*4[r15]{1to16} \ __asm vprefetch0 0[C_ADDR] \ __asm vfmadd231ps zmm12, zmm31, 12*4[r15]{1to16} \ __asm add C_ADDR, r11 \ __asm vfmadd231ps zmm13, zmm31, 13*4[r15]{1to16} \ __asm vfmadd231ps zmm14, zmm31, 14*4[r15]{1to16} \ __asm vfmadd231ps zmm15, zmm31, 15*4[r15]{1to16} \ \ __asm vprefetch1 2*64[r15 + r14] \ __asm vfmadd231ps zmm16, zmm31, 16*4[r15]{1to16} \ __asm vprefetch0 0[C_ADDR] \ __asm vfmadd231ps zmm17, zmm31, 17*4[r15]{1to16} \ __asm add C_ADDR, r11 \ __asm vfmadd231ps zmm18, zmm31, 18*4[r15]{1to16} \ __asm vfmadd231ps zmm19, zmm31, 19*4[r15]{1to16} \ __asm vfmadd231ps zmm20, zmm31, 20*4[r15]{1to16} \ \ __asm vprefetch1 3*64[r15 + r14] \ __asm vfmadd231ps zmm21, zmm31, 21*4[r15]{1to16} \ __asm add r15, r12 \ __asm vfmadd231ps zmm22, zmm31, -10*4[r15]{1to16}\ __asm vfmadd231ps zmm23, zmm31, -9*4[r15]{1to16} \ __asm vfmadd231ps zmm24, zmm31, -8*4[r15]{1to16} \ __asm dec r8 \ __asm vfmadd231ps zmm25, zmm31, -7*4[r15]{1to16} \ \ \ __asm vprefetch1 0[rbx + r13] \ __asm vfmadd231ps zmm26, zmm31, -6*4[r15]{1to16} \ __asm vprefetch0 B_L1_PREFETCH_DIST*16*4[rbx] \ __asm vfmadd231ps zmm27, zmm31, -5*4[r15]{1to16} \ __asm add rbx, r9 \ __asm vfmadd231ps zmm28, zmm31, -4*4[r15]{1to16} \ __asm cmp r8, 0 \ __asm vfmadd231ps zmm29, zmm31, -3*4[r15]{1to16} \ \ } //This is an array used for the scattter/gather instructions. int offsets[16] __attribute__((aligned(0x1000))) = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; //#define MONITORS //#define LOOPMON void bli_sgemm_knc_asm_30x16 ( dim_t m, dim_t n, dim_t k, float* restrict alpha, float* restrict a, float* restrict b, float* restrict beta, float* restrict c, inc_t rs_c, inc_t cs_c, auxinfo_t* restrict data, cntx_t* restrict cntx ) { float * a_next = bli_auxinfo_next_a( data ); float * b_next = bli_auxinfo_next_b( data ); int * offsetPtr = &offsets[0]; uint64_t k64 = k; GEMM_UKR_SETUP_CT( s, 30, 16, true ); #ifdef MONITORS int toph, topl, both, botl, midl, midh, mid2l, mid2h; #endif #ifdef LOOPMON int tlooph, tloopl, blooph, bloopl; #endif __asm { #ifdef MONITORS rdtsc mov topl, eax mov toph, edx #endif vpxord zmm0, zmm0, zmm0 vmovaps zmm1, zmm0 //clear out registers vmovaps zmm2, zmm0 mov rsi, k64 //loop index vmovaps zmm3, zmm0 mov r11, rs_c //load row stride vmovaps zmm4, zmm0 sal r11, 2 //scale row stride vmovaps zmm5, zmm0 mov r15, a //load address of a vmovaps zmm6, zmm0 mov rbx, b //load address of b vmovaps zmm7, zmm0 vmovaps zmm8, zmm0 lea r10, [r11 + 2*r11 + 0] //r10 has 3 * r11 vmovaps zmm9, zmm0 vmovaps zmm10, zmm0 mov rdi, r11 vmovaps zmm11, zmm0 sal rdi, 2 //rdi has 4*r11 vmovaps zmm12, zmm0 mov rcx, c //load address of c for prefetching vmovaps zmm13, zmm0 vmovaps zmm14, zmm0 mov r8, k64 vmovaps zmm15, zmm0 vmovaps zmm16, zmm0 vmovaps zmm17, zmm0 mov r13, L2_PREFETCH_DIST*4*16 vmovaps zmm18, zmm0 mov r14, L2_PREFETCH_DIST*4*32 vmovaps zmm19, zmm0 vmovaps zmm20, zmm0 vmovaps zmm21, zmm0 vmovaps zmm22, zmm0 vmovaps zmm23, zmm0 sub r8, 30 + L2_PREFETCH_DIST //Check if we have over 40 operations to do. vmovaps zmm24, zmm0 mov r8, 30 vmovaps zmm25, zmm0 mov r9, 16*4 //amount to increment b* by each iteration vmovaps zmm26, zmm0 mov r12, 32*4 //amount to increment a* by each iteration vmovaps zmm27, zmm0 vmovaps zmm28, zmm0 vmovaps zmm29, zmm0 #ifdef MONITORS rdtsc mov midl, eax mov midh, edx #endif jle CONSIDER_UNDER_40 sub rsi, 30 + L2_PREFETCH_DIST //First 30 iterations LOOPREFECHCL2: ONE_ITER_PC_L2(rcx) jne LOOPREFECHCL2 mov rcx, c //Main Loop. LOOPMAIN: ONE_ITER_MAIN_LOOP(rcx, rsi) jne LOOPMAIN //Penultimate 22 iterations. //Break these off from the main loop to avoid prefetching extra shit. mov r14, a_next mov r13, b_next sub r14, r15 sub r13, rbx mov rsi, L2_PREFETCH_DIST-10 LOOPMAIN2: ONE_ITER_MAIN_LOOP(rcx, rsi) jne LOOPMAIN2 //Last 10 iterations mov r8, 10 LOOPREFETCHCL1: ONE_ITER_PC_L1(rcx) jne LOOPREFETCHCL1 jmp POSTACCUM //Alternate main loop, with no prefetching of C //Used when <= 40 iterations CONSIDER_UNDER_40: mov rsi, k64 test rsi, rsi je POSTACCUM LOOP_UNDER_40: ONE_ITER_MAIN_LOOP(rcx, rsi) jne LOOP_UNDER_40 POSTACCUM: #ifdef MONITORS rdtsc mov mid2l, eax mov mid2h, edx #endif mov r9, c //load address of c for update mov r12, alpha //load address of alpha mov r14, beta vbroadcastss zmm31, 0[r14] vmulps zmm0, zmm0, 0[r12]{1to16} vmulps zmm1, zmm1, 0[r12]{1to16} vmulps zmm2, zmm2, 0[r12]{1to16} vmulps zmm3, zmm3, 0[r12]{1to16} vfmadd231ps zmm0, zmm31, [r9+0] vfmadd231ps zmm1, zmm31, [r9+r11+0] vfmadd231ps zmm2, zmm31, [r9+2*r11+0] vfmadd231ps zmm3, zmm31, [r9+r10+0] vmovaps [r9+0], zmm0 vmovaps [r9+r11+0], zmm1 vmovaps [r9+2*r11+0], zmm2 vmovaps [r9+r10+0], zmm3 add r9, rdi vmulps zmm4, zmm4, 0[r12]{1to16} vmulps zmm5, zmm5, 0[r12]{1to16} vmulps zmm6, zmm6, 0[r12]{1to16} vmulps zmm7, zmm7, 0[r12]{1to16} vfmadd231ps zmm4, zmm31, [r9+0] vfmadd231ps zmm5, zmm31, [r9+r11+0] vfmadd231ps zmm6, zmm31, [r9+2*r11+0] vfmadd231ps zmm7, zmm31, [r9+r10+0] vmovaps [r9+0], zmm4 vmovaps [r9+r11+0], zmm5 vmovaps [r9+2*r11+0], zmm6 vmovaps [r9+r10+0], zmm7 add r9, rdi vmulps zmm8, zmm8, 0[r12]{1to16} vmulps zmm9, zmm9, 0[r12]{1to16} vmulps zmm10, zmm10, 0[r12]{1to16} vmulps zmm11, zmm11, 0[r12]{1to16} vfmadd231ps zmm8, zmm31, [r9+0] vfmadd231ps zmm9, zmm31, [r9+r11+0] vfmadd231ps zmm10, zmm31, [r9+2*r11+0] vfmadd231ps zmm11, zmm31, [r9+r10+0] vmovaps [r9+0], zmm8 vmovaps [r9+r11+0], zmm9 vmovaps [r9+2*r11+0], zmm10 vmovaps [r9+r10+0], zmm11 add r9, rdi vmulps zmm12, zmm12, 0[r12]{1to16} vmulps zmm13, zmm13, 0[r12]{1to16} vmulps zmm14, zmm14, 0[r12]{1to16} vmulps zmm15, zmm15, 0[r12]{1to16} vfmadd231ps zmm12, zmm31, [r9+0] vfmadd231ps zmm13, zmm31, [r9+r11+0] vfmadd231ps zmm14, zmm31, [r9+2*r11+0] vfmadd231ps zmm15, zmm31, [r9+r10+0] vmovaps [r9+0], zmm12 vmovaps [r9+r11+0], zmm13 vmovaps [r9+2*r11+0], zmm14 vmovaps [r9+r10+0], zmm15 add r9, rdi vmulps zmm16, zmm16, 0[r12]{1to16} vmulps zmm17, zmm17, 0[r12]{1to16} vmulps zmm18, zmm18, 0[r12]{1to16} vmulps zmm19, zmm19, 0[r12]{1to16} vfmadd231ps zmm16, zmm31, [r9+0] vfmadd231ps zmm17, zmm31, [r9+r11+0] vfmadd231ps zmm18, zmm31, [r9+2*r11+0] vfmadd231ps zmm19, zmm31, [r9+r10+0] vmovaps [r9+0], zmm16 vmovaps [r9+r11+0], zmm17 vmovaps [r9+2*r11+0], zmm18 vmovaps [r9+r10+0], zmm19 add r9, rdi vmulps zmm20, zmm20, 0[r12]{1to16} vmulps zmm21, zmm21, 0[r12]{1to16} vmulps zmm22, zmm22, 0[r12]{1to16} vmulps zmm23, zmm23, 0[r12]{1to16} vfmadd231ps zmm20, zmm31, [r9+0] vfmadd231ps zmm21, zmm31, [r9+r11+0] vfmadd231ps zmm22, zmm31, [r9+2*r11+0] vfmadd231ps zmm23, zmm31, [r9+r10+0] vmovaps [r9+0], zmm20 vmovaps [r9+r11+0], zmm21 vmovaps [r9+2*r11+0], zmm22 vmovaps [r9+r10+0], zmm23 add r9, rdi vmulps zmm24, zmm24, 0[r12]{1to16} vmulps zmm25, zmm25, 0[r12]{1to16} vmulps zmm26, zmm26, 0[r12]{1to16} vmulps zmm27, zmm27, 0[r12]{1to16} vfmadd231ps zmm24, zmm31, [r9+0] vfmadd231ps zmm25, zmm31, [r9+r11+0] vfmadd231ps zmm26, zmm31, [r9+2*r11+0] vfmadd231ps zmm27, zmm31, [r9+r10+0] vmovaps [r9+0], zmm24 vmovaps [r9+r11+0], zmm25 vmovaps [r9+2*r11+0], zmm26 vmovaps [r9+r10+0], zmm27 add r9, rdi vmulps zmm28, zmm28, 0[r12]{1to16} vmulps zmm29, zmm29, 0[r12]{1to16} vfmadd231ps zmm28, zmm31, [r9+0] vfmadd231ps zmm29, zmm31, [r9+r11+0] vmovaps [r9+0], zmm28 vmovaps [r9+r11+0], zmm29 END: #ifdef MONITORS rdtsc mov botl, eax mov both, edx #endif } GEMM_UKR_FLUSH_CT( s ); #ifdef LOOPMON printf("looptime = \t%d\n", bloopl - tloopl); #endif #ifdef MONITORS dim_t top = ((dim_t)toph << 32) | topl; dim_t mid = ((dim_t)midh << 32) | midl; dim_t mid2 = ((dim_t)mid2h << 32) | mid2l; dim_t bot = ((dim_t)both << 32) | botl; printf("setup =\t%u\tmain loop =\t%u\tcleanup=\t%u\ttotal=\t%u\n", mid - top, mid2 - mid, bot - mid2, bot - top); #endif } blis-0.9.0/kernels/knc/bli_kernels_knc.h000066400000000000000000000033531422157504600201760ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ GEMM_UKR_PROT( float, s, gemm_knc_asm_30x16 ) GEMM_UKR_PROT( double, d, gemm_knc_asm_30x8 ) blis-0.9.0/kernels/knl/000077500000000000000000000000001422157504600147065ustar00rootroot00000000000000blis-0.9.0/kernels/knl/1m/000077500000000000000000000000001422157504600152235ustar00rootroot00000000000000blis-0.9.0/kernels/knl/1m/bli_dpackm_knl_asm_24x8.c000066400000000000000000000463451422157504600217610ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define BLIS_ASM_SYNTAX_INTEL #include "bli_x86_asm_macros.h" #define LOADMUL8x8(a,o,s1,s3,s5,s7, \ z0,z1,z2,z3,z4,z5,z6,z7) \ \ VMULPD(ZMM(z0), ZMM(31), MEM(a, o)) \ VMULPD(ZMM(z1), ZMM(31), MEM(a,s1,1,o)) \ VMULPD(ZMM(z2), ZMM(31), MEM(a,s1,2,o)) \ VMULPD(ZMM(z3), ZMM(31), MEM(a,s3,1,o)) \ VMULPD(ZMM(z4), ZMM(31), MEM(a,s1,4,o)) \ VMULPD(ZMM(z5), ZMM(31), MEM(a,s5,1,o)) \ VMULPD(ZMM(z6), ZMM(31), MEM(a,s3,2,o)) \ VMULPD(ZMM(z7), ZMM(31), MEM(a,s7,1,o)) #define LOADMUL8x8_MASK(a,o,s1,s3,s5,s7, \ z0,z1,z2,z3,z4,z5,z6,z7,k) \ \ VMULPD(ZMM(z0) MASK_KZ(k), ZMM(31), MEM(a, o)) \ VMULPD(ZMM(z1) MASK_KZ(k), ZMM(31), MEM(a,s1,1,o)) \ VMULPD(ZMM(z2) MASK_KZ(k), ZMM(31), MEM(a,s1,2,o)) \ VMULPD(ZMM(z3) MASK_KZ(k), ZMM(31), MEM(a,s3,1,o)) \ VMULPD(ZMM(z4) MASK_KZ(k), ZMM(31), MEM(a,s1,4,o)) \ VMULPD(ZMM(z5) MASK_KZ(k), ZMM(31), MEM(a,s5,1,o)) \ VMULPD(ZMM(z6) MASK_KZ(k), ZMM(31), MEM(a,s3,2,o)) \ VMULPD(ZMM(z7) MASK_KZ(k), ZMM(31), MEM(a,s7,1,o)) #define STORE8x8(a,o,s1,s3,s5,s7, \ z0,z1,z2,z3,z4,z5,z6,z7) \ \ VMOVUPD(MEM(a, o), ZMM(z0)) \ VMOVUPD(MEM(a,s1,1,o), ZMM(z1)) \ VMOVUPD(MEM(a,s1,2,o), ZMM(z2)) \ VMOVUPD(MEM(a,s3,1,o), ZMM(z3)) \ VMOVUPD(MEM(a,s1,4,o), ZMM(z4)) \ VMOVUPD(MEM(a,s5,1,o), ZMM(z5)) \ VMOVUPD(MEM(a,s3,2,o), ZMM(z6)) \ VMOVUPD(MEM(a,s7,1,o), ZMM(z7)) #define TRANSPOSE8x8(a0,a1,a2,a3,a4,a5,a6,a7, \ b0,b1,b2,b3,b4,b5,b6,b7) \ \ VUNPCKLPD(ZMM(b0), ZMM(a0), ZMM(a1)) \ VUNPCKHPD(ZMM(b1), ZMM(a0), ZMM(a1)) \ VUNPCKLPD(ZMM(b2), ZMM(a2), ZMM(a3)) \ VUNPCKHPD(ZMM(b3), ZMM(a2), ZMM(a3)) \ VUNPCKLPD(ZMM(b4), ZMM(a4), ZMM(a5)) \ VUNPCKHPD(ZMM(b5), ZMM(a4), ZMM(a5)) \ VUNPCKLPD(ZMM(b6), ZMM(a6), ZMM(a7)) \ VUNPCKHPD(ZMM(b7), ZMM(a6), ZMM(a7)) \ VSHUFF64X2(ZMM(a0), ZMM(b0), ZMM(b2), IMM(0x44)) \ VSHUFF64X2(ZMM(a1), ZMM(b1), ZMM(b3), IMM(0x44)) \ VSHUFF64X2(ZMM(a2), ZMM(b0), ZMM(b2), IMM(0xEE)) \ VSHUFF64X2(ZMM(a3), ZMM(b1), ZMM(b3), IMM(0xEE)) \ VSHUFF64X2(ZMM(a4), ZMM(b4), ZMM(b6), IMM(0x44)) \ VSHUFF64X2(ZMM(a5), ZMM(b5), ZMM(b7), IMM(0x44)) \ VSHUFF64X2(ZMM(a6), ZMM(b4), ZMM(b6), IMM(0xEE)) \ VSHUFF64X2(ZMM(a7), ZMM(b5), ZMM(b7), IMM(0xEE)) \ VSHUFF64X2(ZMM(b0), ZMM(a0), ZMM(a4), IMM(0x88)) \ VSHUFF64X2(ZMM(b1), ZMM(a1), ZMM(a5), IMM(0x88)) \ VSHUFF64X2(ZMM(b2), ZMM(a0), ZMM(a4), IMM(0xDD)) \ VSHUFF64X2(ZMM(b3), ZMM(a1), ZMM(a5), IMM(0xDD)) \ VSHUFF64X2(ZMM(b4), ZMM(a2), ZMM(a6), IMM(0x88)) \ VSHUFF64X2(ZMM(b5), ZMM(a3), ZMM(a7), IMM(0x88)) \ VSHUFF64X2(ZMM(b6), ZMM(a2), ZMM(a6), IMM(0xDD)) \ VSHUFF64X2(ZMM(b7), ZMM(a3), ZMM(a7), IMM(0xDD)) //This is an array used for the scatter/gather instructions. static int32_t offsets[32] __attribute__((aligned(64))) = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15, 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31}; void bli_dpackm_knl_asm_8xk ( conj_t conja, pack_t schema, dim_t cdim_, dim_t n_, dim_t n_max_, double* restrict kappa_, double* restrict a_, inc_t inca_, inc_t lda_, double* restrict p_, inc_t ldp_, cntx_t* restrict cntx ) { const int32_t* offsetPtr = &offsets[0]; double* a = ( double* )a_; double* p = ( double* )p_; double* kappa = ( double* )kappa_; const int64_t cdim = cdim_; const int64_t mnr = 8; const int64_t n = n_; const int64_t n_max = n_max_; const int64_t inca = inca_; const int64_t lda = lda_; const int64_t ldp = ldp_; if ( cdim == mnr ) { BEGIN_ASM() MOV(RSI, VAR(n)) MOV(RAX, VAR(a)) MOV(RBX, VAR(inca)) MOV(RCX, VAR(lda)) MOV(R14, VAR(p)) MOV(RDI, VAR(ldp)) TEST(RSI, RSI) JZ(PACK8_DONE) LEA(RBX, MEM(,RBX,8)) //inca in bytes LEA(RCX, MEM(,RCX,8)) //lda in bytes LEA(RDI, MEM(,RDI,8)) //ldp in bytes LEA(R11, MEM(RDI,RDI,2)) //ldp*3 LEA(R12, MEM(RDI,RDI,4)) //ldp*5 LEA(R13, MEM(R11,RDI,4)) //ldp*7 VBROADCASTSD(ZMM(31), VAR(kappa)) CMP(RBX, IMM(8)) JNE(PACK8_T) LABEL(PACK8_N) MOV(RDX, RSI) AND(RDX, IMM(7)) SAR(RSI, IMM(3)) JZ(PACK8_N_TAIL) LEA(R8, MEM(RCX,RCX,2)) //lda*3 LEA(R9, MEM(RCX,RCX,4)) //lda*5 LEA(R10, MEM(R8 ,RCX,4)) //lda*7 LABEL(PACK8_N_LOOP) LOADMUL8x8(RAX,0,RCX,R8,R9,R10,0,1,2,3,4,5,6,7) STORE8x8(R14,0,RDI,R11,R12,R13,0,1,2,3,4,5,6,7) LEA(RAX, MEM(RAX,RCX,8)) LEA(R14, MEM(R14,RDI,8)) SUB(RSI, IMM(1)) JNZ(PACK8_N_LOOP) TEST(RDX, RDX) JZ(PACK8_DONE) LABEL(PACK8_N_TAIL) VMULPD(ZMM(0), ZMM(31), MEM(RAX)) VMOVUPD(MEM(R14), ZMM(0)) LEA(RAX, MEM(RAX,RCX,1)) LEA(R14, MEM(R14,RDI,1)) SUB(RDX, IMM(1)) JNZ(PACK8_N_TAIL) JMP(PACK8_DONE) LABEL(PACK8_T) CMP(RCX, IMM(8)) JNE(PACK8_G) LEA(R8, MEM(RBX,RBX,2)) //inca*3 LEA(R9, MEM(RBX,RBX,4)) //inca*5 LEA(R10, MEM(R8 ,RBX,4)) //inca*7 MOV(RDX, RSI) AND(RDX, IMM(7)) SAR(RSI, IMM(3)) JZ(PACK8_T_TAIL) LABEL(PACK8_T_LOOP) LOADMUL8x8(RAX,0,RBX,R8,R9,R10,0,1,2,3,4,5,6,7) TRANSPOSE8x8( 0, 1, 2, 3, 4, 5, 6, 7, 16,17,18,19,20,21,22,23) STORE8x8(R14,0,RDI,R11,R12,R13,16,17,18,19,20,21,22,23) LEA(RAX, MEM(RAX,RCX,8)) LEA(R14, MEM(R14,RDI,8)) SUB(RSI, IMM(1)) JNZ(PACK8_T_LOOP) TEST(RDX, RDX) JZ(PACK8_DONE) LABEL(PACK8_T_TAIL) MOV(RSI, IMM(1)) SHLX(RSI, RSI, RDX) SUB(RSI, IMM(1)) KMOVW(K(1), ESI) //mask for n%8 elements LOADMUL8x8_MASK(RAX,0,RBX,R8,R9,R10,0,1,2,3,4,5,6,7,1) TRANSPOSE8x8( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15) VMOVUPD(MEM(R14 ), ZMM( 8)) SUB(RDX, IMM(1)) JZ(PACK8_DONE) VMOVUPD(MEM(R14,RDI,1), ZMM( 9)) SUB(RDX, IMM(1)) JZ(PACK8_DONE) VMOVUPD(MEM(R14,RDI,2), ZMM(10)) SUB(RDX, IMM(1)) JZ(PACK8_DONE) VMOVUPD(MEM(R14,R11,1), ZMM(11)) SUB(RDX, IMM(1)) JZ(PACK8_DONE) VMOVUPD(MEM(R14,RDI,4), ZMM(12)) SUB(RDX, IMM(1)) JZ(PACK8_DONE) VMOVUPD(MEM(R14,R12,1), ZMM(13)) SUB(RDX, IMM(1)) JZ(PACK8_DONE) VMOVUPD(MEM(R14,R11,2), ZMM(14)) JMP(PACK8_DONE) LABEL(PACK8_G) VPBROADCASTD(ZMM(3), VAR(inca)) MOV(RBX, VAR(offsetPtr)) VPMULLD(YMM(0), YMM(3), MEM(RBX)) LABEL(PACK8_G_LOOP) KXNORW(K(1), K(0), K(0)) VGATHERDPD(ZMM(3) MASK_K(1), MEM(RAX,YMM(0),8)) VMULPD(ZMM(3), ZMM(3), ZMM(31)) VMOVUPD(MEM(R14), ZMM(3)) LEA(RAX, MEM(RAX,RCX,1)) LEA(R14, MEM(R14,RDI,1)) SUB(RSI, IMM(1)) JNZ(PACK8_G_LOOP) LABEL(PACK8_DONE) END_ASM( : //output operands : //input operands [n] "m" (n), [kappa] "m" (*kappa), [a] "m" (a), [inca] "m" (inca), [lda] "m" (lda), [p] "m" (p), [ldp] "m" (ldp), [offsetPtr] "m" (offsetPtr) : //clobbers "zmm0", "zmm1", "zmm2", "zmm3", "zmm4", "zmm5", "zmm6", "zmm7", "zmm8", "zmm9", "zmm10", "zmm11", "zmm12", "zmm13", "zmm14", "zmm15", "zmm16", "zmm17", "zmm18", "zmm19", "zmm20", "zmm21", "zmm22", "zmm23", "zmm24", "zmm25", "zmm26", "zmm27", "zmm28", "zmm29", "zmm30", "zmm31", "rax", "rbx", "rcx", "rdx", "rdi", "rsi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "memory" ) } else // if ( cdim < mnr ) { bli_dscal2m_ex \ ( \ 0, \ BLIS_NONUNIT_DIAG, \ BLIS_DENSE, \ ( trans_t )conja, \ cdim, \ n, \ kappa, \ a, inca, lda, \ p, 1, ldp, \ cntx, \ NULL \ ); \ // if ( cdim < mnr ) { const dim_t i = cdim; const dim_t m_edge = mnr - i; const dim_t n_edge = n_max; double* restrict p_edge = p + (i )*1; bli_dset0s_mxn ( m_edge, n_edge, p_edge, 1, ldp ); } } if ( n < n_max ) { const dim_t j = n; const dim_t m_edge = mnr; const dim_t n_edge = n_max - j; double* restrict p_edge = p + (j )*ldp; bli_dset0s_mxn ( m_edge, n_edge, p_edge, 1, ldp ); } } void bli_dpackm_knl_asm_24xk ( conj_t conja, pack_t schema, dim_t cdim_, dim_t n_, dim_t n_max_, double* restrict kappa_, double* restrict a_, inc_t inca_, inc_t lda_, double* restrict p_, inc_t ldp_, cntx_t* restrict cntx ) { const int32_t* offsetPtr = &offsets[0]; double* a = ( double* )a_; double* p = ( double* )p_; double* kappa = ( double* )kappa_; const int64_t cdim = cdim_; const int64_t mnr = 24; const int64_t n = n_; const int64_t n_max = n_max_; const int64_t inca = inca_; const int64_t lda = lda_; const int64_t ldp = ldp_; if ( cdim == mnr ) { BEGIN_ASM() MOV(RSI, VAR(n)) MOV(RAX, VAR(a)) MOV(RBX, VAR(inca)) MOV(RCX, VAR(lda)) MOV(R15, VAR(p)) MOV(RDI, VAR(ldp)) LEA(RBX, MEM(,RBX,8)) //inca in bytes LEA(RCX, MEM(,RCX,8)) //lda in bytes LEA(RDI, MEM(,RDI,8)) //ldp in bytes LEA(R11, MEM(RDI,RDI,2)) //ldp*3 LEA(R12, MEM(RDI,RDI,4)) //ldp*5 LEA(R13, MEM(R11,RDI,4)) //ldp*7 VBROADCASTSD(ZMM(31), VAR(kappa)) TEST(RSI, RSI) JZ(PACK24_DONE) CMP(RBX, IMM(8)) JNE(PACK24_T) LABEL(PACK24_N) SAR(RSI, IMM(3)) JZ(PACK24_N_TAIL) LEA(R8, MEM(RCX,RCX,2)) //lda*3 LEA(R9, MEM(RCX,RCX,4)) //lda*5 LEA(R10, MEM(R8 ,RCX,4)) //lda*7 LABEL(PACK24_N_LOOP) LOADMUL8x8(RAX, 0,RCX,R8,R9,R10, 0, 1, 2, 3, 4, 5, 6, 7) LOADMUL8x8(RAX, 64,RCX,R8,R9,R10, 8, 9,10,11,12,13,14,15) LOADMUL8x8(RAX,128,RCX,R8,R9,R10,16,17,18,19,20,21,22,23) STORE8x8(R15, 0,RDI,R11,R12,R13, 0, 1, 2, 3, 4, 5, 6, 7) STORE8x8(R15, 64,RDI,R11,R12,R13, 8, 9,10,11,12,13,14,15) STORE8x8(R15,128,RDI,R11,R12,R13,16,17,18,19,20,21,22,23) LEA(RAX, MEM(RAX,RCX,8)) LEA(R15, MEM(R15,RDI,8)) SUB(RSI, IMM(1)) JNZ(PACK24_N_LOOP) LABEL(PACK24_N_TAIL) MOV(RSI, VAR(n)) AND(RSI, IMM(7)) TEST(RSI, RSI) JZ(PACK24_DONE) LABEL(PACK24_N_TAIL_LOOP) VMULPD(ZMM(0), ZMM(31), MEM(RAX, 0)) VMULPD(ZMM(1), ZMM(31), MEM(RAX, 64)) VMULPD(ZMM(2), ZMM(31), MEM(RAX,128)) VMOVUPD(MEM(R15, 0), ZMM(0)) VMOVUPD(MEM(R15, 64), ZMM(1)) VMOVUPD(MEM(R15,128), ZMM(2)) LEA(RAX, MEM(RAX,RCX,1)) LEA(R15, MEM(R15,RDI,1)) SUB(RSI, IMM(1)) JNZ(PACK24_N_TAIL_LOOP) JMP(PACK24_DONE) LABEL(PACK24_T) CMP(RCX, IMM(8)) JNE(PACK24_G) LEA(R8, MEM(RBX,RBX,2)) //inca*3 LEA(R9, MEM(RBX,RBX,4)) //inca*5 LEA(R10, MEM(R8 ,RBX,4)) //inca*7 LEA(R14, MEM(RAX,RBX,8)) LEA(RCX, MEM(R14,RBX,8)) SAR(RSI, IMM(3)) JZ(PACK24_T_TAIL) LABEL(PACK24_T_LOOP) LOADMUL8x8(RAX,0,RBX,R8,R9,R10, 0, 1, 2, 3, 4, 5, 6, 7) LOADMUL8x8(R14,0,RBX,R8,R9,R10, 8, 9,10,11,12,13,14,15) TRANSPOSE8x8( 0, 1, 2, 3, 4, 5, 6, 7, 16,17,18,19,20,21,22,23) STORE8x8(R15, 0,RDI,R11,R12,R13,16,17,18,19,20,21,22,23) LOADMUL8x8(RCX,0,RBX,R8,R9,R10, 0, 1, 2, 3, 4, 5, 6, 7) TRANSPOSE8x8( 8, 9,10,11,12,13,14,15, 16,17,18,19,20,21,22,23) STORE8x8(R15, 64,RDI,R11,R12,R13,16,17,18,19,20,21,22,23) TRANSPOSE8x8( 0, 1, 2, 3, 4, 5, 6, 7, 16,17,18,19,20,21,22,23) STORE8x8(R15,128,RDI,R11,R12,R13,16,17,18,19,20,21,22,23) LEA(RAX, MEM(RAX,64)) LEA(R14, MEM(R14,64)) LEA(RCX, MEM(RCX,64)) LEA(R15, MEM(R15,RDI,8)) SUB(RSI, IMM(1)) JNZ(PACK24_T_LOOP) LABEL(PACK24_T_TAIL) MOV(RSI, VAR(n)) AND(RSI, IMM(7)) TEST(RSI, RSI) JZ(PACK24_DONE) MOV(R13, IMM(1)) SHLX(R13, R13, RSI) SUB(R13, IMM(1)) KMOVW(K(1), R13D) //mask for n%8 elements LOADMUL8x8_MASK(RAX,0,RBX,R8,R9,R10, 0, 1, 2, 3, 4, 5, 6, 7,1) LOADMUL8x8_MASK(R14,0,RBX,R8,R9,R10, 8, 9,10,11,12,13,14,15,1) LOADMUL8x8_MASK(RCX,0,RBX,R8,R9,R10,16,17,18,19,20,21,22,23,1) TRANSPOSE8x8(16,17,18,19,20,21,22,23, 24,25,26,27,28,29,30,31) TRANSPOSE8x8( 8, 9,10,11,12,13,14,15, 16,17,18,19,20,21,22,23) TRANSPOSE8x8( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15) VMOVUPD(MEM(R15, 0), ZMM( 8)) VMOVUPD(MEM(R15, 64), ZMM(16)) VMOVUPD(MEM(R15, 128), ZMM(24)) SUB(RSI, IMM(1)) JZ(PACK24_DONE) VMOVUPD(MEM(R15,RDI,1, 0), ZMM( 9)) VMOVUPD(MEM(R15,RDI,1, 64), ZMM(17)) VMOVUPD(MEM(R15,RDI,1,128), ZMM(25)) SUB(RSI, IMM(1)) JZ(PACK24_DONE) VMOVUPD(MEM(R15,RDI,2, 0), ZMM(10)) VMOVUPD(MEM(R15,RDI,2, 64), ZMM(18)) VMOVUPD(MEM(R15,RDI,2,128), ZMM(26)) SUB(RSI, IMM(1)) JZ(PACK24_DONE) VMOVUPD(MEM(R15,R11,1, 0), ZMM(11)) VMOVUPD(MEM(R15,R11,1, 64), ZMM(19)) VMOVUPD(MEM(R15,R11,1,128), ZMM(27)) SUB(RSI, IMM(1)) JZ(PACK24_DONE) VMOVUPD(MEM(R15,RDI,4, 0), ZMM(12)) VMOVUPD(MEM(R15,RDI,4, 64), ZMM(20)) VMOVUPD(MEM(R15,RDI,4,128), ZMM(28)) SUB(RSI, IMM(1)) JZ(PACK24_DONE) VMOVUPD(MEM(R15,R12,1, 0), ZMM(13)) VMOVUPD(MEM(R15,R12,1, 64), ZMM(21)) VMOVUPD(MEM(R15,R12,1,128), ZMM(29)) SUB(RSI, IMM(1)) JZ(PACK24_DONE) VMOVUPD(MEM(R15,R11,2, 0), ZMM(14)) VMOVUPD(MEM(R15,R11,2, 64), ZMM(22)) VMOVUPD(MEM(R15,R11,2,128), ZMM(30)) JMP(PACK24_DONE) LABEL(PACK24_G) VPBROADCASTD(ZMM(3), VAR(inca)) MOV(RBX, VAR(offsetPtr)) VPMULLD(YMM(0), YMM(3), MEM(RBX, 0)) VPMULLD(YMM(1), YMM(3), MEM(RBX,32)) VPMULLD(YMM(2), YMM(3), MEM(RBX,64)) LABEL(PACK24_G_LOOP) KXNORW(K(1), K(0), K(0)) KXNORW(K(2), K(0), K(0)) KXNORW(K(3), K(0), K(0)) VGATHERDPD(ZMM(3) MASK_K(1), MEM(RAX,YMM(0),8)) VGATHERDPD(ZMM(4) MASK_K(2), MEM(RAX,YMM(1),8)) VGATHERDPD(ZMM(5) MASK_K(3), MEM(RAX,YMM(2),8)) VMULPD(ZMM(3), ZMM(3), ZMM(31)) VMULPD(ZMM(4), ZMM(4), ZMM(31)) VMULPD(ZMM(5), ZMM(5), ZMM(31)) VMOVUPD(MEM(R15, 0), ZMM(3)) VMOVUPD(MEM(R15, 64), ZMM(4)) VMOVUPD(MEM(R15,128), ZMM(5)) LEA(RAX, MEM(RAX,RCX,1)) LEA(R15, MEM(R15,RDI,1)) SUB(RSI, IMM(1)) JNZ(PACK24_G_LOOP) LABEL(PACK24_DONE) END_ASM( : //output operands : //input operands [n] "m" (n), [kappa] "m" (*kappa), [a] "m" (a), [inca] "m" (inca), [lda] "m" (lda), [p] "m" (p), [ldp] "m" (ldp), [offsetPtr] "m" (offsetPtr) : //clobbers "zmm0", "zmm1", "zmm2", "zmm3", "zmm4", "zmm5", "zmm6", "zmm7", "zmm8", "zmm9", "zmm10", "zmm11", "zmm12", "zmm13", "zmm14", "zmm15", "zmm16", "zmm17", "zmm18", "zmm19", "zmm20", "zmm21", "zmm22", "zmm23", "zmm24", "zmm25", "zmm26", "zmm27", "zmm28", "zmm29", "zmm30", "zmm31", "rax", "rbx", "rcx", "rdi", "rsi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "memory" ) } else // if ( cdim < mnr ) { bli_dscal2m_ex \ ( \ 0, \ BLIS_NONUNIT_DIAG, \ BLIS_DENSE, \ ( trans_t )conja, \ cdim, \ n, \ kappa, \ a, inca, lda, \ p, 1, ldp, \ cntx, \ NULL \ ); \ // if ( cdim < mnr ) { const dim_t i = cdim; const dim_t m_edge = mnr - i; const dim_t n_edge = n_max; double* restrict p_edge = p + (i )*1; bli_dset0s_mxn ( m_edge, n_edge, p_edge, 1, ldp ); } } if ( n < n_max ) { const dim_t j = n; const dim_t m_edge = mnr; const dim_t n_edge = n_max - j; double* restrict p_edge = p + (j )*ldp; bli_dset0s_mxn ( m_edge, n_edge, p_edge, 1, ldp ); } } blis-0.9.0/kernels/knl/1m/bli_spackm_knl_asm_24x16.c000066400000000000000000000502301422157504600220430ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define BLIS_ASM_SYNTAX_INTEL #include "bli_x86_asm_macros.h" #define LOADMUL8x8(a,o,s1,s3,s5,s7, \ z0,z1,z2,z3,z4,z5,z6,z7) \ \ VMULPS(YMM(z0), YMM(15), MEM(a, o)) \ VMULPS(YMM(z1), YMM(15), MEM(a,s1,1,o)) \ VMULPS(YMM(z2), YMM(15), MEM(a,s1,2,o)) \ VMULPS(YMM(z3), YMM(15), MEM(a,s3,1,o)) \ VMULPS(YMM(z4), YMM(15), MEM(a,s1,4,o)) \ VMULPS(YMM(z5), YMM(15), MEM(a,s5,1,o)) \ VMULPS(YMM(z6), YMM(15), MEM(a,s3,2,o)) \ VMULPS(YMM(z7), YMM(15), MEM(a,s7,1,o)) #define STORE8x8(a,o,s, \ z0,z1,z2,z3,z4,z5,z6,z7) \ \ VMOVUPS(MEM(a,(o)+0*(s)), YMM(z0)) \ VMOVUPS(MEM(a,(o)+1*(s)), YMM(z1)) \ VMOVUPS(MEM(a,(o)+2*(s)), YMM(z2)) \ VMOVUPS(MEM(a,(o)+3*(s)), YMM(z3)) \ VMOVUPS(MEM(a,(o)+4*(s)), YMM(z4)) \ VMOVUPS(MEM(a,(o)+5*(s)), YMM(z5)) \ VMOVUPS(MEM(a,(o)+6*(s)), YMM(z6)) \ VMOVUPS(MEM(a,(o)+7*(s)), YMM(z7)) #define STORETRANS8x8(a,o,s, \ a0,a1,a2,a3,a4,a5,a6,a7, \ t0,t1,t2,t3,t4,t5) \ \ VUNPCKLPS(YMM(t0), YMM(a0), YMM(a1)) \ VUNPCKLPS(YMM(t2), YMM(a2), YMM(a3)) \ VUNPCKLPS(YMM(t1), YMM(a4), YMM(a5)) \ VUNPCKLPS(YMM(t3), YMM(a6), YMM(a7)) \ \ VSHUFPS(YMM(t4), YMM(t0), YMM(t2), IMM(0x44)) \ VSHUFPS(YMM(t5), YMM(t1), YMM(t3), IMM(0x44)) \ VMOVUPS(MEM(a,(o )+0*(s)), XMM(t4)) \ VMOVUPS(MEM(a,(o+16)+0*(s)), XMM(t5)) \ VEXTRACTF128(MEM(a,(o )+4*(s)), YMM(t4), IMM(1)) \ VEXTRACTF128(MEM(a,(o+16)+4*(s)), YMM(t5), IMM(1)) \ \ VSHUFPS(YMM(t4), YMM(t0), YMM(t2), IMM(0xEE)) \ VSHUFPS(YMM(t5), YMM(t1), YMM(t3), IMM(0xEE)) \ VMOVUPS(MEM(a,(o )+1*(s)), XMM(t4)) \ VMOVUPS(MEM(a,(o+16)+1*(s)), XMM(t5)) \ VEXTRACTF128(MEM(a,(o )+5*(s)), YMM(t4), IMM(1)) \ VEXTRACTF128(MEM(a,(o+16)+5*(s)), YMM(t5), IMM(1)) \ \ VUNPCKHPS(YMM(t0), YMM(a0), YMM(a1)) \ VUNPCKHPS(YMM(t2), YMM(a2), YMM(a3)) \ VUNPCKHPS(YMM(t1), YMM(a4), YMM(a5)) \ VUNPCKHPS(YMM(t3), YMM(a6), YMM(a7)) \ \ VSHUFPS(YMM(t4), YMM(t0), YMM(t2), IMM(0x44)) \ VSHUFPS(YMM(t5), YMM(t1), YMM(t3), IMM(0x44)) \ VMOVUPS(MEM(a,(o )+2*(s)), XMM(t4)) \ VMOVUPS(MEM(a,(o+16)+2*(s)), XMM(t5)) \ VEXTRACTF128(MEM(a,(o )+6*(s)), YMM(t4), IMM(1)) \ VEXTRACTF128(MEM(a,(o+16)+6*(s)), YMM(t5), IMM(1)) \ \ VSHUFPS(YMM(t4), YMM(t0), YMM(t2), IMM(0xEE)) \ VSHUFPS(YMM(t5), YMM(t1), YMM(t3), IMM(0xEE)) \ VMOVUPS(MEM(a,(o )+3*(s)), XMM(t4)) \ VMOVUPS(MEM(a,(o+16)+3*(s)), XMM(t5)) \ VEXTRACTF128(MEM(a,(o )+7*(s)), YMM(t4), IMM(1)) \ VEXTRACTF128(MEM(a,(o+16)+7*(s)), YMM(t5), IMM(1)) //This is an array used for the scatter/gather instructions. static int32_t offsets[32] __attribute__((aligned(64))) = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15, 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31}; void bli_spackm_knl_asm_16xk ( conj_t conja, pack_t schema, dim_t cdim_, dim_t n_, dim_t n_max_, float* restrict kappa_, float* restrict a_, inc_t inca_, inc_t lda_, float* restrict p_, inc_t ldp_, cntx_t* restrict cntx ) { const int32_t* offsetPtr = &offsets[0]; float* a = ( float* )a_; float* p = ( float* )p_; float* kappa = ( float* )kappa_; const int64_t cdim = cdim_; const int64_t mnr = 16; const int64_t n = n_; const int64_t n_max = n_max_; const int64_t inca = inca_; const int64_t lda = lda_; const int64_t ldp = ldp_; if ( cdim == mnr ) { BEGIN_ASM() MOV(RSI, VAR(n)) MOV(RAX, VAR(a)) MOV(RBX, VAR(inca)) MOV(RCX, VAR(lda)) MOV(R14, VAR(p)) TEST(RSI, RSI) JZ(PACK16_DONE) LEA(RBX, MEM(,RBX,4)) //inca in bytes LEA(RCX, MEM(,RCX,4)) //lda in bytes VBROADCASTSS(YMM(15), VAR(kappa)) CMP(RBX, IMM(4)) JNE(PACK16_T) LABEL(PACK16_N) MOV(RDX, RSI) AND(RDX, IMM(7)) SAR(RSI, IMM(3)) JZ(PACK16_N_TAIL) LEA(R8, MEM(RCX,RCX,2)) //lda*3 LEA(R9, MEM(RCX,RCX,4)) //lda*5 LEA(R10, MEM(R8 ,RCX,4)) //lda*7 LABEL(PACK16_N_LOOP) LOADMUL8x8(RAX,0,RCX,R8,R9,R10,0,1,2,3,4,5,6,7) STORE8x8(R14,0,16*4,0,1,2,3,4,5,6,7) LOADMUL8x8(RAX,32,RCX,R8,R9,R10,0,1,2,3,4,5,6,7) STORE8x8(R14,32,16*4,0,1,2,3,4,5,6,7) LEA(RAX, MEM(RAX,RCX,8)) LEA(R14, MEM(R14,16*8*4)) SUB(RSI, IMM(1)) JNZ(PACK16_N_LOOP) TEST(RDX, RDX) JZ(PACK16_DONE) LABEL(PACK16_N_TAIL) VMULPS(YMM(0), YMM(15), MEM(RAX )) VMULPS(YMM(1), YMM(15), MEM(RAX,32)) VMOVUPS(MEM(R14 ), YMM(0)) VMOVUPS(MEM(R14,32), YMM(1)) LEA(RAX, MEM(RAX,RCX,1)) LEA(R14, MEM(R14, 16*4)) SUB(RDX, IMM(1)) JNZ(PACK16_N_TAIL) JMP(PACK16_DONE) LABEL(PACK16_T) CMP(RCX, IMM(4)) JNE(PACK16_G) LEA(R8, MEM(RBX,RBX,2)) //inca*3 LEA(R9, MEM(RBX,RBX,4)) //inca*5 LEA(R10, MEM(R8 ,RBX,4)) //inca*7 LEA(R11, MEM(RAX,RBX,8)) MOV(RDX, RSI) AND(RDX, IMM(7)) SAR(RSI, IMM(3)) JZ(PACK16_T_TAIL) LABEL(PACK16_T_LOOP) LOADMUL8x8(RAX,0,RBX,R8,R9,R10,0,1,2,3,4,5,6,7) STORETRANS8x8(R14,0,16*4,0,1,2,3,4,5,6,7,8,9,10,11,12,13) LOADMUL8x8(R11,0,RBX,R8,R9,R10,0,1,2,3,4,5,6,7) STORETRANS8x8(R14,32,16*4,0,1,2,3,4,5,6,7,8,9,10,11,12,13) LEA(RAX, MEM(RAX, 8*4)) LEA(R11, MEM(R11, 8*4)) LEA(R14, MEM(R14,16*8*4)) SUB(RSI, IMM(1)) JNZ(PACK16_T_LOOP) TEST(RDX, RDX) JZ(PACK16_DONE) LABEL(PACK16_T_TAIL) VMULSS(XMM(0), XMM(15), MEM(RAX )) VMULSS(XMM(1), XMM(15), MEM(RAX,RBX,1)) VMULSS(XMM(2), XMM(15), MEM(RAX,RBX,2)) VMULSS(XMM(3), XMM(15), MEM(RAX,R8 ,1)) VMULSS(XMM(4), XMM(15), MEM(RAX,RBX,4)) VMULSS(XMM(5), XMM(15), MEM(RAX,R9 ,1)) VMULSS(XMM(6), XMM(15), MEM(RAX,R8 ,2)) VMULSS(XMM(7), XMM(15), MEM(RAX,R10,1)) VMOVSS(MEM(R14,0*4), XMM(0)) VMOVSS(MEM(R14,1*4), XMM(1)) VMOVSS(MEM(R14,2*4), XMM(2)) VMOVSS(MEM(R14,3*4), XMM(3)) VMOVSS(MEM(R14,4*4), XMM(4)) VMOVSS(MEM(R14,5*4), XMM(5)) VMOVSS(MEM(R14,6*4), XMM(6)) VMOVSS(MEM(R14,7*4), XMM(7)) VMULSS(XMM(0), XMM(15), MEM(R11 )) VMULSS(XMM(1), XMM(15), MEM(R11,RBX,1)) VMULSS(XMM(2), XMM(15), MEM(R11,RBX,2)) VMULSS(XMM(3), XMM(15), MEM(R11,R8 ,1)) VMULSS(XMM(4), XMM(15), MEM(R11,RBX,4)) VMULSS(XMM(5), XMM(15), MEM(R11,R9 ,1)) VMULSS(XMM(6), XMM(15), MEM(R11,R8 ,2)) VMULSS(XMM(7), XMM(15), MEM(R11,R10,1)) VMOVSS(MEM(R14, 8*4), XMM(0)) VMOVSS(MEM(R14, 9*4), XMM(1)) VMOVSS(MEM(R14,10*4), XMM(2)) VMOVSS(MEM(R14,11*4), XMM(3)) VMOVSS(MEM(R14,12*4), XMM(4)) VMOVSS(MEM(R14,13*4), XMM(5)) VMOVSS(MEM(R14,14*4), XMM(6)) VMOVSS(MEM(R14,15*4), XMM(7)) LEA(RAX, MEM(RAX, 4)) LEA(R11, MEM(R11, 4)) LEA(R14, MEM(R14,16*4)) SUB(RDX, IMM(1)) JNZ(PACK16_T_TAIL) JMP(PACK16_DONE) LABEL(PACK16_G) VPBROADCASTD(ZMM(3), VAR(inca)) MOV(RBX, VAR(offsetPtr)) VPMULLD(ZMM(0), ZMM(3), MEM(RBX)) LABEL(PACK16_G_LOOP) KXNORW(K(1), K(0), K(0)) VGATHERDPS(ZMM(3) MASK_K(1), MEM(RAX,ZMM(0),8)) VMULPS(ZMM(3), ZMM(3), ZMM(15)) VMOVUPS(MEM(R14), ZMM(3)) LEA(RAX, MEM(RAX,RCX,1)) LEA(R14, MEM(R14, 16*4)) SUB(RSI, IMM(1)) JNZ(PACK16_G_LOOP) LABEL(PACK16_DONE) END_ASM( : //output operands : //input operands [n] "m" (n), [kappa] "m" (*kappa), [a] "m" (a), [inca] "m" (inca), [lda] "m" (lda), [p] "m" (p), [ldp] "m" (ldp), [offsetPtr] "m" (offsetPtr) : //clobbers "zmm0", "zmm1", "zmm2", "zmm3", "zmm4", "zmm5", "zmm6", "zmm7", "zmm8", "zmm9", "zmm10", "zmm11", "zmm12", "zmm13", "zmm14", "zmm15", "zmm16", "zmm17", "zmm18", "zmm19", "zmm20", "zmm21", "zmm22", "zmm23", "zmm24", "zmm25", "zmm26", "zmm27", "zmm28", "zmm29", "zmm30", "zmm31", "rax", "rbx", "rcx", "rdx", "rdi", "rsi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "memory" ) } else // if ( cdim < mnr ) { bli_sscal2m_ex \ ( \ 0, \ BLIS_NONUNIT_DIAG, \ BLIS_DENSE, \ ( trans_t )conja, \ cdim, \ n, \ kappa, \ a, inca, lda, \ p, 1, ldp, \ cntx, \ NULL \ ); \ // if ( cdim < mnr ) { const dim_t i = cdim; const dim_t m_edge = mnr - i; const dim_t n_edge = n_max; float* restrict p_edge = p + (i )*1; bli_sset0s_mxn ( m_edge, n_edge, p_edge, 1, ldp ); } } if ( n < n_max ) { const dim_t j = n; const dim_t m_edge = mnr; const dim_t n_edge = n_max - j; float* restrict p_edge = p + (j )*ldp; bli_sset0s_mxn ( m_edge, n_edge, p_edge, 1, ldp ); } } void bli_spackm_knl_asm_24xk ( conj_t conja, pack_t schema, dim_t cdim_, dim_t n_, dim_t n_max_, float* restrict kappa_, float* restrict a_, inc_t inca_, inc_t lda_, float* restrict p_, inc_t ldp_, cntx_t* restrict cntx ) { const int32_t* offsetPtr = &offsets[0]; float* a = ( float* )a_; float* p = ( float* )p_; float* kappa = ( float* )kappa_; const int64_t cdim = cdim_; const int64_t mnr = 24; const int64_t n = n_; const int64_t n_max = n_max_; const int64_t inca = inca_; const int64_t lda = lda_; const int64_t ldp = ldp_; if ( cdim == mnr ) { BEGIN_ASM() MOV(RSI, VAR(n)) MOV(RAX, VAR(a)) MOV(RBX, VAR(inca)) MOV(RCX, VAR(lda)) MOV(R14, VAR(p)) MOV(RDI, VAR(ldp)) TEST(RSI, RSI) JZ(PACK24_DONE) LEA(RBX, MEM(,RBX,4)) //inca in bytes LEA(RCX, MEM(,RCX,4)) //lda in bytes LEA(RDI, MEM(,RDI,4)) //ldp in bytes VBROADCASTSS(ZMM(15), VAR(kappa)) CMP(RBX, IMM(4)) JNE(PACK24_T) LABEL(PACK24_N) MOV(RDX, RSI) AND(RDX, IMM(7)) SAR(RSI, IMM(3)) JZ(PACK24_N_TAIL) LEA(R8, MEM(RCX,RCX,2)) //lda*3 LEA(R9, MEM(RCX,RCX,4)) //lda*5 LEA(R10, MEM(R8 ,RCX,4)) //lda*7 LABEL(PACK24_N_LOOP) LOADMUL8x8(RAX,0,RCX,R8,R9,R10,0,1,2,3,4,5,6,7) STORE8x8(R14,0,24*4,0,1,2,3,4,5,6,7) LOADMUL8x8(RAX,32,RCX,R8,R9,R10,0,1,2,3,4,5,6,7) STORE8x8(R14,32,24*4,0,1,2,3,4,5,6,7) LOADMUL8x8(RAX,64,RCX,R8,R9,R10,0,1,2,3,4,5,6,7) STORE8x8(R14,64,24*4,0,1,2,3,4,5,6,7) LEA(RAX, MEM(RAX,RCX,8)) LEA(R14, MEM(R14,RDI,8)) SUB(RSI, IMM(1)) JNZ(PACK24_N_LOOP) TEST(RDX, RDX) JZ(PACK24_DONE) LABEL(PACK24_N_TAIL) VMULPS(ZMM(0), ZMM(15), MEM(RAX)) VMOVUPS(MEM(R14), ZMM(0)) VMULPS(YMM(1), YMM(15), MEM(RAX,64)) VMOVUPS(MEM(R14,64), YMM(1)) LEA(RAX, MEM(RAX,RCX,1)) LEA(R14, MEM(R14,RDI,1)) SUB(RDX, IMM(1)) JNZ(PACK24_N_TAIL) JMP(PACK24_DONE) LABEL(PACK24_T) CMP(RCX, IMM(4)) JNE(PACK24_G) LEA(R8, MEM(RBX,RBX,2)) //inca*3 LEA(R9, MEM(RBX,RBX,4)) //inca*5 LEA(R10, MEM(R8 ,RBX,4)) //inca*7 LEA(R11, MEM(RAX,RBX,8)) LEA(R12, MEM(R11,RBX,8)) MOV(RDX, RSI) AND(RDX, IMM(7)) SAR(RSI, IMM(3)) JZ(PACK24_T_TAIL) LABEL(PACK24_T_LOOP) LOADMUL8x8(RAX,0,RBX,R8,R9,R10,0,1,2,3,4,5,6,7) STORETRANS8x8(R14,0,24*4,0,1,2,3,4,5,6,7,8,9,10,11,12,13) LOADMUL8x8(R11,0,RBX,R8,R9,R10,0,1,2,3,4,5,6,7) STORETRANS8x8(R14,32,24*4,0,1,2,3,4,5,6,7,8,9,10,11,12,13) LOADMUL8x8(R12,0,RBX,R8,R9,R10,0,1,2,3,4,5,6,7) STORETRANS8x8(R14,64,24*4,0,1,2,3,4,5,6,7,8,9,10,11,12,13) LEA(RAX, MEM(RAX,RCX,8)) LEA(R11, MEM(R11,RCX,8)) LEA(R12, MEM(R12,RCX,8)) LEA(R14, MEM(R14,RDI,8)) SUB(RSI, IMM(1)) JNZ(PACK24_T_LOOP) TEST(RDX, RDX) JZ(PACK24_DONE) LABEL(PACK24_T_TAIL) VMULSS(XMM(0), XMM(15), MEM(RAX)) VMULSS(XMM(1), XMM(15), MEM(RAX,RBX,1)) VMULSS(XMM(2), XMM(15), MEM(RAX,RBX,2)) VMULSS(XMM(3), XMM(15), MEM(RAX,R8,1)) VMULSS(XMM(4), XMM(15), MEM(RAX,RBX,4)) VMULSS(XMM(5), XMM(15), MEM(RAX,R9,1)) VMULSS(XMM(6), XMM(15), MEM(RAX,R8,2)) VMULSS(XMM(7), XMM(15), MEM(RAX,R10,1)) VMOVSS(MEM(R14,0*4), XMM(0)) VMOVSS(MEM(R14,1*4), XMM(1)) VMOVSS(MEM(R14,2*4), XMM(2)) VMOVSS(MEM(R14,3*4), XMM(3)) VMOVSS(MEM(R14,4*4), XMM(4)) VMOVSS(MEM(R14,5*4), XMM(5)) VMOVSS(MEM(R14,6*4), XMM(6)) VMOVSS(MEM(R14,7*4), XMM(7)) VMULSS(XMM(0), XMM(15), MEM(R11)) VMULSS(XMM(1), XMM(15), MEM(R11,RBX,1)) VMULSS(XMM(2), XMM(15), MEM(R11,RBX,2)) VMULSS(XMM(3), XMM(15), MEM(R11,R8,1)) VMULSS(XMM(4), XMM(15), MEM(R11,RBX,4)) VMULSS(XMM(5), XMM(15), MEM(R11,R9,1)) VMULSS(XMM(6), XMM(15), MEM(R11,R8,2)) VMULSS(XMM(7), XMM(15), MEM(R11,R10,1)) VMOVSS(MEM(R14, 8*4), XMM(0)) VMOVSS(MEM(R14, 9*4), XMM(1)) VMOVSS(MEM(R14,10*4), XMM(2)) VMOVSS(MEM(R14,11*4), XMM(3)) VMOVSS(MEM(R14,12*4), XMM(4)) VMOVSS(MEM(R14,13*4), XMM(5)) VMOVSS(MEM(R14,14*4), XMM(6)) VMOVSS(MEM(R14,15*4), XMM(7)) VMULSS(XMM(0), XMM(15), MEM(R12)) VMULSS(XMM(1), XMM(15), MEM(R12,RBX,1)) VMULSS(XMM(2), XMM(15), MEM(R12,RBX,2)) VMULSS(XMM(3), XMM(15), MEM(R12,R8,1)) VMULSS(XMM(4), XMM(15), MEM(R12,RBX,4)) VMULSS(XMM(5), XMM(15), MEM(R12,R9,1)) VMULSS(XMM(6), XMM(15), MEM(R12,R8,2)) VMULSS(XMM(7), XMM(15), MEM(R12,R10,1)) VMOVSS(MEM(R14,16*4), XMM(0)) VMOVSS(MEM(R14,17*4), XMM(1)) VMOVSS(MEM(R14,18*4), XMM(2)) VMOVSS(MEM(R14,19*4), XMM(3)) VMOVSS(MEM(R14,20*4), XMM(4)) VMOVSS(MEM(R14,21*4), XMM(5)) VMOVSS(MEM(R14,22*4), XMM(6)) VMOVSS(MEM(R14,23*4), XMM(7)) LEA(RAX, MEM(RAX,RCX,1)) LEA(R11, MEM(R11,RCX,1)) LEA(R12, MEM(R12,RCX,1)) LEA(R14, MEM(R14,RDI,1)) SUB(RDX, IMM(1)) JNZ(PACK24_T_TAIL) JMP(PACK24_DONE) LABEL(PACK24_G) VPBROADCASTD(ZMM(3), VAR(inca)) MOV(RBX, VAR(offsetPtr)) VPMULLD(ZMM(0), ZMM(3), MEM(RBX)) LEA(R11, MEM(RAX,RBX,8)) LEA(R11, MEM(R11,RBX,8)) LABEL(PACK24_G_LOOP) KXNORW(K(1), K(0), K(0)) KSHIFTRW(K(2), K(1), IMM(8)) VGATHERDPS(ZMM(3) MASK_K(1), MEM(RAX,ZMM(0),8)) VGATHERDPS(ZMM(4) MASK_K(2), MEM(R11,ZMM(0),8)) VMULPS(ZMM(3), ZMM(3), ZMM(15)) VMULPS(YMM(4), YMM(4), YMM(15)) VMOVUPS(MEM(R14), ZMM(3)) VMOVUPS(MEM(R14,64), YMM(4)) LEA(RAX, MEM(RAX,RCX,1)) LEA(R14, MEM(R14,RDI,1)) SUB(RSI, IMM(1)) JNZ(PACK24_G_LOOP) LABEL(PACK24_DONE) END_ASM( : //output operands : //input operands [n] "m" (n), [kappa] "m" (*kappa), [a] "m" (a), [inca] "m" (inca), [lda] "m" (lda), [p] "m" (p), [ldp] "m" (ldp), [offsetPtr] "m" (offsetPtr) : //clobbers "zmm0", "zmm1", "zmm2", "zmm3", "zmm4", "zmm5", "zmm6", "zmm7", "zmm8", "zmm9", "zmm10", "zmm11", "zmm12", "zmm13", "zmm14", "zmm15", "zmm16", "zmm17", "zmm18", "zmm19", "zmm20", "zmm21", "zmm22", "zmm23", "zmm24", "zmm25", "zmm26", "zmm27", "zmm28", "zmm29", "zmm30", "zmm31", "rax", "rbx", "rcx", "rdx", "rdi", "rsi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "memory" ) } else // if ( cdim < mnr ) { bli_sscal2m_ex \ ( \ 0, \ BLIS_NONUNIT_DIAG, \ BLIS_DENSE, \ ( trans_t )conja, \ cdim, \ n, \ kappa, \ a, inca, lda, \ p, 1, ldp, \ cntx, \ NULL \ ); \ // if ( cdim < mnr ) { const dim_t i = cdim; const dim_t m_edge = mnr - i; const dim_t n_edge = n_max; float* restrict p_edge = p + (i )*1; bli_sset0s_mxn ( m_edge, n_edge, p_edge, 1, ldp ); } } if ( n < n_max ) { const dim_t j = n; const dim_t m_edge = mnr; const dim_t n_edge = n_max - j; float* restrict p_edge = p + (j )*ldp; bli_sset0s_mxn ( m_edge, n_edge, p_edge, 1, ldp ); } } blis-0.9.0/kernels/knl/1m/old/000077500000000000000000000000001422157504600160015ustar00rootroot00000000000000blis-0.9.0/kernels/knl/1m/old/bli_packm_knl_asm_30x8.c000066400000000000000000000365131422157504600223640ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "bli_avx512_macros.h" #include "blis.h" #define LOADMUL8x8(a,o,s1,s3,s5,s7, \ z0,z1,z2,z3,z4,z5,z6,z7) \ \ VMULPD(ZMM(z0), ZMM(31), MEM(a, o)) \ VMULPD(ZMM(z1), ZMM(31), MEM(a,s1,1,o)) \ VMULPD(ZMM(z2), ZMM(31), MEM(a,s1,2,o)) \ VMULPD(ZMM(z3), ZMM(31), MEM(a,s3,1,o)) \ VMULPD(ZMM(z4), ZMM(31), MEM(a,s1,4,o)) \ VMULPD(ZMM(z5), ZMM(31), MEM(a,s5,1,o)) \ VMULPD(ZMM(z6), ZMM(31), MEM(a,s3,2,o)) \ VMULPD(ZMM(z7), ZMM(31), MEM(a,s7,1,o)) #define LOADMUL6x8(a,o,s1,s3,s5, \ z0,z1,z2,z3,z4,z5) \ \ VMULPD(ZMM(z0), ZMM(31), MEM(a, o)) \ VMULPD(ZMM(z1), ZMM(31), MEM(a,s1,1,o)) \ VMULPD(ZMM(z2), ZMM(31), MEM(a,s1,2,o)) \ VMULPD(ZMM(z3), ZMM(31), MEM(a,s3,1,o)) \ VMULPD(ZMM(z4), ZMM(31), MEM(a,s1,4,o)) \ VMULPD(ZMM(z5), ZMM(31), MEM(a,s5,1,o)) #define LOADMUL8x6(a,o,s1,s3,s5,s7, \ z0,z1,z2,z3,z4,z5,z6,z7) \ \ KXNORW(K(7), K(0), K(0)) \ KSHIFTRW(K(7), K(7), IMM(10)) \ LOADMUL8x8_MASK(a,o,s1,s3,s5,s7,z0,z1,z2,z3,z4,z5,z6,z7,7) #define LOADMUL8x8_MASK(a,o,s1,s3,s5,s7, \ z0,z1,z2,z3,z4,z5,z6,z7,k) \ \ VMULPD(ZMM(z0) MASK_KZ(k), ZMM(31), MEM(a, o)) \ VMULPD(ZMM(z1) MASK_KZ(k), ZMM(31), MEM(a,s1,1,o)) \ VMULPD(ZMM(z2) MASK_KZ(k), ZMM(31), MEM(a,s1,2,o)) \ VMULPD(ZMM(z3) MASK_KZ(k), ZMM(31), MEM(a,s3,1,o)) \ VMULPD(ZMM(z4) MASK_KZ(k), ZMM(31), MEM(a,s1,4,o)) \ VMULPD(ZMM(z5) MASK_KZ(k), ZMM(31), MEM(a,s5,1,o)) \ VMULPD(ZMM(z6) MASK_KZ(k), ZMM(31), MEM(a,s3,2,o)) \ VMULPD(ZMM(z7) MASK_KZ(k), ZMM(31), MEM(a,s7,1,o)) #define LOADMUL6x8_MASK(a,o,s1,s3,s5, \ z0,z1,z2,z3,z4,z5,k) \ \ VMULPD(ZMM(z0) MASK_KZ(k), ZMM(31), MEM(a, o)) \ VMULPD(ZMM(z1) MASK_KZ(k), ZMM(31), MEM(a,s1,1,o)) \ VMULPD(ZMM(z2) MASK_KZ(k), ZMM(31), MEM(a,s1,2,o)) \ VMULPD(ZMM(z3) MASK_KZ(k), ZMM(31), MEM(a,s3,1,o)) \ VMULPD(ZMM(z4) MASK_KZ(k), ZMM(31), MEM(a,s1,4,o)) \ VMULPD(ZMM(z5) MASK_KZ(k), ZMM(31), MEM(a,s5,1,o)) #define STORE8x8(a,o,s1,s3,s5,s7, \ z0,z1,z2,z3,z4,z5,z6,z7) \ \ VMOVUPD(MEM(a, o), ZMM(z0)) \ VMOVUPD(MEM(a,s1,1,o), ZMM(z1)) \ VMOVUPD(MEM(a,s1,2,o), ZMM(z2)) \ VMOVUPD(MEM(a,s3,1,o), ZMM(z3)) \ VMOVUPD(MEM(a,s1,4,o), ZMM(z4)) \ VMOVUPD(MEM(a,s5,1,o), ZMM(z5)) \ VMOVUPD(MEM(a,s3,2,o), ZMM(z6)) \ VMOVUPD(MEM(a,s7,1,o), ZMM(z7)) #define TRANSPOSE8x8(a0,a1,a2,a3,a4,a5,a6,a7, \ b0,b1,b2,b3,b4,b5,b6,b7) \ \ VUNPCKLPD(ZMM(b0), ZMM(a0), ZMM(a1)) \ VUNPCKHPD(ZMM(b1), ZMM(a0), ZMM(a1)) \ VUNPCKLPD(ZMM(b2), ZMM(a2), ZMM(a3)) \ VUNPCKHPD(ZMM(b3), ZMM(a2), ZMM(a3)) \ VUNPCKLPD(ZMM(b4), ZMM(a4), ZMM(a5)) \ VUNPCKHPD(ZMM(b5), ZMM(a4), ZMM(a5)) \ VUNPCKLPD(ZMM(b6), ZMM(a6), ZMM(a7)) \ VUNPCKHPD(ZMM(b7), ZMM(a6), ZMM(a7)) \ VSHUFF64X2(ZMM(a0), ZMM(b0), ZMM(b2), IMM(0x44)) \ VSHUFF64X2(ZMM(a1), ZMM(b1), ZMM(b3), IMM(0x44)) \ VSHUFF64X2(ZMM(a2), ZMM(b0), ZMM(b2), IMM(0xEE)) \ VSHUFF64X2(ZMM(a3), ZMM(b1), ZMM(b3), IMM(0xEE)) \ VSHUFF64X2(ZMM(a4), ZMM(b4), ZMM(b6), IMM(0x44)) \ VSHUFF64X2(ZMM(a5), ZMM(b5), ZMM(b7), IMM(0x44)) \ VSHUFF64X2(ZMM(a6), ZMM(b4), ZMM(b6), IMM(0xEE)) \ VSHUFF64X2(ZMM(a7), ZMM(b5), ZMM(b7), IMM(0xEE)) \ VSHUFF64X2(ZMM(b0), ZMM(a0), ZMM(a4), IMM(0x88)) \ VSHUFF64X2(ZMM(b1), ZMM(a1), ZMM(a5), IMM(0x88)) \ VSHUFF64X2(ZMM(b2), ZMM(a0), ZMM(a4), IMM(0xDD)) \ VSHUFF64X2(ZMM(b3), ZMM(a1), ZMM(a5), IMM(0xDD)) \ VSHUFF64X2(ZMM(b4), ZMM(a2), ZMM(a6), IMM(0x88)) \ VSHUFF64X2(ZMM(b5), ZMM(a3), ZMM(a7), IMM(0x88)) \ VSHUFF64X2(ZMM(b6), ZMM(a2), ZMM(a6), IMM(0xDD)) \ VSHUFF64X2(ZMM(b7), ZMM(a3), ZMM(a7), IMM(0xDD)) //This is an array used for the scatter/gather instructions. extern int32_t offsets[32]; // NOTE: assumes packdim_mr == 32 void bli_dpackm_knl_asm_30xk ( conj_t conja, dim_t n_, void* restrict kappa_, void* restrict a_, inc_t inca_, inc_t lda_, void* restrict p_, inc_t ldp_, cntx_t* restrict cntx ) { (void)conja; const int32_t * offsetPtr = &offsets[0]; double* a = (double*)a_; double* p = (double*)p_; double* kappa = (double*)kappa_; const int64_t n = n_; const int64_t inca = inca_; const int64_t lda = lda_; const int64_t ldp = ldp_; __asm__ volatile ( MOV(RSI, VAR(n)) MOV(RAX, VAR(a)) MOV(RBX, VAR(inca)) MOV(RCX, VAR(lda)) MOV(R15, VAR(p)) MOV(RDI, VAR(ldp)) LEA(RBX, MEM(,RBX,8)) //inca in bytes LEA(RCX, MEM(,RCX,8)) //lda in bytes LEA(RDI, MEM(,RDI,8)) //ldp in bytes LEA(R11, MEM(RDI,RDI,2)) //ldp*3 LEA(R12, MEM(RDI,RDI,4)) //ldp*5 LEA(R13, MEM(R11,RDI,4)) //ldp*7 VBROADCASTSD(ZMM(31), VAR(kappa)) TEST(RSI, RSI) JZ(PACK30_DONE) CMP(RBX, IMM(8)) JNE(PACK30_T) LABEL(PACK30_N) MOV(RDX, RSI) AND(RDX, IMM(7)) SAR(RSI, IMM(3)) JZ(PACK30_N_TAIL) LEA(R8, MEM(RCX,RCX,2)) //lda*3 LEA(R9, MEM(RCX,RCX,4)) //lda*5 LEA(R10, MEM(R8 ,RCX,4)) //lda*7 LABEL(PACK30_N_LOOP) LOADMUL8x8(RAX, 0,RCX,R8, R9, R10, 0, 1, 2, 3, 4, 5, 6, 7) LOADMUL8x8(RAX, 64,RCX,R8, R9, R10, 8, 9,10,11,12,13,14,15) LOADMUL8x8(RAX,128,RCX,R8, R9, R10,16,17,18,19,20,21,22,23) STORE8x8 (R15, 0,RDI,R11,R12,R13, 0, 1, 2, 3, 4, 5, 6, 7) STORE8x8 (R15, 64,RDI,R11,R12,R13, 8, 9,10,11,12,13,14,15) STORE8x8 (R15,128,RDI,R11,R12,R13,16,17,18,19,20,21,22,23) LOADMUL8x6(RAX,192,RCX,R8, R9, R10, 0, 1, 2, 3, 4, 5, 6, 7) STORE8x8 (R15,192,RDI,R11,R12,R13, 0, 1, 2, 3, 4, 5, 6, 7) LEA(RAX, MEM(RAX,RCX,8)) LEA(R15, MEM(R15,RDI,8)) SUB(RSI, IMM(1)) JNZ(PACK30_N_LOOP) TEST(RDX, RDX) JZ(PACK30_DONE) LABEL(PACK30_N_TAIL) KXNORW(K(7), K(0), K(0)) KSHIFTRW(K(7), K(7), IMM(10)) VMULPD(ZMM(0), ZMM(31), MEM(RAX, 0)) VMULPD(ZMM(1), ZMM(31), MEM(RAX, 64)) VMULPD(ZMM(2), ZMM(31), MEM(RAX,128)) VMULPD(ZMM(3) MASK_KZ(7), ZMM(31), MEM(RAX,192)) VMOVUPD(MEM(R15, 0), ZMM(0)) VMOVUPD(MEM(R15, 64), ZMM(1)) VMOVUPD(MEM(R15,128), ZMM(2)) VMOVUPD(MEM(R15,192), ZMM(3)) LEA(RAX, MEM(RAX,RCX,1)) LEA(R15, MEM(R15,RDI,1)) SUB(RDX, IMM(1)) JNZ(PACK30_N_TAIL) JMP(PACK30_DONE) LABEL(PACK30_T) CMP(RCX, IMM(8)) JNE(PACK30_G) LEA(R8, MEM(RBX,RBX,2)) //inca*3 LEA(R9, MEM(RBX,RBX,4)) //inca*5 LEA(R10, MEM(R8 ,RBX,4)) //inca*7 LEA(R14, MEM(RAX,RBX,8)) LEA(RCX, MEM(R14,RBX,8)) SAR(RSI, IMM(3)) JZ(PACK30_T_TAIL) LABEL(PACK30_T_LOOP) LOADMUL8x8(RAX,0,RBX,R8,R9,R10, 0, 1, 2, 3, 4, 5, 6, 7) LOADMUL8x8(R14,0,RBX,R8,R9,R10, 8, 9,10,11,12,13,14,15) TRANSPOSE8x8( 0, 1, 2, 3, 4, 5, 6, 7, 16,17,18,19,20,21,22,23) STORE8x8(R15, 0,RDI,R11,R12,R13,16,17,18,19,20,21,22,23) LOADMUL8x8(RCX,0,RBX,R8,R9,R10, 0, 1, 2, 3, 4, 5, 6, 7) TRANSPOSE8x8( 8, 9,10,11,12,13,14,15, 16,17,18,19,20,21,22,23) STORE8x8(R15, 64,RDI,R11,R12,R13,16,17,18,19,20,21,22,23) LEA(RCX, MEM(RCX,RBX,8)) LOADMUL6x8(RCX,0,RBX,R8,R9, 8, 9,10,11,12,13) TRANSPOSE8x8( 0, 1, 2, 3, 4, 5, 6, 7, 16,17,18,19,20,21,22,23) STORE8x8(R15,128,RDI,R11,R12,R13,16,17,18,19,20,21,22,23) TRANSPOSE8x8( 8, 9,10,11,12,13,14,15, 0, 1, 2, 3, 4, 5, 6, 7) STORE8x8(R15,192,RDI,R11,R12,R13, 0, 1, 2, 3, 4, 5, 6, 7) LEA(RAX, MEM(RAX,64)) LEA(R14, MEM(R14,64)) LEA(RCX, MEM(R14,RBX,8)) LEA(R15, MEM(R15,RDI,8)) SUB(RSI, IMM(1)) JNZ(PACK30_T_LOOP) LABEL(PACK30_T_TAIL) MOV(RSI, VAR(n)) AND(RSI, IMM(7)) TEST(RSI, RSI) JZ(PACK30_DONE) MOV(R13, IMM(1)) SHLX(R13, R13, RSI) SUB(R13, IMM(1)) KMOV(K(1), R13D) //mask for n%8 elements LOADMUL8x8_MASK(RAX,0,RBX,R8,R9,R10, 0, 1, 2, 3, 4, 5, 6, 7,1) LOADMUL8x8_MASK(R14,0,RBX,R8,R9,R10, 8, 9,10,11,12,13,14,15,1) LOADMUL8x8_MASK(RCX,0,RBX,R8,R9,R10,16,17,18,19,20,21,22,23,1) TRANSPOSE8x8(16,17,18,19,20,21,22,23, 24,25,26,27,28,29,30,31) TRANSPOSE8x8( 8, 9,10,11,12,13,14,15, 16,17,18,19,20,21,22,23) TRANSPOSE8x8( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15) VMOVUPD(MEM(R15, 0), ZMM( 8)) VMOVUPD(MEM(R15, 64), ZMM(16)) VMOVUPD(MEM(R15, 128), ZMM(24)) SUB(RSI, IMM(1)) JZ(PACK30_T_ALMOST_DONE) VMOVUPD(MEM(R15,RDI,1, 0), ZMM( 9)) VMOVUPD(MEM(R15,RDI,1, 64), ZMM(17)) VMOVUPD(MEM(R15,RDI,1,128), ZMM(25)) SUB(RSI, IMM(1)) JZ(PACK30_T_ALMOST_DONE) VMOVUPD(MEM(R15,RDI,2, 0), ZMM(10)) VMOVUPD(MEM(R15,RDI,2, 64), ZMM(18)) VMOVUPD(MEM(R15,RDI,2,128), ZMM(26)) SUB(RSI, IMM(1)) JZ(PACK30_T_ALMOST_DONE) VMOVUPD(MEM(R15,R11,1, 0), ZMM(11)) VMOVUPD(MEM(R15,R11,1, 64), ZMM(19)) VMOVUPD(MEM(R15,R11,1,128), ZMM(27)) SUB(RSI, IMM(1)) JZ(PACK30_T_ALMOST_DONE) VMOVUPD(MEM(R15,RDI,4, 0), ZMM(12)) VMOVUPD(MEM(R15,RDI,4, 64), ZMM(20)) VMOVUPD(MEM(R15,RDI,4,128), ZMM(28)) SUB(RSI, IMM(1)) JZ(PACK30_T_ALMOST_DONE) VMOVUPD(MEM(R15,R12,1, 0), ZMM(13)) VMOVUPD(MEM(R15,R12,1, 64), ZMM(21)) VMOVUPD(MEM(R15,R12,1,128), ZMM(29)) SUB(RSI, IMM(1)) JZ(PACK30_T_ALMOST_DONE) VMOVUPD(MEM(R15,R11,2, 0), ZMM(14)) VMOVUPD(MEM(R15,R11,2, 64), ZMM(22)) VMOVUPD(MEM(R15,R11,2,128), ZMM(30)) LABEL(PACK30_T_ALMOST_DONE) MOV(RSI, VAR(n)) AND(RSI, IMM(7)) VBROADCASTSD(ZMM(31), VAR(kappa)) LEA(RAX, MEM(RCX,RBX,8)) LOADMUL6x8_MASK(RAX,0,RBX,R8,R9, 0, 1, 2, 3, 4, 5,1) TRANSPOSE8x8( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15) VMOVUPD(MEM(R15, 192), ZMM( 8)) SUB(RSI, IMM(1)) JZ(PACK30_DONE) VMOVUPD(MEM(R15,RDI,1,192), ZMM( 9)) SUB(RSI, IMM(1)) JZ(PACK30_DONE) VMOVUPD(MEM(R15,RDI,2,192), ZMM(10)) SUB(RSI, IMM(1)) JZ(PACK30_DONE) VMOVUPD(MEM(R15,R11,1,192), ZMM(11)) SUB(RSI, IMM(1)) JZ(PACK30_DONE) VMOVUPD(MEM(R15,RDI,4,192), ZMM(12)) SUB(RSI, IMM(1)) JZ(PACK30_DONE) VMOVUPD(MEM(R15,R12,1,192), ZMM(13)) SUB(RSI, IMM(1)) JZ(PACK30_DONE) VMOVUPD(MEM(R15,R11,2,192), ZMM(14)) JMP(PACK30_DONE) LABEL(PACK30_G) VPBROADCASTD(ZMM(4), VAR(inca)) MOV(RBX, VAR(offsetPtr)) VPMULLD(YMM(0), YMM(4), MEM(RBX, 0)) VPMULLD(YMM(1), YMM(4), MEM(RBX,32)) VPMULLD(YMM(2), YMM(4), MEM(RBX,64)) VPMULLD(YMM(3), YMM(4), MEM(RBX,96)) LABEL(PACK30_G_LOOP) KXNORW(K(1), K(0), K(0)) KXNORW(K(2), K(0), K(0)) KXNORW(K(3), K(0), K(0)) KSHIFTRW(K(4), K(3), IMM(10)) VGATHERDPD(ZMM(4) MASK_K(1), MEM(RAX,YMM(0),8)) VGATHERDPD(ZMM(5) MASK_K(2), MEM(RAX,YMM(1),8)) VGATHERDPD(ZMM(6) MASK_K(3), MEM(RAX,YMM(2),8)) VGATHERDPD(ZMM(7) MASK_K(4), MEM(RAX,YMM(3),8)) VMULPD(ZMM(4), ZMM(4), ZMM(31)) VMULPD(ZMM(5), ZMM(5), ZMM(31)) VMULPD(ZMM(6), ZMM(6), ZMM(31)) VMULPD(ZMM(7), ZMM(7), ZMM(31)) VMOVUPD(MEM(R15, 0), ZMM(4)) VMOVUPD(MEM(R15, 64), ZMM(5)) VMOVUPD(MEM(R15,128), ZMM(6)) VMOVUPD(MEM(R15,192), ZMM(7)) LEA(RAX, MEM(RAX,RCX,1)) LEA(R15, MEM(R15,RDI,1)) SUB(RSI, IMM(1)) JNZ(PACK30_G_LOOP) LABEL(PACK30_DONE) : //output operands : //input operands [n] "m" (n), [kappa] "m" (*kappa), [a] "m" (a), [inca] "m" (inca), [lda] "m" (lda), [p] "m" (p), [ldp] "m" (ldp), [offsetPtr] "m" (offsetPtr) : //clobbers "zmm0", "zmm1", "zmm2", "zmm3", "zmm4", "zmm5", "zmm6", "zmm7", "zmm8", "zmm9", "zmm10", "zmm11", "zmm12", "zmm13", "zmm14", "zmm15", "zmm16", "zmm17", "zmm18", "zmm19", "zmm20", "zmm21", "zmm22", "zmm23", "zmm24", "zmm25", "zmm26", "zmm27", "zmm28", "zmm29", "zmm30", "zmm31", "rax", "rbx", "rcx", "rdi", "rsi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "memory" ); } blis-0.9.0/kernels/knl/3/000077500000000000000000000000001422157504600150505ustar00rootroot00000000000000blis-0.9.0/kernels/knl/3/bli_dgemm_knl_asm_24x8.c000066400000000000000000000461621422157504600214350ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 UNIVERSITY OF TEXAS 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. */ #include "blis.h" #include #define BLIS_ASM_SYNTAX_INTEL #include "bli_x86_asm_macros.h" #define UNROLL_K 32 #define SCATTER_PREFETCH_C 1 #define PREFETCH_A_L2 0 #define PREFETCH_B_L2 0 #define L2_PREFETCH_DIST 64 #define A_L1_PREFETCH_DIST 18 #define B_L1_PREFETCH_DIST 18 #define LOOP_ALIGN ALIGN16 #define UPDATE_C_FOUR_ROWS(R1,R2,R3,R4) \ \ VMULPD(ZMM(R1), ZMM(R1), ZMM(0)) \ VMULPD(ZMM(R2), ZMM(R2), ZMM(0)) \ VMULPD(ZMM(R3), ZMM(R3), ZMM(0)) \ VMULPD(ZMM(R4), ZMM(R4), ZMM(0)) \ VFMADD231PD(ZMM(R1), ZMM(1), MEM(RCX )) \ VFMADD231PD(ZMM(R2), ZMM(1), MEM(RCX,RAX,1)) \ VFMADD231PD(ZMM(R3), ZMM(1), MEM(RCX,RAX,2)) \ VFMADD231PD(ZMM(R4), ZMM(1), MEM(RCX,RDI,1)) \ VMOVUPD(MEM(RCX ), ZMM(R1)) \ VMOVUPD(MEM(RCX,RAX,1), ZMM(R2)) \ VMOVUPD(MEM(RCX,RAX,2), ZMM(R3)) \ VMOVUPD(MEM(RCX,RDI,1), ZMM(R4)) \ LEA(RCX, MEM(RCX,RAX,4)) #define UPDATE_C_BZ_FOUR_ROWS(R1,R2,R3,R4) \ \ VMULPD(ZMM(R1), ZMM(R1), ZMM(0)) \ VMULPD(ZMM(R2), ZMM(R2), ZMM(0)) \ VMULPD(ZMM(R3), ZMM(R3), ZMM(0)) \ VMULPD(ZMM(R4), ZMM(R4), ZMM(0)) \ VMOVUPD(MEM(RCX ), ZMM(R1)) \ VMOVUPD(MEM(RCX,RAX,1), ZMM(R2)) \ VMOVUPD(MEM(RCX,RAX,2), ZMM(R3)) \ VMOVUPD(MEM(RCX,RDI,1), ZMM(R4)) \ LEA(RCX, MEM(RCX,RAX,4)) #define UPDATE_C_ROW_SCATTERED(NUM) \ \ KXNORW(K(1), K(0), K(0)) \ KXNORW(K(2), K(0), K(0)) \ VMULPD(ZMM(NUM), ZMM(NUM), ZMM(0)) \ VGATHERDPD(ZMM(3) MASK_K(1), MEM(RCX,YMM(2),8)) \ VFMADD231PD(ZMM(NUM), ZMM(3), ZMM(1)) \ VSCATTERDPD(MEM(RCX,YMM(2),8) MASK_K(2), ZMM(NUM)) \ ADD(RCX, RAX) #define UPDATE_C_BZ_ROW_SCATTERED(NUM) \ \ KXNORW(K(1), K(0), K(0)) \ VMULPD(ZMM(NUM), ZMM(NUM), ZMM(0)) \ VSCATTERDPD(MEM(RCX,YMM(2),8) MASK_K(1), ZMM(NUM)) \ ADD(RCX, RAX) #define PREFETCH_A_L1_1(n) PREFETCH(0, MEM(RAX,(A_L1_PREFETCH_DIST+n)*24*8)) #define PREFETCH_A_L1_2(n) PREFETCH(0, MEM(RAX,(A_L1_PREFETCH_DIST+n)*24*8+64)) #define PREFETCH_A_L1_3(n) PREFETCH(0, MEM(RAX,(A_L1_PREFETCH_DIST+n)*24*8+128)) #if PREFETCH_A_L2 #undef PREFETCH_A_L2 #define PREFETCH_A_L2(n) \ \ PREFETCH(1, MEM(RAX,(L2_PREFETCH_DIST+n)*24*8)) \ PREFETCH(1, MEM(RAX,(L2_PREFETCH_DIST+n)*24*8+64)) \ PREFETCH(1, MEM(RAX,(L2_PREFETCH_DIST+n)*24*8+128)) #else #undef PREFETCH_A_L2 #define PREFETCH_A_L2(...) #endif #define PREFETCH_B_L1(n) PREFETCH(0, MEM(RBX,(B_L1_PREFETCH_DIST+n)*8*8)) #if PREFETCH_B_L2 #undef PREFETCH_B_L2 #define PREFETCH_B_L2(n) PREFETCH(1, MEM(RBX,(L2_PREFETCH_DIST+n)*8*8)) #else #undef PREFETCH_B_L2 #define PREFETCH_B_L2(...) #endif #define PREFETCH_C_L1_1 #define PREFETCH_C_L1_2 #define PREFETCH_C_L1_3 // // n: index in unrolled loop // // a: ZMM register to load into // b: ZMM register to read from // // ...: addressing for A, except for offset // #define SUBITER(n,a,b,...) \ \ PREFETCH_A_L2(n) \ \ VMOVAPD(ZMM(a), MEM(RBX,(n+1)*64)) \ VFMADD231PD(ZMM( 8), ZMM(b), MEM_1TO8(__VA_ARGS__,((n%%4)*24+ 0)*8)) \ VFMADD231PD(ZMM( 9), ZMM(b), MEM_1TO8(__VA_ARGS__,((n%%4)*24+ 1)*8)) \ VFMADD231PD(ZMM(10), ZMM(b), MEM_1TO8(__VA_ARGS__,((n%%4)*24+ 2)*8)) \ PREFETCH_A_L1_1(n) \ VFMADD231PD(ZMM(11), ZMM(b), MEM_1TO8(__VA_ARGS__,((n%%4)*24+ 3)*8)) \ VFMADD231PD(ZMM(12), ZMM(b), MEM_1TO8(__VA_ARGS__,((n%%4)*24+ 4)*8)) \ VFMADD231PD(ZMM(13), ZMM(b), MEM_1TO8(__VA_ARGS__,((n%%4)*24+ 5)*8)) \ PREFETCH_C_L1_1 \ VFMADD231PD(ZMM(14), ZMM(b), MEM_1TO8(__VA_ARGS__,((n%%4)*24+ 6)*8)) \ VFMADD231PD(ZMM(15), ZMM(b), MEM_1TO8(__VA_ARGS__,((n%%4)*24+ 7)*8)) \ VFMADD231PD(ZMM(16), ZMM(b), MEM_1TO8(__VA_ARGS__,((n%%4)*24+ 8)*8)) \ PREFETCH_A_L1_2(n) \ VFMADD231PD(ZMM(17), ZMM(b), MEM_1TO8(__VA_ARGS__,((n%%4)*24+ 9)*8)) \ VFMADD231PD(ZMM(18), ZMM(b), MEM_1TO8(__VA_ARGS__,((n%%4)*24+10)*8)) \ VFMADD231PD(ZMM(19), ZMM(b), MEM_1TO8(__VA_ARGS__,((n%%4)*24+11)*8)) \ PREFETCH_C_L1_2 \ VFMADD231PD(ZMM(20), ZMM(b), MEM_1TO8(__VA_ARGS__,((n%%4)*24+12)*8)) \ VFMADD231PD(ZMM(21), ZMM(b), MEM_1TO8(__VA_ARGS__,((n%%4)*24+13)*8)) \ VFMADD231PD(ZMM(22), ZMM(b), MEM_1TO8(__VA_ARGS__,((n%%4)*24+14)*8)) \ PREFETCH_A_L1_3(n) \ VFMADD231PD(ZMM(23), ZMM(b), MEM_1TO8(__VA_ARGS__,((n%%4)*24+15)*8)) \ VFMADD231PD(ZMM(24), ZMM(b), MEM_1TO8(__VA_ARGS__,((n%%4)*24+16)*8)) \ VFMADD231PD(ZMM(25), ZMM(b), MEM_1TO8(__VA_ARGS__,((n%%4)*24+17)*8)) \ PREFETCH_C_L1_3 \ VFMADD231PD(ZMM(26), ZMM(b), MEM_1TO8(__VA_ARGS__,((n%%4)*24+18)*8)) \ VFMADD231PD(ZMM(27), ZMM(b), MEM_1TO8(__VA_ARGS__,((n%%4)*24+19)*8)) \ VFMADD231PD(ZMM(28), ZMM(b), MEM_1TO8(__VA_ARGS__,((n%%4)*24+20)*8)) \ PREFETCH_B_L1(n) \ VFMADD231PD(ZMM(29), ZMM(b), MEM_1TO8(__VA_ARGS__,((n%%4)*24+21)*8)) \ VFMADD231PD(ZMM(30), ZMM(b), MEM_1TO8(__VA_ARGS__,((n%%4)*24+22)*8)) \ VFMADD231PD(ZMM(31), ZMM(b), MEM_1TO8(__VA_ARGS__,((n%%4)*24+23)*8)) \ PREFETCH_B_L2(n) //This is an array used for the scatter/gather instructions. static int32_t offsets[32] __attribute__((aligned(64))) = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15, 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31}; //#define MONITORS //#define LOOPMON void bli_dgemm_knl_asm_24x8 ( dim_t m, dim_t n, dim_t k_, double* restrict alpha, double* restrict a, double* restrict b, double* restrict beta, double* restrict c, inc_t rs_c_, inc_t cs_c_, auxinfo_t* restrict data, cntx_t* restrict cntx ) { (void)data; (void)cntx; const double * a_next = bli_auxinfo_next_a( data ); const double * b_next = bli_auxinfo_next_b( data ); int32_t * offsetPtr = &offsets[0]; int64_t k = k_; int64_t rs_c = rs_c_; int64_t cs_c = cs_c_; GEMM_UKR_SETUP_CT( d, 24, 8, true ); #ifdef MONITORS int toph, topl, both, botl, midl, midh, mid2l, mid2h; #endif #ifdef LOOPMON int tlooph, tloopl, blooph, bloopl; #endif BEGIN_ASM() #ifdef MONITORS RDTSC MOV(VAR(topl), EAX) MOV(VAR(toph), EDX) #endif VPXORD(ZMM(8), ZMM(8), ZMM(8)) //clear out registers VMOVAPS(ZMM( 9), ZMM(8)) MOV(R12, VAR(rs_c)) VMOVAPS(ZMM(10), ZMM(8)) MOV(RSI, VAR(k)) //loop index VMOVAPS(ZMM(11), ZMM(8)) MOV(RAX, VAR(a)) //load address of a VMOVAPS(ZMM(12), ZMM(8)) MOV(RBX, VAR(b)) //load address of b VMOVAPS(ZMM(13), ZMM(8)) MOV(RCX, VAR(c)) //load address of c VMOVAPS(ZMM(14), ZMM(8)) VMOVAPD(ZMM(0), MEM(RBX)) //pre-load b VMOVAPS(ZMM(15), ZMM(8)) MOV(RDI, VAR(offsetPtr)) VMOVAPS(ZMM(16), ZMM(8)) VMOVAPS(ZMM(4), MEM(RDI)) #if SCATTER_PREFETCH_C VMOVAPS(ZMM(17), ZMM(8)) VMOVAPS(ZMM(18), ZMM(8)) VMOVAPS(ZMM(19), ZMM(8)) VBROADCASTSS(ZMM(5), VAR(rs_c)) VMOVAPS(ZMM(20), ZMM(8)) VMOVAPS(ZMM(21), ZMM(8)) VPMULLD(ZMM(2), ZMM(4), ZMM(5)) VMOVAPS(ZMM(22), ZMM(8)) VMOVAPS(YMM(3), MEM(RDI,64)) VMOVAPS(ZMM(23), ZMM(8)) VPMULLD(YMM(3), YMM(3), YMM(5)) #else VMOVAPS(ZMM(17), ZMM(8)) VMOVAPS(ZMM(18), ZMM(8)) LEA(R13, MEM(R12,R12,2)) VMOVAPS(ZMM(19), ZMM(8)) LEA(R14, MEM(R12,R12,4)) VMOVAPS(ZMM(20), ZMM(8)) LEA(R15, MEM(R13,R12,4)) VMOVAPS(ZMM(21), ZMM(8)) VMOVAPS(ZMM(22), ZMM(8)) VMOVAPS(ZMM(23), ZMM(8)) #endif VMOVAPS(ZMM(24), ZMM(8)) VPSLLD(ZMM(4), ZMM(4), IMM(3)) VMOVAPS(ZMM(25), ZMM(8)) MOV(R8, IMM(4*24*8)) //offset for 4 iterations VMOVAPS(ZMM(26), ZMM(8)) LEA(R9, MEM(R8,R8,2)) //*3 VMOVAPS(ZMM(27), ZMM(8)) LEA(R10, MEM(R8,R8,4)) //*5 VMOVAPS(ZMM(28), ZMM(8)) LEA(R11, MEM(R9,R8,4)) //*7 VMOVAPS(ZMM(29), ZMM(8)) VMOVAPS(ZMM(30), ZMM(8)) VMOVAPS(ZMM(31), ZMM(8)) #ifdef MONITORS RDTSC MOV(VAR(midl), EAX) MOV(VAR(midh), EDX) #endif SUB(RSI, IMM(32)) JLE(TAIL) //prefetch C into L2 #if SCATTER_PREFETCH_C ADD(RSI, IMM(24)) KXNORW(K(1), K(0), K(0)) KXNORW(K(2), K(0), K(0)) VSCATTERPFDPS(1, MEM(RCX,ZMM(2),8) MASK_K(1)) VSCATTERPFDPD(1, MEM(RCX,YMM(3),8) MASK_K(2)) #else PREFETCHW1(MEM(RCX )) SUBITER( 0,1,0,RAX ) PREFETCHW1(MEM(RCX,R12,1)) SUBITER( 1,0,1,RAX ) PREFETCHW1(MEM(RCX,R12,2)) SUBITER( 2,1,0,RAX ) PREFETCHW1(MEM(RCX,R13,1)) SUBITER( 3,0,1,RAX ) PREFETCHW1(MEM(RCX,R12,4)) SUBITER( 4,1,0,RAX,R8, 1) PREFETCHW1(MEM(RCX,R14,1)) SUBITER( 5,0,1,RAX,R8, 1) PREFETCHW1(MEM(RCX,R13,2)) SUBITER( 6,1,0,RAX,R8, 1) PREFETCHW1(MEM(RCX,R15,1)) SUBITER( 7,0,1,RAX,R8, 1) LEA(RDX, MEM(RCX,R12,8)) PREFETCHW1(MEM(RDX )) SUBITER( 8,1,0,RAX,R8, 2) PREFETCHW1(MEM(RDX,R12,1)) SUBITER( 9,0,1,RAX,R8, 2) PREFETCHW1(MEM(RDX,R12,2)) SUBITER(10,1,0,RAX,R8, 2) PREFETCHW1(MEM(RDX,R13,1)) SUBITER(11,0,1,RAX,R8, 2) PREFETCHW1(MEM(RDX,R12,4)) SUBITER(12,1,0,RAX,R9, 1) PREFETCHW1(MEM(RDX,R14,1)) SUBITER(13,0,1,RAX,R9, 1) PREFETCHW1(MEM(RDX,R13,2)) SUBITER(14,1,0,RAX,R9, 1) PREFETCHW1(MEM(RDX,R15,1)) SUBITER(15,0,1,RAX,R9, 1) LEA(RDI, MEM(RDX,R12,8)) PREFETCHW1(MEM(RDI )) SUBITER(16,1,0,RAX,R8, 4) PREFETCHW1(MEM(RDI,R12,1)) SUBITER(17,0,1,RAX,R8, 4) PREFETCHW1(MEM(RDI,R12,2)) SUBITER(18,1,0,RAX,R8, 4) PREFETCHW1(MEM(RDI,R13,1)) SUBITER(19,0,1,RAX,R8, 4) PREFETCHW1(MEM(RDI,R12,4)) SUBITER(20,1,0,RAX,R10,1) PREFETCHW1(MEM(RDI,R14,1)) SUBITER(21,0,1,RAX,R10,1) PREFETCHW1(MEM(RDI,R13,2)) SUBITER(22,1,0,RAX,R10,1) PREFETCHW1(MEM(RDI,R15,1)) SUBITER(23,0,1,RAX,R10,1) ADD(RAX, IMM(24*24*8)) ADD(RBX, IMM(24* 8*8)) #endif MOV(RDI, RSI) AND(RDI, IMM(31)) SAR(RSI, IMM(5)) JZ(REM_1) LOOP_ALIGN LABEL(MAIN_LOOP) SUBITER( 0,1,0,RAX ) SUBITER( 1,0,1,RAX ) SUBITER( 2,1,0,RAX ) SUBITER( 3,0,1,RAX ) SUBITER( 4,1,0,RAX,R8, 1) SUBITER( 5,0,1,RAX,R8, 1) SUBITER( 6,1,0,RAX,R8, 1) SUBITER( 7,0,1,RAX,R8, 1) SUBITER( 8,1,0,RAX,R8, 2) SUBITER( 9,0,1,RAX,R8, 2) SUBITER(10,1,0,RAX,R8, 2) SUBITER(11,0,1,RAX,R8, 2) SUBITER(12,1,0,RAX,R9, 1) SUBITER(13,0,1,RAX,R9, 1) SUBITER(14,1,0,RAX,R9, 1) SUBITER(15,0,1,RAX,R9, 1) SUBITER(16,1,0,RAX,R8, 4) SUBITER(17,0,1,RAX,R8, 4) SUBITER(18,1,0,RAX,R8, 4) SUBITER(19,0,1,RAX,R8, 4) SUBITER(20,1,0,RAX,R10,1) SUBITER(21,0,1,RAX,R10,1) SUBITER(22,1,0,RAX,R10,1) SUBITER(23,0,1,RAX,R10,1) SUBITER(24,1,0,RAX,R9, 2) SUBITER(25,0,1,RAX,R9, 2) SUBITER(26,1,0,RAX,R9, 2) SUBITER(27,0,1,RAX,R9, 2) SUBITER(28,1,0,RAX,R11,1) SUBITER(29,0,1,RAX,R11,1) SUBITER(30,1,0,RAX,R11,1) SUBITER(31,0,1,RAX,R11,1) ADD(RAX, IMM(32*24*8)) ADD(RBX, IMM(32* 8*8)) SUB(RSI, IMM(1)) JNZ(MAIN_LOOP) LABEL(REM_1) SAR(RDI) JNC(REM_2) SUBITER(0,1,0,RAX) VMOVAPD(ZMM(0), ZMM(1)) ADD(RAX, IMM(24*8)) ADD(RBX, IMM( 8*8)) LABEL(REM_2) SAR(RDI) JNC(REM_4) SUBITER(0,1,0,RAX) SUBITER(1,0,1,RAX) ADD(RAX, IMM(2*24*8)) ADD(RBX, IMM(2* 8*8)) LABEL(REM_4) SAR(RDI) JNC(REM_8) SUBITER(0,1,0,RAX) SUBITER(1,0,1,RAX) SUBITER(2,1,0,RAX) SUBITER(3,0,1,RAX) ADD(RAX, IMM(4*24*8)) ADD(RBX, IMM(4* 8*8)) LABEL(REM_8) SAR(RDI) JNC(REM_16) SUBITER(0,1,0,RAX ) SUBITER(1,0,1,RAX ) SUBITER(2,1,0,RAX ) SUBITER(3,0,1,RAX ) SUBITER(4,1,0,RAX,R8,1) SUBITER(5,0,1,RAX,R8,1) SUBITER(6,1,0,RAX,R8,1) SUBITER(7,0,1,RAX,R8,1) ADD(RAX, IMM(8*24*8)) ADD(RBX, IMM(8* 8*8)) LABEL(REM_16) SAR(RDI) JNC(AFTER_LOOP) SUBITER( 0,1,0,RAX ) SUBITER( 1,0,1,RAX ) SUBITER( 2,1,0,RAX ) SUBITER( 3,0,1,RAX ) SUBITER( 4,1,0,RAX,R8, 1) SUBITER( 5,0,1,RAX,R8, 1) SUBITER( 6,1,0,RAX,R8, 1) SUBITER( 7,0,1,RAX,R8, 1) SUBITER( 8,1,0,RAX,R8, 2) SUBITER( 9,0,1,RAX,R8, 2) SUBITER(10,1,0,RAX,R8, 2) SUBITER(11,0,1,RAX,R8, 2) SUBITER(12,1,0,RAX,R9, 1) SUBITER(13,0,1,RAX,R9, 1) SUBITER(14,1,0,RAX,R9, 1) SUBITER(15,0,1,RAX,R9, 1) ADD(RAX, IMM(16*24*8)) ADD(RBX, IMM(16* 8*8)) LABEL(AFTER_LOOP) //prefetch C into L1 #if SCATTER_PREFETCH_C KXNORW(K(1), K(0), K(0)) KXNORW(K(2), K(0), K(0)) VSCATTERPFDPS(0, MEM(RCX,ZMM(2),8) MASK_K(1)) VSCATTERPFDPD(0, MEM(RCX,YMM(3),8) MASK_K(2)) SUBITER(0,1,0,RAX ) SUBITER(1,0,1,RAX ) SUBITER(2,1,0,RAX ) SUBITER(3,0,1,RAX ) SUBITER(4,1,0,RAX,R8,1) SUBITER(5,0,1,RAX,R8,1) SUBITER(6,1,0,RAX,R8,1) SUBITER(7,0,1,RAX,R8,1) #else LEA(RDX, MEM(RCX,R12,8)) LEA(RDI, MEM(RDX,R12,8)) #undef PREFETCH_C_L1_1 #undef PREFETCH_C_L1_2 #undef PREFETCH_C_L1_3 #define PREFETCH_C_L1_1 PREFETCHW0(MEM(RCX )) #define PREFETCH_C_L1_2 PREFETCHW0(MEM(RCX,R12,1)) #define PREFETCH_C_L1_3 PREFETCHW0(MEM(RCX,R12,2)) SUBITER(0,1,0,RAX ) #undef PREFETCH_C_L1_1 #undef PREFETCH_C_L1_2 #undef PREFETCH_C_L1_3 #define PREFETCH_C_L1_1 PREFETCHW0(MEM(RCX,R13,1)) #define PREFETCH_C_L1_2 PREFETCHW0(MEM(RCX,R12,4)) #define PREFETCH_C_L1_3 PREFETCHW0(MEM(RCX,R14,1)) SUBITER(1,0,1,RAX ) #undef PREFETCH_C_L1_1 #undef PREFETCH_C_L1_2 #undef PREFETCH_C_L1_3 #define PREFETCH_C_L1_1 PREFETCHW0(MEM(RCX,R13,2)) #define PREFETCH_C_L1_2 PREFETCHW0(MEM(RCX,R15,1)) #define PREFETCH_C_L1_3 PREFETCHW0(MEM(RDX )) SUBITER(2,1,0,RAX ) #undef PREFETCH_C_L1_1 #undef PREFETCH_C_L1_2 #undef PREFETCH_C_L1_3 #define PREFETCH_C_L1_1 PREFETCHW0(MEM(RDX,R12,1)) #define PREFETCH_C_L1_2 PREFETCHW0(MEM(RDX,R12,2)) #define PREFETCH_C_L1_3 PREFETCHW0(MEM(RDX,R13,1)) SUBITER(3,0,1,RAX ) #undef PREFETCH_C_L1_1 #undef PREFETCH_C_L1_2 #undef PREFETCH_C_L1_3 #define PREFETCH_C_L1_1 PREFETCHW0(MEM(RDX,R12,4)) #define PREFETCH_C_L1_2 PREFETCHW0(MEM(RDX,R14,1)) #define PREFETCH_C_L1_3 PREFETCHW0(MEM(RDX,R13,2)) SUBITER(4,1,0,RAX,R8,1) #undef PREFETCH_C_L1_1 #undef PREFETCH_C_L1_2 #undef PREFETCH_C_L1_3 #define PREFETCH_C_L1_1 PREFETCHW0(MEM(RDX,R15,1)) #define PREFETCH_C_L1_2 PREFETCHW0(MEM(RDI )) #define PREFETCH_C_L1_3 PREFETCHW0(MEM(RDI,R12,1)) SUBITER(5,0,1,RAX,R8,1) #undef PREFETCH_C_L1_1 #undef PREFETCH_C_L1_2 #undef PREFETCH_C_L1_3 #define PREFETCH_C_L1_1 PREFETCHW0(MEM(RDI,R12,2)) #define PREFETCH_C_L1_2 PREFETCHW0(MEM(RDI,R13,1)) #define PREFETCH_C_L1_3 PREFETCHW0(MEM(RDI,R12,4)) SUBITER(6,1,0,RAX,R8,1) #undef PREFETCH_C_L1_1 #undef PREFETCH_C_L1_2 #undef PREFETCH_C_L1_3 #define PREFETCH_C_L1_1 PREFETCHW0(MEM(RDI,R14,1)) #define PREFETCH_C_L1_2 PREFETCHW0(MEM(RDI,R13,2)) #define PREFETCH_C_L1_3 PREFETCHW0(MEM(RDI,R15,1)) SUBITER(7,0,1,RAX,R8,1) #endif JMP(POSTACCUM) LABEL(TAIL) MOV(RDX, RCX) ADD(RSI, IMM(32)) JZ(POSTACCUM) LABEL(TAIL_LOOP) PREFETCHW0(MEM(RDX)) ADD(RDX, R12) SUBITER(0,1,0,RAX) VMOVAPD(ZMM(0), ZMM(1)) ADD(RAX, IMM(24*8)) ADD(RBX, IMM( 8*8)) SUB(RSI, IMM(1)) JNZ(TAIL_LOOP) LABEL(POSTACCUM) #ifdef MONITORS RDTSC MOV(VAR(mid2l), EAX) MOV(VAR(mid2h), EDX) #endif MOV(RAX, VAR(alpha)) MOV(RBX, VAR(beta)) VBROADCASTSD(ZMM(0), MEM(RAX)) VBROADCASTSD(ZMM(1), MEM(RBX)) // Check if C is row stride. If not, jump to the slow scattered update MOV(RAX, VAR(rs_c)) LEA(RAX, MEM(,RAX,8)) LEA(RDI, MEM(RAX,RAX,2)) VMOVQ(RDX, XMM(1)) SAL(RDX) //shift out sign bit JZ(COLSTORBZ) UPDATE_C_FOUR_ROWS( 8, 9,10,11) UPDATE_C_FOUR_ROWS(12,13,14,15) UPDATE_C_FOUR_ROWS(16,17,18,19) UPDATE_C_FOUR_ROWS(20,21,22,23) UPDATE_C_FOUR_ROWS(24,25,26,27) UPDATE_C_FOUR_ROWS(28,29,30,31) JMP(END) LABEL(COLSTORBZ) UPDATE_C_BZ_FOUR_ROWS( 8, 9,10,11) UPDATE_C_BZ_FOUR_ROWS(12,13,14,15) UPDATE_C_BZ_FOUR_ROWS(16,17,18,19) UPDATE_C_BZ_FOUR_ROWS(20,21,22,23) UPDATE_C_BZ_FOUR_ROWS(24,25,26,27) UPDATE_C_BZ_FOUR_ROWS(28,29,30,31) LABEL(END) #ifdef MONITORS RDTSC MOV(VAR(botl), EAX) MOV(VAR(both), EDX) #endif END_ASM( : // output operands #ifdef MONITORS [topl] "=m" (topl), [toph] "=m" (toph), [midl] "=m" (midl), [midh] "=m" (midh), [mid2l] "=m" (mid2l), [mid2h] "=m" (mid2h), [botl] "=m" (botl), [both] "=m" (both) #endif : // input operands [k] "m" (k), [a] "m" (a), [b] "m" (b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c), [a_next] "m" (a_next), [b_next] "m" (b_next), [offsetPtr] "m" (offsetPtr) : // register clobber list "rax", "rbx", "rcx", "rdx", "rdi", "rsi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "zmm0", "zmm1", "zmm2", "zmm3", "zmm4", "zmm5", "zmm6", "zmm7", "zmm8", "zmm9", "zmm10", "zmm11", "zmm12", "zmm13", "zmm14", "zmm15", "zmm16", "zmm17", "zmm18", "zmm19", "zmm20", "zmm21", "zmm22", "zmm23", "zmm24", "zmm25", "zmm26", "zmm27", "zmm28", "zmm29", "zmm30", "zmm31", "memory" ) GEMM_UKR_FLUSH_CT( d ); #ifdef LOOPMON printf("looptime = \t%d\n", bloopl - tloopl); #endif #ifdef MONITORS dim_t top = ((dim_t)toph << 32) | topl; dim_t mid = ((dim_t)midh << 32) | midl; dim_t mid2 = ((dim_t)mid2h << 32) | mid2l; dim_t bot = ((dim_t)both << 32) | botl; printf("setup =\t%u\tmain loop =\t%u\tcleanup=\t%u\ttotal=\t%u\n", mid - top, mid2 - mid, bot - mid2, bot - top); #endif } blis-0.9.0/kernels/knl/3/bli_sgemm_knl_asm_24x16.c000066400000000000000000000457461422157504600215420ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 UNIVERSITY OF TEXAS 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. */ #include "blis.h" #include #define BLIS_ASM_SYNTAX_INTEL #include "bli_x86_asm_macros.h" #define UNROLL_K 32 #define SCATTER_PREFETCH_C 1 #define PREFETCH_A_L2 0 #define PREFETCH_B_L2 0 #define L2_PREFETCH_DIST 64 #define A_L1_PREFETCH_DIST 36 #define B_L1_PREFETCH_DIST 18 #define LOOP_ALIGN ALIGN16 #define UPDATE_C_FOUR_ROWS(R1,R2,R3,R4) \ \ VMULPS(ZMM(R1), ZMM(R1), ZMM(0)) \ VMULPS(ZMM(R2), ZMM(R2), ZMM(0)) \ VMULPS(ZMM(R3), ZMM(R3), ZMM(0)) \ VMULPS(ZMM(R4), ZMM(R4), ZMM(0)) \ VFMADD231PS(ZMM(R1), ZMM(1), MEM(RCX )) \ VFMADD231PS(ZMM(R2), ZMM(1), MEM(RCX,RAX,1)) \ VFMADD231PS(ZMM(R3), ZMM(1), MEM(RCX,RAX,2)) \ VFMADD231PS(ZMM(R4), ZMM(1), MEM(RCX,RDI,1)) \ VMOVUPS(MEM(RCX ), ZMM(R1)) \ VMOVUPS(MEM(RCX,RAX,1), ZMM(R2)) \ VMOVUPS(MEM(RCX,RAX,2), ZMM(R3)) \ VMOVUPS(MEM(RCX,RDI,1), ZMM(R4)) \ LEA(RCX, MEM(RCX,RAX,4)) #define UPDATE_C_BZ_FOUR_ROWS(R1,R2,R3,R4) \ \ VMULPS(ZMM(R1), ZMM(R1), ZMM(0)) \ VMULPS(ZMM(R2), ZMM(R2), ZMM(0)) \ VMULPS(ZMM(R3), ZMM(R3), ZMM(0)) \ VMULPS(ZMM(R4), ZMM(R4), ZMM(0)) \ VMOVUPS(MEM(RCX ), ZMM(R1)) \ VMOVUPS(MEM(RCX,RAX,1), ZMM(R2)) \ VMOVUPS(MEM(RCX,RAX,2), ZMM(R3)) \ VMOVUPS(MEM(RCX,RDI,1), ZMM(R4)) \ LEA(RCX, MEM(RCX,RAX,4)) #define UPDATE_C_ROW_SCATTERED(NUM) \ \ KXNORW(K(1), K(0), K(0)) \ KXNORW(K(2), K(0), K(0)) \ VMULPS(ZMM(NUM), ZMM(NUM), ZMM(0)) \ VGATHERDPS(ZMM(3) MASK_K(1), MEM(RCX,ZMM(2),4)) \ VFMADD231PS(ZMM(NUM), ZMM(3), ZMM(1)) \ VSCATTERDPS(MEM(RCX,ZMM(2),4) MASK_K(2), ZMM(NUM)) \ ADD(RCX, RAX) #define UPDATE_C_BZ_ROW_SCATTERED(NUM) \ \ KXNORW(K(1), K(0), K(0)) \ VMULPS(ZMM(NUM), ZMM(NUM), ZMM(0)) \ VSCATTERDPS(MEM(RCX,ZMM(2),4) MASK_K(1), ZMM(NUM)) \ ADD(RCX, RAX) #define PREFETCH_A_L1_1(n) PREFETCH(0, MEM(RAX,(A_L1_PREFETCH_DIST+n)*24*4)) #define PREFETCH_A_L1_2(n) PREFETCH(0, MEM(RAX,(A_L1_PREFETCH_DIST+n)*24*4+64)) #if PREFETCH_A_L2 #undef PREFETCH_A_L2 #define PREFETCH_A_L2(n) \ \ PREFETCH(1, MEM(RAX,(L2_PREFETCH_DIST+n)*24*4)) \ PREFETCH(1, MEM(RAX,(L2_PREFETCH_DIST+n)*24*4+64)) #else #undef PREFETCH_A_L2 #define PREFETCH_A_L2(...) #endif #define PREFETCH_B_L1(n) PREFETCH(0, MEM(RBX,(B_L1_PREFETCH_DIST+n)*16*4)) #if PREFETCH_B_L2 #undef PREFETCH_B_L2 #define PREFETCH_B_L2(n) PREFETCH(1, MEM(RBX,(L2_PREFETCH_DIST+n)*16*4)) #else #undef PREFETCH_B_L2 #define PREFETCH_B_L2(...) #endif #define PREFETCH_C_L1_1 #define PREFETCH_C_L1_2 #define PREFETCH_C_L1_3 // // n: index in unrolled loop // // a: ZMM register to load into // b: ZMM register to read from // // ...: addressing for A, except for offset // #define SUBITER(n,a,b,...) \ \ PREFETCH_A_L2(n) \ \ VMOVAPS(ZMM(a), MEM(RBX,(n+1)*64)) \ VFMADD231PS(ZMM( 8), ZMM(b), MEM_1TO16(__VA_ARGS__,((n%%4)*24+ 0)*4)) \ VFMADD231PS(ZMM( 9), ZMM(b), MEM_1TO16(__VA_ARGS__,((n%%4)*24+ 1)*4)) \ VFMADD231PS(ZMM(10), ZMM(b), MEM_1TO16(__VA_ARGS__,((n%%4)*24+ 2)*4)) \ PREFETCH_A_L1_1(n) \ VFMADD231PS(ZMM(11), ZMM(b), MEM_1TO16(__VA_ARGS__,((n%%4)*24+ 3)*4)) \ VFMADD231PS(ZMM(12), ZMM(b), MEM_1TO16(__VA_ARGS__,((n%%4)*24+ 4)*4)) \ VFMADD231PS(ZMM(13), ZMM(b), MEM_1TO16(__VA_ARGS__,((n%%4)*24+ 5)*4)) \ PREFETCH_C_L1_1 \ VFMADD231PS(ZMM(14), ZMM(b), MEM_1TO16(__VA_ARGS__,((n%%4)*24+ 6)*4)) \ VFMADD231PS(ZMM(15), ZMM(b), MEM_1TO16(__VA_ARGS__,((n%%4)*24+ 7)*4)) \ VFMADD231PS(ZMM(16), ZMM(b), MEM_1TO16(__VA_ARGS__,((n%%4)*24+ 8)*4)) \ PREFETCH_A_L1_2(n) \ VFMADD231PS(ZMM(17), ZMM(b), MEM_1TO16(__VA_ARGS__,((n%%4)*24+ 9)*4)) \ VFMADD231PS(ZMM(18), ZMM(b), MEM_1TO16(__VA_ARGS__,((n%%4)*24+10)*4)) \ VFMADD231PS(ZMM(19), ZMM(b), MEM_1TO16(__VA_ARGS__,((n%%4)*24+11)*4)) \ PREFETCH_C_L1_2 \ VFMADD231PS(ZMM(20), ZMM(b), MEM_1TO16(__VA_ARGS__,((n%%4)*24+12)*4)) \ VFMADD231PS(ZMM(21), ZMM(b), MEM_1TO16(__VA_ARGS__,((n%%4)*24+13)*4)) \ VFMADD231PS(ZMM(22), ZMM(b), MEM_1TO16(__VA_ARGS__,((n%%4)*24+14)*4)) \ PREFETCH_C_L1_3 \ VFMADD231PS(ZMM(23), ZMM(b), MEM_1TO16(__VA_ARGS__,((n%%4)*24+15)*4)) \ VFMADD231PS(ZMM(24), ZMM(b), MEM_1TO16(__VA_ARGS__,((n%%4)*24+16)*4)) \ VFMADD231PS(ZMM(25), ZMM(b), MEM_1TO16(__VA_ARGS__,((n%%4)*24+17)*4)) \ PREFETCH_B_L1(n) \ VFMADD231PS(ZMM(26), ZMM(b), MEM_1TO16(__VA_ARGS__,((n%%4)*24+18)*4)) \ VFMADD231PS(ZMM(27), ZMM(b), MEM_1TO16(__VA_ARGS__,((n%%4)*24+19)*4)) \ VFMADD231PS(ZMM(28), ZMM(b), MEM_1TO16(__VA_ARGS__,((n%%4)*24+20)*4)) \ PREFETCH_B_L2(n) \ VFMADD231PS(ZMM(29), ZMM(b), MEM_1TO16(__VA_ARGS__,((n%%4)*24+21)*4)) \ VFMADD231PS(ZMM(30), ZMM(b), MEM_1TO16(__VA_ARGS__,((n%%4)*24+22)*4)) \ VFMADD231PS(ZMM(31), ZMM(b), MEM_1TO16(__VA_ARGS__,((n%%4)*24+23)*4)) //This is an array used for the scatter/gather instructions. static int32_t offsets[32] __attribute__((aligned(64))) = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15, 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31}; //#define MONITORS //#define LOOPMON void bli_sgemm_knl_asm_24x16 ( dim_t m, dim_t n, dim_t k_, float* restrict alpha, float* restrict a, float* restrict b, float* restrict beta, float* restrict c, inc_t rs_c_, inc_t cs_c_, auxinfo_t* restrict data, cntx_t* restrict cntx ) { (void)data; (void)cntx; const double * a_next = bli_auxinfo_next_a( data ); const double * b_next = bli_auxinfo_next_b( data ); int32_t * offsetPtr = &offsets[0]; int64_t k = k_; int64_t rs_c = rs_c_; int64_t cs_c = cs_c_; GEMM_UKR_SETUP_CT( s, 24, 16, true ); #ifdef MONITORS int toph, topl, both, botl, midl, midh, mid2l, mid2h; #endif #ifdef LOOPMON int tlooph, tloopl, blooph, bloopl; #endif BEGIN_ASM() #ifdef MONITORS RDTSC MOV(VAR(topl), EAX) MOV(VAR(toph), EDX) #endif VPXORD(ZMM(8), ZMM(8), ZMM(8)) //clear out registers VMOVAPS(ZMM( 9), ZMM(8)) MOV(R12, VAR(rs_c)) VMOVAPS(ZMM(10), ZMM(8)) MOV(RSI, VAR(k)) //loop index VMOVAPS(ZMM(11), ZMM(8)) MOV(RAX, VAR(a)) //load address of a VMOVAPS(ZMM(12), ZMM(8)) MOV(RBX, VAR(b)) //load address of b VMOVAPS(ZMM(13), ZMM(8)) MOV(RCX, VAR(c)) //load address of c VMOVAPS(ZMM(14), ZMM(8)) VMOVAPD(ZMM(0), MEM(RBX)) //pre-load b VMOVAPS(ZMM(15), ZMM(8)) MOV(RDI, VAR(offsetPtr)) VMOVAPS(ZMM(16), ZMM(8)) VMOVAPS(ZMM(4), MEM(RDI)) #if SCATTER_PREFETCH_C VMOVAPS(ZMM(17), ZMM(8)) VMOVAPS(ZMM(18), ZMM(8)) VMOVAPS(ZMM(19), ZMM(8)) VBROADCASTSS(ZMM(5), VAR(rs_c)) VMOVAPS(ZMM(20), ZMM(8)) VMOVAPS(ZMM(21), ZMM(8)) VPMULLD(ZMM(2), ZMM(4), ZMM(5)) VMOVAPS(ZMM(22), ZMM(8)) VMOVAPS(YMM(3), MEM(RDI,64)) VMOVAPS(ZMM(23), ZMM(8)) VPMULLD(YMM(3), YMM(3), YMM(5)) #else VMOVAPS(ZMM(17), ZMM(8)) VMOVAPS(ZMM(18), ZMM(8)) LEA(R13, MEM(R12,R12,2)) VMOVAPS(ZMM(19), ZMM(8)) LEA(R14, MEM(R12,R12,4)) VMOVAPS(ZMM(20), ZMM(8)) LEA(R15, MEM(R13,R12,4)) VMOVAPS(ZMM(21), ZMM(8)) VMOVAPS(ZMM(22), ZMM(8)) VMOVAPS(ZMM(23), ZMM(8)) #endif VMOVAPS(ZMM(24), ZMM(8)) VPSLLD(ZMM(4), ZMM(4), IMM(2)) VMOVAPS(ZMM(25), ZMM(8)) MOV(R8, IMM(4*24*4)) //offset for 4 iterations VMOVAPS(ZMM(26), ZMM(8)) LEA(R9, MEM(R8,R8,2)) //*3 VMOVAPS(ZMM(27), ZMM(8)) LEA(R10, MEM(R8,R8,4)) //*5 VMOVAPS(ZMM(28), ZMM(8)) LEA(R11, MEM(R9,R8,4)) //*7 VMOVAPS(ZMM(29), ZMM(8)) VMOVAPS(ZMM(30), ZMM(8)) VMOVAPS(ZMM(31), ZMM(8)) #ifdef MONITORS RDTSC MOV(VAR(midl), EAX) MOV(VAR(midh), EDX) #endif SUB(RSI, IMM(32)) JLE(TAIL) //prefetch C into L2 #if SCATTER_PREFETCH_C ADD(RSI, IMM(24)) KXNORW(K(1), K(0), K(0)) KXNORW(K(2), K(0), K(0)) VSCATTERPFDPS(1, MEM(RCX,ZMM(2),8) MASK_K(1)) VSCATTERPFDPD(1, MEM(RCX,YMM(3),8) MASK_K(2)) #else PREFETCHW1(MEM(RCX )) SUBITER( 0,1,0,RAX ) PREFETCHW1(MEM(RCX,R12,1)) SUBITER( 1,0,1,RAX ) PREFETCHW1(MEM(RCX,R12,2)) SUBITER( 2,1,0,RAX ) PREFETCHW1(MEM(RCX,R13,1)) SUBITER( 3,0,1,RAX ) PREFETCHW1(MEM(RCX,R12,4)) SUBITER( 4,1,0,RAX,R8, 1) PREFETCHW1(MEM(RCX,R14,1)) SUBITER( 5,0,1,RAX,R8, 1) PREFETCHW1(MEM(RCX,R13,2)) SUBITER( 6,1,0,RAX,R8, 1) PREFETCHW1(MEM(RCX,R15,1)) SUBITER( 7,0,1,RAX,R8, 1) LEA(RDX, MEM(RCX,R12,8)) PREFETCHW1(MEM(RDX )) SUBITER( 8,1,0,RAX,R8, 2) PREFETCHW1(MEM(RDX,R12,1)) SUBITER( 9,0,1,RAX,R8, 2) PREFETCHW1(MEM(RDX,R12,2)) SUBITER(10,1,0,RAX,R8, 2) PREFETCHW1(MEM(RDX,R13,1)) SUBITER(11,0,1,RAX,R8, 2) PREFETCHW1(MEM(RDX,R12,4)) SUBITER(12,1,0,RAX,R9, 1) PREFETCHW1(MEM(RDX,R14,1)) SUBITER(13,0,1,RAX,R9, 1) PREFETCHW1(MEM(RDX,R13,2)) SUBITER(14,1,0,RAX,R9, 1) PREFETCHW1(MEM(RDX,R15,1)) SUBITER(15,0,1,RAX,R9, 1) LEA(RDI, MEM(RDX,R12,8)) PREFETCHW1(MEM(RDI )) SUBITER(16,1,0,RAX,R8, 4) PREFETCHW1(MEM(RDI,R12,1)) SUBITER(17,0,1,RAX,R8, 4) PREFETCHW1(MEM(RDI,R12,2)) SUBITER(18,1,0,RAX,R8, 4) PREFETCHW1(MEM(RDI,R13,1)) SUBITER(19,0,1,RAX,R8, 4) PREFETCHW1(MEM(RDI,R12,4)) SUBITER(20,1,0,RAX,R10,1) PREFETCHW1(MEM(RDI,R14,1)) SUBITER(21,0,1,RAX,R10,1) PREFETCHW1(MEM(RDI,R13,2)) SUBITER(22,1,0,RAX,R10,1) PREFETCHW1(MEM(RDI,R15,1)) SUBITER(23,0,1,RAX,R10,1) ADD(RAX, IMM(24*24*4)) ADD(RBX, IMM(24*16*4)) #endif MOV(RDI, RSI) AND(RDI, IMM(31)) SAR(RSI, IMM(5)) JZ(REM_1) LOOP_ALIGN LABEL(MAIN_LOOP) SUBITER( 0,1,0,RAX ) SUBITER( 1,0,1,RAX ) SUBITER( 2,1,0,RAX ) SUBITER( 3,0,1,RAX ) SUBITER( 4,1,0,RAX,R8, 1) SUBITER( 5,0,1,RAX,R8, 1) SUBITER( 6,1,0,RAX,R8, 1) SUBITER( 7,0,1,RAX,R8, 1) SUBITER( 8,1,0,RAX,R8, 2) SUBITER( 9,0,1,RAX,R8, 2) SUBITER(10,1,0,RAX,R8, 2) SUBITER(11,0,1,RAX,R8, 2) SUBITER(12,1,0,RAX,R9, 1) SUBITER(13,0,1,RAX,R9, 1) SUBITER(14,1,0,RAX,R9, 1) SUBITER(15,0,1,RAX,R9, 1) SUBITER(16,1,0,RAX,R8, 4) SUBITER(17,0,1,RAX,R8, 4) SUBITER(18,1,0,RAX,R8, 4) SUBITER(19,0,1,RAX,R8, 4) SUBITER(20,1,0,RAX,R10,1) SUBITER(21,0,1,RAX,R10,1) SUBITER(22,1,0,RAX,R10,1) SUBITER(23,0,1,RAX,R10,1) SUBITER(24,1,0,RAX,R9, 2) SUBITER(25,0,1,RAX,R9, 2) SUBITER(26,1,0,RAX,R9, 2) SUBITER(27,0,1,RAX,R9, 2) SUBITER(28,1,0,RAX,R11,1) SUBITER(29,0,1,RAX,R11,1) SUBITER(30,1,0,RAX,R11,1) SUBITER(31,0,1,RAX,R11,1) ADD(RAX, IMM(32*24*4)) ADD(RBX, IMM(32*16*4)) SUB(RSI, IMM(1)) JNZ(MAIN_LOOP) LABEL(REM_1) SAR(RDI) JNC(REM_2) SUBITER(0,1,0,RAX) VMOVAPD(ZMM(0), ZMM(1)) ADD(RAX, IMM(24*4)) ADD(RBX, IMM(16*4)) LABEL(REM_2) SAR(RDI) JNC(REM_4) SUBITER(0,1,0,RAX) SUBITER(1,0,1,RAX) ADD(RAX, IMM(2*24*4)) ADD(RBX, IMM(2*16*4)) LABEL(REM_4) SAR(RDI) JNC(REM_8) SUBITER(0,1,0,RAX) SUBITER(1,0,1,RAX) SUBITER(2,1,0,RAX) SUBITER(3,0,1,RAX) ADD(RAX, IMM(4*24*4)) ADD(RBX, IMM(4*16*4)) LABEL(REM_8) SAR(RDI) JNC(REM_16) SUBITER(0,1,0,RAX ) SUBITER(1,0,1,RAX ) SUBITER(2,1,0,RAX ) SUBITER(3,0,1,RAX ) SUBITER(4,1,0,RAX,R8,1) SUBITER(5,0,1,RAX,R8,1) SUBITER(6,1,0,RAX,R8,1) SUBITER(7,0,1,RAX,R8,1) ADD(RAX, IMM(8*24*4)) ADD(RBX, IMM(8*16*4)) LABEL(REM_16) SAR(RDI) JNC(AFTER_LOOP) SUBITER( 0,1,0,RAX ) SUBITER( 1,0,1,RAX ) SUBITER( 2,1,0,RAX ) SUBITER( 3,0,1,RAX ) SUBITER( 4,1,0,RAX,R8, 1) SUBITER( 5,0,1,RAX,R8, 1) SUBITER( 6,1,0,RAX,R8, 1) SUBITER( 7,0,1,RAX,R8, 1) SUBITER( 8,1,0,RAX,R8, 2) SUBITER( 9,0,1,RAX,R8, 2) SUBITER(10,1,0,RAX,R8, 2) SUBITER(11,0,1,RAX,R8, 2) SUBITER(12,1,0,RAX,R9, 1) SUBITER(13,0,1,RAX,R9, 1) SUBITER(14,1,0,RAX,R9, 1) SUBITER(15,0,1,RAX,R9, 1) ADD(RAX, IMM(16*24*4)) ADD(RBX, IMM(16*16*4)) LABEL(AFTER_LOOP) //prefetch C into L1 #if SCATTER_PREFETCH_C KXNORW(K(1), K(0), K(0)) KXNORW(K(2), K(0), K(0)) VSCATTERPFDPS(0, MEM(RCX,ZMM(2),8) MASK_K(1)) VSCATTERPFDPD(0, MEM(RCX,YMM(3),8) MASK_K(2)) SUBITER(0,1,0,RAX ) SUBITER(1,0,1,RAX ) SUBITER(2,1,0,RAX ) SUBITER(3,0,1,RAX ) SUBITER(4,1,0,RAX,R8,1) SUBITER(5,0,1,RAX,R8,1) SUBITER(6,1,0,RAX,R8,1) SUBITER(7,0,1,RAX,R8,1) #else LEA(RDX, MEM(RCX,R12,8)) LEA(RDI, MEM(RDX,R12,8)) #undef PREFETCH_C_L1_1 #undef PREFETCH_C_L1_2 #undef PREFETCH_C_L1_3 #define PREFETCH_C_L1_1 PREFETCHW0(MEM(RCX )) #define PREFETCH_C_L1_2 PREFETCHW0(MEM(RCX,R12,1)) #define PREFETCH_C_L1_3 PREFETCHW0(MEM(RCX,R12,2)) SUBITER(0,1,0,RAX ) #undef PREFETCH_C_L1_1 #undef PREFETCH_C_L1_2 #undef PREFETCH_C_L1_3 #define PREFETCH_C_L1_1 PREFETCHW0(MEM(RCX,R13,1)) #define PREFETCH_C_L1_2 PREFETCHW0(MEM(RCX,R12,4)) #define PREFETCH_C_L1_3 PREFETCHW0(MEM(RCX,R14,1)) SUBITER(1,0,1,RAX ) #undef PREFETCH_C_L1_1 #undef PREFETCH_C_L1_2 #undef PREFETCH_C_L1_3 #define PREFETCH_C_L1_1 PREFETCHW0(MEM(RCX,R13,2)) #define PREFETCH_C_L1_2 PREFETCHW0(MEM(RCX,R15,1)) #define PREFETCH_C_L1_3 PREFETCHW0(MEM(RDX )) SUBITER(2,1,0,RAX ) #undef PREFETCH_C_L1_1 #undef PREFETCH_C_L1_2 #undef PREFETCH_C_L1_3 #define PREFETCH_C_L1_1 PREFETCHW0(MEM(RDX,R12,1)) #define PREFETCH_C_L1_2 PREFETCHW0(MEM(RDX,R12,2)) #define PREFETCH_C_L1_3 PREFETCHW0(MEM(RDX,R13,1)) SUBITER(3,0,1,RAX ) #undef PREFETCH_C_L1_1 #undef PREFETCH_C_L1_2 #undef PREFETCH_C_L1_3 #define PREFETCH_C_L1_1 PREFETCHW0(MEM(RDX,R12,4)) #define PREFETCH_C_L1_2 PREFETCHW0(MEM(RDX,R14,1)) #define PREFETCH_C_L1_3 PREFETCHW0(MEM(RDX,R13,2)) SUBITER(4,1,0,RAX,R8,1) #undef PREFETCH_C_L1_1 #undef PREFETCH_C_L1_2 #undef PREFETCH_C_L1_3 #define PREFETCH_C_L1_1 PREFETCHW0(MEM(RDX,R15,1)) #define PREFETCH_C_L1_2 PREFETCHW0(MEM(RDI )) #define PREFETCH_C_L1_3 PREFETCHW0(MEM(RDI,R12,1)) SUBITER(5,0,1,RAX,R8,1) #undef PREFETCH_C_L1_1 #undef PREFETCH_C_L1_2 #undef PREFETCH_C_L1_3 #define PREFETCH_C_L1_1 PREFETCHW0(MEM(RDI,R12,2)) #define PREFETCH_C_L1_2 PREFETCHW0(MEM(RDI,R13,1)) #define PREFETCH_C_L1_3 PREFETCHW0(MEM(RDI,R12,4)) SUBITER(6,1,0,RAX,R8,1) #undef PREFETCH_C_L1_1 #undef PREFETCH_C_L1_2 #undef PREFETCH_C_L1_3 #define PREFETCH_C_L1_1 PREFETCHW0(MEM(RDI,R14,1)) #define PREFETCH_C_L1_2 PREFETCHW0(MEM(RDI,R13,2)) #define PREFETCH_C_L1_3 PREFETCHW0(MEM(RDI,R15,1)) SUBITER(7,0,1,RAX,R8,1) #endif JMP(POSTACCUM) LABEL(TAIL) MOV(RDX, RCX) ADD(RSI, IMM(32)) JZ(POSTACCUM) LABEL(TAIL_LOOP) PREFETCHW0(MEM(RDX)) ADD(RDX, R12) SUBITER(0,1,0,RAX) VMOVAPD(ZMM(0), ZMM(1)) ADD(RAX, IMM(24*4)) ADD(RBX, IMM(16*4)) SUB(RSI, IMM(1)) JNZ(TAIL_LOOP) LABEL(POSTACCUM) #ifdef MONITORS RDTSC MOV(VAR(mid2l), EAX) MOV(VAR(mid2h), EDX) #endif MOV(RAX, VAR(alpha)) MOV(RBX, VAR(beta)) VBROADCASTSS(ZMM(0), MEM(RAX)) VBROADCASTSS(ZMM(1), MEM(RBX)) // Check if C is row stride. If not, jump to the slow scattered update MOV(RAX, VAR(rs_c)) LEA(RAX, MEM(,RAX,4)) LEA(RDI, MEM(RAX,RAX,2)) VMOVD(EDX, XMM(1)) SAL(EDX) //shift out sign bit JZ(COLSTORBZ) UPDATE_C_FOUR_ROWS( 8, 9,10,11) UPDATE_C_FOUR_ROWS(12,13,14,15) UPDATE_C_FOUR_ROWS(16,17,18,19) UPDATE_C_FOUR_ROWS(20,21,22,23) UPDATE_C_FOUR_ROWS(24,25,26,27) UPDATE_C_FOUR_ROWS(28,29,30,31) JMP(END) LABEL(COLSTORBZ) UPDATE_C_BZ_FOUR_ROWS( 8, 9,10,11) UPDATE_C_BZ_FOUR_ROWS(12,13,14,15) UPDATE_C_BZ_FOUR_ROWS(16,17,18,19) UPDATE_C_BZ_FOUR_ROWS(20,21,22,23) UPDATE_C_BZ_FOUR_ROWS(24,25,26,27) UPDATE_C_BZ_FOUR_ROWS(28,29,30,31) LABEL(END) #ifdef MONITORS RDTSC MOV(VAR(botl), EAX) MOV(VAR(both), EDX) #endif END_ASM( : // output operands #ifdef MONITORS [topl] "=m" (topl), [toph] "=m" (toph), [midl] "=m" (midl), [midh] "=m" (midh), [mid2l] "=m" (mid2l), [mid2h] "=m" (mid2h), [botl] "=m" (botl), [both] "=m" (both) #endif : // input operands [k] "m" (k), [a] "m" (a), [b] "m" (b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c), [a_next] "m" (a_next), [b_next] "m" (b_next), [offsetPtr] "m" (offsetPtr) : // register clobber list "rax", "rbx", "rcx", "rdx", "rdi", "rsi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "zmm0", "zmm1", "zmm2", "zmm3", "zmm4", "zmm5", "zmm6", "zmm7", "zmm8", "zmm9", "zmm10", "zmm11", "zmm12", "zmm13", "zmm14", "zmm15", "zmm16", "zmm17", "zmm18", "zmm19", "zmm20", "zmm21", "zmm22", "zmm23", "zmm24", "zmm25", "zmm26", "zmm27", "zmm28", "zmm29", "zmm30", "zmm31", "memory" ) GEMM_UKR_FLUSH_CT( s ); #ifdef LOOPMON printf("looptime = \t%d\n", bloopl - tloopl); #endif #ifdef MONITORS dim_t top = ((dim_t)toph << 32) | topl; dim_t mid = ((dim_t)midh << 32) | midl; dim_t mid2 = ((dim_t)mid2h << 32) | mid2l; dim_t bot = ((dim_t)both << 32) | botl; printf("setup =\t%u\tmain loop =\t%u\tcleanup=\t%u\ttotal=\t%u\n", mid - top, mid2 - mid, bot - mid2, bot - top); #endif } blis-0.9.0/kernels/knl/3/other/000077500000000000000000000000001422157504600161715ustar00rootroot00000000000000blis-0.9.0/kernels/knl/3/other/bli_dgemm_knl_asm_12x16.c000066400000000000000000000604751422157504600226350ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "bli_avx512_macros.h" extern int32_t offsets[16]; void bli_dgemm_knl_asm_12x16 ( dim_t k, double* restrict alpha, double* restrict a, double* restrict b, double* restrict beta, double* restrict c, inc_t rs_c, inc_t cs_c, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //const void* a_next = bli_auxinfo_next_a( data ); //const void* b_next = bli_auxinfo_next_b( data ); const int32_t * offsetPtr = &offsets[0]; __asm__ volatile ( VPXORD(ZMM(8), ZMM(8), ZMM(8)) MOV(RAX, VAR(a)) VMOVAPD(ZMM( 9), ZMM(8)) MOV(RBX, VAR(b)) VMOVAPD(ZMM(10), ZMM(8)) //no ADD(RBX, IMM(4*64)) VMOVAPD(ZMM(11), ZMM(8)) //maybe? PREFETCH(0, MEM(RAX, 0)) VMOVAPD(ZMM(12), ZMM(8)) //maybe? PREFETCH(0, MEM(RAX,64)) VMOVAPD(ZMM(13), ZMM(8)) VMOVAPD(ZMM(0), MEM(RBX,0*64)) VMOVAPD(ZMM(14), ZMM(8)) VMOVAPD(ZMM(1), MEM(RBX,1*64)) VMOVAPD(ZMM(15), ZMM(8)) MOV(RCX, VAR(c)) VMOVAPD(ZMM(16), ZMM(8)) MOV(RDI, RCX) VMOVAPD(ZMM(17), ZMM(8)) VBROADCASTSS(ZMM(4), VAR(cs_c)) VMOVAPD(ZMM(18), ZMM(8)) VMOVAPS(ZMM(5), VAR(offsetPtr)) VMOVAPD(ZMM(19), ZMM(8)) VPMULLD(ZMM(4), ZMM(5), ZMM(4)) VMOVAPD(ZMM(20), ZMM(8)) MOV(RDX, IMM(0xFFF)) VMOVAPD(ZMM(21), ZMM(8)) KMOV(K(1), EDX) VMOVAPD(ZMM(22), ZMM(8)) KMOV(K(2), EDX) VMOVAPD(ZMM(23), ZMM(8)) KMOV(K(3), EDX) VMOVAPD(ZMM(24), ZMM(8)) VSCATTERPFDPS(0, MEM(RCX,ZMM(4),8, 0) MASK_K(1)) VMOVAPD(ZMM(25), ZMM(8)) VSCATTERPFDPS(0, MEM(RCX,ZMM(4),8, 8*8) MASK_K(2)) VMOVAPD(ZMM(26), ZMM(8)) VSCATTERPFDPS(0, MEM(RCX,ZMM(4),8,15*8) MASK_K(3)) VMOVAPD(ZMM(27), ZMM(8)) MOV(RSI, VAR(k)) VMOVAPD(ZMM(28), ZMM(8)) SAR(RSI, IMM(2)) // rsi = k/4 VMOVAPD(ZMM(29), ZMM(8)) VMOVAPD(ZMM(30), ZMM(8)) VMOVAPD(ZMM(31), ZMM(8)) JZ(.DCONSIDKLEFT) ALIGN16 LABEL(.DLOOPKITER) VBROADCASTSD(ZMM(2), MEM(RAX, 0*8)) // Iteration 0 VBROADCASTSD(ZMM(3), MEM(RAX, 1*8)) VBROADCASTSD(ZMM(4), MEM(RAX, 2*8)) VBROADCASTSD(ZMM(5), MEM(RAX, 3*8)) VBROADCASTSD(ZMM(6), MEM(RAX, 4*8)) VBROADCASTSD(ZMM(7), MEM(RAX, 5*8)) VFMADD231PD(ZMM( 8), ZMM(0), ZMM(2)) VFMADD231PD(ZMM( 9), ZMM(1), ZMM(2)) VFMADD231PD(ZMM(10), ZMM(0), ZMM(3)) VFMADD231PD(ZMM(11), ZMM(1), ZMM(3)) VFMADD231PD(ZMM(12), ZMM(0), ZMM(4)) VFMADD231PD(ZMM(13), ZMM(1), ZMM(4)) VFMADD231PD(ZMM(14), ZMM(0), ZMM(5)) VFMADD231PD(ZMM(15), ZMM(1), ZMM(5)) VFMADD231PD(ZMM(16), ZMM(0), ZMM(6)) VFMADD231PD(ZMM(17), ZMM(1), ZMM(6)) VFMADD231PD(ZMM(18), ZMM(0), ZMM(7)) VFMADD231PD(ZMM(19), ZMM(1), ZMM(7)) VBROADCASTSD(ZMM(2), MEM(RAX, 6*8)) VBROADCASTSD(ZMM(3), MEM(RAX, 7*8)) VBROADCASTSD(ZMM(4), MEM(RAX, 8*8)) VBROADCASTSD(ZMM(5), MEM(RAX, 9*8)) VBROADCASTSD(ZMM(6), MEM(RAX, 10*8)) VBROADCASTSD(ZMM(7), MEM(RAX, 11*8)) VFMADD231PD(ZMM(20), ZMM(0), ZMM(2)) VFMADD231PD(ZMM(21), ZMM(1), ZMM(2)) VFMADD231PD(ZMM(22), ZMM(0), ZMM(3)) VFMADD231PD(ZMM(23), ZMM(1), ZMM(3)) VFMADD231PD(ZMM(24), ZMM(0), ZMM(4)) VFMADD231PD(ZMM(25), ZMM(1), ZMM(4)) VFMADD231PD(ZMM(26), ZMM(0), ZMM(5)) VFMADD231PD(ZMM(27), ZMM(1), ZMM(5)) VFMADD231PD(ZMM(28), ZMM(0), ZMM(6)) VFMADD231PD(ZMM(29), ZMM(1), ZMM(6)) VFMADD231PD(ZMM(30), ZMM(0), ZMM(7)) VFMADD231PD(ZMM(31), ZMM(1), ZMM(7)) VMOVAPD(ZMM(0), MEM(RBX,2*64)) VMOVAPD(ZMM(1), MEM(RBX,3*64)) PREFETCH(0, MEM(RAX, 64*8)) PREFETCH(0, MEM(RAX, 72*8)) VBROADCASTSD(ZMM(2), MEM(RAX, 12*8)) // Iteration 1 VBROADCASTSD(ZMM(3), MEM(RAX, 13*8)) VBROADCASTSD(ZMM(4), MEM(RAX, 14*8)) VBROADCASTSD(ZMM(5), MEM(RAX, 15*8)) VBROADCASTSD(ZMM(6), MEM(RAX, 16*8)) VBROADCASTSD(ZMM(7), MEM(RAX, 17*8)) VFMADD231PD(ZMM( 8), ZMM(0), ZMM(2)) VFMADD231PD(ZMM( 9), ZMM(1), ZMM(2)) VFMADD231PD(ZMM(10), ZMM(0), ZMM(3)) VFMADD231PD(ZMM(11), ZMM(1), ZMM(3)) VFMADD231PD(ZMM(12), ZMM(0), ZMM(4)) VFMADD231PD(ZMM(13), ZMM(1), ZMM(4)) VFMADD231PD(ZMM(14), ZMM(0), ZMM(5)) VFMADD231PD(ZMM(15), ZMM(1), ZMM(5)) VFMADD231PD(ZMM(16), ZMM(0), ZMM(6)) VFMADD231PD(ZMM(17), ZMM(1), ZMM(6)) VFMADD231PD(ZMM(18), ZMM(0), ZMM(7)) VFMADD231PD(ZMM(19), ZMM(1), ZMM(7)) VBROADCASTSD(ZMM(2), MEM(RAX, 18*8)) VBROADCASTSD(ZMM(3), MEM(RAX, 19*8)) VBROADCASTSD(ZMM(4), MEM(RAX, 20*8)) VBROADCASTSD(ZMM(5), MEM(RAX, 21*8)) VBROADCASTSD(ZMM(6), MEM(RAX, 22*8)) VBROADCASTSD(ZMM(7), MEM(RAX, 23*8)) VFMADD231PD(ZMM(20), ZMM(0), ZMM(2)) VFMADD231PD(ZMM(21), ZMM(1), ZMM(2)) VFMADD231PD(ZMM(22), ZMM(0), ZMM(3)) VFMADD231PD(ZMM(23), ZMM(1), ZMM(3)) VFMADD231PD(ZMM(24), ZMM(0), ZMM(4)) VFMADD231PD(ZMM(25), ZMM(1), ZMM(4)) VFMADD231PD(ZMM(26), ZMM(0), ZMM(5)) VFMADD231PD(ZMM(27), ZMM(1), ZMM(5)) VFMADD231PD(ZMM(28), ZMM(0), ZMM(6)) VFMADD231PD(ZMM(29), ZMM(1), ZMM(6)) VFMADD231PD(ZMM(30), ZMM(0), ZMM(7)) VFMADD231PD(ZMM(31), ZMM(1), ZMM(7)) VMOVAPD(ZMM(0), MEM(RBX,4*64)) VMOVAPD(ZMM(1), MEM(RBX,5*64)) PREFETCH(0, MEM(RAX, 80*8)) PREFETCH(0, MEM(RAX, 88*8)) VBROADCASTSD(ZMM(2), MEM(RAX, 24*8)) // Iteration 2 VBROADCASTSD(ZMM(3), MEM(RAX, 25*8)) VBROADCASTSD(ZMM(4), MEM(RAX, 26*8)) VBROADCASTSD(ZMM(5), MEM(RAX, 27*8)) VBROADCASTSD(ZMM(6), MEM(RAX, 28*8)) VBROADCASTSD(ZMM(7), MEM(RAX, 29*8)) VFMADD231PD(ZMM( 8), ZMM(0), ZMM(2)) VFMADD231PD(ZMM( 9), ZMM(1), ZMM(2)) VFMADD231PD(ZMM(10), ZMM(0), ZMM(3)) VFMADD231PD(ZMM(11), ZMM(1), ZMM(3)) VFMADD231PD(ZMM(12), ZMM(0), ZMM(4)) VFMADD231PD(ZMM(13), ZMM(1), ZMM(4)) VFMADD231PD(ZMM(14), ZMM(0), ZMM(5)) VFMADD231PD(ZMM(15), ZMM(1), ZMM(5)) VFMADD231PD(ZMM(16), ZMM(0), ZMM(6)) VFMADD231PD(ZMM(17), ZMM(1), ZMM(6)) VFMADD231PD(ZMM(18), ZMM(0), ZMM(7)) VFMADD231PD(ZMM(19), ZMM(1), ZMM(7)) VBROADCASTSD(ZMM(2), MEM(RAX, 30*8)) VBROADCASTSD(ZMM(3), MEM(RAX, 31*8)) VBROADCASTSD(ZMM(4), MEM(RAX, 32*8)) VBROADCASTSD(ZMM(5), MEM(RAX, 33*8)) VBROADCASTSD(ZMM(6), MEM(RAX, 34*8)) VBROADCASTSD(ZMM(7), MEM(RAX, 35*8)) VFMADD231PD(ZMM(20), ZMM(0), ZMM(2)) VFMADD231PD(ZMM(21), ZMM(1), ZMM(2)) VFMADD231PD(ZMM(22), ZMM(0), ZMM(3)) VFMADD231PD(ZMM(23), ZMM(1), ZMM(3)) VFMADD231PD(ZMM(24), ZMM(0), ZMM(4)) VFMADD231PD(ZMM(25), ZMM(1), ZMM(4)) VFMADD231PD(ZMM(26), ZMM(0), ZMM(5)) VFMADD231PD(ZMM(27), ZMM(1), ZMM(5)) VFMADD231PD(ZMM(28), ZMM(0), ZMM(6)) VFMADD231PD(ZMM(29), ZMM(1), ZMM(6)) VFMADD231PD(ZMM(30), ZMM(0), ZMM(7)) VFMADD231PD(ZMM(31), ZMM(1), ZMM(7)) VMOVAPD(ZMM(0), MEM(RBX,6*64)) VMOVAPD(ZMM(1), MEM(RBX,7*64)) ADD(RBX, IMM(4*8*16)) PREFETCH(0, MEM(RAX, 96*8)) PREFETCH(0, MEM(RAX, 104*8)) VBROADCASTSD(ZMM(2), MEM(RAX, 36*8)) // Iteration 3 VBROADCASTSD(ZMM(3), MEM(RAX, 37*8)) VBROADCASTSD(ZMM(4), MEM(RAX, 38*8)) VBROADCASTSD(ZMM(5), MEM(RAX, 39*8)) VBROADCASTSD(ZMM(6), MEM(RAX, 40*8)) VBROADCASTSD(ZMM(7), MEM(RAX, 41*8)) VFMADD231PD(ZMM( 8), ZMM(0), ZMM(2)) VFMADD231PD(ZMM( 9), ZMM(1), ZMM(2)) VFMADD231PD(ZMM(10), ZMM(0), ZMM(3)) VFMADD231PD(ZMM(11), ZMM(1), ZMM(3)) VFMADD231PD(ZMM(12), ZMM(0), ZMM(4)) VFMADD231PD(ZMM(13), ZMM(1), ZMM(4)) VFMADD231PD(ZMM(14), ZMM(0), ZMM(5)) VFMADD231PD(ZMM(15), ZMM(1), ZMM(5)) VFMADD231PD(ZMM(16), ZMM(0), ZMM(6)) VFMADD231PD(ZMM(17), ZMM(1), ZMM(6)) VFMADD231PD(ZMM(18), ZMM(0), ZMM(7)) VFMADD231PD(ZMM(19), ZMM(1), ZMM(7)) VBROADCASTSD(ZMM(2), MEM(RAX, 42*8)) VBROADCASTSD(ZMM(3), MEM(RAX, 43*8)) VBROADCASTSD(ZMM(4), MEM(RAX, 44*8)) VBROADCASTSD(ZMM(5), MEM(RAX, 45*8)) VBROADCASTSD(ZMM(6), MEM(RAX, 46*8)) VBROADCASTSD(ZMM(7), MEM(RAX, 47*8)) VFMADD231PD(ZMM(20), ZMM(0), ZMM(2)) VFMADD231PD(ZMM(21), ZMM(1), ZMM(2)) VFMADD231PD(ZMM(22), ZMM(0), ZMM(3)) VFMADD231PD(ZMM(23), ZMM(1), ZMM(3)) VFMADD231PD(ZMM(24), ZMM(0), ZMM(4)) VFMADD231PD(ZMM(25), ZMM(1), ZMM(4)) VFMADD231PD(ZMM(26), ZMM(0), ZMM(5)) VFMADD231PD(ZMM(27), ZMM(1), ZMM(5)) VFMADD231PD(ZMM(28), ZMM(0), ZMM(6)) VFMADD231PD(ZMM(29), ZMM(1), ZMM(6)) VFMADD231PD(ZMM(30), ZMM(0), ZMM(7)) VFMADD231PD(ZMM(31), ZMM(1), ZMM(7)) ADD(RAX, IMM(4*8*12)) SUB(RSI, IMM(1)) VMOVAPD(ZMM(0), MEM(RBX,0*64)) VMOVAPD(ZMM(1), MEM(RBX,1*64)) JNZ(.DLOOPKITER) LABEL(.DCONSIDKLEFT) MOV(RSI, VAR(k)) AND(RSI, IMM(3)) // rsi = k%4 JZ(.DPOSTACCUM) ALIGN16 LABEL(.DLOOPKLEFT) VBROADCASTSD(ZMM(2), MEM(RAX, 0*8)) VBROADCASTSD(ZMM(3), MEM(RAX, 1*8)) VBROADCASTSD(ZMM(4), MEM(RAX, 2*8)) VBROADCASTSD(ZMM(5), MEM(RAX, 3*8)) VBROADCASTSD(ZMM(6), MEM(RAX, 4*8)) VBROADCASTSD(ZMM(7), MEM(RAX, 5*8)) VFMADD231PD(ZMM( 8), ZMM(0), ZMM(2)) VFMADD231PD(ZMM( 9), ZMM(1), ZMM(2)) VFMADD231PD(ZMM(10), ZMM(0), ZMM(3)) VFMADD231PD(ZMM(11), ZMM(1), ZMM(3)) VFMADD231PD(ZMM(12), ZMM(0), ZMM(4)) VFMADD231PD(ZMM(13), ZMM(1), ZMM(4)) VFMADD231PD(ZMM(14), ZMM(0), ZMM(5)) VFMADD231PD(ZMM(15), ZMM(1), ZMM(5)) VFMADD231PD(ZMM(16), ZMM(0), ZMM(6)) VFMADD231PD(ZMM(17), ZMM(1), ZMM(6)) VFMADD231PD(ZMM(18), ZMM(0), ZMM(7)) VFMADD231PD(ZMM(19), ZMM(1), ZMM(7)) VBROADCASTSD(ZMM(2), MEM(RAX, 6*8)) VBROADCASTSD(ZMM(3), MEM(RAX, 7*8)) VBROADCASTSD(ZMM(4), MEM(RAX, 8*8)) VBROADCASTSD(ZMM(5), MEM(RAX, 9*8)) VBROADCASTSD(ZMM(6), MEM(RAX, 10*8)) VBROADCASTSD(ZMM(7), MEM(RAX, 11*8)) VFMADD231PD(ZMM(20), ZMM(0), ZMM(2)) VFMADD231PD(ZMM(21), ZMM(1), ZMM(2)) VFMADD231PD(ZMM(22), ZMM(0), ZMM(3)) VFMADD231PD(ZMM(23), ZMM(1), ZMM(3)) VFMADD231PD(ZMM(24), ZMM(0), ZMM(4)) VFMADD231PD(ZMM(25), ZMM(1), ZMM(4)) VFMADD231PD(ZMM(26), ZMM(0), ZMM(5)) VFMADD231PD(ZMM(27), ZMM(1), ZMM(5)) VFMADD231PD(ZMM(28), ZMM(0), ZMM(6)) VFMADD231PD(ZMM(29), ZMM(1), ZMM(6)) VFMADD231PD(ZMM(30), ZMM(0), ZMM(7)) VFMADD231PD(ZMM(31), ZMM(1), ZMM(7)) ADD(RAX, IMM(12*8)) ADD(RBX, IMM(16*8)) SUB(RSI, IMM(1)) VMOVAPD(ZMM(0), MEM(RBX,0*64)) VMOVAPD(ZMM(1), MEM(RBX,1*64)) JNZ(.DLOOPKLEFT) LABEL(.DPOSTACCUM) MOV(RAX, VAR(alpha)) MOV(RBX, VAR(beta)) VBROADCASTSD(ZMM(0), MEM(RAX)) VBROADCASTSD(ZMM(1), MEM(RBX)) VMULPD(ZMM( 8), ZMM( 8), ZMM(0)) VMULPD(ZMM( 9), ZMM( 9), ZMM(0)) VMULPD(ZMM(10), ZMM(10), ZMM(0)) VMULPD(ZMM(11), ZMM(11), ZMM(0)) VMULPD(ZMM(12), ZMM(12), ZMM(0)) VMULPD(ZMM(13), ZMM(13), ZMM(0)) VMULPD(ZMM(14), ZMM(14), ZMM(0)) VMULPD(ZMM(15), ZMM(15), ZMM(0)) VMULPD(ZMM(16), ZMM(16), ZMM(0)) VMULPD(ZMM(17), ZMM(17), ZMM(0)) VMULPD(ZMM(18), ZMM(18), ZMM(0)) VMULPD(ZMM(19), ZMM(19), ZMM(0)) VMULPD(ZMM(20), ZMM(20), ZMM(0)) VMULPD(ZMM(21), ZMM(21), ZMM(0)) VMULPD(ZMM(22), ZMM(22), ZMM(0)) VMULPD(ZMM(23), ZMM(23), ZMM(0)) VMULPD(ZMM(24), ZMM(24), ZMM(0)) VMULPD(ZMM(25), ZMM(25), ZMM(0)) VMULPD(ZMM(26), ZMM(26), ZMM(0)) VMULPD(ZMM(27), ZMM(27), ZMM(0)) VMULPD(ZMM(28), ZMM(28), ZMM(0)) VMULPD(ZMM(29), ZMM(29), ZMM(0)) VMULPD(ZMM(30), ZMM(30), ZMM(0)) VMULPD(ZMM(31), ZMM(31), ZMM(0)) MOV(RDI, VAR(rs_c)) SUB(RDI, IMM(1)) JNZ(.DGENSTORED) LABEL(.ROWSTORED) MOV(RSI, VAR(cs_c)) MOV(R(8), MEM(RBX)) LEA(RSI, MEM(,RSI,8)) LEA(RDX, MEM(RCX,RSI,4)) LEA(RDI, MEM(RCX,RSI,8)) LEA(R(13), MEM(RSI,RSI,2)) SAL1(R(8)) // shift out the sign bit to check for +/- zero JZ(.DROWSTORBZ) VFMADD231PD(ZMM( 8), ZMM(1), MEM(RCX)) VFMADD231PD(ZMM( 9), ZMM(1), MEM(RCX,64)) VMOVUPD(MEM(RCX), ZMM( 8)) VMOVUPD(MEM(RCX,64), ZMM( 9)) VFMADD231PD(ZMM(10), ZMM(1), MEM(RCX,RSI,1)) VFMADD231PD(ZMM(11), ZMM(1), MEM(RCX,RSI,1,64)) VMOVUPD(MEM(RCX,RSI,1), ZMM(10)) VMOVUPD(MEM(RCX,RSI,1,64), ZMM(11)) VFMADD231PD(ZMM(12), ZMM(1), MEM(RCX,RSI,2)) VFMADD231PD(ZMM(13), ZMM(1), MEM(RCX,RSI,2,64)) VMOVUPD(MEM(RCX,RSI,2), ZMM(12)) VMOVUPD(MEM(RCX,RSI,2,64), ZMM(13)) VFMADD231PD(ZMM(14), ZMM(1), MEM(RCX,R(13),1)) VFMADD231PD(ZMM(15), ZMM(1), MEM(RCX,R(13),1,64)) VMOVUPD(MEM(RCX,R(13),1), ZMM(14)) VMOVUPD(MEM(RCX,R(13),1,64), ZMM(15)) VFMADD231PD(ZMM(16), ZMM(1), MEM(RDX)) VFMADD231PD(ZMM(17), ZMM(1), MEM(RDX,64)) VMOVUPD(MEM(RDX), ZMM(16)) VMOVUPD(MEM(RDX,64), ZMM(17)) VFMADD231PD(ZMM(18), ZMM(1), MEM(RDX,RSI,1)) VFMADD231PD(ZMM(19), ZMM(1), MEM(RDX,RSI,1,64)) VMOVUPD(MEM(RDX,RSI,1), ZMM(18)) VMOVUPD(MEM(RDX,RSI,1,64), ZMM(19)) VFMADD231PD(ZMM(20), ZMM(1), MEM(RDX,RSI,2)) VFMADD231PD(ZMM(21), ZMM(1), MEM(RDX,RSI,2,64)) VMOVUPD(MEM(RDX,RSI,2), ZMM(20)) VMOVUPD(MEM(RDX,RSI,2,64), ZMM(21)) VFMADD231PD(ZMM(22), ZMM(1), MEM(RDX,R(13),1)) VFMADD231PD(ZMM(23), ZMM(1), MEM(RDX,R(13),1,64)) VMOVUPD(MEM(RDX,R(13),1), ZMM(22)) VMOVUPD(MEM(RDX,R(13),1,64), ZMM(23)) VFMADD231PD(ZMM(24), ZMM(1), MEM(RDI)) VFMADD231PD(ZMM(25), ZMM(1), MEM(RDI,64)) VMOVUPD(MEM(RDI), ZMM(24)) VMOVUPD(MEM(RDI,64), ZMM(25)) VFMADD231PD(ZMM(26), ZMM(1), MEM(RDI,RSI,1)) VFMADD231PD(ZMM(27), ZMM(1), MEM(RDI,RSI,1,64)) VMOVUPD(MEM(RDI,RSI,1), ZMM(26)) VMOVUPD(MEM(RDI,RSI,1,64), ZMM(27)) VFMADD231PD(ZMM(28), ZMM(1), MEM(RDI,RSI,2)) VFMADD231PD(ZMM(29), ZMM(1), MEM(RDI,RSI,2,64)) VMOVUPD(MEM(RDI,RSI,2), ZMM(28)) VMOVUPD(MEM(RDI,RSI,2,64), ZMM(29)) VFMADD231PD(ZMM(30), ZMM(1), MEM(RDI,R(13),1)) VFMADD231PD(ZMM(31), ZMM(1), MEM(RDI,R(13),1,64)) VMOVUPD(MEM(RDI,R(13),1), ZMM(30)) VMOVUPD(MEM(RDI,R(13),1,64), ZMM(31)) JMP(.DDONE) LABEL(.DROWSTORBZ) VMOVUPD(MEM(RCX), ZMM( 8)) VMOVUPD(MEM(RCX,64), ZMM( 9)) VMOVUPD(MEM(RCX,RSI,1), ZMM(10)) VMOVUPD(MEM(RCX,RSI,1,64), ZMM(11)) VMOVUPD(MEM(RCX,RSI,2), ZMM(12)) VMOVUPD(MEM(RCX,RSI,2,64), ZMM(13)) VMOVUPD(MEM(RCX,R(13),1), ZMM(14)) VMOVUPD(MEM(RCX,R(13),1,64), ZMM(15)) VMOVUPD(MEM(RDX), ZMM(16)) VMOVUPD(MEM(RDX,64), ZMM(17)) VMOVUPD(MEM(RDX,RSI,1), ZMM(18)) VMOVUPD(MEM(RDX,RSI,1,64), ZMM(19)) VMOVUPD(MEM(RDX,RSI,2), ZMM(20)) VMOVUPD(MEM(RDX,RSI,2,64), ZMM(21)) VMOVUPD(MEM(RDX,R(13),1), ZMM(22)) VMOVUPD(MEM(RDX,R(13),1,64), ZMM(23)) VMOVUPD(MEM(RDI), ZMM(24)) VMOVUPD(MEM(RDI,64), ZMM(25)) VMOVUPD(MEM(RDI,RSI,1), ZMM(26)) VMOVUPD(MEM(RDI,RSI,1,64), ZMM(27)) VMOVUPD(MEM(RDI,RSI,2), ZMM(28)) VMOVUPD(MEM(RDI,RSI,2,64), ZMM(29)) VMOVUPD(MEM(RDI,R(13),1), ZMM(30)) VMOVUPD(MEM(RDI,R(13),1,64), ZMM(31)) JMP(.DDONE) LABEL(.DGENSTORED) MOV(RDI, VAR(cs_c)) MOV(RAX, VAR(rs_c)) LEA(RDI, MEM(,RDI,8)) MOV(R(8), MEM(RBX)) VBROADCASTSS(YMM(4), VAR(rs_c)) VMOVAPS(YMM(5), VAR(offsetPtr)) VPMULLD(YMM(4), YMM(5), YMM(4)) LEA(RDX, MEM(RCX,RAX,8)) MOV(RSI, 0x3F) SAL1(R(8)) // shift out the sign bit to check for +/- zero JZ(.DGENSTORBZ) KMOV(K(1), ESI) KMOV(K(2), ESI) VGATHERDPD(ZMM(2) MASK_K(1), MEM(RCX,YMM(4),8)) VGATHERDPD(ZMM(3) MASK_K(2), MEM(RDX,YMM(4),8)) VFMADD231PD(ZMM(2), ZMM(1), ZMM( 8)) VFMADD231PD(ZMM(3), ZMM(1), ZMM( 9)) KMOV(K(1), ESI) KMOV(K(2), ESI) VSCATTERDPD(MEM(RCX,YMM(4),8) MASK_K(1), ZMM( 8)) VSCATTERDPD(MEM(RDX,YMM(4),8) MASK_K(2), ZMM( 9)) ADD(RCX, RDI) ADD(RDX, RDI) KMOV(K(3), ESI) KMOV(K(4), ESI) VGATHERDPD(ZMM(2) MASK_K(3), MEM(RCX,YMM(4),8)) VGATHERDPD(ZMM(3) MASK_K(4), MEM(RDX,YMM(4),8)) VFMADD231PD(ZMM(2), ZMM(1), ZMM(10)) VFMADD231PD(ZMM(3), ZMM(1), ZMM(11)) KMOV(K(3), ESI) KMOV(K(4), ESI) VSCATTERDPD(MEM(RCX,YMM(4),8) MASK_K(3), ZMM(10)) VSCATTERDPD(MEM(RDX,YMM(4),8) MASK_K(4), ZMM(11)) ADD(RCX, RDI) ADD(RDX, RDI) KMOV(K(1), ESI) KMOV(K(2), ESI) VGATHERDPD(ZMM(2) MASK_K(1), MEM(RCX,YMM(4),8)) VGATHERDPD(ZMM(3) MASK_K(2), MEM(RDX,YMM(4),8)) VFMADD231PD(ZMM(2), ZMM(1), ZMM(12)) VFMADD231PD(ZMM(3), ZMM(1), ZMM(13)) KMOV(K(1), ESI) KMOV(K(2), ESI) VSCATTERDPD(MEM(RCX,YMM(4),8) MASK_K(1), ZMM(12)) VSCATTERDPD(MEM(RDX,YMM(4),8) MASK_K(2), ZMM(13)) ADD(RCX, RDI) ADD(RDX, RDI) KMOV(K(3), ESI) KMOV(K(4), ESI) VGATHERDPD(ZMM(2) MASK_K(3), MEM(RCX,YMM(4),8)) VGATHERDPD(ZMM(3) MASK_K(4), MEM(RDX,YMM(4),8)) VFMADD231PD(ZMM(2), ZMM(1), ZMM(14)) VFMADD231PD(ZMM(3), ZMM(1), ZMM(15)) KMOV(K(3), ESI) KMOV(K(4), ESI) VSCATTERDPD(MEM(RCX,YMM(4),8) MASK_K(3), ZMM(14)) VSCATTERDPD(MEM(RDX,YMM(4),8) MASK_K(4), ZMM(15)) ADD(RCX, RDI) ADD(RDX, RDI) KMOV(K(1), ESI) KMOV(K(2), ESI) VGATHERDPD(ZMM(2) MASK_K(1), MEM(RCX,YMM(4),8)) VGATHERDPD(ZMM(3) MASK_K(2), MEM(RDX,YMM(4),8)) VFMADD231PD(ZMM(2), ZMM(1), ZMM(16)) VFMADD231PD(ZMM(3), ZMM(1), ZMM(17)) KMOV(K(1), ESI) KMOV(K(2), ESI) VSCATTERDPD(MEM(RCX,YMM(4),8) MASK_K(1), ZMM(16)) VSCATTERDPD(MEM(RDX,YMM(4),8) MASK_K(2), ZMM(17)) ADD(RCX, RDI) ADD(RDX, RDI) KMOV(K(3), ESI) KMOV(K(4), ESI) VGATHERDPD(ZMM(2) MASK_K(3), MEM(RCX,YMM(4),8)) VGATHERDPD(ZMM(3) MASK_K(4), MEM(RDX,YMM(4),8)) VFMADD231PD(ZMM(2), ZMM(1), ZMM(18)) VFMADD231PD(ZMM(3), ZMM(1), ZMM(19)) KMOV(K(3), ESI) KMOV(K(4), ESI) VSCATTERDPD(MEM(RCX,YMM(4),8) MASK_K(3), ZMM(18)) VSCATTERDPD(MEM(RDX,YMM(4),8) MASK_K(4), ZMM(19)) ADD(RCX, RDI) ADD(RDX, RDI) KMOV(K(1), ESI) KMOV(K(2), ESI) VGATHERDPD(ZMM(2) MASK_K(1), MEM(RCX,YMM(4),8)) VGATHERDPD(ZMM(3) MASK_K(2), MEM(RDX,YMM(4),8)) VFMADD231PD(ZMM(2), ZMM(1), ZMM(20)) VFMADD231PD(ZMM(3), ZMM(1), ZMM(21)) KMOV(K(1), ESI) KMOV(K(2), ESI) VSCATTERDPD(MEM(RCX,YMM(4),8) MASK_K(1), ZMM(20)) VSCATTERDPD(MEM(RDX,YMM(4),8) MASK_K(2), ZMM(21)) ADD(RCX, RDI) ADD(RDX, RDI) KMOV(K(3), ESI) KMOV(K(4), ESI) VGATHERDPD(ZMM(2) MASK_K(3), MEM(RCX,YMM(4),8)) VGATHERDPD(ZMM(3) MASK_K(4), MEM(RDX,YMM(4),8)) VFMADD231PD(ZMM(2), ZMM(1), ZMM(22)) VFMADD231PD(ZMM(3), ZMM(1), ZMM(23)) KMOV(K(3), ESI) KMOV(K(4), ESI) VSCATTERDPD(MEM(RCX,YMM(4),8) MASK_K(3), ZMM(22)) VSCATTERDPD(MEM(RDX,YMM(4),8) MASK_K(4), ZMM(23)) ADD(RCX, RDI) ADD(RDX, RDI) KMOV(K(1), ESI) KMOV(K(2), ESI) VGATHERDPD(ZMM(2) MASK_K(1), MEM(RCX,YMM(4),8)) VGATHERDPD(ZMM(3) MASK_K(2), MEM(RDX,YMM(4),8)) VFMADD231PD(ZMM(2), ZMM(1), ZMM(24)) VFMADD231PD(ZMM(3), ZMM(1), ZMM(25)) KMOV(K(1), ESI) KMOV(K(2), ESI) VSCATTERDPD(MEM(RCX,YMM(4),8) MASK_K(1), ZMM(24)) VSCATTERDPD(MEM(RDX,YMM(4),8) MASK_K(2), ZMM(25)) ADD(RCX, RDI) ADD(RDX, RDI) KMOV(K(3), ESI) KMOV(K(4), ESI) VGATHERDPD(ZMM(2) MASK_K(3), MEM(RCX,YMM(4),8)) VGATHERDPD(ZMM(3) MASK_K(4), MEM(RDX,YMM(4),8)) VFMADD231PD(ZMM(2), ZMM(1), ZMM(26)) VFMADD231PD(ZMM(3), ZMM(1), ZMM(27)) KMOV(K(3), ESI) KMOV(K(4), ESI) VSCATTERDPD(MEM(RCX,YMM(4),8) MASK_K(3), ZMM(26)) VSCATTERDPD(MEM(RDX,YMM(4),8) MASK_K(4), ZMM(27)) ADD(RCX, RDI) ADD(RDX, RDI) KMOV(K(1), ESI) KMOV(K(2), ESI) VGATHERDPD(ZMM(2) MASK_K(1), MEM(RCX,YMM(4),8)) VGATHERDPD(ZMM(3) MASK_K(2), MEM(RDX,YMM(4),8)) VFMADD231PD(ZMM(2), ZMM(1), ZMM(28)) VFMADD231PD(ZMM(3), ZMM(1), ZMM(29)) KMOV(K(1), ESI) KMOV(K(2), ESI) VSCATTERDPD(MEM(RCX,YMM(4),8) MASK_K(1), ZMM(28)) VSCATTERDPD(MEM(RDX,YMM(4),8) MASK_K(2), ZMM(29)) ADD(RCX, RDI) ADD(RDX, RDI) KMOV(K(3), ESI) KMOV(K(4), ESI) VGATHERDPD(ZMM(2) MASK_K(3), MEM(RCX,YMM(4),8)) VGATHERDPD(ZMM(3) MASK_K(4), MEM(RDX,YMM(4),8)) VFMADD231PD(ZMM(2), ZMM(1), ZMM(30)) VFMADD231PD(ZMM(3), ZMM(1), ZMM(31)) KMOV(K(3), ESI) KMOV(K(4), ESI) VSCATTERDPD(MEM(RCX,YMM(4),8) MASK_K(3), ZMM(30)) VSCATTERDPD(MEM(RDX,YMM(4),8) MASK_K(4), ZMM(31)) ADD(RCX, RDI) ADD(RDX, RDI) JMP(.DDONE) LABEL(.DGENSTORBZ) KMOV(K(1), ESI) KMOV(K(2), ESI) VSCATTERDPD(MEM(RCX,YMM(4),8) MASK_K(1), ZMM( 8)) VSCATTERDPD(MEM(RDX,YMM(4),8) MASK_K(2), ZMM( 9)) ADD(RCX, RDI) ADD(RDX, RDI) KMOV(K(1), ESI) KMOV(K(2), ESI) VSCATTERDPD(MEM(RCX,YMM(4),8) MASK_K(1), ZMM(10)) VSCATTERDPD(MEM(RDX,YMM(4),8) MASK_K(2), ZMM(11)) ADD(RCX, RDI) ADD(RDX, RDI) KMOV(K(1), ESI) KMOV(K(2), ESI) VSCATTERDPD(MEM(RCX,YMM(4),8) MASK_K(1), ZMM(12)) VSCATTERDPD(MEM(RDX,YMM(4),8) MASK_K(2), ZMM(13)) ADD(RCX, RDI) ADD(RDX, RDI) KMOV(K(1), ESI) KMOV(K(2), ESI) VSCATTERDPD(MEM(RCX,YMM(4),8) MASK_K(1), ZMM(14)) VSCATTERDPD(MEM(RDX,YMM(4),8) MASK_K(2), ZMM(15)) ADD(RCX, RDI) ADD(RDX, RDI) KMOV(K(1), ESI) KMOV(K(2), ESI) VSCATTERDPD(MEM(RCX,YMM(4),8) MASK_K(1), ZMM(16)) VSCATTERDPD(MEM(RDX,YMM(4),8) MASK_K(2), ZMM(17)) ADD(RCX, RDI) ADD(RDX, RDI) KMOV(K(1), ESI) KMOV(K(2), ESI) VSCATTERDPD(MEM(RCX,YMM(4),8) MASK_K(1), ZMM(18)) VSCATTERDPD(MEM(RDX,YMM(4),8) MASK_K(2), ZMM(19)) ADD(RCX, RDI) ADD(RDX, RDI) KMOV(K(1), ESI) KMOV(K(2), ESI) VSCATTERDPD(MEM(RCX,YMM(4),8) MASK_K(1), ZMM(20)) VSCATTERDPD(MEM(RDX,YMM(4),8) MASK_K(2), ZMM(21)) ADD(RCX, RDI) ADD(RDX, RDI) KMOV(K(1), ESI) KMOV(K(2), ESI) VSCATTERDPD(MEM(RCX,YMM(4),8) MASK_K(1), ZMM(22)) VSCATTERDPD(MEM(RDX,YMM(4),8) MASK_K(2), ZMM(23)) ADD(RCX, RDI) ADD(RDX, RDI) KMOV(K(1), ESI) KMOV(K(2), ESI) VSCATTERDPD(MEM(RCX,YMM(4),8) MASK_K(1), ZMM(24)) VSCATTERDPD(MEM(RDX,YMM(4),8) MASK_K(2), ZMM(25)) ADD(RCX, RDI) ADD(RDX, RDI) KMOV(K(1), ESI) KMOV(K(2), ESI) VSCATTERDPD(MEM(RCX,YMM(4),8) MASK_K(1), ZMM(26)) VSCATTERDPD(MEM(RDX,YMM(4),8) MASK_K(2), ZMM(27)) ADD(RCX, RDI) ADD(RDX, RDI) KMOV(K(1), ESI) KMOV(K(2), ESI) VSCATTERDPD(MEM(RCX,YMM(4),8) MASK_K(1), ZMM(28)) VSCATTERDPD(MEM(RDX,YMM(4),8) MASK_K(2), ZMM(29)) ADD(RCX, RDI) ADD(RDX, RDI) KMOV(K(1), ESI) KMOV(K(2), ESI) VSCATTERDPD(MEM(RCX,YMM(4),8) MASK_K(1), ZMM(30)) VSCATTERDPD(MEM(RDX,YMM(4),8) MASK_K(2), ZMM(31)) ADD(RCX, RDI) ADD(RDX, RDI) LABEL(.DDONE) : // output operands (none) : // input operands [k] "m" (k), [a] "m" (a), [b] "m" (b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c), //[a_next] "m" (a_next), //[b_next] "m" (b_next), [offsetPtr] "m" (offsetPtr) : // register clobber list "rax", "rbx", "rcx", "rdx", "rdi", "rsi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "zmm0", "zmm1", "zmm2", "zmm3", "zmm4", "zmm5", "zmm6", "zmm7", "zmm8", "zmm9", "zmm10", "zmm11", "zmm12", "zmm13", "zmm14", "zmm15", "zmm16", "zmm17", "zmm18", "zmm19", "zmm20", "zmm21", "zmm22", "zmm23", "zmm24", "zmm25", "zmm26", "zmm27", "zmm28", "zmm29", "zmm30", "zmm31", "memory" ); } blis-0.9.0/kernels/knl/3/other/bli_dgemm_knl_asm_30x8.c000066400000000000000000000563231422157504600225530ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 UNIVERSITY OF TEXAS 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. */ #include "blis.h" #include #include "bli_avx512_macros.h" #define UNROLL_K 32 #define SCATTER_PREFETCH_C 1 #define PREFETCH_A_L2 0 #define PREFETCH_B_L2 0 #define L2_PREFETCH_DIST 64 #define A_L1_PREFETCH_DIST 18 #define B_L1_PREFETCH_DIST 18 #define LOOP_ALIGN ALIGN16 #define UPDATE_C_FOUR_ROWS(R1,R2,R3,R4) \ \ VMULPD(ZMM(R1), ZMM(R1), ZMM(0)) \ VMULPD(ZMM(R2), ZMM(R2), ZMM(0)) \ VMULPD(ZMM(R3), ZMM(R3), ZMM(0)) \ VMULPD(ZMM(R4), ZMM(R4), ZMM(0)) \ VFMADD231PD(ZMM(R1), ZMM(1), MEM(RCX )) \ VFMADD231PD(ZMM(R2), ZMM(1), MEM(RCX,RAX,1)) \ VFMADD231PD(ZMM(R3), ZMM(1), MEM(RCX,RAX,2)) \ VFMADD231PD(ZMM(R4), ZMM(1), MEM(RCX,RDI,1)) \ VMOVUPD(MEM(RCX ), ZMM(R1)) \ VMOVUPD(MEM(RCX,RAX,1), ZMM(R2)) \ VMOVUPD(MEM(RCX,RAX,2), ZMM(R3)) \ VMOVUPD(MEM(RCX,RDI,1), ZMM(R4)) \ LEA(RCX, MEM(RCX,RAX,4)) #define UPDATE_C_TWO_ROWS(R1,R2) \ \ VMULPD(ZMM(R1), ZMM(R1), ZMM(0)) \ VMULPD(ZMM(R2), ZMM(R2), ZMM(0)) \ VFMADD231PD(ZMM(R1), ZMM(1), MEM(RCX )) \ VFMADD231PD(ZMM(R2), ZMM(1), MEM(RCX,RAX,1)) \ VMOVUPD(MEM(RCX ), ZMM(R1)) \ VMOVUPD(MEM(RCX,RAX,1), ZMM(R2)) \ LEA(RCX, MEM(RCX,RAX,2)) #define UPDATE_C_BZ_FOUR_ROWS(R1,R2,R3,R4) \ \ VMULPD(ZMM(R1), ZMM(R1), ZMM(0)) \ VMULPD(ZMM(R2), ZMM(R2), ZMM(0)) \ VMULPD(ZMM(R3), ZMM(R3), ZMM(0)) \ VMULPD(ZMM(R4), ZMM(R4), ZMM(0)) \ VMOVUPD(MEM(RCX ), ZMM(R1)) \ VMOVUPD(MEM(RCX,RAX,1), ZMM(R2)) \ VMOVUPD(MEM(RCX,RAX,2), ZMM(R3)) \ VMOVUPD(MEM(RCX,RDI,1), ZMM(R4)) \ LEA(RCX, MEM(RCX,RAX,4)) #define UPDATE_C_BZ_TWO_ROWS(R1,R2) \ \ VMULPD(ZMM(R1), ZMM(R1), ZMM(0)) \ VMULPD(ZMM(R2), ZMM(R2), ZMM(0)) \ VMOVUPD(MEM(RCX ), ZMM(R1)) \ VMOVUPD(MEM(RCX,RAX,1), ZMM(R2)) \ LEA(RCX, MEM(RCX,RAX,2)) #define UPDATE_C_ROW_SCATTERED(NUM) \ \ KXNORW(K(1), K(0), K(0)) \ KXNORW(K(2), K(0), K(0)) \ VGATHERDPD(ZMM(1) MASK_K(1), MEM(RCX,YMM(0),8)) \ VFMADD231PD(ZMM(NUM), ZMM(1), MEM_1TO8(RBX)) \ VSCATTERDPD(MEM(RCX,YMM(0),8) MASK_K(2), ZMM(NUM)) \ ADD(RCX, RAX) #define UPDATE_C_BZ_ROW_SCATTERED(NUM) \ \ KXNORW(K(1), K(0), K(0)) \ VSCATTERDPD(MEM(RCX,YMM(0),8) MASK_K(1), ZMM(NUM)) \ ADD(RCX, RAX) #define PREFETCH_A_L1_1(n) PREFETCH(0, MEM(RAX,(A_L1_PREFETCH_DIST+n)*32*8)) #define PREFETCH_A_L1_2(n) PREFETCH(0, MEM(RAX,(A_L1_PREFETCH_DIST+n)*32*8+64)) #define PREFETCH_A_L1_3(n) PREFETCH(0, MEM(RAX,(A_L1_PREFETCH_DIST+n)*32*8+128)) #define PREFETCH_A_L1_4(n) PREFETCH(0, MEM(RAX,(A_L1_PREFETCH_DIST+n)*32*8+192)) #if PREFETCH_A_L2 #undef PREFETCH_A_L2 #define PREFETCH_A_L2(n) \ \ PREFETCH(1, MEM(RAX,(L2_PREFETCH_DIST+n)*32*8)) \ PREFETCH(1, MEM(RAX,(L2_PREFETCH_DIST+n)*32*8+64)) \ PREFETCH(1, MEM(RAX,(L2_PREFETCH_DIST+n)*32*8+128)) \ PREFETCH(1, MEM(RAX,(L2_PREFETCH_DIST+n)*32*8+192)) #else #undef PREFETCH_A_L2 #define PREFETCH_A_L2(...) #endif #define PREFETCH_B_L1(n) PREFETCH(0, MEM(RBX,(B_L1_PREFETCH_DIST+n)*8*8)) #if PREFETCH_B_L2 #undef PREFETCH_B_L2 #define PREFETCH_B_L2(n) PREFETCH(1, MEM(RBX,(L2_PREFETCH_DIST+n)*8*8)) #else #undef PREFETCH_B_L2 #define PREFETCH_B_L2(...) #endif #define PREFETCH_C_L1_1 #define PREFETCH_C_L1_2 #define PREFETCH_C_L1_3 #define PREFETCH_C_L1_4 // // n: index in unrolled loop // // a: ZMM register to load into // b: ZMM register to read from // // ...: addressing for A, except for offset // #define SUBITER(n,a,b,...) \ \ PREFETCH_A_L2(n) \ \ VMOVAPD(ZMM(a), MEM(RBX,(n+1)*64)) \ VFMADD231PD(ZMM( 2), ZMM(b), MEM_1TO8(__VA_ARGS__,((n%%4)*32+ 0)*8)) \ VFMADD231PD(ZMM( 3), ZMM(b), MEM_1TO8(__VA_ARGS__,((n%%4)*32+ 1)*8)) \ VFMADD231PD(ZMM( 4), ZMM(b), MEM_1TO8(__VA_ARGS__,((n%%4)*32+ 2)*8)) \ PREFETCH_A_L1_1(n) \ VFMADD231PD(ZMM( 5), ZMM(b), MEM_1TO8(__VA_ARGS__,((n%%4)*32+ 3)*8)) \ VFMADD231PD(ZMM( 6), ZMM(b), MEM_1TO8(__VA_ARGS__,((n%%4)*32+ 4)*8)) \ VFMADD231PD(ZMM( 7), ZMM(b), MEM_1TO8(__VA_ARGS__,((n%%4)*32+ 5)*8)) \ PREFETCH_C_L1_1 \ VFMADD231PD(ZMM( 8), ZMM(b), MEM_1TO8(__VA_ARGS__,((n%%4)*32+ 6)*8)) \ VFMADD231PD(ZMM( 9), ZMM(b), MEM_1TO8(__VA_ARGS__,((n%%4)*32+ 7)*8)) \ VFMADD231PD(ZMM(10), ZMM(b), MEM_1TO8(__VA_ARGS__,((n%%4)*32+ 8)*8)) \ PREFETCH_A_L1_2(n) \ VFMADD231PD(ZMM(11), ZMM(b), MEM_1TO8(__VA_ARGS__,((n%%4)*32+ 9)*8)) \ VFMADD231PD(ZMM(12), ZMM(b), MEM_1TO8(__VA_ARGS__,((n%%4)*32+10)*8)) \ VFMADD231PD(ZMM(13), ZMM(b), MEM_1TO8(__VA_ARGS__,((n%%4)*32+11)*8)) \ PREFETCH_C_L1_2 \ VFMADD231PD(ZMM(14), ZMM(b), MEM_1TO8(__VA_ARGS__,((n%%4)*32+12)*8)) \ VFMADD231PD(ZMM(15), ZMM(b), MEM_1TO8(__VA_ARGS__,((n%%4)*32+13)*8)) \ VFMADD231PD(ZMM(16), ZMM(b), MEM_1TO8(__VA_ARGS__,((n%%4)*32+14)*8)) \ PREFETCH_A_L1_3(n) \ VFMADD231PD(ZMM(17), ZMM(b), MEM_1TO8(__VA_ARGS__,((n%%4)*32+15)*8)) \ VFMADD231PD(ZMM(18), ZMM(b), MEM_1TO8(__VA_ARGS__,((n%%4)*32+16)*8)) \ VFMADD231PD(ZMM(19), ZMM(b), MEM_1TO8(__VA_ARGS__,((n%%4)*32+17)*8)) \ PREFETCH_C_L1_3 \ VFMADD231PD(ZMM(20), ZMM(b), MEM_1TO8(__VA_ARGS__,((n%%4)*32+18)*8)) \ VFMADD231PD(ZMM(21), ZMM(b), MEM_1TO8(__VA_ARGS__,((n%%4)*32+19)*8)) \ VFMADD231PD(ZMM(22), ZMM(b), MEM_1TO8(__VA_ARGS__,((n%%4)*32+20)*8)) \ PREFETCH_A_L1_4(n) \ VFMADD231PD(ZMM(23), ZMM(b), MEM_1TO8(__VA_ARGS__,((n%%4)*32+21)*8)) \ VFMADD231PD(ZMM(24), ZMM(b), MEM_1TO8(__VA_ARGS__,((n%%4)*32+22)*8)) \ VFMADD231PD(ZMM(25), ZMM(b), MEM_1TO8(__VA_ARGS__,((n%%4)*32+23)*8)) \ PREFETCH_C_L1_4 \ VFMADD231PD(ZMM(26), ZMM(b), MEM_1TO8(__VA_ARGS__,((n%%4)*32+24)*8)) \ VFMADD231PD(ZMM(27), ZMM(b), MEM_1TO8(__VA_ARGS__,((n%%4)*32+25)*8)) \ VFMADD231PD(ZMM(28), ZMM(b), MEM_1TO8(__VA_ARGS__,((n%%4)*32+26)*8)) \ PREFETCH_B_L1(n) \ VFMADD231PD(ZMM(29), ZMM(b), MEM_1TO8(__VA_ARGS__,((n%%4)*32+27)*8)) \ VFMADD231PD(ZMM(30), ZMM(b), MEM_1TO8(__VA_ARGS__,((n%%4)*32+28)*8)) \ VFMADD231PD(ZMM(31), ZMM(b), MEM_1TO8(__VA_ARGS__,((n%%4)*32+29)*8)) \ PREFETCH_B_L2(n) //This is an array used for the scatter/gather instructions. extern int32_t offsets[32]; //#define MONITORS //#define LOOPMON void bli_dgemm_knl_asm_30x8 ( dim_t k, double* restrict alpha, double* restrict a, double* restrict b, double* restrict beta, double* restrict c, inc_t rs_c, inc_t cs_c, auxinfo_t* restrict data, cntx_t* restrict cntx ) { const int32_t * offsetPtr = &offsets[0]; uint64_t k64 = k; __asm__ volatile ( VPXORD(ZMM(2), ZMM(2), ZMM(2)) //clear out registers VMOVAPS(ZMM( 3), ZMM(2)) VMOVAPS(ZMM( 4), ZMM(2)) VMOVAPS(ZMM( 5), ZMM(2)) VMOVAPS(ZMM( 6), ZMM(2)) VMOVAPS(ZMM( 7), ZMM(2)) VMOVAPS(ZMM( 8), ZMM(2)) VMOVAPS(ZMM( 9), ZMM(2)) MOV(R12, VAR(rs_c)) VMOVAPS(ZMM(10), ZMM(2)) MOV(RSI, VAR(k)) //loop index VMOVAPS(ZMM(11), ZMM(2)) MOV(RAX, VAR(a)) //load address of a VMOVAPS(ZMM(12), ZMM(2)) MOV(RBX, VAR(b)) //load address of b VMOVAPS(ZMM(13), ZMM(2)) MOV(RCX, VAR(c)) //load address of c VMOVAPS(ZMM(14), ZMM(2)) VMOVAPD(ZMM(0), MEM(RBX)) //pre-load b VMOVAPS(ZMM(15), ZMM(2)) MOV(RDI, VAR(offsetPtr)) VMOVAPS(ZMM(16), ZMM(2)) VMOVAPS(ZMM(17), ZMM(2)) VMOVAPS(ZMM(18), ZMM(2)) VMOVAPS(ZMM(19), ZMM(2)) LEA(R13, MEM(R12,R12,2)) VMOVAPS(ZMM(20), ZMM(2)) LEA(R14, MEM(R12,R12,4)) VMOVAPS(ZMM(21), ZMM(2)) LEA(R15, MEM(R13,R12,4)) VMOVAPS(ZMM(22), ZMM(2)) VMOVAPS(ZMM(23), ZMM(2)) VMOVAPS(ZMM(24), ZMM(2)) VMOVAPS(ZMM(25), ZMM(2)) MOV(R8, IMM(4*32*8)) //offset for 4 iterations VMOVAPS(ZMM(26), ZMM(2)) LEA(R9, MEM(R8,R8,2)) //*3 VMOVAPS(ZMM(27), ZMM(2)) LEA(R10, MEM(R8,R8,4)) //*5 VMOVAPS(ZMM(28), ZMM(2)) LEA(R11, MEM(R9,R8,4)) //*7 VMOVAPS(ZMM(29), ZMM(2)) VMOVAPS(ZMM(30), ZMM(2)) VMOVAPS(ZMM(31), ZMM(2)) SUB(RSI, IMM(38)) JLE(TAIL) //prefetch C into L2 #if SCATTER_PREFETCH_C VPBROADCASTD(ZMM(0), R12D) VPBROADCASTD(ZMM(1), R12D) VPMULLD(ZMM(0), ZMM(0), MEM(RDI)) VPMULLD(ZMM(1), ZMM(1), MEM(RDI,64)) ADD(RSI, IMM(30)) KXNORW(K(1), K(0), K(0)) KSHIFTRW(K(2), K(1), IMM(2)) VSCATTERPFDPS(1, MEM(RCX,ZMM(0),8) MASK_K(1)) VSCATTERPFDPS(1, MEM(RCX,ZMM(1),8) MASK_K(2)) VMOVAPD(ZMM(0), MEM(RBX)) #else PREFETCHW1(MEM(RCX )) SUBITER( 0,1,0,RAX ) PREFETCHW1(MEM(RCX,R12,1)) SUBITER( 1,0,1,RAX ) PREFETCHW1(MEM(RCX,R12,2)) SUBITER( 2,1,0,RAX ) PREFETCHW1(MEM(RCX,R13,1)) SUBITER( 3,0,1,RAX ) PREFETCHW1(MEM(RCX,R12,4)) SUBITER( 4,1,0,RAX,R8, 1) PREFETCHW1(MEM(RCX,R14,1)) SUBITER( 5,0,1,RAX,R8, 1) PREFETCHW1(MEM(RCX,R13,2)) SUBITER( 6,1,0,RAX,R8, 1) PREFETCHW1(MEM(RCX,R15,1)) LEA(RDX, MEM(RCX,R12,8)) SUBITER( 7,0,1,RAX,R8, 1) PREFETCHW1(MEM(RDX )) SUBITER( 8,1,0,RAX,R8, 2) PREFETCHW1(MEM(RDX,R12,1)) SUBITER( 9,0,1,RAX,R8, 2) PREFETCHW1(MEM(RDX,R12,2)) SUBITER(10,1,0,RAX,R8, 2) PREFETCHW1(MEM(RDX,R13,1)) SUBITER(11,0,1,RAX,R8, 2) PREFETCHW1(MEM(RDX,R12,4)) SUBITER(12,1,0,RAX,R9, 1) PREFETCHW1(MEM(RDX,R14,1)) SUBITER(13,0,1,RAX,R9, 1) PREFETCHW1(MEM(RDX,R13,2)) SUBITER(14,1,0,RAX,R9, 1) PREFETCHW1(MEM(RDX,R15,1)) LEA(RDX, MEM(RDX,R12,8)) SUBITER(15,0,1,RAX,R9, 1) PREFETCHW1(MEM(RDX )) SUBITER(16,1,0,RAX,R8, 4) PREFETCHW1(MEM(RDX,R12,1)) SUBITER(17,0,1,RAX,R8, 4) PREFETCHW1(MEM(RDX,R12,2)) SUBITER(18,1,0,RAX,R8, 4) PREFETCHW1(MEM(RDX,R13,1)) SUBITER(19,0,1,RAX,R8, 4) PREFETCHW1(MEM(RDX,R12,4)) SUBITER(20,1,0,RAX,R10,1) PREFETCHW1(MEM(RDX,R14,1)) SUBITER(21,0,1,RAX,R10,1) PREFETCHW1(MEM(RDX,R13,2)) SUBITER(22,1,0,RAX,R10,1) PREFETCHW1(MEM(RDX,R15,1)) LEA(RDX, MEM(RDX,R12,8)) SUBITER(23,0,1,RAX,R10,1) PREFETCHW1(MEM(RDX )) SUBITER(24,1,0,RAX,R9, 2) PREFETCHW1(MEM(RDX,R12,1)) SUBITER(25,0,1,RAX,R9, 2) PREFETCHW1(MEM(RDX,R12,2)) SUBITER(26,1,0,RAX,R9, 2) PREFETCHW1(MEM(RDX,R13,1)) SUBITER(27,0,1,RAX,R9, 2) PREFETCHW1(MEM(RDX,R12,4)) SUBITER(28,1,0,RAX,R11,1) PREFETCHW1(MEM(RDX,R14,1)) SUBITER(29,0,1,RAX,R11,1) ADD(RAX, IMM(30*32*8)) ADD(RBX, IMM(30* 8*8)) #endif MOV(RDI, RSI) AND(RDI, IMM(31)) SAR(RSI, IMM(5)) JZ(REM_1) LOOP_ALIGN LABEL(MAIN_LOOP) SUBITER( 0,1,0,RAX ) SUBITER( 1,0,1,RAX ) SUBITER( 2,1,0,RAX ) SUBITER( 3,0,1,RAX ) SUBITER( 4,1,0,RAX,R8, 1) SUBITER( 5,0,1,RAX,R8, 1) SUBITER( 6,1,0,RAX,R8, 1) SUBITER( 7,0,1,RAX,R8, 1) SUBITER( 8,1,0,RAX,R8, 2) SUBITER( 9,0,1,RAX,R8, 2) SUBITER(10,1,0,RAX,R8, 2) SUBITER(11,0,1,RAX,R8, 2) SUBITER(12,1,0,RAX,R9, 1) SUBITER(13,0,1,RAX,R9, 1) SUBITER(14,1,0,RAX,R9, 1) SUBITER(15,0,1,RAX,R9, 1) SUBITER(16,1,0,RAX,R8, 4) SUBITER(17,0,1,RAX,R8, 4) SUBITER(18,1,0,RAX,R8, 4) SUBITER(19,0,1,RAX,R8, 4) SUBITER(20,1,0,RAX,R10,1) SUBITER(21,0,1,RAX,R10,1) SUBITER(22,1,0,RAX,R10,1) SUBITER(23,0,1,RAX,R10,1) SUBITER(24,1,0,RAX,R9, 2) SUBITER(25,0,1,RAX,R9, 2) SUBITER(26,1,0,RAX,R9, 2) SUBITER(27,0,1,RAX,R9, 2) SUBITER(28,1,0,RAX,R11,1) SUBITER(29,0,1,RAX,R11,1) SUBITER(30,1,0,RAX,R11,1) SUBITER(31,0,1,RAX,R11,1) ADD(RAX, IMM(32*32*8)) ADD(RBX, IMM(32* 8*8)) SUB(RSI, IMM(1)) JNZ(MAIN_LOOP) LABEL(REM_1) SAR1(RDI) JNC(REM_2) SUBITER(0,1,0,RAX) VMOVAPD(ZMM(0), ZMM(1)) ADD(RAX, IMM(32*8)) ADD(RBX, IMM( 8*8)) LABEL(REM_2) SAR1(RDI) JNC(REM_4) SUBITER(0,1,0,RAX) SUBITER(1,0,1,RAX) ADD(RAX, IMM(2*32*8)) ADD(RBX, IMM(2* 8*8)) LABEL(REM_4) SAR1(RDI) JNC(REM_8) SUBITER(0,1,0,RAX) SUBITER(1,0,1,RAX) SUBITER(2,1,0,RAX) SUBITER(3,0,1,RAX) ADD(RAX, IMM(4*32*8)) ADD(RBX, IMM(4* 8*8)) LABEL(REM_8) SAR1(RDI) JNC(REM_16) SUBITER(0,1,0,RAX ) SUBITER(1,0,1,RAX ) SUBITER(2,1,0,RAX ) SUBITER(3,0,1,RAX ) SUBITER(4,1,0,RAX,R8,1) SUBITER(5,0,1,RAX,R8,1) SUBITER(6,1,0,RAX,R8,1) SUBITER(7,0,1,RAX,R8,1) ADD(RAX, IMM(8*32*8)) ADD(RBX, IMM(8* 8*8)) LABEL(REM_16) SAR1(RDI) JNC(AFTER_LOOP) SUBITER( 0,1,0,RAX ) SUBITER( 1,0,1,RAX ) SUBITER( 2,1,0,RAX ) SUBITER( 3,0,1,RAX ) SUBITER( 4,1,0,RAX,R8, 1) SUBITER( 5,0,1,RAX,R8, 1) SUBITER( 6,1,0,RAX,R8, 1) SUBITER( 7,0,1,RAX,R8, 1) SUBITER( 8,1,0,RAX,R8, 2) SUBITER( 9,0,1,RAX,R8, 2) SUBITER(10,1,0,RAX,R8, 2) SUBITER(11,0,1,RAX,R8, 2) SUBITER(12,1,0,RAX,R9, 1) SUBITER(13,0,1,RAX,R9, 1) SUBITER(14,1,0,RAX,R9, 1) SUBITER(15,0,1,RAX,R9, 1) ADD(RAX, IMM(16*32*8)) ADD(RBX, IMM(16* 8*8)) LABEL(AFTER_LOOP) //prefetch C into L1 #if SCATTER_PREFETCH_C MOV(RDI, VAR(offsetPtr)) VPBROADCASTD(ZMM(0), R12D) VPBROADCASTD(ZMM(1), R12D) VPMULLD(ZMM(0), ZMM(0), MEM(RDI)) VPMULLD(ZMM(1), ZMM(1), MEM(RDI,64)) KXNORW(K(1), K(0), K(0)) KSHIFTRW(K(2), K(1), IMM(2)) VSCATTERPFDPS(0, MEM(RCX,ZMM(0),8) MASK_K(1)) VSCATTERPFDPS(0, MEM(RCX,ZMM(1),8) MASK_K(2)) VMOVAPD(ZMM(0), MEM(RBX)) SUBITER(0,1,0,RAX ) SUBITER(1,0,1,RAX ) SUBITER(2,1,0,RAX ) SUBITER(3,0,1,RAX ) SUBITER(4,1,0,RAX,R8,1) SUBITER(5,0,1,RAX,R8,1) SUBITER(6,1,0,RAX,R8,1) SUBITER(7,0,1,RAX,R8,1) #else #undef PREFETCH_C_L1_1 #undef PREFETCH_C_L1_2 #undef PREFETCH_C_L1_3 #undef PREFETCH_C_L1_4 #define PREFETCH_C_L1_1 PREFETCHW0(MEM(RCX )) #define PREFETCH_C_L1_2 PREFETCHW0(MEM(RCX,R12,1)) #define PREFETCH_C_L1_3 PREFETCHW0(MEM(RCX,R12,2)) #define PREFETCH_C_L1_4 PREFETCHW0(MEM(RCX,R13,1)) SUBITER(0,1,0,RAX ) #undef PREFETCH_C_L1_1 #undef PREFETCH_C_L1_2 #undef PREFETCH_C_L1_3 #undef PREFETCH_C_L1_4 #define PREFETCH_C_L1_1 PREFETCHW0(MEM(RCX,R12,4)) #define PREFETCH_C_L1_2 PREFETCHW0(MEM(RCX,R14,1)) #define PREFETCH_C_L1_3 PREFETCHW0(MEM(RCX,R13,2)) #define PREFETCH_C_L1_4 PREFETCHW0(MEM(RCX,R15,1)) SUBITER(1,0,1,RAX ) LEA(RDX, MEM(RCX,R12,8)) #undef PREFETCH_C_L1_1 #undef PREFETCH_C_L1_2 #undef PREFETCH_C_L1_3 #undef PREFETCH_C_L1_4 #define PREFETCH_C_L1_1 PREFETCHW0(MEM(RDX )) #define PREFETCH_C_L1_2 PREFETCHW0(MEM(RDX,R12,1)) #define PREFETCH_C_L1_3 PREFETCHW0(MEM(RDX,R12,2)) #define PREFETCH_C_L1_4 PREFETCHW0(MEM(RDX,R13,1)) SUBITER(2,1,0,RAX ) #undef PREFETCH_C_L1_1 #undef PREFETCH_C_L1_2 #undef PREFETCH_C_L1_3 #undef PREFETCH_C_L1_4 #define PREFETCH_C_L1_1 PREFETCHW0(MEM(RDX,R12,4)) #define PREFETCH_C_L1_2 PREFETCHW0(MEM(RDX,R14,1)) #define PREFETCH_C_L1_3 PREFETCHW0(MEM(RDX,R13,2)) #define PREFETCH_C_L1_4 PREFETCHW0(MEM(RDX,R15,1)) SUBITER(3,0,1,RAX ) LEA(RDX, MEM(RDX,R12,8)) #undef PREFETCH_C_L1_1 #undef PREFETCH_C_L1_2 #undef PREFETCH_C_L1_3 #undef PREFETCH_C_L1_4 #define PREFETCH_C_L1_1 PREFETCHW0(MEM(RDX )) #define PREFETCH_C_L1_2 PREFETCHW0(MEM(RDX,R12,1)) #define PREFETCH_C_L1_3 PREFETCHW0(MEM(RDX,R12,2)) #define PREFETCH_C_L1_4 PREFETCHW0(MEM(RDX,R13,1)) SUBITER(4,1,0,RAX,R8,1) #undef PREFETCH_C_L1_1 #undef PREFETCH_C_L1_2 #undef PREFETCH_C_L1_3 #undef PREFETCH_C_L1_4 #define PREFETCH_C_L1_1 PREFETCHW0(MEM(RDX,R12,4)) #define PREFETCH_C_L1_2 PREFETCHW0(MEM(RDX,R14,1)) #define PREFETCH_C_L1_3 PREFETCHW0(MEM(RDX,R13,2)) #define PREFETCH_C_L1_4 PREFETCHW0(MEM(RDX,R15,1)) SUBITER(5,0,1,RAX,R8,1) LEA(RDX, MEM(RDX,R12,8)) #undef PREFETCH_C_L1_1 #undef PREFETCH_C_L1_2 #undef PREFETCH_C_L1_3 #undef PREFETCH_C_L1_4 #define PREFETCH_C_L1_1 PREFETCHW0(MEM(RDX )) #define PREFETCH_C_L1_2 PREFETCHW0(MEM(RDX,R12,1)) #define PREFETCH_C_L1_3 PREFETCHW0(MEM(RDX,R12,2)) #define PREFETCH_C_L1_4 PREFETCHW0(MEM(RDX,R13,1)) SUBITER(6,1,0,RAX,R8,1) #undef PREFETCH_C_L1_1 #undef PREFETCH_C_L1_2 #undef PREFETCH_C_L1_3 #undef PREFETCH_C_L1_4 #define PREFETCH_C_L1_1 PREFETCHW0(MEM(RDX,R12,4)) #define PREFETCH_C_L1_2 PREFETCHW0(MEM(RDX,R14,1)) #define PREFETCH_C_L1_3 #define PREFETCH_C_L1_4 SUBITER(7,0,1,RAX,R8,1) #endif JMP(POSTACCUM) LABEL(TAIL) MOV(RDX, RCX) ADD(RSI, IMM(38)) LABEL(TAIL_LOOP) PREFETCHW0(MEM(RDX)) ADD(RDX, R12) SUBITER(0,1,0,RAX) VMOVAPD(ZMM(0), ZMM(1)) ADD(RAX, IMM(32*8)) ADD(RBX, IMM( 8*8)) SUB(RSI, IMM(1)) JNZ(TAIL_LOOP) LABEL(POSTACCUM) MOV(RAX, VAR(alpha)) MOV(RBX, VAR(beta)) VBROADCASTSD(ZMM(0), MEM(RAX)) VBROADCASTSD(ZMM(1), MEM(RBX)) // Check if C is row stride. If not, jump to the slow scattered update MOV(RAX, VAR(rs_c)) LEA(RAX, MEM(,RAX,8)) MOV(RBX, VAR(cs_c)) LEA(RDI, MEM(RAX,RAX,2)) CMP(RBX, IMM(1)) JNE(SCATTEREDUPDATE) VMOVQ(RDX, XMM(1)) SAL1(RDX) //shift out sign bit JZ(COLSTORBZ) UPDATE_C_FOUR_ROWS( 2, 3, 4, 5) UPDATE_C_FOUR_ROWS( 6, 7, 8, 9) UPDATE_C_FOUR_ROWS(10,11,12,13) UPDATE_C_FOUR_ROWS(14,15,16,17) UPDATE_C_FOUR_ROWS(18,19,20,21) UPDATE_C_FOUR_ROWS(22,23,24,25) UPDATE_C_FOUR_ROWS(26,27,28,29) UPDATE_C_TWO_ROWS (30,31) JMP(END) LABEL(COLSTORBZ) UPDATE_C_BZ_FOUR_ROWS( 2, 3, 4, 5) UPDATE_C_BZ_FOUR_ROWS( 6, 7, 8, 9) UPDATE_C_BZ_FOUR_ROWS(10,11,12,13) UPDATE_C_BZ_FOUR_ROWS(14,15,16,17) UPDATE_C_BZ_FOUR_ROWS(18,19,20,21) UPDATE_C_BZ_FOUR_ROWS(22,23,24,25) UPDATE_C_BZ_FOUR_ROWS(26,27,28,29) UPDATE_C_BZ_TWO_ROWS (30,31) JMP(END) LABEL(SCATTEREDUPDATE) VMULPD(ZMM( 2), ZMM( 2), ZMM(0)) VMULPD(ZMM( 3), ZMM( 3), ZMM(0)) VMULPD(ZMM( 4), ZMM( 4), ZMM(0)) VMULPD(ZMM( 5), ZMM( 5), ZMM(0)) VMULPD(ZMM( 6), ZMM( 6), ZMM(0)) VMULPD(ZMM( 7), ZMM( 7), ZMM(0)) VMULPD(ZMM( 8), ZMM( 8), ZMM(0)) VMULPD(ZMM( 9), ZMM( 9), ZMM(0)) VMULPD(ZMM(10), ZMM(10), ZMM(0)) VMULPD(ZMM(11), ZMM(11), ZMM(0)) VMULPD(ZMM(12), ZMM(12), ZMM(0)) VMULPD(ZMM(13), ZMM(13), ZMM(0)) VMULPD(ZMM(14), ZMM(14), ZMM(0)) VMULPD(ZMM(15), ZMM(15), ZMM(0)) VMULPD(ZMM(16), ZMM(16), ZMM(0)) VMULPD(ZMM(17), ZMM(17), ZMM(0)) VMULPD(ZMM(18), ZMM(18), ZMM(0)) VMULPD(ZMM(19), ZMM(19), ZMM(0)) VMULPD(ZMM(20), ZMM(20), ZMM(0)) VMULPD(ZMM(21), ZMM(21), ZMM(0)) VMULPD(ZMM(22), ZMM(22), ZMM(0)) VMULPD(ZMM(23), ZMM(23), ZMM(0)) VMULPD(ZMM(24), ZMM(24), ZMM(0)) VMULPD(ZMM(25), ZMM(25), ZMM(0)) VMULPD(ZMM(26), ZMM(26), ZMM(0)) VMULPD(ZMM(27), ZMM(27), ZMM(0)) VMULPD(ZMM(28), ZMM(28), ZMM(0)) VMULPD(ZMM(29), ZMM(29), ZMM(0)) VMULPD(ZMM(30), ZMM(30), ZMM(0)) VMULPD(ZMM(31), ZMM(31), ZMM(0)) VMOVQ(RDX, XMM(1)) /* Note that this ignores the upper 32 bits in cs_c */ MOV(RDI, VAR(offsetPtr)) VPBROADCASTD(ZMM(0), EBX) VPMULLD(ZMM(0), ZMM(0), MEM(RDI)) MOV(RBX, VAR(beta)) SAL1(RDX) //shift out sign bit JZ(SCATTERBZ) UPDATE_C_ROW_SCATTERED( 2) UPDATE_C_ROW_SCATTERED( 3) UPDATE_C_ROW_SCATTERED( 4) UPDATE_C_ROW_SCATTERED( 5) UPDATE_C_ROW_SCATTERED( 6) UPDATE_C_ROW_SCATTERED( 7) UPDATE_C_ROW_SCATTERED( 8) UPDATE_C_ROW_SCATTERED( 9) UPDATE_C_ROW_SCATTERED(10) UPDATE_C_ROW_SCATTERED(11) UPDATE_C_ROW_SCATTERED(12) UPDATE_C_ROW_SCATTERED(13) UPDATE_C_ROW_SCATTERED(14) UPDATE_C_ROW_SCATTERED(15) UPDATE_C_ROW_SCATTERED(16) UPDATE_C_ROW_SCATTERED(17) UPDATE_C_ROW_SCATTERED(18) UPDATE_C_ROW_SCATTERED(19) UPDATE_C_ROW_SCATTERED(20) UPDATE_C_ROW_SCATTERED(21) UPDATE_C_ROW_SCATTERED(22) UPDATE_C_ROW_SCATTERED(23) UPDATE_C_ROW_SCATTERED(24) UPDATE_C_ROW_SCATTERED(25) UPDATE_C_ROW_SCATTERED(26) UPDATE_C_ROW_SCATTERED(27) UPDATE_C_ROW_SCATTERED(28) UPDATE_C_ROW_SCATTERED(29) UPDATE_C_ROW_SCATTERED(30) UPDATE_C_ROW_SCATTERED(31) JMP(END) LABEL(SCATTERBZ) UPDATE_C_BZ_ROW_SCATTERED( 2) UPDATE_C_BZ_ROW_SCATTERED( 3) UPDATE_C_BZ_ROW_SCATTERED( 4) UPDATE_C_BZ_ROW_SCATTERED( 5) UPDATE_C_BZ_ROW_SCATTERED( 6) UPDATE_C_BZ_ROW_SCATTERED( 7) UPDATE_C_BZ_ROW_SCATTERED( 8) UPDATE_C_BZ_ROW_SCATTERED( 9) UPDATE_C_BZ_ROW_SCATTERED(10) UPDATE_C_BZ_ROW_SCATTERED(11) UPDATE_C_BZ_ROW_SCATTERED(12) UPDATE_C_BZ_ROW_SCATTERED(13) UPDATE_C_BZ_ROW_SCATTERED(14) UPDATE_C_BZ_ROW_SCATTERED(15) UPDATE_C_BZ_ROW_SCATTERED(16) UPDATE_C_BZ_ROW_SCATTERED(17) UPDATE_C_BZ_ROW_SCATTERED(18) UPDATE_C_BZ_ROW_SCATTERED(19) UPDATE_C_BZ_ROW_SCATTERED(20) UPDATE_C_BZ_ROW_SCATTERED(21) UPDATE_C_BZ_ROW_SCATTERED(22) UPDATE_C_BZ_ROW_SCATTERED(23) UPDATE_C_BZ_ROW_SCATTERED(24) UPDATE_C_BZ_ROW_SCATTERED(25) UPDATE_C_BZ_ROW_SCATTERED(26) UPDATE_C_BZ_ROW_SCATTERED(27) UPDATE_C_BZ_ROW_SCATTERED(28) UPDATE_C_BZ_ROW_SCATTERED(29) UPDATE_C_BZ_ROW_SCATTERED(30) UPDATE_C_BZ_ROW_SCATTERED(31) LABEL(END) : // output operands : // input operands [k] "m" (k64), [a] "m" (a), [b] "m" (b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c), [offsetPtr] "m" (offsetPtr) : // register clobber list "rax", "rbx", "rcx", "rdx", "rdi", "rsi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "zmm0", "zmm1", "zmm2", "zmm3", "zmm4", "zmm5", "zmm6", "zmm7", "zmm8", "zmm9", "zmm10", "zmm11", "zmm12", "zmm13", "zmm14", "zmm15", "zmm16", "zmm17", "zmm18", "zmm19", "zmm20", "zmm21", "zmm22", "zmm23", "zmm24", "zmm25", "zmm26", "zmm27", "zmm28", "zmm29", "zmm30", "zmm31", "memory" ); } blis-0.9.0/kernels/knl/3/other/bli_dgemm_knl_asm_30x8_knc.c000066400000000000000000000371001422157504600233760ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 UNIVERSITY OF TEXAS 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. */ #include "blis.h" #include #include "bli_avx512_macros.h" #define A_L1_PREFETCH_DIST 4 #define B_L1_PREFETCH_DIST 2 #define L2_PREFETCH_DIST 16 // Must be greater than 10, because of the way the loop is constructed. //Alternate code path uused if C is not row-major // r9 = c // ymm0 = cs_c * 1...8 // r11 = rs_c // r12 = &alpha // r13 = &beta #define UPDATE_C_ROW_SCATTERED_(NUM,BNZ1,BNZ2) \ \ BNZ1 KXNORW(K(2), K(0), K(0)) BNZ2 \ KXNORW(K(3), K(0), K(0)) \ BNZ1 VGATHERDPD(ZMM(31) MASK_K(2), MEM(R(9),YMM(0),8)) BNZ2 \ VMULPD(ZMM(NUM), ZMM(NUM), MEM_1TO8(R(12))) /*scale by alpha*/ \ BNZ1 VFMADD231PD(ZMM(NUM), ZMM(31), MEM_1TO8(R(13))) BNZ2 /*scale by beta, add in result*/ \ VSCATTERDPD(MEM(R(9),YMM(0),8) MASK_K(3), ZMM(NUM)) \ ADD(R(9), R(11)) #define UPDATE_C_ROW_SCATTERED(NUM) UPDATE_C_ROW_SCATTERED_(NUM,,) #define UPDATE_C_BZ_ROW_SCATTERED(NUM) UPDATE_C_ROW_SCATTERED_(NUM,COMMENT_BEGIN,COMMENT_END) // r12 = &alpha // zmm31 = beta // r9 = c // r11 = rs_c // r10 = 3*rs_c // rdi = 4*rs_c #define UPDATE_C_4_ROWS_(R1,R2,R3,R4,BNZ1,BNZ2) \ \ VMULPD(ZMM(R1), ZMM(R1), MEM_1TO8(R(12))) \ VMULPD(ZMM(R2), ZMM(R2), MEM_1TO8(R(12))) \ VMULPD(ZMM(R3), ZMM(R3), MEM_1TO8(R(12))) \ VMULPD(ZMM(R4), ZMM(R4), MEM_1TO8(R(12))) \ BNZ1 VFMADD231PD(ZMM(R1), ZMM(31), MEM(R(9) )) BNZ2 \ BNZ1 VFMADD231PD(ZMM(R2), ZMM(31), MEM(R(9),R(11),1)) BNZ2 \ BNZ1 VFMADD231PD(ZMM(R3), ZMM(31), MEM(R(9),R(11),2)) BNZ2 \ BNZ1 VFMADD231PD(ZMM(R4), ZMM(31), MEM(R(9),R(10),1)) BNZ2 \ VMOVUPD(MEM(R(9) ), ZMM(R1)) \ VMOVUPD(MEM(R(9),R(11),1), ZMM(R2)) \ VMOVUPD(MEM(R(9),R(11),2), ZMM(R3)) \ VMOVUPD(MEM(R(9),R(10),1), ZMM(R4)) \ ADD(R(9), RDI) // r12 = &alpha // zmm31 = beta // r9 = c // r11 = rs_c #define UPDATE_C_2_ROWS_(R1,R2,BNZ1,BNZ2) \ \ VMULPD(ZMM(R1), ZMM(R1), MEM_1TO8(R(12))) \ VMULPD(ZMM(R2), ZMM(R2), MEM_1TO8(R(12))) \ BNZ1 VFMADD231PD(ZMM(R1), ZMM(31), MEM(R(9) )) BNZ2 \ BNZ1 VFMADD231PD(ZMM(R2), ZMM(31), MEM(R(9),R(11),1)) BNZ2 \ VMOVUPD(MEM(R(9) ), ZMM(R1)) \ VMOVUPD(MEM(R(9),R(11),1), ZMM(R2)) \ #define UPDATE_C_4_ROWS(R1,R2,R3,R4) UPDATE_C_4_ROWS_(R1,R2,R3,R4,,) #define UPDATE_C_2_ROWS(R1,R2) UPDATE_C_2_ROWS_(R1,R2,,) #define UPDATE_C_BZ_4_ROWS(R1,R2,R3,R4) UPDATE_C_4_ROWS_(R1,R2,R3,R4,COMMENT_BEGIN,COMMENT_END) #define UPDATE_C_BZ_2_ROWS(R1,R2) UPDATE_C_2_ROWS_(R1,R2,COMMENT_BEGIN,COMMENT_END) #define A_TIMES_B_ROW(n) VFMADD231PD(ZMM(n), ZMM(31), MEM_1TO8(R(15),(n-1)*8)) #define A_TIMES_B_ROW_PREV(n) VFMADD231PD(ZMM(n), ZMM(31), MEM_1TO8(R(15),((n-1)-32)*8)) #define PREFETCH_A_L1(n) PREFETCH(0, MEM(R(15),A_L1_PREFETCH_DIST*8*32+n*64)) #define PREFETCH_A_L2(n) PREFETCH(1, MEM(R(15),R(14),1,n*64)) #define PREFETCH_B_L1 PREFETCH(0, MEM(RBX,B_L1_PREFETCH_DIST*8*8)) #define PREFETCH_B_L2 PREFETCH(1, MEM(RBX,R(13),1)) //One iteration of the k_r loop. //Each iteration, we prefetch A into L1 and into L2 // r15 = a // rbx = b // rcx = c // r11 = rs_c // r13 = L2_PREFETCH_DIST*8*8 // r14 = L2_PREFETCH_DIST*8*32 // r12 = 32*8 = dist. to next sliver of a // r9 = 8*8 = dist. to next sliver of b #define MAIN_LOOP_(COUNTER, PC_L1_1, PC_L1_2, PC_L2_1, PC_L2_2) \ \ /* Can this be pre-loaded for next it. in zmm0? */ \ VMOVAPD(ZMM(31), MEM(RBX)) \ \ A_TIMES_B_ROW ( 1) \ A_TIMES_B_ROW ( 2) PREFETCH_A_L1(0) \ A_TIMES_B_ROW ( 3) PREFETCH_A_L1(1) \ A_TIMES_B_ROW ( 4) PREFETCH_A_L1(2) \ A_TIMES_B_ROW ( 5) PREFETCH_A_L1(3) \ A_TIMES_B_ROW ( 6) PREFETCH_A_L2(0) \ A_TIMES_B_ROW ( 7) PC_L1_1 PREFETCH(0, MEM(RCX)) PC_L1_2 \ A_TIMES_B_ROW ( 8) PC_L1_1 ADD(RCX, R(11)) PC_L1_2 \ A_TIMES_B_ROW ( 9) \ A_TIMES_B_ROW (10) PC_L2_1 PREFETCH(1, MEM(RCX)) PC_L2_2 \ A_TIMES_B_ROW (11) PREFETCH_A_L2(1) \ A_TIMES_B_ROW (12) PC_L1_1 PREFETCH(0, MEM(RCX)) PC_L1_2 \ A_TIMES_B_ROW (13) PC_L1_1 ADD(RCX, R(11)) PC_L1_2 \ A_TIMES_B_ROW (14) \ A_TIMES_B_ROW (15) \ A_TIMES_B_ROW (16) PREFETCH_A_L2(2) \ A_TIMES_B_ROW (17) PC_L1_1 PREFETCH(0, MEM(RCX)) PC_L1_2 \ A_TIMES_B_ROW (18) PC_L1_1 ADD(RCX, R(11)) PC_L1_2 \ A_TIMES_B_ROW (19) \ A_TIMES_B_ROW (20) \ A_TIMES_B_ROW (21) PREFETCH_A_L2(3) \ A_TIMES_B_ROW (22) ADD(R(15), R(12)) \ A_TIMES_B_ROW_PREV(23) \ A_TIMES_B_ROW_PREV(24) PC_L2_1 ADD(RCX, R(11)) PC_L2_2 \ A_TIMES_B_ROW_PREV(25) DEC(COUNTER) \ A_TIMES_B_ROW_PREV(26) PREFETCH_B_L2 \ A_TIMES_B_ROW_PREV(27) PREFETCH_B_L1 \ A_TIMES_B_ROW_PREV(28) ADD(RBX, R(9)) \ A_TIMES_B_ROW_PREV(29) CMP(COUNTER, IMM(0)) \ A_TIMES_B_ROW_PREV(30) #define MAIN_LOOP(COUNTER) MAIN_LOOP_(COUNTER,COMMENT_BEGIN,COMMENT_END,COMMENT_BEGIN,COMMENT_END) #define MAIN_LOOP_PC_L1(COUNTER) MAIN_LOOP_(COUNTER,,,COMMENT_BEGIN,COMMENT_END) #define MAIN_LOOP_PC_L2(COUNTER) MAIN_LOOP_(COUNTER,COMMENT_BEGIN,COMMENT_END,,) //This is an array used for the scatter/gather instructions. extern int32_t offsets[16]; //#define MONITORS //#define LOOPMON void bli_dgemm_knl_asm_30x8_knc ( dim_t k, double* restrict alpha, double* restrict a, double* restrict b, double* restrict beta, double* restrict c, inc_t rs_c, inc_t cs_c, auxinfo_t* restrict data, cntx_t* restrict cntx ) { const double * a_next = bli_auxinfo_next_a( data ); const double * b_next = bli_auxinfo_next_b( data ); const int32_t * offsetPtr = &offsets[0]; #ifdef MONITORS int toph, topl, both, botl, midl, midh, mid2l, mid2h; #endif #ifdef LOOPMON int tlooph, tloopl, blooph, bloopl; #endif __asm__ volatile ( #ifdef MONITORS RDTSC MOV(VAR(topl), EAX) MOV(VAR(toph), EDX) #endif VPXORD(ZMM(1), ZMM(1), ZMM(1)) //clear out registers VMOVAPS(ZMM( 2), ZMM(1)) VMOVAPS(ZMM( 3), ZMM(1)) MOV(RSI, VAR(k)) //loop index VMOVAPS(ZMM( 4), ZMM(1)) MOV(R(11), VAR(rs_c)) //load row stride VMOVAPS(ZMM( 5), ZMM(1)) SAL(R(11), IMM(3)) //scale row stride VMOVAPS(ZMM( 6), ZMM(1)) MOV(R(15), VAR(a)) //load address of a VMOVAPS(ZMM( 7), ZMM(1)) MOV(RBX, VAR(b)) //load address of b VMOVAPS(ZMM( 8), ZMM(1)) VMOVAPS(ZMM( 9), ZMM(1)) LEA(R(10), MEM(R(11),R(11),2)) //r10 has 3 * r11 VMOVAPS(ZMM(10), ZMM(1)) VMOVAPS(ZMM(11), ZMM(1)) MOV(RDI, R(11)) VMOVAPS(ZMM(12), ZMM(1)) SAL(RDI, IMM(2)) //rdi has 4*r11 VMOVAPS(ZMM(13), ZMM(1)) MOV(RCX, VAR(c)) //load address of c for prefetching VMOVAPS(ZMM(14), ZMM(1)) VMOVAPS(ZMM(15), ZMM(1)) MOV(R(8), VAR(k)) VMOVAPS(ZMM(16), ZMM(1)) VMOVAPS(ZMM(17), ZMM(1)) VMOVAPS(ZMM(18), ZMM(1)) MOV(R(13), IMM(8*8*L2_PREFETCH_DIST)) VMOVAPS(ZMM(19), ZMM(1)) MOV(R(14), IMM(8*32*L2_PREFETCH_DIST)) VMOVAPS(ZMM(20), ZMM(1)) VMOVAPS(ZMM(21), ZMM(1)) VMOVAPS(ZMM(22), ZMM(1)) VMOVAPS(ZMM(23), ZMM(1)) VMOVAPS(ZMM(24), ZMM(1)) SUB(R(8), IMM(30+L2_PREFETCH_DIST)) //Check if we have over 40 operations to do. VMOVAPS(ZMM(25), ZMM(1)) MOV(R(8), IMM(30)) VMOVAPS(ZMM(26), ZMM(1)) MOV(R(9), IMM(8*8)) //amount to increment b* by each iteration VMOVAPS(ZMM(27), ZMM(1)) MOV(R(12), IMM(8*32)) //amount to increment a* by each iteration VMOVAPS(ZMM(28), ZMM(1)) VMOVAPS(ZMM(29), ZMM(1)) VMOVAPS(ZMM(30), ZMM(1)) #ifdef MONITORS RDTSC MOV(VAR(midl), EAX) MOV(VAR(midh), EDX) #endif JLE(CONSIDER_UNDER_40) SUB(RSI, IMM(30+L2_PREFETCH_DIST)) //First 30 iterations LABEL(LOOPREFECHCL2) MAIN_LOOP_PC_L2(R(8)) JNZ(LOOPREFECHCL2) MOV(RCX, VAR(c)) //Main Loop. LABEL(LOOPMAIN) MAIN_LOOP(RSI) JNZ(LOOPMAIN) //Penultimate 22 iterations. //Break these off from the main loop to avoid prefetching extra shit. MOV(R(14), VAR(a_next)) MOV(R(13), VAR(b_next)) SUB(R(14), R(15)) SUB(R(13), RBX) //Yes, I know 10-20 = -10 MOV(RSI, IMM(10+L2_PREFETCH_DIST-20)) LABEL(LOOPMAIN2) MAIN_LOOP(RSI) JNZ(LOOPMAIN2) //Last 10 iterations MOV(R(8), IMM(10)) LABEL(LOOPREFETCHCL1) MAIN_LOOP_PC_L1(R(8)) JNZ(LOOPREFETCHCL1) JMP(POSTACCUM) //Alternate main loop, with no prefetching of C //Used when <= 40 iterations LABEL(CONSIDER_UNDER_40) MOV(RSI, VAR(k)) TEST(RSI, RSI) JZ(POSTACCUM) LABEL(LOOP_UNDER_40) MAIN_LOOP(RSI) JNZ(LOOP_UNDER_40) LABEL(POSTACCUM) #ifdef MONITORS RDTSC MOV(VAR(mid2l), EAX) MOV(VAR(mid2h), EDX) #endif MOV(R(9), VAR(c)) //load address of c for update MOV(R(12), VAR(alpha)) //load address of alpha // Check if C is row stride. If not, jump to the slow scattered update MOV(R(14), VAR(cs_c)) DEC(R(14)) JNZ(SCATTEREDUPDATE) MOV(R(14), VAR(beta)) VBROADCASTSD(ZMM(31), MEM(R(14))) MOV(RBX, MEM(R(14))) TEST(RBX, RBX) JZ(COLSTORBZ) UPDATE_C_4_ROWS( 1, 2, 3, 4) UPDATE_C_4_ROWS( 5, 6, 7, 8) UPDATE_C_4_ROWS( 9,10,11,12) UPDATE_C_4_ROWS(13,14,15,16) UPDATE_C_4_ROWS(17,18,19,20) UPDATE_C_4_ROWS(21,22,23,24) UPDATE_C_4_ROWS(25,26,27,28) UPDATE_C_2_ROWS(29,30) JMP(END) LABEL(COLSTORBZ) UPDATE_C_BZ_4_ROWS( 1, 2, 3, 4) UPDATE_C_BZ_4_ROWS( 5, 6, 7, 8) UPDATE_C_BZ_4_ROWS( 9,10,11,12) UPDATE_C_BZ_4_ROWS(13,14,15,16) UPDATE_C_BZ_4_ROWS(17,18,19,20) UPDATE_C_BZ_4_ROWS(21,22,23,24) UPDATE_C_BZ_4_ROWS(25,26,27,28) UPDATE_C_BZ_2_ROWS(29,30) JMP(END) LABEL(SCATTEREDUPDATE) MOV(R(13), VAR(beta)) MOV(R(10), VAR(offsetPtr)) VMOVAPS(ZMM(0), MEM(R(10))) MOV(RBX, MEM(R(13))) /* Note that this ignores the upper 32 bits in cs_c */ VPBROADCASTD(ZMM(31), VAR(cs_c)) VPMULLD(ZMM(0), ZMM(31), ZMM(0)) TEST(RBX, RBX) JZ(SCATTERBZ) UPDATE_C_ROW_SCATTERED( 1) UPDATE_C_ROW_SCATTERED( 2) UPDATE_C_ROW_SCATTERED( 3) UPDATE_C_ROW_SCATTERED( 4) UPDATE_C_ROW_SCATTERED( 5) UPDATE_C_ROW_SCATTERED( 6) UPDATE_C_ROW_SCATTERED( 7) UPDATE_C_ROW_SCATTERED( 8) UPDATE_C_ROW_SCATTERED( 9) UPDATE_C_ROW_SCATTERED(10) UPDATE_C_ROW_SCATTERED(11) UPDATE_C_ROW_SCATTERED(12) UPDATE_C_ROW_SCATTERED(13) UPDATE_C_ROW_SCATTERED(14) UPDATE_C_ROW_SCATTERED(15) UPDATE_C_ROW_SCATTERED(16) UPDATE_C_ROW_SCATTERED(17) UPDATE_C_ROW_SCATTERED(18) UPDATE_C_ROW_SCATTERED(19) UPDATE_C_ROW_SCATTERED(20) UPDATE_C_ROW_SCATTERED(21) UPDATE_C_ROW_SCATTERED(22) UPDATE_C_ROW_SCATTERED(23) UPDATE_C_ROW_SCATTERED(24) UPDATE_C_ROW_SCATTERED(25) UPDATE_C_ROW_SCATTERED(26) UPDATE_C_ROW_SCATTERED(27) UPDATE_C_ROW_SCATTERED(28) UPDATE_C_ROW_SCATTERED(29) UPDATE_C_ROW_SCATTERED(30) JMP(END) LABEL(SCATTERBZ) UPDATE_C_BZ_ROW_SCATTERED( 1) UPDATE_C_BZ_ROW_SCATTERED( 2) UPDATE_C_BZ_ROW_SCATTERED( 3) UPDATE_C_BZ_ROW_SCATTERED( 4) UPDATE_C_BZ_ROW_SCATTERED( 5) UPDATE_C_BZ_ROW_SCATTERED( 6) UPDATE_C_BZ_ROW_SCATTERED( 7) UPDATE_C_BZ_ROW_SCATTERED( 8) UPDATE_C_BZ_ROW_SCATTERED( 9) UPDATE_C_BZ_ROW_SCATTERED(10) UPDATE_C_BZ_ROW_SCATTERED(11) UPDATE_C_BZ_ROW_SCATTERED(12) UPDATE_C_BZ_ROW_SCATTERED(13) UPDATE_C_BZ_ROW_SCATTERED(14) UPDATE_C_BZ_ROW_SCATTERED(15) UPDATE_C_BZ_ROW_SCATTERED(16) UPDATE_C_BZ_ROW_SCATTERED(17) UPDATE_C_BZ_ROW_SCATTERED(18) UPDATE_C_BZ_ROW_SCATTERED(19) UPDATE_C_BZ_ROW_SCATTERED(20) UPDATE_C_BZ_ROW_SCATTERED(21) UPDATE_C_BZ_ROW_SCATTERED(22) UPDATE_C_BZ_ROW_SCATTERED(23) UPDATE_C_BZ_ROW_SCATTERED(24) UPDATE_C_BZ_ROW_SCATTERED(25) UPDATE_C_BZ_ROW_SCATTERED(26) UPDATE_C_BZ_ROW_SCATTERED(27) UPDATE_C_BZ_ROW_SCATTERED(28) UPDATE_C_BZ_ROW_SCATTERED(29) UPDATE_C_BZ_ROW_SCATTERED(30) LABEL(END) #ifdef MONITORS RDTSC MOV(VAR(botl), EAX) MOV(VAR(both), EDX) #endif : // output operands #ifdef MONITORS [topl] "=m" (topl), [toph] "=m" (toph), [midl] "=m" (midl), [midh] "=m" (midh), [mid2l] "=m" (mid2l), [mid2h] "=m" (mid2h), [botl] "=m" (botl), [both] "=m" (both) #endif : // input operands [k] "m" (k), [a] "m" (a), [b] "m" (b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c), [a_next] "m" (a_next), [b_next] "m" (b_next), [offsetPtr] "m" (offsetPtr) : // register clobber list "rax", "rbx", "rcx", "rdx", "rdi", "rsi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "zmm0", "zmm1", "zmm2", "zmm3", "zmm4", "zmm5", "zmm6", "zmm7", "zmm8", "zmm9", "zmm10", "zmm11", "zmm12", "zmm13", "zmm14", "zmm15", "zmm16", "zmm17", "zmm18", "zmm19", "zmm20", "zmm21", "zmm22", "zmm23", "zmm24", "zmm25", "zmm26", "zmm27", "zmm28", "zmm29", "zmm30", "zmm31", "memory" ); #ifdef LOOPMON printf("looptime = \t%d\n", bloopl - tloopl); #endif #ifdef MONITORS dim_t top = ((dim_t)toph << 32) | topl; dim_t mid = ((dim_t)midh << 32) | midl; dim_t mid2 = ((dim_t)mid2h << 32) | mid2l; dim_t bot = ((dim_t)both << 32) | botl; printf("setup =\t%u\tmain loop =\t%u\tcleanup=\t%u\ttotal=\t%u\n", mid - top, mid2 - mid, bot - mid2, bot - top); #endif } blis-0.9.0/kernels/knl/3/other/bli_dgemm_knl_asm_8x24.c000066400000000000000000000530411422157504600225500ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 UNIVERSITY OF TEXAS 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. */ #include "blis.h" #include #include "bli_avx512_macros.h" #define UNROLL_K 8 #define SCATTER_PREFETCH_AB 0 #define SCATTER_PREFETCH_C 1 #define PREFETCH_A_L2 0 #define PREFETCH_B_L2 0 #define L2_PREFETCH_DIST 64 #define A_L1_PREFETCH_DIST 32 #define B_L1_PREFETCH_DIST 12 #define C_MIN_L2_ITERS 64 //C is not prefetched into L2 for k <= this #define C_L1_ITERS 8 //number of iterations before the end to prefetch C into L1 //make sure there is an unrolled MAIN_LOOP_X for this number #define LOOP_ALIGN ALIGN16 #define UPDATE_C_FOUR_ROWS(R1,R2,R3,R4) \ \ VMULPD(ZMM(R1), ZMM(R1), ZMM(0)) \ VMULPD(ZMM(R2), ZMM(R2), ZMM(0)) \ VMULPD(ZMM(R3), ZMM(R3), ZMM(0)) \ VMULPD(ZMM(R4), ZMM(R4), ZMM(0)) \ VFMADD231PD(ZMM(R1), ZMM(1), MEM(RCX )) \ VFMADD231PD(ZMM(R2), ZMM(1), MEM(RCX,RAX,1)) \ VFMADD231PD(ZMM(R3), ZMM(1), MEM(RCX,RAX,2)) \ VFMADD231PD(ZMM(R4), ZMM(1), MEM(RCX,RDI,1)) \ VMOVUPD(MEM(RCX ), ZMM(R1)) \ VMOVUPD(MEM(RCX,RAX,1), ZMM(R2)) \ VMOVUPD(MEM(RCX,RAX,2), ZMM(R3)) \ VMOVUPD(MEM(RCX,RDI,1), ZMM(R4)) \ LEA(RCX, MEM(RCX,RAX,4)) #define UPDATE_C_BZ_FOUR_ROWS(R1,R2,R3,R4) \ \ VMULPD(ZMM(R1), ZMM(R1), ZMM(0)) \ VMULPD(ZMM(R2), ZMM(R2), ZMM(0)) \ VMULPD(ZMM(R3), ZMM(R3), ZMM(0)) \ VMULPD(ZMM(R4), ZMM(R4), ZMM(0)) \ VMOVUPD(MEM(RCX ), ZMM(R1)) \ VMOVUPD(MEM(RCX,RAX,1), ZMM(R2)) \ VMOVUPD(MEM(RCX,RAX,2), ZMM(R3)) \ VMOVUPD(MEM(RCX,RDI,1), ZMM(R4)) \ LEA(RCX, MEM(RCX,RAX,4)) #define UPDATE_C_ROW_SCATTERED(NUM) \ \ KXNORW(K(1), K(0), K(0)) \ KXNORW(K(2), K(0), K(0)) \ VMULPD(ZMM(NUM), ZMM(NUM), ZMM(0)) \ VGATHERDPD(ZMM(3) MASK_K(1), MEM(RCX,YMM(2),8)) \ VFMADD231PD(ZMM(NUM), ZMM(3), ZMM(1)) \ VSCATTERDPD(MEM(RCX,YMM(2),8) MASK_K(2), ZMM(NUM)) \ ADD(RCX, RAX) #define UPDATE_C_BZ_ROW_SCATTERED(NUM) \ \ KXNORW(K(1), K(0), K(0)) \ VMULPD(ZMM(NUM), ZMM(NUM), ZMM(0)) \ VSCATTERDPD(MEM(RCX,YMM(2),8) MASK_K(1), ZMM(NUM)) \ ADD(RCX, RAX) #define PREFETCH_B_L1_1(n) PREFETCH(0, MEM(RBX,(B_L1_PREFETCH_DIST+n)*24*8)) #define PREFETCH_B_L1_2(n) PREFETCH(0, MEM(RBX,(B_L1_PREFETCH_DIST+n)*24*8+64)) #define PREFETCH_B_L1_3(n) PREFETCH(0, MEM(RBX,(B_L1_PREFETCH_DIST+n)*24*8+128)) #if PREFETCH_B_L2 #undef PREFETCH_B_L2 #define PREFETCH_B_L2(n) \ \ PREFETCH(1, MEM(RBX,(L2_PREFETCH_DIST+n)*24*8)) \ PREFETCH(1, MEM(RBX,(L2_PREFETCH_DIST+n)*24*8+64)) \ PREFETCH(1, MEM(RBX,(L2_PREFETCH_DIST+n)*24*8+128)) #else #undef PREFETCH_B_L2 #define PREFETCH_B_L2(...) #endif #define PREFETCH_A_L1(n) PREFETCH(0, MEM(RAX,(A_L1_PREFETCH_DIST+n)*8*8)) #if PREFETCH_A_L2 #undef PREFETCH_A_L2 #define PREFETCH_A_L2(n) PREFETCH(1, MEM(RAX,(L2_PREFETCH_DIST+n)*8*8)) #else #undef PREFETCH_A_L2 #define PREFETCH_A_L2(...) #endif #if SCATTER_PREFETCH_AB #undef SCATTER_PREFETCH_AB #undef PREFETCH_B_L1_1 #undef PREFETCH_B_L1_2 #undef PREFETCH_B_L1_3 #undef PREFETCH_A_L1 #define SCATTER_PREFETCH_AB(n) \ \ KXNORW(K(1), K(0), K(0)) \ VGATHERPFDPS(0, MEM(RBX,ZMM(4),8,((3*n )*16+3*B_L1_PREFETCH_DIST)*64) MASK_K(1)) \ KXNORW(K(2), K(0), K(0)) \ VGATHERPFDPS(0, MEM(RBX,ZMM(4),8,((3*n+1)*16+3*B_L1_PREFETCH_DIST)*64) MASK_K(2)) \ KXNORW(K(3), K(0), K(0)) \ VGATHERPFDPS(0, MEM(RBX,ZMM(4),8,((3*n+2)*16+3*B_L1_PREFETCH_DIST)*64) MASK_K(3)) \ KXNORW(K(4), K(0), K(0)) \ VGATHERPFDPS(0, MEM(RAX,ZMM(4),8,( n *16+ A_L1_PREFETCH_DIST)*64) MASK_K(4)) #define PREFETCH_B_L1_1(...) #define PREFETCH_B_L1_2(...) #define PREFETCH_B_L1_3(...) #define PREFETCH_A_L1(...) #else #undef SCATTER_PREFETCH_AB #define SCATTER_PREFETCH_AB(...) #endif // // n: index in unrolled loop (for prefetching offsets) // // a: ZMM register to load into // b: ZMM register to read from // // ...: addressing for B, except for offset // #define SUBITER(n,a,b,...) \ \ PREFETCH_B_L2(n) \ \ VMOVAPD(ZMM(a), MEM(RAX,(n+1)*64)) \ VFMADD231PD(ZMM( 8), ZMM(b), MEM_1TO8(__VA_ARGS__,((n%%4)*24+ 0)*8)) \ VFMADD231PD(ZMM( 9), ZMM(b), MEM_1TO8(__VA_ARGS__,((n%%4)*24+ 1)*8)) \ VFMADD231PD(ZMM(10), ZMM(b), MEM_1TO8(__VA_ARGS__,((n%%4)*24+ 2)*8)) \ VFMADD231PD(ZMM(11), ZMM(b), MEM_1TO8(__VA_ARGS__,((n%%4)*24+ 3)*8)) \ PREFETCH_B_L1_1(n) \ VFMADD231PD(ZMM(12), ZMM(b), MEM_1TO8(__VA_ARGS__,((n%%4)*24+ 4)*8)) \ VFMADD231PD(ZMM(13), ZMM(b), MEM_1TO8(__VA_ARGS__,((n%%4)*24+ 5)*8)) \ VFMADD231PD(ZMM(14), ZMM(b), MEM_1TO8(__VA_ARGS__,((n%%4)*24+ 6)*8)) \ VFMADD231PD(ZMM(15), ZMM(b), MEM_1TO8(__VA_ARGS__,((n%%4)*24+ 7)*8)) \ PREFETCH_B_L1_2(n) \ VFMADD231PD(ZMM(16), ZMM(b), MEM_1TO8(__VA_ARGS__,((n%%4)*24+ 8)*8)) \ VFMADD231PD(ZMM(17), ZMM(b), MEM_1TO8(__VA_ARGS__,((n%%4)*24+ 9)*8)) \ VFMADD231PD(ZMM(18), ZMM(b), MEM_1TO8(__VA_ARGS__,((n%%4)*24+10)*8)) \ VFMADD231PD(ZMM(19), ZMM(b), MEM_1TO8(__VA_ARGS__,((n%%4)*24+11)*8)) \ PREFETCH_B_L1_3(n) \ VFMADD231PD(ZMM(20), ZMM(b), MEM_1TO8(__VA_ARGS__,((n%%4)*24+12)*8)) \ VFMADD231PD(ZMM(21), ZMM(b), MEM_1TO8(__VA_ARGS__,((n%%4)*24+13)*8)) \ VFMADD231PD(ZMM(22), ZMM(b), MEM_1TO8(__VA_ARGS__,((n%%4)*24+14)*8)) \ VFMADD231PD(ZMM(23), ZMM(b), MEM_1TO8(__VA_ARGS__,((n%%4)*24+15)*8)) \ PREFETCH_A_L1(n) \ VFMADD231PD(ZMM(24), ZMM(b), MEM_1TO8(__VA_ARGS__,((n%%4)*24+16)*8)) \ VFMADD231PD(ZMM(25), ZMM(b), MEM_1TO8(__VA_ARGS__,((n%%4)*24+17)*8)) \ VFMADD231PD(ZMM(26), ZMM(b), MEM_1TO8(__VA_ARGS__,((n%%4)*24+18)*8)) \ VFMADD231PD(ZMM(27), ZMM(b), MEM_1TO8(__VA_ARGS__,((n%%4)*24+19)*8)) \ PREFETCH_A_L2(n) \ VFMADD231PD(ZMM(28), ZMM(b), MEM_1TO8(__VA_ARGS__,((n%%4)*24+20)*8)) \ VFMADD231PD(ZMM(29), ZMM(b), MEM_1TO8(__VA_ARGS__,((n%%4)*24+21)*8)) \ VFMADD231PD(ZMM(30), ZMM(b), MEM_1TO8(__VA_ARGS__,((n%%4)*24+22)*8)) \ VFMADD231PD(ZMM(31), ZMM(b), MEM_1TO8(__VA_ARGS__,((n%%4)*24+23)*8)) #define TAIL_LOOP(NAME) \ \ LOOP_ALIGN \ LABEL(NAME) \ \ SUBITER(0,1,0,RBX) \ \ VMOVAPD(ZMM(0), ZMM(1)) \ \ LEA(RBX, MEM(RBX,24*8)) \ LEA(RAX, MEM(RAX, 8*8)) \ \ SUB(RDI, IMM(1)) \ \ JNZ(NAME) #define MAIN_LOOP_1(NAME) \ \ LOOP_ALIGN \ LABEL(NAME##_LOOP) \ \ SUBITER(0,1,0,RBX) \ \ VMOVAPD(ZMM(0), ZMM(1)) \ \ LEA(RBX, MEM(RBX,24*8)) \ LEA(RAX, MEM(RAX, 8*8)) \ \ SUB(RSI, IMM(1)) \ \ JNZ(NAME##_LOOP) #define MAIN_LOOP_2(NAME) \ \ MOV(RDI, RSI) \ AND(RDI, IMM(1)) \ SAR1(RSI) \ JZ(NAME##_TAIL) \ \ LOOP_ALIGN \ LABEL(NAME##_LOOP) \ \ SUBITER(0,1,0,RBX) \ SUBITER(1,0,1,RBX) \ \ LEA(RBX, MEM(RBX,2*24*8)) \ LEA(RAX, MEM(RAX,2* 8*8)) \ \ SUB(RSI, IMM(1)) \ \ JNZ(NAME##_LOOP) \ \ TEST(RDI, RDI) \ JZ(NAME##_DONE) \ \ LABEL(NAME##_TAIL) \ \ SUBITER(0,1,0,RBX) \ \ VMOVAPD(ZMM(0), ZMM(1)) \ \ LEA(RBX, MEM(RBX,24*8)) \ LEA(RAX, MEM(RAX, 8*8)) \ \ LABEL(NAME##_DONE) #define MAIN_LOOP_4(NAME) \ \ MOV(RDI, RSI) \ AND(RDI, IMM(3)) \ SAR(RSI, IMM(2)) \ JZ(NAME##_TAIL) \ \ LOOP_ALIGN \ LABEL(NAME##_LOOP) \ \ SUBITER(0,1,0,RBX) \ SUBITER(1,0,1,RBX) \ SUBITER(2,1,0,RBX) \ SUBITER(3,0,1,RBX) \ \ LEA(RBX, MEM(RBX,4*24*8)) \ LEA(RAX, MEM(RAX,4* 8*8)) \ \ SUB(RSI, IMM(1)) \ \ JNZ(NAME##_LOOP) \ \ TEST(RDI, RDI) \ JZ(NAME##_DONE) \ \ TAIL_LOOP(NAME##_TAIL) \ \ LABEL(NAME##_DONE) #define MAIN_LOOP_8(NAME) \ \ MOV(RDI, RSI) \ AND(RDI, IMM(7)) \ SAR(RSI, IMM(3)) \ JZ(NAME##_TAIL) \ \ LOOP_ALIGN \ LABEL(NAME##_LOOP) \ \ SUBITER(0,1,0,RBX) \ SUBITER(1,0,1,RBX) \ SUBITER(2,1,0,RBX) \ SUBITER(3,0,1,RBX) \ SUBITER(4,1,0,RBX,R8,1) \ SUBITER(5,0,1,RBX,R8,1) \ SUBITER(6,1,0,RBX,R8,1) \ SUBITER(7,0,1,RBX,R8,1) \ \ LEA(RBX, MEM(RBX,8*24*8)) \ LEA(RAX, MEM(RAX,8* 8*8)) \ \ SUB(RSI, IMM(1)) \ \ JNZ(NAME##_LOOP) \ \ TEST(RDI, RDI) \ JZ(NAME##_DONE) \ \ TAIL_LOOP(NAME##_TAIL) \ \ LABEL(NAME##_DONE) #define MAIN_LOOP_16(NAME) \ \ MOV(RDI, RSI) \ AND(RDI, IMM(15)) \ SAR(RSI, IMM(4)) \ JZ(NAME##_TAIL) \ \ LOOP_ALIGN \ LABEL(NAME##_LOOP) \ \ SCATTER_PREFETCH_AB(0) \ \ SUBITER( 0,1,0,RBX) \ SUBITER( 1,0,1,RBX) \ SUBITER( 2,1,0,RBX) \ SUBITER( 3,0,1,RBX) \ SUBITER( 4,1,0,RBX,R8,1) \ SUBITER( 5,0,1,RBX,R8,1) \ SUBITER( 6,1,0,RBX,R8,1) \ SUBITER( 7,0,1,RBX,R8,1) \ SUBITER( 8,1,0,RBX,R8,2) \ SUBITER( 9,0,1,RBX,R8,2) \ SUBITER(10,1,0,RBX,R8,2) \ SUBITER(11,0,1,RBX,R8,2) \ SUBITER(12,1,0,RBX,R9,1) \ SUBITER(13,0,1,RBX,R9,1) \ SUBITER(14,1,0,RBX,R9,1) \ SUBITER(15,0,1,RBX,R9,1) \ \ LEA(RBX, MEM(RBX,16*24*8)) \ LEA(RAX, MEM(RAX,16* 8*8)) \ \ SUB(RSI, IMM(1)) \ \ JNZ(NAME##_LOOP) \ \ TEST(RDI, RDI) \ JZ(NAME##_DONE) \ \ SCATTER_PREFETCH_AB(0) \ \ TAIL_LOOP(NAME##_TAIL) \ \ LABEL(NAME##_DONE) #define MAIN_LOOP_32(NAME) \ \ MOV(RDI, RSI) \ AND(RDI, IMM(31)) \ SAR(RSI, IMM(5)) \ JZ(NAME##_TAIL) \ \ LOOP_ALIGN \ LABEL(NAME##_LOOP) \ \ SCATTER_PREFETCH_AB(0) \ \ SUBITER( 0,1,0,RBX) \ SUBITER( 1,0,1,RBX) \ SUBITER( 2,1,0,RBX) \ SUBITER( 3,0,1,RBX) \ SUBITER( 4,1,0,RBX,R8,1) \ SUBITER( 5,0,1,RBX,R8,1) \ SUBITER( 6,1,0,RBX,R8,1) \ SUBITER( 7,0,1,RBX,R8,1) \ SUBITER( 8,1,0,RBX,R8,2) \ SUBITER( 9,0,1,RBX,R8,2) \ SUBITER(10,1,0,RBX,R8,2) \ SUBITER(11,0,1,RBX,R8,2) \ SUBITER(12,1,0,RBX,R9,1) \ SUBITER(13,0,1,RBX,R9,1) \ SUBITER(14,1,0,RBX,R9,1) \ SUBITER(15,0,1,RBX,R9,1) \ \ SCATTER_PREFETCH_AB(1) \ \ SUBITER(16,1,0,RBX,R8,4) \ SUBITER(17,0,1,RBX,R8,4) \ SUBITER(18,1,0,RBX,R8,4) \ SUBITER(19,0,1,RBX,R8,4) \ SUBITER(20,1,0,RBX,R10,1) \ SUBITER(21,0,1,RBX,R10,1) \ SUBITER(22,1,0,RBX,R10,1) \ SUBITER(23,0,1,RBX,R10,1) \ SUBITER(24,1,0,RBX,R9,2) \ SUBITER(25,0,1,RBX,R9,2) \ SUBITER(26,1,0,RBX,R9,2) \ SUBITER(27,0,1,RBX,R9,2) \ SUBITER(28,1,0,RBX,R11,1) \ SUBITER(29,0,1,RBX,R11,1) \ SUBITER(30,1,0,RBX,R11,1) \ SUBITER(31,0,1,RBX,R11,1) \ \ LEA(RBX, MEM(RBX,32*24*8)) \ LEA(RAX, MEM(RAX,32* 8*8)) \ \ SUB(RSI, IMM(1)) \ \ JNZ(NAME##_LOOP) \ \ TEST(RDI, RDI) \ JZ(NAME##_DONE) \ \ SCATTER_PREFETCH_AB(0) \ SCATTER_PREFETCH_AB(1) \ \ TAIL_LOOP(NAME##_TAIL) \ \ LABEL(NAME##_DONE) #define LOOP_K_(M,K) M##K #define LOOP_K(M,K,NAME) LOOP_K_(M,K)(NAME) #define MAIN_LOOP_L2 LOOP_K(MAIN_LOOP_,UNROLL_K,MAIN_LOOP_L2) #define MAIN_LOOP_L1 LOOP_K(MAIN_LOOP_,C_L1_ITERS,MAIN_LOOP_L1) //This is an array used for the scatter/gather instructions. extern int32_t offsets[24]; //#define MONITORS //#define LOOPMON void bli_dgemm_knl_asm_8x24 ( dim_t k, double* restrict alpha, double* restrict a, double* restrict b, double* restrict beta, double* restrict c, inc_t rs_c, inc_t cs_c, auxinfo_t* restrict data, cntx_t* restrict cntx ) { const double * a_next = bli_auxinfo_next_a( data ); const double * b_next = bli_auxinfo_next_b( data ); const int32_t * offsetPtr = &offsets[0]; uint64_t k64 = k; #ifdef MONITORS int toph, topl, both, botl, midl, midh, mid2l, mid2h; #endif #ifdef LOOPMON int tlooph, tloopl, blooph, bloopl; #endif __asm__ volatile ( #ifdef MONITORS RDTSC MOV(VAR(topl), EAX) MOV(VAR(toph), EDX) #endif VPXORD(ZMM(8), ZMM(8), ZMM(8)) //clear out registers VMOVAPS(ZMM( 9), ZMM(8)) VMOVAPS(ZMM(10), ZMM(8)) MOV(RSI, VAR(k)) //loop index VMOVAPS(ZMM(11), ZMM(8)) MOV(RAX, VAR(a)) //load address of a VMOVAPS(ZMM(12), ZMM(8)) MOV(RBX, VAR(b)) //load address of b VMOVAPS(ZMM(13), ZMM(8)) MOV(RCX, VAR(c)) //load address of c VMOVAPS(ZMM(14), ZMM(8)) VMOVAPD(ZMM(0), MEM(RAX)) //pre-load a VMOVAPS(ZMM(15), ZMM(8)) MOV(RDI, VAR(offsetPtr)) VMOVAPS(ZMM(16), ZMM(8)) VMOVAPS(ZMM(4), MEM(RDI)) #if SCATTER_PREFETCH_C VMOVAPS(ZMM(17), ZMM(8)) VMOVAPS(ZMM(18), ZMM(8)) VMOVAPS(ZMM(19), ZMM(8)) VBROADCASTSS(ZMM(5), VAR(cs_c)) VMOVAPS(ZMM(20), ZMM(8)) VMOVAPS(ZMM(21), ZMM(8)) VPMULLD(ZMM(2), ZMM(4), ZMM(5)) VMOVAPS(ZMM(22), ZMM(8)) VMOVAPS(YMM(3), MEM(RDI,64)) VMOVAPS(ZMM(23), ZMM(8)) VPMULLD(YMM(3), YMM(3), YMM(5)) #else VMOVAPS(ZMM(17), ZMM(8)) MOV(R12, VAR(cs_c)) VMOVAPS(ZMM(18), ZMM(8)) LEA(R13, MEM(R12,R12,2)) VMOVAPS(ZMM(19), ZMM(8)) LEA(R14, MEM(R12,R12,4)) VMOVAPS(ZMM(20), ZMM(8)) LEA(R15, MEM(R13,R12,4)) VMOVAPS(ZMM(21), ZMM(8)) LEA(RDX, MEM(RCX,R12,8)) VMOVAPS(ZMM(22), ZMM(8)) LEA(RDI, MEM(RDX,R12,8)) VMOVAPS(ZMM(23), ZMM(8)) #endif VMOVAPS(ZMM(24), ZMM(8)) VPSLLD(ZMM(4), ZMM(4), IMM(3)) VMOVAPS(ZMM(25), ZMM(8)) MOV(R8, IMM(4*24*8)) //offset for 4 iterations VMOVAPS(ZMM(26), ZMM(8)) LEA(R9, MEM(R8,R8,2)) //*3 VMOVAPS(ZMM(27), ZMM(8)) LEA(R10, MEM(R8,R8,4)) //*5 VMOVAPS(ZMM(28), ZMM(8)) LEA(R11, MEM(R9,R8,4)) //*7 VMOVAPS(ZMM(29), ZMM(8)) VMOVAPS(ZMM(30), ZMM(8)) VMOVAPS(ZMM(31), ZMM(8)) #ifdef MONITORS RDTSC MOV(VAR(midl), EAX) MOV(VAR(midh), EDX) #endif //need 0+... to satisfy preprocessor CMP(RSI, IMM(0+C_MIN_L2_ITERS)) JLE(PREFETCH_C_L1) SUB(RSI, IMM(0+C_L1_ITERS)) //prefetch C into L2 #if SCATTER_PREFETCH_C KXNORW(K(1), K(0), K(0)) KXNORW(K(2), K(0), K(0)) VSCATTERPFDPS(1, MEM(RCX,ZMM(2),8) MASK_K(1)) VSCATTERPFDPD(1, MEM(RCX,YMM(3),8) MASK_K(2)) #else PREFETCH(1, MEM(RCX )) PREFETCH(1, MEM(RCX,R12,1)) PREFETCH(1, MEM(RCX,R12,2)) PREFETCH(1, MEM(RCX,R13,1)) PREFETCH(1, MEM(RCX,R12,4)) PREFETCH(1, MEM(RCX,R14,1)) PREFETCH(1, MEM(RCX,R13,2)) PREFETCH(1, MEM(RCX,R15,1)) PREFETCH(1, MEM(RDX )) PREFETCH(1, MEM(RDX,R12,1)) PREFETCH(1, MEM(RDX,R12,2)) PREFETCH(1, MEM(RDX,R13,1)) PREFETCH(1, MEM(RDX,R12,4)) PREFETCH(1, MEM(RDX,R14,1)) PREFETCH(1, MEM(RDX,R13,2)) PREFETCH(1, MEM(RDX,R15,1)) PREFETCH(1, MEM(RDI )) PREFETCH(1, MEM(RDI,R12,1)) PREFETCH(1, MEM(RDI,R12,2)) PREFETCH(1, MEM(RDI,R13,1)) PREFETCH(1, MEM(RDI,R12,4)) PREFETCH(1, MEM(RDI,R14,1)) PREFETCH(1, MEM(RDI,R13,2)) PREFETCH(1, MEM(RDI,R15,1)) #endif MAIN_LOOP_L2 MOV(RSI, IMM(0+C_L1_ITERS)) LABEL(PREFETCH_C_L1) //prefetch C into L1 #if SCATTER_PREFETCH_C KXNORW(K(1), K(0), K(0)) KXNORW(K(2), K(0), K(0)) VSCATTERPFDPS(0, MEM(RCX,ZMM(2),8) MASK_K(1)) VSCATTERPFDPD(0, MEM(RCX,YMM(3),8) MASK_K(2)) #else PREFETCH(0, MEM(RCX )) PREFETCH(0, MEM(RCX,R12,1)) PREFETCH(0, MEM(RCX,R12,2)) PREFETCH(0, MEM(RCX,R13,1)) PREFETCH(0, MEM(RCX,R12,4)) PREFETCH(0, MEM(RCX,R14,1)) PREFETCH(0, MEM(RCX,R13,2)) PREFETCH(0, MEM(RCX,R15,1)) PREFETCH(0, MEM(RDX )) PREFETCH(0, MEM(RDX,R12,1)) PREFETCH(0, MEM(RDX,R12,2)) PREFETCH(0, MEM(RDX,R13,1)) PREFETCH(0, MEM(RDX,R12,4)) PREFETCH(0, MEM(RDX,R14,1)) PREFETCH(0, MEM(RDX,R13,2)) PREFETCH(0, MEM(RDX,R15,1)) PREFETCH(0, MEM(RDI )) PREFETCH(0, MEM(RDI,R12,1)) PREFETCH(0, MEM(RDI,R12,2)) PREFETCH(0, MEM(RDI,R13,1)) PREFETCH(0, MEM(RDI,R12,4)) PREFETCH(0, MEM(RDI,R14,1)) PREFETCH(0, MEM(RDI,R13,2)) PREFETCH(0, MEM(RDI,R15,1)) #endif MAIN_LOOP_L1 LABEL(POSTACCUM) #ifdef MONITORS RDTSC MOV(VAR(mid2l), EAX) MOV(VAR(mid2h), EDX) #endif MOV(RAX, VAR(alpha)) MOV(RBX, VAR(beta)) VBROADCASTSD(ZMM(0), MEM(RAX)) VBROADCASTSD(ZMM(1), MEM(RBX)) // Check if C is column stride. If not, jump to the slow scattered update MOV(RAX, VAR(cs_c)) LEA(RAX, MEM(,RAX,8)) MOV(RBX, VAR(rs_c)) LEA(RDI, MEM(RAX,RAX,2)) CMP(RBX, IMM(1)) JNE(SCATTEREDUPDATE) VMOVQ(RDX, XMM(1)) SAL1(RDX) //shift out sign bit JZ(COLSTORBZ) UPDATE_C_FOUR_ROWS( 8, 9,10,11) UPDATE_C_FOUR_ROWS(12,13,14,15) UPDATE_C_FOUR_ROWS(16,17,18,19) UPDATE_C_FOUR_ROWS(20,21,22,23) UPDATE_C_FOUR_ROWS(24,25,26,27) UPDATE_C_FOUR_ROWS(28,29,30,31) JMP(END) LABEL(COLSTORBZ) UPDATE_C_BZ_FOUR_ROWS( 8, 9,10,11) UPDATE_C_BZ_FOUR_ROWS(12,13,14,15) UPDATE_C_BZ_FOUR_ROWS(16,17,18,19) UPDATE_C_BZ_FOUR_ROWS(20,21,22,23) UPDATE_C_BZ_FOUR_ROWS(24,25,26,27) UPDATE_C_BZ_FOUR_ROWS(28,29,30,31) JMP(END) LABEL(SCATTEREDUPDATE) MOV(RDI, VAR(offsetPtr)) VMOVAPS(ZMM(2), MEM(RDI)) /* Note that this ignores the upper 32 bits in rs_c */ VPBROADCASTD(ZMM(3), EBX) VPMULLD(ZMM(2), ZMM(3), ZMM(2)) VMOVQ(RDX, XMM(1)) SAL1(RDX) //shift out sign bit JZ(SCATTERBZ) UPDATE_C_ROW_SCATTERED( 8) UPDATE_C_ROW_SCATTERED( 9) UPDATE_C_ROW_SCATTERED(10) UPDATE_C_ROW_SCATTERED(11) UPDATE_C_ROW_SCATTERED(12) UPDATE_C_ROW_SCATTERED(13) UPDATE_C_ROW_SCATTERED(14) UPDATE_C_ROW_SCATTERED(15) UPDATE_C_ROW_SCATTERED(16) UPDATE_C_ROW_SCATTERED(17) UPDATE_C_ROW_SCATTERED(18) UPDATE_C_ROW_SCATTERED(19) UPDATE_C_ROW_SCATTERED(20) UPDATE_C_ROW_SCATTERED(21) UPDATE_C_ROW_SCATTERED(22) UPDATE_C_ROW_SCATTERED(23) UPDATE_C_ROW_SCATTERED(24) UPDATE_C_ROW_SCATTERED(25) UPDATE_C_ROW_SCATTERED(26) UPDATE_C_ROW_SCATTERED(27) UPDATE_C_ROW_SCATTERED(28) UPDATE_C_ROW_SCATTERED(29) UPDATE_C_ROW_SCATTERED(30) UPDATE_C_ROW_SCATTERED(31) JMP(END) LABEL(SCATTERBZ) UPDATE_C_BZ_ROW_SCATTERED( 8) UPDATE_C_BZ_ROW_SCATTERED( 9) UPDATE_C_BZ_ROW_SCATTERED(10) UPDATE_C_BZ_ROW_SCATTERED(11) UPDATE_C_BZ_ROW_SCATTERED(12) UPDATE_C_BZ_ROW_SCATTERED(13) UPDATE_C_BZ_ROW_SCATTERED(14) UPDATE_C_BZ_ROW_SCATTERED(15) UPDATE_C_BZ_ROW_SCATTERED(16) UPDATE_C_BZ_ROW_SCATTERED(17) UPDATE_C_BZ_ROW_SCATTERED(18) UPDATE_C_BZ_ROW_SCATTERED(19) UPDATE_C_BZ_ROW_SCATTERED(20) UPDATE_C_BZ_ROW_SCATTERED(21) UPDATE_C_BZ_ROW_SCATTERED(22) UPDATE_C_BZ_ROW_SCATTERED(23) UPDATE_C_BZ_ROW_SCATTERED(24) UPDATE_C_BZ_ROW_SCATTERED(25) UPDATE_C_BZ_ROW_SCATTERED(26) UPDATE_C_BZ_ROW_SCATTERED(27) UPDATE_C_BZ_ROW_SCATTERED(28) UPDATE_C_BZ_ROW_SCATTERED(29) UPDATE_C_BZ_ROW_SCATTERED(30) UPDATE_C_BZ_ROW_SCATTERED(31) LABEL(END) #ifdef MONITORS RDTSC MOV(VAR(botl), EAX) MOV(VAR(both), EDX) #endif : // output operands #ifdef MONITORS [topl] "=m" (topl), [toph] "=m" (toph), [midl] "=m" (midl), [midh] "=m" (midh), [mid2l] "=m" (mid2l), [mid2h] "=m" (mid2h), [botl] "=m" (botl), [both] "=m" (both) #endif : // input operands [k] "m" (k64), [a] "m" (a), [b] "m" (b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c), [a_next] "m" (a_next), [b_next] "m" (b_next), [offsetPtr] "m" (offsetPtr) : // register clobber list "rax", "rbx", "rcx", "rdx", "rdi", "rsi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "zmm0", "zmm1", "zmm2", "zmm3", "zmm4", "zmm5", "zmm6", "zmm7", "zmm8", "zmm9", "zmm10", "zmm11", "zmm12", "zmm13", "zmm14", "zmm15", "zmm16", "zmm17", "zmm18", "zmm19", "zmm20", "zmm21", "zmm22", "zmm23", "zmm24", "zmm25", "zmm26", "zmm27", "zmm28", "zmm29", "zmm30", "zmm31", "memory" ); #ifdef LOOPMON printf("looptime = \t%d\n", bloopl - tloopl); #endif #ifdef MONITORS dim_t top = ((dim_t)toph << 32) | topl; dim_t mid = ((dim_t)midh << 32) | midl; dim_t mid2 = ((dim_t)mid2h << 32) | mid2l; dim_t bot = ((dim_t)both << 32) | botl; printf("setup =\t%u\tmain loop =\t%u\tcleanup=\t%u\ttotal=\t%u\n", mid - top, mid2 - mid, bot - mid2, bot - top); #endif } blis-0.9.0/kernels/knl/3/other/bli_sgemm_knl_asm_30x16_knc.c000066400000000000000000000400051422157504600234720ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 UNIVERSITY OF TEXAS 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. */ #include "blis.h" #include #include "bli_avx512_macros.h" #define A_L1_PREFETCH_DIST 4 #define B_L1_PREFETCH_DIST 2 #define L2_PREFETCH_DIST 16 // Must be greater than 10, because of the way the loop is constructed. //Alternate code path uused if C is not row-major // r9 = c // zmm30 = cs_c * 1...16 // r11 = rs_c // r12 = &alpha // r13 = &beta #define UPDATE_C_ROW_SCATTERED_(NUM,BNZ1,BNZ2) \ \ BNZ1 KXNORW(K(2), K(0), K(0)) BNZ2 \ KXNORW(K(3), K(0), K(0)) \ BNZ1 VGATHERDPS(ZMM(31) MASK_K(2), MEM(R(9),ZMM(30),4)) BNZ2 \ VMULPS(ZMM(NUM), ZMM(NUM), MEM_1TO16(R(12))) /*scale by alpha*/ \ BNZ1 VFMADD231PS(ZMM(NUM), ZMM(31), MEM_1TO16(R(13))) BNZ2 /*scale by beta, add in result*/ \ VSCATTERDPS(MEM(R(9),ZMM(30),4) MASK_K(3), ZMM(NUM)) \ ADD(R(9), R(11)) #define UPDATE_C_ROW_SCATTERED(NUM) UPDATE_C_ROW_SCATTERED_(NUM,,) #define UPDATE_C_BZ_ROW_SCATTERED(NUM) UPDATE_C_ROW_SCATTERED_(NUM,COMMENT_BEGIN,COMMENT_END) // r12 = &alpha // zmm31 = beta // r9 = c // r11 = rs_c // r10 = 3*rs_c // rdi = 4*rs_c #define UPDATE_C_4_ROWS_(R1,R2,R3,R4,BNZ1,BNZ2) \ \ VMULPS(ZMM(R1), ZMM(R1), MEM_1TO16(R(12))) \ VMULPS(ZMM(R2), ZMM(R2), MEM_1TO16(R(12))) \ VMULPS(ZMM(R3), ZMM(R3), MEM_1TO16(R(12))) \ VMULPS(ZMM(R4), ZMM(R4), MEM_1TO16(R(12))) \ BNZ1 VFMADD231PS(ZMM(R1), ZMM(31), MEM(R(9) )) BNZ2 \ BNZ1 VFMADD231PS(ZMM(R2), ZMM(31), MEM(R(9),R(11),1)) BNZ2 \ BNZ1 VFMADD231PS(ZMM(R3), ZMM(31), MEM(R(9),R(11),2)) BNZ2 \ BNZ1 VFMADD231PS(ZMM(R4), ZMM(31), MEM(R(9),R(10),1)) BNZ2 \ VMOVUPS(MEM(R(9) ), ZMM(R1)) \ VMOVUPS(MEM(R(9),R(11),1), ZMM(R2)) \ VMOVUPS(MEM(R(9),R(11),2), ZMM(R3)) \ VMOVUPS(MEM(R(9),R(10),1), ZMM(R4)) \ ADD(R(9), RDI) // r12 = &alpha // zmm31 = beta // r9 = c // r11 = rs_c #define UPDATE_C_2_ROWS_(R1,R2,BNZ1,BNZ2) \ \ VMULPS(ZMM(R1), ZMM(R1), MEM_1TO16(R(12))) \ VMULPS(ZMM(R2), ZMM(R2), MEM_1TO16(R(12))) \ BNZ1 VFMADD231PS(ZMM(R1), ZMM(31), MEM(R(9) )) BNZ2 \ BNZ1 VFMADD231PS(ZMM(R2), ZMM(31), MEM(R(9),R(11),1)) BNZ2 \ VMOVUPS(MEM(R(9) ), ZMM(R1)) \ VMOVUPS(MEM(R(9),R(11),1), ZMM(R2)) #define UPDATE_C_4_ROWS(R1,R2,R3,R4) UPDATE_C_4_ROWS_(R1,R2,R3,R4,,) #define UPDATE_C_2_ROWS(R1,R2) UPDATE_C_2_ROWS_(R1,R2,,) #define UPDATE_C_BZ_4_ROWS(R1,R2,R3,R4) UPDATE_C_4_ROWS_(R1,R2,R3,R4,COMMENT_BEGIN,COMMENT_END) #define UPDATE_C_BZ_2_ROWS(R1,R2) UPDATE_C_2_ROWS_(R1,R2,COMMENT_BEGIN,COMMENT_END) #define A_TIMES_B_ROW(n) VFMADD231PS(ZMM(n), ZMM(31), MEM_1TO16(R(15),n*4)) #define A_TIMES_B_ROW_PREV(n) VFMADD231PS(ZMM(n), ZMM(31), MEM_1TO16(R(15),(n-32)*4)) #define PREFETCH_A_L1(n) PREFETCH(0, MEM(R(15),A_L1_PREFETCH_DIST*4*32+n*64)) #define PREFETCH_A_L2(n) PREFETCH(1, MEM(R(15),R(14),1,n*64)) #define PREFETCH_B_L1 PREFETCH(0, MEM(RBX,B_L1_PREFETCH_DIST*4*16)) #define PREFETCH_B_L2 PREFETCH(1, MEM(RBX,R(13),1)) //One iteration of the k_r loop. //Each iteration, we prefetch A into L1 and into L2 // r15 = a // rbx = b // rcx = c // r11 = rs_c // r13 = L2_PREFETCH_DIST*4*16 // r14 = L2_PREFETCH_DIST*4*32 // r12 = 32*4 = dist. to next sliver of a // r9 = 16*4 = dist. to next sliver of b #define MAIN_LOOP_(COUNTER, PC_L1_1, PC_L1_2, PC_L2_1, PC_L2_2) \ \ /* Can this be pre-loaded for next it. in zmm30? */ \ VMOVAPS(ZMM(31), MEM(RBX)) \ \ A_TIMES_B_ROW ( 0) \ A_TIMES_B_ROW ( 1) PREFETCH_A_L1(0) \ A_TIMES_B_ROW ( 2) PREFETCH_A_L1(1) \ A_TIMES_B_ROW ( 3) PREFETCH_A_L1(2) \ A_TIMES_B_ROW ( 4) PREFETCH_A_L1(3) \ A_TIMES_B_ROW ( 5) PREFETCH_A_L2(0) \ A_TIMES_B_ROW ( 6) PC_L1_1 PREFETCH(0, MEM(RCX)) PC_L1_2 \ A_TIMES_B_ROW ( 7) PC_L1_1 ADD(RCX, R(11)) PC_L1_2 \ A_TIMES_B_ROW ( 8) \ A_TIMES_B_ROW ( 9) PC_L2_1 PREFETCH(1, MEM(RCX)) PC_L2_2 \ A_TIMES_B_ROW (10) PREFETCH_A_L2(1) \ A_TIMES_B_ROW (11) PC_L1_1 PREFETCH(0, MEM(RCX)) PC_L1_2 \ A_TIMES_B_ROW (12) PC_L1_1 ADD(RCX, R(11)) PC_L1_2 \ A_TIMES_B_ROW (13) \ A_TIMES_B_ROW (14) \ A_TIMES_B_ROW (15) PREFETCH_A_L2(2) \ A_TIMES_B_ROW (16) PC_L1_1 PREFETCH(0, MEM(RCX)) PC_L1_2 \ A_TIMES_B_ROW (17) PC_L1_1 ADD(RCX, R(11)) PC_L1_2 \ A_TIMES_B_ROW (18) \ A_TIMES_B_ROW (19) \ A_TIMES_B_ROW (20) PREFETCH_A_L2(3) \ A_TIMES_B_ROW (21) ADD(R(15), R(12)) \ A_TIMES_B_ROW_PREV(22) \ A_TIMES_B_ROW_PREV(23) PC_L2_1 ADD(RCX, R(11)) PC_L2_2 \ A_TIMES_B_ROW_PREV(24) DEC(COUNTER) \ A_TIMES_B_ROW_PREV(25) PREFETCH_B_L2 \ A_TIMES_B_ROW_PREV(26) PREFETCH_B_L1 \ A_TIMES_B_ROW_PREV(27) ADD(RBX, R(9)) \ A_TIMES_B_ROW_PREV(28) CMP(COUNTER, IMM(0)) \ A_TIMES_B_ROW_PREV(29) #define MAIN_LOOP(COUNTER) MAIN_LOOP_(COUNTER,COMMENT_BEGIN,COMMENT_END,COMMENT_BEGIN,COMMENT_END) #define MAIN_LOOP_PC_L1(COUNTER) MAIN_LOOP_(COUNTER,,,COMMENT_BEGIN,COMMENT_END) #define MAIN_LOOP_PC_L2(COUNTER) MAIN_LOOP_(COUNTER,COMMENT_BEGIN,COMMENT_END,,) //This is an array used for the scatter/gather instructions. int32_t offsets[32] __attribute__((aligned(0x1000))) = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}; //#define MONITORS //#define LOOPMON void bli_sgemm_knl_asm_30x16_knc ( dim_t k_, float* restrict alpha, float* restrict a, float* restrict b, float* restrict beta, float* restrict c, inc_t rs_c_, inc_t cs_c_, auxinfo_t* restrict data, cntx_t* restrict cntx ) { (void)data; (void)cntx; const float * a_next = bli_auxinfo_next_a( data ); const float * b_next = bli_auxinfo_next_b( data ); const int32_t * offsetPtr = &offsets[0]; const int64_t k = k_; const int64_t rs_c = rs_c_; const int64_t cs_c = cs_c_; #ifdef MONITORS int toph, topl, both, botl, midl, midh, mid2l, mid2h; #endif #ifdef LOOPMON int tlooph, tloopl, blooph, bloopl; #endif __asm__ volatile ( #ifdef MONITORS RDTSC MOV(VAR(topl), EAX) MOV(VAR(toph), EDX) #endif VPXORD(ZMM(0), ZMM(0), ZMM(0)) //clear out registers VMOVAPS(ZMM( 1), ZMM(0)) VMOVAPS(ZMM( 2), ZMM(0)) MOV(RSI, VAR(k)) //loop index VMOVAPS(ZMM( 3), ZMM(0)) MOV(R(11), VAR(rs_c)) //load row stride VMOVAPS(ZMM( 4), ZMM(0)) SAL(R(11), IMM(2)) //scale row stride VMOVAPS(ZMM( 5), ZMM(0)) MOV(R(15), VAR(a)) //load address of a VMOVAPS(ZMM( 6), ZMM(0)) MOV(RBX, VAR(b)) //load address of b VMOVAPS(ZMM( 7), ZMM(0)) VMOVAPS(ZMM( 8), ZMM(0)) LEA(R(10), MEM(R(11),R(11),2)) //r10 has 3 * r11 VMOVAPS(ZMM( 9), ZMM(0)) VMOVAPS(ZMM(10), ZMM(0)) MOV(RDI, R(11)) VMOVAPS(ZMM(11), ZMM(0)) SAL(RDI, IMM(2)) //rdi has 4*r11 VMOVAPS(ZMM(12), ZMM(0)) MOV(RCX, VAR(c)) //load address of c for prefetching VMOVAPS(ZMM(13), ZMM(0)) VMOVAPS(ZMM(14), ZMM(0)) MOV(R(8), VAR(k)) VMOVAPS(ZMM(15), ZMM(0)) VMOVAPS(ZMM(16), ZMM(0)) VMOVAPS(ZMM(17), ZMM(0)) MOV(R(13), IMM(4*16*L2_PREFETCH_DIST)) VMOVAPS(ZMM(18), ZMM(0)) MOV(R(14), IMM(4*32*L2_PREFETCH_DIST)) VMOVAPS(ZMM(19), ZMM(0)) VMOVAPS(ZMM(20), ZMM(0)) VMOVAPS(ZMM(21), ZMM(0)) VMOVAPS(ZMM(22), ZMM(0)) VMOVAPS(ZMM(23), ZMM(0)) SUB(R(8), IMM(30+L2_PREFETCH_DIST)) //Check if we have over 40 operations to do. VMOVAPS(ZMM(24), ZMM(0)) MOV(R(8), IMM(30)) VMOVAPS(ZMM(25), ZMM(0)) MOV(R(9), IMM(4*16)) //amount to increment b* by each iteration VMOVAPS(ZMM(26), ZMM(0)) MOV(R(12), IMM(4*32)) //amount to increment a* by each iteration VMOVAPS(ZMM(27), ZMM(0)) VMOVAPS(ZMM(28), ZMM(0)) VMOVAPS(ZMM(29), ZMM(0)) #ifdef MONITORS RDTSC MOV(VAR(midl), EAX) MOV(VAR(midh), EDX) #endif JLE(CONSIDER_UNDER_40) SUB(RSI, IMM(30+L2_PREFETCH_DIST)) //First 30 iterations LABEL(LOOPREFECHCL2) MAIN_LOOP_PC_L2(R(8)) JNZ(LOOPREFECHCL2) MOV(RCX, VAR(c)) //Main Loop. LABEL(LOOPMAIN) MAIN_LOOP(RSI) JNZ(LOOPMAIN) //Penultimate 22 iterations. //Break these off from the main loop to avoid prefetching extra shit. MOV(R(14), VAR(a_next)) MOV(R(13), VAR(b_next)) SUB(R(14), R(15)) SUB(R(13), RBX) //Yes, I know 10-20 = -10 MOV(RSI, IMM(10+L2_PREFETCH_DIST-20)) LABEL(LOOPMAIN2) MAIN_LOOP(RSI) JNZ(LOOPMAIN2) //Last 10 iterations MOV(R(8), IMM(10)) LABEL(LOOPREFETCHCL1) MAIN_LOOP_PC_L1(R(8)) JNZ(LOOPREFETCHCL1) JMP(POSTACCUM) //Alternate main loop, with no prefetching of C //Used when <= 40 iterations LABEL(CONSIDER_UNDER_40) MOV(RSI, VAR(k)) TEST(RSI, RSI) JZ(POSTACCUM) LABEL(LOOP_UNDER_40) MAIN_LOOP(RSI) JNZ(LOOP_UNDER_40) LABEL(POSTACCUM) #ifdef MONITORS RDTSC MOV(VAR(mid2l), EAX) MOV(VAR(mid2h), EDX) #endif MOV(R(9), VAR(c)) //load address of c for update MOV(R(12), VAR(alpha)) //load address of alpha // Check if C is row stride. If not, jump to the slow scattered update MOV(R(14), VAR(cs_c)) DEC(R(14)) JNZ(SCATTEREDUPDATE) MOV(R(14), VAR(beta)) VBROADCASTSS(ZMM(31), MEM(R(14))) MOV(EBX, MEM(R(14))) TEST(EBX, EBX) JZ(COLSTORBZ) UPDATE_C_4_ROWS( 0, 1, 2, 3) UPDATE_C_4_ROWS( 4, 5, 6, 7) UPDATE_C_4_ROWS( 8, 9,10,11) UPDATE_C_4_ROWS(12,13,14,15) UPDATE_C_4_ROWS(16,17,18,19) UPDATE_C_4_ROWS(20,21,22,23) UPDATE_C_4_ROWS(24,25,26,27) UPDATE_C_2_ROWS(28,29) JMP(END) LABEL(COLSTORBZ) UPDATE_C_BZ_4_ROWS( 0, 1, 2, 3) UPDATE_C_BZ_4_ROWS( 4, 5, 6, 7) UPDATE_C_BZ_4_ROWS( 8, 9,10,11) UPDATE_C_BZ_4_ROWS(12,13,14,15) UPDATE_C_BZ_4_ROWS(16,17,18,19) UPDATE_C_BZ_4_ROWS(20,21,22,23) UPDATE_C_BZ_4_ROWS(24,25,26,27) UPDATE_C_BZ_2_ROWS(28,29) JMP(END) LABEL(SCATTEREDUPDATE) MOV(R(13), VAR(beta)) MOV(R(10), VAR(offsetPtr)) VMOVAPS(ZMM(30), MEM(R(10))) MOV(EBX, MEM(R(13))) /* Note that this ignores the upper 32 bits in cs_c */ VPBROADCASTD(ZMM(31), VAR(cs_c)) VPMULLD(ZMM(30), ZMM(31), ZMM(30)) TEST(EBX, EBX) JZ(SCATTERBZ) UPDATE_C_ROW_SCATTERED( 0) UPDATE_C_ROW_SCATTERED( 1) UPDATE_C_ROW_SCATTERED( 2) UPDATE_C_ROW_SCATTERED( 3) UPDATE_C_ROW_SCATTERED( 4) UPDATE_C_ROW_SCATTERED( 5) UPDATE_C_ROW_SCATTERED( 6) UPDATE_C_ROW_SCATTERED( 7) UPDATE_C_ROW_SCATTERED( 8) UPDATE_C_ROW_SCATTERED( 9) UPDATE_C_ROW_SCATTERED(10) UPDATE_C_ROW_SCATTERED(11) UPDATE_C_ROW_SCATTERED(12) UPDATE_C_ROW_SCATTERED(13) UPDATE_C_ROW_SCATTERED(14) UPDATE_C_ROW_SCATTERED(15) UPDATE_C_ROW_SCATTERED(16) UPDATE_C_ROW_SCATTERED(17) UPDATE_C_ROW_SCATTERED(18) UPDATE_C_ROW_SCATTERED(19) UPDATE_C_ROW_SCATTERED(20) UPDATE_C_ROW_SCATTERED(21) UPDATE_C_ROW_SCATTERED(22) UPDATE_C_ROW_SCATTERED(23) UPDATE_C_ROW_SCATTERED(24) UPDATE_C_ROW_SCATTERED(25) UPDATE_C_ROW_SCATTERED(26) UPDATE_C_ROW_SCATTERED(27) UPDATE_C_ROW_SCATTERED(28) UPDATE_C_ROW_SCATTERED(29) JMP(END) LABEL(SCATTERBZ) UPDATE_C_BZ_ROW_SCATTERED( 0) UPDATE_C_BZ_ROW_SCATTERED( 1) UPDATE_C_BZ_ROW_SCATTERED( 2) UPDATE_C_BZ_ROW_SCATTERED( 3) UPDATE_C_BZ_ROW_SCATTERED( 4) UPDATE_C_BZ_ROW_SCATTERED( 5) UPDATE_C_BZ_ROW_SCATTERED( 6) UPDATE_C_BZ_ROW_SCATTERED( 7) UPDATE_C_BZ_ROW_SCATTERED( 8) UPDATE_C_BZ_ROW_SCATTERED( 9) UPDATE_C_BZ_ROW_SCATTERED(10) UPDATE_C_BZ_ROW_SCATTERED(11) UPDATE_C_BZ_ROW_SCATTERED(12) UPDATE_C_BZ_ROW_SCATTERED(13) UPDATE_C_BZ_ROW_SCATTERED(14) UPDATE_C_BZ_ROW_SCATTERED(15) UPDATE_C_BZ_ROW_SCATTERED(16) UPDATE_C_BZ_ROW_SCATTERED(17) UPDATE_C_BZ_ROW_SCATTERED(18) UPDATE_C_BZ_ROW_SCATTERED(19) UPDATE_C_BZ_ROW_SCATTERED(20) UPDATE_C_BZ_ROW_SCATTERED(21) UPDATE_C_BZ_ROW_SCATTERED(22) UPDATE_C_BZ_ROW_SCATTERED(23) UPDATE_C_BZ_ROW_SCATTERED(24) UPDATE_C_BZ_ROW_SCATTERED(25) UPDATE_C_BZ_ROW_SCATTERED(26) UPDATE_C_BZ_ROW_SCATTERED(27) UPDATE_C_BZ_ROW_SCATTERED(28) UPDATE_C_BZ_ROW_SCATTERED(29) LABEL(END) #ifdef MONITORS RDTSC MOV(VAR(botl), EAX) MOV(VAR(both), EDX) #endif : // output operands #ifdef MONITORS [topl] "=m" (topl), [toph] "=m" (toph), [midl] "=m" (midl), [midh] "=m" (midh), [mid2l] "=m" (mid2l), [mid2h] "=m" (mid2h), [botl] "=m" (botl), [both] "=m" (both) #endif : // input operands [k] "m" (k), [a] "m" (a), [b] "m" (b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c), [a_next] "m" (a_next), [b_next] "m" (b_next), [offsetPtr] "m" (offsetPtr) : // register clobber list "rax", "rbx", "rcx", "rdx", "rdi", "rsi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "zmm0", "zmm1", "zmm2", "zmm3", "zmm4", "zmm5", "zmm6", "zmm7", "zmm8", "zmm9", "zmm10", "zmm11", "zmm12", "zmm13", "zmm14", "zmm15", "zmm16", "zmm17", "zmm18", "zmm19", "zmm20", "zmm21", "zmm22", "zmm23", "zmm24", "zmm25", "zmm26", "zmm27", "zmm28", "zmm29", "zmm30", "zmm31", "memory" ); #ifdef LOOPMON printf("looptime = \t%d\n", bloopl - tloopl); #endif #ifdef MONITORS dim_t top = ((dim_t)toph << 32) | topl; dim_t mid = ((dim_t)midh << 32) | midl; dim_t mid2 = ((dim_t)mid2h << 32) | mid2l; dim_t bot = ((dim_t)both << 32) | botl; printf("setup =\t%u\tmain loop =\t%u\tcleanup=\t%u\ttotal=\t%u\n", mid - top, mid2 - mid, bot - mid2, bot - top); #endif } blis-0.9.0/kernels/knl/bli_kernels_knl.h000066400000000000000000000042051422157504600202150ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ GEMM_UKR_PROT( float, s, gemm_knl_asm_24x16 ) GEMM_UKR_PROT( double, d, gemm_knl_asm_24x8 ) PACKM_KER_PROT( float, s, packm_knl_asm_24xk ) PACKM_KER_PROT( float, s, packm_knl_asm_16xk ) PACKM_KER_PROT( double, d, packm_knl_asm_24xk ) PACKM_KER_PROT( double, d, packm_knl_asm_8xk ) // unused: GEMM_UKR_PROT( double, d, gemm_knl_asm_12x16 ) GEMM_UKR_PROT( double, d, gemm_knl_asm_30x8 ) GEMM_UKR_PROT( double, d, gemm_knl_asm_8x24 ) PACKM_KER_PROT( double, d, packm_knl_asm_30xk ) blis-0.9.0/kernels/old/000077500000000000000000000000001422157504600147005ustar00rootroot00000000000000blis-0.9.0/kernels/old/c99/000077500000000000000000000000001422157504600153045ustar00rootroot00000000000000blis-0.9.0/kernels/old/c99/3/000077500000000000000000000000001422157504600154465ustar00rootroot00000000000000blis-0.9.0/kernels/old/c99/3/bli_gemm_c99_4x4.c000066400000000000000000000142671422157504600205620ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENTFUNC #define GENTFUNC( ctype, ch, kername ) \ \ void PASTEMAC(ch,kername) \ ( \ dim_t k, \ ctype* restrict alpha, \ ctype* restrict a, \ ctype* restrict b, \ ctype* restrict beta, \ ctype* restrict c, inc_t rs_c, inc_t cs_c, \ auxinfo_t* restrict data, \ cntx_t* restrict cntx \ ) \ { \ ctype a0; \ ctype a1; \ ctype a2; \ ctype a3; \ \ ctype b0, b1, b2, b3; \ \ ctype ab00, ab01, ab02, ab03; \ ctype ab10, ab11, ab12, ab13; \ ctype ab20, ab21, ab22, ab23; \ ctype ab30, ab31, ab32, ab33; \ \ ctype* c00, * c01, * c02, * c03; \ ctype* c10, * c11, * c12, * c13; \ ctype* c20, * c21, * c22, * c23; \ ctype* c30, * c31, * c32, * c33; \ \ dim_t i; \ \ \ c00 = (c + 0*rs_c + 0*cs_c); \ c10 = (c + 1*rs_c + 0*cs_c); \ c20 = (c + 2*rs_c + 0*cs_c); \ c30 = (c + 3*rs_c + 0*cs_c); \ \ c01 = (c + 0*rs_c + 1*cs_c); \ c11 = (c + 1*rs_c + 1*cs_c); \ c21 = (c + 2*rs_c + 1*cs_c); \ c31 = (c + 3*rs_c + 1*cs_c); \ \ c02 = (c + 0*rs_c + 2*cs_c); \ c12 = (c + 1*rs_c + 2*cs_c); \ c22 = (c + 2*rs_c + 2*cs_c); \ c32 = (c + 3*rs_c + 2*cs_c); \ \ c03 = (c + 0*rs_c + 3*cs_c); \ c13 = (c + 1*rs_c + 3*cs_c); \ c23 = (c + 2*rs_c + 3*cs_c); \ c33 = (c + 3*rs_c + 3*cs_c); \ \ PASTEMAC(ch,set0s)( ab00 ); \ PASTEMAC(ch,set0s)( ab10 ); \ PASTEMAC(ch,set0s)( ab20 ); \ PASTEMAC(ch,set0s)( ab30 ); \ \ PASTEMAC(ch,set0s)( ab01 ); \ PASTEMAC(ch,set0s)( ab11 ); \ PASTEMAC(ch,set0s)( ab21 ); \ PASTEMAC(ch,set0s)( ab31 ); \ \ PASTEMAC(ch,set0s)( ab02 ); \ PASTEMAC(ch,set0s)( ab12 ); \ PASTEMAC(ch,set0s)( ab22 ); \ PASTEMAC(ch,set0s)( ab32 ); \ \ PASTEMAC(ch,set0s)( ab03 ); \ PASTEMAC(ch,set0s)( ab13 ); \ PASTEMAC(ch,set0s)( ab23 ); \ PASTEMAC(ch,set0s)( ab33 ); \ \ for ( i = 0; i < k; ++i ) \ { \ a0 = *(a + 0); \ a1 = *(a + 1); \ a2 = *(a + 2); \ a3 = *(a + 3); \ \ b0 = *(b + 0); \ b1 = *(b + 1); \ b2 = *(b + 2); \ b3 = *(b + 3); \ \ PASTEMAC(ch,dots)( a0, b0, ab00 ); \ PASTEMAC(ch,dots)( a1, b0, ab10 ); \ PASTEMAC(ch,dots)( a2, b0, ab20 ); \ PASTEMAC(ch,dots)( a3, b0, ab30 ); \ \ PASTEMAC(ch,dots)( a0, b1, ab01 ); \ PASTEMAC(ch,dots)( a1, b1, ab11 ); \ PASTEMAC(ch,dots)( a2, b1, ab21 ); \ PASTEMAC(ch,dots)( a3, b1, ab31 ); \ \ PASTEMAC(ch,dots)( a0, b2, ab02 ); \ PASTEMAC(ch,dots)( a1, b2, ab12 ); \ PASTEMAC(ch,dots)( a2, b2, ab22 ); \ PASTEMAC(ch,dots)( a3, b2, ab32 ); \ \ PASTEMAC(ch,dots)( a0, b3, ab03 ); \ PASTEMAC(ch,dots)( a1, b3, ab13 ); \ PASTEMAC(ch,dots)( a2, b3, ab23 ); \ PASTEMAC(ch,dots)( a3, b3, ab33 ); \ \ a += 4; \ b += 4; \ } \ \ if ( PASTEMAC(ch,eq0)( *beta ) ) \ { \ PASTEMAC(ch,set0s)( *c00 ); \ PASTEMAC(ch,set0s)( *c10 ); \ PASTEMAC(ch,set0s)( *c20 ); \ PASTEMAC(ch,set0s)( *c30 ); \ \ PASTEMAC(ch,set0s)( *c01 ); \ PASTEMAC(ch,set0s)( *c11 ); \ PASTEMAC(ch,set0s)( *c21 ); \ PASTEMAC(ch,set0s)( *c31 ); \ \ PASTEMAC(ch,set0s)( *c02 ); \ PASTEMAC(ch,set0s)( *c12 ); \ PASTEMAC(ch,set0s)( *c22 ); \ PASTEMAC(ch,set0s)( *c32 ); \ \ PASTEMAC(ch,set0s)( *c03 ); \ PASTEMAC(ch,set0s)( *c13 ); \ PASTEMAC(ch,set0s)( *c23 ); \ PASTEMAC(ch,set0s)( *c33 ); \ } \ else \ { \ PASTEMAC(ch,scals)( *beta, *c00 ); \ PASTEMAC(ch,scals)( *beta, *c10 ); \ PASTEMAC(ch,scals)( *beta, *c20 ); \ PASTEMAC(ch,scals)( *beta, *c30 ); \ \ PASTEMAC(ch,scals)( *beta, *c01 ); \ PASTEMAC(ch,scals)( *beta, *c11 ); \ PASTEMAC(ch,scals)( *beta, *c21 ); \ PASTEMAC(ch,scals)( *beta, *c31 ); \ \ PASTEMAC(ch,scals)( *beta, *c02 ); \ PASTEMAC(ch,scals)( *beta, *c12 ); \ PASTEMAC(ch,scals)( *beta, *c22 ); \ PASTEMAC(ch,scals)( *beta, *c32 ); \ \ PASTEMAC(ch,scals)( *beta, *c03 ); \ PASTEMAC(ch,scals)( *beta, *c13 ); \ PASTEMAC(ch,scals)( *beta, *c23 ); \ PASTEMAC(ch,scals)( *beta, *c33 ); \ } \ \ PASTEMAC(ch,dots)( *alpha, ab00, *c00 ); \ PASTEMAC(ch,dots)( *alpha, ab10, *c10 ); \ PASTEMAC(ch,dots)( *alpha, ab20, *c20 ); \ PASTEMAC(ch,dots)( *alpha, ab30, *c30 ); \ \ PASTEMAC(ch,dots)( *alpha, ab01, *c01 ); \ PASTEMAC(ch,dots)( *alpha, ab11, *c11 ); \ PASTEMAC(ch,dots)( *alpha, ab21, *c21 ); \ PASTEMAC(ch,dots)( *alpha, ab31, *c31 ); \ \ PASTEMAC(ch,dots)( *alpha, ab02, *c02 ); \ PASTEMAC(ch,dots)( *alpha, ab12, *c12 ); \ PASTEMAC(ch,dots)( *alpha, ab22, *c22 ); \ PASTEMAC(ch,dots)( *alpha, ab32, *c32 ); \ \ PASTEMAC(ch,dots)( *alpha, ab03, *c03 ); \ PASTEMAC(ch,dots)( *alpha, ab13, *c13 ); \ PASTEMAC(ch,dots)( *alpha, ab23, *c23 ); \ PASTEMAC(ch,dots)( *alpha, ab33, *c33 ); \ } INSERT_GENTFUNC_BASIC0( gemm_c99_4x4 ) blis-0.9.0/kernels/old/c99/3/bli_gemmtrsm_l_c99_4x4.c000066400000000000000000000053701422157504600217760ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENTFUNC #define GENTFUNC( ctype, ch, varname, gemmkerid, trsmkerid ) \ \ void PASTEMAC(ch,varname) \ ( \ dim_t k, \ ctype* restrict alpha, \ ctype* restrict a10, \ ctype* restrict a11, \ ctype* restrict b01, \ ctype* restrict b11, \ ctype* restrict c11, inc_t rs_c, inc_t cs_c, \ auxinfo_t* restrict data, \ cntx_t* restrict cntx \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ const inc_t rs_b = 4; \ const inc_t cs_b = 1; \ \ ctype* minus_one = PASTEMAC(ch,m1); \ \ PASTECH(ch,gemm_ukr_ft) \ gemm_ukr = bli_cntx_get_l3_ukr_dt( dt, gemmkerid, cntx ); \ PASTECH(ch,trsm_ukr_ft) \ trsm_ukr = bli_cntx_get_l3_ukr_dt( dt, trsmkerid, cntx ); \ \ gemm_ukr \ ( \ k, \ minus_one, \ a10, \ b01, \ alpha, \ b11, rs_b, cs_b, \ data, \ cntx \ ); \ \ trsm_ukr \ ( \ a11, \ b11, \ c11, rs_c, cs_c, \ data, \ cntx \ ); \ } INSERT_GENTFUNC_BASIC2( gemmtrsm_l_c99_4x4, BLIS_GEMM_UKR, BLIS_TRSM_L_UKR ) blis-0.9.0/kernels/old/c99/3/bli_gemmtrsm_u_c99_4x4.c000066400000000000000000000053701422157504600220070ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENTFUNC #define GENTFUNC( ctype, ch, varname, gemmkerid, trsmkerid ) \ \ void PASTEMAC(ch,varname) \ ( \ dim_t k, \ ctype* restrict alpha, \ ctype* restrict a12, \ ctype* restrict a11, \ ctype* restrict b21, \ ctype* restrict b11, \ ctype* restrict c11, inc_t rs_c, inc_t cs_c, \ auxinfo_t* restrict data, \ cntx_t* restrict cntx \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ const inc_t rs_b = 4; \ const inc_t cs_b = 1; \ \ ctype* minus_one = PASTEMAC(ch,m1); \ \ PASTECH(ch,gemm_ukr_ft) \ gemm_ukr = bli_cntx_get_l3_ukr_dt( dt, gemmkerid, cntx ); \ PASTECH(ch,trsm_ukr_ft) \ trsm_ukr = bli_cntx_get_l3_ukr_dt( dt, trsmkerid, cntx ); \ \ gemm_ukr \ ( \ k, \ minus_one, \ a12, \ b21, \ alpha, \ b11, rs_b, cs_b, \ data, \ cntx \ ); \ \ trsm_ukr \ ( \ a11, \ b11, \ c11, rs_c, cs_c, \ data, \ cntx \ ); \ } INSERT_GENTFUNC_BASIC2( gemmtrsm_u_c99_4x4, BLIS_GEMM_UKR, BLIS_TRSM_U_UKR ) blis-0.9.0/kernels/old/c99/3/bli_trsm_l_c99_4x4.c000066400000000000000000000135231422157504600211270ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENTFUNC #define GENTFUNC( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ ctype* restrict a, \ ctype* restrict b, \ ctype* restrict c, inc_t rs_c, inc_t cs_c, \ auxinfo_t* restrict data, \ cntx_t* restrict cntx \ ) \ { \ const dim_t rs_a = 1; \ const dim_t cs_a = 4; \ \ const dim_t rs_b = 4; \ const dim_t cs_b = 1; \ \ ctype a00; \ ctype a10, a11; \ ctype a20, a21, a22; \ ctype a30, a31, a32, a33; \ \ ctype b00, b01, b02, b03; \ ctype b10, b11, b12, b13; \ ctype b20, b21, b22, b23; \ ctype b30, b31, b32, b33; \ \ \ /* Load contents of B. */ \ \ b00 = *(b + 0*rs_b + 0*cs_b); \ b01 = *(b + 0*rs_b + 1*cs_b); \ b02 = *(b + 0*rs_b + 2*cs_b); \ b03 = *(b + 0*rs_b + 3*cs_b); \ \ b10 = *(b + 1*rs_b + 0*cs_b); \ b11 = *(b + 1*rs_b + 1*cs_b); \ b12 = *(b + 1*rs_b + 2*cs_b); \ b13 = *(b + 1*rs_b + 3*cs_b); \ \ b20 = *(b + 2*rs_b + 0*cs_b); \ b21 = *(b + 2*rs_b + 1*cs_b); \ b22 = *(b + 2*rs_b + 2*cs_b); \ b23 = *(b + 2*rs_b + 3*cs_b); \ \ b30 = *(b + 3*rs_b + 0*cs_b); \ b31 = *(b + 3*rs_b + 1*cs_b); \ b32 = *(b + 3*rs_b + 2*cs_b); \ b33 = *(b + 3*rs_b + 3*cs_b); \ \ \ /* iteration 0 */ \ \ a00 = *(a + 0*rs_a + 0*cs_a); \ \ PASTEMAC(ch,scals)( a00, b00 ); \ PASTEMAC(ch,scals)( a00, b01 ); \ PASTEMAC(ch,scals)( a00, b02 ); \ PASTEMAC(ch,scals)( a00, b03 ); \ \ *(b + 0*rs_b + 0*cs_b) = b00; \ *(b + 0*rs_b + 1*cs_b) = b01; \ *(b + 0*rs_b + 2*cs_b) = b02; \ *(b + 0*rs_b + 3*cs_b) = b03; \ \ *(c + 0*rs_c + 0*cs_c) = b00; \ *(c + 0*rs_c + 1*cs_c) = b01; \ *(c + 0*rs_c + 2*cs_c) = b02; \ *(c + 0*rs_c + 3*cs_c) = b03; \ \ \ /* iteration 1 */ \ \ a10 = *(a + 1*rs_a + 0*cs_a); \ a11 = *(a + 1*rs_a + 1*cs_a); \ \ PASTEMAC(ch,axmys)( a10, b00, b10 ); \ PASTEMAC(ch,axmys)( a10, b01, b11 ); \ PASTEMAC(ch,axmys)( a10, b02, b12 ); \ PASTEMAC(ch,axmys)( a10, b03, b13 ); \ \ PASTEMAC(ch,scals)( a11, b10 ); \ PASTEMAC(ch,scals)( a11, b11 ); \ PASTEMAC(ch,scals)( a11, b12 ); \ PASTEMAC(ch,scals)( a11, b13 ); \ \ *(b + 1*rs_b + 0*cs_b) = b10; \ *(b + 1*rs_b + 1*cs_b) = b11; \ *(b + 1*rs_b + 2*cs_b) = b12; \ *(b + 1*rs_b + 3*cs_b) = b13; \ \ *(c + 1*rs_c + 0*cs_c) = b10; \ *(c + 1*rs_c + 1*cs_c) = b11; \ *(c + 1*rs_c + 2*cs_c) = b12; \ *(c + 1*rs_c + 3*cs_c) = b13; \ \ \ /* iteration 2 */ \ \ a20 = *(a + 2*rs_a + 0*cs_a); \ a21 = *(a + 2*rs_a + 1*cs_a); \ a22 = *(a + 2*rs_a + 2*cs_a); \ \ PASTEMAC(ch,axmys)( a20, b00, b20 ); \ PASTEMAC(ch,axmys)( a20, b01, b21 ); \ PASTEMAC(ch,axmys)( a20, b02, b22 ); \ PASTEMAC(ch,axmys)( a20, b03, b23 ); \ \ PASTEMAC(ch,axmys)( a21, b10, b20 ); \ PASTEMAC(ch,axmys)( a21, b11, b21 ); \ PASTEMAC(ch,axmys)( a21, b12, b22 ); \ PASTEMAC(ch,axmys)( a21, b13, b23 ); \ \ PASTEMAC(ch,scals)( a22, b20 ); \ PASTEMAC(ch,scals)( a22, b21 ); \ PASTEMAC(ch,scals)( a22, b22 ); \ PASTEMAC(ch,scals)( a22, b23 ); \ \ *(b + 2*rs_b + 0*cs_b) = b20; \ *(b + 2*rs_b + 1*cs_b) = b21; \ *(b + 2*rs_b + 2*cs_b) = b22; \ *(b + 2*rs_b + 3*cs_b) = b23; \ \ *(c + 2*rs_c + 0*cs_c) = b20; \ *(c + 2*rs_c + 1*cs_c) = b21; \ *(c + 2*rs_c + 2*cs_c) = b22; \ *(c + 2*rs_c + 3*cs_c) = b23; \ \ \ /* iteration 3 */ \ \ a30 = *(a + 3*rs_a + 0*cs_a); \ a31 = *(a + 3*rs_a + 1*cs_a); \ a32 = *(a + 3*rs_a + 2*cs_a); \ a33 = *(a + 3*rs_a + 3*cs_a); \ \ PASTEMAC(ch,axmys)( a30, b00, b30 ); \ PASTEMAC(ch,axmys)( a30, b01, b31 ); \ PASTEMAC(ch,axmys)( a30, b02, b32 ); \ PASTEMAC(ch,axmys)( a30, b03, b33 ); \ \ PASTEMAC(ch,axmys)( a31, b10, b30 ); \ PASTEMAC(ch,axmys)( a31, b11, b31 ); \ PASTEMAC(ch,axmys)( a31, b12, b32 ); \ PASTEMAC(ch,axmys)( a31, b13, b33 ); \ \ PASTEMAC(ch,axmys)( a32, b20, b30 ); \ PASTEMAC(ch,axmys)( a32, b21, b31 ); \ PASTEMAC(ch,axmys)( a32, b22, b32 ); \ PASTEMAC(ch,axmys)( a32, b23, b33 ); \ \ PASTEMAC(ch,scals)( a33, b30 ); \ PASTEMAC(ch,scals)( a33, b31 ); \ PASTEMAC(ch,scals)( a33, b32 ); \ PASTEMAC(ch,scals)( a33, b33 ); \ \ *(b + 3*rs_b + 0*cs_b) = b30; \ *(b + 3*rs_b + 1*cs_b) = b31; \ *(b + 3*rs_b + 2*cs_b) = b32; \ *(b + 3*rs_b + 3*cs_b) = b33; \ \ *(c + 3*rs_c + 0*cs_c) = b30; \ *(c + 3*rs_c + 1*cs_c) = b31; \ *(c + 3*rs_c + 2*cs_c) = b32; \ *(c + 3*rs_c + 3*cs_c) = b33; \ } INSERT_GENTFUNC_BASIC0( trsm_l_c99_4x4 ) blis-0.9.0/kernels/old/c99/3/bli_trsm_u_c99_4x4.c000066400000000000000000000135611422157504600211420ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENTFUNC #define GENTFUNC( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ ctype* restrict a, \ ctype* restrict b, \ ctype* restrict c, inc_t rs_c, inc_t cs_c, \ auxinfo_t* restrict data, \ cntx_t* restrict cntx \ ) \ { \ const dim_t rs_a = 1; \ const dim_t cs_a = 4; \ \ const dim_t rs_b = 4; \ const dim_t cs_b = 1; \ \ ctype a00, a01, a02, a03; \ ctype a11, a12, a13; \ ctype a22, a23; \ ctype a33; \ \ ctype b00, b01, b02, b03; \ ctype b10, b11, b12, b13; \ ctype b20, b21, b22, b23; \ ctype b30, b31, b32, b33; \ \ \ /* Load contents of B. */ \ \ b00 = *(b + 0*rs_b + 0*cs_b); \ b01 = *(b + 0*rs_b + 1*cs_b); \ b02 = *(b + 0*rs_b + 2*cs_b); \ b03 = *(b + 0*rs_b + 3*cs_b); \ \ b10 = *(b + 1*rs_b + 0*cs_b); \ b11 = *(b + 1*rs_b + 1*cs_b); \ b12 = *(b + 1*rs_b + 2*cs_b); \ b13 = *(b + 1*rs_b + 3*cs_b); \ \ b20 = *(b + 2*rs_b + 0*cs_b); \ b21 = *(b + 2*rs_b + 1*cs_b); \ b22 = *(b + 2*rs_b + 2*cs_b); \ b23 = *(b + 2*rs_b + 3*cs_b); \ \ b30 = *(b + 3*rs_b + 0*cs_b); \ b31 = *(b + 3*rs_b + 1*cs_b); \ b32 = *(b + 3*rs_b + 2*cs_b); \ b33 = *(b + 3*rs_b + 3*cs_b); \ \ \ /* iteration 0 */ \ \ a33 = *(a + 3*rs_a + 3*cs_a); \ \ PASTEMAC(ch,scals)( a33, b30 ); \ PASTEMAC(ch,scals)( a33, b31 ); \ PASTEMAC(ch,scals)( a33, b32 ); \ PASTEMAC(ch,scals)( a33, b33 ); \ \ *(b + 3*rs_b + 0*cs_b) = b30; \ *(b + 3*rs_b + 1*cs_b) = b31; \ *(b + 3*rs_b + 2*cs_b) = b32; \ *(b + 3*rs_b + 3*cs_b) = b33; \ \ *(c + 3*rs_c + 0*cs_c) = b30; \ *(c + 3*rs_c + 1*cs_c) = b31; \ *(c + 3*rs_c + 2*cs_c) = b32; \ *(c + 3*rs_c + 3*cs_c) = b33; \ \ \ /* iteration 1 */ \ \ a22 = *(a + 2*rs_a + 2*cs_a); \ a23 = *(a + 2*rs_a + 3*cs_a); \ \ PASTEMAC(ch,axmys)( a23, b30, b20 ); \ PASTEMAC(ch,axmys)( a23, b31, b21 ); \ PASTEMAC(ch,axmys)( a23, b32, b22 ); \ PASTEMAC(ch,axmys)( a23, b33, b23 ); \ \ PASTEMAC(ch,scals)( a22, b20 ); \ PASTEMAC(ch,scals)( a22, b21 ); \ PASTEMAC(ch,scals)( a22, b22 ); \ PASTEMAC(ch,scals)( a22, b23 ); \ \ *(b + 2*rs_b + 0*cs_b) = b20; \ *(b + 2*rs_b + 1*cs_b) = b21; \ *(b + 2*rs_b + 2*cs_b) = b22; \ *(b + 2*rs_b + 3*cs_b) = b23; \ \ *(c + 2*rs_c + 0*cs_c) = b20; \ *(c + 2*rs_c + 1*cs_c) = b21; \ *(c + 2*rs_c + 2*cs_c) = b22; \ *(c + 2*rs_c + 3*cs_c) = b23; \ \ \ /* iteration 2 */ \ \ a11 = *(a + 1*rs_a + 1*cs_a); \ a12 = *(a + 1*rs_a + 2*cs_a); \ a13 = *(a + 1*rs_a + 3*cs_a); \ \ PASTEMAC(ch,axmys)( a12, b20, b10 ); \ PASTEMAC(ch,axmys)( a12, b21, b11 ); \ PASTEMAC(ch,axmys)( a12, b22, b12 ); \ PASTEMAC(ch,axmys)( a12, b23, b13 ); \ \ PASTEMAC(ch,axmys)( a13, b30, b10 ); \ PASTEMAC(ch,axmys)( a13, b31, b11 ); \ PASTEMAC(ch,axmys)( a13, b32, b12 ); \ PASTEMAC(ch,axmys)( a13, b33, b13 ); \ \ PASTEMAC(ch,scals)( a11, b10 ); \ PASTEMAC(ch,scals)( a11, b11 ); \ PASTEMAC(ch,scals)( a11, b12 ); \ PASTEMAC(ch,scals)( a11, b13 ); \ \ *(b + 1*rs_b + 0*cs_b) = b10; \ *(b + 1*rs_b + 1*cs_b) = b11; \ *(b + 1*rs_b + 2*cs_b) = b12; \ *(b + 1*rs_b + 3*cs_b) = b13; \ \ *(c + 1*rs_c + 0*cs_c) = b10; \ *(c + 1*rs_c + 1*cs_c) = b11; \ *(c + 1*rs_c + 2*cs_c) = b12; \ *(c + 1*rs_c + 3*cs_c) = b13; \ \ \ /* iteration 3 */ \ \ a00 = *(a + 0*rs_a + 0*cs_a); \ a01 = *(a + 0*rs_a + 1*cs_a); \ a02 = *(a + 0*rs_a + 2*cs_a); \ a03 = *(a + 0*rs_a + 3*cs_a); \ \ PASTEMAC(ch,axmys)( a01, b10, b00 ); \ PASTEMAC(ch,axmys)( a01, b11, b01 ); \ PASTEMAC(ch,axmys)( a01, b12, b02 ); \ PASTEMAC(ch,axmys)( a01, b13, b03 ); \ \ PASTEMAC(ch,axmys)( a02, b20, b00 ); \ PASTEMAC(ch,axmys)( a02, b21, b01 ); \ PASTEMAC(ch,axmys)( a02, b22, b02 ); \ PASTEMAC(ch,axmys)( a02, b23, b03 ); \ \ PASTEMAC(ch,axmys)( a03, b30, b00 ); \ PASTEMAC(ch,axmys)( a03, b31, b01 ); \ PASTEMAC(ch,axmys)( a03, b32, b02 ); \ PASTEMAC(ch,axmys)( a03, b33, b03 ); \ \ PASTEMAC(ch,scals)( a00, b00 ); \ PASTEMAC(ch,scals)( a00, b01 ); \ PASTEMAC(ch,scals)( a00, b02 ); \ PASTEMAC(ch,scals)( a00, b03 ); \ \ *(b + 0*rs_b + 0*cs_b) = b00; \ *(b + 0*rs_b + 1*cs_b) = b01; \ *(b + 0*rs_b + 2*cs_b) = b02; \ *(b + 0*rs_b + 3*cs_b) = b03; \ \ *(c + 0*rs_c + 0*cs_c) = b00; \ *(c + 0*rs_c + 1*cs_c) = b01; \ *(c + 0*rs_c + 2*cs_c) = b02; \ *(c + 0*rs_c + 3*cs_c) = b03; \ } INSERT_GENTFUNC_BASIC0( trsm_u_c99_4x4 ) blis-0.9.0/kernels/old/c99/bli_kernels_c99.h000066400000000000000000000045061422157504600204370ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ GEMM_UKR_PROT( gemm_c99_4x4 ) GEMM_UKR_PROT( gemm_c99_4x4 ) GEMM_UKR_PROT( gemm_c99_4x4 ) GEMM_UKR_PROT( gemm_c99_4x4 ) GEMMTRSM_UKR_PROT( gemmtrsm_l_c99_4x4 ) GEMMTRSM_UKR_PROT( gemmtrsm_l_c99_4x4 ) GEMMTRSM_UKR_PROT( gemmtrsm_l_c99_4x4 ) GEMMTRSM_UKR_PROT( gemmtrsm_l_c99_4x4 ) GEMMTRSM_UKR_PROT( gemmtrsm_u_c99_4x4 ) GEMMTRSM_UKR_PROT( gemmtrsm_u_c99_4x4 ) GEMMTRSM_UKR_PROT( gemmtrsm_u_c99_4x4 ) GEMMTRSM_UKR_PROT( gemmtrsm_u_c99_4x4 ) TRSM_UKR_PROT( trsm_l_c99_4x4 ) TRSM_UKR_PROT( trsm_l_c99_4x4 ) TRSM_UKR_PROT( trsm_l_c99_4x4 ) TRSM_UKR_PROT( trsm_l_c99_4x4 ) TRSM_UKR_PROT( trsm_u_c99_4x4 ) TRSM_UKR_PROT( trsm_u_c99_4x4 ) TRSM_UKR_PROT( trsm_u_c99_4x4 ) TRSM_UKR_PROT( trsm_u_c99_4x4 ) blis-0.9.0/kernels/old/loongson3a/000077500000000000000000000000001422157504600167625ustar00rootroot00000000000000blis-0.9.0/kernels/old/loongson3a/3/000077500000000000000000000000001422157504600171245ustar00rootroot00000000000000blis-0.9.0/kernels/old/loongson3a/3/bli_gemm_loongson3a_opt_d4x4.c000066400000000000000000000550131422157504600247360ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_dgemm_loongson3a_opt_4x4 ( dim_t k, double* restrict alpha, double* restrict a, double* restrict b, double* restrict beta, double* restrict c, inc_t rs_c, inc_t cs_c, auxinfo_t* restrict data, cntx_t* restrict cntx ) { uint64_t k_iter = k / 4; uint64_t k_left = k % 4; __asm__ volatile ( //General purpose registers // //$8=k_iter, $9=k_left //$10=a address, $11=b address //$12=prefetch a, $13=prefetch b //$14=rs_c, $15=cs_c, // //$16=c00 address, $17=c01 address, //$18=c02 address, $19=c03 address, // //Floating-point registers // //$f0=a0, $f1=a1, $f2=a4, $f3=a3 //$f4=next_a0, $f5=next_a1, $f6=next_a2, $f7=next_a3 // //$f8=b0, $f9=b1, $f10=b2, $f11=b3 //$f12=next_b0, $f13=next_b1, $f14=next_b2, $f15=next_b3 // //$f16=a0b0, $f17=a0b1, $f18=a0b2, $f19=a0b3 //$f20=a1b0, $f21=a1b1, $f22=a1b2, $f23=a1b3 //$f24=a2b0, $f25=a2b1, $f26=a2b2, $f27=a2b3 //$f28=a3b0, $f29=a3b1, $f30=a3b2, $f31=a3b3 // "ld $8, %0 \n\t" //load k_iter "dmtc1 $0, $f16 \n\t" //Init "ld $9, %1 \n\t" //load k_left "dmtc1 $0, $f17 \n\t" //Init "ld $14, %7 \n\t" //load rs_c "dmtc1 $0, $f18 \n\t" //Init "ld $15, %8 \n\t" //load cs_c "dmtc1 $0, $f19 \n\t" //Init "ld $16, %6 \n\t" //load c "dmtc1 $0, $f20 \n\t" //Init "ld $10, %2 \n\t" //load a "dmtc1 $0, $f21 \n\t" //Init "ld $11, %3 \n\t" //load b "dmtc1 $0, $f22 \n\t" //Init "dsll $14, $14, 3 \n\t" //rs_c * sizeof(double) "dmtc1 $0, $f23 \n\t" //Init "dsll $15, $15, 3 \n\t" //cs_c * sizeof(double) "dmtc1 $0, $f24 \n\t" //Init "dadd $17, $16, $15 \n\t" //c01 address "ld $12, %9 \n\t" //load kc "dmtc1 $0, $f25 \n\t" //Init "dmtc1 $0, $f26 \n\t" //Init "dadd $18, $17, $15 \n\t" //c02 address "dsll $13, $12, 5 \n\t" //B prefetch distance= next panel B(nr*kc = kc*4*8bytes = kc<<5) "dmtc1 $0, $f27 \n\t" //Init "dmtc1 $0, $f28 \n\t" //Init "dadd $19, $18, $15 \n\t" //c03 address "dsll $12, $12, 4 \n\t" //A prefetch distance= panel A/2(mr*kc/2 = kc*4*8bytes/2 = kc<<4) "dmtc1 $0, $f29 \n\t" //Init "dmtc1 $0, $f30 \n\t" //Init "dadd $13, $11, $13 \n\t" //B prefetch address "ld $0, 0($16) \n\t" //prefetch c00 "dmtc1 $0, $f31 \n\t" //Init "dadd $12, $10, $12 \n\t" //A prefetch address "ld $0, 0($17) \n\t" //prefetch c01 "gsLQC1 $f1, $f0, 0($10) \n\t" //load 2 values from a "gsLQC1 $f9, $f8, 0($11) \n\t" //load 2 values from b "gsLQC1 $f3, $f2, 1*16($10) \n\t" //load 2 values from a "gsLQC1 $f11, $f10, 1*16($11) \n\t" //load 2 values from b "ld $0, 0($18) \n\t" //prefetch c02 "ld $0, 0($19) \n\t" //prefetch c03 "beqz $8, .Remain \n\t" ".align 4 \n\t" ".MainLoop: \n\t" " \n\t" //iteration 0 "daddiu $8, $8, -1 \n\t" //k_iter-- "gsLQC1 $f5, $f4, 2*16($10) \n\t" //load next 2 values from a "madd.d $f16, $f16, $f0, $f8 \n\t" //a0b0 "madd.d $f20, $f20, $f1, $f8 \n\t" //a1b0 " \n\t" "gsLQC1 $f13, $f12, 2*16($11) \n\t" //load next 2 values from b "madd.d $f17, $f17, $f0, $f9 \n\t" //a0b1 "madd.d $f21, $f21, $f1, $f9 \n\t" //a1b1 " \n\t" "gsLQC1 $f7, $f6, 3*16($10) \n\t" //load next 2 values from a "madd.d $f24, $f24, $f2, $f8 \n\t" //a2b0 "madd.d $f28, $f28, $f3, $f8 \n\t" //a3b0 " \n\t" "gsLQC1 $f15, $f14, 3*16($11) \n\t" //load next 2 values from b "madd.d $f25, $f25, $f2, $f9 \n\t" //a2b1 "madd.d $f29, $f29, $f3, $f9 \n\t" //a3b1 " \n\t" "ld $0, 0($13) \n\t" //prefetch B "madd.d $f18, $f18, $f0, $f10 \n\t" //a0b2 "madd.d $f22, $f22, $f1, $f10 \n\t" //a1b2 " \n\t" "madd.d $f19, $f19, $f0, $f11 \n\t" //a0b3 "madd.d $f23, $f23, $f1, $f11 \n\t" //a1b3 " \n\t" "ld $0, 0($12) \n\t" //prefetch A "madd.d $f26, $f26, $f2, $f10 \n\t" //a2b2 "madd.d $f30, $f30, $f3, $f10 \n\t" //a3b2 " \n\t" "madd.d $f27, $f27, $f2, $f11 \n\t" //a2b3 "madd.d $f31, $f31, $f3, $f11 \n\t" //a3b3 " \n\t" //iteration 1 "gsLQC1 $f1, $f0, 4*16($10) \n\t" //load next 2 values from a "madd.d $f16, $f16, $f4, $f12 \n\t" //a0b0 "madd.d $f20, $f20, $f5, $f12 \n\t" //a1b0 " \n\t" "gsLQC1 $f9, $f8, 4*16($11) \n\t" //load next 2 values from b "madd.d $f17, $f17, $f4, $f13 \n\t" //a0b1 "madd.d $f21, $f21, $f5, $f13 \n\t" //a1b1 " \n\t" "gsLQC1 $f3, $f2, 5*16($10) \n\t" //load next 2 values from a "madd.d $f24, $f24, $f6, $f12 \n\t" //a2b0 "madd.d $f28, $f28, $f7, $f12 \n\t" //a3b0 " \n\t" "gsLQC1 $f11, $f10, 5*16($11) \n\t" //load next 2 values from b "madd.d $f25, $f25, $f6, $f13 \n\t" //a2b1 "madd.d $f29, $f29, $f7, $f13 \n\t" //a3b1 " \n\t" "ld $0, 4*8($13) \n\t" //prefetch B "madd.d $f18, $f18, $f4, $f14 \n\t" //a0b2 "madd.d $f22, $f22, $f5, $f14 \n\t" //a1b2 " \n\t" "madd.d $f19, $f19, $f4, $f15 \n\t" //a0b3 "madd.d $f23, $f23, $f5, $f15 \n\t" //a1b3 " \n\t" "ld $0, 4*8($12) \n\t" //prefetch A "madd.d $f26, $f26, $f6, $f14 \n\t" //a2b2 "madd.d $f30, $f30, $f7, $f14 \n\t" //a3b2 " \n\t" "madd.d $f27, $f27, $f6, $f15 \n\t" //a2b3 "madd.d $f31, $f31, $f7, $f15 \n\t" //a3b3 " \n\t" //iteration 2 "gsLQC1 $f5, $f4, 6*16($10) \n\t" //load next 2 values from a "madd.d $f16, $f16, $f0, $f8 \n\t" //a0b0 "madd.d $f20, $f20, $f1, $f8 \n\t" //a1b0 " \n\t" "gsLQC1 $f13, $f12, 6*16($11) \n\t" //load next 2 values from b "madd.d $f17, $f17, $f0, $f9 \n\t" //a0b1 "madd.d $f21, $f21, $f1, $f9 \n\t" //a1b1 " \n\t" "gsLQC1 $f7, $f6, 7*16($10) \n\t" //load next 2 values from a "madd.d $f24, $f24, $f2, $f8 \n\t" //a2b0 "madd.d $f28, $f28, $f3, $f8 \n\t" //a3b0 "daddu $10, $10, 16*8 \n\t" //move A address " \n\t" "gsLQC1 $f15, $f14, 7*16($11) \n\t" //load next 2 values from b "madd.d $f25, $f25, $f2, $f9 \n\t" //a2b1 "madd.d $f29, $f29, $f3, $f9 \n\t" //a3b1 "daddu $11, $11, 16*8 \n\t" //move B address " \n\t" "ld $0, 8*8($13) \n\t" //prefetch B "madd.d $f18, $f18, $f0, $f10 \n\t" //a0b2 "madd.d $f22, $f22, $f1, $f10 \n\t" //a1b2 " \n\t" "madd.d $f19, $f19, $f0, $f11 \n\t" //a0b3 "madd.d $f23, $f23, $f1, $f11 \n\t" //a1b3 " \n\t" "ld $0, 8*8($12) \n\t" //prefetch A "madd.d $f26, $f26, $f2, $f10 \n\t" //a2b2 "madd.d $f30, $f30, $f3, $f10 \n\t" //a3b2 " \n\t" "madd.d $f27, $f27, $f2, $f11 \n\t" //a2b3 "madd.d $f31, $f31, $f3, $f11 \n\t" //a3b3 " \n\t" //iteration 3 "gsLQC1 $f1, $f0, 0($10) \n\t" //load next 2 values from a "madd.d $f16, $f16, $f4, $f12 \n\t" //a0b0 "madd.d $f20, $f20, $f5, $f12 \n\t" //a1b0 " \n\t" "gsLQC1 $f9, $f8, 0($11) \n\t" //load next 2 values from b "madd.d $f17, $f17, $f4, $f13 \n\t" //a0b1 "madd.d $f21, $f21, $f5, $f13 \n\t" //a1b1 " \n\t" "gsLQC1 $f3, $f2, 1*16($10) \n\t" //load next 2 values from a "madd.d $f24, $f24, $f6, $f12 \n\t" //a2b0 "madd.d $f28, $f28, $f7, $f12 \n\t" //a3b0 " \n\t" "gsLQC1 $f11, $f10, 1*16($11) \n\t" //load next 2 values from b "madd.d $f25, $f25, $f6, $f13 \n\t" //a2b1 "madd.d $f29, $f29, $f7, $f13 \n\t" //a3b1 " \n\t" "ld $0, 12*8($13) \n\t" //prefetch B "madd.d $f18, $f18, $f4, $f14 \n\t" //a0b2 "madd.d $f22, $f22, $f5, $f14 \n\t" //a1b2 "daddu $13, $13, 16*8 \n\t" //move prefetch B address " \n\t" "madd.d $f19, $f19, $f4, $f15 \n\t" //a0b3 "madd.d $f23, $f23, $f5, $f15 \n\t" //a1b3 " \n\t" "ld $0, 12*8($12) \n\t" //prefetch A "madd.d $f26, $f26, $f6, $f14 \n\t" //a2b2 "madd.d $f30, $f30, $f7, $f14 \n\t" //a3b2 "daddu $12, $12, 16*8 \n\t" //move prefetch B address " \n\t" "madd.d $f27, $f27, $f6, $f15 \n\t" //a2b3 "madd.d $f31, $f31, $f7, $f15 \n\t" //a3b3 "bnez $8, .MainLoop \n\t" ".align 4 \n\t" ".Remain: \n\t" //deal with the tail. k%4 "beqz $9, .StoreC \n\t" "andi $8, $9, 2 \n\t" "nop \n\t" "nop \n\t" "beqz $8, .Remaink1 \n\t" "nop \n\t" " \n\t" // k%4=2 "gsLQC1 $f5, $f4, 2*16($10) \n\t" //load next 2 values from a "madd.d $f16, $f16, $f0, $f8 \n\t" //a0b0 "madd.d $f20, $f20, $f1, $f8 \n\t" //a1b0 " \n\t" "gsLQC1 $f13, $f12, 2*16($11) \n\t" //load next 2 values from b "madd.d $f17, $f17, $f0, $f9 \n\t" //a0b1 "madd.d $f21, $f21, $f1, $f9 \n\t" //a1b1 " \n\t" "gsLQC1 $f7, $f6, 3*16($10) \n\t" //load next 2 values from a "madd.d $f24, $f24, $f2, $f8 \n\t" //a2b0 "madd.d $f28, $f28, $f3, $f8 \n\t" //a3b0 "daddu $10, $10, 8*8 \n\t" //move A address " \n\t" "gsLQC1 $f15, $f14, 3*16($11) \n\t" //load next 2 values from b "madd.d $f25, $f25, $f2, $f9 \n\t" //a2b1 "madd.d $f29, $f29, $f3, $f9 \n\t" //a3b1 "daddu $11, $11, 8*8 \n\t" //move B address " \n\t" "ld $0, 0($13) \n\t" //prefetch B "madd.d $f18, $f18, $f0, $f10 \n\t" //a0b2 "madd.d $f22, $f22, $f1, $f10 \n\t" //a1b2 " \n\t" "madd.d $f19, $f19, $f0, $f11 \n\t" //a0b3 "madd.d $f23, $f23, $f1, $f11 \n\t" //a1b3 " \n\t" "ld $0, 0($12) \n\t" //prefetch A "madd.d $f26, $f26, $f2, $f10 \n\t" //a2b2 "madd.d $f30, $f30, $f3, $f10 \n\t" //a3b2 " \n\t" "madd.d $f27, $f27, $f2, $f11 \n\t" //a2b3 "madd.d $f31, $f31, $f3, $f11 \n\t" //a3b3 " \n\t" "gsLQC1 $f1, $f0, 0*16($10) \n\t" //load next 2 values from a "madd.d $f16, $f16, $f4, $f12 \n\t" //a0b0 "madd.d $f20, $f20, $f5, $f12 \n\t" //a1b0 " \n\t" "gsLQC1 $f9, $f8, 0*16($11) \n\t" //load next 2 values from b "madd.d $f17, $f17, $f4, $f13 \n\t" //a0b1 "madd.d $f21, $f21, $f5, $f13 \n\t" //a1b1 " \n\t" "gsLQC1 $f3, $f2, 1*16($10) \n\t" //load next 2 values from a "madd.d $f24, $f24, $f6, $f12 \n\t" //a2b0 "madd.d $f28, $f28, $f7, $f12 \n\t" //a3b0 " \n\t" "gsLQC1 $f11, $f10, 1*16($11) \n\t" //load next 2 values from b "madd.d $f25, $f25, $f6, $f13 \n\t" //a2b1 "madd.d $f29, $f29, $f7, $f13 \n\t" //a3b1 " \n\t" "ld $0, 4*8($13) \n\t" //prefetch B "madd.d $f18, $f18, $f4, $f14 \n\t" //a0b2 "madd.d $f22, $f22, $f5, $f14 \n\t" //a1b2 " \n\t" "daddu $13, $13, 8*8 \n\t" "madd.d $f19, $f19, $f4, $f15 \n\t" //a0b3 "madd.d $f23, $f23, $f5, $f15 \n\t" //a1b3 " \n\t" "ld $0, 4*8($12) \n\t" //prefetch A "madd.d $f26, $f26, $f6, $f14 \n\t" //a2b2 "madd.d $f30, $f30, $f7, $f14 \n\t" //a3b2 " \n\t" "daddu $12, $12, 8*8 \n\t" "madd.d $f27, $f27, $f6, $f15 \n\t" //a2b3 "madd.d $f31, $f31, $f7, $f15 \n\t" //a3b3 ".align 4 \n\t" ".Remaink1: \n\t" // k%4=1 "andi $8, $9, 1 \n\t" "beqz $8, .StoreC \n\t" "nop \n\t" " \n\t" "ld $0, 0($13) \n\t" //prefetch B "madd.d $f16, $f16, $f0, $f8 \n\t" //a0b0 "madd.d $f20, $f20, $f1, $f8 \n\t" //a1b0 " \n\t" "madd.d $f17, $f17, $f0, $f9 \n\t" //a0b1 "madd.d $f21, $f21, $f1, $f9 \n\t" //a1b1 " \n\t" "ld $0, 0($12) \n\t" //prefetch A "madd.d $f24, $f24, $f2, $f8 \n\t" //a2b0 "madd.d $f28, $f28, $f3, $f8 \n\t" //a3b0 " \n\t" "madd.d $f25, $f25, $f2, $f9 \n\t" //a2b1 "madd.d $f29, $f29, $f3, $f9 \n\t" //a3b1 " \n\t" "madd.d $f18, $f18, $f0, $f10 \n\t" //a0b2 "madd.d $f22, $f22, $f1, $f10 \n\t" //a1b2 " \n\t" "madd.d $f19, $f19, $f0, $f11 \n\t" //a0b3 "madd.d $f23, $f23, $f1, $f11 \n\t" //a1b3 " \n\t" "madd.d $f26, $f26, $f2, $f10 \n\t" //a2b2 "madd.d $f30, $f30, $f3, $f10 \n\t" //a3b2 " \n\t" "madd.d $f27, $f27, $f2, $f11 \n\t" //a2b3 "madd.d $f31, $f31, $f3, $f11 \n\t" //a3b3 ".align 4 \n\t" ".StoreC: \n\t" //Write C " \n\t" //$f14=alpha, $f15=beta " \n\t" "ld $8, %4 \n\t" //load alpha address "ld $9, %5 \n\t" //load beta address "ldc1 $f14, 0($8) \n\t" //load alpha "ldc1 $f15, 0($9) \n\t" //load beta " \n\t" "ldc1 $f0, 0($16) \n\t" //load c00 "dadd $20, $16, $14 \n\t" "ldc1 $f1, 0($17) \n\t" //load c01 "dadd $21, $17, $14 \n\t" "ldc1 $f2, 0($18) \n\t" //load c02 "dadd $22, $18, $14 \n\t" "ldc1 $f3, 0($19) \n\t" //load c03 "dadd $23, $19, $14 \n\t" " \n\t" "ldc1 $f4, 0($20) \n\t" //load c10 "dadd $8, $20, $14 \n\t" "mul.d $f0, $f0, $f15 \n\t" //c00 * beta "ldc1 $f5, 0($21) \n\t" //load c11 "dadd $9, $21, $14 \n\t" "mul.d $f1, $f1, $f15 \n\t" //c01 * beta "ldc1 $f6, 0($22) \n\t" //load c12 "dadd $10, $22, $14 \n\t" "mul.d $f2, $f2, $f15 \n\t" //c02 * beta "ldc1 $f7, 0($23) \n\t" //load c13 "dadd $11, $23, $14 \n\t" "mul.d $f3, $f3, $f15 \n\t" //c03 * beta " \n\t" "ldc1 $f8, 0($8) \n\t" //load c20 "dadd $12, $8, $14 \n\t" "mul.d $f4, $f4, $f15 \n\t" //c10 * beta "madd.d $f16, $f0, $f16, $f14\n\t" //c00+=alpha*a0b0 "ldc1 $f9, 0($9) \n\t" //load c21 "dadd $13, $9, $14 \n\t" "mul.d $f5, $f5, $f15 \n\t" //c11 * beta "madd.d $f17, $f1, $f17, $f14\n\t" //c01+=alpha*a0b1 "ldc1 $f10, 0($10) \n\t" //load c22 "dadd $24, $10, $14 \n\t" "mul.d $f6, $f6, $f15 \n\t" //c12 * beta "madd.d $f18, $f2, $f18, $f14\n\t" //c02+=alpha*a0b2 "ldc1 $f11, 0($11) \n\t" //load c23 "dadd $25, $11, $14 \n\t" "mul.d $f7, $f7, $f15 \n\t" //c13 * beta "madd.d $f19, $f3, $f19, $f14\n\t" //c03+=alpha*a0b3 " \n\t" "ldc1 $f12, 0($12) \n\t" //load c30 "mul.d $f8, $f8, $f15 \n\t" //c20 * beta "madd.d $f20, $f4, $f20, $f14 \n\t" //c10+=alpha*a1b0 "ldc1 $f13, 0($13) \n\t" //load c31 "mul.d $f9, $f9, $f15 \n\t" //c21 * beta "madd.d $f21, $f5, $f21, $f14 \n\t" //c11+=alpha*a1b1 "ldc1 $f0, 0($24) \n\t" //load c32 "mul.d $f10, $f10, $f15 \n\t" //c22 * beta "madd.d $f22, $f6, $f22, $f14 \n\t" //c12+=alpha*a1b2 "ldc1 $f1, 0($25) \n\t" //load c33 "mul.d $f11, $f11, $f15 \n\t" //c23 * beta "madd.d $f23, $f7, $f23, $f14 \n\t" //c13+=alpha*a1b3 " \n\t" "sdc1 $f16, 0($16) \n\t" //store c00 "mul.d $f12, $f12, $f15 \n\t" //c30 * beta "madd.d $f24, $f8, $f24, $f14 \n\t" //c20+=alpha*a2b0 "sdc1 $f17, 0($17) \n\t" //store c01 "mul.d $f13, $f13, $f15 \n\t" //c31 * beta "madd.d $f25, $f9, $f25, $f14 \n\t" //c21+=alpha*a2b1 "sdc1 $f18, 0($18) \n\t" //store c02 "mul.d $f0, $f0, $f15 \n\t" //c32 * beta "madd.d $f26, $f10, $f26, $f14 \n\t" //c22+=alpha*a2b2 "sdc1 $f19, 0($19) \n\t" //store c03 "mul.d $f1, $f1, $f15 \n\t" //c33 * beta "madd.d $f27, $f11, $f27, $f14 \n\t" //c23+=alpha*a2b3 " \n\t" "sdc1 $f20, 0($20) \n\t" //store c10 "madd.d $f28, $f12, $f28, $f14 \n\t" //c30+=alpha*a3b0 "sdc1 $f21, 0($21) \n\t" //store c11 "madd.d $f29, $f13, $f29, $f14 \n\t" //c31+=alpha*a3b1 "sdc1 $f22, 0($22) \n\t" //store c12 "madd.d $f30, $f0, $f30, $f14 \n\t" //c32+=alpha*a3b2 "sdc1 $f23, 0($23) \n\t" //store c13 "madd.d $f31, $f1, $f31, $f14 \n\t" //c33+=alpha*a3b3 " \n\t" "sdc1 $f24, 0($8) \n\t" //store c20 "sdc1 $f25, 0($9) \n\t" //store c21 "sdc1 $f26, 0($10) \n\t" //store c22 "sdc1 $f27, 0($11) \n\t" //store c23 " \n\t" "sdc1 $f28, 0($12) \n\t" //store c30 "sdc1 $f29, 0($13) \n\t" //store c31 "sdc1 $f30, 0($24) \n\t" //store c32 "sdc1 $f31, 0($25) \n\t" //store c33 " \n\t" ://output operands (none) ://input operands "m" (k_iter), "m" (k_left), "m" (a), "m" (b), "m" (alpha), "m" (beta), "m" (c), "m" (rs_c), "m" (cs_c), "m" (k) ://register clober list //general purpose registers "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23", "$24", "$25", //floating-point registers "$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7", "$f8", "$f9", "$f10", "$f11", "$f12", "$f13", "$f14", "$f15", "$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23", "$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "$f30", "$f31", "memory" ); } blis-0.9.0/kernels/old/nacl/000077500000000000000000000000001422157504600156155ustar00rootroot00000000000000blis-0.9.0/kernels/old/nacl/pnacl/000077500000000000000000000000001422157504600167125ustar00rootroot00000000000000blis-0.9.0/kernels/old/nacl/pnacl/1/000077500000000000000000000000001422157504600170525ustar00rootroot00000000000000blis-0.9.0/kernels/old/nacl/pnacl/1/bli_axpyv_opt.c000066400000000000000000000115241422157504600221000ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #if PPAPI_RELEASE >= 36 typedef float v4sf __attribute__ ((vector_size(16))); inline v4sf v4sf_splat(float x) { return (v4sf) { x, x, x, x }; } inline v4sf v4sf_load(const float* a) { return *((const v4sf*)a); } inline v4sf v4sf_cload(const scomplex* a) { return *((const v4sf*)a); } inline void v4sf_store(float* a, v4sf x) { *((v4sf*)a) = x; } inline void v4sf_cstore(scomplex* a, v4sf x) { *((v4sf*)a) = x; } inline v4sf v4sf_zero() { return (v4sf) { 0.0f, 0.0f, 0.0f, 0.0f }; } #endif void bli_saxpyv_opt( conj_t conjx, dim_t n, float alpha[restrict static 1], float x[restrict static n], inc_t incx, float y[restrict static n], inc_t incy) { if (bli_zero_dim1(n)) { return; } if (bli_seq0(*alpha)) { return; } #if PPAPI_RELEASE >= 36 if (!bli_has_nonunit_inc2(incx, incy)) { const v4sf alphav = v4sf_splat(*alpha); while (n >= 4) { const v4sf xv = v4sf_load(x); v4sf yv = v4sf_load(y); yv += xv * alphav; v4sf_store(y, yv); x += 4; y += 4; n -= 4; } const float alphac = *alpha; while (n--) { (*y++) += (*x++) * alphac; } } #endif /* Just call the reference implementation. */ BLIS_SAXPYV_KERNEL_REF( conjx, n, alpha, x, incx, y, incy); } void bli_caxpyv_opt( conj_t conjx, dim_t n, scomplex alpha[restrict static 1], scomplex x[restrict static n], inc_t incx, scomplex y[restrict static n], inc_t incy) { if (bli_zero_dim1(n)) { return; } if (bli_ceq0(*alpha)) { return; } #if PPAPI_RELEASE >= 36 if (!bli_has_nonunit_inc2(incx, incy)) { if (bli_is_noconj(conjx)) { const v4sf alphav0 = v4sf_splat(alpha->real); const v4sf alphav1 = (v4sf) { -alpha->imag, alpha->imag, -alpha->imag, alpha->imag }; while (n >= 2) { const v4sf xv0 = v4sf_cload(x); v4sf yv = v4sf_cload(y); const v4sf xv1 = __builtin_shufflevector(xv0, xv0, 1, 0, 3, 2); yv += xv0 * alphav0 + xv1 * alphav1; v4sf_cstore(y, yv); x += 2; y += 2; n -= 2; } const float alphar = alpha->real; const float alphai = alpha->imag; while (n--) { const float xr = x->real; const float xi = x->imag; const float yr = y->real; const float yi = y->imag; y->real = yr + xr * alphar - xi * alphai; y->imag = yi + xr * alphai + xi * alphar; x += 1; y += 1; } } else { const v4sf alphav0 = (v4sf) { alpha->real, -alpha->real, alpha->real, -alpha->real }; const v4sf alphav1 = v4sf_splat(alpha->imag); while (n >= 2) { const v4sf xv0 = v4sf_cload(x); v4sf yv = v4sf_cload(y); const v4sf xv1 = __builtin_shufflevector(xv0, xv0, 1, 0, 3, 2); yv += xv0 * alphav0 + xv1 * alphav1; v4sf_cstore(y, yv); x += 2; y += 2; n -= 2; } const float alphar = alpha->real; const float alphai = alpha->imag; while (n--) { const float xr = x->real; const float xi = x->imag; const float yr = y->real; const float yi = y->imag; y->real = yr + xr * alphar + xi * alphai; y->imag = yi + xr * alphai - xi * alphar; x += 1; y += 1; } } } #endif /* Just call the reference implementation. */ BLIS_CAXPYV_KERNEL_REF( conjx, n, alpha, x, incx, y, incy); } blis-0.9.0/kernels/old/nacl/pnacl/1/bli_dotv_opt.c000066400000000000000000000336141422157504600217110ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #if PPAPI_RELEASE >= 36 typedef float v4sf __attribute__ ((vector_size(16))); inline v4sf v4sf_splat(float x) { return (v4sf) { x, x, x, x }; } inline v4sf v4sf_load(const float* a) { return *((const v4sf*)a); } inline v4sf v4sf_cload(const scomplex* a) { return *((const v4sf*)a); } inline void v4sf_store(float* a, v4sf x) { *((v4sf*)a) = x; } inline void v4sf_cstore(scomplex* a, v4sf x) { *((v4sf*)a) = x; } inline v4sf v4sf_zero() { return (v4sf) { 0.0f, 0.0f, 0.0f, 0.0f }; } #endif void bli_sdotv_opt( conj_t conjx, conj_t conjy, dim_t n, float x[restrict static n], inc_t incx, float y[restrict static n], inc_t incy, float rho[restrict static 1]) { #if PPAPI_RELEASE >= 36 // If the vector lengths are zero, set rho to zero and return. if (bli_zero_dim1(n)) { *rho = 0.0f; return; } // If there is anything that would interfere with our use of aligned // vector loads/stores, call the reference implementation. if (bli_has_nonunit_inc2(incx, incy)) { float sum0 = 0.0f, sum1 = 0.0f, sum2 = 0.0f, sum3 = 0.0f, sum4 = 0.0f, sum5 = 0.0f; while (n >= 6) { sum0 += (*x) * (*y); x += incx; y += incy; sum1 += (*x) * (*y); x += incx; y += incy; sum2 += (*x) * (*y); x += incx; y += incy; sum3 += (*x) * (*y); x += incx; y += incy; sum4 += (*x) * (*y); x += incx; y += incy; sum5 += (*x) * (*y); x += incx; y += incy; n -= 6; } float sum = (sum0 + sum1 + sum2) + (sum3 + sum4 + sum5); while (n--) { sum += (*x) * (*y); x += incx; y += incy; } *rho = sum; } else { v4sf vsum0 = v4sf_zero(), vsum1 = v4sf_zero(), vsum2 = v4sf_zero(); v4sf vsum3 = v4sf_zero(), vsum4 = v4sf_zero(), vsum5 = v4sf_zero(); while (n >= 24) { vsum0 += v4sf_load(x) * v4sf_load(y); vsum1 += v4sf_load(x+4) * v4sf_load(y+4); vsum2 += v4sf_load(x+8) * v4sf_load(y+8); vsum3 += v4sf_load(x+12) * v4sf_load(y+12); vsum4 += v4sf_load(x+16) * v4sf_load(y+16); vsum5 += v4sf_load(x+20) * v4sf_load(y+20); x += 24; y += 24; n -= 24; } v4sf vsum = (vsum0 + vsum1 + vsum2) + (vsum3 + vsum4 + vsum5); while (n >= 4) { vsum += v4sf_load(x) * v4sf_load(y); x += 4; y += 4; n -= 4; } float sum = (vsum[0] + vsum[1]) + (vsum[2] + vsum[3]); while (n--) { sum += (*x++) * (*y++); } *rho = sum; } #else float sum0 = 0.0f, sum1 = 0.0f, sum2 = 0.0f, sum3 = 0.0f, sum4 = 0.0f, sum5 = 0.0f; while (n >= 6) { sum0 += (*x) * (*y); x += incx; y += incy; sum1 += (*x) * (*y); x += incx; y += incy; sum2 += (*x) * (*y); x += incx; y += incy; sum3 += (*x) * (*y); x += incx; y += incy; sum4 += (*x) * (*y); x += incx; y += incy; sum5 += (*x) * (*y); x += incx; y += incy; n -= 6; } float sum = (sum0 + sum1 + sum2) + (sum3 + sum4 + sum5); while (n--) { sum += (*x) * (*y); x += incx; y += incy; } *rho = sum; #endif } void bli_ddotv_opt( conj_t conjx, conj_t conjy, dim_t n, double x[restrict static n], inc_t incx, double y[restrict static n], inc_t incy, double rho[restrict static 1]) { double sum0 = 0.0, sum1 = 0.0, sum2 = 0.0, sum3 = 0.0, sum4 = 0.0, sum5 = 0.0; while (n >= 6) { sum0 += (*x) * (*y); x += incx; y += incy; sum1 += (*x) * (*y); x += incx; y += incy; sum2 += (*x) * (*y); x += incx; y += incy; sum3 += (*x) * (*y); x += incx; y += incy; sum4 += (*x) * (*y); x += incx; y += incy; sum5 += (*x) * (*y); x += incx; y += incy; n -= 6; } double sum = (sum0 + sum1 + sum2) + (sum3 + sum4 + sum5); while (n--) { sum += (*x) * (*y); x += incx; y += incy; } *rho = sum; } void bli_cdotv_opt( conj_t conjx, conj_t conjy, dim_t n, scomplex x[restrict static n], inc_t incx, scomplex y[restrict static n], inc_t incy, scomplex rho[restrict static 1]) { if (bli_is_conj(conjy)) { bli_toggle_conj(&conjx); } if (bli_zero_dim1(n)) { rho->real = 0.0f; rho->imag = 0.0f; return; } float sumr; float sumi; #if PPAPI_RELEASE >= 36 if (bli_is_noconj(conjx)) { if (bli_has_nonunit_inc2(incx, incy)) { float sum0r = 0.0f, sum1r = 0.0f; float sum0i = 0.0f, sum1i = 0.0f; while (n >= 2) { const float x0r = x->real; const float x0i = x->imag; const float y0r = y->real; const float y0i = y->imag; sum0r += x0r * y0r - x0i * y0i; sum0i += x0r * y0i + x0i * y0r; x += incx; y += incy; const float x1r = x->real; const float x1i = x->imag; const float y1r = y->real; const float y1i = y->imag; sum1r += x1r * y1r - x1i * y1i; sum1i += x1r * y1i + x1i * y1r; x += incx; y += incy; n -= 2; } sumr = sum0r + sum1r; sumi = sum0i + sum1i; } else { v4sf sumv0r = v4sf_zero(), sumv1r = v4sf_zero(); v4sf sumv0i = v4sf_zero(), sumv1i = v4sf_zero(); while (n >= 8) { const v4sf xv0t = v4sf_cload(x); const v4sf xv0b = v4sf_cload(x+2); const v4sf yv0t = v4sf_cload(y); const v4sf yv0b = v4sf_cload(y+2); const v4sf xv0r = __builtin_shufflevector(xv0t, xv0b, 0, 2, 4, 6); const v4sf xv0i = __builtin_shufflevector(xv0t, xv0b, 1, 3, 5, 7); const v4sf yv0r = __builtin_shufflevector(yv0t, yv0b, 0, 2, 4, 6); const v4sf yv0i = __builtin_shufflevector(yv0t, yv0b, 1, 3, 5, 7); sumv0r += xv0r * yv0r - xv0i * yv0i; sumv0i += xv0r * yv0i + xv0i * yv0r; const v4sf xv1t = v4sf_cload(x+4); const v4sf xv1b = v4sf_cload(x+6); const v4sf yv1t = v4sf_cload(y+4); const v4sf yv1b = v4sf_cload(y+6); const v4sf xv1r = __builtin_shufflevector(xv1t, xv1b, 0, 2, 4, 6); const v4sf xv1i = __builtin_shufflevector(xv1t, xv1b, 1, 3, 5, 7); const v4sf yv1r = __builtin_shufflevector(yv1t, yv1b, 0, 2, 4, 6); const v4sf yv1i = __builtin_shufflevector(yv1t, yv1b, 1, 3, 5, 7); sumv1r += xv1r * yv1r - xv1i * yv1i; sumv1i += xv1r * yv1i + xv1i * yv1r; x += 8; y += 8; n -= 8; } const v4sf sumvr = sumv0r + sumv1r; const v4sf sumvi = sumv0i + sumv1i; sumr = (sumvr[0] + sumvr[1]) + (sumvr[2] + sumvr[3]); sumi = (sumvi[0] + sumvi[1]) + (sumvi[2] + sumvi[3]); } while (n--) { const float xr = x->real; const float xi = x->imag; const float yr = y->real; const float yi = y->imag; sumr += xr * yr - xi * yi; sumi += xr * yi + xi * yr; x += incx; y += incy; } } else { if (bli_has_nonunit_inc2(incx, incy)) { float sum0r = 0.0f, sum1r = 0.0f; float sum0i = 0.0f, sum1i = 0.0f; while (n >= 2) { const float x0r = x->real; const float x0i = x->imag; const float y0r = y->real; const float y0i = y->imag; sum0r += x0r * y0r + x0i * y0i; sum0i += x0r * y0i - x0i * y0r; x += incx; y += incy; const float x1r = x->real; const float x1i = x->imag; const float y1r = y->real; const float y1i = y->imag; sum1r += x1r * y1r + x1i * y1i; sum1i += x1r * y1i - x1i * y1r; x += incx; y += incy; n -= 2; } sumr = sum0r + sum1r; sumi = sum0i + sum1i; } else { v4sf sumv0r = v4sf_zero(), sumv1r = v4sf_zero(); v4sf sumv0i = v4sf_zero(), sumv1i = v4sf_zero(); while (n >= 8) { const v4sf xv0t = v4sf_cload(x); const v4sf xv0b = v4sf_cload(x+2); const v4sf yv0t = v4sf_cload(y); const v4sf yv0b = v4sf_cload(y+2); const v4sf xv0r = __builtin_shufflevector(xv0t, xv0b, 0, 2, 4, 6); const v4sf xv0i = __builtin_shufflevector(xv0t, xv0b, 1, 3, 5, 7); const v4sf yv0r = __builtin_shufflevector(yv0t, yv0b, 0, 2, 4, 6); const v4sf yv0i = __builtin_shufflevector(yv0t, yv0b, 1, 3, 5, 7); sumv0r += xv0r * yv0r + xv0i * yv0i; sumv0i += xv0r * yv0i - xv0i * yv0r; const v4sf xv1t = v4sf_cload(x+4); const v4sf xv1b = v4sf_cload(x+6); const v4sf yv1t = v4sf_cload(y+4); const v4sf yv1b = v4sf_cload(y+6); const v4sf xv1r = __builtin_shufflevector(xv1t, xv1b, 0, 2, 4, 6); const v4sf xv1i = __builtin_shufflevector(xv1t, xv1b, 1, 3, 5, 7); const v4sf yv1r = __builtin_shufflevector(yv1t, yv1b, 0, 2, 4, 6); const v4sf yv1i = __builtin_shufflevector(yv1t, yv1b, 1, 3, 5, 7); sumv1r += xv1r * yv1r + xv1i * yv1i; sumv1i += xv1r * yv1i - xv1i * yv1r; x += 8; y += 8; n -= 8; } const v4sf sumvr = sumv0r + sumv1r; const v4sf sumvi = sumv0i + sumv1i; sumr = (sumvr[0] + sumvr[1]) + (sumvr[2] + sumvr[3]); sumi = (sumvi[0] + sumvi[1]) + (sumvi[2] + sumvi[3]); } while (n--) { const float xr = x->real; const float xi = x->imag; const float yr = y->real; const float yi = y->imag; sumr += xr * yr + xi * yi; sumi += xr * yi - xi * yr; x += incx; y += incy; } } #else if (bli_is_noconj(conjx)) { float sum0r = 0.0f, sum1r = 0.0f; float sum0i = 0.0f, sum1i = 0.0f; while (n >= 2) { const float x0r = x->real; const float x0i = x->imag; const float y0r = y->real; const float y0i = y->imag; sum0r += x0r * y0r - x0i * y0i; sum0i += x0r * y0i + x0i * y0r; x += incx; y += incy; const float x1r = x->real; const float x1i = x->imag; const float y1r = y->real; const float y1i = y->imag; sum1r += x1r * y1r - x1i * y1i; sum1i += x1r * y1i + x1i * y1r; x += incx; y += incy; n -= 2; } sumr = sum0r + sum1r; sumi = sum0i + sum1i; if (n != 0) { const float xr = x->real; const float xi = x->imag; const float yr = y->real; const float yi = y->imag; sumr += xr * yr - xi * yi; sumi += xr * yi + xi * yr; } } else { float sum0r = 0.0f, sum1r = 0.0f; float sum0i = 0.0f, sum1i = 0.0f; while (n >= 2) { const float x0r = x->real; const float x0i = x->imag; const float y0r = y->real; const float y0i = y->imag; sum0r += x0r * y0r + x0i * y0i; sum0i += x0r * y0i - x0i * y0r; x += incx; y += incy; const float x1r = x->real; const float x1i = x->imag; const float y1r = y->real; const float y1i = y->imag; sum1r += x1r * y1r + x1i * y1i; sum1i += x1r * y1i - x1i * y1r; x += incx; y += incy; n -= 2; } sumr = sum0r + sum1r; sumi = sum0i + sum1i; if (n != 0) { const float xr = x->real; const float xi = x->imag; const float yr = y->real; const float yi = y->imag; sumr += xr * yr + xi * yi; sumi += xr * yi - xi * yr; } } #endif rho->real = sumr; rho->imag = bli_is_conj(conjy) ? -sumi : sumi; } void bli_zdotv_opt( conj_t conjx, conj_t conjy, dim_t n, dcomplex x[restrict static n], inc_t incx, dcomplex y[restrict static n], inc_t incy, dcomplex rho[restrict static 1]) { if (bli_is_conj(conjy)) { bli_toggle_conj(&conjx); } if (bli_zero_dim1(n)) { rho->real = 0.0; rho->imag = 0.0; return; } double sumr; double sumi; if (bli_is_noconj(conjx)) { double sum0r = 0.0, sum1r = 0.0; double sum0i = 0.0, sum1i = 0.0; while (n >= 2) { const double x0r = x->real; const double x0i = x->imag; const double y0r = y->real; const double y0i = y->imag; sum0r += x0r * y0r - x0i * y0i; sum0i += x0r * y0i + x0i * y0r; x += incx; y += incy; const double x1r = x->real; const double x1i = x->imag; const double y1r = y->real; const double y1i = y->imag; sum1r += x1r * y1r - x1i * y1i; sum1i += x1r * y1i + x1i * y1r; x += incx; y += incy; n -= 2; } sumr = sum0r + sum1r; sumi = sum0i + sum1i; if (n != 0) { const double xr = x->real; const double xi = x->imag; const double yr = y->real; const double yi = y->imag; sumr += xr * yr - xi * yi; sumi += xr * yi + xi * yr; } } else { double sum0r = 0.0, sum1r = 0.0; double sum0i = 0.0, sum1i = 0.0; while (n >= 2) { const double x0r = x->real; const double x0i = x->imag; const double y0r = y->real; const double y0i = y->imag; sum0r += x0r * y0r + x0i * y0i; sum0i += x0r * y0i - x0i * y0r; x += incx; y += incy; const double x1r = x->real; const double x1i = x->imag; const double y1r = y->real; const double y1i = y->imag; sum1r += x1r * y1r + x1i * y1i; sum1i += x1r * y1i - x1i * y1r; x += incx; y += incy; n -= 2; } sumr = sum0r + sum1r; sumi = sum0i + sum1i; if (n != 0) { const double xr = x->real; const double xi = x->imag; const double yr = y->real; const double yi = y->imag; sumr += xr * yr + xi * yi; sumi += xr * yi - xi * yr; } } rho->real = sumr; rho->imag = bli_is_conj(conjy) ? -sumi : sumi; } blis-0.9.0/kernels/old/nacl/pnacl/3/000077500000000000000000000000001422157504600170545ustar00rootroot00000000000000blis-0.9.0/kernels/old/nacl/pnacl/3/bli_gemm_opt.c000066400000000000000000000335631422157504600216670ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #if PPAPI_RELEASE >= 36 typedef float v4sf __attribute__ ((vector_size(16))); inline v4sf v4sf_splat(float x) { return (v4sf) { x, x, x, x }; } inline v4sf v4sf_load(const float* a) { return *((const v4sf*)a); } inline v4sf v4sf_cload(const scomplex* a) { return *((const v4sf*)a); } inline void v4sf_store(float* a, v4sf x) { *((v4sf*)a) = x; } inline void v4sf_cstore(scomplex* a, v4sf x) { *((v4sf*)a) = x; } inline v4sf v4sf_zero() { return (v4sf) { 0.0f, 0.0f, 0.0f, 0.0f }; } void bli_sgemm_opt ( dim_t k, float alpha[restrict static 1], float a[restrict static 8*k], float b[restrict static k*4], float beta[restrict static 1], float c[restrict static 8*4], inc_t rs_c, inc_t cs_c, auxinfo_t* data, cntx_t* cntx ) { // Vectors for accummulating column 0, 1, 2, 3 (initialize to 0.0) v4sf abv0t = v4sf_zero(), abv1t = v4sf_zero(), abv2t = v4sf_zero(), abv3t = v4sf_zero(); v4sf abv0b = v4sf_zero(), abv1b = v4sf_zero(), abv2b = v4sf_zero(), abv3b = v4sf_zero(); for (dim_t i = 0; i < k; i += 1) { const v4sf avt = v4sf_load(a); const v4sf avb = v4sf_load(a+4); const v4sf bv_xxxx = v4sf_splat(b[0]); abv0t += avt * bv_xxxx; abv0b += avb * bv_xxxx; const v4sf bv_yyyy = v4sf_splat(b[1]); abv1t += avt * bv_yyyy; abv1b += avb * bv_yyyy; const v4sf bv_zzzz = v4sf_splat(b[2]); abv2t += avt * bv_zzzz; abv2b += avb * bv_zzzz; const v4sf bv_wwww = v4sf_splat(b[3]); abv3t += avt * bv_wwww; abv3b += avb * bv_wwww; a += 8; b += 4; } const v4sf alphav = v4sf_splat(*alpha); abv0t *= alphav; abv0b *= alphav; abv1t *= alphav; abv1b *= alphav; abv2t *= alphav; abv2b *= alphav; abv3t *= alphav; abv3b *= alphav; if (rs_c == 1) { v4sf cv0t = v4sf_load(&c[0*rs_c + 0*cs_c]); v4sf cv1t = v4sf_load(&c[0*rs_c + 1*cs_c]); v4sf cv2t = v4sf_load(&c[0*rs_c + 2*cs_c]); v4sf cv3t = v4sf_load(&c[0*rs_c + 3*cs_c]); v4sf cv0b = v4sf_load(&c[4*rs_c + 0*cs_c]); v4sf cv1b = v4sf_load(&c[4*rs_c + 1*cs_c]); v4sf cv2b = v4sf_load(&c[4*rs_c + 2*cs_c]); v4sf cv3b = v4sf_load(&c[4*rs_c + 3*cs_c]); const v4sf betav = v4sf_splat(*beta); cv0t = cv0t * betav + abv0t; cv1t = cv1t * betav + abv1t; cv2t = cv2t * betav + abv2t; cv3t = cv3t * betav + abv3t; cv0b = cv0b * betav + abv0b; cv1b = cv1b * betav + abv1b; cv2b = cv2b * betav + abv2b; cv3b = cv3b * betav + abv3b; v4sf_store(&c[0*rs_c + 0*cs_c], cv0t); v4sf_store(&c[0*rs_c + 1*cs_c], cv1t); v4sf_store(&c[0*rs_c + 2*cs_c], cv2t); v4sf_store(&c[0*rs_c + 3*cs_c], cv3t); v4sf_store(&c[4*rs_c + 0*cs_c], cv0b); v4sf_store(&c[4*rs_c + 1*cs_c], cv1b); v4sf_store(&c[4*rs_c + 2*cs_c], cv2b); v4sf_store(&c[4*rs_c + 3*cs_c], cv3b); } else { // Load columns 0, 1, 2, 3 (top part) v4sf cv0t = (v4sf){ c[0*rs_c + 0*cs_c], c[1*rs_c + 0*cs_c], c[2*rs_c + 0*cs_c], c[3*rs_c + 0*cs_c] }; v4sf cv1t = (v4sf){ c[0*rs_c + 1*cs_c], c[1*rs_c + 1*cs_c], c[2*rs_c + 1*cs_c], c[3*rs_c + 1*cs_c] }; v4sf cv2t = (v4sf){ c[0*rs_c + 2*cs_c], c[1*rs_c + 2*cs_c], c[2*rs_c + 2*cs_c], c[3*rs_c + 2*cs_c] }; v4sf cv3t = (v4sf){ c[0*rs_c + 3*cs_c], c[1*rs_c + 3*cs_c], c[2*rs_c + 3*cs_c], c[3*rs_c + 3*cs_c] }; // Load columns 0, 1, 2, 3 (bottom part) v4sf cv0b = (v4sf){ c[4*rs_c + 0*cs_c], c[5*rs_c + 0*cs_c], c[6*rs_c + 0*cs_c], c[7*rs_c + 0*cs_c] }; v4sf cv1b = (v4sf){ c[4*rs_c + 1*cs_c], c[5*rs_c + 1*cs_c], c[6*rs_c + 1*cs_c], c[7*rs_c + 1*cs_c] }; v4sf cv2b = (v4sf){ c[4*rs_c + 2*cs_c], c[5*rs_c + 2*cs_c], c[6*rs_c + 2*cs_c], c[7*rs_c + 2*cs_c] }; v4sf cv3b = (v4sf){ c[4*rs_c + 3*cs_c], c[5*rs_c + 3*cs_c], c[6*rs_c + 3*cs_c], c[7*rs_c + 3*cs_c] }; const v4sf betav = v4sf_splat(*beta); cv0t = cv0t * betav + abv0t; cv1t = cv1t * betav + abv1t; cv2t = cv2t * betav + abv2t; cv3t = cv3t * betav + abv3t; cv0b = cv0b * betav + abv0b; cv1b = cv1b * betav + abv1b; cv2b = cv2b * betav + abv2b; cv3b = cv3b * betav + abv3b; // Store column 0 c[0*rs_c + 0*cs_c] = cv0t[0]; c[1*rs_c + 0*cs_c] = cv0t[1]; c[2*rs_c + 0*cs_c] = cv0t[2]; c[3*rs_c + 0*cs_c] = cv0t[3]; c[4*rs_c + 0*cs_c] = cv0b[0]; c[5*rs_c + 0*cs_c] = cv0b[1]; c[6*rs_c + 0*cs_c] = cv0b[2]; c[7*rs_c + 0*cs_c] = cv0b[3]; // Store column 1 c[0*rs_c + 1*cs_c] = cv1t[0]; c[1*rs_c + 1*cs_c] = cv1t[1]; c[2*rs_c + 1*cs_c] = cv1t[2]; c[3*rs_c + 1*cs_c] = cv1t[3]; c[4*rs_c + 1*cs_c] = cv1b[0]; c[5*rs_c + 1*cs_c] = cv1b[1]; c[6*rs_c + 1*cs_c] = cv1b[2]; c[7*rs_c + 1*cs_c] = cv1b[3]; // Store column 2 c[0*rs_c + 2*cs_c] = cv2t[0]; c[1*rs_c + 2*cs_c] = cv2t[1]; c[2*rs_c + 2*cs_c] = cv2t[2]; c[3*rs_c + 2*cs_c] = cv2t[3]; c[4*rs_c + 2*cs_c] = cv2b[0]; c[5*rs_c + 2*cs_c] = cv2b[1]; c[6*rs_c + 2*cs_c] = cv2b[2]; c[7*rs_c + 2*cs_c] = cv2b[3]; // Store column 3 c[0*rs_c + 3*cs_c] = cv3t[0]; c[1*rs_c + 3*cs_c] = cv3t[1]; c[2*rs_c + 3*cs_c] = cv3t[2]; c[3*rs_c + 3*cs_c] = cv3t[3]; c[4*rs_c + 3*cs_c] = cv3b[0]; c[5*rs_c + 3*cs_c] = cv3b[1]; c[6*rs_c + 3*cs_c] = cv3b[2]; c[7*rs_c + 3*cs_c] = cv3b[3]; } } void bli_cgemm_opt ( dim_t k, scomplex alpha[restrict static 1], scomplex a[restrict static 4*k], scomplex b[restrict static k*4], scomplex beta[restrict static 1], scomplex c[restrict static 4*4], inc_t rs_c, inc_t cs_c, auxinfo_t* data, cntx_t* cntx ) { // Vectors for accummulating column 0, 1, 2, 3 (initialize to 0.0) v4sf abv0r = v4sf_zero(), abv1r = v4sf_zero(), abv2r = v4sf_zero(), abv3r = v4sf_zero(); v4sf abv0i = v4sf_zero(), abv1i = v4sf_zero(), abv2i = v4sf_zero(), abv3i = v4sf_zero(); for (dim_t i = 0; i < k; i += 1) { const v4sf avt = v4sf_cload(a); const v4sf avb = v4sf_cload(a+2); const v4sf avr = __builtin_shufflevector(avt, avb, 0, 2, 4, 6); const v4sf avi = __builtin_shufflevector(avt, avb, 1, 3, 5, 7); const v4sf bv0r = v4sf_splat(b[0].real); const v4sf bv0i = v4sf_splat(b[0].imag); abv0r += avr * bv0r - avi * bv0i; abv0i += avr * bv0i + avi * bv0r; const v4sf bv1r = v4sf_splat(b[1].real); const v4sf bv1i = v4sf_splat(b[1].imag); abv1r += avr * bv1r - avi * bv1i; abv1i += avr * bv1i + avi * bv1r; const v4sf bv2r = v4sf_splat(b[2].real); const v4sf bv2i = v4sf_splat(b[2].imag); abv2r += avr * bv2r - avi * bv2i; abv2i += avr * bv2i + avi * bv2r; const v4sf bv3r = v4sf_splat(b[3].real); const v4sf bv3i = v4sf_splat(b[3].imag); abv3r += avr * bv3r - avi * bv3i; abv3i += avr * bv3i + avi * bv3r; a += 4; b += 4; } const v4sf alphavr = v4sf_splat(alpha->real); const v4sf alphavi = v4sf_splat(alpha->imag); v4sf temp; temp = abv0r * alphavr - abv0i * alphavi; abv0i = abv0r * alphavi + abv0i * alphavr; abv0r = temp; temp = abv1r * alphavr - abv1i * alphavi; abv1i = abv1r * alphavi + abv1i * alphavr; abv1r = temp; temp = abv2r * alphavr - abv2i * alphavi; abv2i = abv2r * alphavi + abv2i * alphavr; abv2r = temp; temp = abv3r * alphavr - abv3i * alphavi; abv3i = abv3r * alphavi + abv3i * alphavr; abv3r = temp; if (rs_c == 1) { const v4sf cv0t = v4sf_cload(&c[0*rs_c + 0*cs_c]); const v4sf cv1t = v4sf_cload(&c[0*rs_c + 1*cs_c]); const v4sf cv2t = v4sf_cload(&c[0*rs_c + 2*cs_c]); const v4sf cv3t = v4sf_cload(&c[0*rs_c + 3*cs_c]); const v4sf cv0b = v4sf_cload(&c[2*rs_c + 0*cs_c]); const v4sf cv1b = v4sf_cload(&c[2*rs_c + 1*cs_c]); const v4sf cv2b = v4sf_cload(&c[2*rs_c + 2*cs_c]); const v4sf cv3b = v4sf_cload(&c[2*rs_c + 3*cs_c]); v4sf cv0r = __builtin_shufflevector(cv0t, cv0b, 0, 2, 4, 6); v4sf cv0i = __builtin_shufflevector(cv0t, cv0b, 1, 3, 5, 7); v4sf cv1r = __builtin_shufflevector(cv1t, cv1b, 0, 2, 4, 6); v4sf cv1i = __builtin_shufflevector(cv1t, cv1b, 1, 3, 5, 7); v4sf cv2r = __builtin_shufflevector(cv2t, cv2b, 0, 2, 4, 6); v4sf cv2i = __builtin_shufflevector(cv2t, cv2b, 1, 3, 5, 7); v4sf cv3r = __builtin_shufflevector(cv3t, cv3b, 0, 2, 4, 6); v4sf cv3i = __builtin_shufflevector(cv3t, cv3b, 1, 3, 5, 7); const v4sf betavr = v4sf_splat(beta->real); const v4sf betavi = v4sf_splat(beta->imag); temp = abv0r + cv0r * betavr - cv0i * betavi; cv0i = abv0i + cv0r * betavi + cv0i * betavr; cv0r = temp; temp = abv1r + cv1r * betavr - cv1i * betavi; cv1i = abv1i + cv1r * betavi + cv1i * betavr; cv1r = temp; temp = abv2r + cv2r * betavr - cv2i * betavi; cv2i = abv2i + cv2r * betavi + cv2i * betavr; cv2r = temp; temp = abv3r + cv3r * betavr - cv3i * betavi; cv3i = abv3i + cv3r * betavi + cv3i * betavr; cv3r = temp; v4sf_cstore(&c[0*rs_c + 0*cs_c], __builtin_shufflevector(cv0r, cv0i, 0, 4, 1, 5)); v4sf_cstore(&c[2*rs_c + 0*cs_c], __builtin_shufflevector(cv0r, cv0i, 2, 6, 3, 7)); v4sf_cstore(&c[0*rs_c + 1*cs_c], __builtin_shufflevector(cv1r, cv1i, 0, 4, 1, 5)); v4sf_cstore(&c[2*rs_c + 1*cs_c], __builtin_shufflevector(cv1r, cv1i, 2, 6, 3, 7)); v4sf_cstore(&c[0*rs_c + 2*cs_c], __builtin_shufflevector(cv2r, cv2i, 0, 4, 1, 5)); v4sf_cstore(&c[2*rs_c + 2*cs_c], __builtin_shufflevector(cv2r, cv2i, 2, 6, 3, 7)); v4sf_cstore(&c[0*rs_c + 3*cs_c], __builtin_shufflevector(cv3r, cv3i, 0, 4, 1, 5)); v4sf_cstore(&c[2*rs_c + 3*cs_c], __builtin_shufflevector(cv3r, cv3i, 2, 6, 3, 7)); } else { // Load columns 0, 1, 2, 3 (real part) v4sf cv0r = (v4sf){ c[0*rs_c + 0*cs_c].real, c[1*rs_c + 0*cs_c].real, c[2*rs_c + 0*cs_c].real, c[3*rs_c + 0*cs_c].real }; v4sf cv1r = (v4sf){ c[0*rs_c + 1*cs_c].real, c[1*rs_c + 1*cs_c].real, c[2*rs_c + 1*cs_c].real, c[3*rs_c + 1*cs_c].real }; v4sf cv2r = (v4sf){ c[0*rs_c + 2*cs_c].real, c[1*rs_c + 2*cs_c].real, c[2*rs_c + 2*cs_c].real, c[3*rs_c + 2*cs_c].real }; v4sf cv3r = (v4sf){ c[0*rs_c + 3*cs_c].real, c[1*rs_c + 3*cs_c].real, c[2*rs_c + 3*cs_c].real, c[3*rs_c + 3*cs_c].real }; // Load columns 0, 1, 2, 3 (imaginary part) v4sf cv0i = (v4sf){ c[0*rs_c + 0*cs_c].imag, c[1*rs_c + 0*cs_c].imag, c[2*rs_c + 0*cs_c].imag, c[3*rs_c + 0*cs_c].imag }; v4sf cv1i = (v4sf){ c[0*rs_c + 1*cs_c].imag, c[1*rs_c + 1*cs_c].imag, c[2*rs_c + 1*cs_c].imag, c[3*rs_c + 1*cs_c].imag }; v4sf cv2i = (v4sf){ c[0*rs_c + 2*cs_c].imag, c[1*rs_c + 2*cs_c].imag, c[2*rs_c + 2*cs_c].imag, c[3*rs_c + 2*cs_c].imag }; v4sf cv3i = (v4sf){ c[0*rs_c + 3*cs_c].imag, c[1*rs_c + 3*cs_c].imag, c[2*rs_c + 3*cs_c].imag, c[3*rs_c + 3*cs_c].imag }; const v4sf betavr = v4sf_splat(beta->real); const v4sf betavi = v4sf_splat(beta->imag); temp = abv0r + cv0r * betavr - cv0i * betavi; cv0i = abv0i + cv0r * betavi + cv0i * betavr; cv0r = temp; temp = abv1r + cv1r * betavr - cv1i * betavi; cv1i = abv1i + cv1r * betavi + cv1i * betavr; cv1r = temp; temp = abv2r + cv2r * betavr - cv2i * betavi; cv2i = abv2i + cv2r * betavi + cv2i * betavr; cv2r = temp; temp = abv3r + cv3r * betavr - cv3i * betavi; cv3i = abv3i + cv3r * betavi + cv3i * betavr; cv3r = temp; // Store column 0 c[0*rs_c + 0*cs_c].real = cv0r[0]; c[0*rs_c + 0*cs_c].imag = cv0i[0]; c[1*rs_c + 0*cs_c].real = cv0r[1]; c[1*rs_c + 0*cs_c].imag = cv0i[1]; c[2*rs_c + 0*cs_c].real = cv0r[2]; c[2*rs_c + 0*cs_c].imag = cv0i[2]; c[3*rs_c + 0*cs_c].real = cv0r[3]; c[3*rs_c + 0*cs_c].imag = cv0i[3]; // Store column 1 c[0*rs_c + 1*cs_c].real = cv1r[0]; c[0*rs_c + 1*cs_c].imag = cv1i[0]; c[1*rs_c + 1*cs_c].real = cv1r[1]; c[1*rs_c + 1*cs_c].imag = cv1i[1]; c[2*rs_c + 1*cs_c].real = cv1r[2]; c[2*rs_c + 1*cs_c].imag = cv1i[2]; c[3*rs_c + 1*cs_c].real = cv1r[3]; c[3*rs_c + 1*cs_c].imag = cv1i[3]; // Store column 2 c[0*rs_c + 2*cs_c].real = cv2r[0]; c[0*rs_c + 2*cs_c].imag = cv2i[0]; c[1*rs_c + 2*cs_c].real = cv2r[1]; c[1*rs_c + 2*cs_c].imag = cv2i[1]; c[2*rs_c + 2*cs_c].real = cv2r[2]; c[2*rs_c + 2*cs_c].imag = cv2i[2]; c[3*rs_c + 2*cs_c].real = cv2r[3]; c[3*rs_c + 2*cs_c].imag = cv2i[3]; // Store column 3 c[0*rs_c + 3*cs_c].real = cv3r[0]; c[0*rs_c + 3*cs_c].imag = cv3i[0]; c[1*rs_c + 3*cs_c].real = cv3r[1]; c[1*rs_c + 3*cs_c].imag = cv3i[1]; c[2*rs_c + 3*cs_c].real = cv3r[2]; c[2*rs_c + 3*cs_c].imag = cv3i[2]; c[3*rs_c + 3*cs_c].real = cv3r[3]; c[3*rs_c + 3*cs_c].imag = cv3i[3]; } } #endif blis-0.9.0/kernels/old/x86/000077500000000000000000000000001422157504600153255ustar00rootroot00000000000000blis-0.9.0/kernels/old/x86/1m/000077500000000000000000000000001422157504600156425ustar00rootroot00000000000000blis-0.9.0/kernels/old/x86/1m/bli_packm_2xk.c000066400000000000000000000242731422157504600205230ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_spackm_2xk( conj_t conja, dim_t n, void* beta, void* a, inc_t inca, inc_t lda, void* p ) { bli_check_error_code( BLIS_NOT_YET_IMPLEMENTED ); } void bli_dpackm_2xk( conj_t conja, dim_t n, void* beta, void* a, inc_t inca, inc_t lda, void* p ) { double* restrict beta_cast = beta; double* restrict alpha1 = a; double* restrict pi1 = p; inc_t off1 = 1 * inca * sizeof(double); inc_t ldas = lda * sizeof(double); if ( bli_deq1( *beta_cast ) ) { dim_t n_iter = n / 4; dim_t n_left = n % 4; __asm__ volatile ( " \n\t" "movl %2, %%edi \n\t" // load a "movl %3, %%ebp \n\t" // load p " \n\t" "movl %4, %%eax \n\t" // load ldas "leal (%%edi,%%eax), %%edx \n\t" // load a + ldas "sall $1, %%eax \n\t" // ldas *= 2; " \n\t" "movl %5, %%ebx \n\t" // load off1 " \n\t" " \n\t" "movl %0, %%esi \n\t" "testl %%esi, %%esi \n\t" "je .DCONSIDERKLEFT \n\t" " \n\t" " \n\t" ".DLOOPKITER: \n\t" " \n\t" "addl $64, %%ebp \n\t" " \n\t" "movlpd (%%edi ), %%xmm0 \n\t" // iteration 0 "movhpd (%%edi,%%ebx, ), %%xmm0 \n\t" "addl %%eax, %%edi \n\t" "movapd %%xmm0, -8 * 8(%%ebp) \n\t" " \n\t" "movlpd (%%edx ), %%xmm1 \n\t" // iteration 1 "movhpd (%%edx,%%ebx, ), %%xmm1 \n\t" "addl %%eax, %%edx \n\t" "movapd %%xmm1, -6 * 8(%%ebp) \n\t" " \n\t" "movlpd (%%edi ), %%xmm2 \n\t" // iteration 2 "movhpd (%%edi,%%ebx, ), %%xmm2 \n\t" "addl %%eax, %%edi \n\t" "movapd %%xmm2, -4 * 8(%%ebp) \n\t" " \n\t" "movlpd (%%edx ), %%xmm3 \n\t" // iteration 3 "movhpd (%%edx,%%ebx, ), %%xmm3 \n\t" "addl %%eax, %%edx \n\t" "movapd %%xmm3, -2 * 8(%%ebp) \n\t" " \n\t" "decl %%esi \n\t" "jne .DLOOPKITER \n\t" " \n\t" " \n\t" " \n\t" ".DCONSIDERKLEFT: \n\t" " \n\t" "movl %1, %%esi \n\t" "testl %%esi, %%esi \n\t" "je .DDONE \n\t" " \n\t" " \n\t" " \n\t" ".DLOOPKLEFT: \n\t" " \n\t" "addl $16, %%ebp \n\t" " \n\t" "movlpd (%%edi ), %%xmm0 \n\t" "movhpd (%%edi,%%ebx, ), %%xmm0 \n\t" "addl %%eax, %%edi \n\t" "movapd %%xmm0, -2 * 8(%%ebp) \n\t" " \n\t" "decl %%esi \n\t" "jne .DLOOPKLEFT \n\t" " \n\t" " \n\t" " \n\t" ".DDONE: \n\t" " \n\t" : // output operands : // input operands "m" (n_iter), "m" (n_left), "m" (alpha1), "m" (pi1), "m" (ldas), "m" (off1) : // register clobber list "eax", "ebx", "ecx", "edx", "edi", "ebp", "esi", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "memory" ); } else { dim_t n_iter = n / 4; dim_t n_left = n % 4; __asm__ volatile ( " \n\t" "movl %2, %%edi \n\t" // load a "movl %3, %%ebp \n\t" // load p " \n\t" "movl %4, %%eax \n\t" // load ldas "leal (%%edi,%%eax), %%edx \n\t" // load a + ldas "sall $1, %%eax \n\t" // ldas *= 2; " \n\t" "movl %5, %%ebx \n\t" // load off1 " \n\t" "movl %6, %%esi \n\t" // load beta "movddup (%%esi), %%xmm7 \n\t" // load and duplicate *beta " \n\t" "movl %0, %%esi \n\t" "testl %%esi, %%esi \n\t" "je .DCONSIDERKLEFT2 \n\t" " \n\t" " \n\t" ".DLOOPKITER2: \n\t" " \n\t" "addl $64, %%ebp \n\t" " \n\t" "movlpd (%%edi ), %%xmm0 \n\t" // iteration 0 "movhpd (%%edi,%%ebx, ), %%xmm0 \n\t" "mulpd %%xmm7, %%xmm0 \n\t" "addl %%eax, %%edi \n\t" "movapd %%xmm0, -8 * 8(%%ebp) \n\t" " \n\t" "movlpd (%%edx ), %%xmm1 \n\t" // iteration 1 "movhpd (%%edx,%%ebx, ), %%xmm1 \n\t" "mulpd %%xmm7, %%xmm1 \n\t" "addl %%eax, %%edx \n\t" "movapd %%xmm1, -6 * 8(%%ebp) \n\t" " \n\t" "movlpd (%%edi ), %%xmm2 \n\t" // iteration 2 "movhpd (%%edi,%%ebx, ), %%xmm2 \n\t" "mulpd %%xmm7, %%xmm2 \n\t" "addl %%eax, %%edi \n\t" "movapd %%xmm2, -4 * 8(%%ebp) \n\t" " \n\t" "movlpd (%%edx ), %%xmm3 \n\t" // iteration 3 "movhpd (%%edx,%%ebx, ), %%xmm3 \n\t" "mulpd %%xmm7, %%xmm3 \n\t" "addl %%eax, %%edx \n\t" "movapd %%xmm3, -2 * 8(%%ebp) \n\t" " \n\t" "decl %%esi \n\t" "jne .DLOOPKITER2 \n\t" " \n\t" " \n\t" " \n\t" ".DCONSIDERKLEFT2: \n\t" " \n\t" "movl %1, %%esi \n\t" "testl %%esi, %%esi \n\t" "je .DDONE2 \n\t" " \n\t" " \n\t" " \n\t" ".DLOOPKLEFT2: \n\t" " \n\t" "addl $16, %%ebp \n\t" " \n\t" "movlpd (%%edi ), %%xmm0 \n\t" "movhpd (%%edi,%%ebx, ), %%xmm0 \n\t" "mulpd %%xmm7, %%xmm0 \n\t" "addl %%eax, %%edi \n\t" "movapd %%xmm0, -2 * 8(%%ebp) \n\t" " \n\t" "decl %%esi \n\t" "jne .DLOOPKLEFT2 \n\t" " \n\t" " \n\t" " \n\t" ".DDONE2: \n\t" " \n\t" : // output operands : // input operands "m" (n_iter), "m" (n_left), "m" (alpha1), "m" (pi1), "m" (ldas), "m" (off1), "m" (beta) : // register clobber list "eax", "ebx", "ecx", "edx", "edi", "ebp", "esi", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "memory" ); } } void bli_cpackm_2xk( conj_t conja, dim_t n, void* beta, void* a, inc_t inca, inc_t lda, void* p ) { bli_check_error_code( BLIS_NOT_YET_IMPLEMENTED ); } void bli_zpackm_2xk( conj_t conja, dim_t n, void* beta, void* a, inc_t inca, inc_t lda, void* p ) { bli_check_error_code( BLIS_NOT_YET_IMPLEMENTED ); } blis-0.9.0/kernels/old/x86/1m/bli_packm_2xk.h000066400000000000000000000040101422157504600205130ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #undef GENTPROT #define GENTPROT( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname)( \ conj_t conja, \ dim_t n, \ void* beta, \ void* a, inc_t inca, inc_t lda, \ void* p \ ); INSERT_GENTPROT_BASIC( packm_2xk ) blis-0.9.0/kernels/old/x86/1m/bli_packm_4xk.c000066400000000000000000000261621422157504600205240ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_spackm_4xk( conj_t conja, dim_t n, void* beta, void* a, inc_t inca, inc_t lda, void* p ) { bli_check_error_code( BLIS_NOT_YET_IMPLEMENTED ); } void bli_dpackm_4xk( conj_t conja, dim_t n, void* beta, void* a, inc_t inca, inc_t lda, void* p ) { double* restrict beta_cast = beta; double* restrict alpha1 = a; double* restrict pi1 = p; inc_t off1 = 1 * inca * sizeof(double); inc_t off3 = 3 * inca * sizeof(double); inc_t ldas = lda * sizeof(double); if ( bli_deq1( *beta_cast ) ) { dim_t n_iter = n / 4; dim_t n_left = n % 4; __asm__ volatile ( " \n\t" //"movapd 4096(%%ebp), %%xmm7 \n\t" //"movapd %%xmm7, 4096(%%ebp) \n\t" " \n\t" "movl %2, %%edi \n\t" // load a "movl %3, %%ebp \n\t" // load p " \n\t" "movl %4, %%eax \n\t" // load ldas "leal (%%edi,%%eax), %%edx \n\t" // load a + ldas "sall $1, %%eax \n\t" // ldas *= 2; " \n\t" "movl %5, %%ebx \n\t" // load off1 "movl %6, %%ecx \n\t" // load off3 " \n\t" "movl %0, %%esi \n\t" "testl %%esi, %%esi \n\t" "je .DCONSIDERKLEFT \n\t" " \n\t" " \n\t" " \n\t" ".DLOOPKITER: \n\t" " \n\t" "addl $128, %%ebp \n\t" " \n\t" "movlpd (%%edi ), %%xmm0 \n\t" // iteration 0 "movhpd (%%edi,%%ebx, ), %%xmm0 \n\t" "movlpd (%%edi,%%ebx,2), %%xmm1 \n\t" "movhpd (%%edi,%%ecx, ), %%xmm1 \n\t" "addl %%eax, %%edi \n\t" "movapd %%xmm0, -16 * 8(%%ebp) \n\t" "movapd %%xmm1, -14 * 8(%%ebp) \n\t" " \n\t" "movlpd (%%edx ), %%xmm2 \n\t" // iteration 1 "movhpd (%%edx,%%ebx, ), %%xmm2 \n\t" "movlpd (%%edx,%%ebx,2), %%xmm3 \n\t" "movhpd (%%edx,%%ecx, ), %%xmm3 \n\t" "addl %%eax, %%edx \n\t" "movapd %%xmm2, -12 * 8(%%ebp) \n\t" "movapd %%xmm3, -10 * 8(%%ebp) \n\t" " \n\t" "movlpd (%%edi ), %%xmm4 \n\t" // iteration 2 "movhpd (%%edi,%%ebx, ), %%xmm4 \n\t" "movlpd (%%edi,%%ebx,2), %%xmm5 \n\t" "movhpd (%%edi,%%ecx, ), %%xmm5 \n\t" "addl %%eax, %%edi \n\t" "movapd %%xmm4, -8 * 8(%%ebp) \n\t" "movapd %%xmm5, -6 * 8(%%ebp) \n\t" " \n\t" "movlpd (%%edx ), %%xmm6 \n\t" // iteration 3 "movhpd (%%edx,%%ebx, ), %%xmm6 \n\t" "movlpd (%%edx,%%ebx,2), %%xmm7 \n\t" "movhpd (%%edx,%%ecx, ), %%xmm7 \n\t" "addl %%eax, %%edx \n\t" "movapd %%xmm6, -4 * 8(%%ebp) \n\t" "movapd %%xmm7, -2 * 8(%%ebp) \n\t" " \n\t" "decl %%esi \n\t" "jne .DLOOPKITER \n\t" " \n\t" " \n\t" " \n\t" ".DCONSIDERKLEFT: \n\t" " \n\t" "movl %1, %%esi \n\t" "testl %%esi, %%esi \n\t" "je .DDONE \n\t" " \n\t" " \n\t" " \n\t" ".DLOOPKLEFT: \n\t" " \n\t" "addl $32, %%ebp \n\t" " \n\t" "movlpd (%%edi ), %%xmm0 \n\t" "movhpd (%%edi,%%ebx, ), %%xmm0 \n\t" "movlpd (%%edi,%%ebx,2), %%xmm1 \n\t" "movhpd (%%edi,%%ecx, ), %%xmm1 \n\t" "addl %%eax, %%edi \n\t" "movapd %%xmm0, -4 * 8(%%ebp) \n\t" "movapd %%xmm1, -2 * 8(%%ebp) \n\t" " \n\t" "decl %%esi \n\t" "jne .DLOOPKLEFT \n\t" " \n\t" " \n\t" " \n\t" ".DDONE: \n\t" " \n\t" : // output operands : // input operands "m" (n_iter), "m" (n_left), "m" (alpha1), "m" (pi1), "m" (ldas), "m" (off1), "m" (off3) : // register clobber list "eax", "ebx", "ecx", "edx", "edi", "ebp", "esi", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "memory" ); } else { dim_t n_iter = n / 2; dim_t n_left = n % 2; __asm__ volatile ( " \n\t" "movl %2, %%edi \n\t" // load a "movl %3, %%ebp \n\t" // load p " \n\t" "movl %4, %%eax \n\t" // load ldas "leal (%%edi,%%eax), %%edx \n\t" // load a + ldas "sall $1, %%eax \n\t" // ldas *= 2; " \n\t" "movl %5, %%ebx \n\t" // load off1 "movl %6, %%ecx \n\t" // load off3 " \n\t" "movl %7, %%esi \n\t" // load beta "movddup (%%esi), %%xmm7 \n\t" // load and duplicate *beta " \n\t" "movl %0, %%esi \n\t" "testl %%esi, %%esi \n\t" "je .DCONSIDERKLEFT2 \n\t" " \n\t" " \n\t" ".DLOOPKITER2: \n\t" " \n\t" "addl $64, %%ebp \n\t" " \n\t" "movlpd (%%edi ), %%xmm0 \n\t" // iteration 0 "movhpd (%%edi,%%ebx, ), %%xmm0 \n\t" "movlpd (%%edi,%%ebx,2), %%xmm1 \n\t" "movhpd (%%edi,%%ecx, ), %%xmm1 \n\t" "mulpd %%xmm7, %%xmm0 \n\t" "mulpd %%xmm7, %%xmm1 \n\t" "addl %%eax, %%edi \n\t" "movapd %%xmm0, -8 * 8(%%ebp) \n\t" "movapd %%xmm1, -6 * 8(%%ebp) \n\t" " \n\t" "movlpd (%%edx ), %%xmm2 \n\t" // iteration 1 "movhpd (%%edx,%%ebx, ), %%xmm2 \n\t" "movlpd (%%edx,%%ebx,2), %%xmm3 \n\t" "movhpd (%%edx,%%ecx, ), %%xmm3 \n\t" "mulpd %%xmm7, %%xmm2 \n\t" "mulpd %%xmm7, %%xmm3 \n\t" "addl %%eax, %%edx \n\t" "movapd %%xmm2, -4 * 8(%%ebp) \n\t" "movapd %%xmm3, -2 * 8(%%ebp) \n\t" " \n\t" "decl %%esi \n\t" "jne .DLOOPKITER2 \n\t" " \n\t" " \n\t" " \n\t" ".DCONSIDERKLEFT2: \n\t" " \n\t" "movl %1, %%esi \n\t" "testl %%esi, %%esi \n\t" "je .DDONE2 \n\t" " \n\t" " \n\t" " \n\t" ".DLOOPKLEFT2: \n\t" " \n\t" "addl $32, %%ebp \n\t" " \n\t" "movlpd (%%edi ), %%xmm0 \n\t" "movhpd (%%edi,%%ebx, ), %%xmm0 \n\t" "movlpd (%%edi,%%ebx,2), %%xmm1 \n\t" "movhpd (%%edi,%%ecx, ), %%xmm1 \n\t" "mulpd %%xmm7, %%xmm0 \n\t" "mulpd %%xmm7, %%xmm1 \n\t" "addl %%eax, %%edi \n\t" "movapd %%xmm0, -4 * 8(%%ebp) \n\t" "movapd %%xmm1, -2 * 8(%%ebp) \n\t" " \n\t" "decl %%esi \n\t" "jne .DLOOPKLEFT2 \n\t" " \n\t" " \n\t" " \n\t" ".DDONE2: \n\t" " \n\t" : // output operands : // input operands "m" (n_iter), "m" (n_left), "m" (alpha1), "m" (pi1), "m" (ldas), "m" (off1), "m" (off3), "m" (beta) : // register clobber list "eax", "ebx", "ecx", "edx", "edi", "ebp", "esi", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "memory" ); } } void bli_cpackm_4xk( conj_t conja, dim_t n, void* beta, void* a, inc_t inca, inc_t lda, void* p ) { bli_check_error_code( BLIS_NOT_YET_IMPLEMENTED ); } void bli_zpackm_4xk( conj_t conja, dim_t n, void* beta, void* a, inc_t inca, inc_t lda, void* p ) { bli_check_error_code( BLIS_NOT_YET_IMPLEMENTED ); } blis-0.9.0/kernels/old/x86/1m/bli_packm_4xk.h000066400000000000000000000040101422157504600205150ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #undef GENTPROT #define GENTPROT( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname)( \ conj_t conja, \ dim_t n, \ void* beta, \ void* a, inc_t inca, inc_t lda, \ void* p \ ); INSERT_GENTPROT_BASIC( packm_4xk ) blis-0.9.0/kernels/old/x86/3/000077500000000000000000000000001422157504600154675ustar00rootroot00000000000000blis-0.9.0/kernels/old/x86/3/bli_gemm_opt_d2x4.c000066400000000000000000000407361422157504600211430ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_sgemm_opt_d2x4( dim_t k, float* restrict alpha, float* restrict a, float* restrict b, float* restrict beta, float* restrict c, inc_t rs_c, inc_t cs_c ) { bli_check_error_code( BLIS_NOT_YET_IMPLEMENTED ); } void bli_dgemm_opt_d2x4( dim_t k, double* restrict alpha, double* restrict a, double* restrict b, double* restrict beta, double* restrict c, inc_t rs_c, inc_t cs_c ) { dim_t k_iter; dim_t k_left; k_iter = k / 8; k_left = k % 8; __asm__ volatile ( " \n\t" "movl %6, %%ecx \n\t" // load address of c " \n\t" "movl %8, %%edi \n\t" // load cs_c "sall $3, %%edi \n\t" // cs_c *= sizeof(double) " \n\t" "leal (%%ecx,%%edi,2), %%edx \n\t" // load address of c + 2*cs_c " \n\t" "prefetcht0 (%%ecx) \n\t" // give a T0 prefetch hint for c00. "prefetcht0 (%%ecx,%%edi) \n\t" // give a T0 prefetch hint for c01. "prefetcht0 (%%edx) \n\t" // give a T0 prefetch hint for c02. "prefetcht0 (%%edx,%%edi) \n\t" // give a T0 prefetch hint for c03. " \n\t" "movl %2, %%eax \n\t" // load address of a. "movl %3, %%ebx \n\t" // load address of b. " \n\t" "addl $8 * 16, %%eax \n\t" // increment pointers to allow byte "addl $8 * 16, %%ebx \n\t" // offsets in the unrolled iterations. " \n\t" "movapd -8 * 16(%%eax), %%xmm0 \n\t" // initialize loop by pre-loading elements "movapd -8 * 16(%%ebx), %%xmm1 \n\t" // of a and b. " \n\t" "pxor %%xmm2, %%xmm2 \n\t" "pxor %%xmm3, %%xmm3 \n\t" " \n\t" "pxor %%xmm4, %%xmm4 \n\t" "pxor %%xmm5, %%xmm5 \n\t" "pxor %%xmm6, %%xmm6 \n\t" "pxor %%xmm7, %%xmm7 \n\t" " \n\t" " \n\t" " \n\t" "movl %0, %%esi \n\t" // i = k_iter; "testl %%esi, %%esi \n\t" // check i via logical AND. "je .CONSIDERKLEFT \n\t" // if i == 0, jump to code that " \n\t" // contains the k_left loop. " \n\t" " \n\t" ".LOOPKITER: \n\t" // MAIN LOOP " \n\t" "prefetcht0 (8*21+4)*8(%%eax) \n\t" " \n\t" " \n\t" "addpd %%xmm3, %%xmm7 \n\t" // iteration 0 "movapd -7 * 16(%%ebx), %%xmm3 \n\t" "addpd %%xmm2, %%xmm6 \n\t" "pshufd $0x4e, %%xmm1, %%xmm2 \n\t" "mulpd %%xmm0, %%xmm1 \n\t" "mulpd %%xmm0, %%xmm2 \n\t" " \n\t" "addpd %%xmm1, %%xmm5 \n\t" "movapd -6 * 16(%%ebx), %%xmm1 \n\t" "addpd %%xmm2, %%xmm4 \n\t" "pshufd $0x4e, %%xmm3, %%xmm2 \n\t" "mulpd %%xmm0, %%xmm3 \n\t" "mulpd %%xmm0, %%xmm2 \n\t" "movapd -7 * 16(%%eax), %%xmm0 \n\t" " \n\t" " \n\t" "addpd %%xmm3, %%xmm7 \n\t" // iteration 1 "movapd -5 * 16(%%ebx), %%xmm3 \n\t" "addpd %%xmm2, %%xmm6 \n\t" "pshufd $0x4e, %%xmm1, %%xmm2 \n\t" "mulpd %%xmm0, %%xmm1 \n\t" "mulpd %%xmm0, %%xmm2 \n\t" " \n\t" "addpd %%xmm1, %%xmm5 \n\t" "movapd -4 * 16(%%ebx), %%xmm1 \n\t" "addpd %%xmm2, %%xmm4 \n\t" "pshufd $0x4e, %%xmm3, %%xmm2 \n\t" "mulpd %%xmm0, %%xmm3 \n\t" "mulpd %%xmm0, %%xmm2 \n\t" "movapd -6 * 16(%%eax), %%xmm0 \n\t" " \n\t" " \n\t" "addpd %%xmm3, %%xmm7 \n\t" // iteration 2 "movapd -3 * 16(%%ebx), %%xmm3 \n\t" "addpd %%xmm2, %%xmm6 \n\t" "pshufd $0x4e, %%xmm1, %%xmm2 \n\t" "mulpd %%xmm0, %%xmm1 \n\t" "mulpd %%xmm0, %%xmm2 \n\t" " \n\t" "addpd %%xmm1, %%xmm5 \n\t" "movapd -2 * 16(%%ebx), %%xmm1 \n\t" "addpd %%xmm2, %%xmm4 \n\t" "pshufd $0x4e, %%xmm3, %%xmm2 \n\t" "mulpd %%xmm0, %%xmm3 \n\t" "mulpd %%xmm0, %%xmm2 \n\t" "movapd -5 * 16(%%eax), %%xmm0 \n\t" " \n\t" " \n\t" "addpd %%xmm3, %%xmm7 \n\t" // iteration 3 "movapd -1 * 16(%%ebx), %%xmm3 \n\t" "addpd %%xmm2, %%xmm6 \n\t" "pshufd $0x4e, %%xmm1, %%xmm2 \n\t" "mulpd %%xmm0, %%xmm1 \n\t" "mulpd %%xmm0, %%xmm2 \n\t" " \n\t" "addpd %%xmm1, %%xmm5 \n\t" "movapd 0 * 16(%%ebx), %%xmm1 \n\t" "addpd %%xmm2, %%xmm4 \n\t" "pshufd $0x4e, %%xmm3, %%xmm2 \n\t" "mulpd %%xmm0, %%xmm3 \n\t" "mulpd %%xmm0, %%xmm2 \n\t" "movapd -4 * 16(%%eax), %%xmm0 \n\t" " \n\t" " \n\t" "prefetcht0 (8*21+12)*8(%%eax) \n\t" " \n\t" " \n\t" "addpd %%xmm3, %%xmm7 \n\t" // iteration 4 "movapd 1 * 16(%%ebx), %%xmm3 \n\t" "addpd %%xmm2, %%xmm6 \n\t" "pshufd $0x4e, %%xmm1, %%xmm2 \n\t" "mulpd %%xmm0, %%xmm1 \n\t" "mulpd %%xmm0, %%xmm2 \n\t" " \n\t" "addpd %%xmm1, %%xmm5 \n\t" "movapd 2 * 16(%%ebx), %%xmm1 \n\t" "addpd %%xmm2, %%xmm4 \n\t" "pshufd $0x4e, %%xmm3, %%xmm2 \n\t" "mulpd %%xmm0, %%xmm3 \n\t" "mulpd %%xmm0, %%xmm2 \n\t" "movapd -3 * 16(%%eax), %%xmm0 \n\t" " \n\t" " \n\t" "addpd %%xmm3, %%xmm7 \n\t" // iteration 5 "movapd 3 * 16(%%ebx), %%xmm3 \n\t" "addpd %%xmm2, %%xmm6 \n\t" "pshufd $0x4e, %%xmm1, %%xmm2 \n\t" "mulpd %%xmm0, %%xmm1 \n\t" "mulpd %%xmm0, %%xmm2 \n\t" " \n\t" "addpd %%xmm1, %%xmm5 \n\t" "movapd 4 * 16(%%ebx), %%xmm1 \n\t" "addpd %%xmm2, %%xmm4 \n\t" "pshufd $0x4e, %%xmm3, %%xmm2 \n\t" "mulpd %%xmm0, %%xmm3 \n\t" "mulpd %%xmm0, %%xmm2 \n\t" "movapd -2 * 16(%%eax), %%xmm0 \n\t" " \n\t" " \n\t" "addpd %%xmm3, %%xmm7 \n\t" // iteration 6 "movapd 5 * 16(%%ebx), %%xmm3 \n\t" "addpd %%xmm2, %%xmm6 \n\t" "pshufd $0x4e, %%xmm1, %%xmm2 \n\t" "mulpd %%xmm0, %%xmm1 \n\t" "mulpd %%xmm0, %%xmm2 \n\t" " \n\t" "addpd %%xmm1, %%xmm5 \n\t" "movapd 6 * 16(%%ebx), %%xmm1 \n\t" "addpd %%xmm2, %%xmm4 \n\t" "pshufd $0x4e, %%xmm3, %%xmm2 \n\t" "mulpd %%xmm0, %%xmm3 \n\t" "mulpd %%xmm0, %%xmm2 \n\t" "movapd -1 * 16(%%eax), %%xmm0 \n\t" " \n\t" " \n\t" "addpd %%xmm3, %%xmm7 \n\t" // iteration 7 "movapd 7 * 16(%%ebx), %%xmm3 \n\t" "addpd %%xmm2, %%xmm6 \n\t" "pshufd $0x4e, %%xmm1, %%xmm2 \n\t" "mulpd %%xmm0, %%xmm1 \n\t" "mulpd %%xmm0, %%xmm2 \n\t" " \n\t" "addpd %%xmm1, %%xmm5 \n\t" "movapd 8 * 16(%%ebx), %%xmm1 \n\t" "addpd %%xmm2, %%xmm4 \n\t" "pshufd $0x4e, %%xmm3, %%xmm2 \n\t" "mulpd %%xmm0, %%xmm3 \n\t" "mulpd %%xmm0, %%xmm2 \n\t" "movapd 0 * 16(%%eax), %%xmm0 \n\t" " \n\t" "addl $256, %%ebx \n\t" // b += 8*2*2 (unroll x nr x ndup) "addl $128, %%eax \n\t" // a += 8*4 (unroll x mr) " \n\t" " \n\t" "decl %%esi \n\t" // i -= 1; "jne .LOOPKITER \n\t" // iterate again if i != 0. " \n\t" " \n\t" " \n\t" ".CONSIDERKLEFT: \n\t" " \n\t" "movl %1, %%esi \n\t" // i = k_left; "testl %%esi, %%esi \n\t" // check i via logical AND. "je .POSTACCUM \n\t" // if i == 0, we're done; jump to end. " \n\t" // else, we prepare to enter k_left loop. " \n\t" " \n\t" ".LOOPKLEFT: \n\t" // EDGE LOOP " \n\t" "addpd %%xmm3, %%xmm7 \n\t" // iteration i "movapd -7 * 16(%%ebx), %%xmm3 \n\t" "addpd %%xmm2, %%xmm6 \n\t" "pshufd $0x4e, %%xmm1, %%xmm2 \n\t" "mulpd %%xmm0, %%xmm1 \n\t" "mulpd %%xmm0, %%xmm2 \n\t" " \n\t" "addpd %%xmm1, %%xmm5 \n\t" "movapd -6 * 16(%%ebx), %%xmm1 \n\t" "addpd %%xmm2, %%xmm4 \n\t" "pshufd $0x4e, %%xmm3, %%xmm2 \n\t" "mulpd %%xmm0, %%xmm3 \n\t" "mulpd %%xmm0, %%xmm2 \n\t" "movapd -7 * 16(%%eax), %%xmm0 \n\t" " \n\t" " \n\t" " \n\t" " \n\t" "addl $32, %%ebx \n\t" // b += 4 (1 x mr) "addl $16, %%eax \n\t" // a += 2*2 (1 x nr x ndup) " \n\t" "decl %%esi \n\t" // i -= 1; "jne .LOOPKLEFT \n\t" // iterate again if i != 0. " \n\t" " \n\t" " \n\t" ".POSTACCUM: \n\t" " \n\t" "addpd %%xmm2, %%xmm6 \n\t" "addpd %%xmm3, %%xmm7 \n\t" " \n\t" " \n\t" "movl %4, %%eax \n\t" // load address of alpha "movl %5, %%ebx \n\t" // load address of beta "movddup (%%eax), %%xmm2 \n\t" // load alpha and duplicate "movddup (%%ebx), %%xmm3 \n\t" // load beta and duplicate " \n\t" " \n\t" " \n\t" "movl %7, %%esi \n\t" // load rs_c "sall $3, %%esi \n\t" // rs_c *= sizeof(double) " \n\t" " \n\t" "movapd %%xmm4, %%xmm0 \n\t" "movsd %%xmm5, %%xmm4 \n\t" "movsd %%xmm0, %%xmm5 \n\t" " \n\t" "movapd %%xmm6, %%xmm0 \n\t" "movsd %%xmm7, %%xmm6 \n\t" "movsd %%xmm0, %%xmm7 \n\t" " \n\t" " \n\t" " \n\t" "movlpd (%%ecx), %%xmm0 \n\t" // load c00 and c10, "movhpd (%%ecx,%%esi), %%xmm0 \n\t" "mulpd %%xmm2, %%xmm4 \n\t" // scale by alpha, "mulpd %%xmm3, %%xmm0 \n\t" // scale by beta, "addpd %%xmm4, %%xmm0 \n\t" // add the gemm result, "movlpd %%xmm0, (%%ecx) \n\t" // and store back to memory. "movhpd %%xmm0, (%%ecx,%%esi) \n\t" "addl %%edi, %%ecx \n\t" " \n\t" "movlpd (%%edx), %%xmm1 \n\t" // load c02 and c12, "movhpd (%%edx,%%esi), %%xmm1 \n\t" "mulpd %%xmm2, %%xmm6 \n\t" // scale by alpha, "mulpd %%xmm3, %%xmm1 \n\t" // scale by beta, "addpd %%xmm6, %%xmm1 \n\t" // add the gemm result, "movlpd %%xmm1, (%%edx) \n\t" // and store back to memory. "movhpd %%xmm1, (%%edx,%%esi) \n\t" "addl %%edi, %%edx \n\t" " \n\t" "movlpd (%%ecx), %%xmm0 \n\t" // load c01 and c11, "movhpd (%%ecx,%%esi), %%xmm0 \n\t" "mulpd %%xmm2, %%xmm5 \n\t" // scale by alpha, "mulpd %%xmm3, %%xmm0 \n\t" // scale by beta, "addpd %%xmm5, %%xmm0 \n\t" // add the gemm result, "movlpd %%xmm0, (%%ecx) \n\t" // and store back to memory. "movhpd %%xmm0, (%%ecx,%%esi) \n\t" " \n\t" "movlpd (%%edx), %%xmm1 \n\t" // load c03 and c13, "movhpd (%%edx,%%esi), %%xmm1 \n\t" "mulpd %%xmm2, %%xmm7 \n\t" // scale by alpha, "mulpd %%xmm3, %%xmm1 \n\t" // scale by beta, "addpd %%xmm7, %%xmm1 \n\t" // add the gemm result, "movlpd %%xmm1, (%%edx) \n\t" // and store back to memory. "movhpd %%xmm1, (%%edx,%%esi) \n\t" " \n\t" " \n\t" " \n\t" : // output operands (none) : // input operands "m" (k_iter), "m" (k_left), "m" (a), "m" (b), "m" (alpha), "m" (beta), "m" (c), "m" (rs_c), "m" (cs_c) : // register clobber list "eax", "ebx", "ecx", "edx", "esi", "edi", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "memory" ); } void bli_cgemm_opt_d2x4( dim_t k, scomplex* restrict alpha, scomplex* restrict a, scomplex* restrict b, scomplex* restrict beta, scomplex* restrict c, inc_t rs_c, inc_t cs_c ) { bli_check_error_code( BLIS_NOT_YET_IMPLEMENTED ); } void bli_zgemm_opt_d2x4( dim_t k, dcomplex* restrict alpha, dcomplex* restrict a, dcomplex* restrict b, dcomplex* restrict beta, dcomplex* restrict c, inc_t rs_c, inc_t cs_c ) { bli_check_error_code( BLIS_NOT_YET_IMPLEMENTED ); } blis-0.9.0/kernels/old/x86/3/bli_gemm_opt_d4x2.c000066400000000000000000000356511422157504600211430ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_sgemm_opt_d4x2( dim_t k, float* restrict alpha, float* restrict a, float* restrict b, float* restrict beta, float* restrict c, inc_t rs_c, inc_t cs_c, float* restrict a_next, float* restrict b_next ) { bli_check_error_code( BLIS_NOT_YET_IMPLEMENTED ); } void bli_dgemm_opt_d4x2( dim_t k, double* restrict alpha, double* restrict a, double* restrict b, double* restrict beta, double* restrict c, inc_t rs_c, inc_t cs_c, double* restrict a_next, double* restrict b_next ) { dim_t k_iter; dim_t k_left; k_iter = k / 8; k_left = k % 8; __asm__ volatile ( " \n\t" "movl %6, %%ecx \n\t" // load address of c " \n\t" "movl %8, %%edi \n\t" // load cs_c "sall $3, %%edi \n\t" // cs_c *= sizeof(double) " \n\t" "prefetcht0 (%%ecx) \n\t" // give a T0 prefetch hint for c00. "prefetcht0 (%%ecx,%%edi) \n\t" // give a T0 prefetch hint for c01. " \n\t" "movl %2, %%eax \n\t" // load address of a. "movl %3, %%ebx \n\t" // load address of b. " \n\t" "addl $8 * 16, %%eax \n\t" // increment pointers to allow byte "addl $8 * 16, %%ebx \n\t" // offsets in the unrolled iterations. " \n\t" "movapd -8 * 16(%%eax), %%xmm0 \n\t" // initialize loop by pre-loading elements "movapd -4 * 16(%%eax), %%xmm3 \n\t" // of a. " \n\t" "pxor %%xmm4, %%xmm4 \n\t" "pxor %%xmm5, %%xmm5 \n\t" "pxor %%xmm6, %%xmm6 \n\t" "pxor %%xmm7, %%xmm7 \n\t" " \n\t" " \n\t" " \n\t" "movl %0, %%esi \n\t" // i = k_iter; "testl %%esi, %%esi \n\t" // check i via logical AND. "je .CONSIDERKLEFT \n\t" // if i == 0, jump to code that " \n\t" // contains the k_left loop. " \n\t" " \n\t" ".LOOPKITER: \n\t" // MAIN LOOP " \n\t" "movapd -8 * 16(%%ebx), %%xmm1 \n\t" // iteration 0 "movapd %%xmm1, %%xmm2 \n\t" "mulpd %%xmm0, %%xmm1 \n\t" "addpd %%xmm1, %%xmm4 \n\t" "movapd -7 * 16(%%ebx), %%xmm1 \n\t" "mulpd %%xmm1, %%xmm0 \n\t" "addpd %%xmm0, %%xmm5 \n\t" "movapd -7 * 16(%%eax), %%xmm0 \n\t" "mulpd %%xmm0, %%xmm2 \n\t" "mulpd %%xmm0, %%xmm1 \n\t" "movapd -6 * 16(%%eax), %%xmm0 \n\t" "addpd %%xmm2, %%xmm6 \n\t" "addpd %%xmm1, %%xmm7 \n\t" " \n\t" "movapd -6 * 16(%%ebx), %%xmm1 \n\t" // iteration 1 "movapd %%xmm1, %%xmm2 \n\t" "mulpd %%xmm0, %%xmm1 \n\t" "addpd %%xmm1, %%xmm4 \n\t" "movapd -5 * 16(%%ebx), %%xmm1 \n\t" "mulpd %%xmm1, %%xmm0 \n\t" "addpd %%xmm0, %%xmm5 \n\t" "movapd -5 * 16(%%eax), %%xmm0 \n\t" "mulpd %%xmm0, %%xmm2 \n\t" "mulpd %%xmm0, %%xmm1 \n\t" "movapd 0 * 16(%%eax), %%xmm0 \n\t" "addpd %%xmm2, %%xmm6 \n\t" "addpd %%xmm1, %%xmm7 \n\t" " \n\t" "movapd -4 * 16(%%ebx), %%xmm1 \n\t" // iteration 2 "movapd %%xmm1, %%xmm2 \n\t" "mulpd %%xmm3, %%xmm1 \n\t" "addpd %%xmm1, %%xmm4 \n\t" "movapd -3 * 16(%%ebx), %%xmm1 \n\t" "mulpd %%xmm1, %%xmm3 \n\t" "addpd %%xmm3, %%xmm5 \n\t" "movapd -3 * 16(%%eax), %%xmm3 \n\t" "mulpd %%xmm3, %%xmm2 \n\t" "mulpd %%xmm3, %%xmm1 \n\t" "movapd -2 * 16(%%eax), %%xmm3 \n\t" "addpd %%xmm2, %%xmm6 \n\t" "addpd %%xmm1, %%xmm7 \n\t" " \n\t" "movapd -2 * 16(%%ebx), %%xmm1 \n\t" // iteration 3 "movapd %%xmm1, %%xmm2 \n\t" "mulpd %%xmm3, %%xmm1 \n\t" "addpd %%xmm1, %%xmm4 \n\t" "movapd -1 * 16(%%ebx), %%xmm1 \n\t" "mulpd %%xmm1, %%xmm3 \n\t" "addpd %%xmm3, %%xmm5 \n\t" "movapd -1 * 16(%%eax), %%xmm3 \n\t" "mulpd %%xmm3, %%xmm2 \n\t" "mulpd %%xmm3, %%xmm1 \n\t" "movapd 4 * 16(%%eax), %%xmm3 \n\t" "addpd %%xmm2, %%xmm6 \n\t" "addpd %%xmm1, %%xmm7 \n\t" " \n\t" "movapd 0 * 16(%%ebx), %%xmm1 \n\t" // iteration 4 "movapd %%xmm1, %%xmm2 \n\t" "mulpd %%xmm0, %%xmm1 \n\t" "addpd %%xmm1, %%xmm4 \n\t" "movapd 1 * 16(%%ebx), %%xmm1 \n\t" "mulpd %%xmm1, %%xmm0 \n\t" "addpd %%xmm0, %%xmm5 \n\t" "movapd 1 * 16(%%eax), %%xmm0 \n\t" "mulpd %%xmm0, %%xmm2 \n\t" "mulpd %%xmm0, %%xmm1 \n\t" "movapd 2 * 16(%%eax), %%xmm0 \n\t" "addpd %%xmm2, %%xmm6 \n\t" "addpd %%xmm1, %%xmm7 \n\t" " \n\t" "movapd 2 * 16(%%ebx), %%xmm1 \n\t" // iteration 5 "movapd %%xmm1, %%xmm2 \n\t" "mulpd %%xmm0, %%xmm1 \n\t" "addpd %%xmm1, %%xmm4 \n\t" "movapd 3 * 16(%%ebx), %%xmm1 \n\t" "mulpd %%xmm1, %%xmm0 \n\t" "addpd %%xmm0, %%xmm5 \n\t" "movapd 3 * 16(%%eax), %%xmm0 \n\t" "mulpd %%xmm0, %%xmm2 \n\t" "mulpd %%xmm0, %%xmm1 \n\t" "movapd 8 * 16(%%eax), %%xmm0 \n\t" "addpd %%xmm2, %%xmm6 \n\t" "addpd %%xmm1, %%xmm7 \n\t" " \n\t" "movapd 4 * 16(%%ebx), %%xmm1 \n\t" // iteration 6 "movapd %%xmm1, %%xmm2 \n\t" "mulpd %%xmm3, %%xmm1 \n\t" "addpd %%xmm1, %%xmm4 \n\t" "movapd 5 * 16(%%ebx), %%xmm1 \n\t" "mulpd %%xmm1, %%xmm3 \n\t" "addpd %%xmm3, %%xmm5 \n\t" "movapd 5 * 16(%%eax), %%xmm3 \n\t" "mulpd %%xmm3, %%xmm2 \n\t" "mulpd %%xmm3, %%xmm1 \n\t" "movapd 6 * 16(%%eax), %%xmm3 \n\t" "addl $8 * 4 * 8, %%eax \n\t" // a += 8*4 (unroll x mr) "addpd %%xmm2, %%xmm6 \n\t" "addpd %%xmm1, %%xmm7 \n\t" " \n\t" "movapd 6 * 16(%%ebx), %%xmm1 \n\t" // iteration 7 "movapd %%xmm1, %%xmm2 \n\t" "mulpd %%xmm3, %%xmm1 \n\t" "addpd %%xmm1, %%xmm4 \n\t" "movapd 7 * 16(%%ebx), %%xmm1 \n\t" "addl $8 * 2 * 2 * 8, %%ebx \n\t" // b += 8*2*2 (unroll x nr x ndup) "mulpd %%xmm1, %%xmm3 \n\t" "addpd %%xmm3, %%xmm5 \n\t" "movapd -9 * 16(%%eax), %%xmm3 \n\t" "mulpd %%xmm3, %%xmm2 \n\t" "mulpd %%xmm3, %%xmm1 \n\t" "decl %%esi \n\t" // i -= 1; "movapd -4 * 16(%%eax), %%xmm3 \n\t" "addpd %%xmm2, %%xmm6 \n\t" "addpd %%xmm1, %%xmm7 \n\t" " \n\t" "jne .LOOPKITER \n\t" // iterate again if i != 0. " \n\t" " \n\t" " \n\t" ".CONSIDERKLEFT: \n\t" " \n\t" "movl %1, %%esi \n\t" // i = k_left; "testl %%esi, %%esi \n\t" // check i via logical AND. "je .POSTACCUM \n\t" // if i == 0, we're done; jump to end. " \n\t" // else, we prepare to enter k_left loop. " \n\t" " \n\t" ".LOOPKLEFT: \n\t" // EDGE LOOP " \n\t" "movapd -8 * 16(%%ebx), %%xmm1 \n\t" // iteration i "movapd %%xmm1, %%xmm2 \n\t" "mulpd %%xmm0, %%xmm1 \n\t" "addpd %%xmm1, %%xmm4 \n\t" "movapd -7 * 16(%%ebx), %%xmm1 \n\t" "addl $1 * 2 * 2 * 8, %%ebx \n\t" // b += 2*2 (1 x nr x ndup) "mulpd %%xmm1, %%xmm0 \n\t" "addpd %%xmm0, %%xmm5 \n\t" "movapd -7 * 16(%%eax), %%xmm0 \n\t" "mulpd %%xmm0, %%xmm2 \n\t" "mulpd %%xmm0, %%xmm1 \n\t" "movapd -6 * 16(%%eax), %%xmm0 \n\t" "addl $1 * 4 * 8, %%eax \n\t" // a += 4 (1 x mr) "addpd %%xmm2, %%xmm6 \n\t" "addpd %%xmm1, %%xmm7 \n\t" " \n\t" "decl %%esi \n\t" // i -= 1; "jne .LOOPKLEFT \n\t" // iterate again if i != 0. " \n\t" " \n\t" " \n\t" ".POSTACCUM: \n\t" " \n\t" "movl %4, %%eax \n\t" // load address of alpha "movl %5, %%ebx \n\t" // load address of beta "movddup (%%eax), %%xmm2 \n\t" // load alpha and duplicate "movddup (%%ebx), %%xmm3 \n\t" // load beta and duplicate " \n\t" " \n\t" " \n\t" "movl %7, %%esi \n\t" // load rs_c "sall $3, %%esi \n\t" // rs_c *= sizeof(double) " \n\t" "leal (%%ecx,%%esi,2), %%edx \n\t" // load address of c + 2*rs_c; " \n\t" " \n\t" " \n\t" "movlpd (%%ecx), %%xmm0 \n\t" // load c00 and c10, "movhpd (%%ecx,%%esi), %%xmm0 \n\t" "mulpd %%xmm2, %%xmm4 \n\t" // scale by alpha, "mulpd %%xmm3, %%xmm0 \n\t" // scale by beta, "addpd %%xmm4, %%xmm0 \n\t" // add the gemm result, "movlpd %%xmm0, (%%ecx) \n\t" // and store back to memory. "movhpd %%xmm0, (%%ecx,%%esi) \n\t" "addl %%edi, %%ecx \n\t" " \n\t" "movlpd (%%edx), %%xmm1 \n\t" // load c01 and c11, "movhpd (%%edx,%%esi), %%xmm1 \n\t" "mulpd %%xmm2, %%xmm6 \n\t" // scale by alpha, "mulpd %%xmm3, %%xmm1 \n\t" // scale by beta, "addpd %%xmm6, %%xmm1 \n\t" // add the gemm result, "movlpd %%xmm1, (%%edx) \n\t" // and store back to memory. "movhpd %%xmm1, (%%edx,%%esi) \n\t" "addl %%edi, %%edx \n\t" " \n\t" "movlpd (%%ecx), %%xmm0 \n\t" // load c20 and c30, "movhpd (%%ecx,%%esi), %%xmm0 \n\t" "mulpd %%xmm2, %%xmm5 \n\t" // scale by alpha, "mulpd %%xmm3, %%xmm0 \n\t" // scale by beta, "addpd %%xmm5, %%xmm0 \n\t" // add the gemm result, "movlpd %%xmm0, (%%ecx) \n\t" // and store back to memory. "movhpd %%xmm0, (%%ecx,%%esi) \n\t" " \n\t" "movlpd (%%edx), %%xmm1 \n\t" // load c21 and c31, "movhpd (%%edx,%%esi), %%xmm1 \n\t" "mulpd %%xmm2, %%xmm7 \n\t" // scale by alpha, "mulpd %%xmm3, %%xmm1 \n\t" // scale by beta, "addpd %%xmm7, %%xmm1 \n\t" // add the gemm result, "movlpd %%xmm1, (%%edx) \n\t" // and store back to memory. "movhpd %%xmm1, (%%edx,%%esi) \n\t" " \n\t" " \n\t" " \n\t" : // output operands (none) : // input operands "m" (k_iter), "m" (k_left), "m" (a), "m" (b), "m" (alpha), "m" (beta), "m" (c), "m" (rs_c), "m" (cs_c) : // register clobber list "eax", "ebx", "ecx", "edx", "esi", "edi", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "memory" ); } void bli_cgemm_opt_d4x2( dim_t k, scomplex* restrict alpha, scomplex* restrict a, scomplex* restrict b, scomplex* restrict beta, scomplex* restrict c, inc_t rs_c, inc_t cs_c, scomplex* restrict a_next, scomplex* restrict b_next ) { bli_check_error_code( BLIS_NOT_YET_IMPLEMENTED ); } void bli_zgemm_opt_d4x2( dim_t k, dcomplex* restrict alpha, dcomplex* restrict a, dcomplex* restrict b, dcomplex* restrict beta, dcomplex* restrict c, inc_t rs_c, inc_t cs_c, dcomplex* restrict a_next, dcomplex* restrict b_next ) { bli_check_error_code( BLIS_NOT_YET_IMPLEMENTED ); } blis-0.9.0/kernels/old/x86/3/bli_gemmtrsm_l_opt_d4x2.c000066400000000000000000000516121422157504600223570ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_sgemmtrsm_l_opt_d4x2( dim_t k, float* restrict alpha, float* restrict a10, float* restrict a11, float* restrict bd01, float* restrict bd11, float* restrict b11, float* restrict c11, inc_t rs_c, inc_t cs_c, float* restrict a_next, float* restrict b_next ) { bli_check_error_code( BLIS_NOT_YET_IMPLEMENTED ); } void bli_dgemmtrsm_l_opt_d4x2( dim_t k, double* restrict alpha, double* restrict a10, double* restrict a11, double* restrict bd01, double* restrict bd11, double* restrict b11, double* restrict c11, inc_t rs_c, inc_t cs_c, double* restrict a_next, double* restrict b_next ) { dim_t k_iter; dim_t k_left; k_iter = k / 8; k_left = k % 8; __asm__ volatile ( " \n\t" "movl %2, %%eax \n\t" // load address of a10. "movl %4, %%ebx \n\t" // load address of bd01. " \n\t" "addl $8 * 16, %%eax \n\t" // increment pointers to allow byte "addl $8 * 16, %%ebx \n\t" // offsets in the unrolled iterations. " \n\t" "movapd -8 * 16(%%eax), %%xmm0 \n\t" // initialize loop by pre-loading elements "movapd -4 * 16(%%eax), %%xmm3 \n\t" // and of a. " \n\t" "pxor %%xmm4, %%xmm4 \n\t" "pxor %%xmm5, %%xmm5 \n\t" "pxor %%xmm6, %%xmm6 \n\t" "pxor %%xmm7, %%xmm7 \n\t" " \n\t" " \n\t" " \n\t" "movl %0, %%esi \n\t" // i = k_iter; "testl %%esi, %%esi \n\t" // check i via logical AND. "je .CONSIDERKLEFT \n\t" // if i == 0, jump to code that " \n\t" // contains the k_left loop. " \n\t" " \n\t" ".LOOPKITER: \n\t" // MAIN LOOP " \n\t" "movapd -8 * 16(%%ebx), %%xmm1 \n\t" // iteration 0 "movapd %%xmm1, %%xmm2 \n\t" "mulpd %%xmm0, %%xmm1 \n\t" "addpd %%xmm1, %%xmm4 \n\t" "movapd -7 * 16(%%ebx), %%xmm1 \n\t" "mulpd %%xmm1, %%xmm0 \n\t" "addpd %%xmm0, %%xmm5 \n\t" "movapd -7 * 16(%%eax), %%xmm0 \n\t" "mulpd %%xmm0, %%xmm2 \n\t" "mulpd %%xmm0, %%xmm1 \n\t" "movapd -6 * 16(%%eax), %%xmm0 \n\t" "addpd %%xmm2, %%xmm6 \n\t" "addpd %%xmm1, %%xmm7 \n\t" " \n\t" "movapd -6 * 16(%%ebx), %%xmm1 \n\t" // iteration 1 "movapd %%xmm1, %%xmm2 \n\t" "mulpd %%xmm0, %%xmm1 \n\t" "addpd %%xmm1, %%xmm4 \n\t" "movapd -5 * 16(%%ebx), %%xmm1 \n\t" "mulpd %%xmm1, %%xmm0 \n\t" "addpd %%xmm0, %%xmm5 \n\t" "movapd -5 * 16(%%eax), %%xmm0 \n\t" "mulpd %%xmm0, %%xmm2 \n\t" "mulpd %%xmm0, %%xmm1 \n\t" "movapd 0 * 16(%%eax), %%xmm0 \n\t" "addpd %%xmm2, %%xmm6 \n\t" "addpd %%xmm1, %%xmm7 \n\t" " \n\t" "movapd -4 * 16(%%ebx), %%xmm1 \n\t" // iteration 2 "movapd %%xmm1, %%xmm2 \n\t" "mulpd %%xmm3, %%xmm1 \n\t" "addpd %%xmm1, %%xmm4 \n\t" "movapd -3 * 16(%%ebx), %%xmm1 \n\t" "mulpd %%xmm1, %%xmm3 \n\t" "addpd %%xmm3, %%xmm5 \n\t" "movapd -3 * 16(%%eax), %%xmm3 \n\t" "mulpd %%xmm3, %%xmm2 \n\t" "mulpd %%xmm3, %%xmm1 \n\t" "movapd -2 * 16(%%eax), %%xmm3 \n\t" "addpd %%xmm2, %%xmm6 \n\t" "addpd %%xmm1, %%xmm7 \n\t" " \n\t" "movapd -2 * 16(%%ebx), %%xmm1 \n\t" // iteration 3 "movapd %%xmm1, %%xmm2 \n\t" "mulpd %%xmm3, %%xmm1 \n\t" "addpd %%xmm1, %%xmm4 \n\t" "movapd -1 * 16(%%ebx), %%xmm1 \n\t" "mulpd %%xmm1, %%xmm3 \n\t" "addpd %%xmm3, %%xmm5 \n\t" "movapd -1 * 16(%%eax), %%xmm3 \n\t" "mulpd %%xmm3, %%xmm2 \n\t" "mulpd %%xmm3, %%xmm1 \n\t" "movapd 4 * 16(%%eax), %%xmm3 \n\t" "addpd %%xmm2, %%xmm6 \n\t" "addpd %%xmm1, %%xmm7 \n\t" " \n\t" "movapd 0 * 16(%%ebx), %%xmm1 \n\t" // iteration 4 "movapd %%xmm1, %%xmm2 \n\t" "mulpd %%xmm0, %%xmm1 \n\t" "addpd %%xmm1, %%xmm4 \n\t" "movapd 1 * 16(%%ebx), %%xmm1 \n\t" "mulpd %%xmm1, %%xmm0 \n\t" "addpd %%xmm0, %%xmm5 \n\t" "movapd 1 * 16(%%eax), %%xmm0 \n\t" "mulpd %%xmm0, %%xmm2 \n\t" "mulpd %%xmm0, %%xmm1 \n\t" "movapd 2 * 16(%%eax), %%xmm0 \n\t" "addpd %%xmm2, %%xmm6 \n\t" "addpd %%xmm1, %%xmm7 \n\t" " \n\t" "movapd 2 * 16(%%ebx), %%xmm1 \n\t" // iteration 5 "movapd %%xmm1, %%xmm2 \n\t" "mulpd %%xmm0, %%xmm1 \n\t" "addpd %%xmm1, %%xmm4 \n\t" "movapd 3 * 16(%%ebx), %%xmm1 \n\t" "mulpd %%xmm1, %%xmm0 \n\t" "addpd %%xmm0, %%xmm5 \n\t" "movapd 3 * 16(%%eax), %%xmm0 \n\t" "mulpd %%xmm0, %%xmm2 \n\t" "mulpd %%xmm0, %%xmm1 \n\t" "movapd 8 * 16(%%eax), %%xmm0 \n\t" "addpd %%xmm2, %%xmm6 \n\t" "addpd %%xmm1, %%xmm7 \n\t" " \n\t" "movapd 4 * 16(%%ebx), %%xmm1 \n\t" // iteration 6 "movapd %%xmm1, %%xmm2 \n\t" "mulpd %%xmm3, %%xmm1 \n\t" "addpd %%xmm1, %%xmm4 \n\t" "movapd 5 * 16(%%ebx), %%xmm1 \n\t" "mulpd %%xmm1, %%xmm3 \n\t" "addpd %%xmm3, %%xmm5 \n\t" "movapd 5 * 16(%%eax), %%xmm3 \n\t" "mulpd %%xmm3, %%xmm2 \n\t" "mulpd %%xmm3, %%xmm1 \n\t" "movapd 6 * 16(%%eax), %%xmm3 \n\t" "addl $8 * 4 * 8, %%eax \n\t" // a += 8*4 (unroll x mr) "addpd %%xmm2, %%xmm6 \n\t" "addpd %%xmm1, %%xmm7 \n\t" " \n\t" "movapd 6 * 16(%%ebx), %%xmm1 \n\t" // iteration 7 "movapd %%xmm1, %%xmm2 \n\t" "mulpd %%xmm3, %%xmm1 \n\t" "addpd %%xmm1, %%xmm4 \n\t" "movapd 7 * 16(%%ebx), %%xmm1 \n\t" "addl $8 * 2 * 2 * 8, %%ebx \n\t" // b += 8*2*2 (unroll x nr x ndup) "mulpd %%xmm1, %%xmm3 \n\t" "addpd %%xmm3, %%xmm5 \n\t" "movapd -9 * 16(%%eax), %%xmm3 \n\t" "mulpd %%xmm3, %%xmm2 \n\t" "mulpd %%xmm3, %%xmm1 \n\t" "decl %%esi \n\t" // i -= 1; "movapd -4 * 16(%%eax), %%xmm3 \n\t" "addpd %%xmm2, %%xmm6 \n\t" "addpd %%xmm1, %%xmm7 \n\t" " \n\t" "jne .LOOPKITER \n\t" // iterate again if i != 0. " \n\t" " \n\t" " \n\t" ".CONSIDERKLEFT: \n\t" " \n\t" "movl %1, %%esi \n\t" // i = k_left; "testl %%esi, %%esi \n\t" // check i via logical AND. "je .POSTACCUM \n\t" // if i == 0, we're done; jump to end. " \n\t" // else, we prepare to enter k_left loop. " \n\t" " \n\t" ".LOOPKLEFT: \n\t" // EDGE LOOP " \n\t" "movapd -8 * 16(%%ebx), %%xmm1 \n\t" // iteration i "movapd %%xmm1, %%xmm2 \n\t" "mulpd %%xmm0, %%xmm1 \n\t" "addpd %%xmm1, %%xmm4 \n\t" "movapd -7 * 16(%%ebx), %%xmm1 \n\t" "addl $1 * 2 * 2 * 8, %%ebx \n\t" // b += 2*2 (1 x nr x ndup) "mulpd %%xmm1, %%xmm0 \n\t" "addpd %%xmm0, %%xmm5 \n\t" "movapd -7 * 16(%%eax), %%xmm0 \n\t" "mulpd %%xmm0, %%xmm2 \n\t" "mulpd %%xmm0, %%xmm1 \n\t" "movapd -6 * 16(%%eax), %%xmm0 \n\t" "addl $1 * 4 * 8, %%eax \n\t" // a += 4 (1 x mr) "addpd %%xmm2, %%xmm6 \n\t" "addpd %%xmm1, %%xmm7 \n\t" " \n\t" "decl %%esi \n\t" // i -= 1; "jne .LOOPKLEFT \n\t" // iterate again if i != 0. " \n\t" " \n\t" " \n\t" ".POSTACCUM: \n\t" " \n\t" " \n\t" "movl %6, %%ebx \n\t" // load address of b11. " \n\t" " \n\t" // xmm4 == ( ab00 xmm5 == ( ab01 " \n\t" // ab10 ) ab11 ) " \n\t" // xmm6 == ( ab20 xmm7 == ( ab21 " \n\t" // ab30 ) ab31 ) "movapd %%xmm4, %%xmm0 \n\t" "unpcklpd %%xmm5, %%xmm0 \n\t" "unpckhpd %%xmm5, %%xmm4 \n\t" "movapd %%xmm4, %%xmm1 \n\t" " \n\t" "movapd %%xmm6, %%xmm2 \n\t" "unpcklpd %%xmm7, %%xmm2 \n\t" "unpckhpd %%xmm7, %%xmm6 \n\t" "movapd %%xmm6, %%xmm3 \n\t" " \n\t" // xmm0 == ( ab00 ab01 ) " \n\t" // xmm1 == ( ab10 ab11 ) " \n\t" // xmm2 == ( ab20 ab21 ) " \n\t" // xmm3 == ( ab30 ab31 ) " \n\t" "movl %10, %%eax \n\t" // load address of alpha "movddup (%%eax), %%xmm7 \n\t" // load alpha and duplicate " \n\t" "movapd 0 * 16(%%ebx), %%xmm4 \n\t" "movapd 1 * 16(%%ebx), %%xmm5 \n\t" "mulpd %%xmm7, %%xmm4 \n\t" // xmm4 = alpha * ( beta00 beta01 ) "mulpd %%xmm7, %%xmm5 \n\t" // xmm5 = alpha * ( beta10 beta11 ) "movapd 2 * 16(%%ebx), %%xmm6 \n\t" "mulpd %%xmm7, %%xmm6 \n\t" // xmm6 = alpha * ( beta20 beta21 ) "mulpd 3 * 16(%%ebx), %%xmm7 \n\t" // xmm7 = alpha * ( beta30 beta31 ) " \n\t" "subpd %%xmm0, %%xmm4 \n\t" // xmm4 -= xmm0 "subpd %%xmm1, %%xmm5 \n\t" // xmm5 -= xmm1 "subpd %%xmm2, %%xmm6 \n\t" // xmm6 -= xmm2 "subpd %%xmm3, %%xmm7 \n\t" // xmm7 -= xmm3 " \n\t" " \n\t" " \n\t" ".TRSM: \n\t" " \n\t" " \n\t" "movl %3, %%eax \n\t" // load address of a11 "movl %7, %%ecx \n\t" // load address of c11 " \n\t" "movl %8, %%edi \n\t" // load rs_c "movl %9, %%esi \n\t" // load cs_c "sall $3, %%edi \n\t" // rs_c *= sizeof( double ) "sall $3, %%esi \n\t" // cs_c *= sizeof( double ) " \n\t" " \n\t" " \n\t" " \n\t" // iteration 0 " \n\t" "movddup (0+0*4)*8(%%eax), %%xmm0 \n\t" // load xmm0 = (1/alpha00) " \n\t" "mulpd %%xmm0, %%xmm4 \n\t" // xmm4 *= (1/alpha00); " \n\t" "movapd %%xmm4, 0 * 16(%%ebx) \n\t" // store ( beta00 beta01 ) = xmm4 "movlpd %%xmm4, (%%ecx) \n\t" // store ( gamma00 ) = xmm4[0] "movhpd %%xmm4, (%%ecx,%%esi) \n\t" // store ( gamma01 ) = xmm4[1] "addl %%edi, %%ecx \n\t" // c11 += rs_c " \n\t" " \n\t" " \n\t" " \n\t" // iteration 1 " \n\t" "movddup (1+0*4)*8(%%eax), %%xmm0 \n\t" // load xmm0 = alpha10 "movddup (1+1*4)*8(%%eax), %%xmm1 \n\t" // load xmm1 = (1/alpha11) " \n\t" "mulpd %%xmm4, %%xmm0 \n\t" // xmm0 = alpha10 * ( beta00 beta01 ) "subpd %%xmm0, %%xmm5 \n\t" // xmm5 -= xmm0 "mulpd %%xmm1, %%xmm5 \n\t" // xmm5 *= (1/alpha11); " \n\t" "movapd %%xmm5, 1 * 16(%%ebx) \n\t" // store ( beta10 beta11 ) = xmm5 "movlpd %%xmm5, (%%ecx) \n\t" // store ( gamma10 ) = xmm5[0] "movhpd %%xmm5, (%%ecx,%%esi) \n\t" // store ( gamma11 ) = xmm5[1] "addl %%edi, %%ecx \n\t" // c11 += rs_c " \n\t" " \n\t" " \n\t" " \n\t" // iteration 2 " \n\t" "movddup (2+0*4)*8(%%eax), %%xmm0 \n\t" // load xmm0 = alpha20 "movddup (2+1*4)*8(%%eax), %%xmm1 \n\t" // load xmm1 = alpha21 "movddup (2+2*4)*8(%%eax), %%xmm2 \n\t" // load xmm2 = (1/alpha22) " \n\t" "mulpd %%xmm4, %%xmm0 \n\t" // xmm0 = alpha20 * ( beta00 beta01 ) "mulpd %%xmm5, %%xmm1 \n\t" // xmm1 = alpha21 * ( beta10 beta11 ) "addpd %%xmm1, %%xmm0 \n\t" // xmm0 += xmm1; "subpd %%xmm0, %%xmm6 \n\t" // xmm6 -= xmm0 "mulpd %%xmm2, %%xmm6 \n\t" // xmm6 *= (1/alpha22); " \n\t" "movapd %%xmm6, 2 * 16(%%ebx) \n\t" // store ( beta20 beta21 ) = xmm6 "movlpd %%xmm6, (%%ecx) \n\t" // store ( gamma20 ) = xmm6[0] "movhpd %%xmm6, (%%ecx,%%esi) \n\t" // store ( gamma21 ) = xmm6[1] "addl %%edi, %%ecx \n\t" // c11 += rs_c " \n\t" " \n\t" " \n\t" " \n\t" // iteration 3 " \n\t" "movddup (3+0*4)*8(%%eax), %%xmm0 \n\t" // load xmm0 = alpha30 "movddup (3+1*4)*8(%%eax), %%xmm1 \n\t" // load xmm1 = alpha31 "movddup (3+2*4)*8(%%eax), %%xmm2 \n\t" // load xmm2 = alpha32 "movddup (3+3*4)*8(%%eax), %%xmm3 \n\t" // load xmm3 = (1/alpha33) " \n\t" "mulpd %%xmm4, %%xmm0 \n\t" // xmm0 = alpha30 * ( beta00 beta01 ) "mulpd %%xmm5, %%xmm1 \n\t" // xmm1 = alpha31 * ( beta10 beta11 ) "mulpd %%xmm6, %%xmm2 \n\t" // xmm2 = alpha32 * ( beta20 beta21 ) "addpd %%xmm1, %%xmm0 \n\t" // xmm0 += xmm1 "addpd %%xmm2, %%xmm0 \n\t" // xmm0 += xmm2 "subpd %%xmm0, %%xmm7 \n\t" // xmm7 -= xmm0 "mulpd %%xmm3, %%xmm7 \n\t" // xmm7 *= (1/alpha33); " \n\t" "movapd %%xmm7, 3 * 16(%%ebx) \n\t" // store ( beta30 beta31 ) = xmm7 "movlpd %%xmm7, (%%ecx) \n\t" // store ( gamma30 ) = xmm7[0] "movhpd %%xmm7, (%%ecx,%%esi) \n\t" // store ( gamma31 ) = xmm7[1] " \n\t" " \n\t" " \n\t" ".UPDATEBD11: \n\t" " \n\t" " \n\t" "movl %5, %%edx \n\t" " \n\t" "movddup %%xmm4, %%xmm0 \n\t" "movddup %%xmm5, %%xmm1 \n\t" "movddup %%xmm6, %%xmm2 \n\t" "movddup %%xmm7, %%xmm3 \n\t" " \n\t" "unpckhpd %%xmm4, %%xmm4 \n\t" "unpckhpd %%xmm5, %%xmm5 \n\t" "unpckhpd %%xmm6, %%xmm6 \n\t" "unpckhpd %%xmm7, %%xmm7 \n\t" " \n\t" "movapd %%xmm0, 0 * 16(%%edx) \n\t" "movapd %%xmm4, 1 * 16(%%edx) \n\t" "movapd %%xmm1, 2 * 16(%%edx) \n\t" "movapd %%xmm5, 3 * 16(%%edx) \n\t" "movapd %%xmm2, 4 * 16(%%edx) \n\t" "movapd %%xmm6, 5 * 16(%%edx) \n\t" "movapd %%xmm3, 6 * 16(%%edx) \n\t" "movapd %%xmm7, 7 * 16(%%edx) \n\t" " \n\t" " \n\t" : // output operands (none) : // input operands "m" (k_iter), "m" (k_left), "m" (a10), "m" (a11), "m" (bd01), "m" (bd11), "m" (b11), "m" (c11), "m" (rs_c), "m" (cs_c), "m" (alpha) : // register clobber list "eax", "ebx", "ecx", "edx", "esi", "edi", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "memory" ); } void bli_cgemmtrsm_l_opt_d4x2( dim_t k, scomplex* restrict alpha, scomplex* restrict a10, scomplex* restrict a11, scomplex* restrict bd01, scomplex* restrict bd11, scomplex* restrict b11, scomplex* restrict c11, inc_t rs_c, inc_t cs_c, scomplex* restrict a_next, scomplex* restrict b_next ) { bli_check_error_code( BLIS_NOT_YET_IMPLEMENTED ); } void bli_zgemmtrsm_l_opt_d4x2( dim_t k, dcomplex* restrict alpha, dcomplex* restrict a10, dcomplex* restrict a11, dcomplex* restrict bd01, dcomplex* restrict bd11, dcomplex* restrict b11, dcomplex* restrict c11, inc_t rs_c, inc_t cs_c, dcomplex* restrict a_next, dcomplex* restrict b_next ) { bli_check_error_code( BLIS_NOT_YET_IMPLEMENTED ); } blis-0.9.0/kernels/old/x86/3/bli_gemmtrsm_u_opt_d4x2.c000066400000000000000000000522251422157504600223710ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_sgemmtrsm_u_opt_d4x2( dim_t k, float* restrict alpha, float* restrict a12, float* restrict a11, float* restrict bd21, float* restrict bd11, float* restrict b11, float* restrict c11, inc_t rs_c, inc_t cs_c, float* restrict a_next, float* restrict b_next ) { bli_check_error_code( BLIS_NOT_YET_IMPLEMENTED ); } void bli_dgemmtrsm_u_opt_d4x2( dim_t k, double* restrict alpha, double* restrict a12, double* restrict a11, double* restrict bd21, double* restrict bd11, double* restrict b11, double* restrict c11, inc_t rs_c, inc_t cs_c, double* restrict a_next, double* restrict b_next ) { dim_t k_iter; dim_t k_left; k_iter = k / 8; k_left = k % 8; __asm__ volatile ( " \n\t" "movl %2, %%eax \n\t" // load address of a12. "movl %4, %%ebx \n\t" // load address of bd21. " \n\t" "addl $8 * 16, %%eax \n\t" // increment pointers to allow byte "addl $8 * 16, %%ebx \n\t" // offsets in the unrolled iterations. " \n\t" "movapd -8 * 16(%%eax), %%xmm0 \n\t" // initialize loop by pre-loading elements "movapd -4 * 16(%%eax), %%xmm3 \n\t" // of a. " \n\t" "pxor %%xmm4, %%xmm4 \n\t" "pxor %%xmm5, %%xmm5 \n\t" "pxor %%xmm6, %%xmm6 \n\t" "pxor %%xmm7, %%xmm7 \n\t" " \n\t" " \n\t" " \n\t" "movl %0, %%esi \n\t" // i = k_iter; "testl %%esi, %%esi \n\t" // check i via logical AND. "je .CONSIDERKLEFT \n\t" // if i == 0, jump to code that " \n\t" // contains the k_left loop. " \n\t" " \n\t" ".LOOPKITER: \n\t" // MAIN LOOP " \n\t" "movapd -8 * 16(%%ebx), %%xmm1 \n\t" // iteration 0 "movapd %%xmm1, %%xmm2 \n\t" "mulpd %%xmm0, %%xmm1 \n\t" "addpd %%xmm1, %%xmm4 \n\t" "movapd -7 * 16(%%ebx), %%xmm1 \n\t" "mulpd %%xmm1, %%xmm0 \n\t" "addpd %%xmm0, %%xmm5 \n\t" "movapd -7 * 16(%%eax), %%xmm0 \n\t" "mulpd %%xmm0, %%xmm2 \n\t" "mulpd %%xmm0, %%xmm1 \n\t" "movapd -6 * 16(%%eax), %%xmm0 \n\t" "addpd %%xmm2, %%xmm6 \n\t" "addpd %%xmm1, %%xmm7 \n\t" " \n\t" "movapd -6 * 16(%%ebx), %%xmm1 \n\t" // iteration 1 "movapd %%xmm1, %%xmm2 \n\t" "mulpd %%xmm0, %%xmm1 \n\t" "addpd %%xmm1, %%xmm4 \n\t" "movapd -5 * 16(%%ebx), %%xmm1 \n\t" "mulpd %%xmm1, %%xmm0 \n\t" "addpd %%xmm0, %%xmm5 \n\t" "movapd -5 * 16(%%eax), %%xmm0 \n\t" "mulpd %%xmm0, %%xmm2 \n\t" "mulpd %%xmm0, %%xmm1 \n\t" "movapd 0 * 16(%%eax), %%xmm0 \n\t" "addpd %%xmm2, %%xmm6 \n\t" "addpd %%xmm1, %%xmm7 \n\t" " \n\t" "movapd -4 * 16(%%ebx), %%xmm1 \n\t" // iteration 2 "movapd %%xmm1, %%xmm2 \n\t" "mulpd %%xmm3, %%xmm1 \n\t" "addpd %%xmm1, %%xmm4 \n\t" "movapd -3 * 16(%%ebx), %%xmm1 \n\t" "mulpd %%xmm1, %%xmm3 \n\t" "addpd %%xmm3, %%xmm5 \n\t" "movapd -3 * 16(%%eax), %%xmm3 \n\t" "mulpd %%xmm3, %%xmm2 \n\t" "mulpd %%xmm3, %%xmm1 \n\t" "movapd -2 * 16(%%eax), %%xmm3 \n\t" "addpd %%xmm2, %%xmm6 \n\t" "addpd %%xmm1, %%xmm7 \n\t" " \n\t" "movapd -2 * 16(%%ebx), %%xmm1 \n\t" // iteration 3 "movapd %%xmm1, %%xmm2 \n\t" "mulpd %%xmm3, %%xmm1 \n\t" "addpd %%xmm1, %%xmm4 \n\t" "movapd -1 * 16(%%ebx), %%xmm1 \n\t" "mulpd %%xmm1, %%xmm3 \n\t" "addpd %%xmm3, %%xmm5 \n\t" "movapd -1 * 16(%%eax), %%xmm3 \n\t" "mulpd %%xmm3, %%xmm2 \n\t" "mulpd %%xmm3, %%xmm1 \n\t" "movapd 4 * 16(%%eax), %%xmm3 \n\t" "addpd %%xmm2, %%xmm6 \n\t" "addpd %%xmm1, %%xmm7 \n\t" " \n\t" "movapd 0 * 16(%%ebx), %%xmm1 \n\t" // iteration 4 "movapd %%xmm1, %%xmm2 \n\t" "mulpd %%xmm0, %%xmm1 \n\t" "addpd %%xmm1, %%xmm4 \n\t" "movapd 1 * 16(%%ebx), %%xmm1 \n\t" "mulpd %%xmm1, %%xmm0 \n\t" "addpd %%xmm0, %%xmm5 \n\t" "movapd 1 * 16(%%eax), %%xmm0 \n\t" "mulpd %%xmm0, %%xmm2 \n\t" "mulpd %%xmm0, %%xmm1 \n\t" "movapd 2 * 16(%%eax), %%xmm0 \n\t" "addpd %%xmm2, %%xmm6 \n\t" "addpd %%xmm1, %%xmm7 \n\t" " \n\t" "movapd 2 * 16(%%ebx), %%xmm1 \n\t" // iteration 5 "movapd %%xmm1, %%xmm2 \n\t" "mulpd %%xmm0, %%xmm1 \n\t" "addpd %%xmm1, %%xmm4 \n\t" "movapd 3 * 16(%%ebx), %%xmm1 \n\t" "mulpd %%xmm1, %%xmm0 \n\t" "addpd %%xmm0, %%xmm5 \n\t" "movapd 3 * 16(%%eax), %%xmm0 \n\t" "mulpd %%xmm0, %%xmm2 \n\t" "mulpd %%xmm0, %%xmm1 \n\t" "movapd 8 * 16(%%eax), %%xmm0 \n\t" "addpd %%xmm2, %%xmm6 \n\t" "addpd %%xmm1, %%xmm7 \n\t" " \n\t" "movapd 4 * 16(%%ebx), %%xmm1 \n\t" // iteration 6 "movapd %%xmm1, %%xmm2 \n\t" "mulpd %%xmm3, %%xmm1 \n\t" "addpd %%xmm1, %%xmm4 \n\t" "movapd 5 * 16(%%ebx), %%xmm1 \n\t" "mulpd %%xmm1, %%xmm3 \n\t" "addpd %%xmm3, %%xmm5 \n\t" "movapd 5 * 16(%%eax), %%xmm3 \n\t" "mulpd %%xmm3, %%xmm2 \n\t" "mulpd %%xmm3, %%xmm1 \n\t" "movapd 6 * 16(%%eax), %%xmm3 \n\t" "addl $8 * 4 * 8, %%eax \n\t" // a += 8*4 (unroll x mr) "addpd %%xmm2, %%xmm6 \n\t" "addpd %%xmm1, %%xmm7 \n\t" " \n\t" "movapd 6 * 16(%%ebx), %%xmm1 \n\t" // iteration 7 "movapd %%xmm1, %%xmm2 \n\t" "mulpd %%xmm3, %%xmm1 \n\t" "addpd %%xmm1, %%xmm4 \n\t" "movapd 7 * 16(%%ebx), %%xmm1 \n\t" "addl $8 * 2 * 2 * 8, %%ebx \n\t" // b += 8*2*2 (unroll x nr x ndup) "mulpd %%xmm1, %%xmm3 \n\t" "addpd %%xmm3, %%xmm5 \n\t" "movapd -9 * 16(%%eax), %%xmm3 \n\t" "mulpd %%xmm3, %%xmm2 \n\t" "mulpd %%xmm3, %%xmm1 \n\t" "decl %%esi \n\t" // i -= 1; "movapd -4 * 16(%%eax), %%xmm3 \n\t" "addpd %%xmm2, %%xmm6 \n\t" "addpd %%xmm1, %%xmm7 \n\t" " \n\t" "jne .LOOPKITER \n\t" // iterate again if i != 0. " \n\t" " \n\t" " \n\t" ".CONSIDERKLEFT: \n\t" " \n\t" "movl %1, %%esi \n\t" // i = k_left; "testl %%esi, %%esi \n\t" // check i via logical AND. "je .POSTACCUM \n\t" // if i == 0, we're done; jump to end. " \n\t" // else, we prepare to enter k_left loop. " \n\t" " \n\t" ".LOOPKLEFT: \n\t" // EDGE LOOP " \n\t" "movapd -8 * 16(%%ebx), %%xmm1 \n\t" // iteration i "movapd %%xmm1, %%xmm2 \n\t" "mulpd %%xmm0, %%xmm1 \n\t" "addpd %%xmm1, %%xmm4 \n\t" "movapd -7 * 16(%%ebx), %%xmm1 \n\t" "addl $1 * 2 * 2 * 8, %%ebx \n\t" // b += 2*2 (1 x nr x ndup) "mulpd %%xmm1, %%xmm0 \n\t" "addpd %%xmm0, %%xmm5 \n\t" "movapd -7 * 16(%%eax), %%xmm0 \n\t" "mulpd %%xmm0, %%xmm2 \n\t" "mulpd %%xmm0, %%xmm1 \n\t" "movapd -6 * 16(%%eax), %%xmm0 \n\t" "addl $1 * 4 * 8, %%eax \n\t" // a += 4 (1 x mr) "addpd %%xmm2, %%xmm6 \n\t" "addpd %%xmm1, %%xmm7 \n\t" " \n\t" "decl %%esi \n\t" // i -= 1; "jne .LOOPKLEFT \n\t" // iterate again if i != 0. " \n\t" " \n\t" " \n\t" ".POSTACCUM: \n\t" " \n\t" " \n\t" "movl %6, %%ebx \n\t" // load address of b11. " \n\t" " \n\t" // xmm4 == ( ab00 xmm5 == ( ab01 " \n\t" // ab10 ) ab11 ) " \n\t" // xmm6 == ( ab20 xmm7 == ( ab21 " \n\t" // ab30 ) ab31 ) "movapd %%xmm4, %%xmm0 \n\t" "unpcklpd %%xmm5, %%xmm0 \n\t" "unpckhpd %%xmm5, %%xmm4 \n\t" "movapd %%xmm4, %%xmm1 \n\t" " \n\t" "movapd %%xmm6, %%xmm2 \n\t" "unpcklpd %%xmm7, %%xmm2 \n\t" "unpckhpd %%xmm7, %%xmm6 \n\t" "movapd %%xmm6, %%xmm3 \n\t" " \n\t" // xmm0 == ( ab00 ab01 ) " \n\t" // xmm1 == ( ab10 ab11 ) " \n\t" // xmm2 == ( ab20 ab21 ) " \n\t" // xmm3 == ( ab30 ab31 ) " \n\t" "movl %10, %%eax \n\t" // load address of alpha "movddup (%%eax), %%xmm7 \n\t" // load alpha and duplicate " \n\t" "movapd 0 * 16(%%ebx), %%xmm4 \n\t" // load xmm4 = ( beta00 beta01 ) "movapd 1 * 16(%%ebx), %%xmm5 \n\t" // load xmm5 = ( beta10 beta11 ) "movapd 2 * 16(%%ebx), %%xmm6 \n\t" // load xmm6 = ( beta20 beta21 ) "mulpd %%xmm7, %%xmm4 \n\t" // xmm4 *= alpha "mulpd %%xmm7, %%xmm5 \n\t" // xmm5 *= alpha "mulpd %%xmm7, %%xmm6 \n\t" // xmm6 *= alpha //"movapd 3 * 16(%%ebx), %%xmm7 \n\t" // load xmm7 = ( beta30 beta31 ) "mulpd 3 * 16(%%ebx), %%xmm7 \n\t" // xmm7 = alpha * ( beta30 beta31 ) " \n\t" "subpd %%xmm0, %%xmm4 \n\t" // xmm4 -= xmm0 "subpd %%xmm1, %%xmm5 \n\t" // xmm5 -= xmm1 "subpd %%xmm2, %%xmm6 \n\t" // xmm6 -= xmm2 "subpd %%xmm3, %%xmm7 \n\t" // xmm7 -= xmm3 " \n\t" " \n\t" " \n\t" ".TRSM: \n\t" " \n\t" " \n\t" "movl %3, %%eax \n\t" // load address of a11 "movl %7, %%ecx \n\t" // load address of c11 " \n\t" "movl %8, %%edi \n\t" // load rs_c "movl %9, %%esi \n\t" // load cs_c "sall $3, %%edi \n\t" // rs_c *= sizeof( double ) "sall $3, %%esi \n\t" // cs_c *= sizeof( double ) " \n\t" "addl %%edi, %%ecx \n\t" // c11 += (4-1)*rs_c "addl %%edi, %%ecx \n\t" "addl %%edi, %%ecx \n\t" " \n\t" " \n\t" " \n\t" // iteration 0 " \n\t" "movddup (3+3*4)*8(%%eax), %%xmm3 \n\t" // load xmm3 = (1/alpha33) " \n\t" "mulpd %%xmm3, %%xmm7 \n\t" // xmm7 *= (1/alpha33); " \n\t" "movapd %%xmm7, 3 * 16(%%ebx) \n\t" // store ( beta30 beta31 ) = xmm7 "movlpd %%xmm7, (%%ecx) \n\t" // store ( gamma30 ) = xmm7[0] "movhpd %%xmm7, (%%ecx,%%esi) \n\t" // store ( gamma31 ) = xmm7[1] "subl %%edi, %%ecx \n\t" // c11 -= rs_c " \n\t" " \n\t" " \n\t" " \n\t" // iteration 1 " \n\t" "movddup (2+2*4)*8(%%eax), %%xmm2 \n\t" // load xmm2 = (1/alpha22) "movddup (2+3*4)*8(%%eax), %%xmm3 \n\t" // load xmm3 = alpha23 " \n\t" "mulpd %%xmm7, %%xmm3 \n\t" // xmm3 = alpha23 * ( beta30 beta31 ) "subpd %%xmm3, %%xmm6 \n\t" // xmm6 -= xmm3 "mulpd %%xmm2, %%xmm6 \n\t" // xmm6 *= (1/alpha22); " \n\t" "movapd %%xmm6, 2 * 16(%%ebx) \n\t" // store ( beta20 beta21 ) = xmm6 "movlpd %%xmm6, (%%ecx) \n\t" // store ( gamma20 ) = xmm6[0] "movhpd %%xmm6, (%%ecx,%%esi) \n\t" // store ( gamma21 ) = xmm6[1] "subl %%edi, %%ecx \n\t" // c11 -= rs_c " \n\t" " \n\t" " \n\t" " \n\t" // iteration 2 " \n\t" "movddup (1+1*4)*8(%%eax), %%xmm1 \n\t" // load xmm1 = (1/alpha11) "movddup (1+2*4)*8(%%eax), %%xmm2 \n\t" // load xmm2 = alpha12 "movddup (1+3*4)*8(%%eax), %%xmm3 \n\t" // load xmm3 = alpha13 " \n\t" "mulpd %%xmm6, %%xmm2 \n\t" // xmm2 = alpha12 * ( beta20 beta21 ) "mulpd %%xmm7, %%xmm3 \n\t" // xmm3 = alpha13 * ( beta30 beta31 ) "addpd %%xmm3, %%xmm2 \n\t" // xmm2 += xmm3; "subpd %%xmm2, %%xmm5 \n\t" // xmm5 -= xmm2 "mulpd %%xmm1, %%xmm5 \n\t" // xmm5 *= (1/alpha11); " \n\t" "movapd %%xmm5, 1 * 16(%%ebx) \n\t" // store ( beta10 beta11 ) = xmm5 "movlpd %%xmm5, (%%ecx) \n\t" // store ( gamma10 ) = xmm5[0] "movhpd %%xmm5, (%%ecx,%%esi) \n\t" // store ( gamma11 ) = xmm5[1] "subl %%edi, %%ecx \n\t" // c11 -= rs_c " \n\t" " \n\t" " \n\t" " \n\t" // iteration 3 " \n\t" "movddup (0+0*4)*8(%%eax), %%xmm0 \n\t" // load xmm0 = (1/alpha00) "movddup (0+1*4)*8(%%eax), %%xmm1 \n\t" // load xmm1 = alpha01 "movddup (0+2*4)*8(%%eax), %%xmm2 \n\t" // load xmm2 = alpha02 "movddup (0+3*4)*8(%%eax), %%xmm3 \n\t" // load xmm3 = alpha03 " \n\t" "mulpd %%xmm5, %%xmm1 \n\t" // xmm1 = alpha01 * ( beta10 beta11 ) "mulpd %%xmm6, %%xmm2 \n\t" // xmm2 = alpha02 * ( beta20 beta21 ) "mulpd %%xmm7, %%xmm3 \n\t" // xmm3 = alpha03 * ( beta30 beta31 ) "addpd %%xmm2, %%xmm1 \n\t" // xmm1 += xmm2; "addpd %%xmm3, %%xmm1 \n\t" // xmm1 += xmm3; "subpd %%xmm1, %%xmm4 \n\t" // xmm4 -= xmm1 "mulpd %%xmm0, %%xmm4 \n\t" // xmm4 *= (1/alpha00); " \n\t" "movapd %%xmm4, 0 * 16(%%ebx) \n\t" // store ( beta00 beta01 ) = xmm4 "movlpd %%xmm4, (%%ecx) \n\t" // store ( gamma00 ) = xmm4[0] "movhpd %%xmm4, (%%ecx,%%esi) \n\t" // store ( gamma01 ) = xmm4[1] " \n\t" " \n\t" " \n\t" ".UPDATEBD11: \n\t" " \n\t" " \n\t" "movl %5, %%edx \n\t" " \n\t" "movddup %%xmm4, %%xmm0 \n\t" "movddup %%xmm5, %%xmm1 \n\t" "movddup %%xmm6, %%xmm2 \n\t" "movddup %%xmm7, %%xmm3 \n\t" " \n\t" "unpckhpd %%xmm4, %%xmm4 \n\t" "unpckhpd %%xmm5, %%xmm5 \n\t" "unpckhpd %%xmm6, %%xmm6 \n\t" "unpckhpd %%xmm7, %%xmm7 \n\t" " \n\t" "movapd %%xmm0, 0 * 16(%%edx) \n\t" "movapd %%xmm4, 1 * 16(%%edx) \n\t" "movapd %%xmm1, 2 * 16(%%edx) \n\t" "movapd %%xmm5, 3 * 16(%%edx) \n\t" "movapd %%xmm2, 4 * 16(%%edx) \n\t" "movapd %%xmm6, 5 * 16(%%edx) \n\t" "movapd %%xmm3, 6 * 16(%%edx) \n\t" "movapd %%xmm7, 7 * 16(%%edx) \n\t" " \n\t" " \n\t" : // output operands (none) : // input operands "m" (k_iter), "m" (k_left), "m" (a12), "m" (a11), "m" (bd21), "m" (bd11), "m" (b11), "m" (c11), "m" (rs_c), "m" (cs_c), "m" (alpha) : // register clobber list "eax", "ebx", "ecx", "edx", "esi", "edi", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "memory" ); } void bli_cgemmtrsm_u_opt_d4x2( dim_t k, scomplex* restrict alpha, scomplex* restrict a12, scomplex* restrict a11, scomplex* restrict bd21, scomplex* restrict bd11, scomplex* restrict b11, scomplex* restrict c11, inc_t rs_c, inc_t cs_c, scomplex* restrict a_next, scomplex* restrict b_next ) { bli_check_error_code( BLIS_NOT_YET_IMPLEMENTED ); } void bli_zgemmtrsm_u_opt_d4x2( dim_t k, dcomplex* restrict alpha, dcomplex* restrict a12, dcomplex* restrict a11, dcomplex* restrict bd21, dcomplex* restrict bd11, dcomplex* restrict b11, dcomplex* restrict c11, inc_t rs_c, inc_t cs_c, dcomplex* restrict a_next, dcomplex* restrict b_next ) { bli_check_error_code( BLIS_NOT_YET_IMPLEMENTED ); } blis-0.9.0/kernels/old/x86/3/bli_trsm_l_opt_d4x2.c000066400000000000000000000226171422157504600215140ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bli_strsm_l_opt_d4x2( float* restrict a11, float* restrict b11, float* restrict bd11, float* restrict c11, inc_t rs_c, inc_t cs_c ) { bli_check_error_code( BLIS_NOT_YET_IMPLEMENTED ); } void bli_dtrsm_l_opt_d4x2( double* restrict a11, double* restrict b11, double* restrict bd11, double* restrict c11, inc_t rs_c, inc_t cs_c ) { __asm__ volatile ( " \n\t" "movl %1, %%ebx \n\t" // load address of b11. " \n\t" "movapd 0 * 16(%%ebx), %%xmm4 \n\t" // load xmm4 = ( beta00 beta01 ) "movapd 1 * 16(%%ebx), %%xmm5 \n\t" // load xmm5 = ( beta10 beta11 ) "movapd 2 * 16(%%ebx), %%xmm6 \n\t" // load xmm6 = ( beta20 beta21 ) "movapd 3 * 16(%%ebx), %%xmm7 \n\t" // load xmm7 = ( beta30 beta31 ) " \n\t" " \n\t" "movl %0, %%eax \n\t" // load address of a11 "movl %3, %%ecx \n\t" // load address of c11 " \n\t" "movl %4, %%edi \n\t" // load rs_c "movl %5, %%esi \n\t" // load cs_c "sall $3, %%edi \n\t" // rs_c *= sizeof( double ) "sall $3, %%esi \n\t" // cs_c *= sizeof( double ) " \n\t" " \n\t" " \n\t" " \n\t" // iteration 0 " \n\t" "movddup (0+0*4)*8(%%eax), %%xmm0 \n\t" // load xmm0 = (1/alpha00) " \n\t" "mulpd %%xmm0, %%xmm4 \n\t" // xmm4 *= (1/alpha00); " \n\t" "movapd %%xmm4, 0 * 16(%%ebx) \n\t" // store ( beta00 beta01 ) = xmm4 "movlpd %%xmm4, (%%ecx) \n\t" // store ( gamma00 ) = xmm4[0] "movhpd %%xmm4, (%%ecx,%%esi) \n\t" // store ( gamma01 ) = xmm4[1] "addl %%edi, %%ecx \n\t" // c11 += rs_c " \n\t" " \n\t" " \n\t" " \n\t" // iteration 1 " \n\t" "movddup (1+0*4)*8(%%eax), %%xmm0 \n\t" // load xmm0 = alpha10 "movddup (1+1*4)*8(%%eax), %%xmm1 \n\t" // load xmm1 = (1/alpha11) " \n\t" "mulpd %%xmm4, %%xmm0 \n\t" // xmm0 = alpha10 * ( beta00 beta01 ) "subpd %%xmm0, %%xmm5 \n\t" // xmm5 -= xmm0 "mulpd %%xmm1, %%xmm5 \n\t" // xmm5 *= (1/alpha11); " \n\t" "movapd %%xmm5, 1 * 16(%%ebx) \n\t" // store ( beta10 beta11 ) = xmm5 "movlpd %%xmm5, (%%ecx) \n\t" // store ( gamma10 ) = xmm5[0] "movhpd %%xmm5, (%%ecx,%%esi) \n\t" // store ( gamma11 ) = xmm5[1] "addl %%edi, %%ecx \n\t" // c11 += rs_c " \n\t" " \n\t" " \n\t" " \n\t" // iteration 2 " \n\t" "movddup (2+0*4)*8(%%eax), %%xmm0 \n\t" // load xmm0 = alpha20 "movddup (2+1*4)*8(%%eax), %%xmm1 \n\t" // load xmm1 = alpha21 "movddup (2+2*4)*8(%%eax), %%xmm2 \n\t" // load xmm2 = (1/alpha22) " \n\t" "mulpd %%xmm4, %%xmm0 \n\t" // xmm0 = alpha20 * ( beta00 beta01 ) "mulpd %%xmm5, %%xmm1 \n\t" // xmm1 = alpha21 * ( beta10 beta11 ) "addpd %%xmm1, %%xmm0 \n\t" // xmm0 += xmm1; "subpd %%xmm0, %%xmm6 \n\t" // xmm6 -= xmm0 "mulpd %%xmm2, %%xmm6 \n\t" // xmm6 *= (1/alpha22); " \n\t" "movapd %%xmm6, 2 * 16(%%ebx) \n\t" // store ( beta20 beta21 ) = xmm6 "movlpd %%xmm6, (%%ecx) \n\t" // store ( gamma20 ) = xmm6[0] "movhpd %%xmm6, (%%ecx,%%esi) \n\t" // store ( gamma21 ) = xmm6[1] "addl %%edi, %%ecx \n\t" // c11 += rs_c " \n\t" " \n\t" " \n\t" " \n\t" // iteration 3 " \n\t" "movddup (3+0*4)*8(%%eax), %%xmm0 \n\t" // load xmm0 = alpha30 "movddup (3+1*4)*8(%%eax), %%xmm1 \n\t" // load xmm1 = alpha31 "movddup (3+2*4)*8(%%eax), %%xmm2 \n\t" // load xmm2 = alpha32 "movddup (3+3*4)*8(%%eax), %%xmm3 \n\t" // load xmm3 = (1/alpha33) " \n\t" "mulpd %%xmm4, %%xmm0 \n\t" // xmm0 = alpha30 * ( beta00 beta01 ) "mulpd %%xmm5, %%xmm1 \n\t" // xmm1 = alpha31 * ( beta10 beta11 ) "mulpd %%xmm6, %%xmm2 \n\t" // xmm2 = alpha32 * ( beta20 beta21 ) "addpd %%xmm1, %%xmm0 \n\t" // xmm0 += xmm1 "addpd %%xmm2, %%xmm0 \n\t" // xmm0 += xmm2 "subpd %%xmm0, %%xmm7 \n\t" // xmm7 -= xmm0 "mulpd %%xmm3, %%xmm7 \n\t" // xmm7 *= (1/alpha33); " \n\t" "movapd %%xmm7, 3 * 16(%%ebx) \n\t" // store ( beta30 beta31 ) = xmm7 "movlpd %%xmm7, (%%ecx) \n\t" // store ( gamma30 ) = xmm7[0] "movhpd %%xmm7, (%%ecx,%%esi) \n\t" // store ( gamma31 ) = xmm7[1] " \n\t" " \n\t" " \n\t" ".UPDATEBD11: \n\t" " \n\t" " \n\t" "movl %2, %%edx \n\t" " \n\t" "movddup %%xmm4, %%xmm0 \n\t" "movddup %%xmm5, %%xmm1 \n\t" "movddup %%xmm6, %%xmm2 \n\t" "movddup %%xmm7, %%xmm3 \n\t" " \n\t" "unpckhpd %%xmm4, %%xmm4 \n\t" "unpckhpd %%xmm5, %%xmm5 \n\t" "unpckhpd %%xmm6, %%xmm6 \n\t" "unpckhpd %%xmm7, %%xmm7 \n\t" " \n\t" "movapd %%xmm0, 0 * 16(%%edx) \n\t" "movapd %%xmm4, 1 * 16(%%edx) \n\t" "movapd %%xmm1, 2 * 16(%%edx) \n\t" "movapd %%xmm5, 3 * 16(%%edx) \n\t" "movapd %%xmm2, 4 * 16(%%edx) \n\t" "movapd %%xmm6, 5 * 16(%%edx) \n\t" "movapd %%xmm3, 6 * 16(%%edx) \n\t" "movapd %%xmm7, 7 * 16(%%edx) \n\t" " \n\t" " \n\t" : // output operands (none) : // input operands "m" (a11), "m" (b11), "m" (bd11), "m" (c11), "m" (rs_c), "m" (cs_c) : // register clobber list "eax", "ebx", "ecx", "edx", "esi", "edi", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "memory" ); } void bli_ctrsm_l_opt_d4x2( scomplex* restrict a11, scomplex* restrict b11, scomplex* restrict bd11, scomplex* restrict c11, inc_t rs_c, inc_t cs_c ) { bli_check_error_code( BLIS_NOT_YET_IMPLEMENTED ); } void bli_ztrsm_l_opt_d4x2( dcomplex* restrict a11, dcomplex* restrict b11, dcomplex* restrict bd11, dcomplex* restrict c11, inc_t rs_c, inc_t cs_c ) { bli_check_error_code( BLIS_NOT_YET_IMPLEMENTED ); } blis-0.9.0/kernels/penryn/000077500000000000000000000000001422157504600154355ustar00rootroot00000000000000blis-0.9.0/kernels/penryn/1/000077500000000000000000000000001422157504600155755ustar00rootroot00000000000000blis-0.9.0/kernels/penryn/1/bli_axpyv_penryn_int.c000066400000000000000000000106701422157504600222070ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "pmmintrin.h" #include "blis.h" typedef union { __m128d v; double d[2]; } v2df_t; void bli_daxpyv_penryn_int ( conj_t conjx, dim_t n, double* restrict alpha, double* restrict x, inc_t incx, double* restrict y, inc_t incy, cntx_t* restrict cntx ) { double* restrict alpha_cast = alpha; double* restrict x_cast = x; double* restrict y_cast = y; dim_t i; const dim_t n_elem_per_reg = 2; const dim_t n_iter_unroll = 4; dim_t n_pre; dim_t n_run; dim_t n_left; double* restrict x1; double* restrict y1; double alpha1c, x1c; v2df_t alpha1v; v2df_t x1v, x2v, x3v, x4v; v2df_t y1v, y2v, y3v, y4v; bool use_ref = FALSE; if ( bli_zero_dim1( n ) ) return; n_pre = 0; // If there is anything that would interfere with our use of aligned // vector loads/stores, call the reference implementation. if ( incx != 1 || incy != 1 ) { use_ref = TRUE; } else if ( bli_is_unaligned_to( ( siz_t )x, 16 ) || bli_is_unaligned_to( ( siz_t )y, 16 ) ) { use_ref = TRUE; if ( bli_is_unaligned_to( ( siz_t )x, 16 ) && bli_is_unaligned_to( ( siz_t )y, 16 ) ) { use_ref = FALSE; n_pre = 1; } } // Call the reference implementation if needed. if ( use_ref == TRUE ) { daxpyv_ker_ft f = bli_cntx_get_l1v_ker_dt( BLIS_DOUBLE, BLIS_AXPYV_KER, cntx ); f ( conjx, n, alpha, x, incx, y, incy, cntx ); return; } n_run = ( n - n_pre ) / ( n_elem_per_reg * n_iter_unroll ); n_left = ( n - n_pre ) % ( n_elem_per_reg * n_iter_unroll ); alpha1c = *alpha_cast; x1 = x_cast; y1 = y_cast; if ( n_pre == 1 ) { x1c = *x1; *y1 += alpha1c * x1c; x1 += incx; y1 += incy; } alpha1v.v = _mm_loaddup_pd( ( double* )&alpha1c ); for ( i = 0; i < n_run; ++i ) { y1v.v = _mm_load_pd( ( double* )y1 ); x1v.v = _mm_load_pd( ( double* )x1 ); y1v.v += alpha1v.v * x1v.v; _mm_store_pd( ( double* )(y1 ), y1v.v ); y2v.v = _mm_load_pd( ( double* )(y1 + 2) ); x2v.v = _mm_load_pd( ( double* )(x1 + 2) ); y2v.v += alpha1v.v * x2v.v; _mm_store_pd( ( double* )(y1 + 2), y2v.v ); y3v.v = _mm_load_pd( ( double* )(y1 + 4) ); x3v.v = _mm_load_pd( ( double* )(x1 + 4) ); y3v.v += alpha1v.v * x3v.v; _mm_store_pd( ( double* )(y1 + 4), y3v.v ); y4v.v = _mm_load_pd( ( double* )(y1 + 6) ); x4v.v = _mm_load_pd( ( double* )(x1 + 6) ); y4v.v += alpha1v.v * x4v.v; _mm_store_pd( ( double* )(y1 + 6), y4v.v ); x1 += n_elem_per_reg * n_iter_unroll; y1 += n_elem_per_reg * n_iter_unroll; } if ( n_left > 0 ) { for ( i = 0; i < n_left; ++i ) { x1c = *x1; *y1 += alpha1c * x1c; x1 += incx; y1 += incy; } } } blis-0.9.0/kernels/penryn/1/bli_dotv_penryn_int.c000066400000000000000000000076341422157504600220220ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "pmmintrin.h" #include "blis.h" typedef union { __m128d v; double d[2]; } v2df_t; void bli_ddotv_penryn_int ( conj_t conjx, conj_t conjy, dim_t n, double* restrict x, inc_t incx, double* restrict y, inc_t incy, double* restrict rho, cntx_t* restrict cntx ) { double* restrict x_cast = x; double* restrict y_cast = y; double* restrict rho_cast = rho; dim_t i; dim_t n_pre; dim_t n_run; dim_t n_left; double* restrict x1; double* restrict y1; double rho1; double x1c, y1c; v2df_t rho1v; v2df_t x1v, y1v; bool use_ref = FALSE; // If the vector lengths are zero, set rho to zero and return. if ( bli_zero_dim1( n ) ) { PASTEMAC(d,set0s)( *rho_cast ); return; } n_pre = 0; // If there is anything that would interfere with our use of aligned // vector loads/stores, call the reference implementation. if ( incx != 1 || incy != 1 ) { use_ref = TRUE; } else if ( bli_is_unaligned_to( ( siz_t )x, 16 ) || bli_is_unaligned_to( ( siz_t )y, 16 ) ) { use_ref = TRUE; if ( bli_is_unaligned_to( ( siz_t )x, 16 ) && bli_is_unaligned_to( ( siz_t )y, 16 ) ) { use_ref = FALSE; n_pre = 1; } } // Call the reference implementation if needed. if ( use_ref == TRUE ) { ddotv_ker_ft f = bli_cntx_get_l1v_ker_dt( BLIS_DOUBLE, BLIS_DOTV_KER, cntx ); f ( conjx, conjy, n, x, incx, y, incy, rho, cntx ); return; } n_run = ( n - n_pre ) / 2; n_left = ( n - n_pre ) % 2; x1 = x_cast; y1 = y_cast; PASTEMAC(d,set0s)( rho1 ); if ( n_pre == 1 ) { x1c = *x1; y1c = *y1; rho1 += x1c * y1c; x1 += incx; y1 += incy; } rho1v.v = _mm_setzero_pd(); for ( i = 0; i < n_run; ++i ) { x1v.v = _mm_load_pd( ( double* )x1 ); y1v.v = _mm_load_pd( ( double* )y1 ); rho1v.v += x1v.v * y1v.v; //x1 += 2*incx; //y1 += 2*incy; x1 += 2; y1 += 2; } rho1 += rho1v.d[0] + rho1v.d[1]; if ( n_left > 0 ) { for ( i = 0; i < n_left; ++i ) { x1c = *x1; y1c = *y1; rho1 += x1c * y1c; x1 += incx; y1 += incy; } } PASTEMAC(d,copys)( rho1, *rho_cast ); } blis-0.9.0/kernels/penryn/1f/000077500000000000000000000000001422157504600157435ustar00rootroot00000000000000blis-0.9.0/kernels/penryn/1f/bli_axpy2v_penryn_int.c000066400000000000000000000153301422157504600224350ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "pmmintrin.h" #include "blis.h" typedef union { __m128d v; double d[2]; } v2df_t; void bli_daxpy2v_penryn_int ( conj_t conjx, conj_t conjy, dim_t n, double* restrict alpha, double* restrict beta, double* restrict x, inc_t incx, double* restrict y, inc_t incy, double* restrict z, inc_t incz, cntx_t* restrict cntx ) { double* restrict alpha_cast = alpha; double* restrict beta_cast = beta; double* restrict x_cast = x; double* restrict y_cast = y; double* restrict z_cast = z; dim_t i; const dim_t n_elem_per_reg = 2; const dim_t n_iter_unroll = 4; dim_t n_pre; dim_t n_run; dim_t n_left; double* restrict x1; double* restrict y1; double* restrict z1; double alphac, betac, x1c, y1c; v2df_t alphav, betav; v2df_t x1v, y1v, z1v; v2df_t x2v, y2v, z2v; bool use_ref = FALSE; if ( bli_zero_dim1( n ) ) return; n_pre = 0; // If there is anything that would interfere with our use of aligned // vector loads/stores, call the reference implementation. if ( incx != 1 || incy != 1 || incz != 1 ) { use_ref = TRUE; } else if ( bli_is_unaligned_to( ( siz_t )x, 16 ) || bli_is_unaligned_to( ( siz_t )y, 16 ) || bli_is_unaligned_to( ( siz_t )z, 16 ) ) { use_ref = TRUE; if ( bli_is_unaligned_to( ( siz_t )x, 16 ) && bli_is_unaligned_to( ( siz_t )y, 16 ) && bli_is_unaligned_to( ( siz_t )z, 16 ) ) { use_ref = FALSE; n_pre = 1; } } // Call the reference implementation if needed. if ( use_ref == TRUE ) { daxpy2v_ker_ft f = bli_cntx_get_l1f_ker_dt( BLIS_DOUBLE, BLIS_AXPY2V_KER, cntx ); f ( conjx, conjy, n, alpha, beta, x, incx, y, incy, z, incz, cntx ); return; } n_run = ( n - n_pre ) / ( n_elem_per_reg * n_iter_unroll ); n_left = ( n - n_pre ) % ( n_elem_per_reg * n_iter_unroll ); alphac = *alpha_cast; betac = *beta_cast; x1 = x_cast; y1 = y_cast; z1 = z_cast; if ( n_pre == 1 ) { x1c = *x1; y1c = *y1; *z1 += alphac * x1c + betac * y1c; x1 += incx; y1 += incy; z1 += incz; } alphav.v = _mm_loaddup_pd( ( double* )alpha_cast ); betav.v = _mm_loaddup_pd( ( double* )beta_cast ); for ( i = 0; i < n_run; ++i ) { /* z1v.v = _mm_load_pd( ( double* )z1 + 0*n_elem_per_reg ); x1v.v = _mm_load_pd( ( double* )x1 + 0*n_elem_per_reg ); y1v.v = _mm_load_pd( ( double* )y1 + 0*n_elem_per_reg ); z1v.v += alphav.v * x1v.v; z1v.v += betav.v * y1v.v; _mm_store_pd( ( double* )(z1 + 0*n_elem_per_reg ), z1v.v ); z1v.v = _mm_load_pd( ( double* )z1 + 1*n_elem_per_reg ); x1v.v = _mm_load_pd( ( double* )x1 + 1*n_elem_per_reg ); y1v.v = _mm_load_pd( ( double* )y1 + 1*n_elem_per_reg ); z1v.v += alphav.v * x1v.v; z1v.v += betav.v * y1v.v; _mm_store_pd( ( double* )(z1 + 1*n_elem_per_reg ), z1v.v ); */ /* z1v.v = _mm_load_pd( ( double* )z1 + 0*n_elem_per_reg ); x1v.v = _mm_load_pd( ( double* )x1 + 0*n_elem_per_reg ); y1v.v = _mm_load_pd( ( double* )y1 + 0*n_elem_per_reg ); z2v.v = _mm_load_pd( ( double* )z1 + 1*n_elem_per_reg ); x2v.v = _mm_load_pd( ( double* )x1 + 1*n_elem_per_reg ); y2v.v = _mm_load_pd( ( double* )y1 + 1*n_elem_per_reg ); z1v.v += alphav.v * x1v.v; z1v.v += betav.v * y1v.v; _mm_store_pd( ( double* )(z1 + 0*n_elem_per_reg ), z1v.v ); z2v.v += alphav.v * x2v.v; z2v.v += betav.v * y2v.v; _mm_store_pd( ( double* )(z1 + 1*n_elem_per_reg ), z2v.v ); */ z1v.v = _mm_load_pd( ( double* )z1 + 0*n_elem_per_reg ); x1v.v = _mm_load_pd( ( double* )x1 + 0*n_elem_per_reg ); y1v.v = _mm_load_pd( ( double* )y1 + 0*n_elem_per_reg ); z2v.v = _mm_load_pd( ( double* )z1 + 1*n_elem_per_reg ); x2v.v = _mm_load_pd( ( double* )x1 + 1*n_elem_per_reg ); y2v.v = _mm_load_pd( ( double* )y1 + 1*n_elem_per_reg ); z1v.v += alphav.v * x1v.v; z1v.v += betav.v * y1v.v; _mm_store_pd( ( double* )(z1 + 0*n_elem_per_reg ), z1v.v ); z1v.v = _mm_load_pd( ( double* )z1 + 2*n_elem_per_reg ); x1v.v = _mm_load_pd( ( double* )x1 + 2*n_elem_per_reg ); y1v.v = _mm_load_pd( ( double* )y1 + 2*n_elem_per_reg ); z2v.v += alphav.v * x2v.v; z2v.v += betav.v * y2v.v; _mm_store_pd( ( double* )(z1 + 1*n_elem_per_reg ), z2v.v ); z2v.v = _mm_load_pd( ( double* )z1 + 3*n_elem_per_reg ); x2v.v = _mm_load_pd( ( double* )x1 + 3*n_elem_per_reg ); y2v.v = _mm_load_pd( ( double* )y1 + 3*n_elem_per_reg ); z1v.v += alphav.v * x1v.v; z1v.v += betav.v * y1v.v; _mm_store_pd( ( double* )(z1 + 2*n_elem_per_reg ), z1v.v ); z2v.v += alphav.v * x2v.v; z2v.v += betav.v * y2v.v; _mm_store_pd( ( double* )(z1 + 3*n_elem_per_reg ), z2v.v ); x1 += n_elem_per_reg * n_iter_unroll; y1 += n_elem_per_reg * n_iter_unroll; z1 += n_elem_per_reg * n_iter_unroll; } if ( n_left > 0 ) { for ( i = 0; i < n_left; ++i ) { x1c = *x1; y1c = *y1; *z1 += alphac * x1c + betac * y1c; x1 += incx; y1 += incy; z1 += incz; } } } blis-0.9.0/kernels/penryn/1f/bli_axpyf_penryn_int.c000066400000000000000000000142611422157504600223350ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "pmmintrin.h" #include "blis.h" typedef union { __m128d v; double d[2]; } v2df_t; void bli_daxpyf_penryn_int ( conj_t conja, conj_t conjx, dim_t m, dim_t b_n, double* restrict alpha, double* restrict a, inc_t inca, inc_t lda, double* restrict x, inc_t incx, double* restrict y, inc_t incy, cntx_t* restrict cntx ) { double* restrict alpha_cast = alpha; double* restrict a_cast = a; double* restrict x_cast = x; double* restrict y_cast = y; dim_t i; const dim_t n_elem_per_reg = 2; const dim_t n_iter_unroll = 2; dim_t m_pre; dim_t m_run; dim_t m_left; double* restrict a0; double* restrict a1; double* restrict a2; double* restrict a3; double* restrict y0; double a0c, a1c, a2c, a3c; double chi0, chi1, chi2, chi3; v2df_t a00v, a01v, a02v, a03v, y0v; v2df_t a10v, a11v, a12v, a13v, y1v; v2df_t chi0v, chi1v, chi2v, chi3v; bool use_ref = FALSE; if ( bli_zero_dim2( m, b_n ) ) return; m_pre = 0; // If there is anything that would interfere with our use of aligned // vector loads/stores, call the reference implementation. if ( b_n < bli_cntx_get_blksz_def_dt( BLIS_DOUBLE, BLIS_AF, cntx ) ) { use_ref = TRUE; } else if ( inca != 1 || incx != 1 || incy != 1 || bli_is_unaligned_to( ( siz_t )(lda*sizeof(double)), 16 ) ) { use_ref = TRUE; } else if ( bli_is_unaligned_to( ( siz_t )a, 16 ) || bli_is_unaligned_to( ( siz_t )y, 16 ) ) { use_ref = TRUE; if ( bli_is_unaligned_to( ( siz_t )a, 16 ) && bli_is_unaligned_to( ( siz_t )y, 16 ) ) { use_ref = FALSE; m_pre = 1; } } // Call the reference implementation if needed. if ( use_ref == TRUE ) { daxpyf_ker_ft f = bli_cntx_get_l1f_ker_dt( BLIS_DOUBLE, BLIS_AXPYF_KER, cntx ); f ( conja, conjx, m, b_n, alpha_cast, a_cast, inca, lda, x_cast, incx, y_cast, incy, cntx ); return; } m_run = ( m - m_pre ) / ( n_elem_per_reg * n_iter_unroll ); m_left = ( m - m_pre ) % ( n_elem_per_reg * n_iter_unroll ); a0 = a_cast + 0*lda; a1 = a_cast + 1*lda; a2 = a_cast + 2*lda; a3 = a_cast + 3*lda; y0 = y_cast; chi0 = *(x_cast + 0*incx); chi1 = *(x_cast + 1*incx); chi2 = *(x_cast + 2*incx); chi3 = *(x_cast + 3*incx); PASTEMAC2(d,d,scals)( *alpha_cast, chi0 ); PASTEMAC2(d,d,scals)( *alpha_cast, chi1 ); PASTEMAC2(d,d,scals)( *alpha_cast, chi2 ); PASTEMAC2(d,d,scals)( *alpha_cast, chi3 ); if ( m_pre == 1 ) { a0c = *a0; a1c = *a1; a2c = *a2; a3c = *a3; *y0 += chi0 * a0c + chi1 * a1c + chi2 * a2c + chi3 * a3c; a0 += inca; a1 += inca; a2 += inca; a3 += inca; y0 += incy; } chi0v.v = _mm_loaddup_pd( ( double* )&chi0 ); chi1v.v = _mm_loaddup_pd( ( double* )&chi1 ); chi2v.v = _mm_loaddup_pd( ( double* )&chi2 ); chi3v.v = _mm_loaddup_pd( ( double* )&chi3 ); for ( i = 0; i < m_run; ++i ) { y0v.v = _mm_load_pd( ( double* )(y0 + 0*n_elem_per_reg) ); a00v.v = _mm_load_pd( ( double* )(a0 + 0*n_elem_per_reg) ); a01v.v = _mm_load_pd( ( double* )(a1 + 0*n_elem_per_reg) ); y0v.v += chi0v.v * a00v.v; y0v.v += chi1v.v * a01v.v; a02v.v = _mm_load_pd( ( double* )(a2 + 0*n_elem_per_reg) ); a03v.v = _mm_load_pd( ( double* )(a3 + 0*n_elem_per_reg) ); y0v.v += chi2v.v * a02v.v; y0v.v += chi3v.v * a03v.v; _mm_store_pd( ( double* )(y0 + 0*n_elem_per_reg), y0v.v ); y1v.v = _mm_load_pd( ( double* )(y0 + 1*n_elem_per_reg) ); a10v.v = _mm_load_pd( ( double* )(a0 + 1*n_elem_per_reg) ); a11v.v = _mm_load_pd( ( double* )(a1 + 1*n_elem_per_reg) ); y1v.v += chi0v.v * a10v.v; y1v.v += chi1v.v * a11v.v; a12v.v = _mm_load_pd( ( double* )(a2 + 1*n_elem_per_reg) ); a13v.v = _mm_load_pd( ( double* )(a3 + 1*n_elem_per_reg) ); y1v.v += chi2v.v * a12v.v; y1v.v += chi3v.v * a13v.v; _mm_store_pd( ( double* )(y0 + 1*n_elem_per_reg), y1v.v ); a0 += n_elem_per_reg * n_iter_unroll; a1 += n_elem_per_reg * n_iter_unroll; a2 += n_elem_per_reg * n_iter_unroll; a3 += n_elem_per_reg * n_iter_unroll; y0 += n_elem_per_reg * n_iter_unroll; } if ( m_left > 0 ) { for ( i = 0; i < m_left; ++i ) { a0c = *a0; a1c = *a1; a2c = *a2; a3c = *a3; *y0 += chi0 * a0c + chi1 * a1c + chi2 * a2c + chi3 * a3c; a0 += inca; a1 += inca; a2 += inca; a3 += inca; y0 += incy; } } } blis-0.9.0/kernels/penryn/1f/bli_dotaxpyv_penryn_int.c000066400000000000000000000116111422157504600230600ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "pmmintrin.h" #include "blis.h" typedef union { __m128d v; double d[2]; } v2df_t; void bli_ddotaxpyv_penryn_int ( conj_t conjxt, conj_t conjx, conj_t conjy, dim_t n, double* restrict alpha, double* restrict x, inc_t incx, double* restrict y, inc_t incy, double* restrict rho, double* restrict z, inc_t incz, cntx_t* restrict cntx ) { double* restrict alpha_cast = alpha; double* restrict x_cast = x; double* restrict y_cast = y; double* restrict rho_cast = rho; double* restrict z_cast = z; dim_t n_pre; dim_t n_run; dim_t n_left; double* restrict chi1; double* restrict psi1; double* restrict zeta1; double alpha1c, chi1c, psi1c, rho1c; dim_t i; //inc_t stepx, stepy, stepz; v2df_t alphav, rhov; v2df_t x1v, y1v, z1v; bool use_ref = FALSE; // If the vector lengths are zero, set rho to zero and return. if ( bli_zero_dim1( n ) ) { PASTEMAC(d,set0s)( *rho_cast ); return; } n_pre = 0; // If there is anything that would interfere with our use of aligned // vector loads/stores, call the reference implementation. if ( incx != 1 || incy != 1 || incz != 1 ) { use_ref = TRUE; } else if ( bli_is_unaligned_to( ( siz_t )x, 16 ) || bli_is_unaligned_to( ( siz_t )y, 16 ) || bli_is_unaligned_to( ( siz_t )z, 16 ) ) { use_ref = TRUE; if ( bli_is_unaligned_to( ( siz_t )x, 16 ) && bli_is_unaligned_to( ( siz_t )y, 16 ) && bli_is_unaligned_to( ( siz_t )z, 16 ) ) { use_ref = FALSE; n_pre = 1; } } // Call the reference implementation if needed. if ( use_ref == TRUE ) { ddotaxpyv_ker_ft f = bli_cntx_get_l1f_ker_dt( BLIS_DOUBLE, BLIS_DOTAXPYV_KER, cntx ); f ( conjxt, conjx, conjy, n, alpha, x, incx, y, incy, rho, z, incz, cntx ); return; } n_run = ( n - n_pre ) / ( 2 * 1 ); n_left = ( n - n_pre ) % ( 2 * 1 ); //stepx = 2 * incx; //stepy = 2 * incy; //stepz = 2 * incz; PASTEMAC(d,set0s)( rho1c ); alpha1c = *alpha_cast; chi1 = x_cast; psi1 = y_cast; zeta1 = z_cast; if ( n_pre == 1 ) { chi1c = *chi1; psi1c = *psi1; rho1c += chi1c * psi1c; *zeta1 += alpha1c * chi1c; chi1 += incx; psi1 += incy; zeta1 += incz; } rhov.v = _mm_setzero_pd(); alphav.v = _mm_loaddup_pd( ( double* )alpha_cast ); for ( i = 0; i < n_run; ++i ) { x1v.v = _mm_load_pd( ( double* )chi1 ); y1v.v = _mm_load_pd( ( double* )psi1 ); z1v.v = _mm_load_pd( ( double* )zeta1 ); //y1v.v = _mm_setr_pd( *psi1, *(psi1 + incy) ); //z1v.v = _mm_setr_pd( *zeta1, *(zeta1 + incz) ); rhov.v += x1v.v * y1v.v; z1v.v += alphav.v * x1v.v; _mm_store_pd( ( double* )zeta1, z1v.v ); //chi1 += stepx; //psi1 += stepy; //zeta1 += stepz; chi1 += 2; psi1 += 2; zeta1 += 2; } if ( n_left > 0 ) { for ( i = 0; i < n_left; ++i ) { chi1c = *chi1; psi1c = *psi1; rho1c += chi1c * psi1c; *zeta1 += alpha1c * chi1c; chi1 += incx; psi1 += incy; zeta1 += incz; } } rho1c += rhov.d[0] + rhov.d[1]; *rho_cast = rho1c; } blis-0.9.0/kernels/penryn/1f/bli_dotxaxpyf_penryn_int.c000066400000000000000000000225101422157504600232300ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "pmmintrin.h" #include "blis.h" typedef union { __m128d v; double d[2]; } v2df_t; void bli_ddotxaxpyf_penryn_int ( conj_t conjat, conj_t conja, conj_t conjw, conj_t conjx, dim_t m, dim_t b_n, double* restrict alpha, double* restrict a, inc_t inca, inc_t lda, double* restrict w, inc_t incw, double* restrict x, inc_t incx, double* restrict beta, double* restrict y, inc_t incy, double* restrict z, inc_t incz, cntx_t* restrict cntx ) { double* restrict alpha_cast = alpha; double* restrict beta_cast = beta; double* restrict a_cast = a; double* restrict w_cast = w; double* restrict x_cast = x; double* restrict y_cast = y; double* restrict z_cast = z; dim_t i; const dim_t n_elem_per_reg = 2; const dim_t n_iter_unroll = 2; dim_t m_pre; dim_t m_run; dim_t m_left; double* restrict a0; double* restrict a1; double* restrict a2; double* restrict a3; double* restrict w1; double* restrict z1; double rho0, rho1, rho2, rho3; double chi0, chi1, chi2, chi3; double a0c, a1c, a2c, a3c, w1c, z1c; v2df_t rho0v, rho1v, rho2v, rho3v; v2df_t chi0v, chi1v, chi2v, chi3v; //v2df_t a0v, a1v, a2v, a3v, w1v, z1v; v2df_t a00v, a01v, a02v, a03v; v2df_t a10v, a11v, a12v, a13v; v2df_t w1v, z1v; v2df_t w2v, z2v; v2df_t psi0v, psi1v, betav, alphav; bool use_ref = FALSE; if ( bli_zero_dim1( b_n ) ) return; // If the vector lengths are zero, scale y by beta and return. if ( bli_zero_dim1( m ) ) { dscalv_ker_ft f = bli_cntx_get_l1v_ker_dt( BLIS_DOUBLE, BLIS_SCALV_KER, cntx ); f ( BLIS_NO_CONJUGATE, b_n, beta, y, incy, cntx ); return; } m_pre = 0; // If there is anything that would interfere with our use of aligned // vector loads/stores, call the reference implementation. if ( b_n < bli_cntx_get_blksz_def_dt( BLIS_DOUBLE, BLIS_XF, cntx ) ) { use_ref = TRUE; } else if ( inca != 1 || incw != 1 || incx != 1 || incy != 1 || incz != 1 || bli_is_unaligned_to( ( siz_t )(lda*sizeof(double)), 16 ) ) { use_ref = TRUE; } else if ( bli_is_unaligned_to( ( siz_t )a, 16 ) || bli_is_unaligned_to( ( siz_t )w, 16 ) || bli_is_unaligned_to( ( siz_t )z, 16 ) || bli_is_unaligned_to( ( siz_t )y, 16 ) ) { use_ref = TRUE; if ( bli_is_unaligned_to( ( siz_t )a, 16 ) && bli_is_unaligned_to( ( siz_t )w, 16 ) && bli_is_unaligned_to( ( siz_t )z, 16 ) && bli_is_aligned_to( ( siz_t )y, 16 ) ) // Note: y is not affected by a, w, and z being unaligned. { use_ref = FALSE; m_pre = 1; } } if ( use_ref == TRUE ) { ddotxaxpyf_ker_ft f = bli_cntx_get_l1f_ker_dt( BLIS_DOUBLE, BLIS_DOTXAXPYF_KER, cntx ); f ( conjat, conja, conjw, conjx, m, b_n, alpha_cast, a_cast, inca, lda, w_cast, incw, x_cast, incx, beta_cast, y_cast, incy, z_cast, incz, cntx ); return; } m_run = ( m - m_pre ) / ( n_elem_per_reg * n_iter_unroll ); m_left = ( m - m_pre ) % ( n_elem_per_reg * n_iter_unroll ); a0 = a_cast + 0*lda; a1 = a_cast + 1*lda; a2 = a_cast + 2*lda; a3 = a_cast + 3*lda; w1 = w_cast; z1 = z_cast; chi0 = *(x_cast + 0*incx); chi1 = *(x_cast + 1*incx); chi2 = *(x_cast + 2*incx); chi3 = *(x_cast + 3*incx); PASTEMAC2(d,d,scals)( *alpha_cast, chi0 ); PASTEMAC2(d,d,scals)( *alpha_cast, chi1 ); PASTEMAC2(d,d,scals)( *alpha_cast, chi2 ); PASTEMAC2(d,d,scals)( *alpha_cast, chi3 ); PASTEMAC(d,set0s)( rho0 ); PASTEMAC(d,set0s)( rho1 ); PASTEMAC(d,set0s)( rho2 ); PASTEMAC(d,set0s)( rho3 ); if ( m_pre == 1 ) { a0c = *a0; a1c = *a1; a2c = *a2; a3c = *a3; w1c = *w1; z1c = *z1; rho0 += a0c * w1c; rho1 += a1c * w1c; rho2 += a2c * w1c; rho3 += a3c * w1c; z1c += chi0 * a0c + chi1 * a1c + chi2 * a2c + chi3 * a3c; *z1 = z1c; a0 += inca; a1 += inca; a2 += inca; a3 += inca; w1 += incw; z1 += incz; } rho0v.v = _mm_setzero_pd(); rho1v.v = _mm_setzero_pd(); rho2v.v = _mm_setzero_pd(); rho3v.v = _mm_setzero_pd(); chi0v.v = _mm_loaddup_pd( ( double* )&chi0 ); chi1v.v = _mm_loaddup_pd( ( double* )&chi1 ); chi2v.v = _mm_loaddup_pd( ( double* )&chi2 ); chi3v.v = _mm_loaddup_pd( ( double* )&chi3 ); /* y = beta * y + alpha * A^T w; */ \ /* z = z + alpha * A x; */ \ //for ( i = 0; i < m_run; ++i ) for ( i = m_run; i != 0; --i ) { z1v.v = _mm_load_pd( ( double* )(z1 + 0*n_elem_per_reg) ); w1v.v = _mm_load_pd( ( double* )(w1 + 0*n_elem_per_reg) ); a00v.v = _mm_load_pd( ( double* )(a0 + 0*n_elem_per_reg) ); //a01v.v = _mm_load_pd( ( double* )(a1 + 0*n_elem_per_reg) ); a01v.v = _mm_load_pd( ( double* )(a0 + 1*lda + 0*n_elem_per_reg) ); rho0v.v += a00v.v * w1v.v; rho1v.v += a01v.v * w1v.v; z1v.v += chi0v.v * a00v.v; z1v.v += chi1v.v * a01v.v; a02v.v = _mm_load_pd( ( double* )(a2 + 0*n_elem_per_reg) ); //a03v.v = _mm_load_pd( ( double* )(a3 + 0*n_elem_per_reg) ); a03v.v = _mm_load_pd( ( double* )(a2 + 1*lda + 0*n_elem_per_reg) ); rho2v.v += a02v.v * w1v.v; rho3v.v += a03v.v * w1v.v; z1v.v += chi2v.v * a02v.v; z1v.v += chi3v.v * a03v.v; _mm_store_pd( ( double* )(z1 + 0*n_elem_per_reg), z1v.v ); z2v.v = _mm_load_pd( ( double* )(z1 + 1*n_elem_per_reg) ); w2v.v = _mm_load_pd( ( double* )(w1 + 1*n_elem_per_reg) ); a10v.v = _mm_load_pd( ( double* )(a0 + 1*n_elem_per_reg) ); //a11v.v = _mm_load_pd( ( double* )(a1 + 1*n_elem_per_reg) ); a11v.v = _mm_load_pd( ( double* )(a0 + 1*lda + 1*n_elem_per_reg) ); rho0v.v += a10v.v * w2v.v; rho1v.v += a11v.v * w2v.v; z2v.v += chi0v.v * a10v.v; z2v.v += chi1v.v * a11v.v; a12v.v = _mm_load_pd( ( double* )(a2 + 1*n_elem_per_reg) ); //a13v.v = _mm_load_pd( ( double* )(a3 + 1*n_elem_per_reg) ); a13v.v = _mm_load_pd( ( double* )(a2 + 1*lda + 1*n_elem_per_reg) ); rho2v.v += a12v.v * w2v.v; rho3v.v += a13v.v * w2v.v; z2v.v += chi2v.v * a12v.v; z2v.v += chi3v.v * a13v.v; _mm_store_pd( ( double* )(z1 + 1*n_elem_per_reg), z2v.v ); a0 += n_elem_per_reg * n_iter_unroll; //a1 += n_elem_per_reg * n_iter_unroll; a2 += n_elem_per_reg * n_iter_unroll; //a3 += n_elem_per_reg * n_iter_unroll; w1 += n_elem_per_reg * n_iter_unroll; z1 += n_elem_per_reg * n_iter_unroll; } rho0 += rho0v.d[0] + rho0v.d[1]; rho1 += rho1v.d[0] + rho1v.d[1]; rho2 += rho2v.d[0] + rho2v.d[1]; rho3 += rho3v.d[0] + rho3v.d[1]; if ( m_left > 0 ) { for ( i = 0; i < m_left; ++i ) { a0c = *a0; //a1c = *a1; a1c = *(a0 + lda); a2c = *a2; //a3c = *a3; a3c = *(a2 + lda); w1c = *w1; z1c = *z1; rho0 += a0c * w1c; rho1 += a1c * w1c; rho2 += a2c * w1c; rho3 += a3c * w1c; z1c += chi0 * a0c + chi1 * a1c + chi2 * a2c + chi3 * a3c; *z1 = z1c; a0 += inca; //a1 += inca; a2 += inca; //a3 += inca; w1 += incw; z1 += incz; } } rho0v.d[0] = rho0; rho0v.d[1] = rho1; rho1v.d[0] = rho2; rho1v.d[1] = rho3; betav.v = _mm_loaddup_pd( ( double* ) beta_cast ); alphav.v = _mm_loaddup_pd( ( double* ) alpha_cast ); psi0v.v = _mm_load_pd( ( double* )(y_cast + 0*n_elem_per_reg ) ); psi1v.v = _mm_load_pd( ( double* )(y_cast + 1*n_elem_per_reg ) ); psi0v.v = betav.v * psi0v.v + alphav.v * rho0v.v; psi1v.v = betav.v * psi1v.v + alphav.v * rho1v.v; _mm_store_pd( ( double* )(y_cast + 0*n_elem_per_reg ), psi0v.v ); _mm_store_pd( ( double* )(y_cast + 1*n_elem_per_reg ), psi1v.v ); } blis-0.9.0/kernels/penryn/1f/bli_dotxf_penryn_int.c000066400000000000000000000203251422157504600223300ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "pmmintrin.h" #include "blis.h" typedef union { __m128d v; double d[2]; } v2df_t; void bli_ddotxf_penryn_int ( conj_t conjat, conj_t conjx, dim_t m, dim_t b_n, double* restrict alpha, double* restrict a, inc_t inca, inc_t lda, double* restrict x, inc_t incx, double* restrict beta, double* restrict y, inc_t incy, cntx_t* restrict cntx ) { double* restrict alpha_cast = alpha; double* restrict beta_cast = beta; double* restrict a_cast = a; double* restrict x_cast = x; double* restrict y_cast = y; dim_t i; const dim_t n_elem_per_reg = 2; const dim_t n_iter_unroll = 4; dim_t m_pre; dim_t m_run; dim_t m_left; double* restrict x0; double* restrict x1; double* restrict x2; double* restrict x3; double* restrict y0; double rho0, rho1, rho2, rho3; double x0c, x1c, x2c, x3c, y0c; v2df_t rho0v, rho1v, rho2v, rho3v; v2df_t x0v, x1v, x2v, x3v, y0v, betav, alphav; bool use_ref = FALSE; if ( bli_zero_dim1( b_n ) ) return; // If the vector lengths are zero, scale r by beta and return. if ( bli_zero_dim1( m ) ) { dscalv_ker_ft f = bli_cntx_get_l1v_ker_dt( BLIS_DOUBLE, BLIS_SCALV_KER, cntx ); f ( BLIS_NO_CONJUGATE, b_n, beta_cast, y_cast, incy, cntx ); return; } m_pre = 0; // If there is anything that would interfere with our use of aligned // vector loads/stores, call the reference implementation. if ( b_n < bli_cntx_get_blksz_def_dt( BLIS_DOUBLE, BLIS_DF, cntx ) ) { use_ref = TRUE; } else if ( inca != 1 || incx != 1 || incy != 1 || bli_is_unaligned_to( ( siz_t )(lda*sizeof(double)), 16 ) ) { use_ref = TRUE; } else if ( bli_is_unaligned_to( ( siz_t )a, 16 ) || bli_is_unaligned_to( ( siz_t )x, 16 ) || bli_is_unaligned_to( ( siz_t )y, 16 ) ) { use_ref = TRUE; if ( bli_is_unaligned_to( ( siz_t )a, 16 ) && bli_is_unaligned_to( ( siz_t )x, 16 ) && bli_is_aligned_to( ( siz_t )y, 16 ) ) // Note: r is not affected by x and y being unaligned. { use_ref = FALSE; m_pre = 1; } } // Call the reference implementation if needed. if ( use_ref == TRUE ) { ddotxf_ker_ft f = bli_cntx_get_l1f_ker_dt( BLIS_DOUBLE, BLIS_DOTXF_KER, cntx ); f ( conjat, conjx, m, b_n, alpha_cast, a_cast, inca, lda, x_cast, incx, beta_cast, y_cast, incy, cntx ); return; } m_run = ( m - m_pre ) / ( n_elem_per_reg * n_iter_unroll ); m_left = ( m - m_pre ) % ( n_elem_per_reg * n_iter_unroll ); x0 = a_cast; x1 = a_cast + lda; x2 = a_cast + 2*lda; x3 = a_cast + 3*lda; y0 = x_cast; PASTEMAC(d,set0s)( rho0 ); PASTEMAC(d,set0s)( rho1 ); PASTEMAC(d,set0s)( rho2 ); PASTEMAC(d,set0s)( rho3 ); if ( m_pre == 1 ) { x0c = *x0; x1c = *x1; x2c = *x2; x3c = *x3; y0c = *y0; rho0 += x0c * y0c; rho1 += x1c * y0c; rho2 += x2c * y0c; rho3 += x3c * y0c; x0 += inca; x1 += inca; x2 += inca; x3 += inca; y0 += incx; } rho0v.v = _mm_setzero_pd(); rho1v.v = _mm_setzero_pd(); rho2v.v = _mm_setzero_pd(); rho3v.v = _mm_setzero_pd(); for ( i = 0; i < m_run; ++i ) { x0v.v = _mm_load_pd( ( double* )(x0 + 0*n_elem_per_reg) ); x1v.v = _mm_load_pd( ( double* )(x1 + 0*n_elem_per_reg) ); x2v.v = _mm_load_pd( ( double* )(x2 + 0*n_elem_per_reg) ); x3v.v = _mm_load_pd( ( double* )(x3 + 0*n_elem_per_reg) ); y0v.v = _mm_load_pd( ( double* )(y0 + 0*n_elem_per_reg) ); rho0v.v += x0v.v * y0v.v; rho1v.v += x1v.v * y0v.v; rho2v.v += x2v.v * y0v.v; rho3v.v += x3v.v * y0v.v; x0v.v = _mm_load_pd( ( double* )(x0 + 1*n_elem_per_reg) ); x1v.v = _mm_load_pd( ( double* )(x1 + 1*n_elem_per_reg) ); x2v.v = _mm_load_pd( ( double* )(x2 + 1*n_elem_per_reg) ); x3v.v = _mm_load_pd( ( double* )(x3 + 1*n_elem_per_reg) ); y0v.v = _mm_load_pd( ( double* )(y0 + 1*n_elem_per_reg) ); rho0v.v += x0v.v * y0v.v; rho1v.v += x1v.v * y0v.v; rho2v.v += x2v.v * y0v.v; rho3v.v += x3v.v * y0v.v; x0v.v = _mm_load_pd( ( double* )(x0 + 2*n_elem_per_reg) ); x1v.v = _mm_load_pd( ( double* )(x1 + 2*n_elem_per_reg) ); x2v.v = _mm_load_pd( ( double* )(x2 + 2*n_elem_per_reg) ); x3v.v = _mm_load_pd( ( double* )(x3 + 2*n_elem_per_reg) ); y0v.v = _mm_load_pd( ( double* )(y0 + 2*n_elem_per_reg) ); rho0v.v += x0v.v * y0v.v; rho1v.v += x1v.v * y0v.v; rho2v.v += x2v.v * y0v.v; rho3v.v += x3v.v * y0v.v; x0v.v = _mm_load_pd( ( double* )(x0 + 3*n_elem_per_reg) ); x1v.v = _mm_load_pd( ( double* )(x1 + 3*n_elem_per_reg) ); x2v.v = _mm_load_pd( ( double* )(x2 + 3*n_elem_per_reg) ); x3v.v = _mm_load_pd( ( double* )(x3 + 3*n_elem_per_reg) ); y0v.v = _mm_load_pd( ( double* )(y0 + 3*n_elem_per_reg) ); rho0v.v += x0v.v * y0v.v; rho1v.v += x1v.v * y0v.v; rho2v.v += x2v.v * y0v.v; rho3v.v += x3v.v * y0v.v; x0 += n_elem_per_reg * n_iter_unroll; x1 += n_elem_per_reg * n_iter_unroll; x2 += n_elem_per_reg * n_iter_unroll; x3 += n_elem_per_reg * n_iter_unroll; y0 += n_elem_per_reg * n_iter_unroll; } rho0 += rho0v.d[0] + rho0v.d[1]; rho1 += rho1v.d[0] + rho1v.d[1]; rho2 += rho2v.d[0] + rho2v.d[1]; rho3 += rho3v.d[0] + rho3v.d[1]; if ( m_left > 0 ) { for ( i = 0; i < m_left; ++i ) { x0c = *x0; x1c = *x1; x2c = *x2; x3c = *x3; y0c = *y0; rho0 += x0c * y0c; rho1 += x1c * y0c; rho2 += x2c * y0c; rho3 += x3c * y0c; x0 += inca; x1 += inca; x2 += inca; x3 += inca; y0 += incx; } } /* PASTEMAC2(d,d,scals)( *beta_cast, *(y_cast ) ); \ PASTEMAC2(d,d,scals)( *beta_cast, *(y_cast+1) ); \ PASTEMAC2(d,d,scals)( *beta_cast, *(y_cast+2) ); \ PASTEMAC2(d,d,scals)( *beta_cast, *(y_cast+3) ); \ PASTEMAC3(d,d,d,axpys)( *alpha_cast, rho1, *(y_cast ) ); \ PASTEMAC3(d,d,d,axpys)( *alpha_cast, rho2, *(y_cast+1) ); \ PASTEMAC3(d,d,d,axpys)( *alpha_cast, rho3, *(y_cast+2) ); \ PASTEMAC3(d,d,d,axpys)( *alpha_cast, rho4, *(y_cast+3) ); \ */ rho1v.d[0] = rho0; rho1v.d[1] = rho1; rho3v.d[0] = rho2; rho3v.d[1] = rho3; betav.v = _mm_loaddup_pd( ( double* ) beta_cast ); alphav.v = _mm_loaddup_pd( ( double* ) alpha_cast ); rho0v.v = _mm_load_pd( ( double* )(y_cast + 0*n_elem_per_reg) ); rho2v.v = _mm_load_pd( ( double* )(y_cast + 1*n_elem_per_reg) ); rho0v.v *= betav.v; rho2v.v *= betav.v; rho0v.v += alphav.v * rho1v.v; rho2v.v += alphav.v * rho3v.v; _mm_store_pd( ( double* )(y_cast + 0*n_elem_per_reg), rho0v.v ); _mm_store_pd( ( double* )(y_cast + 1*n_elem_per_reg), rho2v.v ); } blis-0.9.0/kernels/penryn/3/000077500000000000000000000000001422157504600155775ustar00rootroot00000000000000blis-0.9.0/kernels/penryn/3/bli_gemm_penryn_asm_d4x4.c000066400000000000000000000621351422157504600226230ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define BLIS_ASM_SYNTAX_ATT #include "bli_x86_asm_macros.h" void bli_sgemm_penryn_asm_8x4 ( dim_t m, dim_t n, dim_t k, float* restrict alpha, float* restrict a, float* restrict b, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k / 4; uint64_t k_left = k % 4; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; GEMM_UKR_SETUP_CT_ALIGNED( s, 8, 4, false, 16 ); begin_asm() mov(var(a), rax) // load address of a. mov(var(b), rbx) // load address of b. mov(var(b_next), r9) // load address of b_next. sub(imm(0-8*16), rax) // increment pointers to allow byte sub(imm(0-8*16), rbx) // offsets in the unrolled iterations. movaps(mem(rax, -8*16), xmm0) // initialize loop by pre-loading elements movaps(mem(rax, -7*16), xmm1) // of a and b. movaps(mem(rbx, -8*16), xmm2) mov(var(c), rcx) // load address of c mov(var(cs_c), rdi) // load cs_c lea(mem(, rdi, 4), rdi) // cs_c *= sizeof(float) mov(rdi, r12) // make a copy of cs_c (in bytes) lea(mem(rcx, rdi, 2), r10) // load address of c + 2*cs_c; prefetch(2, mem(r9, 0*4)) // prefetch b_next xorps(xmm3, xmm3) xorps(xmm4, xmm4) xorps(xmm5, xmm5) xorps(xmm6, xmm6) prefetch(2, mem(rcx, 6*4)) // prefetch c + 0*cs_c xorps(xmm8, xmm8) xorps(xmm9, xmm9) prefetch(2, mem(rcx, rdi, 1, 6*4)) // prefetch c + 1*cs_c xorps(xmm10, xmm10) xorps(xmm11, xmm11) prefetch(2, mem(r10, 6*4)) // prefetch c + 2*cs_c xorps(xmm12, xmm12) xorps(xmm13, xmm13) prefetch(2, mem(r10, rdi, 1, 6*4)) // prefetch c + 3*cs_c xorps(xmm14, xmm14) xorps(xmm15, xmm15) mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP prefetch(0, mem(rax, (4*35+1)*8)) addps(xmm6, xmm10) // iteration 0 addps(xmm3, xmm14) movaps(xmm2, xmm3) pshufd(imm(0x39), xmm2, xmm7) mulps(xmm0, xmm2) mulps(xmm1, xmm3) addps(xmm4, xmm11) addps(xmm5, xmm15) movaps(xmm7, xmm5) pshufd(imm(0x39), xmm7, xmm6) mulps(xmm0, xmm7) mulps(xmm1, xmm5) addps(xmm2, xmm8) movaps(mem(rbx, -7*16), xmm2) addps(xmm3, xmm12) movaps(xmm6, xmm3) pshufd(imm(0x39), xmm6, xmm4) mulps(xmm0, xmm6) mulps(xmm1, xmm3) addps(xmm7, xmm9) addps(xmm5, xmm13) movaps(xmm4, xmm5) mulps(xmm0, xmm4) movaps(mem(rax, -6*16), xmm0) mulps(xmm1, xmm5) movaps(mem(rax, -5*16), xmm1) addps(xmm6, xmm10) // iteration 1 addps(xmm3, xmm14) movaps(xmm2, xmm3) pshufd(imm(0x39), xmm2, xmm7) mulps(xmm0, xmm2) mulps(xmm1, xmm3) addps(xmm4, xmm11) addps(xmm5, xmm15) movaps(xmm7, xmm5) pshufd(imm(0x39), xmm7, xmm6) mulps(xmm0, xmm7) mulps(xmm1, xmm5) addps(xmm2, xmm8) movaps(mem(rbx, -6*16), xmm2) addps(xmm3, xmm12) movaps(xmm6, xmm3) pshufd(imm(0x39), xmm6, xmm4) mulps(xmm0, xmm6) mulps(xmm1, xmm3) addps(xmm7, xmm9) addps(xmm5, xmm13) movaps(xmm4, xmm5) mulps(xmm0, xmm4) movaps(mem(rax, -4*16), xmm0) mulps(xmm1, xmm5) movaps(mem(rax, -3*16), xmm1) addps(xmm6, xmm10) // iteration 2 addps(xmm3, xmm14) movaps(xmm2, xmm3) pshufd(imm(0x39), xmm2, xmm7) mulps(xmm0, xmm2) mulps(xmm1, xmm3) addps(xmm4, xmm11) addps(xmm5, xmm15) movaps(xmm7, xmm5) pshufd(imm(0x39), xmm7, xmm6) mulps(xmm0, xmm7) mulps(xmm1, xmm5) addps(xmm2, xmm8) movaps(mem(rbx, -5*16), xmm2) addps(xmm3, xmm12) movaps(xmm6, xmm3) pshufd(imm(0x39), xmm6, xmm4) mulps(xmm0, xmm6) mulps(xmm1, xmm3) addps(xmm7, xmm9) addps(xmm5, xmm13) movaps(xmm4, xmm5) mulps(xmm0, xmm4) movaps(mem(rax, -2*16), xmm0) mulps(xmm1, xmm5) movaps(mem(rax, -1*16), xmm1) addps(xmm6, xmm10) // iteration 3 addps(xmm3, xmm14) movaps(xmm2, xmm3) pshufd(imm(0x39), xmm2, xmm7) mulps(xmm0, xmm2) mulps(xmm1, xmm3) sub(imm(0-4*8*4), rax) // a += 4*8 (unroll x mr) addps(xmm4, xmm11) addps(xmm5, xmm15) movaps(xmm7, xmm5) pshufd(imm(0x39), xmm7, xmm6) mulps(xmm0, xmm7) mulps(xmm1, xmm5) sub(imm(0-4*4*4), r9) // b_next += 4*4 (unroll x nr) addps(xmm2, xmm8) movaps(mem(rbx, -4*16), xmm2) addps(xmm3, xmm12) movaps(xmm6, xmm3) pshufd(imm(0x39), xmm6, xmm4) mulps(xmm0, xmm6) mulps(xmm1, xmm3) sub(imm(0-4*4*4), rbx) // b += 4*4 (unroll x nr) addps(xmm7, xmm9) addps(xmm5, xmm13) movaps(xmm4, xmm5) mulps(xmm0, xmm4) movaps(mem(rax, -8*16), xmm0) mulps(xmm1, xmm5) movaps(mem(rax, -7*16), xmm1) prefetch(2, mem(r9, 0*4)) // prefetch b_next[0] prefetch(2, mem(r9, 16*4)) // prefetch b_next[16] dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP addps(xmm6, xmm10) // iteration 0 addps(xmm3, xmm14) movaps(xmm2, xmm3) pshufd(imm(0x39), xmm2, xmm7) mulps(xmm0, xmm2) mulps(xmm1, xmm3) addps(xmm4, xmm11) addps(xmm5, xmm15) movaps(xmm7, xmm5) pshufd(imm(0x39), xmm7, xmm6) mulps(xmm0, xmm7) mulps(xmm1, xmm5) addps(xmm2, xmm8) movaps(mem(rbx, -7*16), xmm2) addps(xmm3, xmm12) movaps(xmm6, xmm3) pshufd(imm(0x39), xmm6, xmm4) mulps(xmm0, xmm6) mulps(xmm1, xmm3) addps(xmm7, xmm9) addps(xmm5, xmm13) movaps(xmm4, xmm5) mulps(xmm0, xmm4) movaps(mem(rax, -6*16), xmm0) mulps(xmm1, xmm5) movaps(mem(rax, -5*16), xmm1) sub(imm(0-1*8*4), rax) // a += 8 (1 x mr) sub(imm(0-1*4*4), rbx) // b += 4 (1 x nr) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) addps(xmm6, xmm10) addps(xmm3, xmm14) addps(xmm4, xmm11) addps(xmm5, xmm15) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta movss(mem(rax), xmm6) // load alpha to bottom 4 bytes of xmm6 movss(mem(rbx), xmm7) // load beta to bottom 4 bytes of xmm7 pshufd(imm(0x00), xmm6, xmm6) // populate xmm6 with four alphas pshufd(imm(0x00), xmm7, xmm7) // populate xmm7 with four betas mov(var(rs_c), rsi) // load rs_c mov(rsi, r8) // make a copy of rs_c lea(mem(, rsi, 4), rsi) // rsi = rs_c * sizeof(float) lea(mem(rsi, rsi, 2), r11) // r11 = 3*(rs_c * sizeof(float)) lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*rs_c; // xmm8: xmm9: xmm10: xmm11: // ( ab00 ( ab01 ( ab02 ( ab03 // ab11 ab12 ab13 ab10 // ab22 ab23 ab20 ab21 // ab33 ) ab30 ) ab31 ) ab32 ) // // xmm12: xmm13: xmm14: xmm15: // ( ab40 ( ab41 ( ab42 ( ab43 // ab51 ab52 ab53 ab50 // ab62 ab63 ab60 ab61 // ab73 ) ab70 ) ab71 ) ab72 ) movaps(xmm9, xmm4) shufps(imm(0xd8), xmm8, xmm9) shufps(imm(0xd8), xmm11, xmm8) shufps(imm(0xd8), xmm10, xmm11) shufps(imm(0xd8), xmm4, xmm10) movaps(xmm8, xmm4) shufps(imm(0xd8), xmm10, xmm8) shufps(imm(0xd8), xmm4, xmm10) movaps(xmm9, xmm5) shufps(imm(0xd8), xmm11, xmm9) shufps(imm(0xd8), xmm5, xmm11) movaps(xmm13, xmm4) shufps(imm(0xd8), xmm12, xmm13) shufps(imm(0xd8), xmm15, xmm12) shufps(imm(0xd8), xmm14, xmm15) shufps(imm(0xd8), xmm4, xmm14) movaps(xmm12, xmm4) shufps(imm(0xd8), xmm14, xmm12) shufps(imm(0xd8), xmm4, xmm14) movaps(xmm13, xmm5) shufps(imm(0xd8), xmm15, xmm13) shufps(imm(0xd8), xmm5, xmm15) // xmm8: xmm9: xmm10: xmm11: // ( ab00 ( ab01 ( ab02 ( ab03 // ab10 ab11 ab12 ab13 // ab20 ab21 ab22 ab23 // ab30 ) ab31 ) ab32 ) ab33 ) // // xmm12: xmm13: xmm14: xmm15: // ( ab40 ( ab41 ( ab42 ( ab43 // ab50 ab51 ab52 ab53 // ab60 ab61 ab62 ab63 // ab70 ) ab71 ) ab72 ) ab73 ) // now avoid loading C if beta == 0 xorpd(xmm0, xmm0) // set xmm0 to zero. ucomisd(xmm0, xmm7) // check if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case movaps(mem(rcx), xmm0) // load c00 ~ c30, mulps(xmm6, xmm8) // scale by alpha, mulps(xmm7, xmm0) // scale by beta, addps(xmm8, xmm0) // add the gemm result, movaps(xmm0, mem(rcx)) // and store back to memory. add(rdi, rcx) movaps(mem(rdx), xmm1) // load c40 ~ c70, mulps(xmm6, xmm12) // scale by alpha, mulps(xmm7, xmm1) // scale by beta, addps(xmm12, xmm1) // add the gemm result, movaps(xmm1, mem(rdx)) // and store back to memory. add(rdi, rdx) movaps(mem(rcx), xmm0) // load c01 ~ c31, mulps(xmm6, xmm9) // scale by alpha, mulps(xmm7, xmm0) // scale by beta, addps(xmm9, xmm0) // add the gemm result, movaps(xmm0, mem(rcx)) // and store back to memory. add(rdi, rcx) movaps(mem(rdx), xmm1) // load c41 ~ c71, mulps(xmm6, xmm13) // scale by alpha, mulps(xmm7, xmm1) // scale by beta, addps(xmm13, xmm1) // add the gemm result, movaps(xmm1, mem(rdx)) // and store back to memory. add(rdi, rdx) movaps(mem(rcx), xmm0) // load c02 ~ c32, mulps(xmm6, xmm10) // scale by alpha, mulps(xmm7, xmm0) // scale by beta, addps(xmm10, xmm0) // add the gemm result, movaps(xmm0, mem(rcx)) // and store back to memory. add(rdi, rcx) movaps(mem(rdx), xmm1) // load c42 ~ c72, mulps(xmm6, xmm14) // scale by alpha, mulps(xmm7, xmm1) // scale by beta, addps(xmm14, xmm1) // add the gemm result, movaps(xmm1, mem(rdx)) // and store back to memory. add(rdi, rdx) movaps(mem(rcx), xmm0) // load c03 ~ c33, mulps(xmm6, xmm11) // scale by alpha, mulps(xmm7, xmm0) // scale by beta, addps(xmm11, xmm0) // add the gemm result, movaps(xmm0, mem(rcx)) // and store back to memory. movaps(mem(rdx), xmm1) // load c43 ~ c73, mulps(xmm6, xmm15) // scale by alpha, mulps(xmm7, xmm1) // scale by beta, addps(xmm15, xmm1) // add the gemm result, movaps(xmm1, mem(rdx)) // and store back to memory. jmp(.SDONE) // jump to end. label(.SBETAZERO) // skip loading c00 ~ c30, mulps(xmm6, xmm8) // scale by alpha, movaps(xmm8, mem(rcx)) // and store back to memory. add(rdi, rcx) // skip loading c40 ~ c70, mulps(xmm6, xmm12) // scale by alpha, movaps(xmm12, mem(rdx)) // and store back to memory. add(rdi, rdx) // skip loading c01 ~ c31, mulps(xmm6, xmm9) // scale by alpha, movaps(xmm9, mem(rcx)) // and store back to memory. add(rdi, rcx) // skip loading c41 ~ c71, mulps(xmm6, xmm13) // scale by alpha, movaps(xmm13, mem(rdx)) // and store back to memory. add(rdi, rdx) // skip loading c02 ~ c32, mulps(xmm6, xmm10) // scale by alpha, movaps(xmm10, mem(rcx)) // and store back to memory. add(rdi, rcx) // skip loading c42 ~ c72, mulps(xmm6, xmm14) // scale by alpha, movaps(xmm14, mem(rdx)) // and store back to memory. add(rdi, rdx) // skip loading c03 ~ c33, mulps(xmm6, xmm11) // scale by alpha, movaps(xmm11, mem(rcx)) // and store back to memory. // skip loading c43 ~ c73, mulps(xmm6, xmm15) // scale by alpha, movaps(xmm15, mem(rdx)) // and store back to memory. label(.SDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), // 0 [k_left] "m" (k_left), // 1 [a] "m" (a), // 2 [b] "m" (b), // 3 [alpha] "m" (alpha), // 4 [beta] "m" (beta), // 5 [c] "m" (c), // 6 [rs_c] "m" (rs_c), // 7 [cs_c] "m" (cs_c), // 8 [b_next] "m" (b_next)/*, // 9 [a_next] "m" (a_next)*/ // 10 : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) GEMM_UKR_FLUSH_CT( s ); } void bli_dgemm_penryn_asm_4x4 ( dim_t m, dim_t n, dim_t k, double* restrict alpha, double* restrict a, double* restrict b, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { void* a_next = bli_auxinfo_next_a( data ); void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k / 4; uint64_t k_left = k % 4; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; GEMM_UKR_SETUP_CT_ALIGNED( d, 4, 4, false, 16 ); begin_asm() mov(var(a), rax) // load address of a. mov(var(b), rbx) // load address of b. mov(var(b_next), r9) // load address of b_next. mov(var(a_next), r11) // load address of a_next. sub(imm(0-8*16), rax) // increment pointers to allow byte sub(imm(0-8*16), rbx) // offsets in the unrolled iterations. movaps(mem(rax, -8*16), xmm0) // initialize loop by pre-loading elements movaps(mem(rax, -7*16), xmm1) // of a and b. movaps(mem(rbx, -8*16), xmm2) mov(var(c), rcx) // load address of c mov(var(cs_c), rdi) // load cs_c lea(mem(, rdi, 8), rdi) // cs_c *= sizeof(double) mov(rdi, r12) // make a copy of cs_c (in bytes) lea(mem(rcx, rdi, 2), r10) // load address of c + 2*cs_c; prefetch(2, mem(r9, 0*8)) // prefetch b_next xorpd(xmm3, xmm3) xorpd(xmm4, xmm4) xorpd(xmm5, xmm5) xorpd(xmm6, xmm6) prefetch(2, mem(rcx, 3*8)) // prefetch c + 0*cs_c xorpd(xmm8, xmm8) xorpd(xmm9, xmm9) prefetch(2, mem(rcx, rdi, 1, 3*8)) // prefetch c + 1*cs_c xorpd(xmm10, xmm10) xorpd(xmm11, xmm11) prefetch(2, mem(r10, 3*8)) // prefetch c + 2*cs_c xorpd(xmm12, xmm12) xorpd(xmm13, xmm13) prefetch(2, mem(r10, rdi, 1, 3*8)) // prefetch c + 3*cs_c xorpd(xmm14, xmm14) xorpd(xmm15, xmm15) mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.DLOOPKITER) // MAIN LOOP prefetch(0, mem(rax, (4*35+1)*8)) //prefetch(0, mem(rax, (8*97+4)*8)) //prefetch(0, mem(r11, 67*4*8)) // prefetch a_next[0] addpd(xmm3, xmm11) // iteration 0 movaps(mem(rbx, -7*16), xmm3) addpd(xmm4, xmm15) movaps(xmm2, xmm4) pshufd(imm(0x4e), xmm2, xmm7) mulpd(xmm0, xmm2) mulpd(xmm1, xmm4) addpd(xmm5, xmm10) addpd(xmm6, xmm14) movaps(xmm7, xmm6) mulpd(xmm0, xmm7) mulpd(xmm1, xmm6) addpd(xmm2, xmm9) movaps(mem(rbx, -6*16), xmm2) addpd(xmm4, xmm13) movaps(xmm3, xmm4) pshufd(imm(0x4e), xmm3, xmm5) mulpd(xmm0, xmm3) mulpd(xmm1, xmm4) addpd(xmm7, xmm8) addpd(xmm6, xmm12) movaps(xmm5, xmm6) mulpd(xmm0, xmm5) movaps(mem(rax, -6*16), xmm0) mulpd(xmm1, xmm6) movaps(mem(rax, -5*16), xmm1) addpd(xmm3, xmm11) // iteration 1 movaps(mem(rbx, -5*16), xmm3) addpd(xmm4, xmm15) movaps(xmm2, xmm4) pshufd(imm(0x4e), xmm2, xmm7) mulpd(xmm0, xmm2) mulpd(xmm1, xmm4) addpd(xmm5, xmm10) addpd(xmm6, xmm14) movaps(xmm7, xmm6) mulpd(xmm0, xmm7) mulpd(xmm1, xmm6) addpd(xmm2, xmm9) movaps(mem(rbx, -4*16), xmm2) addpd(xmm4, xmm13) movaps(xmm3, xmm4) pshufd(imm(0x4e), xmm3, xmm5) mulpd(xmm0, xmm3) mulpd(xmm1, xmm4) addpd(xmm7, xmm8) addpd(xmm6, xmm12) movaps(xmm5, xmm6) mulpd(xmm0, xmm5) movaps(mem(rax, -4*16), xmm0) mulpd(xmm1, xmm6) movaps(mem(rax, -3*16), xmm1) prefetch(0, mem(rax, (4*37+1)*8)) //prefetch(0, mem(rax, (8*97+12)*8)) //prefetch(0, mem(r11, 69*4*8)) // prefetch a_next[8] //sub(imm(-4*4*8), r11) // a_next += 4*4 (unroll x mr) addpd(xmm3, xmm11) // iteration 2 movaps(mem(rbx, -3*16), xmm3) addpd(xmm4, xmm15) movaps(xmm2, xmm4) pshufd(imm(0x4e), xmm2, xmm7) mulpd(xmm0, xmm2) mulpd(xmm1, xmm4) addpd(xmm5, xmm10) addpd(xmm6, xmm14) movaps(xmm7, xmm6) mulpd(xmm0, xmm7) mulpd(xmm1, xmm6) addpd(xmm2, xmm9) movaps(mem(rbx, -2*16), xmm2) addpd(xmm4, xmm13) movaps(xmm3, xmm4) pshufd(imm(0x4e), xmm3, xmm5) mulpd(xmm0, xmm3) mulpd(xmm1, xmm4) addpd(xmm7, xmm8) addpd(xmm6, xmm12) movaps(xmm5, xmm6) mulpd(xmm0, xmm5) movaps(mem(rax, -2*16), xmm0) mulpd(xmm1, xmm6) movaps(mem(rax, -1*16), xmm1) addpd(xmm3, xmm11) // iteration 3 movaps(mem(rbx, -1*16), xmm3) addpd(xmm4, xmm15) movaps(xmm2, xmm4) pshufd(imm(0x4e), xmm2, xmm7) mulpd(xmm0, xmm2) mulpd(xmm1, xmm4) sub(imm(0-4*4*8), rax) // a += 4*4 (unroll x mr) addpd(xmm5, xmm10) addpd(xmm6, xmm14) movaps(xmm7, xmm6) mulpd(xmm0, xmm7) mulpd(xmm1, xmm6) sub(imm(0-4*4*8), r9) // b_next += 4*4 (unroll x nr) addpd(xmm2, xmm9) movaps(mem(rbx, 0*16), xmm2) addpd(xmm4, xmm13) movaps(xmm3, xmm4) pshufd(imm(0x4e), xmm3, xmm5) mulpd(xmm0, xmm3) mulpd(xmm1, xmm4) sub(imm(0-4*4*8), rbx) // b += 4*4 (unroll x nr) addpd(xmm7, xmm8) addpd(xmm6, xmm12) movaps(xmm5, xmm6) mulpd(xmm0, xmm5) movaps(mem(rax, -8*16), xmm0) mulpd(xmm1, xmm6) movaps(mem(rax, -7*16), xmm1) prefetch(2, mem(r9, 0*8)) // prefetch b_next[0] prefetch(2, mem(r9, 8*8)) // prefetch b_next[8] dec(rsi) // i -= 1; jne(.DLOOPKITER) // iterate again if i != 0. //prefetch(2, mem(r9, -8*8)) // prefetch b_next[-8] label(.DCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.DLOOPKLEFT) // EDGE LOOP addpd(xmm3, xmm11) // iteration 0 movaps(mem(rbx, -7*16), xmm3) addpd(xmm4, xmm15) movaps(xmm2, xmm4) pshufd(imm(0x4e), xmm2, xmm7) mulpd(xmm0, xmm2) mulpd(xmm1, xmm4) addpd(xmm5, xmm10) addpd(xmm6, xmm14) movaps(xmm7, xmm6) mulpd(xmm0, xmm7) mulpd(xmm1, xmm6) addpd(xmm2, xmm9) movaps(mem(rbx, -6*16), xmm2) addpd(xmm4, xmm13) movaps(xmm3, xmm4) pshufd(imm(0x4e), xmm3, xmm5) mulpd(xmm0, xmm3) mulpd(xmm1, xmm4) addpd(xmm7, xmm8) addpd(xmm6, xmm12) movaps(xmm5, xmm6) mulpd(xmm0, xmm5) movaps(mem(rax, -6*16), xmm0) mulpd(xmm1, xmm6) movaps(mem(rax, -5*16), xmm1) sub(imm(0-4*1*8), rax) // a += 4 (1 x mr) sub(imm(0-4*1*8), rbx) // b += 4 (1 x nr) dec(rsi) // i -= 1; jne(.DLOOPKLEFT) // iterate again if i != 0. label(.DPOSTACCUM) addpd(xmm3, xmm11) addpd(xmm4, xmm15) addpd(xmm5, xmm10) addpd(xmm6, xmm14) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta movddup(mem(rax), xmm6) // load alpha and duplicate movddup(mem(rbx), xmm7) // load beta and duplicate mov(var(rs_c), rsi) // load rs_c mov(rsi, r8) // make a copy of rs_c lea(mem(, rsi, 8), rsi) // rsi = rs_c * sizeof(double) lea(mem(rcx, rsi, 2), rdx) // load address of c + 2*rs_c; // xmm8: xmm9: xmm10: xmm11: // ( ab01 ( ab00 ( ab03 ( ab02 // ab10 ) ab11 ) ab12 ) ab13 ) // // xmm12: xmm13: xmm14: xmm15: // ( ab21 ( ab20 ( ab23 ( ab22 // ab30 ) ab31 ) ab32 ) ab33 ) movaps(xmm8, xmm0) movsd(xmm9, xmm8) movsd(xmm0, xmm9) movaps(xmm10, xmm0) movsd(xmm11, xmm10) movsd(xmm0, xmm11) movaps(xmm12, xmm0) movsd(xmm13, xmm12) movsd(xmm0, xmm13) movaps(xmm14, xmm0) movsd(xmm15, xmm14) movsd(xmm0, xmm15) // xmm8: xmm9: xmm10: xmm11: // ( ab00 ( ab01 ( ab02 ( ab03 // ab10 ) ab11 ) ab12 ) ab13 ) // // xmm12: xmm13: xmm14: xmm15: // ( ab20 ( ab21 ( ab22 ( ab23 // ab30 ) ab31 ) ab32 ) ab33 ) // now avoid loading C if beta == 0 xorpd(xmm0, xmm0) // set xmm0 to zero. ucomisd(xmm0, xmm7) // check if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case movaps(mem(rcx), xmm0) // load c00 and c10, mulpd(xmm6, xmm8) // scale by alpha, mulpd(xmm7, xmm0) // scale by beta, addpd(xmm8, xmm0) // add the gemm result, movaps(xmm0, mem(rcx)) // and store back to memory. add(rdi, rcx) movaps(mem(rdx), xmm1) // load c20 and c30, mulpd(xmm6, xmm12) // scale by alpha, mulpd(xmm7, xmm1) // scale by beta, addpd(xmm12, xmm1) // add the gemm result, movaps(xmm1, mem(rdx)) // and store back to memory. add(rdi, rdx) movaps(mem(rcx), xmm0) // load c01 and c11, mulpd(xmm6, xmm9) // scale by alpha, mulpd(xmm7, xmm0) // scale by beta, addpd(xmm9, xmm0) // add the gemm result, movaps(xmm0, mem(rcx)) // and store back to memory. add(rdi, rcx) movaps(mem(rdx), xmm1) // load c21 and c31, mulpd(xmm6, xmm13) // scale by alpha, mulpd(xmm7, xmm1) // scale by beta, addpd(xmm13, xmm1) // add the gemm result, movaps(xmm1, mem(rdx)) // and store back to memory. add(rdi, rdx) movaps(mem(rcx), xmm0) // load c02 and c12, mulpd(xmm6, xmm10) // scale by alpha, mulpd(xmm7, xmm0) // scale by beta, addpd(xmm10, xmm0) // add the gemm result, movaps(xmm0, mem(rcx)) // and store back to memory. add(rdi, rcx) movaps(mem(rdx), xmm1) // load c22 and c32, mulpd(xmm6, xmm14) // scale by alpha, mulpd(xmm7, xmm1) // scale by beta, addpd(xmm14, xmm1) // add the gemm result, movaps(xmm1, mem(rdx)) // and store back to memory. add(rdi, rdx) movaps(mem(rcx), xmm0) // load c03 and c13, mulpd(xmm6, xmm11) // scale by alpha, mulpd(xmm7, xmm0) // scale by beta, addpd(xmm11, xmm0) // add the gemm result, movaps(xmm0, mem(rcx)) // and store back to memory. movaps(mem(rdx), xmm1) // load c23 and c33, mulpd(xmm6, xmm15) // scale by alpha, mulpd(xmm7, xmm1) // scale by beta, addpd(xmm15, xmm1) // add the gemm result, movaps(xmm1, mem(rdx)) // and store back to memory. jmp(.DDONE) // jump to end. label(.DBETAZERO) // skip loading c00 and c10, mulpd(xmm6, xmm8) // scale by alpha, movaps(xmm8, mem(rcx)) // and store back to memory. add(rdi, rcx) // skip loading c20 and c30, mulpd(xmm6, xmm12) // scale by alpha, movaps(xmm12, mem(rdx)) // and store back to memory. add(rdi, rdx) // skip loading c01 and c11, mulpd(xmm6, xmm9) // scale by alpha, movaps(xmm9, mem(rcx)) // and store back to memory. add(rdi, rcx) // skip loading c21 and c31, mulpd(xmm6, xmm13) // scale by alpha, movaps(xmm13, mem(rdx)) // and store back to memory. add(rdi, rdx) // skip loading c02 and c12, mulpd(xmm6, xmm10) // scale by alpha, movaps(xmm10, mem(rcx)) // and store back to memory. add(rdi, rcx) // skip loading c22 and c32, mulpd(xmm6, xmm14) // scale by alpha, movaps(xmm14, mem(rdx)) // and store back to memory. add(rdi, rdx) // skip loading c03 and c13, mulpd(xmm6, xmm11) // scale by alpha, movaps(xmm11, mem(rcx)) // and store back to memory. // skip loading c23 and c33, mulpd(xmm6, xmm15) // scale by alpha, movaps(xmm15, mem(rdx)) // and store back to memory. label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), // 0 [k_left] "m" (k_left), // 1 [a] "m" (a), // 2 [b] "m" (b), // 3 [alpha] "m" (alpha), // 4 [beta] "m" (beta), // 5 [c] "m" (c), // 6 [rs_c] "m" (rs_c), // 7 [cs_c] "m" (cs_c), // 8 [b_next] "m" (b_next), // 9 [a_next] "m" (a_next) // 10 : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) GEMM_UKR_FLUSH_CT( d ); } blis-0.9.0/kernels/penryn/3/bli_gemmtrsm_l_penryn_asm_d4x4.c000066400000000000000000000402521422157504600240400ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define BLIS_ASM_SYNTAX_ATT #include "bli_x86_asm_macros.h" #if 0 void bli_sgemmtrsm_l_penryn_asm_8x4 ( dim_t k0, float* restrict alpha, float* restrict a10, float* restrict a11, float* restrict b01, float* restrict b11, float* restrict c11, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { } #endif void bli_dgemmtrsm_l_penryn_asm_4x4 ( dim_t m, dim_t n, dim_t k0, double* restrict alpha, double* restrict a10, double* restrict a11, double* restrict b01, double* restrict b11, double* restrict c11, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; GEMMTRSM_UKR_SETUP_CT( d, 4, 4, false ); begin_asm() mov(var(a10), rax) // load address of a10. mov(var(b01), rbx) // load address of b01. //mov(var(b_next), r9) // load address of b_next. sub(imm(0-8*16), rax) // increment pointers to allow byte sub(imm(0-8*16), rbx) // offsets in the unrolled iterations. movaps(mem(rax, -8*16), xmm0) // initialize loop by pre-loading elements movaps(mem(rax, -7*16), xmm1) // of a and b. movaps(mem(rbx, -8*16), xmm2) //mov(var(c11), rcx) // load address of c11 //mov(var(rs_c), rdi) // load cs_c //lea(mem(, rdi, 8), rdi) // cs_c *= sizeof(double) //lea(mem(rcx, rdi, 2), rdx) // load address of c + 2*cs_c; //prefetch(2, mem(r9, 0*8)) // prefetch b_next xorpd(xmm3, xmm3) xorpd(xmm4, xmm4) xorpd(xmm5, xmm5) xorpd(xmm6, xmm6) //prefetch(2, mem(rcx, 3*8)) // prefetch c + 0*cs_c xorpd(xmm8, xmm8) movaps(xmm8, xmm9) //prefetch(2, mem(rcx, rdi, 1, 3*8)) // prefetch c + 1*cs_c movaps(xmm8, xmm10) movaps(xmm8, xmm11) //prefetch(2, mem(rdx, 3*8)) // prefetch c + 2*cs_c movaps(xmm8, xmm12) movaps(xmm8, xmm13) //prefetch(2, mem(rdx, rdi, 1, 3*8)) // prefetch c + 3*cs_c movaps(xmm8, xmm14) movaps(xmm8, xmm15) mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.CONSIDERKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.LOOPKITER) // MAIN LOOP //prefetch(0, mem(rax, 1264)) prefetch(0, mem(rax, (4*35+1)*8)) addpd(xmm3, xmm11) // iteration 0 movaps(mem(rbx, -7*16), xmm3) addpd(xmm4, xmm15) movaps(xmm2, xmm4) pshufd(imm(0x4e), xmm2, xmm7) mulpd(xmm0, xmm2) mulpd(xmm1, xmm4) addpd(xmm5, xmm10) addpd(xmm6, xmm14) movaps(xmm7, xmm6) mulpd(xmm0, xmm7) mulpd(xmm1, xmm6) addpd(xmm2, xmm9) movaps(mem(rbx, -6*16), xmm2) addpd(xmm4, xmm13) movaps(xmm3, xmm4) pshufd(imm(0x4e), xmm3, xmm5) mulpd(xmm0, xmm3) mulpd(xmm1, xmm4) addpd(xmm7, xmm8) addpd(xmm6, xmm12) movaps(xmm5, xmm6) mulpd(xmm0, xmm5) movaps(mem(rax, -6*16), xmm0) mulpd(xmm1, xmm6) movaps(mem(rax, -5*16), xmm1) addpd(xmm3, xmm11) // iteration 1 movaps(mem(rbx, -5*16), xmm3) addpd(xmm4, xmm15) movaps(xmm2, xmm4) pshufd(imm(0x4e), xmm2, xmm7) mulpd(xmm0, xmm2) mulpd(xmm1, xmm4) addpd(xmm5, xmm10) addpd(xmm6, xmm14) movaps(xmm7, xmm6) mulpd(xmm0, xmm7) mulpd(xmm1, xmm6) addpd(xmm2, xmm9) movaps(mem(rbx, -4*16), xmm2) addpd(xmm4, xmm13) movaps(xmm3, xmm4) pshufd(imm(0x4e), xmm3, xmm5) mulpd(xmm0, xmm3) mulpd(xmm1, xmm4) addpd(xmm7, xmm8) addpd(xmm6, xmm12) movaps(xmm5, xmm6) mulpd(xmm0, xmm5) movaps(mem(rax, -4*16), xmm0) mulpd(xmm1, xmm6) movaps(mem(rax, -3*16), xmm1) //prefetch(0, mem(rax, 1328)) prefetch(0, mem(rax, (4*37+1)*8)) addpd(xmm3, xmm11) // iteration 2 movaps(mem(rbx, -3*16), xmm3) addpd(xmm4, xmm15) movaps(xmm2, xmm4) pshufd(imm(0x4e), xmm2, xmm7) mulpd(xmm0, xmm2) mulpd(xmm1, xmm4) addpd(xmm5, xmm10) addpd(xmm6, xmm14) movaps(xmm7, xmm6) mulpd(xmm0, xmm7) mulpd(xmm1, xmm6) addpd(xmm2, xmm9) movaps(mem(rbx, -2*16), xmm2) addpd(xmm4, xmm13) movaps(xmm3, xmm4) pshufd(imm(0x4e), xmm3, xmm5) mulpd(xmm0, xmm3) mulpd(xmm1, xmm4) addpd(xmm7, xmm8) addpd(xmm6, xmm12) movaps(xmm5, xmm6) mulpd(xmm0, xmm5) movaps(mem(rax, -2*16), xmm0) mulpd(xmm1, xmm6) movaps(mem(rax, -1*16), xmm1) addpd(xmm3, xmm11) // iteration 3 movaps(mem(rbx, -1*16), xmm3) addpd(xmm4, xmm15) movaps(xmm2, xmm4) pshufd(imm(0x4e), xmm2, xmm7) mulpd(xmm0, xmm2) mulpd(xmm1, xmm4) sub(imm(0-4*4*8), rax) // a += 4*4 (unroll x mr) addpd(xmm5, xmm10) addpd(xmm6, xmm14) movaps(xmm7, xmm6) mulpd(xmm0, xmm7) mulpd(xmm1, xmm6) //sub(imm(-4*4*8), r9) // b_next += 4*4 (unroll x nr) addpd(xmm2, xmm9) movaps(mem(rbx, 0*16), xmm2) addpd(xmm4, xmm13) movaps(xmm3, xmm4) pshufd(imm(0x4e), xmm3, xmm5) mulpd(xmm0, xmm3) mulpd(xmm1, xmm4) sub(imm(0-4*4*8), rbx) // b += 4*4 (unroll x nr) addpd(xmm7, xmm8) addpd(xmm6, xmm12) movaps(xmm5, xmm6) mulpd(xmm0, xmm5) movaps(mem(rax, -8*16), xmm0) mulpd(xmm1, xmm6) movaps(mem(rax, -7*16), xmm1) //prefetch(2, mem(r9, 0*8)) // prefetch b_next[0] //prefetch(2, mem(r9, 8*8)) // prefetch b_next[8] dec(rsi) // i -= 1; jne(.LOOPKITER) // iterate again if i != 0. label(.CONSIDERKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.POSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.LOOPKLEFT) // EDGE LOOP addpd(xmm3, xmm11) // iteration 0 movaps(mem(rbx, -7*16), xmm3) addpd(xmm4, xmm15) movaps(xmm2, xmm4) pshufd(imm(0x4e), xmm2, xmm7) mulpd(xmm0, xmm2) mulpd(xmm1, xmm4) addpd(xmm5, xmm10) addpd(xmm6, xmm14) movaps(xmm7, xmm6) mulpd(xmm0, xmm7) mulpd(xmm1, xmm6) addpd(xmm2, xmm9) movaps(mem(rbx, -6*16), xmm2) addpd(xmm4, xmm13) movaps(xmm3, xmm4) pshufd(imm(0x4e), xmm3, xmm5) mulpd(xmm0, xmm3) mulpd(xmm1, xmm4) addpd(xmm7, xmm8) addpd(xmm6, xmm12) movaps(xmm5, xmm6) mulpd(xmm0, xmm5) movaps(mem(rax, -6*16), xmm0) mulpd(xmm1, xmm6) movaps(mem(rax, -5*16), xmm1) sub(imm(0-4*1*8), rax) // a += 4 (1 x mr) sub(imm(0-4*1*8), rbx) // b += 4 (1 x nr) dec(rsi) // i -= 1; jne(.LOOPKLEFT) // iterate again if i != 0. label(.POSTACCUM) addpd(xmm3, xmm11) addpd(xmm4, xmm15) addpd(xmm5, xmm10) addpd(xmm6, xmm14) mov(var(b11), rbx) // load address of b11. // xmm8: xmm9: xmm10: xmm11: // ( ab01 ( ab00 ( ab03 ( ab02 // ab10 ) ab11 ) ab12 ) ab13 ) // // xmm12: xmm13: xmm14: xmm15: // ( ab21 ( ab20 ( ab23 ( ab22 // ab30 ) ab31 ) ab32 ) ab33 ) movaps(xmm9, xmm0) movaps(xmm8, xmm1) unpcklpd(xmm8, xmm0) unpckhpd(xmm9, xmm1) movaps(xmm11, xmm4) movaps(xmm10, xmm5) unpcklpd(xmm10, xmm4) unpckhpd(xmm11, xmm5) movaps(xmm13, xmm2) movaps(xmm12, xmm3) unpcklpd(xmm12, xmm2) unpckhpd(xmm13, xmm3) movaps(xmm15, xmm6) movaps(xmm14, xmm7) unpcklpd(xmm14, xmm6) unpckhpd(xmm15, xmm7) // xmm0: ( ab00 ab01 ) xmm4: ( ab02 ab03 ) // xmm1: ( ab10 ab11 ) xmm5: ( ab12 ab13 ) // xmm2: ( ab20 ab21 ) xmm6: ( ab22 ab23 ) // xmm3: ( ab30 ab31 ) xmm7: ( ab32 ab33 ) mov(var(alpha), rax) // load address of alpha movddup(mem(rax), xmm15) // load alpha and duplicate movaps(mem(rbx, 0*16), xmm8) movaps(mem(rbx, 1*16), xmm12) mulpd(xmm15, xmm8) // xmm8 = alpha * ( beta00 beta01 ) mulpd(xmm15, xmm12) // xmm12 = alpha * ( beta02 beta03 ) movaps(mem(rbx, 2*16), xmm9) movaps(mem(rbx, 3*16), xmm13) mulpd(xmm15, xmm9) // xmm9 = alpha * ( beta10 beta11 ) mulpd(xmm15, xmm13) // xmm13 = alpha * ( beta12 beta13 ) movaps(mem(rbx, 4*16), xmm10) movaps(mem(rbx, 5*16), xmm14) mulpd(xmm15, xmm10) // xmm10 = alpha * ( beta20 beta21 ) mulpd(xmm15, xmm14) // xmm14 = alpha * ( beta22 beta23 ) movaps(mem(rbx, 6*16), xmm11) mulpd(xmm15, xmm11) // xmm11 = alpha * ( beta30 beta31 ) mulpd(mem(rbx, 7*16), xmm15) // xmm15 = alpha * ( beta32 beta33 ) // (Now scaled by alpha:) // xmm8: ( beta00 beta01 ) xmm12: ( beta02 beta03 ) // xmm9: ( beta10 beta11 ) xmm13: ( beta12 beta13 ) // xmm10: ( beta20 beta21 ) xmm14: ( beta22 beta23 ) // xmm11: ( beta30 beta31 ) xmm15: ( beta32 beta33 ) subpd(xmm0, xmm8) // xmm8 -= xmm0 subpd(xmm1, xmm9) // xmm9 -= xmm1 subpd(xmm2, xmm10) // xmm10 -= xmm2 subpd(xmm3, xmm11) // xmm11 -= xmm3 subpd(xmm4, xmm12) // xmm12 -= xmm4 subpd(xmm5, xmm13) // xmm13 -= xmm5 subpd(xmm6, xmm14) // xmm14 -= xmm6 subpd(xmm7, xmm15) // xmm15 -= xmm7 label(.TRSM) mov(var(a11), rax) // load address of a11 mov(var(c11), rcx) // load address of c11 mov(var(rs_c), rsi) // load rs_c mov(var(cs_c), rdi) // load cs_c sal(imm(3), rsi) // rs_c *= sizeof( double ) sal(imm(3), rdi) // cs_c *= sizeof( double ) lea(mem(rcx, rdi, 2), rdx) // c11_2 = c11 + 2*cs_c // iteration 0 movddup(mem(0+0*4)*8(rax), xmm0) // load xmm0 = (1/alpha00) #ifdef BLIS_ENABLE_TRSM_PREINVERSION mulpd(xmm0, xmm8) // xmm8 *= (1/alpha00); mulpd(xmm0, xmm12) // xmm12 *= (1/alpha00); #else divpd(xmm0, xmm8) // xmm8 /= alpha00; divpd(xmm0, xmm12) // xmm12 /= alpha00; #endif movaps(xmm8, mem(rbx, 0*16)) // store ( beta00 beta01 ) = xmm8 movaps(xmm12, mem(rbx, 1*16)) // store ( beta02 beta03 ) = xmm12 movlpd(xmm8, mem(rcx)) // store ( gamma00 ) = xmm8[0] movhpd(xmm8, mem(rcx, rdi, 1)) // store ( gamma01 ) = xmm8[1] movlpd(xmm12, mem(rdx)) // store ( gamma02 ) = xmm12[0] movhpd(xmm12, mem(rdx, rdi, 1)) // store ( gamma03 ) = xmm12[1] add(rsi, rcx) // c11 += rs_c add(rsi, rdx) // c11_2 += rs_c // iteration 1 movddup(mem(1+0*4)*8(rax), xmm0) // load xmm0 = alpha10 movddup(mem(1+1*4)*8(rax), xmm1) // load xmm1 = (1/alpha11) movaps(xmm0, xmm4) // xmm4 = xmm0 mulpd(xmm8, xmm0) // xmm0 = alpha10 * ( beta00 beta01 ) mulpd(xmm12, xmm4) // xmm4 = alpha10 * ( beta02 beta03 ) subpd(xmm0, xmm9) // xmm9 -= xmm0 subpd(xmm4, xmm13) // xmm13 -= xmm4 #ifdef BLIS_ENABLE_TRSM_PREINVERSION mulpd(xmm1, xmm9) // xmm9 *= (1/alpha11); mulpd(xmm1, xmm13) // xmm13 *= (1/alpha11); #else divpd(xmm1, xmm9) // xmm9 /= alpha11; divpd(xmm1, xmm13) // xmm13 /= alpha11; #endif movaps(xmm9, mem(rbx, 2*16)) // store ( beta10 beta11 ) = xmm9 movaps(xmm13, mem(rbx, 3*16)) // store ( beta12 beta13 ) = xmm13 movlpd(xmm9, mem(rcx)) // store ( gamma10 ) = xmm9[0] movhpd(xmm9, mem(rcx, rdi, 1)) // store ( gamma11 ) = xmm9[1] movlpd(xmm13, mem(rdx)) // store ( gamma12 ) = xmm13[0] movhpd(xmm13, mem(rdx, rdi, 1)) // store ( gamma13 ) = xmm13[1] add(rsi, rcx) // c11 += rs_c add(rsi, rdx) // c11_2 += rs_c // iteration 2 movddup(mem(2+0*4)*8(rax), xmm0) // load xmm0 = alpha20 movddup(mem(2+1*4)*8(rax), xmm1) // load xmm1 = alpha21 movddup(mem(2+2*4)*8(rax), xmm2) // load xmm2 = (1/alpha22) movaps(xmm0, xmm4) // xmm4 = xmm0 movaps(xmm1, xmm5) // xmm5 = xmm1 mulpd(xmm8, xmm0) // xmm0 = alpha20 * ( beta00 beta01 ) mulpd(xmm12, xmm4) // xmm4 = alpha20 * ( beta02 beta03 ) mulpd(xmm9, xmm1) // xmm1 = alpha21 * ( beta10 beta11 ) mulpd(xmm13, xmm5) // xmm5 = alpha21 * ( beta12 beta13 ) addpd(xmm1, xmm0) // xmm0 += xmm1; addpd(xmm5, xmm4) // xmm4 += xmm5; subpd(xmm0, xmm10) // xmm10 -= xmm0 subpd(xmm4, xmm14) // xmm14 -= xmm4 #ifdef BLIS_ENABLE_TRSM_PREINVERSION mulpd(xmm2, xmm10) // xmm10 *= (1/alpha22); mulpd(xmm2, xmm14) // xmm14 *= (1/alpha22); #else divpd(xmm2, xmm10) // xmm10 /= alpha22; divpd(xmm2, xmm14) // xmm14 /= alpha22; #endif movaps(xmm10, mem(rbx, 4*16)) // store ( beta20 beta21 ) = xmm10 movaps(xmm14, mem(rbx, 5*16)) // store ( beta22 beta23 ) = xmm14 movlpd(xmm10, mem(rcx)) // store ( gamma20 ) = xmm10[0] movhpd(xmm10, mem(rcx, rdi, 1)) // store ( gamma21 ) = xmm10[1] movlpd(xmm14, mem(rdx)) // store ( gamma22 ) = xmm14[0] movhpd(xmm14, mem(rdx, rdi, 1)) // store ( gamma23 ) = xmm14[1] add(rsi, rcx) // c11 += rs_c add(rsi, rdx) // c11_2 += rs_c // iteration 3 movddup(mem(3+0*4)*8(rax), xmm0) // load xmm0 = alpha30 movddup(mem(3+1*4)*8(rax), xmm1) // load xmm1 = alpha31 movddup(mem(3+2*4)*8(rax), xmm2) // load xmm2 = alpha32 movddup(mem(3+3*4)*8(rax), xmm3) // load xmm3 = (1/alpha33) movaps(xmm0, xmm4) // xmm4 = xmm0 movaps(xmm1, xmm5) // xmm5 = xmm1 movaps(xmm2, xmm6) // xmm6 = xmm2 mulpd(xmm8, xmm0) // xmm0 = alpha30 * ( beta00 beta01 ) mulpd(xmm12, xmm4) // xmm4 = alpha30 * ( beta02 beta03 ) mulpd(xmm9, xmm1) // xmm1 = alpha31 * ( beta10 beta11 ) mulpd(xmm13, xmm5) // xmm5 = alpha31 * ( beta12 beta13 ) mulpd(xmm10, xmm2) // xmm2 = alpha32 * ( beta20 beta21 ) mulpd(xmm14, xmm6) // xmm6 = alpha32 * ( beta22 beta23 ) addpd(xmm1, xmm0) // xmm0 += xmm1; addpd(xmm5, xmm4) // xmm4 += xmm5; addpd(xmm2, xmm0) // xmm0 += xmm2; addpd(xmm6, xmm4) // xmm4 += xmm6; subpd(xmm0, xmm11) // xmm11 -= xmm0 subpd(xmm4, xmm15) // xmm15 -= xmm4 #ifdef BLIS_ENABLE_TRSM_PREINVERSION mulpd(xmm3, xmm11) // xmm11 *= (1/alpha33); mulpd(xmm3, xmm15) // xmm15 *= (1/alpha33); #else divpd(xmm3, xmm11) // xmm11 /= alpha33; divpd(xmm3, xmm15) // xmm15 /= alpha33; #endif movaps(xmm11, mem(rbx, 6*16)) // store ( beta30 beta31 ) = xmm11 movaps(xmm15, mem(rbx, 7*16)) // store ( beta32 beta33 ) = xmm15 movlpd(xmm11, mem(rcx)) // store ( gamma30 ) = xmm11[0] movhpd(xmm11, mem(rcx, rdi, 1)) // store ( gamma31 ) = xmm11[1] movlpd(xmm15, mem(rdx)) // store ( gamma32 ) = xmm15[0] movhpd(xmm15, mem(rdx, rdi, 1)) // store ( gamma33 ) = xmm15[1] end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), // 0 [k_left] "m" (k_left), // 1 [a10] "m" (a10), // 2 [a11] "m" (a11), // 3 [b01] "m" (b01), // 4 [b11] "m" (b11), // 5 [c11] "m" (c11), // 6 [rs_c] "m" (rs_c), // 7 [cs_c] "m" (cs_c), // 8 [alpha] "m" (alpha), // 9 [b_next] "m" (b_next) // 10 : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", //"r8", "r9", "r10", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) GEMMTRSM_UKR_FLUSH_CT( d ); } blis-0.9.0/kernels/penryn/3/bli_gemmtrsm_u_penryn_asm_d4x4.c000066400000000000000000000366711422157504600240630ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define BLIS_ASM_SYNTAX_ATT #include "bli_x86_asm_macros.h" #if 0 void bli_sgemmtrsm_u_penryn_asm_8x4 ( dim_t k0, float* restrict alpha, float* restrict a12, float* restrict a11, float* restrict b21, float* restrict b11, float* restrict c11, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { } #endif void bli_dgemmtrsm_u_penryn_asm_4x4 ( dim_t m, dim_t n, dim_t k0, double* restrict alpha, double* restrict a12, double* restrict a11, double* restrict b21, double* restrict b11, double* restrict c11, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; GEMMTRSM_UKR_SETUP_CT( d, 4, 4, false ); begin_asm() mov(var(a12), rax) // load address of a12. mov(var(b21), rbx) // load address of b21. //mov(var(b_next), r9) // load address of b_next. add(imm(8*16), rax) // increment pointers to allow byte add(imm(8*16), rbx) // offsets in the unrolled iterations. movaps(mem(rax, -8*16), xmm0) // initialize loop by pre-loading elements movaps(mem(rax, -7*16), xmm1) // of a and b. movaps(mem(rbx, -8*16), xmm2) xorpd(xmm3, xmm3) xorpd(xmm4, xmm4) xorpd(xmm5, xmm5) xorpd(xmm6, xmm6) xorpd(xmm8, xmm8) movaps(xmm8, xmm9) movaps(xmm8, xmm10) movaps(xmm8, xmm11) movaps(xmm8, xmm12) movaps(xmm8, xmm13) movaps(xmm8, xmm14) movaps(xmm8, xmm15) mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.CONSIDERKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.LOOPKITER) // MAIN LOOP prefetch(0, mem(rax, 1264)) addpd(xmm3, xmm11) // iteration 0 movaps(mem(rbx, -7*16), xmm3) addpd(xmm4, xmm15) movaps(xmm2, xmm4) pshufd(imm(0x4e), xmm2, xmm7) mulpd(xmm0, xmm2) mulpd(xmm1, xmm4) addpd(xmm5, xmm10) addpd(xmm6, xmm14) movaps(xmm7, xmm6) mulpd(xmm0, xmm7) mulpd(xmm1, xmm6) addpd(xmm2, xmm9) movaps(mem(rbx, -6*16), xmm2) addpd(xmm4, xmm13) movaps(xmm3, xmm4) pshufd(imm(0x4e), xmm3, xmm5) mulpd(xmm0, xmm3) mulpd(xmm1, xmm4) addpd(xmm7, xmm8) addpd(xmm6, xmm12) movaps(xmm5, xmm6) mulpd(xmm0, xmm5) movaps(mem(rax, -6*16), xmm0) mulpd(xmm1, xmm6) movaps(mem(rax, -5*16), xmm1) addpd(xmm3, xmm11) // iteration 1 movaps(mem(rbx, -5*16), xmm3) addpd(xmm4, xmm15) movaps(xmm2, xmm4) pshufd(imm(0x4e), xmm2, xmm7) mulpd(xmm0, xmm2) mulpd(xmm1, xmm4) addpd(xmm5, xmm10) addpd(xmm6, xmm14) movaps(xmm7, xmm6) mulpd(xmm0, xmm7) mulpd(xmm1, xmm6) addpd(xmm2, xmm9) movaps(mem(rbx, -4*16), xmm2) addpd(xmm4, xmm13) movaps(xmm3, xmm4) pshufd(imm(0x4e), xmm3, xmm5) mulpd(xmm0, xmm3) mulpd(xmm1, xmm4) addpd(xmm7, xmm8) addpd(xmm6, xmm12) movaps(xmm5, xmm6) mulpd(xmm0, xmm5) movaps(mem(rax, -4*16), xmm0) mulpd(xmm1, xmm6) movaps(mem(rax, -3*16), xmm1) prefetch(0, mem(rax, 1328)) addpd(xmm3, xmm11) // iteration 2 movaps(mem(rbx, -3*16), xmm3) addpd(xmm4, xmm15) movaps(xmm2, xmm4) pshufd(imm(0x4e), xmm2, xmm7) mulpd(xmm0, xmm2) mulpd(xmm1, xmm4) addpd(xmm5, xmm10) addpd(xmm6, xmm14) movaps(xmm7, xmm6) mulpd(xmm0, xmm7) mulpd(xmm1, xmm6) addpd(xmm2, xmm9) movaps(mem(rbx, -2*16), xmm2) addpd(xmm4, xmm13) movaps(xmm3, xmm4) pshufd(imm(0x4e), xmm3, xmm5) mulpd(xmm0, xmm3) mulpd(xmm1, xmm4) addpd(xmm7, xmm8) addpd(xmm6, xmm12) movaps(xmm5, xmm6) mulpd(xmm0, xmm5) movaps(mem(rax, -2*16), xmm0) mulpd(xmm1, xmm6) movaps(mem(rax, -1*16), xmm1) addpd(xmm3, xmm11) // iteration 3 movaps(mem(rbx, -1*16), xmm3) addpd(xmm4, xmm15) movaps(xmm2, xmm4) pshufd(imm(0x4e), xmm2, xmm7) mulpd(xmm0, xmm2) mulpd(xmm1, xmm4) addpd(xmm5, xmm10) addpd(xmm6, xmm14) movaps(xmm7, xmm6) mulpd(xmm0, xmm7) mulpd(xmm1, xmm6) add(imm(4*4*8), rax) // a += 4*4 (unroll x mr) addpd(xmm2, xmm9) movaps(mem(rbx, 0*16), xmm2) addpd(xmm4, xmm13) movaps(xmm3, xmm4) pshufd(imm(0x4e), xmm3, xmm5) mulpd(xmm0, xmm3) mulpd(xmm1, xmm4) add(imm(4*4*8), rbx) // b += 4*4 (unroll x nr) addpd(xmm7, xmm8) addpd(xmm6, xmm12) movaps(xmm5, xmm6) mulpd(xmm0, xmm5) movaps(mem(rax, -8*16), xmm0) mulpd(xmm1, xmm6) movaps(mem(rax, -7*16), xmm1) dec(rsi) // i -= 1; jne(.LOOPKITER) // iterate again if i != 0. label(.CONSIDERKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.POSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.LOOPKLEFT) // EDGE LOOP addpd(xmm3, xmm11) // iteration 0 movaps(mem(rbx, -7*16), xmm3) addpd(xmm4, xmm15) movaps(xmm2, xmm4) pshufd(imm(0x4e), xmm2, xmm7) mulpd(xmm0, xmm2) mulpd(xmm1, xmm4) addpd(xmm5, xmm10) addpd(xmm6, xmm14) movaps(xmm7, xmm6) mulpd(xmm0, xmm7) mulpd(xmm1, xmm6) addpd(xmm2, xmm9) movaps(mem(rbx, -6*16), xmm2) addpd(xmm4, xmm13) movaps(xmm3, xmm4) pshufd(imm(0x4e), xmm3, xmm5) mulpd(xmm0, xmm3) mulpd(xmm1, xmm4) addpd(xmm7, xmm8) addpd(xmm6, xmm12) movaps(xmm5, xmm6) mulpd(xmm0, xmm5) movaps(mem(rax, -6*16), xmm0) mulpd(xmm1, xmm6) movaps(mem(rax, -5*16), xmm1) add(imm(4*1*8), rax) // a += 4 (1 x mr) add(imm(4*1*8), rbx) // b += 4 (1 x nr) dec(rsi) // i -= 1; jne(.LOOPKLEFT) // iterate again if i != 0. label(.POSTACCUM) addpd(xmm3, xmm11) addpd(xmm4, xmm15) addpd(xmm5, xmm10) addpd(xmm6, xmm14) mov(var(b11), rbx) // load address of b11. // xmm8: xmm9: xmm10: xmm11: // ( ab01 ( ab00 ( ab03 ( ab02 // ab10 ) ab11 ) ab12 ) ab13 ) // // xmm12: xmm13: xmm14: xmm15: // ( ab21 ( ab20 ( ab23 ( ab22 // ab30 ) ab31 ) ab32 ) ab33 ) movaps(xmm9, xmm0) movaps(xmm8, xmm1) unpcklpd(xmm8, xmm0) unpckhpd(xmm9, xmm1) movaps(xmm11, xmm4) movaps(xmm10, xmm5) unpcklpd(xmm10, xmm4) unpckhpd(xmm11, xmm5) movaps(xmm13, xmm2) movaps(xmm12, xmm3) unpcklpd(xmm12, xmm2) unpckhpd(xmm13, xmm3) movaps(xmm15, xmm6) movaps(xmm14, xmm7) unpcklpd(xmm14, xmm6) unpckhpd(xmm15, xmm7) // xmm0: ( ab00 ab01 ) xmm4: ( ab02 ab03 ) // xmm1: ( ab10 ab11 ) xmm5: ( ab12 ab13 ) // xmm2: ( ab20 ab21 ) xmm6: ( ab22 ab23 ) // xmm3: ( ab30 ab31 ) xmm7: ( ab32 ab33 ) mov(var(alpha), rax) // load address of alpha movddup(mem(rax), xmm15) // load alpha and duplicate movaps(mem(rbx, 0*16), xmm8) movaps(mem(rbx, 1*16), xmm12) mulpd(xmm15, xmm8) // xmm8 = alpha * ( beta00 beta01 ) mulpd(xmm15, xmm12) // xmm12 = alpha * ( beta02 beta03 ) movaps(mem(rbx, 2*16), xmm9) movaps(mem(rbx, 3*16), xmm13) mulpd(xmm15, xmm9) // xmm9 = alpha * ( beta10 beta11 ) mulpd(xmm15, xmm13) // xmm13 = alpha * ( beta12 beta13 ) movaps(mem(rbx, 4*16), xmm10) movaps(mem(rbx, 5*16), xmm14) mulpd(xmm15, xmm10) // xmm10 = alpha * ( beta20 beta21 ) mulpd(xmm15, xmm14) // xmm14 = alpha * ( beta22 beta23 ) movaps(mem(rbx, 6*16), xmm11) mulpd(xmm15, xmm11) // xmm11 = alpha * ( beta30 beta31 ) mulpd(mem(rbx, 7*16), xmm15) // xmm15 = alpha * ( beta32 beta33 ) // (Now scaled by alpha:) // xmm8: ( beta00 beta01 ) xmm12: ( beta02 beta03 ) // xmm9: ( beta10 beta11 ) xmm13: ( beta12 beta13 ) // xmm10: ( beta20 beta21 ) xmm14: ( beta22 beta23 ) // xmm11: ( beta30 beta31 ) xmm15: ( beta32 beta33 ) subpd(xmm0, xmm8) // xmm8 -= xmm0 subpd(xmm1, xmm9) // xmm9 -= xmm1 subpd(xmm2, xmm10) // xmm10 -= xmm2 subpd(xmm3, xmm11) // xmm11 -= xmm3 subpd(xmm4, xmm12) // xmm12 -= xmm4 subpd(xmm5, xmm13) // xmm13 -= xmm5 subpd(xmm6, xmm14) // xmm14 -= xmm6 subpd(xmm7, xmm15) // xmm15 -= xmm7 label(.TRSM) mov(var(a11), rax) // load address of a11 mov(var(c11), rcx) // load address of c11 mov(var(rs_c), rsi) // load rs_c mov(var(cs_c), rdi) // load cs_c sal(imm(3), rsi) // rs_c *= sizeof( double ) sal(imm(3), rdi) // cs_c *= sizeof( double ) add(rsi, rcx) // c11 += (4-1)*rs_c add(rsi, rcx) add(rsi, rcx) lea(mem(rcx, rdi, 2), rdx) // c11_2 = c11 + 2*cs_c; // iteration 0 movddup(mem(3+3*4)*8(rax), xmm3) // load xmm3 = (1/alpha33) #ifdef BLIS_ENABLE_TRSM_PREINVERSION mulpd(xmm3, xmm11) // xmm11 *= (1/alpha33); mulpd(xmm3, xmm15) // xmm15 *= (1/alpha33); #else divpd(xmm3, xmm11) // xmm11 /= alpha33; divpd(xmm3, xmm15) // xmm15 /= alpha33; #endif movaps(xmm11, mem(rbx, 6*16)) // store ( beta30 beta31 ) = xmm11 movaps(xmm15, mem(rbx, 7*16)) // store ( beta32 beta33 ) = xmm15 movlpd(xmm11, mem(rcx)) // store ( gamma30 ) = xmm11[0] movhpd(xmm11, mem(rcx, rdi, 1)) // store ( gamma31 ) = xmm11[1] movlpd(xmm15, mem(rdx)) // store ( gamma32 ) = xmm15[0] movhpd(xmm15, mem(rdx, rdi, 1)) // store ( gamma33 ) = xmm15[1] sub(rsi, rcx) // c11 -= rs_c sub(rsi, rdx) // c11_2 -= rs_c // iteration 1 movddup(mem(2+2*4)*8(rax), xmm2) // load xmm2 = (1/alpha22) movddup(mem(2+3*4)*8(rax), xmm3) // load xmm3 = alpha23 movaps(xmm3, xmm7) // xmm7 = xmm3 mulpd(xmm11, xmm3) // xmm3 = alpha23 * ( beta30 beta31 ) mulpd(xmm15, xmm7) // xmm7 = alpha23 * ( beta32 beta33 ) subpd(xmm3, xmm10) // xmm10 -= xmm3 subpd(xmm7, xmm14) // xmm14 -= xmm7 #ifdef BLIS_ENABLE_TRSM_PREINVERSION mulpd(xmm2, xmm10) // xmm10 *= (1/alpha22); mulpd(xmm2, xmm14) // xmm14 *= (1/alpha22); #else divpd(xmm2, xmm10) // xmm10 /= alpha22; divpd(xmm2, xmm14) // xmm14 /= alpha22; #endif movaps(xmm10, mem(rbx, 4*16)) // store ( beta20 beta21 ) = xmm10 movaps(xmm14, mem(rbx, 5*16)) // store ( beta22 beta23 ) = xmm14 movlpd(xmm10, mem(rcx)) // store ( gamma20 ) = xmm10[0] movhpd(xmm10, mem(rcx, rdi, 1)) // store ( gamma21 ) = xmm10[1] movlpd(xmm14, mem(rdx)) // store ( gamma22 ) = xmm14[0] movhpd(xmm14, mem(rdx, rdi, 1)) // store ( gamma23 ) = xmm14[1] sub(rsi, rcx) // c11 -= rs_c sub(rsi, rdx) // c11_2 -= rs_c // iteration 2 movddup(mem(1+1*4)*8(rax), xmm1) // load xmm1 = (1/alpha11) movddup(mem(1+2*4)*8(rax), xmm2) // load xmm2 = alpha12 movddup(mem(1+3*4)*8(rax), xmm3) // load xmm3 = alpha13 movaps(xmm2, xmm6) // xmm6 = xmm2 movaps(xmm3, xmm7) // xmm7 = xmm3 mulpd(xmm10, xmm2) // xmm2 = alpha12 * ( beta20 beta21 ) mulpd(xmm14, xmm6) // xmm6 = alpha12 * ( beta22 beta23 ) mulpd(xmm11, xmm3) // xmm3 = alpha13 * ( beta30 beta31 ) mulpd(xmm15, xmm7) // xmm7 = alpha13 * ( beta32 beta33 ) addpd(xmm3, xmm2) // xmm2 += xmm3; addpd(xmm7, xmm6) // xmm6 += xmm7; subpd(xmm2, xmm9) // xmm9 -= xmm2 subpd(xmm6, xmm13) // xmm13 -= xmm6 #ifdef BLIS_ENABLE_TRSM_PREINVERSION mulpd(xmm1, xmm9) // xmm9 *= (1/alpha11); mulpd(xmm1, xmm13) // xmm13 *= (1/alpha11); #else divpd(xmm1, xmm9) // xmm9 /= alpha11; divpd(xmm1, xmm13) // xmm13 /= alpha11; #endif movaps(xmm9, mem(rbx, 2*16)) // store ( beta10 beta11 ) = xmm9 movaps(xmm13, mem(rbx, 3*16)) // store ( beta12 beta13 ) = xmm13 movlpd(xmm9, mem(rcx)) // store ( gamma10 ) = xmm9[0] movhpd(xmm9, mem(rcx, rdi, 1)) // store ( gamma11 ) = xmm9[1] movlpd(xmm13, mem(rdx)) // store ( gamma12 ) = xmm13[0] movhpd(xmm13, mem(rdx, rdi, 1)) // store ( gamma13 ) = xmm13[1] sub(rsi, rcx) // c11 -= rs_c sub(rsi, rdx) // c11_2 -= rs_c // iteration 3 movddup(mem(0+0*4)*8(rax), xmm0) // load xmm0 = (1/alpha00) movddup(mem(0+1*4)*8(rax), xmm1) // load xmm1 = alpha01 movddup(mem(0+2*4)*8(rax), xmm2) // load xmm2 = alpha02 movddup(mem(0+3*4)*8(rax), xmm3) // load xmm3 = alpha03 movaps(xmm1, xmm5) // xmm5 = xmm1 movaps(xmm2, xmm6) // xmm6 = xmm2 movaps(xmm3, xmm7) // xmm7 = xmm3 mulpd(xmm9, xmm1) // xmm1 = alpha01 * ( beta10 beta11 ) mulpd(xmm13, xmm5) // xmm5 = alpha01 * ( beta12 beta13 ) mulpd(xmm10, xmm2) // xmm2 = alpha02 * ( beta20 beta21 ) mulpd(xmm14, xmm6) // xmm6 = alpha02 * ( beta22 beta23 ) mulpd(xmm11, xmm3) // xmm3 = alpha03 * ( beta30 beta31 ) mulpd(xmm15, xmm7) // xmm7 = alpha03 * ( beta32 beta33 ) addpd(xmm2, xmm1) // xmm1 += xmm2; addpd(xmm6, xmm5) // xmm5 += xmm6; addpd(xmm3, xmm1) // xmm1 += xmm3; addpd(xmm7, xmm5) // xmm5 += xmm7; subpd(xmm1, xmm8) // xmm8 -= xmm1 subpd(xmm5, xmm12) // xmm12 -= xmm5 #ifdef BLIS_ENABLE_TRSM_PREINVERSION mulpd(xmm0, xmm8) // xmm8 *= (1/alpha00); mulpd(xmm0, xmm12) // xmm12 *= (1/alpha00); #else divpd(xmm0, xmm8) // xmm8 /= alpha00; divpd(xmm0, xmm12) // xmm12 /= alpha00; #endif movaps(xmm8, mem(rbx, 0*16)) // store ( beta00 beta01 ) = xmm8 movaps(xmm12, mem(rbx, 1*16)) // store ( beta02 beta03 ) = xmm12 movlpd(xmm8, mem(rcx)) // store ( gamma00 ) = xmm8[0] movhpd(xmm8, mem(rcx, rdi, 1)) // store ( gamma01 ) = xmm8[1] movlpd(xmm12, mem(rdx)) // store ( gamma02 ) = xmm12[0] movhpd(xmm12, mem(rdx, rdi, 1)) // store ( gamma03 ) = xmm12[1] end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), // 0 [k_left] "m" (k_left), // 1 [a12] "m" (a12), // 2 [a11] "m" (a11), // 3 [b21] "m" (b21), // 4 [b11] "m" (b11), // 5 [c11] "m" (c11), // 6 [rs_c] "m" (rs_c), // 7 [cs_c] "m" (cs_c), // 8 [alpha] "m" (alpha), // 9 [b_next] "m" (b_next) // 10 : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) GEMMTRSM_UKR_FLUSH_CT( d ); } blis-0.9.0/kernels/penryn/3/bli_trsm_l_penryn_asm_d4x4.c000066400000000000000000000174761422157504600232060ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define BLIS_ASM_SYNTAX_ATT #include "bli_x86_asm_macros.h" #if 0 void bli_strsm_l_penryn_asm_8x4 ( float* restrict a11, float* restrict b11, float* restrict c11, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { } #endif void bli_dtrsm_l_penryn_asm_4x4 ( double* restrict a11, double* restrict b11, double* restrict c11, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; begin_asm() mov(var(b11), rbx) // load address of b11. movaps(mem(rbx, 0*16), xmm8) // xmm8 = ( beta00 beta01 ) movaps(mem(rbx, 1*16), xmm12) // xmm9 = ( beta02 beta03 ) movaps(mem(rbx, 2*16), xmm9) // xmm10 = ( beta10 beta11 ) movaps(mem(rbx, 3*16), xmm13) // xmm11 = ( beta12 beta13 ) movaps(mem(rbx, 4*16), xmm10) // xmm12 = ( beta20 beta21 ) movaps(mem(rbx, 5*16), xmm14) // xmm13 = ( beta22 beta23 ) movaps(mem(rbx, 6*16), xmm11) // xmm14 = ( beta30 beta31 ) movaps(mem(rbx, 7*16), xmm15) // xmm15 = ( beta32 beta33 ) mov(var(a11), rax) // load address of a11 mov(var(c11), rcx) // load address of c11 mov(var(rs_c), rsi) // load rs_c mov(var(cs_c), rdi) // load cs_c sal(imm(3), rsi) // rs_c *= sizeof( double ) sal(imm(3), rdi) // cs_c *= sizeof( double ) lea(mem(rcx, rdi, 2), rdx) // c11_2 = c11 + 2*cs_c // iteration 0 movddup(mem(0+0*4)*8(rax), xmm0) // load xmm0 = (1/alpha00) mulpd(xmm0, xmm8) // xmm8 *= (1/alpha00); mulpd(xmm0, xmm12) // xmm12 *= (1/alpha00); movaps(xmm8, mem(rbx, 0*16)) // store ( beta00 beta01 ) = xmm8 movaps(xmm12, mem(rbx, 1*16)) // store ( beta02 beta03 ) = xmm12 movlpd(xmm8, mem(rcx)) // store ( gamma00 ) = xmm8[0] movhpd(xmm8, mem(rcx, rdi, 1)) // store ( gamma01 ) = xmm8[1] movlpd(xmm12, mem(rdx)) // store ( gamma02 ) = xmm12[0] movhpd(xmm12, mem(rdx, rdi, 1)) // store ( gamma03 ) = xmm12[1] add(rsi, rcx) // c11 += rs_c add(rsi, rdx) // c11_2 += rs_c // iteration 1 movddup(mem(1+0*4)*8(rax), xmm0) // load xmm0 = alpha10 movddup(mem(1+1*4)*8(rax), xmm1) // load xmm1 = (1/alpha11) movaps(xmm0, xmm4) // xmm4 = xmm0 mulpd(xmm8, xmm0) // xmm0 = alpha10 * ( beta00 beta01 ) mulpd(xmm12, xmm4) // xmm4 = alpha10 * ( beta02 beta03 ) subpd(xmm0, xmm9) // xmm9 -= xmm0 subpd(xmm4, xmm13) // xmm13 -= xmm4 mulpd(xmm1, xmm9) // xmm9 *= (1/alpha11); mulpd(xmm1, xmm13) // xmm13 *= (1/alpha11); movaps(xmm9, mem(rbx, 2*16)) // store ( beta10 beta11 ) = xmm9 movaps(xmm13, mem(rbx, 3*16)) // store ( beta12 beta13 ) = xmm13 movlpd(xmm9, mem(rcx)) // store ( gamma10 ) = xmm9[0] movhpd(xmm9, mem(rcx, rdi, 1)) // store ( gamma11 ) = xmm9[1] movlpd(xmm13, mem(rdx)) // store ( gamma12 ) = xmm13[0] movhpd(xmm13, mem(rdx, rdi, 1)) // store ( gamma13 ) = xmm13[1] add(rsi, rcx) // c11 += rs_c add(rsi, rdx) // c11_2 += rs_c // iteration 2 movddup(mem(2+0*4)*8(rax), xmm0) // load xmm0 = alpha20 movddup(mem(2+1*4)*8(rax), xmm1) // load xmm1 = alpha21 movddup(mem(2+2*4)*8(rax), xmm2) // load xmm2 = (1/alpha22) movaps(xmm0, xmm4) // xmm4 = xmm0 movaps(xmm1, xmm5) // xmm5 = xmm1 mulpd(xmm8, xmm0) // xmm0 = alpha20 * ( beta00 beta01 ) mulpd(xmm12, xmm4) // xmm4 = alpha20 * ( beta02 beta03 ) mulpd(xmm9, xmm1) // xmm1 = alpha21 * ( beta10 beta11 ) mulpd(xmm13, xmm5) // xmm5 = alpha21 * ( beta12 beta13 ) addpd(xmm1, xmm0) // xmm0 += xmm1; addpd(xmm5, xmm4) // xmm4 += xmm5; subpd(xmm0, xmm10) // xmm10 -= xmm0 subpd(xmm4, xmm14) // xmm14 -= xmm4 mulpd(xmm2, xmm10) // xmm10 *= (1/alpha22); mulpd(xmm2, xmm14) // xmm14 *= (1/alpha22); movaps(xmm10, mem(rbx, 4*16)) // store ( beta20 beta21 ) = xmm10 movaps(xmm14, mem(rbx, 5*16)) // store ( beta22 beta23 ) = xmm14 movlpd(xmm10, mem(rcx)) // store ( gamma20 ) = xmm10[0] movhpd(xmm10, mem(rcx, rdi, 1)) // store ( gamma21 ) = xmm10[1] movlpd(xmm14, mem(rdx)) // store ( gamma22 ) = xmm14[0] movhpd(xmm14, mem(rdx, rdi, 1)) // store ( gamma23 ) = xmm14[1] add(rsi, rcx) // c11 += rs_c add(rsi, rdx) // c11_2 += rs_c // iteration 3 movddup(mem(3+0*4)*8(rax), xmm0) // load xmm0 = alpha30 movddup(mem(3+1*4)*8(rax), xmm1) // load xmm1 = alpha31 movddup(mem(3+2*4)*8(rax), xmm2) // load xmm2 = alpha32 movddup(mem(3+3*4)*8(rax), xmm3) // load xmm3 = (1/alpha33) movaps(xmm0, xmm4) // xmm4 = xmm0 movaps(xmm1, xmm5) // xmm5 = xmm1 movaps(xmm2, xmm6) // xmm6 = xmm2 mulpd(xmm8, xmm0) // xmm0 = alpha30 * ( beta00 beta01 ) mulpd(xmm12, xmm4) // xmm4 = alpha30 * ( beta02 beta03 ) mulpd(xmm9, xmm1) // xmm1 = alpha31 * ( beta10 beta11 ) mulpd(xmm13, xmm5) // xmm5 = alpha31 * ( beta12 beta13 ) mulpd(xmm10, xmm2) // xmm2 = alpha32 * ( beta20 beta21 ) mulpd(xmm14, xmm6) // xmm6 = alpha32 * ( beta22 beta23 ) addpd(xmm1, xmm0) // xmm0 += xmm1; addpd(xmm5, xmm4) // xmm4 += xmm5; addpd(xmm2, xmm0) // xmm0 += xmm2; addpd(xmm6, xmm4) // xmm4 += xmm6; subpd(xmm0, xmm11) // xmm11 -= xmm0 subpd(xmm4, xmm15) // xmm15 -= xmm4 mulpd(xmm3, xmm11) // xmm11 *= (1/alpha33); mulpd(xmm3, xmm15) // xmm15 *= (1/alpha33); movaps(xmm11, mem(rbx, 6*16)) // store ( beta30 beta31 ) = xmm11 movaps(xmm15, mem(rbx, 7*16)) // store ( beta32 beta33 ) = xmm15 movlpd(xmm11, mem(rcx)) // store ( gamma30 ) = xmm11[0] movhpd(xmm11, mem(rcx, rdi, 1)) // store ( gamma31 ) = xmm11[1] movlpd(xmm15, mem(rdx)) // store ( gamma32 ) = xmm15[0] movhpd(xmm15, mem(rdx, rdi, 1)) // store ( gamma33 ) = xmm15[1] end_asm( : // output operands (none) : // input operands [a11] "m" (a11), // 0 [b11] "m" (b11), // 1 [c11] "m" (c11), // 2 [rs_c] "m" (rs_c), // 3 [cs_c] "m" (cs_c) // 4 : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", //"r8", "r9", "r10", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } blis-0.9.0/kernels/penryn/3/bli_trsm_u_penryn_asm_d4x4.c000066400000000000000000000175241422157504600232110ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define BLIS_ASM_SYNTAX_ATT #include "bli_x86_asm_macros.h" #if 0 void bli_strsm_u_penryn_asm_8x4 ( float* restrict a11, float* restrict b11, float* restrict c11, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { } #endif void bli_dtrsm_u_penryn_asm_4x4 ( double* restrict a11, double* restrict b11, double* restrict c11, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; begin_asm() mov(var(b11), rbx) // load address of b11. movaps(mem(rbx, 0*16), xmm8) // xmm8 = ( beta00 beta01 ) movaps(mem(rbx, 1*16), xmm12) // xmm9 = ( beta02 beta03 ) movaps(mem(rbx, 2*16), xmm9) // xmm10 = ( beta10 beta11 ) movaps(mem(rbx, 3*16), xmm13) // xmm11 = ( beta12 beta13 ) movaps(mem(rbx, 4*16), xmm10) // xmm12 = ( beta20 beta21 ) movaps(mem(rbx, 5*16), xmm14) // xmm13 = ( beta22 beta23 ) movaps(mem(rbx, 6*16), xmm11) // xmm14 = ( beta30 beta31 ) movaps(mem(rbx, 7*16), xmm15) // xmm15 = ( beta32 beta33 ) mov(var(a11), rax) // load address of a11 mov(var(c11), rcx) // load address of c11 mov(var(rs_c), rsi) // load rs_c mov(var(cs_c), rdi) // load cs_c sal(imm(3), rsi) // rs_c *= sizeof( double ) sal(imm(3), rdi) // cs_c *= sizeof( double ) add(rsi, rcx) // c11 += (4-1)*rs_c add(rsi, rcx) add(rsi, rcx) lea(mem(rcx, rdi, 2), rdx) // c11_2 = c11 + 2*cs_c; // iteration 0 movddup(mem(3+3*4)*8(rax), xmm3) // load xmm3 = (1/alpha33) mulpd(xmm3, xmm11) // xmm11 *= (1/alpha33); mulpd(xmm3, xmm15) // xmm15 *= (1/alpha33); movaps(xmm11, mem(rbx, 6*16)) // store ( beta30 beta31 ) = xmm11 movaps(xmm15, mem(rbx, 7*16)) // store ( beta32 beta33 ) = xmm15 movlpd(xmm11, mem(rcx)) // store ( gamma30 ) = xmm11[0] movhpd(xmm11, mem(rcx, rdi, 1)) // store ( gamma31 ) = xmm11[1] movlpd(xmm15, mem(rdx)) // store ( gamma32 ) = xmm15[0] movhpd(xmm15, mem(rdx, rdi, 1)) // store ( gamma33 ) = xmm15[1] sub(rsi, rcx) // c11 -= rs_c sub(rsi, rdx) // c11_2 -= rs_c // iteration 1 movddup(mem(2+2*4)*8(rax), xmm2) // load xmm2 = (1/alpha22) movddup(mem(2+3*4)*8(rax), xmm3) // load xmm3 = alpha23 movaps(xmm3, xmm7) // xmm7 = xmm3 mulpd(xmm11, xmm3) // xmm3 = alpha23 * ( beta30 beta31 ) mulpd(xmm15, xmm7) // xmm7 = alpha23 * ( beta32 beta33 ) subpd(xmm3, xmm10) // xmm10 -= xmm3 subpd(xmm7, xmm14) // xmm14 -= xmm7 mulpd(xmm2, xmm10) // xmm10 *= (1/alpha22); mulpd(xmm2, xmm14) // xmm14 *= (1/alpha22); movaps(xmm10, mem(rbx, 4*16)) // store ( beta20 beta21 ) = xmm10 movaps(xmm14, mem(rbx, 5*16)) // store ( beta22 beta23 ) = xmm14 movlpd(xmm10, mem(rcx)) // store ( gamma20 ) = xmm10[0] movhpd(xmm10, mem(rcx, rdi, 1)) // store ( gamma21 ) = xmm10[1] movlpd(xmm14, mem(rdx)) // store ( gamma22 ) = xmm14[0] movhpd(xmm14, mem(rdx, rdi, 1)) // store ( gamma23 ) = xmm14[1] sub(rsi, rcx) // c11 -= rs_c sub(rsi, rdx) // c11_2 -= rs_c // iteration 2 movddup(mem(1+1*4)*8(rax), xmm1) // load xmm1 = (1/alpha11) movddup(mem(1+2*4)*8(rax), xmm2) // load xmm2 = alpha12 movddup(mem(1+3*4)*8(rax), xmm3) // load xmm3 = alpha13 movaps(xmm2, xmm6) // xmm6 = xmm2 movaps(xmm3, xmm7) // xmm7 = xmm3 mulpd(xmm10, xmm2) // xmm2 = alpha12 * ( beta20 beta21 ) mulpd(xmm14, xmm6) // xmm6 = alpha12 * ( beta22 beta23 ) mulpd(xmm11, xmm3) // xmm3 = alpha13 * ( beta30 beta31 ) mulpd(xmm15, xmm7) // xmm7 = alpha13 * ( beta32 beta33 ) addpd(xmm3, xmm2) // xmm2 += xmm3; addpd(xmm7, xmm6) // xmm6 += xmm7; subpd(xmm2, xmm9) // xmm9 -= xmm2 subpd(xmm6, xmm13) // xmm13 -= xmm6 mulpd(xmm1, xmm9) // xmm9 *= (1/alpha11); mulpd(xmm1, xmm13) // xmm13 *= (1/alpha11); movaps(xmm9, mem(rbx, 2*16)) // store ( beta10 beta11 ) = xmm9 movaps(xmm13, mem(rbx, 3*16)) // store ( beta12 beta13 ) = xmm13 movlpd(xmm9, mem(rcx)) // store ( gamma10 ) = xmm9[0] movhpd(xmm9, mem(rcx, rdi, 1)) // store ( gamma11 ) = xmm9[1] movlpd(xmm13, mem(rdx)) // store ( gamma12 ) = xmm13[0] movhpd(xmm13, mem(rdx, rdi, 1)) // store ( gamma13 ) = xmm13[1] sub(rsi, rcx) // c11 -= rs_c sub(rsi, rdx) // c11_2 -= rs_c // iteration 3 movddup(mem(0+0*4)*8(rax), xmm0) // load xmm0 = (1/alpha00) movddup(mem(0+1*4)*8(rax), xmm1) // load xmm1 = alpha01 movddup(mem(0+2*4)*8(rax), xmm2) // load xmm2 = alpha02 movddup(mem(0+3*4)*8(rax), xmm3) // load xmm3 = alpha03 movaps(xmm1, xmm5) // xmm5 = xmm1 movaps(xmm2, xmm6) // xmm6 = xmm2 movaps(xmm3, xmm7) // xmm7 = xmm3 mulpd(xmm9, xmm1) // xmm1 = alpha01 * ( beta10 beta11 ) mulpd(xmm13, xmm5) // xmm5 = alpha01 * ( beta12 beta13 ) mulpd(xmm10, xmm2) // xmm2 = alpha02 * ( beta20 beta21 ) mulpd(xmm14, xmm6) // xmm6 = alpha02 * ( beta22 beta23 ) mulpd(xmm11, xmm3) // xmm3 = alpha03 * ( beta30 beta31 ) mulpd(xmm15, xmm7) // xmm7 = alpha03 * ( beta32 beta33 ) addpd(xmm2, xmm1) // xmm1 += xmm2; addpd(xmm6, xmm5) // xmm5 += xmm6; addpd(xmm3, xmm1) // xmm1 += xmm3; addpd(xmm7, xmm5) // xmm5 += xmm7; subpd(xmm1, xmm8) // xmm8 -= xmm1 subpd(xmm5, xmm12) // xmm12 -= xmm5 mulpd(xmm0, xmm8) // xmm8 *= (1/alpha00); mulpd(xmm0, xmm12) // xmm12 *= (1/alpha00); movaps(xmm8, mem(rbx, 0*16)) // store ( beta00 beta01 ) = xmm8 movaps(xmm12, mem(rbx, 1*16)) // store ( beta02 beta03 ) = xmm12 movlpd(xmm8, mem(rcx)) // store ( gamma00 ) = xmm8[0] movhpd(xmm8, mem(rcx, rdi, 1)) // store ( gamma01 ) = xmm8[1] movlpd(xmm12, mem(rdx)) // store ( gamma02 ) = xmm12[0] movhpd(xmm12, mem(rdx, rdi, 1)) // store ( gamma03 ) = xmm12[1] end_asm( : // output operands (none) : // input operands [a11] "m" (a11), // 0 [b11] "m" (b11), // 1 [c11] "m" (c11), // 2 [rs_c] "m" (rs_c), // 3 [cs_c] "m" (cs_c) // 4 : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } blis-0.9.0/kernels/penryn/bli_kernels_penryn.h000066400000000000000000000037201422157504600214740ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ GEMM_UKR_PROT( float, s, gemm_penryn_asm_8x4 ) GEMM_UKR_PROT( double, d, gemm_penryn_asm_4x4 ) GEMMTRSM_UKR_PROT( double, d, gemmtrsm_l_penryn_asm_4x4 ) GEMMTRSM_UKR_PROT( double, d, gemmtrsm_u_penryn_asm_4x4 ) TRSM_UKR_PROT( double, d, trsm_l_penryn_asm_4x4 ) TRSM_UKR_PROT( double, d, trsm_u_penryn_asm_4x4 ) blis-0.9.0/kernels/piledriver/000077500000000000000000000000001422157504600162675ustar00rootroot00000000000000blis-0.9.0/kernels/piledriver/3/000077500000000000000000000000001422157504600164315ustar00rootroot00000000000000blis-0.9.0/kernels/piledriver/3/bli_gemm_piledriver_asm_d8x3.c000066400000000000000000001360051422157504600243100ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ /* NOTE: The micro-kernels in this file were partially inspired by portions of code found in OpenBLAS 0.2.12 (http://www.openblas.net/). -FGVZ */ #include "blis.h" #define BLIS_ASM_SYNTAX_ATT #include "bli_x86_asm_macros.h" void bli_sgemm_piledriver_asm_16x3 ( dim_t m, dim_t n, dim_t k, float* restrict alpha, float* restrict a, float* restrict b, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { void* a_next = bli_auxinfo_next_a( data ); void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k / 8; uint64_t k_left = k % 8; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; GEMM_UKR_SETUP_CT( s, 16, 3, false ); begin_asm() mov(var(a), rax) // load address of a. mov(var(b), rbx) // load address of b. mov(var(b_next), r15) // load address of b_next. mov(var(a_next), r14) // load address of a_next. prefetch(0, mem(rbx, 128)) // prefetch b prefetch(0, mem(rbx, 64+128)) // prefetch b prefetch(0, mem(rbx, 128+128)) // prefetch b add(imm(32*4), rax) add(imm(12*4), rbx) mov(var(c), rcx) // load address of c mov(var(cs_c), rdi) // load cs_c lea(mem(, rdi, 4), rdi) // cs_c *= sizeof(float) lea(mem(rcx, rdi, 1), r10) // load address of c + 1*cs_c; lea(mem(rcx, rdi, 2), r11) // load address of c + 2*cs_c; vbroadcastss(mem(rbx, -12*4), xmm1) vbroadcastss(mem(rbx, -11*4), xmm2) vbroadcastss(mem(rbx, -10*4), xmm3) vxorps(xmm4, xmm4, xmm4) vxorps(xmm5, xmm5, xmm5) vxorps(xmm6, xmm6, xmm6) vxorps(xmm7, xmm7, xmm7) vxorps(xmm8, xmm8, xmm8) vxorps(xmm9, xmm9, xmm9) vxorps(xmm10, xmm10, xmm10) vxorps(xmm11, xmm11, xmm11) vxorps(xmm12, xmm12, xmm12) vxorps(xmm13, xmm13, xmm13) vxorps(xmm14, xmm14, xmm14) vxorps(xmm15, xmm15, xmm15) mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP je(.SCONSIDKLEFT) // if i == 0, jump to k_left code. prefetch(0, mem(rbx, 16+192)) // prefetch b // iteration 0 vmovaps(mem(rax, -32*4), xmm0) prefetch(0, mem(rax, 384)) vfmadd231ps(xmm1, xmm0, xmm4) vfmadd231ps(xmm2, xmm0, xmm5) vfmadd231ps(xmm3, xmm0, xmm6) vmovaps(mem(rax, -28*4), xmm0) vfmadd231ps(xmm1, xmm0, xmm7) vfmadd231ps(xmm2, xmm0, xmm8) vfmadd231ps(xmm3, xmm0, xmm9) vmovaps(mem(rax, -24*4), xmm0) vfmadd231ps(xmm1, xmm0, xmm10) vfmadd231ps(xmm2, xmm0, xmm11) vfmadd231ps(xmm3, xmm0, xmm12) vmovaps(mem(rax, -20*4), xmm0) vfmadd231ps(xmm1, xmm0, xmm13) vbroadcastss(mem(rbx, -9*4), xmm1) vfmadd231ps(xmm2, xmm0, xmm14) vbroadcastss(mem(rbx, -8*4), xmm2) vfmadd231ps(xmm3, xmm0, xmm15) // iteration 1 vmovaps(mem(rax, -16*4), xmm0) vbroadcastss(mem(rbx, -7*4), xmm3) prefetch(0, mem(rax, 64+384)) vfmadd231ps(xmm1, xmm0, xmm4) vfmadd231ps(xmm2, xmm0, xmm5) vfmadd231ps(xmm3, xmm0, xmm6) vmovaps(mem(rax, -12*4), xmm0) vfmadd231ps(xmm1, xmm0, xmm7) vfmadd231ps(xmm2, xmm0, xmm8) vfmadd231ps(xmm3, xmm0, xmm9) vmovaps(mem(rax, -8*4), xmm0) vfmadd231ps(xmm1, xmm0, xmm10) vfmadd231ps(xmm2, xmm0, xmm11) vfmadd231ps(xmm3, xmm0, xmm12) vmovaps(mem(rax, -4*4), xmm0) vfmadd231ps(xmm1, xmm0, xmm13) vbroadcastss(mem(rbx, -6*4), xmm1) vfmadd231ps(xmm2, xmm0, xmm14) vbroadcastss(mem(rbx, -5*4), xmm2) vfmadd231ps(xmm3, xmm0, xmm15) // iteration 2 vmovaps(mem(rax, 0*4), xmm0) vbroadcastss(mem(rbx, -4*4), xmm3) prefetch(0, mem(rax, 128+384)) vfmadd231ps(xmm1, xmm0, xmm4) vfmadd231ps(xmm2, xmm0, xmm5) vfmadd231ps(xmm3, xmm0, xmm6) vmovaps(mem(rax, 4*4), xmm0) vfmadd231ps(xmm1, xmm0, xmm7) vfmadd231ps(xmm2, xmm0, xmm8) vfmadd231ps(xmm3, xmm0, xmm9) vmovaps(mem(rax, 8*4), xmm0) vfmadd231ps(xmm1, xmm0, xmm10) vfmadd231ps(xmm2, xmm0, xmm11) vfmadd231ps(xmm3, xmm0, xmm12) vmovaps(mem(rax, 12*4), xmm0) vfmadd231ps(xmm1, xmm0, xmm13) vbroadcastss(mem(rbx, -3*4), xmm1) vfmadd231ps(xmm2, xmm0, xmm14) vbroadcastss(mem(rbx, -2*4), xmm2) vfmadd231ps(xmm3, xmm0, xmm15) // iteration 3 vmovaps(mem(rax, 16*4), xmm0) vbroadcastss(mem(rbx, -1*4), xmm3) prefetch(0, mem(rax, 192+384)) vfmadd231ps(xmm1, xmm0, xmm4) vfmadd231ps(xmm2, xmm0, xmm5) vfmadd231ps(xmm3, xmm0, xmm6) vmovaps(mem(rax, 20*4), xmm0) vfmadd231ps(xmm1, xmm0, xmm7) vfmadd231ps(xmm2, xmm0, xmm8) vfmadd231ps(xmm3, xmm0, xmm9) vmovaps(mem(rax, 24*4), xmm0) vfmadd231ps(xmm1, xmm0, xmm10) vfmadd231ps(xmm2, xmm0, xmm11) vfmadd231ps(xmm3, xmm0, xmm12) vmovaps(mem(rax, 28*4), xmm0) vfmadd231ps(xmm1, xmm0, xmm13) vbroadcastss(mem(rbx, 0*4), xmm1) vfmadd231ps(xmm2, xmm0, xmm14) vbroadcastss(mem(rbx, 1*4), xmm2) vfmadd231ps(xmm3, xmm0, xmm15) add(imm(4*16*4), rax) // a += 4*16 (unroll x mr) // iteration 4 vmovaps(mem(rax, -32*4), xmm0) vbroadcastss(mem(rbx, 2*4), xmm3) prefetch(0, mem(rax, 384)) vfmadd231ps(xmm1, xmm0, xmm4) vfmadd231ps(xmm2, xmm0, xmm5) vfmadd231ps(xmm3, xmm0, xmm6) vmovaps(mem(rax, -28*4), xmm0) vfmadd231ps(xmm1, xmm0, xmm7) vfmadd231ps(xmm2, xmm0, xmm8) vfmadd231ps(xmm3, xmm0, xmm9) vmovaps(mem(rax, -24*4), xmm0) vfmadd231ps(xmm1, xmm0, xmm10) vfmadd231ps(xmm2, xmm0, xmm11) vfmadd231ps(xmm3, xmm0, xmm12) vmovaps(mem(rax, -20*4), xmm0) vfmadd231ps(xmm1, xmm0, xmm13) vbroadcastss(mem(rbx, 3*4), xmm1) vfmadd231ps(xmm2, xmm0, xmm14) vbroadcastss(mem(rbx, 4*4), xmm2) vfmadd231ps(xmm3, xmm0, xmm15) prefetch(0, mem(rbx, 80+192)) // prefetch b // iteration 5 vmovaps(mem(rax, -16*4), xmm0) vbroadcastss(mem(rbx, 5*4), xmm3) prefetch(0, mem(rax, 64+384)) vfmadd231ps(xmm1, xmm0, xmm4) vfmadd231ps(xmm2, xmm0, xmm5) vfmadd231ps(xmm3, xmm0, xmm6) vmovaps(mem(rax, -12*4), xmm0) vfmadd231ps(xmm1, xmm0, xmm7) vfmadd231ps(xmm2, xmm0, xmm8) vfmadd231ps(xmm3, xmm0, xmm9) vmovaps(mem(rax, -8*4), xmm0) vfmadd231ps(xmm1, xmm0, xmm10) vfmadd231ps(xmm2, xmm0, xmm11) vfmadd231ps(xmm3, xmm0, xmm12) vmovaps(mem(rax, -4*4), xmm0) vfmadd231ps(xmm1, xmm0, xmm13) vbroadcastss(mem(rbx, 6*4), xmm1) vfmadd231ps(xmm2, xmm0, xmm14) vbroadcastss(mem(rbx, 7*4), xmm2) vfmadd231ps(xmm3, xmm0, xmm15) // iteration 6 vmovaps(mem(rax, 0*4), xmm0) vbroadcastss(mem(rbx, 8*4), xmm3) prefetch(0, mem(rax, 128+384)) vfmadd231ps(xmm1, xmm0, xmm4) vfmadd231ps(xmm2, xmm0, xmm5) vfmadd231ps(xmm3, xmm0, xmm6) vmovaps(mem(rax, 4*4), xmm0) vfmadd231ps(xmm1, xmm0, xmm7) vfmadd231ps(xmm2, xmm0, xmm8) vfmadd231ps(xmm3, xmm0, xmm9) vmovaps(mem(rax, 8*4), xmm0) vfmadd231ps(xmm1, xmm0, xmm10) vfmadd231ps(xmm2, xmm0, xmm11) vfmadd231ps(xmm3, xmm0, xmm12) vmovaps(mem(rax, 12*4), xmm0) vfmadd231ps(xmm1, xmm0, xmm13) vbroadcastss(mem(rbx, 9*4), xmm1) vfmadd231ps(xmm2, xmm0, xmm14) vbroadcastss(mem(rbx, 10*4), xmm2) vfmadd231ps(xmm3, xmm0, xmm15) // iteration 7 vmovaps(mem(rax, 16*4), xmm0) vbroadcastss(mem(rbx, 11*4), xmm3) add(imm(8*3*4), rbx) // a += 4*3 (unroll x nr) prefetch(0, mem(rax, 192+384)) vfmadd231ps(xmm1, xmm0, xmm4) vfmadd231ps(xmm2, xmm0, xmm5) vfmadd231ps(xmm3, xmm0, xmm6) vmovaps(mem(rax, 20*4), xmm0) vfmadd231ps(xmm1, xmm0, xmm7) vfmadd231ps(xmm2, xmm0, xmm8) vfmadd231ps(xmm3, xmm0, xmm9) vmovaps(mem(rax, 24*4), xmm0) vfmadd231ps(xmm1, xmm0, xmm10) vfmadd231ps(xmm2, xmm0, xmm11) vfmadd231ps(xmm3, xmm0, xmm12) vmovaps(mem(rax, 28*4), xmm0) add(imm(4*16*4), rax) // a += 4*16 (unroll x mr) vfmadd231ps(xmm1, xmm0, xmm13) vbroadcastss(mem(rbx, -12*4), xmm1) vfmadd231ps(xmm2, xmm0, xmm14) vbroadcastss(mem(rbx, -11*4), xmm2) vfmadd231ps(xmm3, xmm0, xmm15) vbroadcastss(mem(rbx, -10*4), xmm3) dec(rsi) // i -= 1; jmp(.SLOOPKITER) // jump to beginning of loop. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP je(.SPOSTACCUM) // if i == 0, we're done. prefetch(0, mem(rbx, 16+192)) // prefetch b // iteration 0 vmovaps(mem(rax, -32*4), xmm0) prefetch(0, mem(rax, 384)) vfmadd231ps(xmm1, xmm0, xmm4) vfmadd231ps(xmm2, xmm0, xmm5) vfmadd231ps(xmm3, xmm0, xmm6) vmovaps(mem(rax, -28*4), xmm0) vfmadd231ps(xmm1, xmm0, xmm7) vfmadd231ps(xmm2, xmm0, xmm8) vfmadd231ps(xmm3, xmm0, xmm9) vmovaps(mem(rax, -24*4), xmm0) vfmadd231ps(xmm1, xmm0, xmm10) vfmadd231ps(xmm2, xmm0, xmm11) vfmadd231ps(xmm3, xmm0, xmm12) vmovaps(mem(rax, -20*4), xmm0) vfmadd231ps(xmm1, xmm0, xmm13) vbroadcastss(mem(rbx, -9*4), xmm1) vfmadd231ps(xmm2, xmm0, xmm14) vbroadcastss(mem(rbx, -8*4), xmm2) vfmadd231ps(xmm3, xmm0, xmm15) vbroadcastss(mem(rbx, -7*4), xmm3) add(imm(1*16*4), rax) // a += 4*16 (unroll x mr) add(imm(1*3*4), rbx) // a += 4*3 (unroll x nr) dec(rsi) // i -= 1; jmp(.SLOOPKLEFT) // jump to beginning of loop. label(.SPOSTACCUM) prefetchw0(mem(rcx, 0*8)) // prefetch c + 0*cs_c prefetchw0(mem(r10, 0*8)) // prefetch c + 1*cs_c prefetchw0(mem(r11, 0*8)) // prefetch c + 2*cs_c // xmm4: xmm5: xmm6: // ( ab00 ( ab01 ( ab02 // ab10 ab11 ab12 // ab20 ab21 ab22 // ab30 ) ab31 ) ab32 ) // xmm7: xmm8: xmm9: // ( ab40 ( ab41 ( ab42 // ab50 ab51 ab52 // ab60 ab61 ab62 // ab70 ) ab71 ) ab72 ) // xmm10: xmm11: xmm12: // ( ab80 ( ab01 ( ab02 // ab90 ab11 ab12 // abA0 abA1 abA2 // abB0 ) abB1 ) abB2 ) // xmm13: xmm14: xmm15: // ( abC0 ( abC1 ( abC2 // abD0 abD1 abD2 // abE0 abE1 abE2 // abF0 ) abF1 ) abF2 ) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), xmm0) // load alpha and duplicate vbroadcastss(mem(rbx), xmm2) // load beta and duplicate vmulps(xmm0, xmm4, xmm4) // scale by alpha vmulps(xmm0, xmm5, xmm5) vmulps(xmm0, xmm6, xmm6) vmulps(xmm0, xmm7, xmm7) vmulps(xmm0, xmm8, xmm8) vmulps(xmm0, xmm9, xmm9) vmulps(xmm0, xmm10, xmm10) vmulps(xmm0, xmm11, xmm11) vmulps(xmm0, xmm12, xmm12) vmulps(xmm0, xmm13, xmm13) vmulps(xmm0, xmm14, xmm14) vmulps(xmm0, xmm15, xmm15) prefetch(0, mem(r14)) // prefetch a_next prefetch(0, mem(r14, 64)) // prefetch a_next mov(var(rs_c), rsi) // load rs_c lea(mem(, rsi, 4), rsi) // rsi = rs_c * sizeof(float) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*rs_c; lea(mem(, rsi, 2), r12) // r12 = 2*rs_c; lea(mem(rsi, rsi, 2), r13) // r13 = 3*rs_c; // determine if // c % 32 == 0, AND // 4*cs_c % 32 == 0, AND // rs_c == 1 // ie: aligned, ldim aligned, and // column-stored cmp(imm(4), rsi) // set ZF if (4*rs_c) == 4. sete(bl) // bl = ( ZF == 1 ? 1 : 0 ); test(imm(31), rcx) // set ZF if c & 32 is zero. setz(bh) // bh = ( ZF == 0 ? 1 : 0 ); test(imm(31), rdi) // set ZF if (4*cs_c) & 32 is zero. setz(al) // al = ( ZF == 0 ? 1 : 0 ); // and(bl,bh) followed by // and(bh,al) will reveal result prefetch(0, mem(r15)) // prefetch b_next prefetch(0, mem(r15, 64)) // prefetch b_next // now avoid loading C if beta == 0 vxorps(xmm0, xmm0, xmm0) // set xmm0 to zero. vucomiss(xmm0, xmm2) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case vfmadd231ps(mem(rcx, 0*16), xmm2, xmm4) vfmadd231ps(mem(rcx, 1*16), xmm2, xmm7) vfmadd231ps(mem(rcx, 2*16), xmm2, xmm10) vfmadd231ps(mem(rcx, 3*16), xmm2, xmm13) vfmadd231ps(mem(r10, 0*16), xmm2, xmm5) vfmadd231ps(mem(r10, 1*16), xmm2, xmm8) vfmadd231ps(mem(r10, 2*16), xmm2, xmm11) vfmadd231ps(mem(r10, 3*16), xmm2, xmm14) vfmadd231ps(mem(r11, 0*16), xmm2, xmm6) vfmadd231ps(mem(r11, 1*16), xmm2, xmm9) vfmadd231ps(mem(r11, 2*16), xmm2, xmm12) vfmadd231ps(mem(r11, 3*16), xmm2, xmm15) // fall through label(.SBETAZERO) vmovups(xmm4, mem(rcx, 0*16)) vmovups(xmm7, mem(rcx, 1*16)) vmovups(xmm10, mem(rcx, 2*16)) vmovups(xmm13, mem(rcx, 3*16)) vmovups(xmm5, mem(r10, 0*16)) vmovups(xmm8, mem(r10, 1*16)) vmovups(xmm11, mem(r10, 2*16)) vmovups(xmm14, mem(r10, 3*16)) vmovups(xmm6, mem(r11, 0*16)) vmovups(xmm9, mem(r11, 1*16)) vmovups(xmm12, mem(r11, 2*16)) vmovups(xmm15, mem(r11, 3*16)) label(.SDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), // 0 [k_left] "m" (k_left), // 1 [a] "m" (a), // 2 [b] "m" (b), // 3 [alpha] "m" (alpha), // 4 [beta] "m" (beta), // 5 [c] "m" (c), // 6 [rs_c] "m" (rs_c), // 7 [cs_c] "m" (cs_c), // 8 [b_next] "m" (b_next), // 9 [a_next] "m" (a_next) // 10 : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) GEMM_UKR_FLUSH_CT( s ); } void bli_dgemm_piledriver_asm_8x3 ( dim_t m, dim_t n, dim_t k, double* restrict alpha, double* restrict a, double* restrict b, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { void* a_next = bli_auxinfo_next_a( data ); void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k / 8; uint64_t k_left = k % 8; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; GEMM_UKR_SETUP_CT( d, 8, 3, false ); begin_asm() mov(var(a), rax) // load address of a. mov(var(b), rbx) // load address of b. mov(var(b_next), r15) // load address of b_next. mov(var(a_next), r14) // load address of a_next. prefetch(0, mem(rbx, 128)) // prefetch b prefetch(0, mem(rbx, 64+128)) // prefetch b prefetch(0, mem(rbx, 128+128)) // prefetch b add(imm(16*8), rax) add(imm(12*8), rbx) mov(var(c), rcx) // load address of c mov(var(cs_c), rdi) // load cs_c lea(mem(, rdi, 8), rdi) // cs_c *= sizeof(double) lea(mem(rcx, rdi, 1), r10) // load address of c + 1*cs_c; lea(mem(rcx, rdi, 2), r11) // load address of c + 2*cs_c; vmovddup(mem(rbx, -12*8), xmm1) vmovddup(mem(rbx, -11*8), xmm2) vmovddup(mem(rbx, -10*8), xmm3) vxorpd(xmm4, xmm4, xmm4) vxorpd(xmm5, xmm5, xmm5) vxorpd(xmm6, xmm6, xmm6) vxorpd(xmm7, xmm7, xmm7) vxorpd(xmm8, xmm8, xmm8) vxorpd(xmm9, xmm9, xmm9) vxorpd(xmm10, xmm10, xmm10) vxorpd(xmm11, xmm11, xmm11) vxorpd(xmm12, xmm12, xmm12) vxorpd(xmm13, xmm13, xmm13) vxorpd(xmm14, xmm14, xmm14) vxorpd(xmm15, xmm15, xmm15) mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.DCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.DLOOPKITER) // MAIN LOOP je(.DCONSIDKLEFT) // if i == 0, jump to k_left code. prefetch(0, mem(rbx, -32+256)) // prefetch b prefetch(0, mem(rbx, 32+256)) // prefetch b // iteration 0 vmovaps(mem(rax, -8*16), xmm0) prefetch(0, mem(rax, 384)) // prefetch a vfmadd231pd(xmm1, xmm0, xmm4) vfmadd231pd(xmm2, xmm0, xmm5) vfmadd231pd(xmm3, xmm0, xmm6) vmovaps(mem(rax, -7*16), xmm0) vfmadd231pd(xmm1, xmm0, xmm7) vfmadd231pd(xmm2, xmm0, xmm8) vfmadd231pd(xmm3, xmm0, xmm9) vmovaps(mem(rax, -6*16), xmm0) vfmadd231pd(xmm1, xmm0, xmm10) vfmadd231pd(xmm2, xmm0, xmm11) vfmadd231pd(xmm3, xmm0, xmm12) vmovaps(mem(rax, -5*16), xmm0) vfmadd231pd(xmm1, xmm0, xmm13) vmovddup(mem(rbx, -9*8), xmm1) vfmadd231pd(xmm2, xmm0, xmm14) vmovddup(mem(rbx, -8*8), xmm2) vfmadd231pd(xmm3, xmm0, xmm15) // iteration 1 vmovaps(mem(rax, -4*16), xmm0) prefetch(0, mem(rax, 64+384)) // prefetch a vmovddup(mem(rbx, -7*8), xmm3) vfmadd231pd(xmm1, xmm0, xmm4) vfmadd231pd(xmm2, xmm0, xmm5) vfmadd231pd(xmm3, xmm0, xmm6) vmovaps(mem(rax, -3*16), xmm0) vfmadd231pd(xmm1, xmm0, xmm7) vfmadd231pd(xmm2, xmm0, xmm8) vfmadd231pd(xmm3, xmm0, xmm9) vmovaps(mem(rax, -2*16), xmm0) vfmadd231pd(xmm1, xmm0, xmm10) vfmadd231pd(xmm2, xmm0, xmm11) vfmadd231pd(xmm3, xmm0, xmm12) vmovaps(mem(rax, -1*16), xmm0) vfmadd231pd(xmm1, xmm0, xmm13) vmovddup(mem(rbx, -6*8), xmm1) vfmadd231pd(xmm2, xmm0, xmm14) vmovddup(mem(rbx, -5*8), xmm2) vfmadd231pd(xmm3, xmm0, xmm15) // iteration 2 vmovaps(mem(rax, 0*16), xmm0) prefetch(0, mem(rax, 128+384)) // prefetch a vmovddup(mem(rbx, -4*8), xmm3) vfmadd231pd(xmm1, xmm0, xmm4) vfmadd231pd(xmm2, xmm0, xmm5) vfmadd231pd(xmm3, xmm0, xmm6) vmovaps(mem(rax, 1*16), xmm0) vfmadd231pd(xmm1, xmm0, xmm7) vfmadd231pd(xmm2, xmm0, xmm8) vfmadd231pd(xmm3, xmm0, xmm9) vmovaps(mem(rax, 2*16), xmm0) vfmadd231pd(xmm1, xmm0, xmm10) vfmadd231pd(xmm2, xmm0, xmm11) vfmadd231pd(xmm3, xmm0, xmm12) vmovaps(mem(rax, 3*16), xmm0) vfmadd231pd(xmm1, xmm0, xmm13) vmovddup(mem(rbx, -3*8), xmm1) vfmadd231pd(xmm2, xmm0, xmm14) vmovddup(mem(rbx, -2*8), xmm2) vfmadd231pd(xmm3, xmm0, xmm15) // iteration 3 vmovaps(mem(rax, 4*16), xmm0) prefetch(0, mem(rax, 192+384)) // prefetch a vmovddup(mem(rbx, -1*8), xmm3) vfmadd231pd(xmm1, xmm0, xmm4) vfmadd231pd(xmm2, xmm0, xmm5) vfmadd231pd(xmm3, xmm0, xmm6) vmovaps(mem(rax, 5*16), xmm0) vfmadd231pd(xmm1, xmm0, xmm7) vfmadd231pd(xmm2, xmm0, xmm8) vfmadd231pd(xmm3, xmm0, xmm9) vmovaps(mem(rax, 6*16), xmm0) vfmadd231pd(xmm1, xmm0, xmm10) vfmadd231pd(xmm2, xmm0, xmm11) vfmadd231pd(xmm3, xmm0, xmm12) vmovaps(mem(rax, 7*16), xmm0) add(imm(4*8*8), rax) // a += 4*8 (unroll x mr) vfmadd231pd(xmm1, xmm0, xmm13) vmovddup(mem(rbx, 0*8), xmm1) vfmadd231pd(xmm2, xmm0, xmm14) vmovddup(mem(rbx, 1*8), xmm2) vfmadd231pd(xmm3, xmm0, xmm15) // iteration 4 vmovaps(mem(rax, -8*16), xmm0) prefetch(0, mem(rax, 384)) // prefetch a vmovddup(mem(rbx, 2*8), xmm3) vfmadd231pd(xmm1, xmm0, xmm4) vfmadd231pd(xmm2, xmm0, xmm5) vfmadd231pd(xmm3, xmm0, xmm6) vmovaps(mem(rax, -7*16), xmm0) vfmadd231pd(xmm1, xmm0, xmm7) vfmadd231pd(xmm2, xmm0, xmm8) vfmadd231pd(xmm3, xmm0, xmm9) vmovaps(mem(rax, -6*16), xmm0) vfmadd231pd(xmm1, xmm0, xmm10) vfmadd231pd(xmm2, xmm0, xmm11) vfmadd231pd(xmm3, xmm0, xmm12) vmovaps(mem(rax, -5*16), xmm0) vfmadd231pd(xmm1, xmm0, xmm13) vmovddup(mem(rbx, 3*8), xmm1) vfmadd231pd(xmm2, xmm0, xmm14) vmovddup(mem(rbx, 4*8), xmm2) vfmadd231pd(xmm3, xmm0, xmm15) prefetch(0, mem(rbx, 96+256)) // prefetch b // iteration 5 vmovaps(mem(rax, -4*16), xmm0) prefetch(0, mem(rax, 64+384)) // prefetch a vmovddup(mem(rbx, 5*8), xmm3) vfmadd231pd(xmm1, xmm0, xmm4) vfmadd231pd(xmm2, xmm0, xmm5) vfmadd231pd(xmm3, xmm0, xmm6) vmovaps(mem(rax, -3*16), xmm0) vfmadd231pd(xmm1, xmm0, xmm7) vfmadd231pd(xmm2, xmm0, xmm8) vfmadd231pd(xmm3, xmm0, xmm9) vmovaps(mem(rax, -2*16), xmm0) vfmadd231pd(xmm1, xmm0, xmm10) vfmadd231pd(xmm2, xmm0, xmm11) vfmadd231pd(xmm3, xmm0, xmm12) vmovaps(mem(rax, -1*16), xmm0) vfmadd231pd(xmm1, xmm0, xmm13) vmovddup(mem(rbx, 6*8), xmm1) vfmadd231pd(xmm2, xmm0, xmm14) vmovddup(mem(rbx, 7*8), xmm2) vfmadd231pd(xmm3, xmm0, xmm15) // iteration 6 vmovaps(mem(rax, 0*16), xmm0) prefetch(0, mem(rax, 128+384)) // prefetch a vmovddup(mem(rbx, 8*8), xmm3) vfmadd231pd(xmm1, xmm0, xmm4) vfmadd231pd(xmm2, xmm0, xmm5) vfmadd231pd(xmm3, xmm0, xmm6) vmovaps(mem(rax, 1*16), xmm0) vfmadd231pd(xmm1, xmm0, xmm7) vfmadd231pd(xmm2, xmm0, xmm8) vfmadd231pd(xmm3, xmm0, xmm9) vmovaps(mem(rax, 2*16), xmm0) vfmadd231pd(xmm1, xmm0, xmm10) vfmadd231pd(xmm2, xmm0, xmm11) vfmadd231pd(xmm3, xmm0, xmm12) vmovaps(mem(rax, 3*16), xmm0) vfmadd231pd(xmm1, xmm0, xmm13) vmovddup(mem(rbx, 9*8), xmm1) vfmadd231pd(xmm2, xmm0, xmm14) vmovddup(mem(rbx, 10*8), xmm2) vfmadd231pd(xmm3, xmm0, xmm15) // iteration 7 vmovaps(mem(rax, 4*16), xmm0) prefetch(0, mem(rax, 192+384)) // prefetch a vmovddup(mem(rbx, 11*8), xmm3) add(imm(8*3*8), rbx) // b += 8*3 (unroll x nr) vfmadd231pd(xmm1, xmm0, xmm4) vfmadd231pd(xmm2, xmm0, xmm5) vfmadd231pd(xmm3, xmm0, xmm6) vmovaps(mem(rax, 5*16), xmm0) vfmadd231pd(xmm1, xmm0, xmm7) vfmadd231pd(xmm2, xmm0, xmm8) vfmadd231pd(xmm3, xmm0, xmm9) vmovaps(mem(rax, 6*16), xmm0) vfmadd231pd(xmm1, xmm0, xmm10) vfmadd231pd(xmm2, xmm0, xmm11) vfmadd231pd(xmm3, xmm0, xmm12) vmovaps(mem(rax, 7*16), xmm0) add(imm(4*8*8), rax) // a += 4*8 (unroll x mr) vfmadd231pd(xmm1, xmm0, xmm13) vmovddup(mem(rbx, -12*8), xmm1) vfmadd231pd(xmm2, xmm0, xmm14) vmovddup(mem(rbx, -11*8), xmm2) vfmadd231pd(xmm3, xmm0, xmm15) vmovddup(mem(rbx, -10*8), xmm3) dec(rsi) // i -= 1; jmp(.DLOOPKITER) // jump to beginning of loop. label(.DCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.DPOSTACCUM) // if i == 0, we're done. // else, we prepare to // enter k_left loop. label(.DLOOPKLEFT) // EDGE LOOP je(.DPOSTACCUM) // if i == 0, we're done. // iteration 0 vmovaps(mem(rax, -8*16), xmm0) prefetch(0, mem(rax, 512)) // prefetch a vfmadd231pd(xmm1, xmm0, xmm4) vfmadd231pd(xmm2, xmm0, xmm5) vfmadd231pd(xmm3, xmm0, xmm6) vmovaps(mem(rax, -7*16), xmm0) vfmadd231pd(xmm1, xmm0, xmm7) vfmadd231pd(xmm2, xmm0, xmm8) vfmadd231pd(xmm3, xmm0, xmm9) vmovaps(mem(rax, -6*16), xmm0) vfmadd231pd(xmm1, xmm0, xmm10) vfmadd231pd(xmm2, xmm0, xmm11) vfmadd231pd(xmm3, xmm0, xmm12) vmovaps(mem(rax, -5*16), xmm0) vfmadd231pd(xmm1, xmm0, xmm13) vmovddup(mem(rbx, -9*8), xmm1) vfmadd231pd(xmm2, xmm0, xmm14) vmovddup(mem(rbx, -8*8), xmm2) vfmadd231pd(xmm3, xmm0, xmm15) vmovddup(mem(rbx, -7*8), xmm3) add(imm(1*8*8), rax) // a += 1*8 (1 x mr) add(imm(1*3*8), rbx) // b += 1*3 (1 x nr) dec(rsi) // i -= 1; jmp(.DLOOPKLEFT) // jump to beginning of loop. label(.DPOSTACCUM) prefetchw0(mem(rcx, 0*8)) // prefetch c + 0*cs_c prefetchw0(mem(r10, 0*8)) // prefetch c + 1*cs_c prefetchw0(mem(r11, 0*8)) // prefetch c + 2*cs_c // xmm4: xmm5: xmm6: // ( ab00 ( ab01 ( ab02 // ab10 ) ab11 ) ab12 ) // // xmm7: xmm8: xmm9: // ( ab20 ( ab21 ( ab22 // ab30 ) ab31 ) ab32 ) // // xmm10: xmm11: xmm12: // ( ab40 ( ab41 ( ab42 // ab50 ) ab51 ) ab52 ) // // xmm13: xmm14: xmm15: // ( ab60 ( ab61 ( ab62 // ab70 ) ab71 ) ab72 ) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vmovddup(mem(rax), xmm0) // load alpha and duplicate vmovddup(mem(rbx), xmm2) // load beta and duplicate vmulpd(xmm0, xmm4, xmm4) // scale by alpha vmulpd(xmm0, xmm5, xmm5) vmulpd(xmm0, xmm6, xmm6) vmulpd(xmm0, xmm7, xmm7) vmulpd(xmm0, xmm8, xmm8) vmulpd(xmm0, xmm9, xmm9) vmulpd(xmm0, xmm10, xmm10) vmulpd(xmm0, xmm11, xmm11) vmulpd(xmm0, xmm12, xmm12) vmulpd(xmm0, xmm13, xmm13) vmulpd(xmm0, xmm14, xmm14) vmulpd(xmm0, xmm15, xmm15) prefetch(0, mem(r14)) // prefetch a_next prefetch(0, mem(r14, 64)) // prefetch a_next prefetch(0, mem(r15)) // prefetch b_next prefetch(0, mem(r15, 64)) // prefetch b_next // now avoid loading C if beta == 0 vxorpd(xmm0, xmm0, xmm0) // set xmm0 to zero. vucomisd(xmm0, xmm2) // set ZF if beta == 0. je(.DBETAZERO) // if ZF = 1, jump to beta == 0 case // xmm4: xmm5: xmm6: // ( ab00 ( ab01 ( ab02 // ab10 ) ab11 ) ab12 ) // // xmm7: xmm8: xmm9: // ( ab20 ( ab21 ( ab22 // ab30 ) ab31 ) ab32 ) // // xmm10: xmm11: xmm12: // ( ab40 ( ab41 ( ab42 // ab50 ) ab51 ) ab52 ) // // xmm13: xmm14: xmm15: // ( ab60 ( ab61 ( ab62 // ab70 ) ab71 ) ab72 ) vfmadd231pd(mem(rcx, 0*16), xmm2, xmm4) vfmadd231pd(mem(rcx, 1*16), xmm2, xmm7) vfmadd231pd(mem(rcx, 2*16), xmm2, xmm10) vfmadd231pd(mem(rcx, 3*16), xmm2, xmm13) vfmadd231pd(mem(r10, 0*16), xmm2, xmm5) vfmadd231pd(mem(r10, 1*16), xmm2, xmm8) vfmadd231pd(mem(r10, 2*16), xmm2, xmm11) vfmadd231pd(mem(r10, 3*16), xmm2, xmm14) vfmadd231pd(mem(r11, 0*16), xmm2, xmm6) vfmadd231pd(mem(r11, 1*16), xmm2, xmm9) vfmadd231pd(mem(r11, 2*16), xmm2, xmm12) vfmadd231pd(mem(r11, 3*16), xmm2, xmm15) // fall through label(.DBETAZERO) vmovups(xmm4, mem(rcx, 0*16)) vmovups(xmm7, mem(rcx, 1*16)) vmovups(xmm10, mem(rcx, 2*16)) vmovups(xmm13, mem(rcx, 3*16)) vmovups(xmm5, mem(r10, 0*16)) vmovups(xmm8, mem(r10, 1*16)) vmovups(xmm11, mem(r10, 2*16)) vmovups(xmm14, mem(r10, 3*16)) vmovups(xmm6, mem(r11, 0*16)) vmovups(xmm9, mem(r11, 1*16)) vmovups(xmm12, mem(r11, 2*16)) vmovups(xmm15, mem(r11, 3*16)) label(.DDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), // 0 [k_left] "m" (k_left), // 1 [a] "m" (a), // 2 [b] "m" (b), // 3 [alpha] "m" (alpha), // 4 [beta] "m" (beta), // 5 [c] "m" (c), // 6 [rs_c] "m" (rs_c), // 7 [cs_c] "m" (cs_c), // 8 [b_next] "m" (b_next), // 9 [a_next] "m" (a_next) // 10 : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) GEMM_UKR_FLUSH_CT( d ); } void bli_cgemm_piledriver_asm_4x2 ( dim_t m, dim_t n, dim_t k, scomplex* restrict alpha, scomplex* restrict a, scomplex* restrict b, scomplex* restrict beta, scomplex* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { void* a_next = bli_auxinfo_next_a( data ); void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k / 8; uint64_t k_left = k % 8; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; GEMM_UKR_SETUP_CT( c, 4, 2, false ); begin_asm() mov(var(a), rax) // load address of a. mov(var(b), rbx) // load address of b. mov(var(b_next), r15) // load address of b_next. mov(var(a_next), r14) // load address of a_next. mov(var(c), rcx) // load address of c mov(var(cs_c), rdi) // load cs_c lea(mem(, rdi, 8), rdi) // cs_c *= sizeof(scomplex) lea(mem(rcx, rdi, 1), r10) // load address of c + 1*cs_c; add(imm(32*4), rax) add(imm(16*4), rbx) vxorps(xmm8, xmm8, xmm8) vxorps(xmm9, xmm9, xmm9) vxorps(xmm10, xmm10, xmm10) vxorps(xmm11, xmm11, xmm11) vxorps(xmm12, xmm12, xmm12) vxorps(xmm13, xmm13, xmm13) vxorps(xmm14, xmm14, xmm14) vxorps(xmm15, xmm15, xmm15) //vzeroall() mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.CCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.CLOOPKITER) // MAIN LOOP je(.CCONSIDKLEFT) // if i == 0, jump to k_left code. prefetch(0, mem(rbx, 256)) prefetch(0, mem(rax, 512)) // iteration 0 vmovaps(mem(rax, -32*4), xmm0) vbroadcastss(mem(rbx, -16*4), xmm4) vfmadd231ps(xmm0, xmm4, xmm8) vmovaps(mem(rax, -28*4), xmm1) vfmadd231ps(xmm1, xmm4, xmm12) vbroadcastss(mem(rbx, -15*4), xmm5) vfmadd231ps(xmm0, xmm5, xmm9) vfmadd231ps(xmm1, xmm5, xmm13) vbroadcastss(mem(rbx, -14*4), xmm6) vfmadd231ps(xmm0, xmm6, xmm10) vfmadd231ps(xmm1, xmm6, xmm14) vbroadcastss(mem(rbx, -13*4), xmm7) vfmadd231ps(xmm0, xmm7, xmm11) vfmadd231ps(xmm1, xmm7, xmm15) // iteration 1 vmovaps(mem(rax, -24*4), xmm0) vbroadcastss(mem(rbx, -12*4), xmm4) vfmadd231ps(xmm0, xmm4, xmm8) vmovaps(mem(rax, -20*4), xmm1) vfmadd231ps(xmm1, xmm4, xmm12) vbroadcastss(mem(rbx, -11*4), xmm5) vfmadd231ps(xmm0, xmm5, xmm9) vfmadd231ps(xmm1, xmm5, xmm13) vbroadcastss(mem(rbx, -10*4), xmm6) vfmadd231ps(xmm0, xmm6, xmm10) vfmadd231ps(xmm1, xmm6, xmm14) vbroadcastss(mem(rbx, -9*4), xmm7) vfmadd231ps(xmm0, xmm7, xmm11) vfmadd231ps(xmm1, xmm7, xmm15) prefetch(0, mem(rbx, 64+256)) prefetch(0, mem(rax, 64+512)) // iteration 2 vmovaps(mem(rax, -16*4), xmm0) vbroadcastss(mem(rbx, -8*4), xmm4) vfmadd231ps(xmm0, xmm4, xmm8) vmovaps(mem(rax, -12*4), xmm1) vfmadd231ps(xmm1, xmm4, xmm12) vbroadcastss(mem(rbx, -7*4), xmm5) vfmadd231ps(xmm0, xmm5, xmm9) vfmadd231ps(xmm1, xmm5, xmm13) vbroadcastss(mem(rbx, -6*4), xmm6) vfmadd231ps(xmm0, xmm6, xmm10) vfmadd231ps(xmm1, xmm6, xmm14) vbroadcastss(mem(rbx, -5*4), xmm7) vfmadd231ps(xmm0, xmm7, xmm11) vfmadd231ps(xmm1, xmm7, xmm15) // iteration 3 vmovaps(mem(rax, -8*4), xmm0) vbroadcastss(mem(rbx, -4*4), xmm4) vfmadd231ps(xmm0, xmm4, xmm8) vmovaps(mem(rax, -4*4), xmm1) vfmadd231ps(xmm1, xmm4, xmm12) vbroadcastss(mem(rbx, -3*4), xmm5) vfmadd231ps(xmm0, xmm5, xmm9) vfmadd231ps(xmm1, xmm5, xmm13) vbroadcastss(mem(rbx, -2*4), xmm6) vfmadd231ps(xmm0, xmm6, xmm10) vfmadd231ps(xmm1, xmm6, xmm14) vbroadcastss(mem(rbx, -1*4), xmm7) vfmadd231ps(xmm0, xmm7, xmm11) vfmadd231ps(xmm1, xmm7, xmm15) prefetch(0, mem(rbx, 128+256)) prefetch(0, mem(rax, 128+512)) // iteration 4 vmovaps(mem(rax, 0*4), xmm0) vbroadcastss(mem(rbx, 0*4), xmm4) vfmadd231ps(xmm0, xmm4, xmm8) vmovaps(mem(rax, 4*4), xmm1) vfmadd231ps(xmm1, xmm4, xmm12) vbroadcastss(mem(rbx, 1*4), xmm5) vfmadd231ps(xmm0, xmm5, xmm9) vfmadd231ps(xmm1, xmm5, xmm13) vbroadcastss(mem(rbx, 2*4), xmm6) vfmadd231ps(xmm0, xmm6, xmm10) vfmadd231ps(xmm1, xmm6, xmm14) vbroadcastss(mem(rbx, 3*4), xmm7) vfmadd231ps(xmm0, xmm7, xmm11) vfmadd231ps(xmm1, xmm7, xmm15) // iteration 5 vmovaps(mem(rax, 8*4), xmm0) vbroadcastss(mem(rbx, 4*4), xmm4) vfmadd231ps(xmm0, xmm4, xmm8) vmovaps(mem(rax, 12*4), xmm1) vfmadd231ps(xmm1, xmm4, xmm12) vbroadcastss(mem(rbx, 5*4), xmm5) vfmadd231ps(xmm0, xmm5, xmm9) vfmadd231ps(xmm1, xmm5, xmm13) vbroadcastss(mem(rbx, 6*4), xmm6) vfmadd231ps(xmm0, xmm6, xmm10) vfmadd231ps(xmm1, xmm6, xmm14) vbroadcastss(mem(rbx, 7*4), xmm7) vfmadd231ps(xmm0, xmm7, xmm11) vfmadd231ps(xmm1, xmm7, xmm15) prefetch(0, mem(rbx, 128+256)) prefetch(0, mem(rax, 128+512)) // iteration 6 vmovaps(mem(rax, 16*4), xmm0) vbroadcastss(mem(rbx, 8*4), xmm4) vfmadd231ps(xmm0, xmm4, xmm8) vmovaps(mem(rax, 20*4), xmm1) vfmadd231ps(xmm1, xmm4, xmm12) vbroadcastss(mem(rbx, 9*4), xmm5) vfmadd231ps(xmm0, xmm5, xmm9) vfmadd231ps(xmm1, xmm5, xmm13) vbroadcastss(mem(rbx, 10*4), xmm6) vfmadd231ps(xmm0, xmm6, xmm10) vfmadd231ps(xmm1, xmm6, xmm14) vbroadcastss(mem(rbx, 11*4), xmm7) vfmadd231ps(xmm0, xmm7, xmm11) vfmadd231ps(xmm1, xmm7, xmm15) // iteration 7 vmovaps(mem(rax, 24*4), xmm0) vbroadcastss(mem(rbx, 12*4), xmm4) vfmadd231ps(xmm0, xmm4, xmm8) vmovaps(mem(rax, 28*4), xmm1) add(imm(8*4*8), rax) // a += 8*2 (unroll x mr) vfmadd231ps(xmm1, xmm4, xmm12) vbroadcastss(mem(rbx, 13*4), xmm5) vfmadd231ps(xmm0, xmm5, xmm9) vfmadd231ps(xmm1, xmm5, xmm13) vbroadcastss(mem(rbx, 14*4), xmm6) vfmadd231ps(xmm0, xmm6, xmm10) vfmadd231ps(xmm1, xmm6, xmm14) vbroadcastss(mem(rbx, 15*4), xmm7) add(imm(8*2*8), rbx) // b += 8*2 (unroll x nr) vfmadd231ps(xmm0, xmm7, xmm11) vfmadd231ps(xmm1, xmm7, xmm15) dec(rsi) // i -= 1; jmp(.CLOOPKITER) // jump to beginning of loop. label(.CCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.CPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.CLOOPKLEFT) // EDGE LOOP je(.CPOSTACCUM) // if i == 0, we're done. prefetch(0, mem(rbx, 256)) prefetch(0, mem(rax, 512)) // iteration 0 vmovaps(mem(rax, -32*4), xmm0) vbroadcastss(mem(rbx, -16*4), xmm4) vfmadd231ps(xmm0, xmm4, xmm8) vmovaps(mem(rax, -28*4), xmm1) vfmadd231ps(xmm1, xmm4, xmm12) vbroadcastss(mem(rbx, -15*4), xmm5) vfmadd231ps(xmm0, xmm5, xmm9) vfmadd231ps(xmm1, xmm5, xmm13) vbroadcastss(mem(rbx, -14*4), xmm6) vfmadd231ps(xmm0, xmm6, xmm10) vfmadd231ps(xmm1, xmm6, xmm14) vbroadcastss(mem(rbx, -13*4), xmm7) vfmadd231ps(xmm0, xmm7, xmm11) vfmadd231ps(xmm1, xmm7, xmm15) add(imm(1*4*8), rax) // a += 1*2 (1 x mr) add(imm(1*2*8), rbx) // b += 1*2 (1 x nr) dec(rsi) // i -= 1; jmp(.CLOOPKLEFT) // jump to beginning of loop. label(.CPOSTACCUM) prefetchw0(mem(rcx, 0*8)) // prefetch c + 0*cs_c prefetchw0(mem(r10, 0*8)) // prefetch c + 1*cs_c vpermilps(imm(0xb1), xmm9, xmm9) vpermilps(imm(0xb1), xmm11, xmm11) vpermilps(imm(0xb1), xmm13, xmm13) vpermilps(imm(0xb1), xmm15, xmm15) vaddsubps(xmm9, xmm8, xmm8) vaddsubps(xmm11, xmm10, xmm10) vaddsubps(xmm13, xmm12, xmm12) vaddsubps(xmm15, xmm14, xmm14) // xmm8: xmm10: // ( ab00 ( ab01 // ab10 ab11 // ab20 ab21 // ab30 ) ab31 ) // xmm12: xmm14: // ( ab40 ( ab41 // ab50 ab51 // ab60 ab61 // ab70 ) ab71 ) prefetch(0, mem(r14)) // prefetch a_next prefetch(0, mem(r14, 64)) // prefetch a_next // scale by alpha mov(var(alpha), rax) // load address of alpha vbroadcastss(mem(rax), xmm0) // load alpha_r and duplicate vbroadcastss(mem(rax, 4), xmm1) // load alpha_i and duplicate vpermilps(imm(0xb1), xmm8, xmm9) vpermilps(imm(0xb1), xmm10, xmm11) vpermilps(imm(0xb1), xmm12, xmm13) vpermilps(imm(0xb1), xmm14, xmm15) vmulps(xmm8, xmm0, xmm8) vmulps(xmm10, xmm0, xmm10) vmulps(xmm12, xmm0, xmm12) vmulps(xmm14, xmm0, xmm14) vmulps(xmm9, xmm1, xmm9) vmulps(xmm11, xmm1, xmm11) vmulps(xmm13, xmm1, xmm13) vmulps(xmm15, xmm1, xmm15) vaddsubps(xmm9, xmm8, xmm8) vaddsubps(xmm11, xmm10, xmm10) vaddsubps(xmm13, xmm12, xmm12) vaddsubps(xmm15, xmm14, xmm14) mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rbx), xmm6) // load beta_r and duplicate vbroadcastss(mem(rbx, 4), xmm7) // load beta_i and duplicate prefetch(0, mem(r15)) // prefetch b_next prefetch(0, mem(r15, 64)) // prefetch b_next // now avoid loading C if beta == 0 vxorps(xmm0, xmm0, xmm0) // set xmm0 to zero. vucomiss(xmm0, xmm6) // set ZF if beta_r == 0. sete(r8b) // r8b = ( ZF == 1 ? 1 : 0 ); vucomiss(xmm0, xmm7) // set ZF if beta_i == 0. sete(r9b) // r9b = ( ZF == 1 ? 1 : 0 ); and(r8b, r9b) // set ZF if r8b & r9b == 1. jne(.CBETAZERO) // if ZF = 0, jump to beta == 0 case vmovups(mem(rcx), xmm0) // load c00:c10 vmovups(mem(rcx, 16), xmm2) // load c20:c30 vpermilps(imm(0xb1), xmm0, xmm1) vpermilps(imm(0xb1), xmm2, xmm3) vmulps(xmm6, xmm0, xmm0) vmulps(xmm7, xmm1, xmm1) vaddsubps(xmm1, xmm0, xmm0) vaddps(xmm8, xmm0, xmm0) vmulps(xmm6, xmm2, xmm2) vmulps(xmm7, xmm3, xmm3) vaddsubps(xmm3, xmm2, xmm2) vaddps(xmm12, xmm2, xmm2) vmovups(mem(r10), xmm0) // load c01:c11 vmovups(mem(r10, 16), xmm2) // load c21:c31 vpermilps(imm(0xb1), xmm0, xmm1) vpermilps(imm(0xb1), xmm2, xmm3) vmulps(xmm6, xmm0, xmm0) vmulps(xmm7, xmm1, xmm1) vaddsubps(xmm1, xmm0, xmm0) vaddps(xmm10, xmm0, xmm0) vmulps(xmm6, xmm2, xmm2) vmulps(xmm7, xmm3, xmm3) vaddsubps(xmm3, xmm2, xmm2) vaddps(xmm14, xmm2, xmm2) // fall through label(.CBETAZERO) vmovups(xmm8, mem(rcx)) // store c00:c10 vmovups(xmm12, mem(rcx, 16)) // store c20:c30 vmovups(xmm10, mem(r10)) // store c01:c11 vmovups(xmm14, mem(r10, 16)) // store c21:c31 label(.CDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), // 0 [k_left] "m" (k_left), // 1 [a] "m" (a), // 2 [b] "m" (b), // 3 [alpha] "m" (alpha), // 4 [beta] "m" (beta), // 5 [c] "m" (c), // 6 [rs_c] "m" (rs_c), // 7 [cs_c] "m" (cs_c), // 8 [b_next] "m" (b_next), // 9 [a_next] "m" (a_next) // 10 : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) GEMM_UKR_FLUSH_CT( c ); } void bli_zgemm_piledriver_asm_2x2 ( dim_t m, dim_t n, dim_t k, dcomplex* restrict alpha, dcomplex* restrict a, dcomplex* restrict b, dcomplex* restrict beta, dcomplex* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { void* a_next = bli_auxinfo_next_a( data ); void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k / 8; uint64_t k_left = k % 8; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; GEMM_UKR_SETUP_CT( z, 2, 2, false ); begin_asm() mov(var(a), rax) // load address of a. mov(var(b), rbx) // load address of b. mov(var(b_next), r15) // load address of b_next. mov(var(a_next), r14) // load address of a_next. mov(var(c), rcx) // load address of c mov(var(cs_c), rdi) // load cs_c lea(mem(, rdi, 8), rdi) // cs_c *= sizeof(dcomplex) lea(mem(, rdi, 2), rdi) lea(mem(rcx, rdi, 1), r10) // load address of c + 1*cs_c; add(imm(16*8), rax) add(imm(16*8), rbx) vxorpd(xmm8, xmm8, xmm8) vxorpd(xmm9, xmm9, xmm9) vxorpd(xmm10, xmm10, xmm10) vxorpd(xmm11, xmm11, xmm11) vxorpd(xmm12, xmm12, xmm12) vxorpd(xmm13, xmm13, xmm13) vxorpd(xmm14, xmm14, xmm14) vxorpd(xmm15, xmm15, xmm15) mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.ZCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.ZLOOPKITER) // MAIN LOOP je(.ZCONSIDKLEFT) // if i == 0, jump to k_left code. prefetch(0, mem(rbx, 256)) prefetch(0, mem(rax, 512)) // iteration 0 vmovaps(mem(rax, -16*8), xmm0) vmovddup(mem(rbx, -16*8), xmm4) vfmadd231pd(xmm0, xmm4, xmm8) vmovaps(mem(rax, -14*8), xmm1) vfmadd231pd(xmm1, xmm4, xmm12) vmovddup(mem(rbx, -15*8), xmm5) vfmadd231pd(xmm0, xmm5, xmm9) vfmadd231pd(xmm1, xmm5, xmm13) vmovddup(mem(rbx, -14*8), xmm6) vfmadd231pd(xmm0, xmm6, xmm10) vfmadd231pd(xmm1, xmm6, xmm14) vmovddup(mem(rbx, -13*8), xmm7) vfmadd231pd(xmm0, xmm7, xmm11) vmovaps(mem(rax, -12*8), xmm0) vmovddup(mem(rbx, -12*8), xmm4) vfmadd231pd(xmm1, xmm7, xmm15) // iteration 1 vfmadd231pd(xmm0, xmm4, xmm8) vmovaps(mem(rax, -10*8), xmm1) vfmadd231pd(xmm1, xmm4, xmm12) vmovddup(mem(rbx, -11*8), xmm5) vfmadd231pd(xmm0, xmm5, xmm9) vfmadd231pd(xmm1, xmm5, xmm13) vmovddup(mem(rbx, -10*8), xmm6) vfmadd231pd(xmm0, xmm6, xmm10) vfmadd231pd(xmm1, xmm6, xmm14) vmovddup(mem(rbx, -9*8), xmm7) vfmadd231pd(xmm0, xmm7, xmm11) vmovaps(mem(rax, -8*8), xmm0) vmovddup(mem(rbx, -8*8), xmm4) vfmadd231pd(xmm1, xmm7, xmm15) prefetch(0, mem(rbx, 64+256)) prefetch(0, mem(rax, 64+512)) // iteration 2 vfmadd231pd(xmm0, xmm4, xmm8) vmovaps(mem(rax, -6*8), xmm1) vfmadd231pd(xmm1, xmm4, xmm12) vmovddup(mem(rbx, -7*8), xmm5) vfmadd231pd(xmm0, xmm5, xmm9) vfmadd231pd(xmm1, xmm5, xmm13) vmovddup(mem(rbx, -6*8), xmm6) vfmadd231pd(xmm0, xmm6, xmm10) vfmadd231pd(xmm1, xmm6, xmm14) vmovddup(mem(rbx, -5*8), xmm7) vfmadd231pd(xmm0, xmm7, xmm11) vmovaps(mem(rax, -4*8), xmm0) vmovddup(mem(rbx, -4*8), xmm4) vfmadd231pd(xmm1, xmm7, xmm15) // iteration 3 vfmadd231pd(xmm0, xmm4, xmm8) vmovaps(mem(rax, -2*8), xmm1) vfmadd231pd(xmm1, xmm4, xmm12) vmovddup(mem(rbx, -3*8), xmm5) vfmadd231pd(xmm0, xmm5, xmm9) vfmadd231pd(xmm1, xmm5, xmm13) vmovddup(mem(rbx, -2*8), xmm6) vfmadd231pd(xmm0, xmm6, xmm10) vfmadd231pd(xmm1, xmm6, xmm14) vmovddup(mem(rbx, -1*8), xmm7) vfmadd231pd(xmm0, xmm7, xmm11) vmovaps(mem(rax, 0*8), xmm0) vmovddup(mem(rbx, 0*8), xmm4) vfmadd231pd(xmm1, xmm7, xmm15) prefetch(0, mem(rbx, 128+256)) prefetch(0, mem(rax, 128+512)) // iteration 4 vfmadd231pd(xmm0, xmm4, xmm8) vmovaps(mem(rax, 2*8), xmm1) vfmadd231pd(xmm1, xmm4, xmm12) vmovddup(mem(rbx, 1*8), xmm5) vfmadd231pd(xmm0, xmm5, xmm9) vfmadd231pd(xmm1, xmm5, xmm13) vmovddup(mem(rbx, 2*8), xmm6) vfmadd231pd(xmm0, xmm6, xmm10) vfmadd231pd(xmm1, xmm6, xmm14) vmovddup(mem(rbx, 3*8), xmm7) vfmadd231pd(xmm0, xmm7, xmm11) vmovaps(mem(rax, 4*8), xmm0) vmovddup(mem(rbx, 4*8), xmm4) vfmadd231pd(xmm1, xmm7, xmm15) // iteration 5 vfmadd231pd(xmm0, xmm4, xmm8) vmovaps(mem(rax, 6*8), xmm1) vfmadd231pd(xmm1, xmm4, xmm12) vmovddup(mem(rbx, 5*8), xmm5) vfmadd231pd(xmm0, xmm5, xmm9) vfmadd231pd(xmm1, xmm5, xmm13) vmovddup(mem(rbx, 6*8), xmm6) vfmadd231pd(xmm0, xmm6, xmm10) vfmadd231pd(xmm1, xmm6, xmm14) vmovddup(mem(rbx, 7*8), xmm7) vfmadd231pd(xmm0, xmm7, xmm11) vmovaps(mem(rax, 8*8), xmm0) vmovddup(mem(rbx, 8*8), xmm4) vfmadd231pd(xmm1, xmm7, xmm15) prefetch(0, mem(rbx, 128+256)) prefetch(0, mem(rax, 128+512)) // iteration 6 vfmadd231pd(xmm0, xmm4, xmm8) vmovaps(mem(rax, 10*8), xmm1) vfmadd231pd(xmm1, xmm4, xmm12) vmovddup(mem(rbx, 9*8), xmm5) vfmadd231pd(xmm0, xmm5, xmm9) vfmadd231pd(xmm1, xmm5, xmm13) vmovddup(mem(rbx, 10*8), xmm6) vfmadd231pd(xmm0, xmm6, xmm10) vfmadd231pd(xmm1, xmm6, xmm14) vmovddup(mem(rbx, 11*8), xmm7) vfmadd231pd(xmm0, xmm7, xmm11) vmovaps(mem(rax, 12*8), xmm0) vmovddup(mem(rbx, 12*8), xmm4) vfmadd231pd(xmm1, xmm7, xmm15) // iteration 7 vfmadd231pd(xmm0, xmm4, xmm8) vmovaps(mem(rax, 14*8), xmm1) add(imm(8*2*16), rax) // a += 8*2 (unroll x mr) vfmadd231pd(xmm1, xmm4, xmm12) vmovddup(mem(rbx, 13*8), xmm5) vfmadd231pd(xmm0, xmm5, xmm9) vfmadd231pd(xmm1, xmm5, xmm13) vmovddup(mem(rbx, 14*8), xmm6) vfmadd231pd(xmm0, xmm6, xmm10) vfmadd231pd(xmm1, xmm6, xmm14) vmovddup(mem(rbx, 15*8), xmm7) add(imm(8*2*16), rbx) // b += 8*2 (unroll x nr) vfmadd231pd(xmm0, xmm7, xmm11) vfmadd231pd(xmm1, xmm7, xmm15) dec(rsi) // i -= 1; jmp(.ZLOOPKITER) // jump to beginning of loop. label(.ZCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.ZPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.ZLOOPKLEFT) // EDGE LOOP je(.ZPOSTACCUM) // if i == 0, we're done. prefetch(0, mem(rbx, 256)) prefetch(0, mem(rax, 512)) // iteration 0 vmovaps(mem(rax, -16*8), xmm0) vmovddup(mem(rbx, -16*8), xmm4) vfmadd231pd(xmm0, xmm4, xmm8) vmovaps(mem(rax, -14*8), xmm1) vfmadd231pd(xmm1, xmm4, xmm12) vmovddup(mem(rbx, -15*8), xmm5) vfmadd231pd(xmm0, xmm5, xmm9) vfmadd231pd(xmm1, xmm5, xmm13) vmovddup(mem(rbx, -14*8), xmm6) vfmadd231pd(xmm0, xmm6, xmm10) vfmadd231pd(xmm1, xmm6, xmm14) vmovddup(mem(rbx, -13*8), xmm7) vfmadd231pd(xmm0, xmm7, xmm11) vfmadd231pd(xmm1, xmm7, xmm15) add(imm(1*2*16), rax) // a += 1*2 (1 x mr) add(imm(1*2*16), rbx) // b += 1*2 (1 x nr) dec(rsi) // i -= 1; jmp(.ZLOOPKLEFT) // jump to beginning of loop. label(.ZPOSTACCUM) prefetchw0(mem(rcx, 0*8)) // prefetch c + 0*cs_c prefetchw0(mem(r10, 0*8)) // prefetch c + 1*cs_c vpermilpd(imm(0x1), xmm9, xmm9) vpermilpd(imm(0x1), xmm11, xmm11) vpermilpd(imm(0x1), xmm13, xmm13) vpermilpd(imm(0x1), xmm15, xmm15) vaddsubpd(xmm9, xmm8, xmm8) vaddsubpd(xmm11, xmm10, xmm10) vaddsubpd(xmm13, xmm12, xmm12) vaddsubpd(xmm15, xmm14, xmm14) // xmm8: xmm10: // ( ab00 ( ab01 // ab10 ) ab11 ) // xmm12: xmm14: // ( ab20 ( ab21 // ab30 ) ab31 ) prefetch(0, mem(r14)) // prefetch a_next prefetch(0, mem(r14, 64)) // prefetch a_next // scale by alpha mov(var(alpha), rax) // load address of alpha vmovddup(mem(rax), xmm0) // load alpha_r and duplicate vmovddup(mem(rax, 8), xmm1) // load alpha_i and duplicate vpermilpd(imm(0x1), xmm8, xmm9) vpermilpd(imm(0x1), xmm10, xmm11) vpermilpd(imm(0x1), xmm12, xmm13) vpermilpd(imm(0x1), xmm14, xmm15) vmulpd(xmm8, xmm0, xmm8) vmulpd(xmm10, xmm0, xmm10) vmulpd(xmm12, xmm0, xmm12) vmulpd(xmm14, xmm0, xmm14) vmulpd(xmm9, xmm1, xmm9) vmulpd(xmm11, xmm1, xmm11) vmulpd(xmm13, xmm1, xmm13) vmulpd(xmm15, xmm1, xmm15) vaddsubpd(xmm9, xmm8, xmm8) vaddsubpd(xmm11, xmm10, xmm10) vaddsubpd(xmm13, xmm12, xmm12) vaddsubpd(xmm15, xmm14, xmm14) mov(var(beta), rbx) // load address of beta vmovddup(mem(rbx), xmm6) // load beta_r and duplicate vmovddup(mem(rbx, 8), xmm7) // load beta_i and duplicate prefetch(0, mem(r15)) // prefetch b_next prefetch(0, mem(r15, 64)) // prefetch b_next // now avoid loading C if beta == 0 vxorpd(xmm0, xmm0, xmm0) // set xmm0 to zero. vucomisd(xmm0, xmm6) // set ZF if beta_r == 0. sete(r8b) // r8b = ( ZF == 1 ? 1 : 0 ); vucomisd(xmm0, xmm7) // set ZF if beta_i == 0. sete(r9b) // r9b = ( ZF == 1 ? 1 : 0 ); and(r8b, r9b) // set ZF if r8b & r9b == 1. jne(.ZBETAZERO) // if ZF = 0, jump to beta == 0 case vmovups(mem(rcx), xmm0) // load c00 vmovups(mem(rcx, 16), xmm2) // load c10 vpermilpd(imm(0x1), xmm0, xmm1) vpermilpd(imm(0x1), xmm2, xmm3) vmulpd(xmm6, xmm0, xmm0) vmulpd(xmm7, xmm1, xmm1) vaddsubpd(xmm1, xmm0, xmm0) vaddpd(xmm8, xmm0, xmm0) vmulpd(xmm6, xmm2, xmm2) vmulpd(xmm7, xmm3, xmm3) vaddsubpd(xmm3, xmm2, xmm2) vaddpd(xmm12, xmm2, xmm2) vmovups(mem(r10), xmm0) // load c01 vmovups(mem(r10, 16), xmm2) // load c11 vpermilpd(imm(0x1), xmm0, xmm1) vpermilpd(imm(0x1), xmm2, xmm3) vmulpd(xmm6, xmm0, xmm0) vmulpd(xmm7, xmm1, xmm1) vaddsubpd(xmm1, xmm0, xmm0) vaddpd(xmm10, xmm0, xmm0) vmulpd(xmm6, xmm2, xmm2) vmulpd(xmm7, xmm3, xmm3) vaddsubpd(xmm3, xmm2, xmm2) vaddpd(xmm14, xmm2, xmm2) // fall through label(.ZBETAZERO) vmovups(xmm8, mem(rcx)) // store c00 vmovups(xmm12, mem(rcx, 16)) // store c10 vmovups(xmm10, mem(r10)) // store c01 vmovups(xmm14, mem(r10, 16)) // store c11 label(.ZDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), // 0 [k_left] "m" (k_left), // 1 [a] "m" (a), // 2 [b] "m" (b), // 3 [alpha] "m" (alpha), // 4 [beta] "m" (beta), // 5 [c] "m" (c), // 6 [rs_c] "m" (rs_c), // 7 [cs_c] "m" (cs_c), // 8 [b_next] "m" (b_next), // 9 [a_next] "m" (a_next) // 10 : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) GEMM_UKR_FLUSH_CT( z ); } blis-0.9.0/kernels/piledriver/bli_kernels_piledriver.h000066400000000000000000000035661422157504600231700ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // d8x4 (assembly) GEMM_UKR_PROT( float, s, gemm_piledriver_asm_16x3 ) GEMM_UKR_PROT( double, d, gemm_piledriver_asm_8x3 ) GEMM_UKR_PROT( scomplex, c, gemm_piledriver_asm_4x2 ) GEMM_UKR_PROT( dcomplex, z, gemm_piledriver_asm_2x2 ) blis-0.9.0/kernels/power10/000077500000000000000000000000001422157504600154175ustar00rootroot00000000000000blis-0.9.0/kernels/power10/3/000077500000000000000000000000001422157504600155615ustar00rootroot00000000000000blis-0.9.0/kernels/power10/3/bli_dgemm_power10_mma.c000066400000000000000000000151731422157504600220620ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "vector_int_macros.h" #define D_ASSEMBLE_VEC_PAIR \ __builtin_mma_assemble_pair (&colA_1, ca[1], ca[0]); \ __builtin_mma_assemble_pair (&colA_2, ca[3], ca[2]); #define D_ACCUMULATE \ __builtin_mma_xvf64gerpp (&acc0, colA_1, rb[0]); \ __builtin_mma_xvf64gerpp (&acc1, colA_1, rb[1]); \ __builtin_mma_xvf64gerpp (&acc2, colA_1, rb[2]); \ __builtin_mma_xvf64gerpp (&acc3, colA_1, rb[3]); \ __builtin_mma_xvf64gerpp (&acc4, colA_2, rb[0]); \ __builtin_mma_xvf64gerpp (&acc5, colA_2, rb[1]); \ __builtin_mma_xvf64gerpp (&acc6, colA_2, rb[2]); \ __builtin_mma_xvf64gerpp (&acc7, colA_2, rb[3]); #define D_INCREMENT \ A0+=8; \ B0+=8; #define D_AB_PRODUCT \ LOAD_VECTORS \ D_ASSEMBLE_VEC_PAIR \ D_INCREMENT \ D_ACCUMULATE void bli_dgemm_power10_mma_8x8 ( dim_t m, dim_t n, dim_t k, double* restrict alpha, double* restrict a, double* restrict b, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c, auxinfo_t* restrict data, cntx_t* restrict cntx ) { // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. // (1 is subtracted from k0 because 1 iteration of the k loop is pulled out) uint64_t k_iter = (k-1) / 4; uint64_t k_left = (k-1) % 4; uint64_t rs_c = rs_c0; GEMM_UKR_SETUP_CT( d, 8, 8, true ); double* restrict A0 = a; double* restrict B0 = b; double* restrict C0 = c; double alpha_ = *alpha, beta_ = *beta; dv4sf_t result[4]; dv4sf_t *rowC; /* 8 accumulator registers that will be used to store the result. Each accumulator register is mapped to 4 vector registers. Illustration: acc0 = [ vs0 vs1 vs3 vs4 ] These registers are used to store the result of an outer product instruction (general outer product instruction syntax: xv???ger??). */ __vector_quad acc0, acc1, acc2, acc3, acc4, acc5, acc6, acc7; /* 2 vector pairs are necessary for a double precision outer product instruction. */ __vector_pair colA_1, colA_2; /* Prefetch C so that it stays in cache */ PREFETCH1 (C0, 0); PREFETCH1 (C0 + rs_c, 0); PREFETCH1 (C0 + rs_c + rs_c, 0); PREFETCH1 (C0 + rs_c + rs_c + rs_c, 0); PREFETCH1 (C0, 128); PREFETCH1 (C0 + rs_c, 128); PREFETCH1 (C0 + rs_c + rs_c, 128); PREFETCH1 (C0 + rs_c + rs_c + rs_c, 128); /* Load elements into vector registers */ vec_t *ca = (vec_t *) A0; vec_t *rb = (vec_t *) B0; /* Each accumulator represents a matrix of size 4 x ( 16 / (datatype size in bytes) ) (vector register size = 16B) Thus in the case of double, the accumulate registers represent a 4x2 matrix. However, a vector register can hold at most 2 doubles. Thus, if we performed an outer product using 2 vector register, we can only get a 2x2 matrix. Therefore, we must create a vector register pair in order to get the desired 4x2 matrix. */ D_ASSEMBLE_VEC_PAIR /* Compute accumulate outer products and override accumulators with result */ __builtin_mma_xvf64ger (&acc0, colA_1, rb[0]); __builtin_mma_xvf64ger (&acc1, colA_1, rb[1]); __builtin_mma_xvf64ger (&acc2, colA_1, rb[2]); __builtin_mma_xvf64ger (&acc3, colA_1, rb[3]); __builtin_mma_xvf64ger (&acc4, colA_2, rb[0]); __builtin_mma_xvf64ger (&acc5, colA_2, rb[1]); __builtin_mma_xvf64ger (&acc6, colA_2, rb[2]); __builtin_mma_xvf64ger (&acc7, colA_2, rb[3]); /* Move A and B pointers */ D_INCREMENT // k loop (unrolled by 4) for (int k = 0; k #define COLMAJ_INDEX(row,col,ld) ((col*ld)+row) #define ROWMAJ_INDEX(row,col,ld) ((row*ld)+col) #define BLIS_INDEX(row,col,rs,cs) ((row*rs)+(col*cs)) /* * Perform * c = beta * c + alpha * a * b * where * alpha & beta are scalars * c is mr x nr in blis-format, (col-stride & row-stride) * a is mr x k in packed col-maj format (leading dim is mr) * b is k x nr in packed row-maj format (leading dim is nr) */ void bli_sgemm_power7_int_8x4 ( dim_t m, dim_t n, dim_t k, float* restrict alpha, float* restrict a, float* restrict b, float* restrict beta, float* restrict c, inc_t rs_c, inc_t cs_c, auxinfo_t* restrict data, cntx_t* restrict cntx ) { #if 1 || defined(UTEST) const long MR = BLIS_DEFAULT_MR_S, NR = BLIS_DEFAULT_NR_S; const long LDA = MR, LDB = NR; long i, j, kk; float c00; for (i=0; i < m; i++) { for (j=0; j < n; j++) { c00 = c[BLIS_INDEX(i,j,rs_c,cs_c)] * *beta; for (kk=0; kk < k; kk++) c00 += *alpha * (a[COLMAJ_INDEX(i,kk,LDA)] * b[ROWMAJ_INDEX(kk,j,LDB)]); c[BLIS_INDEX(i,j,rs_c,cs_c)] = c00; } } #else //BLIS_SGEMM_UKERNEL_REF(k, alpha, a, b, beta, c, rs_c, cs_c, data); #endif } /* * Perform * c = beta * c + alpha * a * b * where * alpha & beta are scalars * c is mr x nr in blis-format, (col-stride & row-stride) * a is mr x k in packed col-maj format (leading dim is mr) * b is k x nr in packed row-maj format (leading dim is nr) */ void bli_dgemm_power7_int_8x4 ( dim_t m, dim_t n, dim_t k, double* restrict alpha, double* restrict a, double* restrict b, double* restrict beta, double* restrict c, inc_t rs_c, inc_t cs_c, auxinfo_t* restrict data, cntx_t* restrict cntx ) { if ( cs_c == 1 ) { // Optimized code for case where C rows are contiguous (i.e. C is row-major) vector double vzero = vec_splats( 0.0 ); vector double vc00_01 = vzero; vector double vc02_03 = vzero; vector double vc10_11 = vzero; vector double vc12_13 = vzero; vector double vc20_21 = vzero; vector double vc22_23 = vzero; vector double vc30_31 = vzero; vector double vc32_33 = vzero; vector double vc40_41 = vzero; vector double vc42_43 = vzero; vector double vc50_51 = vzero; vector double vc52_53 = vzero; vector double vc60_61 = vzero; vector double vc62_63 = vzero; vector double vc70_71 = vzero; vector double vc72_73 = vzero; unsigned long long pa = (unsigned long long)a; unsigned long long pb = (unsigned long long)b; #if 0 unsigned long long d1 = 1*sizeof(double); unsigned long long d2 = 2*sizeof(double); unsigned long long d3 = 3*sizeof(double); unsigned long long d4 = 4*sizeof(double); unsigned long long d6 = 6*sizeof(double); #else // ppc64 linux abi: r14-r31 Nonvolatile registers used for local variables register unsigned long long d1 __asm ("r21") = 1*sizeof(double); register unsigned long long d2 __asm ("r22") = 2*sizeof(double); register unsigned long long d3 __asm ("r23") = 3*sizeof(double); register unsigned long long d4 __asm ("r24") = 4*sizeof(double); register unsigned long long d5 __asm ("r25") = 5*sizeof(double); register unsigned long long d6 __asm ("r26") = 6*sizeof(double); register unsigned long long d7 __asm ("r27") = 7*sizeof(double); __asm__ volatile (";" : "=r" (d1) : "r" (d1) ); __asm__ volatile (";" : "=r" (d2) : "r" (d2) ); __asm__ volatile (";" : "=r" (d3) : "r" (d3) ); __asm__ volatile (";" : "=r" (d4) : "r" (d4) ); __asm__ volatile (";" : "=r" (d5) : "r" (d5) ); __asm__ volatile (";" : "=r" (d6) : "r" (d6) ); __asm__ volatile (";" : "=r" (d7) : "r" (d7) ); #endif int kk; for (kk=k; kk > 0; kk--) { vector double va00 = vec_splats( *(double *)( pa+0 ) ); vector double va10 = vec_splats( *(double *)( pa+d1 ) ); vector double va20 = vec_splats( *(double *)( pa+d2 ) ); vector double va30 = vec_splats( *(double *)( pa+d3 ) ); vector double va40 = vec_splats( *(double *)( pa+d4 ) ); vector double va50 = vec_splats( *(double *)( pa+d5 ) ); vector double va60 = vec_splats( *(double *)( pa+d6 ) ); vector double va70 = vec_splats( *(double *)( pa+d7 ) ); pa += 8*sizeof(double); vector double vb00_01 = *(vector double *)( pb+0 ); vector double vb02_03 = *(vector double *)( pb+d2 ); pb += 4*sizeof(double); vc00_01 = vec_madd(va00, vb00_01, vc00_01); vc02_03 = vec_madd(va00, vb02_03, vc02_03); vc10_11 = vec_madd(va10, vb00_01, vc10_11); vc12_13 = vec_madd(va10, vb02_03, vc12_13); vc20_21 = vec_madd(va20, vb00_01, vc20_21); vc22_23 = vec_madd(va20, vb02_03, vc22_23); vc30_31 = vec_madd(va30, vb00_01, vc30_31); vc32_33 = vec_madd(va30, vb02_03, vc32_33); vc40_41 = vec_madd(va40, vb00_01, vc40_41); vc42_43 = vec_madd(va40, vb02_03, vc42_43); vc50_51 = vec_madd(va50, vb00_01, vc50_51); vc52_53 = vec_madd(va50, vb02_03, vc52_53); vc60_61 = vec_madd(va60, vb00_01, vc60_61); vc62_63 = vec_madd(va60, vb02_03, vc62_63); vc70_71 = vec_madd(va70, vb00_01, vc70_71); vc72_73 = vec_madd(va70, vb02_03, vc72_73); } vector double valpha = vec_splats( *alpha ); vector double vbeta = (vector double) { *beta, *beta }; vector double *pc = (vector double *)c; vc00_01 = vec_mul(valpha, vc00_01); vc02_03 = vec_mul(valpha, vc02_03); pc[0] = vec_madd( pc[0], vbeta, vc00_01); pc[1] = vec_madd( pc[1], vbeta, vc02_03); pc += rs_c/2; vc10_11 = vec_mul(valpha, vc10_11); vc12_13 = vec_mul(valpha, vc12_13); pc[0] = vec_madd( pc[0], vbeta, vc10_11); pc[1] = vec_madd( pc[1], vbeta, vc12_13); pc += rs_c/2; vc20_21 = vec_mul(valpha, vc20_21); vc22_23 = vec_mul(valpha, vc22_23); pc[0] = vec_madd( pc[0], vbeta, vc20_21); pc[1] = vec_madd( pc[1], vbeta, vc22_23); pc += rs_c/2; vc30_31 = vec_mul(valpha, vc30_31); vc32_33 = vec_mul(valpha, vc32_33); pc[0] = vec_madd( pc[0], vbeta, vc30_31); pc[1] = vec_madd( pc[1], vbeta, vc32_33); pc += rs_c/2; vc40_41 = vec_mul(valpha, vc40_41); vc42_43 = vec_mul(valpha, vc42_43); pc[0] = vec_madd( pc[0], vbeta, vc40_41); pc[1] = vec_madd( pc[1], vbeta, vc42_43); pc += rs_c/2; vc50_51 = vec_mul(valpha, vc50_51); vc52_53 = vec_mul(valpha, vc52_53); pc[0] = vec_madd( pc[0], vbeta, vc50_51); pc[1] = vec_madd( pc[1], vbeta, vc52_53); pc += rs_c/2; vc60_61 = vec_mul(valpha, vc60_61); vc62_63 = vec_mul(valpha, vc62_63); pc[0] = vec_madd( pc[0], vbeta, vc60_61); pc[1] = vec_madd( pc[1], vbeta, vc62_63); pc += rs_c/2; vc70_71 = vec_mul(valpha, vc70_71); vc72_73 = vec_mul(valpha, vc72_73); pc[0] = vec_madd( pc[0], vbeta, vc70_71); pc[1] = vec_madd( pc[1], vbeta, vc72_73); pc += rs_c/2; } else { GEMM_UKR_SETUP_CT( d, 8, 4, false ); // Optimized code for case where C columns are contiguous (column-major C) vector double vzero = vec_splats( 0.0 ); vector double vc00_10 = vzero; vector double vc20_30 = vzero; vector double vc40_50 = vzero; vector double vc60_70 = vzero; vector double vc01_11 = vzero; vector double vc21_31 = vzero; vector double vc41_51 = vzero; vector double vc61_71 = vzero; vector double vc02_12 = vzero; vector double vc22_32 = vzero; vector double vc42_52 = vzero; vector double vc62_72 = vzero; vector double vc03_13 = vzero; vector double vc23_33 = vzero; vector double vc43_53 = vzero; vector double vc63_73 = vzero; unsigned long long pa = (unsigned long long)a; unsigned long long pb = (unsigned long long)b; #if 0 unsigned long long d1 = 1*sizeof(double); unsigned long long d2 = 2*sizeof(double); unsigned long long d3 = 3*sizeof(double); unsigned long long d4 = 4*sizeof(double); unsigned long long d6 = 6*sizeof(double); #else // ppc64 linux abi: r14-r31 Nonvolatile registers used for local variables register unsigned long long d1 __asm ("r21") = 1*sizeof(double); register unsigned long long d2 __asm ("r22") = 2*sizeof(double); register unsigned long long d3 __asm ("r23") = 3*sizeof(double); register unsigned long long d4 __asm ("r24") = 4*sizeof(double); register unsigned long long d6 __asm ("r26") = 6*sizeof(double); __asm__ volatile (";" : "=r" (d1) : "r" (d1) ); __asm__ volatile (";" : "=r" (d2) : "r" (d2) ); __asm__ volatile (";" : "=r" (d3) : "r" (d3) ); __asm__ volatile (";" : "=r" (d4) : "r" (d4) ); __asm__ volatile (";" : "=r" (d6) : "r" (d6) ); #endif int kk; for (kk=k; kk > 1; kk-=2) { vector double va00_10 = *(vector double *)( pa+0 ); vector double va20_30 = *(vector double *)( pa+d2 ); vector double va40_50 = *(vector double *)( pa+d4 ); vector double va60_70 = *(vector double *)( pa+d6 ); pa += 8*sizeof(double); vector double vb00 = vec_splats( *(double *)( pb+0 ) ); vector double vb01 = vec_splats( *(double *)( pb+d1 ) ); vector double vb02 = vec_splats( *(double *)( pb+d2 ) ); vector double vb03 = vec_splats( *(double *)( pb+d3 ) ); pb += 4*sizeof(double); vc00_10 = vec_madd(va00_10, vb00, vc00_10); vc20_30 = vec_madd(va20_30, vb00, vc20_30); vc40_50 = vec_madd(va40_50, vb00, vc40_50); vc60_70 = vec_madd(va60_70, vb00, vc60_70); vc01_11 = vec_madd(va00_10, vb01, vc01_11); vc21_31 = vec_madd(va20_30, vb01, vc21_31); vc41_51 = vec_madd(va40_50, vb01, vc41_51); vc61_71 = vec_madd(va60_70, vb01, vc61_71); vc02_12 = vec_madd(va00_10, vb02, vc02_12); vc22_32 = vec_madd(va20_30, vb02, vc22_32); vc42_52 = vec_madd(va40_50, vb02, vc42_52); vc62_72 = vec_madd(va60_70, vb02, vc62_72); vc03_13 = vec_madd(va00_10, vb03, vc03_13); vc23_33 = vec_madd(va20_30, vb03, vc23_33); vc43_53 = vec_madd(va40_50, vb03, vc43_53); vc63_73 = vec_madd(va60_70, vb03, vc63_73); va00_10 = *(vector double *)( pa+0 ); va20_30 = *(vector double *)( pa+d2 ); va40_50 = *(vector double *)( pa+d4 ); va60_70 = *(vector double *)( pa+d6 ); pa += 8*sizeof(double); vb00 = vec_splats( *(double *)( pb+0 ) ); vb01 = vec_splats( *(double *)( pb+d1 ) ); vb02 = vec_splats( *(double *)( pb+d2 ) ); vb03 = vec_splats( *(double *)( pb+d3 ) ); pb += 4*sizeof(double); vc00_10 = vec_madd(va00_10, vb00, vc00_10); vc20_30 = vec_madd(va20_30, vb00, vc20_30); vc40_50 = vec_madd(va40_50, vb00, vc40_50); vc60_70 = vec_madd(va60_70, vb00, vc60_70); vc01_11 = vec_madd(va00_10, vb01, vc01_11); vc21_31 = vec_madd(va20_30, vb01, vc21_31); vc41_51 = vec_madd(va40_50, vb01, vc41_51); vc61_71 = vec_madd(va60_70, vb01, vc61_71); vc02_12 = vec_madd(va00_10, vb02, vc02_12); vc22_32 = vec_madd(va20_30, vb02, vc22_32); vc42_52 = vec_madd(va40_50, vb02, vc42_52); vc62_72 = vec_madd(va60_70, vb02, vc62_72); vc03_13 = vec_madd(va00_10, vb03, vc03_13); vc23_33 = vec_madd(va20_30, vb03, vc23_33); vc43_53 = vec_madd(va40_50, vb03, vc43_53); vc63_73 = vec_madd(va60_70, vb03, vc63_73); } for (kk=kk; kk > 0; kk--) { vector double va00_10 = *(vector double *)( pa+0 ); vector double va20_30 = *(vector double *)( pa+d2 ); vector double va40_50 = *(vector double *)( pa+d4 ); vector double va60_70 = *(vector double *)( pa+d6 ); pa += 8*sizeof(double); vector double vb00 = vec_splats( *(double *)( pb+0 ) ); vector double vb01 = vec_splats( *(double *)( pb+d1 ) ); vector double vb02 = vec_splats( *(double *)( pb+d2 ) ); vector double vb03 = vec_splats( *(double *)( pb+d3 ) ); pb += 4*sizeof(double); vc00_10 = vec_madd(va00_10, vb00, vc00_10); vc20_30 = vec_madd(va20_30, vb00, vc20_30); vc40_50 = vec_madd(va40_50, vb00, vc40_50); vc60_70 = vec_madd(va60_70, vb00, vc60_70); vc01_11 = vec_madd(va00_10, vb01, vc01_11); vc21_31 = vec_madd(va20_30, vb01, vc21_31); vc41_51 = vec_madd(va40_50, vb01, vc41_51); vc61_71 = vec_madd(va60_70, vb01, vc61_71); vc02_12 = vec_madd(va00_10, vb02, vc02_12); vc22_32 = vec_madd(va20_30, vb02, vc22_32); vc42_52 = vec_madd(va40_50, vb02, vc42_52); vc62_72 = vec_madd(va60_70, vb02, vc62_72); vc03_13 = vec_madd(va00_10, vb03, vc03_13); vc23_33 = vec_madd(va20_30, vb03, vc23_33); vc43_53 = vec_madd(va40_50, vb03, vc43_53); vc63_73 = vec_madd(va60_70, vb03, vc63_73); } // The following code is dependent on rs_c == 1 vector double valpha = vec_splats( *alpha ); vector double vbeta = (vector double) { *beta, *beta }; vector double *pc = (vector double *)c; vc00_10 = vec_mul(valpha, vc00_10); vc20_30 = vec_mul(valpha, vc20_30); vc40_50 = vec_mul(valpha, vc40_50); vc60_70 = vec_mul(valpha, vc60_70); pc[0] = vec_madd( pc[0], vbeta, vc00_10); pc[1] = vec_madd( pc[1], vbeta, vc20_30); pc[2] = vec_madd( pc[2], vbeta, vc40_50); pc[3] = vec_madd( pc[3], vbeta, vc60_70); pc += cs_c/2; vc01_11 = vec_mul(valpha, vc01_11); vc21_31 = vec_mul(valpha, vc21_31); vc41_51 = vec_mul(valpha, vc41_51); vc61_71 = vec_mul(valpha, vc61_71); pc[0] = vec_madd( pc[0], vbeta, vc01_11); pc[1] = vec_madd( pc[1], vbeta, vc21_31); pc[2] = vec_madd( pc[2], vbeta, vc41_51); pc[3] = vec_madd( pc[3], vbeta, vc61_71); pc += cs_c/2; vc02_12 = vec_mul(valpha, vc02_12); vc22_32 = vec_mul(valpha, vc22_32); vc42_52 = vec_mul(valpha, vc42_52); vc62_72 = vec_mul(valpha, vc62_72); pc[0] = vec_madd( pc[0], vbeta, vc02_12); pc[1] = vec_madd( pc[1], vbeta, vc22_32); pc[2] = vec_madd( pc[2], vbeta, vc42_52); pc[3] = vec_madd( pc[3], vbeta, vc62_72); pc += cs_c/2; vc03_13 = vec_mul(valpha, vc03_13); vc23_33 = vec_mul(valpha, vc23_33); vc43_53 = vec_mul(valpha, vc43_53); vc63_73 = vec_mul(valpha, vc63_73); pc[0] = vec_madd( pc[0], vbeta, vc03_13); pc[1] = vec_madd( pc[1], vbeta, vc23_33); pc[2] = vec_madd( pc[2], vbeta, vc43_53); pc[3] = vec_madd( pc[3], vbeta, vc63_73); GEMM_UKR_FLUSH_CT( d ); } } /* * Perform * c = beta * c + alpha * a * b * where * alpha & beta are scalars * c is mr x nr in blis-format, (col-stride & row-stride) * a is mr x k in packed col-maj format (leading dim is mr) * b is k x nr in packed row-maj format (leading dim is nr) */ void bli_cgemm_power7_int_8x4 ( dim_t m, dim_t n, dim_t k, scomplex* restrict alpha, scomplex* restrict a, scomplex* restrict b, scomplex* restrict beta, scomplex* restrict c, inc_t rs_c, inc_t cs_c, auxinfo_t* restrict data, cntx_t* restrict cntx ) { #if 1 || defined(UTEST) const long MR = BLIS_DEFAULT_MR_C, NR = BLIS_DEFAULT_NR_C; const long LDA = MR, LDB = NR; int i, j, kk; scomplex c00; for (i=0; i < m; i++) { for (j=0; j < n; j++) { scomplex tmpc, tmpa, tmpb, tmp; //c00 = c[BLIS_INDEX(i,j,rs_c,cs_c)] * *beta; tmpc = c[BLIS_INDEX(i,j,rs_c,cs_c)]; c00.real = tmpc.real * (*beta).real - tmpc.imag * (*beta).imag; c00.imag = tmpc.real * (*beta).imag + tmpc.imag * (*beta).real; for (kk=0; kk < k; kk++) { //c00 += *alpha * (a[COLMAJ_INDEX(i,kk,LDA)] * b[ROWMAJ_INDEX(kk,j,LDB)]); tmpa = a[COLMAJ_INDEX(i,kk,LDA)]; tmpb = b[ROWMAJ_INDEX(kk,j,LDB)]; tmp.real = tmpa.real * tmpb.real - tmpa.imag * tmpb.imag; tmp.imag = tmpa.real * tmpb.imag + tmpa.imag * tmpb.real; c00.real += (*alpha).real * tmp.real - (*alpha).imag * tmp.imag; c00.imag += (*alpha).real * tmp.imag + (*alpha).imag * tmp.real; } c[BLIS_INDEX(i,j,rs_c,cs_c)] = c00; } } #else //BLIS_CGEMM_UKERNEL_REF(k, alpha, a, b, beta, c, rs_c, cs_c, data); #endif } /* * Perform * c = beta * c + alpha * a * b * where * alpha & beta are scalars * c is mr x nr in blis-format, (col-stride & row-stride) * a is mr x k in packed col-maj format (leading dim is mr) * b is k x nr in packed row-maj format (leading dim is nr) */ void bli_zgemm_power7_int_8x4 ( dim_t m, dim_t n, dim_t k, scomplex* restrict alpha, scomplex* restrict a, scomplex* restrict b, scomplex* restrict beta, scomplex* restrict c, inc_t rs_c, inc_t cs_c, auxinfo_t* restrict data, cntx_t* restrict cntx ) { #if 1 || defined(UTEST) const long MR = BLIS_DEFAULT_MR_Z, NR = BLIS_DEFAULT_NR_Z; const long LDA = MR, LDB = NR; int i, j, kk; dcomplex c00; for (i=0; i < m; i++) { for (j=0; j < n; j++) { dcomplex tmpc, tmpa, tmpb, tmp; //c00 = c[BLIS_INDEX(i,j,rs_c,cs_c)] * *beta; tmpc = c[BLIS_INDEX(i,j,rs_c,cs_c)]; c00.real = tmpc.real * (*beta).real - tmpc.imag * (*beta).imag; c00.imag = tmpc.real * (*beta).imag + tmpc.imag * (*beta).real; for (kk=0; kk < k; kk++) { //c00 += *alpha * (a[COLMAJ_INDEX(i,kk,LDA)] * b[ROWMAJ_INDEX(kk,j,LDB)]); tmpa = a[COLMAJ_INDEX(i,kk,LDA)]; tmpb = b[ROWMAJ_INDEX(kk,j,LDB)]; tmp.real = tmpa.real * tmpb.real - tmpa.imag * tmpb.imag; tmp.imag = tmpa.real * tmpb.imag + tmpa.imag * tmpb.real; c00.real += (*alpha).real * tmp.real - (*alpha).imag * tmp.imag; c00.imag += (*alpha).real * tmp.imag + (*alpha).imag * tmp.real; } c[BLIS_INDEX(i,j,rs_c,cs_c)] = c00; } } #else //BLIS_ZGEMM_UKERNEL_REF(k, alpha, a, b, beta, c, rs_c, cs_c, data); #endif } blis-0.9.0/kernels/power7/3/test/000077500000000000000000000000001422157504600164665ustar00rootroot00000000000000blis-0.9.0/kernels/power7/3/test/Makefile000066400000000000000000000003061422157504600201250ustar00rootroot00000000000000 CC = gcc TARGET_ARCH = -m64 -mvsx TGTS = exp KERNEL = bli_gemm_opt_8x4.o CFLAGS = -DUTEST -std=gnu99 -ggdb3 -Wall CFLAGS += -O3 all: $(TGTS) exp: exp.o $(KERNEL) clean: rm -f $(TGTS) *.o blis-0.9.0/kernels/power7/3/test/bli_gemm_power7_int_8x4.c000077700000000000000000000000001422157504600302722../bli_gemm_power7_int_8x4.custar00rootroot00000000000000blis-0.9.0/kernels/power7/3/test/bli_gemm_power7_int_8x4.h000066400000000000000000000063541422157504600233020ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef _BLI_GEMM_OPT_8X4_H_ #define _BLI_GEMM_OPT_8X4_H_ #ifdef UTEST #include "blis_utest.h" #else #include "blis.h" #endif void bli_sgemm_opt_8x4 ( dim_t m, dim_t n, dim_t k, float* restrict alpha, float* restrict a, float* restrict b, float* restrict beta, float* restrict c, inc_t rs_c, inc_t cs_c, auxinfo_t* restrict data, cntx_t* restrict cntx ); void bli_dgemm_opt_8x4 ( dim_t m, dim_t n, dim_t k, double* restrict alpha, double* restrict a, double* restrict b, double* restrict beta, double* restrict c, inc_t rs_c, inc_t cs_c, auxinfo_t* restrict data, cntx_t* restrict cntx ); void bli_cgemm_opt_8x4 ( dim_t m, dim_t n, dim_t k, scomplex* restrict alpha, scomplex* restrict a, scomplex* restrict b, scomplex* restrict beta, scomplex* restrict c, inc_t rs_c, inc_t cs_c, auxinfo_t* restrict data, cntx_t* restrict cntx ); void bli_zgemm_opt_8x4 ( dim_t m, dim_t n, dim_t k, dcomplex* restrict alpha, dcomplex* restrict a, dcomplex* restrict b, dcomplex* restrict beta, dcomplex* restrict c, inc_t rs_c, inc_t cs_c, auxinfo_t* restrict data, cntx_t* restrict cntx ); #endif blis-0.9.0/kernels/power7/3/test/blis_utest.h000066400000000000000000000010751422157504600210170ustar00rootroot00000000000000 #ifndef _BLIS_UTEST_H_ #define _BLIS_UTEST_H_ #define BLIS_DEFAULT_MR_S 8 #define BLIS_DEFAULT_NR_S 4 #define BLIS_DEFAULT_MR_D 8 #define BLIS_DEFAULT_NR_D 4 #define BLIS_DEFAULT_MR_C 8 #define BLIS_DEFAULT_NR_C 4 #define BLIS_DEFAULT_MR_Z 8 #define BLIS_DEFAULT_NR_Z 4 typedef unsigned long dim_t; typedef long inc_t; // Complex types typedef struct scomplex_s { float real; float imag; } scomplex; typedef struct dcomplex_s { double real; double imag; } dcomplex; #define bli_check_error_code(x) #endif blis-0.9.0/kernels/power7/3/test/exp.c000066400000000000000000000071471422157504600174370ustar00rootroot00000000000000#ifdef UTEST #include #include #include #include /* fabs */ #include "blis_utest.h" #include "bli_gemm_power7_opt_8x4.h" #define COLMAJ_INDEX(row,col,ld) ((col*ld)+row) #define ROWMAJ_INDEX(row,col,ld) ((row*ld)+col) #define BLIS_INDEX(row,col,rs,cs) ((row*rs)+(col*cs)) #define MR BLIS_DEFAULT_MR_D #define NR BLIS_DEFAULT_NR_D #define LDA MR #define LDB NR #define EPSILON 0.0000001 /* * Perform * c = beta * c + alpha * a * b * where * alpha & beta are scalars * c is mr x nr in blis-format, (col-stride & row-stride) * a is mr x k in packed col-maj format (leading dim is mr) * b is k x nr in packed row-maj format (leading dim is nr) */ void bli_dgemm_check( dim_t k, double* restrict alpha, double* restrict a, double* restrict b, double* restrict beta, double* restrict c, inc_t rs_c, inc_t cs_c, auxinfo_t* data ) { int i, j, kk; double c00; for (i=0; i < MR; i++) { for (j=0; j < NR; j++) { c00 = c[BLIS_INDEX(i,j,rs_c,cs_c)] * *beta; for (kk=0; kk < k; kk++) c00 += *alpha * (a[COLMAJ_INDEX(i,kk,LDA)] * b[ROWMAJ_INDEX(kk,j,LDB)]); c[BLIS_INDEX(i,j,rs_c,cs_c)] = c00; } } } int main(int argc, char *argv[]) { double *A, *B, *C, *C2; double alpha = 1.0, beta = 1.0; long i, j; long k = 128; int iters = 10; int errors; struct timeval tv_start, tv_end; switch (argc) { case 2: k = atoi(argv[1]); case 1: break; default: printf("Usage: %s [k]\n", argv[0]); return 1; break; } //long rs_c = 1, cs_c = MR; // Column major long rs_c = NR, cs_c = 1; // Row major A = (double*)malloc(LDA * k * sizeof(double)); B = (double*)malloc(LDB * k * sizeof(double)); C = (double*)malloc(MR * NR * sizeof(double)); C2 = (double*)malloc(MR * NR * sizeof(double)); /* Initialize C matrix in blis format */ for (j=0; j EPSILON) { if (errors<20) printf(" %ld expected=%f got=%f\n", i, C2[i], C[i]); errors++; } } printf("Errors = %d\n", errors); if (errors) { return -1; } /* Now get the performance */ gettimeofday(&tv_start, NULL); for (i=0; i #include #include "blis.h" #if 0 void bli_sgemm_sandybridge_int_8x8 ( dim_t m, dim_t n, dim_t k, float* restrict alpha, float* restrict a, float* restrict b, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { } #endif void bli_dgemm_sandybridge_int_8x4 ( dim_t m, dim_t n, dim_t k, double* restrict alpha, double* restrict a, double* restrict b, double* restrict beta, double* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k / 2; uint64_t k_left = k % 2; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; uint64_t i; GEMM_UKR_SETUP_CT( d, 8, 4, false ); double *c00, *c01, *c02, *c03; double *c40, *c41, *c42, *c43; // Quad registers. __m256d va0_3, va4_7; __m256d vA0_3, vA4_7; __m256d vb0, vb1, vb2, vb3; __m256d vb; __m256d vB0; __m256d va0_3b_0, va4_7b_0; __m256d va0_3b_1, va4_7b_1; __m256d va0_3b_2, va4_7b_2; __m256d va0_3b_3, va4_7b_3; __m256d va0_3b0, va4_7b0; __m256d va0_3b1, va4_7b1; __m256d va0_3b2, va4_7b2; __m256d va0_3b3, va4_7b3; __m256d valpha, vbeta, vtmp; __m256d vc0_3_0, vc0_3_1, vc0_3_2, vc0_3_3; __m256d vc4_7_0, vc4_7_1, vc4_7_2, vc4_7_3; __asm__ volatile( "prefetcht0 0(%0) \n\t" : :"r"(a) ); __asm__ volatile( "prefetcht2 0(%0) \n\t" : :"r"(b_next) ); __asm__ volatile( "prefetcht0 0(%0) \n\t" : :"r"(c) ); va0_3b0 = _mm256_setzero_pd(); va0_3b1 = _mm256_setzero_pd(); va0_3b2 = _mm256_setzero_pd(); va0_3b3 = _mm256_setzero_pd(); va4_7b0 = _mm256_setzero_pd(); va4_7b1 = _mm256_setzero_pd(); va4_7b2 = _mm256_setzero_pd(); va4_7b3 = _mm256_setzero_pd(); va0_3b_0 = _mm256_setzero_pd(); va0_3b_1 = _mm256_setzero_pd(); va0_3b_2 = _mm256_setzero_pd(); va0_3b_3 = _mm256_setzero_pd(); va4_7b_0 = _mm256_setzero_pd(); va4_7b_1 = _mm256_setzero_pd(); va4_7b_2 = _mm256_setzero_pd(); va4_7b_3 = _mm256_setzero_pd(); // Load va0_3 va0_3 = _mm256_load_pd( a ); // Load va4_7 va4_7 = _mm256_load_pd( a + 4 ); // Load vb (b0,b1,b2,b3) vb0 = _mm256_load_pd( b ); for( i = 0; i < k_iter; ++i ) { __asm__ volatile( "prefetcht0 192(%0) \n\t" : :"r"(a) ); // Load va0_3 (Prefetch) vA0_3 = _mm256_load_pd( a + 8 ); // Iteration 0. vtmp = _mm256_mul_pd( va0_3, vb0 ); va0_3b_0 = _mm256_add_pd( va0_3b_0, vtmp ); vtmp = _mm256_mul_pd( va4_7, vb0 ); va4_7b_0 = _mm256_add_pd( va4_7b_0, vtmp ); // Load va4_7 (Prefetch) vA4_7 = _mm256_load_pd( a + 12 ); // Shuffle vb (b1,b0,b3,b2) vb1 = _mm256_shuffle_pd( vb0, vb0, 0x5 ); vtmp = _mm256_mul_pd( va0_3, vb1 ); va0_3b_1 = _mm256_add_pd( va0_3b_1, vtmp ); vtmp = _mm256_mul_pd( va4_7, vb1 ); va4_7b_1 = _mm256_add_pd( va4_7b_1, vtmp ); // Permute vb (b3,b2,b1,b0) vb2 = _mm256_permute2f128_pd( vb1, vb1, 0x1 ); // Load vb (b0,b1,b2,b3) (Prefetch) vB0 = _mm256_load_pd( b + 4 ); vtmp = _mm256_mul_pd( va0_3, vb2 ); va0_3b_2 = _mm256_add_pd( va0_3b_2, vtmp ); vtmp = _mm256_mul_pd( va4_7, vb2 ); va4_7b_2 = _mm256_add_pd( va4_7b_2, vtmp ); // Shuffle vb (b3,b2,b1,b0) vb3 = _mm256_shuffle_pd( vb2, vb2, 0x5 ); vtmp = _mm256_mul_pd( va0_3, vb3 ); va0_3b_3 = _mm256_add_pd( va0_3b_3, vtmp ); vtmp = _mm256_mul_pd( va4_7, vb3 ); va4_7b_3 = _mm256_add_pd( va4_7b_3, vtmp ); // Iteration 1. __asm__ volatile( "prefetcht0 512(%0) \n\t" : :"r"(a) ); // Load va0_3 (Next iteration) va0_3 = _mm256_load_pd( a + 16 ); vtmp = _mm256_mul_pd( vA0_3, vB0 ); va0_3b_0 = _mm256_add_pd( va0_3b_0, vtmp ); vb1 = _mm256_shuffle_pd( vB0, vB0, 0x5 ); vtmp = _mm256_mul_pd( vA4_7, vB0 ); va4_7b_0 = _mm256_add_pd( va4_7b_0, vtmp ); vtmp = _mm256_mul_pd( vA0_3, vb1 ); va0_3b_1 = _mm256_add_pd( va0_3b_1, vtmp ); // Load va4_7 (Next iteration) va4_7 = _mm256_load_pd( a + 20 ); vb2 = _mm256_permute2f128_pd( vb1, vb1, 0x1 ); vtmp = _mm256_mul_pd( vA4_7, vb1 ); va4_7b_1 = _mm256_add_pd( va4_7b_1, vtmp ); vtmp = _mm256_mul_pd( vA0_3, vb2 ); va0_3b_2 = _mm256_add_pd( va0_3b_2, vtmp ); vb3 = _mm256_shuffle_pd( vb2, vb2, 0x5 ); vtmp = _mm256_mul_pd( vA4_7, vb2 ); va4_7b_2 = _mm256_add_pd( va4_7b_2, vtmp ); // Load vb0(Next iteration) vb0 = _mm256_load_pd( b + 8 ); vtmp = _mm256_mul_pd( vA0_3, vb3 ); va0_3b_3 = _mm256_add_pd( va0_3b_3, vtmp ); vtmp = _mm256_mul_pd( vA4_7, vb3 ); va4_7b_3 = _mm256_add_pd( va4_7b_3, vtmp ); a += 16; b += 8; } for( i = 0; i < k_left; ++i ) { // Iteration 0. // Load va0_3 va0_3 = _mm256_load_pd( a ); // Load va4_7 va4_7 = _mm256_load_pd( a + 4 ); // Load vb (b0,b1,b2,b3) vb = _mm256_load_pd( b ); vtmp = _mm256_mul_pd( va0_3, vb ); va0_3b_0 = _mm256_add_pd( va0_3b_0, vtmp ); vtmp = _mm256_mul_pd( va4_7, vb ); va4_7b_0 = _mm256_add_pd( va4_7b_0, vtmp ); // Shuffle vb (b1,b0,b3,b2) vb = _mm256_shuffle_pd( vb, vb, 0x5 ); vtmp = _mm256_mul_pd( va0_3, vb ); va0_3b_1 = _mm256_add_pd( va0_3b_1, vtmp ); vtmp = _mm256_mul_pd( va4_7, vb ); va4_7b_1 = _mm256_add_pd( va4_7b_1, vtmp ); // Permute vb (b3,b2,b1,b0) vb = _mm256_permute2f128_pd( vb, vb, 0x1 ); vtmp = _mm256_mul_pd( va0_3, vb ); va0_3b_2 = _mm256_add_pd( va0_3b_2, vtmp ); vtmp = _mm256_mul_pd( va4_7, vb ); va4_7b_2 = _mm256_add_pd( va4_7b_2, vtmp ); // Shuffle vb (b3,b2,b1,b0) vb = _mm256_shuffle_pd( vb, vb, 0x5 ); vtmp = _mm256_mul_pd( va0_3, vb ); va0_3b_3 = _mm256_add_pd( va0_3b_3, vtmp ); vtmp = _mm256_mul_pd( va4_7, vb ); va4_7b_3 = _mm256_add_pd( va4_7b_3, vtmp ); a += 8; b += 4; } vbeta = _mm256_broadcast_sd( beta ); __m256d vtmpa_0_3b_0 = _mm256_blend_pd( va0_3b_0, va0_3b_1, 0x6 ); __m256d vtmpa_0_3b_1 = _mm256_blend_pd( va0_3b_1, va0_3b_0, 0x6 ); __m256d vtmpa_0_3b_2 = _mm256_blend_pd( va0_3b_2, va0_3b_3, 0x6 ); __m256d vtmpa_0_3b_3 = _mm256_blend_pd( va0_3b_3, va0_3b_2, 0x6 ); __m256d vtmpa_4_7b_0 = _mm256_blend_pd( va4_7b_0, va4_7b_1, 0x6 ); __m256d vtmpa_4_7b_1 = _mm256_blend_pd( va4_7b_1, va4_7b_0, 0x6 ); __m256d vtmpa_4_7b_2 = _mm256_blend_pd( va4_7b_2, va4_7b_3, 0x6 ); __m256d vtmpa_4_7b_3 = _mm256_blend_pd( va4_7b_3, va4_7b_2, 0x6 ); valpha = _mm256_broadcast_sd( alpha ); va0_3b0 = _mm256_permute2f128_pd( vtmpa_0_3b_0, vtmpa_0_3b_2, 0x30 ); va0_3b3 = _mm256_permute2f128_pd( vtmpa_0_3b_2, vtmpa_0_3b_0, 0x30 ); va0_3b1 = _mm256_permute2f128_pd( vtmpa_0_3b_1, vtmpa_0_3b_3, 0x30 ); va0_3b2 = _mm256_permute2f128_pd( vtmpa_0_3b_3, vtmpa_0_3b_1, 0x30 ); va4_7b0 = _mm256_permute2f128_pd( vtmpa_4_7b_0, vtmpa_4_7b_2, 0x30 ); va4_7b3 = _mm256_permute2f128_pd( vtmpa_4_7b_2, vtmpa_4_7b_0, 0x30 ); va4_7b1 = _mm256_permute2f128_pd( vtmpa_4_7b_1, vtmpa_4_7b_3, 0x30 ); va4_7b2 = _mm256_permute2f128_pd( vtmpa_4_7b_3, vtmpa_4_7b_1, 0x30 ); __m128d vzero = _mm_setzero_pd( ); if( _mm_comieq_sd( _mm256_castpd256_pd128(vbeta), vzero ) ) { // Calculate address c00 = ( c + 0 + 0*cs_c ); // Scale by alpha vtmp = _mm256_mul_pd( valpha, va0_3b0); // Store back to memory _mm256_store_pd( c00, vtmp ); // Calculate address c40 = ( c + 4 + 0*cs_c ); // Scale by alpha vtmp = _mm256_mul_pd( valpha, va4_7b0); // Store back to memory _mm256_store_pd( c40, vtmp ); // Calculate address c01 = ( c + 0 + 1*cs_c ); // Scale by alpha vtmp = _mm256_mul_pd( valpha, va0_3b1); // Store back to memory _mm256_store_pd( c01, vtmp ); // Calculate address c41 = ( c + 4 + 1*cs_c ); // Scale by alpha vtmp = _mm256_mul_pd( valpha, va4_7b1); // Store back to memory _mm256_store_pd( c41, vtmp ); // Calculate address c02 = ( c + 0 + 2*cs_c ); // Scale by alpha vtmp = _mm256_mul_pd( valpha, va0_3b2); // Store back to memory _mm256_store_pd( c02, vtmp ); // Calculate address c42 = ( c + 4 + 2*cs_c ); // Scale by alpha vtmp = _mm256_mul_pd( valpha, va4_7b2); // Store back to memory _mm256_store_pd( c42, vtmp ); // Calculate address c03 = ( c + 0 + 3*cs_c ); // Scale by alpha vtmp = _mm256_mul_pd( valpha, va0_3b3); // Store back to memory _mm256_store_pd( c03, vtmp ); // Calculate address c43 = ( c + 4 + 3*cs_c ); // Scale by alpha vtmp = _mm256_mul_pd( valpha, va4_7b3); // Store back to memory _mm256_store_pd( c43, vtmp ); } else { // Calculate address c00 = ( c + 0 + 0*cs_c ); // Load //vc0_3_0 = _mm256_load_pd( c + 0 + 0*cs_c ); vc0_3_0 = _mm256_load_pd( c00 ); // Scale by alpha vtmp = _mm256_mul_pd( valpha, va0_3b0); // Scale by beta vc0_3_0 = _mm256_mul_pd( vbeta, vc0_3_0 ); // Add gemm result vc0_3_0 = _mm256_add_pd( vc0_3_0, vtmp ); // Store back to memory _mm256_store_pd( c00, vc0_3_0 ); // Calculate address c40 = ( c + 4 + 0*cs_c ); // Load //vc4_7_0 = _mm256_load_pd( c + 4 + 0*cs_c ); vc4_7_0 = _mm256_load_pd( c40 ); // Scale by alpha vtmp = _mm256_mul_pd( valpha, va4_7b0); // Scale by beta vc4_7_0 = _mm256_mul_pd( vbeta, vc4_7_0 ); // Add gemm result vc4_7_0 = _mm256_add_pd( vc4_7_0, vtmp ); // Store back to memory _mm256_store_pd( c40, vc4_7_0 ); // Calculate address c01 = ( c + 0 + 1*cs_c ); // Load //vc0_3_1 = _mm256_load_pd( c + 0 + 1*cs_c ); vc0_3_1 = _mm256_load_pd( c01 ); // Scale by alpha vtmp = _mm256_mul_pd( valpha, va0_3b1); // Scale by beta vc0_3_1 = _mm256_mul_pd( vbeta, vc0_3_1 ); // Add gemm result vc0_3_1 = _mm256_add_pd( vc0_3_1, vtmp ); // Store back to memory _mm256_store_pd( c01, vc0_3_1 ); // Calculate address c41 = ( c + 4 + 1*cs_c ); // Load //vc4_7_1 = _mm256_load_pd( c + 4 + 1*cs_c ); vc4_7_1 = _mm256_load_pd( c41 ); // Scale by alpha vtmp = _mm256_mul_pd( valpha, va4_7b1); // Scale by beta vc4_7_1 = _mm256_mul_pd( vbeta, vc4_7_1 ); // Add gemm result vc4_7_1 = _mm256_add_pd( vc4_7_1, vtmp ); // Store back to memory _mm256_store_pd( c41, vc4_7_1 ); // Calculate address c02 = ( c + 0 + 2*cs_c ); // Load //vc0_3_2 = _mm256_load_pd( c + 0 + 2*cs_c ); vc0_3_2 = _mm256_load_pd( c02 ); // Scale by alpha vtmp = _mm256_mul_pd( valpha, va0_3b2); // Scale by beta vc0_3_2 = _mm256_mul_pd( vbeta, vc0_3_2 ); // Add gemm result vc0_3_2 = _mm256_add_pd( vc0_3_2, vtmp ); // Store back to memory _mm256_store_pd( c02, vc0_3_2 ); // Calculate address c42 = ( c + 4 + 2*cs_c ); // Load //vc4_7_2 = _mm256_load_pd( c + 4 + 2*cs_c ); vc4_7_2 = _mm256_load_pd( c42 ); // Scale by alpha vtmp = _mm256_mul_pd( valpha, va4_7b2); // Scale by beta vc4_7_2 = _mm256_mul_pd( vbeta, vc4_7_2 ); // Add gemm result vc4_7_2 = _mm256_add_pd( vc4_7_2, vtmp ); // Store back to memory _mm256_store_pd( c42, vc4_7_2 ); // Calculate address c03 = ( c + 0 + 3*cs_c ); // Load //vc0_3_3 = _mm256_load_pd( c + 0 + 3*cs_c ); vc0_3_3 = _mm256_load_pd( c03 ); // Scale by alpha vtmp = _mm256_mul_pd( valpha, va0_3b3); // Scale by beta vc0_3_3 = _mm256_mul_pd( vbeta, vc0_3_3 ); // Add gemm result vc0_3_3 = _mm256_add_pd( vc0_3_3, vtmp ); // Store back to memory _mm256_store_pd( c03, vc0_3_3 ); // Calculate address c43 = ( c + 4 + 3*cs_c ); // Load //vc4_7_3 = _mm256_load_pd( c + 4 + 3*cs_c ); vc4_7_3 = _mm256_load_pd( c43 ); // Scale by alpha vtmp = _mm256_mul_pd( valpha, va4_7b3); // Scale by beta vc4_7_3 = _mm256_mul_pd( vbeta, vc4_7_3 ); // Add gemm result vc4_7_3 = _mm256_add_pd( vc4_7_3, vtmp ); // Store back to memory _mm256_store_pd( c43, vc4_7_3 ); } GEMM_UKR_FLUSH_CT( d ); } #if 0 void bli_cgemm_sandybridge_int_8x4 ( dim_t m, dim_t n, dim_t k, scomplex* restrict alpha, scomplex* restrict a, scomplex* restrict b, scomplex* restrict beta, scomplex* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { } #endif #if 0 void bli_zgemm_sandybridge_int_4x4 ( dim_t m, dim_t n, dim_t k, dcomplex* restrict alpha, dcomplex* restrict a, dcomplex* restrict b, dcomplex* restrict beta, dcomplex* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { } #endif blis-0.9.0/kernels/sandybridge/bli_kernels_sandybridge.h000066400000000000000000000041531422157504600234350ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // d8x4 (assembly) GEMM_UKR_PROT( float, s, gemm_sandybridge_asm_8x8 ) GEMM_UKR_PROT( double, d, gemm_sandybridge_asm_8x4 ) GEMM_UKR_PROT( scomplex, c, gemm_sandybridge_asm_8x4 ) GEMM_UKR_PROT( dcomplex, z, gemm_sandybridge_asm_4x4 ) // d8x4 (intrinsics) GEMM_UKR_PROT( float, s, gemm_sandybridge_int_8x8 ) GEMM_UKR_PROT( double, d, gemm_sandybridge_int_8x4 ) GEMM_UKR_PROT( scomplex, c, gemm_sandybridge_int_8x4 ) GEMM_UKR_PROT( dcomplex, z, gemm_sandybridge_int_4x4 ) blis-0.9.0/kernels/skx/000077500000000000000000000000001422157504600147275ustar00rootroot00000000000000blis-0.9.0/kernels/skx/3/000077500000000000000000000000001422157504600150715ustar00rootroot00000000000000blis-0.9.0/kernels/skx/3/bli_dgemm_skx_asm_16x12_l2.c000066400000000000000000000364441422157504600221520ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 UNIVERSITY OF TEXAS 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. */ #include "blis.h" #define BLIS_ASM_SYNTAX_INTEL #include "bli_x86_asm_macros.h" #define A_L1_PREFETCH_DIST 4 //should be multiple of 2 /*The pointer of B is moved ahead by one iteration of k before the loop starts.Therefore, prefetching 3 k iterations ahead*/ #define B_L1_PREFETCH_DIST 4 #define TAIL_NITER 8 #define CACHELINE_SIZE 64 //size of cache line in bytes /* During each subiteration, prefetching 2 cache lines of B * UNROLL factor ahead. 2cache lines = 16 doubles (NR). * */ #define PREFETCH_A_L1(n, k) \ PREFETCH(0, MEM(RAX, A_L1_PREFETCH_DIST*16*8 + (2*n+k) * CACHELINE_SIZE)) /* Preloading B for the first iteration of the main loop. * for subiter(1), subiter(2), and subiter(3) */ #define PREFETCH_B_L1_1ITER \ PREFETCH(0, MEM(RBX )) \ PREFETCH(0, MEM(RBX, CACHELINE_SIZE)) \ PREFETCH(0, MEM(RBX, 2*CACHELINE_SIZE)) \ PREFETCH(0, MEM(RBX, 3*CACHELINE_SIZE)) \ PREFETCH(0, MEM(RBX, 4*CACHELINE_SIZE)) \ PREFETCH(0, MEM(RBX, 5*CACHELINE_SIZE)) #define LOOP_ALIGN ALIGN16 #define UPDATE_C(R1,R2,R3,R4) \ \ VMULPD(ZMM(R1), ZMM(R1), ZMM(0)) \ VMULPD(ZMM(R2), ZMM(R2), ZMM(0)) \ VMULPD(ZMM(R3), ZMM(R3), ZMM(0)) \ VMULPD(ZMM(R4), ZMM(R4), ZMM(0)) \ VFMADD231PD(ZMM(R1), ZMM(1), MEM(RCX,0*64)) \ VFMADD231PD(ZMM(R2), ZMM(1), MEM(RCX,1*64)) \ VFMADD231PD(ZMM(R3), ZMM(1), MEM(RCX,RAX,1,0*64)) \ VFMADD231PD(ZMM(R4), ZMM(1), MEM(RCX,RAX,1,1*64)) \ VMOVUPD(MEM(RCX,0*64), ZMM(R1)) \ VMOVUPD(MEM(RCX,1*64), ZMM(R2)) \ VMOVUPD(MEM(RCX,RAX,1,0*64), ZMM(R3)) \ VMOVUPD(MEM(RCX,RAX,1,1*64), ZMM(R4)) \ LEA(RCX, MEM(RCX,RAX,2)) #define UPDATE_C_BZ(R1,R2,R3,R4) \ \ VMULPD(ZMM(R1), ZMM(R1), ZMM(0)) \ VMULPD(ZMM(R2), ZMM(R2), ZMM(0)) \ VMULPD(ZMM(R3), ZMM(R3), ZMM(0)) \ VMULPD(ZMM(R4), ZMM(R4), ZMM(0)) \ VMOVUPD(MEM(RCX,0*64), ZMM(R1)) \ VMOVUPD(MEM(RCX,1*64), ZMM(R2)) \ VMOVUPD(MEM(RCX,RAX,1,0*64), ZMM(R3)) \ VMOVUPD(MEM(RCX,RAX,1,1*64), ZMM(R4)) \ LEA(RCX, MEM(RCX,RAX,2)) #define UPDATE_C_ROW_SCATTERED(R1,R2,R3,R4) \ \ KXNORW(K(1), K(0), K(0)) \ KXNORW(K(2), K(0), K(0)) \ VMULPD(ZMM(R1), ZMM(R1), ZMM(0)) \ VGATHERQPD(ZMM(6) MASK_K(1), MEM(RCX,ZMM(2),1)) \ VFMADD231PD(ZMM(R1), ZMM(6), ZMM(1)) \ VSCATTERQPD(MEM(RCX,ZMM(2),1) MASK_K(2), ZMM(R1)) \ \ KXNORW(K(1), K(0), K(0)) \ KXNORW(K(2), K(0), K(0)) \ VMULPD(ZMM(R2), ZMM(R2), ZMM(0)) \ VGATHERQPD(ZMM(6) MASK_K(1), MEM(RCX,ZMM(3),1)) \ VFMADD231PD(ZMM(R2), ZMM(6), ZMM(1)) \ VSCATTERQPD(MEM(RCX,ZMM(3),1) MASK_K(2), ZMM(R2)) \ \ LEA(RCX, MEM(RCX,RAX,1)) \ \ KXNORW(K(1), K(0), K(0)) \ KXNORW(K(2), K(0), K(0)) \ VMULPD(ZMM(R3), ZMM(R3), ZMM(0)) \ VGATHERQPD(ZMM(6) MASK_K(1), MEM(RCX,ZMM(2),1)) \ VFMADD231PD(ZMM(R3), ZMM(6), ZMM(1)) \ VSCATTERQPD(MEM(RCX,ZMM(2),1) MASK_K(2), ZMM(R3)) \ \ KXNORW(K(1), K(0), K(0)) \ KXNORW(K(2), K(0), K(0)) \ VMULPD(ZMM(R4), ZMM(R4), ZMM(0)) \ VGATHERQPD(ZMM(6) MASK_K(1), MEM(RCX,ZMM(3),1)) \ VFMADD231PD(ZMM(R4), ZMM(6), ZMM(1)) \ VSCATTERQPD(MEM(RCX,ZMM(3),1) MASK_K(2), ZMM(R4)) \ \ LEA(RCX, MEM(RCX,RAX,1)) #define UPDATE_C_BZ_ROW_SCATTERED(R1,R2,R3,R4) \ \ KXNORW(K(1), K(0), K(0)) \ VMULPD(ZMM(R1), ZMM(R1), ZMM(0)) \ VSCATTERQPD(MEM(RCX,ZMM(2),1) MASK_K(1), ZMM(R1)) \ \ KXNORW(K(1), K(0), K(0)) \ VMULPD(ZMM(R2), ZMM(R2), ZMM(0)) \ VSCATTERQPD(MEM(RCX,ZMM(3),1) MASK_K(1), ZMM(R2)) \ \ LEA(RCX, MEM(RCX,RAX,1)) \ \ KXNORW(K(1), K(0), K(0)) \ VMULPD(ZMM(R3), ZMM(R3), ZMM(0)) \ VSCATTERQPD(MEM(RCX,ZMM(2),1) MASK_K(1), ZMM(R3)) \ \ KXNORW(K(1), K(0), K(0)) \ VMULPD(ZMM(R4), ZMM(R4), ZMM(0)) \ VSCATTERQPD(MEM(RCX,ZMM(3),1) MASK_K(1), ZMM(R4)) \ \ LEA(RCX, MEM(RCX,RAX,1)) #ifdef PREFETCH_C_L2 #undef PREFETCH_C_L2 #define PREFETCH_C_L2 \ \ PREFETCH(1, MEM(RCX, 0*64)) \ PREFETCH(1, MEM(RCX, 1*64)) \ \ PREFETCH(1, MEM(RCX,R12,1,0*64)) \ PREFETCH(1, MEM(RCX,R12,1,1*64)) \ \ PREFETCH(1, MEM(RCX,R12,2,0*64)) \ PREFETCH(1, MEM(RCX,R12,2,1*64)) \ \ PREFETCH(1, MEM(RCX,R13,1,0*64)) \ PREFETCH(1, MEM(RCX,R13,1,1*64)) \ \ PREFETCH(1, MEM(RCX,R12,4,0*64)) \ PREFETCH(1, MEM(RCX,R12,4,1*64)) \ \ PREFETCH(1, MEM(RCX,R14,1,0*64)) \ PREFETCH(1, MEM(RCX,R14,1,1*64)) \ \ PREFETCH(1, MEM(RCX,R13,2,0*64)) \ PREFETCH(1, MEM(RCX,R13,2,1*64)) \ \ PREFETCH(1, MEM(RCX,R15,1,0*64)) \ PREFETCH(1, MEM(RCX,R15,1,1*64)) \ \ PREFETCH(1, MEM(RDX, 0*64)) \ PREFETCH(1, MEM(RDX, 1*64)) \ \ PREFETCH(1, MEM(RDX,R12,1,0*64)) \ PREFETCH(1, MEM(RDX,R12,1,1*64)) \ \ PREFETCH(1, MEM(RDX,R12,2,0*64)) \ PREFETCH(1, MEM(RDX,R12,2,1*64)) \ \ PREFETCH(1, MEM(RDX,R13,1,0*64)) \ PREFETCH(1, MEM(RDX,R13,1,1*64)) #else #undef PREFETCH_C_L2 #define PREFETCH_C_L2 #endif #define PREFETCH_C_L1 \ \ PREFETCHW0(MEM(RCX, 0*64)) \ PREFETCHW0(MEM(RCX, 1*64)) \ PREFETCHW0(MEM(RCX,R12,1,0*64)) \ PREFETCHW0(MEM(RCX,R12,1,1*64)) \ PREFETCHW0(MEM(RCX,R12,2,0*64)) \ PREFETCHW0(MEM(RCX,R12,2,1*64)) \ PREFETCHW0(MEM(RCX,R13,1,0*64)) \ PREFETCHW0(MEM(RCX,R13,1,1*64)) \ PREFETCHW0(MEM(RCX,R12,4,0*64)) \ PREFETCHW0(MEM(RCX,R12,4,1*64)) \ PREFETCHW0(MEM(RCX,R14,1,0*64)) \ PREFETCHW0(MEM(RCX,R14,1,1*64)) \ PREFETCHW0(MEM(RCX,R13,2,0*64)) \ PREFETCHW0(MEM(RCX,R13,2,1*64)) \ PREFETCHW0(MEM(RCX,R15,1,0*64)) \ PREFETCHW0(MEM(RCX,R15,1,1*64)) \ PREFETCHW0(MEM(RDX, 0*64)) \ PREFETCHW0(MEM(RDX, 1*64)) \ PREFETCHW0(MEM(RDX,R12,1,0*64)) \ PREFETCHW0(MEM(RDX,R12,1,1*64)) \ PREFETCHW0(MEM(RDX,R12,2,0*64)) \ PREFETCHW0(MEM(RDX,R12,2,1*64)) \ PREFETCHW0(MEM(RDX,R13,1,0*64)) \ PREFETCHW0(MEM(RDX,R13,1,1*64)) // // n: index in unrolled loop // // a: ZMM register to load into // b: ZMM register to read from // // ...: addressing for A, except for offset // #define SUBITER(n) \ \ PREFETCH_A_L1(n, 0) \ \ VBROADCASTSD(ZMM(3), MEM(RBX,(12*n+ 0)*8)) \ VBROADCASTSD(ZMM(4), MEM(RBX,(12*n+ 1)*8)) \ VFMADD231PD(ZMM( 8), ZMM(0), ZMM(3)) \ VFMADD231PD(ZMM( 9), ZMM(1), ZMM(3)) \ VFMADD231PD(ZMM(10), ZMM(0), ZMM(4)) \ VFMADD231PD(ZMM(11), ZMM(1), ZMM(4)) \ \ VBROADCASTSD(ZMM(3), MEM(RBX,(12*n+ 2)*8)) \ VBROADCASTSD(ZMM(4), MEM(RBX,(12*n+ 3)*8)) \ VFMADD231PD(ZMM(12), ZMM(0), ZMM(3)) \ VFMADD231PD(ZMM(13), ZMM(1), ZMM(3)) \ VFMADD231PD(ZMM(14), ZMM(0), ZMM(4)) \ VFMADD231PD(ZMM(15), ZMM(1), ZMM(4)) \ \ VBROADCASTSD(ZMM(3), MEM(RBX,(12*n+ 4)*8)) \ VBROADCASTSD(ZMM(4), MEM(RBX,(12*n+ 5)*8)) \ VFMADD231PD(ZMM(16), ZMM(0), ZMM(3)) \ VFMADD231PD(ZMM(17), ZMM(1), ZMM(3)) \ VFMADD231PD(ZMM(18), ZMM(0), ZMM(4)) \ VFMADD231PD(ZMM(19), ZMM(1), ZMM(4)) \ \ PREFETCH_A_L1(n, 1) \ \ VBROADCASTSD(ZMM(3), MEM(RBX,(12*n+ 6)*8)) \ VBROADCASTSD(ZMM(4), MEM(RBX,(12*n+ 7)*8)) \ VFMADD231PD(ZMM(20), ZMM(0), ZMM(3)) \ VFMADD231PD(ZMM(21), ZMM(1), ZMM(3)) \ VFMADD231PD(ZMM(22), ZMM(0), ZMM(4)) \ VFMADD231PD(ZMM(23), ZMM(1), ZMM(4)) \ \ VBROADCASTSD(ZMM(3), MEM(RBX,(12*n+ 8)*8)) \ VBROADCASTSD(ZMM(4), MEM(RBX,(12*n+ 9)*8)) \ VFMADD231PD(ZMM(24), ZMM(0), ZMM(3)) \ VFMADD231PD(ZMM(25), ZMM(1), ZMM(3)) \ VFMADD231PD(ZMM(26), ZMM(0), ZMM(4)) \ VFMADD231PD(ZMM(27), ZMM(1), ZMM(4)) \ \ VBROADCASTSD(ZMM(3), MEM(RBX,(12*n+10)*8)) \ VBROADCASTSD(ZMM(4), MEM(RBX,(12*n+11)*8)) \ VFMADD231PD(ZMM(28), ZMM(0), ZMM(3)) \ VFMADD231PD(ZMM(29), ZMM(1), ZMM(3)) \ VFMADD231PD(ZMM(30), ZMM(0), ZMM(4)) \ VFMADD231PD(ZMM(31), ZMM(1), ZMM(4)) \ \ VMOVAPD(ZMM(0), MEM(RAX,(16*n+0)*8)) \ VMOVAPD(ZMM(1), MEM(RAX,(16*n+8)*8)) //This is an array used for the scatter/gather instructions. static int64_t offsets[16] __attribute__((aligned(64))) = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15}; void bli_dgemm_skx_asm_16x12_l2 ( dim_t m, dim_t n, dim_t k_, double* restrict alpha, double* restrict a, double* restrict b, double* restrict beta, double* restrict c, inc_t rs_c_, inc_t cs_c_, auxinfo_t* data, cntx_t* restrict cntx ) { (void)data; (void)cntx; int64_t k = k_; int64_t rs_c = rs_c_; int64_t cs_c = cs_c_; GEMM_UKR_SETUP_CT( d, 16, 12, false ); BEGIN_ASM() VXORPD(YMM(8), YMM(8), YMM(8)) //clear out registers VMOVAPD(YMM( 7), YMM(8)) VMOVAPD(YMM( 9), YMM(8)) VMOVAPD(YMM(10), YMM(8)) MOV(RSI, VAR(k)) //loop index VMOVAPD(YMM(11), YMM(8)) MOV(RAX, VAR(a)) //load address of a VMOVAPD(YMM(12), YMM(8)) MOV(RBX, VAR(b)) //load address of b VMOVAPD(YMM(13), YMM(8)) MOV(RCX, VAR(c)) //load address of c VMOVAPD(YMM(14), YMM(8)) VMOVAPD(YMM(15), YMM(8)) VMOVAPD(ZMM(0), MEM(RAX, 0*8)) //pre-load a VMOVAPD(YMM(16), YMM(8)) VMOVAPD(ZMM(1), MEM(RAX, 8*8)) //pre-load a VMOVAPD(YMM(17), YMM(8)) VMOVAPD(YMM(18), YMM(8)) VMOVAPD(YMM(19), YMM(8)) MOV(R12, VAR(cs_c)) //cs_c VMOVAPD(YMM(20), YMM(8)) LEA(R13, MEM(R12,R12,2)) //*3 VMOVAPD(YMM(21), YMM(8)) LEA(R14, MEM(R12,R12,4)) //*5 VMOVAPD(YMM(22), YMM(8)) LEA(R15, MEM(R14,R12,2)) //*7 VMOVAPD(YMM(23), YMM(8)) LEA(RDX, MEM(RCX,R12,8)) //c + 8*cs_c VMOVAPD(YMM(24), YMM(8)) VMOVAPD(YMM(25), YMM(8)) MOV(R8, IMM(16*8)) //mr*sizeof(double) VMOVAPD(YMM(26), YMM(8)) MOV(R9, IMM(12*8)) //nr*sizeof(double) VMOVAPD(YMM(27), YMM(8)) VMOVAPD(YMM(28), YMM(8)) LEA(RAX, MEM(RAX,R8,1)) //adjust a for pre-load VMOVAPD(YMM(29), YMM(8)) VMOVAPD(YMM(30), YMM(8)) VMOVAPD(YMM(31), YMM(8)) TEST(RSI, RSI) JZ(POSTACCUM) #ifdef PREFETCH_A_BEFORE PREFETCH(0, MEM(RAX,0*64)) PREFETCH(0, MEM(RAX,1*64)) PREFETCH(0, MEM(RAX,2*64)) PREFETCH(0, MEM(RAX,3*64)) PREFETCH(0, MEM(RAX,4*64)) PREFETCH(0, MEM(RAX,5*64)) PREFETCH(0, MEM(RAX,6*64)) PREFETCH(0, MEM(RAX,7*64)) #endif #ifdef PREFETCH_B_BEFORE PREFETCH(0, MEM(RBX,0*64)) PREFETCH(0, MEM(RBX,1*64)) PREFETCH(0, MEM(RBX,2*64)) PREFETCH(0, MEM(RBX,3*64)) PREFETCH(0, MEM(RBX,4*64)) PREFETCH(0, MEM(RBX,5*64)) #endif PREFETCH_C_L2 MOV(RDI, RSI) AND(RSI, IMM(3)) SAR(RDI, IMM(2)) SUB(RDI, IMM(0+TAIL_NITER)) JLE(K_SMALL) LOOP_ALIGN LABEL(MAIN_LOOP) PREFETCH(0, MEM(RBX,B_L1_PREFETCH_DIST*12*8)) PREFETCH(0, MEM(RBX,B_L1_PREFETCH_DIST*12*8+64)) SUBITER(0) PREFETCH(0, MEM(RBX,B_L1_PREFETCH_DIST*12*8+128)) SUBITER(1) PREFETCH(0, MEM(RBX,B_L1_PREFETCH_DIST*12*8+192)) PREFETCH(0, MEM(RBX,B_L1_PREFETCH_DIST*12*8+256)) SUBITER(2) PREFETCH(0, MEM(RBX,B_L1_PREFETCH_DIST*12*8+320)) SUBITER(3) LEA(RAX, MEM(RAX,R8,4)) LEA(RBX, MEM(RBX,R9,4)) DEC(RDI) JNZ(MAIN_LOOP) LABEL(K_SMALL) PREFETCH_C_L1 ADD(RDI, IMM(0+TAIL_NITER)) JZ(TAIL_LOOP) LOOP_ALIGN LABEL(SMALL_LOOP) PREFETCH(0, MEM(RBX,B_L1_PREFETCH_DIST*12*8)) PREFETCH(0, MEM(RBX,B_L1_PREFETCH_DIST*12*8+64)) SUBITER(0) PREFETCH(0, MEM(RBX,B_L1_PREFETCH_DIST*12*8+128)) SUBITER(1) PREFETCH(0, MEM(RBX,B_L1_PREFETCH_DIST*12*8+192)) PREFETCH(0, MEM(RBX,B_L1_PREFETCH_DIST*12*8+256)) SUBITER(2) PREFETCH(0, MEM(RBX,B_L1_PREFETCH_DIST*12*8+320)) SUBITER(3) LEA(RAX, MEM(RAX,R8,4)) LEA(RBX, MEM(RBX,R9,4)) DEC(RDI) JNZ(SMALL_LOOP) TEST(RSI, RSI) JZ(POSTACCUM) LOOP_ALIGN LABEL(TAIL_LOOP) PREFETCH(0, MEM(RBX,B_L1_PREFETCH_DIST*12*8)) PREFETCH(0, MEM(RBX,B_L1_PREFETCH_DIST*12*8+64)) SUBITER(0) ADD(RAX, R8) ADD(RBX, R9) DEC(RSI) JNZ(TAIL_LOOP) LABEL(POSTACCUM) #ifdef PREFETCH_A_AFTER MOV(R8, VAR(a)) PREFETCH(0, MEM(R8,0*64)) PREFETCH(0, MEM(R8,1*64)) PREFETCH(0, MEM(R8,2*64)) PREFETCH(0, MEM(R8,3*64)) PREFETCH(0, MEM(R8,4*64)) PREFETCH(0, MEM(R8,5*64)) PREFETCH(0, MEM(R8,6*64)) PREFETCH(0, MEM(R8,7*64)) #endif #ifdef PREFETCH_B_AFTER MOV(R9, VAR(b)) PREFETCH(0, MEM(R9,0*64)) PREFETCH(0, MEM(R9,1*64)) PREFETCH(0, MEM(R9,2*64)) PREFETCH(0, MEM(R9,3*64)) PREFETCH(0, MEM(R9,4*64)) PREFETCH(0, MEM(R9,5*64)) #endif MOV(RAX, VAR(alpha)) MOV(RBX, VAR(beta)) VBROADCASTSD(ZMM(0), MEM(RAX)) VBROADCASTSD(ZMM(1), MEM(RBX)) MOV(RAX, VAR(cs_c)) LEA(RAX, MEM(,RAX,8)) VCOMISD(XMM(1), XMM(7)) JE(COLSTORBZ) UPDATE_C( 8, 9,10,11) UPDATE_C(12,13,14,15) UPDATE_C(16,17,18,19) UPDATE_C(20,21,22,23) UPDATE_C(24,25,26,27) UPDATE_C(28,29,30,31) JMP(END) LABEL(COLSTORBZ) UPDATE_C_BZ( 8, 9,10,11) UPDATE_C_BZ(12,13,14,15) UPDATE_C_BZ(16,17,18,19) UPDATE_C_BZ(20,21,22,23) UPDATE_C_BZ(24,25,26,27) UPDATE_C_BZ(28,29,30,31) LABEL(END) VZEROUPPER() END_ASM( : // output operands : // input operands [k] "m" (k), [a] "m" (a), [b] "m" (b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c) : // register clobber list "rax", "rbx", "rcx", "rdx", "rdi", "rsi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "zmm0", "zmm1", "zmm2", "zmm3", "zmm4", "zmm5", "zmm6", "zmm7", "zmm8", "zmm9", "zmm10", "zmm11", "zmm12", "zmm13", "zmm14", "zmm15", "zmm16", "zmm17", "zmm18", "zmm19", "zmm20", "zmm21", "zmm22", "zmm23", "zmm24", "zmm25", "zmm26", "zmm27", "zmm28", "zmm29", "zmm30", "zmm31", "memory" ) GEMM_UKR_FLUSH_CT( d ); } blis-0.9.0/kernels/skx/3/bli_dgemm_skx_asm_16x14.c000066400000000000000000000264551422157504600215600ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 UNIVERSITY OF TEXAS 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. */ #include "blis.h" #include "bli_x86_asm_macros.h" #define A_L1_PREFETCH_DIST 4 // in units of k iterations #define B_L1_PREFETCH_DIST 4 // e.g. 4 k iterations ~= 56 cycles #define TAIL_NITER 5 // in units of 4x unrolled k iterations // e.g. 5 -> 4*5 k iterations ~= 280 cycles #define PREFETCH_A_L1(n, k) \ PREFETCH(0, MEM(RAX, A_L1_PREFETCH_DIST*16*8 + (2*n+k)*64)) #define PREFETCH_B_L1(n, k) \ PREFETCH(0, MEM(RBX, B_L1_PREFETCH_DIST*14*8 + (2*n+k)*56)) #define LOOP_ALIGN ALIGN32 #define UPDATE_C(R1,R2) \ \ VMULPD(ZMM(R1), ZMM(R1), ZMM(0)) \ VMULPD(ZMM(R2), ZMM(R2), ZMM(0)) \ VFMADD231PD(ZMM(R1), ZMM(1), MEM(RCX)) \ VFMADD231PD(ZMM(R2), ZMM(1), MEM(RCX,64)) \ VMOVUPD(MEM(RCX), ZMM(R1)) \ VMOVUPD(MEM(RCX,64), ZMM(R2)) \ LEA(RCX, MEM(RCX,RBX,1)) #define UPDATE_C_BZ(R1,R2) \ \ VMULPD(ZMM(R1), ZMM(R1), ZMM(0)) \ VMULPD(ZMM(R2), ZMM(R2), ZMM(0)) \ VMOVUPD(MEM(RCX), ZMM(R1)) \ VMOVUPD(MEM(RCX,64), ZMM(R2)) \ LEA(RCX, MEM(RCX,RBX,1)) #define UPDATE_C_COL_SCATTERED(R1,R2) \ \ KXNORW(K(1), K(0), K(0)) \ KXNORW(K(2), K(0), K(0)) \ KXNORW(K(3), K(0), K(0)) \ KXNORW(K(4), K(0), K(0)) \ VGATHERQPD(ZMM(0) MASK_K(1), MEM(RCX,ZMM(2),1)) \ VFMADD231PD(ZMM(R1), ZMM(0), ZMM(1)) \ VGATHERQPD(ZMM(0) MASK_K(2), MEM(RCX,ZMM(3),1)) \ VFMADD231PD(ZMM(R2), ZMM(0), ZMM(1)) \ VSCATTERQPD(MEM(RCX,ZMM(2),1) MASK_K(3), ZMM(R1)) \ VSCATTERQPD(MEM(RCX,ZMM(3),1) MASK_K(4), ZMM(R2)) \ LEA(RCX, MEM(RCX,RBX,1)) #define UPDATE_C_BZ_COL_SCATTERED(R1,R2) \ \ KXNORW(K(1), K(0), K(0)) \ KXNORW(K(2), K(0), K(0)) \ VSCATTERQPD(MEM(RCX,ZMM(2),1) MASK_K(1), ZMM(R1)) \ VSCATTERQPD(MEM(RCX,ZMM(3),1) MASK_K(2), ZMM(R2)) \ LEA(RCX, MEM(RCX,RBX,1)) #define SUBITER(n) \ \ PREFETCH_A_L1(n, 0) \ \ VBROADCASTSD(ZMM(2), MEM(RBX,(14*n+ 0)*8)) \ VBROADCASTSD(ZMM(3), MEM(RBX,(14*n+ 1)*8)) \ VFMADD231PD(ZMM( 4), ZMM(0), ZMM(2)) \ VFMADD231PD(ZMM( 5), ZMM(1), ZMM(2)) \ VFMADD231PD(ZMM( 6), ZMM(0), ZMM(3)) \ VFMADD231PD(ZMM( 7), ZMM(1), ZMM(3)) \ \ VBROADCASTSD(ZMM(2), MEM(RBX,(14*n+ 2)*8)) \ VBROADCASTSD(ZMM(3), MEM(RBX,(14*n+ 3)*8)) \ VFMADD231PD(ZMM( 8), ZMM(0), ZMM(2)) \ VFMADD231PD(ZMM( 9), ZMM(1), ZMM(2)) \ VFMADD231PD(ZMM(10), ZMM(0), ZMM(3)) \ VFMADD231PD(ZMM(11), ZMM(1), ZMM(3)) \ \ PREFETCH_B_L1(n, 0) \ \ VBROADCASTSD(ZMM(2), MEM(RBX,(14*n+ 4)*8)) \ VBROADCASTSD(ZMM(3), MEM(RBX,(14*n+ 5)*8)) \ VFMADD231PD(ZMM(12), ZMM(0), ZMM(2)) \ VFMADD231PD(ZMM(13), ZMM(1), ZMM(2)) \ VFMADD231PD(ZMM(14), ZMM(0), ZMM(3)) \ VFMADD231PD(ZMM(15), ZMM(1), ZMM(3)) \ \ VBROADCASTSD(ZMM(2), MEM(RBX,(14*n+ 6)*8)) \ VBROADCASTSD(ZMM(3), MEM(RBX,(14*n+ 7)*8)) \ VFMADD231PD(ZMM(16), ZMM(0), ZMM(2)) \ VFMADD231PD(ZMM(17), ZMM(1), ZMM(2)) \ VFMADD231PD(ZMM(18), ZMM(0), ZMM(3)) \ VFMADD231PD(ZMM(19), ZMM(1), ZMM(3)) \ \ PREFETCH_A_L1(n, 1) \ \ VBROADCASTSD(ZMM(2), MEM(RBX,(14*n+ 8)*8)) \ VBROADCASTSD(ZMM(3), MEM(RBX,(14*n+ 9)*8)) \ VFMADD231PD(ZMM(20), ZMM(0), ZMM(2)) \ VFMADD231PD(ZMM(21), ZMM(1), ZMM(2)) \ VFMADD231PD(ZMM(22), ZMM(0), ZMM(3)) \ VFMADD231PD(ZMM(23), ZMM(1), ZMM(3)) \ \ VBROADCASTSD(ZMM(2), MEM(RBX,(14*n+10)*8)) \ VBROADCASTSD(ZMM(3), MEM(RBX,(14*n+11)*8)) \ VFMADD231PD(ZMM(24), ZMM(0), ZMM(2)) \ VFMADD231PD(ZMM(25), ZMM(1), ZMM(2)) \ VFMADD231PD(ZMM(26), ZMM(0), ZMM(3)) \ VFMADD231PD(ZMM(27), ZMM(1), ZMM(3)) \ \ PREFETCH_B_L1(n, 1) \ \ VBROADCASTSD(ZMM(2), MEM(RBX,(14*n+12)*8)) \ VBROADCASTSD(ZMM(3), MEM(RBX,(14*n+13)*8)) \ VFMADD231PD(ZMM(28), ZMM(0), ZMM(2)) \ VFMADD231PD(ZMM(29), ZMM(1), ZMM(2)) \ VFMADD231PD(ZMM(30), ZMM(0), ZMM(3)) \ VFMADD231PD(ZMM(31), ZMM(1), ZMM(3)) \ \ VMOVAPD(ZMM(0), MEM(RAX,(16*n+0)*8)) \ VMOVAPD(ZMM(1), MEM(RAX,(16*n+8)*8)) //This is an array used for the scatter/gather instructions. static int64_t offsets[16] __attribute__((aligned(64))) = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15}; void bli_dgemm_skx_asm_16x14 ( dim_t m, dim_t n, dim_t k_, double* restrict alpha, double* restrict a, double* restrict b, double* restrict beta, double* restrict c, inc_t rs_c_, inc_t cs_c_, auxinfo_t* data, cntx_t* restrict cntx ) { (void)data; (void)cntx; int64_t k = k_; int64_t rs_c = rs_c_; int64_t cs_c = cs_c_; GEMM_UKR_SETUP_CT( d, 16, 14, false ); BEGIN_ASM() VXORPD(YMM( 4), YMM( 4), YMM( 4)) //clear out registers VXORPD(YMM( 5), YMM( 5), YMM( 5)) VXORPD(YMM( 6), YMM( 6), YMM( 6)) VXORPD(YMM( 7), YMM( 7), YMM( 7)) VXORPD(YMM( 8), YMM( 8), YMM( 8)) VXORPD(YMM( 9), YMM( 9), YMM( 9)) VXORPD(YMM(10), YMM(10), YMM(10)) VXORPD(YMM(11), YMM(11), YMM(11)) VXORPD(YMM(12), YMM(12), YMM(12)) VXORPD(YMM(13), YMM(13), YMM(13)) VXORPD(YMM(14), YMM(14), YMM(14)) VXORPD(YMM(15), YMM(15), YMM(15)) VXORPD(YMM(16), YMM(16), YMM(16)) VXORPD(YMM(17), YMM(17), YMM(17)) VXORPD(YMM(18), YMM(18), YMM(18)) VXORPD(YMM(19), YMM(19), YMM(19)) VXORPD(YMM(20), YMM(20), YMM(20)) VXORPD(YMM(21), YMM(21), YMM(21)) VXORPD(YMM(22), YMM(22), YMM(22)) VXORPD(YMM(23), YMM(23), YMM(23)) VXORPD(YMM(24), YMM(24), YMM(24)) VXORPD(YMM(25), YMM(25), YMM(25)) VXORPD(YMM(26), YMM(26), YMM(26)) VXORPD(YMM(27), YMM(27), YMM(27)) VXORPD(YMM(28), YMM(28), YMM(28)) VXORPD(YMM(29), YMM(29), YMM(29)) VXORPD(YMM(30), YMM(30), YMM(30)) VXORPD(YMM(31), YMM(31), YMM(31)) MOV(RSI, VAR(k)) //loop index MOV(RAX, VAR(a)) //load address of a MOV(RBX, VAR(b)) //load address of b MOV(RCX, VAR(c)) //load address of c LEA(RDX, MEM(RSI,RSI,2)) LEA(RDX, MEM(,RDX,4)) LEA(RDX, MEM(RDX,RSI,2)) // 14*k LEA(RDX, MEM(RBX,RDX,8,-128)) // b_next LEA(R9, MEM(RCX,63)) // c for prefetching VMOVAPD(ZMM(0), MEM(RAX, 0*8)) //pre-load a VMOVAPD(ZMM(1), MEM(RAX, 8*8)) //pre-load a LEA(RAX, MEM(RAX,16*8)) //adjust a for pre-load MOV(R12, VAR(rs_c)) MOV(R10, VAR(cs_c)) LEA(R12, MEM(,R12,8)) LEA(R10, MEM(,R10,8)) MOV(RDI, RSI) AND(RSI, IMM(3)) SAR(RDI, IMM(2)) SUB(RDI, IMM(14+TAIL_NITER)) JLE(K_LE_80) LOOP_ALIGN LABEL(LOOP1) SUBITER(0) PREFETCH(1, MEM(RDX)) SUBITER(1) SUB(RDI, IMM(1)) SUBITER(2) PREFETCH(1, MEM(RDX,64)) SUBITER(3) LEA(RAX, MEM(RAX,4*16*8)) LEA(RBX, MEM(RBX,4*14*8)) LEA(RDX, MEM(RDX,16*8)) JNZ(LOOP1) LABEL(K_LE_80) ADD(RDI, IMM(14)) JLE(K_LE_24) LOOP_ALIGN LABEL(LOOP2) PREFETCH(0, MEM(R9)) SUBITER(0) PREFETCH(1, MEM(RDX)) SUBITER(1) PREFETCH(0, MEM(R9,64)) SUB(RDI, IMM(1)) SUBITER(2) PREFETCH(1, MEM(RDX,64)) SUBITER(3) LEA(RAX, MEM(RAX,4*16*8)) LEA(RBX, MEM(RBX,4*14*8)) LEA(RDX, MEM(RDX,16*8)) LEA(R9, MEM(R9,R10,1)) JNZ(LOOP2) LABEL(K_LE_24) ADD(RDI, IMM(0+TAIL_NITER)) JLE(TAIL) LOOP_ALIGN LABEL(LOOP3) SUBITER(0) PREFETCH(1, MEM(RDX)) SUBITER(1) SUB(RDI, IMM(1)) SUBITER(2) PREFETCH(1, MEM(RDX,64)) SUBITER(3) LEA(RAX, MEM(RAX,4*16*8)) LEA(RBX, MEM(RBX,4*14*8)) LEA(RDX, MEM(RDX,16*8)) JNZ(LOOP3) LABEL(TAIL) TEST(RSI, RSI) JZ(POSTACCUM) LOOP_ALIGN LABEL(TAIL_LOOP) SUB(RSI, IMM(1)) SUBITER(0) LEA(RAX, MEM(RAX,16*8)) LEA(RBX, MEM(RBX,14*8)) JNZ(TAIL_LOOP) LABEL(POSTACCUM) MOV(RAX, VAR(alpha)) MOV(RBX, VAR(beta)) VBROADCASTSD(ZMM(0), MEM(RAX)) VBROADCASTSD(ZMM(1), MEM(RBX)) VXORPD(YMM(2), YMM(2), YMM(2)) MOV(RAX, R12) MOV(RBX, R10) VCOMISD(XMM(1), XMM(2)) JE(COLSTORBZ) UPDATE_C( 4, 5) UPDATE_C( 6, 7) UPDATE_C( 8, 9) UPDATE_C(10,11) UPDATE_C(12,13) UPDATE_C(14,15) UPDATE_C(16,17) UPDATE_C(18,19) UPDATE_C(20,21) UPDATE_C(22,23) UPDATE_C(24,25) UPDATE_C(26,27) UPDATE_C(28,29) UPDATE_C(30,31) JMP(END) LABEL(COLSTORBZ) UPDATE_C_BZ( 4, 5) UPDATE_C_BZ( 6, 7) UPDATE_C_BZ( 8, 9) UPDATE_C_BZ(10,11) UPDATE_C_BZ(12,13) UPDATE_C_BZ(14,15) UPDATE_C_BZ(16,17) UPDATE_C_BZ(18,19) UPDATE_C_BZ(20,21) UPDATE_C_BZ(22,23) UPDATE_C_BZ(24,25) UPDATE_C_BZ(26,27) UPDATE_C_BZ(28,29) UPDATE_C_BZ(30,31) LABEL(END) VZEROUPPER() END_ASM ( : // output operands : // input operands [k] "m" (k), [a] "m" (a), [b] "m" (b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c) : // register clobber list "rax", "rbx", "rcx", "rdx", "rdi", "rsi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "zmm0", "zmm1", "zmm2", "zmm3", "zmm4", "zmm5", "zmm6", "zmm7", "zmm8", "zmm9", "zmm10", "zmm11", "zmm12", "zmm13", "zmm14", "zmm15", "zmm16", "zmm17", "zmm18", "zmm19", "zmm20", "zmm21", "zmm22", "zmm23", "zmm24", "zmm25", "zmm26", "zmm27", "zmm28", "zmm29", "zmm30", "zmm31", "memory" ) GEMM_UKR_FLUSH_CT( d ); } blis-0.9.0/kernels/skx/3/bli_sgemm_skx_asm_32x12_l2.c000066400000000000000000000403171422157504600221610ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 UNIVERSITY OF TEXAS 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. */ #include "blis.h" #define BLIS_ASM_SYNTAX_INTEL #include "bli_x86_asm_macros.h" #define CACHELINE_SIZE 64 //size of cache line in bytes #define A_L1_PREFETCH_DIST 4 //should be multiple of 2 /*The pointer of B is moved ahead by one iteration of k before the loop starts.Therefore, prefetching 3 k iterations ahead*/ #define B_L1_PREFETCH_DIST 4 #define TAIL_NITER 8 /* During each subiteration, prefetching 2 cache lines of B * UNROLL factor ahead. 2cache lines = 32 floats (NR). * */ #define PREFETCH_A_L1(n, k) \ PREFETCH(0, MEM(RAX, A_L1_PREFETCH_DIST*32*4 + (2*n+k) * CACHELINE_SIZE)) #define LOOP_ALIGN ALIGN16 #define UPDATE_C(R1,R2,R3,R4) \ \ VMULPS(ZMM(R1), ZMM(R1), ZMM(0)) \ VMULPS(ZMM(R2), ZMM(R2), ZMM(0)) \ VMULPS(ZMM(R3), ZMM(R3), ZMM(0)) \ VMULPS(ZMM(R4), ZMM(R4), ZMM(0)) \ VFMADD231PS(ZMM(R1), ZMM(1), MEM(RCX,0*64)) \ VFMADD231PS(ZMM(R2), ZMM(1), MEM(RCX,1*64)) \ VFMADD231PS(ZMM(R3), ZMM(1), MEM(RCX,RAX,1,0*64)) \ VFMADD231PS(ZMM(R4), ZMM(1), MEM(RCX,RAX,1,1*64)) \ VMOVUPS(MEM(RCX,0*64), ZMM(R1)) \ VMOVUPS(MEM(RCX,1*64), ZMM(R2)) \ VMOVUPS(MEM(RCX,RAX,1,0*64), ZMM(R3)) \ VMOVUPS(MEM(RCX,RAX,1,1*64), ZMM(R4)) \ LEA(RCX, MEM(RCX,RAX,2)) #define UPDATE_C_BZ(R1,R2,R3,R4) \ \ VMULPS(ZMM(R1), ZMM(R1), ZMM(0)) \ VMULPS(ZMM(R2), ZMM(R2), ZMM(0)) \ VMULPS(ZMM(R3), ZMM(R3), ZMM(0)) \ VMULPS(ZMM(R4), ZMM(R4), ZMM(0)) \ VMOVUPS(MEM(RCX,0*64), ZMM(R1)) \ VMOVUPS(MEM(RCX,1*64), ZMM(R2)) \ VMOVUPS(MEM(RCX,RAX,1,0*64), ZMM(R3)) \ VMOVUPS(MEM(RCX,RAX,1,1*64), ZMM(R4)) \ LEA(RCX, MEM(RCX,RAX,2)) #define UPDATE_C_ROW_SCATTERED(R1,R2,R3,R4) \ \ KXNORW(K(1), K(0), K(0)) \ KXNORW(K(2), K(0), K(0)) \ KXNORW(K(3), K(0), K(0)) \ KXNORW(K(4), K(0), K(0)) \ VMULPS(ZMM(R1), ZMM(R1), ZMM(0)) \ VEXTRACTF64X4(YMM(5), ZMM(R1), IMM(1)) \ VGATHERQPS(YMM(6) MASK_K(1), MEM(RCX,ZMM(2),1)) \ VGATHERQPS(YMM(7) MASK_K(2), MEM(RCX,ZMM(3),1)) \ VFMADD231PS(YMM(R1), YMM(6), YMM(1)) \ VFMADD231PS(YMM( 5), YMM(7), YMM(1)) \ VSCATTERQPS(MEM(RCX,ZMM(2),1) MASK_K(3), YMM(R1)) \ VSCATTERQPS(MEM(RCX,ZMM(3),1) MASK_K(4), YMM( 5)) \ \ KXNORW(K(1), K(0), K(0)) \ KXNORW(K(2), K(0), K(0)) \ KXNORW(K(3), K(0), K(0)) \ KXNORW(K(4), K(0), K(0)) \ VMULPS(ZMM(R2), ZMM(R2), ZMM(0)) \ VEXTRACTF64X4(YMM(5), ZMM(R2), IMM(1)) \ VGATHERQPS(YMM(6) MASK_K(1), MEM(RDX,ZMM(2),1)) \ VGATHERQPS(YMM(7) MASK_K(2), MEM(RDX,ZMM(3),1)) \ VFMADD231PS(YMM(R2), YMM(6), YMM(1)) \ VFMADD231PS(YMM( 5), YMM(7), YMM(1)) \ VSCATTERQPS(MEM(RDX,ZMM(2),1) MASK_K(3), YMM(R2)) \ VSCATTERQPS(MEM(RDX,ZMM(3),1) MASK_K(4), YMM( 5)) \ \ LEA(RCX, MEM(RCX,RAX,1)) \ LEA(RDX, MEM(RDX,RAX,1)) \ \ KXNORW(K(1), K(0), K(0)) \ KXNORW(K(2), K(0), K(0)) \ KXNORW(K(3), K(0), K(0)) \ KXNORW(K(4), K(0), K(0)) \ VMULPS(ZMM(R3), ZMM(R3), ZMM(0)) \ VEXTRACTF64X4(YMM(5), ZMM(R3), IMM(1)) \ VGATHERQPS(YMM(6) MASK_K(1), MEM(RCX,ZMM(2),1)) \ VGATHERQPS(YMM(7) MASK_K(2), MEM(RCX,ZMM(3),1)) \ VFMADD231PS(YMM(R3), YMM(6), YMM(1)) \ VFMADD231PS(YMM( 5), YMM(7), YMM(1)) \ VSCATTERQPS(MEM(RCX,ZMM(2),1) MASK_K(3), YMM(R3)) \ VSCATTERQPS(MEM(RCX,ZMM(3),1) MASK_K(4), YMM( 5)) \ \ KXNORW(K(1), K(0), K(0)) \ KXNORW(K(2), K(0), K(0)) \ KXNORW(K(3), K(0), K(0)) \ KXNORW(K(4), K(0), K(0)) \ VMULPS(ZMM(R4), ZMM(R4), ZMM(0)) \ VEXTRACTF64X4(YMM(5), ZMM(R4), IMM(1)) \ VGATHERQPS(YMM(6) MASK_K(1), MEM(RDX,ZMM(2),1)) \ VGATHERQPS(YMM(7) MASK_K(2), MEM(RDX,ZMM(3),1)) \ VFMADD231PS(YMM(R4), YMM(6), YMM(1)) \ VFMADD231PS(YMM( 5), YMM(7), YMM(1)) \ VSCATTERQPS(MEM(RDX,ZMM(2),1) MASK_K(3), YMM(R4)) \ VSCATTERQPS(MEM(RDX,ZMM(3),1) MASK_K(4), YMM( 5)) \ \ LEA(RCX, MEM(RCX,RAX,1)) \ LEA(RDX, MEM(RDX,RAX,1)) #define UPDATE_C_BZ_ROW_SCATTERED(R1,R2,R3,R4) \ \ KXNORW(K(1), K(0), K(0)) \ KXNORW(K(2), K(0), K(0)) \ VMULPS(ZMM(R1), ZMM(R1), ZMM(0)) \ VEXTRACTF64X4(YMM(5), ZMM(R1), IMM(1)) \ VSCATTERQPS(MEM(RCX,ZMM(2),1) MASK_K(1), YMM(R1)) \ VSCATTERQPS(MEM(RCX,ZMM(3),1) MASK_K(2), YMM( 5)) \ \ KXNORW(K(1), K(0), K(0)) \ KXNORW(K(2), K(0), K(0)) \ VMULPS(ZMM(R2), ZMM(R2), ZMM(0)) \ VEXTRACTF64X4(YMM(5), ZMM(R2), IMM(1)) \ VSCATTERQPS(MEM(RDX,ZMM(2),1) MASK_K(1), YMM(R2)) \ VSCATTERQPS(MEM(RDX,ZMM(3),1) MASK_K(2), YMM( 5)) \ \ LEA(RCX, MEM(RCX,RAX,1)) \ LEA(RDX, MEM(RDX,RAX,1)) \ \ KXNORW(K(1), K(0), K(0)) \ KXNORW(K(2), K(0), K(0)) \ VMULPS(ZMM(R3), ZMM(R3), ZMM(0)) \ VEXTRACTF64X4(YMM(5), ZMM(R3), IMM(1)) \ VSCATTERQPS(MEM(RCX,ZMM(2),1) MASK_K(1), YMM(R3)) \ VSCATTERQPS(MEM(RCX,ZMM(3),1) MASK_K(2), YMM( 5)) \ \ KXNORW(K(1), K(0), K(0)) \ KXNORW(K(2), K(0), K(0)) \ VMULPS(ZMM(R4), ZMM(R4), ZMM(0)) \ VEXTRACTF64X4(YMM(5), ZMM(R4), IMM(1)) \ VSCATTERQPS(MEM(RDX,ZMM(2),1) MASK_K(1), YMM(R4)) \ VSCATTERQPS(MEM(RDX,ZMM(3),1) MASK_K(2), YMM( 5)) \ \ LEA(RCX, MEM(RCX,RAX,1)) \ LEA(RDX, MEM(RDX,RAX,1)) #ifdef PREFETCH_C_L2 #undef PREFETCH_C_L2 #define PREFETCH_C_L2 \ \ PREFETCH(1, MEM(RCX, 0*64)) \ PREFETCH(1, MEM(RCX, 1*64)) \ \ PREFETCH(1, MEM(RCX,R12,1,0*64)) \ PREFETCH(1, MEM(RCX,R12,1,1*64)) \ \ PREFETCH(1, MEM(RCX,R12,2,0*64)) \ PREFETCH(1, MEM(RCX,R12,2,1*64)) \ \ PREFETCH(1, MEM(RCX,R13,1,0*64)) \ PREFETCH(1, MEM(RCX,R13,1,1*64)) \ \ PREFETCH(1, MEM(RCX,R12,4,0*64)) \ PREFETCH(1, MEM(RCX,R12,4,1*64)) \ \ PREFETCH(1, MEM(RCX,R14,1,0*64)) \ PREFETCH(1, MEM(RCX,R14,1,1*64)) \ \ PREFETCH(1, MEM(RCX,R13,2,0*64)) \ PREFETCH(1, MEM(RCX,R13,2,1*64)) \ \ PREFETCH(1, MEM(RCX,R15,1,0*64)) \ PREFETCH(1, MEM(RCX,R15,1,1*64)) \ \ PREFETCH(1, MEM(RDX, 0*64)) \ PREFETCH(1, MEM(RDX, 1*64)) \ \ PREFETCH(1, MEM(RDX,R12,1,0*64)) \ PREFETCH(1, MEM(RDX,R12,1,1*64)) \ \ PREFETCH(1, MEM(RDX,R12,2,0*64)) \ PREFETCH(1, MEM(RDX,R12,2,1*64)) \ \ PREFETCH(1, MEM(RDX,R13,1,0*64)) \ PREFETCH(1, MEM(RDX,R13,1,1*64)) #else #undef PREFETCH_C_L2 #define PREFETCH_C_L2 #endif #define PREFETCH_C_L1 \ \ PREFETCHW0(MEM(RCX, 0*64)) \ PREFETCHW0(MEM(RCX, 1*64)) \ PREFETCHW0(MEM(RCX,R12,1,0*64)) \ PREFETCHW0(MEM(RCX,R12,1,1*64)) \ PREFETCHW0(MEM(RCX,R12,2,0*64)) \ PREFETCHW0(MEM(RCX,R12,2,1*64)) \ PREFETCHW0(MEM(RCX,R13,1,0*64)) \ PREFETCHW0(MEM(RCX,R13,1,1*64)) \ PREFETCHW0(MEM(RCX,R12,4,0*64)) \ PREFETCHW0(MEM(RCX,R12,4,1*64)) \ PREFETCHW0(MEM(RCX,R14,1,0*64)) \ PREFETCHW0(MEM(RCX,R14,1,1*64)) \ PREFETCHW0(MEM(RCX,R13,2,0*64)) \ PREFETCHW0(MEM(RCX,R13,2,1*64)) \ PREFETCHW0(MEM(RCX,R15,1,0*64)) \ PREFETCHW0(MEM(RCX,R15,1,1*64)) \ PREFETCHW0(MEM(RDX, 0*64)) \ PREFETCHW0(MEM(RDX, 1*64)) \ PREFETCHW0(MEM(RDX,R12,1,0*64)) \ PREFETCHW0(MEM(RDX,R12,1,1*64)) \ PREFETCHW0(MEM(RDX,R12,2,0*64)) \ PREFETCHW0(MEM(RDX,R12,2,1*64)) \ PREFETCHW0(MEM(RDX,R13,1,0*64)) \ PREFETCHW0(MEM(RDX,R13,1,1*64)) // // n: index in unrolled loop // // a: ZMM register to load into // b: ZMM register to read from // // ...: addressing for B, except for offset // #define SUBITER(n) \ \ PREFETCH_A_L1(n, 0) \ \ VBROADCASTSS(ZMM(3), MEM(RBX,(12*n+ 0)*4)) \ VBROADCASTSS(ZMM(4), MEM(RBX,(12*n+ 1)*4)) \ VFMADD231PS(ZMM( 8), ZMM(0), ZMM(3)) \ VFMADD231PS(ZMM( 9), ZMM(1), ZMM(3)) \ VFMADD231PS(ZMM(10), ZMM(0), ZMM(4)) \ VFMADD231PS(ZMM(11), ZMM(1), ZMM(4)) \ \ VBROADCASTSS(ZMM(3), MEM(RBX,(12*n+ 2)*4)) \ VBROADCASTSS(ZMM(4), MEM(RBX,(12*n+ 3)*4)) \ VFMADD231PS(ZMM(12), ZMM(0), ZMM(3)) \ VFMADD231PS(ZMM(13), ZMM(1), ZMM(3)) \ VFMADD231PS(ZMM(14), ZMM(0), ZMM(4)) \ VFMADD231PS(ZMM(15), ZMM(1), ZMM(4)) \ \ VBROADCASTSS(ZMM(3), MEM(RBX,(12*n+ 4)*4)) \ VBROADCASTSS(ZMM(4), MEM(RBX,(12*n+ 5)*4)) \ VFMADD231PS(ZMM(16), ZMM(0), ZMM(3)) \ VFMADD231PS(ZMM(17), ZMM(1), ZMM(3)) \ VFMADD231PS(ZMM(18), ZMM(0), ZMM(4)) \ VFMADD231PS(ZMM(19), ZMM(1), ZMM(4)) \ \ PREFETCH_A_L1(n, 1) \ \ VBROADCASTSS(ZMM(3), MEM(RBX,(12*n+ 6)*4)) \ VBROADCASTSS(ZMM(4), MEM(RBX,(12*n+ 7)*4)) \ VFMADD231PS(ZMM(20), ZMM(0), ZMM(3)) \ VFMADD231PS(ZMM(21), ZMM(1), ZMM(3)) \ VFMADD231PS(ZMM(22), ZMM(0), ZMM(4)) \ VFMADD231PS(ZMM(23), ZMM(1), ZMM(4)) \ \ VBROADCASTSS(ZMM(3), MEM(RBX,(12*n+ 8)*4)) \ VBROADCASTSS(ZMM(4), MEM(RBX,(12*n+ 9)*4)) \ VFMADD231PS(ZMM(24), ZMM(0), ZMM(3)) \ VFMADD231PS(ZMM(25), ZMM(1), ZMM(3)) \ VFMADD231PS(ZMM(26), ZMM(0), ZMM(4)) \ VFMADD231PS(ZMM(27), ZMM(1), ZMM(4)) \ \ VBROADCASTSS(ZMM(3), MEM(RBX,(12*n+10)*4)) \ VBROADCASTSS(ZMM(4), MEM(RBX,(12*n+11)*4)) \ VFMADD231PS(ZMM(28), ZMM(0), ZMM(3)) \ VFMADD231PS(ZMM(29), ZMM(1), ZMM(3)) \ VFMADD231PS(ZMM(30), ZMM(0), ZMM(4)) \ VFMADD231PS(ZMM(31), ZMM(1), ZMM(4)) \ \ VMOVAPD(ZMM(0), MEM(RAX,(32*n+0)*4)) \ VMOVAPD(ZMM(1), MEM(RAX,(32*n+16)*4)) //This is an array used for the scatter/gather instructions. static int64_t offsets[16] __attribute__((aligned(64))) = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15}; void bli_sgemm_skx_asm_32x12_l2 ( dim_t m, dim_t n, dim_t k_, float* restrict alpha, float* restrict a, float* restrict b, float* restrict beta, float* restrict c, inc_t rs_c_, inc_t cs_c_, auxinfo_t* data, cntx_t* restrict cntx ) { (void)data; (void)cntx; int64_t k = k_; int64_t rs_c = rs_c_; int64_t cs_c = cs_c_; GEMM_UKR_SETUP_CT( s, 32, 12, false ); BEGIN_ASM() VXORPD(YMM(8), YMM(8), YMM(8)) //clear out registers VMOVAPD(YMM( 7), YMM(8)) VMOVAPD(YMM( 9), YMM(8)) VMOVAPD(YMM(10), YMM(8)) MOV(RSI, VAR(k)) //loop index VMOVAPD(YMM(11), YMM(8)) MOV(RAX, VAR(a)) //load address of a VMOVAPD(YMM(12), YMM(8)) MOV(RBX, VAR(b)) //load address of b VMOVAPD(YMM(13), YMM(8)) MOV(RCX, VAR(c)) //load address of c VMOVAPD(YMM(14), YMM(8)) VMOVAPD(YMM(15), YMM(8)) VMOVAPD(ZMM(0), MEM(RAX, 0*4)) //pre-load a VMOVAPD(YMM(16), YMM(8)) VMOVAPD(ZMM(1), MEM(RAX, 16*4)) //pre-load a VMOVAPD(YMM(17), YMM(8)) VMOVAPD(YMM(18), YMM(8)) VMOVAPD(YMM(19), YMM(8)) MOV(R12, VAR(cs_c)) //cs_c VMOVAPD(YMM(20), YMM(8)) LEA(R13, MEM(R12,R12,2)) //*3 VMOVAPD(YMM(21), YMM(8)) LEA(R14, MEM(R12,R12,4)) //*5 VMOVAPD(YMM(22), YMM(8)) LEA(R15, MEM(R14,R12,2)) //*7 VMOVAPD(YMM(23), YMM(8)) LEA(RDX, MEM(RCX,R12,8)) //c + 8*cs_c VMOVAPD(YMM(24), YMM(8)) VMOVAPD(YMM(25), YMM(8)) MOV(R8, IMM(32*4)) //mr*sizeof(float) VMOVAPD(YMM(26), YMM(8)) MOV(R9, IMM(12*4)) //nr*sizeof(float) VMOVAPD(YMM(27), YMM(8)) VMOVAPD(YMM(28), YMM(8)) LEA(RAX, MEM(RAX,R8,1)) //adjust a for pre-load VMOVAPD(YMM(29), YMM(8)) VMOVAPD(YMM(30), YMM(8)) VMOVAPD(YMM(31), YMM(8)) TEST(RSI, RSI) JZ(POSTACCUM) #ifdef PREFETCH_A_BEFORE /* Prefetching 8 cachlines of A (4 iterations worth of data (32 (MR) x4 (sizeof(float)) x4 iter /64 = 8 cachelines) */ PREFETCH(0, MEM(RAX,0*64)) PREFETCH(0, MEM(RAX,1*64)) PREFETCH(0, MEM(RAX,2*64)) PREFETCH(0, MEM(RAX,3*64)) PREFETCH(0, MEM(RAX,4*64)) PREFETCH(0, MEM(RAX,5*64)) PREFETCH(0, MEM(RAX,6*64)) PREFETCH(0, MEM(RAX,7*64)) #endif #ifdef PREFETCH_B_BEFORE /* Prefetching 3 cachlines of B (4 iterations worth of data (12 (NR) x 4 (sizeof(float)) x 4 iter /64 = 3 cachelines) */ PREFETCH(0, MEM(RBX,0*64)) PREFETCH(0, MEM(RBX,1*64)) PREFETCH(0, MEM(RBX,2*64)) #endif PREFETCH_C_L2 MOV(RDI, RSI) AND(RSI, IMM(3)) SAR(RDI, IMM(2)) SUB(RDI, IMM(0+TAIL_NITER)) JLE(K_SMALL) LOOP_ALIGN LABEL(MAIN_LOOP) PREFETCH(0, MEM(RBX,B_L1_PREFETCH_DIST*12*4)) SUBITER(0) PREFETCH(0, MEM(RBX,B_L1_PREFETCH_DIST*12*4+64)) SUBITER(1) PREFETCH(0, MEM(RBX,B_L1_PREFETCH_DIST*12*4+128)) SUBITER(2) SUBITER(3) LEA(RAX, MEM(RAX,R8,4)) LEA(RBX, MEM(RBX,R9,4)) DEC(RDI) JNZ(MAIN_LOOP) LABEL(K_SMALL) PREFETCH_C_L1 ADD(RDI, IMM(0+TAIL_NITER)) JZ(TAIL_LOOP) LOOP_ALIGN LABEL(SMALL_LOOP) PREFETCH(0, MEM(RBX,B_L1_PREFETCH_DIST*12*4)) SUBITER(0) PREFETCH(0, MEM(RBX,B_L1_PREFETCH_DIST*12*4+64)) SUBITER(1) PREFETCH(0, MEM(RBX,B_L1_PREFETCH_DIST*12*4+128)) SUBITER(2) SUBITER(3) LEA(RAX, MEM(RAX,R8,4)) LEA(RBX, MEM(RBX,R9,4)) DEC(RDI) JNZ(SMALL_LOOP) TEST(RSI, RSI) JZ(POSTACCUM) LOOP_ALIGN LABEL(TAIL_LOOP) PREFETCH(0, MEM(RBX,B_L1_PREFETCH_DIST*12*4)) SUBITER(0) ADD(RAX, R8) ADD(RBX, R9) DEC(RSI) JNZ(TAIL_LOOP) LABEL(POSTACCUM) #ifdef PREFETCH_A_AFTER MOV(R8, VAR(a)) PREFETCH(0, MEM(R8,0*64)) PREFETCH(0, MEM(R8,1*64)) PREFETCH(0, MEM(R8,2*64)) PREFETCH(0, MEM(R8,3*64)) PREFETCH(0, MEM(R8,4*64)) PREFETCH(0, MEM(R8,5*64)) PREFETCH(0, MEM(R8,6*64)) PREFETCH(0, MEM(R8,7*64)) #endif #ifdef PREFETCH_B_AFTER MOV(R9, VAR(b)) PREFETCH(0, MEM(R9,0*64)) PREFETCH(0, MEM(R9,1*64)) PREFETCH(0, MEM(R9,2*64)) #endif MOV(RAX, VAR(alpha)) MOV(RBX, VAR(beta)) VBROADCASTSS(ZMM(0), MEM(RAX)) VBROADCASTSS(ZMM(1), MEM(RBX)) MOV(RAX, VAR(cs_c)) LEA(RAX, MEM(,RAX,4)) VCOMISS(XMM(1), XMM(7)) JE(COLSTORBZ) UPDATE_C( 8, 9,10,11) UPDATE_C(12,13,14,15) UPDATE_C(16,17,18,19) UPDATE_C(20,21,22,23) UPDATE_C(24,25,26,27) UPDATE_C(28,29,30,31) JMP(END) LABEL(COLSTORBZ) UPDATE_C_BZ( 8, 9,10,11) UPDATE_C_BZ(12,13,14,15) UPDATE_C_BZ(16,17,18,19) UPDATE_C_BZ(20,21,22,23) UPDATE_C_BZ(24,25,26,27) UPDATE_C_BZ(28,29,30,31) LABEL(END) VZEROUPPER() END_ASM( : // output operands : // input operands [k] "m" (k), [a] "m" (a), [b] "m" (b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c) : // register clobber list "rax", "rbx", "rcx", "rdx", "rdi", "rsi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "zmm0", "zmm1", "zmm2", "zmm3", "zmm4", "zmm5", "zmm6", "zmm7", "zmm8", "zmm9", "zmm10", "zmm11", "zmm12", "zmm13", "zmm14", "zmm15", "zmm16", "zmm17", "zmm18", "zmm19", "zmm20", "zmm21", "zmm22", "zmm23", "zmm24", "zmm25", "zmm26", "zmm27", "zmm28", "zmm29", "zmm30", "zmm31", "memory" ) GEMM_UKR_FLUSH_CT( s ); } blis-0.9.0/kernels/skx/bli_kernels_skx.h000066400000000000000000000035311422157504600202600ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ GEMM_UKR_PROT( float , s, gemm_skx_asm_32x12_l2 ) GEMM_UKR_PROT( float , s, gemm_skx_asm_12x32_l2 ) GEMM_UKR_PROT( double, d, gemm_skx_asm_16x12_l2 ) GEMM_UKR_PROT( double, d, gemm_skx_asm_16x14 ) blis-0.9.0/kernels/zen/000077500000000000000000000000001422157504600147165ustar00rootroot00000000000000blis-0.9.0/kernels/zen/1/000077500000000000000000000000001422157504600150565ustar00rootroot00000000000000blis-0.9.0/kernels/zen/1/bli_amaxv_zen_int.c000066400000000000000000000414671422157504600207260ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2016 - 2018 - 2019, Advanced Micro Devices, Inc. Copyright (C) 2018, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "immintrin.h" #include "blis.h" /* Union data structure to access AVX registers One 256-bit AVX register holds 8 SP elements. */ typedef union { __m256 v; float f[8] __attribute__((aligned(64))); } v8sf_t; typedef union { __m128 v; float f[4]; } v4sf_t; /* Union data structure to access AVX registers One 256-bit AVX register holds 4 DP elements. */ typedef union { __m256d v; double d[4] __attribute__((aligned(64))); }v4df_t; typedef union { __m128d v; double d[2]; }v2dd_t; // return a mask which indicates either: // - v1 > v2 // - v1 is NaN and v2 is not // assumes that idx(v1) > idx(v2) // all "OQ" comparisons false if either operand NaN #define CMP256( dt, v1, v2 ) \ _mm256_or_p##dt( _mm256_cmp_p##dt( v1, v2, _CMP_GT_OQ ), /* v1 > v2 || */ \ _mm256_andnot_p##dt( _mm256_cmp_p##dt( v2, v2, _CMP_UNORD_Q ), /* ( !isnan(v2) && */ \ _mm256_cmp_p##dt( v1, v1, _CMP_UNORD_Q ) /* isnan(v1) ) */ \ ) \ ); // return a mask which indicates either: // - v1 > v2 // - v1 is NaN and v2 is not // - v1 == v2 (maybe == NaN) and i1 < i2 // all "OQ" comparisons false if either operand NaN #define CMP128( dt, v1, v2, i1, i2 ) \ _mm_or_p##dt( _mm_or_p##dt( _mm_cmp_p##dt( v1, v2, _CMP_GT_OQ ), /* ( v1 > v2 || */ \ _mm_andnot_p##dt( _mm_cmp_p##dt( v2, v2, _CMP_UNORD_Q ), /* ( !isnan(v2) && */ \ _mm_cmp_p##dt( v1, v1, _CMP_UNORD_Q ) /* isnan(v1) ) ) || */ \ ) \ ), \ _mm_and_p##dt( _mm_or_p##dt( _mm_cmp_p##dt( v1, v2, _CMP_EQ_OQ ), /* ( ( v1 == v2 || */ \ _mm_and_p##dt( _mm_cmp_p##dt( v1, v1, _CMP_UNORD_Q ), /* ( isnan(v1) && */ \ _mm_cmp_p##dt( v2, v2, _CMP_UNORD_Q ) /* isnan(v2) ) ) && */ \ ) \ ), \ _mm_cmp_p##dt( i1, i2, _CMP_LT_OQ ) /* i1 < i2 ) */ \ ) \ ); // ----------------------------------------------------------------------------- void bli_samaxv_zen_int ( dim_t n, float* restrict x, inc_t incx, dim_t* restrict i_max, cntx_t* restrict cntx ) { float* minus_one = PASTEMAC(s,m1); dim_t* zero_i = PASTEMAC(i,0); float chi1_r; //float chi1_i; float abs_chi1; float abs_chi1_max; dim_t i_max_l; dim_t i; /* If the vector length is zero, return early. This directly emulates the behavior of netlib BLAS's i?amax() routines. */ if ( bli_zero_dim1( n ) ) { PASTEMAC(i,copys)( *zero_i, *i_max ); return; } /* Initialize the index of the maximum absolute value to zero. */ PASTEMAC(i,copys)( *zero_i, i_max_l ); /* Initialize the maximum absolute value search candidate with -1, which is guaranteed to be less than all values we will compute. */ PASTEMAC(s,copys)( *minus_one, abs_chi1_max ); // For non-unit strides, or very small vector lengths, compute with // scalar code. if ( incx != 1 || n < 8 ) { for ( i = 0; i < n; ++i ) { float* chi1 = x + (i )*incx; /* Get the real and imaginary components of chi1. */ chi1_r = *chi1; /* Replace chi1_r and chi1_i with their absolute values. */ chi1_r = fabsf( chi1_r ); /* Add the real and imaginary absolute values together. */ abs_chi1 = chi1_r; /* If the absolute value of the current element exceeds that of the previous largest, save it and its index. If NaN is encountered, then treat it the same as if it were a valid value that was smaller than any previously seen. This behavior mimics that of LAPACK's i?amax(). */ if ( abs_chi1_max < abs_chi1 || ( isnan( abs_chi1 ) && !isnan( abs_chi1_max ) ) ) { abs_chi1_max = abs_chi1; i_max_l = i; } } } else { dim_t n_iter, n_left; dim_t num_vec_elements = 8; v8sf_t x_vec, max_vec, maxInx_vec, mask_vec; v8sf_t idx_vec, inc_vec; v8sf_t sign_mask; v4sf_t max_vec_lo, max_vec_hi, mask_vec_lo; v4sf_t maxInx_vec_lo, maxInx_vec_hi; n_iter = n / num_vec_elements; n_left = n % num_vec_elements; idx_vec.v = _mm256_set_ps( 7, 6, 5, 4, 3, 2, 1, 0 ); inc_vec.v = _mm256_set1_ps( 8 ); max_vec.v = _mm256_set1_ps( -1 ); maxInx_vec.v = _mm256_setzero_ps(); sign_mask.v = _mm256_set1_ps( -0.f ); for ( i = 0; i < n_iter; ++i ) { x_vec.v = _mm256_loadu_ps( x ); // Get the absolute value of the vector element. x_vec.v = _mm256_andnot_ps( sign_mask.v, x_vec.v ); mask_vec.v = CMP256( s, x_vec.v, max_vec.v ); max_vec.v = _mm256_blendv_ps( max_vec.v, x_vec.v, mask_vec.v ); maxInx_vec.v = _mm256_blendv_ps( maxInx_vec.v, idx_vec.v, mask_vec.v ); idx_vec.v += inc_vec.v; x += num_vec_elements; } max_vec_lo.v = _mm256_extractf128_ps( max_vec.v, 0 ); max_vec_hi.v = _mm256_extractf128_ps( max_vec.v, 1 ); maxInx_vec_lo.v = _mm256_extractf128_ps( maxInx_vec.v, 0 ); maxInx_vec_hi.v = _mm256_extractf128_ps( maxInx_vec.v, 1 ); mask_vec_lo.v = CMP128( s, max_vec_hi.v, max_vec_lo.v, maxInx_vec_hi.v, maxInx_vec_lo.v ); max_vec_lo.v = _mm_blendv_ps( max_vec_lo.v, max_vec_hi.v, mask_vec_lo.v ); maxInx_vec_lo.v = _mm_blendv_ps( maxInx_vec_lo.v, maxInx_vec_hi.v, mask_vec_lo.v ); max_vec_hi.v = _mm_permute_ps( max_vec_lo.v, 14 ); maxInx_vec_hi.v = _mm_permute_ps( maxInx_vec_lo.v, 14 ); mask_vec_lo.v = CMP128( s, max_vec_hi.v, max_vec_lo.v, maxInx_vec_hi.v, maxInx_vec_lo.v ); max_vec_lo.v = _mm_blendv_ps( max_vec_lo.v, max_vec_hi.v, mask_vec_lo.v ); maxInx_vec_lo.v = _mm_blendv_ps( maxInx_vec_lo.v, maxInx_vec_hi.v, mask_vec_lo.v ); max_vec_hi.v = _mm_permute_ps( max_vec_lo.v, 1 ); maxInx_vec_hi.v = _mm_permute_ps( maxInx_vec_lo.v, 1 ); mask_vec_lo.v = CMP128( s, max_vec_hi.v, max_vec_lo.v, maxInx_vec_hi.v, maxInx_vec_lo.v ); max_vec_lo.v = _mm_blendv_ps( max_vec_lo.v, max_vec_hi.v, mask_vec_lo.v ); maxInx_vec_lo.v = _mm_blendv_ps( maxInx_vec_lo.v, maxInx_vec_hi.v, mask_vec_lo.v ); abs_chi1_max = max_vec_lo.f[0]; i_max_l = maxInx_vec_lo.f[0]; for ( i = n - n_left; i < n; i++ ) { float* chi1 = x; /* Get the real and imaginary components of chi1. */ chi1_r = *chi1; /* Replace chi1_r and chi1_i with their absolute values. */ abs_chi1 = fabsf( chi1_r ); /* If the absolute value of the current element exceeds that of the previous largest, save it and its index. If NaN is encountered, then treat it the same as if it were a valid value that was smaller than any previously seen. This behavior mimics that of LAPACK's i?amax(). */ if ( abs_chi1_max < abs_chi1 || ( isnan( abs_chi1 ) && !isnan( abs_chi1_max ) ) ) { abs_chi1_max = abs_chi1; i_max_l = i; } x += 1; } } // Issue vzeroupper instruction to clear upper lanes of ymm registers. // This avoids a performance penalty caused by false dependencies when // transitioning from from AVX to SSE instructions (which may occur // later, especially if BLIS is compiled with -mfpmath=sse). _mm256_zeroupper(); /* Store final index to output variable. */ *i_max = i_max_l; } // ----------------------------------------------------------------------------- void bli_damaxv_zen_int ( dim_t n, double* restrict x, inc_t incx, dim_t* restrict i_max, cntx_t* restrict cntx ) { double* minus_one = PASTEMAC(d,m1); dim_t* zero_i = PASTEMAC(i,0); double chi1_r; //double chi1_i; double abs_chi1; double abs_chi1_max; dim_t i_max_l; dim_t i; /* If the vector length is zero, return early. This directly emulates the behavior of netlib BLAS's i?amax() routines. */ if ( bli_zero_dim1( n ) ) { PASTEMAC(i,copys)( *zero_i, *i_max ); return; } /* Initialize the index of the maximum absolute value to zero. */ \ PASTEMAC(i,copys)( *zero_i, i_max_l ); /* Initialize the maximum absolute value search candidate with -1, which is guaranteed to be less than all values we will compute. */ PASTEMAC(d,copys)( *minus_one, abs_chi1_max ); // For non-unit strides, or very small vector lengths, compute with // scalar code. if ( incx != 1 || n < 4 ) { for ( i = 0; i < n; ++i ) { double* chi1 = x + (i )*incx; /* Get the real and imaginary components of chi1. */ chi1_r = *chi1; /* Replace chi1_r and chi1_i with their absolute values. */ chi1_r = fabs( chi1_r ); /* Add the real and imaginary absolute values together. */ abs_chi1 = chi1_r; /* If the absolute value of the current element exceeds that of the previous largest, save it and its index. If NaN is encountered, then treat it the same as if it were a valid value that was smaller than any previously seen. This behavior mimics that of LAPACK's i?amax(). */ if ( abs_chi1_max < abs_chi1 || ( isnan( abs_chi1 ) && !isnan( abs_chi1_max ) ) ) { abs_chi1_max = abs_chi1; i_max_l = i; } } } else { dim_t n_iter, n_left; dim_t num_vec_elements = 4; v4df_t x_vec, max_vec, maxInx_vec, mask_vec; v4df_t idx_vec, inc_vec; v4df_t sign_mask; v2dd_t max_vec_lo, max_vec_hi, mask_vec_lo; v2dd_t maxInx_vec_lo, maxInx_vec_hi; n_iter = n / num_vec_elements; n_left = n % num_vec_elements; idx_vec.v = _mm256_set_pd( 3, 2, 1, 0 ); inc_vec.v = _mm256_set1_pd( 4 ); max_vec.v = _mm256_set1_pd( -1 ); maxInx_vec.v = _mm256_setzero_pd(); sign_mask.v = _mm256_set1_pd( -0.f ); for ( i = 0; i < n_iter; ++i ) { x_vec.v = _mm256_loadu_pd( x ); // Get the absolute value of the vector element. x_vec.v = _mm256_andnot_pd( sign_mask.v, x_vec.v ); mask_vec.v = CMP256( d, x_vec.v, max_vec.v ); max_vec.v = _mm256_blendv_pd( max_vec.v, x_vec.v, mask_vec.v ); maxInx_vec.v = _mm256_blendv_pd( maxInx_vec.v, idx_vec.v, mask_vec.v ); idx_vec.v += inc_vec.v; x += num_vec_elements; } max_vec_lo.v = _mm256_extractf128_pd( max_vec.v, 0 ); max_vec_hi.v = _mm256_extractf128_pd( max_vec.v, 1 ); maxInx_vec_lo.v = _mm256_extractf128_pd( maxInx_vec.v, 0 ); maxInx_vec_hi.v = _mm256_extractf128_pd( maxInx_vec.v, 1 ); mask_vec_lo.v = CMP128( d, max_vec_hi.v, max_vec_lo.v, maxInx_vec_hi.v, maxInx_vec_lo.v ); max_vec_lo.v = _mm_blendv_pd( max_vec_lo.v, max_vec_hi.v, mask_vec_lo.v ); maxInx_vec_lo.v = _mm_blendv_pd( maxInx_vec_lo.v, maxInx_vec_hi.v, mask_vec_lo.v ); max_vec_hi.v = _mm_permute_pd( max_vec_lo.v, 1 ); maxInx_vec_hi.v = _mm_permute_pd( maxInx_vec_lo.v, 1 ); mask_vec_lo.v = CMP128( d, max_vec_hi.v, max_vec_lo.v, maxInx_vec_hi.v, maxInx_vec_lo.v ); max_vec_lo.v = _mm_blendv_pd( max_vec_lo.v, max_vec_hi.v, mask_vec_lo.v ); maxInx_vec_lo.v = _mm_blendv_pd( maxInx_vec_lo.v, maxInx_vec_hi.v, mask_vec_lo.v ); abs_chi1_max = max_vec_lo.d[0]; i_max_l = maxInx_vec_lo.d[0]; for ( i = n - n_left; i < n; i++ ) { double* chi1 = x; /* Get the real and imaginary components of chi1. */ chi1_r = *chi1; /* Replace chi1_r and chi1_i with their absolute values. */ abs_chi1 = fabs( chi1_r ); /* If the absolute value of the current element exceeds that of the previous largest, save it and its index. If NaN is encountered, return the index of the first NaN. This behavior mimics that of LAPACK's i?amax(). */ if ( abs_chi1_max < abs_chi1 || ( isnan( abs_chi1 ) && !isnan( abs_chi1_max ) ) ) { abs_chi1_max = abs_chi1; i_max_l = i; } x += 1; } } // Issue vzeroupper instruction to clear upper lanes of ymm registers. // This avoids a performance penalty caused by false dependencies when // transitioning from from AVX to SSE instructions (which may occur // later, especially if BLIS is compiled with -mfpmath=sse). _mm256_zeroupper(); /* Store final index to output variable. */ *i_max = i_max_l; } // ----------------------------------------------------------------------------- #if 0 #undef GENTFUNCR #define GENTFUNCR( ctype, ctype_r, ch, chr, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ dim_t n, \ ctype* x, inc_t incx, \ dim_t* i_max, \ cntx_t* cntx \ ) \ { \ ctype_r* minus_one = PASTEMAC(chr,m1); \ dim_t* zero_i = PASTEMAC(i,0); \ \ ctype_r chi1_r; \ ctype_r chi1_i; \ ctype_r abs_chi1; \ ctype_r abs_chi1_max; \ dim_t i; \ \ /* Initialize the index of the maximum absolute value to zero. */ \ PASTEMAC(i,copys)( zero_i, *i_max ); \ \ /* If the vector length is zero, return early. This directly emulates the behavior of netlib BLAS's i?amax() routines. */ \ if ( bli_zero_dim1( n ) ) return; \ \ /* Initialize the maximum absolute value search candidate with -1, which is guaranteed to be less than all values we will compute. */ \ PASTEMAC(chr,copys)( *minus_one, abs_chi1_max ); \ \ if ( incx == 1 ) \ { \ for ( i = 0; i < n; ++i ) \ { \ /* Get the real and imaginary components of chi1. */ \ PASTEMAC2(ch,chr,gets)( x[i], chi1_r, chi1_i ); \ \ /* Replace chi1_r and chi1_i with their absolute values. */ \ PASTEMAC(chr,abval2s)( chi1_r, chi1_r ); \ PASTEMAC(chr,abval2s)( chi1_i, chi1_i ); \ \ /* Add the real and imaginary absolute values together. */ \ PASTEMAC(chr,set0s)( abs_chi1 ); \ PASTEMAC(chr,adds)( chi1_r, abs_chi1 ); \ PASTEMAC(chr,adds)( chi1_i, abs_chi1 ); \ \ /* If the absolute value of the current element exceeds that of the previous largest, save it and its index. If NaN is encountered, then treat it the same as if it were a valid value that was smaller than any previously seen. This behavior mimics that of LAPACK's ?lange(). */ \ if ( abs_chi1_max < abs_chi1 || bli_isnan( abs_chi1 ) ) \ { \ abs_chi1_max = abs_chi1; \ *i_max = i; \ } \ } \ } \ else \ { \ for ( i = 0; i < n; ++i ) \ { \ ctype* chi1 = x + (i )*incx; \ \ /* Get the real and imaginary components of chi1. */ \ PASTEMAC2(ch,chr,gets)( *chi1, chi1_r, chi1_i ); \ \ /* Replace chi1_r and chi1_i with their absolute values. */ \ PASTEMAC(chr,abval2s)( chi1_r, chi1_r ); \ PASTEMAC(chr,abval2s)( chi1_i, chi1_i ); \ \ /* Add the real and imaginary absolute values together. */ \ PASTEMAC(chr,set0s)( abs_chi1 ); \ PASTEMAC(chr,adds)( chi1_r, abs_chi1 ); \ PASTEMAC(chr,adds)( chi1_i, abs_chi1 ); \ \ /* If the absolute value of the current element exceeds that of the previous largest, save it and its index. If NaN is encountered, then treat it the same as if it were a valid value that was smaller than any previously seen. This behavior mimics that of LAPACK's ?lange(). */ \ if ( abs_chi1_max < abs_chi1 || bli_isnan( abs_chi1 ) ) \ { \ abs_chi1_max = abs_chi1; \ *i_max = i; \ } \ } \ } \ } GENTFUNCR( scomplex, float, c, s, amaxv_zen_int ) GENTFUNCR( dcomplex, double, z, d, amaxv_zen_int ) #endif blis-0.9.0/kernels/zen/1/bli_axpyv_zen_int.c000066400000000000000000000201631422157504600207470ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2016 - 2019, Advanced Micro Devices, Inc. Copyright (C) 2018, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "immintrin.h" #include "blis.h" /* Union data structure to access AVX registers One 256-bit AVX register holds 8 SP elements. */ typedef union { __m256 v; float f[8] __attribute__((aligned(64))); } v8sf_t; /* Union data structure to access AVX registers * One 256-bit AVX register holds 4 DP elements. */ typedef union { __m256d v; double d[4] __attribute__((aligned(64))); } v4df_t; // ----------------------------------------------------------------------------- void bli_saxpyv_zen_int ( conj_t conjx, dim_t n, float* restrict alpha, float* restrict x, inc_t incx, float* restrict y, inc_t incy, cntx_t* restrict cntx ) { const dim_t n_elem_per_reg = 8; const dim_t n_iter_unroll = 4; dim_t i; dim_t n_viter; dim_t n_left; float* restrict x0; float* restrict y0; v8sf_t alphav; v8sf_t x0v, x1v, x2v, x3v; v8sf_t y0v, y1v, y2v, y3v; // If the vector dimension is zero, or if alpha is zero, return early. if ( bli_zero_dim1( n ) || PASTEMAC(s,eq0)( *alpha ) ) return; // Use the unrolling factor and the number of elements per register // to compute the number of vectorized and leftover iterations. n_viter = ( n ) / ( n_elem_per_reg * n_iter_unroll ); n_left = ( n ) % ( n_elem_per_reg * n_iter_unroll ); // If there is anything that would interfere with our use of contiguous // vector loads/stores, override n_viter and n_left to use scalar code // for all iterations. if ( incx != 1 || incy != 1 ) { n_viter = 0; n_left = n; } // Initialize local pointers. x0 = x; y0 = y; // Broadcast the alpha scalar to all elements of a vector register. alphav.v = _mm256_broadcast_ss( alpha ); // If there are vectorized iterations, perform them with vector // instructions. for ( i = 0; i < n_viter; ++i ) { // Load the input values. y0v.v = _mm256_loadu_ps( y0 + 0*n_elem_per_reg ); x0v.v = _mm256_loadu_ps( x0 + 0*n_elem_per_reg ); y1v.v = _mm256_loadu_ps( y0 + 1*n_elem_per_reg ); x1v.v = _mm256_loadu_ps( x0 + 1*n_elem_per_reg ); y2v.v = _mm256_loadu_ps( y0 + 2*n_elem_per_reg ); x2v.v = _mm256_loadu_ps( x0 + 2*n_elem_per_reg ); y3v.v = _mm256_loadu_ps( y0 + 3*n_elem_per_reg ); x3v.v = _mm256_loadu_ps( x0 + 3*n_elem_per_reg ); // perform : y += alpha * x; y0v.v = _mm256_fmadd_ps( alphav.v, x0v.v, y0v.v ); y1v.v = _mm256_fmadd_ps( alphav.v, x1v.v, y1v.v ); y2v.v = _mm256_fmadd_ps( alphav.v, x2v.v, y2v.v ); y3v.v = _mm256_fmadd_ps( alphav.v, x3v.v, y3v.v ); // Store the output. _mm256_storeu_ps( (y0 + 0*n_elem_per_reg), y0v.v ); _mm256_storeu_ps( (y0 + 1*n_elem_per_reg), y1v.v ); _mm256_storeu_ps( (y0 + 2*n_elem_per_reg), y2v.v ); _mm256_storeu_ps( (y0 + 3*n_elem_per_reg), y3v.v ); x0 += n_elem_per_reg * n_iter_unroll; y0 += n_elem_per_reg * n_iter_unroll; } // Issue vzeroupper instruction to clear upper lanes of ymm registers. // This avoids a performance penalty caused by false dependencies when // transitioning from from AVX to SSE instructions (which may occur // as soon as the n_left cleanup loop below if BLIS is compiled with // -mfpmath=sse). _mm256_zeroupper(); const float alphac = *alpha; // If there are leftover iterations, perform them with scalar code. for ( i = 0; i < n_left; ++i ) { const float x0c = *x0; *y0 += alphac * x0c; x0 += incx; y0 += incy; } } // ----------------------------------------------------------------------------- void bli_daxpyv_zen_int ( conj_t conjx, dim_t n, double* restrict alpha, double* restrict x, inc_t incx, double* restrict y, inc_t incy, cntx_t* restrict cntx ) { const dim_t n_elem_per_reg = 4; const dim_t n_iter_unroll = 4; dim_t i; dim_t n_viter; dim_t n_left; double* restrict x0; double* restrict y0; v4df_t alphav; v4df_t x0v, x1v, x2v, x3v; v4df_t y0v, y1v, y2v, y3v; // If the vector dimension is zero, or if alpha is zero, return early. if ( bli_zero_dim1( n ) || PASTEMAC(d,eq0)( *alpha ) ) return; // Use the unrolling factor and the number of elements per register // to compute the number of vectorized and leftover iterations. n_viter = ( n ) / ( n_elem_per_reg * n_iter_unroll ); n_left = ( n ) % ( n_elem_per_reg * n_iter_unroll ); // If there is anything that would interfere with our use of contiguous // vector loads/stores, override n_viter and n_left to use scalar code // for all iterations. if ( incx != 1 || incy != 1 ) { n_viter = 0; n_left = n; } // Initialize local pointers. x0 = x; y0 = y; // Broadcast the alpha scalar to all elements of a vector register. alphav.v = _mm256_broadcast_sd( alpha ); // If there are vectorized iterations, perform them with vector // instructions. for ( i = 0; i < n_viter; ++i ) { // Load the input values. y0v.v = _mm256_loadu_pd( y0 + 0*n_elem_per_reg ); x0v.v = _mm256_loadu_pd( x0 + 0*n_elem_per_reg ); y1v.v = _mm256_loadu_pd( y0 + 1*n_elem_per_reg ); x1v.v = _mm256_loadu_pd( x0 + 1*n_elem_per_reg ); y2v.v = _mm256_loadu_pd( y0 + 2*n_elem_per_reg ); x2v.v = _mm256_loadu_pd( x0 + 2*n_elem_per_reg ); y3v.v = _mm256_loadu_pd( y0 + 3*n_elem_per_reg ); x3v.v = _mm256_loadu_pd( x0 + 3*n_elem_per_reg ); // perform : y += alpha * x; y0v.v = _mm256_fmadd_pd( alphav.v, x0v.v, y0v.v ); y1v.v = _mm256_fmadd_pd( alphav.v, x1v.v, y1v.v ); y2v.v = _mm256_fmadd_pd( alphav.v, x2v.v, y2v.v ); y3v.v = _mm256_fmadd_pd( alphav.v, x3v.v, y3v.v ); // Store the output. _mm256_storeu_pd( (y0 + 0*n_elem_per_reg), y0v.v ); _mm256_storeu_pd( (y0 + 1*n_elem_per_reg), y1v.v ); _mm256_storeu_pd( (y0 + 2*n_elem_per_reg), y2v.v ); _mm256_storeu_pd( (y0 + 3*n_elem_per_reg), y3v.v ); x0 += n_elem_per_reg * n_iter_unroll; y0 += n_elem_per_reg * n_iter_unroll; } // Issue vzeroupper instruction to clear upper lanes of ymm registers. // This avoids a performance penalty caused by false dependencies when // transitioning from from AVX to SSE instructions (which may occur // as soon as the n_left cleanup loop below if BLIS is compiled with // -mfpmath=sse). _mm256_zeroupper(); const double alphac = *alpha; // If there are leftover iterations, perform them with scalar code. for ( i = 0; i < n_left; ++i ) { const double x0c = *x0; *y0 += alphac * x0c; x0 += incx; y0 += incy; } } blis-0.9.0/kernels/zen/1/bli_axpyv_zen_int10.c000066400000000000000000000363431422157504600211170ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2016 - 2019, Advanced Micro Devices, Inc. Copyright (C) 2018, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "immintrin.h" #include "blis.h" /* Union data structure to access AVX registers One 256-bit AVX register holds 8 SP elements. */ typedef union { __m256 v; float f[8] __attribute__((aligned(64))); } v8sf_t; /* Union data structure to access AVX registers * One 256-bit AVX register holds 4 DP elements. */ typedef union { __m256d v; double d[4] __attribute__((aligned(64))); } v4df_t; // ----------------------------------------------------------------------------- void bli_saxpyv_zen_int10 ( conj_t conjx, dim_t n, float* restrict alpha, float* restrict x, inc_t incx, float* restrict y, inc_t incy, cntx_t* restrict cntx ) { const dim_t n_elem_per_reg = 8; dim_t i; float* restrict x0; float* restrict y0; __m256 alphav; __m256 xv[10]; __m256 yv[10]; __m256 zv[10]; // If the vector dimension is zero, or if alpha is zero, return early. if ( bli_zero_dim1( n ) || PASTEMAC(s,eq0)( *alpha ) ) return; // Initialize local pointers. x0 = x; y0 = y; if ( incx == 1 && incy == 1 ) { // Broadcast the alpha scalar to all elements of a vector register. alphav = _mm256_broadcast_ss( alpha ); for ( i = 0; (i + 79) < n; i += 80 ) { // 80 elements will be processed per loop; 10 FMAs will run per loop. xv[0] = _mm256_loadu_ps( x0 + 0*n_elem_per_reg ); xv[1] = _mm256_loadu_ps( x0 + 1*n_elem_per_reg ); xv[2] = _mm256_loadu_ps( x0 + 2*n_elem_per_reg ); xv[3] = _mm256_loadu_ps( x0 + 3*n_elem_per_reg ); xv[4] = _mm256_loadu_ps( x0 + 4*n_elem_per_reg ); xv[5] = _mm256_loadu_ps( x0 + 5*n_elem_per_reg ); xv[6] = _mm256_loadu_ps( x0 + 6*n_elem_per_reg ); xv[7] = _mm256_loadu_ps( x0 + 7*n_elem_per_reg ); xv[8] = _mm256_loadu_ps( x0 + 8*n_elem_per_reg ); xv[9] = _mm256_loadu_ps( x0 + 9*n_elem_per_reg ); yv[0] = _mm256_loadu_ps( y0 + 0*n_elem_per_reg ); yv[1] = _mm256_loadu_ps( y0 + 1*n_elem_per_reg ); yv[2] = _mm256_loadu_ps( y0 + 2*n_elem_per_reg ); yv[3] = _mm256_loadu_ps( y0 + 3*n_elem_per_reg ); yv[4] = _mm256_loadu_ps( y0 + 4*n_elem_per_reg ); yv[5] = _mm256_loadu_ps( y0 + 5*n_elem_per_reg ); yv[6] = _mm256_loadu_ps( y0 + 6*n_elem_per_reg ); yv[7] = _mm256_loadu_ps( y0 + 7*n_elem_per_reg ); yv[8] = _mm256_loadu_ps( y0 + 8*n_elem_per_reg ); yv[9] = _mm256_loadu_ps( y0 + 9*n_elem_per_reg ); zv[0] = _mm256_fmadd_ps( xv[0], alphav, yv[0] ); zv[1] = _mm256_fmadd_ps( xv[1], alphav, yv[1] ); zv[2] = _mm256_fmadd_ps( xv[2], alphav, yv[2] ); zv[3] = _mm256_fmadd_ps( xv[3], alphav, yv[3] ); zv[4] = _mm256_fmadd_ps( xv[4], alphav, yv[4] ); zv[5] = _mm256_fmadd_ps( xv[5], alphav, yv[5] ); zv[6] = _mm256_fmadd_ps( xv[6], alphav, yv[6] ); zv[7] = _mm256_fmadd_ps( xv[7], alphav, yv[7] ); zv[8] = _mm256_fmadd_ps( xv[8], alphav, yv[8] ); zv[9] = _mm256_fmadd_ps( xv[9], alphav, yv[9] ); _mm256_storeu_ps( (y0 + 0*n_elem_per_reg), zv[0] ); _mm256_storeu_ps( (y0 + 1*n_elem_per_reg), zv[1] ); _mm256_storeu_ps( (y0 + 2*n_elem_per_reg), zv[2] ); _mm256_storeu_ps( (y0 + 3*n_elem_per_reg), zv[3] ); _mm256_storeu_ps( (y0 + 4*n_elem_per_reg), zv[4] ); _mm256_storeu_ps( (y0 + 5*n_elem_per_reg), zv[5] ); _mm256_storeu_ps( (y0 + 6*n_elem_per_reg), zv[6] ); _mm256_storeu_ps( (y0 + 7*n_elem_per_reg), zv[7] ); _mm256_storeu_ps( (y0 + 8*n_elem_per_reg), zv[8] ); _mm256_storeu_ps( (y0 + 9*n_elem_per_reg), zv[9] ); x0 += 10*n_elem_per_reg; y0 += 10*n_elem_per_reg; } for ( ; (i + 39) < n; i += 40 ) { xv[0] = _mm256_loadu_ps( x0 + 0*n_elem_per_reg ); xv[1] = _mm256_loadu_ps( x0 + 1*n_elem_per_reg ); xv[2] = _mm256_loadu_ps( x0 + 2*n_elem_per_reg ); xv[3] = _mm256_loadu_ps( x0 + 3*n_elem_per_reg ); xv[4] = _mm256_loadu_ps( x0 + 4*n_elem_per_reg ); yv[0] = _mm256_loadu_ps( y0 + 0*n_elem_per_reg ); yv[1] = _mm256_loadu_ps( y0 + 1*n_elem_per_reg ); yv[2] = _mm256_loadu_ps( y0 + 2*n_elem_per_reg ); yv[3] = _mm256_loadu_ps( y0 + 3*n_elem_per_reg ); yv[4] = _mm256_loadu_ps( y0 + 4*n_elem_per_reg ); zv[0] = _mm256_fmadd_ps( xv[0], alphav, yv[0] ); zv[1] = _mm256_fmadd_ps( xv[1], alphav, yv[1] ); zv[2] = _mm256_fmadd_ps( xv[2], alphav, yv[2] ); zv[3] = _mm256_fmadd_ps( xv[3], alphav, yv[3] ); zv[4] = _mm256_fmadd_ps( xv[4], alphav, yv[4] ); _mm256_storeu_ps( (y0 + 0*n_elem_per_reg), zv[0] ); _mm256_storeu_ps( (y0 + 1*n_elem_per_reg), zv[1] ); _mm256_storeu_ps( (y0 + 2*n_elem_per_reg), zv[2] ); _mm256_storeu_ps( (y0 + 3*n_elem_per_reg), zv[3] ); _mm256_storeu_ps( (y0 + 4*n_elem_per_reg), zv[4] ); x0 += 5*n_elem_per_reg; y0 += 5*n_elem_per_reg; } for ( ; (i + 31) < n; i += 32 ) { xv[0] = _mm256_loadu_ps( x0 + 0*n_elem_per_reg ); xv[1] = _mm256_loadu_ps( x0 + 1*n_elem_per_reg ); xv[2] = _mm256_loadu_ps( x0 + 2*n_elem_per_reg ); xv[3] = _mm256_loadu_ps( x0 + 3*n_elem_per_reg ); yv[0] = _mm256_loadu_ps( y0 + 0*n_elem_per_reg ); yv[1] = _mm256_loadu_ps( y0 + 1*n_elem_per_reg ); yv[2] = _mm256_loadu_ps( y0 + 2*n_elem_per_reg ); yv[3] = _mm256_loadu_ps( y0 + 3*n_elem_per_reg ); zv[0] = _mm256_fmadd_ps( xv[0], alphav, yv[0] ); zv[1] = _mm256_fmadd_ps( xv[1], alphav, yv[1] ); zv[2] = _mm256_fmadd_ps( xv[2], alphav, yv[2] ); zv[3] = _mm256_fmadd_ps( xv[3], alphav, yv[3] ); _mm256_storeu_ps( (y0 + 0*n_elem_per_reg), zv[0] ); _mm256_storeu_ps( (y0 + 1*n_elem_per_reg), zv[1] ); _mm256_storeu_ps( (y0 + 2*n_elem_per_reg), zv[2] ); _mm256_storeu_ps( (y0 + 3*n_elem_per_reg), zv[3] ); x0 += 4*n_elem_per_reg; y0 += 4*n_elem_per_reg; } for ( ; (i + 15) < n; i += 16 ) { xv[0] = _mm256_loadu_ps( x0 + 0*n_elem_per_reg ); xv[1] = _mm256_loadu_ps( x0 + 1*n_elem_per_reg ); yv[0] = _mm256_loadu_ps( y0 + 0*n_elem_per_reg ); yv[1] = _mm256_loadu_ps( y0 + 1*n_elem_per_reg ); zv[0] = _mm256_fmadd_ps( xv[0], alphav, yv[0] ); zv[1] = _mm256_fmadd_ps( xv[1], alphav, yv[1] ); _mm256_storeu_ps( (y0 + 0*n_elem_per_reg), zv[0] ); _mm256_storeu_ps( (y0 + 1*n_elem_per_reg), zv[1] ); x0 += 2*n_elem_per_reg; y0 += 2*n_elem_per_reg; } for ( ; (i + 7) < n; i += 8 ) { xv[0] = _mm256_loadu_ps( x0 + 0*n_elem_per_reg ); yv[0] = _mm256_loadu_ps( y0 + 0*n_elem_per_reg ); zv[0] = _mm256_fmadd_ps( xv[0], alphav, yv[0] ); _mm256_storeu_ps( (y0 + 0*n_elem_per_reg), zv[0] ); x0 += 1*n_elem_per_reg; y0 += 1*n_elem_per_reg; } // Issue vzeroupper instruction to clear upper lanes of ymm registers. // This avoids a performance penalty caused by false dependencies when // transitioning from from AVX to SSE instructions (which may occur // as soon as the n_left cleanup loop below if BLIS is compiled with // -mfpmath=sse). _mm256_zeroupper(); for ( ; (i + 0) < n; i += 1 ) { *y0 += (*alpha) * (*x0); x0 += 1; y0 += 1; } } else { const float alphac = *alpha; for ( i = 0; i < n; ++i ) { const float x0c = *x0; *y0 += alphac * x0c; x0 += incx; y0 += incy; } } } // ----------------------------------------------------------------------------- void bli_daxpyv_zen_int10 ( conj_t conjx, dim_t n, double* restrict alpha, double* restrict x, inc_t incx, double* restrict y, inc_t incy, cntx_t* restrict cntx ) { const dim_t n_elem_per_reg = 4; dim_t i; double* restrict x0 = x; double* restrict y0 = y; __m256d alphav; __m256d xv[10]; __m256d yv[10]; __m256d zv[10]; // If the vector dimension is zero, or if alpha is zero, return early. if ( bli_zero_dim1( n ) || PASTEMAC(d,eq0)( *alpha ) ) return; // Initialize local pointers. x0 = x; y0 = y; if ( incx == 1 && incy == 1 ) { // Broadcast the alpha scalar to all elements of a vector register. alphav = _mm256_broadcast_sd( alpha ); for ( i = 0; (i + 39) < n; i += 40 ) { // 40 elements will be processed per loop; 10 FMAs will run per loop. xv[0] = _mm256_loadu_pd( x0 + 0*n_elem_per_reg ); xv[1] = _mm256_loadu_pd( x0 + 1*n_elem_per_reg ); xv[2] = _mm256_loadu_pd( x0 + 2*n_elem_per_reg ); xv[3] = _mm256_loadu_pd( x0 + 3*n_elem_per_reg ); xv[4] = _mm256_loadu_pd( x0 + 4*n_elem_per_reg ); xv[5] = _mm256_loadu_pd( x0 + 5*n_elem_per_reg ); xv[6] = _mm256_loadu_pd( x0 + 6*n_elem_per_reg ); xv[7] = _mm256_loadu_pd( x0 + 7*n_elem_per_reg ); xv[8] = _mm256_loadu_pd( x0 + 8*n_elem_per_reg ); xv[9] = _mm256_loadu_pd( x0 + 9*n_elem_per_reg ); yv[0] = _mm256_loadu_pd( y0 + 0*n_elem_per_reg ); yv[1] = _mm256_loadu_pd( y0 + 1*n_elem_per_reg ); yv[2] = _mm256_loadu_pd( y0 + 2*n_elem_per_reg ); yv[3] = _mm256_loadu_pd( y0 + 3*n_elem_per_reg ); yv[4] = _mm256_loadu_pd( y0 + 4*n_elem_per_reg ); yv[5] = _mm256_loadu_pd( y0 + 5*n_elem_per_reg ); yv[6] = _mm256_loadu_pd( y0 + 6*n_elem_per_reg ); yv[7] = _mm256_loadu_pd( y0 + 7*n_elem_per_reg ); yv[8] = _mm256_loadu_pd( y0 + 8*n_elem_per_reg ); yv[9] = _mm256_loadu_pd( y0 + 9*n_elem_per_reg ); zv[0] = _mm256_fmadd_pd( xv[0], alphav, yv[0] ); zv[1] = _mm256_fmadd_pd( xv[1], alphav, yv[1] ); zv[2] = _mm256_fmadd_pd( xv[2], alphav, yv[2] ); zv[3] = _mm256_fmadd_pd( xv[3], alphav, yv[3] ); zv[4] = _mm256_fmadd_pd( xv[4], alphav, yv[4] ); zv[5] = _mm256_fmadd_pd( xv[5], alphav, yv[5] ); zv[6] = _mm256_fmadd_pd( xv[6], alphav, yv[6] ); zv[7] = _mm256_fmadd_pd( xv[7], alphav, yv[7] ); zv[8] = _mm256_fmadd_pd( xv[8], alphav, yv[8] ); zv[9] = _mm256_fmadd_pd( xv[9], alphav, yv[9] ); _mm256_storeu_pd( (y0 + 0*n_elem_per_reg), zv[0] ); _mm256_storeu_pd( (y0 + 1*n_elem_per_reg), zv[1] ); _mm256_storeu_pd( (y0 + 2*n_elem_per_reg), zv[2] ); _mm256_storeu_pd( (y0 + 3*n_elem_per_reg), zv[3] ); _mm256_storeu_pd( (y0 + 4*n_elem_per_reg), zv[4] ); _mm256_storeu_pd( (y0 + 5*n_elem_per_reg), zv[5] ); _mm256_storeu_pd( (y0 + 6*n_elem_per_reg), zv[6] ); _mm256_storeu_pd( (y0 + 7*n_elem_per_reg), zv[7] ); _mm256_storeu_pd( (y0 + 8*n_elem_per_reg), zv[8] ); _mm256_storeu_pd( (y0 + 9*n_elem_per_reg), zv[9] ); x0 += 10*n_elem_per_reg; y0 += 10*n_elem_per_reg; } for ( ; (i + 19) < n; i += 20 ) { xv[0] = _mm256_loadu_pd( x0 + 0*n_elem_per_reg ); xv[1] = _mm256_loadu_pd( x0 + 1*n_elem_per_reg ); xv[2] = _mm256_loadu_pd( x0 + 2*n_elem_per_reg ); xv[3] = _mm256_loadu_pd( x0 + 3*n_elem_per_reg ); xv[4] = _mm256_loadu_pd( x0 + 4*n_elem_per_reg ); yv[0] = _mm256_loadu_pd( y0 + 0*n_elem_per_reg ); yv[1] = _mm256_loadu_pd( y0 + 1*n_elem_per_reg ); yv[2] = _mm256_loadu_pd( y0 + 2*n_elem_per_reg ); yv[3] = _mm256_loadu_pd( y0 + 3*n_elem_per_reg ); yv[4] = _mm256_loadu_pd( y0 + 4*n_elem_per_reg ); zv[0] = _mm256_fmadd_pd( xv[0], alphav, yv[0] ); zv[1] = _mm256_fmadd_pd( xv[1], alphav, yv[1] ); zv[2] = _mm256_fmadd_pd( xv[2], alphav, yv[2] ); zv[3] = _mm256_fmadd_pd( xv[3], alphav, yv[3] ); zv[4] = _mm256_fmadd_pd( xv[4], alphav, yv[4] ); _mm256_storeu_pd( (y0 + 0*n_elem_per_reg), zv[0] ); _mm256_storeu_pd( (y0 + 1*n_elem_per_reg), zv[1] ); _mm256_storeu_pd( (y0 + 2*n_elem_per_reg), zv[2] ); _mm256_storeu_pd( (y0 + 3*n_elem_per_reg), zv[3] ); _mm256_storeu_pd( (y0 + 4*n_elem_per_reg), zv[4] ); x0 += 5*n_elem_per_reg; y0 += 5*n_elem_per_reg; } for ( ; (i + 15) < n; i += 16 ) { xv[0] = _mm256_loadu_pd( x0 + 0*n_elem_per_reg ); xv[1] = _mm256_loadu_pd( x0 + 1*n_elem_per_reg ); xv[2] = _mm256_loadu_pd( x0 + 2*n_elem_per_reg ); xv[3] = _mm256_loadu_pd( x0 + 3*n_elem_per_reg ); yv[0] = _mm256_loadu_pd( y0 + 0*n_elem_per_reg ); yv[1] = _mm256_loadu_pd( y0 + 1*n_elem_per_reg ); yv[2] = _mm256_loadu_pd( y0 + 2*n_elem_per_reg ); yv[3] = _mm256_loadu_pd( y0 + 3*n_elem_per_reg ); zv[0] = _mm256_fmadd_pd( xv[0], alphav, yv[0] ); zv[1] = _mm256_fmadd_pd( xv[1], alphav, yv[1] ); zv[2] = _mm256_fmadd_pd( xv[2], alphav, yv[2] ); zv[3] = _mm256_fmadd_pd( xv[3], alphav, yv[3] ); _mm256_storeu_pd( (y0 + 0*n_elem_per_reg), zv[0] ); _mm256_storeu_pd( (y0 + 1*n_elem_per_reg), zv[1] ); _mm256_storeu_pd( (y0 + 2*n_elem_per_reg), zv[2] ); _mm256_storeu_pd( (y0 + 3*n_elem_per_reg), zv[3] ); x0 += 4*n_elem_per_reg; y0 += 4*n_elem_per_reg; } for ( ; i + 7 < n; i += 8 ) { xv[0] = _mm256_loadu_pd( x0 + 0*n_elem_per_reg ); xv[1] = _mm256_loadu_pd( x0 + 1*n_elem_per_reg ); yv[0] = _mm256_loadu_pd( y0 + 0*n_elem_per_reg ); yv[1] = _mm256_loadu_pd( y0 + 1*n_elem_per_reg ); zv[0] = _mm256_fmadd_pd( xv[0], alphav, yv[0] ); zv[1] = _mm256_fmadd_pd( xv[1], alphav, yv[1] ); _mm256_storeu_pd( (y0 + 0*n_elem_per_reg), zv[0] ); _mm256_storeu_pd( (y0 + 1*n_elem_per_reg), zv[1] ); x0 += 2*n_elem_per_reg; y0 += 2*n_elem_per_reg; } for ( ; i + 3 < n; i += 4 ) { xv[0] = _mm256_loadu_pd( x0 + 0*n_elem_per_reg ); yv[0] = _mm256_loadu_pd( y0 + 0*n_elem_per_reg ); zv[0] = _mm256_fmadd_pd( xv[0], alphav, yv[0] ); _mm256_storeu_pd( (y0 + 0*n_elem_per_reg), zv[0] ); x0 += 1*n_elem_per_reg; y0 += 1*n_elem_per_reg; } // Issue vzeroupper instruction to clear upper lanes of ymm registers. // This avoids a performance penalty caused by false dependencies when // transitioning from from AVX to SSE instructions (which may occur // as soon as the n_left cleanup loop below if BLIS is compiled with // -mfpmath=sse). _mm256_zeroupper(); for ( ; i < n; i += 1 ) { *y0 += (*alpha) * (*x0); y0 += 1; x0 += 1; } } else { const double alphac = *alpha; for ( i = 0; i < n; ++i ) { const double x0c = *x0; *y0 += alphac * x0c; x0 += incx; y0 += incy; } } } blis-0.9.0/kernels/zen/1/bli_copyv_zen_int.c000066400000000000000000000266231422157504600207470ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2019 - 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "immintrin.h" #include "blis.h" // ----------------------------------------------------------------------------- void bli_scopyv_zen_int ( conj_t conjx, dim_t n, float* restrict x, inc_t incx, float* restrict y, inc_t incy, cntx_t* restrict cntx ) { const dim_t num_elem_per_reg = 8; dim_t i = 0; __m256 xv[16]; // If the vector dimension is zero return early. if ( bli_zero_dim1( n ) ) return; if ( incx == 1 && incy == 1 ) { #if 0 PRAGMA_SIMD for (i = 0; i < n; i++) { y[i] = x[i]; } #endif #if 0 memcpy(y, x, n << 2); #endif #if 1 // For loop with n & ~0x7F => n & 0xFFFFFF80 masks the lower bits and results in multiples of 128 // for example if n = 255 // n & ~0x7F results in 128: copy from 0 to 128 happens in first loop // n & ~0x3F results in 192: copy from 128 to 192 happens in second loop // n & ~0x1F results in 224: copy from 128 to 192 happens in third loop and so on. for ( i = 0; i < (n & (~0x7F)); i += 128 ) { xv[0] = _mm256_loadu_ps(x + num_elem_per_reg * 0); xv[1] = _mm256_loadu_ps(x + num_elem_per_reg * 1); xv[2] = _mm256_loadu_ps(x + num_elem_per_reg * 2); xv[3] = _mm256_loadu_ps(x + num_elem_per_reg * 3); xv[4] = _mm256_loadu_ps(x + num_elem_per_reg * 4); xv[5] = _mm256_loadu_ps(x + num_elem_per_reg * 5); xv[6] = _mm256_loadu_ps(x + num_elem_per_reg * 6); xv[7] = _mm256_loadu_ps(x + num_elem_per_reg * 7); xv[8] = _mm256_loadu_ps(x + num_elem_per_reg * 8); xv[9] = _mm256_loadu_ps(x + num_elem_per_reg * 9); xv[10] = _mm256_loadu_ps(x + num_elem_per_reg * 10); xv[11] = _mm256_loadu_ps(x + num_elem_per_reg * 11); xv[12] = _mm256_loadu_ps(x + num_elem_per_reg * 12); xv[13] = _mm256_loadu_ps(x + num_elem_per_reg * 13); xv[14] = _mm256_loadu_ps(x + num_elem_per_reg * 14); xv[15] = _mm256_loadu_ps(x + num_elem_per_reg * 15); _mm256_storeu_ps(y + num_elem_per_reg * 0, xv[0]); _mm256_storeu_ps(y + num_elem_per_reg * 1, xv[1]); _mm256_storeu_ps(y + num_elem_per_reg * 2, xv[2]); _mm256_storeu_ps(y + num_elem_per_reg * 3, xv[3]); _mm256_storeu_ps(y + num_elem_per_reg * 4, xv[4]); _mm256_storeu_ps(y + num_elem_per_reg * 5, xv[5]); _mm256_storeu_ps(y + num_elem_per_reg * 6, xv[6]); _mm256_storeu_ps(y + num_elem_per_reg * 7, xv[7]); _mm256_storeu_ps(y + num_elem_per_reg * 8, xv[8]); _mm256_storeu_ps(y + num_elem_per_reg * 9, xv[9]); _mm256_storeu_ps(y + num_elem_per_reg * 10, xv[10]); _mm256_storeu_ps(y + num_elem_per_reg * 11, xv[11]); _mm256_storeu_ps(y + num_elem_per_reg * 12, xv[12]); _mm256_storeu_ps(y + num_elem_per_reg * 13, xv[13]); _mm256_storeu_ps(y + num_elem_per_reg * 14, xv[14]); _mm256_storeu_ps(y + num_elem_per_reg * 15, xv[15]); y += 128; x += 128; } for ( ; i < (n & (~0x3F)); i += 64 ) { xv[0] = _mm256_loadu_ps(x + num_elem_per_reg * 0); xv[1] = _mm256_loadu_ps(x + num_elem_per_reg * 1); xv[2] = _mm256_loadu_ps(x + num_elem_per_reg * 2); xv[3] = _mm256_loadu_ps(x + num_elem_per_reg * 3); xv[4] = _mm256_loadu_ps(x + num_elem_per_reg * 4); xv[5] = _mm256_loadu_ps(x + num_elem_per_reg * 5); xv[6] = _mm256_loadu_ps(x + num_elem_per_reg * 6); xv[7] = _mm256_loadu_ps(x + num_elem_per_reg * 7); _mm256_storeu_ps(y + num_elem_per_reg * 0, xv[0]); _mm256_storeu_ps(y + num_elem_per_reg * 1, xv[1]); _mm256_storeu_ps(y + num_elem_per_reg * 2, xv[2]); _mm256_storeu_ps(y + num_elem_per_reg * 3, xv[3]); _mm256_storeu_ps(y + num_elem_per_reg * 4, xv[4]); _mm256_storeu_ps(y + num_elem_per_reg * 5, xv[5]); _mm256_storeu_ps(y + num_elem_per_reg * 6, xv[6]); _mm256_storeu_ps(y + num_elem_per_reg * 7, xv[7]); y += 64; x += 64; } for ( ; i < (n & (~0x1F)); i += 32 ) { xv[0] = _mm256_loadu_ps(x + num_elem_per_reg * 0); xv[1] = _mm256_loadu_ps(x + num_elem_per_reg * 1); xv[2] = _mm256_loadu_ps(x + num_elem_per_reg * 2); xv[3] = _mm256_loadu_ps(x + num_elem_per_reg * 3); _mm256_storeu_ps(y + num_elem_per_reg * 0, xv[0]); _mm256_storeu_ps(y + num_elem_per_reg * 1, xv[1]); _mm256_storeu_ps(y + num_elem_per_reg * 2, xv[2]); _mm256_storeu_ps(y + num_elem_per_reg * 3, xv[3]); y += 32; x += 32; } for ( ; i < (n & (~0x0F)); i += 16 ) { xv[0] = _mm256_loadu_ps(x + num_elem_per_reg * 0); xv[1] = _mm256_loadu_ps(x + num_elem_per_reg * 1); _mm256_storeu_ps(y + num_elem_per_reg * 0, xv[0]); _mm256_storeu_ps(y + num_elem_per_reg * 1, xv[1]); y += 16; x += 16; } for ( ; i < (n & (~0x07)); i += 8 ) { xv[0] = _mm256_loadu_ps(x + num_elem_per_reg * 0); _mm256_storeu_ps(y + num_elem_per_reg * 0, xv[0]); y += 8; x += 8; } for ( ; i < n; ++i ) { *y++ = *x++; } #endif } else { for ( dim_t i = 0; i < n; ++i ) { *y = *x; x += incx; y += incy; } } } // ----------------------------------------------------------------------------- void bli_dcopyv_zen_int ( conj_t conjx, dim_t n, double* restrict x, inc_t incx, double* restrict y, inc_t incy, cntx_t* restrict cntx ) { const dim_t num_elem_per_reg = 4; dim_t i = 0; __m256d xv[16]; // If the vector dimension is zero return early. if ( bli_zero_dim1( n ) ) return; if ( incx == 1 && incy == 1 ) { #if 0 PRAGMA_SIMD for (i = 0; i < n; ++i) { y[i] = x[i]; } #endif #if 0 memcpy(y, x, n << 3); #endif #if 1 // n & (~0x3F) = n & 0xFFFFFFC0 -> this masks the numbers less than 64, // the copy operation will be done for the multiples of 64 for ( i = 0; i < (n & (~0x3F)); i += 64 ) { xv[0] = _mm256_loadu_pd(x + num_elem_per_reg * 0); xv[1] = _mm256_loadu_pd(x + num_elem_per_reg * 1); xv[2] = _mm256_loadu_pd(x + num_elem_per_reg * 2); xv[3] = _mm256_loadu_pd(x + num_elem_per_reg * 3); xv[4] = _mm256_loadu_pd(x + num_elem_per_reg * 4); xv[5] = _mm256_loadu_pd(x + num_elem_per_reg * 5); xv[6] = _mm256_loadu_pd(x + num_elem_per_reg * 6); xv[7] = _mm256_loadu_pd(x + num_elem_per_reg * 7); xv[8] = _mm256_loadu_pd(x + num_elem_per_reg * 8); xv[9] = _mm256_loadu_pd(x + num_elem_per_reg * 9); xv[10] = _mm256_loadu_pd(x + num_elem_per_reg * 10); xv[11] = _mm256_loadu_pd(x + num_elem_per_reg * 11); xv[12] = _mm256_loadu_pd(x + num_elem_per_reg * 12); xv[13] = _mm256_loadu_pd(x + num_elem_per_reg * 13); xv[14] = _mm256_loadu_pd(x + num_elem_per_reg * 14); xv[15] = _mm256_loadu_pd(x + num_elem_per_reg * 15); _mm256_storeu_pd(y + num_elem_per_reg * 0, xv[0]); _mm256_storeu_pd(y + num_elem_per_reg * 1, xv[1]); _mm256_storeu_pd(y + num_elem_per_reg * 2, xv[2]); _mm256_storeu_pd(y + num_elem_per_reg * 3, xv[3]); _mm256_storeu_pd(y + num_elem_per_reg * 4, xv[4]); _mm256_storeu_pd(y + num_elem_per_reg * 5, xv[5]); _mm256_storeu_pd(y + num_elem_per_reg * 6, xv[6]); _mm256_storeu_pd(y + num_elem_per_reg * 7, xv[7]); _mm256_storeu_pd(y + num_elem_per_reg * 8, xv[8]); _mm256_storeu_pd(y + num_elem_per_reg * 9, xv[9]); _mm256_storeu_pd(y + num_elem_per_reg * 10, xv[10]); _mm256_storeu_pd(y + num_elem_per_reg * 11, xv[11]); _mm256_storeu_pd(y + num_elem_per_reg * 12, xv[12]); _mm256_storeu_pd(y + num_elem_per_reg * 13, xv[13]); _mm256_storeu_pd(y + num_elem_per_reg * 14, xv[14]); _mm256_storeu_pd(y + num_elem_per_reg * 15, xv[15]); y += num_elem_per_reg * 16; x += num_elem_per_reg * 16; } for ( ; i < (n & (~0x1F)); i += 32 ) { xv[0] = _mm256_loadu_pd(x + num_elem_per_reg * 0); xv[1] = _mm256_loadu_pd(x + num_elem_per_reg * 1); xv[2] = _mm256_loadu_pd(x + num_elem_per_reg * 2); xv[3] = _mm256_loadu_pd(x + num_elem_per_reg * 3); xv[4] = _mm256_loadu_pd(x + num_elem_per_reg * 4); xv[5] = _mm256_loadu_pd(x + num_elem_per_reg * 5); xv[6] = _mm256_loadu_pd(x + num_elem_per_reg * 6); xv[7] = _mm256_loadu_pd(x + num_elem_per_reg * 7); _mm256_storeu_pd(y + num_elem_per_reg * 0, xv[0]); _mm256_storeu_pd(y + num_elem_per_reg * 1, xv[1]); _mm256_storeu_pd(y + num_elem_per_reg * 2, xv[2]); _mm256_storeu_pd(y + num_elem_per_reg * 3, xv[3]); _mm256_storeu_pd(y + num_elem_per_reg * 4, xv[4]); _mm256_storeu_pd(y + num_elem_per_reg * 5, xv[5]); _mm256_storeu_pd(y + num_elem_per_reg * 6, xv[6]); _mm256_storeu_pd(y + num_elem_per_reg * 7, xv[7]); y += num_elem_per_reg * 8; x += num_elem_per_reg * 8; } for ( ; i < (n & (~0xF)); i += 16 ) { xv[0] = _mm256_loadu_pd(x + num_elem_per_reg * 0); xv[1] = _mm256_loadu_pd(x + num_elem_per_reg * 1); xv[2] = _mm256_loadu_pd(x + num_elem_per_reg * 2); xv[3] = _mm256_loadu_pd(x + num_elem_per_reg * 3); _mm256_storeu_pd(y + num_elem_per_reg * 0, xv[0]); _mm256_storeu_pd(y + num_elem_per_reg * 1, xv[1]); _mm256_storeu_pd(y + num_elem_per_reg * 2, xv[2]); _mm256_storeu_pd(y + num_elem_per_reg * 3, xv[3]); y += num_elem_per_reg * 4; x += num_elem_per_reg * 4; } for ( ; i < (n & (~0x07)); i += 8 ) { xv[0] = _mm256_loadu_pd(x + num_elem_per_reg * 0); xv[1] = _mm256_loadu_pd(x + num_elem_per_reg * 1); _mm256_storeu_pd(y + num_elem_per_reg * 0, xv[0]); _mm256_storeu_pd(y + num_elem_per_reg * 1, xv[1]); y += num_elem_per_reg * 2; x += num_elem_per_reg * 2; } for ( ; i < (n & (~0x03)); i += 4 ) { xv[0] = _mm256_loadu_pd(x + num_elem_per_reg * 0); _mm256_storeu_pd(y + num_elem_per_reg * 0, xv[0]); y += num_elem_per_reg; x += num_elem_per_reg; } for ( ; i < n; ++i ) { *y++ = *x++; } #endif } else { for ( i = 0; i < n; ++i ) { *y = *x; x += incx; y += incy; } } } blis-0.9.0/kernels/zen/1/bli_dotv_zen_int.c000066400000000000000000000216431422157504600205600ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2016 - 2019, Advanced Micro Devices, Inc. Copyright (C) 2018, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "immintrin.h" #include "blis.h" /* Union data structure to access AVX registers One 256-bit AVX register holds 8 SP elements. */ typedef union { __m256 v; float f[8] __attribute__((aligned(64))); } v8sf_t; /* Union data structure to access AVX registers * One 256-bit AVX register holds 4 DP elements. */ typedef union { __m256d v; double d[4] __attribute__((aligned(64))); } v4df_t; // ----------------------------------------------------------------------------- void bli_sdotv_zen_int ( conj_t conjx, conj_t conjy, dim_t n, float* restrict x, inc_t incx, float* restrict y, inc_t incy, float* restrict rho, cntx_t* restrict cntx ) { const dim_t n_elem_per_reg = 8; const dim_t n_iter_unroll = 4; dim_t i; dim_t n_viter; dim_t n_left; float* restrict x0; float* restrict y0; float rho0; v8sf_t rho0v, rho1v, rho2v, rho3v; v8sf_t x0v, y0v; v8sf_t x1v, y1v; v8sf_t x2v, y2v; v8sf_t x3v, y3v; // If the vector dimension is zero, set rho to zero and return early. if ( bli_zero_dim1( n ) ) { PASTEMAC(s,set0s)( *rho ); return; } // Use the unrolling factor and the number of elements per register // to compute the number of vectorized and leftover iterations. n_viter = ( n ) / ( n_elem_per_reg * n_iter_unroll ); n_left = ( n ) % ( n_elem_per_reg * n_iter_unroll ); // If there is anything that would interfere with our use of contiguous // vector loads/stores, override n_viter and n_left to use scalar code // for all iterations. if ( incx != 1 || incy != 1 ) { n_viter = 0; n_left = n; } // Initialize local pointers. x0 = x; y0 = y; // Initialize the local scalar rho1 to zero. PASTEMAC(s,set0s)( rho0 ); // Initialize the unrolled iterations' rho vectors to zero. rho0v.v = _mm256_setzero_ps(); rho1v.v = _mm256_setzero_ps(); rho2v.v = _mm256_setzero_ps(); rho3v.v = _mm256_setzero_ps(); for ( i = 0; i < n_viter; ++i ) { // Load the x and y input vector elements. x0v.v = _mm256_loadu_ps( x0 + 0*n_elem_per_reg ); y0v.v = _mm256_loadu_ps( y0 + 0*n_elem_per_reg ); x1v.v = _mm256_loadu_ps( x0 + 1*n_elem_per_reg ); y1v.v = _mm256_loadu_ps( y0 + 1*n_elem_per_reg ); x2v.v = _mm256_loadu_ps( x0 + 2*n_elem_per_reg ); y2v.v = _mm256_loadu_ps( y0 + 2*n_elem_per_reg ); x3v.v = _mm256_loadu_ps( x0 + 3*n_elem_per_reg ); y3v.v = _mm256_loadu_ps( y0 + 3*n_elem_per_reg ); // Compute the element-wise product of the x and y vectors, // storing in the corresponding rho vectors. rho0v.v = _mm256_fmadd_ps( x0v.v, y0v.v, rho0v.v ); rho1v.v = _mm256_fmadd_ps( x1v.v, y1v.v, rho1v.v ); rho2v.v = _mm256_fmadd_ps( x2v.v, y2v.v, rho2v.v ); rho3v.v = _mm256_fmadd_ps( x3v.v, y3v.v, rho3v.v ); x0 += ( n_elem_per_reg * n_iter_unroll ); y0 += ( n_elem_per_reg * n_iter_unroll ); } // Accumulate the unrolled rho vectors into a single vector. rho0v.v += rho1v.v; rho0v.v += rho2v.v; rho0v.v += rho3v.v; // Accumulate the final rho vector into a single scalar result. rho0 += rho0v.f[0] + rho0v.f[1] + rho0v.f[2] + rho0v.f[3] + rho0v.f[4] + rho0v.f[5] + rho0v.f[6] + rho0v.f[7]; // Issue vzeroupper instruction to clear upper lanes of ymm registers. // This avoids a performance penalty caused by false dependencies when // transitioning from from AVX to SSE instructions (which may occur // as soon as the n_left cleanup loop below if BLIS is compiled with // -mfpmath=sse). _mm256_zeroupper(); // If there are leftover iterations, perform them with scalar code. for ( i = 0; i < n_left; ++i ) { const float x0c = *x0; const float y0c = *y0; rho0 += x0c * y0c; x0 += incx; y0 += incy; } // Copy the final result into the output variable. PASTEMAC(s,copys)( rho0, *rho ); } // ----------------------------------------------------------------------------- void bli_ddotv_zen_int ( conj_t conjx, conj_t conjy, dim_t n, double* restrict x, inc_t incx, double* restrict y, inc_t incy, double* restrict rho, cntx_t* restrict cntx ) { const dim_t n_elem_per_reg = 4; const dim_t n_iter_unroll = 4; dim_t i; dim_t n_viter; dim_t n_left; double* restrict x0; double* restrict y0; double rho0; v4df_t rho0v, rho1v, rho2v, rho3v; v4df_t x0v, y0v; v4df_t x1v, y1v; v4df_t x2v, y2v; v4df_t x3v, y3v; // If the vector dimension is zero, set rho to zero and return early. if ( bli_zero_dim1( n ) ) { PASTEMAC(d,set0s)( *rho ); return; } // Use the unrolling factor and the number of elements per register // to compute the number of vectorized and leftover iterations. n_viter = ( n ) / ( n_elem_per_reg * n_iter_unroll ); n_left = ( n ) % ( n_elem_per_reg * n_iter_unroll ); // If there is anything that would interfere with our use of contiguous // vector loads/stores, override n_viter and n_left to use scalar code // for all iterations. if ( incx != 1 || incy != 1 ) { n_viter = 0; n_left = n; } // Initialize local pointers. x0 = x; y0 = y; // Initialize the local scalar rho1 to zero. PASTEMAC(d,set0s)( rho0 ); // Initialize the unrolled iterations' rho vectors to zero. rho0v.v = _mm256_setzero_pd(); rho1v.v = _mm256_setzero_pd(); rho2v.v = _mm256_setzero_pd(); rho3v.v = _mm256_setzero_pd(); for ( i = 0; i < n_viter; ++i ) { // Load the x and y input vector elements. x0v.v = _mm256_loadu_pd( x0 + 0*n_elem_per_reg ); y0v.v = _mm256_loadu_pd( y0 + 0*n_elem_per_reg ); x1v.v = _mm256_loadu_pd( x0 + 1*n_elem_per_reg ); y1v.v = _mm256_loadu_pd( y0 + 1*n_elem_per_reg ); x2v.v = _mm256_loadu_pd( x0 + 2*n_elem_per_reg ); y2v.v = _mm256_loadu_pd( y0 + 2*n_elem_per_reg ); x3v.v = _mm256_loadu_pd( x0 + 3*n_elem_per_reg ); y3v.v = _mm256_loadu_pd( y0 + 3*n_elem_per_reg ); // Compute the element-wise product of the x and y vectors, // storing in the corresponding rho vectors. rho0v.v = _mm256_fmadd_pd( x0v.v, y0v.v, rho0v.v ); rho1v.v = _mm256_fmadd_pd( x1v.v, y1v.v, rho1v.v ); rho2v.v = _mm256_fmadd_pd( x2v.v, y2v.v, rho2v.v ); rho3v.v = _mm256_fmadd_pd( x3v.v, y3v.v, rho3v.v ); x0 += ( n_elem_per_reg * n_iter_unroll ); y0 += ( n_elem_per_reg * n_iter_unroll ); } // Accumulate the unrolled rho vectors into a single vector. rho0v.v += rho1v.v; rho0v.v += rho2v.v; rho0v.v += rho3v.v; // Accumulate the final rho vector into a single scalar result. rho0 += rho0v.d[0] + rho0v.d[1] + rho0v.d[2] + rho0v.d[3]; // Issue vzeroupper instruction to clear upper lanes of ymm registers. // This avoids a performance penalty caused by false dependencies when // transitioning from from AVX to SSE instructions (which may occur // as soon as the n_left cleanup loop below if BLIS is compiled with // -mfpmath=sse). _mm256_zeroupper(); // If there are leftover iterations, perform them with scalar code. for ( i = 0; i < n_left; ++i ) { const double x0c = *x0; const double y0c = *y0; rho0 += x0c * y0c; x0 += incx; y0 += incy; } // Copy the final result into the output variable. PASTEMAC(d,copys)( rho0, *rho ); } blis-0.9.0/kernels/zen/1/bli_dotv_zen_int10.c000066400000000000000000000335601422157504600207220ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2016 - 2020, Advanced Micro Devices, Inc. Copyright (C) 2018, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "immintrin.h" #include "blis.h" /* Union data structure to access AVX registers One 256-bit AVX register holds 8 SP elements. */ typedef union { __m256 v; float f[8] __attribute__((aligned(64))); } v8sf_t; /* Union data structure to access AVX registers * One 256-bit AVX register holds 4 DP elements. */ typedef union { __m256d v; double d[4] __attribute__((aligned(64))); } v4df_t; // ----------------------------------------------------------------------------- void bli_sdotv_zen_int10 ( conj_t conjx, conj_t conjy, dim_t n, float* restrict x, inc_t incx, float* restrict y, inc_t incy, float* restrict rho, cntx_t* restrict cntx ) { const dim_t n_elem_per_reg = 8; dim_t i; float* restrict x0; float* restrict y0; float rho0 = 0.0; __m256 xv[10]; __m256 yv[10]; v8sf_t rhov[10]; // If the vector dimension is zero, or if alpha is zero, return early. if ( bli_zero_dim1( n ) ) { PASTEMAC(s,set0s)( *rho ); return; } // Initialize local pointers. x0 = x; y0 = y; PASTEMAC(s,set0s)( rho0 ); if ( incx == 1 && incy == 1 ) { rhov[0].v = _mm256_setzero_ps(); rhov[1].v = _mm256_setzero_ps(); rhov[2].v = _mm256_setzero_ps(); rhov[3].v = _mm256_setzero_ps(); rhov[4].v = _mm256_setzero_ps(); rhov[5].v = _mm256_setzero_ps(); rhov[6].v = _mm256_setzero_ps(); rhov[7].v = _mm256_setzero_ps(); rhov[8].v = _mm256_setzero_ps(); rhov[9].v = _mm256_setzero_ps(); for ( i = 0 ; (i + 79) < n; i += 80 ) { // 80 elements will be processed per loop; 10 FMAs will run per loop. xv[0] = _mm256_loadu_ps( x0 + 0*n_elem_per_reg ); xv[1] = _mm256_loadu_ps( x0 + 1*n_elem_per_reg ); xv[2] = _mm256_loadu_ps( x0 + 2*n_elem_per_reg ); xv[3] = _mm256_loadu_ps( x0 + 3*n_elem_per_reg ); xv[4] = _mm256_loadu_ps( x0 + 4*n_elem_per_reg ); xv[5] = _mm256_loadu_ps( x0 + 5*n_elem_per_reg ); xv[6] = _mm256_loadu_ps( x0 + 6*n_elem_per_reg ); xv[7] = _mm256_loadu_ps( x0 + 7*n_elem_per_reg ); xv[8] = _mm256_loadu_ps( x0 + 8*n_elem_per_reg ); xv[9] = _mm256_loadu_ps( x0 + 9*n_elem_per_reg ); yv[0] = _mm256_loadu_ps( y0 + 0*n_elem_per_reg ); yv[1] = _mm256_loadu_ps( y0 + 1*n_elem_per_reg ); yv[2] = _mm256_loadu_ps( y0 + 2*n_elem_per_reg ); yv[3] = _mm256_loadu_ps( y0 + 3*n_elem_per_reg ); yv[4] = _mm256_loadu_ps( y0 + 4*n_elem_per_reg ); yv[5] = _mm256_loadu_ps( y0 + 5*n_elem_per_reg ); yv[6] = _mm256_loadu_ps( y0 + 6*n_elem_per_reg ); yv[7] = _mm256_loadu_ps( y0 + 7*n_elem_per_reg ); yv[8] = _mm256_loadu_ps( y0 + 8*n_elem_per_reg ); yv[9] = _mm256_loadu_ps( y0 + 9*n_elem_per_reg ); rhov[0].v = _mm256_fmadd_ps( xv[0], yv[0], rhov[0].v ); rhov[1].v = _mm256_fmadd_ps( xv[1], yv[1], rhov[1].v ); rhov[2].v = _mm256_fmadd_ps( xv[2], yv[2], rhov[2].v ); rhov[3].v = _mm256_fmadd_ps( xv[3], yv[3], rhov[3].v ); rhov[4].v = _mm256_fmadd_ps( xv[4], yv[4], rhov[4].v ); rhov[5].v = _mm256_fmadd_ps( xv[5], yv[5], rhov[5].v ); rhov[6].v = _mm256_fmadd_ps( xv[6], yv[6], rhov[6].v ); rhov[7].v = _mm256_fmadd_ps( xv[7], yv[7], rhov[7].v ); rhov[8].v = _mm256_fmadd_ps( xv[8], yv[8], rhov[8].v ); rhov[9].v = _mm256_fmadd_ps( xv[9], yv[9], rhov[9].v ); x0 += 10*n_elem_per_reg; y0 += 10*n_elem_per_reg; } rhov[0].v += rhov[5].v; rhov[1].v += rhov[6].v; rhov[2].v += rhov[7].v; rhov[3].v += rhov[8].v; rhov[4].v += rhov[9].v; for ( ; (i + 39) < n; i += 40 ) { xv[0] = _mm256_loadu_ps( x0 + 0*n_elem_per_reg ); xv[1] = _mm256_loadu_ps( x0 + 1*n_elem_per_reg ); xv[2] = _mm256_loadu_ps( x0 + 2*n_elem_per_reg ); xv[3] = _mm256_loadu_ps( x0 + 3*n_elem_per_reg ); xv[4] = _mm256_loadu_ps( x0 + 4*n_elem_per_reg ); yv[0] = _mm256_loadu_ps( y0 + 0*n_elem_per_reg ); yv[1] = _mm256_loadu_ps( y0 + 1*n_elem_per_reg ); yv[2] = _mm256_loadu_ps( y0 + 2*n_elem_per_reg ); yv[3] = _mm256_loadu_ps( y0 + 3*n_elem_per_reg ); yv[4] = _mm256_loadu_ps( y0 + 4*n_elem_per_reg ); rhov[0].v = _mm256_fmadd_ps( xv[0], yv[0], rhov[0].v ); rhov[1].v = _mm256_fmadd_ps( xv[1], yv[1], rhov[1].v ); rhov[2].v = _mm256_fmadd_ps( xv[2], yv[2], rhov[2].v ); rhov[3].v = _mm256_fmadd_ps( xv[3], yv[3], rhov[3].v ); rhov[4].v = _mm256_fmadd_ps( xv[4], yv[4], rhov[4].v ); x0 += 5*n_elem_per_reg; y0 += 5*n_elem_per_reg; } rhov[0].v += rhov[2].v; rhov[1].v += rhov[3].v; rhov[0].v += rhov[4].v; for ( ; (i + 15) < n; i += 16 ) { xv[0] = _mm256_loadu_ps( x0 + 0*n_elem_per_reg ); xv[1] = _mm256_loadu_ps( x0 + 1*n_elem_per_reg ); yv[0] = _mm256_loadu_ps( y0 + 0*n_elem_per_reg ); yv[1] = _mm256_loadu_ps( y0 + 1*n_elem_per_reg ); rhov[0].v = _mm256_fmadd_ps( xv[0], yv[0], rhov[0].v ); rhov[1].v = _mm256_fmadd_ps( xv[1], yv[1], rhov[1].v ); x0 += 2*n_elem_per_reg; y0 += 2*n_elem_per_reg; } rhov[0].v += rhov[1].v; for ( ; (i + 7) < n; i += 8 ) { xv[0] = _mm256_loadu_ps( x0 + 0*n_elem_per_reg ); yv[0] = _mm256_loadu_ps( y0 + 0*n_elem_per_reg ); rhov[0].v = _mm256_fmadd_ps( xv[0], yv[0], rhov[0].v ); x0 += 1*n_elem_per_reg; y0 += 1*n_elem_per_reg; } for ( ; (i + 0) < n; i += 1 ) { rho0 += (*x0) * (*y0); x0 += 1; y0 += 1; } rho0 += rhov[0].f[0] + rhov[0].f[1] + rhov[0].f[2] + rhov[0].f[3] + rhov[0].f[4] + rhov[0].f[5] + rhov[0].f[6] + rhov[0].f[7]; // Issue vzeroupper instruction to clear upper lanes of ymm registers. // This avoids a performance penalty caused by false dependencies when // transitioning from from AVX to SSE instructions (which may occur // later, especially if BLIS is compiled with -mfpmath=sse). _mm256_zeroupper(); } else { for ( i = 0; i < n; ++i ) { const float x0c = *x0; const float y0c = *y0; rho0 += x0c * y0c; x0 += incx; y0 += incy; } } // Copy the final result into the output variable. PASTEMAC(s,copys)( rho0, *rho ); } // ----------------------------------------------------------------------------- void bli_ddotv_zen_int10 ( conj_t conjx, conj_t conjy, dim_t n, double* restrict x, inc_t incx, double* restrict y, inc_t incy, double* restrict rho, cntx_t* restrict cntx ) { const dim_t n_elem_per_reg = 4; dim_t i; double* restrict x0; double* restrict y0; double rho0 = 0.0; __m256d xv[10]; __m256d yv[10]; v4df_t rhov[10]; // If the vector dimension is zero, or if alpha is zero, return early. if ( bli_zero_dim1( n ) ) { PASTEMAC(d,set0s)( *rho ); return; } // Initialize local pointers. x0 = x; y0 = y; PASTEMAC(d,set0s)( rho0 ); if ( incx == 1 && incy == 1 ) { rhov[0].v = _mm256_setzero_pd(); rhov[1].v = _mm256_setzero_pd(); rhov[2].v = _mm256_setzero_pd(); rhov[3].v = _mm256_setzero_pd(); rhov[4].v = _mm256_setzero_pd(); rhov[5].v = _mm256_setzero_pd(); rhov[6].v = _mm256_setzero_pd(); rhov[7].v = _mm256_setzero_pd(); rhov[8].v = _mm256_setzero_pd(); rhov[9].v = _mm256_setzero_pd(); for ( i = 0; (i + 39) < n; i += 40 ) { // 80 elements will be processed per loop; 10 FMAs will run per loop. xv[0] = _mm256_loadu_pd( x0 + 0*n_elem_per_reg ); xv[1] = _mm256_loadu_pd( x0 + 1*n_elem_per_reg ); xv[2] = _mm256_loadu_pd( x0 + 2*n_elem_per_reg ); xv[3] = _mm256_loadu_pd( x0 + 3*n_elem_per_reg ); xv[4] = _mm256_loadu_pd( x0 + 4*n_elem_per_reg ); xv[5] = _mm256_loadu_pd( x0 + 5*n_elem_per_reg ); xv[6] = _mm256_loadu_pd( x0 + 6*n_elem_per_reg ); xv[7] = _mm256_loadu_pd( x0 + 7*n_elem_per_reg ); xv[8] = _mm256_loadu_pd( x0 + 8*n_elem_per_reg ); xv[9] = _mm256_loadu_pd( x0 + 9*n_elem_per_reg ); yv[0] = _mm256_loadu_pd( y0 + 0*n_elem_per_reg ); yv[1] = _mm256_loadu_pd( y0 + 1*n_elem_per_reg ); yv[2] = _mm256_loadu_pd( y0 + 2*n_elem_per_reg ); yv[3] = _mm256_loadu_pd( y0 + 3*n_elem_per_reg ); yv[4] = _mm256_loadu_pd( y0 + 4*n_elem_per_reg ); yv[5] = _mm256_loadu_pd( y0 + 5*n_elem_per_reg ); yv[6] = _mm256_loadu_pd( y0 + 6*n_elem_per_reg ); yv[7] = _mm256_loadu_pd( y0 + 7*n_elem_per_reg ); yv[8] = _mm256_loadu_pd( y0 + 8*n_elem_per_reg ); yv[9] = _mm256_loadu_pd( y0 + 9*n_elem_per_reg ); rhov[0].v = _mm256_fmadd_pd( xv[0], yv[0], rhov[0].v ); rhov[1].v = _mm256_fmadd_pd( xv[1], yv[1], rhov[1].v ); rhov[2].v = _mm256_fmadd_pd( xv[2], yv[2], rhov[2].v ); rhov[3].v = _mm256_fmadd_pd( xv[3], yv[3], rhov[3].v ); rhov[4].v = _mm256_fmadd_pd( xv[4], yv[4], rhov[4].v ); rhov[5].v = _mm256_fmadd_pd( xv[5], yv[5], rhov[5].v ); rhov[6].v = _mm256_fmadd_pd( xv[6], yv[6], rhov[6].v ); rhov[7].v = _mm256_fmadd_pd( xv[7], yv[7], rhov[7].v ); rhov[8].v = _mm256_fmadd_pd( xv[8], yv[8], rhov[8].v ); rhov[9].v = _mm256_fmadd_pd( xv[9], yv[9], rhov[9].v ); x0 += 10*n_elem_per_reg; y0 += 10*n_elem_per_reg; } rhov[0].v += rhov[5].v; rhov[1].v += rhov[6].v; rhov[2].v += rhov[7].v; rhov[3].v += rhov[8].v; rhov[4].v += rhov[9].v; for ( ; (i + 19) < n; i += 20 ) { xv[0] = _mm256_loadu_pd( x0 + 0*n_elem_per_reg ); xv[1] = _mm256_loadu_pd( x0 + 1*n_elem_per_reg ); xv[2] = _mm256_loadu_pd( x0 + 2*n_elem_per_reg ); xv[3] = _mm256_loadu_pd( x0 + 3*n_elem_per_reg ); xv[4] = _mm256_loadu_pd( x0 + 4*n_elem_per_reg ); yv[0] = _mm256_loadu_pd( y0 + 0*n_elem_per_reg ); yv[1] = _mm256_loadu_pd( y0 + 1*n_elem_per_reg ); yv[2] = _mm256_loadu_pd( y0 + 2*n_elem_per_reg ); yv[3] = _mm256_loadu_pd( y0 + 3*n_elem_per_reg ); yv[4] = _mm256_loadu_pd( y0 + 4*n_elem_per_reg ); rhov[0].v = _mm256_fmadd_pd( xv[0], yv[0], rhov[0].v ); rhov[1].v = _mm256_fmadd_pd( xv[1], yv[1], rhov[1].v ); rhov[2].v = _mm256_fmadd_pd( xv[2], yv[2], rhov[2].v ); rhov[3].v = _mm256_fmadd_pd( xv[3], yv[3], rhov[3].v ); rhov[4].v = _mm256_fmadd_pd( xv[4], yv[4], rhov[4].v ); x0 += 5*n_elem_per_reg; y0 += 5*n_elem_per_reg; } rhov[0].v += rhov[4].v; for ( ; (i + 15) < n; i += 16 ) { xv[0] = _mm256_loadu_pd( x0 + 0*n_elem_per_reg ); xv[1] = _mm256_loadu_pd( x0 + 1*n_elem_per_reg ); xv[2] = _mm256_loadu_pd( x0 + 2*n_elem_per_reg ); xv[3] = _mm256_loadu_pd( x0 + 3*n_elem_per_reg ); yv[0] = _mm256_loadu_pd( y0 + 0*n_elem_per_reg ); yv[1] = _mm256_loadu_pd( y0 + 1*n_elem_per_reg ); yv[2] = _mm256_loadu_pd( y0 + 2*n_elem_per_reg ); yv[3] = _mm256_loadu_pd( y0 + 3*n_elem_per_reg ); rhov[0].v = _mm256_fmadd_pd( xv[0], yv[0], rhov[0].v ); rhov[1].v = _mm256_fmadd_pd( xv[1], yv[1], rhov[1].v ); rhov[2].v = _mm256_fmadd_pd( xv[2], yv[2], rhov[2].v ); rhov[3].v = _mm256_fmadd_pd( xv[3], yv[3], rhov[3].v ); x0 += 4*n_elem_per_reg; y0 += 4*n_elem_per_reg; } rhov[0].v += rhov[2].v; rhov[1].v += rhov[3].v; for ( ; (i + 7) < n; i += 8 ) { xv[0] = _mm256_loadu_pd( x0 + 0*n_elem_per_reg ); xv[1] = _mm256_loadu_pd( x0 + 1*n_elem_per_reg ); yv[0] = _mm256_loadu_pd( y0 + 0*n_elem_per_reg ); yv[1] = _mm256_loadu_pd( y0 + 1*n_elem_per_reg ); rhov[0].v = _mm256_fmadd_pd( xv[0], yv[0], rhov[0].v ); rhov[1].v = _mm256_fmadd_pd( xv[1], yv[1], rhov[1].v ); x0 += 2*n_elem_per_reg; y0 += 2*n_elem_per_reg; } rhov[0].v += rhov[1].v; for ( ; (i + 3) < n; i += 4 ) { xv[0] = _mm256_loadu_pd( x0 + 0*n_elem_per_reg ); yv[0] = _mm256_loadu_pd( y0 + 0*n_elem_per_reg ); rhov[0].v = _mm256_fmadd_pd( xv[0], yv[0], rhov[0].v ); x0 += 1*n_elem_per_reg; y0 += 1*n_elem_per_reg; } for ( ; (i + 0) < n; i += 1 ) { rho0 += (*x0) * (*y0); x0 += 1; y0 += 1; } // Manually add the results from above to finish the sum. rho0 += rhov[0].d[0] + rhov[0].d[1] + rhov[0].d[2] + rhov[0].d[3]; // Issue vzeroupper instruction to clear upper lanes of ymm registers. // This avoids a performance penalty caused by false dependencies when // transitioning from from AVX to SSE instructions (which may occur // later, especially if BLIS is compiled with -mfpmath=sse). _mm256_zeroupper(); } else { for ( i = 0; i < n; ++i ) { const double x0c = *x0; const double y0c = *y0; rho0 += x0c * y0c; x0 += incx; y0 += incy; } } // Copy the final result into the output variable. PASTEMAC(d,copys)( rho0, *rho ); } blis-0.9.0/kernels/zen/1/bli_dotxv_zen_int.c000066400000000000000000000225321422157504600207460ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2016 - 2019, Advanced Micro Devices, Inc. Copyright (C) 2018, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "immintrin.h" #include "blis.h" /* Union data structure to access AVX registers One 256-bit AVX register holds 8 SP elements. */ typedef union { __m256 v; float f[8] __attribute__((aligned(64))); } v8sf_t; /* Union data structure to access AVX registers * One 256-bit AVX register holds 4 DP elements. */ typedef union { __m256d v; double d[4] __attribute__((aligned(64))); } v4df_t; // ----------------------------------------------------------------------------- void bli_sdotxv_zen_int ( conj_t conjx, conj_t conjy, dim_t n, float* restrict alpha, float* restrict x, inc_t incx, float* restrict y, inc_t incy, float* restrict beta, float* restrict rho, cntx_t* restrict cntx ) { const dim_t n_elem_per_reg = 8; const dim_t n_iter_unroll = 4; dim_t i; dim_t n_viter; dim_t n_left; float* restrict x0; float* restrict y0; float rho0; v8sf_t rho0v, rho1v, rho2v, rho3v; v8sf_t x0v, y0v; v8sf_t x1v, y1v; v8sf_t x2v, y2v; v8sf_t x3v, y3v; // If beta is zero, initialize rho1 to zero instead of scaling // rho by beta (in case rho contains NaN or Inf). if ( PASTEMAC(s,eq0)( *beta ) ) { PASTEMAC(s,set0s)( *rho ); } else { PASTEMAC(s,scals)( *beta, *rho ); } // If the vector dimension is zero, output rho and return early. if ( bli_zero_dim1( n ) || PASTEMAC(s,eq0)( *alpha ) ) return; // Use the unrolling factor and the number of elements per register // to compute the number of vectorized and leftover iterations. n_viter = ( n ) / ( n_elem_per_reg * n_iter_unroll ); n_left = ( n ) % ( n_elem_per_reg * n_iter_unroll ); // If there is anything that would interfere with our use of contiguous // vector loads/stores, override n_viter and n_left to use scalar code // for all iterations. if ( incx != 1 || incy != 1 ) { n_viter = 0; n_left = n; } // Initialize local pointers. x0 = x; y0 = y; // Initialize the unrolled iterations' rho vectors to zero. rho0v.v = _mm256_setzero_ps(); rho1v.v = _mm256_setzero_ps(); rho2v.v = _mm256_setzero_ps(); rho3v.v = _mm256_setzero_ps(); for ( i = 0; i < n_viter; ++i ) { // Load the x and y input vector elements. x0v.v = _mm256_loadu_ps( x0 + 0*n_elem_per_reg ); y0v.v = _mm256_loadu_ps( y0 + 0*n_elem_per_reg ); x1v.v = _mm256_loadu_ps( x0 + 1*n_elem_per_reg ); y1v.v = _mm256_loadu_ps( y0 + 1*n_elem_per_reg ); x2v.v = _mm256_loadu_ps( x0 + 2*n_elem_per_reg ); y2v.v = _mm256_loadu_ps( y0 + 2*n_elem_per_reg ); x3v.v = _mm256_loadu_ps( x0 + 3*n_elem_per_reg ); y3v.v = _mm256_loadu_ps( y0 + 3*n_elem_per_reg ); // Compute the element-wise product of the x and y vectors, // storing in the corresponding rho vectors. rho0v.v = _mm256_fmadd_ps( x0v.v, y0v.v, rho0v.v ); rho1v.v = _mm256_fmadd_ps( x1v.v, y1v.v, rho1v.v ); rho2v.v = _mm256_fmadd_ps( x2v.v, y2v.v, rho2v.v ); rho3v.v = _mm256_fmadd_ps( x3v.v, y3v.v, rho3v.v ); x0 += ( n_elem_per_reg * n_iter_unroll ); y0 += ( n_elem_per_reg * n_iter_unroll ); } // Accumulate the unrolled rho vectors into a single vector. rho0v.v += rho1v.v; rho0v.v += rho2v.v; rho0v.v += rho3v.v; // Accumulate the final rho vector into a single scalar result. rho0 = rho0v.f[0] + rho0v.f[1] + rho0v.f[2] + rho0v.f[3] + rho0v.f[4] + rho0v.f[5] + rho0v.f[6] + rho0v.f[7]; // Issue vzeroupper instruction to clear upper lanes of ymm registers. // This avoids a performance penalty caused by false dependencies when // transitioning from from AVX to SSE instructions (which may occur // as soon as the n_left cleanup loop below if BLIS is compiled with // -mfpmath=sse). _mm256_zeroupper(); // If there are leftover iterations, perform them with scalar code. for ( i = 0; i < n_left; ++i ) { const float x0c = *x0; const float y0c = *y0; rho0 += x0c * y0c; x0 += incx; y0 += incy; } // Accumulate the final result into the output variable. PASTEMAC(s,axpys)( *alpha, rho0, *rho ); } // ----------------------------------------------------------------------------- void bli_ddotxv_zen_int ( conj_t conjx, conj_t conjy, dim_t n, double* restrict alpha, double* restrict x, inc_t incx, double* restrict y, inc_t incy, double* restrict beta, double* restrict rho, cntx_t* restrict cntx ) { const dim_t n_elem_per_reg = 4; const dim_t n_iter_unroll = 4; dim_t i; dim_t n_viter; dim_t n_left; double* restrict x0; double* restrict y0; double rho0; v4df_t rho0v, rho1v, rho2v, rho3v; v4df_t x0v, y0v; v4df_t x1v, y1v; v4df_t x2v, y2v; v4df_t x3v, y3v; // If beta is zero, initialize rho1 to zero instead of scaling // rho by beta (in case rho contains NaN or Inf). if ( PASTEMAC(d,eq0)( *beta ) ) { PASTEMAC(d,set0s)( *rho ); } else { PASTEMAC(d,scals)( *beta, *rho ); } // If the vector dimension is zero, output rho and return early. if ( bli_zero_dim1( n ) || PASTEMAC(d,eq0)( *alpha ) ) return; // Use the unrolling factor and the number of elements per register // to compute the number of vectorized and leftover iterations. n_viter = ( n ) / ( n_elem_per_reg * n_iter_unroll ); n_left = ( n ) % ( n_elem_per_reg * n_iter_unroll ); // If there is anything that would interfere with our use of contiguous // vector loads/stores, override n_viter and n_left to use scalar code // for all iterations. if ( incx != 1 || incy != 1 ) { n_viter = 0; n_left = n; } // Initialize local pointers. x0 = x; y0 = y; // Initialize the unrolled iterations' rho vectors to zero. rho0v.v = _mm256_setzero_pd(); rho1v.v = _mm256_setzero_pd(); rho2v.v = _mm256_setzero_pd(); rho3v.v = _mm256_setzero_pd(); for ( i = 0; i < n_viter; ++i ) { // Load the x and y input vector elements. x0v.v = _mm256_loadu_pd( x0 + 0*n_elem_per_reg ); y0v.v = _mm256_loadu_pd( y0 + 0*n_elem_per_reg ); x1v.v = _mm256_loadu_pd( x0 + 1*n_elem_per_reg ); y1v.v = _mm256_loadu_pd( y0 + 1*n_elem_per_reg ); x2v.v = _mm256_loadu_pd( x0 + 2*n_elem_per_reg ); y2v.v = _mm256_loadu_pd( y0 + 2*n_elem_per_reg ); x3v.v = _mm256_loadu_pd( x0 + 3*n_elem_per_reg ); y3v.v = _mm256_loadu_pd( y0 + 3*n_elem_per_reg ); // Compute the element-wise product of the x and y vectors, // storing in the corresponding rho vectors. rho0v.v = _mm256_fmadd_pd( x0v.v, y0v.v, rho0v.v ); rho1v.v = _mm256_fmadd_pd( x1v.v, y1v.v, rho1v.v ); rho2v.v = _mm256_fmadd_pd( x2v.v, y2v.v, rho2v.v ); rho3v.v = _mm256_fmadd_pd( x3v.v, y3v.v, rho3v.v ); x0 += ( n_elem_per_reg * n_iter_unroll ); y0 += ( n_elem_per_reg * n_iter_unroll ); } // Accumulate the unrolled rho vectors into a single vector. rho0v.v += rho1v.v; rho0v.v += rho2v.v; rho0v.v += rho3v.v; // Accumulate the final rho vector into a single scalar result. rho0 = rho0v.d[0] + rho0v.d[1] + rho0v.d[2] + rho0v.d[3]; // Issue vzeroupper instruction to clear upper lanes of ymm registers. // This avoids a performance penalty caused by false dependencies when // transitioning from from AVX to SSE instructions (which may occur // as soon as the n_left cleanup loop below if BLIS is compiled with // -mfpmath=sse). _mm256_zeroupper(); // If there are leftover iterations, perform them with scalar code. for ( i = 0; i < n_left; ++i ) { const double x0c = *x0; const double y0c = *y0; rho0 += x0c * y0c; x0 += incx; y0 += incy; } // Accumulate the final result into the output variable. PASTEMAC(d,axpys)( *alpha, rho0, *rho ); } blis-0.9.0/kernels/zen/1/bli_scalv_zen_int.c000066400000000000000000000163031422157504600207110ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2017 - 2019, Advanced Micro Devices, Inc. Copyright (C) 2018, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "immintrin.h" #include "blis.h" /* Union data structure to access AVX registers One 256-bit AVX register holds 8 SP elements. */ typedef union { __m256 v; float f[8] __attribute__((aligned(64))); } v8sf_t; /* Union data structure to access AVX registers * One 256-bit AVX register holds 4 DP elements. */ typedef union { __m256d v; double d[4] __attribute__((aligned(64))); } v4df_t; // ----------------------------------------------------------------------------- void bli_sscalv_zen_int ( conj_t conjalpha, dim_t n, float* restrict alpha, float* restrict x, inc_t incx, cntx_t* restrict cntx ) { const dim_t n_elem_per_reg = 8; const dim_t n_iter_unroll = 4; dim_t i; dim_t n_viter; dim_t n_left; float* restrict x0; v8sf_t alphav; v8sf_t x0v, x1v, x2v, x3v; // If the vector dimension is zero, or if alpha is unit, return early. if ( bli_zero_dim1( n ) || PASTEMAC(s,eq1)( *alpha ) ) return; // If alpha is zero, use setv (in case y contains NaN or Inf). if ( PASTEMAC(s,eq0)( *alpha ) ) { float* zero = bli_s0; ssetv_ker_ft f = bli_cntx_get_l1v_ker_dt( BLIS_FLOAT, BLIS_SETV_KER, cntx ); f ( BLIS_NO_CONJUGATE, n, zero, x, incx, cntx ); return; } // Use the unrolling factor and the number of elements per register // to compute the number of vectorized and leftover iterations. n_viter = ( n ) / ( n_elem_per_reg * n_iter_unroll ); n_left = ( n ) % ( n_elem_per_reg * n_iter_unroll ); // If there is anything that would interfere with our use of contiguous // vector loads/stores, override n_viter and n_left to use scalar code // for all iterations. if ( incx != 1 ) { n_viter = 0; n_left = n; } // Initialize local pointers. x0 = x; // Broadcast the alpha scalar to all elements of a vector register. alphav.v = _mm256_broadcast_ss( alpha ); // If there are vectorized iterations, perform them with vector // instructions. for ( i = 0; i < n_viter; ++i ) { // Load the input values. x0v.v = _mm256_loadu_ps( x0 + 0*n_elem_per_reg ); x1v.v = _mm256_loadu_ps( x0 + 1*n_elem_per_reg ); x2v.v = _mm256_loadu_ps( x0 + 2*n_elem_per_reg ); x3v.v = _mm256_loadu_ps( x0 + 3*n_elem_per_reg ); // perform : x := alpha * x; x0v.v = _mm256_mul_ps( alphav.v, x0v.v ); x1v.v = _mm256_mul_ps( alphav.v, x1v.v ); x2v.v = _mm256_mul_ps( alphav.v, x2v.v ); x3v.v = _mm256_mul_ps( alphav.v, x3v.v ); // Store the output. _mm256_storeu_ps( (x0 + 0*n_elem_per_reg), x0v.v ); _mm256_storeu_ps( (x0 + 1*n_elem_per_reg), x1v.v ); _mm256_storeu_ps( (x0 + 2*n_elem_per_reg), x2v.v ); _mm256_storeu_ps( (x0 + 3*n_elem_per_reg), x3v.v ); x0 += n_elem_per_reg * n_iter_unroll; } const float alphac = *alpha; // If there are leftover iterations, perform them with scalar code. for ( i = 0; i < n_left; ++i ) { *x0 *= alphac; x0 += incx; } } // ----------------------------------------------------------------------------- void bli_dscalv_zen_int ( conj_t conjalpha, dim_t n, double* restrict alpha, double* restrict x, inc_t incx, cntx_t* restrict cntx ) { const dim_t n_elem_per_reg = 4; const dim_t n_iter_unroll = 4; dim_t i; dim_t n_viter; dim_t n_left; double* restrict x0; v4df_t alphav; v4df_t x0v, x1v, x2v, x3v; // If the vector dimension is zero, or if alpha is unit, return early. if ( bli_zero_dim1( n ) || PASTEMAC(d,eq1)( *alpha ) ) return; // If alpha is zero, use setv (in case y contains NaN or Inf). if ( PASTEMAC(d,eq0)( *alpha ) ) { double* zero = bli_d0; dsetv_ker_ft f = bli_cntx_get_l1v_ker_dt( BLIS_DOUBLE, BLIS_SETV_KER, cntx ); f ( BLIS_NO_CONJUGATE, n, zero, x, incx, cntx ); return; } // Use the unrolling factor and the number of elements per register // to compute the number of vectorized and leftover iterations. n_viter = ( n ) / ( n_elem_per_reg * n_iter_unroll ); n_left = ( n ) % ( n_elem_per_reg * n_iter_unroll ); // If there is anything that would interfere with our use of contiguous // vector loads/stores, override n_viter and n_left to use scalar code // for all iterations. if ( incx != 1 ) { n_viter = 0; n_left = n; } // Initialize local pointers. x0 = x; // Broadcast the alpha scalar to all elements of a vector register. alphav.v = _mm256_broadcast_sd( alpha ); // If there are vectorized iterations, perform them with vector // instructions. for ( i = 0; i < n_viter; ++i ) { // Load the input values. x0v.v = _mm256_loadu_pd( x0 + 0*n_elem_per_reg ); x1v.v = _mm256_loadu_pd( x0 + 1*n_elem_per_reg ); x2v.v = _mm256_loadu_pd( x0 + 2*n_elem_per_reg ); x3v.v = _mm256_loadu_pd( x0 + 3*n_elem_per_reg ); // perform : y += alpha * x; x0v.v = _mm256_mul_pd( alphav.v, x0v.v ); x1v.v = _mm256_mul_pd( alphav.v, x1v.v ); x2v.v = _mm256_mul_pd( alphav.v, x2v.v ); x3v.v = _mm256_mul_pd( alphav.v, x3v.v ); // Store the output. _mm256_storeu_pd( (x0 + 0*n_elem_per_reg), x0v.v ); _mm256_storeu_pd( (x0 + 1*n_elem_per_reg), x1v.v ); _mm256_storeu_pd( (x0 + 2*n_elem_per_reg), x2v.v ); _mm256_storeu_pd( (x0 + 3*n_elem_per_reg), x3v.v ); x0 += n_elem_per_reg * n_iter_unroll; } const double alphac = *alpha; // If there are leftover iterations, perform them with scalar code. for ( i = 0; i < n_left; ++i ) { *x0 *= alphac; x0 += incx; } } blis-0.9.0/kernels/zen/1/bli_scalv_zen_int10.c000066400000000000000000000323451422157504600210560ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2017 - 2022, Advanced Micro Devices, Inc. Copyright (C) 2018, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "immintrin.h" #include "blis.h" /* Union data structure to access AVX registers One 256-bit AVX register holds 8 SP elements. */ typedef union { __m256 v; float f[8] __attribute__((aligned(64))); } v8sf_t; /* Union data structure to access AVX registers * One 256-bit AVX register holds 4 DP elements. */ typedef union { __m256d v; double d[4] __attribute__((aligned(64))); } v4df_t; // ----------------------------------------------------------------------------- void bli_sscalv_zen_int10 ( conj_t conjalpha, dim_t n, float* restrict alpha, float* restrict x, inc_t incx, cntx_t* restrict cntx ) { const dim_t n_elem_per_reg = 8; dim_t i; float* restrict x0; __m256 alphav; __m256 xv[10]; __m256 zv[10]; // If the vector dimension is zero, or if alpha is unit, return early. if ( bli_zero_dim1( n ) || PASTEMAC(s,eq1)( *alpha ) ) return; // If alpha is zero, use setv. if ( PASTEMAC(s,eq0)( *alpha ) ) { float* zero = bli_s0; if ( cntx == NULL ) cntx = bli_gks_query_cntx(); ssetv_ker_ft f = bli_cntx_get_l1v_ker_dt( BLIS_FLOAT, BLIS_SETV_KER, cntx ); f ( BLIS_NO_CONJUGATE, n, zero, x, incx, cntx ); return; } // Initialize local pointers. x0 = x; if ( incx == 1 ) { // Broadcast the alpha scalar to all elements of a vector register. alphav = _mm256_broadcast_ss( alpha ); for ( i = 0; (i + 79) < n; i += 80 ) { // Load the input values. xv[0] = _mm256_loadu_ps( x0 + 0*n_elem_per_reg ); xv[1] = _mm256_loadu_ps( x0 + 1*n_elem_per_reg ); xv[2] = _mm256_loadu_ps( x0 + 2*n_elem_per_reg ); xv[3] = _mm256_loadu_ps( x0 + 3*n_elem_per_reg ); xv[4] = _mm256_loadu_ps( x0 + 4*n_elem_per_reg ); xv[5] = _mm256_loadu_ps( x0 + 5*n_elem_per_reg ); xv[6] = _mm256_loadu_ps( x0 + 6*n_elem_per_reg ); xv[7] = _mm256_loadu_ps( x0 + 7*n_elem_per_reg ); xv[8] = _mm256_loadu_ps( x0 + 8*n_elem_per_reg ); xv[9] = _mm256_loadu_ps( x0 + 9*n_elem_per_reg ); // perform : x := alpha * x; zv[0] = _mm256_mul_ps( alphav, xv[0] ); zv[1] = _mm256_mul_ps( alphav, xv[1] ); zv[2] = _mm256_mul_ps( alphav, xv[2] ); zv[3] = _mm256_mul_ps( alphav, xv[3] ); zv[4] = _mm256_mul_ps( alphav, xv[4] ); zv[5] = _mm256_mul_ps( alphav, xv[5] ); zv[6] = _mm256_mul_ps( alphav, xv[6] ); zv[7] = _mm256_mul_ps( alphav, xv[7] ); zv[8] = _mm256_mul_ps( alphav, xv[8] ); zv[9] = _mm256_mul_ps( alphav, xv[9] ); // Store the output. _mm256_storeu_ps( (x0 + 0*n_elem_per_reg), zv[0] ); _mm256_storeu_ps( (x0 + 1*n_elem_per_reg), zv[1] ); _mm256_storeu_ps( (x0 + 2*n_elem_per_reg), zv[2] ); _mm256_storeu_ps( (x0 + 3*n_elem_per_reg), zv[3] ); _mm256_storeu_ps( (x0 + 4*n_elem_per_reg), zv[4] ); _mm256_storeu_ps( (x0 + 5*n_elem_per_reg), zv[5] ); _mm256_storeu_ps( (x0 + 6*n_elem_per_reg), zv[6] ); _mm256_storeu_ps( (x0 + 7*n_elem_per_reg), zv[7] ); _mm256_storeu_ps( (x0 + 8*n_elem_per_reg), zv[8] ); _mm256_storeu_ps( (x0 + 9*n_elem_per_reg), zv[9] ); x0 += 10*n_elem_per_reg; } for ( ; (i + 39) < n; i += 40 ) { // Load the input values. xv[0] = _mm256_loadu_ps( x0 + 0*n_elem_per_reg ); xv[1] = _mm256_loadu_ps( x0 + 1*n_elem_per_reg ); xv[2] = _mm256_loadu_ps( x0 + 2*n_elem_per_reg ); xv[3] = _mm256_loadu_ps( x0 + 3*n_elem_per_reg ); xv[4] = _mm256_loadu_ps( x0 + 4*n_elem_per_reg ); // perform : x := alpha * x; zv[0] = _mm256_mul_ps( alphav, xv[0] ); zv[1] = _mm256_mul_ps( alphav, xv[1] ); zv[2] = _mm256_mul_ps( alphav, xv[2] ); zv[3] = _mm256_mul_ps( alphav, xv[3] ); zv[4] = _mm256_mul_ps( alphav, xv[4] ); // Store the output. _mm256_storeu_ps( (x0 + 0*n_elem_per_reg), zv[0] ); _mm256_storeu_ps( (x0 + 1*n_elem_per_reg), zv[1] ); _mm256_storeu_ps( (x0 + 2*n_elem_per_reg), zv[2] ); _mm256_storeu_ps( (x0 + 3*n_elem_per_reg), zv[3] ); _mm256_storeu_ps( (x0 + 4*n_elem_per_reg), zv[4] ); x0 += 5*n_elem_per_reg; } for ( ; (i + 31) < n; i += 32 ) { // Load the input values. xv[0] = _mm256_loadu_ps( x0 + 0*n_elem_per_reg ); xv[1] = _mm256_loadu_ps( x0 + 1*n_elem_per_reg ); xv[2] = _mm256_loadu_ps( x0 + 2*n_elem_per_reg ); xv[3] = _mm256_loadu_ps( x0 + 3*n_elem_per_reg ); // perform : x := alpha * x; zv[0] = _mm256_mul_ps( alphav, xv[0] ); zv[1] = _mm256_mul_ps( alphav, xv[1] ); zv[2] = _mm256_mul_ps( alphav, xv[2] ); zv[3] = _mm256_mul_ps( alphav, xv[3] ); // Store the output. _mm256_storeu_ps( (x0 + 0*n_elem_per_reg), zv[0] ); _mm256_storeu_ps( (x0 + 1*n_elem_per_reg), zv[1] ); _mm256_storeu_ps( (x0 + 2*n_elem_per_reg), zv[2] ); _mm256_storeu_ps( (x0 + 3*n_elem_per_reg), zv[3] ); x0 += 4*n_elem_per_reg; } for ( ; (i + 15) < n; i += 16 ) { // Load the input values. xv[0] = _mm256_loadu_ps( x0 + 0*n_elem_per_reg ); xv[1] = _mm256_loadu_ps( x0 + 1*n_elem_per_reg ); // perform : x := alpha * x; zv[0] = _mm256_mul_ps( alphav, xv[0] ); zv[1] = _mm256_mul_ps( alphav, xv[1] ); // Store the output. _mm256_storeu_ps( (x0 + 0*n_elem_per_reg), zv[0] ); _mm256_storeu_ps( (x0 + 1*n_elem_per_reg), zv[1] ); x0 += 2*n_elem_per_reg; } for ( ; (i + 7) < n; i += 8 ) { // Load the input values. xv[0] = _mm256_loadu_ps( x0 + 0*n_elem_per_reg ); // perform : x := alpha * x; zv[0] = _mm256_mul_ps( alphav, xv[0] ); // Store the output. _mm256_storeu_ps( (x0 + 0*n_elem_per_reg), zv[0] ); x0 += 1*n_elem_per_reg; } for ( ; (i + 0) < n; i += 1 ) { *x0 *= *alpha; x0 += 1; } } else { const float alphac = *alpha; for ( i = 0; i < n; ++i ) { *x0 *= alphac; x0 += incx; } } } // ----------------------------------------------------------------------------- void bli_dscalv_zen_int10 ( conj_t conjalpha, dim_t n, double* restrict alpha, double* restrict x, inc_t incx, cntx_t* restrict cntx ) { const dim_t n_elem_per_reg = 4; dim_t i; double* restrict x0; __m256d alphav; __m256d xv[10]; __m256d zv[10]; // If the vector dimension is zero, or if alpha is unit, return early. if ( bli_zero_dim1( n ) || PASTEMAC(d,eq1)( *alpha ) ) return; // If alpha is zero, use setv. if ( PASTEMAC(d,eq0)( *alpha ) ) { double* zero = bli_d0; if( cntx == NULL ) cntx = bli_gks_query_cntx(); dsetv_ker_ft f = bli_cntx_get_l1v_ker_dt( BLIS_DOUBLE, BLIS_SETV_KER, cntx ); f ( BLIS_NO_CONJUGATE, n, zero, x, incx, cntx ); return; } // Initialize local pointers. x0 = x; if ( incx == 1 ) { // Broadcast the alpha scalar to all elements of a vector register. alphav = _mm256_broadcast_sd( alpha ); for ( i = 0; (i + 39) < n; i += 40 ) { // Load the input values. xv[0] = _mm256_loadu_pd( x0 + 0*n_elem_per_reg ); xv[1] = _mm256_loadu_pd( x0 + 1*n_elem_per_reg ); xv[2] = _mm256_loadu_pd( x0 + 2*n_elem_per_reg ); xv[3] = _mm256_loadu_pd( x0 + 3*n_elem_per_reg ); xv[4] = _mm256_loadu_pd( x0 + 4*n_elem_per_reg ); xv[5] = _mm256_loadu_pd( x0 + 5*n_elem_per_reg ); xv[6] = _mm256_loadu_pd( x0 + 6*n_elem_per_reg ); xv[7] = _mm256_loadu_pd( x0 + 7*n_elem_per_reg ); xv[8] = _mm256_loadu_pd( x0 + 8*n_elem_per_reg ); xv[9] = _mm256_loadu_pd( x0 + 9*n_elem_per_reg ); // perform : x := alpha * x; zv[0] = _mm256_mul_pd( alphav, xv[0] ); zv[1] = _mm256_mul_pd( alphav, xv[1] ); zv[2] = _mm256_mul_pd( alphav, xv[2] ); zv[3] = _mm256_mul_pd( alphav, xv[3] ); zv[4] = _mm256_mul_pd( alphav, xv[4] ); zv[5] = _mm256_mul_pd( alphav, xv[5] ); zv[6] = _mm256_mul_pd( alphav, xv[6] ); zv[7] = _mm256_mul_pd( alphav, xv[7] ); zv[8] = _mm256_mul_pd( alphav, xv[8] ); zv[9] = _mm256_mul_pd( alphav, xv[9] ); // Store the output. _mm256_storeu_pd( (x0 + 0*n_elem_per_reg), zv[0] ); _mm256_storeu_pd( (x0 + 1*n_elem_per_reg), zv[1] ); _mm256_storeu_pd( (x0 + 2*n_elem_per_reg), zv[2] ); _mm256_storeu_pd( (x0 + 3*n_elem_per_reg), zv[3] ); _mm256_storeu_pd( (x0 + 4*n_elem_per_reg), zv[4] ); _mm256_storeu_pd( (x0 + 5*n_elem_per_reg), zv[5] ); _mm256_storeu_pd( (x0 + 6*n_elem_per_reg), zv[6] ); _mm256_storeu_pd( (x0 + 7*n_elem_per_reg), zv[7] ); _mm256_storeu_pd( (x0 + 8*n_elem_per_reg), zv[8] ); _mm256_storeu_pd( (x0 + 9*n_elem_per_reg), zv[9] ); x0 += 10*n_elem_per_reg; } for ( ; (i + 19) < n; i += 20 ) { // Load the input values. xv[0] = _mm256_loadu_pd( x0 + 0*n_elem_per_reg ); xv[1] = _mm256_loadu_pd( x0 + 1*n_elem_per_reg ); xv[2] = _mm256_loadu_pd( x0 + 2*n_elem_per_reg ); xv[3] = _mm256_loadu_pd( x0 + 3*n_elem_per_reg ); xv[4] = _mm256_loadu_pd( x0 + 4*n_elem_per_reg ); // perform : x := alpha * x; zv[0] = _mm256_mul_pd( alphav, xv[0] ); zv[1] = _mm256_mul_pd( alphav, xv[1] ); zv[2] = _mm256_mul_pd( alphav, xv[2] ); zv[3] = _mm256_mul_pd( alphav, xv[3] ); zv[4] = _mm256_mul_pd( alphav, xv[4] ); // Store the output. _mm256_storeu_pd( (x0 + 0*n_elem_per_reg), zv[0] ); _mm256_storeu_pd( (x0 + 1*n_elem_per_reg), zv[1] ); _mm256_storeu_pd( (x0 + 2*n_elem_per_reg), zv[2] ); _mm256_storeu_pd( (x0 + 3*n_elem_per_reg), zv[3] ); _mm256_storeu_pd( (x0 + 4*n_elem_per_reg), zv[4] ); x0 += 5*n_elem_per_reg; } for ( ; (i + 15) < n; i += 16 ) { // Load the input values. xv[0] = _mm256_loadu_pd( x0 + 0*n_elem_per_reg ); xv[1] = _mm256_loadu_pd( x0 + 1*n_elem_per_reg ); xv[2] = _mm256_loadu_pd( x0 + 2*n_elem_per_reg ); xv[3] = _mm256_loadu_pd( x0 + 3*n_elem_per_reg ); // perform : x := alpha * x; zv[0] = _mm256_mul_pd( alphav, xv[0] ); zv[1] = _mm256_mul_pd( alphav, xv[1] ); zv[2] = _mm256_mul_pd( alphav, xv[2] ); zv[3] = _mm256_mul_pd( alphav, xv[3] ); // Store the output. _mm256_storeu_pd( (x0 + 0*n_elem_per_reg), zv[0] ); _mm256_storeu_pd( (x0 + 1*n_elem_per_reg), zv[1] ); _mm256_storeu_pd( (x0 + 2*n_elem_per_reg), zv[2] ); _mm256_storeu_pd( (x0 + 3*n_elem_per_reg), zv[3] ); x0 += 4*n_elem_per_reg; } for ( ; (i + 7) < n; i += 8 ) { // Load the input values. xv[0] = _mm256_loadu_pd( x0 + 0*n_elem_per_reg ); xv[1] = _mm256_loadu_pd( x0 + 1*n_elem_per_reg ); // perform : x := alpha * x; zv[0] = _mm256_mul_pd( alphav, xv[0] ); zv[1] = _mm256_mul_pd( alphav, xv[1] ); // Store the output. _mm256_storeu_pd( (x0 + 0*n_elem_per_reg), zv[0] ); _mm256_storeu_pd( (x0 + 1*n_elem_per_reg), zv[1] ); x0 += 2*n_elem_per_reg; } for ( ; (i + 3) < n; i += 4 ) { // Load the input values. xv[0] = _mm256_loadu_pd( x0 + 0*n_elem_per_reg ); // perform : x := alpha * x; zv[0] = _mm256_mul_pd( alphav, xv[0] ); // Store the output. _mm256_storeu_pd( (x0 + 0*n_elem_per_reg), zv[0] ); x0 += 1*n_elem_per_reg; } for ( ; (i + 0) < n; i += 1 ) { *x0 *= *alpha; x0 += 1; } } else { const double alphac = *alpha; for ( i = 0; i < n; ++i ) { *x0 *= alphac; x0 += incx; } } } // ----------------------------------------------------------------------------- // // NOTE: This function definition is provided as a placeholder in order to allow // function names of scalv kernels to be hard-coded in bli_gemv_unf_var2_amd.c. // void bli_cscalv_zen_int10 ( conj_t conjalpha, dim_t n, scomplex* restrict alpha, scomplex* restrict x, inc_t incx, cntx_t* restrict cntx ) { const num_t dt = BLIS_SCOMPLEX; cscalv_ker_ft f = bli_cntx_get_l1v_ker_dt( dt, BLIS_SCALV_KER, cntx ); f ( conjalpha, n, alpha, x, incx, cntx ); } blis-0.9.0/kernels/zen/1/bli_setv_zen_int.c000066400000000000000000000166251422157504600205710ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "immintrin.h" #include "blis.h" // ----------------------------------------------------------------------------- void bli_ssetv_zen_int ( conj_t conjalpha, dim_t n, float* restrict alpha, float* restrict x, inc_t incx, cntx_t* restrict cntx ) { const dim_t num_elem_per_reg = 8; dim_t i = 0; __m256 alphav; // If the vector dimension is zero return early. if ( bli_zero_dim1( n ) ) return; if ( incx == 1 ) { alphav = _mm256_broadcast_ss( alpha ); // For loop with n & ~0x7F => n & 0xFFFFFF80 masks the lower bits and results in multiples of 128 // for example if n = 255 // n & ~0x7F results in 128: copy from 0 to 128 happens in first loop // n & ~0x3F results in 192: copy from 128 to 192 happens in second loop // n & ~0x1F results in 224: copy from 128 to 192 happens in third loop and so on. for ( i = 0; i < (n & (~0x7F)); i += 128 ) { _mm256_storeu_ps(x + num_elem_per_reg * 0, alphav); _mm256_storeu_ps(x + num_elem_per_reg * 1, alphav); _mm256_storeu_ps(x + num_elem_per_reg * 2, alphav); _mm256_storeu_ps(x + num_elem_per_reg * 3, alphav); _mm256_storeu_ps(x + num_elem_per_reg * 4, alphav); _mm256_storeu_ps(x + num_elem_per_reg * 5, alphav); _mm256_storeu_ps(x + num_elem_per_reg * 6, alphav); _mm256_storeu_ps(x + num_elem_per_reg * 7, alphav); _mm256_storeu_ps(x + num_elem_per_reg * 8, alphav); _mm256_storeu_ps(x + num_elem_per_reg * 9, alphav); _mm256_storeu_ps(x + num_elem_per_reg * 10, alphav); _mm256_storeu_ps(x + num_elem_per_reg * 11, alphav); _mm256_storeu_ps(x + num_elem_per_reg * 12, alphav); _mm256_storeu_ps(x + num_elem_per_reg * 13, alphav); _mm256_storeu_ps(x + num_elem_per_reg * 14, alphav); _mm256_storeu_ps(x + num_elem_per_reg * 15, alphav); x += 128; } for ( ; i < (n & (~0x3F)); i += 64 ) { _mm256_storeu_ps(x + num_elem_per_reg * 0, alphav); _mm256_storeu_ps(x + num_elem_per_reg * 1, alphav); _mm256_storeu_ps(x + num_elem_per_reg * 2, alphav); _mm256_storeu_ps(x + num_elem_per_reg * 3, alphav); _mm256_storeu_ps(x + num_elem_per_reg * 4, alphav); _mm256_storeu_ps(x + num_elem_per_reg * 5, alphav); _mm256_storeu_ps(x + num_elem_per_reg * 6, alphav); _mm256_storeu_ps(x + num_elem_per_reg * 7, alphav); x += 64; } for ( ; i < (n & (~0x1F)); i += 32 ) { _mm256_storeu_ps(x + num_elem_per_reg * 0, alphav); _mm256_storeu_ps(x + num_elem_per_reg * 1, alphav); _mm256_storeu_ps(x + num_elem_per_reg * 2, alphav); _mm256_storeu_ps(x + num_elem_per_reg * 3, alphav); x += 32; } for ( ; i < (n & (~0x0F)); i += 16 ) { _mm256_storeu_ps(x + num_elem_per_reg * 0, alphav); _mm256_storeu_ps(x + num_elem_per_reg * 1, alphav); x += 16; } for ( ; i < (n & (~0x07)); i += 8 ) { _mm256_storeu_ps(x + num_elem_per_reg * 0, alphav); x += 8; } for ( ; i < n; ++i ) { *x++ = *alpha; } } else { for ( dim_t i = 0; i < n; ++i ) { *x = *alpha; x += incx; } } } void bli_dsetv_zen_int ( conj_t conjalpha, dim_t n, double* restrict alpha, double* restrict x, inc_t incx, cntx_t* restrict cntx ) { const dim_t num_elem_per_reg = 4; dim_t i = 0; __m256d alphav; // If the vector dimension is zero return early. if ( bli_zero_dim1( n ) ) return; if ( incx == 1 ) { // Broadcast the alpha scalar to all elements of a vector register. alphav = _mm256_broadcast_sd( alpha ); // n & (~0x3F) = n & 0xFFFFFFC0 -> this masks the numbers less than 64, // the copy operation will be done for the multiples of 64 for ( i = 0; i < (n & (~0x3F)); i += 64 ) { _mm256_storeu_pd(x + num_elem_per_reg * 0, alphav); _mm256_storeu_pd(x + num_elem_per_reg * 1, alphav); _mm256_storeu_pd(x + num_elem_per_reg * 2, alphav); _mm256_storeu_pd(x + num_elem_per_reg * 3, alphav); _mm256_storeu_pd(x + num_elem_per_reg * 4, alphav); _mm256_storeu_pd(x + num_elem_per_reg * 5, alphav); _mm256_storeu_pd(x + num_elem_per_reg * 6, alphav); _mm256_storeu_pd(x + num_elem_per_reg * 7, alphav); _mm256_storeu_pd(x + num_elem_per_reg * 8, alphav); _mm256_storeu_pd(x + num_elem_per_reg * 9, alphav); _mm256_storeu_pd(x + num_elem_per_reg * 10, alphav); _mm256_storeu_pd(x + num_elem_per_reg * 11, alphav); _mm256_storeu_pd(x + num_elem_per_reg * 12, alphav); _mm256_storeu_pd(x + num_elem_per_reg * 13, alphav); _mm256_storeu_pd(x + num_elem_per_reg * 14, alphav); _mm256_storeu_pd(x + num_elem_per_reg * 15, alphav); x += num_elem_per_reg * 16; } for ( ; i < (n & (~0x1F)); i += 32 ) { _mm256_storeu_pd(x + num_elem_per_reg * 0, alphav); _mm256_storeu_pd(x + num_elem_per_reg * 1, alphav); _mm256_storeu_pd(x + num_elem_per_reg * 2, alphav); _mm256_storeu_pd(x + num_elem_per_reg * 3, alphav); _mm256_storeu_pd(x + num_elem_per_reg * 4, alphav); _mm256_storeu_pd(x + num_elem_per_reg * 5, alphav); _mm256_storeu_pd(x + num_elem_per_reg * 6, alphav); _mm256_storeu_pd(x + num_elem_per_reg * 7, alphav); x += num_elem_per_reg * 8; } for ( ; i < (n & (~0xF)); i += 16 ) { _mm256_storeu_pd(x + num_elem_per_reg * 0, alphav); _mm256_storeu_pd(x + num_elem_per_reg * 1, alphav); _mm256_storeu_pd(x + num_elem_per_reg * 2, alphav); _mm256_storeu_pd(x + num_elem_per_reg * 3, alphav); x += num_elem_per_reg * 4; } for ( ; i < (n & (~0x07)); i += 8 ) { _mm256_storeu_pd(x + num_elem_per_reg * 0, alphav); _mm256_storeu_pd(x + num_elem_per_reg * 1, alphav); x += num_elem_per_reg * 2; } for ( ; i < (n & (~0x03)); i += 4 ) { _mm256_storeu_pd(x + num_elem_per_reg * 0, alphav); x += num_elem_per_reg; } for ( ; i < n; ++i ) { *x++ = *alpha; } } else { for ( i = 0; i < n; ++i ) { *x = *alpha; x += incx; } } } blis-0.9.0/kernels/zen/1/bli_swapv_zen_int8.c000066400000000000000000000251161422157504600210330ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "immintrin.h" #include "blis.h" /* Union data structure to access AVX registers One 256-bit AVX register holds 8 SP elements. */ typedef union { __m256 v; float f[8] __attribute__((aligned(64))); } v8sf_t; /* Union data structure to access AVX registers * One 256-bit AVX register holds 4 DP elements. */ typedef union { __m256d v; double d[4] __attribute__((aligned(64))); } v4df_t; // ----------------------------------------------------------------------------- void bli_sswapv_zen_int8 ( dim_t n, float* restrict x, inc_t incx, float* restrict y, inc_t incy, cntx_t* restrict cntx ) { const dim_t n_elem_per_reg = 8; dim_t i = 0; float* restrict x0; float* restrict y0; __m256 xv[8]; __m256 yv[8]; // If the vector dimension is zero, return early. if ( bli_zero_dim1( n ) ) return; x0 = x; y0 = y; if ( incx == 1 && incy == 1 ) { for ( i = 0; ( i + 63 ) < n; i += 64 ) { xv[0] = _mm256_loadu_ps( x0 + 0*n_elem_per_reg ); xv[1] = _mm256_loadu_ps( x0 + 1*n_elem_per_reg ); xv[2] = _mm256_loadu_ps( x0 + 2*n_elem_per_reg ); xv[3] = _mm256_loadu_ps( x0 + 3*n_elem_per_reg ); xv[4] = _mm256_loadu_ps( x0 + 4*n_elem_per_reg ); xv[5] = _mm256_loadu_ps( x0 + 5*n_elem_per_reg ); xv[6] = _mm256_loadu_ps( x0 + 6*n_elem_per_reg ); xv[7] = _mm256_loadu_ps( x0 + 7*n_elem_per_reg ); yv[0] = _mm256_loadu_ps( y0 + 0*n_elem_per_reg ); yv[1] = _mm256_loadu_ps( y0 + 1*n_elem_per_reg ); yv[2] = _mm256_loadu_ps( y0 + 2*n_elem_per_reg ); yv[3] = _mm256_loadu_ps( y0 + 3*n_elem_per_reg ); yv[4] = _mm256_loadu_ps( y0 + 4*n_elem_per_reg ); yv[5] = _mm256_loadu_ps( y0 + 5*n_elem_per_reg ); yv[6] = _mm256_loadu_ps( y0 + 6*n_elem_per_reg ); yv[7] = _mm256_loadu_ps( y0 + 7*n_elem_per_reg ); _mm256_storeu_ps( (x0 + 0*n_elem_per_reg), yv[0]); _mm256_storeu_ps( (x0 + 1*n_elem_per_reg), yv[1]); _mm256_storeu_ps( (x0 + 2*n_elem_per_reg), yv[2]); _mm256_storeu_ps( (x0 + 3*n_elem_per_reg), yv[3]); _mm256_storeu_ps( (x0 + 4*n_elem_per_reg), yv[4]); _mm256_storeu_ps( (x0 + 5*n_elem_per_reg), yv[5]); _mm256_storeu_ps( (x0 + 6*n_elem_per_reg), yv[6]); _mm256_storeu_ps( (x0 + 7*n_elem_per_reg), yv[7]); _mm256_storeu_ps( (y0 + 0*n_elem_per_reg), xv[0]); _mm256_storeu_ps( (y0 + 1*n_elem_per_reg), xv[1]); _mm256_storeu_ps( (y0 + 2*n_elem_per_reg), xv[2]); _mm256_storeu_ps( (y0 + 3*n_elem_per_reg), xv[3]); _mm256_storeu_ps( (y0 + 4*n_elem_per_reg), xv[4]); _mm256_storeu_ps( (y0 + 5*n_elem_per_reg), xv[5]); _mm256_storeu_ps( (y0 + 6*n_elem_per_reg), xv[6]); _mm256_storeu_ps( (y0 + 7*n_elem_per_reg), xv[7]); x0 += 8*n_elem_per_reg; y0 += 8*n_elem_per_reg; } for ( ; ( i + 31 ) < n; i += 32 ) { xv[0] = _mm256_loadu_ps( x0 + 0*n_elem_per_reg ); xv[1] = _mm256_loadu_ps( x0 + 1*n_elem_per_reg ); xv[2] = _mm256_loadu_ps( x0 + 2*n_elem_per_reg ); xv[3] = _mm256_loadu_ps( x0 + 3*n_elem_per_reg ); yv[0] = _mm256_loadu_ps( y0 + 0*n_elem_per_reg ); yv[1] = _mm256_loadu_ps( y0 + 1*n_elem_per_reg ); yv[2] = _mm256_loadu_ps( y0 + 2*n_elem_per_reg ); yv[3] = _mm256_loadu_ps( y0 + 3*n_elem_per_reg ); _mm256_storeu_ps( (y0 + 0*n_elem_per_reg), xv[0]); _mm256_storeu_ps( (y0 + 1*n_elem_per_reg), xv[1]); _mm256_storeu_ps( (y0 + 2*n_elem_per_reg), xv[2]); _mm256_storeu_ps( (y0 + 3*n_elem_per_reg), xv[3]); _mm256_storeu_ps( (x0 + 0*n_elem_per_reg), yv[0]); _mm256_storeu_ps( (x0 + 1*n_elem_per_reg), yv[1]); _mm256_storeu_ps( (x0 + 2*n_elem_per_reg), yv[2]); _mm256_storeu_ps( (x0 + 3*n_elem_per_reg), yv[3]); x0 += 4*n_elem_per_reg; y0 += 4*n_elem_per_reg; } for ( ; ( i + 15 ) < n; i += 16 ) { xv[0] = _mm256_loadu_ps( x0 + 0*n_elem_per_reg ); xv[1] = _mm256_loadu_ps( x0 + 1*n_elem_per_reg ); yv[0] = _mm256_loadu_ps( y0 + 0*n_elem_per_reg ); yv[1] = _mm256_loadu_ps( y0 + 1*n_elem_per_reg ); _mm256_storeu_ps( (y0 + 0*n_elem_per_reg), xv[0]); _mm256_storeu_ps( (y0 + 1*n_elem_per_reg), xv[1]); _mm256_storeu_ps( (x0 + 0*n_elem_per_reg), yv[0]); _mm256_storeu_ps( (x0 + 1*n_elem_per_reg), yv[1]); x0 += 2*n_elem_per_reg; y0 += 2*n_elem_per_reg; } for ( ; ( i + 7 ) < n; i += 8 ) { xv[0] = _mm256_loadu_ps( x0 + 0*n_elem_per_reg ); yv[0] = _mm256_loadu_ps( y0 + 0*n_elem_per_reg ); _mm256_storeu_ps( (x0 + 0*n_elem_per_reg), yv[0]); _mm256_storeu_ps( (y0 + 0*n_elem_per_reg), xv[0]); x0 += 1*n_elem_per_reg; y0 += 1*n_elem_per_reg; } for ( ; (i + 0) < n; i += 1 ) { PASTEMAC(s,swaps)( x[i], y[i] ); } } else { for ( i = 0; i < n; ++i ) { PASTEMAC(s,swaps)( (*x0), (*y0) ); x0 += incx; y0 += incy; } } } //-------------------------------------------------------------------------------- void bli_dswapv_zen_int8 ( dim_t n, double* restrict x, inc_t incx, double* restrict y, inc_t incy, cntx_t* restrict cntx ) { const dim_t n_elem_per_reg = 4; dim_t i = 0; double* restrict x0; double* restrict y0; __m256d xv[8]; __m256d yv[8]; // If the vector dimension is zero, return early. if ( bli_zero_dim1( n ) ) return; x0 = x; y0 = y; if ( incx == 1 && incy == 1 ) { for ( ; ( i + 31 ) < n; i += 32 ) { xv[0] = _mm256_loadu_pd( x0 + 0*n_elem_per_reg ); xv[1] = _mm256_loadu_pd( x0 + 1*n_elem_per_reg ); xv[2] = _mm256_loadu_pd( x0 + 2*n_elem_per_reg ); xv[3] = _mm256_loadu_pd( x0 + 3*n_elem_per_reg ); xv[4] = _mm256_loadu_pd( x0 + 4*n_elem_per_reg ); xv[5] = _mm256_loadu_pd( x0 + 5*n_elem_per_reg ); xv[6] = _mm256_loadu_pd( x0 + 6*n_elem_per_reg ); xv[7] = _mm256_loadu_pd( x0 + 7*n_elem_per_reg ); yv[0] = _mm256_loadu_pd( y0 + 0*n_elem_per_reg ); yv[1] = _mm256_loadu_pd( y0 + 1*n_elem_per_reg ); yv[2] = _mm256_loadu_pd( y0 + 2*n_elem_per_reg ); yv[3] = _mm256_loadu_pd( y0 + 3*n_elem_per_reg ); yv[4] = _mm256_loadu_pd( y0 + 4*n_elem_per_reg ); yv[5] = _mm256_loadu_pd( y0 + 5*n_elem_per_reg ); yv[6] = _mm256_loadu_pd( y0 + 6*n_elem_per_reg ); yv[7] = _mm256_loadu_pd( y0 + 7*n_elem_per_reg ); _mm256_storeu_pd( (x0 + 0*n_elem_per_reg), yv[0]); _mm256_storeu_pd( (x0 + 1*n_elem_per_reg), yv[1]); _mm256_storeu_pd( (x0 + 2*n_elem_per_reg), yv[2]); _mm256_storeu_pd( (x0 + 3*n_elem_per_reg), yv[3]); _mm256_storeu_pd( (x0 + 4*n_elem_per_reg), yv[4]); _mm256_storeu_pd( (x0 + 5*n_elem_per_reg), yv[5]); _mm256_storeu_pd( (x0 + 6*n_elem_per_reg), yv[6]); _mm256_storeu_pd( (x0 + 7*n_elem_per_reg), yv[7]); _mm256_storeu_pd( (y0 + 0*n_elem_per_reg), xv[0]); _mm256_storeu_pd( (y0 + 1*n_elem_per_reg), xv[1]); _mm256_storeu_pd( (y0 + 2*n_elem_per_reg), xv[2]); _mm256_storeu_pd( (y0 + 3*n_elem_per_reg), xv[3]); _mm256_storeu_pd( (y0 + 4*n_elem_per_reg), xv[4]); _mm256_storeu_pd( (y0 + 5*n_elem_per_reg), xv[5]); _mm256_storeu_pd( (y0 + 6*n_elem_per_reg), xv[6]); _mm256_storeu_pd( (y0 + 7*n_elem_per_reg), xv[7]); x0 += 8*n_elem_per_reg; y0 += 8*n_elem_per_reg; } for ( ; ( i + 15 ) < n; i += 16 ) { xv[0] = _mm256_loadu_pd( x0 + 0*n_elem_per_reg ); xv[1] = _mm256_loadu_pd( x0 + 1*n_elem_per_reg ); xv[2] = _mm256_loadu_pd( x0 + 2*n_elem_per_reg ); xv[3] = _mm256_loadu_pd( x0 + 3*n_elem_per_reg ); yv[0] = _mm256_loadu_pd( y0 + 0*n_elem_per_reg ); yv[1] = _mm256_loadu_pd( y0 + 1*n_elem_per_reg ); yv[2] = _mm256_loadu_pd( y0 + 2*n_elem_per_reg ); yv[3] = _mm256_loadu_pd( y0 + 3*n_elem_per_reg ); _mm256_storeu_pd( (y0 + 0*n_elem_per_reg), xv[0]); _mm256_storeu_pd( (y0 + 1*n_elem_per_reg), xv[1]); _mm256_storeu_pd( (y0 + 2*n_elem_per_reg), xv[2]); _mm256_storeu_pd( (y0 + 3*n_elem_per_reg), xv[3]); _mm256_storeu_pd( (x0 + 0*n_elem_per_reg), yv[0]); _mm256_storeu_pd( (x0 + 1*n_elem_per_reg), yv[1]); _mm256_storeu_pd( (x0 + 2*n_elem_per_reg), yv[2]); _mm256_storeu_pd( (x0 + 3*n_elem_per_reg), yv[3]); x0 += 4*n_elem_per_reg; y0 += 4*n_elem_per_reg; } for ( ; ( i + 7 ) < n; i += 8 ) { xv[0] = _mm256_loadu_pd( x0 + 0*n_elem_per_reg ); xv[1] = _mm256_loadu_pd( x0 + 1*n_elem_per_reg ); yv[0] = _mm256_loadu_pd( y0 + 0*n_elem_per_reg ); yv[1] = _mm256_loadu_pd( y0 + 1*n_elem_per_reg ); _mm256_storeu_pd( (y0 + 0*n_elem_per_reg), xv[0]); _mm256_storeu_pd( (y0 + 1*n_elem_per_reg), xv[1]); _mm256_storeu_pd( (x0 + 0*n_elem_per_reg), yv[0]); _mm256_storeu_pd( (x0 + 1*n_elem_per_reg), yv[1]); x0 += 2*n_elem_per_reg; y0 += 2*n_elem_per_reg; } for ( ; ( i + 3 ) < n; i += 4 ) { xv[0] = _mm256_loadu_pd( x0 + 0*n_elem_per_reg ); yv[0] = _mm256_loadu_pd( y0 + 0*n_elem_per_reg ); _mm256_storeu_pd( (y0 + 0*n_elem_per_reg), xv[0]); _mm256_storeu_pd( (x0 + 0*n_elem_per_reg), yv[0]); x0 += 1*n_elem_per_reg; y0 += 1*n_elem_per_reg; } for ( ; (i + 0) < n; i += 1 ) { PASTEMAC(d,swaps)( x[i], y[i] ); } } else { for ( i = 0; i < n; ++i ) { PASTEMAC(d,swaps)( (*x0), (*y0) ); x0 += incx; y0 += incy; } } } blis-0.9.0/kernels/zen/1f/000077500000000000000000000000001422157504600152245ustar00rootroot00000000000000blis-0.9.0/kernels/zen/1f/bli_axpyf_zen_int_4.c000066400000000000000000000216621422157504600213250ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2021-2022, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "immintrin.h" #include "blis.h" void bli_caxpyf_zen_int_4 ( conj_t conja, conj_t conjx, dim_t m, dim_t b_n, scomplex* restrict alpha, scomplex* restrict a, inc_t inca, inc_t lda, scomplex* restrict x, inc_t incx, scomplex* restrict y, inc_t incy, cntx_t* restrict cntx ) { inc_t fuse_fac = 4; inc_t i; __m256 ymm0, ymm1, ymm2, ymm3; __m256 ymm4, ymm5, ymm6, ymm7; __m256 ymm8, ymm10; __m256 ymm12, ymm13; float* ap[4]; float* y0 = (float*)y; scomplex chi0; scomplex chi1; scomplex chi2; scomplex chi3; dim_t setPlusOne = 1; if ( bli_is_conj(conja) ) { setPlusOne = -1; } // If either dimension is zero, or if alpha is zero, return early. if ( bli_zero_dim2( m, b_n ) || bli_ceq0( *alpha ) ) return; // If b_n is not equal to the fusing factor, then perform the entire // operation as a loop over axpyv. if ( b_n != fuse_fac ) { if ( cntx == NULL ) cntx = bli_gks_query_cntx(); caxpyv_ker_ft f = bli_cntx_get_l1v_ker_dt( BLIS_SCOMPLEX, BLIS_AXPYV_KER, cntx ); for ( i = 0; i < b_n; ++i ) { scomplex* a1 = a + (0 )*inca + (i )*lda; scomplex* chi1 = x + (i )*incx; scomplex* y1 = y + (0 )*incy; scomplex alpha_chi1; bli_ccopycjs( conjx, *chi1, alpha_chi1 ); bli_cscals( *alpha, alpha_chi1 ); f ( conja, m, &alpha_chi1, a1, inca, y1, incy, cntx ); } return; } // At this point, we know that b_n is exactly equal to the fusing factor. if(bli_is_noconj(conjx)) { chi0 = *( x + 0*incx ); chi1 = *( x + 1*incx ); chi2 = *( x + 2*incx ); chi3 = *( x + 3*incx ); } else { scomplex *pchi0 = x + 0*incx ; scomplex *pchi1 = x + 1*incx ; scomplex *pchi2 = x + 2*incx ; scomplex *pchi3 = x + 3*incx ; bli_ccopycjs( conjx, *pchi0, chi0 ); bli_ccopycjs( conjx, *pchi1, chi1 ); bli_ccopycjs( conjx, *pchi2, chi2 ); bli_ccopycjs( conjx, *pchi3, chi3 ); } // Scale each chi scalar by alpha. bli_cscals( *alpha, chi0 ); bli_cscals( *alpha, chi1 ); bli_cscals( *alpha, chi2 ); bli_cscals( *alpha, chi3 ); lda *= 2; incx *= 2; incy *= 2; inca *= 2; ap[0] = (float*)a; ap[1] = (float*)a + lda; ap[2] = ap[1] + lda; ap[3] = ap[2] + lda; if( inca == 2 && incy == 2 ) { inc_t n1 = m/4; inc_t n2 = m%4; ymm12 = _mm256_setzero_ps(); ymm13 = _mm256_setzero_ps(); // broadcast real & imag parts of 4 elements of x ymm0 = _mm256_broadcast_ss(&chi0.real); // real part of x0 ymm1 = _mm256_broadcast_ss(&chi0.imag); // imag part of x0 ymm2 = _mm256_broadcast_ss(&chi1.real); // real part of x1 ymm3 = _mm256_broadcast_ss(&chi1.imag); // imag part of x1 ymm4 = _mm256_broadcast_ss(&chi2.real); // real part of x2 ymm5 = _mm256_broadcast_ss(&chi2.imag); // imag part of x2 ymm6 = _mm256_broadcast_ss(&chi3.real); // real part of x3 ymm7 = _mm256_broadcast_ss(&chi3.imag); // imag part of x3 for(i = 0; i < n1; i++) { //load first two columns of A ymm8 = _mm256_loadu_ps(ap[0] + 0); ymm10 = _mm256_loadu_ps(ap[1] + 0); ymm12 = _mm256_mul_ps(ymm8, ymm0); ymm13 = _mm256_mul_ps(ymm8, ymm1); ymm12 = _mm256_fmadd_ps(ymm10, ymm2, ymm12); ymm13 = _mm256_fmadd_ps(ymm10, ymm3, ymm13); //load 3rd and 4th columns of A ymm8 = _mm256_loadu_ps(ap[2] + 0); ymm10 = _mm256_loadu_ps(ap[3] + 0); ymm12 = _mm256_fmadd_ps(ymm8, ymm4, ymm12); ymm13 = _mm256_fmadd_ps(ymm8, ymm5, ymm13); ymm12 = _mm256_fmadd_ps(ymm10, ymm6, ymm12); ymm13 = _mm256_fmadd_ps(ymm10, ymm7, ymm13); //load Y vector ymm10 = _mm256_loadu_ps(y0 + 0); if(bli_is_noconj(conja)) { //printf("Inside no conj if\n"); ymm13 = _mm256_permute_ps(ymm13, 0xB1); ymm8 = _mm256_addsub_ps(ymm12, ymm13); } else { ymm12 = _mm256_permute_ps(ymm12, 0xB1); ymm8 = _mm256_addsub_ps(ymm13, ymm12); ymm8 = _mm256_permute_ps(ymm8, 0xB1); } ymm12 = _mm256_add_ps(ymm8, ymm10); _mm256_storeu_ps((float*)(y0), ymm12); y0 += 8; ap[0] += 8; ap[1] += 8; ap[2] += 8; ap[3] += 8; } // If there are leftover iterations, perform them with scalar code. for ( i = 0; (i + 0) < n2 ; ++i ) { scomplex y0c = *(scomplex*)y0; const scomplex a0c = *(scomplex*)ap[0]; const scomplex a1c = *(scomplex*)ap[1]; const scomplex a2c = *(scomplex*)ap[2]; const scomplex a3c = *(scomplex*)ap[3]; y0c.real += chi0.real * a0c.real - chi0.imag * a0c.imag * setPlusOne; y0c.real += chi1.real * a1c.real - chi1.imag * a1c.imag * setPlusOne; y0c.real += chi2.real * a2c.real - chi2.imag * a2c.imag * setPlusOne; y0c.real += chi3.real * a3c.real - chi3.imag * a3c.imag * setPlusOne; y0c.imag += chi0.imag * a0c.real + chi0.real * a0c.imag * setPlusOne; y0c.imag += chi1.imag * a1c.real + chi1.real * a1c.imag * setPlusOne; y0c.imag += chi2.imag * a2c.real + chi2.real * a2c.imag * setPlusOne; y0c.imag += chi3.imag * a3c.real + chi3.real * a3c.imag * setPlusOne; *(scomplex*)y0 = y0c; ap[0] += 2; ap[1] += 2; ap[2] += 2; ap[3] += 2; y0 += 2; } //PASTEMAC(c,fprintm)(stdout, "Y after A*x in axpyf",m, 1, (scomplex*)y, 1, 1, "%4.1f", ""); } else { for (i = 0 ; (i + 0) < m ; ++i ) { scomplex y0c = *(scomplex*)y0; const scomplex a0c = *(scomplex*)ap[0]; const scomplex a1c = *(scomplex*)ap[1]; const scomplex a2c = *(scomplex*)ap[2]; const scomplex a3c = *(scomplex*)ap[3]; y0c.real += chi0.real * a0c.real - chi0.imag * a0c.imag * setPlusOne; y0c.real += chi1.real * a1c.real - chi1.imag * a1c.imag * setPlusOne; y0c.real += chi2.real * a2c.real - chi2.imag * a2c.imag * setPlusOne; y0c.real += chi3.real * a3c.real - chi3.imag * a3c.imag * setPlusOne; y0c.imag += chi0.imag * a0c.real + chi0.real * a0c.imag * setPlusOne; y0c.imag += chi1.imag * a1c.real + chi1.real * a1c.imag * setPlusOne; y0c.imag += chi2.imag * a2c.real + chi2.real * a2c.imag * setPlusOne; y0c.imag += chi3.imag * a3c.real + chi3.real * a3c.imag * setPlusOne; *(scomplex*)y0 = y0c; ap[0] += inca; ap[1] += inca; ap[2] += inca; ap[3] += inca; y0 += incy; } } } blis-0.9.0/kernels/zen/1f/bli_axpyf_zen_int_5.c000066400000000000000000001135051422157504600213240ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2020 - 2022, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "immintrin.h" #include "blis.h" /* Union data structure to access AVX registers One 256-bit AVX register holds 8 SP elements. */ typedef union { __m256 v; float f[8] __attribute__((aligned(64))); } v8sf_t; /* Union data structure to access AVX registers * One 256-bit AVX register holds 4 DP elements. */ typedef union { __m256d v; __m128d xmm[2]; double d[4] __attribute__((aligned(64))); } v4df_t; typedef union { __m128d v; double d[2] __attribute__((aligned(64))); } v2df_t; void bli_saxpyf_zen_int_5 ( conj_t conja, conj_t conjx, dim_t m, dim_t b_n, float* restrict alpha, float* restrict a, inc_t inca, inc_t lda, float* restrict x, inc_t incx, float* restrict y, inc_t incy, cntx_t* restrict cntx ) { const dim_t fuse_fac = 5; const dim_t n_elem_per_reg = 8; const dim_t n_iter_unroll = 2; dim_t i; float* restrict a0; float* restrict a1; float* restrict a2; float* restrict a3; float* restrict a4; float* restrict y0; v8sf_t chi0v, chi1v, chi2v, chi3v; v8sf_t chi4v; v8sf_t a00v, a01v, a02v, a03v; v8sf_t a04v; v8sf_t a10v, a11v, a12v, a13v; v8sf_t a14v; v8sf_t y0v, y1v; float chi0, chi1, chi2, chi3; float chi4; // If either dimension is zero, or if alpha is zero, return early. if ( bli_zero_dim2( m, b_n ) || bli_seq0( *alpha ) ) return; // If b_n is not equal to the fusing factor, then perform the entire // operation as a loop over axpyv. if ( b_n != fuse_fac ) { if(cntx == NULL) cntx = bli_gks_query_cntx(); saxpyv_ker_ft f = bli_cntx_get_l1v_ker_dt( BLIS_FLOAT, BLIS_AXPYV_KER, cntx ); for ( i = 0; i < b_n; ++i ) { float* a1 = a + (0 )*inca + (i )*lda; float* chi1 = x + (i )*incx; float* y1 = y + (0 )*incy; float alpha_chi1; bli_scopycjs( conjx, *chi1, alpha_chi1 ); bli_sscals( *alpha, alpha_chi1 ); f ( conja, m, &alpha_chi1, a1, inca, y1, incy, cntx ); } return; } // At this point, we know that b_n is exactly equal to the fusing factor. a0 = a + 0*lda; a1 = a + 1*lda; a2 = a + 2*lda; a3 = a + 3*lda; a4 = a + 4*lda; y0 = y; chi0 = *( x + 0*incx ); chi1 = *( x + 1*incx ); chi2 = *( x + 2*incx ); chi3 = *( x + 3*incx ); chi4 = *( x + 4*incx ); // Scale each chi scalar by alpha. bli_sscals( *alpha, chi0 ); bli_sscals( *alpha, chi1 ); bli_sscals( *alpha, chi2 ); bli_sscals( *alpha, chi3 ); bli_sscals( *alpha, chi4 ); // Broadcast the (alpha*chi?) scalars to all elements of vector registers. chi0v.v = _mm256_broadcast_ss( &chi0 ); chi1v.v = _mm256_broadcast_ss( &chi1 ); chi2v.v = _mm256_broadcast_ss( &chi2 ); chi3v.v = _mm256_broadcast_ss( &chi3 ); chi4v.v = _mm256_broadcast_ss( &chi4 ); // If there are vectorized iterations, perform them with vector // instructions. if ( inca == 1 && incy == 1 ) { for ( i = 0; (i + 15) < m; i += 16 ) { // Load the input values. y0v.v = _mm256_loadu_ps( y0 + 0*n_elem_per_reg ); y1v.v = _mm256_loadu_ps( y0 + 1*n_elem_per_reg ); a00v.v = _mm256_loadu_ps( a0 + 0*n_elem_per_reg ); a10v.v = _mm256_loadu_ps( a0 + 1*n_elem_per_reg ); a01v.v = _mm256_loadu_ps( a1 + 0*n_elem_per_reg ); a11v.v = _mm256_loadu_ps( a1 + 1*n_elem_per_reg ); a02v.v = _mm256_loadu_ps( a2 + 0*n_elem_per_reg ); a12v.v = _mm256_loadu_ps( a2 + 1*n_elem_per_reg ); a03v.v = _mm256_loadu_ps( a3 + 0*n_elem_per_reg ); a13v.v = _mm256_loadu_ps( a3 + 1*n_elem_per_reg ); a04v.v = _mm256_loadu_ps( a4 + 0*n_elem_per_reg ); a14v.v = _mm256_loadu_ps( a4 + 1*n_elem_per_reg ); // perform : y += alpha * x; y0v.v = _mm256_fmadd_ps( a00v.v, chi0v.v, y0v.v ); y1v.v = _mm256_fmadd_ps( a10v.v, chi0v.v, y1v.v ); y0v.v = _mm256_fmadd_ps( a01v.v, chi1v.v, y0v.v ); y1v.v = _mm256_fmadd_ps( a11v.v, chi1v.v, y1v.v ); y0v.v = _mm256_fmadd_ps( a02v.v, chi2v.v, y0v.v ); y1v.v = _mm256_fmadd_ps( a12v.v, chi2v.v, y1v.v ); y0v.v = _mm256_fmadd_ps( a03v.v, chi3v.v, y0v.v ); y1v.v = _mm256_fmadd_ps( a13v.v, chi3v.v, y1v.v ); y0v.v = _mm256_fmadd_ps( a04v.v, chi4v.v, y0v.v ); y1v.v = _mm256_fmadd_ps( a14v.v, chi4v.v, y1v.v ); // Store the output. _mm256_storeu_ps( (y0 + 0*n_elem_per_reg), y0v.v ); _mm256_storeu_ps( (y0 + 1*n_elem_per_reg), y1v.v ); y0 += n_iter_unroll * n_elem_per_reg; a0 += n_iter_unroll * n_elem_per_reg; a1 += n_iter_unroll * n_elem_per_reg; a2 += n_iter_unroll * n_elem_per_reg; a3 += n_iter_unroll * n_elem_per_reg; a4 += n_iter_unroll * n_elem_per_reg; } for( ; (i + 7) < m; i += 8 ) { // Load the input values. y0v.v = _mm256_loadu_ps( y0 + 0*n_elem_per_reg ); a00v.v = _mm256_loadu_ps( a0 + 0*n_elem_per_reg ); a01v.v = _mm256_loadu_ps( a1 + 0*n_elem_per_reg ); a02v.v = _mm256_loadu_ps( a2 + 0*n_elem_per_reg ); a03v.v = _mm256_loadu_ps( a3 + 0*n_elem_per_reg ); a04v.v = _mm256_loadu_ps( a4 + 0*n_elem_per_reg ); // perform : y += alpha * x; y0v.v = _mm256_fmadd_ps( a00v.v, chi0v.v, y0v.v ); y0v.v = _mm256_fmadd_ps( a01v.v, chi1v.v, y0v.v ); y0v.v = _mm256_fmadd_ps( a02v.v, chi2v.v, y0v.v ); y0v.v = _mm256_fmadd_ps( a03v.v, chi3v.v, y0v.v ); y0v.v = _mm256_fmadd_ps( a04v.v, chi4v.v, y0v.v ); // Store the output. _mm256_storeu_ps( (y0 + 0*n_elem_per_reg), y0v.v ); y0 += n_elem_per_reg; a0 += n_elem_per_reg; a1 += n_elem_per_reg; a2 += n_elem_per_reg; a3 += n_elem_per_reg; a4 += n_elem_per_reg; } // If there are leftover iterations, perform them with scalar code. for ( ; (i + 0) < m ; ++i ) { double y0c = *y0; const float a0c = *a0; const float a1c = *a1; const float a2c = *a2; const float a3c = *a3; const float a4c = *a4; y0c += chi0 * a0c; y0c += chi1 * a1c; y0c += chi2 * a2c; y0c += chi3 * a3c; y0c += chi4 * a4c; *y0 = y0c; a0 += 1; a1 += 1; a2 += 1; a3 += 1; a4 += 1; y0 += 1; } } else { for ( i = 0; (i + 0) < m ; ++i ) { double y0c = *y0; const float a0c = *a0; const float a1c = *a1; const float a2c = *a2; const float a3c = *a3; const float a4c = *a4; y0c += chi0 * a0c; y0c += chi1 * a1c; y0c += chi2 * a2c; y0c += chi3 * a3c; y0c += chi4 * a4c; *y0 = y0c; a0 += inca; a1 += inca; a2 += inca; a3 += inca; a4 += inca; y0 += incy; } } } // ----------------------------------------------------------------------------- void bli_daxpyf_zen_int_5 ( conj_t conja, conj_t conjx, dim_t m, dim_t b_n, double* restrict alpha, double* restrict a, inc_t inca, inc_t lda, double* restrict x, inc_t incx, double* restrict y, inc_t incy, cntx_t* restrict cntx ) { const dim_t fuse_fac = 5; const dim_t n_elem_per_reg = 4; const dim_t n_iter_unroll = 2; dim_t i; double* restrict a0; double* restrict a1; double* restrict a2; double* restrict a3; double* restrict a4; double* restrict y0; v4df_t chi0v, chi1v, chi2v, chi3v; v4df_t chi4v; v4df_t a00v, a01v, a02v, a03v; v4df_t a04v; v4df_t a10v, a11v, a12v, a13v; v4df_t a14v; v4df_t y0v, y1v; double chi0, chi1, chi2, chi3; double chi4; // If either dimension is zero, or if alpha is zero, return early. if ( bli_zero_dim2( m, b_n ) || bli_deq0( *alpha ) ) return; // If b_n is not equal to the fusing factor, then perform the entire // operation as a loop over axpyv. if ( b_n != fuse_fac ) { daxpyv_ker_ft f = bli_cntx_get_l1v_ker_dt( BLIS_DOUBLE, BLIS_AXPYV_KER, cntx ); for ( i = 0; i < b_n; ++i ) { double* a1 = a + (0 )*inca + (i )*lda; double* chi1 = x + (i )*incx; double* y1 = y + (0 )*incy; double alpha_chi1; bli_dcopycjs( conjx, *chi1, alpha_chi1 ); bli_dscals( *alpha, alpha_chi1 ); f ( conja, m, &alpha_chi1, a1, inca, y1, incy, cntx ); } return; } // At this point, we know that b_n is exactly equal to the fusing factor. a0 = a + 0*lda; a1 = a + 1*lda; a2 = a + 2*lda; a3 = a + 3*lda; a4 = a + 4*lda; y0 = y; chi0 = *( x + 0*incx ); chi1 = *( x + 1*incx ); chi2 = *( x + 2*incx ); chi3 = *( x + 3*incx ); chi4 = *( x + 4*incx ); // Scale each chi scalar by alpha. bli_dscals( *alpha, chi0 ); bli_dscals( *alpha, chi1 ); bli_dscals( *alpha, chi2 ); bli_dscals( *alpha, chi3 ); bli_dscals( *alpha, chi4 ); // Broadcast the (alpha*chi?) scalars to all elements of vector registers. chi0v.v = _mm256_broadcast_sd( &chi0 ); chi1v.v = _mm256_broadcast_sd( &chi1 ); chi2v.v = _mm256_broadcast_sd( &chi2 ); chi3v.v = _mm256_broadcast_sd( &chi3 ); chi4v.v = _mm256_broadcast_sd( &chi4 ); // If there are vectorized iterations, perform them with vector // instructions. if ( inca == 1 && incy == 1 ) { for ( i = 0; (i + 7) < m; i += 8 ) { // Load the input values. y0v.v = _mm256_loadu_pd( y0 + 0*n_elem_per_reg ); y1v.v = _mm256_loadu_pd( y0 + 1*n_elem_per_reg ); a00v.v = _mm256_loadu_pd( a0 + 0*n_elem_per_reg ); a10v.v = _mm256_loadu_pd( a0 + 1*n_elem_per_reg ); a01v.v = _mm256_loadu_pd( a1 + 0*n_elem_per_reg ); a11v.v = _mm256_loadu_pd( a1 + 1*n_elem_per_reg ); a02v.v = _mm256_loadu_pd( a2 + 0*n_elem_per_reg ); a12v.v = _mm256_loadu_pd( a2 + 1*n_elem_per_reg ); a03v.v = _mm256_loadu_pd( a3 + 0*n_elem_per_reg ); a13v.v = _mm256_loadu_pd( a3 + 1*n_elem_per_reg ); a04v.v = _mm256_loadu_pd( a4 + 0*n_elem_per_reg ); a14v.v = _mm256_loadu_pd( a4 + 1*n_elem_per_reg ); // perform : y += alpha * x; y0v.v = _mm256_fmadd_pd( a00v.v, chi0v.v, y0v.v ); y1v.v = _mm256_fmadd_pd( a10v.v, chi0v.v, y1v.v ); y0v.v = _mm256_fmadd_pd( a01v.v, chi1v.v, y0v.v ); y1v.v = _mm256_fmadd_pd( a11v.v, chi1v.v, y1v.v ); y0v.v = _mm256_fmadd_pd( a02v.v, chi2v.v, y0v.v ); y1v.v = _mm256_fmadd_pd( a12v.v, chi2v.v, y1v.v ); y0v.v = _mm256_fmadd_pd( a03v.v, chi3v.v, y0v.v ); y1v.v = _mm256_fmadd_pd( a13v.v, chi3v.v, y1v.v ); y0v.v = _mm256_fmadd_pd( a04v.v, chi4v.v, y0v.v ); y1v.v = _mm256_fmadd_pd( a14v.v, chi4v.v, y1v.v ); // Store the output. _mm256_storeu_pd( (double *)(y0 + 0*n_elem_per_reg), y0v.v ); _mm256_storeu_pd( (double *)(y0 + 1*n_elem_per_reg), y1v.v ); y0 += n_iter_unroll * n_elem_per_reg; a0 += n_iter_unroll * n_elem_per_reg; a1 += n_iter_unroll * n_elem_per_reg; a2 += n_iter_unroll * n_elem_per_reg; a3 += n_iter_unroll * n_elem_per_reg; a4 += n_iter_unroll * n_elem_per_reg; } for( ; (i + 3) < m; i += 4 ) { // Load the input values. y0v.v = _mm256_loadu_pd( y0 + 0*n_elem_per_reg ); a00v.v = _mm256_loadu_pd( a0 + 0*n_elem_per_reg ); a01v.v = _mm256_loadu_pd( a1 + 0*n_elem_per_reg ); a02v.v = _mm256_loadu_pd( a2 + 0*n_elem_per_reg ); a03v.v = _mm256_loadu_pd( a3 + 0*n_elem_per_reg ); a04v.v = _mm256_loadu_pd( a4 + 0*n_elem_per_reg ); // perform : y += alpha * x; y0v.v = _mm256_fmadd_pd( a00v.v, chi0v.v, y0v.v ); y0v.v = _mm256_fmadd_pd( a01v.v, chi1v.v, y0v.v ); y0v.v = _mm256_fmadd_pd( a02v.v, chi2v.v, y0v.v ); y0v.v = _mm256_fmadd_pd( a03v.v, chi3v.v, y0v.v ); y0v.v = _mm256_fmadd_pd( a04v.v, chi4v.v, y0v.v ); // Store the output. _mm256_storeu_pd( (y0 + 0*n_elem_per_reg), y0v.v ); y0 += n_elem_per_reg; a0 += n_elem_per_reg; a1 += n_elem_per_reg; a2 += n_elem_per_reg; a3 += n_elem_per_reg; a4 += n_elem_per_reg; } // If there are leftover iterations, perform them with scalar code. for ( ; (i + 0) < m ; ++i ) { double y0c = *y0; const double a0c = *a0; const double a1c = *a1; const double a2c = *a2; const double a3c = *a3; const double a4c = *a4; y0c += chi0 * a0c; y0c += chi1 * a1c; y0c += chi2 * a2c; y0c += chi3 * a3c; y0c += chi4 * a4c; *y0 = y0c; a0 += 1; a1 += 1; a2 += 1; a3 += 1; a4 += 1; y0 += 1; } } else { for ( i = 0; (i + 0) < m ; ++i ) { double y0c = *y0; const double a0c = *a0; const double a1c = *a1; const double a2c = *a2; const double a3c = *a3; const double a4c = *a4; y0c += chi0 * a0c; y0c += chi1 * a1c; y0c += chi2 * a2c; y0c += chi3 * a3c; y0c += chi4 * a4c; *y0 = y0c; a0 += inca; a1 += inca; a2 += inca; a3 += inca; a4 += inca; y0 += incy; } } } // ----------------------------------------------------------------------------- static void bli_daxpyf_zen_int_16x2 ( conj_t conja, conj_t conjx, dim_t m, dim_t b_n, double* restrict alpha, double* restrict a, inc_t inca, inc_t lda, double* restrict x, inc_t incx, double* restrict y, inc_t incy, cntx_t* restrict cntx ) { const dim_t fuse_fac = 2; const dim_t n_elem_per_reg = 4; const dim_t n_iter_unroll = 4; dim_t i; double* restrict a0; double* restrict a1; double* restrict y0; v4df_t chi0v, chi1v; v4df_t a00v, a01v; v4df_t a10v, a11v; v4df_t a20v, a21v; v4df_t a30v, a31v; v4df_t y0v, y1v, y2v, y3v; double chi0, chi1; v2df_t a40v, a41v; v2df_t y4v; // If either dimension is zero, or if alpha is zero, return early. if ( bli_zero_dim2( m, b_n ) || bli_deq0( *alpha ) ) return; // If b_n is not equal to the fusing factor, then perform the entire // operation as a loop over axpyv. if ( b_n != fuse_fac ) { daxpyv_ker_ft f = bli_cntx_get_l1v_ker_dt( BLIS_DOUBLE, BLIS_AXPYV_KER, cntx ); for ( i = 0; i < b_n; ++i ) { double* a1 = a + (0 )*inca + (i )*lda; double* chi1 = x + (i )*incx; double* y1 = y + (0 )*incy; double alpha_chi1; bli_dcopycjs( conjx, *chi1, alpha_chi1 ); bli_dscals( *alpha, alpha_chi1 ); f ( conja, m, &alpha_chi1, a1, inca, y1, incy, cntx ); } return; } // At this point, we know that b_n is exactly equal to the fusing factor. a0 = a + 0*lda; a1 = a + 1*lda; y0 = y; chi0 = *( x + 0*incx ); chi1 = *( x + 1*incx ); // Scale each chi scalar by alpha. bli_dscals( *alpha, chi0 ); bli_dscals( *alpha, chi1 ); // Broadcast the (alpha*chi?) scalars to all elements of vector registers. chi0v.v = _mm256_broadcast_sd( &chi0 ); chi1v.v = _mm256_broadcast_sd( &chi1 ); // If there are vectorized iterations, perform them with vector // instructions. if ( inca == 1 && incy == 1 ) { for ( i = 0; (i + 15) < m; i += 16 ) { // Load the input values. y0v.v = _mm256_loadu_pd( y0 + 0*n_elem_per_reg ); y1v.v = _mm256_loadu_pd( y0 + 1*n_elem_per_reg ); y2v.v = _mm256_loadu_pd( y0 + 2*n_elem_per_reg ); y3v.v = _mm256_loadu_pd( y0 + 3*n_elem_per_reg ); a00v.v = _mm256_loadu_pd( a0 + 0*n_elem_per_reg ); a10v.v = _mm256_loadu_pd( a0 + 1*n_elem_per_reg ); a20v.v = _mm256_loadu_pd( a0 + 2*n_elem_per_reg ); a30v.v = _mm256_loadu_pd( a0 + 3*n_elem_per_reg ); a01v.v = _mm256_loadu_pd( a1 + 0*n_elem_per_reg ); a11v.v = _mm256_loadu_pd( a1 + 1*n_elem_per_reg ); a21v.v = _mm256_loadu_pd( a1 + 2*n_elem_per_reg ); a31v.v = _mm256_loadu_pd( a1 + 3*n_elem_per_reg ); // perform : y += alpha * x; y0v.v = _mm256_fmadd_pd( a00v.v, chi0v.v, y0v.v ); y1v.v = _mm256_fmadd_pd( a10v.v, chi0v.v, y1v.v ); y2v.v = _mm256_fmadd_pd( a20v.v, chi0v.v, y2v.v ); y3v.v = _mm256_fmadd_pd( a30v.v, chi0v.v, y3v.v ); y0v.v = _mm256_fmadd_pd( a01v.v, chi1v.v, y0v.v ); y1v.v = _mm256_fmadd_pd( a11v.v, chi1v.v, y1v.v ); y2v.v = _mm256_fmadd_pd( a21v.v, chi1v.v, y2v.v ); y3v.v = _mm256_fmadd_pd( a31v.v, chi1v.v, y3v.v ); // Store the output. _mm256_storeu_pd( (double *)(y0 + 0*n_elem_per_reg), y0v.v ); _mm256_storeu_pd( (double *)(y0 + 1*n_elem_per_reg), y1v.v ); _mm256_storeu_pd( (double *)(y0 + 2*n_elem_per_reg), y2v.v ); _mm256_storeu_pd( (double *)(y0 + 3*n_elem_per_reg), y3v.v ); y0 += n_iter_unroll * n_elem_per_reg; a0 += n_iter_unroll * n_elem_per_reg; a1 += n_iter_unroll * n_elem_per_reg; } for ( ; (i + 11) < m; i += 12 ) { // Load the input values. y0v.v = _mm256_loadu_pd( y0 + 0*n_elem_per_reg ); y1v.v = _mm256_loadu_pd( y0 + 1*n_elem_per_reg ); y2v.v = _mm256_loadu_pd( y0 + 2*n_elem_per_reg ); a00v.v = _mm256_loadu_pd( a0 + 0*n_elem_per_reg ); a10v.v = _mm256_loadu_pd( a0 + 1*n_elem_per_reg ); a20v.v = _mm256_loadu_pd( a0 + 2*n_elem_per_reg ); a01v.v = _mm256_loadu_pd( a1 + 0*n_elem_per_reg ); a11v.v = _mm256_loadu_pd( a1 + 1*n_elem_per_reg ); a21v.v = _mm256_loadu_pd( a1 + 2*n_elem_per_reg ); // perform : y += alpha * x; y0v.v = _mm256_fmadd_pd( a00v.v, chi0v.v, y0v.v ); y1v.v = _mm256_fmadd_pd( a10v.v, chi0v.v, y1v.v ); y2v.v = _mm256_fmadd_pd( a20v.v, chi0v.v, y2v.v ); y0v.v = _mm256_fmadd_pd( a01v.v, chi1v.v, y0v.v ); y1v.v = _mm256_fmadd_pd( a11v.v, chi1v.v, y1v.v ); y2v.v = _mm256_fmadd_pd( a21v.v, chi1v.v, y2v.v ); // Store the output. _mm256_storeu_pd( (double *)(y0 + 0*n_elem_per_reg), y0v.v ); _mm256_storeu_pd( (double *)(y0 + 1*n_elem_per_reg), y1v.v ); _mm256_storeu_pd( (double *)(y0 + 2*n_elem_per_reg), y2v.v ); y0 += 3 * n_elem_per_reg; a0 += 3 * n_elem_per_reg; a1 += 3 * n_elem_per_reg; } for ( ; (i + 7) < m; i += 8 ) { // Load the input values. y0v.v = _mm256_loadu_pd( y0 + 0*n_elem_per_reg ); y1v.v = _mm256_loadu_pd( y0 + 1*n_elem_per_reg ); a00v.v = _mm256_loadu_pd( a0 + 0*n_elem_per_reg ); a10v.v = _mm256_loadu_pd( a0 + 1*n_elem_per_reg ); a01v.v = _mm256_loadu_pd( a1 + 0*n_elem_per_reg ); a11v.v = _mm256_loadu_pd( a1 + 1*n_elem_per_reg ); // perform : y += alpha * x; y0v.v = _mm256_fmadd_pd( a00v.v, chi0v.v, y0v.v ); y1v.v = _mm256_fmadd_pd( a10v.v, chi0v.v, y1v.v ); y0v.v = _mm256_fmadd_pd( a01v.v, chi1v.v, y0v.v ); y1v.v = _mm256_fmadd_pd( a11v.v, chi1v.v, y1v.v ); // Store the output. _mm256_storeu_pd( (double *)(y0 + 0*n_elem_per_reg), y0v.v ); _mm256_storeu_pd( (double *)(y0 + 1*n_elem_per_reg), y1v.v ); y0 += 2 * n_elem_per_reg; a0 += 2 * n_elem_per_reg; a1 += 2 * n_elem_per_reg; } for ( ; (i + 3) < m; i += 4 ) { // Load the input values. y0v.v = _mm256_loadu_pd( y0 + 0*n_elem_per_reg ); a00v.v = _mm256_loadu_pd( a0 + 0*n_elem_per_reg ); a01v.v = _mm256_loadu_pd( a1 + 0*n_elem_per_reg ); // perform : y += alpha * x; y0v.v = _mm256_fmadd_pd( a00v.v, chi0v.v, y0v.v ); y0v.v = _mm256_fmadd_pd( a01v.v, chi1v.v, y0v.v ); // Store the output. _mm256_storeu_pd( (double *)(y0 + 0*n_elem_per_reg), y0v.v ); y0 += n_elem_per_reg; a0 += n_elem_per_reg; a1 += n_elem_per_reg; } for ( ; (i + 1) < m; i += 2 ) { // Load the input values. y4v.v = _mm_loadu_pd( y0 + 0*n_elem_per_reg ); a40v.v = _mm_loadu_pd( a0 + 0*n_elem_per_reg ); a41v.v = _mm_loadu_pd( a1 + 0*n_elem_per_reg ); // perform : y += alpha * x; y4v.v = _mm_fmadd_pd( a40v.v, chi0v.xmm[0], y4v.v ); y4v.v = _mm_fmadd_pd( a41v.v, chi1v.xmm[0], y4v.v ); // Store the output. _mm_storeu_pd( (double *)(y0 + 0*n_elem_per_reg), y4v.v ); y0 += 2; a0 += 2; a1 += 2; } // If there are leftover iterations, perform them with scalar code. for ( ; (i + 0) < m ; ++i ) { double y0c = *y0; const double a0c = *a0; const double a1c = *a1; y0c += chi0 * a0c; y0c += chi1 * a1c; *y0 = y0c; a0 += 1; a1 += 1; y0 += 1; } } else { for ( i = 0; (i + 0) < m ; ++i ) { double y0c = *y0; const double a0c = *a0; const double a1c = *a1; y0c += chi0 * a0c; y0c += chi1 * a1c; *y0 = y0c; a0 += inca; a1 += inca; y0 += incy; } } } // ----------------------------------------------------------------------------- void bli_daxpyf_zen_int_16x4 ( conj_t conja, conj_t conjx, dim_t m, dim_t b_n, double* restrict alpha, double* restrict a, inc_t inca, inc_t lda, double* restrict x, inc_t incx, double* restrict y, inc_t incy, cntx_t* restrict cntx ) { const dim_t fuse_fac = 4; const dim_t n_elem_per_reg = 4; const dim_t n_iter_unroll = 4; dim_t i; double* restrict a0; double* restrict a1; double* restrict a2; double* restrict a3; double* restrict y0; v4df_t chi0v, chi1v, chi2v, chi3v; v4df_t a00v, a01v, a02v, a03v; v4df_t a10v, a11v, a12v, a13v; v4df_t a20v, a21v, a22v, a23v; v4df_t a30v, a31v, a32v, a33v; v4df_t y0v, y1v, y2v, y3v; double chi0, chi1, chi2, chi3; v2df_t y4v; v2df_t a40v, a41v, a42v, a43v; // If either dimension is zero, or if alpha is zero, return early. if ( bli_zero_dim2( m, b_n ) || bli_deq0( *alpha ) ) return; // If b_n is not equal to the fusing factor, then perform the entire // operation as a loop over axpyv. if ( b_n != fuse_fac ) { if(cntx == NULL) cntx = bli_gks_query_cntx(); daxpyv_ker_ft f = bli_cntx_get_l1v_ker_dt( BLIS_DOUBLE, BLIS_AXPYV_KER, cntx ); for ( i = 0; i < b_n; ++i ) { double* a1 = a + (0 )*inca + (i )*lda; double* chi1 = x + (i )*incx; double* y1 = y + (0 )*incy; double alpha_chi1; bli_dcopycjs( conjx, *chi1, alpha_chi1 ); bli_dscals( *alpha, alpha_chi1 ); f ( conja, m, &alpha_chi1, a1, inca, y1, incy, cntx ); } return; } // At this point, we know that b_n is exactly equal to the fusing factor. a0 = a + 0*lda; a1 = a + 1*lda; a2 = a + 2*lda; a3 = a + 3*lda; y0 = y; chi0 = *( x + 0*incx ); chi1 = *( x + 1*incx ); chi2 = *( x + 2*incx ); chi3 = *( x + 3*incx ); // Scale each chi scalar by alpha. bli_dscals( *alpha, chi0 ); bli_dscals( *alpha, chi1 ); bli_dscals( *alpha, chi2 ); bli_dscals( *alpha, chi3 ); // Broadcast the (alpha*chi?) scalars to all elements of vector registers. chi0v.v = _mm256_broadcast_sd( &chi0 ); chi1v.v = _mm256_broadcast_sd( &chi1 ); chi2v.v = _mm256_broadcast_sd( &chi2 ); chi3v.v = _mm256_broadcast_sd( &chi3 ); // If there are vectorized iterations, perform them with vector // instructions. if ( inca == 1 && incy == 1 ) { for ( i = 0; (i + 15) < m; i += 16 ) { // Load the input values. y0v.v = _mm256_loadu_pd( y0 + 0*n_elem_per_reg ); y1v.v = _mm256_loadu_pd( y0 + 1*n_elem_per_reg ); y2v.v = _mm256_loadu_pd( y0 + 2*n_elem_per_reg ); y3v.v = _mm256_loadu_pd( y0 + 3*n_elem_per_reg ); a00v.v = _mm256_loadu_pd( a0 + 0*n_elem_per_reg ); a10v.v = _mm256_loadu_pd( a0 + 1*n_elem_per_reg ); a20v.v = _mm256_loadu_pd( a0 + 2*n_elem_per_reg ); a30v.v = _mm256_loadu_pd( a0 + 3*n_elem_per_reg ); a01v.v = _mm256_loadu_pd( a1 + 0*n_elem_per_reg ); a11v.v = _mm256_loadu_pd( a1 + 1*n_elem_per_reg ); a21v.v = _mm256_loadu_pd( a1 + 2*n_elem_per_reg ); a31v.v = _mm256_loadu_pd( a1 + 3*n_elem_per_reg ); a02v.v = _mm256_loadu_pd( a2 + 0*n_elem_per_reg ); a12v.v = _mm256_loadu_pd( a2 + 1*n_elem_per_reg ); a22v.v = _mm256_loadu_pd( a2 + 2*n_elem_per_reg ); a32v.v = _mm256_loadu_pd( a2 + 3*n_elem_per_reg ); a03v.v = _mm256_loadu_pd( a3 + 0*n_elem_per_reg ); a13v.v = _mm256_loadu_pd( a3 + 1*n_elem_per_reg ); a23v.v = _mm256_loadu_pd( a3 + 2*n_elem_per_reg ); a33v.v = _mm256_loadu_pd( a3 + 3*n_elem_per_reg ); // perform : y += alpha * x; y0v.v = _mm256_fmadd_pd( a00v.v, chi0v.v, y0v.v ); y1v.v = _mm256_fmadd_pd( a10v.v, chi0v.v, y1v.v ); y2v.v = _mm256_fmadd_pd( a20v.v, chi0v.v, y2v.v ); y3v.v = _mm256_fmadd_pd( a30v.v, chi0v.v, y3v.v ); y0v.v = _mm256_fmadd_pd( a01v.v, chi1v.v, y0v.v ); y1v.v = _mm256_fmadd_pd( a11v.v, chi1v.v, y1v.v ); y2v.v = _mm256_fmadd_pd( a21v.v, chi1v.v, y2v.v ); y3v.v = _mm256_fmadd_pd( a31v.v, chi1v.v, y3v.v ); y0v.v = _mm256_fmadd_pd( a02v.v, chi2v.v, y0v.v ); y1v.v = _mm256_fmadd_pd( a12v.v, chi2v.v, y1v.v ); y2v.v = _mm256_fmadd_pd( a22v.v, chi2v.v, y2v.v ); y3v.v = _mm256_fmadd_pd( a32v.v, chi2v.v, y3v.v ); y0v.v = _mm256_fmadd_pd( a03v.v, chi3v.v, y0v.v ); y1v.v = _mm256_fmadd_pd( a13v.v, chi3v.v, y1v.v ); y2v.v = _mm256_fmadd_pd( a23v.v, chi3v.v, y2v.v ); y3v.v = _mm256_fmadd_pd( a33v.v, chi3v.v, y3v.v ); // Store the output. _mm256_storeu_pd( (double *)(y0 + 0*n_elem_per_reg), y0v.v ); _mm256_storeu_pd( (double *)(y0 + 1*n_elem_per_reg), y1v.v ); _mm256_storeu_pd( (double *)(y0 + 2*n_elem_per_reg), y2v.v ); _mm256_storeu_pd( (double *)(y0 + 3*n_elem_per_reg), y3v.v ); y0 += n_iter_unroll * n_elem_per_reg; a0 += n_iter_unroll * n_elem_per_reg; a1 += n_iter_unroll * n_elem_per_reg; a2 += n_iter_unroll * n_elem_per_reg; a3 += n_iter_unroll * n_elem_per_reg; } for ( ; (i + 11) < m; i += 12 ) { // Load the input values. y0v.v = _mm256_loadu_pd( y0 + 0*n_elem_per_reg ); y1v.v = _mm256_loadu_pd( y0 + 1*n_elem_per_reg ); y2v.v = _mm256_loadu_pd( y0 + 2*n_elem_per_reg ); a00v.v = _mm256_loadu_pd( a0 + 0*n_elem_per_reg ); a10v.v = _mm256_loadu_pd( a0 + 1*n_elem_per_reg ); a20v.v = _mm256_loadu_pd( a0 + 2*n_elem_per_reg ); a01v.v = _mm256_loadu_pd( a1 + 0*n_elem_per_reg ); a11v.v = _mm256_loadu_pd( a1 + 1*n_elem_per_reg ); a21v.v = _mm256_loadu_pd( a1 + 2*n_elem_per_reg ); a02v.v = _mm256_loadu_pd( a2 + 0*n_elem_per_reg ); a12v.v = _mm256_loadu_pd( a2 + 1*n_elem_per_reg ); a22v.v = _mm256_loadu_pd( a2 + 2*n_elem_per_reg ); a03v.v = _mm256_loadu_pd( a3 + 0*n_elem_per_reg ); a13v.v = _mm256_loadu_pd( a3 + 1*n_elem_per_reg ); a23v.v = _mm256_loadu_pd( a3 + 2*n_elem_per_reg ); // perform : y += alpha * x; y0v.v = _mm256_fmadd_pd( a00v.v, chi0v.v, y0v.v ); y1v.v = _mm256_fmadd_pd( a10v.v, chi0v.v, y1v.v ); y2v.v = _mm256_fmadd_pd( a20v.v, chi0v.v, y2v.v ); y0v.v = _mm256_fmadd_pd( a01v.v, chi1v.v, y0v.v ); y1v.v = _mm256_fmadd_pd( a11v.v, chi1v.v, y1v.v ); y2v.v = _mm256_fmadd_pd( a21v.v, chi1v.v, y2v.v ); y0v.v = _mm256_fmadd_pd( a02v.v, chi2v.v, y0v.v ); y1v.v = _mm256_fmadd_pd( a12v.v, chi2v.v, y1v.v ); y2v.v = _mm256_fmadd_pd( a22v.v, chi2v.v, y2v.v ); y0v.v = _mm256_fmadd_pd( a03v.v, chi3v.v, y0v.v ); y1v.v = _mm256_fmadd_pd( a13v.v, chi3v.v, y1v.v ); y2v.v = _mm256_fmadd_pd( a23v.v, chi3v.v, y2v.v ); // Store the output. _mm256_storeu_pd( (double *)(y0 + 0*n_elem_per_reg), y0v.v ); _mm256_storeu_pd( (double *)(y0 + 1*n_elem_per_reg), y1v.v ); _mm256_storeu_pd( (double *)(y0 + 2*n_elem_per_reg), y2v.v ); y0 += 3 * n_elem_per_reg; a0 += 3 * n_elem_per_reg; a1 += 3 * n_elem_per_reg; a2 += 3 * n_elem_per_reg; a3 += 3 * n_elem_per_reg; } for ( ; (i + 7) < m; i += 8 ) { // Load the input values. y0v.v = _mm256_loadu_pd( y0 + 0*n_elem_per_reg ); y1v.v = _mm256_loadu_pd( y0 + 1*n_elem_per_reg ); a00v.v = _mm256_loadu_pd( a0 + 0*n_elem_per_reg ); a10v.v = _mm256_loadu_pd( a0 + 1*n_elem_per_reg ); a01v.v = _mm256_loadu_pd( a1 + 0*n_elem_per_reg ); a11v.v = _mm256_loadu_pd( a1 + 1*n_elem_per_reg ); a02v.v = _mm256_loadu_pd( a2 + 0*n_elem_per_reg ); a12v.v = _mm256_loadu_pd( a2 + 1*n_elem_per_reg ); a03v.v = _mm256_loadu_pd( a3 + 0*n_elem_per_reg ); a13v.v = _mm256_loadu_pd( a3 + 1*n_elem_per_reg ); // perform : y += alpha * x; y0v.v = _mm256_fmadd_pd( a00v.v, chi0v.v, y0v.v ); y1v.v = _mm256_fmadd_pd( a10v.v, chi0v.v, y1v.v ); y0v.v = _mm256_fmadd_pd( a01v.v, chi1v.v, y0v.v ); y1v.v = _mm256_fmadd_pd( a11v.v, chi1v.v, y1v.v ); y0v.v = _mm256_fmadd_pd( a02v.v, chi2v.v, y0v.v ); y1v.v = _mm256_fmadd_pd( a12v.v, chi2v.v, y1v.v ); y0v.v = _mm256_fmadd_pd( a03v.v, chi3v.v, y0v.v ); y1v.v = _mm256_fmadd_pd( a13v.v, chi3v.v, y1v.v ); // Store the output. _mm256_storeu_pd( (double *)(y0 + 0*n_elem_per_reg), y0v.v ); _mm256_storeu_pd( (double *)(y0 + 1*n_elem_per_reg), y1v.v ); y0 += 2 * n_elem_per_reg; a0 += 2 * n_elem_per_reg; a1 += 2 * n_elem_per_reg; a2 += 2 * n_elem_per_reg; a3 += 2 * n_elem_per_reg; } for ( ; (i + 3) < m; i += 4) { // Load the input values. y0v.v = _mm256_loadu_pd( y0 + 0*n_elem_per_reg ); a00v.v = _mm256_loadu_pd( a0 + 0*n_elem_per_reg ); a01v.v = _mm256_loadu_pd( a1 + 0*n_elem_per_reg ); a02v.v = _mm256_loadu_pd( a2 + 0*n_elem_per_reg ); a03v.v = _mm256_loadu_pd( a3 + 0*n_elem_per_reg ); // perform : y += alpha * x; y0v.v = _mm256_fmadd_pd( a00v.v, chi0v.v, y0v.v ); y0v.v = _mm256_fmadd_pd( a01v.v, chi1v.v, y0v.v ); y0v.v = _mm256_fmadd_pd( a02v.v, chi2v.v, y0v.v ); y0v.v = _mm256_fmadd_pd( a03v.v, chi3v.v, y0v.v ); // Store the output. _mm256_storeu_pd( (double *)(y0 + 0*n_elem_per_reg), y0v.v ); y0 += n_elem_per_reg; a0 += n_elem_per_reg; a1 += n_elem_per_reg; a2 += n_elem_per_reg; a3 += n_elem_per_reg; } #if 1 for ( ; (i + 1) < m; i += 2) { // Load the input values. y4v.v = _mm_loadu_pd( y0 + 0*n_elem_per_reg ); a40v.v = _mm_loadu_pd( a0 + 0*n_elem_per_reg ); a41v.v = _mm_loadu_pd( a1 + 0*n_elem_per_reg ); a42v.v = _mm_loadu_pd( a2 + 0*n_elem_per_reg ); a43v.v = _mm_loadu_pd( a3 + 0*n_elem_per_reg ); // perform : y += alpha * x; y4v.v = _mm_fmadd_pd( a40v.v, chi0v.xmm[0], y4v.v ); y4v.v = _mm_fmadd_pd( a41v.v, chi1v.xmm[0], y4v.v ); y4v.v = _mm_fmadd_pd( a42v.v, chi2v.xmm[0], y4v.v ); y4v.v = _mm_fmadd_pd( a43v.v, chi3v.xmm[0], y4v.v ); // Store the output. _mm_storeu_pd( (double *)(y0 + 0*n_elem_per_reg), y4v.v ); y0 += 2; a0 += 2; a1 += 2; a2 += 2; a3 += 2; } #endif // If there are leftover iterations, perform them with scalar code. for ( ; (i + 0) < m ; ++i ) { double y0c = *y0; const double a0c = *a0; const double a1c = *a1; const double a2c = *a2; const double a3c = *a3; y0c += chi0 * a0c; y0c += chi1 * a1c; y0c += chi2 * a2c; y0c += chi3 * a3c; *y0 = y0c; a0 += 1; a1 += 1; a2 += 1; a3 += 1; y0 += 1; } } else { for ( i = 0; (i + 0) < m ; ++i ) { double y0c = *y0; const double a0c = *a0; const double a1c = *a1; const double a2c = *a2; const double a3c = *a3; y0c += chi0 * a0c; y0c += chi1 * a1c; y0c += chi2 * a2c; y0c += chi3 * a3c; *y0 = y0c; a0 += inca; a1 += inca; a2 += inca; a3 += inca; y0 += incy; } } } blis-0.9.0/kernels/zen/1f/bli_axpyf_zen_int_8.c000066400000000000000000000315221422157504600213250ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2018, The University of Texas at Austin Copyright (C) 2016 - 2018, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "immintrin.h" #include "blis.h" /* Union data structure to access AVX registers One 256-bit AVX register holds 8 SP elements. */ typedef union { __m256 v; float f[8] __attribute__((aligned(64))); } v8sf_t; /* Union data structure to access AVX registers * One 256-bit AVX register holds 4 DP elements. */ typedef union { __m256d v; double d[4] __attribute__((aligned(64))); } v4df_t; // ----------------------------------------------------------------------------- void bli_saxpyf_zen_int_8 ( conj_t conja, conj_t conjx, dim_t m, dim_t b_n, float* restrict alpha, float* restrict a, inc_t inca, inc_t lda, float* restrict x, inc_t incx, float* restrict y, inc_t incy, cntx_t* restrict cntx ) { const dim_t fuse_fac = 8; const dim_t n_elem_per_reg = 8; const dim_t n_iter_unroll = 1; dim_t i; dim_t m_viter; dim_t m_left; float* restrict a0; float* restrict a1; float* restrict a2; float* restrict a3; float* restrict a4; float* restrict a5; float* restrict a6; float* restrict a7; float* restrict y0; v8sf_t chi0v, chi1v, chi2v, chi3v; v8sf_t chi4v, chi5v, chi6v, chi7v; v8sf_t a0v, a1v, a2v, a3v; v8sf_t a4v, a5v, a6v, a7v; v8sf_t y0v; float chi0, chi1, chi2, chi3; float chi4, chi5, chi6, chi7; // If either dimension is zero, or if alpha is zero, return early. if ( bli_zero_dim2( m, b_n ) || PASTEMAC(s,eq0)( *alpha ) ) return; // If b_n is not equal to the fusing factor, then perform the entire // operation as a loop over axpyv. if ( b_n != fuse_fac ) { saxpyv_ker_ft f = bli_cntx_get_l1v_ker_dt( BLIS_FLOAT, BLIS_AXPYV_KER, cntx ); for ( i = 0; i < b_n; ++i ) { float* a1 = a + (0 )*inca + (i )*lda; float* chi1 = x + (i )*incx; float* y1 = y + (0 )*incy; float alpha_chi1; PASTEMAC(s,copycjs)( conjx, *chi1, alpha_chi1 ); PASTEMAC(s,scals)( *alpha, alpha_chi1 ); f ( conja, m, &alpha_chi1, a1, inca, y1, incy, cntx ); } return; } // At this point, we know that b_n is exactly equal to the fusing factor. // Use the unrolling factor and the number of elements per register // to compute the number of vectorized and leftover iterations. m_viter = ( m ) / ( n_elem_per_reg * n_iter_unroll ); m_left = ( m ) % ( n_elem_per_reg * n_iter_unroll ); // If there is anything that would interfere with our use of contiguous // vector loads/stores, override m_viter and m_left to use scalar code // for all iterations. if ( inca != 1 || incy != 1 ) { m_viter = 0; m_left = m; } a0 = a + 0*lda; a1 = a + 1*lda; a2 = a + 2*lda; a3 = a + 3*lda; a4 = a + 4*lda; a5 = a + 5*lda; a6 = a + 6*lda; a7 = a + 7*lda; y0 = y; chi0 = *( x + 0*incx ); chi1 = *( x + 1*incx ); chi2 = *( x + 2*incx ); chi3 = *( x + 3*incx ); chi4 = *( x + 4*incx ); chi5 = *( x + 5*incx ); chi6 = *( x + 6*incx ); chi7 = *( x + 7*incx ); // Scale each chi scalar by alpha. PASTEMAC(s,scals)( *alpha, chi0 ); PASTEMAC(s,scals)( *alpha, chi1 ); PASTEMAC(s,scals)( *alpha, chi2 ); PASTEMAC(s,scals)( *alpha, chi3 ); PASTEMAC(s,scals)( *alpha, chi4 ); PASTEMAC(s,scals)( *alpha, chi5 ); PASTEMAC(s,scals)( *alpha, chi6 ); PASTEMAC(s,scals)( *alpha, chi7 ); // Broadcast the (alpha*chi?) scalars to all elements of vector registers. chi0v.v = _mm256_broadcast_ss( &chi0 ); chi1v.v = _mm256_broadcast_ss( &chi1 ); chi2v.v = _mm256_broadcast_ss( &chi2 ); chi3v.v = _mm256_broadcast_ss( &chi3 ); chi4v.v = _mm256_broadcast_ss( &chi4 ); chi5v.v = _mm256_broadcast_ss( &chi5 ); chi6v.v = _mm256_broadcast_ss( &chi6 ); chi7v.v = _mm256_broadcast_ss( &chi7 ); // If there are vectorized iterations, perform them with vector // instructions. for ( i = 0; i < m_viter; ++i ) { // Load the input values. y0v.v = _mm256_loadu_ps( y0 + 0*n_elem_per_reg ); a0v.v = _mm256_loadu_ps( a0 + 0*n_elem_per_reg ); a1v.v = _mm256_loadu_ps( a1 + 0*n_elem_per_reg ); a2v.v = _mm256_loadu_ps( a2 + 0*n_elem_per_reg ); a3v.v = _mm256_loadu_ps( a3 + 0*n_elem_per_reg ); a4v.v = _mm256_loadu_ps( a4 + 0*n_elem_per_reg ); a5v.v = _mm256_loadu_ps( a5 + 0*n_elem_per_reg ); a6v.v = _mm256_loadu_ps( a6 + 0*n_elem_per_reg ); a7v.v = _mm256_loadu_ps( a7 + 0*n_elem_per_reg ); // perform : y += alpha * x; y0v.v = _mm256_fmadd_ps( a0v.v, chi0v.v, y0v.v ); y0v.v = _mm256_fmadd_ps( a1v.v, chi1v.v, y0v.v ); y0v.v = _mm256_fmadd_ps( a2v.v, chi2v.v, y0v.v ); y0v.v = _mm256_fmadd_ps( a3v.v, chi3v.v, y0v.v ); y0v.v = _mm256_fmadd_ps( a4v.v, chi4v.v, y0v.v ); y0v.v = _mm256_fmadd_ps( a5v.v, chi5v.v, y0v.v ); y0v.v = _mm256_fmadd_ps( a6v.v, chi6v.v, y0v.v ); y0v.v = _mm256_fmadd_ps( a7v.v, chi7v.v, y0v.v ); // Store the output. _mm256_storeu_ps( (y0 + 0*n_elem_per_reg), y0v.v ); y0 += n_elem_per_reg; a0 += n_elem_per_reg; a1 += n_elem_per_reg; a2 += n_elem_per_reg; a3 += n_elem_per_reg; a4 += n_elem_per_reg; a5 += n_elem_per_reg; a6 += n_elem_per_reg; a7 += n_elem_per_reg; } // If there are leftover iterations, perform them with scalar code. for ( i = 0; i < m_left ; ++i ) { float y0c = *y0; const float a0c = *a0; const float a1c = *a1; const float a2c = *a2; const float a3c = *a3; const float a4c = *a4; const float a5c = *a5; const float a6c = *a6; const float a7c = *a7; y0c += chi0 * a0c; y0c += chi1 * a1c; y0c += chi2 * a2c; y0c += chi3 * a3c; y0c += chi4 * a4c; y0c += chi5 * a5c; y0c += chi6 * a6c; y0c += chi7 * a7c; *y0 = y0c; a0 += inca; a1 += inca; a2 += inca; a3 += inca; a4 += inca; a5 += inca; a6 += inca; a7 += inca; y0 += incy; } } // ----------------------------------------------------------------------------- void bli_daxpyf_zen_int_8 ( conj_t conja, conj_t conjx, dim_t m, dim_t b_n, double* restrict alpha, double* restrict a, inc_t inca, inc_t lda, double* restrict x, inc_t incx, double* restrict y, inc_t incy, cntx_t* restrict cntx ) { const dim_t fuse_fac = 8; const dim_t n_elem_per_reg = 4; const dim_t n_iter_unroll = 1; dim_t i; dim_t m_viter; dim_t m_left; double* restrict a0; double* restrict a1; double* restrict a2; double* restrict a3; double* restrict a4; double* restrict a5; double* restrict a6; double* restrict a7; double* restrict y0; v4df_t chi0v, chi1v, chi2v, chi3v; v4df_t chi4v, chi5v, chi6v, chi7v; v4df_t a0v, a1v, a2v, a3v; v4df_t a4v, a5v, a6v, a7v; v4df_t y0v; double chi0, chi1, chi2, chi3; double chi4, chi5, chi6, chi7; // If either dimension is zero, or if alpha is zero, return early. if ( bli_zero_dim2( m, b_n ) || PASTEMAC(d,eq0)( *alpha ) ) return; // If b_n is not equal to the fusing factor, then perform the entire // operation as a loop over axpyv. if ( b_n != fuse_fac ) { daxpyv_ker_ft f = bli_cntx_get_l1v_ker_dt( BLIS_DOUBLE, BLIS_AXPYV_KER, cntx ); for ( i = 0; i < b_n; ++i ) { double* a1 = a + (0 )*inca + (i )*lda; double* chi1 = x + (i )*incx; double* y1 = y + (0 )*incy; double alpha_chi1; PASTEMAC(d,copycjs)( conjx, *chi1, alpha_chi1 ); PASTEMAC(d,scals)( *alpha, alpha_chi1 ); f ( conja, m, &alpha_chi1, a1, inca, y1, incy, cntx ); } return; } // At this point, we know that b_n is exactly equal to the fusing factor. // Use the unrolling factor and the number of elements per register // to compute the number of vectorized and leftover iterations. m_viter = ( m ) / ( n_elem_per_reg * n_iter_unroll ); m_left = ( m ) % ( n_elem_per_reg * n_iter_unroll ); // If there is anything that would interfere with our use of contiguous // vector loads/stores, override m_viter and m_left to use scalar code // for all iterations. if ( inca != 1 || incy != 1 ) { m_viter = 0; m_left = m; } a0 = a + 0*lda; a1 = a + 1*lda; a2 = a + 2*lda; a3 = a + 3*lda; a4 = a + 4*lda; a5 = a + 5*lda; a6 = a + 6*lda; a7 = a + 7*lda; y0 = y; chi0 = *( x + 0*incx ); chi1 = *( x + 1*incx ); chi2 = *( x + 2*incx ); chi3 = *( x + 3*incx ); chi4 = *( x + 4*incx ); chi5 = *( x + 5*incx ); chi6 = *( x + 6*incx ); chi7 = *( x + 7*incx ); // Scale each chi scalar by alpha. PASTEMAC(d,scals)( *alpha, chi0 ); PASTEMAC(d,scals)( *alpha, chi1 ); PASTEMAC(d,scals)( *alpha, chi2 ); PASTEMAC(d,scals)( *alpha, chi3 ); PASTEMAC(d,scals)( *alpha, chi4 ); PASTEMAC(d,scals)( *alpha, chi5 ); PASTEMAC(d,scals)( *alpha, chi6 ); PASTEMAC(d,scals)( *alpha, chi7 ); // Broadcast the (alpha*chi?) scalars to all elements of vector registers. chi0v.v = _mm256_broadcast_sd( &chi0 ); chi1v.v = _mm256_broadcast_sd( &chi1 ); chi2v.v = _mm256_broadcast_sd( &chi2 ); chi3v.v = _mm256_broadcast_sd( &chi3 ); chi4v.v = _mm256_broadcast_sd( &chi4 ); chi5v.v = _mm256_broadcast_sd( &chi5 ); chi6v.v = _mm256_broadcast_sd( &chi6 ); chi7v.v = _mm256_broadcast_sd( &chi7 ); // If there are vectorized iterations, perform them with vector // instructions. for ( i = 0; i < m_viter; ++i ) { // Load the input values. y0v.v = _mm256_loadu_pd( y0 + 0*n_elem_per_reg ); a0v.v = _mm256_loadu_pd( a0 + 0*n_elem_per_reg ); a1v.v = _mm256_loadu_pd( a1 + 0*n_elem_per_reg ); a2v.v = _mm256_loadu_pd( a2 + 0*n_elem_per_reg ); a3v.v = _mm256_loadu_pd( a3 + 0*n_elem_per_reg ); a4v.v = _mm256_loadu_pd( a4 + 0*n_elem_per_reg ); a5v.v = _mm256_loadu_pd( a5 + 0*n_elem_per_reg ); a6v.v = _mm256_loadu_pd( a6 + 0*n_elem_per_reg ); a7v.v = _mm256_loadu_pd( a7 + 0*n_elem_per_reg ); // perform : y += alpha * x; y0v.v = _mm256_fmadd_pd( a0v.v, chi0v.v, y0v.v ); y0v.v = _mm256_fmadd_pd( a1v.v, chi1v.v, y0v.v ); y0v.v = _mm256_fmadd_pd( a2v.v, chi2v.v, y0v.v ); y0v.v = _mm256_fmadd_pd( a3v.v, chi3v.v, y0v.v ); y0v.v = _mm256_fmadd_pd( a4v.v, chi4v.v, y0v.v ); y0v.v = _mm256_fmadd_pd( a5v.v, chi5v.v, y0v.v ); y0v.v = _mm256_fmadd_pd( a6v.v, chi6v.v, y0v.v ); y0v.v = _mm256_fmadd_pd( a7v.v, chi7v.v, y0v.v ); // Store the output. _mm256_storeu_pd( (y0 + 0*n_elem_per_reg), y0v.v ); y0 += n_elem_per_reg; a0 += n_elem_per_reg; a1 += n_elem_per_reg; a2 += n_elem_per_reg; a3 += n_elem_per_reg; a4 += n_elem_per_reg; a5 += n_elem_per_reg; a6 += n_elem_per_reg; a7 += n_elem_per_reg; } // If there are leftover iterations, perform them with scalar code. for ( i = 0; i < m_left ; ++i ) { double y0c = *y0; const double a0c = *a0; const double a1c = *a1; const double a2c = *a2; const double a3c = *a3; const double a4c = *a4; const double a5c = *a5; const double a6c = *a6; const double a7c = *a7; y0c += chi0 * a0c; y0c += chi1 * a1c; y0c += chi2 * a2c; y0c += chi3 * a3c; y0c += chi4 * a4c; y0c += chi5 * a5c; y0c += chi6 * a6c; y0c += chi7 * a7c; *y0 = y0c; a0 += inca; a1 += inca; a2 += inca; a3 += inca; a4 += inca; a5 += inca; a6 += inca; a7 += inca; y0 += incy; } } blis-0.9.0/kernels/zen/1f/bli_dotxf_zen_int_8.c000066400000000000000000000644211422157504600213260ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2018, The University of Texas at Austin Copyright (C) 2016 - 2018, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "immintrin.h" #include "blis.h" /* Union data structure to access AVX registers One 256-bit AVX register holds 8 SP elements. */ typedef union { __m256 v; float f[8] __attribute__((aligned(64))); } v8sf_t; /* Union data structure to access AVX registers * One 256-bit AVX register holds 4 DP elements. */ typedef union { __m256d v; double d[4] __attribute__((aligned(64))); } v4df_t; // ----------------------------------------------------------------------------- void bli_sdotxf_zen_int_8 ( conj_t conjat, conj_t conjx, dim_t m, dim_t b_n, float* restrict alpha, float* restrict a, inc_t inca, inc_t lda, float* restrict x, inc_t incx, float* restrict beta, float* restrict y, inc_t incy, cntx_t* restrict cntx ) { const dim_t fuse_fac = 8; const dim_t n_elem_per_reg = 8; // If the b_n dimension is zero, y is empty and there is no computation. if ( bli_zero_dim1( b_n ) ) return; // If the m dimension is zero, or if alpha is zero, the computation // simplifies to updating y. if ( bli_zero_dim1( m ) || PASTEMAC(s,eq0)( *alpha ) ) { sscalv_ker_ft f = bli_cntx_get_l1v_ker_dt( BLIS_FLOAT, BLIS_SCALV_KER, cntx ); f ( BLIS_NO_CONJUGATE, b_n, beta, y, incy, cntx ); return; } // If b_n is not equal to the fusing factor, then perform the entire // operation as a loop over dotxv. if ( b_n != fuse_fac ) { sdotxv_ker_ft f = bli_cntx_get_l1v_ker_dt( BLIS_FLOAT, BLIS_DOTXV_KER, cntx ); for ( dim_t i = 0; i < b_n; ++i ) { float* a1 = a + (0 )*inca + (i )*lda; float* x1 = x + (0 )*incx; float* psi1 = y + (i )*incy; f ( conjat, conjx, m, alpha, a1, inca, x1, incx, beta, psi1, cntx ); } return; } // At this point, we know that b_n is exactly equal to the fusing factor. // However, m may not be a multiple of the number of elements per vector. // Going forward, we handle two possible storage formats of A explicitly: // (1) A is stored by columns, or (2) A is stored by rows. Either case is // further split into two subproblems along the m dimension: // (a) a vectorized part, starting at m = 0 and ending at any 0 <= m' <= m. // (b) a scalar part, starting at m' and ending at m. If no vectorization // is possible then m' == 0 and thus the scalar part is the entire // problem. If 0 < m', then the a and x pointers and m variable will // be adjusted accordingly for the second subproblem. // Note: since parts (b) for both (1) and (2) are so similar, they are // factored out into one code block after the following conditional, which // distinguishes between (1) and (2). // Intermediate variables to hold the completed dot products float rho0 = 0, rho1 = 0, rho2 = 0, rho3 = 0, rho4 = 0, rho5 = 0, rho6 = 0, rho7 = 0; if ( inca == 1 && incx == 1 ) { const dim_t n_iter_unroll = 1; // Use the unrolling factor and the number of elements per register // to compute the number of vectorized and leftover iterations. dim_t m_viter = ( m ) / ( n_elem_per_reg * n_iter_unroll ); // Set up pointers for x and the b_n columns of A (rows of A^T). float* restrict x0 = x; float* restrict a0 = a + 0*lda; float* restrict a1 = a + 1*lda; float* restrict a2 = a + 2*lda; float* restrict a3 = a + 3*lda; float* restrict a4 = a + 4*lda; float* restrict a5 = a + 5*lda; float* restrict a6 = a + 6*lda; float* restrict a7 = a + 7*lda; // Initialize b_n rho vector accumulators to zero. v8sf_t rho0v; rho0v.v = _mm256_setzero_ps(); v8sf_t rho1v; rho1v.v = _mm256_setzero_ps(); v8sf_t rho2v; rho2v.v = _mm256_setzero_ps(); v8sf_t rho3v; rho3v.v = _mm256_setzero_ps(); v8sf_t rho4v; rho4v.v = _mm256_setzero_ps(); v8sf_t rho5v; rho5v.v = _mm256_setzero_ps(); v8sf_t rho6v; rho6v.v = _mm256_setzero_ps(); v8sf_t rho7v; rho7v.v = _mm256_setzero_ps(); v8sf_t x0v; v8sf_t a0v, a1v, a2v, a3v, a4v, a5v, a6v, a7v; // If there are vectorized iterations, perform them with vector // instructions. for ( dim_t i = 0; i < m_viter; ++i ) { // Load the input values. x0v.v = _mm256_loadu_ps( x0 + 0*n_elem_per_reg ); a0v.v = _mm256_loadu_ps( a0 + 0*n_elem_per_reg ); a1v.v = _mm256_loadu_ps( a1 + 0*n_elem_per_reg ); a2v.v = _mm256_loadu_ps( a2 + 0*n_elem_per_reg ); a3v.v = _mm256_loadu_ps( a3 + 0*n_elem_per_reg ); a4v.v = _mm256_loadu_ps( a4 + 0*n_elem_per_reg ); a5v.v = _mm256_loadu_ps( a5 + 0*n_elem_per_reg ); a6v.v = _mm256_loadu_ps( a6 + 0*n_elem_per_reg ); a7v.v = _mm256_loadu_ps( a7 + 0*n_elem_per_reg ); // perform: rho?v += a?v * x0v; rho0v.v = _mm256_fmadd_ps( a0v.v, x0v.v, rho0v.v ); rho1v.v = _mm256_fmadd_ps( a1v.v, x0v.v, rho1v.v ); rho2v.v = _mm256_fmadd_ps( a2v.v, x0v.v, rho2v.v ); rho3v.v = _mm256_fmadd_ps( a3v.v, x0v.v, rho3v.v ); rho4v.v = _mm256_fmadd_ps( a4v.v, x0v.v, rho4v.v ); rho5v.v = _mm256_fmadd_ps( a5v.v, x0v.v, rho5v.v ); rho6v.v = _mm256_fmadd_ps( a6v.v, x0v.v, rho6v.v ); rho7v.v = _mm256_fmadd_ps( a7v.v, x0v.v, rho7v.v ); x0 += n_elem_per_reg * n_iter_unroll; a0 += n_elem_per_reg * n_iter_unroll; a1 += n_elem_per_reg * n_iter_unroll; a2 += n_elem_per_reg * n_iter_unroll; a3 += n_elem_per_reg * n_iter_unroll; a4 += n_elem_per_reg * n_iter_unroll; a5 += n_elem_per_reg * n_iter_unroll; a6 += n_elem_per_reg * n_iter_unroll; a7 += n_elem_per_reg * n_iter_unroll; } #if 0 rho0 += rho0v.f[0] + rho0v.f[1] + rho0v.f[2] + rho0v.f[3] + rho0v.f[4] + rho0v.f[5] + rho0v.f[6] + rho0v.f[7]; rho1 += rho1v.f[0] + rho1v.f[1] + rho1v.f[2] + rho1v.f[3] + rho1v.f[4] + rho1v.f[5] + rho1v.f[6] + rho1v.f[7]; rho2 += rho2v.f[0] + rho2v.f[1] + rho2v.f[2] + rho2v.f[3] + rho2v.f[4] + rho2v.f[5] + rho2v.f[6] + rho2v.f[7]; rho3 += rho3v.f[0] + rho3v.f[1] + rho3v.f[2] + rho3v.f[3] + rho3v.f[4] + rho3v.f[5] + rho3v.f[6] + rho3v.f[7]; rho4 += rho4v.f[0] + rho4v.f[1] + rho4v.f[2] + rho4v.f[3] + rho4v.f[4] + rho4v.f[5] + rho4v.f[6] + rho4v.f[7]; rho5 += rho5v.f[0] + rho5v.f[1] + rho5v.f[2] + rho5v.f[3] + rho5v.f[4] + rho5v.f[5] + rho5v.f[6] + rho5v.f[7]; rho6 += rho6v.f[0] + rho6v.f[1] + rho6v.f[2] + rho6v.f[3] + rho6v.f[4] + rho6v.f[5] + rho6v.f[6] + rho6v.f[7]; rho7 += rho7v.f[0] + rho7v.f[1] + rho7v.f[2] + rho7v.f[3] + rho7v.f[4] + rho7v.f[5] + rho7v.f[6] + rho7v.f[7]; #else // Now we need to sum the elements within each vector. v8sf_t onev; onev.v = _mm256_set1_ps( 1.0f ); // Sum the elements of a given rho?v by dotting it with 1. The '1' in // '0xf1' stores the sum of the upper four and lower four values to // the low elements of each lane: elements 4 and 0, respectively. (The // 'f' in '0xf1' means include all four elements of each lane in the // summation.) rho0v.v = _mm256_dp_ps( rho0v.v, onev.v, 0xf1 ); rho1v.v = _mm256_dp_ps( rho1v.v, onev.v, 0xf1 ); rho2v.v = _mm256_dp_ps( rho2v.v, onev.v, 0xf1 ); rho3v.v = _mm256_dp_ps( rho3v.v, onev.v, 0xf1 ); rho4v.v = _mm256_dp_ps( rho4v.v, onev.v, 0xf1 ); rho5v.v = _mm256_dp_ps( rho5v.v, onev.v, 0xf1 ); rho6v.v = _mm256_dp_ps( rho6v.v, onev.v, 0xf1 ); rho7v.v = _mm256_dp_ps( rho7v.v, onev.v, 0xf1 ); // Manually add the results from above to finish the sum. rho0 = rho0v.f[0] + rho0v.f[4]; rho1 = rho1v.f[0] + rho1v.f[4]; rho2 = rho2v.f[0] + rho2v.f[4]; rho3 = rho3v.f[0] + rho3v.f[4]; rho4 = rho4v.f[0] + rho4v.f[4]; rho5 = rho5v.f[0] + rho5v.f[4]; rho6 = rho6v.f[0] + rho6v.f[4]; rho7 = rho7v.f[0] + rho7v.f[4]; #endif // Adjust for scalar subproblem. m -= n_elem_per_reg * n_iter_unroll * m_viter; a += n_elem_per_reg * n_iter_unroll * m_viter /* * inca */; x += n_elem_per_reg * n_iter_unroll * m_viter /* * incx */; } else if ( lda == 1 ) { const dim_t n_iter_unroll = 4; // Use the unrolling factor and the number of elements per register // to compute the number of vectorized and leftover iterations. dim_t m_viter = ( m ) / ( n_iter_unroll ); // Initialize pointers for x and A. float* restrict x0 = x; float* restrict a0 = a; // Initialize rho vector accumulators to zero. v8sf_t rho0v; rho0v.v = _mm256_setzero_ps(); v8sf_t rho1v; rho1v.v = _mm256_setzero_ps(); v8sf_t rho2v; rho2v.v = _mm256_setzero_ps(); v8sf_t rho3v; rho3v.v = _mm256_setzero_ps(); v8sf_t x0v, x1v, x2v, x3v; v8sf_t a0v, a1v, a2v, a3v; for ( dim_t i = 0; i < m_viter; ++i ) { // Load the input values. a0v.v = _mm256_loadu_ps( a0 + 0*inca ); a1v.v = _mm256_loadu_ps( a0 + 1*inca ); a2v.v = _mm256_loadu_ps( a0 + 2*inca ); a3v.v = _mm256_loadu_ps( a0 + 3*inca ); x0v.v = _mm256_broadcast_ss( x0 + 0*incx ); x1v.v = _mm256_broadcast_ss( x0 + 1*incx ); x2v.v = _mm256_broadcast_ss( x0 + 2*incx ); x3v.v = _mm256_broadcast_ss( x0 + 3*incx ); // perform : rho?v += a?v * x?v; rho0v.v = _mm256_fmadd_ps( a0v.v, x0v.v, rho0v.v ); rho1v.v = _mm256_fmadd_ps( a1v.v, x1v.v, rho1v.v ); rho2v.v = _mm256_fmadd_ps( a2v.v, x2v.v, rho2v.v ); rho3v.v = _mm256_fmadd_ps( a3v.v, x3v.v, rho3v.v ); x0 += incx * n_iter_unroll; a0 += inca * n_iter_unroll; } // Combine the 8 accumulators into one vector register. rho0v.v = _mm256_add_ps( rho0v.v, rho1v.v ); rho2v.v = _mm256_add_ps( rho2v.v, rho3v.v ); rho0v.v = _mm256_add_ps( rho0v.v, rho2v.v ); // Write vector components to scalar values. rho0 = rho0v.f[0]; rho1 = rho0v.f[1]; rho2 = rho0v.f[2]; rho3 = rho0v.f[3]; rho4 = rho0v.f[4]; rho5 = rho0v.f[5]; rho6 = rho0v.f[6]; rho7 = rho0v.f[7]; // Adjust for scalar subproblem. m -= n_iter_unroll * m_viter; a += n_iter_unroll * m_viter * inca; x += n_iter_unroll * m_viter * incx; } else { // No vectorization possible; use scalar iterations for the entire // problem. } // Scalar edge case. { // Initialize pointers for x and the b_n columns of A (rows of A^T). float* restrict x0 = x; float* restrict a0 = a + 0*lda; float* restrict a1 = a + 1*lda; float* restrict a2 = a + 2*lda; float* restrict a3 = a + 3*lda; float* restrict a4 = a + 4*lda; float* restrict a5 = a + 5*lda; float* restrict a6 = a + 6*lda; float* restrict a7 = a + 7*lda; // If there are leftover iterations, perform them with scalar code. for ( dim_t i = 0; i < m ; ++i ) { const float x0c = *x0; const float a0c = *a0; const float a1c = *a1; const float a2c = *a2; const float a3c = *a3; const float a4c = *a4; const float a5c = *a5; const float a6c = *a6; const float a7c = *a7; rho0 += a0c * x0c; rho1 += a1c * x0c; rho2 += a2c * x0c; rho3 += a3c * x0c; rho4 += a4c * x0c; rho5 += a5c * x0c; rho6 += a6c * x0c; rho7 += a7c * x0c; x0 += incx; a0 += inca; a1 += inca; a2 += inca; a3 += inca; a4 += inca; a5 += inca; a6 += inca; a7 += inca; } } // Now prepare the final rho values to output/accumulate back into // the y vector. v8sf_t rho0v, y0v; // Insert the scalar rho values into a single vector. rho0v.f[0] = rho0; rho0v.f[1] = rho1; rho0v.f[2] = rho2; rho0v.f[3] = rho3; rho0v.f[4] = rho4; rho0v.f[5] = rho5; rho0v.f[6] = rho6; rho0v.f[7] = rho7; // Broadcast the alpha scalar. v8sf_t alphav; alphav.v = _mm256_broadcast_ss( alpha ); // We know at this point that alpha is nonzero; however, beta may still // be zero. If beta is indeed zero, we must overwrite y rather than scale // by beta (in case y contains NaN or Inf). if ( PASTEMAC(s,eq0)( *beta ) ) { // Apply alpha to the accumulated dot product in rho: // y := alpha * rho y0v.v = _mm256_mul_ps( alphav.v, rho0v.v ); } else { // Broadcast the beta scalar. v8sf_t betav; betav.v = _mm256_broadcast_ss( beta ); // Load y. if ( incy == 1 ) { y0v.v = _mm256_loadu_ps( y + 0*n_elem_per_reg ); } else { y0v.f[0] = *(y + 0*incy); y0v.f[1] = *(y + 1*incy); y0v.f[2] = *(y + 2*incy); y0v.f[3] = *(y + 3*incy); y0v.f[4] = *(y + 4*incy); y0v.f[5] = *(y + 5*incy); y0v.f[6] = *(y + 6*incy); y0v.f[7] = *(y + 7*incy); } // Apply beta to y and alpha to the accumulated dot product in rho: // y := beta * y + alpha * rho y0v.v = _mm256_mul_ps( betav.v, y0v.v ); y0v.v = _mm256_fmadd_ps( alphav.v, rho0v.v, y0v.v ); } // Store the output. if ( incy == 1 ) { _mm256_storeu_ps( (y + 0*n_elem_per_reg), y0v.v ); } else { *(y + 0*incy) = y0v.f[0]; *(y + 1*incy) = y0v.f[1]; *(y + 2*incy) = y0v.f[2]; *(y + 3*incy) = y0v.f[3]; *(y + 4*incy) = y0v.f[4]; *(y + 5*incy) = y0v.f[5]; *(y + 6*incy) = y0v.f[6]; *(y + 7*incy) = y0v.f[7]; } } // ----------------------------------------------------------------------------- void bli_ddotxf_zen_int_8 ( conj_t conjat, conj_t conjx, dim_t m, dim_t b_n, double* restrict alpha, double* restrict a, inc_t inca, inc_t lda, double* restrict x, inc_t incx, double* restrict beta, double* restrict y, inc_t incy, cntx_t* restrict cntx ) { const dim_t fuse_fac = 8; const dim_t n_elem_per_reg = 4; // If the b_n dimension is zero, y is empty and there is no computation. if ( bli_zero_dim1( b_n ) ) return; // If the m dimension is zero, or if alpha is zero, the computation // simplifies to updating y. if ( bli_zero_dim1( m ) || PASTEMAC(d,eq0)( *alpha ) ) { dscalv_ker_ft f = bli_cntx_get_l1v_ker_dt( BLIS_DOUBLE, BLIS_SCALV_KER, cntx ); f ( BLIS_NO_CONJUGATE, b_n, beta, y, incy, cntx ); return; } // If b_n is not equal to the fusing factor, then perform the entire // operation as a loop over dotxv. if ( b_n != fuse_fac ) { ddotxv_ker_ft f = bli_cntx_get_l1v_ker_dt( BLIS_DOUBLE, BLIS_DOTXV_KER, cntx ); for ( dim_t i = 0; i < b_n; ++i ) { double* a1 = a + (0 )*inca + (i )*lda; double* x1 = x + (0 )*incx; double* psi1 = y + (i )*incy; f ( conjat, conjx, m, alpha, a1, inca, x1, incx, beta, psi1, cntx ); } return; } // At this point, we know that b_n is exactly equal to the fusing factor. // However, m may not be a multiple of the number of elements per vector. // Going forward, we handle two possible storage formats of A explicitly: // (1) A is stored by columns, or (2) A is stored by rows. Either case is // further split into two subproblems along the m dimension: // (a) a vectorized part, starting at m = 0 and ending at any 0 <= m' <= m. // (b) a scalar part, starting at m' and ending at m. If no vectorization // is possible then m' == 0 and thus the scalar part is the entire // problem. If 0 < m', then the a and x pointers and m variable will // be adjusted accordingly for the second subproblem. // Note: since parts (b) for both (1) and (2) are so similar, they are // factored out into one code block after the following conditional, which // distinguishes between (1) and (2). // Intermediate variables to hold the completed dot products double rho0 = 0, rho1 = 0, rho2 = 0, rho3 = 0, rho4 = 0, rho5 = 0, rho6 = 0, rho7 = 0; if ( inca == 1 && incx == 1 ) { const dim_t n_iter_unroll = 1; // Use the unrolling factor and the number of elements per register // to compute the number of vectorized and leftover iterations. dim_t m_viter = ( m ) / ( n_elem_per_reg * n_iter_unroll ); // Set up pointers for x and the b_n columns of A (rows of A^T). double* restrict x0 = x; double* restrict a0 = a + 0*lda; double* restrict a1 = a + 1*lda; double* restrict a2 = a + 2*lda; double* restrict a3 = a + 3*lda; double* restrict a4 = a + 4*lda; double* restrict a5 = a + 5*lda; double* restrict a6 = a + 6*lda; double* restrict a7 = a + 7*lda; // Initialize b_n rho vector accumulators to zero. v4df_t rho0v; rho0v.v = _mm256_setzero_pd(); v4df_t rho1v; rho1v.v = _mm256_setzero_pd(); v4df_t rho2v; rho2v.v = _mm256_setzero_pd(); v4df_t rho3v; rho3v.v = _mm256_setzero_pd(); v4df_t rho4v; rho4v.v = _mm256_setzero_pd(); v4df_t rho5v; rho5v.v = _mm256_setzero_pd(); v4df_t rho6v; rho6v.v = _mm256_setzero_pd(); v4df_t rho7v; rho7v.v = _mm256_setzero_pd(); v4df_t x0v; v4df_t a0v, a1v, a2v, a3v, a4v, a5v, a6v, a7v; // If there are vectorized iterations, perform them with vector // instructions. for ( dim_t i = 0; i < m_viter; ++i ) { // Load the input values. x0v.v = _mm256_loadu_pd( x0 + 0*n_elem_per_reg ); a0v.v = _mm256_loadu_pd( a0 + 0*n_elem_per_reg ); a1v.v = _mm256_loadu_pd( a1 + 0*n_elem_per_reg ); a2v.v = _mm256_loadu_pd( a2 + 0*n_elem_per_reg ); a3v.v = _mm256_loadu_pd( a3 + 0*n_elem_per_reg ); a4v.v = _mm256_loadu_pd( a4 + 0*n_elem_per_reg ); a5v.v = _mm256_loadu_pd( a5 + 0*n_elem_per_reg ); a6v.v = _mm256_loadu_pd( a6 + 0*n_elem_per_reg ); a7v.v = _mm256_loadu_pd( a7 + 0*n_elem_per_reg ); // perform: rho?v += a?v * x0v; rho0v.v = _mm256_fmadd_pd( a0v.v, x0v.v, rho0v.v ); rho1v.v = _mm256_fmadd_pd( a1v.v, x0v.v, rho1v.v ); rho2v.v = _mm256_fmadd_pd( a2v.v, x0v.v, rho2v.v ); rho3v.v = _mm256_fmadd_pd( a3v.v, x0v.v, rho3v.v ); rho4v.v = _mm256_fmadd_pd( a4v.v, x0v.v, rho4v.v ); rho5v.v = _mm256_fmadd_pd( a5v.v, x0v.v, rho5v.v ); rho6v.v = _mm256_fmadd_pd( a6v.v, x0v.v, rho6v.v ); rho7v.v = _mm256_fmadd_pd( a7v.v, x0v.v, rho7v.v ); x0 += n_elem_per_reg * n_iter_unroll; a0 += n_elem_per_reg * n_iter_unroll; a1 += n_elem_per_reg * n_iter_unroll; a2 += n_elem_per_reg * n_iter_unroll; a3 += n_elem_per_reg * n_iter_unroll; a4 += n_elem_per_reg * n_iter_unroll; a5 += n_elem_per_reg * n_iter_unroll; a6 += n_elem_per_reg * n_iter_unroll; a7 += n_elem_per_reg * n_iter_unroll; } #if 0 rho0 += rho0v.d[0] + rho0v.d[1] + rho0v.d[2] + rho0v.d[3]; rho1 += rho1v.d[0] + rho1v.d[1] + rho1v.d[2] + rho1v.d[3]; rho2 += rho2v.d[0] + rho2v.d[1] + rho2v.d[2] + rho2v.d[3]; rho3 += rho3v.d[0] + rho3v.d[1] + rho3v.d[2] + rho3v.d[3]; rho4 += rho4v.d[0] + rho4v.d[1] + rho4v.d[2] + rho4v.d[3]; rho5 += rho5v.d[0] + rho5v.d[1] + rho5v.d[2] + rho5v.d[3]; rho6 += rho6v.d[0] + rho6v.d[1] + rho6v.d[2] + rho6v.d[3]; rho7 += rho7v.d[0] + rho7v.d[1] + rho7v.d[2] + rho7v.d[3]; #else // Sum the elements of a given rho?v. This computes the sum of // elements within lanes and stores the sum to both elements. rho0v.v = _mm256_hadd_pd( rho0v.v, rho0v.v ); rho1v.v = _mm256_hadd_pd( rho1v.v, rho1v.v ); rho2v.v = _mm256_hadd_pd( rho2v.v, rho2v.v ); rho3v.v = _mm256_hadd_pd( rho3v.v, rho3v.v ); rho4v.v = _mm256_hadd_pd( rho4v.v, rho4v.v ); rho5v.v = _mm256_hadd_pd( rho5v.v, rho5v.v ); rho6v.v = _mm256_hadd_pd( rho6v.v, rho6v.v ); rho7v.v = _mm256_hadd_pd( rho7v.v, rho7v.v ); // Manually add the results from above to finish the sum. rho0 = rho0v.d[0] + rho0v.d[2]; rho1 = rho1v.d[0] + rho1v.d[2]; rho2 = rho2v.d[0] + rho2v.d[2]; rho3 = rho3v.d[0] + rho3v.d[2]; rho4 = rho4v.d[0] + rho4v.d[2]; rho5 = rho5v.d[0] + rho5v.d[2]; rho6 = rho6v.d[0] + rho6v.d[2]; rho7 = rho7v.d[0] + rho7v.d[2]; #endif // Adjust for scalar subproblem. m -= n_elem_per_reg * n_iter_unroll * m_viter; a += n_elem_per_reg * n_iter_unroll * m_viter /* * inca */; x += n_elem_per_reg * n_iter_unroll * m_viter /* * incx */; } else if ( lda == 1 ) { const dim_t n_iter_unroll = 3; const dim_t n_reg_per_row = 2; // fuse_fac / n_elem_per_reg; // Use the unrolling factor and the number of elements per register // to compute the number of vectorized and leftover iterations. dim_t m_viter = ( m ) / ( n_reg_per_row * n_iter_unroll ); // Initialize pointers for x and A. double* restrict x0 = x; double* restrict a0 = a; // Initialize rho vector accumulators to zero. v4df_t rho0v; rho0v.v = _mm256_setzero_pd(); v4df_t rho1v; rho1v.v = _mm256_setzero_pd(); v4df_t rho2v; rho2v.v = _mm256_setzero_pd(); v4df_t rho3v; rho3v.v = _mm256_setzero_pd(); v4df_t rho4v; rho4v.v = _mm256_setzero_pd(); v4df_t rho5v; rho5v.v = _mm256_setzero_pd(); v4df_t x0v, x1v, x2v; v4df_t a0v, a1v, a2v, a3v, a4v, a5v; for ( dim_t i = 0; i < m_viter; ++i ) { // Load the input values. a0v.v = _mm256_loadu_pd( a0 + 0*inca + 0*n_elem_per_reg ); a1v.v = _mm256_loadu_pd( a0 + 0*inca + 1*n_elem_per_reg ); a2v.v = _mm256_loadu_pd( a0 + 1*inca + 0*n_elem_per_reg ); a3v.v = _mm256_loadu_pd( a0 + 1*inca + 1*n_elem_per_reg ); a4v.v = _mm256_loadu_pd( a0 + 2*inca + 0*n_elem_per_reg ); a5v.v = _mm256_loadu_pd( a0 + 2*inca + 1*n_elem_per_reg ); x0v.v = _mm256_broadcast_sd( x0 + 0*incx ); x1v.v = _mm256_broadcast_sd( x0 + 1*incx ); x2v.v = _mm256_broadcast_sd( x0 + 2*incx ); // perform : rho?v += a?v * x?v; rho0v.v = _mm256_fmadd_pd( a0v.v, x0v.v, rho0v.v ); rho1v.v = _mm256_fmadd_pd( a1v.v, x0v.v, rho1v.v ); rho2v.v = _mm256_fmadd_pd( a2v.v, x1v.v, rho2v.v ); rho3v.v = _mm256_fmadd_pd( a3v.v, x1v.v, rho3v.v ); rho4v.v = _mm256_fmadd_pd( a4v.v, x2v.v, rho4v.v ); rho5v.v = _mm256_fmadd_pd( a5v.v, x2v.v, rho5v.v ); x0 += incx * n_iter_unroll; a0 += inca * n_iter_unroll; } // Combine the 8 accumulators into one vector register. rho0v.v = _mm256_add_pd( rho0v.v, rho2v.v ); rho0v.v = _mm256_add_pd( rho0v.v, rho4v.v ); rho1v.v = _mm256_add_pd( rho1v.v, rho3v.v ); rho1v.v = _mm256_add_pd( rho1v.v, rho5v.v ); // Write vector components to scalar values. rho0 = rho0v.d[0]; rho1 = rho0v.d[1]; rho2 = rho0v.d[2]; rho3 = rho0v.d[3]; rho4 = rho1v.d[0]; rho5 = rho1v.d[1]; rho6 = rho1v.d[2]; rho7 = rho1v.d[3]; // Adjust for scalar subproblem. m -= n_iter_unroll * m_viter; a += n_iter_unroll * m_viter * inca; x += n_iter_unroll * m_viter * incx; } else { // No vectorization possible; use scalar iterations for the entire // problem. } // Scalar edge case. { // Initialize pointers for x and the b_n columns of A (rows of A^T). double* restrict x0 = x; double* restrict a0 = a + 0*lda; double* restrict a1 = a + 1*lda; double* restrict a2 = a + 2*lda; double* restrict a3 = a + 3*lda; double* restrict a4 = a + 4*lda; double* restrict a5 = a + 5*lda; double* restrict a6 = a + 6*lda; double* restrict a7 = a + 7*lda; // If there are leftover iterations, perform them with scalar code. for ( dim_t i = 0; i < m ; ++i ) { const double x0c = *x0; const double a0c = *a0; const double a1c = *a1; const double a2c = *a2; const double a3c = *a3; const double a4c = *a4; const double a5c = *a5; const double a6c = *a6; const double a7c = *a7; rho0 += a0c * x0c; rho1 += a1c * x0c; rho2 += a2c * x0c; rho3 += a3c * x0c; rho4 += a4c * x0c; rho5 += a5c * x0c; rho6 += a6c * x0c; rho7 += a7c * x0c; x0 += incx; a0 += inca; a1 += inca; a2 += inca; a3 += inca; a4 += inca; a5 += inca; a6 += inca; a7 += inca; } } // Now prepare the final rho values to output/accumulate back into // the y vector. v4df_t rho0v, rho1v, y0v, y1v; // Insert the scalar rho values into a single vector. rho0v.d[0] = rho0; rho0v.d[1] = rho1; rho0v.d[2] = rho2; rho0v.d[3] = rho3; rho1v.d[0] = rho4; rho1v.d[1] = rho5; rho1v.d[2] = rho6; rho1v.d[3] = rho7; // Broadcast the alpha scalar. v4df_t alphav; alphav.v = _mm256_broadcast_sd( alpha ); // We know at this point that alpha is nonzero; however, beta may still // be zero. If beta is indeed zero, we must overwrite y rather than scale // by beta (in case y contains NaN or Inf). if ( PASTEMAC(d,eq0)( *beta ) ) { // Apply alpha to the accumulated dot product in rho: // y := alpha * rho y0v.v = _mm256_mul_pd( alphav.v, rho0v.v ); y1v.v = _mm256_mul_pd( alphav.v, rho1v.v ); } else { // Broadcast the beta scalar. v4df_t betav; betav.v = _mm256_broadcast_sd( beta ); // Load y. if ( incy == 1 ) { y0v.v = _mm256_loadu_pd( y + 0*n_elem_per_reg ); y1v.v = _mm256_loadu_pd( y + 1*n_elem_per_reg ); } else { y0v.d[0] = *(y + 0*incy); y0v.d[1] = *(y + 1*incy); y0v.d[2] = *(y + 2*incy); y0v.d[3] = *(y + 3*incy); y1v.d[0] = *(y + 4*incy); y1v.d[1] = *(y + 5*incy); y1v.d[2] = *(y + 6*incy); y1v.d[3] = *(y + 7*incy); } // Apply beta to y and alpha to the accumulated dot product in rho: // y := beta * y + alpha * rho y0v.v = _mm256_mul_pd( betav.v, y0v.v ); y1v.v = _mm256_mul_pd( betav.v, y1v.v ); y0v.v = _mm256_fmadd_pd( alphav.v, rho0v.v, y0v.v ); y1v.v = _mm256_fmadd_pd( alphav.v, rho1v.v, y1v.v ); } if ( incy == 1 ) { // Store the output. _mm256_storeu_pd( (y + 0*n_elem_per_reg), y0v.v ); _mm256_storeu_pd( (y + 1*n_elem_per_reg), y1v.v ); } else { *(y + 0*incy) = y0v.d[0]; *(y + 1*incy) = y0v.d[1]; *(y + 2*incy) = y0v.d[2]; *(y + 3*incy) = y0v.d[3]; *(y + 4*incy) = y1v.d[0]; *(y + 5*incy) = y1v.d[1]; *(y + 6*incy) = y1v.d[2]; *(y + 7*incy) = y1v.d[3]; } } blis-0.9.0/kernels/zen/3/000077500000000000000000000000001422157504600150605ustar00rootroot00000000000000blis-0.9.0/kernels/zen/3/bli_gemm_small.c000066400000000000000000005122111422157504600201710ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2017 - 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "immintrin.h" #include "xmmintrin.h" #include "blis.h" #define AOCL_DTL_TRACE_ENTRY(x) ; #define AOCL_DTL_TRACE_EXIT(x) ; #define AOCL_DTL_TRACE_EXIT_ERR(x,y) ; #ifdef BLIS_ENABLE_SMALL_MATRIX #define MR 32 #define D_MR (MR >> 1) #define NR 3 #define D_BLIS_SMALL_MATRIX_K_THRES_ROME 256 #define BLIS_ENABLE_PREFETCH #define D_BLIS_SMALL_MATRIX_THRES (BLIS_SMALL_MATRIX_THRES / 2 ) #define D_BLIS_SMALL_M_RECT_MATRIX_THRES (BLIS_SMALL_M_RECT_MATRIX_THRES / 2) #define D_BLIS_SMALL_K_RECT_MATRIX_THRES (BLIS_SMALL_K_RECT_MATRIX_THRES / 2) #define BLIS_ATBN_M_THRES 40 // Threshold value of M for/below which small matrix code is called. #define AT_MR 4 // The kernel dimension of the A transpose GEMM kernel.(AT_MR * NR). static err_t bli_sgemm_small ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, cntl_t* cntl ); static err_t bli_dgemm_small ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, cntl_t* cntl ); static err_t bli_sgemm_small_atbn ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, cntl_t* cntl ); static err_t bli_dgemm_small_atbn ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, cntl_t* cntl ); /* * The bli_gemm_small function will use the * custom MRxNR kernels, to perform the computation. * The custom kernels are used if the [M * N] < 240 * 240 */ err_t bli_gemm_small ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, cntl_t* cntl ) { AOCL_DTL_TRACE_ENTRY(AOCL_DTL_LEVEL_TRACE_7); #ifdef BLIS_ENABLE_MULTITHREADING AOCL_DTL_TRACE_EXIT(AOCL_DTL_LEVEL_TRACE_7); return BLIS_NOT_YET_IMPLEMENTED; #endif // If alpha is zero, scale by beta and return. if (bli_obj_equals(alpha, &BLIS_ZERO)) { return BLIS_NOT_YET_IMPLEMENTED; } // if row major format return. if ((bli_obj_row_stride( a ) != 1) || (bli_obj_row_stride( b ) != 1) || (bli_obj_row_stride( c ) != 1)) { return BLIS_INVALID_ROW_STRIDE; } num_t dt = bli_obj_dt(c); if (bli_obj_has_trans( a )) { if (bli_obj_has_notrans( b )) { if (dt == BLIS_FLOAT) { return bli_sgemm_small_atbn(alpha, a, b, beta, c, cntx, cntl); } else if (dt == BLIS_DOUBLE) { return bli_dgemm_small_atbn(alpha, a, b, beta, c, cntx, cntl); } } return BLIS_NOT_YET_IMPLEMENTED; } if (dt == BLIS_DOUBLE) { return bli_dgemm_small(alpha, a, b, beta, c, cntx, cntl); } if (dt == BLIS_FLOAT) { return bli_sgemm_small(alpha, a, b, beta, c, cntx, cntl); } AOCL_DTL_TRACE_EXIT(AOCL_DTL_LEVEL_TRACE_7); return BLIS_NOT_YET_IMPLEMENTED; }; static err_t bli_sgemm_small ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, cntl_t* cntl ) { AOCL_DTL_TRACE_ENTRY(AOCL_DTL_LEVEL_TRACE_7); gint_t M = bli_obj_length( c ); // number of rows of Matrix C gint_t N = bli_obj_width( c ); // number of columns of Matrix C gint_t K = bli_obj_width( a ); // number of columns of OP(A), will be updated if OP(A) is Transpose(A) . gint_t L = M * N; // when N is equal to 1 call GEMV instead of GEMM if (N == 1) { bli_gemv ( alpha, a, b, beta, c ); AOCL_DTL_TRACE_EXIT(AOCL_DTL_LEVEL_TRACE_7); return BLIS_SUCCESS; } if ((((L) < (BLIS_SMALL_MATRIX_THRES * BLIS_SMALL_MATRIX_THRES)) || ((M < BLIS_SMALL_M_RECT_MATRIX_THRES) && (K < BLIS_SMALL_K_RECT_MATRIX_THRES))) && ((L!=0) && (K!=0))) { guint_t lda = bli_obj_col_stride( a ); // column stride of matrix OP(A), where OP(A) is Transpose(A) if transA enabled. guint_t ldb = bli_obj_col_stride( b ); // column stride of matrix OP(B), where OP(B) is Transpose(B) if transB enabled. guint_t ldc = bli_obj_col_stride( c ); // column stride of matrix C guint_t row_idx, col_idx, k; float *A = bli_obj_buffer_at_off(a); // pointer to elements of Matrix A float *B = bli_obj_buffer_at_off(b); // pointer to elements of Matrix B float *C = bli_obj_buffer_at_off(c); // pointer to elements of Matrix C float *tA = A, *tB = B, *tC = C;//, *tA_pack; float *tA_packed; // temporary pointer to hold packed A memory pointer guint_t row_idx_packed; //packed A memory row index guint_t lda_packed; //lda of packed A guint_t col_idx_start; //starting index after A matrix is packed. dim_t tb_inc_row = 1; // row stride of matrix B dim_t tb_inc_col = ldb; // column stride of matrix B __m256 ymm4, ymm5, ymm6, ymm7; __m256 ymm8, ymm9, ymm10, ymm11; __m256 ymm12, ymm13, ymm14, ymm15; __m256 ymm0, ymm1, ymm2, ymm3; gint_t n_remainder; // If the N is non multiple of 3.(N%3) gint_t m_remainder; // If the M is non multiple of 32.(M%32) gint_t required_packing_A = 1; mem_t local_mem_buf_A_s; float *A_pack = NULL; rntm_t rntm; const num_t dt_exec = bli_obj_dt( c ); float* restrict alpha_cast = bli_obj_buffer_for_1x1( dt_exec, alpha ); float* restrict beta_cast = bli_obj_buffer_for_1x1( dt_exec, beta ); /*Beta Zero Check*/ bool is_beta_non_zero=0; if ( !bli_obj_equals( beta, &BLIS_ZERO ) ){ is_beta_non_zero = 1; } //update the pointer math if matrix B needs to be transposed. if (bli_obj_has_trans( b )) { tb_inc_col = 1; //switch row and column strides tb_inc_row = ldb; } /* * This function was using global array to pack part of A input when needed. * However, using this global array make the function non-reentrant. * Instead of using a global array we should allocate buffer for each invocation. * Since the buffer size is too big or stack and doing malloc every time will be too expensive, * better approach is to get the buffer from the pre-allocated pool and return * it the pool once we are doing. * * In order to get the buffer from pool, we need access to memory broker, * currently this function is not invoked in such a way that it can receive * the memory broker (via rntm). Following hack will get the global memory * broker that can be use it to access the pool. * * Note there will be memory allocation at least on first innovation * as there will not be any pool created for this size. * Subsequent invocations will just reuse the buffer from the pool. */ bli_rntm_init_from_global( &rntm ); bli_rntm_set_num_threads_only( 1, &rntm ); bli_pba_rntm_set_pba( &rntm ); // Get the current size of the buffer pool for A block packing. // We will use the same size to avoid pool re-initialization siz_t buffer_size = bli_pool_block_size(bli_pba_pool(bli_packbuf_index(BLIS_BITVAL_BUFFER_FOR_A_BLOCK), bli_rntm_pba(&rntm))); // Based on the available memory in the buffer we will decide if // we want to do packing or not. // // This kernel assumes that "A" will be un-packged if N <= 3. // Usually this range (N <= 3) is handled by SUP, however, // if SUP is disabled or for any other condition if we do // enter this kernel with N <= 3, we want to make sure that // "A" remains unpacked. // // If this check is removed it will result in the crash as // reported in CPUPL-587. // if ((N <= 3) || (((MR * K) << 2) > buffer_size)) { required_packing_A = 0; } else { #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_sgemm_small: Requesting mem pool block of size %lu\n", buffer_size); #endif // Get the buffer from the pool, if there is no pool with // required size, it will be created. bli_pba_acquire_m(&rntm, buffer_size, BLIS_BITVAL_BUFFER_FOR_A_BLOCK, &local_mem_buf_A_s); A_pack = bli_mem_buffer(&local_mem_buf_A_s); } /* * The computation loop runs for MRxN columns of C matrix, thus * accessing the MRxK A matrix data and KxNR B matrix data. * The computation is organized as inner loops of dimension MRxNR. */ // Process MR rows of C matrix at a time. for (row_idx = 0; (row_idx + (MR - 1)) < M; row_idx += MR) { col_idx_start = 0; tA_packed = A; row_idx_packed = row_idx; lda_packed = lda; // This is the part of the pack and compute optimization. // During the first column iteration, we store the accessed A matrix into // contiguous static memory. This helps to keep te A matrix in Cache and // aviods the TLB misses. if (required_packing_A) { col_idx = 0; //pointer math to point to proper memory tC = C + ldc * col_idx + row_idx; tB = B + tb_inc_col * col_idx; tA = A + row_idx; tA_packed = A_pack; #ifdef BLIS_ENABLE_PREFETCH _mm_prefetch((char*)(tC + 0), _MM_HINT_T0); _mm_prefetch((char*)(tC + 16), _MM_HINT_T0); _mm_prefetch((char*)(tC + ldc), _MM_HINT_T0); _mm_prefetch((char*)(tC + ldc + 16), _MM_HINT_T0); _mm_prefetch((char*)(tC + 2 * ldc), _MM_HINT_T0); _mm_prefetch((char*)(tC + 2 * ldc + 16), _MM_HINT_T0); #endif // clear scratch registers. ymm4 = _mm256_setzero_ps(); ymm5 = _mm256_setzero_ps(); ymm6 = _mm256_setzero_ps(); ymm7 = _mm256_setzero_ps(); ymm8 = _mm256_setzero_ps(); ymm9 = _mm256_setzero_ps(); ymm10 = _mm256_setzero_ps(); ymm11 = _mm256_setzero_ps(); ymm12 = _mm256_setzero_ps(); ymm13 = _mm256_setzero_ps(); ymm14 = _mm256_setzero_ps(); ymm15 = _mm256_setzero_ps(); for (k = 0; k < K; ++k) { // The inner loop broadcasts the B matrix data and // multiplies it with the A matrix. // This loop is processing MR x K ymm0 = _mm256_broadcast_ss(tB + tb_inc_col * 0); ymm1 = _mm256_broadcast_ss(tB + tb_inc_col * 1); ymm2 = _mm256_broadcast_ss(tB + tb_inc_col * 2); tB += tb_inc_row; //broadcasted matrix B elements are multiplied //with matrix A columns. ymm3 = _mm256_loadu_ps(tA); _mm256_storeu_ps(tA_packed, ymm3); // the packing of matrix A // ymm4 += ymm0 * ymm3; ymm4 = _mm256_fmadd_ps(ymm0, ymm3, ymm4); // ymm8 += ymm1 * ymm3; ymm8 = _mm256_fmadd_ps(ymm1, ymm3, ymm8); // ymm12 += ymm2 * ymm3; ymm12 = _mm256_fmadd_ps(ymm2, ymm3, ymm12); ymm3 = _mm256_loadu_ps(tA + 8); _mm256_storeu_ps(tA_packed + 8, ymm3); // the packing of matrix A // ymm5 += ymm0 * ymm3; ymm5 = _mm256_fmadd_ps(ymm0, ymm3, ymm5); // ymm9 += ymm1 * ymm3; ymm9 = _mm256_fmadd_ps(ymm1, ymm3, ymm9); // ymm13 += ymm2 * ymm3; ymm13 = _mm256_fmadd_ps(ymm2, ymm3, ymm13); ymm3 = _mm256_loadu_ps(tA + 16); _mm256_storeu_ps(tA_packed + 16, ymm3); // the packing of matrix A // ymm6 += ymm0 * ymm3; ymm6 = _mm256_fmadd_ps(ymm0, ymm3, ymm6); // ymm10 += ymm1 * ymm3; ymm10 = _mm256_fmadd_ps(ymm1, ymm3, ymm10); // ymm14 += ymm2 * ymm3; ymm14 = _mm256_fmadd_ps(ymm2, ymm3, ymm14); ymm3 = _mm256_loadu_ps(tA + 24); _mm256_storeu_ps(tA_packed + 24, ymm3); // the packing of matrix A // ymm7 += ymm0 * ymm3; ymm7 = _mm256_fmadd_ps(ymm0, ymm3, ymm7); // ymm11 += ymm1 * ymm3; ymm11 = _mm256_fmadd_ps(ymm1, ymm3, ymm11); // ymm15 += ymm2 * ymm3; ymm15 = _mm256_fmadd_ps(ymm2, ymm3, ymm15); tA += lda; tA_packed += MR; } // alpha, beta multiplication. ymm0 = _mm256_broadcast_ss(alpha_cast); //multiply A*B by alpha. ymm4 = _mm256_mul_ps(ymm4, ymm0); ymm5 = _mm256_mul_ps(ymm5, ymm0); ymm6 = _mm256_mul_ps(ymm6, ymm0); ymm7 = _mm256_mul_ps(ymm7, ymm0); ymm8 = _mm256_mul_ps(ymm8, ymm0); ymm9 = _mm256_mul_ps(ymm9, ymm0); ymm10 = _mm256_mul_ps(ymm10, ymm0); ymm11 = _mm256_mul_ps(ymm11, ymm0); ymm12 = _mm256_mul_ps(ymm12, ymm0); ymm13 = _mm256_mul_ps(ymm13, ymm0); ymm14 = _mm256_mul_ps(ymm14, ymm0); ymm15 = _mm256_mul_ps(ymm15, ymm0); if(is_beta_non_zero) { ymm1 = _mm256_broadcast_ss(beta_cast); // multiply C by beta and accumulate col 1. ymm2 = _mm256_loadu_ps(tC); ymm4 = _mm256_fmadd_ps(ymm2, ymm1, ymm4); ymm2 = _mm256_loadu_ps(tC + 8); ymm5 = _mm256_fmadd_ps(ymm2, ymm1, ymm5); ymm2 = _mm256_loadu_ps(tC + 16); ymm6 = _mm256_fmadd_ps(ymm2, ymm1, ymm6); ymm2 = _mm256_loadu_ps(tC + 24); ymm7 = _mm256_fmadd_ps(ymm2, ymm1, ymm7); float* ttC = tC +ldc; ymm2 = _mm256_loadu_ps(ttC); ymm8 = _mm256_fmadd_ps(ymm2, ymm1, ymm8); ymm2 = _mm256_loadu_ps(ttC + 8); ymm9 = _mm256_fmadd_ps(ymm2, ymm1, ymm9); ymm2 = _mm256_loadu_ps(ttC + 16); ymm10 = _mm256_fmadd_ps(ymm2, ymm1, ymm10); ymm2 = _mm256_loadu_ps(ttC + 24); ymm11 = _mm256_fmadd_ps(ymm2, ymm1, ymm11); ttC += ldc; ymm2 = _mm256_loadu_ps(ttC); ymm12 = _mm256_fmadd_ps(ymm2, ymm1, ymm12); ymm2 = _mm256_loadu_ps(ttC + 8); ymm13 = _mm256_fmadd_ps(ymm2, ymm1, ymm13); ymm2 = _mm256_loadu_ps(ttC + 16); ymm14 = _mm256_fmadd_ps(ymm2, ymm1, ymm14); ymm2 = _mm256_loadu_ps(ttC + 24); ymm15 = _mm256_fmadd_ps(ymm2, ymm1, ymm15); } _mm256_storeu_ps(tC, ymm4); _mm256_storeu_ps(tC + 8, ymm5); _mm256_storeu_ps(tC + 16, ymm6); _mm256_storeu_ps(tC + 24, ymm7); // multiply C by beta and accumulate, col 2. tC += ldc; _mm256_storeu_ps(tC, ymm8); _mm256_storeu_ps(tC + 8, ymm9); _mm256_storeu_ps(tC + 16, ymm10); _mm256_storeu_ps(tC + 24, ymm11); // multiply C by beta and accumulate, col 3. tC += ldc; _mm256_storeu_ps(tC, ymm12); _mm256_storeu_ps(tC + 8, ymm13); _mm256_storeu_ps(tC + 16, ymm14); _mm256_storeu_ps(tC + 24, ymm15); // modify the pointer arithematic to use packed A matrix. col_idx_start = NR; tA_packed = A_pack; row_idx_packed = 0; lda_packed = MR; } // Process NR columns of C matrix at a time. for (col_idx = col_idx_start; (col_idx + (NR - 1)) < N; col_idx += NR) { //pointer math to point to proper memory tC = C + ldc * col_idx + row_idx; tB = B + tb_inc_col * col_idx; tA = tA_packed + row_idx_packed; #ifdef BLIS_ENABLE_PREFETCH _mm_prefetch((char*)(tC + 0), _MM_HINT_T0); _mm_prefetch((char*)(tC + 16), _MM_HINT_T0); _mm_prefetch((char*)(tC + ldc), _MM_HINT_T0); _mm_prefetch((char*)(tC + ldc + 16), _MM_HINT_T0); _mm_prefetch((char*)(tC + 2 * ldc), _MM_HINT_T0); _mm_prefetch((char*)(tC + 2 * ldc + 16), _MM_HINT_T0); #endif // clear scratch registers. ymm4 = _mm256_setzero_ps(); ymm5 = _mm256_setzero_ps(); ymm6 = _mm256_setzero_ps(); ymm7 = _mm256_setzero_ps(); ymm8 = _mm256_setzero_ps(); ymm9 = _mm256_setzero_ps(); ymm10 = _mm256_setzero_ps(); ymm11 = _mm256_setzero_ps(); ymm12 = _mm256_setzero_ps(); ymm13 = _mm256_setzero_ps(); ymm14 = _mm256_setzero_ps(); ymm15 = _mm256_setzero_ps(); for (k = 0; k < K; ++k) { // The inner loop broadcasts the B matrix data and // multiplies it with the A matrix. // This loop is processing MR x K ymm0 = _mm256_broadcast_ss(tB + tb_inc_col * 0); ymm1 = _mm256_broadcast_ss(tB + tb_inc_col * 1); ymm2 = _mm256_broadcast_ss(tB + tb_inc_col * 2); tB += tb_inc_row; //broadcasted matrix B elements are multiplied //with matrix A columns. ymm3 = _mm256_loadu_ps(tA); // ymm4 += ymm0 * ymm3; ymm4 = _mm256_fmadd_ps(ymm0, ymm3, ymm4); // ymm8 += ymm1 * ymm3; ymm8 = _mm256_fmadd_ps(ymm1, ymm3, ymm8); // ymm12 += ymm2 * ymm3; ymm12 = _mm256_fmadd_ps(ymm2, ymm3, ymm12); ymm3 = _mm256_loadu_ps(tA + 8); // ymm5 += ymm0 * ymm3; ymm5 = _mm256_fmadd_ps(ymm0, ymm3, ymm5); // ymm9 += ymm1 * ymm3; ymm9 = _mm256_fmadd_ps(ymm1, ymm3, ymm9); // ymm13 += ymm2 * ymm3; ymm13 = _mm256_fmadd_ps(ymm2, ymm3, ymm13); ymm3 = _mm256_loadu_ps(tA + 16); // ymm6 += ymm0 * ymm3; ymm6 = _mm256_fmadd_ps(ymm0, ymm3, ymm6); // ymm10 += ymm1 * ymm3; ymm10 = _mm256_fmadd_ps(ymm1, ymm3, ymm10); // ymm14 += ymm2 * ymm3; ymm14 = _mm256_fmadd_ps(ymm2, ymm3, ymm14); ymm3 = _mm256_loadu_ps(tA + 24); // ymm7 += ymm0 * ymm3; ymm7 = _mm256_fmadd_ps(ymm0, ymm3, ymm7); // ymm11 += ymm1 * ymm3; ymm11 = _mm256_fmadd_ps(ymm1, ymm3, ymm11); // ymm15 += ymm2 * ymm3; ymm15 = _mm256_fmadd_ps(ymm2, ymm3, ymm15); tA += lda_packed; } // alpha, beta multiplication. ymm0 = _mm256_broadcast_ss(alpha_cast); //multiply A*B by alpha. ymm4 = _mm256_mul_ps(ymm4, ymm0); ymm5 = _mm256_mul_ps(ymm5, ymm0); ymm6 = _mm256_mul_ps(ymm6, ymm0); ymm7 = _mm256_mul_ps(ymm7, ymm0); ymm8 = _mm256_mul_ps(ymm8, ymm0); ymm9 = _mm256_mul_ps(ymm9, ymm0); ymm10 = _mm256_mul_ps(ymm10, ymm0); ymm11 = _mm256_mul_ps(ymm11, ymm0); ymm12 = _mm256_mul_ps(ymm12, ymm0); ymm13 = _mm256_mul_ps(ymm13, ymm0); ymm14 = _mm256_mul_ps(ymm14, ymm0); ymm15 = _mm256_mul_ps(ymm15, ymm0); if(is_beta_non_zero) { ymm1 = _mm256_broadcast_ss(beta_cast); // multiply C by beta and accumulate col 1. ymm2 = _mm256_loadu_ps(tC); ymm4 = _mm256_fmadd_ps(ymm2, ymm1, ymm4); ymm2 = _mm256_loadu_ps(tC + 8); ymm5 = _mm256_fmadd_ps(ymm2, ymm1, ymm5); ymm2 = _mm256_loadu_ps(tC + 16); ymm6 = _mm256_fmadd_ps(ymm2, ymm1, ymm6); ymm2 = _mm256_loadu_ps(tC + 24); ymm7 = _mm256_fmadd_ps(ymm2, ymm1, ymm7); float* ttC = tC +ldc; ymm2 = _mm256_loadu_ps(ttC); ymm8 = _mm256_fmadd_ps(ymm2, ymm1, ymm8); ymm2 = _mm256_loadu_ps(ttC + 8); ymm9 = _mm256_fmadd_ps(ymm2, ymm1, ymm9); ymm2 = _mm256_loadu_ps(ttC + 16); ymm10 = _mm256_fmadd_ps(ymm2, ymm1, ymm10); ymm2 = _mm256_loadu_ps(ttC + 24); ymm11 = _mm256_fmadd_ps(ymm2, ymm1, ymm11); ttC = ttC +ldc; ymm2 = _mm256_loadu_ps(ttC); ymm12 = _mm256_fmadd_ps(ymm2, ymm1, ymm12); ymm2 = _mm256_loadu_ps(ttC + 8); ymm13 = _mm256_fmadd_ps(ymm2, ymm1, ymm13); ymm2 = _mm256_loadu_ps(ttC + 16); ymm14 = _mm256_fmadd_ps(ymm2, ymm1, ymm14); ymm2 = _mm256_loadu_ps(ttC + 24); ymm15 = _mm256_fmadd_ps(ymm2, ymm1, ymm15); } _mm256_storeu_ps(tC, ymm4); _mm256_storeu_ps(tC + 8, ymm5); _mm256_storeu_ps(tC + 16, ymm6); _mm256_storeu_ps(tC + 24, ymm7); // multiply C by beta and accumulate, col 2. tC += ldc; _mm256_storeu_ps(tC, ymm8); _mm256_storeu_ps(tC + 8, ymm9); _mm256_storeu_ps(tC + 16, ymm10); _mm256_storeu_ps(tC + 24, ymm11); // multiply C by beta and accumulate, col 3. tC += ldc; _mm256_storeu_ps(tC, ymm12); _mm256_storeu_ps(tC + 8, ymm13); _mm256_storeu_ps(tC + 16, ymm14); _mm256_storeu_ps(tC + 24, ymm15); } n_remainder = N - col_idx; // if the N is not multiple of 3. // handling edge case. if (n_remainder == 2) { //pointer math to point to proper memory tC = C + ldc * col_idx + row_idx; tB = B + tb_inc_col * col_idx; tA = A + row_idx; // clear scratch registers. ymm8 = _mm256_setzero_ps(); ymm9 = _mm256_setzero_ps(); ymm10 = _mm256_setzero_ps(); ymm11 = _mm256_setzero_ps(); ymm12 = _mm256_setzero_ps(); ymm13 = _mm256_setzero_ps(); ymm14 = _mm256_setzero_ps(); ymm15 = _mm256_setzero_ps(); for (k = 0; k < K; ++k) { // The inner loop broadcasts the B matrix data and // multiplies it with the A matrix. ymm0 = _mm256_broadcast_ss(tB + tb_inc_col * 0); ymm1 = _mm256_broadcast_ss(tB + tb_inc_col * 1); tB += tb_inc_row; //broadcasted matrix B elements are multiplied //with matrix A columns. ymm3 = _mm256_loadu_ps(tA); ymm8 = _mm256_fmadd_ps(ymm0, ymm3, ymm8); ymm12 = _mm256_fmadd_ps(ymm1, ymm3, ymm12); ymm3 = _mm256_loadu_ps(tA + 8); ymm9 = _mm256_fmadd_ps(ymm0, ymm3, ymm9); ymm13 = _mm256_fmadd_ps(ymm1, ymm3, ymm13); ymm3 = _mm256_loadu_ps(tA + 16); ymm10 = _mm256_fmadd_ps(ymm0, ymm3, ymm10); ymm14 = _mm256_fmadd_ps(ymm1, ymm3, ymm14); ymm3 = _mm256_loadu_ps(tA + 24); ymm11 = _mm256_fmadd_ps(ymm0, ymm3, ymm11); ymm15 = _mm256_fmadd_ps(ymm1, ymm3, ymm15); tA += lda; } // alpha, beta multiplication. ymm0 = _mm256_broadcast_ss(alpha_cast); //multiply A*B by alpha. ymm8 = _mm256_mul_ps(ymm8, ymm0); ymm9 = _mm256_mul_ps(ymm9, ymm0); ymm10 = _mm256_mul_ps(ymm10, ymm0); ymm11 = _mm256_mul_ps(ymm11, ymm0); ymm12 = _mm256_mul_ps(ymm12, ymm0); ymm13 = _mm256_mul_ps(ymm13, ymm0); ymm14 = _mm256_mul_ps(ymm14, ymm0); ymm15 = _mm256_mul_ps(ymm15, ymm0); // multiply C by beta and accumulate, col 1. if(is_beta_non_zero) { ymm1 = _mm256_broadcast_ss(beta_cast); ymm2 = _mm256_loadu_ps(tC); ymm8 = _mm256_fmadd_ps(ymm2, ymm1, ymm8); ymm2 = _mm256_loadu_ps(tC + 8); ymm9 = _mm256_fmadd_ps(ymm2, ymm1, ymm9); ymm2 = _mm256_loadu_ps(tC + 16); ymm10 = _mm256_fmadd_ps(ymm2, ymm1, ymm10); ymm2 = _mm256_loadu_ps(tC + 24); ymm11 = _mm256_fmadd_ps(ymm2, ymm1, ymm11); float* ttC = tC +ldc; // multiply C by beta and accumulate, col 2. ymm2 = _mm256_loadu_ps(ttC); ymm12 = _mm256_fmadd_ps(ymm2, ymm1, ymm12); ymm2 = _mm256_loadu_ps(ttC + 8); ymm13 = _mm256_fmadd_ps(ymm2, ymm1, ymm13); ymm2 = _mm256_loadu_ps(ttC + 16); ymm14 = _mm256_fmadd_ps(ymm2, ymm1, ymm14); ymm2 = _mm256_loadu_ps(ttC + 24); ymm15 = _mm256_fmadd_ps(ymm2, ymm1, ymm15); } _mm256_storeu_ps(tC, ymm8); _mm256_storeu_ps(tC + 8, ymm9); _mm256_storeu_ps(tC + 16, ymm10); _mm256_storeu_ps(tC + 24, ymm11); tC += ldc; _mm256_storeu_ps(tC, ymm12); _mm256_storeu_ps(tC + 8, ymm13); _mm256_storeu_ps(tC + 16, ymm14); _mm256_storeu_ps(tC + 24, ymm15); col_idx += 2; } // if the N is not multiple of 3. // handling edge case. if (n_remainder == 1) { //pointer math to point to proper memory tC = C + ldc * col_idx + row_idx; tB = B + tb_inc_col * col_idx; tA = A + row_idx; // clear scratch registers. ymm12 = _mm256_setzero_ps(); ymm13 = _mm256_setzero_ps(); ymm14 = _mm256_setzero_ps(); ymm15 = _mm256_setzero_ps(); for (k = 0; k < K; ++k) { // The inner loop broadcasts the B matrix data and // multiplies it with the A matrix. ymm0 = _mm256_broadcast_ss(tB + tb_inc_col * 0); tB += tb_inc_row; //broadcasted matrix B elements are multiplied //with matrix A columns. ymm3 = _mm256_loadu_ps(tA); ymm12 = _mm256_fmadd_ps(ymm0, ymm3, ymm12); ymm3 = _mm256_loadu_ps(tA + 8); ymm13 = _mm256_fmadd_ps(ymm0, ymm3, ymm13); ymm3 = _mm256_loadu_ps(tA + 16); ymm14 = _mm256_fmadd_ps(ymm0, ymm3, ymm14); ymm3 = _mm256_loadu_ps(tA + 24); ymm15 = _mm256_fmadd_ps(ymm0, ymm3, ymm15); tA += lda; } // alpha, beta multiplication. ymm0 = _mm256_broadcast_ss(alpha_cast); //multiply A*B by alpha. ymm12 = _mm256_mul_ps(ymm12, ymm0); ymm13 = _mm256_mul_ps(ymm13, ymm0); ymm14 = _mm256_mul_ps(ymm14, ymm0); ymm15 = _mm256_mul_ps(ymm15, ymm0); if(is_beta_non_zero) { ymm1 = _mm256_broadcast_ss(beta_cast); // multiply C by beta and accumulate. ymm2 = _mm256_loadu_ps(tC + 0); ymm12 = _mm256_fmadd_ps(ymm2, ymm1, ymm12); ymm2 = _mm256_loadu_ps(tC + 8); ymm13 = _mm256_fmadd_ps(ymm2, ymm1, ymm13); ymm2 = _mm256_loadu_ps(tC + 16); ymm14 = _mm256_fmadd_ps(ymm2, ymm1, ymm14); ymm2 = _mm256_loadu_ps(tC + 24); ymm15 = _mm256_fmadd_ps(ymm2, ymm1, ymm15); } _mm256_storeu_ps(tC + 0, ymm12); _mm256_storeu_ps(tC + 8, ymm13); _mm256_storeu_ps(tC + 16, ymm14); _mm256_storeu_ps(tC + 24, ymm15); } } m_remainder = M - row_idx; if (m_remainder >= 24) { m_remainder -= 24; for (col_idx = 0; (col_idx + 2) < N; col_idx += 3) { //pointer math to point to proper memory tC = C + ldc * col_idx + row_idx; tB = B + tb_inc_col * col_idx; tA = A + row_idx; // clear scratch registers. ymm4 = _mm256_setzero_ps(); ymm5 = _mm256_setzero_ps(); ymm6 = _mm256_setzero_ps(); ymm8 = _mm256_setzero_ps(); ymm9 = _mm256_setzero_ps(); ymm10 = _mm256_setzero_ps(); ymm12 = _mm256_setzero_ps(); ymm13 = _mm256_setzero_ps(); ymm14 = _mm256_setzero_ps(); for (k = 0; k < K; ++k) { // The inner loop broadcasts the B matrix data and // multiplies it with the A matrix. ymm0 = _mm256_broadcast_ss(tB + tb_inc_col * 0); ymm1 = _mm256_broadcast_ss(tB + tb_inc_col * 1); ymm2 = _mm256_broadcast_ss(tB + tb_inc_col * 2); tB += tb_inc_row; //broadcasted matrix B elements are multiplied //with matrix A columns. ymm3 = _mm256_loadu_ps(tA); // ymm4 += ymm0 * ymm3; ymm4 = _mm256_fmadd_ps(ymm0, ymm3, ymm4); // ymm8 += ymm1 * ymm3; ymm8 = _mm256_fmadd_ps(ymm1, ymm3, ymm8); // ymm12 += ymm2 * ymm3; ymm12 = _mm256_fmadd_ps(ymm2, ymm3, ymm12); ymm3 = _mm256_loadu_ps(tA + 8); // ymm5 += ymm0 * ymm3; ymm5 = _mm256_fmadd_ps(ymm0, ymm3, ymm5); // ymm9 += ymm1 * ymm3; ymm9 = _mm256_fmadd_ps(ymm1, ymm3, ymm9); // ymm13 += ymm2 * ymm3; ymm13 = _mm256_fmadd_ps(ymm2, ymm3, ymm13); ymm3 = _mm256_loadu_ps(tA + 16); // ymm6 += ymm0 * ymm3; ymm6 = _mm256_fmadd_ps(ymm0, ymm3, ymm6); // ymm10 += ymm1 * ymm3; ymm10 = _mm256_fmadd_ps(ymm1, ymm3, ymm10); // ymm14 += ymm2 * ymm3; ymm14 = _mm256_fmadd_ps(ymm2, ymm3, ymm14); tA += lda; } // alpha, beta multiplication. ymm0 = _mm256_broadcast_ss(alpha_cast); //multiply A*B by alpha. ymm4 = _mm256_mul_ps(ymm4, ymm0); ymm5 = _mm256_mul_ps(ymm5, ymm0); ymm6 = _mm256_mul_ps(ymm6, ymm0); ymm8 = _mm256_mul_ps(ymm8, ymm0); ymm9 = _mm256_mul_ps(ymm9, ymm0); ymm10 = _mm256_mul_ps(ymm10, ymm0); ymm12 = _mm256_mul_ps(ymm12, ymm0); ymm13 = _mm256_mul_ps(ymm13, ymm0); ymm14 = _mm256_mul_ps(ymm14, ymm0); if(is_beta_non_zero) { ymm1 = _mm256_broadcast_ss(beta_cast); // multiply C by beta and accumulate. ymm2 = _mm256_loadu_ps(tC); ymm4 = _mm256_fmadd_ps(ymm2, ymm1, ymm4); ymm2 = _mm256_loadu_ps(tC + 8); ymm5 = _mm256_fmadd_ps(ymm2, ymm1, ymm5); ymm2 = _mm256_loadu_ps(tC + 16); ymm6 = _mm256_fmadd_ps(ymm2, ymm1, ymm6); float* ttC = tC +ldc; ymm2 = _mm256_loadu_ps(ttC); ymm8 = _mm256_fmadd_ps(ymm2, ymm1, ymm8); ymm2 = _mm256_loadu_ps(ttC + 8); ymm9 = _mm256_fmadd_ps(ymm2, ymm1, ymm9); ymm2 = _mm256_loadu_ps(ttC + 16); ymm10 = _mm256_fmadd_ps(ymm2, ymm1, ymm10); ttC += ldc; ymm2 = _mm256_loadu_ps(ttC); ymm12 = _mm256_fmadd_ps(ymm2, ymm1, ymm12); ymm2 = _mm256_loadu_ps(ttC + 8); ymm13 = _mm256_fmadd_ps(ymm2, ymm1, ymm13); ymm2 = _mm256_loadu_ps(ttC + 16); ymm14 = _mm256_fmadd_ps(ymm2, ymm1, ymm14); } _mm256_storeu_ps(tC, ymm4); _mm256_storeu_ps(tC + 8, ymm5); _mm256_storeu_ps(tC + 16, ymm6); // multiply C by beta and accumulate. tC += ldc; _mm256_storeu_ps(tC, ymm8); _mm256_storeu_ps(tC + 8, ymm9); _mm256_storeu_ps(tC + 16, ymm10); // multiply C by beta and accumulate. tC += ldc; _mm256_storeu_ps(tC, ymm12); _mm256_storeu_ps(tC + 8, ymm13); _mm256_storeu_ps(tC + 16, ymm14); } n_remainder = N - col_idx; // if the N is not multiple of 3. // handling edge case. if (n_remainder == 2) { //pointer math to point to proper memory tC = C + ldc * col_idx + row_idx; tB = B + tb_inc_col * col_idx; tA = A + row_idx; // clear scratch registers. ymm8 = _mm256_setzero_ps(); ymm9 = _mm256_setzero_ps(); ymm10 = _mm256_setzero_ps(); ymm12 = _mm256_setzero_ps(); ymm13 = _mm256_setzero_ps(); ymm14 = _mm256_setzero_ps(); for (k = 0; k < K; ++k) { // The inner loop broadcasts the B matrix data and // multiplies it with the A matrix. ymm0 = _mm256_broadcast_ss(tB + tb_inc_col * 0); ymm1 = _mm256_broadcast_ss(tB + tb_inc_col * 1); tB += tb_inc_row; //broadcasted matrix B elements are multiplied //with matrix A columns. ymm3 = _mm256_loadu_ps(tA); ymm8 = _mm256_fmadd_ps(ymm0, ymm3, ymm8); ymm12 = _mm256_fmadd_ps(ymm1, ymm3, ymm12); ymm3 = _mm256_loadu_ps(tA + 8); ymm9 = _mm256_fmadd_ps(ymm0, ymm3, ymm9); ymm13 = _mm256_fmadd_ps(ymm1, ymm3, ymm13); ymm3 = _mm256_loadu_ps(tA + 16); ymm10 = _mm256_fmadd_ps(ymm0, ymm3, ymm10); ymm14 = _mm256_fmadd_ps(ymm1, ymm3, ymm14); tA += lda; } // alpha, beta multiplication. ymm0 = _mm256_broadcast_ss(alpha_cast); //multiply A*B by alpha. ymm8 = _mm256_mul_ps(ymm8, ymm0); ymm9 = _mm256_mul_ps(ymm9, ymm0); ymm10 = _mm256_mul_ps(ymm10, ymm0); ymm12 = _mm256_mul_ps(ymm12, ymm0); ymm13 = _mm256_mul_ps(ymm13, ymm0); ymm14 = _mm256_mul_ps(ymm14, ymm0); if(is_beta_non_zero) { ymm1 = _mm256_broadcast_ss(beta_cast); // multiply C by beta and accumulate. ymm2 = _mm256_loadu_ps(tC); ymm8 = _mm256_fmadd_ps(ymm2, ymm1, ymm8); ymm2 = _mm256_loadu_ps(tC + 8); ymm9 = _mm256_fmadd_ps(ymm2, ymm1, ymm9); ymm2 = _mm256_loadu_ps(tC + 16); ymm10 = _mm256_fmadd_ps(ymm2, ymm1, ymm10); float* ttC = tC +ldc; // multiply C by beta and accumulate. ymm2 = _mm256_loadu_ps(ttC); ymm12 = _mm256_fmadd_ps(ymm2, ymm1, ymm12); ymm2 = _mm256_loadu_ps(ttC + 8); ymm13 = _mm256_fmadd_ps(ymm2, ymm1, ymm13); ymm2 = _mm256_loadu_ps(ttC + 16); ymm14 = _mm256_fmadd_ps(ymm2, ymm1, ymm14); } _mm256_storeu_ps(tC, ymm8); _mm256_storeu_ps(tC + 8, ymm9); _mm256_storeu_ps(tC + 16, ymm10); tC += ldc; _mm256_storeu_ps(tC, ymm12); _mm256_storeu_ps(tC + 8, ymm13); _mm256_storeu_ps(tC + 16, ymm14); col_idx += 2; } // if the N is not multiple of 3. // handling edge case. if (n_remainder == 1) { //pointer math to point to proper memory tC = C + ldc * col_idx + row_idx; tB = B + tb_inc_col * col_idx; tA = A + row_idx; // clear scratch registers. ymm12 = _mm256_setzero_ps(); ymm13 = _mm256_setzero_ps(); ymm14 = _mm256_setzero_ps(); for (k = 0; k < K; ++k) { // The inner loop broadcasts the B matrix data and // multiplies it with the A matrix. ymm0 = _mm256_broadcast_ss(tB + tb_inc_col * 0); tB += tb_inc_row; //broadcasted matrix B elements are multiplied //with matrix A columns. ymm3 = _mm256_loadu_ps(tA); ymm12 = _mm256_fmadd_ps(ymm0, ymm3, ymm12); ymm3 = _mm256_loadu_ps(tA + 8); ymm13 = _mm256_fmadd_ps(ymm0, ymm3, ymm13); ymm3 = _mm256_loadu_ps(tA + 16); ymm14 = _mm256_fmadd_ps(ymm0, ymm3, ymm14); tA += lda; } // alpha, beta multiplication. ymm0 = _mm256_broadcast_ss(alpha_cast); //multiply A*B by alpha. ymm12 = _mm256_mul_ps(ymm12, ymm0); ymm13 = _mm256_mul_ps(ymm13, ymm0); ymm14 = _mm256_mul_ps(ymm14, ymm0); if(is_beta_non_zero) { ymm1 = _mm256_broadcast_ss(beta_cast); // multiply C by beta and accumulate. ymm2 = _mm256_loadu_ps(tC + 0); ymm12 = _mm256_fmadd_ps(ymm2, ymm1, ymm12); ymm2 = _mm256_loadu_ps(tC + 8); ymm13 = _mm256_fmadd_ps(ymm2, ymm1, ymm13); ymm2 = _mm256_loadu_ps(tC + 16); ymm14 = _mm256_fmadd_ps(ymm2, ymm1, ymm14); } _mm256_storeu_ps(tC + 0, ymm12); _mm256_storeu_ps(tC + 8, ymm13); _mm256_storeu_ps(tC + 16, ymm14); } row_idx += 24; } if (m_remainder >= 16) { m_remainder -= 16; for (col_idx = 0; (col_idx + 2) < N; col_idx += 3) { //pointer math to point to proper memory tC = C + ldc * col_idx + row_idx; tB = B + tb_inc_col * col_idx; tA = A + row_idx; // clear scratch registers. ymm4 = _mm256_setzero_ps(); ymm5 = _mm256_setzero_ps(); ymm6 = _mm256_setzero_ps(); ymm7 = _mm256_setzero_ps(); ymm8 = _mm256_setzero_ps(); ymm9 = _mm256_setzero_ps(); for (k = 0; k < K; ++k) { // The inner loop broadcasts the B matrix data and // multiplies it with the A matrix. ymm0 = _mm256_broadcast_ss(tB + tb_inc_col * 0); ymm1 = _mm256_broadcast_ss(tB + tb_inc_col * 1); ymm2 = _mm256_broadcast_ss(tB + tb_inc_col * 2); tB += tb_inc_row; //broadcasted matrix B elements are multiplied //with matrix A columns. ymm3 = _mm256_loadu_ps(tA); ymm4 = _mm256_fmadd_ps(ymm0, ymm3, ymm4); ymm6 = _mm256_fmadd_ps(ymm1, ymm3, ymm6); ymm8 = _mm256_fmadd_ps(ymm2, ymm3, ymm8); ymm3 = _mm256_loadu_ps(tA + 8); ymm5 = _mm256_fmadd_ps(ymm0, ymm3, ymm5); ymm7 = _mm256_fmadd_ps(ymm1, ymm3, ymm7); ymm9 = _mm256_fmadd_ps(ymm2, ymm3, ymm9); tA += lda; } // alpha, beta multiplication. ymm0 = _mm256_broadcast_ss(alpha_cast); //multiply A*B by alpha. ymm4 = _mm256_mul_ps(ymm4, ymm0); ymm5 = _mm256_mul_ps(ymm5, ymm0); ymm6 = _mm256_mul_ps(ymm6, ymm0); ymm7 = _mm256_mul_ps(ymm7, ymm0); ymm8 = _mm256_mul_ps(ymm8, ymm0); ymm9 = _mm256_mul_ps(ymm9, ymm0); if(is_beta_non_zero) { ymm1 = _mm256_broadcast_ss(beta_cast); // multiply C by beta and accumulate. ymm2 = _mm256_loadu_ps(tC); ymm4 = _mm256_fmadd_ps(ymm2, ymm1, ymm4); ymm2 = _mm256_loadu_ps(tC + 8); ymm5 = _mm256_fmadd_ps(ymm2, ymm1, ymm5); float* ttC = tC + ldc; ymm2 = _mm256_loadu_ps(ttC); ymm6 = _mm256_fmadd_ps(ymm2, ymm1, ymm6); ymm2 = _mm256_loadu_ps(ttC + 8); ymm7 = _mm256_fmadd_ps(ymm2, ymm1, ymm7); ttC += ldc; ymm2 = _mm256_loadu_ps(ttC); ymm8 = _mm256_fmadd_ps(ymm2, ymm1, ymm8); ymm2 = _mm256_loadu_ps(ttC + 8); ymm9 = _mm256_fmadd_ps(ymm2, ymm1, ymm9); } _mm256_storeu_ps(tC, ymm4); _mm256_storeu_ps(tC + 8, ymm5); // multiply C by beta and accumulate. tC += ldc; _mm256_storeu_ps(tC, ymm6); _mm256_storeu_ps(tC + 8, ymm7); // multiply C by beta and accumulate. tC += ldc; _mm256_storeu_ps(tC, ymm8); _mm256_storeu_ps(tC + 8, ymm9); } n_remainder = N - col_idx; // if the N is not multiple of 3. // handling edge case. if (n_remainder == 2) { //pointer math to point to proper memory tC = C + ldc * col_idx + row_idx; tB = B + tb_inc_col * col_idx; tA = A + row_idx; // clear scratch registers. ymm4 = _mm256_setzero_ps(); ymm5 = _mm256_setzero_ps(); ymm6 = _mm256_setzero_ps(); ymm7 = _mm256_setzero_ps(); for (k = 0; k < K; ++k) { // The inner loop broadcasts the B matrix data and // multiplies it with the A matrix. ymm0 = _mm256_broadcast_ss(tB + tb_inc_col * 0); ymm1 = _mm256_broadcast_ss(tB + tb_inc_col * 1); tB += tb_inc_row; //broadcasted matrix B elements are multiplied //with matrix A columns. ymm3 = _mm256_loadu_ps(tA); ymm4 = _mm256_fmadd_ps(ymm0, ymm3, ymm4); ymm6 = _mm256_fmadd_ps(ymm1, ymm3, ymm6); ymm3 = _mm256_loadu_ps(tA + 8); ymm5 = _mm256_fmadd_ps(ymm0, ymm3, ymm5); ymm7 = _mm256_fmadd_ps(ymm1, ymm3, ymm7); tA += lda; } // alpha, beta multiplication. ymm0 = _mm256_broadcast_ss(alpha_cast); //multiply A*B by alpha. ymm4 = _mm256_mul_ps(ymm4, ymm0); ymm5 = _mm256_mul_ps(ymm5, ymm0); ymm6 = _mm256_mul_ps(ymm6, ymm0); ymm7 = _mm256_mul_ps(ymm7, ymm0); if(is_beta_non_zero) { ymm1 = _mm256_broadcast_ss(beta_cast); // multiply C by beta and accumulate. ymm2 = _mm256_loadu_ps(tC); ymm4 = _mm256_fmadd_ps(ymm2, ymm1, ymm4); ymm2 = _mm256_loadu_ps(tC + 8); ymm5 = _mm256_fmadd_ps(ymm2, ymm1, ymm5); float* ttC = tC + ldc; ymm2 = _mm256_loadu_ps(ttC); ymm6 = _mm256_fmadd_ps(ymm2, ymm1, ymm6); ymm2 = _mm256_loadu_ps(ttC + 8); ymm7 = _mm256_fmadd_ps(ymm2, ymm1, ymm7); } _mm256_storeu_ps(tC, ymm4); _mm256_storeu_ps(tC + 8, ymm5); // multiply C by beta and accumulate. tC += ldc; _mm256_storeu_ps(tC, ymm6); _mm256_storeu_ps(tC + 8, ymm7); col_idx += 2; } // if the N is not multiple of 3. // handling edge case. if (n_remainder == 1) { //pointer math to point to proper memory tC = C + ldc * col_idx + row_idx; tB = B + tb_inc_col * col_idx; tA = A + row_idx; ymm4 = _mm256_setzero_ps(); ymm5 = _mm256_setzero_ps(); for (k = 0; k < K; ++k) { // The inner loop broadcasts the B matrix data and // multiplies it with the A matrix. ymm0 = _mm256_broadcast_ss(tB + tb_inc_col * 0); tB += tb_inc_row; //broadcasted matrix B elements are multiplied //with matrix A columns. ymm3 = _mm256_loadu_ps(tA); ymm4 = _mm256_fmadd_ps(ymm0, ymm3, ymm4); ymm3 = _mm256_loadu_ps(tA + 8); ymm5 = _mm256_fmadd_ps(ymm0, ymm3, ymm5); tA += lda; } // alpha, beta multiplication. ymm0 = _mm256_broadcast_ss(alpha_cast); ymm4 = _mm256_mul_ps(ymm4, ymm0); ymm5 = _mm256_mul_ps(ymm5, ymm0); // multiply C by beta and accumulate. if(is_beta_non_zero) { ymm1 = _mm256_broadcast_ss(beta_cast); ymm2 = _mm256_loadu_ps(tC); ymm4 = _mm256_fmadd_ps(ymm2, ymm1, ymm4); ymm2 = _mm256_loadu_ps(tC + 8); ymm5 = _mm256_fmadd_ps(ymm2, ymm1, ymm5); } _mm256_storeu_ps(tC, ymm4); _mm256_storeu_ps(tC + 8, ymm5); } row_idx += 16; } if (m_remainder >= 8) { m_remainder -= 8; for (col_idx = 0; (col_idx + 2) < N; col_idx += 3) { //pointer math to point to proper memory tC = C + ldc * col_idx + row_idx; tB = B + tb_inc_col * col_idx; tA = A + row_idx; // clear scratch registers. ymm4 = _mm256_setzero_ps(); ymm5 = _mm256_setzero_ps(); ymm6 = _mm256_setzero_ps(); for (k = 0; k < K; ++k) { // The inner loop broadcasts the B matrix data and // multiplies it with the A matrix. ymm0 = _mm256_broadcast_ss(tB + tb_inc_col * 0); ymm1 = _mm256_broadcast_ss(tB + tb_inc_col * 1); ymm2 = _mm256_broadcast_ss(tB + tb_inc_col * 2); tB += tb_inc_row; //broadcasted matrix B elements are multiplied //with matrix A columns. ymm3 = _mm256_loadu_ps(tA); ymm4 = _mm256_fmadd_ps(ymm0, ymm3, ymm4); ymm5 = _mm256_fmadd_ps(ymm1, ymm3, ymm5); ymm6 = _mm256_fmadd_ps(ymm2, ymm3, ymm6); tA += lda; } // alpha, beta multiplication. ymm0 = _mm256_broadcast_ss(alpha_cast); //multiply A*B by alpha. ymm4 = _mm256_mul_ps(ymm4, ymm0); ymm5 = _mm256_mul_ps(ymm5, ymm0); ymm6 = _mm256_mul_ps(ymm6, ymm0); if(is_beta_non_zero) { ymm1 = _mm256_broadcast_ss(beta_cast); ymm2 = _mm256_loadu_ps(tC); ymm4 = _mm256_fmadd_ps(ymm2, ymm1, ymm4); ymm2 = _mm256_loadu_ps(tC + ldc); ymm5 = _mm256_fmadd_ps(ymm2, ymm1, ymm5); ymm2 = _mm256_loadu_ps(tC + 2*ldc); ymm6 = _mm256_fmadd_ps(ymm2, ymm1, ymm6); } _mm256_storeu_ps(tC, ymm4); // multiply C by beta and accumulate. tC += ldc; _mm256_storeu_ps(tC, ymm5); // multiply C by beta and accumulate. tC += ldc; _mm256_storeu_ps(tC, ymm6); } n_remainder = N - col_idx; // if the N is not multiple of 3. // handling edge case. if (n_remainder == 2) { //pointer math to point to proper memory tC = C + ldc * col_idx + row_idx; tB = B + tb_inc_col * col_idx; tA = A + row_idx; ymm4 = _mm256_setzero_ps(); ymm5 = _mm256_setzero_ps(); for (k = 0; k < K; ++k) { // The inner loop broadcasts the B matrix data and // multiplies it with the A matrix. ymm0 = _mm256_broadcast_ss(tB + tb_inc_col * 0); ymm1 = _mm256_broadcast_ss(tB + tb_inc_col * 1); tB += tb_inc_row; //broadcasted matrix B elements are multiplied //with matrix A columns. ymm3 = _mm256_loadu_ps(tA); ymm4 = _mm256_fmadd_ps(ymm0, ymm3, ymm4); ymm5 = _mm256_fmadd_ps(ymm1, ymm3, ymm5); tA += lda; } // alpha, beta multiplication. ymm0 = _mm256_broadcast_ss(alpha_cast); //multiply A*B by alpha. ymm4 = _mm256_mul_ps(ymm4, ymm0); ymm5 = _mm256_mul_ps(ymm5, ymm0); if(is_beta_non_zero) { ymm1 = _mm256_broadcast_ss(beta_cast); // multiply C by beta and accumulate. ymm2 = _mm256_loadu_ps(tC); ymm4 = _mm256_fmadd_ps(ymm2, ymm1, ymm4); ymm2 = _mm256_loadu_ps(tC + ldc); ymm5 = _mm256_fmadd_ps(ymm2, ymm1, ymm5); } _mm256_storeu_ps(tC, ymm4); // multiply C by beta and accumulate. tC += ldc; _mm256_storeu_ps(tC, ymm5); col_idx += 2; } // if the N is not multiple of 3. // handling edge case. if (n_remainder == 1) { //pointer math to point to proper memory tC = C + ldc * col_idx + row_idx; tB = B + tb_inc_col * col_idx; tA = A + row_idx; ymm4 = _mm256_setzero_ps(); for (k = 0; k < K; ++k) { // The inner loop broadcasts the B matrix data and // multiplies it with the A matrix. ymm0 = _mm256_broadcast_ss(tB + tb_inc_col * 0); tB += tb_inc_row; //broadcasted matrix B elements are multiplied //with matrix A columns. ymm3 = _mm256_loadu_ps(tA); ymm4 = _mm256_fmadd_ps(ymm0, ymm3, ymm4); tA += lda; } // alpha, beta multiplication. ymm0 = _mm256_broadcast_ss(alpha_cast); ymm4 = _mm256_mul_ps(ymm4, ymm0); if(is_beta_non_zero) { ymm1 = _mm256_broadcast_ss(beta_cast); // multiply C by beta and accumulate. ymm2 = _mm256_loadu_ps(tC); ymm4 = _mm256_fmadd_ps(ymm2, ymm1, ymm4); } _mm256_storeu_ps(tC, ymm4); } row_idx += 8; } // M is not a multiple of 32. // The handling of edge case where the remainder // dimension is less than 8. The padding takes place // to handle this case. if ((m_remainder) && (lda > 7)) { float f_temp[8] = {0.0}; for (col_idx = 0; (col_idx + 2) < N; col_idx += 3) { //pointer math to point to proper memory tC = C + ldc * col_idx + row_idx; tB = B + tb_inc_col * col_idx; tA = A + row_idx; // clear scratch registers. ymm5 = _mm256_setzero_ps(); ymm7 = _mm256_setzero_ps(); ymm9 = _mm256_setzero_ps(); for (k = 0; k < (K - 1); ++k) { // The inner loop broadcasts the B matrix data and // multiplies it with the A matrix. ymm0 = _mm256_broadcast_ss(tB + tb_inc_col * 0); ymm1 = _mm256_broadcast_ss(tB + tb_inc_col * 1); ymm2 = _mm256_broadcast_ss(tB + tb_inc_col * 2); tB += tb_inc_row; //broadcasted matrix B elements are multiplied //with matrix A columns. ymm3 = _mm256_loadu_ps(tA); ymm5 = _mm256_fmadd_ps(ymm0, ymm3, ymm5); ymm7 = _mm256_fmadd_ps(ymm1, ymm3, ymm7); ymm9 = _mm256_fmadd_ps(ymm2, ymm3, ymm9); tA += lda; } // alpha, beta multiplication. ymm0 = _mm256_broadcast_ss(tB + tb_inc_col * 0); ymm1 = _mm256_broadcast_ss(tB + tb_inc_col * 1); ymm2 = _mm256_broadcast_ss(tB + tb_inc_col * 2); tB += tb_inc_row; for (int i = 0; i < m_remainder; i++) { f_temp[i] = tA[i]; } ymm3 = _mm256_loadu_ps(f_temp); ymm5 = _mm256_fmadd_ps(ymm0, ymm3, ymm5); ymm7 = _mm256_fmadd_ps(ymm1, ymm3, ymm7); ymm9 = _mm256_fmadd_ps(ymm2, ymm3, ymm9); ymm0 = _mm256_broadcast_ss(alpha_cast); ymm1 = _mm256_broadcast_ss(beta_cast); //multiply A*B by alpha. ymm5 = _mm256_mul_ps(ymm5, ymm0); ymm7 = _mm256_mul_ps(ymm7, ymm0); ymm9 = _mm256_mul_ps(ymm9, ymm0); for (int i = 0; i < m_remainder; i++) { f_temp[i] = tC[i]; } ymm2 = _mm256_loadu_ps(f_temp); if(is_beta_non_zero){ ymm5 = _mm256_fmadd_ps(ymm2, ymm1, ymm5); } _mm256_storeu_ps(f_temp, ymm5); for (int i = 0; i < m_remainder; i++) { tC[i] = f_temp[i]; } tC += ldc; for (int i = 0; i < m_remainder; i++) { f_temp[i] = tC[i]; } ymm2 = _mm256_loadu_ps(f_temp); if(is_beta_non_zero){ ymm7 = _mm256_fmadd_ps(ymm2, ymm1, ymm7); } _mm256_storeu_ps(f_temp, ymm7); for (int i = 0; i < m_remainder; i++) { tC[i] = f_temp[i]; } tC += ldc; for (int i = 0; i < m_remainder; i++) { f_temp[i] = tC[i]; } ymm2 = _mm256_loadu_ps(f_temp); if(is_beta_non_zero){ ymm9 = _mm256_fmadd_ps(ymm2, ymm1, ymm9); } _mm256_storeu_ps(f_temp, ymm9); for (int i = 0; i < m_remainder; i++) { tC[i] = f_temp[i]; } } n_remainder = N - col_idx; // if the N is not multiple of 3. // handling edge case. if (n_remainder == 2) { //pointer math to point to proper memory tC = C + ldc * col_idx + row_idx; tB = B + tb_inc_col * col_idx; tA = A + row_idx; ymm5 = _mm256_setzero_ps(); ymm7 = _mm256_setzero_ps(); for (k = 0; k < (K - 1); ++k) { // The inner loop broadcasts the B matrix data and // multiplies it with the A matrix. ymm0 = _mm256_broadcast_ss(tB + tb_inc_col * 0); ymm1 = _mm256_broadcast_ss(tB + tb_inc_col * 1); tB += tb_inc_row; ymm3 = _mm256_loadu_ps(tA); ymm5 = _mm256_fmadd_ps(ymm0, ymm3, ymm5); ymm7 = _mm256_fmadd_ps(ymm1, ymm3, ymm7); tA += lda; } ymm0 = _mm256_broadcast_ss(tB + tb_inc_col * 0); ymm1 = _mm256_broadcast_ss(tB + tb_inc_col * 1); tB += tb_inc_row; for (int i = 0; i < m_remainder; i++) { f_temp[i] = tA[i]; } ymm3 = _mm256_loadu_ps(f_temp); ymm5 = _mm256_fmadd_ps(ymm0, ymm3, ymm5); ymm7 = _mm256_fmadd_ps(ymm1, ymm3, ymm7); ymm0 = _mm256_broadcast_ss(alpha_cast); ymm1 = _mm256_broadcast_ss(beta_cast); ymm5 = _mm256_mul_ps(ymm5, ymm0); ymm7 = _mm256_mul_ps(ymm7, ymm0); for (int i = 0; i < m_remainder; i++) { f_temp[i] = tC[i]; } ymm2 = _mm256_loadu_ps(f_temp); if(is_beta_non_zero){ ymm5 = _mm256_fmadd_ps(ymm2, ymm1, ymm5); } _mm256_storeu_ps(f_temp, ymm5); for (int i = 0; i < m_remainder; i++) { tC[i] = f_temp[i]; } tC += ldc; for (int i = 0; i < m_remainder; i++) { f_temp[i] = tC[i]; } ymm2 = _mm256_loadu_ps(f_temp); if(is_beta_non_zero){ ymm7 = _mm256_fmadd_ps(ymm2, ymm1, ymm7); } _mm256_storeu_ps(f_temp, ymm7); for (int i = 0; i < m_remainder; i++) { tC[i] = f_temp[i]; } } // if the N is not multiple of 3. // handling edge case. if (n_remainder == 1) { //pointer math to point to proper memory tC = C + ldc * col_idx + row_idx; tB = B + tb_inc_col * col_idx; tA = A + row_idx; ymm5 = _mm256_setzero_ps(); for (k = 0; k < (K - 1); ++k) { // The inner loop broadcasts the B matrix data and // multiplies it with the A matrix. ymm0 = _mm256_broadcast_ss(tB + tb_inc_col * 0); tB += tb_inc_row; ymm3 = _mm256_loadu_ps(tA); ymm5 = _mm256_fmadd_ps(ymm0, ymm3, ymm5); tA += lda; } ymm0 = _mm256_broadcast_ss(tB + tb_inc_col * 0); tB += tb_inc_row; for (int i = 0; i < m_remainder; i++) { f_temp[i] = tA[i]; } ymm3 = _mm256_loadu_ps(f_temp); ymm5 = _mm256_fmadd_ps(ymm0, ymm3, ymm5); ymm0 = _mm256_broadcast_ss(alpha_cast); // multiply C by beta and accumulate. ymm5 = _mm256_mul_ps(ymm5, ymm0); for (int i = 0; i < m_remainder; i++) { f_temp[i] = tC[i]; } ymm2 = _mm256_loadu_ps(f_temp); if(is_beta_non_zero){ ymm1 = _mm256_broadcast_ss(beta_cast); ymm5 = _mm256_fmadd_ps(ymm2, ymm1, ymm5); } _mm256_storeu_ps(f_temp, ymm5); for (int i = 0; i < m_remainder; i++) { tC[i] = f_temp[i]; } } m_remainder = 0; } if (m_remainder) { float result; for (; row_idx < M; row_idx += 1) { for (col_idx = 0; col_idx < N; col_idx += 1) { //pointer math to point to proper memory tC = C + ldc * col_idx + row_idx; tB = B + tb_inc_col * col_idx; tA = A + row_idx; result = 0; for (k = 0; k < K; ++k) { result += (*tA) * (*tB); tA += lda; tB += tb_inc_row; } result *= (*alpha_cast); if(is_beta_non_zero){ (*tC) = (*tC) * (*beta_cast) + result; }else{ (*tC) = result; } } } } // Return the buffer to pool if ((required_packing_A == 1) && bli_mem_is_alloc( &local_mem_buf_A_s) ) { #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_sgemm_small(): releasing mem pool block\n" ); #endif bli_pba_release(&rntm, &local_mem_buf_A_s); } AOCL_DTL_TRACE_EXIT(AOCL_DTL_LEVEL_TRACE_7); return BLIS_SUCCESS; } else { AOCL_DTL_TRACE_EXIT_ERR( AOCL_DTL_LEVEL_INFO, "Invalid dimesions for small gemm." ); return BLIS_NONCONFORMAL_DIMENSIONS; } }; static err_t bli_dgemm_small ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, cntl_t* cntl ) { AOCL_DTL_TRACE_ENTRY(AOCL_DTL_LEVEL_INFO); gint_t M = bli_obj_length( c ); // number of rows of Matrix C gint_t N = bli_obj_width( c ); // number of columns of Matrix C gint_t K = bli_obj_width( a ); // number of columns of OP(A), will be updated if OP(A) is Transpose(A) . gint_t L = M * N; // when N is equal to 1 call GEMV instead of GEMM if (N == 1) { bli_gemv ( alpha, a, b, beta, c ); AOCL_DTL_TRACE_EXIT(AOCL_DTL_LEVEL_INFO); return BLIS_SUCCESS; } if (N<3) //Implemenation assumes that N is atleast 3. { AOCL_DTL_TRACE_EXIT_ERR( AOCL_DTL_LEVEL_INFO, "N < 3, cannot be processed by small gemm" ); return BLIS_NOT_YET_IMPLEMENTED; } #ifdef BLIS_ENABLE_SMALL_MATRIX_ROME if( (L && K) && ((K < D_BLIS_SMALL_MATRIX_K_THRES_ROME) || ((N < BLIS_SMALL_MATRIX_THRES_ROME) && (K < BLIS_SMALL_MATRIX_THRES_ROME)))) #else if ((((L) < (D_BLIS_SMALL_MATRIX_THRES * D_BLIS_SMALL_MATRIX_THRES)) || ((M < D_BLIS_SMALL_M_RECT_MATRIX_THRES) && (K < D_BLIS_SMALL_K_RECT_MATRIX_THRES))) && ((L!=0) && (K!=0))) #endif { guint_t lda = bli_obj_col_stride( a ); // column stride of matrix OP(A), where OP(A) is Transpose(A) if transA enabled. guint_t ldb = bli_obj_col_stride( b ); // column stride of matrix OP(B), where OP(B) is Transpose(B) if transB enabled. guint_t ldc = bli_obj_col_stride( c ); // column stride of matrix C guint_t row_idx, col_idx, k; double *A = bli_obj_buffer_at_off(a); // pointer to elements of Matrix A double *B = bli_obj_buffer_at_off(b); // pointer to elements of Matrix B double *C = bli_obj_buffer_at_off(c); // pointer to elements of Matrix C double *tA = A, *tB = B, *tC = C;//, *tA_pack; double *tA_packed; // temprorary pointer to hold packed A memory pointer guint_t row_idx_packed; //packed A memory row index guint_t lda_packed; //lda of packed A guint_t col_idx_start; //starting index after A matrix is packed. dim_t tb_inc_row = 1; // row stride of matrix B dim_t tb_inc_col = ldb; // column stride of matrix B __m256d ymm4, ymm5, ymm6, ymm7; __m256d ymm8, ymm9, ymm10, ymm11; __m256d ymm12, ymm13, ymm14, ymm15; __m256d ymm0, ymm1, ymm2, ymm3; gint_t n_remainder; // If the N is non multiple of 3.(N%3) gint_t m_remainder; // If the M is non multiple of 16.(M%16) double *alpha_cast, *beta_cast; // alpha, beta multiples alpha_cast = bli_obj_buffer_for_1x1(BLIS_DOUBLE, alpha); beta_cast = bli_obj_buffer_for_1x1(BLIS_DOUBLE, beta); gint_t required_packing_A = 1; mem_t local_mem_buf_A_s; double *D_A_pack = NULL; rntm_t rntm; //update the pointer math if matrix B needs to be transposed. if (bli_obj_has_trans( b )) { tb_inc_col = 1; //switch row and column strides tb_inc_row = ldb; } //checking whether beta value is zero. //if true, we should perform C=alpha * A*B operation //instead of C = beta * C + alpha * (A * B) bool is_beta_non_zero = 0; if(!bli_obj_equals(beta, &BLIS_ZERO)) is_beta_non_zero = 1; /* * This function was using global array to pack part of A input when needed. * However, using this global array make the function non-reentrant. * Instead of using a global array we should allocate buffer for each invocation. * Since the buffer size is too big or stack and doing malloc every time will be too expensive, * better approach is to get the buffer from the pre-allocated pool and return * it the pool once we are doing. * * In order to get the buffer from pool, we need access to memory broker, * currently this function is not invoked in such a way that it can receive * the memory broker (via rntm). Following hack will get the global memory * broker that can be use it to access the pool. * * Note there will be memory allocation at least on first innovation * as there will not be any pool created for this size. * Subsequent invocations will just reuse the buffer from the pool. */ bli_rntm_init_from_global( &rntm ); bli_rntm_set_num_threads_only( 1, &rntm ); bli_pba_rntm_set_pba( &rntm ); // Get the current size of the buffer pool for A block packing. // We will use the same size to avoid pool re-initliazaton siz_t buffer_size = bli_pool_block_size( bli_pba_pool(bli_packbuf_index(BLIS_BITVAL_BUFFER_FOR_A_BLOCK), bli_rntm_pba(&rntm))); // // This kernel assumes that "A" will be unpackged if N <= 3. // Usually this range (N <= 3) is handled by SUP, however, // if SUP is disabled or for any other condition if we do // enter this kernel with N <= 3, we want to make sure that // "A" remains unpacked. // // If this check is removed it will result in the crash as // reported in CPUPL-587. // if ((N <= 3) || ((D_MR * K) << 3) > buffer_size) { required_packing_A = 0; } if (required_packing_A == 1) { #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_dgemm_small: Requesting mem pool block of size %lu\n", buffer_size); #endif // Get the buffer from the pool. bli_pba_acquire_m(&rntm, buffer_size, BLIS_BITVAL_BUFFER_FOR_A_BLOCK, &local_mem_buf_A_s); D_A_pack = bli_mem_buffer(&local_mem_buf_A_s); } /* * The computation loop runs for D_MRxN columns of C matrix, thus * accessing the D_MRxK A matrix data and KxNR B matrix data. * The computation is organized as inner loops of dimension D_MRxNR. */ // Process D_MR rows of C matrix at a time. for (row_idx = 0; (row_idx + (D_MR - 1)) < M; row_idx += D_MR) { col_idx_start = 0; tA_packed = A; row_idx_packed = row_idx; lda_packed = lda; // This is the part of the pack and compute optimization. // During the first column iteration, we store the accessed A matrix into // contiguous static memory. This helps to keep te A matrix in Cache and // aviods the TLB misses. if (required_packing_A) { col_idx = 0; //pointer math to point to proper memory tC = C + ldc * col_idx + row_idx; tB = B + tb_inc_col * col_idx; tA = A + row_idx; tA_packed = D_A_pack; #ifdef BLIS_ENABLE_PREFETCH _mm_prefetch((char*)(tC + 0), _MM_HINT_T0); _mm_prefetch((char*)(tC + 8), _MM_HINT_T0); _mm_prefetch((char*)(tC + ldc), _MM_HINT_T0); _mm_prefetch((char*)(tC + ldc + 8), _MM_HINT_T0); _mm_prefetch((char*)(tC + 2 * ldc), _MM_HINT_T0); _mm_prefetch((char*)(tC + 2 * ldc + 8), _MM_HINT_T0); #endif // clear scratch registers. ymm4 = _mm256_setzero_pd(); ymm5 = _mm256_setzero_pd(); ymm6 = _mm256_setzero_pd(); ymm7 = _mm256_setzero_pd(); ymm8 = _mm256_setzero_pd(); ymm9 = _mm256_setzero_pd(); ymm10 = _mm256_setzero_pd(); ymm11 = _mm256_setzero_pd(); ymm12 = _mm256_setzero_pd(); ymm13 = _mm256_setzero_pd(); ymm14 = _mm256_setzero_pd(); ymm15 = _mm256_setzero_pd(); for (k = 0; k < K; ++k) { // The inner loop broadcasts the B matrix data and // multiplies it with the A matrix. // This loop is processing D_MR x K ymm0 = _mm256_broadcast_sd(tB + tb_inc_col * 0); ymm1 = _mm256_broadcast_sd(tB + tb_inc_col * 1); ymm2 = _mm256_broadcast_sd(tB + tb_inc_col * 2); tB += tb_inc_row; //broadcasted matrix B elements are multiplied //with matrix A columns. ymm3 = _mm256_loadu_pd(tA); _mm256_storeu_pd(tA_packed, ymm3); // the packing of matrix A // ymm4 += ymm0 * ymm3; ymm4 = _mm256_fmadd_pd(ymm0, ymm3, ymm4); // ymm8 += ymm1 * ymm3; ymm8 = _mm256_fmadd_pd(ymm1, ymm3, ymm8); // ymm12 += ymm2 * ymm3; ymm12 = _mm256_fmadd_pd(ymm2, ymm3, ymm12); ymm3 = _mm256_loadu_pd(tA + 4); _mm256_storeu_pd(tA_packed + 4, ymm3); // the packing of matrix A // ymm5 += ymm0 * ymm3; ymm5 = _mm256_fmadd_pd(ymm0, ymm3, ymm5); // ymm9 += ymm1 * ymm3; ymm9 = _mm256_fmadd_pd(ymm1, ymm3, ymm9); // ymm13 += ymm2 * ymm3; ymm13 = _mm256_fmadd_pd(ymm2, ymm3, ymm13); ymm3 = _mm256_loadu_pd(tA + 8); _mm256_storeu_pd(tA_packed + 8, ymm3); // the packing of matrix A // ymm6 += ymm0 * ymm3; ymm6 = _mm256_fmadd_pd(ymm0, ymm3, ymm6); // ymm10 += ymm1 * ymm3; ymm10 = _mm256_fmadd_pd(ymm1, ymm3, ymm10); // ymm14 += ymm2 * ymm3; ymm14 = _mm256_fmadd_pd(ymm2, ymm3, ymm14); ymm3 = _mm256_loadu_pd(tA + 12); _mm256_storeu_pd(tA_packed + 12, ymm3); // the packing of matrix A // ymm7 += ymm0 * ymm3; ymm7 = _mm256_fmadd_pd(ymm0, ymm3, ymm7); // ymm11 += ymm1 * ymm3; ymm11 = _mm256_fmadd_pd(ymm1, ymm3, ymm11); // ymm15 += ymm2 * ymm3; ymm15 = _mm256_fmadd_pd(ymm2, ymm3, ymm15); tA += lda; tA_packed += D_MR; } // alpha, beta multiplication. ymm0 = _mm256_broadcast_sd(alpha_cast); ymm1 = _mm256_broadcast_sd(beta_cast); //multiply A*B by alpha. ymm4 = _mm256_mul_pd(ymm4, ymm0); ymm5 = _mm256_mul_pd(ymm5, ymm0); ymm6 = _mm256_mul_pd(ymm6, ymm0); ymm7 = _mm256_mul_pd(ymm7, ymm0); ymm8 = _mm256_mul_pd(ymm8, ymm0); ymm9 = _mm256_mul_pd(ymm9, ymm0); ymm10 = _mm256_mul_pd(ymm10, ymm0); ymm11 = _mm256_mul_pd(ymm11, ymm0); ymm12 = _mm256_mul_pd(ymm12, ymm0); ymm13 = _mm256_mul_pd(ymm13, ymm0); ymm14 = _mm256_mul_pd(ymm14, ymm0); ymm15 = _mm256_mul_pd(ymm15, ymm0); if(is_beta_non_zero) { // multiply C by beta and accumulate col 1. ymm2 = _mm256_loadu_pd(tC); ymm4 = _mm256_fmadd_pd(ymm2, ymm1, ymm4); ymm2 = _mm256_loadu_pd(tC + 4); ymm5 = _mm256_fmadd_pd(ymm2, ymm1, ymm5); ymm2 = _mm256_loadu_pd(tC + 8); ymm6 = _mm256_fmadd_pd(ymm2, ymm1, ymm6); ymm2 = _mm256_loadu_pd(tC + 12); ymm7 = _mm256_fmadd_pd(ymm2, ymm1, ymm7); double* ttC = tC + ldc; // multiply C by beta and accumulate, col 2. ymm2 = _mm256_loadu_pd(ttC); ymm8 = _mm256_fmadd_pd(ymm2, ymm1, ymm8); ymm2 = _mm256_loadu_pd(ttC + 4); ymm9 = _mm256_fmadd_pd(ymm2, ymm1, ymm9); ymm2 = _mm256_loadu_pd(ttC + 8); ymm10 = _mm256_fmadd_pd(ymm2, ymm1, ymm10); ymm2 = _mm256_loadu_pd(ttC + 12); ymm11 = _mm256_fmadd_pd(ymm2, ymm1, ymm11); ttC += ldc; // multiply C by beta and accumulate, col 3. ymm2 = _mm256_loadu_pd(ttC); ymm12 = _mm256_fmadd_pd(ymm2, ymm1, ymm12); ymm2 = _mm256_loadu_pd(ttC + 4); ymm13 = _mm256_fmadd_pd(ymm2, ymm1, ymm13); ymm2 = _mm256_loadu_pd(ttC + 8); ymm14 = _mm256_fmadd_pd(ymm2, ymm1, ymm14); ymm2 = _mm256_loadu_pd(ttC + 12); ymm15 = _mm256_fmadd_pd(ymm2, ymm1, ymm15); } _mm256_storeu_pd(tC, ymm4); _mm256_storeu_pd(tC + 4, ymm5); _mm256_storeu_pd(tC + 8, ymm6); _mm256_storeu_pd(tC + 12, ymm7); tC += ldc; _mm256_storeu_pd(tC, ymm8); _mm256_storeu_pd(tC + 4, ymm9); _mm256_storeu_pd(tC + 8, ymm10); _mm256_storeu_pd(tC + 12, ymm11); tC += ldc; _mm256_storeu_pd(tC, ymm12); _mm256_storeu_pd(tC + 4, ymm13); _mm256_storeu_pd(tC + 8, ymm14); _mm256_storeu_pd(tC + 12, ymm15); // modify the pointer arithematic to use packed A matrix. col_idx_start = NR; tA_packed = D_A_pack; row_idx_packed = 0; lda_packed = D_MR; } // Process NR columns of C matrix at a time. for (col_idx = col_idx_start; (col_idx + (NR - 1)) < N; col_idx += NR) { //pointer math to point to proper memory tC = C + ldc * col_idx + row_idx; tB = B + tb_inc_col * col_idx; tA = tA_packed + row_idx_packed; #ifdef BLIS_ENABLE_PREFETCH _mm_prefetch((char*)(tC + 0), _MM_HINT_T0); _mm_prefetch((char*)(tC + 8), _MM_HINT_T0); _mm_prefetch((char*)(tC + ldc), _MM_HINT_T0); _mm_prefetch((char*)(tC + ldc + 8), _MM_HINT_T0); _mm_prefetch((char*)(tC + 2 * ldc), _MM_HINT_T0); _mm_prefetch((char*)(tC + 2 * ldc + 8), _MM_HINT_T0); #endif // clear scratch registers. ymm4 = _mm256_setzero_pd(); ymm5 = _mm256_setzero_pd(); ymm6 = _mm256_setzero_pd(); ymm7 = _mm256_setzero_pd(); ymm8 = _mm256_setzero_pd(); ymm9 = _mm256_setzero_pd(); ymm10 = _mm256_setzero_pd(); ymm11 = _mm256_setzero_pd(); ymm12 = _mm256_setzero_pd(); ymm13 = _mm256_setzero_pd(); ymm14 = _mm256_setzero_pd(); ymm15 = _mm256_setzero_pd(); for (k = 0; k < K; ++k) { // The inner loop broadcasts the B matrix data and // multiplies it with the A matrix. // This loop is processing D_MR x K ymm0 = _mm256_broadcast_sd(tB + tb_inc_col * 0); ymm1 = _mm256_broadcast_sd(tB + tb_inc_col * 1); ymm2 = _mm256_broadcast_sd(tB + tb_inc_col * 2); tB += tb_inc_row; //broadcasted matrix B elements are multiplied //with matrix A columns. ymm3 = _mm256_loadu_pd(tA); // ymm4 += ymm0 * ymm3; ymm4 = _mm256_fmadd_pd(ymm0, ymm3, ymm4); // ymm8 += ymm1 * ymm3; ymm8 = _mm256_fmadd_pd(ymm1, ymm3, ymm8); // ymm12 += ymm2 * ymm3; ymm12 = _mm256_fmadd_pd(ymm2, ymm3, ymm12); ymm3 = _mm256_loadu_pd(tA + 4); // ymm5 += ymm0 * ymm3; ymm5 = _mm256_fmadd_pd(ymm0, ymm3, ymm5); // ymm9 += ymm1 * ymm3; ymm9 = _mm256_fmadd_pd(ymm1, ymm3, ymm9); // ymm13 += ymm2 * ymm3; ymm13 = _mm256_fmadd_pd(ymm2, ymm3, ymm13); ymm3 = _mm256_loadu_pd(tA + 8); // ymm6 += ymm0 * ymm3; ymm6 = _mm256_fmadd_pd(ymm0, ymm3, ymm6); // ymm10 += ymm1 * ymm3; ymm10 = _mm256_fmadd_pd(ymm1, ymm3, ymm10); // ymm14 += ymm2 * ymm3; ymm14 = _mm256_fmadd_pd(ymm2, ymm3, ymm14); ymm3 = _mm256_loadu_pd(tA + 12); // ymm7 += ymm0 * ymm3; ymm7 = _mm256_fmadd_pd(ymm0, ymm3, ymm7); // ymm11 += ymm1 * ymm3; ymm11 = _mm256_fmadd_pd(ymm1, ymm3, ymm11); // ymm15 += ymm2 * ymm3; ymm15 = _mm256_fmadd_pd(ymm2, ymm3, ymm15); tA += lda_packed; } // alpha, beta multiplication. ymm0 = _mm256_broadcast_sd(alpha_cast); ymm1 = _mm256_broadcast_sd(beta_cast); //multiply A*B by alpha. ymm4 = _mm256_mul_pd(ymm4, ymm0); ymm5 = _mm256_mul_pd(ymm5, ymm0); ymm6 = _mm256_mul_pd(ymm6, ymm0); ymm7 = _mm256_mul_pd(ymm7, ymm0); ymm8 = _mm256_mul_pd(ymm8, ymm0); ymm9 = _mm256_mul_pd(ymm9, ymm0); ymm10 = _mm256_mul_pd(ymm10, ymm0); ymm11 = _mm256_mul_pd(ymm11, ymm0); ymm12 = _mm256_mul_pd(ymm12, ymm0); ymm13 = _mm256_mul_pd(ymm13, ymm0); ymm14 = _mm256_mul_pd(ymm14, ymm0); ymm15 = _mm256_mul_pd(ymm15, ymm0); if(is_beta_non_zero) { // multiply C by beta and accumulate col 1. ymm2 = _mm256_loadu_pd(tC); ymm4 = _mm256_fmadd_pd(ymm2, ymm1, ymm4); ymm2 = _mm256_loadu_pd(tC + 4); ymm5 = _mm256_fmadd_pd(ymm2, ymm1, ymm5); ymm2 = _mm256_loadu_pd(tC + 8); ymm6 = _mm256_fmadd_pd(ymm2, ymm1, ymm6); ymm2 = _mm256_loadu_pd(tC + 12); ymm7 = _mm256_fmadd_pd(ymm2, ymm1, ymm7); // multiply C by beta and accumulate, col 2. double* ttC = tC + ldc; ymm2 = _mm256_loadu_pd(ttC); ymm8 = _mm256_fmadd_pd(ymm2, ymm1, ymm8); ymm2 = _mm256_loadu_pd(ttC + 4); ymm9 = _mm256_fmadd_pd(ymm2, ymm1, ymm9); ymm2 = _mm256_loadu_pd(ttC + 8); ymm10 = _mm256_fmadd_pd(ymm2, ymm1, ymm10); ymm2 = _mm256_loadu_pd(ttC + 12); ymm11 = _mm256_fmadd_pd(ymm2, ymm1, ymm11); // multiply C by beta and accumulate, col 3. ttC += ldc; ymm2 = _mm256_loadu_pd(ttC); ymm12 = _mm256_fmadd_pd(ymm2, ymm1, ymm12); ymm2 = _mm256_loadu_pd(ttC + 4); ymm13 = _mm256_fmadd_pd(ymm2, ymm1, ymm13); ymm2 = _mm256_loadu_pd(ttC + 8); ymm14 = _mm256_fmadd_pd(ymm2, ymm1, ymm14); ymm2 = _mm256_loadu_pd(ttC + 12); ymm15 = _mm256_fmadd_pd(ymm2, ymm1, ymm15); } _mm256_storeu_pd(tC, ymm4); _mm256_storeu_pd(tC + 4, ymm5); _mm256_storeu_pd(tC + 8, ymm6); _mm256_storeu_pd(tC + 12, ymm7); tC += ldc; _mm256_storeu_pd(tC, ymm8); _mm256_storeu_pd(tC + 4, ymm9); _mm256_storeu_pd(tC + 8, ymm10); _mm256_storeu_pd(tC + 12, ymm11); tC += ldc; _mm256_storeu_pd(tC, ymm12); _mm256_storeu_pd(tC + 4, ymm13); _mm256_storeu_pd(tC + 8, ymm14); _mm256_storeu_pd(tC + 12, ymm15); } n_remainder = N - col_idx; // if the N is not multiple of 3. // handling edge case. if (n_remainder == 2) { //pointer math to point to proper memory tC = C + ldc * col_idx + row_idx; tB = B + tb_inc_col * col_idx; tA = A + row_idx; // clear scratch registers. ymm8 = _mm256_setzero_pd(); ymm9 = _mm256_setzero_pd(); ymm10 = _mm256_setzero_pd(); ymm11 = _mm256_setzero_pd(); ymm12 = _mm256_setzero_pd(); ymm13 = _mm256_setzero_pd(); ymm14 = _mm256_setzero_pd(); ymm15 = _mm256_setzero_pd(); for (k = 0; k < K; ++k) { // The inner loop broadcasts the B matrix data and // multiplies it with the A matrix. ymm0 = _mm256_broadcast_sd(tB + tb_inc_col * 0); ymm1 = _mm256_broadcast_sd(tB + tb_inc_col * 1); tB += tb_inc_row; //broadcasted matrix B elements are multiplied //with matrix A columns. ymm3 = _mm256_loadu_pd(tA); ymm8 = _mm256_fmadd_pd(ymm0, ymm3, ymm8); ymm12 = _mm256_fmadd_pd(ymm1, ymm3, ymm12); ymm3 = _mm256_loadu_pd(tA + 4); ymm9 = _mm256_fmadd_pd(ymm0, ymm3, ymm9); ymm13 = _mm256_fmadd_pd(ymm1, ymm3, ymm13); ymm3 = _mm256_loadu_pd(tA + 8); ymm10 = _mm256_fmadd_pd(ymm0, ymm3, ymm10); ymm14 = _mm256_fmadd_pd(ymm1, ymm3, ymm14); ymm3 = _mm256_loadu_pd(tA + 12); ymm11 = _mm256_fmadd_pd(ymm0, ymm3, ymm11); ymm15 = _mm256_fmadd_pd(ymm1, ymm3, ymm15); tA += lda; } // alpha, beta multiplication. ymm0 = _mm256_broadcast_sd(alpha_cast); ymm1 = _mm256_broadcast_sd(beta_cast); //multiply A*B by alpha. ymm8 = _mm256_mul_pd(ymm8, ymm0); ymm9 = _mm256_mul_pd(ymm9, ymm0); ymm10 = _mm256_mul_pd(ymm10, ymm0); ymm11 = _mm256_mul_pd(ymm11, ymm0); ymm12 = _mm256_mul_pd(ymm12, ymm0); ymm13 = _mm256_mul_pd(ymm13, ymm0); ymm14 = _mm256_mul_pd(ymm14, ymm0); ymm15 = _mm256_mul_pd(ymm15, ymm0); if(is_beta_non_zero) { // multiply C by beta and accumulate, col 1. ymm2 = _mm256_loadu_pd(tC + 0); ymm8 = _mm256_fmadd_pd(ymm2, ymm1, ymm8); ymm2 = _mm256_loadu_pd(tC + 4); ymm9 = _mm256_fmadd_pd(ymm2, ymm1, ymm9); ymm2 = _mm256_loadu_pd(tC + 8); ymm10 = _mm256_fmadd_pd(ymm2, ymm1, ymm10); ymm2 = _mm256_loadu_pd(tC + 12); ymm11 = _mm256_fmadd_pd(ymm2, ymm1, ymm11); // multiply C by beta and accumulate, col 2. double *ttC = tC + ldc; ymm2 = _mm256_loadu_pd(ttC); ymm12 = _mm256_fmadd_pd(ymm2, ymm1, ymm12); ymm2 = _mm256_loadu_pd(ttC + 4); ymm13 = _mm256_fmadd_pd(ymm2, ymm1, ymm13); ymm2 = _mm256_loadu_pd(ttC + 8); ymm14 = _mm256_fmadd_pd(ymm2, ymm1, ymm14); ymm2 = _mm256_loadu_pd(ttC + 12); ymm15 = _mm256_fmadd_pd(ymm2, ymm1, ymm15); } _mm256_storeu_pd(tC + 0, ymm8); _mm256_storeu_pd(tC + 4, ymm9); _mm256_storeu_pd(tC + 8, ymm10); _mm256_storeu_pd(tC + 12, ymm11); tC += ldc; _mm256_storeu_pd(tC, ymm12); _mm256_storeu_pd(tC + 4, ymm13); _mm256_storeu_pd(tC + 8, ymm14); _mm256_storeu_pd(tC + 12, ymm15); col_idx += 2; } // if the N is not multiple of 3. // handling edge case. if (n_remainder == 1) { //pointer math to point to proper memory tC = C + ldc * col_idx + row_idx; tB = B + tb_inc_col * col_idx; tA = A + row_idx; // clear scratch registers. ymm12 = _mm256_setzero_pd(); ymm13 = _mm256_setzero_pd(); ymm14 = _mm256_setzero_pd(); ymm15 = _mm256_setzero_pd(); for (k = 0; k < K; ++k) { // The inner loop broadcasts the B matrix data and // multiplies it with the A matrix. ymm0 = _mm256_broadcast_sd(tB + tb_inc_col * 0); tB += tb_inc_row; //broadcasted matrix B elements are multiplied //with matrix A columns. ymm3 = _mm256_loadu_pd(tA); ymm12 = _mm256_fmadd_pd(ymm0, ymm3, ymm12); ymm3 = _mm256_loadu_pd(tA + 4); ymm13 = _mm256_fmadd_pd(ymm0, ymm3, ymm13); ymm3 = _mm256_loadu_pd(tA + 8); ymm14 = _mm256_fmadd_pd(ymm0, ymm3, ymm14); ymm3 = _mm256_loadu_pd(tA + 12); ymm15 = _mm256_fmadd_pd(ymm0, ymm3, ymm15); tA += lda; } // alpha, beta multiplication. ymm0 = _mm256_broadcast_sd(alpha_cast); ymm1 = _mm256_broadcast_sd(beta_cast); //multiply A*B by alpha. ymm12 = _mm256_mul_pd(ymm12, ymm0); ymm13 = _mm256_mul_pd(ymm13, ymm0); ymm14 = _mm256_mul_pd(ymm14, ymm0); ymm15 = _mm256_mul_pd(ymm15, ymm0); if(is_beta_non_zero) { // multiply C by beta and accumulate. ymm2 = _mm256_loadu_pd(tC + 0); ymm12 = _mm256_fmadd_pd(ymm2, ymm1, ymm12); ymm2 = _mm256_loadu_pd(tC + 4); ymm13 = _mm256_fmadd_pd(ymm2, ymm1, ymm13); ymm2 = _mm256_loadu_pd(tC + 8); ymm14 = _mm256_fmadd_pd(ymm2, ymm1, ymm14); ymm2 = _mm256_loadu_pd(tC + 12); ymm15 = _mm256_fmadd_pd(ymm2, ymm1, ymm15); } _mm256_storeu_pd(tC + 0, ymm12); _mm256_storeu_pd(tC + 4, ymm13); _mm256_storeu_pd(tC + 8, ymm14); _mm256_storeu_pd(tC + 12, ymm15); } } m_remainder = M - row_idx; if (m_remainder >= 12) { m_remainder -= 12; for (col_idx = 0; (col_idx + 2) < N; col_idx += 3) { //pointer math to point to proper memory tC = C + ldc * col_idx + row_idx; tB = B + tb_inc_col * col_idx; tA = A + row_idx; // clear scratch registers. ymm4 = _mm256_setzero_pd(); ymm5 = _mm256_setzero_pd(); ymm6 = _mm256_setzero_pd(); ymm8 = _mm256_setzero_pd(); ymm9 = _mm256_setzero_pd(); ymm10 = _mm256_setzero_pd(); ymm12 = _mm256_setzero_pd(); ymm13 = _mm256_setzero_pd(); ymm14 = _mm256_setzero_pd(); for (k = 0; k < K; ++k) { // The inner loop broadcasts the B matrix data and // multiplies it with the A matrix. ymm0 = _mm256_broadcast_sd(tB + tb_inc_col * 0); ymm1 = _mm256_broadcast_sd(tB + tb_inc_col * 1); ymm2 = _mm256_broadcast_sd(tB + tb_inc_col * 2); tB += tb_inc_row; //broadcasted matrix B elements are multiplied //with matrix A columns. ymm3 = _mm256_loadu_pd(tA); // ymm4 += ymm0 * ymm3; ymm4 = _mm256_fmadd_pd(ymm0, ymm3, ymm4); // ymm8 += ymm1 * ymm3; ymm8 = _mm256_fmadd_pd(ymm1, ymm3, ymm8); // ymm12 += ymm2 * ymm3; ymm12 = _mm256_fmadd_pd(ymm2, ymm3, ymm12); ymm3 = _mm256_loadu_pd(tA + 4); // ymm5 += ymm0 * ymm3; ymm5 = _mm256_fmadd_pd(ymm0, ymm3, ymm5); // ymm9 += ymm1 * ymm3; ymm9 = _mm256_fmadd_pd(ymm1, ymm3, ymm9); // ymm13 += ymm2 * ymm3; ymm13 = _mm256_fmadd_pd(ymm2, ymm3, ymm13); ymm3 = _mm256_loadu_pd(tA + 8); // ymm6 += ymm0 * ymm3; ymm6 = _mm256_fmadd_pd(ymm0, ymm3, ymm6); // ymm10 += ymm1 * ymm3; ymm10 = _mm256_fmadd_pd(ymm1, ymm3, ymm10); // ymm14 += ymm2 * ymm3; ymm14 = _mm256_fmadd_pd(ymm2, ymm3, ymm14); tA += lda; } // alpha, beta multiplication. ymm0 = _mm256_broadcast_sd(alpha_cast); ymm1 = _mm256_broadcast_sd(beta_cast); //multiply A*B by alpha. ymm4 = _mm256_mul_pd(ymm4, ymm0); ymm5 = _mm256_mul_pd(ymm5, ymm0); ymm6 = _mm256_mul_pd(ymm6, ymm0); ymm8 = _mm256_mul_pd(ymm8, ymm0); ymm9 = _mm256_mul_pd(ymm9, ymm0); ymm10 = _mm256_mul_pd(ymm10, ymm0); ymm12 = _mm256_mul_pd(ymm12, ymm0); ymm13 = _mm256_mul_pd(ymm13, ymm0); ymm14 = _mm256_mul_pd(ymm14, ymm0); if(is_beta_non_zero) { // multiply C by beta and accumulate. ymm2 = _mm256_loadu_pd(tC); ymm4 = _mm256_fmadd_pd(ymm2, ymm1, ymm4); ymm2 = _mm256_loadu_pd(tC + 4); ymm5 = _mm256_fmadd_pd(ymm2, ymm1, ymm5); ymm2 = _mm256_loadu_pd(tC + 8); ymm6 = _mm256_fmadd_pd(ymm2, ymm1, ymm6); // multiply C by beta and accumulate. double *ttC = tC +ldc; ymm2 = _mm256_loadu_pd(ttC); ymm8 = _mm256_fmadd_pd(ymm2, ymm1, ymm8); ymm2 = _mm256_loadu_pd(ttC + 4); ymm9 = _mm256_fmadd_pd(ymm2, ymm1, ymm9); ymm2 = _mm256_loadu_pd(ttC + 8); ymm10 = _mm256_fmadd_pd(ymm2, ymm1, ymm10); // multiply C by beta and accumulate. ttC += ldc; ymm2 = _mm256_loadu_pd(ttC); ymm12 = _mm256_fmadd_pd(ymm2, ymm1, ymm12); ymm2 = _mm256_loadu_pd(ttC + 4); ymm13 = _mm256_fmadd_pd(ymm2, ymm1, ymm13); ymm2 = _mm256_loadu_pd(ttC + 8); ymm14 = _mm256_fmadd_pd(ymm2, ymm1, ymm14); } _mm256_storeu_pd(tC, ymm4); _mm256_storeu_pd(tC + 4, ymm5); _mm256_storeu_pd(tC + 8, ymm6); tC += ldc; _mm256_storeu_pd(tC, ymm8); _mm256_storeu_pd(tC + 4, ymm9); _mm256_storeu_pd(tC + 8, ymm10); tC += ldc; _mm256_storeu_pd(tC, ymm12); _mm256_storeu_pd(tC + 4, ymm13); _mm256_storeu_pd(tC + 8, ymm14); } n_remainder = N - col_idx; // if the N is not multiple of 3. // handling edge case. if (n_remainder == 2) { //pointer math to point to proper memory tC = C + ldc * col_idx + row_idx; tB = B + tb_inc_col * col_idx; tA = A + row_idx; // clear scratch registers. ymm8 = _mm256_setzero_pd(); ymm9 = _mm256_setzero_pd(); ymm10 = _mm256_setzero_pd(); ymm12 = _mm256_setzero_pd(); ymm13 = _mm256_setzero_pd(); ymm14 = _mm256_setzero_pd(); for (k = 0; k < K; ++k) { // The inner loop broadcasts the B matrix data and // multiplies it with the A matrix. ymm0 = _mm256_broadcast_sd(tB + tb_inc_col * 0); ymm1 = _mm256_broadcast_sd(tB + tb_inc_col * 1); tB += tb_inc_row; //broadcasted matrix B elements are multiplied //with matrix A columns. ymm3 = _mm256_loadu_pd(tA); ymm8 = _mm256_fmadd_pd(ymm0, ymm3, ymm8); ymm12 = _mm256_fmadd_pd(ymm1, ymm3, ymm12); ymm3 = _mm256_loadu_pd(tA + 4); ymm9 = _mm256_fmadd_pd(ymm0, ymm3, ymm9); ymm13 = _mm256_fmadd_pd(ymm1, ymm3, ymm13); ymm3 = _mm256_loadu_pd(tA + 8); ymm10 = _mm256_fmadd_pd(ymm0, ymm3, ymm10); ymm14 = _mm256_fmadd_pd(ymm1, ymm3, ymm14); tA += lda; } // alpha, beta multiplication. ymm0 = _mm256_broadcast_sd(alpha_cast); ymm1 = _mm256_broadcast_sd(beta_cast); //multiply A*B by alpha. ymm8 = _mm256_mul_pd(ymm8, ymm0); ymm9 = _mm256_mul_pd(ymm9, ymm0); ymm10 = _mm256_mul_pd(ymm10, ymm0); ymm12 = _mm256_mul_pd(ymm12, ymm0); ymm13 = _mm256_mul_pd(ymm13, ymm0); ymm14 = _mm256_mul_pd(ymm14, ymm0); if(is_beta_non_zero) { // multiply C by beta and accumulate. ymm2 = _mm256_loadu_pd(tC + 0); ymm8 = _mm256_fmadd_pd(ymm2, ymm1, ymm8); ymm2 = _mm256_loadu_pd(tC + 4); ymm9 = _mm256_fmadd_pd(ymm2, ymm1, ymm9); ymm2 = _mm256_loadu_pd(tC + 8); ymm10 = _mm256_fmadd_pd(ymm2, ymm1, ymm10); double *ttC = tC + ldc; // multiply C by beta and accumulate. ymm2 = _mm256_loadu_pd(ttC); ymm12 = _mm256_fmadd_pd(ymm2, ymm1, ymm12); ymm2 = _mm256_loadu_pd(ttC + 4); ymm13 = _mm256_fmadd_pd(ymm2, ymm1, ymm13); ymm2 = _mm256_loadu_pd(ttC + 8); ymm14 = _mm256_fmadd_pd(ymm2, ymm1, ymm14); } _mm256_storeu_pd(tC + 0, ymm8); _mm256_storeu_pd(tC + 4, ymm9); _mm256_storeu_pd(tC + 8, ymm10); tC += ldc; _mm256_storeu_pd(tC, ymm12); _mm256_storeu_pd(tC + 4, ymm13); _mm256_storeu_pd(tC + 8, ymm14); col_idx += 2; } // if the N is not multiple of 3. // handling edge case. if (n_remainder == 1) { //pointer math to point to proper memory tC = C + ldc * col_idx + row_idx; tB = B + tb_inc_col * col_idx; tA = A + row_idx; // clear scratch registers. ymm12 = _mm256_setzero_pd(); ymm13 = _mm256_setzero_pd(); ymm14 = _mm256_setzero_pd(); for (k = 0; k < K; ++k) { // The inner loop broadcasts the B matrix data and // multiplies it with the A matrix. ymm0 = _mm256_broadcast_sd(tB + tb_inc_col * 0); tB += tb_inc_row; //broadcasted matrix B elements are multiplied //with matrix A columns. ymm3 = _mm256_loadu_pd(tA); ymm12 = _mm256_fmadd_pd(ymm0, ymm3, ymm12); ymm3 = _mm256_loadu_pd(tA + 4); ymm13 = _mm256_fmadd_pd(ymm0, ymm3, ymm13); ymm3 = _mm256_loadu_pd(tA + 8); ymm14 = _mm256_fmadd_pd(ymm0, ymm3, ymm14); tA += lda; } // alpha, beta multiplication. ymm0 = _mm256_broadcast_sd(alpha_cast); ymm1 = _mm256_broadcast_sd(beta_cast); //multiply A*B by alpha. ymm12 = _mm256_mul_pd(ymm12, ymm0); ymm13 = _mm256_mul_pd(ymm13, ymm0); ymm14 = _mm256_mul_pd(ymm14, ymm0); if(is_beta_non_zero) { // multiply C by beta and accumulate. ymm2 = _mm256_loadu_pd(tC + 0); ymm12 = _mm256_fmadd_pd(ymm2, ymm1, ymm12); ymm2 = _mm256_loadu_pd(tC + 4); ymm13 = _mm256_fmadd_pd(ymm2, ymm1, ymm13); ymm2 = _mm256_loadu_pd(tC + 8); ymm14 = _mm256_fmadd_pd(ymm2, ymm1, ymm14); } _mm256_storeu_pd(tC + 0, ymm12); _mm256_storeu_pd(tC + 4, ymm13); _mm256_storeu_pd(tC + 8, ymm14); } row_idx += 12; } if (m_remainder >= 8) { m_remainder -= 8; for (col_idx = 0; (col_idx + 2) < N; col_idx += 3) { //pointer math to point to proper memory tC = C + ldc * col_idx + row_idx; tB = B + tb_inc_col * col_idx; tA = A + row_idx; // clear scratch registers. ymm4 = _mm256_setzero_pd(); ymm5 = _mm256_setzero_pd(); ymm6 = _mm256_setzero_pd(); ymm7 = _mm256_setzero_pd(); ymm8 = _mm256_setzero_pd(); ymm9 = _mm256_setzero_pd(); for (k = 0; k < K; ++k) { // The inner loop broadcasts the B matrix data and // multiplies it with the A matrix. ymm0 = _mm256_broadcast_sd(tB + tb_inc_col * 0); ymm1 = _mm256_broadcast_sd(tB + tb_inc_col * 1); ymm2 = _mm256_broadcast_sd(tB + tb_inc_col * 2); tB += tb_inc_row; //broadcasted matrix B elements are multiplied //with matrix A columns. ymm3 = _mm256_loadu_pd(tA); ymm4 = _mm256_fmadd_pd(ymm0, ymm3, ymm4); ymm6 = _mm256_fmadd_pd(ymm1, ymm3, ymm6); ymm8 = _mm256_fmadd_pd(ymm2, ymm3, ymm8); ymm3 = _mm256_loadu_pd(tA + 4); ymm5 = _mm256_fmadd_pd(ymm0, ymm3, ymm5); ymm7 = _mm256_fmadd_pd(ymm1, ymm3, ymm7); ymm9 = _mm256_fmadd_pd(ymm2, ymm3, ymm9); tA += lda; } // alpha, beta multiplication. ymm0 = _mm256_broadcast_sd(alpha_cast); ymm1 = _mm256_broadcast_sd(beta_cast); //multiply A*B by alpha. ymm4 = _mm256_mul_pd(ymm4, ymm0); ymm5 = _mm256_mul_pd(ymm5, ymm0); ymm6 = _mm256_mul_pd(ymm6, ymm0); ymm7 = _mm256_mul_pd(ymm7, ymm0); ymm8 = _mm256_mul_pd(ymm8, ymm0); ymm9 = _mm256_mul_pd(ymm9, ymm0); if(is_beta_non_zero) { // multiply C by beta and accumulate. ymm2 = _mm256_loadu_pd(tC); ymm4 = _mm256_fmadd_pd(ymm2, ymm1, ymm4); ymm2 = _mm256_loadu_pd(tC + 4); ymm5 = _mm256_fmadd_pd(ymm2, ymm1, ymm5); double* ttC = tC + ldc; // multiply C by beta and accumulate. ymm2 = _mm256_loadu_pd(ttC); ymm6 = _mm256_fmadd_pd(ymm2, ymm1, ymm6); ymm2 = _mm256_loadu_pd(ttC + 4); ymm7 = _mm256_fmadd_pd(ymm2, ymm1, ymm7); ttC += ldc; // multiply C by beta and accumulate. ymm2 = _mm256_loadu_pd(ttC); ymm8 = _mm256_fmadd_pd(ymm2, ymm1, ymm8); ymm2 = _mm256_loadu_pd(ttC + 4); ymm9 = _mm256_fmadd_pd(ymm2, ymm1, ymm9); } _mm256_storeu_pd(tC, ymm4); _mm256_storeu_pd(tC + 4, ymm5); tC += ldc; _mm256_storeu_pd(tC, ymm6); _mm256_storeu_pd(tC + 4, ymm7); tC += ldc; _mm256_storeu_pd(tC, ymm8); _mm256_storeu_pd(tC + 4, ymm9); } n_remainder = N - col_idx; // if the N is not multiple of 3. // handling edge case. if (n_remainder == 2) { //pointer math to point to proper memory tC = C + ldc * col_idx + row_idx; tB = B + tb_inc_col * col_idx; tA = A + row_idx; // clear scratch registers. ymm4 = _mm256_setzero_pd(); ymm5 = _mm256_setzero_pd(); ymm6 = _mm256_setzero_pd(); ymm7 = _mm256_setzero_pd(); for (k = 0; k < K; ++k) { // The inner loop broadcasts the B matrix data and // multiplies it with the A matrix. ymm0 = _mm256_broadcast_sd(tB + tb_inc_col * 0); ymm1 = _mm256_broadcast_sd(tB + tb_inc_col * 1); tB += tb_inc_row; //broadcasted matrix B elements are multiplied //with matrix A columns. ymm3 = _mm256_loadu_pd(tA); ymm4 = _mm256_fmadd_pd(ymm0, ymm3, ymm4); ymm6 = _mm256_fmadd_pd(ymm1, ymm3, ymm6); ymm3 = _mm256_loadu_pd(tA + 4); ymm5 = _mm256_fmadd_pd(ymm0, ymm3, ymm5); ymm7 = _mm256_fmadd_pd(ymm1, ymm3, ymm7); tA += lda; } // alpha, beta multiplication. ymm0 = _mm256_broadcast_sd(alpha_cast); ymm1 = _mm256_broadcast_sd(beta_cast); //multiply A*B by alpha. ymm4 = _mm256_mul_pd(ymm4, ymm0); ymm5 = _mm256_mul_pd(ymm5, ymm0); ymm6 = _mm256_mul_pd(ymm6, ymm0); ymm7 = _mm256_mul_pd(ymm7, ymm0); if(is_beta_non_zero) { // multiply C by beta and accumulate. ymm2 = _mm256_loadu_pd(tC); ymm4 = _mm256_fmadd_pd(ymm2, ymm1, ymm4); ymm2 = _mm256_loadu_pd(tC + 4); ymm5 = _mm256_fmadd_pd(ymm2, ymm1, ymm5); double* ttC = tC + ldc; // multiply C by beta and accumulate. ymm2 = _mm256_loadu_pd(ttC); ymm6 = _mm256_fmadd_pd(ymm2, ymm1, ymm6); ymm2 = _mm256_loadu_pd(ttC + 4); ymm7 = _mm256_fmadd_pd(ymm2, ymm1, ymm7); } _mm256_storeu_pd(tC, ymm4); _mm256_storeu_pd(tC + 4, ymm5); tC += ldc; _mm256_storeu_pd(tC, ymm6); _mm256_storeu_pd(tC + 4, ymm7); col_idx += 2; } // if the N is not multiple of 3. // handling edge case. if (n_remainder == 1) { //pointer math to point to proper memory tC = C + ldc * col_idx + row_idx; tB = B + tb_inc_col * col_idx; tA = A + row_idx; ymm4 = _mm256_setzero_pd(); ymm5 = _mm256_setzero_pd(); for (k = 0; k < K; ++k) { // The inner loop broadcasts the B matrix data and // multiplies it with the A matrix. ymm0 = _mm256_broadcast_sd(tB + tb_inc_col * 0); tB += tb_inc_row; //broadcasted matrix B elements are multiplied //with matrix A columns. ymm3 = _mm256_loadu_pd(tA); ymm4 = _mm256_fmadd_pd(ymm0, ymm3, ymm4); ymm3 = _mm256_loadu_pd(tA + 4); ymm5 = _mm256_fmadd_pd(ymm0, ymm3, ymm5); tA += lda; } // alpha, beta multiplication. ymm0 = _mm256_broadcast_sd(alpha_cast); ymm1 = _mm256_broadcast_sd(beta_cast); ymm4 = _mm256_mul_pd(ymm4, ymm0); ymm5 = _mm256_mul_pd(ymm5, ymm0); if(is_beta_non_zero) { // multiply C by beta and accumulate. ymm2 = _mm256_loadu_pd(tC); ymm4 = _mm256_fmadd_pd(ymm2, ymm1, ymm4); ymm2 = _mm256_loadu_pd(tC + 4); ymm5 = _mm256_fmadd_pd(ymm2, ymm1, ymm5); } _mm256_storeu_pd(tC, ymm4); _mm256_storeu_pd(tC + 4, ymm5); } row_idx += 8; } if (m_remainder >= 4) { //printf("HERE\n"); m_remainder -= 4; for (col_idx = 0; (col_idx + 2) < N; col_idx += 3) { //pointer math to point to proper memory tC = C + ldc * col_idx + row_idx; tB = B + tb_inc_col * col_idx; tA = A + row_idx; // clear scratch registers. ymm4 = _mm256_setzero_pd(); ymm5 = _mm256_setzero_pd(); ymm6 = _mm256_setzero_pd(); for (k = 0; k < K; ++k) { // The inner loop broadcasts the B matrix data and // multiplies it with the A matrix. ymm0 = _mm256_broadcast_sd(tB + tb_inc_col * 0); ymm1 = _mm256_broadcast_sd(tB + tb_inc_col * 1); ymm2 = _mm256_broadcast_sd(tB + tb_inc_col * 2); tB += tb_inc_row; //broadcasted matrix B elements are multiplied //with matrix A columns. ymm3 = _mm256_loadu_pd(tA); ymm4 = _mm256_fmadd_pd(ymm0, ymm3, ymm4); ymm5 = _mm256_fmadd_pd(ymm1, ymm3, ymm5); ymm6 = _mm256_fmadd_pd(ymm2, ymm3, ymm6); tA += lda; } // alpha, beta multiplication. ymm0 = _mm256_broadcast_sd(alpha_cast); ymm1 = _mm256_broadcast_sd(beta_cast); //multiply A*B by alpha. ymm4 = _mm256_mul_pd(ymm4, ymm0); ymm5 = _mm256_mul_pd(ymm5, ymm0); ymm6 = _mm256_mul_pd(ymm6, ymm0); if(is_beta_non_zero) { // multiply C by beta and accumulate. ymm2 = _mm256_loadu_pd(tC); ymm4 = _mm256_fmadd_pd(ymm2, ymm1, ymm4); double* ttC = tC + ldc; // multiply C by beta and accumulate. ymm2 = _mm256_loadu_pd(ttC); ymm5 = _mm256_fmadd_pd(ymm2, ymm1, ymm5); ttC += ldc; // multiply C by beta and accumulate. ymm2 = _mm256_loadu_pd(ttC); ymm6 = _mm256_fmadd_pd(ymm2, ymm1, ymm6); } _mm256_storeu_pd(tC, ymm4); tC += ldc; _mm256_storeu_pd(tC, ymm5); tC += ldc; _mm256_storeu_pd(tC, ymm6); } n_remainder = N - col_idx; // if the N is not multiple of 3. // handling edge case. if (n_remainder == 2) { //pointer math to point to proper memory tC = C + ldc * col_idx + row_idx; tB = B + tb_inc_col * col_idx; tA = A + row_idx; ymm4 = _mm256_setzero_pd(); ymm5 = _mm256_setzero_pd(); for (k = 0; k < K; ++k) { // The inner loop broadcasts the B matrix data and // multiplies it with the A matrix. ymm0 = _mm256_broadcast_sd(tB + tb_inc_col * 0); ymm1 = _mm256_broadcast_sd(tB + tb_inc_col * 1); tB += tb_inc_row; //broadcasted matrix B elements are multiplied //with matrix A columns. ymm3 = _mm256_loadu_pd(tA); ymm4 = _mm256_fmadd_pd(ymm0, ymm3, ymm4); ymm5 = _mm256_fmadd_pd(ymm1, ymm3, ymm5); tA += lda; } // alpha, beta multiplication. ymm0 = _mm256_broadcast_sd(alpha_cast); ymm1 = _mm256_broadcast_sd(beta_cast); //multiply A*B by alpha. ymm4 = _mm256_mul_pd(ymm4, ymm0); ymm5 = _mm256_mul_pd(ymm5, ymm0); if(is_beta_non_zero) { // multiply C by beta and accumulate. ymm2 = _mm256_loadu_pd(tC); ymm4 = _mm256_fmadd_pd(ymm2, ymm1, ymm4); double* ttC = tC + ldc; // multiply C by beta and accumulate. ymm2 = _mm256_loadu_pd(ttC); ymm5 = _mm256_fmadd_pd(ymm2, ymm1, ymm5); } _mm256_storeu_pd(tC, ymm4); tC += ldc; _mm256_storeu_pd(tC, ymm5); col_idx += 2; } // if the N is not multiple of 3. // handling edge case. if (n_remainder == 1) { //pointer math to point to proper memory tC = C + ldc * col_idx + row_idx; tB = B + tb_inc_col * col_idx; tA = A + row_idx; ymm4 = _mm256_setzero_pd(); for (k = 0; k < K; ++k) { // The inner loop broadcasts the B matrix data and // multiplies it with the A matrix. ymm0 = _mm256_broadcast_sd(tB + tb_inc_col * 0); tB += tb_inc_row; //broadcasted matrix B elements are multiplied //with matrix A columns. ymm3 = _mm256_loadu_pd(tA); ymm4 = _mm256_fmadd_pd(ymm0, ymm3, ymm4); tA += lda; } // alpha, beta multiplication. ymm0 = _mm256_broadcast_sd(alpha_cast); ymm1 = _mm256_broadcast_sd(beta_cast); ymm4 = _mm256_mul_pd(ymm4, ymm0); if(is_beta_non_zero) { // multiply C by beta and accumulate. ymm2 = _mm256_loadu_pd(tC); ymm4 = _mm256_fmadd_pd(ymm2, ymm1, ymm4); } _mm256_storeu_pd(tC, ymm4); } row_idx += 4; } // M is not a multiple of 32. // The handling of edge case where the remainder // dimension is less than 8. The padding takes place // to handle this case. if ((m_remainder) && (lda > 3)) { double f_temp[8] = {0.0}; for (col_idx = 0; (col_idx + 2) < N; col_idx += 3) { //pointer math to point to proper memory tC = C + ldc * col_idx + row_idx; tB = B + tb_inc_col * col_idx; tA = A + row_idx; // clear scratch registers. ymm5 = _mm256_setzero_pd(); ymm7 = _mm256_setzero_pd(); ymm9 = _mm256_setzero_pd(); for (k = 0; k < (K - 1); ++k) { // The inner loop broadcasts the B matrix data and // multiplies it with the A matrix. ymm0 = _mm256_broadcast_sd(tB + tb_inc_col * 0); ymm1 = _mm256_broadcast_sd(tB + tb_inc_col * 1); ymm2 = _mm256_broadcast_sd(tB + tb_inc_col * 2); tB += tb_inc_row; //broadcasted matrix B elements are multiplied //with matrix A columns. ymm3 = _mm256_loadu_pd(tA); ymm5 = _mm256_fmadd_pd(ymm0, ymm3, ymm5); ymm7 = _mm256_fmadd_pd(ymm1, ymm3, ymm7); ymm9 = _mm256_fmadd_pd(ymm2, ymm3, ymm9); tA += lda; } // alpha, beta multiplication. ymm0 = _mm256_broadcast_sd(tB + tb_inc_col * 0); ymm1 = _mm256_broadcast_sd(tB + tb_inc_col * 1); ymm2 = _mm256_broadcast_sd(tB + tb_inc_col * 2); tB += tb_inc_row; for (int i = 0; i < m_remainder; i++) { f_temp[i] = tA[i]; } ymm3 = _mm256_loadu_pd(f_temp); ymm5 = _mm256_fmadd_pd(ymm0, ymm3, ymm5); ymm7 = _mm256_fmadd_pd(ymm1, ymm3, ymm7); ymm9 = _mm256_fmadd_pd(ymm2, ymm3, ymm9); ymm0 = _mm256_broadcast_sd(alpha_cast); ymm1 = _mm256_broadcast_sd(beta_cast); //multiply A*B by alpha. ymm5 = _mm256_mul_pd(ymm5, ymm0); ymm7 = _mm256_mul_pd(ymm7, ymm0); ymm9 = _mm256_mul_pd(ymm9, ymm0); if(is_beta_non_zero) { for (int i = 0; i < m_remainder; i++) { f_temp[i] = tC[i]; } ymm2 = _mm256_loadu_pd(f_temp); ymm5 = _mm256_fmadd_pd(ymm2, ymm1, ymm5); double* ttC = tC + ldc; for (int i = 0; i < m_remainder; i++) { f_temp[i] = ttC[i]; } ymm2 = _mm256_loadu_pd(f_temp); ymm7 = _mm256_fmadd_pd(ymm2, ymm1, ymm7); ttC += ldc; for (int i = 0; i < m_remainder; i++) { f_temp[i] = ttC[i]; } ymm2 = _mm256_loadu_pd(f_temp); ymm9 = _mm256_fmadd_pd(ymm2, ymm1, ymm9); } _mm256_storeu_pd(f_temp, ymm5); for (int i = 0; i < m_remainder; i++) { tC[i] = f_temp[i]; } tC += ldc; _mm256_storeu_pd(f_temp, ymm7); for (int i = 0; i < m_remainder; i++) { tC[i] = f_temp[i]; } tC += ldc; _mm256_storeu_pd(f_temp, ymm9); for (int i = 0; i < m_remainder; i++) { tC[i] = f_temp[i]; } } n_remainder = N - col_idx; // if the N is not multiple of 3. // handling edge case. if (n_remainder == 2) { //pointer math to point to proper memory tC = C + ldc * col_idx + row_idx; tB = B + tb_inc_col * col_idx; tA = A + row_idx; ymm5 = _mm256_setzero_pd(); ymm7 = _mm256_setzero_pd(); for (k = 0; k < (K - 1); ++k) { // The inner loop broadcasts the B matrix data and // multiplies it with the A matrix. ymm0 = _mm256_broadcast_sd(tB + tb_inc_col * 0); ymm1 = _mm256_broadcast_sd(tB + tb_inc_col * 1); tB += tb_inc_row; ymm3 = _mm256_loadu_pd(tA); ymm5 = _mm256_fmadd_pd(ymm0, ymm3, ymm5); ymm7 = _mm256_fmadd_pd(ymm1, ymm3, ymm7); tA += lda; } ymm0 = _mm256_broadcast_sd(tB + tb_inc_col * 0); ymm1 = _mm256_broadcast_sd(tB + tb_inc_col * 1); tB += tb_inc_row; for (int i = 0; i < m_remainder; i++) { f_temp[i] = tA[i]; } ymm3 = _mm256_loadu_pd(f_temp); ymm5 = _mm256_fmadd_pd(ymm0, ymm3, ymm5); ymm7 = _mm256_fmadd_pd(ymm1, ymm3, ymm7); ymm0 = _mm256_broadcast_sd(alpha_cast); ymm1 = _mm256_broadcast_sd(beta_cast); ymm5 = _mm256_mul_pd(ymm5, ymm0); ymm7 = _mm256_mul_pd(ymm7, ymm0); if(is_beta_non_zero) { for (int i = 0; i < m_remainder; i++) { f_temp[i] = tC[i]; } ymm2 = _mm256_loadu_pd(f_temp); ymm5 = _mm256_fmadd_pd(ymm2, ymm1, ymm5); double* ttC = tC + ldc; for (int i = 0; i < m_remainder; i++) { f_temp[i] = ttC[i]; } ymm2 = _mm256_loadu_pd(f_temp); ymm7 = _mm256_fmadd_pd(ymm2, ymm1, ymm7); } _mm256_storeu_pd(f_temp, ymm5); for (int i = 0; i < m_remainder; i++) { tC[i] = f_temp[i]; } tC += ldc; _mm256_storeu_pd(f_temp, ymm7); for (int i = 0; i < m_remainder; i++) { tC[i] = f_temp[i]; } } // if the N is not multiple of 3. // handling edge case. if (n_remainder == 1) { //pointer math to point to proper memory tC = C + ldc * col_idx + row_idx; tB = B + tb_inc_col * col_idx; tA = A + row_idx; ymm5 = _mm256_setzero_pd(); for (k = 0; k < (K - 1); ++k) { // The inner loop broadcasts the B matrix data and // multiplies it with the A matrix. ymm0 = _mm256_broadcast_sd(tB + tb_inc_col * 0); tB += tb_inc_row; ymm3 = _mm256_loadu_pd(tA); ymm5 = _mm256_fmadd_pd(ymm0, ymm3, ymm5); tA += lda; } ymm0 = _mm256_broadcast_sd(tB + tb_inc_col * 0); tB += tb_inc_row; for (int i = 0; i < m_remainder; i++) { f_temp[i] = tA[i]; } ymm3 = _mm256_loadu_pd(f_temp); ymm5 = _mm256_fmadd_pd(ymm0, ymm3, ymm5); ymm0 = _mm256_broadcast_sd(alpha_cast); ymm1 = _mm256_broadcast_sd(beta_cast); // multiply C by beta and accumulate. ymm5 = _mm256_mul_pd(ymm5, ymm0); if(is_beta_non_zero) { for (int i = 0; i < m_remainder; i++) { f_temp[i] = tC[i]; } ymm2 = _mm256_loadu_pd(f_temp); ymm5 = _mm256_fmadd_pd(ymm2, ymm1, ymm5); } _mm256_storeu_pd(f_temp, ymm5); for (int i = 0; i < m_remainder; i++) { tC[i] = f_temp[i]; } } m_remainder = 0; } if (m_remainder) { double result; for (; row_idx < M; row_idx += 1) { for (col_idx = 0; col_idx < N; col_idx += 1) { //pointer math to point to proper memory tC = C + ldc * col_idx + row_idx; tB = B + tb_inc_col * col_idx; tA = A + row_idx; result = 0; for (k = 0; k < K; ++k) { result += (*tA) * (*tB); tA += lda; tB += tb_inc_row; } result *= (*alpha_cast); if(is_beta_non_zero) (*tC) = (*tC) * (*beta_cast) + result; else (*tC) = result; } } } // Return the buffer to pool if ((required_packing_A == 1) && bli_mem_is_alloc( &local_mem_buf_A_s )) { #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_dgemm_small(): releasing mem pool block\n" ); #endif bli_pba_release(&rntm, &local_mem_buf_A_s); } AOCL_DTL_TRACE_EXIT(AOCL_DTL_LEVEL_INFO); return BLIS_SUCCESS; } else { AOCL_DTL_TRACE_EXIT_ERR( AOCL_DTL_LEVEL_INFO, "Invalid dimesions for small gemm." ); return BLIS_NONCONFORMAL_DIMENSIONS; } }; static err_t bli_sgemm_small_atbn ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, cntl_t* cntl ) { AOCL_DTL_TRACE_ENTRY(AOCL_DTL_LEVEL_INFO); gint_t M = bli_obj_length( c ); // number of rows of Matrix C gint_t N = bli_obj_width( c ); // number of columns of Matrix C gint_t K = bli_obj_length( b ); // number of rows of Matrix B guint_t lda = bli_obj_col_stride( a ); // column stride of matrix OP(A), where OP(A) is Transpose(A) if transA enabled. guint_t ldb = bli_obj_col_stride( b ); // column stride of matrix OP(B), where OP(B) is Transpose(B) if transB enabled. guint_t ldc = bli_obj_col_stride( c ); // column stride of matrix C int row_idx = 0, col_idx = 0, k; float *A = bli_obj_buffer_at_off(a); // pointer to matrix A elements, stored in row major format float *B = bli_obj_buffer_at_off(b); // pointer to matrix B elements, stored in column major format float *C = bli_obj_buffer_at_off(c); // pointer to matrix C elements, stored in column major format float *tA = A, *tB = B, *tC = C; __m256 ymm4, ymm5, ymm6, ymm7; __m256 ymm8, ymm9, ymm10, ymm11; __m256 ymm12, ymm13, ymm14, ymm15; __m256 ymm0, ymm1, ymm2, ymm3; float result; float scratch[8] = {0.0}; const num_t dt_exec = bli_obj_dt( c ); float* restrict alpha_cast = bli_obj_buffer_for_1x1( dt_exec, alpha ); float* restrict beta_cast = bli_obj_buffer_for_1x1( dt_exec, beta ); /*Beta Zero Check*/ bool is_beta_non_zero=0; if ( !bli_obj_equals( beta, &BLIS_ZERO ) ){ is_beta_non_zero = 1; } // The non-copy version of the A^T GEMM gives better performance for the small M cases. // The threshold is controlled by BLIS_ATBN_M_THRES if (M <= BLIS_ATBN_M_THRES) { for (col_idx = 0; (col_idx + (NR - 1)) < N; col_idx += NR) { for (row_idx = 0; (row_idx + (AT_MR - 1)) < M; row_idx += AT_MR) { tA = A + row_idx * lda; tB = B + col_idx * ldb; tC = C + col_idx * ldc + row_idx; // clear scratch registers. ymm4 = _mm256_setzero_ps(); ymm5 = _mm256_setzero_ps(); ymm6 = _mm256_setzero_ps(); ymm7 = _mm256_setzero_ps(); ymm8 = _mm256_setzero_ps(); ymm9 = _mm256_setzero_ps(); ymm10 = _mm256_setzero_ps(); ymm11 = _mm256_setzero_ps(); ymm12 = _mm256_setzero_ps(); ymm13 = _mm256_setzero_ps(); ymm14 = _mm256_setzero_ps(); ymm15 = _mm256_setzero_ps(); //The inner loop computes the 4x3 values of the matrix. //The computation pattern is: // ymm4 ymm5 ymm6 // ymm7 ymm8 ymm9 // ymm10 ymm11 ymm12 // ymm13 ymm14 ymm15 //The Dot operation is performed in the inner loop, 8 float elements fit //in the YMM register hence loop count incremented by 8 for (k = 0; (k + 7) < K; k += 8) { ymm0 = _mm256_loadu_ps(tB + 0); ymm1 = _mm256_loadu_ps(tB + ldb); ymm2 = _mm256_loadu_ps(tB + 2 * ldb); ymm3 = _mm256_loadu_ps(tA); ymm4 = _mm256_fmadd_ps(ymm0, ymm3, ymm4); ymm5 = _mm256_fmadd_ps(ymm1, ymm3, ymm5); ymm6 = _mm256_fmadd_ps(ymm2, ymm3, ymm6); ymm3 = _mm256_loadu_ps(tA + lda); ymm7 = _mm256_fmadd_ps(ymm0, ymm3, ymm7); ymm8 = _mm256_fmadd_ps(ymm1, ymm3, ymm8); ymm9 = _mm256_fmadd_ps(ymm2, ymm3, ymm9); ymm3 = _mm256_loadu_ps(tA + 2 * lda); ymm10 = _mm256_fmadd_ps(ymm0, ymm3, ymm10); ymm11 = _mm256_fmadd_ps(ymm1, ymm3, ymm11); ymm12 = _mm256_fmadd_ps(ymm2, ymm3, ymm12); ymm3 = _mm256_loadu_ps(tA + 3 * lda); ymm13 = _mm256_fmadd_ps(ymm0, ymm3, ymm13); ymm14 = _mm256_fmadd_ps(ymm1, ymm3, ymm14); ymm15 = _mm256_fmadd_ps(ymm2, ymm3, ymm15); tA += 8; tB += 8; } // if K is not a multiple of 8, padding is done before load using temproary array. if (k < K) { int iter; float data_feeder[8] = { 0.0 }; for (iter = 0; iter < (K - k); iter++) data_feeder[iter] = tB[iter]; ymm0 = _mm256_loadu_ps(data_feeder); for (iter = 0; iter < (K - k); iter++) data_feeder[iter] = tB[iter + ldb]; ymm1 = _mm256_loadu_ps(data_feeder); for (iter = 0; iter < (K - k); iter++) data_feeder[iter] = tB[iter + 2 * ldb]; ymm2 = _mm256_loadu_ps(data_feeder); for (iter = 0; iter < (K - k); iter++) data_feeder[iter] = tA[iter]; ymm3 = _mm256_loadu_ps(data_feeder); ymm4 = _mm256_fmadd_ps(ymm0, ymm3, ymm4); ymm5 = _mm256_fmadd_ps(ymm1, ymm3, ymm5); ymm6 = _mm256_fmadd_ps(ymm2, ymm3, ymm6); for (iter = 0; iter < (K - k); iter++) data_feeder[iter] = tA[lda + iter]; ymm3 = _mm256_loadu_ps(data_feeder); ymm7 = _mm256_fmadd_ps(ymm0, ymm3, ymm7); ymm8 = _mm256_fmadd_ps(ymm1, ymm3, ymm8); ymm9 = _mm256_fmadd_ps(ymm2, ymm3, ymm9); for (iter = 0; iter < (K - k); iter++) data_feeder[iter] = tA[2 * lda + iter]; ymm3 = _mm256_loadu_ps(data_feeder); ymm10 = _mm256_fmadd_ps(ymm0, ymm3, ymm10); ymm11 = _mm256_fmadd_ps(ymm1, ymm3, ymm11); ymm12 = _mm256_fmadd_ps(ymm2, ymm3, ymm12); for (iter = 0; iter < (K - k); iter++) data_feeder[iter] = tA[3 * lda + iter]; ymm3 = _mm256_loadu_ps(data_feeder); ymm13 = _mm256_fmadd_ps(ymm0, ymm3, ymm13); ymm14 = _mm256_fmadd_ps(ymm1, ymm3, ymm14); ymm15 = _mm256_fmadd_ps(ymm2, ymm3, ymm15); } //horizontal addition and storage of the data. //Results for 4x3 blocks of C is stored here ymm4 = _mm256_hadd_ps(ymm4, ymm4); ymm4 = _mm256_hadd_ps(ymm4, ymm4); _mm256_storeu_ps(scratch, ymm4); result = scratch[0] + scratch[4]; result *= (*alpha_cast); if(is_beta_non_zero){ tC[0] = result + tC[0] * (*beta_cast); }else{ tC[0] = result; } ymm7 = _mm256_hadd_ps(ymm7, ymm7); ymm7 = _mm256_hadd_ps(ymm7, ymm7); _mm256_storeu_ps(scratch, ymm7); result = scratch[0] + scratch[4]; result *= (*alpha_cast); if(is_beta_non_zero){ tC[1] = result + tC[1] * (*beta_cast); }else{ tC[1] = result; } ymm10 = _mm256_hadd_ps(ymm10, ymm10); ymm10 = _mm256_hadd_ps(ymm10, ymm10); _mm256_storeu_ps(scratch, ymm10); result = scratch[0] + scratch[4]; result *= (*alpha_cast); if(is_beta_non_zero){ tC[2] = result + tC[2] * (*beta_cast); }else{ tC[2] = result; } ymm13 = _mm256_hadd_ps(ymm13, ymm13); ymm13 = _mm256_hadd_ps(ymm13, ymm13); _mm256_storeu_ps(scratch, ymm13); result = scratch[0] + scratch[4]; result *= (*alpha_cast); if(is_beta_non_zero){ tC[3] = result + tC[3] * (*beta_cast); }else{ tC[3] = result; } tC += ldc; ymm5 = _mm256_hadd_ps(ymm5, ymm5); ymm5 = _mm256_hadd_ps(ymm5, ymm5); _mm256_storeu_ps(scratch, ymm5); result = scratch[0] + scratch[4]; result *= (*alpha_cast); if(is_beta_non_zero){ tC[0] = result + tC[0] * (*beta_cast); }else{ tC[0] = result; } ymm8 = _mm256_hadd_ps(ymm8, ymm8); ymm8 = _mm256_hadd_ps(ymm8, ymm8); _mm256_storeu_ps(scratch, ymm8); result = scratch[0] + scratch[4]; result *= (*alpha_cast); if(is_beta_non_zero){ tC[1] = result + tC[1] * (*beta_cast); }else{ tC[1] = result; } ymm11 = _mm256_hadd_ps(ymm11, ymm11); ymm11 = _mm256_hadd_ps(ymm11, ymm11); _mm256_storeu_ps(scratch, ymm11); result = scratch[0] + scratch[4]; result *= (*alpha_cast); if(is_beta_non_zero){ tC[2] = result + tC[2] * (*beta_cast); }else{ tC[2] = result; } ymm14 = _mm256_hadd_ps(ymm14, ymm14); ymm14 = _mm256_hadd_ps(ymm14, ymm14); _mm256_storeu_ps(scratch, ymm14); result = scratch[0] + scratch[4]; result *= (*alpha_cast); if(is_beta_non_zero){ tC[3] = result + tC[3] * (*beta_cast); }else{ tC[3] = result; } tC += ldc; ymm6 = _mm256_hadd_ps(ymm6, ymm6); ymm6 = _mm256_hadd_ps(ymm6, ymm6); _mm256_storeu_ps(scratch, ymm6); result = scratch[0] + scratch[4]; result *= (*alpha_cast); if(is_beta_non_zero){ tC[0] = result + tC[0] * (*beta_cast); }else{ tC[0] = result; } ymm9 = _mm256_hadd_ps(ymm9, ymm9); ymm9 = _mm256_hadd_ps(ymm9, ymm9); _mm256_storeu_ps(scratch, ymm9); result = scratch[0] + scratch[4]; result *= (*alpha_cast); if(is_beta_non_zero){ tC[1] = result + tC[1] * (*beta_cast); }else{ tC[1] = result; } ymm12 = _mm256_hadd_ps(ymm12, ymm12); ymm12 = _mm256_hadd_ps(ymm12, ymm12); _mm256_storeu_ps(scratch, ymm12); result = scratch[0] + scratch[4]; result *= (*alpha_cast); if(is_beta_non_zero){ tC[2] = result + tC[2] * (*beta_cast); }else{ tC[2] = result; } ymm15 = _mm256_hadd_ps(ymm15, ymm15); ymm15 = _mm256_hadd_ps(ymm15, ymm15); _mm256_storeu_ps(scratch, ymm15); result = scratch[0] + scratch[4]; result *= (*alpha_cast); if(is_beta_non_zero){ tC[3] = result + tC[3] * (*beta_cast); }else{ tC[3] = result; } } } int processed_col = col_idx; int processed_row = row_idx; //The edge case handling where N is not a multiple of 3 if (processed_col < N) { for (col_idx = processed_col; col_idx < N; col_idx += 1) { for (row_idx = 0; (row_idx + (AT_MR - 1)) < M; row_idx += AT_MR) { tA = A + row_idx * lda; tB = B + col_idx * ldb; tC = C + col_idx * ldc + row_idx; // clear scratch registers. ymm4 = _mm256_setzero_ps(); ymm7 = _mm256_setzero_ps(); ymm10 = _mm256_setzero_ps(); ymm13 = _mm256_setzero_ps(); //The inner loop computes the 4x1 values of the matrix. //The computation pattern is: // ymm4 // ymm7 // ymm10 // ymm13 for (k = 0; (k + 7) < K; k += 8) { ymm0 = _mm256_loadu_ps(tB + 0); ymm3 = _mm256_loadu_ps(tA); ymm4 = _mm256_fmadd_ps(ymm0, ymm3, ymm4); ymm3 = _mm256_loadu_ps(tA + lda); ymm7 = _mm256_fmadd_ps(ymm0, ymm3, ymm7); ymm3 = _mm256_loadu_ps(tA + 2 * lda); ymm10 = _mm256_fmadd_ps(ymm0, ymm3, ymm10); ymm3 = _mm256_loadu_ps(tA + 3 * lda); ymm13 = _mm256_fmadd_ps(ymm0, ymm3, ymm13); tA += 8; tB += 8; } // if K is not a multiple of 8, padding is done before load using temproary array. if (k < K) { int iter; float data_feeder[8] = { 0.0 }; for (iter = 0; iter < (K - k); iter++) data_feeder[iter] = tB[iter]; ymm0 = _mm256_loadu_ps(data_feeder); for (iter = 0; iter < (K - k); iter++) data_feeder[iter] = tA[iter]; ymm3 = _mm256_loadu_ps(data_feeder); ymm4 = _mm256_fmadd_ps(ymm0, ymm3, ymm4); for (iter = 0; iter < (K - k); iter++) data_feeder[iter] = tA[lda + iter]; ymm3 = _mm256_loadu_ps(data_feeder); ymm7 = _mm256_fmadd_ps(ymm0, ymm3, ymm7); for (iter = 0; iter < (K - k); iter++) data_feeder[iter] = tA[2 * lda + iter]; ymm3 = _mm256_loadu_ps(data_feeder); ymm10 = _mm256_fmadd_ps(ymm0, ymm3, ymm10); for (iter = 0; iter < (K - k); iter++) data_feeder[iter] = tA[3 * lda + iter]; ymm3 = _mm256_loadu_ps(data_feeder); ymm13 = _mm256_fmadd_ps(ymm0, ymm3, ymm13); } //horizontal addition and storage of the data. //Results for 4x1 blocks of C is stored here ymm4 = _mm256_hadd_ps(ymm4, ymm4); ymm4 = _mm256_hadd_ps(ymm4, ymm4); _mm256_storeu_ps(scratch, ymm4); result = scratch[0] + scratch[4]; result *= (*alpha_cast); if(is_beta_non_zero){ tC[0] = result + tC[0] * (*beta_cast); }else{ tC[0] = result; } ymm7 = _mm256_hadd_ps(ymm7, ymm7); ymm7 = _mm256_hadd_ps(ymm7, ymm7); _mm256_storeu_ps(scratch, ymm7); result = scratch[0] + scratch[4]; result *= (*alpha_cast); if(is_beta_non_zero){ tC[1] = result + tC[1] * (*beta_cast); }else{ tC[1] = result; } ymm10 = _mm256_hadd_ps(ymm10, ymm10); ymm10 = _mm256_hadd_ps(ymm10, ymm10); _mm256_storeu_ps(scratch, ymm10); result = scratch[0] + scratch[4]; result *= (*alpha_cast); if(is_beta_non_zero){ tC[2] = result + tC[2] * (*beta_cast); }else{ tC[2] = result; } ymm13 = _mm256_hadd_ps(ymm13, ymm13); ymm13 = _mm256_hadd_ps(ymm13, ymm13); _mm256_storeu_ps(scratch, ymm13); result = scratch[0] + scratch[4]; result *= (*alpha_cast); if(is_beta_non_zero){ tC[3] = result + tC[3] * (*beta_cast); }else{ tC[3] = result; } } } processed_row = row_idx; } //The edge case handling where M is not a multiple of 4 if (processed_row < M) { for (row_idx = processed_row; row_idx < M; row_idx += 1) { for (col_idx = 0; col_idx < N; col_idx += 1) { tA = A + row_idx * lda; tB = B + col_idx * ldb; tC = C + col_idx * ldc + row_idx; // clear scratch registers. ymm4 = _mm256_setzero_ps(); for (k = 0; (k + 7) < K; k += 8) { ymm0 = _mm256_loadu_ps(tB + 0); ymm3 = _mm256_loadu_ps(tA); ymm4 = _mm256_fmadd_ps(ymm0, ymm3, ymm4); tA += 8; tB += 8; } // if K is not a multiple of 8, padding is done before load using temproary array. if (k < K) { int iter; float data_feeder[8] = { 0.0 }; for (iter = 0; iter < (K - k); iter++) data_feeder[iter] = tB[iter]; ymm0 = _mm256_loadu_ps(data_feeder); for (iter = 0; iter < (K - k); iter++) data_feeder[iter] = tA[iter]; ymm3 = _mm256_loadu_ps(data_feeder); ymm4 = _mm256_fmadd_ps(ymm0, ymm3, ymm4); } //horizontal addition and storage of the data. ymm4 = _mm256_hadd_ps(ymm4, ymm4); ymm4 = _mm256_hadd_ps(ymm4, ymm4); _mm256_storeu_ps(scratch, ymm4); result = scratch[0] + scratch[4]; result *= (*alpha_cast); if(is_beta_non_zero){ tC[0] = result + tC[0] * (*beta_cast); }else{ tC[0] = result; } } } } AOCL_DTL_TRACE_EXIT(AOCL_DTL_LEVEL_INFO); return BLIS_SUCCESS; } else { AOCL_DTL_TRACE_EXIT_ERR( AOCL_DTL_LEVEL_INFO, "Invalid dimesions for small gemm." ); return BLIS_NONCONFORMAL_DIMENSIONS; } } static err_t bli_dgemm_small_atbn ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, cntl_t* cntl ) { AOCL_DTL_TRACE_ENTRY(AOCL_DTL_LEVEL_INFO); gint_t M = bli_obj_length( c ); // number of rows of Matrix C gint_t N = bli_obj_width( c ); // number of columns of Matrix C gint_t K = bli_obj_length( b ); // number of rows of Matrix B // The non-copy version of the A^T GEMM gives better performance for the small M cases. // The threshold is controlled by BLIS_ATBN_M_THRES if (M <= BLIS_ATBN_M_THRES) { guint_t lda = bli_obj_col_stride( a ); // column stride of matrix OP(A), where OP(A) is Transpose(A) if transA enabled. guint_t ldb = bli_obj_col_stride( b ); // column stride of matrix OP(B), where OP(B) is Transpose(B) if transB enabled. guint_t ldc = bli_obj_col_stride( c ); // column stride of matrix C guint_t row_idx = 0, col_idx = 0, k; double *A = bli_obj_buffer_at_off(a); // pointer to matrix A elements, stored in row major format double *B = bli_obj_buffer_at_off(b); // pointer to matrix B elements, stored in column major format double *C = bli_obj_buffer_at_off(c); // pointer to matrix C elements, stored in column major format double *tA = A, *tB = B, *tC = C; __m256d ymm4, ymm5, ymm6, ymm7; __m256d ymm8, ymm9, ymm10, ymm11; __m256d ymm12, ymm13, ymm14, ymm15; __m256d ymm0, ymm1, ymm2, ymm3; double result; double scratch[8] = {0.0}; double *alpha_cast, *beta_cast; // alpha, beta multiples alpha_cast = bli_obj_buffer_for_1x1(BLIS_DOUBLE, alpha); beta_cast = bli_obj_buffer_for_1x1(BLIS_DOUBLE, beta); //check if beta is zero //if true, we need to perform C = alpha * (A * B) //instead of C = beta * C + alpha * (A * B) bool is_beta_non_zero = 0; if(!bli_obj_equals(beta,&BLIS_ZERO)) is_beta_non_zero = 1; for (col_idx = 0; (col_idx + (NR - 1)) < N; col_idx += NR) { for (row_idx = 0; (row_idx + (AT_MR - 1)) < M; row_idx += AT_MR) { tA = A + row_idx * lda; tB = B + col_idx * ldb; tC = C + col_idx * ldc + row_idx; // clear scratch registers. ymm4 = _mm256_setzero_pd(); ymm5 = _mm256_setzero_pd(); ymm6 = _mm256_setzero_pd(); ymm7 = _mm256_setzero_pd(); ymm8 = _mm256_setzero_pd(); ymm9 = _mm256_setzero_pd(); ymm10 = _mm256_setzero_pd(); ymm11 = _mm256_setzero_pd(); ymm12 = _mm256_setzero_pd(); ymm13 = _mm256_setzero_pd(); ymm14 = _mm256_setzero_pd(); ymm15 = _mm256_setzero_pd(); //The inner loop computes the 4x3 values of the matrix. //The computation pattern is: // ymm4 ymm5 ymm6 // ymm7 ymm8 ymm9 // ymm10 ymm11 ymm12 // ymm13 ymm14 ymm15 //The Dot operation is performed in the inner loop, 4 double elements fit //in the YMM register hence loop count incremented by 4 for (k = 0; (k + 3) < K; k += 4) { ymm0 = _mm256_loadu_pd(tB + 0); ymm1 = _mm256_loadu_pd(tB + ldb); ymm2 = _mm256_loadu_pd(tB + 2 * ldb); ymm3 = _mm256_loadu_pd(tA); ymm4 = _mm256_fmadd_pd(ymm0, ymm3, ymm4); ymm5 = _mm256_fmadd_pd(ymm1, ymm3, ymm5); ymm6 = _mm256_fmadd_pd(ymm2, ymm3, ymm6); ymm3 = _mm256_loadu_pd(tA + lda); ymm7 = _mm256_fmadd_pd(ymm0, ymm3, ymm7); ymm8 = _mm256_fmadd_pd(ymm1, ymm3, ymm8); ymm9 = _mm256_fmadd_pd(ymm2, ymm3, ymm9); ymm3 = _mm256_loadu_pd(tA + 2 * lda); ymm10 = _mm256_fmadd_pd(ymm0, ymm3, ymm10); ymm11 = _mm256_fmadd_pd(ymm1, ymm3, ymm11); ymm12 = _mm256_fmadd_pd(ymm2, ymm3, ymm12); ymm3 = _mm256_loadu_pd(tA + 3 * lda); ymm13 = _mm256_fmadd_pd(ymm0, ymm3, ymm13); ymm14 = _mm256_fmadd_pd(ymm1, ymm3, ymm14); ymm15 = _mm256_fmadd_pd(ymm2, ymm3, ymm15); tA += 4; tB += 4; } // if K is not a multiple of 4, padding is done before load using temproary array. if (k < K) { int iter; double data_feeder[4] = { 0.0 }; for (iter = 0; iter < (K - k); iter++) data_feeder[iter] = tB[iter]; ymm0 = _mm256_loadu_pd(data_feeder); for (iter = 0; iter < (K - k); iter++) data_feeder[iter] = tB[iter + ldb]; ymm1 = _mm256_loadu_pd(data_feeder); for (iter = 0; iter < (K - k); iter++) data_feeder[iter] = tB[iter + 2 * ldb]; ymm2 = _mm256_loadu_pd(data_feeder); for (iter = 0; iter < (K - k); iter++) data_feeder[iter] = tA[iter]; ymm3 = _mm256_loadu_pd(data_feeder); ymm4 = _mm256_fmadd_pd(ymm0, ymm3, ymm4); ymm5 = _mm256_fmadd_pd(ymm1, ymm3, ymm5); ymm6 = _mm256_fmadd_pd(ymm2, ymm3, ymm6); for (iter = 0; iter < (K - k); iter++) data_feeder[iter] = tA[lda + iter]; ymm3 = _mm256_loadu_pd(data_feeder); ymm7 = _mm256_fmadd_pd(ymm0, ymm3, ymm7); ymm8 = _mm256_fmadd_pd(ymm1, ymm3, ymm8); ymm9 = _mm256_fmadd_pd(ymm2, ymm3, ymm9); for (iter = 0; iter < (K - k); iter++) data_feeder[iter] = tA[2 * lda + iter]; ymm3 = _mm256_loadu_pd(data_feeder); ymm10 = _mm256_fmadd_pd(ymm0, ymm3, ymm10); ymm11 = _mm256_fmadd_pd(ymm1, ymm3, ymm11); ymm12 = _mm256_fmadd_pd(ymm2, ymm3, ymm12); for (iter = 0; iter < (K - k); iter++) data_feeder[iter] = tA[3 * lda + iter]; ymm3 = _mm256_loadu_pd(data_feeder); ymm13 = _mm256_fmadd_pd(ymm0, ymm3, ymm13); ymm14 = _mm256_fmadd_pd(ymm1, ymm3, ymm14); ymm15 = _mm256_fmadd_pd(ymm2, ymm3, ymm15); } //horizontal addition and storage of the data. //Results for 4x3 blocks of C is stored here ymm4 = _mm256_hadd_pd(ymm4, ymm4); _mm256_storeu_pd(scratch, ymm4); result = scratch[0] + scratch[2]; result *= (*alpha_cast); if(is_beta_non_zero) tC[0] = result + tC[0] * (*beta_cast); else tC[0] = result; ymm7 = _mm256_hadd_pd(ymm7, ymm7); _mm256_storeu_pd(scratch, ymm7); result = scratch[0] + scratch[2]; result *= (*alpha_cast); if(is_beta_non_zero) tC[1] = result + tC[1] * (*beta_cast); else tC[1] = result; ymm10 = _mm256_hadd_pd(ymm10, ymm10); _mm256_storeu_pd(scratch, ymm10); result = scratch[0] + scratch[2]; result *= (*alpha_cast); if(is_beta_non_zero) tC[2] = result + tC[2] * (*beta_cast); else tC[2] = result; ymm13 = _mm256_hadd_pd(ymm13, ymm13); _mm256_storeu_pd(scratch, ymm13); result = scratch[0] + scratch[2]; result *= (*alpha_cast); if(is_beta_non_zero) tC[3] = result + tC[3] * (*beta_cast); else tC[3] = result; tC += ldc; ymm5 = _mm256_hadd_pd(ymm5, ymm5); _mm256_storeu_pd(scratch, ymm5); result = scratch[0] + scratch[2]; result *= (*alpha_cast); if(is_beta_non_zero) tC[0] = result + tC[0] * (*beta_cast); else tC[0] = result; ymm8 = _mm256_hadd_pd(ymm8, ymm8); _mm256_storeu_pd(scratch, ymm8); result = scratch[0] + scratch[2]; result *= (*alpha_cast); if(is_beta_non_zero) tC[1] = result + tC[1] * (*beta_cast); else tC[1] = result; ymm11 = _mm256_hadd_pd(ymm11, ymm11); _mm256_storeu_pd(scratch, ymm11); result = scratch[0] + scratch[2]; result *= (*alpha_cast); if(is_beta_non_zero) tC[2] = result + tC[2] * (*beta_cast); else tC[2] = result; ymm14 = _mm256_hadd_pd(ymm14, ymm14); _mm256_storeu_pd(scratch, ymm14); result = scratch[0] + scratch[2]; result *= (*alpha_cast); if(is_beta_non_zero) tC[3] = result + tC[3] * (*beta_cast); else tC[3] = result; tC += ldc; ymm6 = _mm256_hadd_pd(ymm6, ymm6); _mm256_storeu_pd(scratch, ymm6); result = scratch[0] + scratch[2]; result *= (*alpha_cast); if(is_beta_non_zero) tC[0] = result + tC[0] * (*beta_cast); else tC[0] = result; ymm9 = _mm256_hadd_pd(ymm9, ymm9); _mm256_storeu_pd(scratch, ymm9); result = scratch[0] + scratch[2]; result *= (*alpha_cast); if(is_beta_non_zero) tC[1] = result + tC[1] * (*beta_cast); else tC[1] = result; ymm12 = _mm256_hadd_pd(ymm12, ymm12); _mm256_storeu_pd(scratch, ymm12); result = scratch[0] + scratch[2]; result *= (*alpha_cast); if(is_beta_non_zero) tC[2] = result + tC[2] * (*beta_cast); else tC[2] = result; ymm15 = _mm256_hadd_pd(ymm15, ymm15); _mm256_storeu_pd(scratch, ymm15); result = scratch[0] + scratch[2]; result *= (*alpha_cast); if(is_beta_non_zero) tC[3] = result + tC[3] * (*beta_cast); else tC[3] = result; } } int processed_col = col_idx; int processed_row = row_idx; //The edge case handling where N is not a multiple of 3 if (processed_col < N) { for (col_idx = processed_col; col_idx < N; col_idx += 1) { for (row_idx = 0; (row_idx + (AT_MR - 1)) < M; row_idx += AT_MR) { tA = A + row_idx * lda; tB = B + col_idx * ldb; tC = C + col_idx * ldc + row_idx; // clear scratch registers. ymm4 = _mm256_setzero_pd(); ymm7 = _mm256_setzero_pd(); ymm10 = _mm256_setzero_pd(); ymm13 = _mm256_setzero_pd(); //The inner loop computes the 4x1 values of the matrix. //The computation pattern is: // ymm4 // ymm7 // ymm10 // ymm13 for (k = 0; (k + 3) < K; k += 4) { ymm0 = _mm256_loadu_pd(tB + 0); ymm3 = _mm256_loadu_pd(tA); ymm4 = _mm256_fmadd_pd(ymm0, ymm3, ymm4); ymm3 = _mm256_loadu_pd(tA + lda); ymm7 = _mm256_fmadd_pd(ymm0, ymm3, ymm7); ymm3 = _mm256_loadu_pd(tA + 2 * lda); ymm10 = _mm256_fmadd_pd(ymm0, ymm3, ymm10); ymm3 = _mm256_loadu_pd(tA + 3 * lda); ymm13 = _mm256_fmadd_pd(ymm0, ymm3, ymm13); tA += 4; tB += 4; } // if K is not a multiple of 4, padding is done before load using temproary array. if (k < K) { int iter; double data_feeder[4] = { 0.0 }; for (iter = 0; iter < (K - k); iter++) data_feeder[iter] = tB[iter]; ymm0 = _mm256_loadu_pd(data_feeder); for (iter = 0; iter < (K - k); iter++) data_feeder[iter] = tA[iter]; ymm3 = _mm256_loadu_pd(data_feeder); ymm4 = _mm256_fmadd_pd(ymm0, ymm3, ymm4); for (iter = 0; iter < (K - k); iter++) data_feeder[iter] = tA[lda + iter]; ymm3 = _mm256_loadu_pd(data_feeder); ymm7 = _mm256_fmadd_pd(ymm0, ymm3, ymm7); for (iter = 0; iter < (K - k); iter++) data_feeder[iter] = tA[2 * lda + iter]; ymm3 = _mm256_loadu_pd(data_feeder); ymm10 = _mm256_fmadd_pd(ymm0, ymm3, ymm10); for (iter = 0; iter < (K - k); iter++) data_feeder[iter] = tA[3 * lda + iter]; ymm3 = _mm256_loadu_pd(data_feeder); ymm13 = _mm256_fmadd_pd(ymm0, ymm3, ymm13); } //horizontal addition and storage of the data. //Results for 4x1 blocks of C is stored here ymm4 = _mm256_hadd_pd(ymm4, ymm4); _mm256_storeu_pd(scratch, ymm4); result = scratch[0] + scratch[2]; result *= (*alpha_cast); if(is_beta_non_zero) tC[0] = result + tC[0] * (*beta_cast); else tC[0] = result; ymm7 = _mm256_hadd_pd(ymm7, ymm7); _mm256_storeu_pd(scratch, ymm7); result = scratch[0] + scratch[2]; result *= (*alpha_cast); if(is_beta_non_zero) tC[1] = result + tC[1] * (*beta_cast); else tC[1] = result; ymm10 = _mm256_hadd_pd(ymm10, ymm10); _mm256_storeu_pd(scratch, ymm10); result = scratch[0] + scratch[2]; result *= (*alpha_cast); if(is_beta_non_zero) tC[2] = result + tC[2] * (*beta_cast); else tC[2] = result; ymm13 = _mm256_hadd_pd(ymm13, ymm13); _mm256_storeu_pd(scratch, ymm13); result = scratch[0] + scratch[2]; result *= (*alpha_cast); if(is_beta_non_zero) tC[3] = result + tC[3] * (*beta_cast); else tC[3] = result; } } processed_row = row_idx; } // The edge case handling where M is not a multiple of 4 if (processed_row < M) { for (row_idx = processed_row; row_idx < M; row_idx += 1) { for (col_idx = 0; col_idx < N; col_idx += 1) { tA = A + row_idx * lda; tB = B + col_idx * ldb; tC = C + col_idx * ldc + row_idx; // clear scratch registers. ymm4 = _mm256_setzero_pd(); for (k = 0; (k + 3) < K; k += 4) { ymm0 = _mm256_loadu_pd(tB + 0); ymm3 = _mm256_loadu_pd(tA); ymm4 = _mm256_fmadd_pd(ymm0, ymm3, ymm4); tA += 4; tB += 4; } // if K is not a multiple of 4, padding is done before load using temproary array. if (k < K) { int iter; double data_feeder[4] = { 0.0 }; for (iter = 0; iter < (K - k); iter++) data_feeder[iter] = tB[iter]; ymm0 = _mm256_loadu_pd(data_feeder); for (iter = 0; iter < (K - k); iter++) data_feeder[iter] = tA[iter]; ymm3 = _mm256_loadu_pd(data_feeder); ymm4 = _mm256_fmadd_pd(ymm0, ymm3, ymm4); } //horizontal addition and storage of the data. ymm4 = _mm256_hadd_pd(ymm4, ymm4); _mm256_storeu_pd(scratch, ymm4); result = scratch[0] + scratch[2]; result *= (*alpha_cast); if(is_beta_non_zero) tC[0] = result + tC[0] * (*beta_cast); else tC[0] = result; } } } AOCL_DTL_TRACE_EXIT(AOCL_DTL_LEVEL_INFO); return BLIS_SUCCESS; } else { AOCL_DTL_TRACE_EXIT_ERR( AOCL_DTL_LEVEL_INFO, "Invalid dimesions for small gemm." ); return BLIS_NONCONFORMAL_DIMENSIONS; } } #endif blis-0.9.0/kernels/zen/3/bli_gemmt_small.c000066400000000000000000005140621422157504600203630ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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 The University of Texas at Austin 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 COPYRIGHT HOLDER 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 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. */ #include "immintrin.h" #include "xmmintrin.h" #include "blis.h" #ifdef BLIS_ENABLE_SMALL_MATRIX #define MR 32 #define D_MR (MR >> 1) #define NR 3 #define BLIS_ENABLE_PREFETCH #define F_SCRATCH_DIM (BLIS_SMALL_MATRIX_THRES * BLIS_SMALL_MATRIX_THRES) static float A_pack[F_SCRATCH_DIM] __attribute__((aligned(64))); static float C_pack[F_SCRATCH_DIM] __attribute__((aligned(64))); #define D_BLIS_SMALL_MATRIX_THRES (BLIS_SMALL_MATRIX_THRES / 2 ) #define D_BLIS_SMALL_M_RECT_MATRIX_THRES (BLIS_SMALL_M_RECT_MATRIX_THRES / 2) #define D_BLIS_SMALL_K_RECT_MATRIX_THRES (BLIS_SMALL_K_RECT_MATRIX_THRES / 2) #define D_SCRATCH_DIM (D_BLIS_SMALL_MATRIX_THRES * D_BLIS_SMALL_MATRIX_THRES) static double D_A_pack[D_SCRATCH_DIM] __attribute__((aligned(64))); static double D_C_pack[D_SCRATCH_DIM] __attribute__((aligned(64))); #define BLIS_ATBN_M_THRES 40 // Threshold value of M for/below which small matrix code is called. #define AT_MR 4 // The kernel dimension of the A transpose GEMMT kernel.(AT_MR * NR). static err_t bli_sgemmt_small ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, cntl_t* cntl ); static err_t bli_dgemmt_small ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, cntl_t* cntl ); static err_t bli_sgemmt_small_atbn ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, cntl_t* cntl ); static err_t bli_dgemmt_small_atbn ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, cntl_t* cntl ); /* * The bli_gemmt_small function will use the * custom MRxNR kernels, to perform the computation. * The custom kernels are used if the [M * N] < 240 * 240 */ err_t bli_gemmt_small ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, cntl_t* cntl ) { // FGVZ: This code was originally in bli_gemmt_front(). However, it really // fits more naturally here within the bli_gemmt_small() function. This // becomes a bit more obvious now that the code is here, as it contains // cpp macros such as BLIS_SMALL_MATRIX_A_THRES_M_GEMMT, which are specific // to this implementation. if ( bli_obj_has_trans( a ) ) { // Continue with small implementation. ; } else if ( ( bli_obj_length( a ) <= BLIS_SMALL_MATRIX_A_THRES_M_GEMMT && bli_obj_width( a ) < BLIS_SMALL_MATRIX_A_THRES_N_GEMMT ) || ( bli_obj_length( a ) < BLIS_SMALL_MATRIX_A_THRES_M_GEMMT && bli_obj_width( a ) <= BLIS_SMALL_MATRIX_A_THRES_N_GEMMT ) ) { // Continue with small implementation. ; } else { // Reject the problem and return to large code path. return BLIS_FAILURE; } #ifdef BLIS_ENABLE_MULTITHREADING return BLIS_NOT_YET_IMPLEMENTED; #endif // If alpha is zero, scale by beta and return. if (bli_obj_equals(alpha, &BLIS_ZERO)) { return BLIS_NOT_YET_IMPLEMENTED; } // if row major format return. if ((bli_obj_row_stride( a ) != 1) || (bli_obj_row_stride( b ) != 1) || (bli_obj_row_stride( c ) != 1)) { return BLIS_INVALID_ROW_STRIDE; } num_t dt = ((*c).info & (0x7 << 0)); if (bli_obj_has_trans( a )) { if (bli_obj_has_notrans( b )) { if (dt == BLIS_FLOAT) { return bli_sgemmt_small_atbn(alpha, a, b, beta, c, cntx, cntl); } else if (dt == BLIS_DOUBLE) { return bli_dgemmt_small_atbn(alpha, a, b, beta, c, cntx, cntl); } } return BLIS_NOT_YET_IMPLEMENTED; } if (dt == BLIS_DOUBLE) { return bli_dgemmt_small(alpha, a, b, beta, c, cntx, cntl); } if (dt == BLIS_FLOAT) { return bli_sgemmt_small(alpha, a, b, beta, c, cntx, cntl); } return BLIS_NOT_YET_IMPLEMENTED; }; static err_t bli_sgemmt_small ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, cntl_t* cntl ) { int M = bli_obj_length( c ); // number of rows of Matrix C int N = bli_obj_width( c ); // number of columns of Matrix C int K = bli_obj_width( a ); // number of columns of OP(A), will be updated if OP(A) is Transpose(A) . int L = M * N; if ((((L) < (BLIS_SMALL_MATRIX_THRES * BLIS_SMALL_MATRIX_THRES)) || ((M < BLIS_SMALL_M_RECT_MATRIX_THRES) && (K < BLIS_SMALL_K_RECT_MATRIX_THRES))) && ((L!=0) && (K!=0))) { int lda = bli_obj_col_stride(a); // column stride of matrix OP(A), where OP(A) is Transpose(A) if transA enabled. int ldb = bli_obj_col_stride(b); // column stride of matrix OP(B), where OP(B) is Transpose(B) if transB enabled. int ldc_matC = bli_obj_col_stride( c ); // column stride of matrix C int ldc = M;//bli_obj_col_stride( c ); // column stride of static buffer for matrix C int row_idx, col_idx, k; int rs_matC = bli_obj_row_stride( c ); int rsc = 1; float *A = a->buffer; // pointer to elements of Matrix A float *B = b->buffer; // pointer to elements of Matrix B float *C = C_pack; // pointer to elements of Matrix C float *matCbuf = c->buffer; float *tA = A, *tB = B, *tC = C;//, *tA_pack; float *tA_packed; // temprorary pointer to hold packed A memory pointer int row_idx_packed; //packed A memory row index int lda_packed; //lda of packed A int col_idx_start; //starting index after A matrix is packed. dim_t tb_inc_row = 1; // row stride of matrix B dim_t tb_inc_col = ldb; // column stride of matrix B __m256 ymm4, ymm5, ymm6, ymm7; __m256 ymm8, ymm9, ymm10, ymm11; __m256 ymm12, ymm13, ymm14, ymm15; __m256 ymm0, ymm1, ymm2, ymm3; int n_remainder; // If the N is non multiple of 3.(N%3) int m_remainder; // If the M is non multiple of 32.(M%32) float *alpha_cast, *beta_cast; // alpha, beta multiples alpha_cast = (alpha->buffer); beta_cast = (beta->buffer); int required_packing_A = 1; // when N is equal to 1 call GEMV instead of GEMMT if (N == 1) { bli_gemv ( alpha, a, b, beta, c ); return BLIS_SUCCESS; } //update the pointer math if matrix B needs to be transposed. if (bli_obj_has_trans( b )) { tb_inc_col = 1; //switch row and column strides tb_inc_row = ldb; } if ((N <= 3) || ((MR * K) > F_SCRATCH_DIM)) { required_packing_A = 0; } /* * The computation loop runs for MRxN columns of C matrix, thus * accessing the MRxK A matrix data and KxNR B matrix data. * The computation is organized as inner loops of dimension MRxNR. */ // Process MR rows of C matrix at a time. for (row_idx = 0; (row_idx + (MR - 1)) < M; row_idx += MR) { col_idx_start = 0; tA_packed = A; row_idx_packed = row_idx; lda_packed = lda; // This is the part of the pack and compute optimization. // During the first column iteration, we store the accessed A matrix into // contiguous static memory. This helps to keep te A matrix in Cache and // aviods the TLB misses. if (required_packing_A) { col_idx = 0; //pointer math to point to proper memory tC = C + ldc * col_idx + row_idx; tB = B + tb_inc_col * col_idx; tA = A + row_idx; tA_packed = A_pack; #if 0//def BLIS_ENABLE_PREFETCH _mm_prefetch((char*)(tC + 0), _MM_HINT_T0); _mm_prefetch((char*)(tC + 16), _MM_HINT_T0); _mm_prefetch((char*)(tC + ldc), _MM_HINT_T0); _mm_prefetch((char*)(tC + ldc + 16), _MM_HINT_T0); _mm_prefetch((char*)(tC + 2 * ldc), _MM_HINT_T0); _mm_prefetch((char*)(tC + 2 * ldc + 16), _MM_HINT_T0); #endif // clear scratch registers. ymm4 = _mm256_setzero_ps(); ymm5 = _mm256_setzero_ps(); ymm6 = _mm256_setzero_ps(); ymm7 = _mm256_setzero_ps(); ymm8 = _mm256_setzero_ps(); ymm9 = _mm256_setzero_ps(); ymm10 = _mm256_setzero_ps(); ymm11 = _mm256_setzero_ps(); ymm12 = _mm256_setzero_ps(); ymm13 = _mm256_setzero_ps(); ymm14 = _mm256_setzero_ps(); ymm15 = _mm256_setzero_ps(); for (k = 0; k < K; ++k) { // The inner loop broadcasts the B matrix data and // multiplies it with the A matrix. // This loop is processing MR x K ymm0 = _mm256_broadcast_ss(tB + tb_inc_col * 0); ymm1 = _mm256_broadcast_ss(tB + tb_inc_col * 1); ymm2 = _mm256_broadcast_ss(tB + tb_inc_col * 2); tB += tb_inc_row; //broadcasted matrix B elements are multiplied //with matrix A columns. ymm3 = _mm256_loadu_ps(tA); _mm256_storeu_ps(tA_packed, ymm3); // the packing of matrix A // ymm4 += ymm0 * ymm3; ymm4 = _mm256_fmadd_ps(ymm0, ymm3, ymm4); // ymm8 += ymm1 * ymm3; ymm8 = _mm256_fmadd_ps(ymm1, ymm3, ymm8); // ymm12 += ymm2 * ymm3; ymm12 = _mm256_fmadd_ps(ymm2, ymm3, ymm12); ymm3 = _mm256_loadu_ps(tA + 8); _mm256_storeu_ps(tA_packed + 8, ymm3); // the packing of matrix A // ymm5 += ymm0 * ymm3; ymm5 = _mm256_fmadd_ps(ymm0, ymm3, ymm5); // ymm9 += ymm1 * ymm3; ymm9 = _mm256_fmadd_ps(ymm1, ymm3, ymm9); // ymm13 += ymm2 * ymm3; ymm13 = _mm256_fmadd_ps(ymm2, ymm3, ymm13); ymm3 = _mm256_loadu_ps(tA + 16); _mm256_storeu_ps(tA_packed + 16, ymm3); // the packing of matrix A // ymm6 += ymm0 * ymm3; ymm6 = _mm256_fmadd_ps(ymm0, ymm3, ymm6); // ymm10 += ymm1 * ymm3; ymm10 = _mm256_fmadd_ps(ymm1, ymm3, ymm10); // ymm14 += ymm2 * ymm3; ymm14 = _mm256_fmadd_ps(ymm2, ymm3, ymm14); ymm3 = _mm256_loadu_ps(tA + 24); _mm256_storeu_ps(tA_packed + 24, ymm3); // the packing of matrix A // ymm7 += ymm0 * ymm3; ymm7 = _mm256_fmadd_ps(ymm0, ymm3, ymm7); // ymm11 += ymm1 * ymm3; ymm11 = _mm256_fmadd_ps(ymm1, ymm3, ymm11); // ymm15 += ymm2 * ymm3; ymm15 = _mm256_fmadd_ps(ymm2, ymm3, ymm15); tA += lda; tA_packed += MR; } // alpha, beta multiplication. ymm0 = _mm256_broadcast_ss(alpha_cast); //ymm1 = _mm256_broadcast_ss(beta_cast); //multiply A*B by alpha. ymm4 = _mm256_mul_ps(ymm4, ymm0); ymm5 = _mm256_mul_ps(ymm5, ymm0); ymm6 = _mm256_mul_ps(ymm6, ymm0); ymm7 = _mm256_mul_ps(ymm7, ymm0); ymm8 = _mm256_mul_ps(ymm8, ymm0); ymm9 = _mm256_mul_ps(ymm9, ymm0); ymm10 = _mm256_mul_ps(ymm10, ymm0); ymm11 = _mm256_mul_ps(ymm11, ymm0); ymm12 = _mm256_mul_ps(ymm12, ymm0); ymm13 = _mm256_mul_ps(ymm13, ymm0); ymm14 = _mm256_mul_ps(ymm14, ymm0); ymm15 = _mm256_mul_ps(ymm15, ymm0); // multiply C by beta and accumulate col 1. /*ymm2 = _mm256_loadu_ps(tC); ymm4 = _mm256_fmadd_ps(ymm2, ymm1, ymm4); ymm2 = _mm256_loadu_ps(tC + 8); ymm5 = _mm256_fmadd_ps(ymm2, ymm1, ymm5); ymm2 = _mm256_loadu_ps(tC + 16); ymm6 = _mm256_fmadd_ps(ymm2, ymm1, ymm6); ymm2 = _mm256_loadu_ps(tC + 24); ymm7 = _mm256_fmadd_ps(ymm2, ymm1, ymm7);*/ _mm256_storeu_ps(tC, ymm4); _mm256_storeu_ps(tC + 8, ymm5); _mm256_storeu_ps(tC + 16, ymm6); _mm256_storeu_ps(tC + 24, ymm7); // multiply C by beta and accumulate, col 2. tC += ldc; /*ymm2 = _mm256_loadu_ps(tC); ymm8 = _mm256_fmadd_ps(ymm2, ymm1, ymm8); ymm2 = _mm256_loadu_ps(tC + 8); ymm9 = _mm256_fmadd_ps(ymm2, ymm1, ymm9); ymm2 = _mm256_loadu_ps(tC + 16); ymm10 = _mm256_fmadd_ps(ymm2, ymm1, ymm10); ymm2 = _mm256_loadu_ps(tC + 24); ymm11 = _mm256_fmadd_ps(ymm2, ymm1, ymm11);*/ _mm256_storeu_ps(tC, ymm8); _mm256_storeu_ps(tC + 8, ymm9); _mm256_storeu_ps(tC + 16, ymm10); _mm256_storeu_ps(tC + 24, ymm11); // multiply C by beta and accumulate, col 3. tC += ldc; /*ymm2 = _mm256_loadu_ps(tC); ymm12 = _mm256_fmadd_ps(ymm2, ymm1, ymm12); ymm2 = _mm256_loadu_ps(tC + 8); ymm13 = _mm256_fmadd_ps(ymm2, ymm1, ymm13); ymm2 = _mm256_loadu_ps(tC + 16); ymm14 = _mm256_fmadd_ps(ymm2, ymm1, ymm14); ymm2 = _mm256_loadu_ps(tC + 24); ymm15 = _mm256_fmadd_ps(ymm2, ymm1, ymm15);*/ _mm256_storeu_ps(tC, ymm12); _mm256_storeu_ps(tC + 8, ymm13); _mm256_storeu_ps(tC + 16, ymm14); _mm256_storeu_ps(tC + 24, ymm15); // modify the pointer arithematic to use packed A matrix. col_idx_start = NR; tA_packed = A_pack; row_idx_packed = 0; lda_packed = MR; } // Process NR columns of C matrix at a time. for (col_idx = col_idx_start; (col_idx + (NR - 1)) < N; col_idx += NR) { //pointer math to point to proper memory tC = C + ldc * col_idx + row_idx; tB = B + tb_inc_col * col_idx; tA = tA_packed + row_idx_packed; #if 0//def BLIS_ENABLE_PREFETCH _mm_prefetch((char*)(tC + 0), _MM_HINT_T0); _mm_prefetch((char*)(tC + 16), _MM_HINT_T0); _mm_prefetch((char*)(tC + ldc), _MM_HINT_T0); _mm_prefetch((char*)(tC + ldc + 16), _MM_HINT_T0); _mm_prefetch((char*)(tC + 2 * ldc), _MM_HINT_T0); _mm_prefetch((char*)(tC + 2 * ldc + 16), _MM_HINT_T0); #endif // clear scratch registers. ymm4 = _mm256_setzero_ps(); ymm5 = _mm256_setzero_ps(); ymm6 = _mm256_setzero_ps(); ymm7 = _mm256_setzero_ps(); ymm8 = _mm256_setzero_ps(); ymm9 = _mm256_setzero_ps(); ymm10 = _mm256_setzero_ps(); ymm11 = _mm256_setzero_ps(); ymm12 = _mm256_setzero_ps(); ymm13 = _mm256_setzero_ps(); ymm14 = _mm256_setzero_ps(); ymm15 = _mm256_setzero_ps(); for (k = 0; k < K; ++k) { // The inner loop broadcasts the B matrix data and // multiplies it with the A matrix. // This loop is processing MR x K ymm0 = _mm256_broadcast_ss(tB + tb_inc_col * 0); ymm1 = _mm256_broadcast_ss(tB + tb_inc_col * 1); ymm2 = _mm256_broadcast_ss(tB + tb_inc_col * 2); tB += tb_inc_row; //broadcasted matrix B elements are multiplied //with matrix A columns. ymm3 = _mm256_loadu_ps(tA); // ymm4 += ymm0 * ymm3; ymm4 = _mm256_fmadd_ps(ymm0, ymm3, ymm4); // ymm8 += ymm1 * ymm3; ymm8 = _mm256_fmadd_ps(ymm1, ymm3, ymm8); // ymm12 += ymm2 * ymm3; ymm12 = _mm256_fmadd_ps(ymm2, ymm3, ymm12); ymm3 = _mm256_loadu_ps(tA + 8); // ymm5 += ymm0 * ymm3; ymm5 = _mm256_fmadd_ps(ymm0, ymm3, ymm5); // ymm9 += ymm1 * ymm3; ymm9 = _mm256_fmadd_ps(ymm1, ymm3, ymm9); // ymm13 += ymm2 * ymm3; ymm13 = _mm256_fmadd_ps(ymm2, ymm3, ymm13); ymm3 = _mm256_loadu_ps(tA + 16); // ymm6 += ymm0 * ymm3; ymm6 = _mm256_fmadd_ps(ymm0, ymm3, ymm6); // ymm10 += ymm1 * ymm3; ymm10 = _mm256_fmadd_ps(ymm1, ymm3, ymm10); // ymm14 += ymm2 * ymm3; ymm14 = _mm256_fmadd_ps(ymm2, ymm3, ymm14); ymm3 = _mm256_loadu_ps(tA + 24); // ymm7 += ymm0 * ymm3; ymm7 = _mm256_fmadd_ps(ymm0, ymm3, ymm7); // ymm11 += ymm1 * ymm3; ymm11 = _mm256_fmadd_ps(ymm1, ymm3, ymm11); // ymm15 += ymm2 * ymm3; ymm15 = _mm256_fmadd_ps(ymm2, ymm3, ymm15); tA += lda_packed; } // alpha, beta multiplication. ymm0 = _mm256_broadcast_ss(alpha_cast); //ymm1 = _mm256_broadcast_ss(beta_cast); //multiply A*B by alpha. ymm4 = _mm256_mul_ps(ymm4, ymm0); ymm5 = _mm256_mul_ps(ymm5, ymm0); ymm6 = _mm256_mul_ps(ymm6, ymm0); ymm7 = _mm256_mul_ps(ymm7, ymm0); ymm8 = _mm256_mul_ps(ymm8, ymm0); ymm9 = _mm256_mul_ps(ymm9, ymm0); ymm10 = _mm256_mul_ps(ymm10, ymm0); ymm11 = _mm256_mul_ps(ymm11, ymm0); ymm12 = _mm256_mul_ps(ymm12, ymm0); ymm13 = _mm256_mul_ps(ymm13, ymm0); ymm14 = _mm256_mul_ps(ymm14, ymm0); ymm15 = _mm256_mul_ps(ymm15, ymm0); // multiply C by beta and accumulate col 1. /*ymm2 = _mm256_loadu_ps(tC); ymm4 = _mm256_fmadd_ps(ymm2, ymm1, ymm4); ymm2 = _mm256_loadu_ps(tC + 8); ymm5 = _mm256_fmadd_ps(ymm2, ymm1, ymm5); ymm2 = _mm256_loadu_ps(tC + 16); ymm6 = _mm256_fmadd_ps(ymm2, ymm1, ymm6); ymm2 = _mm256_loadu_ps(tC + 24); ymm7 = _mm256_fmadd_ps(ymm2, ymm1, ymm7);*/ _mm256_storeu_ps(tC, ymm4); _mm256_storeu_ps(tC + 8, ymm5); _mm256_storeu_ps(tC + 16, ymm6); _mm256_storeu_ps(tC + 24, ymm7); // multiply C by beta and accumulate, col 2. tC += ldc; /*ymm2 = _mm256_loadu_ps(tC); ymm8 = _mm256_fmadd_ps(ymm2, ymm1, ymm8); ymm2 = _mm256_loadu_ps(tC + 8); ymm9 = _mm256_fmadd_ps(ymm2, ymm1, ymm9); ymm2 = _mm256_loadu_ps(tC + 16); ymm10 = _mm256_fmadd_ps(ymm2, ymm1, ymm10); ymm2 = _mm256_loadu_ps(tC + 24); ymm11 = _mm256_fmadd_ps(ymm2, ymm1, ymm11);*/ _mm256_storeu_ps(tC, ymm8); _mm256_storeu_ps(tC + 8, ymm9); _mm256_storeu_ps(tC + 16, ymm10); _mm256_storeu_ps(tC + 24, ymm11); // multiply C by beta and accumulate, col 3. tC += ldc; /*ymm2 = _mm256_loadu_ps(tC); ymm12 = _mm256_fmadd_ps(ymm2, ymm1, ymm12); ymm2 = _mm256_loadu_ps(tC + 8); ymm13 = _mm256_fmadd_ps(ymm2, ymm1, ymm13); ymm2 = _mm256_loadu_ps(tC + 16); ymm14 = _mm256_fmadd_ps(ymm2, ymm1, ymm14); ymm2 = _mm256_loadu_ps(tC + 24); ymm15 = _mm256_fmadd_ps(ymm2, ymm1, ymm15);*/ _mm256_storeu_ps(tC, ymm12); _mm256_storeu_ps(tC + 8, ymm13); _mm256_storeu_ps(tC + 16, ymm14); _mm256_storeu_ps(tC + 24, ymm15); } n_remainder = N - col_idx; // if the N is not multiple of 3. // handling edge case. if (n_remainder == 2) { //pointer math to point to proper memory tC = C + ldc * col_idx + row_idx; tB = B + tb_inc_col * col_idx; tA = A + row_idx; // clear scratch registers. ymm8 = _mm256_setzero_ps(); ymm9 = _mm256_setzero_ps(); ymm10 = _mm256_setzero_ps(); ymm11 = _mm256_setzero_ps(); ymm12 = _mm256_setzero_ps(); ymm13 = _mm256_setzero_ps(); ymm14 = _mm256_setzero_ps(); ymm15 = _mm256_setzero_ps(); for (k = 0; k < K; ++k) { // The inner loop broadcasts the B matrix data and // multiplies it with the A matrix. ymm0 = _mm256_broadcast_ss(tB + tb_inc_col * 0); ymm1 = _mm256_broadcast_ss(tB + tb_inc_col * 1); tB += tb_inc_row; //broadcasted matrix B elements are multiplied //with matrix A columns. ymm3 = _mm256_loadu_ps(tA); ymm8 = _mm256_fmadd_ps(ymm0, ymm3, ymm8); ymm12 = _mm256_fmadd_ps(ymm1, ymm3, ymm12); ymm3 = _mm256_loadu_ps(tA + 8); ymm9 = _mm256_fmadd_ps(ymm0, ymm3, ymm9); ymm13 = _mm256_fmadd_ps(ymm1, ymm3, ymm13); ymm3 = _mm256_loadu_ps(tA + 16); ymm10 = _mm256_fmadd_ps(ymm0, ymm3, ymm10); ymm14 = _mm256_fmadd_ps(ymm1, ymm3, ymm14); ymm3 = _mm256_loadu_ps(tA + 24); ymm11 = _mm256_fmadd_ps(ymm0, ymm3, ymm11); ymm15 = _mm256_fmadd_ps(ymm1, ymm3, ymm15); tA += lda; } // alpha, beta multiplication. ymm0 = _mm256_broadcast_ss(alpha_cast); //ymm1 = _mm256_broadcast_ss(beta_cast); //multiply A*B by alpha. ymm8 = _mm256_mul_ps(ymm8, ymm0); ymm9 = _mm256_mul_ps(ymm9, ymm0); ymm10 = _mm256_mul_ps(ymm10, ymm0); ymm11 = _mm256_mul_ps(ymm11, ymm0); ymm12 = _mm256_mul_ps(ymm12, ymm0); ymm13 = _mm256_mul_ps(ymm13, ymm0); ymm14 = _mm256_mul_ps(ymm14, ymm0); ymm15 = _mm256_mul_ps(ymm15, ymm0); // multiply C by beta and accumulate, col 1. /*ymm2 = _mm256_loadu_ps(tC + 0); ymm8 = _mm256_fmadd_ps(ymm2, ymm1, ymm8); ymm2 = _mm256_loadu_ps(tC + 8); ymm9 = _mm256_fmadd_ps(ymm2, ymm1, ymm9); ymm2 = _mm256_loadu_ps(tC + 16); ymm10 = _mm256_fmadd_ps(ymm2, ymm1, ymm10); ymm2 = _mm256_loadu_ps(tC + 24); ymm11 = _mm256_fmadd_ps(ymm2, ymm1, ymm11);*/ _mm256_storeu_ps(tC + 0, ymm8); _mm256_storeu_ps(tC + 8, ymm9); _mm256_storeu_ps(tC + 16, ymm10); _mm256_storeu_ps(tC + 24, ymm11); // multiply C by beta and accumulate, col 2. tC += ldc; /*ymm2 = _mm256_loadu_ps(tC); ymm12 = _mm256_fmadd_ps(ymm2, ymm1, ymm12); ymm2 = _mm256_loadu_ps(tC + 8); ymm13 = _mm256_fmadd_ps(ymm2, ymm1, ymm13); ymm2 = _mm256_loadu_ps(tC + 16); ymm14 = _mm256_fmadd_ps(ymm2, ymm1, ymm14); ymm2 = _mm256_loadu_ps(tC + 24); ymm15 = _mm256_fmadd_ps(ymm2, ymm1, ymm15);*/ _mm256_storeu_ps(tC, ymm12); _mm256_storeu_ps(tC + 8, ymm13); _mm256_storeu_ps(tC + 16, ymm14); _mm256_storeu_ps(tC + 24, ymm15); col_idx += 2; } // if the N is not multiple of 3. // handling edge case. if (n_remainder == 1) { //pointer math to point to proper memory tC = C + ldc * col_idx + row_idx; tB = B + tb_inc_col * col_idx; tA = A + row_idx; // clear scratch registers. ymm12 = _mm256_setzero_ps(); ymm13 = _mm256_setzero_ps(); ymm14 = _mm256_setzero_ps(); ymm15 = _mm256_setzero_ps(); for (k = 0; k < K; ++k) { // The inner loop broadcasts the B matrix data and // multiplies it with the A matrix. ymm0 = _mm256_broadcast_ss(tB + tb_inc_col * 0); tB += tb_inc_row; //broadcasted matrix B elements are multiplied //with matrix A columns. ymm3 = _mm256_loadu_ps(tA); ymm12 = _mm256_fmadd_ps(ymm0, ymm3, ymm12); ymm3 = _mm256_loadu_ps(tA + 8); ymm13 = _mm256_fmadd_ps(ymm0, ymm3, ymm13); ymm3 = _mm256_loadu_ps(tA + 16); ymm14 = _mm256_fmadd_ps(ymm0, ymm3, ymm14); ymm3 = _mm256_loadu_ps(tA + 24); ymm15 = _mm256_fmadd_ps(ymm0, ymm3, ymm15); tA += lda; } // alpha, beta multiplication. ymm0 = _mm256_broadcast_ss(alpha_cast); //ymm1 = _mm256_broadcast_ss(beta_cast); //multiply A*B by alpha. ymm12 = _mm256_mul_ps(ymm12, ymm0); ymm13 = _mm256_mul_ps(ymm13, ymm0); ymm14 = _mm256_mul_ps(ymm14, ymm0); ymm15 = _mm256_mul_ps(ymm15, ymm0); // multiply C by beta and accumulate. /*ymm2 = _mm256_loadu_ps(tC + 0); ymm12 = _mm256_fmadd_ps(ymm2, ymm1, ymm12); ymm2 = _mm256_loadu_ps(tC + 8); ymm13 = _mm256_fmadd_ps(ymm2, ymm1, ymm13); ymm2 = _mm256_loadu_ps(tC + 16); ymm14 = _mm256_fmadd_ps(ymm2, ymm1, ymm14); ymm2 = _mm256_loadu_ps(tC + 24); ymm15 = _mm256_fmadd_ps(ymm2, ymm1, ymm15);*/ _mm256_storeu_ps(tC + 0, ymm12); _mm256_storeu_ps(tC + 8, ymm13); _mm256_storeu_ps(tC + 16, ymm14); _mm256_storeu_ps(tC + 24, ymm15); } } m_remainder = M - row_idx; if (m_remainder >= 24) { m_remainder -= 24; for (col_idx = 0; (col_idx + 2) < N; col_idx += 3) { //pointer math to point to proper memory tC = C + ldc * col_idx + row_idx; tB = B + tb_inc_col * col_idx; tA = A + row_idx; // clear scratch registers. ymm4 = _mm256_setzero_ps(); ymm5 = _mm256_setzero_ps(); ymm6 = _mm256_setzero_ps(); ymm8 = _mm256_setzero_ps(); ymm9 = _mm256_setzero_ps(); ymm10 = _mm256_setzero_ps(); ymm12 = _mm256_setzero_ps(); ymm13 = _mm256_setzero_ps(); ymm14 = _mm256_setzero_ps(); for (k = 0; k < K; ++k) { // The inner loop broadcasts the B matrix data and // multiplies it with the A matrix. ymm0 = _mm256_broadcast_ss(tB + tb_inc_col * 0); ymm1 = _mm256_broadcast_ss(tB + tb_inc_col * 1); ymm2 = _mm256_broadcast_ss(tB + tb_inc_col * 2); tB += tb_inc_row; //broadcasted matrix B elements are multiplied //with matrix A columns. ymm3 = _mm256_loadu_ps(tA); // ymm4 += ymm0 * ymm3; ymm4 = _mm256_fmadd_ps(ymm0, ymm3, ymm4); // ymm8 += ymm1 * ymm3; ymm8 = _mm256_fmadd_ps(ymm1, ymm3, ymm8); // ymm12 += ymm2 * ymm3; ymm12 = _mm256_fmadd_ps(ymm2, ymm3, ymm12); ymm3 = _mm256_loadu_ps(tA + 8); // ymm5 += ymm0 * ymm3; ymm5 = _mm256_fmadd_ps(ymm0, ymm3, ymm5); // ymm9 += ymm1 * ymm3; ymm9 = _mm256_fmadd_ps(ymm1, ymm3, ymm9); // ymm13 += ymm2 * ymm3; ymm13 = _mm256_fmadd_ps(ymm2, ymm3, ymm13); ymm3 = _mm256_loadu_ps(tA + 16); // ymm6 += ymm0 * ymm3; ymm6 = _mm256_fmadd_ps(ymm0, ymm3, ymm6); // ymm10 += ymm1 * ymm3; ymm10 = _mm256_fmadd_ps(ymm1, ymm3, ymm10); // ymm14 += ymm2 * ymm3; ymm14 = _mm256_fmadd_ps(ymm2, ymm3, ymm14); tA += lda; } // alpha, beta multiplication. ymm0 = _mm256_broadcast_ss(alpha_cast); //ymm1 = _mm256_broadcast_ss(beta_cast); //multiply A*B by alpha. ymm4 = _mm256_mul_ps(ymm4, ymm0); ymm5 = _mm256_mul_ps(ymm5, ymm0); ymm6 = _mm256_mul_ps(ymm6, ymm0); ymm8 = _mm256_mul_ps(ymm8, ymm0); ymm9 = _mm256_mul_ps(ymm9, ymm0); ymm10 = _mm256_mul_ps(ymm10, ymm0); ymm12 = _mm256_mul_ps(ymm12, ymm0); ymm13 = _mm256_mul_ps(ymm13, ymm0); ymm14 = _mm256_mul_ps(ymm14, ymm0); // multiply C by beta and accumulate. /*ymm2 = _mm256_loadu_ps(tC); ymm4 = _mm256_fmadd_ps(ymm2, ymm1, ymm4); ymm2 = _mm256_loadu_ps(tC + 8); ymm5 = _mm256_fmadd_ps(ymm2, ymm1, ymm5); ymm2 = _mm256_loadu_ps(tC + 16); ymm6 = _mm256_fmadd_ps(ymm2, ymm1, ymm6);*/ _mm256_storeu_ps(tC, ymm4); _mm256_storeu_ps(tC + 8, ymm5); _mm256_storeu_ps(tC + 16, ymm6); // multiply C by beta and accumulate. tC += ldc; /*ymm2 = _mm256_loadu_ps(tC); ymm8 = _mm256_fmadd_ps(ymm2, ymm1, ymm8); ymm2 = _mm256_loadu_ps(tC + 8); ymm9 = _mm256_fmadd_ps(ymm2, ymm1, ymm9); ymm2 = _mm256_loadu_ps(tC + 16); ymm10 = _mm256_fmadd_ps(ymm2, ymm1, ymm10);*/ _mm256_storeu_ps(tC, ymm8); _mm256_storeu_ps(tC + 8, ymm9); _mm256_storeu_ps(tC + 16, ymm10); // multiply C by beta and accumulate. tC += ldc; /*ymm2 = _mm256_loadu_ps(tC); ymm12 = _mm256_fmadd_ps(ymm2, ymm1, ymm12); ymm2 = _mm256_loadu_ps(tC + 8); ymm13 = _mm256_fmadd_ps(ymm2, ymm1, ymm13); ymm2 = _mm256_loadu_ps(tC + 16); ymm14 = _mm256_fmadd_ps(ymm2, ymm1, ymm14);*/ _mm256_storeu_ps(tC, ymm12); _mm256_storeu_ps(tC + 8, ymm13); _mm256_storeu_ps(tC + 16, ymm14); } n_remainder = N - col_idx; // if the N is not multiple of 3. // handling edge case. if (n_remainder == 2) { //pointer math to point to proper memory tC = C + ldc * col_idx + row_idx; tB = B + tb_inc_col * col_idx; tA = A + row_idx; // clear scratch registers. ymm8 = _mm256_setzero_ps(); ymm9 = _mm256_setzero_ps(); ymm10 = _mm256_setzero_ps(); ymm12 = _mm256_setzero_ps(); ymm13 = _mm256_setzero_ps(); ymm14 = _mm256_setzero_ps(); for (k = 0; k < K; ++k) { // The inner loop broadcasts the B matrix data and // multiplies it with the A matrix. ymm0 = _mm256_broadcast_ss(tB + tb_inc_col * 0); ymm1 = _mm256_broadcast_ss(tB + tb_inc_col * 1); tB += tb_inc_row; //broadcasted matrix B elements are multiplied //with matrix A columns. ymm3 = _mm256_loadu_ps(tA); ymm8 = _mm256_fmadd_ps(ymm0, ymm3, ymm8); ymm12 = _mm256_fmadd_ps(ymm1, ymm3, ymm12); ymm3 = _mm256_loadu_ps(tA + 8); ymm9 = _mm256_fmadd_ps(ymm0, ymm3, ymm9); ymm13 = _mm256_fmadd_ps(ymm1, ymm3, ymm13); ymm3 = _mm256_loadu_ps(tA + 16); ymm10 = _mm256_fmadd_ps(ymm0, ymm3, ymm10); ymm14 = _mm256_fmadd_ps(ymm1, ymm3, ymm14); tA += lda; } // alpha, beta multiplication. ymm0 = _mm256_broadcast_ss(alpha_cast); //ymm1 = _mm256_broadcast_ss(beta_cast); //multiply A*B by alpha. ymm8 = _mm256_mul_ps(ymm8, ymm0); ymm9 = _mm256_mul_ps(ymm9, ymm0); ymm10 = _mm256_mul_ps(ymm10, ymm0); ymm12 = _mm256_mul_ps(ymm12, ymm0); ymm13 = _mm256_mul_ps(ymm13, ymm0); ymm14 = _mm256_mul_ps(ymm14, ymm0); // multiply C by beta and accumulate. /*ymm2 = _mm256_loadu_ps(tC + 0); ymm8 = _mm256_fmadd_ps(ymm2, ymm1, ymm8); ymm2 = _mm256_loadu_ps(tC + 8); ymm9 = _mm256_fmadd_ps(ymm2, ymm1, ymm9); ymm2 = _mm256_loadu_ps(tC + 16); ymm10 = _mm256_fmadd_ps(ymm2, ymm1, ymm10);*/ _mm256_storeu_ps(tC + 0, ymm8); _mm256_storeu_ps(tC + 8, ymm9); _mm256_storeu_ps(tC + 16, ymm10); // multiply C by beta and accumulate. tC += ldc; /*ymm2 = _mm256_loadu_ps(tC); ymm12 = _mm256_fmadd_ps(ymm2, ymm1, ymm12); ymm2 = _mm256_loadu_ps(tC + 8); ymm13 = _mm256_fmadd_ps(ymm2, ymm1, ymm13); ymm2 = _mm256_loadu_ps(tC + 16); ymm14 = _mm256_fmadd_ps(ymm2, ymm1, ymm14);*/ _mm256_storeu_ps(tC, ymm12); _mm256_storeu_ps(tC + 8, ymm13); _mm256_storeu_ps(tC + 16, ymm14); col_idx += 2; } // if the N is not multiple of 3. // handling edge case. if (n_remainder == 1) { //pointer math to point to proper memory tC = C + ldc * col_idx + row_idx; tB = B + tb_inc_col * col_idx; tA = A + row_idx; // clear scratch registers. ymm12 = _mm256_setzero_ps(); ymm13 = _mm256_setzero_ps(); ymm14 = _mm256_setzero_ps(); for (k = 0; k < K; ++k) { // The inner loop broadcasts the B matrix data and // multiplies it with the A matrix. ymm0 = _mm256_broadcast_ss(tB + tb_inc_col * 0); tB += tb_inc_row; //broadcasted matrix B elements are multiplied //with matrix A columns. ymm3 = _mm256_loadu_ps(tA); ymm12 = _mm256_fmadd_ps(ymm0, ymm3, ymm12); ymm3 = _mm256_loadu_ps(tA + 8); ymm13 = _mm256_fmadd_ps(ymm0, ymm3, ymm13); ymm3 = _mm256_loadu_ps(tA + 16); ymm14 = _mm256_fmadd_ps(ymm0, ymm3, ymm14); tA += lda; } // alpha, beta multiplication. ymm0 = _mm256_broadcast_ss(alpha_cast); //ymm1 = _mm256_broadcast_ss(beta_cast); //multiply A*B by alpha. ymm12 = _mm256_mul_ps(ymm12, ymm0); ymm13 = _mm256_mul_ps(ymm13, ymm0); ymm14 = _mm256_mul_ps(ymm14, ymm0); // multiply C by beta and accumulate. /*ymm2 = _mm256_loadu_ps(tC + 0); ymm12 = _mm256_fmadd_ps(ymm2, ymm1, ymm12); ymm2 = _mm256_loadu_ps(tC + 8); ymm13 = _mm256_fmadd_ps(ymm2, ymm1, ymm13); ymm2 = _mm256_loadu_ps(tC + 16); ymm14 = _mm256_fmadd_ps(ymm2, ymm1, ymm14);*/ _mm256_storeu_ps(tC + 0, ymm12); _mm256_storeu_ps(tC + 8, ymm13); _mm256_storeu_ps(tC + 16, ymm14); } row_idx += 24; } if (m_remainder >= 16) { m_remainder -= 16; for (col_idx = 0; (col_idx + 2) < N; col_idx += 3) { //pointer math to point to proper memory tC = C + ldc * col_idx + row_idx; tB = B + tb_inc_col * col_idx; tA = A + row_idx; // clear scratch registers. ymm4 = _mm256_setzero_ps(); ymm5 = _mm256_setzero_ps(); ymm6 = _mm256_setzero_ps(); ymm7 = _mm256_setzero_ps(); ymm8 = _mm256_setzero_ps(); ymm9 = _mm256_setzero_ps(); for (k = 0; k < K; ++k) { // The inner loop broadcasts the B matrix data and // multiplies it with the A matrix. ymm0 = _mm256_broadcast_ss(tB + tb_inc_col * 0); ymm1 = _mm256_broadcast_ss(tB + tb_inc_col * 1); ymm2 = _mm256_broadcast_ss(tB + tb_inc_col * 2); tB += tb_inc_row; //broadcasted matrix B elements are multiplied //with matrix A columns. ymm3 = _mm256_loadu_ps(tA); ymm4 = _mm256_fmadd_ps(ymm0, ymm3, ymm4); ymm6 = _mm256_fmadd_ps(ymm1, ymm3, ymm6); ymm8 = _mm256_fmadd_ps(ymm2, ymm3, ymm8); ymm3 = _mm256_loadu_ps(tA + 8); ymm5 = _mm256_fmadd_ps(ymm0, ymm3, ymm5); ymm7 = _mm256_fmadd_ps(ymm1, ymm3, ymm7); ymm9 = _mm256_fmadd_ps(ymm2, ymm3, ymm9); tA += lda; } // alpha, beta multiplication. ymm0 = _mm256_broadcast_ss(alpha_cast); //ymm1 = _mm256_broadcast_ss(beta_cast); //multiply A*B by alpha. ymm4 = _mm256_mul_ps(ymm4, ymm0); ymm5 = _mm256_mul_ps(ymm5, ymm0); ymm6 = _mm256_mul_ps(ymm6, ymm0); ymm7 = _mm256_mul_ps(ymm7, ymm0); ymm8 = _mm256_mul_ps(ymm8, ymm0); ymm9 = _mm256_mul_ps(ymm9, ymm0); // multiply C by beta and accumulate. /*ymm2 = _mm256_loadu_ps(tC); ymm4 = _mm256_fmadd_ps(ymm2, ymm1, ymm4); ymm2 = _mm256_loadu_ps(tC + 8); ymm5 = _mm256_fmadd_ps(ymm2, ymm1, ymm5);*/ _mm256_storeu_ps(tC, ymm4); _mm256_storeu_ps(tC + 8, ymm5); // multiply C by beta and accumulate. tC += ldc; /*ymm2 = _mm256_loadu_ps(tC); ymm6 = _mm256_fmadd_ps(ymm2, ymm1, ymm6); ymm2 = _mm256_loadu_ps(tC + 8); ymm7 = _mm256_fmadd_ps(ymm2, ymm1, ymm7);*/ _mm256_storeu_ps(tC, ymm6); _mm256_storeu_ps(tC + 8, ymm7); // multiply C by beta and accumulate. tC += ldc; /*ymm2 = _mm256_loadu_ps(tC); ymm8 = _mm256_fmadd_ps(ymm2, ymm1, ymm8); ymm2 = _mm256_loadu_ps(tC + 8); ymm9 = _mm256_fmadd_ps(ymm2, ymm1, ymm9);*/ _mm256_storeu_ps(tC, ymm8); _mm256_storeu_ps(tC + 8, ymm9); } n_remainder = N - col_idx; // if the N is not multiple of 3. // handling edge case. if (n_remainder == 2) { //pointer math to point to proper memory tC = C + ldc * col_idx + row_idx; tB = B + tb_inc_col * col_idx; tA = A + row_idx; // clear scratch registers. ymm4 = _mm256_setzero_ps(); ymm5 = _mm256_setzero_ps(); ymm6 = _mm256_setzero_ps(); ymm7 = _mm256_setzero_ps(); for (k = 0; k < K; ++k) { // The inner loop broadcasts the B matrix data and // multiplies it with the A matrix. ymm0 = _mm256_broadcast_ss(tB + tb_inc_col * 0); ymm1 = _mm256_broadcast_ss(tB + tb_inc_col * 1); tB += tb_inc_row; //broadcasted matrix B elements are multiplied //with matrix A columns. ymm3 = _mm256_loadu_ps(tA); ymm4 = _mm256_fmadd_ps(ymm0, ymm3, ymm4); ymm6 = _mm256_fmadd_ps(ymm1, ymm3, ymm6); ymm3 = _mm256_loadu_ps(tA + 8); ymm5 = _mm256_fmadd_ps(ymm0, ymm3, ymm5); ymm7 = _mm256_fmadd_ps(ymm1, ymm3, ymm7); tA += lda; } // alpha, beta multiplication. ymm0 = _mm256_broadcast_ss(alpha_cast); //ymm1 = _mm256_broadcast_ss(beta_cast); //multiply A*B by alpha. ymm4 = _mm256_mul_ps(ymm4, ymm0); ymm5 = _mm256_mul_ps(ymm5, ymm0); ymm6 = _mm256_mul_ps(ymm6, ymm0); ymm7 = _mm256_mul_ps(ymm7, ymm0); // multiply C by beta and accumulate. /*ymm2 = _mm256_loadu_ps(tC); ymm4 = _mm256_fmadd_ps(ymm2, ymm1, ymm4); ymm2 = _mm256_loadu_ps(tC + 8); ymm5 = _mm256_fmadd_ps(ymm2, ymm1, ymm5);*/ _mm256_storeu_ps(tC, ymm4); _mm256_storeu_ps(tC + 8, ymm5); // multiply C by beta and accumulate. tC += ldc; /*ymm2 = _mm256_loadu_ps(tC); ymm6 = _mm256_fmadd_ps(ymm2, ymm1, ymm6); ymm2 = _mm256_loadu_ps(tC + 8); ymm7 = _mm256_fmadd_ps(ymm2, ymm1, ymm7);*/ _mm256_storeu_ps(tC, ymm6); _mm256_storeu_ps(tC + 8, ymm7); col_idx += 2; } // if the N is not multiple of 3. // handling edge case. if (n_remainder == 1) { //pointer math to point to proper memory tC = C + ldc * col_idx + row_idx; tB = B + tb_inc_col * col_idx; tA = A + row_idx; ymm4 = _mm256_setzero_ps(); ymm5 = _mm256_setzero_ps(); for (k = 0; k < K; ++k) { // The inner loop broadcasts the B matrix data and // multiplies it with the A matrix. ymm0 = _mm256_broadcast_ss(tB + tb_inc_col * 0); tB += tb_inc_row; //broadcasted matrix B elements are multiplied //with matrix A columns. ymm3 = _mm256_loadu_ps(tA); ymm4 = _mm256_fmadd_ps(ymm0, ymm3, ymm4); ymm3 = _mm256_loadu_ps(tA + 8); ymm5 = _mm256_fmadd_ps(ymm0, ymm3, ymm5); tA += lda; } // alpha, beta multiplication. ymm0 = _mm256_broadcast_ss(alpha_cast); //ymm1 = _mm256_broadcast_ss(beta_cast); ymm4 = _mm256_mul_ps(ymm4, ymm0); ymm5 = _mm256_mul_ps(ymm5, ymm0); // multiply C by beta and accumulate. /*ymm2 = _mm256_loadu_ps(tC); ymm4 = _mm256_fmadd_ps(ymm2, ymm1, ymm4); ymm2 = _mm256_loadu_ps(tC + 8); ymm5 = _mm256_fmadd_ps(ymm2, ymm1, ymm5);*/ _mm256_storeu_ps(tC, ymm4); _mm256_storeu_ps(tC + 8, ymm5); } row_idx += 16; } if (m_remainder >= 8) { m_remainder -= 8; for (col_idx = 0; (col_idx + 2) < N; col_idx += 3) { //pointer math to point to proper memory tC = C + ldc * col_idx + row_idx; tB = B + tb_inc_col * col_idx; tA = A + row_idx; // clear scratch registers. ymm4 = _mm256_setzero_ps(); ymm5 = _mm256_setzero_ps(); ymm6 = _mm256_setzero_ps(); for (k = 0; k < K; ++k) { // The inner loop broadcasts the B matrix data and // multiplies it with the A matrix. ymm0 = _mm256_broadcast_ss(tB + tb_inc_col * 0); ymm1 = _mm256_broadcast_ss(tB + tb_inc_col * 1); ymm2 = _mm256_broadcast_ss(tB + tb_inc_col * 2); tB += tb_inc_row; //broadcasted matrix B elements are multiplied //with matrix A columns. ymm3 = _mm256_loadu_ps(tA); ymm4 = _mm256_fmadd_ps(ymm0, ymm3, ymm4); ymm5 = _mm256_fmadd_ps(ymm1, ymm3, ymm5); ymm6 = _mm256_fmadd_ps(ymm2, ymm3, ymm6); tA += lda; } // alpha, beta multiplication. ymm0 = _mm256_broadcast_ss(alpha_cast); //ymm1 = _mm256_broadcast_ss(beta_cast); //multiply A*B by alpha. ymm4 = _mm256_mul_ps(ymm4, ymm0); ymm5 = _mm256_mul_ps(ymm5, ymm0); ymm6 = _mm256_mul_ps(ymm6, ymm0); // multiply C by beta and accumulate. /*ymm2 = _mm256_loadu_ps(tC); ymm4 = _mm256_fmadd_ps(ymm2, ymm1, ymm4);*/ _mm256_storeu_ps(tC, ymm4); // multiply C by beta and accumulate. tC += ldc; /*ymm2 = _mm256_loadu_ps(tC); ymm5 = _mm256_fmadd_ps(ymm2, ymm1, ymm5);*/ _mm256_storeu_ps(tC, ymm5); // multiply C by beta and accumulate. tC += ldc; /*ymm2 = _mm256_loadu_ps(tC); ymm6 = _mm256_fmadd_ps(ymm2, ymm1, ymm6);*/ _mm256_storeu_ps(tC, ymm6); } n_remainder = N - col_idx; // if the N is not multiple of 3. // handling edge case. if (n_remainder == 2) { //pointer math to point to proper memory tC = C + ldc * col_idx + row_idx; tB = B + tb_inc_col * col_idx; tA = A + row_idx; ymm4 = _mm256_setzero_ps(); ymm5 = _mm256_setzero_ps(); for (k = 0; k < K; ++k) { // The inner loop broadcasts the B matrix data and // multiplies it with the A matrix. ymm0 = _mm256_broadcast_ss(tB + tb_inc_col * 0); ymm1 = _mm256_broadcast_ss(tB + tb_inc_col * 1); tB += tb_inc_row; //broadcasted matrix B elements are multiplied //with matrix A columns. ymm3 = _mm256_loadu_ps(tA); ymm4 = _mm256_fmadd_ps(ymm0, ymm3, ymm4); ymm5 = _mm256_fmadd_ps(ymm1, ymm3, ymm5); tA += lda; } // alpha, beta multiplication. ymm0 = _mm256_broadcast_ss(alpha_cast); //ymm1 = _mm256_broadcast_ss(beta_cast); //multiply A*B by alpha. ymm4 = _mm256_mul_ps(ymm4, ymm0); ymm5 = _mm256_mul_ps(ymm5, ymm0); // multiply C by beta and accumulate. /*ymm2 = _mm256_loadu_ps(tC); ymm4 = _mm256_fmadd_ps(ymm2, ymm1, ymm4);*/ _mm256_storeu_ps(tC, ymm4); // multiply C by beta and accumulate. tC += ldc; /*ymm2 = _mm256_loadu_ps(tC); ymm5 = _mm256_fmadd_ps(ymm2, ymm1, ymm5);*/ _mm256_storeu_ps(tC, ymm5); col_idx += 2; } // if the N is not multiple of 3. // handling edge case. if (n_remainder == 1) { //pointer math to point to proper memory tC = C + ldc * col_idx + row_idx; tB = B + tb_inc_col * col_idx; tA = A + row_idx; ymm4 = _mm256_setzero_ps(); for (k = 0; k < K; ++k) { // The inner loop broadcasts the B matrix data and // multiplies it with the A matrix. ymm0 = _mm256_broadcast_ss(tB + tb_inc_col * 0); tB += tb_inc_row; //broadcasted matrix B elements are multiplied //with matrix A columns. ymm3 = _mm256_loadu_ps(tA); ymm4 = _mm256_fmadd_ps(ymm0, ymm3, ymm4); tA += lda; } // alpha, beta multiplication. ymm0 = _mm256_broadcast_ss(alpha_cast); //ymm1 = _mm256_broadcast_ss(beta_cast); ymm4 = _mm256_mul_ps(ymm4, ymm0); // multiply C by beta and accumulate. /*ymm2 = _mm256_loadu_ps(tC); ymm4 = _mm256_fmadd_ps(ymm2, ymm1, ymm4);*/ _mm256_storeu_ps(tC, ymm4); } row_idx += 8; } // M is not a multiple of 32. // The handling of edge case where the remainder // dimension is less than 8. The padding takes place // to handle this case. if ((m_remainder) && (lda > 7)) { float f_temp[8]; for (col_idx = 0; (col_idx + 2) < N; col_idx += 3) { //pointer math to point to proper memory tC = C + ldc * col_idx + row_idx; tB = B + tb_inc_col * col_idx; tA = A + row_idx; // clear scratch registers. ymm5 = _mm256_setzero_ps(); ymm7 = _mm256_setzero_ps(); ymm9 = _mm256_setzero_ps(); for (k = 0; k < (K - 1); ++k) { // The inner loop broadcasts the B matrix data and // multiplies it with the A matrix. ymm0 = _mm256_broadcast_ss(tB + tb_inc_col * 0); ymm1 = _mm256_broadcast_ss(tB + tb_inc_col * 1); ymm2 = _mm256_broadcast_ss(tB + tb_inc_col * 2); tB += tb_inc_row; //broadcasted matrix B elements are multiplied //with matrix A columns. ymm3 = _mm256_loadu_ps(tA); ymm5 = _mm256_fmadd_ps(ymm0, ymm3, ymm5); ymm7 = _mm256_fmadd_ps(ymm1, ymm3, ymm7); ymm9 = _mm256_fmadd_ps(ymm2, ymm3, ymm9); tA += lda; } // alpha, beta multiplication. ymm0 = _mm256_broadcast_ss(tB + tb_inc_col * 0); ymm1 = _mm256_broadcast_ss(tB + tb_inc_col * 1); ymm2 = _mm256_broadcast_ss(tB + tb_inc_col * 2); tB += tb_inc_row; for (int i = 0; i < m_remainder; i++) { f_temp[i] = tA[i]; } ymm3 = _mm256_loadu_ps(f_temp); ymm5 = _mm256_fmadd_ps(ymm0, ymm3, ymm5); ymm7 = _mm256_fmadd_ps(ymm1, ymm3, ymm7); ymm9 = _mm256_fmadd_ps(ymm2, ymm3, ymm9); ymm0 = _mm256_broadcast_ss(alpha_cast); //ymm1 = _mm256_broadcast_ss(beta_cast); //multiply A*B by alpha. ymm5 = _mm256_mul_ps(ymm5, ymm0); ymm7 = _mm256_mul_ps(ymm7, ymm0); ymm9 = _mm256_mul_ps(ymm9, ymm0); /*for (int i = 0; i < m_remainder; i++) { f_temp[i] = tC[i]; } ymm2 = _mm256_loadu_ps(f_temp); ymm5 = _mm256_fmadd_ps(ymm2, ymm1, ymm5);*/ _mm256_storeu_ps(f_temp, ymm5); for (int i = 0; i < m_remainder; i++) { tC[i] = f_temp[i]; } tC += ldc; /*for (int i = 0; i < m_remainder; i++) { f_temp[i] = tC[i]; } ymm2 = _mm256_loadu_ps(f_temp); ymm7 = _mm256_fmadd_ps(ymm2, ymm1, ymm7);*/ _mm256_storeu_ps(f_temp, ymm7); for (int i = 0; i < m_remainder; i++) { tC[i] = f_temp[i]; } tC += ldc; /*for (int i = 0; i < m_remainder; i++) { f_temp[i] = tC[i]; } ymm2 = _mm256_loadu_ps(f_temp); ymm9 = _mm256_fmadd_ps(ymm2, ymm1, ymm9);*/ _mm256_storeu_ps(f_temp, ymm9); for (int i = 0; i < m_remainder; i++) { tC[i] = f_temp[i]; } } n_remainder = N - col_idx; // if the N is not multiple of 3. // handling edge case. if (n_remainder == 2) { //pointer math to point to proper memory tC = C + ldc * col_idx + row_idx; tB = B + tb_inc_col * col_idx; tA = A + row_idx; ymm5 = _mm256_setzero_ps(); ymm7 = _mm256_setzero_ps(); for (k = 0; k < (K - 1); ++k) { // The inner loop broadcasts the B matrix data and // multiplies it with the A matrix. ymm0 = _mm256_broadcast_ss(tB + tb_inc_col * 0); ymm1 = _mm256_broadcast_ss(tB + tb_inc_col * 1); tB += tb_inc_row; ymm3 = _mm256_loadu_ps(tA); ymm5 = _mm256_fmadd_ps(ymm0, ymm3, ymm5); ymm7 = _mm256_fmadd_ps(ymm1, ymm3, ymm7); tA += lda; } ymm0 = _mm256_broadcast_ss(tB + tb_inc_col * 0); ymm1 = _mm256_broadcast_ss(tB + tb_inc_col * 1); tB += tb_inc_row; for (int i = 0; i < m_remainder; i++) { f_temp[i] = tA[i]; } ymm3 = _mm256_loadu_ps(f_temp); ymm5 = _mm256_fmadd_ps(ymm0, ymm3, ymm5); ymm7 = _mm256_fmadd_ps(ymm1, ymm3, ymm7); ymm0 = _mm256_broadcast_ss(alpha_cast); //ymm1 = _mm256_broadcast_ss(beta_cast); ymm5 = _mm256_mul_ps(ymm5, ymm0); ymm7 = _mm256_mul_ps(ymm7, ymm0); /*for (int i = 0; i < m_remainder; i++) { f_temp[i] = tC[i]; } ymm2 = _mm256_loadu_ps(f_temp); ymm5 = _mm256_fmadd_ps(ymm2, ymm1, ymm5);*/ _mm256_storeu_ps(f_temp, ymm5); for (int i = 0; i < m_remainder; i++) { tC[i] = f_temp[i]; } tC += ldc; /*for (int i = 0; i < m_remainder; i++) { f_temp[i] = tC[i]; } ymm2 = _mm256_loadu_ps(f_temp); ymm7 = _mm256_fmadd_ps(ymm2, ymm1, ymm7);*/ _mm256_storeu_ps(f_temp, ymm7); for (int i = 0; i < m_remainder; i++) { tC[i] = f_temp[i]; } } // if the N is not multiple of 3. // handling edge case. if (n_remainder == 1) { //pointer math to point to proper memory tC = C + ldc * col_idx + row_idx; tB = B + tb_inc_col * col_idx; tA = A + row_idx; ymm5 = _mm256_setzero_ps(); for (k = 0; k < (K - 1); ++k) { // The inner loop broadcasts the B matrix data and // multiplies it with the A matrix. ymm0 = _mm256_broadcast_ss(tB + tb_inc_col * 0); tB += tb_inc_row; ymm3 = _mm256_loadu_ps(tA); ymm5 = _mm256_fmadd_ps(ymm0, ymm3, ymm5); tA += lda; } ymm0 = _mm256_broadcast_ss(tB + tb_inc_col * 0); tB += tb_inc_row; for (int i = 0; i < m_remainder; i++) { f_temp[i] = tA[i]; } ymm3 = _mm256_loadu_ps(f_temp); ymm5 = _mm256_fmadd_ps(ymm0, ymm3, ymm5); ymm0 = _mm256_broadcast_ss(alpha_cast); //ymm1 = _mm256_broadcast_ss(beta_cast); // multiply C by beta and accumulate. ymm5 = _mm256_mul_ps(ymm5, ymm0); /*for (int i = 0; i < m_remainder; i++) { f_temp[i] = tC[i]; } ymm2 = _mm256_loadu_ps(f_temp); ymm5 = _mm256_fmadd_ps(ymm2, ymm1, ymm5);*/ _mm256_storeu_ps(f_temp, ymm5); for (int i = 0; i < m_remainder; i++) { tC[i] = f_temp[i]; } } m_remainder = 0; } if (m_remainder) { float result; for (; row_idx < M; row_idx += 1) { for (col_idx = 0; col_idx < N; col_idx += 1) { //pointer math to point to proper memory tC = C + ldc * col_idx + row_idx; tB = B + tb_inc_col * col_idx; tA = A + row_idx; result = 0; for (k = 0; k < K; ++k) { result += (*tA) * (*tB); tA += lda; tB += tb_inc_row; } result *= (*alpha_cast); (*tC) = /*(*tC) * (*beta_cast) + */result; } } } //copy/compute sryk values back to C using SIMD if ( bli_seq0( *beta_cast ) ) {//just copy in case of beta = 0 dim_t _i, _j, k, _l; if(bli_obj_is_lower(c)) // c is lower { //first column _j = 0; k = M >> 3; _i = 0; for ( _l = 0; _l < k; _l++ ) { ymm0 = _mm256_loadu_ps((C + _i*rsc)); _mm256_storeu_ps((matCbuf + _i*rs_matC), ymm0); _i += 8; } while (_i < M ) { bli_sscopys( *(C + _i*rsc + _j*ldc), *(matCbuf + _i*rs_matC + _j*ldc_matC) ); _i++; } _j++; while ( _j < N ) //next column { //k = (_j + (8 - (_j & 7))); _l = _j & 7; k = (_l != 0) ? (_j + (8 - _l)) : _j; k = (k <= M) ? k : M; for ( _i = _j; _i < k; ++_i ) { bli_sscopys( *(C + _i*rsc + _j*ldc), *(matCbuf + _i*rs_matC + _j*ldc_matC) ); } k = (M - _i) >> 3; _l = 0; while ( _l < k ) { ymm0 = _mm256_loadu_ps((C + _i*rsc + _j*ldc)); _mm256_storeu_ps((matCbuf + _i*rs_matC + _j*ldc_matC), ymm0); _i += 8; _l++; } while (_i < M ) { bli_sscopys( *(C + _i*rsc + _j*ldc), *(matCbuf + _i*rs_matC + _j*ldc_matC) ); _i++; } _j++; } } else //c is upper { for ( _j = 0; _j < N; ++_j ) { k = (_j + 1) >> 3; _i = 0; _l = 0; while ( _l < k ) { ymm0 = _mm256_loadu_ps((C + _i*rsc + _j*ldc)); _mm256_storeu_ps((matCbuf + _i*rs_matC + _j*ldc_matC), ymm0); _i += 8; _l++; } while (_i <= _j ) { bli_sscopys( *(C + _i*rsc + _j*ldc), *(matCbuf + _i*rs_matC + _j*ldc_matC) ); ++_i; } } } } else {//when beta is non-zero, fmadd and store the results dim_t _i, _j, k, _l; ymm1 = _mm256_broadcast_ss(beta_cast); if(bli_obj_is_lower(c)) //c is lower { //first column _j = 0; k = M >> 3; _i = 0; for ( _l = 0; _l < k; _l++ ) { ymm2 = _mm256_loadu_ps((matCbuf + _i*rs_matC)); ymm0 = _mm256_loadu_ps((C + _i*rsc)); ymm0 = _mm256_fmadd_ps(ymm2, ymm1, ymm0); _mm256_storeu_ps((matCbuf + _i*rs_matC), ymm0); _i += 8; } while (_i < M ) { bli_sssxpbys( *(C + _i*rsc + _j*ldc), *(beta_cast), *(matCbuf + _i*rs_matC + _j*ldc_matC) ); _i++; } _j++; while ( _j < N ) //next column { //k = (_j + (8 - (_j & 7))); _l = _j & 7; k = (_l != 0) ? (_j + (8 - _l)) : _j; k = (k <= M) ? k : M; for ( _i = _j; _i < k; ++_i ) { bli_sssxpbys( *(C + _i*rsc + _j*ldc), *(beta_cast), *(matCbuf + _i*rs_matC + _j*ldc_matC) ); } k = (M - _i) >> 3; _l = 0; while ( _l < k ) { ymm2 = _mm256_loadu_ps((matCbuf + _i*rs_matC + _j*ldc_matC)); ymm0 = _mm256_loadu_ps((C + _i*rsc + _j*ldc)); ymm0 = _mm256_fmadd_ps(ymm2, ymm1, ymm0); _mm256_storeu_ps((matCbuf + _i*rs_matC + _j*ldc_matC), ymm0); _i += 8; _l++; } while (_i < M ) { bli_sssxpbys( *(C + _i*rsc + _j*ldc), *(beta_cast), *(matCbuf + _i*rs_matC + _j*ldc_matC) ); _i++; } _j++; } } else //c is upper { for ( _j = 0; _j < N; ++_j ) { k = (_j + 1) >> 3; _i = 0; _l = 0; while ( _l < k ) { ymm2 = _mm256_loadu_ps((matCbuf + _i*rs_matC + _j*ldc_matC)); ymm0 = _mm256_loadu_ps((C + _i*rsc + _j*ldc)); ymm0 = _mm256_fmadd_ps(ymm2, ymm1, ymm0); _mm256_storeu_ps((matCbuf + _i*rs_matC + _j*ldc_matC), ymm0); _i += 8; _l++; } while (_i <= _j ) { bli_sssxpbys( *(C + _i*rsc + _j*ldc), *(beta_cast), *(matCbuf + _i*rs_matC + _j*ldc_matC) ); ++_i; } } } } return BLIS_SUCCESS; } else return BLIS_NONCONFORMAL_DIMENSIONS; }; static err_t bli_dgemmt_small ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, cntl_t* cntl ) { int M = bli_obj_length( c ); // number of rows of Matrix C int N = bli_obj_width( c ); // number of columns of Matrix C int K = bli_obj_width( a ); // number of columns of OP(A), will be updated if OP(A) is Transpose(A) . int L = M * N; // If alpha is zero, scale by beta and return. if ((((L) < (D_BLIS_SMALL_MATRIX_THRES * D_BLIS_SMALL_MATRIX_THRES)) || ((M < D_BLIS_SMALL_M_RECT_MATRIX_THRES) && (K < D_BLIS_SMALL_K_RECT_MATRIX_THRES))) && ((L!=0) && (K!=0))) { int lda = bli_obj_col_stride( a ); // column stride of matrix OP(A), where OP(A) is Transpose(A) if transA enabled. int ldb = bli_obj_col_stride( b ); // column stride of matrix OP(B), where OP(B) is Transpose(B) if transB enabled. int ldc_matC = bli_obj_col_stride( c ); // column stride of matrix C int ldc = M;//bli_obj_col_stride( c ); // column stride of static buffer for matrix C int row_idx, col_idx, k; int rs_matC = bli_obj_row_stride( c ); int rsc = 1; double *A = a->buffer; // pointer to elements of Matrix A double *B = b->buffer; // pointer to elements of Matrix B double *C = D_C_pack; // pointer to elements of Matrix C double *matCbuf = c->buffer; double *tA = A, *tB = B, *tC = C;//, *tA_pack; double *tA_packed; // temprorary pointer to hold packed A memory pointer int row_idx_packed; //packed A memory row index int lda_packed; //lda of packed A int col_idx_start; //starting index after A matrix is packed. dim_t tb_inc_row = 1; // row stride of matrix B dim_t tb_inc_col = ldb; // column stride of matrix B __m256d ymm4, ymm5, ymm6, ymm7; __m256d ymm8, ymm9, ymm10, ymm11; __m256d ymm12, ymm13, ymm14, ymm15; __m256d ymm0, ymm1, ymm2, ymm3; int n_remainder; // If the N is non multiple of 3.(N%3) int m_remainder; // If the M is non multiple of 16.(M%16) double *alpha_cast, *beta_cast; // alpha, beta multiples alpha_cast = (alpha->buffer); beta_cast = (beta->buffer); int required_packing_A = 1; // when N is equal to 1 call GEMV instead of GEMMT if (N == 1) { bli_gemv ( alpha, a, b, beta, c ); return BLIS_SUCCESS; } //update the pointer math if matrix B needs to be transposed. if (bli_obj_has_trans( b )) { tb_inc_col = 1; //switch row and column strides tb_inc_row = ldb; } if ((N <= 3) || ((D_MR * K) > D_SCRATCH_DIM)) { required_packing_A = 0; } /* * The computation loop runs for D_MRxN columns of C matrix, thus * accessing the D_MRxK A matrix data and KxNR B matrix data. * The computation is organized as inner loops of dimension D_MRxNR. */ // Process D_MR rows of C matrix at a time. for (row_idx = 0; (row_idx + (D_MR - 1)) < M; row_idx += D_MR) { col_idx_start = 0; tA_packed = A; row_idx_packed = row_idx; lda_packed = lda; // This is the part of the pack and compute optimization. // During the first column iteration, we store the accessed A matrix into // contiguous static memory. This helps to keep te A matrix in Cache and // aviods the TLB misses. if (required_packing_A) { col_idx = 0; //pointer math to point to proper memory tC = C + ldc * col_idx + row_idx; tB = B + tb_inc_col * col_idx; tA = A + row_idx; tA_packed = D_A_pack; #if 0//def BLIS_ENABLE_PREFETCH _mm_prefetch((char*)(tC + 0), _MM_HINT_T0); _mm_prefetch((char*)(tC + 8), _MM_HINT_T0); _mm_prefetch((char*)(tC + ldc), _MM_HINT_T0); _mm_prefetch((char*)(tC + ldc + 8), _MM_HINT_T0); _mm_prefetch((char*)(tC + 2 * ldc), _MM_HINT_T0); _mm_prefetch((char*)(tC + 2 * ldc + 8), _MM_HINT_T0); #endif // clear scratch registers. ymm4 = _mm256_setzero_pd(); ymm5 = _mm256_setzero_pd(); ymm6 = _mm256_setzero_pd(); ymm7 = _mm256_setzero_pd(); ymm8 = _mm256_setzero_pd(); ymm9 = _mm256_setzero_pd(); ymm10 = _mm256_setzero_pd(); ymm11 = _mm256_setzero_pd(); ymm12 = _mm256_setzero_pd(); ymm13 = _mm256_setzero_pd(); ymm14 = _mm256_setzero_pd(); ymm15 = _mm256_setzero_pd(); for (k = 0; k < K; ++k) { // The inner loop broadcasts the B matrix data and // multiplies it with the A matrix. // This loop is processing D_MR x K ymm0 = _mm256_broadcast_sd(tB + tb_inc_col * 0); ymm1 = _mm256_broadcast_sd(tB + tb_inc_col * 1); ymm2 = _mm256_broadcast_sd(tB + tb_inc_col * 2); tB += tb_inc_row; //broadcasted matrix B elements are multiplied //with matrix A columns. ymm3 = _mm256_loadu_pd(tA); _mm256_storeu_pd(tA_packed, ymm3); // the packing of matrix A // ymm4 += ymm0 * ymm3; ymm4 = _mm256_fmadd_pd(ymm0, ymm3, ymm4); // ymm8 += ymm1 * ymm3; ymm8 = _mm256_fmadd_pd(ymm1, ymm3, ymm8); // ymm12 += ymm2 * ymm3; ymm12 = _mm256_fmadd_pd(ymm2, ymm3, ymm12); ymm3 = _mm256_loadu_pd(tA + 4); _mm256_storeu_pd(tA_packed + 4, ymm3); // the packing of matrix A // ymm5 += ymm0 * ymm3; ymm5 = _mm256_fmadd_pd(ymm0, ymm3, ymm5); // ymm9 += ymm1 * ymm3; ymm9 = _mm256_fmadd_pd(ymm1, ymm3, ymm9); // ymm13 += ymm2 * ymm3; ymm13 = _mm256_fmadd_pd(ymm2, ymm3, ymm13); ymm3 = _mm256_loadu_pd(tA + 8); _mm256_storeu_pd(tA_packed + 8, ymm3); // the packing of matrix A // ymm6 += ymm0 * ymm3; ymm6 = _mm256_fmadd_pd(ymm0, ymm3, ymm6); // ymm10 += ymm1 * ymm3; ymm10 = _mm256_fmadd_pd(ymm1, ymm3, ymm10); // ymm14 += ymm2 * ymm3; ymm14 = _mm256_fmadd_pd(ymm2, ymm3, ymm14); ymm3 = _mm256_loadu_pd(tA + 12); _mm256_storeu_pd(tA_packed + 12, ymm3); // the packing of matrix A // ymm7 += ymm0 * ymm3; ymm7 = _mm256_fmadd_pd(ymm0, ymm3, ymm7); // ymm11 += ymm1 * ymm3; ymm11 = _mm256_fmadd_pd(ymm1, ymm3, ymm11); // ymm15 += ymm2 * ymm3; ymm15 = _mm256_fmadd_pd(ymm2, ymm3, ymm15); tA += lda; tA_packed += D_MR; } // alpha, beta multiplication. ymm0 = _mm256_broadcast_sd(alpha_cast); //ymm1 = _mm256_broadcast_sd(beta_cast); //multiply A*B by alpha. ymm4 = _mm256_mul_pd(ymm4, ymm0); ymm5 = _mm256_mul_pd(ymm5, ymm0); ymm6 = _mm256_mul_pd(ymm6, ymm0); ymm7 = _mm256_mul_pd(ymm7, ymm0); ymm8 = _mm256_mul_pd(ymm8, ymm0); ymm9 = _mm256_mul_pd(ymm9, ymm0); ymm10 = _mm256_mul_pd(ymm10, ymm0); ymm11 = _mm256_mul_pd(ymm11, ymm0); ymm12 = _mm256_mul_pd(ymm12, ymm0); ymm13 = _mm256_mul_pd(ymm13, ymm0); ymm14 = _mm256_mul_pd(ymm14, ymm0); ymm15 = _mm256_mul_pd(ymm15, ymm0); // multiply C by beta and accumulate col 1. /*ymm2 = _mm256_loadu_pd(tC); ymm4 = _mm256_fmadd_pd(ymm2, ymm1, ymm4); ymm2 = _mm256_loadu_pd(tC + 4); ymm5 = _mm256_fmadd_pd(ymm2, ymm1, ymm5); ymm2 = _mm256_loadu_pd(tC + 8); ymm6 = _mm256_fmadd_pd(ymm2, ymm1, ymm6); ymm2 = _mm256_loadu_pd(tC + 12); ymm7 = _mm256_fmadd_pd(ymm2, ymm1, ymm7);*/ _mm256_storeu_pd(tC, ymm4); _mm256_storeu_pd(tC + 4, ymm5); _mm256_storeu_pd(tC + 8, ymm6); _mm256_storeu_pd(tC + 12, ymm7); // multiply C by beta and accumulate, col 2. tC += ldc; /*ymm2 = _mm256_loadu_pd(tC); ymm8 = _mm256_fmadd_pd(ymm2, ymm1, ymm8); ymm2 = _mm256_loadu_pd(tC + 4); ymm9 = _mm256_fmadd_pd(ymm2, ymm1, ymm9); ymm2 = _mm256_loadu_pd(tC + 8); ymm10 = _mm256_fmadd_pd(ymm2, ymm1, ymm10); ymm2 = _mm256_loadu_pd(tC + 12); ymm11 = _mm256_fmadd_pd(ymm2, ymm1, ymm11);*/ _mm256_storeu_pd(tC, ymm8); _mm256_storeu_pd(tC + 4, ymm9); _mm256_storeu_pd(tC + 8, ymm10); _mm256_storeu_pd(tC + 12, ymm11); // multiply C by beta and accumulate, col 3. tC += ldc; /*ymm2 = _mm256_loadu_pd(tC); ymm12 = _mm256_fmadd_pd(ymm2, ymm1, ymm12); ymm2 = _mm256_loadu_pd(tC + 4); ymm13 = _mm256_fmadd_pd(ymm2, ymm1, ymm13); ymm2 = _mm256_loadu_pd(tC + 8); ymm14 = _mm256_fmadd_pd(ymm2, ymm1, ymm14); ymm2 = _mm256_loadu_pd(tC + 12); ymm15 = _mm256_fmadd_pd(ymm2, ymm1, ymm15);*/ _mm256_storeu_pd(tC, ymm12); _mm256_storeu_pd(tC + 4, ymm13); _mm256_storeu_pd(tC + 8, ymm14); _mm256_storeu_pd(tC + 12, ymm15); // modify the pointer arithematic to use packed A matrix. col_idx_start = NR; tA_packed = D_A_pack; row_idx_packed = 0; lda_packed = D_MR; } // Process NR columns of C matrix at a time. for (col_idx = col_idx_start; (col_idx + (NR - 1)) < N; col_idx += NR) { //pointer math to point to proper memory tC = C + ldc * col_idx + row_idx; tB = B + tb_inc_col * col_idx; tA = tA_packed + row_idx_packed; #if 0//def BLIS_ENABLE_PREFETCH _mm_prefetch((char*)(tC + 0), _MM_HINT_T0); _mm_prefetch((char*)(tC + 8), _MM_HINT_T0); _mm_prefetch((char*)(tC + ldc), _MM_HINT_T0); _mm_prefetch((char*)(tC + ldc + 8), _MM_HINT_T0); _mm_prefetch((char*)(tC + 2 * ldc), _MM_HINT_T0); _mm_prefetch((char*)(tC + 2 * ldc + 8), _MM_HINT_T0); #endif // clear scratch registers. ymm4 = _mm256_setzero_pd(); ymm5 = _mm256_setzero_pd(); ymm6 = _mm256_setzero_pd(); ymm7 = _mm256_setzero_pd(); ymm8 = _mm256_setzero_pd(); ymm9 = _mm256_setzero_pd(); ymm10 = _mm256_setzero_pd(); ymm11 = _mm256_setzero_pd(); ymm12 = _mm256_setzero_pd(); ymm13 = _mm256_setzero_pd(); ymm14 = _mm256_setzero_pd(); ymm15 = _mm256_setzero_pd(); for (k = 0; k < K; ++k) { // The inner loop broadcasts the B matrix data and // multiplies it with the A matrix. // This loop is processing D_MR x K ymm0 = _mm256_broadcast_sd(tB + tb_inc_col * 0); ymm1 = _mm256_broadcast_sd(tB + tb_inc_col * 1); ymm2 = _mm256_broadcast_sd(tB + tb_inc_col * 2); tB += tb_inc_row; //broadcasted matrix B elements are multiplied //with matrix A columns. ymm3 = _mm256_loadu_pd(tA); // ymm4 += ymm0 * ymm3; ymm4 = _mm256_fmadd_pd(ymm0, ymm3, ymm4); // ymm8 += ymm1 * ymm3; ymm8 = _mm256_fmadd_pd(ymm1, ymm3, ymm8); // ymm12 += ymm2 * ymm3; ymm12 = _mm256_fmadd_pd(ymm2, ymm3, ymm12); ymm3 = _mm256_loadu_pd(tA + 4); // ymm5 += ymm0 * ymm3; ymm5 = _mm256_fmadd_pd(ymm0, ymm3, ymm5); // ymm9 += ymm1 * ymm3; ymm9 = _mm256_fmadd_pd(ymm1, ymm3, ymm9); // ymm13 += ymm2 * ymm3; ymm13 = _mm256_fmadd_pd(ymm2, ymm3, ymm13); ymm3 = _mm256_loadu_pd(tA + 8); // ymm6 += ymm0 * ymm3; ymm6 = _mm256_fmadd_pd(ymm0, ymm3, ymm6); // ymm10 += ymm1 * ymm3; ymm10 = _mm256_fmadd_pd(ymm1, ymm3, ymm10); // ymm14 += ymm2 * ymm3; ymm14 = _mm256_fmadd_pd(ymm2, ymm3, ymm14); ymm3 = _mm256_loadu_pd(tA + 12); // ymm7 += ymm0 * ymm3; ymm7 = _mm256_fmadd_pd(ymm0, ymm3, ymm7); // ymm11 += ymm1 * ymm3; ymm11 = _mm256_fmadd_pd(ymm1, ymm3, ymm11); // ymm15 += ymm2 * ymm3; ymm15 = _mm256_fmadd_pd(ymm2, ymm3, ymm15); tA += lda_packed; } // alpha, beta multiplication. ymm0 = _mm256_broadcast_sd(alpha_cast); //ymm1 = _mm256_broadcast_sd(beta_cast); //multiply A*B by alpha. ymm4 = _mm256_mul_pd(ymm4, ymm0); ymm5 = _mm256_mul_pd(ymm5, ymm0); ymm6 = _mm256_mul_pd(ymm6, ymm0); ymm7 = _mm256_mul_pd(ymm7, ymm0); ymm8 = _mm256_mul_pd(ymm8, ymm0); ymm9 = _mm256_mul_pd(ymm9, ymm0); ymm10 = _mm256_mul_pd(ymm10, ymm0); ymm11 = _mm256_mul_pd(ymm11, ymm0); ymm12 = _mm256_mul_pd(ymm12, ymm0); ymm13 = _mm256_mul_pd(ymm13, ymm0); ymm14 = _mm256_mul_pd(ymm14, ymm0); ymm15 = _mm256_mul_pd(ymm15, ymm0); // multiply C by beta and accumulate col 1. /*ymm2 = _mm256_loadu_pd(tC); ymm4 = _mm256_fmadd_pd(ymm2, ymm1, ymm4); ymm2 = _mm256_loadu_pd(tC + 4); ymm5 = _mm256_fmadd_pd(ymm2, ymm1, ymm5); ymm2 = _mm256_loadu_pd(tC + 8); ymm6 = _mm256_fmadd_pd(ymm2, ymm1, ymm6); ymm2 = _mm256_loadu_pd(tC + 12); ymm7 = _mm256_fmadd_pd(ymm2, ymm1, ymm7);*/ _mm256_storeu_pd(tC, ymm4); _mm256_storeu_pd(tC + 4, ymm5); _mm256_storeu_pd(tC + 8, ymm6); _mm256_storeu_pd(tC + 12, ymm7); // multiply C by beta and accumulate, col 2. tC += ldc; /*ymm2 = _mm256_loadu_pd(tC); ymm8 = _mm256_fmadd_pd(ymm2, ymm1, ymm8); ymm2 = _mm256_loadu_pd(tC + 4); ymm9 = _mm256_fmadd_pd(ymm2, ymm1, ymm9); ymm2 = _mm256_loadu_pd(tC + 8); ymm10 = _mm256_fmadd_pd(ymm2, ymm1, ymm10); ymm2 = _mm256_loadu_pd(tC + 12); ymm11 = _mm256_fmadd_pd(ymm2, ymm1, ymm11);*/ _mm256_storeu_pd(tC, ymm8); _mm256_storeu_pd(tC + 4, ymm9); _mm256_storeu_pd(tC + 8, ymm10); _mm256_storeu_pd(tC + 12, ymm11); // multiply C by beta and accumulate, col 3. tC += ldc; /*ymm2 = _mm256_loadu_pd(tC); ymm12 = _mm256_fmadd_pd(ymm2, ymm1, ymm12); ymm2 = _mm256_loadu_pd(tC + 4); ymm13 = _mm256_fmadd_pd(ymm2, ymm1, ymm13); ymm2 = _mm256_loadu_pd(tC + 8); ymm14 = _mm256_fmadd_pd(ymm2, ymm1, ymm14); ymm2 = _mm256_loadu_pd(tC + 12); ymm15 = _mm256_fmadd_pd(ymm2, ymm1, ymm15);*/ _mm256_storeu_pd(tC, ymm12); _mm256_storeu_pd(tC + 4, ymm13); _mm256_storeu_pd(tC + 8, ymm14); _mm256_storeu_pd(tC + 12, ymm15); } n_remainder = N - col_idx; // if the N is not multiple of 3. // handling edge case. if (n_remainder == 2) { //pointer math to point to proper memory tC = C + ldc * col_idx + row_idx; tB = B + tb_inc_col * col_idx; tA = A + row_idx; // clear scratch registers. ymm8 = _mm256_setzero_pd(); ymm9 = _mm256_setzero_pd(); ymm10 = _mm256_setzero_pd(); ymm11 = _mm256_setzero_pd(); ymm12 = _mm256_setzero_pd(); ymm13 = _mm256_setzero_pd(); ymm14 = _mm256_setzero_pd(); ymm15 = _mm256_setzero_pd(); for (k = 0; k < K; ++k) { // The inner loop broadcasts the B matrix data and // multiplies it with the A matrix. ymm0 = _mm256_broadcast_sd(tB + tb_inc_col * 0); ymm1 = _mm256_broadcast_sd(tB + tb_inc_col * 1); tB += tb_inc_row; //broadcasted matrix B elements are multiplied //with matrix A columns. ymm3 = _mm256_loadu_pd(tA); ymm8 = _mm256_fmadd_pd(ymm0, ymm3, ymm8); ymm12 = _mm256_fmadd_pd(ymm1, ymm3, ymm12); ymm3 = _mm256_loadu_pd(tA + 4); ymm9 = _mm256_fmadd_pd(ymm0, ymm3, ymm9); ymm13 = _mm256_fmadd_pd(ymm1, ymm3, ymm13); ymm3 = _mm256_loadu_pd(tA + 8); ymm10 = _mm256_fmadd_pd(ymm0, ymm3, ymm10); ymm14 = _mm256_fmadd_pd(ymm1, ymm3, ymm14); ymm3 = _mm256_loadu_pd(tA + 12); ymm11 = _mm256_fmadd_pd(ymm0, ymm3, ymm11); ymm15 = _mm256_fmadd_pd(ymm1, ymm3, ymm15); tA += lda; } // alpha, beta multiplication. ymm0 = _mm256_broadcast_sd(alpha_cast); //ymm1 = _mm256_broadcast_sd(beta_cast); //multiply A*B by alpha. ymm8 = _mm256_mul_pd(ymm8, ymm0); ymm9 = _mm256_mul_pd(ymm9, ymm0); ymm10 = _mm256_mul_pd(ymm10, ymm0); ymm11 = _mm256_mul_pd(ymm11, ymm0); ymm12 = _mm256_mul_pd(ymm12, ymm0); ymm13 = _mm256_mul_pd(ymm13, ymm0); ymm14 = _mm256_mul_pd(ymm14, ymm0); ymm15 = _mm256_mul_pd(ymm15, ymm0); // multiply C by beta and accumulate, col 1. /*ymm2 = _mm256_loadu_pd(tC + 0); ymm8 = _mm256_fmadd_pd(ymm2, ymm1, ymm8); ymm2 = _mm256_loadu_pd(tC + 4); ymm9 = _mm256_fmadd_pd(ymm2, ymm1, ymm9); ymm2 = _mm256_loadu_pd(tC + 8); ymm10 = _mm256_fmadd_pd(ymm2, ymm1, ymm10); ymm2 = _mm256_loadu_pd(tC + 12); ymm11 = _mm256_fmadd_pd(ymm2, ymm1, ymm11);*/ _mm256_storeu_pd(tC + 0, ymm8); _mm256_storeu_pd(tC + 4, ymm9); _mm256_storeu_pd(tC + 8, ymm10); _mm256_storeu_pd(tC + 12, ymm11); // multiply C by beta and accumulate, col 2. tC += ldc; /*ymm2 = _mm256_loadu_pd(tC); ymm12 = _mm256_fmadd_pd(ymm2, ymm1, ymm12); ymm2 = _mm256_loadu_pd(tC + 4); ymm13 = _mm256_fmadd_pd(ymm2, ymm1, ymm13); ymm2 = _mm256_loadu_pd(tC + 8); ymm14 = _mm256_fmadd_pd(ymm2, ymm1, ymm14); ymm2 = _mm256_loadu_pd(tC + 12); ymm15 = _mm256_fmadd_pd(ymm2, ymm1, ymm15);*/ _mm256_storeu_pd(tC, ymm12); _mm256_storeu_pd(tC + 4, ymm13); _mm256_storeu_pd(tC + 8, ymm14); _mm256_storeu_pd(tC + 12, ymm15); col_idx += 2; } // if the N is not multiple of 3. // handling edge case. if (n_remainder == 1) { //pointer math to point to proper memory tC = C + ldc * col_idx + row_idx; tB = B + tb_inc_col * col_idx; tA = A + row_idx; // clear scratch registers. ymm12 = _mm256_setzero_pd(); ymm13 = _mm256_setzero_pd(); ymm14 = _mm256_setzero_pd(); ymm15 = _mm256_setzero_pd(); for (k = 0; k < K; ++k) { // The inner loop broadcasts the B matrix data and // multiplies it with the A matrix. ymm0 = _mm256_broadcast_sd(tB + tb_inc_col * 0); tB += tb_inc_row; //broadcasted matrix B elements are multiplied //with matrix A columns. ymm3 = _mm256_loadu_pd(tA); ymm12 = _mm256_fmadd_pd(ymm0, ymm3, ymm12); ymm3 = _mm256_loadu_pd(tA + 4); ymm13 = _mm256_fmadd_pd(ymm0, ymm3, ymm13); ymm3 = _mm256_loadu_pd(tA + 8); ymm14 = _mm256_fmadd_pd(ymm0, ymm3, ymm14); ymm3 = _mm256_loadu_pd(tA + 12); ymm15 = _mm256_fmadd_pd(ymm0, ymm3, ymm15); tA += lda; } // alpha, beta multiplication. ymm0 = _mm256_broadcast_sd(alpha_cast); //ymm1 = _mm256_broadcast_sd(beta_cast); //multiply A*B by alpha. ymm12 = _mm256_mul_pd(ymm12, ymm0); ymm13 = _mm256_mul_pd(ymm13, ymm0); ymm14 = _mm256_mul_pd(ymm14, ymm0); ymm15 = _mm256_mul_pd(ymm15, ymm0); // multiply C by beta and accumulate. /*ymm2 = _mm256_loadu_pd(tC + 0); ymm12 = _mm256_fmadd_pd(ymm2, ymm1, ymm12); ymm2 = _mm256_loadu_pd(tC + 4); ymm13 = _mm256_fmadd_pd(ymm2, ymm1, ymm13); ymm2 = _mm256_loadu_pd(tC + 8); ymm14 = _mm256_fmadd_pd(ymm2, ymm1, ymm14); ymm2 = _mm256_loadu_pd(tC + 12); ymm15 = _mm256_fmadd_pd(ymm2, ymm1, ymm15);*/ _mm256_storeu_pd(tC + 0, ymm12); _mm256_storeu_pd(tC + 4, ymm13); _mm256_storeu_pd(tC + 8, ymm14); _mm256_storeu_pd(tC + 12, ymm15); } } m_remainder = M - row_idx; if (m_remainder >= 12) { m_remainder -= 12; for (col_idx = 0; (col_idx + 2) < N; col_idx += 3) { //pointer math to point to proper memory tC = C + ldc * col_idx + row_idx; tB = B + tb_inc_col * col_idx; tA = A + row_idx; // clear scratch registers. ymm4 = _mm256_setzero_pd(); ymm5 = _mm256_setzero_pd(); ymm6 = _mm256_setzero_pd(); ymm8 = _mm256_setzero_pd(); ymm9 = _mm256_setzero_pd(); ymm10 = _mm256_setzero_pd(); ymm12 = _mm256_setzero_pd(); ymm13 = _mm256_setzero_pd(); ymm14 = _mm256_setzero_pd(); for (k = 0; k < K; ++k) { // The inner loop broadcasts the B matrix data and // multiplies it with the A matrix. ymm0 = _mm256_broadcast_sd(tB + tb_inc_col * 0); ymm1 = _mm256_broadcast_sd(tB + tb_inc_col * 1); ymm2 = _mm256_broadcast_sd(tB + tb_inc_col * 2); tB += tb_inc_row; //broadcasted matrix B elements are multiplied //with matrix A columns. ymm3 = _mm256_loadu_pd(tA); // ymm4 += ymm0 * ymm3; ymm4 = _mm256_fmadd_pd(ymm0, ymm3, ymm4); // ymm8 += ymm1 * ymm3; ymm8 = _mm256_fmadd_pd(ymm1, ymm3, ymm8); // ymm12 += ymm2 * ymm3; ymm12 = _mm256_fmadd_pd(ymm2, ymm3, ymm12); ymm3 = _mm256_loadu_pd(tA + 4); // ymm5 += ymm0 * ymm3; ymm5 = _mm256_fmadd_pd(ymm0, ymm3, ymm5); // ymm9 += ymm1 * ymm3; ymm9 = _mm256_fmadd_pd(ymm1, ymm3, ymm9); // ymm13 += ymm2 * ymm3; ymm13 = _mm256_fmadd_pd(ymm2, ymm3, ymm13); ymm3 = _mm256_loadu_pd(tA + 8); // ymm6 += ymm0 * ymm3; ymm6 = _mm256_fmadd_pd(ymm0, ymm3, ymm6); // ymm10 += ymm1 * ymm3; ymm10 = _mm256_fmadd_pd(ymm1, ymm3, ymm10); // ymm14 += ymm2 * ymm3; ymm14 = _mm256_fmadd_pd(ymm2, ymm3, ymm14); tA += lda; } // alpha, beta multiplication. ymm0 = _mm256_broadcast_sd(alpha_cast); //ymm1 = _mm256_broadcast_sd(beta_cast); //multiply A*B by alpha. ymm4 = _mm256_mul_pd(ymm4, ymm0); ymm5 = _mm256_mul_pd(ymm5, ymm0); ymm6 = _mm256_mul_pd(ymm6, ymm0); ymm8 = _mm256_mul_pd(ymm8, ymm0); ymm9 = _mm256_mul_pd(ymm9, ymm0); ymm10 = _mm256_mul_pd(ymm10, ymm0); ymm12 = _mm256_mul_pd(ymm12, ymm0); ymm13 = _mm256_mul_pd(ymm13, ymm0); ymm14 = _mm256_mul_pd(ymm14, ymm0); // multiply C by beta and accumulate. /*ymm2 = _mm256_loadu_pd(tC); ymm4 = _mm256_fmadd_pd(ymm2, ymm1, ymm4); ymm2 = _mm256_loadu_pd(tC + 4); ymm5 = _mm256_fmadd_pd(ymm2, ymm1, ymm5); ymm2 = _mm256_loadu_pd(tC + 8); ymm6 = _mm256_fmadd_pd(ymm2, ymm1, ymm6);*/ _mm256_storeu_pd(tC, ymm4); _mm256_storeu_pd(tC + 4, ymm5); _mm256_storeu_pd(tC + 8, ymm6); // multiply C by beta and accumulate. tC += ldc; /*ymm2 = _mm256_loadu_pd(tC); ymm8 = _mm256_fmadd_pd(ymm2, ymm1, ymm8); ymm2 = _mm256_loadu_pd(tC + 4); ymm9 = _mm256_fmadd_pd(ymm2, ymm1, ymm9); ymm2 = _mm256_loadu_pd(tC + 8); ymm10 = _mm256_fmadd_pd(ymm2, ymm1, ymm10);*/ _mm256_storeu_pd(tC, ymm8); _mm256_storeu_pd(tC + 4, ymm9); _mm256_storeu_pd(tC + 8, ymm10); // multiply C by beta and accumulate. tC += ldc; /*ymm2 = _mm256_loadu_pd(tC); ymm12 = _mm256_fmadd_pd(ymm2, ymm1, ymm12); ymm2 = _mm256_loadu_pd(tC + 4); ymm13 = _mm256_fmadd_pd(ymm2, ymm1, ymm13); ymm2 = _mm256_loadu_pd(tC + 8); ymm14 = _mm256_fmadd_pd(ymm2, ymm1, ymm14);*/ _mm256_storeu_pd(tC, ymm12); _mm256_storeu_pd(tC + 4, ymm13); _mm256_storeu_pd(tC + 8, ymm14); } n_remainder = N - col_idx; // if the N is not multiple of 3. // handling edge case. if (n_remainder == 2) { //pointer math to point to proper memory tC = C + ldc * col_idx + row_idx; tB = B + tb_inc_col * col_idx; tA = A + row_idx; // clear scratch registers. ymm8 = _mm256_setzero_pd(); ymm9 = _mm256_setzero_pd(); ymm10 = _mm256_setzero_pd(); ymm12 = _mm256_setzero_pd(); ymm13 = _mm256_setzero_pd(); ymm14 = _mm256_setzero_pd(); for (k = 0; k < K; ++k) { // The inner loop broadcasts the B matrix data and // multiplies it with the A matrix. ymm0 = _mm256_broadcast_sd(tB + tb_inc_col * 0); ymm1 = _mm256_broadcast_sd(tB + tb_inc_col * 1); tB += tb_inc_row; //broadcasted matrix B elements are multiplied //with matrix A columns. ymm3 = _mm256_loadu_pd(tA); ymm8 = _mm256_fmadd_pd(ymm0, ymm3, ymm8); ymm12 = _mm256_fmadd_pd(ymm1, ymm3, ymm12); ymm3 = _mm256_loadu_pd(tA + 4); ymm9 = _mm256_fmadd_pd(ymm0, ymm3, ymm9); ymm13 = _mm256_fmadd_pd(ymm1, ymm3, ymm13); ymm3 = _mm256_loadu_pd(tA + 8); ymm10 = _mm256_fmadd_pd(ymm0, ymm3, ymm10); ymm14 = _mm256_fmadd_pd(ymm1, ymm3, ymm14); tA += lda; } // alpha, beta multiplication. ymm0 = _mm256_broadcast_sd(alpha_cast); //ymm1 = _mm256_broadcast_sd(beta_cast); //multiply A*B by alpha. ymm8 = _mm256_mul_pd(ymm8, ymm0); ymm9 = _mm256_mul_pd(ymm9, ymm0); ymm10 = _mm256_mul_pd(ymm10, ymm0); ymm12 = _mm256_mul_pd(ymm12, ymm0); ymm13 = _mm256_mul_pd(ymm13, ymm0); ymm14 = _mm256_mul_pd(ymm14, ymm0); // multiply C by beta and accumulate. /*ymm2 = _mm256_loadu_pd(tC + 0); ymm8 = _mm256_fmadd_pd(ymm2, ymm1, ymm8); ymm2 = _mm256_loadu_pd(tC + 4); ymm9 = _mm256_fmadd_pd(ymm2, ymm1, ymm9); ymm2 = _mm256_loadu_pd(tC + 8); ymm10 = _mm256_fmadd_pd(ymm2, ymm1, ymm10);*/ _mm256_storeu_pd(tC + 0, ymm8); _mm256_storeu_pd(tC + 4, ymm9); _mm256_storeu_pd(tC + 8, ymm10); // multiply C by beta and accumulate. tC += ldc; /*ymm2 = _mm256_loadu_pd(tC); ymm12 = _mm256_fmadd_pd(ymm2, ymm1, ymm12); ymm2 = _mm256_loadu_pd(tC + 4); ymm13 = _mm256_fmadd_pd(ymm2, ymm1, ymm13); ymm2 = _mm256_loadu_pd(tC + 8); ymm14 = _mm256_fmadd_pd(ymm2, ymm1, ymm14);*/ _mm256_storeu_pd(tC, ymm12); _mm256_storeu_pd(tC + 4, ymm13); _mm256_storeu_pd(tC + 8, ymm14); col_idx += 2; } // if the N is not multiple of 3. // handling edge case. if (n_remainder == 1) { //pointer math to point to proper memory tC = C + ldc * col_idx + row_idx; tB = B + tb_inc_col * col_idx; tA = A + row_idx; // clear scratch registers. ymm12 = _mm256_setzero_pd(); ymm13 = _mm256_setzero_pd(); ymm14 = _mm256_setzero_pd(); for (k = 0; k < K; ++k) { // The inner loop broadcasts the B matrix data and // multiplies it with the A matrix. ymm0 = _mm256_broadcast_sd(tB + tb_inc_col * 0); tB += tb_inc_row; //broadcasted matrix B elements are multiplied //with matrix A columns. ymm3 = _mm256_loadu_pd(tA); ymm12 = _mm256_fmadd_pd(ymm0, ymm3, ymm12); ymm3 = _mm256_loadu_pd(tA + 4); ymm13 = _mm256_fmadd_pd(ymm0, ymm3, ymm13); ymm3 = _mm256_loadu_pd(tA + 8); ymm14 = _mm256_fmadd_pd(ymm0, ymm3, ymm14); tA += lda; } // alpha, beta multiplication. ymm0 = _mm256_broadcast_sd(alpha_cast); //ymm1 = _mm256_broadcast_sd(beta_cast); //multiply A*B by alpha. ymm12 = _mm256_mul_pd(ymm12, ymm0); ymm13 = _mm256_mul_pd(ymm13, ymm0); ymm14 = _mm256_mul_pd(ymm14, ymm0); // multiply C by beta and accumulate. /*ymm2 = _mm256_loadu_pd(tC + 0); ymm12 = _mm256_fmadd_pd(ymm2, ymm1, ymm12); ymm2 = _mm256_loadu_pd(tC + 4); ymm13 = _mm256_fmadd_pd(ymm2, ymm1, ymm13); ymm2 = _mm256_loadu_pd(tC + 8); ymm14 = _mm256_fmadd_pd(ymm2, ymm1, ymm14);*/ _mm256_storeu_pd(tC + 0, ymm12); _mm256_storeu_pd(tC + 4, ymm13); _mm256_storeu_pd(tC + 8, ymm14); } row_idx += 12; } if (m_remainder >= 8) { m_remainder -= 8; for (col_idx = 0; (col_idx + 2) < N; col_idx += 3) { //pointer math to point to proper memory tC = C + ldc * col_idx + row_idx; tB = B + tb_inc_col * col_idx; tA = A + row_idx; // clear scratch registers. ymm4 = _mm256_setzero_pd(); ymm5 = _mm256_setzero_pd(); ymm6 = _mm256_setzero_pd(); ymm7 = _mm256_setzero_pd(); ymm8 = _mm256_setzero_pd(); ymm9 = _mm256_setzero_pd(); for (k = 0; k < K; ++k) { // The inner loop broadcasts the B matrix data and // multiplies it with the A matrix. ymm0 = _mm256_broadcast_sd(tB + tb_inc_col * 0); ymm1 = _mm256_broadcast_sd(tB + tb_inc_col * 1); ymm2 = _mm256_broadcast_sd(tB + tb_inc_col * 2); tB += tb_inc_row; //broadcasted matrix B elements are multiplied //with matrix A columns. ymm3 = _mm256_loadu_pd(tA); ymm4 = _mm256_fmadd_pd(ymm0, ymm3, ymm4); ymm6 = _mm256_fmadd_pd(ymm1, ymm3, ymm6); ymm8 = _mm256_fmadd_pd(ymm2, ymm3, ymm8); ymm3 = _mm256_loadu_pd(tA + 4); ymm5 = _mm256_fmadd_pd(ymm0, ymm3, ymm5); ymm7 = _mm256_fmadd_pd(ymm1, ymm3, ymm7); ymm9 = _mm256_fmadd_pd(ymm2, ymm3, ymm9); tA += lda; } // alpha, beta multiplication. ymm0 = _mm256_broadcast_sd(alpha_cast); //ymm1 = _mm256_broadcast_sd(beta_cast); //multiply A*B by alpha. ymm4 = _mm256_mul_pd(ymm4, ymm0); ymm5 = _mm256_mul_pd(ymm5, ymm0); ymm6 = _mm256_mul_pd(ymm6, ymm0); ymm7 = _mm256_mul_pd(ymm7, ymm0); ymm8 = _mm256_mul_pd(ymm8, ymm0); ymm9 = _mm256_mul_pd(ymm9, ymm0); // multiply C by beta and accumulate. /*ymm2 = _mm256_loadu_pd(tC); ymm4 = _mm256_fmadd_pd(ymm2, ymm1, ymm4); ymm2 = _mm256_loadu_pd(tC + 4); ymm5 = _mm256_fmadd_pd(ymm2, ymm1, ymm5);*/ _mm256_storeu_pd(tC, ymm4); _mm256_storeu_pd(tC + 4, ymm5); // multiply C by beta and accumulate. tC += ldc; /*ymm2 = _mm256_loadu_pd(tC); ymm6 = _mm256_fmadd_pd(ymm2, ymm1, ymm6); ymm2 = _mm256_loadu_pd(tC + 4); ymm7 = _mm256_fmadd_pd(ymm2, ymm1, ymm7);*/ _mm256_storeu_pd(tC, ymm6); _mm256_storeu_pd(tC + 4, ymm7); // multiply C by beta and accumulate. tC += ldc; /*ymm2 = _mm256_loadu_pd(tC); ymm8 = _mm256_fmadd_pd(ymm2, ymm1, ymm8); ymm2 = _mm256_loadu_pd(tC + 4); ymm9 = _mm256_fmadd_pd(ymm2, ymm1, ymm9);*/ _mm256_storeu_pd(tC, ymm8); _mm256_storeu_pd(tC + 4, ymm9); } n_remainder = N - col_idx; // if the N is not multiple of 3. // handling edge case. if (n_remainder == 2) { //pointer math to point to proper memory tC = C + ldc * col_idx + row_idx; tB = B + tb_inc_col * col_idx; tA = A + row_idx; // clear scratch registers. ymm4 = _mm256_setzero_pd(); ymm5 = _mm256_setzero_pd(); ymm6 = _mm256_setzero_pd(); ymm7 = _mm256_setzero_pd(); for (k = 0; k < K; ++k) { // The inner loop broadcasts the B matrix data and // multiplies it with the A matrix. ymm0 = _mm256_broadcast_sd(tB + tb_inc_col * 0); ymm1 = _mm256_broadcast_sd(tB + tb_inc_col * 1); tB += tb_inc_row; //broadcasted matrix B elements are multiplied //with matrix A columns. ymm3 = _mm256_loadu_pd(tA); ymm4 = _mm256_fmadd_pd(ymm0, ymm3, ymm4); ymm6 = _mm256_fmadd_pd(ymm1, ymm3, ymm6); ymm3 = _mm256_loadu_pd(tA + 4); ymm5 = _mm256_fmadd_pd(ymm0, ymm3, ymm5); ymm7 = _mm256_fmadd_pd(ymm1, ymm3, ymm7); tA += lda; } // alpha, beta multiplication. ymm0 = _mm256_broadcast_sd(alpha_cast); //ymm1 = _mm256_broadcast_sd(beta_cast); //multiply A*B by alpha. ymm4 = _mm256_mul_pd(ymm4, ymm0); ymm5 = _mm256_mul_pd(ymm5, ymm0); ymm6 = _mm256_mul_pd(ymm6, ymm0); ymm7 = _mm256_mul_pd(ymm7, ymm0); // multiply C by beta and accumulate. /*ymm2 = _mm256_loadu_pd(tC); ymm4 = _mm256_fmadd_pd(ymm2, ymm1, ymm4); ymm2 = _mm256_loadu_pd(tC + 4); ymm5 = _mm256_fmadd_pd(ymm2, ymm1, ymm5);*/ _mm256_storeu_pd(tC, ymm4); _mm256_storeu_pd(tC + 4, ymm5); // multiply C by beta and accumulate. tC += ldc; /*ymm2 = _mm256_loadu_pd(tC); ymm6 = _mm256_fmadd_pd(ymm2, ymm1, ymm6); ymm2 = _mm256_loadu_pd(tC + 4); ymm7 = _mm256_fmadd_pd(ymm2, ymm1, ymm7);*/ _mm256_storeu_pd(tC, ymm6); _mm256_storeu_pd(tC + 4, ymm7); col_idx += 2; } // if the N is not multiple of 3. // handling edge case. if (n_remainder == 1) { //pointer math to point to proper memory tC = C + ldc * col_idx + row_idx; tB = B + tb_inc_col * col_idx; tA = A + row_idx; ymm4 = _mm256_setzero_pd(); ymm5 = _mm256_setzero_pd(); for (k = 0; k < K; ++k) { // The inner loop broadcasts the B matrix data and // multiplies it with the A matrix. ymm0 = _mm256_broadcast_sd(tB + tb_inc_col * 0); tB += tb_inc_row; //broadcasted matrix B elements are multiplied //with matrix A columns. ymm3 = _mm256_loadu_pd(tA); ymm4 = _mm256_fmadd_pd(ymm0, ymm3, ymm4); ymm3 = _mm256_loadu_pd(tA + 4); ymm5 = _mm256_fmadd_pd(ymm0, ymm3, ymm5); tA += lda; } // alpha, beta multiplication. ymm0 = _mm256_broadcast_sd(alpha_cast); //ymm1 = _mm256_broadcast_sd(beta_cast); ymm4 = _mm256_mul_pd(ymm4, ymm0); ymm5 = _mm256_mul_pd(ymm5, ymm0); // multiply C by beta and accumulate. /*ymm2 = _mm256_loadu_pd(tC); ymm4 = _mm256_fmadd_pd(ymm2, ymm1, ymm4); ymm2 = _mm256_loadu_pd(tC + 4); ymm5 = _mm256_fmadd_pd(ymm2, ymm1, ymm5);*/ _mm256_storeu_pd(tC, ymm4); _mm256_storeu_pd(tC + 4, ymm5); } row_idx += 8; } if (m_remainder >= 4) { m_remainder -= 4; for (col_idx = 0; (col_idx + 2) < N; col_idx += 3) { //pointer math to point to proper memory tC = C + ldc * col_idx + row_idx; tB = B + tb_inc_col * col_idx; tA = A + row_idx; // clear scratch registers. ymm4 = _mm256_setzero_pd(); ymm5 = _mm256_setzero_pd(); ymm6 = _mm256_setzero_pd(); for (k = 0; k < K; ++k) { // The inner loop broadcasts the B matrix data and // multiplies it with the A matrix. ymm0 = _mm256_broadcast_sd(tB + tb_inc_col * 0); ymm1 = _mm256_broadcast_sd(tB + tb_inc_col * 1); ymm2 = _mm256_broadcast_sd(tB + tb_inc_col * 2); tB += tb_inc_row; //broadcasted matrix B elements are multiplied //with matrix A columns. ymm3 = _mm256_loadu_pd(tA); ymm4 = _mm256_fmadd_pd(ymm0, ymm3, ymm4); ymm5 = _mm256_fmadd_pd(ymm1, ymm3, ymm5); ymm6 = _mm256_fmadd_pd(ymm2, ymm3, ymm6); tA += lda; } // alpha, beta multiplication. ymm0 = _mm256_broadcast_sd(alpha_cast); //ymm1 = _mm256_broadcast_sd(beta_cast); //multiply A*B by alpha. ymm4 = _mm256_mul_pd(ymm4, ymm0); ymm5 = _mm256_mul_pd(ymm5, ymm0); ymm6 = _mm256_mul_pd(ymm6, ymm0); // multiply C by beta and accumulate. /*ymm2 = _mm256_loadu_pd(tC); ymm4 = _mm256_fmadd_pd(ymm2, ymm1, ymm4);*/ _mm256_storeu_pd(tC, ymm4); // multiply C by beta and accumulate. tC += ldc; /*ymm2 = _mm256_loadu_pd(tC); ymm5 = _mm256_fmadd_pd(ymm2, ymm1, ymm5);*/ _mm256_storeu_pd(tC, ymm5); // multiply C by beta and accumulate. tC += ldc; /*ymm2 = _mm256_loadu_pd(tC); ymm6 = _mm256_fmadd_pd(ymm2, ymm1, ymm6);*/ _mm256_storeu_pd(tC, ymm6); } n_remainder = N - col_idx; // if the N is not multiple of 3. // handling edge case. if (n_remainder == 2) { //pointer math to point to proper memory tC = C + ldc * col_idx + row_idx; tB = B + tb_inc_col * col_idx; tA = A + row_idx; ymm4 = _mm256_setzero_pd(); ymm5 = _mm256_setzero_pd(); for (k = 0; k < K; ++k) { // The inner loop broadcasts the B matrix data and // multiplies it with the A matrix. ymm0 = _mm256_broadcast_sd(tB + tb_inc_col * 0); ymm1 = _mm256_broadcast_sd(tB + tb_inc_col * 1); tB += tb_inc_row; //broadcasted matrix B elements are multiplied //with matrix A columns. ymm3 = _mm256_loadu_pd(tA); ymm4 = _mm256_fmadd_pd(ymm0, ymm3, ymm4); ymm5 = _mm256_fmadd_pd(ymm1, ymm3, ymm5); tA += lda; } // alpha, beta multiplication. ymm0 = _mm256_broadcast_sd(alpha_cast); //ymm1 = _mm256_broadcast_sd(beta_cast); //multiply A*B by alpha. ymm4 = _mm256_mul_pd(ymm4, ymm0); ymm5 = _mm256_mul_pd(ymm5, ymm0); // multiply C by beta and accumulate. /*ymm2 = _mm256_loadu_pd(tC); ymm4 = _mm256_fmadd_pd(ymm2, ymm1, ymm4);*/ _mm256_storeu_pd(tC, ymm4); // multiply C by beta and accumulate. tC += ldc; /*ymm2 = _mm256_loadu_pd(tC); ymm5 = _mm256_fmadd_pd(ymm2, ymm1, ymm5);*/ _mm256_storeu_pd(tC, ymm5); col_idx += 2; } // if the N is not multiple of 3. // handling edge case. if (n_remainder == 1) { //pointer math to point to proper memory tC = C + ldc * col_idx + row_idx; tB = B + tb_inc_col * col_idx; tA = A + row_idx; ymm4 = _mm256_setzero_pd(); for (k = 0; k < K; ++k) { // The inner loop broadcasts the B matrix data and // multiplies it with the A matrix. ymm0 = _mm256_broadcast_sd(tB + tb_inc_col * 0); tB += tb_inc_row; //broadcasted matrix B elements are multiplied //with matrix A columns. ymm3 = _mm256_loadu_pd(tA); ymm4 = _mm256_fmadd_pd(ymm0, ymm3, ymm4); tA += lda; } // alpha, beta multiplication. ymm0 = _mm256_broadcast_sd(alpha_cast); //ymm1 = _mm256_broadcast_sd(beta_cast); ymm4 = _mm256_mul_pd(ymm4, ymm0); // multiply C by beta and accumulate. /*ymm2 = _mm256_loadu_pd(tC); ymm4 = _mm256_fmadd_pd(ymm2, ymm1, ymm4);*/ _mm256_storeu_pd(tC, ymm4); } row_idx += 4; } // M is not a multiple of 32. // The handling of edge case where the remainder // dimension is less than 8. The padding takes place // to handle this case. if ((m_remainder) && (lda > 3)) { double f_temp[8]; for (col_idx = 0; (col_idx + 2) < N; col_idx += 3) { //pointer math to point to proper memory tC = C + ldc * col_idx + row_idx; tB = B + tb_inc_col * col_idx; tA = A + row_idx; // clear scratch registers. ymm5 = _mm256_setzero_pd(); ymm7 = _mm256_setzero_pd(); ymm9 = _mm256_setzero_pd(); for (k = 0; k < (K - 1); ++k) { // The inner loop broadcasts the B matrix data and // multiplies it with the A matrix. ymm0 = _mm256_broadcast_sd(tB + tb_inc_col * 0); ymm1 = _mm256_broadcast_sd(tB + tb_inc_col * 1); ymm2 = _mm256_broadcast_sd(tB + tb_inc_col * 2); tB += tb_inc_row; //broadcasted matrix B elements are multiplied //with matrix A columns. ymm3 = _mm256_loadu_pd(tA); ymm5 = _mm256_fmadd_pd(ymm0, ymm3, ymm5); ymm7 = _mm256_fmadd_pd(ymm1, ymm3, ymm7); ymm9 = _mm256_fmadd_pd(ymm2, ymm3, ymm9); tA += lda; } // alpha, beta multiplication. ymm0 = _mm256_broadcast_sd(tB + tb_inc_col * 0); ymm1 = _mm256_broadcast_sd(tB + tb_inc_col * 1); ymm2 = _mm256_broadcast_sd(tB + tb_inc_col * 2); tB += tb_inc_row; for (int i = 0; i < m_remainder; i++) { f_temp[i] = tA[i]; } ymm3 = _mm256_loadu_pd(f_temp); ymm5 = _mm256_fmadd_pd(ymm0, ymm3, ymm5); ymm7 = _mm256_fmadd_pd(ymm1, ymm3, ymm7); ymm9 = _mm256_fmadd_pd(ymm2, ymm3, ymm9); ymm0 = _mm256_broadcast_sd(alpha_cast); //ymm1 = _mm256_broadcast_sd(beta_cast); //multiply A*B by alpha. ymm5 = _mm256_mul_pd(ymm5, ymm0); ymm7 = _mm256_mul_pd(ymm7, ymm0); ymm9 = _mm256_mul_pd(ymm9, ymm0); /*for (int i = 0; i < m_remainder; i++) { f_temp[i] = tC[i]; } ymm2 = _mm256_loadu_pd(f_temp); ymm5 = _mm256_fmadd_pd(ymm2, ymm1, ymm5);*/ _mm256_storeu_pd(f_temp, ymm5); for (int i = 0; i < m_remainder; i++) { tC[i] = f_temp[i]; } tC += ldc; /*for (int i = 0; i < m_remainder; i++) { f_temp[i] = tC[i]; } ymm2 = _mm256_loadu_pd(f_temp); ymm7 = _mm256_fmadd_pd(ymm2, ymm1, ymm7);*/ _mm256_storeu_pd(f_temp, ymm7); for (int i = 0; i < m_remainder; i++) { tC[i] = f_temp[i]; } tC += ldc; /*for (int i = 0; i < m_remainder; i++) { f_temp[i] = tC[i]; } ymm2 = _mm256_loadu_pd(f_temp); ymm9 = _mm256_fmadd_pd(ymm2, ymm1, ymm9);*/ _mm256_storeu_pd(f_temp, ymm9); for (int i = 0; i < m_remainder; i++) { tC[i] = f_temp[i]; } } n_remainder = N - col_idx; // if the N is not multiple of 3. // handling edge case. if (n_remainder == 2) { //pointer math to point to proper memory tC = C + ldc * col_idx + row_idx; tB = B + tb_inc_col * col_idx; tA = A + row_idx; ymm5 = _mm256_setzero_pd(); ymm7 = _mm256_setzero_pd(); for (k = 0; k < (K - 1); ++k) { // The inner loop broadcasts the B matrix data and // multiplies it with the A matrix. ymm0 = _mm256_broadcast_sd(tB + tb_inc_col * 0); ymm1 = _mm256_broadcast_sd(tB + tb_inc_col * 1); tB += tb_inc_row; ymm3 = _mm256_loadu_pd(tA); ymm5 = _mm256_fmadd_pd(ymm0, ymm3, ymm5); ymm7 = _mm256_fmadd_pd(ymm1, ymm3, ymm7); tA += lda; } ymm0 = _mm256_broadcast_sd(tB + tb_inc_col * 0); ymm1 = _mm256_broadcast_sd(tB + tb_inc_col * 1); tB += tb_inc_row; for (int i = 0; i < m_remainder; i++) { f_temp[i] = tA[i]; } ymm3 = _mm256_loadu_pd(f_temp); ymm5 = _mm256_fmadd_pd(ymm0, ymm3, ymm5); ymm7 = _mm256_fmadd_pd(ymm1, ymm3, ymm7); ymm0 = _mm256_broadcast_sd(alpha_cast); //ymm1 = _mm256_broadcast_sd(beta_cast); ymm5 = _mm256_mul_pd(ymm5, ymm0); ymm7 = _mm256_mul_pd(ymm7, ymm0); /*for (int i = 0; i < m_remainder; i++) { f_temp[i] = tC[i]; } ymm2 = _mm256_loadu_pd(f_temp); ymm5 = _mm256_fmadd_pd(ymm2, ymm1, ymm5);*/ _mm256_storeu_pd(f_temp, ymm5); for (int i = 0; i < m_remainder; i++) { tC[i] = f_temp[i]; } tC += ldc; /*for (int i = 0; i < m_remainder; i++) { f_temp[i] = tC[i]; } ymm2 = _mm256_loadu_pd(f_temp); ymm7 = _mm256_fmadd_pd(ymm2, ymm1, ymm7);*/ _mm256_storeu_pd(f_temp, ymm7); for (int i = 0; i < m_remainder; i++) { tC[i] = f_temp[i]; } } // if the N is not multiple of 3. // handling edge case. if (n_remainder == 1) { //pointer math to point to proper memory tC = C + ldc * col_idx + row_idx; tB = B + tb_inc_col * col_idx; tA = A + row_idx; ymm5 = _mm256_setzero_pd(); for (k = 0; k < (K - 1); ++k) { // The inner loop broadcasts the B matrix data and // multiplies it with the A matrix. ymm0 = _mm256_broadcast_sd(tB + tb_inc_col * 0); tB += tb_inc_row; ymm3 = _mm256_loadu_pd(tA); ymm5 = _mm256_fmadd_pd(ymm0, ymm3, ymm5); tA += lda; } ymm0 = _mm256_broadcast_sd(tB + tb_inc_col * 0); tB += tb_inc_row; for (int i = 0; i < m_remainder; i++) { f_temp[i] = tA[i]; } ymm3 = _mm256_loadu_pd(f_temp); ymm5 = _mm256_fmadd_pd(ymm0, ymm3, ymm5); ymm0 = _mm256_broadcast_sd(alpha_cast); //ymm1 = _mm256_broadcast_sd(beta_cast); // multiply C by beta and accumulate. ymm5 = _mm256_mul_pd(ymm5, ymm0); /*for (int i = 0; i < m_remainder; i++) { f_temp[i] = tC[i]; } ymm2 = _mm256_loadu_pd(f_temp); ymm5 = _mm256_fmadd_pd(ymm2, ymm1, ymm5);*/ _mm256_storeu_pd(f_temp, ymm5); for (int i = 0; i < m_remainder; i++) { tC[i] = f_temp[i]; } } m_remainder = 0; } if (m_remainder) { double result; for (; row_idx < M; row_idx += 1) { for (col_idx = 0; col_idx < N; col_idx += 1) { //pointer math to point to proper memory tC = C + ldc * col_idx + row_idx; tB = B + tb_inc_col * col_idx; tA = A + row_idx; result = 0; for (k = 0; k < K; ++k) { result += (*tA) * (*tB); tA += lda; tB += tb_inc_row; } result *= (*alpha_cast); (*tC) = /*(*tC) * (*beta_cast) + */result; } } } //copy/compute sryk values back to C using SIMD if ( bli_seq0( *beta_cast ) ) {//just copy for beta = 0 dim_t _i, _j, k, _l; if(bli_obj_is_lower(c)) //c is lower { //first column _j = 0; k = M >> 2; _i = 0; for ( _l = 0; _l < k; _l++ ) { ymm0 = _mm256_loadu_pd((C + _i*rsc)); _mm256_storeu_pd((matCbuf + _i*rs_matC), ymm0); _i += 4; } while (_i < M ) { bli_ddcopys( *(C + _i*rsc + _j*ldc), *(matCbuf + _i*rs_matC + _j*ldc_matC) ); _i++; } _j++; while ( _j < N ) //next column { //k = (_j + (4 - (_j & 3))); _l = _j & 3; k = (_l != 0) ? (_j + (4 - _l)) : _j; k = (k <= M) ? k : M; for ( _i = _j; _i < k; ++_i ) { bli_ddcopys( *(C + _i*rsc + _j*ldc), *(matCbuf + _i*rs_matC + _j*ldc_matC) ); } k = (M - _i) >> 2; _l = 0; while ( _l < k ) { ymm0 = _mm256_loadu_pd((C + _i*rsc + _j*ldc)); _mm256_storeu_pd((matCbuf + _i*rs_matC + _j*ldc_matC), ymm0); _i += 4; _l++; } while (_i < M ) { bli_ddcopys( *(C + _i*rsc + _j*ldc), *(matCbuf + _i*rs_matC + _j*ldc_matC) ); _i++; } _j++; } } else //c is upper { for ( _j = 0; _j < N; ++_j ) { k = (_j + 1) >> 2; _i = 0; _l = 0; while ( _l < k ) { ymm0 = _mm256_loadu_pd((C + _i*rsc + _j*ldc)); _mm256_storeu_pd((matCbuf + _i*rs_matC + _j*ldc_matC), ymm0); _i += 4; _l++; } while (_i <= _j ) { bli_ddcopys( *(C + _i*rsc + _j*ldc), *(matCbuf + _i*rs_matC + _j*ldc_matC) ); ++_i; } } } } else {//when beta is non-zero, fmadd and store the results dim_t _i, _j, k, _l; ymm1 = _mm256_broadcast_sd(beta_cast); if(bli_obj_is_lower(c)) //c is lower { //first column _j = 0; k = M >> 2; _i = 0; for ( _l = 0; _l < k; _l++ ) { ymm2 = _mm256_loadu_pd((matCbuf + _i*rs_matC)); ymm0 = _mm256_loadu_pd((C + _i*rsc)); ymm0 = _mm256_fmadd_pd(ymm2, ymm1, ymm0); _mm256_storeu_pd((matCbuf + _i*rs_matC), ymm0); _i += 4; } while (_i < M ) { bli_dddxpbys( *(C + _i*rsc + _j*ldc), *(beta_cast), *(matCbuf + _i*rs_matC + _j*ldc_matC) ); _i++; } _j++; while ( _j < N ) //next column { //k = (_j + (4 - (_j & 3))); _l = _j & 3; k = (_l != 0) ? (_j + (4 - _l)) : _j; k = (k <= M) ? k : M; for ( _i = _j; _i < k; ++_i ) { bli_dddxpbys( *(C + _i*rsc + _j*ldc), *(beta_cast), *(matCbuf + _i*rs_matC + _j*ldc_matC) ); } k = (M - _i) >> 2; _l = 0; while ( _l < k ) { ymm2 = _mm256_loadu_pd((matCbuf + _i*rs_matC + _j*ldc_matC)); ymm0 = _mm256_loadu_pd((C + _i*rsc + _j*ldc)); ymm0 = _mm256_fmadd_pd(ymm2, ymm1, ymm0); _mm256_storeu_pd((matCbuf + _i*rs_matC + _j*ldc_matC), ymm0); _i += 4; _l++; } while (_i < M ) { bli_dddxpbys( *(C + _i*rsc + _j*ldc), *(beta_cast), *(matCbuf + _i*rs_matC + _j*ldc_matC) ); _i++; } _j++; } } else //c is upper { for ( _j = 0; _j < N; ++_j ) { k = (_j + 1) >> 2; _i = 0; _l = 0; while ( _l < k ) { ymm2 = _mm256_loadu_pd((matCbuf + _i*rs_matC + _j*ldc_matC)); ymm0 = _mm256_loadu_pd((C + _i*rsc + _j*ldc)); ymm0 = _mm256_fmadd_pd(ymm2, ymm1, ymm0); _mm256_storeu_pd((matCbuf + _i*rs_matC + _j*ldc_matC), ymm0); _i += 4; _l++; } while (_i <= _j ) { bli_dddxpbys( *(C + _i*rsc + _j*ldc), *(beta_cast), *(matCbuf + _i*rs_matC + _j*ldc_matC) ); ++_i; } } } } return BLIS_SUCCESS; } else return BLIS_NONCONFORMAL_DIMENSIONS; }; static err_t bli_sgemmt_small_atbn ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, cntl_t* cntl ) { int M = bli_obj_length(c); // number of rows of Matrix C int N = bli_obj_width(c); // number of columns of Matrix C int K = bli_obj_length(b); // number of rows of Matrix B int lda = bli_obj_col_stride(a); // column stride of matrix OP(A), where OP(A) is Transpose(A) if transA enabled. int ldb = bli_obj_col_stride(b); // column stride of matrix OP(B), where OP(B) is Transpose(B) if transB enabled. int ldc_matC = bli_obj_col_stride( c ); // column stride of matrix C int ldc = M;//bli_obj_col_stride( c ); // column stride of static buffer for matrix C int row_idx = 0, col_idx = 0, k; int rs_matC = bli_obj_row_stride( c ); int rsc = 1; float *A = a->buffer; // pointer to matrix A elements, stored in row major format float *B = b->buffer; // pointer to matrix B elements, stored in column major format float *C = C_pack; // pointer to matrix C elements, stored in column major format float *matCbuf = c->buffer; float *tA = A, *tB = B, *tC = C; __m256 ymm4, ymm5, ymm6, ymm7; __m256 ymm8, ymm9, ymm10, ymm11; __m256 ymm12, ymm13, ymm14, ymm15; __m256 ymm0, ymm1, ymm2, ymm3; float result, scratch[8]; float *alpha_cast, *beta_cast; // alpha, beta multiples alpha_cast = (alpha->buffer); beta_cast = (beta->buffer); // The non-copy version of the A^T GEMMT gives better performance for the small M cases. // The threshold is controlled by BLIS_ATBN_M_THRES if (M <= BLIS_ATBN_M_THRES) { for (col_idx = 0; (col_idx + (NR - 1)) < N; col_idx += NR) { for (row_idx = 0; (row_idx + (AT_MR - 1)) < M; row_idx += AT_MR) { tA = A + row_idx * lda; tB = B + col_idx * ldb; tC = C + col_idx * ldc + row_idx; // clear scratch registers. ymm4 = _mm256_setzero_ps(); ymm5 = _mm256_setzero_ps(); ymm6 = _mm256_setzero_ps(); ymm7 = _mm256_setzero_ps(); ymm8 = _mm256_setzero_ps(); ymm9 = _mm256_setzero_ps(); ymm10 = _mm256_setzero_ps(); ymm11 = _mm256_setzero_ps(); ymm12 = _mm256_setzero_ps(); ymm13 = _mm256_setzero_ps(); ymm14 = _mm256_setzero_ps(); ymm15 = _mm256_setzero_ps(); //The inner loop computes the 4x3 values of the matrix. //The computation pattern is: // ymm4 ymm5 ymm6 // ymm7 ymm8 ymm9 // ymm10 ymm11 ymm12 // ymm13 ymm14 ymm15 //The Dot operation is performed in the inner loop, 8 float elements fit //in the YMM register hence loop count incremented by 8 for (k = 0; (k + 7) < K; k += 8) { ymm0 = _mm256_loadu_ps(tB + 0); ymm1 = _mm256_loadu_ps(tB + ldb); ymm2 = _mm256_loadu_ps(tB + 2 * ldb); ymm3 = _mm256_loadu_ps(tA); ymm4 = _mm256_fmadd_ps(ymm0, ymm3, ymm4); ymm5 = _mm256_fmadd_ps(ymm1, ymm3, ymm5); ymm6 = _mm256_fmadd_ps(ymm2, ymm3, ymm6); ymm3 = _mm256_loadu_ps(tA + lda); ymm7 = _mm256_fmadd_ps(ymm0, ymm3, ymm7); ymm8 = _mm256_fmadd_ps(ymm1, ymm3, ymm8); ymm9 = _mm256_fmadd_ps(ymm2, ymm3, ymm9); ymm3 = _mm256_loadu_ps(tA + 2 * lda); ymm10 = _mm256_fmadd_ps(ymm0, ymm3, ymm10); ymm11 = _mm256_fmadd_ps(ymm1, ymm3, ymm11); ymm12 = _mm256_fmadd_ps(ymm2, ymm3, ymm12); ymm3 = _mm256_loadu_ps(tA + 3 * lda); ymm13 = _mm256_fmadd_ps(ymm0, ymm3, ymm13); ymm14 = _mm256_fmadd_ps(ymm1, ymm3, ymm14); ymm15 = _mm256_fmadd_ps(ymm2, ymm3, ymm15); tA += 8; tB += 8; } // if K is not a multiple of 8, padding is done before load using temproary array. if (k < K) { int iter; float data_feeder[8] = { 0.0 }; for (iter = 0; iter < (K - k); iter++) data_feeder[iter] = tB[iter]; ymm0 = _mm256_loadu_ps(data_feeder); for (iter = 0; iter < (K - k); iter++) data_feeder[iter] = tB[iter + ldb]; ymm1 = _mm256_loadu_ps(data_feeder); for (iter = 0; iter < (K - k); iter++) data_feeder[iter] = tB[iter + 2 * ldb]; ymm2 = _mm256_loadu_ps(data_feeder); for (iter = 0; iter < (K - k); iter++) data_feeder[iter] = tA[iter]; ymm3 = _mm256_loadu_ps(data_feeder); ymm4 = _mm256_fmadd_ps(ymm0, ymm3, ymm4); ymm5 = _mm256_fmadd_ps(ymm1, ymm3, ymm5); ymm6 = _mm256_fmadd_ps(ymm2, ymm3, ymm6); for (iter = 0; iter < (K - k); iter++) data_feeder[iter] = tA[lda + iter]; ymm3 = _mm256_loadu_ps(data_feeder); ymm7 = _mm256_fmadd_ps(ymm0, ymm3, ymm7); ymm8 = _mm256_fmadd_ps(ymm1, ymm3, ymm8); ymm9 = _mm256_fmadd_ps(ymm2, ymm3, ymm9); for (iter = 0; iter < (K - k); iter++) data_feeder[iter] = tA[2 * lda + iter]; ymm3 = _mm256_loadu_ps(data_feeder); ymm10 = _mm256_fmadd_ps(ymm0, ymm3, ymm10); ymm11 = _mm256_fmadd_ps(ymm1, ymm3, ymm11); ymm12 = _mm256_fmadd_ps(ymm2, ymm3, ymm12); for (iter = 0; iter < (K - k); iter++) data_feeder[iter] = tA[3 * lda + iter]; ymm3 = _mm256_loadu_ps(data_feeder); ymm13 = _mm256_fmadd_ps(ymm0, ymm3, ymm13); ymm14 = _mm256_fmadd_ps(ymm1, ymm3, ymm14); ymm15 = _mm256_fmadd_ps(ymm2, ymm3, ymm15); } //horizontal addition and storage of the data. //Results for 4x3 blocks of C is stored here ymm4 = _mm256_hadd_ps(ymm4, ymm4); ymm4 = _mm256_hadd_ps(ymm4, ymm4); _mm256_storeu_ps(scratch, ymm4); result = scratch[0] + scratch[4]; result *= (*alpha_cast); tC[0] = result/* + tC[0] * (*beta_cast)*/; ymm7 = _mm256_hadd_ps(ymm7, ymm7); ymm7 = _mm256_hadd_ps(ymm7, ymm7); _mm256_storeu_ps(scratch, ymm7); result = scratch[0] + scratch[4]; result *= (*alpha_cast); tC[1] = result/* + tC[1] * (*beta_cast)*/; ymm10 = _mm256_hadd_ps(ymm10, ymm10); ymm10 = _mm256_hadd_ps(ymm10, ymm10); _mm256_storeu_ps(scratch, ymm10); result = scratch[0] + scratch[4]; result *= (*alpha_cast); tC[2] = result/* + tC[2] * (*beta_cast)*/; ymm13 = _mm256_hadd_ps(ymm13, ymm13); ymm13 = _mm256_hadd_ps(ymm13, ymm13); _mm256_storeu_ps(scratch, ymm13); result = scratch[0] + scratch[4]; result *= (*alpha_cast); tC[3] = result/* + tC[3] * (*beta_cast)*/; tC += ldc; ymm5 = _mm256_hadd_ps(ymm5, ymm5); ymm5 = _mm256_hadd_ps(ymm5, ymm5); _mm256_storeu_ps(scratch, ymm5); result = scratch[0] + scratch[4]; result *= (*alpha_cast); tC[0] = result/* + tC[0] * (*beta_cast)*/; ymm8 = _mm256_hadd_ps(ymm8, ymm8); ymm8 = _mm256_hadd_ps(ymm8, ymm8); _mm256_storeu_ps(scratch, ymm8); result = scratch[0] + scratch[4]; result *= (*alpha_cast); tC[1] = result/* + tC[1] * (*beta_cast)*/; ymm11 = _mm256_hadd_ps(ymm11, ymm11); ymm11 = _mm256_hadd_ps(ymm11, ymm11); _mm256_storeu_ps(scratch, ymm11); result = scratch[0] + scratch[4]; result *= (*alpha_cast); tC[2] = result/* + tC[2] * (*beta_cast)*/; ymm14 = _mm256_hadd_ps(ymm14, ymm14); ymm14 = _mm256_hadd_ps(ymm14, ymm14); _mm256_storeu_ps(scratch, ymm14); result = scratch[0] + scratch[4]; result *= (*alpha_cast); tC[3] = result/* + tC[3] * (*beta_cast)*/; tC += ldc; ymm6 = _mm256_hadd_ps(ymm6, ymm6); ymm6 = _mm256_hadd_ps(ymm6, ymm6); _mm256_storeu_ps(scratch, ymm6); result = scratch[0] + scratch[4]; result *= (*alpha_cast); tC[0] = result/* + tC[0] * (*beta_cast)*/; ymm9 = _mm256_hadd_ps(ymm9, ymm9); ymm9 = _mm256_hadd_ps(ymm9, ymm9); _mm256_storeu_ps(scratch, ymm9); result = scratch[0] + scratch[4]; result *= (*alpha_cast); tC[1] = result/* + tC[1] * (*beta_cast)*/; ymm12 = _mm256_hadd_ps(ymm12, ymm12); ymm12 = _mm256_hadd_ps(ymm12, ymm12); _mm256_storeu_ps(scratch, ymm12); result = scratch[0] + scratch[4]; result *= (*alpha_cast); tC[2] = result/* + tC[2] * (*beta_cast)*/; ymm15 = _mm256_hadd_ps(ymm15, ymm15); ymm15 = _mm256_hadd_ps(ymm15, ymm15); _mm256_storeu_ps(scratch, ymm15); result = scratch[0] + scratch[4]; result *= (*alpha_cast); tC[3] = result/* + tC[3] * (*beta_cast)*/; } } int processed_col = col_idx; int processed_row = row_idx; //The edge case handling where N is not a multiple of 3 if (processed_col < N) { for (col_idx = processed_col; col_idx < N; col_idx += 1) { for (row_idx = 0; (row_idx + (AT_MR - 1)) < M; row_idx += AT_MR) { tA = A + row_idx * lda; tB = B + col_idx * ldb; tC = C + col_idx * ldc + row_idx; // clear scratch registers. ymm4 = _mm256_setzero_ps(); ymm7 = _mm256_setzero_ps(); ymm10 = _mm256_setzero_ps(); ymm13 = _mm256_setzero_ps(); //The inner loop computes the 4x1 values of the matrix. //The computation pattern is: // ymm4 // ymm7 // ymm10 // ymm13 for (k = 0; (k + 7) < K; k += 8) { ymm0 = _mm256_loadu_ps(tB + 0); ymm3 = _mm256_loadu_ps(tA); ymm4 = _mm256_fmadd_ps(ymm0, ymm3, ymm4); ymm3 = _mm256_loadu_ps(tA + lda); ymm7 = _mm256_fmadd_ps(ymm0, ymm3, ymm7); ymm3 = _mm256_loadu_ps(tA + 2 * lda); ymm10 = _mm256_fmadd_ps(ymm0, ymm3, ymm10); ymm3 = _mm256_loadu_ps(tA + 3 * lda); ymm13 = _mm256_fmadd_ps(ymm0, ymm3, ymm13); tA += 8; tB += 8; } // if K is not a multiple of 8, padding is done before load using temproary array. if (k < K) { int iter; float data_feeder[8] = { 0.0 }; for (iter = 0; iter < (K - k); iter++) data_feeder[iter] = tB[iter]; ymm0 = _mm256_loadu_ps(data_feeder); for (iter = 0; iter < (K - k); iter++) data_feeder[iter] = tA[iter]; ymm3 = _mm256_loadu_ps(data_feeder); ymm4 = _mm256_fmadd_ps(ymm0, ymm3, ymm4); for (iter = 0; iter < (K - k); iter++) data_feeder[iter] = tA[lda + iter]; ymm3 = _mm256_loadu_ps(data_feeder); ymm7 = _mm256_fmadd_ps(ymm0, ymm3, ymm7); for (iter = 0; iter < (K - k); iter++) data_feeder[iter] = tA[2 * lda + iter]; ymm3 = _mm256_loadu_ps(data_feeder); ymm10 = _mm256_fmadd_ps(ymm0, ymm3, ymm10); for (iter = 0; iter < (K - k); iter++) data_feeder[iter] = tA[3 * lda + iter]; ymm3 = _mm256_loadu_ps(data_feeder); ymm13 = _mm256_fmadd_ps(ymm0, ymm3, ymm13); } //horizontal addition and storage of the data. //Results for 4x1 blocks of C is stored here ymm4 = _mm256_hadd_ps(ymm4, ymm4); ymm4 = _mm256_hadd_ps(ymm4, ymm4); _mm256_storeu_ps(scratch, ymm4); result = scratch[0] + scratch[4]; result *= (*alpha_cast); tC[0] = result/* + tC[0] * (*beta_cast)*/; ymm7 = _mm256_hadd_ps(ymm7, ymm7); ymm7 = _mm256_hadd_ps(ymm7, ymm7); _mm256_storeu_ps(scratch, ymm7); result = scratch[0] + scratch[4]; result *= (*alpha_cast); tC[1] = result/* + tC[1] * (*beta_cast)*/; ymm10 = _mm256_hadd_ps(ymm10, ymm10); ymm10 = _mm256_hadd_ps(ymm10, ymm10); _mm256_storeu_ps(scratch, ymm10); result = scratch[0] + scratch[4]; result *= (*alpha_cast); tC[2] = result/* + tC[2] * (*beta_cast)*/; ymm13 = _mm256_hadd_ps(ymm13, ymm13); ymm13 = _mm256_hadd_ps(ymm13, ymm13); _mm256_storeu_ps(scratch, ymm13); result = scratch[0] + scratch[4]; result *= (*alpha_cast); tC[3] = result/* + tC[3] * (*beta_cast)*/; } } processed_row = row_idx; } //The edge case handling where M is not a multiple of 4 if (processed_row < M) { for (row_idx = processed_row; row_idx < M; row_idx += 1) { for (col_idx = 0; col_idx < N; col_idx += 1) { tA = A + row_idx * lda; tB = B + col_idx * ldb; tC = C + col_idx * ldc + row_idx; // clear scratch registers. ymm4 = _mm256_setzero_ps(); for (k = 0; (k + 7) < K; k += 8) { ymm0 = _mm256_loadu_ps(tB + 0); ymm3 = _mm256_loadu_ps(tA); ymm4 = _mm256_fmadd_ps(ymm0, ymm3, ymm4); tA += 8; tB += 8; } // if K is not a multiple of 8, padding is done before load using temproary array. if (k < K) { int iter; float data_feeder[8] = { 0.0 }; for (iter = 0; iter < (K - k); iter++) data_feeder[iter] = tB[iter]; ymm0 = _mm256_loadu_ps(data_feeder); for (iter = 0; iter < (K - k); iter++) data_feeder[iter] = tA[iter]; ymm3 = _mm256_loadu_ps(data_feeder); ymm4 = _mm256_fmadd_ps(ymm0, ymm3, ymm4); } //horizontal addition and storage of the data. ymm4 = _mm256_hadd_ps(ymm4, ymm4); ymm4 = _mm256_hadd_ps(ymm4, ymm4); _mm256_storeu_ps(scratch, ymm4); result = scratch[0] + scratch[4]; result *= (*alpha_cast); tC[0] = result/* + tC[0] * (*beta_cast)*/; } } } //copy/compute sryk values back to C if ( bli_seq0( *beta_cast ) ) //when beta is 0, just copy result to C { dim_t _i, _j; if(bli_obj_is_lower(c)) //c is lower { for ( _j = 0; _j < N; ++_j ) for ( _i = 0; _i < M; ++_i ) if ( (doff_t)_j - (doff_t)_i <= 0 ) { bli_sscopys( *(C + _i*rsc + _j*ldc), *(matCbuf + _i*rs_matC + _j*ldc_matC) ); } } else //c is upper { for ( _j = 0; _j < N; ++_j ) for ( _i = 0; _i < M; ++_i ) if ( (doff_t)_j - (doff_t)_i >= 0 ) { bli_sscopys( *(C + _i*rsc + _j*ldc), *(matCbuf + _i*rs_matC + _j*ldc_matC) ); } } } else //when beta is non-zero, multiply and store result to C { dim_t _i, _j; if(bli_obj_is_lower(c)) //c is lower { for ( _j = 0; _j < N; ++_j ) for ( _i = 0; _i < M; ++_i ) if ( (doff_t)_j - (doff_t)_i <= 0 ) { bli_sssxpbys( *(C + _i*rsc + _j*ldc), *(beta_cast), *(matCbuf + _i*rs_matC + _j*ldc_matC) ); } } else //c is upper { for ( _j = 0; _j < N; ++_j ) for ( _i = 0; _i < M; ++_i ) if ( (doff_t)_j - (doff_t)_i >= 0 ) { bli_sssxpbys( *(C + _i*rsc + _j*ldc), *(beta_cast), *(matCbuf + _i*rs_matC + _j*ldc_matC) ); } } } return BLIS_SUCCESS; } else return BLIS_NONCONFORMAL_DIMENSIONS; } static err_t bli_dgemmt_small_atbn ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, cntl_t* cntl ) { int M = bli_obj_length( c ); // number of rows of Matrix C int N = bli_obj_width( c ); // number of columns of Matrix C int K = bli_obj_length( b ); // number of rows of Matrix B int lda = bli_obj_col_stride( a ); // column stride of matrix OP(A), where OP(A) is Transpose(A) if transA enabled. int ldb = bli_obj_col_stride( b ); // column stride of matrix OP(B), where OP(B) is Transpose(B) if transB enabled. int ldc_matC = bli_obj_col_stride( c ); // column stride of matrix C int ldc = M;//bli_obj_col_stride( c ); // column stride of static buffer for matrix C int row_idx = 0, col_idx = 0, k; int rs_matC = bli_obj_row_stride( c ); int rsc = 1; double *A = a->buffer; // pointer to matrix A elements, stored in row major format double *B = b->buffer; // pointer to matrix B elements, stored in column major format double *C = D_C_pack; // pointer to matrix C elements, stored in column major format double *matCbuf = c->buffer; double *tA = A, *tB = B, *tC = C; __m256d ymm4, ymm5, ymm6, ymm7; __m256d ymm8, ymm9, ymm10, ymm11; __m256d ymm12, ymm13, ymm14, ymm15; __m256d ymm0, ymm1, ymm2, ymm3; double result, scratch[8]; double *alpha_cast, *beta_cast; // alpha, beta multiples alpha_cast = (alpha->buffer); beta_cast = (beta->buffer); // The non-copy version of the A^T GEMMT gives better performance for the small M cases. // The threshold is controlled by BLIS_ATBN_M_THRES if (M <= BLIS_ATBN_M_THRES) { for (col_idx = 0; (col_idx + (NR - 1)) < N; col_idx += NR) { for (row_idx = 0; (row_idx + (AT_MR - 1)) < M; row_idx += AT_MR) { tA = A + row_idx * lda; tB = B + col_idx * ldb; tC = C + col_idx * ldc + row_idx; // clear scratch registers. ymm4 = _mm256_setzero_pd(); ymm5 = _mm256_setzero_pd(); ymm6 = _mm256_setzero_pd(); ymm7 = _mm256_setzero_pd(); ymm8 = _mm256_setzero_pd(); ymm9 = _mm256_setzero_pd(); ymm10 = _mm256_setzero_pd(); ymm11 = _mm256_setzero_pd(); ymm12 = _mm256_setzero_pd(); ymm13 = _mm256_setzero_pd(); ymm14 = _mm256_setzero_pd(); ymm15 = _mm256_setzero_pd(); //The inner loop computes the 4x3 values of the matrix. //The computation pattern is: // ymm4 ymm5 ymm6 // ymm7 ymm8 ymm9 // ymm10 ymm11 ymm12 // ymm13 ymm14 ymm15 //The Dot operation is performed in the inner loop, 4 double elements fit //in the YMM register hence loop count incremented by 4 for (k = 0; (k + 3) < K; k += 4) { ymm0 = _mm256_loadu_pd(tB + 0); ymm1 = _mm256_loadu_pd(tB + ldb); ymm2 = _mm256_loadu_pd(tB + 2 * ldb); ymm3 = _mm256_loadu_pd(tA); ymm4 = _mm256_fmadd_pd(ymm0, ymm3, ymm4); ymm5 = _mm256_fmadd_pd(ymm1, ymm3, ymm5); ymm6 = _mm256_fmadd_pd(ymm2, ymm3, ymm6); ymm3 = _mm256_loadu_pd(tA + lda); ymm7 = _mm256_fmadd_pd(ymm0, ymm3, ymm7); ymm8 = _mm256_fmadd_pd(ymm1, ymm3, ymm8); ymm9 = _mm256_fmadd_pd(ymm2, ymm3, ymm9); ymm3 = _mm256_loadu_pd(tA + 2 * lda); ymm10 = _mm256_fmadd_pd(ymm0, ymm3, ymm10); ymm11 = _mm256_fmadd_pd(ymm1, ymm3, ymm11); ymm12 = _mm256_fmadd_pd(ymm2, ymm3, ymm12); ymm3 = _mm256_loadu_pd(tA + 3 * lda); ymm13 = _mm256_fmadd_pd(ymm0, ymm3, ymm13); ymm14 = _mm256_fmadd_pd(ymm1, ymm3, ymm14); ymm15 = _mm256_fmadd_pd(ymm2, ymm3, ymm15); tA += 4; tB += 4; } // if K is not a multiple of 4, padding is done before load using temproary array. if (k < K) { int iter; double data_feeder[4] = { 0.0 }; for (iter = 0; iter < (K - k); iter++) data_feeder[iter] = tB[iter]; ymm0 = _mm256_loadu_pd(data_feeder); for (iter = 0; iter < (K - k); iter++) data_feeder[iter] = tB[iter + ldb]; ymm1 = _mm256_loadu_pd(data_feeder); for (iter = 0; iter < (K - k); iter++) data_feeder[iter] = tB[iter + 2 * ldb]; ymm2 = _mm256_loadu_pd(data_feeder); for (iter = 0; iter < (K - k); iter++) data_feeder[iter] = tA[iter]; ymm3 = _mm256_loadu_pd(data_feeder); ymm4 = _mm256_fmadd_pd(ymm0, ymm3, ymm4); ymm5 = _mm256_fmadd_pd(ymm1, ymm3, ymm5); ymm6 = _mm256_fmadd_pd(ymm2, ymm3, ymm6); for (iter = 0; iter < (K - k); iter++) data_feeder[iter] = tA[lda + iter]; ymm3 = _mm256_loadu_pd(data_feeder); ymm7 = _mm256_fmadd_pd(ymm0, ymm3, ymm7); ymm8 = _mm256_fmadd_pd(ymm1, ymm3, ymm8); ymm9 = _mm256_fmadd_pd(ymm2, ymm3, ymm9); for (iter = 0; iter < (K - k); iter++) data_feeder[iter] = tA[2 * lda + iter]; ymm3 = _mm256_loadu_pd(data_feeder); ymm10 = _mm256_fmadd_pd(ymm0, ymm3, ymm10); ymm11 = _mm256_fmadd_pd(ymm1, ymm3, ymm11); ymm12 = _mm256_fmadd_pd(ymm2, ymm3, ymm12); for (iter = 0; iter < (K - k); iter++) data_feeder[iter] = tA[3 * lda + iter]; ymm3 = _mm256_loadu_pd(data_feeder); ymm13 = _mm256_fmadd_pd(ymm0, ymm3, ymm13); ymm14 = _mm256_fmadd_pd(ymm1, ymm3, ymm14); ymm15 = _mm256_fmadd_pd(ymm2, ymm3, ymm15); } //horizontal addition and storage of the data. //Results for 4x3 blocks of C is stored here ymm4 = _mm256_hadd_pd(ymm4, ymm4); _mm256_storeu_pd(scratch, ymm4); result = scratch[0] + scratch[2]; result *= (*alpha_cast); tC[0] = result/* + tC[0] * (*beta_cast)*/; ymm7 = _mm256_hadd_pd(ymm7, ymm7); _mm256_storeu_pd(scratch, ymm7); result = scratch[0] + scratch[2]; result *= (*alpha_cast); tC[1] = result/* + tC[1] * (*beta_cast)*/; ymm10 = _mm256_hadd_pd(ymm10, ymm10); _mm256_storeu_pd(scratch, ymm10); result = scratch[0] + scratch[2]; result *= (*alpha_cast); tC[2] = result/* + tC[2] * (*beta_cast)*/; ymm13 = _mm256_hadd_pd(ymm13, ymm13); _mm256_storeu_pd(scratch, ymm13); result = scratch[0] + scratch[2]; result *= (*alpha_cast); tC[3] = result/* + tC[3] * (*beta_cast)*/; tC += ldc; ymm5 = _mm256_hadd_pd(ymm5, ymm5); _mm256_storeu_pd(scratch, ymm5); result = scratch[0] + scratch[2]; result *= (*alpha_cast); tC[0] = result/* + tC[0] * (*beta_cast)*/; ymm8 = _mm256_hadd_pd(ymm8, ymm8); _mm256_storeu_pd(scratch, ymm8); result = scratch[0] + scratch[2]; result *= (*alpha_cast); tC[1] = result/* + tC[1] * (*beta_cast)*/; ymm11 = _mm256_hadd_pd(ymm11, ymm11); _mm256_storeu_pd(scratch, ymm11); result = scratch[0] + scratch[2]; result *= (*alpha_cast); tC[2] = result/* + tC[2] * (*beta_cast)*/; ymm14 = _mm256_hadd_pd(ymm14, ymm14); _mm256_storeu_pd(scratch, ymm14); result = scratch[0] + scratch[2]; result *= (*alpha_cast); tC[3] = result/* + tC[3] * (*beta_cast)*/; tC += ldc; ymm6 = _mm256_hadd_pd(ymm6, ymm6); _mm256_storeu_pd(scratch, ymm6); result = scratch[0] + scratch[2]; result *= (*alpha_cast); tC[0] = result/* + tC[0] * (*beta_cast)*/; ymm9 = _mm256_hadd_pd(ymm9, ymm9); _mm256_storeu_pd(scratch, ymm9); result = scratch[0] + scratch[2]; result *= (*alpha_cast); tC[1] = result/* + tC[1] * (*beta_cast)*/; ymm12 = _mm256_hadd_pd(ymm12, ymm12); _mm256_storeu_pd(scratch, ymm12); result = scratch[0] + scratch[2]; result *= (*alpha_cast); tC[2] = result/* + tC[2] * (*beta_cast)*/; ymm15 = _mm256_hadd_pd(ymm15, ymm15); _mm256_storeu_pd(scratch, ymm15); result = scratch[0] + scratch[2]; result *= (*alpha_cast); tC[3] = result/* + tC[3] * (*beta_cast)*/; } } int processed_col = col_idx; int processed_row = row_idx; //The edge case handling where N is not a multiple of 3 if (processed_col < N) { for (col_idx = processed_col; col_idx < N; col_idx += 1) { for (row_idx = 0; (row_idx + (AT_MR - 1)) < M; row_idx += AT_MR) { tA = A + row_idx * lda; tB = B + col_idx * ldb; tC = C + col_idx * ldc + row_idx; // clear scratch registers. ymm4 = _mm256_setzero_pd(); ymm7 = _mm256_setzero_pd(); ymm10 = _mm256_setzero_pd(); ymm13 = _mm256_setzero_pd(); //The inner loop computes the 4x1 values of the matrix. //The computation pattern is: // ymm4 // ymm7 // ymm10 // ymm13 for (k = 0; (k + 3) < K; k += 4) { ymm0 = _mm256_loadu_pd(tB + 0); ymm3 = _mm256_loadu_pd(tA); ymm4 = _mm256_fmadd_pd(ymm0, ymm3, ymm4); ymm3 = _mm256_loadu_pd(tA + lda); ymm7 = _mm256_fmadd_pd(ymm0, ymm3, ymm7); ymm3 = _mm256_loadu_pd(tA + 2 * lda); ymm10 = _mm256_fmadd_pd(ymm0, ymm3, ymm10); ymm3 = _mm256_loadu_pd(tA + 3 * lda); ymm13 = _mm256_fmadd_pd(ymm0, ymm3, ymm13); tA += 4; tB += 4; } // if K is not a multiple of 4, padding is done before load using temproary array. if (k < K) { int iter; double data_feeder[4] = { 0.0 }; for (iter = 0; iter < (K - k); iter++) data_feeder[iter] = tB[iter]; ymm0 = _mm256_loadu_pd(data_feeder); for (iter = 0; iter < (K - k); iter++) data_feeder[iter] = tA[iter]; ymm3 = _mm256_loadu_pd(data_feeder); ymm4 = _mm256_fmadd_pd(ymm0, ymm3, ymm4); for (iter = 0; iter < (K - k); iter++) data_feeder[iter] = tA[lda + iter]; ymm3 = _mm256_loadu_pd(data_feeder); ymm7 = _mm256_fmadd_pd(ymm0, ymm3, ymm7); for (iter = 0; iter < (K - k); iter++) data_feeder[iter] = tA[2 * lda + iter]; ymm3 = _mm256_loadu_pd(data_feeder); ymm10 = _mm256_fmadd_pd(ymm0, ymm3, ymm10); for (iter = 0; iter < (K - k); iter++) data_feeder[iter] = tA[3 * lda + iter]; ymm3 = _mm256_loadu_pd(data_feeder); ymm13 = _mm256_fmadd_pd(ymm0, ymm3, ymm13); } //horizontal addition and storage of the data. //Results for 4x1 blocks of C is stored here ymm4 = _mm256_hadd_pd(ymm4, ymm4); _mm256_storeu_pd(scratch, ymm4); result = scratch[0] + scratch[2]; result *= (*alpha_cast); tC[0] = result/* + tC[0] * (*beta_cast)*/; ymm7 = _mm256_hadd_pd(ymm7, ymm7); _mm256_storeu_pd(scratch, ymm7); result = scratch[0] + scratch[2]; result *= (*alpha_cast); tC[1] = result/* + tC[1] * (*beta_cast)*/; ymm10 = _mm256_hadd_pd(ymm10, ymm10); _mm256_storeu_pd(scratch, ymm10); result = scratch[0] + scratch[2]; result *= (*alpha_cast); tC[2] = result/* + tC[2] * (*beta_cast)*/; ymm13 = _mm256_hadd_pd(ymm13, ymm13); _mm256_storeu_pd(scratch, ymm13); result = scratch[0] + scratch[2]; result *= (*alpha_cast); tC[3] = result/* + tC[3] * (*beta_cast)*/; } } processed_row = row_idx; } // The edge case handling where M is not a multiple of 4 if (processed_row < M) { for (row_idx = processed_row; row_idx < M; row_idx += 1) { for (col_idx = 0; col_idx < N; col_idx += 1) { tA = A + row_idx * lda; tB = B + col_idx * ldb; tC = C + col_idx * ldc + row_idx; // clear scratch registers. ymm4 = _mm256_setzero_pd(); for (k = 0; (k + 3) < K; k += 4) { ymm0 = _mm256_loadu_pd(tB + 0); ymm3 = _mm256_loadu_pd(tA); ymm4 = _mm256_fmadd_pd(ymm0, ymm3, ymm4); tA += 4; tB += 4; } // if K is not a multiple of 4, padding is done before load using temproary array. if (k < K) { int iter; double data_feeder[4] = { 0.0 }; for (iter = 0; iter < (K - k); iter++) data_feeder[iter] = tB[iter]; ymm0 = _mm256_loadu_pd(data_feeder); for (iter = 0; iter < (K - k); iter++) data_feeder[iter] = tA[iter]; ymm3 = _mm256_loadu_pd(data_feeder); ymm4 = _mm256_fmadd_pd(ymm0, ymm3, ymm4); } //horizontal addition and storage of the data. ymm4 = _mm256_hadd_pd(ymm4, ymm4); _mm256_storeu_pd(scratch, ymm4); result = scratch[0] + scratch[2]; result *= (*alpha_cast); tC[0] = result/* + tC[0] * (*beta_cast)*/; } } } //copy/compute sryk values back to C if ( bli_seq0( *beta_cast ) ) //when beta is 0, just copy result to C { dim_t _i, _j; if(bli_obj_is_lower(c)) //c is lower { for ( _j = 0; _j < N; ++_j ) for ( _i = 0; _i < M; ++_i ) if ( (doff_t)_j - (doff_t)_i <= 0 ) { bli_ddcopys( *(C + _i*rsc + _j*ldc), *(matCbuf + _i*rs_matC + _j*ldc_matC) ); } } else //c is upper { for ( _j = 0; _j < N; ++_j ) for ( _i = 0; _i < M; ++_i ) if ( (doff_t)_j - (doff_t)_i >= 0 ) { bli_ddcopys( *(C + _i*rsc + _j*ldc), *(matCbuf + _i*rs_matC + _j*ldc_matC) ); } } } else //when beta is non-zero, multiply and store result to C { dim_t _i, _j; if(bli_obj_is_lower(c)) //c is lower { for ( _j = 0; _j < N; ++_j ) for ( _i = 0; _i < M; ++_i ) if ( (doff_t)_j - (doff_t)_i <= 0 ) { bli_dddxpbys( *(C + _i*rsc + _j*ldc), *(beta_cast), *(matCbuf + _i*rs_matC + _j*ldc_matC) ); } } else //c is upper { for ( _j = 0; _j < N; ++_j ) for ( _i = 0; _i < M; ++_i ) if ( (doff_t)_j - (doff_t)_i >= 0 ) { bli_dddxpbys( *(C + _i*rsc + _j*ldc), *(beta_cast), *(matCbuf + _i*rs_matC + _j*ldc_matC) ); } } } return BLIS_SUCCESS; } else return BLIS_NONCONFORMAL_DIMENSIONS; } #endif blis-0.9.0/kernels/zen/3/bli_trsm_small.c000066400000000000000000065012561422157504600202460ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2018-2019, Advanced Micro Devices, Inc. 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 The University of Texas at Austin 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #ifdef BLIS_ENABLE_SMALL_MATRIX_TRSM #include "immintrin.h" #define GEMM_BLK_V1 8 //Block size to perform gemm and apply trsm #define GEMM_ACCUM_A 1 //Peform B1=B1-(B0*A0) operation instead of B1'=(B0*A0) and then B1=B1-B1' #define OPT_CACHE_BLOCKING_L1 1 //Perform trsm block-wise in blocks of GEMM_BLK_V1 instead of all columns of B together. #define REARRANGE_SHFL 0 //Rearrange operations using blend or shuffle #define BLI_AlXB_M_SP 16 #define BLI_XAltB_N_SP 128 #define BLI_AutXB_M_SP 64 #define BLI_AutXB_N_SP 128 // XA = B; A is lower-traingular; No transpose; double precision; non-unit diagonal static err_t bli_dtrsm_small_XAlB( side_t side, obj_t* AlphaObj, obj_t* a, obj_t* b, cntx_t* cntx, cntl_t* cntl ); //XA = B; A is lower triabgular; No transpose; double precision; unit-diagonal static err_t bli_dtrsm_small_XAlB_unitDiag( side_t side, obj_t* AlphaObj, obj_t* a, obj_t* b, cntx_t* cntx, cntl_t* cntl ); //XA = B; A is lower-triangular; A is transposed; double precision; non-unit-diagonal static err_t bli_dtrsm_small_XAltB( side_t side, obj_t* AlphaObj, obj_t* a, obj_t* b, cntx_t* cntx, cntl_t* cntl ); //XA = B; A is lower-triangular; A is transposed; double precision; unit-diagonal static err_t bli_dtrsm_small_XAltB_unitDiag( side_t side, obj_t* AlphaObj, obj_t* a, obj_t* b, cntx_t* cntx, cntl_t* cntl ); // XA = B; A is upper triangular; No transpose; double presicion; non-unit diagonal static err_t bli_dtrsm_small_XAuB ( side_t side, obj_t* alpha, obj_t* a, obj_t* b, cntx_t* cntx, cntl_t* cntl ); //XA = B; A is upper triangular; No transpose; double precision; unit-diagonal static err_t bli_dtrsm_small_XAuB_unitDiag( side_t side, obj_t* AlphaObj, obj_t* a, obj_t* b, cntx_t* cntx, cntl_t* cntl ); //XA = B; A is upper-triangular; A is transposed; double precision; non-unit diagonal static err_t bli_dtrsm_small_XAutB( side_t side, obj_t* AlphaObj, obj_t* a, obj_t* b, cntx_t* cntx, cntl_t* cntl ); //XA = B; A is upper-triangular; A is transposed; double precision; unit diagonal static err_t bli_dtrsm_small_XAutB_unitDiag( side_t side, obj_t* AlphaObj, obj_t* a, obj_t* b, cntx_t* cntx, cntl_t* cntl ); //AX = B; A is lower triangular; No transpose; double precision; non-unit diagonal static err_t bli_dtrsm_small_AlXB( side_t side, obj_t* AlphaObj, obj_t* a, obj_t* b, cntx_t* cntx, cntl_t* cntl ); //AX = B; A is lower triangular; No transpose; double precision; unit diagonal static err_t bli_dtrsm_small_AlXB_unitDiag( side_t side, obj_t* AlphaObj, obj_t* a, obj_t* b, cntx_t* cntx, cntl_t* cntl ); static void (*fp_blis_strsm_microkernel)( float *ptr_l, float *ptr_b, int numRows_lb, int numCols_b, int rs_l, int rs_b, int cs_l, int cs_b ); static void blis_strsm_microkernel( float *ptr_l, float *ptr_b, int numRows_lb, int numCols_b, int rs_l, int rs_b, int cs_l, int cs_b ); static void blis_strsm_microkernel_alpha( float *ptr_l, float *ptr_b, int numRows_lb, int numCols_b, int rs_l, int rs_b, int cs_l, int cs_b, float alphaVal ); static void blis_strsm_microkernel_unitDiag( float *ptr_l, float *ptr_b, int numRows_lb, int numCols_b, int rs_l, int rs_b, int cs_l, int cs_b ); static void blis_strsm_microkernel_alpha_unitDiag( float *ptr_l, float *ptr_b, int numRows_lb, int numCols_b, int rs_l, int rs_b, int cs_l, int cs_b, float alphaVal ); static void trsm_XAtB_block_allSmallSizedMatrices(float *ptr_l, float *ptr_b, int numRows_lb, int numCols_b, int rs_l, int rs_b, int cs_l, int cs_b); static void trsm_XAtB_block_allSmallSizedMatrices_alpha(float *ptr_l, float *ptr_b, int numRows_lb, int numCols_b, int rs_l, int rs_b, int cs_l, int cs_b, float alphaVal); static void trsm_XAtB_block_allSmallSizedMatrices_unitDiag(float *ptr_l, float *ptr_b, int numRows_lb, int numCols_b, int rs_l, int rs_b, int cs_l, int cs_b); static void trsm_XAtB_block_allSmallSizedMatrices_alpha_unitDiag(float *ptr_l, float *ptr_b, int numRows_lb, int numCols_b, int rs_l, int rs_b, int cs_l, int cs_b, float alphaVal); static void blis_dtrsm_microkernel( double *ptr_l, double *ptr_b, int numRows_lb, int numCols_b, int rs_l, int rs_b, int cs_l, int cs_b ); static void blis_dtrsm_microkernel_alpha( double *ptr_l, double *ptr_b, int numRows_lb, int numCols_b, int rs_l, int rs_b, int cs_l, int cs_b, double alphaVal ); static void blis_dtrsm_microkernel_unitDiag( double *ptr_l, double *ptr_b, int numRows_lb, int numCols_b, int rs_l, int rs_b, int cs_l, int cs_b ); static void blis_dtrsm_microkernel_alpha_unitDiag( double *ptr_l, double *ptr_b, int numRows_lb, int numCols_b, int rs_l, int rs_b, int cs_l, int cs_b, double alphaVal ); static void dtrsm_XAtB_block_allSmallSizedMatrices(double *ptr_l, double *ptr_b, int numRows_lb, int numCols_b, int rs_l, int rs_b, int cs_l, int cs_b); static void dtrsm_XAtB_block_allSmallSizedMatrices_alpha(double *ptr_l, double *ptr_b, int numRows_lb, int numCols_b, int rs_l, int rs_b, int cs_l, int cs_b, double alphaVal); static void dtrsm_XAtB_block_allSmallSizedMatrices_unitDiag(double *ptr_l, double *ptr_b, int numRows_lb, int numCols_b, int rs_l, int rs_b, int cs_l, int cs_b); static void dtrsm_XAtB_block_allSmallSizedMatrices_alpha_unitDiag(double *ptr_l, double *ptr_b, int numRows_lb, int numCols_b, int rs_l, int rs_b, int cs_l, int cs_b, double alphaVal); static void trsm_AutXB_block_allSmallSizedMatrices(float *ptr_l, float *ptr_b, int numRows_lb, int numCols_b, int rs_l, int rs_b, int cs_l, int cs_b); static void trsm_AutXB_block_allSmallSizedMatrices_alpha(float *ptr_l, float *ptr_b, int numRows_lb, int numCols_b, int rs_l, int rs_b, int cs_l, int cs_b, float alpha); static void trsm_AutXB_block_allSmallSizedMatrices_unitDiag(float *ptr_l, float *ptr_b, int numRows_lb, int numCols_b, int rs_l, int rs_b, int cs_l, int cs_b); static void trsm_AutXB_block_allSmallSizedMatrices_alpha_unitDiag(float *ptr_l, float *ptr_b, int numRows_lb, int numCols_b, int rs_l, int rs_b, int cs_l, int cs_b, float alpha); //AX = B; A is lower triangular; No transpose; single precision static err_t bli_strsm_small_AlXB ( side_t side, obj_t* alpha, obj_t* a, obj_t* b, cntx_t* cntx, cntl_t* cntl ); //A.'X = B; A is upper triangular; A has to be transposed; single precision static err_t bli_strsm_small_AutXB ( side_t side, obj_t* alpha, obj_t* a, obj_t* b, cntx_t* cntx, cntl_t* cntl ); //XA.' = B; A is lower triangular; A has to be transposed; single precision static err_t bli_strsm_small_XAltB ( side_t side, obj_t* alpha, obj_t* a, obj_t* b, cntx_t* cntx, cntl_t* cntl ); //A.'X = B; A is upper triangular; A has to be transposed; double precision static err_t bli_dtrsm_small_AutXB ( side_t side, obj_t* alpha, obj_t* a, obj_t* b, cntx_t* cntx, cntl_t* cntl ); /* * The bli_trsm_small implements unpacked version of TRSM * Currently only column-major is supported, A & B are column-major * Input: A: MxM (triangular matrix) * B: MxN matrix * Output: X: MxN matrix such that AX = alpha*B or XA = alpha*B or A'X = alpha*B or XA' = alpha*B * Here the output X is stored in B * The custom-kernel will be called only when M*(M+N)* sizeof(Matrix Elements) < L3 cache */ err_t bli_trsm_small ( side_t side, obj_t* alpha, obj_t* a, obj_t* b, cntx_t* cntx, cntl_t* cntl ) { #ifdef BLIS_ENABLE_MULTITHREADING return BLIS_NOT_YET_IMPLEMENTED; #endif dim_t m = bli_obj_length(b); dim_t n = bli_obj_width(b); if(!(m && n)) return BLIS_SUCCESS; // If alpha is zero, B matrix will become zero after scaling & hence solution is also zero matrix if (bli_obj_equals(alpha, &BLIS_ZERO)) { return BLIS_NOT_YET_IMPLEMENTED; // scale B by alpha } // We have to call matrix scaling if alpha != 1.0 // if row major format return. Check this again. if ((bli_obj_row_stride(a) != 1) || (bli_obj_row_stride(b) != 1)) { return BLIS_INVALID_ROW_STRIDE; } num_t dt = ((*b).info & (0x7 << 0)); // only float and double datatypes are supported as of now. if (dt != BLIS_DOUBLE && dt != BLIS_FLOAT) { return BLIS_EXPECTED_REAL_DATATYPE; } // A is expected to be triangular in trsm if (!bli_obj_is_upper_or_lower (a)) { return BLIS_EXPECTED_TRIANGULAR_OBJECT; } // can use other control structs - even can use array of function pointers, // indexed by a number with bits formed by f('side', 'uplo', 'transa', dt). // In the below implementation, based on the number of finally implemented // cases, can move the checks with more cases higher up. if(side == BLIS_LEFT) { if(bli_obj_has_trans(a)) { if(dt == BLIS_DOUBLE) { if(bli_obj_is_upper(a)) { //return bli_dtrsm_small_AutXB(side, alpha, a, b, cntx, cntl); return BLIS_NOT_YET_IMPLEMENTED; } else { //return bli_dtrsm_small_AltXB(side, alpha, a, b, cntx, cntl); return BLIS_NOT_YET_IMPLEMENTED; } } else { if(bli_obj_is_upper(a)) { return bli_strsm_small_AutXB(side, alpha, a, b, cntx, cntl); } else { //return bli_strsm_small_AltXB(side, alpha, a, b, cntx, cntl); return BLIS_NOT_YET_IMPLEMENTED; } } } else { if(dt == BLIS_DOUBLE) { if(bli_obj_is_upper(a)) { //return bli_dtrsm_small_AuXB(side, alpha, a, b, cntx, cntl); return BLIS_NOT_YET_IMPLEMENTED; } else { if(bli_obj_has_unit_diag(a)) return bli_dtrsm_small_AlXB_unitDiag(side, alpha, a, b, cntx, cntl); else return bli_dtrsm_small_AlXB(side, alpha, a, b, cntx, cntl); } } else { if(bli_obj_is_upper(a)) { //return bli_strsm_small_AuXB(side, alpha, a, b, cntx, cntl); return BLIS_NOT_YET_IMPLEMENTED; } else { return bli_strsm_small_AlXB(side, alpha, a, b, cntx, cntl); } } } } else { if(bli_obj_has_trans(a)) { if(dt == BLIS_DOUBLE) { if(bli_obj_is_upper(a)) { if(bli_obj_has_unit_diag(a)) return bli_dtrsm_small_XAutB_unitDiag(side, alpha, a, b, cntx, cntl); else return bli_dtrsm_small_XAutB(side, alpha, a, b, cntx, cntl); } else { if(bli_obj_has_unit_diag(a)) return bli_dtrsm_small_XAltB_unitDiag(side, alpha, a, b, cntx, cntl); else return bli_dtrsm_small_XAltB(side, alpha, a, b, cntx, cntl); } } else { if(bli_obj_is_upper(a)) { //return bli_strsm_small_XAutB(side, alpha, a, b, cntx, cntl); return BLIS_NOT_YET_IMPLEMENTED; } else { return bli_strsm_small_XAltB(side, alpha, a, b, cntx, cntl); } } } else { if(dt == BLIS_DOUBLE) { if(bli_obj_is_upper(a)) { if(bli_obj_has_unit_diag(a)) return bli_dtrsm_small_XAuB_unitDiag(side, alpha, a, b, cntx, cntl); else return bli_dtrsm_small_XAuB(side, alpha, a, b, cntx, cntl); } else { if(bli_obj_has_unit_diag(a)) return bli_dtrsm_small_XAlB_unitDiag(side, alpha, a, b, cntx, cntl); else return bli_dtrsm_small_XAlB(side, alpha, a, b, cntx, cntl); } } else { if(bli_obj_is_upper(a)) { //return bli_strsm_small_XAuB(side, alpha, a, b, cntx, cntl); return BLIS_NOT_YET_IMPLEMENTED; } else { //return bli_strsm_small_XAlB(side, alpha, a, b, cntx, cntl); return BLIS_NOT_YET_IMPLEMENTED; } } } } return BLIS_NOT_YET_IMPLEMENTED; }; /* TRSM scalar code for the case AX = alpha * B * A is lower-triangular, non-unit-diagonal, no transpose * Dimensions: A: mxm X: mxn B:mxn */ static err_t dtrsm_small_AlXB ( double *A, double *B, dim_t M, dim_t N, dim_t lda, dim_t ldb ) { dim_t i, j, k; for (k = 0; k < M; k++) { double lkk_inv = 1.0/A[k+k*lda]; for (j = 0; j < N; j++) { B[k + j*ldb] *= lkk_inv; for (i = k+1; i < M; i++) { B[i + j*ldb] -= A[i + k*lda] * B[k + j*ldb]; } } }// k -loop return BLIS_SUCCESS; }// end of function /* TRSM scalar code for the case AX = alpha * B * A is lower-triangular, unit-diagonal, no transpose * Dimensions: A: mxm X: mxn B:mxn */ static err_t dtrsm_small_AlXB_unitDiag ( double *A, double *B, dim_t M, dim_t N, dim_t lda, dim_t ldb ) { dim_t i, j, k; for (k = 0; k < M; k++) { for (j = 0; j < N; j++) { for (i = k+1; i < M; i++) { B[i + j*ldb] -= A[i + k*lda] * B[k + j*ldb]; } } } return BLIS_SUCCESS; }// end of function /* TRSM scalar code for the case XA = alpha * B * A is upper-triangular, non-unit-diagonal no transpose * Dimensions: X:mxn A:nxn B:mxn */ static err_t dtrsm_small_XAuB ( double *A, double *B, dim_t M, dim_t N, dim_t lda, dim_t ldb ) { dim_t i, j, k; for(k = 0; k < N; k++) { double lkk_inv = 1.0/A[k+k*lda]; for(i = 0; i < M; i++) { B[i+k*ldb] *= lkk_inv; for(j = k+1; j < N; j++) { B[i+j*ldb] -= B[i+k*ldb] * A[k+j*lda]; } } } return BLIS_SUCCESS; } /* TRSM scalar code for the case XA = alpha * B * A is lower-triangular, non-unit triangular, no transpose * Dimensions: X:mxn A:nxn B:mxn */ static err_t dtrsm_small_XAlB ( double *A, double *B, double alpha, dim_t M, dim_t N, dim_t lda, dim_t ldb ) { dim_t i, j, k; for(j = 0; j < N; j++) for(i = 0; i < M; i++) B[i+j*ldb] *= alpha; for(k = N;k--;) { double lkk_inv = 1.0/A[(k)+(k)*lda]; for(i = M;i--;) { B[(i)+(k)*ldb] *= lkk_inv; for(j = k;j--;) { B[(i)+(j)*ldb] -= B[(i)+(k)*ldb] * A[(k)+(j)*lda]; } } } return BLIS_SUCCESS; } /* TRSM scalar code for the case XA = alpha * B * A is lower-triangular, unit-diagonal, no transpose *Dimensions: X:mxn A:nxn B:mxn */ static err_t dtrsm_small_XAlB_unitDiag( double *A, double *B, double alpha, dim_t M, dim_t N, dim_t lda, dim_t ldb ) { dim_t i, j, k; for(j = 0 ; j < N; j++) for(i = 0; i < M; i++) B[i+j*ldb] *= alpha; double A_k_j; for(k = N; k--;) { for(j = k; j--;) { A_k_j = A[(k)+(j)*lda]; for(i = M; i--;) { B[(i)+(j)*ldb] -= B[(i)+(k)*ldb] * A_k_j; } } } return BLIS_SUCCESS; } /* TRSM scalar code for the case XA = alpha * B *A is upper-triangular, non-unit-diagonal, A is transposed * Dimensions: X:mxn A:nxn B:mxn */ static err_t dtrsm_small_XAutB ( double *A, double *B, double alpha, dim_t M, dim_t N, dim_t lda, dim_t ldb ) { dim_t i, j, k; for(j = 0; j < N; j++) for(i = 0; i < M; i++) B[i+j*ldb] *=alpha; for(k = N; k--;) { double lkk_inv = 1.0/A[(k)+(k)*lda]; for(i = M; i--;) { B[(i)+(k)*ldb] *= lkk_inv; for(j = k; j--;) { B[(i)+(j)*ldb] -= B[(i)+(k)*ldb] * A[(j)+(k)*lda]; } } } return BLIS_SUCCESS; } /* TRSM scalar code for the case XA = alpha * B * A is upper-triangular, unit-diagonal, A has to be transposed * Dimensions: X:mxn A:nxn B:mxn */ static err_t dtrsm_small_XAutB_unitDiag( double *A, double *B, double alpha, dim_t M, dim_t N, dim_t lda, dim_t ldb ) { dim_t i, j, k; double A_k_j; for(j = 0; j< N; j++) for(i = 0; i< M; i++) B[i+j*ldb] *= alpha; for(k = N; k--;) { for(j = k; j--;) { A_k_j = A[(j)+(k)*lda]; for(i = M; i--;) { B[(i)+(j)*ldb] -= B[(i)+(k)*ldb] * A_k_j; } } } return BLIS_SUCCESS; } /* TRSM scalar code for the case XA = alpha * B * A is lower-triangular, non-unit-diagonal, A has to be transposed * Dimensions: X:mxn A:nxn B:mxn */ static err_t dtrsm_small_XAltB ( double *A, double *B, dim_t M, dim_t N, dim_t lda, dim_t ldb ) { dim_t i, j, k; for(k = 0; k < N; k++) { double lkk_inv = 1.0/A[k+k*lda]; for(i = 0; i < M; i++) { B[i+k*ldb] *= lkk_inv; for(j = k+1; j < N; j++) { B[i+j*ldb] -= B[i+k*ldb] * A[j+k*lda]; } } } return BLIS_SUCCESS; } /* TRSM scalar code for XA = alpha * B * A is lower-triangular, unit-diagonal, A has to be transposed * Dimensions: X:mxn A:nxn B:mxn */ static err_t dtrsm_small_XAltB_unitDiag( double *A, double *B, dim_t M, dim_t N, dim_t lda, dim_t ldb ) { dim_t i, j, k; for(k = 0; k < N; k++) { for(i = 0; i < M; i++) { for(j = k+1; j < N; j++) { B[i+j*ldb] -= B[i+k*ldb] * A[j+k*lda]; } } } return BLIS_SUCCESS; } /* TRSM scalar code for the case XA = alpha * B * A is upper-triangular, unit-diagonal, no transpose * Dimensions: X:mxn A:nxn B:mxn */ static err_t dtrsm_small_XAuB_unitDiag ( double *A, double *B, dim_t M, dim_t N, dim_t lda, dim_t ldb ) { dim_t i, j, k; for(k = 0; k < N; k++) { for(i = 0; i < M; i++) { for(j = k+1; j < N; j++) { B[i+j*ldb] -= B[i+k*ldb] * A[k+j*lda]; } } } return BLIS_SUCCESS; } /* TRSM for the case AX = alpha * B, Double precision * A is lower-triangular, no-transpose, non-unit diagonal * dimensions A: mxm X: mxn B: mxn b01---> * ***************** ** * * * * * * * * * * * * * * *b01* * * * * * * * * * * a10 ****** b11 ***************** | * * * | * * * * * | * * * | * * * * * | *a10*a11* | *b11* * * * v * * * v * * * * * *********** ***************** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * **************** ***************** a11---> */ static err_t bli_dtrsm_small_AlXB( side_t side, obj_t* AlphaObj, obj_t* a, obj_t* b, cntx_t* cntx, cntl_t* cntl ) { dim_t D_MR = 4; //size of block along 'M' dimpension dim_t D_NR = 8; //size of block along 'N' dimension dim_t m = bli_obj_length(b); // number of rows of matrix B dim_t n = bli_obj_width(b); // number of columns of matrix B #ifdef BLIS_ENABLE_SMALL_MATRIX_ROME if((m>D_BLIS_SMALL_MATRIX_THRES_TRSM_ALXB_ROME_ROW_PANEL_M && n>D_BLIS_SMALL_MATRIX_THRES_TRSM_ALXB_ROME) || (m> D_BLIS_SMALL_MATRIX_THRES_TRSM_ALXB_ROME && n>D_BLIS_SMALL_MATRIX_THRES_TRSM_ALXB_ROME_COLUMN_PANEL_N) || (m>D_BLIS_SMALL_MATRIX_THRES_TRSM_ALXB_ROME_COLUMN_PANEL_M && n D_BLIS_SMALL_MATRIX_THRES_TRSM_ALXB_NAPLES) { return BLIS_NOT_YET_IMPLEMENTED; } #endif dim_t m_remainder = m & 3; //number of remainder rows dim_t n_remainder = n & 7; //number of remainder columns dim_t cs_a = bli_obj_col_stride(a); // column stride of A dim_t cs_b = bli_obj_col_stride(b); // column stride of B dim_t i, j, k; //loop variables dim_t k_iter; //number of times GEMM to be performed double AlphaVal = *(double *)AlphaObj->buffer; //value of alpha double *L = a->buffer; //pointer to matrix A double *B = b->buffer; //pointer to matrix B double *a10, *a11, *b01, *b11; //pointers that point to blocks for GEMM and TRSM double *ptr_b01_dup; double f_t[4] __attribute__((aligned(64)));//buffer to store corner column when m_remainder !=0 double* f_temp; double ones = 1.0; //scratch registers __m256d ymm0, ymm1, ymm2, ymm3; __m256d ymm4, ymm5, ymm6, ymm7; __m256d ymm8, ymm9, ymm10, ymm11; __m256d ymm12, ymm13, ymm14, ymm15; __m256d ymm16; for(j = 0; j+D_NR-1 < n; j += D_NR) //loop along 'N' dimension { for(i = 0;i+D_MR-1 < m; i += D_MR) //loop along 'M' dimension { a10 = L +i; //pointer to block of A to be used for GEMM a11 = L + i + (i*cs_a); //pointer to block of A to be used for TRSM b01 = B + j*cs_b; //pointer to block of B to be used for GEMM b11 = B + i + j* cs_b; //pointer to block of B to be used for TRSM k_iter = i / D_MR; //number of times GEMM to be performed(in blocks of 4x4) ymm8 = _mm256_setzero_pd(); ymm9 = _mm256_setzero_pd(); ymm10 = _mm256_setzero_pd(); ymm11 = _mm256_setzero_pd(); ymm12 = _mm256_setzero_pd(); ymm13 = _mm256_setzero_pd(); ymm14 = _mm256_setzero_pd(); ymm15 = _mm256_setzero_pd(); ///GEMM code begins/// for(k = 0; k< k_iter; k++) //loop for number of GEMM operations { ptr_b01_dup = b01; ymm16 = _mm256_loadu_pd((double const *)(a10));//A10[0][0] A10[1][0] A10[2][0] A10[3][0] ymm4 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 0)); //B01[0][0] ymm5 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 1)); //B01[0][1] ymm6 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 2)); //B01[0][2] ymm7 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 3)); //B01[0][3] ymm0 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 4)); //B01[0][4] ymm1 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 5)); //B01[0][5] ymm2 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 6)); //B01[0][6] ymm3 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 7)); //B01[0][7] b01 += 1; //mobe to next row of B ymm8 = _mm256_fmadd_pd(ymm4, ymm16, ymm8); //ymm8 += (B01[0][0]*A10[0][0] B01[0][0]*A10[1][0] B01[0][0]*A10[2][0] B01[0][0]*A10[3][0]) ymm9 = _mm256_fmadd_pd(ymm5, ymm16, ymm9); //ymm9 += (B01[0][1]*A10[0][0] B01[0][1]*A10[1][0] B01[0][1]*A10[2][0] B01[0][1]*A10[3][0]) ymm10 = _mm256_fmadd_pd(ymm6, ymm16, ymm10); //ymm10 += (B01[0][2]*A10[0][0] B01[0][2]*A10[1][0] B01[0][2]*A10[2][0] B01[0][2]*A10[3][0]) ymm11 = _mm256_fmadd_pd(ymm7, ymm16, ymm11); //ymm11 += (B01[0][3]*A10[0][0] B01[0][3]*A10[1][0] B01[0][3]*A10[2][0] B01[0][3]*A10[3][0]) ymm12 = _mm256_fmadd_pd(ymm0, ymm16, ymm12); //ymm12 += (B01[0][4]*A10[0][0] B01[0][4]*A10[1][0] B01[0][4]*A10[2][0] B01[0][4]*A10[3][0]) ymm13 = _mm256_fmadd_pd(ymm1, ymm16, ymm13); //ymm13 += (B01[0][5]*A10[0][0] B01[0][5]*A10[1][0] B01[0][5]*A10[2][0] B01[0][5]*A10[3][0]) ymm14 = _mm256_fmadd_pd(ymm2, ymm16, ymm14); //ymm14 += (B01[0][6]*A10[0][0] B01[0][6]*A10[1][0] B01[0][6]*A10[2][0] B01[0][6]*A10[3][0]) ymm15 = _mm256_fmadd_pd(ymm3, ymm16, ymm15); //ymm15 += (B01[0][7]*A10[0][0] B01[0][7]*A10[1][0] B01[0][7]*A10[2][0] B01[0][7]*A10[3][0]) ymm16 = _mm256_loadu_pd((double const *)(a10 + cs_a));//A10[0][1] A10[1][1] A10[2][1] A10[3][1] ymm4 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 0)); //B01[1][0] ymm5 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 1)); //B01[1][1] ymm6 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 2)); //B01[1][2] ymm7 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 3)); //B01[1][3] ymm0 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 4)); //B01[1][4] ymm1 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 5)); //B01[1][5] ymm2 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 6)); //B01[1][6] ymm3 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 7)); //B01[1][7] b01 += 1; //mobe to next row of B ymm8 = _mm256_fmadd_pd(ymm4, ymm16, ymm8); //ymm8 += (B01[1][0]*A10[0][1] B01[1][0]*A10[1][1] B01[1][0]*A10[2][1] B01[1][0]*A10[3][1]) ymm9 = _mm256_fmadd_pd(ymm5, ymm16, ymm9); //ymm9 += (B01[1][1]*A10[0][1] B01[1][1]*A10[1][1] B01[1][1]*A10[2][1] B01[1][1]*A10[3][1]) ymm10 = _mm256_fmadd_pd(ymm6, ymm16, ymm10); //ymm10 += (B01[1][2]*A10[0][1] B01[1][2]*A10[1][1] B01[1][2]*A10[2][1] B01[1][2]*A10[3][1]) ymm11 = _mm256_fmadd_pd(ymm7, ymm16, ymm11); //ymm11 += (B01[1][3]*A10[0][1] B01[1][3]*A10[1][1] B01[1][3]*A10[2][1] B01[1][3]*A10[3][1]) ymm12 = _mm256_fmadd_pd(ymm0, ymm16, ymm12); //ymm12 += (B01[1][4]*A10[0][1] B01[1][4]*A10[1][1] B01[1][4]*A10[2][1] B01[1][4]*A10[3][1]) ymm13 = _mm256_fmadd_pd(ymm1, ymm16, ymm13); //ymm13 += (B01[1][5]*A10[0][1] B01[1][5]*A10[1][1] B01[1][5]*A10[2][1] B01[1][5]*A10[3][1]) ymm14 = _mm256_fmadd_pd(ymm2, ymm16, ymm14); //ymm14 += (B01[1][6]*A10[0][1] B01[1][6]*A10[1][1] B01[1][6]*A10[2][1] B01[1][6]*A10[3][1]) ymm15 = _mm256_fmadd_pd(ymm3, ymm16, ymm15); //ymm15 += (B01[1][7]*A10[0][1] B01[1][7]*A10[1][1] B01[1][7]*A10[2][1] B01[1][7]*A10[3][1]) ymm16 = _mm256_loadu_pd((double const *)(a10 + cs_a * 2));//A10[0][2] A10[1][2] A10[2][2] A10[3][2] ymm4 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 0)); //B01[2][0] ymm5 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 1)); //B01[2][1] ymm6 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 2)); //B01[2][2] ymm7 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 3)); //B01[2][3] ymm0 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 4)); //B01[2][4] ymm1 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 5)); //B01[2][5] ymm2 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 6)); //B01[2][6] ymm3 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 7)); //B01[2][7] b01 += 1; //mobe to next row of B ymm8 = _mm256_fmadd_pd(ymm4, ymm16, ymm8); //ymm8 += (B01[2][0]*A10[0][2] B01[2][0]*A10[1][2] B01[2][0]*A10[2][2] B01[2][0]*A10[3][2]) ymm9 = _mm256_fmadd_pd(ymm5, ymm16, ymm9); //ymm9 += (B01[2][1]*A10[0][2] B01[2][1]*A10[1][2] B01[2][1]*A10[2][2] B01[2][1]*A10[3][2]) ymm10 = _mm256_fmadd_pd(ymm6, ymm16, ymm10); //ymm10 += (B01[2][2]*A10[0][2] B01[2][2]*A10[1][2] B01[2][2]*A10[2][2] B01[2][2]*A10[3][2]) ymm11 = _mm256_fmadd_pd(ymm7, ymm16, ymm11); //ymm11 += (B01[2][3]*A10[0][2] B01[2][3]*A10[1][2] B01[2][3]*A10[2][2] B01[2][3]*A10[3][2]) ymm12 = _mm256_fmadd_pd(ymm0, ymm16, ymm12); //ymm12 += (B01[2][4]*A10[0][2] B01[2][4]*A10[1][2] B01[2][4]*A10[2][2] B01[2][4]*A10[3][2]) ymm13 = _mm256_fmadd_pd(ymm1, ymm16, ymm13); //ymm13 += (B01[2][5]*A10[0][2] B01[2][5]*A10[1][2] B01[2][5]*A10[2][2] B01[2][5]*A10[3][2]) ymm14 = _mm256_fmadd_pd(ymm2, ymm16, ymm14); //ymm14 += (B01[2][6]*A10[0][2] B01[2][6]*A10[1][2] B01[2][6]*A10[2][2] B01[2][6]*A10[3][2]) ymm15 = _mm256_fmadd_pd(ymm3, ymm16, ymm15); //ymm15 += (B01[2][7]*A10[0][2] B01[2][7]*A10[1][2] B01[2][7]*A10[2][2] B01[2][7]*A10[3][2]) ymm16 = _mm256_loadu_pd((double const *)(a10 + cs_a * 3));//A10[0][3] A10[1][3] A10[2][3] A10[3][3] ymm4 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 0)); //B01[3][0] ymm5 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 1)); //B01[3][1] ymm6 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 2)); //B01[3][2] ymm7 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 3)); //B01[3][3] ymm0 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 4)); //B01[3][4] ymm1 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 5)); //B01[3][5] ymm2 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 6)); //B01[3][6] ymm3 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 7)); //B01[3][7] b01 += 1; //mobe to next row of B ymm8 = _mm256_fmadd_pd(ymm4, ymm16, ymm8); //ymm8 += (B01[3][0]*A10[0][3] B01[3][0]*A10[3][0] B01[3][0]*A10[2][3] B01[3][0]*A10[3][0]) ymm9 = _mm256_fmadd_pd(ymm5, ymm16, ymm9); //ymm9 += (B01[3][1]*A10[0][3] B01[3][1]*A10[3][0] B01[3][1]*A10[2][3] B01[3][1]*A10[3][0]) ymm10 = _mm256_fmadd_pd(ymm6, ymm16, ymm10); //ymm10 += (B01[3][2]*A10[0][3] B01[3][2]*A10[3][0] B01[3][2]*A10[2][3] B01[3][2]*A10[3][0]) ymm11 = _mm256_fmadd_pd(ymm7, ymm16, ymm11); //ymm11 += (B01[3][3]*A10[0][3] B01[3][3]*A10[3][0] B01[3][3]*A10[2][3] B01[3][3]*A10[3][0]) ymm12 = _mm256_fmadd_pd(ymm0, ymm16, ymm12); //ymm12 += (B01[3][4]*A10[0][3] B01[3][4]*A10[3][0] B01[3][4]*A10[2][3] B01[3][4]*A10[3][3]) ymm13 = _mm256_fmadd_pd(ymm1, ymm16, ymm13); //ymm13 += (B01[3][5]*A10[0][3] B01[3][5]*A10[3][0] B01[3][5]*A10[2][3] B01[3][5]*A10[3][3]) ymm14 = _mm256_fmadd_pd(ymm2, ymm16, ymm14); //ymm14 += (B01[3][6]*A10[0][3] B01[3][6]*A10[3][0] B01[3][6]*A10[2][3] B01[3][6]*A10[3][3]) ymm15 = _mm256_fmadd_pd(ymm3, ymm16, ymm15); //ymm15 += (B01[3][7]*A10[0][3] B01[3][7]*A10[3][0] B01[3][7]*A10[2][3] B01[3][7]*A10[3][3]) a10 += D_MR * cs_a; //pointer math to calculate next block of A for GEMM b01 = ptr_b01_dup + D_MR; //pointer math to calculate next block of B for GEMM } ymm16 = _mm256_broadcast_sd((double const *)&AlphaVal); //register to hold alpha ymm0 = _mm256_loadu_pd((double const *)(b11 + cs_b *0)); //B11[0][0] B11[1][0] B11[2][0] B11[3][0] ymm1 = _mm256_loadu_pd((double const *)(b11 + cs_b *1)); //B11[0][1] B11[1][1] B11[2][1] B11[3][1] ymm2 = _mm256_loadu_pd((double const *)(b11 + cs_b *2)); //B11[0][2] B11[1][2] B11[2][2] B11[3][2] ymm3 = _mm256_loadu_pd((double const *)(b11 + cs_b *3)); //B11[0][3] B11[1][3] B11[2][3] B11[3][3] ymm4 = _mm256_loadu_pd((double const *)(b11 + cs_b *4)); //B11[0][4] B11[1][4] B11[2][4] B11[3][4] ymm5 = _mm256_loadu_pd((double const *)(b11 + cs_b *5)); //B11[0][5] B11[1][5] B11[2][5] B11[3][5] ymm6 = _mm256_loadu_pd((double const *)(b11 + cs_b *6)); //B11[0][6] B11[1][6] B11[2][6] B11[3][6] ymm7 = _mm256_loadu_pd((double const *)(b11 + cs_b *7)); //B11[0][7] B11[1][7] B11[2][7] B11[3][7] ymm0 = _mm256_fmsub_pd(ymm0, ymm16, ymm8); //B11[0-3][0] * alpha -= B01[0-3][0] ymm1 = _mm256_fmsub_pd(ymm1, ymm16, ymm9); //B11[0-3][1] * alpha -= B01[0-3][1] ymm2 = _mm256_fmsub_pd(ymm2, ymm16, ymm10); //B11[0-3][2] * alpha -= B01[0-3][2] ymm3 = _mm256_fmsub_pd(ymm3, ymm16, ymm11); //B11[0-3][3] * alpha -= B01[0-3][3] ymm4 = _mm256_fmsub_pd(ymm4, ymm16, ymm12); //B11[0-3][4] * alpha -= B01[0-3][4] ymm5 = _mm256_fmsub_pd(ymm5, ymm16, ymm13); //B11[0-3][5] * alpha -= B01[0-3][5] ymm6 = _mm256_fmsub_pd(ymm6, ymm16, ymm14); //B11[0-3][6] * alpha -= B01[0-3][6] ymm7 = _mm256_fmsub_pd(ymm7, ymm16, ymm15); //B11[0-3][7] * alpha -= B01[0-3][7] ///implement TRSM/// ///transpose of B11// ///unpacklow/// ymm9 = _mm256_unpacklo_pd(ymm0, ymm1); //B11[0][0] B11[0][1] B11[2][0] B11[2][1] ymm11 = _mm256_unpacklo_pd(ymm2, ymm3); //B11[0][2] B11[0][3] B11[2][2] B11[2][3] ymm13 = _mm256_unpacklo_pd(ymm4, ymm5); //B11[0][4] B11[0][5] B11[2][4] B11[2][5] ymm15 = _mm256_unpacklo_pd(ymm6, ymm7); //B11[0][6] B11[0][7] B11[2][6] B11[2][7] //rearrange low elements ymm8 = _mm256_permute2f128_pd(ymm9,ymm11,0x20); //B11[0][0] B11[0][1] B11[0][2] B11[0][3] ymm10 = _mm256_permute2f128_pd(ymm9,ymm11,0x31); //B11[2][0] B11[2][1] B11[2][2] B11[2][3] ymm12 = _mm256_permute2f128_pd(ymm13,ymm15,0x20); //B11[4][0] B11[4][1] B11[4][2] B11[4][3] ymm14 = _mm256_permute2f128_pd(ymm13,ymm15,0x31); //B11[6][0] B11[6][1] B11[6][2] B11[6][3] ////unpackhigh//// ymm0 = _mm256_unpackhi_pd(ymm0, ymm1); //B11[1][0] B11[1][1] B11[3][0] B11[3][1] ymm1 = _mm256_unpackhi_pd(ymm2, ymm3); //B11[1][2] B11[1][3] B11[3][2] B11[3][3] ymm4 = _mm256_unpackhi_pd(ymm4, ymm5); //B11[1][4] B11[1][5] B11[3][4] B11[3][5] ymm5 = _mm256_unpackhi_pd(ymm6, ymm7); //B11[1][6] B11[1][7] B11[3][6] B11[3][7] //rearrange high elements ymm9 = _mm256_permute2f128_pd(ymm0,ymm1,0x20); //B11[1][0] B11[1][1] B11[1][2] B11[1][3] ymm11 = _mm256_permute2f128_pd(ymm0,ymm1,0x31); //B11[3][0] B11[3][1] B11[3][2] B11[3][3] ymm13 = _mm256_permute2f128_pd(ymm4,ymm5,0x20); //B11[5][0] B11[5][1] B11[5][2] B11[5][3] ymm15 = _mm256_permute2f128_pd(ymm4,ymm5,0x31); //B11[7][0] B11[7][1] B11[7][2] B11[7][3] ymm0 = _mm256_broadcast_sd((double const *)&ones); //broadcast diagonal elements of A11 ymm1 = _mm256_broadcast_sd((double const *)(a11+0)); //A11[0][0] ymm2 = _mm256_broadcast_sd((double const *)(a11+ cs_a +1)); //A11[1][1] ymm3 = _mm256_broadcast_sd((double const *)(a11+cs_a*2 + 2)); //A11[2][2] ymm4 = _mm256_broadcast_sd((double const *)(a11+cs_a*3 + 3)); //A11[3][3] ymm5 = _mm256_unpacklo_pd(ymm1, ymm2); //A11[0][0] A11[0][0] A11[1][1] A11[1][1] ymm6 = _mm256_unpacklo_pd(ymm3, ymm4); //A11[2][2] A11[2][2] A11[3][3] A11[3][3] ymm5 = _mm256_blend_pd(ymm5, ymm6, 0x0C); //A11[0][0] A11[1][1] A11[2][2] A11[3][3] ymm0 = _mm256_div_pd(ymm0, ymm5); //1/A11[0][0] 1/A11[1][1] 1/A11[2][2] 1/A11[2][2] //extract a00 ymm1 = _mm256_permute_pd(ymm0, 0x00); //1/A11[0][0] 1/A11[0][0] 1/A11[2][2] 1/A11[2][2] ymm1 = _mm256_permute2f128_pd(ymm1, ymm1, 0x00); //1/A11[0][0] 1/A11[0][0] 1/A11[0][0] 1/A11[0][0] //(Row 0): perform mul operation of reciprocal of L(0,0) element with 1st row elements of B ymm8 = _mm256_mul_pd(ymm8, ymm1); //B11[0-3][0] /= A11[0][0] ymm12 = _mm256_mul_pd(ymm12, ymm1); //B11[0-3][4] /= A11[0][0] //extract a11 ymm1 = _mm256_permute_pd(ymm0, 0x03); //1/A11[1][1] 1/A11[1][1] 1/A11[3][3] 1/A11[3][3] ymm1 = _mm256_permute2f128_pd(ymm1, ymm1, 0x00); //1/A11[1][1] 1/A11[1][1] 1/A11[1][1] 1/A11[1][1] ymm2 = _mm256_broadcast_sd((double const *)(a11 +1)); //A11[1][0] ymm3 = _mm256_broadcast_sd((double const *)(a11 +2)); //A11[2][0] ymm4 = _mm256_broadcast_sd((double const *)(a11 +3)); //A11[3][0] a11 += cs_a; //(Row1): FMA operations ymm9 = _mm256_fnmadd_pd(ymm2, ymm8, ymm9); //B11[1][0-3] -= A11[1][0] * B11[0-3][0] ymm10 = _mm256_fnmadd_pd(ymm3, ymm8, ymm10); //B11[2][0-3] -= A11[2][0] * B11[0-3][0] ymm11 = _mm256_fnmadd_pd(ymm4, ymm8, ymm11); //B11[3][0-3] -= A11[3][0] * B11[0-3][0] ymm13 = _mm256_fnmadd_pd(ymm2, ymm12, ymm13); //B11[5][0-3] -= A11[1][0] * B11[0-3][4] ymm14 = _mm256_fnmadd_pd(ymm3, ymm12, ymm14); //B11[6][0-3] -= A11[2][0] * B11[0-3][4] ymm15 = _mm256_fnmadd_pd(ymm4, ymm12, ymm15); //B11[7][0-3] -= A11[3][0] * B11[0-3][4] ymm9 = _mm256_mul_pd(ymm9, ymm1); //B11[0-3][1] /= A11[1][1] ymm13 = _mm256_mul_pd(ymm13, ymm1); //B11[0-3][5] /= A11[1][1] ymm3 = _mm256_broadcast_sd((double const *)(a11 +2)); //A11[2][1] ymm4 = _mm256_broadcast_sd((double const *)(a11 +3)); //A11[3][1] a11 += cs_a; //extract a22 ymm1 = _mm256_permute_pd(ymm0, 0x00); //1/A11[0][0] 1/A110[][0] 1/A11[2][2] 1/A11[2][2] ymm1 = _mm256_permute2f128_pd(ymm1, ymm1, 0x11); //1/A11[2][2] 1/A11[2][2] 1/A11[2][2] 1/A11[2][2] //(ROw2): FMA operations ymm10 = _mm256_fnmadd_pd(ymm3, ymm9, ymm10); //B11[2][0-3] -= A11[2][1] * B11[0-3][1] ymm11 = _mm256_fnmadd_pd(ymm4, ymm9, ymm11); //B11[3][0-3] -= A11[3][1] * B11[0-3][1] ymm14 = _mm256_fnmadd_pd(ymm3, ymm13, ymm14); //B11[6][0-3] -= A11[2][1] * B11[0-3][5] ymm15 = _mm256_fnmadd_pd(ymm4, ymm13, ymm15); //B11[7][0-3] -= A11[3][1] * B11[0-3][5] //perform mul operation ymm10 = _mm256_mul_pd(ymm10, ymm1); //B11[0-3][2] /= A11[2][2] ymm14 = _mm256_mul_pd(ymm14, ymm1); //B11[0-3][6] /= A11[2][2] ymm4 = _mm256_broadcast_sd((double const *)(a11 +3)); //A11[3][2] a11 += cs_a; //extract a33 ymm1 = _mm256_permute_pd(ymm0, 0x0C); //1/A11[0][0] 1/A11[0][0] 1/A11[3][3] 1/A11[3][3] ymm1 = _mm256_permute2f128_pd(ymm1, ymm1, 0x11);//1/A11[3][3] 1/A11[3][3] 1/A11[3][3] 1/A11[3][3] //(ROw2): FMA operations ymm11 = _mm256_fnmadd_pd(ymm4, ymm10, ymm11); //B11[3][0-3] -= A11[3][2] * B11[0-3][2] ymm15 = _mm256_fnmadd_pd(ymm4, ymm14, ymm15); //B11[7][0-3] -= A11[3][2] * B11[0-3][6] //perform mul operation ymm11 = _mm256_mul_pd(ymm11, ymm1); //B11[0-3][3] /= A11[3][3] ymm15 = _mm256_mul_pd(ymm15, ymm1); //B11[0-3][7] /= A11[3][3] //unpacklow// ymm1 = _mm256_unpacklo_pd(ymm8, ymm9); //B11[0][0] B11[1][0] B11[0][2] B11[1][2] ymm3 = _mm256_unpacklo_pd(ymm10, ymm11); //B11[2][0] B11[3][0] B11[2][2] B11[3][2] ymm5 = _mm256_unpacklo_pd(ymm12, ymm13); //B11[4][0] B11[5][0] B11[4][2] B11[5][2] ymm7 = _mm256_unpacklo_pd(ymm14, ymm15); //B11[6][0] B11[7][0] B11[6][2] B11[7][2] //rearrange low elements ymm0 = _mm256_permute2f128_pd(ymm1, ymm3, 0x20); //B11[0][0] B11[1][0] B11[2][0] B11[3][0] ymm2 = _mm256_permute2f128_pd(ymm1, ymm3, 0x31); //B11[0][2] B11[1][2] B11[2][2] B11[3][2] ymm4 = _mm256_permute2f128_pd(ymm5, ymm7, 0x20); //B11[4][0] B11[5][0] B11[6][0] B11[7][0] ymm6 = _mm256_permute2f128_pd(ymm5, ymm7, 0x31); //B11[4][2] B11[5][2] B11[6][2] B11[7][2] ///unpack high/// ymm8 = _mm256_unpackhi_pd(ymm8, ymm9); //B11[0][1] B11[1][1] B11[0][3] B11[1][3] ymm9 = _mm256_unpackhi_pd(ymm10, ymm11); //B11[2][1] B11[3][1] B11[2][3] B11[3][3] ymm12 = _mm256_unpackhi_pd(ymm12, ymm13); //B11[4][1] B11[5][1] B11[4][3] B11[5][3] ymm13 = _mm256_unpackhi_pd(ymm14, ymm15); //B11[6][1] B11[7][1] B11[6][3] B11[7][3] //rearrange high elements ymm1 = _mm256_permute2f128_pd(ymm8, ymm9, 0x20); //B11[0][1] B11[1][1] B11[2][1] B11[3][1] ymm3 = _mm256_permute2f128_pd(ymm8, ymm9, 0x31); //B11[0][3] B11[1][3] B11[2][3] B11[3][3] ymm5 = _mm256_permute2f128_pd(ymm12, ymm13, 0x20); //B11[4][1] B11[5][1] B11[6][1] B11[7][1] ymm7 = _mm256_permute2f128_pd(ymm12, ymm13, 0x31); //B11[4][3] B11[5][3] B11[6][3] B11[7][3] _mm256_storeu_pd((double *)(b11 + cs_b * 0), ymm0); //store B11[0][0-3] _mm256_storeu_pd((double *)(b11 + cs_b * 1), ymm1); //store B11[1][0-3] _mm256_storeu_pd((double *)(b11 + cs_b * 2), ymm2); //store B11[2][0-3] _mm256_storeu_pd((double *)(b11 + cs_b * 3), ymm3); //store B11[3][0-3] _mm256_storeu_pd((double *)(b11 + cs_b * 4), ymm4); //store B11[4][0-3] _mm256_storeu_pd((double *)(b11 + cs_b * 5), ymm5); //store B11[5][0-3] _mm256_storeu_pd((double *)(b11 + cs_b * 6), ymm6); //store B11[6][0-3] _mm256_storeu_pd((double *)(b11 + cs_b * 7), ymm7); //store B11[7][0-3] } if(m_remainder) //implementation for reamainder rows(when 'M' is not a multiple of D_MR) { a10 = L +i; //pointer to block of A to be used for GEMM a11 = L + i + (i*cs_a); //pointer to block of A to be used for TRSM b01 = B + j*cs_b; //pointer to block of B to be used for GEMM b11 = B + i + j* cs_b; //pointer to block of B to be used for TRSM k_iter = i / D_MR; //number of times GEMM operation to be done(in blocks of 4x4) int iter; if((j+D_NR) == n) { for(iter = 0; iter < m_remainder; iter++) f_t[iter] = (b11 + cs_b * 7)[iter]; f_temp = f_t; } else f_temp = (b11 + cs_b * 7); ymm8 = _mm256_setzero_pd(); ymm9 = _mm256_setzero_pd(); ymm10 = _mm256_setzero_pd(); ymm11 = _mm256_setzero_pd(); ymm12 = _mm256_setzero_pd(); ymm13 = _mm256_setzero_pd(); ymm14 = _mm256_setzero_pd(); ymm15 = _mm256_setzero_pd(); ///GEMM code Begins/// for(k = 0; k< k_iter; k++) //loop for number of GEMM operations { ptr_b01_dup = b01; ymm16 = _mm256_loadu_pd((double const *)(a10)); //A10[0][0] A10[1][0] A10[2][0] A10[3][0] ymm4 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 0)); //B01[0][0] ymm5 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 1)); //B01[0][1] ymm6 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 2)); //B01[0][2] ymm7 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 3)); //B01[0][3] ymm0 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 4)); //B01[0][4] ymm1 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 5)); //B01[0][5] ymm2 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 6)); //B01[0][6] ymm3 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 7)); //B01[0][7] b01 += 1; //move to next row of B ymm8 = _mm256_fmadd_pd(ymm4, ymm16, ymm8); //ymm8 += (B01[0][0]*A10[0][0] B01[0][0]*A10[1][0] B01[0][0]*A10[2][0] B01[0][0]*A10[3][0] ) ymm9 = _mm256_fmadd_pd(ymm5, ymm16, ymm9); //ymm9 += (B01[0][1]*A10[0][0] B01[0][1]*A10[1][0] B01[0][1]*A10[2][0] B01[0][1]*A10[3][0]) ymm10 = _mm256_fmadd_pd(ymm6, ymm16, ymm10); //ymm10 += (B01[0][2]*A10[0][0] B01[0][2]*A10[1][0] B01[0][2]*A10[2][0] B01[0][2]*A10[3][0]) ymm11 = _mm256_fmadd_pd(ymm7, ymm16, ymm11); //ymm11 += (B01[0][3]*A10[0][0] B01[0][3]*A10[1][0] B01[0][3]*A10[2][0] B01[0][3]*A10[3][0]) ymm12 = _mm256_fmadd_pd(ymm0, ymm16, ymm12); //ymm12 += (B01[0][4]*A10[0][0] B01[0][4]*A10[1][0] B01[0][4]*A10[2][0] B01[0][4]*A10[3][0]) ymm13 = _mm256_fmadd_pd(ymm1, ymm16, ymm13); //ymm13 += (B01[0][5]*A10[0][0] B01[0][5]*A10[1][0] B01[0][5]*A10[2][0] B01[0][5]*A10[3][0]) ymm14 = _mm256_fmadd_pd(ymm2, ymm16, ymm14); //ymm14 += (B01[0][6]*A10[0][0] B01[0][6]*A10[1][0] B01[0][6]*A10[2][0] B01[0][6]*A10[3][0]) ymm15 = _mm256_fmadd_pd(ymm3, ymm16, ymm15); //ymm16 += (B01[0][7]*A10[0][0] B01[0][7]*A10[1][0] B01[0][7]*A10[2][0] B01[0][7]*A10[3][0]) ymm16 = _mm256_loadu_pd((double const *)(a10 + cs_a * 1)); //A10[0][1] A10[1][1] A10[2][1] A10[3][1] ymm4 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 0)); //B01[1][0] ymm5 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 1)); //B01[1][1] ymm6 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 2)); //B01[1][2] ymm7 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 3)); //B01[1][3] ymm0 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 4)); //B01[1][4] ymm1 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 5)); //B01[1][5] ymm2 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 6)); //B01[1][6] ymm3 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 7)); //B01[1][7] b01 += 1; //move to next row of B01 ymm8 = _mm256_fmadd_pd(ymm4, ymm16, ymm8); //ymm8 += (B01[1][0]*A10[0][1] B01[1][0]*A10[1][1] B01[1][0]*A10[2][1] B01[1][0]*A10[3][1]) ymm9 = _mm256_fmadd_pd(ymm5, ymm16, ymm9); //ymm9 += (B01[1][1]*A10[0][1] B01[1][1]*A10[1][1] B01[1][1]*A10[2][1] B01[1][1]*A10[3][1]) ymm10 = _mm256_fmadd_pd(ymm6, ymm16, ymm10); //ymm10 += (B01[1][2]*A10[0][1] B01[1][2]*A10[1][1] B01[1][2]*A10[2][1] B01[1][2]*A10[3][1]) ymm11 = _mm256_fmadd_pd(ymm7, ymm16, ymm11); //ymm11 += (B01[1][3]*A10[0][1] B01[1][3]*A10[1][1] B01[1][3]*A10[2][1] B01[1][3]*A10[3][1]) ymm12 = _mm256_fmadd_pd(ymm0, ymm16, ymm12); //ymm12 += (B01[1][4]*A10[0][1] B01[1][4]*A10[1][1] B01[1][4]*A10[2][1] B01[1][4]*A10[3][1]) ymm13 = _mm256_fmadd_pd(ymm1, ymm16, ymm13); //ymm13 += (B01[1][5]*A10[0][1] B01[1][5]*A10[1][1] B01[1][5]*A10[2][1] B01[1][5]*A10[3][1]) ymm14 = _mm256_fmadd_pd(ymm2, ymm16, ymm14); //ymm14 += (B01[1][6]*A10[0][1] B01[1][6]*A10[1][1] B01[1][6]*A10[2][1] B01[1][6]*A10[3][1]) ymm15 = _mm256_fmadd_pd(ymm3, ymm16, ymm15); //ymm15 += (B01[1][7]*A10[0][1] B01[1][7]*A10[1][1] B01[1][7]*A10[2][1] B01[1][7]*A10[3][1]) ymm16 = _mm256_loadu_pd((double const *)(a10 + cs_a * 2)); //A10[0][2] //A10[1][2] A10[2][2] A10[3][2] ymm4 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 0)); //B01[2][0] ymm5 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 1)); //B01[2][1] ymm6 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 2)); //B01[2][2] ymm7 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 3)); //B01[2][3] ymm0 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 4)); //B01[2][4] ymm1 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 5)); //B01[2][5] ymm2 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 6)); //B01[2][6] ymm3 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 7)); //B01[2][7] b01 += 1; //move to next row of B ymm8 = _mm256_fmadd_pd(ymm4, ymm16, ymm8); //ymm8 += (B01[2][0]*A10[0][2] B01[2][0]*A10[1][2] B01[2][0]*A10[2][2] B01[2][0]*A10[3][2]) ymm9 = _mm256_fmadd_pd(ymm5, ymm16, ymm9); //ymm9 += (B01[2][1]*A10[0][2] B01[2][1]*A10[1][2] B01[2][1]*A10[2][2] B01[2][1]*A10[3][2]) ymm10 = _mm256_fmadd_pd(ymm6, ymm16, ymm10); //ymm10 += (B01[2][2]*A10[0][2] B01[2][2]*A10[1][2] B01[2][2]*A10[2][2] B01[2][2]*A10[3][2]) ymm11 = _mm256_fmadd_pd(ymm7, ymm16, ymm11); //ymm11 += (B01[2][3]*A10[0][2] B01[2][3]*A10[1][2] B01[2][3]*A10[2][2] B01[2][3]*A10[3][2]) ymm12 = _mm256_fmadd_pd(ymm0, ymm16, ymm12); //ymm12 += (B01[2][4]*A10[0][2] B01[2][4]*A10[1][2] B01[2][4]*A10[2][2] B01[2][0]*A10[3][2]) ymm13 = _mm256_fmadd_pd(ymm1, ymm16, ymm13); //ymm13 += (B01[2][5]*A10[0][2] B01[2][5]*A10[1][2] B01[2][5]*A10[2][2] B01[2][1]*A10[3][2]) ymm14 = _mm256_fmadd_pd(ymm2, ymm16, ymm14); //ymm14 += (B01[2][6]*A10[0][2] B01[2][6]*A10[1][2] B01[2][6]*A10[2][2] B01[2][2]*A10[3][2]) ymm15 = _mm256_fmadd_pd(ymm3, ymm16, ymm15); //ymm15 += (B01[2][7]*A10[0][2] B01[2][7]*A10[1][2] B01[2][7]*A10[2][2] B01[2][3]*A10[3][2]) ymm16 = _mm256_loadu_pd((double const *)(a10 + cs_a * 3)); //A10[0][3] A10[1][3] A10[2][3] A10[3][3] ymm4 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 0)); //B01[3][0] ymm5 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 1)); //B01[3][1] ymm6 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 2)); //B01[3][2] ymm7 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 3)); //B01[3][3] ymm0 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 4)); //B01[3][4] ymm1 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 5)); //B01[3][5] ymm2 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 6)); //B01[3][6] ymm3 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 7)); //B01[3][7] b01 += 1; //move to next row of B ymm8 = _mm256_fmadd_pd(ymm4, ymm16, ymm8); //ymm8 += (B01[3][0]*A10[0][3] B01[3][0]*A10[1][3] B01[3][0]*A10[2][3] B01[3][0]*A10[3][3]) ymm9 = _mm256_fmadd_pd(ymm5, ymm16, ymm9); //ymm8 += (B01[3][1]*A10[0][3] B01[3][1]*A10[1][3] B01[3][1]*A10[2][3] B01[3][1]*A10[3][3]) ymm10 = _mm256_fmadd_pd(ymm6, ymm16, ymm10); //ymm8 += (B01[3][2]*A10[0][3] B01[3][2]*A10[1][3] B01[3][2]*A10[2][3] B01[3][2]*A10[3][3]) ymm11 = _mm256_fmadd_pd(ymm7, ymm16, ymm11); //ymm8 += (B01[3][3]*A10[0][3] B01[3][3]*A10[1][3] B01[3][3]*A10[2][3] B01[3][3]*A10[3][3]) ymm12 = _mm256_fmadd_pd(ymm0, ymm16, ymm12); //ymm8 += (B01[3][0]*A10[0][3] B01[3][4]*A10[1][3] B01[3][4]*A10[2][3] B01[3][4]*A10[3][3]) ymm13 = _mm256_fmadd_pd(ymm1, ymm16, ymm13); //ymm8 += (B01[3][1]*A10[0][3] B01[3][5]*A10[1][3] B01[3][5]*A10[2][3] B01[3][5]*A10[3][3]) ymm14 = _mm256_fmadd_pd(ymm2, ymm16, ymm14); //ymm8 += (B01[3][2]*A10[0][3] B01[3][6]*A10[1][3] B01[3][6]*A10[2][3] B01[3][6]*A10[3][3]) ymm15 = _mm256_fmadd_pd(ymm3, ymm16, ymm15); //ymm8 += (B01[3][3]*A10[0][3] B01[3][7]*A10[1][3] B01[3][7]*A10[2][3] B01[3][7]*A10[3][3]) a10 += D_MR * cs_a; //pointer math to find next block of A for GEMM b01 = ptr_b01_dup + D_MR; //pointer math to find next block of B for GEMM } ///GEMM code ends/// ymm16 = _mm256_broadcast_sd((double const *)&AlphaVal); //register to store alpha value ymm0 = _mm256_loadu_pd((double const *)(b11 + cs_b *0)); //B11[0][0] B11[1][0] B11[2][0] B11[3][0] ymm1 = _mm256_loadu_pd((double const *)(b11 + cs_b *1)); //B11[0][1] B11[1][1] B11[2][1] B11[3][1] ymm2 = _mm256_loadu_pd((double const *)(b11 + cs_b *2)); //B11[0][2] B11[1][2] B11[2][2] B11[3][2] ymm3 = _mm256_loadu_pd((double const *)(b11 + cs_b *3)); //B11[0][3] B11[1][3] B11[2][3] B11[3][3] ymm4 = _mm256_loadu_pd((double const *)(b11 + cs_b *4)); //B11[0][4] B11[1][4] B11[2][4] B11[3][4] ymm5 = _mm256_loadu_pd((double const *)(b11 + cs_b *5)); //B11[0][5] B11[1][5] B11[2][5] B11[3][5] ymm6 = _mm256_loadu_pd((double const *)(b11 + cs_b *6)); //B11[0][6] B11[1][6] B11[2][6] B11[3][6] ymm7 = _mm256_loadu_pd((double const *)(f_temp)); //B11[0][7] B11[1][7] B11[2][7] B11[3][7] ymm0 = _mm256_fmsub_pd(ymm0, ymm16, ymm8); //B11[0-3][0] *alpha -= B01[0-3][0] ymm1 = _mm256_fmsub_pd(ymm1, ymm16, ymm9); //B11[0-3][1] *alpha -= B01[0-3][1] ymm2 = _mm256_fmsub_pd(ymm2, ymm16, ymm10); //B11[0-3][2] *alpha -= B01[0-3][2] ymm3 = _mm256_fmsub_pd(ymm3, ymm16, ymm11); //B11[0-3][3] *alpha -= B01[0-3][3] ymm4 = _mm256_fmsub_pd(ymm4, ymm16, ymm12); //B11[0-3][4] *alpha -= B01[0-3][4] ymm5 = _mm256_fmsub_pd(ymm5, ymm16, ymm13); //B11[0-3][5] *alpha -= B01[0-3][5] ymm6 = _mm256_fmsub_pd(ymm6, ymm16, ymm14); //B11[0-3][6] *alpha -= B01[0-3][6] ymm7 = _mm256_fmsub_pd(ymm7, ymm16, ymm15); //B11[0-3][7] *alpha -= B01[0-3][7] if(3 == m_remainder) { ///implement TRSM/// ///unpacklow/// ymm9 = _mm256_unpacklo_pd(ymm0, ymm1); //B11[0][0] B11[0][1] B11[2][0] B11[2][1] ymm11 = _mm256_unpacklo_pd(ymm2, ymm3); //B11[0][2] B11[0][3] B11[2][2] B11[2][3] ymm13 = _mm256_unpacklo_pd(ymm4, ymm5); //B11[0][4] B11[0][5] B11[1][4] B11[1][5] ymm15 = _mm256_unpacklo_pd(ymm6, ymm7); //B11[0][6] B11[0][7] B11[1][6] B11[1][7] //rearrange low elements ymm8 = _mm256_permute2f128_pd(ymm9,ymm11,0x20); //B11[0][0] B11[0][1] B11[0][2] B11[0][3] ymm10 = _mm256_permute2f128_pd(ymm9,ymm11,0x31); //B11[2][0] B11[2][1] B11[2][2] B11[2][3] ymm12 = _mm256_permute2f128_pd(ymm13,ymm15,0x20); //B11[4][0] B11[4][1] B11[4][2] B11[4][3] ymm14 = _mm256_permute2f128_pd(ymm13,ymm15,0x31); //B11[6][0] B11[6][1] B11[6][2] B11[6][3] ////unpackhigh//// ymm0 = _mm256_unpackhi_pd(ymm0, ymm1); //B11[1][0] B11[1][1] B11[3][0] B11[3][1] ymm1 = _mm256_unpackhi_pd(ymm2, ymm3); //B11[1][2] B11[1][3] B11[3][2] B11[3][3] ymm4 = _mm256_unpackhi_pd(ymm4, ymm5); //B11[5][0] B11[5][1] B11[7][0] B11[7][1] ymm5 = _mm256_unpackhi_pd(ymm6, ymm7); //B11[5][2] B11[5][3] B11[7][2] B11[7][3] //rearrange high elements ymm9 = _mm256_permute2f128_pd(ymm0,ymm1,0x20); //B11[1][0] B11[1][1] B11[1][2] B11[1][3] ymm11 = _mm256_permute2f128_pd(ymm0,ymm1,0x31); //B11[3][0] B11[3][1] B11[3][2] B11[3][3] ymm13 = _mm256_permute2f128_pd(ymm4,ymm5,0x20); //B11[5][0] B11[5][1] B11[5][2] B11[5][3] ymm15 = _mm256_permute2f128_pd(ymm4,ymm5,0x31); //B11[7][0] B11[7][1] B11[7][2] B11[7][3] ymm0 = _mm256_broadcast_sd((double const *)&ones); //broadcast diagonal elements of A11 ymm1 = _mm256_broadcast_sd((double const *)(a11+0)); //A11[0][0] ymm2 = _mm256_broadcast_sd((double const *)(a11+ cs_a +1)); //A11[1][1] ymm3 = _mm256_broadcast_sd((double const *)(a11+cs_a*2 + 2)); //A11[2][2] ymm5 = _mm256_unpacklo_pd(ymm1, ymm2); //A11[0][0] A11[0][0] A11[1][1] A11[1][1] ymm6 = _mm256_unpacklo_pd(ymm3, ymm0); //A11[2][2] A11[2][2] A11[3][3] A11[3][3] ymm5 = _mm256_blend_pd(ymm5, ymm6, 0x0C); //A11[0][0] A11[1][1] A11[2][2] A11[3][3] ymm0 = _mm256_div_pd(ymm0, ymm5); //1/A11[0][0] 1/A11[1][1] 1/A11[2][2] 1/A11[3][3] //extract a00 ymm1 = _mm256_permute_pd(ymm0, 0x00); //1/A11[0][0] 1/A11[0][0] 1/A11[2][2] 1/A11[2][2] ymm1 = _mm256_permute2f128_pd(ymm1, ymm1, 0x00); //1/A11[0][0] 1/A11[0][0] 1/A11[0][0] 1/A11[0][0] //(Row 0): perform mul operation of reciprocal of L(0,0) element with 1st row elements of B ymm8 = _mm256_mul_pd(ymm8, ymm1); //B11[0-3][0] /= A11[0][0] ymm12 = _mm256_mul_pd(ymm12, ymm1); //B11[0-3][4] /= A11[0][0] //extract a11 ymm1 = _mm256_permute_pd(ymm0, 0x03); //1/A11[1][1] 1/A11[1][1] 1/A11[3][3] 1/A11[3][3] ymm1 = _mm256_permute2f128_pd(ymm1, ymm1, 0x00); //1/A11[1][1] 1/A11[1][1] 1/A11[1][1] 1/A11[1][1] ymm2 = _mm256_broadcast_sd((double const *)(a11 +1)); //A11[1][0] ymm3 = _mm256_broadcast_sd((double const *)(a11 +2)); //A11[2][0] a11 += cs_a; //(Row1): FMA operations ymm9 = _mm256_fnmadd_pd(ymm2, ymm8, ymm9); //B11[1][0-3] -= B11[0-3][0]*A11[1][0] ymm10 = _mm256_fnmadd_pd(ymm3, ymm8, ymm10); //B11[2][0-3] -= B11[0-3][0]*A11[2][0] ymm13 = _mm256_fnmadd_pd(ymm2, ymm12, ymm13); //B11[5][0-3] -= B11[0-3][4]*A11[1][4] ymm14 = _mm256_fnmadd_pd(ymm3, ymm12, ymm14); //B11[6][0-3] -= B11[0-3][4]*A11[2][4] ymm9 = _mm256_mul_pd(ymm9, ymm1); //B11[0-3][1] /= A11[1][1] ymm13 = _mm256_mul_pd(ymm13, ymm1); //B11[0-3][5] /= A11[1][1] ymm3 = _mm256_broadcast_sd((double const *)(a11 +2)); //A11[2][1] a11 += cs_a; //extract a22 ymm1 = _mm256_permute_pd(ymm0, 0x00); //1/A11[0][0] 1/A11[0][0] 1/A11[2][2] 1/A11[2][2] ymm1 = _mm256_permute2f128_pd(ymm1, ymm1, 0x11); //1/A11[2][2] 1/A11[2][2] 1/A11[2][2] 1/A11[2][2] //(ROw2): FMA operations ymm10 = _mm256_fnmadd_pd(ymm3, ymm9, ymm10); //B11[2][0-3] -= A11[2][1] * B11[0-3][1] ymm14 = _mm256_fnmadd_pd(ymm3, ymm13, ymm14); //B11[6][0-3] -= A11[2][1] * B11[0-3][5] //perform mul operation ymm10 = _mm256_mul_pd(ymm10, ymm1); //B11[0-3][2] /=A11[2][2] ymm14 = _mm256_mul_pd(ymm14, ymm1); //B11[0-3][6] /= A11[2][2] ymm11 = _mm256_broadcast_sd((double const *)(&ones)); ymm15 = _mm256_broadcast_sd((double const *)(&ones)); //unpacklow// ymm1 = _mm256_unpacklo_pd(ymm8, ymm9); //B11[0][0] B11[1][0] B11[0][2] B11[1][2] ymm3 = _mm256_unpacklo_pd(ymm10, ymm11); //B11[2][0] B11[3][0] B11[2][2] B11[3][2] ymm5 = _mm256_unpacklo_pd(ymm12, ymm13); //B11[4][0] B11[5][0] B11[4][2] B11[5][2] ymm7 = _mm256_unpacklo_pd(ymm14, ymm15); //B11[6][0] B11[7][0] B11[6][2] B11[7][2] //rearrange low elements ymm0 = _mm256_permute2f128_pd(ymm1, ymm3, 0x20); //B11[0][0] B11[1][0] B11[2][0] B11[3][0] ymm2 = _mm256_permute2f128_pd(ymm1, ymm3, 0x31); //B11[0][2] B11[1][2] B11[2][2] B11[3][2] ymm4 = _mm256_permute2f128_pd(ymm5, ymm7, 0x20); //B11[0][4] B11[1][4] B11[2][4] B11[3][4] ymm6 = _mm256_permute2f128_pd(ymm5, ymm7, 0x31); //B11[0][6] B11[1][6] B11[2][6] B11[3][6] ///unpack high/// ymm8 = _mm256_unpackhi_pd(ymm8, ymm9); //B11[0][1] B11[1][1] B11[0][3] B11[1][3] ymm9 = _mm256_unpackhi_pd(ymm10, ymm11); //B11[2][1] B11[3][1] B11[2][3] B11[3][3] ymm12 = _mm256_unpackhi_pd(ymm12, ymm13); //B11[0][5] B11[1][5] B11[0][7] B11[1][7] ymm13 = _mm256_unpackhi_pd(ymm14, ymm15); //B11[2][5] B11[3][5] B11[2][7] B11[3][7] //rearrange high elements ymm1 = _mm256_permute2f128_pd(ymm8, ymm9, 0x20); //B11[0][1] B11[1][1] B11[2][1] B11[3][1] ymm3 = _mm256_permute2f128_pd(ymm8, ymm9, 0x31); //B11[0][3] B11[1][3] B11[2][3] B11[3][3] ymm5 = _mm256_permute2f128_pd(ymm12, ymm13, 0x20); //B11[0][5] B11[1][5] B11[2][5] B11[3][5] ymm7 = _mm256_permute2f128_pd(ymm12, ymm13, 0x31); //B11[0][7] B11[1][7] B11[2][7] B11[3][7] ymm8 = _mm256_loadu_pd((double const *)(b11 + cs_b * 0)); //load B11[0-3][0] ymm9 = _mm256_loadu_pd((double const *)(b11 + cs_b * 1)); //load B11[0-3][1] ymm10 = _mm256_loadu_pd((double const *)(b11 + cs_b * 2)); //load B11[0-3][2] ymm11 = _mm256_loadu_pd((double const *)(b11 + cs_b * 3)); //load B11[0-3][3] ymm12 = _mm256_loadu_pd((double const *)(b11 + cs_b * 4)); //load B11[0-3][4] ymm13 = _mm256_loadu_pd((double const *)(b11 + cs_b * 5)); //load B11[0-3][5] ymm14 = _mm256_loadu_pd((double const *)(b11 + cs_b * 6)); //load B11[0-3][6] ymm15 = _mm256_loadu_pd((double const *)(f_temp)); //load B11[0-3][7] //determine correct values to store ymm0 = _mm256_blend_pd(ymm0, ymm8, 0x08); ymm1 = _mm256_blend_pd(ymm1, ymm9, 0x08); ymm2 = _mm256_blend_pd(ymm2, ymm10, 0x08); ymm3 = _mm256_blend_pd(ymm3, ymm11, 0x08); ymm4 = _mm256_blend_pd(ymm4, ymm12, 0x08); ymm5 = _mm256_blend_pd(ymm5, ymm13, 0x08); ymm6 = _mm256_blend_pd(ymm6, ymm14, 0x08); ymm7 = _mm256_blend_pd(ymm7, ymm15, 0x08); } else if(2 == m_remainder) { ///implement TRSM/// ///unpacklow/// ymm9 = _mm256_unpacklo_pd(ymm0, ymm1); //B11[0][0] B11[0][1] B11[2][0] B11[2][1] ymm11 = _mm256_unpacklo_pd(ymm2, ymm3); //B11[0][2] B11[0][3] B11[2][2] B11[2][3] ymm13 = _mm256_unpacklo_pd(ymm4, ymm5); //B11[0][4] B11[0][5] B11[1][4] B11[1][5] ymm15 = _mm256_unpacklo_pd(ymm6, ymm7); //B11[0][6] B11[0][7] B11[1][6] B11[1][7] //rearrange low elements ymm8 = _mm256_permute2f128_pd(ymm9,ymm11,0x20); //B11[0][0] B11[0][1] B11[0][2] B11[0][3] ymm10 = _mm256_permute2f128_pd(ymm9,ymm11,0x31); //B11[2][0] B11[2][1] B11[2][2] B11[2][3] ymm12 = _mm256_permute2f128_pd(ymm13,ymm15,0x20); //B11[4][0] B11[4][1] B11[4][2] B11[4][3] ymm14 = _mm256_permute2f128_pd(ymm13,ymm15,0x31); //B11[6][0] B11[6][1] B11[6][2] B11[6][3] ////unpackhigh//// ymm0 = _mm256_unpackhi_pd(ymm0, ymm1); //B11[1][0] B11[1][1] B11[3][0] B11[3][1] ymm1 = _mm256_unpackhi_pd(ymm2, ymm3); //B11[1][2] B11[1][3] B11[3][2] B11[3][3] ymm4 = _mm256_unpackhi_pd(ymm4, ymm5); //B11[5][0] B11[5][1] B11[7][0] B11[7][1] ymm5 = _mm256_unpackhi_pd(ymm6, ymm7); //B11[5][2] B11[5][3] B11[7][2] B11[7][3] //rearrange high elements ymm9 = _mm256_permute2f128_pd(ymm0,ymm1,0x20); //B11[1][0] B11[1][1] B11[1][2] B11[1][3] ymm11 = _mm256_permute2f128_pd(ymm0,ymm1,0x31); //B11[3][0] B11[3][1] B11[3][2] B11[3][3] ymm13 = _mm256_permute2f128_pd(ymm4,ymm5,0x20); //B11[5][0] B11[5][1] B11[5][2] B11[5][3] ymm15 = _mm256_permute2f128_pd(ymm4,ymm5,0x31); //B11[7][0] B11[7][1] B11[7][2] B11[7][3] ymm0 = _mm256_broadcast_sd((double const *)&ones); //broadcast diagonal elements of A11 ymm1 = _mm256_broadcast_sd((double const *)(a11+0)); //A11[0][0] ymm2 = _mm256_broadcast_sd((double const *)(a11+ cs_a +1)); //A11[1][1] ymm5 = _mm256_unpacklo_pd(ymm1, ymm2); //A11[0][0] A11[0][0] A11[1][1] A11[1][1] ymm5 = _mm256_blend_pd(ymm5, ymm0, 0x0C); //A11[0][0] A11[1][1] A11[2][2] A11[3][3] ymm0 = _mm256_div_pd(ymm0, ymm5); //1/A11[0][0] 1/A11[1][1] 1/A11[2][2] 1/A11[3][3] //extract a00 ymm1 = _mm256_permute_pd(ymm0, 0x00); //1/A11[0][0] 1/A11[0][0] 1/A11[2][2] 1/A11[2][2] ymm1 = _mm256_permute2f128_pd(ymm1, ymm1, 0x00); //1/A11[0][0] 1/A11[0][0] 1/A11[0][0] 1/A11[0][0] //(Row 0): perform mul operation of reciprocal of L(0,0) element with 1st row elements of B ymm8 = _mm256_mul_pd(ymm8, ymm1); //B11[0-3][0] /= A11[0][0] ymm12 = _mm256_mul_pd(ymm12, ymm1); //B11[0-3][4] /= A11[0][0] //extract a11 ymm1 = _mm256_permute_pd(ymm0, 0x03); //1/A11[1][1] 1/A11[1][1] 1/A11[3][3] 1/A11[3][3] ymm1 = _mm256_permute2f128_pd(ymm1, ymm1, 0x00); //1/A11[1][1] 1/A11[1][1] 1/A11[1][1] 1/A11[1][1] ymm2 = _mm256_broadcast_sd((double const *)(a11 +1)); //A11[1][0] a11 += cs_a; //(Row1): FMA operations ymm9 = _mm256_fnmadd_pd(ymm2, ymm8, ymm9); //B11[1][0-3] -= B11[0-3][0]*A11[1][0] ymm13 = _mm256_fnmadd_pd(ymm2, ymm12, ymm13); //B11[5][0-3] -= B11[0-3][4]*A11[1][4] ymm9 = _mm256_mul_pd(ymm9, ymm1); //B11[0-3][1] /= A11[1][1] ymm13 = _mm256_mul_pd(ymm13, ymm1); //B11[0-3][5] /= A11[1][1] ymm10 = _mm256_broadcast_sd((double const *)&ones); //unpacklow// ymm1 = _mm256_unpacklo_pd(ymm8, ymm9); //B11[0][0] B11[1][0] B11[0][2] B11[1][2] ymm5 = _mm256_unpacklo_pd(ymm12, ymm13); //B11[4][0] B11[5][0] B11[4][2] B11[5][2] //rearrange low elements ymm0 = _mm256_permute2f128_pd(ymm1, ymm10, 0x20); //B11[0][0] B11[1][0] B11[2][0] B11[3][0] ymm2 = _mm256_permute2f128_pd(ymm1, ymm10, 0x31); //B11[0][2] B11[1][2] B11[2][2] B11[3][2] ymm4 = _mm256_permute2f128_pd(ymm5, ymm10, 0x20); //B11[0][4] B11[1][4] B11[2][4] B11[3][4] ymm6 = _mm256_permute2f128_pd(ymm5, ymm10, 0x31); //B11[0][6] B11[1][6] B11[2][6] B11[3][6] ///unpack high/// ymm8 = _mm256_unpackhi_pd(ymm8, ymm9); //B11[0][1] B11[1][1] B11[0][3] B11[1][3] ymm12 = _mm256_unpackhi_pd(ymm12, ymm13); //B11[0][5] B11[1][5] B11[0][7] B11[1][7] //rearrange high elements ymm1 = _mm256_permute2f128_pd(ymm8, ymm10, 0x20); //B11[0][1] B11[1][1] B11[2][1] B11[3][1] ymm3 = _mm256_permute2f128_pd(ymm8, ymm10, 0x31); //B11[0][3] B11[1][3] B11[2][3] B11[3][3] ymm5 = _mm256_permute2f128_pd(ymm12, ymm10, 0x20); //B11[0][5] B11[1][5] B11[2][5] B11[3][5] ymm7 = _mm256_permute2f128_pd(ymm12, ymm10, 0x31); //B11[0][7] B11[1][7] B11[2][7] B11[3][7] ymm8 = _mm256_loadu_pd((double const *)(b11 + cs_b * 0)); //load B11[0-3][0] ymm9 = _mm256_loadu_pd((double const *)(b11 + cs_b * 1)); //load B11[0-3][1] ymm10 = _mm256_loadu_pd((double const *)(b11 + cs_b * 2)); //load B11[0-3][2] ymm11 = _mm256_loadu_pd((double const *)(b11 + cs_b * 3)); //load B11[0-3][3] ymm12 = _mm256_loadu_pd((double const *)(b11 + cs_b * 4)); //load B11[0-3][4] ymm13 = _mm256_loadu_pd((double const *)(b11 + cs_b * 5)); //load B11[0-3][5] ymm14 = _mm256_loadu_pd((double const *)(b11 + cs_b * 6)); //load B11[0-3][6] ymm15 = _mm256_loadu_pd((double const *)(f_temp)); //load B11[0-3][7] //determine correct values to store ymm0 = _mm256_permute2f128_pd(ymm0, ymm8, 0x30); ymm1 = _mm256_permute2f128_pd(ymm1, ymm9, 0x30); ymm2 = _mm256_permute2f128_pd(ymm2, ymm10, 0x30); ymm3 = _mm256_permute2f128_pd(ymm3, ymm11, 0x30); ymm4 = _mm256_permute2f128_pd(ymm4, ymm12, 0x30); ymm5 = _mm256_permute2f128_pd(ymm5, ymm13, 0x30); ymm6 = _mm256_permute2f128_pd(ymm6, ymm14, 0x30); ymm7 = _mm256_permute2f128_pd(ymm7, ymm15, 0x30); } else if(1 == m_remainder) { ///implement TRSM/// ///unpacklow/// ymm9 = _mm256_unpacklo_pd(ymm0, ymm1); //B11[0][0] B11[0][1] B11[2][0] B11[2][1] ymm11 = _mm256_unpacklo_pd(ymm2, ymm3); //B11[0][2] B11[0][3] B11[2][2] B11[2][3] ymm13 = _mm256_unpacklo_pd(ymm4, ymm5); //B11[0][4] B11[0][5] B11[1][4] B11[1][5] ymm15 = _mm256_unpacklo_pd(ymm6, ymm7); //B11[0][6] B11[0][7] B11[1][6] B11[1][7] //rearrange low elements ymm8 = _mm256_permute2f128_pd(ymm9,ymm11,0x20); //B11[0][0] B11[0][1] B11[0][2] B11[0][3] ymm10 = _mm256_permute2f128_pd(ymm9,ymm11,0x31); //B11[2][0] B11[2][1] B11[2][2] B11[2][3] ymm12 = _mm256_permute2f128_pd(ymm13,ymm15,0x20); //B11[4][0] B11[4][1] B11[4][2] B11[4][3] ymm14 = _mm256_permute2f128_pd(ymm13,ymm15,0x31); //B11[6][0] B11[6][1] B11[6][2] B11[6][3] ////unpackhigh//// ymm0 = _mm256_unpackhi_pd(ymm0, ymm1); //B11[1][0] B11[1][1] B11[3][0] B11[3][1] ymm1 = _mm256_unpackhi_pd(ymm2, ymm3); //B11[1][2] B11[1][3] B11[3][2] B11[3][3] ymm4 = _mm256_unpackhi_pd(ymm4, ymm5); //B11[5][0] B11[5][1] B11[7][0] B11[7][1] ymm5 = _mm256_unpackhi_pd(ymm6, ymm7); //B11[5][2] B11[5][3] B11[7][2] B11[7][3] //rearrange high elements ymm9 = _mm256_permute2f128_pd(ymm0,ymm1,0x20); //B11[1][0] B11[1][1] B11[1][2] B11[1][3] ymm11 = _mm256_permute2f128_pd(ymm0,ymm1,0x31); //B11[3][0] B11[3][1] B11[3][2] B11[3][3] ymm13 = _mm256_permute2f128_pd(ymm4,ymm5,0x20); //B11[5][0] B11[5][1] B11[5][2] B11[5][3] ymm15 = _mm256_permute2f128_pd(ymm4,ymm5,0x31); //B11[7][0] B11[7][1] B11[7][2] B11[7][3] ymm0 = _mm256_broadcast_sd((double const *)&ones); //broadcast diagonal elements of A11 ymm1 = _mm256_broadcast_sd((double const *)(a11+0)); //A11[0][0] ymm0 = _mm256_div_pd(ymm0, ymm1); //1/A11[0][0] 1/A11[1][1] 1/A11[2][2] 1/A11[3][3] //extract a00 ymm1 = _mm256_permute_pd(ymm0, 0x00); //1/A11[0][0] 1/A11[0][0] 1/A11[2][2] 1/A11[2][2] ymm1 = _mm256_permute2f128_pd(ymm1, ymm1, 0x00); //1/A11[0][0] 1/A11[0][0] 1/A11[0][0] 1/A11[0][0] //(Row 0): perform mul operation of reciprocal of L(0,0) element with 1st row elements of B ymm8 = _mm256_mul_pd(ymm8, ymm1); //B11[0-3][0] /= A11[0][0] ymm12 = _mm256_mul_pd(ymm12, ymm1); //B11[0-3][4] /= A11[0][0] ymm9 = _mm256_broadcast_sd((double const *)(&ones)); //unpacklow// ymm1 = _mm256_unpacklo_pd(ymm8, ymm9); //B11[0][0] B11[1][0] B11[0][2] B11[1][2] ymm5 = _mm256_unpacklo_pd(ymm12, ymm9); //B11[4][0] B11[5][0] B11[4][2] B11[5][2] //rearrange low elements ymm0 = _mm256_permute2f128_pd(ymm1, ymm9, 0x20); //B11[0][0] B11[1][0] B11[2][0] B11[3][0] ymm2 = _mm256_permute2f128_pd(ymm1, ymm9, 0x31); //B11[0][2] B11[1][2] B11[2][2] B11[3][2] ymm4 = _mm256_permute2f128_pd(ymm5, ymm9, 0x20); //B11[0][4] B11[1][4] B11[2][4] B11[3][4] ymm6 = _mm256_permute2f128_pd(ymm5, ymm9, 0x31); //B11[0][6] B11[1][6] B11[2][6] B11[3][6] ///unpack high/// ymm8 = _mm256_unpackhi_pd(ymm8, ymm9); //B11[0][1] B11[1][1] B11[0][3] B11[1][3] ymm12 = _mm256_unpackhi_pd(ymm12, ymm9); //B11[0][5] B11[1][5] B11[0][7] B11[1][7] //rearrange high elements ymm1 = _mm256_permute2f128_pd(ymm8, ymm9, 0x20); //B11[0][1] B11[1][1] B11[2][1] B11[3][1] ymm3 = _mm256_permute2f128_pd(ymm8, ymm9, 0x31); //B11[0][3] B11[1][3] B11[2][3] B11[3][3] ymm5 = _mm256_permute2f128_pd(ymm12, ymm9, 0x20); //B11[0][5] B11[1][5] B11[2][5] B11[3][5] ymm7 = _mm256_permute2f128_pd(ymm12, ymm9, 0x31); //B11[0][7] B11[1][7] B11[2][7] B11[3][7] ymm8 = _mm256_loadu_pd((double const *)(b11 + cs_b * 0)); //load B11[0-3][0] ymm9 = _mm256_loadu_pd((double const *)(b11 + cs_b * 1)); //load B11[0-3][1] ymm10 = _mm256_loadu_pd((double const *)(b11 + cs_b * 2)); //load B11[0-3][2] ymm11 = _mm256_loadu_pd((double const *)(b11 + cs_b * 3)); //load B11[0-3][3] ymm12 = _mm256_loadu_pd((double const *)(b11 + cs_b * 4)); //load B11[0-3][4] ymm13 = _mm256_loadu_pd((double const *)(b11 + cs_b * 5)); //load B11[0-3][5] ymm14 = _mm256_loadu_pd((double const *)(b11 + cs_b * 6)); //load B11[0-3][6] ymm15 = _mm256_loadu_pd((double const *)(f_temp)); //load B11[0-3][7] //determine correct values to store ymm0 = _mm256_blend_pd(ymm0, ymm8, 0x0E); ymm1 = _mm256_blend_pd(ymm1, ymm9, 0x0E); ymm2 = _mm256_blend_pd(ymm2, ymm10, 0x0E); ymm3 = _mm256_blend_pd(ymm3, ymm11, 0x0E); ymm4 = _mm256_blend_pd(ymm4, ymm12, 0x0E); ymm5 = _mm256_blend_pd(ymm5, ymm13, 0x0E); ymm6 = _mm256_blend_pd(ymm6, ymm14, 0x0E); ymm7 = _mm256_blend_pd(ymm7, ymm15, 0x0E); } _mm256_storeu_pd((double *)(b11 + cs_b * 0), ymm0); //store(B11[0-3][0]) _mm256_storeu_pd((double *)(b11 + cs_b * 1), ymm1); //store(B11[0-3][1]) _mm256_storeu_pd((double *)(b11 + cs_b * 2), ymm2); //store(B11[0-3][2]) _mm256_storeu_pd((double *)(b11 + cs_b * 3), ymm3); //store(B11[0-3][3]) _mm256_storeu_pd((double *)(b11 + cs_b * 4), ymm4); //store(B11[0-3][4]) _mm256_storeu_pd((double *)(b11 + cs_b * 5), ymm5); //store(B11[0-3][5]) _mm256_storeu_pd((double *)(b11 + cs_b * 6), ymm6); //store(B11[0-3][6]) _mm256_storeu_pd((double *)(f_temp), ymm7); //store(B11[0-3][7]) if((j+D_NR) == n) { for(iter = 0; iter < m_remainder; iter++) (b11 + cs_b * 7)[iter] = f_t[iter]; } } } if((n & 4)) //implementation for remainder columns(when 'n_remainder' is greater than 4) { for(i = 0;i+D_MR-1 < m; i += D_MR) //loop along 'M' direction { a10 = L +i; //pointer to block of A to be used for GEMM a11 = L + i + (i*cs_a); //pointer to block of A to be used for TRSM b01 = B + j*cs_b; //pointer to block of B to be used for GEMM b11 = B + i + j* cs_b; //pointer to block of B to be used for TRSM k_iter = i / D_MR; //number of times GEMM to be performed(in block of 4) ///GEMM for previously calculated values /// //load 4x4 block from b11 ymm0 = _mm256_loadu_pd((double const *)(b11)); //B11[0][0] B11[1][0] B11[2][0] B11[3][0] ymm1 = _mm256_loadu_pd((double const *)(b11 + cs_b)); //B11[0][1] B11[1][1] B11[2][1] B11[3][1] ymm2 = _mm256_loadu_pd((double const *)(b11 + cs_b*2)); //B11[0][2] B11[1][2] B11[2][2] B11[3][2] ymm3 = _mm256_loadu_pd((double const *)(b11 + cs_b*3)); //B11[0][3] B11[1][3] B11[2][3] B11[3][3] ymm4 = _mm256_setzero_pd(); ymm5 = _mm256_setzero_pd(); ymm6 = _mm256_setzero_pd(); ymm7 = _mm256_setzero_pd(); for(k = 0; k < k_iter; k++) //loop for number of GEMM operations { ptr_b01_dup = b01; ymm8 = _mm256_loadu_pd((double const *)(a10)); //A10[0][0] A10[1][0] A10[2][0] A10[3][0] ymm9 = _mm256_loadu_pd((double const *)(a10 + cs_a)); //A10[0][1] A10[1][1] A10[2][1] A10[3][1] ymm10 = _mm256_loadu_pd((double const *)(a10 + cs_a*2)); //A10[0][2] A10[1][2] A10[2][2] A10[3][2] ymm11 = _mm256_loadu_pd((double const *)(a10 + cs_a * 3)); //A10[0][3] A10[1][3] A10[2][3] A10[3][3] ymm12 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 0)); //B01[0][0] ymm13 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 1)); //B01[0][1] ymm14 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 2)); //B01[0][2] ymm15 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 3)); //B01[0][3] b01 += 1; //move to next row of B ymm4 = _mm256_fmadd_pd(ymm12, ymm8, ymm4); //ymm4 += (B01[0][0]*A10[0][0] B01[0][0]*A10[1][0] B01[0][0]*A10[2][0] B01[0][0]*A10[3][0]) ymm5 = _mm256_fmadd_pd(ymm13, ymm8, ymm5); //ymm5 += (B01[0][1]*A10[0][0] B01[0][1]*A10[1][0] B01[0][1]*A10[2][0] B01[0][1]*A10[3][0]) ymm6 = _mm256_fmadd_pd(ymm14, ymm8, ymm6); //ymm6 += (B01[0][2]*A10[0][0] B01[0][2]*A10[1][0] B01[0][2]*A10[2][0] B01[0][2]*A10[3][0]) ymm7 = _mm256_fmadd_pd(ymm15, ymm8, ymm7); //ymm7 += (B01[0][3]*A10[0][0] B01[0][3]*A10[1][0] B01[0][3]*A10[2][0] B01[0][3]*A10[3][0]) ymm12 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 0)); //B01[1][0] ymm13 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 1)); //B01[1][1] ymm14 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 2)); //B01[1][2] ymm15 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 3)); //B01[1][3] b01 += 1; ymm4 = _mm256_fmadd_pd(ymm12, ymm9, ymm4); //ymm4 += (B01[1][0]*A10[0][1] B01[1][0]*A10[1][1] B01[1][0]*A10[2][1] B01[1][0]*A10[3][1]) ymm5 = _mm256_fmadd_pd(ymm13, ymm9, ymm5); //ymm5 += (B01[1][1]*A10[0][1] B01[1][1]*A10[1][1] B01[1][1]*A10[2][1] B01[1][1]*A10[3][1]) ymm6 = _mm256_fmadd_pd(ymm14, ymm9, ymm6); //ymm6 += (B01[1][2]*A10[0][1] B01[1][2]*A10[1][1] B01[1][2]*A10[2][1] B01[1][2]*A10[3][1]) ymm7 = _mm256_fmadd_pd(ymm15, ymm9, ymm7); //ymm7 += (B01[1][3]*A10[0][1] B01[1][3]*A10[1][1] B01[1][3]*A10[2][1] B01[1][3]*A10[3][1]) ymm12 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 0)); //B01[2][0] ymm13 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 1)); //B01[2][1] ymm14 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 2)); //B01[2][2] ymm15 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 3)); //B01[2][3] b01 += 1; ymm4 = _mm256_fmadd_pd(ymm12, ymm10, ymm4); //ymm4 += (B01[2][0]*A10[0][2] B01[2][0]*A10[1][2] B01[2][0]*A10[2][2] B01[2][0]*A10[3][2]) ymm5 = _mm256_fmadd_pd(ymm13, ymm10, ymm5); //ymm5 += (B01[2][1]*A10[1][2] B01[2][1]*A10[1][2] B01[2][1]*A10[2][2] B01[2][1]*A10[3][2]) ymm6 = _mm256_fmadd_pd(ymm14, ymm10, ymm6); //ymm6 += (B01[2][2]*A10[2][2] B01[2][2]*A10[1][2] B01[2][2]*A10[2][2] B01[2][2]*A10[3][2]) ymm7 = _mm256_fmadd_pd(ymm15, ymm10, ymm7); //ymm7 += (B01[2][3]*A10[3][2] B01[2][3]*A10[1][2] B01[2][3]*A10[2][2] B01[2][3]*A10[3][2]) ymm12 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 0)); //B01[3][0] ymm13 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 1)); //B01[3][1] ymm14 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 2)); //B01[3][2] ymm15 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 3)); //B01[3][3] b01 += 1; ymm4 = _mm256_fmadd_pd(ymm12, ymm11, ymm4); //ymm4 += (B01[3][0]*A10[0][3] B01[3][0]*A10[1][3] B01[3][0]*A10[2][3] B01[3][0]*A10[3][3]) ymm5 = _mm256_fmadd_pd(ymm13, ymm11, ymm5); //ymm5 += (B01[3][1]*A10[0][3] B01[3][1]*A10[1][3] B01[3][1]*A10[2][3] B01[3][1]*A10[3][3]) ymm6 = _mm256_fmadd_pd(ymm14, ymm11, ymm6); //ymm6 += (B01[3][2]*A10[0][3] B01[3][2]*A10[1][3] B01[3][2]*A10[2][3] B01[3][2]*A10[3][3]) ymm7 = _mm256_fmadd_pd(ymm15, ymm11, ymm7); //ymm7 += (B01[3][3]*A10[0][3] B01[3][3]*A10[1][3] B01[3][3]*A10[2][3] B01[3][3]*A10[3][3]) a10 += D_MR * cs_a; //pointer math to find next block of A for GEMM b01 = ptr_b01_dup + D_MR; //pointer math to find next block of B for GEMM } ymm15 = _mm256_broadcast_sd((double const *)&AlphaVal); //register to store alpha ymm0 = _mm256_fmsub_pd(ymm0, ymm15, ymm4); //B11[0-3][0] *alpha -= ymm4 ymm1 = _mm256_fmsub_pd(ymm1, ymm15, ymm5); //B01[0-3][1] *alpha -= ymm5 ymm2 = _mm256_fmsub_pd(ymm2, ymm15, ymm6); //B01[0-3][2] *alpha -= ymm6 ymm3 = _mm256_fmsub_pd(ymm3, ymm15, ymm7); //B01[0-3][3] *alpha -= ymm7 ///implement TRSM/// //1st col ymm4 = _mm256_broadcast_sd((double const *)(a11+0)); //A11[0][0] ymm5 = _mm256_broadcast_sd((double const *)(a11+1)); //A11[1][0] ymm6 = _mm256_broadcast_sd((double const *)(a11+2)); //A11[2][0] ymm7 = _mm256_broadcast_sd((double const *)(a11+3)); //A11[3][0] //2nd col a11 += cs_a; ymm8 = _mm256_broadcast_sd((double const *)(a11 + 1)); //A11[1][1] ymm9 = _mm256_broadcast_sd((double const *)(a11 + 2)); //A11[2][1] ymm10 = _mm256_broadcast_sd((double const *)(a11 + 3)); //A11[3][1] //3rd col a11 += cs_a; ymm11 = _mm256_broadcast_sd((double const *)(a11 + 2)); //A11[2][2] ymm12 = _mm256_broadcast_sd((double const *)(a11 + 3)); //A11[3][2] //4th col a11 += cs_a; ymm13 = _mm256_broadcast_sd((double const *)(a11 + 3)); //A11[3][3] //compute reciprocals of L(i,i) and broadcast in registers ymm4 = _mm256_unpacklo_pd(ymm4, ymm8); //A11[0][0] A11[0][0] A11[2][2] A11[2][2] ymm8 = _mm256_unpacklo_pd(ymm11, ymm13); //A11[1][1] A11[1][1] A11[3][3] A11[3][3] ymm14 = _mm256_broadcast_sd((double const *)&ones); ymm4 = _mm256_blend_pd(ymm4, ymm8, 0x0C); //A11[0][0] A11[1][1] A11[2][2] A11[3][3] ymm14 = _mm256_div_pd(ymm14, ymm4); //1/A11[0][0] 1/A11[1][1] 1/A11[2][2] 1/A11[3][3] ////unpacklow//// ymm8 = _mm256_unpacklo_pd(ymm0, ymm1); //B11[0][0] B11[0][1] B11[2][0] B11[2][1] ymm13 = _mm256_unpacklo_pd(ymm2, ymm3); //B11[0][2] B11[0][3] B11[2][2] B11[2][3] //rearrange low elements ymm4 = _mm256_permute2f128_pd(ymm8,ymm13,0x20); //B11[0][0] B11[0][1] B11[0][2] B11[0][3] ymm11 = _mm256_permute2f128_pd(ymm8,ymm13,0x31);//B11[2][0] B11[2][1] B11[2][2] B11[2][3] ////unpackhigh//// ymm0 = _mm256_unpackhi_pd(ymm0, ymm1); //B11[1][0] B11[1][1] B11[3][0] B11[3][1] ymm1 = _mm256_unpackhi_pd(ymm2, ymm3); //B11[1][2] B11[1][3] B11[3][2] B11[3][3] //rearrange high elements ymm8 = _mm256_permute2f128_pd(ymm0,ymm1,0x20); //B11[1][0] B11[1][1] B11[1][2] B11[1][3] ymm13 = _mm256_permute2f128_pd(ymm0,ymm1,0x31); //B11[3][0] B11[3][1] B11[3][2] B11[3][3] //extract a00 ymm15 = _mm256_permute_pd(ymm14, 0x00); //1/A11[0][0] 1/A11[0][0] 1/A11[2][2] 1/A11[2][2] ymm15 = _mm256_permute2f128_pd(ymm15, ymm15, 0x00); //1/A11[0][0] 1/A11[0][0] 1/A11[0][0] 1/A11[0][0] //(Row0): Perform mul operation of reciprocal of L(0,0) element with 1st row elements of B ymm4 = _mm256_mul_pd(ymm4, ymm15); //B11[0][0-3] /= A11[0][0] //extract diag a11 from a ymm15 = _mm256_permute_pd(ymm14, 0x03); //1/A11[1][1] 1/A11[1][1] 1/A11[3][3] 1/A11[3][3] ymm15 = _mm256_permute2f128_pd(ymm15, ymm15, 0x00); //1/A11[1][1] 1/A11[1][1] 1/A11[1][1] 1/A11[1][1] //(Row1): FMA operations of b1 with elements of indices from (1, 0) uptill (3, 0) ymm8 = _mm256_fnmadd_pd(ymm5, ymm4, ymm8);//d = c - (a*b) //B11[1][0-3] -= A11[1][0]*B11[0][0-3] ymm11 = _mm256_fnmadd_pd(ymm6, ymm4, ymm11);//d = c - (a*b) //B11[2][0-3] -= A11[2][0]*B11[0][0-3] ymm13 = _mm256_fnmadd_pd(ymm7, ymm4, ymm13);//d = c - (a*b) //B11[3][0-3] -= A11[3][0]*B11[0][0-3] //Perform mul operation of reciprocal of L(1,1) element with 2nd row elements of B ymm8 = _mm256_mul_pd(ymm8, ymm15); //B11[1][0-3] /= A11[1][1] //extract diag a22 from a ymm15 = _mm256_permute_pd(ymm14, 0x00); //1/A11[0][0] 1/A11[0][0] 1/A11[2][2] 1/A11[2][2] ymm15 = _mm256_permute2f128_pd(ymm15, ymm15, 0x11); //1/A11[2][2] 1/A11[2][2] 1/A11[2][2] 1/A11[2][2] //(Row2): FMA operations of b2 with elements of indices from (2, 0) uptill (7, 0) ymm11 = _mm256_fnmadd_pd(ymm9, ymm8, ymm11);//d = c - (a*b) //B11[2][0-3] -= A11[2][1]*B11[1][0-3] ymm13 = _mm256_fnmadd_pd(ymm10, ymm8, ymm13);//d = c - (a*b) //B11[3][0-3] -= A11[3][1]*B11[1][0-3] //Perform mul operation of reciprocal of L(2, 2) element with 3rd row elements of B ymm11 = _mm256_mul_pd(ymm11, ymm15); //B11[2][0-3] /= A11[2][2] //extract diag a33 from a ymm15 = _mm256_permute_pd(ymm14, 0x0C); //1/A11[0][0] 1/A11[0][0] 1/A11[3][3] 1/A11[3][3] ymm15 = _mm256_permute2f128_pd(ymm15, ymm15, 0x11); //1/A11[3][3] 1/A11[3][3] 1/A11[3][3] 1/A11[3][3] //(Row3): FMA operations of b3 with elements of indices from (3, 0) uptill (7, 0) ymm13 = _mm256_fnmadd_pd(ymm12, ymm11, ymm13);//d = c - (a*b) //B11[3][0-3] -= A11[3][2]*B11[2][0-3] //Perform mul operation of reciprocal of L(3, 3) element with 4rth row elements of B ymm13 = _mm256_mul_pd(ymm13, ymm15); //B11[3][0-3] /= A11[3][3] //--> Transpose and store results of columns of B block <--// ////unpacklow//// ymm1 = _mm256_unpacklo_pd(ymm4, ymm8); //B11[0][0] B11[1][0] B11[0][2] B11[1][2] ymm3 = _mm256_unpacklo_pd(ymm11, ymm13); //B11[2][0] B11[3][0] B11[2][2] B11[3][2] //rearrange low elements ymm0 = _mm256_permute2f128_pd(ymm1,ymm3,0x20); //B11[0][0] B11[1][0] B11[2][0] B11[3][0] ymm2 = _mm256_permute2f128_pd(ymm1,ymm3,0x31); //B11[0][2] B11[1][2] B11[2][2] B11[3][2] ////unpackhigh//// ymm14 = _mm256_unpackhi_pd(ymm4, ymm8); //B11[0][1] B11[1][1] B11[0][3] B11[1][3] ymm15 = _mm256_unpackhi_pd(ymm11, ymm13); //B11[2][1] B11[3][1] B11[2][3] B11[3][3] //rearrange high elements ymm1 = _mm256_permute2f128_pd(ymm14,ymm15,0x20); //B11[0][1] B11[1][1] B11[2][1] B11[3][1] ymm3 = _mm256_permute2f128_pd(ymm14,ymm15,0x31); //B11[0][3] B11[1][3] B11[2][3] B11[3][3] _mm256_storeu_pd((double *)b11, ymm0); //store(B11[0-3][0]) _mm256_storeu_pd((double *)(b11 + (cs_b)), ymm1); //store(B11[0-3][1]) _mm256_storeu_pd((double *)(b11 + cs_b*2), ymm2); //store(B11[0-3][2]) _mm256_storeu_pd((double *)(b11 + cs_b*3), ymm3); //store(B11[0-3][3]) } if(m_remainder) //implementation for remainder rows(when 'M' is not a multiple of D_MR) { a10 = L +i; //pointer to block of A to be used for GEMM a11 = L + i + (i*cs_a); //pointer to block of A to be used for TRSM b01 = B + j*cs_b; //pointer to block of B to be used for GEMM b11 = B + i + j* cs_b; //pointer to block of B to be used for TRSM k_iter = i / D_MR; //number of GEMM operations to be performed(in blocks of 4x4) dim_t iter; if((j+4) == n) { f_temp = f_t; for(iter = 0; iter < m_remainder; iter++) f_temp[iter] = (b11 + cs_b * 3)[iter]; } else f_temp = (b11 + cs_b * 3); ///GEMM for previously calculated values /// //load 4x4 block from b11 ymm0 = _mm256_loadu_pd((double const *)(b11)); //B11[0][0] B11[1][0] B11[2][0] B11[3][0] ymm1 = _mm256_loadu_pd((double const *)(b11 + cs_b)); //B11[0][1] B11[1][1] B11[2][1] B11[3][1] ymm2 = _mm256_loadu_pd((double const *)(b11 + cs_b * 2)); //B11[0][2] B11[1][2] B11[2][2] B11[3][2] ymm3 = _mm256_loadu_pd((double const *)(f_temp)); //B11[0][3] B11[1][3] B11[2][3] B11[3][3] ymm4 = _mm256_setzero_pd(); ymm5 = _mm256_setzero_pd(); ymm6 = _mm256_setzero_pd(); ymm7 = _mm256_setzero_pd(); for(k = 0; k < k_iter; k++) //looop for number of GEMM operations { ptr_b01_dup = b01; ymm8 = _mm256_loadu_pd((double const *)(a10)); //A10[0][0] A10[1][0] A10[2][0] A10[3][0] ymm9 = _mm256_loadu_pd((double const *)(a10 + cs_a)); //A10[0][1] A10[1][1] A10[2][1] A10[3][1] ymm10 = _mm256_loadu_pd((double const *)(a10 + cs_a * 2)); //A10[0][2] A10[1][2] A10[2][2] A10[3][2] ymm11 = _mm256_loadu_pd((double const *)(a10 + cs_a * 3)); //A10[0][3] A10[1][3] A10[2][3] A10[3][3] ymm12 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 0)); //B01[0][0] ymm13 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 1)); //B01[0][1] ymm14 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 2)); //B01[0][2] ymm15 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 3)); //B01[0][3] b01 += 1; ymm4 = _mm256_fmadd_pd(ymm12, ymm8, ymm4); //ymm4 += (B01[0][0]*A10[0][0] B01[0][0]*A10[1][0] B01[0][0]*A10[2][0] B01[0][0]*A10[3][0]) ymm5 = _mm256_fmadd_pd(ymm13, ymm8, ymm5); //ymm5 += (B01[0][1]*A10[0][0] B01[0][1]*A10[1][0] B01[0][1]*A10[2][0] B01[0][1]*A10[3][0]) ymm6 = _mm256_fmadd_pd(ymm14, ymm8, ymm6); //ymm6 += (B01[0][2]*A10[0][0] B01[0][2]*A10[1][0] B01[0][2]*A10[2][0] B01[0][2]*A10[3][0]) ymm7 = _mm256_fmadd_pd(ymm15, ymm8, ymm7); //ymm7 += (B01[0][3]*A10[0][0] B01[0][3]*A10[1][0] B01[0][3]*A10[2][0] B01[0][3]*A10[3][0]) ymm12 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 0)); //B01[1][0] ymm13 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 1)); //B01[1][1] ymm14 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 2)); //B01[1][2] ymm15 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 3)); //B01[1][3] b01 += 1; ymm4 = _mm256_fmadd_pd(ymm12, ymm9, ymm4); //ymm4 += (B01[1][0]*A10[0][1] B01[1][0]*A10[1][1] B01[1][0]*A10[2][1] B01[1][0]*A10[3][1]) ymm5 = _mm256_fmadd_pd(ymm13, ymm9, ymm5); //ymm5 += (B01[1][1]*A10[0][1] B01[1][1]*A10[1][1] B01[1][1]*A10[2][1] B01[1][1]*A10[3][1]) ymm6 = _mm256_fmadd_pd(ymm14, ymm9, ymm6); //ymm6 += (B01[1][2]*A10[0][1] B01[1][2]*A10[1][1] B01[1][2]*A10[2][1] B01[1][2]*A10[3][1]) ymm7 = _mm256_fmadd_pd(ymm15, ymm9, ymm7); //ymm7 += (B01[1][3]*A10[0][1] B01[1][3]*A10[1][1] B01[1][3]*A10[2][1] B01[1][3]*A10[3][1]) ymm12 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 0)); //B01[2][0] ymm13 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 1)); //B01[2][1] ymm14 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 2)); //B01[2][2] ymm15 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 3)); //B01[2][3] b01 += 1; ymm4 = _mm256_fmadd_pd(ymm12, ymm10, ymm4); //ymm4 += (B01[2][0]*A10[0][2] B01[2][0]*A10[1][2] B01[2][0]*A10[2][2] B01[2][0]*A10[3][2]) ymm5 = _mm256_fmadd_pd(ymm13, ymm10, ymm5); //ymm5 += (B01[2][1]*A10[0][2] B01[2][1]*A10[1][2] B01[2][1]*A10[2][2] B01[2][1]*A10[3][2]) ymm6 = _mm256_fmadd_pd(ymm14, ymm10, ymm6); //ymm6 += (B01[2][2]*A10[0][2] B01[2][2]*A10[1][2] B01[2][2]*A10[2][2] B01[2][2]*A10[3][2]) ymm7 = _mm256_fmadd_pd(ymm15, ymm10, ymm7); //ymm7 += (B01[2][3]*A10[0][2] B01[2][3]*A10[1][2] B01[2][3]*A10[2][2] B01[2][3]*A10[3][2]) ymm12 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 0)); //B01[3][0] ymm13 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 1)); //B01[3][1] ymm14 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 2)); //B01[3][2] ymm15 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 3)); //B01[3][3] b01 += 1; ymm4 = _mm256_fmadd_pd(ymm12, ymm11, ymm4); //ymm4 += (B01[3][0]*A10[0][3] B01[3][0]*A10[1][3] B01[3][0]*A10[2][3] B01[3][0]*A10[3][3]) ymm5 = _mm256_fmadd_pd(ymm13, ymm11, ymm5); //ymm5 += (B01[3][1]*A10[0][3] B01[3][1]*A10[1][3] B01[3][1]*A10[2][3] B01[3][1]*A10[3][3]) ymm6 = _mm256_fmadd_pd(ymm14, ymm11, ymm6); //ymm6 += (B01[3][2]*A10[0][3] B01[3][2]*A10[1][3] B01[3][2]*A10[2][3] B01[3][2]*A10[3][3]) ymm7 = _mm256_fmadd_pd(ymm15, ymm11, ymm7); //ymm7 += (B01[3][3]*A10[0][3] B01[3][3]*A10[1][3] B01[3][3]*A10[2][3] B01[3][3]*A10[3][3]) a10 += D_MR * cs_a; //pointer math to find next block of A for GEMM b01 = ptr_b01_dup + D_MR; //pointer math to find next block of B for GEMM } ymm15 = _mm256_broadcast_sd((double const *)&AlphaVal); //register to store alpha ymm0 = _mm256_fmsub_pd(ymm0, ymm15, ymm4); //B11[0-3][0] *alpha -= ymm4 ymm1 = _mm256_fmsub_pd(ymm1, ymm15, ymm5); //B11[0-3][1] *alpha -= ymm5 ymm2 = _mm256_fmsub_pd(ymm2, ymm15, ymm6); //B11[0-3][2] *alpha -= ymm6 ymm3 = _mm256_fmsub_pd(ymm3, ymm15, ymm7); //B11[0-3][3] *alpha -= ymm7 if(3 == m_remainder) { ///implement TRSM/// //1st col ymm4 = _mm256_broadcast_sd((double const *)(a11+0)); //A11[0][0] ymm5 = _mm256_broadcast_sd((double const *)(a11+1)); //A11[1][0] ymm6 = _mm256_broadcast_sd((double const *)(a11+2)); //A11[2][0] //2nd col a11 += cs_a; ymm8 = _mm256_broadcast_sd((double const *)(a11 + 1)); //A11[1][1] ymm9 = _mm256_broadcast_sd((double const *)(a11 + 2)); //A11[2][1] //3rd col a11 += cs_a; ymm11 = _mm256_broadcast_sd((double const *)(a11 + 2)); //A11[2][2] //4th col a11 += cs_a; ymm13 = _mm256_broadcast_sd((double const *)(&ones)); //A11[3][3] //compute reciprocals of L(i,i) and broadcast in registers ymm4 = _mm256_unpacklo_pd(ymm4, ymm8); //A11[0][0] A11[0][0] A11[1][1] A11[1][1] ymm8 = _mm256_unpacklo_pd(ymm11, ymm13); //A11[2][2] A11[2][2] A11[3][3] A11[3][3] ymm14 = _mm256_broadcast_sd((double const *)&ones); ymm4 = _mm256_blend_pd(ymm4, ymm8, 0x0C); //A11[0][0] A11[1][1] A11[2][2] A11[3][3] ymm14 = _mm256_div_pd(ymm14, ymm4); //1/A11[0][0] 1/A11[1][1] 1/A11[2][2] 1/A11[3][3] ////unpacklow//// ymm8 = _mm256_unpacklo_pd(ymm0, ymm1); //B11[0][0] B11[0][1] B11[2][0] B11[2][1] ymm13 = _mm256_unpacklo_pd(ymm2, ymm3); //B11[0][2] B11[0][3] B11[2][2] B11[2][3] //rearrange low elements ymm4 = _mm256_permute2f128_pd(ymm8,ymm13,0x20); //B11[0][0] B11[0][1] B11[0][2] B11[0][3] ymm11 = _mm256_permute2f128_pd(ymm8,ymm13,0x31);//B11[2][0] B11[2][1] B11[2][2] B11[2][3] ////unpackhigh//// ymm0 = _mm256_unpackhi_pd(ymm0, ymm1); //B11[1][0] B11[1][1] B11[3][0] B11[3][1] ymm1 = _mm256_unpackhi_pd(ymm2, ymm3); //B11[1][2] B11[1][3] B11[3][2] B11[3][3] //rearrange high elements ymm8 = _mm256_permute2f128_pd(ymm0,ymm1,0x20); //B11[1][0] B11[1][1] B11[1][2] B11[1][3] ymm13 = _mm256_permute2f128_pd(ymm0,ymm1,0x31); //B11[3][0] B11[3][1] B11[3][2] B11[3][3] //extract a00 ymm15 = _mm256_permute_pd(ymm14, 0x00); //1/A11[0][0] 1/A11[0][0] 1/A11[2][2] 1/A11[2][2] ymm15 = _mm256_permute2f128_pd(ymm15, ymm15, 0x00);//1/A11[0][0] 1/A11[0][0] 1/A11[0][0] 1/A11[0][0] //(Row0): Perform mul operation of reciprocal of L(0,0) element with 1st row elements of B ymm4 = _mm256_mul_pd(ymm4, ymm15); //B11[0][0-3] /= A11[0][0] //extract diag a11 from a ymm15 = _mm256_permute_pd(ymm14, 0x03); //1/A11[1][1] 1/A11[1][1] 1/A11[3][3] 1/A11[3][3] ymm15 = _mm256_permute2f128_pd(ymm15, ymm15, 0x00); //1/A11[][] 1/A11[1][1] 1/A11[1][1] 1/A11[1][1] //(Row1): FMA operations of b1 with elements of indices from (1, 0) uptill (3, 0) ymm8 = _mm256_fnmadd_pd(ymm5, ymm4, ymm8);//d = c - (a*b) //B11[1][0-3] -= A11[1][0]* B11[0][0-3] ymm11 = _mm256_fnmadd_pd(ymm6, ymm4, ymm11);//d = c - (a*b) //B11[2][0-3] -= A11[2][0]* B11[0][0-3] //Perform mul operation of reciprocal of L(1,1) element with 2nd row elements of B ymm8 = _mm256_mul_pd(ymm8, ymm15); //B11[1][0-3] /= A11[1][1] //extract diag a22 from a ymm15 = _mm256_permute_pd(ymm14, 0x00); //1/A11[0][0] 1/A11[0][0] 1/A11[2][2] 1/A11[2][2] ymm15 = _mm256_permute2f128_pd(ymm15, ymm15, 0x11); //1/A11[2][2] 1/A11[2][2] 1/A11[2][2] 1/A11[2][2] //(Row2): FMA operations of b2 with elements of indices from (2, 0) uptill (7, 0) ymm11 = _mm256_fnmadd_pd(ymm9, ymm8, ymm11);//d = c - (a*b) //B11[2][0-3] -= A11[2][1]* B11[1][0-3] //Perform mul operation of reciprocal of L(2, 2) element with 3rd row elements of B ymm11 = _mm256_mul_pd(ymm11, ymm15); //B11[2][0-3] /= A11[2][2] ymm13 = _mm256_broadcast_sd((double const *)(&ones)); //--> Transpose and store results of columns of B block <--// ////unpacklow//// ymm1 = _mm256_unpacklo_pd(ymm4, ymm8); //B11[0][0] B11[1][0] B11[0][2] B11[1][2] ymm3 = _mm256_unpacklo_pd(ymm11, ymm13); //B11[2][0] B11[3][0] B11[2][2] B11[3][2] //rearrange low elements ymm0 = _mm256_permute2f128_pd(ymm1,ymm3,0x20); //B11[0][0] B11[1][0] B11[2][0] B11[3][0] ymm2 = _mm256_permute2f128_pd(ymm1,ymm3,0x31); //B11[0][2] B11[1][2] B11[2][2] B11[3][2] ////unpackhigh//// ymm14 = _mm256_unpackhi_pd(ymm4, ymm8); //B11[0][1] B11[1][1] B11[0][3] B11[1][3] ymm15 = _mm256_unpackhi_pd(ymm11, ymm13); //B11[2][1] B11[3][1] B11[2][3] B11[3][3] //rearrange high elements ymm1 = _mm256_permute2f128_pd(ymm14,ymm15,0x20); //B11[0][1] B11[1][1] B11[2][1] B11[3][1] ymm3 = _mm256_permute2f128_pd(ymm14,ymm15,0x31); //B11[0][3] B11[1][3] B11[2][3] B11[3][3] //load 4x4 block from b11 ymm4 = _mm256_loadu_pd((double const *)(b11)); //B11[0][0] B11[1][0] B11[2][0] B11[3][0] ymm5 = _mm256_loadu_pd((double const *)(b11 + cs_b)); //B11[0][1] B11[1][1] B11[2][1] B11[3][1] ymm6 = _mm256_loadu_pd((double const *)(b11 + cs_b * 2)); //B11[0][2] B11[1][2] B11[2][2] B11[3][2] ymm7 = _mm256_loadu_pd((double const *)(f_temp)); //B11[0][3] B11[1][3] B11[2][2] B11[3][3] //determine correct values to store ymm0 = _mm256_blend_pd(ymm0, ymm4, 0x08); ymm1 = _mm256_blend_pd(ymm1, ymm5, 0x08); ymm2 = _mm256_blend_pd(ymm2, ymm6, 0x08); ymm3 = _mm256_blend_pd(ymm3, ymm7, 0x08); } else if( 2 == m_remainder ) { ///implement TRSM/// //1st col ymm4 = _mm256_broadcast_sd((double const *)(a11+0)); //A11[0][0] ymm5 = _mm256_broadcast_sd((double const *)(a11+1)); //A11[1][0] //2nd col a11 += cs_a; ymm8 = _mm256_broadcast_sd((double const *)(a11 + 1)); //A11[1][1] //compute reciprocals of L(i,i) and broadcast in registers ymm4 = _mm256_unpacklo_pd(ymm4, ymm8); //A11[0][0] A11[0][0] A11[1][1] A11[1][1] ymm14 = _mm256_broadcast_sd((double const *)&ones); ymm4 = _mm256_blend_pd(ymm4, ymm14, 0x0C); //A11[0][0] A11[1][1] A11[2][2] A11[3][3] ymm14 = _mm256_div_pd(ymm14, ymm4); //1/A11[0][0] 1/A11[1][1] 1/A11[2][2] 1/A11[3][3] ////unpacklow//// ymm8 = _mm256_unpacklo_pd(ymm0, ymm1); //B11[0][0] B11[0][1] B11[2][0] B11[2][1] ymm13 = _mm256_unpacklo_pd(ymm2, ymm3); //B11[0][2] B11[0][3] B11[2][2] B11[2][3] //rearrange low elements ymm4 = _mm256_permute2f128_pd(ymm8,ymm13,0x20); //B11[0][0] B11[0][1] B11[0][2] B11[0][3] ymm11 = _mm256_permute2f128_pd(ymm8,ymm13,0x31);//B11[2][0] B11[2][1] B11[2][2] B11[2][3] ////unpackhigh//// ymm0 = _mm256_unpackhi_pd(ymm0, ymm1); //B11[1][0] B11[1][1] B11[3][0] B11[3][1] ymm1 = _mm256_unpackhi_pd(ymm2, ymm3); //B11[1][2] B11[1][3] B11[3][2] B11[3][3] //rearrange high elements ymm8 = _mm256_permute2f128_pd(ymm0,ymm1,0x20); //B11[1][0] B11[1][1] B11[1][2] B11[1][3] ymm13 = _mm256_permute2f128_pd(ymm0,ymm1,0x31); //B11[3][0] B11[3][1] B11[3][2] B11[3][3] //extract a00 ymm15 = _mm256_permute_pd(ymm14, 0x00); //1/A11[0][0] 1/A11[0][0] 1/A11[2][2] 1/A11[2][2] ymm15 = _mm256_permute2f128_pd(ymm15, ymm15, 0x00);//1/A11[0][0] 1/A11[0][0] 1/A11[0][0] 1/A11[0][0] //(Row0): Perform mul operation of reciprocal of L(0,0) element with 1st row elements of B ymm4 = _mm256_mul_pd(ymm4, ymm15); //B11[0][0-3] /= A11[0][0] //extract diag a11 from a ymm15 = _mm256_permute_pd(ymm14, 0x03); //1/A11[1][1] 1/A11[1][1] 1/A11[3][3] 1/A11[3][3] ymm15 = _mm256_permute2f128_pd(ymm15, ymm15, 0x00); //1/A11[][] 1/A11[1][1] 1/A11[1][1] 1/A11[1][1] //(Row1): FMA operations of b1 with elements of indices from (1, 0) uptill (3, 0) ymm8 = _mm256_fnmadd_pd(ymm5, ymm4, ymm8);//d = c - (a*b) //B11[1][0-3] -= A11[1][0]* B11[0][0-3] //Perform mul operation of reciprocal of L(1,1) element with 2nd row elements of B ymm8 = _mm256_mul_pd(ymm8, ymm15); //B11[1][0-3] /= A11[1][1] ymm11 = _mm256_broadcast_sd((double const *)(&ones)); ymm13 = _mm256_broadcast_sd((double const *)(&ones)); //--> Transpose and store results of columns of B block <--// ////unpacklow//// ymm1 = _mm256_unpacklo_pd(ymm4, ymm8); //B11[0][0] B11[1][0] B11[0][2] B11[1][2] ymm3 = _mm256_unpacklo_pd(ymm11, ymm13); //B11[2][0] B11[3][0] B11[2][2] B11[3][2] //rearrange low elements ymm0 = _mm256_permute2f128_pd(ymm1,ymm3,0x20); //B11[0][0] B11[1][0] B11[2][0] B11[3][0] ymm2 = _mm256_permute2f128_pd(ymm1,ymm3,0x31); //B11[0][2] B11[1][2] B11[2][2] B11[3][2] ////unpackhigh//// ymm14 = _mm256_unpackhi_pd(ymm4, ymm8); //B11[0][1] B11[1][1] B11[0][3] B11[1][3] ymm15 = _mm256_unpackhi_pd(ymm11, ymm13); //B11[2][1] B11[3][1] B11[2][3] B11[3][3] //rearrange high elements ymm1 = _mm256_permute2f128_pd(ymm14,ymm15,0x20); //B11[0][1] B11[1][1] B11[2][1] B11[3][1] ymm3 = _mm256_permute2f128_pd(ymm14,ymm15,0x31); //B11[0][3] B11[1][3] B11[2][3] B11[3][3] //load 4x4 block from b11 ymm4 = _mm256_loadu_pd((double const *)(b11)); //B11[0][0] B11[1][0] B11[2][0] B11[3][0] ymm5 = _mm256_loadu_pd((double const *)(b11 + cs_b)); //B11[0][1] B11[1][1] B11[2][1] B11[3][1] ymm6 = _mm256_loadu_pd((double const *)(b11 + cs_b * 2)); //B11[0][2] B11[1][2] B11[2][2] B11[3][2] ymm7 = _mm256_loadu_pd((double const *)(f_temp)); //B11[0][3] B11[1][3] B11[2][2] B11[3][3] //determine correct values to store ymm0 = _mm256_permute2f128_pd(ymm0, ymm4,0x30); ymm1 = _mm256_permute2f128_pd(ymm1, ymm5,0x30); ymm2 = _mm256_permute2f128_pd(ymm2, ymm6,0x30); ymm3 = _mm256_permute2f128_pd(ymm3, ymm7,0x30); } else if(1 == m_remainder) { ///implement TRSM/// //1st col ymm4 = _mm256_broadcast_sd((double const *)(a11+0)); //A11[0][0] ymm14 = _mm256_broadcast_sd((double const *)&ones); ymm14 = _mm256_div_pd(ymm14, ymm4); //1/A11[0][0] 1/A11[1][1] 1/A11[2][2] 1/A11[3][3] ////unpacklow//// ymm8 = _mm256_unpacklo_pd(ymm0, ymm1); //B11[0][0] B11[0][1] B11[2][0] B11[2][1] ymm13 = _mm256_unpacklo_pd(ymm2, ymm3); //B11[0][2] B11[0][3] B11[2][2] B11[2][3] //rearrange low elements ymm4 = _mm256_permute2f128_pd(ymm8,ymm13,0x20); //B11[0][0] B11[0][1] B11[0][2] B11[0][3] ymm11 = _mm256_permute2f128_pd(ymm8,ymm13,0x31);//B11[2][0] B11[2][1] B11[2][2] B11[2][3] ////unpackhigh//// ymm0 = _mm256_unpackhi_pd(ymm0, ymm1); //B11[1][0] B11[1][1] B11[3][0] B11[3][1] ymm1 = _mm256_unpackhi_pd(ymm2, ymm3); //B11[1][2] B11[1][3] B11[3][2] B11[3][3] //rearrange high elements ymm8 = _mm256_permute2f128_pd(ymm0,ymm1,0x20); //B11[1][0] B11[1][1] B11[1][2] B11[1][3] ymm13 = _mm256_permute2f128_pd(ymm0,ymm1,0x31); //B11[3][0] B11[3][1] B11[3][2] B11[3][3] //extract a00 ymm15 = _mm256_permute_pd(ymm14, 0x00); //1/A11[0][0] 1/A11[0][0] 1/A11[2][2] 1/A11[2][2] ymm15 = _mm256_permute2f128_pd(ymm15, ymm15, 0x00);//1/A11[0][0] 1/A11[0][0] 1/A11[0][0] 1/A11[0][0] //(Row0): Perform mul operation of reciprocal of L(0,0) element with 1st row elements of B ymm4 = _mm256_mul_pd(ymm4, ymm15); //B11[0][0-3] /= A11[0][0] ymm8 = _mm256_broadcast_sd((double const *)(&ones)); ymm11 = _mm256_broadcast_sd((double const *)(&ones)); ymm13 = _mm256_broadcast_sd((double const *)(&ones)); //--> Transpose and store results of columns of B block <--// ////unpacklow//// ymm1 = _mm256_unpacklo_pd(ymm4, ymm8); //B11[0][0] B11[1][0] B11[0][2] B11[1][2] ymm3 = _mm256_unpacklo_pd(ymm11, ymm13); //B11[2][0] B11[3][0] B11[2][2] B11[3][2] //rearrange low elements ymm0 = _mm256_permute2f128_pd(ymm1,ymm3,0x20); //B11[0][0] B11[1][0] B11[2][0] B11[3][0] ymm2 = _mm256_permute2f128_pd(ymm1,ymm3,0x31); //B11[0][2] B11[1][2] B11[2][2] B11[3][2] ////unpackhigh//// ymm14 = _mm256_unpackhi_pd(ymm4, ymm8); //B11[0][1] B11[1][1] B11[0][3] B11[1][3] ymm15 = _mm256_unpackhi_pd(ymm11, ymm13); //B11[2][1] B11[3][1] B11[2][3] B11[3][3] //rearrange high elements ymm1 = _mm256_permute2f128_pd(ymm14,ymm15,0x20); //B11[0][1] B11[1][1] B11[2][1] B11[3][1] ymm3 = _mm256_permute2f128_pd(ymm14,ymm15,0x31); //B11[0][3] B11[1][3] B11[2][3] B11[3][3] //load 4x4 block from b11 ymm4 = _mm256_loadu_pd((double const *)(b11)); //B11[0][0] B11[1][0] B11[2][0] B11[3][0] ymm5 = _mm256_loadu_pd((double const *)(b11 + cs_b)); //B11[0][1] B11[1][1] B11[2][1] B11[3][1] ymm6 = _mm256_loadu_pd((double const *)(b11 + cs_b * 2)); //B11[0][2] B11[1][2] B11[2][2] B11[3][2] ymm7 = _mm256_loadu_pd((double const *)(f_temp)); //B11[0][3] B11[1][3] B11[2][2] B11[3][3] //determine correct values to store ymm0 = _mm256_blend_pd(ymm0, ymm4, 0x0E); ymm1 = _mm256_blend_pd(ymm1, ymm5, 0x0E); ymm2 = _mm256_blend_pd(ymm2, ymm6, 0x0E); ymm3 = _mm256_blend_pd(ymm3, ymm7, 0x0E); } _mm256_storeu_pd((double *)b11, ymm0); //store(B11[0-3][0]) _mm256_storeu_pd((double *)(b11 + (cs_b)), ymm1); //store(B11[0-3][1]) _mm256_storeu_pd((double *)(b11 + cs_b * 2), ymm2); //store(B11[0-3][2]) _mm256_storeu_pd((double *)(f_temp), ymm3); //store(B11[0-3][3]) if((j+4) == n) { for(iter = 0; iter < m_remainder; iter++) (b11 + cs_b * 3)[iter] = f_temp[iter]; } } n_remainder -= 4; j += 4; } if(n_remainder) //implementation fo remaining columns(when 'N' is not a multiple of D_NR) { for(i = 0;i+D_MR-1 < m; i += D_MR) //loop along 'M' direction { a10 = L +i; //pointer to block of A to be used for GEMM a11 = L + i + (i*cs_a); //pointer to block of A to be used for TRSM b01 = B + j*cs_b; //pointer to block of B to be used for GEMM b11 = B + i + j* cs_b; //pointer to block of B to be used for TRSM k_iter = i / D_MR; //number of GEMM operations to be performed(in blocks of 4x4) ymm4 = _mm256_setzero_pd(); ymm5 = _mm256_setzero_pd(); ymm6 = _mm256_setzero_pd(); ymm7 = _mm256_setzero_pd(); ///GEMM for previously calculated values /// //load 4x4 block from b11 if(3 == n_remainder) { ymm0 = _mm256_loadu_pd((double const *)(b11)); //B11[0][0] B11[1][0] B11[2][0] B11[3][0] ymm1 = _mm256_loadu_pd((double const *)(b11 + cs_b)); //B11[0][1] B11[1][1] B11[2][1] B11[3][1] ymm2 = _mm256_loadu_pd((double const *)(b11 + cs_b * 2)); //B11[0][2] B11[1][2] B11[2][2] B11[3][2] for(k = 0; k < k_iter; k++) { ptr_b01_dup = b01; ymm8 = _mm256_loadu_pd((double const *)(a10)); //A10[0][0] A10[1][0] A10[2][0] A10[3][0] ymm9 = _mm256_loadu_pd((double const *)(a10 + cs_a)); //A10[0][1] A10[1][1] A10[2][1] A10[3][1] ymm10 = _mm256_loadu_pd((double const *)(a10 + cs_a * 2)); //A10[0][2] A10[1][2] A10[2][2] A10[3][2] ymm11 = _mm256_loadu_pd((double const *)(a10 + cs_a * 3)); //A10[0][3] A10[1][3] A10[2][3] A10[3][3] ymm12 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 0)); //B01[0][0] ymm13 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 1)); //B01[0][1] ymm14 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 2)); //B01[0][2] b01 += 1; ymm4 = _mm256_fmadd_pd(ymm12, ymm8, ymm4); //ymm4 += (B01[0][0]*A10[0][0] B01[0][0]*A10[1][0] B01[0][0]*A10[2][0] B01[0][0]*A10[3][0]) ymm5 = _mm256_fmadd_pd(ymm13, ymm8, ymm5); //ymm5 += (B01[0][1]*A10[0][0] B01[0][1]*A10[1][0] B01[0][1]*A10[2][0] B01[0][1]*A10[3][0]) ymm6 = _mm256_fmadd_pd(ymm14, ymm8, ymm6); //ymm6 += (B01[0][2]*A10[0][0] B01[0][2]*A10[1][0] B01[0][2]*A10[2][0] B01[0][2]*A10[3][0]) ymm12 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 0)); //B01[1][0] ymm13 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 1)); //B01[1][1] ymm14 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 2)); //B01[1][2] b01 += 1; ymm4 = _mm256_fmadd_pd(ymm12, ymm9, ymm4); //ymm4 += (B01[1][0]*A10[0][1] B01[1][0]*A10[1][1] B01[1][0]*A10[2][1] B01[1][0]*A10[3][1]) ymm5 = _mm256_fmadd_pd(ymm13, ymm9, ymm5); //ymm5 += (B01[1][1]*A10[0][1] B01[1][1]*A10[1][1] B01[1][1]*A10[2][1] B01[1][1]*A10[3][1]) ymm6 = _mm256_fmadd_pd(ymm14, ymm9, ymm6); //ymm6 += (B01[1][2]*A10[0][1] B01[1][2]*A10[1][1] B01[1][2]*A10[2][1] B01[1][2]*A10[3][1]) ymm12 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 0)); //B01[2][0] ymm13 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 1)); //B01[2][1] ymm14 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 2)); //B01[2][2] b01 += 1; ymm4 = _mm256_fmadd_pd(ymm12, ymm10, ymm4); //ymm4 += (B01[2][0]*A10[0][2] B01[2][0]*A10[1][2] B01[2][0]*A10[2][2] B01[2][0]*A10[3][2]) ymm5 = _mm256_fmadd_pd(ymm13, ymm10, ymm5); //ymm5 += (B01[2][1]*A10[0][2] B01[2][1]*A10[1][2] B01[2][1]*A10[2][2] B01[2][1]*A10[3][2]) ymm6 = _mm256_fmadd_pd(ymm14, ymm10, ymm6); //ymm6 += (B01[2][2]*A10[0][2] B01[2][2]*A10[1][2] B01[2][2]*A10[2][2] B01[2][2]*A10[3][2]) ymm12 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 0)); //B01[3][0] ymm13 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 1)); //B01[3][1] ymm14 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 2)); //B01[3][2] b01 += 1; ymm4 = _mm256_fmadd_pd(ymm12, ymm11, ymm4); //ymm4 += (B01[3][0]*A10[0][3] B01[3][0]*A10[1][3] B01[3][0]*A10[2][3] B01[3][0]*A10[3][3]) ymm5 = _mm256_fmadd_pd(ymm13, ymm11, ymm5); //ymm5 += (B01[3][1]*A10[0][3] B01[3][1]*A10[1][3] B01[3][1]*A10[2][3] B01[3][1]*A10[3][3]) ymm6 = _mm256_fmadd_pd(ymm14, ymm11, ymm6); //ymm6 += (B01[3][2]*A10[0][3] B01[3][2]*A10[1][3] B01[3][2]*A10[2][3] B01[3][2]*A10[3][3]) a10 += D_MR * cs_a; //pointer math to find next block of A for GEMM b01 = ptr_b01_dup + D_MR; //pointer math to find next block of B for GEMM } ///GEMM code ends/// ymm15 = _mm256_broadcast_sd((double const *)&AlphaVal); //register to store alpha Value ymm0 = _mm256_fmsub_pd(ymm0, ymm15, ymm4); //B11[0-3][0] *alpha -= ymm4 ymm1 = _mm256_fmsub_pd(ymm1, ymm15, ymm5); //B11[0-3][1] *alpha -= ymm5 ymm2 = _mm256_fmsub_pd(ymm2, ymm15, ymm6); //B11[0-3][2] *alpha -= ymm6 ymm3 = _mm256_broadcast_sd((double const *)(&ones)); //B11[0-3][3] *alpha -= ymm7 } else if(2 == n_remainder) { ymm0 = _mm256_loadu_pd((double const *)(b11)); //B11[0][0] B11[1][0] B11[2][0] B11[3][0] ymm1 = _mm256_loadu_pd((double const *)(b11 + cs_b)); //B11[0][1] B11[1][1] B11[2][1] B11[3][1] for(k = 0; k < k_iter; k++) { ptr_b01_dup = b01; ymm8 = _mm256_loadu_pd((double const *)(a10)); //A10[0][0] A10[1][0] A10[2][0] A10[3][0] ymm9 = _mm256_loadu_pd((double const *)(a10 + cs_a)); //A10[0][1] A10[1][1] A10[2][1] A10[3][1] ymm10 = _mm256_loadu_pd((double const *)(a10 + cs_a * 2)); //A10[0][2] A10[1][2] A10[2][2] A10[3][2] ymm11 = _mm256_loadu_pd((double const *)(a10 + cs_a * 3)); //A10[0][3] A10[1][3] A10[2][3] A10[3][3] ymm12 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 0)); //B01[0][0] ymm13 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 1)); //B01[0][1] b01 += 1; ymm4 = _mm256_fmadd_pd(ymm12, ymm8, ymm4); //ymm4 += (B01[0][0]*A10[0][0] B01[0][0]*A10[1][0] B01[0][0]*A10[2][0] B01[0][0]*A10[3][0]) ymm5 = _mm256_fmadd_pd(ymm13, ymm8, ymm5); //ymm5 += (B01[0][1]*A10[0][0] B01[0][1]*A10[1][0] B01[0][1]*A10[2][0] B01[0][1]*A10[3][0]) ymm12 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 0)); //B01[1][0] ymm13 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 1)); //B01[1][1] b01 += 1; ymm4 = _mm256_fmadd_pd(ymm12, ymm9, ymm4); //ymm4 += (B01[1][0]*A10[0][1] B01[1][0]*A10[1][1] B01[1][0]*A10[2][1] B01[1][0]*A10[3][1]) ymm5 = _mm256_fmadd_pd(ymm13, ymm9, ymm5); //ymm5 += (B01[1][1]*A10[0][1] B01[1][1]*A10[1][1] B01[1][1]*A10[2][1] B01[1][1]*A10[3][1]) ymm12 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 0)); //B01[2][0] ymm13 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 1)); //B01[2][1] b01 += 1; ymm4 = _mm256_fmadd_pd(ymm12, ymm10, ymm4); //ymm4 += (B01[2][0]*A10[0][2] B01[2][0]*A10[1][2] B01[2][0]*A10[2][2] B01[2][0]*A10[3][2]) ymm5 = _mm256_fmadd_pd(ymm13, ymm10, ymm5); //ymm5 += (B01[2][1]*A10[0][2] B01[2][1]*A10[1][2] B01[2][1]*A10[2][2] B01[2][1]*A10[3][2]) ymm12 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 0)); //B01[3][0] ymm13 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 1)); //B01[3][1] b01 += 1; ymm4 = _mm256_fmadd_pd(ymm12, ymm11, ymm4); //ymm4 += (B01[3][0]*A10[0][3] B01[3][0]*A10[1][3] B01[3][0]*A10[2][3] B01[3][0]*A10[3][3]) ymm5 = _mm256_fmadd_pd(ymm13, ymm11, ymm5); //ymm5 += (B01[3][1]*A10[0][3] B01[3][1]*A10[1][3] B01[3][1]*A10[2][3] B01[3][1]*A10[3][3]) a10 += D_MR * cs_a; //pointer math to find next block of A for GEMM b01 = ptr_b01_dup + D_MR; //pointer math to find next block of B for GEMM } ///GEMM code ends/// ymm15 = _mm256_broadcast_sd((double const *)&AlphaVal); //register to store alpha Value ymm0 = _mm256_fmsub_pd(ymm0, ymm15, ymm4); //B11[0-3][0] *alpha -= ymm4 ymm1 = _mm256_fmsub_pd(ymm1, ymm15, ymm5); //B11[0-3][1] *alpha -= ymm5 ymm2 = _mm256_broadcast_sd((double const *)(&ones)); //B11[0-3][2] *alpha -= ymm6 ymm3 = _mm256_broadcast_sd((double const *)(&ones)); //B11[0-3][3] *alpha -= ymm7 } else if(1 == n_remainder) { ymm0 = _mm256_loadu_pd((double const *)(b11)); //B11[0][0] B11[1][0] B11[2][0] B11[3][0] for(k = 0; k < k_iter; k++) { ptr_b01_dup = b01; ymm8 = _mm256_loadu_pd((double const *)(a10)); //A10[0][0] A10[1][0] A10[2][0] A10[3][0] ymm9 = _mm256_loadu_pd((double const *)(a10 + cs_a)); //A10[0][1] A10[1][1] A10[2][1] A10[3][1] ymm10 = _mm256_loadu_pd((double const *)(a10 + cs_a * 2)); //A10[0][2] A10[1][2] A10[2][2] A10[3][2] ymm11 = _mm256_loadu_pd((double const *)(a10 + cs_a * 3)); //A10[0][3] A10[1][3] A10[2][3] A10[3][3] ymm12 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 0)); //B01[0][0] b01 += 1; ymm4 = _mm256_fmadd_pd(ymm12, ymm8, ymm4); //ymm4 += (B01[0][0]*A10[0][0] B01[0][0]*A10[1][0] B01[0][0]*A10[2][0] B01[0][0]*A10[3][0]) ymm12 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 0)); //B01[1][0] b01 += 1; ymm4 = _mm256_fmadd_pd(ymm12, ymm9, ymm4); //ymm4 += (B01[1][0]*A10[0][1] B01[1][0]*A10[1][1] B01[1][0]*A10[2][1] B01[1][0]*A10[3][1]) ymm12 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 0)); //B01[2][0] b01 += 1; ymm4 = _mm256_fmadd_pd(ymm12, ymm10, ymm4); //ymm4 += (B01[2][0]*A10[0][2] B01[2][0]*A10[1][2] B01[2][0]*A10[2][2] B01[2][0]*A10[3][2]) ymm12 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 0)); //B01[3][0] b01 += 1; ymm4 = _mm256_fmadd_pd(ymm12, ymm11, ymm4); //ymm4 += (B01[3][0]*A10[0][3] B01[3][0]*A10[1][3] B01[3][0]*A10[2][3] B01[3][0]*A10[3][3]) a10 += D_MR * cs_a; //pointer math to find next block of A for GEMM b01 = ptr_b01_dup + D_MR; //pointer math to find next block of B for GEMM } ///GEMM code ends/// ymm15 = _mm256_broadcast_sd((double const *)&AlphaVal); //register to store alpha Value ymm0 = _mm256_fmsub_pd(ymm0, ymm15, ymm4); //B11[0-3][0] *alpha -= ymm4 ymm1 = _mm256_broadcast_sd((double const *)(&ones)); //B11[0-3][1] *alpha -= ymm5 ymm2 = _mm256_broadcast_sd((double const *)(&ones)); //B11[0-3][2] *alpha -= ymm6 ymm3 = _mm256_broadcast_sd((double const *)(&ones)); //B11[0-3][3] *alpha -= ymm7 } ///implement TRSM/// //1st col ymm4 = _mm256_broadcast_sd((double const *)(a11+0)); //A11[0][0] ymm5 = _mm256_broadcast_sd((double const *)(a11+1)); //A11[1][0] ymm6 = _mm256_broadcast_sd((double const *)(a11+2)); //A11[2][0] ymm7 = _mm256_broadcast_sd((double const *)(a11+3)); //A11[3][0] //2nd col a11 += cs_a; ymm8 = _mm256_broadcast_sd((double const *)(a11 + 1)); //A11[1][1] ymm9 = _mm256_broadcast_sd((double const *)(a11 + 2)); //A11[2][1] ymm10 = _mm256_broadcast_sd((double const *)(a11 + 3)); //A11[3][1] //3rd col a11 += cs_a; ymm11 = _mm256_broadcast_sd((double const *)(a11 + 2)); //A11[2][2] ymm12 = _mm256_broadcast_sd((double const *)(a11 + 3)); //A11[3][2] //4th col a11 += cs_a; ymm13 = _mm256_broadcast_sd((double const *)(a11 + 3)); //A11[3][3] //compute reciprocals of L(i,i) and broadcast in registers ymm4 = _mm256_unpacklo_pd(ymm4, ymm8); //A11[0][0] A11[0][0] A11[1][1] A11[1][1] ymm8 = _mm256_unpacklo_pd(ymm11, ymm13); //A11[2][2] A11[2][2] A11[3][3] A11[3][3] ymm14 = _mm256_broadcast_sd((double const *)&ones); ymm4 = _mm256_blend_pd(ymm4, ymm8, 0x0C); //A11[0][0] A11[1][1] A11[2][2] A11[3][3] ymm14 = _mm256_div_pd(ymm14, ymm4); //1/A11[0][0] 1/A11[1][1] 1/A11[2][2] 1/A11[3][3] ////unpacklow//// ymm8 = _mm256_unpacklo_pd(ymm0, ymm1); //B11[0][0] B11[0][1] B11[2][0] B11[2][1] ymm13 = _mm256_unpacklo_pd(ymm2, ymm3); //B11[0][2] B11[0][3] B11[2][2] B11[2][3] //rearrange low elements ymm4 = _mm256_permute2f128_pd(ymm8,ymm13,0x20); //B11[0][0] B11[0][1] B11[0][2] B11[0][3] ymm11 = _mm256_permute2f128_pd(ymm8,ymm13,0x31);//B11[2][0] B11[2][1] B11[2][2] B11[2][3] ////unpackhigh//// ymm0 = _mm256_unpackhi_pd(ymm0, ymm1); //B11[1][0] B11[1][1] B11[3][0] B11[3][1] ymm1 = _mm256_unpackhi_pd(ymm2, ymm3); //B11[1][2] B11[1][3] B11[3][2] B11[3][3] //rearrange high elements ymm8 = _mm256_permute2f128_pd(ymm0,ymm1,0x20); //B11[1][0] B11[1][1] B11[1][2] B11[1][3] ymm13 = _mm256_permute2f128_pd(ymm0,ymm1,0x31); //B11[3][0] B11[3][1] B11[3][2] B11[3][3] //extract a00 ymm15 = _mm256_permute_pd(ymm14, 0x00); //1/A11[0][0] 1/A11[0][0] 1/A11[2][2] 1/A11[2][2] ymm15 = _mm256_permute2f128_pd(ymm15, ymm15, 0x00); //1/A11[0][0] 1/A11[0][0] 1/A11[0][0] 1/A11[0][0] //(Row0): Perform mul operation of reciprocal of L(0,0) element with 1st row elements of B ymm4 = _mm256_mul_pd(ymm4, ymm15); //B11[0][0-3] /= A11[0][0] //extract diag a11 from a ymm15 = _mm256_permute_pd(ymm14, 0x03); //1/A11[1][1] 1/A11[1][1] 1/A11[2][2] 1/A11[2][2] ymm15 = _mm256_permute2f128_pd(ymm15, ymm15, 0x00); //1/A11[1][1] 1/A11[1][1] 1/A11[1][1] 1/A11[1][1] //(Row1): FMA operations of b1 with elements of indices from (1, 0) uptill (3, 0) ymm8 = _mm256_fnmadd_pd(ymm5, ymm4, ymm8);//d = c - (a*b) //B11[1][0-3] -= A11[1][0] * B11[0][0-3] ymm11 = _mm256_fnmadd_pd(ymm6, ymm4, ymm11);//d = c - (a*b) //B11[2][0-3] -= A11[2][0] * B11[0][0-3] ymm13 = _mm256_fnmadd_pd(ymm7, ymm4, ymm13);//d = c - (a*b) //B11[3][0-3] -= A11[3][0] * B11[0][0-3] //Perform mul operation of reciprocal of L(1,1) element with 2nd row elements of B ymm8 = _mm256_mul_pd(ymm8, ymm15); //B11[1][0-3] /= A11[1][1] //extract diag a22 from a ymm15 = _mm256_permute_pd(ymm14, 0x00); //1/A11[0][0] 1/A11[0][0] 1/A11[2][2] 1/A11[2][2] ymm15 = _mm256_permute2f128_pd(ymm15, ymm15, 0x11); //1/A11[2][2] 1/A11[2][2] 1/A11[2][2] 1/A11[2][2] //(Row2): FMA operations of b2 with elements of indices from (2, 0) uptill (7, 0) ymm11 = _mm256_fnmadd_pd(ymm9, ymm8, ymm11);//d = c - (a*b) //B11[2][0-3] -= A11[2][1] * B11[1][0-3] ymm13 = _mm256_fnmadd_pd(ymm10, ymm8, ymm13);//d = c - (a*b) //B11[3][0-3] -= A11[3][1] * B11[1][0-3] //Perform mul operation of reciprocal of L(2, 2) element with 3rd row elements of B ymm11 = _mm256_mul_pd(ymm11, ymm15); //B11[2][0-3] /= A11[2][2] //extract diag a33 from a ymm15 = _mm256_permute_pd(ymm14, 0x0C); //1/A11[0][0] 1/A11[0][0] 1/A11[3][3] 1/A11[3][3] ymm15 = _mm256_permute2f128_pd(ymm15, ymm15, 0x11); //1/A11[3][3] 1/A11[3][3] 1/A11[3][3] 1/A11[3][3] //(Row3): FMA operations of b3 with elements of indices from (3, 0) uptill (7, 0) ymm13 = _mm256_fnmadd_pd(ymm12, ymm11, ymm13);//d = c - (a*b) //B11[3][0-3] -= A11[3][2] * B11[2][0-3] //Perform mul operation of reciprocal of L(3, 3) element with 4rth row elements of B ymm13 = _mm256_mul_pd(ymm13, ymm15); //B11[3][0-3] /= A11[3][3] //--> Transpose and store results of columns of B block <--// ////unpacklow//// ymm1 = _mm256_unpacklo_pd(ymm4, ymm8); //B11[0][0] B11[1][0] B11[0][2] B11[1][2] ymm3 = _mm256_unpacklo_pd(ymm11, ymm13); //B11[2][0] B11[3][0] B11[2][2] B11[3][2] //rearrange low elements ymm0 = _mm256_permute2f128_pd(ymm1,ymm3,0x20); //B11[0][0] B11[1][0] B11[2][0] B11[3][0] ymm2 = _mm256_permute2f128_pd(ymm1,ymm3,0x31); //B11[0][2] B11[1][2] B11[2][2] B11[3][2] ////unpackhigh//// ymm14 = _mm256_unpackhi_pd(ymm4, ymm8); //B11[0][1] B11[1][1] B11[0][3] B11[1][3] ymm15 = _mm256_unpackhi_pd(ymm11, ymm13); //B11[2][1] B11[3][1] B11[2][3] B11[3][3] //rearrange high elements ymm1 = _mm256_permute2f128_pd(ymm14,ymm15,0x20); //B11[0][1] B11[1][1] B11[2][1] B11[3][1] ymm3 = _mm256_permute2f128_pd(ymm14,ymm15,0x31); //B11[0][3] B11[1][3] B11[2][3] B11[3][3] if(3 == n_remainder) { _mm256_storeu_pd((double *)b11, ymm0); //store(B11[0-3][0]) _mm256_storeu_pd((double *)(b11 + (cs_b)), ymm1); //store(B11[0-3][1]) _mm256_storeu_pd((double *)(b11 + cs_b * 2), ymm2); //store(B11[0-3][2]) } else if(2 == n_remainder) { _mm256_storeu_pd((double *)b11, ymm0); //store(B11[0-3][0]) _mm256_storeu_pd((double *)(b11 + (cs_b)), ymm1); //store(B11[0-3][1]) } else if(1 == n_remainder) { _mm256_storeu_pd((double *)b11, ymm0); //store(B11[0-3][0]) } } if(m_remainder) //implementation for remainder rows(when 'M' is not a multiple of D_MR) { a10 = L +i; //pointer to block of A to be used for GEMM a11 = L + i + (i*cs_a); //pointer to block of A to be used for TRSM b01 = B + j*cs_b; //pointer to block of B to be used for GEMM b11 = B + i + j* cs_b; //pointer to block of B to be used for TRSM k_iter = i / D_MR; //number of times GEMM operations to be performed dim_t iter; if((j+n_remainder) == n) { f_temp = f_t; for(iter = 0; iter < m_remainder; iter++) f_temp[iter] = (b11 + cs_b * (n_remainder -1))[iter]; } else f_temp = (b11 + cs_b * (n_remainder -1)); ymm4 = _mm256_setzero_pd(); ymm5 = _mm256_setzero_pd(); ymm6 = _mm256_setzero_pd(); ymm7 = _mm256_setzero_pd(); ///GEMM for previously calculated values /// //load 4x4 block from b11 if(3 == n_remainder) { ymm0 = _mm256_loadu_pd((double const *)(b11)); //B11[0][0] B11[1][0] B11[2][0] B11[3][0] ymm1 = _mm256_loadu_pd((double const *)(b11 + cs_b)); //B11[0][1] B11[1][1] B11[2][1] B11[3][1] ymm2 = _mm256_loadu_pd((double const *)(f_temp)); //B11[0][2] B11[1][2] B11[2][2] B11[3][2] for(k = 0; k < k_iter; k++) //loop for number of GEMM operations { ptr_b01_dup = b01; ymm8 = _mm256_loadu_pd((double const *)(a10)); //A10[0][0] A10[1][0] A10[2][0] A10[3][0] ymm9 = _mm256_loadu_pd((double const *)(a10 + cs_a)); //A10[0][1] A10[1][1] A10[2][1] A10[3][1] ymm10 = _mm256_loadu_pd((double const *)(a10 + cs_a * 2)); //A10[0][2] A10[1][2] A10[2][2] A10[3][2] ymm11 = _mm256_loadu_pd((double const *)(a10 + cs_a * 3)); //A10[0][3] A10[1][3] A10[2][3] A10[3][3] ymm12 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 0)); //B10[0][0] ymm13 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 1)); //B10[0][1] ymm14 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 2)); //B10[0][2] b01 += 1; //move to next row of B ymm4 = _mm256_fmadd_pd(ymm12, ymm8, ymm4); //ymm4 += (B01[0][0]*A10[0][0] B01[0][0]*A10[1][0] B01[0][0]*A10[2][0] B01[0][0]*A10[3][0]) ymm5 = _mm256_fmadd_pd(ymm13, ymm8, ymm5); //ymm5 += (B01[0][1]*A10[0][0] B01[0][1]*A10[1][0] B01[0][1]*A10[2][0] B01[0][1]*A10[3][0]) ymm6 = _mm256_fmadd_pd(ymm14, ymm8, ymm6); //ymm6 += (B01[0][2]*A10[0][0] B01[0][2]*A10[1][0] B01[0][2]*A10[2][0] B01[0][2]*A10[3][0]) ymm12 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 0)); //B10[1][0] ymm13 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 1)); //B10[1][1] ymm14 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 2)); //B10[1][2] b01 += 1; //move to next row of B ymm4 = _mm256_fmadd_pd(ymm12, ymm9, ymm4); //ymm4 += (B01[1][0]*A10[0][1] B01[1][0]*A10[1][1] B01[1][0]*A10[2][1] B01[1][0]*A10[3][1]) ymm5 = _mm256_fmadd_pd(ymm13, ymm9, ymm5); //ymm5 += (B01[1][1]*A10[0][1] B01[1][1]*A10[1][1] B01[1][1]*A10[2][1] B01[1][1]*A10[3][1]) ymm6 = _mm256_fmadd_pd(ymm14, ymm9, ymm6); //ymm6 += (B01[1][2]*A10[0][1] B01[1][2]*A10[1][1] B01[1][2]*A10[2][1] B01[1][2]*A10[3][1]) ymm12 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 0)); //B10[2][0] ymm13 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 1)); //B10[2][1] ymm14 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 2)); //B10[2][2] b01 += 1; //move to next row of B ymm4 = _mm256_fmadd_pd(ymm12, ymm10, ymm4); //ymm4 += (B01[2][0]*A10[0][2] B01[2][0]*A10[1][2] B01[2][0]*A10[2][2] B01[2][0]*A10[3][2]) ymm5 = _mm256_fmadd_pd(ymm13, ymm10, ymm5); //ymm5 += (B01[2][1]*A10[0][2] B01[2][1]*A10[1][2] B01[2][1]*A10[2][2] B01[2][1]*A10[3][2]) ymm6 = _mm256_fmadd_pd(ymm14, ymm10, ymm6); //ymm6 += (B01[2][2]*A10[0][2] B01[2][2]*A10[1][2] B01[2][2]*A10[2][2] B01[2][2]*A10[3][2]) ymm12 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 0)); //B10[3][0] ymm13 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 1)); //B10[3][1] ymm14 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 2)); //B10[3][2] b01 += 1; //move to next row of B ymm4 = _mm256_fmadd_pd(ymm12, ymm11, ymm4); //ymm4 += (B01[3][0]*A10[0][3] B01[3][0]*A10[1][3] B01[3][0]*A10[2][3] B01[3][0]*A10[3][3]) ymm5 = _mm256_fmadd_pd(ymm13, ymm11, ymm5); //ymm5 += (B01[3][1]*A10[0][3] B01[3][1]*A10[1][3] B01[3][1]*A10[2][3] B01[3][1]*A10[3][3]) ymm6 = _mm256_fmadd_pd(ymm14, ymm11, ymm6); //ymm6 += (B01[3][2]*A10[0][3] B01[3][2]*A10[1][3] B01[3][2]*A10[2][3] B01[3][2]*A10[3][3]) a10 += D_MR * cs_a; //pointer math to find next block of A for GEMM b01 = ptr_b01_dup + D_MR; //pointer math to find next block of B for GEMM } ymm15 = _mm256_broadcast_sd((double const *)&AlphaVal); //register to hold alpha value ymm8 = _mm256_fmsub_pd(ymm0, ymm15, ymm4); //B11[0-3][0] * alpha -= ymm4 ymm9 = _mm256_fmsub_pd(ymm1, ymm15, ymm5); //B11[0-3][1] * alpha -= ymm5 ymm10 = _mm256_fmsub_pd(ymm2, ymm15, ymm6); //B11[0-3][2] * alpha -= ymm6 ///implement TRSM/// //determine correct values to store if(3 == m_remainder) { ymm0 = _mm256_blend_pd(ymm8, ymm0, 0x08); ymm1 = _mm256_blend_pd(ymm9, ymm1, 0x08); ymm2 = _mm256_blend_pd(ymm10, ymm2, 0x08); } else if(2 == m_remainder) { ymm0 = _mm256_permute2f128_pd(ymm8, ymm0, 0x30); ymm1 = _mm256_permute2f128_pd(ymm9, ymm1, 0x30); ymm2 = _mm256_permute2f128_pd(ymm10, ymm2, 0x30); } else if(1 == m_remainder) { ymm0 = _mm256_blend_pd(ymm8, ymm0, 0x0E); ymm1 = _mm256_blend_pd(ymm9, ymm1, 0x0E); ymm2 = _mm256_blend_pd(ymm10, ymm2, 0x0E); } _mm256_storeu_pd((double *)b11, ymm0); //store(B11[0-3][0]) _mm256_storeu_pd((double *)(b11 + (cs_b)), ymm1); //store(B11[0-3][1]) _mm256_storeu_pd((double *)(f_temp), ymm2); //store(B11[0-3][2]) } if(2 == n_remainder) { ymm0 = _mm256_loadu_pd((double const *)(b11)); //B11[0][0] B11[1][0] B11[2][0] B11[3][0] ymm1 = _mm256_loadu_pd((double const *)(f_temp)); //B11[0][1] B11[1][1] B11[2][1] B11[3][1] for(k = 0; k < k_iter; k++) //loop for number of GEMM operations { ptr_b01_dup = b01; ymm8 = _mm256_loadu_pd((double const *)(a10)); //A10[0][0] A10[1][0] A10[2][0] A10[3][0] ymm9 = _mm256_loadu_pd((double const *)(a10 + cs_a)); //A10[0][1] A10[1][1] A10[2][1] A10[3][1] ymm10 = _mm256_loadu_pd((double const *)(a10 + cs_a * 2)); //A10[0][2] A10[1][2] A10[2][2] A10[3][2] ymm11 = _mm256_loadu_pd((double const *)(a10 + cs_a * 3)); //A10[0][3] A10[1][3] A10[2][3] A10[3][3] ymm12 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 0)); //B10[0][0] ymm13 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 1)); //B10[0][1] b01 += 1; //move to next row of B ymm4 = _mm256_fmadd_pd(ymm12, ymm8, ymm4); //ymm4 += (B01[0][0]*A10[0][0] B01[0][0]*A10[1][0] B01[0][0]*A10[2][0] B01[0][0]*A10[3][0]) ymm5 = _mm256_fmadd_pd(ymm13, ymm8, ymm5); //ymm5 += (B01[0][1]*A10[0][0] B01[0][1]*A10[1][0] B01[0][1]*A10[2][0] B01[0][1]*A10[3][0]) ymm12 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 0)); //B10[1][0] ymm13 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 1)); //B10[1][1] b01 += 1; //move to next row of B ymm4 = _mm256_fmadd_pd(ymm12, ymm9, ymm4); //ymm4 += (B01[1][0]*A10[0][1] B01[1][0]*A10[1][1] B01[1][0]*A10[2][1] B01[1][0]*A10[3][1]) ymm5 = _mm256_fmadd_pd(ymm13, ymm9, ymm5); //ymm5 += (B01[1][1]*A10[0][1] B01[1][1]*A10[1][1] B01[1][1]*A10[2][1] B01[1][1]*A10[3][1]) ymm12 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 0)); //B10[2][0] ymm13 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 1)); //B10[2][1] b01 += 1; //move to next row of B ymm4 = _mm256_fmadd_pd(ymm12, ymm10, ymm4); //ymm4 += (B01[2][0]*A10[0][2] B01[2][0]*A10[1][2] B01[2][0]*A10[2][2] B01[2][0]*A10[3][2]) ymm5 = _mm256_fmadd_pd(ymm13, ymm10, ymm5); //ymm5 += (B01[2][1]*A10[0][2] B01[2][1]*A10[1][2] B01[2][1]*A10[2][2] B01[2][1]*A10[3][2]) ymm12 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 0)); //B10[3][0] ymm13 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 1)); //B10[3][1] b01 += 1; //move to next row of B ymm4 = _mm256_fmadd_pd(ymm12, ymm11, ymm4); //ymm4 += (B01[3][0]*A10[0][3] B01[3][0]*A10[1][3] B01[3][0]*A10[2][3] B01[3][0]*A10[3][3]) ymm5 = _mm256_fmadd_pd(ymm13, ymm11, ymm5); //ymm5 += (B01[3][1]*A10[0][3] B01[3][1]*A10[1][3] B01[3][1]*A10[2][3] B01[3][1]*A10[3][3]) a10 += D_MR * cs_a; //pointer math to find next block of A for GEMM b01 = ptr_b01_dup + D_MR; //pointer math to find next block of B for GEMM } ymm15 = _mm256_broadcast_sd((double const *)&AlphaVal); //register to hold alpha value ymm8 = _mm256_fmsub_pd(ymm0, ymm15, ymm4); //B11[0-3][0] * alpha -= ymm4 ymm9 = _mm256_fmsub_pd(ymm1, ymm15, ymm5); //B11[0-3][1] * alpha -= ymm5 ///implement TRSM/// //determine correct values to store if(3 == m_remainder) { ymm0 = _mm256_blend_pd(ymm8, ymm0, 0x08); ymm1 = _mm256_blend_pd(ymm9, ymm1, 0x08); } else if(2 == m_remainder) { ymm0 = _mm256_permute2f128_pd(ymm8, ymm0, 0x30); ymm1 = _mm256_permute2f128_pd(ymm9, ymm1, 0x30); } else if(1 == m_remainder) { ymm0 = _mm256_blend_pd(ymm8, ymm0, 0x0E); ymm1 = _mm256_blend_pd(ymm9, ymm1, 0x0E); } _mm256_storeu_pd((double *)b11, ymm0); //store(B11[0-3][0]) _mm256_storeu_pd((double *)(f_temp), ymm1); //store(B11[0-3][1]) } if(n_remainder == 1) { ymm0 = _mm256_loadu_pd((double const *)(f_temp)); //B11[0][0] B11[1][0] B11[2][0] B11[3][0] for(k = 0; k < k_iter; k++) //loop for number of GEMM operations { ptr_b01_dup = b01; ymm8 = _mm256_loadu_pd((double const *)(a10)); //A10[0][0] A10[1][0] A10[2][0] A10[3][0] ymm9 = _mm256_loadu_pd((double const *)(a10 + cs_a)); //A10[0][1] A10[1][1] A10[2][1] A10[3][1] ymm10 = _mm256_loadu_pd((double const *)(a10 + cs_a * 2)); //A10[0][2] A10[1][2] A10[2][2] A10[3][2] ymm11 = _mm256_loadu_pd((double const *)(a10 + cs_a * 3)); //A10[0][3] A10[1][3] A10[2][3] A10[3][3] ymm12 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 0)); //B10[0][0] b01 += 1; //move to next row of B ymm4 = _mm256_fmadd_pd(ymm12, ymm8, ymm4); //ymm4 += (B01[0][0]*A10[0][0] B01[0][0]*A10[1][0] B01[0][0]*A10[2][0] B01[0][0]*A10[3][0]) ymm12 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 0)); //B10[1][0] b01 += 1; //move to next row of B ymm4 = _mm256_fmadd_pd(ymm12, ymm9, ymm4); //ymm4 += (B01[1][0]*A10[0][1] B01[1][0]*A10[1][1] B01[1][0]*A10[2][1] B01[1][0]*A10[3][1]) ymm12 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 0)); //B10[2][0] b01 += 1; //move to next row of B ymm4 = _mm256_fmadd_pd(ymm12, ymm10, ymm4); //ymm4 += (B01[2][0]*A10[0][2] B01[2][0]*A10[1][2] B01[2][0]*A10[2][2] B01[2][0]*A10[3][2]) ymm12 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 0)); //B10[3][0] b01 += 1; //move to next row of B ymm4 = _mm256_fmadd_pd(ymm12, ymm11, ymm4); //ymm4 += (B01[3][0]*A10[0][3] B01[3][0]*A10[1][3] B01[3][0]*A10[2][3] B01[3][0]*A10[3][3]) a10 += D_MR * cs_a; //pointer math to find next block of A for GEMM b01 = ptr_b01_dup + D_MR; //pointer math to find next block of B for GEMM } ymm15 = _mm256_broadcast_sd((double const *)&AlphaVal); //register to hold alpha value ymm8 = _mm256_fmsub_pd(ymm0, ymm15, ymm4); //B11[0-3][0] * alpha -= ymm4 ///implement TRSM/// //determine correct values to store if(3 == m_remainder) { ymm0 = _mm256_blend_pd(ymm8, ymm0, 0x08); } else if(2 == m_remainder) { ymm0 = _mm256_permute2f128_pd(ymm8, ymm0, 0x30); } else if(1 == m_remainder) { ymm0 = _mm256_blend_pd(ymm8, ymm0, 0x0E); } _mm256_storeu_pd((double *)(f_temp), ymm0); //store(B11[0-3][0]) } if((j+n_remainder) == n) { for(iter = 0; iter < m_remainder; iter++) (b11 + cs_b * (n_remainder-1))[iter] = f_temp[iter]; } ///scalar code for trsm without alpha/// dtrsm_small_AlXB(a11, b11, m_remainder, n_remainder, cs_a, cs_b); } } return BLIS_SUCCESS; } /* TRSM for the case AX = alpha * B, Double precision * A is lower-triangular, no-transpose, unit diagonal * dimensions A: mxm X: mxn B: mxn b01---> * ***************** ** * * * * * * * * * * * * * * *b01* * * * * * * * * * * a10 ****** b11 ***************** | * * * | * * * * * | * * * | * * * * * | *a10*a11* | *b11* * * * v * * * v * * * * * *********** ***************** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * **************** ***************** a11---> */ static err_t bli_dtrsm_small_AlXB_unitDiag( side_t side, obj_t* AlphaObj, obj_t* a, obj_t* b, cntx_t* cntx, cntl_t* cntl ) { dim_t D_MR = 4; //size of block along 'M' dimpension dim_t D_NR = 8; //size of block along 'N' dimension dim_t m = bli_obj_length(b); // number of rows of matrix B dim_t n = bli_obj_width(b); // number of columns of matrix B #ifdef BLIS_ENABLE_SMALL_MATRIX_ROME if((m>D_BLIS_SMALL_MATRIX_THRES_TRSM_ALXB_ROME_ROW_PANEL_M && n>D_BLIS_SMALL_MATRIX_THRES_TRSM_ALXB_ROME) || (m> D_BLIS_SMALL_MATRIX_THRES_TRSM_ALXB_ROME && n>D_BLIS_SMALL_MATRIX_THRES_TRSM_ALXB_ROME_COLUMN_PANEL_N) || (m>D_BLIS_SMALL_MATRIX_THRES_TRSM_ALXB_ROME_COLUMN_PANEL_M && n D_BLIS_SMALL_MATRIX_THRES_TRSM_ALXB_NAPLES) { return BLIS_NOT_YET_IMPLEMENTED; } #endif dim_t m_remainder = m & (3); //number of remainder rows dim_t n_remainder = n & (7); //number of remainder columns dim_t cs_a = bli_obj_col_stride(a); // column stride of A dim_t cs_b = bli_obj_col_stride(b); // column stride of B dim_t i, j, k; //loop variables dim_t k_iter; //number of times GEMM to be performed double AlphaVal = *(double *)AlphaObj->buffer; //value of alpha double *L = a->buffer; //pointer to matrix A double *B = b->buffer; //pointer to matrix B double *a10, *a11, *b01, *b11; //pointers that point to blocks for GEMM and TRSM double *ptr_b01_dup; double f_t[4] __attribute__((aligned(64)));//buffer to store corner column when m_remainder !=0 double* f_temp; double ones = 1.0; //scratch registers __m256d ymm0, ymm1, ymm2, ymm3; __m256d ymm4, ymm5, ymm6, ymm7; __m256d ymm8, ymm9, ymm10, ymm11; __m256d ymm12, ymm13, ymm14, ymm15; __m256d ymm16; for(j = 0; j+D_NR-1 < n; j += D_NR) //loop along 'N' dimension { for(i = 0;i+D_MR-1 < m; i += D_MR) //loop along 'M' dimension { a10 = L +i; //pointer to block of A to be used for GEMM a11 = L + i + (i*cs_a); //pointer to block of A to be used for TRSM b01 = B + j*cs_b; //pointer to block of B to be used for GEMM b11 = B + i + j* cs_b; //pointer to block of B to be used for TRSM k_iter = i / D_MR; //number of times GEMM to be performed(in blocks of 4x4) ymm8 = _mm256_setzero_pd(); ymm9 = _mm256_setzero_pd(); ymm10 = _mm256_setzero_pd(); ymm11 = _mm256_setzero_pd(); ymm12 = _mm256_setzero_pd(); ymm13 = _mm256_setzero_pd(); ymm14 = _mm256_setzero_pd(); ymm15 = _mm256_setzero_pd(); ///GEMM code begins/// for(k = 0; k< k_iter; k++) //loop for number of GEMM operations { ptr_b01_dup = b01; ymm16 = _mm256_loadu_pd((double const *)(a10));//A10[0][0] A10[1][0] A10[2][0] A10[3][0] ymm4 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 0)); //B01[0][0] ymm5 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 1)); //B01[0][1] ymm6 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 2)); //B01[0][2] ymm7 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 3)); //B01[0][3] ymm0 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 4)); //B01[0][4] ymm1 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 5)); //B01[0][5] ymm2 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 6)); //B01[0][6] ymm3 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 7)); //B01[0][7] b01 += 1; //mobe to next row of B ymm8 = _mm256_fmadd_pd(ymm4, ymm16, ymm8); //ymm8 += (B01[0][0]*A10[0][0] B01[0][0]*A10[1][0] B01[0][0]*A10[2][0] B01[0][0]*A10[3][0]) ymm9 = _mm256_fmadd_pd(ymm5, ymm16, ymm9); //ymm9 += (B01[0][1]*A10[0][0] B01[0][1]*A10[1][0] B01[0][1]*A10[2][0] B01[0][1]*A10[3][0]) ymm10 = _mm256_fmadd_pd(ymm6, ymm16, ymm10); //ymm10 += (B01[0][2]*A10[0][0] B01[0][2]*A10[1][0] B01[0][2]*A10[2][0] B01[0][2]*A10[3][0]) ymm11 = _mm256_fmadd_pd(ymm7, ymm16, ymm11); //ymm11 += (B01[0][3]*A10[0][0] B01[0][3]*A10[1][0] B01[0][3]*A10[2][0] B01[0][3]*A10[3][0]) ymm12 = _mm256_fmadd_pd(ymm0, ymm16, ymm12); //ymm12 += (B01[0][4]*A10[0][0] B01[0][4]*A10[1][0] B01[0][4]*A10[2][0] B01[0][4]*A10[3][0]) ymm13 = _mm256_fmadd_pd(ymm1, ymm16, ymm13); //ymm13 += (B01[0][5]*A10[0][0] B01[0][5]*A10[1][0] B01[0][5]*A10[2][0] B01[0][5]*A10[3][0]) ymm14 = _mm256_fmadd_pd(ymm2, ymm16, ymm14); //ymm14 += (B01[0][6]*A10[0][0] B01[0][6]*A10[1][0] B01[0][6]*A10[2][0] B01[0][6]*A10[3][0]) ymm15 = _mm256_fmadd_pd(ymm3, ymm16, ymm15); //ymm15 += (B01[0][7]*A10[0][0] B01[0][7]*A10[1][0] B01[0][7]*A10[2][0] B01[0][7]*A10[3][0]) ymm16 = _mm256_loadu_pd((double const *)(a10 + cs_a));//A10[0][1] A10[1][1] A10[2][1] A10[3][1] ymm4 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 0)); //B01[1][0] ymm5 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 1)); //B01[1][1] ymm6 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 2)); //B01[1][2] ymm7 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 3)); //B01[1][3] ymm0 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 4)); //B01[1][4] ymm1 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 5)); //B01[1][5] ymm2 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 6)); //B01[1][6] ymm3 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 7)); //B01[1][7] b01 += 1; //mobe to next row of B ymm8 = _mm256_fmadd_pd(ymm4, ymm16, ymm8); //ymm8 += (B01[1][0]*A10[0][1] B01[1][0]*A10[1][1] B01[1][0]*A10[2][1] B01[1][0]*A10[3][1]) ymm9 = _mm256_fmadd_pd(ymm5, ymm16, ymm9); //ymm9 += (B01[1][1]*A10[0][1] B01[1][1]*A10[1][1] B01[1][1]*A10[2][1] B01[1][1]*A10[3][1]) ymm10 = _mm256_fmadd_pd(ymm6, ymm16, ymm10); //ymm10 += (B01[1][2]*A10[0][1] B01[1][2]*A10[1][1] B01[1][2]*A10[2][1] B01[1][2]*A10[3][1]) ymm11 = _mm256_fmadd_pd(ymm7, ymm16, ymm11); //ymm11 += (B01[1][3]*A10[0][1] B01[1][3]*A10[1][1] B01[1][3]*A10[2][1] B01[1][3]*A10[3][1]) ymm12 = _mm256_fmadd_pd(ymm0, ymm16, ymm12); //ymm12 += (B01[1][4]*A10[0][1] B01[1][4]*A10[1][1] B01[1][4]*A10[2][1] B01[1][4]*A10[3][1]) ymm13 = _mm256_fmadd_pd(ymm1, ymm16, ymm13); //ymm13 += (B01[1][5]*A10[0][1] B01[1][5]*A10[1][1] B01[1][5]*A10[2][1] B01[1][5]*A10[3][1]) ymm14 = _mm256_fmadd_pd(ymm2, ymm16, ymm14); //ymm14 += (B01[1][6]*A10[0][1] B01[1][6]*A10[1][1] B01[1][6]*A10[2][1] B01[1][6]*A10[3][1]) ymm15 = _mm256_fmadd_pd(ymm3, ymm16, ymm15); //ymm15 += (B01[1][7]*A10[0][1] B01[1][7]*A10[1][1] B01[1][7]*A10[2][1] B01[1][7]*A10[3][1]) ymm16 = _mm256_loadu_pd((double const *)(a10 + cs_a * 2));//A10[0][2] A10[1][2] A10[2][2] A10[3][2] ymm4 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 0)); //B01[2][0] ymm5 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 1)); //B01[2][1] ymm6 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 2)); //B01[2][2] ymm7 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 3)); //B01[2][3] ymm0 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 4)); //B01[2][4] ymm1 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 5)); //B01[2][5] ymm2 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 6)); //B01[2][6] ymm3 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 7)); //B01[2][7] b01 += 1; //mobe to next row of B ymm8 = _mm256_fmadd_pd(ymm4, ymm16, ymm8); //ymm8 += (B01[2][0]*A10[0][2] B01[2][0]*A10[1][2] B01[2][0]*A10[2][2] B01[2][0]*A10[3][2]) ymm9 = _mm256_fmadd_pd(ymm5, ymm16, ymm9); //ymm9 += (B01[2][1]*A10[0][2] B01[2][1]*A10[1][2] B01[2][1]*A10[2][2] B01[2][1]*A10[3][2]) ymm10 = _mm256_fmadd_pd(ymm6, ymm16, ymm10); //ymm10 += (B01[2][2]*A10[0][2] B01[2][2]*A10[1][2] B01[2][2]*A10[2][2] B01[2][2]*A10[3][2]) ymm11 = _mm256_fmadd_pd(ymm7, ymm16, ymm11); //ymm11 += (B01[2][3]*A10[0][2] B01[2][3]*A10[1][2] B01[2][3]*A10[2][2] B01[2][3]*A10[3][2]) ymm12 = _mm256_fmadd_pd(ymm0, ymm16, ymm12); //ymm12 += (B01[2][4]*A10[0][2] B01[2][4]*A10[1][2] B01[2][4]*A10[2][2] B01[2][4]*A10[3][2]) ymm13 = _mm256_fmadd_pd(ymm1, ymm16, ymm13); //ymm13 += (B01[2][5]*A10[0][2] B01[2][5]*A10[1][2] B01[2][5]*A10[2][2] B01[2][5]*A10[3][2]) ymm14 = _mm256_fmadd_pd(ymm2, ymm16, ymm14); //ymm14 += (B01[2][6]*A10[0][2] B01[2][6]*A10[1][2] B01[2][6]*A10[2][2] B01[2][6]*A10[3][2]) ymm15 = _mm256_fmadd_pd(ymm3, ymm16, ymm15); //ymm15 += (B01[2][7]*A10[0][2] B01[2][7]*A10[1][2] B01[2][7]*A10[2][2] B01[2][7]*A10[3][2]) ymm16 = _mm256_loadu_pd((double const *)(a10 + cs_a * 3));//A10[0][3] A10[1][3] A10[2][3] A10[3][3] ymm4 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 0)); //B01[3][0] ymm5 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 1)); //B01[3][1] ymm6 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 2)); //B01[3][2] ymm7 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 3)); //B01[3][3] ymm0 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 4)); //B01[3][4] ymm1 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 5)); //B01[3][5] ymm2 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 6)); //B01[3][6] ymm3 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 7)); //B01[3][7] b01 += 1; //mobe to next row of B ymm8 = _mm256_fmadd_pd(ymm4, ymm16, ymm8); //ymm8 += (B01[3][0]*A10[0][3] B01[3][0]*A10[3][0] B01[3][0]*A10[2][3] B01[3][0]*A10[3][0]) ymm9 = _mm256_fmadd_pd(ymm5, ymm16, ymm9); //ymm9 += (B01[3][1]*A10[0][3] B01[3][1]*A10[3][0] B01[3][1]*A10[2][3] B01[3][1]*A10[3][0]) ymm10 = _mm256_fmadd_pd(ymm6, ymm16, ymm10); //ymm10 += (B01[3][2]*A10[0][3] B01[3][2]*A10[3][0] B01[3][2]*A10[2][3] B01[3][2]*A10[3][0]) ymm11 = _mm256_fmadd_pd(ymm7, ymm16, ymm11); //ymm11 += (B01[3][3]*A10[0][3] B01[3][3]*A10[3][0] B01[3][3]*A10[2][3] B01[3][3]*A10[3][0]) ymm12 = _mm256_fmadd_pd(ymm0, ymm16, ymm12); //ymm12 += (B01[3][4]*A10[0][3] B01[3][4]*A10[3][0] B01[3][4]*A10[2][3] B01[3][4]*A10[3][3]) ymm13 = _mm256_fmadd_pd(ymm1, ymm16, ymm13); //ymm13 += (B01[3][5]*A10[0][3] B01[3][5]*A10[3][0] B01[3][5]*A10[2][3] B01[3][5]*A10[3][3]) ymm14 = _mm256_fmadd_pd(ymm2, ymm16, ymm14); //ymm14 += (B01[3][6]*A10[0][3] B01[3][6]*A10[3][0] B01[3][6]*A10[2][3] B01[3][6]*A10[3][3]) ymm15 = _mm256_fmadd_pd(ymm3, ymm16, ymm15); //ymm15 += (B01[3][7]*A10[0][3] B01[3][7]*A10[3][0] B01[3][7]*A10[2][3] B01[3][7]*A10[3][3]) a10 += D_MR * cs_a; //pointer math to calculate next block of A for GEMM b01 = ptr_b01_dup + D_MR; //pointer math to calculate next block of B for GEMM } ymm16 = _mm256_broadcast_sd((double const *)&AlphaVal); //register to hold alpha ymm0 = _mm256_loadu_pd((double const *)(b11 + cs_b *0)); //B11[0][0] B11[1][0] B11[2][0] B11[3][0] ymm1 = _mm256_loadu_pd((double const *)(b11 + cs_b *1)); //B11[0][1] B11[1][1] B11[2][1] B11[3][1] ymm2 = _mm256_loadu_pd((double const *)(b11 + cs_b *2)); //B11[0][2] B11[1][2] B11[2][2] B11[3][2] ymm3 = _mm256_loadu_pd((double const *)(b11 + cs_b *3)); //B11[0][3] B11[1][3] B11[2][3] B11[3][3] ymm4 = _mm256_loadu_pd((double const *)(b11 + cs_b *4)); //B11[0][4] B11[1][4] B11[2][4] B11[3][4] ymm5 = _mm256_loadu_pd((double const *)(b11 + cs_b *5)); //B11[0][5] B11[1][5] B11[2][5] B11[3][5] ymm6 = _mm256_loadu_pd((double const *)(b11 + cs_b *6)); //B11[0][6] B11[1][6] B11[2][6] B11[3][6] ymm7 = _mm256_loadu_pd((double const *)(b11 + cs_b *7)); //B11[0][7] B11[1][7] B11[2][7] B11[3][7] ymm0 = _mm256_fmsub_pd(ymm0, ymm16, ymm8); //B11[0-3][0] * alpha -= B01[0-3][0] ymm1 = _mm256_fmsub_pd(ymm1, ymm16, ymm9); //B11[0-3][1] * alpha -= B01[0-3][1] ymm2 = _mm256_fmsub_pd(ymm2, ymm16, ymm10); //B11[0-3][2] * alpha -= B01[0-3][2] ymm3 = _mm256_fmsub_pd(ymm3, ymm16, ymm11); //B11[0-3][3] * alpha -= B01[0-3][3] ymm4 = _mm256_fmsub_pd(ymm4, ymm16, ymm12); //B11[0-3][4] * alpha -= B01[0-3][4] ymm5 = _mm256_fmsub_pd(ymm5, ymm16, ymm13); //B11[0-3][5] * alpha -= B01[0-3][5] ymm6 = _mm256_fmsub_pd(ymm6, ymm16, ymm14); //B11[0-3][6] * alpha -= B01[0-3][6] ymm7 = _mm256_fmsub_pd(ymm7, ymm16, ymm15); //B11[0-3][7] * alpha -= B01[0-3][7] ///implement TRSM/// ///transpose of B11// ///unpacklow/// ymm9 = _mm256_unpacklo_pd(ymm0, ymm1); //B11[0][0] B11[0][1] B11[2][0] B11[2][1] ymm11 = _mm256_unpacklo_pd(ymm2, ymm3); //B11[0][2] B11[0][3] B11[2][2] B11[2][3] ymm13 = _mm256_unpacklo_pd(ymm4, ymm5); //B11[0][4] B11[0][5] B11[2][4] B11[2][5] ymm15 = _mm256_unpacklo_pd(ymm6, ymm7); //B11[0][6] B11[0][7] B11[2][6] B11[2][7] //rearrange low elements ymm8 = _mm256_permute2f128_pd(ymm9,ymm11,0x20); //B11[0][0] B11[0][1] B11[0][2] B11[0][3] ymm10 = _mm256_permute2f128_pd(ymm9,ymm11,0x31); //B11[2][0] B11[2][1] B11[2][2] B11[2][3] ymm12 = _mm256_permute2f128_pd(ymm13,ymm15,0x20); //B11[4][0] B11[4][1] B11[4][2] B11[4][3] ymm14 = _mm256_permute2f128_pd(ymm13,ymm15,0x31); //B11[6][0] B11[6][1] B11[6][2] B11[6][3] ////unpackhigh//// ymm0 = _mm256_unpackhi_pd(ymm0, ymm1); //B11[1][0] B11[1][1] B11[3][0] B11[3][1] ymm1 = _mm256_unpackhi_pd(ymm2, ymm3); //B11[1][2] B11[1][3] B11[3][2] B11[3][3] ymm4 = _mm256_unpackhi_pd(ymm4, ymm5); //B11[1][4] B11[1][5] B11[3][4] B11[3][5] ymm5 = _mm256_unpackhi_pd(ymm6, ymm7); //B11[1][6] B11[1][7] B11[3][6] B11[3][7] //rearrange high elements ymm9 = _mm256_permute2f128_pd(ymm0,ymm1,0x20); //B11[1][0] B11[1][1] B11[1][2] B11[1][3] ymm11 = _mm256_permute2f128_pd(ymm0,ymm1,0x31); //B11[3][0] B11[3][1] B11[3][2] B11[3][3] ymm13 = _mm256_permute2f128_pd(ymm4,ymm5,0x20); //B11[5][0] B11[5][1] B11[5][2] B11[5][3] ymm15 = _mm256_permute2f128_pd(ymm4,ymm5,0x31); //B11[7][0] B11[7][1] B11[7][2] B11[7][3] ymm2 = _mm256_broadcast_sd((double const *)(a11 +1)); //A11[1][0] ymm3 = _mm256_broadcast_sd((double const *)(a11 +2)); //A11[2][0] ymm4 = _mm256_broadcast_sd((double const *)(a11 +3)); //A11[3][0] a11 += cs_a; //(Row1): FMA operations ymm9 = _mm256_fnmadd_pd(ymm2, ymm8, ymm9); //B11[1][0-3] -= A11[1][0] * B11[0-3][0] ymm10 = _mm256_fnmadd_pd(ymm3, ymm8, ymm10); //B11[2][0-3] -= A11[2][0] * B11[0-3][0] ymm11 = _mm256_fnmadd_pd(ymm4, ymm8, ymm11); //B11[3][0-3] -= A11[3][0] * B11[0-3][0] ymm13 = _mm256_fnmadd_pd(ymm2, ymm12, ymm13); //B11[5][0-3] -= A11[1][0] * B11[0-3][4] ymm14 = _mm256_fnmadd_pd(ymm3, ymm12, ymm14); //B11[6][0-3] -= A11[2][0] * B11[0-3][4] ymm15 = _mm256_fnmadd_pd(ymm4, ymm12, ymm15); //B11[7][0-3] -= A11[3][0] * B11[0-3][4] ymm3 = _mm256_broadcast_sd((double const *)(a11 +2)); //A11[2][1] ymm4 = _mm256_broadcast_sd((double const *)(a11 +3)); //A11[3][1] a11 += cs_a; //(ROw2): FMA operations ymm10 = _mm256_fnmadd_pd(ymm3, ymm9, ymm10); //B11[2][0-3] -= A11[2][1] * B11[0-3][1] ymm11 = _mm256_fnmadd_pd(ymm4, ymm9, ymm11); //B11[3][0-3] -= A11[3][1] * B11[0-3][1] ymm14 = _mm256_fnmadd_pd(ymm3, ymm13, ymm14); //B11[6][0-3] -= A11[2][1] * B11[0-3][5] ymm15 = _mm256_fnmadd_pd(ymm4, ymm13, ymm15); //B11[7][0-3] -= A11[3][1] * B11[0-3][5] ymm4 = _mm256_broadcast_sd((double const *)(a11 +3)); //A11[3][2] a11 += cs_a; //(ROw1): FMA operations ymm11 = _mm256_fnmadd_pd(ymm4, ymm10, ymm11); //B11[3][0-3] -= A11[3][2] * B11[0-3][2] ymm15 = _mm256_fnmadd_pd(ymm4, ymm14, ymm15); //B11[7][0-3] -= A11[3][2] * B11[0-3][6] //unpacklow// ymm1 = _mm256_unpacklo_pd(ymm8, ymm9); //B11[0][0] B11[1][0] B11[0][2] B11[1][2] ymm3 = _mm256_unpacklo_pd(ymm10, ymm11); //B11[2][0] B11[3][0] B11[2][2] B11[3][2] ymm5 = _mm256_unpacklo_pd(ymm12, ymm13); //B11[4][0] B11[5][0] B11[4][2] B11[5][2] ymm7 = _mm256_unpacklo_pd(ymm14, ymm15); //B11[6][0] B11[7][0] B11[6][2] B11[7][2] //rearrange low elements ymm0 = _mm256_permute2f128_pd(ymm1, ymm3, 0x20); //B11[0][0] B11[1][0] B11[2][0] B11[3][0] ymm2 = _mm256_permute2f128_pd(ymm1, ymm3, 0x31); //B11[0][2] B11[1][2] B11[2][2] B11[3][2] ymm4 = _mm256_permute2f128_pd(ymm5, ymm7, 0x20); //B11[4][0] B11[5][0] B11[6][0] B11[7][0] ymm6 = _mm256_permute2f128_pd(ymm5, ymm7, 0x31); //B11[4][2] B11[5][2] B11[6][2] B11[7][2] ///unpack high/// ymm8 = _mm256_unpackhi_pd(ymm8, ymm9); //B11[0][1] B11[1][1] B11[0][3] B11[1][3] ymm9 = _mm256_unpackhi_pd(ymm10, ymm11); //B11[2][1] B11[3][1] B11[2][3] B11[3][3] ymm12 = _mm256_unpackhi_pd(ymm12, ymm13); //B11[4][1] B11[5][1] B11[4][3] B11[5][3] ymm13 = _mm256_unpackhi_pd(ymm14, ymm15); //B11[6][1] B11[7][1] B11[6][3] B11[7][3] //rearrange high elements ymm1 = _mm256_permute2f128_pd(ymm8, ymm9, 0x20); //B11[0][1] B11[1][1] B11[2][1] B11[3][1] ymm3 = _mm256_permute2f128_pd(ymm8, ymm9, 0x31); //B11[0][3] B11[1][3] B11[2][3] B11[3][3] ymm5 = _mm256_permute2f128_pd(ymm12, ymm13, 0x20); //B11[4][1] B11[5][1] B11[6][1] B11[7][1] ymm7 = _mm256_permute2f128_pd(ymm12, ymm13, 0x31); //B11[4][3] B11[5][3] B11[6][3] B11[7][3] _mm256_storeu_pd((double *)(b11 + cs_b * 0), ymm0); //store B11[0][0-3] _mm256_storeu_pd((double *)(b11 + cs_b * 1), ymm1); //store B11[1][0-3] _mm256_storeu_pd((double *)(b11 + cs_b * 2), ymm2); //store B11[2][0-3] _mm256_storeu_pd((double *)(b11 + cs_b * 3), ymm3); //store B11[3][0-3] _mm256_storeu_pd((double *)(b11 + cs_b * 4), ymm4); //store B11[4][0-3] _mm256_storeu_pd((double *)(b11 + cs_b * 5), ymm5); //store B11[5][0-3] _mm256_storeu_pd((double *)(b11 + cs_b * 6), ymm6); //store B11[6][0-3] _mm256_storeu_pd((double *)(b11 + cs_b * 7), ymm7); //store B11[7][0-3] } if(m_remainder) //implementation for reamainder rows(when 'M' is not a multiple of D_MR) { a10 = L +i; //pointer to block of A to be used for GEMM a11 = L + i + (i*cs_a); //pointer to block of A to be used for TRSM b01 = B + j*cs_b; //pointer to block of B to be used for GEMM b11 = B + i + j* cs_b; //pointer to block of B to be used for TRSM k_iter = i / D_MR; //number of times GEMM operation to be done(in blocks of 4x4) dim_t iter; if((j+D_NR) == n) { f_temp = f_t; for(iter = 0; iter < m_remainder; iter++) f_temp[iter] = (b11 + cs_b * 7)[iter]; } else f_temp = (b11 + cs_b * 7); ymm8 = _mm256_setzero_pd(); ymm9 = _mm256_setzero_pd(); ymm10 = _mm256_setzero_pd(); ymm11 = _mm256_setzero_pd(); ymm12 = _mm256_setzero_pd(); ymm13 = _mm256_setzero_pd(); ymm14 = _mm256_setzero_pd(); ymm15 = _mm256_setzero_pd(); ///GEMM code Begins/// for(k = 0; k< k_iter; k++) //loop for number of GEMM operations { ptr_b01_dup = b01; ymm16 = _mm256_loadu_pd((double const *)(a10)); //A10[0][0] A10[1][0] A10[2][0] A10[3][0] ymm4 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 0)); //B01[0][0] ymm5 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 1)); //B01[0][1] ymm6 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 2)); //B01[0][2] ymm7 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 3)); //B01[0][3] ymm0 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 4)); //B01[0][4] ymm1 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 5)); //B01[0][5] ymm2 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 6)); //B01[0][6] ymm3 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 7)); //B01[0][7] b01 += 1; //move to next row of B ymm8 = _mm256_fmadd_pd(ymm4, ymm16, ymm8); //ymm8 += (B01[0][0]*A10[0][0] B01[0][0]*A10[1][0] B01[0][0]*A10[2][0] B01[0][0]*A10[3][0] ) ymm9 = _mm256_fmadd_pd(ymm5, ymm16, ymm9); //ymm9 += (B01[0][1]*A10[0][0] B01[0][1]*A10[1][0] B01[0][1]*A10[2][0] B01[0][1]*A10[3][0]) ymm10 = _mm256_fmadd_pd(ymm6, ymm16, ymm10); //ymm10 += (B01[0][2]*A10[0][0] B01[0][2]*A10[1][0] B01[0][2]*A10[2][0] B01[0][2]*A10[3][0]) ymm11 = _mm256_fmadd_pd(ymm7, ymm16, ymm11); //ymm11 += (B01[0][3]*A10[0][0] B01[0][3]*A10[1][0] B01[0][3]*A10[2][0] B01[0][3]*A10[3][0]) ymm12 = _mm256_fmadd_pd(ymm0, ymm16, ymm12); //ymm12 += (B01[0][4]*A10[0][0] B01[0][4]*A10[1][0] B01[0][4]*A10[2][0] B01[0][4]*A10[3][0]) ymm13 = _mm256_fmadd_pd(ymm1, ymm16, ymm13); //ymm13 += (B01[0][5]*A10[0][0] B01[0][5]*A10[1][0] B01[0][5]*A10[2][0] B01[0][5]*A10[3][0]) ymm14 = _mm256_fmadd_pd(ymm2, ymm16, ymm14); //ymm14 += (B01[0][6]*A10[0][0] B01[0][6]*A10[1][0] B01[0][6]*A10[2][0] B01[0][6]*A10[3][0]) ymm15 = _mm256_fmadd_pd(ymm3, ymm16, ymm15); //ymm16 += (B01[0][7]*A10[0][0] B01[0][7]*A10[1][0] B01[0][7]*A10[2][0] B01[0][7]*A10[3][0]) ymm16 = _mm256_loadu_pd((double const *)(a10 + cs_a * 1)); //A10[0][1] A10[1][1] A10[2][1] A10[3][1] ymm4 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 0)); //B01[1][0] ymm5 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 1)); //B01[1][1] ymm6 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 2)); //B01[1][2] ymm7 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 3)); //B01[1][3] ymm0 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 4)); //B01[1][4] ymm1 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 5)); //B01[1][5] ymm2 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 6)); //B01[1][6] ymm3 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 7)); //B01[1][7] b01 += 1; //move to next row of B01 ymm8 = _mm256_fmadd_pd(ymm4, ymm16, ymm8); //ymm8 += (B01[1][0]*A10[0][1] B01[1][0]*A10[1][1] B01[1][0]*A10[2][1] B01[1][0]*A10[3][1]) ymm9 = _mm256_fmadd_pd(ymm5, ymm16, ymm9); //ymm9 += (B01[1][1]*A10[0][1] B01[1][1]*A10[1][1] B01[1][1]*A10[2][1] B01[1][1]*A10[3][1]) ymm10 = _mm256_fmadd_pd(ymm6, ymm16, ymm10); //ymm10 += (B01[1][2]*A10[0][1] B01[1][2]*A10[1][1] B01[1][2]*A10[2][1] B01[1][2]*A10[3][1]) ymm11 = _mm256_fmadd_pd(ymm7, ymm16, ymm11); //ymm11 += (B01[1][3]*A10[0][1] B01[1][3]*A10[1][1] B01[1][3]*A10[2][1] B01[1][3]*A10[3][1]) ymm12 = _mm256_fmadd_pd(ymm0, ymm16, ymm12); //ymm12 += (B01[1][4]*A10[0][1] B01[1][4]*A10[1][1] B01[1][4]*A10[2][1] B01[1][4]*A10[3][1]) ymm13 = _mm256_fmadd_pd(ymm1, ymm16, ymm13); //ymm13 += (B01[1][5]*A10[0][1] B01[1][5]*A10[1][1] B01[1][5]*A10[2][1] B01[1][5]*A10[3][1]) ymm14 = _mm256_fmadd_pd(ymm2, ymm16, ymm14); //ymm14 += (B01[1][6]*A10[0][1] B01[1][6]*A10[1][1] B01[1][6]*A10[2][1] B01[1][6]*A10[3][1]) ymm15 = _mm256_fmadd_pd(ymm3, ymm16, ymm15); //ymm15 += (B01[1][7]*A10[0][1] B01[1][7]*A10[1][1] B01[1][7]*A10[2][1] B01[1][7]*A10[3][1]) ymm16 = _mm256_loadu_pd((double const *)(a10 + cs_a * 2)); //A10[0][2] //A10[1][2] A10[2][2] A10[3][2] ymm4 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 0)); //B01[2][0] ymm5 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 1)); //B01[2][1] ymm6 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 2)); //B01[2][2] ymm7 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 3)); //B01[2][3] ymm0 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 4)); //B01[2][4] ymm1 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 5)); //B01[2][5] ymm2 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 6)); //B01[2][6] ymm3 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 7)); //B01[2][7] b01 += 1; //move to next row of B ymm8 = _mm256_fmadd_pd(ymm4, ymm16, ymm8); //ymm8 += (B01[2][0]*A10[0][2] B01[2][0]*A10[1][2] B01[2][0]*A10[2][2] B01[2][0]*A10[3][2]) ymm9 = _mm256_fmadd_pd(ymm5, ymm16, ymm9); //ymm9 += (B01[2][1]*A10[0][2] B01[2][1]*A10[1][2] B01[2][1]*A10[2][2] B01[2][1]*A10[3][2]) ymm10 = _mm256_fmadd_pd(ymm6, ymm16, ymm10); //ymm10 += (B01[2][2]*A10[0][2] B01[2][2]*A10[1][2] B01[2][2]*A10[2][2] B01[2][2]*A10[3][2]) ymm11 = _mm256_fmadd_pd(ymm7, ymm16, ymm11); //ymm11 += (B01[2][3]*A10[0][2] B01[2][3]*A10[1][2] B01[2][3]*A10[2][2] B01[2][3]*A10[3][2]) ymm12 = _mm256_fmadd_pd(ymm0, ymm16, ymm12); //ymm12 += (B01[2][4]*A10[0][2] B01[2][4]*A10[1][2] B01[2][4]*A10[2][2] B01[2][0]*A10[3][2]) ymm13 = _mm256_fmadd_pd(ymm1, ymm16, ymm13); //ymm13 += (B01[2][5]*A10[0][2] B01[2][5]*A10[1][2] B01[2][5]*A10[2][2] B01[2][1]*A10[3][2]) ymm14 = _mm256_fmadd_pd(ymm2, ymm16, ymm14); //ymm14 += (B01[2][6]*A10[0][2] B01[2][6]*A10[1][2] B01[2][6]*A10[2][2] B01[2][2]*A10[3][2]) ymm15 = _mm256_fmadd_pd(ymm3, ymm16, ymm15); //ymm15 += (B01[2][7]*A10[0][2] B01[2][7]*A10[1][2] B01[2][7]*A10[2][2] B01[2][3]*A10[3][2]) ymm16 = _mm256_loadu_pd((double const *)(a10 + cs_a * 3)); //A10[0][3] A10[1][3] A10[2][3] A10[3][3] ymm4 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 0)); //B01[3][0] ymm5 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 1)); //B01[3][1] ymm6 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 2)); //B01[3][2] ymm7 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 3)); //B01[3][3] ymm0 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 4)); //B01[3][4] ymm1 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 5)); //B01[3][5] ymm2 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 6)); //B01[3][6] ymm3 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 7)); //B01[3][7] b01 += 1; //move to next row of B ymm8 = _mm256_fmadd_pd(ymm4, ymm16, ymm8); //ymm8 += (B01[3][0]*A10[0][3] B01[3][0]*A10[1][3] B01[3][0]*A10[2][3] B01[3][0]*A10[3][3]) ymm9 = _mm256_fmadd_pd(ymm5, ymm16, ymm9); //ymm8 += (B01[3][1]*A10[0][3] B01[3][1]*A10[1][3] B01[3][1]*A10[2][3] B01[3][1]*A10[3][3]) ymm10 = _mm256_fmadd_pd(ymm6, ymm16, ymm10); //ymm8 += (B01[3][2]*A10[0][3] B01[3][2]*A10[1][3] B01[3][2]*A10[2][3] B01[3][2]*A10[3][3]) ymm11 = _mm256_fmadd_pd(ymm7, ymm16, ymm11); //ymm8 += (B01[3][3]*A10[0][3] B01[3][3]*A10[1][3] B01[3][3]*A10[2][3] B01[3][3]*A10[3][3]) ymm12 = _mm256_fmadd_pd(ymm0, ymm16, ymm12); //ymm8 += (B01[3][0]*A10[0][3] B01[3][4]*A10[1][3] B01[3][4]*A10[2][3] B01[3][4]*A10[3][3]) ymm13 = _mm256_fmadd_pd(ymm1, ymm16, ymm13); //ymm8 += (B01[3][1]*A10[0][3] B01[3][5]*A10[1][3] B01[3][5]*A10[2][3] B01[3][5]*A10[3][3]) ymm14 = _mm256_fmadd_pd(ymm2, ymm16, ymm14); //ymm8 += (B01[3][2]*A10[0][3] B01[3][6]*A10[1][3] B01[3][6]*A10[2][3] B01[3][6]*A10[3][3]) ymm15 = _mm256_fmadd_pd(ymm3, ymm16, ymm15); //ymm8 += (B01[3][3]*A10[0][3] B01[3][7]*A10[1][3] B01[3][7]*A10[2][3] B01[3][7]*A10[3][3]) a10 += D_MR * cs_a; //pointer math to find next block of A for GEMM b01 = ptr_b01_dup + D_MR; //pointer math to find next block of B for GEMM } ///GEMM code ends/// ymm16 = _mm256_broadcast_sd((double const *)&AlphaVal); //register to store alpha value ymm0 = _mm256_loadu_pd((double const *)(b11 + cs_b *0)); //B11[0][0] B11[1][0] B11[2][0] B11[3][0] ymm1 = _mm256_loadu_pd((double const *)(b11 + cs_b *1)); //B11[0][1] B11[1][1] B11[2][1] B11[3][1] ymm2 = _mm256_loadu_pd((double const *)(b11 + cs_b *2)); //B11[0][2] B11[1][2] B11[2][2] B11[3][2] ymm3 = _mm256_loadu_pd((double const *)(b11 + cs_b *3)); //B11[0][3] B11[1][3] B11[2][3] B11[3][3] ymm4 = _mm256_loadu_pd((double const *)(b11 + cs_b *4)); //B11[0][4] B11[1][4] B11[2][4] B11[3][4] ymm5 = _mm256_loadu_pd((double const *)(b11 + cs_b *5)); //B11[0][5] B11[1][5] B11[2][5] B11[3][5] ymm6 = _mm256_loadu_pd((double const *)(b11 + cs_b *6)); //B11[0][6] B11[1][6] B11[2][6] B11[3][6] ymm7 = _mm256_loadu_pd((double const *)(f_temp)); //B11[0][7] B11[1][7] B11[2][7] B11[3][7] ymm0 = _mm256_fmsub_pd(ymm0, ymm16, ymm8); //B11[0-3][0] *alpha -= B01[0-3][0] ymm1 = _mm256_fmsub_pd(ymm1, ymm16, ymm9); //B11[0-3][1] *alpha -= B01[0-3][1] ymm2 = _mm256_fmsub_pd(ymm2, ymm16, ymm10); //B11[0-3][2] *alpha -= B01[0-3][2] ymm3 = _mm256_fmsub_pd(ymm3, ymm16, ymm11); //B11[0-3][3] *alpha -= B01[0-3][3] ymm4 = _mm256_fmsub_pd(ymm4, ymm16, ymm12); //B11[0-3][4] *alpha -= B01[0-3][4] ymm5 = _mm256_fmsub_pd(ymm5, ymm16, ymm13); //B11[0-3][5] *alpha -= B01[0-3][5] ymm6 = _mm256_fmsub_pd(ymm6, ymm16, ymm14); //B11[0-3][6] *alpha -= B01[0-3][6] ymm7 = _mm256_fmsub_pd(ymm7, ymm16, ymm15); //B11[0-3][7] *alpha -= B01[0-3][7] if(3 == m_remainder) { ///implement TRSM/// ///unpacklow/// ymm9 = _mm256_unpacklo_pd(ymm0, ymm1); //B11[0][0] B11[0][1] B11[2][0] B11[2][1] ymm11 = _mm256_unpacklo_pd(ymm2, ymm3); //B11[0][2] B11[0][3] B11[2][2] B11[2][3] ymm13 = _mm256_unpacklo_pd(ymm4, ymm5); //B11[0][4] B11[0][5] B11[1][4] B11[1][5] ymm15 = _mm256_unpacklo_pd(ymm6, ymm7); //B11[0][6] B11[0][7] B11[1][6] B11[1][7] //rearrange low elements ymm8 = _mm256_permute2f128_pd(ymm9,ymm11,0x20); //B11[0][0] B11[0][1] B11[0][2] B11[0][3] ymm10 = _mm256_permute2f128_pd(ymm9,ymm11,0x31); //B11[2][0] B11[2][1] B11[2][2] B11[2][3] ymm12 = _mm256_permute2f128_pd(ymm13,ymm15,0x20); //B11[4][0] B11[4][1] B11[4][2] B11[4][3] ymm14 = _mm256_permute2f128_pd(ymm13,ymm15,0x31); //B11[6][0] B11[6][1] B11[6][2] B11[6][3] ////unpackhigh//// ymm0 = _mm256_unpackhi_pd(ymm0, ymm1); //B11[1][0] B11[1][1] B11[3][0] B11[3][1] ymm1 = _mm256_unpackhi_pd(ymm2, ymm3); //B11[1][2] B11[1][3] B11[3][2] B11[3][3] ymm4 = _mm256_unpackhi_pd(ymm4, ymm5); //B11[5][0] B11[5][1] B11[7][0] B11[7][1] ymm5 = _mm256_unpackhi_pd(ymm6, ymm7); //B11[5][2] B11[5][3] B11[7][2] B11[7][3] //rearrange high elements ymm9 = _mm256_permute2f128_pd(ymm0,ymm1,0x20); //B11[1][0] B11[1][1] B11[1][2] B11[1][3] ymm11 = _mm256_permute2f128_pd(ymm0,ymm1,0x31); //B11[3][0] B11[3][1] B11[3][2] B11[3][3] ymm13 = _mm256_permute2f128_pd(ymm4,ymm5,0x20); //B11[5][0] B11[5][1] B11[5][2] B11[5][3] ymm15 = _mm256_permute2f128_pd(ymm4,ymm5,0x31); //B11[7][0] B11[7][1] B11[7][2] B11[7][3] ymm2 = _mm256_broadcast_sd((double const *)(a11 +1)); //A11[1][0] ymm3 = _mm256_broadcast_sd((double const *)(a11 +2)); //A11[2][0] a11 += cs_a; //(Row1): FMA operations ymm9 = _mm256_fnmadd_pd(ymm2, ymm8, ymm9); //B11[1][0-3] -= B11[0-3][0]*A11[1][0] ymm10 = _mm256_fnmadd_pd(ymm3, ymm8, ymm10); //B11[2][0-3] -= B11[0-3][0]*A11[2][0] ymm13 = _mm256_fnmadd_pd(ymm2, ymm12, ymm13); //B11[5][0-3] -= B11[0-3][4]*A11[1][4] ymm14 = _mm256_fnmadd_pd(ymm3, ymm12, ymm14); //B11[6][0-3] -= B11[0-3][4]*A11[2][4] ymm3 = _mm256_broadcast_sd((double const *)(a11 +2)); //A11[2][1] a11 += cs_a; //(ROw2): FMA operations ymm10 = _mm256_fnmadd_pd(ymm3, ymm9, ymm10); //B11[2][0-3] -= A11[2][1] * B11[0-3][1] ymm14 = _mm256_fnmadd_pd(ymm3, ymm13, ymm14); //B11[6][0-3] -= A11[2][1] * B11[0-3][5] ymm11 = _mm256_broadcast_sd((double const *)(&ones)); ymm15 = _mm256_broadcast_sd((double const *)(&ones)); //unpacklow// ymm1 = _mm256_unpacklo_pd(ymm8, ymm9); //B11[0][0] B11[1][0] B11[0][2] B11[1][2] ymm3 = _mm256_unpacklo_pd(ymm10, ymm11); //B11[2][0] B11[3][0] B11[2][2] B11[3][2] ymm5 = _mm256_unpacklo_pd(ymm12, ymm13); //B11[4][0] B11[5][0] B11[4][2] B11[5][2] ymm7 = _mm256_unpacklo_pd(ymm14, ymm15); //B11[6][0] B11[7][0] B11[6][2] B11[7][2] //rearrange low elements ymm0 = _mm256_permute2f128_pd(ymm1, ymm3, 0x20); //B11[0][0] B11[1][0] B11[2][0] B11[3][0] ymm2 = _mm256_permute2f128_pd(ymm1, ymm3, 0x31); //B11[0][2] B11[1][2] B11[2][2] B11[3][2] ymm4 = _mm256_permute2f128_pd(ymm5, ymm7, 0x20); //B11[0][4] B11[1][4] B11[2][4] B11[3][4] ymm6 = _mm256_permute2f128_pd(ymm5, ymm7, 0x31); //B11[0][6] B11[1][6] B11[2][6] B11[3][6] ///unpack high/// ymm8 = _mm256_unpackhi_pd(ymm8, ymm9); //B11[0][1] B11[1][1] B11[0][3] B11[1][3] ymm9 = _mm256_unpackhi_pd(ymm10, ymm11); //B11[2][1] B11[3][1] B11[2][3] B11[3][3] ymm12 = _mm256_unpackhi_pd(ymm12, ymm13); //B11[0][5] B11[1][5] B11[0][7] B11[1][7] ymm13 = _mm256_unpackhi_pd(ymm14, ymm15); //B11[2][5] B11[3][5] B11[2][7] B11[3][7] //rearrange high elements ymm1 = _mm256_permute2f128_pd(ymm8, ymm9, 0x20); //B11[0][1] B11[1][1] B11[2][1] B11[3][1] ymm3 = _mm256_permute2f128_pd(ymm8, ymm9, 0x31); //B11[0][3] B11[1][3] B11[2][3] B11[3][3] ymm5 = _mm256_permute2f128_pd(ymm12, ymm13, 0x20); //B11[0][5] B11[1][5] B11[2][5] B11[3][5] ymm7 = _mm256_permute2f128_pd(ymm12, ymm13, 0x31); //B11[0][7] B11[1][7] B11[2][7] B11[3][7] ymm8 = _mm256_loadu_pd((double const *)(b11 + cs_b * 0)); //load B11[0-3][0] ymm9 = _mm256_loadu_pd((double const *)(b11 + cs_b * 1)); //load B11[0-3][1] ymm10 = _mm256_loadu_pd((double const *)(b11 + cs_b * 2)); //load B11[0-3][2] ymm11 = _mm256_loadu_pd((double const *)(b11 + cs_b * 3)); //load B11[0-3][3] ymm12 = _mm256_loadu_pd((double const *)(b11 + cs_b * 4)); //load B11[0-3][4] ymm13 = _mm256_loadu_pd((double const *)(b11 + cs_b * 5)); //load B11[0-3][5] ymm14 = _mm256_loadu_pd((double const *)(b11 + cs_b * 6)); //load B11[0-3][6] ymm15 = _mm256_loadu_pd((double const *)(f_temp)); //load B11[0-3][7] //determine correct values to store ymm0 = _mm256_blend_pd(ymm0, ymm8, 0x08); ymm1 = _mm256_blend_pd(ymm1, ymm9, 0x08); ymm2 = _mm256_blend_pd(ymm2, ymm10, 0x08); ymm3 = _mm256_blend_pd(ymm3, ymm11, 0x08); ymm4 = _mm256_blend_pd(ymm4, ymm12, 0x08); ymm5 = _mm256_blend_pd(ymm5, ymm13, 0x08); ymm6 = _mm256_blend_pd(ymm6, ymm14, 0x08); ymm7 = _mm256_blend_pd(ymm7, ymm15, 0x08); } else if(2 == m_remainder) { ///implement TRSM/// ///unpacklow/// ymm9 = _mm256_unpacklo_pd(ymm0, ymm1); //B11[0][0] B11[0][1] B11[2][0] B11[2][1] ymm11 = _mm256_unpacklo_pd(ymm2, ymm3); //B11[0][2] B11[0][3] B11[2][2] B11[2][3] ymm13 = _mm256_unpacklo_pd(ymm4, ymm5); //B11[0][4] B11[0][5] B11[1][4] B11[1][5] ymm15 = _mm256_unpacklo_pd(ymm6, ymm7); //B11[0][6] B11[0][7] B11[1][6] B11[1][7] //rearrange low elements ymm8 = _mm256_permute2f128_pd(ymm9,ymm11,0x20); //B11[0][0] B11[0][1] B11[0][2] B11[0][3] ymm10 = _mm256_permute2f128_pd(ymm9,ymm11,0x31); //B11[2][0] B11[2][1] B11[2][2] B11[2][3] ymm12 = _mm256_permute2f128_pd(ymm13,ymm15,0x20); //B11[4][0] B11[4][1] B11[4][2] B11[4][3] ymm14 = _mm256_permute2f128_pd(ymm13,ymm15,0x31); //B11[6][0] B11[6][1] B11[6][2] B11[6][3] ////unpackhigh//// ymm0 = _mm256_unpackhi_pd(ymm0, ymm1); //B11[1][0] B11[1][1] B11[3][0] B11[3][1] ymm1 = _mm256_unpackhi_pd(ymm2, ymm3); //B11[1][2] B11[1][3] B11[3][2] B11[3][3] ymm4 = _mm256_unpackhi_pd(ymm4, ymm5); //B11[5][0] B11[5][1] B11[7][0] B11[7][1] ymm5 = _mm256_unpackhi_pd(ymm6, ymm7); //B11[5][2] B11[5][3] B11[7][2] B11[7][3] //rearrange high elements ymm9 = _mm256_permute2f128_pd(ymm0,ymm1,0x20); //B11[1][0] B11[1][1] B11[1][2] B11[1][3] ymm11 = _mm256_permute2f128_pd(ymm0,ymm1,0x31); //B11[3][0] B11[3][1] B11[3][2] B11[3][3] ymm13 = _mm256_permute2f128_pd(ymm4,ymm5,0x20); //B11[5][0] B11[5][1] B11[5][2] B11[5][3] ymm15 = _mm256_permute2f128_pd(ymm4,ymm5,0x31); //B11[7][0] B11[7][1] B11[7][2] B11[7][3] ymm2 = _mm256_broadcast_sd((double const *)(a11 +1)); //A11[1][0] a11 += cs_a; //(Row1): FMA operations ymm9 = _mm256_fnmadd_pd(ymm2, ymm8, ymm9); //B11[1][0-3] -= B11[0-3][0]*A11[1][0] ymm13 = _mm256_fnmadd_pd(ymm2, ymm12, ymm13); //B11[5][0-3] -= B11[0-3][4]*A11[1][4] ymm10 = _mm256_broadcast_sd((double const *)&ones); //unpacklow// ymm1 = _mm256_unpacklo_pd(ymm8, ymm9); //B11[0][0] B11[1][0] B11[0][2] B11[1][2] ymm5 = _mm256_unpacklo_pd(ymm12, ymm13); //B11[4][0] B11[5][0] B11[4][2] B11[5][2] //rearrange low elements ymm0 = _mm256_permute2f128_pd(ymm1, ymm10, 0x20); //B11[0][0] B11[1][0] B11[2][0] B11[3][0] ymm2 = _mm256_permute2f128_pd(ymm1, ymm10, 0x31); //B11[0][2] B11[1][2] B11[2][2] B11[3][2] ymm4 = _mm256_permute2f128_pd(ymm5, ymm10, 0x20); //B11[0][4] B11[1][4] B11[2][4] B11[3][4] ymm6 = _mm256_permute2f128_pd(ymm5, ymm10, 0x31); //B11[0][6] B11[1][6] B11[2][6] B11[3][6] ///unpack high/// ymm8 = _mm256_unpackhi_pd(ymm8, ymm9); //B11[0][1] B11[1][1] B11[0][3] B11[1][3] ymm12 = _mm256_unpackhi_pd(ymm12, ymm13); //B11[0][5] B11[1][5] B11[0][7] B11[1][7] //rearrange high elements ymm1 = _mm256_permute2f128_pd(ymm8, ymm10, 0x20); //B11[0][1] B11[1][1] B11[2][1] B11[3][1] ymm3 = _mm256_permute2f128_pd(ymm8, ymm10, 0x31); //B11[0][3] B11[1][3] B11[2][3] B11[3][3] ymm5 = _mm256_permute2f128_pd(ymm12, ymm10, 0x20); //B11[0][5] B11[1][5] B11[2][5] B11[3][5] ymm7 = _mm256_permute2f128_pd(ymm12, ymm10, 0x31); //B11[0][7] B11[1][7] B11[2][7] B11[3][7] ymm8 = _mm256_loadu_pd((double const *)(b11 + cs_b * 0)); //load B11[0-3][0] ymm9 = _mm256_loadu_pd((double const *)(b11 + cs_b * 1)); //load B11[0-3][1] ymm10 = _mm256_loadu_pd((double const *)(b11 + cs_b * 2)); //load B11[0-3][2] ymm11 = _mm256_loadu_pd((double const *)(b11 + cs_b * 3)); //load B11[0-3][3] ymm12 = _mm256_loadu_pd((double const *)(b11 + cs_b * 4)); //load B11[0-3][4] ymm13 = _mm256_loadu_pd((double const *)(b11 + cs_b * 5)); //load B11[0-3][5] ymm14 = _mm256_loadu_pd((double const *)(b11 + cs_b * 6)); //load B11[0-3][6] ymm15 = _mm256_loadu_pd((double const *)(f_temp)); //load B11[0-3][7] //determine correct values to store ymm0 = _mm256_permute2f128_pd(ymm0, ymm8, 0x30); ymm1 = _mm256_permute2f128_pd(ymm1, ymm9, 0x30); ymm2 = _mm256_permute2f128_pd(ymm2, ymm10, 0x30); ymm3 = _mm256_permute2f128_pd(ymm3, ymm11, 0x30); ymm4 = _mm256_permute2f128_pd(ymm4, ymm12, 0x30); ymm5 = _mm256_permute2f128_pd(ymm5, ymm13, 0x30); ymm6 = _mm256_permute2f128_pd(ymm6, ymm14, 0x30); ymm7 = _mm256_permute2f128_pd(ymm7, ymm15, 0x30); } else if(1 == m_remainder) { ymm8 = _mm256_loadu_pd((double const *)(b11 + cs_b * 0)); //load B11[0-3][0] ymm9 = _mm256_loadu_pd((double const *)(b11 + cs_b * 1)); //load B11[0-3][1] ymm10 = _mm256_loadu_pd((double const *)(b11 + cs_b * 2)); //load B11[0-3][2] ymm11 = _mm256_loadu_pd((double const *)(b11 + cs_b * 3)); //load B11[0-3][3] ymm12 = _mm256_loadu_pd((double const *)(b11 + cs_b * 4)); //load B11[0-3][4] ymm13 = _mm256_loadu_pd((double const *)(b11 + cs_b * 5)); //load B11[0-3][5] ymm14 = _mm256_loadu_pd((double const *)(b11 + cs_b * 6)); //load B11[0-3][6] ymm15 = _mm256_loadu_pd((double const *)(f_temp)); //load B11[0-3][7] //determine correct values to store ymm0 = _mm256_blend_pd(ymm0, ymm8, 0x0E); ymm1 = _mm256_blend_pd(ymm1, ymm9, 0x0E); ymm2 = _mm256_blend_pd(ymm2, ymm10, 0x0E); ymm3 = _mm256_blend_pd(ymm3, ymm11, 0x0E); ymm4 = _mm256_blend_pd(ymm4, ymm12, 0x0E); ymm5 = _mm256_blend_pd(ymm5, ymm13, 0x0E); ymm6 = _mm256_blend_pd(ymm6, ymm14, 0x0E); ymm7 = _mm256_blend_pd(ymm7, ymm15, 0x0E); } _mm256_storeu_pd((double *)(b11 + cs_b * 0), ymm0); //store(B11[0-3][0]) _mm256_storeu_pd((double *)(b11 + cs_b * 1), ymm1); //store(B11[0-3][1]) _mm256_storeu_pd((double *)(b11 + cs_b * 2), ymm2); //store(B11[0-3][2]) _mm256_storeu_pd((double *)(b11 + cs_b * 3), ymm3); //store(B11[0-3][3]) _mm256_storeu_pd((double *)(b11 + cs_b * 4), ymm4); //store(B11[0-3][4]) _mm256_storeu_pd((double *)(b11 + cs_b * 5), ymm5); //store(B11[0-3][5]) _mm256_storeu_pd((double *)(b11 + cs_b * 6), ymm6); //store(B11[0-3][6]) _mm256_storeu_pd((double *)(f_temp), ymm7); //store(B11[0-3][7]) if((j+D_NR) == n) { for(iter = 0; iter < m_remainder; iter++) (b11 + cs_b * 7)[iter] = f_temp[iter]; } } } if((n & 4)) //implementation for remainder columns(when 'n_remainder' is greater than 4) { for(i = 0;i+D_MR-1 < m; i += D_MR) //loop along 'M' direction { a10 = L +i; //pointer to block of A to be used for GEMM a11 = L + i + (i*cs_a); //pointer to block of A to be used for TRSM b01 = B + j*cs_b; //pointer to block of B to be used for GEMM b11 = B + i + j* cs_b; //pointer to block of B to be used for TRSM k_iter = i / D_MR; //number of times GEMM to be performed(in block of 4) ///GEMM for previously calculated values /// //load 4x4 block from b11 ymm0 = _mm256_loadu_pd((double const *)(b11)); //B11[0][0] B11[1][0] B11[2][0] B11[3][0] ymm1 = _mm256_loadu_pd((double const *)(b11 + cs_b)); //B11[0][1] B11[1][1] B11[2][1] B11[3][1] ymm2 = _mm256_loadu_pd((double const *)(b11 + cs_b*2)); //B11[0][2] B11[1][2] B11[2][2] B11[3][2] ymm3 = _mm256_loadu_pd((double const *)(b11 + cs_b*3)); //B11[0][3] B11[1][3] B11[2][3] B11[3][3] ymm4 = _mm256_setzero_pd(); ymm5 = _mm256_setzero_pd(); ymm6 = _mm256_setzero_pd(); ymm7 = _mm256_setzero_pd(); for(k = 0; k < k_iter; k++) //loop for number of GEMM operations { ptr_b01_dup = b01; ymm8 = _mm256_loadu_pd((double const *)(a10)); //A10[0][0] A10[1][0] A10[2][0] A10[3][0] ymm9 = _mm256_loadu_pd((double const *)(a10 + cs_a)); //A10[0][1] A10[1][1] A10[2][1] A10[3][1] ymm10 = _mm256_loadu_pd((double const *)(a10 + cs_a*2)); //A10[0][2] A10[1][2] A10[2][2] A10[3][2] ymm11 = _mm256_loadu_pd((double const *)(a10 + cs_a * 3)); //A10[0][3] A10[1][3] A10[2][3] A10[3][3] ymm12 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 0)); //B01[0][0] ymm13 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 1)); //B01[0][1] ymm14 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 2)); //B01[0][2] ymm15 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 3)); //B01[0][3] b01 += 1; //move to next row of B ymm4 = _mm256_fmadd_pd(ymm12, ymm8, ymm4); //ymm4 += (B01[0][0]*A10[0][0] B01[0][0]*A10[1][0] B01[0][0]*A10[2][0] B01[0][0]*A10[3][0]) ymm5 = _mm256_fmadd_pd(ymm13, ymm8, ymm5); //ymm5 += (B01[0][1]*A10[0][0] B01[0][1]*A10[1][0] B01[0][1]*A10[2][0] B01[0][1]*A10[3][0]) ymm6 = _mm256_fmadd_pd(ymm14, ymm8, ymm6); //ymm6 += (B01[0][2]*A10[0][0] B01[0][2]*A10[1][0] B01[0][2]*A10[2][0] B01[0][2]*A10[3][0]) ymm7 = _mm256_fmadd_pd(ymm15, ymm8, ymm7); //ymm7 += (B01[0][3]*A10[0][0] B01[0][3]*A10[1][0] B01[0][3]*A10[2][0] B01[0][3]*A10[3][0]) ymm12 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 0)); //B01[1][0] ymm13 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 1)); //B01[1][1] ymm14 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 2)); //B01[1][2] ymm15 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 3)); //B01[1][3] b01 += 1; ymm4 = _mm256_fmadd_pd(ymm12, ymm9, ymm4); //ymm4 += (B01[1][0]*A10[0][1] B01[1][0]*A10[1][1] B01[1][0]*A10[2][1] B01[1][0]*A10[3][1]) ymm5 = _mm256_fmadd_pd(ymm13, ymm9, ymm5); //ymm5 += (B01[1][1]*A10[0][1] B01[1][1]*A10[1][1] B01[1][1]*A10[2][1] B01[1][1]*A10[3][1]) ymm6 = _mm256_fmadd_pd(ymm14, ymm9, ymm6); //ymm6 += (B01[1][2]*A10[0][1] B01[1][2]*A10[1][1] B01[1][2]*A10[2][1] B01[1][2]*A10[3][1]) ymm7 = _mm256_fmadd_pd(ymm15, ymm9, ymm7); //ymm7 += (B01[1][3]*A10[0][1] B01[1][3]*A10[1][1] B01[1][3]*A10[2][1] B01[1][3]*A10[3][1]) ymm12 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 0)); //B01[2][0] ymm13 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 1)); //B01[2][1] ymm14 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 2)); //B01[2][2] ymm15 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 3)); //B01[2][3] b01 += 1; ymm4 = _mm256_fmadd_pd(ymm12, ymm10, ymm4); //ymm4 += (B01[2][0]*A10[0][2] B01[2][0]*A10[1][2] B01[2][0]*A10[2][2] B01[2][0]*A10[3][2]) ymm5 = _mm256_fmadd_pd(ymm13, ymm10, ymm5); //ymm5 += (B01[2][1]*A10[1][2] B01[2][1]*A10[1][2] B01[2][1]*A10[2][2] B01[2][1]*A10[3][2]) ymm6 = _mm256_fmadd_pd(ymm14, ymm10, ymm6); //ymm6 += (B01[2][2]*A10[2][2] B01[2][2]*A10[1][2] B01[2][2]*A10[2][2] B01[2][2]*A10[3][2]) ymm7 = _mm256_fmadd_pd(ymm15, ymm10, ymm7); //ymm7 += (B01[2][3]*A10[3][2] B01[2][3]*A10[1][2] B01[2][3]*A10[2][2] B01[2][3]*A10[3][2]) ymm12 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 0)); //B01[3][0] ymm13 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 1)); //B01[3][1] ymm14 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 2)); //B01[3][2] ymm15 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 3)); //B01[3][3] b01 += 1; ymm4 = _mm256_fmadd_pd(ymm12, ymm11, ymm4); //ymm4 += (B01[3][0]*A10[0][3] B01[3][0]*A10[1][3] B01[3][0]*A10[2][3] B01[3][0]*A10[3][3]) ymm5 = _mm256_fmadd_pd(ymm13, ymm11, ymm5); //ymm5 += (B01[3][1]*A10[0][3] B01[3][1]*A10[1][3] B01[3][1]*A10[2][3] B01[3][1]*A10[3][3]) ymm6 = _mm256_fmadd_pd(ymm14, ymm11, ymm6); //ymm6 += (B01[3][2]*A10[0][3] B01[3][2]*A10[1][3] B01[3][2]*A10[2][3] B01[3][2]*A10[3][3]) ymm7 = _mm256_fmadd_pd(ymm15, ymm11, ymm7); //ymm7 += (B01[3][3]*A10[0][3] B01[3][3]*A10[1][3] B01[3][3]*A10[2][3] B01[3][3]*A10[3][3]) a10 += D_MR * cs_a; //pointer math to find next block of A for GEMM b01 = ptr_b01_dup + D_MR; //pointer math to find next block of B for GEMM } ymm15 = _mm256_broadcast_sd((double const *)&AlphaVal); //register to store alpha ymm0 = _mm256_fmsub_pd(ymm0, ymm15, ymm4); //B11[0-3][0] *alpha -= ymm4 ymm1 = _mm256_fmsub_pd(ymm1, ymm15, ymm5); //B01[0-3][1] *alpha -= ymm5 ymm2 = _mm256_fmsub_pd(ymm2, ymm15, ymm6); //B01[0-3][2] *alpha -= ymm6 ymm3 = _mm256_fmsub_pd(ymm3, ymm15, ymm7); //B01[0-3][3] *alpha -= ymm7 ///implement TRSM/// //1st col ymm5 = _mm256_broadcast_sd((double const *)(a11+1)); //A11[1][0] ymm6 = _mm256_broadcast_sd((double const *)(a11+2)); //A11[2][0] ymm7 = _mm256_broadcast_sd((double const *)(a11+3)); //A11[3][0] //2nd col a11 += cs_a; ymm9 = _mm256_broadcast_sd((double const *)(a11 + 2)); //A11[2][1] ymm10 = _mm256_broadcast_sd((double const *)(a11 + 3)); //A11[3][1] //3rd col a11 += cs_a; ymm12 = _mm256_broadcast_sd((double const *)(a11 + 3)); //A11[3][2] ////unpacklow//// ymm8 = _mm256_unpacklo_pd(ymm0, ymm1); //B11[0][0] B11[0][1] B11[2][0] B11[2][1] ymm13 = _mm256_unpacklo_pd(ymm2, ymm3); //B11[0][2] B11[0][3] B11[2][2] B11[2][3] //rearrange low elements ymm4 = _mm256_permute2f128_pd(ymm8,ymm13,0x20); //B11[0][0] B11[0][1] B11[0][2] B11[0][3] ymm11 = _mm256_permute2f128_pd(ymm8,ymm13,0x31);//B11[2][0] B11[2][1] B11[2][2] B11[2][3] ////unpackhigh//// ymm0 = _mm256_unpackhi_pd(ymm0, ymm1); //B11[1][0] B11[1][1] B11[3][0] B11[3][1] ymm1 = _mm256_unpackhi_pd(ymm2, ymm3); //B11[1][2] B11[1][3] B11[3][2] B11[3][3] //rearrange high elements ymm8 = _mm256_permute2f128_pd(ymm0,ymm1,0x20); //B11[1][0] B11[1][1] B11[1][2] B11[1][3] ymm13 = _mm256_permute2f128_pd(ymm0,ymm1,0x31); //B11[3][0] B11[3][1] B11[3][2] B11[3][3] //(Row1): FMA operations of b1 with elements of indices from (1, 0) uptill (3, 0) ymm8 = _mm256_fnmadd_pd(ymm5, ymm4, ymm8);//d = c - (a*b) //B11[1][0-3] -= A11[1][0]*B11[0][0-3] ymm11 = _mm256_fnmadd_pd(ymm6, ymm4, ymm11);//d = c - (a*b) //B11[2][0-3] -= A11[2][0]*B11[0][0-3] ymm13 = _mm256_fnmadd_pd(ymm7, ymm4, ymm13);//d = c - (a*b) //B11[3][0-3] -= A11[3][0]*B11[0][0-3] //(Row2): FMA operations of b2 with elements of indices from (2, 0) uptill (7, 0) ymm11 = _mm256_fnmadd_pd(ymm9, ymm8, ymm11);//d = c - (a*b) //B11[2][0-3] -= A11[2][1]*B11[1][0-3] ymm13 = _mm256_fnmadd_pd(ymm10, ymm8, ymm13);//d = c - (a*b) //B11[3][0-3] -= A11[3][1]*B11[1][0-3] //(Row3): FMA operations of b3 with elements of indices from (3, 0) uptill (7, 0) ymm13 = _mm256_fnmadd_pd(ymm12, ymm11, ymm13);//d = c - (a*b) //B11[3][0-3] -= A11[3][2]*B11[2][0-3] //--> Transpose and store results of columns of B block <--// ////unpacklow//// ymm1 = _mm256_unpacklo_pd(ymm4, ymm8); //B11[0][0] B11[1][0] B11[0][2] B11[1][2] ymm3 = _mm256_unpacklo_pd(ymm11, ymm13); //B11[2][0] B11[3][0] B11[2][2] B11[3][2] //rearrange low elements ymm0 = _mm256_permute2f128_pd(ymm1,ymm3,0x20); //B11[0][0] B11[1][0] B11[2][0] B11[3][0] ymm2 = _mm256_permute2f128_pd(ymm1,ymm3,0x31); //B11[0][2] B11[1][2] B11[2][2] B11[3][2] ////unpackhigh//// ymm14 = _mm256_unpackhi_pd(ymm4, ymm8); //B11[0][1] B11[1][1] B11[0][3] B11[1][3] ymm15 = _mm256_unpackhi_pd(ymm11, ymm13); //B11[2][1] B11[3][1] B11[2][3] B11[3][3] //rearrange high elements ymm1 = _mm256_permute2f128_pd(ymm14,ymm15,0x20); //B11[0][1] B11[1][1] B11[2][1] B11[3][1] ymm3 = _mm256_permute2f128_pd(ymm14,ymm15,0x31); //B11[0][3] B11[1][3] B11[2][3] B11[3][3] _mm256_storeu_pd((double *)b11, ymm0); //store(B11[0-3][0]) _mm256_storeu_pd((double *)(b11 + (cs_b)), ymm1); //store(B11[0-3][1]) _mm256_storeu_pd((double *)(b11 + cs_b*2), ymm2); //store(B11[0-3][2]) _mm256_storeu_pd((double *)(b11 + cs_b*3), ymm3); //store(B11[0-3][3]) } if(m_remainder) //implementation for remainder rows(when 'M' is not a multiple of D_MR) { a10 = L +i; //pointer to block of A to be used for GEMM a11 = L + i + (i*cs_a); //pointer to block of A to be used for TRSM b01 = B + j*cs_b; //pointer to block of B to be used for GEMM b11 = B + i + j* cs_b; //pointer to block of B to be used for TRSM k_iter = i / D_MR; //number of GEMM operations to be performed(in blocks of 4x4) dim_t iter; if((j+4) == n) { f_temp = f_t; for(iter = 0; iter < m_remainder; iter++) f_temp[iter] = (b11 + cs_b * 3)[iter]; } else f_temp = (b11 + cs_b * 3); ///GEMM for previously calculated values /// //load 4x4 block from b11 ymm0 = _mm256_loadu_pd((double const *)(b11)); //B11[0][0] B11[1][0] B11[2][0] B11[3][0] ymm1 = _mm256_loadu_pd((double const *)(b11 + cs_b)); //B11[0][1] B11[1][1] B11[2][1] B11[3][1] ymm2 = _mm256_loadu_pd((double const *)(b11 + cs_b * 2)); //B11[0][2] B11[1][2] B11[2][2] B11[3][2] ymm3 = _mm256_loadu_pd((double const *)(f_temp)); //B11[0][3] B11[1][3] B11[2][3] B11[3][3] ymm4 = _mm256_setzero_pd(); ymm5 = _mm256_setzero_pd(); ymm6 = _mm256_setzero_pd(); ymm7 = _mm256_setzero_pd(); for(k = 0; k < k_iter; k++) //looop for number of GEMM operations { ptr_b01_dup = b01; ymm8 = _mm256_loadu_pd((double const *)(a10)); //A10[0][0] A10[1][0] A10[2][0] A10[3][0] ymm9 = _mm256_loadu_pd((double const *)(a10 + cs_a)); //A10[0][1] A10[1][1] A10[2][1] A10[3][1] ymm10 = _mm256_loadu_pd((double const *)(a10 + cs_a * 2)); //A10[0][2] A10[1][2] A10[2][2] A10[3][2] ymm11 = _mm256_loadu_pd((double const *)(a10 + cs_a * 3)); //A10[0][3] A10[1][3] A10[2][3] A10[3][3] ymm12 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 0)); //B01[0][0] ymm13 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 1)); //B01[0][1] ymm14 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 2)); //B01[0][2] ymm15 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 3)); //B01[0][3] b01 += 1; ymm4 = _mm256_fmadd_pd(ymm12, ymm8, ymm4); //ymm4 += (B01[0][0]*A10[0][0] B01[0][0]*A10[1][0] B01[0][0]*A10[2][0] B01[0][0]*A10[3][0]) ymm5 = _mm256_fmadd_pd(ymm13, ymm8, ymm5); //ymm5 += (B01[0][1]*A10[0][0] B01[0][1]*A10[1][0] B01[0][1]*A10[2][0] B01[0][1]*A10[3][0]) ymm6 = _mm256_fmadd_pd(ymm14, ymm8, ymm6); //ymm6 += (B01[0][2]*A10[0][0] B01[0][2]*A10[1][0] B01[0][2]*A10[2][0] B01[0][2]*A10[3][0]) ymm7 = _mm256_fmadd_pd(ymm15, ymm8, ymm7); //ymm7 += (B01[0][3]*A10[0][0] B01[0][3]*A10[1][0] B01[0][3]*A10[2][0] B01[0][3]*A10[3][0]) ymm12 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 0)); //B01[1][0] ymm13 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 1)); //B01[1][1] ymm14 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 2)); //B01[1][2] ymm15 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 3)); //B01[1][3] b01 += 1; ymm4 = _mm256_fmadd_pd(ymm12, ymm9, ymm4); //ymm4 += (B01[1][0]*A10[0][1] B01[1][0]*A10[1][1] B01[1][0]*A10[2][1] B01[1][0]*A10[3][1]) ymm5 = _mm256_fmadd_pd(ymm13, ymm9, ymm5); //ymm5 += (B01[1][1]*A10[0][1] B01[1][1]*A10[1][1] B01[1][1]*A10[2][1] B01[1][1]*A10[3][1]) ymm6 = _mm256_fmadd_pd(ymm14, ymm9, ymm6); //ymm6 += (B01[1][2]*A10[0][1] B01[1][2]*A10[1][1] B01[1][2]*A10[2][1] B01[1][2]*A10[3][1]) ymm7 = _mm256_fmadd_pd(ymm15, ymm9, ymm7); //ymm7 += (B01[1][3]*A10[0][1] B01[1][3]*A10[1][1] B01[1][3]*A10[2][1] B01[1][3]*A10[3][1]) ymm12 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 0)); //B01[2][0] ymm13 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 1)); //B01[2][1] ymm14 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 2)); //B01[2][2] ymm15 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 3)); //B01[2][3] b01 += 1; ymm4 = _mm256_fmadd_pd(ymm12, ymm10, ymm4); //ymm4 += (B01[2][0]*A10[0][2] B01[2][0]*A10[1][2] B01[2][0]*A10[2][2] B01[2][0]*A10[3][2]) ymm5 = _mm256_fmadd_pd(ymm13, ymm10, ymm5); //ymm5 += (B01[2][1]*A10[0][2] B01[2][1]*A10[1][2] B01[2][1]*A10[2][2] B01[2][1]*A10[3][2]) ymm6 = _mm256_fmadd_pd(ymm14, ymm10, ymm6); //ymm6 += (B01[2][2]*A10[0][2] B01[2][2]*A10[1][2] B01[2][2]*A10[2][2] B01[2][2]*A10[3][2]) ymm7 = _mm256_fmadd_pd(ymm15, ymm10, ymm7); //ymm7 += (B01[2][3]*A10[0][2] B01[2][3]*A10[1][2] B01[2][3]*A10[2][2] B01[2][3]*A10[3][2]) ymm12 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 0)); //B01[3][0] ymm13 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 1)); //B01[3][1] ymm14 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 2)); //B01[3][2] ymm15 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 3)); //B01[3][3] b01 += 1; ymm4 = _mm256_fmadd_pd(ymm12, ymm11, ymm4); //ymm4 += (B01[3][0]*A10[0][3] B01[3][0]*A10[1][3] B01[3][0]*A10[2][3] B01[3][0]*A10[3][3]) ymm5 = _mm256_fmadd_pd(ymm13, ymm11, ymm5); //ymm5 += (B01[3][1]*A10[0][3] B01[3][1]*A10[1][3] B01[3][1]*A10[2][3] B01[3][1]*A10[3][3]) ymm6 = _mm256_fmadd_pd(ymm14, ymm11, ymm6); //ymm6 += (B01[3][2]*A10[0][3] B01[3][2]*A10[1][3] B01[3][2]*A10[2][3] B01[3][2]*A10[3][3]) ymm7 = _mm256_fmadd_pd(ymm15, ymm11, ymm7); //ymm7 += (B01[3][3]*A10[0][3] B01[3][3]*A10[1][3] B01[3][3]*A10[2][3] B01[3][3]*A10[3][3]) a10 += D_MR * cs_a; //pointer math to find next block of A for GEMM b01 = ptr_b01_dup + D_MR; //pointer math to find next block of B for GEMM } ymm15 = _mm256_broadcast_sd((double const *)&AlphaVal); //register to store alpha ymm0 = _mm256_fmsub_pd(ymm0, ymm15, ymm4); //B11[0-3][0] *alpha -= ymm4 ymm1 = _mm256_fmsub_pd(ymm1, ymm15, ymm5); //B11[0-3][1] *alpha -= ymm5 ymm2 = _mm256_fmsub_pd(ymm2, ymm15, ymm6); //B11[0-3][2] *alpha -= ymm6 ymm3 = _mm256_fmsub_pd(ymm3, ymm15, ymm7); //B11[0-3][3] *alpha -= ymm7 if(3 == m_remainder) { ///implement TRSM/// //1st col ymm5 = _mm256_broadcast_sd((double const *)(a11+1)); //A11[1][0] ymm6 = _mm256_broadcast_sd((double const *)(a11+2)); //A11[2][0] //2nd col a11 += cs_a; ymm9 = _mm256_broadcast_sd((double const *)(a11 + 2)); //A11[2][1] ////unpacklow//// ymm8 = _mm256_unpacklo_pd(ymm0, ymm1); //B11[0][0] B11[0][1] B11[2][0] B11[2][1] ymm13 = _mm256_unpacklo_pd(ymm2, ymm3); //B11[0][2] B11[0][3] B11[2][2] B11[2][3] //rearrange low elements ymm4 = _mm256_permute2f128_pd(ymm8,ymm13,0x20); //B11[0][0] B11[0][1] B11[0][2] B11[0][3] ymm11 = _mm256_permute2f128_pd(ymm8,ymm13,0x31);//B11[2][0] B11[2][1] B11[2][2] B11[2][3] ////unpackhigh//// ymm0 = _mm256_unpackhi_pd(ymm0, ymm1); //B11[1][0] B11[1][1] B11[3][0] B11[3][1] ymm1 = _mm256_unpackhi_pd(ymm2, ymm3); //B11[1][2] B11[1][3] B11[3][2] B11[3][3] //rearrange high elements ymm8 = _mm256_permute2f128_pd(ymm0,ymm1,0x20); //B11[1][0] B11[1][1] B11[1][2] B11[1][3] ymm13 = _mm256_permute2f128_pd(ymm0,ymm1,0x31); //B11[3][0] B11[3][1] B11[3][2] B11[3][3] //(Row1): FMA operations of b1 with elements of indices from (1, 0) uptill (3, 0) ymm8 = _mm256_fnmadd_pd(ymm5, ymm4, ymm8);//d = c - (a*b) //B11[1][0-3] -= A11[1][0]* B11[0][0-3] ymm11 = _mm256_fnmadd_pd(ymm6, ymm4, ymm11);//d = c - (a*b) //B11[2][0-3] -= A11[2][0]* B11[0][0-3] //(Row2): FMA operations of b2 with elements of indices from (2, 0) uptill (7, 0) ymm11 = _mm256_fnmadd_pd(ymm9, ymm8, ymm11);//d = c - (a*b) //B11[2][0-3] -= A11[2][1]* B11[1][0-3] ymm13 = _mm256_broadcast_sd((double const *)(&ones)); //--> Transpose and store results of columns of B block <--// ////unpacklow//// ymm1 = _mm256_unpacklo_pd(ymm4, ymm8); //B11[0][0] B11[1][0] B11[0][2] B11[1][2] ymm3 = _mm256_unpacklo_pd(ymm11, ymm13); //B11[2][0] B11[3][0] B11[2][2] B11[3][2] //rearrange low elements ymm0 = _mm256_permute2f128_pd(ymm1,ymm3,0x20); //B11[0][0] B11[1][0] B11[2][0] B11[3][0] ymm2 = _mm256_permute2f128_pd(ymm1,ymm3,0x31); //B11[0][2] B11[1][2] B11[2][2] B11[3][2] ////unpackhigh//// ymm14 = _mm256_unpackhi_pd(ymm4, ymm8); //B11[0][1] B11[1][1] B11[0][3] B11[1][3] ymm15 = _mm256_unpackhi_pd(ymm11, ymm13); //B11[2][1] B11[3][1] B11[2][3] B11[3][3] //rearrange high elements ymm1 = _mm256_permute2f128_pd(ymm14,ymm15,0x20); //B11[0][1] B11[1][1] B11[2][1] B11[3][1] ymm3 = _mm256_permute2f128_pd(ymm14,ymm15,0x31); //B11[0][3] B11[1][3] B11[2][3] B11[3][3] //load 4x4 block from b11 ymm4 = _mm256_loadu_pd((double const *)(b11)); //B11[0][0] B11[1][0] B11[2][0] B11[3][0] ymm5 = _mm256_loadu_pd((double const *)(b11 + cs_b)); //B11[0][1] B11[1][1] B11[2][1] B11[3][1] ymm6 = _mm256_loadu_pd((double const *)(b11 + cs_b * 2)); //B11[0][2] B11[1][2] B11[2][2] B11[3][2] ymm7 = _mm256_loadu_pd((double const *)(f_temp)); //B11[0][3] B11[1][3] B11[2][2] B11[3][3] //determine correct values to store ymm0 = _mm256_blend_pd(ymm0, ymm4, 0x08); ymm1 = _mm256_blend_pd(ymm1, ymm5, 0x08); ymm2 = _mm256_blend_pd(ymm2, ymm6, 0x08); ymm3 = _mm256_blend_pd(ymm3, ymm7, 0x08); } else if(2 == m_remainder) { ///implement TRSM/// //1st col ymm5 = _mm256_broadcast_sd((double const *)(a11+1)); //A11[1][0] ////unpacklow//// ymm8 = _mm256_unpacklo_pd(ymm0, ymm1); //B11[0][0] B11[0][1] B11[2][0] B11[2][1] ymm13 = _mm256_unpacklo_pd(ymm2, ymm3); //B11[0][2] B11[0][3] B11[2][2] B11[2][3] //rearrange low elements ymm4 = _mm256_permute2f128_pd(ymm8,ymm13,0x20); //B11[0][0] B11[0][1] B11[0][2] B11[0][3] ymm11 = _mm256_permute2f128_pd(ymm8,ymm13,0x31);//B11[2][0] B11[2][1] B11[2][2] B11[2][3] ////unpackhigh//// ymm0 = _mm256_unpackhi_pd(ymm0, ymm1); //B11[1][0] B11[1][1] B11[3][0] B11[3][1] ymm1 = _mm256_unpackhi_pd(ymm2, ymm3); //B11[1][2] B11[1][3] B11[3][2] B11[3][3] //rearrange high elements ymm8 = _mm256_permute2f128_pd(ymm0,ymm1,0x20); //B11[1][0] B11[1][1] B11[1][2] B11[1][3] ymm13 = _mm256_permute2f128_pd(ymm0,ymm1,0x31); //B11[3][0] B11[3][1] B11[3][2] B11[3][3] //(Row1): FMA operations of b1 with elements of indices from (1, 0) uptill (3, 0) ymm8 = _mm256_fnmadd_pd(ymm5, ymm4, ymm8);//d = c - (a*b) //B11[1][0-3] -= A11[1][0]* B11[0][0-3] ymm11 = _mm256_broadcast_sd((double const *)(&ones)); ymm13 = _mm256_broadcast_sd((double const *)(&ones)); //--> Transpose and store results of columns of B block <--// ////unpacklow//// ymm1 = _mm256_unpacklo_pd(ymm4, ymm8); //B11[0][0] B11[1][0] B11[0][2] B11[1][2] ymm3 = _mm256_unpacklo_pd(ymm11, ymm13); //B11[2][0] B11[3][0] B11[2][2] B11[3][2] //rearrange low elements ymm0 = _mm256_permute2f128_pd(ymm1,ymm3,0x20); //B11[0][0] B11[1][0] B11[2][0] B11[3][0] ymm2 = _mm256_permute2f128_pd(ymm1,ymm3,0x31); //B11[0][2] B11[1][2] B11[2][2] B11[3][2] ////unpackhigh//// ymm14 = _mm256_unpackhi_pd(ymm4, ymm8); //B11[0][1] B11[1][1] B11[0][3] B11[1][3] ymm15 = _mm256_unpackhi_pd(ymm11, ymm13); //B11[2][1] B11[3][1] B11[2][3] B11[3][3] //rearrange high elements ymm1 = _mm256_permute2f128_pd(ymm14,ymm15,0x20); //B11[0][1] B11[1][1] B11[2][1] B11[3][1] ymm3 = _mm256_permute2f128_pd(ymm14,ymm15,0x31); //B11[0][3] B11[1][3] B11[2][3] B11[3][3] //load 4x4 block from b11 ymm4 = _mm256_loadu_pd((double const *)(b11)); //B11[0][0] B11[1][0] B11[2][0] B11[3][0] ymm5 = _mm256_loadu_pd((double const *)(b11 + cs_b)); //B11[0][1] B11[1][1] B11[2][1] B11[3][1] ymm6 = _mm256_loadu_pd((double const *)(b11 + cs_b * 2)); //B11[0][2] B11[1][2] B11[2][2] B11[3][2] ymm7 = _mm256_loadu_pd((double const *)(f_temp)); //B11[0][3] B11[1][3] B11[2][2] B11[3][3] //determine correct values to store ymm0 = _mm256_permute2f128_pd(ymm0, ymm4,0x30); ymm1 = _mm256_permute2f128_pd(ymm1, ymm5,0x30); ymm2 = _mm256_permute2f128_pd(ymm2, ymm6,0x30); ymm3 = _mm256_permute2f128_pd(ymm3, ymm7,0x30); } else if(1 == m_remainder) { //load 4x4 block from b11 ymm4 = _mm256_loadu_pd((double const *)(b11)); //B11[0][0] B11[1][0] B11[2][0] B11[3][0] ymm5 = _mm256_loadu_pd((double const *)(b11 + cs_b)); //B11[0][1] B11[1][1] B11[2][1] B11[3][1] ymm6 = _mm256_loadu_pd((double const *)(b11 + cs_b * 2)); //B11[0][2] B11[1][2] B11[2][2] B11[3][2] ymm7 = _mm256_loadu_pd((double const *)(f_temp)); //B11[0][3] B11[1][3] B11[2][2] B11[3][3] //determine correct values to store ymm0 = _mm256_blend_pd(ymm0, ymm4, 0x0E); ymm1 = _mm256_blend_pd(ymm1, ymm5, 0x0E); ymm2 = _mm256_blend_pd(ymm2, ymm6, 0x0E); ymm3 = _mm256_blend_pd(ymm3, ymm7, 0x0E); } _mm256_storeu_pd((double *)b11, ymm0); //store(B11[0-3][0]) _mm256_storeu_pd((double *)(b11 + (cs_b)), ymm1); //store(B11[0-3][1]) _mm256_storeu_pd((double *)(b11 + cs_b * 2), ymm2); //store(B11[0-3][2]) _mm256_storeu_pd((double *)(f_temp), ymm3); //store(B11[0-3][3]) if((j+4) == n) { for(iter = 0; iter < m_remainder; iter++) (b11 + cs_b * 3)[iter] = f_temp[iter]; } } n_remainder -= 4; j += 4; } if(n_remainder) //implementation fo remaining columns(when 'N' is not a multiple of D_NR) { for(i = 0;i+D_MR-1 < m; i += D_MR) //loop along 'M' direction { a10 = L +i; //pointer to block of A to be used for GEMM a11 = L + i + (i*cs_a); //pointer to block of A to be used for TRSM b01 = B + j*cs_b; //pointer to block of B to be used for GEMM b11 = B + i + j* cs_b; //pointer to block of B to be used for TRSM k_iter = i / D_MR; //number of GEMM operations to be performed(in blocks of 4x4) ymm4 = _mm256_setzero_pd(); ymm5 = _mm256_setzero_pd(); ymm6 = _mm256_setzero_pd(); ymm7 = _mm256_setzero_pd(); ///GEMM for previously calculated values /// //load 4x4 block from b11 if(3 == n_remainder) { ymm0 = _mm256_loadu_pd((double const *)(b11)); //B11[0][0] B11[1][0] B11[2][0] B11[3][0] ymm1 = _mm256_loadu_pd((double const *)(b11 + cs_b)); //B11[0][1] B11[1][1] B11[2][1] B11[3][1] ymm2 = _mm256_loadu_pd((double const *)(b11 + cs_b * 2)); //B11[0][2] B11[1][2] B11[2][2] B11[3][2] for(k = 0; k < k_iter; k++) { ptr_b01_dup = b01; ymm8 = _mm256_loadu_pd((double const *)(a10)); //A10[0][0] A10[1][0] A10[2][0] A10[3][0] ymm9 = _mm256_loadu_pd((double const *)(a10 + cs_a)); //A10[0][1] A10[1][1] A10[2][1] A10[3][1] ymm10 = _mm256_loadu_pd((double const *)(a10 + cs_a * 2)); //A10[0][2] A10[1][2] A10[2][2] A10[3][2] ymm11 = _mm256_loadu_pd((double const *)(a10 + cs_a * 3)); //A10[0][3] A10[1][3] A10[2][3] A10[3][3] ymm12 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 0)); //B01[0][0] ymm13 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 1)); //B01[0][1] ymm14 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 2)); //B01[0][2] b01 += 1; ymm4 = _mm256_fmadd_pd(ymm12, ymm8, ymm4); //ymm4 += (B01[0][0]*A10[0][0] B01[0][0]*A10[1][0] B01[0][0]*A10[2][0] B01[0][0]*A10[3][0]) ymm5 = _mm256_fmadd_pd(ymm13, ymm8, ymm5); //ymm5 += (B01[0][1]*A10[0][0] B01[0][1]*A10[1][0] B01[0][1]*A10[2][0] B01[0][1]*A10[3][0]) ymm6 = _mm256_fmadd_pd(ymm14, ymm8, ymm6); //ymm6 += (B01[0][2]*A10[0][0] B01[0][2]*A10[1][0] B01[0][2]*A10[2][0] B01[0][2]*A10[3][0]) ymm12 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 0)); //B01[1][0] ymm13 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 1)); //B01[1][1] ymm14 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 2)); //B01[1][2] b01 += 1; ymm4 = _mm256_fmadd_pd(ymm12, ymm9, ymm4); //ymm4 += (B01[1][0]*A10[0][1] B01[1][0]*A10[1][1] B01[1][0]*A10[2][1] B01[1][0]*A10[3][1]) ymm5 = _mm256_fmadd_pd(ymm13, ymm9, ymm5); //ymm5 += (B01[1][1]*A10[0][1] B01[1][1]*A10[1][1] B01[1][1]*A10[2][1] B01[1][1]*A10[3][1]) ymm6 = _mm256_fmadd_pd(ymm14, ymm9, ymm6); //ymm6 += (B01[1][2]*A10[0][1] B01[1][2]*A10[1][1] B01[1][2]*A10[2][1] B01[1][2]*A10[3][1]) ymm12 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 0)); //B01[2][0] ymm13 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 1)); //B01[2][1] ymm14 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 2)); //B01[2][2] b01 += 1; ymm4 = _mm256_fmadd_pd(ymm12, ymm10, ymm4); //ymm4 += (B01[2][0]*A10[0][2] B01[2][0]*A10[1][2] B01[2][0]*A10[2][2] B01[2][0]*A10[3][2]) ymm5 = _mm256_fmadd_pd(ymm13, ymm10, ymm5); //ymm5 += (B01[2][1]*A10[0][2] B01[2][1]*A10[1][2] B01[2][1]*A10[2][2] B01[2][1]*A10[3][2]) ymm6 = _mm256_fmadd_pd(ymm14, ymm10, ymm6); //ymm6 += (B01[2][2]*A10[0][2] B01[2][2]*A10[1][2] B01[2][2]*A10[2][2] B01[2][2]*A10[3][2]) ymm12 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 0)); //B01[3][0] ymm13 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 1)); //B01[3][1] ymm14 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 2)); //B01[3][2] b01 += 1; ymm4 = _mm256_fmadd_pd(ymm12, ymm11, ymm4); //ymm4 += (B01[3][0]*A10[0][3] B01[3][0]*A10[1][3] B01[3][0]*A10[2][3] B01[3][0]*A10[3][3]) ymm5 = _mm256_fmadd_pd(ymm13, ymm11, ymm5); //ymm5 += (B01[3][1]*A10[0][3] B01[3][1]*A10[1][3] B01[3][1]*A10[2][3] B01[3][1]*A10[3][3]) ymm6 = _mm256_fmadd_pd(ymm14, ymm11, ymm6); //ymm6 += (B01[3][2]*A10[0][3] B01[3][2]*A10[1][3] B01[3][2]*A10[2][3] B01[3][2]*A10[3][3]) a10 += D_MR * cs_a; //pointer math to find next block of A for GEMM b01 = ptr_b01_dup + D_MR; //pointer math to find next block of B for GEMM } ///GEMM code ends/// ymm15 = _mm256_broadcast_sd((double const *)&AlphaVal); //register to store alpha Value ymm0 = _mm256_fmsub_pd(ymm0, ymm15, ymm4); //B11[0-3][0] *alpha -= ymm4 ymm1 = _mm256_fmsub_pd(ymm1, ymm15, ymm5); //B11[0-3][1] *alpha -= ymm5 ymm2 = _mm256_fmsub_pd(ymm2, ymm15, ymm6); //B11[0-3][2] *alpha -= ymm6 ymm3 = _mm256_broadcast_sd((double const *)(&ones)); //B11[0-3][3] *alpha -= ymm7 } else if(2 == n_remainder) { ymm0 = _mm256_loadu_pd((double const *)(b11)); //B11[0][0] B11[1][0] B11[2][0] B11[3][0] ymm1 = _mm256_loadu_pd((double const *)(b11 + cs_b)); //B11[0][1] B11[1][1] B11[2][1] B11[3][1] for(k = 0; k < k_iter; k++) { ptr_b01_dup = b01; ymm8 = _mm256_loadu_pd((double const *)(a10)); //A10[0][0] A10[1][0] A10[2][0] A10[3][0] ymm9 = _mm256_loadu_pd((double const *)(a10 + cs_a)); //A10[0][1] A10[1][1] A10[2][1] A10[3][1] ymm10 = _mm256_loadu_pd((double const *)(a10 + cs_a * 2)); //A10[0][2] A10[1][2] A10[2][2] A10[3][2] ymm11 = _mm256_loadu_pd((double const *)(a10 + cs_a * 3)); //A10[0][3] A10[1][3] A10[2][3] A10[3][3] ymm12 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 0)); //B01[0][0] ymm13 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 1)); //B01[0][1] b01 += 1; ymm4 = _mm256_fmadd_pd(ymm12, ymm8, ymm4); //ymm4 += (B01[0][0]*A10[0][0] B01[0][0]*A10[1][0] B01[0][0]*A10[2][0] B01[0][0]*A10[3][0]) ymm5 = _mm256_fmadd_pd(ymm13, ymm8, ymm5); //ymm5 += (B01[0][1]*A10[0][0] B01[0][1]*A10[1][0] B01[0][1]*A10[2][0] B01[0][1]*A10[3][0]) ymm12 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 0)); //B01[1][0] ymm13 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 1)); //B01[1][1] b01 += 1; ymm4 = _mm256_fmadd_pd(ymm12, ymm9, ymm4); //ymm4 += (B01[1][0]*A10[0][1] B01[1][0]*A10[1][1] B01[1][0]*A10[2][1] B01[1][0]*A10[3][1]) ymm5 = _mm256_fmadd_pd(ymm13, ymm9, ymm5); //ymm5 += (B01[1][1]*A10[0][1] B01[1][1]*A10[1][1] B01[1][1]*A10[2][1] B01[1][1]*A10[3][1]) ymm12 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 0)); //B01[2][0] ymm13 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 1)); //B01[2][1] b01 += 1; ymm4 = _mm256_fmadd_pd(ymm12, ymm10, ymm4); //ymm4 += (B01[2][0]*A10[0][2] B01[2][0]*A10[1][2] B01[2][0]*A10[2][2] B01[2][0]*A10[3][2]) ymm5 = _mm256_fmadd_pd(ymm13, ymm10, ymm5); //ymm5 += (B01[2][1]*A10[0][2] B01[2][1]*A10[1][2] B01[2][1]*A10[2][2] B01[2][1]*A10[3][2]) ymm12 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 0)); //B01[3][0] ymm13 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 1)); //B01[3][1] b01 += 1; ymm4 = _mm256_fmadd_pd(ymm12, ymm11, ymm4); //ymm4 += (B01[3][0]*A10[0][3] B01[3][0]*A10[1][3] B01[3][0]*A10[2][3] B01[3][0]*A10[3][3]) ymm5 = _mm256_fmadd_pd(ymm13, ymm11, ymm5); //ymm5 += (B01[3][1]*A10[0][3] B01[3][1]*A10[1][3] B01[3][1]*A10[2][3] B01[3][1]*A10[3][3]) a10 += D_MR * cs_a; //pointer math to find next block of A for GEMM b01 = ptr_b01_dup + D_MR; //pointer math to find next block of B for GEMM } ///GEMM code ends/// ymm15 = _mm256_broadcast_sd((double const *)&AlphaVal); //register to store alpha Value ymm0 = _mm256_fmsub_pd(ymm0, ymm15, ymm4); //B11[0-3][0] *alpha -= ymm4 ymm1 = _mm256_fmsub_pd(ymm1, ymm15, ymm5); //B11[0-3][1] *alpha -= ymm5 ymm2 = _mm256_broadcast_sd((double const *)(&ones)); //B11[0-3][2] *alpha -= ymm6 ymm3 = _mm256_broadcast_sd((double const *)(&ones)); //B11[0-3][3] *alpha -= ymm7 } else if(1 == n_remainder) { ymm0 = _mm256_loadu_pd((double const *)(b11)); //B11[0][0] B11[1][0] B11[2][0] B11[3][0] for(k = 0; k < k_iter; k++) { ptr_b01_dup = b01; ymm8 = _mm256_loadu_pd((double const *)(a10)); //A10[0][0] A10[1][0] A10[2][0] A10[3][0] ymm9 = _mm256_loadu_pd((double const *)(a10 + cs_a)); //A10[0][1] A10[1][1] A10[2][1] A10[3][1] ymm10 = _mm256_loadu_pd((double const *)(a10 + cs_a * 2)); //A10[0][2] A10[1][2] A10[2][2] A10[3][2] ymm11 = _mm256_loadu_pd((double const *)(a10 + cs_a * 3)); //A10[0][3] A10[1][3] A10[2][3] A10[3][3] ymm12 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 0)); //B01[0][0] b01 += 1; ymm4 = _mm256_fmadd_pd(ymm12, ymm8, ymm4); //ymm4 += (B01[0][0]*A10[0][0] B01[0][0]*A10[1][0] B01[0][0]*A10[2][0] B01[0][0]*A10[3][0]) ymm12 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 0)); //B01[1][0] b01 += 1; ymm4 = _mm256_fmadd_pd(ymm12, ymm9, ymm4); //ymm4 += (B01[1][0]*A10[0][1] B01[1][0]*A10[1][1] B01[1][0]*A10[2][1] B01[1][0]*A10[3][1]) ymm12 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 0)); //B01[2][0] b01 += 1; ymm4 = _mm256_fmadd_pd(ymm12, ymm10, ymm4); //ymm4 += (B01[2][0]*A10[0][2] B01[2][0]*A10[1][2] B01[2][0]*A10[2][2] B01[2][0]*A10[3][2]) ymm12 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 0)); //B01[3][0] b01 += 1; ymm4 = _mm256_fmadd_pd(ymm12, ymm11, ymm4); //ymm4 += (B01[3][0]*A10[0][3] B01[3][0]*A10[1][3] B01[3][0]*A10[2][3] B01[3][0]*A10[3][3]) a10 += D_MR * cs_a; //pointer math to find next block of A for GEMM b01 = ptr_b01_dup + D_MR; //pointer math to find next block of B for GEMM } ///GEMM code ends/// ymm15 = _mm256_broadcast_sd((double const *)&AlphaVal); //register to store alpha Value ymm0 = _mm256_fmsub_pd(ymm0, ymm15, ymm4); //B11[0-3][0] *alpha -= ymm4 ymm1 = _mm256_broadcast_sd((double const *)(&ones)); //B11[0-3][1] *alpha -= ymm5 ymm2 = _mm256_broadcast_sd((double const *)(&ones)); //B11[0-3][2] *alpha -= ymm6 ymm3 = _mm256_broadcast_sd((double const *)(&ones)); //B11[0-3][3] *alpha -= ymm7 } ///implement TRSM/// //1st col ymm5 = _mm256_broadcast_sd((double const *)(a11+1)); //A11[1][0] ymm6 = _mm256_broadcast_sd((double const *)(a11+2)); //A11[2][0] ymm7 = _mm256_broadcast_sd((double const *)(a11+3)); //A11[3][0] //2nd col a11 += cs_a; ymm9 = _mm256_broadcast_sd((double const *)(a11 + 2)); //A11[2][1] ymm10 = _mm256_broadcast_sd((double const *)(a11 + 3)); //A11[3][1] //3rd col a11 += cs_a; ymm12 = _mm256_broadcast_sd((double const *)(a11 + 3)); //A11[3][2] ////unpacklow//// ymm8 = _mm256_unpacklo_pd(ymm0, ymm1); //B11[0][0] B11[0][1] B11[2][0] B11[2][1] ymm13 = _mm256_unpacklo_pd(ymm2, ymm3); //B11[0][2] B11[0][3] B11[2][2] B11[2][3] //rearrange low elements ymm4 = _mm256_permute2f128_pd(ymm8,ymm13,0x20); //B11[0][0] B11[0][1] B11[0][2] B11[0][3] ymm11 = _mm256_permute2f128_pd(ymm8,ymm13,0x31);//B11[2][0] B11[2][1] B11[2][2] B11[2][3] ////unpackhigh//// ymm0 = _mm256_unpackhi_pd(ymm0, ymm1); //B11[1][0] B11[1][1] B11[3][0] B11[3][1] ymm1 = _mm256_unpackhi_pd(ymm2, ymm3); //B11[1][2] B11[1][3] B11[3][2] B11[3][3] //rearrange high elements ymm8 = _mm256_permute2f128_pd(ymm0,ymm1,0x20); //B11[1][0] B11[1][1] B11[1][2] B11[1][3] ymm13 = _mm256_permute2f128_pd(ymm0,ymm1,0x31); //B11[3][0] B11[3][1] B11[3][2] B11[3][3] //(Row1): FMA operations of b1 with elements of indices from (1, 0) uptill (3, 0) ymm8 = _mm256_fnmadd_pd(ymm5, ymm4, ymm8);//d = c - (a*b) //B11[1][0-3] -= A11[1][0] * B11[0][0-3] ymm11 = _mm256_fnmadd_pd(ymm6, ymm4, ymm11);//d = c - (a*b) //B11[2][0-3] -= A11[2][0] * B11[0][0-3] ymm13 = _mm256_fnmadd_pd(ymm7, ymm4, ymm13);//d = c - (a*b) //B11[3][0-3] -= A11[3][0] * B11[0][0-3] //(Row2): FMA operations of b2 with elements of indices from (2, 0) uptill (7, 0) ymm11 = _mm256_fnmadd_pd(ymm9, ymm8, ymm11);//d = c - (a*b) //B11[2][0-3] -= A11[2][1] * B11[1][0-3] ymm13 = _mm256_fnmadd_pd(ymm10, ymm8, ymm13);//d = c - (a*b) //B11[3][0-3] -= A11[3][1] * B11[1][0-3] //(Row3): FMA operations of b3 with elements of indices from (3, 0) uptill (7, 0) ymm13 = _mm256_fnmadd_pd(ymm12, ymm11, ymm13);//d = c - (a*b) //B11[3][0-3] -= A11[3][2] * B11[2][0-3] //--> Transpose and store results of columns of B block <--// ////unpacklow//// ymm1 = _mm256_unpacklo_pd(ymm4, ymm8); //B11[0][0] B11[1][0] B11[0][2] B11[1][2] ymm3 = _mm256_unpacklo_pd(ymm11, ymm13); //B11[2][0] B11[3][0] B11[2][2] B11[3][2] //rearrange low elements ymm0 = _mm256_permute2f128_pd(ymm1,ymm3,0x20); //B11[0][0] B11[1][0] B11[2][0] B11[3][0] ymm2 = _mm256_permute2f128_pd(ymm1,ymm3,0x31); //B11[0][2] B11[1][2] B11[2][2] B11[3][2] ////unpackhigh//// ymm14 = _mm256_unpackhi_pd(ymm4, ymm8); //B11[0][1] B11[1][1] B11[0][3] B11[1][3] ymm15 = _mm256_unpackhi_pd(ymm11, ymm13); //B11[2][1] B11[3][1] B11[2][3] B11[3][3] //rearrange high elements ymm1 = _mm256_permute2f128_pd(ymm14,ymm15,0x20); //B11[0][1] B11[1][1] B11[2][1] B11[3][1] ymm3 = _mm256_permute2f128_pd(ymm14,ymm15,0x31); //B11[0][3] B11[1][3] B11[2][3] B11[3][3] if(3 == n_remainder) { _mm256_storeu_pd((double *)b11, ymm0); //store(B11[0-3][0]) _mm256_storeu_pd((double *)(b11 + (cs_b)), ymm1); //store(B11[0-3][1]) _mm256_storeu_pd((double *)(b11 + cs_b * 2), ymm2); //store(B11[0-3][2]) } else if(2 == n_remainder) { _mm256_storeu_pd((double *)b11, ymm0); //store(B11[0-3][0]) _mm256_storeu_pd((double *)(b11 + (cs_b)), ymm1); //store(B11[0-3][1]) } else if(1 == n_remainder) { _mm256_storeu_pd((double *)b11, ymm0); //store(B11[0-3][0]) } } if(m_remainder) //implementation for remainder rows(when 'M' is not a multiple of D_MR) { a10 = L +i; //pointer to block of A to be used for GEMM a11 = L + i + (i*cs_a); //pointer to block of A to be used for TRSM b01 = B + j*cs_b; //pointer to block of B to be used for GEMM b11 = B + i + j* cs_b; //pointer to block of B to be used for TRSM k_iter = i / D_MR; //number of times GEMM operations to be performed dim_t iter; if((j+n_remainder) == n) { f_temp = f_t; for(iter = 0; iter < m_remainder; iter++) f_temp[iter] = (b11 + cs_b * (n_remainder -1))[iter]; } else f_temp = (b11 + cs_b * (n_remainder -1)); ymm4 = _mm256_setzero_pd(); ymm5 = _mm256_setzero_pd(); ymm6 = _mm256_setzero_pd(); ymm7 = _mm256_setzero_pd(); ///GEMM for previously calculated values /// //load 4x4 block from b11 if(3 == n_remainder) { ymm0 = _mm256_loadu_pd((double const *)(b11)); //B11[0][0] B11[1][0] B11[2][0] B11[3][0] ymm1 = _mm256_loadu_pd((double const *)(b11 + cs_b)); //B11[0][1] B11[1][1] B11[2][1] B11[3][1] ymm2 = _mm256_loadu_pd((double const *)(f_temp)); //B11[0][2] B11[1][2] B11[2][2] B11[3][2] for(k = 0; k < k_iter; k++) //loop for number of GEMM operations { ptr_b01_dup = b01; ymm8 = _mm256_loadu_pd((double const *)(a10)); //A10[0][0] A10[1][0] A10[2][0] A10[3][0] ymm9 = _mm256_loadu_pd((double const *)(a10 + cs_a)); //A10[0][1] A10[1][1] A10[2][1] A10[3][1] ymm10 = _mm256_loadu_pd((double const *)(a10 + cs_a * 2)); //A10[0][2] A10[1][2] A10[2][2] A10[3][2] ymm11 = _mm256_loadu_pd((double const *)(a10 + cs_a * 3)); //A10[0][3] A10[1][3] A10[2][3] A10[3][3] ymm12 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 0)); //B10[0][0] ymm13 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 1)); //B10[0][1] ymm14 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 2)); //B10[0][2] b01 += 1; //move to next row of B ymm4 = _mm256_fmadd_pd(ymm12, ymm8, ymm4); //ymm4 += (B01[0][0]*A10[0][0] B01[0][0]*A10[1][0] B01[0][0]*A10[2][0] B01[0][0]*A10[3][0]) ymm5 = _mm256_fmadd_pd(ymm13, ymm8, ymm5); //ymm5 += (B01[0][1]*A10[0][0] B01[0][1]*A10[1][0] B01[0][1]*A10[2][0] B01[0][1]*A10[3][0]) ymm6 = _mm256_fmadd_pd(ymm14, ymm8, ymm6); //ymm6 += (B01[0][2]*A10[0][0] B01[0][2]*A10[1][0] B01[0][2]*A10[2][0] B01[0][2]*A10[3][0]) ymm12 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 0)); //B10[1][0] ymm13 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 1)); //B10[1][1] ymm14 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 2)); //B10[1][2] b01 += 1; //move to next row of B ymm4 = _mm256_fmadd_pd(ymm12, ymm9, ymm4); //ymm4 += (B01[1][0]*A10[0][1] B01[1][0]*A10[1][1] B01[1][0]*A10[2][1] B01[1][0]*A10[3][1]) ymm5 = _mm256_fmadd_pd(ymm13, ymm9, ymm5); //ymm5 += (B01[1][1]*A10[0][1] B01[1][1]*A10[1][1] B01[1][1]*A10[2][1] B01[1][1]*A10[3][1]) ymm6 = _mm256_fmadd_pd(ymm14, ymm9, ymm6); //ymm6 += (B01[1][2]*A10[0][1] B01[1][2]*A10[1][1] B01[1][2]*A10[2][1] B01[1][2]*A10[3][1]) ymm12 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 0)); //B10[2][0] ymm13 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 1)); //B10[2][1] ymm14 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 2)); //B10[2][2] b01 += 1; //move to next row of B ymm4 = _mm256_fmadd_pd(ymm12, ymm10, ymm4); //ymm4 += (B01[2][0]*A10[0][2] B01[2][0]*A10[1][2] B01[2][0]*A10[2][2] B01[2][0]*A10[3][2]) ymm5 = _mm256_fmadd_pd(ymm13, ymm10, ymm5); //ymm5 += (B01[2][1]*A10[0][2] B01[2][1]*A10[1][2] B01[2][1]*A10[2][2] B01[2][1]*A10[3][2]) ymm6 = _mm256_fmadd_pd(ymm14, ymm10, ymm6); //ymm6 += (B01[2][2]*A10[0][2] B01[2][2]*A10[1][2] B01[2][2]*A10[2][2] B01[2][2]*A10[3][2]) ymm12 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 0)); //B10[3][0] ymm13 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 1)); //B10[3][1] ymm14 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 2)); //B10[3][2] b01 += 1; //move to next row of B ymm4 = _mm256_fmadd_pd(ymm12, ymm11, ymm4); //ymm4 += (B01[3][0]*A10[0][3] B01[3][0]*A10[1][3] B01[3][0]*A10[2][3] B01[3][0]*A10[3][3]) ymm5 = _mm256_fmadd_pd(ymm13, ymm11, ymm5); //ymm5 += (B01[3][1]*A10[0][3] B01[3][1]*A10[1][3] B01[3][1]*A10[2][3] B01[3][1]*A10[3][3]) ymm6 = _mm256_fmadd_pd(ymm14, ymm11, ymm6); //ymm6 += (B01[3][2]*A10[0][3] B01[3][2]*A10[1][3] B01[3][2]*A10[2][3] B01[3][2]*A10[3][3]) a10 += D_MR * cs_a; //pointer math to find next block of A for GEMM b01 = ptr_b01_dup + D_MR; //pointer math to find next block of B for GEMM } ymm15 = _mm256_broadcast_sd((double const *)&AlphaVal); //register to hold alpha value ymm8 = _mm256_fmsub_pd(ymm0, ymm15, ymm4); //B11[0-3][0] * alpha -= ymm4 ymm9 = _mm256_fmsub_pd(ymm1, ymm15, ymm5); //B11[0-3][1] * alpha -= ymm5 ymm10 = _mm256_fmsub_pd(ymm2, ymm15, ymm6); //B11[0-3][2] * alpha -= ymm6 ///implement TRSM/// //determine correct values to store if(3 == m_remainder) { ymm0 = _mm256_blend_pd(ymm8, ymm0, 0x08); ymm1 = _mm256_blend_pd(ymm9, ymm1, 0x08); ymm2 = _mm256_blend_pd(ymm10, ymm2, 0x08); } else if(2 == m_remainder) { ymm0 = _mm256_permute2f128_pd(ymm8, ymm0, 0x30); ymm1 = _mm256_permute2f128_pd(ymm9, ymm1, 0x30); ymm2 = _mm256_permute2f128_pd(ymm10, ymm2, 0x30); } else if(1 == m_remainder) { ymm0 = _mm256_blend_pd(ymm8, ymm0, 0x0E); ymm1 = _mm256_blend_pd(ymm9, ymm1, 0x0E); ymm2 = _mm256_blend_pd(ymm10, ymm2, 0x0E); } _mm256_storeu_pd((double *)b11, ymm0); //store(B11[0-3][0]) _mm256_storeu_pd((double *)(b11 + (cs_b)), ymm1); //store(B11[0-3][1]) _mm256_storeu_pd((double *)(f_temp), ymm2); //store(B11[0-3][2]) } else if(2 == n_remainder) { ymm0 = _mm256_loadu_pd((double const *)(b11)); //B11[0][0] B11[1][0] B11[2][0] B11[3][0] ymm1 = _mm256_loadu_pd((double const *)(f_temp)); //B11[0][1] B11[1][1] B11[2][1] B11[3][1] for(k = 0; k < k_iter; k++) //loop for number of GEMM operations { ptr_b01_dup = b01; ymm8 = _mm256_loadu_pd((double const *)(a10)); //A10[0][0] A10[1][0] A10[2][0] A10[3][0] ymm9 = _mm256_loadu_pd((double const *)(a10 + cs_a)); //A10[0][1] A10[1][1] A10[2][1] A10[3][1] ymm10 = _mm256_loadu_pd((double const *)(a10 + cs_a * 2)); //A10[0][2] A10[1][2] A10[2][2] A10[3][2] ymm11 = _mm256_loadu_pd((double const *)(a10 + cs_a * 3)); //A10[0][3] A10[1][3] A10[2][3] A10[3][3] ymm12 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 0)); //B10[0][0] ymm13 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 1)); //B10[0][1] b01 += 1; //move to next row of B ymm4 = _mm256_fmadd_pd(ymm12, ymm8, ymm4); //ymm4 += (B01[0][0]*A10[0][0] B01[0][0]*A10[1][0] B01[0][0]*A10[2][0] B01[0][0]*A10[3][0]) ymm5 = _mm256_fmadd_pd(ymm13, ymm8, ymm5); //ymm5 += (B01[0][1]*A10[0][0] B01[0][1]*A10[1][0] B01[0][1]*A10[2][0] B01[0][1]*A10[3][0]) ymm12 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 0)); //B10[1][0] ymm13 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 1)); //B10[1][1] b01 += 1; //move to next row of B ymm4 = _mm256_fmadd_pd(ymm12, ymm9, ymm4); //ymm4 += (B01[1][0]*A10[0][1] B01[1][0]*A10[1][1] B01[1][0]*A10[2][1] B01[1][0]*A10[3][1]) ymm5 = _mm256_fmadd_pd(ymm13, ymm9, ymm5); //ymm5 += (B01[1][1]*A10[0][1] B01[1][1]*A10[1][1] B01[1][1]*A10[2][1] B01[1][1]*A10[3][1]) ymm12 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 0)); //B10[2][0] ymm13 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 1)); //B10[2][1] b01 += 1; //move to next row of B ymm4 = _mm256_fmadd_pd(ymm12, ymm10, ymm4); //ymm4 += (B01[2][0]*A10[0][2] B01[2][0]*A10[1][2] B01[2][0]*A10[2][2] B01[2][0]*A10[3][2]) ymm5 = _mm256_fmadd_pd(ymm13, ymm10, ymm5); //ymm5 += (B01[2][1]*A10[0][2] B01[2][1]*A10[1][2] B01[2][1]*A10[2][2] B01[2][1]*A10[3][2]) ymm12 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 0)); //B10[3][0] ymm13 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 1)); //B10[3][1] b01 += 1; //move to next row of B ymm4 = _mm256_fmadd_pd(ymm12, ymm11, ymm4); //ymm4 += (B01[3][0]*A10[0][3] B01[3][0]*A10[1][3] B01[3][0]*A10[2][3] B01[3][0]*A10[3][3]) ymm5 = _mm256_fmadd_pd(ymm13, ymm11, ymm5); //ymm5 += (B01[3][1]*A10[0][3] B01[3][1]*A10[1][3] B01[3][1]*A10[2][3] B01[3][1]*A10[3][3]) a10 += D_MR * cs_a; //pointer math to find next block of A for GEMM b01 = ptr_b01_dup + D_MR; //pointer math to find next block of B for GEMM } ymm15 = _mm256_broadcast_sd((double const *)&AlphaVal); //register to hold alpha value ymm8 = _mm256_fmsub_pd(ymm0, ymm15, ymm4); //B11[0-3][0] * alpha -= ymm4 ymm9 = _mm256_fmsub_pd(ymm1, ymm15, ymm5); //B11[0-3][1] * alpha -= ymm5 ///implement TRSM/// //determine correct values to store if(3 == m_remainder) { ymm0 = _mm256_blend_pd(ymm8, ymm0, 0x08); ymm1 = _mm256_blend_pd(ymm9, ymm1, 0x08); } else if(2 == m_remainder) { ymm0 = _mm256_permute2f128_pd(ymm8, ymm0, 0x30); ymm1 = _mm256_permute2f128_pd(ymm9, ymm1, 0x30); } else if(1 == m_remainder) { ymm0 = _mm256_blend_pd(ymm8, ymm0, 0x0E); ymm1 = _mm256_blend_pd(ymm9, ymm1, 0x0E); } _mm256_storeu_pd((double *)b11, ymm0); //store(B11[0-3][0]) _mm256_storeu_pd((double *)(f_temp), ymm1); //store(B11[0-3][1]) } else if(1 == n_remainder) { ymm0 = _mm256_loadu_pd((double const *)(f_temp)); //B11[0][0] B11[1][0] B11[2][0] B11[3][0] for(k = 0; k < k_iter; k++) //loop for number of GEMM operations { ptr_b01_dup = b01; ymm8 = _mm256_loadu_pd((double const *)(a10)); //A10[0][0] A10[1][0] A10[2][0] A10[3][0] ymm9 = _mm256_loadu_pd((double const *)(a10 + cs_a)); //A10[0][1] A10[1][1] A10[2][1] A10[3][1] ymm10 = _mm256_loadu_pd((double const *)(a10 + cs_a * 2)); //A10[0][2] A10[1][2] A10[2][2] A10[3][2] ymm11 = _mm256_loadu_pd((double const *)(a10 + cs_a * 3)); //A10[0][3] A10[1][3] A10[2][3] A10[3][3] ymm12 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 0)); //B10[0][0] b01 += 1; //move to next row of B ymm4 = _mm256_fmadd_pd(ymm12, ymm8, ymm4); //ymm4 += (B01[0][0]*A10[0][0] B01[0][0]*A10[1][0] B01[0][0]*A10[2][0] B01[0][0]*A10[3][0]) ymm12 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 0)); //B10[1][0] b01 += 1; //move to next row of B ymm4 = _mm256_fmadd_pd(ymm12, ymm9, ymm4); //ymm4 += (B01[1][0]*A10[0][1] B01[1][0]*A10[1][1] B01[1][0]*A10[2][1] B01[1][0]*A10[3][1]) ymm12 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 0)); //B10[2][0] b01 += 1; //move to next row of B ymm4 = _mm256_fmadd_pd(ymm12, ymm10, ymm4); //ymm4 += (B01[2][0]*A10[0][2] B01[2][0]*A10[1][2] B01[2][0]*A10[2][2] B01[2][0]*A10[3][2]) ymm12 = _mm256_broadcast_sd((double const *)(b01 + cs_b * 0)); //B10[3][0] b01 += 1; //move to next row of B ymm4 = _mm256_fmadd_pd(ymm12, ymm11, ymm4); //ymm4 += (B01[3][0]*A10[0][3] B01[3][0]*A10[1][3] B01[3][0]*A10[2][3] B01[3][0]*A10[3][3]) a10 += D_MR * cs_a; //pointer math to find next block of A for GEMM b01 = ptr_b01_dup + D_MR; //pointer math to find next block of B for GEMM } ymm15 = _mm256_broadcast_sd((double const *)&AlphaVal); //register to hold alpha value ymm8 = _mm256_fmsub_pd(ymm0, ymm15, ymm4); //B11[0-3][0] * alpha -= ymm4 ///implement TRSM/// //determine correct values to store if(3 == m_remainder) { ymm0 = _mm256_blend_pd(ymm8, ymm0, 0x08); } else if(2 == m_remainder) { ymm0 = _mm256_permute2f128_pd(ymm8, ymm0, 0x30); } else if(1 == m_remainder) { ymm0 = _mm256_blend_pd(ymm8, ymm0, 0x0E); } _mm256_storeu_pd((double *)(f_temp), ymm0); //store(B11[0-3][0]) } if((j+n_remainder) == n) { for(iter = 0; iter < m_remainder; iter++) (b11 + cs_b * (n_remainder-1))[iter] = f_temp[iter]; } ///scalar code for trsm without alpha/// dtrsm_small_AlXB_unitDiag(a11, b11, m_remainder, n_remainder, cs_a, cs_b); } } return BLIS_SUCCESS; } /*implements TRSM for the case XA = alpha * B *A is upper triangular, non-unit diagonal, no transpose *dimensions: X:mxn A:nxn B: mxn */ /* b11---> a01 ----> ***************** *********** *b01*b11* * * * * * * b11 * * * * * **a01 * * a11 | ***************** ********* | | * * * * * *a11* * | | * * * * * * * * | v ***************** ****** v * * * * * * * * * * * * * * ***************** * * * */ static err_t bli_dtrsm_small_XAuB( side_t side, obj_t* AlphaObj, obj_t* a, obj_t* b, cntx_t* cntx, cntl_t* cntl ) { dim_t D_MR = 8; //block dimension along the rows dim_t D_NR = 4; //block dimension along the columns dim_t m = bli_obj_length(b); //number of rows dim_t n = bli_obj_width(b); //number of columns dim_t m_remainder = m & 7; //number of corner rows dim_t n_remainder = n & 3; //number of corner columns dim_t cs_a = bli_obj_col_stride(a); //column stride of matrix A dim_t cs_b = bli_obj_col_stride(b); //column stride of matrix B #ifdef BLIS_ENABLE_SMALL_MATRIX_ROME if((m>D_BLIS_SMALL_MATRIX_THRES_TRSM_XAUB_ROME_ROW_PANEL_M && n>D_BLIS_SMALL_MATRIX_THRES_TRSM_XAUB_ROME) || (m>D_BLIS_SMALL_MATRIX_THRES_TRSM_XAUB_ROME && n>D_BLIS_SMALL_MATRIX_THRES_TRSM_XAUB_ROME_COLUMN_PANEL_N) ) return BLIS_NOT_YET_IMPLEMENTED; #else if(bli_max(m,n)>D_BLIS_SMALL_MATRIX_THRES_TRSM_NAPLES && (m/n) < D_BLIS_SMALL_MATRIX_THRES_TRSM_DIM_RATIO) { return BLIS_NOT_YET_IMPLEMENTED; } #endif dim_t i, j, k; //loop variablse dim_t k_iter; //determines the number of GEMM operations to be done dim_t cs_b_offset[2]; //pre-calculated strides double ones = 1.0; double AlphaVal = *(double *)AlphaObj->buffer; //value of Alpha double *L = a->buffer; //pointer to matrix A double *B = b->buffer; //pointer to matrix B double *a01, *a11, *b10, *b11; //pointers for GEMM and TRSM blocks double *ptr_a01_dup; double f_t[4] __attribute__((aligned(64)));//buffer to store corner column when m_remainder !=0 double* f_temp; cs_b_offset[0] = cs_b << 1; //cs_b_offset[0] = cs_b * 2; cs_b_offset[1] = cs_b_offset[0] + cs_b;//cs_b_offset[1] = cs_b * 3; //ymm scratch reginsters __m256d ymm0, ymm1, ymm2, ymm3; __m256d ymm4, ymm5, ymm6, ymm7; __m256d ymm8, ymm9, ymm10, ymm11; __m256d ymm12, ymm13, ymm14, ymm15; __m256d ymm16; for(i = 0; (i+D_MR-1) < m; i += D_MR) //loop along 'M' direction { for(j = 0; (j+D_NR-1) < n; j += D_NR) //loop along 'N' direction { a01 = L + j*cs_a; //pointer to block of A to be used in GEMM a11 = L + j*cs_a + j; //pointer to block of A to be used for TRSM b10 = B + i; //pointer to block of B to be used in GEMM b11 = B + i + j*cs_b; //pointer to block of B to be used for TRSM k_iter = j / D_NR; //number of GEMM operations to be done(in blocks of 4x4) ymm0 = _mm256_setzero_pd(); ymm1 = _mm256_setzero_pd(); ymm2 = _mm256_setzero_pd(); ymm3 = _mm256_setzero_pd(); ymm4 = _mm256_setzero_pd(); ymm5 = _mm256_setzero_pd(); ymm6 = _mm256_setzero_pd(); ymm7 = _mm256_setzero_pd(); ///GEMM implementation starts/// for(k = 0; k < k_iter; k++) //loop for number of GEMM operations { ptr_a01_dup = a01; //broadcast 1st row of A01 ymm8 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 0)); //A01[0][0] ymm9 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 1)); //A01[0][1] ymm10 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 2)); //A01[0][2] ymm11 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 3)); //A01[0][3] a01 += 1; //move to next row //load 8x2 block of B10 ymm12 = _mm256_loadu_pd((double const *)b10); //B10[0][0] B10[1][0] B10[2][0] B10[3][0] ymm13 = _mm256_loadu_pd((double const *)(b10 + D_NR)); //B10[4][0] B10[5][0] B10[6][0] B10[7][0] ymm14 = _mm256_loadu_pd((double const *)(b10 + cs_b)); //B10[0][1] B10[1][1] B10[2][1] B10[3][1] ymm15 = _mm256_loadu_pd((double const *)(b10 + cs_b + D_NR)); //B10[4][1] B10[5][1] B10[6][1] B10[7][1] ymm0 = _mm256_fmadd_pd(ymm8, ymm12, ymm0); //ymm0 += (B10[0][0]*A01[0][0] B10[1][0]*A01[0][0] B10[2][0]*A01[0][0] B10[3][0]*A01[0][0]) ymm1 = _mm256_fmadd_pd(ymm9, ymm12, ymm1); //ymm1 += (B10[0][0]*A01[0][1] B10[1][0]*A01[0][1] B10[2][0]*A01[0][1] B10[3][0]*A01[0][1]) ymm2 = _mm256_fmadd_pd(ymm10, ymm12, ymm2); //ymm2 += (B10[0][0]*A01[0][2] B10[1][0]*A01[0][2] B10[2][0]*A01[0][2] B10[3][0]*A01[0][2]) ymm3 = _mm256_fmadd_pd(ymm11, ymm12, ymm3); //ymm3 += (B10[0][0]*A01[0][3] B10[1][0]*A01[0][3] B10[2][0]*A01[0][3] B10[3][0]*A01[0][3]) ymm4 = _mm256_fmadd_pd(ymm8, ymm13, ymm4); //ymm4 += (B10[4][0]*A01[0][0] B10[5][0]*A01[0][0] B10[6][0]*A01[0][0] B10[7][0]*A01[0][0]) ymm5 = _mm256_fmadd_pd(ymm9, ymm13, ymm5); //ymm5 += (B10[4][0]*A01[0][1] B10[5][0]*A01[0][1] B10[6][0]*A01[0][1] B10[7][0]*A01[0][1]) ymm6 = _mm256_fmadd_pd(ymm10, ymm13, ymm6); //ymm6 += (B10[4][0]*A01[0][2] B10[5][0]*A01[0][2] B10[6][0]*A01[0][2] B10[7][0]*A01[0][2]) ymm7 = _mm256_fmadd_pd(ymm11, ymm13, ymm7); //ymm7 += (B10[4][0]*A01[0][3] B10[5][0]*A01[0][3] B10[6][0]*A01[0][3] B10[7][0]*A01[0][3]) //broadcast 2nd row of A01 ymm8 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 0)); //A01[1][0] ymm9 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 1)); //A01[1][1] ymm10 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 2)); //A01[1][2] ymm11 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 3)); //A01[1][3] a01 += 1; //move to next row of A ymm0 = _mm256_fmadd_pd(ymm8, ymm14, ymm0); //ymm0 += (B10[0][1]*A01[0][0] B10[1][1]*A01[0][0] B10[2][1]*A01[0][0] B10[3][1]*A01[0][0]) ymm1 = _mm256_fmadd_pd(ymm9, ymm14, ymm1); //ymm1 += (B10[0][1]*A01[0][1] B10[1][1]*A01[0][1] B10[2][1]*A01[0][1] B10[3][1]*A01[0][1]) ymm2 = _mm256_fmadd_pd(ymm10, ymm14, ymm2); //ymm2 += (B10[0][1]*A01[0][2] B10[1][1]*A01[0][2] B10[2][1]*A01[0][2] B10[3][1]*A01[0][2]) ymm3 = _mm256_fmadd_pd(ymm11, ymm14, ymm3); //ymm3 += (B10[0][1]*A01[0][3] B10[1][1]*A01[0][3] B10[2][1]*A01[0][3] B10[3][1]*A01[0][3]) ymm4 = _mm256_fmadd_pd(ymm8, ymm15, ymm4); //ymm4 += (B10[4][1]*A01[0][0] B10[5][1]*A01[0][0] B10[6][1]*A01[0][0] B10[7][1]*A01[0][0]) ymm5 = _mm256_fmadd_pd(ymm9, ymm15, ymm5); //ymm5 += (B10[4][1]*A01[0][1] B10[5][1]*A01[0][1] B10[6][1]*A01[0][1] B10[7][1]*A01[0][1]) ymm6 = _mm256_fmadd_pd(ymm10, ymm15, ymm6); //ymm6 += (B10[4][1]*A01[0][2] B10[5][1]*A01[0][2] B10[6][1]*A01[0][2] B10[7][1]*A01[0][2]) ymm7 = _mm256_fmadd_pd(ymm11, ymm15, ymm7); //ymm7 += (B10[4][1]*A01[0][3] B10[5][1]*A01[0][3] B10[6][1]*A01[0][3] B10[7][1]*A01[0][3]) //broadcast 3rd row of A01 ymm8 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 0)); //A01[2][0] ymm9 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 1)); //A01[2][1] ymm10 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 2)); //A01[2][2] ymm11 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 3)); //A01[2][3] a01 += 1; //move to next row of A01 //load next 8x2 block of B10 ymm12 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0])); //(B10[0][2] B10[1][2] B10[2][2] B10[3][2]) ymm13 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + D_NR)); //(B10[4][2] B10[5][2] B10[6][2] B10[7][2]) ymm14 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + cs_b)); //(B10[0][3] B10[1][3] B10[2][3] B10[3][3]) ymm15 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + cs_b + D_NR)); //(B10[4][3] B10[5][3] B10[6][3] B10[7][3]) ymm0 = _mm256_fmadd_pd(ymm8, ymm12, ymm0); //ymm0 += (B10[0][2]*A01[0][0] B10[1][2]*A01[0][0] B10[2][2]*A01[0][0] B10[3][2]*A01[0][0]) ymm1 = _mm256_fmadd_pd(ymm9, ymm12, ymm1); //ymm1 += (B10[0][2]*A01[0][1] B10[1][2]*A01[0][1] B10[2][2]*A01[0][1] B10[3][2]*A01[0][1]) ymm2 = _mm256_fmadd_pd(ymm10, ymm12, ymm2); //ymm2 += (B10[0][2]*A01[0][2] B10[1][2]*A01[0][2] B10[2][2]*A01[0][2] B10[3][2]*A01[0][2]) ymm3 = _mm256_fmadd_pd(ymm11, ymm12, ymm3); //ymm3 += (B10[0][2]*A01[0][3] B10[1][2]*A01[0][3] B10[2][2]*A01[0][3] B10[3][2]*A01[0][3]) ymm4 = _mm256_fmadd_pd(ymm8, ymm13, ymm4); //ymm4 += (B10[4][2]*A01[0][0] B10[5][2]*A01[0][0] B10[6][2]*A01[0][0] B10[7][2]*A01[0][0]) ymm5 = _mm256_fmadd_pd(ymm9, ymm13, ymm5); //ymm5 += (B10[4][2]*A01[0][1] B10[5][2]*A01[0][1] B10[6][2]*A01[0][1] B10[7][2]*A01[0][1]) ymm6 = _mm256_fmadd_pd(ymm10, ymm13, ymm6); //ymm6 += (B10[4][2]*A01[0][2] B10[5][2]*A01[0][2] B10[6][2]*A01[0][2] B10[7][2]*A01[0][2]) ymm7 = _mm256_fmadd_pd(ymm11, ymm13, ymm7); //ymm7 += (B10[4][2]*A01[0][3] B10[5][2]*A01[0][3] B10[6][2]*A01[0][3] B10[7][2]*A01[0][3]) //broadcast 4th row of A01 ymm8 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 0)); //A01[3][0] ymm9 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 1)); //A01[3][1] ymm10 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 2)); //A01[3][2] ymm11 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 3)); //A01[3][3] a01 += 1; //move to next row of A01 ymm0 = _mm256_fmadd_pd(ymm8, ymm14, ymm0); //ymm0 += (B10[0][3]*A01[0][0] B10[1][3]*A01[0][0] B10[2][3]*A01[0][0] B10[3][3]*A01[0][0]) ymm1 = _mm256_fmadd_pd(ymm9, ymm14, ymm1); //ymm1 += (B10[0][3]*A01[0][1] B10[1][3]*A01[0][1] B10[2][3]*A01[0][1] B10[3][3]*A01[0][1]) ymm2 = _mm256_fmadd_pd(ymm10, ymm14, ymm2); //ymm2 += (B10[0][3]*A01[0][2] B10[1][3]*A01[0][2] B10[2][3]*A01[0][2] B10[3][3]*A01[0][2]) ymm3 = _mm256_fmadd_pd(ymm11, ymm14, ymm3); //ymm3 += (B10[0][3]*A01[0][3] B10[1][3]*A01[0][3] B10[2][3]*A01[0][3] B10[3][3]*A01[0][3]) ymm4 = _mm256_fmadd_pd(ymm8, ymm15, ymm4); //ymm4 += (B10[4][3]*A01[0][0] B10[5][3]*A01[0][0] B10[6][3]*A01[0][0] B10[7][3]*A01[0][0]) ymm5 = _mm256_fmadd_pd(ymm9, ymm15, ymm5); //ymm5 += (B10[4][3]*A01[0][1] B10[5][3]*A01[0][1] B10[6][3]*A01[0][1] B10[7][3]*A01[0][1]) ymm6 = _mm256_fmadd_pd(ymm10, ymm15, ymm6); //ymm6 += (B10[4][3]*A01[0][2] B10[5][3]*A01[0][2] B10[6][3]*A01[0][2] B10[7][3]*A01[0][2]) ymm7 = _mm256_fmadd_pd(ymm11, ymm15, ymm7); //ymm7 += (B10[4][3]*A01[0][3] B10[5][3]*A01[0][3] B10[6][3]*A01[0][3] B10[7][3]*A01[0][3]) b10 += D_NR * cs_b; //pointer math to find next block of B for GEMM a01 = ptr_a01_dup + D_NR; //pointer math to find next block of A for GEMM } ///GEMM code ends/// ymm16 = _mm256_broadcast_sd((double const *)&AlphaVal); //load 8x4 block of B11 ymm8 = _mm256_loadu_pd((double const *)b11); //B11[0][0] B11[1][0] B11[2][0] B11[3][0] ymm12 = _mm256_loadu_pd((double const *)(b11 + D_NR)); //B11[4][0] B11[5][0] B11[6][0] B11[7][0] ymm9 = _mm256_loadu_pd((double const *)(b11 + cs_b)); //B11[0][1] B11[1][1] B11[2][1] B11[3][1] ymm13 = _mm256_loadu_pd((double const *)(b11 + cs_b + D_NR)); //B11[4][1] B11[5][1] B11[6][1] B11[7][1] ymm10 = _mm256_loadu_pd((double const *)(b11 + cs_b_offset[0])); //B11[0][2] B11[1][2] B11[2][2] B11[3][2] ymm14 = _mm256_loadu_pd((double const *)(b11 + cs_b_offset[0] + D_NR)); //B11[4][2] B11[5][2] B11[6][2] B11[7][2] ymm11 = _mm256_loadu_pd((double const *)(b11 + cs_b_offset[1])); //B11[0][3] B11[1][3] B11[2][3] B11[3][3] ymm15 = _mm256_loadu_pd((double const *)(b11 + cs_b_offset[1] + D_NR)); //B11[4][3] B11[5][3] B11[6][3] B11[7][3] ymm8 = _mm256_fmsub_pd(ymm8, ymm16, ymm0); //B11[0-3][0] * alpha -= ymm0 ymm9 = _mm256_fmsub_pd(ymm9, ymm16, ymm1); //B11[4-7][0] * alpha-= ymm1 ymm10 = _mm256_fmsub_pd(ymm10, ymm16, ymm2); //B11[0-3][1] * alpha-= ymm2 ymm11 = _mm256_fmsub_pd(ymm11, ymm16, ymm3); //B11[4-7][1] * alpha -= ymm3 ymm12 = _mm256_fmsub_pd(ymm12, ymm16, ymm4); //B11[0-3][2] * alpha -= ymm4 ymm13 = _mm256_fmsub_pd(ymm13, ymm16, ymm5); //B11[4-7][2] * alpha -= ymm5 ymm14 = _mm256_fmsub_pd(ymm14, ymm16, ymm6); //B11[0-3][3] * alpha -= ymm6 ymm15 = _mm256_fmsub_pd(ymm15, ymm16, ymm7); //B11[4-7][3] * alpha -= ymm7 ///implement TRSM/// ///read 4x4 block of A11/// ymm7 = _mm256_broadcast_sd((double const *)(&ones)); //1st col ymm0 = _mm256_broadcast_sd((double const *)(a11+0)); //A11[0][0] //2nd col a11 += cs_a; ymm1 = _mm256_broadcast_sd((double const *)(a11+0)); //A11[0][1] ymm2 = _mm256_broadcast_sd((double const *)(a11+1)); //A11[1][1] //3rd col a11 += cs_a; ymm3 = _mm256_broadcast_sd((double const *)(a11+0)); //A11[0][2] ymm4 = _mm256_broadcast_sd((double const *)(a11+1)); //A11[1][2] ymm5 = _mm256_broadcast_sd((double const *)(a11+2)); //A11[2][2] //4th col a11 += cs_a; ymm6 = _mm256_broadcast_sd((double const *)(a11+3)); //A11[3][3] //compute reciprocals of L(i,i) and broadcast in registers ymm0 = _mm256_unpacklo_pd(ymm0, ymm2); //A11[0][0] A11[1][1] A11[0][0] A11[1][1] ymm2 = _mm256_unpacklo_pd(ymm5, ymm6); //A11[2][2] A11[3][3] A11[1][1] A11[3][3] ymm0 = _mm256_blend_pd(ymm0, ymm2, 0x0C); //A11[0][0] A11[1][1] A11[2][2] A11[3][3] ymm7 = _mm256_div_pd(ymm7, ymm0); //(1/A11[0][0] 1/A11[1][1] 1/A11[2][2] 1/A11[3][3]) ymm2 = _mm256_broadcast_sd((double const *)(a11+0)); //A11[0][3] ymm5 = _mm256_broadcast_sd((double const *)(a11+1)); //A11[1][3] ymm6 = _mm256_broadcast_sd((double const *)(a11+2)); //A11[2][3] //extract a00 ymm0 = _mm256_permute_pd(ymm7, 0x00); //(1/A11[0][0] 1/A11[0][0] 1/A11[2][2] 1/A11[2][2]) ymm0 = _mm256_permute2f128_pd(ymm0, ymm0, 0x00); //(1/A11[0][0] 1/A11[0][0] 1/A11[0][0] 1/A11[0][0]) ymm8 = _mm256_mul_pd(ymm8, ymm0); //B11[0-3][0] /= A11[0][0] ymm12 = _mm256_mul_pd(ymm12, ymm0); //B11[4-7][0] /= A11[0][0] //extract a11 ymm0 = _mm256_permute_pd(ymm7, 0x03); //(1/A11[1][1] 1/A11[1][1] 1/A11[2][2] 1/A11[2][2]) ymm0 = _mm256_permute2f128_pd(ymm0, ymm0, 0x00);//(1/A11[1][1] 1/A11[1][1] 1/A11[1][1] 1/A11[1][1]) //(Row1): FMA operations ymm9 = _mm256_fnmadd_pd(ymm1, ymm8, ymm9); //B11[0-3][1] -= B11[0-3][0] * A11[0][1] ymm10 = _mm256_fnmadd_pd(ymm3, ymm8, ymm10); //B11[0-3][2] -= B11[0-3][0] * A11[0][2] ymm11 = _mm256_fnmadd_pd(ymm2, ymm8, ymm11); //B11[0-3][3] -= B11[0-3][0] * A11[0][3] ymm13 = _mm256_fnmadd_pd(ymm1, ymm12, ymm13); //B11[4-7][1] -= B11[4-7][0] * A11[0][1] ymm14 = _mm256_fnmadd_pd(ymm3, ymm12, ymm14); //B11[4-7][2] -= B11[4-7][0] * A11[0][2] ymm15 = _mm256_fnmadd_pd(ymm2, ymm12, ymm15); //B11[4-7][3] -= B11[4-7][0] * A11[0][3] ymm9 = _mm256_mul_pd(ymm9, ymm0); //B11[0-3][1] /= A11[1][1] ymm13 = _mm256_mul_pd(ymm13, ymm0); //B11[4-7][1] /= A11[1][1] //extract a22 ymm0 = _mm256_permute_pd(ymm7, 0x00); //(1/A11[0][0] 1/A11[0][0] 1/A11[2][2] 1/A11[2][2]) ymm0 = _mm256_permute2f128_pd(ymm0, ymm0, 0x11);//(1/A11[2][2] 1/A11[2][2] 1/A11[2][2] 1/A11[2][2]) //(Row2)FMA operations ymm10 = _mm256_fnmadd_pd(ymm4, ymm9, ymm10); //B11[0-3][2] -= B11[0-3][1] * A11[1][2] ymm11 = _mm256_fnmadd_pd(ymm5, ymm9, ymm11); //B11[0-3][3] -= B11[0-3][1] * A11[1][3] ymm14 = _mm256_fnmadd_pd(ymm4, ymm13, ymm14); //B11[4-7][2] -= B11[4-7][1] * A11[1][2] ymm15 = _mm256_fnmadd_pd(ymm5, ymm13, ymm15); //B11[4-7][3] -= B11[4-7][1] * A11[1][3] ymm10 = _mm256_mul_pd(ymm10, ymm0); //B11[0-3][2] /= A11[2][2] ymm14 = _mm256_mul_pd(ymm14, ymm0); //B11[4-7][2] /= A11[2][2] //extract a33 ymm0 = _mm256_permute_pd(ymm7, 0x0C); //(1/A11[0][0] 1/A11[0][0] 1/A11[3][3] 1/A11[3][3] 1/A11[3][3]) ymm0 = _mm256_permute2f128_pd(ymm0, ymm0, 0x11);//(1/A11[3][3] 1/A11[3][3] 1/A11[3][3] 1/A11[3][3]) //(Row3)FMA operations ymm11 = _mm256_fnmadd_pd(ymm6, ymm10, ymm11); //B11[0-3][3] -= B11[0-3][2] * A11[2][3] ymm15 = _mm256_fnmadd_pd(ymm6, ymm14, ymm15); //B11[4-7][3] -= B11[4-7][2] * A11[2][3] ymm11 = _mm256_mul_pd(ymm11, ymm0); //B11[0-3][3] /= A11[3][3] ymm15 = _mm256_mul_pd(ymm15, ymm0); //B11[4-7][3] /= A11[3][3] _mm256_storeu_pd((double *)b11, ymm8); //store(B11[0-3][0]) _mm256_storeu_pd((double *)(b11 + D_NR), ymm12); //store(B11[4-7][0]) _mm256_storeu_pd((double *)(b11 + cs_b), ymm9); //store(B11[0-3][1]) _mm256_storeu_pd((double *)(b11 + cs_b + D_NR), ymm13); //store(B11[4-7][1]) _mm256_storeu_pd((double *)(b11 + cs_b_offset[0]), ymm10); //store(B11[0-3][2]) _mm256_storeu_pd((double *)(b11 + cs_b_offset[0] + D_NR), ymm14); //store(B11[4-7][2]) _mm256_storeu_pd((double *)(b11 + cs_b_offset[0] + cs_b), ymm11); //store(B11[0-3][3]) _mm256_storeu_pd((double *)(b11 + cs_b_offset[0] + cs_b + D_NR), ymm15);//store(B11[4-7][3]) } if(n_remainder) //implementation for remainder columns(when n is not multiple of D_NR) { a01 = L + j*cs_a; //pointer to block of A to be used for GEMM a11 = L + j*cs_a + j; //pointer to block of A to be used for TRSM b10 = B + i; //pointer to block of B to be used for GEMM b11 = B + i + j*cs_b; //pointer to block of B to be used for TRSM k_iter = j / D_NR; //number of GEMM operations to be performed(in blocks of 4x4) ///load 4x4 block of b11 ymm0 = _mm256_setzero_pd(); ymm1 = _mm256_setzero_pd(); ymm2 = _mm256_setzero_pd(); ymm3 = _mm256_setzero_pd(); ymm4 = _mm256_setzero_pd(); ymm5 = _mm256_setzero_pd(); ymm6 = _mm256_setzero_pd(); ymm7 = _mm256_setzero_pd(); //subtract the calculated GEMM block from current TRSM block //load 8x4 block of B11 if(3 == n_remainder) { ///GEMM implementation begins/// for(k = 0; k < k_iter; k++) ///loop for number of GEMM operations { ptr_a01_dup = a01; //broadcast 1st row of A01 ymm8 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 0)); //A01[0][0] ymm9 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 1)); //A01[0][1] ymm10 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 2)); //A01[0][2] a01 += 1; //move to next row of A //load 8x2 block of B10 ymm12 = _mm256_loadu_pd((double const *)b10); //B10[0][0] B10[1][0] B10[2][0] B10[3][0] ymm13 = _mm256_loadu_pd((double const *)(b10 + D_NR)); //B10[4][0] B10[5][0] B10[6][0] B10[7][0] ymm14 = _mm256_loadu_pd((double const *)(b10 + cs_b)); //B10[0][1] B10[1][1] B10[2][1] B10[3][1] ymm15 = _mm256_loadu_pd((double const *)(b10 + cs_b + D_NR));//B10[4][1] B10[5][1] B10[6][1] B10[7][1] ymm0 = _mm256_fmadd_pd(ymm8, ymm12, ymm0); //ymm0 += (B10[0][0]*A01[0][0] B10[1][0]*A01[0][0] B10[2][0]*A01[0][0] B10[3][0]*A01[0][0]) ymm1 = _mm256_fmadd_pd(ymm9, ymm12, ymm1); //ymm1 += (B10[0][0]*A01[0][1] B10[1][0]*A01[0][1] B10[2][0]*A01[0][1] B10[3][0]*A01[0][1]) ymm2 = _mm256_fmadd_pd(ymm10, ymm12, ymm2); //ymm2 += (B10[0][0]*A01[0][2] B10[1][0]*A01[0][2] B10[2][0]*A01[0][2] B10[3][0]*A01[0][2]) ymm4 = _mm256_fmadd_pd(ymm8, ymm13, ymm4); //ymm4 += (B10[4][0]*A01[0][0] B10[5][0]*A01[0][0] B10[6][0]*A01[0][0] B10[7][0]*A01[0][0]) ymm5 = _mm256_fmadd_pd(ymm9, ymm13, ymm5); //ymm5 += (B10[4][0]*A01[0][1] B10[5][0]*A01[0][1] B10[6][0]*A01[0][1] B10[7][0]*A01[0][1]) ymm6 = _mm256_fmadd_pd(ymm10, ymm13, ymm6); //ymm6 += (B10[4][0]*A01[0][2] B10[5][0]*A01[0][2] B10[6][0]*A01[0][2] B10[7][0]*A01[0][2]) //broadcast 2nd row of A01 ymm8 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 0)); //A01[1][0] ymm9 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 1)); //A01[1][1] ymm10 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 2)); //A01[1][2] a01 += 1; //move to next row of A ymm0 = _mm256_fmadd_pd(ymm8, ymm14, ymm0); //ymm0 += (B10[0][1]*A01[0][0] B10[1][1]*A01[0][0] B10[2][1]*A01[0][0] B10[3][1]*A01[0][0]) ymm1 = _mm256_fmadd_pd(ymm9, ymm14, ymm1); //ymm1 += (B10[0][1]*A01[0][1] B10[1][1]*A01[0][1] B10[2][1]*A01[0][1] B10[3][1]*A01[0][1]) ymm2 = _mm256_fmadd_pd(ymm10, ymm14, ymm2); //ymm2 += (B10[0][1]*A01[0][2] B10[1][1]*A01[0][2] B10[2][1]*A01[0][2] B10[3][1]*A01[0][2]) ymm4 = _mm256_fmadd_pd(ymm8, ymm15, ymm4); //ymm4 += (B10[4][1]*A01[0][0] B10[5][1]*A01[0][0] B10[6][1]*A01[0][0] B10[7][1]*A01[0][0]) ymm5 = _mm256_fmadd_pd(ymm9, ymm15, ymm5); //ymm5 += (B10[4][1]*A01[0][1] B10[5][1]*A01[0][1] B10[6][1]*A01[0][1] B10[7][1]*A01[0][1]) ymm6 = _mm256_fmadd_pd(ymm10, ymm15, ymm6); //ymm6 += (B10[4][1]*A01[0][2] B10[5][1]*A01[0][2] B10[6][1]*A01[0][2] B10[7][1]*A01[0][2]) //broadcast 3rd row of A01 ymm8 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 0)); //A01[2][0] ymm9 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 1)); //A01[2][1] ymm10 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 2)); //A01[2][2] a01 += 1; //move to next row of A //load next 8x2 block of B10 ymm12 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0])); //(B10[0][2] B10[1][2] B10[2][2] B10[3][2]) ymm13 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + D_NR)); //(B10[4][2] B10[5][2] B10[6][2] B10[7][2]) ymm14 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + cs_b)); //(B10[0][3] B10[1][3] B10[2][3] B10[3][3]) ymm15 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + cs_b + D_NR)); //(B10[4][3] B10[5][3] B10[6][3] B10[7][3]) ymm0 = _mm256_fmadd_pd(ymm8, ymm12, ymm0); //ymm0 += (B10[0][2]*A01[0][0] B10[1][2]*A01[0][0] B10[2][2]*A01[0][0] B10[3][2]*A01[0][0]) ymm1 = _mm256_fmadd_pd(ymm9, ymm12, ymm1); //ymm1 += (B10[0][2]*A01[0][1] B10[1][2]*A01[0][1] B10[2][2]*A01[0][1] B10[3][2]*A01[0][1]) ymm2 = _mm256_fmadd_pd(ymm10, ymm12, ymm2); //ymm2 += (B10[0][2]*A01[0][2] B10[1][2]*A01[0][2] B10[2][2]*A01[0][2] B10[3][2]*A01[0][2]) ymm4 = _mm256_fmadd_pd(ymm8, ymm13, ymm4); //ymm4 += (B10[4][2]*A01[0][0] B10[5][2]*A01[0][0] B10[6][2]*A01[0][0] B10[7][2]*A01[0][0]) ymm5 = _mm256_fmadd_pd(ymm9, ymm13, ymm5); //ymm5 += (B10[4][2]*A01[0][1] B10[5][2]*A01[0][1] B10[6][2]*A01[0][1] B10[7][2]*A01[0][1]) ymm6 = _mm256_fmadd_pd(ymm10, ymm13, ymm6); //ymm6 += (B10[4][2]*A01[0][2] B10[5][2]*A01[0][2] B10[6][2]*A01[0][2] B10[7][2]*A01[0][2]) //broadcast 4th row of A01 ymm8 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 0)); //A01[3][0] ymm9 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 1)); //A01[3][1] ymm10 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 2)); //A01[3][2] a01 += 1; //move to next row of A ymm0 = _mm256_fmadd_pd(ymm8, ymm14, ymm0); //ymm0 += (B10[0][3]*A01[0][0] B10[1][3]*A01[0][0] B10[2][3]*A01[0][0] B10[3][3]*A01[0][0]) ymm1 = _mm256_fmadd_pd(ymm9, ymm14, ymm1); //ymm1 += (B10[0][3]*A01[0][1] B10[1][3]*A01[0][1] B10[2][3]*A01[0][1] B10[3][3]*A01[0][1]) ymm2 = _mm256_fmadd_pd(ymm10, ymm14, ymm2); //ymm2 += (B10[0][3]*A01[0][2] B10[1][3]*A01[0][2] B10[2][3]*A01[0][2] B10[3][3]*A01[0][2]) ymm4 = _mm256_fmadd_pd(ymm8, ymm15, ymm4); //ymm4 += (B10[4][3]*A01[0][0] B10[5][3]*A01[0][0] B10[6][3]*A01[0][0] B10[7][3]*A01[0][0]) ymm5 = _mm256_fmadd_pd(ymm9, ymm15, ymm5); //ymm5 += (B10[4][3]*A01[0][1] B10[5][3]*A01[0][1] B10[6][3]*A01[0][1] B10[7][3]*A01[0][1]) ymm6 = _mm256_fmadd_pd(ymm10, ymm15, ymm6); //ymm6 += (B10[4][3]*A01[0][2] B10[5][3]*A01[0][2] B10[6][3]*A01[0][2] B10[7][3]*A01[0][2]) b10 += D_NR * cs_b; //pointer math to find next block of B for GEMM a01 = ptr_a01_dup + D_NR; //pointer math to find next block of A for GEMM } ymm15 = _mm256_broadcast_sd((double const *)&AlphaVal); ///GEMM code ends/// ymm8 = _mm256_loadu_pd((double const *)b11); //B11[0-3][0] ymm12 = _mm256_loadu_pd((double const *)(b11 + D_NR)); //B11[4-7][0] ymm9 = _mm256_loadu_pd((double const *)(b11 + cs_b)); //B11[0-3][1] ymm13 = _mm256_loadu_pd((double const *)(b11 + cs_b + D_NR)); //B11[4-7][1] ymm10 = _mm256_loadu_pd((double const *)(b11 + cs_b_offset[0])); //B11[0-3][2] ymm14 = _mm256_loadu_pd((double const *)(b11 + cs_b_offset[0] + D_NR)); //B11[4-7][2] ymm8 = _mm256_fmsub_pd(ymm8, ymm15, ymm0); //B11[0-3][0] * alpha -= B10[0-3][0] ymm9 = _mm256_fmsub_pd(ymm9, ymm15, ymm1); //B11[4-7][0] * alpha -= B10[4-7][0] ymm10 = _mm256_fmsub_pd(ymm10, ymm15, ymm2); //B11[0-3][1] * alpha -= B10[0-3][1] ymm12 = _mm256_fmsub_pd(ymm12, ymm15, ymm4); //B11[0-3][2] * alpha -= B10[0-3][2] ymm13 = _mm256_fmsub_pd(ymm13, ymm15, ymm5); //B11[4-7][2] * alpha -= B10[4-7][2] ymm14 = _mm256_fmsub_pd(ymm14, ymm15, ymm6); //B11[0-3][3] * alpha -= B10[0-3][3] ///implement TRSM/// ///read 4x4 block of A11/// ymm7 = _mm256_broadcast_sd((double const *)(&ones)); //1st col ymm0 = _mm256_broadcast_sd((double const *)(a11+0)); //A11[0][0] //2nd col a11 += cs_a; ymm1 = _mm256_broadcast_sd((double const *)(a11+0)); //A11[0][1] ymm2 = _mm256_broadcast_sd((double const *)(a11+1)); //A11[1][1] //3rd col a11 += cs_a; ymm3 = _mm256_broadcast_sd((double const *)(a11+0)); //A11[0][2] ymm4 = _mm256_broadcast_sd((double const *)(a11+1)); //A11[1][2] ymm5 = _mm256_broadcast_sd((double const *)(a11+2)); //A11[2][2] //4th col a11 += cs_a; ymm6 = _mm256_broadcast_sd((double const *)(&ones)); //A11[3][3] //compute reciprocals of L(i,i) and broadcast in registers ymm0 = _mm256_unpacklo_pd(ymm0, ymm2); //A11[0][0] A11[1][1] A11[0][0] A11[1][1] ymm2 = _mm256_unpacklo_pd(ymm5, ymm6); //A11[2][2] A11[3][3] A11[1][1] A11[3][3] ymm0 = _mm256_blend_pd(ymm0, ymm2, 0x0C); //A11[0][0] A11[1][1] A11[2][2] A11[3][3] ymm7 = _mm256_div_pd(ymm7, ymm0); //(1/A11[0][0] 1/A11[1][1] 1/A11[2][2] 1/A11[3][3]) //extract a00 ymm0 = _mm256_permute_pd(ymm7, 0x00); //(1/A11[0][0] 1/A11[0][0] 1/A11[2][2] 1/A11[2][2]) ymm0 = _mm256_permute2f128_pd(ymm0, ymm0, 0x00);//(1/A11[0][0] 1/A11[0][0] 1/A11[0][0] 1/A11[0][0]) ymm8 = _mm256_mul_pd(ymm8, ymm0); //B11[0-3][0] /= A11[0][0] ymm12 = _mm256_mul_pd(ymm12, ymm0); //B11[4-7][0] /= A11[0][0] //extract a11 ymm0 = _mm256_permute_pd(ymm7, 0x03); //(1/A11[1][1] 1/A11[1][1] 1/A11[2][2] 1/A11[2][2]) ymm0 = _mm256_permute2f128_pd(ymm0, ymm0, 0x00);//(1/A11[1][1] 1/A11[1][1] 1/A11[1][1] 1/A11[1][1]) //(Row1): FMA operations ymm9 = _mm256_fnmadd_pd(ymm1, ymm8, ymm9); //B11[0-3][1] -= B11[0-3][0] * A11[0][1] ymm10 = _mm256_fnmadd_pd(ymm3, ymm8, ymm10); //B11[0-3][2] -= B11[0-3][0] * A11[0][2] ymm13 = _mm256_fnmadd_pd(ymm1, ymm12, ymm13); //B11[4-7][1] -= B11[4-7][0] * A11[0][1] ymm14 = _mm256_fnmadd_pd(ymm3, ymm12, ymm14); //B11[4-7][2] -= B11[4-7][0] * A11[0][2] ymm9 = _mm256_mul_pd(ymm9, ymm0); //B11[0-3][1] /= A11[1][1] ymm13 = _mm256_mul_pd(ymm13, ymm0); //B11[4-7][1] /= A11[1][1] //extract a22 ymm0 = _mm256_permute_pd(ymm7, 0x00); //(1/A11[0][0] 1/A11[0][0] 1/A11[2][2] 1/A11[2][2]) ymm0 = _mm256_permute2f128_pd(ymm0, ymm0, 0x11);//(1/A11[2][2] 1/A11[2][2] 1/A11[2][2] 1/A11[2][2]) //(Row2)FMA operations ymm10 = _mm256_fnmadd_pd(ymm4, ymm9, ymm10); //B11[0-3][2] -= B11[0-3][1] * A11[1][2] ymm14 = _mm256_fnmadd_pd(ymm4, ymm13, ymm14); //B11[4-7][2] -= B11[4-7][1] * A11[1][2] ymm10 = _mm256_mul_pd(ymm10, ymm0); //B11[0-3][2] /= A11[2][2] ymm14 = _mm256_mul_pd(ymm14, ymm0); //B11[4-7][2] /= A11[2][2] _mm256_storeu_pd((double *)b11, ymm8); //store(B11[0-3][0]) _mm256_storeu_pd((double *)(b11 + D_NR), ymm12); //store(B11[4-7][0]) _mm256_storeu_pd((double *)(b11 + cs_b), ymm9); //store(B11[0-3][1]) _mm256_storeu_pd((double *)(b11 + cs_b + D_NR), ymm13); //store(B11[4-7][1]) _mm256_storeu_pd((double *)(b11 + cs_b_offset[0]), ymm10); //store(B11[0-3][2]) _mm256_storeu_pd((double *)(b11 + cs_b_offset[0] + D_NR), ymm14);//store(B11[4-7][2]) } else if(2 == n_remainder) { ///GEMM implementation begins/// for(k = 0; k < k_iter; k++) ///loop for number of GEMM operations { ptr_a01_dup = a01; //broadcast 1st row of A01 ymm8 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 0)); //A01[0][0] ymm9 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 1)); //A01[0][1] a01 += 1; //move to next row of A //load 8x2 block of B10 ymm12 = _mm256_loadu_pd((double const *)b10); //B10[0][0] B10[1][0] B10[2][0] B10[3][0] ymm13 = _mm256_loadu_pd((double const *)(b10 + D_NR)); //B10[4][0] B10[5][0] B10[6][0] B10[7][0] ymm14 = _mm256_loadu_pd((double const *)(b10 + cs_b)); //B10[0][1] B10[1][1] B10[2][1] B10[3][1] ymm15 = _mm256_loadu_pd((double const *)(b10 + cs_b + D_NR));//B10[4][1] B10[5][1] B10[6][1] B10[7][1] ymm0 = _mm256_fmadd_pd(ymm8, ymm12, ymm0); //ymm0 += (B10[0][0]*A01[0][0] B10[1][0]*A01[0][0] B10[2][0]*A01[0][0] B10[3][0]*A01[0][0]) ymm1 = _mm256_fmadd_pd(ymm9, ymm12, ymm1); //ymm1 += (B10[0][0]*A01[0][1] B10[1][0]*A01[0][1] B10[2][0]*A01[0][1] B10[3][0]*A01[0][1]) ymm4 = _mm256_fmadd_pd(ymm8, ymm13, ymm4); //ymm4 += (B10[4][0]*A01[0][0] B10[5][0]*A01[0][0] B10[6][0]*A01[0][0] B10[7][0]*A01[0][0]) ymm5 = _mm256_fmadd_pd(ymm9, ymm13, ymm5); //ymm5 += (B10[4][0]*A01[0][1] B10[5][0]*A01[0][1] B10[6][0]*A01[0][1] B10[7][0]*A01[0][1]) //broadcast 2nd row of A01 ymm8 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 0)); //A01[1][0] ymm9 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 1)); //A01[1][1] a01 += 1; //move to next row of A ymm0 = _mm256_fmadd_pd(ymm8, ymm14, ymm0); //ymm0 += (B10[0][1]*A01[0][0] B10[1][1]*A01[0][0] B10[2][1]*A01[0][0] B10[3][1]*A01[0][0]) ymm1 = _mm256_fmadd_pd(ymm9, ymm14, ymm1); //ymm1 += (B10[0][1]*A01[0][1] B10[1][1]*A01[0][1] B10[2][1]*A01[0][1] B10[3][1]*A01[0][1]) ymm4 = _mm256_fmadd_pd(ymm8, ymm15, ymm4); //ymm4 += (B10[4][1]*A01[0][0] B10[5][1]*A01[0][0] B10[6][1]*A01[0][0] B10[7][1]*A01[0][0]) ymm5 = _mm256_fmadd_pd(ymm9, ymm15, ymm5); //ymm5 += (B10[4][1]*A01[0][1] B10[5][1]*A01[0][1] B10[6][1]*A01[0][1] B10[7][1]*A01[0][1]) //broadcast 3rd row of A01 ymm8 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 0)); //A01[2][0] ymm9 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 1)); //A01[2][1] a01 += 1; //move to next row of A //load next 8x2 block of B10 ymm12 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0])); //(B10[0][2] B10[1][2] B10[2][2] B10[3][2]) ymm13 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + D_NR)); //(B10[4][2] B10[5][2] B10[6][2] B10[7][2]) ymm14 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + cs_b)); //(B10[0][3] B10[1][3] B10[2][3] B10[3][3]) ymm15 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + cs_b + D_NR)); //(B10[4][3] B10[5][3] B10[6][3] B10[7][3]) ymm0 = _mm256_fmadd_pd(ymm8, ymm12, ymm0); //ymm0 += (B10[0][2]*A01[0][0] B10[1][2]*A01[0][0] B10[2][2]*A01[0][0] B10[3][2]*A01[0][0]) ymm1 = _mm256_fmadd_pd(ymm9, ymm12, ymm1); //ymm1 += (B10[0][2]*A01[0][1] B10[1][2]*A01[0][1] B10[2][2]*A01[0][1] B10[3][2]*A01[0][1]) ymm4 = _mm256_fmadd_pd(ymm8, ymm13, ymm4); //ymm4 += (B10[4][2]*A01[0][0] B10[5][2]*A01[0][0] B10[6][2]*A01[0][0] B10[7][2]*A01[0][0]) ymm5 = _mm256_fmadd_pd(ymm9, ymm13, ymm5); //ymm5 += (B10[4][2]*A01[0][1] B10[5][2]*A01[0][1] B10[6][2]*A01[0][1] B10[7][2]*A01[0][1]) //broadcast 4th row of A01 ymm8 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 0)); //A01[3][0] ymm9 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 1)); //A01[3][1] a01 += 1; //move to next row of A ymm0 = _mm256_fmadd_pd(ymm8, ymm14, ymm0); //ymm0 += (B10[0][3]*A01[0][0] B10[1][3]*A01[0][0] B10[2][3]*A01[0][0] B10[3][3]*A01[0][0]) ymm1 = _mm256_fmadd_pd(ymm9, ymm14, ymm1); //ymm1 += (B10[0][3]*A01[0][1] B10[1][3]*A01[0][1] B10[2][3]*A01[0][1] B10[3][3]*A01[0][1]) ymm4 = _mm256_fmadd_pd(ymm8, ymm15, ymm4); //ymm4 += (B10[4][3]*A01[0][0] B10[5][3]*A01[0][0] B10[6][3]*A01[0][0] B10[7][3]*A01[0][0]) ymm5 = _mm256_fmadd_pd(ymm9, ymm15, ymm5); //ymm5 += (B10[4][3]*A01[0][1] B10[5][3]*A01[0][1] B10[6][3]*A01[0][1] B10[7][3]*A01[0][1]) b10 += D_NR * cs_b; //pointer math to find next block of B for GEMM a01 = ptr_a01_dup + D_NR; //pointer math to find next block of A for GEMM } ymm15 = _mm256_broadcast_sd((double const *)&AlphaVal); ///GEMM code ends/// ymm8 = _mm256_loadu_pd((double const *)b11); //B11[0-3][0] ymm12 = _mm256_loadu_pd((double const *)(b11 + D_NR)); //B11[4-7][0] ymm9 = _mm256_loadu_pd((double const *)(b11 + cs_b)); //B11[0-3][1] ymm13 = _mm256_loadu_pd((double const *)(b11 + cs_b + D_NR)); //B11[4-7][1] ymm8 = _mm256_fmsub_pd(ymm8, ymm15, ymm0); //B11[0-3][0] * alpha -= B10[0-3][0] ymm9 = _mm256_fmsub_pd(ymm9, ymm15, ymm1); //B11[4-7][0] * alpha -= B10[4-7][0] ymm12 = _mm256_fmsub_pd(ymm12, ymm15, ymm4); //B11[0-3][2] * alpha -= B10[0-3][2] ymm13 = _mm256_fmsub_pd(ymm13, ymm15, ymm5); //B11[4-7][2] * alpha -= B10[4-7][2] ///implement TRSM/// ///read 4x4 block of A11/// ymm7 = _mm256_broadcast_sd((double const *)(&ones)); //1st col ymm0 = _mm256_broadcast_sd((double const *)(a11+0)); //A11[0][0] //2nd col a11 += cs_a; ymm1 = _mm256_broadcast_sd((double const *)(a11+0)); //A11[0][1] ymm2 = _mm256_broadcast_sd((double const *)(a11+1)); //A11[1][1] //compute reciprocals of L(i,i) and broadcast in registers ymm0 = _mm256_unpacklo_pd(ymm0, ymm2); //A11[0][0] A11[1][1] A11[0][0] A11[1][1] ymm0 = _mm256_blend_pd(ymm0, ymm7, 0x0C); //A11[0][0] A11[1][1] 1 1 ymm7 = _mm256_div_pd(ymm7, ymm0); //(1/A11[0][0] 1/A11[1][1] 1/1 1/1) //extract a00 ymm0 = _mm256_permute_pd(ymm7, 0x00); //(1/A11[0][0] 1/A11[0][0] 1/A11[2][2] 1/A11[2][2]) ymm0 = _mm256_permute2f128_pd(ymm0, ymm0, 0x00);//(1/A11[0][0] 1/A11[0][0] 1/A11[0][0] 1/A11[0][0]) ymm8 = _mm256_mul_pd(ymm8, ymm0); //B11[0-3][0] /= A11[0][0] ymm12 = _mm256_mul_pd(ymm12, ymm0); //B11[4-7][0] /= A11[0][0] //extract a11 ymm0 = _mm256_permute_pd(ymm7, 0x03); //(1/A11[1][1] 1/A11[1][1] 1/A11[2][2] 1/A11[2][2]) ymm0 = _mm256_permute2f128_pd(ymm0, ymm0, 0x00);//(1/A11[1][1] 1/A11[1][1] 1/A11[1][1] 1/A11[1][1]) //(Row1): FMA operations ymm9 = _mm256_fnmadd_pd(ymm1, ymm8, ymm9); //B11[0-3][1] -= B11[0-3][0] * A11[0][1] ymm13 = _mm256_fnmadd_pd(ymm1, ymm12, ymm13); //B11[4-7][1] -= B11[4-7][0] * A11[0][1] ymm9 = _mm256_mul_pd(ymm9, ymm0); //B11[0-3][1] /= A11[1][1] ymm13 = _mm256_mul_pd(ymm13, ymm0); //B11[4-7][1] /= A11[1][1] _mm256_storeu_pd((double *)b11, ymm8); //store(B11[0-3][0]) _mm256_storeu_pd((double *)(b11 + D_NR), ymm12); //store(B11[4-7][0]) _mm256_storeu_pd((double *)(b11 + cs_b), ymm9); //store(B11[0-3][1]) _mm256_storeu_pd((double *)(b11 + cs_b + D_NR), ymm13); //store(B11[4-7][1]) } else if(1 == n_remainder) { ///GEMM implementation begins/// for(k = 0; k < k_iter; k++) ///loop for number of GEMM operations { ptr_a01_dup = a01; //broadcast 1st row of A01 ymm8 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 0)); //A01[0][0] a01 += 1; //move to next row of A //load 8x2 block of B10 ymm12 = _mm256_loadu_pd((double const *)b10); //B10[0][0] B10[1][0] B10[2][0] B10[3][0] ymm13 = _mm256_loadu_pd((double const *)(b10 + D_NR)); //B10[4][0] B10[5][0] B10[6][0] B10[7][0] ymm14 = _mm256_loadu_pd((double const *)(b10 + cs_b)); //B10[0][1] B10[1][1] B10[2][1] B10[3][1] ymm15 = _mm256_loadu_pd((double const *)(b10 + cs_b + D_NR));//B10[4][1] B10[5][1] B10[6][1] B10[7][1] ymm0 = _mm256_fmadd_pd(ymm8, ymm12, ymm0); //ymm0 += (B10[0][0]*A01[0][0] B10[1][0]*A01[0][0] B10[2][0]*A01[0][0] B10[3][0]*A01[0][0]) ymm4 = _mm256_fmadd_pd(ymm8, ymm13, ymm4); //ymm4 += (B10[4][0]*A01[0][0] B10[5][0]*A01[0][0] B10[6][0]*A01[0][0] B10[7][0]*A01[0][0]) //broadcast 2nd row of A01 ymm8 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 0)); //A01[1][0] a01 += 1; //move to next row of A ymm0 = _mm256_fmadd_pd(ymm8, ymm14, ymm0); //ymm0 += (B10[0][1]*A01[0][0] B10[1][1]*A01[0][0] B10[2][1]*A01[0][0] B10[3][1]*A01[0][0]) ymm4 = _mm256_fmadd_pd(ymm8, ymm15, ymm4); //ymm4 += (B10[4][1]*A01[0][0] B10[5][1]*A01[0][0] B10[6][1]*A01[0][0] B10[7][1]*A01[0][0]) //broadcast 3rd row of A01 ymm8 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 0)); //A01[2][0] a01 += 1; //move to next row of A //load next 8x2 block of B10 ymm12 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0])); //(B10[0][2] B10[1][2] B10[2][2] B10[3][2]) ymm13 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + D_NR)); //(B10[4][2] B10[5][2] B10[6][2] B10[7][2]) ymm14 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + cs_b)); //(B10[0][3] B10[1][3] B10[2][3] B10[3][3]) ymm15 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + cs_b + D_NR)); //(B10[4][3] B10[5][3] B10[6][3] B10[7][3]) ymm0 = _mm256_fmadd_pd(ymm8, ymm12, ymm0); //ymm0 += (B10[0][2]*A01[0][0] B10[1][2]*A01[0][0] B10[2][2]*A01[0][0] B10[3][2]*A01[0][0]) ymm4 = _mm256_fmadd_pd(ymm8, ymm13, ymm4); //ymm4 += (B10[4][2]*A01[0][0] B10[5][2]*A01[0][0] B10[6][2]*A01[0][0] B10[7][2]*A01[0][0]) //broadcast 4th row of A01 ymm8 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 0)); //A01[3][0] a01 += 1; //move to next row of A ymm0 = _mm256_fmadd_pd(ymm8, ymm14, ymm0); //ymm0 += (B10[0][3]*A01[0][0] B10[1][3]*A01[0][0] B10[2][3]*A01[0][0] B10[3][3]*A01[0][0]) ymm4 = _mm256_fmadd_pd(ymm8, ymm15, ymm4); //ymm4 += (B10[4][3]*A01[0][0] B10[5][3]*A01[0][0] B10[6][3]*A01[0][0] B10[7][3]*A01[0][0]) b10 += D_NR * cs_b; //pointer math to find next block of B for GEMM a01 = ptr_a01_dup + D_NR; //pointer math to find next block of A for GEMM } ymm15 = _mm256_broadcast_sd((double const *)&AlphaVal); ///GEMM code ends/// ymm8 = _mm256_loadu_pd((double const *)b11); //B11[0-3][0] ymm12 = _mm256_loadu_pd((double const *)(b11 + D_NR)); //B11[4-7][0] ymm8 = _mm256_fmsub_pd(ymm8, ymm15, ymm0); //B11[0-3][0] * alpha -= B10[0-3][0] ymm12 = _mm256_fmsub_pd(ymm12, ymm15, ymm4); //B11[0-3][2] * alpha -= B10[0-3][2] ///implement TRSM/// ///read 4x4 block of A11/// ymm7 = _mm256_broadcast_sd((double const *)(&ones)); //1st col ymm0 = _mm256_broadcast_sd((double const *)(a11+0)); //A11[0][0] ymm7 = _mm256_div_pd(ymm7, ymm0); //(1/A11[0][0] 1/A11[1][1] 1/A11[2][2] 1/A11[3][3]) //extract a00 ymm0 = _mm256_permute_pd(ymm7, 0x00); //(1/A11[0][0] 1/A11[0][0] 1/A11[2][2] 1/A11[2][2]) ymm0 = _mm256_permute2f128_pd(ymm0, ymm0, 0x00);//(1/A11[0][0] 1/A11[0][0] 1/A11[0][0] 1/A11[0][0]) ymm8 = _mm256_mul_pd(ymm8, ymm0); //B11[0-3][0] /= A11[0][0] ymm12 = _mm256_mul_pd(ymm12, ymm0); //B11[4-7][0] /= A11[0][0] _mm256_storeu_pd((double *)b11, ymm8); //store(B11[0-3][0]) _mm256_storeu_pd((double *)(b11 + D_NR), ymm12); //store(B11[4-7][0]) } } } if((m & 4)) ///implementation for remainder rows(when m_remainder is greater than 4) { for(j = 0; (j+D_NR-1) a01 ----> ***************** *********** *b01*b11* * * * * * * b11 * * * * * **a01 * * a11 | ***************** ********* | | * * * * * *a11* * | | * * * * * * * * | v ***************** ****** v * * * * * * * * * * * * * * ***************** * * * */ static err_t bli_dtrsm_small_XAuB_unitDiag( side_t side, obj_t* AlphaObj, obj_t* a, obj_t* b, cntx_t* cntx, cntl_t* cntl ) { dim_t D_MR = 8; //block dimension along the rows dim_t D_NR = 4; //block dimension along the columns dim_t m = bli_obj_length(b); //number of rows dim_t n = bli_obj_width(b); //number of columns dim_t m_remainder = m & 7; //number of corner rows dim_t n_remainder = n & 3; //number of corner columns dim_t cs_a = bli_obj_col_stride(a); //column stride of matrix A dim_t cs_b = bli_obj_col_stride(b); //column stride of matrix B #ifdef BLIS_ENABLE_SMALL_MATRIX_ROME if((m>D_BLIS_SMALL_MATRIX_THRES_TRSM_XAUB_ROME_ROW_PANEL_M && n>D_BLIS_SMALL_MATRIX_THRES_TRSM_XAUB_ROME) || (m>D_BLIS_SMALL_MATRIX_THRES_TRSM_XAUB_ROME && n>D_BLIS_SMALL_MATRIX_THRES_TRSM_XAUB_ROME_COLUMN_PANEL_N) ) return BLIS_NOT_YET_IMPLEMENTED; #else if(bli_max(m,n)>D_BLIS_SMALL_MATRIX_THRES_TRSM_NAPLES && (m/n) < D_BLIS_SMALL_MATRIX_THRES_TRSM_DIM_RATIO) { return BLIS_NOT_YET_IMPLEMENTED; } #endif dim_t i, j, k; //loop variablse dim_t k_iter; //determines the number of GEMM operations to be done dim_t cs_b_offset[2]; //pre-calculated strides double ones = 1.0; double AlphaVal = *(double *)AlphaObj->buffer; //value of Alpha double *L = a->buffer; //pointer to matrix A double *B = b->buffer; //pointer to matrix B double *a01, *a11, *b10, *b11; //pointers for GEMM and TRSM blocks double *ptr_a01_dup; double f_t[4] __attribute__((aligned(64)));//buffer to store corner column when m_remainder !=0 double* f_temp; cs_b_offset[0] = cs_b << 1; //cs_b_offset[0] = cs_b * 2; cs_b_offset[1] = cs_b_offset[0] + cs_b;//cs_b_offset[1] = cs_b * 3; //ymm scratch reginsters __m256d ymm0, ymm1, ymm2, ymm3; __m256d ymm4, ymm5, ymm6, ymm7; __m256d ymm8, ymm9, ymm10, ymm11; __m256d ymm12, ymm13, ymm14, ymm15; __m256d ymm16; for(i = 0; (i+D_MR-1) < m; i += D_MR) //loop along 'M' direction { for(j = 0; (j+D_NR-1) < n; j += D_NR) //loop along 'N' direction { a01 = L + j*cs_a; //pointer to block of A to be used in GEMM a11 = L + j*cs_a + j; //pointer to block of A to be used for TRSM b10 = B + i; //pointer to block of B to be used in GEMM b11 = B + i + j*cs_b; //pointer to block of B to be used for TRSM k_iter = j / D_NR; //number of GEMM operations to be done(in blocks of 4x4) ymm0 = _mm256_setzero_pd(); ymm1 = _mm256_setzero_pd(); ymm2 = _mm256_setzero_pd(); ymm3 = _mm256_setzero_pd(); ymm4 = _mm256_setzero_pd(); ymm5 = _mm256_setzero_pd(); ymm6 = _mm256_setzero_pd(); ymm7 = _mm256_setzero_pd(); ///GEMM implementation starts/// for(k = 0; k < k_iter; k++) //loop for number of GEMM operations { ptr_a01_dup = a01; //broadcast 1st row of A01 ymm8 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 0)); //A01[0][0] ymm9 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 1)); //A01[0][1] ymm10 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 2)); //A01[0][2] ymm11 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 3)); //A01[0][3] a01 += 1; //move to next row //load 8x2 block of B10 ymm12 = _mm256_loadu_pd((double const *)b10); //B10[0][0] B10[1][0] B10[2][0] B10[3][0] ymm13 = _mm256_loadu_pd((double const *)(b10 + D_NR)); //B10[4][0] B10[5][0] B10[6][0] B10[7][0] ymm14 = _mm256_loadu_pd((double const *)(b10 + cs_b)); //B10[0][1] B10[1][1] B10[2][1] B10[3][1] ymm15 = _mm256_loadu_pd((double const *)(b10 + cs_b + D_NR)); //B10[4][1] B10[5][1] B10[6][1] B10[7][1] ymm0 = _mm256_fmadd_pd(ymm8, ymm12, ymm0); //ymm0 += (B10[0][0]*A01[0][0] B10[1][0]*A01[0][0] B10[2][0]*A01[0][0] B10[3][0]*A01[0][0]) ymm1 = _mm256_fmadd_pd(ymm9, ymm12, ymm1); //ymm1 += (B10[0][0]*A01[0][1] B10[1][0]*A01[0][1] B10[2][0]*A01[0][1] B10[3][0]*A01[0][1]) ymm2 = _mm256_fmadd_pd(ymm10, ymm12, ymm2); //ymm2 += (B10[0][0]*A01[0][2] B10[1][0]*A01[0][2] B10[2][0]*A01[0][2] B10[3][0]*A01[0][2]) ymm3 = _mm256_fmadd_pd(ymm11, ymm12, ymm3); //ymm3 += (B10[0][0]*A01[0][3] B10[1][0]*A01[0][3] B10[2][0]*A01[0][3] B10[3][0]*A01[0][3]) ymm4 = _mm256_fmadd_pd(ymm8, ymm13, ymm4); //ymm4 += (B10[4][0]*A01[0][0] B10[5][0]*A01[0][0] B10[6][0]*A01[0][0] B10[7][0]*A01[0][0]) ymm5 = _mm256_fmadd_pd(ymm9, ymm13, ymm5); //ymm5 += (B10[4][0]*A01[0][1] B10[5][0]*A01[0][1] B10[6][0]*A01[0][1] B10[7][0]*A01[0][1]) ymm6 = _mm256_fmadd_pd(ymm10, ymm13, ymm6); //ymm6 += (B10[4][0]*A01[0][2] B10[5][0]*A01[0][2] B10[6][0]*A01[0][2] B10[7][0]*A01[0][2]) ymm7 = _mm256_fmadd_pd(ymm11, ymm13, ymm7); //ymm7 += (B10[4][0]*A01[0][3] B10[5][0]*A01[0][3] B10[6][0]*A01[0][3] B10[7][0]*A01[0][3]) //broadcast 2nd row of A01 ymm8 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 0)); //A01[1][0] ymm9 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 1)); //A01[1][1] ymm10 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 2)); //A01[1][2] ymm11 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 3)); //A01[1][3] a01 += 1; //move to next row of A ymm0 = _mm256_fmadd_pd(ymm8, ymm14, ymm0); //ymm0 += (B10[0][1]*A01[0][0] B10[1][1]*A01[0][0] B10[2][1]*A01[0][0] B10[3][1]*A01[0][0]) ymm1 = _mm256_fmadd_pd(ymm9, ymm14, ymm1); //ymm1 += (B10[0][1]*A01[0][1] B10[1][1]*A01[0][1] B10[2][1]*A01[0][1] B10[3][1]*A01[0][1]) ymm2 = _mm256_fmadd_pd(ymm10, ymm14, ymm2); //ymm2 += (B10[0][1]*A01[0][2] B10[1][1]*A01[0][2] B10[2][1]*A01[0][2] B10[3][1]*A01[0][2]) ymm3 = _mm256_fmadd_pd(ymm11, ymm14, ymm3); //ymm3 += (B10[0][1]*A01[0][3] B10[1][1]*A01[0][3] B10[2][1]*A01[0][3] B10[3][1]*A01[0][3]) ymm4 = _mm256_fmadd_pd(ymm8, ymm15, ymm4); //ymm4 += (B10[4][1]*A01[0][0] B10[5][1]*A01[0][0] B10[6][1]*A01[0][0] B10[7][1]*A01[0][0]) ymm5 = _mm256_fmadd_pd(ymm9, ymm15, ymm5); //ymm5 += (B10[4][1]*A01[0][1] B10[5][1]*A01[0][1] B10[6][1]*A01[0][1] B10[7][1]*A01[0][1]) ymm6 = _mm256_fmadd_pd(ymm10, ymm15, ymm6); //ymm6 += (B10[4][1]*A01[0][2] B10[5][1]*A01[0][2] B10[6][1]*A01[0][2] B10[7][1]*A01[0][2]) ymm7 = _mm256_fmadd_pd(ymm11, ymm15, ymm7); //ymm7 += (B10[4][1]*A01[0][3] B10[5][1]*A01[0][3] B10[6][1]*A01[0][3] B10[7][1]*A01[0][3]) //broadcast 3rd row of A01 ymm8 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 0)); //A01[2][0] ymm9 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 1)); //A01[2][1] ymm10 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 2)); //A01[2][2] ymm11 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 3)); //A01[2][3] a01 += 1; //move to next row of A01 //load next 8x2 block of B10 ymm12 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0])); //(B10[0][2] B10[1][2] B10[2][2] B10[3][2]) ymm13 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + D_NR)); //(B10[4][2] B10[5][2] B10[6][2] B10[7][2]) ymm14 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + cs_b)); //(B10[0][3] B10[1][3] B10[2][3] B10[3][3]) ymm15 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + cs_b + D_NR)); //(B10[4][3] B10[5][3] B10[6][3] B10[7][3]) ymm0 = _mm256_fmadd_pd(ymm8, ymm12, ymm0); //ymm0 += (B10[0][2]*A01[0][0] B10[1][2]*A01[0][0] B10[2][2]*A01[0][0] B10[3][2]*A01[0][0]) ymm1 = _mm256_fmadd_pd(ymm9, ymm12, ymm1); //ymm1 += (B10[0][2]*A01[0][1] B10[1][2]*A01[0][1] B10[2][2]*A01[0][1] B10[3][2]*A01[0][1]) ymm2 = _mm256_fmadd_pd(ymm10, ymm12, ymm2); //ymm2 += (B10[0][2]*A01[0][2] B10[1][2]*A01[0][2] B10[2][2]*A01[0][2] B10[3][2]*A01[0][2]) ymm3 = _mm256_fmadd_pd(ymm11, ymm12, ymm3); //ymm3 += (B10[0][2]*A01[0][3] B10[1][2]*A01[0][3] B10[2][2]*A01[0][3] B10[3][2]*A01[0][3]) ymm4 = _mm256_fmadd_pd(ymm8, ymm13, ymm4); //ymm4 += (B10[4][2]*A01[0][0] B10[5][2]*A01[0][0] B10[6][2]*A01[0][0] B10[7][2]*A01[0][0]) ymm5 = _mm256_fmadd_pd(ymm9, ymm13, ymm5); //ymm5 += (B10[4][2]*A01[0][1] B10[5][2]*A01[0][1] B10[6][2]*A01[0][1] B10[7][2]*A01[0][1]) ymm6 = _mm256_fmadd_pd(ymm10, ymm13, ymm6); //ymm6 += (B10[4][2]*A01[0][2] B10[5][2]*A01[0][2] B10[6][2]*A01[0][2] B10[7][2]*A01[0][2]) ymm7 = _mm256_fmadd_pd(ymm11, ymm13, ymm7); //ymm7 += (B10[4][2]*A01[0][3] B10[5][2]*A01[0][3] B10[6][2]*A01[0][3] B10[7][2]*A01[0][3]) //broadcast 4th row of A01 ymm8 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 0)); //A01[3][0] ymm9 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 1)); //A01[3][1] ymm10 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 2)); //A01[3][2] ymm11 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 3)); //A01[3][3] a01 += 1; //move to next row of A01 ymm0 = _mm256_fmadd_pd(ymm8, ymm14, ymm0); //ymm0 += (B10[0][3]*A01[0][0] B10[1][3]*A01[0][0] B10[2][3]*A01[0][0] B10[3][3]*A01[0][0]) ymm1 = _mm256_fmadd_pd(ymm9, ymm14, ymm1); //ymm1 += (B10[0][3]*A01[0][1] B10[1][3]*A01[0][1] B10[2][3]*A01[0][1] B10[3][3]*A01[0][1]) ymm2 = _mm256_fmadd_pd(ymm10, ymm14, ymm2); //ymm2 += (B10[0][3]*A01[0][2] B10[1][3]*A01[0][2] B10[2][3]*A01[0][2] B10[3][3]*A01[0][2]) ymm3 = _mm256_fmadd_pd(ymm11, ymm14, ymm3); //ymm3 += (B10[0][3]*A01[0][3] B10[1][3]*A01[0][3] B10[2][3]*A01[0][3] B10[3][3]*A01[0][3]) ymm4 = _mm256_fmadd_pd(ymm8, ymm15, ymm4); //ymm4 += (B10[4][3]*A01[0][0] B10[5][3]*A01[0][0] B10[6][3]*A01[0][0] B10[7][3]*A01[0][0]) ymm5 = _mm256_fmadd_pd(ymm9, ymm15, ymm5); //ymm5 += (B10[4][3]*A01[0][1] B10[5][3]*A01[0][1] B10[6][3]*A01[0][1] B10[7][3]*A01[0][1]) ymm6 = _mm256_fmadd_pd(ymm10, ymm15, ymm6); //ymm6 += (B10[4][3]*A01[0][2] B10[5][3]*A01[0][2] B10[6][3]*A01[0][2] B10[7][3]*A01[0][2]) ymm7 = _mm256_fmadd_pd(ymm11, ymm15, ymm7); //ymm7 += (B10[4][3]*A01[0][3] B10[5][3]*A01[0][3] B10[6][3]*A01[0][3] B10[7][3]*A01[0][3]) b10 += D_NR * cs_b; //pointer math to find next block of B for GEMM a01 = ptr_a01_dup + D_NR; //pointer math to find next block of A for GEMM } ///GEMM code ends/// ymm16 = _mm256_broadcast_sd((double const *)&AlphaVal); //load 8x4 block of B11 ymm8 = _mm256_loadu_pd((double const *)b11); //B11[0][0] B11[1][0] B11[2][0] B11[3][0] ymm12 = _mm256_loadu_pd((double const *)(b11 + D_NR)); //B11[4][0] B11[5][0] B11[6][0] B11[7][0] ymm9 = _mm256_loadu_pd((double const *)(b11 + cs_b)); //B11[0][1] B11[1][1] B11[2][1] B11[3][1] ymm13 = _mm256_loadu_pd((double const *)(b11 + cs_b + D_NR)); //B11[4][1] B11[5][1] B11[6][1] B11[7][1] ymm10 = _mm256_loadu_pd((double const *)(b11 + cs_b_offset[0])); //B11[0][2] B11[1][2] B11[2][2] B11[3][2] ymm14 = _mm256_loadu_pd((double const *)(b11 + cs_b_offset[0] + D_NR)); //B11[4][2] B11[5][2] B11[6][2] B11[7][2] ymm11 = _mm256_loadu_pd((double const *)(b11 + cs_b_offset[1])); //B11[0][3] B11[1][3] B11[2][3] B11[3][3] ymm15 = _mm256_loadu_pd((double const *)(b11 + cs_b_offset[1] + D_NR)); //B11[4][3] B11[5][3] B11[6][3] B11[7][3] ymm8 = _mm256_fmsub_pd(ymm8, ymm16, ymm0); //B11[0-3][0] * alpha -= ymm0 ymm9 = _mm256_fmsub_pd(ymm9, ymm16, ymm1); //B11[4-7][0] * alpha-= ymm1 ymm10 = _mm256_fmsub_pd(ymm10, ymm16, ymm2); //B11[0-3][1] * alpha-= ymm2 ymm11 = _mm256_fmsub_pd(ymm11, ymm16, ymm3); //B11[4-7][1] * alpha -= ymm3 ymm12 = _mm256_fmsub_pd(ymm12, ymm16, ymm4); //B11[0-3][2] * alpha -= ymm4 ymm13 = _mm256_fmsub_pd(ymm13, ymm16, ymm5); //B11[4-7][2] * alpha -= ymm5 ymm14 = _mm256_fmsub_pd(ymm14, ymm16, ymm6); //B11[0-3][3] * alpha -= ymm6 ymm15 = _mm256_fmsub_pd(ymm15, ymm16, ymm7); //B11[4-7][3] * alpha -= ymm7 ///implement TRSM/// ///read 4x4 block of A11/// ymm7 = _mm256_broadcast_sd((double const *)(&ones)); //2nd col a11 += cs_a; ymm1 = _mm256_broadcast_sd((double const *)(a11+0)); //A11[0][1] //3rd col a11 += cs_a; ymm3 = _mm256_broadcast_sd((double const *)(a11+0)); //A11[0][2] ymm4 = _mm256_broadcast_sd((double const *)(a11+1)); //A11[1][2] //4th col a11 += cs_a; ymm2 = _mm256_broadcast_sd((double const *)(a11+0)); //A11[0][3] ymm5 = _mm256_broadcast_sd((double const *)(a11+1)); //A11[1][3] ymm6 = _mm256_broadcast_sd((double const *)(a11+2)); //A11[2][3] //(Row1): FMA operations ymm9 = _mm256_fnmadd_pd(ymm1, ymm8, ymm9); //B11[0-3][1] -= B11[0-3][0] * A11[0][1] ymm10 = _mm256_fnmadd_pd(ymm3, ymm8, ymm10); //B11[0-3][2] -= B11[0-3][0] * A11[0][2] ymm11 = _mm256_fnmadd_pd(ymm2, ymm8, ymm11); //B11[0-3][3] -= B11[0-3][0] * A11[0][3] ymm13 = _mm256_fnmadd_pd(ymm1, ymm12, ymm13); //B11[4-7][1] -= B11[4-7][0] * A11[0][1] ymm14 = _mm256_fnmadd_pd(ymm3, ymm12, ymm14); //B11[4-7][2] -= B11[4-7][0] * A11[0][2] ymm15 = _mm256_fnmadd_pd(ymm2, ymm12, ymm15); //B11[4-7][3] -= B11[4-7][0] * A11[0][3] //(Row2)FMA operations ymm10 = _mm256_fnmadd_pd(ymm4, ymm9, ymm10); //B11[0-3][2] -= B11[0-3][1] * A11[1][2] ymm11 = _mm256_fnmadd_pd(ymm5, ymm9, ymm11); //B11[0-3][3] -= B11[0-3][1] * A11[1][3] ymm14 = _mm256_fnmadd_pd(ymm4, ymm13, ymm14); //B11[4-7][2] -= B11[4-7][1] * A11[1][2] ymm15 = _mm256_fnmadd_pd(ymm5, ymm13, ymm15); //B11[4-7][3] -= B11[4-7][1] * A11[1][3] //(Row3)FMA operations ymm11 = _mm256_fnmadd_pd(ymm6, ymm10, ymm11); //B11[0-3][3] -= B11[0-3][2] * A11[2][3] ymm15 = _mm256_fnmadd_pd(ymm6, ymm14, ymm15); //B11[4-7][3] -= B11[4-7][2] * A11[2][3] _mm256_storeu_pd((double *)b11, ymm8); //store(B11[0-3][0]) _mm256_storeu_pd((double *)(b11 + D_NR), ymm12); //store(B11[4-7][0]) _mm256_storeu_pd((double *)(b11 + cs_b), ymm9); //store(B11[0-3][1]) _mm256_storeu_pd((double *)(b11 + cs_b + D_NR), ymm13); //store(B11[4-7][1]) _mm256_storeu_pd((double *)(b11 + cs_b_offset[0]), ymm10); //store(B11[0-3][2]) _mm256_storeu_pd((double *)(b11 + cs_b_offset[0] + D_NR), ymm14); //store(B11[4-7][2]) _mm256_storeu_pd((double *)(b11 + cs_b_offset[0] + cs_b), ymm11); //store(B11[0-3][3]) _mm256_storeu_pd((double *)(b11 + cs_b_offset[0] + cs_b + D_NR), ymm15);//store(B11[4-7][3]) } if(n_remainder) //implementation for remainder columns(when n is not multiple of D_NR) { a01 = L + j*cs_a; //pointer to block of A to be used for GEMM a11 = L + j*cs_a + j; //pointer to block of A to be used for TRSM b10 = B + i; //pointer to block of B to be used for GEMM b11 = B + i + j*cs_b; //pointer to block of B to be used for TRSM k_iter = j / D_NR; //number of GEMM operations to be performed(in blocks of 4x4) ///load 4x4 block of b11 ymm0 = _mm256_setzero_pd(); ymm1 = _mm256_setzero_pd(); ymm2 = _mm256_setzero_pd(); ymm3 = _mm256_setzero_pd(); ymm4 = _mm256_setzero_pd(); ymm5 = _mm256_setzero_pd(); ymm6 = _mm256_setzero_pd(); ymm7 = _mm256_setzero_pd(); //subtract the calculated GEMM block from current TRSM block //load 8x4 block of B11 if(3 == n_remainder) { ///GEMM implementation begins/// for(k = 0; k < k_iter; k++) ///loop for number of GEMM operations { ptr_a01_dup = a01; //broadcast 1st row of A01 ymm8 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 0)); //A01[0][0] ymm9 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 1)); //A01[0][1] ymm10 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 2)); //A01[0][2] a01 += 1; //move to next row of A //load 8x2 block of B10 ymm12 = _mm256_loadu_pd((double const *)b10); //B10[0][0] B10[1][0] B10[2][0] B10[3][0] ymm13 = _mm256_loadu_pd((double const *)(b10 + D_NR)); //B10[4][0] B10[5][0] B10[6][0] B10[7][0] ymm14 = _mm256_loadu_pd((double const *)(b10 + cs_b)); //B10[0][1] B10[1][1] B10[2][1] B10[3][1] ymm15 = _mm256_loadu_pd((double const *)(b10 + cs_b + D_NR));//B10[4][1] B10[5][1] B10[6][1] B10[7][1] ymm0 = _mm256_fmadd_pd(ymm8, ymm12, ymm0); //ymm0 += (B10[0][0]*A01[0][0] B10[1][0]*A01[0][0] B10[2][0]*A01[0][0] B10[3][0]*A01[0][0]) ymm1 = _mm256_fmadd_pd(ymm9, ymm12, ymm1); //ymm1 += (B10[0][0]*A01[0][1] B10[1][0]*A01[0][1] B10[2][0]*A01[0][1] B10[3][0]*A01[0][1]) ymm2 = _mm256_fmadd_pd(ymm10, ymm12, ymm2); //ymm2 += (B10[0][0]*A01[0][2] B10[1][0]*A01[0][2] B10[2][0]*A01[0][2] B10[3][0]*A01[0][2]) ymm4 = _mm256_fmadd_pd(ymm8, ymm13, ymm4); //ymm4 += (B10[4][0]*A01[0][0] B10[5][0]*A01[0][0] B10[6][0]*A01[0][0] B10[7][0]*A01[0][0]) ymm5 = _mm256_fmadd_pd(ymm9, ymm13, ymm5); //ymm5 += (B10[4][0]*A01[0][1] B10[5][0]*A01[0][1] B10[6][0]*A01[0][1] B10[7][0]*A01[0][1]) ymm6 = _mm256_fmadd_pd(ymm10, ymm13, ymm6); //ymm6 += (B10[4][0]*A01[0][2] B10[5][0]*A01[0][2] B10[6][0]*A01[0][2] B10[7][0]*A01[0][2]) //broadcast 2nd row of A01 ymm8 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 0)); //A01[1][0] ymm9 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 1)); //A01[1][1] ymm10 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 2)); //A01[1][2] a01 += 1; //move to next row of A ymm0 = _mm256_fmadd_pd(ymm8, ymm14, ymm0); //ymm0 += (B10[0][1]*A01[0][0] B10[1][1]*A01[0][0] B10[2][1]*A01[0][0] B10[3][1]*A01[0][0]) ymm1 = _mm256_fmadd_pd(ymm9, ymm14, ymm1); //ymm1 += (B10[0][1]*A01[0][1] B10[1][1]*A01[0][1] B10[2][1]*A01[0][1] B10[3][1]*A01[0][1]) ymm2 = _mm256_fmadd_pd(ymm10, ymm14, ymm2); //ymm2 += (B10[0][1]*A01[0][2] B10[1][1]*A01[0][2] B10[2][1]*A01[0][2] B10[3][1]*A01[0][2]) ymm4 = _mm256_fmadd_pd(ymm8, ymm15, ymm4); //ymm4 += (B10[4][1]*A01[0][0] B10[5][1]*A01[0][0] B10[6][1]*A01[0][0] B10[7][1]*A01[0][0]) ymm5 = _mm256_fmadd_pd(ymm9, ymm15, ymm5); //ymm5 += (B10[4][1]*A01[0][1] B10[5][1]*A01[0][1] B10[6][1]*A01[0][1] B10[7][1]*A01[0][1]) ymm6 = _mm256_fmadd_pd(ymm10, ymm15, ymm6); //ymm6 += (B10[4][1]*A01[0][2] B10[5][1]*A01[0][2] B10[6][1]*A01[0][2] B10[7][1]*A01[0][2]) //broadcast 3rd row of A01 ymm8 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 0)); //A01[2][0] ymm9 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 1)); //A01[2][1] ymm10 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 2)); //A01[2][2] a01 += 1; //move to next row of A //load next 8x2 block of B10 ymm12 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0])); //(B10[0][2] B10[1][2] B10[2][2] B10[3][2]) ymm13 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + D_NR)); //(B10[4][2] B10[5][2] B10[6][2] B10[7][2]) ymm14 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + cs_b)); //(B10[0][3] B10[1][3] B10[2][3] B10[3][3]) ymm15 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + cs_b + D_NR)); //(B10[4][3] B10[5][3] B10[6][3] B10[7][3]) ymm0 = _mm256_fmadd_pd(ymm8, ymm12, ymm0); //ymm0 += (B10[0][2]*A01[0][0] B10[1][2]*A01[0][0] B10[2][2]*A01[0][0] B10[3][2]*A01[0][0]) ymm1 = _mm256_fmadd_pd(ymm9, ymm12, ymm1); //ymm1 += (B10[0][2]*A01[0][1] B10[1][2]*A01[0][1] B10[2][2]*A01[0][1] B10[3][2]*A01[0][1]) ymm2 = _mm256_fmadd_pd(ymm10, ymm12, ymm2); //ymm2 += (B10[0][2]*A01[0][2] B10[1][2]*A01[0][2] B10[2][2]*A01[0][2] B10[3][2]*A01[0][2]) ymm4 = _mm256_fmadd_pd(ymm8, ymm13, ymm4); //ymm4 += (B10[4][2]*A01[0][0] B10[5][2]*A01[0][0] B10[6][2]*A01[0][0] B10[7][2]*A01[0][0]) ymm5 = _mm256_fmadd_pd(ymm9, ymm13, ymm5); //ymm5 += (B10[4][2]*A01[0][1] B10[5][2]*A01[0][1] B10[6][2]*A01[0][1] B10[7][2]*A01[0][1]) ymm6 = _mm256_fmadd_pd(ymm10, ymm13, ymm6); //ymm6 += (B10[4][2]*A01[0][2] B10[5][2]*A01[0][2] B10[6][2]*A01[0][2] B10[7][2]*A01[0][2]) //broadcast 4th row of A01 ymm8 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 0)); //A01[3][0] ymm9 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 1)); //A01[3][1] ymm10 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 2)); //A01[3][2] a01 += 1; //move to next row of A ymm0 = _mm256_fmadd_pd(ymm8, ymm14, ymm0); //ymm0 += (B10[0][3]*A01[0][0] B10[1][3]*A01[0][0] B10[2][3]*A01[0][0] B10[3][3]*A01[0][0]) ymm1 = _mm256_fmadd_pd(ymm9, ymm14, ymm1); //ymm1 += (B10[0][3]*A01[0][1] B10[1][3]*A01[0][1] B10[2][3]*A01[0][1] B10[3][3]*A01[0][1]) ymm2 = _mm256_fmadd_pd(ymm10, ymm14, ymm2); //ymm2 += (B10[0][3]*A01[0][2] B10[1][3]*A01[0][2] B10[2][3]*A01[0][2] B10[3][3]*A01[0][2]) ymm4 = _mm256_fmadd_pd(ymm8, ymm15, ymm4); //ymm4 += (B10[4][3]*A01[0][0] B10[5][3]*A01[0][0] B10[6][3]*A01[0][0] B10[7][3]*A01[0][0]) ymm5 = _mm256_fmadd_pd(ymm9, ymm15, ymm5); //ymm5 += (B10[4][3]*A01[0][1] B10[5][3]*A01[0][1] B10[6][3]*A01[0][1] B10[7][3]*A01[0][1]) ymm6 = _mm256_fmadd_pd(ymm10, ymm15, ymm6); //ymm6 += (B10[4][3]*A01[0][2] B10[5][3]*A01[0][2] B10[6][3]*A01[0][2] B10[7][3]*A01[0][2]) b10 += D_NR * cs_b; //pointer math to find next block of B for GEMM a01 = ptr_a01_dup + D_NR; //pointer math to find next block of A for GEMM } ymm15 = _mm256_broadcast_sd((double const *)&AlphaVal); ///GEMM code ends/// ymm8 = _mm256_loadu_pd((double const *)b11); //B11[0-3][0] ymm12 = _mm256_loadu_pd((double const *)(b11 + D_NR)); //B11[4-7][0] ymm9 = _mm256_loadu_pd((double const *)(b11 + cs_b)); //B11[0-3][1] ymm13 = _mm256_loadu_pd((double const *)(b11 + cs_b + D_NR)); //B11[4-7][1] ymm10 = _mm256_loadu_pd((double const *)(b11 + cs_b_offset[0])); //B11[0-3][2] ymm14 = _mm256_loadu_pd((double const *)(b11 + cs_b_offset[0] + D_NR)); //B11[4-7][2] ymm8 = _mm256_fmsub_pd(ymm8, ymm15, ymm0); //B11[0-3][0] * alpha -= B10[0-3][0] ymm9 = _mm256_fmsub_pd(ymm9, ymm15, ymm1); //B11[4-7][0] * alpha -= B10[4-7][0] ymm10 = _mm256_fmsub_pd(ymm10, ymm15, ymm2); //B11[0-3][1] * alpha -= B10[0-3][1] ymm12 = _mm256_fmsub_pd(ymm12, ymm15, ymm4); //B11[0-3][2] * alpha -= B10[0-3][2] ymm13 = _mm256_fmsub_pd(ymm13, ymm15, ymm5); //B11[4-7][2] * alpha -= B10[4-7][2] ymm14 = _mm256_fmsub_pd(ymm14, ymm15, ymm6); //B11[0-3][3] * alpha -= B10[0-3][3] ///implement TRSM/// ///read 4x4 block of A11/// ymm7 = _mm256_broadcast_sd((double const *)(&ones)); //2nd col a11 += cs_a; ymm1 = _mm256_broadcast_sd((double const *)(a11+0)); //A11[0][1] //3rd col a11 += cs_a; ymm3 = _mm256_broadcast_sd((double const *)(a11+0)); //A11[0][2] ymm4 = _mm256_broadcast_sd((double const *)(a11+1)); //A11[1][2] //(Row1): FMA operations ymm9 = _mm256_fnmadd_pd(ymm1, ymm8, ymm9); //B11[0-3][1] -= B11[0-3][0] * A11[0][1] ymm10 = _mm256_fnmadd_pd(ymm3, ymm8, ymm10); //B11[0-3][2] -= B11[0-3][0] * A11[0][2] ymm13 = _mm256_fnmadd_pd(ymm1, ymm12, ymm13); //B11[4-7][1] -= B11[4-7][0] * A11[0][1] ymm14 = _mm256_fnmadd_pd(ymm3, ymm12, ymm14); //B11[4-7][2] -= B11[4-7][0] * A11[0][2] //(Row2)FMA operations ymm10 = _mm256_fnmadd_pd(ymm4, ymm9, ymm10); //B11[0-3][2] -= B11[0-3][1] * A11[1][2] ymm14 = _mm256_fnmadd_pd(ymm4, ymm13, ymm14); //B11[4-7][2] -= B11[4-7][1] * A11[1][2] _mm256_storeu_pd((double *)b11, ymm8); //store(B11[0-3][0]) _mm256_storeu_pd((double *)(b11 + D_NR), ymm12); //store(B11[4-7][0]) _mm256_storeu_pd((double *)(b11 + cs_b), ymm9); //store(B11[0-3][1]) _mm256_storeu_pd((double *)(b11 + cs_b + D_NR), ymm13); //store(B11[4-7][1]) _mm256_storeu_pd((double *)(b11 + cs_b_offset[0]), ymm10); //store(B11[0-3][2]) _mm256_storeu_pd((double *)(b11 + cs_b_offset[0] + D_NR), ymm14);//store(B11[4-7][2]) } else if(2 == n_remainder) { ///GEMM implementation begins/// for(k = 0; k < k_iter; k++) ///loop for number of GEMM operations { ptr_a01_dup = a01; //broadcast 1st row of A01 ymm8 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 0)); //A01[0][0] ymm9 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 1)); //A01[0][1] a01 += 1; //move to next row of A //load 8x2 block of B10 ymm12 = _mm256_loadu_pd((double const *)b10); //B10[0][0] B10[1][0] B10[2][0] B10[3][0] ymm13 = _mm256_loadu_pd((double const *)(b10 + D_NR)); //B10[4][0] B10[5][0] B10[6][0] B10[7][0] ymm14 = _mm256_loadu_pd((double const *)(b10 + cs_b)); //B10[0][1] B10[1][1] B10[2][1] B10[3][1] ymm15 = _mm256_loadu_pd((double const *)(b10 + cs_b + D_NR));//B10[4][1] B10[5][1] B10[6][1] B10[7][1] ymm0 = _mm256_fmadd_pd(ymm8, ymm12, ymm0); //ymm0 += (B10[0][0]*A01[0][0] B10[1][0]*A01[0][0] B10[2][0]*A01[0][0] B10[3][0]*A01[0][0]) ymm1 = _mm256_fmadd_pd(ymm9, ymm12, ymm1); //ymm1 += (B10[0][0]*A01[0][1] B10[1][0]*A01[0][1] B10[2][0]*A01[0][1] B10[3][0]*A01[0][1]) ymm4 = _mm256_fmadd_pd(ymm8, ymm13, ymm4); //ymm4 += (B10[4][0]*A01[0][0] B10[5][0]*A01[0][0] B10[6][0]*A01[0][0] B10[7][0]*A01[0][0]) ymm5 = _mm256_fmadd_pd(ymm9, ymm13, ymm5); //ymm5 += (B10[4][0]*A01[0][1] B10[5][0]*A01[0][1] B10[6][0]*A01[0][1] B10[7][0]*A01[0][1]) //broadcast 2nd row of A01 ymm8 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 0)); //A01[1][0] ymm9 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 1)); //A01[1][1] a01 += 1; //move to next row of A ymm0 = _mm256_fmadd_pd(ymm8, ymm14, ymm0); //ymm0 += (B10[0][1]*A01[0][0] B10[1][1]*A01[0][0] B10[2][1]*A01[0][0] B10[3][1]*A01[0][0]) ymm1 = _mm256_fmadd_pd(ymm9, ymm14, ymm1); //ymm1 += (B10[0][1]*A01[0][1] B10[1][1]*A01[0][1] B10[2][1]*A01[0][1] B10[3][1]*A01[0][1]) ymm4 = _mm256_fmadd_pd(ymm8, ymm15, ymm4); //ymm4 += (B10[4][1]*A01[0][0] B10[5][1]*A01[0][0] B10[6][1]*A01[0][0] B10[7][1]*A01[0][0]) ymm5 = _mm256_fmadd_pd(ymm9, ymm15, ymm5); //ymm5 += (B10[4][1]*A01[0][1] B10[5][1]*A01[0][1] B10[6][1]*A01[0][1] B10[7][1]*A01[0][1]) //broadcast 3rd row of A01 ymm8 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 0)); //A01[2][0] ymm9 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 1)); //A01[2][1] a01 += 1; //move to next row of A //load next 8x2 block of B10 ymm12 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0])); //(B10[0][2] B10[1][2] B10[2][2] B10[3][2]) ymm13 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + D_NR)); //(B10[4][2] B10[5][2] B10[6][2] B10[7][2]) ymm14 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + cs_b)); //(B10[0][3] B10[1][3] B10[2][3] B10[3][3]) ymm15 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + cs_b + D_NR)); //(B10[4][3] B10[5][3] B10[6][3] B10[7][3]) ymm0 = _mm256_fmadd_pd(ymm8, ymm12, ymm0); //ymm0 += (B10[0][2]*A01[0][0] B10[1][2]*A01[0][0] B10[2][2]*A01[0][0] B10[3][2]*A01[0][0]) ymm1 = _mm256_fmadd_pd(ymm9, ymm12, ymm1); //ymm1 += (B10[0][2]*A01[0][1] B10[1][2]*A01[0][1] B10[2][2]*A01[0][1] B10[3][2]*A01[0][1]) ymm4 = _mm256_fmadd_pd(ymm8, ymm13, ymm4); //ymm4 += (B10[4][2]*A01[0][0] B10[5][2]*A01[0][0] B10[6][2]*A01[0][0] B10[7][2]*A01[0][0]) ymm5 = _mm256_fmadd_pd(ymm9, ymm13, ymm5); //ymm5 += (B10[4][2]*A01[0][1] B10[5][2]*A01[0][1] B10[6][2]*A01[0][1] B10[7][2]*A01[0][1]) //broadcast 4th row of A01 ymm8 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 0)); //A01[3][0] ymm9 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 1)); //A01[3][1] a01 += 1; //move to next row of A ymm0 = _mm256_fmadd_pd(ymm8, ymm14, ymm0); //ymm0 += (B10[0][3]*A01[0][0] B10[1][3]*A01[0][0] B10[2][3]*A01[0][0] B10[3][3]*A01[0][0]) ymm1 = _mm256_fmadd_pd(ymm9, ymm14, ymm1); //ymm1 += (B10[0][3]*A01[0][1] B10[1][3]*A01[0][1] B10[2][3]*A01[0][1] B10[3][3]*A01[0][1]) ymm4 = _mm256_fmadd_pd(ymm8, ymm15, ymm4); //ymm4 += (B10[4][3]*A01[0][0] B10[5][3]*A01[0][0] B10[6][3]*A01[0][0] B10[7][3]*A01[0][0]) ymm5 = _mm256_fmadd_pd(ymm9, ymm15, ymm5); //ymm5 += (B10[4][3]*A01[0][1] B10[5][3]*A01[0][1] B10[6][3]*A01[0][1] B10[7][3]*A01[0][1]) b10 += D_NR * cs_b; //pointer math to find next block of B for GEMM a01 = ptr_a01_dup + D_NR; //pointer math to find next block of A for GEMM } ///GEMM code ends/// ymm15 = _mm256_broadcast_sd((double const *)&AlphaVal); ymm8 = _mm256_loadu_pd((double const *)b11); //B11[0-3][0] ymm12 = _mm256_loadu_pd((double const *)(b11 + D_NR)); //B11[4-7][0] ymm9 = _mm256_loadu_pd((double const *)(b11 + cs_b)); //B11[0-3][1] ymm13 = _mm256_loadu_pd((double const *)(b11 + cs_b + D_NR)); //B11[4-7][1] ymm8 = _mm256_fmsub_pd(ymm8, ymm15, ymm0); //B11[0-3][0] * alpha -= B10[0-3][0] ymm9 = _mm256_fmsub_pd(ymm9, ymm15, ymm1); //B11[4-7][0] * alpha -= B10[4-7][0] ymm12 = _mm256_fmsub_pd(ymm12, ymm15, ymm4); //B11[0-3][2] * alpha -= B10[0-3][2] ymm13 = _mm256_fmsub_pd(ymm13, ymm15, ymm5); //B11[4-7][2] * alpha -= B10[4-7][2] ///implement TRSM/// ///read 4x4 block of A11/// ymm7 = _mm256_broadcast_sd((double const *)(&ones)); //2nd col a11 += cs_a; ymm1 = _mm256_broadcast_sd((double const *)(a11+0)); //A11[0][1] //(Row1): FMA operations ymm9 = _mm256_fnmadd_pd(ymm1, ymm8, ymm9); //B11[0-3][1] -= B11[0-3][0] * A11[0][1] ymm13 = _mm256_fnmadd_pd(ymm1, ymm12, ymm13); //B11[4-7][1] -= B11[4-7][0] * A11[0][1] _mm256_storeu_pd((double *)b11, ymm8); //store(B11[0-3][0]) _mm256_storeu_pd((double *)(b11 + D_NR), ymm12); //store(B11[4-7][0]) _mm256_storeu_pd((double *)(b11 + cs_b), ymm9); //store(B11[0-3][1]) _mm256_storeu_pd((double *)(b11 + cs_b + D_NR), ymm13); //store(B11[4-7][1]) } else if(1 == n_remainder) { ///GEMM implementation begins/// for(k = 0; k < k_iter; k++) ///loop for number of GEMM operations { ptr_a01_dup = a01; //broadcast 1st row of A01 ymm8 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 0)); //A01[0][0] a01 += 1; //move to next row of A //load 8x2 block of B10 ymm12 = _mm256_loadu_pd((double const *)b10); //B10[0][0] B10[1][0] B10[2][0] B10[3][0] ymm13 = _mm256_loadu_pd((double const *)(b10 + D_NR)); //B10[4][0] B10[5][0] B10[6][0] B10[7][0] ymm14 = _mm256_loadu_pd((double const *)(b10 + cs_b)); //B10[0][1] B10[1][1] B10[2][1] B10[3][1] ymm15 = _mm256_loadu_pd((double const *)(b10 + cs_b + D_NR));//B10[4][1] B10[5][1] B10[6][1] B10[7][1] ymm0 = _mm256_fmadd_pd(ymm8, ymm12, ymm0); //ymm0 += (B10[0][0]*A01[0][0] B10[1][0]*A01[0][0] B10[2][0]*A01[0][0] B10[3][0]*A01[0][0]) ymm4 = _mm256_fmadd_pd(ymm8, ymm13, ymm4); //ymm4 += (B10[4][0]*A01[0][0] B10[5][0]*A01[0][0] B10[6][0]*A01[0][0] B10[7][0]*A01[0][0]) //broadcast 2nd row of A01 ymm8 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 0)); //A01[1][0] a01 += 1; //move to next row of A ymm0 = _mm256_fmadd_pd(ymm8, ymm14, ymm0); //ymm0 += (B10[0][1]*A01[0][0] B10[1][1]*A01[0][0] B10[2][1]*A01[0][0] B10[3][1]*A01[0][0]) ymm4 = _mm256_fmadd_pd(ymm8, ymm15, ymm4); //ymm4 += (B10[4][1]*A01[0][0] B10[5][1]*A01[0][0] B10[6][1]*A01[0][0] B10[7][1]*A01[0][0]) //broadcast 3rd row of A01 ymm8 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 0)); //A01[2][0] a01 += 1; //move to next row of A //load next 8x2 block of B10 ymm12 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0])); //(B10[0][2] B10[1][2] B10[2][2] B10[3][2]) ymm13 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + D_NR)); //(B10[4][2] B10[5][2] B10[6][2] B10[7][2]) ymm14 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + cs_b)); //(B10[0][3] B10[1][3] B10[2][3] B10[3][3]) ymm15 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + cs_b + D_NR)); //(B10[4][3] B10[5][3] B10[6][3] B10[7][3]) ymm0 = _mm256_fmadd_pd(ymm8, ymm12, ymm0); //ymm0 += (B10[0][2]*A01[0][0] B10[1][2]*A01[0][0] B10[2][2]*A01[0][0] B10[3][2]*A01[0][0]) ymm4 = _mm256_fmadd_pd(ymm8, ymm13, ymm4); //ymm4 += (B10[4][2]*A01[0][0] B10[5][2]*A01[0][0] B10[6][2]*A01[0][0] B10[7][2]*A01[0][0]) //broadcast 4th row of A01 ymm8 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 0)); //A01[3][0] a01 += 1; //move to next row of A ymm0 = _mm256_fmadd_pd(ymm8, ymm14, ymm0); //ymm0 += (B10[0][3]*A01[0][0] B10[1][3]*A01[0][0] B10[2][3]*A01[0][0] B10[3][3]*A01[0][0]) ymm4 = _mm256_fmadd_pd(ymm8, ymm15, ymm4); //ymm4 += (B10[4][3]*A01[0][0] B10[5][3]*A01[0][0] B10[6][3]*A01[0][0] B10[7][3]*A01[0][0]) b10 += D_NR * cs_b; //pointer math to find next block of B for GEMM a01 = ptr_a01_dup + D_NR; //pointer math to find next block of A for GEMM } ///GEMM code ends/// ymm15 = _mm256_broadcast_sd((double const *)&AlphaVal); ymm8 = _mm256_loadu_pd((double const *)b11); //B11[0-3][0] ymm12 = _mm256_loadu_pd((double const *)(b11 + D_NR)); //B11[4-7][0] ymm8 = _mm256_fmsub_pd(ymm8, ymm15, ymm0); //B11[0-3][0] * alpha -= B10[0-3][0] ymm12 = _mm256_fmsub_pd(ymm12, ymm15, ymm4); //B11[0-3][2] * alpha -= B10[0-3][2] _mm256_storeu_pd((double *)b11, ymm8); //store(B11[0-3][0]) _mm256_storeu_pd((double *)(b11 + D_NR), ymm12); //store(B11[4-7][0]) } } } if((m & 4)) ///implementation for remainder rows(when m_remainder is greater than 4) { for(j = 0; (j+D_NR-1) a01 ----> ***************** *********** *b01*b11* * * * * * * b11 * * * * * **a01 * * a11 | ***************** ********* | | * * * * * *a11* * | | * * * * * * * * | v ***************** ****** v * * * * * * * * * * * * * * ***************** * * * */ static err_t bli_dtrsm_small_XAltB( side_t side, obj_t* AlphaObj, obj_t* a, obj_t* b, cntx_t* cntx, cntl_t* cntl ) { dim_t D_MR = 8; //block dimension along the rows dim_t D_NR = 4; //block dimension along the columns dim_t m = bli_obj_length(b); //number of rows dim_t n = bli_obj_width(b); //number of columns dim_t m_remainder = m & 7; //number of corner rows dim_t n_remainder = n & 3; //number of corner columns dim_t cs_a = bli_obj_col_stride(a); //column stride of matrix A dim_t cs_b = bli_obj_col_stride(b); //column stride of matrix B #ifdef BLIS_ENABLE_SMALL_MATRIX_ROME if((m < D_BLIS_SMALL_MATRIX_THRES_TRSM_XALTB_ROME_ROW_PANEL_M && n>D_BLIS_SMALL_MATRIX_THRES_TRSM_XALTB_ROME_ROW_PANEL_N) || (m < D_BLIS_SMALL_MATRIX_THRES_TRSM_XALTB_ROME_SQUARE_M && n > D_BLIS_SMALL_MATRIX_THRES_TRSM_XALTB_ROME_SQUARE_N) || (m < D_BLIS_SMALL_MATRIX_THRES_TRSM_XALTB_ROME_COLUMN_PANEL_N && n > D_BLIS_SMALL_MATRIX_THRES_TRSM_XALTB_ROME) || (m < D_BLIS_SMALL_MATRIX_THRES_TRSM_XALTB_ROME && n > D_BLIS_SMALL_MATRIX_THRES_TRSM_XALTB_ROME) || (m > D_BLIS_SMALL_MATRIX_THRES_TRSM_XALTB_ROME && n > D_BLIS_SMALL_MATRIX_THRES_TRSM_XALTB_ROME_COLUMN_PANEL_N) ) return BLIS_NOT_YET_IMPLEMENTED; #else if(bli_max(m,n) > D_BLIS_SMALL_MATRIX_THRES_TRSM_NAPLES) { return BLIS_NOT_YET_IMPLEMENTED; } #endif dim_t i, j, k; //loop variablse dim_t k_iter; //determines the number of GEMM operations to be done dim_t cs_b_offset[2]; //pre-calculated strides double ones = 1.0; double AlphaVal = *(double *)AlphaObj->buffer; //value of Alpha double *L = a->buffer; //pointer to matrix A double *B = b->buffer; //pointer to matrix B double *a01, *a11, *b10, *b11; //pointers for GEMM and TRSM blocks double *ptr_a01_dup; double f_t[4] __attribute__((aligned(64)));//buffer to store corner column when m_remainder !=0 double* f_temp; cs_b_offset[0] = cs_b << 1; //cs_b_offset[0] = cs_b * 2; cs_b_offset[1] = cs_b_offset[0] + cs_b;//cs_b_offset[1] = cs_b * 3; //ymm scratch reginsters __m256d ymm0, ymm1, ymm2, ymm3; __m256d ymm4, ymm5, ymm6, ymm7; __m256d ymm8, ymm9, ymm10, ymm11; __m256d ymm12, ymm13, ymm14, ymm15; __m256d ymm16; for(i = 0; (i+D_MR-1) < m; i += D_MR) //loop along 'M' direction { for(j = 0; (j+D_NR-1) < n; j += D_NR) //loop along 'N' direction { a01 = L + j; //pointer to block of A to be used in GEMM a11 = L + j*cs_a + j; //pointer to block of A to be used for TRSM b10 = B + i; //pointer to block of B to be used in GEMM b11 = B + i + j*cs_b; //pointer to block of B to be used for TRSM k_iter = j / D_NR; //number of GEMM operations to be done(in blocks of 4x4) ymm0 = _mm256_setzero_pd(); ymm1 = _mm256_setzero_pd(); ymm2 = _mm256_setzero_pd(); ymm3 = _mm256_setzero_pd(); ymm4 = _mm256_setzero_pd(); ymm5 = _mm256_setzero_pd(); ymm6 = _mm256_setzero_pd(); ymm7 = _mm256_setzero_pd(); ///GEMM implementation starts/// for(k = 0; k < k_iter; k++) //loop for number of GEMM operations { ptr_a01_dup = a01; //broadcast 1st row of A01 ymm8 = _mm256_broadcast_sd((double const *)(a01 + 0)); //A01[0][0] ymm9 = _mm256_broadcast_sd((double const *)(a01 + 1)); //A01[0][1] ymm10 = _mm256_broadcast_sd((double const *)(a01 + 2)); //A01[0][2] ymm11 = _mm256_broadcast_sd((double const *)(a01 + 3)); //A01[0][3] a01 += cs_a; //move to next row //load 8x2 block of B10 ymm12 = _mm256_loadu_pd((double const *)b10); //B10[0][0] B10[1][0] B10[2][0] B10[3][0] ymm13 = _mm256_loadu_pd((double const *)(b10 + D_NR)); //B10[4][0] B10[5][0] B10[6][0] B10[7][0] ymm14 = _mm256_loadu_pd((double const *)(b10 + cs_b)); //B10[0][1] B10[1][1] B10[2][1] B10[3][1] ymm15 = _mm256_loadu_pd((double const *)(b10 + cs_b + D_NR)); //B10[4][1] B10[5][1] B10[6][1] B10[7][1] ymm0 = _mm256_fmadd_pd(ymm8, ymm12, ymm0); //ymm0 += (B10[0][0]*A01[0][0] B10[1][0]*A01[0][0] B10[2][0]*A01[0][0] B10[3][0]*A01[0][0]) ymm1 = _mm256_fmadd_pd(ymm9, ymm12, ymm1); //ymm1 += (B10[0][0]*A01[0][1] B10[1][0]*A01[0][1] B10[2][0]*A01[0][1] B10[3][0]*A01[0][1]) ymm2 = _mm256_fmadd_pd(ymm10, ymm12, ymm2); //ymm2 += (B10[0][0]*A01[0][2] B10[1][0]*A01[0][2] B10[2][0]*A01[0][2] B10[3][0]*A01[0][2]) ymm3 = _mm256_fmadd_pd(ymm11, ymm12, ymm3); //ymm3 += (B10[0][0]*A01[0][3] B10[1][0]*A01[0][3] B10[2][0]*A01[0][3] B10[3][0]*A01[0][3]) ymm4 = _mm256_fmadd_pd(ymm8, ymm13, ymm4); //ymm4 += (B10[4][0]*A01[0][0] B10[5][0]*A01[0][0] B10[6][0]*A01[0][0] B10[7][0]*A01[0][0]) ymm5 = _mm256_fmadd_pd(ymm9, ymm13, ymm5); //ymm5 += (B10[4][0]*A01[0][1] B10[5][0]*A01[0][1] B10[6][0]*A01[0][1] B10[7][0]*A01[0][1]) ymm6 = _mm256_fmadd_pd(ymm10, ymm13, ymm6); //ymm6 += (B10[4][0]*A01[0][2] B10[5][0]*A01[0][2] B10[6][0]*A01[0][2] B10[7][0]*A01[0][2]) ymm7 = _mm256_fmadd_pd(ymm11, ymm13, ymm7); //ymm7 += (B10[4][0]*A01[0][3] B10[5][0]*A01[0][3] B10[6][0]*A01[0][3] B10[7][0]*A01[0][3]) //broadcast 2nd row of A01 ymm8 = _mm256_broadcast_sd((double const *)(a01 + 0)); //A01[1][0] ymm9 = _mm256_broadcast_sd((double const *)(a01 + 1)); //A01[1][1] ymm10 = _mm256_broadcast_sd((double const *)(a01 + 2)); //A01[1][2] ymm11 = _mm256_broadcast_sd((double const *)(a01 + 3)); //A01[1][3] a01 += cs_a; //move to next row of A ymm0 = _mm256_fmadd_pd(ymm8, ymm14, ymm0); //ymm0 += (B10[0][1]*A01[0][0] B10[1][1]*A01[0][0] B10[2][1]*A01[0][0] B10[3][1]*A01[0][0]) ymm1 = _mm256_fmadd_pd(ymm9, ymm14, ymm1); //ymm1 += (B10[0][1]*A01[0][1] B10[1][1]*A01[0][1] B10[2][1]*A01[0][1] B10[3][1]*A01[0][1]) ymm2 = _mm256_fmadd_pd(ymm10, ymm14, ymm2); //ymm2 += (B10[0][1]*A01[0][2] B10[1][1]*A01[0][2] B10[2][1]*A01[0][2] B10[3][1]*A01[0][2]) ymm3 = _mm256_fmadd_pd(ymm11, ymm14, ymm3); //ymm3 += (B10[0][1]*A01[0][3] B10[1][1]*A01[0][3] B10[2][1]*A01[0][3] B10[3][1]*A01[0][3]) ymm4 = _mm256_fmadd_pd(ymm8, ymm15, ymm4); //ymm4 += (B10[4][1]*A01[0][0] B10[5][1]*A01[0][0] B10[6][1]*A01[0][0] B10[7][1]*A01[0][0]) ymm5 = _mm256_fmadd_pd(ymm9, ymm15, ymm5); //ymm5 += (B10[4][1]*A01[0][1] B10[5][1]*A01[0][1] B10[6][1]*A01[0][1] B10[7][1]*A01[0][1]) ymm6 = _mm256_fmadd_pd(ymm10, ymm15, ymm6); //ymm6 += (B10[4][1]*A01[0][2] B10[5][1]*A01[0][2] B10[6][1]*A01[0][2] B10[7][1]*A01[0][2]) ymm7 = _mm256_fmadd_pd(ymm11, ymm15, ymm7); //ymm7 += (B10[4][1]*A01[0][3] B10[5][1]*A01[0][3] B10[6][1]*A01[0][3] B10[7][1]*A01[0][3]) //broadcast 3rd row of A01 ymm8 = _mm256_broadcast_sd((double const *)(a01 + 0)); //A01[2][0] ymm9 = _mm256_broadcast_sd((double const *)(a01 + 1)); //A01[2][1] ymm10 = _mm256_broadcast_sd((double const *)(a01 + 2)); //A01[2][2] ymm11 = _mm256_broadcast_sd((double const *)(a01 + 3)); //A01[2][3] a01 += cs_a; //move to next row of A01 //load next 8x2 block of B10 ymm12 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0])); //(B10[0][2] B10[1][2] B10[2][2] B10[3][2]) ymm13 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + D_NR)); //(B10[4][2] B10[5][2] B10[6][2] B10[7][2]) ymm14 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + cs_b)); //(B10[0][3] B10[1][3] B10[2][3] B10[3][3]) ymm15 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + cs_b + D_NR)); //(B10[4][3] B10[5][3] B10[6][3] B10[7][3]) ymm0 = _mm256_fmadd_pd(ymm8, ymm12, ymm0); //ymm0 += (B10[0][2]*A01[0][0] B10[1][2]*A01[0][0] B10[2][2]*A01[0][0] B10[3][2]*A01[0][0]) ymm1 = _mm256_fmadd_pd(ymm9, ymm12, ymm1); //ymm1 += (B10[0][2]*A01[0][1] B10[1][2]*A01[0][1] B10[2][2]*A01[0][1] B10[3][2]*A01[0][1]) ymm2 = _mm256_fmadd_pd(ymm10, ymm12, ymm2); //ymm2 += (B10[0][2]*A01[0][2] B10[1][2]*A01[0][2] B10[2][2]*A01[0][2] B10[3][2]*A01[0][2]) ymm3 = _mm256_fmadd_pd(ymm11, ymm12, ymm3); //ymm3 += (B10[0][2]*A01[0][3] B10[1][2]*A01[0][3] B10[2][2]*A01[0][3] B10[3][2]*A01[0][3]) ymm4 = _mm256_fmadd_pd(ymm8, ymm13, ymm4); //ymm4 += (B10[4][2]*A01[0][0] B10[5][2]*A01[0][0] B10[6][2]*A01[0][0] B10[7][2]*A01[0][0]) ymm5 = _mm256_fmadd_pd(ymm9, ymm13, ymm5); //ymm5 += (B10[4][2]*A01[0][1] B10[5][2]*A01[0][1] B10[6][2]*A01[0][1] B10[7][2]*A01[0][1]) ymm6 = _mm256_fmadd_pd(ymm10, ymm13, ymm6); //ymm6 += (B10[4][2]*A01[0][2] B10[5][2]*A01[0][2] B10[6][2]*A01[0][2] B10[7][2]*A01[0][2]) ymm7 = _mm256_fmadd_pd(ymm11, ymm13, ymm7); //ymm7 += (B10[4][2]*A01[0][3] B10[5][2]*A01[0][3] B10[6][2]*A01[0][3] B10[7][2]*A01[0][3]) //broadcast 4th row of A01 ymm8 = _mm256_broadcast_sd((double const *)(a01 + 0)); //A01[3][0] ymm9 = _mm256_broadcast_sd((double const *)(a01 + 1)); //A01[3][1] ymm10 = _mm256_broadcast_sd((double const *)(a01 + 2)); //A01[3][2] ymm11 = _mm256_broadcast_sd((double const *)(a01 + 3)); //A01[3][3] a01 += cs_a; //move to next row of A01 ymm0 = _mm256_fmadd_pd(ymm8, ymm14, ymm0); //ymm0 += (B10[0][3]*A01[0][0] B10[1][3]*A01[0][0] B10[2][3]*A01[0][0] B10[3][3]*A01[0][0]) ymm1 = _mm256_fmadd_pd(ymm9, ymm14, ymm1); //ymm1 += (B10[0][3]*A01[0][1] B10[1][3]*A01[0][1] B10[2][3]*A01[0][1] B10[3][3]*A01[0][1]) ymm2 = _mm256_fmadd_pd(ymm10, ymm14, ymm2); //ymm2 += (B10[0][3]*A01[0][2] B10[1][3]*A01[0][2] B10[2][3]*A01[0][2] B10[3][3]*A01[0][2]) ymm3 = _mm256_fmadd_pd(ymm11, ymm14, ymm3); //ymm3 += (B10[0][3]*A01[0][3] B10[1][3]*A01[0][3] B10[2][3]*A01[0][3] B10[3][3]*A01[0][3]) ymm4 = _mm256_fmadd_pd(ymm8, ymm15, ymm4); //ymm4 += (B10[4][3]*A01[0][0] B10[5][3]*A01[0][0] B10[6][3]*A01[0][0] B10[7][3]*A01[0][0]) ymm5 = _mm256_fmadd_pd(ymm9, ymm15, ymm5); //ymm5 += (B10[4][3]*A01[0][1] B10[5][3]*A01[0][1] B10[6][3]*A01[0][1] B10[7][3]*A01[0][1]) ymm6 = _mm256_fmadd_pd(ymm10, ymm15, ymm6); //ymm6 += (B10[4][3]*A01[0][2] B10[5][3]*A01[0][2] B10[6][3]*A01[0][2] B10[7][3]*A01[0][2]) ymm7 = _mm256_fmadd_pd(ymm11, ymm15, ymm7); //ymm7 += (B10[4][3]*A01[0][3] B10[5][3]*A01[0][3] B10[6][3]*A01[0][3] B10[7][3]*A01[0][3]) b10 += D_NR * cs_b; //pointer math to find next block of B for GEMM a01 = ptr_a01_dup + (D_NR * cs_a); //pointer math to find next block of A for GEMM } ///GEMM code ends/// ymm16 = _mm256_broadcast_sd((double const *)&AlphaVal); //load 8x4 block of B11 ymm8 = _mm256_loadu_pd((double const *)b11); //B11[0][0] B11[1][0] B11[2][0] B11[3][0] ymm12 = _mm256_loadu_pd((double const *)(b11 + D_NR)); //B11[4][0] B11[5][0] B11[6][0] B11[7][0] ymm9 = _mm256_loadu_pd((double const *)(b11 + cs_b)); //B11[0][1] B11[1][1] B11[2][1] B11[3][1] ymm13 = _mm256_loadu_pd((double const *)(b11 + cs_b + D_NR)); //B11[4][1] B11[5][1] B11[6][1] B11[7][1] ymm10 = _mm256_loadu_pd((double const *)(b11 + cs_b_offset[0])); //B11[0][2] B11[1][2] B11[2][2] B11[3][2] ymm14 = _mm256_loadu_pd((double const *)(b11 + cs_b_offset[0] + D_NR)); //B11[4][2] B11[5][2] B11[6][2] B11[7][2] ymm11 = _mm256_loadu_pd((double const *)(b11 + cs_b_offset[1])); //B11[0][3] B11[1][3] B11[2][3] B11[3][3] ymm15 = _mm256_loadu_pd((double const *)(b11 + cs_b_offset[1] + D_NR)); //B11[4][3] B11[5][3] B11[6][3] B11[7][3] ymm8 = _mm256_fmsub_pd(ymm8, ymm16, ymm0); //B11[0-3][0] * alpha -= ymm0 ymm9 = _mm256_fmsub_pd(ymm9, ymm16, ymm1); //B11[4-7][0] * alpha-= ymm1 ymm10 = _mm256_fmsub_pd(ymm10, ymm16, ymm2); //B11[0-3][1] * alpha-= ymm2 ymm11 = _mm256_fmsub_pd(ymm11, ymm16, ymm3); //B11[4-7][1] * alpha -= ymm3 ymm12 = _mm256_fmsub_pd(ymm12, ymm16, ymm4); //B11[0-3][2] * alpha -= ymm4 ymm13 = _mm256_fmsub_pd(ymm13, ymm16, ymm5); //B11[4-7][2] * alpha -= ymm5 ymm14 = _mm256_fmsub_pd(ymm14, ymm16, ymm6); //B11[0-3][3] * alpha -= ymm6 ymm15 = _mm256_fmsub_pd(ymm15, ymm16, ymm7); //B11[4-7][3] * alpha -= ymm7 ///implement TRSM/// ///read 4x4 block of A11/// ymm7 = _mm256_broadcast_sd((double const *)(&ones)); //1st col ymm0 = _mm256_broadcast_sd((double const *)(a11+0)); //A11[0][0] //2nd col a11 += 1; ymm1 = _mm256_broadcast_sd((double const *)(a11+ cs_a * 0)); //A11[0][1] ymm2 = _mm256_broadcast_sd((double const *)(a11+ cs_a * 1)); //A11[1][1] //3rd col a11 += 1; ymm3 = _mm256_broadcast_sd((double const *)(a11+ cs_a * 0)); //A11[0][2] ymm4 = _mm256_broadcast_sd((double const *)(a11+ cs_a * 1)); //A11[1][2] ymm5 = _mm256_broadcast_sd((double const *)(a11+ cs_a * 2)); //A11[2][2] //4th col a11 += 1; ymm6 = _mm256_broadcast_sd((double const *)(a11+ cs_a * 3)); //A11[3][3] //compute reciprocals of L(i,i) and broadcast in registers ymm0 = _mm256_unpacklo_pd(ymm0, ymm2); //A11[0][0] A11[1][1] A11[0][0] A11[1][1] ymm2 = _mm256_unpacklo_pd(ymm5, ymm6); //A11[2][2] A11[3][3] A11[1][1] A11[3][3] ymm0 = _mm256_blend_pd(ymm0, ymm2, 0x0C); //A11[0][0] A11[1][1] A11[2][2] A11[3][3] ymm7 = _mm256_div_pd(ymm7, ymm0); //(1/A11[0][0] 1/A11[1][1] 1/A11[2][2] 1/A11[3][3]) ymm2 = _mm256_broadcast_sd((double const *)(a11+ cs_a * 0)); //A11[0][3] ymm5 = _mm256_broadcast_sd((double const *)(a11+ cs_a * 1)); //A11[1][3] ymm6 = _mm256_broadcast_sd((double const *)(a11+ cs_a * 2)); //A11[2][3] //extract a00 ymm0 = _mm256_permute_pd(ymm7, 0x00); //(1/A11[0][0] 1/A11[0][0] 1/A11[2][2] 1/A11[2][2]) ymm0 = _mm256_permute2f128_pd(ymm0, ymm0, 0x00); //(1/A11[0][0] 1/A11[0][0] 1/A11[0][0] 1/A11[0][0]) ymm8 = _mm256_mul_pd(ymm8, ymm0); //B11[0-3][0] /= A11[0][0] ymm12 = _mm256_mul_pd(ymm12, ymm0); //B11[4-7][0] /= A11[0][0] //extract a11 ymm0 = _mm256_permute_pd(ymm7, 0x03); //(1/A11[1][1] 1/A11[1][1] 1/A11[2][2] 1/A11[2][2]) ymm0 = _mm256_permute2f128_pd(ymm0, ymm0, 0x00);//(1/A11[1][1] 1/A11[1][1] 1/A11[1][1] 1/A11[1][1]) //(Row1): FMA operations ymm9 = _mm256_fnmadd_pd(ymm1, ymm8, ymm9); //B11[0-3][1] -= B11[0-3][0] * A11[0][1] ymm10 = _mm256_fnmadd_pd(ymm3, ymm8, ymm10); //B11[0-3][2] -= B11[0-3][0] * A11[0][2] ymm11 = _mm256_fnmadd_pd(ymm2, ymm8, ymm11); //B11[0-3][3] -= B11[0-3][0] * A11[0][3] ymm13 = _mm256_fnmadd_pd(ymm1, ymm12, ymm13); //B11[4-7][1] -= B11[4-7][0] * A11[0][1] ymm14 = _mm256_fnmadd_pd(ymm3, ymm12, ymm14); //B11[4-7][2] -= B11[4-7][0] * A11[0][2] ymm15 = _mm256_fnmadd_pd(ymm2, ymm12, ymm15); //B11[4-7][3] -= B11[4-7][0] * A11[0][3] ymm9 = _mm256_mul_pd(ymm9, ymm0); //B11[0-3][1] /= A11[1][1] ymm13 = _mm256_mul_pd(ymm13, ymm0); //B11[4-7][1] /= A11[1][1] //extract a22 ymm0 = _mm256_permute_pd(ymm7, 0x00); //(1/A11[0][0] 1/A11[0][0] 1/A11[2][2] 1/A11[2][2]) ymm0 = _mm256_permute2f128_pd(ymm0, ymm0, 0x11);//(1/A11[2][2] 1/A11[2][2] 1/A11[2][2] 1/A11[2][2]) //(Row2)FMA operations ymm10 = _mm256_fnmadd_pd(ymm4, ymm9, ymm10); //B11[0-3][2] -= B11[0-3][1] * A11[1][2] ymm11 = _mm256_fnmadd_pd(ymm5, ymm9, ymm11); //B11[0-3][3] -= B11[0-3][1] * A11[1][3] ymm14 = _mm256_fnmadd_pd(ymm4, ymm13, ymm14); //B11[4-7][2] -= B11[4-7][1] * A11[1][2] ymm15 = _mm256_fnmadd_pd(ymm5, ymm13, ymm15); //B11[4-7][3] -= B11[4-7][1] * A11[1][3] ymm10 = _mm256_mul_pd(ymm10, ymm0); //B11[0-3][2] /= A11[2][2] ymm14 = _mm256_mul_pd(ymm14, ymm0); //B11[4-7][2] /= A11[2][2] //extract a33 ymm0 = _mm256_permute_pd(ymm7, 0x0C); //(1/A11[0][0] 1/A11[0][0] 1/A11[3][3] 1/A11[3][3] 1/A11[3][3]) ymm0 = _mm256_permute2f128_pd(ymm0, ymm0, 0x11);//(1/A11[3][3] 1/A11[3][3] 1/A11[3][3] 1/A11[3][3]) //(Row3)FMA operations ymm11 = _mm256_fnmadd_pd(ymm6, ymm10, ymm11); //B11[0-3][3] -= B11[0-3][2] * A11[2][3] ymm15 = _mm256_fnmadd_pd(ymm6, ymm14, ymm15); //B11[4-7][3] -= B11[4-7][2] * A11[2][3] ymm11 = _mm256_mul_pd(ymm11, ymm0); //B11[0-3][3] /= A11[3][3] ymm15 = _mm256_mul_pd(ymm15, ymm0); //B11[4-7][3] /= A11[3][3] _mm256_storeu_pd((double *)b11, ymm8); //store(B11[0-3][0]) _mm256_storeu_pd((double *)(b11 + D_NR), ymm12); //store(B11[4-7][0]) _mm256_storeu_pd((double *)(b11 + cs_b), ymm9); //store(B11[0-3][1]) _mm256_storeu_pd((double *)(b11 + cs_b + D_NR), ymm13); //store(B11[4-7][1]) _mm256_storeu_pd((double *)(b11 + cs_b_offset[0]), ymm10); //store(B11[0-3][2]) _mm256_storeu_pd((double *)(b11 + cs_b_offset[0] + D_NR), ymm14); //store(B11[4-7][2]) _mm256_storeu_pd((double *)(b11 + cs_b_offset[0] + cs_b), ymm11); //store(B11[0-3][3]) _mm256_storeu_pd((double *)(b11 + cs_b_offset[0] + cs_b + D_NR), ymm15);//store(B11[4-7][3]) } if(n_remainder) //implementation for remainder columns(when n is not multiple of D_NR) { a01 = L + j; //pointer to block of A to be used for GEMM a11 = L + j*cs_a + j; //pointer to block of A to be used for TRSM b10 = B + i; //pointer to block of B to be used for GEMM b11 = B + i + j*cs_b; //pointer to block of B to be used for TRSM k_iter = j / D_NR; //number of GEMM operations to be performed(in blocks of 4x4) ///load 4x4 block of b11 ymm0 = _mm256_setzero_pd(); ymm1 = _mm256_setzero_pd(); ymm2 = _mm256_setzero_pd(); ymm3 = _mm256_setzero_pd(); ymm4 = _mm256_setzero_pd(); ymm5 = _mm256_setzero_pd(); ymm6 = _mm256_setzero_pd(); ymm7 = _mm256_setzero_pd(); //subtract the calculated GEMM block from current TRSM block //load 8x4 block of B11 if(3 == n_remainder) { ///GEMM implementation begins/// for(k = 0; k < k_iter; k++) ///loop for number of GEMM operations { ptr_a01_dup = a01; //broadcast 1st row of A01 ymm8 = _mm256_broadcast_sd((double const *)(a01 + 0)); //A01[0][0] ymm9 = _mm256_broadcast_sd((double const *)(a01 + 1)); //A01[0][1] ymm10 = _mm256_broadcast_sd((double const *)(a01 + 2)); //A01[0][2] a01 += cs_a; //move to next row of A //load 8x2 block of B10 ymm12 = _mm256_loadu_pd((double const *)b10); //B10[0][0] B10[1][0] B10[2][0] B10[3][0] ymm13 = _mm256_loadu_pd((double const *)(b10 + D_NR)); //B10[4][0] B10[5][0] B10[6][0] B10[7][0] ymm14 = _mm256_loadu_pd((double const *)(b10 + cs_b)); //B10[0][1] B10[1][1] B10[2][1] B10[3][1] ymm15 = _mm256_loadu_pd((double const *)(b10 + cs_b + D_NR));//B10[4][1] B10[5][1] B10[6][1] B10[7][1] ymm0 = _mm256_fmadd_pd(ymm8, ymm12, ymm0); //ymm0 += (B10[0][0]*A01[0][0] B10[1][0]*A01[0][0] B10[2][0]*A01[0][0] B10[3][0]*A01[0][0]) ymm1 = _mm256_fmadd_pd(ymm9, ymm12, ymm1); //ymm1 += (B10[0][0]*A01[0][1] B10[1][0]*A01[0][1] B10[2][0]*A01[0][1] B10[3][0]*A01[0][1]) ymm2 = _mm256_fmadd_pd(ymm10, ymm12, ymm2); //ymm2 += (B10[0][0]*A01[0][2] B10[1][0]*A01[0][2] B10[2][0]*A01[0][2] B10[3][0]*A01[0][2]) ymm4 = _mm256_fmadd_pd(ymm8, ymm13, ymm4); //ymm4 += (B10[4][0]*A01[0][0] B10[5][0]*A01[0][0] B10[6][0]*A01[0][0] B10[7][0]*A01[0][0]) ymm5 = _mm256_fmadd_pd(ymm9, ymm13, ymm5); //ymm5 += (B10[4][0]*A01[0][1] B10[5][0]*A01[0][1] B10[6][0]*A01[0][1] B10[7][0]*A01[0][1]) ymm6 = _mm256_fmadd_pd(ymm10, ymm13, ymm6); //ymm6 += (B10[4][0]*A01[0][2] B10[5][0]*A01[0][2] B10[6][0]*A01[0][2] B10[7][0]*A01[0][2]) //broadcast 2nd row of A01 ymm8 = _mm256_broadcast_sd((double const *)(a01 + 0)); //A01[1][0] ymm9 = _mm256_broadcast_sd((double const *)(a01 + 1)); //A01[1][1] ymm10 = _mm256_broadcast_sd((double const *)(a01 + 2)); //A01[1][2] a01 += cs_a; //move to next row of A ymm0 = _mm256_fmadd_pd(ymm8, ymm14, ymm0); //ymm0 += (B10[0][1]*A01[0][0] B10[1][1]*A01[0][0] B10[2][1]*A01[0][0] B10[3][1]*A01[0][0]) ymm1 = _mm256_fmadd_pd(ymm9, ymm14, ymm1); //ymm1 += (B10[0][1]*A01[0][1] B10[1][1]*A01[0][1] B10[2][1]*A01[0][1] B10[3][1]*A01[0][1]) ymm2 = _mm256_fmadd_pd(ymm10, ymm14, ymm2); //ymm2 += (B10[0][1]*A01[0][2] B10[1][1]*A01[0][2] B10[2][1]*A01[0][2] B10[3][1]*A01[0][2]) ymm4 = _mm256_fmadd_pd(ymm8, ymm15, ymm4); //ymm4 += (B10[4][1]*A01[0][0] B10[5][1]*A01[0][0] B10[6][1]*A01[0][0] B10[7][1]*A01[0][0]) ymm5 = _mm256_fmadd_pd(ymm9, ymm15, ymm5); //ymm5 += (B10[4][1]*A01[0][1] B10[5][1]*A01[0][1] B10[6][1]*A01[0][1] B10[7][1]*A01[0][1]) ymm6 = _mm256_fmadd_pd(ymm10, ymm15, ymm6); //ymm6 += (B10[4][1]*A01[0][2] B10[5][1]*A01[0][2] B10[6][1]*A01[0][2] B10[7][1]*A01[0][2]) //broadcast 3rd row of A01 ymm8 = _mm256_broadcast_sd((double const *)(a01 + 0)); //A01[2][0] ymm9 = _mm256_broadcast_sd((double const *)(a01 + 1)); //A01[2][1] ymm10 = _mm256_broadcast_sd((double const *)(a01 + 2)); //A01[2][2] a01 += cs_a; //move to next row of A //load next 8x2 block of B10 ymm12 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0])); //(B10[0][2] B10[1][2] B10[2][2] B10[3][2]) ymm13 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + D_NR)); //(B10[4][2] B10[5][2] B10[6][2] B10[7][2]) ymm14 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + cs_b)); //(B10[0][3] B10[1][3] B10[2][3] B10[3][3]) ymm15 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + cs_b + D_NR)); //(B10[4][3] B10[5][3] B10[6][3] B10[7][3]) ymm0 = _mm256_fmadd_pd(ymm8, ymm12, ymm0); //ymm0 += (B10[0][2]*A01[0][0] B10[1][2]*A01[0][0] B10[2][2]*A01[0][0] B10[3][2]*A01[0][0]) ymm1 = _mm256_fmadd_pd(ymm9, ymm12, ymm1); //ymm1 += (B10[0][2]*A01[0][1] B10[1][2]*A01[0][1] B10[2][2]*A01[0][1] B10[3][2]*A01[0][1]) ymm2 = _mm256_fmadd_pd(ymm10, ymm12, ymm2); //ymm2 += (B10[0][2]*A01[0][2] B10[1][2]*A01[0][2] B10[2][2]*A01[0][2] B10[3][2]*A01[0][2]) ymm4 = _mm256_fmadd_pd(ymm8, ymm13, ymm4); //ymm4 += (B10[4][2]*A01[0][0] B10[5][2]*A01[0][0] B10[6][2]*A01[0][0] B10[7][2]*A01[0][0]) ymm5 = _mm256_fmadd_pd(ymm9, ymm13, ymm5); //ymm5 += (B10[4][2]*A01[0][1] B10[5][2]*A01[0][1] B10[6][2]*A01[0][1] B10[7][2]*A01[0][1]) ymm6 = _mm256_fmadd_pd(ymm10, ymm13, ymm6); //ymm6 += (B10[4][2]*A01[0][2] B10[5][2]*A01[0][2] B10[6][2]*A01[0][2] B10[7][2]*A01[0][2]) //broadcast 4th row of A01 ymm8 = _mm256_broadcast_sd((double const *)(a01 + 0)); //A01[3][0] ymm9 = _mm256_broadcast_sd((double const *)(a01 + 1)); //A01[3][1] ymm10 = _mm256_broadcast_sd((double const *)(a01 + 2)); //A01[3][2] a01 += cs_a; //move to next row of A ymm0 = _mm256_fmadd_pd(ymm8, ymm14, ymm0); //ymm0 += (B10[0][3]*A01[0][0] B10[1][3]*A01[0][0] B10[2][3]*A01[0][0] B10[3][3]*A01[0][0]) ymm1 = _mm256_fmadd_pd(ymm9, ymm14, ymm1); //ymm1 += (B10[0][3]*A01[0][1] B10[1][3]*A01[0][1] B10[2][3]*A01[0][1] B10[3][3]*A01[0][1]) ymm2 = _mm256_fmadd_pd(ymm10, ymm14, ymm2); //ymm2 += (B10[0][3]*A01[0][2] B10[1][3]*A01[0][2] B10[2][3]*A01[0][2] B10[3][3]*A01[0][2]) ymm4 = _mm256_fmadd_pd(ymm8, ymm15, ymm4); //ymm4 += (B10[4][3]*A01[0][0] B10[5][3]*A01[0][0] B10[6][3]*A01[0][0] B10[7][3]*A01[0][0]) ymm5 = _mm256_fmadd_pd(ymm9, ymm15, ymm5); //ymm5 += (B10[4][3]*A01[0][1] B10[5][3]*A01[0][1] B10[6][3]*A01[0][1] B10[7][3]*A01[0][1]) ymm6 = _mm256_fmadd_pd(ymm10, ymm15, ymm6); //ymm6 += (B10[4][3]*A01[0][2] B10[5][3]*A01[0][2] B10[6][3]*A01[0][2] B10[7][3]*A01[0][2]) b10 += D_NR * cs_b; //pointer math to find next block of B for GEMM a01 = ptr_a01_dup + (D_NR * cs_a); //pointer math to find next block of A for GEMM } ///GEMM code ends/// ymm15 = _mm256_broadcast_sd((double const *)&AlphaVal); ymm8 = _mm256_loadu_pd((double const *)b11); //B11[0-3][0] ymm12 = _mm256_loadu_pd((double const *)(b11 + D_NR)); //B11[4-7][0] ymm9 = _mm256_loadu_pd((double const *)(b11 + cs_b)); //B11[0-3][1] ymm13 = _mm256_loadu_pd((double const *)(b11 + cs_b + D_NR)); //B11[4-7][1] ymm10 = _mm256_loadu_pd((double const *)(b11 + cs_b_offset[0])); //B11[0-3][2] ymm14 = _mm256_loadu_pd((double const *)(b11 + cs_b_offset[0] + D_NR)); //B11[4-7][2] ymm8 = _mm256_fmsub_pd(ymm8, ymm15, ymm0); //B11[0-3][0] * alpha -= B10[0-3][0] ymm9 = _mm256_fmsub_pd(ymm9, ymm15, ymm1); //B11[4-7][0] * alpha -= B10[4-7][0] ymm10 = _mm256_fmsub_pd(ymm10, ymm15, ymm2); //B11[0-3][1] * alpha -= B10[0-3][1] ymm12 = _mm256_fmsub_pd(ymm12, ymm15, ymm4); //B11[0-3][2] * alpha -= B10[0-3][2] ymm13 = _mm256_fmsub_pd(ymm13, ymm15, ymm5); //B11[4-7][2] * alpha -= B10[4-7][2] ymm14 = _mm256_fmsub_pd(ymm14, ymm15, ymm6); //B11[0-3][3] * alpha -= B10[0-3][3] ///implement TRSM/// ///read 4x4 block of A11/// ymm7 = _mm256_broadcast_sd((double const *)(&ones)); //1st col ymm0 = _mm256_broadcast_sd((double const *)(a11+0)); //A11[0][0] //2nd col a11 += 1; ymm1 = _mm256_broadcast_sd((double const *)(a11+ cs_a * 0)); //A11[0][1] ymm2 = _mm256_broadcast_sd((double const *)(a11+ cs_a * 1)); //A11[1][1] //3rd col a11 += 1; ymm3 = _mm256_broadcast_sd((double const *)(a11+ cs_a * 0)); //A11[0][2] ymm4 = _mm256_broadcast_sd((double const *)(a11+ cs_a * 1)); //A11[1][2] ymm5 = _mm256_broadcast_sd((double const *)(a11+ cs_a * 2)); //A11[2][2] //4th col a11 += 1; ymm6 = _mm256_broadcast_sd((double const *)(&ones)); //A11[3][3] //compute reciprocals of L(i,i) and broadcast in registers ymm0 = _mm256_unpacklo_pd(ymm0, ymm2); //A11[0][0] A11[1][1] A11[0][0] A11[1][1] ymm2 = _mm256_unpacklo_pd(ymm5, ymm6); //A11[2][2] A11[3][3] A11[1][1] A11[3][3] ymm0 = _mm256_blend_pd(ymm0, ymm2, 0x0C); //A11[0][0] A11[1][1] A11[2][2] A11[3][3] ymm7 = _mm256_div_pd(ymm7, ymm0); //(1/A11[0][0] 1/A11[1][1] 1/A11[2][2] 1/A11[3][3]) ymm2 = _mm256_broadcast_sd((double const *)(a11+ cs_a * 0)); //A11[0][3] ymm5 = _mm256_broadcast_sd((double const *)(a11+ cs_a * 1)); //A11[1][3] ymm6 = _mm256_broadcast_sd((double const *)(a11+ cs_a * 2)); //A11[2][3] //extract a00 ymm0 = _mm256_permute_pd(ymm7, 0x00); //(1/A11[0][0] 1/A11[0][0] 1/A11[2][2] 1/A11[2][2]) ymm0 = _mm256_permute2f128_pd(ymm0, ymm0, 0x00);//(1/A11[0][0] 1/A11[0][0] 1/A11[0][0] 1/A11[0][0]) ymm8 = _mm256_mul_pd(ymm8, ymm0); //B11[0-3][0] /= A11[0][0] ymm12 = _mm256_mul_pd(ymm12, ymm0); //B11[4-7][0] /= A11[0][0] //extract a11 ymm0 = _mm256_permute_pd(ymm7, 0x03); //(1/A11[1][1] 1/A11[1][1] 1/A11[2][2] 1/A11[2][2]) ymm0 = _mm256_permute2f128_pd(ymm0, ymm0, 0x00);//(1/A11[1][1] 1/A11[1][1] 1/A11[1][1] 1/A11[1][1]) //(Row1): FMA operations ymm9 = _mm256_fnmadd_pd(ymm1, ymm8, ymm9); //B11[0-3][1] -= B11[0-3][0] * A11[0][1] ymm10 = _mm256_fnmadd_pd(ymm3, ymm8, ymm10); //B11[0-3][2] -= B11[0-3][0] * A11[0][2] ymm13 = _mm256_fnmadd_pd(ymm1, ymm12, ymm13); //B11[4-7][1] -= B11[4-7][0] * A11[0][1] ymm14 = _mm256_fnmadd_pd(ymm3, ymm12, ymm14); //B11[4-7][2] -= B11[4-7][0] * A11[0][2] ymm9 = _mm256_mul_pd(ymm9, ymm0); //B11[0-3][1] /= A11[1][1] ymm13 = _mm256_mul_pd(ymm13, ymm0); //B11[4-7][1] /= A11[1][1] //extract a22 ymm0 = _mm256_permute_pd(ymm7, 0x00); //(1/A11[0][0] 1/A11[0][0] 1/A11[2][2] 1/A11[2][2]) ymm0 = _mm256_permute2f128_pd(ymm0, ymm0, 0x11);//(1/A11[2][2] 1/A11[2][2] 1/A11[2][2] 1/A11[2][2]) //(Row2)FMA operations ymm10 = _mm256_fnmadd_pd(ymm4, ymm9, ymm10); //B11[0-3][2] -= B11[0-3][1] * A11[1][2] ymm14 = _mm256_fnmadd_pd(ymm4, ymm13, ymm14); //B11[4-7][2] -= B11[4-7][1] * A11[1][2] ymm10 = _mm256_mul_pd(ymm10, ymm0); //B11[0-3][2] /= A11[2][2] ymm14 = _mm256_mul_pd(ymm14, ymm0); //B11[4-7][2] /= A11[2][2] _mm256_storeu_pd((double *)b11, ymm8); //store(B11[0-3][0]) _mm256_storeu_pd((double *)(b11 + D_NR), ymm12); //store(B11[4-7][0]) _mm256_storeu_pd((double *)(b11 + cs_b), ymm9); //store(B11[0-3][1]) _mm256_storeu_pd((double *)(b11 + cs_b + D_NR), ymm13); //store(B11[4-7][1]) _mm256_storeu_pd((double *)(b11 + cs_b_offset[0]), ymm10); //store(B11[0-3][2]) _mm256_storeu_pd((double *)(b11 + cs_b_offset[0] + D_NR), ymm14);//store(B11[4-7][2]) } else if(2 == n_remainder) { ///GEMM implementation begins/// for(k = 0; k < k_iter; k++) ///loop for number of GEMM operations { ptr_a01_dup = a01; //broadcast 1st row of A01 ymm8 = _mm256_broadcast_sd((double const *)(a01 + 0)); //A01[0][0] ymm9 = _mm256_broadcast_sd((double const *)(a01 + 1)); //A01[0][1] a01 += cs_a; //move to next row of A //load 8x2 block of B10 ymm12 = _mm256_loadu_pd((double const *)b10); //B10[0][0] B10[1][0] B10[2][0] B10[3][0] ymm13 = _mm256_loadu_pd((double const *)(b10 + D_NR)); //B10[4][0] B10[5][0] B10[6][0] B10[7][0] ymm14 = _mm256_loadu_pd((double const *)(b10 + cs_b)); //B10[0][1] B10[1][1] B10[2][1] B10[3][1] ymm15 = _mm256_loadu_pd((double const *)(b10 + cs_b + D_NR));//B10[4][1] B10[5][1] B10[6][1] B10[7][1] ymm0 = _mm256_fmadd_pd(ymm8, ymm12, ymm0); //ymm0 += (B10[0][0]*A01[0][0] B10[1][0]*A01[0][0] B10[2][0]*A01[0][0] B10[3][0]*A01[0][0]) ymm1 = _mm256_fmadd_pd(ymm9, ymm12, ymm1); //ymm1 += (B10[0][0]*A01[0][1] B10[1][0]*A01[0][1] B10[2][0]*A01[0][1] B10[3][0]*A01[0][1]) ymm4 = _mm256_fmadd_pd(ymm8, ymm13, ymm4); //ymm4 += (B10[4][0]*A01[0][0] B10[5][0]*A01[0][0] B10[6][0]*A01[0][0] B10[7][0]*A01[0][0]) ymm5 = _mm256_fmadd_pd(ymm9, ymm13, ymm5); //ymm5 += (B10[4][0]*A01[0][1] B10[5][0]*A01[0][1] B10[6][0]*A01[0][1] B10[7][0]*A01[0][1]) //broadcast 2nd row of A01 ymm8 = _mm256_broadcast_sd((double const *)(a01 + 0)); //A01[1][0] ymm9 = _mm256_broadcast_sd((double const *)(a01 + 1)); //A01[1][1] a01 += cs_a; //move to next row of A ymm0 = _mm256_fmadd_pd(ymm8, ymm14, ymm0); //ymm0 += (B10[0][1]*A01[0][0] B10[1][1]*A01[0][0] B10[2][1]*A01[0][0] B10[3][1]*A01[0][0]) ymm1 = _mm256_fmadd_pd(ymm9, ymm14, ymm1); //ymm1 += (B10[0][1]*A01[0][1] B10[1][1]*A01[0][1] B10[2][1]*A01[0][1] B10[3][1]*A01[0][1]) ymm4 = _mm256_fmadd_pd(ymm8, ymm15, ymm4); //ymm4 += (B10[4][1]*A01[0][0] B10[5][1]*A01[0][0] B10[6][1]*A01[0][0] B10[7][1]*A01[0][0]) ymm5 = _mm256_fmadd_pd(ymm9, ymm15, ymm5); //ymm5 += (B10[4][1]*A01[0][1] B10[5][1]*A01[0][1] B10[6][1]*A01[0][1] B10[7][1]*A01[0][1]) //broadcast 3rd row of A01 ymm8 = _mm256_broadcast_sd((double const *)(a01 + 0)); //A01[2][0] ymm9 = _mm256_broadcast_sd((double const *)(a01 + 1)); //A01[2][1] a01 += cs_a; //move to next row of A //load next 8x2 block of B10 ymm12 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0])); //(B10[0][2] B10[1][2] B10[2][2] B10[3][2]) ymm13 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + D_NR)); //(B10[4][2] B10[5][2] B10[6][2] B10[7][2]) ymm14 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + cs_b)); //(B10[0][3] B10[1][3] B10[2][3] B10[3][3]) ymm15 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + cs_b + D_NR)); //(B10[4][3] B10[5][3] B10[6][3] B10[7][3]) ymm0 = _mm256_fmadd_pd(ymm8, ymm12, ymm0); //ymm0 += (B10[0][2]*A01[0][0] B10[1][2]*A01[0][0] B10[2][2]*A01[0][0] B10[3][2]*A01[0][0]) ymm1 = _mm256_fmadd_pd(ymm9, ymm12, ymm1); //ymm1 += (B10[0][2]*A01[0][1] B10[1][2]*A01[0][1] B10[2][2]*A01[0][1] B10[3][2]*A01[0][1]) ymm4 = _mm256_fmadd_pd(ymm8, ymm13, ymm4); //ymm4 += (B10[4][2]*A01[0][0] B10[5][2]*A01[0][0] B10[6][2]*A01[0][0] B10[7][2]*A01[0][0]) ymm5 = _mm256_fmadd_pd(ymm9, ymm13, ymm5); //ymm5 += (B10[4][2]*A01[0][1] B10[5][2]*A01[0][1] B10[6][2]*A01[0][1] B10[7][2]*A01[0][1]) //broadcast 4th row of A01 ymm8 = _mm256_broadcast_sd((double const *)(a01 + 0)); //A01[3][0] ymm9 = _mm256_broadcast_sd((double const *)(a01 + 1)); //A01[3][1] a01 += cs_a; //move to next row of A ymm0 = _mm256_fmadd_pd(ymm8, ymm14, ymm0); //ymm0 += (B10[0][3]*A01[0][0] B10[1][3]*A01[0][0] B10[2][3]*A01[0][0] B10[3][3]*A01[0][0]) ymm1 = _mm256_fmadd_pd(ymm9, ymm14, ymm1); //ymm1 += (B10[0][3]*A01[0][1] B10[1][3]*A01[0][1] B10[2][3]*A01[0][1] B10[3][3]*A01[0][1]) ymm4 = _mm256_fmadd_pd(ymm8, ymm15, ymm4); //ymm4 += (B10[4][3]*A01[0][0] B10[5][3]*A01[0][0] B10[6][3]*A01[0][0] B10[7][3]*A01[0][0]) ymm5 = _mm256_fmadd_pd(ymm9, ymm15, ymm5); //ymm5 += (B10[4][3]*A01[0][1] B10[5][3]*A01[0][1] B10[6][3]*A01[0][1] B10[7][3]*A01[0][1]) b10 += D_NR * cs_b; //pointer math to find next block of B for GEMM a01 = ptr_a01_dup + (D_NR * cs_a); //pointer math to find next block of A for GEMM } ///GEMM code ends/// ymm15 = _mm256_broadcast_sd((double const *)&AlphaVal); ymm8 = _mm256_loadu_pd((double const *)b11); ymm12 = _mm256_loadu_pd((double const *)(b11 + D_NR)); ymm9 = _mm256_loadu_pd((double const *)(b11 + cs_b)); ymm13 = _mm256_loadu_pd((double const *)(b11 + cs_b + D_NR)); ymm8 = _mm256_fmsub_pd(ymm8, ymm15, ymm0); //B11[0-3][0] * alpha -= B10[0-3][0] ymm9 = _mm256_fmsub_pd(ymm9, ymm15, ymm1); //B11[4-7][0] * alpha -= B10[4-7][0] ymm12 = _mm256_fmsub_pd(ymm12, ymm15, ymm4); //B11[0-3][2] * alpha -= B10[0-3][2] ymm13 = _mm256_fmsub_pd(ymm13, ymm15, ymm5); //B11[4-7][2] * alpha -= B10[4-7][2] ///implement TRSM/// ///read 4x4 block of A11/// ymm7 = _mm256_broadcast_sd((double const *)(&ones)); //1st col ymm0 = _mm256_broadcast_sd((double const *)(a11+0)); //A11[0][0] //2nd col a11 += 1; ymm1 = _mm256_broadcast_sd((double const *)(a11+ cs_a * 0)); //A11[0][1] ymm2 = _mm256_broadcast_sd((double const *)(a11+ cs_a * 1)); //A11[1][1] //compute reciprocals of L(i,i) and broadcast in registers ymm0 = _mm256_unpacklo_pd(ymm0, ymm2); //A11[0][0] A11[1][1] A11[0][0] A11[1][1] ymm0 = _mm256_blend_pd(ymm0, ymm7, 0x0C); //A11[0][0] A11[1][1] A11[2][2] A11[3][3] ymm7 = _mm256_div_pd(ymm7, ymm0); //(1/A11[0][0] 1/A11[1][1] 1/A11[2][2] 1/A11[3][3]) //extract a00 ymm0 = _mm256_permute_pd(ymm7, 0x00); //(1/A11[0][0] 1/A11[0][0] 1/A11[2][2] 1/A11[2][2]) ymm0 = _mm256_permute2f128_pd(ymm0, ymm0, 0x00);//(1/A11[0][0] 1/A11[0][0] 1/A11[0][0] 1/A11[0][0]) ymm8 = _mm256_mul_pd(ymm8, ymm0); //B11[0-3][0] /= A11[0][0] ymm12 = _mm256_mul_pd(ymm12, ymm0); //B11[4-7][0] /= A11[0][0] //extract a11 ymm0 = _mm256_permute_pd(ymm7, 0x03); //(1/A11[1][1] 1/A11[1][1] 1/A11[2][2] 1/A11[2][2]) ymm0 = _mm256_permute2f128_pd(ymm0, ymm0, 0x00);//(1/A11[1][1] 1/A11[1][1] 1/A11[1][1] 1/A11[1][1]) //(Row1): FMA operations ymm9 = _mm256_fnmadd_pd(ymm1, ymm8, ymm9); //B11[0-3][1] -= B11[0-3][0] * A11[0][1] ymm13 = _mm256_fnmadd_pd(ymm1, ymm12, ymm13); //B11[4-7][1] -= B11[4-7][0] * A11[0][1] ymm9 = _mm256_mul_pd(ymm9, ymm0); //B11[0-3][1] /= A11[1][1] ymm13 = _mm256_mul_pd(ymm13, ymm0); //B11[4-7][1] /= A11[1][1] _mm256_storeu_pd((double *)b11, ymm8); //store(B11[0-3][0]) _mm256_storeu_pd((double *)(b11 + D_NR), ymm12); //store(B11[4-7][0]) _mm256_storeu_pd((double *)(b11 + cs_b), ymm9); //store(B11[0-3][1]) _mm256_storeu_pd((double *)(b11 + cs_b + D_NR), ymm13); //store(B11[4-7][1]) } else if(1 == n_remainder) { ///GEMM implementation begins/// for(k = 0; k < k_iter; k++) ///loop for number of GEMM operations { ptr_a01_dup = a01; //broadcast 1st row of A01 ymm8 = _mm256_broadcast_sd((double const *)(a01 + 0)); //A01[0][0] a01 += cs_a; //move to next row of A //load 8x2 block of B10 ymm12 = _mm256_loadu_pd((double const *)b10); //B10[0][0] B10[1][0] B10[2][0] B10[3][0] ymm13 = _mm256_loadu_pd((double const *)(b10 + D_NR)); //B10[4][0] B10[5][0] B10[6][0] B10[7][0] ymm14 = _mm256_loadu_pd((double const *)(b10 + cs_b)); //B10[0][1] B10[1][1] B10[2][1] B10[3][1] ymm15 = _mm256_loadu_pd((double const *)(b10 + cs_b + D_NR));//B10[4][1] B10[5][1] B10[6][1] B10[7][1] ymm0 = _mm256_fmadd_pd(ymm8, ymm12, ymm0); //ymm0 += (B10[0][0]*A01[0][0] B10[1][0]*A01[0][0] B10[2][0]*A01[0][0] B10[3][0]*A01[0][0]) ymm4 = _mm256_fmadd_pd(ymm8, ymm13, ymm4); //ymm4 += (B10[4][0]*A01[0][0] B10[5][0]*A01[0][0] B10[6][0]*A01[0][0] B10[7][0]*A01[0][0]) //broadcast 2nd row of A01 ymm8 = _mm256_broadcast_sd((double const *)(a01 + 0)); //A01[1][0] a01 += cs_a; //move to next row of A ymm0 = _mm256_fmadd_pd(ymm8, ymm14, ymm0); //ymm0 += (B10[0][1]*A01[0][0] B10[1][1]*A01[0][0] B10[2][1]*A01[0][0] B10[3][1]*A01[0][0]) ymm4 = _mm256_fmadd_pd(ymm8, ymm15, ymm4); //ymm4 += (B10[4][1]*A01[0][0] B10[5][1]*A01[0][0] B10[6][1]*A01[0][0] B10[7][1]*A01[0][0]) //broadcast 3rd row of A01 ymm8 = _mm256_broadcast_sd((double const *)(a01 + 0)); //A01[2][0] a01 += cs_a; //move to next row of A //load next 8x2 block of B10 ymm12 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0])); //(B10[0][2] B10[1][2] B10[2][2] B10[3][2]) ymm13 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + D_NR)); //(B10[4][2] B10[5][2] B10[6][2] B10[7][2]) ymm14 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + cs_b)); //(B10[0][3] B10[1][3] B10[2][3] B10[3][3]) ymm15 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + cs_b + D_NR)); //(B10[4][3] B10[5][3] B10[6][3] B10[7][3]) ymm0 = _mm256_fmadd_pd(ymm8, ymm12, ymm0); //ymm0 += (B10[0][2]*A01[0][0] B10[1][2]*A01[0][0] B10[2][2]*A01[0][0] B10[3][2]*A01[0][0]) ymm4 = _mm256_fmadd_pd(ymm8, ymm13, ymm4); //ymm4 += (B10[4][2]*A01[0][0] B10[5][2]*A01[0][0] B10[6][2]*A01[0][0] B10[7][2]*A01[0][0]) //broadcast 4th row of A01 ymm8 = _mm256_broadcast_sd((double const *)(a01 + 0)); //A01[3][0] a01 += cs_a; //move to next row of A ymm0 = _mm256_fmadd_pd(ymm8, ymm14, ymm0); //ymm0 += (B10[0][3]*A01[0][0] B10[1][3]*A01[0][0] B10[2][3]*A01[0][0] B10[3][3]*A01[0][0]) ymm4 = _mm256_fmadd_pd(ymm8, ymm15, ymm4); //ymm4 += (B10[4][3]*A01[0][0] B10[5][3]*A01[0][0] B10[6][3]*A01[0][0] B10[7][3]*A01[0][0]) b10 += D_NR * cs_b; //pointer math to find next block of B for GEMM a01 = ptr_a01_dup + (D_NR * cs_a); //pointer math to find next block of A for GEMM } ///GEMM code ends/// ymm15 = _mm256_broadcast_sd((double const *)&AlphaVal); ymm8 = _mm256_loadu_pd((double const *)b11); //B11[0-3][0] ymm12 = _mm256_loadu_pd((double const *)(b11 + D_NR)); //B11[4-7][0] ymm8 = _mm256_fmsub_pd(ymm8, ymm15, ymm0); //B11[0-3][0] * alpha -= B10[0-3][0] ymm12 = _mm256_fmsub_pd(ymm12, ymm15, ymm4); //B11[0-3][2] * alpha -= B10[0-3][2] ///implement TRSM/// ymm7 = _mm256_broadcast_sd((double const *)(&ones)); //1st col ymm0 = _mm256_broadcast_sd((double const *)(a11+0)); //A11[0][0] ymm7 = _mm256_div_pd(ymm7, ymm0); //(1/A11[0][0] 1/A11[1][1] 1/A11[2][2] 1/A11[3][3]) ymm8 = _mm256_mul_pd(ymm8, ymm7); //B11[0-3][0] /= A11[0][0] ymm12 = _mm256_mul_pd(ymm12, ymm7); //B11[4-7][0] /= A11[0][0] _mm256_storeu_pd((double *)b11, ymm8); //store(B11[0-3][0]) _mm256_storeu_pd((double *)(b11 + D_NR), ymm12); //store(B11[4-7][0]) } } } if((m & 4)) ///implementation for remainder rows(when m_remainder is greater than 4) { for(j = 0; (j+D_NR-1) a01 ----> ***************** *********** *b01*b11* * * * * * * b11 * * * * * **a01 * * a11 | ***************** ********* | | * * * * * *a11* * | | * * * * * * * * | v ***************** ****** v * * * * * * * * * * * * * * ***************** * * * */ static err_t bli_dtrsm_small_XAltB_unitDiag( side_t side, obj_t* AlphaObj, obj_t* a, obj_t* b, cntx_t* cntx, cntl_t* cntl ) { dim_t D_MR = 8; //block dimension along the rows dim_t D_NR = 4; //block dimension along the columns dim_t m = bli_obj_length(b); //number of rows dim_t n = bli_obj_width(b); //number of columns dim_t m_remainder = m & 7; //number of corner rows dim_t n_remainder = n & 3; //number of corner columns dim_t cs_a = bli_obj_col_stride(a); //column stride of matrix A dim_t cs_b = bli_obj_col_stride(b); //column stride of matrix B #ifdef BLIS_ENABLE_SMALL_MATRIX_ROME if((m < D_BLIS_SMALL_MATRIX_THRES_TRSM_XALTB_ROME_ROW_PANEL_M && n>D_BLIS_SMALL_MATRIX_THRES_TRSM_XALTB_ROME_ROW_PANEL_N) || (m < D_BLIS_SMALL_MATRIX_THRES_TRSM_XALTB_ROME_SQUARE_M && n > D_BLIS_SMALL_MATRIX_THRES_TRSM_XALTB_ROME_SQUARE_N) || (m < D_BLIS_SMALL_MATRIX_THRES_TRSM_XALTB_ROME_COLUMN_PANEL_N && n > D_BLIS_SMALL_MATRIX_THRES_TRSM_XALTB_ROME) || (m < D_BLIS_SMALL_MATRIX_THRES_TRSM_XALTB_ROME && n > D_BLIS_SMALL_MATRIX_THRES_TRSM_XALTB_ROME) || (m > D_BLIS_SMALL_MATRIX_THRES_TRSM_XALTB_ROME && n > D_BLIS_SMALL_MATRIX_THRES_TRSM_XALTB_ROME_COLUMN_PANEL_N) ) return BLIS_NOT_YET_IMPLEMENTED; #else if(bli_max(m,n) > D_BLIS_SMALL_MATRIX_THRES_TRSM_NAPLES) { return BLIS_NOT_YET_IMPLEMENTED; } #endif dim_t i, j, k; //loop variablse dim_t k_iter; //determines the number of GEMM operations to be done dim_t cs_b_offset[2]; //pre-calculated strides double AlphaVal = *(double *)AlphaObj->buffer; //value of Alpha double *L = a->buffer; //pointer to matrix A double *B = b->buffer; //pointer to matrix B double *a01, *a11, *b10, *b11; //pointers for GEMM and TRSM blocks double *ptr_a01_dup; double f_t[4] __attribute__((aligned(64)));//buffer to store corner column when m_remainder !=0 double* f_temp; cs_b_offset[0] = cs_b << 1; //cs_b_offset[0] = cs_b * 2; cs_b_offset[1] = cs_b_offset[0] + cs_b;//cs_b_offset[1] = cs_b * 3; //ymm scratch reginsters __m256d ymm0, ymm1, ymm2, ymm3; __m256d ymm4, ymm5, ymm6, ymm7; __m256d ymm8, ymm9, ymm10, ymm11; __m256d ymm12, ymm13, ymm14, ymm15; __m256d ymm16; for(i = 0; (i+D_MR-1) < m; i += D_MR) //loop along 'M' direction { for(j = 0; (j+D_NR-1) < n; j += D_NR) //loop along 'N' direction { a01 = L + j; //pointer to block of A to be used in GEMM a11 = L + j*cs_a + j; //pointer to block of A to be used for TRSM b10 = B + i; //pointer to block of B to be used in GEMM b11 = B + i + j*cs_b; //pointer to block of B to be used for TRSM k_iter = j / D_NR; //number of GEMM operations to be done(in blocks of 4x4) ymm0 = _mm256_setzero_pd(); ymm1 = _mm256_setzero_pd(); ymm2 = _mm256_setzero_pd(); ymm3 = _mm256_setzero_pd(); ymm4 = _mm256_setzero_pd(); ymm5 = _mm256_setzero_pd(); ymm6 = _mm256_setzero_pd(); ymm7 = _mm256_setzero_pd(); ///GEMM implementation starts/// for(k = 0; k < k_iter; k++) //loop for number of GEMM operations { ptr_a01_dup = a01; //broadcast 1st row of A01 ymm8 = _mm256_broadcast_sd((double const *)(a01 + 0)); //A01[0][0] ymm9 = _mm256_broadcast_sd((double const *)(a01 + 1)); //A01[0][1] ymm10 = _mm256_broadcast_sd((double const *)(a01 + 2)); //A01[0][2] ymm11 = _mm256_broadcast_sd((double const *)(a01 + 3)); //A01[0][3] a01 += cs_a; //move to next row //load 8x2 block of B10 ymm12 = _mm256_loadu_pd((double const *)b10); //B10[0][0] B10[1][0] B10[2][0] B10[3][0] ymm13 = _mm256_loadu_pd((double const *)(b10 + D_NR)); //B10[4][0] B10[5][0] B10[6][0] B10[7][0] ymm14 = _mm256_loadu_pd((double const *)(b10 + cs_b)); //B10[0][1] B10[1][1] B10[2][1] B10[3][1] ymm15 = _mm256_loadu_pd((double const *)(b10 + cs_b + D_NR)); //B10[4][1] B10[5][1] B10[6][1] B10[7][1] ymm0 = _mm256_fmadd_pd(ymm8, ymm12, ymm0); //ymm0 += (B10[0][0]*A01[0][0] B10[1][0]*A01[0][0] B10[2][0]*A01[0][0] B10[3][0]*A01[0][0]) ymm1 = _mm256_fmadd_pd(ymm9, ymm12, ymm1); //ymm1 += (B10[0][0]*A01[0][1] B10[1][0]*A01[0][1] B10[2][0]*A01[0][1] B10[3][0]*A01[0][1]) ymm2 = _mm256_fmadd_pd(ymm10, ymm12, ymm2); //ymm2 += (B10[0][0]*A01[0][2] B10[1][0]*A01[0][2] B10[2][0]*A01[0][2] B10[3][0]*A01[0][2]) ymm3 = _mm256_fmadd_pd(ymm11, ymm12, ymm3); //ymm3 += (B10[0][0]*A01[0][3] B10[1][0]*A01[0][3] B10[2][0]*A01[0][3] B10[3][0]*A01[0][3]) ymm4 = _mm256_fmadd_pd(ymm8, ymm13, ymm4); //ymm4 += (B10[4][0]*A01[0][0] B10[5][0]*A01[0][0] B10[6][0]*A01[0][0] B10[7][0]*A01[0][0]) ymm5 = _mm256_fmadd_pd(ymm9, ymm13, ymm5); //ymm5 += (B10[4][0]*A01[0][1] B10[5][0]*A01[0][1] B10[6][0]*A01[0][1] B10[7][0]*A01[0][1]) ymm6 = _mm256_fmadd_pd(ymm10, ymm13, ymm6); //ymm6 += (B10[4][0]*A01[0][2] B10[5][0]*A01[0][2] B10[6][0]*A01[0][2] B10[7][0]*A01[0][2]) ymm7 = _mm256_fmadd_pd(ymm11, ymm13, ymm7); //ymm7 += (B10[4][0]*A01[0][3] B10[5][0]*A01[0][3] B10[6][0]*A01[0][3] B10[7][0]*A01[0][3]) //broadcast 2nd row of A01 ymm8 = _mm256_broadcast_sd((double const *)(a01 + 0)); //A01[1][0] ymm9 = _mm256_broadcast_sd((double const *)(a01 + 1)); //A01[1][1] ymm10 = _mm256_broadcast_sd((double const *)(a01 + 2)); //A01[1][2] ymm11 = _mm256_broadcast_sd((double const *)(a01 + 3)); //A01[1][3] a01 += cs_a; //move to next row of A ymm0 = _mm256_fmadd_pd(ymm8, ymm14, ymm0); //ymm0 += (B10[0][1]*A01[0][0] B10[1][1]*A01[0][0] B10[2][1]*A01[0][0] B10[3][1]*A01[0][0]) ymm1 = _mm256_fmadd_pd(ymm9, ymm14, ymm1); //ymm1 += (B10[0][1]*A01[0][1] B10[1][1]*A01[0][1] B10[2][1]*A01[0][1] B10[3][1]*A01[0][1]) ymm2 = _mm256_fmadd_pd(ymm10, ymm14, ymm2); //ymm2 += (B10[0][1]*A01[0][2] B10[1][1]*A01[0][2] B10[2][1]*A01[0][2] B10[3][1]*A01[0][2]) ymm3 = _mm256_fmadd_pd(ymm11, ymm14, ymm3); //ymm3 += (B10[0][1]*A01[0][3] B10[1][1]*A01[0][3] B10[2][1]*A01[0][3] B10[3][1]*A01[0][3]) ymm4 = _mm256_fmadd_pd(ymm8, ymm15, ymm4); //ymm4 += (B10[4][1]*A01[0][0] B10[5][1]*A01[0][0] B10[6][1]*A01[0][0] B10[7][1]*A01[0][0]) ymm5 = _mm256_fmadd_pd(ymm9, ymm15, ymm5); //ymm5 += (B10[4][1]*A01[0][1] B10[5][1]*A01[0][1] B10[6][1]*A01[0][1] B10[7][1]*A01[0][1]) ymm6 = _mm256_fmadd_pd(ymm10, ymm15, ymm6); //ymm6 += (B10[4][1]*A01[0][2] B10[5][1]*A01[0][2] B10[6][1]*A01[0][2] B10[7][1]*A01[0][2]) ymm7 = _mm256_fmadd_pd(ymm11, ymm15, ymm7); //ymm7 += (B10[4][1]*A01[0][3] B10[5][1]*A01[0][3] B10[6][1]*A01[0][3] B10[7][1]*A01[0][3]) //broadcast 3rd row of A01 ymm8 = _mm256_broadcast_sd((double const *)(a01 + 0)); //A01[2][0] ymm9 = _mm256_broadcast_sd((double const *)(a01 + 1)); //A01[2][1] ymm10 = _mm256_broadcast_sd((double const *)(a01 + 2)); //A01[2][2] ymm11 = _mm256_broadcast_sd((double const *)(a01 + 3)); //A01[2][3] a01 += cs_a; //move to next row of A01 //load next 8x2 block of B10 ymm12 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0])); //(B10[0][2] B10[1][2] B10[2][2] B10[3][2]) ymm13 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + D_NR)); //(B10[4][2] B10[5][2] B10[6][2] B10[7][2]) ymm14 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + cs_b)); //(B10[0][3] B10[1][3] B10[2][3] B10[3][3]) ymm15 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + cs_b + D_NR)); //(B10[4][3] B10[5][3] B10[6][3] B10[7][3]) ymm0 = _mm256_fmadd_pd(ymm8, ymm12, ymm0); //ymm0 += (B10[0][2]*A01[0][0] B10[1][2]*A01[0][0] B10[2][2]*A01[0][0] B10[3][2]*A01[0][0]) ymm1 = _mm256_fmadd_pd(ymm9, ymm12, ymm1); //ymm1 += (B10[0][2]*A01[0][1] B10[1][2]*A01[0][1] B10[2][2]*A01[0][1] B10[3][2]*A01[0][1]) ymm2 = _mm256_fmadd_pd(ymm10, ymm12, ymm2); //ymm2 += (B10[0][2]*A01[0][2] B10[1][2]*A01[0][2] B10[2][2]*A01[0][2] B10[3][2]*A01[0][2]) ymm3 = _mm256_fmadd_pd(ymm11, ymm12, ymm3); //ymm3 += (B10[0][2]*A01[0][3] B10[1][2]*A01[0][3] B10[2][2]*A01[0][3] B10[3][2]*A01[0][3]) ymm4 = _mm256_fmadd_pd(ymm8, ymm13, ymm4); //ymm4 += (B10[4][2]*A01[0][0] B10[5][2]*A01[0][0] B10[6][2]*A01[0][0] B10[7][2]*A01[0][0]) ymm5 = _mm256_fmadd_pd(ymm9, ymm13, ymm5); //ymm5 += (B10[4][2]*A01[0][1] B10[5][2]*A01[0][1] B10[6][2]*A01[0][1] B10[7][2]*A01[0][1]) ymm6 = _mm256_fmadd_pd(ymm10, ymm13, ymm6); //ymm6 += (B10[4][2]*A01[0][2] B10[5][2]*A01[0][2] B10[6][2]*A01[0][2] B10[7][2]*A01[0][2]) ymm7 = _mm256_fmadd_pd(ymm11, ymm13, ymm7); //ymm7 += (B10[4][2]*A01[0][3] B10[5][2]*A01[0][3] B10[6][2]*A01[0][3] B10[7][2]*A01[0][3]) //broadcast 4th row of A01 ymm8 = _mm256_broadcast_sd((double const *)(a01 + 0)); //A01[3][0] ymm9 = _mm256_broadcast_sd((double const *)(a01 + 1)); //A01[3][1] ymm10 = _mm256_broadcast_sd((double const *)(a01 + 2)); //A01[3][2] ymm11 = _mm256_broadcast_sd((double const *)(a01 + 3)); //A01[3][3] a01 += cs_a; //move to next row of A01 ymm0 = _mm256_fmadd_pd(ymm8, ymm14, ymm0); //ymm0 += (B10[0][3]*A01[0][0] B10[1][3]*A01[0][0] B10[2][3]*A01[0][0] B10[3][3]*A01[0][0]) ymm1 = _mm256_fmadd_pd(ymm9, ymm14, ymm1); //ymm1 += (B10[0][3]*A01[0][1] B10[1][3]*A01[0][1] B10[2][3]*A01[0][1] B10[3][3]*A01[0][1]) ymm2 = _mm256_fmadd_pd(ymm10, ymm14, ymm2); //ymm2 += (B10[0][3]*A01[0][2] B10[1][3]*A01[0][2] B10[2][3]*A01[0][2] B10[3][3]*A01[0][2]) ymm3 = _mm256_fmadd_pd(ymm11, ymm14, ymm3); //ymm3 += (B10[0][3]*A01[0][3] B10[1][3]*A01[0][3] B10[2][3]*A01[0][3] B10[3][3]*A01[0][3]) ymm4 = _mm256_fmadd_pd(ymm8, ymm15, ymm4); //ymm4 += (B10[4][3]*A01[0][0] B10[5][3]*A01[0][0] B10[6][3]*A01[0][0] B10[7][3]*A01[0][0]) ymm5 = _mm256_fmadd_pd(ymm9, ymm15, ymm5); //ymm5 += (B10[4][3]*A01[0][1] B10[5][3]*A01[0][1] B10[6][3]*A01[0][1] B10[7][3]*A01[0][1]) ymm6 = _mm256_fmadd_pd(ymm10, ymm15, ymm6); //ymm6 += (B10[4][3]*A01[0][2] B10[5][3]*A01[0][2] B10[6][3]*A01[0][2] B10[7][3]*A01[0][2]) ymm7 = _mm256_fmadd_pd(ymm11, ymm15, ymm7); //ymm7 += (B10[4][3]*A01[0][3] B10[5][3]*A01[0][3] B10[6][3]*A01[0][3] B10[7][3]*A01[0][3]) b10 += D_NR * cs_b; //pointer math to find next block of B for GEMM a01 = ptr_a01_dup + (D_NR * cs_a); //pointer math to find next block of A for GEMM } ///GEMM code ends/// ymm16 = _mm256_broadcast_sd((double const *)&AlphaVal); //load 8x4 block of B11 ymm8 = _mm256_loadu_pd((double const *)b11); //B11[0][0] B11[1][0] B11[2][0] B11[3][0] ymm12 = _mm256_loadu_pd((double const *)(b11 + D_NR)); //B11[4][0] B11[5][0] B11[6][0] B11[7][0] ymm9 = _mm256_loadu_pd((double const *)(b11 + cs_b)); //B11[0][1] B11[1][1] B11[2][1] B11[3][1] ymm13 = _mm256_loadu_pd((double const *)(b11 + cs_b + D_NR)); //B11[4][1] B11[5][1] B11[6][1] B11[7][1] ymm10 = _mm256_loadu_pd((double const *)(b11 + cs_b_offset[0])); //B11[0][2] B11[1][2] B11[2][2] B11[3][2] ymm14 = _mm256_loadu_pd((double const *)(b11 + cs_b_offset[0] + D_NR)); //B11[4][2] B11[5][2] B11[6][2] B11[7][2] ymm11 = _mm256_loadu_pd((double const *)(b11 + cs_b_offset[1])); //B11[0][3] B11[1][3] B11[2][3] B11[3][3] ymm15 = _mm256_loadu_pd((double const *)(b11 + cs_b_offset[1] + D_NR)); //B11[4][3] B11[5][3] B11[6][3] B11[7][3] ymm8 = _mm256_fmsub_pd(ymm8, ymm16, ymm0); //B11[0-3][0] * alpha -= ymm0 ymm9 = _mm256_fmsub_pd(ymm9, ymm16, ymm1); //B11[4-7][0] * alpha-= ymm1 ymm10 = _mm256_fmsub_pd(ymm10, ymm16, ymm2); //B11[0-3][1] * alpha-= ymm2 ymm11 = _mm256_fmsub_pd(ymm11, ymm16, ymm3); //B11[4-7][1] * alpha -= ymm3 ymm12 = _mm256_fmsub_pd(ymm12, ymm16, ymm4); //B11[0-3][2] * alpha -= ymm4 ymm13 = _mm256_fmsub_pd(ymm13, ymm16, ymm5); //B11[4-7][2] * alpha -= ymm5 ymm14 = _mm256_fmsub_pd(ymm14, ymm16, ymm6); //B11[0-3][3] * alpha -= ymm6 ymm15 = _mm256_fmsub_pd(ymm15, ymm16, ymm7); //B11[4-7][3] * alpha -= ymm7 ///implement TRSM/// ///read 4x4 block of A11/// //2nd col a11 += 1; ymm1 = _mm256_broadcast_sd((double const *)(a11+ cs_a * 0)); //A11[0][1] //3rd col a11 += 1; ymm3 = _mm256_broadcast_sd((double const *)(a11+ cs_a * 0)); //A11[0][2] ymm4 = _mm256_broadcast_sd((double const *)(a11+ cs_a * 1)); //A11[1][2] //4th col a11 += 1; ymm2 = _mm256_broadcast_sd((double const *)(a11+ cs_a * 0)); //A11[0][3] ymm5 = _mm256_broadcast_sd((double const *)(a11+ cs_a * 1)); //A11[1][3] ymm6 = _mm256_broadcast_sd((double const *)(a11+ cs_a * 2)); //A11[2][3] //(Row1): FMA operations ymm9 = _mm256_fnmadd_pd(ymm1, ymm8, ymm9); //B11[0-3][1] -= B11[0-3][0] * A11[0][1] ymm10 = _mm256_fnmadd_pd(ymm3, ymm8, ymm10); //B11[0-3][2] -= B11[0-3][0] * A11[0][2] ymm11 = _mm256_fnmadd_pd(ymm2, ymm8, ymm11); //B11[0-3][3] -= B11[0-3][0] * A11[0][3] ymm13 = _mm256_fnmadd_pd(ymm1, ymm12, ymm13); //B11[4-7][1] -= B11[4-7][0] * A11[0][1] ymm14 = _mm256_fnmadd_pd(ymm3, ymm12, ymm14); //B11[4-7][2] -= B11[4-7][0] * A11[0][2] ymm15 = _mm256_fnmadd_pd(ymm2, ymm12, ymm15); //B11[4-7][3] -= B11[4-7][0] * A11[0][3] //(Row2)FMA operations ymm10 = _mm256_fnmadd_pd(ymm4, ymm9, ymm10); //B11[0-3][2] -= B11[0-3][1] * A11[1][2] ymm11 = _mm256_fnmadd_pd(ymm5, ymm9, ymm11); //B11[0-3][3] -= B11[0-3][1] * A11[1][3] ymm14 = _mm256_fnmadd_pd(ymm4, ymm13, ymm14); //B11[4-7][2] -= B11[4-7][1] * A11[1][2] ymm15 = _mm256_fnmadd_pd(ymm5, ymm13, ymm15); //B11[4-7][3] -= B11[4-7][1] * A11[1][3] //(Row3)FMA operations ymm11 = _mm256_fnmadd_pd(ymm6, ymm10, ymm11); //B11[0-3][3] -= B11[0-3][2] * A11[2][3] ymm15 = _mm256_fnmadd_pd(ymm6, ymm14, ymm15); //B11[4-7][3] -= B11[4-7][2] * A11[2][3] _mm256_storeu_pd((double *)b11, ymm8); //store(B11[0-3][0]) _mm256_storeu_pd((double *)(b11 + D_NR), ymm12); //store(B11[4-7][0]) _mm256_storeu_pd((double *)(b11 + cs_b), ymm9); //store(B11[0-3][1]) _mm256_storeu_pd((double *)(b11 + cs_b + D_NR), ymm13); //store(B11[4-7][1]) _mm256_storeu_pd((double *)(b11 + cs_b_offset[0]), ymm10); //store(B11[0-3][2]) _mm256_storeu_pd((double *)(b11 + cs_b_offset[0] + D_NR), ymm14); //store(B11[4-7][2]) _mm256_storeu_pd((double *)(b11 + cs_b_offset[0] + cs_b), ymm11); //store(B11[0-3][3]) _mm256_storeu_pd((double *)(b11 + cs_b_offset[0] + cs_b + D_NR), ymm15);//store(B11[4-7][3]) } if(n_remainder) //implementation for remainder columns(when n is not multiple of D_NR) { a01 = L + j; //pointer to block of A to be used for GEMM a11 = L + j*cs_a + j; //pointer to block of A to be used for TRSM b10 = B + i; //pointer to block of B to be used for GEMM b11 = B + i + j*cs_b; //pointer to block of B to be used for TRSM k_iter = j / D_NR; //number of GEMM operations to be performed(in blocks of 4x4) ///load 4x4 block of b11 ymm0 = _mm256_setzero_pd(); ymm1 = _mm256_setzero_pd(); ymm2 = _mm256_setzero_pd(); ymm3 = _mm256_setzero_pd(); ymm4 = _mm256_setzero_pd(); ymm5 = _mm256_setzero_pd(); ymm6 = _mm256_setzero_pd(); ymm7 = _mm256_setzero_pd(); //subtract the calculated GEMM block from current TRSM block //load 8x4 block of B11 if(3 == n_remainder) { ///GEMM implementation begins/// for(k = 0; k < k_iter; k++) ///loop for number of GEMM operations { ptr_a01_dup = a01; //broadcast 1st row of A01 ymm8 = _mm256_broadcast_sd((double const *)(a01 + 0)); //A01[0][0] ymm9 = _mm256_broadcast_sd((double const *)(a01 + 1)); //A01[0][1] ymm10 = _mm256_broadcast_sd((double const *)(a01 + 2)); //A01[0][2] a01 += cs_a; //move to next row of A //load 8x2 block of B10 ymm12 = _mm256_loadu_pd((double const *)b10); //B10[0][0] B10[1][0] B10[2][0] B10[3][0] ymm13 = _mm256_loadu_pd((double const *)(b10 + D_NR)); //B10[4][0] B10[5][0] B10[6][0] B10[7][0] ymm14 = _mm256_loadu_pd((double const *)(b10 + cs_b)); //B10[0][1] B10[1][1] B10[2][1] B10[3][1] ymm15 = _mm256_loadu_pd((double const *)(b10 + cs_b + D_NR));//B10[4][1] B10[5][1] B10[6][1] B10[7][1] ymm0 = _mm256_fmadd_pd(ymm8, ymm12, ymm0); //ymm0 += (B10[0][0]*A01[0][0] B10[1][0]*A01[0][0] B10[2][0]*A01[0][0] B10[3][0]*A01[0][0]) ymm1 = _mm256_fmadd_pd(ymm9, ymm12, ymm1); //ymm1 += (B10[0][0]*A01[0][1] B10[1][0]*A01[0][1] B10[2][0]*A01[0][1] B10[3][0]*A01[0][1]) ymm2 = _mm256_fmadd_pd(ymm10, ymm12, ymm2); //ymm2 += (B10[0][0]*A01[0][2] B10[1][0]*A01[0][2] B10[2][0]*A01[0][2] B10[3][0]*A01[0][2]) ymm4 = _mm256_fmadd_pd(ymm8, ymm13, ymm4); //ymm4 += (B10[4][0]*A01[0][0] B10[5][0]*A01[0][0] B10[6][0]*A01[0][0] B10[7][0]*A01[0][0]) ymm5 = _mm256_fmadd_pd(ymm9, ymm13, ymm5); //ymm5 += (B10[4][0]*A01[0][1] B10[5][0]*A01[0][1] B10[6][0]*A01[0][1] B10[7][0]*A01[0][1]) ymm6 = _mm256_fmadd_pd(ymm10, ymm13, ymm6); //ymm6 += (B10[4][0]*A01[0][2] B10[5][0]*A01[0][2] B10[6][0]*A01[0][2] B10[7][0]*A01[0][2]) //broadcast 2nd row of A01 ymm8 = _mm256_broadcast_sd((double const *)(a01 + 0)); //A01[1][0] ymm9 = _mm256_broadcast_sd((double const *)(a01 + 1)); //A01[1][1] ymm10 = _mm256_broadcast_sd((double const *)(a01 + 2)); //A01[1][2] a01 += cs_a; //move to next row of A ymm0 = _mm256_fmadd_pd(ymm8, ymm14, ymm0); //ymm0 += (B10[0][1]*A01[0][0] B10[1][1]*A01[0][0] B10[2][1]*A01[0][0] B10[3][1]*A01[0][0]) ymm1 = _mm256_fmadd_pd(ymm9, ymm14, ymm1); //ymm1 += (B10[0][1]*A01[0][1] B10[1][1]*A01[0][1] B10[2][1]*A01[0][1] B10[3][1]*A01[0][1]) ymm2 = _mm256_fmadd_pd(ymm10, ymm14, ymm2); //ymm2 += (B10[0][1]*A01[0][2] B10[1][1]*A01[0][2] B10[2][1]*A01[0][2] B10[3][1]*A01[0][2]) ymm4 = _mm256_fmadd_pd(ymm8, ymm15, ymm4); //ymm4 += (B10[4][1]*A01[0][0] B10[5][1]*A01[0][0] B10[6][1]*A01[0][0] B10[7][1]*A01[0][0]) ymm5 = _mm256_fmadd_pd(ymm9, ymm15, ymm5); //ymm5 += (B10[4][1]*A01[0][1] B10[5][1]*A01[0][1] B10[6][1]*A01[0][1] B10[7][1]*A01[0][1]) ymm6 = _mm256_fmadd_pd(ymm10, ymm15, ymm6); //ymm6 += (B10[4][1]*A01[0][2] B10[5][1]*A01[0][2] B10[6][1]*A01[0][2] B10[7][1]*A01[0][2]) //broadcast 3rd row of A01 ymm8 = _mm256_broadcast_sd((double const *)(a01 + 0)); //A01[2][0] ymm9 = _mm256_broadcast_sd((double const *)(a01 + 1)); //A01[2][1] ymm10 = _mm256_broadcast_sd((double const *)(a01 + 2)); //A01[2][2] a01 += cs_a; //move to next row of A //load next 8x2 block of B10 ymm12 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0])); //(B10[0][2] B10[1][2] B10[2][2] B10[3][2]) ymm13 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + D_NR)); //(B10[4][2] B10[5][2] B10[6][2] B10[7][2]) ymm14 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + cs_b)); //(B10[0][3] B10[1][3] B10[2][3] B10[3][3]) ymm15 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + cs_b + D_NR)); //(B10[4][3] B10[5][3] B10[6][3] B10[7][3]) ymm0 = _mm256_fmadd_pd(ymm8, ymm12, ymm0); //ymm0 += (B10[0][2]*A01[0][0] B10[1][2]*A01[0][0] B10[2][2]*A01[0][0] B10[3][2]*A01[0][0]) ymm1 = _mm256_fmadd_pd(ymm9, ymm12, ymm1); //ymm1 += (B10[0][2]*A01[0][1] B10[1][2]*A01[0][1] B10[2][2]*A01[0][1] B10[3][2]*A01[0][1]) ymm2 = _mm256_fmadd_pd(ymm10, ymm12, ymm2); //ymm2 += (B10[0][2]*A01[0][2] B10[1][2]*A01[0][2] B10[2][2]*A01[0][2] B10[3][2]*A01[0][2]) ymm4 = _mm256_fmadd_pd(ymm8, ymm13, ymm4); //ymm4 += (B10[4][2]*A01[0][0] B10[5][2]*A01[0][0] B10[6][2]*A01[0][0] B10[7][2]*A01[0][0]) ymm5 = _mm256_fmadd_pd(ymm9, ymm13, ymm5); //ymm5 += (B10[4][2]*A01[0][1] B10[5][2]*A01[0][1] B10[6][2]*A01[0][1] B10[7][2]*A01[0][1]) ymm6 = _mm256_fmadd_pd(ymm10, ymm13, ymm6); //ymm6 += (B10[4][2]*A01[0][2] B10[5][2]*A01[0][2] B10[6][2]*A01[0][2] B10[7][2]*A01[0][2]) //broadcast 4th row of A01 ymm8 = _mm256_broadcast_sd((double const *)(a01 + 0)); //A01[3][0] ymm9 = _mm256_broadcast_sd((double const *)(a01 + 1)); //A01[3][1] ymm10 = _mm256_broadcast_sd((double const *)(a01 + 2)); //A01[3][2] a01 += cs_a; //move to next row of A ymm0 = _mm256_fmadd_pd(ymm8, ymm14, ymm0); //ymm0 += (B10[0][3]*A01[0][0] B10[1][3]*A01[0][0] B10[2][3]*A01[0][0] B10[3][3]*A01[0][0]) ymm1 = _mm256_fmadd_pd(ymm9, ymm14, ymm1); //ymm1 += (B10[0][3]*A01[0][1] B10[1][3]*A01[0][1] B10[2][3]*A01[0][1] B10[3][3]*A01[0][1]) ymm2 = _mm256_fmadd_pd(ymm10, ymm14, ymm2); //ymm2 += (B10[0][3]*A01[0][2] B10[1][3]*A01[0][2] B10[2][3]*A01[0][2] B10[3][3]*A01[0][2]) ymm4 = _mm256_fmadd_pd(ymm8, ymm15, ymm4); //ymm4 += (B10[4][3]*A01[0][0] B10[5][3]*A01[0][0] B10[6][3]*A01[0][0] B10[7][3]*A01[0][0]) ymm5 = _mm256_fmadd_pd(ymm9, ymm15, ymm5); //ymm5 += (B10[4][3]*A01[0][1] B10[5][3]*A01[0][1] B10[6][3]*A01[0][1] B10[7][3]*A01[0][1]) ymm6 = _mm256_fmadd_pd(ymm10, ymm15, ymm6); //ymm6 += (B10[4][3]*A01[0][2] B10[5][3]*A01[0][2] B10[6][3]*A01[0][2] B10[7][3]*A01[0][2]) b10 += D_NR * cs_b; //pointer math to find next block of B for GEMM a01 = ptr_a01_dup + (D_NR * cs_a); //pointer math to find next block of A for GEMM } ///GEMM code ends/// ymm15 = _mm256_broadcast_sd((double const *)&AlphaVal); ymm8 = _mm256_loadu_pd((double const *)b11); //B11[0-3][0] ymm12 = _mm256_loadu_pd((double const *)(b11 + D_NR)); //B11[4-7][0] ymm9 = _mm256_loadu_pd((double const *)(b11 + cs_b)); //B11[0-3][1] ymm13 = _mm256_loadu_pd((double const *)(b11 + cs_b + D_NR)); //B11[4-7][1] ymm10 = _mm256_loadu_pd((double const *)(b11 + cs_b_offset[0])); //B11[0-3][2] ymm14 = _mm256_loadu_pd((double const *)(b11 + cs_b_offset[0] + D_NR)); //B11[4-7][2] ymm8 = _mm256_fmsub_pd(ymm8, ymm15, ymm0); //B11[0-3][0] * alpha -= B10[0-3][0] ymm9 = _mm256_fmsub_pd(ymm9, ymm15, ymm1); //B11[4-7][0] * alpha -= B10[4-7][0] ymm10 = _mm256_fmsub_pd(ymm10, ymm15, ymm2); //B11[0-3][1] * alpha -= B10[0-3][1] ymm12 = _mm256_fmsub_pd(ymm12, ymm15, ymm4); //B11[0-3][2] * alpha -= B10[0-3][2] ymm13 = _mm256_fmsub_pd(ymm13, ymm15, ymm5); //B11[4-7][2] * alpha -= B10[4-7][2] ymm14 = _mm256_fmsub_pd(ymm14, ymm15, ymm6); //B11[0-3][3] * alpha -= B10[0-3][3] ///implement TRSM/// ///read 4x4 block of A11/// //2nd col a11 += 1; ymm1 = _mm256_broadcast_sd((double const *)(a11+ cs_a * 0)); //A11[0][1] //3rd col a11 += 1; ymm3 = _mm256_broadcast_sd((double const *)(a11+ cs_a * 0)); //A11[0][2] ymm4 = _mm256_broadcast_sd((double const *)(a11+ cs_a * 1)); //A11[1][2] //4th col a11 += 1; ymm2 = _mm256_broadcast_sd((double const *)(a11+ cs_a * 0)); //A11[0][3] ymm5 = _mm256_broadcast_sd((double const *)(a11+ cs_a * 1)); //A11[1][3] ymm6 = _mm256_broadcast_sd((double const *)(a11+ cs_a * 2)); //A11[2][3] //(Row1): FMA operations ymm9 = _mm256_fnmadd_pd(ymm1, ymm8, ymm9); //B11[0-3][1] -= B11[0-3][0] * A11[0][1] ymm10 = _mm256_fnmadd_pd(ymm3, ymm8, ymm10); //B11[0-3][2] -= B11[0-3][0] * A11[0][2] ymm13 = _mm256_fnmadd_pd(ymm1, ymm12, ymm13); //B11[4-7][1] -= B11[4-7][0] * A11[0][1] ymm14 = _mm256_fnmadd_pd(ymm3, ymm12, ymm14); //B11[4-7][2] -= B11[4-7][0] * A11[0][2] //(Row2)FMA operations ymm10 = _mm256_fnmadd_pd(ymm4, ymm9, ymm10); //B11[0-3][2] -= B11[0-3][1] * A11[1][2] ymm14 = _mm256_fnmadd_pd(ymm4, ymm13, ymm14); //B11[4-7][2] -= B11[4-7][1] * A11[1][2] _mm256_storeu_pd((double *)b11, ymm8); //store(B11[0-3][0]) _mm256_storeu_pd((double *)(b11 + D_NR), ymm12); //store(B11[4-7][0]) _mm256_storeu_pd((double *)(b11 + cs_b), ymm9); //store(B11[0-3][1]) _mm256_storeu_pd((double *)(b11 + cs_b + D_NR), ymm13); //store(B11[4-7][1]) _mm256_storeu_pd((double *)(b11 + cs_b_offset[0]), ymm10); //store(B11[0-3][2]) _mm256_storeu_pd((double *)(b11 + cs_b_offset[0] + D_NR), ymm14);//store(B11[4-7][2]) } else if(2 == n_remainder) { ///GEMM implementation begins/// for(k = 0; k < k_iter; k++) ///loop for number of GEMM operations { ptr_a01_dup = a01; //broadcast 1st row of A01 ymm8 = _mm256_broadcast_sd((double const *)(a01 + 0)); //A01[0][0] ymm9 = _mm256_broadcast_sd((double const *)(a01 + 1)); //A01[0][1] a01 += cs_a; //move to next row of A //load 8x2 block of B10 ymm12 = _mm256_loadu_pd((double const *)b10); //B10[0][0] B10[1][0] B10[2][0] B10[3][0] ymm13 = _mm256_loadu_pd((double const *)(b10 + D_NR)); //B10[4][0] B10[5][0] B10[6][0] B10[7][0] ymm14 = _mm256_loadu_pd((double const *)(b10 + cs_b)); //B10[0][1] B10[1][1] B10[2][1] B10[3][1] ymm15 = _mm256_loadu_pd((double const *)(b10 + cs_b + D_NR));//B10[4][1] B10[5][1] B10[6][1] B10[7][1] ymm0 = _mm256_fmadd_pd(ymm8, ymm12, ymm0); //ymm0 += (B10[0][0]*A01[0][0] B10[1][0]*A01[0][0] B10[2][0]*A01[0][0] B10[3][0]*A01[0][0]) ymm1 = _mm256_fmadd_pd(ymm9, ymm12, ymm1); //ymm1 += (B10[0][0]*A01[0][1] B10[1][0]*A01[0][1] B10[2][0]*A01[0][1] B10[3][0]*A01[0][1]) ymm4 = _mm256_fmadd_pd(ymm8, ymm13, ymm4); //ymm4 += (B10[4][0]*A01[0][0] B10[5][0]*A01[0][0] B10[6][0]*A01[0][0] B10[7][0]*A01[0][0]) ymm5 = _mm256_fmadd_pd(ymm9, ymm13, ymm5); //ymm5 += (B10[4][0]*A01[0][1] B10[5][0]*A01[0][1] B10[6][0]*A01[0][1] B10[7][0]*A01[0][1]) //broadcast 2nd row of A01 ymm8 = _mm256_broadcast_sd((double const *)(a01 + 0)); //A01[1][0] ymm9 = _mm256_broadcast_sd((double const *)(a01 + 1)); //A01[1][1] a01 += cs_a; //move to next row of A ymm0 = _mm256_fmadd_pd(ymm8, ymm14, ymm0); //ymm0 += (B10[0][1]*A01[0][0] B10[1][1]*A01[0][0] B10[2][1]*A01[0][0] B10[3][1]*A01[0][0]) ymm1 = _mm256_fmadd_pd(ymm9, ymm14, ymm1); //ymm1 += (B10[0][1]*A01[0][1] B10[1][1]*A01[0][1] B10[2][1]*A01[0][1] B10[3][1]*A01[0][1]) ymm4 = _mm256_fmadd_pd(ymm8, ymm15, ymm4); //ymm4 += (B10[4][1]*A01[0][0] B10[5][1]*A01[0][0] B10[6][1]*A01[0][0] B10[7][1]*A01[0][0]) ymm5 = _mm256_fmadd_pd(ymm9, ymm15, ymm5); //ymm5 += (B10[4][1]*A01[0][1] B10[5][1]*A01[0][1] B10[6][1]*A01[0][1] B10[7][1]*A01[0][1]) //broadcast 3rd row of A01 ymm8 = _mm256_broadcast_sd((double const *)(a01 + 0)); //A01[2][0] ymm9 = _mm256_broadcast_sd((double const *)(a01 + 1)); //A01[2][1] a01 += cs_a; //move to next row of A //load next 8x2 block of B10 ymm12 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0])); //(B10[0][2] B10[1][2] B10[2][2] B10[3][2]) ymm13 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + D_NR)); //(B10[4][2] B10[5][2] B10[6][2] B10[7][2]) ymm14 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + cs_b)); //(B10[0][3] B10[1][3] B10[2][3] B10[3][3]) ymm15 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + cs_b + D_NR)); //(B10[4][3] B10[5][3] B10[6][3] B10[7][3]) ymm0 = _mm256_fmadd_pd(ymm8, ymm12, ymm0); //ymm0 += (B10[0][2]*A01[0][0] B10[1][2]*A01[0][0] B10[2][2]*A01[0][0] B10[3][2]*A01[0][0]) ymm1 = _mm256_fmadd_pd(ymm9, ymm12, ymm1); //ymm1 += (B10[0][2]*A01[0][1] B10[1][2]*A01[0][1] B10[2][2]*A01[0][1] B10[3][2]*A01[0][1]) ymm4 = _mm256_fmadd_pd(ymm8, ymm13, ymm4); //ymm4 += (B10[4][2]*A01[0][0] B10[5][2]*A01[0][0] B10[6][2]*A01[0][0] B10[7][2]*A01[0][0]) ymm5 = _mm256_fmadd_pd(ymm9, ymm13, ymm5); //ymm5 += (B10[4][2]*A01[0][1] B10[5][2]*A01[0][1] B10[6][2]*A01[0][1] B10[7][2]*A01[0][1]) //broadcast 4th row of A01 ymm8 = _mm256_broadcast_sd((double const *)(a01 + 0)); //A01[3][0] ymm9 = _mm256_broadcast_sd((double const *)(a01 + 1)); //A01[3][1] a01 += cs_a; //move to next row of A ymm0 = _mm256_fmadd_pd(ymm8, ymm14, ymm0); //ymm0 += (B10[0][3]*A01[0][0] B10[1][3]*A01[0][0] B10[2][3]*A01[0][0] B10[3][3]*A01[0][0]) ymm1 = _mm256_fmadd_pd(ymm9, ymm14, ymm1); //ymm1 += (B10[0][3]*A01[0][1] B10[1][3]*A01[0][1] B10[2][3]*A01[0][1] B10[3][3]*A01[0][1]) ymm4 = _mm256_fmadd_pd(ymm8, ymm15, ymm4); //ymm4 += (B10[4][3]*A01[0][0] B10[5][3]*A01[0][0] B10[6][3]*A01[0][0] B10[7][3]*A01[0][0]) ymm5 = _mm256_fmadd_pd(ymm9, ymm15, ymm5); //ymm5 += (B10[4][3]*A01[0][1] B10[5][3]*A01[0][1] B10[6][3]*A01[0][1] B10[7][3]*A01[0][1]) b10 += D_NR * cs_b; //pointer math to find next block of B for GEMM a01 = ptr_a01_dup + (D_NR * cs_a); //pointer math to find next block of A for GEMM } ///GEMM code ends/// ymm15 = _mm256_broadcast_sd((double const *)&AlphaVal); ymm8 = _mm256_loadu_pd((double const *)b11); ymm12 = _mm256_loadu_pd((double const *)(b11 + D_NR)); ymm9 = _mm256_loadu_pd((double const *)(b11 + cs_b)); ymm13 = _mm256_loadu_pd((double const *)(b11 + cs_b + D_NR)); ymm8 = _mm256_fmsub_pd(ymm8, ymm15, ymm0); //B11[0-3][0] * alpha -= B10[0-3][0] ymm9 = _mm256_fmsub_pd(ymm9, ymm15, ymm1); //B11[4-7][0] * alpha -= B10[4-7][0] ymm12 = _mm256_fmsub_pd(ymm12, ymm15, ymm4); //B11[0-3][2] * alpha -= B10[0-3][2] ymm13 = _mm256_fmsub_pd(ymm13, ymm15, ymm5); //B11[4-7][2] * alpha -= B10[4-7][2] ///implement TRSM/// ///read 4x4 block of A11/// //2nd col a11 += 1; ymm1 = _mm256_broadcast_sd((double const *)(a11+ cs_a * 0)); //A11[0][1] //(Row1): FMA operations ymm9 = _mm256_fnmadd_pd(ymm1, ymm8, ymm9); //B11[0-3][1] -= B11[0-3][0] * A11[0][1] ymm13 = _mm256_fnmadd_pd(ymm1, ymm12, ymm13); //B11[4-7][1] -= B11[4-7][0] * A11[0][1] _mm256_storeu_pd((double *)b11, ymm8); //store(B11[0-3][0]) _mm256_storeu_pd((double *)(b11 + D_NR), ymm12); //store(B11[4-7][0]) _mm256_storeu_pd((double *)(b11 + cs_b), ymm9); //store(B11[0-3][1]) _mm256_storeu_pd((double *)(b11 + cs_b + D_NR), ymm13); //store(B11[4-7][1]) } else if(1 == n_remainder) { ///GEMM implementation begins/// for(k = 0; k < k_iter; k++) ///loop for number of GEMM operations { ptr_a01_dup = a01; //broadcast 1st row of A01 ymm8 = _mm256_broadcast_sd((double const *)(a01 + 0)); //A01[0][0] a01 += cs_a; //move to next row of A //load 8x2 block of B10 ymm12 = _mm256_loadu_pd((double const *)b10); //B10[0][0] B10[1][0] B10[2][0] B10[3][0] ymm13 = _mm256_loadu_pd((double const *)(b10 + D_NR)); //B10[4][0] B10[5][0] B10[6][0] B10[7][0] ymm14 = _mm256_loadu_pd((double const *)(b10 + cs_b)); //B10[0][1] B10[1][1] B10[2][1] B10[3][1] ymm15 = _mm256_loadu_pd((double const *)(b10 + cs_b + D_NR));//B10[4][1] B10[5][1] B10[6][1] B10[7][1] ymm0 = _mm256_fmadd_pd(ymm8, ymm12, ymm0); //ymm0 += (B10[0][0]*A01[0][0] B10[1][0]*A01[0][0] B10[2][0]*A01[0][0] B10[3][0]*A01[0][0]) ymm4 = _mm256_fmadd_pd(ymm8, ymm13, ymm4); //ymm4 += (B10[4][0]*A01[0][0] B10[5][0]*A01[0][0] B10[6][0]*A01[0][0] B10[7][0]*A01[0][0]) //broadcast 2nd row of A01 ymm8 = _mm256_broadcast_sd((double const *)(a01 + 0)); //A01[1][0] a01 += cs_a; //move to next row of A ymm0 = _mm256_fmadd_pd(ymm8, ymm14, ymm0); //ymm0 += (B10[0][1]*A01[0][0] B10[1][1]*A01[0][0] B10[2][1]*A01[0][0] B10[3][1]*A01[0][0]) ymm4 = _mm256_fmadd_pd(ymm8, ymm15, ymm4); //ymm4 += (B10[4][1]*A01[0][0] B10[5][1]*A01[0][0] B10[6][1]*A01[0][0] B10[7][1]*A01[0][0]) //broadcast 3rd row of A01 ymm8 = _mm256_broadcast_sd((double const *)(a01 + 0)); //A01[2][0] a01 += cs_a; //move to next row of A //load next 8x2 block of B10 ymm12 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0])); //(B10[0][2] B10[1][2] B10[2][2] B10[3][2]) ymm13 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + D_NR)); //(B10[4][2] B10[5][2] B10[6][2] B10[7][2]) ymm14 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + cs_b)); //(B10[0][3] B10[1][3] B10[2][3] B10[3][3]) ymm15 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + cs_b + D_NR)); //(B10[4][3] B10[5][3] B10[6][3] B10[7][3]) ymm0 = _mm256_fmadd_pd(ymm8, ymm12, ymm0); //ymm0 += (B10[0][2]*A01[0][0] B10[1][2]*A01[0][0] B10[2][2]*A01[0][0] B10[3][2]*A01[0][0]) ymm4 = _mm256_fmadd_pd(ymm8, ymm13, ymm4); //ymm4 += (B10[4][2]*A01[0][0] B10[5][2]*A01[0][0] B10[6][2]*A01[0][0] B10[7][2]*A01[0][0]) //broadcast 4th row of A01 ymm8 = _mm256_broadcast_sd((double const *)(a01 + 0)); //A01[3][0] a01 += cs_a; //move to next row of A ymm0 = _mm256_fmadd_pd(ymm8, ymm14, ymm0); //ymm0 += (B10[0][3]*A01[0][0] B10[1][3]*A01[0][0] B10[2][3]*A01[0][0] B10[3][3]*A01[0][0]) ymm4 = _mm256_fmadd_pd(ymm8, ymm15, ymm4); //ymm4 += (B10[4][3]*A01[0][0] B10[5][3]*A01[0][0] B10[6][3]*A01[0][0] B10[7][3]*A01[0][0]) b10 += D_NR * cs_b; //pointer math to find next block of B for GEMM a01 = ptr_a01_dup + (D_NR * cs_a); //pointer math to find next block of A for GEMM } ///GEMM code ends/// ymm15 = _mm256_broadcast_sd((double const *)&AlphaVal); ymm8 = _mm256_loadu_pd((double const *)b11); //B11[0-3][0] ymm12 = _mm256_loadu_pd((double const *)(b11 + D_NR)); //B11[4-7][0] ymm8 = _mm256_fmsub_pd(ymm8, ymm15, ymm0); //B11[0-3][0] * alpha -= B10[0-3][0] ymm12 = _mm256_fmsub_pd(ymm12, ymm15, ymm4); //B11[0-3][2] * alpha -= B10[0-3][2] _mm256_storeu_pd((double *)b11, ymm8); //store(B11[0-3][0]) _mm256_storeu_pd((double *)(b11 + D_NR), ymm12); //store(B11[4-7][0]) } } } if((m & 4)) ///implementation for remainder rows(when m_remainder is greater than 4) { for(j = 0; (j+D_NR-1) D_BLIS_SMALL_MATRIX_THRES_TRSM_XALB_ROME) ||(m > D_BLIS_SMALL_MATRIX_THRES_TRSM_XALB_ROME && n > D_BLIS_SMALL_MATRIX_THRES_TRSM_XALB_ROME_COL_PANEL_N) ) return BLIS_NOT_YET_IMPLEMENTED; #else if(bli_max(m,n) > D_BLIS_SMALL_MATRIX_THRES_TRSM_NAPLES) { return BLIS_NOT_YET_IMPLEMENTED; } #endif dim_t i, j, k; //loop variablse dim_t k_iter; //determines the number of GEMM operations to be done dim_t cs_b_offset[2]; //pre-calculated strides double ones = 1.0; double AlphaVal = *(double *)AlphaObj->buffer; //value of Alpha double* restrict L = a->buffer; //pointer to matrix A double* restrict B = b->buffer; //pointer to matrix B double *a01, *a11, *b10, *b11; //pointers for GEMM and TRSM blocks double *ptr_a01_dup; cs_b_offset[0] = cs_b << 1; //cs_b_offset[0] = cs_b * 2; cs_b_offset[1] = cs_b_offset[0] + cs_b;//cs_b_offset[1] = cs_b * 3; //ymm scratch reginsters __m256d ymm0, ymm1, ymm2, ymm3; __m256d ymm4, ymm5, ymm6, ymm7; __m256d ymm8, ymm9, ymm10, ymm11; __m256d ymm12, ymm13, ymm14, ymm15; __m256d ymm16; for(i = (m-D_MR); (i+1) > 0; i -= D_MR) //loop along 'M' direction { for(j = (n-D_NR); (j+1) > 0; j -= D_NR) //loop along 'N' direction { a01 = L + j*cs_a +(j+D_NR); //pointer to block of A to be used in GEMM a11 = L + j*cs_a + j; //pointer to block of A to be used for TRSM b10 = B + i + (j+D_NR)*cs_b; //pointer to block of B to be used in GEMM b11 = B + (i) + (j)*cs_b; //pointer to block of B to be used for TRSM k_iter = (n-j-D_NR) / D_NR; //number of GEMM operations to be done(in blocks of 4x4) ymm0 = _mm256_setzero_pd(); ymm1 = _mm256_setzero_pd(); ymm2 = _mm256_setzero_pd(); ymm3 = _mm256_setzero_pd(); ymm4 = _mm256_setzero_pd(); ymm5 = _mm256_setzero_pd(); ymm6 = _mm256_setzero_pd(); ymm7 = _mm256_setzero_pd(); ///GEMM implementation starts/// for(k = 0; k < k_iter; k++) //loop for number of GEMM operations { ptr_a01_dup = a01; //broadcast 1st row of A01 ymm8 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 0)); //A01[0][0] ymm9 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 1)); //A01[0][1] ymm10 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 2)); //A01[0][2] ymm11 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 3)); //A01[0][3] a01 += 1; //move to next row //load 8x2 block of B10 ymm12 = _mm256_loadu_pd((double const *)b10); //B10[0][0] B10[1][0] B10[2][0] B10[3][0] ymm13 = _mm256_loadu_pd((double const *)(b10 + D_NR)); //B10[4][0] B10[5][0] B10[6][0] B10[7][0] ymm14 = _mm256_loadu_pd((double const *)(b10 + cs_b)); //B10[0][1] B10[1][1] B10[2][1] B10[3][1] ymm15 = _mm256_loadu_pd((double const *)(b10 + cs_b + D_NR)); //B10[4][1] B10[5][1] B10[6][1] B10[7][1] ymm0 = _mm256_fmadd_pd(ymm8, ymm12, ymm0); //ymm0 += (B10[0][0]*A01[0][0] B10[1][0]*A01[0][0] B10[2][0]*A01[0][0] B10[3][0]*A01[0][0]) ymm1 = _mm256_fmadd_pd(ymm9, ymm12, ymm1); //ymm1 += (B10[0][0]*A01[0][1] B10[1][0]*A01[0][1] B10[2][0]*A01[0][1] B10[3][0]*A01[0][1]) ymm2 = _mm256_fmadd_pd(ymm10, ymm12, ymm2); //ymm2 += (B10[0][0]*A01[0][2] B10[1][0]*A01[0][2] B10[2][0]*A01[0][2] B10[3][0]*A01[0][2]) ymm3 = _mm256_fmadd_pd(ymm11, ymm12, ymm3); //ymm3 += (B10[0][0]*A01[0][3] B10[1][0]*A01[0][3] B10[2][0]*A01[0][3] B10[3][0]*A01[0][3]) ymm4 = _mm256_fmadd_pd(ymm8, ymm13, ymm4); //ymm4 += (B10[4][0]*A01[0][0] B10[5][0]*A01[0][0] B10[6][0]*A01[0][0] B10[7][0]*A01[0][0]) ymm5 = _mm256_fmadd_pd(ymm9, ymm13, ymm5); //ymm5 += (B10[4][0]*A01[0][1] B10[5][0]*A01[0][1] B10[6][0]*A01[0][1] B10[7][0]*A01[0][1]) ymm6 = _mm256_fmadd_pd(ymm10, ymm13, ymm6); //ymm6 += (B10[4][0]*A01[0][2] B10[5][0]*A01[0][2] B10[6][0]*A01[0][2] B10[7][0]*A01[0][2]) ymm7 = _mm256_fmadd_pd(ymm11, ymm13, ymm7); //ymm7 += (B10[4][0]*A01[0][3] B10[5][0]*A01[0][3] B10[6][0]*A01[0][3] B10[7][0]*A01[0][3]) //broadcast 2nd row of A01 ymm8 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 0)); //A01[1][0] ymm9 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 1)); //A01[1][1] ymm10 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 2)); //A01[1][2] ymm11 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 3)); //A01[1][3] a01 += 1; //move to next row of A ymm0 = _mm256_fmadd_pd(ymm8, ymm14, ymm0); //ymm0 += (B10[0][1]*A01[0][0] B10[1][1]*A01[0][0] B10[2][1]*A01[0][0] B10[3][1]*A01[0][0]) ymm1 = _mm256_fmadd_pd(ymm9, ymm14, ymm1); //ymm1 += (B10[0][1]*A01[0][1] B10[1][1]*A01[0][1] B10[2][1]*A01[0][1] B10[3][1]*A01[0][1]) ymm2 = _mm256_fmadd_pd(ymm10, ymm14, ymm2); //ymm2 += (B10[0][1]*A01[0][2] B10[1][1]*A01[0][2] B10[2][1]*A01[0][2] B10[3][1]*A01[0][2]) ymm3 = _mm256_fmadd_pd(ymm11, ymm14, ymm3); //ymm3 += (B10[0][1]*A01[0][3] B10[1][1]*A01[0][3] B10[2][1]*A01[0][3] B10[3][1]*A01[0][3]) ymm4 = _mm256_fmadd_pd(ymm8, ymm15, ymm4); //ymm4 += (B10[4][1]*A01[0][0] B10[5][1]*A01[0][0] B10[6][1]*A01[0][0] B10[7][1]*A01[0][0]) ymm5 = _mm256_fmadd_pd(ymm9, ymm15, ymm5); //ymm5 += (B10[4][1]*A01[0][1] B10[5][1]*A01[0][1] B10[6][1]*A01[0][1] B10[7][1]*A01[0][1]) ymm6 = _mm256_fmadd_pd(ymm10, ymm15, ymm6); //ymm6 += (B10[4][1]*A01[0][2] B10[5][1]*A01[0][2] B10[6][1]*A01[0][2] B10[7][1]*A01[0][2]) ymm7 = _mm256_fmadd_pd(ymm11, ymm15, ymm7); //ymm7 += (B10[4][1]*A01[0][3] B10[5][1]*A01[0][3] B10[6][1]*A01[0][3] B10[7][1]*A01[0][3]) //broadcast 3rd row of A01 ymm8 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 0)); //A01[2][0] ymm9 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 1)); //A01[2][1] ymm10 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 2)); //A01[2][2] ymm11 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 3)); //A01[2][3] a01 += 1; //move to next row of A01 //load next 8x2 block of B10 ymm12 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0])); //(B10[0][2] B10[1][2] B10[2][2] B10[3][2]) ymm13 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + D_NR)); //(B10[4][2] B10[5][2] B10[6][2] B10[7][2]) ymm14 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + cs_b)); //(B10[0][3] B10[1][3] B10[2][3] B10[3][3]) ymm15 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + cs_b + D_NR)); //(B10[4][3] B10[5][3] B10[6][3] B10[7][3]) ymm0 = _mm256_fmadd_pd(ymm8, ymm12, ymm0); //ymm0 += (B10[0][2]*A01[0][0] B10[1][2]*A01[0][0] B10[2][2]*A01[0][0] B10[3][2]*A01[0][0]) ymm1 = _mm256_fmadd_pd(ymm9, ymm12, ymm1); //ymm1 += (B10[0][2]*A01[0][1] B10[1][2]*A01[0][1] B10[2][2]*A01[0][1] B10[3][2]*A01[0][1]) ymm2 = _mm256_fmadd_pd(ymm10, ymm12, ymm2); //ymm2 += (B10[0][2]*A01[0][2] B10[1][2]*A01[0][2] B10[2][2]*A01[0][2] B10[3][2]*A01[0][2]) ymm3 = _mm256_fmadd_pd(ymm11, ymm12, ymm3); //ymm3 += (B10[0][2]*A01[0][3] B10[1][2]*A01[0][3] B10[2][2]*A01[0][3] B10[3][2]*A01[0][3]) ymm4 = _mm256_fmadd_pd(ymm8, ymm13, ymm4); //ymm4 += (B10[4][2]*A01[0][0] B10[5][2]*A01[0][0] B10[6][2]*A01[0][0] B10[7][2]*A01[0][0]) ymm5 = _mm256_fmadd_pd(ymm9, ymm13, ymm5); //ymm5 += (B10[4][2]*A01[0][1] B10[5][2]*A01[0][1] B10[6][2]*A01[0][1] B10[7][2]*A01[0][1]) ymm6 = _mm256_fmadd_pd(ymm10, ymm13, ymm6); //ymm6 += (B10[4][2]*A01[0][2] B10[5][2]*A01[0][2] B10[6][2]*A01[0][2] B10[7][2]*A01[0][2]) ymm7 = _mm256_fmadd_pd(ymm11, ymm13, ymm7); //ymm7 += (B10[4][2]*A01[0][3] B10[5][2]*A01[0][3] B10[6][2]*A01[0][3] B10[7][2]*A01[0][3]) //broadcast 4th row of A01 ymm8 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 0)); //A01[3][0] ymm9 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 1)); //A01[3][1] ymm10 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 2)); //A01[3][2] ymm11 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 3)); //A01[3][3] a01 += 1; //move to next row of A01 ymm0 = _mm256_fmadd_pd(ymm8, ymm14, ymm0); //ymm0 += (B10[0][3]*A01[0][0] B10[1][3]*A01[0][0] B10[2][3]*A01[0][0] B10[3][3]*A01[0][0]) ymm1 = _mm256_fmadd_pd(ymm9, ymm14, ymm1); //ymm1 += (B10[0][3]*A01[0][1] B10[1][3]*A01[0][1] B10[2][3]*A01[0][1] B10[3][3]*A01[0][1]) ymm2 = _mm256_fmadd_pd(ymm10, ymm14, ymm2); //ymm2 += (B10[0][3]*A01[0][2] B10[1][3]*A01[0][2] B10[2][3]*A01[0][2] B10[3][3]*A01[0][2]) ymm3 = _mm256_fmadd_pd(ymm11, ymm14, ymm3); //ymm3 += (B10[0][3]*A01[0][3] B10[1][3]*A01[0][3] B10[2][3]*A01[0][3] B10[3][3]*A01[0][3]) ymm4 = _mm256_fmadd_pd(ymm8, ymm15, ymm4); //ymm4 += (B10[4][3]*A01[0][0] B10[5][3]*A01[0][0] B10[6][3]*A01[0][0] B10[7][3]*A01[0][0]) ymm5 = _mm256_fmadd_pd(ymm9, ymm15, ymm5); //ymm5 += (B10[4][3]*A01[0][1] B10[5][3]*A01[0][1] B10[6][3]*A01[0][1] B10[7][3]*A01[0][1]) ymm6 = _mm256_fmadd_pd(ymm10, ymm15, ymm6); //ymm6 += (B10[4][3]*A01[0][2] B10[5][3]*A01[0][2] B10[6][3]*A01[0][2] B10[7][3]*A01[0][2]) ymm7 = _mm256_fmadd_pd(ymm11, ymm15, ymm7); //ymm7 += (B10[4][3]*A01[0][3] B10[5][3]*A01[0][3] B10[6][3]*A01[0][3] B10[7][3]*A01[0][3]) b10 += D_NR * cs_b; //pointer math to find next block of B for GEMM a01 = ptr_a01_dup + D_NR; //pointer math to find next block of A for GEMM } ///GEMM code ends/// ymm16 = _mm256_broadcast_sd((double const *)&AlphaVal); //load 8x4 block of B11 ymm8 = _mm256_loadu_pd((double const *)b11); //B11[0][0] B11[1][0] B11[2][0] B11[3][0] ymm12 = _mm256_loadu_pd((double const *)(b11 + D_NR)); //B11[4][0] B11[5][0] B11[6][0] B11[7][0] ymm9 = _mm256_loadu_pd((double const *)(b11 + cs_b)); //B11[0][1] B11[1][1] B11[2][1] B11[3][1] ymm13 = _mm256_loadu_pd((double const *)(b11 + cs_b + D_NR)); //B11[4][1] B11[5][1] B11[6][1] B11[7][1] ymm10 = _mm256_loadu_pd((double const *)(b11 + cs_b_offset[0])); //B11[0][2] B11[1][2] B11[2][2] B11[3][2] ymm14 = _mm256_loadu_pd((double const *)(b11 + cs_b_offset[0] + D_NR)); //B11[4][2] B11[5][2] B11[6][2] B11[7][2] ymm11 = _mm256_loadu_pd((double const *)(b11 + cs_b_offset[1])); //B11[0][3] B11[1][3] B11[2][3] B11[3][3] ymm15 = _mm256_loadu_pd((double const *)(b11 + cs_b_offset[1] + D_NR)); //B11[4][3] B11[5][3] B11[6][3] B11[7][3] ymm8 = _mm256_fmsub_pd(ymm8, ymm16, ymm0); //B11[0-3][0] * alpha -= ymm0 ymm9 = _mm256_fmsub_pd(ymm9, ymm16, ymm1); //B11[4-7][0] * alpha-= ymm1 ymm10 = _mm256_fmsub_pd(ymm10, ymm16, ymm2); //B11[0-3][1] * alpha-= ymm2 ymm11 = _mm256_fmsub_pd(ymm11, ymm16, ymm3); //B11[4-7][1] * alpha -= ymm3 ymm12 = _mm256_fmsub_pd(ymm12, ymm16, ymm4); //B11[0-3][2] * alpha -= ymm4 ymm13 = _mm256_fmsub_pd(ymm13, ymm16, ymm5); //B11[4-7][2] * alpha -= ymm5 ymm14 = _mm256_fmsub_pd(ymm14, ymm16, ymm6); //B11[0-3][3] * alpha -= ymm6 ymm15 = _mm256_fmsub_pd(ymm15, ymm16, ymm7); //B11[4-7][3] * alpha -= ymm7 ///implement TRSM/// ///read 4x4 block of A11/// ymm7 = _mm256_broadcast_sd((double const *)(&ones)); //1st col ymm0 = _mm256_broadcast_sd((double const *)(a11+0)); //A11[0][0] //2nd col a11 += 1; ymm1 = _mm256_broadcast_sd((double const *)(a11+ cs_a * 0)); //A11[0][1] ymm2 = _mm256_broadcast_sd((double const *)(a11+ cs_a * 1)); //A11[1][1] //3rd col a11 += 1; ymm3 = _mm256_broadcast_sd((double const *)(a11+ cs_a * 0)); //A11[0][2] ymm4 = _mm256_broadcast_sd((double const *)(a11+ cs_a * 1)); //A11[1][2] ymm5 = _mm256_broadcast_sd((double const *)(a11+ cs_a * 2)); //A11[2][2] //4th col a11 += 1; ymm6 = _mm256_broadcast_sd((double const *)(a11+ cs_a * 3)); //A11[3][3] //compute reciprocals of L(i,i) and broadcast in registers ymm0 = _mm256_unpacklo_pd(ymm0, ymm2); //A11[0][0] A11[1][1] A11[0][0] A11[1][1] ymm2 = _mm256_unpacklo_pd(ymm5, ymm6); //A11[2][2] A11[3][3] A11[1][1] A11[3][3] ymm0 = _mm256_blend_pd(ymm0, ymm2, 0x0C); //A11[0][0] A11[1][1] A11[2][2] A11[3][3] ymm7 = _mm256_div_pd(ymm7, ymm0); //(1/A11[0][0] 1/A11[1][1] 1/A11[2][2] 1/A11[3][3]) ymm2 = _mm256_broadcast_sd((double const *)(a11+ cs_a * 0)); //A11[0][3] ymm5 = _mm256_broadcast_sd((double const *)(a11+ cs_a * 1)); //A11[1][3] ymm6 = _mm256_broadcast_sd((double const *)(a11+ cs_a * 2)); //A11[2][3] //extract a33 ymm0 = _mm256_permute_pd(ymm7, 0x0C); //(1/A11[0][0] 1/A11[0][0] 1/A11[3][3] 1/A11[3][3] 1/A11[3][3]) ymm0 = _mm256_permute2f128_pd(ymm0, ymm0, 0x11);//(1/A11[3][3] 1/A11[3][3] 1/A11[3][3] 1/A11[3][3]) ymm11 = _mm256_mul_pd(ymm11, ymm0); ymm15 = _mm256_mul_pd(ymm15, ymm0); //extract a22 ymm0 = _mm256_permute_pd(ymm7, 0x00); //(1/A11[0][0] 1/A11[0][0] 1/A11[2][2] 1/A11[2][2]) ymm0 = _mm256_permute2f128_pd(ymm0, ymm0, 0x11);//(1/A11[2][2] 1/A11[2][2] 1/A11[2][2] 1/A11[2][2]) //(row 3):FMA operations ymm10 = _mm256_fnmadd_pd(ymm11, ymm6, ymm10); ymm9 = _mm256_fnmadd_pd(ymm11, ymm5, ymm9); ymm8 = _mm256_fnmadd_pd(ymm11, ymm2, ymm8); ymm14 = _mm256_fnmadd_pd(ymm15, ymm6, ymm14); ymm13 = _mm256_fnmadd_pd(ymm15, ymm5, ymm13); ymm12 = _mm256_fnmadd_pd(ymm15, ymm2, ymm12); ymm10 = _mm256_mul_pd(ymm10, ymm0); ymm14 = _mm256_mul_pd(ymm14, ymm0); //extract a11 ymm0 = _mm256_permute_pd(ymm7, 0x03); //(1/A11[1][1] 1/A11[1][1] 1/A11[2][2] 1/A11[2][2]) ymm0 = _mm256_permute2f128_pd(ymm0, ymm0, 0x00);//(1/A11[1][1] 1/A11[1][1] 1/A11[1][1] 1/A11[1][1]) //(Row 2): FMA operations ymm9 = _mm256_fnmadd_pd(ymm10, ymm4, ymm9); ymm8 = _mm256_fnmadd_pd(ymm10, ymm3, ymm8); ymm13 = _mm256_fnmadd_pd(ymm14, ymm4, ymm13); ymm12 = _mm256_fnmadd_pd(ymm14, ymm3, ymm12); ymm9 = _mm256_mul_pd(ymm9, ymm0); ymm13 = _mm256_mul_pd(ymm13, ymm0); //extract a00 ymm0 = _mm256_permute_pd(ymm7, 0x00); //(1/A11[0][0] 1/A11[0][0] 1/A11[2][2] 1/A11[2][2]) ymm0 = _mm256_permute2f128_pd(ymm0, ymm0, 0x00); //(1/A11[0][0] 1/A11[0][0] 1/A11[0][0] 1/A11[0][0]) //(Row 1): FMA operations ymm8 = _mm256_fnmadd_pd(ymm9, ymm1, ymm8); ymm12 = _mm256_fnmadd_pd(ymm13, ymm1, ymm12); ymm8 = _mm256_mul_pd(ymm8, ymm0); //B11[0-3][0] /= A11[0][0] ymm12 = _mm256_mul_pd(ymm12, ymm0); //B11[4-7][0] /= A11[0][0] _mm256_storeu_pd((double *)b11, ymm8); //store(B11[0-3][0]) _mm256_storeu_pd((double *)(b11 + D_NR), ymm12); //store(B11[4-7][0]) _mm256_storeu_pd((double *)(b11 + cs_b), ymm9); //store(B11[0-3][1]) _mm256_storeu_pd((double *)(b11 + cs_b + D_NR), ymm13); //store(B11[4-7][1]) _mm256_storeu_pd((double *)(b11 + cs_b_offset[0]), ymm10); //store(B11[0-3][2]) _mm256_storeu_pd((double *)(b11 + cs_b_offset[0] + D_NR), ymm14); //store(B11[4-7][2]) _mm256_storeu_pd((double *)(b11 + cs_b_offset[0] + cs_b), ymm11); //store(B11[0-3][3]) _mm256_storeu_pd((double *)(b11 + cs_b_offset[0] + cs_b + D_NR), ymm15);//store(B11[4-7][3]) } if(n_remainder) //implementation for remainder columns(when n is not multiple of D_NR) { a01 = L + j*cs_a + (j+D_NR); //pointer to block of A to be used for GEMM a11 = L + j*cs_a + j; //pointer to block of A to be used for TRSM b10 = B + i + (j + D_NR)*cs_b; //pointer to block of B to be used for GEMM b11 = B + i + j*cs_b; //pointer to block of B to be used for TRSM k_iter = (n-j-D_NR) / D_NR; //number of GEMM operations to be performed(in blocks of 4x4) ///load 4x4 block of b11 ymm0 = _mm256_setzero_pd(); ymm1 = _mm256_setzero_pd(); ymm2 = _mm256_setzero_pd(); ymm3 = _mm256_setzero_pd(); ymm4 = _mm256_setzero_pd(); ymm5 = _mm256_setzero_pd(); ymm6 = _mm256_setzero_pd(); ymm7 = _mm256_setzero_pd(); //subtract the calculated GEMM block from current TRSM block //load 8x4 block of B11 if(3 == n_remainder) { ///GEMM implementation begins/// for(k = 0; k < k_iter; k++) ///loop for number of GEMM operations { ptr_a01_dup = a01; //broadcast 1st row of A01 ymm9 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 1)); //A01[0][1] ymm10 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 2)); //A01[0][2] ymm11 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 3)); //A01[0][3] a01 += 1; //move to next row of A //load 8x2 block of B10 ymm12 = _mm256_loadu_pd((double const *)b10); //B10[0][0] B10[1][0] B10[2][0] B10[3][0] ymm13 = _mm256_loadu_pd((double const *)(b10 + D_NR)); //B10[4][0] B10[5][0] B10[6][0] B10[7][0] ymm14 = _mm256_loadu_pd((double const *)(b10 + cs_b)); //B10[0][1] B10[1][1] B10[2][1] B10[3][1] ymm15 = _mm256_loadu_pd((double const *)(b10 + cs_b + D_NR));//B10[4][1] B10[5][1] B10[6][1] B10[7][1] ymm1 = _mm256_fmadd_pd(ymm9, ymm12, ymm1); //ymm1 += (B10[0][0]*A01[0][1] B10[1][0]*A01[0][1] B10[2][0]*A01[0][1] B10[3][0]*A01[0][1]) ymm2 = _mm256_fmadd_pd(ymm10, ymm12, ymm2); //ymm2 += (B10[0][0]*A01[0][2] B10[1][0]*A01[0][2] B10[2][0]*A01[0][2] B10[3][0]*A01[0][2]) ymm3 = _mm256_fmadd_pd(ymm11, ymm12, ymm3); //ymm3 += (B10[0][0]*A01[0][3] B10[1][0]*A01[0][3] B10[2][0]*A01[0][3] B10[3][0]*A01[0][3]) ymm5 = _mm256_fmadd_pd(ymm9, ymm13, ymm5); //ymm5 += (B10[4][0]*A01[0][1] B10[5][0]*A01[0][1] B10[6][0]*A01[0][1] B10[7][0]*A01[0][1]) ymm6 = _mm256_fmadd_pd(ymm10, ymm13, ymm6); //ymm6 += (B10[4][0]*A01[0][2] B10[5][0]*A01[0][2] B10[6][0]*A01[0][2] B10[7][0]*A01[0][2]) ymm7 = _mm256_fmadd_pd(ymm11, ymm13, ymm7); //ymm7 += (B10[4][0]*A01[0][3] B10[5][0]*A01[0][3] B10[6][0]*A01[0][3] B10[7][0]*A01[0][3]) //broadcast 2nd row of A01 ymm9 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 1)); //A01[1][1] ymm10 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 2)); //A01[1][2] ymm11 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 3)); //A01[1][3] a01 += 1; //move to next row of A ymm1 = _mm256_fmadd_pd(ymm9, ymm14, ymm1); //ymm1 += (B10[0][1]*A01[0][1] B10[1][1]*A01[0][1] B10[2][1]*A01[0][1] B10[3][1]*A01[0][1]) ymm2 = _mm256_fmadd_pd(ymm10, ymm14, ymm2); //ymm2 += (B10[0][1]*A01[0][2] B10[1][1]*A01[0][2] B10[2][1]*A01[0][2] B10[3][1]*A01[0][2]) ymm3 = _mm256_fmadd_pd(ymm11, ymm14, ymm3); //ymm3 += (B10[0][1]*A01[0][3] B10[1][1]*A01[0][3] B10[2][1]*A01[0][3] B10[3][1]*A01[0][3]) ymm5 = _mm256_fmadd_pd(ymm9, ymm15, ymm5); //ymm5 += (B10[4][1]*A01[0][1] B10[5][1]*A01[0][1] B10[6][1]*A01[0][1] B10[7][1]*A01[0][1]) ymm6 = _mm256_fmadd_pd(ymm10, ymm15, ymm6); //ymm6 += (B10[4][1]*A01[0][2] B10[5][1]*A01[0][2] B10[6][1]*A01[0][2] B10[7][1]*A01[0][2]) ymm7 = _mm256_fmadd_pd(ymm11, ymm15, ymm7); //ymm7 += (B10[4][1]*A01[0][3] B10[5][1]*A01[0][3] B10[6][1]*A01[0][3] B10[7][1]*A01[0][3]) //broadcast 3rd row of A01 ymm9 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 1)); //A01[2][1] ymm10 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 2)); //A01[2][2] ymm11 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 3)); //A01[2][3] a01 += 1; //move to next row of A //load next 8x2 block of B10 ymm12 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0])); //(B10[0][2] B10[1][2] B10[2][2] B10[3][2]) ymm13 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + D_NR)); //(B10[4][2] B10[5][2] B10[6][2] B10[7][2]) ymm14 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[1] )); //(B10[0][3] B10[1][3] B10[2][3] B10[3][3]) ymm15 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[1] + D_NR)); //(B10[4][3] B10[5][3] B10[6][3] B10[7][3]) ymm1 = _mm256_fmadd_pd(ymm9, ymm12, ymm1); //ymm1 += (B10[0][2]*A01[0][1] B10[1][2]*A01[0][1] B10[2][2]*A01[0][1] B10[3][2]*A01[0][1]) ymm2 = _mm256_fmadd_pd(ymm10, ymm12, ymm2); //ymm2 += (B10[0][2]*A01[0][2] B10[1][2]*A01[0][2] B10[2][2]*A01[0][2] B10[3][2]*A01[0][2]) ymm3 = _mm256_fmadd_pd(ymm11, ymm12, ymm3); //ymm3 += (B10[0][2]*A01[0][3] B10[1][2]*A01[0][3] B10[2][2]*A01[0][3] B10[3][2]*A01[0][3]) ymm5 = _mm256_fmadd_pd(ymm9, ymm13, ymm5); //ymm5 += (B10[4][2]*A01[0][1] B10[5][2]*A01[0][1] B10[6][2]*A01[0][1] B10[7][2]*A01[0][1]) ymm6 = _mm256_fmadd_pd(ymm10, ymm13, ymm6); //ymm6 += (B10[4][2]*A01[0][2] B10[5][2]*A01[0][2] B10[6][2]*A01[0][2] B10[7][2]*A01[0][2]) ymm7 = _mm256_fmadd_pd(ymm11, ymm13, ymm7); //ymm7 += (B10[4][2]*A01[0][3] B10[5][2]*A01[0][3] B10[6][2]*A01[0][3] B10[7][2]*A01[0][3]) //broadcast 4th row of A01 ymm9 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 1)); //A01[3][1] ymm10 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 2)); //A01[3][2] ymm11 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 3)); //A01[3][3] a01 += 1; //move to next row of A ymm1 = _mm256_fmadd_pd(ymm9, ymm14, ymm1); //ymm1 += (B10[0][3]*A01[0][1] B10[1][3]*A01[0][1] B10[2][3]*A01[0][1] B10[3][3]*A01[0][1]) ymm2 = _mm256_fmadd_pd(ymm10, ymm14, ymm2); //ymm2 += (B10[0][3]*A01[0][2] B10[1][3]*A01[0][2] B10[2][3]*A01[0][2] B10[3][3]*A01[0][2]) ymm3 = _mm256_fmadd_pd(ymm11, ymm14, ymm3); //ymm3 += (B10[0][3]*A01[0][3] B10[1][3]*A01[0][3] B10[2][3]*A01[0][3] B10[3][3]*A01[0][3]) ymm5 = _mm256_fmadd_pd(ymm9, ymm15, ymm5); //ymm5 += (B10[4][3]*A01[0][1] B10[5][3]*A01[0][1] B10[6][3]*A01[0][1] B10[7][3]*A01[0][1]) ymm6 = _mm256_fmadd_pd(ymm10, ymm15, ymm6); //ymm6 += (B10[4][3]*A01[0][2] B10[5][3]*A01[0][2] B10[6][3]*A01[0][2] B10[7][3]*A01[0][2]) ymm7 = _mm256_fmadd_pd(ymm11, ymm15, ymm7); //ymm7 += (B10[4][3]*A01[0][3] B10[5][3]*A01[0][3] B10[6][3]*A01[0][3] B10[7][3]*A01[0][3]) b10 += D_NR * cs_b; //pointer math to find next block of B for GEMM a01 = ptr_a01_dup + D_NR; //pointer math to find next block of A for GEMM } ///GEMM code ends/// ymm8 = _mm256_broadcast_sd((double const *)&AlphaVal); ymm9 = _mm256_loadu_pd((double const *)(b11+cs_b)); //B11[0-3][0] ymm13 = _mm256_loadu_pd((double const *)(b11 + cs_b + D_NR)); //B11[4-7][0] ymm10 = _mm256_loadu_pd((double const *)(b11 + cs_b*2)); //B11[0-3][1] ymm14 = _mm256_loadu_pd((double const *)(b11 + cs_b*2 + D_NR)); //B11[4-7][1] ymm11 = _mm256_loadu_pd((double const *)(b11 + cs_b_offset[1])); //B11[0-3][2] ymm15 = _mm256_loadu_pd((double const *)(b11 + cs_b_offset[1] + D_NR)); //B11[4-7][2] ymm9 = _mm256_fmsub_pd(ymm9, ymm8, ymm1); //B11[4-7][0] * alpha -= B10[4-7][0] ymm10 = _mm256_fmsub_pd(ymm10, ymm8, ymm2); //B11[0-3][1] * alpha -= B10[0-3][1] ymm11 = _mm256_fmsub_pd(ymm11, ymm8, ymm3); //B11[4-7][1] * alpha -= B10[4-7][1] ymm13 = _mm256_fmsub_pd(ymm13, ymm8, ymm5); //B11[4-7][2] * alpha -= B10[4-7][2] ymm14 = _mm256_fmsub_pd(ymm14, ymm8, ymm6); //B11[0-3][3] * alpha -= B10[0-3][3] ymm15 = _mm256_fmsub_pd(ymm15, ymm8, ymm7); //B11[4-7][3] * alpha -= B10[4-7][3] ///implement TRSM/// ///read 4x4 block of A11/// ymm7 = _mm256_broadcast_sd((double const *)(&ones)); //1st col ymm0 = _mm256_broadcast_sd((double const *)(&ones)); //A11[0][0] //2nd col a11 += 1; ymm2 = _mm256_broadcast_sd((double const *)(a11+ cs_a * 1)); //A11[1][1] //3rd col a11 += 1; ymm4 = _mm256_broadcast_sd((double const *)(a11+ cs_a * 1)); //A11[1][2] ymm5 = _mm256_broadcast_sd((double const *)(a11+ cs_a * 2)); //A11[2][2] //4th col a11 += 1; ymm6 = _mm256_broadcast_sd((double const *)(a11+ cs_a * 3)); //A11[3][3] //compute reciprocals of L(i,i) and broadcast in registers ymm0 = _mm256_unpacklo_pd(ymm0, ymm2); //A11[0][0] A11[1][1] A11[0][0] A11[1][1] ymm2 = _mm256_unpacklo_pd(ymm5, ymm6); //A11[2][2] A11[3][3] A11[1][1] A11[3][3] ymm0 = _mm256_blend_pd(ymm0, ymm2, 0x0C); //A11[0][0] A11[1][1] A11[2][2] A11[3][3] ymm7 = _mm256_div_pd(ymm7, ymm0); //(1/A11[0][0] 1/A11[1][1] 1/A11[2][2] 1/A11[3][3]) ymm5 = _mm256_broadcast_sd((double const *)(a11+ cs_a * 1)); //A11[1][3] ymm6 = _mm256_broadcast_sd((double const *)(a11+ cs_a * 2)); //A11[2][3] //extract a33 ymm0 = _mm256_permute_pd(ymm7, 0x0C); //(1/A11[0][0] 1/A11[0][0] 1/A11[3][3] 1/A11[3][3] 1/A11[3][3]) ymm0 = _mm256_permute2f128_pd(ymm0, ymm0, 0x11);//(1/A11[3][3] 1/A11[3][3] 1/A11[3][3] 1/A11[3][3]) ymm11 = _mm256_mul_pd(ymm11, ymm0); ymm15 = _mm256_mul_pd(ymm15, ymm0); //extract a22 ymm0 = _mm256_permute_pd(ymm7, 0x00); //(1/A11[0][0] 1/A11[0][0] 1/A11[2][2] 1/A11[2][2]) ymm0 = _mm256_permute2f128_pd(ymm0, ymm0, 0x11);//(1/A11[2][2] 1/A11[2][2] 1/A11[2][2] 1/A11[2][2]) //(row 3):FMA operations ymm10 = _mm256_fnmadd_pd(ymm11, ymm6, ymm10); ymm9 = _mm256_fnmadd_pd(ymm11, ymm5, ymm9); ymm14 = _mm256_fnmadd_pd(ymm15, ymm6, ymm14); ymm13 = _mm256_fnmadd_pd(ymm15, ymm5, ymm13); ymm10 = _mm256_mul_pd(ymm10, ymm0); ymm14 = _mm256_mul_pd(ymm14, ymm0); //extract a11 ymm0 = _mm256_permute_pd(ymm7, 0x03); //(1/A11[1][1] 1/A11[1][1] 1/A11[2][2] 1/A11[2][2]) ymm0 = _mm256_permute2f128_pd(ymm0, ymm0, 0x00);//(1/A11[1][1] 1/A11[1][1] 1/A11[1][1] 1/A11[1][1]) //(Row 2): FMA operations ymm9 = _mm256_fnmadd_pd(ymm10, ymm4, ymm9); ymm13 = _mm256_fnmadd_pd(ymm14, ymm4, ymm13); ymm9 = _mm256_mul_pd(ymm9, ymm0); ymm13 = _mm256_mul_pd(ymm13, ymm0); _mm256_storeu_pd((double *)(b11 + cs_b), ymm9); //store(B11[0-3][1]) _mm256_storeu_pd((double *)(b11 + cs_b + D_NR), ymm13); //store(B11[4-7][1]) _mm256_storeu_pd((double *)(b11 + cs_b_offset[0]), ymm10); //store(B11[0-3][2]) _mm256_storeu_pd((double *)(b11 + cs_b_offset[0] + D_NR), ymm14);//store(B11[4-7][2]) _mm256_storeu_pd((double *)(b11 + cs_b_offset[1]), ymm11); //store(B11[0-3][0]) _mm256_storeu_pd((double *)(b11 + cs_b_offset[1] + D_NR), ymm15); //store(B11[4-7][0]) } else if(2 == n_remainder) { ///GEMM implementation begins/// for(k = 0; k < k_iter; k++) ///loop for number of GEMM operations { ptr_a01_dup = a01; //broadcast 1st row of A01 ymm10 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 2)); //A01[0][2] ymm11 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 3)); //A01[0][3] a01 += 1; //move to next row of A //load 8x2 block of B10 ymm12 = _mm256_loadu_pd((double const *)b10); //B10[0][0] B10[1][0] B10[2][0] B10[3][0] ymm13 = _mm256_loadu_pd((double const *)(b10 + D_NR)); //B10[4][0] B10[5][0] B10[6][0] B10[7][0] ymm14 = _mm256_loadu_pd((double const *)(b10 + cs_b)); //B10[0][1] B10[1][1] B10[2][1] B10[3][1] ymm15 = _mm256_loadu_pd((double const *)(b10 + cs_b + D_NR));//B10[4][1] B10[5][1] B10[6][1] B10[7][1] ymm2 = _mm256_fmadd_pd(ymm10, ymm12, ymm2); //ymm2 += (B10[0][0]*A01[0][2] B10[1][0]*A01[0][2] B10[2][0]*A01[0][2] B10[3][0]*A01[0][2]) ymm3 = _mm256_fmadd_pd(ymm11, ymm12, ymm3); //ymm3 += (B10[0][0]*A01[0][3] B10[1][0]*A01[0][3] B10[2][0]*A01[0][3] B10[3][0]*A01[0][3]) ymm6 = _mm256_fmadd_pd(ymm10, ymm13, ymm6); //ymm6 += (B10[4][0]*A01[0][2] B10[5][0]*A01[0][2] B10[6][0]*A01[0][2] B10[7][0]*A01[0][2]) ymm7 = _mm256_fmadd_pd(ymm11, ymm13, ymm7); //ymm7 += (B10[4][0]*A01[0][3] B10[5][0]*A01[0][3] B10[6][0]*A01[0][3] B10[7][0]*A01[0][3]) //broadcast 2nd row of A01 ymm10 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 2)); //A01[1][2] ymm11 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 3)); //A01[1][3] a01 += 1; //move to next row of A ymm2 = _mm256_fmadd_pd(ymm10, ymm14, ymm2); //ymm2 += (B10[0][1]*A01[0][2] B10[1][1]*A01[0][2] B10[2][1]*A01[0][2] B10[3][1]*A01[0][2]) ymm3 = _mm256_fmadd_pd(ymm11, ymm14, ymm3); //ymm3 += (B10[0][1]*A01[0][3] B10[1][1]*A01[0][3] B10[2][1]*A01[0][3] B10[3][1]*A01[0][3]) ymm6 = _mm256_fmadd_pd(ymm10, ymm15, ymm6); //ymm6 += (B10[4][1]*A01[0][2] B10[5][1]*A01[0][2] B10[6][1]*A01[0][2] B10[7][1]*A01[0][2]) ymm7 = _mm256_fmadd_pd(ymm11, ymm15, ymm7); //ymm7 += (B10[4][1]*A01[0][3] B10[5][1]*A01[0][3] B10[6][1]*A01[0][3] B10[7][1]*A01[0][3]) //broadcast 3rd row of A01 ymm10 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 2)); //A01[2][2] ymm11 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 3)); //A01[2][3] a01 += 1; //move to next row of A //load next 8x2 block of B10 ymm12 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0])); //(B10[0][2] B10[1][2] B10[2][2] B10[3][2]) ymm13 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + D_NR)); //(B10[4][2] B10[5][2] B10[6][2] B10[7][2]) ymm14 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + cs_b)); //(B10[0][3] B10[1][3] B10[2][3] B10[3][3]) ymm15 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + cs_b + D_NR)); //(B10[4][3] B10[5][3] B10[6][3] B10[7][3]) ymm2 = _mm256_fmadd_pd(ymm10, ymm12, ymm2); //ymm2 += (B10[0][2]*A01[0][2] B10[1][2]*A01[0][2] B10[2][2]*A01[0][2] B10[3][2]*A01[0][2]) ymm3 = _mm256_fmadd_pd(ymm11, ymm12, ymm3); //ymm3 += (B10[0][2]*A01[0][3] B10[1][2]*A01[0][3] B10[2][2]*A01[0][3] B10[3][2]*A01[0][3]) ymm6 = _mm256_fmadd_pd(ymm10, ymm13, ymm6); //ymm6 += (B10[4][2]*A01[0][2] B10[5][2]*A01[0][2] B10[6][2]*A01[0][2] B10[7][2]*A01[0][2]) ymm7 = _mm256_fmadd_pd(ymm11, ymm13, ymm7); //ymm7 += (B10[4][2]*A01[0][3] B10[5][2]*A01[0][3] B10[6][2]*A01[0][3] B10[7][2]*A01[0][3]) //broadcast 4th row of A01 ymm10 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 2)); //A01[3][2] ymm11 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 3)); //A01[3][3] a01 += 1; //move to next row of A ymm2 = _mm256_fmadd_pd(ymm10, ymm14, ymm2); //ymm2 += (B10[0][3]*A01[0][2] B10[1][3]*A01[0][2] B10[2][3]*A01[0][2] B10[3][3]*A01[0][2]) ymm3 = _mm256_fmadd_pd(ymm11, ymm14, ymm3); //ymm3 += (B10[0][3]*A01[0][3] B10[1][3]*A01[0][3] B10[2][3]*A01[0][3] B10[3][3]*A01[0][3]) ymm6 = _mm256_fmadd_pd(ymm10, ymm15, ymm6); //ymm6 += (B10[4][3]*A01[0][2] B10[5][3]*A01[0][2] B10[6][3]*A01[0][2] B10[7][3]*A01[0][2]) ymm7 = _mm256_fmadd_pd(ymm11, ymm15, ymm7); //ymm7 += (B10[4][3]*A01[0][3] B10[5][3]*A01[0][3] B10[6][3]*A01[0][3] B10[7][3]*A01[0][3]) b10 += D_NR * cs_b; //pointer math to find next block of B for GEMM a01 = ptr_a01_dup + D_NR; //pointer math to find next block of A for GEMM } ///GEMM code ends/// ymm8 = _mm256_broadcast_sd((double const *)&AlphaVal); ymm10 = _mm256_loadu_pd((double const *)(b11 + cs_b_offset[0])); //B11[0-3][0] ymm14 = _mm256_loadu_pd((double const *)(b11 + cs_b_offset[0] + D_NR)); //B11[4-7][0] ymm11 = _mm256_loadu_pd((double const *)(b11 + cs_b_offset[1])); //B11[0-3][1] ymm15 = _mm256_loadu_pd((double const *)(b11 + cs_b_offset[1] + D_NR)); //B11[4-7][1] ymm10 = _mm256_fmsub_pd(ymm10, ymm8, ymm2); //B11[0-3][1] * alpha -= B10[0-3][1] ymm11 = _mm256_fmsub_pd(ymm11, ymm8, ymm3); //B11[4-7][1] * alpha -= B10[4-7][1] ymm14 = _mm256_fmsub_pd(ymm14, ymm8, ymm6); //B11[0-3][3] * alpha -= B10[0-3][3] ymm15 = _mm256_fmsub_pd(ymm15, ymm8, ymm7); //B11[4-7][3] * alpha -= B10[4-7][3] ///implement TRSM/// ///read 4x4 block of A11/// ymm7 = _mm256_broadcast_sd((double const *)(&ones)); //3rd col a11 += 2; ymm5 = _mm256_broadcast_sd((double const *)(a11+ cs_a * 2)); //A11[2][2] //4th col a11 += 1; ymm6 = _mm256_broadcast_sd((double const *)(a11+ cs_a * 3)); //A11[3][3] //compute reciprocals of L(i,i) and broadcast in registers ymm2 = _mm256_unpacklo_pd(ymm5, ymm6); //A11[2][2] A11[3][3] A11[1][1] A11[3][3] ymm0 = _mm256_blend_pd(ymm7, ymm2, 0x0C); //A11[0][0] A11[1][1] A11[2][2] A11[3][3] ymm7 = _mm256_div_pd(ymm7, ymm0); //(1/A11[0][0] 1/A11[1][1] 1/A11[2][2] 1/A11[3][3]) ymm6 = _mm256_broadcast_sd((double const *)(a11+ cs_a * 2)); //A11[2][3] //extract a33 ymm0 = _mm256_permute_pd(ymm7, 0x0C); //(1/A11[0][0] 1/A11[0][0] 1/A11[3][3] 1/A11[3][3] 1/A11[3][3]) ymm0 = _mm256_permute2f128_pd(ymm0, ymm0, 0x11);//(1/A11[3][3] 1/A11[3][3] 1/A11[3][3] 1/A11[3][3]) ymm11 = _mm256_mul_pd(ymm11, ymm0); ymm15 = _mm256_mul_pd(ymm15, ymm0); //extract a22 ymm0 = _mm256_permute_pd(ymm7, 0x00); //(1/A11[0][0] 1/A11[0][0] 1/A11[2][2] 1/A11[2][2]) ymm0 = _mm256_permute2f128_pd(ymm0, ymm0, 0x11);//(1/A11[2][2] 1/A11[2][2] 1/A11[2][2] 1/A11[2][2]) //(row 3):FMA operations ymm10 = _mm256_fnmadd_pd(ymm11, ymm6, ymm10); ymm14 = _mm256_fnmadd_pd(ymm15, ymm6, ymm14); ymm10 = _mm256_mul_pd(ymm10, ymm0); ymm14 = _mm256_mul_pd(ymm14, ymm0); _mm256_storeu_pd((double *)(b11 + cs_b_offset[0]), ymm10); //store(B11[0-3][1]) _mm256_storeu_pd((double *)(b11 + cs_b_offset[0] + D_NR), ymm14); //store(B11[4-7][1]) _mm256_storeu_pd((double *)(b11 + cs_b_offset[1]), ymm11); //store(B11[0-3][0]) _mm256_storeu_pd((double *)(b11 + cs_b_offset[1] + D_NR), ymm15); //store(B11[4-7][0]) } else if(1 == n_remainder) { ///GEMM implementation begins/// for(k = 0; k < k_iter; k++) ///loop for number of GEMM operations { ptr_a01_dup = a01; //broadcast 1st row of A01 ymm11 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 3)); //A01[0][3] a01 += 1; //move to next row of A //load 8x2 block of B10 ymm12 = _mm256_loadu_pd((double const *)b10); //B10[0][0] B10[1][0] B10[2][0] B10[3][0] ymm13 = _mm256_loadu_pd((double const *)(b10 + D_NR)); //B10[4][0] B10[5][0] B10[6][0] B10[7][0] ymm14 = _mm256_loadu_pd((double const *)(b10 + cs_b)); //B10[0][1] B10[1][1] B10[2][1] B10[3][1] ymm15 = _mm256_loadu_pd((double const *)(b10 + cs_b + D_NR));//B10[4][1] B10[5][1] B10[6][1] B10[7][1] ymm3 = _mm256_fmadd_pd(ymm11, ymm12, ymm3); //ymm3 += (B10[0][0]*A01[0][3] B10[1][0]*A01[0][3] B10[2][0]*A01[0][3] B10[3][0]*A01[0][3]) ymm7 = _mm256_fmadd_pd(ymm11, ymm13, ymm7); //ymm7 += (B10[4][0]*A01[0][3] B10[5][0]*A01[0][3] B10[6][0]*A01[0][3] B10[7][0]*A01[0][3]) //broadcast 2nd row of A01 ymm11 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 3)); //A01[1][3] a01 += 1; //move to next row of A ymm3 = _mm256_fmadd_pd(ymm11, ymm14, ymm3); //ymm3 += (B10[0][1]*A01[0][3] B10[1][1]*A01[0][3] B10[2][1]*A01[0][3] B10[3][1]*A01[0][3]) ymm7 = _mm256_fmadd_pd(ymm11, ymm15, ymm7); //ymm7 += (B10[4][1]*A01[0][3] B10[5][1]*A01[0][3] B10[6][1]*A01[0][3] B10[7][1]*A01[0][3]) //broadcast 3rd row of A01 ymm11 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 3)); //A01[2][3] a01 += 1; //move to next row of A //load next 8x2 block of B10 ymm12 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0])); //(B10[0][2] B10[1][2] B10[2][2] B10[3][2]) ymm13 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + D_NR)); //(B10[4][2] B10[5][2] B10[6][2] B10[7][2]) ymm14 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + cs_b)); //(B10[0][3] B10[1][3] B10[2][3] B10[3][3]) ymm15 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + cs_b + D_NR)); //(B10[4][3] B10[5][3] B10[6][3] B10[7][3]) ymm3 = _mm256_fmadd_pd(ymm11, ymm12, ymm3); //ymm3 += (B10[0][2]*A01[0][3] B10[1][2]*A01[0][3] B10[2][2]*A01[0][3] B10[3][2]*A01[0][3]) ymm7 = _mm256_fmadd_pd(ymm11, ymm13, ymm7); //ymm7 += (B10[4][2]*A01[0][3] B10[5][2]*A01[0][3] B10[6][2]*A01[0][3] B10[7][2]*A01[0][3]) //broadcast 4th row of A01 ymm11 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 3)); //A01[3][3] a01 += 1; //move to next row of A ymm3 = _mm256_fmadd_pd(ymm11, ymm14, ymm3); //ymm3 += (B10[0][3]*A01[0][3] B10[1][3]*A01[0][3] B10[2][3]*A01[0][3] B10[3][3]*A01[0][3]) ymm7 = _mm256_fmadd_pd(ymm11, ymm15, ymm7); //ymm7 += (B10[4][3]*A01[0][3] B10[5][3]*A01[0][3] B10[6][3]*A01[0][3] B10[7][3]*A01[0][3]) b10 += D_NR * cs_b; //pointer math to find next block of B for GEMM a01 = ptr_a01_dup + D_NR; //pointer math to find next block of A for GEMM } ///GEMM code ends/// ymm8 = _mm256_broadcast_sd((double const *)&AlphaVal); ymm11 = _mm256_loadu_pd((double const *)(b11+cs_b_offset[1])); //B11[0-3][0] ymm15 = _mm256_loadu_pd((double const *)(b11 + cs_b_offset[1] +D_NR)); //B11[4-7][0] ymm11 = _mm256_fmsub_pd(ymm11, ymm8, ymm3); //B11[4-7][1] * alpha -= B10[4-7][1] ymm15 = _mm256_fmsub_pd(ymm15, ymm8, ymm7); //B11[4-7][3] * alpha -= B10[4-7][3] ///implement TRSM/// ///read 4x4 block of A11/// ymm7 = _mm256_broadcast_sd((double const *)(&ones)); //4th col a11 += 3; ymm6 = _mm256_broadcast_sd((double const *)(a11+ cs_a * 3)); //A11[3][3] //compute reciprocals of L(i,i) and broadcast in registers ymm7 = _mm256_div_pd(ymm7, ymm6); //(1/A11[0][0] 1/A11[1][1] 1/A11[2][2] 1/A11[3][3]) ymm11 = _mm256_mul_pd(ymm11, ymm7); ymm15 = _mm256_mul_pd(ymm15, ymm7); _mm256_storeu_pd((double *)(b11+ cs_b_offset[1]), ymm11); //store(B11[0-3][0]) _mm256_storeu_pd((double *)(b11 + cs_b_offset[1] + D_NR), ymm15); //store(B11[4-7][0]) } } } if(i<0) i += D_NR; if((m & 4)) ///implementation for remainder rows(when m_remainder is greater than 4) { for(j = (n-D_NR); (j+1) > 0; j -=D_NR) //loop along n direction { a01 = L + j*cs_a + (j+D_NR); //pointer to block of A to be used for GEMM a11 = L + j*cs_a + j; //pointer to block of A to be used for TRSM b10 = B + i + (j+D_NR)*cs_b; //pointer to block of B to be used for GEMM b11 = B + i + j*cs_b; //pointer to block of B to be used for TRSM k_iter = (n-j-D_NR) / D_NR; //number of times GEMM operations to be performed(in blocks of 4x4) ///GEMM for previous blocks /// ///load 4x4 block of b11 ymm0 = _mm256_loadu_pd((double const *)b11); //B11[0][0] B11[1][0] B11[2][0] B11[3][0] ymm1 = _mm256_loadu_pd((double const *)(b11 + cs_b)); //B11[0][1] B11[1][1] B11[2][1] B11[3][1] ymm2 = _mm256_loadu_pd((double const *)(b11 + cs_b_offset[0])); //B11[0][2] B11[1][2] B11[2][2] B11[3][2] ymm3 = _mm256_loadu_pd((double const *)(b11 + cs_b_offset[1])); //B11[0][3] B11[1][3] B11[2][3] B11[3][3] ymm4 = _mm256_setzero_pd(); ymm5 = _mm256_setzero_pd(); ymm6 = _mm256_setzero_pd(); ymm7 = _mm256_setzero_pd(); ///GEMM implementation starts/// for(k = 0; k < k_iter; k++) //loop for number of GEMM operations { ptr_a01_dup = a01; //load 4x4 bblock of b10 ymm8 = _mm256_loadu_pd((double const *)b10); //B10[0][0] B10[1][0] B10[2][0] B10[3][0] ymm9 = _mm256_loadu_pd((double const *)(b10 + cs_b)); //B10[0][1] B10[1][1] B10[2][1] B10[3][1] ymm10 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0])); //B10[0][2] B10[1][2] B10[2][2] B10[3][2] ymm11 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[1])); //B10[0][3] B10[1][3] B10[2][3] B10[3][3] //broadcast 1st row of A01 ymm12 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 0)); //A01[0][0] ymm13 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 1)); //A01[0][1] ymm14 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 2)); //A01[0][2] ymm15 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 3)); //A01[0][3] a01 += 1; //move to next row of A ymm4 = _mm256_fmadd_pd(ymm12, ymm8, ymm4); //ymm4 += (B10[0][0]*A01[0][0] B10[1][0]*A01[0][0] B10[2][0]*A01[0][0] B10[3][0]*A01[0][0]) ymm5 = _mm256_fmadd_pd(ymm13, ymm8, ymm5); //ymm5 += (B10[0][0]*A01[0][1] B10[1][0]*A01[0][1] B10[2][0]*A01[0][1] B10[3][0]*A01[0][1]) ymm6 = _mm256_fmadd_pd(ymm14, ymm8, ymm6); //ymm6 += (B10[0][0]*A01[0][2] B10[1][0]*A01[0][2] B10[2][0]*A01[0][2] B10[3][0]*A01[0][2]) ymm7 = _mm256_fmadd_pd(ymm15, ymm8, ymm7); //ymm7 += (B10[0][0]*A01[0][3] B10[1][0]*A01[0][3] B10[2][0]*A01[0][3] B10[3][0]*A01[0][3]) //broadcast 2nd row of A01 ymm12 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 0)); //A01[1][0] ymm13 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 1)); //A01[1][1] ymm14 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 2)); //A01[1][2] ymm15 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 3)); //A01[1][3] a01 += 1; //move to next row of A ymm4 = _mm256_fmadd_pd(ymm12, ymm9, ymm4); //ymm4 += (B10[0][1]*A01[1][0] B10[1][1]*A01[1][0] B10[2][1]*A01[1][0] B10[3][1]*A01[1][0]) ymm5 = _mm256_fmadd_pd(ymm13, ymm9, ymm5); //ymm5 += (B10[0][1]*A01[1][1] B10[1][1]*A01[1][1] B10[2][1]*A01[1][1] B10[3][1]*A01[1][1]) ymm6 = _mm256_fmadd_pd(ymm14, ymm9, ymm6); //ymm6 += (B10[0][1]*A01[1][2] B10[1][1]*A01[1][2] B10[2][1]*A01[1][2] B10[3][1]*A01[1][2]) ymm7 = _mm256_fmadd_pd(ymm15, ymm9, ymm7); //ymm7 += (B10[0][1]*A01[1][3] B10[1][1]*A01[1][3] B10[2][1]*A01[1][3] B10[3][1]*A01[1][3]) //braodcast 3rd row of A01 ymm12 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 0)); //A01[2][0] ymm13 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 1)); //A01[2][1] ymm14 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 2)); //A01[2][2] ymm15 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 3)); //A01[2][3] a01 += 1; //move to next row of A ymm4 = _mm256_fmadd_pd(ymm12, ymm10, ymm4); //ymm4 += (B10[0][2]*A01[2][0] B10[1][2]*A01[2][0] B10[2][2]*A01[2][0] B10[3][2]*A01[2][0]) ymm5 = _mm256_fmadd_pd(ymm13, ymm10, ymm5); //ymm5 += (B10[0][2]*A01[2][1] B10[1][2]*A01[2][1] B10[2][2]*A01[2][1] B10[3][2]*A01[2][1]) ymm6 = _mm256_fmadd_pd(ymm14, ymm10, ymm6); //ymm6 += (B10[0][2]*A01[2][2] B10[1][2]*A01[2][2] B10[2][2]*A01[2][2] B10[3][2]*A01[2][2]) ymm7 = _mm256_fmadd_pd(ymm15, ymm10, ymm7); //ymm7 += (B10[0][2]*A01[2][3] B10[1][2]*A01[2][3] B10[2][2]*A01[2][3] B10[3][2]*A01[2][3]) //broadcast 4th row of A01 ymm12 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 0)); //A01[3][0] ymm13 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 1)); //A01[3][1] ymm14 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 2)); //A01[3][2] ymm15 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 3)); //A01[3][3] a01 += 1; //move to next row of A ymm4 = _mm256_fmadd_pd(ymm12, ymm11, ymm4); //ymm4 += (B10[0][3]*A01[3][0] B10[1][3]*A01[3][0] B10[2][3]*A01[3][0] B10[3][3]*A01[3][0]) ymm5 = _mm256_fmadd_pd(ymm13, ymm11, ymm5); //ymm5 += (B10[0][3]*A01[3][1] B10[1][3]*A01[3][1] B10[2][3]*A01[3][1] B10[3][3]*A01[3][1]) ymm6 = _mm256_fmadd_pd(ymm14, ymm11, ymm6); //ymm6 += (B10[0][3]*A01[3][2] B10[1][3]*A01[3][2] B10[2][3]*A01[3][2] B10[3][3]*A01[3][2]) ymm7 = _mm256_fmadd_pd(ymm15, ymm11, ymm7); //ymm7 += (B10[0][3]*A01[3][3] B10[1][3]*A01[3][3] B10[2][3]*A01[3][3] B10[3][3]*A01[3][3]) b10 += D_NR * cs_b; //pointer math to find next block of B for GEMM a01 = ptr_a01_dup + D_NR; //pointer math to find next block of A for GEMM } ///GEMM code end/// ymm15 = _mm256_broadcast_sd((double const *)&AlphaVal); //register to store alpha ymm0 = _mm256_fmsub_pd(ymm0, ymm15, ymm4); //B11[x][0] -=ymm4 ymm1 = _mm256_fmsub_pd(ymm1, ymm15, ymm5); //B11[x][1] -= ymm5 ymm2 = _mm256_fmsub_pd(ymm2, ymm15, ymm6); //B11[x][2] -= ymm6 ymm3 = _mm256_fmsub_pd(ymm3, ymm15, ymm7); //B11[x][3] -= ymm7 ///implement TRSM/// ///read 4x4 block of A11/// //1st col ymm4 = _mm256_broadcast_sd((double const *)(a11+0)); //A11[0][0] ymm5 = _mm256_broadcast_sd((double const *)(a11+1)); //A11[0][0] ymm6 = _mm256_broadcast_sd((double const *)(a11+2)); //A11[0][0] ymm7 = _mm256_broadcast_sd((double const *)(a11+3)); //A11[0][0] //2nd col a11 += cs_a; ymm8 = _mm256_broadcast_sd((double const *)(a11+1)); //A11[0][1] ymm9 = _mm256_broadcast_sd((double const *)(a11+2)); //A11[1][1] ymm10 = _mm256_broadcast_sd((double const *)(a11+3)); //A11[1][1] //3rd col a11 += cs_a; ymm11 = _mm256_broadcast_sd((double const *)(a11+2)); //A11[0][2] ymm12 = _mm256_broadcast_sd((double const *)(a11+3)); //A11[1][2] //4th col a11 += cs_a; ymm13 = _mm256_broadcast_sd((double const *)(a11+3)); //A11[0][3] ymm14 = _mm256_broadcast_sd((double const *)&ones); //compute reciprocals of A(i,i) and broadcast in registers ymm4 = _mm256_unpacklo_pd(ymm4, ymm8); //A11[0][0] A11[1][1] A11[0][0] A11[1][1] ymm8 = _mm256_unpacklo_pd(ymm11, ymm13); //A11[2][2] A11[3][3] A11[2][2] A11[3][3] ymm15 = _mm256_blend_pd(ymm4, ymm8, 0x0C); //A11[0][0] A11[1][1] A11[2][2] A11[3][3] ymm14 = _mm256_div_pd(ymm14, ymm15); // 1/A11[0][0] 1/A11[1][1] 1/A11[2][2] 1/A11[3][3] //extract a33 ymm15 = _mm256_permute_pd(ymm14, 0x0C); //(1/A11[0][0] 1/A11[0][0] 1/A11[3][3] 1/A11[3][3]) ymm15 = _mm256_permute2f128_pd(ymm15, ymm15, 0x11); //(1/A11[3][3] 1/A11[3][3] 1/A11[3][3] 1/A11[3][3]) ymm3 = _mm256_mul_pd(ymm3, ymm15); //extract a22 ymm15 = _mm256_permute_pd(ymm14, 0x00); //(1/A11[0][0] 1/A11[0][0] 1/A11[2][2] 1/A11[2][2]) ymm15 = _mm256_permute2f128_pd(ymm15, ymm15, 0x11); //(1/A11[2][2] 1/A11[2][2] 1/A11[2][2] 1/A11[2][2]) //(Row 3): FMA operations ymm2 = _mm256_fnmadd_pd(ymm3, ymm12, ymm2); ymm1 = _mm256_fnmadd_pd(ymm3, ymm10, ymm1); ymm0 = _mm256_fnmadd_pd(ymm3, ymm7, ymm0); ymm2 = _mm256_mul_pd(ymm2, ymm15); //extract a11 ymm15 = _mm256_permute_pd(ymm14, 0x03); //(1/A11[1][1] 1/A11[1][1] 1/A11[2][2] 1/A11[2][2]) ymm15 = _mm256_permute2f128_pd(ymm15, ymm15, 0x00); //(1/A11[1][1] 1/A11[1][1] 1/A11[1][1] 1/A11[1][1]) //(ROW 2): FMA operations ymm1 = _mm256_fnmadd_pd(ymm2, ymm9, ymm1); ymm0 = _mm256_fnmadd_pd(ymm2, ymm6, ymm0); ymm1 = _mm256_mul_pd(ymm1, ymm15); //extract A00 ymm15 = _mm256_permute_pd(ymm14, 0x00); //(1/A11[0][0] 1/A11[0][0] 1/A11[2][2] 1/A11[2][2]) ymm15 = _mm256_permute2f128_pd(ymm15, ymm15, 0x00); //(1/A11[0][0] 1/A11[0][0] 1/A11[0][0] 1/A11[0][0]) //(Row 1):FMA operations ymm0 = _mm256_fnmadd_pd(ymm1, ymm5, ymm0); ymm0 = _mm256_mul_pd(ymm0, ymm15); _mm256_storeu_pd((double *)b11, ymm0); //store(B11[x][0]) _mm256_storeu_pd((double *)(b11 + cs_b), ymm1); //store(B11[x][1]) _mm256_storeu_pd((double *)(b11 + cs_b_offset[0]), ymm2); //(store(B11[x][2])) _mm256_storeu_pd((double *)(b11 + cs_b_offset[1]), ymm3); //store(B11[x][3]) } if(n_remainder) //implementation for remainder columns(when n is not a multiple of D_NR) { a01 = L + j*cs_a + (j+D_NR); //pointer to block of A to be used for GEMM a11 = L + j*cs_a + j; //pointwr to block of A to be used for TRSM b10 = B + i + (j+D_NR)*cs_b; //pointer to block of B to be used for GEMM b11 = B + i + j*cs_b; //pointer to block of B to be used for TRSM k_iter = (n-j-D_NR) / D_NR; //number of times GEMM operations to be performed(in blocks of 4x4) ymm4 = _mm256_setzero_pd(); ymm5 = _mm256_setzero_pd(); ymm6 = _mm256_setzero_pd(); ymm7 = _mm256_setzero_pd(); ///GEMM for previous blocks /// if(3 == n_remainder) { ///load 4x4 block of b11 ymm0 = _mm256_broadcast_sd((double const *)&ones); //B11[0][3] B11[1][3] B11[2][3] B11[3][3] ymm1 = _mm256_loadu_pd((double const *)b11+ cs_b); //B11[0][0] B11[1][0] B11[2][0] B11[3][0] ymm2 = _mm256_loadu_pd((double const *)(b11 + cs_b * 2)); //B11[0][1] B11[1][1] B11[2][1] B11[3][1] ymm3 = _mm256_loadu_pd((double const *)(b11 + cs_b * 3)); //B11[0][2] B11[1][2] B11[2][2] B11[3][2] ///GEMM processing stars/// for(k = 0; k < k_iter; k++) { ptr_a01_dup = a01; //load 4x4 bblock of b10 ymm8 = _mm256_loadu_pd((double const *)b10); //B10[0][0] B10[1][0] B10[2][0] B10[3][0] ymm9 = _mm256_loadu_pd((double const *)(b10 + cs_b)); //B10[0][1] B10[1][1] B10[2][1] B10[3][1] ymm10 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0])); //B10[0][2] B10[1][2] B10[2][2] B10[3][2] ymm11 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[1])); //B10[0][3] B10[1][3] B10[2][3] B10[3][3] //broadcast 1st row of A01 ymm13 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 1)); //A01[0][1] ymm14 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 2)); //A01[0][2] ymm15 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 3)); //A01[0][3] a01 += 1; //move to next row of A ymm5 = _mm256_fmadd_pd(ymm13, ymm8, ymm5); //ymm5 += (B10[0][0]*A01[0][1] B10[1][0]*A01[0][1] B10[2][0]*A01[0][1] B10[3][0]*A01[0][1]) ymm6 = _mm256_fmadd_pd(ymm14, ymm8, ymm6); //ymm6 += (B10[0][0]*A01[0][2] B10[1][0]*A01[0][2] B10[2][0]*A01[0][2] B10[3][0]*A01[0][2]) ymm7 = _mm256_fmadd_pd(ymm15, ymm8, ymm7); //ymm7 += (B10[0][0]*A01[0][3] B10[1][0]*A01[0][3] B10[2][0]*A01[0][3] B10[3][0]*A01[0][3]) //broadcast 2nd row of A01 ymm13 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 1)); //A01[1][1] ymm14 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 2)); //A01[1][2] ymm15 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 3)); //A01[1][3] a01 += 1; //move to next row of A ymm5 = _mm256_fmadd_pd(ymm13, ymm9, ymm5); //ymm5 += (B10[0][1]*A01[1][1] B10[1][1]*A01[1][1] B10[2][1]*A01[1][1] B10[3][1]*A01[1][1]) ymm6 = _mm256_fmadd_pd(ymm14, ymm9, ymm6); //ymm6 += (B10[0][1]*A01[1][2] B10[1][1]*A01[1][2] B10[2][1]*A01[1][2] B10[3][1]*A01[1][2]) ymm7 = _mm256_fmadd_pd(ymm15, ymm9, ymm7); //ymm7 += (B10[0][1]*A01[1][3] B10[1][1]*A01[1][3] B10[2][1]*A01[1][3] B10[3][1]*A01[1][3]) //braodcast 3rd row of A01 ymm13 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 1)); //A01[2][1] ymm14 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 2)); //A01[2][2] ymm15 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 3)); //A01[2][3] a01 += 1; //move to next row of A ymm5 = _mm256_fmadd_pd(ymm13, ymm10, ymm5); //ymm5 += (B10[0][2]*A01[2][1] B10[1][2]*A01[2][1] B10[2][2]*A01[2][1] B10[3][2]*A01[2][1]) ymm6 = _mm256_fmadd_pd(ymm14, ymm10, ymm6); //ymm6 += (B10[0][2]*A01[2][2] B10[1][2]*A01[2][2] B10[2][2]*A01[2][2] B10[3][2]*A01[2][2]) ymm7 = _mm256_fmadd_pd(ymm15, ymm10, ymm7); //ymm7 += (B10[0][2]*A01[2][3] B10[1][2]*A01[2][3] B10[2][2]*A01[2][3] B10[3][2]*A01[2][3]) //broadcast 4th row of A01 ymm13 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 1)); //A01[3][1] ymm14 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 2)); //A01[3][2] ymm15 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 3)); //A01[3][3] a01 += 1; //move to next row of A ymm5 = _mm256_fmadd_pd(ymm13, ymm11, ymm5); //ymm5 += (B10[0][3]*A01[3][1] B10[1][3]*A01[3][1] B10[2][3]*A01[3][1] B10[3][3]*A01[3][1]) ymm6 = _mm256_fmadd_pd(ymm14, ymm11, ymm6); //ymm6 += (B10[0][3]*A01[3][2] B10[1][3]*A01[3][2] B10[2][3]*A01[3][2] B10[3][3]*A01[3][2]) ymm7 = _mm256_fmadd_pd(ymm15, ymm11, ymm7); //ymm7 += (B10[0][3]*A01[3][3] B10[1][3]*A01[3][3] B10[2][3]*A01[3][3] B10[3][3]*A01[3][3]) b10 += D_NR * cs_b; //pointer math to find next block of B for GEMM a01 = ptr_a01_dup + D_NR; //pointer math to find next block of A for GEMM } ///GEMM code ends/// ymm15 = _mm256_broadcast_sd((double const *)&AlphaVal); //register to store alpha ymm1 = _mm256_fmsub_pd(ymm1, ymm15, ymm5); //B11[x][1] -= ymm5 ymm2 = _mm256_fmsub_pd(ymm2, ymm15, ymm6); //B11[x][2] -= ymm6 ymm3 = _mm256_fmsub_pd(ymm3, ymm15, ymm7); //B11[x][3] -= ymm7 ///implement TRSM/// ///read 4x4 block of A11/// //2nd col a11 += cs_a; ymm8 = _mm256_broadcast_sd((double const *)(a11+1)); //A11[0][1] ymm9 = _mm256_broadcast_sd((double const *)(a11+2)); //A11[1][1] ymm10 = _mm256_broadcast_sd((double const *)(a11+3)); //A11[1][1] //3rd col a11 += cs_a; ymm11 = _mm256_broadcast_sd((double const *)(a11+2)); //A11[0][2] ymm12 = _mm256_broadcast_sd((double const *)(a11+3)); //A11[1][2] //4th col a11 += cs_a; ymm13 = _mm256_broadcast_sd((double const *)(a11+3)); //A11[0][3] ymm14 = _mm256_broadcast_sd((double const *)&ones); //compute reciprocals of A(i,i) and broadcast in registers ymm4 = _mm256_unpacklo_pd(ymm14, ymm8); //A11[0][0] A11[1][1] A11[0][0] A11[1][1] ymm8 = _mm256_unpacklo_pd(ymm11, ymm13); //A11[2][2] A11[3][3] A11[2][2] A11[3][3] ymm15 = _mm256_blend_pd(ymm4, ymm8, 0x0C); //A11[0][0] A11[1][1] A11[2][2] A11[3][3] ymm14 = _mm256_div_pd(ymm14, ymm15); // 1/A11[0][0] 1/A11[1][1] 1/A11[2][2] 1/A11[3][3] //extract a33 ymm15 = _mm256_permute_pd(ymm14, 0x0C); //(1/A11[0][0] 1/A11[0][0] 1/A11[3][3] 1/A11[3][3]) ymm15 = _mm256_permute2f128_pd(ymm15, ymm15, 0x11); //(1/A11[3][3] 1/A11[3][3] 1/A11[3][3] 1/A11[3][3]) ymm3 = _mm256_mul_pd(ymm3, ymm15); //extract a22 ymm15 = _mm256_permute_pd(ymm14, 0x00); //(1/A11[0][0] 1/A11[0][0] 1/A11[2][2] 1/A11[2][2]) ymm15 = _mm256_permute2f128_pd(ymm15, ymm15, 0x11); //(1/A11[2][2] 1/A11[2][2] 1/A11[2][2] 1/A11[2][2]) //(Row 3): FMA operations ymm2 = _mm256_fnmadd_pd(ymm3, ymm12, ymm2); ymm1 = _mm256_fnmadd_pd(ymm3, ymm10, ymm1); ymm2 = _mm256_mul_pd(ymm2, ymm15); //extract a11 ymm15 = _mm256_permute_pd(ymm14, 0x03); //(1/A11[1][1] 1/A11[1][1] 1/A11[2][2] 1/A11[2][2]) ymm15 = _mm256_permute2f128_pd(ymm15, ymm15, 0x00); //(1/A11[1][1] 1/A11[1][1] 1/A11[1][1] 1/A11[1][1]) //(ROW 2): FMA operations ymm1 = _mm256_fnmadd_pd(ymm2, ymm9, ymm1); ymm1 = _mm256_mul_pd(ymm1, ymm15); _mm256_storeu_pd((double *)(b11 + cs_b), ymm1); //store(B11[x][1]) _mm256_storeu_pd((double *)(b11 + cs_b_offset[0]), ymm2); //(store(B11[x][2])) _mm256_storeu_pd((double *)(b11 + cs_b*3), ymm3); //store(B11[x][0]) } else if(2 == n_remainder) { ymm2 = _mm256_loadu_pd((double const *)(b11 + cs_b * 2)); //B11[0][0] B11[1][0] B11[2][0] B11[3][0] ymm3 = _mm256_loadu_pd((double const *)(b11 + cs_b * 3)); //B11[0][1] B11[1][1] B11[2][1] B11[3][1] ///GEMM processing stars/// for(k = 0; k < k_iter; k++) { ptr_a01_dup = a01; //load 4x4 bblock of b10 ymm8 = _mm256_loadu_pd((double const *)b10); //B10[0][0] B10[1][0] B10[2][0] B10[3][0] ymm9 = _mm256_loadu_pd((double const *)(b10 + cs_b)); //B10[0][1] B10[1][1] B10[2][1] B10[3][1] ymm10 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0])); //B10[0][2] B10[1][2] B10[2][2] B10[3][2] ymm11 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[1])); //B10[0][3] B10[1][3] B10[2][3] B10[3][3] //broadcast 1st row of A01 ymm14 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 2)); //A01[0][2] ymm15 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 3)); //A01[0][3] a01 += 1; //move to next row of A ymm6 = _mm256_fmadd_pd(ymm14, ymm8, ymm6); //ymm6 += (B10[0][0]*A01[0][2] B10[1][0]*A01[0][2] B10[2][0]*A01[0][2] B10[3][0]*A01[0][2]) ymm7 = _mm256_fmadd_pd(ymm15, ymm8, ymm7); //ymm7 += (B10[0][0]*A01[0][3] B10[1][0]*A01[0][3] B10[2][0]*A01[0][3] B10[3][0]*A01[0][3]) //broadcast 2nd row of A01 ymm14 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 2)); //A01[1][2] ymm15 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 3)); //A01[1][3] a01 += 1; //move to next row of A ymm6 = _mm256_fmadd_pd(ymm14, ymm9, ymm6); //ymm6 += (B10[0][1]*A01[1][2] B10[1][1]*A01[1][2] B10[2][1]*A01[1][2] B10[3][1]*A01[1][2]) ymm7 = _mm256_fmadd_pd(ymm15, ymm9, ymm7); //ymm7 += (B10[0][1]*A01[1][3] B10[1][1]*A01[1][3] B10[2][1]*A01[1][3] B10[3][1]*A01[1][3]) //braodcast 3rd row of A01 ymm14 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 2)); //A01[2][2] ymm15 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 3)); //A01[2][3] a01 += 1; //move to next row of A ymm6 = _mm256_fmadd_pd(ymm14, ymm10, ymm6); //ymm6 += (B10[0][2]*A01[2][2] B10[1][2]*A01[2][2] B10[2][2]*A01[2][2] B10[3][2]*A01[2][2]) ymm7 = _mm256_fmadd_pd(ymm15, ymm10, ymm7); //ymm7 += (B10[0][2]*A01[2][3] B10[1][2]*A01[2][3] B10[2][2]*A01[2][3] B10[3][2]*A01[2][3]) //broadcast 4th row of A01 ymm14 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 2)); //A01[3][2] ymm15 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 3)); //A01[3][3] a01 += 1; //move to next row of A ymm6 = _mm256_fmadd_pd(ymm14, ymm11, ymm6); //ymm6 += (B10[0][3]*A01[3][2] B10[1][3]*A01[3][2] B10[2][3]*A01[3][2] B10[3][3]*A01[3][2]) ymm7 = _mm256_fmadd_pd(ymm15, ymm11, ymm7); //ymm7 += (B10[0][3]*A01[3][3] B10[1][3]*A01[3][3] B10[2][3]*A01[3][3] B10[3][3]*A01[3][3]) b10 += D_NR * cs_b; //pointer math to find next block of B for GEMM a01 = ptr_a01_dup + D_NR; //pointer math to find next block of A for GEMM } ///GEMM code ends/// ymm15 = _mm256_broadcast_sd((double const *)&AlphaVal); //register to store alpha ymm2 = _mm256_fmsub_pd(ymm2, ymm15, ymm6); //B11[x][2] -= ymm6 ymm3 = _mm256_fmsub_pd(ymm3, ymm15, ymm7); //B11[x][3] -= ymm7 ///implement TRSM/// ///read 4x4 block of A11/// //3rd col a11 += 2 * cs_a; ymm11 = _mm256_broadcast_sd((double const *)(a11+2)); //A11[0][2] ymm12 = _mm256_broadcast_sd((double const *)(a11+3)); //A11[1][2] //4th col a11 += cs_a; ymm13 = _mm256_broadcast_sd((double const *)(a11+3)); //A11[0][3] ymm14 = _mm256_broadcast_sd((double const *)&ones); //compute reciprocals of A(i,i) and broadcast in registers ymm8 = _mm256_unpacklo_pd(ymm11, ymm13); //A11[2][2] A11[3][3] A11[2][2] A11[3][3] ymm15 = _mm256_blend_pd(ymm14, ymm8, 0x0C); //A11[0][0] A11[1][1] A11[2][2] A11[3][3] ymm14 = _mm256_div_pd(ymm14, ymm15); // 1/A11[0][0] 1/A11[1][1] 1/A11[2][2] 1/A11[3][3] //extract a33 ymm15 = _mm256_permute_pd(ymm14, 0x0C); //(1/A11[0][0] 1/A11[0][0] 1/A11[3][3] 1/A11[3][3]) ymm15 = _mm256_permute2f128_pd(ymm15, ymm15, 0x11); //(1/A11[3][3] 1/A11[3][3] 1/A11[3][3] 1/A11[3][3]) ymm3 = _mm256_mul_pd(ymm3, ymm15); //extract a22 ymm15 = _mm256_permute_pd(ymm14, 0x00); //(1/A11[0][0] 1/A11[0][0] 1/A11[2][2] 1/A11[2][2]) ymm15 = _mm256_permute2f128_pd(ymm15, ymm15, 0x11); //(1/A11[2][2] 1/A11[2][2] 1/A11[2][2] 1/A11[2][2]) //(Row 3): FMA operations ymm2 = _mm256_fnmadd_pd(ymm3, ymm12, ymm2); ymm2 = _mm256_mul_pd(ymm2, ymm15); _mm256_storeu_pd((double *)(b11+ cs_b * 2), ymm2); //store(B11[x][0]) _mm256_storeu_pd((double *)(b11 + cs_b * 3), ymm3); //store(B11[x][1]) } else if(1 == n_remainder) { ymm3 = _mm256_loadu_pd((double const *)(b11 + cs_b * 3)); //B11[0][0] B11[1][0] B11[2][0] B11[3][0] ///GEMM processing stars/// for(k = 0; k < k_iter; k++) { ptr_a01_dup = a01; //load 4x4 bblock of b10 ymm8 = _mm256_loadu_pd((double const *)b10); //B10[0][0] B10[1][0] B10[2][0] B10[3][0] ymm9 = _mm256_loadu_pd((double const *)(b10 + cs_b)); //B10[0][1] B10[1][1] B10[2][1] B10[3][1] ymm10 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0])); //B10[0][2] B10[1][2] B10[2][2] B10[3][2] ymm11 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[1])); //B10[0][3] B10[1][3] B10[2][3] B10[3][3] //broadcast 1st row of A01 ymm15 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 3)); //A01[0][3] a01 += 1; //move to next row of A ymm7 = _mm256_fmadd_pd(ymm15, ymm8, ymm7); //ymm7 += (B10[0][0]*A01[0][3] B10[1][0]*A01[0][3] B10[2][0]*A01[0][3] B10[3][0]*A01[0][3]) //broadcast 2nd row of A01 ymm15 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 3)); //A01[1][3] a01 += 1; //move to next row of A ymm7 = _mm256_fmadd_pd(ymm15, ymm9, ymm7); //ymm7 += (B10[0][1]*A01[1][3] B10[1][1]*A01[1][3] B10[2][1]*A01[1][3] B10[3][1]*A01[1][3]) //braodcast 3rd row of A01 ymm15 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 3)); //A01[2][3] a01 += 1; //move to next row of A ymm7 = _mm256_fmadd_pd(ymm15, ymm10, ymm7); //ymm7 += (B10[0][2]*A01[2][3] B10[1][2]*A01[2][3] B10[2][2]*A01[2][3] B10[3][2]*A01[2][3]) //broadcast 4th row of A01 ymm15 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 3)); //A01[3][3] a01 += 1; //move to next row of A ymm7 = _mm256_fmadd_pd(ymm15, ymm11, ymm7); //ymm7 += (B10[0][3]*A01[3][3] B10[1][3]*A01[3][3] B10[2][3]*A01[3][3] B10[3][3]*A01[3][3]) b10 += D_NR * cs_b; //pointer math to find next block of B for GEMM a01 = ptr_a01_dup + D_NR; //pointer math to find next block of A for GEMM } ///GEMM code ends/// ymm15 = _mm256_broadcast_sd((double const *)&AlphaVal); //register to store alpha ymm3 = _mm256_fmsub_pd(ymm3, ymm15, ymm7); //B11[x][3] -= ymm7 ///implement TRSM/// ///read 4x4 block of A11/// //4th col a11 += 3 * cs_a; ymm13 = _mm256_broadcast_sd((double const *)(a11+3)); //A11[0][3] ymm14 = _mm256_broadcast_sd((double const *)&ones); //compute reciprocals of A(i,i) and broadcast in registers ymm14 = _mm256_div_pd(ymm14, ymm13); // 1/A11[0][0] 1/A11[1][1] 1/A11[2][2] 1/A11[3][3] //extract a33 ymm3 = _mm256_mul_pd(ymm3, ymm14); _mm256_storeu_pd((double *)(b11 + cs_b * 3), ymm3); //store(B11[x][0]) } } m_remainder -= 4; i -= 4; } // if(i < 0) i = 0; if(m_remainder) ///implementation for remainder rows { dtrsm_small_XAlB(L, B, AlphaVal, m_remainder, n, cs_a, cs_b); } return BLIS_SUCCESS; } /*implements TRSM for the case XA = alpha * B *A is lower triangular, unit-diagonal, no transpose *dimensions: X:mxn A:nxn B: mxn */ /* <---b11 <---a11 ***************** * *b01*b11* * * * * ^ * * * * * ^ * * | ***************** | ******* | * * * * * | * * * | * * * * * a01* * * b10 ***************** ************* * * * * * * * * * * * * * * * * * * ***************** ******************* */ static err_t bli_dtrsm_small_XAlB_unitDiag( side_t side, obj_t* AlphaObj, obj_t* a, obj_t* b, cntx_t* cntx, cntl_t* cntl ) { dim_t D_MR = 8; //block dimension along the rows dim_t D_NR = 4; //block dimension along the columns dim_t m = bli_obj_length(b); //number of rows dim_t n = bli_obj_width(b); //number of columns dim_t m_remainder = m & 7; //number of corner rows dim_t n_remainder = n & 3; //number of corner columns dim_t cs_a = bli_obj_col_stride(a); //column stride of matrix A dim_t cs_b = bli_obj_col_stride(b); //column stride of matrix B #ifdef BLIS_ENABLE_SMALL_MATRIX_ROME if((m < D_BLIS_SMALL_MATRIX_THRES_TRSM_XALB_ROME && n > D_BLIS_SMALL_MATRIX_THRES_TRSM_XALB_ROME) ||(m > D_BLIS_SMALL_MATRIX_THRES_TRSM_XALB_ROME && n > D_BLIS_SMALL_MATRIX_THRES_TRSM_XALB_ROME_COL_PANEL_N) ) return BLIS_NOT_YET_IMPLEMENTED; #else if(bli_max(m,n) > D_BLIS_SMALL_MATRIX_THRES_TRSM_NAPLES) { return BLIS_NOT_YET_IMPLEMENTED; } #endif dim_t i, j, k; //loop variablse dim_t k_iter; //determines the number of GEMM operations to be done dim_t cs_b_offset[2]; //pre-calculated strides double AlphaVal = *(double *)AlphaObj->buffer; //value of Alpha double* restrict L = a->buffer; //pointer to matrix A double* restrict B = b->buffer; //pointer to matrix B double *a01, *a11, *b10, *b11; //pointers for GEMM and TRSM blocks double *ptr_a01_dup; cs_b_offset[0] = cs_b << 1; //cs_b_offset[0] = cs_b * 2; cs_b_offset[1] = cs_b_offset[0] + cs_b;//cs_b_offset[1] = cs_b * 3; //ymm scratch reginsters __m256d ymm0, ymm1, ymm2, ymm3; __m256d ymm4, ymm5, ymm6, ymm7; __m256d ymm8, ymm9, ymm10, ymm11; __m256d ymm12, ymm13, ymm14, ymm15; __m256d ymm16; for(i = (m-D_MR); (i+1) > 0; i -= D_MR) //loop along 'M' direction { for(j = (n-D_NR); (j+1) > 0; j -= D_NR) //loop along 'N' direction { a01 = L + j*cs_a +(j+D_NR); //pointer to block of A to be used in GEMM a11 = L + j*cs_a + j; //pointer to block of A to be used for TRSM b10 = B + i + (j+D_NR)*cs_b; //pointer to block of B to be used in GEMM b11 = B + (i) + (j)*cs_b; //pointer to block of B to be used for TRSM k_iter = (n-j-D_NR) / D_NR; //number of GEMM operations to be done(in blocks of 4x4) ymm0 = _mm256_setzero_pd(); ymm1 = _mm256_setzero_pd(); ymm2 = _mm256_setzero_pd(); ymm3 = _mm256_setzero_pd(); ymm4 = _mm256_setzero_pd(); ymm5 = _mm256_setzero_pd(); ymm6 = _mm256_setzero_pd(); ymm7 = _mm256_setzero_pd(); ///GEMM implementation starts/// for(k = 0; k < k_iter; k++) //loop for number of GEMM operations { ptr_a01_dup = a01; //broadcast 1st row of A01 ymm8 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 0)); //A01[0][0] ymm9 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 1)); //A01[0][1] ymm10 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 2)); //A01[0][2] ymm11 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 3)); //A01[0][3] a01 += 1; //move to next row //load 8x2 block of B10 ymm12 = _mm256_loadu_pd((double const *)b10); //B10[0][0] B10[1][0] B10[2][0] B10[3][0] ymm13 = _mm256_loadu_pd((double const *)(b10 + D_NR)); //B10[4][0] B10[5][0] B10[6][0] B10[7][0] ymm14 = _mm256_loadu_pd((double const *)(b10 + cs_b)); //B10[0][1] B10[1][1] B10[2][1] B10[3][1] ymm15 = _mm256_loadu_pd((double const *)(b10 + cs_b + D_NR)); //B10[4][1] B10[5][1] B10[6][1] B10[7][1] ymm0 = _mm256_fmadd_pd(ymm8, ymm12, ymm0); //ymm0 += (B10[0][0]*A01[0][0] B10[1][0]*A01[0][0] B10[2][0]*A01[0][0] B10[3][0]*A01[0][0]) ymm1 = _mm256_fmadd_pd(ymm9, ymm12, ymm1); //ymm1 += (B10[0][0]*A01[0][1] B10[1][0]*A01[0][1] B10[2][0]*A01[0][1] B10[3][0]*A01[0][1]) ymm2 = _mm256_fmadd_pd(ymm10, ymm12, ymm2); //ymm2 += (B10[0][0]*A01[0][2] B10[1][0]*A01[0][2] B10[2][0]*A01[0][2] B10[3][0]*A01[0][2]) ymm3 = _mm256_fmadd_pd(ymm11, ymm12, ymm3); //ymm3 += (B10[0][0]*A01[0][3] B10[1][0]*A01[0][3] B10[2][0]*A01[0][3] B10[3][0]*A01[0][3]) ymm4 = _mm256_fmadd_pd(ymm8, ymm13, ymm4); //ymm4 += (B10[4][0]*A01[0][0] B10[5][0]*A01[0][0] B10[6][0]*A01[0][0] B10[7][0]*A01[0][0]) ymm5 = _mm256_fmadd_pd(ymm9, ymm13, ymm5); //ymm5 += (B10[4][0]*A01[0][1] B10[5][0]*A01[0][1] B10[6][0]*A01[0][1] B10[7][0]*A01[0][1]) ymm6 = _mm256_fmadd_pd(ymm10, ymm13, ymm6); //ymm6 += (B10[4][0]*A01[0][2] B10[5][0]*A01[0][2] B10[6][0]*A01[0][2] B10[7][0]*A01[0][2]) ymm7 = _mm256_fmadd_pd(ymm11, ymm13, ymm7); //ymm7 += (B10[4][0]*A01[0][3] B10[5][0]*A01[0][3] B10[6][0]*A01[0][3] B10[7][0]*A01[0][3]) //broadcast 2nd row of A01 ymm8 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 0)); //A01[1][0] ymm9 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 1)); //A01[1][1] ymm10 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 2)); //A01[1][2] ymm11 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 3)); //A01[1][3] a01 += 1; //move to next row of A ymm0 = _mm256_fmadd_pd(ymm8, ymm14, ymm0); //ymm0 += (B10[0][1]*A01[0][0] B10[1][1]*A01[0][0] B10[2][1]*A01[0][0] B10[3][1]*A01[0][0]) ymm1 = _mm256_fmadd_pd(ymm9, ymm14, ymm1); //ymm1 += (B10[0][1]*A01[0][1] B10[1][1]*A01[0][1] B10[2][1]*A01[0][1] B10[3][1]*A01[0][1]) ymm2 = _mm256_fmadd_pd(ymm10, ymm14, ymm2); //ymm2 += (B10[0][1]*A01[0][2] B10[1][1]*A01[0][2] B10[2][1]*A01[0][2] B10[3][1]*A01[0][2]) ymm3 = _mm256_fmadd_pd(ymm11, ymm14, ymm3); //ymm3 += (B10[0][1]*A01[0][3] B10[1][1]*A01[0][3] B10[2][1]*A01[0][3] B10[3][1]*A01[0][3]) ymm4 = _mm256_fmadd_pd(ymm8, ymm15, ymm4); //ymm4 += (B10[4][1]*A01[0][0] B10[5][1]*A01[0][0] B10[6][1]*A01[0][0] B10[7][1]*A01[0][0]) ymm5 = _mm256_fmadd_pd(ymm9, ymm15, ymm5); //ymm5 += (B10[4][1]*A01[0][1] B10[5][1]*A01[0][1] B10[6][1]*A01[0][1] B10[7][1]*A01[0][1]) ymm6 = _mm256_fmadd_pd(ymm10, ymm15, ymm6); //ymm6 += (B10[4][1]*A01[0][2] B10[5][1]*A01[0][2] B10[6][1]*A01[0][2] B10[7][1]*A01[0][2]) ymm7 = _mm256_fmadd_pd(ymm11, ymm15, ymm7); //ymm7 += (B10[4][1]*A01[0][3] B10[5][1]*A01[0][3] B10[6][1]*A01[0][3] B10[7][1]*A01[0][3]) //broadcast 3rd row of A01 ymm8 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 0)); //A01[2][0] ymm9 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 1)); //A01[2][1] ymm10 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 2)); //A01[2][2] ymm11 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 3)); //A01[2][3] a01 += 1; //move to next row of A01 //load next 8x2 block of B10 ymm12 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0])); //(B10[0][2] B10[1][2] B10[2][2] B10[3][2]) ymm13 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + D_NR)); //(B10[4][2] B10[5][2] B10[6][2] B10[7][2]) ymm14 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + cs_b)); //(B10[0][3] B10[1][3] B10[2][3] B10[3][3]) ymm15 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + cs_b + D_NR)); //(B10[4][3] B10[5][3] B10[6][3] B10[7][3]) ymm0 = _mm256_fmadd_pd(ymm8, ymm12, ymm0); //ymm0 += (B10[0][2]*A01[0][0] B10[1][2]*A01[0][0] B10[2][2]*A01[0][0] B10[3][2]*A01[0][0]) ymm1 = _mm256_fmadd_pd(ymm9, ymm12, ymm1); //ymm1 += (B10[0][2]*A01[0][1] B10[1][2]*A01[0][1] B10[2][2]*A01[0][1] B10[3][2]*A01[0][1]) ymm2 = _mm256_fmadd_pd(ymm10, ymm12, ymm2); //ymm2 += (B10[0][2]*A01[0][2] B10[1][2]*A01[0][2] B10[2][2]*A01[0][2] B10[3][2]*A01[0][2]) ymm3 = _mm256_fmadd_pd(ymm11, ymm12, ymm3); //ymm3 += (B10[0][2]*A01[0][3] B10[1][2]*A01[0][3] B10[2][2]*A01[0][3] B10[3][2]*A01[0][3]) ymm4 = _mm256_fmadd_pd(ymm8, ymm13, ymm4); //ymm4 += (B10[4][2]*A01[0][0] B10[5][2]*A01[0][0] B10[6][2]*A01[0][0] B10[7][2]*A01[0][0]) ymm5 = _mm256_fmadd_pd(ymm9, ymm13, ymm5); //ymm5 += (B10[4][2]*A01[0][1] B10[5][2]*A01[0][1] B10[6][2]*A01[0][1] B10[7][2]*A01[0][1]) ymm6 = _mm256_fmadd_pd(ymm10, ymm13, ymm6); //ymm6 += (B10[4][2]*A01[0][2] B10[5][2]*A01[0][2] B10[6][2]*A01[0][2] B10[7][2]*A01[0][2]) ymm7 = _mm256_fmadd_pd(ymm11, ymm13, ymm7); //ymm7 += (B10[4][2]*A01[0][3] B10[5][2]*A01[0][3] B10[6][2]*A01[0][3] B10[7][2]*A01[0][3]) //broadcast 4th row of A01 ymm8 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 0)); //A01[3][0] ymm9 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 1)); //A01[3][1] ymm10 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 2)); //A01[3][2] ymm11 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 3)); //A01[3][3] a01 += 1; //move to next row of A01 ymm0 = _mm256_fmadd_pd(ymm8, ymm14, ymm0); //ymm0 += (B10[0][3]*A01[0][0] B10[1][3]*A01[0][0] B10[2][3]*A01[0][0] B10[3][3]*A01[0][0]) ymm1 = _mm256_fmadd_pd(ymm9, ymm14, ymm1); //ymm1 += (B10[0][3]*A01[0][1] B10[1][3]*A01[0][1] B10[2][3]*A01[0][1] B10[3][3]*A01[0][1]) ymm2 = _mm256_fmadd_pd(ymm10, ymm14, ymm2); //ymm2 += (B10[0][3]*A01[0][2] B10[1][3]*A01[0][2] B10[2][3]*A01[0][2] B10[3][3]*A01[0][2]) ymm3 = _mm256_fmadd_pd(ymm11, ymm14, ymm3); //ymm3 += (B10[0][3]*A01[0][3] B10[1][3]*A01[0][3] B10[2][3]*A01[0][3] B10[3][3]*A01[0][3]) ymm4 = _mm256_fmadd_pd(ymm8, ymm15, ymm4); //ymm4 += (B10[4][3]*A01[0][0] B10[5][3]*A01[0][0] B10[6][3]*A01[0][0] B10[7][3]*A01[0][0]) ymm5 = _mm256_fmadd_pd(ymm9, ymm15, ymm5); //ymm5 += (B10[4][3]*A01[0][1] B10[5][3]*A01[0][1] B10[6][3]*A01[0][1] B10[7][3]*A01[0][1]) ymm6 = _mm256_fmadd_pd(ymm10, ymm15, ymm6); //ymm6 += (B10[4][3]*A01[0][2] B10[5][3]*A01[0][2] B10[6][3]*A01[0][2] B10[7][3]*A01[0][2]) ymm7 = _mm256_fmadd_pd(ymm11, ymm15, ymm7); //ymm7 += (B10[4][3]*A01[0][3] B10[5][3]*A01[0][3] B10[6][3]*A01[0][3] B10[7][3]*A01[0][3]) b10 += D_NR * cs_b; //pointer math to find next block of B for GEMM a01 = ptr_a01_dup + D_NR; //pointer math to find next block of A for GEMM } ///GEMM code ends/// ymm16 = _mm256_broadcast_sd((double const *)&AlphaVal); //load 8x4 block of B11 ymm8 = _mm256_loadu_pd((double const *)b11); //B11[0][0] B11[1][0] B11[2][0] B11[3][0] ymm12 = _mm256_loadu_pd((double const *)(b11 + D_NR)); //B11[4][0] B11[5][0] B11[6][0] B11[7][0] ymm9 = _mm256_loadu_pd((double const *)(b11 + cs_b)); //B11[0][1] B11[1][1] B11[2][1] B11[3][1] ymm13 = _mm256_loadu_pd((double const *)(b11 + cs_b + D_NR)); //B11[4][1] B11[5][1] B11[6][1] B11[7][1] ymm10 = _mm256_loadu_pd((double const *)(b11 + cs_b_offset[0])); //B11[0][2] B11[1][2] B11[2][2] B11[3][2] ymm14 = _mm256_loadu_pd((double const *)(b11 + cs_b_offset[0] + D_NR)); //B11[4][2] B11[5][2] B11[6][2] B11[7][2] ymm11 = _mm256_loadu_pd((double const *)(b11 + cs_b_offset[1])); //B11[0][3] B11[1][3] B11[2][3] B11[3][3] ymm15 = _mm256_loadu_pd((double const *)(b11 + cs_b_offset[1] + D_NR)); //B11[4][3] B11[5][3] B11[6][3] B11[7][3] ymm8 = _mm256_fmsub_pd(ymm8, ymm16, ymm0); //B11[0-3][0] * alpha -= ymm0 ymm9 = _mm256_fmsub_pd(ymm9, ymm16, ymm1); //B11[4-7][0] * alpha-= ymm1 ymm10 = _mm256_fmsub_pd(ymm10, ymm16, ymm2); //B11[0-3][1] * alpha-= ymm2 ymm11 = _mm256_fmsub_pd(ymm11, ymm16, ymm3); //B11[4-7][1] * alpha -= ymm3 ymm12 = _mm256_fmsub_pd(ymm12, ymm16, ymm4); //B11[0-3][2] * alpha -= ymm4 ymm13 = _mm256_fmsub_pd(ymm13, ymm16, ymm5); //B11[4-7][2] * alpha -= ymm5 ymm14 = _mm256_fmsub_pd(ymm14, ymm16, ymm6); //B11[0-3][3] * alpha -= ymm6 ymm15 = _mm256_fmsub_pd(ymm15, ymm16, ymm7); //B11[4-7][3] * alpha -= ymm7 ///implement TRSM/// ///read 4x4 block of A11/// //2nd col a11 += 1; ymm1 = _mm256_broadcast_sd((double const *)(a11+ cs_a * 0)); //A11[0][1] //3rd col a11 += 1; ymm3 = _mm256_broadcast_sd((double const *)(a11+ cs_a * 0)); //A11[0][2] ymm4 = _mm256_broadcast_sd((double const *)(a11+ cs_a * 1)); //A11[1][2] //4th col a11 += 1; ymm2 = _mm256_broadcast_sd((double const *)(a11+ cs_a * 0)); //A11[0][3] ymm5 = _mm256_broadcast_sd((double const *)(a11+ cs_a * 1)); //A11[1][3] ymm6 = _mm256_broadcast_sd((double const *)(a11+ cs_a * 2)); //A11[2][3] //(row 3):FMA operations ymm10 = _mm256_fnmadd_pd(ymm11, ymm6, ymm10); ymm9 = _mm256_fnmadd_pd(ymm11, ymm5, ymm9); ymm8 = _mm256_fnmadd_pd(ymm11, ymm2, ymm8); ymm14 = _mm256_fnmadd_pd(ymm15, ymm6, ymm14); ymm13 = _mm256_fnmadd_pd(ymm15, ymm5, ymm13); ymm12 = _mm256_fnmadd_pd(ymm15, ymm2, ymm12); //(Row 2): FMA operations ymm9 = _mm256_fnmadd_pd(ymm10, ymm4, ymm9); ymm8 = _mm256_fnmadd_pd(ymm10, ymm3, ymm8); ymm13 = _mm256_fnmadd_pd(ymm14, ymm4, ymm13); ymm12 = _mm256_fnmadd_pd(ymm14, ymm3, ymm12); //(Row 1): FMA operations ymm8 = _mm256_fnmadd_pd(ymm9, ymm1, ymm8); ymm12 = _mm256_fnmadd_pd(ymm13, ymm1, ymm12); _mm256_storeu_pd((double *)b11, ymm8); //store(B11[0-3][0]) _mm256_storeu_pd((double *)(b11 + D_NR), ymm12); //store(B11[4-7][0]) _mm256_storeu_pd((double *)(b11 + cs_b), ymm9); //store(B11[0-3][1]) _mm256_storeu_pd((double *)(b11 + cs_b + D_NR), ymm13); //store(B11[4-7][1]) _mm256_storeu_pd((double *)(b11 + cs_b_offset[0]), ymm10); //store(B11[0-3][2]) _mm256_storeu_pd((double *)(b11 + cs_b_offset[0] + D_NR), ymm14); //store(B11[4-7][2]) _mm256_storeu_pd((double *)(b11 + cs_b_offset[0] + cs_b), ymm11); //store(B11[0-3][3]) _mm256_storeu_pd((double *)(b11 + cs_b_offset[0] + cs_b + D_NR), ymm15);//store(B11[4-7][3]) } if(n_remainder) //implementation for remainder columns(when n is not multiple of D_NR) { a01 = L + j*cs_a + (j+D_NR); //pointer to block of A to be used for GEMM a11 = L + j*cs_a + j; //pointer to block of A to be used for TRSM b10 = B + i + (j + D_NR)*cs_b; //pointer to block of B to be used for GEMM b11 = B + i + j*cs_b; //pointer to block of B to be used for TRSM k_iter = (n-j-D_NR) / D_NR; //number of GEMM operations to be performed(in blocks of 4x4) ///load 4x4 block of b11 ymm0 = _mm256_setzero_pd(); ymm1 = _mm256_setzero_pd(); ymm2 = _mm256_setzero_pd(); ymm3 = _mm256_setzero_pd(); ymm4 = _mm256_setzero_pd(); ymm5 = _mm256_setzero_pd(); ymm6 = _mm256_setzero_pd(); ymm7 = _mm256_setzero_pd(); //subtract the calculated GEMM block from current TRSM block //load 8x4 block of B11 if(3 == n_remainder) { ///GEMM implementation begins/// for(k = 0; k < k_iter; k++) ///loop for number of GEMM operations { ptr_a01_dup = a01; //broadcast 1st row of A01 ymm9 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 1)); //A01[0][1] ymm10 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 2)); //A01[0][2] ymm11 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 3)); //A01[0][3] a01 += 1; //move to next row of A //load 8x2 block of B10 ymm12 = _mm256_loadu_pd((double const *)b10); //B10[0][0] B10[1][0] B10[2][0] B10[3][0] ymm13 = _mm256_loadu_pd((double const *)(b10 + D_NR)); //B10[4][0] B10[5][0] B10[6][0] B10[7][0] ymm14 = _mm256_loadu_pd((double const *)(b10 + cs_b)); //B10[0][1] B10[1][1] B10[2][1] B10[3][1] ymm15 = _mm256_loadu_pd((double const *)(b10 + cs_b + D_NR));//B10[4][1] B10[5][1] B10[6][1] B10[7][1] ymm1 = _mm256_fmadd_pd(ymm9, ymm12, ymm1); //ymm1 += (B10[0][0]*A01[0][1] B10[1][0]*A01[0][1] B10[2][0]*A01[0][1] B10[3][0]*A01[0][1]) ymm2 = _mm256_fmadd_pd(ymm10, ymm12, ymm2); //ymm2 += (B10[0][0]*A01[0][2] B10[1][0]*A01[0][2] B10[2][0]*A01[0][2] B10[3][0]*A01[0][2]) ymm3 = _mm256_fmadd_pd(ymm11, ymm12, ymm3); //ymm3 += (B10[0][0]*A01[0][3] B10[1][0]*A01[0][3] B10[2][0]*A01[0][3] B10[3][0]*A01[0][3]) ymm5 = _mm256_fmadd_pd(ymm9, ymm13, ymm5); //ymm5 += (B10[4][0]*A01[0][1] B10[5][0]*A01[0][1] B10[6][0]*A01[0][1] B10[7][0]*A01[0][1]) ymm6 = _mm256_fmadd_pd(ymm10, ymm13, ymm6); //ymm6 += (B10[4][0]*A01[0][2] B10[5][0]*A01[0][2] B10[6][0]*A01[0][2] B10[7][0]*A01[0][2]) ymm7 = _mm256_fmadd_pd(ymm11, ymm13, ymm7); //ymm7 += (B10[4][0]*A01[0][3] B10[5][0]*A01[0][3] B10[6][0]*A01[0][3] B10[7][0]*A01[0][3]) //broadcast 2nd row of A01 ymm9 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 1)); //A01[1][1] ymm10 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 2)); //A01[1][2] ymm11 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 3)); //A01[1][3] a01 += 1; //move to next row of A ymm1 = _mm256_fmadd_pd(ymm9, ymm14, ymm1); //ymm1 += (B10[0][1]*A01[0][1] B10[1][1]*A01[0][1] B10[2][1]*A01[0][1] B10[3][1]*A01[0][1]) ymm2 = _mm256_fmadd_pd(ymm10, ymm14, ymm2); //ymm2 += (B10[0][1]*A01[0][2] B10[1][1]*A01[0][2] B10[2][1]*A01[0][2] B10[3][1]*A01[0][2]) ymm3 = _mm256_fmadd_pd(ymm11, ymm14, ymm3); //ymm3 += (B10[0][1]*A01[0][3] B10[1][1]*A01[0][3] B10[2][1]*A01[0][3] B10[3][1]*A01[0][3]) ymm5 = _mm256_fmadd_pd(ymm9, ymm15, ymm5); //ymm5 += (B10[4][1]*A01[0][1] B10[5][1]*A01[0][1] B10[6][1]*A01[0][1] B10[7][1]*A01[0][1]) ymm6 = _mm256_fmadd_pd(ymm10, ymm15, ymm6); //ymm6 += (B10[4][1]*A01[0][2] B10[5][1]*A01[0][2] B10[6][1]*A01[0][2] B10[7][1]*A01[0][2]) ymm7 = _mm256_fmadd_pd(ymm11, ymm15, ymm7); //ymm7 += (B10[4][1]*A01[0][3] B10[5][1]*A01[0][3] B10[6][1]*A01[0][3] B10[7][1]*A01[0][3]) //broadcast 3rd row of A01 ymm9 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 1)); //A01[2][1] ymm10 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 2)); //A01[2][2] ymm11 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 3)); //A01[2][3] a01 += 1; //move to next row of A //load next 8x2 block of B10 ymm12 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0])); //(B10[0][2] B10[1][2] B10[2][2] B10[3][2]) ymm13 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + D_NR)); //(B10[4][2] B10[5][2] B10[6][2] B10[7][2]) ymm14 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[1] )); //(B10[0][3] B10[1][3] B10[2][3] B10[3][3]) ymm15 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[1] + D_NR)); //(B10[4][3] B10[5][3] B10[6][3] B10[7][3]) ymm1 = _mm256_fmadd_pd(ymm9, ymm12, ymm1); //ymm1 += (B10[0][2]*A01[0][1] B10[1][2]*A01[0][1] B10[2][2]*A01[0][1] B10[3][2]*A01[0][1]) ymm2 = _mm256_fmadd_pd(ymm10, ymm12, ymm2); //ymm2 += (B10[0][2]*A01[0][2] B10[1][2]*A01[0][2] B10[2][2]*A01[0][2] B10[3][2]*A01[0][2]) ymm3 = _mm256_fmadd_pd(ymm11, ymm12, ymm3); //ymm3 += (B10[0][2]*A01[0][3] B10[1][2]*A01[0][3] B10[2][2]*A01[0][3] B10[3][2]*A01[0][3]) ymm5 = _mm256_fmadd_pd(ymm9, ymm13, ymm5); //ymm5 += (B10[4][2]*A01[0][1] B10[5][2]*A01[0][1] B10[6][2]*A01[0][1] B10[7][2]*A01[0][1]) ymm6 = _mm256_fmadd_pd(ymm10, ymm13, ymm6); //ymm6 += (B10[4][2]*A01[0][2] B10[5][2]*A01[0][2] B10[6][2]*A01[0][2] B10[7][2]*A01[0][2]) ymm7 = _mm256_fmadd_pd(ymm11, ymm13, ymm7); //ymm7 += (B10[4][2]*A01[0][3] B10[5][2]*A01[0][3] B10[6][2]*A01[0][3] B10[7][2]*A01[0][3]) //broadcast 4th row of A01 ymm9 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 1)); //A01[3][1] ymm10 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 2)); //A01[3][2] ymm11 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 3)); //A01[3][3] a01 += 1; //move to next row of A ymm1 = _mm256_fmadd_pd(ymm9, ymm14, ymm1); //ymm1 += (B10[0][3]*A01[0][1] B10[1][3]*A01[0][1] B10[2][3]*A01[0][1] B10[3][3]*A01[0][1]) ymm2 = _mm256_fmadd_pd(ymm10, ymm14, ymm2); //ymm2 += (B10[0][3]*A01[0][2] B10[1][3]*A01[0][2] B10[2][3]*A01[0][2] B10[3][3]*A01[0][2]) ymm3 = _mm256_fmadd_pd(ymm11, ymm14, ymm3); //ymm3 += (B10[0][3]*A01[0][3] B10[1][3]*A01[0][3] B10[2][3]*A01[0][3] B10[3][3]*A01[0][3]) ymm5 = _mm256_fmadd_pd(ymm9, ymm15, ymm5); //ymm5 += (B10[4][3]*A01[0][1] B10[5][3]*A01[0][1] B10[6][3]*A01[0][1] B10[7][3]*A01[0][1]) ymm6 = _mm256_fmadd_pd(ymm10, ymm15, ymm6); //ymm6 += (B10[4][3]*A01[0][2] B10[5][3]*A01[0][2] B10[6][3]*A01[0][2] B10[7][3]*A01[0][2]) ymm7 = _mm256_fmadd_pd(ymm11, ymm15, ymm7); //ymm7 += (B10[4][3]*A01[0][3] B10[5][3]*A01[0][3] B10[6][3]*A01[0][3] B10[7][3]*A01[0][3]) b10 += D_NR * cs_b; //pointer math to find next block of B for GEMM a01 = ptr_a01_dup + D_NR; //pointer math to find next block of A for GEMM } ///GEMM code ends/// ymm8 = _mm256_broadcast_sd((double const *)&AlphaVal); ymm9 = _mm256_loadu_pd((double const *)(b11+cs_b)); //B11[0-3][0] ymm13 = _mm256_loadu_pd((double const *)(b11 + cs_b + D_NR)); //B11[4-7][0] ymm10 = _mm256_loadu_pd((double const *)(b11 + cs_b*2)); //B11[0-3][1] ymm14 = _mm256_loadu_pd((double const *)(b11 + cs_b*2 + D_NR)); //B11[4-7][1] ymm11 = _mm256_loadu_pd((double const *)(b11 + cs_b_offset[1])); //B11[0-3][2] ymm15 = _mm256_loadu_pd((double const *)(b11 + cs_b_offset[1] + D_NR)); //B11[4-7][2] ymm9 = _mm256_fmsub_pd(ymm9, ymm8, ymm1); //B11[4-7][0] * alpha -= B10[4-7][0] ymm10 = _mm256_fmsub_pd(ymm10, ymm8, ymm2); //B11[0-3][1] * alpha -= B10[0-3][1] ymm11 = _mm256_fmsub_pd(ymm11, ymm8, ymm3); //B11[4-7][1] * alpha -= B10[4-7][1] ymm13 = _mm256_fmsub_pd(ymm13, ymm8, ymm5); //B11[4-7][2] * alpha -= B10[4-7][2] ymm14 = _mm256_fmsub_pd(ymm14, ymm8, ymm6); //B11[0-3][3] * alpha -= B10[0-3][3] ymm15 = _mm256_fmsub_pd(ymm15, ymm8, ymm7); //B11[4-7][3] * alpha -= B10[4-7][3] ///implement TRSM/// ///read 4x4 block of A11/// //3rd col a11 += 2; ymm4 = _mm256_broadcast_sd((double const *)(a11+ cs_a * 1)); //A11[1][2] //4th col a11 += 1; ymm5 = _mm256_broadcast_sd((double const *)(a11+ cs_a * 1)); //A11[1][3] ymm6 = _mm256_broadcast_sd((double const *)(a11+ cs_a * 2)); //A11[2][3] //(row 3):FMA operations ymm10 = _mm256_fnmadd_pd(ymm11, ymm6, ymm10); ymm9 = _mm256_fnmadd_pd(ymm11, ymm5, ymm9); ymm14 = _mm256_fnmadd_pd(ymm15, ymm6, ymm14); ymm13 = _mm256_fnmadd_pd(ymm15, ymm5, ymm13); //(Row 2): FMA operations ymm9 = _mm256_fnmadd_pd(ymm10, ymm4, ymm9); ymm13 = _mm256_fnmadd_pd(ymm14, ymm4, ymm13); _mm256_storeu_pd((double *)(b11 + cs_b), ymm9); //store(B11[0-3][1]) _mm256_storeu_pd((double *)(b11 + cs_b + D_NR), ymm13); //store(B11[4-7][1]) _mm256_storeu_pd((double *)(b11 + cs_b_offset[0]), ymm10); //store(B11[0-3][2]) _mm256_storeu_pd((double *)(b11 + cs_b_offset[0] + D_NR), ymm14);//store(B11[4-7][2]) _mm256_storeu_pd((double *)(b11 + cs_b_offset[1]), ymm11); //store(B11[0-3][0]) _mm256_storeu_pd((double *)(b11 + cs_b_offset[1] + D_NR), ymm15); //store(B11[4-7][0]) } else if(2 == n_remainder) { ///GEMM implementation begins/// for(k = 0; k < k_iter; k++) ///loop for number of GEMM operations { ptr_a01_dup = a01; //broadcast 1st row of A01 ymm10 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 2)); //A01[0][2] ymm11 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 3)); //A01[0][3] a01 += 1; //move to next row of A //load 8x2 block of B10 ymm12 = _mm256_loadu_pd((double const *)b10); //B10[0][0] B10[1][0] B10[2][0] B10[3][0] ymm13 = _mm256_loadu_pd((double const *)(b10 + D_NR)); //B10[4][0] B10[5][0] B10[6][0] B10[7][0] ymm14 = _mm256_loadu_pd((double const *)(b10 + cs_b)); //B10[0][1] B10[1][1] B10[2][1] B10[3][1] ymm15 = _mm256_loadu_pd((double const *)(b10 + cs_b + D_NR));//B10[4][1] B10[5][1] B10[6][1] B10[7][1] ymm2 = _mm256_fmadd_pd(ymm10, ymm12, ymm2); //ymm2 += (B10[0][0]*A01[0][2] B10[1][0]*A01[0][2] B10[2][0]*A01[0][2] B10[3][0]*A01[0][2]) ymm3 = _mm256_fmadd_pd(ymm11, ymm12, ymm3); //ymm3 += (B10[0][0]*A01[0][3] B10[1][0]*A01[0][3] B10[2][0]*A01[0][3] B10[3][0]*A01[0][3]) ymm6 = _mm256_fmadd_pd(ymm10, ymm13, ymm6); //ymm6 += (B10[4][0]*A01[0][2] B10[5][0]*A01[0][2] B10[6][0]*A01[0][2] B10[7][0]*A01[0][2]) ymm7 = _mm256_fmadd_pd(ymm11, ymm13, ymm7); //ymm7 += (B10[4][0]*A01[0][3] B10[5][0]*A01[0][3] B10[6][0]*A01[0][3] B10[7][0]*A01[0][3]) //broadcast 2nd row of A01 ymm10 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 2)); //A01[1][2] ymm11 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 3)); //A01[1][3] a01 += 1; //move to next row of A ymm2 = _mm256_fmadd_pd(ymm10, ymm14, ymm2); //ymm2 += (B10[0][1]*A01[0][2] B10[1][1]*A01[0][2] B10[2][1]*A01[0][2] B10[3][1]*A01[0][2]) ymm3 = _mm256_fmadd_pd(ymm11, ymm14, ymm3); //ymm3 += (B10[0][1]*A01[0][3] B10[1][1]*A01[0][3] B10[2][1]*A01[0][3] B10[3][1]*A01[0][3]) ymm6 = _mm256_fmadd_pd(ymm10, ymm15, ymm6); //ymm6 += (B10[4][1]*A01[0][2] B10[5][1]*A01[0][2] B10[6][1]*A01[0][2] B10[7][1]*A01[0][2]) ymm7 = _mm256_fmadd_pd(ymm11, ymm15, ymm7); //ymm7 += (B10[4][1]*A01[0][3] B10[5][1]*A01[0][3] B10[6][1]*A01[0][3] B10[7][1]*A01[0][3]) //broadcast 3rd row of A01 ymm10 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 2)); //A01[2][2] ymm11 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 3)); //A01[2][3] a01 += 1; //move to next row of A //load next 8x2 block of B10 ymm12 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0])); //(B10[0][2] B10[1][2] B10[2][2] B10[3][2]) ymm13 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + D_NR)); //(B10[4][2] B10[5][2] B10[6][2] B10[7][2]) ymm14 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + cs_b)); //(B10[0][3] B10[1][3] B10[2][3] B10[3][3]) ymm15 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + cs_b + D_NR)); //(B10[4][3] B10[5][3] B10[6][3] B10[7][3]) ymm2 = _mm256_fmadd_pd(ymm10, ymm12, ymm2); //ymm2 += (B10[0][2]*A01[0][2] B10[1][2]*A01[0][2] B10[2][2]*A01[0][2] B10[3][2]*A01[0][2]) ymm3 = _mm256_fmadd_pd(ymm11, ymm12, ymm3); //ymm3 += (B10[0][2]*A01[0][3] B10[1][2]*A01[0][3] B10[2][2]*A01[0][3] B10[3][2]*A01[0][3]) ymm6 = _mm256_fmadd_pd(ymm10, ymm13, ymm6); //ymm6 += (B10[4][2]*A01[0][2] B10[5][2]*A01[0][2] B10[6][2]*A01[0][2] B10[7][2]*A01[0][2]) ymm7 = _mm256_fmadd_pd(ymm11, ymm13, ymm7); //ymm7 += (B10[4][2]*A01[0][3] B10[5][2]*A01[0][3] B10[6][2]*A01[0][3] B10[7][2]*A01[0][3]) //broadcast 4th row of A01 ymm10 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 2)); //A01[3][2] ymm11 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 3)); //A01[3][3] a01 += 1; //move to next row of A ymm2 = _mm256_fmadd_pd(ymm10, ymm14, ymm2); //ymm2 += (B10[0][3]*A01[0][2] B10[1][3]*A01[0][2] B10[2][3]*A01[0][2] B10[3][3]*A01[0][2]) ymm3 = _mm256_fmadd_pd(ymm11, ymm14, ymm3); //ymm3 += (B10[0][3]*A01[0][3] B10[1][3]*A01[0][3] B10[2][3]*A01[0][3] B10[3][3]*A01[0][3]) ymm6 = _mm256_fmadd_pd(ymm10, ymm15, ymm6); //ymm6 += (B10[4][3]*A01[0][2] B10[5][3]*A01[0][2] B10[6][3]*A01[0][2] B10[7][3]*A01[0][2]) ymm7 = _mm256_fmadd_pd(ymm11, ymm15, ymm7); //ymm7 += (B10[4][3]*A01[0][3] B10[5][3]*A01[0][3] B10[6][3]*A01[0][3] B10[7][3]*A01[0][3]) b10 += D_NR * cs_b; //pointer math to find next block of B for GEMM a01 = ptr_a01_dup + D_NR; //pointer math to find next block of A for GEMM } ///GEMM code ends/// ymm8 = _mm256_broadcast_sd((double const *)&AlphaVal); ymm10 = _mm256_loadu_pd((double const *)(b11 + cs_b_offset[0])); //B11[0-3][0] ymm14 = _mm256_loadu_pd((double const *)(b11 + cs_b_offset[0] + D_NR)); //B11[4-7][0] ymm11 = _mm256_loadu_pd((double const *)(b11 + cs_b_offset[1])); //B11[0-3][1] ymm15 = _mm256_loadu_pd((double const *)(b11 + cs_b_offset[1] + D_NR)); //B11[4-7][1] ymm10 = _mm256_fmsub_pd(ymm10, ymm8, ymm2); //B11[0-3][1] * alpha -= B10[0-3][1] ymm11 = _mm256_fmsub_pd(ymm11, ymm8, ymm3); //B11[4-7][1] * alpha -= B10[4-7][1] ymm14 = _mm256_fmsub_pd(ymm14, ymm8, ymm6); //B11[0-3][3] * alpha -= B10[0-3][3] ymm15 = _mm256_fmsub_pd(ymm15, ymm8, ymm7); //B11[4-7][3] * alpha -= B10[4-7][3] ///implement TRSM/// ///read 4x4 block of A11/// //4th col a11 += 3; ymm6 = _mm256_broadcast_sd((double const *)(a11+ cs_a * 2)); //A11[2][3] //(row 3):FMA operations ymm10 = _mm256_fnmadd_pd(ymm11, ymm6, ymm10); ymm14 = _mm256_fnmadd_pd(ymm15, ymm6, ymm14); _mm256_storeu_pd((double *)(b11 + cs_b_offset[0]), ymm10); //store(B11[0-3][1]) _mm256_storeu_pd((double *)(b11 + cs_b_offset[0] + D_NR), ymm14); //store(B11[4-7][1]) _mm256_storeu_pd((double *)(b11 + cs_b_offset[1]), ymm11); //store(B11[0-3][0]) _mm256_storeu_pd((double *)(b11 + cs_b_offset[1] + D_NR), ymm15); //store(B11[4-7][0]) } else if(1 == n_remainder) { ///GEMM implementation begins/// for(k = 0; k < k_iter; k++) ///loop for number of GEMM operations { ptr_a01_dup = a01; //broadcast 1st row of A01 ymm11 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 3)); //A01[0][3] a01 += 1; //move to next row of A //load 8x2 block of B10 ymm12 = _mm256_loadu_pd((double const *)b10); //B10[0][0] B10[1][0] B10[2][0] B10[3][0] ymm13 = _mm256_loadu_pd((double const *)(b10 + D_NR)); //B10[4][0] B10[5][0] B10[6][0] B10[7][0] ymm14 = _mm256_loadu_pd((double const *)(b10 + cs_b)); //B10[0][1] B10[1][1] B10[2][1] B10[3][1] ymm15 = _mm256_loadu_pd((double const *)(b10 + cs_b + D_NR));//B10[4][1] B10[5][1] B10[6][1] B10[7][1] ymm3 = _mm256_fmadd_pd(ymm11, ymm12, ymm3); //ymm3 += (B10[0][0]*A01[0][3] B10[1][0]*A01[0][3] B10[2][0]*A01[0][3] B10[3][0]*A01[0][3]) ymm7 = _mm256_fmadd_pd(ymm11, ymm13, ymm7); //ymm7 += (B10[4][0]*A01[0][3] B10[5][0]*A01[0][3] B10[6][0]*A01[0][3] B10[7][0]*A01[0][3]) //broadcast 2nd row of A01 ymm11 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 3)); //A01[1][3] a01 += 1; //move to next row of A ymm3 = _mm256_fmadd_pd(ymm11, ymm14, ymm3); //ymm3 += (B10[0][1]*A01[0][3] B10[1][1]*A01[0][3] B10[2][1]*A01[0][3] B10[3][1]*A01[0][3]) ymm7 = _mm256_fmadd_pd(ymm11, ymm15, ymm7); //ymm7 += (B10[4][1]*A01[0][3] B10[5][1]*A01[0][3] B10[6][1]*A01[0][3] B10[7][1]*A01[0][3]) //broadcast 3rd row of A01 ymm11 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 3)); //A01[2][3] a01 += 1; //move to next row of A //load next 8x2 block of B10 ymm12 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0])); //(B10[0][2] B10[1][2] B10[2][2] B10[3][2]) ymm13 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + D_NR)); //(B10[4][2] B10[5][2] B10[6][2] B10[7][2]) ymm14 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + cs_b)); //(B10[0][3] B10[1][3] B10[2][3] B10[3][3]) ymm15 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + cs_b + D_NR)); //(B10[4][3] B10[5][3] B10[6][3] B10[7][3]) ymm3 = _mm256_fmadd_pd(ymm11, ymm12, ymm3); //ymm3 += (B10[0][2]*A01[0][3] B10[1][2]*A01[0][3] B10[2][2]*A01[0][3] B10[3][2]*A01[0][3]) ymm7 = _mm256_fmadd_pd(ymm11, ymm13, ymm7); //ymm7 += (B10[4][2]*A01[0][3] B10[5][2]*A01[0][3] B10[6][2]*A01[0][3] B10[7][2]*A01[0][3]) //broadcast 4th row of A01 ymm11 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 3)); //A01[3][3] a01 += 1; //move to next row of A ymm3 = _mm256_fmadd_pd(ymm11, ymm14, ymm3); //ymm3 += (B10[0][3]*A01[0][3] B10[1][3]*A01[0][3] B10[2][3]*A01[0][3] B10[3][3]*A01[0][3]) ymm7 = _mm256_fmadd_pd(ymm11, ymm15, ymm7); //ymm7 += (B10[4][3]*A01[0][3] B10[5][3]*A01[0][3] B10[6][3]*A01[0][3] B10[7][3]*A01[0][3]) b10 += D_NR * cs_b; //pointer math to find next block of B for GEMM a01 = ptr_a01_dup + D_NR; //pointer math to find next block of A for GEMM } ///GEMM code ends/// ymm8 = _mm256_broadcast_sd((double const *)&AlphaVal); ymm11 = _mm256_loadu_pd((double const *)(b11+cs_b_offset[1])); //B11[0-3][0] ymm15 = _mm256_loadu_pd((double const *)(b11 + cs_b_offset[1] +D_NR)); //B11[4-7][0] ymm11 = _mm256_fmsub_pd(ymm11, ymm8, ymm3); //B11[4-7][1] * alpha -= B10[4-7][1] ymm15 = _mm256_fmsub_pd(ymm15, ymm8, ymm7); //B11[4-7][3] * alpha -= B10[4-7][3] _mm256_storeu_pd((double *)(b11+ cs_b_offset[1]), ymm11); //store(B11[0-3][0]) _mm256_storeu_pd((double *)(b11 + cs_b_offset[1] + D_NR), ymm15); //store(B11[4-7][0]) } } } if(i<0) i += D_NR; if((m & 4)) ///implementation for remainder rows(when m_remainder is greater than 4) { for(j = (n-D_NR); (j+1) > 0; j -=D_NR) //loop along n direction { a01 = L + j*cs_a + (j+D_NR); //pointer to block of A to be used for GEMM a11 = L + j*cs_a + j; //pointer to block of A to be used for TRSM b10 = B + i + (j+D_NR)*cs_b; //pointer to block of B to be used for GEMM b11 = B + i + j*cs_b; //pointer to block of B to be used for TRSM k_iter = (n-j-D_NR) / D_NR; //number of times GEMM operations to be performed(in blocks of 4x4) ///GEMM for previous blocks /// ///load 4x4 block of b11 ymm0 = _mm256_loadu_pd((double const *)b11); //B11[0][0] B11[1][0] B11[2][0] B11[3][0] ymm1 = _mm256_loadu_pd((double const *)(b11 + cs_b)); //B11[0][1] B11[1][1] B11[2][1] B11[3][1] ymm2 = _mm256_loadu_pd((double const *)(b11 + cs_b_offset[0])); //B11[0][2] B11[1][2] B11[2][2] B11[3][2] ymm3 = _mm256_loadu_pd((double const *)(b11 + cs_b_offset[1])); //B11[0][3] B11[1][3] B11[2][3] B11[3][3] ymm4 = _mm256_setzero_pd(); ymm5 = _mm256_setzero_pd(); ymm6 = _mm256_setzero_pd(); ymm7 = _mm256_setzero_pd(); ///GEMM implementation starts/// for(k = 0; k < k_iter; k++) //loop for number of GEMM operations { ptr_a01_dup = a01; //load 4x4 bblock of b10 ymm8 = _mm256_loadu_pd((double const *)b10); //B10[0][0] B10[1][0] B10[2][0] B10[3][0] ymm9 = _mm256_loadu_pd((double const *)(b10 + cs_b)); //B10[0][1] B10[1][1] B10[2][1] B10[3][1] ymm10 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0])); //B10[0][2] B10[1][2] B10[2][2] B10[3][2] ymm11 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[1])); //B10[0][3] B10[1][3] B10[2][3] B10[3][3] //broadcast 1st row of A01 ymm12 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 0)); //A01[0][0] ymm13 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 1)); //A01[0][1] ymm14 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 2)); //A01[0][2] ymm15 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 3)); //A01[0][3] a01 += 1; //move to next row of A ymm4 = _mm256_fmadd_pd(ymm12, ymm8, ymm4); //ymm4 += (B10[0][0]*A01[0][0] B10[1][0]*A01[0][0] B10[2][0]*A01[0][0] B10[3][0]*A01[0][0]) ymm5 = _mm256_fmadd_pd(ymm13, ymm8, ymm5); //ymm5 += (B10[0][0]*A01[0][1] B10[1][0]*A01[0][1] B10[2][0]*A01[0][1] B10[3][0]*A01[0][1]) ymm6 = _mm256_fmadd_pd(ymm14, ymm8, ymm6); //ymm6 += (B10[0][0]*A01[0][2] B10[1][0]*A01[0][2] B10[2][0]*A01[0][2] B10[3][0]*A01[0][2]) ymm7 = _mm256_fmadd_pd(ymm15, ymm8, ymm7); //ymm7 += (B10[0][0]*A01[0][3] B10[1][0]*A01[0][3] B10[2][0]*A01[0][3] B10[3][0]*A01[0][3]) //broadcast 2nd row of A01 ymm12 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 0)); //A01[1][0] ymm13 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 1)); //A01[1][1] ymm14 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 2)); //A01[1][2] ymm15 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 3)); //A01[1][3] a01 += 1; //move to next row of A ymm4 = _mm256_fmadd_pd(ymm12, ymm9, ymm4); //ymm4 += (B10[0][1]*A01[1][0] B10[1][1]*A01[1][0] B10[2][1]*A01[1][0] B10[3][1]*A01[1][0]) ymm5 = _mm256_fmadd_pd(ymm13, ymm9, ymm5); //ymm5 += (B10[0][1]*A01[1][1] B10[1][1]*A01[1][1] B10[2][1]*A01[1][1] B10[3][1]*A01[1][1]) ymm6 = _mm256_fmadd_pd(ymm14, ymm9, ymm6); //ymm6 += (B10[0][1]*A01[1][2] B10[1][1]*A01[1][2] B10[2][1]*A01[1][2] B10[3][1]*A01[1][2]) ymm7 = _mm256_fmadd_pd(ymm15, ymm9, ymm7); //ymm7 += (B10[0][1]*A01[1][3] B10[1][1]*A01[1][3] B10[2][1]*A01[1][3] B10[3][1]*A01[1][3]) //braodcast 3rd row of A01 ymm12 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 0)); //A01[2][0] ymm13 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 1)); //A01[2][1] ymm14 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 2)); //A01[2][2] ymm15 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 3)); //A01[2][3] a01 += 1; //move to next row of A ymm4 = _mm256_fmadd_pd(ymm12, ymm10, ymm4); //ymm4 += (B10[0][2]*A01[2][0] B10[1][2]*A01[2][0] B10[2][2]*A01[2][0] B10[3][2]*A01[2][0]) ymm5 = _mm256_fmadd_pd(ymm13, ymm10, ymm5); //ymm5 += (B10[0][2]*A01[2][1] B10[1][2]*A01[2][1] B10[2][2]*A01[2][1] B10[3][2]*A01[2][1]) ymm6 = _mm256_fmadd_pd(ymm14, ymm10, ymm6); //ymm6 += (B10[0][2]*A01[2][2] B10[1][2]*A01[2][2] B10[2][2]*A01[2][2] B10[3][2]*A01[2][2]) ymm7 = _mm256_fmadd_pd(ymm15, ymm10, ymm7); //ymm7 += (B10[0][2]*A01[2][3] B10[1][2]*A01[2][3] B10[2][2]*A01[2][3] B10[3][2]*A01[2][3]) //broadcast 4th row of A01 ymm12 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 0)); //A01[3][0] ymm13 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 1)); //A01[3][1] ymm14 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 2)); //A01[3][2] ymm15 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 3)); //A01[3][3] a01 += 1; //move to next row of A ymm4 = _mm256_fmadd_pd(ymm12, ymm11, ymm4); //ymm4 += (B10[0][3]*A01[3][0] B10[1][3]*A01[3][0] B10[2][3]*A01[3][0] B10[3][3]*A01[3][0]) ymm5 = _mm256_fmadd_pd(ymm13, ymm11, ymm5); //ymm5 += (B10[0][3]*A01[3][1] B10[1][3]*A01[3][1] B10[2][3]*A01[3][1] B10[3][3]*A01[3][1]) ymm6 = _mm256_fmadd_pd(ymm14, ymm11, ymm6); //ymm6 += (B10[0][3]*A01[3][2] B10[1][3]*A01[3][2] B10[2][3]*A01[3][2] B10[3][3]*A01[3][2]) ymm7 = _mm256_fmadd_pd(ymm15, ymm11, ymm7); //ymm7 += (B10[0][3]*A01[3][3] B10[1][3]*A01[3][3] B10[2][3]*A01[3][3] B10[3][3]*A01[3][3]) b10 += D_NR * cs_b; //pointer math to find next block of B for GEMM a01 = ptr_a01_dup + D_NR; //pointer math to find next block of A for GEMM } ///GEMM code end/// ymm15 = _mm256_broadcast_sd((double const *)&AlphaVal); //register to store alpha ymm0 = _mm256_fmsub_pd(ymm0, ymm15, ymm4); //B11[x][0] -=ymm4 ymm1 = _mm256_fmsub_pd(ymm1, ymm15, ymm5); //B11[x][1] -= ymm5 ymm2 = _mm256_fmsub_pd(ymm2, ymm15, ymm6); //B11[x][2] -= ymm6 ymm3 = _mm256_fmsub_pd(ymm3, ymm15, ymm7); //B11[x][3] -= ymm7 ///implement TRSM/// ///read 4x4 block of A11/// //1st col ymm5 = _mm256_broadcast_sd((double const *)(a11+1)); //A11[0][0] ymm6 = _mm256_broadcast_sd((double const *)(a11+2)); //A11[0][0] ymm7 = _mm256_broadcast_sd((double const *)(a11+3)); //A11[0][0] //2nd col a11 += cs_a; ymm9 = _mm256_broadcast_sd((double const *)(a11+2)); //A11[1][1] ymm10 = _mm256_broadcast_sd((double const *)(a11+3)); //A11[1][1] //3rd col a11 += cs_a; ymm12 = _mm256_broadcast_sd((double const *)(a11+3)); //A11[1][2] //(Row 3): FMA operations ymm2 = _mm256_fnmadd_pd(ymm3, ymm12, ymm2); ymm1 = _mm256_fnmadd_pd(ymm3, ymm10, ymm1); ymm0 = _mm256_fnmadd_pd(ymm3, ymm7, ymm0); //(ROW 2): FMA operations ymm1 = _mm256_fnmadd_pd(ymm2, ymm9, ymm1); ymm0 = _mm256_fnmadd_pd(ymm2, ymm6, ymm0); //(Row 1):FMA operations ymm0 = _mm256_fnmadd_pd(ymm1, ymm5, ymm0); _mm256_storeu_pd((double *)b11, ymm0); //store(B11[x][0]) _mm256_storeu_pd((double *)(b11 + cs_b), ymm1); //store(B11[x][1]) _mm256_storeu_pd((double *)(b11 + cs_b_offset[0]), ymm2); //(store(B11[x][2])) _mm256_storeu_pd((double *)(b11 + cs_b_offset[1]), ymm3); //store(B11[x][3]) } if(n_remainder) //implementation for remainder columns(when n is not a multiple of D_NR) { a01 = L + j*cs_a + (j+D_NR); //pointer to block of A to be used for GEMM a11 = L + j*cs_a + j; //pointwr to block of A to be used for TRSM b10 = B + i + (j+D_NR)*cs_b; //pointer to block of B to be used for GEMM b11 = B + i + j*cs_b; //pointer to block of B to be used for TRSM k_iter = (n-j-D_NR) / D_NR; //number of times GEMM operations to be performed(in blocks of 4x4) ymm4 = _mm256_setzero_pd(); ymm5 = _mm256_setzero_pd(); ymm6 = _mm256_setzero_pd(); ymm7 = _mm256_setzero_pd(); ///GEMM for previous blocks /// if(3 == n_remainder) { ///load 4x4 block of b11 ymm1 = _mm256_loadu_pd((double const *)b11+ cs_b); //B11[0][0] B11[1][0] B11[2][0] B11[3][0] ymm2 = _mm256_loadu_pd((double const *)(b11 + cs_b * 2)); //B11[0][1] B11[1][1] B11[2][1] B11[3][1] ymm3 = _mm256_loadu_pd((double const *)(b11 + cs_b * 3)); //B11[0][2] B11[1][2] B11[2][2] B11[3][2] ///GEMM processing stars/// for(k = 0; k < k_iter; k++) { ptr_a01_dup = a01; //load 4x4 bblock of b10 ymm8 = _mm256_loadu_pd((double const *)b10); //B10[0][0] B10[1][0] B10[2][0] B10[3][0] ymm9 = _mm256_loadu_pd((double const *)(b10 + cs_b)); //B10[0][1] B10[1][1] B10[2][1] B10[3][1] ymm10 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0])); //B10[0][2] B10[1][2] B10[2][2] B10[3][2] ymm11 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[1])); //B10[0][3] B10[1][3] B10[2][3] B10[3][3] //broadcast 1st row of A01 ymm13 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 1)); //A01[0][1] ymm14 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 2)); //A01[0][2] ymm15 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 3)); //A01[0][3] a01 += 1; //move to next row of A ymm5 = _mm256_fmadd_pd(ymm13, ymm8, ymm5); //ymm5 += (B10[0][0]*A01[0][1] B10[1][0]*A01[0][1] B10[2][0]*A01[0][1] B10[3][0]*A01[0][1]) ymm6 = _mm256_fmadd_pd(ymm14, ymm8, ymm6); //ymm6 += (B10[0][0]*A01[0][2] B10[1][0]*A01[0][2] B10[2][0]*A01[0][2] B10[3][0]*A01[0][2]) ymm7 = _mm256_fmadd_pd(ymm15, ymm8, ymm7); //ymm7 += (B10[0][0]*A01[0][3] B10[1][0]*A01[0][3] B10[2][0]*A01[0][3] B10[3][0]*A01[0][3]) //broadcast 2nd row of A01 ymm13 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 1)); //A01[1][1] ymm14 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 2)); //A01[1][2] ymm15 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 3)); //A01[1][3] a01 += 1; //move to next row of A ymm5 = _mm256_fmadd_pd(ymm13, ymm9, ymm5); //ymm5 += (B10[0][1]*A01[1][1] B10[1][1]*A01[1][1] B10[2][1]*A01[1][1] B10[3][1]*A01[1][1]) ymm6 = _mm256_fmadd_pd(ymm14, ymm9, ymm6); //ymm6 += (B10[0][1]*A01[1][2] B10[1][1]*A01[1][2] B10[2][1]*A01[1][2] B10[3][1]*A01[1][2]) ymm7 = _mm256_fmadd_pd(ymm15, ymm9, ymm7); //ymm7 += (B10[0][1]*A01[1][3] B10[1][1]*A01[1][3] B10[2][1]*A01[1][3] B10[3][1]*A01[1][3]) //braodcast 3rd row of A01 ymm13 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 1)); //A01[2][1] ymm14 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 2)); //A01[2][2] ymm15 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 3)); //A01[2][3] a01 += 1; //move to next row of A ymm5 = _mm256_fmadd_pd(ymm13, ymm10, ymm5); //ymm5 += (B10[0][2]*A01[2][1] B10[1][2]*A01[2][1] B10[2][2]*A01[2][1] B10[3][2]*A01[2][1]) ymm6 = _mm256_fmadd_pd(ymm14, ymm10, ymm6); //ymm6 += (B10[0][2]*A01[2][2] B10[1][2]*A01[2][2] B10[2][2]*A01[2][2] B10[3][2]*A01[2][2]) ymm7 = _mm256_fmadd_pd(ymm15, ymm10, ymm7); //ymm7 += (B10[0][2]*A01[2][3] B10[1][2]*A01[2][3] B10[2][2]*A01[2][3] B10[3][2]*A01[2][3]) //broadcast 4th row of A01 ymm13 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 1)); //A01[3][1] ymm14 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 2)); //A01[3][2] ymm15 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 3)); //A01[3][3] a01 += 1; //move to next row of A ymm5 = _mm256_fmadd_pd(ymm13, ymm11, ymm5); //ymm5 += (B10[0][3]*A01[3][1] B10[1][3]*A01[3][1] B10[2][3]*A01[3][1] B10[3][3]*A01[3][1]) ymm6 = _mm256_fmadd_pd(ymm14, ymm11, ymm6); //ymm6 += (B10[0][3]*A01[3][2] B10[1][3]*A01[3][2] B10[2][3]*A01[3][2] B10[3][3]*A01[3][2]) ymm7 = _mm256_fmadd_pd(ymm15, ymm11, ymm7); //ymm7 += (B10[0][3]*A01[3][3] B10[1][3]*A01[3][3] B10[2][3]*A01[3][3] B10[3][3]*A01[3][3]) b10 += D_NR * cs_b; //pointer math to find next block of B for GEMM a01 = ptr_a01_dup + D_NR; //pointer math to find next block of A for GEMM } ///GEMM code ends/// ymm15 = _mm256_broadcast_sd((double const *)&AlphaVal); //register to store alpha value ymm1 = _mm256_fmsub_pd(ymm1, ymm15, ymm5); //B11[x][1] -= ymm5 ymm2 = _mm256_fmsub_pd(ymm2, ymm15, ymm6); //B11[x][2] -= ymm6 ymm3 = _mm256_fmsub_pd(ymm3, ymm15, ymm7); //B11[x][3] -= ymm7 ///implement TRSM/// ///read 4x4 block of A11/// //2nd col a11 += cs_a; ymm9 = _mm256_broadcast_sd((double const *)(a11+2)); //A11[1][1] ymm10 = _mm256_broadcast_sd((double const *)(a11+3)); //A11[1][1] //3rd col a11 += cs_a; ymm12 = _mm256_broadcast_sd((double const *)(a11+3)); //A11[1][2] //(Row 3): FMA operations ymm2 = _mm256_fnmadd_pd(ymm3, ymm12, ymm2); ymm1 = _mm256_fnmadd_pd(ymm3, ymm10, ymm1); //(ROW 2): FMA operations ymm1 = _mm256_fnmadd_pd(ymm2, ymm9, ymm1); _mm256_storeu_pd((double *)(b11 + cs_b), ymm1); //store(B11[x][1]) _mm256_storeu_pd((double *)(b11 + cs_b_offset[0]), ymm2); //(store(B11[x][2])) _mm256_storeu_pd((double *)(b11 + cs_b*3), ymm3); //store(B11[x][0]) } else if(2 == n_remainder) { ymm2 = _mm256_loadu_pd((double const *)(b11 + cs_b * 2)); //B11[0][0] B11[1][0] B11[2][0] B11[3][0] ymm3 = _mm256_loadu_pd((double const *)(b11 + cs_b * 3)); //B11[0][1] B11[1][1] B11[2][1] B11[3][1] ///GEMM processing stars/// for(k = 0; k < k_iter; k++) { ptr_a01_dup = a01; //load 4x4 bblock of b10 ymm8 = _mm256_loadu_pd((double const *)b10); //B10[0][0] B10[1][0] B10[2][0] B10[3][0] ymm9 = _mm256_loadu_pd((double const *)(b10 + cs_b)); //B10[0][1] B10[1][1] B10[2][1] B10[3][1] ymm10 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0])); //B10[0][2] B10[1][2] B10[2][2] B10[3][2] ymm11 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[1])); //B10[0][3] B10[1][3] B10[2][3] B10[3][3] //broadcast 1st row of A01 ymm14 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 2)); //A01[0][2] ymm15 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 3)); //A01[0][3] a01 += 1; //move to next row of A ymm6 = _mm256_fmadd_pd(ymm14, ymm8, ymm6); //ymm6 += (B10[0][0]*A01[0][2] B10[1][0]*A01[0][2] B10[2][0]*A01[0][2] B10[3][0]*A01[0][2]) ymm7 = _mm256_fmadd_pd(ymm15, ymm8, ymm7); //ymm7 += (B10[0][0]*A01[0][3] B10[1][0]*A01[0][3] B10[2][0]*A01[0][3] B10[3][0]*A01[0][3]) //broadcast 2nd row of A01 ymm14 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 2)); //A01[1][2] ymm15 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 3)); //A01[1][3] a01 += 1; //move to next row of A ymm6 = _mm256_fmadd_pd(ymm14, ymm9, ymm6); //ymm6 += (B10[0][1]*A01[1][2] B10[1][1]*A01[1][2] B10[2][1]*A01[1][2] B10[3][1]*A01[1][2]) ymm7 = _mm256_fmadd_pd(ymm15, ymm9, ymm7); //ymm7 += (B10[0][1]*A01[1][3] B10[1][1]*A01[1][3] B10[2][1]*A01[1][3] B10[3][1]*A01[1][3]) //braodcast 3rd row of A01 ymm14 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 2)); //A01[2][2] ymm15 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 3)); //A01[2][3] a01 += 1; //move to next row of A ymm6 = _mm256_fmadd_pd(ymm14, ymm10, ymm6); //ymm6 += (B10[0][2]*A01[2][2] B10[1][2]*A01[2][2] B10[2][2]*A01[2][2] B10[3][2]*A01[2][2]) ymm7 = _mm256_fmadd_pd(ymm15, ymm10, ymm7); //ymm7 += (B10[0][2]*A01[2][3] B10[1][2]*A01[2][3] B10[2][2]*A01[2][3] B10[3][2]*A01[2][3]) //broadcast 4th row of A01 ymm14 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 2)); //A01[3][2] ymm15 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 3)); //A01[3][3] a01 += 1; //move to next row of A ymm6 = _mm256_fmadd_pd(ymm14, ymm11, ymm6); //ymm6 += (B10[0][3]*A01[3][2] B10[1][3]*A01[3][2] B10[2][3]*A01[3][2] B10[3][3]*A01[3][2]) ymm7 = _mm256_fmadd_pd(ymm15, ymm11, ymm7); //ymm7 += (B10[0][3]*A01[3][3] B10[1][3]*A01[3][3] B10[2][3]*A01[3][3] B10[3][3]*A01[3][3]) b10 += D_NR * cs_b; //pointer math to find next block of B for GEMM a01 = ptr_a01_dup + D_NR; //pointer math to find next block of A for GEMM } ///GEMM code ends/// ymm15 = _mm256_broadcast_sd((double const *)&AlphaVal); //register to store alpha value ymm2 = _mm256_fmsub_pd(ymm2, ymm15, ymm6); //B11[x][2] -= ymm6 ymm3 = _mm256_fmsub_pd(ymm3, ymm15, ymm7); //B11[x][3] -= ymm7 ///implement TRSM/// ///read 4x4 block of A11/// //3rd col a11 += 2 * cs_a; ymm12 = _mm256_broadcast_sd((double const *)(a11+3)); //A11[1][2] //(Row 3): FMA operations ymm2 = _mm256_fnmadd_pd(ymm3, ymm12, ymm2); _mm256_storeu_pd((double *)(b11+ cs_b * 2), ymm2); //store(B11[x][0]) _mm256_storeu_pd((double *)(b11 + cs_b * 3), ymm3); //store(B11[x][1]) } else if(1 == n_remainder) { ymm3 = _mm256_loadu_pd((double const *)(b11 + cs_b * 3)); //B11[0][0] B11[1][0] B11[2][0] B11[3][0] ///GEMM processing stars/// for(k = 0; k < k_iter; k++) { ptr_a01_dup = a01; //load 4x4 bblock of b10 ymm8 = _mm256_loadu_pd((double const *)b10); //B10[0][0] B10[1][0] B10[2][0] B10[3][0] ymm9 = _mm256_loadu_pd((double const *)(b10 + cs_b)); //B10[0][1] B10[1][1] B10[2][1] B10[3][1] ymm10 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0])); //B10[0][2] B10[1][2] B10[2][2] B10[3][2] ymm11 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[1])); //B10[0][3] B10[1][3] B10[2][3] B10[3][3] //broadcast 1st row of A01 ymm15 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 3)); //A01[0][3] a01 += 1; //move to next row of A ymm7 = _mm256_fmadd_pd(ymm15, ymm8, ymm7); //ymm7 += (B10[0][0]*A01[0][3] B10[1][0]*A01[0][3] B10[2][0]*A01[0][3] B10[3][0]*A01[0][3]) //broadcast 2nd row of A01 ymm15 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 3)); //A01[1][3] a01 += 1; //move to next row of A ymm7 = _mm256_fmadd_pd(ymm15, ymm9, ymm7); //ymm7 += (B10[0][1]*A01[1][3] B10[1][1]*A01[1][3] B10[2][1]*A01[1][3] B10[3][1]*A01[1][3]) //braodcast 3rd row of A01 ymm15 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 3)); //A01[2][3] a01 += 1; //move to next row of A ymm7 = _mm256_fmadd_pd(ymm15, ymm10, ymm7); //ymm7 += (B10[0][2]*A01[2][3] B10[1][2]*A01[2][3] B10[2][2]*A01[2][3] B10[3][2]*A01[2][3]) //broadcast 4th row of A01 ymm15 = _mm256_broadcast_sd((double const *)(a01 + cs_a * 3)); //A01[3][3] a01 += 1; //move to next row of A ymm7 = _mm256_fmadd_pd(ymm15, ymm11, ymm7); //ymm7 += (B10[0][3]*A01[3][3] B10[1][3]*A01[3][3] B10[2][3]*A01[3][3] B10[3][3]*A01[3][3]) b10 += D_NR * cs_b; //pointer math to find next block of B for GEMM a01 = ptr_a01_dup + D_NR; //pointer math to find next block of A for GEMM } ///GEMM code ends/// ymm15 = _mm256_broadcast_sd((double const *)&AlphaVal); //register to store alpha value ymm3 = _mm256_fmsub_pd(ymm3, ymm15, ymm7); //B11[x][3] -= ymm7 _mm256_storeu_pd((double *)(b11 + cs_b * 3), ymm3); //store(B11[x][0]) } } m_remainder -= 4; i -= 4; } // if(i < 0) i = 0; if(m_remainder) ///implementation for remainder rows { dtrsm_small_XAlB_unitDiag(L, B, AlphaVal, m_remainder, n, cs_a, cs_b); } return BLIS_SUCCESS; } /*implements TRSM for the case XA = alpha * B *A is lower triangular, non-unit diagonal, no transpose *dimensions: X:mxn A:nxn B: mxn */ /* <---b11 <---a11 ***************** * *b01*b11* * * * * ^ * * * * * ^ * * | ***************** | ******* | * * * * * | * * * | * * * * * a01* * * b10 ***************** ************* * * * * * * * * * * * * * * * * * * ***************** ******************* */ static err_t bli_dtrsm_small_XAutB( side_t side, obj_t* AlphaObj, obj_t* a, obj_t* b, cntx_t* cntx, cntl_t* cntl ) { dim_t D_MR = 8; //block dimension along the rows dim_t D_NR = 4; //block dimension along the columns dim_t m = bli_obj_length(b); //number of rows dim_t n = bli_obj_width(b); //number of columns dim_t m_remainder = m & 7; //number of corner rows dim_t n_remainder = n & 3; //number of corner columns dim_t cs_a = bli_obj_col_stride(a); //column stride of matrix A dim_t cs_b = bli_obj_col_stride(b); //column stride of matrix B #ifdef BLIS_ENABLE_SMALL_MATRIX_ROME if((m < D_BLIS_SMALL_MATRIX_THRES_TRSM_XAUTB_ROME && n > D_BLIS_SMALL_MATRIX_THRES_TRSM_XAUTB_ROME) ||(m > D_BLIS_SMALL_MATRIX_THRES_TRSM_XAUTB_ROME && n > D_BLIS_SMALL_MATRIX_THRES_TRSM_XALB_ROME_COL_PANEL_N) ) return BLIS_NOT_YET_IMPLEMENTED; #else if(bli_max(m,n) > D_BLIS_SMALL_MATRIX_THRES_TRSM_NAPLES) { return BLIS_NOT_YET_IMPLEMENTED; } #endif dim_t i, j, k; //loop variablse dim_t k_iter; //determines the number of GEMM operations to be done dim_t cs_b_offset[2]; //pre-calculated strides double ones = 1.0; double AlphaVal = *(double *)AlphaObj->buffer; //value of Alpha double* restrict L = a->buffer; //pointer to matrix A double* restrict B = b->buffer; //pointer to matrix B double *a01, *a11, *b10, *b11; //pointers for GEMM and TRSM blocks double *ptr_a01_dup; cs_b_offset[0] = cs_b << 1; //cs_b_offset[0] = cs_b * 2; cs_b_offset[1] = cs_b_offset[0] + cs_b;//cs_b_offset[1] = cs_b * 3; //ymm scratch reginsters __m256d ymm0, ymm1, ymm2, ymm3; __m256d ymm4, ymm5, ymm6, ymm7; __m256d ymm8, ymm9, ymm10, ymm11; __m256d ymm12, ymm13, ymm14, ymm15; __m256d ymm16; for(i = (m-D_MR); (i+1) > 0; i -= D_MR) //loop along 'M' direction { for(j = (n-D_NR); (j+1) > 0; j -= D_NR) //loop along 'N' direction { a01 = L + (j+D_NR)*cs_a +(j); //pointer to block of A to be used in GEMM a11 = L + j*cs_a + j; //pointer to block of A to be used for TRSM b10 = B + i + (j+D_NR)*cs_b; //pointer to block of B to be used in GEMM b11 = B + (i) + (j)*cs_b; //pointer to block of B to be used for TRSM k_iter = (n-j-D_NR) / D_NR; //number of GEMM operations to be done(in blocks of 4x4) ymm0 = _mm256_setzero_pd(); ymm1 = _mm256_setzero_pd(); ymm2 = _mm256_setzero_pd(); ymm3 = _mm256_setzero_pd(); ymm4 = _mm256_setzero_pd(); ymm5 = _mm256_setzero_pd(); ymm6 = _mm256_setzero_pd(); ymm7 = _mm256_setzero_pd(); ///GEMM implementation starts/// for(k = 0; k < k_iter; k++) //loop for number of GEMM operations { ptr_a01_dup = a01; //broadcast 1st row of A01 ymm8 = _mm256_broadcast_sd((double const *)(a01 + 0)); //A01[0][0] ymm9 = _mm256_broadcast_sd((double const *)(a01 + 1)); //A01[0][1] ymm10 = _mm256_broadcast_sd((double const *)(a01 + 2)); //A01[0][2] ymm11 = _mm256_broadcast_sd((double const *)(a01 + 3)); //A01[0][3] a01 += cs_a; //move to next row //load 8x2 block of B10 ymm12 = _mm256_loadu_pd((double const *)b10); //B10[0][0] B10[1][0] B10[2][0] B10[3][0] ymm13 = _mm256_loadu_pd((double const *)(b10 + D_NR)); //B10[4][0] B10[5][0] B10[6][0] B10[7][0] ymm14 = _mm256_loadu_pd((double const *)(b10 + cs_b)); //B10[0][1] B10[1][1] B10[2][1] B10[3][1] ymm15 = _mm256_loadu_pd((double const *)(b10 + cs_b + D_NR)); //B10[4][1] B10[5][1] B10[6][1] B10[7][1] ymm0 = _mm256_fmadd_pd(ymm8, ymm12, ymm0); //ymm0 += (B10[0][0]*A01[0][0] B10[1][0]*A01[0][0] B10[2][0]*A01[0][0] B10[3][0]*A01[0][0]) ymm1 = _mm256_fmadd_pd(ymm9, ymm12, ymm1); //ymm1 += (B10[0][0]*A01[0][1] B10[1][0]*A01[0][1] B10[2][0]*A01[0][1] B10[3][0]*A01[0][1]) ymm2 = _mm256_fmadd_pd(ymm10, ymm12, ymm2); //ymm2 += (B10[0][0]*A01[0][2] B10[1][0]*A01[0][2] B10[2][0]*A01[0][2] B10[3][0]*A01[0][2]) ymm3 = _mm256_fmadd_pd(ymm11, ymm12, ymm3); //ymm3 += (B10[0][0]*A01[0][3] B10[1][0]*A01[0][3] B10[2][0]*A01[0][3] B10[3][0]*A01[0][3]) ymm4 = _mm256_fmadd_pd(ymm8, ymm13, ymm4); //ymm4 += (B10[4][0]*A01[0][0] B10[5][0]*A01[0][0] B10[6][0]*A01[0][0] B10[7][0]*A01[0][0]) ymm5 = _mm256_fmadd_pd(ymm9, ymm13, ymm5); //ymm5 += (B10[4][0]*A01[0][1] B10[5][0]*A01[0][1] B10[6][0]*A01[0][1] B10[7][0]*A01[0][1]) ymm6 = _mm256_fmadd_pd(ymm10, ymm13, ymm6); //ymm6 += (B10[4][0]*A01[0][2] B10[5][0]*A01[0][2] B10[6][0]*A01[0][2] B10[7][0]*A01[0][2]) ymm7 = _mm256_fmadd_pd(ymm11, ymm13, ymm7); //ymm7 += (B10[4][0]*A01[0][3] B10[5][0]*A01[0][3] B10[6][0]*A01[0][3] B10[7][0]*A01[0][3]) //broadcast 2nd row of A01 ymm8 = _mm256_broadcast_sd((double const *)(a01 + 0)); //A01[1][0] ymm9 = _mm256_broadcast_sd((double const *)(a01 + 1)); //A01[1][1] ymm10 = _mm256_broadcast_sd((double const *)(a01 + 2)); //A01[1][2] ymm11 = _mm256_broadcast_sd((double const *)(a01 + 3)); //A01[1][3] a01 += cs_a; //move to next row of A ymm0 = _mm256_fmadd_pd(ymm8, ymm14, ymm0); //ymm0 += (B10[0][1]*A01[0][0] B10[1][1]*A01[0][0] B10[2][1]*A01[0][0] B10[3][1]*A01[0][0]) ymm1 = _mm256_fmadd_pd(ymm9, ymm14, ymm1); //ymm1 += (B10[0][1]*A01[0][1] B10[1][1]*A01[0][1] B10[2][1]*A01[0][1] B10[3][1]*A01[0][1]) ymm2 = _mm256_fmadd_pd(ymm10, ymm14, ymm2); //ymm2 += (B10[0][1]*A01[0][2] B10[1][1]*A01[0][2] B10[2][1]*A01[0][2] B10[3][1]*A01[0][2]) ymm3 = _mm256_fmadd_pd(ymm11, ymm14, ymm3); //ymm3 += (B10[0][1]*A01[0][3] B10[1][1]*A01[0][3] B10[2][1]*A01[0][3] B10[3][1]*A01[0][3]) ymm4 = _mm256_fmadd_pd(ymm8, ymm15, ymm4); //ymm4 += (B10[4][1]*A01[0][0] B10[5][1]*A01[0][0] B10[6][1]*A01[0][0] B10[7][1]*A01[0][0]) ymm5 = _mm256_fmadd_pd(ymm9, ymm15, ymm5); //ymm5 += (B10[4][1]*A01[0][1] B10[5][1]*A01[0][1] B10[6][1]*A01[0][1] B10[7][1]*A01[0][1]) ymm6 = _mm256_fmadd_pd(ymm10, ymm15, ymm6); //ymm6 += (B10[4][1]*A01[0][2] B10[5][1]*A01[0][2] B10[6][1]*A01[0][2] B10[7][1]*A01[0][2]) ymm7 = _mm256_fmadd_pd(ymm11, ymm15, ymm7); //ymm7 += (B10[4][1]*A01[0][3] B10[5][1]*A01[0][3] B10[6][1]*A01[0][3] B10[7][1]*A01[0][3]) //broadcast 3rd row of A01 ymm8 = _mm256_broadcast_sd((double const *)(a01 + 0)); //A01[2][0] ymm9 = _mm256_broadcast_sd((double const *)(a01 + 1)); //A01[2][1] ymm10 = _mm256_broadcast_sd((double const *)(a01 + 2)); //A01[2][2] ymm11 = _mm256_broadcast_sd((double const *)(a01 + 3)); //A01[2][3] a01 += cs_a; //move to next row of A01 //load next 8x2 block of B10 ymm12 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0])); //(B10[0][2] B10[1][2] B10[2][2] B10[3][2]) ymm13 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + D_NR)); //(B10[4][2] B10[5][2] B10[6][2] B10[7][2]) ymm14 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + cs_b)); //(B10[0][3] B10[1][3] B10[2][3] B10[3][3]) ymm15 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + cs_b + D_NR)); //(B10[4][3] B10[5][3] B10[6][3] B10[7][3]) ymm0 = _mm256_fmadd_pd(ymm8, ymm12, ymm0); //ymm0 += (B10[0][2]*A01[0][0] B10[1][2]*A01[0][0] B10[2][2]*A01[0][0] B10[3][2]*A01[0][0]) ymm1 = _mm256_fmadd_pd(ymm9, ymm12, ymm1); //ymm1 += (B10[0][2]*A01[0][1] B10[1][2]*A01[0][1] B10[2][2]*A01[0][1] B10[3][2]*A01[0][1]) ymm2 = _mm256_fmadd_pd(ymm10, ymm12, ymm2); //ymm2 += (B10[0][2]*A01[0][2] B10[1][2]*A01[0][2] B10[2][2]*A01[0][2] B10[3][2]*A01[0][2]) ymm3 = _mm256_fmadd_pd(ymm11, ymm12, ymm3); //ymm3 += (B10[0][2]*A01[0][3] B10[1][2]*A01[0][3] B10[2][2]*A01[0][3] B10[3][2]*A01[0][3]) ymm4 = _mm256_fmadd_pd(ymm8, ymm13, ymm4); //ymm4 += (B10[4][2]*A01[0][0] B10[5][2]*A01[0][0] B10[6][2]*A01[0][0] B10[7][2]*A01[0][0]) ymm5 = _mm256_fmadd_pd(ymm9, ymm13, ymm5); //ymm5 += (B10[4][2]*A01[0][1] B10[5][2]*A01[0][1] B10[6][2]*A01[0][1] B10[7][2]*A01[0][1]) ymm6 = _mm256_fmadd_pd(ymm10, ymm13, ymm6); //ymm6 += (B10[4][2]*A01[0][2] B10[5][2]*A01[0][2] B10[6][2]*A01[0][2] B10[7][2]*A01[0][2]) ymm7 = _mm256_fmadd_pd(ymm11, ymm13, ymm7); //ymm7 += (B10[4][2]*A01[0][3] B10[5][2]*A01[0][3] B10[6][2]*A01[0][3] B10[7][2]*A01[0][3]) //broadcast 4th row of A01 ymm8 = _mm256_broadcast_sd((double const *)(a01 + 0)); //A01[3][0] ymm9 = _mm256_broadcast_sd((double const *)(a01 + 1)); //A01[3][1] ymm10 = _mm256_broadcast_sd((double const *)(a01 + 2)); //A01[3][2] ymm11 = _mm256_broadcast_sd((double const *)(a01 + 3)); //A01[3][3] a01 += cs_a; //move to next row of A01 ymm0 = _mm256_fmadd_pd(ymm8, ymm14, ymm0); //ymm0 += (B10[0][3]*A01[0][0] B10[1][3]*A01[0][0] B10[2][3]*A01[0][0] B10[3][3]*A01[0][0]) ymm1 = _mm256_fmadd_pd(ymm9, ymm14, ymm1); //ymm1 += (B10[0][3]*A01[0][1] B10[1][3]*A01[0][1] B10[2][3]*A01[0][1] B10[3][3]*A01[0][1]) ymm2 = _mm256_fmadd_pd(ymm10, ymm14, ymm2); //ymm2 += (B10[0][3]*A01[0][2] B10[1][3]*A01[0][2] B10[2][3]*A01[0][2] B10[3][3]*A01[0][2]) ymm3 = _mm256_fmadd_pd(ymm11, ymm14, ymm3); //ymm3 += (B10[0][3]*A01[0][3] B10[1][3]*A01[0][3] B10[2][3]*A01[0][3] B10[3][3]*A01[0][3]) ymm4 = _mm256_fmadd_pd(ymm8, ymm15, ymm4); //ymm4 += (B10[4][3]*A01[0][0] B10[5][3]*A01[0][0] B10[6][3]*A01[0][0] B10[7][3]*A01[0][0]) ymm5 = _mm256_fmadd_pd(ymm9, ymm15, ymm5); //ymm5 += (B10[4][3]*A01[0][1] B10[5][3]*A01[0][1] B10[6][3]*A01[0][1] B10[7][3]*A01[0][1]) ymm6 = _mm256_fmadd_pd(ymm10, ymm15, ymm6); //ymm6 += (B10[4][3]*A01[0][2] B10[5][3]*A01[0][2] B10[6][3]*A01[0][2] B10[7][3]*A01[0][2]) ymm7 = _mm256_fmadd_pd(ymm11, ymm15, ymm7); //ymm7 += (B10[4][3]*A01[0][3] B10[5][3]*A01[0][3] B10[6][3]*A01[0][3] B10[7][3]*A01[0][3]) b10 += D_NR * cs_b; //pointer math to find next block of B for GEMM a01 = ptr_a01_dup + (D_NR * cs_a); //pointer math to find next block of A for GEMM } ///GEMM code ends/// ymm16 = _mm256_broadcast_sd((double const *)&AlphaVal); //load 8x4 block of B11 ymm8 = _mm256_loadu_pd((double const *)b11); //B11[0][0] B11[1][0] B11[2][0] B11[3][0] ymm12 = _mm256_loadu_pd((double const *)(b11 + D_NR)); //B11[4][0] B11[5][0] B11[6][0] B11[7][0] ymm9 = _mm256_loadu_pd((double const *)(b11 + cs_b)); //B11[0][1] B11[1][1] B11[2][1] B11[3][1] ymm13 = _mm256_loadu_pd((double const *)(b11 + cs_b + D_NR)); //B11[4][1] B11[5][1] B11[6][1] B11[7][1] ymm10 = _mm256_loadu_pd((double const *)(b11 + cs_b_offset[0])); //B11[0][2] B11[1][2] B11[2][2] B11[3][2] ymm14 = _mm256_loadu_pd((double const *)(b11 + cs_b_offset[0] + D_NR)); //B11[4][2] B11[5][2] B11[6][2] B11[7][2] ymm11 = _mm256_loadu_pd((double const *)(b11 + cs_b_offset[1])); //B11[0][3] B11[1][3] B11[2][3] B11[3][3] ymm15 = _mm256_loadu_pd((double const *)(b11 + cs_b_offset[1] + D_NR)); //B11[4][3] B11[5][3] B11[6][3] B11[7][3] ymm8 = _mm256_fmsub_pd(ymm8, ymm16, ymm0); //B11[0-3][0] * alpha -= ymm0 ymm9 = _mm256_fmsub_pd(ymm9, ymm16, ymm1); //B11[4-7][0] * alpha-= ymm1 ymm10 = _mm256_fmsub_pd(ymm10, ymm16, ymm2); //B11[0-3][1] * alpha-= ymm2 ymm11 = _mm256_fmsub_pd(ymm11, ymm16, ymm3); //B11[4-7][1] * alpha -= ymm3 ymm12 = _mm256_fmsub_pd(ymm12, ymm16, ymm4); //B11[0-3][2] * alpha -= ymm4 ymm13 = _mm256_fmsub_pd(ymm13, ymm16, ymm5); //B11[4-7][2] * alpha -= ymm5 ymm14 = _mm256_fmsub_pd(ymm14, ymm16, ymm6); //B11[0-3][3] * alpha -= ymm6 ymm15 = _mm256_fmsub_pd(ymm15, ymm16, ymm7); //B11[4-7][3] * alpha -= ymm7 ///implement TRSM/// ///read 4x4 block of A11/// //1st col ymm0 = _mm256_broadcast_sd((double const *)(a11+0)); //A11[0][0] a11 += cs_a; //2nd col ymm1 = _mm256_broadcast_sd((double const *)(a11+0)); //A11[0][1] ymm2 = _mm256_broadcast_sd((double const *)(a11+1)); //A11[0][1] a11 += cs_a; //3rd col ymm3 = _mm256_broadcast_sd((double const *)(a11+0)); //A11[0][1] ymm4 = _mm256_broadcast_sd((double const *)(a11+1)); //A11[0][1] ymm5 = _mm256_broadcast_sd((double const *)(a11+2)); //A11[0][1] a11 += cs_a; //4th col ymm6 = _mm256_broadcast_sd((double const *)(a11+3)); //A11[0][1] ymm7 = _mm256_broadcast_sd((double const *)&ones); //compute reciprocals of A(i,i) and broadcast in registers ymm0 = _mm256_unpacklo_pd(ymm0, ymm2); //A11[0][0] A11[1][1] A11[0][0] A11[1][1] ymm2 = _mm256_unpacklo_pd(ymm5, ymm6); //A11[2][2] A11[3][3] A11[2][2] A11[3][3] ymm0 = _mm256_blend_pd(ymm0, ymm2, 0x0C); //A11[0][0] A11[1][1] A11[2][2] A11[3][3] ymm0 = _mm256_div_pd(ymm7, ymm0); // 1/A11[0][0] 1/A11[1][1] 1/A11[2][2] 1/A11[3][3] ymm2 = _mm256_broadcast_sd((double const *)(a11+0)); //A11[0][1] ymm5 = _mm256_broadcast_sd((double const *)(a11+1)); //A11[0][1] ymm6 = _mm256_broadcast_sd((double const *)(a11+2)); //A11[0][1] //extract a33 ymm7 = _mm256_permute_pd(ymm0, 0x0C); //(1/A11[0][0] 1/A11[0][0] 1/A11[3][3] 1/A11[3][3]) ymm7 = _mm256_permute2f128_pd(ymm7, ymm7, 0x11); //(1/A11[3][3] 1/A11[3][3] 1/A11[3][3] 1/A11[3][3]) ymm11 = _mm256_mul_pd(ymm11, ymm7); ymm15 = _mm256_mul_pd(ymm15, ymm7); //extract a22 ymm7 = _mm256_permute_pd(ymm0, 0x00); //(1/A11[0][0] 1/A11[0][0] 1/A11[2][2] 1/A11[2][2]) ymm7 = _mm256_permute2f128_pd(ymm7, ymm7, 0x11); //(1/A11[2][2] 1/A11[2][2] 1/A11[2][2] 1/A11[2][2]) //(Row 3): FMA operations ymm10 = _mm256_fnmadd_pd(ymm11, ymm6, ymm10); ymm9 = _mm256_fnmadd_pd(ymm11, ymm5, ymm9); ymm8 = _mm256_fnmadd_pd(ymm11, ymm2, ymm8); //(Row 3): FMA operations ymm14 = _mm256_fnmadd_pd(ymm15, ymm6, ymm14); ymm13 = _mm256_fnmadd_pd(ymm15, ymm5, ymm13); ymm12 = _mm256_fnmadd_pd(ymm15, ymm2, ymm12); ymm10 = _mm256_mul_pd(ymm10, ymm7); ymm14 = _mm256_mul_pd(ymm14, ymm7); //extract a11 ymm7 = _mm256_permute_pd(ymm0, 0x03); //(1/A11[1][1] 1/A11[1][1] 1/A11[2][2] 1/A11[2][2]) ymm7 = _mm256_permute2f128_pd(ymm7, ymm7, 0x00); //(1/A11[1][1] 1/A11[1][1] 1/A11[1][1] 1/A11[1][1]) //(ROW 2): FMA operations ymm9 = _mm256_fnmadd_pd(ymm10, ymm4, ymm9); ymm8 = _mm256_fnmadd_pd(ymm10, ymm3, ymm8); ymm13 = _mm256_fnmadd_pd(ymm14, ymm4, ymm13); ymm12 = _mm256_fnmadd_pd(ymm14, ymm3, ymm12); ymm9 = _mm256_mul_pd(ymm9, ymm7); ymm13 = _mm256_mul_pd(ymm13, ymm7); //extract A00 ymm7 = _mm256_permute_pd(ymm0, 0x00); //(1/A11[0][0] 1/A11[0][0] 1/A11[2][2] 1/A11[2][2]) ymm7 = _mm256_permute2f128_pd(ymm7, ymm7, 0x00); //(1/A11[0][0] 1/A11[0][0] 1/A11[0][0] 1/A11[0][0]) //(Row 1):FMA operations ymm8 = _mm256_fnmadd_pd(ymm9, ymm1, ymm8); ymm12 = _mm256_fnmadd_pd(ymm13, ymm1, ymm12); ymm8 = _mm256_mul_pd(ymm8, ymm7); ymm12 = _mm256_mul_pd(ymm12, ymm7); _mm256_storeu_pd((double *)b11, ymm8); //store(B11[x][0]) _mm256_storeu_pd((double *)(b11 + D_NR), ymm12); //store(B11[x][0]) _mm256_storeu_pd((double *)(b11 + cs_b), ymm9); //store(B11[x][1]) _mm256_storeu_pd((double *)(b11 + cs_b + D_NR), ymm13); //store(B11[x][1]) _mm256_storeu_pd((double *)(b11 + cs_b_offset[0]), ymm10); //(store(B11[x][2])) _mm256_storeu_pd((double *)(b11 + cs_b_offset[0] + D_NR), ymm14); //(store(B11[x][2])) _mm256_storeu_pd((double *)(b11 + cs_b_offset[1]), ymm11); //store(B11[x][3]) _mm256_storeu_pd((double *)(b11 + cs_b_offset[1] + D_NR), ymm15); //store(B11[x][3]) } if(n_remainder) //implementation for remainder columns(when n is not multiple of D_NR) { a01 = L + (j+D_NR)*cs_a +(j); //pointer to block of A to be used in GEMM a11 = L + j*cs_a + j; //pointer to block of A to be used for TRSM b10 = B + i + (j+D_NR)*cs_b; //pointer to block of B to be used in GEMM b11 = B + (i) + (j)*cs_b; //pointer to block of B to be used for TRSM k_iter = (n-j-D_NR) / D_NR; //number of GEMM operations to be done(in blocks of 4x4) ymm0 = _mm256_setzero_pd(); ymm1 = _mm256_setzero_pd(); ymm2 = _mm256_setzero_pd(); ymm3 = _mm256_setzero_pd(); ymm4 = _mm256_setzero_pd(); ymm5 = _mm256_setzero_pd(); ymm6 = _mm256_setzero_pd(); ymm7 = _mm256_setzero_pd(); //load 8x4 block of B11 if(3 == n_remainder) { ///GEMM implementation starts/// for(k = 0; k < k_iter; k++) //loop for number of GEMM operations { ptr_a01_dup = a01; //broadcast 1st row of A01 ymm9 = _mm256_broadcast_sd((double const *)(a01 + 1)); //A01[0][1] ymm10 = _mm256_broadcast_sd((double const *)(a01 + 2)); //A01[0][2] ymm11 = _mm256_broadcast_sd((double const *)(a01 + 3)); //A01[0][3] a01 += cs_a; //move to next row //load 8x2 block of B10 ymm12 = _mm256_loadu_pd((double const *)b10); //B10[0][0] B10[1][0] B10[2][0] B10[3][0] ymm13 = _mm256_loadu_pd((double const *)(b10 + D_NR)); //B10[4][0] B10[5][0] B10[6][0] B10[7][0] ymm14 = _mm256_loadu_pd((double const *)(b10 + cs_b)); //B10[0][1] B10[1][1] B10[2][1] B10[3][1] ymm15 = _mm256_loadu_pd((double const *)(b10 + cs_b + D_NR)); //B10[4][1] B10[5][1] B10[6][1] B10[7][1] ymm1 = _mm256_fmadd_pd(ymm9, ymm12, ymm1); //ymm1 += (B10[0][0]*A01[0][1] B10[1][0]*A01[0][1] B10[2][0]*A01[0][1] B10[3][0]*A01[0][1]) ymm2 = _mm256_fmadd_pd(ymm10, ymm12, ymm2); //ymm2 += (B10[0][0]*A01[0][2] B10[1][0]*A01[0][2] B10[2][0]*A01[0][2] B10[3][0]*A01[0][2]) ymm3 = _mm256_fmadd_pd(ymm11, ymm12, ymm3); //ymm3 += (B10[0][0]*A01[0][3] B10[1][0]*A01[0][3] B10[2][0]*A01[0][3] B10[3][0]*A01[0][3]) ymm5 = _mm256_fmadd_pd(ymm9, ymm13, ymm5); //ymm5 += (B10[4][0]*A01[0][1] B10[5][0]*A01[0][1] B10[6][0]*A01[0][1] B10[7][0]*A01[0][1]) ymm6 = _mm256_fmadd_pd(ymm10, ymm13, ymm6); //ymm6 += (B10[4][0]*A01[0][2] B10[5][0]*A01[0][2] B10[6][0]*A01[0][2] B10[7][0]*A01[0][2]) ymm7 = _mm256_fmadd_pd(ymm11, ymm13, ymm7); //ymm7 += (B10[4][0]*A01[0][3] B10[5][0]*A01[0][3] B10[6][0]*A01[0][3] B10[7][0]*A01[0][3]) //broadcast 2nd row of A01 ymm9 = _mm256_broadcast_sd((double const *)(a01 + 1)); //A01[1][1] ymm10 = _mm256_broadcast_sd((double const *)(a01 + 2)); //A01[1][2] ymm11 = _mm256_broadcast_sd((double const *)(a01 + 3)); //A01[1][3] a01 += cs_a; //move to next row of A ymm1 = _mm256_fmadd_pd(ymm9, ymm14, ymm1); //ymm1 += (B10[0][1]*A01[0][1] B10[1][1]*A01[0][1] B10[2][1]*A01[0][1] B10[3][1]*A01[0][1]) ymm2 = _mm256_fmadd_pd(ymm10, ymm14, ymm2); //ymm2 += (B10[0][1]*A01[0][2] B10[1][1]*A01[0][2] B10[2][1]*A01[0][2] B10[3][1]*A01[0][2]) ymm3 = _mm256_fmadd_pd(ymm11, ymm14, ymm3); //ymm3 += (B10[0][1]*A01[0][3] B10[1][1]*A01[0][3] B10[2][1]*A01[0][3] B10[3][1]*A01[0][3]) ymm5 = _mm256_fmadd_pd(ymm9, ymm15, ymm5); //ymm5 += (B10[4][1]*A01[0][1] B10[5][1]*A01[0][1] B10[6][1]*A01[0][1] B10[7][1]*A01[0][1]) ymm6 = _mm256_fmadd_pd(ymm10, ymm15, ymm6); //ymm6 += (B10[4][1]*A01[0][2] B10[5][1]*A01[0][2] B10[6][1]*A01[0][2] B10[7][1]*A01[0][2]) ymm7 = _mm256_fmadd_pd(ymm11, ymm15, ymm7); //ymm7 += (B10[4][1]*A01[0][3] B10[5][1]*A01[0][3] B10[6][1]*A01[0][3] B10[7][1]*A01[0][3]) //broadcast 3rd row of A01 ymm9 = _mm256_broadcast_sd((double const *)(a01 + 1)); //A01[2][1] ymm10 = _mm256_broadcast_sd((double const *)(a01 + 2)); //A01[2][2] ymm11 = _mm256_broadcast_sd((double const *)(a01 + 3)); //A01[2][3] a01 += cs_a; //move to next row of A01 //load next 8x2 block of B10 ymm12 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0])); //(B10[0][2] B10[1][2] B10[2][2] B10[3][2]) ymm13 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + D_NR)); //(B10[4][2] B10[5][2] B10[6][2] B10[7][2]) ymm14 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + cs_b)); //(B10[0][3] B10[1][3] B10[2][3] B10[3][3]) ymm15 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + cs_b + D_NR)); //(B10[4][3] B10[5][3] B10[6][3] B10[7][3]) ymm1 = _mm256_fmadd_pd(ymm9, ymm12, ymm1); //ymm1 += (B10[0][2]*A01[0][1] B10[1][2]*A01[0][1] B10[2][2]*A01[0][1] B10[3][2]*A01[0][1]) ymm2 = _mm256_fmadd_pd(ymm10, ymm12, ymm2); //ymm2 += (B10[0][2]*A01[0][2] B10[1][2]*A01[0][2] B10[2][2]*A01[0][2] B10[3][2]*A01[0][2]) ymm3 = _mm256_fmadd_pd(ymm11, ymm12, ymm3); //ymm3 += (B10[0][2]*A01[0][3] B10[1][2]*A01[0][3] B10[2][2]*A01[0][3] B10[3][2]*A01[0][3]) ymm5 = _mm256_fmadd_pd(ymm9, ymm13, ymm5); //ymm5 += (B10[4][2]*A01[0][1] B10[5][2]*A01[0][1] B10[6][2]*A01[0][1] B10[7][2]*A01[0][1]) ymm6 = _mm256_fmadd_pd(ymm10, ymm13, ymm6); //ymm6 += (B10[4][2]*A01[0][2] B10[5][2]*A01[0][2] B10[6][2]*A01[0][2] B10[7][2]*A01[0][2]) ymm7 = _mm256_fmadd_pd(ymm11, ymm13, ymm7); //ymm7 += (B10[4][2]*A01[0][3] B10[5][2]*A01[0][3] B10[6][2]*A01[0][3] B10[7][2]*A01[0][3]) //broadcast 4th row of A01 ymm9 = _mm256_broadcast_sd((double const *)(a01 + 1)); //A01[3][1] ymm10 = _mm256_broadcast_sd((double const *)(a01 + 2)); //A01[3][2] ymm11 = _mm256_broadcast_sd((double const *)(a01 + 3)); //A01[3][3] a01 += cs_a; //move to next row of A01 ymm1 = _mm256_fmadd_pd(ymm9, ymm14, ymm1); //ymm1 += (B10[0][3]*A01[0][1] B10[1][3]*A01[0][1] B10[2][3]*A01[0][1] B10[3][3]*A01[0][1]) ymm2 = _mm256_fmadd_pd(ymm10, ymm14, ymm2); //ymm2 += (B10[0][3]*A01[0][2] B10[1][3]*A01[0][2] B10[2][3]*A01[0][2] B10[3][3]*A01[0][2]) ymm3 = _mm256_fmadd_pd(ymm11, ymm14, ymm3); //ymm3 += (B10[0][3]*A01[0][3] B10[1][3]*A01[0][3] B10[2][3]*A01[0][3] B10[3][3]*A01[0][3]) ymm5 = _mm256_fmadd_pd(ymm9, ymm15, ymm5); //ymm5 += (B10[4][3]*A01[0][1] B10[5][3]*A01[0][1] B10[6][3]*A01[0][1] B10[7][3]*A01[0][1]) ymm6 = _mm256_fmadd_pd(ymm10, ymm15, ymm6); //ymm6 += (B10[4][3]*A01[0][2] B10[5][3]*A01[0][2] B10[6][3]*A01[0][2] B10[7][3]*A01[0][2]) ymm7 = _mm256_fmadd_pd(ymm11, ymm15, ymm7); //ymm7 += (B10[4][3]*A01[0][3] B10[5][3]*A01[0][3] B10[6][3]*A01[0][3] B10[7][3]*A01[0][3]) b10 += D_NR * cs_b; //pointer math to find next block of B for GEMM a01 = ptr_a01_dup + (D_NR * cs_a); //pointer math to find next block of A for GEMM } ///GEMM code ends/// ymm8 = _mm256_broadcast_sd((double const *)&AlphaVal); ymm9 = _mm256_loadu_pd((double const *)(b11+cs_b)); //B11[0-3][0] ymm13 = _mm256_loadu_pd((double const *)(b11 + cs_b + D_NR)); //B11[4-7][0] ymm10 = _mm256_loadu_pd((double const *)(b11 + cs_b*2)); //B11[0-3][1] ymm14 = _mm256_loadu_pd((double const *)(b11 + cs_b*2 + D_NR)); //B11[4-7][1] ymm11 = _mm256_loadu_pd((double const *)(b11 + cs_b_offset[1])); //B11[0-3][2] ymm15 = _mm256_loadu_pd((double const *)(b11 + cs_b_offset[1] + D_NR)); //B11[4-7][2] ymm9 = _mm256_fmsub_pd(ymm9, ymm8, ymm1); //B11[4-7][0] * alpha-= ymm1 ymm10 = _mm256_fmsub_pd(ymm10, ymm8, ymm2); //B11[0-3][1] * alpha-= ymm2 ymm11 = _mm256_fmsub_pd(ymm11, ymm8, ymm3); //B11[4-7][1] * alpha -= ymm3 ymm13 = _mm256_fmsub_pd(ymm13, ymm8, ymm5); //B11[4-7][2] * alpha -= ymm5 ymm14 = _mm256_fmsub_pd(ymm14, ymm8, ymm6); //B11[0-3][3] * alpha -= ymm6 ymm15 = _mm256_fmsub_pd(ymm15, ymm8, ymm7); //B11[4-7][3] * alpha -= ymm7 ///implement TRSM/// ///read 4x4 block of A11/// //1st col ymm0 = _mm256_broadcast_sd((double const *)(&ones)); //A11[0][0] a11 += cs_a; //2nd col ymm2 = _mm256_broadcast_sd((double const *)(a11+1)); //A11[0][1] a11 += cs_a; //3rd col ymm4 = _mm256_broadcast_sd((double const *)(a11+1)); //A11[0][1] ymm5 = _mm256_broadcast_sd((double const *)(a11+2)); //A11[0][1] a11 += cs_a; //4th col ymm6 = _mm256_broadcast_sd((double const *)(a11+3)); //A11[0][1] ymm7 = _mm256_broadcast_sd((double const *)&ones); //compute reciprocals of A(i,i) and broadcast in registers ymm0 = _mm256_unpacklo_pd(ymm0, ymm2); //A11[0][0] A11[1][1] A11[0][0] A11[1][1] ymm2 = _mm256_unpacklo_pd(ymm5, ymm6); //A11[2][2] A11[3][3] A11[2][2] A11[3][3] ymm0 = _mm256_blend_pd(ymm0, ymm2, 0x0C); //A11[0][0] A11[1][1] A11[2][2] A11[3][3] ymm0 = _mm256_div_pd(ymm7, ymm0); // 1/A11[0][0] 1/A11[1][1] 1/A11[2][2] 1/A11[3][3] ymm5 = _mm256_broadcast_sd((double const *)(a11+1)); //A11[0][1] ymm6 = _mm256_broadcast_sd((double const *)(a11+2)); //A11[0][1] //extract a33 ymm7 = _mm256_permute_pd(ymm0, 0x0C); //(1/A11[0][0] 1/A11[0][0] 1/A11[3][3] 1/A11[3][3]) ymm7 = _mm256_permute2f128_pd(ymm7, ymm7, 0x11); //(1/A11[3][3] 1/A11[3][3] 1/A11[3][3] 1/A11[3][3]) ymm11 = _mm256_mul_pd(ymm11, ymm7); ymm15 = _mm256_mul_pd(ymm15, ymm7); //extract a22 ymm7 = _mm256_permute_pd(ymm0, 0x00); //(1/A11[0][0] 1/A11[0][0] 1/A11[2][2] 1/A11[2][2]) ymm7 = _mm256_permute2f128_pd(ymm7, ymm7, 0x11); //(1/A11[2][2] 1/A11[2][2] 1/A11[2][2] 1/A11[2][2]) //(Row 3): FMA operations ymm10 = _mm256_fnmadd_pd(ymm11, ymm6, ymm10); ymm9 = _mm256_fnmadd_pd(ymm11, ymm5, ymm9); //(Row 3): FMA operations ymm14 = _mm256_fnmadd_pd(ymm15, ymm6, ymm14); ymm13 = _mm256_fnmadd_pd(ymm15, ymm5, ymm13); ymm10 = _mm256_mul_pd(ymm10, ymm7); ymm14 = _mm256_mul_pd(ymm14, ymm7); //extract a11 ymm7 = _mm256_permute_pd(ymm0, 0x03); //(1/A11[1][1] 1/A11[1][1] 1/A11[2][2] 1/A11[2][2]) ymm7 = _mm256_permute2f128_pd(ymm7, ymm7, 0x00); //(1/A11[1][1] 1/A11[1][1] 1/A11[1][1] 1/A11[1][1]) //(ROW 2): FMA operations ymm9 = _mm256_fnmadd_pd(ymm10, ymm4, ymm9); ymm13 = _mm256_fnmadd_pd(ymm14, ymm4, ymm13); ymm9 = _mm256_mul_pd(ymm9, ymm7); ymm13 = _mm256_mul_pd(ymm13, ymm7); _mm256_storeu_pd((double *)(b11 + cs_b), ymm9); //store(B11[0-3][1]) _mm256_storeu_pd((double *)(b11 + cs_b + D_NR), ymm13); //store(B11[4-7][1]) _mm256_storeu_pd((double *)(b11 + cs_b_offset[0]), ymm10); //store(B11[0-3][2]) _mm256_storeu_pd((double *)(b11 + cs_b_offset[0] + D_NR), ymm14);//store(B11[4-7][2]) _mm256_storeu_pd((double *)(b11 + cs_b_offset[1]), ymm11); //store(B11[0-3][0]) _mm256_storeu_pd((double *)(b11 + cs_b_offset[1] + D_NR), ymm15); //store(B11[4-7][0]) } else if(2 == n_remainder) { ///GEMM implementation starts/// for(k = 0; k < k_iter; k++) //loop for number of GEMM operations { ptr_a01_dup = a01; //broadcast 1st row of A01 ymm10 = _mm256_broadcast_sd((double const *)(a01 + 2)); //A01[0][2] ymm11 = _mm256_broadcast_sd((double const *)(a01 + 3)); //A01[0][3] a01 += cs_a; //move to next row //load 8x2 block of B10 ymm12 = _mm256_loadu_pd((double const *)b10); //B10[0][0] B10[1][0] B10[2][0] B10[3][0] ymm13 = _mm256_loadu_pd((double const *)(b10 + D_NR)); //B10[4][0] B10[5][0] B10[6][0] B10[7][0] ymm14 = _mm256_loadu_pd((double const *)(b10 + cs_b)); //B10[0][1] B10[1][1] B10[2][1] B10[3][1] ymm15 = _mm256_loadu_pd((double const *)(b10 + cs_b + D_NR)); //B10[4][1] B10[5][1] B10[6][1] B10[7][1] ymm2 = _mm256_fmadd_pd(ymm10, ymm12, ymm2); //ymm2 += (B10[0][0]*A01[0][2] B10[1][0]*A01[0][2] B10[2][0]*A01[0][2] B10[3][0]*A01[0][2]) ymm3 = _mm256_fmadd_pd(ymm11, ymm12, ymm3); //ymm3 += (B10[0][0]*A01[0][3] B10[1][0]*A01[0][3] B10[2][0]*A01[0][3] B10[3][0]*A01[0][3]) ymm6 = _mm256_fmadd_pd(ymm10, ymm13, ymm6); //ymm6 += (B10[4][0]*A01[0][2] B10[5][0]*A01[0][2] B10[6][0]*A01[0][2] B10[7][0]*A01[0][2]) ymm7 = _mm256_fmadd_pd(ymm11, ymm13, ymm7); //ymm7 += (B10[4][0]*A01[0][3] B10[5][0]*A01[0][3] B10[6][0]*A01[0][3] B10[7][0]*A01[0][3]) //broadcast 2nd row of A01 ymm10 = _mm256_broadcast_sd((double const *)(a01 + 2)); //A01[1][2] ymm11 = _mm256_broadcast_sd((double const *)(a01 + 3)); //A01[1][3] a01 += cs_a; //move to next row of A ymm2 = _mm256_fmadd_pd(ymm10, ymm14, ymm2); //ymm2 += (B10[0][1]*A01[0][2] B10[1][1]*A01[0][2] B10[2][1]*A01[0][2] B10[3][1]*A01[0][2]) ymm3 = _mm256_fmadd_pd(ymm11, ymm14, ymm3); //ymm3 += (B10[0][1]*A01[0][3] B10[1][1]*A01[0][3] B10[2][1]*A01[0][3] B10[3][1]*A01[0][3]) ymm6 = _mm256_fmadd_pd(ymm10, ymm15, ymm6); //ymm6 += (B10[4][1]*A01[0][2] B10[5][1]*A01[0][2] B10[6][1]*A01[0][2] B10[7][1]*A01[0][2]) ymm7 = _mm256_fmadd_pd(ymm11, ymm15, ymm7); //ymm7 += (B10[4][1]*A01[0][3] B10[5][1]*A01[0][3] B10[6][1]*A01[0][3] B10[7][1]*A01[0][3]) //broadcast 3rd row of A01 ymm10 = _mm256_broadcast_sd((double const *)(a01 + 2)); //A01[2][2] ymm11 = _mm256_broadcast_sd((double const *)(a01 + 3)); //A01[2][3] a01 += cs_a; //move to next row of A01 //load next 8x2 block of B10 ymm12 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0])); //(B10[0][2] B10[1][2] B10[2][2] B10[3][2]) ymm13 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + D_NR)); //(B10[4][2] B10[5][2] B10[6][2] B10[7][2]) ymm14 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + cs_b)); //(B10[0][3] B10[1][3] B10[2][3] B10[3][3]) ymm15 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + cs_b + D_NR)); //(B10[4][3] B10[5][3] B10[6][3] B10[7][3]) ymm2 = _mm256_fmadd_pd(ymm10, ymm12, ymm2); //ymm2 += (B10[0][2]*A01[0][2] B10[1][2]*A01[0][2] B10[2][2]*A01[0][2] B10[3][2]*A01[0][2]) ymm3 = _mm256_fmadd_pd(ymm11, ymm12, ymm3); //ymm3 += (B10[0][2]*A01[0][3] B10[1][2]*A01[0][3] B10[2][2]*A01[0][3] B10[3][2]*A01[0][3]) ymm6 = _mm256_fmadd_pd(ymm10, ymm13, ymm6); //ymm6 += (B10[4][2]*A01[0][2] B10[5][2]*A01[0][2] B10[6][2]*A01[0][2] B10[7][2]*A01[0][2]) ymm7 = _mm256_fmadd_pd(ymm11, ymm13, ymm7); //ymm7 += (B10[4][2]*A01[0][3] B10[5][2]*A01[0][3] B10[6][2]*A01[0][3] B10[7][2]*A01[0][3]) //broadcast 4th row of A01 ymm10 = _mm256_broadcast_sd((double const *)(a01 + 2)); //A01[3][2] ymm11 = _mm256_broadcast_sd((double const *)(a01 + 3)); //A01[3][3] a01 += cs_a; //move to next row of A01 ymm2 = _mm256_fmadd_pd(ymm10, ymm14, ymm2); //ymm2 += (B10[0][3]*A01[0][2] B10[1][3]*A01[0][2] B10[2][3]*A01[0][2] B10[3][3]*A01[0][2]) ymm3 = _mm256_fmadd_pd(ymm11, ymm14, ymm3); //ymm3 += (B10[0][3]*A01[0][3] B10[1][3]*A01[0][3] B10[2][3]*A01[0][3] B10[3][3]*A01[0][3]) ymm6 = _mm256_fmadd_pd(ymm10, ymm15, ymm6); //ymm6 += (B10[4][3]*A01[0][2] B10[5][3]*A01[0][2] B10[6][3]*A01[0][2] B10[7][3]*A01[0][2]) ymm7 = _mm256_fmadd_pd(ymm11, ymm15, ymm7); //ymm7 += (B10[4][3]*A01[0][3] B10[5][3]*A01[0][3] B10[6][3]*A01[0][3] B10[7][3]*A01[0][3]) b10 += D_NR * cs_b; //pointer math to find next block of B for GEMM a01 = ptr_a01_dup + (D_NR * cs_a); //pointer math to find next block of A for GEMM } ///GEMM code ends/// ymm8 = _mm256_broadcast_sd((double const *)&AlphaVal); ymm10 = _mm256_loadu_pd((double const *)(b11 + cs_b_offset[0])); ymm14 = _mm256_loadu_pd((double const *)(b11 + cs_b_offset[0] + D_NR)); //B11[4-7][0] ymm11 = _mm256_loadu_pd((double const *)(b11 + cs_b_offset[1])); //B11[0-3][1] ymm15 = _mm256_loadu_pd((double const *)(b11 + cs_b_offset[1] + D_NR)); //B11[4-7][1] ymm10 = _mm256_fmsub_pd(ymm10, ymm8, ymm2); //B11[0-3][1] * alpha-= ymm2 ymm11 = _mm256_fmsub_pd(ymm11, ymm8, ymm3); //B11[4-7][1] * alpha -= ymm3 ymm14 = _mm256_fmsub_pd(ymm14, ymm8, ymm6); //B11[0-3][3] * alpha -= ymm6 ymm15 = _mm256_fmsub_pd(ymm15, ymm8, ymm7); //B11[4-7][3] * alpha -= ymm7 ///implement TRSM/// ///read 4x4 block of A11/// //1st col a11 += 2 * cs_a; //3rd col ymm5 = _mm256_broadcast_sd((double const *)(a11+2)); //A11[0][1] a11 += cs_a; //4th col ymm6 = _mm256_broadcast_sd((double const *)(a11+3)); //A11[0][1] ymm7 = _mm256_broadcast_sd((double const *)&ones); //compute reciprocals of A(i,i) and broadcast in registers ymm2 = _mm256_unpacklo_pd(ymm5, ymm6); //A11[2][2] A11[3][3] A11[2][2] A11[3][3] ymm0 = _mm256_blend_pd(ymm7, ymm2, 0x0C); //A11[0][0] A11[1][1] A11[2][2] A11[3][3] ymm0 = _mm256_div_pd(ymm7, ymm0); // 1/A11[0][0] 1/A11[1][1] 1/A11[2][2] 1/A11[3][3] ymm6 = _mm256_broadcast_sd((double const *)(a11+2)); //A11[0][1] //extract a33 ymm7 = _mm256_permute_pd(ymm0, 0x0C); //(1/A11[0][0] 1/A11[0][0] 1/A11[3][3] 1/A11[3][3]) ymm7 = _mm256_permute2f128_pd(ymm7, ymm7, 0x11); //(1/A11[3][3] 1/A11[3][3] 1/A11[3][3] 1/A11[3][3]) ymm11 = _mm256_mul_pd(ymm11, ymm7); ymm15 = _mm256_mul_pd(ymm15, ymm7); //extract a22 ymm7 = _mm256_permute_pd(ymm0, 0x00); //(1/A11[0][0] 1/A11[0][0] 1/A11[2][2] 1/A11[2][2]) ymm7 = _mm256_permute2f128_pd(ymm7, ymm7, 0x11); //(1/A11[2][2] 1/A11[2][2] 1/A11[2][2] 1/A11[2][2]) //(Row 3): FMA operations ymm10 = _mm256_fnmadd_pd(ymm11, ymm6, ymm10); //(Row 3): FMA operations ymm14 = _mm256_fnmadd_pd(ymm15, ymm6, ymm14); ymm10 = _mm256_mul_pd(ymm10, ymm7); ymm14 = _mm256_mul_pd(ymm14, ymm7); _mm256_storeu_pd((double *)(b11 + cs_b_offset[0]), ymm10); //store(B11[0-3][1]) _mm256_storeu_pd((double *)(b11 + cs_b_offset[0] + D_NR), ymm14); //store(B11[4-7][1]) _mm256_storeu_pd((double *)(b11 + cs_b_offset[1]), ymm11); //store(B11[0-3][0]) _mm256_storeu_pd((double *)(b11 + cs_b_offset[1] + D_NR), ymm15); //store(B11[4-7][0]) } else if(1 == n_remainder) { ///GEMM implementation starts/// for(k = 0; k < k_iter; k++) //loop for number of GEMM operations { ptr_a01_dup = a01; //broadcast 1st row of A01 ymm11 = _mm256_broadcast_sd((double const *)(a01 + 3)); //A01[0][3] a01 += cs_a; //move to next row //load 8x2 block of B10 ymm12 = _mm256_loadu_pd((double const *)b10); //B10[0][0] B10[1][0] B10[2][0] B10[3][0] ymm13 = _mm256_loadu_pd((double const *)(b10 + D_NR)); //B10[4][0] B10[5][0] B10[6][0] B10[7][0] ymm14 = _mm256_loadu_pd((double const *)(b10 + cs_b)); //B10[0][1] B10[1][1] B10[2][1] B10[3][1] ymm15 = _mm256_loadu_pd((double const *)(b10 + cs_b + D_NR)); //B10[4][1] B10[5][1] B10[6][1] B10[7][1] ymm3 = _mm256_fmadd_pd(ymm11, ymm12, ymm3); //ymm3 += (B10[0][0]*A01[0][3] B10[1][0]*A01[0][3] B10[2][0]*A01[0][3] B10[3][0]*A01[0][3]) ymm7 = _mm256_fmadd_pd(ymm11, ymm13, ymm7); //ymm7 += (B10[4][0]*A01[0][3] B10[5][0]*A01[0][3] B10[6][0]*A01[0][3] B10[7][0]*A01[0][3]) //broadcast 2nd row of A01 ymm11 = _mm256_broadcast_sd((double const *)(a01 + 3)); //A01[1][3] a01 += cs_a; //move to next row of A ymm3 = _mm256_fmadd_pd(ymm11, ymm14, ymm3); //ymm3 += (B10[0][1]*A01[0][3] B10[1][1]*A01[0][3] B10[2][1]*A01[0][3] B10[3][1]*A01[0][3]) ymm7 = _mm256_fmadd_pd(ymm11, ymm15, ymm7); //ymm7 += (B10[4][1]*A01[0][3] B10[5][1]*A01[0][3] B10[6][1]*A01[0][3] B10[7][1]*A01[0][3]) //broadcast 3rd row of A01 ymm11 = _mm256_broadcast_sd((double const *)(a01 + 3)); //A01[2][3] a01 += cs_a; //move to next row of A01 //load next 8x2 block of B10 ymm12 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0])); //(B10[0][2] B10[1][2] B10[2][2] B10[3][2]) ymm13 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + D_NR)); //(B10[4][2] B10[5][2] B10[6][2] B10[7][2]) ymm14 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + cs_b)); //(B10[0][3] B10[1][3] B10[2][3] B10[3][3]) ymm15 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + cs_b + D_NR)); //(B10[4][3] B10[5][3] B10[6][3] B10[7][3]) ymm3 = _mm256_fmadd_pd(ymm11, ymm12, ymm3); //ymm3 += (B10[0][2]*A01[0][3] B10[1][2]*A01[0][3] B10[2][2]*A01[0][3] B10[3][2]*A01[0][3]) ymm7 = _mm256_fmadd_pd(ymm11, ymm13, ymm7); //ymm7 += (B10[4][2]*A01[0][3] B10[5][2]*A01[0][3] B10[6][2]*A01[0][3] B10[7][2]*A01[0][3]) //broadcast 4th row of A01 ymm11 = _mm256_broadcast_sd((double const *)(a01 + 3)); //A01[3][3] a01 += cs_a; //move to next row of A01 ymm3 = _mm256_fmadd_pd(ymm11, ymm14, ymm3); //ymm3 += (B10[0][3]*A01[0][3] B10[1][3]*A01[0][3] B10[2][3]*A01[0][3] B10[3][3]*A01[0][3]) ymm7 = _mm256_fmadd_pd(ymm11, ymm15, ymm7); //ymm7 += (B10[4][3]*A01[0][3] B10[5][3]*A01[0][3] B10[6][3]*A01[0][3] B10[7][3]*A01[0][3]) b10 += D_NR * cs_b; //pointer math to find next block of B for GEMM a01 = ptr_a01_dup + (D_NR * cs_a); //pointer math to find next block of A for GEMM } ///GEMM code ends/// ymm8 = _mm256_broadcast_sd((double const *)&AlphaVal); ymm11 = _mm256_loadu_pd((double const *)(b11+cs_b_offset[1])); //B11[0-3][0] ymm15 = _mm256_loadu_pd((double const *)(b11 + cs_b_offset[1] +D_NR)); //B11[4-7][0] ymm11 = _mm256_fmsub_pd(ymm11, ymm8, ymm3); //B11[4-7][1] * alpha -= ymm3 ymm15 = _mm256_fmsub_pd(ymm15, ymm8, ymm7); //B11[4-7][3] * alpha -= ymm7 ///implement TRSM/// ///read 4x4 block of A11/// a11 += 3 * cs_a; //4th col ymm6 = _mm256_broadcast_sd((double const *)(a11+3)); //A11[0][1] ymm7 = _mm256_broadcast_sd((double const *)&ones); ymm0 = _mm256_div_pd(ymm7, ymm6); // 1/A11[0][0] 1/A11[1][1] 1/A11[2][2] 1/A11[3][3] ymm11 = _mm256_mul_pd(ymm11, ymm0); ymm15 = _mm256_mul_pd(ymm15, ymm0); _mm256_storeu_pd((double *)(b11+ cs_b_offset[1]), ymm11); //store(B11[0-3][0]) _mm256_storeu_pd((double *)(b11 + cs_b_offset[1] + D_NR), ymm15); //store(B11[4-7][0]) } } } if(i<0) i += D_NR; if((m & 4)) ///implementation for remainder rows(when m_remainder is greater than 4) { for(j = (n-D_NR); (j+1) > 0; j -=D_NR) //loop along n direction { a01 = L + (j+D_NR)*cs_a + (j); //pointer to block of A to be used for GEMM a11 = L + j*cs_a + j; //pointer to block of A to be used for TRSM b10 = B + i + (j+D_NR)*cs_b; //pointer to block of B to be used for GEMM b11 = B + i + j*cs_b; //pointer to block of B to be used for TRSM k_iter = (n-j-D_NR) / D_NR; //number of times GEMM operations to be performed(in blocks of 4x4) ///GEMM for previous blocks /// ///load 4x4 block of b11 ymm0 = _mm256_loadu_pd((double const *)b11); //B11[0][0] B11[1][0] B11[2][0] B11[3][0] ymm1 = _mm256_loadu_pd((double const *)(b11 + cs_b)); //B11[0][1] B11[1][1] B11[2][1] B11[3][1] ymm2 = _mm256_loadu_pd((double const *)(b11 + cs_b_offset[0])); //B11[0][2] B11[1][2] B11[2][2] B11[3][2] ymm3 = _mm256_loadu_pd((double const *)(b11 + cs_b_offset[1])); //B11[0][3] B11[1][3] B11[2][3] B11[3][3] ymm4 = _mm256_setzero_pd(); ymm5 = _mm256_setzero_pd(); ymm6 = _mm256_setzero_pd(); ymm7 = _mm256_setzero_pd(); ///GEMM implementation starts/// for(k = 0; k < k_iter; k++) //loop for number of GEMM operations { ptr_a01_dup = a01; //load 4x4 bblock of b10 ymm8 = _mm256_loadu_pd((double const *)b10); //B10[0][0] B10[1][0] B10[2][0] B10[3][0] ymm9 = _mm256_loadu_pd((double const *)(b10 + cs_b)); //B10[0][1] B10[1][1] B10[2][1] B10[3][1] ymm10 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0])); //B10[0][2] B10[1][2] B10[2][2] B10[3][2] ymm11 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[1])); //B10[0][3] B10[1][3] B10[2][3] B10[3][3] //broadcast 1st row of A01 ymm12 = _mm256_broadcast_sd((double const *)(a01 + 0)); //A01[0][0] ymm13 = _mm256_broadcast_sd((double const *)(a01 + 1)); //A01[0][1] ymm14 = _mm256_broadcast_sd((double const *)(a01 + 2)); //A01[0][2] ymm15 = _mm256_broadcast_sd((double const *)(a01 + 3)); //A01[0][3] a01 += cs_a; //move to next row of A ymm4 = _mm256_fmadd_pd(ymm12, ymm8, ymm4); //ymm4 += (B10[0][0]*A01[0][0] B10[1][0]*A01[0][0] B10[2][0]*A01[0][0] B10[3][0]*A01[0][0]) ymm5 = _mm256_fmadd_pd(ymm13, ymm8, ymm5); //ymm5 += (B10[0][0]*A01[0][1] B10[1][0]*A01[0][1] B10[2][0]*A01[0][1] B10[3][0]*A01[0][1]) ymm6 = _mm256_fmadd_pd(ymm14, ymm8, ymm6); //ymm6 += (B10[0][0]*A01[0][2] B10[1][0]*A01[0][2] B10[2][0]*A01[0][2] B10[3][0]*A01[0][2]) ymm7 = _mm256_fmadd_pd(ymm15, ymm8, ymm7); //ymm7 += (B10[0][0]*A01[0][3] B10[1][0]*A01[0][3] B10[2][0]*A01[0][3] B10[3][0]*A01[0][3]) //broadcast 2nd row of A01 ymm12 = _mm256_broadcast_sd((double const *)(a01 + 0)); //A01[1][0] ymm13 = _mm256_broadcast_sd((double const *)(a01 + 1)); //A01[1][1] ymm14 = _mm256_broadcast_sd((double const *)(a01 + 2)); //A01[1][2] ymm15 = _mm256_broadcast_sd((double const *)(a01 + 3)); //A01[1][3] a01 += cs_a; //move to next row of A ymm4 = _mm256_fmadd_pd(ymm12, ymm9, ymm4); //ymm4 += (B10[0][1]*A01[1][0] B10[1][1]*A01[1][0] B10[2][1]*A01[1][0] B10[3][1]*A01[1][0]) ymm5 = _mm256_fmadd_pd(ymm13, ymm9, ymm5); //ymm5 += (B10[0][1]*A01[1][1] B10[1][1]*A01[1][1] B10[2][1]*A01[1][1] B10[3][1]*A01[1][1]) ymm6 = _mm256_fmadd_pd(ymm14, ymm9, ymm6); //ymm6 += (B10[0][1]*A01[1][2] B10[1][1]*A01[1][2] B10[2][1]*A01[1][2] B10[3][1]*A01[1][2]) ymm7 = _mm256_fmadd_pd(ymm15, ymm9, ymm7); //ymm7 += (B10[0][1]*A01[1][3] B10[1][1]*A01[1][3] B10[2][1]*A01[1][3] B10[3][1]*A01[1][3]) //braodcast 3rd row of A01 ymm12 = _mm256_broadcast_sd((double const *)(a01 + 0)); //A01[2][0] ymm13 = _mm256_broadcast_sd((double const *)(a01 + 1)); //A01[2][1] ymm14 = _mm256_broadcast_sd((double const *)(a01 + 2)); //A01[2][2] ymm15 = _mm256_broadcast_sd((double const *)(a01 + 3)); //A01[2][3] a01 += cs_a; //move to next row of A ymm4 = _mm256_fmadd_pd(ymm12, ymm10, ymm4); //ymm4 += (B10[0][2]*A01[2][0] B10[1][2]*A01[2][0] B10[2][2]*A01[2][0] B10[3][2]*A01[2][0]) ymm5 = _mm256_fmadd_pd(ymm13, ymm10, ymm5); //ymm5 += (B10[0][2]*A01[2][1] B10[1][2]*A01[2][1] B10[2][2]*A01[2][1] B10[3][2]*A01[2][1]) ymm6 = _mm256_fmadd_pd(ymm14, ymm10, ymm6); //ymm6 += (B10[0][2]*A01[2][2] B10[1][2]*A01[2][2] B10[2][2]*A01[2][2] B10[3][2]*A01[2][2]) ymm7 = _mm256_fmadd_pd(ymm15, ymm10, ymm7); //ymm7 += (B10[0][2]*A01[2][3] B10[1][2]*A01[2][3] B10[2][2]*A01[2][3] B10[3][2]*A01[2][3]) //broadcast 4th row of A01 ymm12 = _mm256_broadcast_sd((double const *)(a01 + 0)); //A01[3][0] ymm13 = _mm256_broadcast_sd((double const *)(a01 + 1)); //A01[3][1] ymm14 = _mm256_broadcast_sd((double const *)(a01 + 2)); //A01[3][2] ymm15 = _mm256_broadcast_sd((double const *)(a01 + 3)); //A01[3][3] a01 += cs_a; //move to next row of A ymm4 = _mm256_fmadd_pd(ymm12, ymm11, ymm4); //ymm4 += (B10[0][3]*A01[3][0] B10[1][3]*A01[3][0] B10[2][3]*A01[3][0] B10[3][3]*A01[3][0]) ymm5 = _mm256_fmadd_pd(ymm13, ymm11, ymm5); //ymm5 += (B10[0][3]*A01[3][1] B10[1][3]*A01[3][1] B10[2][3]*A01[3][1] B10[3][3]*A01[3][1]) ymm6 = _mm256_fmadd_pd(ymm14, ymm11, ymm6); //ymm6 += (B10[0][3]*A01[3][2] B10[1][3]*A01[3][2] B10[2][3]*A01[3][2] B10[3][3]*A01[3][2]) ymm7 = _mm256_fmadd_pd(ymm15, ymm11, ymm7); //ymm7 += (B10[0][3]*A01[3][3] B10[1][3]*A01[3][3] B10[2][3]*A01[3][3] B10[3][3]*A01[3][3]) b10 += D_NR * cs_b; //pointer math to find next block of B for GEMM a01 = ptr_a01_dup + D_NR*cs_a; //pointer math to find next block of A for GEMM } ///GEMM code end/// ymm15 = _mm256_broadcast_sd((double const *)&AlphaVal); //register to store alpha ymm0 = _mm256_fmsub_pd(ymm0, ymm15, ymm4); //B11[x][0] -=ymm4 ymm1 = _mm256_fmsub_pd(ymm1, ymm15, ymm5); //B11[x][1] -= ymm5 ymm2 = _mm256_fmsub_pd(ymm2, ymm15, ymm6); //B11[x][2] -= ymm6 ymm3 = _mm256_fmsub_pd(ymm3, ymm15, ymm7); //B11[x][3] -= ymm7 ///implement TRSM/// ///read 4x4 block of A11/// //1st col ymm4 = _mm256_broadcast_sd((double const *)(a11+0)); //A11[0][0] a11 += cs_a; //2nd col ymm5 = _mm256_broadcast_sd((double const *)(a11+0)); //A11[0][1] ymm8 = _mm256_broadcast_sd((double const *)(a11+1)); //A11[0][1] a11 += cs_a; //3rd col ymm6 = _mm256_broadcast_sd((double const *)(a11+0)); //A11[0][1] ymm9 = _mm256_broadcast_sd((double const *)(a11+1)); //A11[0][1] ymm11 = _mm256_broadcast_sd((double const *)(a11+2)); //A11[0][1] a11 += cs_a; //4th col ymm7 = _mm256_broadcast_sd((double const *)(a11+0)); //A11[0][1] ymm10 = _mm256_broadcast_sd((double const *)(a11+1)); //A11[0][1] ymm12 = _mm256_broadcast_sd((double const *)(a11+2)); //A11[0][1] ymm13 = _mm256_broadcast_sd((double const *)(a11+3)); //A11[0][1] ymm14 = _mm256_broadcast_sd((double const *)&ones); //compute reciprocals of A(i,i) and broadcast in registers ymm4 = _mm256_unpacklo_pd(ymm4, ymm8); //A11[0][0] A11[1][1] A11[0][0] A11[1][1] ymm8 = _mm256_unpacklo_pd(ymm11, ymm13); //A11[2][2] A11[3][3] A11[2][2] A11[3][3] ymm15 = _mm256_blend_pd(ymm4, ymm8, 0x0C); //A11[0][0] A11[1][1] A11[2][2] A11[3][3] ymm14 = _mm256_div_pd(ymm14, ymm15); // 1/A11[0][0] 1/A11[1][1] 1/A11[2][2] 1/A11[3][3] //extract a33 ymm15 = _mm256_permute_pd(ymm14, 0x0C); //(1/A11[0][0] 1/A11[0][0] 1/A11[3][3] 1/A11[3][3]) ymm15 = _mm256_permute2f128_pd(ymm15, ymm15, 0x11); //(1/A11[3][3] 1/A11[3][3] 1/A11[3][3] 1/A11[3][3]) ymm3 = _mm256_mul_pd(ymm3, ymm15); //extract a22 ymm15 = _mm256_permute_pd(ymm14, 0x00); //(1/A11[0][0] 1/A11[0][0] 1/A11[2][2] 1/A11[2][2]) ymm15 = _mm256_permute2f128_pd(ymm15, ymm15, 0x11); //(1/A11[2][2] 1/A11[2][2] 1/A11[2][2] 1/A11[2][2]) //(Row 3): FMA operations ymm2 = _mm256_fnmadd_pd(ymm3, ymm12, ymm2); ymm1 = _mm256_fnmadd_pd(ymm3, ymm10, ymm1); ymm0 = _mm256_fnmadd_pd(ymm3, ymm7, ymm0); ymm2 = _mm256_mul_pd(ymm2, ymm15); //extract a11 ymm15 = _mm256_permute_pd(ymm14, 0x03); //(1/A11[1][1] 1/A11[1][1] 1/A11[2][2] 1/A11[2][2]) ymm15 = _mm256_permute2f128_pd(ymm15, ymm15, 0x00); //(1/A11[1][1] 1/A11[1][1] 1/A11[1][1] 1/A11[1][1]) //(ROW 2): FMA operations ymm1 = _mm256_fnmadd_pd(ymm2, ymm9, ymm1); ymm0 = _mm256_fnmadd_pd(ymm2, ymm6, ymm0); ymm1 = _mm256_mul_pd(ymm1, ymm15); //extract A00 ymm15 = _mm256_permute_pd(ymm14, 0x00); //(1/A11[0][0] 1/A11[0][0] 1/A11[2][2] 1/A11[2][2]) ymm15 = _mm256_permute2f128_pd(ymm15, ymm15, 0x00); //(1/A11[0][0] 1/A11[0][0] 1/A11[0][0] 1/A11[0][0]) //(Row 1):FMA operations ymm0 = _mm256_fnmadd_pd(ymm1, ymm5, ymm0); ymm0 = _mm256_mul_pd(ymm0, ymm15); _mm256_storeu_pd((double *)b11, ymm0); //store(B11[x][0]) _mm256_storeu_pd((double *)(b11 + cs_b), ymm1); //store(B11[x][1]) _mm256_storeu_pd((double *)(b11 + cs_b_offset[0]), ymm2); //(store(B11[x][2])) _mm256_storeu_pd((double *)(b11 + cs_b_offset[1]), ymm3); //store(B11[x][3]) } if(n_remainder) //implementation for remainder columns(when n is not a multiple of D_NR) { a01 = L + (j+D_NR)*cs_a + (j); //pointer to block of A to be used for GEMM a11 = L + j*cs_a + j; //pointer to block of A to be used for TRSM b10 = B + i + (j+D_NR)*cs_b; //pointer to block of B to be used for GEMM b11 = B + i + j*cs_b; //pointer to block of B to be used for TRSM k_iter = (n-j-D_NR) / D_NR; //number of times GEMM operations to be performed(in blocks of 4x4) ymm16 = _mm256_broadcast_sd((double const *)&AlphaVal); //register to store alpha ///GEMM for previous blocks /// ymm4 = _mm256_setzero_pd(); ymm5 = _mm256_setzero_pd(); ymm6 = _mm256_setzero_pd(); ymm7 = _mm256_setzero_pd(); ///load 4x4 block of b11 if(3 == n_remainder) { ymm1 = _mm256_loadu_pd((double const *)b11+ cs_b); //B11[0][0] B11[1][0] B11[2][0] B11[3][0] ymm2 = _mm256_loadu_pd((double const *)(b11 + cs_b * 2)); //B11[0][1] B11[1][1] B11[2][1] B11[3][1] ymm3 = _mm256_loadu_pd((double const *)(b11 + cs_b * 3)); //B11[0][2] B11[1][2] B11[2][2] B11[3][2] ///GEMM implementation starts/// for(k = 0; k < k_iter; k++) //loop for number of GEMM operations { ptr_a01_dup = a01; //load 4x4 bblock of b10 ymm8 = _mm256_loadu_pd((double const *)b10); //B10[0][0] B10[1][0] B10[2][0] B10[3][0] ymm9 = _mm256_loadu_pd((double const *)(b10 + cs_b)); //B10[0][1] B10[1][1] B10[2][1] B10[3][1] ymm10 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0])); //B10[0][2] B10[1][2] B10[2][2] B10[3][2] ymm11 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[1])); //B10[0][3] B10[1][3] B10[2][3] B10[3][3] //broadcast 1st row of A01 ymm13 = _mm256_broadcast_sd((double const *)(a01 + 1)); //A01[0][1] ymm14 = _mm256_broadcast_sd((double const *)(a01 + 2)); //A01[0][2] ymm15 = _mm256_broadcast_sd((double const *)(a01 + 3)); //A01[0][3] a01 += cs_a; //move to next row of A ymm5 = _mm256_fmadd_pd(ymm13, ymm8, ymm5); //ymm5 += (B10[0][0]*A01[0][1] B10[1][0]*A01[0][1] B10[2][0]*A01[0][1] B10[3][0]*A01[0][1]) ymm6 = _mm256_fmadd_pd(ymm14, ymm8, ymm6); //ymm6 += (B10[0][0]*A01[0][2] B10[1][0]*A01[0][2] B10[2][0]*A01[0][2] B10[3][0]*A01[0][2]) ymm7 = _mm256_fmadd_pd(ymm15, ymm8, ymm7); //ymm7 += (B10[0][0]*A01[0][3] B10[1][0]*A01[0][3] B10[2][0]*A01[0][3] B10[3][0]*A01[0][3]) //broadcast 2nd row of A01 ymm13 = _mm256_broadcast_sd((double const *)(a01 + 1)); //A01[1][1] ymm14 = _mm256_broadcast_sd((double const *)(a01 + 2)); //A01[1][2] ymm15 = _mm256_broadcast_sd((double const *)(a01 + 3)); //A01[1][3] a01 += cs_a; //move to next row of A ymm5 = _mm256_fmadd_pd(ymm13, ymm9, ymm5); //ymm5 += (B10[0][1]*A01[1][1] B10[1][1]*A01[1][1] B10[2][1]*A01[1][1] B10[3][1]*A01[1][1]) ymm6 = _mm256_fmadd_pd(ymm14, ymm9, ymm6); //ymm6 += (B10[0][1]*A01[1][2] B10[1][1]*A01[1][2] B10[2][1]*A01[1][2] B10[3][1]*A01[1][2]) ymm7 = _mm256_fmadd_pd(ymm15, ymm9, ymm7); //ymm7 += (B10[0][1]*A01[1][3] B10[1][1]*A01[1][3] B10[2][1]*A01[1][3] B10[3][1]*A01[1][3]) //braodcast 3rd row of A01 ymm13 = _mm256_broadcast_sd((double const *)(a01 + 1)); //A01[2][1] ymm14 = _mm256_broadcast_sd((double const *)(a01 + 2)); //A01[2][2] ymm15 = _mm256_broadcast_sd((double const *)(a01 + 3)); //A01[2][3] a01 += cs_a; //move to next row of A ymm5 = _mm256_fmadd_pd(ymm13, ymm10, ymm5); //ymm5 += (B10[0][2]*A01[2][1] B10[1][2]*A01[2][1] B10[2][2]*A01[2][1] B10[3][2]*A01[2][1]) ymm6 = _mm256_fmadd_pd(ymm14, ymm10, ymm6); //ymm6 += (B10[0][2]*A01[2][2] B10[1][2]*A01[2][2] B10[2][2]*A01[2][2] B10[3][2]*A01[2][2]) ymm7 = _mm256_fmadd_pd(ymm15, ymm10, ymm7); //ymm7 += (B10[0][2]*A01[2][3] B10[1][2]*A01[2][3] B10[2][2]*A01[2][3] B10[3][2]*A01[2][3]) //broadcast 4th row of A01 ymm13 = _mm256_broadcast_sd((double const *)(a01 + 1)); //A01[3][1] ymm14 = _mm256_broadcast_sd((double const *)(a01 + 2)); //A01[3][2] ymm15 = _mm256_broadcast_sd((double const *)(a01 + 3)); //A01[3][3] a01 += cs_a; //move to next row of A ymm5 = _mm256_fmadd_pd(ymm13, ymm11, ymm5); //ymm5 += (B10[0][3]*A01[3][1] B10[1][3]*A01[3][1] B10[2][3]*A01[3][1] B10[3][3]*A01[3][1]) ymm6 = _mm256_fmadd_pd(ymm14, ymm11, ymm6); //ymm6 += (B10[0][3]*A01[3][2] B10[1][3]*A01[3][2] B10[2][3]*A01[3][2] B10[3][3]*A01[3][2]) ymm7 = _mm256_fmadd_pd(ymm15, ymm11, ymm7); //ymm7 += (B10[0][3]*A01[3][3] B10[1][3]*A01[3][3] B10[2][3]*A01[3][3] B10[3][3]*A01[3][3]) b10 += D_NR * cs_b; //pointer math to find next block of B for GEMM a01 = ptr_a01_dup + (D_NR * cs_a); //pointer math to find next block of A for GEMM } ///GEMM code end/// ymm15 = _mm256_broadcast_sd((double const *)&AlphaVal); //register to store alpha ymm1 = _mm256_fmsub_pd(ymm1, ymm15, ymm5); //B11[x][1] -= ymm5 ymm2 = _mm256_fmsub_pd(ymm2, ymm15, ymm6); //B11[x][2] -= ymm6 ymm3 = _mm256_fmsub_pd(ymm3, ymm15, ymm7); //B11[x][3] -= ymm7 ///implement TRSM/// ///read 4x4 block of A11/// //1st col ymm4 = _mm256_broadcast_sd((double const *)(&ones)); //A11[0][0] a11 += cs_a; //2nd col ymm8 = _mm256_broadcast_sd((double const *)(a11+1)); //A11[0][1] a11 += cs_a; //3rd col ymm9 = _mm256_broadcast_sd((double const *)(a11+1)); //A11[0][1] ymm11 = _mm256_broadcast_sd((double const *)(a11+2)); //A11[0][1] a11 += cs_a; //4th col ymm10 = _mm256_broadcast_sd((double const *)(a11+1)); //A11[0][1] ymm12 = _mm256_broadcast_sd((double const *)(a11+2)); //A11[0][1] ymm13 = _mm256_broadcast_sd((double const *)(a11+3)); //A11[0][1] ymm14 = _mm256_broadcast_sd((double const *)&ones); //compute reciprocals of A(i,i) and broadcast in registers ymm4 = _mm256_unpacklo_pd(ymm4, ymm8); //A11[0][0] A11[1][1] A11[0][0] A11[1][1] ymm8 = _mm256_unpacklo_pd(ymm11, ymm13); //A11[2][2] A11[3][3] A11[2][2] A11[3][3] ymm15 = _mm256_blend_pd(ymm4, ymm8, 0x0C); //A11[0][0] A11[1][1] A11[2][2] A11[3][3] ymm14 = _mm256_div_pd(ymm14, ymm15); // 1/A11[0][0] 1/A11[1][1] 1/A11[2][2] 1/A11[3][3] //extract a33 ymm15 = _mm256_permute_pd(ymm14, 0x0C); //(1/A11[0][0] 1/A11[0][0] 1/A11[3][3] 1/A11[3][3]) ymm15 = _mm256_permute2f128_pd(ymm15, ymm15, 0x11); //(1/A11[3][3] 1/A11[3][3] 1/A11[3][3] 1/A11[3][3]) ymm3 = _mm256_mul_pd(ymm3, ymm15); //extract a22 ymm15 = _mm256_permute_pd(ymm14, 0x00); //(1/A11[0][0] 1/A11[0][0] 1/A11[2][2] 1/A11[2][2]) ymm15 = _mm256_permute2f128_pd(ymm15, ymm15, 0x11); //(1/A11[2][2] 1/A11[2][2] 1/A11[2][2] 1/A11[2][2]) //(Row 3): FMA operations ymm2 = _mm256_fnmadd_pd(ymm3, ymm12, ymm2); ymm1 = _mm256_fnmadd_pd(ymm3, ymm10, ymm1); ymm2 = _mm256_mul_pd(ymm2, ymm15); //extract a11 ymm15 = _mm256_permute_pd(ymm14, 0x03); //(1/A11[1][1] 1/A11[1][1] 1/A11[2][2] 1/A11[2][2]) ymm15 = _mm256_permute2f128_pd(ymm15, ymm15, 0x00); //(1/A11[1][1] 1/A11[1][1] 1/A11[1][1] 1/A11[1][1]) //(ROW 2): FMA operations ymm1 = _mm256_fnmadd_pd(ymm2, ymm9, ymm1); ymm1 = _mm256_mul_pd(ymm1, ymm15); _mm256_storeu_pd((double *)(b11 + cs_b), ymm1); //store(B11[x][1]) _mm256_storeu_pd((double *)(b11 + cs_b_offset[0]), ymm2); //(store(B11[x][2])) _mm256_storeu_pd((double *)(b11 + cs_b*3), ymm3); //store(B11[x][0]) } else if(2 == n_remainder) { ymm2 = _mm256_loadu_pd((double const *)(b11 + cs_b * 2)); //B11[0][0] B11[1][0] B11[2][0] B11[3][0] ymm3 = _mm256_loadu_pd((double const *)(b11 + cs_b * 3)); //B11[0][1] B11[1][1] B11[2][1] B11[3][1] ///GEMM implementation starts/// for(k = 0; k < k_iter; k++) //loop for number of GEMM operations { ptr_a01_dup = a01; //load 4x4 bblock of b10 ymm8 = _mm256_loadu_pd((double const *)b10); //B10[0][0] B10[1][0] B10[2][0] B10[3][0] ymm9 = _mm256_loadu_pd((double const *)(b10 + cs_b)); //B10[0][1] B10[1][1] B10[2][1] B10[3][1] ymm10 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0])); //B10[0][2] B10[1][2] B10[2][2] B10[3][2] ymm11 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[1])); //B10[0][3] B10[1][3] B10[2][3] B10[3][3] //broadcast 1st row of A01 ymm14 = _mm256_broadcast_sd((double const *)(a01 + 2)); //A01[0][2] ymm15 = _mm256_broadcast_sd((double const *)(a01 + 3)); //A01[0][3] a01 += cs_a; //move to next row of A ymm6 = _mm256_fmadd_pd(ymm14, ymm8, ymm6); //ymm6 += (B10[0][0]*A01[0][2] B10[1][0]*A01[0][2] B10[2][0]*A01[0][2] B10[3][0]*A01[0][2]) ymm7 = _mm256_fmadd_pd(ymm15, ymm8, ymm7); //ymm7 += (B10[0][0]*A01[0][3] B10[1][0]*A01[0][3] B10[2][0]*A01[0][3] B10[3][0]*A01[0][3]) //broadcast 2nd row of A01 ymm14 = _mm256_broadcast_sd((double const *)(a01 + 2)); //A01[1][2] ymm15 = _mm256_broadcast_sd((double const *)(a01 + 3)); //A01[1][3] a01 += cs_a; //move to next row of A ymm6 = _mm256_fmadd_pd(ymm14, ymm9, ymm6); //ymm6 += (B10[0][1]*A01[1][2] B10[1][1]*A01[1][2] B10[2][1]*A01[1][2] B10[3][1]*A01[1][2]) ymm7 = _mm256_fmadd_pd(ymm15, ymm9, ymm7); //ymm7 += (B10[0][1]*A01[1][3] B10[1][1]*A01[1][3] B10[2][1]*A01[1][3] B10[3][1]*A01[1][3]) //braodcast 3rd row of A01 ymm14 = _mm256_broadcast_sd((double const *)(a01 + 2)); //A01[2][2] ymm15 = _mm256_broadcast_sd((double const *)(a01 + 3)); //A01[2][3] a01 += cs_a; //move to next row of A ymm6 = _mm256_fmadd_pd(ymm14, ymm10, ymm6); //ymm6 += (B10[0][2]*A01[2][2] B10[1][2]*A01[2][2] B10[2][2]*A01[2][2] B10[3][2]*A01[2][2]) ymm7 = _mm256_fmadd_pd(ymm15, ymm10, ymm7); //ymm7 += (B10[0][2]*A01[2][3] B10[1][2]*A01[2][3] B10[2][2]*A01[2][3] B10[3][2]*A01[2][3]) //broadcast 4th row of A01 ymm14 = _mm256_broadcast_sd((double const *)(a01 + 2)); //A01[3][2] ymm15 = _mm256_broadcast_sd((double const *)(a01 + 3)); //A01[3][3] a01 += cs_a; //move to next row of A ymm6 = _mm256_fmadd_pd(ymm14, ymm11, ymm6); //ymm6 += (B10[0][3]*A01[3][2] B10[1][3]*A01[3][2] B10[2][3]*A01[3][2] B10[3][3]*A01[3][2]) ymm7 = _mm256_fmadd_pd(ymm15, ymm11, ymm7); //ymm7 += (B10[0][3]*A01[3][3] B10[1][3]*A01[3][3] B10[2][3]*A01[3][3] B10[3][3]*A01[3][3]) b10 += D_NR * cs_b; //pointer math to find next block of B for GEMM a01 = ptr_a01_dup + (D_NR * cs_a); //pointer math to find next block of A for GEMM } ///GEMM code end/// ymm15 = _mm256_broadcast_sd((double const *)&AlphaVal); //register to store alpha ymm2 = _mm256_fmsub_pd(ymm2, ymm15, ymm6); //B11[x][2] -= ymm6 ymm3 = _mm256_fmsub_pd(ymm3, ymm15, ymm7); //B11[x][3] -= ymm7 ///implement TRSM/// ///read 4x4 block of A11/// //1st col a11 += 2 * cs_a; //3rd col ymm11 = _mm256_broadcast_sd((double const *)(a11+2)); //A11[0][1] a11 += cs_a; //4th col ymm12 = _mm256_broadcast_sd((double const *)(a11+2)); //A11[0][1] ymm13 = _mm256_broadcast_sd((double const *)(a11+3)); //A11[0][1] ymm14 = _mm256_broadcast_sd((double const *)&ones); //compute reciprocals of A(i,i) and broadcast in registers ymm8 = _mm256_unpacklo_pd(ymm11, ymm13); //A11[2][2] A11[3][3] A11[2][2] A11[3][3] ymm15 = _mm256_blend_pd(ymm14, ymm8, 0x0C); //A11[0][0] A11[1][1] A11[2][2] A11[3][3] ymm14 = _mm256_div_pd(ymm14, ymm15); // 1/A11[0][0] 1/A11[1][1] 1/A11[2][2] 1/A11[3][3] //extract a33 ymm15 = _mm256_permute_pd(ymm14, 0x0C); //(1/A11[0][0] 1/A11[0][0] 1/A11[3][3] 1/A11[3][3]) ymm15 = _mm256_permute2f128_pd(ymm15, ymm15, 0x11); //(1/A11[3][3] 1/A11[3][3] 1/A11[3][3] 1/A11[3][3]) ymm3 = _mm256_mul_pd(ymm3, ymm15); //extract a22 ymm15 = _mm256_permute_pd(ymm14, 0x00); //(1/A11[0][0] 1/A11[0][0] 1/A11[2][2] 1/A11[2][2]) ymm15 = _mm256_permute2f128_pd(ymm15, ymm15, 0x11); //(1/A11[2][2] 1/A11[2][2] 1/A11[2][2] 1/A11[2][2]) //(Row 3): FMA operations ymm2 = _mm256_fnmadd_pd(ymm3, ymm12, ymm2); ymm2 = _mm256_mul_pd(ymm2, ymm15); _mm256_storeu_pd((double *)(b11+ cs_b * 2), ymm2); //store(B11[x][0]) _mm256_storeu_pd((double *)(b11 + cs_b * 3), ymm3); //store(B11[x][1]) } else if(1 == n_remainder) { ymm3 = _mm256_loadu_pd((double const *)(b11 + cs_b * 3)); //B11[0][0] B11[1][0] B11[2][0] B11[3][0] ///GEMM implementation starts/// for(k = 0; k < k_iter; k++) //loop for number of GEMM operations { ptr_a01_dup = a01; //load 4x4 bblock of b10 ymm8 = _mm256_loadu_pd((double const *)b10); //B10[0][0] B10[1][0] B10[2][0] B10[3][0] ymm9 = _mm256_loadu_pd((double const *)(b10 + cs_b)); //B10[0][1] B10[1][1] B10[2][1] B10[3][1] ymm10 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0])); //B10[0][2] B10[1][2] B10[2][2] B10[3][2] ymm11 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[1])); //B10[0][3] B10[1][3] B10[2][3] B10[3][3] //broadcast 1st row of A01 ymm15 = _mm256_broadcast_sd((double const *)(a01 + 3)); //A01[0][3] a01 += cs_a; //move to next row of A ymm7 = _mm256_fmadd_pd(ymm15, ymm8, ymm7); //ymm7 += (B10[0][0]*A01[0][3] B10[1][0]*A01[0][3] B10[2][0]*A01[0][3] B10[3][0]*A01[0][3]) //broadcast 2nd row of A01 ymm15 = _mm256_broadcast_sd((double const *)(a01 + 3)); //A01[1][3] a01 += cs_a; //move to next row of A ymm7 = _mm256_fmadd_pd(ymm15, ymm9, ymm7); //ymm7 += (B10[0][1]*A01[1][3] B10[1][1]*A01[1][3] B10[2][1]*A01[1][3] B10[3][1]*A01[1][3]) //braodcast 3rd row of A01 ymm15 = _mm256_broadcast_sd((double const *)(a01 + 3)); //A01[2][3] a01 += cs_a; //move to next row of A ymm7 = _mm256_fmadd_pd(ymm15, ymm10, ymm7); //ymm7 += (B10[0][2]*A01[2][3] B10[1][2]*A01[2][3] B10[2][2]*A01[2][3] B10[3][2]*A01[2][3]) //broadcast 4th row of A01 ymm15 = _mm256_broadcast_sd((double const *)(a01 + 3)); //A01[3][3] a01 += cs_a; //move to next row of A ymm7 = _mm256_fmadd_pd(ymm15, ymm11, ymm7); //ymm7 += (B10[0][3]*A01[3][3] B10[1][3]*A01[3][3] B10[2][3]*A01[3][3] B10[3][3]*A01[3][3]) b10 += D_NR * cs_b; //pointer math to find next block of B for GEMM a01 = ptr_a01_dup + (D_NR * cs_a); //pointer math to find next block of A for GEMM } ///GEMM code end/// ymm15 = _mm256_broadcast_sd((double const *)&AlphaVal); //register to store alpha ymm3 = _mm256_fmsub_pd(ymm3, ymm15, ymm7); //B11[x][3] -= ymm7 ///implement TRSM/// ///read 4x4 block of A11/// a11 += 3 * cs_a; //4th col ymm13 = _mm256_broadcast_sd((double const *)(a11+3)); //A11[0][1] ymm14 = _mm256_broadcast_sd((double const *)&ones); //compute reciprocals of A(i,i) and broadcast in registers ymm14 = _mm256_div_pd(ymm14, ymm13); // 1/A11[0][0] 1/A11[1][1] 1/A11[2][2] 1/A11[3][3] ymm3 = _mm256_mul_pd(ymm3, ymm14); _mm256_storeu_pd((double *)(b11 + cs_b * 3), ymm3); //store(B11[x][0]) } } m_remainder -= 4; i -= 4; } if(m_remainder) ///implementation for remainder rows { dtrsm_small_XAutB(L, B, AlphaVal, m_remainder, n, cs_a, cs_b); } return BLIS_SUCCESS; } /*implements TRSM for the case XA = alpha * B *A is lower triangular, unit-diagonal, no transpose *dimensions: X:mxn A:nxn B: mxn */ /* <---b11 <---a11 ***************** * *b01*b11* * * * * ^ * * * * * ^ * * | ***************** | ******* | * * * * * | * * * | * * * * * a01* * * b10 ***************** ************* * * * * * * * * * * * * * * * * * * ***************** ******************* */ static err_t bli_dtrsm_small_XAutB_unitDiag( side_t side, obj_t* AlphaObj, obj_t* a, obj_t* b, cntx_t* cntx, cntl_t* cntl ) { dim_t D_MR = 8; //block dimension along the rows dim_t D_NR = 4; //block dimension along the columns dim_t m = bli_obj_length(b); //number of rows dim_t n = bli_obj_width(b); //number of columns dim_t m_remainder = m & 7; //number of corner rows dim_t n_remainder = n & 3; //number of corner columns dim_t cs_a = bli_obj_col_stride(a); //column stride of matrix A dim_t cs_b = bli_obj_col_stride(b); //column stride of matrix B #ifdef BLIS_ENABLE_SMALL_MATRIX_ROME if((m < D_BLIS_SMALL_MATRIX_THRES_TRSM_XAUTB_ROME && n > D_BLIS_SMALL_MATRIX_THRES_TRSM_XAUTB_ROME) ||(m > D_BLIS_SMALL_MATRIX_THRES_TRSM_XAUTB_ROME && n > D_BLIS_SMALL_MATRIX_THRES_TRSM_XALB_ROME_COL_PANEL_N) ) return BLIS_NOT_YET_IMPLEMENTED; #else if(bli_max(m,n) > D_BLIS_SMALL_MATRIX_THRES_TRSM_NAPLES) { return BLIS_NOT_YET_IMPLEMENTED; } #endif dim_t i, j, k; //loop variablse dim_t k_iter; //determines the number of GEMM operations to be done dim_t cs_b_offset[2]; //pre-calculated strides double AlphaVal = *(double *)AlphaObj->buffer; //value of Alpha double* restrict L = a->buffer; //pointer to matrix A double* restrict B = b->buffer; //pointer to matrix B double *a01, *a11, *b10, *b11; //pointers for GEMM and TRSM blocks double *ptr_a01_dup; cs_b_offset[0] = cs_b << 1; //cs_b_offset[0] = cs_b * 2; cs_b_offset[1] = cs_b_offset[0] + cs_b;//cs_b_offset[1] = cs_b * 3; //ymm scratch reginsters __m256d ymm0, ymm1, ymm2, ymm3; __m256d ymm4, ymm5, ymm6, ymm7; __m256d ymm8, ymm9, ymm10, ymm11; __m256d ymm12, ymm13, ymm14, ymm15; __m256d ymm16; for(i = (m-D_MR); (i+1) > 0; i -= D_MR) //loop along 'M' direction { for(j = (n-D_NR); (j+1) > 0; j -= D_NR) //loop along 'N' direction { a01 = L + (j+D_NR)*cs_a +(j); //pointer to block of A to be used in GEMM a11 = L + j*cs_a + j; //pointer to block of A to be used for TRSM b10 = B + i + (j+D_NR)*cs_b; //pointer to block of B to be used in GEMM b11 = B + (i) + (j)*cs_b; //pointer to block of B to be used for TRSM k_iter = (n-j-D_NR) / D_NR; //number of GEMM operations to be done(in blocks of 4x4) ymm0 = _mm256_setzero_pd(); ymm1 = _mm256_setzero_pd(); ymm2 = _mm256_setzero_pd(); ymm3 = _mm256_setzero_pd(); ymm4 = _mm256_setzero_pd(); ymm5 = _mm256_setzero_pd(); ymm6 = _mm256_setzero_pd(); ymm7 = _mm256_setzero_pd(); ///GEMM implementation starts/// for(k = 0; k < k_iter; k++) //loop for number of GEMM operations { ptr_a01_dup = a01; //broadcast 1st row of A01 ymm8 = _mm256_broadcast_sd((double const *)(a01 + 0)); //A01[0][0] ymm9 = _mm256_broadcast_sd((double const *)(a01 + 1)); //A01[0][1] ymm10 = _mm256_broadcast_sd((double const *)(a01 + 2)); //A01[0][2] ymm11 = _mm256_broadcast_sd((double const *)(a01 + 3)); //A01[0][3] a01 += cs_a; //move to next row //load 8x2 block of B10 ymm12 = _mm256_loadu_pd((double const *)b10); //B10[0][0] B10[1][0] B10[2][0] B10[3][0] ymm13 = _mm256_loadu_pd((double const *)(b10 + D_NR)); //B10[4][0] B10[5][0] B10[6][0] B10[7][0] ymm14 = _mm256_loadu_pd((double const *)(b10 + cs_b)); //B10[0][1] B10[1][1] B10[2][1] B10[3][1] ymm15 = _mm256_loadu_pd((double const *)(b10 + cs_b + D_NR)); //B10[4][1] B10[5][1] B10[6][1] B10[7][1] ymm0 = _mm256_fmadd_pd(ymm8, ymm12, ymm0); //ymm0 += (B10[0][0]*A01[0][0] B10[1][0]*A01[0][0] B10[2][0]*A01[0][0] B10[3][0]*A01[0][0]) ymm1 = _mm256_fmadd_pd(ymm9, ymm12, ymm1); //ymm1 += (B10[0][0]*A01[0][1] B10[1][0]*A01[0][1] B10[2][0]*A01[0][1] B10[3][0]*A01[0][1]) ymm2 = _mm256_fmadd_pd(ymm10, ymm12, ymm2); //ymm2 += (B10[0][0]*A01[0][2] B10[1][0]*A01[0][2] B10[2][0]*A01[0][2] B10[3][0]*A01[0][2]) ymm3 = _mm256_fmadd_pd(ymm11, ymm12, ymm3); //ymm3 += (B10[0][0]*A01[0][3] B10[1][0]*A01[0][3] B10[2][0]*A01[0][3] B10[3][0]*A01[0][3]) ymm4 = _mm256_fmadd_pd(ymm8, ymm13, ymm4); //ymm4 += (B10[4][0]*A01[0][0] B10[5][0]*A01[0][0] B10[6][0]*A01[0][0] B10[7][0]*A01[0][0]) ymm5 = _mm256_fmadd_pd(ymm9, ymm13, ymm5); //ymm5 += (B10[4][0]*A01[0][1] B10[5][0]*A01[0][1] B10[6][0]*A01[0][1] B10[7][0]*A01[0][1]) ymm6 = _mm256_fmadd_pd(ymm10, ymm13, ymm6); //ymm6 += (B10[4][0]*A01[0][2] B10[5][0]*A01[0][2] B10[6][0]*A01[0][2] B10[7][0]*A01[0][2]) ymm7 = _mm256_fmadd_pd(ymm11, ymm13, ymm7); //ymm7 += (B10[4][0]*A01[0][3] B10[5][0]*A01[0][3] B10[6][0]*A01[0][3] B10[7][0]*A01[0][3]) //broadcast 2nd row of A01 ymm8 = _mm256_broadcast_sd((double const *)(a01 + 0)); //A01[1][0] ymm9 = _mm256_broadcast_sd((double const *)(a01 + 1)); //A01[1][1] ymm10 = _mm256_broadcast_sd((double const *)(a01 + 2)); //A01[1][2] ymm11 = _mm256_broadcast_sd((double const *)(a01 + 3)); //A01[1][3] a01 += cs_a; //move to next row of A ymm0 = _mm256_fmadd_pd(ymm8, ymm14, ymm0); //ymm0 += (B10[0][1]*A01[0][0] B10[1][1]*A01[0][0] B10[2][1]*A01[0][0] B10[3][1]*A01[0][0]) ymm1 = _mm256_fmadd_pd(ymm9, ymm14, ymm1); //ymm1 += (B10[0][1]*A01[0][1] B10[1][1]*A01[0][1] B10[2][1]*A01[0][1] B10[3][1]*A01[0][1]) ymm2 = _mm256_fmadd_pd(ymm10, ymm14, ymm2); //ymm2 += (B10[0][1]*A01[0][2] B10[1][1]*A01[0][2] B10[2][1]*A01[0][2] B10[3][1]*A01[0][2]) ymm3 = _mm256_fmadd_pd(ymm11, ymm14, ymm3); //ymm3 += (B10[0][1]*A01[0][3] B10[1][1]*A01[0][3] B10[2][1]*A01[0][3] B10[3][1]*A01[0][3]) ymm4 = _mm256_fmadd_pd(ymm8, ymm15, ymm4); //ymm4 += (B10[4][1]*A01[0][0] B10[5][1]*A01[0][0] B10[6][1]*A01[0][0] B10[7][1]*A01[0][0]) ymm5 = _mm256_fmadd_pd(ymm9, ymm15, ymm5); //ymm5 += (B10[4][1]*A01[0][1] B10[5][1]*A01[0][1] B10[6][1]*A01[0][1] B10[7][1]*A01[0][1]) ymm6 = _mm256_fmadd_pd(ymm10, ymm15, ymm6); //ymm6 += (B10[4][1]*A01[0][2] B10[5][1]*A01[0][2] B10[6][1]*A01[0][2] B10[7][1]*A01[0][2]) ymm7 = _mm256_fmadd_pd(ymm11, ymm15, ymm7); //ymm7 += (B10[4][1]*A01[0][3] B10[5][1]*A01[0][3] B10[6][1]*A01[0][3] B10[7][1]*A01[0][3]) //broadcast 3rd row of A01 ymm8 = _mm256_broadcast_sd((double const *)(a01 + 0)); //A01[2][0] ymm9 = _mm256_broadcast_sd((double const *)(a01 + 1)); //A01[2][1] ymm10 = _mm256_broadcast_sd((double const *)(a01 + 2)); //A01[2][2] ymm11 = _mm256_broadcast_sd((double const *)(a01 + 3)); //A01[2][3] a01 += cs_a; //move to next row of A01 //load next 8x2 block of B10 ymm12 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0])); //(B10[0][2] B10[1][2] B10[2][2] B10[3][2]) ymm13 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + D_NR)); //(B10[4][2] B10[5][2] B10[6][2] B10[7][2]) ymm14 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + cs_b)); //(B10[0][3] B10[1][3] B10[2][3] B10[3][3]) ymm15 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + cs_b + D_NR)); //(B10[4][3] B10[5][3] B10[6][3] B10[7][3]) ymm0 = _mm256_fmadd_pd(ymm8, ymm12, ymm0); //ymm0 += (B10[0][2]*A01[0][0] B10[1][2]*A01[0][0] B10[2][2]*A01[0][0] B10[3][2]*A01[0][0]) ymm1 = _mm256_fmadd_pd(ymm9, ymm12, ymm1); //ymm1 += (B10[0][2]*A01[0][1] B10[1][2]*A01[0][1] B10[2][2]*A01[0][1] B10[3][2]*A01[0][1]) ymm2 = _mm256_fmadd_pd(ymm10, ymm12, ymm2); //ymm2 += (B10[0][2]*A01[0][2] B10[1][2]*A01[0][2] B10[2][2]*A01[0][2] B10[3][2]*A01[0][2]) ymm3 = _mm256_fmadd_pd(ymm11, ymm12, ymm3); //ymm3 += (B10[0][2]*A01[0][3] B10[1][2]*A01[0][3] B10[2][2]*A01[0][3] B10[3][2]*A01[0][3]) ymm4 = _mm256_fmadd_pd(ymm8, ymm13, ymm4); //ymm4 += (B10[4][2]*A01[0][0] B10[5][2]*A01[0][0] B10[6][2]*A01[0][0] B10[7][2]*A01[0][0]) ymm5 = _mm256_fmadd_pd(ymm9, ymm13, ymm5); //ymm5 += (B10[4][2]*A01[0][1] B10[5][2]*A01[0][1] B10[6][2]*A01[0][1] B10[7][2]*A01[0][1]) ymm6 = _mm256_fmadd_pd(ymm10, ymm13, ymm6); //ymm6 += (B10[4][2]*A01[0][2] B10[5][2]*A01[0][2] B10[6][2]*A01[0][2] B10[7][2]*A01[0][2]) ymm7 = _mm256_fmadd_pd(ymm11, ymm13, ymm7); //ymm7 += (B10[4][2]*A01[0][3] B10[5][2]*A01[0][3] B10[6][2]*A01[0][3] B10[7][2]*A01[0][3]) //broadcast 4th row of A01 ymm8 = _mm256_broadcast_sd((double const *)(a01 + 0)); //A01[3][0] ymm9 = _mm256_broadcast_sd((double const *)(a01 + 1)); //A01[3][1] ymm10 = _mm256_broadcast_sd((double const *)(a01 + 2)); //A01[3][2] ymm11 = _mm256_broadcast_sd((double const *)(a01 + 3)); //A01[3][3] a01 += cs_a; //move to next row of A01 ymm0 = _mm256_fmadd_pd(ymm8, ymm14, ymm0); //ymm0 += (B10[0][3]*A01[0][0] B10[1][3]*A01[0][0] B10[2][3]*A01[0][0] B10[3][3]*A01[0][0]) ymm1 = _mm256_fmadd_pd(ymm9, ymm14, ymm1); //ymm1 += (B10[0][3]*A01[0][1] B10[1][3]*A01[0][1] B10[2][3]*A01[0][1] B10[3][3]*A01[0][1]) ymm2 = _mm256_fmadd_pd(ymm10, ymm14, ymm2); //ymm2 += (B10[0][3]*A01[0][2] B10[1][3]*A01[0][2] B10[2][3]*A01[0][2] B10[3][3]*A01[0][2]) ymm3 = _mm256_fmadd_pd(ymm11, ymm14, ymm3); //ymm3 += (B10[0][3]*A01[0][3] B10[1][3]*A01[0][3] B10[2][3]*A01[0][3] B10[3][3]*A01[0][3]) ymm4 = _mm256_fmadd_pd(ymm8, ymm15, ymm4); //ymm4 += (B10[4][3]*A01[0][0] B10[5][3]*A01[0][0] B10[6][3]*A01[0][0] B10[7][3]*A01[0][0]) ymm5 = _mm256_fmadd_pd(ymm9, ymm15, ymm5); //ymm5 += (B10[4][3]*A01[0][1] B10[5][3]*A01[0][1] B10[6][3]*A01[0][1] B10[7][3]*A01[0][1]) ymm6 = _mm256_fmadd_pd(ymm10, ymm15, ymm6); //ymm6 += (B10[4][3]*A01[0][2] B10[5][3]*A01[0][2] B10[6][3]*A01[0][2] B10[7][3]*A01[0][2]) ymm7 = _mm256_fmadd_pd(ymm11, ymm15, ymm7); //ymm7 += (B10[4][3]*A01[0][3] B10[5][3]*A01[0][3] B10[6][3]*A01[0][3] B10[7][3]*A01[0][3]) b10 += D_NR * cs_b; //pointer math to find next block of B for GEMM a01 = ptr_a01_dup + (D_NR * cs_a); //pointer math to find next block of A for GEMM } ///GEMM code ends/// ymm16 = _mm256_broadcast_sd((double const *)&AlphaVal); //load 8x4 block of B11 ymm8 = _mm256_loadu_pd((double const *)b11); //B11[0][0] B11[1][0] B11[2][0] B11[3][0] ymm12 = _mm256_loadu_pd((double const *)(b11 + D_NR)); //B11[4][0] B11[5][0] B11[6][0] B11[7][0] ymm9 = _mm256_loadu_pd((double const *)(b11 + cs_b)); //B11[0][1] B11[1][1] B11[2][1] B11[3][1] ymm13 = _mm256_loadu_pd((double const *)(b11 + cs_b + D_NR)); //B11[4][1] B11[5][1] B11[6][1] B11[7][1] ymm10 = _mm256_loadu_pd((double const *)(b11 + cs_b_offset[0])); //B11[0][2] B11[1][2] B11[2][2] B11[3][2] ymm14 = _mm256_loadu_pd((double const *)(b11 + cs_b_offset[0] + D_NR)); //B11[4][2] B11[5][2] B11[6][2] B11[7][2] ymm11 = _mm256_loadu_pd((double const *)(b11 + cs_b_offset[1])); //B11[0][3] B11[1][3] B11[2][3] B11[3][3] ymm15 = _mm256_loadu_pd((double const *)(b11 + cs_b_offset[1] + D_NR)); //B11[4][3] B11[5][3] B11[6][3] B11[7][3] ymm8 = _mm256_fmsub_pd(ymm8, ymm16, ymm0); //B11[0-3][0] * alpha -= ymm0 ymm9 = _mm256_fmsub_pd(ymm9, ymm16, ymm1); //B11[4-7][0] * alpha-= ymm1 ymm10 = _mm256_fmsub_pd(ymm10, ymm16, ymm2); //B11[0-3][1] * alpha-= ymm2 ymm11 = _mm256_fmsub_pd(ymm11, ymm16, ymm3); //B11[4-7][1] * alpha -= ymm3 ymm12 = _mm256_fmsub_pd(ymm12, ymm16, ymm4); //B11[0-3][2] * alpha -= ymm4 ymm13 = _mm256_fmsub_pd(ymm13, ymm16, ymm5); //B11[4-7][2] * alpha -= ymm5 ymm14 = _mm256_fmsub_pd(ymm14, ymm16, ymm6); //B11[0-3][3] * alpha -= ymm6 ymm15 = _mm256_fmsub_pd(ymm15, ymm16, ymm7); //B11[4-7][3] * alpha -= ymm7 ///implement TRSM/// ///read 4x4 block of A11/// //1st col a11 += cs_a; //2nd col ymm1 = _mm256_broadcast_sd((double const *)(a11+0)); //A11[0][1] a11 += cs_a; //3rd col ymm3 = _mm256_broadcast_sd((double const *)(a11+0)); //A11[0][1] ymm4 = _mm256_broadcast_sd((double const *)(a11+1)); //A11[0][1] a11 += cs_a; //4th col ymm2 = _mm256_broadcast_sd((double const *)(a11+0)); //A11[0][1] ymm5 = _mm256_broadcast_sd((double const *)(a11+1)); //A11[0][1] ymm6 = _mm256_broadcast_sd((double const *)(a11+2)); //A11[0][1] //(Row 3): FMA operations ymm10 = _mm256_fnmadd_pd(ymm11, ymm6, ymm10); ymm9 = _mm256_fnmadd_pd(ymm11, ymm5, ymm9); ymm8 = _mm256_fnmadd_pd(ymm11, ymm2, ymm8); //(Row 3): FMA operations ymm14 = _mm256_fnmadd_pd(ymm15, ymm6, ymm14); ymm13 = _mm256_fnmadd_pd(ymm15, ymm5, ymm13); ymm12 = _mm256_fnmadd_pd(ymm15, ymm2, ymm12); //(ROW 2): FMA operations ymm9 = _mm256_fnmadd_pd(ymm10, ymm4, ymm9); ymm8 = _mm256_fnmadd_pd(ymm10, ymm3, ymm8); ymm13 = _mm256_fnmadd_pd(ymm14, ymm4, ymm13); ymm12 = _mm256_fnmadd_pd(ymm14, ymm3, ymm12); //(Row 1):FMA operations ymm8 = _mm256_fnmadd_pd(ymm9, ymm1, ymm8); ymm12 = _mm256_fnmadd_pd(ymm13, ymm1, ymm12); _mm256_storeu_pd((double *)b11, ymm8); //store(B11[x][0]) _mm256_storeu_pd((double *)(b11 + D_NR), ymm12); //store(B11[x][0]) _mm256_storeu_pd((double *)(b11 + cs_b), ymm9); //store(B11[x][1]) _mm256_storeu_pd((double *)(b11 + cs_b + D_NR), ymm13); //store(B11[x][1]) _mm256_storeu_pd((double *)(b11 + cs_b_offset[0]), ymm10); //(store(B11[x][2])) _mm256_storeu_pd((double *)(b11 + cs_b_offset[0] + D_NR), ymm14); //(store(B11[x][2])) _mm256_storeu_pd((double *)(b11 + cs_b_offset[1]), ymm11); //store(B11[x][3]) _mm256_storeu_pd((double *)(b11 + cs_b_offset[1] + D_NR), ymm15); //store(B11[x][3]) } if(n_remainder) //implementation for remainder columns(when n is not multiple of D_NR) { a01 = L + (j+D_NR)*cs_a +(j); //pointer to block of A to be used in GEMM a11 = L + j*cs_a + j; //pointer to block of A to be used for TRSM b10 = B + i + (j+D_NR)*cs_b; //pointer to block of B to be used in GEMM b11 = B + (i) + (j)*cs_b; //pointer to block of B to be used for TRSM k_iter = (n-j-D_NR) / D_NR; //number of GEMM operations to be done(in blocks of 4x4) ymm0 = _mm256_setzero_pd(); ymm1 = _mm256_setzero_pd(); ymm2 = _mm256_setzero_pd(); ymm3 = _mm256_setzero_pd(); ymm4 = _mm256_setzero_pd(); ymm5 = _mm256_setzero_pd(); ymm6 = _mm256_setzero_pd(); ymm7 = _mm256_setzero_pd(); //load 8x4 block of B11 if(3 == n_remainder) { ///GEMM implementation starts/// for(k = 0; k < k_iter; k++) //loop for number of GEMM operations { ptr_a01_dup = a01; //broadcast 1st row of A01 ymm9 = _mm256_broadcast_sd((double const *)(a01 + 1)); //A01[0][1] ymm10 = _mm256_broadcast_sd((double const *)(a01 + 2)); //A01[0][2] ymm11 = _mm256_broadcast_sd((double const *)(a01 + 3)); //A01[0][3] a01 += cs_a; //move to next row //load 8x2 block of B10 ymm12 = _mm256_loadu_pd((double const *)b10); //B10[0][0] B10[1][0] B10[2][0] B10[3][0] ymm13 = _mm256_loadu_pd((double const *)(b10 + D_NR)); //B10[4][0] B10[5][0] B10[6][0] B10[7][0] ymm14 = _mm256_loadu_pd((double const *)(b10 + cs_b)); //B10[0][1] B10[1][1] B10[2][1] B10[3][1] ymm15 = _mm256_loadu_pd((double const *)(b10 + cs_b + D_NR)); //B10[4][1] B10[5][1] B10[6][1] B10[7][1] ymm1 = _mm256_fmadd_pd(ymm9, ymm12, ymm1); //ymm1 += (B10[0][0]*A01[0][1] B10[1][0]*A01[0][1] B10[2][0]*A01[0][1] B10[3][0]*A01[0][1]) ymm2 = _mm256_fmadd_pd(ymm10, ymm12, ymm2); //ymm2 += (B10[0][0]*A01[0][2] B10[1][0]*A01[0][2] B10[2][0]*A01[0][2] B10[3][0]*A01[0][2]) ymm3 = _mm256_fmadd_pd(ymm11, ymm12, ymm3); //ymm3 += (B10[0][0]*A01[0][3] B10[1][0]*A01[0][3] B10[2][0]*A01[0][3] B10[3][0]*A01[0][3]) ymm5 = _mm256_fmadd_pd(ymm9, ymm13, ymm5); //ymm5 += (B10[4][0]*A01[0][1] B10[5][0]*A01[0][1] B10[6][0]*A01[0][1] B10[7][0]*A01[0][1]) ymm6 = _mm256_fmadd_pd(ymm10, ymm13, ymm6); //ymm6 += (B10[4][0]*A01[0][2] B10[5][0]*A01[0][2] B10[6][0]*A01[0][2] B10[7][0]*A01[0][2]) ymm7 = _mm256_fmadd_pd(ymm11, ymm13, ymm7); //ymm7 += (B10[4][0]*A01[0][3] B10[5][0]*A01[0][3] B10[6][0]*A01[0][3] B10[7][0]*A01[0][3]) //broadcast 2nd row of A01 ymm9 = _mm256_broadcast_sd((double const *)(a01 + 1)); //A01[1][1] ymm10 = _mm256_broadcast_sd((double const *)(a01 + 2)); //A01[1][2] ymm11 = _mm256_broadcast_sd((double const *)(a01 + 3)); //A01[1][3] a01 += cs_a; //move to next row of A ymm1 = _mm256_fmadd_pd(ymm9, ymm14, ymm1); //ymm1 += (B10[0][1]*A01[0][1] B10[1][1]*A01[0][1] B10[2][1]*A01[0][1] B10[3][1]*A01[0][1]) ymm2 = _mm256_fmadd_pd(ymm10, ymm14, ymm2); //ymm2 += (B10[0][1]*A01[0][2] B10[1][1]*A01[0][2] B10[2][1]*A01[0][2] B10[3][1]*A01[0][2]) ymm3 = _mm256_fmadd_pd(ymm11, ymm14, ymm3); //ymm3 += (B10[0][1]*A01[0][3] B10[1][1]*A01[0][3] B10[2][1]*A01[0][3] B10[3][1]*A01[0][3]) ymm5 = _mm256_fmadd_pd(ymm9, ymm15, ymm5); //ymm5 += (B10[4][1]*A01[0][1] B10[5][1]*A01[0][1] B10[6][1]*A01[0][1] B10[7][1]*A01[0][1]) ymm6 = _mm256_fmadd_pd(ymm10, ymm15, ymm6); //ymm6 += (B10[4][1]*A01[0][2] B10[5][1]*A01[0][2] B10[6][1]*A01[0][2] B10[7][1]*A01[0][2]) ymm7 = _mm256_fmadd_pd(ymm11, ymm15, ymm7); //ymm7 += (B10[4][1]*A01[0][3] B10[5][1]*A01[0][3] B10[6][1]*A01[0][3] B10[7][1]*A01[0][3]) //broadcast 3rd row of A01 ymm9 = _mm256_broadcast_sd((double const *)(a01 + 1)); //A01[2][1] ymm10 = _mm256_broadcast_sd((double const *)(a01 + 2)); //A01[2][2] ymm11 = _mm256_broadcast_sd((double const *)(a01 + 3)); //A01[2][3] a01 += cs_a; //move to next row of A01 //load next 8x2 block of B10 ymm12 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0])); //(B10[0][2] B10[1][2] B10[2][2] B10[3][2]) ymm13 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + D_NR)); //(B10[4][2] B10[5][2] B10[6][2] B10[7][2]) ymm14 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + cs_b)); //(B10[0][3] B10[1][3] B10[2][3] B10[3][3]) ymm15 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + cs_b + D_NR)); //(B10[4][3] B10[5][3] B10[6][3] B10[7][3]) ymm1 = _mm256_fmadd_pd(ymm9, ymm12, ymm1); //ymm1 += (B10[0][2]*A01[0][1] B10[1][2]*A01[0][1] B10[2][2]*A01[0][1] B10[3][2]*A01[0][1]) ymm2 = _mm256_fmadd_pd(ymm10, ymm12, ymm2); //ymm2 += (B10[0][2]*A01[0][2] B10[1][2]*A01[0][2] B10[2][2]*A01[0][2] B10[3][2]*A01[0][2]) ymm3 = _mm256_fmadd_pd(ymm11, ymm12, ymm3); //ymm3 += (B10[0][2]*A01[0][3] B10[1][2]*A01[0][3] B10[2][2]*A01[0][3] B10[3][2]*A01[0][3]) ymm5 = _mm256_fmadd_pd(ymm9, ymm13, ymm5); //ymm5 += (B10[4][2]*A01[0][1] B10[5][2]*A01[0][1] B10[6][2]*A01[0][1] B10[7][2]*A01[0][1]) ymm6 = _mm256_fmadd_pd(ymm10, ymm13, ymm6); //ymm6 += (B10[4][2]*A01[0][2] B10[5][2]*A01[0][2] B10[6][2]*A01[0][2] B10[7][2]*A01[0][2]) ymm7 = _mm256_fmadd_pd(ymm11, ymm13, ymm7); //ymm7 += (B10[4][2]*A01[0][3] B10[5][2]*A01[0][3] B10[6][2]*A01[0][3] B10[7][2]*A01[0][3]) //broadcast 4th row of A01 ymm9 = _mm256_broadcast_sd((double const *)(a01 + 1)); //A01[3][1] ymm10 = _mm256_broadcast_sd((double const *)(a01 + 2)); //A01[3][2] ymm11 = _mm256_broadcast_sd((double const *)(a01 + 3)); //A01[3][3] a01 += cs_a; //move to next row of A01 ymm1 = _mm256_fmadd_pd(ymm9, ymm14, ymm1); //ymm1 += (B10[0][3]*A01[0][1] B10[1][3]*A01[0][1] B10[2][3]*A01[0][1] B10[3][3]*A01[0][1]) ymm2 = _mm256_fmadd_pd(ymm10, ymm14, ymm2); //ymm2 += (B10[0][3]*A01[0][2] B10[1][3]*A01[0][2] B10[2][3]*A01[0][2] B10[3][3]*A01[0][2]) ymm3 = _mm256_fmadd_pd(ymm11, ymm14, ymm3); //ymm3 += (B10[0][3]*A01[0][3] B10[1][3]*A01[0][3] B10[2][3]*A01[0][3] B10[3][3]*A01[0][3]) ymm5 = _mm256_fmadd_pd(ymm9, ymm15, ymm5); //ymm5 += (B10[4][3]*A01[0][1] B10[5][3]*A01[0][1] B10[6][3]*A01[0][1] B10[7][3]*A01[0][1]) ymm6 = _mm256_fmadd_pd(ymm10, ymm15, ymm6); //ymm6 += (B10[4][3]*A01[0][2] B10[5][3]*A01[0][2] B10[6][3]*A01[0][2] B10[7][3]*A01[0][2]) ymm7 = _mm256_fmadd_pd(ymm11, ymm15, ymm7); //ymm7 += (B10[4][3]*A01[0][3] B10[5][3]*A01[0][3] B10[6][3]*A01[0][3] B10[7][3]*A01[0][3]) b10 += D_NR * cs_b; //pointer math to find next block of B for GEMM a01 = ptr_a01_dup + (D_NR * cs_a); //pointer math to find next block of A for GEMM } ///GEMM code ends/// ymm8 = _mm256_broadcast_sd((double const *)&AlphaVal); ymm9 = _mm256_loadu_pd((double const *)(b11+cs_b)); //B11[0-3][0] ymm13 = _mm256_loadu_pd((double const *)(b11 + cs_b + D_NR)); //B11[4-7][0] ymm10 = _mm256_loadu_pd((double const *)(b11 + cs_b*2)); //B11[0-3][1] ymm14 = _mm256_loadu_pd((double const *)(b11 + cs_b*2 + D_NR)); //B11[4-7][1] ymm11 = _mm256_loadu_pd((double const *)(b11 + cs_b_offset[1])); //B11[0-3][2] ymm15 = _mm256_loadu_pd((double const *)(b11 + cs_b_offset[1] + D_NR)); //B11[4-7][2] ymm9 = _mm256_fmsub_pd(ymm9, ymm8, ymm1); //B11[4-7][0] * alpha-= ymm1 ymm10 = _mm256_fmsub_pd(ymm10, ymm8, ymm2); //B11[0-3][1] * alpha-= ymm2 ymm11 = _mm256_fmsub_pd(ymm11, ymm8, ymm3); //B11[4-7][1] * alpha -= ymm3 ymm13 = _mm256_fmsub_pd(ymm13, ymm8, ymm5); //B11[4-7][2] * alpha -= ymm5 ymm14 = _mm256_fmsub_pd(ymm14, ymm8, ymm6); //B11[0-3][3] * alpha -= ymm6 ymm15 = _mm256_fmsub_pd(ymm15, ymm8, ymm7); //B11[4-7][3] * alpha -= ymm7 ///implement TRSM/// ///read 4x4 block of A11/// a11 += 2 * cs_a; //3rd col ymm4 = _mm256_broadcast_sd((double const *)(a11+1)); //A11[0][1] a11 += cs_a; //4th col ymm5 = _mm256_broadcast_sd((double const *)(a11+1)); //A11[0][1] ymm6 = _mm256_broadcast_sd((double const *)(a11+2)); //A11[0][1] //(Row 3): FMA operations ymm10 = _mm256_fnmadd_pd(ymm11, ymm6, ymm10); ymm9 = _mm256_fnmadd_pd(ymm11, ymm5, ymm9); //(Row 3): FMA operations ymm14 = _mm256_fnmadd_pd(ymm15, ymm6, ymm14); ymm13 = _mm256_fnmadd_pd(ymm15, ymm5, ymm13); //(ROW 2): FMA operations ymm9 = _mm256_fnmadd_pd(ymm10, ymm4, ymm9); ymm13 = _mm256_fnmadd_pd(ymm14, ymm4, ymm13); _mm256_storeu_pd((double *)(b11 + cs_b), ymm9); //store(B11[0-3][1]) _mm256_storeu_pd((double *)(b11 + cs_b + D_NR), ymm13); //store(B11[4-7][1]) _mm256_storeu_pd((double *)(b11 + cs_b_offset[0]), ymm10); //store(B11[0-3][2]) _mm256_storeu_pd((double *)(b11 + cs_b_offset[0] + D_NR), ymm14);//store(B11[4-7][2]) _mm256_storeu_pd((double *)(b11 + cs_b_offset[1]), ymm11); //store(B11[0-3][0]) _mm256_storeu_pd((double *)(b11 + cs_b_offset[1] + D_NR), ymm15); //store(B11[4-7][0]) } else if(2 == n_remainder) { ///GEMM implementation starts/// for(k = 0; k < k_iter; k++) //loop for number of GEMM operations { ptr_a01_dup = a01; //broadcast 1st row of A01 ymm10 = _mm256_broadcast_sd((double const *)(a01 + 2)); //A01[0][2] ymm11 = _mm256_broadcast_sd((double const *)(a01 + 3)); //A01[0][3] a01 += cs_a; //move to next row //load 8x2 block of B10 ymm12 = _mm256_loadu_pd((double const *)b10); //B10[0][0] B10[1][0] B10[2][0] B10[3][0] ymm13 = _mm256_loadu_pd((double const *)(b10 + D_NR)); //B10[4][0] B10[5][0] B10[6][0] B10[7][0] ymm14 = _mm256_loadu_pd((double const *)(b10 + cs_b)); //B10[0][1] B10[1][1] B10[2][1] B10[3][1] ymm15 = _mm256_loadu_pd((double const *)(b10 + cs_b + D_NR)); //B10[4][1] B10[5][1] B10[6][1] B10[7][1] ymm2 = _mm256_fmadd_pd(ymm10, ymm12, ymm2); //ymm2 += (B10[0][0]*A01[0][2] B10[1][0]*A01[0][2] B10[2][0]*A01[0][2] B10[3][0]*A01[0][2]) ymm3 = _mm256_fmadd_pd(ymm11, ymm12, ymm3); //ymm3 += (B10[0][0]*A01[0][3] B10[1][0]*A01[0][3] B10[2][0]*A01[0][3] B10[3][0]*A01[0][3]) ymm6 = _mm256_fmadd_pd(ymm10, ymm13, ymm6); //ymm6 += (B10[4][0]*A01[0][2] B10[5][0]*A01[0][2] B10[6][0]*A01[0][2] B10[7][0]*A01[0][2]) ymm7 = _mm256_fmadd_pd(ymm11, ymm13, ymm7); //ymm7 += (B10[4][0]*A01[0][3] B10[5][0]*A01[0][3] B10[6][0]*A01[0][3] B10[7][0]*A01[0][3]) //broadcast 2nd row of A01 ymm10 = _mm256_broadcast_sd((double const *)(a01 + 2)); //A01[1][2] ymm11 = _mm256_broadcast_sd((double const *)(a01 + 3)); //A01[1][3] a01 += cs_a; //move to next row of A ymm2 = _mm256_fmadd_pd(ymm10, ymm14, ymm2); //ymm2 += (B10[0][1]*A01[0][2] B10[1][1]*A01[0][2] B10[2][1]*A01[0][2] B10[3][1]*A01[0][2]) ymm3 = _mm256_fmadd_pd(ymm11, ymm14, ymm3); //ymm3 += (B10[0][1]*A01[0][3] B10[1][1]*A01[0][3] B10[2][1]*A01[0][3] B10[3][1]*A01[0][3]) ymm6 = _mm256_fmadd_pd(ymm10, ymm15, ymm6); //ymm6 += (B10[4][1]*A01[0][2] B10[5][1]*A01[0][2] B10[6][1]*A01[0][2] B10[7][1]*A01[0][2]) ymm7 = _mm256_fmadd_pd(ymm11, ymm15, ymm7); //ymm7 += (B10[4][1]*A01[0][3] B10[5][1]*A01[0][3] B10[6][1]*A01[0][3] B10[7][1]*A01[0][3]) //broadcast 3rd row of A01 ymm10 = _mm256_broadcast_sd((double const *)(a01 + 2)); //A01[2][2] ymm11 = _mm256_broadcast_sd((double const *)(a01 + 3)); //A01[2][3] a01 += cs_a; //move to next row of A01 //load next 8x2 block of B10 ymm12 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0])); //(B10[0][2] B10[1][2] B10[2][2] B10[3][2]) ymm13 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + D_NR)); //(B10[4][2] B10[5][2] B10[6][2] B10[7][2]) ymm14 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + cs_b)); //(B10[0][3] B10[1][3] B10[2][3] B10[3][3]) ymm15 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + cs_b + D_NR)); //(B10[4][3] B10[5][3] B10[6][3] B10[7][3]) ymm2 = _mm256_fmadd_pd(ymm10, ymm12, ymm2); //ymm2 += (B10[0][2]*A01[0][2] B10[1][2]*A01[0][2] B10[2][2]*A01[0][2] B10[3][2]*A01[0][2]) ymm3 = _mm256_fmadd_pd(ymm11, ymm12, ymm3); //ymm3 += (B10[0][2]*A01[0][3] B10[1][2]*A01[0][3] B10[2][2]*A01[0][3] B10[3][2]*A01[0][3]) ymm6 = _mm256_fmadd_pd(ymm10, ymm13, ymm6); //ymm6 += (B10[4][2]*A01[0][2] B10[5][2]*A01[0][2] B10[6][2]*A01[0][2] B10[7][2]*A01[0][2]) ymm7 = _mm256_fmadd_pd(ymm11, ymm13, ymm7); //ymm7 += (B10[4][2]*A01[0][3] B10[5][2]*A01[0][3] B10[6][2]*A01[0][3] B10[7][2]*A01[0][3]) //broadcast 4th row of A01 ymm10 = _mm256_broadcast_sd((double const *)(a01 + 2)); //A01[3][2] ymm11 = _mm256_broadcast_sd((double const *)(a01 + 3)); //A01[3][3] a01 += cs_a; //move to next row of A01 ymm2 = _mm256_fmadd_pd(ymm10, ymm14, ymm2); //ymm2 += (B10[0][3]*A01[0][2] B10[1][3]*A01[0][2] B10[2][3]*A01[0][2] B10[3][3]*A01[0][2]) ymm3 = _mm256_fmadd_pd(ymm11, ymm14, ymm3); //ymm3 += (B10[0][3]*A01[0][3] B10[1][3]*A01[0][3] B10[2][3]*A01[0][3] B10[3][3]*A01[0][3]) ymm6 = _mm256_fmadd_pd(ymm10, ymm15, ymm6); //ymm6 += (B10[4][3]*A01[0][2] B10[5][3]*A01[0][2] B10[6][3]*A01[0][2] B10[7][3]*A01[0][2]) ymm7 = _mm256_fmadd_pd(ymm11, ymm15, ymm7); //ymm7 += (B10[4][3]*A01[0][3] B10[5][3]*A01[0][3] B10[6][3]*A01[0][3] B10[7][3]*A01[0][3]) b10 += D_NR * cs_b; //pointer math to find next block of B for GEMM a01 = ptr_a01_dup + (D_NR * cs_a); //pointer math to find next block of A for GEMM } ///GEMM code ends/// ymm8 = _mm256_broadcast_sd((double const *)&AlphaVal); ymm10 = _mm256_loadu_pd((double const *)(b11 + cs_b_offset[0])); ymm14 = _mm256_loadu_pd((double const *)(b11 + cs_b_offset[0] + D_NR)); //B11[4-7][0] ymm11 = _mm256_loadu_pd((double const *)(b11 + cs_b_offset[1])); //B11[0-3][1] ymm15 = _mm256_loadu_pd((double const *)(b11 + cs_b_offset[1] + D_NR)); //B11[4-7][1] ymm10 = _mm256_fmsub_pd(ymm10, ymm8, ymm2); //B11[0-3][1] * alpha-= ymm2 ymm11 = _mm256_fmsub_pd(ymm11, ymm8, ymm3); //B11[4-7][1] * alpha -= ymm3 ymm14 = _mm256_fmsub_pd(ymm14, ymm8, ymm6); //B11[0-3][3] * alpha -= ymm6 ymm15 = _mm256_fmsub_pd(ymm15, ymm8, ymm7); //B11[4-7][3] * alpha -= ymm7 ///implement TRSM/// ///read 4x4 block of A11/// a11 += 3 * cs_a; //4th col ymm6 = _mm256_broadcast_sd((double const *)(a11+2)); //A11[0][1] //(Row 3): FMA operations ymm10 = _mm256_fnmadd_pd(ymm11, ymm6, ymm10); //(Row 3): FMA operations ymm14 = _mm256_fnmadd_pd(ymm15, ymm6, ymm14); _mm256_storeu_pd((double *)(b11 + cs_b_offset[0]), ymm10); //store(B11[0-3][1]) _mm256_storeu_pd((double *)(b11 + cs_b_offset[0] + D_NR), ymm14); //store(B11[4-7][1]) _mm256_storeu_pd((double *)(b11 + cs_b_offset[1]), ymm11); //store(B11[0-3][0]) _mm256_storeu_pd((double *)(b11 + cs_b_offset[1] + D_NR), ymm15); //store(B11[4-7][0]) } else if(1 == n_remainder) { ///GEMM implementation starts/// for(k = 0; k < k_iter; k++) //loop for number of GEMM operations { ptr_a01_dup = a01; //broadcast 1st row of A01 ymm11 = _mm256_broadcast_sd((double const *)(a01 + 3)); //A01[0][3] a01 += cs_a; //move to next row //load 8x2 block of B10 ymm12 = _mm256_loadu_pd((double const *)b10); //B10[0][0] B10[1][0] B10[2][0] B10[3][0] ymm13 = _mm256_loadu_pd((double const *)(b10 + D_NR)); //B10[4][0] B10[5][0] B10[6][0] B10[7][0] ymm14 = _mm256_loadu_pd((double const *)(b10 + cs_b)); //B10[0][1] B10[1][1] B10[2][1] B10[3][1] ymm15 = _mm256_loadu_pd((double const *)(b10 + cs_b + D_NR)); //B10[4][1] B10[5][1] B10[6][1] B10[7][1] ymm3 = _mm256_fmadd_pd(ymm11, ymm12, ymm3); //ymm3 += (B10[0][0]*A01[0][3] B10[1][0]*A01[0][3] B10[2][0]*A01[0][3] B10[3][0]*A01[0][3]) ymm7 = _mm256_fmadd_pd(ymm11, ymm13, ymm7); //ymm7 += (B10[4][0]*A01[0][3] B10[5][0]*A01[0][3] B10[6][0]*A01[0][3] B10[7][0]*A01[0][3]) //broadcast 2nd row of A01 ymm11 = _mm256_broadcast_sd((double const *)(a01 + 3)); //A01[1][3] a01 += cs_a; //move to next row of A ymm3 = _mm256_fmadd_pd(ymm11, ymm14, ymm3); //ymm3 += (B10[0][1]*A01[0][3] B10[1][1]*A01[0][3] B10[2][1]*A01[0][3] B10[3][1]*A01[0][3]) ymm7 = _mm256_fmadd_pd(ymm11, ymm15, ymm7); //ymm7 += (B10[4][1]*A01[0][3] B10[5][1]*A01[0][3] B10[6][1]*A01[0][3] B10[7][1]*A01[0][3]) //broadcast 3rd row of A01 ymm11 = _mm256_broadcast_sd((double const *)(a01 + 3)); //A01[2][3] a01 += cs_a; //move to next row of A01 //load next 8x2 block of B10 ymm12 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0])); //(B10[0][2] B10[1][2] B10[2][2] B10[3][2]) ymm13 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + D_NR)); //(B10[4][2] B10[5][2] B10[6][2] B10[7][2]) ymm14 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + cs_b)); //(B10[0][3] B10[1][3] B10[2][3] B10[3][3]) ymm15 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0] + cs_b + D_NR)); //(B10[4][3] B10[5][3] B10[6][3] B10[7][3]) ymm3 = _mm256_fmadd_pd(ymm11, ymm12, ymm3); //ymm3 += (B10[0][2]*A01[0][3] B10[1][2]*A01[0][3] B10[2][2]*A01[0][3] B10[3][2]*A01[0][3]) ymm7 = _mm256_fmadd_pd(ymm11, ymm13, ymm7); //ymm7 += (B10[4][2]*A01[0][3] B10[5][2]*A01[0][3] B10[6][2]*A01[0][3] B10[7][2]*A01[0][3]) //broadcast 4th row of A01 ymm11 = _mm256_broadcast_sd((double const *)(a01 + 3)); //A01[3][3] a01 += cs_a; //move to next row of A01 ymm3 = _mm256_fmadd_pd(ymm11, ymm14, ymm3); //ymm3 += (B10[0][3]*A01[0][3] B10[1][3]*A01[0][3] B10[2][3]*A01[0][3] B10[3][3]*A01[0][3]) ymm7 = _mm256_fmadd_pd(ymm11, ymm15, ymm7); //ymm7 += (B10[4][3]*A01[0][3] B10[5][3]*A01[0][3] B10[6][3]*A01[0][3] B10[7][3]*A01[0][3]) b10 += D_NR * cs_b; //pointer math to find next block of B for GEMM a01 = ptr_a01_dup + (D_NR * cs_a); //pointer math to find next block of A for GEMM } ///GEMM code ends/// ymm8 = _mm256_broadcast_sd((double const *)&AlphaVal); ymm11 = _mm256_loadu_pd((double const *)(b11+cs_b_offset[1])); //B11[0-3][0] ymm15 = _mm256_loadu_pd((double const *)(b11 + cs_b_offset[1] +D_NR)); //B11[4-7][0] ymm11 = _mm256_fmsub_pd(ymm11, ymm8, ymm3); //B11[4-7][1] * alpha -= ymm3 ymm15 = _mm256_fmsub_pd(ymm15, ymm8, ymm7); //B11[4-7][3] * alpha -= ymm7 _mm256_storeu_pd((double *)(b11+ cs_b_offset[1]), ymm11); //store(B11[0-3][0]) _mm256_storeu_pd((double *)(b11 + cs_b_offset[1] + D_NR), ymm15); //store(B11[4-7][0]) } } } if(i<0) i += D_NR; if((m & 4)) ///implementation for remainder rows(when m_remainder is greater than 4) { for(j = (n-D_NR); (j+1) > 0; j -=D_NR) //loop along n direction { a01 = L + (j+D_NR)*cs_a + (j); //pointer to block of A to be used for GEMM a11 = L + j*cs_a + j; //pointer to block of A to be used for TRSM b10 = B + i + (j+D_NR)*cs_b; //pointer to block of B to be used for GEMM b11 = B + i + j*cs_b; //pointer to block of B to be used for TRSM k_iter = (n-j-D_NR) / D_NR; //number of times GEMM operations to be performed(in blocks of 4x4) ///GEMM for previous blocks /// ///load 4x4 block of b11 ymm0 = _mm256_loadu_pd((double const *)b11); //B11[0][0] B11[1][0] B11[2][0] B11[3][0] ymm1 = _mm256_loadu_pd((double const *)(b11 + cs_b)); //B11[0][1] B11[1][1] B11[2][1] B11[3][1] ymm2 = _mm256_loadu_pd((double const *)(b11 + cs_b_offset[0])); //B11[0][2] B11[1][2] B11[2][2] B11[3][2] ymm3 = _mm256_loadu_pd((double const *)(b11 + cs_b_offset[1])); //B11[0][3] B11[1][3] B11[2][3] B11[3][3] ymm4 = _mm256_setzero_pd(); ymm5 = _mm256_setzero_pd(); ymm6 = _mm256_setzero_pd(); ymm7 = _mm256_setzero_pd(); ///GEMM implementation starts/// for(k = 0; k < k_iter; k++) //loop for number of GEMM operations { ptr_a01_dup = a01; //load 4x4 bblock of b10 ymm8 = _mm256_loadu_pd((double const *)b10); //B10[0][0] B10[1][0] B10[2][0] B10[3][0] ymm9 = _mm256_loadu_pd((double const *)(b10 + cs_b)); //B10[0][1] B10[1][1] B10[2][1] B10[3][1] ymm10 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0])); //B10[0][2] B10[1][2] B10[2][2] B10[3][2] ymm11 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[1])); //B10[0][3] B10[1][3] B10[2][3] B10[3][3] //broadcast 1st row of A01 ymm12 = _mm256_broadcast_sd((double const *)(a01 + 0)); //A01[0][0] ymm13 = _mm256_broadcast_sd((double const *)(a01 + 1)); //A01[0][1] ymm14 = _mm256_broadcast_sd((double const *)(a01 + 2)); //A01[0][2] ymm15 = _mm256_broadcast_sd((double const *)(a01 + 3)); //A01[0][3] a01 += cs_a; //move to next row of A ymm4 = _mm256_fmadd_pd(ymm12, ymm8, ymm4); //ymm4 += (B10[0][0]*A01[0][0] B10[1][0]*A01[0][0] B10[2][0]*A01[0][0] B10[3][0]*A01[0][0]) ymm5 = _mm256_fmadd_pd(ymm13, ymm8, ymm5); //ymm5 += (B10[0][0]*A01[0][1] B10[1][0]*A01[0][1] B10[2][0]*A01[0][1] B10[3][0]*A01[0][1]) ymm6 = _mm256_fmadd_pd(ymm14, ymm8, ymm6); //ymm6 += (B10[0][0]*A01[0][2] B10[1][0]*A01[0][2] B10[2][0]*A01[0][2] B10[3][0]*A01[0][2]) ymm7 = _mm256_fmadd_pd(ymm15, ymm8, ymm7); //ymm7 += (B10[0][0]*A01[0][3] B10[1][0]*A01[0][3] B10[2][0]*A01[0][3] B10[3][0]*A01[0][3]) //broadcast 2nd row of A01 ymm12 = _mm256_broadcast_sd((double const *)(a01 + 0)); //A01[1][0] ymm13 = _mm256_broadcast_sd((double const *)(a01 + 1)); //A01[1][1] ymm14 = _mm256_broadcast_sd((double const *)(a01 + 2)); //A01[1][2] ymm15 = _mm256_broadcast_sd((double const *)(a01 + 3)); //A01[1][3] a01 += cs_a; //move to next row of A ymm4 = _mm256_fmadd_pd(ymm12, ymm9, ymm4); //ymm4 += (B10[0][1]*A01[1][0] B10[1][1]*A01[1][0] B10[2][1]*A01[1][0] B10[3][1]*A01[1][0]) ymm5 = _mm256_fmadd_pd(ymm13, ymm9, ymm5); //ymm5 += (B10[0][1]*A01[1][1] B10[1][1]*A01[1][1] B10[2][1]*A01[1][1] B10[3][1]*A01[1][1]) ymm6 = _mm256_fmadd_pd(ymm14, ymm9, ymm6); //ymm6 += (B10[0][1]*A01[1][2] B10[1][1]*A01[1][2] B10[2][1]*A01[1][2] B10[3][1]*A01[1][2]) ymm7 = _mm256_fmadd_pd(ymm15, ymm9, ymm7); //ymm7 += (B10[0][1]*A01[1][3] B10[1][1]*A01[1][3] B10[2][1]*A01[1][3] B10[3][1]*A01[1][3]) //braodcast 3rd row of A01 ymm12 = _mm256_broadcast_sd((double const *)(a01 + 0)); //A01[2][0] ymm13 = _mm256_broadcast_sd((double const *)(a01 + 1)); //A01[2][1] ymm14 = _mm256_broadcast_sd((double const *)(a01 + 2)); //A01[2][2] ymm15 = _mm256_broadcast_sd((double const *)(a01 + 3)); //A01[2][3] a01 += cs_a; //move to next row of A ymm4 = _mm256_fmadd_pd(ymm12, ymm10, ymm4); //ymm4 += (B10[0][2]*A01[2][0] B10[1][2]*A01[2][0] B10[2][2]*A01[2][0] B10[3][2]*A01[2][0]) ymm5 = _mm256_fmadd_pd(ymm13, ymm10, ymm5); //ymm5 += (B10[0][2]*A01[2][1] B10[1][2]*A01[2][1] B10[2][2]*A01[2][1] B10[3][2]*A01[2][1]) ymm6 = _mm256_fmadd_pd(ymm14, ymm10, ymm6); //ymm6 += (B10[0][2]*A01[2][2] B10[1][2]*A01[2][2] B10[2][2]*A01[2][2] B10[3][2]*A01[2][2]) ymm7 = _mm256_fmadd_pd(ymm15, ymm10, ymm7); //ymm7 += (B10[0][2]*A01[2][3] B10[1][2]*A01[2][3] B10[2][2]*A01[2][3] B10[3][2]*A01[2][3]) //broadcast 4th row of A01 ymm12 = _mm256_broadcast_sd((double const *)(a01 + 0)); //A01[3][0] ymm13 = _mm256_broadcast_sd((double const *)(a01 + 1)); //A01[3][1] ymm14 = _mm256_broadcast_sd((double const *)(a01 + 2)); //A01[3][2] ymm15 = _mm256_broadcast_sd((double const *)(a01 + 3)); //A01[3][3] a01 += cs_a; //move to next row of A ymm4 = _mm256_fmadd_pd(ymm12, ymm11, ymm4); //ymm4 += (B10[0][3]*A01[3][0] B10[1][3]*A01[3][0] B10[2][3]*A01[3][0] B10[3][3]*A01[3][0]) ymm5 = _mm256_fmadd_pd(ymm13, ymm11, ymm5); //ymm5 += (B10[0][3]*A01[3][1] B10[1][3]*A01[3][1] B10[2][3]*A01[3][1] B10[3][3]*A01[3][1]) ymm6 = _mm256_fmadd_pd(ymm14, ymm11, ymm6); //ymm6 += (B10[0][3]*A01[3][2] B10[1][3]*A01[3][2] B10[2][3]*A01[3][2] B10[3][3]*A01[3][2]) ymm7 = _mm256_fmadd_pd(ymm15, ymm11, ymm7); //ymm7 += (B10[0][3]*A01[3][3] B10[1][3]*A01[3][3] B10[2][3]*A01[3][3] B10[3][3]*A01[3][3]) b10 += D_NR * cs_b; //pointer math to find next block of B for GEMM a01 = ptr_a01_dup + D_NR*cs_a; //pointer math to find next block of A for GEMM } ///GEMM code end/// ymm15 = _mm256_broadcast_sd((double const *)&AlphaVal); //register to store alpha ymm0 = _mm256_fmsub_pd(ymm0, ymm15, ymm4); //B11[x][0] -=ymm4 ymm1 = _mm256_fmsub_pd(ymm1, ymm15, ymm5); //B11[x][1] -= ymm5 ymm2 = _mm256_fmsub_pd(ymm2, ymm15, ymm6); //B11[x][2] -= ymm6 ymm3 = _mm256_fmsub_pd(ymm3, ymm15, ymm7); //B11[x][3] -= ymm7 ///implement TRSM/// ///read 4x4 block of A11/// a11 += cs_a; //2nd col ymm5 = _mm256_broadcast_sd((double const *)(a11+0)); //A11[0][1] a11 += cs_a; //3rd col ymm6 = _mm256_broadcast_sd((double const *)(a11+0)); //A11[0][1] ymm9 = _mm256_broadcast_sd((double const *)(a11+1)); //A11[0][1] a11 += cs_a; //4th col ymm7 = _mm256_broadcast_sd((double const *)(a11+0)); //A11[0][1] ymm10 = _mm256_broadcast_sd((double const *)(a11+1)); //A11[0][1] ymm12 = _mm256_broadcast_sd((double const *)(a11+2)); //A11[0][1] //(Row 3): FMA operations ymm2 = _mm256_fnmadd_pd(ymm3, ymm12, ymm2); ymm1 = _mm256_fnmadd_pd(ymm3, ymm10, ymm1); ymm0 = _mm256_fnmadd_pd(ymm3, ymm7, ymm0); //(ROW 2): FMA operations ymm1 = _mm256_fnmadd_pd(ymm2, ymm9, ymm1); ymm0 = _mm256_fnmadd_pd(ymm2, ymm6, ymm0); //(Row 1):FMA operations ymm0 = _mm256_fnmadd_pd(ymm1, ymm5, ymm0); _mm256_storeu_pd((double *)b11, ymm0); //store(B11[x][0]) _mm256_storeu_pd((double *)(b11 + cs_b), ymm1); //store(B11[x][1]) _mm256_storeu_pd((double *)(b11 + cs_b_offset[0]), ymm2); //(store(B11[x][2])) _mm256_storeu_pd((double *)(b11 + cs_b_offset[1]), ymm3); //store(B11[x][3]) } if(n_remainder) //implementation for remainder columns(when n is not a multiple of D_NR) { a01 = L + (j+D_NR)*cs_a + (j); //pointer to block of A to be used for GEMM a11 = L + j*cs_a + j; //pointer to block of A to be used for TRSM b10 = B + i + (j+D_NR)*cs_b; //pointer to block of B to be used for GEMM b11 = B + i + j*cs_b; //pointer to block of B to be used for TRSM k_iter = (n-j-D_NR) / D_NR; //number of times GEMM operations to be performed(in blocks of 4x4) ///GEMM for previous blocks /// ymm4 = _mm256_setzero_pd(); ymm5 = _mm256_setzero_pd(); ymm6 = _mm256_setzero_pd(); ymm7 = _mm256_setzero_pd(); ///load 4x4 block of b11 if(3 == n_remainder) { ymm1 = _mm256_loadu_pd((double const *)b11+ cs_b); //B11[0][0] B11[1][0] B11[2][0] B11[3][0] ymm2 = _mm256_loadu_pd((double const *)(b11 + cs_b * 2)); //B11[0][1] B11[1][1] B11[2][1] B11[3][1] ymm3 = _mm256_loadu_pd((double const *)(b11 + cs_b * 3)); //B11[0][2] B11[1][2] B11[2][2] B11[3][2] ///GEMM implementation starts/// for(k = 0; k < k_iter; k++) //loop for number of GEMM operations { ptr_a01_dup = a01; //load 4x4 bblock of b10 ymm8 = _mm256_loadu_pd((double const *)b10); //B10[0][0] B10[1][0] B10[2][0] B10[3][0] ymm9 = _mm256_loadu_pd((double const *)(b10 + cs_b)); //B10[0][1] B10[1][1] B10[2][1] B10[3][1] ymm10 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0])); //B10[0][2] B10[1][2] B10[2][2] B10[3][2] ymm11 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[1])); //B10[0][3] B10[1][3] B10[2][3] B10[3][3] //broadcast 1st row of A01 ymm13 = _mm256_broadcast_sd((double const *)(a01 + 1)); //A01[0][1] ymm14 = _mm256_broadcast_sd((double const *)(a01 + 2)); //A01[0][2] ymm15 = _mm256_broadcast_sd((double const *)(a01 + 3)); //A01[0][3] a01 += cs_a; //move to next row of A ymm5 = _mm256_fmadd_pd(ymm13, ymm8, ymm5); //ymm5 += (B10[0][0]*A01[0][1] B10[1][0]*A01[0][1] B10[2][0]*A01[0][1] B10[3][0]*A01[0][1]) ymm6 = _mm256_fmadd_pd(ymm14, ymm8, ymm6); //ymm6 += (B10[0][0]*A01[0][2] B10[1][0]*A01[0][2] B10[2][0]*A01[0][2] B10[3][0]*A01[0][2]) ymm7 = _mm256_fmadd_pd(ymm15, ymm8, ymm7); //ymm7 += (B10[0][0]*A01[0][3] B10[1][0]*A01[0][3] B10[2][0]*A01[0][3] B10[3][0]*A01[0][3]) //broadcast 2nd row of A01 ymm13 = _mm256_broadcast_sd((double const *)(a01 + 1)); //A01[1][1] ymm14 = _mm256_broadcast_sd((double const *)(a01 + 2)); //A01[1][2] ymm15 = _mm256_broadcast_sd((double const *)(a01 + 3)); //A01[1][3] a01 += cs_a; //move to next row of A ymm5 = _mm256_fmadd_pd(ymm13, ymm9, ymm5); //ymm5 += (B10[0][1]*A01[1][1] B10[1][1]*A01[1][1] B10[2][1]*A01[1][1] B10[3][1]*A01[1][1]) ymm6 = _mm256_fmadd_pd(ymm14, ymm9, ymm6); //ymm6 += (B10[0][1]*A01[1][2] B10[1][1]*A01[1][2] B10[2][1]*A01[1][2] B10[3][1]*A01[1][2]) ymm7 = _mm256_fmadd_pd(ymm15, ymm9, ymm7); //ymm7 += (B10[0][1]*A01[1][3] B10[1][1]*A01[1][3] B10[2][1]*A01[1][3] B10[3][1]*A01[1][3]) //braodcast 3rd row of A01 ymm13 = _mm256_broadcast_sd((double const *)(a01 + 1)); //A01[2][1] ymm14 = _mm256_broadcast_sd((double const *)(a01 + 2)); //A01[2][2] ymm15 = _mm256_broadcast_sd((double const *)(a01 + 3)); //A01[2][3] a01 += cs_a; //move to next row of A ymm5 = _mm256_fmadd_pd(ymm13, ymm10, ymm5); //ymm5 += (B10[0][2]*A01[2][1] B10[1][2]*A01[2][1] B10[2][2]*A01[2][1] B10[3][2]*A01[2][1]) ymm6 = _mm256_fmadd_pd(ymm14, ymm10, ymm6); //ymm6 += (B10[0][2]*A01[2][2] B10[1][2]*A01[2][2] B10[2][2]*A01[2][2] B10[3][2]*A01[2][2]) ymm7 = _mm256_fmadd_pd(ymm15, ymm10, ymm7); //ymm7 += (B10[0][2]*A01[2][3] B10[1][2]*A01[2][3] B10[2][2]*A01[2][3] B10[3][2]*A01[2][3]) //broadcast 4th row of A01 ymm13 = _mm256_broadcast_sd((double const *)(a01 + 1)); //A01[3][1] ymm14 = _mm256_broadcast_sd((double const *)(a01 + 2)); //A01[3][2] ymm15 = _mm256_broadcast_sd((double const *)(a01 + 3)); //A01[3][3] a01 += cs_a; //move to next row of A ymm5 = _mm256_fmadd_pd(ymm13, ymm11, ymm5); //ymm5 += (B10[0][3]*A01[3][1] B10[1][3]*A01[3][1] B10[2][3]*A01[3][1] B10[3][3]*A01[3][1]) ymm6 = _mm256_fmadd_pd(ymm14, ymm11, ymm6); //ymm6 += (B10[0][3]*A01[3][2] B10[1][3]*A01[3][2] B10[2][3]*A01[3][2] B10[3][3]*A01[3][2]) ymm7 = _mm256_fmadd_pd(ymm15, ymm11, ymm7); //ymm7 += (B10[0][3]*A01[3][3] B10[1][3]*A01[3][3] B10[2][3]*A01[3][3] B10[3][3]*A01[3][3]) b10 += D_NR * cs_b; //pointer math to find next block of B for GEMM a01 = ptr_a01_dup + (D_NR * cs_a); //pointer math to find next block of A for GEMM } ///GEMM code end/// ymm15 = _mm256_broadcast_sd((double const *)&AlphaVal); //register to store alpha ymm1 = _mm256_fmsub_pd(ymm1, ymm15, ymm5); //B11[x][1] -= ymm5 ymm2 = _mm256_fmsub_pd(ymm2, ymm15, ymm6); //B11[x][2] -= ymm6 ymm3 = _mm256_fmsub_pd(ymm3, ymm15, ymm7); //B11[x][3] -= ymm7 ///implement TRSM/// ///read 4x4 block of A11/// a11 += 2 * cs_a; //3rd col ymm9 = _mm256_broadcast_sd((double const *)(a11+1)); //A11[0][1] a11 += cs_a; //4th col ymm10 = _mm256_broadcast_sd((double const *)(a11+1)); //A11[0][1] ymm12 = _mm256_broadcast_sd((double const *)(a11+2)); //A11[0][1] //(Row 3): FMA operations ymm2 = _mm256_fnmadd_pd(ymm3, ymm12, ymm2); ymm1 = _mm256_fnmadd_pd(ymm3, ymm10, ymm1); //(ROW 2): FMA operations ymm1 = _mm256_fnmadd_pd(ymm2, ymm9, ymm1); _mm256_storeu_pd((double *)(b11 + cs_b), ymm1); //store(B11[x][1]) _mm256_storeu_pd((double *)(b11 + cs_b_offset[0]), ymm2); //(store(B11[x][2])) _mm256_storeu_pd((double *)(b11 + cs_b*3), ymm3); //store(B11[x][0]) } else if(2 == n_remainder) { ymm2 = _mm256_loadu_pd((double const *)(b11 + cs_b * 2)); //B11[0][0] B11[1][0] B11[2][0] B11[3][0] ymm3 = _mm256_loadu_pd((double const *)(b11 + cs_b * 3)); //B11[0][1] B11[1][1] B11[2][1] B11[3][1] ///GEMM implementation starts/// for(k = 0; k < k_iter; k++) //loop for number of GEMM operations { ptr_a01_dup = a01; //load 4x4 bblock of b10 ymm8 = _mm256_loadu_pd((double const *)b10); //B10[0][0] B10[1][0] B10[2][0] B10[3][0] ymm9 = _mm256_loadu_pd((double const *)(b10 + cs_b)); //B10[0][1] B10[1][1] B10[2][1] B10[3][1] ymm10 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0])); //B10[0][2] B10[1][2] B10[2][2] B10[3][2] ymm11 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[1])); //B10[0][3] B10[1][3] B10[2][3] B10[3][3] //broadcast 1st row of A01 ymm14 = _mm256_broadcast_sd((double const *)(a01 + 2)); //A01[0][2] ymm15 = _mm256_broadcast_sd((double const *)(a01 + 3)); //A01[0][3] a01 += cs_a; //move to next row of A ymm6 = _mm256_fmadd_pd(ymm14, ymm8, ymm6); //ymm6 += (B10[0][0]*A01[0][2] B10[1][0]*A01[0][2] B10[2][0]*A01[0][2] B10[3][0]*A01[0][2]) ymm7 = _mm256_fmadd_pd(ymm15, ymm8, ymm7); //ymm7 += (B10[0][0]*A01[0][3] B10[1][0]*A01[0][3] B10[2][0]*A01[0][3] B10[3][0]*A01[0][3]) //broadcast 2nd row of A01 ymm14 = _mm256_broadcast_sd((double const *)(a01 + 2)); //A01[1][2] ymm15 = _mm256_broadcast_sd((double const *)(a01 + 3)); //A01[1][3] a01 += cs_a; //move to next row of A ymm6 = _mm256_fmadd_pd(ymm14, ymm9, ymm6); //ymm6 += (B10[0][1]*A01[1][2] B10[1][1]*A01[1][2] B10[2][1]*A01[1][2] B10[3][1]*A01[1][2]) ymm7 = _mm256_fmadd_pd(ymm15, ymm9, ymm7); //ymm7 += (B10[0][1]*A01[1][3] B10[1][1]*A01[1][3] B10[2][1]*A01[1][3] B10[3][1]*A01[1][3]) //braodcast 3rd row of A01 ymm14 = _mm256_broadcast_sd((double const *)(a01 + 2)); //A01[2][2] ymm15 = _mm256_broadcast_sd((double const *)(a01 + 3)); //A01[2][3] a01 += cs_a; //move to next row of A ymm6 = _mm256_fmadd_pd(ymm14, ymm10, ymm6); //ymm6 += (B10[0][2]*A01[2][2] B10[1][2]*A01[2][2] B10[2][2]*A01[2][2] B10[3][2]*A01[2][2]) ymm7 = _mm256_fmadd_pd(ymm15, ymm10, ymm7); //ymm7 += (B10[0][2]*A01[2][3] B10[1][2]*A01[2][3] B10[2][2]*A01[2][3] B10[3][2]*A01[2][3]) //broadcast 4th row of A01 ymm14 = _mm256_broadcast_sd((double const *)(a01 + 2)); //A01[3][2] ymm15 = _mm256_broadcast_sd((double const *)(a01 + 3)); //A01[3][3] a01 += cs_a; //move to next row of A ymm6 = _mm256_fmadd_pd(ymm14, ymm11, ymm6); //ymm6 += (B10[0][3]*A01[3][2] B10[1][3]*A01[3][2] B10[2][3]*A01[3][2] B10[3][3]*A01[3][2]) ymm7 = _mm256_fmadd_pd(ymm15, ymm11, ymm7); //ymm7 += (B10[0][3]*A01[3][3] B10[1][3]*A01[3][3] B10[2][3]*A01[3][3] B10[3][3]*A01[3][3]) b10 += D_NR * cs_b; //pointer math to find next block of B for GEMM a01 = ptr_a01_dup + (D_NR * cs_a); //pointer math to find next block of A for GEMM } ///GEMM code end/// ymm15 = _mm256_broadcast_sd((double const *)&AlphaVal); //register to store alpha ymm2 = _mm256_fmsub_pd(ymm2, ymm15, ymm6); //B11[x][2] -= ymm6 ymm3 = _mm256_fmsub_pd(ymm3, ymm15, ymm7); //B11[x][3] -= ymm7 ///implement TRSM/// ///read 4x4 block of A11/// a11 += 3 * cs_a; //4th col ymm12 = _mm256_broadcast_sd((double const *)(a11+2)); //A11[0][1] //(Row 3): FMA operations ymm2 = _mm256_fnmadd_pd(ymm3, ymm12, ymm2); _mm256_storeu_pd((double *)(b11+ cs_b * 2), ymm2); //store(B11[x][0]) _mm256_storeu_pd((double *)(b11 + cs_b * 3), ymm3); //store(B11[x][1]) } else if(1 == n_remainder) { ymm3 = _mm256_loadu_pd((double const *)(b11 + cs_b * 3)); //B11[0][0] B11[1][0] B11[2][0] B11[3][0] ///GEMM implementation starts/// for(k = 0; k < k_iter; k++) //loop for number of GEMM operations { ptr_a01_dup = a01; //load 4x4 bblock of b10 ymm8 = _mm256_loadu_pd((double const *)b10); //B10[0][0] B10[1][0] B10[2][0] B10[3][0] ymm9 = _mm256_loadu_pd((double const *)(b10 + cs_b)); //B10[0][1] B10[1][1] B10[2][1] B10[3][1] ymm10 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[0])); //B10[0][2] B10[1][2] B10[2][2] B10[3][2] ymm11 = _mm256_loadu_pd((double const *)(b10 + cs_b_offset[1])); //B10[0][3] B10[1][3] B10[2][3] B10[3][3] //broadcast 1st row of A01 ymm15 = _mm256_broadcast_sd((double const *)(a01 + 3)); //A01[0][3] a01 += cs_a; //move to next row of A ymm7 = _mm256_fmadd_pd(ymm15, ymm8, ymm7); //ymm7 += (B10[0][0]*A01[0][3] B10[1][0]*A01[0][3] B10[2][0]*A01[0][3] B10[3][0]*A01[0][3]) //broadcast 2nd row of A01 ymm15 = _mm256_broadcast_sd((double const *)(a01 + 3)); //A01[1][3] a01 += cs_a; //move to next row of A ymm7 = _mm256_fmadd_pd(ymm15, ymm9, ymm7); //ymm7 += (B10[0][1]*A01[1][3] B10[1][1]*A01[1][3] B10[2][1]*A01[1][3] B10[3][1]*A01[1][3]) //braodcast 3rd row of A01 ymm15 = _mm256_broadcast_sd((double const *)(a01 + 3)); //A01[2][3] a01 += cs_a; //move to next row of A ymm7 = _mm256_fmadd_pd(ymm15, ymm10, ymm7); //ymm7 += (B10[0][2]*A01[2][3] B10[1][2]*A01[2][3] B10[2][2]*A01[2][3] B10[3][2]*A01[2][3]) //broadcast 4th row of A01 ymm15 = _mm256_broadcast_sd((double const *)(a01 + 3)); //A01[3][3] a01 += cs_a; //move to next row of A ymm7 = _mm256_fmadd_pd(ymm15, ymm11, ymm7); //ymm7 += (B10[0][3]*A01[3][3] B10[1][3]*A01[3][3] B10[2][3]*A01[3][3] B10[3][3]*A01[3][3]) b10 += D_NR * cs_b; //pointer math to find next block of B for GEMM a01 = ptr_a01_dup + (D_NR * cs_a); //pointer math to find next block of A for GEMM } ///GEMM code end/// ymm15 = _mm256_broadcast_sd((double const *)&AlphaVal); //register to store alpha ymm3 = _mm256_fmsub_pd(ymm3, ymm15, ymm7); //B11[x][3] -= ymm7 _mm256_storeu_pd((double *)(b11 + cs_b * 3), ymm3); //store(B11[x][0]) } } m_remainder -= 4; i -= 4; } if(m_remainder) ///implementation for remainder rows { dtrsm_small_XAutB_unitDiag(L, B, AlphaVal, m_remainder, n, cs_a, cs_b); } return BLIS_SUCCESS; } /* * AX = Alpha*B, Single precision, A: lower triangular * This kernel implementation supports matrices A and B such that m is equal to BLI_AlXB_M_SP and n is mutiple of 8 */ static err_t bli_strsm_small_AlXB ( side_t side, obj_t* AlphaObj, obj_t* a, obj_t* b, cntx_t* cntx, cntl_t* cntl ) { obj_t alpha, beta; // gemm parameters obj_t Ga, Gb, Gc; // for GEMM int m = bli_obj_length(b); // number of rows of matrix B int n = bli_obj_width(b); // number of columns of matrix B int lda = bli_obj_col_stride(a); // column stride of A int ldb = bli_obj_col_stride(b); // column stride of B int rsa = bli_obj_row_stride(a); // row stride of A int rsb = bli_obj_row_stride(b); // row stride of B int i = 0; int j; int blk_size = 8; int isUnitDiag = bli_obj_has_unit_diag(a); float alphaVal; float* restrict L = a->buffer; float* restrict B = b->buffer; if (m != BLI_AlXB_M_SP || (n&7) != 0) { return BLIS_NOT_YET_IMPLEMENTED; } if ( (m*(m + n)) > BLIS_SMALL_MATRIX_THRES_TRSM ) { return BLIS_NOT_YET_IMPLEMENTED; } alphaVal = *((float *)bli_obj_buffer_for_const(BLIS_FLOAT, AlphaObj)); /* Small _GEMM preparation code */ bli_obj_create( BLIS_FLOAT, 1, 1, 0, 0, &alpha ); bli_obj_create( BLIS_FLOAT, 1, 1, 0, 0, &beta ); /* B = B - A*B */ bli_setsc( -(1.0), 0.0, &alpha ); bli_setsc( (1.0), 0.0, &beta ); bli_obj_create_with_attached_buffer( BLIS_FLOAT, blk_size, blk_size, a->buffer, rsa, lda, &Ga); bli_obj_create_with_attached_buffer( BLIS_FLOAT, blk_size, n, b->buffer, rsb, ldb, &Gb); bli_obj_create_with_attached_buffer( BLIS_FLOAT, blk_size, n, b->buffer, rsb, ldb, &Gc); bli_obj_set_conjtrans( BLIS_NO_TRANSPOSE, &Ga ); bli_obj_set_conjtrans( BLIS_NO_TRANSPOSE, &Gb ); bli_obj_set_conjtrans( BLIS_NO_TRANSPOSE, &Gc ); //first block of trsm Gb.buffer = (void*)(B + i); //trsm of first 8xn block if (alphaVal != 1) { if (isUnitDiag == 0) { blis_strsm_microkernel_alpha((L + i * lda + i), (B + i), m, n, rsa, rsb, lda, ldb, alphaVal); fp_blis_strsm_microkernel = blis_strsm_microkernel; } else { blis_strsm_microkernel_alpha_unitDiag((L + i * lda + i), (B + i), m, n, rsa, rsb, lda, ldb, alphaVal); fp_blis_strsm_microkernel = blis_strsm_microkernel_unitDiag; } bli_setsc( alphaVal, 0.0, &beta ); } else { if (isUnitDiag == 0) { blis_strsm_microkernel((L + i * lda + i), (B + i), m, n, rsa, rsb, lda, ldb); fp_blis_strsm_microkernel = blis_strsm_microkernel; } else { blis_strsm_microkernel_unitDiag((L + i * lda + i), (B + i), m, n, rsa, rsb, lda, ldb); fp_blis_strsm_microkernel = blis_strsm_microkernel_unitDiag; } } //gemm update for (j = i + blk_size; j < m; j += blk_size) // for rows upto multiple of BLOCK_HEIGHT { Ga.buffer = (void*)(L + j + i*lda); Gc.buffer = (void*)(B + j); bli_gemm_small(&alpha, &Ga, &Gb, &beta, &Gc, cntx, cntl ); // Gc = beta*Gc + alpha*Ga *Gb } //trsm of remaining blocks for (i = blk_size; i < m; i += blk_size) { Gb.buffer = (void*)(B + i); fp_blis_strsm_microkernel((L + i * lda + i), (B + i), m, n, rsa, rsb, lda, ldb); for (j = i + blk_size; j < m; j += blk_size) // for rows upto multiple of BLOCK_HEIGHT { Ga.buffer = (void*)(L + j + i*lda); Gc.buffer = (void*)(B + j); bli_gemm_small(&alpha, &Ga, &Gb, &beta, &Gc, cntx, cntl ); // Gc = beta*Gc + alpha*Ga *Gb } } // End of for loop - i return BLIS_SUCCESS; } /* * XA' = Alpha*B, Single precision, A: lower triangular * This kernel implementation supports matrices A and B such that * m and n are multiples of 8 and n is less than or equal to BLI_XAltB_N_SP */ static err_t bli_strsm_small_XAltB( side_t side, obj_t* AlphaObj, obj_t* a, obj_t* b, cntx_t* cntx, cntl_t* cntl ) { int m = bli_obj_length(a); // number of rows of matrix B int n = bli_obj_length(b); // number of columns of matrix B int lda = bli_obj_col_stride(a); // column stride of A int ldb = bli_obj_col_stride(b); // column stride of B int rsa = bli_obj_row_stride(a); // row stride of A int rsb = bli_obj_row_stride(b); // row stride of B int i = 0; int isUnitDiag = bli_obj_has_unit_diag(a); float alphaVal; float *L = a->buffer; float *B = b->buffer; if ((m&7) != 0 || (n&7) != 0) { return BLIS_NOT_YET_IMPLEMENTED; } if ( n > BLI_XAltB_N_SP || (m*(m + n)) > BLIS_SMALL_MATRIX_THRES_TRSM ) { return BLIS_NOT_YET_IMPLEMENTED; } alphaVal = *((float *)bli_obj_buffer_for_const(BLIS_FLOAT, AlphaObj)); if (alphaVal != 1) { if (isUnitDiag == 0) { trsm_XAtB_block_allSmallSizedMatrices_alpha((L + i * lda + i), (B + i), m, n, rsa, rsb, lda, ldb, alphaVal); } else { trsm_XAtB_block_allSmallSizedMatrices_alpha_unitDiag((L + i * lda + i), (B + i), m, n, rsa, rsb, lda, ldb, alphaVal); } } else { if (isUnitDiag == 0) { trsm_XAtB_block_allSmallSizedMatrices((L + i * lda + i), (B + i), m, n, rsa, rsb, lda, ldb); } else { trsm_XAtB_block_allSmallSizedMatrices_unitDiag((L + i * lda + i), (B + i), m, n, rsa, rsb, lda, ldb); } } return BLIS_SUCCESS; } /* * A'X = Alpha*B, Single precision, A: upper triangular * This kernel implementation supports matrices A and B such that * m and n are multiples of 8, m is less than or equal to BLI_AutXB_M_SP and n is less than or equal to BLI_AutXB_N_SP */ static err_t bli_strsm_small_AutXB( side_t side, obj_t* AlphaObj, obj_t* a, obj_t* b, cntx_t* cntx, cntl_t* cntl ) { int m = bli_obj_width(a); // number of rows of matrix A (since At, so width is taken) int n = bli_obj_width(b); // number of columns of matrix B int lda = bli_obj_col_stride(a); // column stride of A int ldb = bli_obj_col_stride(b); // column stride of B int rsa = bli_obj_row_stride(a); // row stride of A int rsb = bli_obj_row_stride(b); // row stride of B int i = 0; int isUnitDiag = bli_obj_has_unit_diag(a); float alphaVal; float *L = a->buffer; float *B = b->buffer; if ((m&7) != 0 || (n&7) != 0) { return BLIS_NOT_YET_IMPLEMENTED; } if ( m > BLI_AutXB_M_SP || n > BLI_AutXB_N_SP || (m*(m + n)) > BLIS_SMALL_MATRIX_THRES_TRSM ) { return BLIS_NOT_YET_IMPLEMENTED; } alphaVal = *((float *)bli_obj_buffer_for_const(BLIS_FLOAT, AlphaObj)); if (alphaVal != 1) { if (isUnitDiag == 0) { trsm_AutXB_block_allSmallSizedMatrices_alpha((L + i * lda + i), (B + i), m, n, rsa, rsb, lda, ldb, alphaVal); } else { trsm_AutXB_block_allSmallSizedMatrices_alpha_unitDiag((L + i * lda + i), (B + i), m, n, rsa, rsb, lda, ldb, alphaVal); } } else { if (isUnitDiag == 0) { trsm_AutXB_block_allSmallSizedMatrices((L + i * lda + i), (B + i), m, n, rsa, rsb, lda, ldb); } else { trsm_AutXB_block_allSmallSizedMatrices_unitDiag((L + i * lda + i), (B + i), m, n, rsa, rsb, lda, ldb); } } return BLIS_SUCCESS; } ///////////////////////////// AX=B /////////////////////////////// static void blis_strsm_microkernel_alpha(float *ptr_l, float *ptr_b, int numRows_lb, int numCols_b, int rs_l, int rs_b, int cs_l, int cs_b, float alphaVal) { float ones = 1.0; int j; int cs_b_offset[6]; //int row2, row4, row6; float *ptr_b_dup; //70 number of ymm(256 bits) registers used __m256 mat_b_col[8]; __m256 mat_b_rearr[8]; __m256 mat_a_cols[8]; __m256 mat_a_cols_rearr[36]; __m256 mat_a_diag_inv[8]; __m256 reciprocal_diags; __m256 alphaReg; cs_b_offset[0] = (cs_b << 1); cs_b_offset[1] = cs_b + cs_b_offset[0]; cs_b_offset[2] = (cs_b << 2); cs_b_offset[3] = cs_b + cs_b_offset[2]; cs_b_offset[4] = cs_b_offset[0] + cs_b_offset[2]; cs_b_offset[5] = cs_b + cs_b_offset[4]; //reciprocal_diags = _mm256_loadu_ps((float const *)ones); reciprocal_diags = _mm256_broadcast_ss((float const *)&ones); alphaReg = _mm256_broadcast_ss((float const *)&alphaVal); // ---> considering that the matrix size is multiple of 16 rows and 8 cols <--- // //read first set of 16x8 block of B into registers, where 16 is the blk_height and 8 is the blk_width for B mat_b_col[0] = _mm256_loadu_ps((float const *)ptr_b); //_mm_prefetch((char*)(ptr_l + 0), _MM_HINT_T0); //row2 = (cs_l << 1); //row4 = (cs_l << 2); mat_b_col[1] = _mm256_loadu_ps((float const *)(ptr_b + (cs_b))); //_mm_prefetch((char*)(ptr_l + cs_l), _MM_HINT_T0); mat_b_col[2] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[0])); //_mm_prefetch((char*)(ptr_l + row2), _MM_HINT_T0); mat_b_col[3] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[1])); //_mm_prefetch((char*)(ptr_l + row2 + cs_l), _MM_HINT_T0); //row6 = row2 + row4; mat_b_col[4] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[2])); //_mm_prefetch((char*)(ptr_l + row4), _MM_HINT_T0); mat_b_col[5] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[3])); //_mm_prefetch((char*)(ptr_l + row4 + cs_l), _MM_HINT_T0); mat_b_col[6] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[4])); //_mm_prefetch((char*)(ptr_l + row6), _MM_HINT_T0); mat_b_col[7] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[5])); //_mm_prefetch((char*)(ptr_l + row6 + cs_l), _MM_HINT_T0); //reciprocal_diags = _mm256_loadu_ps((float const *)ones); //read first set of 16x16 block of L, where 16 is the blk_height and 16 is the blk_width for L /*mat_a_cols[0] = _mm256_loadu_ps((float const *)ptr_l); ptr_l += cs_l; mat_a_cols[1] = _mm256_loadu_ps((float const *)ptr_l); ptr_l += cs_l; mat_a_cols[2] = _mm256_loadu_ps((float const *)ptr_l); ptr_l += cs_l; mat_a_cols[3] = _mm256_loadu_ps((float const *)ptr_l); ptr_l += cs_l; mat_a_cols[4] = _mm256_loadu_ps((float const *)ptr_l); ptr_l += cs_l; mat_a_cols[5] = _mm256_loadu_ps((float const *)ptr_l); ptr_l += cs_l; mat_a_cols[6] = _mm256_loadu_ps((float const *)ptr_l); ptr_l += cs_l; mat_a_cols[7] = _mm256_loadu_ps((float const *)ptr_l);*/ //Shuffle to rearrange/transpose 16x16 block of L into contiguous row-wise registers //tmpRegs[0] = _mm256_castps256_ps128(mat_a_cols[0]); //zero latency, no instruction added actually. //mat_a_cols_rearr[0] = _mm256_broadcastss_ps(tmpRegs[0]); //1st col mat_a_cols_rearr[0] = _mm256_broadcast_ss((float const *)(ptr_l+0)); mat_a_cols_rearr[1] = _mm256_broadcast_ss((float const *)(ptr_l+1)); mat_a_cols_rearr[3] = _mm256_broadcast_ss((float const *)(ptr_l+2)); mat_a_cols_rearr[6] = _mm256_broadcast_ss((float const *)(ptr_l+3)); mat_a_cols_rearr[10] = _mm256_broadcast_ss((float const *)(ptr_l+4)); mat_a_cols_rearr[15] = _mm256_broadcast_ss((float const *)(ptr_l+5)); mat_a_cols_rearr[21] = _mm256_broadcast_ss((float const *)(ptr_l+6)); mat_a_cols_rearr[28] = _mm256_broadcast_ss((float const *)(ptr_l+7)); //2nd col ptr_l += cs_l; mat_a_cols_rearr[2] = _mm256_broadcast_ss((float const *)(ptr_l + 1)); mat_a_cols_rearr[4] = _mm256_broadcast_ss((float const *)(ptr_l + 2)); mat_a_cols_rearr[7] = _mm256_broadcast_ss((float const *)(ptr_l + 3)); mat_a_cols_rearr[11] = _mm256_broadcast_ss((float const *)(ptr_l + 4)); mat_a_cols_rearr[16] = _mm256_broadcast_ss((float const *)(ptr_l + 5)); mat_a_cols_rearr[22] = _mm256_broadcast_ss((float const *)(ptr_l + 6)); mat_a_cols_rearr[29] = _mm256_broadcast_ss((float const *)(ptr_l + 7)); //3rd col ptr_l += cs_l; mat_a_cols_rearr[5] = _mm256_broadcast_ss((float const *)(ptr_l + 2)); mat_a_cols_rearr[8] = _mm256_broadcast_ss((float const *)(ptr_l + 3)); mat_a_cols_rearr[12] = _mm256_broadcast_ss((float const *)(ptr_l + 4)); mat_a_cols_rearr[17] = _mm256_broadcast_ss((float const *)(ptr_l + 5)); mat_a_cols_rearr[23] = _mm256_broadcast_ss((float const *)(ptr_l + 6)); mat_a_cols_rearr[30] = _mm256_broadcast_ss((float const *)(ptr_l + 7)); //4rth col ptr_l += cs_l; mat_a_cols_rearr[9] = _mm256_broadcast_ss((float const *)(ptr_l + 3)); mat_a_cols_rearr[13] = _mm256_broadcast_ss((float const *)(ptr_l + 4)); mat_a_cols_rearr[18] = _mm256_broadcast_ss((float const *)(ptr_l + 5)); mat_a_cols_rearr[24] = _mm256_broadcast_ss((float const *)(ptr_l + 6)); mat_a_cols_rearr[31] = _mm256_broadcast_ss((float const *)(ptr_l + 7)); //5th col ptr_l += cs_l; mat_a_cols_rearr[14] = _mm256_broadcast_ss((float const *)(ptr_l + 4)); mat_a_cols_rearr[19] = _mm256_broadcast_ss((float const *)(ptr_l + 5)); mat_a_cols_rearr[25] = _mm256_broadcast_ss((float const *)(ptr_l + 6)); mat_a_cols_rearr[32] = _mm256_broadcast_ss((float const *)(ptr_l + 7)); //6th col ptr_l += cs_l; mat_a_cols_rearr[20] = _mm256_broadcast_ss((float const *)(ptr_l + 5)); mat_a_cols_rearr[26] = _mm256_broadcast_ss((float const *)(ptr_l + 6)); mat_a_cols_rearr[33] = _mm256_broadcast_ss((float const *)(ptr_l + 7)); //7th col ptr_l += cs_l; mat_a_cols_rearr[27] = _mm256_broadcast_ss((float const *)(ptr_l + 6)); mat_a_cols_rearr[34] = _mm256_broadcast_ss((float const *)(ptr_l + 7)); //7th col ptr_l += cs_l; mat_a_cols_rearr[35] = _mm256_broadcast_ss((float const *)(ptr_l + 7)); numCols_b -= 8; // blk_width = 8 //compute reciprocals of L(i,i) and broadcast in registers mat_a_diag_inv[0] = _mm256_unpacklo_ps(mat_a_cols_rearr[0], mat_a_cols_rearr[2]); mat_a_diag_inv[1] = _mm256_unpacklo_ps(mat_a_cols_rearr[5], mat_a_cols_rearr[9]); mat_a_diag_inv[2] = _mm256_unpacklo_ps(mat_a_cols_rearr[14], mat_a_cols_rearr[20]); mat_a_diag_inv[3] = _mm256_unpacklo_ps(mat_a_cols_rearr[27], mat_a_cols_rearr[35]); //mat_a_diag_inv[1] = _mm256_permute_ps(mat_a_diag_inv[1], 0x55); //mat_a_diag_inv[3] = _mm256_permute_ps(mat_a_diag_inv[3], 0x55); mat_a_diag_inv[0] = _mm256_blend_ps(mat_a_diag_inv[0], mat_a_diag_inv[1], 0xCC); mat_a_diag_inv[1] = _mm256_blend_ps(mat_a_diag_inv[2], mat_a_diag_inv[3], 0xCC); mat_a_diag_inv[0] = _mm256_permute2f128_ps(mat_a_diag_inv[0], mat_a_diag_inv[1], 0x20); //reciprocal of diagnol elements reciprocal_diags = _mm256_div_ps(reciprocal_diags, mat_a_diag_inv[0]); //Start loop for cols of B to be processed in size of blk_width for (j = 0; j < numCols_b; j += 8) { ptr_b_dup = ptr_b; /*Shuffle to rearrange/transpose 16x8 block of B into contiguous row-wise registers*/ ////unpacklow//// mat_b_rearr[0] = _mm256_unpacklo_ps(mat_b_col[0], mat_b_col[1]); mat_b_rearr[1] = _mm256_unpacklo_ps(mat_b_col[2], mat_b_col[3]); mat_b_rearr[2] = _mm256_unpacklo_ps(mat_b_col[4], mat_b_col[5]); mat_b_rearr[3] = _mm256_unpacklo_ps(mat_b_col[6], mat_b_col[7]); //Rearrange low elements #if REARRANGE_SHFL == 1 mat_b_rearr[4] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0x44); mat_b_rearr[5] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0xEE); mat_b_rearr[6] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0x44); mat_b_rearr[7] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0xEE); #else mat_b_rearr[6] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0x4E); mat_b_rearr[7] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0x4E); mat_b_rearr[4] = _mm256_blend_ps(mat_b_rearr[0], mat_b_rearr[6], 0xCC); mat_b_rearr[5] = _mm256_blend_ps(mat_b_rearr[1], mat_b_rearr[6], 0x33); mat_b_rearr[6] = _mm256_blend_ps(mat_b_rearr[2], mat_b_rearr[7], 0xCC); mat_b_rearr[7] = _mm256_blend_ps(mat_b_rearr[3], mat_b_rearr[7], 0x33); #endif //Merge rearranged low elements into complete rows mat_b_rearr[0] = _mm256_permute2f128_ps(mat_b_rearr[4], mat_b_rearr[6], 0x20); mat_b_rearr[4] = _mm256_permute2f128_ps(mat_b_rearr[4], mat_b_rearr[6], 0x31); mat_b_rearr[1] = _mm256_permute2f128_ps(mat_b_rearr[5], mat_b_rearr[7], 0x20); mat_b_rearr[5] = _mm256_permute2f128_ps(mat_b_rearr[5], mat_b_rearr[7], 0x31); mat_b_rearr[0] = _mm256_mul_ps(mat_b_rearr[0], alphaReg); mat_b_rearr[4] = _mm256_mul_ps(mat_b_rearr[4], alphaReg); mat_b_rearr[1] = _mm256_mul_ps(mat_b_rearr[1], alphaReg); mat_b_rearr[5] = _mm256_mul_ps(mat_b_rearr[5], alphaReg); ////unpackhigh//// mat_b_col[0] = _mm256_unpackhi_ps(mat_b_col[0], mat_b_col[1]); mat_b_col[1] = _mm256_unpackhi_ps(mat_b_col[2], mat_b_col[3]); mat_b_col[2] = _mm256_unpackhi_ps(mat_b_col[4], mat_b_col[5]); mat_b_col[3] = _mm256_unpackhi_ps(mat_b_col[6], mat_b_col[7]); //Rearrange high elements #if REARRANGE_SHFL == 1 mat_b_col[4] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0x44); mat_b_col[5] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0xEE); mat_b_col[6] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0x44); mat_b_col[7] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0xEE); #else mat_b_col[6] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0x4E); mat_b_col[7] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0x4E); mat_b_col[4] = _mm256_blend_ps(mat_b_col[0], mat_b_col[6], 0xCC); mat_b_col[5] = _mm256_blend_ps(mat_b_col[1], mat_b_col[6], 0x33); mat_b_col[6] = _mm256_blend_ps(mat_b_col[2], mat_b_col[7], 0xCC); mat_b_col[7] = _mm256_blend_ps(mat_b_col[3], mat_b_col[7], 0x33); #endif //extract diag a00 from a mat_a_diag_inv[0] = _mm256_permute_ps(reciprocal_diags, 0x00); mat_a_diag_inv[0] = _mm256_permute2f128_ps(mat_a_diag_inv[0], mat_a_diag_inv[0], 0x00); //(Row0): Perform mul operation of reciprocal of L(0,0) element with 1st row elements of B mat_b_rearr[0] = _mm256_mul_ps(mat_b_rearr[0], mat_a_diag_inv[0]); //Merge rearranged high elements into complete rows mat_b_rearr[2] = _mm256_permute2f128_ps(mat_b_col[4], mat_b_col[6], 0x20); mat_b_rearr[6] = _mm256_permute2f128_ps(mat_b_col[4], mat_b_col[6], 0x31); mat_b_rearr[3] = _mm256_permute2f128_ps(mat_b_col[5], mat_b_col[7], 0x20); mat_b_rearr[7] = _mm256_permute2f128_ps(mat_b_col[5], mat_b_col[7], 0x31); mat_b_rearr[2] = _mm256_mul_ps(mat_b_rearr[2], alphaReg); mat_b_rearr[6] = _mm256_mul_ps(mat_b_rearr[6], alphaReg); mat_b_rearr[3] = _mm256_mul_ps(mat_b_rearr[3], alphaReg); mat_b_rearr[7] = _mm256_mul_ps(mat_b_rearr[7], alphaReg); //extract diag a11 from a mat_a_diag_inv[1] = _mm256_permute_ps(reciprocal_diags, 0x55); mat_a_diag_inv[1] = _mm256_permute2f128_ps(mat_a_diag_inv[1], mat_a_diag_inv[1], 0x00); //(Row1): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_cols_rearr[1], mat_b_rearr[0], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_cols_rearr[3], mat_b_rearr[0], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_cols_rearr[6], mat_b_rearr[0], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_cols_rearr[10], mat_b_rearr[0], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_cols_rearr[15], mat_b_rearr[0], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_cols_rearr[21], mat_b_rearr[0], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_cols_rearr[28], mat_b_rearr[0], mat_b_rearr[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(1,1) element with 2nd row elements of B mat_b_rearr[1] = _mm256_mul_ps(mat_b_rearr[1], mat_a_diag_inv[1]); //extract diag a22 from a mat_a_diag_inv[2] = _mm256_permute_ps(reciprocal_diags, 0xAA); mat_a_diag_inv[2] = _mm256_permute2f128_ps(mat_a_diag_inv[2], mat_a_diag_inv[2], 0x00); //(Row2): FMA operations of b2 with elements of indices from (2, 0) uptill (7, 0) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_cols_rearr[4], mat_b_rearr[1], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_cols_rearr[7], mat_b_rearr[1], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_cols_rearr[11], mat_b_rearr[1], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_cols_rearr[16], mat_b_rearr[1], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_cols_rearr[22], mat_b_rearr[1], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_cols_rearr[29], mat_b_rearr[1], mat_b_rearr[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(2, 2) element with 3rd row elements of B mat_b_rearr[2] = _mm256_mul_ps(mat_b_rearr[2], mat_a_diag_inv[2]); //extract diag a33 from a mat_a_diag_inv[3] = _mm256_permute_ps(reciprocal_diags, 0xFF); mat_a_diag_inv[3] = _mm256_permute2f128_ps(mat_a_diag_inv[3], mat_a_diag_inv[3], 0x00); //(Row3): FMA operations of b3 with elements of indices from (3, 0) uptill (7, 0) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_cols_rearr[8], mat_b_rearr[2], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_cols_rearr[12], mat_b_rearr[2], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_cols_rearr[17], mat_b_rearr[2], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_cols_rearr[23], mat_b_rearr[2], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_cols_rearr[30], mat_b_rearr[2], mat_b_rearr[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(3, 3) element with 4rth row elements of B mat_b_rearr[3] = _mm256_mul_ps(mat_b_rearr[3], mat_a_diag_inv[3]); //extract diag a44 from a mat_a_diag_inv[4] = _mm256_permute_ps(reciprocal_diags, 0x00); mat_a_diag_inv[4] = _mm256_permute2f128_ps(mat_a_diag_inv[4], mat_a_diag_inv[4], 0x11); //(Row4): FMA operations of b4 with elements of indices from (4, 0) uptill (7, 0) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_cols_rearr[13], mat_b_rearr[3], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_cols_rearr[18], mat_b_rearr[3], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_cols_rearr[24], mat_b_rearr[3], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_cols_rearr[31], mat_b_rearr[3], mat_b_rearr[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(4, 4) element with 4rth row elements of B mat_b_rearr[4] = _mm256_mul_ps(mat_b_rearr[4], mat_a_diag_inv[4]); //extract diag a55 from a mat_a_diag_inv[5] = _mm256_permute_ps(reciprocal_diags, 0x55); mat_a_diag_inv[5] = _mm256_permute2f128_ps(mat_a_diag_inv[5], mat_a_diag_inv[5], 0x11); //(Row5): FMA operations of b5 with elements of indices from (5, 0) uptill (7, 0) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_cols_rearr[19], mat_b_rearr[4], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_cols_rearr[25], mat_b_rearr[4], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_cols_rearr[32], mat_b_rearr[4], mat_b_rearr[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(5, 5) element with 5th row elements of B mat_b_rearr[5] = _mm256_mul_ps(mat_b_rearr[5], mat_a_diag_inv[5]); //extract diag a66 from a mat_a_diag_inv[6] = _mm256_permute_ps(reciprocal_diags, 0xAA); mat_a_diag_inv[6] = _mm256_permute2f128_ps(mat_a_diag_inv[6], mat_a_diag_inv[6], 0x11); //(Row6): FMA operations of b6 with elements of indices from (6, 0) uptill (7, 0) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_cols_rearr[26], mat_b_rearr[5], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_cols_rearr[33], mat_b_rearr[5], mat_b_rearr[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(6, 6) element with 6th row elements of B mat_b_rearr[6] = _mm256_mul_ps(mat_b_rearr[6], mat_a_diag_inv[6]); //extract diag a77 from a mat_a_diag_inv[7] = _mm256_permute_ps(reciprocal_diags, 0xFF); mat_a_diag_inv[7] = _mm256_permute2f128_ps(mat_a_diag_inv[7], mat_a_diag_inv[7], 0x11); //(Row7): FMA operations of b7 with elements of index (7, 0) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_cols_rearr[34], mat_b_rearr[6], mat_b_rearr[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(7, 7) element with 7th row elements of B mat_b_rearr[7] = _mm256_mul_ps(mat_b_rearr[7], mat_a_diag_inv[7]); //--> Transpose and store results of columns of B block <--// ////unpacklow//// mat_a_cols[0] = _mm256_unpacklo_ps(mat_b_rearr[0], mat_b_rearr[1]); mat_a_cols[1] = _mm256_unpacklo_ps(mat_b_rearr[2], mat_b_rearr[3]); mat_a_cols[2] = _mm256_unpacklo_ps(mat_b_rearr[4], mat_b_rearr[5]); mat_a_cols[3] = _mm256_unpacklo_ps(mat_b_rearr[6], mat_b_rearr[7]); //Rearrange low elements #if REARRANGE_SHFL == 1 mat_a_cols[4] = _mm256_shuffle_ps(mat_a_cols[0], mat_a_cols[1], 0x44); mat_a_cols[5] = _mm256_shuffle_ps(mat_a_cols[0], mat_a_cols[1], 0xEE); mat_a_cols[6] = _mm256_shuffle_ps(mat_a_cols[2], mat_a_cols[3], 0x44); mat_a_cols[7] = _mm256_shuffle_ps(mat_a_cols[2], mat_a_cols[3], 0xEE); #else mat_a_cols[6] = _mm256_shuffle_ps(mat_a_cols[0], mat_a_cols[1], 0x4E); mat_a_cols[7] = _mm256_shuffle_ps(mat_a_cols[2], mat_a_cols[3], 0x4E); mat_a_cols[4] = _mm256_blend_ps(mat_a_cols[0], mat_a_cols[6], 0xCC); mat_a_cols[5] = _mm256_blend_ps(mat_a_cols[1], mat_a_cols[6], 0x33); mat_a_cols[6] = _mm256_blend_ps(mat_a_cols[2], mat_a_cols[7], 0xCC); mat_a_cols[7] = _mm256_blend_ps(mat_a_cols[3], mat_a_cols[7], 0x33); #endif //Merge rearranged low elements into complete rows mat_a_cols[0] = _mm256_permute2f128_ps(mat_a_cols[4], mat_a_cols[6], 0x20); mat_a_cols[4] = _mm256_permute2f128_ps(mat_a_cols[4], mat_a_cols[6], 0x31); mat_a_cols[1] = _mm256_permute2f128_ps(mat_a_cols[5], mat_a_cols[7], 0x20); mat_a_cols[5] = _mm256_permute2f128_ps(mat_a_cols[5], mat_a_cols[7], 0x31); ////unpackhigh//// mat_b_rearr[0] = _mm256_unpackhi_ps(mat_b_rearr[0], mat_b_rearr[1]); mat_b_rearr[1] = _mm256_unpackhi_ps(mat_b_rearr[2], mat_b_rearr[3]); mat_b_rearr[2] = _mm256_unpackhi_ps(mat_b_rearr[4], mat_b_rearr[5]); mat_b_rearr[3] = _mm256_unpackhi_ps(mat_b_rearr[6], mat_b_rearr[7]); //Rearrange high elements #if REARRANGE_SHFL == 1 mat_b_rearr[4] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0x44); mat_b_rearr[5] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0xEE); mat_b_rearr[6] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0x44); mat_b_rearr[7] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0xEE); #else mat_b_rearr[6] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0x4E); mat_b_rearr[7] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0x4E); mat_b_rearr[4] = _mm256_blend_ps(mat_b_rearr[0], mat_b_rearr[6], 0xCC); mat_b_rearr[5] = _mm256_blend_ps(mat_b_rearr[1], mat_b_rearr[6], 0x33); mat_b_rearr[6] = _mm256_blend_ps(mat_b_rearr[2], mat_b_rearr[7], 0xCC); mat_b_rearr[7] = _mm256_blend_ps(mat_b_rearr[3], mat_b_rearr[7], 0x33); #endif //Merge rearranged high elements into complete rows mat_a_cols[2] = _mm256_permute2f128_ps(mat_b_rearr[4], mat_b_rearr[6], 0x20); mat_a_cols[6] = _mm256_permute2f128_ps(mat_b_rearr[4], mat_b_rearr[6], 0x31); mat_a_cols[3] = _mm256_permute2f128_ps(mat_b_rearr[5], mat_b_rearr[7], 0x20); mat_a_cols[7] = _mm256_permute2f128_ps(mat_b_rearr[5], mat_b_rearr[7], 0x31); //Read next set of B columns ptr_b += (cs_b + cs_b_offset[5]); mat_b_col[0] = _mm256_loadu_ps((float const *)ptr_b); mat_b_col[1] = _mm256_loadu_ps((float const *)(ptr_b + (cs_b))); mat_b_col[2] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[0])); mat_b_col[3] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[1])); mat_b_col[4] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[2])); mat_b_col[5] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[3])); mat_b_col[6] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[4])); mat_b_col[7] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[5])); //Store the computed B columns _mm256_storeu_ps((float *)ptr_b_dup, mat_a_cols[0]); _mm256_storeu_ps((float *)(ptr_b_dup + (cs_b)), mat_a_cols[1]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[0]), mat_a_cols[2]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[1]), mat_a_cols[3]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[2]), mat_a_cols[4]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[3]), mat_a_cols[5]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[4]), mat_a_cols[6]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[5]), mat_a_cols[7]); //end loop of cols } //Last block trsm processing ptr_b_dup = ptr_b; /*Shuffle to rearrange/transpose 16x8 block of B into contiguous row-wise registers*/ ////unpacklow//// mat_b_rearr[0] = _mm256_unpacklo_ps(mat_b_col[0], mat_b_col[1]); mat_b_rearr[1] = _mm256_unpacklo_ps(mat_b_col[2], mat_b_col[3]); mat_b_rearr[2] = _mm256_unpacklo_ps(mat_b_col[4], mat_b_col[5]); mat_b_rearr[3] = _mm256_unpacklo_ps(mat_b_col[6], mat_b_col[7]); //Rearrange low elements #if REARRANGE_SHFL == 1 mat_b_rearr[4] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0x44); mat_b_rearr[5] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0xEE); mat_b_rearr[6] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0x44); mat_b_rearr[7] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0xEE); #else mat_b_rearr[6] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0x4E); mat_b_rearr[7] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0x4E); mat_b_rearr[4] = _mm256_blend_ps(mat_b_rearr[0], mat_b_rearr[6], 0xCC); mat_b_rearr[5] = _mm256_blend_ps(mat_b_rearr[1], mat_b_rearr[6], 0x33); mat_b_rearr[6] = _mm256_blend_ps(mat_b_rearr[2], mat_b_rearr[7], 0xCC); mat_b_rearr[7] = _mm256_blend_ps(mat_b_rearr[3], mat_b_rearr[7], 0x33); #endif //Merge rearranged low elements into complete rows mat_b_rearr[0] = _mm256_permute2f128_ps(mat_b_rearr[4], mat_b_rearr[6], 0x20); mat_b_rearr[4] = _mm256_permute2f128_ps(mat_b_rearr[4], mat_b_rearr[6], 0x31); mat_b_rearr[1] = _mm256_permute2f128_ps(mat_b_rearr[5], mat_b_rearr[7], 0x20); mat_b_rearr[5] = _mm256_permute2f128_ps(mat_b_rearr[5], mat_b_rearr[7], 0x31); mat_b_rearr[0] = _mm256_mul_ps(mat_b_rearr[0], alphaReg); mat_b_rearr[4] = _mm256_mul_ps(mat_b_rearr[4], alphaReg); mat_b_rearr[1] = _mm256_mul_ps(mat_b_rearr[1], alphaReg); mat_b_rearr[5] = _mm256_mul_ps(mat_b_rearr[5], alphaReg); ////unpackhigh//// mat_b_col[0] = _mm256_unpackhi_ps(mat_b_col[0], mat_b_col[1]); mat_b_col[1] = _mm256_unpackhi_ps(mat_b_col[2], mat_b_col[3]); mat_b_col[2] = _mm256_unpackhi_ps(mat_b_col[4], mat_b_col[5]); mat_b_col[3] = _mm256_unpackhi_ps(mat_b_col[6], mat_b_col[7]); //Rearrange high elements #if REARRANGE_SHFL == 1 mat_b_col[4] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0x44); mat_b_col[5] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0xEE); mat_b_col[6] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0x44); mat_b_col[7] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0xEE); #else mat_b_col[6] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0x4E); mat_b_col[7] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0x4E); mat_b_col[4] = _mm256_blend_ps(mat_b_col[0], mat_b_col[6], 0xCC); mat_b_col[5] = _mm256_blend_ps(mat_b_col[1], mat_b_col[6], 0x33); mat_b_col[6] = _mm256_blend_ps(mat_b_col[2], mat_b_col[7], 0xCC); mat_b_col[7] = _mm256_blend_ps(mat_b_col[3], mat_b_col[7], 0x33); #endif //extract diag a00 from a mat_a_diag_inv[0] = _mm256_permute_ps(reciprocal_diags, 0x00); mat_a_diag_inv[0] = _mm256_permute2f128_ps(mat_a_diag_inv[0], mat_a_diag_inv[0], 0x00); //(Row0): Perform mul operation of reciprocal of L(0,0) element with 1st row elements of B mat_b_rearr[0] = _mm256_mul_ps(mat_b_rearr[0], mat_a_diag_inv[0]); //Merge rearranged high elements into complete rows mat_b_rearr[2] = _mm256_permute2f128_ps(mat_b_col[4], mat_b_col[6], 0x20); mat_b_rearr[6] = _mm256_permute2f128_ps(mat_b_col[4], mat_b_col[6], 0x31); mat_b_rearr[3] = _mm256_permute2f128_ps(mat_b_col[5], mat_b_col[7], 0x20); mat_b_rearr[7] = _mm256_permute2f128_ps(mat_b_col[5], mat_b_col[7], 0x31); mat_b_rearr[2] = _mm256_mul_ps(mat_b_rearr[2], alphaReg); mat_b_rearr[6] = _mm256_mul_ps(mat_b_rearr[6], alphaReg); mat_b_rearr[3] = _mm256_mul_ps(mat_b_rearr[3], alphaReg); mat_b_rearr[7] = _mm256_mul_ps(mat_b_rearr[7], alphaReg); //extract diag a11 from a mat_a_diag_inv[1] = _mm256_permute_ps(reciprocal_diags, 0x55); mat_a_diag_inv[1] = _mm256_permute2f128_ps(mat_a_diag_inv[1], mat_a_diag_inv[1], 0x00); //(Row1): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_cols_rearr[1], mat_b_rearr[0], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_cols_rearr[3], mat_b_rearr[0], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_cols_rearr[6], mat_b_rearr[0], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_cols_rearr[10], mat_b_rearr[0], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_cols_rearr[15], mat_b_rearr[0], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_cols_rearr[21], mat_b_rearr[0], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_cols_rearr[28], mat_b_rearr[0], mat_b_rearr[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(1,1) element with 2nd row elements of B mat_b_rearr[1] = _mm256_mul_ps(mat_b_rearr[1], mat_a_diag_inv[1]); //extract diag a22 from a mat_a_diag_inv[2] = _mm256_permute_ps(reciprocal_diags, 0xAA); mat_a_diag_inv[2] = _mm256_permute2f128_ps(mat_a_diag_inv[2], mat_a_diag_inv[2], 0x00); //(Row2): FMA operations of b2 with elements of indices from (2, 0) uptill (7, 0) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_cols_rearr[4], mat_b_rearr[1], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_cols_rearr[7], mat_b_rearr[1], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_cols_rearr[11], mat_b_rearr[1], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_cols_rearr[16], mat_b_rearr[1], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_cols_rearr[22], mat_b_rearr[1], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_cols_rearr[29], mat_b_rearr[1], mat_b_rearr[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(2, 2) element with 3rd row elements of B mat_b_rearr[2] = _mm256_mul_ps(mat_b_rearr[2], mat_a_diag_inv[2]); //extract diag a33 from a mat_a_diag_inv[3] = _mm256_permute_ps(reciprocal_diags, 0xFF); mat_a_diag_inv[3] = _mm256_permute2f128_ps(mat_a_diag_inv[3], mat_a_diag_inv[3], 0x00); //(Row3): FMA operations of b3 with elements of indices from (3, 0) uptill (7, 0) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_cols_rearr[8], mat_b_rearr[2], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_cols_rearr[12], mat_b_rearr[2], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_cols_rearr[17], mat_b_rearr[2], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_cols_rearr[23], mat_b_rearr[2], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_cols_rearr[30], mat_b_rearr[2], mat_b_rearr[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(3, 3) element with 4rth row elements of B mat_b_rearr[3] = _mm256_mul_ps(mat_b_rearr[3], mat_a_diag_inv[3]); //extract diag a44 from a mat_a_diag_inv[4] = _mm256_permute_ps(reciprocal_diags, 0x00); mat_a_diag_inv[4] = _mm256_permute2f128_ps(mat_a_diag_inv[4], mat_a_diag_inv[4], 0x11); //(Row4): FMA operations of b4 with elements of indices from (4, 0) uptill (7, 0) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_cols_rearr[13], mat_b_rearr[3], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_cols_rearr[18], mat_b_rearr[3], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_cols_rearr[24], mat_b_rearr[3], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_cols_rearr[31], mat_b_rearr[3], mat_b_rearr[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(4, 4) element with 4rth row elements of B mat_b_rearr[4] = _mm256_mul_ps(mat_b_rearr[4], mat_a_diag_inv[4]); //extract diag a55 from a mat_a_diag_inv[5] = _mm256_permute_ps(reciprocal_diags, 0x55); mat_a_diag_inv[5] = _mm256_permute2f128_ps(mat_a_diag_inv[5], mat_a_diag_inv[5], 0x11); //(Row5): FMA operations of b5 with elements of indices from (5, 0) uptill (7, 0) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_cols_rearr[19], mat_b_rearr[4], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_cols_rearr[25], mat_b_rearr[4], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_cols_rearr[32], mat_b_rearr[4], mat_b_rearr[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(5, 5) element with 5th row elements of B mat_b_rearr[5] = _mm256_mul_ps(mat_b_rearr[5], mat_a_diag_inv[5]); //extract diag a66 from a mat_a_diag_inv[6] = _mm256_permute_ps(reciprocal_diags, 0xAA); mat_a_diag_inv[6] = _mm256_permute2f128_ps(mat_a_diag_inv[6], mat_a_diag_inv[6], 0x11); //(Row6): FMA operations of b6 with elements of indices from (6, 0) uptill (7, 0) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_cols_rearr[26], mat_b_rearr[5], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_cols_rearr[33], mat_b_rearr[5], mat_b_rearr[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(6, 6) element with 6th row elements of B mat_b_rearr[6] = _mm256_mul_ps(mat_b_rearr[6], mat_a_diag_inv[6]); //extract diag a77 from a mat_a_diag_inv[7] = _mm256_permute_ps(reciprocal_diags, 0xFF); mat_a_diag_inv[7] = _mm256_permute2f128_ps(mat_a_diag_inv[7], mat_a_diag_inv[7], 0x11); //(Row7): FMA operations of b7 with elements of index (7, 0) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_cols_rearr[34], mat_b_rearr[6], mat_b_rearr[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(7, 7) element with 7th row elements of B mat_b_rearr[7] = _mm256_mul_ps(mat_b_rearr[7], mat_a_diag_inv[7]); //--> Transpose and store results of columns of B block <--// ////unpacklow//// mat_a_cols[0] = _mm256_unpacklo_ps(mat_b_rearr[0], mat_b_rearr[1]); mat_a_cols[1] = _mm256_unpacklo_ps(mat_b_rearr[2], mat_b_rearr[3]); mat_a_cols[2] = _mm256_unpacklo_ps(mat_b_rearr[4], mat_b_rearr[5]); mat_a_cols[3] = _mm256_unpacklo_ps(mat_b_rearr[6], mat_b_rearr[7]); //Rearrange low elements #if REARRANGE_SHFL == 1 mat_a_cols[4] = _mm256_shuffle_ps(mat_a_cols[0], mat_a_cols[1], 0x44); mat_a_cols[5] = _mm256_shuffle_ps(mat_a_cols[0], mat_a_cols[1], 0xEE); mat_a_cols[6] = _mm256_shuffle_ps(mat_a_cols[2], mat_a_cols[3], 0x44); mat_a_cols[7] = _mm256_shuffle_ps(mat_a_cols[2], mat_a_cols[3], 0xEE); #else mat_a_cols[6] = _mm256_shuffle_ps(mat_a_cols[0], mat_a_cols[1], 0x4E); mat_a_cols[7] = _mm256_shuffle_ps(mat_a_cols[2], mat_a_cols[3], 0x4E); mat_a_cols[4] = _mm256_blend_ps(mat_a_cols[0], mat_a_cols[6], 0xCC); mat_a_cols[5] = _mm256_blend_ps(mat_a_cols[1], mat_a_cols[6], 0x33); mat_a_cols[6] = _mm256_blend_ps(mat_a_cols[2], mat_a_cols[7], 0xCC); mat_a_cols[7] = _mm256_blend_ps(mat_a_cols[3], mat_a_cols[7], 0x33); #endif //Merge rearranged low elements into complete rows mat_a_cols[0] = _mm256_permute2f128_ps(mat_a_cols[4], mat_a_cols[6], 0x20); mat_a_cols[4] = _mm256_permute2f128_ps(mat_a_cols[4], mat_a_cols[6], 0x31); mat_a_cols[1] = _mm256_permute2f128_ps(mat_a_cols[5], mat_a_cols[7], 0x20); mat_a_cols[5] = _mm256_permute2f128_ps(mat_a_cols[5], mat_a_cols[7], 0x31); ////unpackhigh//// mat_b_rearr[0] = _mm256_unpackhi_ps(mat_b_rearr[0], mat_b_rearr[1]); mat_b_rearr[1] = _mm256_unpackhi_ps(mat_b_rearr[2], mat_b_rearr[3]); mat_b_rearr[2] = _mm256_unpackhi_ps(mat_b_rearr[4], mat_b_rearr[5]); mat_b_rearr[3] = _mm256_unpackhi_ps(mat_b_rearr[6], mat_b_rearr[7]); //Rearrange high elements #if REARRANGE_SHFL == 1 mat_b_rearr[4] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0x44); mat_b_rearr[5] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0xEE); mat_b_rearr[6] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0x44); mat_b_rearr[7] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0xEE); #else mat_b_rearr[6] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0x4E); mat_b_rearr[7] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0x4E); mat_b_rearr[4] = _mm256_blend_ps(mat_b_rearr[0], mat_b_rearr[6], 0xCC); mat_b_rearr[5] = _mm256_blend_ps(mat_b_rearr[1], mat_b_rearr[6], 0x33); mat_b_rearr[6] = _mm256_blend_ps(mat_b_rearr[2], mat_b_rearr[7], 0xCC); mat_b_rearr[7] = _mm256_blend_ps(mat_b_rearr[3], mat_b_rearr[7], 0x33); #endif //Merge rearranged high elements into complete rows mat_a_cols[2] = _mm256_permute2f128_ps(mat_b_rearr[4], mat_b_rearr[6], 0x20); mat_a_cols[6] = _mm256_permute2f128_ps(mat_b_rearr[4], mat_b_rearr[6], 0x31); mat_a_cols[3] = _mm256_permute2f128_ps(mat_b_rearr[5], mat_b_rearr[7], 0x20); mat_a_cols[7] = _mm256_permute2f128_ps(mat_b_rearr[5], mat_b_rearr[7], 0x31); //Store the computed B columns _mm256_storeu_ps((float *)ptr_b_dup, mat_a_cols[0]); _mm256_storeu_ps((float *)(ptr_b_dup + (cs_b)), mat_a_cols[1]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[0]), mat_a_cols[2]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[1]), mat_a_cols[3]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[2]), mat_a_cols[4]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[3]), mat_a_cols[5]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[4]), mat_a_cols[6]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[5]), mat_a_cols[7]); //end loop of cols } static void blis_strsm_microkernel_alpha_unitDiag(float *ptr_l, float *ptr_b, int numRows_lb, int numCols_b, int rs_l, int rs_b, int cs_l, int cs_b, float alphaVal) { //float ones = 1.0; int j; int cs_b_offset[6]; //int row2, row4, row6; float *ptr_b_dup; //70 number of ymm(256 bits) registers used __m256 mat_b_col[8]; __m256 mat_b_rearr[8]; __m256 mat_a_cols[8]; __m256 mat_a_cols_rearr[36]; //__m256 mat_a_diag_inv[8]; //__m256 reciprocal_diags; __m256 alphaReg; cs_b_offset[0] = (cs_b << 1); cs_b_offset[1] = cs_b + cs_b_offset[0]; cs_b_offset[2] = (cs_b << 2); cs_b_offset[3] = cs_b + cs_b_offset[2]; cs_b_offset[4] = cs_b_offset[0] + cs_b_offset[2]; cs_b_offset[5] = cs_b + cs_b_offset[4]; //reciprocal_diags = _mm256_loadu_ps((float const *)ones); //reciprocal_diags = _mm256_broadcast_ss((float const *)&ones); alphaReg = _mm256_broadcast_ss((float const *)&alphaVal); // ---> considering that the matrix size is multiple of 16 rows and 8 cols <--- // //read first set of 16x8 block of B into registers, where 16 is the blk_height and 8 is the blk_width for B mat_b_col[0] = _mm256_loadu_ps((float const *)ptr_b); //_mm_prefetch((char*)(ptr_l + 0), _MM_HINT_T0); //row2 = (cs_l << 1); //row4 = (cs_l << 2); mat_b_col[1] = _mm256_loadu_ps((float const *)(ptr_b + (cs_b))); //_mm_prefetch((char*)(ptr_l + cs_l), _MM_HINT_T0); mat_b_col[2] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[0])); //_mm_prefetch((char*)(ptr_l + row2), _MM_HINT_T0); mat_b_col[3] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[1])); //_mm_prefetch((char*)(ptr_l + row2 + cs_l), _MM_HINT_T0); //row6 = row2 + row4; mat_b_col[4] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[2])); //_mm_prefetch((char*)(ptr_l + row4), _MM_HINT_T0); mat_b_col[5] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[3])); //_mm_prefetch((char*)(ptr_l + row4 + cs_l), _MM_HINT_T0); mat_b_col[6] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[4])); //_mm_prefetch((char*)(ptr_l + row6), _MM_HINT_T0); mat_b_col[7] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[5])); //_mm_prefetch((char*)(ptr_l + row6 + cs_l), _MM_HINT_T0); //reciprocal_diags = _mm256_loadu_ps((float const *)ones); //read first set of 16x16 block of L, where 16 is the blk_height and 16 is the blk_width for L /*mat_a_cols[0] = _mm256_loadu_ps((float const *)ptr_l); ptr_l += cs_l; mat_a_cols[1] = _mm256_loadu_ps((float const *)ptr_l); ptr_l += cs_l; mat_a_cols[2] = _mm256_loadu_ps((float const *)ptr_l); ptr_l += cs_l; mat_a_cols[3] = _mm256_loadu_ps((float const *)ptr_l); ptr_l += cs_l; mat_a_cols[4] = _mm256_loadu_ps((float const *)ptr_l); ptr_l += cs_l; mat_a_cols[5] = _mm256_loadu_ps((float const *)ptr_l); ptr_l += cs_l; mat_a_cols[6] = _mm256_loadu_ps((float const *)ptr_l); ptr_l += cs_l; mat_a_cols[7] = _mm256_loadu_ps((float const *)ptr_l);*/ //Shuffle to rearrange/transpose 16x16 block of L into contiguous row-wise registers //tmpRegs[0] = _mm256_castps256_ps128(mat_a_cols[0]); //zero latency, no instruction added actually. //mat_a_cols_rearr[0] = _mm256_broadcastss_ps(tmpRegs[0]); //1st col mat_a_cols_rearr[0] = _mm256_broadcast_ss((float const *)(ptr_l+0)); mat_a_cols_rearr[1] = _mm256_broadcast_ss((float const *)(ptr_l+1)); mat_a_cols_rearr[3] = _mm256_broadcast_ss((float const *)(ptr_l+2)); mat_a_cols_rearr[6] = _mm256_broadcast_ss((float const *)(ptr_l+3)); mat_a_cols_rearr[10] = _mm256_broadcast_ss((float const *)(ptr_l+4)); mat_a_cols_rearr[15] = _mm256_broadcast_ss((float const *)(ptr_l+5)); mat_a_cols_rearr[21] = _mm256_broadcast_ss((float const *)(ptr_l+6)); mat_a_cols_rearr[28] = _mm256_broadcast_ss((float const *)(ptr_l+7)); //2nd col ptr_l += cs_l; mat_a_cols_rearr[2] = _mm256_broadcast_ss((float const *)(ptr_l + 1)); mat_a_cols_rearr[4] = _mm256_broadcast_ss((float const *)(ptr_l + 2)); mat_a_cols_rearr[7] = _mm256_broadcast_ss((float const *)(ptr_l + 3)); mat_a_cols_rearr[11] = _mm256_broadcast_ss((float const *)(ptr_l + 4)); mat_a_cols_rearr[16] = _mm256_broadcast_ss((float const *)(ptr_l + 5)); mat_a_cols_rearr[22] = _mm256_broadcast_ss((float const *)(ptr_l + 6)); mat_a_cols_rearr[29] = _mm256_broadcast_ss((float const *)(ptr_l + 7)); //3rd col ptr_l += cs_l; mat_a_cols_rearr[5] = _mm256_broadcast_ss((float const *)(ptr_l + 2)); mat_a_cols_rearr[8] = _mm256_broadcast_ss((float const *)(ptr_l + 3)); mat_a_cols_rearr[12] = _mm256_broadcast_ss((float const *)(ptr_l + 4)); mat_a_cols_rearr[17] = _mm256_broadcast_ss((float const *)(ptr_l + 5)); mat_a_cols_rearr[23] = _mm256_broadcast_ss((float const *)(ptr_l + 6)); mat_a_cols_rearr[30] = _mm256_broadcast_ss((float const *)(ptr_l + 7)); //4rth col ptr_l += cs_l; mat_a_cols_rearr[9] = _mm256_broadcast_ss((float const *)(ptr_l + 3)); mat_a_cols_rearr[13] = _mm256_broadcast_ss((float const *)(ptr_l + 4)); mat_a_cols_rearr[18] = _mm256_broadcast_ss((float const *)(ptr_l + 5)); mat_a_cols_rearr[24] = _mm256_broadcast_ss((float const *)(ptr_l + 6)); mat_a_cols_rearr[31] = _mm256_broadcast_ss((float const *)(ptr_l + 7)); //5th col ptr_l += cs_l; mat_a_cols_rearr[14] = _mm256_broadcast_ss((float const *)(ptr_l + 4)); mat_a_cols_rearr[19] = _mm256_broadcast_ss((float const *)(ptr_l + 5)); mat_a_cols_rearr[25] = _mm256_broadcast_ss((float const *)(ptr_l + 6)); mat_a_cols_rearr[32] = _mm256_broadcast_ss((float const *)(ptr_l + 7)); //6th col ptr_l += cs_l; mat_a_cols_rearr[20] = _mm256_broadcast_ss((float const *)(ptr_l + 5)); mat_a_cols_rearr[26] = _mm256_broadcast_ss((float const *)(ptr_l + 6)); mat_a_cols_rearr[33] = _mm256_broadcast_ss((float const *)(ptr_l + 7)); //7th col ptr_l += cs_l; mat_a_cols_rearr[27] = _mm256_broadcast_ss((float const *)(ptr_l + 6)); mat_a_cols_rearr[34] = _mm256_broadcast_ss((float const *)(ptr_l + 7)); //8th col //ptr_l += cs_l; //mat_a_cols_rearr[35] = _mm256_broadcast_ss((float const *)(ptr_l + 7)); numCols_b -= 8; // blk_width = 8 //compute reciprocals of L(i,i) and broadcast in registers //mat_a_diag_inv[0] = _mm256_unpacklo_ps(mat_a_cols_rearr[0], mat_a_cols_rearr[2]); //mat_a_diag_inv[1] = _mm256_unpacklo_ps(mat_a_cols_rearr[5], mat_a_cols_rearr[9]); //mat_a_diag_inv[2] = _mm256_unpacklo_ps(mat_a_cols_rearr[14], mat_a_cols_rearr[20]); //mat_a_diag_inv[3] = _mm256_unpacklo_ps(mat_a_cols_rearr[27], mat_a_cols_rearr[35]); //mat_a_diag_inv[1] = _mm256_permute_ps(mat_a_diag_inv[1], 0x55); //mat_a_diag_inv[3] = _mm256_permute_ps(mat_a_diag_inv[3], 0x55); //mat_a_diag_inv[0] = _mm256_blend_ps(mat_a_diag_inv[0], mat_a_diag_inv[1], 0xCC); //mat_a_diag_inv[1] = _mm256_blend_ps(mat_a_diag_inv[2], mat_a_diag_inv[3], 0xCC); //mat_a_diag_inv[0] = _mm256_permute2f128_ps(mat_a_diag_inv[0], mat_a_diag_inv[1], 0x20); //reciprocal of diagnol elements //reciprocal_diags = _mm256_div_ps(reciprocal_diags, mat_a_diag_inv[0]); //Start loop for cols of B to be processed in size of blk_width for (j = 0; j < numCols_b; j += 8) { ptr_b_dup = ptr_b; /*Shuffle to rearrange/transpose 16x8 block of B into contiguous row-wise registers*/ ////unpacklow//// mat_b_rearr[0] = _mm256_unpacklo_ps(mat_b_col[0], mat_b_col[1]); mat_b_rearr[1] = _mm256_unpacklo_ps(mat_b_col[2], mat_b_col[3]); mat_b_rearr[2] = _mm256_unpacklo_ps(mat_b_col[4], mat_b_col[5]); mat_b_rearr[3] = _mm256_unpacklo_ps(mat_b_col[6], mat_b_col[7]); //Rearrange low elements #if REARRANGE_SHFL == 1 mat_b_rearr[4] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0x44); mat_b_rearr[5] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0xEE); mat_b_rearr[6] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0x44); mat_b_rearr[7] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0xEE); #else mat_b_rearr[6] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0x4E); mat_b_rearr[7] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0x4E); mat_b_rearr[4] = _mm256_blend_ps(mat_b_rearr[0], mat_b_rearr[6], 0xCC); mat_b_rearr[5] = _mm256_blend_ps(mat_b_rearr[1], mat_b_rearr[6], 0x33); mat_b_rearr[6] = _mm256_blend_ps(mat_b_rearr[2], mat_b_rearr[7], 0xCC); mat_b_rearr[7] = _mm256_blend_ps(mat_b_rearr[3], mat_b_rearr[7], 0x33); #endif //Merge rearranged low elements into complete rows mat_b_rearr[0] = _mm256_permute2f128_ps(mat_b_rearr[4], mat_b_rearr[6], 0x20); mat_b_rearr[4] = _mm256_permute2f128_ps(mat_b_rearr[4], mat_b_rearr[6], 0x31); mat_b_rearr[1] = _mm256_permute2f128_ps(mat_b_rearr[5], mat_b_rearr[7], 0x20); mat_b_rearr[5] = _mm256_permute2f128_ps(mat_b_rearr[5], mat_b_rearr[7], 0x31); mat_b_rearr[0] = _mm256_mul_ps(mat_b_rearr[0], alphaReg); mat_b_rearr[4] = _mm256_mul_ps(mat_b_rearr[4], alphaReg); mat_b_rearr[1] = _mm256_mul_ps(mat_b_rearr[1], alphaReg); mat_b_rearr[5] = _mm256_mul_ps(mat_b_rearr[5], alphaReg); ////unpackhigh//// mat_b_col[0] = _mm256_unpackhi_ps(mat_b_col[0], mat_b_col[1]); mat_b_col[1] = _mm256_unpackhi_ps(mat_b_col[2], mat_b_col[3]); mat_b_col[2] = _mm256_unpackhi_ps(mat_b_col[4], mat_b_col[5]); mat_b_col[3] = _mm256_unpackhi_ps(mat_b_col[6], mat_b_col[7]); //Rearrange high elements #if REARRANGE_SHFL == 1 mat_b_col[4] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0x44); mat_b_col[5] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0xEE); mat_b_col[6] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0x44); mat_b_col[7] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0xEE); #else mat_b_col[6] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0x4E); mat_b_col[7] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0x4E); mat_b_col[4] = _mm256_blend_ps(mat_b_col[0], mat_b_col[6], 0xCC); mat_b_col[5] = _mm256_blend_ps(mat_b_col[1], mat_b_col[6], 0x33); mat_b_col[6] = _mm256_blend_ps(mat_b_col[2], mat_b_col[7], 0xCC); mat_b_col[7] = _mm256_blend_ps(mat_b_col[3], mat_b_col[7], 0x33); #endif //extract diag a00 from a //mat_a_diag_inv[0] = _mm256_permute_ps(reciprocal_diags, 0x00); //mat_a_diag_inv[0] = _mm256_permute2f128_ps(mat_a_diag_inv[0], mat_a_diag_inv[0], 0x00); //(Row0): Perform mul operation of reciprocal of L(0,0) element with 1st row elements of B //mat_b_rearr[0] = _mm256_mul_ps(mat_b_rearr[0], mat_a_diag_inv[0]); //Merge rearranged high elements into complete rows mat_b_rearr[2] = _mm256_permute2f128_ps(mat_b_col[4], mat_b_col[6], 0x20); mat_b_rearr[6] = _mm256_permute2f128_ps(mat_b_col[4], mat_b_col[6], 0x31); mat_b_rearr[3] = _mm256_permute2f128_ps(mat_b_col[5], mat_b_col[7], 0x20); mat_b_rearr[7] = _mm256_permute2f128_ps(mat_b_col[5], mat_b_col[7], 0x31); mat_b_rearr[2] = _mm256_mul_ps(mat_b_rearr[2], alphaReg); mat_b_rearr[6] = _mm256_mul_ps(mat_b_rearr[6], alphaReg); mat_b_rearr[3] = _mm256_mul_ps(mat_b_rearr[3], alphaReg); mat_b_rearr[7] = _mm256_mul_ps(mat_b_rearr[7], alphaReg); //extract diag a11 from a //mat_a_diag_inv[1] = _mm256_permute_ps(reciprocal_diags, 0x55); //mat_a_diag_inv[1] = _mm256_permute2f128_ps(mat_a_diag_inv[1], mat_a_diag_inv[1], 0x00); //(Row1): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_cols_rearr[1], mat_b_rearr[0], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_cols_rearr[3], mat_b_rearr[0], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_cols_rearr[6], mat_b_rearr[0], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_cols_rearr[10], mat_b_rearr[0], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_cols_rearr[15], mat_b_rearr[0], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_cols_rearr[21], mat_b_rearr[0], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_cols_rearr[28], mat_b_rearr[0], mat_b_rearr[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(1,1) element with 2nd row elements of B //mat_b_rearr[1] = _mm256_mul_ps(mat_b_rearr[1], mat_a_diag_inv[1]); //extract diag a22 from a //mat_a_diag_inv[2] = _mm256_permute_ps(reciprocal_diags, 0xAA); //mat_a_diag_inv[2] = _mm256_permute2f128_ps(mat_a_diag_inv[2], mat_a_diag_inv[2], 0x00); //(Row2): FMA operations of b2 with elements of indices from (2, 0) uptill (7, 0) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_cols_rearr[4], mat_b_rearr[1], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_cols_rearr[7], mat_b_rearr[1], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_cols_rearr[11], mat_b_rearr[1], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_cols_rearr[16], mat_b_rearr[1], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_cols_rearr[22], mat_b_rearr[1], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_cols_rearr[29], mat_b_rearr[1], mat_b_rearr[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(2, 2) element with 3rd row elements of B //mat_b_rearr[2] = _mm256_mul_ps(mat_b_rearr[2], mat_a_diag_inv[2]); //extract diag a33 from a //mat_a_diag_inv[3] = _mm256_permute_ps(reciprocal_diags, 0xFF); //mat_a_diag_inv[3] = _mm256_permute2f128_ps(mat_a_diag_inv[3], mat_a_diag_inv[3], 0x00); //(Row3): FMA operations of b3 with elements of indices from (3, 0) uptill (7, 0) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_cols_rearr[8], mat_b_rearr[2], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_cols_rearr[12], mat_b_rearr[2], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_cols_rearr[17], mat_b_rearr[2], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_cols_rearr[23], mat_b_rearr[2], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_cols_rearr[30], mat_b_rearr[2], mat_b_rearr[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(3, 3) element with 4rth row elements of B //mat_b_rearr[3] = _mm256_mul_ps(mat_b_rearr[3], mat_a_diag_inv[3]); //extract diag a44 from a //mat_a_diag_inv[4] = _mm256_permute_ps(reciprocal_diags, 0x00); //mat_a_diag_inv[4] = _mm256_permute2f128_ps(mat_a_diag_inv[4], mat_a_diag_inv[4], 0x11); //(Row4): FMA operations of b4 with elements of indices from (4, 0) uptill (7, 0) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_cols_rearr[13], mat_b_rearr[3], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_cols_rearr[18], mat_b_rearr[3], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_cols_rearr[24], mat_b_rearr[3], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_cols_rearr[31], mat_b_rearr[3], mat_b_rearr[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(4, 4) element with 4rth row elements of B //mat_b_rearr[4] = _mm256_mul_ps(mat_b_rearr[4], mat_a_diag_inv[4]); //extract diag a55 from a //mat_a_diag_inv[5] = _mm256_permute_ps(reciprocal_diags, 0x55); //mat_a_diag_inv[5] = _mm256_permute2f128_ps(mat_a_diag_inv[5], mat_a_diag_inv[5], 0x11); //(Row5): FMA operations of b5 with elements of indices from (5, 0) uptill (7, 0) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_cols_rearr[19], mat_b_rearr[4], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_cols_rearr[25], mat_b_rearr[4], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_cols_rearr[32], mat_b_rearr[4], mat_b_rearr[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(5, 5) element with 5th row elements of B //mat_b_rearr[5] = _mm256_mul_ps(mat_b_rearr[5], mat_a_diag_inv[5]); //extract diag a66 from a //mat_a_diag_inv[6] = _mm256_permute_ps(reciprocal_diags, 0xAA); //mat_a_diag_inv[6] = _mm256_permute2f128_ps(mat_a_diag_inv[6], mat_a_diag_inv[6], 0x11); //(Row6): FMA operations of b6 with elements of indices from (6, 0) uptill (7, 0) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_cols_rearr[26], mat_b_rearr[5], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_cols_rearr[33], mat_b_rearr[5], mat_b_rearr[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(6, 6) element with 6th row elements of B //mat_b_rearr[6] = _mm256_mul_ps(mat_b_rearr[6], mat_a_diag_inv[6]); //extract diag a77 from a //mat_a_diag_inv[7] = _mm256_permute_ps(reciprocal_diags, 0xFF); //mat_a_diag_inv[7] = _mm256_permute2f128_ps(mat_a_diag_inv[7], mat_a_diag_inv[7], 0x11); //(Row7): FMA operations of b7 with elements of index (7, 0) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_cols_rearr[34], mat_b_rearr[6], mat_b_rearr[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(7, 7) element with 7th row elements of B //mat_b_rearr[7] = _mm256_mul_ps(mat_b_rearr[7], mat_a_diag_inv[7]); //--> Transpose and store results of columns of B block <--// ////unpacklow//// mat_a_cols[0] = _mm256_unpacklo_ps(mat_b_rearr[0], mat_b_rearr[1]); mat_a_cols[1] = _mm256_unpacklo_ps(mat_b_rearr[2], mat_b_rearr[3]); mat_a_cols[2] = _mm256_unpacklo_ps(mat_b_rearr[4], mat_b_rearr[5]); mat_a_cols[3] = _mm256_unpacklo_ps(mat_b_rearr[6], mat_b_rearr[7]); //Rearrange low elements #if REARRANGE_SHFL == 1 mat_a_cols[4] = _mm256_shuffle_ps(mat_a_cols[0], mat_a_cols[1], 0x44); mat_a_cols[5] = _mm256_shuffle_ps(mat_a_cols[0], mat_a_cols[1], 0xEE); mat_a_cols[6] = _mm256_shuffle_ps(mat_a_cols[2], mat_a_cols[3], 0x44); mat_a_cols[7] = _mm256_shuffle_ps(mat_a_cols[2], mat_a_cols[3], 0xEE); #else mat_a_cols[6] = _mm256_shuffle_ps(mat_a_cols[0], mat_a_cols[1], 0x4E); mat_a_cols[7] = _mm256_shuffle_ps(mat_a_cols[2], mat_a_cols[3], 0x4E); mat_a_cols[4] = _mm256_blend_ps(mat_a_cols[0], mat_a_cols[6], 0xCC); mat_a_cols[5] = _mm256_blend_ps(mat_a_cols[1], mat_a_cols[6], 0x33); mat_a_cols[6] = _mm256_blend_ps(mat_a_cols[2], mat_a_cols[7], 0xCC); mat_a_cols[7] = _mm256_blend_ps(mat_a_cols[3], mat_a_cols[7], 0x33); #endif //Merge rearranged low elements into complete rows mat_a_cols[0] = _mm256_permute2f128_ps(mat_a_cols[4], mat_a_cols[6], 0x20); mat_a_cols[4] = _mm256_permute2f128_ps(mat_a_cols[4], mat_a_cols[6], 0x31); mat_a_cols[1] = _mm256_permute2f128_ps(mat_a_cols[5], mat_a_cols[7], 0x20); mat_a_cols[5] = _mm256_permute2f128_ps(mat_a_cols[5], mat_a_cols[7], 0x31); ////unpackhigh//// mat_b_rearr[0] = _mm256_unpackhi_ps(mat_b_rearr[0], mat_b_rearr[1]); mat_b_rearr[1] = _mm256_unpackhi_ps(mat_b_rearr[2], mat_b_rearr[3]); mat_b_rearr[2] = _mm256_unpackhi_ps(mat_b_rearr[4], mat_b_rearr[5]); mat_b_rearr[3] = _mm256_unpackhi_ps(mat_b_rearr[6], mat_b_rearr[7]); //Rearrange high elements #if REARRANGE_SHFL == 1 mat_b_rearr[4] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0x44); mat_b_rearr[5] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0xEE); mat_b_rearr[6] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0x44); mat_b_rearr[7] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0xEE); #else mat_b_rearr[6] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0x4E); mat_b_rearr[7] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0x4E); mat_b_rearr[4] = _mm256_blend_ps(mat_b_rearr[0], mat_b_rearr[6], 0xCC); mat_b_rearr[5] = _mm256_blend_ps(mat_b_rearr[1], mat_b_rearr[6], 0x33); mat_b_rearr[6] = _mm256_blend_ps(mat_b_rearr[2], mat_b_rearr[7], 0xCC); mat_b_rearr[7] = _mm256_blend_ps(mat_b_rearr[3], mat_b_rearr[7], 0x33); #endif //Merge rearranged high elements into complete rows mat_a_cols[2] = _mm256_permute2f128_ps(mat_b_rearr[4], mat_b_rearr[6], 0x20); mat_a_cols[6] = _mm256_permute2f128_ps(mat_b_rearr[4], mat_b_rearr[6], 0x31); mat_a_cols[3] = _mm256_permute2f128_ps(mat_b_rearr[5], mat_b_rearr[7], 0x20); mat_a_cols[7] = _mm256_permute2f128_ps(mat_b_rearr[5], mat_b_rearr[7], 0x31); //Read next set of B columns ptr_b += (cs_b + cs_b_offset[5]); mat_b_col[0] = _mm256_loadu_ps((float const *)ptr_b); mat_b_col[1] = _mm256_loadu_ps((float const *)(ptr_b + (cs_b))); mat_b_col[2] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[0])); mat_b_col[3] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[1])); mat_b_col[4] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[2])); mat_b_col[5] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[3])); mat_b_col[6] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[4])); mat_b_col[7] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[5])); //Store the computed B columns _mm256_storeu_ps((float *)ptr_b_dup, mat_a_cols[0]); _mm256_storeu_ps((float *)(ptr_b_dup + (cs_b)), mat_a_cols[1]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[0]), mat_a_cols[2]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[1]), mat_a_cols[3]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[2]), mat_a_cols[4]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[3]), mat_a_cols[5]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[4]), mat_a_cols[6]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[5]), mat_a_cols[7]); //end loop of cols } //Last block trsm processing ptr_b_dup = ptr_b; /*Shuffle to rearrange/transpose 16x8 block of B into contiguous row-wise registers*/ ////unpacklow//// mat_b_rearr[0] = _mm256_unpacklo_ps(mat_b_col[0], mat_b_col[1]); mat_b_rearr[1] = _mm256_unpacklo_ps(mat_b_col[2], mat_b_col[3]); mat_b_rearr[2] = _mm256_unpacklo_ps(mat_b_col[4], mat_b_col[5]); mat_b_rearr[3] = _mm256_unpacklo_ps(mat_b_col[6], mat_b_col[7]); //Rearrange low elements #if REARRANGE_SHFL == 1 mat_b_rearr[4] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0x44); mat_b_rearr[5] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0xEE); mat_b_rearr[6] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0x44); mat_b_rearr[7] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0xEE); #else mat_b_rearr[6] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0x4E); mat_b_rearr[7] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0x4E); mat_b_rearr[4] = _mm256_blend_ps(mat_b_rearr[0], mat_b_rearr[6], 0xCC); mat_b_rearr[5] = _mm256_blend_ps(mat_b_rearr[1], mat_b_rearr[6], 0x33); mat_b_rearr[6] = _mm256_blend_ps(mat_b_rearr[2], mat_b_rearr[7], 0xCC); mat_b_rearr[7] = _mm256_blend_ps(mat_b_rearr[3], mat_b_rearr[7], 0x33); #endif //Merge rearranged low elements into complete rows mat_b_rearr[0] = _mm256_permute2f128_ps(mat_b_rearr[4], mat_b_rearr[6], 0x20); mat_b_rearr[4] = _mm256_permute2f128_ps(mat_b_rearr[4], mat_b_rearr[6], 0x31); mat_b_rearr[1] = _mm256_permute2f128_ps(mat_b_rearr[5], mat_b_rearr[7], 0x20); mat_b_rearr[5] = _mm256_permute2f128_ps(mat_b_rearr[5], mat_b_rearr[7], 0x31); mat_b_rearr[0] = _mm256_mul_ps(mat_b_rearr[0], alphaReg); mat_b_rearr[4] = _mm256_mul_ps(mat_b_rearr[4], alphaReg); mat_b_rearr[1] = _mm256_mul_ps(mat_b_rearr[1], alphaReg); mat_b_rearr[5] = _mm256_mul_ps(mat_b_rearr[5], alphaReg); ////unpackhigh//// mat_b_col[0] = _mm256_unpackhi_ps(mat_b_col[0], mat_b_col[1]); mat_b_col[1] = _mm256_unpackhi_ps(mat_b_col[2], mat_b_col[3]); mat_b_col[2] = _mm256_unpackhi_ps(mat_b_col[4], mat_b_col[5]); mat_b_col[3] = _mm256_unpackhi_ps(mat_b_col[6], mat_b_col[7]); //Rearrange high elements #if REARRANGE_SHFL == 1 mat_b_col[4] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0x44); mat_b_col[5] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0xEE); mat_b_col[6] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0x44); mat_b_col[7] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0xEE); #else mat_b_col[6] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0x4E); mat_b_col[7] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0x4E); mat_b_col[4] = _mm256_blend_ps(mat_b_col[0], mat_b_col[6], 0xCC); mat_b_col[5] = _mm256_blend_ps(mat_b_col[1], mat_b_col[6], 0x33); mat_b_col[6] = _mm256_blend_ps(mat_b_col[2], mat_b_col[7], 0xCC); mat_b_col[7] = _mm256_blend_ps(mat_b_col[3], mat_b_col[7], 0x33); #endif //extract diag a00 from a //mat_a_diag_inv[0] = _mm256_permute_ps(reciprocal_diags, 0x00); //mat_a_diag_inv[0] = _mm256_permute2f128_ps(mat_a_diag_inv[0], mat_a_diag_inv[0], 0x00); //(Row0): Perform mul operation of reciprocal of L(0,0) element with 1st row elements of B //mat_b_rearr[0] = _mm256_mul_ps(mat_b_rearr[0], mat_a_diag_inv[0]); //Merge rearranged high elements into complete rows mat_b_rearr[2] = _mm256_permute2f128_ps(mat_b_col[4], mat_b_col[6], 0x20); mat_b_rearr[6] = _mm256_permute2f128_ps(mat_b_col[4], mat_b_col[6], 0x31); mat_b_rearr[3] = _mm256_permute2f128_ps(mat_b_col[5], mat_b_col[7], 0x20); mat_b_rearr[7] = _mm256_permute2f128_ps(mat_b_col[5], mat_b_col[7], 0x31); mat_b_rearr[2] = _mm256_mul_ps(mat_b_rearr[2], alphaReg); mat_b_rearr[6] = _mm256_mul_ps(mat_b_rearr[6], alphaReg); mat_b_rearr[3] = _mm256_mul_ps(mat_b_rearr[3], alphaReg); mat_b_rearr[7] = _mm256_mul_ps(mat_b_rearr[7], alphaReg); //extract diag a11 from a //mat_a_diag_inv[1] = _mm256_permute_ps(reciprocal_diags, 0x55); //mat_a_diag_inv[1] = _mm256_permute2f128_ps(mat_a_diag_inv[1], mat_a_diag_inv[1], 0x00); //(Row1): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_cols_rearr[1], mat_b_rearr[0], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_cols_rearr[3], mat_b_rearr[0], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_cols_rearr[6], mat_b_rearr[0], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_cols_rearr[10], mat_b_rearr[0], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_cols_rearr[15], mat_b_rearr[0], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_cols_rearr[21], mat_b_rearr[0], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_cols_rearr[28], mat_b_rearr[0], mat_b_rearr[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(1,1) element with 2nd row elements of B //mat_b_rearr[1] = _mm256_mul_ps(mat_b_rearr[1], mat_a_diag_inv[1]); //extract diag a22 from a //mat_a_diag_inv[2] = _mm256_permute_ps(reciprocal_diags, 0xAA); //mat_a_diag_inv[2] = _mm256_permute2f128_ps(mat_a_diag_inv[2], mat_a_diag_inv[2], 0x00); //(Row2): FMA operations of b2 with elements of indices from (2, 0) uptill (7, 0) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_cols_rearr[4], mat_b_rearr[1], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_cols_rearr[7], mat_b_rearr[1], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_cols_rearr[11], mat_b_rearr[1], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_cols_rearr[16], mat_b_rearr[1], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_cols_rearr[22], mat_b_rearr[1], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_cols_rearr[29], mat_b_rearr[1], mat_b_rearr[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(2, 2) element with 3rd row elements of B //mat_b_rearr[2] = _mm256_mul_ps(mat_b_rearr[2], mat_a_diag_inv[2]); //extract diag a33 from a //mat_a_diag_inv[3] = _mm256_permute_ps(reciprocal_diags, 0xFF); //mat_a_diag_inv[3] = _mm256_permute2f128_ps(mat_a_diag_inv[3], mat_a_diag_inv[3], 0x00); //(Row3): FMA operations of b3 with elements of indices from (3, 0) uptill (7, 0) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_cols_rearr[8], mat_b_rearr[2], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_cols_rearr[12], mat_b_rearr[2], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_cols_rearr[17], mat_b_rearr[2], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_cols_rearr[23], mat_b_rearr[2], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_cols_rearr[30], mat_b_rearr[2], mat_b_rearr[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(3, 3) element with 4rth row elements of B //mat_b_rearr[3] = _mm256_mul_ps(mat_b_rearr[3], mat_a_diag_inv[3]); //extract diag a44 from a //mat_a_diag_inv[4] = _mm256_permute_ps(reciprocal_diags, 0x00); //mat_a_diag_inv[4] = _mm256_permute2f128_ps(mat_a_diag_inv[4], mat_a_diag_inv[4], 0x11); //(Row4): FMA operations of b4 with elements of indices from (4, 0) uptill (7, 0) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_cols_rearr[13], mat_b_rearr[3], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_cols_rearr[18], mat_b_rearr[3], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_cols_rearr[24], mat_b_rearr[3], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_cols_rearr[31], mat_b_rearr[3], mat_b_rearr[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(4, 4) element with 4rth row elements of B //mat_b_rearr[4] = _mm256_mul_ps(mat_b_rearr[4], mat_a_diag_inv[4]); //extract diag a55 from a //mat_a_diag_inv[5] = _mm256_permute_ps(reciprocal_diags, 0x55); //mat_a_diag_inv[5] = _mm256_permute2f128_ps(mat_a_diag_inv[5], mat_a_diag_inv[5], 0x11); //(Row5): FMA operations of b5 with elements of indices from (5, 0) uptill (7, 0) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_cols_rearr[19], mat_b_rearr[4], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_cols_rearr[25], mat_b_rearr[4], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_cols_rearr[32], mat_b_rearr[4], mat_b_rearr[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(5, 5) element with 5th row elements of B //mat_b_rearr[5] = _mm256_mul_ps(mat_b_rearr[5], mat_a_diag_inv[5]); //extract diag a66 from a //mat_a_diag_inv[6] = _mm256_permute_ps(reciprocal_diags, 0xAA); //mat_a_diag_inv[6] = _mm256_permute2f128_ps(mat_a_diag_inv[6], mat_a_diag_inv[6], 0x11); //(Row6): FMA operations of b6 with elements of indices from (6, 0) uptill (7, 0) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_cols_rearr[26], mat_b_rearr[5], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_cols_rearr[33], mat_b_rearr[5], mat_b_rearr[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(6, 6) element with 6th row elements of B //mat_b_rearr[6] = _mm256_mul_ps(mat_b_rearr[6], mat_a_diag_inv[6]); //extract diag a77 from a //mat_a_diag_inv[7] = _mm256_permute_ps(reciprocal_diags, 0xFF); //mat_a_diag_inv[7] = _mm256_permute2f128_ps(mat_a_diag_inv[7], mat_a_diag_inv[7], 0x11); //(Row7): FMA operations of b7 with elements of index (7, 0) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_cols_rearr[34], mat_b_rearr[6], mat_b_rearr[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(7, 7) element with 7th row elements of B //mat_b_rearr[7] = _mm256_mul_ps(mat_b_rearr[7], mat_a_diag_inv[7]); //--> Transpose and store results of columns of B block <--// ////unpacklow//// mat_a_cols[0] = _mm256_unpacklo_ps(mat_b_rearr[0], mat_b_rearr[1]); mat_a_cols[1] = _mm256_unpacklo_ps(mat_b_rearr[2], mat_b_rearr[3]); mat_a_cols[2] = _mm256_unpacklo_ps(mat_b_rearr[4], mat_b_rearr[5]); mat_a_cols[3] = _mm256_unpacklo_ps(mat_b_rearr[6], mat_b_rearr[7]); //Rearrange low elements #if REARRANGE_SHFL == 1 mat_a_cols[4] = _mm256_shuffle_ps(mat_a_cols[0], mat_a_cols[1], 0x44); mat_a_cols[5] = _mm256_shuffle_ps(mat_a_cols[0], mat_a_cols[1], 0xEE); mat_a_cols[6] = _mm256_shuffle_ps(mat_a_cols[2], mat_a_cols[3], 0x44); mat_a_cols[7] = _mm256_shuffle_ps(mat_a_cols[2], mat_a_cols[3], 0xEE); #else mat_a_cols[6] = _mm256_shuffle_ps(mat_a_cols[0], mat_a_cols[1], 0x4E); mat_a_cols[7] = _mm256_shuffle_ps(mat_a_cols[2], mat_a_cols[3], 0x4E); mat_a_cols[4] = _mm256_blend_ps(mat_a_cols[0], mat_a_cols[6], 0xCC); mat_a_cols[5] = _mm256_blend_ps(mat_a_cols[1], mat_a_cols[6], 0x33); mat_a_cols[6] = _mm256_blend_ps(mat_a_cols[2], mat_a_cols[7], 0xCC); mat_a_cols[7] = _mm256_blend_ps(mat_a_cols[3], mat_a_cols[7], 0x33); #endif //Merge rearranged low elements into complete rows mat_a_cols[0] = _mm256_permute2f128_ps(mat_a_cols[4], mat_a_cols[6], 0x20); mat_a_cols[4] = _mm256_permute2f128_ps(mat_a_cols[4], mat_a_cols[6], 0x31); mat_a_cols[1] = _mm256_permute2f128_ps(mat_a_cols[5], mat_a_cols[7], 0x20); mat_a_cols[5] = _mm256_permute2f128_ps(mat_a_cols[5], mat_a_cols[7], 0x31); ////unpackhigh//// mat_b_rearr[0] = _mm256_unpackhi_ps(mat_b_rearr[0], mat_b_rearr[1]); mat_b_rearr[1] = _mm256_unpackhi_ps(mat_b_rearr[2], mat_b_rearr[3]); mat_b_rearr[2] = _mm256_unpackhi_ps(mat_b_rearr[4], mat_b_rearr[5]); mat_b_rearr[3] = _mm256_unpackhi_ps(mat_b_rearr[6], mat_b_rearr[7]); //Rearrange high elements #if REARRANGE_SHFL == 1 mat_b_rearr[4] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0x44); mat_b_rearr[5] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0xEE); mat_b_rearr[6] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0x44); mat_b_rearr[7] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0xEE); #else mat_b_rearr[6] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0x4E); mat_b_rearr[7] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0x4E); mat_b_rearr[4] = _mm256_blend_ps(mat_b_rearr[0], mat_b_rearr[6], 0xCC); mat_b_rearr[5] = _mm256_blend_ps(mat_b_rearr[1], mat_b_rearr[6], 0x33); mat_b_rearr[6] = _mm256_blend_ps(mat_b_rearr[2], mat_b_rearr[7], 0xCC); mat_b_rearr[7] = _mm256_blend_ps(mat_b_rearr[3], mat_b_rearr[7], 0x33); #endif //Merge rearranged high elements into complete rows mat_a_cols[2] = _mm256_permute2f128_ps(mat_b_rearr[4], mat_b_rearr[6], 0x20); mat_a_cols[6] = _mm256_permute2f128_ps(mat_b_rearr[4], mat_b_rearr[6], 0x31); mat_a_cols[3] = _mm256_permute2f128_ps(mat_b_rearr[5], mat_b_rearr[7], 0x20); mat_a_cols[7] = _mm256_permute2f128_ps(mat_b_rearr[5], mat_b_rearr[7], 0x31); //Store the computed B columns _mm256_storeu_ps((float *)ptr_b_dup, mat_a_cols[0]); _mm256_storeu_ps((float *)(ptr_b_dup + (cs_b)), mat_a_cols[1]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[0]), mat_a_cols[2]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[1]), mat_a_cols[3]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[2]), mat_a_cols[4]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[3]), mat_a_cols[5]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[4]), mat_a_cols[6]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[5]), mat_a_cols[7]); //end loop of cols } static void blis_strsm_microkernel_unitDiag(float *ptr_l, float *ptr_b, int numRows_lb, int numCols_b, int rs_l, int rs_b, int cs_l, int cs_b) { //float ones = 1.0; int j; int cs_b_offset[6]; //int row2, row4, row6; float *ptr_b_dup; //70 number of ymm(256 bits) registers used __m256 mat_b_col[8]; __m256 mat_b_rearr[8]; __m256 mat_a_cols[8]; __m256 mat_a_cols_rearr[36]; //__m256 mat_a_diag_inv[8]; //__m256 reciprocal_diags; cs_b_offset[0] = (cs_b << 1); cs_b_offset[1] = cs_b + cs_b_offset[0]; cs_b_offset[2] = (cs_b << 2); cs_b_offset[3] = cs_b + cs_b_offset[2]; cs_b_offset[4] = cs_b_offset[0] + cs_b_offset[2]; cs_b_offset[5] = cs_b + cs_b_offset[4]; //reciprocal_diags = _mm256_loadu_ps((float const *)ones); //reciprocal_diags = _mm256_broadcast_ss((float const *)&ones); // ---> considering that the matrix size is multiple of 16 rows and 8 cols <--- // //read first set of 16x8 block of B into registers, where 16 is the blk_height and 8 is the blk_width for B mat_b_col[0] = _mm256_loadu_ps((float const *)ptr_b); //_mm_prefetch((char*)(ptr_l + 0), _MM_HINT_T0); //row2 = (cs_l << 1); //row4 = (cs_l << 2); mat_b_col[1] = _mm256_loadu_ps((float const *)(ptr_b + (cs_b))); //_mm_prefetch((char*)(ptr_l + cs_l), _MM_HINT_T0); mat_b_col[2] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[0])); //_mm_prefetch((char*)(ptr_l + row2), _MM_HINT_T0); mat_b_col[3] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[1])); //_mm_prefetch((char*)(ptr_l + row2 + cs_l), _MM_HINT_T0); //row6 = row2 + row4; mat_b_col[4] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[2])); //_mm_prefetch((char*)(ptr_l + row4), _MM_HINT_T0); mat_b_col[5] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[3])); //_mm_prefetch((char*)(ptr_l + row4 + cs_l), _MM_HINT_T0); mat_b_col[6] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[4])); //_mm_prefetch((char*)(ptr_l + row6), _MM_HINT_T0); mat_b_col[7] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[5])); //_mm_prefetch((char*)(ptr_l + row6 + cs_l), _MM_HINT_T0); //reciprocal_diags = _mm256_loadu_ps((float const *)ones); //read first set of 16x16 block of L, where 16 is the blk_height and 16 is the blk_width for L /*mat_a_cols[0] = _mm256_loadu_ps((float const *)ptr_l); ptr_l += cs_l; mat_a_cols[1] = _mm256_loadu_ps((float const *)ptr_l); ptr_l += cs_l; mat_a_cols[2] = _mm256_loadu_ps((float const *)ptr_l); ptr_l += cs_l; mat_a_cols[3] = _mm256_loadu_ps((float const *)ptr_l); ptr_l += cs_l; mat_a_cols[4] = _mm256_loadu_ps((float const *)ptr_l); ptr_l += cs_l; mat_a_cols[5] = _mm256_loadu_ps((float const *)ptr_l); ptr_l += cs_l; mat_a_cols[6] = _mm256_loadu_ps((float const *)ptr_l); ptr_l += cs_l; mat_a_cols[7] = _mm256_loadu_ps((float const *)ptr_l);*/ //Shuffle to rearrange/transpose 16x16 block of L into contiguous row-wise registers //tmpRegs[0] = _mm256_castps256_ps128(mat_a_cols[0]); //zero latency, no instruction added actually. //mat_a_cols_rearr[0] = _mm256_broadcastss_ps(tmpRegs[0]); //1st col mat_a_cols_rearr[0] = _mm256_broadcast_ss((float const *)(ptr_l+0)); mat_a_cols_rearr[1] = _mm256_broadcast_ss((float const *)(ptr_l+1)); mat_a_cols_rearr[3] = _mm256_broadcast_ss((float const *)(ptr_l+2)); mat_a_cols_rearr[6] = _mm256_broadcast_ss((float const *)(ptr_l+3)); mat_a_cols_rearr[10] = _mm256_broadcast_ss((float const *)(ptr_l+4)); mat_a_cols_rearr[15] = _mm256_broadcast_ss((float const *)(ptr_l+5)); mat_a_cols_rearr[21] = _mm256_broadcast_ss((float const *)(ptr_l+6)); mat_a_cols_rearr[28] = _mm256_broadcast_ss((float const *)(ptr_l+7)); //2nd col ptr_l += cs_l; mat_a_cols_rearr[2] = _mm256_broadcast_ss((float const *)(ptr_l + 1)); mat_a_cols_rearr[4] = _mm256_broadcast_ss((float const *)(ptr_l + 2)); mat_a_cols_rearr[7] = _mm256_broadcast_ss((float const *)(ptr_l + 3)); mat_a_cols_rearr[11] = _mm256_broadcast_ss((float const *)(ptr_l + 4)); mat_a_cols_rearr[16] = _mm256_broadcast_ss((float const *)(ptr_l + 5)); mat_a_cols_rearr[22] = _mm256_broadcast_ss((float const *)(ptr_l + 6)); mat_a_cols_rearr[29] = _mm256_broadcast_ss((float const *)(ptr_l + 7)); //3rd col ptr_l += cs_l; mat_a_cols_rearr[5] = _mm256_broadcast_ss((float const *)(ptr_l + 2)); mat_a_cols_rearr[8] = _mm256_broadcast_ss((float const *)(ptr_l + 3)); mat_a_cols_rearr[12] = _mm256_broadcast_ss((float const *)(ptr_l + 4)); mat_a_cols_rearr[17] = _mm256_broadcast_ss((float const *)(ptr_l + 5)); mat_a_cols_rearr[23] = _mm256_broadcast_ss((float const *)(ptr_l + 6)); mat_a_cols_rearr[30] = _mm256_broadcast_ss((float const *)(ptr_l + 7)); //4rth col ptr_l += cs_l; mat_a_cols_rearr[9] = _mm256_broadcast_ss((float const *)(ptr_l + 3)); mat_a_cols_rearr[13] = _mm256_broadcast_ss((float const *)(ptr_l + 4)); mat_a_cols_rearr[18] = _mm256_broadcast_ss((float const *)(ptr_l + 5)); mat_a_cols_rearr[24] = _mm256_broadcast_ss((float const *)(ptr_l + 6)); mat_a_cols_rearr[31] = _mm256_broadcast_ss((float const *)(ptr_l + 7)); //5th col ptr_l += cs_l; mat_a_cols_rearr[14] = _mm256_broadcast_ss((float const *)(ptr_l + 4)); mat_a_cols_rearr[19] = _mm256_broadcast_ss((float const *)(ptr_l + 5)); mat_a_cols_rearr[25] = _mm256_broadcast_ss((float const *)(ptr_l + 6)); mat_a_cols_rearr[32] = _mm256_broadcast_ss((float const *)(ptr_l + 7)); //6th col ptr_l += cs_l; mat_a_cols_rearr[20] = _mm256_broadcast_ss((float const *)(ptr_l + 5)); mat_a_cols_rearr[26] = _mm256_broadcast_ss((float const *)(ptr_l + 6)); mat_a_cols_rearr[33] = _mm256_broadcast_ss((float const *)(ptr_l + 7)); //7th col ptr_l += cs_l; mat_a_cols_rearr[27] = _mm256_broadcast_ss((float const *)(ptr_l + 6)); mat_a_cols_rearr[34] = _mm256_broadcast_ss((float const *)(ptr_l + 7)); //8th col //ptr_l += cs_l; //mat_a_cols_rearr[35] = _mm256_broadcast_ss((float const *)(ptr_l + 7)); numCols_b -= 8; // blk_width = 8 //compute reciprocals of L(i,i) and broadcast in registers //mat_a_diag_inv[0] = _mm256_unpacklo_ps(mat_a_cols_rearr[0], mat_a_cols_rearr[2]); //mat_a_diag_inv[1] = _mm256_unpacklo_ps(mat_a_cols_rearr[5], mat_a_cols_rearr[9]); //mat_a_diag_inv[2] = _mm256_unpacklo_ps(mat_a_cols_rearr[14], mat_a_cols_rearr[20]); //mat_a_diag_inv[3] = _mm256_unpacklo_ps(mat_a_cols_rearr[27], mat_a_cols_rearr[35]); //mat_a_diag_inv[1] = _mm256_permute_ps(mat_a_diag_inv[1], 0x55); //mat_a_diag_inv[3] = _mm256_permute_ps(mat_a_diag_inv[3], 0x55); //mat_a_diag_inv[0] = _mm256_blend_ps(mat_a_diag_inv[0], mat_a_diag_inv[1], 0xCC); //mat_a_diag_inv[1] = _mm256_blend_ps(mat_a_diag_inv[2], mat_a_diag_inv[3], 0xCC); //mat_a_diag_inv[0] = _mm256_permute2f128_ps(mat_a_diag_inv[0], mat_a_diag_inv[1], 0x20); //reciprocal of diagnol elements //reciprocal_diags = _mm256_div_ps(reciprocal_diags, mat_a_diag_inv[0]); //Start loop for cols of B to be processed in size of blk_width for (j = 0; j < numCols_b; j += 8) { ptr_b_dup = ptr_b; /*Shuffle to rearrange/transpose 16x8 block of B into contiguous row-wise registers*/ ////unpacklow//// mat_b_rearr[0] = _mm256_unpacklo_ps(mat_b_col[0], mat_b_col[1]); mat_b_rearr[1] = _mm256_unpacklo_ps(mat_b_col[2], mat_b_col[3]); mat_b_rearr[2] = _mm256_unpacklo_ps(mat_b_col[4], mat_b_col[5]); mat_b_rearr[3] = _mm256_unpacklo_ps(mat_b_col[6], mat_b_col[7]); //Rearrange low elements #if REARRANGE_SHFL == 1 mat_b_rearr[4] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0x44); mat_b_rearr[5] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0xEE); mat_b_rearr[6] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0x44); mat_b_rearr[7] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0xEE); #else mat_b_rearr[6] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0x4E); mat_b_rearr[7] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0x4E); mat_b_rearr[4] = _mm256_blend_ps(mat_b_rearr[0], mat_b_rearr[6], 0xCC); mat_b_rearr[5] = _mm256_blend_ps(mat_b_rearr[1], mat_b_rearr[6], 0x33); mat_b_rearr[6] = _mm256_blend_ps(mat_b_rearr[2], mat_b_rearr[7], 0xCC); mat_b_rearr[7] = _mm256_blend_ps(mat_b_rearr[3], mat_b_rearr[7], 0x33); #endif //Merge rearranged low elements into complete rows mat_b_rearr[0] = _mm256_permute2f128_ps(mat_b_rearr[4], mat_b_rearr[6], 0x20); mat_b_rearr[4] = _mm256_permute2f128_ps(mat_b_rearr[4], mat_b_rearr[6], 0x31); mat_b_rearr[1] = _mm256_permute2f128_ps(mat_b_rearr[5], mat_b_rearr[7], 0x20); mat_b_rearr[5] = _mm256_permute2f128_ps(mat_b_rearr[5], mat_b_rearr[7], 0x31); ////unpackhigh//// mat_b_col[0] = _mm256_unpackhi_ps(mat_b_col[0], mat_b_col[1]); mat_b_col[1] = _mm256_unpackhi_ps(mat_b_col[2], mat_b_col[3]); mat_b_col[2] = _mm256_unpackhi_ps(mat_b_col[4], mat_b_col[5]); mat_b_col[3] = _mm256_unpackhi_ps(mat_b_col[6], mat_b_col[7]); //Rearrange high elements #if REARRANGE_SHFL == 1 mat_b_col[4] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0x44); mat_b_col[5] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0xEE); mat_b_col[6] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0x44); mat_b_col[7] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0xEE); #else mat_b_col[6] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0x4E); mat_b_col[7] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0x4E); mat_b_col[4] = _mm256_blend_ps(mat_b_col[0], mat_b_col[6], 0xCC); mat_b_col[5] = _mm256_blend_ps(mat_b_col[1], mat_b_col[6], 0x33); mat_b_col[6] = _mm256_blend_ps(mat_b_col[2], mat_b_col[7], 0xCC); mat_b_col[7] = _mm256_blend_ps(mat_b_col[3], mat_b_col[7], 0x33); #endif //extract diag a00 from a //mat_a_diag_inv[0] = _mm256_permute_ps(reciprocal_diags, 0x00); //mat_a_diag_inv[0] = _mm256_permute2f128_ps(mat_a_diag_inv[0], mat_a_diag_inv[0], 0x00); //(Row0): Perform mul operation of reciprocal of L(0,0) element with 1st row elements of B //mat_b_rearr[0] = _mm256_mul_ps(mat_b_rearr[0], mat_a_diag_inv[0]); //Merge rearranged high elements into complete rows mat_b_rearr[2] = _mm256_permute2f128_ps(mat_b_col[4], mat_b_col[6], 0x20); mat_b_rearr[6] = _mm256_permute2f128_ps(mat_b_col[4], mat_b_col[6], 0x31); mat_b_rearr[3] = _mm256_permute2f128_ps(mat_b_col[5], mat_b_col[7], 0x20); mat_b_rearr[7] = _mm256_permute2f128_ps(mat_b_col[5], mat_b_col[7], 0x31); //extract diag a11 from a //mat_a_diag_inv[1] = _mm256_permute_ps(reciprocal_diags, 0x55); //mat_a_diag_inv[1] = _mm256_permute2f128_ps(mat_a_diag_inv[1], mat_a_diag_inv[1], 0x00); //(Row1): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_cols_rearr[1], mat_b_rearr[0], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_cols_rearr[3], mat_b_rearr[0], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_cols_rearr[6], mat_b_rearr[0], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_cols_rearr[10], mat_b_rearr[0], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_cols_rearr[15], mat_b_rearr[0], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_cols_rearr[21], mat_b_rearr[0], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_cols_rearr[28], mat_b_rearr[0], mat_b_rearr[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(1,1) element with 2nd row elements of B //mat_b_rearr[1] = _mm256_mul_ps(mat_b_rearr[1], mat_a_diag_inv[1]); //extract diag a22 from a //mat_a_diag_inv[2] = _mm256_permute_ps(reciprocal_diags, 0xAA); //mat_a_diag_inv[2] = _mm256_permute2f128_ps(mat_a_diag_inv[2], mat_a_diag_inv[2], 0x00); //(Row2): FMA operations of b2 with elements of indices from (2, 0) uptill (7, 0) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_cols_rearr[4], mat_b_rearr[1], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_cols_rearr[7], mat_b_rearr[1], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_cols_rearr[11], mat_b_rearr[1], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_cols_rearr[16], mat_b_rearr[1], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_cols_rearr[22], mat_b_rearr[1], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_cols_rearr[29], mat_b_rearr[1], mat_b_rearr[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(2, 2) element with 3rd row elements of B //mat_b_rearr[2] = _mm256_mul_ps(mat_b_rearr[2], mat_a_diag_inv[2]); //extract diag a33 from a //mat_a_diag_inv[3] = _mm256_permute_ps(reciprocal_diags, 0xFF); //mat_a_diag_inv[3] = _mm256_permute2f128_ps(mat_a_diag_inv[3], mat_a_diag_inv[3], 0x00); //(Row3): FMA operations of b3 with elements of indices from (3, 0) uptill (7, 0) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_cols_rearr[8], mat_b_rearr[2], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_cols_rearr[12], mat_b_rearr[2], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_cols_rearr[17], mat_b_rearr[2], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_cols_rearr[23], mat_b_rearr[2], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_cols_rearr[30], mat_b_rearr[2], mat_b_rearr[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(3, 3) element with 4rth row elements of B //mat_b_rearr[3] = _mm256_mul_ps(mat_b_rearr[3], mat_a_diag_inv[3]); //extract diag a44 from a //mat_a_diag_inv[4] = _mm256_permute_ps(reciprocal_diags, 0x00); //mat_a_diag_inv[4] = _mm256_permute2f128_ps(mat_a_diag_inv[4], mat_a_diag_inv[4], 0x11); //(Row4): FMA operations of b4 with elements of indices from (4, 0) uptill (7, 0) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_cols_rearr[13], mat_b_rearr[3], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_cols_rearr[18], mat_b_rearr[3], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_cols_rearr[24], mat_b_rearr[3], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_cols_rearr[31], mat_b_rearr[3], mat_b_rearr[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(4, 4) element with 4rth row elements of B //mat_b_rearr[4] = _mm256_mul_ps(mat_b_rearr[4], mat_a_diag_inv[4]); //extract diag a55 from a //mat_a_diag_inv[5] = _mm256_permute_ps(reciprocal_diags, 0x55); //mat_a_diag_inv[5] = _mm256_permute2f128_ps(mat_a_diag_inv[5], mat_a_diag_inv[5], 0x11); //(Row5): FMA operations of b5 with elements of indices from (5, 0) uptill (7, 0) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_cols_rearr[19], mat_b_rearr[4], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_cols_rearr[25], mat_b_rearr[4], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_cols_rearr[32], mat_b_rearr[4], mat_b_rearr[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(5, 5) element with 5th row elements of B //mat_b_rearr[5] = _mm256_mul_ps(mat_b_rearr[5], mat_a_diag_inv[5]); //extract diag a66 from a //mat_a_diag_inv[6] = _mm256_permute_ps(reciprocal_diags, 0xAA); //mat_a_diag_inv[6] = _mm256_permute2f128_ps(mat_a_diag_inv[6], mat_a_diag_inv[6], 0x11); //(Row6): FMA operations of b6 with elements of indices from (6, 0) uptill (7, 0) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_cols_rearr[26], mat_b_rearr[5], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_cols_rearr[33], mat_b_rearr[5], mat_b_rearr[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(6, 6) element with 6th row elements of B //mat_b_rearr[6] = _mm256_mul_ps(mat_b_rearr[6], mat_a_diag_inv[6]); //extract diag a77 from a //mat_a_diag_inv[7] = _mm256_permute_ps(reciprocal_diags, 0xFF); //mat_a_diag_inv[7] = _mm256_permute2f128_ps(mat_a_diag_inv[7], mat_a_diag_inv[7], 0x11); //(Row7): FMA operations of b7 with elements of index (7, 0) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_cols_rearr[34], mat_b_rearr[6], mat_b_rearr[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(7, 7) element with 7th row elements of B //mat_b_rearr[7] = _mm256_mul_ps(mat_b_rearr[7], mat_a_diag_inv[7]); //--> Transpose and store results of columns of B block <--// ////unpacklow//// mat_a_cols[0] = _mm256_unpacklo_ps(mat_b_rearr[0], mat_b_rearr[1]); mat_a_cols[1] = _mm256_unpacklo_ps(mat_b_rearr[2], mat_b_rearr[3]); mat_a_cols[2] = _mm256_unpacklo_ps(mat_b_rearr[4], mat_b_rearr[5]); mat_a_cols[3] = _mm256_unpacklo_ps(mat_b_rearr[6], mat_b_rearr[7]); //Rearrange low elements #if REARRANGE_SHFL == 1 mat_a_cols[4] = _mm256_shuffle_ps(mat_a_cols[0], mat_a_cols[1], 0x44); mat_a_cols[5] = _mm256_shuffle_ps(mat_a_cols[0], mat_a_cols[1], 0xEE); mat_a_cols[6] = _mm256_shuffle_ps(mat_a_cols[2], mat_a_cols[3], 0x44); mat_a_cols[7] = _mm256_shuffle_ps(mat_a_cols[2], mat_a_cols[3], 0xEE); #else mat_a_cols[6] = _mm256_shuffle_ps(mat_a_cols[0], mat_a_cols[1], 0x4E); mat_a_cols[7] = _mm256_shuffle_ps(mat_a_cols[2], mat_a_cols[3], 0x4E); mat_a_cols[4] = _mm256_blend_ps(mat_a_cols[0], mat_a_cols[6], 0xCC); mat_a_cols[5] = _mm256_blend_ps(mat_a_cols[1], mat_a_cols[6], 0x33); mat_a_cols[6] = _mm256_blend_ps(mat_a_cols[2], mat_a_cols[7], 0xCC); mat_a_cols[7] = _mm256_blend_ps(mat_a_cols[3], mat_a_cols[7], 0x33); #endif //Merge rearranged low elements into complete rows mat_a_cols[0] = _mm256_permute2f128_ps(mat_a_cols[4], mat_a_cols[6], 0x20); mat_a_cols[4] = _mm256_permute2f128_ps(mat_a_cols[4], mat_a_cols[6], 0x31); mat_a_cols[1] = _mm256_permute2f128_ps(mat_a_cols[5], mat_a_cols[7], 0x20); mat_a_cols[5] = _mm256_permute2f128_ps(mat_a_cols[5], mat_a_cols[7], 0x31); ////unpackhigh//// mat_b_rearr[0] = _mm256_unpackhi_ps(mat_b_rearr[0], mat_b_rearr[1]); mat_b_rearr[1] = _mm256_unpackhi_ps(mat_b_rearr[2], mat_b_rearr[3]); mat_b_rearr[2] = _mm256_unpackhi_ps(mat_b_rearr[4], mat_b_rearr[5]); mat_b_rearr[3] = _mm256_unpackhi_ps(mat_b_rearr[6], mat_b_rearr[7]); //Rearrange high elements #if REARRANGE_SHFL == 1 mat_b_rearr[4] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0x44); mat_b_rearr[5] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0xEE); mat_b_rearr[6] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0x44); mat_b_rearr[7] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0xEE); #else mat_b_rearr[6] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0x4E); mat_b_rearr[7] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0x4E); mat_b_rearr[4] = _mm256_blend_ps(mat_b_rearr[0], mat_b_rearr[6], 0xCC); mat_b_rearr[5] = _mm256_blend_ps(mat_b_rearr[1], mat_b_rearr[6], 0x33); mat_b_rearr[6] = _mm256_blend_ps(mat_b_rearr[2], mat_b_rearr[7], 0xCC); mat_b_rearr[7] = _mm256_blend_ps(mat_b_rearr[3], mat_b_rearr[7], 0x33); #endif //Merge rearranged high elements into complete rows mat_a_cols[2] = _mm256_permute2f128_ps(mat_b_rearr[4], mat_b_rearr[6], 0x20); mat_a_cols[6] = _mm256_permute2f128_ps(mat_b_rearr[4], mat_b_rearr[6], 0x31); mat_a_cols[3] = _mm256_permute2f128_ps(mat_b_rearr[5], mat_b_rearr[7], 0x20); mat_a_cols[7] = _mm256_permute2f128_ps(mat_b_rearr[5], mat_b_rearr[7], 0x31); //Read next set of B columns ptr_b += (cs_b + cs_b_offset[5]); mat_b_col[0] = _mm256_loadu_ps((float const *)ptr_b); mat_b_col[1] = _mm256_loadu_ps((float const *)(ptr_b + (cs_b))); mat_b_col[2] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[0])); mat_b_col[3] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[1])); mat_b_col[4] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[2])); mat_b_col[5] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[3])); mat_b_col[6] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[4])); mat_b_col[7] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[5])); //Store the computed B columns _mm256_storeu_ps((float *)ptr_b_dup, mat_a_cols[0]); _mm256_storeu_ps((float *)(ptr_b_dup + (cs_b)), mat_a_cols[1]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[0]), mat_a_cols[2]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[1]), mat_a_cols[3]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[2]), mat_a_cols[4]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[3]), mat_a_cols[5]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[4]), mat_a_cols[6]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[5]), mat_a_cols[7]); //end loop of cols } //Last block trsm processing ptr_b_dup = ptr_b; /*Shuffle to rearrange/transpose 16x8 block of B into contiguous row-wise registers*/ ////unpacklow//// mat_b_rearr[0] = _mm256_unpacklo_ps(mat_b_col[0], mat_b_col[1]); mat_b_rearr[1] = _mm256_unpacklo_ps(mat_b_col[2], mat_b_col[3]); mat_b_rearr[2] = _mm256_unpacklo_ps(mat_b_col[4], mat_b_col[5]); mat_b_rearr[3] = _mm256_unpacklo_ps(mat_b_col[6], mat_b_col[7]); //Rearrange low elements #if REARRANGE_SHFL == 1 mat_b_rearr[4] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0x44); mat_b_rearr[5] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0xEE); mat_b_rearr[6] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0x44); mat_b_rearr[7] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0xEE); #else mat_b_rearr[6] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0x4E); mat_b_rearr[7] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0x4E); mat_b_rearr[4] = _mm256_blend_ps(mat_b_rearr[0], mat_b_rearr[6], 0xCC); mat_b_rearr[5] = _mm256_blend_ps(mat_b_rearr[1], mat_b_rearr[6], 0x33); mat_b_rearr[6] = _mm256_blend_ps(mat_b_rearr[2], mat_b_rearr[7], 0xCC); mat_b_rearr[7] = _mm256_blend_ps(mat_b_rearr[3], mat_b_rearr[7], 0x33); #endif //Merge rearranged low elements into complete rows mat_b_rearr[0] = _mm256_permute2f128_ps(mat_b_rearr[4], mat_b_rearr[6], 0x20); mat_b_rearr[4] = _mm256_permute2f128_ps(mat_b_rearr[4], mat_b_rearr[6], 0x31); mat_b_rearr[1] = _mm256_permute2f128_ps(mat_b_rearr[5], mat_b_rearr[7], 0x20); mat_b_rearr[5] = _mm256_permute2f128_ps(mat_b_rearr[5], mat_b_rearr[7], 0x31); ////unpackhigh//// mat_b_col[0] = _mm256_unpackhi_ps(mat_b_col[0], mat_b_col[1]); mat_b_col[1] = _mm256_unpackhi_ps(mat_b_col[2], mat_b_col[3]); mat_b_col[2] = _mm256_unpackhi_ps(mat_b_col[4], mat_b_col[5]); mat_b_col[3] = _mm256_unpackhi_ps(mat_b_col[6], mat_b_col[7]); //Rearrange high elements #if REARRANGE_SHFL == 1 mat_b_col[4] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0x44); mat_b_col[5] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0xEE); mat_b_col[6] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0x44); mat_b_col[7] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0xEE); #else mat_b_col[6] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0x4E); mat_b_col[7] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0x4E); mat_b_col[4] = _mm256_blend_ps(mat_b_col[0], mat_b_col[6], 0xCC); mat_b_col[5] = _mm256_blend_ps(mat_b_col[1], mat_b_col[6], 0x33); mat_b_col[6] = _mm256_blend_ps(mat_b_col[2], mat_b_col[7], 0xCC); mat_b_col[7] = _mm256_blend_ps(mat_b_col[3], mat_b_col[7], 0x33); #endif //extract diag a00 from a //mat_a_diag_inv[0] = _mm256_permute_ps(reciprocal_diags, 0x00); //mat_a_diag_inv[0] = _mm256_permute2f128_ps(mat_a_diag_inv[0], mat_a_diag_inv[0], 0x00); //(Row0): Perform mul operation of reciprocal of L(0,0) element with 1st row elements of B //mat_b_rearr[0] = _mm256_mul_ps(mat_b_rearr[0], mat_a_diag_inv[0]); //Merge rearranged high elements into complete rows mat_b_rearr[2] = _mm256_permute2f128_ps(mat_b_col[4], mat_b_col[6], 0x20); mat_b_rearr[6] = _mm256_permute2f128_ps(mat_b_col[4], mat_b_col[6], 0x31); mat_b_rearr[3] = _mm256_permute2f128_ps(mat_b_col[5], mat_b_col[7], 0x20); mat_b_rearr[7] = _mm256_permute2f128_ps(mat_b_col[5], mat_b_col[7], 0x31); //extract diag a11 from a //mat_a_diag_inv[1] = _mm256_permute_ps(reciprocal_diags, 0x55); //mat_a_diag_inv[1] = _mm256_permute2f128_ps(mat_a_diag_inv[1], mat_a_diag_inv[1], 0x00); //(Row1): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_cols_rearr[1], mat_b_rearr[0], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_cols_rearr[3], mat_b_rearr[0], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_cols_rearr[6], mat_b_rearr[0], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_cols_rearr[10], mat_b_rearr[0], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_cols_rearr[15], mat_b_rearr[0], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_cols_rearr[21], mat_b_rearr[0], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_cols_rearr[28], mat_b_rearr[0], mat_b_rearr[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(1,1) element with 2nd row elements of B //mat_b_rearr[1] = _mm256_mul_ps(mat_b_rearr[1], mat_a_diag_inv[1]); //extract diag a22 from a //mat_a_diag_inv[2] = _mm256_permute_ps(reciprocal_diags, 0xAA); //mat_a_diag_inv[2] = _mm256_permute2f128_ps(mat_a_diag_inv[2], mat_a_diag_inv[2], 0x00); //(Row2): FMA operations of b2 with elements of indices from (2, 0) uptill (7, 0) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_cols_rearr[4], mat_b_rearr[1], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_cols_rearr[7], mat_b_rearr[1], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_cols_rearr[11], mat_b_rearr[1], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_cols_rearr[16], mat_b_rearr[1], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_cols_rearr[22], mat_b_rearr[1], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_cols_rearr[29], mat_b_rearr[1], mat_b_rearr[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(2, 2) element with 3rd row elements of B //mat_b_rearr[2] = _mm256_mul_ps(mat_b_rearr[2], mat_a_diag_inv[2]); //extract diag a33 from a //mat_a_diag_inv[3] = _mm256_permute_ps(reciprocal_diags, 0xFF); //mat_a_diag_inv[3] = _mm256_permute2f128_ps(mat_a_diag_inv[3], mat_a_diag_inv[3], 0x00); //(Row3): FMA operations of b3 with elements of indices from (3, 0) uptill (7, 0) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_cols_rearr[8], mat_b_rearr[2], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_cols_rearr[12], mat_b_rearr[2], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_cols_rearr[17], mat_b_rearr[2], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_cols_rearr[23], mat_b_rearr[2], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_cols_rearr[30], mat_b_rearr[2], mat_b_rearr[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(3, 3) element with 4rth row elements of B //mat_b_rearr[3] = _mm256_mul_ps(mat_b_rearr[3], mat_a_diag_inv[3]); //extract diag a44 from a //mat_a_diag_inv[4] = _mm256_permute_ps(reciprocal_diags, 0x00); //mat_a_diag_inv[4] = _mm256_permute2f128_ps(mat_a_diag_inv[4], mat_a_diag_inv[4], 0x11); //(Row4): FMA operations of b4 with elements of indices from (4, 0) uptill (7, 0) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_cols_rearr[13], mat_b_rearr[3], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_cols_rearr[18], mat_b_rearr[3], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_cols_rearr[24], mat_b_rearr[3], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_cols_rearr[31], mat_b_rearr[3], mat_b_rearr[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(4, 4) element with 4rth row elements of B //mat_b_rearr[4] = _mm256_mul_ps(mat_b_rearr[4], mat_a_diag_inv[4]); //extract diag a55 from a //mat_a_diag_inv[5] = _mm256_permute_ps(reciprocal_diags, 0x55); //mat_a_diag_inv[5] = _mm256_permute2f128_ps(mat_a_diag_inv[5], mat_a_diag_inv[5], 0x11); //(Row5): FMA operations of b5 with elements of indices from (5, 0) uptill (7, 0) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_cols_rearr[19], mat_b_rearr[4], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_cols_rearr[25], mat_b_rearr[4], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_cols_rearr[32], mat_b_rearr[4], mat_b_rearr[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(5, 5) element with 5th row elements of B //mat_b_rearr[5] = _mm256_mul_ps(mat_b_rearr[5], mat_a_diag_inv[5]); //extract diag a66 from a //mat_a_diag_inv[6] = _mm256_permute_ps(reciprocal_diags, 0xAA); //mat_a_diag_inv[6] = _mm256_permute2f128_ps(mat_a_diag_inv[6], mat_a_diag_inv[6], 0x11); //(Row6): FMA operations of b6 with elements of indices from (6, 0) uptill (7, 0) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_cols_rearr[26], mat_b_rearr[5], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_cols_rearr[33], mat_b_rearr[5], mat_b_rearr[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(6, 6) element with 6th row elements of B //mat_b_rearr[6] = _mm256_mul_ps(mat_b_rearr[6], mat_a_diag_inv[6]); //extract diag a77 from a //mat_a_diag_inv[7] = _mm256_permute_ps(reciprocal_diags, 0xFF); //mat_a_diag_inv[7] = _mm256_permute2f128_ps(mat_a_diag_inv[7], mat_a_diag_inv[7], 0x11); //(Row7): FMA operations of b7 with elements of index (7, 0) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_cols_rearr[34], mat_b_rearr[6], mat_b_rearr[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(7, 7) element with 7th row elements of B //mat_b_rearr[7] = _mm256_mul_ps(mat_b_rearr[7], mat_a_diag_inv[7]); //--> Transpose and store results of columns of B block <--// ////unpacklow//// mat_a_cols[0] = _mm256_unpacklo_ps(mat_b_rearr[0], mat_b_rearr[1]); mat_a_cols[1] = _mm256_unpacklo_ps(mat_b_rearr[2], mat_b_rearr[3]); mat_a_cols[2] = _mm256_unpacklo_ps(mat_b_rearr[4], mat_b_rearr[5]); mat_a_cols[3] = _mm256_unpacklo_ps(mat_b_rearr[6], mat_b_rearr[7]); //Rearrange low elements #if REARRANGE_SHFL == 1 mat_a_cols[4] = _mm256_shuffle_ps(mat_a_cols[0], mat_a_cols[1], 0x44); mat_a_cols[5] = _mm256_shuffle_ps(mat_a_cols[0], mat_a_cols[1], 0xEE); mat_a_cols[6] = _mm256_shuffle_ps(mat_a_cols[2], mat_a_cols[3], 0x44); mat_a_cols[7] = _mm256_shuffle_ps(mat_a_cols[2], mat_a_cols[3], 0xEE); #else mat_a_cols[6] = _mm256_shuffle_ps(mat_a_cols[0], mat_a_cols[1], 0x4E); mat_a_cols[7] = _mm256_shuffle_ps(mat_a_cols[2], mat_a_cols[3], 0x4E); mat_a_cols[4] = _mm256_blend_ps(mat_a_cols[0], mat_a_cols[6], 0xCC); mat_a_cols[5] = _mm256_blend_ps(mat_a_cols[1], mat_a_cols[6], 0x33); mat_a_cols[6] = _mm256_blend_ps(mat_a_cols[2], mat_a_cols[7], 0xCC); mat_a_cols[7] = _mm256_blend_ps(mat_a_cols[3], mat_a_cols[7], 0x33); #endif //Merge rearranged low elements into complete rows mat_a_cols[0] = _mm256_permute2f128_ps(mat_a_cols[4], mat_a_cols[6], 0x20); mat_a_cols[4] = _mm256_permute2f128_ps(mat_a_cols[4], mat_a_cols[6], 0x31); mat_a_cols[1] = _mm256_permute2f128_ps(mat_a_cols[5], mat_a_cols[7], 0x20); mat_a_cols[5] = _mm256_permute2f128_ps(mat_a_cols[5], mat_a_cols[7], 0x31); ////unpackhigh//// mat_b_rearr[0] = _mm256_unpackhi_ps(mat_b_rearr[0], mat_b_rearr[1]); mat_b_rearr[1] = _mm256_unpackhi_ps(mat_b_rearr[2], mat_b_rearr[3]); mat_b_rearr[2] = _mm256_unpackhi_ps(mat_b_rearr[4], mat_b_rearr[5]); mat_b_rearr[3] = _mm256_unpackhi_ps(mat_b_rearr[6], mat_b_rearr[7]); //Rearrange high elements #if REARRANGE_SHFL == 1 mat_b_rearr[4] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0x44); mat_b_rearr[5] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0xEE); mat_b_rearr[6] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0x44); mat_b_rearr[7] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0xEE); #else mat_b_rearr[6] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0x4E); mat_b_rearr[7] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0x4E); mat_b_rearr[4] = _mm256_blend_ps(mat_b_rearr[0], mat_b_rearr[6], 0xCC); mat_b_rearr[5] = _mm256_blend_ps(mat_b_rearr[1], mat_b_rearr[6], 0x33); mat_b_rearr[6] = _mm256_blend_ps(mat_b_rearr[2], mat_b_rearr[7], 0xCC); mat_b_rearr[7] = _mm256_blend_ps(mat_b_rearr[3], mat_b_rearr[7], 0x33); #endif //Merge rearranged high elements into complete rows mat_a_cols[2] = _mm256_permute2f128_ps(mat_b_rearr[4], mat_b_rearr[6], 0x20); mat_a_cols[6] = _mm256_permute2f128_ps(mat_b_rearr[4], mat_b_rearr[6], 0x31); mat_a_cols[3] = _mm256_permute2f128_ps(mat_b_rearr[5], mat_b_rearr[7], 0x20); mat_a_cols[7] = _mm256_permute2f128_ps(mat_b_rearr[5], mat_b_rearr[7], 0x31); //Store the computed B columns _mm256_storeu_ps((float *)ptr_b_dup, mat_a_cols[0]); _mm256_storeu_ps((float *)(ptr_b_dup + (cs_b)), mat_a_cols[1]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[0]), mat_a_cols[2]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[1]), mat_a_cols[3]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[2]), mat_a_cols[4]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[3]), mat_a_cols[5]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[4]), mat_a_cols[6]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[5]), mat_a_cols[7]); //end loop of cols } static void blis_strsm_microkernel(float *ptr_l, float *ptr_b, int numRows_lb, int numCols_b, int rs_l, int rs_b, int cs_l, int cs_b) { float ones = 1.0; int j; int cs_b_offset[6]; //int row2, row4, row6; float *ptr_b_dup; //70 number of ymm(256 bits) registers used __m256 mat_b_col[8]; __m256 mat_b_rearr[8]; __m256 mat_a_cols[8]; __m256 mat_a_cols_rearr[36]; __m256 mat_a_diag_inv[8]; __m256 reciprocal_diags; cs_b_offset[0] = (cs_b << 1); cs_b_offset[1] = cs_b + cs_b_offset[0]; cs_b_offset[2] = (cs_b << 2); cs_b_offset[3] = cs_b + cs_b_offset[2]; cs_b_offset[4] = cs_b_offset[0] + cs_b_offset[2]; cs_b_offset[5] = cs_b + cs_b_offset[4]; //reciprocal_diags = _mm256_loadu_ps((float const *)ones); reciprocal_diags = _mm256_broadcast_ss((float const *)&ones); // ---> considering that the matrix size is multiple of 16 rows and 8 cols <--- // //read first set of 16x8 block of B into registers, where 16 is the blk_height and 8 is the blk_width for B mat_b_col[0] = _mm256_loadu_ps((float const *)ptr_b); //_mm_prefetch((char*)(ptr_l + 0), _MM_HINT_T0); //row2 = (cs_l << 1); //row4 = (cs_l << 2); mat_b_col[1] = _mm256_loadu_ps((float const *)(ptr_b + (cs_b))); //_mm_prefetch((char*)(ptr_l + cs_l), _MM_HINT_T0); mat_b_col[2] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[0])); //_mm_prefetch((char*)(ptr_l + row2), _MM_HINT_T0); mat_b_col[3] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[1])); //_mm_prefetch((char*)(ptr_l + row2 + cs_l), _MM_HINT_T0); //row6 = row2 + row4; mat_b_col[4] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[2])); //_mm_prefetch((char*)(ptr_l + row4), _MM_HINT_T0); mat_b_col[5] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[3])); //_mm_prefetch((char*)(ptr_l + row4 + cs_l), _MM_HINT_T0); mat_b_col[6] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[4])); //_mm_prefetch((char*)(ptr_l + row6), _MM_HINT_T0); mat_b_col[7] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[5])); //_mm_prefetch((char*)(ptr_l + row6 + cs_l), _MM_HINT_T0); //reciprocal_diags = _mm256_loadu_ps((float const *)ones); //read first set of 16x16 block of L, where 16 is the blk_height and 16 is the blk_width for L /*mat_a_cols[0] = _mm256_loadu_ps((float const *)ptr_l); ptr_l += cs_l; mat_a_cols[1] = _mm256_loadu_ps((float const *)ptr_l); ptr_l += cs_l; mat_a_cols[2] = _mm256_loadu_ps((float const *)ptr_l); ptr_l += cs_l; mat_a_cols[3] = _mm256_loadu_ps((float const *)ptr_l); ptr_l += cs_l; mat_a_cols[4] = _mm256_loadu_ps((float const *)ptr_l); ptr_l += cs_l; mat_a_cols[5] = _mm256_loadu_ps((float const *)ptr_l); ptr_l += cs_l; mat_a_cols[6] = _mm256_loadu_ps((float const *)ptr_l); ptr_l += cs_l; mat_a_cols[7] = _mm256_loadu_ps((float const *)ptr_l);*/ //Shuffle to rearrange/transpose 16x16 block of L into contiguous row-wise registers //tmpRegs[0] = _mm256_castps256_ps128(mat_a_cols[0]); //zero latency, no instruction added actually. //mat_a_cols_rearr[0] = _mm256_broadcastss_ps(tmpRegs[0]); //1st col mat_a_cols_rearr[0] = _mm256_broadcast_ss((float const *)(ptr_l+0)); mat_a_cols_rearr[1] = _mm256_broadcast_ss((float const *)(ptr_l+1)); mat_a_cols_rearr[3] = _mm256_broadcast_ss((float const *)(ptr_l+2)); mat_a_cols_rearr[6] = _mm256_broadcast_ss((float const *)(ptr_l+3)); mat_a_cols_rearr[10] = _mm256_broadcast_ss((float const *)(ptr_l+4)); mat_a_cols_rearr[15] = _mm256_broadcast_ss((float const *)(ptr_l+5)); mat_a_cols_rearr[21] = _mm256_broadcast_ss((float const *)(ptr_l+6)); mat_a_cols_rearr[28] = _mm256_broadcast_ss((float const *)(ptr_l+7)); //2nd col ptr_l += cs_l; mat_a_cols_rearr[2] = _mm256_broadcast_ss((float const *)(ptr_l + 1)); mat_a_cols_rearr[4] = _mm256_broadcast_ss((float const *)(ptr_l + 2)); mat_a_cols_rearr[7] = _mm256_broadcast_ss((float const *)(ptr_l + 3)); mat_a_cols_rearr[11] = _mm256_broadcast_ss((float const *)(ptr_l + 4)); mat_a_cols_rearr[16] = _mm256_broadcast_ss((float const *)(ptr_l + 5)); mat_a_cols_rearr[22] = _mm256_broadcast_ss((float const *)(ptr_l + 6)); mat_a_cols_rearr[29] = _mm256_broadcast_ss((float const *)(ptr_l + 7)); //3rd col ptr_l += cs_l; mat_a_cols_rearr[5] = _mm256_broadcast_ss((float const *)(ptr_l + 2)); mat_a_cols_rearr[8] = _mm256_broadcast_ss((float const *)(ptr_l + 3)); mat_a_cols_rearr[12] = _mm256_broadcast_ss((float const *)(ptr_l + 4)); mat_a_cols_rearr[17] = _mm256_broadcast_ss((float const *)(ptr_l + 5)); mat_a_cols_rearr[23] = _mm256_broadcast_ss((float const *)(ptr_l + 6)); mat_a_cols_rearr[30] = _mm256_broadcast_ss((float const *)(ptr_l + 7)); //4rth col ptr_l += cs_l; mat_a_cols_rearr[9] = _mm256_broadcast_ss((float const *)(ptr_l + 3)); mat_a_cols_rearr[13] = _mm256_broadcast_ss((float const *)(ptr_l + 4)); mat_a_cols_rearr[18] = _mm256_broadcast_ss((float const *)(ptr_l + 5)); mat_a_cols_rearr[24] = _mm256_broadcast_ss((float const *)(ptr_l + 6)); mat_a_cols_rearr[31] = _mm256_broadcast_ss((float const *)(ptr_l + 7)); //5th col ptr_l += cs_l; mat_a_cols_rearr[14] = _mm256_broadcast_ss((float const *)(ptr_l + 4)); mat_a_cols_rearr[19] = _mm256_broadcast_ss((float const *)(ptr_l + 5)); mat_a_cols_rearr[25] = _mm256_broadcast_ss((float const *)(ptr_l + 6)); mat_a_cols_rearr[32] = _mm256_broadcast_ss((float const *)(ptr_l + 7)); //6th col ptr_l += cs_l; mat_a_cols_rearr[20] = _mm256_broadcast_ss((float const *)(ptr_l + 5)); mat_a_cols_rearr[26] = _mm256_broadcast_ss((float const *)(ptr_l + 6)); mat_a_cols_rearr[33] = _mm256_broadcast_ss((float const *)(ptr_l + 7)); //7th col ptr_l += cs_l; mat_a_cols_rearr[27] = _mm256_broadcast_ss((float const *)(ptr_l + 6)); mat_a_cols_rearr[34] = _mm256_broadcast_ss((float const *)(ptr_l + 7)); //7th col ptr_l += cs_l; mat_a_cols_rearr[35] = _mm256_broadcast_ss((float const *)(ptr_l + 7)); numCols_b -= 8; // blk_width = 8 //compute reciprocals of L(i,i) and broadcast in registers mat_a_diag_inv[0] = _mm256_unpacklo_ps(mat_a_cols_rearr[0], mat_a_cols_rearr[2]); mat_a_diag_inv[1] = _mm256_unpacklo_ps(mat_a_cols_rearr[5], mat_a_cols_rearr[9]); mat_a_diag_inv[2] = _mm256_unpacklo_ps(mat_a_cols_rearr[14], mat_a_cols_rearr[20]); mat_a_diag_inv[3] = _mm256_unpacklo_ps(mat_a_cols_rearr[27], mat_a_cols_rearr[35]); //mat_a_diag_inv[1] = _mm256_permute_ps(mat_a_diag_inv[1], 0x55); //mat_a_diag_inv[3] = _mm256_permute_ps(mat_a_diag_inv[3], 0x55); mat_a_diag_inv[0] = _mm256_blend_ps(mat_a_diag_inv[0], mat_a_diag_inv[1], 0xCC); mat_a_diag_inv[1] = _mm256_blend_ps(mat_a_diag_inv[2], mat_a_diag_inv[3], 0xCC); mat_a_diag_inv[0] = _mm256_permute2f128_ps(mat_a_diag_inv[0], mat_a_diag_inv[1], 0x20); //reciprocal of diagnol elements reciprocal_diags = _mm256_div_ps(reciprocal_diags, mat_a_diag_inv[0]); //Start loop for cols of B to be processed in size of blk_width for (j = 0; j < numCols_b; j += 8) { ptr_b_dup = ptr_b; /*Shuffle to rearrange/transpose 16x8 block of B into contiguous row-wise registers*/ ////unpacklow//// mat_b_rearr[0] = _mm256_unpacklo_ps(mat_b_col[0], mat_b_col[1]); mat_b_rearr[1] = _mm256_unpacklo_ps(mat_b_col[2], mat_b_col[3]); mat_b_rearr[2] = _mm256_unpacklo_ps(mat_b_col[4], mat_b_col[5]); mat_b_rearr[3] = _mm256_unpacklo_ps(mat_b_col[6], mat_b_col[7]); //Rearrange low elements #if REARRANGE_SHFL == 1 mat_b_rearr[4] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0x44); mat_b_rearr[5] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0xEE); mat_b_rearr[6] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0x44); mat_b_rearr[7] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0xEE); #else mat_b_rearr[6] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0x4E); mat_b_rearr[7] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0x4E); mat_b_rearr[4] = _mm256_blend_ps(mat_b_rearr[0], mat_b_rearr[6], 0xCC); mat_b_rearr[5] = _mm256_blend_ps(mat_b_rearr[1], mat_b_rearr[6], 0x33); mat_b_rearr[6] = _mm256_blend_ps(mat_b_rearr[2], mat_b_rearr[7], 0xCC); mat_b_rearr[7] = _mm256_blend_ps(mat_b_rearr[3], mat_b_rearr[7], 0x33); #endif //Merge rearranged low elements into complete rows mat_b_rearr[0] = _mm256_permute2f128_ps(mat_b_rearr[4], mat_b_rearr[6], 0x20); mat_b_rearr[4] = _mm256_permute2f128_ps(mat_b_rearr[4], mat_b_rearr[6], 0x31); mat_b_rearr[1] = _mm256_permute2f128_ps(mat_b_rearr[5], mat_b_rearr[7], 0x20); mat_b_rearr[5] = _mm256_permute2f128_ps(mat_b_rearr[5], mat_b_rearr[7], 0x31); ////unpackhigh//// mat_b_col[0] = _mm256_unpackhi_ps(mat_b_col[0], mat_b_col[1]); mat_b_col[1] = _mm256_unpackhi_ps(mat_b_col[2], mat_b_col[3]); mat_b_col[2] = _mm256_unpackhi_ps(mat_b_col[4], mat_b_col[5]); mat_b_col[3] = _mm256_unpackhi_ps(mat_b_col[6], mat_b_col[7]); //Rearrange high elements #if REARRANGE_SHFL == 1 mat_b_col[4] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0x44); mat_b_col[5] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0xEE); mat_b_col[6] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0x44); mat_b_col[7] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0xEE); #else mat_b_col[6] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0x4E); mat_b_col[7] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0x4E); mat_b_col[4] = _mm256_blend_ps(mat_b_col[0], mat_b_col[6], 0xCC); mat_b_col[5] = _mm256_blend_ps(mat_b_col[1], mat_b_col[6], 0x33); mat_b_col[6] = _mm256_blend_ps(mat_b_col[2], mat_b_col[7], 0xCC); mat_b_col[7] = _mm256_blend_ps(mat_b_col[3], mat_b_col[7], 0x33); #endif //extract diag a00 from a mat_a_diag_inv[0] = _mm256_permute_ps(reciprocal_diags, 0x00); mat_a_diag_inv[0] = _mm256_permute2f128_ps(mat_a_diag_inv[0], mat_a_diag_inv[0], 0x00); //(Row0): Perform mul operation of reciprocal of L(0,0) element with 1st row elements of B mat_b_rearr[0] = _mm256_mul_ps(mat_b_rearr[0], mat_a_diag_inv[0]); //Merge rearranged high elements into complete rows mat_b_rearr[2] = _mm256_permute2f128_ps(mat_b_col[4], mat_b_col[6], 0x20); mat_b_rearr[6] = _mm256_permute2f128_ps(mat_b_col[4], mat_b_col[6], 0x31); mat_b_rearr[3] = _mm256_permute2f128_ps(mat_b_col[5], mat_b_col[7], 0x20); mat_b_rearr[7] = _mm256_permute2f128_ps(mat_b_col[5], mat_b_col[7], 0x31); //extract diag a11 from a mat_a_diag_inv[1] = _mm256_permute_ps(reciprocal_diags, 0x55); mat_a_diag_inv[1] = _mm256_permute2f128_ps(mat_a_diag_inv[1], mat_a_diag_inv[1], 0x00); //(Row1): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_cols_rearr[1], mat_b_rearr[0], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_cols_rearr[3], mat_b_rearr[0], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_cols_rearr[6], mat_b_rearr[0], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_cols_rearr[10], mat_b_rearr[0], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_cols_rearr[15], mat_b_rearr[0], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_cols_rearr[21], mat_b_rearr[0], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_cols_rearr[28], mat_b_rearr[0], mat_b_rearr[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(1,1) element with 2nd row elements of B mat_b_rearr[1] = _mm256_mul_ps(mat_b_rearr[1], mat_a_diag_inv[1]); //extract diag a22 from a mat_a_diag_inv[2] = _mm256_permute_ps(reciprocal_diags, 0xAA); mat_a_diag_inv[2] = _mm256_permute2f128_ps(mat_a_diag_inv[2], mat_a_diag_inv[2], 0x00); //(Row2): FMA operations of b2 with elements of indices from (2, 0) uptill (7, 0) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_cols_rearr[4], mat_b_rearr[1], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_cols_rearr[7], mat_b_rearr[1], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_cols_rearr[11], mat_b_rearr[1], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_cols_rearr[16], mat_b_rearr[1], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_cols_rearr[22], mat_b_rearr[1], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_cols_rearr[29], mat_b_rearr[1], mat_b_rearr[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(2, 2) element with 3rd row elements of B mat_b_rearr[2] = _mm256_mul_ps(mat_b_rearr[2], mat_a_diag_inv[2]); //extract diag a33 from a mat_a_diag_inv[3] = _mm256_permute_ps(reciprocal_diags, 0xFF); mat_a_diag_inv[3] = _mm256_permute2f128_ps(mat_a_diag_inv[3], mat_a_diag_inv[3], 0x00); //(Row3): FMA operations of b3 with elements of indices from (3, 0) uptill (7, 0) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_cols_rearr[8], mat_b_rearr[2], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_cols_rearr[12], mat_b_rearr[2], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_cols_rearr[17], mat_b_rearr[2], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_cols_rearr[23], mat_b_rearr[2], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_cols_rearr[30], mat_b_rearr[2], mat_b_rearr[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(3, 3) element with 4rth row elements of B mat_b_rearr[3] = _mm256_mul_ps(mat_b_rearr[3], mat_a_diag_inv[3]); //extract diag a44 from a mat_a_diag_inv[4] = _mm256_permute_ps(reciprocal_diags, 0x00); mat_a_diag_inv[4] = _mm256_permute2f128_ps(mat_a_diag_inv[4], mat_a_diag_inv[4], 0x11); //(Row4): FMA operations of b4 with elements of indices from (4, 0) uptill (7, 0) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_cols_rearr[13], mat_b_rearr[3], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_cols_rearr[18], mat_b_rearr[3], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_cols_rearr[24], mat_b_rearr[3], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_cols_rearr[31], mat_b_rearr[3], mat_b_rearr[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(4, 4) element with 4rth row elements of B mat_b_rearr[4] = _mm256_mul_ps(mat_b_rearr[4], mat_a_diag_inv[4]); //extract diag a55 from a mat_a_diag_inv[5] = _mm256_permute_ps(reciprocal_diags, 0x55); mat_a_diag_inv[5] = _mm256_permute2f128_ps(mat_a_diag_inv[5], mat_a_diag_inv[5], 0x11); //(Row5): FMA operations of b5 with elements of indices from (5, 0) uptill (7, 0) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_cols_rearr[19], mat_b_rearr[4], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_cols_rearr[25], mat_b_rearr[4], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_cols_rearr[32], mat_b_rearr[4], mat_b_rearr[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(5, 5) element with 5th row elements of B mat_b_rearr[5] = _mm256_mul_ps(mat_b_rearr[5], mat_a_diag_inv[5]); //extract diag a66 from a mat_a_diag_inv[6] = _mm256_permute_ps(reciprocal_diags, 0xAA); mat_a_diag_inv[6] = _mm256_permute2f128_ps(mat_a_diag_inv[6], mat_a_diag_inv[6], 0x11); //(Row6): FMA operations of b6 with elements of indices from (6, 0) uptill (7, 0) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_cols_rearr[26], mat_b_rearr[5], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_cols_rearr[33], mat_b_rearr[5], mat_b_rearr[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(6, 6) element with 6th row elements of B mat_b_rearr[6] = _mm256_mul_ps(mat_b_rearr[6], mat_a_diag_inv[6]); //extract diag a77 from a mat_a_diag_inv[7] = _mm256_permute_ps(reciprocal_diags, 0xFF); mat_a_diag_inv[7] = _mm256_permute2f128_ps(mat_a_diag_inv[7], mat_a_diag_inv[7], 0x11); //(Row7): FMA operations of b7 with elements of index (7, 0) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_cols_rearr[34], mat_b_rearr[6], mat_b_rearr[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(7, 7) element with 7th row elements of B mat_b_rearr[7] = _mm256_mul_ps(mat_b_rearr[7], mat_a_diag_inv[7]); //--> Transpose and store results of columns of B block <--// ////unpacklow//// mat_a_cols[0] = _mm256_unpacklo_ps(mat_b_rearr[0], mat_b_rearr[1]); mat_a_cols[1] = _mm256_unpacklo_ps(mat_b_rearr[2], mat_b_rearr[3]); mat_a_cols[2] = _mm256_unpacklo_ps(mat_b_rearr[4], mat_b_rearr[5]); mat_a_cols[3] = _mm256_unpacklo_ps(mat_b_rearr[6], mat_b_rearr[7]); //Rearrange low elements #if REARRANGE_SHFL == 1 mat_a_cols[4] = _mm256_shuffle_ps(mat_a_cols[0], mat_a_cols[1], 0x44); mat_a_cols[5] = _mm256_shuffle_ps(mat_a_cols[0], mat_a_cols[1], 0xEE); mat_a_cols[6] = _mm256_shuffle_ps(mat_a_cols[2], mat_a_cols[3], 0x44); mat_a_cols[7] = _mm256_shuffle_ps(mat_a_cols[2], mat_a_cols[3], 0xEE); #else mat_a_cols[6] = _mm256_shuffle_ps(mat_a_cols[0], mat_a_cols[1], 0x4E); mat_a_cols[7] = _mm256_shuffle_ps(mat_a_cols[2], mat_a_cols[3], 0x4E); mat_a_cols[4] = _mm256_blend_ps(mat_a_cols[0], mat_a_cols[6], 0xCC); mat_a_cols[5] = _mm256_blend_ps(mat_a_cols[1], mat_a_cols[6], 0x33); mat_a_cols[6] = _mm256_blend_ps(mat_a_cols[2], mat_a_cols[7], 0xCC); mat_a_cols[7] = _mm256_blend_ps(mat_a_cols[3], mat_a_cols[7], 0x33); #endif //Merge rearranged low elements into complete rows mat_a_cols[0] = _mm256_permute2f128_ps(mat_a_cols[4], mat_a_cols[6], 0x20); mat_a_cols[4] = _mm256_permute2f128_ps(mat_a_cols[4], mat_a_cols[6], 0x31); mat_a_cols[1] = _mm256_permute2f128_ps(mat_a_cols[5], mat_a_cols[7], 0x20); mat_a_cols[5] = _mm256_permute2f128_ps(mat_a_cols[5], mat_a_cols[7], 0x31); ////unpackhigh//// mat_b_rearr[0] = _mm256_unpackhi_ps(mat_b_rearr[0], mat_b_rearr[1]); mat_b_rearr[1] = _mm256_unpackhi_ps(mat_b_rearr[2], mat_b_rearr[3]); mat_b_rearr[2] = _mm256_unpackhi_ps(mat_b_rearr[4], mat_b_rearr[5]); mat_b_rearr[3] = _mm256_unpackhi_ps(mat_b_rearr[6], mat_b_rearr[7]); //Rearrange high elements #if REARRANGE_SHFL == 1 mat_b_rearr[4] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0x44); mat_b_rearr[5] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0xEE); mat_b_rearr[6] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0x44); mat_b_rearr[7] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0xEE); #else mat_b_rearr[6] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0x4E); mat_b_rearr[7] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0x4E); mat_b_rearr[4] = _mm256_blend_ps(mat_b_rearr[0], mat_b_rearr[6], 0xCC); mat_b_rearr[5] = _mm256_blend_ps(mat_b_rearr[1], mat_b_rearr[6], 0x33); mat_b_rearr[6] = _mm256_blend_ps(mat_b_rearr[2], mat_b_rearr[7], 0xCC); mat_b_rearr[7] = _mm256_blend_ps(mat_b_rearr[3], mat_b_rearr[7], 0x33); #endif //Merge rearranged high elements into complete rows mat_a_cols[2] = _mm256_permute2f128_ps(mat_b_rearr[4], mat_b_rearr[6], 0x20); mat_a_cols[6] = _mm256_permute2f128_ps(mat_b_rearr[4], mat_b_rearr[6], 0x31); mat_a_cols[3] = _mm256_permute2f128_ps(mat_b_rearr[5], mat_b_rearr[7], 0x20); mat_a_cols[7] = _mm256_permute2f128_ps(mat_b_rearr[5], mat_b_rearr[7], 0x31); //Read next set of B columns ptr_b += (cs_b + cs_b_offset[5]); mat_b_col[0] = _mm256_loadu_ps((float const *)ptr_b); mat_b_col[1] = _mm256_loadu_ps((float const *)(ptr_b + (cs_b))); mat_b_col[2] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[0])); mat_b_col[3] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[1])); mat_b_col[4] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[2])); mat_b_col[5] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[3])); mat_b_col[6] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[4])); mat_b_col[7] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[5])); //Store the computed B columns _mm256_storeu_ps((float *)ptr_b_dup, mat_a_cols[0]); _mm256_storeu_ps((float *)(ptr_b_dup + (cs_b)), mat_a_cols[1]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[0]), mat_a_cols[2]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[1]), mat_a_cols[3]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[2]), mat_a_cols[4]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[3]), mat_a_cols[5]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[4]), mat_a_cols[6]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[5]), mat_a_cols[7]); //end loop of cols } //Last block trsm processing ptr_b_dup = ptr_b; /*Shuffle to rearrange/transpose 16x8 block of B into contiguous row-wise registers*/ ////unpacklow//// mat_b_rearr[0] = _mm256_unpacklo_ps(mat_b_col[0], mat_b_col[1]); mat_b_rearr[1] = _mm256_unpacklo_ps(mat_b_col[2], mat_b_col[3]); mat_b_rearr[2] = _mm256_unpacklo_ps(mat_b_col[4], mat_b_col[5]); mat_b_rearr[3] = _mm256_unpacklo_ps(mat_b_col[6], mat_b_col[7]); //Rearrange low elements #if REARRANGE_SHFL == 1 mat_b_rearr[4] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0x44); mat_b_rearr[5] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0xEE); mat_b_rearr[6] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0x44); mat_b_rearr[7] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0xEE); #else mat_b_rearr[6] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0x4E); mat_b_rearr[7] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0x4E); mat_b_rearr[4] = _mm256_blend_ps(mat_b_rearr[0], mat_b_rearr[6], 0xCC); mat_b_rearr[5] = _mm256_blend_ps(mat_b_rearr[1], mat_b_rearr[6], 0x33); mat_b_rearr[6] = _mm256_blend_ps(mat_b_rearr[2], mat_b_rearr[7], 0xCC); mat_b_rearr[7] = _mm256_blend_ps(mat_b_rearr[3], mat_b_rearr[7], 0x33); #endif //Merge rearranged low elements into complete rows mat_b_rearr[0] = _mm256_permute2f128_ps(mat_b_rearr[4], mat_b_rearr[6], 0x20); mat_b_rearr[4] = _mm256_permute2f128_ps(mat_b_rearr[4], mat_b_rearr[6], 0x31); mat_b_rearr[1] = _mm256_permute2f128_ps(mat_b_rearr[5], mat_b_rearr[7], 0x20); mat_b_rearr[5] = _mm256_permute2f128_ps(mat_b_rearr[5], mat_b_rearr[7], 0x31); ////unpackhigh//// mat_b_col[0] = _mm256_unpackhi_ps(mat_b_col[0], mat_b_col[1]); mat_b_col[1] = _mm256_unpackhi_ps(mat_b_col[2], mat_b_col[3]); mat_b_col[2] = _mm256_unpackhi_ps(mat_b_col[4], mat_b_col[5]); mat_b_col[3] = _mm256_unpackhi_ps(mat_b_col[6], mat_b_col[7]); //Rearrange high elements #if REARRANGE_SHFL == 1 mat_b_col[4] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0x44); mat_b_col[5] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0xEE); mat_b_col[6] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0x44); mat_b_col[7] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0xEE); #else mat_b_col[6] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0x4E); mat_b_col[7] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0x4E); mat_b_col[4] = _mm256_blend_ps(mat_b_col[0], mat_b_col[6], 0xCC); mat_b_col[5] = _mm256_blend_ps(mat_b_col[1], mat_b_col[6], 0x33); mat_b_col[6] = _mm256_blend_ps(mat_b_col[2], mat_b_col[7], 0xCC); mat_b_col[7] = _mm256_blend_ps(mat_b_col[3], mat_b_col[7], 0x33); #endif //extract diag a00 from a mat_a_diag_inv[0] = _mm256_permute_ps(reciprocal_diags, 0x00); mat_a_diag_inv[0] = _mm256_permute2f128_ps(mat_a_diag_inv[0], mat_a_diag_inv[0], 0x00); //(Row0): Perform mul operation of reciprocal of L(0,0) element with 1st row elements of B mat_b_rearr[0] = _mm256_mul_ps(mat_b_rearr[0], mat_a_diag_inv[0]); //Merge rearranged high elements into complete rows mat_b_rearr[2] = _mm256_permute2f128_ps(mat_b_col[4], mat_b_col[6], 0x20); mat_b_rearr[6] = _mm256_permute2f128_ps(mat_b_col[4], mat_b_col[6], 0x31); mat_b_rearr[3] = _mm256_permute2f128_ps(mat_b_col[5], mat_b_col[7], 0x20); mat_b_rearr[7] = _mm256_permute2f128_ps(mat_b_col[5], mat_b_col[7], 0x31); //extract diag a11 from a mat_a_diag_inv[1] = _mm256_permute_ps(reciprocal_diags, 0x55); mat_a_diag_inv[1] = _mm256_permute2f128_ps(mat_a_diag_inv[1], mat_a_diag_inv[1], 0x00); //(Row1): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_cols_rearr[1], mat_b_rearr[0], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_cols_rearr[3], mat_b_rearr[0], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_cols_rearr[6], mat_b_rearr[0], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_cols_rearr[10], mat_b_rearr[0], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_cols_rearr[15], mat_b_rearr[0], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_cols_rearr[21], mat_b_rearr[0], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_cols_rearr[28], mat_b_rearr[0], mat_b_rearr[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(1,1) element with 2nd row elements of B mat_b_rearr[1] = _mm256_mul_ps(mat_b_rearr[1], mat_a_diag_inv[1]); //extract diag a22 from a mat_a_diag_inv[2] = _mm256_permute_ps(reciprocal_diags, 0xAA); mat_a_diag_inv[2] = _mm256_permute2f128_ps(mat_a_diag_inv[2], mat_a_diag_inv[2], 0x00); //(Row2): FMA operations of b2 with elements of indices from (2, 0) uptill (7, 0) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_cols_rearr[4], mat_b_rearr[1], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_cols_rearr[7], mat_b_rearr[1], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_cols_rearr[11], mat_b_rearr[1], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_cols_rearr[16], mat_b_rearr[1], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_cols_rearr[22], mat_b_rearr[1], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_cols_rearr[29], mat_b_rearr[1], mat_b_rearr[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(2, 2) element with 3rd row elements of B mat_b_rearr[2] = _mm256_mul_ps(mat_b_rearr[2], mat_a_diag_inv[2]); //extract diag a33 from a mat_a_diag_inv[3] = _mm256_permute_ps(reciprocal_diags, 0xFF); mat_a_diag_inv[3] = _mm256_permute2f128_ps(mat_a_diag_inv[3], mat_a_diag_inv[3], 0x00); //(Row3): FMA operations of b3 with elements of indices from (3, 0) uptill (7, 0) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_cols_rearr[8], mat_b_rearr[2], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_cols_rearr[12], mat_b_rearr[2], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_cols_rearr[17], mat_b_rearr[2], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_cols_rearr[23], mat_b_rearr[2], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_cols_rearr[30], mat_b_rearr[2], mat_b_rearr[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(3, 3) element with 4rth row elements of B mat_b_rearr[3] = _mm256_mul_ps(mat_b_rearr[3], mat_a_diag_inv[3]); //extract diag a44 from a mat_a_diag_inv[4] = _mm256_permute_ps(reciprocal_diags, 0x00); mat_a_diag_inv[4] = _mm256_permute2f128_ps(mat_a_diag_inv[4], mat_a_diag_inv[4], 0x11); //(Row4): FMA operations of b4 with elements of indices from (4, 0) uptill (7, 0) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_cols_rearr[13], mat_b_rearr[3], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_cols_rearr[18], mat_b_rearr[3], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_cols_rearr[24], mat_b_rearr[3], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_cols_rearr[31], mat_b_rearr[3], mat_b_rearr[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(4, 4) element with 4rth row elements of B mat_b_rearr[4] = _mm256_mul_ps(mat_b_rearr[4], mat_a_diag_inv[4]); //extract diag a55 from a mat_a_diag_inv[5] = _mm256_permute_ps(reciprocal_diags, 0x55); mat_a_diag_inv[5] = _mm256_permute2f128_ps(mat_a_diag_inv[5], mat_a_diag_inv[5], 0x11); //(Row5): FMA operations of b5 with elements of indices from (5, 0) uptill (7, 0) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_cols_rearr[19], mat_b_rearr[4], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_cols_rearr[25], mat_b_rearr[4], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_cols_rearr[32], mat_b_rearr[4], mat_b_rearr[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(5, 5) element with 5th row elements of B mat_b_rearr[5] = _mm256_mul_ps(mat_b_rearr[5], mat_a_diag_inv[5]); //extract diag a66 from a mat_a_diag_inv[6] = _mm256_permute_ps(reciprocal_diags, 0xAA); mat_a_diag_inv[6] = _mm256_permute2f128_ps(mat_a_diag_inv[6], mat_a_diag_inv[6], 0x11); //(Row6): FMA operations of b6 with elements of indices from (6, 0) uptill (7, 0) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_cols_rearr[26], mat_b_rearr[5], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_cols_rearr[33], mat_b_rearr[5], mat_b_rearr[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(6, 6) element with 6th row elements of B mat_b_rearr[6] = _mm256_mul_ps(mat_b_rearr[6], mat_a_diag_inv[6]); //extract diag a77 from a mat_a_diag_inv[7] = _mm256_permute_ps(reciprocal_diags, 0xFF); mat_a_diag_inv[7] = _mm256_permute2f128_ps(mat_a_diag_inv[7], mat_a_diag_inv[7], 0x11); //(Row7): FMA operations of b7 with elements of index (7, 0) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_cols_rearr[34], mat_b_rearr[6], mat_b_rearr[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(7, 7) element with 7th row elements of B mat_b_rearr[7] = _mm256_mul_ps(mat_b_rearr[7], mat_a_diag_inv[7]); //--> Transpose and store results of columns of B block <--// ////unpacklow//// mat_a_cols[0] = _mm256_unpacklo_ps(mat_b_rearr[0], mat_b_rearr[1]); mat_a_cols[1] = _mm256_unpacklo_ps(mat_b_rearr[2], mat_b_rearr[3]); mat_a_cols[2] = _mm256_unpacklo_ps(mat_b_rearr[4], mat_b_rearr[5]); mat_a_cols[3] = _mm256_unpacklo_ps(mat_b_rearr[6], mat_b_rearr[7]); //Rearrange low elements #if REARRANGE_SHFL == 1 mat_a_cols[4] = _mm256_shuffle_ps(mat_a_cols[0], mat_a_cols[1], 0x44); mat_a_cols[5] = _mm256_shuffle_ps(mat_a_cols[0], mat_a_cols[1], 0xEE); mat_a_cols[6] = _mm256_shuffle_ps(mat_a_cols[2], mat_a_cols[3], 0x44); mat_a_cols[7] = _mm256_shuffle_ps(mat_a_cols[2], mat_a_cols[3], 0xEE); #else mat_a_cols[6] = _mm256_shuffle_ps(mat_a_cols[0], mat_a_cols[1], 0x4E); mat_a_cols[7] = _mm256_shuffle_ps(mat_a_cols[2], mat_a_cols[3], 0x4E); mat_a_cols[4] = _mm256_blend_ps(mat_a_cols[0], mat_a_cols[6], 0xCC); mat_a_cols[5] = _mm256_blend_ps(mat_a_cols[1], mat_a_cols[6], 0x33); mat_a_cols[6] = _mm256_blend_ps(mat_a_cols[2], mat_a_cols[7], 0xCC); mat_a_cols[7] = _mm256_blend_ps(mat_a_cols[3], mat_a_cols[7], 0x33); #endif //Merge rearranged low elements into complete rows mat_a_cols[0] = _mm256_permute2f128_ps(mat_a_cols[4], mat_a_cols[6], 0x20); mat_a_cols[4] = _mm256_permute2f128_ps(mat_a_cols[4], mat_a_cols[6], 0x31); mat_a_cols[1] = _mm256_permute2f128_ps(mat_a_cols[5], mat_a_cols[7], 0x20); mat_a_cols[5] = _mm256_permute2f128_ps(mat_a_cols[5], mat_a_cols[7], 0x31); ////unpackhigh//// mat_b_rearr[0] = _mm256_unpackhi_ps(mat_b_rearr[0], mat_b_rearr[1]); mat_b_rearr[1] = _mm256_unpackhi_ps(mat_b_rearr[2], mat_b_rearr[3]); mat_b_rearr[2] = _mm256_unpackhi_ps(mat_b_rearr[4], mat_b_rearr[5]); mat_b_rearr[3] = _mm256_unpackhi_ps(mat_b_rearr[6], mat_b_rearr[7]); //Rearrange high elements #if REARRANGE_SHFL == 1 mat_b_rearr[4] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0x44); mat_b_rearr[5] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0xEE); mat_b_rearr[6] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0x44); mat_b_rearr[7] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0xEE); #else mat_b_rearr[6] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0x4E); mat_b_rearr[7] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0x4E); mat_b_rearr[4] = _mm256_blend_ps(mat_b_rearr[0], mat_b_rearr[6], 0xCC); mat_b_rearr[5] = _mm256_blend_ps(mat_b_rearr[1], mat_b_rearr[6], 0x33); mat_b_rearr[6] = _mm256_blend_ps(mat_b_rearr[2], mat_b_rearr[7], 0xCC); mat_b_rearr[7] = _mm256_blend_ps(mat_b_rearr[3], mat_b_rearr[7], 0x33); #endif //Merge rearranged high elements into complete rows mat_a_cols[2] = _mm256_permute2f128_ps(mat_b_rearr[4], mat_b_rearr[6], 0x20); mat_a_cols[6] = _mm256_permute2f128_ps(mat_b_rearr[4], mat_b_rearr[6], 0x31); mat_a_cols[3] = _mm256_permute2f128_ps(mat_b_rearr[5], mat_b_rearr[7], 0x20); mat_a_cols[7] = _mm256_permute2f128_ps(mat_b_rearr[5], mat_b_rearr[7], 0x31); //Store the computed B columns _mm256_storeu_ps((float *)ptr_b_dup, mat_a_cols[0]); _mm256_storeu_ps((float *)(ptr_b_dup + (cs_b)), mat_a_cols[1]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[0]), mat_a_cols[2]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[1]), mat_a_cols[3]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[2]), mat_a_cols[4]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[3]), mat_a_cols[5]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[4]), mat_a_cols[6]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[5]), mat_a_cols[7]); //end loop of cols } #if OPT_CACHE_BLOCKING_L1 //new intrinsic kernels static void trsm_XAtB_block_allSmallSizedMatrices(float *ptr_l, float *ptr_b, int numRows_lb, int numCols_b, int rs_l, int rs_b, int cs_l, int cs_b) { float ones = 1.0; int i, i1, i2, i3, i4, j, k, l, r; int cs_b_offset[7]; int cs_l_offset[7]; float *ptr_b_dup, *ptr_l_dup; //57 number of ymm(256 bits) registers used __m256 mat_b_col[8]; __m256 mat_b_rearr[8]; __m256 mat_a_blk_elems[8]; __m256 mat_a_diag_inv[8]; __m256 reciprocal_diags[2]; reciprocal_diags[0] = _mm256_broadcast_ss((float const *)(&ones)); // ---> considering that the matrix size is multiple of 16 rows and 8 cols <--- // //L matrix offsets cs_l_offset[0] = (cs_l << 1); cs_l_offset[1] = cs_l + cs_l_offset[0]; cs_l_offset[2] = (cs_l << 2); cs_l_offset[3] = cs_l + cs_l_offset[2]; cs_l_offset[4] = cs_l_offset[0] + cs_l_offset[2]; cs_l_offset[5] = cs_l + cs_l_offset[4]; cs_l_offset[6] = (cs_l_offset[5] + cs_l); //read diag elems of L 16x16 block mat_a_blk_elems[0] = _mm256_loadu_ps((float const *)ptr_l); mat_a_blk_elems[1] = _mm256_loadu_ps((float const *)ptr_l + cs_l); mat_a_blk_elems[2] = _mm256_loadu_ps((float const *)ptr_l + cs_l_offset[0]); mat_a_blk_elems[3] = _mm256_loadu_ps((float const *)ptr_l + cs_l_offset[1]); mat_a_blk_elems[4] = _mm256_loadu_ps((float const *)ptr_l + cs_l_offset[2]); mat_a_blk_elems[5] = _mm256_loadu_ps((float const *)ptr_l + cs_l_offset[3]); mat_a_blk_elems[6] = _mm256_loadu_ps((float const *)ptr_l + cs_l_offset[4]); mat_a_blk_elems[7] = _mm256_loadu_ps((float const *)ptr_l + cs_l_offset[5]); cs_b_offset[0] = (cs_b << 1); cs_b_offset[1] = cs_b + cs_b_offset[0]; cs_b_offset[2] = (cs_b << 2); cs_b_offset[3] = cs_b + cs_b_offset[2]; cs_b_offset[4] = cs_b_offset[0] + cs_b_offset[2]; cs_b_offset[5] = cs_b + cs_b_offset[4]; cs_b_offset[6] = (cs_b_offset[5] + cs_b); reciprocal_diags[1] = reciprocal_diags[0]; //pack first 8 diags together mat_a_diag_inv[0] = _mm256_blend_ps(mat_a_blk_elems[0], mat_a_blk_elems[1], 0xAA);//diag 0,1 mat_a_diag_inv[1] = _mm256_blend_ps(mat_a_blk_elems[2], mat_a_blk_elems[3], 0xAA);//diag 2,3 mat_a_diag_inv[2] = _mm256_blend_ps(mat_a_blk_elems[4], mat_a_blk_elems[5], 0xAA);//diag 4,5 mat_a_diag_inv[3] = _mm256_blend_ps(mat_a_blk_elems[6], mat_a_blk_elems[7], 0xAA);//diag 6,7 mat_a_diag_inv[0] = _mm256_blend_ps(mat_a_diag_inv[0], mat_a_diag_inv[1], 0xCC);//diag 0,1,2,3 mat_a_diag_inv[2] = _mm256_blend_ps(mat_a_diag_inv[2], mat_a_diag_inv[3], 0xCC);//diag 4,5,6,7 mat_a_diag_inv[0] = _mm256_blend_ps(mat_a_diag_inv[0], mat_a_diag_inv[2], 0xF0);//diag 0,1,2,3,4,5,6,7 //reciprocal of diagnal elements 0,1,2,3,4,5,6,7 reciprocal_diags[0] = _mm256_div_ps(reciprocal_diags[0], mat_a_diag_inv[0]); //extract diag a00 from a mat_a_diag_inv[0] = _mm256_permute_ps(reciprocal_diags[0], 0x00); mat_a_diag_inv[0] = _mm256_permute2f128_ps(mat_a_diag_inv[0], mat_a_diag_inv[0], 0x00); //mat_a_diag_inv[0] = _mm256_unpacklo_ps(mat_a_diag_inv[0], mat_a_diag_inv[0]); //extract diag a11 from a mat_a_diag_inv[1] = _mm256_permute_ps(reciprocal_diags[0], 0x55); mat_a_diag_inv[1] = _mm256_permute2f128_ps(mat_a_diag_inv[1], mat_a_diag_inv[1], 0x00); //mat_a_diag_inv[1] = _mm256_unpacklo_ps(mat_a_diag_inv[1], mat_a_diag_inv[1]); //extract diag a22 from a mat_a_diag_inv[2] = _mm256_permute_ps(reciprocal_diags[0], 0xAA); mat_a_diag_inv[2] = _mm256_permute2f128_ps(mat_a_diag_inv[2], mat_a_diag_inv[2], 0x00); //mat_a_diag_inv[2] = _mm256_unpacklo_ps(mat_a_diag_inv[2], mat_a_diag_inv[2]); //extract diag a33 from a mat_a_diag_inv[3] = _mm256_permute_ps(reciprocal_diags[0], 0xFF); mat_a_diag_inv[3] = _mm256_permute2f128_ps(mat_a_diag_inv[3], mat_a_diag_inv[3], 0x00); //mat_a_diag_inv[3] = _mm256_unpacklo_ps(mat_a_diag_inv[3], mat_a_diag_inv[3]); //extract diag a44 from a mat_a_diag_inv[4] = _mm256_permute_ps(reciprocal_diags[0], 0x00); mat_a_diag_inv[4] = _mm256_permute2f128_ps(mat_a_diag_inv[4], mat_a_diag_inv[4], 0x11); //mat_a_diag_inv[4] = _mm256_unpacklo_ps(mat_a_diag_inv[4], mat_a_diag_inv[4]); //extract diag a55 from a mat_a_diag_inv[5] = _mm256_permute_ps(reciprocal_diags[0], 0x55); mat_a_diag_inv[5] = _mm256_permute2f128_ps(mat_a_diag_inv[5], mat_a_diag_inv[5], 0x11); //mat_a_diag_inv[5] = _mm256_unpacklo_ps(mat_a_diag_inv[5], mat_a_diag_inv[5]); //extract diag a66 from a mat_a_diag_inv[6] = _mm256_permute_ps(reciprocal_diags[0], 0xAA); mat_a_diag_inv[6] = _mm256_permute2f128_ps(mat_a_diag_inv[6], mat_a_diag_inv[6], 0x11); //mat_a_diag_inv[6] = _mm256_unpacklo_ps(mat_a_diag_inv[6], mat_a_diag_inv[6]); //extract diag a77 from a mat_a_diag_inv[7] = _mm256_permute_ps(reciprocal_diags[0], 0xFF); mat_a_diag_inv[7] = _mm256_permute2f128_ps(mat_a_diag_inv[7], mat_a_diag_inv[7], 0x11); //mat_a_diag_inv[7] = _mm256_unpacklo_ps(mat_a_diag_inv[7], mat_a_diag_inv[7]); /***************** first set of 8 rows of B processing starts *****************/ ptr_b_dup = ptr_b; i = 0; for (j = 0; j < numCols_b; j += 8) { /////////////////// Complete Upper 8x8 block trsm of B :- upper 8x8 block of B with upper 8x8 block of A //read 8x8 block of B into registers mat_b_col[0] = _mm256_loadu_ps((float const *)ptr_b + i); mat_b_col[1] = _mm256_loadu_ps((float const *)(ptr_b + cs_b + i)); mat_b_col[2] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[0] + i)); mat_b_col[3] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[1] + i)); mat_b_col[4] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[2] + i)); mat_b_col[5] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[3] + i)); mat_b_col[6] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[4] + i)); mat_b_col[7] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[5] + i)); //(Row0): Perform mul operation of reciprocal of L(0,0) element with 1st row elements of B mat_b_col[0] = _mm256_mul_ps(mat_b_col[0], mat_a_diag_inv[0]); mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + 1)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + 2)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l + 3)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l + 4)); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l + 5)); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l + 6)); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l + 7)); //(Row1): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_col[1] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[0], mat_b_col[1]);//d = c - (a*b) mat_b_col[2] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[0], mat_b_col[2]);//d = c - (a*b) mat_b_col[3] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[0], mat_b_col[3]);//d = c - (a*b) mat_b_col[4] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[0], mat_b_col[4]);//d = c - (a*b) mat_b_col[5] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[0], mat_b_col[5]);//d = c - (a*b) mat_b_col[6] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[0], mat_b_col[6]);//d = c - (a*b) mat_b_col[7] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_col[0], mat_b_col[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(1,1) element with 2nd row elements of B mat_b_col[1] = _mm256_mul_ps(mat_b_col[1], mat_a_diag_inv[1]); mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 2)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 3)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 4)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 5)); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 6)); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 7)); //(Row2): FMA operations of b2 with elements of indices from (2, 0) uptill (7, 0) mat_b_col[2] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[1], mat_b_col[2]);//d = c - (a*b) mat_b_col[3] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[1], mat_b_col[3]);//d = c - (a*b) mat_b_col[4] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[1], mat_b_col[4]);//d = c - (a*b) mat_b_col[5] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[1], mat_b_col[5]);//d = c - (a*b) mat_b_col[6] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[1], mat_b_col[6]);//d = c - (a*b) mat_b_col[7] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[1], mat_b_col[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(2, 2) element with 3rd row elements of B mat_b_col[2] = _mm256_mul_ps(mat_b_col[2], mat_a_diag_inv[2]); mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + 3)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + 4)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + 5)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + 6)); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + 7)); //(Row3): FMA operations of b3 with elements of indices from (3, 0) uptill (7, 0) mat_b_col[3] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[2], mat_b_col[3]);//d = c - (a*b) mat_b_col[4] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[2], mat_b_col[4]);//d = c - (a*b) mat_b_col[5] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[2], mat_b_col[5]);//d = c - (a*b) mat_b_col[6] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[2], mat_b_col[6]);//d = c - (a*b) mat_b_col[7] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[2], mat_b_col[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(3, 3) element with 4rth row elements of B mat_b_col[3] = _mm256_mul_ps(mat_b_col[3], mat_a_diag_inv[3]); mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + 4)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + 5)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + 6)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + 7)); //(Row4): FMA operations of b4 with elements of indices from (4, 0) uptill (7, 0) mat_b_col[4] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[3], mat_b_col[4]);//d = c - (a*b) mat_b_col[5] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[3], mat_b_col[5]);//d = c - (a*b) mat_b_col[6] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[3], mat_b_col[6]);//d = c - (a*b) mat_b_col[7] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[3], mat_b_col[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(4, 4) element with 4rth row elements of B mat_b_col[4] = _mm256_mul_ps(mat_b_col[4], mat_a_diag_inv[4]); mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[2] + 5)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[2] + 6)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[2] + 7)); //(Row5): FMA operations of b5 with elements of indices from (5, 0) uptill (7, 0) mat_b_col[5] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[4], mat_b_col[5]);//d = c - (a*b) mat_b_col[6] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[4], mat_b_col[6]);//d = c - (a*b) mat_b_col[7] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[4], mat_b_col[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(5, 5) element with 5th row elements of B mat_b_col[5] = _mm256_mul_ps(mat_b_col[5], mat_a_diag_inv[5]); mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[3] + 6)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[3] + 7)); //(Row6): FMA operations of b6 with elements of indices from (6, 0) uptill (7, 0) mat_b_col[6] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[5], mat_b_col[6]);//d = c - (a*b) mat_b_col[7] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[5], mat_b_col[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(6, 6) element with 6th row elements of B mat_b_col[6] = _mm256_mul_ps(mat_b_col[6], mat_a_diag_inv[6]); mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[4] + 7)); //(Row7): FMA operations of b7 with elements of index (7, 0) mat_b_col[7] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[6], mat_b_col[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(7, 7) element with 7th row elements of B mat_b_col[7] = _mm256_mul_ps(mat_b_col[7], mat_a_diag_inv[7]); //////////////////////////////////////////////////////////////////////////////// //Store the computed B columns _mm256_storeu_ps((float *)ptr_b_dup, mat_b_col[0]); _mm256_storeu_ps((float *)(ptr_b_dup + (cs_b)), mat_b_col[1]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[0]), mat_b_col[2]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[1]), mat_b_col[3]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[2]), mat_b_col[4]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[3]), mat_b_col[5]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[4]), mat_b_col[6]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[5]), mat_b_col[7]); //i += cs_b_offset[6]; //ptr_b_dup += cs_b_offset[6]; i += 8; ptr_b_dup += 8; } //c = 0; /***************** first set of 8 cols of B processing done *****************/ ptr_b_dup = ptr_b; i3 = 0; i1 = 0; //Start loop for cols of B to be processed in size of blk_width for (j = 8; j < numRows_lb; j += 8)//m :- 8x8 block row { ptr_l += 8; //ptr_b += j; //ptr_b_dup += 8; ptr_b_dup += cs_b_offset[6]; i1 += cs_b_offset[6]; //Read next 8x8 block of A to get diag elements i3 += cs_l_offset[6]; mat_a_blk_elems[0] = _mm256_loadu_ps((float const *)ptr_l + i3); mat_a_blk_elems[1] = _mm256_loadu_ps((float const *)ptr_l + i3 + cs_l); mat_a_blk_elems[2] = _mm256_loadu_ps((float const *)ptr_l + i3 + cs_l_offset[0]); mat_a_blk_elems[3] = _mm256_loadu_ps((float const *)ptr_l + i3 + cs_l_offset[1]); mat_a_blk_elems[4] = _mm256_loadu_ps((float const *)ptr_l + i3 + cs_l_offset[2]); mat_a_blk_elems[5] = _mm256_loadu_ps((float const *)ptr_l + i3 + cs_l_offset[3]); mat_a_blk_elems[6] = _mm256_loadu_ps((float const *)ptr_l + i3 + cs_l_offset[4]); mat_a_blk_elems[7] = _mm256_loadu_ps((float const *)ptr_l + i3 + cs_l_offset[5]); //pack 8 diags of A together reciprocal_diags[0] = reciprocal_diags[1]; mat_a_diag_inv[0] = _mm256_blend_ps(mat_a_blk_elems[0], mat_a_blk_elems[1], 0xAA);//diag 0,1 mat_a_diag_inv[1] = _mm256_blend_ps(mat_a_blk_elems[2], mat_a_blk_elems[3], 0xAA);//diag 2,3 mat_a_diag_inv[2] = _mm256_blend_ps(mat_a_blk_elems[4], mat_a_blk_elems[5], 0xAA);//diag 4,5 mat_a_diag_inv[3] = _mm256_blend_ps(mat_a_blk_elems[6], mat_a_blk_elems[7], 0xAA);//diag 6,7 mat_a_diag_inv[0] = _mm256_blend_ps(mat_a_diag_inv[0], mat_a_diag_inv[1], 0xCC);//diag 0,1,2,3 mat_a_diag_inv[2] = _mm256_blend_ps(mat_a_diag_inv[2], mat_a_diag_inv[3], 0xCC);//diag 4,5,6,7 mat_a_diag_inv[0] = _mm256_blend_ps(mat_a_diag_inv[0], mat_a_diag_inv[2], 0xF0);//diag 0,1,2,3,4,5,6,7 //reciprocal of diagnal elements of A :- 0,1,2,3,4,5,6,7 reciprocal_diags[0] = _mm256_div_ps(reciprocal_diags[0], mat_a_diag_inv[0]); //extract diag a00 from a mat_a_diag_inv[0] = _mm256_permute_ps(reciprocal_diags[0], 0x00); mat_a_diag_inv[0] = _mm256_permute2f128_ps(mat_a_diag_inv[0], mat_a_diag_inv[0], 0x00); //mat_a_diag_inv2[0] = _mm256_unpacklo_ps(mat_a_diag_inv2[0], mat_a_diag_inv2[0]); //extract diag a11 from a mat_a_diag_inv[1] = _mm256_permute_ps(reciprocal_diags[0], 0x55); mat_a_diag_inv[1] = _mm256_permute2f128_ps(mat_a_diag_inv[1], mat_a_diag_inv[1], 0x00); //mat_a_diag_inv[1] = _mm256_unpacklo_ps(mat_a_diag_inv[1], mat_a_diag_inv[1]); //extract diag a22 from a mat_a_diag_inv[2] = _mm256_permute_ps(reciprocal_diags[0], 0xAA); mat_a_diag_inv[2] = _mm256_permute2f128_ps(mat_a_diag_inv[2], mat_a_diag_inv[2], 0x00); //mat_a_diag_inv[2] = _mm256_unpacklo_ps(mat_a_diag_inv[2], mat_a_diag_inv[2]); //extract diag a33 from a mat_a_diag_inv[3] = _mm256_permute_ps(reciprocal_diags[0], 0xFF); mat_a_diag_inv[3] = _mm256_permute2f128_ps(mat_a_diag_inv[3], mat_a_diag_inv[3], 0x00); //mat_a_diag_inv[3] = _mm256_unpacklo_ps(mat_a_diag_inv[3], mat_a_diag_inv[3]); //extract diag a44 from a mat_a_diag_inv[4] = _mm256_permute_ps(reciprocal_diags[0], 0x00); mat_a_diag_inv[4] = _mm256_permute2f128_ps(mat_a_diag_inv[4], mat_a_diag_inv[4], 0x11); //mat_a_diag_inv[4] = _mm256_unpacklo_ps(mat_a_diag_inv[4], mat_a_diag_inv[4]); //extract diag a55 from a mat_a_diag_inv[5] = _mm256_permute_ps(reciprocal_diags[0], 0x55); mat_a_diag_inv[5] = _mm256_permute2f128_ps(mat_a_diag_inv[5], mat_a_diag_inv[5], 0x11); //mat_a_diag_inv[5] = _mm256_unpacklo_ps(mat_a_diag_inv[5], mat_a_diag_inv[5]); //extract diag a66 from a mat_a_diag_inv[6] = _mm256_permute_ps(reciprocal_diags[0], 0xAA); mat_a_diag_inv[6] = _mm256_permute2f128_ps(mat_a_diag_inv[6], mat_a_diag_inv[6], 0x11); //mat_a_diag_inv[6] = _mm256_unpacklo_ps(mat_a_diag_inv[6], mat_a_diag_inv[6]); //extract diag a77 from a mat_a_diag_inv[7] = _mm256_permute_ps(reciprocal_diags[0], 0xFF); mat_a_diag_inv[7] = _mm256_permute2f128_ps(mat_a_diag_inv[7], mat_a_diag_inv[7], 0x11); //mat_a_diag_inv[7] = _mm256_unpacklo_ps(mat_a_diag_inv[7], mat_a_diag_inv[7]); for (r = 0; r < numCols_b; r += GEMM_BLK_V1) { #if GEMM_ACCUM_A i = i1 + r; //Read 8 cols of B columns of Block-to-be-solved mat_b_rearr[0] = _mm256_loadu_ps((float const *)ptr_b + i); mat_b_rearr[1] = _mm256_loadu_ps((float const *)(ptr_b + cs_b + i)); mat_b_rearr[2] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[0] + i)); mat_b_rearr[3] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[1] + i)); mat_b_rearr[4] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[2] + i)); mat_b_rearr[5] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[3] + i)); mat_b_rearr[6] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[4] + i)); mat_b_rearr[7] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[5] + i)); #endif i = 0; i2 = 0; for (l = 0; l < j; l += 8) // move across m { //for (k = 0; k < numCols_b; k += 8) // move across n for the same value of l (index of m) { /////////////////// Partial Lower 8x8 block trsm of B ptr_l_dup = ptr_l; i4 = i2 + r; //Read current 8 cols of B columns from specified 8x8 current-block of B mat_b_col[0] = _mm256_loadu_ps((float const *)ptr_b + i4); mat_b_col[1] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b)); mat_b_col[2] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b_offset[0])); mat_b_col[3] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b_offset[1])); mat_b_col[4] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b_offset[2])); mat_b_col[5] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b_offset[3])); mat_b_col[6] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b_offset[4])); mat_b_col[7] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b_offset[5])); //Broadcast A8,0 to A15,0 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 1)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 2)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 3)); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 4)); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 5)); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 6)); mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 7)); i4 = k >> 3; ptr_l_dup += cs_l; #if GEMM_ACCUM_A //(Row8): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[0] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[0], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[0], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[0], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[0], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[0], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[0], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_col[0], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[7], mat_b_col[0], mat_b_rearr[7]);//d = c - (a*b) #else mat_b_rearr[0] = _mm256_mul_ps(mat_a_blk_elems[0], mat_b_col[0]); mat_b_rearr[1] = _mm256_mul_ps(mat_a_blk_elems[1], mat_b_col[0]); mat_b_rearr[2] = _mm256_mul_ps(mat_a_blk_elems[2], mat_b_col[0]); mat_b_rearr[3] = _mm256_mul_ps(mat_a_blk_elems[3], mat_b_col[0]); mat_b_rearr[4] = _mm256_mul_ps(mat_a_blk_elems[4], mat_b_col[0]); mat_b_rearr[5] = _mm256_mul_ps(mat_a_blk_elems[5], mat_b_col[0]); mat_b_rearr[6] = _mm256_mul_ps(mat_a_blk_elems[6], mat_b_col[0]); mat_b_rearr[7] = _mm256_mul_ps(mat_a_blk_elems[7], mat_b_col[0]); #endif //Broadcast A21 to A71 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 1)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 2)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 3)); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 4)); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 5)); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 6)); mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 7)); ptr_l_dup += cs_l; #if GEMM_ACCUM_A //(Row9): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[0] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[1], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[1], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[1], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[1], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[1], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[1], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_col[1], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[7], mat_b_col[1], mat_b_rearr[7]);//d = c - (a*b) #else mat_b_rearr[0] = _mm256_fmadd_ps(mat_a_blk_elems[0], mat_b_col[1], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fmadd_ps(mat_a_blk_elems[1], mat_b_col[1], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fmadd_ps(mat_a_blk_elems[2], mat_b_col[1], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fmadd_ps(mat_a_blk_elems[3], mat_b_col[1], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fmadd_ps(mat_a_blk_elems[4], mat_b_col[1], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fmadd_ps(mat_a_blk_elems[5], mat_b_col[1], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fmadd_ps(mat_a_blk_elems[6], mat_b_col[1], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fmadd_ps(mat_a_blk_elems[7], mat_b_col[1], mat_b_rearr[7]);//d = c - (a*b) #endif //Broadcast A8,2 to A15,2 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 1)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 2)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 3)); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 4)); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 5)); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 6)); mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 7)); ptr_l_dup += cs_l; #if GEMM_ACCUM_A //(Row10): FMA operations of b2 with elements of indices from (2, 0) uptill (7, 0) mat_b_rearr[0] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[2], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[2], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[2], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[2], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[2], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[2], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_col[2], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[7], mat_b_col[2], mat_b_rearr[7]);//d = c - (a*b) #else mat_b_rearr[0] = _mm256_fmadd_ps(mat_a_blk_elems[0], mat_b_col[2], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fmadd_ps(mat_a_blk_elems[1], mat_b_col[2], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fmadd_ps(mat_a_blk_elems[2], mat_b_col[2], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fmadd_ps(mat_a_blk_elems[3], mat_b_col[2], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fmadd_ps(mat_a_blk_elems[4], mat_b_col[2], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fmadd_ps(mat_a_blk_elems[5], mat_b_col[2], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fmadd_ps(mat_a_blk_elems[6], mat_b_col[2], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fmadd_ps(mat_a_blk_elems[7], mat_b_col[2], mat_b_rearr[7]);//d = c - (a*b) #endif //Broadcast A8,3 to A15,3 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 1)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 2)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 3)); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 4)); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 5)); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 6)); mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 7)); ptr_l_dup += cs_l; #if GEMM_ACCUM_A //(Row11): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[0] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[3], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[3], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[3], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[3], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[3], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[3], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_col[3], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[7], mat_b_col[3], mat_b_rearr[7]);//d = c - (a*b) #else mat_b_rearr[0] = _mm256_fmadd_ps(mat_a_blk_elems[0], mat_b_col[3], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fmadd_ps(mat_a_blk_elems[1], mat_b_col[3], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fmadd_ps(mat_a_blk_elems[2], mat_b_col[3], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fmadd_ps(mat_a_blk_elems[3], mat_b_col[3], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fmadd_ps(mat_a_blk_elems[4], mat_b_col[3], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fmadd_ps(mat_a_blk_elems[5], mat_b_col[3], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fmadd_ps(mat_a_blk_elems[6], mat_b_col[3], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fmadd_ps(mat_a_blk_elems[7], mat_b_col[3], mat_b_rearr[7]);//d = c - (a*b) #endif //Broadcast A8,4 to A15,4 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 1)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 2)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 3)); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 4)); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 5)); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 6)); mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 7)); ptr_l_dup += cs_l; #if GEMM_ACCUM_A //(Row12): FMA operations of b2 with elements of indices from (2, 0) uptill (7, 0) mat_b_rearr[0] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[4], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[4], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[4], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[4], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[4], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[4], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_col[4], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[7], mat_b_col[4], mat_b_rearr[7]);//d = c - (a*b) #else mat_b_rearr[0] = _mm256_fmadd_ps(mat_a_blk_elems[0], mat_b_col[4], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fmadd_ps(mat_a_blk_elems[1], mat_b_col[4], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fmadd_ps(mat_a_blk_elems[2], mat_b_col[4], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fmadd_ps(mat_a_blk_elems[3], mat_b_col[4], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fmadd_ps(mat_a_blk_elems[4], mat_b_col[4], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fmadd_ps(mat_a_blk_elems[5], mat_b_col[4], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fmadd_ps(mat_a_blk_elems[6], mat_b_col[4], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fmadd_ps(mat_a_blk_elems[7], mat_b_col[4], mat_b_rearr[7]);//d = c - (a*b) #endif //Broadcast A8,5 to A15,5 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 1)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 2)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 3)); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 4)); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 5)); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 6)); mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 7)); ptr_l_dup += cs_l; #if GEMM_ACCUM_A //(Row13): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[0] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[5], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[5], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[5], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[5], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[5], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[5], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_col[5], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[7], mat_b_col[5], mat_b_rearr[7]);//d = c - (a*b) #else mat_b_rearr[0] = _mm256_fmadd_ps(mat_a_blk_elems[0], mat_b_col[5], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fmadd_ps(mat_a_blk_elems[1], mat_b_col[5], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fmadd_ps(mat_a_blk_elems[2], mat_b_col[5], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fmadd_ps(mat_a_blk_elems[3], mat_b_col[5], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fmadd_ps(mat_a_blk_elems[4], mat_b_col[5], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fmadd_ps(mat_a_blk_elems[5], mat_b_col[5], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fmadd_ps(mat_a_blk_elems[6], mat_b_col[5], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fmadd_ps(mat_a_blk_elems[7], mat_b_col[5], mat_b_rearr[7]);//d = c - (a*b) #endif //Broadcast A8,6 to A15,6 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 1)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 2)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 3)); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 4)); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 5)); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 6)); mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 7)); ptr_l_dup += cs_l; #if GEMM_ACCUM_A //(Row14): FMA operations of b2 with elements of indices from (2, 0) uptill (7, 0) mat_b_rearr[0] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[6], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[6], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[6], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[6], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[6], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[6], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_col[6], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[7], mat_b_col[6], mat_b_rearr[7]);//d = c - (a*b) #else mat_b_rearr[0] = _mm256_fmadd_ps(mat_a_blk_elems[0], mat_b_col[6], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fmadd_ps(mat_a_blk_elems[1], mat_b_col[6], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fmadd_ps(mat_a_blk_elems[2], mat_b_col[6], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fmadd_ps(mat_a_blk_elems[3], mat_b_col[6], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fmadd_ps(mat_a_blk_elems[4], mat_b_col[6], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fmadd_ps(mat_a_blk_elems[5], mat_b_col[6], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fmadd_ps(mat_a_blk_elems[6], mat_b_col[6], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fmadd_ps(mat_a_blk_elems[7], mat_b_col[6], mat_b_rearr[7]);//d = c - (a*b) #endif //Broadcast A8,7 to A15,7 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 1)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 2)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 3)); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 4)); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 5)); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 6)); mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 7)); ptr_l_dup += cs_l; #if GEMM_ACCUM_A //(Row15): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[0] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[7], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[7], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[7], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[7], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[7], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[7], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_col[7], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[7], mat_b_col[7], mat_b_rearr[7]);//d = c - (a*b) #else mat_b_rearr[0] = _mm256_fmadd_ps(mat_a_blk_elems[0], mat_b_col[7], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fmadd_ps(mat_a_blk_elems[1], mat_b_col[7], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fmadd_ps(mat_a_blk_elems[2], mat_b_col[7], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fmadd_ps(mat_a_blk_elems[3], mat_b_col[7], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fmadd_ps(mat_a_blk_elems[4], mat_b_col[7], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fmadd_ps(mat_a_blk_elems[5], mat_b_col[7], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fmadd_ps(mat_a_blk_elems[6], mat_b_col[7], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fmadd_ps(mat_a_blk_elems[7], mat_b_col[7], mat_b_rearr[7]);//d = c - (a*b) #endif //end loop of cols } i2 += cs_b_offset[6]; i += cs_l_offset[6]; } //trsm solve k = 0; //for (i2 = 0; i2 < numCols_b; i2 += 8) { i2 = i1 + r; /////////////////// Complete Lower 8x8 block trsm of B :- lower 8x8 block of B with lower right 8x8 block of A #if !GEMM_ACCUM_A //Read 8 cols of B columns of Block-to-be-solved mat_b_col[0] = _mm256_loadu_ps((float const *)ptr_b + i2); mat_b_col[1] = _mm256_loadu_ps((float const *)(ptr_b + cs_b + i2)); mat_b_col[2] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[0] + i2)); mat_b_col[3] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[1] + i2)); mat_b_col[4] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[2] + i2)); mat_b_col[5] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[3] + i2)); mat_b_col[6] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[4] + i2)); mat_b_col[7] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[5] + i2)); #endif //Broadcast A10 to A70 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + i + 1)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + i + 2)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l + i + 3)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l + i + 4)); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l + i + 5)); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l + i + 6)); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l + i + 7)); i += cs_l; #if GEMM_ACCUM_A //(Row0): Perform mul operation of reciprocal of L(0,0) element with 1st row elements of B mat_b_rearr[0] = _mm256_mul_ps(mat_b_rearr[0], mat_a_diag_inv[0]); #else mat_b_rearr[0] = _mm256_sub_ps(mat_b_col[0], mat_b_rearr[0]); mat_b_rearr[0] = _mm256_mul_ps(mat_b_rearr[0], mat_a_diag_inv[0]); #endif #if GEMM_ACCUM_A mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_rearr[0], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_rearr[0], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_rearr[0], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_rearr[0], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_rearr[0], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_rearr[0], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_rearr[0], mat_b_rearr[7]);//d = c - (a*b) #else mat_b_rearr[1] = _mm256_sub_ps(mat_b_col[1], mat_b_rearr[1]); mat_b_rearr[2] = _mm256_sub_ps(mat_b_col[2], mat_b_rearr[2]); mat_b_rearr[3] = _mm256_sub_ps(mat_b_col[3], mat_b_rearr[3]); mat_b_rearr[4] = _mm256_sub_ps(mat_b_col[4], mat_b_rearr[4]); mat_b_rearr[5] = _mm256_sub_ps(mat_b_col[5], mat_b_rearr[5]); mat_b_rearr[6] = _mm256_sub_ps(mat_b_col[6], mat_b_rearr[6]); mat_b_rearr[7] = _mm256_sub_ps(mat_b_col[7], mat_b_rearr[7]); //(Row1): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_rearr[0], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_rearr[0], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_rearr[0], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_rearr[0], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_rearr[0], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_rearr[0], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_rearr[0], mat_b_rearr[7]);//d = c - (a*b) #endif //Broadcast A21 to A71 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + i + 2)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + i + 3)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l + i + 4)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l + i + 5)); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l + i + 6)); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l + i + 7)); i += cs_l; //Perform mul operation of reciprocal of L(1,1) element with 2nd row elements of B mat_b_rearr[1] = _mm256_mul_ps(mat_b_rearr[1], mat_a_diag_inv[1]); //(Row2): FMA operations of b2 with elements of indices from (2, 0) uptill (7, 0) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_rearr[1], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_rearr[1], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_rearr[1], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_rearr[1], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_rearr[1], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_rearr[1], mat_b_rearr[7]);//d = c - (a*b) //Broadcast A32 to A72 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + i + 3)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + i + 4)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l + i + 5)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l + i + 6)); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l + i + 7)); i += cs_l; //Perform mul operation of reciprocal of L(2, 2) element with 3rd row elements of B mat_b_rearr[2] = _mm256_mul_ps(mat_b_rearr[2], mat_a_diag_inv[2]); //(Row3): FMA operations of b3 with elements of indices from (3, 0) uptill (7, 0) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_rearr[2], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_rearr[2], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_rearr[2], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_rearr[2], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_rearr[2], mat_b_rearr[7]);//d = c - (a*b) //Broadcast A43 to A73 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + i + 4)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + i + 5)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l + i + 6)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l + i + 7)); i += cs_l; //Perform mul operation of reciprocal of L(3, 3) element with 4rth row elements of B mat_b_rearr[3] = _mm256_mul_ps(mat_b_rearr[3], mat_a_diag_inv[3]); //(Row4): FMA operations of b4 with elements of indices from (4, 0) uptill (7, 0) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_rearr[3], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_rearr[3], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_rearr[3], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_rearr[3], mat_b_rearr[7]);//d = c - (a*b) //Broadcast A54 to A74 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + i + 5)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + i + 6)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l + i + 7)); i += cs_l; //Perform mul operation of reciprocal of L(4, 4) element with 4rth row elements of B mat_b_rearr[4] = _mm256_mul_ps(mat_b_rearr[4], mat_a_diag_inv[4]); //(Row5): FMA operations of b5 with elements of indices from (5, 0) uptill (7, 0) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_rearr[4], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_rearr[4], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_rearr[4], mat_b_rearr[7]);//d = c - (a*b) //Broadcast A65 to A75 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + i + 6)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + i + 7)); i += cs_l; //Perform mul operation of reciprocal of L(5, 5) element with 5th row elements of B mat_b_rearr[5] = _mm256_mul_ps(mat_b_rearr[5], mat_a_diag_inv[5]); //(Row6): FMA operations of b6 with elements of indices from (6, 0) uptill (7, 0) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_rearr[5], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_rearr[5], mat_b_rearr[7]);//d = c - (a*b) //Broadcast A76 to register mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + i + 7)); //Perform mul operation of reciprocal of L(6, 6) element with 6th row elements of B mat_b_rearr[6] = _mm256_mul_ps(mat_b_rearr[6], mat_a_diag_inv[6]); //(Row7): FMA operations of b7 with elements of index (7, 0) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_rearr[6], mat_b_rearr[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(7, 7) element with 7th row elements of B mat_b_rearr[7] = _mm256_mul_ps(mat_b_rearr[7], mat_a_diag_inv[7]); //////////////////////////////////////////////////////////////////////////////// //Store the computed B columns _mm256_storeu_ps((float *)ptr_b_dup + r, mat_b_rearr[0]); _mm256_storeu_ps((float *)(ptr_b_dup + (cs_b)+r), mat_b_rearr[1]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[0] + r), mat_b_rearr[2]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[1] + r), mat_b_rearr[3]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[2] + r), mat_b_rearr[4]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[3] + r), mat_b_rearr[5]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[4] + r), mat_b_rearr[6]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[5] + r), mat_b_rearr[7]); //printf("writing B => m[%d], n[%d], [%f]\n", j, k, *(ptr_b_dup + k)); k++; } } } //numRows of A ///////////////////loop ends ///////////////////// } static void trsm_XAtB_block_allSmallSizedMatrices_alpha(float *ptr_l, float *ptr_b, int numRows_lb, int numCols_b, int rs_l, int rs_b, int cs_l, int cs_b, float alpha) { float ones = 1.0; int i, i1, i2, i3, i4, j, k, l, r; int cs_b_offset[7]; int cs_l_offset[7]; float *ptr_b_dup, *ptr_l_dup; //57 number of ymm(256 bits) registers used __m256 mat_b_col[8]; __m256 mat_b_rearr[8]; __m256 mat_a_blk_elems[8]; __m256 mat_a_diag_inv[8]; __m256 reciprocal_diags[2]; __m256 alphaReg; reciprocal_diags[0] = _mm256_broadcast_ss((float const *)(&ones)); alphaReg = _mm256_broadcast_ss((float const *)&alpha); // ---> considering that the matrix size is multiple of 16 rows and 8 cols <--- // //L matrix offsets cs_l_offset[0] = (cs_l << 1); cs_l_offset[1] = cs_l + cs_l_offset[0]; cs_l_offset[2] = (cs_l << 2); cs_l_offset[3] = cs_l + cs_l_offset[2]; cs_l_offset[4] = cs_l_offset[0] + cs_l_offset[2]; cs_l_offset[5] = cs_l + cs_l_offset[4]; cs_l_offset[6] = (cs_l_offset[5] + cs_l); //read diag elems of L 16x16 block mat_a_blk_elems[0] = _mm256_loadu_ps((float const *)ptr_l); mat_a_blk_elems[1] = _mm256_loadu_ps((float const *)ptr_l + cs_l); mat_a_blk_elems[2] = _mm256_loadu_ps((float const *)ptr_l + cs_l_offset[0]); mat_a_blk_elems[3] = _mm256_loadu_ps((float const *)ptr_l + cs_l_offset[1]); mat_a_blk_elems[4] = _mm256_loadu_ps((float const *)ptr_l + cs_l_offset[2]); mat_a_blk_elems[5] = _mm256_loadu_ps((float const *)ptr_l + cs_l_offset[3]); mat_a_blk_elems[6] = _mm256_loadu_ps((float const *)ptr_l + cs_l_offset[4]); mat_a_blk_elems[7] = _mm256_loadu_ps((float const *)ptr_l + cs_l_offset[5]); cs_b_offset[0] = (cs_b << 1); cs_b_offset[1] = cs_b + cs_b_offset[0]; cs_b_offset[2] = (cs_b << 2); cs_b_offset[3] = cs_b + cs_b_offset[2]; cs_b_offset[4] = cs_b_offset[0] + cs_b_offset[2]; cs_b_offset[5] = cs_b + cs_b_offset[4]; cs_b_offset[6] = (cs_b_offset[5] + cs_b); reciprocal_diags[1] = reciprocal_diags[0]; //pack first 8 diags together mat_a_diag_inv[0] = _mm256_blend_ps(mat_a_blk_elems[0], mat_a_blk_elems[1], 0xAA);//diag 0,1 mat_a_diag_inv[1] = _mm256_blend_ps(mat_a_blk_elems[2], mat_a_blk_elems[3], 0xAA);//diag 2,3 mat_a_diag_inv[2] = _mm256_blend_ps(mat_a_blk_elems[4], mat_a_blk_elems[5], 0xAA);//diag 4,5 mat_a_diag_inv[3] = _mm256_blend_ps(mat_a_blk_elems[6], mat_a_blk_elems[7], 0xAA);//diag 6,7 mat_a_diag_inv[0] = _mm256_blend_ps(mat_a_diag_inv[0], mat_a_diag_inv[1], 0xCC);//diag 0,1,2,3 mat_a_diag_inv[2] = _mm256_blend_ps(mat_a_diag_inv[2], mat_a_diag_inv[3], 0xCC);//diag 4,5,6,7 mat_a_diag_inv[0] = _mm256_blend_ps(mat_a_diag_inv[0], mat_a_diag_inv[2], 0xF0);//diag 0,1,2,3,4,5,6,7 //reciprocal of diagnal elements 0,1,2,3,4,5,6,7 reciprocal_diags[0] = _mm256_div_ps(reciprocal_diags[0], mat_a_diag_inv[0]); #if 0 //Broadcast A10 to A70 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + 1)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + 2)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l + 3)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l + 4)); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l + 5)); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l + 6)); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l + 7)); //Broadcast A21 to A71 to registers mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 2)); mat_a_blk_elems[8] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 3)); mat_a_blk_elems[9] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 4)); mat_a_blk_elems[10] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 5)); mat_a_blk_elems[11] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 6)); mat_a_blk_elems[12] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 7)); //Broadcast A32 to A72 to registers mat_a_blk_elems[13] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + 3)); mat_a_blk_elems[14] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + 4)); mat_a_blk_elems[15] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + 5)); mat_a_blk_elems[16] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + 6)); mat_a_blk_elems[17] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + 7)); //Broadcast A43 to A73 to registers mat_a_blk_elems[18] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + 4)); mat_a_blk_elems[19] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + 5)); mat_a_blk_elems[20] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + 6)); mat_a_blk_elems[21] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + 7)); //Broadcast A54 to A74 to registers mat_a_blk_elems[22] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[2] + 5)); mat_a_blk_elems[23] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[2] + 6)); mat_a_blk_elems[24] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[2] + 7)); //Broadcast A65 to A75 to registers mat_a_blk_elems[25] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[3] + 6)); mat_a_blk_elems[26] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[3] + 7)); //Broadcast A76 to register mat_a_blk_elems[27] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[4] + 7)); #endif //extract diag a00 from a mat_a_diag_inv[0] = _mm256_permute_ps(reciprocal_diags[0], 0x00); mat_a_diag_inv[0] = _mm256_permute2f128_ps(mat_a_diag_inv[0], mat_a_diag_inv[0], 0x00); //mat_a_diag_inv[0] = _mm256_unpacklo_ps(mat_a_diag_inv[0], mat_a_diag_inv[0]); //extract diag a11 from a mat_a_diag_inv[1] = _mm256_permute_ps(reciprocal_diags[0], 0x55); mat_a_diag_inv[1] = _mm256_permute2f128_ps(mat_a_diag_inv[1], mat_a_diag_inv[1], 0x00); //mat_a_diag_inv[1] = _mm256_unpacklo_ps(mat_a_diag_inv[1], mat_a_diag_inv[1]); //extract diag a22 from a mat_a_diag_inv[2] = _mm256_permute_ps(reciprocal_diags[0], 0xAA); mat_a_diag_inv[2] = _mm256_permute2f128_ps(mat_a_diag_inv[2], mat_a_diag_inv[2], 0x00); //mat_a_diag_inv[2] = _mm256_unpacklo_ps(mat_a_diag_inv[2], mat_a_diag_inv[2]); //extract diag a33 from a mat_a_diag_inv[3] = _mm256_permute_ps(reciprocal_diags[0], 0xFF); mat_a_diag_inv[3] = _mm256_permute2f128_ps(mat_a_diag_inv[3], mat_a_diag_inv[3], 0x00); //mat_a_diag_inv[3] = _mm256_unpacklo_ps(mat_a_diag_inv[3], mat_a_diag_inv[3]); //extract diag a44 from a mat_a_diag_inv[4] = _mm256_permute_ps(reciprocal_diags[0], 0x00); mat_a_diag_inv[4] = _mm256_permute2f128_ps(mat_a_diag_inv[4], mat_a_diag_inv[4], 0x11); //mat_a_diag_inv[4] = _mm256_unpacklo_ps(mat_a_diag_inv[4], mat_a_diag_inv[4]); //extract diag a55 from a mat_a_diag_inv[5] = _mm256_permute_ps(reciprocal_diags[0], 0x55); mat_a_diag_inv[5] = _mm256_permute2f128_ps(mat_a_diag_inv[5], mat_a_diag_inv[5], 0x11); //mat_a_diag_inv[5] = _mm256_unpacklo_ps(mat_a_diag_inv[5], mat_a_diag_inv[5]); //extract diag a66 from a mat_a_diag_inv[6] = _mm256_permute_ps(reciprocal_diags[0], 0xAA); mat_a_diag_inv[6] = _mm256_permute2f128_ps(mat_a_diag_inv[6], mat_a_diag_inv[6], 0x11); //mat_a_diag_inv[6] = _mm256_unpacklo_ps(mat_a_diag_inv[6], mat_a_diag_inv[6]); //extract diag a77 from a mat_a_diag_inv[7] = _mm256_permute_ps(reciprocal_diags[0], 0xFF); mat_a_diag_inv[7] = _mm256_permute2f128_ps(mat_a_diag_inv[7], mat_a_diag_inv[7], 0x11); //mat_a_diag_inv[7] = _mm256_unpacklo_ps(mat_a_diag_inv[7], mat_a_diag_inv[7]); /***************** first set of 8 rows of B processing starts *****************/ ptr_b_dup = ptr_b; i = 0; for (j = 0; j < numCols_b; j += 8) { /////////////////// Complete Upper 8x8 block trsm of B :- upper 8x8 block of B with upper 8x8 block of A //read 8x8 block of B into registers mat_b_col[0] = _mm256_loadu_ps((float const *)ptr_b + i); mat_b_col[1] = _mm256_loadu_ps((float const *)(ptr_b + cs_b + i)); mat_b_col[2] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[0] + i)); mat_b_col[3] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[1] + i)); mat_b_col[4] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[2] + i)); mat_b_col[5] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[3] + i)); mat_b_col[6] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[4] + i)); mat_b_col[7] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[5] + i)); mat_b_col[0] = _mm256_mul_ps(mat_b_col[0], alphaReg); mat_b_col[1] = _mm256_mul_ps(mat_b_col[1], alphaReg); mat_b_col[2] = _mm256_mul_ps(mat_b_col[2], alphaReg); mat_b_col[3] = _mm256_mul_ps(mat_b_col[3], alphaReg); mat_b_col[4] = _mm256_mul_ps(mat_b_col[4], alphaReg); mat_b_col[5] = _mm256_mul_ps(mat_b_col[5], alphaReg); mat_b_col[6] = _mm256_mul_ps(mat_b_col[6], alphaReg); mat_b_col[7] = _mm256_mul_ps(mat_b_col[7], alphaReg); //(Row0): Perform mul operation of reciprocal of L(0,0) element with 1st row elements of B mat_b_col[0] = _mm256_mul_ps(mat_b_col[0], mat_a_diag_inv[0]); mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + 1)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + 2)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l + 3)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l + 4)); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l + 5)); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l + 6)); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l + 7)); //(Row1): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_col[1] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[0], mat_b_col[1]);//d = c - (a*b) mat_b_col[2] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[0], mat_b_col[2]);//d = c - (a*b) mat_b_col[3] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[0], mat_b_col[3]);//d = c - (a*b) mat_b_col[4] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[0], mat_b_col[4]);//d = c - (a*b) mat_b_col[5] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[0], mat_b_col[5]);//d = c - (a*b) mat_b_col[6] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[0], mat_b_col[6]);//d = c - (a*b) mat_b_col[7] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_col[0], mat_b_col[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(1,1) element with 2nd row elements of B mat_b_col[1] = _mm256_mul_ps(mat_b_col[1], mat_a_diag_inv[1]); mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 2)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 3)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 4)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 5)); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 6)); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 7)); //(Row2): FMA operations of b2 with elements of indices from (2, 0) uptill (7, 0) mat_b_col[2] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[1], mat_b_col[2]);//d = c - (a*b) mat_b_col[3] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[1], mat_b_col[3]);//d = c - (a*b) mat_b_col[4] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[1], mat_b_col[4]);//d = c - (a*b) mat_b_col[5] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[1], mat_b_col[5]);//d = c - (a*b) mat_b_col[6] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[1], mat_b_col[6]);//d = c - (a*b) mat_b_col[7] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[1], mat_b_col[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(2, 2) element with 3rd row elements of B mat_b_col[2] = _mm256_mul_ps(mat_b_col[2], mat_a_diag_inv[2]); mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + 3)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + 4)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + 5)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + 6)); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + 7)); //(Row3): FMA operations of b3 with elements of indices from (3, 0) uptill (7, 0) mat_b_col[3] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[2], mat_b_col[3]);//d = c - (a*b) mat_b_col[4] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[2], mat_b_col[4]);//d = c - (a*b) mat_b_col[5] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[2], mat_b_col[5]);//d = c - (a*b) mat_b_col[6] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[2], mat_b_col[6]);//d = c - (a*b) mat_b_col[7] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[2], mat_b_col[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(3, 3) element with 4rth row elements of B mat_b_col[3] = _mm256_mul_ps(mat_b_col[3], mat_a_diag_inv[3]); mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + 4)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + 5)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + 6)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + 7)); //(Row4): FMA operations of b4 with elements of indices from (4, 0) uptill (7, 0) mat_b_col[4] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[3], mat_b_col[4]);//d = c - (a*b) mat_b_col[5] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[3], mat_b_col[5]);//d = c - (a*b) mat_b_col[6] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[3], mat_b_col[6]);//d = c - (a*b) mat_b_col[7] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[3], mat_b_col[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(4, 4) element with 4rth row elements of B mat_b_col[4] = _mm256_mul_ps(mat_b_col[4], mat_a_diag_inv[4]); mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[2] + 5)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[2] + 6)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[2] + 7)); //(Row5): FMA operations of b5 with elements of indices from (5, 0) uptill (7, 0) mat_b_col[5] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[4], mat_b_col[5]);//d = c - (a*b) mat_b_col[6] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[4], mat_b_col[6]);//d = c - (a*b) mat_b_col[7] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[4], mat_b_col[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(5, 5) element with 5th row elements of B mat_b_col[5] = _mm256_mul_ps(mat_b_col[5], mat_a_diag_inv[5]); mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[3] + 6)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[3] + 7)); //(Row6): FMA operations of b6 with elements of indices from (6, 0) uptill (7, 0) mat_b_col[6] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[5], mat_b_col[6]);//d = c - (a*b) mat_b_col[7] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[5], mat_b_col[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(6, 6) element with 6th row elements of B mat_b_col[6] = _mm256_mul_ps(mat_b_col[6], mat_a_diag_inv[6]); mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[4] + 7)); //(Row7): FMA operations of b7 with elements of index (7, 0) mat_b_col[7] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[6], mat_b_col[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(7, 7) element with 7th row elements of B mat_b_col[7] = _mm256_mul_ps(mat_b_col[7], mat_a_diag_inv[7]); //////////////////////////////////////////////////////////////////////////////// //Store the computed B columns _mm256_storeu_ps((float *)ptr_b_dup, mat_b_col[0]); _mm256_storeu_ps((float *)(ptr_b_dup + (cs_b)), mat_b_col[1]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[0]), mat_b_col[2]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[1]), mat_b_col[3]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[2]), mat_b_col[4]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[3]), mat_b_col[5]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[4]), mat_b_col[6]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[5]), mat_b_col[7]); //i += cs_b_offset[6]; //ptr_b_dup += cs_b_offset[6]; i += 8; ptr_b_dup += 8; } //c = 0; /***************** first set of 8 cols of B processing done *****************/ ptr_b_dup = ptr_b; i3 = 0; i1 = 0; //Start loop for cols of B to be processed in size of blk_width for (j = 8; j < numRows_lb; j += 8)//m :- 8x8 block row { ptr_l += 8; //ptr_b += j; //ptr_b_dup += 8; ptr_b_dup += cs_b_offset[6]; i1 += cs_b_offset[6]; //Read next 8x8 block of A to get diag elements i3 += cs_l_offset[6]; mat_a_blk_elems[0] = _mm256_loadu_ps((float const *)ptr_l + i3); mat_a_blk_elems[1] = _mm256_loadu_ps((float const *)ptr_l + i3 + cs_l); mat_a_blk_elems[2] = _mm256_loadu_ps((float const *)ptr_l + i3 + cs_l_offset[0]); mat_a_blk_elems[3] = _mm256_loadu_ps((float const *)ptr_l + i3 + cs_l_offset[1]); mat_a_blk_elems[4] = _mm256_loadu_ps((float const *)ptr_l + i3 + cs_l_offset[2]); mat_a_blk_elems[5] = _mm256_loadu_ps((float const *)ptr_l + i3 + cs_l_offset[3]); mat_a_blk_elems[6] = _mm256_loadu_ps((float const *)ptr_l + i3 + cs_l_offset[4]); mat_a_blk_elems[7] = _mm256_loadu_ps((float const *)ptr_l + i3 + cs_l_offset[5]); //pack 8 diags of A together reciprocal_diags[0] = reciprocal_diags[1]; mat_a_diag_inv[0] = _mm256_blend_ps(mat_a_blk_elems[0], mat_a_blk_elems[1], 0xAA);//diag 0,1 mat_a_diag_inv[1] = _mm256_blend_ps(mat_a_blk_elems[2], mat_a_blk_elems[3], 0xAA);//diag 2,3 mat_a_diag_inv[2] = _mm256_blend_ps(mat_a_blk_elems[4], mat_a_blk_elems[5], 0xAA);//diag 4,5 mat_a_diag_inv[3] = _mm256_blend_ps(mat_a_blk_elems[6], mat_a_blk_elems[7], 0xAA);//diag 6,7 mat_a_diag_inv[0] = _mm256_blend_ps(mat_a_diag_inv[0], mat_a_diag_inv[1], 0xCC);//diag 0,1,2,3 mat_a_diag_inv[2] = _mm256_blend_ps(mat_a_diag_inv[2], mat_a_diag_inv[3], 0xCC);//diag 4,5,6,7 mat_a_diag_inv[0] = _mm256_blend_ps(mat_a_diag_inv[0], mat_a_diag_inv[2], 0xF0);//diag 0,1,2,3,4,5,6,7 //reciprocal of diagnal elements of A :- 0,1,2,3,4,5,6,7 reciprocal_diags[0] = _mm256_div_ps(reciprocal_diags[0], mat_a_diag_inv[0]); //extract diag a00 from a mat_a_diag_inv[0] = _mm256_permute_ps(reciprocal_diags[0], 0x00); mat_a_diag_inv[0] = _mm256_permute2f128_ps(mat_a_diag_inv[0], mat_a_diag_inv[0], 0x00); //mat_a_diag_inv2[0] = _mm256_unpacklo_ps(mat_a_diag_inv2[0], mat_a_diag_inv2[0]); //extract diag a11 from a mat_a_diag_inv[1] = _mm256_permute_ps(reciprocal_diags[0], 0x55); mat_a_diag_inv[1] = _mm256_permute2f128_ps(mat_a_diag_inv[1], mat_a_diag_inv[1], 0x00); //mat_a_diag_inv[1] = _mm256_unpacklo_ps(mat_a_diag_inv[1], mat_a_diag_inv[1]); //extract diag a22 from a mat_a_diag_inv[2] = _mm256_permute_ps(reciprocal_diags[0], 0xAA); mat_a_diag_inv[2] = _mm256_permute2f128_ps(mat_a_diag_inv[2], mat_a_diag_inv[2], 0x00); //mat_a_diag_inv[2] = _mm256_unpacklo_ps(mat_a_diag_inv[2], mat_a_diag_inv[2]); //extract diag a33 from a mat_a_diag_inv[3] = _mm256_permute_ps(reciprocal_diags[0], 0xFF); mat_a_diag_inv[3] = _mm256_permute2f128_ps(mat_a_diag_inv[3], mat_a_diag_inv[3], 0x00); //mat_a_diag_inv[3] = _mm256_unpacklo_ps(mat_a_diag_inv[3], mat_a_diag_inv[3]); //extract diag a44 from a mat_a_diag_inv[4] = _mm256_permute_ps(reciprocal_diags[0], 0x00); mat_a_diag_inv[4] = _mm256_permute2f128_ps(mat_a_diag_inv[4], mat_a_diag_inv[4], 0x11); //mat_a_diag_inv[4] = _mm256_unpacklo_ps(mat_a_diag_inv[4], mat_a_diag_inv[4]); //extract diag a55 from a mat_a_diag_inv[5] = _mm256_permute_ps(reciprocal_diags[0], 0x55); mat_a_diag_inv[5] = _mm256_permute2f128_ps(mat_a_diag_inv[5], mat_a_diag_inv[5], 0x11); //mat_a_diag_inv[5] = _mm256_unpacklo_ps(mat_a_diag_inv[5], mat_a_diag_inv[5]); //extract diag a66 from a mat_a_diag_inv[6] = _mm256_permute_ps(reciprocal_diags[0], 0xAA); mat_a_diag_inv[6] = _mm256_permute2f128_ps(mat_a_diag_inv[6], mat_a_diag_inv[6], 0x11); //mat_a_diag_inv[6] = _mm256_unpacklo_ps(mat_a_diag_inv[6], mat_a_diag_inv[6]); //extract diag a77 from a mat_a_diag_inv[7] = _mm256_permute_ps(reciprocal_diags[0], 0xFF); mat_a_diag_inv[7] = _mm256_permute2f128_ps(mat_a_diag_inv[7], mat_a_diag_inv[7], 0x11); //mat_a_diag_inv[7] = _mm256_unpacklo_ps(mat_a_diag_inv[7], mat_a_diag_inv[7]); for (r = 0; r < numCols_b; r += GEMM_BLK_V1) { #if GEMM_ACCUM_A i = i1 + r; //Read 8 cols of B columns of Block-to-be-solved mat_b_rearr[0] = _mm256_loadu_ps((float const *)ptr_b + i); mat_b_rearr[1] = _mm256_loadu_ps((float const *)(ptr_b + cs_b + i)); mat_b_rearr[2] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[0] + i)); mat_b_rearr[3] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[1] + i)); mat_b_rearr[4] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[2] + i)); mat_b_rearr[5] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[3] + i)); mat_b_rearr[6] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[4] + i)); mat_b_rearr[7] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[5] + i)); mat_b_rearr[0] = _mm256_mul_ps(mat_b_rearr[0], alphaReg); mat_b_rearr[1] = _mm256_mul_ps(mat_b_rearr[1], alphaReg); mat_b_rearr[2] = _mm256_mul_ps(mat_b_rearr[2], alphaReg); mat_b_rearr[3] = _mm256_mul_ps(mat_b_rearr[3], alphaReg); mat_b_rearr[4] = _mm256_mul_ps(mat_b_rearr[4], alphaReg); mat_b_rearr[5] = _mm256_mul_ps(mat_b_rearr[5], alphaReg); mat_b_rearr[6] = _mm256_mul_ps(mat_b_rearr[6], alphaReg); mat_b_rearr[7] = _mm256_mul_ps(mat_b_rearr[7], alphaReg); #endif i = 0; i2 = 0; for (l = 0; l < j; l += 8) // move across m { //for (k = 0; k < numCols_b; k += 8) // move across n for the same value of l (index of m) { /////////////////// Partial Lower 8x8 block trsm of B ptr_l_dup = ptr_l; i4 = i2 + r; //Read current 8 cols of B columns from specified 8x8 current-block of B mat_b_col[0] = _mm256_loadu_ps((float const *)ptr_b + i4); mat_b_col[1] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b)); mat_b_col[2] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b_offset[0])); mat_b_col[3] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b_offset[1])); mat_b_col[4] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b_offset[2])); mat_b_col[5] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b_offset[3])); mat_b_col[6] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b_offset[4])); mat_b_col[7] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b_offset[5])); //Broadcast A8,0 to A15,0 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 1)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 2)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 3)); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 4)); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 5)); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 6)); mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 7)); i4 = k >> 3; ptr_l_dup += cs_l; #if GEMM_ACCUM_A //(Row8): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[0] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[0], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[0], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[0], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[0], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[0], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[0], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_col[0], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[7], mat_b_col[0], mat_b_rearr[7]);//d = c - (a*b) #else mat_b_rearr[0] = _mm256_mul_ps(mat_a_blk_elems[0], mat_b_col[0]); mat_b_rearr[1] = _mm256_mul_ps(mat_a_blk_elems[1], mat_b_col[0]); mat_b_rearr[2] = _mm256_mul_ps(mat_a_blk_elems[2], mat_b_col[0]); mat_b_rearr[3] = _mm256_mul_ps(mat_a_blk_elems[3], mat_b_col[0]); mat_b_rearr[4] = _mm256_mul_ps(mat_a_blk_elems[4], mat_b_col[0]); mat_b_rearr[5] = _mm256_mul_ps(mat_a_blk_elems[5], mat_b_col[0]); mat_b_rearr[6] = _mm256_mul_ps(mat_a_blk_elems[6], mat_b_col[0]); mat_b_rearr[7] = _mm256_mul_ps(mat_a_blk_elems[7], mat_b_col[0]); #endif //Broadcast A21 to A71 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 1)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 2)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 3)); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 4)); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 5)); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 6)); mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 7)); ptr_l_dup += cs_l; #if GEMM_ACCUM_A //(Row9): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[0] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[1], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[1], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[1], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[1], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[1], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[1], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_col[1], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[7], mat_b_col[1], mat_b_rearr[7]);//d = c - (a*b) #else mat_b_rearr[0] = _mm256_fmadd_ps(mat_a_blk_elems[0], mat_b_col[1], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fmadd_ps(mat_a_blk_elems[1], mat_b_col[1], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fmadd_ps(mat_a_blk_elems[2], mat_b_col[1], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fmadd_ps(mat_a_blk_elems[3], mat_b_col[1], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fmadd_ps(mat_a_blk_elems[4], mat_b_col[1], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fmadd_ps(mat_a_blk_elems[5], mat_b_col[1], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fmadd_ps(mat_a_blk_elems[6], mat_b_col[1], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fmadd_ps(mat_a_blk_elems[7], mat_b_col[1], mat_b_rearr[7]);//d = c - (a*b) #endif //Broadcast A8,2 to A15,2 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 1)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 2)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 3)); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 4)); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 5)); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 6)); mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 7)); ptr_l_dup += cs_l; #if GEMM_ACCUM_A //(Row10): FMA operations of b2 with elements of indices from (2, 0) uptill (7, 0) mat_b_rearr[0] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[2], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[2], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[2], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[2], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[2], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[2], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_col[2], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[7], mat_b_col[2], mat_b_rearr[7]);//d = c - (a*b) #else mat_b_rearr[0] = _mm256_fmadd_ps(mat_a_blk_elems[0], mat_b_col[2], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fmadd_ps(mat_a_blk_elems[1], mat_b_col[2], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fmadd_ps(mat_a_blk_elems[2], mat_b_col[2], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fmadd_ps(mat_a_blk_elems[3], mat_b_col[2], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fmadd_ps(mat_a_blk_elems[4], mat_b_col[2], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fmadd_ps(mat_a_blk_elems[5], mat_b_col[2], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fmadd_ps(mat_a_blk_elems[6], mat_b_col[2], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fmadd_ps(mat_a_blk_elems[7], mat_b_col[2], mat_b_rearr[7]);//d = c - (a*b) #endif //Broadcast A8,3 to A15,3 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 1)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 2)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 3)); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 4)); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 5)); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 6)); mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 7)); ptr_l_dup += cs_l; #if GEMM_ACCUM_A //(Row11): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[0] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[3], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[3], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[3], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[3], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[3], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[3], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_col[3], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[7], mat_b_col[3], mat_b_rearr[7]);//d = c - (a*b) #else mat_b_rearr[0] = _mm256_fmadd_ps(mat_a_blk_elems[0], mat_b_col[3], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fmadd_ps(mat_a_blk_elems[1], mat_b_col[3], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fmadd_ps(mat_a_blk_elems[2], mat_b_col[3], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fmadd_ps(mat_a_blk_elems[3], mat_b_col[3], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fmadd_ps(mat_a_blk_elems[4], mat_b_col[3], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fmadd_ps(mat_a_blk_elems[5], mat_b_col[3], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fmadd_ps(mat_a_blk_elems[6], mat_b_col[3], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fmadd_ps(mat_a_blk_elems[7], mat_b_col[3], mat_b_rearr[7]);//d = c - (a*b) #endif //Broadcast A8,4 to A15,4 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 1)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 2)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 3)); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 4)); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 5)); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 6)); mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 7)); ptr_l_dup += cs_l; #if GEMM_ACCUM_A //(Row12): FMA operations of b2 with elements of indices from (2, 0) uptill (7, 0) mat_b_rearr[0] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[4], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[4], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[4], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[4], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[4], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[4], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_col[4], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[7], mat_b_col[4], mat_b_rearr[7]);//d = c - (a*b) #else mat_b_rearr[0] = _mm256_fmadd_ps(mat_a_blk_elems[0], mat_b_col[4], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fmadd_ps(mat_a_blk_elems[1], mat_b_col[4], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fmadd_ps(mat_a_blk_elems[2], mat_b_col[4], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fmadd_ps(mat_a_blk_elems[3], mat_b_col[4], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fmadd_ps(mat_a_blk_elems[4], mat_b_col[4], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fmadd_ps(mat_a_blk_elems[5], mat_b_col[4], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fmadd_ps(mat_a_blk_elems[6], mat_b_col[4], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fmadd_ps(mat_a_blk_elems[7], mat_b_col[4], mat_b_rearr[7]);//d = c - (a*b) #endif //Broadcast A8,5 to A15,5 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 1)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 2)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 3)); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 4)); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 5)); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 6)); mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 7)); ptr_l_dup += cs_l; #if GEMM_ACCUM_A //(Row13): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[0] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[5], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[5], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[5], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[5], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[5], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[5], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_col[5], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[7], mat_b_col[5], mat_b_rearr[7]);//d = c - (a*b) #else mat_b_rearr[0] = _mm256_fmadd_ps(mat_a_blk_elems[0], mat_b_col[5], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fmadd_ps(mat_a_blk_elems[1], mat_b_col[5], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fmadd_ps(mat_a_blk_elems[2], mat_b_col[5], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fmadd_ps(mat_a_blk_elems[3], mat_b_col[5], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fmadd_ps(mat_a_blk_elems[4], mat_b_col[5], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fmadd_ps(mat_a_blk_elems[5], mat_b_col[5], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fmadd_ps(mat_a_blk_elems[6], mat_b_col[5], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fmadd_ps(mat_a_blk_elems[7], mat_b_col[5], mat_b_rearr[7]);//d = c - (a*b) #endif //Broadcast A8,6 to A15,6 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 1)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 2)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 3)); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 4)); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 5)); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 6)); mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 7)); ptr_l_dup += cs_l; #if GEMM_ACCUM_A //(Row14): FMA operations of b2 with elements of indices from (2, 0) uptill (7, 0) mat_b_rearr[0] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[6], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[6], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[6], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[6], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[6], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[6], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_col[6], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[7], mat_b_col[6], mat_b_rearr[7]);//d = c - (a*b) #else mat_b_rearr[0] = _mm256_fmadd_ps(mat_a_blk_elems[0], mat_b_col[6], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fmadd_ps(mat_a_blk_elems[1], mat_b_col[6], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fmadd_ps(mat_a_blk_elems[2], mat_b_col[6], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fmadd_ps(mat_a_blk_elems[3], mat_b_col[6], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fmadd_ps(mat_a_blk_elems[4], mat_b_col[6], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fmadd_ps(mat_a_blk_elems[5], mat_b_col[6], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fmadd_ps(mat_a_blk_elems[6], mat_b_col[6], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fmadd_ps(mat_a_blk_elems[7], mat_b_col[6], mat_b_rearr[7]);//d = c - (a*b) #endif //Broadcast A8,7 to A15,7 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 1)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 2)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 3)); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 4)); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 5)); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 6)); mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 7)); ptr_l_dup += cs_l; #if GEMM_ACCUM_A //(Row15): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[0] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[7], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[7], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[7], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[7], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[7], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[7], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_col[7], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[7], mat_b_col[7], mat_b_rearr[7]);//d = c - (a*b) #else mat_b_rearr[0] = _mm256_fmadd_ps(mat_a_blk_elems[0], mat_b_col[7], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fmadd_ps(mat_a_blk_elems[1], mat_b_col[7], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fmadd_ps(mat_a_blk_elems[2], mat_b_col[7], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fmadd_ps(mat_a_blk_elems[3], mat_b_col[7], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fmadd_ps(mat_a_blk_elems[4], mat_b_col[7], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fmadd_ps(mat_a_blk_elems[5], mat_b_col[7], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fmadd_ps(mat_a_blk_elems[6], mat_b_col[7], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fmadd_ps(mat_a_blk_elems[7], mat_b_col[7], mat_b_rearr[7]);//d = c - (a*b) #endif //end loop of cols } i2 += cs_b_offset[6]; i += cs_l_offset[6]; } //trsm solve k = 0; //for (i2 = 0; i2 < numCols_b; i2 += 8) { i2 = i1 + r; /////////////////// Complete Lower 8x8 block trsm of B :- lower 8x8 block of B with lower right 8x8 block of A #if !GEMM_ACCUM_A //Read 8 cols of B columns of Block-to-be-solved mat_b_col[0] = _mm256_loadu_ps((float const *)ptr_b + i2); mat_b_col[1] = _mm256_loadu_ps((float const *)(ptr_b + cs_b + i2)); mat_b_col[2] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[0] + i2)); mat_b_col[3] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[1] + i2)); mat_b_col[4] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[2] + i2)); mat_b_col[5] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[3] + i2)); mat_b_col[6] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[4] + i2)); mat_b_col[7] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[5] + i2)); mat_b_col[0] = _mm256_mul_ps(mat_b_col[0], alphaReg); mat_b_col[1] = _mm256_mul_ps(mat_b_col[1], alphaReg); mat_b_col[2] = _mm256_mul_ps(mat_b_col[2], alphaReg); mat_b_col[3] = _mm256_mul_ps(mat_b_col[3], alphaReg); mat_b_col[4] = _mm256_mul_ps(mat_b_col[4], alphaReg); mat_b_col[5] = _mm256_mul_ps(mat_b_col[5], alphaReg); mat_b_col[6] = _mm256_mul_ps(mat_b_col[6], alphaReg); mat_b_col[7] = _mm256_mul_ps(mat_b_col[7], alphaReg); #endif //Broadcast A10 to A70 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + i + 1)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + i + 2)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l + i + 3)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l + i + 4)); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l + i + 5)); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l + i + 6)); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l + i + 7)); i += cs_l; #if GEMM_ACCUM_A //(Row0): Perform mul operation of reciprocal of L(0,0) element with 1st row elements of B mat_b_rearr[0] = _mm256_mul_ps(mat_b_rearr[0], mat_a_diag_inv[0]); #else mat_b_rearr[0] = _mm256_sub_ps(mat_b_col[0], mat_b_rearr[0]); mat_b_rearr[0] = _mm256_mul_ps(mat_b_rearr[0], mat_a_diag_inv[0]); #endif #if GEMM_ACCUM_A mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_rearr[0], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_rearr[0], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_rearr[0], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_rearr[0], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_rearr[0], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_rearr[0], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_rearr[0], mat_b_rearr[7]);//d = c - (a*b) #else mat_b_rearr[1] = _mm256_sub_ps(mat_b_col[1], mat_b_rearr[1]); mat_b_rearr[2] = _mm256_sub_ps(mat_b_col[2], mat_b_rearr[2]); mat_b_rearr[3] = _mm256_sub_ps(mat_b_col[3], mat_b_rearr[3]); mat_b_rearr[4] = _mm256_sub_ps(mat_b_col[4], mat_b_rearr[4]); mat_b_rearr[5] = _mm256_sub_ps(mat_b_col[5], mat_b_rearr[5]); mat_b_rearr[6] = _mm256_sub_ps(mat_b_col[6], mat_b_rearr[6]); mat_b_rearr[7] = _mm256_sub_ps(mat_b_col[7], mat_b_rearr[7]); //(Row1): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_rearr[0], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_rearr[0], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_rearr[0], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_rearr[0], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_rearr[0], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_rearr[0], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_rearr[0], mat_b_rearr[7]);//d = c - (a*b) #endif //Broadcast A21 to A71 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + i + 2)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + i + 3)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l + i + 4)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l + i + 5)); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l + i + 6)); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l + i + 7)); i += cs_l; //Perform mul operation of reciprocal of L(1,1) element with 2nd row elements of B mat_b_rearr[1] = _mm256_mul_ps(mat_b_rearr[1], mat_a_diag_inv[1]); //(Row2): FMA operations of b2 with elements of indices from (2, 0) uptill (7, 0) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_rearr[1], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_rearr[1], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_rearr[1], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_rearr[1], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_rearr[1], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_rearr[1], mat_b_rearr[7]);//d = c - (a*b) //Broadcast A32 to A72 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + i + 3)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + i + 4)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l + i + 5)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l + i + 6)); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l + i + 7)); i += cs_l; //Perform mul operation of reciprocal of L(2, 2) element with 3rd row elements of B mat_b_rearr[2] = _mm256_mul_ps(mat_b_rearr[2], mat_a_diag_inv[2]); //(Row3): FMA operations of b3 with elements of indices from (3, 0) uptill (7, 0) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_rearr[2], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_rearr[2], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_rearr[2], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_rearr[2], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_rearr[2], mat_b_rearr[7]);//d = c - (a*b) //Broadcast A43 to A73 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + i + 4)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + i + 5)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l + i + 6)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l + i + 7)); i += cs_l; //Perform mul operation of reciprocal of L(3, 3) element with 4rth row elements of B mat_b_rearr[3] = _mm256_mul_ps(mat_b_rearr[3], mat_a_diag_inv[3]); //(Row4): FMA operations of b4 with elements of indices from (4, 0) uptill (7, 0) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_rearr[3], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_rearr[3], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_rearr[3], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_rearr[3], mat_b_rearr[7]);//d = c - (a*b) //Broadcast A54 to A74 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + i + 5)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + i + 6)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l + i + 7)); i += cs_l; //Perform mul operation of reciprocal of L(4, 4) element with 4rth row elements of B mat_b_rearr[4] = _mm256_mul_ps(mat_b_rearr[4], mat_a_diag_inv[4]); //(Row5): FMA operations of b5 with elements of indices from (5, 0) uptill (7, 0) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_rearr[4], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_rearr[4], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_rearr[4], mat_b_rearr[7]);//d = c - (a*b) //Broadcast A65 to A75 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + i + 6)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + i + 7)); i += cs_l; //Perform mul operation of reciprocal of L(5, 5) element with 5th row elements of B mat_b_rearr[5] = _mm256_mul_ps(mat_b_rearr[5], mat_a_diag_inv[5]); //(Row6): FMA operations of b6 with elements of indices from (6, 0) uptill (7, 0) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_rearr[5], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_rearr[5], mat_b_rearr[7]);//d = c - (a*b) //Broadcast A76 to register mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + i + 7)); //Perform mul operation of reciprocal of L(6, 6) element with 6th row elements of B mat_b_rearr[6] = _mm256_mul_ps(mat_b_rearr[6], mat_a_diag_inv[6]); //(Row7): FMA operations of b7 with elements of index (7, 0) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_rearr[6], mat_b_rearr[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(7, 7) element with 7th row elements of B mat_b_rearr[7] = _mm256_mul_ps(mat_b_rearr[7], mat_a_diag_inv[7]); //////////////////////////////////////////////////////////////////////////////// //Store the computed B columns _mm256_storeu_ps((float *)ptr_b_dup + r, mat_b_rearr[0]); _mm256_storeu_ps((float *)(ptr_b_dup + (cs_b)+r), mat_b_rearr[1]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[0] + r), mat_b_rearr[2]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[1] + r), mat_b_rearr[3]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[2] + r), mat_b_rearr[4]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[3] + r), mat_b_rearr[5]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[4] + r), mat_b_rearr[6]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[5] + r), mat_b_rearr[7]); //printf("writing B => m[%d], n[%d], [%f]\n", j, k, *(ptr_b_dup + k)); k++; } } } //numRows of A ///////////////////loop ends ///////////////////// } static void trsm_XAtB_block_allSmallSizedMatrices_unitDiag(float *ptr_l, float *ptr_b, int numRows_lb, int numCols_b, int rs_l, int rs_b, int cs_l, int cs_b) { //float ones = 1.0; int i, i1, i2, i3, i4, j, k, l, r; int cs_b_offset[7]; int cs_l_offset[7]; float *ptr_b_dup, *ptr_l_dup; //57 number of ymm(256 bits) registers used __m256 mat_b_col[8]; __m256 mat_b_rearr[8]; __m256 mat_a_blk_elems[8]; //__m256 mat_a_diag_inv[8]; //__m256 reciprocal_diags[2]; // ---> considering that the matrix size is multiple of 16 rows and 8 cols <--- // //L matrix offsets cs_l_offset[0] = (cs_l << 1); cs_l_offset[1] = cs_l + cs_l_offset[0]; cs_l_offset[2] = (cs_l << 2); cs_l_offset[3] = cs_l + cs_l_offset[2]; cs_l_offset[4] = cs_l_offset[0] + cs_l_offset[2]; cs_l_offset[5] = cs_l + cs_l_offset[4]; cs_l_offset[6] = (cs_l_offset[5] + cs_l); cs_b_offset[0] = (cs_b << 1); cs_b_offset[1] = cs_b + cs_b_offset[0]; cs_b_offset[2] = (cs_b << 2); cs_b_offset[3] = cs_b + cs_b_offset[2]; cs_b_offset[4] = cs_b_offset[0] + cs_b_offset[2]; cs_b_offset[5] = cs_b + cs_b_offset[4]; cs_b_offset[6] = (cs_b_offset[5] + cs_b); /***************** first set of 8 rows of B processing starts *****************/ ptr_b_dup = ptr_b; i = 0; for (j = 0; j < numCols_b; j += 8) { /////////////////// Complete Upper 8x8 block trsm of B :- upper 8x8 block of B with upper 8x8 block of A //read 8x8 block of B into registers mat_b_col[0] = _mm256_loadu_ps((float const *)ptr_b + i); mat_b_col[1] = _mm256_loadu_ps((float const *)(ptr_b + cs_b + i)); mat_b_col[2] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[0] + i)); mat_b_col[3] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[1] + i)); mat_b_col[4] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[2] + i)); mat_b_col[5] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[3] + i)); mat_b_col[6] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[4] + i)); mat_b_col[7] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[5] + i)); //(Row0) mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + 1)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + 2)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l + 3)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l + 4)); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l + 5)); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l + 6)); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l + 7)); //(Row1): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_col[1] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[0], mat_b_col[1]);//d = c - (a*b) mat_b_col[2] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[0], mat_b_col[2]);//d = c - (a*b) mat_b_col[3] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[0], mat_b_col[3]);//d = c - (a*b) mat_b_col[4] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[0], mat_b_col[4]);//d = c - (a*b) mat_b_col[5] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[0], mat_b_col[5]);//d = c - (a*b) mat_b_col[6] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[0], mat_b_col[6]);//d = c - (a*b) mat_b_col[7] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_col[0], mat_b_col[7]);//d = c - (a*b) mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 2)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 3)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 4)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 5)); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 6)); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 7)); //(Row2): FMA operations of b2 with elements of indices from (2, 0) uptill (7, 0) mat_b_col[2] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[1], mat_b_col[2]);//d = c - (a*b) mat_b_col[3] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[1], mat_b_col[3]);//d = c - (a*b) mat_b_col[4] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[1], mat_b_col[4]);//d = c - (a*b) mat_b_col[5] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[1], mat_b_col[5]);//d = c - (a*b) mat_b_col[6] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[1], mat_b_col[6]);//d = c - (a*b) mat_b_col[7] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[1], mat_b_col[7]);//d = c - (a*b) mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + 3)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + 4)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + 5)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + 6)); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + 7)); //(Row3): FMA operations of b3 with elements of indices from (3, 0) uptill (7, 0) mat_b_col[3] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[2], mat_b_col[3]);//d = c - (a*b) mat_b_col[4] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[2], mat_b_col[4]);//d = c - (a*b) mat_b_col[5] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[2], mat_b_col[5]);//d = c - (a*b) mat_b_col[6] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[2], mat_b_col[6]);//d = c - (a*b) mat_b_col[7] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[2], mat_b_col[7]);//d = c - (a*b) mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + 4)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + 5)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + 6)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + 7)); //(Row4): FMA operations of b4 with elements of indices from (4, 0) uptill (7, 0) mat_b_col[4] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[3], mat_b_col[4]);//d = c - (a*b) mat_b_col[5] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[3], mat_b_col[5]);//d = c - (a*b) mat_b_col[6] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[3], mat_b_col[6]);//d = c - (a*b) mat_b_col[7] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[3], mat_b_col[7]);//d = c - (a*b) mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[2] + 5)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[2] + 6)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[2] + 7)); //(Row5): FMA operations of b5 with elements of indices from (5, 0) uptill (7, 0) mat_b_col[5] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[4], mat_b_col[5]);//d = c - (a*b) mat_b_col[6] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[4], mat_b_col[6]);//d = c - (a*b) mat_b_col[7] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[4], mat_b_col[7]);//d = c - (a*b) mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[3] + 6)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[3] + 7)); //(Row6): FMA operations of b6 with elements of indices from (6, 0) uptill (7, 0) mat_b_col[6] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[5], mat_b_col[6]);//d = c - (a*b) mat_b_col[7] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[5], mat_b_col[7]);//d = c - (a*b) mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[4] + 7)); //(Row7): FMA operations of b7 with elements of index (7, 0) mat_b_col[7] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[6], mat_b_col[7]);//d = c - (a*b) //////////////////////////////////////////////////////////////////////////////// //Store the computed B columns _mm256_storeu_ps((float *)ptr_b_dup, mat_b_col[0]); _mm256_storeu_ps((float *)(ptr_b_dup + (cs_b)), mat_b_col[1]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[0]), mat_b_col[2]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[1]), mat_b_col[3]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[2]), mat_b_col[4]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[3]), mat_b_col[5]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[4]), mat_b_col[6]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[5]), mat_b_col[7]); //i += cs_b_offset[6]; //ptr_b_dup += cs_b_offset[6]; i += 8; ptr_b_dup += 8; } //c = 0; /***************** first set of 8 cols of B processing done *****************/ ptr_b_dup = ptr_b; i3 = 0; i1 = 0; //Start loop for cols of B to be processed in size of blk_width for (j = 8; j < numRows_lb; j += 8)//m :- 8x8 block row { ptr_l += 8; //ptr_b += j; //ptr_b_dup += 8; ptr_b_dup += cs_b_offset[6]; i1 += cs_b_offset[6]; i3 += cs_l_offset[6]; i = 0; i2 = 0; for (r = 0; r < numCols_b; r += GEMM_BLK_V1) { #if GEMM_ACCUM_A i = i1 + r; //Read 8 cols of B columns of Block-to-be-solved mat_b_rearr[0] = _mm256_loadu_ps((float const *)ptr_b + i); mat_b_rearr[1] = _mm256_loadu_ps((float const *)(ptr_b + cs_b + i)); mat_b_rearr[2] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[0] + i)); mat_b_rearr[3] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[1] + i)); mat_b_rearr[4] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[2] + i)); mat_b_rearr[5] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[3] + i)); mat_b_rearr[6] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[4] + i)); mat_b_rearr[7] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[5] + i)); #endif i = 0; i2 = 0; for (l = 0; l < j; l += 8) // move across m { //for (k = 0; k < numCols_b; k += 8) // move across n for the same value of l (index of m) { /////////////////// Partial Lower 8x8 block trsm of B ptr_l_dup = ptr_l; i4 = i2 + r; //Read current 8 cols of B columns from specified 8x8 current-block of B mat_b_col[0] = _mm256_loadu_ps((float const *)ptr_b + i4); mat_b_col[1] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b)); mat_b_col[2] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b_offset[0])); mat_b_col[3] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b_offset[1])); mat_b_col[4] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b_offset[2])); mat_b_col[5] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b_offset[3])); mat_b_col[6] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b_offset[4])); mat_b_col[7] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b_offset[5])); //Broadcast A8,0 to A15,0 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 1)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 2)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 3)); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 4)); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 5)); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 6)); mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 7)); i4 = k >> 3; ptr_l_dup += cs_l; #if GEMM_ACCUM_A //(Row8): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[0] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[0], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[0], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[0], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[0], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[0], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[0], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_col[0], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[7], mat_b_col[0], mat_b_rearr[7]);//d = c - (a*b) #else mat_b_rearr[0] = _mm256_mul_ps(mat_a_blk_elems[0], mat_b_col[0]); mat_b_rearr[1] = _mm256_mul_ps(mat_a_blk_elems[1], mat_b_col[0]); mat_b_rearr[2] = _mm256_mul_ps(mat_a_blk_elems[2], mat_b_col[0]); mat_b_rearr[3] = _mm256_mul_ps(mat_a_blk_elems[3], mat_b_col[0]); mat_b_rearr[4] = _mm256_mul_ps(mat_a_blk_elems[4], mat_b_col[0]); mat_b_rearr[5] = _mm256_mul_ps(mat_a_blk_elems[5], mat_b_col[0]); mat_b_rearr[6] = _mm256_mul_ps(mat_a_blk_elems[6], mat_b_col[0]); mat_b_rearr[7] = _mm256_mul_ps(mat_a_blk_elems[7], mat_b_col[0]); #endif //Broadcast A21 to A71 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 1)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 2)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 3)); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 4)); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 5)); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 6)); mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 7)); ptr_l_dup += cs_l; #if GEMM_ACCUM_A //(Row9): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[0] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[1], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[1], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[1], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[1], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[1], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[1], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_col[1], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[7], mat_b_col[1], mat_b_rearr[7]);//d = c - (a*b) #else mat_b_rearr[0] = _mm256_fmadd_ps(mat_a_blk_elems[0], mat_b_col[1], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fmadd_ps(mat_a_blk_elems[1], mat_b_col[1], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fmadd_ps(mat_a_blk_elems[2], mat_b_col[1], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fmadd_ps(mat_a_blk_elems[3], mat_b_col[1], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fmadd_ps(mat_a_blk_elems[4], mat_b_col[1], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fmadd_ps(mat_a_blk_elems[5], mat_b_col[1], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fmadd_ps(mat_a_blk_elems[6], mat_b_col[1], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fmadd_ps(mat_a_blk_elems[7], mat_b_col[1], mat_b_rearr[7]);//d = c - (a*b) #endif //Broadcast A8,2 to A15,2 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 1)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 2)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 3)); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 4)); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 5)); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 6)); mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 7)); ptr_l_dup += cs_l; #if GEMM_ACCUM_A //(Row10): FMA operations of b2 with elements of indices from (2, 0) uptill (7, 0) mat_b_rearr[0] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[2], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[2], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[2], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[2], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[2], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[2], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_col[2], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[7], mat_b_col[2], mat_b_rearr[7]);//d = c - (a*b) #else mat_b_rearr[0] = _mm256_fmadd_ps(mat_a_blk_elems[0], mat_b_col[2], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fmadd_ps(mat_a_blk_elems[1], mat_b_col[2], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fmadd_ps(mat_a_blk_elems[2], mat_b_col[2], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fmadd_ps(mat_a_blk_elems[3], mat_b_col[2], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fmadd_ps(mat_a_blk_elems[4], mat_b_col[2], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fmadd_ps(mat_a_blk_elems[5], mat_b_col[2], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fmadd_ps(mat_a_blk_elems[6], mat_b_col[2], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fmadd_ps(mat_a_blk_elems[7], mat_b_col[2], mat_b_rearr[7]);//d = c - (a*b) #endif //Broadcast A8,3 to A15,3 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 1)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 2)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 3)); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 4)); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 5)); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 6)); mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 7)); ptr_l_dup += cs_l; #if GEMM_ACCUM_A //(Row11): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[0] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[3], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[3], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[3], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[3], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[3], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[3], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_col[3], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[7], mat_b_col[3], mat_b_rearr[7]);//d = c - (a*b) #else mat_b_rearr[0] = _mm256_fmadd_ps(mat_a_blk_elems[0], mat_b_col[3], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fmadd_ps(mat_a_blk_elems[1], mat_b_col[3], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fmadd_ps(mat_a_blk_elems[2], mat_b_col[3], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fmadd_ps(mat_a_blk_elems[3], mat_b_col[3], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fmadd_ps(mat_a_blk_elems[4], mat_b_col[3], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fmadd_ps(mat_a_blk_elems[5], mat_b_col[3], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fmadd_ps(mat_a_blk_elems[6], mat_b_col[3], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fmadd_ps(mat_a_blk_elems[7], mat_b_col[3], mat_b_rearr[7]);//d = c - (a*b) #endif //Broadcast A8,4 to A15,4 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 1)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 2)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 3)); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 4)); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 5)); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 6)); mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 7)); ptr_l_dup += cs_l; #if GEMM_ACCUM_A //(Row12): FMA operations of b2 with elements of indices from (2, 0) uptill (7, 0) mat_b_rearr[0] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[4], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[4], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[4], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[4], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[4], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[4], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_col[4], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[7], mat_b_col[4], mat_b_rearr[7]);//d = c - (a*b) #else mat_b_rearr[0] = _mm256_fmadd_ps(mat_a_blk_elems[0], mat_b_col[4], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fmadd_ps(mat_a_blk_elems[1], mat_b_col[4], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fmadd_ps(mat_a_blk_elems[2], mat_b_col[4], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fmadd_ps(mat_a_blk_elems[3], mat_b_col[4], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fmadd_ps(mat_a_blk_elems[4], mat_b_col[4], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fmadd_ps(mat_a_blk_elems[5], mat_b_col[4], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fmadd_ps(mat_a_blk_elems[6], mat_b_col[4], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fmadd_ps(mat_a_blk_elems[7], mat_b_col[4], mat_b_rearr[7]);//d = c - (a*b) #endif //Broadcast A8,5 to A15,5 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 1)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 2)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 3)); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 4)); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 5)); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 6)); mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 7)); ptr_l_dup += cs_l; #if GEMM_ACCUM_A //(Row13): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[0] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[5], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[5], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[5], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[5], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[5], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[5], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_col[5], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[7], mat_b_col[5], mat_b_rearr[7]);//d = c - (a*b) #else mat_b_rearr[0] = _mm256_fmadd_ps(mat_a_blk_elems[0], mat_b_col[5], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fmadd_ps(mat_a_blk_elems[1], mat_b_col[5], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fmadd_ps(mat_a_blk_elems[2], mat_b_col[5], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fmadd_ps(mat_a_blk_elems[3], mat_b_col[5], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fmadd_ps(mat_a_blk_elems[4], mat_b_col[5], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fmadd_ps(mat_a_blk_elems[5], mat_b_col[5], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fmadd_ps(mat_a_blk_elems[6], mat_b_col[5], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fmadd_ps(mat_a_blk_elems[7], mat_b_col[5], mat_b_rearr[7]);//d = c - (a*b) #endif //Broadcast A8,6 to A15,6 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 1)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 2)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 3)); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 4)); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 5)); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 6)); mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 7)); ptr_l_dup += cs_l; #if GEMM_ACCUM_A //(Row14): FMA operations of b2 with elements of indices from (2, 0) uptill (7, 0) mat_b_rearr[0] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[6], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[6], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[6], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[6], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[6], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[6], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_col[6], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[7], mat_b_col[6], mat_b_rearr[7]);//d = c - (a*b) #else mat_b_rearr[0] = _mm256_fmadd_ps(mat_a_blk_elems[0], mat_b_col[6], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fmadd_ps(mat_a_blk_elems[1], mat_b_col[6], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fmadd_ps(mat_a_blk_elems[2], mat_b_col[6], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fmadd_ps(mat_a_blk_elems[3], mat_b_col[6], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fmadd_ps(mat_a_blk_elems[4], mat_b_col[6], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fmadd_ps(mat_a_blk_elems[5], mat_b_col[6], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fmadd_ps(mat_a_blk_elems[6], mat_b_col[6], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fmadd_ps(mat_a_blk_elems[7], mat_b_col[6], mat_b_rearr[7]);//d = c - (a*b) #endif //Broadcast A8,7 to A15,7 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 1)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 2)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 3)); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 4)); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 5)); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 6)); mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 7)); ptr_l_dup += cs_l; #if GEMM_ACCUM_A //(Row15): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[0] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[7], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[7], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[7], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[7], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[7], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[7], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_col[7], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[7], mat_b_col[7], mat_b_rearr[7]);//d = c - (a*b) #else mat_b_rearr[0] = _mm256_fmadd_ps(mat_a_blk_elems[0], mat_b_col[7], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fmadd_ps(mat_a_blk_elems[1], mat_b_col[7], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fmadd_ps(mat_a_blk_elems[2], mat_b_col[7], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fmadd_ps(mat_a_blk_elems[3], mat_b_col[7], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fmadd_ps(mat_a_blk_elems[4], mat_b_col[7], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fmadd_ps(mat_a_blk_elems[5], mat_b_col[7], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fmadd_ps(mat_a_blk_elems[6], mat_b_col[7], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fmadd_ps(mat_a_blk_elems[7], mat_b_col[7], mat_b_rearr[7]);//d = c - (a*b) #endif //end loop of cols } i2 += cs_b_offset[6]; i += cs_l_offset[6]; } //trsm solve k = 0; //for (i2 = 0; i2 < numCols_b; i2 += 8) { i2 = i1 + r; /////////////////// Complete Lower 8x8 block trsm of B :- lower 8x8 block of B with lower right 8x8 block of A #if !GEMM_ACCUM_A //Read 8 cols of B columns of Block-to-be-solved mat_b_col[0] = _mm256_loadu_ps((float const *)ptr_b + i2); mat_b_col[1] = _mm256_loadu_ps((float const *)(ptr_b + cs_b + i2)); mat_b_col[2] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[0] + i2)); mat_b_col[3] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[1] + i2)); mat_b_col[4] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[2] + i2)); mat_b_col[5] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[3] + i2)); mat_b_col[6] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[4] + i2)); mat_b_col[7] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[5] + i2)); #endif //Broadcast A10 to A70 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + i + 1)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + i + 2)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l + i + 3)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l + i + 4)); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l + i + 5)); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l + i + 6)); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l + i + 7)); i += cs_l; #if GEMM_ACCUM_A //(Row0): already done #else mat_b_rearr[0] = _mm256_sub_ps(mat_b_col[0], mat_b_rearr[0]); #endif #if GEMM_ACCUM_A mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_rearr[0], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_rearr[0], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_rearr[0], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_rearr[0], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_rearr[0], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_rearr[0], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_rearr[0], mat_b_rearr[7]);//d = c - (a*b) #else mat_b_rearr[1] = _mm256_sub_ps(mat_b_col[1], mat_b_rearr[1]); mat_b_rearr[2] = _mm256_sub_ps(mat_b_col[2], mat_b_rearr[2]); mat_b_rearr[3] = _mm256_sub_ps(mat_b_col[3], mat_b_rearr[3]); mat_b_rearr[4] = _mm256_sub_ps(mat_b_col[4], mat_b_rearr[4]); mat_b_rearr[5] = _mm256_sub_ps(mat_b_col[5], mat_b_rearr[5]); mat_b_rearr[6] = _mm256_sub_ps(mat_b_col[6], mat_b_rearr[6]); mat_b_rearr[7] = _mm256_sub_ps(mat_b_col[7], mat_b_rearr[7]); //(Row1): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_rearr[0], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_rearr[0], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_rearr[0], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_rearr[0], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_rearr[0], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_rearr[0], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_rearr[0], mat_b_rearr[7]);//d = c - (a*b) #endif //Broadcast A21 to A71 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + i + 2)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + i + 3)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l + i + 4)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l + i + 5)); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l + i + 6)); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l + i + 7)); i += cs_l; //(Row2): FMA operations of b2 with elements of indices from (2, 0) uptill (7, 0) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_rearr[1], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_rearr[1], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_rearr[1], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_rearr[1], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_rearr[1], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_rearr[1], mat_b_rearr[7]);//d = c - (a*b) //Broadcast A32 to A72 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + i + 3)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + i + 4)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l + i + 5)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l + i + 6)); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l + i + 7)); i += cs_l; //(Row3): FMA operations of b3 with elements of indices from (3, 0) uptill (7, 0) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_rearr[2], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_rearr[2], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_rearr[2], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_rearr[2], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_rearr[2], mat_b_rearr[7]);//d = c - (a*b) //Broadcast A43 to A73 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + i + 4)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + i + 5)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l + i + 6)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l + i + 7)); i += cs_l; //(Row4): FMA operations of b4 with elements of indices from (4, 0) uptill (7, 0) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_rearr[3], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_rearr[3], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_rearr[3], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_rearr[3], mat_b_rearr[7]);//d = c - (a*b) //Broadcast A54 to A74 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + i + 5)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + i + 6)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l + i + 7)); i += cs_l; //(Row5): FMA operations of b5 with elements of indices from (5, 0) uptill (7, 0) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_rearr[4], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_rearr[4], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_rearr[4], mat_b_rearr[7]);//d = c - (a*b) //Broadcast A65 to A75 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + i + 6)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + i + 7)); i += cs_l; //(Row6): FMA operations of b6 with elements of indices from (6, 0) uptill (7, 0) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_rearr[5], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_rearr[5], mat_b_rearr[7]);//d = c - (a*b) //Broadcast A76 to register mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + i + 7)); //(Row7): FMA operations of b7 with elements of index (7, 0) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_rearr[6], mat_b_rearr[7]);//d = c - (a*b) //////////////////////////////////////////////////////////////////////////////// //Store the computed B columns _mm256_storeu_ps((float *)ptr_b_dup + r, mat_b_rearr[0]); _mm256_storeu_ps((float *)(ptr_b_dup + (cs_b)+r), mat_b_rearr[1]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[0] + r), mat_b_rearr[2]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[1] + r), mat_b_rearr[3]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[2] + r), mat_b_rearr[4]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[3] + r), mat_b_rearr[5]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[4] + r), mat_b_rearr[6]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[5] + r), mat_b_rearr[7]); //printf("writing B => m[%d], n[%d], [%f]\n", j, k, *(ptr_b_dup + k)); k++; } } } //numRows of A ///////////////////loop ends ///////////////////// } static void trsm_XAtB_block_allSmallSizedMatrices_alpha_unitDiag(float *ptr_l, float *ptr_b, int numRows_lb, int numCols_b, int rs_l, int rs_b, int cs_l, int cs_b, float alpha) { //float ones = 1.0; int i, i1, i2, i3, i4, j, k, l, r; int cs_b_offset[7]; int cs_l_offset[7]; float *ptr_b_dup, *ptr_l_dup; //57 number of ymm(256 bits) registers used __m256 mat_b_col[8]; __m256 mat_b_rearr[8]; __m256 mat_a_blk_elems[8]; //__m256 mat_a_diag_inv[8]; //__m256 reciprocal_diags[2]; __m256 alphaReg; alphaReg = _mm256_broadcast_ss((float const *)&alpha); // ---> considering that the matrix size is multiple of 16 rows and 8 cols <--- // //L matrix offsets cs_l_offset[0] = (cs_l << 1); cs_l_offset[1] = cs_l + cs_l_offset[0]; cs_l_offset[2] = (cs_l << 2); cs_l_offset[3] = cs_l + cs_l_offset[2]; cs_l_offset[4] = cs_l_offset[0] + cs_l_offset[2]; cs_l_offset[5] = cs_l + cs_l_offset[4]; cs_l_offset[6] = (cs_l_offset[5] + cs_l); cs_b_offset[0] = (cs_b << 1); cs_b_offset[1] = cs_b + cs_b_offset[0]; cs_b_offset[2] = (cs_b << 2); cs_b_offset[3] = cs_b + cs_b_offset[2]; cs_b_offset[4] = cs_b_offset[0] + cs_b_offset[2]; cs_b_offset[5] = cs_b + cs_b_offset[4]; cs_b_offset[6] = (cs_b_offset[5] + cs_b); #if 0 //Broadcast A10 to A70 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + 1)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + 2)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l + 3)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l + 4)); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l + 5)); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l + 6)); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l + 7)); //Broadcast A21 to A71 to registers mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 2)); mat_a_blk_elems[8] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 3)); mat_a_blk_elems[9] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 4)); mat_a_blk_elems[10] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 5)); mat_a_blk_elems[11] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 6)); mat_a_blk_elems[12] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 7)); //Broadcast A32 to A72 to registers mat_a_blk_elems[13] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + 3)); mat_a_blk_elems[14] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + 4)); mat_a_blk_elems[15] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + 5)); mat_a_blk_elems[16] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + 6)); mat_a_blk_elems[17] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + 7)); //Broadcast A43 to A73 to registers mat_a_blk_elems[18] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + 4)); mat_a_blk_elems[19] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + 5)); mat_a_blk_elems[20] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + 6)); mat_a_blk_elems[21] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + 7)); //Broadcast A54 to A74 to registers mat_a_blk_elems[22] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[2] + 5)); mat_a_blk_elems[23] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[2] + 6)); mat_a_blk_elems[24] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[2] + 7)); //Broadcast A65 to A75 to registers mat_a_blk_elems[25] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[3] + 6)); mat_a_blk_elems[26] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[3] + 7)); //Broadcast A76 to register mat_a_blk_elems[27] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[4] + 7)); #endif /***************** first set of 8 rows of B processing starts *****************/ ptr_b_dup = ptr_b; i = 0; for (j = 0; j < numCols_b; j += 8) { /////////////////// Complete Upper 8x8 block trsm of B :- upper 8x8 block of B with upper 8x8 block of A //read 8x8 block of B into registers mat_b_col[0] = _mm256_loadu_ps((float const *)ptr_b + i); mat_b_col[1] = _mm256_loadu_ps((float const *)(ptr_b + cs_b + i)); mat_b_col[2] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[0] + i)); mat_b_col[3] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[1] + i)); mat_b_col[4] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[2] + i)); mat_b_col[5] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[3] + i)); mat_b_col[6] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[4] + i)); mat_b_col[7] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[5] + i)); mat_b_col[0] = _mm256_mul_ps(mat_b_col[0], alphaReg); mat_b_col[1] = _mm256_mul_ps(mat_b_col[1], alphaReg); mat_b_col[2] = _mm256_mul_ps(mat_b_col[2], alphaReg); mat_b_col[3] = _mm256_mul_ps(mat_b_col[3], alphaReg); mat_b_col[4] = _mm256_mul_ps(mat_b_col[4], alphaReg); mat_b_col[5] = _mm256_mul_ps(mat_b_col[5], alphaReg); mat_b_col[6] = _mm256_mul_ps(mat_b_col[6], alphaReg); mat_b_col[7] = _mm256_mul_ps(mat_b_col[7], alphaReg); //(Row0) mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + 1)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + 2)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l + 3)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l + 4)); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l + 5)); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l + 6)); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l + 7)); //(Row1): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_col[1] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[0], mat_b_col[1]);//d = c - (a*b) mat_b_col[2] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[0], mat_b_col[2]);//d = c - (a*b) mat_b_col[3] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[0], mat_b_col[3]);//d = c - (a*b) mat_b_col[4] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[0], mat_b_col[4]);//d = c - (a*b) mat_b_col[5] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[0], mat_b_col[5]);//d = c - (a*b) mat_b_col[6] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[0], mat_b_col[6]);//d = c - (a*b) mat_b_col[7] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_col[0], mat_b_col[7]);//d = c - (a*b) mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 2)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 3)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 4)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 5)); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 6)); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 7)); //(Row2): FMA operations of b2 with elements of indices from (2, 0) uptill (7, 0) mat_b_col[2] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[1], mat_b_col[2]);//d = c - (a*b) mat_b_col[3] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[1], mat_b_col[3]);//d = c - (a*b) mat_b_col[4] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[1], mat_b_col[4]);//d = c - (a*b) mat_b_col[5] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[1], mat_b_col[5]);//d = c - (a*b) mat_b_col[6] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[1], mat_b_col[6]);//d = c - (a*b) mat_b_col[7] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[1], mat_b_col[7]);//d = c - (a*b) mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + 3)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + 4)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + 5)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + 6)); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + 7)); //(Row3): FMA operations of b3 with elements of indices from (3, 0) uptill (7, 0) mat_b_col[3] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[2], mat_b_col[3]);//d = c - (a*b) mat_b_col[4] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[2], mat_b_col[4]);//d = c - (a*b) mat_b_col[5] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[2], mat_b_col[5]);//d = c - (a*b) mat_b_col[6] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[2], mat_b_col[6]);//d = c - (a*b) mat_b_col[7] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[2], mat_b_col[7]);//d = c - (a*b) mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + 4)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + 5)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + 6)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + 7)); //(Row4): FMA operations of b4 with elements of indices from (4, 0) uptill (7, 0) mat_b_col[4] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[3], mat_b_col[4]);//d = c - (a*b) mat_b_col[5] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[3], mat_b_col[5]);//d = c - (a*b) mat_b_col[6] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[3], mat_b_col[6]);//d = c - (a*b) mat_b_col[7] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[3], mat_b_col[7]);//d = c - (a*b) mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[2] + 5)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[2] + 6)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[2] + 7)); //(Row5): FMA operations of b5 with elements of indices from (5, 0) uptill (7, 0) mat_b_col[5] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[4], mat_b_col[5]);//d = c - (a*b) mat_b_col[6] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[4], mat_b_col[6]);//d = c - (a*b) mat_b_col[7] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[4], mat_b_col[7]);//d = c - (a*b) mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[3] + 6)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[3] + 7)); //(Row6): FMA operations of b6 with elements of indices from (6, 0) uptill (7, 0) mat_b_col[6] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[5], mat_b_col[6]);//d = c - (a*b) mat_b_col[7] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[5], mat_b_col[7]);//d = c - (a*b) mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[4] + 7)); //(Row7): FMA operations of b7 with elements of index (7, 0) mat_b_col[7] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[6], mat_b_col[7]);//d = c - (a*b) //////////////////////////////////////////////////////////////////////////////// //Store the computed B columns _mm256_storeu_ps((float *)ptr_b_dup, mat_b_col[0]); _mm256_storeu_ps((float *)(ptr_b_dup + (cs_b)), mat_b_col[1]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[0]), mat_b_col[2]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[1]), mat_b_col[3]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[2]), mat_b_col[4]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[3]), mat_b_col[5]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[4]), mat_b_col[6]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[5]), mat_b_col[7]); //i += cs_b_offset[6]; //ptr_b_dup += cs_b_offset[6]; i += 8; ptr_b_dup += 8; } //c = 0; /***************** first set of 8 cols of B processing done *****************/ ptr_b_dup = ptr_b; i3 = 0; i1 = 0; //Start loop for cols of B to be processed in size of blk_width for (j = 8; j < numRows_lb; j += 8)//m :- 8x8 block row { ptr_l += 8; //ptr_b += j; //ptr_b_dup += 8; ptr_b_dup += cs_b_offset[6]; i1 += cs_b_offset[6]; i3 += cs_l_offset[6]; i = 0; i2 = 0; for (r = 0; r < numCols_b; r += GEMM_BLK_V1) { #if GEMM_ACCUM_A i = i1 + r; //Read 8 cols of B columns of Block-to-be-solved mat_b_rearr[0] = _mm256_loadu_ps((float const *)ptr_b + i); mat_b_rearr[1] = _mm256_loadu_ps((float const *)(ptr_b + cs_b + i)); mat_b_rearr[2] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[0] + i)); mat_b_rearr[3] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[1] + i)); mat_b_rearr[4] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[2] + i)); mat_b_rearr[5] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[3] + i)); mat_b_rearr[6] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[4] + i)); mat_b_rearr[7] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[5] + i)); mat_b_rearr[0] = _mm256_mul_ps(mat_b_rearr[0], alphaReg); mat_b_rearr[1] = _mm256_mul_ps(mat_b_rearr[1], alphaReg); mat_b_rearr[2] = _mm256_mul_ps(mat_b_rearr[2], alphaReg); mat_b_rearr[3] = _mm256_mul_ps(mat_b_rearr[3], alphaReg); mat_b_rearr[4] = _mm256_mul_ps(mat_b_rearr[4], alphaReg); mat_b_rearr[5] = _mm256_mul_ps(mat_b_rearr[5], alphaReg); mat_b_rearr[6] = _mm256_mul_ps(mat_b_rearr[6], alphaReg); mat_b_rearr[7] = _mm256_mul_ps(mat_b_rearr[7], alphaReg); #endif i = 0; i2 = 0; for (l = 0; l < j; l += 8) // move across m { //for (k = 0; k < numCols_b; k += 8) // move across n for the same value of l (index of m) { /////////////////// Partial Lower 8x8 block trsm of B ptr_l_dup = ptr_l; i4 = i2 + r; //Read current 8 cols of B columns from specified 8x8 current-block of B mat_b_col[0] = _mm256_loadu_ps((float const *)ptr_b + i4); mat_b_col[1] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b)); mat_b_col[2] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b_offset[0])); mat_b_col[3] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b_offset[1])); mat_b_col[4] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b_offset[2])); mat_b_col[5] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b_offset[3])); mat_b_col[6] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b_offset[4])); mat_b_col[7] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b_offset[5])); //Broadcast A8,0 to A15,0 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 1)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 2)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 3)); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 4)); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 5)); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 6)); mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 7)); i4 = k >> 3; ptr_l_dup += cs_l; #if GEMM_ACCUM_A //(Row8): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[0] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[0], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[0], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[0], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[0], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[0], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[0], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_col[0], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[7], mat_b_col[0], mat_b_rearr[7]);//d = c - (a*b) #else mat_b_rearr[0] = _mm256_mul_ps(mat_a_blk_elems[0], mat_b_col[0]); mat_b_rearr[1] = _mm256_mul_ps(mat_a_blk_elems[1], mat_b_col[0]); mat_b_rearr[2] = _mm256_mul_ps(mat_a_blk_elems[2], mat_b_col[0]); mat_b_rearr[3] = _mm256_mul_ps(mat_a_blk_elems[3], mat_b_col[0]); mat_b_rearr[4] = _mm256_mul_ps(mat_a_blk_elems[4], mat_b_col[0]); mat_b_rearr[5] = _mm256_mul_ps(mat_a_blk_elems[5], mat_b_col[0]); mat_b_rearr[6] = _mm256_mul_ps(mat_a_blk_elems[6], mat_b_col[0]); mat_b_rearr[7] = _mm256_mul_ps(mat_a_blk_elems[7], mat_b_col[0]); #endif //Broadcast A21 to A71 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 1)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 2)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 3)); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 4)); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 5)); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 6)); mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 7)); ptr_l_dup += cs_l; #if GEMM_ACCUM_A //(Row9): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[0] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[1], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[1], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[1], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[1], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[1], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[1], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_col[1], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[7], mat_b_col[1], mat_b_rearr[7]);//d = c - (a*b) #else mat_b_rearr[0] = _mm256_fmadd_ps(mat_a_blk_elems[0], mat_b_col[1], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fmadd_ps(mat_a_blk_elems[1], mat_b_col[1], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fmadd_ps(mat_a_blk_elems[2], mat_b_col[1], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fmadd_ps(mat_a_blk_elems[3], mat_b_col[1], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fmadd_ps(mat_a_blk_elems[4], mat_b_col[1], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fmadd_ps(mat_a_blk_elems[5], mat_b_col[1], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fmadd_ps(mat_a_blk_elems[6], mat_b_col[1], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fmadd_ps(mat_a_blk_elems[7], mat_b_col[1], mat_b_rearr[7]);//d = c - (a*b) #endif //Broadcast A8,2 to A15,2 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 1)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 2)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 3)); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 4)); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 5)); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 6)); mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 7)); ptr_l_dup += cs_l; #if GEMM_ACCUM_A //(Row10): FMA operations of b2 with elements of indices from (2, 0) uptill (7, 0) mat_b_rearr[0] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[2], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[2], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[2], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[2], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[2], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[2], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_col[2], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[7], mat_b_col[2], mat_b_rearr[7]);//d = c - (a*b) #else mat_b_rearr[0] = _mm256_fmadd_ps(mat_a_blk_elems[0], mat_b_col[2], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fmadd_ps(mat_a_blk_elems[1], mat_b_col[2], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fmadd_ps(mat_a_blk_elems[2], mat_b_col[2], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fmadd_ps(mat_a_blk_elems[3], mat_b_col[2], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fmadd_ps(mat_a_blk_elems[4], mat_b_col[2], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fmadd_ps(mat_a_blk_elems[5], mat_b_col[2], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fmadd_ps(mat_a_blk_elems[6], mat_b_col[2], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fmadd_ps(mat_a_blk_elems[7], mat_b_col[2], mat_b_rearr[7]);//d = c - (a*b) #endif //Broadcast A8,3 to A15,3 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 1)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 2)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 3)); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 4)); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 5)); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 6)); mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 7)); ptr_l_dup += cs_l; #if GEMM_ACCUM_A //(Row11): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[0] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[3], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[3], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[3], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[3], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[3], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[3], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_col[3], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[7], mat_b_col[3], mat_b_rearr[7]);//d = c - (a*b) #else mat_b_rearr[0] = _mm256_fmadd_ps(mat_a_blk_elems[0], mat_b_col[3], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fmadd_ps(mat_a_blk_elems[1], mat_b_col[3], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fmadd_ps(mat_a_blk_elems[2], mat_b_col[3], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fmadd_ps(mat_a_blk_elems[3], mat_b_col[3], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fmadd_ps(mat_a_blk_elems[4], mat_b_col[3], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fmadd_ps(mat_a_blk_elems[5], mat_b_col[3], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fmadd_ps(mat_a_blk_elems[6], mat_b_col[3], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fmadd_ps(mat_a_blk_elems[7], mat_b_col[3], mat_b_rearr[7]);//d = c - (a*b) #endif //Broadcast A8,4 to A15,4 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 1)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 2)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 3)); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 4)); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 5)); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 6)); mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 7)); ptr_l_dup += cs_l; #if GEMM_ACCUM_A //(Row12): FMA operations of b2 with elements of indices from (2, 0) uptill (7, 0) mat_b_rearr[0] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[4], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[4], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[4], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[4], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[4], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[4], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_col[4], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[7], mat_b_col[4], mat_b_rearr[7]);//d = c - (a*b) #else mat_b_rearr[0] = _mm256_fmadd_ps(mat_a_blk_elems[0], mat_b_col[4], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fmadd_ps(mat_a_blk_elems[1], mat_b_col[4], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fmadd_ps(mat_a_blk_elems[2], mat_b_col[4], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fmadd_ps(mat_a_blk_elems[3], mat_b_col[4], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fmadd_ps(mat_a_blk_elems[4], mat_b_col[4], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fmadd_ps(mat_a_blk_elems[5], mat_b_col[4], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fmadd_ps(mat_a_blk_elems[6], mat_b_col[4], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fmadd_ps(mat_a_blk_elems[7], mat_b_col[4], mat_b_rearr[7]);//d = c - (a*b) #endif //Broadcast A8,5 to A15,5 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 1)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 2)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 3)); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 4)); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 5)); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 6)); mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 7)); ptr_l_dup += cs_l; #if GEMM_ACCUM_A //(Row13): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[0] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[5], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[5], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[5], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[5], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[5], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[5], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_col[5], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[7], mat_b_col[5], mat_b_rearr[7]);//d = c - (a*b) #else mat_b_rearr[0] = _mm256_fmadd_ps(mat_a_blk_elems[0], mat_b_col[5], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fmadd_ps(mat_a_blk_elems[1], mat_b_col[5], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fmadd_ps(mat_a_blk_elems[2], mat_b_col[5], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fmadd_ps(mat_a_blk_elems[3], mat_b_col[5], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fmadd_ps(mat_a_blk_elems[4], mat_b_col[5], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fmadd_ps(mat_a_blk_elems[5], mat_b_col[5], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fmadd_ps(mat_a_blk_elems[6], mat_b_col[5], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fmadd_ps(mat_a_blk_elems[7], mat_b_col[5], mat_b_rearr[7]);//d = c - (a*b) #endif //Broadcast A8,6 to A15,6 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 1)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 2)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 3)); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 4)); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 5)); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 6)); mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 7)); ptr_l_dup += cs_l; #if GEMM_ACCUM_A //(Row14): FMA operations of b2 with elements of indices from (2, 0) uptill (7, 0) mat_b_rearr[0] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[6], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[6], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[6], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[6], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[6], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[6], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_col[6], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[7], mat_b_col[6], mat_b_rearr[7]);//d = c - (a*b) #else mat_b_rearr[0] = _mm256_fmadd_ps(mat_a_blk_elems[0], mat_b_col[6], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fmadd_ps(mat_a_blk_elems[1], mat_b_col[6], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fmadd_ps(mat_a_blk_elems[2], mat_b_col[6], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fmadd_ps(mat_a_blk_elems[3], mat_b_col[6], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fmadd_ps(mat_a_blk_elems[4], mat_b_col[6], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fmadd_ps(mat_a_blk_elems[5], mat_b_col[6], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fmadd_ps(mat_a_blk_elems[6], mat_b_col[6], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fmadd_ps(mat_a_blk_elems[7], mat_b_col[6], mat_b_rearr[7]);//d = c - (a*b) #endif //Broadcast A8,7 to A15,7 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 1)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 2)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 3)); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 4)); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 5)); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 6)); mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l_dup + i + 7)); ptr_l_dup += cs_l; #if GEMM_ACCUM_A //(Row15): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[0] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[7], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[7], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[7], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[7], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[7], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[7], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_col[7], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[7], mat_b_col[7], mat_b_rearr[7]);//d = c - (a*b) #else mat_b_rearr[0] = _mm256_fmadd_ps(mat_a_blk_elems[0], mat_b_col[7], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fmadd_ps(mat_a_blk_elems[1], mat_b_col[7], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fmadd_ps(mat_a_blk_elems[2], mat_b_col[7], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fmadd_ps(mat_a_blk_elems[3], mat_b_col[7], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fmadd_ps(mat_a_blk_elems[4], mat_b_col[7], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fmadd_ps(mat_a_blk_elems[5], mat_b_col[7], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fmadd_ps(mat_a_blk_elems[6], mat_b_col[7], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fmadd_ps(mat_a_blk_elems[7], mat_b_col[7], mat_b_rearr[7]);//d = c - (a*b) #endif //end loop of cols } i2 += cs_b_offset[6]; i += cs_l_offset[6]; } //trsm solve k = 0; //for (i2 = 0; i2 < numCols_b; i2 += 8) { i2 = i1 + r; /////////////////// Complete Lower 8x8 block trsm of B :- lower 8x8 block of B with lower right 8x8 block of A #if !GEMM_ACCUM_A //Read 8 cols of B columns of Block-to-be-solved mat_b_col[0] = _mm256_loadu_ps((float const *)ptr_b + i2); mat_b_col[1] = _mm256_loadu_ps((float const *)(ptr_b + cs_b + i2)); mat_b_col[2] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[0] + i2)); mat_b_col[3] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[1] + i2)); mat_b_col[4] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[2] + i2)); mat_b_col[5] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[3] + i2)); mat_b_col[6] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[4] + i2)); mat_b_col[7] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[5] + i2)); mat_b_col[0] = _mm256_mul_ps(mat_b_col[0], alphaReg); mat_b_col[1] = _mm256_mul_ps(mat_b_col[1], alphaReg); mat_b_col[2] = _mm256_mul_ps(mat_b_col[2], alphaReg); mat_b_col[3] = _mm256_mul_ps(mat_b_col[3], alphaReg); mat_b_col[4] = _mm256_mul_ps(mat_b_col[4], alphaReg); mat_b_col[5] = _mm256_mul_ps(mat_b_col[5], alphaReg); mat_b_col[6] = _mm256_mul_ps(mat_b_col[6], alphaReg); mat_b_col[7] = _mm256_mul_ps(mat_b_col[7], alphaReg); #endif //Broadcast A10 to A70 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + i + 1)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + i + 2)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l + i + 3)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l + i + 4)); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l + i + 5)); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l + i + 6)); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l + i + 7)); i += cs_l; #if GEMM_ACCUM_A //(Row0): already done #else mat_b_rearr[0] = _mm256_sub_ps(mat_b_col[0], mat_b_rearr[0]); #endif #if GEMM_ACCUM_A mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_rearr[0], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_rearr[0], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_rearr[0], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_rearr[0], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_rearr[0], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_rearr[0], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_rearr[0], mat_b_rearr[7]);//d = c - (a*b) #else mat_b_rearr[1] = _mm256_sub_ps(mat_b_col[1], mat_b_rearr[1]); mat_b_rearr[2] = _mm256_sub_ps(mat_b_col[2], mat_b_rearr[2]); mat_b_rearr[3] = _mm256_sub_ps(mat_b_col[3], mat_b_rearr[3]); mat_b_rearr[4] = _mm256_sub_ps(mat_b_col[4], mat_b_rearr[4]); mat_b_rearr[5] = _mm256_sub_ps(mat_b_col[5], mat_b_rearr[5]); mat_b_rearr[6] = _mm256_sub_ps(mat_b_col[6], mat_b_rearr[6]); mat_b_rearr[7] = _mm256_sub_ps(mat_b_col[7], mat_b_rearr[7]); //(Row1): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_rearr[0], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_rearr[0], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_rearr[0], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_rearr[0], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_rearr[0], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_rearr[0], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_rearr[0], mat_b_rearr[7]);//d = c - (a*b) #endif //Broadcast A21 to A71 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + i + 2)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + i + 3)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l + i + 4)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l + i + 5)); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l + i + 6)); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l + i + 7)); i += cs_l; //(Row2): FMA operations of b2 with elements of indices from (2, 0) uptill (7, 0) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_rearr[1], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_rearr[1], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_rearr[1], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_rearr[1], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_rearr[1], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_rearr[1], mat_b_rearr[7]);//d = c - (a*b) //Broadcast A32 to A72 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + i + 3)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + i + 4)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l + i + 5)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l + i + 6)); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l + i + 7)); i += cs_l; //(Row3): FMA operations of b3 with elements of indices from (3, 0) uptill (7, 0) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_rearr[2], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_rearr[2], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_rearr[2], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_rearr[2], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_rearr[2], mat_b_rearr[7]);//d = c - (a*b) //Broadcast A43 to A73 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + i + 4)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + i + 5)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l + i + 6)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l + i + 7)); i += cs_l; //(Row4): FMA operations of b4 with elements of indices from (4, 0) uptill (7, 0) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_rearr[3], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_rearr[3], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_rearr[3], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_rearr[3], mat_b_rearr[7]);//d = c - (a*b) //Broadcast A54 to A74 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + i + 5)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + i + 6)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l + i + 7)); i += cs_l; //(Row5): FMA operations of b5 with elements of indices from (5, 0) uptill (7, 0) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_rearr[4], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_rearr[4], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_rearr[4], mat_b_rearr[7]);//d = c - (a*b) //Broadcast A65 to A75 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + i + 6)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + i + 7)); i += cs_l; //(Row6): FMA operations of b6 with elements of indices from (6, 0) uptill (7, 0) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_rearr[5], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_rearr[5], mat_b_rearr[7]);//d = c - (a*b) //Broadcast A76 to register mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + i + 7)); //(Row7): FMA operations of b7 with elements of index (7, 0) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_rearr[6], mat_b_rearr[7]);//d = c - (a*b) //////////////////////////////////////////////////////////////////////////////// //Store the computed B columns _mm256_storeu_ps((float *)ptr_b_dup + r, mat_b_rearr[0]); _mm256_storeu_ps((float *)(ptr_b_dup + (cs_b)+r), mat_b_rearr[1]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[0] + r), mat_b_rearr[2]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[1] + r), mat_b_rearr[3]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[2] + r), mat_b_rearr[4]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[3] + r), mat_b_rearr[5]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[4] + r), mat_b_rearr[6]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[5] + r), mat_b_rearr[7]); //printf("writing B => m[%d], n[%d], [%f]\n", j, k, *(ptr_b_dup + k)); k++; } } } //numRows of A ///////////////////loop ends ///////////////////// } #else //rel 1.0 intrisic kernels (NOT OPT_CACHE_BLOCKING_L1) static void trsm_XAtB_block_allSmallSizedMatrices(float *ptr_l, float *ptr_b, int numRows_lb, int numCols_b, int rs_l, int rs_b, int cs_l, int cs_b) { float ones = 1.0; int i, i1, i2, i3, i4, j, k, l; int cs_b_offset[7]; int cs_l_offset[7]; float *ptr_b_dup; //57 number of ymm(256 bits) registers used __m256 mat_b_col[8]; __m256 mat_b_rearr[16][8]; __m256 mat_a_cols_rearr[8]; __m256 mat_a_blk_elems[64]; __m256 mat_a_diag_inv[8]; __m256 reciprocal_diags[2]; reciprocal_diags[0] = _mm256_broadcast_ss((float const *)(&ones)); // ---> considering that the matrix size is multiple of 16 rows and 8 cols <--- // //L matrix offsets cs_l_offset[0] = (cs_l << 1); cs_l_offset[1] = cs_l + cs_l_offset[0]; cs_l_offset[2] = (cs_l << 2); cs_l_offset[3] = cs_l + cs_l_offset[2]; cs_l_offset[4] = cs_l_offset[0] + cs_l_offset[2]; cs_l_offset[5] = cs_l + cs_l_offset[4]; cs_l_offset[6] = (cs_l_offset[5] + cs_l); //read diag elems of L 16x16 block mat_a_cols_rearr[0] = _mm256_loadu_ps((float const *)ptr_l); mat_a_cols_rearr[1] = _mm256_loadu_ps((float const *)ptr_l + cs_l); mat_a_cols_rearr[2] = _mm256_loadu_ps((float const *)ptr_l + cs_l_offset[0]); mat_a_cols_rearr[3] = _mm256_loadu_ps((float const *)ptr_l + cs_l_offset[1]); mat_a_cols_rearr[4] = _mm256_loadu_ps((float const *)ptr_l + cs_l_offset[2]); mat_a_cols_rearr[5] = _mm256_loadu_ps((float const *)ptr_l + cs_l_offset[3]); mat_a_cols_rearr[6] = _mm256_loadu_ps((float const *)ptr_l + cs_l_offset[4]); mat_a_cols_rearr[7] = _mm256_loadu_ps((float const *)ptr_l + cs_l_offset[5]); cs_b_offset[0] = (cs_b << 1); cs_b_offset[1] = cs_b + cs_b_offset[0]; cs_b_offset[2] = (cs_b << 2); cs_b_offset[3] = cs_b + cs_b_offset[2]; cs_b_offset[4] = cs_b_offset[0] + cs_b_offset[2]; cs_b_offset[5] = cs_b + cs_b_offset[4]; cs_b_offset[6] = (cs_b_offset[5] + cs_b); reciprocal_diags[1] = reciprocal_diags[0]; //pack first 8 diags together mat_a_diag_inv[0] = _mm256_blend_ps(mat_a_cols_rearr[0], mat_a_cols_rearr[1], 0xAA);//diag 0,1 mat_a_diag_inv[1] = _mm256_blend_ps(mat_a_cols_rearr[2], mat_a_cols_rearr[3], 0xAA);//diag 2,3 mat_a_diag_inv[2] = _mm256_blend_ps(mat_a_cols_rearr[4], mat_a_cols_rearr[5], 0xAA);//diag 4,5 mat_a_diag_inv[3] = _mm256_blend_ps(mat_a_cols_rearr[6], mat_a_cols_rearr[7], 0xAA);//diag 6,7 mat_a_diag_inv[0] = _mm256_blend_ps(mat_a_diag_inv[0], mat_a_diag_inv[1], 0xCC);//diag 0,1,2,3 mat_a_diag_inv[2] = _mm256_blend_ps(mat_a_diag_inv[2], mat_a_diag_inv[3], 0xCC);//diag 4,5,6,7 mat_a_diag_inv[0] = _mm256_blend_ps(mat_a_diag_inv[0], mat_a_diag_inv[2], 0xF0);//diag 0,1,2,3,4,5,6,7 //reciprocal of diagnal elements 0,1,2,3,4,5,6,7 reciprocal_diags[0] = _mm256_div_ps(reciprocal_diags[0], mat_a_diag_inv[0]); //Broadcast A10 to A70 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + 1)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + 2)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l + 3)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l + 4)); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l + 5)); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l + 6)); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l + 7)); //Broadcast A21 to A71 to registers mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 2)); mat_a_blk_elems[8] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 3)); mat_a_blk_elems[9] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 4)); mat_a_blk_elems[10] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 5)); mat_a_blk_elems[11] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 6)); mat_a_blk_elems[12] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 7)); //Broadcast A32 to A72 to registers mat_a_blk_elems[13] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + 3)); mat_a_blk_elems[14] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + 4)); mat_a_blk_elems[15] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + 5)); mat_a_blk_elems[16] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + 6)); mat_a_blk_elems[17] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + 7)); //Broadcast A43 to A73 to registers mat_a_blk_elems[18] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + 4)); mat_a_blk_elems[19] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + 5)); mat_a_blk_elems[20] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + 6)); mat_a_blk_elems[21] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + 7)); //Broadcast A54 to A74 to registers mat_a_blk_elems[22] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[2] + 5)); mat_a_blk_elems[23] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[2] + 6)); mat_a_blk_elems[24] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[2] + 7)); //Broadcast A65 to A75 to registers mat_a_blk_elems[25] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[3] + 6)); mat_a_blk_elems[26] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[3] + 7)); //Broadcast A76 to register mat_a_blk_elems[27] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[4] + 7)); //extract diag a00 from a mat_a_diag_inv[0] = _mm256_permute_ps(reciprocal_diags[0], 0x00); mat_a_diag_inv[0] = _mm256_permute2f128_ps(mat_a_diag_inv[0], mat_a_diag_inv[0], 0x00); //mat_a_diag_inv[0] = _mm256_unpacklo_ps(mat_a_diag_inv[0], mat_a_diag_inv[0]); //extract diag a11 from a mat_a_diag_inv[1] = _mm256_permute_ps(reciprocal_diags[0], 0x55); mat_a_diag_inv[1] = _mm256_permute2f128_ps(mat_a_diag_inv[1], mat_a_diag_inv[1], 0x00); //mat_a_diag_inv[1] = _mm256_unpacklo_ps(mat_a_diag_inv[1], mat_a_diag_inv[1]); //extract diag a22 from a mat_a_diag_inv[2] = _mm256_permute_ps(reciprocal_diags[0], 0xAA); mat_a_diag_inv[2] = _mm256_permute2f128_ps(mat_a_diag_inv[2], mat_a_diag_inv[2], 0x00); //mat_a_diag_inv[2] = _mm256_unpacklo_ps(mat_a_diag_inv[2], mat_a_diag_inv[2]); //extract diag a33 from a mat_a_diag_inv[3] = _mm256_permute_ps(reciprocal_diags[0], 0xFF); mat_a_diag_inv[3] = _mm256_permute2f128_ps(mat_a_diag_inv[3], mat_a_diag_inv[3], 0x00); //mat_a_diag_inv[3] = _mm256_unpacklo_ps(mat_a_diag_inv[3], mat_a_diag_inv[3]); //extract diag a44 from a mat_a_diag_inv[4] = _mm256_permute_ps(reciprocal_diags[0], 0x00); mat_a_diag_inv[4] = _mm256_permute2f128_ps(mat_a_diag_inv[4], mat_a_diag_inv[4], 0x11); //mat_a_diag_inv[4] = _mm256_unpacklo_ps(mat_a_diag_inv[4], mat_a_diag_inv[4]); //extract diag a55 from a mat_a_diag_inv[5] = _mm256_permute_ps(reciprocal_diags[0], 0x55); mat_a_diag_inv[5] = _mm256_permute2f128_ps(mat_a_diag_inv[5], mat_a_diag_inv[5], 0x11); //mat_a_diag_inv[5] = _mm256_unpacklo_ps(mat_a_diag_inv[5], mat_a_diag_inv[5]); //extract diag a66 from a mat_a_diag_inv[6] = _mm256_permute_ps(reciprocal_diags[0], 0xAA); mat_a_diag_inv[6] = _mm256_permute2f128_ps(mat_a_diag_inv[6], mat_a_diag_inv[6], 0x11); //mat_a_diag_inv[6] = _mm256_unpacklo_ps(mat_a_diag_inv[6], mat_a_diag_inv[6]); //extract diag a77 from a mat_a_diag_inv[7] = _mm256_permute_ps(reciprocal_diags[0], 0xFF); mat_a_diag_inv[7] = _mm256_permute2f128_ps(mat_a_diag_inv[7], mat_a_diag_inv[7], 0x11); //mat_a_diag_inv[7] = _mm256_unpacklo_ps(mat_a_diag_inv[7], mat_a_diag_inv[7]); /***************** first set of 8 rows of B processing starts *****************/ ptr_b_dup = ptr_b; i = 0; for (j = 0; j < numCols_b; j += 8) { /////////////////// Complete Upper 8x8 block trsm of B :- upper 8x8 block of B with upper 8x8 block of A //read 8x8 block of B into registers mat_b_rearr[0][0] = _mm256_loadu_ps((float const *)ptr_b + i); mat_b_rearr[1][0] = _mm256_loadu_ps((float const *)(ptr_b + cs_b + i)); mat_b_rearr[2][0] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[0] + i)); mat_b_rearr[3][0] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[1] + i)); mat_b_rearr[4][0] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[2] + i)); mat_b_rearr[5][0] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[3] + i)); mat_b_rearr[6][0] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[4] + i)); mat_b_rearr[7][0] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[5] + i)); //(Row0): Perform mul operation of reciprocal of L(0,0) element with 1st row elements of B mat_b_col[0] = _mm256_mul_ps(mat_b_rearr[0][0], mat_a_diag_inv[0]); //(Row1): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[1][0] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[0], mat_b_rearr[1][0]);//d = c - (a*b) mat_b_rearr[2][0] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[0], mat_b_rearr[2][0]);//d = c - (a*b) mat_b_rearr[3][0] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[0], mat_b_rearr[3][0]);//d = c - (a*b) mat_b_rearr[4][0] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[0], mat_b_rearr[4][0]);//d = c - (a*b) mat_b_rearr[5][0] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[0], mat_b_rearr[5][0]);//d = c - (a*b) mat_b_rearr[6][0] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[0], mat_b_rearr[6][0]);//d = c - (a*b) mat_b_rearr[7][0] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_col[0], mat_b_rearr[7][0]);//d = c - (a*b) //Perform mul operation of reciprocal of L(1,1) element with 2nd row elements of B mat_b_col[1] = _mm256_mul_ps(mat_b_rearr[1][0], mat_a_diag_inv[1]); //(Row2): FMA operations of b2 with elements of indices from (2, 0) uptill (7, 0) mat_b_rearr[2][0] = _mm256_fnmadd_ps(mat_a_blk_elems[7], mat_b_col[1], mat_b_rearr[2][0]);//d = c - (a*b) mat_b_rearr[3][0] = _mm256_fnmadd_ps(mat_a_blk_elems[8], mat_b_col[1], mat_b_rearr[3][0]);//d = c - (a*b) mat_b_rearr[4][0] = _mm256_fnmadd_ps(mat_a_blk_elems[9], mat_b_col[1], mat_b_rearr[4][0]);//d = c - (a*b) mat_b_rearr[5][0] = _mm256_fnmadd_ps(mat_a_blk_elems[10], mat_b_col[1], mat_b_rearr[5][0]);//d = c - (a*b) mat_b_rearr[6][0] = _mm256_fnmadd_ps(mat_a_blk_elems[11], mat_b_col[1], mat_b_rearr[6][0]);//d = c - (a*b) mat_b_rearr[7][0] = _mm256_fnmadd_ps(mat_a_blk_elems[12], mat_b_col[1], mat_b_rearr[7][0]);//d = c - (a*b) //Perform mul operation of reciprocal of L(2, 2) element with 3rd row elements of B mat_b_col[2] = _mm256_mul_ps(mat_b_rearr[2][0], mat_a_diag_inv[2]); //(Row3): FMA operations of b3 with elements of indices from (3, 0) uptill (7, 0) mat_b_rearr[3][0] = _mm256_fnmadd_ps(mat_a_blk_elems[13], mat_b_col[2], mat_b_rearr[3][0]);//d = c - (a*b) mat_b_rearr[4][0] = _mm256_fnmadd_ps(mat_a_blk_elems[14], mat_b_col[2], mat_b_rearr[4][0]);//d = c - (a*b) mat_b_rearr[5][0] = _mm256_fnmadd_ps(mat_a_blk_elems[15], mat_b_col[2], mat_b_rearr[5][0]);//d = c - (a*b) mat_b_rearr[6][0] = _mm256_fnmadd_ps(mat_a_blk_elems[16], mat_b_col[2], mat_b_rearr[6][0]);//d = c - (a*b) mat_b_rearr[7][0] = _mm256_fnmadd_ps(mat_a_blk_elems[17], mat_b_col[2], mat_b_rearr[7][0]);//d = c - (a*b) //Perform mul operation of reciprocal of L(3, 3) element with 4rth row elements of B mat_b_col[3] = _mm256_mul_ps(mat_b_rearr[3][0], mat_a_diag_inv[3]); //(Row4): FMA operations of b4 with elements of indices from (4, 0) uptill (7, 0) mat_b_rearr[4][0] = _mm256_fnmadd_ps(mat_a_blk_elems[18], mat_b_col[3], mat_b_rearr[4][0]);//d = c - (a*b) mat_b_rearr[5][0] = _mm256_fnmadd_ps(mat_a_blk_elems[19], mat_b_col[3], mat_b_rearr[5][0]);//d = c - (a*b) mat_b_rearr[6][0] = _mm256_fnmadd_ps(mat_a_blk_elems[20], mat_b_col[3], mat_b_rearr[6][0]);//d = c - (a*b) mat_b_rearr[7][0] = _mm256_fnmadd_ps(mat_a_blk_elems[21], mat_b_col[3], mat_b_rearr[7][0]);//d = c - (a*b) //Perform mul operation of reciprocal of L(4, 4) element with 4rth row elements of B mat_b_col[4] = _mm256_mul_ps(mat_b_rearr[4][0], mat_a_diag_inv[4]); //(Row5): FMA operations of b5 with elements of indices from (5, 0) uptill (7, 0) mat_b_rearr[5][0] = _mm256_fnmadd_ps(mat_a_blk_elems[22], mat_b_col[4], mat_b_rearr[5][0]);//d = c - (a*b) mat_b_rearr[6][0] = _mm256_fnmadd_ps(mat_a_blk_elems[23], mat_b_col[4], mat_b_rearr[6][0]);//d = c - (a*b) mat_b_rearr[7][0] = _mm256_fnmadd_ps(mat_a_blk_elems[24], mat_b_col[4], mat_b_rearr[7][0]);//d = c - (a*b) //Perform mul operation of reciprocal of L(5, 5) element with 5th row elements of B mat_b_col[5] = _mm256_mul_ps(mat_b_rearr[5][0], mat_a_diag_inv[5]); //(Row6): FMA operations of b6 with elements of indices from (6, 0) uptill (7, 0) mat_b_rearr[6][0] = _mm256_fnmadd_ps(mat_a_blk_elems[25], mat_b_col[5], mat_b_rearr[6][0]);//d = c - (a*b) mat_b_rearr[7][0] = _mm256_fnmadd_ps(mat_a_blk_elems[26], mat_b_col[5], mat_b_rearr[7][0]);//d = c - (a*b) //Perform mul operation of reciprocal of L(6, 6) element with 6th row elements of B mat_b_col[6] = _mm256_mul_ps(mat_b_rearr[6][0], mat_a_diag_inv[6]); //(Row7): FMA operations of b7 with elements of index (7, 0) mat_b_rearr[7][0] = _mm256_fnmadd_ps(mat_a_blk_elems[27], mat_b_col[6], mat_b_rearr[7][0]);//d = c - (a*b) //Perform mul operation of reciprocal of L(7, 7) element with 7th row elements of B mat_b_col[7] = _mm256_mul_ps(mat_b_rearr[7][0], mat_a_diag_inv[7]); //////////////////////////////////////////////////////////////////////////////// //Store the computed B columns _mm256_storeu_ps((float *)ptr_b_dup, mat_b_col[0]); _mm256_storeu_ps((float *)(ptr_b_dup + (cs_b)), mat_b_col[1]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[0]), mat_b_col[2]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[1]), mat_b_col[3]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[2]), mat_b_col[4]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[3]), mat_b_col[5]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[4]), mat_b_col[6]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[5]), mat_b_col[7]); //i += cs_b_offset[6]; //ptr_b_dup += cs_b_offset[6]; i += 8; ptr_b_dup += 8; } //c = 0; /***************** first set of 8 cols of B processing done *****************/ ptr_b_dup = ptr_b; i3 = 0; i1 = 0; //Start loop for cols of B to be processed in size of blk_width for (j = 8; j < numRows_lb; j += 8)//m :- 8x8 block row { ptr_l += 8; //ptr_b += j; //ptr_b_dup += 8; ptr_b_dup += cs_b_offset[6]; i1 += cs_b_offset[6]; //Read next 8x8 block of A to get diag elements i3 += cs_l_offset[6]; mat_a_cols_rearr[0] = _mm256_loadu_ps((float const *)ptr_l + i3); mat_a_cols_rearr[1] = _mm256_loadu_ps((float const *)ptr_l + i3 + cs_l); mat_a_cols_rearr[2] = _mm256_loadu_ps((float const *)ptr_l + i3 + cs_l_offset[0]); mat_a_cols_rearr[3] = _mm256_loadu_ps((float const *)ptr_l + i3 + cs_l_offset[1]); mat_a_cols_rearr[4] = _mm256_loadu_ps((float const *)ptr_l + i3 + cs_l_offset[2]); mat_a_cols_rearr[5] = _mm256_loadu_ps((float const *)ptr_l + i3 + cs_l_offset[3]); mat_a_cols_rearr[6] = _mm256_loadu_ps((float const *)ptr_l + i3 + cs_l_offset[4]); mat_a_cols_rearr[7] = _mm256_loadu_ps((float const *)ptr_l + i3 + cs_l_offset[5]); //pack 8 diags of A together reciprocal_diags[0] = reciprocal_diags[1]; mat_a_diag_inv[0] = _mm256_blend_ps(mat_a_cols_rearr[0], mat_a_cols_rearr[1], 0xAA);//diag 0,1 mat_a_diag_inv[1] = _mm256_blend_ps(mat_a_cols_rearr[2], mat_a_cols_rearr[3], 0xAA);//diag 2,3 mat_a_diag_inv[2] = _mm256_blend_ps(mat_a_cols_rearr[4], mat_a_cols_rearr[5], 0xAA);//diag 4,5 mat_a_diag_inv[3] = _mm256_blend_ps(mat_a_cols_rearr[6], mat_a_cols_rearr[7], 0xAA);//diag 6,7 mat_a_diag_inv[0] = _mm256_blend_ps(mat_a_diag_inv[0], mat_a_diag_inv[1], 0xCC);//diag 0,1,2,3 mat_a_diag_inv[2] = _mm256_blend_ps(mat_a_diag_inv[2], mat_a_diag_inv[3], 0xCC);//diag 4,5,6,7 mat_a_diag_inv[0] = _mm256_blend_ps(mat_a_diag_inv[0], mat_a_diag_inv[2], 0xF0);//diag 0,1,2,3,4,5,6,7 //reciprocal of diagnal elements of A :- 0,1,2,3,4,5,6,7 reciprocal_diags[0] = _mm256_div_ps(reciprocal_diags[0], mat_a_diag_inv[0]); i = 0; i2 = 0; for (k = 0; k < numCols_b; k += 8) { i = i1 + k; //Read 8 cols of B columns of Block-to-be-solved mat_b_rearr[i2][0] = _mm256_loadu_ps((float const *)ptr_b + i); mat_b_rearr[i2][1] = _mm256_loadu_ps((float const *)(ptr_b + cs_b + i)); mat_b_rearr[i2][2] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[0] + i)); mat_b_rearr[i2][3] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[1] + i)); mat_b_rearr[i2][4] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[2] + i)); mat_b_rearr[i2][5] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[3] + i)); mat_b_rearr[i2][6] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[4] + i)); mat_b_rearr[i2][7] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[5] + i)); i2++; } i = 0; i2 = 0; for (l = 0; l < j; l += 8) // move across m { //Broadcast A8,0 to A15,0 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + i)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + i + 1)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l + i + 2)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l + i + 3)); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l + i + 4)); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l + i + 5)); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l + i + 6)); mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l + i + 7)); //Broadcast A21 to A71 to registers mat_a_blk_elems[8] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + i)); mat_a_blk_elems[9] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + i + 1)); mat_a_blk_elems[10] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + i + 2)); mat_a_blk_elems[11] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + i + 3)); mat_a_blk_elems[12] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + i + 4)); mat_a_blk_elems[13] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + i + 5)); mat_a_blk_elems[14] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + i + 6)); mat_a_blk_elems[15] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + i + 7)); //Broadcast A8,2 to A15,2 to registers mat_a_blk_elems[16] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + i)); mat_a_blk_elems[17] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + i + 1)); mat_a_blk_elems[18] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + i + 2)); mat_a_blk_elems[19] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + i + 3)); mat_a_blk_elems[20] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + i + 4)); mat_a_blk_elems[21] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + i + 5)); mat_a_blk_elems[22] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + i + 6)); mat_a_blk_elems[23] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + i + 7)); //Broadcast A8,3 to A15,3 to registers mat_a_blk_elems[24] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + i)); mat_a_blk_elems[25] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + i + 1)); mat_a_blk_elems[26] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + i + 2)); mat_a_blk_elems[27] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + i + 3)); mat_a_blk_elems[28] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + i + 4)); mat_a_blk_elems[29] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + i + 5)); mat_a_blk_elems[30] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + i + 6)); mat_a_blk_elems[31] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + i + 7)); // _mm256_permute2f128_ps() //Broadcast A8,4 to A15,4 to registers mat_a_blk_elems[32] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[2] + i)); mat_a_blk_elems[33] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[2] + i + 1)); mat_a_blk_elems[34] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[2] + i + 2)); mat_a_blk_elems[35] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[2] + i + 3)); mat_a_blk_elems[36] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[2] + i + 4)); mat_a_blk_elems[37] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[2] + i + 5)); mat_a_blk_elems[38] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[2] + i + 6)); mat_a_blk_elems[39] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[2] + i + 7)); //Broadcast A8,5 to A15,5 to registers mat_a_blk_elems[40] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[3] + i)); mat_a_blk_elems[41] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[3] + i + 1)); mat_a_blk_elems[42] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[3] + i + 2)); mat_a_blk_elems[43] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[3] + i + 3)); mat_a_blk_elems[44] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[3] + i + 4)); mat_a_blk_elems[45] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[3] + i + 5)); mat_a_blk_elems[46] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[3] + i + 6)); mat_a_blk_elems[47] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[3] + i + 7)); //Broadcast A8,6 to A15,6 to registers mat_a_blk_elems[48] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[4] + i)); mat_a_blk_elems[49] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[4] + i + 1)); mat_a_blk_elems[50] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[4] + i + 2)); mat_a_blk_elems[51] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[4] + i + 3)); mat_a_blk_elems[52] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[4] + i + 4)); mat_a_blk_elems[53] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[4] + i + 5)); mat_a_blk_elems[54] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[4] + i + 6)); mat_a_blk_elems[55] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[4] + i + 7)); //Broadcast A8,7 to A15,7 to registers mat_a_blk_elems[56] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[5] + i)); mat_a_blk_elems[57] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[5] + i + 1)); mat_a_blk_elems[58] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[5] + i + 2)); mat_a_blk_elems[59] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[5] + i + 3)); mat_a_blk_elems[60] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[5] + i + 4)); mat_a_blk_elems[61] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[5] + i + 5)); mat_a_blk_elems[62] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[5] + i + 6)); mat_a_blk_elems[63] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[5] + i + 7)); i += cs_l_offset[6]; for (k = 0; k < numCols_b; k += 8) // move across n for the same value of l (index of m) { /////////////////// Partial Lower 8x8 block trsm of B i4 = i2 + k; //Read current 8 cols of B columns from specified 8x8 current-block of B mat_b_col[0] = _mm256_loadu_ps((float const *)ptr_b + i4); mat_b_col[1] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b)); mat_b_col[2] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b_offset[0])); mat_b_col[3] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b_offset[1])); mat_b_col[4] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b_offset[2])); mat_b_col[5] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b_offset[3])); mat_b_col[6] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b_offset[4])); mat_b_col[7] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b_offset[5])); i4 = k >> 3; //(Row8): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[i4][0] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[0], mat_b_rearr[i4][0]);//d = c - (a*b) mat_b_rearr[i4][1] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[0], mat_b_rearr[i4][1]);//d = c - (a*b) mat_b_rearr[i4][2] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[0], mat_b_rearr[i4][2]);//d = c - (a*b) mat_b_rearr[i4][3] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[0], mat_b_rearr[i4][3]);//d = c - (a*b) mat_b_rearr[i4][4] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[0], mat_b_rearr[i4][4]);//d = c - (a*b) mat_b_rearr[i4][5] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[0], mat_b_rearr[i4][5]);//d = c - (a*b) mat_b_rearr[i4][6] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_col[0], mat_b_rearr[i4][6]);//d = c - (a*b) mat_b_rearr[i4][7] = _mm256_fnmadd_ps(mat_a_blk_elems[7], mat_b_col[0], mat_b_rearr[i4][7]);//d = c - (a*b) //(Row9): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[i4][0] = _mm256_fnmadd_ps(mat_a_blk_elems[8], mat_b_col[1], mat_b_rearr[i4][0]);//d = c - (a*b) mat_b_rearr[i4][1] = _mm256_fnmadd_ps(mat_a_blk_elems[9], mat_b_col[1], mat_b_rearr[i4][1]);//d = c - (a*b) mat_b_rearr[i4][2] = _mm256_fnmadd_ps(mat_a_blk_elems[10], mat_b_col[1], mat_b_rearr[i4][2]);//d = c - (a*b) mat_b_rearr[i4][3] = _mm256_fnmadd_ps(mat_a_blk_elems[11], mat_b_col[1], mat_b_rearr[i4][3]);//d = c - (a*b) mat_b_rearr[i4][4] = _mm256_fnmadd_ps(mat_a_blk_elems[12], mat_b_col[1], mat_b_rearr[i4][4]);//d = c - (a*b) mat_b_rearr[i4][5] = _mm256_fnmadd_ps(mat_a_blk_elems[13], mat_b_col[1], mat_b_rearr[i4][5]);//d = c - (a*b) mat_b_rearr[i4][6] = _mm256_fnmadd_ps(mat_a_blk_elems[14], mat_b_col[1], mat_b_rearr[i4][6]);//d = c - (a*b) mat_b_rearr[i4][7] = _mm256_fnmadd_ps(mat_a_blk_elems[15], mat_b_col[1], mat_b_rearr[i4][7]);//d = c - (a*b) //(Row10): FMA operations of b2 with elements of indices from (2, 0) uptill (7, 0) mat_b_rearr[i4][0] = _mm256_fnmadd_ps(mat_a_blk_elems[16], mat_b_col[2], mat_b_rearr[i4][0]);//d = c - (a*b) mat_b_rearr[i4][1] = _mm256_fnmadd_ps(mat_a_blk_elems[17], mat_b_col[2], mat_b_rearr[i4][1]);//d = c - (a*b) mat_b_rearr[i4][2] = _mm256_fnmadd_ps(mat_a_blk_elems[18], mat_b_col[2], mat_b_rearr[i4][2]);//d = c - (a*b) mat_b_rearr[i4][3] = _mm256_fnmadd_ps(mat_a_blk_elems[19], mat_b_col[2], mat_b_rearr[i4][3]);//d = c - (a*b) mat_b_rearr[i4][4] = _mm256_fnmadd_ps(mat_a_blk_elems[20], mat_b_col[2], mat_b_rearr[i4][4]);//d = c - (a*b) mat_b_rearr[i4][5] = _mm256_fnmadd_ps(mat_a_blk_elems[21], mat_b_col[2], mat_b_rearr[i4][5]);//d = c - (a*b) mat_b_rearr[i4][6] = _mm256_fnmadd_ps(mat_a_blk_elems[22], mat_b_col[2], mat_b_rearr[i4][6]);//d = c - (a*b) mat_b_rearr[i4][7] = _mm256_fnmadd_ps(mat_a_blk_elems[23], mat_b_col[2], mat_b_rearr[i4][7]);//d = c - (a*b) //(Row11): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[i4][0] = _mm256_fnmadd_ps(mat_a_blk_elems[24], mat_b_col[3], mat_b_rearr[i4][0]);//d = c - (a*b) mat_b_rearr[i4][1] = _mm256_fnmadd_ps(mat_a_blk_elems[25], mat_b_col[3], mat_b_rearr[i4][1]);//d = c - (a*b) mat_b_rearr[i4][2] = _mm256_fnmadd_ps(mat_a_blk_elems[26], mat_b_col[3], mat_b_rearr[i4][2]);//d = c - (a*b) mat_b_rearr[i4][3] = _mm256_fnmadd_ps(mat_a_blk_elems[27], mat_b_col[3], mat_b_rearr[i4][3]);//d = c - (a*b) mat_b_rearr[i4][4] = _mm256_fnmadd_ps(mat_a_blk_elems[28], mat_b_col[3], mat_b_rearr[i4][4]);//d = c - (a*b) mat_b_rearr[i4][5] = _mm256_fnmadd_ps(mat_a_blk_elems[29], mat_b_col[3], mat_b_rearr[i4][5]);//d = c - (a*b) mat_b_rearr[i4][6] = _mm256_fnmadd_ps(mat_a_blk_elems[30], mat_b_col[3], mat_b_rearr[i4][6]);//d = c - (a*b) mat_b_rearr[i4][7] = _mm256_fnmadd_ps(mat_a_blk_elems[31], mat_b_col[3], mat_b_rearr[i4][7]);//d = c - (a*b) //(Row12): FMA operations of b2 with elements of indices from (2, 0) uptill (7, 0) mat_b_rearr[i4][0] = _mm256_fnmadd_ps(mat_a_blk_elems[32], mat_b_col[4], mat_b_rearr[i4][0]);//d = c - (a*b) mat_b_rearr[i4][1] = _mm256_fnmadd_ps(mat_a_blk_elems[33], mat_b_col[4], mat_b_rearr[i4][1]);//d = c - (a*b) mat_b_rearr[i4][2] = _mm256_fnmadd_ps(mat_a_blk_elems[34], mat_b_col[4], mat_b_rearr[i4][2]);//d = c - (a*b) mat_b_rearr[i4][3] = _mm256_fnmadd_ps(mat_a_blk_elems[35], mat_b_col[4], mat_b_rearr[i4][3]);//d = c - (a*b) mat_b_rearr[i4][4] = _mm256_fnmadd_ps(mat_a_blk_elems[36], mat_b_col[4], mat_b_rearr[i4][4]);//d = c - (a*b) mat_b_rearr[i4][5] = _mm256_fnmadd_ps(mat_a_blk_elems[37], mat_b_col[4], mat_b_rearr[i4][5]);//d = c - (a*b) mat_b_rearr[i4][6] = _mm256_fnmadd_ps(mat_a_blk_elems[38], mat_b_col[4], mat_b_rearr[i4][6]);//d = c - (a*b) mat_b_rearr[i4][7] = _mm256_fnmadd_ps(mat_a_blk_elems[39], mat_b_col[4], mat_b_rearr[i4][7]);//d = c - (a*b) //(Row13): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[i4][0] = _mm256_fnmadd_ps(mat_a_blk_elems[40], mat_b_col[5], mat_b_rearr[i4][0]);//d = c - (a*b) mat_b_rearr[i4][1] = _mm256_fnmadd_ps(mat_a_blk_elems[41], mat_b_col[5], mat_b_rearr[i4][1]);//d = c - (a*b) mat_b_rearr[i4][2] = _mm256_fnmadd_ps(mat_a_blk_elems[42], mat_b_col[5], mat_b_rearr[i4][2]);//d = c - (a*b) mat_b_rearr[i4][3] = _mm256_fnmadd_ps(mat_a_blk_elems[43], mat_b_col[5], mat_b_rearr[i4][3]);//d = c - (a*b) mat_b_rearr[i4][4] = _mm256_fnmadd_ps(mat_a_blk_elems[44], mat_b_col[5], mat_b_rearr[i4][4]);//d = c - (a*b) mat_b_rearr[i4][5] = _mm256_fnmadd_ps(mat_a_blk_elems[45], mat_b_col[5], mat_b_rearr[i4][5]);//d = c - (a*b) mat_b_rearr[i4][6] = _mm256_fnmadd_ps(mat_a_blk_elems[46], mat_b_col[5], mat_b_rearr[i4][6]);//d = c - (a*b) mat_b_rearr[i4][7] = _mm256_fnmadd_ps(mat_a_blk_elems[47], mat_b_col[5], mat_b_rearr[i4][7]);//d = c - (a*b) //(Row14): FMA operations of b2 with elements of indices from (2, 0) uptill (7, 0) mat_b_rearr[i4][0] = _mm256_fnmadd_ps(mat_a_blk_elems[48], mat_b_col[6], mat_b_rearr[i4][0]);//d = c - (a*b) mat_b_rearr[i4][1] = _mm256_fnmadd_ps(mat_a_blk_elems[49], mat_b_col[6], mat_b_rearr[i4][1]);//d = c - (a*b) mat_b_rearr[i4][2] = _mm256_fnmadd_ps(mat_a_blk_elems[50], mat_b_col[6], mat_b_rearr[i4][2]);//d = c - (a*b) mat_b_rearr[i4][3] = _mm256_fnmadd_ps(mat_a_blk_elems[51], mat_b_col[6], mat_b_rearr[i4][3]);//d = c - (a*b) mat_b_rearr[i4][4] = _mm256_fnmadd_ps(mat_a_blk_elems[52], mat_b_col[6], mat_b_rearr[i4][4]);//d = c - (a*b) mat_b_rearr[i4][5] = _mm256_fnmadd_ps(mat_a_blk_elems[53], mat_b_col[6], mat_b_rearr[i4][5]);//d = c - (a*b) mat_b_rearr[i4][6] = _mm256_fnmadd_ps(mat_a_blk_elems[54], mat_b_col[6], mat_b_rearr[i4][6]);//d = c - (a*b) mat_b_rearr[i4][7] = _mm256_fnmadd_ps(mat_a_blk_elems[55], mat_b_col[6], mat_b_rearr[i4][7]);//d = c - (a*b) //(Row15): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[i4][0] = _mm256_fnmadd_ps(mat_a_blk_elems[56], mat_b_col[7], mat_b_rearr[i4][0]);//d = c - (a*b) mat_b_rearr[i4][1] = _mm256_fnmadd_ps(mat_a_blk_elems[57], mat_b_col[7], mat_b_rearr[i4][1]);//d = c - (a*b) mat_b_rearr[i4][2] = _mm256_fnmadd_ps(mat_a_blk_elems[58], mat_b_col[7], mat_b_rearr[i4][2]);//d = c - (a*b) mat_b_rearr[i4][3] = _mm256_fnmadd_ps(mat_a_blk_elems[59], mat_b_col[7], mat_b_rearr[i4][3]);//d = c - (a*b) mat_b_rearr[i4][4] = _mm256_fnmadd_ps(mat_a_blk_elems[60], mat_b_col[7], mat_b_rearr[i4][4]);//d = c - (a*b) mat_b_rearr[i4][5] = _mm256_fnmadd_ps(mat_a_blk_elems[61], mat_b_col[7], mat_b_rearr[i4][5]);//d = c - (a*b) mat_b_rearr[i4][6] = _mm256_fnmadd_ps(mat_a_blk_elems[62], mat_b_col[7], mat_b_rearr[i4][6]);//d = c - (a*b) mat_b_rearr[i4][7] = _mm256_fnmadd_ps(mat_a_blk_elems[63], mat_b_col[7], mat_b_rearr[i4][7]);//d = c - (a*b) //end loop of cols } i2 += cs_b_offset[6]; } //Broadcast A10 to A70 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + i + 1)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + i + 2)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l + i + 3)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l + i + 4)); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l + i + 5)); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l + i + 6)); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l + i + 7)); i += cs_l; //extract diag a00 from a mat_a_diag_inv[0] = _mm256_permute_ps(reciprocal_diags[0], 0x00); mat_a_diag_inv[0] = _mm256_permute2f128_ps(mat_a_diag_inv[0], mat_a_diag_inv[0], 0x00); //mat_a_diag_inv2[0] = _mm256_unpacklo_ps(mat_a_diag_inv2[0], mat_a_diag_inv2[0]); //Broadcast A21 to A71 to registers mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l + i + 2)); mat_a_blk_elems[8] = _mm256_broadcast_ss((float const *)(ptr_l + i + 3)); mat_a_blk_elems[9] = _mm256_broadcast_ss((float const *)(ptr_l + i + 4)); mat_a_blk_elems[10] = _mm256_broadcast_ss((float const *)(ptr_l + i + 5)); mat_a_blk_elems[11] = _mm256_broadcast_ss((float const *)(ptr_l + i + 6)); mat_a_blk_elems[12] = _mm256_broadcast_ss((float const *)(ptr_l + i + 7)); i += cs_l; //extract diag a11 from a mat_a_diag_inv[1] = _mm256_permute_ps(reciprocal_diags[0], 0x55); mat_a_diag_inv[1] = _mm256_permute2f128_ps(mat_a_diag_inv[1], mat_a_diag_inv[1], 0x00); //mat_a_diag_inv[1] = _mm256_unpacklo_ps(mat_a_diag_inv[1], mat_a_diag_inv[1]); //Broadcast A32 to A72 to registers mat_a_blk_elems[13] = _mm256_broadcast_ss((float const *)(ptr_l + i + 3)); mat_a_blk_elems[14] = _mm256_broadcast_ss((float const *)(ptr_l + i + 4)); mat_a_blk_elems[15] = _mm256_broadcast_ss((float const *)(ptr_l + i + 5)); mat_a_blk_elems[16] = _mm256_broadcast_ss((float const *)(ptr_l + i + 6)); mat_a_blk_elems[17] = _mm256_broadcast_ss((float const *)(ptr_l + i + 7)); i += cs_l; //extract diag a22 from a mat_a_diag_inv[2] = _mm256_permute_ps(reciprocal_diags[0], 0xAA); mat_a_diag_inv[2] = _mm256_permute2f128_ps(mat_a_diag_inv[2], mat_a_diag_inv[2], 0x00); //mat_a_diag_inv[2] = _mm256_unpacklo_ps(mat_a_diag_inv[2], mat_a_diag_inv[2]); //Broadcast A43 to A73 to registers mat_a_blk_elems[18] = _mm256_broadcast_ss((float const *)(ptr_l + i + 4)); mat_a_blk_elems[19] = _mm256_broadcast_ss((float const *)(ptr_l + i + 5)); mat_a_blk_elems[20] = _mm256_broadcast_ss((float const *)(ptr_l + i + 6)); mat_a_blk_elems[21] = _mm256_broadcast_ss((float const *)(ptr_l + i + 7)); i += cs_l; //extract diag a33 from a mat_a_diag_inv[3] = _mm256_permute_ps(reciprocal_diags[0], 0xFF); mat_a_diag_inv[3] = _mm256_permute2f128_ps(mat_a_diag_inv[3], mat_a_diag_inv[3], 0x00); //mat_a_diag_inv[3] = _mm256_unpacklo_ps(mat_a_diag_inv[3], mat_a_diag_inv[3]); //Broadcast A54 to A74 to registers mat_a_blk_elems[22] = _mm256_broadcast_ss((float const *)(ptr_l + i + 5)); mat_a_blk_elems[23] = _mm256_broadcast_ss((float const *)(ptr_l + i + 6)); mat_a_blk_elems[24] = _mm256_broadcast_ss((float const *)(ptr_l + i + 7)); i += cs_l; //extract diag a44 from a mat_a_diag_inv[4] = _mm256_permute_ps(reciprocal_diags[0], 0x00); mat_a_diag_inv[4] = _mm256_permute2f128_ps(mat_a_diag_inv[4], mat_a_diag_inv[4], 0x11); //mat_a_diag_inv[4] = _mm256_unpacklo_ps(mat_a_diag_inv[4], mat_a_diag_inv[4]); //Broadcast A65 to A75 to registers mat_a_blk_elems[25] = _mm256_broadcast_ss((float const *)(ptr_l + i + 6)); mat_a_blk_elems[26] = _mm256_broadcast_ss((float const *)(ptr_l + i + 7)); i += cs_l; //extract diag a55 from a mat_a_diag_inv[5] = _mm256_permute_ps(reciprocal_diags[0], 0x55); mat_a_diag_inv[5] = _mm256_permute2f128_ps(mat_a_diag_inv[5], mat_a_diag_inv[5], 0x11); //mat_a_diag_inv[5] = _mm256_unpacklo_ps(mat_a_diag_inv[5], mat_a_diag_inv[5]); //Broadcast A76 to register mat_a_blk_elems[27] = _mm256_broadcast_ss((float const *)(ptr_l + i + 7)); //extract diag a66 from a mat_a_diag_inv[6] = _mm256_permute_ps(reciprocal_diags[0], 0xAA); mat_a_diag_inv[6] = _mm256_permute2f128_ps(mat_a_diag_inv[6], mat_a_diag_inv[6], 0x11); //mat_a_diag_inv[6] = _mm256_unpacklo_ps(mat_a_diag_inv[6], mat_a_diag_inv[6]); //extract diag a77 from a mat_a_diag_inv[7] = _mm256_permute_ps(reciprocal_diags[0], 0xFF); mat_a_diag_inv[7] = _mm256_permute2f128_ps(mat_a_diag_inv[7], mat_a_diag_inv[7], 0x11); //mat_a_diag_inv[7] = _mm256_unpacklo_ps(mat_a_diag_inv[7], mat_a_diag_inv[7]); k = 0; for (i = 0; i < numCols_b; i+=8) { /////////////////// Complete Lower 8x8 block trsm of B :- lower 8x8 block of B with lower right 8x8 block of A //(Row0): Perform mul operation of reciprocal of L(0,0) element with 1st row elements of B mat_b_rearr[k][0] = _mm256_mul_ps(mat_b_rearr[k][0], mat_a_diag_inv[0]); //(Row1): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[k][1] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_rearr[k][0], mat_b_rearr[k][1]);//d = c - (a*b) mat_b_rearr[k][2] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_rearr[k][0], mat_b_rearr[k][2]);//d = c - (a*b) mat_b_rearr[k][3] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_rearr[k][0], mat_b_rearr[k][3]);//d = c - (a*b) mat_b_rearr[k][4] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_rearr[k][0], mat_b_rearr[k][4]);//d = c - (a*b) mat_b_rearr[k][5] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_rearr[k][0], mat_b_rearr[k][5]);//d = c - (a*b) mat_b_rearr[k][6] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_rearr[k][0], mat_b_rearr[k][6]);//d = c - (a*b) mat_b_rearr[k][7] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_rearr[k][0], mat_b_rearr[k][7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(1,1) element with 2nd row elements of B mat_b_rearr[k][1] = _mm256_mul_ps(mat_b_rearr[k][1], mat_a_diag_inv[1]); //(Row2): FMA operations of b2 with elements of indices from (2, 0) uptill (7, 0) mat_b_rearr[k][2] = _mm256_fnmadd_ps(mat_a_blk_elems[7], mat_b_rearr[k][1], mat_b_rearr[k][2]);//d = c - (a*b) mat_b_rearr[k][3] = _mm256_fnmadd_ps(mat_a_blk_elems[8], mat_b_rearr[k][1], mat_b_rearr[k][3]);//d = c - (a*b) mat_b_rearr[k][4] = _mm256_fnmadd_ps(mat_a_blk_elems[9], mat_b_rearr[k][1], mat_b_rearr[k][4]);//d = c - (a*b) mat_b_rearr[k][5] = _mm256_fnmadd_ps(mat_a_blk_elems[10], mat_b_rearr[k][1], mat_b_rearr[k][5]);//d = c - (a*b) mat_b_rearr[k][6] = _mm256_fnmadd_ps(mat_a_blk_elems[11], mat_b_rearr[k][1], mat_b_rearr[k][6]);//d = c - (a*b) mat_b_rearr[k][7] = _mm256_fnmadd_ps(mat_a_blk_elems[12], mat_b_rearr[k][1], mat_b_rearr[k][7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(2, 2) element with 3rd row elements of B mat_b_rearr[k][2] = _mm256_mul_ps(mat_b_rearr[k][2], mat_a_diag_inv[2]); //(Row3): FMA operations of b3 with elements of indices from (3, 0) uptill (7, 0) mat_b_rearr[k][3] = _mm256_fnmadd_ps(mat_a_blk_elems[13], mat_b_rearr[k][2], mat_b_rearr[k][3]);//d = c - (a*b) mat_b_rearr[k][4] = _mm256_fnmadd_ps(mat_a_blk_elems[14], mat_b_rearr[k][2], mat_b_rearr[k][4]);//d = c - (a*b) mat_b_rearr[k][5] = _mm256_fnmadd_ps(mat_a_blk_elems[15], mat_b_rearr[k][2], mat_b_rearr[k][5]);//d = c - (a*b) mat_b_rearr[k][6] = _mm256_fnmadd_ps(mat_a_blk_elems[16], mat_b_rearr[k][2], mat_b_rearr[k][6]);//d = c - (a*b) mat_b_rearr[k][7] = _mm256_fnmadd_ps(mat_a_blk_elems[17], mat_b_rearr[k][2], mat_b_rearr[k][7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(3, 3) element with 4rth row elements of B mat_b_rearr[k][3] = _mm256_mul_ps(mat_b_rearr[k][3], mat_a_diag_inv[3]); //(Row4): FMA operations of b4 with elements of indices from (4, 0) uptill (7, 0) mat_b_rearr[k][4] = _mm256_fnmadd_ps(mat_a_blk_elems[18], mat_b_rearr[k][3], mat_b_rearr[k][4]);//d = c - (a*b) mat_b_rearr[k][5] = _mm256_fnmadd_ps(mat_a_blk_elems[19], mat_b_rearr[k][3], mat_b_rearr[k][5]);//d = c - (a*b) mat_b_rearr[k][6] = _mm256_fnmadd_ps(mat_a_blk_elems[20], mat_b_rearr[k][3], mat_b_rearr[k][6]);//d = c - (a*b) mat_b_rearr[k][7] = _mm256_fnmadd_ps(mat_a_blk_elems[21], mat_b_rearr[k][3], mat_b_rearr[k][7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(4, 4) element with 4rth row elements of B mat_b_rearr[k][4] = _mm256_mul_ps(mat_b_rearr[k][4], mat_a_diag_inv[4]); //(Row5): FMA operations of b5 with elements of indices from (5, 0) uptill (7, 0) mat_b_rearr[k][5] = _mm256_fnmadd_ps(mat_a_blk_elems[22], mat_b_rearr[k][4], mat_b_rearr[k][5]);//d = c - (a*b) mat_b_rearr[k][6] = _mm256_fnmadd_ps(mat_a_blk_elems[23], mat_b_rearr[k][4], mat_b_rearr[k][6]);//d = c - (a*b) mat_b_rearr[k][7] = _mm256_fnmadd_ps(mat_a_blk_elems[24], mat_b_rearr[k][4], mat_b_rearr[k][7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(5, 5) element with 5th row elements of B mat_b_rearr[k][5] = _mm256_mul_ps(mat_b_rearr[k][5], mat_a_diag_inv[5]); //(Row6): FMA operations of b6 with elements of indices from (6, 0) uptill (7, 0) mat_b_rearr[k][6] = _mm256_fnmadd_ps(mat_a_blk_elems[25], mat_b_rearr[k][5], mat_b_rearr[k][6]);//d = c - (a*b) mat_b_rearr[k][7] = _mm256_fnmadd_ps(mat_a_blk_elems[26], mat_b_rearr[k][5], mat_b_rearr[k][7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(6, 6) element with 6th row elements of B mat_b_rearr[k][6] = _mm256_mul_ps(mat_b_rearr[k][6], mat_a_diag_inv[6]); //(Row7): FMA operations of b7 with elements of index (7, 0) mat_b_rearr[k][7] = _mm256_fnmadd_ps(mat_a_blk_elems[27], mat_b_rearr[k][6], mat_b_rearr[k][7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(7, 7) element with 7th row elements of B mat_b_rearr[k][7] = _mm256_mul_ps(mat_b_rearr[k][7], mat_a_diag_inv[7]); //////////////////////////////////////////////////////////////////////////////// //Store the computed B columns _mm256_storeu_ps((float *)ptr_b_dup + i, mat_b_rearr[k][0]); _mm256_storeu_ps((float *)(ptr_b_dup + (cs_b) + i), mat_b_rearr[k][1]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[0] + i), mat_b_rearr[k][2]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[1] + i), mat_b_rearr[k][3]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[2] + i), mat_b_rearr[k][4]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[3] + i), mat_b_rearr[k][5]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[4] + i), mat_b_rearr[k][6]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[5] + i), mat_b_rearr[k][7]); //printf("writing B => m[%d], n[%d], [%f]\n", j, k, *(ptr_b_dup + k)); k++; } } ///////////////////loop ends ///////////////////// } static void trsm_XAtB_block_allSmallSizedMatrices_alpha(float *ptr_l, float *ptr_b, int numRows_lb, int numCols_b, int rs_l, int rs_b, int cs_l, int cs_b, float alpha) { float ones = 1.0; int i, i1, i2, i3, i4, j, k, l; int cs_b_offset[7]; int cs_l_offset[7]; float *ptr_b_dup; //57 number of ymm(256 bits) registers used __m256 mat_b_col[8]; __m256 mat_b_rearr[16][8]; __m256 mat_a_cols_rearr[8]; __m256 mat_a_blk_elems[64]; __m256 mat_a_diag_inv[8]; __m256 reciprocal_diags[2]; __m256 alphaReg; reciprocal_diags[0] = _mm256_broadcast_ss((float const *)(&ones)); alphaReg = _mm256_broadcast_ss((float const *)&alpha); // ---> considering that the matrix size is multiple of 16 rows and 8 cols <--- // //L matrix offsets cs_l_offset[0] = (cs_l << 1); cs_l_offset[1] = cs_l + cs_l_offset[0]; cs_l_offset[2] = (cs_l << 2); cs_l_offset[3] = cs_l + cs_l_offset[2]; cs_l_offset[4] = cs_l_offset[0] + cs_l_offset[2]; cs_l_offset[5] = cs_l + cs_l_offset[4]; cs_l_offset[6] = (cs_l_offset[5] + cs_l); //read diag elems of L 16x16 block mat_a_cols_rearr[0] = _mm256_loadu_ps((float const *)ptr_l); mat_a_cols_rearr[1] = _mm256_loadu_ps((float const *)ptr_l + cs_l); mat_a_cols_rearr[2] = _mm256_loadu_ps((float const *)ptr_l + cs_l_offset[0]); mat_a_cols_rearr[3] = _mm256_loadu_ps((float const *)ptr_l + cs_l_offset[1]); mat_a_cols_rearr[4] = _mm256_loadu_ps((float const *)ptr_l + cs_l_offset[2]); mat_a_cols_rearr[5] = _mm256_loadu_ps((float const *)ptr_l + cs_l_offset[3]); mat_a_cols_rearr[6] = _mm256_loadu_ps((float const *)ptr_l + cs_l_offset[4]); mat_a_cols_rearr[7] = _mm256_loadu_ps((float const *)ptr_l + cs_l_offset[5]); cs_b_offset[0] = (cs_b << 1); cs_b_offset[1] = cs_b + cs_b_offset[0]; cs_b_offset[2] = (cs_b << 2); cs_b_offset[3] = cs_b + cs_b_offset[2]; cs_b_offset[4] = cs_b_offset[0] + cs_b_offset[2]; cs_b_offset[5] = cs_b + cs_b_offset[4]; cs_b_offset[6] = (cs_b_offset[5] + cs_b); reciprocal_diags[1] = reciprocal_diags[0]; //pack first 8 diags together mat_a_diag_inv[0] = _mm256_blend_ps(mat_a_cols_rearr[0], mat_a_cols_rearr[1], 0xAA);//diag 0,1 mat_a_diag_inv[1] = _mm256_blend_ps(mat_a_cols_rearr[2], mat_a_cols_rearr[3], 0xAA);//diag 2,3 mat_a_diag_inv[2] = _mm256_blend_ps(mat_a_cols_rearr[4], mat_a_cols_rearr[5], 0xAA);//diag 4,5 mat_a_diag_inv[3] = _mm256_blend_ps(mat_a_cols_rearr[6], mat_a_cols_rearr[7], 0xAA);//diag 6,7 mat_a_diag_inv[0] = _mm256_blend_ps(mat_a_diag_inv[0], mat_a_diag_inv[1], 0xCC);//diag 0,1,2,3 mat_a_diag_inv[2] = _mm256_blend_ps(mat_a_diag_inv[2], mat_a_diag_inv[3], 0xCC);//diag 4,5,6,7 mat_a_diag_inv[0] = _mm256_blend_ps(mat_a_diag_inv[0], mat_a_diag_inv[2], 0xF0);//diag 0,1,2,3,4,5,6,7 //reciprocal of diagnal elements 0,1,2,3,4,5,6,7 reciprocal_diags[0] = _mm256_div_ps(reciprocal_diags[0], mat_a_diag_inv[0]); //Broadcast A10 to A70 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + 1)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + 2)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l + 3)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l + 4)); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l + 5)); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l + 6)); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l + 7)); //Broadcast A21 to A71 to registers mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 2)); mat_a_blk_elems[8] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 3)); mat_a_blk_elems[9] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 4)); mat_a_blk_elems[10] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 5)); mat_a_blk_elems[11] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 6)); mat_a_blk_elems[12] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 7)); //Broadcast A32 to A72 to registers mat_a_blk_elems[13] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + 3)); mat_a_blk_elems[14] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + 4)); mat_a_blk_elems[15] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + 5)); mat_a_blk_elems[16] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + 6)); mat_a_blk_elems[17] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + 7)); //Broadcast A43 to A73 to registers mat_a_blk_elems[18] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + 4)); mat_a_blk_elems[19] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + 5)); mat_a_blk_elems[20] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + 6)); mat_a_blk_elems[21] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + 7)); //Broadcast A54 to A74 to registers mat_a_blk_elems[22] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[2] + 5)); mat_a_blk_elems[23] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[2] + 6)); mat_a_blk_elems[24] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[2] + 7)); //Broadcast A65 to A75 to registers mat_a_blk_elems[25] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[3] + 6)); mat_a_blk_elems[26] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[3] + 7)); //Broadcast A76 to register mat_a_blk_elems[27] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[4] + 7)); //extract diag a00 from a mat_a_diag_inv[0] = _mm256_permute_ps(reciprocal_diags[0], 0x00); mat_a_diag_inv[0] = _mm256_permute2f128_ps(mat_a_diag_inv[0], mat_a_diag_inv[0], 0x00); //mat_a_diag_inv[0] = _mm256_unpacklo_ps(mat_a_diag_inv[0], mat_a_diag_inv[0]); //extract diag a11 from a mat_a_diag_inv[1] = _mm256_permute_ps(reciprocal_diags[0], 0x55); mat_a_diag_inv[1] = _mm256_permute2f128_ps(mat_a_diag_inv[1], mat_a_diag_inv[1], 0x00); //mat_a_diag_inv[1] = _mm256_unpacklo_ps(mat_a_diag_inv[1], mat_a_diag_inv[1]); //extract diag a22 from a mat_a_diag_inv[2] = _mm256_permute_ps(reciprocal_diags[0], 0xAA); mat_a_diag_inv[2] = _mm256_permute2f128_ps(mat_a_diag_inv[2], mat_a_diag_inv[2], 0x00); //mat_a_diag_inv[2] = _mm256_unpacklo_ps(mat_a_diag_inv[2], mat_a_diag_inv[2]); //extract diag a33 from a mat_a_diag_inv[3] = _mm256_permute_ps(reciprocal_diags[0], 0xFF); mat_a_diag_inv[3] = _mm256_permute2f128_ps(mat_a_diag_inv[3], mat_a_diag_inv[3], 0x00); //mat_a_diag_inv[3] = _mm256_unpacklo_ps(mat_a_diag_inv[3], mat_a_diag_inv[3]); //extract diag a44 from a mat_a_diag_inv[4] = _mm256_permute_ps(reciprocal_diags[0], 0x00); mat_a_diag_inv[4] = _mm256_permute2f128_ps(mat_a_diag_inv[4], mat_a_diag_inv[4], 0x11); //mat_a_diag_inv[4] = _mm256_unpacklo_ps(mat_a_diag_inv[4], mat_a_diag_inv[4]); //extract diag a55 from a mat_a_diag_inv[5] = _mm256_permute_ps(reciprocal_diags[0], 0x55); mat_a_diag_inv[5] = _mm256_permute2f128_ps(mat_a_diag_inv[5], mat_a_diag_inv[5], 0x11); //mat_a_diag_inv[5] = _mm256_unpacklo_ps(mat_a_diag_inv[5], mat_a_diag_inv[5]); //extract diag a66 from a mat_a_diag_inv[6] = _mm256_permute_ps(reciprocal_diags[0], 0xAA); mat_a_diag_inv[6] = _mm256_permute2f128_ps(mat_a_diag_inv[6], mat_a_diag_inv[6], 0x11); //mat_a_diag_inv[6] = _mm256_unpacklo_ps(mat_a_diag_inv[6], mat_a_diag_inv[6]); //extract diag a77 from a mat_a_diag_inv[7] = _mm256_permute_ps(reciprocal_diags[0], 0xFF); mat_a_diag_inv[7] = _mm256_permute2f128_ps(mat_a_diag_inv[7], mat_a_diag_inv[7], 0x11); //mat_a_diag_inv[7] = _mm256_unpacklo_ps(mat_a_diag_inv[7], mat_a_diag_inv[7]); /***************** first set of 8 rows of B processing starts *****************/ ptr_b_dup = ptr_b; i = 0; for (j = 0; j < numCols_b; j += 8) { /////////////////// Complete Upper 8x8 block trsm of B :- upper 8x8 block of B with upper 8x8 block of A //read 8x8 block of B into registers mat_b_rearr[0][0] = _mm256_loadu_ps((float const *)ptr_b + i); mat_b_rearr[1][0] = _mm256_loadu_ps((float const *)(ptr_b + cs_b + i)); mat_b_rearr[2][0] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[0] + i)); mat_b_rearr[3][0] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[1] + i)); mat_b_rearr[4][0] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[2] + i)); mat_b_rearr[5][0] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[3] + i)); mat_b_rearr[6][0] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[4] + i)); mat_b_rearr[7][0] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[5] + i)); mat_b_rearr[0][0] = _mm256_mul_ps(mat_b_rearr[0][0], alphaReg); mat_b_rearr[1][0] = _mm256_mul_ps(mat_b_rearr[1][0], alphaReg); mat_b_rearr[2][0] = _mm256_mul_ps(mat_b_rearr[2][0], alphaReg); mat_b_rearr[3][0] = _mm256_mul_ps(mat_b_rearr[3][0], alphaReg); mat_b_rearr[4][0] = _mm256_mul_ps(mat_b_rearr[4][0], alphaReg); mat_b_rearr[5][0] = _mm256_mul_ps(mat_b_rearr[5][0], alphaReg); mat_b_rearr[6][0] = _mm256_mul_ps(mat_b_rearr[6][0], alphaReg); mat_b_rearr[7][0] = _mm256_mul_ps(mat_b_rearr[7][0], alphaReg); //(Row0): Perform mul operation of reciprocal of L(0,0) element with 1st row elements of B mat_b_col[0] = _mm256_mul_ps(mat_b_rearr[0][0], mat_a_diag_inv[0]); //(Row1): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[1][0] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[0], mat_b_rearr[1][0]);//d = c - (a*b) mat_b_rearr[2][0] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[0], mat_b_rearr[2][0]);//d = c - (a*b) mat_b_rearr[3][0] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[0], mat_b_rearr[3][0]);//d = c - (a*b) mat_b_rearr[4][0] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[0], mat_b_rearr[4][0]);//d = c - (a*b) mat_b_rearr[5][0] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[0], mat_b_rearr[5][0]);//d = c - (a*b) mat_b_rearr[6][0] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[0], mat_b_rearr[6][0]);//d = c - (a*b) mat_b_rearr[7][0] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_col[0], mat_b_rearr[7][0]);//d = c - (a*b) //Perform mul operation of reciprocal of L(1,1) element with 2nd row elements of B mat_b_col[1] = _mm256_mul_ps(mat_b_rearr[1][0], mat_a_diag_inv[1]); //(Row2): FMA operations of b2 with elements of indices from (2, 0) uptill (7, 0) mat_b_rearr[2][0] = _mm256_fnmadd_ps(mat_a_blk_elems[7], mat_b_col[1], mat_b_rearr[2][0]);//d = c - (a*b) mat_b_rearr[3][0] = _mm256_fnmadd_ps(mat_a_blk_elems[8], mat_b_col[1], mat_b_rearr[3][0]);//d = c - (a*b) mat_b_rearr[4][0] = _mm256_fnmadd_ps(mat_a_blk_elems[9], mat_b_col[1], mat_b_rearr[4][0]);//d = c - (a*b) mat_b_rearr[5][0] = _mm256_fnmadd_ps(mat_a_blk_elems[10], mat_b_col[1], mat_b_rearr[5][0]);//d = c - (a*b) mat_b_rearr[6][0] = _mm256_fnmadd_ps(mat_a_blk_elems[11], mat_b_col[1], mat_b_rearr[6][0]);//d = c - (a*b) mat_b_rearr[7][0] = _mm256_fnmadd_ps(mat_a_blk_elems[12], mat_b_col[1], mat_b_rearr[7][0]);//d = c - (a*b) //Perform mul operation of reciprocal of L(2, 2) element with 3rd row elements of B mat_b_col[2] = _mm256_mul_ps(mat_b_rearr[2][0], mat_a_diag_inv[2]); //(Row3): FMA operations of b3 with elements of indices from (3, 0) uptill (7, 0) mat_b_rearr[3][0] = _mm256_fnmadd_ps(mat_a_blk_elems[13], mat_b_col[2], mat_b_rearr[3][0]);//d = c - (a*b) mat_b_rearr[4][0] = _mm256_fnmadd_ps(mat_a_blk_elems[14], mat_b_col[2], mat_b_rearr[4][0]);//d = c - (a*b) mat_b_rearr[5][0] = _mm256_fnmadd_ps(mat_a_blk_elems[15], mat_b_col[2], mat_b_rearr[5][0]);//d = c - (a*b) mat_b_rearr[6][0] = _mm256_fnmadd_ps(mat_a_blk_elems[16], mat_b_col[2], mat_b_rearr[6][0]);//d = c - (a*b) mat_b_rearr[7][0] = _mm256_fnmadd_ps(mat_a_blk_elems[17], mat_b_col[2], mat_b_rearr[7][0]);//d = c - (a*b) //Perform mul operation of reciprocal of L(3, 3) element with 4rth row elements of B mat_b_col[3] = _mm256_mul_ps(mat_b_rearr[3][0], mat_a_diag_inv[3]); //(Row4): FMA operations of b4 with elements of indices from (4, 0) uptill (7, 0) mat_b_rearr[4][0] = _mm256_fnmadd_ps(mat_a_blk_elems[18], mat_b_col[3], mat_b_rearr[4][0]);//d = c - (a*b) mat_b_rearr[5][0] = _mm256_fnmadd_ps(mat_a_blk_elems[19], mat_b_col[3], mat_b_rearr[5][0]);//d = c - (a*b) mat_b_rearr[6][0] = _mm256_fnmadd_ps(mat_a_blk_elems[20], mat_b_col[3], mat_b_rearr[6][0]);//d = c - (a*b) mat_b_rearr[7][0] = _mm256_fnmadd_ps(mat_a_blk_elems[21], mat_b_col[3], mat_b_rearr[7][0]);//d = c - (a*b) //Perform mul operation of reciprocal of L(4, 4) element with 4rth row elements of B mat_b_col[4] = _mm256_mul_ps(mat_b_rearr[4][0], mat_a_diag_inv[4]); //(Row5): FMA operations of b5 with elements of indices from (5, 0) uptill (7, 0) mat_b_rearr[5][0] = _mm256_fnmadd_ps(mat_a_blk_elems[22], mat_b_col[4], mat_b_rearr[5][0]);//d = c - (a*b) mat_b_rearr[6][0] = _mm256_fnmadd_ps(mat_a_blk_elems[23], mat_b_col[4], mat_b_rearr[6][0]);//d = c - (a*b) mat_b_rearr[7][0] = _mm256_fnmadd_ps(mat_a_blk_elems[24], mat_b_col[4], mat_b_rearr[7][0]);//d = c - (a*b) //Perform mul operation of reciprocal of L(5, 5) element with 5th row elements of B mat_b_col[5] = _mm256_mul_ps(mat_b_rearr[5][0], mat_a_diag_inv[5]); //(Row6): FMA operations of b6 with elements of indices from (6, 0) uptill (7, 0) mat_b_rearr[6][0] = _mm256_fnmadd_ps(mat_a_blk_elems[25], mat_b_col[5], mat_b_rearr[6][0]);//d = c - (a*b) mat_b_rearr[7][0] = _mm256_fnmadd_ps(mat_a_blk_elems[26], mat_b_col[5], mat_b_rearr[7][0]);//d = c - (a*b) //Perform mul operation of reciprocal of L(6, 6) element with 6th row elements of B mat_b_col[6] = _mm256_mul_ps(mat_b_rearr[6][0], mat_a_diag_inv[6]); //(Row7): FMA operations of b7 with elements of index (7, 0) mat_b_rearr[7][0] = _mm256_fnmadd_ps(mat_a_blk_elems[27], mat_b_col[6], mat_b_rearr[7][0]);//d = c - (a*b) //Perform mul operation of reciprocal of L(7, 7) element with 7th row elements of B mat_b_col[7] = _mm256_mul_ps(mat_b_rearr[7][0], mat_a_diag_inv[7]); //////////////////////////////////////////////////////////////////////////////// //Store the computed B columns _mm256_storeu_ps((float *)ptr_b_dup, mat_b_col[0]); _mm256_storeu_ps((float *)(ptr_b_dup + (cs_b)), mat_b_col[1]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[0]), mat_b_col[2]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[1]), mat_b_col[3]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[2]), mat_b_col[4]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[3]), mat_b_col[5]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[4]), mat_b_col[6]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[5]), mat_b_col[7]); //i += cs_b_offset[6]; //ptr_b_dup += cs_b_offset[6]; i += 8; ptr_b_dup += 8; } //c = 0; /***************** first set of 8 cols of B processing done *****************/ ptr_b_dup = ptr_b; i3 = 0; i1 = 0; //Start loop for cols of B to be processed in size of blk_width for (j = 8; j < numRows_lb; j += 8)//m :- 8x8 block row { ptr_l += 8; //ptr_b += j; //ptr_b_dup += 8; ptr_b_dup += cs_b_offset[6]; i1 += cs_b_offset[6]; //Read next 8x8 block of A to get diag elements i3 += cs_l_offset[6]; mat_a_cols_rearr[0] = _mm256_loadu_ps((float const *)ptr_l + i3); mat_a_cols_rearr[1] = _mm256_loadu_ps((float const *)ptr_l + i3 + cs_l); mat_a_cols_rearr[2] = _mm256_loadu_ps((float const *)ptr_l + i3 + cs_l_offset[0]); mat_a_cols_rearr[3] = _mm256_loadu_ps((float const *)ptr_l + i3 + cs_l_offset[1]); mat_a_cols_rearr[4] = _mm256_loadu_ps((float const *)ptr_l + i3 + cs_l_offset[2]); mat_a_cols_rearr[5] = _mm256_loadu_ps((float const *)ptr_l + i3 + cs_l_offset[3]); mat_a_cols_rearr[6] = _mm256_loadu_ps((float const *)ptr_l + i3 + cs_l_offset[4]); mat_a_cols_rearr[7] = _mm256_loadu_ps((float const *)ptr_l + i3 + cs_l_offset[5]); //pack 8 diags of A together reciprocal_diags[0] = reciprocal_diags[1]; mat_a_diag_inv[0] = _mm256_blend_ps(mat_a_cols_rearr[0], mat_a_cols_rearr[1], 0xAA);//diag 0,1 mat_a_diag_inv[1] = _mm256_blend_ps(mat_a_cols_rearr[2], mat_a_cols_rearr[3], 0xAA);//diag 2,3 mat_a_diag_inv[2] = _mm256_blend_ps(mat_a_cols_rearr[4], mat_a_cols_rearr[5], 0xAA);//diag 4,5 mat_a_diag_inv[3] = _mm256_blend_ps(mat_a_cols_rearr[6], mat_a_cols_rearr[7], 0xAA);//diag 6,7 mat_a_diag_inv[0] = _mm256_blend_ps(mat_a_diag_inv[0], mat_a_diag_inv[1], 0xCC);//diag 0,1,2,3 mat_a_diag_inv[2] = _mm256_blend_ps(mat_a_diag_inv[2], mat_a_diag_inv[3], 0xCC);//diag 4,5,6,7 mat_a_diag_inv[0] = _mm256_blend_ps(mat_a_diag_inv[0], mat_a_diag_inv[2], 0xF0);//diag 0,1,2,3,4,5,6,7 //reciprocal of diagnal elements of A :- 0,1,2,3,4,5,6,7 reciprocal_diags[0] = _mm256_div_ps(reciprocal_diags[0], mat_a_diag_inv[0]); i = 0; i2 = 0; for (k = 0; k < numCols_b; k += 8) { i = i1 + k; //Read 8 cols of B columns of Block-to-be-solved mat_b_rearr[i2][0] = _mm256_loadu_ps((float const *)ptr_b + i); mat_b_rearr[i2][1] = _mm256_loadu_ps((float const *)(ptr_b + cs_b + i)); mat_b_rearr[i2][2] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[0] + i)); mat_b_rearr[i2][3] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[1] + i)); mat_b_rearr[i2][4] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[2] + i)); mat_b_rearr[i2][5] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[3] + i)); mat_b_rearr[i2][6] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[4] + i)); mat_b_rearr[i2][7] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[5] + i)); mat_b_rearr[i2][0] = _mm256_mul_ps(mat_b_rearr[i2][0], alphaReg); mat_b_rearr[i2][1] = _mm256_mul_ps(mat_b_rearr[i2][1], alphaReg); mat_b_rearr[i2][2] = _mm256_mul_ps(mat_b_rearr[i2][2], alphaReg); mat_b_rearr[i2][3] = _mm256_mul_ps(mat_b_rearr[i2][3], alphaReg); mat_b_rearr[i2][4] = _mm256_mul_ps(mat_b_rearr[i2][4], alphaReg); mat_b_rearr[i2][5] = _mm256_mul_ps(mat_b_rearr[i2][5], alphaReg); mat_b_rearr[i2][6] = _mm256_mul_ps(mat_b_rearr[i2][6], alphaReg); mat_b_rearr[i2][7] = _mm256_mul_ps(mat_b_rearr[i2][7], alphaReg); i2++; } i = 0; i2 = 0; for (l = 0; l < j; l += 8) // move across m { //Broadcast A8,0 to A15,0 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + i)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + i + 1)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l + i + 2)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l + i + 3)); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l + i + 4)); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l + i + 5)); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l + i + 6)); mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l + i + 7)); //Broadcast A21 to A71 to registers mat_a_blk_elems[8] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + i)); mat_a_blk_elems[9] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + i + 1)); mat_a_blk_elems[10] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + i + 2)); mat_a_blk_elems[11] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + i + 3)); mat_a_blk_elems[12] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + i + 4)); mat_a_blk_elems[13] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + i + 5)); mat_a_blk_elems[14] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + i + 6)); mat_a_blk_elems[15] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + i + 7)); //Broadcast A8,2 to A15,2 to registers mat_a_blk_elems[16] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + i)); mat_a_blk_elems[17] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + i + 1)); mat_a_blk_elems[18] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + i + 2)); mat_a_blk_elems[19] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + i + 3)); mat_a_blk_elems[20] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + i + 4)); mat_a_blk_elems[21] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + i + 5)); mat_a_blk_elems[22] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + i + 6)); mat_a_blk_elems[23] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + i + 7)); //Broadcast A8,3 to A15,3 to registers mat_a_blk_elems[24] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + i)); mat_a_blk_elems[25] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + i + 1)); mat_a_blk_elems[26] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + i + 2)); mat_a_blk_elems[27] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + i + 3)); mat_a_blk_elems[28] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + i + 4)); mat_a_blk_elems[29] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + i + 5)); mat_a_blk_elems[30] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + i + 6)); mat_a_blk_elems[31] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + i + 7)); // _mm256_permute2f128_ps() //Broadcast A8,4 to A15,4 to registers mat_a_blk_elems[32] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[2] + i)); mat_a_blk_elems[33] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[2] + i + 1)); mat_a_blk_elems[34] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[2] + i + 2)); mat_a_blk_elems[35] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[2] + i + 3)); mat_a_blk_elems[36] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[2] + i + 4)); mat_a_blk_elems[37] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[2] + i + 5)); mat_a_blk_elems[38] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[2] + i + 6)); mat_a_blk_elems[39] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[2] + i + 7)); //Broadcast A8,5 to A15,5 to registers mat_a_blk_elems[40] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[3] + i)); mat_a_blk_elems[41] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[3] + i + 1)); mat_a_blk_elems[42] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[3] + i + 2)); mat_a_blk_elems[43] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[3] + i + 3)); mat_a_blk_elems[44] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[3] + i + 4)); mat_a_blk_elems[45] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[3] + i + 5)); mat_a_blk_elems[46] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[3] + i + 6)); mat_a_blk_elems[47] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[3] + i + 7)); //Broadcast A8,6 to A15,6 to registers mat_a_blk_elems[48] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[4] + i)); mat_a_blk_elems[49] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[4] + i + 1)); mat_a_blk_elems[50] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[4] + i + 2)); mat_a_blk_elems[51] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[4] + i + 3)); mat_a_blk_elems[52] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[4] + i + 4)); mat_a_blk_elems[53] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[4] + i + 5)); mat_a_blk_elems[54] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[4] + i + 6)); mat_a_blk_elems[55] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[4] + i + 7)); //Broadcast A8,7 to A15,7 to registers mat_a_blk_elems[56] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[5] + i)); mat_a_blk_elems[57] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[5] + i + 1)); mat_a_blk_elems[58] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[5] + i + 2)); mat_a_blk_elems[59] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[5] + i + 3)); mat_a_blk_elems[60] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[5] + i + 4)); mat_a_blk_elems[61] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[5] + i + 5)); mat_a_blk_elems[62] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[5] + i + 6)); mat_a_blk_elems[63] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[5] + i + 7)); i += cs_l_offset[6]; for (k = 0; k < numCols_b; k += 8) // move across n for the same value of l (index of m) { /////////////////// Partial Lower 8x8 block trsm of B i4 = i2 + k; //Read current 8 cols of B columns from specified 8x8 current-block of B mat_b_col[0] = _mm256_loadu_ps((float const *)ptr_b + i4); mat_b_col[1] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b)); mat_b_col[2] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b_offset[0])); mat_b_col[3] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b_offset[1])); mat_b_col[4] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b_offset[2])); mat_b_col[5] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b_offset[3])); mat_b_col[6] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b_offset[4])); mat_b_col[7] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b_offset[5])); i4 = k >> 3; //(Row8): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[i4][0] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[0], mat_b_rearr[i4][0]);//d = c - (a*b) mat_b_rearr[i4][1] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[0], mat_b_rearr[i4][1]);//d = c - (a*b) mat_b_rearr[i4][2] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[0], mat_b_rearr[i4][2]);//d = c - (a*b) mat_b_rearr[i4][3] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[0], mat_b_rearr[i4][3]);//d = c - (a*b) mat_b_rearr[i4][4] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[0], mat_b_rearr[i4][4]);//d = c - (a*b) mat_b_rearr[i4][5] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[0], mat_b_rearr[i4][5]);//d = c - (a*b) mat_b_rearr[i4][6] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_col[0], mat_b_rearr[i4][6]);//d = c - (a*b) mat_b_rearr[i4][7] = _mm256_fnmadd_ps(mat_a_blk_elems[7], mat_b_col[0], mat_b_rearr[i4][7]);//d = c - (a*b) //(Row9): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[i4][0] = _mm256_fnmadd_ps(mat_a_blk_elems[8], mat_b_col[1], mat_b_rearr[i4][0]);//d = c - (a*b) mat_b_rearr[i4][1] = _mm256_fnmadd_ps(mat_a_blk_elems[9], mat_b_col[1], mat_b_rearr[i4][1]);//d = c - (a*b) mat_b_rearr[i4][2] = _mm256_fnmadd_ps(mat_a_blk_elems[10], mat_b_col[1], mat_b_rearr[i4][2]);//d = c - (a*b) mat_b_rearr[i4][3] = _mm256_fnmadd_ps(mat_a_blk_elems[11], mat_b_col[1], mat_b_rearr[i4][3]);//d = c - (a*b) mat_b_rearr[i4][4] = _mm256_fnmadd_ps(mat_a_blk_elems[12], mat_b_col[1], mat_b_rearr[i4][4]);//d = c - (a*b) mat_b_rearr[i4][5] = _mm256_fnmadd_ps(mat_a_blk_elems[13], mat_b_col[1], mat_b_rearr[i4][5]);//d = c - (a*b) mat_b_rearr[i4][6] = _mm256_fnmadd_ps(mat_a_blk_elems[14], mat_b_col[1], mat_b_rearr[i4][6]);//d = c - (a*b) mat_b_rearr[i4][7] = _mm256_fnmadd_ps(mat_a_blk_elems[15], mat_b_col[1], mat_b_rearr[i4][7]);//d = c - (a*b) //(Row10): FMA operations of b2 with elements of indices from (2, 0) uptill (7, 0) mat_b_rearr[i4][0] = _mm256_fnmadd_ps(mat_a_blk_elems[16], mat_b_col[2], mat_b_rearr[i4][0]);//d = c - (a*b) mat_b_rearr[i4][1] = _mm256_fnmadd_ps(mat_a_blk_elems[17], mat_b_col[2], mat_b_rearr[i4][1]);//d = c - (a*b) mat_b_rearr[i4][2] = _mm256_fnmadd_ps(mat_a_blk_elems[18], mat_b_col[2], mat_b_rearr[i4][2]);//d = c - (a*b) mat_b_rearr[i4][3] = _mm256_fnmadd_ps(mat_a_blk_elems[19], mat_b_col[2], mat_b_rearr[i4][3]);//d = c - (a*b) mat_b_rearr[i4][4] = _mm256_fnmadd_ps(mat_a_blk_elems[20], mat_b_col[2], mat_b_rearr[i4][4]);//d = c - (a*b) mat_b_rearr[i4][5] = _mm256_fnmadd_ps(mat_a_blk_elems[21], mat_b_col[2], mat_b_rearr[i4][5]);//d = c - (a*b) mat_b_rearr[i4][6] = _mm256_fnmadd_ps(mat_a_blk_elems[22], mat_b_col[2], mat_b_rearr[i4][6]);//d = c - (a*b) mat_b_rearr[i4][7] = _mm256_fnmadd_ps(mat_a_blk_elems[23], mat_b_col[2], mat_b_rearr[i4][7]);//d = c - (a*b) //(Row11): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[i4][0] = _mm256_fnmadd_ps(mat_a_blk_elems[24], mat_b_col[3], mat_b_rearr[i4][0]);//d = c - (a*b) mat_b_rearr[i4][1] = _mm256_fnmadd_ps(mat_a_blk_elems[25], mat_b_col[3], mat_b_rearr[i4][1]);//d = c - (a*b) mat_b_rearr[i4][2] = _mm256_fnmadd_ps(mat_a_blk_elems[26], mat_b_col[3], mat_b_rearr[i4][2]);//d = c - (a*b) mat_b_rearr[i4][3] = _mm256_fnmadd_ps(mat_a_blk_elems[27], mat_b_col[3], mat_b_rearr[i4][3]);//d = c - (a*b) mat_b_rearr[i4][4] = _mm256_fnmadd_ps(mat_a_blk_elems[28], mat_b_col[3], mat_b_rearr[i4][4]);//d = c - (a*b) mat_b_rearr[i4][5] = _mm256_fnmadd_ps(mat_a_blk_elems[29], mat_b_col[3], mat_b_rearr[i4][5]);//d = c - (a*b) mat_b_rearr[i4][6] = _mm256_fnmadd_ps(mat_a_blk_elems[30], mat_b_col[3], mat_b_rearr[i4][6]);//d = c - (a*b) mat_b_rearr[i4][7] = _mm256_fnmadd_ps(mat_a_blk_elems[31], mat_b_col[3], mat_b_rearr[i4][7]);//d = c - (a*b) //(Row12): FMA operations of b2 with elements of indices from (2, 0) uptill (7, 0) mat_b_rearr[i4][0] = _mm256_fnmadd_ps(mat_a_blk_elems[32], mat_b_col[4], mat_b_rearr[i4][0]);//d = c - (a*b) mat_b_rearr[i4][1] = _mm256_fnmadd_ps(mat_a_blk_elems[33], mat_b_col[4], mat_b_rearr[i4][1]);//d = c - (a*b) mat_b_rearr[i4][2] = _mm256_fnmadd_ps(mat_a_blk_elems[34], mat_b_col[4], mat_b_rearr[i4][2]);//d = c - (a*b) mat_b_rearr[i4][3] = _mm256_fnmadd_ps(mat_a_blk_elems[35], mat_b_col[4], mat_b_rearr[i4][3]);//d = c - (a*b) mat_b_rearr[i4][4] = _mm256_fnmadd_ps(mat_a_blk_elems[36], mat_b_col[4], mat_b_rearr[i4][4]);//d = c - (a*b) mat_b_rearr[i4][5] = _mm256_fnmadd_ps(mat_a_blk_elems[37], mat_b_col[4], mat_b_rearr[i4][5]);//d = c - (a*b) mat_b_rearr[i4][6] = _mm256_fnmadd_ps(mat_a_blk_elems[38], mat_b_col[4], mat_b_rearr[i4][6]);//d = c - (a*b) mat_b_rearr[i4][7] = _mm256_fnmadd_ps(mat_a_blk_elems[39], mat_b_col[4], mat_b_rearr[i4][7]);//d = c - (a*b) //(Row13): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[i4][0] = _mm256_fnmadd_ps(mat_a_blk_elems[40], mat_b_col[5], mat_b_rearr[i4][0]);//d = c - (a*b) mat_b_rearr[i4][1] = _mm256_fnmadd_ps(mat_a_blk_elems[41], mat_b_col[5], mat_b_rearr[i4][1]);//d = c - (a*b) mat_b_rearr[i4][2] = _mm256_fnmadd_ps(mat_a_blk_elems[42], mat_b_col[5], mat_b_rearr[i4][2]);//d = c - (a*b) mat_b_rearr[i4][3] = _mm256_fnmadd_ps(mat_a_blk_elems[43], mat_b_col[5], mat_b_rearr[i4][3]);//d = c - (a*b) mat_b_rearr[i4][4] = _mm256_fnmadd_ps(mat_a_blk_elems[44], mat_b_col[5], mat_b_rearr[i4][4]);//d = c - (a*b) mat_b_rearr[i4][5] = _mm256_fnmadd_ps(mat_a_blk_elems[45], mat_b_col[5], mat_b_rearr[i4][5]);//d = c - (a*b) mat_b_rearr[i4][6] = _mm256_fnmadd_ps(mat_a_blk_elems[46], mat_b_col[5], mat_b_rearr[i4][6]);//d = c - (a*b) mat_b_rearr[i4][7] = _mm256_fnmadd_ps(mat_a_blk_elems[47], mat_b_col[5], mat_b_rearr[i4][7]);//d = c - (a*b) //(Row14): FMA operations of b2 with elements of indices from (2, 0) uptill (7, 0) mat_b_rearr[i4][0] = _mm256_fnmadd_ps(mat_a_blk_elems[48], mat_b_col[6], mat_b_rearr[i4][0]);//d = c - (a*b) mat_b_rearr[i4][1] = _mm256_fnmadd_ps(mat_a_blk_elems[49], mat_b_col[6], mat_b_rearr[i4][1]);//d = c - (a*b) mat_b_rearr[i4][2] = _mm256_fnmadd_ps(mat_a_blk_elems[50], mat_b_col[6], mat_b_rearr[i4][2]);//d = c - (a*b) mat_b_rearr[i4][3] = _mm256_fnmadd_ps(mat_a_blk_elems[51], mat_b_col[6], mat_b_rearr[i4][3]);//d = c - (a*b) mat_b_rearr[i4][4] = _mm256_fnmadd_ps(mat_a_blk_elems[52], mat_b_col[6], mat_b_rearr[i4][4]);//d = c - (a*b) mat_b_rearr[i4][5] = _mm256_fnmadd_ps(mat_a_blk_elems[53], mat_b_col[6], mat_b_rearr[i4][5]);//d = c - (a*b) mat_b_rearr[i4][6] = _mm256_fnmadd_ps(mat_a_blk_elems[54], mat_b_col[6], mat_b_rearr[i4][6]);//d = c - (a*b) mat_b_rearr[i4][7] = _mm256_fnmadd_ps(mat_a_blk_elems[55], mat_b_col[6], mat_b_rearr[i4][7]);//d = c - (a*b) //(Row15): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[i4][0] = _mm256_fnmadd_ps(mat_a_blk_elems[56], mat_b_col[7], mat_b_rearr[i4][0]);//d = c - (a*b) mat_b_rearr[i4][1] = _mm256_fnmadd_ps(mat_a_blk_elems[57], mat_b_col[7], mat_b_rearr[i4][1]);//d = c - (a*b) mat_b_rearr[i4][2] = _mm256_fnmadd_ps(mat_a_blk_elems[58], mat_b_col[7], mat_b_rearr[i4][2]);//d = c - (a*b) mat_b_rearr[i4][3] = _mm256_fnmadd_ps(mat_a_blk_elems[59], mat_b_col[7], mat_b_rearr[i4][3]);//d = c - (a*b) mat_b_rearr[i4][4] = _mm256_fnmadd_ps(mat_a_blk_elems[60], mat_b_col[7], mat_b_rearr[i4][4]);//d = c - (a*b) mat_b_rearr[i4][5] = _mm256_fnmadd_ps(mat_a_blk_elems[61], mat_b_col[7], mat_b_rearr[i4][5]);//d = c - (a*b) mat_b_rearr[i4][6] = _mm256_fnmadd_ps(mat_a_blk_elems[62], mat_b_col[7], mat_b_rearr[i4][6]);//d = c - (a*b) mat_b_rearr[i4][7] = _mm256_fnmadd_ps(mat_a_blk_elems[63], mat_b_col[7], mat_b_rearr[i4][7]);//d = c - (a*b) //end loop of cols } i2 += cs_b_offset[6]; } //Broadcast A10 to A70 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + i + 1)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + i + 2)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l + i + 3)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l + i + 4)); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l + i + 5)); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l + i + 6)); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l + i + 7)); i += cs_l; //extract diag a00 from a mat_a_diag_inv[0] = _mm256_permute_ps(reciprocal_diags[0], 0x00); mat_a_diag_inv[0] = _mm256_permute2f128_ps(mat_a_diag_inv[0], mat_a_diag_inv[0], 0x00); //mat_a_diag_inv2[0] = _mm256_unpacklo_ps(mat_a_diag_inv2[0], mat_a_diag_inv2[0]); //Broadcast A21 to A71 to registers mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l + i + 2)); mat_a_blk_elems[8] = _mm256_broadcast_ss((float const *)(ptr_l + i + 3)); mat_a_blk_elems[9] = _mm256_broadcast_ss((float const *)(ptr_l + i + 4)); mat_a_blk_elems[10] = _mm256_broadcast_ss((float const *)(ptr_l + i + 5)); mat_a_blk_elems[11] = _mm256_broadcast_ss((float const *)(ptr_l + i + 6)); mat_a_blk_elems[12] = _mm256_broadcast_ss((float const *)(ptr_l + i + 7)); i += cs_l; //extract diag a11 from a mat_a_diag_inv[1] = _mm256_permute_ps(reciprocal_diags[0], 0x55); mat_a_diag_inv[1] = _mm256_permute2f128_ps(mat_a_diag_inv[1], mat_a_diag_inv[1], 0x00); //mat_a_diag_inv[1] = _mm256_unpacklo_ps(mat_a_diag_inv[1], mat_a_diag_inv[1]); //Broadcast A32 to A72 to registers mat_a_blk_elems[13] = _mm256_broadcast_ss((float const *)(ptr_l + i + 3)); mat_a_blk_elems[14] = _mm256_broadcast_ss((float const *)(ptr_l + i + 4)); mat_a_blk_elems[15] = _mm256_broadcast_ss((float const *)(ptr_l + i + 5)); mat_a_blk_elems[16] = _mm256_broadcast_ss((float const *)(ptr_l + i + 6)); mat_a_blk_elems[17] = _mm256_broadcast_ss((float const *)(ptr_l + i + 7)); i += cs_l; //extract diag a22 from a mat_a_diag_inv[2] = _mm256_permute_ps(reciprocal_diags[0], 0xAA); mat_a_diag_inv[2] = _mm256_permute2f128_ps(mat_a_diag_inv[2], mat_a_diag_inv[2], 0x00); //mat_a_diag_inv[2] = _mm256_unpacklo_ps(mat_a_diag_inv[2], mat_a_diag_inv[2]); //Broadcast A43 to A73 to registers mat_a_blk_elems[18] = _mm256_broadcast_ss((float const *)(ptr_l + i + 4)); mat_a_blk_elems[19] = _mm256_broadcast_ss((float const *)(ptr_l + i + 5)); mat_a_blk_elems[20] = _mm256_broadcast_ss((float const *)(ptr_l + i + 6)); mat_a_blk_elems[21] = _mm256_broadcast_ss((float const *)(ptr_l + i + 7)); i += cs_l; //extract diag a33 from a mat_a_diag_inv[3] = _mm256_permute_ps(reciprocal_diags[0], 0xFF); mat_a_diag_inv[3] = _mm256_permute2f128_ps(mat_a_diag_inv[3], mat_a_diag_inv[3], 0x00); //mat_a_diag_inv[3] = _mm256_unpacklo_ps(mat_a_diag_inv[3], mat_a_diag_inv[3]); //Broadcast A54 to A74 to registers mat_a_blk_elems[22] = _mm256_broadcast_ss((float const *)(ptr_l + i + 5)); mat_a_blk_elems[23] = _mm256_broadcast_ss((float const *)(ptr_l + i + 6)); mat_a_blk_elems[24] = _mm256_broadcast_ss((float const *)(ptr_l + i + 7)); i += cs_l; //extract diag a44 from a mat_a_diag_inv[4] = _mm256_permute_ps(reciprocal_diags[0], 0x00); mat_a_diag_inv[4] = _mm256_permute2f128_ps(mat_a_diag_inv[4], mat_a_diag_inv[4], 0x11); //mat_a_diag_inv[4] = _mm256_unpacklo_ps(mat_a_diag_inv[4], mat_a_diag_inv[4]); //Broadcast A65 to A75 to registers mat_a_blk_elems[25] = _mm256_broadcast_ss((float const *)(ptr_l + i + 6)); mat_a_blk_elems[26] = _mm256_broadcast_ss((float const *)(ptr_l + i + 7)); i += cs_l; //extract diag a55 from a mat_a_diag_inv[5] = _mm256_permute_ps(reciprocal_diags[0], 0x55); mat_a_diag_inv[5] = _mm256_permute2f128_ps(mat_a_diag_inv[5], mat_a_diag_inv[5], 0x11); //mat_a_diag_inv[5] = _mm256_unpacklo_ps(mat_a_diag_inv[5], mat_a_diag_inv[5]); //Broadcast A76 to register mat_a_blk_elems[27] = _mm256_broadcast_ss((float const *)(ptr_l + i + 7)); //extract diag a66 from a mat_a_diag_inv[6] = _mm256_permute_ps(reciprocal_diags[0], 0xAA); mat_a_diag_inv[6] = _mm256_permute2f128_ps(mat_a_diag_inv[6], mat_a_diag_inv[6], 0x11); //mat_a_diag_inv[6] = _mm256_unpacklo_ps(mat_a_diag_inv[6], mat_a_diag_inv[6]); //extract diag a77 from a mat_a_diag_inv[7] = _mm256_permute_ps(reciprocal_diags[0], 0xFF); mat_a_diag_inv[7] = _mm256_permute2f128_ps(mat_a_diag_inv[7], mat_a_diag_inv[7], 0x11); //mat_a_diag_inv[7] = _mm256_unpacklo_ps(mat_a_diag_inv[7], mat_a_diag_inv[7]); k = 0; for (i = 0; i < numCols_b; i+=8) { /////////////////// Complete Lower 8x8 block trsm of B :- lower 8x8 block of B with lower right 8x8 block of A //(Row0): Perform mul operation of reciprocal of L(0,0) element with 1st row elements of B mat_b_rearr[k][0] = _mm256_mul_ps(mat_b_rearr[k][0], mat_a_diag_inv[0]); //(Row1): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[k][1] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_rearr[k][0], mat_b_rearr[k][1]);//d = c - (a*b) mat_b_rearr[k][2] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_rearr[k][0], mat_b_rearr[k][2]);//d = c - (a*b) mat_b_rearr[k][3] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_rearr[k][0], mat_b_rearr[k][3]);//d = c - (a*b) mat_b_rearr[k][4] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_rearr[k][0], mat_b_rearr[k][4]);//d = c - (a*b) mat_b_rearr[k][5] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_rearr[k][0], mat_b_rearr[k][5]);//d = c - (a*b) mat_b_rearr[k][6] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_rearr[k][0], mat_b_rearr[k][6]);//d = c - (a*b) mat_b_rearr[k][7] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_rearr[k][0], mat_b_rearr[k][7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(1,1) element with 2nd row elements of B mat_b_rearr[k][1] = _mm256_mul_ps(mat_b_rearr[k][1], mat_a_diag_inv[1]); //(Row2): FMA operations of b2 with elements of indices from (2, 0) uptill (7, 0) mat_b_rearr[k][2] = _mm256_fnmadd_ps(mat_a_blk_elems[7], mat_b_rearr[k][1], mat_b_rearr[k][2]);//d = c - (a*b) mat_b_rearr[k][3] = _mm256_fnmadd_ps(mat_a_blk_elems[8], mat_b_rearr[k][1], mat_b_rearr[k][3]);//d = c - (a*b) mat_b_rearr[k][4] = _mm256_fnmadd_ps(mat_a_blk_elems[9], mat_b_rearr[k][1], mat_b_rearr[k][4]);//d = c - (a*b) mat_b_rearr[k][5] = _mm256_fnmadd_ps(mat_a_blk_elems[10], mat_b_rearr[k][1], mat_b_rearr[k][5]);//d = c - (a*b) mat_b_rearr[k][6] = _mm256_fnmadd_ps(mat_a_blk_elems[11], mat_b_rearr[k][1], mat_b_rearr[k][6]);//d = c - (a*b) mat_b_rearr[k][7] = _mm256_fnmadd_ps(mat_a_blk_elems[12], mat_b_rearr[k][1], mat_b_rearr[k][7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(2, 2) element with 3rd row elements of B mat_b_rearr[k][2] = _mm256_mul_ps(mat_b_rearr[k][2], mat_a_diag_inv[2]); //(Row3): FMA operations of b3 with elements of indices from (3, 0) uptill (7, 0) mat_b_rearr[k][3] = _mm256_fnmadd_ps(mat_a_blk_elems[13], mat_b_rearr[k][2], mat_b_rearr[k][3]);//d = c - (a*b) mat_b_rearr[k][4] = _mm256_fnmadd_ps(mat_a_blk_elems[14], mat_b_rearr[k][2], mat_b_rearr[k][4]);//d = c - (a*b) mat_b_rearr[k][5] = _mm256_fnmadd_ps(mat_a_blk_elems[15], mat_b_rearr[k][2], mat_b_rearr[k][5]);//d = c - (a*b) mat_b_rearr[k][6] = _mm256_fnmadd_ps(mat_a_blk_elems[16], mat_b_rearr[k][2], mat_b_rearr[k][6]);//d = c - (a*b) mat_b_rearr[k][7] = _mm256_fnmadd_ps(mat_a_blk_elems[17], mat_b_rearr[k][2], mat_b_rearr[k][7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(3, 3) element with 4rth row elements of B mat_b_rearr[k][3] = _mm256_mul_ps(mat_b_rearr[k][3], mat_a_diag_inv[3]); //(Row4): FMA operations of b4 with elements of indices from (4, 0) uptill (7, 0) mat_b_rearr[k][4] = _mm256_fnmadd_ps(mat_a_blk_elems[18], mat_b_rearr[k][3], mat_b_rearr[k][4]);//d = c - (a*b) mat_b_rearr[k][5] = _mm256_fnmadd_ps(mat_a_blk_elems[19], mat_b_rearr[k][3], mat_b_rearr[k][5]);//d = c - (a*b) mat_b_rearr[k][6] = _mm256_fnmadd_ps(mat_a_blk_elems[20], mat_b_rearr[k][3], mat_b_rearr[k][6]);//d = c - (a*b) mat_b_rearr[k][7] = _mm256_fnmadd_ps(mat_a_blk_elems[21], mat_b_rearr[k][3], mat_b_rearr[k][7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(4, 4) element with 4rth row elements of B mat_b_rearr[k][4] = _mm256_mul_ps(mat_b_rearr[k][4], mat_a_diag_inv[4]); //(Row5): FMA operations of b5 with elements of indices from (5, 0) uptill (7, 0) mat_b_rearr[k][5] = _mm256_fnmadd_ps(mat_a_blk_elems[22], mat_b_rearr[k][4], mat_b_rearr[k][5]);//d = c - (a*b) mat_b_rearr[k][6] = _mm256_fnmadd_ps(mat_a_blk_elems[23], mat_b_rearr[k][4], mat_b_rearr[k][6]);//d = c - (a*b) mat_b_rearr[k][7] = _mm256_fnmadd_ps(mat_a_blk_elems[24], mat_b_rearr[k][4], mat_b_rearr[k][7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(5, 5) element with 5th row elements of B mat_b_rearr[k][5] = _mm256_mul_ps(mat_b_rearr[k][5], mat_a_diag_inv[5]); //(Row6): FMA operations of b6 with elements of indices from (6, 0) uptill (7, 0) mat_b_rearr[k][6] = _mm256_fnmadd_ps(mat_a_blk_elems[25], mat_b_rearr[k][5], mat_b_rearr[k][6]);//d = c - (a*b) mat_b_rearr[k][7] = _mm256_fnmadd_ps(mat_a_blk_elems[26], mat_b_rearr[k][5], mat_b_rearr[k][7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(6, 6) element with 6th row elements of B mat_b_rearr[k][6] = _mm256_mul_ps(mat_b_rearr[k][6], mat_a_diag_inv[6]); //(Row7): FMA operations of b7 with elements of index (7, 0) mat_b_rearr[k][7] = _mm256_fnmadd_ps(mat_a_blk_elems[27], mat_b_rearr[k][6], mat_b_rearr[k][7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(7, 7) element with 7th row elements of B mat_b_rearr[k][7] = _mm256_mul_ps(mat_b_rearr[k][7], mat_a_diag_inv[7]); //////////////////////////////////////////////////////////////////////////////// //Store the computed B columns _mm256_storeu_ps((float *)ptr_b_dup + i, mat_b_rearr[k][0]); _mm256_storeu_ps((float *)(ptr_b_dup + (cs_b) + i), mat_b_rearr[k][1]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[0] + i), mat_b_rearr[k][2]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[1] + i), mat_b_rearr[k][3]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[2] + i), mat_b_rearr[k][4]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[3] + i), mat_b_rearr[k][5]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[4] + i), mat_b_rearr[k][6]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[5] + i), mat_b_rearr[k][7]); k++; } } ///////////////////loop ends ///////////////////// } static void trsm_XAtB_block_allSmallSizedMatrices_unitDiag(float *ptr_l, float *ptr_b, int numRows_lb, int numCols_b, int rs_l, int rs_b, int cs_l, int cs_b) { //float ones = 1.0; int i, i1, i2, i3, i4, j, k, l; int cs_b_offset[7]; int cs_l_offset[7]; float *ptr_b_dup; //57 number of ymm(256 bits) registers used __m256 mat_b_col[8]; __m256 mat_b_rearr[16][8]; //__m256 mat_a_cols_rearr[8]; __m256 mat_a_blk_elems[64]; //__m256 mat_a_diag_inv[8]; //__m256 reciprocal_diags[2]; // ---> considering that the matrix size is multiple of 16 rows and 8 cols <--- // //L matrix offsets cs_l_offset[0] = (cs_l << 1); cs_l_offset[1] = cs_l + cs_l_offset[0]; cs_l_offset[2] = (cs_l << 2); cs_l_offset[3] = cs_l + cs_l_offset[2]; cs_l_offset[4] = cs_l_offset[0] + cs_l_offset[2]; cs_l_offset[5] = cs_l + cs_l_offset[4]; cs_l_offset[6] = (cs_l_offset[5] + cs_l); cs_b_offset[0] = (cs_b << 1); cs_b_offset[1] = cs_b + cs_b_offset[0]; cs_b_offset[2] = (cs_b << 2); cs_b_offset[3] = cs_b + cs_b_offset[2]; cs_b_offset[4] = cs_b_offset[0] + cs_b_offset[2]; cs_b_offset[5] = cs_b + cs_b_offset[4]; cs_b_offset[6] = (cs_b_offset[5] + cs_b); //Broadcast A10 to A70 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + 1)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + 2)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l + 3)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l + 4)); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l + 5)); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l + 6)); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l + 7)); //Broadcast A21 to A71 to registers mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 2)); mat_a_blk_elems[8] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 3)); mat_a_blk_elems[9] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 4)); mat_a_blk_elems[10] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 5)); mat_a_blk_elems[11] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 6)); mat_a_blk_elems[12] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 7)); //Broadcast A32 to A72 to registers mat_a_blk_elems[13] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + 3)); mat_a_blk_elems[14] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + 4)); mat_a_blk_elems[15] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + 5)); mat_a_blk_elems[16] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + 6)); mat_a_blk_elems[17] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + 7)); //Broadcast A43 to A73 to registers mat_a_blk_elems[18] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + 4)); mat_a_blk_elems[19] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + 5)); mat_a_blk_elems[20] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + 6)); mat_a_blk_elems[21] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + 7)); //Broadcast A54 to A74 to registers mat_a_blk_elems[22] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[2] + 5)); mat_a_blk_elems[23] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[2] + 6)); mat_a_blk_elems[24] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[2] + 7)); //Broadcast A65 to A75 to registers mat_a_blk_elems[25] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[3] + 6)); mat_a_blk_elems[26] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[3] + 7)); //Broadcast A76 to register mat_a_blk_elems[27] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[4] + 7)); /***************** first set of 8 rows of B processing starts *****************/ ptr_b_dup = ptr_b; i = 0; for (j = 0; j < numCols_b; j += 8) { /////////////////// Complete Upper 8x8 block trsm of B :- upper 8x8 block of B with upper 8x8 block of A //read 8x8 block of B into registers mat_b_rearr[0][0] = _mm256_loadu_ps((float const *)ptr_b + i); mat_b_rearr[1][0] = _mm256_loadu_ps((float const *)(ptr_b + cs_b + i)); mat_b_rearr[2][0] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[0] + i)); mat_b_rearr[3][0] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[1] + i)); mat_b_rearr[4][0] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[2] + i)); mat_b_rearr[5][0] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[3] + i)); mat_b_rearr[6][0] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[4] + i)); mat_b_rearr[7][0] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[5] + i)); //(Row0) mat_b_col[0] = mat_b_rearr[0][0]; //(Row1): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_col[1] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[0], mat_b_rearr[1][0]);//d = c - (a*b) mat_b_rearr[2][0] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[0], mat_b_rearr[2][0]);//d = c - (a*b) mat_b_rearr[3][0] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[0], mat_b_rearr[3][0]);//d = c - (a*b) mat_b_rearr[4][0] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[0], mat_b_rearr[4][0]);//d = c - (a*b) mat_b_rearr[5][0] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[0], mat_b_rearr[5][0]);//d = c - (a*b) mat_b_rearr[6][0] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[0], mat_b_rearr[6][0]);//d = c - (a*b) mat_b_rearr[7][0] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_col[0], mat_b_rearr[7][0]);//d = c - (a*b) //(Row2): FMA operations of b2 with elements of indices from (2, 0) uptill (7, 0) mat_b_col[2] = _mm256_fnmadd_ps(mat_a_blk_elems[7], mat_b_col[1], mat_b_rearr[2][0]);//d = c - (a*b) mat_b_rearr[3][0] = _mm256_fnmadd_ps(mat_a_blk_elems[8], mat_b_col[1], mat_b_rearr[3][0]);//d = c - (a*b) mat_b_rearr[4][0] = _mm256_fnmadd_ps(mat_a_blk_elems[9], mat_b_col[1], mat_b_rearr[4][0]);//d = c - (a*b) mat_b_rearr[5][0] = _mm256_fnmadd_ps(mat_a_blk_elems[10], mat_b_col[1], mat_b_rearr[5][0]);//d = c - (a*b) mat_b_rearr[6][0] = _mm256_fnmadd_ps(mat_a_blk_elems[11], mat_b_col[1], mat_b_rearr[6][0]);//d = c - (a*b) mat_b_rearr[7][0] = _mm256_fnmadd_ps(mat_a_blk_elems[12], mat_b_col[1], mat_b_rearr[7][0]);//d = c - (a*b) //(Row3): FMA operations of b3 with elements of indices from (3, 0) uptill (7, 0) mat_b_col[3] = _mm256_fnmadd_ps(mat_a_blk_elems[13], mat_b_col[2], mat_b_rearr[3][0]);//d = c - (a*b) mat_b_rearr[4][0] = _mm256_fnmadd_ps(mat_a_blk_elems[14], mat_b_col[2], mat_b_rearr[4][0]);//d = c - (a*b) mat_b_rearr[5][0] = _mm256_fnmadd_ps(mat_a_blk_elems[15], mat_b_col[2], mat_b_rearr[5][0]);//d = c - (a*b) mat_b_rearr[6][0] = _mm256_fnmadd_ps(mat_a_blk_elems[16], mat_b_col[2], mat_b_rearr[6][0]);//d = c - (a*b) mat_b_rearr[7][0] = _mm256_fnmadd_ps(mat_a_blk_elems[17], mat_b_col[2], mat_b_rearr[7][0]);//d = c - (a*b) //(Row4): FMA operations of b4 with elements of indices from (4, 0) uptill (7, 0) mat_b_col[4] = _mm256_fnmadd_ps(mat_a_blk_elems[18], mat_b_col[3], mat_b_rearr[4][0]);//d = c - (a*b) mat_b_rearr[5][0] = _mm256_fnmadd_ps(mat_a_blk_elems[19], mat_b_col[3], mat_b_rearr[5][0]);//d = c - (a*b) mat_b_rearr[6][0] = _mm256_fnmadd_ps(mat_a_blk_elems[20], mat_b_col[3], mat_b_rearr[6][0]);//d = c - (a*b) mat_b_rearr[7][0] = _mm256_fnmadd_ps(mat_a_blk_elems[21], mat_b_col[3], mat_b_rearr[7][0]);//d = c - (a*b) //(Row5): FMA operations of b5 with elements of indices from (5, 0) uptill (7, 0) mat_b_col[5] = _mm256_fnmadd_ps(mat_a_blk_elems[22], mat_b_col[4], mat_b_rearr[5][0]);//d = c - (a*b) mat_b_rearr[6][0] = _mm256_fnmadd_ps(mat_a_blk_elems[23], mat_b_col[4], mat_b_rearr[6][0]);//d = c - (a*b) mat_b_rearr[7][0] = _mm256_fnmadd_ps(mat_a_blk_elems[24], mat_b_col[4], mat_b_rearr[7][0]);//d = c - (a*b) //(Row6): FMA operations of b6 with elements of indices from (6, 0) uptill (7, 0) mat_b_col[6] = _mm256_fnmadd_ps(mat_a_blk_elems[25], mat_b_col[5], mat_b_rearr[6][0]);//d = c - (a*b) mat_b_rearr[7][0] = _mm256_fnmadd_ps(mat_a_blk_elems[26], mat_b_col[5], mat_b_rearr[7][0]);//d = c - (a*b) //(Row7): FMA operations of b7 with elements of index (7, 0) mat_b_col[7] = _mm256_fnmadd_ps(mat_a_blk_elems[27], mat_b_col[6], mat_b_rearr[7][0]);//d = c - (a*b) //////////////////////////////////////////////////////////////////////////////// //Store the computed B columns _mm256_storeu_ps((float *)ptr_b_dup, mat_b_col[0]); _mm256_storeu_ps((float *)(ptr_b_dup + (cs_b)), mat_b_col[1]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[0]), mat_b_col[2]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[1]), mat_b_col[3]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[2]), mat_b_col[4]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[3]), mat_b_col[5]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[4]), mat_b_col[6]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[5]), mat_b_col[7]); //i += cs_b_offset[6]; //ptr_b_dup += cs_b_offset[6]; i += 8; ptr_b_dup += 8; } //c = 0; /***************** first set of 8 cols of B processing done *****************/ ptr_b_dup = ptr_b; i3 = 0; i1 = 0; //Start loop for cols of B to be processed in size of blk_width for (j = 8; j < numRows_lb; j += 8)//m :- 8x8 block row { ptr_l += 8; //ptr_b += j; //ptr_b_dup += 8; ptr_b_dup += cs_b_offset[6]; i1 += cs_b_offset[6]; i3 += cs_l_offset[6]; i = 0; i2 = 0; for (k = 0; k < numCols_b; k += 8) { i = i1 + k; //Read 8 cols of B columns of Block-to-be-solved mat_b_rearr[i2][0] = _mm256_loadu_ps((float const *)ptr_b + i); mat_b_rearr[i2][1] = _mm256_loadu_ps((float const *)(ptr_b + cs_b + i)); mat_b_rearr[i2][2] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[0] + i)); mat_b_rearr[i2][3] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[1] + i)); mat_b_rearr[i2][4] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[2] + i)); mat_b_rearr[i2][5] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[3] + i)); mat_b_rearr[i2][6] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[4] + i)); mat_b_rearr[i2][7] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[5] + i)); i2++; } i = 0; i2 = 0; for (l = 0; l < j; l += 8) // move across m { //Broadcast A8,0 to A15,0 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + i)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + i + 1)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l + i + 2)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l + i + 3)); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l + i + 4)); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l + i + 5)); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l + i + 6)); mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l + i + 7)); //Broadcast A21 to A71 to registers mat_a_blk_elems[8] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + i)); mat_a_blk_elems[9] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + i + 1)); mat_a_blk_elems[10] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + i + 2)); mat_a_blk_elems[11] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + i + 3)); mat_a_blk_elems[12] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + i + 4)); mat_a_blk_elems[13] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + i + 5)); mat_a_blk_elems[14] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + i + 6)); mat_a_blk_elems[15] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + i + 7)); //Broadcast A8,2 to A15,2 to registers mat_a_blk_elems[16] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + i)); mat_a_blk_elems[17] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + i + 1)); mat_a_blk_elems[18] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + i + 2)); mat_a_blk_elems[19] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + i + 3)); mat_a_blk_elems[20] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + i + 4)); mat_a_blk_elems[21] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + i + 5)); mat_a_blk_elems[22] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + i + 6)); mat_a_blk_elems[23] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + i + 7)); //Broadcast A8,3 to A15,3 to registers mat_a_blk_elems[24] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + i)); mat_a_blk_elems[25] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + i + 1)); mat_a_blk_elems[26] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + i + 2)); mat_a_blk_elems[27] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + i + 3)); mat_a_blk_elems[28] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + i + 4)); mat_a_blk_elems[29] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + i + 5)); mat_a_blk_elems[30] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + i + 6)); mat_a_blk_elems[31] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + i + 7)); // _mm256_permute2f128_ps() //Broadcast A8,4 to A15,4 to registers mat_a_blk_elems[32] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[2] + i)); mat_a_blk_elems[33] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[2] + i + 1)); mat_a_blk_elems[34] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[2] + i + 2)); mat_a_blk_elems[35] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[2] + i + 3)); mat_a_blk_elems[36] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[2] + i + 4)); mat_a_blk_elems[37] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[2] + i + 5)); mat_a_blk_elems[38] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[2] + i + 6)); mat_a_blk_elems[39] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[2] + i + 7)); //Broadcast A8,5 to A15,5 to registers mat_a_blk_elems[40] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[3] + i)); mat_a_blk_elems[41] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[3] + i + 1)); mat_a_blk_elems[42] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[3] + i + 2)); mat_a_blk_elems[43] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[3] + i + 3)); mat_a_blk_elems[44] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[3] + i + 4)); mat_a_blk_elems[45] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[3] + i + 5)); mat_a_blk_elems[46] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[3] + i + 6)); mat_a_blk_elems[47] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[3] + i + 7)); //Broadcast A8,6 to A15,6 to registers mat_a_blk_elems[48] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[4] + i)); mat_a_blk_elems[49] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[4] + i + 1)); mat_a_blk_elems[50] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[4] + i + 2)); mat_a_blk_elems[51] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[4] + i + 3)); mat_a_blk_elems[52] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[4] + i + 4)); mat_a_blk_elems[53] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[4] + i + 5)); mat_a_blk_elems[54] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[4] + i + 6)); mat_a_blk_elems[55] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[4] + i + 7)); //Broadcast A8,7 to A15,7 to registers mat_a_blk_elems[56] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[5] + i)); mat_a_blk_elems[57] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[5] + i + 1)); mat_a_blk_elems[58] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[5] + i + 2)); mat_a_blk_elems[59] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[5] + i + 3)); mat_a_blk_elems[60] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[5] + i + 4)); mat_a_blk_elems[61] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[5] + i + 5)); mat_a_blk_elems[62] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[5] + i + 6)); mat_a_blk_elems[63] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[5] + i + 7)); i += cs_l_offset[6]; for (k = 0; k < numCols_b; k += 8) // move across n for the same value of l (index of m) { /////////////////// Partial Lower 8x8 block trsm of B i4 = i2 + k; //Read current 8 cols of B columns from specified 8x8 current-block of B mat_b_col[0] = _mm256_loadu_ps((float const *)ptr_b + i4); mat_b_col[1] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b)); mat_b_col[2] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b_offset[0])); mat_b_col[3] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b_offset[1])); mat_b_col[4] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b_offset[2])); mat_b_col[5] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b_offset[3])); mat_b_col[6] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b_offset[4])); mat_b_col[7] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b_offset[5])); i4 = k >> 3; //(Row8): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[i4][0] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[0], mat_b_rearr[i4][0]);//d = c - (a*b) mat_b_rearr[i4][1] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[0], mat_b_rearr[i4][1]);//d = c - (a*b) mat_b_rearr[i4][2] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[0], mat_b_rearr[i4][2]);//d = c - (a*b) mat_b_rearr[i4][3] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[0], mat_b_rearr[i4][3]);//d = c - (a*b) mat_b_rearr[i4][4] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[0], mat_b_rearr[i4][4]);//d = c - (a*b) mat_b_rearr[i4][5] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[0], mat_b_rearr[i4][5]);//d = c - (a*b) mat_b_rearr[i4][6] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_col[0], mat_b_rearr[i4][6]);//d = c - (a*b) mat_b_rearr[i4][7] = _mm256_fnmadd_ps(mat_a_blk_elems[7], mat_b_col[0], mat_b_rearr[i4][7]);//d = c - (a*b) //(Row9): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[i4][0] = _mm256_fnmadd_ps(mat_a_blk_elems[8], mat_b_col[1], mat_b_rearr[i4][0]);//d = c - (a*b) mat_b_rearr[i4][1] = _mm256_fnmadd_ps(mat_a_blk_elems[9], mat_b_col[1], mat_b_rearr[i4][1]);//d = c - (a*b) mat_b_rearr[i4][2] = _mm256_fnmadd_ps(mat_a_blk_elems[10], mat_b_col[1], mat_b_rearr[i4][2]);//d = c - (a*b) mat_b_rearr[i4][3] = _mm256_fnmadd_ps(mat_a_blk_elems[11], mat_b_col[1], mat_b_rearr[i4][3]);//d = c - (a*b) mat_b_rearr[i4][4] = _mm256_fnmadd_ps(mat_a_blk_elems[12], mat_b_col[1], mat_b_rearr[i4][4]);//d = c - (a*b) mat_b_rearr[i4][5] = _mm256_fnmadd_ps(mat_a_blk_elems[13], mat_b_col[1], mat_b_rearr[i4][5]);//d = c - (a*b) mat_b_rearr[i4][6] = _mm256_fnmadd_ps(mat_a_blk_elems[14], mat_b_col[1], mat_b_rearr[i4][6]);//d = c - (a*b) mat_b_rearr[i4][7] = _mm256_fnmadd_ps(mat_a_blk_elems[15], mat_b_col[1], mat_b_rearr[i4][7]);//d = c - (a*b) //(Row10): FMA operations of b2 with elements of indices from (2, 0) uptill (7, 0) mat_b_rearr[i4][0] = _mm256_fnmadd_ps(mat_a_blk_elems[16], mat_b_col[2], mat_b_rearr[i4][0]);//d = c - (a*b) mat_b_rearr[i4][1] = _mm256_fnmadd_ps(mat_a_blk_elems[17], mat_b_col[2], mat_b_rearr[i4][1]);//d = c - (a*b) mat_b_rearr[i4][2] = _mm256_fnmadd_ps(mat_a_blk_elems[18], mat_b_col[2], mat_b_rearr[i4][2]);//d = c - (a*b) mat_b_rearr[i4][3] = _mm256_fnmadd_ps(mat_a_blk_elems[19], mat_b_col[2], mat_b_rearr[i4][3]);//d = c - (a*b) mat_b_rearr[i4][4] = _mm256_fnmadd_ps(mat_a_blk_elems[20], mat_b_col[2], mat_b_rearr[i4][4]);//d = c - (a*b) mat_b_rearr[i4][5] = _mm256_fnmadd_ps(mat_a_blk_elems[21], mat_b_col[2], mat_b_rearr[i4][5]);//d = c - (a*b) mat_b_rearr[i4][6] = _mm256_fnmadd_ps(mat_a_blk_elems[22], mat_b_col[2], mat_b_rearr[i4][6]);//d = c - (a*b) mat_b_rearr[i4][7] = _mm256_fnmadd_ps(mat_a_blk_elems[23], mat_b_col[2], mat_b_rearr[i4][7]);//d = c - (a*b) //(Row11): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[i4][0] = _mm256_fnmadd_ps(mat_a_blk_elems[24], mat_b_col[3], mat_b_rearr[i4][0]);//d = c - (a*b) mat_b_rearr[i4][1] = _mm256_fnmadd_ps(mat_a_blk_elems[25], mat_b_col[3], mat_b_rearr[i4][1]);//d = c - (a*b) mat_b_rearr[i4][2] = _mm256_fnmadd_ps(mat_a_blk_elems[26], mat_b_col[3], mat_b_rearr[i4][2]);//d = c - (a*b) mat_b_rearr[i4][3] = _mm256_fnmadd_ps(mat_a_blk_elems[27], mat_b_col[3], mat_b_rearr[i4][3]);//d = c - (a*b) mat_b_rearr[i4][4] = _mm256_fnmadd_ps(mat_a_blk_elems[28], mat_b_col[3], mat_b_rearr[i4][4]);//d = c - (a*b) mat_b_rearr[i4][5] = _mm256_fnmadd_ps(mat_a_blk_elems[29], mat_b_col[3], mat_b_rearr[i4][5]);//d = c - (a*b) mat_b_rearr[i4][6] = _mm256_fnmadd_ps(mat_a_blk_elems[30], mat_b_col[3], mat_b_rearr[i4][6]);//d = c - (a*b) mat_b_rearr[i4][7] = _mm256_fnmadd_ps(mat_a_blk_elems[31], mat_b_col[3], mat_b_rearr[i4][7]);//d = c - (a*b) //(Row12): FMA operations of b2 with elements of indices from (2, 0) uptill (7, 0) mat_b_rearr[i4][0] = _mm256_fnmadd_ps(mat_a_blk_elems[32], mat_b_col[4], mat_b_rearr[i4][0]);//d = c - (a*b) mat_b_rearr[i4][1] = _mm256_fnmadd_ps(mat_a_blk_elems[33], mat_b_col[4], mat_b_rearr[i4][1]);//d = c - (a*b) mat_b_rearr[i4][2] = _mm256_fnmadd_ps(mat_a_blk_elems[34], mat_b_col[4], mat_b_rearr[i4][2]);//d = c - (a*b) mat_b_rearr[i4][3] = _mm256_fnmadd_ps(mat_a_blk_elems[35], mat_b_col[4], mat_b_rearr[i4][3]);//d = c - (a*b) mat_b_rearr[i4][4] = _mm256_fnmadd_ps(mat_a_blk_elems[36], mat_b_col[4], mat_b_rearr[i4][4]);//d = c - (a*b) mat_b_rearr[i4][5] = _mm256_fnmadd_ps(mat_a_blk_elems[37], mat_b_col[4], mat_b_rearr[i4][5]);//d = c - (a*b) mat_b_rearr[i4][6] = _mm256_fnmadd_ps(mat_a_blk_elems[38], mat_b_col[4], mat_b_rearr[i4][6]);//d = c - (a*b) mat_b_rearr[i4][7] = _mm256_fnmadd_ps(mat_a_blk_elems[39], mat_b_col[4], mat_b_rearr[i4][7]);//d = c - (a*b) //(Row13): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[i4][0] = _mm256_fnmadd_ps(mat_a_blk_elems[40], mat_b_col[5], mat_b_rearr[i4][0]);//d = c - (a*b) mat_b_rearr[i4][1] = _mm256_fnmadd_ps(mat_a_blk_elems[41], mat_b_col[5], mat_b_rearr[i4][1]);//d = c - (a*b) mat_b_rearr[i4][2] = _mm256_fnmadd_ps(mat_a_blk_elems[42], mat_b_col[5], mat_b_rearr[i4][2]);//d = c - (a*b) mat_b_rearr[i4][3] = _mm256_fnmadd_ps(mat_a_blk_elems[43], mat_b_col[5], mat_b_rearr[i4][3]);//d = c - (a*b) mat_b_rearr[i4][4] = _mm256_fnmadd_ps(mat_a_blk_elems[44], mat_b_col[5], mat_b_rearr[i4][4]);//d = c - (a*b) mat_b_rearr[i4][5] = _mm256_fnmadd_ps(mat_a_blk_elems[45], mat_b_col[5], mat_b_rearr[i4][5]);//d = c - (a*b) mat_b_rearr[i4][6] = _mm256_fnmadd_ps(mat_a_blk_elems[46], mat_b_col[5], mat_b_rearr[i4][6]);//d = c - (a*b) mat_b_rearr[i4][7] = _mm256_fnmadd_ps(mat_a_blk_elems[47], mat_b_col[5], mat_b_rearr[i4][7]);//d = c - (a*b) //(Row14): FMA operations of b2 with elements of indices from (2, 0) uptill (7, 0) mat_b_rearr[i4][0] = _mm256_fnmadd_ps(mat_a_blk_elems[48], mat_b_col[6], mat_b_rearr[i4][0]);//d = c - (a*b) mat_b_rearr[i4][1] = _mm256_fnmadd_ps(mat_a_blk_elems[49], mat_b_col[6], mat_b_rearr[i4][1]);//d = c - (a*b) mat_b_rearr[i4][2] = _mm256_fnmadd_ps(mat_a_blk_elems[50], mat_b_col[6], mat_b_rearr[i4][2]);//d = c - (a*b) mat_b_rearr[i4][3] = _mm256_fnmadd_ps(mat_a_blk_elems[51], mat_b_col[6], mat_b_rearr[i4][3]);//d = c - (a*b) mat_b_rearr[i4][4] = _mm256_fnmadd_ps(mat_a_blk_elems[52], mat_b_col[6], mat_b_rearr[i4][4]);//d = c - (a*b) mat_b_rearr[i4][5] = _mm256_fnmadd_ps(mat_a_blk_elems[53], mat_b_col[6], mat_b_rearr[i4][5]);//d = c - (a*b) mat_b_rearr[i4][6] = _mm256_fnmadd_ps(mat_a_blk_elems[54], mat_b_col[6], mat_b_rearr[i4][6]);//d = c - (a*b) mat_b_rearr[i4][7] = _mm256_fnmadd_ps(mat_a_blk_elems[55], mat_b_col[6], mat_b_rearr[i4][7]);//d = c - (a*b) //(Row15): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[i4][0] = _mm256_fnmadd_ps(mat_a_blk_elems[56], mat_b_col[7], mat_b_rearr[i4][0]);//d = c - (a*b) mat_b_rearr[i4][1] = _mm256_fnmadd_ps(mat_a_blk_elems[57], mat_b_col[7], mat_b_rearr[i4][1]);//d = c - (a*b) mat_b_rearr[i4][2] = _mm256_fnmadd_ps(mat_a_blk_elems[58], mat_b_col[7], mat_b_rearr[i4][2]);//d = c - (a*b) mat_b_rearr[i4][3] = _mm256_fnmadd_ps(mat_a_blk_elems[59], mat_b_col[7], mat_b_rearr[i4][3]);//d = c - (a*b) mat_b_rearr[i4][4] = _mm256_fnmadd_ps(mat_a_blk_elems[60], mat_b_col[7], mat_b_rearr[i4][4]);//d = c - (a*b) mat_b_rearr[i4][5] = _mm256_fnmadd_ps(mat_a_blk_elems[61], mat_b_col[7], mat_b_rearr[i4][5]);//d = c - (a*b) mat_b_rearr[i4][6] = _mm256_fnmadd_ps(mat_a_blk_elems[62], mat_b_col[7], mat_b_rearr[i4][6]);//d = c - (a*b) mat_b_rearr[i4][7] = _mm256_fnmadd_ps(mat_a_blk_elems[63], mat_b_col[7], mat_b_rearr[i4][7]);//d = c - (a*b) //end loop of cols } i2 += cs_b_offset[6]; } //Broadcast A10 to A70 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + i + 1)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + i + 2)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l + i + 3)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l + i + 4)); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l + i + 5)); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l + i + 6)); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l + i + 7)); i += cs_l; //Broadcast A21 to A71 to registers mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l + i + 2)); mat_a_blk_elems[8] = _mm256_broadcast_ss((float const *)(ptr_l + i + 3)); mat_a_blk_elems[9] = _mm256_broadcast_ss((float const *)(ptr_l + i + 4)); mat_a_blk_elems[10] = _mm256_broadcast_ss((float const *)(ptr_l + i + 5)); mat_a_blk_elems[11] = _mm256_broadcast_ss((float const *)(ptr_l + i + 6)); mat_a_blk_elems[12] = _mm256_broadcast_ss((float const *)(ptr_l + i + 7)); i += cs_l; //Broadcast A32 to A72 to registers mat_a_blk_elems[13] = _mm256_broadcast_ss((float const *)(ptr_l + i + 3)); mat_a_blk_elems[14] = _mm256_broadcast_ss((float const *)(ptr_l + i + 4)); mat_a_blk_elems[15] = _mm256_broadcast_ss((float const *)(ptr_l + i + 5)); mat_a_blk_elems[16] = _mm256_broadcast_ss((float const *)(ptr_l + i + 6)); mat_a_blk_elems[17] = _mm256_broadcast_ss((float const *)(ptr_l + i + 7)); i += cs_l; //Broadcast A43 to A73 to registers mat_a_blk_elems[18] = _mm256_broadcast_ss((float const *)(ptr_l + i + 4)); mat_a_blk_elems[19] = _mm256_broadcast_ss((float const *)(ptr_l + i + 5)); mat_a_blk_elems[20] = _mm256_broadcast_ss((float const *)(ptr_l + i + 6)); mat_a_blk_elems[21] = _mm256_broadcast_ss((float const *)(ptr_l + i + 7)); i += cs_l; //Broadcast A54 to A74 to registers mat_a_blk_elems[22] = _mm256_broadcast_ss((float const *)(ptr_l + i + 5)); mat_a_blk_elems[23] = _mm256_broadcast_ss((float const *)(ptr_l + i + 6)); mat_a_blk_elems[24] = _mm256_broadcast_ss((float const *)(ptr_l + i + 7)); i += cs_l; //Broadcast A65 to A75 to registers mat_a_blk_elems[25] = _mm256_broadcast_ss((float const *)(ptr_l + i + 6)); mat_a_blk_elems[26] = _mm256_broadcast_ss((float const *)(ptr_l + i + 7)); i += cs_l; //Broadcast A76 to register mat_a_blk_elems[27] = _mm256_broadcast_ss((float const *)(ptr_l + i + 7)); k = 0; for (i = 0; i < numCols_b; i+=8) { /////////////////// Complete Lower 8x8 block trsm of B :- lower 8x8 block of B with lower right 8x8 block of A //(Row0): already done //(Row1): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[k][1] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_rearr[k][0], mat_b_rearr[k][1]);//d = c - (a*b) mat_b_rearr[k][2] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_rearr[k][0], mat_b_rearr[k][2]);//d = c - (a*b) mat_b_rearr[k][3] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_rearr[k][0], mat_b_rearr[k][3]);//d = c - (a*b) mat_b_rearr[k][4] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_rearr[k][0], mat_b_rearr[k][4]);//d = c - (a*b) mat_b_rearr[k][5] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_rearr[k][0], mat_b_rearr[k][5]);//d = c - (a*b) mat_b_rearr[k][6] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_rearr[k][0], mat_b_rearr[k][6]);//d = c - (a*b) mat_b_rearr[k][7] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_rearr[k][0], mat_b_rearr[k][7]);//d = c - (a*b) //(Row2): FMA operations of b2 with elements of indices from (2, 0) uptill (7, 0) mat_b_rearr[k][2] = _mm256_fnmadd_ps(mat_a_blk_elems[7], mat_b_rearr[k][1], mat_b_rearr[k][2]);//d = c - (a*b) mat_b_rearr[k][3] = _mm256_fnmadd_ps(mat_a_blk_elems[8], mat_b_rearr[k][1], mat_b_rearr[k][3]);//d = c - (a*b) mat_b_rearr[k][4] = _mm256_fnmadd_ps(mat_a_blk_elems[9], mat_b_rearr[k][1], mat_b_rearr[k][4]);//d = c - (a*b) mat_b_rearr[k][5] = _mm256_fnmadd_ps(mat_a_blk_elems[10], mat_b_rearr[k][1], mat_b_rearr[k][5]);//d = c - (a*b) mat_b_rearr[k][6] = _mm256_fnmadd_ps(mat_a_blk_elems[11], mat_b_rearr[k][1], mat_b_rearr[k][6]);//d = c - (a*b) mat_b_rearr[k][7] = _mm256_fnmadd_ps(mat_a_blk_elems[12], mat_b_rearr[k][1], mat_b_rearr[k][7]);//d = c - (a*b) //(Row3): FMA operations of b3 with elements of indices from (3, 0) uptill (7, 0) mat_b_rearr[k][3] = _mm256_fnmadd_ps(mat_a_blk_elems[13], mat_b_rearr[k][2], mat_b_rearr[k][3]);//d = c - (a*b) mat_b_rearr[k][4] = _mm256_fnmadd_ps(mat_a_blk_elems[14], mat_b_rearr[k][2], mat_b_rearr[k][4]);//d = c - (a*b) mat_b_rearr[k][5] = _mm256_fnmadd_ps(mat_a_blk_elems[15], mat_b_rearr[k][2], mat_b_rearr[k][5]);//d = c - (a*b) mat_b_rearr[k][6] = _mm256_fnmadd_ps(mat_a_blk_elems[16], mat_b_rearr[k][2], mat_b_rearr[k][6]);//d = c - (a*b) mat_b_rearr[k][7] = _mm256_fnmadd_ps(mat_a_blk_elems[17], mat_b_rearr[k][2], mat_b_rearr[k][7]);//d = c - (a*b) //(Row4): FMA operations of b4 with elements of indices from (4, 0) uptill (7, 0) mat_b_rearr[k][4] = _mm256_fnmadd_ps(mat_a_blk_elems[18], mat_b_rearr[k][3], mat_b_rearr[k][4]);//d = c - (a*b) mat_b_rearr[k][5] = _mm256_fnmadd_ps(mat_a_blk_elems[19], mat_b_rearr[k][3], mat_b_rearr[k][5]);//d = c - (a*b) mat_b_rearr[k][6] = _mm256_fnmadd_ps(mat_a_blk_elems[20], mat_b_rearr[k][3], mat_b_rearr[k][6]);//d = c - (a*b) mat_b_rearr[k][7] = _mm256_fnmadd_ps(mat_a_blk_elems[21], mat_b_rearr[k][3], mat_b_rearr[k][7]);//d = c - (a*b) //(Row5): FMA operations of b5 with elements of indices from (5, 0) uptill (7, 0) mat_b_rearr[k][5] = _mm256_fnmadd_ps(mat_a_blk_elems[22], mat_b_rearr[k][4], mat_b_rearr[k][5]);//d = c - (a*b) mat_b_rearr[k][6] = _mm256_fnmadd_ps(mat_a_blk_elems[23], mat_b_rearr[k][4], mat_b_rearr[k][6]);//d = c - (a*b) mat_b_rearr[k][7] = _mm256_fnmadd_ps(mat_a_blk_elems[24], mat_b_rearr[k][4], mat_b_rearr[k][7]);//d = c - (a*b) //(Row6): FMA operations of b6 with elements of indices from (6, 0) uptill (7, 0) mat_b_rearr[k][6] = _mm256_fnmadd_ps(mat_a_blk_elems[25], mat_b_rearr[k][5], mat_b_rearr[k][6]);//d = c - (a*b) mat_b_rearr[k][7] = _mm256_fnmadd_ps(mat_a_blk_elems[26], mat_b_rearr[k][5], mat_b_rearr[k][7]);//d = c - (a*b) //(Row7): FMA operations of b7 with elements of index (7, 0) mat_b_rearr[k][7] = _mm256_fnmadd_ps(mat_a_blk_elems[27], mat_b_rearr[k][6], mat_b_rearr[k][7]);//d = c - (a*b) //////////////////////////////////////////////////////////////////////////////// //Store the computed B columns _mm256_storeu_ps((float *)ptr_b_dup + i, mat_b_rearr[k][0]); _mm256_storeu_ps((float *)(ptr_b_dup + (cs_b) + i), mat_b_rearr[k][1]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[0] + i), mat_b_rearr[k][2]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[1] + i), mat_b_rearr[k][3]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[2] + i), mat_b_rearr[k][4]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[3] + i), mat_b_rearr[k][5]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[4] + i), mat_b_rearr[k][6]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[5] + i), mat_b_rearr[k][7]); //printf("writing B => m[%d], n[%d], [%f]\n", j, k, *(ptr_b_dup + k)); k++; } } ///////////////////loop ends ///////////////////// } static void trsm_XAtB_block_allSmallSizedMatrices_alpha_unitDiag(float *ptr_l, float *ptr_b, int numRows_lb, int numCols_b, int rs_l, int rs_b, int cs_l, int cs_b, float alpha) { //float ones = 1.0; int i, i1, i2, i3, i4, j, k, l; int cs_b_offset[7]; int cs_l_offset[7]; float *ptr_b_dup; //57 number of ymm(256 bits) registers used __m256 mat_b_col[8]; __m256 mat_b_rearr[16][8]; //__m256 mat_a_cols_rearr[8]; __m256 mat_a_blk_elems[64]; //__m256 mat_a_diag_inv[8]; //__m256 reciprocal_diags[2]; __m256 alphaReg; alphaReg = _mm256_broadcast_ss((float const *)&alpha); // ---> considering that the matrix size is multiple of 16 rows and 8 cols <--- // //L matrix offsets cs_l_offset[0] = (cs_l << 1); cs_l_offset[1] = cs_l + cs_l_offset[0]; cs_l_offset[2] = (cs_l << 2); cs_l_offset[3] = cs_l + cs_l_offset[2]; cs_l_offset[4] = cs_l_offset[0] + cs_l_offset[2]; cs_l_offset[5] = cs_l + cs_l_offset[4]; cs_l_offset[6] = (cs_l_offset[5] + cs_l); cs_b_offset[0] = (cs_b << 1); cs_b_offset[1] = cs_b + cs_b_offset[0]; cs_b_offset[2] = (cs_b << 2); cs_b_offset[3] = cs_b + cs_b_offset[2]; cs_b_offset[4] = cs_b_offset[0] + cs_b_offset[2]; cs_b_offset[5] = cs_b + cs_b_offset[4]; cs_b_offset[6] = (cs_b_offset[5] + cs_b); //Broadcast A10 to A70 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + 1)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + 2)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l + 3)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l + 4)); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l + 5)); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l + 6)); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l + 7)); //Broadcast A21 to A71 to registers mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 2)); mat_a_blk_elems[8] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 3)); mat_a_blk_elems[9] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 4)); mat_a_blk_elems[10] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 5)); mat_a_blk_elems[11] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 6)); mat_a_blk_elems[12] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 7)); //Broadcast A32 to A72 to registers mat_a_blk_elems[13] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + 3)); mat_a_blk_elems[14] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + 4)); mat_a_blk_elems[15] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + 5)); mat_a_blk_elems[16] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + 6)); mat_a_blk_elems[17] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + 7)); //Broadcast A43 to A73 to registers mat_a_blk_elems[18] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + 4)); mat_a_blk_elems[19] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + 5)); mat_a_blk_elems[20] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + 6)); mat_a_blk_elems[21] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + 7)); //Broadcast A54 to A74 to registers mat_a_blk_elems[22] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[2] + 5)); mat_a_blk_elems[23] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[2] + 6)); mat_a_blk_elems[24] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[2] + 7)); //Broadcast A65 to A75 to registers mat_a_blk_elems[25] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[3] + 6)); mat_a_blk_elems[26] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[3] + 7)); //Broadcast A76 to register mat_a_blk_elems[27] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[4] + 7)); /***************** first set of 8 rows of B processing starts *****************/ ptr_b_dup = ptr_b; i = 0; for (j = 0; j < numCols_b; j += 8) { /////////////////// Complete Upper 8x8 block trsm of B :- upper 8x8 block of B with upper 8x8 block of A //read 8x8 block of B into registers mat_b_rearr[0][0] = _mm256_loadu_ps((float const *)ptr_b + i); mat_b_rearr[1][0] = _mm256_loadu_ps((float const *)(ptr_b + cs_b + i)); mat_b_rearr[2][0] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[0] + i)); mat_b_rearr[3][0] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[1] + i)); mat_b_rearr[4][0] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[2] + i)); mat_b_rearr[5][0] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[3] + i)); mat_b_rearr[6][0] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[4] + i)); mat_b_rearr[7][0] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[5] + i)); mat_b_rearr[0][0] = _mm256_mul_ps(mat_b_rearr[0][0], alphaReg); mat_b_rearr[1][0] = _mm256_mul_ps(mat_b_rearr[1][0], alphaReg); mat_b_rearr[2][0] = _mm256_mul_ps(mat_b_rearr[2][0], alphaReg); mat_b_rearr[3][0] = _mm256_mul_ps(mat_b_rearr[3][0], alphaReg); mat_b_rearr[4][0] = _mm256_mul_ps(mat_b_rearr[4][0], alphaReg); mat_b_rearr[5][0] = _mm256_mul_ps(mat_b_rearr[5][0], alphaReg); mat_b_rearr[6][0] = _mm256_mul_ps(mat_b_rearr[6][0], alphaReg); mat_b_rearr[7][0] = _mm256_mul_ps(mat_b_rearr[7][0], alphaReg); //(Row0) mat_b_col[0] = mat_b_rearr[0][0]; //(Row1): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_col[1] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[0], mat_b_rearr[1][0]);//d = c - (a*b) mat_b_rearr[2][0] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[0], mat_b_rearr[2][0]);//d = c - (a*b) mat_b_rearr[3][0] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[0], mat_b_rearr[3][0]);//d = c - (a*b) mat_b_rearr[4][0] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[0], mat_b_rearr[4][0]);//d = c - (a*b) mat_b_rearr[5][0] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[0], mat_b_rearr[5][0]);//d = c - (a*b) mat_b_rearr[6][0] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[0], mat_b_rearr[6][0]);//d = c - (a*b) mat_b_rearr[7][0] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_col[0], mat_b_rearr[7][0]);//d = c - (a*b) //(Row2): FMA operations of b2 with elements of indices from (2, 0) uptill (7, 0) mat_b_col[2] = _mm256_fnmadd_ps(mat_a_blk_elems[7], mat_b_col[1], mat_b_rearr[2][0]);//d = c - (a*b) mat_b_rearr[3][0] = _mm256_fnmadd_ps(mat_a_blk_elems[8], mat_b_col[1], mat_b_rearr[3][0]);//d = c - (a*b) mat_b_rearr[4][0] = _mm256_fnmadd_ps(mat_a_blk_elems[9], mat_b_col[1], mat_b_rearr[4][0]);//d = c - (a*b) mat_b_rearr[5][0] = _mm256_fnmadd_ps(mat_a_blk_elems[10], mat_b_col[1], mat_b_rearr[5][0]);//d = c - (a*b) mat_b_rearr[6][0] = _mm256_fnmadd_ps(mat_a_blk_elems[11], mat_b_col[1], mat_b_rearr[6][0]);//d = c - (a*b) mat_b_rearr[7][0] = _mm256_fnmadd_ps(mat_a_blk_elems[12], mat_b_col[1], mat_b_rearr[7][0]);//d = c - (a*b) //(Row3): FMA operations of b3 with elements of indices from (3, 0) uptill (7, 0) mat_b_col[3] = _mm256_fnmadd_ps(mat_a_blk_elems[13], mat_b_col[2], mat_b_rearr[3][0]);//d = c - (a*b) mat_b_rearr[4][0] = _mm256_fnmadd_ps(mat_a_blk_elems[14], mat_b_col[2], mat_b_rearr[4][0]);//d = c - (a*b) mat_b_rearr[5][0] = _mm256_fnmadd_ps(mat_a_blk_elems[15], mat_b_col[2], mat_b_rearr[5][0]);//d = c - (a*b) mat_b_rearr[6][0] = _mm256_fnmadd_ps(mat_a_blk_elems[16], mat_b_col[2], mat_b_rearr[6][0]);//d = c - (a*b) mat_b_rearr[7][0] = _mm256_fnmadd_ps(mat_a_blk_elems[17], mat_b_col[2], mat_b_rearr[7][0]);//d = c - (a*b) //(Row4): FMA operations of b4 with elements of indices from (4, 0) uptill (7, 0) mat_b_col[4] = _mm256_fnmadd_ps(mat_a_blk_elems[18], mat_b_col[3], mat_b_rearr[4][0]);//d = c - (a*b) mat_b_rearr[5][0] = _mm256_fnmadd_ps(mat_a_blk_elems[19], mat_b_col[3], mat_b_rearr[5][0]);//d = c - (a*b) mat_b_rearr[6][0] = _mm256_fnmadd_ps(mat_a_blk_elems[20], mat_b_col[3], mat_b_rearr[6][0]);//d = c - (a*b) mat_b_rearr[7][0] = _mm256_fnmadd_ps(mat_a_blk_elems[21], mat_b_col[3], mat_b_rearr[7][0]);//d = c - (a*b) //(Row5): FMA operations of b5 with elements of indices from (5, 0) uptill (7, 0) mat_b_col[5] = _mm256_fnmadd_ps(mat_a_blk_elems[22], mat_b_col[4], mat_b_rearr[5][0]);//d = c - (a*b) mat_b_rearr[6][0] = _mm256_fnmadd_ps(mat_a_blk_elems[23], mat_b_col[4], mat_b_rearr[6][0]);//d = c - (a*b) mat_b_rearr[7][0] = _mm256_fnmadd_ps(mat_a_blk_elems[24], mat_b_col[4], mat_b_rearr[7][0]);//d = c - (a*b) //(Row6): FMA operations of b6 with elements of indices from (6, 0) uptill (7, 0) mat_b_col[6] = _mm256_fnmadd_ps(mat_a_blk_elems[25], mat_b_col[5], mat_b_rearr[6][0]);//d = c - (a*b) mat_b_rearr[7][0] = _mm256_fnmadd_ps(mat_a_blk_elems[26], mat_b_col[5], mat_b_rearr[7][0]);//d = c - (a*b) //(Row7): FMA operations of b7 with elements of index (7, 0) mat_b_col[7] = _mm256_fnmadd_ps(mat_a_blk_elems[27], mat_b_col[6], mat_b_rearr[7][0]);//d = c - (a*b) //////////////////////////////////////////////////////////////////////////////// //Store the computed B columns _mm256_storeu_ps((float *)ptr_b_dup, mat_b_col[0]); _mm256_storeu_ps((float *)(ptr_b_dup + (cs_b)), mat_b_col[1]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[0]), mat_b_col[2]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[1]), mat_b_col[3]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[2]), mat_b_col[4]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[3]), mat_b_col[5]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[4]), mat_b_col[6]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[5]), mat_b_col[7]); //i += cs_b_offset[6]; //ptr_b_dup += cs_b_offset[6]; i += 8; ptr_b_dup += 8; } //c = 0; /***************** first set of 8 cols of B processing done *****************/ ptr_b_dup = ptr_b; i3 = 0; i1 = 0; //Start loop for cols of B to be processed in size of blk_width for (j = 8; j < numRows_lb; j += 8)//m :- 8x8 block row { ptr_l += 8; //ptr_b += j; //ptr_b_dup += 8; ptr_b_dup += cs_b_offset[6]; i1 += cs_b_offset[6]; i3 += cs_l_offset[6]; i = 0; i2 = 0; for (k = 0; k < numCols_b; k += 8) { i = i1 + k; //Read 8 cols of B columns of Block-to-be-solved mat_b_rearr[i2][0] = _mm256_loadu_ps((float const *)ptr_b + i); mat_b_rearr[i2][1] = _mm256_loadu_ps((float const *)(ptr_b + cs_b + i)); mat_b_rearr[i2][2] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[0] + i)); mat_b_rearr[i2][3] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[1] + i)); mat_b_rearr[i2][4] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[2] + i)); mat_b_rearr[i2][5] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[3] + i)); mat_b_rearr[i2][6] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[4] + i)); mat_b_rearr[i2][7] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[5] + i)); mat_b_rearr[i2][0] = _mm256_mul_ps(mat_b_rearr[i2][0], alphaReg); mat_b_rearr[i2][1] = _mm256_mul_ps(mat_b_rearr[i2][1], alphaReg); mat_b_rearr[i2][2] = _mm256_mul_ps(mat_b_rearr[i2][2], alphaReg); mat_b_rearr[i2][3] = _mm256_mul_ps(mat_b_rearr[i2][3], alphaReg); mat_b_rearr[i2][4] = _mm256_mul_ps(mat_b_rearr[i2][4], alphaReg); mat_b_rearr[i2][5] = _mm256_mul_ps(mat_b_rearr[i2][5], alphaReg); mat_b_rearr[i2][6] = _mm256_mul_ps(mat_b_rearr[i2][6], alphaReg); mat_b_rearr[i2][7] = _mm256_mul_ps(mat_b_rearr[i2][7], alphaReg); i2++; } i = 0; i2 = 0; for (l = 0; l < j; l += 8) // move across m { //Broadcast A8,0 to A15,0 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + i)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + i + 1)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l + i + 2)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l + i + 3)); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l + i + 4)); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l + i + 5)); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l + i + 6)); mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l + i + 7)); //Broadcast A21 to A71 to registers mat_a_blk_elems[8] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + i)); mat_a_blk_elems[9] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + i + 1)); mat_a_blk_elems[10] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + i + 2)); mat_a_blk_elems[11] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + i + 3)); mat_a_blk_elems[12] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + i + 4)); mat_a_blk_elems[13] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + i + 5)); mat_a_blk_elems[14] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + i + 6)); mat_a_blk_elems[15] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + i + 7)); //Broadcast A8,2 to A15,2 to registers mat_a_blk_elems[16] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + i)); mat_a_blk_elems[17] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + i + 1)); mat_a_blk_elems[18] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + i + 2)); mat_a_blk_elems[19] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + i + 3)); mat_a_blk_elems[20] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + i + 4)); mat_a_blk_elems[21] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + i + 5)); mat_a_blk_elems[22] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + i + 6)); mat_a_blk_elems[23] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + i + 7)); //Broadcast A8,3 to A15,3 to registers mat_a_blk_elems[24] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + i)); mat_a_blk_elems[25] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + i + 1)); mat_a_blk_elems[26] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + i + 2)); mat_a_blk_elems[27] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + i + 3)); mat_a_blk_elems[28] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + i + 4)); mat_a_blk_elems[29] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + i + 5)); mat_a_blk_elems[30] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + i + 6)); mat_a_blk_elems[31] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + i + 7)); // _mm256_permute2f128_ps() //Broadcast A8,4 to A15,4 to registers mat_a_blk_elems[32] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[2] + i)); mat_a_blk_elems[33] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[2] + i + 1)); mat_a_blk_elems[34] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[2] + i + 2)); mat_a_blk_elems[35] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[2] + i + 3)); mat_a_blk_elems[36] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[2] + i + 4)); mat_a_blk_elems[37] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[2] + i + 5)); mat_a_blk_elems[38] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[2] + i + 6)); mat_a_blk_elems[39] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[2] + i + 7)); //Broadcast A8,5 to A15,5 to registers mat_a_blk_elems[40] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[3] + i)); mat_a_blk_elems[41] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[3] + i + 1)); mat_a_blk_elems[42] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[3] + i + 2)); mat_a_blk_elems[43] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[3] + i + 3)); mat_a_blk_elems[44] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[3] + i + 4)); mat_a_blk_elems[45] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[3] + i + 5)); mat_a_blk_elems[46] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[3] + i + 6)); mat_a_blk_elems[47] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[3] + i + 7)); //Broadcast A8,6 to A15,6 to registers mat_a_blk_elems[48] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[4] + i)); mat_a_blk_elems[49] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[4] + i + 1)); mat_a_blk_elems[50] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[4] + i + 2)); mat_a_blk_elems[51] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[4] + i + 3)); mat_a_blk_elems[52] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[4] + i + 4)); mat_a_blk_elems[53] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[4] + i + 5)); mat_a_blk_elems[54] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[4] + i + 6)); mat_a_blk_elems[55] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[4] + i + 7)); //Broadcast A8,7 to A15,7 to registers mat_a_blk_elems[56] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[5] + i)); mat_a_blk_elems[57] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[5] + i + 1)); mat_a_blk_elems[58] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[5] + i + 2)); mat_a_blk_elems[59] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[5] + i + 3)); mat_a_blk_elems[60] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[5] + i + 4)); mat_a_blk_elems[61] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[5] + i + 5)); mat_a_blk_elems[62] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[5] + i + 6)); mat_a_blk_elems[63] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[5] + i + 7)); i += cs_l_offset[6]; for (k = 0; k < numCols_b; k += 8) // move across n for the same value of l (index of m) { /////////////////// Partial Lower 8x8 block trsm of B i4 = i2 + k; //Read current 8 cols of B columns from specified 8x8 current-block of B mat_b_col[0] = _mm256_loadu_ps((float const *)ptr_b + i4); mat_b_col[1] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b)); mat_b_col[2] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b_offset[0])); mat_b_col[3] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b_offset[1])); mat_b_col[4] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b_offset[2])); mat_b_col[5] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b_offset[3])); mat_b_col[6] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b_offset[4])); mat_b_col[7] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b_offset[5])); i4 = k >> 3; //(Row8): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[i4][0] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[0], mat_b_rearr[i4][0]);//d = c - (a*b) mat_b_rearr[i4][1] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[0], mat_b_rearr[i4][1]);//d = c - (a*b) mat_b_rearr[i4][2] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[0], mat_b_rearr[i4][2]);//d = c - (a*b) mat_b_rearr[i4][3] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[0], mat_b_rearr[i4][3]);//d = c - (a*b) mat_b_rearr[i4][4] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[0], mat_b_rearr[i4][4]);//d = c - (a*b) mat_b_rearr[i4][5] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[0], mat_b_rearr[i4][5]);//d = c - (a*b) mat_b_rearr[i4][6] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_col[0], mat_b_rearr[i4][6]);//d = c - (a*b) mat_b_rearr[i4][7] = _mm256_fnmadd_ps(mat_a_blk_elems[7], mat_b_col[0], mat_b_rearr[i4][7]);//d = c - (a*b) //(Row9): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[i4][0] = _mm256_fnmadd_ps(mat_a_blk_elems[8], mat_b_col[1], mat_b_rearr[i4][0]);//d = c - (a*b) mat_b_rearr[i4][1] = _mm256_fnmadd_ps(mat_a_blk_elems[9], mat_b_col[1], mat_b_rearr[i4][1]);//d = c - (a*b) mat_b_rearr[i4][2] = _mm256_fnmadd_ps(mat_a_blk_elems[10], mat_b_col[1], mat_b_rearr[i4][2]);//d = c - (a*b) mat_b_rearr[i4][3] = _mm256_fnmadd_ps(mat_a_blk_elems[11], mat_b_col[1], mat_b_rearr[i4][3]);//d = c - (a*b) mat_b_rearr[i4][4] = _mm256_fnmadd_ps(mat_a_blk_elems[12], mat_b_col[1], mat_b_rearr[i4][4]);//d = c - (a*b) mat_b_rearr[i4][5] = _mm256_fnmadd_ps(mat_a_blk_elems[13], mat_b_col[1], mat_b_rearr[i4][5]);//d = c - (a*b) mat_b_rearr[i4][6] = _mm256_fnmadd_ps(mat_a_blk_elems[14], mat_b_col[1], mat_b_rearr[i4][6]);//d = c - (a*b) mat_b_rearr[i4][7] = _mm256_fnmadd_ps(mat_a_blk_elems[15], mat_b_col[1], mat_b_rearr[i4][7]);//d = c - (a*b) //(Row10): FMA operations of b2 with elements of indices from (2, 0) uptill (7, 0) mat_b_rearr[i4][0] = _mm256_fnmadd_ps(mat_a_blk_elems[16], mat_b_col[2], mat_b_rearr[i4][0]);//d = c - (a*b) mat_b_rearr[i4][1] = _mm256_fnmadd_ps(mat_a_blk_elems[17], mat_b_col[2], mat_b_rearr[i4][1]);//d = c - (a*b) mat_b_rearr[i4][2] = _mm256_fnmadd_ps(mat_a_blk_elems[18], mat_b_col[2], mat_b_rearr[i4][2]);//d = c - (a*b) mat_b_rearr[i4][3] = _mm256_fnmadd_ps(mat_a_blk_elems[19], mat_b_col[2], mat_b_rearr[i4][3]);//d = c - (a*b) mat_b_rearr[i4][4] = _mm256_fnmadd_ps(mat_a_blk_elems[20], mat_b_col[2], mat_b_rearr[i4][4]);//d = c - (a*b) mat_b_rearr[i4][5] = _mm256_fnmadd_ps(mat_a_blk_elems[21], mat_b_col[2], mat_b_rearr[i4][5]);//d = c - (a*b) mat_b_rearr[i4][6] = _mm256_fnmadd_ps(mat_a_blk_elems[22], mat_b_col[2], mat_b_rearr[i4][6]);//d = c - (a*b) mat_b_rearr[i4][7] = _mm256_fnmadd_ps(mat_a_blk_elems[23], mat_b_col[2], mat_b_rearr[i4][7]);//d = c - (a*b) //(Row11): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[i4][0] = _mm256_fnmadd_ps(mat_a_blk_elems[24], mat_b_col[3], mat_b_rearr[i4][0]);//d = c - (a*b) mat_b_rearr[i4][1] = _mm256_fnmadd_ps(mat_a_blk_elems[25], mat_b_col[3], mat_b_rearr[i4][1]);//d = c - (a*b) mat_b_rearr[i4][2] = _mm256_fnmadd_ps(mat_a_blk_elems[26], mat_b_col[3], mat_b_rearr[i4][2]);//d = c - (a*b) mat_b_rearr[i4][3] = _mm256_fnmadd_ps(mat_a_blk_elems[27], mat_b_col[3], mat_b_rearr[i4][3]);//d = c - (a*b) mat_b_rearr[i4][4] = _mm256_fnmadd_ps(mat_a_blk_elems[28], mat_b_col[3], mat_b_rearr[i4][4]);//d = c - (a*b) mat_b_rearr[i4][5] = _mm256_fnmadd_ps(mat_a_blk_elems[29], mat_b_col[3], mat_b_rearr[i4][5]);//d = c - (a*b) mat_b_rearr[i4][6] = _mm256_fnmadd_ps(mat_a_blk_elems[30], mat_b_col[3], mat_b_rearr[i4][6]);//d = c - (a*b) mat_b_rearr[i4][7] = _mm256_fnmadd_ps(mat_a_blk_elems[31], mat_b_col[3], mat_b_rearr[i4][7]);//d = c - (a*b) //(Row12): FMA operations of b2 with elements of indices from (2, 0) uptill (7, 0) mat_b_rearr[i4][0] = _mm256_fnmadd_ps(mat_a_blk_elems[32], mat_b_col[4], mat_b_rearr[i4][0]);//d = c - (a*b) mat_b_rearr[i4][1] = _mm256_fnmadd_ps(mat_a_blk_elems[33], mat_b_col[4], mat_b_rearr[i4][1]);//d = c - (a*b) mat_b_rearr[i4][2] = _mm256_fnmadd_ps(mat_a_blk_elems[34], mat_b_col[4], mat_b_rearr[i4][2]);//d = c - (a*b) mat_b_rearr[i4][3] = _mm256_fnmadd_ps(mat_a_blk_elems[35], mat_b_col[4], mat_b_rearr[i4][3]);//d = c - (a*b) mat_b_rearr[i4][4] = _mm256_fnmadd_ps(mat_a_blk_elems[36], mat_b_col[4], mat_b_rearr[i4][4]);//d = c - (a*b) mat_b_rearr[i4][5] = _mm256_fnmadd_ps(mat_a_blk_elems[37], mat_b_col[4], mat_b_rearr[i4][5]);//d = c - (a*b) mat_b_rearr[i4][6] = _mm256_fnmadd_ps(mat_a_blk_elems[38], mat_b_col[4], mat_b_rearr[i4][6]);//d = c - (a*b) mat_b_rearr[i4][7] = _mm256_fnmadd_ps(mat_a_blk_elems[39], mat_b_col[4], mat_b_rearr[i4][7]);//d = c - (a*b) //(Row13): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[i4][0] = _mm256_fnmadd_ps(mat_a_blk_elems[40], mat_b_col[5], mat_b_rearr[i4][0]);//d = c - (a*b) mat_b_rearr[i4][1] = _mm256_fnmadd_ps(mat_a_blk_elems[41], mat_b_col[5], mat_b_rearr[i4][1]);//d = c - (a*b) mat_b_rearr[i4][2] = _mm256_fnmadd_ps(mat_a_blk_elems[42], mat_b_col[5], mat_b_rearr[i4][2]);//d = c - (a*b) mat_b_rearr[i4][3] = _mm256_fnmadd_ps(mat_a_blk_elems[43], mat_b_col[5], mat_b_rearr[i4][3]);//d = c - (a*b) mat_b_rearr[i4][4] = _mm256_fnmadd_ps(mat_a_blk_elems[44], mat_b_col[5], mat_b_rearr[i4][4]);//d = c - (a*b) mat_b_rearr[i4][5] = _mm256_fnmadd_ps(mat_a_blk_elems[45], mat_b_col[5], mat_b_rearr[i4][5]);//d = c - (a*b) mat_b_rearr[i4][6] = _mm256_fnmadd_ps(mat_a_blk_elems[46], mat_b_col[5], mat_b_rearr[i4][6]);//d = c - (a*b) mat_b_rearr[i4][7] = _mm256_fnmadd_ps(mat_a_blk_elems[47], mat_b_col[5], mat_b_rearr[i4][7]);//d = c - (a*b) //(Row14): FMA operations of b2 with elements of indices from (2, 0) uptill (7, 0) mat_b_rearr[i4][0] = _mm256_fnmadd_ps(mat_a_blk_elems[48], mat_b_col[6], mat_b_rearr[i4][0]);//d = c - (a*b) mat_b_rearr[i4][1] = _mm256_fnmadd_ps(mat_a_blk_elems[49], mat_b_col[6], mat_b_rearr[i4][1]);//d = c - (a*b) mat_b_rearr[i4][2] = _mm256_fnmadd_ps(mat_a_blk_elems[50], mat_b_col[6], mat_b_rearr[i4][2]);//d = c - (a*b) mat_b_rearr[i4][3] = _mm256_fnmadd_ps(mat_a_blk_elems[51], mat_b_col[6], mat_b_rearr[i4][3]);//d = c - (a*b) mat_b_rearr[i4][4] = _mm256_fnmadd_ps(mat_a_blk_elems[52], mat_b_col[6], mat_b_rearr[i4][4]);//d = c - (a*b) mat_b_rearr[i4][5] = _mm256_fnmadd_ps(mat_a_blk_elems[53], mat_b_col[6], mat_b_rearr[i4][5]);//d = c - (a*b) mat_b_rearr[i4][6] = _mm256_fnmadd_ps(mat_a_blk_elems[54], mat_b_col[6], mat_b_rearr[i4][6]);//d = c - (a*b) mat_b_rearr[i4][7] = _mm256_fnmadd_ps(mat_a_blk_elems[55], mat_b_col[6], mat_b_rearr[i4][7]);//d = c - (a*b) //(Row15): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[i4][0] = _mm256_fnmadd_ps(mat_a_blk_elems[56], mat_b_col[7], mat_b_rearr[i4][0]);//d = c - (a*b) mat_b_rearr[i4][1] = _mm256_fnmadd_ps(mat_a_blk_elems[57], mat_b_col[7], mat_b_rearr[i4][1]);//d = c - (a*b) mat_b_rearr[i4][2] = _mm256_fnmadd_ps(mat_a_blk_elems[58], mat_b_col[7], mat_b_rearr[i4][2]);//d = c - (a*b) mat_b_rearr[i4][3] = _mm256_fnmadd_ps(mat_a_blk_elems[59], mat_b_col[7], mat_b_rearr[i4][3]);//d = c - (a*b) mat_b_rearr[i4][4] = _mm256_fnmadd_ps(mat_a_blk_elems[60], mat_b_col[7], mat_b_rearr[i4][4]);//d = c - (a*b) mat_b_rearr[i4][5] = _mm256_fnmadd_ps(mat_a_blk_elems[61], mat_b_col[7], mat_b_rearr[i4][5]);//d = c - (a*b) mat_b_rearr[i4][6] = _mm256_fnmadd_ps(mat_a_blk_elems[62], mat_b_col[7], mat_b_rearr[i4][6]);//d = c - (a*b) mat_b_rearr[i4][7] = _mm256_fnmadd_ps(mat_a_blk_elems[63], mat_b_col[7], mat_b_rearr[i4][7]);//d = c - (a*b) //end loop of cols } i2 += cs_b_offset[6]; } //Broadcast A10 to A70 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + i + 1)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + i + 2)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l + i + 3)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l + i + 4)); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l + i + 5)); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l + i + 6)); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l + i + 7)); i += cs_l; //Broadcast A21 to A71 to registers mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l + i + 2)); mat_a_blk_elems[8] = _mm256_broadcast_ss((float const *)(ptr_l + i + 3)); mat_a_blk_elems[9] = _mm256_broadcast_ss((float const *)(ptr_l + i + 4)); mat_a_blk_elems[10] = _mm256_broadcast_ss((float const *)(ptr_l + i + 5)); mat_a_blk_elems[11] = _mm256_broadcast_ss((float const *)(ptr_l + i + 6)); mat_a_blk_elems[12] = _mm256_broadcast_ss((float const *)(ptr_l + i + 7)); i += cs_l; //Broadcast A32 to A72 to registers mat_a_blk_elems[13] = _mm256_broadcast_ss((float const *)(ptr_l + i + 3)); mat_a_blk_elems[14] = _mm256_broadcast_ss((float const *)(ptr_l + i + 4)); mat_a_blk_elems[15] = _mm256_broadcast_ss((float const *)(ptr_l + i + 5)); mat_a_blk_elems[16] = _mm256_broadcast_ss((float const *)(ptr_l + i + 6)); mat_a_blk_elems[17] = _mm256_broadcast_ss((float const *)(ptr_l + i + 7)); i += cs_l; //Broadcast A43 to A73 to registers mat_a_blk_elems[18] = _mm256_broadcast_ss((float const *)(ptr_l + i + 4)); mat_a_blk_elems[19] = _mm256_broadcast_ss((float const *)(ptr_l + i + 5)); mat_a_blk_elems[20] = _mm256_broadcast_ss((float const *)(ptr_l + i + 6)); mat_a_blk_elems[21] = _mm256_broadcast_ss((float const *)(ptr_l + i + 7)); i += cs_l; //Broadcast A54 to A74 to registers mat_a_blk_elems[22] = _mm256_broadcast_ss((float const *)(ptr_l + i + 5)); mat_a_blk_elems[23] = _mm256_broadcast_ss((float const *)(ptr_l + i + 6)); mat_a_blk_elems[24] = _mm256_broadcast_ss((float const *)(ptr_l + i + 7)); i += cs_l; //Broadcast A65 to A75 to registers mat_a_blk_elems[25] = _mm256_broadcast_ss((float const *)(ptr_l + i + 6)); mat_a_blk_elems[26] = _mm256_broadcast_ss((float const *)(ptr_l + i + 7)); i += cs_l; //Broadcast A76 to register mat_a_blk_elems[27] = _mm256_broadcast_ss((float const *)(ptr_l + i + 7)); k = 0; for (i = 0; i < numCols_b; i+=8) { /////////////////// Complete Lower 8x8 block trsm of B :- lower 8x8 block of B with lower right 8x8 block of A //(Row0): already done //(Row1): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[k][1] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_rearr[k][0], mat_b_rearr[k][1]);//d = c - (a*b) mat_b_rearr[k][2] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_rearr[k][0], mat_b_rearr[k][2]);//d = c - (a*b) mat_b_rearr[k][3] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_rearr[k][0], mat_b_rearr[k][3]);//d = c - (a*b) mat_b_rearr[k][4] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_rearr[k][0], mat_b_rearr[k][4]);//d = c - (a*b) mat_b_rearr[k][5] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_rearr[k][0], mat_b_rearr[k][5]);//d = c - (a*b) mat_b_rearr[k][6] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_rearr[k][0], mat_b_rearr[k][6]);//d = c - (a*b) mat_b_rearr[k][7] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_rearr[k][0], mat_b_rearr[k][7]);//d = c - (a*b) //(Row2): FMA operations of b2 with elements of indices from (2, 0) uptill (7, 0) mat_b_rearr[k][2] = _mm256_fnmadd_ps(mat_a_blk_elems[7], mat_b_rearr[k][1], mat_b_rearr[k][2]);//d = c - (a*b) mat_b_rearr[k][3] = _mm256_fnmadd_ps(mat_a_blk_elems[8], mat_b_rearr[k][1], mat_b_rearr[k][3]);//d = c - (a*b) mat_b_rearr[k][4] = _mm256_fnmadd_ps(mat_a_blk_elems[9], mat_b_rearr[k][1], mat_b_rearr[k][4]);//d = c - (a*b) mat_b_rearr[k][5] = _mm256_fnmadd_ps(mat_a_blk_elems[10], mat_b_rearr[k][1], mat_b_rearr[k][5]);//d = c - (a*b) mat_b_rearr[k][6] = _mm256_fnmadd_ps(mat_a_blk_elems[11], mat_b_rearr[k][1], mat_b_rearr[k][6]);//d = c - (a*b) mat_b_rearr[k][7] = _mm256_fnmadd_ps(mat_a_blk_elems[12], mat_b_rearr[k][1], mat_b_rearr[k][7]);//d = c - (a*b) //(Row3): FMA operations of b3 with elements of indices from (3, 0) uptill (7, 0) mat_b_rearr[k][3] = _mm256_fnmadd_ps(mat_a_blk_elems[13], mat_b_rearr[k][2], mat_b_rearr[k][3]);//d = c - (a*b) mat_b_rearr[k][4] = _mm256_fnmadd_ps(mat_a_blk_elems[14], mat_b_rearr[k][2], mat_b_rearr[k][4]);//d = c - (a*b) mat_b_rearr[k][5] = _mm256_fnmadd_ps(mat_a_blk_elems[15], mat_b_rearr[k][2], mat_b_rearr[k][5]);//d = c - (a*b) mat_b_rearr[k][6] = _mm256_fnmadd_ps(mat_a_blk_elems[16], mat_b_rearr[k][2], mat_b_rearr[k][6]);//d = c - (a*b) mat_b_rearr[k][7] = _mm256_fnmadd_ps(mat_a_blk_elems[17], mat_b_rearr[k][2], mat_b_rearr[k][7]);//d = c - (a*b) //(Row4): FMA operations of b4 with elements of indices from (4, 0) uptill (7, 0) mat_b_rearr[k][4] = _mm256_fnmadd_ps(mat_a_blk_elems[18], mat_b_rearr[k][3], mat_b_rearr[k][4]);//d = c - (a*b) mat_b_rearr[k][5] = _mm256_fnmadd_ps(mat_a_blk_elems[19], mat_b_rearr[k][3], mat_b_rearr[k][5]);//d = c - (a*b) mat_b_rearr[k][6] = _mm256_fnmadd_ps(mat_a_blk_elems[20], mat_b_rearr[k][3], mat_b_rearr[k][6]);//d = c - (a*b) mat_b_rearr[k][7] = _mm256_fnmadd_ps(mat_a_blk_elems[21], mat_b_rearr[k][3], mat_b_rearr[k][7]);//d = c - (a*b) //(Row5): FMA operations of b5 with elements of indices from (5, 0) uptill (7, 0) mat_b_rearr[k][5] = _mm256_fnmadd_ps(mat_a_blk_elems[22], mat_b_rearr[k][4], mat_b_rearr[k][5]);//d = c - (a*b) mat_b_rearr[k][6] = _mm256_fnmadd_ps(mat_a_blk_elems[23], mat_b_rearr[k][4], mat_b_rearr[k][6]);//d = c - (a*b) mat_b_rearr[k][7] = _mm256_fnmadd_ps(mat_a_blk_elems[24], mat_b_rearr[k][4], mat_b_rearr[k][7]);//d = c - (a*b) //(Row6): FMA operations of b6 with elements of indices from (6, 0) uptill (7, 0) mat_b_rearr[k][6] = _mm256_fnmadd_ps(mat_a_blk_elems[25], mat_b_rearr[k][5], mat_b_rearr[k][6]);//d = c - (a*b) mat_b_rearr[k][7] = _mm256_fnmadd_ps(mat_a_blk_elems[26], mat_b_rearr[k][5], mat_b_rearr[k][7]);//d = c - (a*b) //(Row7): FMA operations of b7 with elements of index (7, 0) mat_b_rearr[k][7] = _mm256_fnmadd_ps(mat_a_blk_elems[27], mat_b_rearr[k][6], mat_b_rearr[k][7]);//d = c - (a*b) //////////////////////////////////////////////////////////////////////////////// //Store the computed B columns _mm256_storeu_ps((float *)ptr_b_dup + i, mat_b_rearr[k][0]); _mm256_storeu_ps((float *)(ptr_b_dup + (cs_b) + i), mat_b_rearr[k][1]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[0] + i), mat_b_rearr[k][2]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[1] + i), mat_b_rearr[k][3]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[2] + i), mat_b_rearr[k][4]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[3] + i), mat_b_rearr[k][5]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[4] + i), mat_b_rearr[k][6]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[5] + i), mat_b_rearr[k][7]); //printf("writing B => m[%d], n[%d], [%f]\n", j, k, *(ptr_b_dup + k)); k++; } } ///////////////////loop ends ///////////////////// } #endif //OPT_CACHE_BLOCKING_L1 //////////////////////////// AutX=B /////////////////////// static void trsm_AutXB_block_allSmallSizedMatrices(float *ptr_l, float *ptr_b, int numRows_lb, int numCols_b, int rs_l, int rs_b, int cs_l, int cs_b) { float ones = 1.0; int i, i1, i2, i3, i4, j, k, l, r; int cs_b_offset[7]; int cs_l_offset[7]; float *ptr_b_dup, *ptr_l_dup; //57 number of ymm(256 bits) registers used __m256 mat_b_col[8]; __m256 mat_b_rearr[8]; __m256 mat_a_blk_elems[8]; __m256 mat_a_diag_inv[8]; __m256 reciprocal_diags[2]; reciprocal_diags[0] = _mm256_broadcast_ss((float const *)(&ones)); // ---> considering that the matrix size is multiple of 16 rows and 8 cols <--- // //L matrix offsets cs_l_offset[0] = (cs_l << 1); cs_l_offset[1] = cs_l + cs_l_offset[0]; cs_l_offset[2] = (cs_l << 2); cs_l_offset[3] = cs_l + cs_l_offset[2]; cs_l_offset[4] = cs_l_offset[0] + cs_l_offset[2]; cs_l_offset[5] = cs_l + cs_l_offset[4]; cs_l_offset[6] = (cs_l_offset[5] + cs_l); //read diag elems of L 16x16 block mat_a_blk_elems[0] = _mm256_loadu_ps((float const *)ptr_l); mat_a_blk_elems[1] = _mm256_loadu_ps((float const *)ptr_l + cs_l); mat_a_blk_elems[2] = _mm256_loadu_ps((float const *)ptr_l + cs_l_offset[0]); mat_a_blk_elems[3] = _mm256_loadu_ps((float const *)ptr_l + cs_l_offset[1]); mat_a_blk_elems[4] = _mm256_loadu_ps((float const *)ptr_l + cs_l_offset[2]); mat_a_blk_elems[5] = _mm256_loadu_ps((float const *)ptr_l + cs_l_offset[3]); mat_a_blk_elems[6] = _mm256_loadu_ps((float const *)ptr_l + cs_l_offset[4]); mat_a_blk_elems[7] = _mm256_loadu_ps((float const *)ptr_l + cs_l_offset[5]); cs_b_offset[0] = (cs_b << 1); cs_b_offset[1] = cs_b + cs_b_offset[0]; cs_b_offset[2] = (cs_b << 2); cs_b_offset[3] = cs_b + cs_b_offset[2]; cs_b_offset[4] = cs_b_offset[0] + cs_b_offset[2]; cs_b_offset[5] = cs_b + cs_b_offset[4]; cs_b_offset[6] = (cs_b_offset[5] + cs_b); reciprocal_diags[1] = reciprocal_diags[0]; //pack first 8 diags together mat_a_diag_inv[0] = _mm256_blend_ps(mat_a_blk_elems[0], mat_a_blk_elems[1], 0xAA);//diag 0,1 mat_a_diag_inv[1] = _mm256_blend_ps(mat_a_blk_elems[2], mat_a_blk_elems[3], 0xAA);//diag 2,3 mat_a_diag_inv[2] = _mm256_blend_ps(mat_a_blk_elems[4], mat_a_blk_elems[5], 0xAA);//diag 4,5 mat_a_diag_inv[3] = _mm256_blend_ps(mat_a_blk_elems[6], mat_a_blk_elems[7], 0xAA);//diag 6,7 mat_a_diag_inv[0] = _mm256_blend_ps(mat_a_diag_inv[0], mat_a_diag_inv[1], 0xCC);//diag 0,1,2,3 mat_a_diag_inv[2] = _mm256_blend_ps(mat_a_diag_inv[2], mat_a_diag_inv[3], 0xCC);//diag 4,5,6,7 mat_a_diag_inv[0] = _mm256_blend_ps(mat_a_diag_inv[0], mat_a_diag_inv[2], 0xF0);//diag 0,1,2,3,4,5,6,7 //reciprocal of diagnal elements 0,1,2,3,4,5,6,7 reciprocal_diags[0] = _mm256_div_ps(reciprocal_diags[0], mat_a_diag_inv[0]); #if 0 //Broadcast A10 to A70 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + 1)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + 2)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l + 3)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l + 4)); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l + 5)); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l + 6)); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l + 7)); //Broadcast A21 to A71 to registers mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 2)); mat_a_blk_elems[8] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 3)); mat_a_blk_elems[9] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 4)); mat_a_blk_elems[10] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 5)); mat_a_blk_elems[11] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 6)); mat_a_blk_elems[12] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 7)); //Broadcast A32 to A72 to registers mat_a_blk_elems[13] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + 3)); mat_a_blk_elems[14] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + 4)); mat_a_blk_elems[15] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + 5)); mat_a_blk_elems[16] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + 6)); mat_a_blk_elems[17] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + 7)); //Broadcast A43 to A73 to registers mat_a_blk_elems[18] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + 4)); mat_a_blk_elems[19] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + 5)); mat_a_blk_elems[20] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + 6)); mat_a_blk_elems[21] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + 7)); //Broadcast A54 to A74 to registers mat_a_blk_elems[22] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[2] + 5)); mat_a_blk_elems[23] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[2] + 6)); mat_a_blk_elems[24] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[2] + 7)); //Broadcast A65 to A75 to registers mat_a_blk_elems[25] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[3] + 6)); mat_a_blk_elems[26] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[3] + 7)); //Broadcast A76 to register mat_a_blk_elems[27] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[4] + 7)); #endif //extract diag a00 from a mat_a_diag_inv[0] = _mm256_permute_ps(reciprocal_diags[0], 0x00); mat_a_diag_inv[0] = _mm256_permute2f128_ps(mat_a_diag_inv[0], mat_a_diag_inv[0], 0x00); //mat_a_diag_inv[0] = _mm256_unpacklo_ps(mat_a_diag_inv[0], mat_a_diag_inv[0]); //extract diag a11 from a mat_a_diag_inv[1] = _mm256_permute_ps(reciprocal_diags[0], 0x55); mat_a_diag_inv[1] = _mm256_permute2f128_ps(mat_a_diag_inv[1], mat_a_diag_inv[1], 0x00); //mat_a_diag_inv[1] = _mm256_unpacklo_ps(mat_a_diag_inv[1], mat_a_diag_inv[1]); //extract diag a22 from a mat_a_diag_inv[2] = _mm256_permute_ps(reciprocal_diags[0], 0xAA); mat_a_diag_inv[2] = _mm256_permute2f128_ps(mat_a_diag_inv[2], mat_a_diag_inv[2], 0x00); //mat_a_diag_inv[2] = _mm256_unpacklo_ps(mat_a_diag_inv[2], mat_a_diag_inv[2]); //extract diag a33 from a mat_a_diag_inv[3] = _mm256_permute_ps(reciprocal_diags[0], 0xFF); mat_a_diag_inv[3] = _mm256_permute2f128_ps(mat_a_diag_inv[3], mat_a_diag_inv[3], 0x00); //mat_a_diag_inv[3] = _mm256_unpacklo_ps(mat_a_diag_inv[3], mat_a_diag_inv[3]); //extract diag a44 from a mat_a_diag_inv[4] = _mm256_permute_ps(reciprocal_diags[0], 0x00); mat_a_diag_inv[4] = _mm256_permute2f128_ps(mat_a_diag_inv[4], mat_a_diag_inv[4], 0x11); //mat_a_diag_inv[4] = _mm256_unpacklo_ps(mat_a_diag_inv[4], mat_a_diag_inv[4]); //extract diag a55 from a mat_a_diag_inv[5] = _mm256_permute_ps(reciprocal_diags[0], 0x55); mat_a_diag_inv[5] = _mm256_permute2f128_ps(mat_a_diag_inv[5], mat_a_diag_inv[5], 0x11); //mat_a_diag_inv[5] = _mm256_unpacklo_ps(mat_a_diag_inv[5], mat_a_diag_inv[5]); //extract diag a66 from a mat_a_diag_inv[6] = _mm256_permute_ps(reciprocal_diags[0], 0xAA); mat_a_diag_inv[6] = _mm256_permute2f128_ps(mat_a_diag_inv[6], mat_a_diag_inv[6], 0x11); //mat_a_diag_inv[6] = _mm256_unpacklo_ps(mat_a_diag_inv[6], mat_a_diag_inv[6]); //extract diag a77 from a mat_a_diag_inv[7] = _mm256_permute_ps(reciprocal_diags[0], 0xFF); mat_a_diag_inv[7] = _mm256_permute2f128_ps(mat_a_diag_inv[7], mat_a_diag_inv[7], 0x11); //mat_a_diag_inv[7] = _mm256_unpacklo_ps(mat_a_diag_inv[7], mat_a_diag_inv[7]); /***************** first set of 8 rows of B processing starts *****************/ ptr_b_dup = ptr_b; i = 0; for (j = 0; j < numCols_b; j += 8) { /////////////////// Complete Upper 8x8 block trsm of B :- upper 8x8 block of B with upper 8x8 block of A //read 8x8 block of B into registers mat_b_rearr[0] = _mm256_loadu_ps((float const *)ptr_b + i); mat_b_rearr[1] = _mm256_loadu_ps((float const *)(ptr_b + cs_b + i)); mat_b_rearr[2] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[0] + i)); mat_b_rearr[3] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[1] + i)); mat_b_rearr[4] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[2] + i)); mat_b_rearr[5] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[3] + i)); mat_b_rearr[6] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[4] + i)); mat_b_rearr[7] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[5] + i)); /* transpose steps start */ ////unpacklow//// mat_b_col[0] = _mm256_unpacklo_ps(mat_b_rearr[0], mat_b_rearr[1]); mat_b_col[1] = _mm256_unpacklo_ps(mat_b_rearr[2], mat_b_rearr[3]); mat_b_col[2] = _mm256_unpacklo_ps(mat_b_rearr[4], mat_b_rearr[5]); mat_b_col[3] = _mm256_unpacklo_ps(mat_b_rearr[6], mat_b_rearr[7]); //Rearrange low elements #if REARRANGE_SHFL == 1 mat_b_col[4] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0x44); mat_b_col[5] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0xEE); mat_b_col[6] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0x44); mat_b_col[7] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0xEE); #else mat_b_col[6] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0x4E); mat_b_col[7] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0x4E); mat_b_col[4] = _mm256_blend_ps(mat_b_col[0], mat_b_col[6], 0xCC); mat_b_col[5] = _mm256_blend_ps(mat_b_col[1], mat_b_col[6], 0x33); mat_b_col[6] = _mm256_blend_ps(mat_b_col[2], mat_b_col[7], 0xCC); mat_b_col[7] = _mm256_blend_ps(mat_b_col[3], mat_b_col[7], 0x33); #endif //Merge rearranged low elements into complete rows mat_b_col[0] = _mm256_permute2f128_ps(mat_b_col[4], mat_b_col[6], 0x20); mat_b_col[4] = _mm256_permute2f128_ps(mat_b_col[4], mat_b_col[6], 0x31); mat_b_col[1] = _mm256_permute2f128_ps(mat_b_col[5], mat_b_col[7], 0x20); mat_b_col[5] = _mm256_permute2f128_ps(mat_b_col[5], mat_b_col[7], 0x31); ////unpackhigh//// mat_b_rearr[0] = _mm256_unpackhi_ps(mat_b_rearr[0], mat_b_rearr[1]); mat_b_rearr[1] = _mm256_unpackhi_ps(mat_b_rearr[2], mat_b_rearr[3]); mat_b_rearr[2] = _mm256_unpackhi_ps(mat_b_rearr[4], mat_b_rearr[5]); mat_b_rearr[3] = _mm256_unpackhi_ps(mat_b_rearr[6], mat_b_rearr[7]); //Rearrange high elements #if REARRANGE_SHFL == 1 mat_b_rearr[4] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0x44); mat_b_rearr[5] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0xEE); mat_b_rearr[6] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0x44); mat_b_rearr[7] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0xEE); #else mat_b_rearr[6] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0x4E); mat_b_rearr[7] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0x4E); mat_b_rearr[4] = _mm256_blend_ps(mat_b_rearr[0], mat_b_rearr[6], 0xCC); mat_b_rearr[5] = _mm256_blend_ps(mat_b_rearr[1], mat_b_rearr[6], 0x33); mat_b_rearr[6] = _mm256_blend_ps(mat_b_rearr[2], mat_b_rearr[7], 0xCC); mat_b_rearr[7] = _mm256_blend_ps(mat_b_rearr[3], mat_b_rearr[7], 0x33); #endif //Merge rearranged high elements into complete rows mat_b_col[2] = _mm256_permute2f128_ps(mat_b_rearr[4], mat_b_rearr[6], 0x20); mat_b_col[6] = _mm256_permute2f128_ps(mat_b_rearr[4], mat_b_rearr[6], 0x31); mat_b_col[3] = _mm256_permute2f128_ps(mat_b_rearr[5], mat_b_rearr[7], 0x20); mat_b_col[7] = _mm256_permute2f128_ps(mat_b_rearr[5], mat_b_rearr[7], 0x31); /* transpose steps end */ //(Row0): Perform mul operation of reciprocal of L(0,0) element with 1st row elements of B mat_b_col[0] = _mm256_mul_ps(mat_b_col[0], mat_a_diag_inv[0]); mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0])); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1])); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[2])); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[3])); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[4])); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[5])); //(Row1): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_col[1] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[0], mat_b_col[1]);//d = c - (a*b) mat_b_col[2] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[0], mat_b_col[2]);//d = c - (a*b) mat_b_col[3] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[0], mat_b_col[3]);//d = c - (a*b) mat_b_col[4] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[0], mat_b_col[4]);//d = c - (a*b) mat_b_col[5] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[0], mat_b_col[5]);//d = c - (a*b) mat_b_col[6] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[0], mat_b_col[6]);//d = c - (a*b) mat_b_col[7] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_col[0], mat_b_col[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(1,1) element with 2nd row elements of B mat_b_col[1] = _mm256_mul_ps(mat_b_col[1], mat_a_diag_inv[1]); mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + 1 + cs_l_offset[0])); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + 1 + cs_l_offset[1])); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l + 1 + cs_l_offset[2])); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l + 1 + cs_l_offset[3])); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l + 1 + cs_l_offset[4])); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l + 1 + cs_l_offset[5])); //(Row2): FMA operations of b2 with elements of indices from (2, 0) uptill (7, 0) mat_b_col[2] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[1], mat_b_col[2]);//d = c - (a*b) mat_b_col[3] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[1], mat_b_col[3]);//d = c - (a*b) mat_b_col[4] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[1], mat_b_col[4]);//d = c - (a*b) mat_b_col[5] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[1], mat_b_col[5]);//d = c - (a*b) mat_b_col[6] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[1], mat_b_col[6]);//d = c - (a*b) mat_b_col[7] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[1], mat_b_col[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(2, 2) element with 3rd row elements of B mat_b_col[2] = _mm256_mul_ps(mat_b_col[2], mat_a_diag_inv[2]); mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + 2 + cs_l_offset[1])); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + 2 + cs_l_offset[2])); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l + 2 + cs_l_offset[3])); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l + 2 + cs_l_offset[4])); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l + 2 + cs_l_offset[5])); //(Row3): FMA operations of b3 with elements of indices from (3, 0) uptill (7, 0) mat_b_col[3] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[2], mat_b_col[3]);//d = c - (a*b) mat_b_col[4] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[2], mat_b_col[4]);//d = c - (a*b) mat_b_col[5] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[2], mat_b_col[5]);//d = c - (a*b) mat_b_col[6] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[2], mat_b_col[6]);//d = c - (a*b) mat_b_col[7] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[2], mat_b_col[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(3, 3) element with 4rth row elements of B mat_b_col[3] = _mm256_mul_ps(mat_b_col[3], mat_a_diag_inv[3]); mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + 3 + cs_l_offset[2])); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + 3 + cs_l_offset[3])); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l + 3 + cs_l_offset[4])); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l + 3 + cs_l_offset[5])); //(Row4): FMA operations of b4 with elements of indices from (4, 0) uptill (7, 0) mat_b_col[4] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[3], mat_b_col[4]);//d = c - (a*b) mat_b_col[5] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[3], mat_b_col[5]);//d = c - (a*b) mat_b_col[6] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[3], mat_b_col[6]);//d = c - (a*b) mat_b_col[7] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[3], mat_b_col[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(4, 4) element with 4rth row elements of B mat_b_col[4] = _mm256_mul_ps(mat_b_col[4], mat_a_diag_inv[4]); mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + 4 + cs_l_offset[3])); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + 4 + cs_l_offset[4])); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l + 4 + cs_l_offset[5])); //(Row5): FMA operations of b5 with elements of indices from (5, 0) uptill (7, 0) mat_b_col[5] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[4], mat_b_col[5]);//d = c - (a*b) mat_b_col[6] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[4], mat_b_col[6]);//d = c - (a*b) mat_b_col[7] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[4], mat_b_col[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(5, 5) element with 5th row elements of B mat_b_col[5] = _mm256_mul_ps(mat_b_col[5], mat_a_diag_inv[5]); mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + 5 + cs_l_offset[4])); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + 5 + cs_l_offset[5])); //(Row6): FMA operations of b6 with elements of indices from (6, 0) uptill (7, 0) mat_b_col[6] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[5], mat_b_col[6]);//d = c - (a*b) mat_b_col[7] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[5], mat_b_col[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(6, 6) element with 6th row elements of B mat_b_col[6] = _mm256_mul_ps(mat_b_col[6], mat_a_diag_inv[6]); mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + 6 + cs_l_offset[5])); //(Row7): FMA operations of b7 with elements of index (7, 0) mat_b_col[7] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[6], mat_b_col[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(7, 7) element with 7th row elements of B mat_b_col[7] = _mm256_mul_ps(mat_b_col[7], mat_a_diag_inv[7]); //////////////////////////////////////////////////////////////////////////////// /* transpose steps start */ ////unpacklow//// mat_b_rearr[0] = _mm256_unpacklo_ps(mat_b_col[0], mat_b_col[1]); mat_b_rearr[1] = _mm256_unpacklo_ps(mat_b_col[2], mat_b_col[3]); mat_b_rearr[2] = _mm256_unpacklo_ps(mat_b_col[4], mat_b_col[5]); mat_b_rearr[3] = _mm256_unpacklo_ps(mat_b_col[6], mat_b_col[7]); //Rearrange low elements #if REARRANGE_SHFL == 1 mat_b_rearr[4] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0x44); mat_b_rearr[5] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0xEE); mat_b_rearr[6] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0x44); mat_b_rearr[7] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0xEE); #else mat_b_rearr[6] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0x4E); mat_b_rearr[7] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0x4E); mat_b_rearr[4] = _mm256_blend_ps(mat_b_rearr[0], mat_b_rearr[6], 0xCC); mat_b_rearr[5] = _mm256_blend_ps(mat_b_rearr[1], mat_b_rearr[6], 0x33); mat_b_rearr[6] = _mm256_blend_ps(mat_b_rearr[2], mat_b_rearr[7], 0xCC); mat_b_rearr[7] = _mm256_blend_ps(mat_b_rearr[3], mat_b_rearr[7], 0x33); #endif //Merge rearranged low elements into complete rows mat_b_rearr[0] = _mm256_permute2f128_ps(mat_b_rearr[4], mat_b_rearr[6], 0x20); mat_b_rearr[4] = _mm256_permute2f128_ps(mat_b_rearr[4], mat_b_rearr[6], 0x31); mat_b_rearr[1] = _mm256_permute2f128_ps(mat_b_rearr[5], mat_b_rearr[7], 0x20); mat_b_rearr[5] = _mm256_permute2f128_ps(mat_b_rearr[5], mat_b_rearr[7], 0x31); ////unpackhigh//// mat_b_col[0] = _mm256_unpackhi_ps(mat_b_col[0], mat_b_col[1]); mat_b_col[1] = _mm256_unpackhi_ps(mat_b_col[2], mat_b_col[3]); mat_b_col[2] = _mm256_unpackhi_ps(mat_b_col[4], mat_b_col[5]); mat_b_col[3] = _mm256_unpackhi_ps(mat_b_col[6], mat_b_col[7]); //Rearrange high elements #if REARRANGE_SHFL == 1 mat_b_col[4] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0x44); mat_b_col[5] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0xEE); mat_b_col[6] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0x44); mat_b_col[7] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0xEE); #else mat_b_col[6] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0x4E); mat_b_col[7] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0x4E); mat_b_col[4] = _mm256_blend_ps(mat_b_col[0], mat_b_col[6], 0xCC); mat_b_col[5] = _mm256_blend_ps(mat_b_col[1], mat_b_col[6], 0x33); mat_b_col[6] = _mm256_blend_ps(mat_b_col[2], mat_b_col[7], 0xCC); mat_b_col[7] = _mm256_blend_ps(mat_b_col[3], mat_b_col[7], 0x33); #endif //Merge rearranged high elements into complete rows mat_b_rearr[2] = _mm256_permute2f128_ps(mat_b_col[4], mat_b_col[6], 0x20); mat_b_rearr[6] = _mm256_permute2f128_ps(mat_b_col[4], mat_b_col[6], 0x31); mat_b_rearr[3] = _mm256_permute2f128_ps(mat_b_col[5], mat_b_col[7], 0x20); mat_b_rearr[7] = _mm256_permute2f128_ps(mat_b_col[5], mat_b_col[7], 0x31); /* transpose steps end */ //Store the computed B columns _mm256_storeu_ps((float *)ptr_b_dup, mat_b_rearr[0]); _mm256_storeu_ps((float *)(ptr_b_dup + (cs_b)), mat_b_rearr[1]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[0]), mat_b_rearr[2]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[1]), mat_b_rearr[3]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[2]), mat_b_rearr[4]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[3]), mat_b_rearr[5]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[4]), mat_b_rearr[6]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[5]), mat_b_rearr[7]); i += cs_b_offset[6]; ptr_b_dup += cs_b_offset[6]; //i += 8; //ptr_b_dup += 8; } //c = 0; /***************** first set of 8 cols of B processing done *****************/ ptr_b_dup = ptr_b; i3 = 0; i1 = 0; //Start loop for cols of B to be processed in size of blk_width for (j = 8; j < numRows_lb; j += 8)//m :- 8x8 block row { ptr_l += cs_l_offset[6]; //Read next 8x8 block of A to get diag elements i3 += 8; mat_a_blk_elems[0] = _mm256_loadu_ps((float const *)ptr_l + i3); mat_a_blk_elems[1] = _mm256_loadu_ps((float const *)ptr_l + i3 + cs_l); mat_a_blk_elems[2] = _mm256_loadu_ps((float const *)ptr_l + i3 + cs_l_offset[0]); mat_a_blk_elems[3] = _mm256_loadu_ps((float const *)ptr_l + i3 + cs_l_offset[1]); mat_a_blk_elems[4] = _mm256_loadu_ps((float const *)ptr_l + i3 + cs_l_offset[2]); mat_a_blk_elems[5] = _mm256_loadu_ps((float const *)ptr_l + i3 + cs_l_offset[3]); mat_a_blk_elems[6] = _mm256_loadu_ps((float const *)ptr_l + i3 + cs_l_offset[4]); mat_a_blk_elems[7] = _mm256_loadu_ps((float const *)ptr_l + i3 + cs_l_offset[5]); //pack 8 diags of A together reciprocal_diags[0] = reciprocal_diags[1]; mat_a_diag_inv[0] = _mm256_blend_ps(mat_a_blk_elems[0], mat_a_blk_elems[1], 0xAA);//diag 0,1 mat_a_diag_inv[1] = _mm256_blend_ps(mat_a_blk_elems[2], mat_a_blk_elems[3], 0xAA);//diag 2,3 mat_a_diag_inv[2] = _mm256_blend_ps(mat_a_blk_elems[4], mat_a_blk_elems[5], 0xAA);//diag 4,5 mat_a_diag_inv[3] = _mm256_blend_ps(mat_a_blk_elems[6], mat_a_blk_elems[7], 0xAA);//diag 6,7 mat_a_diag_inv[0] = _mm256_blend_ps(mat_a_diag_inv[0], mat_a_diag_inv[1], 0xCC);//diag 0,1,2,3 mat_a_diag_inv[2] = _mm256_blend_ps(mat_a_diag_inv[2], mat_a_diag_inv[3], 0xCC);//diag 4,5,6,7 mat_a_diag_inv[0] = _mm256_blend_ps(mat_a_diag_inv[0], mat_a_diag_inv[2], 0xF0);//diag 0,1,2,3,4,5,6,7 //reciprocal of diagnal elements of A :- 0,1,2,3,4,5,6,7 reciprocal_diags[0] = _mm256_div_ps(reciprocal_diags[0], mat_a_diag_inv[0]); //ptr_b += j; //ptr_b_dup += 8; ptr_b_dup += 8; i1 += 8; i = i1; i2 = 0; //extract diag a00 from a mat_a_diag_inv[0] = _mm256_permute_ps(reciprocal_diags[0], 0x00); mat_a_diag_inv[0] = _mm256_permute2f128_ps(mat_a_diag_inv[0], mat_a_diag_inv[0], 0x00); //mat_a_diag_inv2[0] = _mm256_unpacklo_ps(mat_a_diag_inv2[0], mat_a_diag_inv2[0]); //extract diag a11 from a mat_a_diag_inv[1] = _mm256_permute_ps(reciprocal_diags[0], 0x55); mat_a_diag_inv[1] = _mm256_permute2f128_ps(mat_a_diag_inv[1], mat_a_diag_inv[1], 0x00); //mat_a_diag_inv[1] = _mm256_unpacklo_ps(mat_a_diag_inv[1], mat_a_diag_inv[1]); //extract diag a22 from a mat_a_diag_inv[2] = _mm256_permute_ps(reciprocal_diags[0], 0xAA); mat_a_diag_inv[2] = _mm256_permute2f128_ps(mat_a_diag_inv[2], mat_a_diag_inv[2], 0x00); //mat_a_diag_inv[2] = _mm256_unpacklo_ps(mat_a_diag_inv[2], mat_a_diag_inv[2]); //extract diag a33 from a mat_a_diag_inv[3] = _mm256_permute_ps(reciprocal_diags[0], 0xFF); mat_a_diag_inv[3] = _mm256_permute2f128_ps(mat_a_diag_inv[3], mat_a_diag_inv[3], 0x00); //mat_a_diag_inv[3] = _mm256_unpacklo_ps(mat_a_diag_inv[3], mat_a_diag_inv[3]); //extract diag a44 from a mat_a_diag_inv[4] = _mm256_permute_ps(reciprocal_diags[0], 0x00); mat_a_diag_inv[4] = _mm256_permute2f128_ps(mat_a_diag_inv[4], mat_a_diag_inv[4], 0x11); //mat_a_diag_inv[4] = _mm256_unpacklo_ps(mat_a_diag_inv[4], mat_a_diag_inv[4]); //extract diag a55 from a mat_a_diag_inv[5] = _mm256_permute_ps(reciprocal_diags[0], 0x55); mat_a_diag_inv[5] = _mm256_permute2f128_ps(mat_a_diag_inv[5], mat_a_diag_inv[5], 0x11); //mat_a_diag_inv[5] = _mm256_unpacklo_ps(mat_a_diag_inv[5], mat_a_diag_inv[5]); //extract diag a66 from a mat_a_diag_inv[6] = _mm256_permute_ps(reciprocal_diags[0], 0xAA); mat_a_diag_inv[6] = _mm256_permute2f128_ps(mat_a_diag_inv[6], mat_a_diag_inv[6], 0x11); //mat_a_diag_inv[6] = _mm256_unpacklo_ps(mat_a_diag_inv[6], mat_a_diag_inv[6]); //extract diag a77 from a mat_a_diag_inv[7] = _mm256_permute_ps(reciprocal_diags[0], 0xFF); mat_a_diag_inv[7] = _mm256_permute2f128_ps(mat_a_diag_inv[7], mat_a_diag_inv[7], 0x11); //mat_a_diag_inv[7] = _mm256_unpacklo_ps(mat_a_diag_inv[7], mat_a_diag_inv[7]); for (r = 0; r < numCols_b; r += GEMM_BLK_V1) { #if GEMM_ACCUM_A //Read 8 cols of B columns of Block-to-be-solved mat_b_col[0] = _mm256_loadu_ps((float const *)ptr_b + i); mat_b_col[1] = _mm256_loadu_ps((float const *)(ptr_b + cs_b + i)); mat_b_col[2] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[0] + i)); mat_b_col[3] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[1] + i)); mat_b_col[4] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[2] + i)); mat_b_col[5] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[3] + i)); mat_b_col[6] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[4] + i)); mat_b_col[7] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[5] + i)); /* transpose steps start */ ////unpacklow//// mat_b_rearr[0] = _mm256_unpacklo_ps(mat_b_col[0], mat_b_col[1]); mat_b_rearr[1] = _mm256_unpacklo_ps(mat_b_col[2], mat_b_col[3]); mat_b_rearr[2] = _mm256_unpacklo_ps(mat_b_col[4], mat_b_col[5]); mat_b_rearr[3] = _mm256_unpacklo_ps(mat_b_col[6], mat_b_col[7]); //Rearrange low elements #if REARRANGE_SHFL == 1 mat_b_rearr[4] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0x44); mat_b_rearr[5] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0xEE); mat_b_rearr[6] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0x44); mat_b_rearr[7] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0xEE); #else mat_b_rearr[6] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0x4E); mat_b_rearr[7] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0x4E); mat_b_rearr[4] = _mm256_blend_ps(mat_b_rearr[0], mat_b_rearr[6], 0xCC); mat_b_rearr[5] = _mm256_blend_ps(mat_b_rearr[1], mat_b_rearr[6], 0x33); mat_b_rearr[6] = _mm256_blend_ps(mat_b_rearr[2], mat_b_rearr[7], 0xCC); mat_b_rearr[7] = _mm256_blend_ps(mat_b_rearr[3], mat_b_rearr[7], 0x33); #endif //Merge rearranged low elements into complete rows mat_b_rearr[0] = _mm256_permute2f128_ps(mat_b_rearr[4], mat_b_rearr[6], 0x20); mat_b_rearr[4] = _mm256_permute2f128_ps(mat_b_rearr[4], mat_b_rearr[6], 0x31); mat_b_rearr[1] = _mm256_permute2f128_ps(mat_b_rearr[5], mat_b_rearr[7], 0x20); mat_b_rearr[5] = _mm256_permute2f128_ps(mat_b_rearr[5], mat_b_rearr[7], 0x31); ////unpackhigh//// mat_b_col[0] = _mm256_unpackhi_ps(mat_b_col[0], mat_b_col[1]); mat_b_col[1] = _mm256_unpackhi_ps(mat_b_col[2], mat_b_col[3]); mat_b_col[2] = _mm256_unpackhi_ps(mat_b_col[4], mat_b_col[5]); mat_b_col[3] = _mm256_unpackhi_ps(mat_b_col[6], mat_b_col[7]); //Rearrange high elements #if REARRANGE_SHFL == 1 mat_b_col[4] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0x44); mat_b_col[5] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0xEE); mat_b_col[6] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0x44); mat_b_col[7] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0xEE); #else mat_b_col[6] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0x4E); mat_b_col[7] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0x4E); mat_b_col[4] = _mm256_blend_ps(mat_b_col[0], mat_b_col[6], 0xCC); mat_b_col[5] = _mm256_blend_ps(mat_b_col[1], mat_b_col[6], 0x33); mat_b_col[6] = _mm256_blend_ps(mat_b_col[2], mat_b_col[7], 0xCC); mat_b_col[7] = _mm256_blend_ps(mat_b_col[3], mat_b_col[7], 0x33); #endif //Merge rearranged high elements into complete rows mat_b_rearr[2] = _mm256_permute2f128_ps(mat_b_col[4], mat_b_col[6], 0x20); mat_b_rearr[6] = _mm256_permute2f128_ps(mat_b_col[4], mat_b_col[6], 0x31); mat_b_rearr[3] = _mm256_permute2f128_ps(mat_b_col[5], mat_b_col[7], 0x20); mat_b_rearr[7] = _mm256_permute2f128_ps(mat_b_col[5], mat_b_col[7], 0x31); /* transpose steps end */ #endif //i = 0; ptr_l_dup = ptr_l; i4 = i2; for (l = 0; l < j; l += 8) // move across m { //for (k = 0; k < numCols_b; k += 8) // move across n for the same value of l (index of m) //{ /////////////////// Partial Lower 8x8 block trsm of B //Read current 8 cols of B columns from specified 8x8 current-block of B mat_a_blk_elems[0] = _mm256_loadu_ps((float const *)ptr_b + i4); mat_a_blk_elems[1] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b)); mat_a_blk_elems[2] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b_offset[0])); mat_a_blk_elems[3] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b_offset[1])); mat_a_blk_elems[4] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b_offset[2])); mat_a_blk_elems[5] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b_offset[3])); mat_a_blk_elems[6] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b_offset[4])); mat_a_blk_elems[7] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b_offset[5])); /* transpose steps start */ ////unpacklow//// mat_b_col[0] = _mm256_unpacklo_ps(mat_a_blk_elems[0], mat_a_blk_elems[1]); mat_b_col[1] = _mm256_unpacklo_ps(mat_a_blk_elems[2], mat_a_blk_elems[3]); mat_b_col[2] = _mm256_unpacklo_ps(mat_a_blk_elems[4], mat_a_blk_elems[5]); mat_b_col[3] = _mm256_unpacklo_ps(mat_a_blk_elems[6], mat_a_blk_elems[7]); //Rearrange low elements #if REARRANGE_SHFL == 1 mat_b_col[4] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0x44); mat_b_col[5] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0xEE); mat_b_col[6] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0x44); mat_b_col[7] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0xEE); #else mat_b_col[6] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0x4E); mat_b_col[7] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0x4E); mat_b_col[4] = _mm256_blend_ps(mat_b_col[0], mat_b_col[6], 0xCC); mat_b_col[5] = _mm256_blend_ps(mat_b_col[1], mat_b_col[6], 0x33); mat_b_col[6] = _mm256_blend_ps(mat_b_col[2], mat_b_col[7], 0xCC); mat_b_col[7] = _mm256_blend_ps(mat_b_col[3], mat_b_col[7], 0x33); #endif //Merge rearranged low elements into complete rows mat_b_col[0] = _mm256_permute2f128_ps(mat_b_col[4], mat_b_col[6], 0x20); mat_b_col[4] = _mm256_permute2f128_ps(mat_b_col[4], mat_b_col[6], 0x31); mat_b_col[1] = _mm256_permute2f128_ps(mat_b_col[5], mat_b_col[7], 0x20); mat_b_col[5] = _mm256_permute2f128_ps(mat_b_col[5], mat_b_col[7], 0x31); ////unpackhigh//// mat_a_blk_elems[0] = _mm256_unpackhi_ps(mat_a_blk_elems[0], mat_a_blk_elems[1]); mat_a_blk_elems[1] = _mm256_unpackhi_ps(mat_a_blk_elems[2], mat_a_blk_elems[3]); mat_a_blk_elems[2] = _mm256_unpackhi_ps(mat_a_blk_elems[4], mat_a_blk_elems[5]); mat_a_blk_elems[3] = _mm256_unpackhi_ps(mat_a_blk_elems[6], mat_a_blk_elems[7]); //Rearrange high elements #if REARRANGE_SHFL == 1 mat_a_blk_elems[4] = _mm256_shuffle_ps(mat_a_blk_elems[0], mat_a_blk_elems[1], 0x44); mat_a_blk_elems[5] = _mm256_shuffle_ps(mat_a_blk_elems[0], mat_a_blk_elems[1], 0xEE); mat_a_blk_elems[6] = _mm256_shuffle_ps(mat_a_blk_elems[2], mat_a_blk_elems[3], 0x44); mat_a_blk_elems[7] = _mm256_shuffle_ps(mat_a_blk_elems[2], mat_a_blk_elems[3], 0xEE); #else mat_a_blk_elems[6] = _mm256_shuffle_ps(mat_a_blk_elems[0], mat_a_blk_elems[1], 0x4E); mat_a_blk_elems[7] = _mm256_shuffle_ps(mat_a_blk_elems[2], mat_a_blk_elems[3], 0x4E); mat_a_blk_elems[4] = _mm256_blend_ps(mat_a_blk_elems[0], mat_a_blk_elems[6], 0xCC); mat_a_blk_elems[5] = _mm256_blend_ps(mat_a_blk_elems[1], mat_a_blk_elems[6], 0x33); mat_a_blk_elems[6] = _mm256_blend_ps(mat_a_blk_elems[2], mat_a_blk_elems[7], 0xCC); mat_a_blk_elems[7] = _mm256_blend_ps(mat_a_blk_elems[3], mat_a_blk_elems[7], 0x33); #endif //Merge rearranged high elements into complete rows mat_b_col[2] = _mm256_permute2f128_ps(mat_a_blk_elems[4], mat_a_blk_elems[6], 0x20); mat_b_col[6] = _mm256_permute2f128_ps(mat_a_blk_elems[4], mat_a_blk_elems[6], 0x31); mat_b_col[3] = _mm256_permute2f128_ps(mat_a_blk_elems[5], mat_a_blk_elems[7], 0x20); mat_b_col[7] = _mm256_permute2f128_ps(mat_a_blk_elems[5], mat_a_blk_elems[7], 0x31); /* transpose steps end */ //Broadcast A8,0 to A15,0 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[0])); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[1])); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[2])); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[3])); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[4])); mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[5])); //i4 = k >> 3; ptr_l_dup++; #if GEMM_ACCUM_A //(Row8): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[0] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[0], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[0], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[0], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[0], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[0], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[0], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_col[0], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[7], mat_b_col[0], mat_b_rearr[7]);//d = c - (a*b) #else mat_b_rearr[0] = _mm256_mul_ps(mat_a_blk_elems[0], mat_b_col[0]); mat_b_rearr[1] = _mm256_mul_ps(mat_a_blk_elems[1], mat_b_col[0]); mat_b_rearr[2] = _mm256_mul_ps(mat_a_blk_elems[2], mat_b_col[0]); mat_b_rearr[3] = _mm256_mul_ps(mat_a_blk_elems[3], mat_b_col[0]); mat_b_rearr[4] = _mm256_mul_ps(mat_a_blk_elems[4], mat_b_col[0]); mat_b_rearr[5] = _mm256_mul_ps(mat_a_blk_elems[5], mat_b_col[0]); mat_b_rearr[6] = _mm256_mul_ps(mat_a_blk_elems[6], mat_b_col[0]); mat_b_rearr[7] = _mm256_mul_ps(mat_a_blk_elems[7], mat_b_col[0]); #endif //Broadcast A21 to A71 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[0])); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[1])); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[2])); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[3])); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[4])); mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[5])); ptr_l_dup++; #if GEMM_ACCUM_A //(Row9): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[0] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[1], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[1], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[1], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[1], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[1], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[1], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_col[1], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[7], mat_b_col[1], mat_b_rearr[7]);//d = c - (a*b) #else mat_b_rearr[0] = _mm256_fmadd_ps(mat_a_blk_elems[0], mat_b_col[1], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fmadd_ps(mat_a_blk_elems[1], mat_b_col[1], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fmadd_ps(mat_a_blk_elems[2], mat_b_col[1], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fmadd_ps(mat_a_blk_elems[3], mat_b_col[1], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fmadd_ps(mat_a_blk_elems[4], mat_b_col[1], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fmadd_ps(mat_a_blk_elems[5], mat_b_col[1], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fmadd_ps(mat_a_blk_elems[6], mat_b_col[1], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fmadd_ps(mat_a_blk_elems[7], mat_b_col[1], mat_b_rearr[7]);//d = c - (a*b) #endif //Broadcast A8,2 to A15,2 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[0])); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[1])); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[2])); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[3])); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[4])); mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[5])); ptr_l_dup++; #if GEMM_ACCUM_A //(Row10): FMA operations of b2 with elements of indices from (2, 0) uptill (7, 0) mat_b_rearr[0] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[2], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[2], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[2], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[2], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[2], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[2], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_col[2], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[7], mat_b_col[2], mat_b_rearr[7]);//d = c - (a*b) #else mat_b_rearr[0] = _mm256_fmadd_ps(mat_a_blk_elems[0], mat_b_col[2], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fmadd_ps(mat_a_blk_elems[1], mat_b_col[2], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fmadd_ps(mat_a_blk_elems[2], mat_b_col[2], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fmadd_ps(mat_a_blk_elems[3], mat_b_col[2], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fmadd_ps(mat_a_blk_elems[4], mat_b_col[2], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fmadd_ps(mat_a_blk_elems[5], mat_b_col[2], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fmadd_ps(mat_a_blk_elems[6], mat_b_col[2], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fmadd_ps(mat_a_blk_elems[7], mat_b_col[2], mat_b_rearr[7]);//d = c - (a*b) #endif //Broadcast A8,3 to A15,3 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[0])); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[1])); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[2])); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[3])); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[4])); mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[5])); ptr_l_dup++; #if GEMM_ACCUM_A //(Row11): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[0] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[3], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[3], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[3], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[3], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[3], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[3], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_col[3], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[7], mat_b_col[3], mat_b_rearr[7]);//d = c - (a*b) #else mat_b_rearr[0] = _mm256_fmadd_ps(mat_a_blk_elems[0], mat_b_col[3], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fmadd_ps(mat_a_blk_elems[1], mat_b_col[3], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fmadd_ps(mat_a_blk_elems[2], mat_b_col[3], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fmadd_ps(mat_a_blk_elems[3], mat_b_col[3], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fmadd_ps(mat_a_blk_elems[4], mat_b_col[3], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fmadd_ps(mat_a_blk_elems[5], mat_b_col[3], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fmadd_ps(mat_a_blk_elems[6], mat_b_col[3], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fmadd_ps(mat_a_blk_elems[7], mat_b_col[3], mat_b_rearr[7]);//d = c - (a*b) #endif //Broadcast A8,4 to A15,4 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[0])); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[1])); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[2])); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[3])); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[4])); mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[5])); ptr_l_dup++; #if GEMM_ACCUM_A //(Row12): FMA operations of b2 with elements of indices from (2, 0) uptill (7, 0) mat_b_rearr[0] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[4], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[4], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[4], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[4], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[4], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[4], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_col[4], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[7], mat_b_col[4], mat_b_rearr[7]);//d = c - (a*b) #else mat_b_rearr[0] = _mm256_fmadd_ps(mat_a_blk_elems[0], mat_b_col[4], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fmadd_ps(mat_a_blk_elems[1], mat_b_col[4], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fmadd_ps(mat_a_blk_elems[2], mat_b_col[4], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fmadd_ps(mat_a_blk_elems[3], mat_b_col[4], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fmadd_ps(mat_a_blk_elems[4], mat_b_col[4], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fmadd_ps(mat_a_blk_elems[5], mat_b_col[4], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fmadd_ps(mat_a_blk_elems[6], mat_b_col[4], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fmadd_ps(mat_a_blk_elems[7], mat_b_col[4], mat_b_rearr[7]);//d = c - (a*b) #endif //Broadcast A8,5 to A15,5 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[0])); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[1])); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[2])); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[3])); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[4])); mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[5])); ptr_l_dup++; #if GEMM_ACCUM_A //(Row13): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[0] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[5], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[5], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[5], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[5], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[5], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[5], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_col[5], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[7], mat_b_col[5], mat_b_rearr[7]);//d = c - (a*b) #else mat_b_rearr[0] = _mm256_fmadd_ps(mat_a_blk_elems[0], mat_b_col[5], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fmadd_ps(mat_a_blk_elems[1], mat_b_col[5], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fmadd_ps(mat_a_blk_elems[2], mat_b_col[5], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fmadd_ps(mat_a_blk_elems[3], mat_b_col[5], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fmadd_ps(mat_a_blk_elems[4], mat_b_col[5], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fmadd_ps(mat_a_blk_elems[5], mat_b_col[5], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fmadd_ps(mat_a_blk_elems[6], mat_b_col[5], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fmadd_ps(mat_a_blk_elems[7], mat_b_col[5], mat_b_rearr[7]);//d = c - (a*b) #endif //Broadcast A8,6 to A15,6 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[0])); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[1])); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[2])); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[3])); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[4])); mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[5])); ptr_l_dup++; #if GEMM_ACCUM_A //(Row14): FMA operations of b2 with elements of indices from (2, 0) uptill (7, 0) mat_b_rearr[0] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[6], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[6], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[6], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[6], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[6], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[6], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_col[6], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[7], mat_b_col[6], mat_b_rearr[7]);//d = c - (a*b) #else mat_b_rearr[0] = _mm256_fmadd_ps(mat_a_blk_elems[0], mat_b_col[6], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fmadd_ps(mat_a_blk_elems[1], mat_b_col[6], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fmadd_ps(mat_a_blk_elems[2], mat_b_col[6], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fmadd_ps(mat_a_blk_elems[3], mat_b_col[6], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fmadd_ps(mat_a_blk_elems[4], mat_b_col[6], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fmadd_ps(mat_a_blk_elems[5], mat_b_col[6], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fmadd_ps(mat_a_blk_elems[6], mat_b_col[6], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fmadd_ps(mat_a_blk_elems[7], mat_b_col[6], mat_b_rearr[7]);//d = c - (a*b) #endif //Broadcast A8,7 to A15,7 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[0])); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[1])); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[2])); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[3])); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[4])); mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[5])); ptr_l_dup++; #if GEMM_ACCUM_A //(Row15): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[0] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[7], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[7], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[7], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[7], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[7], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[7], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_col[7], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[7], mat_b_col[7], mat_b_rearr[7]);//d = c - (a*b) #else mat_b_rearr[0] = _mm256_fmadd_ps(mat_a_blk_elems[0], mat_b_col[7], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fmadd_ps(mat_a_blk_elems[1], mat_b_col[7], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fmadd_ps(mat_a_blk_elems[2], mat_b_col[7], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fmadd_ps(mat_a_blk_elems[3], mat_b_col[7], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fmadd_ps(mat_a_blk_elems[4], mat_b_col[7], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fmadd_ps(mat_a_blk_elems[5], mat_b_col[7], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fmadd_ps(mat_a_blk_elems[6], mat_b_col[7], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fmadd_ps(mat_a_blk_elems[7], mat_b_col[7], mat_b_rearr[7]);//d = c - (a*b) #endif //end loop of cols //} //i2 += cs_b_offset[6]; i4 += 8; } //trsm solve k = 0; //for (i2 = 0; i2 < numCols_b; i2 += 8) //{ //i2 = i1 + r; /////////////////// Complete Lower 8x8 block trsm of B :- lower 8x8 block of B with lower right 8x8 block of A #if !GEMM_ACCUM_A //Read 8 cols of B columns of Block-to-be-solved mat_b_rearr[0] = _mm256_loadu_ps((float const *)ptr_b + i); mat_b_rearr[1] = _mm256_loadu_ps((float const *)(ptr_b + cs_b + i)); mat_b_rearr[2] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[0] + i)); mat_b_rearr[3] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[1] + i)); mat_b_rearr[4] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[2] + i)); mat_b_rearr[5] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[3] + i)); mat_b_rearr[6] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[4] + i)); mat_b_rearr[7] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[5] + i)); /* transpose steps start */ ////unpacklow//// mat_b_col[0] = _mm256_unpacklo_ps(mat_b_rearr[0], mat_b_rearr[1]); mat_b_col[1] = _mm256_unpacklo_ps(mat_b_rearr[2], mat_b_rearr[3]); mat_b_col[2] = _mm256_unpacklo_ps(mat_b_rearr[4], mat_b_rearr[5]); mat_b_col[3] = _mm256_unpacklo_ps(mat_b_rearr[6], mat_b_rearr[7]); //Rearrange low elements #if REARRANGE_SHFL == 1 mat_b_col[4] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0x44); mat_b_col[5] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0xEE); mat_b_col[6] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0x44); mat_b_col[7] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0xEE); #else mat_b_col[6] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0x4E); mat_b_col[7] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0x4E); mat_b_col[4] = _mm256_blend_ps(mat_b_col[0], mat_b_col[6], 0xCC); mat_b_col[5] = _mm256_blend_ps(mat_b_col[1], mat_b_col[6], 0x33); mat_b_col[6] = _mm256_blend_ps(mat_b_col[2], mat_b_col[7], 0xCC); mat_b_col[7] = _mm256_blend_ps(mat_b_col[3], mat_b_col[7], 0x33); #endif //Merge rearranged low elements into complete rows mat_b_col[0] = _mm256_permute2f128_ps(mat_b_col[4], mat_b_col[6], 0x20); mat_b_col[4] = _mm256_permute2f128_ps(mat_b_col[4], mat_b_col[6], 0x31); mat_b_col[1] = _mm256_permute2f128_ps(mat_b_col[5], mat_b_col[7], 0x20); mat_b_col[5] = _mm256_permute2f128_ps(mat_b_col[5], mat_b_col[7], 0x31); ////unpackhigh//// mat_b_rearr[0] = _mm256_unpackhi_ps(mat_b_rearr[0], mat_b_rearr[1]); mat_b_rearr[1] = _mm256_unpackhi_ps(mat_b_rearr[2], mat_b_rearr[3]); mat_b_rearr[2] = _mm256_unpackhi_ps(mat_b_rearr[4], mat_b_rearr[5]); mat_b_rearr[3] = _mm256_unpackhi_ps(mat_b_rearr[6], mat_b_rearr[7]); //Rearrange high elements #if REARRANGE_SHFL == 1 mat_b_rearr[4] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0x44); mat_b_rearr[5] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0xEE); mat_b_rearr[6] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0x44); mat_b_rearr[7] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0xEE); #else mat_b_rearr[6] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0x4E); mat_b_rearr[7] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0x4E); mat_b_rearr[4] = _mm256_blend_ps(mat_b_rearr[0], mat_b_rearr[6], 0xCC); mat_b_rearr[5] = _mm256_blend_ps(mat_b_rearr[1], mat_b_rearr[6], 0x33); mat_b_rearr[6] = _mm256_blend_ps(mat_b_rearr[2], mat_b_rearr[7], 0xCC); mat_b_rearr[7] = _mm256_blend_ps(mat_b_rearr[3], mat_b_rearr[7], 0x33); #endif //Merge rearranged high elements into complete rows mat_b_col[2] = _mm256_permute2f128_ps(mat_b_rearr[4], mat_b_rearr[6], 0x20); mat_b_col[6] = _mm256_permute2f128_ps(mat_b_rearr[4], mat_b_rearr[6], 0x31); mat_b_col[3] = _mm256_permute2f128_ps(mat_b_rearr[5], mat_b_rearr[7], 0x20); mat_b_col[7] = _mm256_permute2f128_ps(mat_b_rearr[5], mat_b_rearr[7], 0x31); /* transpose steps end */ #endif //Broadcast A10 to A70 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[0])); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[1])); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[2])); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[3])); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[4])); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[5])); //i += cs_l; #if GEMM_ACCUM_A //(Row0): Perform mul operation of reciprocal of L(0,0) element with 1st row elements of B mat_b_rearr[0] = _mm256_mul_ps(mat_b_rearr[0], mat_a_diag_inv[0]); #else mat_b_rearr[0] = _mm256_sub_ps(mat_b_col[0], mat_b_rearr[0]); mat_b_rearr[0] = _mm256_mul_ps(mat_b_rearr[0], mat_a_diag_inv[0]); #endif #if GEMM_ACCUM_A mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_rearr[0], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_rearr[0], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_rearr[0], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_rearr[0], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_rearr[0], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_rearr[0], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_rearr[0], mat_b_rearr[7]);//d = c - (a*b) #else mat_b_rearr[1] = _mm256_sub_ps(mat_b_col[1], mat_b_rearr[1]); mat_b_rearr[2] = _mm256_sub_ps(mat_b_col[2], mat_b_rearr[2]); mat_b_rearr[3] = _mm256_sub_ps(mat_b_col[3], mat_b_rearr[3]); mat_b_rearr[4] = _mm256_sub_ps(mat_b_col[4], mat_b_rearr[4]); mat_b_rearr[5] = _mm256_sub_ps(mat_b_col[5], mat_b_rearr[5]); mat_b_rearr[6] = _mm256_sub_ps(mat_b_col[6], mat_b_rearr[6]); mat_b_rearr[7] = _mm256_sub_ps(mat_b_col[7], mat_b_rearr[7]); //(Row1): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_rearr[0], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_rearr[0], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_rearr[0], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_rearr[0], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_rearr[0], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_rearr[0], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_rearr[0], mat_b_rearr[7]);//d = c - (a*b) #endif //Broadcast A21 to A71 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 1 + cs_l_offset[0])); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 1 + cs_l_offset[1])); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 1 + cs_l_offset[2])); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 1 + cs_l_offset[3])); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 1 + cs_l_offset[4])); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 1 + cs_l_offset[5])); //i += cs_l; //Perform mul operation of reciprocal of L(1,1) element with 2nd row elements of B mat_b_rearr[1] = _mm256_mul_ps(mat_b_rearr[1], mat_a_diag_inv[1]); //(Row2): FMA operations of b2 with elements of indices from (2, 0) uptill (7, 0) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_rearr[1], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_rearr[1], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_rearr[1], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_rearr[1], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_rearr[1], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_rearr[1], mat_b_rearr[7]);//d = c - (a*b) //Broadcast A32 to A72 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 2 + cs_l_offset[1])); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 2 + cs_l_offset[2])); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 2 + cs_l_offset[3])); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 2 + cs_l_offset[4])); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 2 + cs_l_offset[5])); //i += cs_l; //Perform mul operation of reciprocal of L(2, 2) element with 3rd row elements of B mat_b_rearr[2] = _mm256_mul_ps(mat_b_rearr[2], mat_a_diag_inv[2]); //(Row3): FMA operations of b3 with elements of indices from (3, 0) uptill (7, 0) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_rearr[2], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_rearr[2], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_rearr[2], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_rearr[2], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_rearr[2], mat_b_rearr[7]);//d = c - (a*b) //Broadcast A43 to A73 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 3 + cs_l_offset[2])); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 3 + cs_l_offset[3])); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 3 + cs_l_offset[4])); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 3 + cs_l_offset[5])); //i += cs_l; //Perform mul operation of reciprocal of L(3, 3) element with 4rth row elements of B mat_b_rearr[3] = _mm256_mul_ps(mat_b_rearr[3], mat_a_diag_inv[3]); //(Row4): FMA operations of b4 with elements of indices from (4, 0) uptill (7, 0) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_rearr[3], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_rearr[3], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_rearr[3], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_rearr[3], mat_b_rearr[7]);//d = c - (a*b) //Broadcast A54 to A74 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 4 + cs_l_offset[3])); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 4 + cs_l_offset[4])); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 4 + cs_l_offset[5])); //i += cs_l; //Perform mul operation of reciprocal of L(4, 4) element with 4rth row elements of B mat_b_rearr[4] = _mm256_mul_ps(mat_b_rearr[4], mat_a_diag_inv[4]); //(Row5): FMA operations of b5 with elements of indices from (5, 0) uptill (7, 0) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_rearr[4], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_rearr[4], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_rearr[4], mat_b_rearr[7]);//d = c - (a*b) //Broadcast A65 to A75 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 5 + cs_l_offset[4])); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 5 + cs_l_offset[5])); //i += cs_l; //Perform mul operation of reciprocal of L(5, 5) element with 5th row elements of B mat_b_rearr[5] = _mm256_mul_ps(mat_b_rearr[5], mat_a_diag_inv[5]); //(Row6): FMA operations of b6 with elements of indices from (6, 0) uptill (7, 0) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_rearr[5], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_rearr[5], mat_b_rearr[7]);//d = c - (a*b) //Broadcast A76 to register mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 6 + cs_l_offset[5])); //Perform mul operation of reciprocal of L(6, 6) element with 6th row elements of B mat_b_rearr[6] = _mm256_mul_ps(mat_b_rearr[6], mat_a_diag_inv[6]); //(Row7): FMA operations of b7 with elements of index (7, 0) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_rearr[6], mat_b_rearr[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(7, 7) element with 7th row elements of B mat_b_rearr[7] = _mm256_mul_ps(mat_b_rearr[7], mat_a_diag_inv[7]); //////////////////////////////////////////////////////////////////////////////// /* transpose steps start */ ////unpacklow//// mat_b_col[0] = _mm256_unpacklo_ps(mat_b_rearr[0], mat_b_rearr[1]); mat_b_col[1] = _mm256_unpacklo_ps(mat_b_rearr[2], mat_b_rearr[3]); mat_b_col[2] = _mm256_unpacklo_ps(mat_b_rearr[4], mat_b_rearr[5]); mat_b_col[3] = _mm256_unpacklo_ps(mat_b_rearr[6], mat_b_rearr[7]); //Rearrange low elements #if REARRANGE_SHFL == 1 mat_b_col[4] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0x44); mat_b_col[5] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0xEE); mat_b_col[6] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0x44); mat_b_col[7] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0xEE); #else mat_b_col[6] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0x4E); mat_b_col[7] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0x4E); mat_b_col[4] = _mm256_blend_ps(mat_b_col[0], mat_b_col[6], 0xCC); mat_b_col[5] = _mm256_blend_ps(mat_b_col[1], mat_b_col[6], 0x33); mat_b_col[6] = _mm256_blend_ps(mat_b_col[2], mat_b_col[7], 0xCC); mat_b_col[7] = _mm256_blend_ps(mat_b_col[3], mat_b_col[7], 0x33); #endif //Merge rearranged low elements into complete rows mat_b_col[0] = _mm256_permute2f128_ps(mat_b_col[4], mat_b_col[6], 0x20); mat_b_col[4] = _mm256_permute2f128_ps(mat_b_col[4], mat_b_col[6], 0x31); mat_b_col[1] = _mm256_permute2f128_ps(mat_b_col[5], mat_b_col[7], 0x20); mat_b_col[5] = _mm256_permute2f128_ps(mat_b_col[5], mat_b_col[7], 0x31); ////unpackhigh//// mat_b_rearr[0] = _mm256_unpackhi_ps(mat_b_rearr[0], mat_b_rearr[1]); mat_b_rearr[1] = _mm256_unpackhi_ps(mat_b_rearr[2], mat_b_rearr[3]); mat_b_rearr[2] = _mm256_unpackhi_ps(mat_b_rearr[4], mat_b_rearr[5]); mat_b_rearr[3] = _mm256_unpackhi_ps(mat_b_rearr[6], mat_b_rearr[7]); //Rearrange high elements #if REARRANGE_SHFL == 1 mat_b_rearr[4] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0x44); mat_b_rearr[5] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0xEE); mat_b_rearr[6] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0x44); mat_b_rearr[7] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0xEE); #else mat_b_rearr[6] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0x4E); mat_b_rearr[7] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0x4E); mat_b_rearr[4] = _mm256_blend_ps(mat_b_rearr[0], mat_b_rearr[6], 0xCC); mat_b_rearr[5] = _mm256_blend_ps(mat_b_rearr[1], mat_b_rearr[6], 0x33); mat_b_rearr[6] = _mm256_blend_ps(mat_b_rearr[2], mat_b_rearr[7], 0xCC); mat_b_rearr[7] = _mm256_blend_ps(mat_b_rearr[3], mat_b_rearr[7], 0x33); #endif //Merge rearranged high elements into complete rows mat_b_col[2] = _mm256_permute2f128_ps(mat_b_rearr[4], mat_b_rearr[6], 0x20); mat_b_col[6] = _mm256_permute2f128_ps(mat_b_rearr[4], mat_b_rearr[6], 0x31); mat_b_col[3] = _mm256_permute2f128_ps(mat_b_rearr[5], mat_b_rearr[7], 0x20); mat_b_col[7] = _mm256_permute2f128_ps(mat_b_rearr[5], mat_b_rearr[7], 0x31); /* transpose steps end */ //Store the computed B columns _mm256_storeu_ps((float *)ptr_b_dup + i2, mat_b_col[0]); _mm256_storeu_ps((float *)(ptr_b_dup + (cs_b)+i2), mat_b_col[1]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[0] + i2), mat_b_col[2]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[1] + i2), mat_b_col[3]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[2] + i2), mat_b_col[4]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[3] + i2), mat_b_col[5]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[4] + i2), mat_b_col[6]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[5] + i2), mat_b_col[7]); //printf("writing B => m[%d], n[%d], [%f]\n", j, k, *(ptr_b_dup + k)); k++; //} i += cs_b_offset[6]; i2 += cs_b_offset[6]; } } //numRows of A ///////////////////loop ends ///////////////////// } static void trsm_AutXB_block_allSmallSizedMatrices_alpha(float *ptr_l, float *ptr_b, int numRows_lb, int numCols_b, int rs_l, int rs_b, int cs_l, int cs_b, float alpha) { float ones = 1.0; int i, i1, i2, i3, i4, j, k, l, r; int cs_b_offset[7]; int cs_l_offset[7]; float *ptr_b_dup, *ptr_l_dup; //57 number of ymm(256 bits) registers used __m256 mat_b_col[8]; __m256 mat_b_rearr[8]; __m256 mat_a_blk_elems[8]; __m256 mat_a_diag_inv[8]; __m256 reciprocal_diags[2]; __m256 alphaReg; reciprocal_diags[0] = _mm256_broadcast_ss((float const *)(&ones)); alphaReg = _mm256_broadcast_ss((float const *)&alpha); // ---> considering that the matrix size is multiple of 16 rows and 8 cols <--- // //L matrix offsets cs_l_offset[0] = (cs_l << 1); cs_l_offset[1] = cs_l + cs_l_offset[0]; cs_l_offset[2] = (cs_l << 2); cs_l_offset[3] = cs_l + cs_l_offset[2]; cs_l_offset[4] = cs_l_offset[0] + cs_l_offset[2]; cs_l_offset[5] = cs_l + cs_l_offset[4]; cs_l_offset[6] = (cs_l_offset[5] + cs_l); //read diag elems of L 16x16 block mat_a_blk_elems[0] = _mm256_loadu_ps((float const *)ptr_l); mat_a_blk_elems[1] = _mm256_loadu_ps((float const *)ptr_l + cs_l); mat_a_blk_elems[2] = _mm256_loadu_ps((float const *)ptr_l + cs_l_offset[0]); mat_a_blk_elems[3] = _mm256_loadu_ps((float const *)ptr_l + cs_l_offset[1]); mat_a_blk_elems[4] = _mm256_loadu_ps((float const *)ptr_l + cs_l_offset[2]); mat_a_blk_elems[5] = _mm256_loadu_ps((float const *)ptr_l + cs_l_offset[3]); mat_a_blk_elems[6] = _mm256_loadu_ps((float const *)ptr_l + cs_l_offset[4]); mat_a_blk_elems[7] = _mm256_loadu_ps((float const *)ptr_l + cs_l_offset[5]); cs_b_offset[0] = (cs_b << 1); cs_b_offset[1] = cs_b + cs_b_offset[0]; cs_b_offset[2] = (cs_b << 2); cs_b_offset[3] = cs_b + cs_b_offset[2]; cs_b_offset[4] = cs_b_offset[0] + cs_b_offset[2]; cs_b_offset[5] = cs_b + cs_b_offset[4]; cs_b_offset[6] = (cs_b_offset[5] + cs_b); reciprocal_diags[1] = reciprocal_diags[0]; //pack first 8 diags together mat_a_diag_inv[0] = _mm256_blend_ps(mat_a_blk_elems[0], mat_a_blk_elems[1], 0xAA);//diag 0,1 mat_a_diag_inv[1] = _mm256_blend_ps(mat_a_blk_elems[2], mat_a_blk_elems[3], 0xAA);//diag 2,3 mat_a_diag_inv[2] = _mm256_blend_ps(mat_a_blk_elems[4], mat_a_blk_elems[5], 0xAA);//diag 4,5 mat_a_diag_inv[3] = _mm256_blend_ps(mat_a_blk_elems[6], mat_a_blk_elems[7], 0xAA);//diag 6,7 mat_a_diag_inv[0] = _mm256_blend_ps(mat_a_diag_inv[0], mat_a_diag_inv[1], 0xCC);//diag 0,1,2,3 mat_a_diag_inv[2] = _mm256_blend_ps(mat_a_diag_inv[2], mat_a_diag_inv[3], 0xCC);//diag 4,5,6,7 mat_a_diag_inv[0] = _mm256_blend_ps(mat_a_diag_inv[0], mat_a_diag_inv[2], 0xF0);//diag 0,1,2,3,4,5,6,7 //reciprocal of diagnal elements 0,1,2,3,4,5,6,7 reciprocal_diags[0] = _mm256_div_ps(reciprocal_diags[0], mat_a_diag_inv[0]); #if 0 //Broadcast A10 to A70 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + 1)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + 2)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l + 3)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l + 4)); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l + 5)); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l + 6)); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l + 7)); //Broadcast A21 to A71 to registers mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 2)); mat_a_blk_elems[8] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 3)); mat_a_blk_elems[9] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 4)); mat_a_blk_elems[10] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 5)); mat_a_blk_elems[11] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 6)); mat_a_blk_elems[12] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 7)); //Broadcast A32 to A72 to registers mat_a_blk_elems[13] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + 3)); mat_a_blk_elems[14] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + 4)); mat_a_blk_elems[15] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + 5)); mat_a_blk_elems[16] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + 6)); mat_a_blk_elems[17] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + 7)); //Broadcast A43 to A73 to registers mat_a_blk_elems[18] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + 4)); mat_a_blk_elems[19] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + 5)); mat_a_blk_elems[20] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + 6)); mat_a_blk_elems[21] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + 7)); //Broadcast A54 to A74 to registers mat_a_blk_elems[22] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[2] + 5)); mat_a_blk_elems[23] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[2] + 6)); mat_a_blk_elems[24] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[2] + 7)); //Broadcast A65 to A75 to registers mat_a_blk_elems[25] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[3] + 6)); mat_a_blk_elems[26] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[3] + 7)); //Broadcast A76 to register mat_a_blk_elems[27] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[4] + 7)); #endif //extract diag a00 from a mat_a_diag_inv[0] = _mm256_permute_ps(reciprocal_diags[0], 0x00); mat_a_diag_inv[0] = _mm256_permute2f128_ps(mat_a_diag_inv[0], mat_a_diag_inv[0], 0x00); //mat_a_diag_inv[0] = _mm256_unpacklo_ps(mat_a_diag_inv[0], mat_a_diag_inv[0]); //extract diag a11 from a mat_a_diag_inv[1] = _mm256_permute_ps(reciprocal_diags[0], 0x55); mat_a_diag_inv[1] = _mm256_permute2f128_ps(mat_a_diag_inv[1], mat_a_diag_inv[1], 0x00); //mat_a_diag_inv[1] = _mm256_unpacklo_ps(mat_a_diag_inv[1], mat_a_diag_inv[1]); //extract diag a22 from a mat_a_diag_inv[2] = _mm256_permute_ps(reciprocal_diags[0], 0xAA); mat_a_diag_inv[2] = _mm256_permute2f128_ps(mat_a_diag_inv[2], mat_a_diag_inv[2], 0x00); //mat_a_diag_inv[2] = _mm256_unpacklo_ps(mat_a_diag_inv[2], mat_a_diag_inv[2]); //extract diag a33 from a mat_a_diag_inv[3] = _mm256_permute_ps(reciprocal_diags[0], 0xFF); mat_a_diag_inv[3] = _mm256_permute2f128_ps(mat_a_diag_inv[3], mat_a_diag_inv[3], 0x00); //mat_a_diag_inv[3] = _mm256_unpacklo_ps(mat_a_diag_inv[3], mat_a_diag_inv[3]); //extract diag a44 from a mat_a_diag_inv[4] = _mm256_permute_ps(reciprocal_diags[0], 0x00); mat_a_diag_inv[4] = _mm256_permute2f128_ps(mat_a_diag_inv[4], mat_a_diag_inv[4], 0x11); //mat_a_diag_inv[4] = _mm256_unpacklo_ps(mat_a_diag_inv[4], mat_a_diag_inv[4]); //extract diag a55 from a mat_a_diag_inv[5] = _mm256_permute_ps(reciprocal_diags[0], 0x55); mat_a_diag_inv[5] = _mm256_permute2f128_ps(mat_a_diag_inv[5], mat_a_diag_inv[5], 0x11); //mat_a_diag_inv[5] = _mm256_unpacklo_ps(mat_a_diag_inv[5], mat_a_diag_inv[5]); //extract diag a66 from a mat_a_diag_inv[6] = _mm256_permute_ps(reciprocal_diags[0], 0xAA); mat_a_diag_inv[6] = _mm256_permute2f128_ps(mat_a_diag_inv[6], mat_a_diag_inv[6], 0x11); //mat_a_diag_inv[6] = _mm256_unpacklo_ps(mat_a_diag_inv[6], mat_a_diag_inv[6]); //extract diag a77 from a mat_a_diag_inv[7] = _mm256_permute_ps(reciprocal_diags[0], 0xFF); mat_a_diag_inv[7] = _mm256_permute2f128_ps(mat_a_diag_inv[7], mat_a_diag_inv[7], 0x11); //mat_a_diag_inv[7] = _mm256_unpacklo_ps(mat_a_diag_inv[7], mat_a_diag_inv[7]); /***************** first set of 8 rows of B processing starts *****************/ ptr_b_dup = ptr_b; i = 0; for (j = 0; j < numCols_b; j += 8) { /////////////////// Complete Upper 8x8 block trsm of B :- upper 8x8 block of B with upper 8x8 block of A //read 8x8 block of B into registers mat_b_rearr[0] = _mm256_loadu_ps((float const *)ptr_b + i); mat_b_rearr[1] = _mm256_loadu_ps((float const *)(ptr_b + cs_b + i)); mat_b_rearr[2] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[0] + i)); mat_b_rearr[3] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[1] + i)); mat_b_rearr[4] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[2] + i)); mat_b_rearr[5] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[3] + i)); mat_b_rearr[6] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[4] + i)); mat_b_rearr[7] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[5] + i)); /* transpose steps start */ ////unpacklow//// mat_b_col[0] = _mm256_unpacklo_ps(mat_b_rearr[0], mat_b_rearr[1]); mat_b_col[1] = _mm256_unpacklo_ps(mat_b_rearr[2], mat_b_rearr[3]); mat_b_col[2] = _mm256_unpacklo_ps(mat_b_rearr[4], mat_b_rearr[5]); mat_b_col[3] = _mm256_unpacklo_ps(mat_b_rearr[6], mat_b_rearr[7]); //Rearrange low elements #if REARRANGE_SHFL == 1 mat_b_col[4] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0x44); mat_b_col[5] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0xEE); mat_b_col[6] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0x44); mat_b_col[7] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0xEE); #else mat_b_col[6] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0x4E); mat_b_col[7] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0x4E); mat_b_col[4] = _mm256_blend_ps(mat_b_col[0], mat_b_col[6], 0xCC); mat_b_col[5] = _mm256_blend_ps(mat_b_col[1], mat_b_col[6], 0x33); mat_b_col[6] = _mm256_blend_ps(mat_b_col[2], mat_b_col[7], 0xCC); mat_b_col[7] = _mm256_blend_ps(mat_b_col[3], mat_b_col[7], 0x33); #endif //Merge rearranged low elements into complete rows mat_b_col[0] = _mm256_permute2f128_ps(mat_b_col[4], mat_b_col[6], 0x20); mat_b_col[4] = _mm256_permute2f128_ps(mat_b_col[4], mat_b_col[6], 0x31); mat_b_col[1] = _mm256_permute2f128_ps(mat_b_col[5], mat_b_col[7], 0x20); mat_b_col[5] = _mm256_permute2f128_ps(mat_b_col[5], mat_b_col[7], 0x31); ////unpackhigh//// mat_b_rearr[0] = _mm256_unpackhi_ps(mat_b_rearr[0], mat_b_rearr[1]); mat_b_rearr[1] = _mm256_unpackhi_ps(mat_b_rearr[2], mat_b_rearr[3]); mat_b_rearr[2] = _mm256_unpackhi_ps(mat_b_rearr[4], mat_b_rearr[5]); mat_b_rearr[3] = _mm256_unpackhi_ps(mat_b_rearr[6], mat_b_rearr[7]); //Rearrange high elements #if REARRANGE_SHFL == 1 mat_b_rearr[4] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0x44); mat_b_rearr[5] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0xEE); mat_b_rearr[6] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0x44); mat_b_rearr[7] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0xEE); #else mat_b_rearr[6] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0x4E); mat_b_rearr[7] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0x4E); mat_b_rearr[4] = _mm256_blend_ps(mat_b_rearr[0], mat_b_rearr[6], 0xCC); mat_b_rearr[5] = _mm256_blend_ps(mat_b_rearr[1], mat_b_rearr[6], 0x33); mat_b_rearr[6] = _mm256_blend_ps(mat_b_rearr[2], mat_b_rearr[7], 0xCC); mat_b_rearr[7] = _mm256_blend_ps(mat_b_rearr[3], mat_b_rearr[7], 0x33); #endif //Merge rearranged high elements into complete rows mat_b_col[2] = _mm256_permute2f128_ps(mat_b_rearr[4], mat_b_rearr[6], 0x20); mat_b_col[6] = _mm256_permute2f128_ps(mat_b_rearr[4], mat_b_rearr[6], 0x31); mat_b_col[3] = _mm256_permute2f128_ps(mat_b_rearr[5], mat_b_rearr[7], 0x20); mat_b_col[7] = _mm256_permute2f128_ps(mat_b_rearr[5], mat_b_rearr[7], 0x31); /* transpose steps end */ mat_b_col[0] = _mm256_mul_ps(mat_b_col[0], alphaReg); mat_b_col[1] = _mm256_mul_ps(mat_b_col[1], alphaReg); mat_b_col[2] = _mm256_mul_ps(mat_b_col[2], alphaReg); mat_b_col[3] = _mm256_mul_ps(mat_b_col[3], alphaReg); mat_b_col[4] = _mm256_mul_ps(mat_b_col[4], alphaReg); mat_b_col[5] = _mm256_mul_ps(mat_b_col[5], alphaReg); mat_b_col[6] = _mm256_mul_ps(mat_b_col[6], alphaReg); mat_b_col[7] = _mm256_mul_ps(mat_b_col[7], alphaReg); //(Row0): Perform mul operation of reciprocal of L(0,0) element with 1st row elements of B mat_b_col[0] = _mm256_mul_ps(mat_b_col[0], mat_a_diag_inv[0]); mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0])); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1])); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[2])); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[3])); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[4])); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[5])); //(Row1): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_col[1] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[0], mat_b_col[1]);//d = c - (a*b) mat_b_col[2] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[0], mat_b_col[2]);//d = c - (a*b) mat_b_col[3] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[0], mat_b_col[3]);//d = c - (a*b) mat_b_col[4] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[0], mat_b_col[4]);//d = c - (a*b) mat_b_col[5] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[0], mat_b_col[5]);//d = c - (a*b) mat_b_col[6] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[0], mat_b_col[6]);//d = c - (a*b) mat_b_col[7] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_col[0], mat_b_col[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(1,1) element with 2nd row elements of B mat_b_col[1] = _mm256_mul_ps(mat_b_col[1], mat_a_diag_inv[1]); mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + 1 + cs_l_offset[0])); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + 1 + cs_l_offset[1])); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l + 1 + cs_l_offset[2])); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l + 1 + cs_l_offset[3])); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l + 1 + cs_l_offset[4])); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l + 1 + cs_l_offset[5])); //(Row2): FMA operations of b2 with elements of indices from (2, 0) uptill (7, 0) mat_b_col[2] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[1], mat_b_col[2]);//d = c - (a*b) mat_b_col[3] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[1], mat_b_col[3]);//d = c - (a*b) mat_b_col[4] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[1], mat_b_col[4]);//d = c - (a*b) mat_b_col[5] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[1], mat_b_col[5]);//d = c - (a*b) mat_b_col[6] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[1], mat_b_col[6]);//d = c - (a*b) mat_b_col[7] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[1], mat_b_col[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(2, 2) element with 3rd row elements of B mat_b_col[2] = _mm256_mul_ps(mat_b_col[2], mat_a_diag_inv[2]); mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + 2 + cs_l_offset[1])); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + 2 + cs_l_offset[2])); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l + 2 + cs_l_offset[3])); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l + 2 + cs_l_offset[4])); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l + 2 + cs_l_offset[5])); //(Row3): FMA operations of b3 with elements of indices from (3, 0) uptill (7, 0) mat_b_col[3] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[2], mat_b_col[3]);//d = c - (a*b) mat_b_col[4] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[2], mat_b_col[4]);//d = c - (a*b) mat_b_col[5] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[2], mat_b_col[5]);//d = c - (a*b) mat_b_col[6] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[2], mat_b_col[6]);//d = c - (a*b) mat_b_col[7] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[2], mat_b_col[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(3, 3) element with 4rth row elements of B mat_b_col[3] = _mm256_mul_ps(mat_b_col[3], mat_a_diag_inv[3]); mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + 3 + cs_l_offset[2])); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + 3 + cs_l_offset[3])); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l + 3 + cs_l_offset[4])); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l + 3 + cs_l_offset[5])); //(Row4): FMA operations of b4 with elements of indices from (4, 0) uptill (7, 0) mat_b_col[4] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[3], mat_b_col[4]);//d = c - (a*b) mat_b_col[5] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[3], mat_b_col[5]);//d = c - (a*b) mat_b_col[6] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[3], mat_b_col[6]);//d = c - (a*b) mat_b_col[7] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[3], mat_b_col[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(4, 4) element with 4rth row elements of B mat_b_col[4] = _mm256_mul_ps(mat_b_col[4], mat_a_diag_inv[4]); mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + 4 + cs_l_offset[3])); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + 4 + cs_l_offset[4])); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l + 4 + cs_l_offset[5])); //(Row5): FMA operations of b5 with elements of indices from (5, 0) uptill (7, 0) mat_b_col[5] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[4], mat_b_col[5]);//d = c - (a*b) mat_b_col[6] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[4], mat_b_col[6]);//d = c - (a*b) mat_b_col[7] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[4], mat_b_col[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(5, 5) element with 5th row elements of B mat_b_col[5] = _mm256_mul_ps(mat_b_col[5], mat_a_diag_inv[5]); mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + 5 + cs_l_offset[4])); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + 5 + cs_l_offset[5])); //(Row6): FMA operations of b6 with elements of indices from (6, 0) uptill (7, 0) mat_b_col[6] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[5], mat_b_col[6]);//d = c - (a*b) mat_b_col[7] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[5], mat_b_col[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(6, 6) element with 6th row elements of B mat_b_col[6] = _mm256_mul_ps(mat_b_col[6], mat_a_diag_inv[6]); mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + 6 + cs_l_offset[5])); //(Row7): FMA operations of b7 with elements of index (7, 0) mat_b_col[7] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[6], mat_b_col[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(7, 7) element with 7th row elements of B mat_b_col[7] = _mm256_mul_ps(mat_b_col[7], mat_a_diag_inv[7]); //////////////////////////////////////////////////////////////////////////////// /* transpose steps start */ ////unpacklow//// mat_b_rearr[0] = _mm256_unpacklo_ps(mat_b_col[0], mat_b_col[1]); mat_b_rearr[1] = _mm256_unpacklo_ps(mat_b_col[2], mat_b_col[3]); mat_b_rearr[2] = _mm256_unpacklo_ps(mat_b_col[4], mat_b_col[5]); mat_b_rearr[3] = _mm256_unpacklo_ps(mat_b_col[6], mat_b_col[7]); //Rearrange low elements #if REARRANGE_SHFL == 1 mat_b_rearr[4] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0x44); mat_b_rearr[5] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0xEE); mat_b_rearr[6] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0x44); mat_b_rearr[7] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0xEE); #else mat_b_rearr[6] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0x4E); mat_b_rearr[7] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0x4E); mat_b_rearr[4] = _mm256_blend_ps(mat_b_rearr[0], mat_b_rearr[6], 0xCC); mat_b_rearr[5] = _mm256_blend_ps(mat_b_rearr[1], mat_b_rearr[6], 0x33); mat_b_rearr[6] = _mm256_blend_ps(mat_b_rearr[2], mat_b_rearr[7], 0xCC); mat_b_rearr[7] = _mm256_blend_ps(mat_b_rearr[3], mat_b_rearr[7], 0x33); #endif //Merge rearranged low elements into complete rows mat_b_rearr[0] = _mm256_permute2f128_ps(mat_b_rearr[4], mat_b_rearr[6], 0x20); mat_b_rearr[4] = _mm256_permute2f128_ps(mat_b_rearr[4], mat_b_rearr[6], 0x31); mat_b_rearr[1] = _mm256_permute2f128_ps(mat_b_rearr[5], mat_b_rearr[7], 0x20); mat_b_rearr[5] = _mm256_permute2f128_ps(mat_b_rearr[5], mat_b_rearr[7], 0x31); ////unpackhigh//// mat_b_col[0] = _mm256_unpackhi_ps(mat_b_col[0], mat_b_col[1]); mat_b_col[1] = _mm256_unpackhi_ps(mat_b_col[2], mat_b_col[3]); mat_b_col[2] = _mm256_unpackhi_ps(mat_b_col[4], mat_b_col[5]); mat_b_col[3] = _mm256_unpackhi_ps(mat_b_col[6], mat_b_col[7]); //Rearrange high elements #if REARRANGE_SHFL == 1 mat_b_col[4] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0x44); mat_b_col[5] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0xEE); mat_b_col[6] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0x44); mat_b_col[7] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0xEE); #else mat_b_col[6] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0x4E); mat_b_col[7] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0x4E); mat_b_col[4] = _mm256_blend_ps(mat_b_col[0], mat_b_col[6], 0xCC); mat_b_col[5] = _mm256_blend_ps(mat_b_col[1], mat_b_col[6], 0x33); mat_b_col[6] = _mm256_blend_ps(mat_b_col[2], mat_b_col[7], 0xCC); mat_b_col[7] = _mm256_blend_ps(mat_b_col[3], mat_b_col[7], 0x33); #endif //Merge rearranged high elements into complete rows mat_b_rearr[2] = _mm256_permute2f128_ps(mat_b_col[4], mat_b_col[6], 0x20); mat_b_rearr[6] = _mm256_permute2f128_ps(mat_b_col[4], mat_b_col[6], 0x31); mat_b_rearr[3] = _mm256_permute2f128_ps(mat_b_col[5], mat_b_col[7], 0x20); mat_b_rearr[7] = _mm256_permute2f128_ps(mat_b_col[5], mat_b_col[7], 0x31); /* transpose steps end */ //Store the computed B columns _mm256_storeu_ps((float *)ptr_b_dup, mat_b_rearr[0]); _mm256_storeu_ps((float *)(ptr_b_dup + (cs_b)), mat_b_rearr[1]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[0]), mat_b_rearr[2]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[1]), mat_b_rearr[3]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[2]), mat_b_rearr[4]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[3]), mat_b_rearr[5]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[4]), mat_b_rearr[6]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[5]), mat_b_rearr[7]); i += cs_b_offset[6]; ptr_b_dup += cs_b_offset[6]; //i += 8; //ptr_b_dup += 8; } //c = 0; /***************** first set of 8 cols of B processing done *****************/ ptr_b_dup = ptr_b; i3 = 0; i1 = 0; //Start loop for cols of B to be processed in size of blk_width for (j = 8; j < numRows_lb; j += 8)//m :- 8x8 block row { ptr_l += cs_l_offset[6]; //Read next 8x8 block of A to get diag elements i3 += 8; mat_a_blk_elems[0] = _mm256_loadu_ps((float const *)ptr_l + i3); mat_a_blk_elems[1] = _mm256_loadu_ps((float const *)ptr_l + i3 + cs_l); mat_a_blk_elems[2] = _mm256_loadu_ps((float const *)ptr_l + i3 + cs_l_offset[0]); mat_a_blk_elems[3] = _mm256_loadu_ps((float const *)ptr_l + i3 + cs_l_offset[1]); mat_a_blk_elems[4] = _mm256_loadu_ps((float const *)ptr_l + i3 + cs_l_offset[2]); mat_a_blk_elems[5] = _mm256_loadu_ps((float const *)ptr_l + i3 + cs_l_offset[3]); mat_a_blk_elems[6] = _mm256_loadu_ps((float const *)ptr_l + i3 + cs_l_offset[4]); mat_a_blk_elems[7] = _mm256_loadu_ps((float const *)ptr_l + i3 + cs_l_offset[5]); //pack 8 diags of A together reciprocal_diags[0] = reciprocal_diags[1]; mat_a_diag_inv[0] = _mm256_blend_ps(mat_a_blk_elems[0], mat_a_blk_elems[1], 0xAA);//diag 0,1 mat_a_diag_inv[1] = _mm256_blend_ps(mat_a_blk_elems[2], mat_a_blk_elems[3], 0xAA);//diag 2,3 mat_a_diag_inv[2] = _mm256_blend_ps(mat_a_blk_elems[4], mat_a_blk_elems[5], 0xAA);//diag 4,5 mat_a_diag_inv[3] = _mm256_blend_ps(mat_a_blk_elems[6], mat_a_blk_elems[7], 0xAA);//diag 6,7 mat_a_diag_inv[0] = _mm256_blend_ps(mat_a_diag_inv[0], mat_a_diag_inv[1], 0xCC);//diag 0,1,2,3 mat_a_diag_inv[2] = _mm256_blend_ps(mat_a_diag_inv[2], mat_a_diag_inv[3], 0xCC);//diag 4,5,6,7 mat_a_diag_inv[0] = _mm256_blend_ps(mat_a_diag_inv[0], mat_a_diag_inv[2], 0xF0);//diag 0,1,2,3,4,5,6,7 //reciprocal of diagnal elements of A :- 0,1,2,3,4,5,6,7 reciprocal_diags[0] = _mm256_div_ps(reciprocal_diags[0], mat_a_diag_inv[0]); //ptr_b += j; //ptr_b_dup += 8; ptr_b_dup += 8; i1 += 8; i = i1; i2 = 0; //extract diag a00 from a mat_a_diag_inv[0] = _mm256_permute_ps(reciprocal_diags[0], 0x00); mat_a_diag_inv[0] = _mm256_permute2f128_ps(mat_a_diag_inv[0], mat_a_diag_inv[0], 0x00); //mat_a_diag_inv2[0] = _mm256_unpacklo_ps(mat_a_diag_inv2[0], mat_a_diag_inv2[0]); //extract diag a11 from a mat_a_diag_inv[1] = _mm256_permute_ps(reciprocal_diags[0], 0x55); mat_a_diag_inv[1] = _mm256_permute2f128_ps(mat_a_diag_inv[1], mat_a_diag_inv[1], 0x00); //mat_a_diag_inv[1] = _mm256_unpacklo_ps(mat_a_diag_inv[1], mat_a_diag_inv[1]); //extract diag a22 from a mat_a_diag_inv[2] = _mm256_permute_ps(reciprocal_diags[0], 0xAA); mat_a_diag_inv[2] = _mm256_permute2f128_ps(mat_a_diag_inv[2], mat_a_diag_inv[2], 0x00); //mat_a_diag_inv[2] = _mm256_unpacklo_ps(mat_a_diag_inv[2], mat_a_diag_inv[2]); //extract diag a33 from a mat_a_diag_inv[3] = _mm256_permute_ps(reciprocal_diags[0], 0xFF); mat_a_diag_inv[3] = _mm256_permute2f128_ps(mat_a_diag_inv[3], mat_a_diag_inv[3], 0x00); //mat_a_diag_inv[3] = _mm256_unpacklo_ps(mat_a_diag_inv[3], mat_a_diag_inv[3]); //extract diag a44 from a mat_a_diag_inv[4] = _mm256_permute_ps(reciprocal_diags[0], 0x00); mat_a_diag_inv[4] = _mm256_permute2f128_ps(mat_a_diag_inv[4], mat_a_diag_inv[4], 0x11); //mat_a_diag_inv[4] = _mm256_unpacklo_ps(mat_a_diag_inv[4], mat_a_diag_inv[4]); //extract diag a55 from a mat_a_diag_inv[5] = _mm256_permute_ps(reciprocal_diags[0], 0x55); mat_a_diag_inv[5] = _mm256_permute2f128_ps(mat_a_diag_inv[5], mat_a_diag_inv[5], 0x11); //mat_a_diag_inv[5] = _mm256_unpacklo_ps(mat_a_diag_inv[5], mat_a_diag_inv[5]); //extract diag a66 from a mat_a_diag_inv[6] = _mm256_permute_ps(reciprocal_diags[0], 0xAA); mat_a_diag_inv[6] = _mm256_permute2f128_ps(mat_a_diag_inv[6], mat_a_diag_inv[6], 0x11); //mat_a_diag_inv[6] = _mm256_unpacklo_ps(mat_a_diag_inv[6], mat_a_diag_inv[6]); //extract diag a77 from a mat_a_diag_inv[7] = _mm256_permute_ps(reciprocal_diags[0], 0xFF); mat_a_diag_inv[7] = _mm256_permute2f128_ps(mat_a_diag_inv[7], mat_a_diag_inv[7], 0x11); //mat_a_diag_inv[7] = _mm256_unpacklo_ps(mat_a_diag_inv[7], mat_a_diag_inv[7]); for (r = 0; r < numCols_b; r += GEMM_BLK_V1) { #if GEMM_ACCUM_A //Read 8 cols of B columns of Block-to-be-solved mat_b_col[0] = _mm256_loadu_ps((float const *)ptr_b + i); mat_b_col[1] = _mm256_loadu_ps((float const *)(ptr_b + cs_b + i)); mat_b_col[2] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[0] + i)); mat_b_col[3] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[1] + i)); mat_b_col[4] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[2] + i)); mat_b_col[5] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[3] + i)); mat_b_col[6] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[4] + i)); mat_b_col[7] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[5] + i)); /* transpose steps start */ ////unpacklow//// mat_b_rearr[0] = _mm256_unpacklo_ps(mat_b_col[0], mat_b_col[1]); mat_b_rearr[1] = _mm256_unpacklo_ps(mat_b_col[2], mat_b_col[3]); mat_b_rearr[2] = _mm256_unpacklo_ps(mat_b_col[4], mat_b_col[5]); mat_b_rearr[3] = _mm256_unpacklo_ps(mat_b_col[6], mat_b_col[7]); //Rearrange low elements #if REARRANGE_SHFL == 1 mat_b_rearr[4] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0x44); mat_b_rearr[5] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0xEE); mat_b_rearr[6] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0x44); mat_b_rearr[7] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0xEE); #else mat_b_rearr[6] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0x4E); mat_b_rearr[7] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0x4E); mat_b_rearr[4] = _mm256_blend_ps(mat_b_rearr[0], mat_b_rearr[6], 0xCC); mat_b_rearr[5] = _mm256_blend_ps(mat_b_rearr[1], mat_b_rearr[6], 0x33); mat_b_rearr[6] = _mm256_blend_ps(mat_b_rearr[2], mat_b_rearr[7], 0xCC); mat_b_rearr[7] = _mm256_blend_ps(mat_b_rearr[3], mat_b_rearr[7], 0x33); #endif //Merge rearranged low elements into complete rows mat_b_rearr[0] = _mm256_permute2f128_ps(mat_b_rearr[4], mat_b_rearr[6], 0x20); mat_b_rearr[4] = _mm256_permute2f128_ps(mat_b_rearr[4], mat_b_rearr[6], 0x31); mat_b_rearr[1] = _mm256_permute2f128_ps(mat_b_rearr[5], mat_b_rearr[7], 0x20); mat_b_rearr[5] = _mm256_permute2f128_ps(mat_b_rearr[5], mat_b_rearr[7], 0x31); ////unpackhigh//// mat_b_col[0] = _mm256_unpackhi_ps(mat_b_col[0], mat_b_col[1]); mat_b_col[1] = _mm256_unpackhi_ps(mat_b_col[2], mat_b_col[3]); mat_b_col[2] = _mm256_unpackhi_ps(mat_b_col[4], mat_b_col[5]); mat_b_col[3] = _mm256_unpackhi_ps(mat_b_col[6], mat_b_col[7]); //Rearrange high elements #if REARRANGE_SHFL == 1 mat_b_col[4] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0x44); mat_b_col[5] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0xEE); mat_b_col[6] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0x44); mat_b_col[7] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0xEE); #else mat_b_col[6] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0x4E); mat_b_col[7] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0x4E); mat_b_col[4] = _mm256_blend_ps(mat_b_col[0], mat_b_col[6], 0xCC); mat_b_col[5] = _mm256_blend_ps(mat_b_col[1], mat_b_col[6], 0x33); mat_b_col[6] = _mm256_blend_ps(mat_b_col[2], mat_b_col[7], 0xCC); mat_b_col[7] = _mm256_blend_ps(mat_b_col[3], mat_b_col[7], 0x33); #endif //Merge rearranged high elements into complete rows mat_b_rearr[2] = _mm256_permute2f128_ps(mat_b_col[4], mat_b_col[6], 0x20); mat_b_rearr[6] = _mm256_permute2f128_ps(mat_b_col[4], mat_b_col[6], 0x31); mat_b_rearr[3] = _mm256_permute2f128_ps(mat_b_col[5], mat_b_col[7], 0x20); mat_b_rearr[7] = _mm256_permute2f128_ps(mat_b_col[5], mat_b_col[7], 0x31); /* transpose steps end */ mat_b_rearr[0] = _mm256_mul_ps(mat_b_rearr[0], alphaReg); mat_b_rearr[1] = _mm256_mul_ps(mat_b_rearr[1], alphaReg); mat_b_rearr[2] = _mm256_mul_ps(mat_b_rearr[2], alphaReg); mat_b_rearr[3] = _mm256_mul_ps(mat_b_rearr[3], alphaReg); mat_b_rearr[4] = _mm256_mul_ps(mat_b_rearr[4], alphaReg); mat_b_rearr[5] = _mm256_mul_ps(mat_b_rearr[5], alphaReg); mat_b_rearr[6] = _mm256_mul_ps(mat_b_rearr[6], alphaReg); mat_b_rearr[7] = _mm256_mul_ps(mat_b_rearr[7], alphaReg); #endif //i = 0; ptr_l_dup = ptr_l; i4 = i2; for (l = 0; l < j; l += 8) // move across m { //for (k = 0; k < numCols_b; k += 8) // move across n for the same value of l (index of m) //{ /////////////////// Partial Lower 8x8 block trsm of B //Read current 8 cols of B columns from specified 8x8 current-block of B mat_a_blk_elems[0] = _mm256_loadu_ps((float const *)ptr_b + i4); mat_a_blk_elems[1] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b)); mat_a_blk_elems[2] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b_offset[0])); mat_a_blk_elems[3] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b_offset[1])); mat_a_blk_elems[4] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b_offset[2])); mat_a_blk_elems[5] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b_offset[3])); mat_a_blk_elems[6] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b_offset[4])); mat_a_blk_elems[7] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b_offset[5])); /* transpose steps start */ ////unpacklow//// mat_b_col[0] = _mm256_unpacklo_ps(mat_a_blk_elems[0], mat_a_blk_elems[1]); mat_b_col[1] = _mm256_unpacklo_ps(mat_a_blk_elems[2], mat_a_blk_elems[3]); mat_b_col[2] = _mm256_unpacklo_ps(mat_a_blk_elems[4], mat_a_blk_elems[5]); mat_b_col[3] = _mm256_unpacklo_ps(mat_a_blk_elems[6], mat_a_blk_elems[7]); //Rearrange low elements #if REARRANGE_SHFL == 1 mat_b_col[4] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0x44); mat_b_col[5] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0xEE); mat_b_col[6] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0x44); mat_b_col[7] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0xEE); #else mat_b_col[6] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0x4E); mat_b_col[7] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0x4E); mat_b_col[4] = _mm256_blend_ps(mat_b_col[0], mat_b_col[6], 0xCC); mat_b_col[5] = _mm256_blend_ps(mat_b_col[1], mat_b_col[6], 0x33); mat_b_col[6] = _mm256_blend_ps(mat_b_col[2], mat_b_col[7], 0xCC); mat_b_col[7] = _mm256_blend_ps(mat_b_col[3], mat_b_col[7], 0x33); #endif //Merge rearranged low elements into complete rows mat_b_col[0] = _mm256_permute2f128_ps(mat_b_col[4], mat_b_col[6], 0x20); mat_b_col[4] = _mm256_permute2f128_ps(mat_b_col[4], mat_b_col[6], 0x31); mat_b_col[1] = _mm256_permute2f128_ps(mat_b_col[5], mat_b_col[7], 0x20); mat_b_col[5] = _mm256_permute2f128_ps(mat_b_col[5], mat_b_col[7], 0x31); ////unpackhigh//// mat_a_blk_elems[0] = _mm256_unpackhi_ps(mat_a_blk_elems[0], mat_a_blk_elems[1]); mat_a_blk_elems[1] = _mm256_unpackhi_ps(mat_a_blk_elems[2], mat_a_blk_elems[3]); mat_a_blk_elems[2] = _mm256_unpackhi_ps(mat_a_blk_elems[4], mat_a_blk_elems[5]); mat_a_blk_elems[3] = _mm256_unpackhi_ps(mat_a_blk_elems[6], mat_a_blk_elems[7]); //Rearrange high elements #if REARRANGE_SHFL == 1 mat_a_blk_elems[4] = _mm256_shuffle_ps(mat_a_blk_elems[0], mat_a_blk_elems[1], 0x44); mat_a_blk_elems[5] = _mm256_shuffle_ps(mat_a_blk_elems[0], mat_a_blk_elems[1], 0xEE); mat_a_blk_elems[6] = _mm256_shuffle_ps(mat_a_blk_elems[2], mat_a_blk_elems[3], 0x44); mat_a_blk_elems[7] = _mm256_shuffle_ps(mat_a_blk_elems[2], mat_a_blk_elems[3], 0xEE); #else mat_a_blk_elems[6] = _mm256_shuffle_ps(mat_a_blk_elems[0], mat_a_blk_elems[1], 0x4E); mat_a_blk_elems[7] = _mm256_shuffle_ps(mat_a_blk_elems[2], mat_a_blk_elems[3], 0x4E); mat_a_blk_elems[4] = _mm256_blend_ps(mat_a_blk_elems[0], mat_a_blk_elems[6], 0xCC); mat_a_blk_elems[5] = _mm256_blend_ps(mat_a_blk_elems[1], mat_a_blk_elems[6], 0x33); mat_a_blk_elems[6] = _mm256_blend_ps(mat_a_blk_elems[2], mat_a_blk_elems[7], 0xCC); mat_a_blk_elems[7] = _mm256_blend_ps(mat_a_blk_elems[3], mat_a_blk_elems[7], 0x33); #endif //Merge rearranged high elements into complete rows mat_b_col[2] = _mm256_permute2f128_ps(mat_a_blk_elems[4], mat_a_blk_elems[6], 0x20); mat_b_col[6] = _mm256_permute2f128_ps(mat_a_blk_elems[4], mat_a_blk_elems[6], 0x31); mat_b_col[3] = _mm256_permute2f128_ps(mat_a_blk_elems[5], mat_a_blk_elems[7], 0x20); mat_b_col[7] = _mm256_permute2f128_ps(mat_a_blk_elems[5], mat_a_blk_elems[7], 0x31); /* transpose steps end */ //Broadcast A8,0 to A15,0 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[0])); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[1])); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[2])); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[3])); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[4])); mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[5])); //i4 = k >> 3; ptr_l_dup++; #if GEMM_ACCUM_A //(Row8): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[0] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[0], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[0], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[0], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[0], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[0], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[0], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_col[0], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[7], mat_b_col[0], mat_b_rearr[7]);//d = c - (a*b) #else mat_b_rearr[0] = _mm256_mul_ps(mat_a_blk_elems[0], mat_b_col[0]); mat_b_rearr[1] = _mm256_mul_ps(mat_a_blk_elems[1], mat_b_col[0]); mat_b_rearr[2] = _mm256_mul_ps(mat_a_blk_elems[2], mat_b_col[0]); mat_b_rearr[3] = _mm256_mul_ps(mat_a_blk_elems[3], mat_b_col[0]); mat_b_rearr[4] = _mm256_mul_ps(mat_a_blk_elems[4], mat_b_col[0]); mat_b_rearr[5] = _mm256_mul_ps(mat_a_blk_elems[5], mat_b_col[0]); mat_b_rearr[6] = _mm256_mul_ps(mat_a_blk_elems[6], mat_b_col[0]); mat_b_rearr[7] = _mm256_mul_ps(mat_a_blk_elems[7], mat_b_col[0]); #endif //Broadcast A21 to A71 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[0])); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[1])); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[2])); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[3])); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[4])); mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[5])); ptr_l_dup++; #if GEMM_ACCUM_A //(Row9): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[0] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[1], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[1], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[1], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[1], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[1], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[1], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_col[1], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[7], mat_b_col[1], mat_b_rearr[7]);//d = c - (a*b) #else mat_b_rearr[0] = _mm256_fmadd_ps(mat_a_blk_elems[0], mat_b_col[1], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fmadd_ps(mat_a_blk_elems[1], mat_b_col[1], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fmadd_ps(mat_a_blk_elems[2], mat_b_col[1], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fmadd_ps(mat_a_blk_elems[3], mat_b_col[1], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fmadd_ps(mat_a_blk_elems[4], mat_b_col[1], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fmadd_ps(mat_a_blk_elems[5], mat_b_col[1], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fmadd_ps(mat_a_blk_elems[6], mat_b_col[1], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fmadd_ps(mat_a_blk_elems[7], mat_b_col[1], mat_b_rearr[7]);//d = c - (a*b) #endif //Broadcast A8,2 to A15,2 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[0])); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[1])); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[2])); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[3])); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[4])); mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[5])); ptr_l_dup++; #if GEMM_ACCUM_A //(Row10): FMA operations of b2 with elements of indices from (2, 0) uptill (7, 0) mat_b_rearr[0] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[2], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[2], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[2], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[2], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[2], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[2], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_col[2], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[7], mat_b_col[2], mat_b_rearr[7]);//d = c - (a*b) #else mat_b_rearr[0] = _mm256_fmadd_ps(mat_a_blk_elems[0], mat_b_col[2], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fmadd_ps(mat_a_blk_elems[1], mat_b_col[2], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fmadd_ps(mat_a_blk_elems[2], mat_b_col[2], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fmadd_ps(mat_a_blk_elems[3], mat_b_col[2], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fmadd_ps(mat_a_blk_elems[4], mat_b_col[2], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fmadd_ps(mat_a_blk_elems[5], mat_b_col[2], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fmadd_ps(mat_a_blk_elems[6], mat_b_col[2], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fmadd_ps(mat_a_blk_elems[7], mat_b_col[2], mat_b_rearr[7]);//d = c - (a*b) #endif //Broadcast A8,3 to A15,3 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[0])); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[1])); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[2])); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[3])); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[4])); mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[5])); ptr_l_dup++; #if GEMM_ACCUM_A //(Row11): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[0] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[3], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[3], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[3], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[3], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[3], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[3], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_col[3], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[7], mat_b_col[3], mat_b_rearr[7]);//d = c - (a*b) #else mat_b_rearr[0] = _mm256_fmadd_ps(mat_a_blk_elems[0], mat_b_col[3], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fmadd_ps(mat_a_blk_elems[1], mat_b_col[3], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fmadd_ps(mat_a_blk_elems[2], mat_b_col[3], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fmadd_ps(mat_a_blk_elems[3], mat_b_col[3], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fmadd_ps(mat_a_blk_elems[4], mat_b_col[3], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fmadd_ps(mat_a_blk_elems[5], mat_b_col[3], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fmadd_ps(mat_a_blk_elems[6], mat_b_col[3], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fmadd_ps(mat_a_blk_elems[7], mat_b_col[3], mat_b_rearr[7]);//d = c - (a*b) #endif //Broadcast A8,4 to A15,4 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[0])); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[1])); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[2])); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[3])); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[4])); mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[5])); ptr_l_dup++; #if GEMM_ACCUM_A //(Row12): FMA operations of b2 with elements of indices from (2, 0) uptill (7, 0) mat_b_rearr[0] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[4], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[4], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[4], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[4], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[4], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[4], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_col[4], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[7], mat_b_col[4], mat_b_rearr[7]);//d = c - (a*b) #else mat_b_rearr[0] = _mm256_fmadd_ps(mat_a_blk_elems[0], mat_b_col[4], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fmadd_ps(mat_a_blk_elems[1], mat_b_col[4], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fmadd_ps(mat_a_blk_elems[2], mat_b_col[4], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fmadd_ps(mat_a_blk_elems[3], mat_b_col[4], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fmadd_ps(mat_a_blk_elems[4], mat_b_col[4], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fmadd_ps(mat_a_blk_elems[5], mat_b_col[4], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fmadd_ps(mat_a_blk_elems[6], mat_b_col[4], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fmadd_ps(mat_a_blk_elems[7], mat_b_col[4], mat_b_rearr[7]);//d = c - (a*b) #endif //Broadcast A8,5 to A15,5 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[0])); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[1])); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[2])); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[3])); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[4])); mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[5])); ptr_l_dup++; #if GEMM_ACCUM_A //(Row13): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[0] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[5], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[5], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[5], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[5], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[5], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[5], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_col[5], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[7], mat_b_col[5], mat_b_rearr[7]);//d = c - (a*b) #else mat_b_rearr[0] = _mm256_fmadd_ps(mat_a_blk_elems[0], mat_b_col[5], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fmadd_ps(mat_a_blk_elems[1], mat_b_col[5], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fmadd_ps(mat_a_blk_elems[2], mat_b_col[5], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fmadd_ps(mat_a_blk_elems[3], mat_b_col[5], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fmadd_ps(mat_a_blk_elems[4], mat_b_col[5], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fmadd_ps(mat_a_blk_elems[5], mat_b_col[5], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fmadd_ps(mat_a_blk_elems[6], mat_b_col[5], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fmadd_ps(mat_a_blk_elems[7], mat_b_col[5], mat_b_rearr[7]);//d = c - (a*b) #endif //Broadcast A8,6 to A15,6 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[0])); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[1])); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[2])); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[3])); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[4])); mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[5])); ptr_l_dup++; #if GEMM_ACCUM_A //(Row14): FMA operations of b2 with elements of indices from (2, 0) uptill (7, 0) mat_b_rearr[0] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[6], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[6], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[6], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[6], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[6], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[6], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_col[6], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[7], mat_b_col[6], mat_b_rearr[7]);//d = c - (a*b) #else mat_b_rearr[0] = _mm256_fmadd_ps(mat_a_blk_elems[0], mat_b_col[6], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fmadd_ps(mat_a_blk_elems[1], mat_b_col[6], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fmadd_ps(mat_a_blk_elems[2], mat_b_col[6], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fmadd_ps(mat_a_blk_elems[3], mat_b_col[6], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fmadd_ps(mat_a_blk_elems[4], mat_b_col[6], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fmadd_ps(mat_a_blk_elems[5], mat_b_col[6], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fmadd_ps(mat_a_blk_elems[6], mat_b_col[6], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fmadd_ps(mat_a_blk_elems[7], mat_b_col[6], mat_b_rearr[7]);//d = c - (a*b) #endif //Broadcast A8,7 to A15,7 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[0])); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[1])); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[2])); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[3])); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[4])); mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[5])); ptr_l_dup++; #if GEMM_ACCUM_A //(Row15): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[0] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[7], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[7], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[7], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[7], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[7], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[7], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_col[7], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[7], mat_b_col[7], mat_b_rearr[7]);//d = c - (a*b) #else mat_b_rearr[0] = _mm256_fmadd_ps(mat_a_blk_elems[0], mat_b_col[7], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fmadd_ps(mat_a_blk_elems[1], mat_b_col[7], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fmadd_ps(mat_a_blk_elems[2], mat_b_col[7], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fmadd_ps(mat_a_blk_elems[3], mat_b_col[7], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fmadd_ps(mat_a_blk_elems[4], mat_b_col[7], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fmadd_ps(mat_a_blk_elems[5], mat_b_col[7], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fmadd_ps(mat_a_blk_elems[6], mat_b_col[7], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fmadd_ps(mat_a_blk_elems[7], mat_b_col[7], mat_b_rearr[7]);//d = c - (a*b) #endif //end loop of cols //} //i2 += cs_b_offset[6]; i4 += 8; } //trsm solve k = 0; //for (i2 = 0; i2 < numCols_b; i2 += 8) //{ //i2 = i1 + r; /////////////////// Complete Lower 8x8 block trsm of B :- lower 8x8 block of B with lower right 8x8 block of A #if !GEMM_ACCUM_A //Read 8 cols of B columns of Block-to-be-solved mat_b_rearr[0] = _mm256_loadu_ps((float const *)ptr_b + i); mat_b_rearr[1] = _mm256_loadu_ps((float const *)(ptr_b + cs_b + i)); mat_b_rearr[2] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[0] + i)); mat_b_rearr[3] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[1] + i)); mat_b_rearr[4] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[2] + i)); mat_b_rearr[5] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[3] + i)); mat_b_rearr[6] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[4] + i)); mat_b_rearr[7] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[5] + i)); /* transpose steps start */ ////unpacklow//// mat_b_col[0] = _mm256_unpacklo_ps(mat_b_rearr[0], mat_b_rearr[1]); mat_b_col[1] = _mm256_unpacklo_ps(mat_b_rearr[2], mat_b_rearr[3]); mat_b_col[2] = _mm256_unpacklo_ps(mat_b_rearr[4], mat_b_rearr[5]); mat_b_col[3] = _mm256_unpacklo_ps(mat_b_rearr[6], mat_b_rearr[7]); //Rearrange low elements #if REARRANGE_SHFL == 1 mat_b_col[4] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0x44); mat_b_col[5] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0xEE); mat_b_col[6] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0x44); mat_b_col[7] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0xEE); #else mat_b_col[6] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0x4E); mat_b_col[7] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0x4E); mat_b_col[4] = _mm256_blend_ps(mat_b_col[0], mat_b_col[6], 0xCC); mat_b_col[5] = _mm256_blend_ps(mat_b_col[1], mat_b_col[6], 0x33); mat_b_col[6] = _mm256_blend_ps(mat_b_col[2], mat_b_col[7], 0xCC); mat_b_col[7] = _mm256_blend_ps(mat_b_col[3], mat_b_col[7], 0x33); #endif //Merge rearranged low elements into complete rows mat_b_col[0] = _mm256_permute2f128_ps(mat_b_col[4], mat_b_col[6], 0x20); mat_b_col[4] = _mm256_permute2f128_ps(mat_b_col[4], mat_b_col[6], 0x31); mat_b_col[1] = _mm256_permute2f128_ps(mat_b_col[5], mat_b_col[7], 0x20); mat_b_col[5] = _mm256_permute2f128_ps(mat_b_col[5], mat_b_col[7], 0x31); ////unpackhigh//// mat_b_rearr[0] = _mm256_unpackhi_ps(mat_b_rearr[0], mat_b_rearr[1]); mat_b_rearr[1] = _mm256_unpackhi_ps(mat_b_rearr[2], mat_b_rearr[3]); mat_b_rearr[2] = _mm256_unpackhi_ps(mat_b_rearr[4], mat_b_rearr[5]); mat_b_rearr[3] = _mm256_unpackhi_ps(mat_b_rearr[6], mat_b_rearr[7]); //Rearrange high elements #if REARRANGE_SHFL == 1 mat_b_rearr[4] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0x44); mat_b_rearr[5] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0xEE); mat_b_rearr[6] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0x44); mat_b_rearr[7] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0xEE); #else mat_b_rearr[6] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0x4E); mat_b_rearr[7] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0x4E); mat_b_rearr[4] = _mm256_blend_ps(mat_b_rearr[0], mat_b_rearr[6], 0xCC); mat_b_rearr[5] = _mm256_blend_ps(mat_b_rearr[1], mat_b_rearr[6], 0x33); mat_b_rearr[6] = _mm256_blend_ps(mat_b_rearr[2], mat_b_rearr[7], 0xCC); mat_b_rearr[7] = _mm256_blend_ps(mat_b_rearr[3], mat_b_rearr[7], 0x33); #endif //Merge rearranged high elements into complete rows mat_b_col[2] = _mm256_permute2f128_ps(mat_b_rearr[4], mat_b_rearr[6], 0x20); mat_b_col[6] = _mm256_permute2f128_ps(mat_b_rearr[4], mat_b_rearr[6], 0x31); mat_b_col[3] = _mm256_permute2f128_ps(mat_b_rearr[5], mat_b_rearr[7], 0x20); mat_b_col[7] = _mm256_permute2f128_ps(mat_b_rearr[5], mat_b_rearr[7], 0x31); /* transpose steps end */ mat_b_col[0] = _mm256_mul_ps(mat_b_col[0], alphaReg); mat_b_col[1] = _mm256_mul_ps(mat_b_col[1], alphaReg); mat_b_col[2] = _mm256_mul_ps(mat_b_col[2], alphaReg); mat_b_col[3] = _mm256_mul_ps(mat_b_col[3], alphaReg); mat_b_col[4] = _mm256_mul_ps(mat_b_col[4], alphaReg); mat_b_col[5] = _mm256_mul_ps(mat_b_col[5], alphaReg); mat_b_col[6] = _mm256_mul_ps(mat_b_col[6], alphaReg); mat_b_col[7] = _mm256_mul_ps(mat_b_col[7], alphaReg); #endif //Broadcast A10 to A70 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[0])); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[1])); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[2])); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[3])); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[4])); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[5])); //i += cs_l; #if GEMM_ACCUM_A //(Row0): Perform mul operation of reciprocal of L(0,0) element with 1st row elements of B mat_b_rearr[0] = _mm256_mul_ps(mat_b_rearr[0], mat_a_diag_inv[0]); #else mat_b_rearr[0] = _mm256_sub_ps(mat_b_col[0], mat_b_rearr[0]); mat_b_rearr[0] = _mm256_mul_ps(mat_b_rearr[0], mat_a_diag_inv[0]); #endif #if GEMM_ACCUM_A mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_rearr[0], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_rearr[0], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_rearr[0], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_rearr[0], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_rearr[0], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_rearr[0], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_rearr[0], mat_b_rearr[7]);//d = c - (a*b) #else mat_b_rearr[1] = _mm256_sub_ps(mat_b_col[1], mat_b_rearr[1]); mat_b_rearr[2] = _mm256_sub_ps(mat_b_col[2], mat_b_rearr[2]); mat_b_rearr[3] = _mm256_sub_ps(mat_b_col[3], mat_b_rearr[3]); mat_b_rearr[4] = _mm256_sub_ps(mat_b_col[4], mat_b_rearr[4]); mat_b_rearr[5] = _mm256_sub_ps(mat_b_col[5], mat_b_rearr[5]); mat_b_rearr[6] = _mm256_sub_ps(mat_b_col[6], mat_b_rearr[6]); mat_b_rearr[7] = _mm256_sub_ps(mat_b_col[7], mat_b_rearr[7]); //(Row1): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_rearr[0], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_rearr[0], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_rearr[0], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_rearr[0], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_rearr[0], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_rearr[0], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_rearr[0], mat_b_rearr[7]);//d = c - (a*b) #endif //Broadcast A21 to A71 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 1 + cs_l_offset[0])); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 1 + cs_l_offset[1])); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 1 + cs_l_offset[2])); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 1 + cs_l_offset[3])); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 1 + cs_l_offset[4])); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 1 + cs_l_offset[5])); //i += cs_l; //Perform mul operation of reciprocal of L(1,1) element with 2nd row elements of B mat_b_rearr[1] = _mm256_mul_ps(mat_b_rearr[1], mat_a_diag_inv[1]); //(Row2): FMA operations of b2 with elements of indices from (2, 0) uptill (7, 0) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_rearr[1], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_rearr[1], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_rearr[1], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_rearr[1], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_rearr[1], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_rearr[1], mat_b_rearr[7]);//d = c - (a*b) //Broadcast A32 to A72 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 2 + cs_l_offset[1])); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 2 + cs_l_offset[2])); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 2 + cs_l_offset[3])); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 2 + cs_l_offset[4])); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 2 + cs_l_offset[5])); //i += cs_l; //Perform mul operation of reciprocal of L(2, 2) element with 3rd row elements of B mat_b_rearr[2] = _mm256_mul_ps(mat_b_rearr[2], mat_a_diag_inv[2]); //(Row3): FMA operations of b3 with elements of indices from (3, 0) uptill (7, 0) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_rearr[2], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_rearr[2], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_rearr[2], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_rearr[2], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_rearr[2], mat_b_rearr[7]);//d = c - (a*b) //Broadcast A43 to A73 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 3 + cs_l_offset[2])); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 3 + cs_l_offset[3])); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 3 + cs_l_offset[4])); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 3 + cs_l_offset[5])); //i += cs_l; //Perform mul operation of reciprocal of L(3, 3) element with 4rth row elements of B mat_b_rearr[3] = _mm256_mul_ps(mat_b_rearr[3], mat_a_diag_inv[3]); //(Row4): FMA operations of b4 with elements of indices from (4, 0) uptill (7, 0) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_rearr[3], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_rearr[3], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_rearr[3], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_rearr[3], mat_b_rearr[7]);//d = c - (a*b) //Broadcast A54 to A74 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 4 + cs_l_offset[3])); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 4 + cs_l_offset[4])); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 4 + cs_l_offset[5])); //i += cs_l; //Perform mul operation of reciprocal of L(4, 4) element with 4rth row elements of B mat_b_rearr[4] = _mm256_mul_ps(mat_b_rearr[4], mat_a_diag_inv[4]); //(Row5): FMA operations of b5 with elements of indices from (5, 0) uptill (7, 0) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_rearr[4], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_rearr[4], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_rearr[4], mat_b_rearr[7]);//d = c - (a*b) //Broadcast A65 to A75 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 5 + cs_l_offset[4])); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 5 + cs_l_offset[5])); //i += cs_l; //Perform mul operation of reciprocal of L(5, 5) element with 5th row elements of B mat_b_rearr[5] = _mm256_mul_ps(mat_b_rearr[5], mat_a_diag_inv[5]); //(Row6): FMA operations of b6 with elements of indices from (6, 0) uptill (7, 0) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_rearr[5], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_rearr[5], mat_b_rearr[7]);//d = c - (a*b) //Broadcast A76 to register mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 6 + cs_l_offset[5])); //Perform mul operation of reciprocal of L(6, 6) element with 6th row elements of B mat_b_rearr[6] = _mm256_mul_ps(mat_b_rearr[6], mat_a_diag_inv[6]); //(Row7): FMA operations of b7 with elements of index (7, 0) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_rearr[6], mat_b_rearr[7]);//d = c - (a*b) //Perform mul operation of reciprocal of L(7, 7) element with 7th row elements of B mat_b_rearr[7] = _mm256_mul_ps(mat_b_rearr[7], mat_a_diag_inv[7]); //////////////////////////////////////////////////////////////////////////////// /* transpose steps start */ ////unpacklow//// mat_b_col[0] = _mm256_unpacklo_ps(mat_b_rearr[0], mat_b_rearr[1]); mat_b_col[1] = _mm256_unpacklo_ps(mat_b_rearr[2], mat_b_rearr[3]); mat_b_col[2] = _mm256_unpacklo_ps(mat_b_rearr[4], mat_b_rearr[5]); mat_b_col[3] = _mm256_unpacklo_ps(mat_b_rearr[6], mat_b_rearr[7]); //Rearrange low elements #if REARRANGE_SHFL == 1 mat_b_col[4] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0x44); mat_b_col[5] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0xEE); mat_b_col[6] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0x44); mat_b_col[7] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0xEE); #else mat_b_col[6] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0x4E); mat_b_col[7] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0x4E); mat_b_col[4] = _mm256_blend_ps(mat_b_col[0], mat_b_col[6], 0xCC); mat_b_col[5] = _mm256_blend_ps(mat_b_col[1], mat_b_col[6], 0x33); mat_b_col[6] = _mm256_blend_ps(mat_b_col[2], mat_b_col[7], 0xCC); mat_b_col[7] = _mm256_blend_ps(mat_b_col[3], mat_b_col[7], 0x33); #endif //Merge rearranged low elements into complete rows mat_b_col[0] = _mm256_permute2f128_ps(mat_b_col[4], mat_b_col[6], 0x20); mat_b_col[4] = _mm256_permute2f128_ps(mat_b_col[4], mat_b_col[6], 0x31); mat_b_col[1] = _mm256_permute2f128_ps(mat_b_col[5], mat_b_col[7], 0x20); mat_b_col[5] = _mm256_permute2f128_ps(mat_b_col[5], mat_b_col[7], 0x31); ////unpackhigh//// mat_b_rearr[0] = _mm256_unpackhi_ps(mat_b_rearr[0], mat_b_rearr[1]); mat_b_rearr[1] = _mm256_unpackhi_ps(mat_b_rearr[2], mat_b_rearr[3]); mat_b_rearr[2] = _mm256_unpackhi_ps(mat_b_rearr[4], mat_b_rearr[5]); mat_b_rearr[3] = _mm256_unpackhi_ps(mat_b_rearr[6], mat_b_rearr[7]); //Rearrange high elements #if REARRANGE_SHFL == 1 mat_b_rearr[4] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0x44); mat_b_rearr[5] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0xEE); mat_b_rearr[6] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0x44); mat_b_rearr[7] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0xEE); #else mat_b_rearr[6] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0x4E); mat_b_rearr[7] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0x4E); mat_b_rearr[4] = _mm256_blend_ps(mat_b_rearr[0], mat_b_rearr[6], 0xCC); mat_b_rearr[5] = _mm256_blend_ps(mat_b_rearr[1], mat_b_rearr[6], 0x33); mat_b_rearr[6] = _mm256_blend_ps(mat_b_rearr[2], mat_b_rearr[7], 0xCC); mat_b_rearr[7] = _mm256_blend_ps(mat_b_rearr[3], mat_b_rearr[7], 0x33); #endif //Merge rearranged high elements into complete rows mat_b_col[2] = _mm256_permute2f128_ps(mat_b_rearr[4], mat_b_rearr[6], 0x20); mat_b_col[6] = _mm256_permute2f128_ps(mat_b_rearr[4], mat_b_rearr[6], 0x31); mat_b_col[3] = _mm256_permute2f128_ps(mat_b_rearr[5], mat_b_rearr[7], 0x20); mat_b_col[7] = _mm256_permute2f128_ps(mat_b_rearr[5], mat_b_rearr[7], 0x31); /* transpose steps end */ //Store the computed B columns _mm256_storeu_ps((float *)ptr_b_dup + i2, mat_b_col[0]); _mm256_storeu_ps((float *)(ptr_b_dup + (cs_b)+i2), mat_b_col[1]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[0] + i2), mat_b_col[2]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[1] + i2), mat_b_col[3]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[2] + i2), mat_b_col[4]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[3] + i2), mat_b_col[5]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[4] + i2), mat_b_col[6]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[5] + i2), mat_b_col[7]); //printf("writing B => m[%d], n[%d], [%f]\n", j, k, *(ptr_b_dup + k)); k++; //} i += cs_b_offset[6]; i2 += cs_b_offset[6]; } } //numRows of A ///////////////////loop ends ///////////////////// } static void trsm_AutXB_block_allSmallSizedMatrices_unitDiag(float *ptr_l, float *ptr_b, int numRows_lb, int numCols_b, int rs_l, int rs_b, int cs_l, int cs_b) { //float ones = 1.0; int i, i1, i2, i4, j, k, l, r; int cs_b_offset[7]; int cs_l_offset[7]; float *ptr_b_dup, *ptr_l_dup; //57 number of ymm(256 bits) registers used __m256 mat_b_col[8]; __m256 mat_b_rearr[8]; __m256 mat_a_blk_elems[8]; //__m256 mat_a_diag_inv[8]; //__m256 reciprocal_diags[2]; // ---> considering that the matrix size is multiple of 16 rows and 8 cols <--- // //L matrix offsets cs_l_offset[0] = (cs_l << 1); cs_l_offset[1] = cs_l + cs_l_offset[0]; cs_l_offset[2] = (cs_l << 2); cs_l_offset[3] = cs_l + cs_l_offset[2]; cs_l_offset[4] = cs_l_offset[0] + cs_l_offset[2]; cs_l_offset[5] = cs_l + cs_l_offset[4]; cs_l_offset[6] = (cs_l_offset[5] + cs_l); cs_b_offset[0] = (cs_b << 1); cs_b_offset[1] = cs_b + cs_b_offset[0]; cs_b_offset[2] = (cs_b << 2); cs_b_offset[3] = cs_b + cs_b_offset[2]; cs_b_offset[4] = cs_b_offset[0] + cs_b_offset[2]; cs_b_offset[5] = cs_b + cs_b_offset[4]; cs_b_offset[6] = (cs_b_offset[5] + cs_b); #if 0 //Broadcast A10 to A70 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + 1)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + 2)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l + 3)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l + 4)); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l + 5)); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l + 6)); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l + 7)); //Broadcast A21 to A71 to registers mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 2)); mat_a_blk_elems[8] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 3)); mat_a_blk_elems[9] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 4)); mat_a_blk_elems[10] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 5)); mat_a_blk_elems[11] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 6)); mat_a_blk_elems[12] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 7)); //Broadcast A32 to A72 to registers mat_a_blk_elems[13] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + 3)); mat_a_blk_elems[14] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + 4)); mat_a_blk_elems[15] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + 5)); mat_a_blk_elems[16] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + 6)); mat_a_blk_elems[17] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + 7)); //Broadcast A43 to A73 to registers mat_a_blk_elems[18] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + 4)); mat_a_blk_elems[19] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + 5)); mat_a_blk_elems[20] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + 6)); mat_a_blk_elems[21] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + 7)); //Broadcast A54 to A74 to registers mat_a_blk_elems[22] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[2] + 5)); mat_a_blk_elems[23] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[2] + 6)); mat_a_blk_elems[24] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[2] + 7)); //Broadcast A65 to A75 to registers mat_a_blk_elems[25] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[3] + 6)); mat_a_blk_elems[26] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[3] + 7)); //Broadcast A76 to register mat_a_blk_elems[27] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[4] + 7)); #endif /***************** first set of 8 rows of B processing starts *****************/ ptr_b_dup = ptr_b; i = 0; for (j = 0; j < numCols_b; j += 8) { /////////////////// Complete Upper 8x8 block trsm of B :- upper 8x8 block of B with upper 8x8 block of A //read 8x8 block of B into registers mat_b_rearr[0] = _mm256_loadu_ps((float const *)ptr_b + i); mat_b_rearr[1] = _mm256_loadu_ps((float const *)(ptr_b + cs_b + i)); mat_b_rearr[2] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[0] + i)); mat_b_rearr[3] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[1] + i)); mat_b_rearr[4] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[2] + i)); mat_b_rearr[5] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[3] + i)); mat_b_rearr[6] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[4] + i)); mat_b_rearr[7] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[5] + i)); /* transpose steps start */ ////unpacklow//// mat_b_col[0] = _mm256_unpacklo_ps(mat_b_rearr[0], mat_b_rearr[1]); mat_b_col[1] = _mm256_unpacklo_ps(mat_b_rearr[2], mat_b_rearr[3]); mat_b_col[2] = _mm256_unpacklo_ps(mat_b_rearr[4], mat_b_rearr[5]); mat_b_col[3] = _mm256_unpacklo_ps(mat_b_rearr[6], mat_b_rearr[7]); //Rearrange low elements #if REARRANGE_SHFL == 1 mat_b_col[4] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0x44); mat_b_col[5] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0xEE); mat_b_col[6] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0x44); mat_b_col[7] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0xEE); #else mat_b_col[6] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0x4E); mat_b_col[7] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0x4E); mat_b_col[4] = _mm256_blend_ps(mat_b_col[0], mat_b_col[6], 0xCC); mat_b_col[5] = _mm256_blend_ps(mat_b_col[1], mat_b_col[6], 0x33); mat_b_col[6] = _mm256_blend_ps(mat_b_col[2], mat_b_col[7], 0xCC); mat_b_col[7] = _mm256_blend_ps(mat_b_col[3], mat_b_col[7], 0x33); #endif //Merge rearranged low elements into complete rows mat_b_col[0] = _mm256_permute2f128_ps(mat_b_col[4], mat_b_col[6], 0x20); mat_b_col[4] = _mm256_permute2f128_ps(mat_b_col[4], mat_b_col[6], 0x31); mat_b_col[1] = _mm256_permute2f128_ps(mat_b_col[5], mat_b_col[7], 0x20); mat_b_col[5] = _mm256_permute2f128_ps(mat_b_col[5], mat_b_col[7], 0x31); ////unpackhigh//// mat_b_rearr[0] = _mm256_unpackhi_ps(mat_b_rearr[0], mat_b_rearr[1]); mat_b_rearr[1] = _mm256_unpackhi_ps(mat_b_rearr[2], mat_b_rearr[3]); mat_b_rearr[2] = _mm256_unpackhi_ps(mat_b_rearr[4], mat_b_rearr[5]); mat_b_rearr[3] = _mm256_unpackhi_ps(mat_b_rearr[6], mat_b_rearr[7]); //Rearrange high elements #if REARRANGE_SHFL == 1 mat_b_rearr[4] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0x44); mat_b_rearr[5] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0xEE); mat_b_rearr[6] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0x44); mat_b_rearr[7] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0xEE); #else mat_b_rearr[6] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0x4E); mat_b_rearr[7] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0x4E); mat_b_rearr[4] = _mm256_blend_ps(mat_b_rearr[0], mat_b_rearr[6], 0xCC); mat_b_rearr[5] = _mm256_blend_ps(mat_b_rearr[1], mat_b_rearr[6], 0x33); mat_b_rearr[6] = _mm256_blend_ps(mat_b_rearr[2], mat_b_rearr[7], 0xCC); mat_b_rearr[7] = _mm256_blend_ps(mat_b_rearr[3], mat_b_rearr[7], 0x33); #endif //Merge rearranged high elements into complete rows mat_b_col[2] = _mm256_permute2f128_ps(mat_b_rearr[4], mat_b_rearr[6], 0x20); mat_b_col[6] = _mm256_permute2f128_ps(mat_b_rearr[4], mat_b_rearr[6], 0x31); mat_b_col[3] = _mm256_permute2f128_ps(mat_b_rearr[5], mat_b_rearr[7], 0x20); mat_b_col[7] = _mm256_permute2f128_ps(mat_b_rearr[5], mat_b_rearr[7], 0x31); /* transpose steps end */ //(Row0) mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0])); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1])); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[2])); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[3])); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[4])); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[5])); //(Row1): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_col[1] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[0], mat_b_col[1]);//d = c - (a*b) mat_b_col[2] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[0], mat_b_col[2]);//d = c - (a*b) mat_b_col[3] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[0], mat_b_col[3]);//d = c - (a*b) mat_b_col[4] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[0], mat_b_col[4]);//d = c - (a*b) mat_b_col[5] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[0], mat_b_col[5]);//d = c - (a*b) mat_b_col[6] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[0], mat_b_col[6]);//d = c - (a*b) mat_b_col[7] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_col[0], mat_b_col[7]);//d = c - (a*b) mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + 1 + cs_l_offset[0])); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + 1 + cs_l_offset[1])); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l + 1 + cs_l_offset[2])); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l + 1 + cs_l_offset[3])); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l + 1 + cs_l_offset[4])); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l + 1 + cs_l_offset[5])); //(Row2): FMA operations of b2 with elements of indices from (2, 0) uptill (7, 0) mat_b_col[2] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[1], mat_b_col[2]);//d = c - (a*b) mat_b_col[3] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[1], mat_b_col[3]);//d = c - (a*b) mat_b_col[4] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[1], mat_b_col[4]);//d = c - (a*b) mat_b_col[5] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[1], mat_b_col[5]);//d = c - (a*b) mat_b_col[6] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[1], mat_b_col[6]);//d = c - (a*b) mat_b_col[7] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[1], mat_b_col[7]);//d = c - (a*b) mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + 2 + cs_l_offset[1])); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + 2 + cs_l_offset[2])); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l + 2 + cs_l_offset[3])); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l + 2 + cs_l_offset[4])); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l + 2 + cs_l_offset[5])); //(Row3): FMA operations of b3 with elements of indices from (3, 0) uptill (7, 0) mat_b_col[3] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[2], mat_b_col[3]);//d = c - (a*b) mat_b_col[4] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[2], mat_b_col[4]);//d = c - (a*b) mat_b_col[5] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[2], mat_b_col[5]);//d = c - (a*b) mat_b_col[6] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[2], mat_b_col[6]);//d = c - (a*b) mat_b_col[7] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[2], mat_b_col[7]);//d = c - (a*b) mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + 3 + cs_l_offset[2])); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + 3 + cs_l_offset[3])); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l + 3 + cs_l_offset[4])); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l + 3 + cs_l_offset[5])); //(Row4): FMA operations of b4 with elements of indices from (4, 0) uptill (7, 0) mat_b_col[4] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[3], mat_b_col[4]);//d = c - (a*b) mat_b_col[5] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[3], mat_b_col[5]);//d = c - (a*b) mat_b_col[6] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[3], mat_b_col[6]);//d = c - (a*b) mat_b_col[7] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[3], mat_b_col[7]);//d = c - (a*b) mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + 4 + cs_l_offset[3])); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + 4 + cs_l_offset[4])); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l + 4 + cs_l_offset[5])); //(Row5): FMA operations of b5 with elements of indices from (5, 0) uptill (7, 0) mat_b_col[5] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[4], mat_b_col[5]);//d = c - (a*b) mat_b_col[6] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[4], mat_b_col[6]);//d = c - (a*b) mat_b_col[7] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[4], mat_b_col[7]);//d = c - (a*b) mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + 5 + cs_l_offset[4])); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + 5 + cs_l_offset[5])); //(Row6): FMA operations of b6 with elements of indices from (6, 0) uptill (7, 0) mat_b_col[6] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[5], mat_b_col[6]);//d = c - (a*b) mat_b_col[7] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[5], mat_b_col[7]);//d = c - (a*b) mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + 6 + cs_l_offset[5])); //(Row7): FMA operations of b7 with elements of index (7, 0) mat_b_col[7] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[6], mat_b_col[7]);//d = c - (a*b) //////////////////////////////////////////////////////////////////////////////// /* transpose steps start */ ////unpacklow//// mat_b_rearr[0] = _mm256_unpacklo_ps(mat_b_col[0], mat_b_col[1]); mat_b_rearr[1] = _mm256_unpacklo_ps(mat_b_col[2], mat_b_col[3]); mat_b_rearr[2] = _mm256_unpacklo_ps(mat_b_col[4], mat_b_col[5]); mat_b_rearr[3] = _mm256_unpacklo_ps(mat_b_col[6], mat_b_col[7]); //Rearrange low elements #if REARRANGE_SHFL == 1 mat_b_rearr[4] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0x44); mat_b_rearr[5] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0xEE); mat_b_rearr[6] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0x44); mat_b_rearr[7] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0xEE); #else mat_b_rearr[6] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0x4E); mat_b_rearr[7] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0x4E); mat_b_rearr[4] = _mm256_blend_ps(mat_b_rearr[0], mat_b_rearr[6], 0xCC); mat_b_rearr[5] = _mm256_blend_ps(mat_b_rearr[1], mat_b_rearr[6], 0x33); mat_b_rearr[6] = _mm256_blend_ps(mat_b_rearr[2], mat_b_rearr[7], 0xCC); mat_b_rearr[7] = _mm256_blend_ps(mat_b_rearr[3], mat_b_rearr[7], 0x33); #endif //Merge rearranged low elements into complete rows mat_b_rearr[0] = _mm256_permute2f128_ps(mat_b_rearr[4], mat_b_rearr[6], 0x20); mat_b_rearr[4] = _mm256_permute2f128_ps(mat_b_rearr[4], mat_b_rearr[6], 0x31); mat_b_rearr[1] = _mm256_permute2f128_ps(mat_b_rearr[5], mat_b_rearr[7], 0x20); mat_b_rearr[5] = _mm256_permute2f128_ps(mat_b_rearr[5], mat_b_rearr[7], 0x31); ////unpackhigh//// mat_b_col[0] = _mm256_unpackhi_ps(mat_b_col[0], mat_b_col[1]); mat_b_col[1] = _mm256_unpackhi_ps(mat_b_col[2], mat_b_col[3]); mat_b_col[2] = _mm256_unpackhi_ps(mat_b_col[4], mat_b_col[5]); mat_b_col[3] = _mm256_unpackhi_ps(mat_b_col[6], mat_b_col[7]); //Rearrange high elements #if REARRANGE_SHFL == 1 mat_b_col[4] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0x44); mat_b_col[5] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0xEE); mat_b_col[6] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0x44); mat_b_col[7] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0xEE); #else mat_b_col[6] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0x4E); mat_b_col[7] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0x4E); mat_b_col[4] = _mm256_blend_ps(mat_b_col[0], mat_b_col[6], 0xCC); mat_b_col[5] = _mm256_blend_ps(mat_b_col[1], mat_b_col[6], 0x33); mat_b_col[6] = _mm256_blend_ps(mat_b_col[2], mat_b_col[7], 0xCC); mat_b_col[7] = _mm256_blend_ps(mat_b_col[3], mat_b_col[7], 0x33); #endif //Merge rearranged high elements into complete rows mat_b_rearr[2] = _mm256_permute2f128_ps(mat_b_col[4], mat_b_col[6], 0x20); mat_b_rearr[6] = _mm256_permute2f128_ps(mat_b_col[4], mat_b_col[6], 0x31); mat_b_rearr[3] = _mm256_permute2f128_ps(mat_b_col[5], mat_b_col[7], 0x20); mat_b_rearr[7] = _mm256_permute2f128_ps(mat_b_col[5], mat_b_col[7], 0x31); /* transpose steps end */ //Store the computed B columns _mm256_storeu_ps((float *)ptr_b_dup, mat_b_rearr[0]); _mm256_storeu_ps((float *)(ptr_b_dup + (cs_b)), mat_b_rearr[1]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[0]), mat_b_rearr[2]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[1]), mat_b_rearr[3]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[2]), mat_b_rearr[4]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[3]), mat_b_rearr[5]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[4]), mat_b_rearr[6]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[5]), mat_b_rearr[7]); i += cs_b_offset[6]; ptr_b_dup += cs_b_offset[6]; //i += 8; //ptr_b_dup += 8; } //c = 0; /***************** first set of 8 cols of B processing done *****************/ ptr_b_dup = ptr_b; i1 = 0; //Start loop for cols of B to be processed in size of blk_width for (j = 8; j < numRows_lb; j += 8)//m :- 8x8 block row { ptr_l += cs_l_offset[6]; //ptr_b += j; //ptr_b_dup += 8; ptr_b_dup += 8; i1 += 8; i = i1; i2 = 0; for (r = 0; r < numCols_b; r += GEMM_BLK_V1) { #if GEMM_ACCUM_A //Read 8 cols of B columns of Block-to-be-solved mat_b_col[0] = _mm256_loadu_ps((float const *)ptr_b + i); mat_b_col[1] = _mm256_loadu_ps((float const *)(ptr_b + cs_b + i)); mat_b_col[2] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[0] + i)); mat_b_col[3] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[1] + i)); mat_b_col[4] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[2] + i)); mat_b_col[5] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[3] + i)); mat_b_col[6] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[4] + i)); mat_b_col[7] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[5] + i)); /* transpose steps start */ ////unpacklow//// mat_b_rearr[0] = _mm256_unpacklo_ps(mat_b_col[0], mat_b_col[1]); mat_b_rearr[1] = _mm256_unpacklo_ps(mat_b_col[2], mat_b_col[3]); mat_b_rearr[2] = _mm256_unpacklo_ps(mat_b_col[4], mat_b_col[5]); mat_b_rearr[3] = _mm256_unpacklo_ps(mat_b_col[6], mat_b_col[7]); //Rearrange low elements #if REARRANGE_SHFL == 1 mat_b_rearr[4] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0x44); mat_b_rearr[5] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0xEE); mat_b_rearr[6] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0x44); mat_b_rearr[7] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0xEE); #else mat_b_rearr[6] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0x4E); mat_b_rearr[7] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0x4E); mat_b_rearr[4] = _mm256_blend_ps(mat_b_rearr[0], mat_b_rearr[6], 0xCC); mat_b_rearr[5] = _mm256_blend_ps(mat_b_rearr[1], mat_b_rearr[6], 0x33); mat_b_rearr[6] = _mm256_blend_ps(mat_b_rearr[2], mat_b_rearr[7], 0xCC); mat_b_rearr[7] = _mm256_blend_ps(mat_b_rearr[3], mat_b_rearr[7], 0x33); #endif //Merge rearranged low elements into complete rows mat_b_rearr[0] = _mm256_permute2f128_ps(mat_b_rearr[4], mat_b_rearr[6], 0x20); mat_b_rearr[4] = _mm256_permute2f128_ps(mat_b_rearr[4], mat_b_rearr[6], 0x31); mat_b_rearr[1] = _mm256_permute2f128_ps(mat_b_rearr[5], mat_b_rearr[7], 0x20); mat_b_rearr[5] = _mm256_permute2f128_ps(mat_b_rearr[5], mat_b_rearr[7], 0x31); ////unpackhigh//// mat_b_col[0] = _mm256_unpackhi_ps(mat_b_col[0], mat_b_col[1]); mat_b_col[1] = _mm256_unpackhi_ps(mat_b_col[2], mat_b_col[3]); mat_b_col[2] = _mm256_unpackhi_ps(mat_b_col[4], mat_b_col[5]); mat_b_col[3] = _mm256_unpackhi_ps(mat_b_col[6], mat_b_col[7]); //Rearrange high elements #if REARRANGE_SHFL == 1 mat_b_col[4] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0x44); mat_b_col[5] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0xEE); mat_b_col[6] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0x44); mat_b_col[7] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0xEE); #else mat_b_col[6] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0x4E); mat_b_col[7] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0x4E); mat_b_col[4] = _mm256_blend_ps(mat_b_col[0], mat_b_col[6], 0xCC); mat_b_col[5] = _mm256_blend_ps(mat_b_col[1], mat_b_col[6], 0x33); mat_b_col[6] = _mm256_blend_ps(mat_b_col[2], mat_b_col[7], 0xCC); mat_b_col[7] = _mm256_blend_ps(mat_b_col[3], mat_b_col[7], 0x33); #endif //Merge rearranged high elements into complete rows mat_b_rearr[2] = _mm256_permute2f128_ps(mat_b_col[4], mat_b_col[6], 0x20); mat_b_rearr[6] = _mm256_permute2f128_ps(mat_b_col[4], mat_b_col[6], 0x31); mat_b_rearr[3] = _mm256_permute2f128_ps(mat_b_col[5], mat_b_col[7], 0x20); mat_b_rearr[7] = _mm256_permute2f128_ps(mat_b_col[5], mat_b_col[7], 0x31); /* transpose steps end */ #endif //i = 0; ptr_l_dup = ptr_l; i4 = i2; for (l = 0; l < j; l += 8) // move across m { //for (k = 0; k < numCols_b; k += 8) // move across n for the same value of l (index of m) //{ /////////////////// Partial Lower 8x8 block trsm of B //Read current 8 cols of B columns from specified 8x8 current-block of B mat_a_blk_elems[0] = _mm256_loadu_ps((float const *)ptr_b + i4); mat_a_blk_elems[1] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b)); mat_a_blk_elems[2] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b_offset[0])); mat_a_blk_elems[3] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b_offset[1])); mat_a_blk_elems[4] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b_offset[2])); mat_a_blk_elems[5] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b_offset[3])); mat_a_blk_elems[6] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b_offset[4])); mat_a_blk_elems[7] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b_offset[5])); /* transpose steps start */ ////unpacklow//// mat_b_col[0] = _mm256_unpacklo_ps(mat_a_blk_elems[0], mat_a_blk_elems[1]); mat_b_col[1] = _mm256_unpacklo_ps(mat_a_blk_elems[2], mat_a_blk_elems[3]); mat_b_col[2] = _mm256_unpacklo_ps(mat_a_blk_elems[4], mat_a_blk_elems[5]); mat_b_col[3] = _mm256_unpacklo_ps(mat_a_blk_elems[6], mat_a_blk_elems[7]); //Rearrange low elements #if REARRANGE_SHFL == 1 mat_b_col[4] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0x44); mat_b_col[5] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0xEE); mat_b_col[6] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0x44); mat_b_col[7] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0xEE); #else mat_b_col[6] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0x4E); mat_b_col[7] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0x4E); mat_b_col[4] = _mm256_blend_ps(mat_b_col[0], mat_b_col[6], 0xCC); mat_b_col[5] = _mm256_blend_ps(mat_b_col[1], mat_b_col[6], 0x33); mat_b_col[6] = _mm256_blend_ps(mat_b_col[2], mat_b_col[7], 0xCC); mat_b_col[7] = _mm256_blend_ps(mat_b_col[3], mat_b_col[7], 0x33); #endif //Merge rearranged low elements into complete rows mat_b_col[0] = _mm256_permute2f128_ps(mat_b_col[4], mat_b_col[6], 0x20); mat_b_col[4] = _mm256_permute2f128_ps(mat_b_col[4], mat_b_col[6], 0x31); mat_b_col[1] = _mm256_permute2f128_ps(mat_b_col[5], mat_b_col[7], 0x20); mat_b_col[5] = _mm256_permute2f128_ps(mat_b_col[5], mat_b_col[7], 0x31); ////unpackhigh//// mat_a_blk_elems[0] = _mm256_unpackhi_ps(mat_a_blk_elems[0], mat_a_blk_elems[1]); mat_a_blk_elems[1] = _mm256_unpackhi_ps(mat_a_blk_elems[2], mat_a_blk_elems[3]); mat_a_blk_elems[2] = _mm256_unpackhi_ps(mat_a_blk_elems[4], mat_a_blk_elems[5]); mat_a_blk_elems[3] = _mm256_unpackhi_ps(mat_a_blk_elems[6], mat_a_blk_elems[7]); //Rearrange high elements #if REARRANGE_SHFL == 1 mat_a_blk_elems[4] = _mm256_shuffle_ps(mat_a_blk_elems[0], mat_a_blk_elems[1], 0x44); mat_a_blk_elems[5] = _mm256_shuffle_ps(mat_a_blk_elems[0], mat_a_blk_elems[1], 0xEE); mat_a_blk_elems[6] = _mm256_shuffle_ps(mat_a_blk_elems[2], mat_a_blk_elems[3], 0x44); mat_a_blk_elems[7] = _mm256_shuffle_ps(mat_a_blk_elems[2], mat_a_blk_elems[3], 0xEE); #else mat_a_blk_elems[6] = _mm256_shuffle_ps(mat_a_blk_elems[0], mat_a_blk_elems[1], 0x4E); mat_a_blk_elems[7] = _mm256_shuffle_ps(mat_a_blk_elems[2], mat_a_blk_elems[3], 0x4E); mat_a_blk_elems[4] = _mm256_blend_ps(mat_a_blk_elems[0], mat_a_blk_elems[6], 0xCC); mat_a_blk_elems[5] = _mm256_blend_ps(mat_a_blk_elems[1], mat_a_blk_elems[6], 0x33); mat_a_blk_elems[6] = _mm256_blend_ps(mat_a_blk_elems[2], mat_a_blk_elems[7], 0xCC); mat_a_blk_elems[7] = _mm256_blend_ps(mat_a_blk_elems[3], mat_a_blk_elems[7], 0x33); #endif //Merge rearranged high elements into complete rows mat_b_col[2] = _mm256_permute2f128_ps(mat_a_blk_elems[4], mat_a_blk_elems[6], 0x20); mat_b_col[6] = _mm256_permute2f128_ps(mat_a_blk_elems[4], mat_a_blk_elems[6], 0x31); mat_b_col[3] = _mm256_permute2f128_ps(mat_a_blk_elems[5], mat_a_blk_elems[7], 0x20); mat_b_col[7] = _mm256_permute2f128_ps(mat_a_blk_elems[5], mat_a_blk_elems[7], 0x31); /* transpose steps end */ //Broadcast A8,0 to A15,0 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[0])); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[1])); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[2])); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[3])); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[4])); mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[5])); //i4 = k >> 3; ptr_l_dup++; #if GEMM_ACCUM_A //(Row8): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[0] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[0], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[0], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[0], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[0], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[0], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[0], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_col[0], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[7], mat_b_col[0], mat_b_rearr[7]);//d = c - (a*b) #else mat_b_rearr[0] = _mm256_mul_ps(mat_a_blk_elems[0], mat_b_col[0]); mat_b_rearr[1] = _mm256_mul_ps(mat_a_blk_elems[1], mat_b_col[0]); mat_b_rearr[2] = _mm256_mul_ps(mat_a_blk_elems[2], mat_b_col[0]); mat_b_rearr[3] = _mm256_mul_ps(mat_a_blk_elems[3], mat_b_col[0]); mat_b_rearr[4] = _mm256_mul_ps(mat_a_blk_elems[4], mat_b_col[0]); mat_b_rearr[5] = _mm256_mul_ps(mat_a_blk_elems[5], mat_b_col[0]); mat_b_rearr[6] = _mm256_mul_ps(mat_a_blk_elems[6], mat_b_col[0]); mat_b_rearr[7] = _mm256_mul_ps(mat_a_blk_elems[7], mat_b_col[0]); #endif //Broadcast A21 to A71 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[0])); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[1])); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[2])); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[3])); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[4])); mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[5])); ptr_l_dup++; #if GEMM_ACCUM_A //(Row9): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[0] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[1], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[1], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[1], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[1], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[1], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[1], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_col[1], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[7], mat_b_col[1], mat_b_rearr[7]);//d = c - (a*b) #else mat_b_rearr[0] = _mm256_fmadd_ps(mat_a_blk_elems[0], mat_b_col[1], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fmadd_ps(mat_a_blk_elems[1], mat_b_col[1], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fmadd_ps(mat_a_blk_elems[2], mat_b_col[1], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fmadd_ps(mat_a_blk_elems[3], mat_b_col[1], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fmadd_ps(mat_a_blk_elems[4], mat_b_col[1], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fmadd_ps(mat_a_blk_elems[5], mat_b_col[1], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fmadd_ps(mat_a_blk_elems[6], mat_b_col[1], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fmadd_ps(mat_a_blk_elems[7], mat_b_col[1], mat_b_rearr[7]);//d = c - (a*b) #endif //Broadcast A8,2 to A15,2 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[0])); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[1])); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[2])); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[3])); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[4])); mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[5])); ptr_l_dup++; #if GEMM_ACCUM_A //(Row10): FMA operations of b2 with elements of indices from (2, 0) uptill (7, 0) mat_b_rearr[0] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[2], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[2], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[2], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[2], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[2], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[2], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_col[2], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[7], mat_b_col[2], mat_b_rearr[7]);//d = c - (a*b) #else mat_b_rearr[0] = _mm256_fmadd_ps(mat_a_blk_elems[0], mat_b_col[2], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fmadd_ps(mat_a_blk_elems[1], mat_b_col[2], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fmadd_ps(mat_a_blk_elems[2], mat_b_col[2], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fmadd_ps(mat_a_blk_elems[3], mat_b_col[2], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fmadd_ps(mat_a_blk_elems[4], mat_b_col[2], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fmadd_ps(mat_a_blk_elems[5], mat_b_col[2], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fmadd_ps(mat_a_blk_elems[6], mat_b_col[2], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fmadd_ps(mat_a_blk_elems[7], mat_b_col[2], mat_b_rearr[7]);//d = c - (a*b) #endif //Broadcast A8,3 to A15,3 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[0])); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[1])); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[2])); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[3])); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[4])); mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[5])); ptr_l_dup++; #if GEMM_ACCUM_A //(Row11): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[0] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[3], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[3], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[3], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[3], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[3], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[3], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_col[3], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[7], mat_b_col[3], mat_b_rearr[7]);//d = c - (a*b) #else mat_b_rearr[0] = _mm256_fmadd_ps(mat_a_blk_elems[0], mat_b_col[3], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fmadd_ps(mat_a_blk_elems[1], mat_b_col[3], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fmadd_ps(mat_a_blk_elems[2], mat_b_col[3], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fmadd_ps(mat_a_blk_elems[3], mat_b_col[3], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fmadd_ps(mat_a_blk_elems[4], mat_b_col[3], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fmadd_ps(mat_a_blk_elems[5], mat_b_col[3], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fmadd_ps(mat_a_blk_elems[6], mat_b_col[3], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fmadd_ps(mat_a_blk_elems[7], mat_b_col[3], mat_b_rearr[7]);//d = c - (a*b) #endif //Broadcast A8,4 to A15,4 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[0])); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[1])); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[2])); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[3])); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[4])); mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[5])); ptr_l_dup++; #if GEMM_ACCUM_A //(Row12): FMA operations of b2 with elements of indices from (2, 0) uptill (7, 0) mat_b_rearr[0] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[4], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[4], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[4], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[4], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[4], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[4], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_col[4], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[7], mat_b_col[4], mat_b_rearr[7]);//d = c - (a*b) #else mat_b_rearr[0] = _mm256_fmadd_ps(mat_a_blk_elems[0], mat_b_col[4], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fmadd_ps(mat_a_blk_elems[1], mat_b_col[4], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fmadd_ps(mat_a_blk_elems[2], mat_b_col[4], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fmadd_ps(mat_a_blk_elems[3], mat_b_col[4], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fmadd_ps(mat_a_blk_elems[4], mat_b_col[4], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fmadd_ps(mat_a_blk_elems[5], mat_b_col[4], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fmadd_ps(mat_a_blk_elems[6], mat_b_col[4], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fmadd_ps(mat_a_blk_elems[7], mat_b_col[4], mat_b_rearr[7]);//d = c - (a*b) #endif //Broadcast A8,5 to A15,5 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[0])); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[1])); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[2])); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[3])); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[4])); mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[5])); ptr_l_dup++; #if GEMM_ACCUM_A //(Row13): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[0] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[5], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[5], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[5], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[5], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[5], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[5], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_col[5], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[7], mat_b_col[5], mat_b_rearr[7]);//d = c - (a*b) #else mat_b_rearr[0] = _mm256_fmadd_ps(mat_a_blk_elems[0], mat_b_col[5], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fmadd_ps(mat_a_blk_elems[1], mat_b_col[5], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fmadd_ps(mat_a_blk_elems[2], mat_b_col[5], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fmadd_ps(mat_a_blk_elems[3], mat_b_col[5], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fmadd_ps(mat_a_blk_elems[4], mat_b_col[5], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fmadd_ps(mat_a_blk_elems[5], mat_b_col[5], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fmadd_ps(mat_a_blk_elems[6], mat_b_col[5], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fmadd_ps(mat_a_blk_elems[7], mat_b_col[5], mat_b_rearr[7]);//d = c - (a*b) #endif //Broadcast A8,6 to A15,6 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[0])); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[1])); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[2])); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[3])); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[4])); mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[5])); ptr_l_dup++; #if GEMM_ACCUM_A //(Row14): FMA operations of b2 with elements of indices from (2, 0) uptill (7, 0) mat_b_rearr[0] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[6], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[6], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[6], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[6], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[6], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[6], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_col[6], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[7], mat_b_col[6], mat_b_rearr[7]);//d = c - (a*b) #else mat_b_rearr[0] = _mm256_fmadd_ps(mat_a_blk_elems[0], mat_b_col[6], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fmadd_ps(mat_a_blk_elems[1], mat_b_col[6], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fmadd_ps(mat_a_blk_elems[2], mat_b_col[6], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fmadd_ps(mat_a_blk_elems[3], mat_b_col[6], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fmadd_ps(mat_a_blk_elems[4], mat_b_col[6], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fmadd_ps(mat_a_blk_elems[5], mat_b_col[6], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fmadd_ps(mat_a_blk_elems[6], mat_b_col[6], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fmadd_ps(mat_a_blk_elems[7], mat_b_col[6], mat_b_rearr[7]);//d = c - (a*b) #endif //Broadcast A8,7 to A15,7 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[0])); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[1])); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[2])); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[3])); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[4])); mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[5])); ptr_l_dup++; #if GEMM_ACCUM_A //(Row15): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[0] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[7], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[7], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[7], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[7], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[7], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[7], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_col[7], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[7], mat_b_col[7], mat_b_rearr[7]);//d = c - (a*b) #else mat_b_rearr[0] = _mm256_fmadd_ps(mat_a_blk_elems[0], mat_b_col[7], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fmadd_ps(mat_a_blk_elems[1], mat_b_col[7], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fmadd_ps(mat_a_blk_elems[2], mat_b_col[7], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fmadd_ps(mat_a_blk_elems[3], mat_b_col[7], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fmadd_ps(mat_a_blk_elems[4], mat_b_col[7], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fmadd_ps(mat_a_blk_elems[5], mat_b_col[7], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fmadd_ps(mat_a_blk_elems[6], mat_b_col[7], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fmadd_ps(mat_a_blk_elems[7], mat_b_col[7], mat_b_rearr[7]);//d = c - (a*b) #endif //end loop of cols //} //i2 += cs_b_offset[6]; i4 += 8; } //trsm solve k = 0; //for (i2 = 0; i2 < numCols_b; i2 += 8) //{ //i2 = i1 + r; /////////////////// Complete Lower 8x8 block trsm of B :- lower 8x8 block of B with lower right 8x8 block of A #if !GEMM_ACCUM_A //Read 8 cols of B columns of Block-to-be-solved mat_b_rearr[0] = _mm256_loadu_ps((float const *)ptr_b + i); mat_b_rearr[1] = _mm256_loadu_ps((float const *)(ptr_b + cs_b + i)); mat_b_rearr[2] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[0] + i)); mat_b_rearr[3] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[1] + i)); mat_b_rearr[4] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[2] + i)); mat_b_rearr[5] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[3] + i)); mat_b_rearr[6] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[4] + i)); mat_b_rearr[7] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[5] + i)); /* transpose steps start */ ////unpacklow//// mat_b_col[0] = _mm256_unpacklo_ps(mat_b_rearr[0], mat_b_rearr[1]); mat_b_col[1] = _mm256_unpacklo_ps(mat_b_rearr[2], mat_b_rearr[3]); mat_b_col[2] = _mm256_unpacklo_ps(mat_b_rearr[4], mat_b_rearr[5]); mat_b_col[3] = _mm256_unpacklo_ps(mat_b_rearr[6], mat_b_rearr[7]); //Rearrange low elements #if REARRANGE_SHFL == 1 mat_b_col[4] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0x44); mat_b_col[5] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0xEE); mat_b_col[6] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0x44); mat_b_col[7] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0xEE); #else mat_b_col[6] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0x4E); mat_b_col[7] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0x4E); mat_b_col[4] = _mm256_blend_ps(mat_b_col[0], mat_b_col[6], 0xCC); mat_b_col[5] = _mm256_blend_ps(mat_b_col[1], mat_b_col[6], 0x33); mat_b_col[6] = _mm256_blend_ps(mat_b_col[2], mat_b_col[7], 0xCC); mat_b_col[7] = _mm256_blend_ps(mat_b_col[3], mat_b_col[7], 0x33); #endif //Merge rearranged low elements into complete rows mat_b_col[0] = _mm256_permute2f128_ps(mat_b_col[4], mat_b_col[6], 0x20); mat_b_col[4] = _mm256_permute2f128_ps(mat_b_col[4], mat_b_col[6], 0x31); mat_b_col[1] = _mm256_permute2f128_ps(mat_b_col[5], mat_b_col[7], 0x20); mat_b_col[5] = _mm256_permute2f128_ps(mat_b_col[5], mat_b_col[7], 0x31); ////unpackhigh//// mat_b_rearr[0] = _mm256_unpackhi_ps(mat_b_rearr[0], mat_b_rearr[1]); mat_b_rearr[1] = _mm256_unpackhi_ps(mat_b_rearr[2], mat_b_rearr[3]); mat_b_rearr[2] = _mm256_unpackhi_ps(mat_b_rearr[4], mat_b_rearr[5]); mat_b_rearr[3] = _mm256_unpackhi_ps(mat_b_rearr[6], mat_b_rearr[7]); //Rearrange high elements #if REARRANGE_SHFL == 1 mat_b_rearr[4] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0x44); mat_b_rearr[5] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0xEE); mat_b_rearr[6] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0x44); mat_b_rearr[7] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0xEE); #else mat_b_rearr[6] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0x4E); mat_b_rearr[7] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0x4E); mat_b_rearr[4] = _mm256_blend_ps(mat_b_rearr[0], mat_b_rearr[6], 0xCC); mat_b_rearr[5] = _mm256_blend_ps(mat_b_rearr[1], mat_b_rearr[6], 0x33); mat_b_rearr[6] = _mm256_blend_ps(mat_b_rearr[2], mat_b_rearr[7], 0xCC); mat_b_rearr[7] = _mm256_blend_ps(mat_b_rearr[3], mat_b_rearr[7], 0x33); #endif //Merge rearranged high elements into complete rows mat_b_col[2] = _mm256_permute2f128_ps(mat_b_rearr[4], mat_b_rearr[6], 0x20); mat_b_col[6] = _mm256_permute2f128_ps(mat_b_rearr[4], mat_b_rearr[6], 0x31); mat_b_col[3] = _mm256_permute2f128_ps(mat_b_rearr[5], mat_b_rearr[7], 0x20); mat_b_col[7] = _mm256_permute2f128_ps(mat_b_rearr[5], mat_b_rearr[7], 0x31); /* transpose steps end */ #endif //Broadcast A10 to A70 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[0])); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[1])); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[2])); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[3])); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[4])); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[5])); //i += cs_l; #if GEMM_ACCUM_A //(Row0): already done #else mat_b_rearr[0] = _mm256_sub_ps(mat_b_col[0], mat_b_rearr[0]); #endif #if GEMM_ACCUM_A mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_rearr[0], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_rearr[0], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_rearr[0], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_rearr[0], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_rearr[0], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_rearr[0], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_rearr[0], mat_b_rearr[7]);//d = c - (a*b) #else mat_b_rearr[1] = _mm256_sub_ps(mat_b_col[1], mat_b_rearr[1]); mat_b_rearr[2] = _mm256_sub_ps(mat_b_col[2], mat_b_rearr[2]); mat_b_rearr[3] = _mm256_sub_ps(mat_b_col[3], mat_b_rearr[3]); mat_b_rearr[4] = _mm256_sub_ps(mat_b_col[4], mat_b_rearr[4]); mat_b_rearr[5] = _mm256_sub_ps(mat_b_col[5], mat_b_rearr[5]); mat_b_rearr[6] = _mm256_sub_ps(mat_b_col[6], mat_b_rearr[6]); mat_b_rearr[7] = _mm256_sub_ps(mat_b_col[7], mat_b_rearr[7]); //(Row1): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_rearr[0], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_rearr[0], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_rearr[0], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_rearr[0], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_rearr[0], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_rearr[0], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_rearr[0], mat_b_rearr[7]);//d = c - (a*b) #endif //Broadcast A21 to A71 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 1 + cs_l_offset[0])); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 1 + cs_l_offset[1])); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 1 + cs_l_offset[2])); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 1 + cs_l_offset[3])); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 1 + cs_l_offset[4])); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 1 + cs_l_offset[5])); //i += cs_l; //(Row2): FMA operations of b2 with elements of indices from (2, 0) uptill (7, 0) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_rearr[1], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_rearr[1], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_rearr[1], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_rearr[1], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_rearr[1], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_rearr[1], mat_b_rearr[7]);//d = c - (a*b) //Broadcast A32 to A72 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 2 + cs_l_offset[1])); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 2 + cs_l_offset[2])); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 2 + cs_l_offset[3])); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 2 + cs_l_offset[4])); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 2 + cs_l_offset[5])); //i += cs_l; //(Row3): FMA operations of b3 with elements of indices from (3, 0) uptill (7, 0) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_rearr[2], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_rearr[2], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_rearr[2], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_rearr[2], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_rearr[2], mat_b_rearr[7]);//d = c - (a*b) //Broadcast A43 to A73 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 3 + cs_l_offset[2])); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 3 + cs_l_offset[3])); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 3 + cs_l_offset[4])); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 3 + cs_l_offset[5])); //i += cs_l; //(Row4): FMA operations of b4 with elements of indices from (4, 0) uptill (7, 0) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_rearr[3], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_rearr[3], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_rearr[3], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_rearr[3], mat_b_rearr[7]);//d = c - (a*b) //Broadcast A54 to A74 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 4 + cs_l_offset[3])); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 4 + cs_l_offset[4])); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 4 + cs_l_offset[5])); //i += cs_l; //(Row5): FMA operations of b5 with elements of indices from (5, 0) uptill (7, 0) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_rearr[4], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_rearr[4], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_rearr[4], mat_b_rearr[7]);//d = c - (a*b) //Broadcast A65 to A75 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 5 + cs_l_offset[4])); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 5 + cs_l_offset[5])); //i += cs_l; //(Row6): FMA operations of b6 with elements of indices from (6, 0) uptill (7, 0) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_rearr[5], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_rearr[5], mat_b_rearr[7]);//d = c - (a*b) //Broadcast A76 to register mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 6 + cs_l_offset[5])); //(Row7): FMA operations of b7 with elements of index (7, 0) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_rearr[6], mat_b_rearr[7]);//d = c - (a*b) //////////////////////////////////////////////////////////////////////////////// /* transpose steps start */ ////unpacklow//// mat_b_col[0] = _mm256_unpacklo_ps(mat_b_rearr[0], mat_b_rearr[1]); mat_b_col[1] = _mm256_unpacklo_ps(mat_b_rearr[2], mat_b_rearr[3]); mat_b_col[2] = _mm256_unpacklo_ps(mat_b_rearr[4], mat_b_rearr[5]); mat_b_col[3] = _mm256_unpacklo_ps(mat_b_rearr[6], mat_b_rearr[7]); //Rearrange low elements #if REARRANGE_SHFL == 1 mat_b_col[4] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0x44); mat_b_col[5] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0xEE); mat_b_col[6] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0x44); mat_b_col[7] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0xEE); #else mat_b_col[6] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0x4E); mat_b_col[7] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0x4E); mat_b_col[4] = _mm256_blend_ps(mat_b_col[0], mat_b_col[6], 0xCC); mat_b_col[5] = _mm256_blend_ps(mat_b_col[1], mat_b_col[6], 0x33); mat_b_col[6] = _mm256_blend_ps(mat_b_col[2], mat_b_col[7], 0xCC); mat_b_col[7] = _mm256_blend_ps(mat_b_col[3], mat_b_col[7], 0x33); #endif //Merge rearranged low elements into complete rows mat_b_col[0] = _mm256_permute2f128_ps(mat_b_col[4], mat_b_col[6], 0x20); mat_b_col[4] = _mm256_permute2f128_ps(mat_b_col[4], mat_b_col[6], 0x31); mat_b_col[1] = _mm256_permute2f128_ps(mat_b_col[5], mat_b_col[7], 0x20); mat_b_col[5] = _mm256_permute2f128_ps(mat_b_col[5], mat_b_col[7], 0x31); ////unpackhigh//// mat_b_rearr[0] = _mm256_unpackhi_ps(mat_b_rearr[0], mat_b_rearr[1]); mat_b_rearr[1] = _mm256_unpackhi_ps(mat_b_rearr[2], mat_b_rearr[3]); mat_b_rearr[2] = _mm256_unpackhi_ps(mat_b_rearr[4], mat_b_rearr[5]); mat_b_rearr[3] = _mm256_unpackhi_ps(mat_b_rearr[6], mat_b_rearr[7]); //Rearrange high elements #if REARRANGE_SHFL == 1 mat_b_rearr[4] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0x44); mat_b_rearr[5] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0xEE); mat_b_rearr[6] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0x44); mat_b_rearr[7] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0xEE); #else mat_b_rearr[6] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0x4E); mat_b_rearr[7] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0x4E); mat_b_rearr[4] = _mm256_blend_ps(mat_b_rearr[0], mat_b_rearr[6], 0xCC); mat_b_rearr[5] = _mm256_blend_ps(mat_b_rearr[1], mat_b_rearr[6], 0x33); mat_b_rearr[6] = _mm256_blend_ps(mat_b_rearr[2], mat_b_rearr[7], 0xCC); mat_b_rearr[7] = _mm256_blend_ps(mat_b_rearr[3], mat_b_rearr[7], 0x33); #endif //Merge rearranged high elements into complete rows mat_b_col[2] = _mm256_permute2f128_ps(mat_b_rearr[4], mat_b_rearr[6], 0x20); mat_b_col[6] = _mm256_permute2f128_ps(mat_b_rearr[4], mat_b_rearr[6], 0x31); mat_b_col[3] = _mm256_permute2f128_ps(mat_b_rearr[5], mat_b_rearr[7], 0x20); mat_b_col[7] = _mm256_permute2f128_ps(mat_b_rearr[5], mat_b_rearr[7], 0x31); /* transpose steps end */ //Store the computed B columns _mm256_storeu_ps((float *)ptr_b_dup + i2, mat_b_col[0]); _mm256_storeu_ps((float *)(ptr_b_dup + (cs_b)+i2), mat_b_col[1]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[0] + i2), mat_b_col[2]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[1] + i2), mat_b_col[3]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[2] + i2), mat_b_col[4]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[3] + i2), mat_b_col[5]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[4] + i2), mat_b_col[6]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[5] + i2), mat_b_col[7]); //printf("writing B => m[%d], n[%d], [%f]\n", j, k, *(ptr_b_dup + k)); k++; //} i += cs_b_offset[6]; i2 += cs_b_offset[6]; } } //numRows of A ///////////////////loop ends ///////////////////// } static void trsm_AutXB_block_allSmallSizedMatrices_alpha_unitDiag(float *ptr_l, float *ptr_b, int numRows_lb, int numCols_b, int rs_l, int rs_b, int cs_l, int cs_b, float alpha) { //float ones = 1.0; int i, i1, i2, i4, j, k, l, r; int cs_b_offset[7]; int cs_l_offset[7]; float *ptr_b_dup, *ptr_l_dup; //57 number of ymm(256 bits) registers used __m256 mat_b_col[8]; __m256 mat_b_rearr[8]; __m256 mat_a_blk_elems[8]; //__m256 mat_a_diag_inv[8]; //__m256 reciprocal_diags[2]; __m256 alphaReg; alphaReg = _mm256_broadcast_ss((float const *)&alpha); // ---> considering that the matrix size is multiple of 16 rows and 8 cols <--- // //L matrix offsets cs_l_offset[0] = (cs_l << 1); cs_l_offset[1] = cs_l + cs_l_offset[0]; cs_l_offset[2] = (cs_l << 2); cs_l_offset[3] = cs_l + cs_l_offset[2]; cs_l_offset[4] = cs_l_offset[0] + cs_l_offset[2]; cs_l_offset[5] = cs_l + cs_l_offset[4]; cs_l_offset[6] = (cs_l_offset[5] + cs_l); cs_b_offset[0] = (cs_b << 1); cs_b_offset[1] = cs_b + cs_b_offset[0]; cs_b_offset[2] = (cs_b << 2); cs_b_offset[3] = cs_b + cs_b_offset[2]; cs_b_offset[4] = cs_b_offset[0] + cs_b_offset[2]; cs_b_offset[5] = cs_b + cs_b_offset[4]; cs_b_offset[6] = (cs_b_offset[5] + cs_b); #if 0 //Broadcast A10 to A70 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + 1)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + 2)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l + 3)); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l + 4)); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l + 5)); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l + 6)); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l + 7)); //Broadcast A21 to A71 to registers mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 2)); mat_a_blk_elems[8] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 3)); mat_a_blk_elems[9] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 4)); mat_a_blk_elems[10] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 5)); mat_a_blk_elems[11] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 6)); mat_a_blk_elems[12] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l + 7)); //Broadcast A32 to A72 to registers mat_a_blk_elems[13] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + 3)); mat_a_blk_elems[14] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + 4)); mat_a_blk_elems[15] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + 5)); mat_a_blk_elems[16] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + 6)); mat_a_blk_elems[17] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0] + 7)); //Broadcast A43 to A73 to registers mat_a_blk_elems[18] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + 4)); mat_a_blk_elems[19] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + 5)); mat_a_blk_elems[20] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + 6)); mat_a_blk_elems[21] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1] + 7)); //Broadcast A54 to A74 to registers mat_a_blk_elems[22] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[2] + 5)); mat_a_blk_elems[23] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[2] + 6)); mat_a_blk_elems[24] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[2] + 7)); //Broadcast A65 to A75 to registers mat_a_blk_elems[25] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[3] + 6)); mat_a_blk_elems[26] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[3] + 7)); //Broadcast A76 to register mat_a_blk_elems[27] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[4] + 7)); #endif /***************** first set of 8 rows of B processing starts *****************/ ptr_b_dup = ptr_b; i = 0; for (j = 0; j < numCols_b; j += 8) { /////////////////// Complete Upper 8x8 block trsm of B :- upper 8x8 block of B with upper 8x8 block of A //read 8x8 block of B into registers mat_b_rearr[0] = _mm256_loadu_ps((float const *)ptr_b + i); mat_b_rearr[1] = _mm256_loadu_ps((float const *)(ptr_b + cs_b + i)); mat_b_rearr[2] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[0] + i)); mat_b_rearr[3] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[1] + i)); mat_b_rearr[4] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[2] + i)); mat_b_rearr[5] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[3] + i)); mat_b_rearr[6] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[4] + i)); mat_b_rearr[7] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[5] + i)); /* transpose steps start */ ////unpacklow//// mat_b_col[0] = _mm256_unpacklo_ps(mat_b_rearr[0], mat_b_rearr[1]); mat_b_col[1] = _mm256_unpacklo_ps(mat_b_rearr[2], mat_b_rearr[3]); mat_b_col[2] = _mm256_unpacklo_ps(mat_b_rearr[4], mat_b_rearr[5]); mat_b_col[3] = _mm256_unpacklo_ps(mat_b_rearr[6], mat_b_rearr[7]); //Rearrange low elements #if REARRANGE_SHFL == 1 mat_b_col[4] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0x44); mat_b_col[5] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0xEE); mat_b_col[6] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0x44); mat_b_col[7] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0xEE); #else mat_b_col[6] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0x4E); mat_b_col[7] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0x4E); mat_b_col[4] = _mm256_blend_ps(mat_b_col[0], mat_b_col[6], 0xCC); mat_b_col[5] = _mm256_blend_ps(mat_b_col[1], mat_b_col[6], 0x33); mat_b_col[6] = _mm256_blend_ps(mat_b_col[2], mat_b_col[7], 0xCC); mat_b_col[7] = _mm256_blend_ps(mat_b_col[3], mat_b_col[7], 0x33); #endif //Merge rearranged low elements into complete rows mat_b_col[0] = _mm256_permute2f128_ps(mat_b_col[4], mat_b_col[6], 0x20); mat_b_col[4] = _mm256_permute2f128_ps(mat_b_col[4], mat_b_col[6], 0x31); mat_b_col[1] = _mm256_permute2f128_ps(mat_b_col[5], mat_b_col[7], 0x20); mat_b_col[5] = _mm256_permute2f128_ps(mat_b_col[5], mat_b_col[7], 0x31); ////unpackhigh//// mat_b_rearr[0] = _mm256_unpackhi_ps(mat_b_rearr[0], mat_b_rearr[1]); mat_b_rearr[1] = _mm256_unpackhi_ps(mat_b_rearr[2], mat_b_rearr[3]); mat_b_rearr[2] = _mm256_unpackhi_ps(mat_b_rearr[4], mat_b_rearr[5]); mat_b_rearr[3] = _mm256_unpackhi_ps(mat_b_rearr[6], mat_b_rearr[7]); //Rearrange high elements #if REARRANGE_SHFL == 1 mat_b_rearr[4] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0x44); mat_b_rearr[5] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0xEE); mat_b_rearr[6] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0x44); mat_b_rearr[7] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0xEE); #else mat_b_rearr[6] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0x4E); mat_b_rearr[7] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0x4E); mat_b_rearr[4] = _mm256_blend_ps(mat_b_rearr[0], mat_b_rearr[6], 0xCC); mat_b_rearr[5] = _mm256_blend_ps(mat_b_rearr[1], mat_b_rearr[6], 0x33); mat_b_rearr[6] = _mm256_blend_ps(mat_b_rearr[2], mat_b_rearr[7], 0xCC); mat_b_rearr[7] = _mm256_blend_ps(mat_b_rearr[3], mat_b_rearr[7], 0x33); #endif //Merge rearranged high elements into complete rows mat_b_col[2] = _mm256_permute2f128_ps(mat_b_rearr[4], mat_b_rearr[6], 0x20); mat_b_col[6] = _mm256_permute2f128_ps(mat_b_rearr[4], mat_b_rearr[6], 0x31); mat_b_col[3] = _mm256_permute2f128_ps(mat_b_rearr[5], mat_b_rearr[7], 0x20); mat_b_col[7] = _mm256_permute2f128_ps(mat_b_rearr[5], mat_b_rearr[7], 0x31); /* transpose steps end */ mat_b_col[0] = _mm256_mul_ps(mat_b_col[0], alphaReg); mat_b_col[1] = _mm256_mul_ps(mat_b_col[1], alphaReg); mat_b_col[2] = _mm256_mul_ps(mat_b_col[2], alphaReg); mat_b_col[3] = _mm256_mul_ps(mat_b_col[3], alphaReg); mat_b_col[4] = _mm256_mul_ps(mat_b_col[4], alphaReg); mat_b_col[5] = _mm256_mul_ps(mat_b_col[5], alphaReg); mat_b_col[6] = _mm256_mul_ps(mat_b_col[6], alphaReg); mat_b_col[7] = _mm256_mul_ps(mat_b_col[7], alphaReg); //(Row0) mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[0])); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[1])); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[2])); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[3])); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[4])); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l + cs_l_offset[5])); //(Row1): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_col[1] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[0], mat_b_col[1]);//d = c - (a*b) mat_b_col[2] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[0], mat_b_col[2]);//d = c - (a*b) mat_b_col[3] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[0], mat_b_col[3]);//d = c - (a*b) mat_b_col[4] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[0], mat_b_col[4]);//d = c - (a*b) mat_b_col[5] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[0], mat_b_col[5]);//d = c - (a*b) mat_b_col[6] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[0], mat_b_col[6]);//d = c - (a*b) mat_b_col[7] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_col[0], mat_b_col[7]);//d = c - (a*b) mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + 1 + cs_l_offset[0])); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + 1 + cs_l_offset[1])); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l + 1 + cs_l_offset[2])); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l + 1 + cs_l_offset[3])); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l + 1 + cs_l_offset[4])); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l + 1 + cs_l_offset[5])); //(Row2): FMA operations of b2 with elements of indices from (2, 0) uptill (7, 0) mat_b_col[2] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[1], mat_b_col[2]);//d = c - (a*b) mat_b_col[3] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[1], mat_b_col[3]);//d = c - (a*b) mat_b_col[4] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[1], mat_b_col[4]);//d = c - (a*b) mat_b_col[5] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[1], mat_b_col[5]);//d = c - (a*b) mat_b_col[6] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[1], mat_b_col[6]);//d = c - (a*b) mat_b_col[7] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[1], mat_b_col[7]);//d = c - (a*b) mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + 2 + cs_l_offset[1])); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + 2 + cs_l_offset[2])); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l + 2 + cs_l_offset[3])); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l + 2 + cs_l_offset[4])); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l + 2 + cs_l_offset[5])); //(Row3): FMA operations of b3 with elements of indices from (3, 0) uptill (7, 0) mat_b_col[3] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[2], mat_b_col[3]);//d = c - (a*b) mat_b_col[4] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[2], mat_b_col[4]);//d = c - (a*b) mat_b_col[5] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[2], mat_b_col[5]);//d = c - (a*b) mat_b_col[6] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[2], mat_b_col[6]);//d = c - (a*b) mat_b_col[7] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[2], mat_b_col[7]);//d = c - (a*b) mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + 3 + cs_l_offset[2])); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + 3 + cs_l_offset[3])); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l + 3 + cs_l_offset[4])); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l + 3 + cs_l_offset[5])); //(Row4): FMA operations of b4 with elements of indices from (4, 0) uptill (7, 0) mat_b_col[4] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[3], mat_b_col[4]);//d = c - (a*b) mat_b_col[5] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[3], mat_b_col[5]);//d = c - (a*b) mat_b_col[6] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[3], mat_b_col[6]);//d = c - (a*b) mat_b_col[7] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[3], mat_b_col[7]);//d = c - (a*b) mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + 4 + cs_l_offset[3])); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + 4 + cs_l_offset[4])); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l + 4 + cs_l_offset[5])); //(Row5): FMA operations of b5 with elements of indices from (5, 0) uptill (7, 0) mat_b_col[5] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[4], mat_b_col[5]);//d = c - (a*b) mat_b_col[6] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[4], mat_b_col[6]);//d = c - (a*b) mat_b_col[7] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[4], mat_b_col[7]);//d = c - (a*b) mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + 5 + cs_l_offset[4])); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l + 5 + cs_l_offset[5])); //(Row6): FMA operations of b6 with elements of indices from (6, 0) uptill (7, 0) mat_b_col[6] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[5], mat_b_col[6]);//d = c - (a*b) mat_b_col[7] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[5], mat_b_col[7]);//d = c - (a*b) mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l + 6 + cs_l_offset[5])); //(Row7): FMA operations of b7 with elements of index (7, 0) mat_b_col[7] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[6], mat_b_col[7]);//d = c - (a*b) //////////////////////////////////////////////////////////////////////////////// /* transpose steps start */ ////unpacklow//// mat_b_rearr[0] = _mm256_unpacklo_ps(mat_b_col[0], mat_b_col[1]); mat_b_rearr[1] = _mm256_unpacklo_ps(mat_b_col[2], mat_b_col[3]); mat_b_rearr[2] = _mm256_unpacklo_ps(mat_b_col[4], mat_b_col[5]); mat_b_rearr[3] = _mm256_unpacklo_ps(mat_b_col[6], mat_b_col[7]); //Rearrange low elements #if REARRANGE_SHFL == 1 mat_b_rearr[4] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0x44); mat_b_rearr[5] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0xEE); mat_b_rearr[6] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0x44); mat_b_rearr[7] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0xEE); #else mat_b_rearr[6] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0x4E); mat_b_rearr[7] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0x4E); mat_b_rearr[4] = _mm256_blend_ps(mat_b_rearr[0], mat_b_rearr[6], 0xCC); mat_b_rearr[5] = _mm256_blend_ps(mat_b_rearr[1], mat_b_rearr[6], 0x33); mat_b_rearr[6] = _mm256_blend_ps(mat_b_rearr[2], mat_b_rearr[7], 0xCC); mat_b_rearr[7] = _mm256_blend_ps(mat_b_rearr[3], mat_b_rearr[7], 0x33); #endif //Merge rearranged low elements into complete rows mat_b_rearr[0] = _mm256_permute2f128_ps(mat_b_rearr[4], mat_b_rearr[6], 0x20); mat_b_rearr[4] = _mm256_permute2f128_ps(mat_b_rearr[4], mat_b_rearr[6], 0x31); mat_b_rearr[1] = _mm256_permute2f128_ps(mat_b_rearr[5], mat_b_rearr[7], 0x20); mat_b_rearr[5] = _mm256_permute2f128_ps(mat_b_rearr[5], mat_b_rearr[7], 0x31); ////unpackhigh//// mat_b_col[0] = _mm256_unpackhi_ps(mat_b_col[0], mat_b_col[1]); mat_b_col[1] = _mm256_unpackhi_ps(mat_b_col[2], mat_b_col[3]); mat_b_col[2] = _mm256_unpackhi_ps(mat_b_col[4], mat_b_col[5]); mat_b_col[3] = _mm256_unpackhi_ps(mat_b_col[6], mat_b_col[7]); //Rearrange high elements #if REARRANGE_SHFL == 1 mat_b_col[4] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0x44); mat_b_col[5] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0xEE); mat_b_col[6] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0x44); mat_b_col[7] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0xEE); #else mat_b_col[6] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0x4E); mat_b_col[7] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0x4E); mat_b_col[4] = _mm256_blend_ps(mat_b_col[0], mat_b_col[6], 0xCC); mat_b_col[5] = _mm256_blend_ps(mat_b_col[1], mat_b_col[6], 0x33); mat_b_col[6] = _mm256_blend_ps(mat_b_col[2], mat_b_col[7], 0xCC); mat_b_col[7] = _mm256_blend_ps(mat_b_col[3], mat_b_col[7], 0x33); #endif //Merge rearranged high elements into complete rows mat_b_rearr[2] = _mm256_permute2f128_ps(mat_b_col[4], mat_b_col[6], 0x20); mat_b_rearr[6] = _mm256_permute2f128_ps(mat_b_col[4], mat_b_col[6], 0x31); mat_b_rearr[3] = _mm256_permute2f128_ps(mat_b_col[5], mat_b_col[7], 0x20); mat_b_rearr[7] = _mm256_permute2f128_ps(mat_b_col[5], mat_b_col[7], 0x31); /* transpose steps end */ //Store the computed B columns _mm256_storeu_ps((float *)ptr_b_dup, mat_b_rearr[0]); _mm256_storeu_ps((float *)(ptr_b_dup + (cs_b)), mat_b_rearr[1]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[0]), mat_b_rearr[2]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[1]), mat_b_rearr[3]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[2]), mat_b_rearr[4]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[3]), mat_b_rearr[5]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[4]), mat_b_rearr[6]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[5]), mat_b_rearr[7]); i += cs_b_offset[6]; ptr_b_dup += cs_b_offset[6]; //i += 8; //ptr_b_dup += 8; } //c = 0; /***************** first set of 8 cols of B processing done *****************/ ptr_b_dup = ptr_b; i1 = 0; //Start loop for cols of B to be processed in size of blk_width for (j = 8; j < numRows_lb; j += 8)//m :- 8x8 block row { ptr_l += cs_l_offset[6]; //ptr_b += j; //ptr_b_dup += 8; ptr_b_dup += 8; i1 += 8; i = i1; i2 = 0; for (r = 0; r < numCols_b; r += GEMM_BLK_V1) { #if GEMM_ACCUM_A //Read 8 cols of B columns of Block-to-be-solved mat_b_col[0] = _mm256_loadu_ps((float const *)ptr_b + i); mat_b_col[1] = _mm256_loadu_ps((float const *)(ptr_b + cs_b + i)); mat_b_col[2] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[0] + i)); mat_b_col[3] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[1] + i)); mat_b_col[4] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[2] + i)); mat_b_col[5] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[3] + i)); mat_b_col[6] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[4] + i)); mat_b_col[7] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[5] + i)); /* transpose steps start */ ////unpacklow//// mat_b_rearr[0] = _mm256_unpacklo_ps(mat_b_col[0], mat_b_col[1]); mat_b_rearr[1] = _mm256_unpacklo_ps(mat_b_col[2], mat_b_col[3]); mat_b_rearr[2] = _mm256_unpacklo_ps(mat_b_col[4], mat_b_col[5]); mat_b_rearr[3] = _mm256_unpacklo_ps(mat_b_col[6], mat_b_col[7]); //Rearrange low elements #if REARRANGE_SHFL == 1 mat_b_rearr[4] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0x44); mat_b_rearr[5] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0xEE); mat_b_rearr[6] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0x44); mat_b_rearr[7] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0xEE); #else mat_b_rearr[6] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0x4E); mat_b_rearr[7] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0x4E); mat_b_rearr[4] = _mm256_blend_ps(mat_b_rearr[0], mat_b_rearr[6], 0xCC); mat_b_rearr[5] = _mm256_blend_ps(mat_b_rearr[1], mat_b_rearr[6], 0x33); mat_b_rearr[6] = _mm256_blend_ps(mat_b_rearr[2], mat_b_rearr[7], 0xCC); mat_b_rearr[7] = _mm256_blend_ps(mat_b_rearr[3], mat_b_rearr[7], 0x33); #endif //Merge rearranged low elements into complete rows mat_b_rearr[0] = _mm256_permute2f128_ps(mat_b_rearr[4], mat_b_rearr[6], 0x20); mat_b_rearr[4] = _mm256_permute2f128_ps(mat_b_rearr[4], mat_b_rearr[6], 0x31); mat_b_rearr[1] = _mm256_permute2f128_ps(mat_b_rearr[5], mat_b_rearr[7], 0x20); mat_b_rearr[5] = _mm256_permute2f128_ps(mat_b_rearr[5], mat_b_rearr[7], 0x31); ////unpackhigh//// mat_b_col[0] = _mm256_unpackhi_ps(mat_b_col[0], mat_b_col[1]); mat_b_col[1] = _mm256_unpackhi_ps(mat_b_col[2], mat_b_col[3]); mat_b_col[2] = _mm256_unpackhi_ps(mat_b_col[4], mat_b_col[5]); mat_b_col[3] = _mm256_unpackhi_ps(mat_b_col[6], mat_b_col[7]); //Rearrange high elements #if REARRANGE_SHFL == 1 mat_b_col[4] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0x44); mat_b_col[5] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0xEE); mat_b_col[6] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0x44); mat_b_col[7] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0xEE); #else mat_b_col[6] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0x4E); mat_b_col[7] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0x4E); mat_b_col[4] = _mm256_blend_ps(mat_b_col[0], mat_b_col[6], 0xCC); mat_b_col[5] = _mm256_blend_ps(mat_b_col[1], mat_b_col[6], 0x33); mat_b_col[6] = _mm256_blend_ps(mat_b_col[2], mat_b_col[7], 0xCC); mat_b_col[7] = _mm256_blend_ps(mat_b_col[3], mat_b_col[7], 0x33); #endif //Merge rearranged high elements into complete rows mat_b_rearr[2] = _mm256_permute2f128_ps(mat_b_col[4], mat_b_col[6], 0x20); mat_b_rearr[6] = _mm256_permute2f128_ps(mat_b_col[4], mat_b_col[6], 0x31); mat_b_rearr[3] = _mm256_permute2f128_ps(mat_b_col[5], mat_b_col[7], 0x20); mat_b_rearr[7] = _mm256_permute2f128_ps(mat_b_col[5], mat_b_col[7], 0x31); /* transpose steps end */ mat_b_rearr[0] = _mm256_mul_ps(mat_b_rearr[0], alphaReg); mat_b_rearr[1] = _mm256_mul_ps(mat_b_rearr[1], alphaReg); mat_b_rearr[2] = _mm256_mul_ps(mat_b_rearr[2], alphaReg); mat_b_rearr[3] = _mm256_mul_ps(mat_b_rearr[3], alphaReg); mat_b_rearr[4] = _mm256_mul_ps(mat_b_rearr[4], alphaReg); mat_b_rearr[5] = _mm256_mul_ps(mat_b_rearr[5], alphaReg); mat_b_rearr[6] = _mm256_mul_ps(mat_b_rearr[6], alphaReg); mat_b_rearr[7] = _mm256_mul_ps(mat_b_rearr[7], alphaReg); #endif //i = 0; ptr_l_dup = ptr_l; i4 = i2; for (l = 0; l < j; l += 8) // move across m { //for (k = 0; k < numCols_b; k += 8) // move across n for the same value of l (index of m) //{ /////////////////// Partial Lower 8x8 block trsm of B //Read current 8 cols of B columns from specified 8x8 current-block of B mat_a_blk_elems[0] = _mm256_loadu_ps((float const *)ptr_b + i4); mat_a_blk_elems[1] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b)); mat_a_blk_elems[2] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b_offset[0])); mat_a_blk_elems[3] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b_offset[1])); mat_a_blk_elems[4] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b_offset[2])); mat_a_blk_elems[5] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b_offset[3])); mat_a_blk_elems[6] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b_offset[4])); mat_a_blk_elems[7] = _mm256_loadu_ps((float const *)(ptr_b + i4 + cs_b_offset[5])); /* transpose steps start */ ////unpacklow//// mat_b_col[0] = _mm256_unpacklo_ps(mat_a_blk_elems[0], mat_a_blk_elems[1]); mat_b_col[1] = _mm256_unpacklo_ps(mat_a_blk_elems[2], mat_a_blk_elems[3]); mat_b_col[2] = _mm256_unpacklo_ps(mat_a_blk_elems[4], mat_a_blk_elems[5]); mat_b_col[3] = _mm256_unpacklo_ps(mat_a_blk_elems[6], mat_a_blk_elems[7]); //Rearrange low elements #if REARRANGE_SHFL == 1 mat_b_col[4] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0x44); mat_b_col[5] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0xEE); mat_b_col[6] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0x44); mat_b_col[7] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0xEE); #else mat_b_col[6] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0x4E); mat_b_col[7] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0x4E); mat_b_col[4] = _mm256_blend_ps(mat_b_col[0], mat_b_col[6], 0xCC); mat_b_col[5] = _mm256_blend_ps(mat_b_col[1], mat_b_col[6], 0x33); mat_b_col[6] = _mm256_blend_ps(mat_b_col[2], mat_b_col[7], 0xCC); mat_b_col[7] = _mm256_blend_ps(mat_b_col[3], mat_b_col[7], 0x33); #endif //Merge rearranged low elements into complete rows mat_b_col[0] = _mm256_permute2f128_ps(mat_b_col[4], mat_b_col[6], 0x20); mat_b_col[4] = _mm256_permute2f128_ps(mat_b_col[4], mat_b_col[6], 0x31); mat_b_col[1] = _mm256_permute2f128_ps(mat_b_col[5], mat_b_col[7], 0x20); mat_b_col[5] = _mm256_permute2f128_ps(mat_b_col[5], mat_b_col[7], 0x31); ////unpackhigh//// mat_a_blk_elems[0] = _mm256_unpackhi_ps(mat_a_blk_elems[0], mat_a_blk_elems[1]); mat_a_blk_elems[1] = _mm256_unpackhi_ps(mat_a_blk_elems[2], mat_a_blk_elems[3]); mat_a_blk_elems[2] = _mm256_unpackhi_ps(mat_a_blk_elems[4], mat_a_blk_elems[5]); mat_a_blk_elems[3] = _mm256_unpackhi_ps(mat_a_blk_elems[6], mat_a_blk_elems[7]); //Rearrange high elements #if REARRANGE_SHFL == 1 mat_a_blk_elems[4] = _mm256_shuffle_ps(mat_a_blk_elems[0], mat_a_blk_elems[1], 0x44); mat_a_blk_elems[5] = _mm256_shuffle_ps(mat_a_blk_elems[0], mat_a_blk_elems[1], 0xEE); mat_a_blk_elems[6] = _mm256_shuffle_ps(mat_a_blk_elems[2], mat_a_blk_elems[3], 0x44); mat_a_blk_elems[7] = _mm256_shuffle_ps(mat_a_blk_elems[2], mat_a_blk_elems[3], 0xEE); #else mat_a_blk_elems[6] = _mm256_shuffle_ps(mat_a_blk_elems[0], mat_a_blk_elems[1], 0x4E); mat_a_blk_elems[7] = _mm256_shuffle_ps(mat_a_blk_elems[2], mat_a_blk_elems[3], 0x4E); mat_a_blk_elems[4] = _mm256_blend_ps(mat_a_blk_elems[0], mat_a_blk_elems[6], 0xCC); mat_a_blk_elems[5] = _mm256_blend_ps(mat_a_blk_elems[1], mat_a_blk_elems[6], 0x33); mat_a_blk_elems[6] = _mm256_blend_ps(mat_a_blk_elems[2], mat_a_blk_elems[7], 0xCC); mat_a_blk_elems[7] = _mm256_blend_ps(mat_a_blk_elems[3], mat_a_blk_elems[7], 0x33); #endif //Merge rearranged high elements into complete rows mat_b_col[2] = _mm256_permute2f128_ps(mat_a_blk_elems[4], mat_a_blk_elems[6], 0x20); mat_b_col[6] = _mm256_permute2f128_ps(mat_a_blk_elems[4], mat_a_blk_elems[6], 0x31); mat_b_col[3] = _mm256_permute2f128_ps(mat_a_blk_elems[5], mat_a_blk_elems[7], 0x20); mat_b_col[7] = _mm256_permute2f128_ps(mat_a_blk_elems[5], mat_a_blk_elems[7], 0x31); /* transpose steps end */ //Broadcast A8,0 to A15,0 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[0])); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[1])); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[2])); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[3])); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[4])); mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[5])); //i4 = k >> 3; ptr_l_dup++; #if GEMM_ACCUM_A //(Row8): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[0] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[0], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[0], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[0], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[0], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[0], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[0], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_col[0], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[7], mat_b_col[0], mat_b_rearr[7]);//d = c - (a*b) #else mat_b_rearr[0] = _mm256_mul_ps(mat_a_blk_elems[0], mat_b_col[0]); mat_b_rearr[1] = _mm256_mul_ps(mat_a_blk_elems[1], mat_b_col[0]); mat_b_rearr[2] = _mm256_mul_ps(mat_a_blk_elems[2], mat_b_col[0]); mat_b_rearr[3] = _mm256_mul_ps(mat_a_blk_elems[3], mat_b_col[0]); mat_b_rearr[4] = _mm256_mul_ps(mat_a_blk_elems[4], mat_b_col[0]); mat_b_rearr[5] = _mm256_mul_ps(mat_a_blk_elems[5], mat_b_col[0]); mat_b_rearr[6] = _mm256_mul_ps(mat_a_blk_elems[6], mat_b_col[0]); mat_b_rearr[7] = _mm256_mul_ps(mat_a_blk_elems[7], mat_b_col[0]); #endif //Broadcast A21 to A71 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[0])); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[1])); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[2])); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[3])); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[4])); mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[5])); ptr_l_dup++; #if GEMM_ACCUM_A //(Row9): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[0] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[1], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[1], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[1], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[1], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[1], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[1], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_col[1], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[7], mat_b_col[1], mat_b_rearr[7]);//d = c - (a*b) #else mat_b_rearr[0] = _mm256_fmadd_ps(mat_a_blk_elems[0], mat_b_col[1], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fmadd_ps(mat_a_blk_elems[1], mat_b_col[1], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fmadd_ps(mat_a_blk_elems[2], mat_b_col[1], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fmadd_ps(mat_a_blk_elems[3], mat_b_col[1], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fmadd_ps(mat_a_blk_elems[4], mat_b_col[1], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fmadd_ps(mat_a_blk_elems[5], mat_b_col[1], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fmadd_ps(mat_a_blk_elems[6], mat_b_col[1], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fmadd_ps(mat_a_blk_elems[7], mat_b_col[1], mat_b_rearr[7]);//d = c - (a*b) #endif //Broadcast A8,2 to A15,2 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[0])); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[1])); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[2])); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[3])); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[4])); mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[5])); ptr_l_dup++; #if GEMM_ACCUM_A //(Row10): FMA operations of b2 with elements of indices from (2, 0) uptill (7, 0) mat_b_rearr[0] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[2], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[2], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[2], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[2], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[2], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[2], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_col[2], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[7], mat_b_col[2], mat_b_rearr[7]);//d = c - (a*b) #else mat_b_rearr[0] = _mm256_fmadd_ps(mat_a_blk_elems[0], mat_b_col[2], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fmadd_ps(mat_a_blk_elems[1], mat_b_col[2], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fmadd_ps(mat_a_blk_elems[2], mat_b_col[2], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fmadd_ps(mat_a_blk_elems[3], mat_b_col[2], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fmadd_ps(mat_a_blk_elems[4], mat_b_col[2], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fmadd_ps(mat_a_blk_elems[5], mat_b_col[2], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fmadd_ps(mat_a_blk_elems[6], mat_b_col[2], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fmadd_ps(mat_a_blk_elems[7], mat_b_col[2], mat_b_rearr[7]);//d = c - (a*b) #endif //Broadcast A8,3 to A15,3 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[0])); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[1])); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[2])); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[3])); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[4])); mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[5])); ptr_l_dup++; #if GEMM_ACCUM_A //(Row11): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[0] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[3], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[3], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[3], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[3], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[3], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[3], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_col[3], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[7], mat_b_col[3], mat_b_rearr[7]);//d = c - (a*b) #else mat_b_rearr[0] = _mm256_fmadd_ps(mat_a_blk_elems[0], mat_b_col[3], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fmadd_ps(mat_a_blk_elems[1], mat_b_col[3], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fmadd_ps(mat_a_blk_elems[2], mat_b_col[3], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fmadd_ps(mat_a_blk_elems[3], mat_b_col[3], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fmadd_ps(mat_a_blk_elems[4], mat_b_col[3], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fmadd_ps(mat_a_blk_elems[5], mat_b_col[3], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fmadd_ps(mat_a_blk_elems[6], mat_b_col[3], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fmadd_ps(mat_a_blk_elems[7], mat_b_col[3], mat_b_rearr[7]);//d = c - (a*b) #endif //Broadcast A8,4 to A15,4 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[0])); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[1])); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[2])); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[3])); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[4])); mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[5])); ptr_l_dup++; #if GEMM_ACCUM_A //(Row12): FMA operations of b2 with elements of indices from (2, 0) uptill (7, 0) mat_b_rearr[0] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[4], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[4], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[4], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[4], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[4], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[4], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_col[4], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[7], mat_b_col[4], mat_b_rearr[7]);//d = c - (a*b) #else mat_b_rearr[0] = _mm256_fmadd_ps(mat_a_blk_elems[0], mat_b_col[4], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fmadd_ps(mat_a_blk_elems[1], mat_b_col[4], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fmadd_ps(mat_a_blk_elems[2], mat_b_col[4], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fmadd_ps(mat_a_blk_elems[3], mat_b_col[4], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fmadd_ps(mat_a_blk_elems[4], mat_b_col[4], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fmadd_ps(mat_a_blk_elems[5], mat_b_col[4], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fmadd_ps(mat_a_blk_elems[6], mat_b_col[4], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fmadd_ps(mat_a_blk_elems[7], mat_b_col[4], mat_b_rearr[7]);//d = c - (a*b) #endif //Broadcast A8,5 to A15,5 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[0])); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[1])); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[2])); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[3])); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[4])); mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[5])); ptr_l_dup++; #if GEMM_ACCUM_A //(Row13): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[0] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[5], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[5], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[5], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[5], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[5], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[5], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_col[5], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[7], mat_b_col[5], mat_b_rearr[7]);//d = c - (a*b) #else mat_b_rearr[0] = _mm256_fmadd_ps(mat_a_blk_elems[0], mat_b_col[5], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fmadd_ps(mat_a_blk_elems[1], mat_b_col[5], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fmadd_ps(mat_a_blk_elems[2], mat_b_col[5], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fmadd_ps(mat_a_blk_elems[3], mat_b_col[5], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fmadd_ps(mat_a_blk_elems[4], mat_b_col[5], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fmadd_ps(mat_a_blk_elems[5], mat_b_col[5], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fmadd_ps(mat_a_blk_elems[6], mat_b_col[5], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fmadd_ps(mat_a_blk_elems[7], mat_b_col[5], mat_b_rearr[7]);//d = c - (a*b) #endif //Broadcast A8,6 to A15,6 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[0])); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[1])); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[2])); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[3])); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[4])); mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[5])); ptr_l_dup++; #if GEMM_ACCUM_A //(Row14): FMA operations of b2 with elements of indices from (2, 0) uptill (7, 0) mat_b_rearr[0] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[6], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[6], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[6], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[6], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[6], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[6], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_col[6], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[7], mat_b_col[6], mat_b_rearr[7]);//d = c - (a*b) #else mat_b_rearr[0] = _mm256_fmadd_ps(mat_a_blk_elems[0], mat_b_col[6], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fmadd_ps(mat_a_blk_elems[1], mat_b_col[6], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fmadd_ps(mat_a_blk_elems[2], mat_b_col[6], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fmadd_ps(mat_a_blk_elems[3], mat_b_col[6], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fmadd_ps(mat_a_blk_elems[4], mat_b_col[6], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fmadd_ps(mat_a_blk_elems[5], mat_b_col[6], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fmadd_ps(mat_a_blk_elems[6], mat_b_col[6], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fmadd_ps(mat_a_blk_elems[7], mat_b_col[6], mat_b_rearr[7]);//d = c - (a*b) #endif //Broadcast A8,7 to A15,7 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l)); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[0])); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[1])); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[2])); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[3])); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[4])); mat_a_blk_elems[7] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[5])); ptr_l_dup++; #if GEMM_ACCUM_A //(Row15): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[0] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_col[7], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_col[7], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_col[7], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_col[7], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_col[7], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_col[7], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_col[7], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[7], mat_b_col[7], mat_b_rearr[7]);//d = c - (a*b) #else mat_b_rearr[0] = _mm256_fmadd_ps(mat_a_blk_elems[0], mat_b_col[7], mat_b_rearr[0]);//d = c - (a*b) mat_b_rearr[1] = _mm256_fmadd_ps(mat_a_blk_elems[1], mat_b_col[7], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fmadd_ps(mat_a_blk_elems[2], mat_b_col[7], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fmadd_ps(mat_a_blk_elems[3], mat_b_col[7], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fmadd_ps(mat_a_blk_elems[4], mat_b_col[7], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fmadd_ps(mat_a_blk_elems[5], mat_b_col[7], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fmadd_ps(mat_a_blk_elems[6], mat_b_col[7], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fmadd_ps(mat_a_blk_elems[7], mat_b_col[7], mat_b_rearr[7]);//d = c - (a*b) #endif //end loop of cols //} //i2 += cs_b_offset[6]; i4 += 8; } //trsm solve k = 0; //for (i2 = 0; i2 < numCols_b; i2 += 8) //{ //i2 = i1 + r; /////////////////// Complete Lower 8x8 block trsm of B :- lower 8x8 block of B with lower right 8x8 block of A #if !GEMM_ACCUM_A //Read 8 cols of B columns of Block-to-be-solved mat_b_rearr[0] = _mm256_loadu_ps((float const *)ptr_b + i); mat_b_rearr[1] = _mm256_loadu_ps((float const *)(ptr_b + cs_b + i)); mat_b_rearr[2] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[0] + i)); mat_b_rearr[3] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[1] + i)); mat_b_rearr[4] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[2] + i)); mat_b_rearr[5] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[3] + i)); mat_b_rearr[6] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[4] + i)); mat_b_rearr[7] = _mm256_loadu_ps((float const *)(ptr_b + cs_b_offset[5] + i)); /* transpose steps start */ ////unpacklow//// mat_b_col[0] = _mm256_unpacklo_ps(mat_b_rearr[0], mat_b_rearr[1]); mat_b_col[1] = _mm256_unpacklo_ps(mat_b_rearr[2], mat_b_rearr[3]); mat_b_col[2] = _mm256_unpacklo_ps(mat_b_rearr[4], mat_b_rearr[5]); mat_b_col[3] = _mm256_unpacklo_ps(mat_b_rearr[6], mat_b_rearr[7]); //Rearrange low elements #if REARRANGE_SHFL == 1 mat_b_col[4] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0x44); mat_b_col[5] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0xEE); mat_b_col[6] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0x44); mat_b_col[7] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0xEE); #else mat_b_col[6] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0x4E); mat_b_col[7] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0x4E); mat_b_col[4] = _mm256_blend_ps(mat_b_col[0], mat_b_col[6], 0xCC); mat_b_col[5] = _mm256_blend_ps(mat_b_col[1], mat_b_col[6], 0x33); mat_b_col[6] = _mm256_blend_ps(mat_b_col[2], mat_b_col[7], 0xCC); mat_b_col[7] = _mm256_blend_ps(mat_b_col[3], mat_b_col[7], 0x33); #endif //Merge rearranged low elements into complete rows mat_b_col[0] = _mm256_permute2f128_ps(mat_b_col[4], mat_b_col[6], 0x20); mat_b_col[4] = _mm256_permute2f128_ps(mat_b_col[4], mat_b_col[6], 0x31); mat_b_col[1] = _mm256_permute2f128_ps(mat_b_col[5], mat_b_col[7], 0x20); mat_b_col[5] = _mm256_permute2f128_ps(mat_b_col[5], mat_b_col[7], 0x31); ////unpackhigh//// mat_b_rearr[0] = _mm256_unpackhi_ps(mat_b_rearr[0], mat_b_rearr[1]); mat_b_rearr[1] = _mm256_unpackhi_ps(mat_b_rearr[2], mat_b_rearr[3]); mat_b_rearr[2] = _mm256_unpackhi_ps(mat_b_rearr[4], mat_b_rearr[5]); mat_b_rearr[3] = _mm256_unpackhi_ps(mat_b_rearr[6], mat_b_rearr[7]); //Rearrange high elements #if REARRANGE_SHFL == 1 mat_b_rearr[4] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0x44); mat_b_rearr[5] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0xEE); mat_b_rearr[6] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0x44); mat_b_rearr[7] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0xEE); #else mat_b_rearr[6] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0x4E); mat_b_rearr[7] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0x4E); mat_b_rearr[4] = _mm256_blend_ps(mat_b_rearr[0], mat_b_rearr[6], 0xCC); mat_b_rearr[5] = _mm256_blend_ps(mat_b_rearr[1], mat_b_rearr[6], 0x33); mat_b_rearr[6] = _mm256_blend_ps(mat_b_rearr[2], mat_b_rearr[7], 0xCC); mat_b_rearr[7] = _mm256_blend_ps(mat_b_rearr[3], mat_b_rearr[7], 0x33); #endif //Merge rearranged high elements into complete rows mat_b_col[2] = _mm256_permute2f128_ps(mat_b_rearr[4], mat_b_rearr[6], 0x20); mat_b_col[6] = _mm256_permute2f128_ps(mat_b_rearr[4], mat_b_rearr[6], 0x31); mat_b_col[3] = _mm256_permute2f128_ps(mat_b_rearr[5], mat_b_rearr[7], 0x20); mat_b_col[7] = _mm256_permute2f128_ps(mat_b_rearr[5], mat_b_rearr[7], 0x31); /* transpose steps end */ mat_b_col[0] = _mm256_mul_ps(mat_b_col[0], alphaReg); mat_b_col[1] = _mm256_mul_ps(mat_b_col[1], alphaReg); mat_b_col[2] = _mm256_mul_ps(mat_b_col[2], alphaReg); mat_b_col[3] = _mm256_mul_ps(mat_b_col[3], alphaReg); mat_b_col[4] = _mm256_mul_ps(mat_b_col[4], alphaReg); mat_b_col[5] = _mm256_mul_ps(mat_b_col[5], alphaReg); mat_b_col[6] = _mm256_mul_ps(mat_b_col[6], alphaReg); mat_b_col[7] = _mm256_mul_ps(mat_b_col[7], alphaReg); #endif //Broadcast A10 to A70 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l)); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[0])); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[1])); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[2])); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[3])); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[4])); mat_a_blk_elems[6] = _mm256_broadcast_ss((float const *)(ptr_l_dup + cs_l_offset[5])); //i += cs_l; #if GEMM_ACCUM_A //(Row0): already done #else mat_b_rearr[0] = _mm256_sub_ps(mat_b_col[0], mat_b_rearr[0]); #endif #if GEMM_ACCUM_A mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_rearr[0], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_rearr[0], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_rearr[0], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_rearr[0], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_rearr[0], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_rearr[0], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_rearr[0], mat_b_rearr[7]);//d = c - (a*b) #else mat_b_rearr[1] = _mm256_sub_ps(mat_b_col[1], mat_b_rearr[1]); mat_b_rearr[2] = _mm256_sub_ps(mat_b_col[2], mat_b_rearr[2]); mat_b_rearr[3] = _mm256_sub_ps(mat_b_col[3], mat_b_rearr[3]); mat_b_rearr[4] = _mm256_sub_ps(mat_b_col[4], mat_b_rearr[4]); mat_b_rearr[5] = _mm256_sub_ps(mat_b_col[5], mat_b_rearr[5]); mat_b_rearr[6] = _mm256_sub_ps(mat_b_col[6], mat_b_rearr[6]); mat_b_rearr[7] = _mm256_sub_ps(mat_b_col[7], mat_b_rearr[7]); //(Row1): FMA operations of b1 with elements of indices from (1, 0) uptill (7, 0) mat_b_rearr[1] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_rearr[0], mat_b_rearr[1]);//d = c - (a*b) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_rearr[0], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_rearr[0], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_rearr[0], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_rearr[0], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_rearr[0], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[6], mat_b_rearr[0], mat_b_rearr[7]);//d = c - (a*b) #endif //Broadcast A21 to A71 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 1 + cs_l_offset[0])); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 1 + cs_l_offset[1])); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 1 + cs_l_offset[2])); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 1 + cs_l_offset[3])); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 1 + cs_l_offset[4])); mat_a_blk_elems[5] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 1 + cs_l_offset[5])); //i += cs_l; //(Row2): FMA operations of b2 with elements of indices from (2, 0) uptill (7, 0) mat_b_rearr[2] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_rearr[1], mat_b_rearr[2]);//d = c - (a*b) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_rearr[1], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_rearr[1], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_rearr[1], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_rearr[1], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[5], mat_b_rearr[1], mat_b_rearr[7]);//d = c - (a*b) //Broadcast A32 to A72 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 2 + cs_l_offset[1])); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 2 + cs_l_offset[2])); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 2 + cs_l_offset[3])); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 2 + cs_l_offset[4])); mat_a_blk_elems[4] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 2 + cs_l_offset[5])); //i += cs_l; //(Row3): FMA operations of b3 with elements of indices from (3, 0) uptill (7, 0) mat_b_rearr[3] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_rearr[2], mat_b_rearr[3]);//d = c - (a*b) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_rearr[2], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_rearr[2], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_rearr[2], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[4], mat_b_rearr[2], mat_b_rearr[7]);//d = c - (a*b) //Broadcast A43 to A73 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 3 + cs_l_offset[2])); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 3 + cs_l_offset[3])); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 3 + cs_l_offset[4])); mat_a_blk_elems[3] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 3 + cs_l_offset[5])); //i += cs_l; //(Row4): FMA operations of b4 with elements of indices from (4, 0) uptill (7, 0) mat_b_rearr[4] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_rearr[3], mat_b_rearr[4]);//d = c - (a*b) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_rearr[3], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_rearr[3], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[3], mat_b_rearr[3], mat_b_rearr[7]);//d = c - (a*b) //Broadcast A54 to A74 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 4 + cs_l_offset[3])); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 4 + cs_l_offset[4])); mat_a_blk_elems[2] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 4 + cs_l_offset[5])); //i += cs_l; //(Row5): FMA operations of b5 with elements of indices from (5, 0) uptill (7, 0) mat_b_rearr[5] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_rearr[4], mat_b_rearr[5]);//d = c - (a*b) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_rearr[4], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[2], mat_b_rearr[4], mat_b_rearr[7]);//d = c - (a*b) //Broadcast A65 to A75 to registers mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 5 + cs_l_offset[4])); mat_a_blk_elems[1] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 5 + cs_l_offset[5])); //i += cs_l; //(Row6): FMA operations of b6 with elements of indices from (6, 0) uptill (7, 0) mat_b_rearr[6] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_rearr[5], mat_b_rearr[6]);//d = c - (a*b) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[1], mat_b_rearr[5], mat_b_rearr[7]);//d = c - (a*b) //Broadcast A76 to register mat_a_blk_elems[0] = _mm256_broadcast_ss((float const *)(ptr_l_dup + 6 + cs_l_offset[5])); //(Row7): FMA operations of b7 with elements of index (7, 0) mat_b_rearr[7] = _mm256_fnmadd_ps(mat_a_blk_elems[0], mat_b_rearr[6], mat_b_rearr[7]);//d = c - (a*b) //////////////////////////////////////////////////////////////////////////////// /* transpose steps start */ ////unpacklow//// mat_b_col[0] = _mm256_unpacklo_ps(mat_b_rearr[0], mat_b_rearr[1]); mat_b_col[1] = _mm256_unpacklo_ps(mat_b_rearr[2], mat_b_rearr[3]); mat_b_col[2] = _mm256_unpacklo_ps(mat_b_rearr[4], mat_b_rearr[5]); mat_b_col[3] = _mm256_unpacklo_ps(mat_b_rearr[6], mat_b_rearr[7]); //Rearrange low elements #if REARRANGE_SHFL == 1 mat_b_col[4] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0x44); mat_b_col[5] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0xEE); mat_b_col[6] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0x44); mat_b_col[7] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0xEE); #else mat_b_col[6] = _mm256_shuffle_ps(mat_b_col[0], mat_b_col[1], 0x4E); mat_b_col[7] = _mm256_shuffle_ps(mat_b_col[2], mat_b_col[3], 0x4E); mat_b_col[4] = _mm256_blend_ps(mat_b_col[0], mat_b_col[6], 0xCC); mat_b_col[5] = _mm256_blend_ps(mat_b_col[1], mat_b_col[6], 0x33); mat_b_col[6] = _mm256_blend_ps(mat_b_col[2], mat_b_col[7], 0xCC); mat_b_col[7] = _mm256_blend_ps(mat_b_col[3], mat_b_col[7], 0x33); #endif //Merge rearranged low elements into complete rows mat_b_col[0] = _mm256_permute2f128_ps(mat_b_col[4], mat_b_col[6], 0x20); mat_b_col[4] = _mm256_permute2f128_ps(mat_b_col[4], mat_b_col[6], 0x31); mat_b_col[1] = _mm256_permute2f128_ps(mat_b_col[5], mat_b_col[7], 0x20); mat_b_col[5] = _mm256_permute2f128_ps(mat_b_col[5], mat_b_col[7], 0x31); ////unpackhigh//// mat_b_rearr[0] = _mm256_unpackhi_ps(mat_b_rearr[0], mat_b_rearr[1]); mat_b_rearr[1] = _mm256_unpackhi_ps(mat_b_rearr[2], mat_b_rearr[3]); mat_b_rearr[2] = _mm256_unpackhi_ps(mat_b_rearr[4], mat_b_rearr[5]); mat_b_rearr[3] = _mm256_unpackhi_ps(mat_b_rearr[6], mat_b_rearr[7]); //Rearrange high elements #if REARRANGE_SHFL == 1 mat_b_rearr[4] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0x44); mat_b_rearr[5] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0xEE); mat_b_rearr[6] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0x44); mat_b_rearr[7] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0xEE); #else mat_b_rearr[6] = _mm256_shuffle_ps(mat_b_rearr[0], mat_b_rearr[1], 0x4E); mat_b_rearr[7] = _mm256_shuffle_ps(mat_b_rearr[2], mat_b_rearr[3], 0x4E); mat_b_rearr[4] = _mm256_blend_ps(mat_b_rearr[0], mat_b_rearr[6], 0xCC); mat_b_rearr[5] = _mm256_blend_ps(mat_b_rearr[1], mat_b_rearr[6], 0x33); mat_b_rearr[6] = _mm256_blend_ps(mat_b_rearr[2], mat_b_rearr[7], 0xCC); mat_b_rearr[7] = _mm256_blend_ps(mat_b_rearr[3], mat_b_rearr[7], 0x33); #endif //Merge rearranged high elements into complete rows mat_b_col[2] = _mm256_permute2f128_ps(mat_b_rearr[4], mat_b_rearr[6], 0x20); mat_b_col[6] = _mm256_permute2f128_ps(mat_b_rearr[4], mat_b_rearr[6], 0x31); mat_b_col[3] = _mm256_permute2f128_ps(mat_b_rearr[5], mat_b_rearr[7], 0x20); mat_b_col[7] = _mm256_permute2f128_ps(mat_b_rearr[5], mat_b_rearr[7], 0x31); /* transpose steps end */ //Store the computed B columns _mm256_storeu_ps((float *)ptr_b_dup + i2, mat_b_col[0]); _mm256_storeu_ps((float *)(ptr_b_dup + (cs_b)+i2), mat_b_col[1]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[0] + i2), mat_b_col[2]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[1] + i2), mat_b_col[3]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[2] + i2), mat_b_col[4]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[3] + i2), mat_b_col[5]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[4] + i2), mat_b_col[6]); _mm256_storeu_ps((float *)(ptr_b_dup + cs_b_offset[5] + i2), mat_b_col[7]); //printf("writing B => m[%d], n[%d], [%f]\n", j, k, *(ptr_b_dup + k)); k++; //} i += cs_b_offset[6]; i2 += cs_b_offset[6]; } } //numRows of A ///////////////////loop ends ///////////////////// } #endif blis-0.9.0/kernels/zen/3/sup/000077500000000000000000000000001422157504600156675ustar00rootroot00000000000000blis-0.9.0/kernels/zen/3/sup/broken/000077500000000000000000000000001422157504600171475ustar00rootroot00000000000000blis-0.9.0/kernels/zen/3/sup/broken/bli_gemmsup_rv_zen_asm_c3x8.c000066400000000000000000002102211422157504600247040ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define BLIS_ASM_SYNTAX_ATT #include "bli_x86_asm_macros.h" // assumes beta.r, beta.i have been broadcast into ymm1, ymm2. // outputs to ymm0 #define CGEMM_INPUT_SCALE_CS_BETA_NZ \ vmovlpd(mem(rcx), xmm0, xmm0) \ vmovhpd(mem(rcx, rsi, 1), xmm0, xmm0) \ vmovlpd(mem(rcx, rsi, 2), xmm3, xmm3) \ vmovhpd(mem(rcx, r13, 1), xmm3, xmm3) \ vinsertf128(imm(1), xmm3, ymm0, ymm0) \ vpermilps(imm(0xb1), ymm0, ymm3) \ vmulps(ymm1, ymm0, ymm0) \ vmulps(ymm2, ymm3, ymm3) \ vaddsubps(ymm3, ymm0, ymm0) #define CGEMM_INPUT_SCALE_CS_BETA_NZ_128 \ vmovlpd(mem(rcx), xmm0, xmm0) \ vmovhpd(mem(rcx, rsi, 1), xmm0, xmm0) \ vpermilps(imm(0xb1), xmm0, xmm3) \ vmulps(xmm1, xmm0, xmm0) \ vmulps(xmm2, xmm3, xmm3) \ vaddsubps(xmm3, xmm0, xmm0) // assumes values to output are in ymm0 #define CGEMM_OUTPUT_GS \ vextractf128(imm(1), ymm0, xmm3) \ vmovlpd(xmm0, mem(rcx)) \ vmovhpd(xmm0, mem(rcx, rsi, 1)) \ vmovlpd(xmm3, mem(rcx, rsi, 2)) \ vmovhpd(xmm3, mem(rcx, r13, 1)) #define CGEMM_INPUT_SCALE_RS_BETA_NZ \ vmovups(mem(rcx), ymm0) \ vpermilps(imm(0xb1), ymm0, ymm3) \ vmulps(ymm1, ymm0, ymm0) \ vmulps(ymm2, ymm3, ymm3) \ vaddsubps(ymm3, ymm0, ymm0) #define CGEMM_OUTPUT_RS \ vmovups(ymm0, mem(rcx)) \ #define CGEMM_INPUT_SCALE_RS_BETA_NZ_NEXT \ vmovups(mem(rcx, rsi, 8), ymm0) \ vpermilps(imm(0xb1), ymm0, ymm3) \ vmulps(ymm1, ymm0, ymm0) \ vmulps(ymm2, ymm3, ymm3) \ vaddsubps(ymm3, ymm0, ymm0) #define CGEMM_OUTPUT_RS_NEXT \ vmovups(ymm0, mem(rcx, rsi, 8)) \ void bli_cgemmsup_rv_zen_asm_2x8 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, scomplex* restrict alpha, scomplex* restrict a, inc_t rs_a0, inc_t cs_a0, scomplex* restrict b, inc_t rs_b0, inc_t cs_b0, scomplex* restrict beta, scomplex* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* data, cntx_t* cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() mov(var(a), r14) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(dt) lea(mem(, r9, 8), r9) // cs_a *= sizeof(dt) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(rs_b), r10) // load rs_b lea(mem(, r10, 8), r10) // rs_b *= sizeof(dt) mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(dt) mov(var(b), rbx) // load address of b. //mov(r12, rcx) // reset rcx to current utile of c. mov(r14, rax) // reset rax to current upanel of a. vzeroall() // zero all xmm/ymm registers. cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored pre-fetching on c // not used lea(mem(r12, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; jmp(.SPOSTPFETCH) // jump to end of pre-fetching c label(.SCOLPFETCH) // column-stored pre-fetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(dt) lea(mem(r12, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; lea(mem(rdx, rsi, 2), rdx) // rdx = c + 5*cs_c; label(.SPOSTPFETCH) // done prefetching c lea(mem(r9, r9, 2), rcx) // rcx = 3*cs_a; lea(mem(rax, r8, 4), rdx) // use rdx for pre-fetching lines lea(mem(rdx, r8, 2), rdx) // from next upanel of a. mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vbroadcastss(mem(rax, r8, 1), ymm2) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vbroadcastss(mem(rax, 4), ymm3) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 1, 4), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) add(r9, rax) // a += cs_a; // ---------------------------------- iteration 1 vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vbroadcastss(mem(rax, r8, 1), ymm2) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vbroadcastss(mem(rax, 4), ymm3) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 1, 4), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) add(r9, rax) // a += cs_a; // ---------------------------------- iteration 2 vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vbroadcastss(mem(rax, r8, 1), ymm2) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vbroadcastss(mem(rax, 4), ymm3) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 1, 4), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) add(r9, rax) // a += cs_a; // ---------------------------------- iteration 3 lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vbroadcastss(mem(rax, r8, 1), ymm2) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vbroadcastss(mem(rax, 4), ymm3) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 1, 4), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) add(r9, rax) // a += cs_a; dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vbroadcastss(mem(rax, r8, 1), ymm2) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vbroadcastss(mem(rax, 4), ymm3) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 1, 4), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) add(r9, rax) // a += cs_a; dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(r12, rcx) // reset rcx to current utile of c. // permute even and odd elements // of ymm6/7, ymm10/11 vpermilps(imm(0xb1), ymm6, ymm6) vpermilps(imm(0xb1), ymm7, ymm7) vpermilps(imm(0xb1), ymm10, ymm10) vpermilps(imm(0xb1), ymm11, ymm11) // subtract/add even/odd elements vaddsubps(ymm6, ymm4, ymm4) vaddsubps(ymm7, ymm5, ymm5) vaddsubps(ymm10, ymm8, ymm8) vaddsubps(ymm11, ymm9, ymm9) /* (ar + ai) x AB */ mov(var(alpha), rax) // load address of alpha vbroadcastss(mem(rax), ymm0) // load alpha_r and duplicate vbroadcastss(mem(rax, 4), ymm1) // load alpha_i and duplicate vpermilps(imm(0xb1), ymm4, ymm3) vmulps(ymm0, ymm4, ymm4) vmulps(ymm1, ymm3, ymm3) vaddsubps(ymm3, ymm4, ymm4) vpermilps(imm(0xb1), ymm5, ymm3) vmulps(ymm0, ymm5, ymm5) vmulps(ymm1, ymm3, ymm3) vaddsubps(ymm3, ymm5, ymm5) vpermilps(imm(0xb1), ymm8, ymm3) vmulps(ymm0, ymm8, ymm8) vmulps(ymm1, ymm3, ymm3) vaddsubps(ymm3, ymm8, ymm8) vpermilps(imm(0xb1), ymm9, ymm3) vmulps(ymm0, ymm9, ymm9) vmulps(ymm1, ymm3, ymm3) vaddsubps(ymm3, ymm9, ymm9) /* (ßr + ßi)x C + ((ar + ai) x AB) */ mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rbx), ymm1) // load beta_r and duplicate vbroadcastss(mem(rbx, 4), ymm2) // load beta_i and duplicate mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(dt) lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm1) // set ZF if beta_r == 0. sete(r13b) // r13b = ( ZF == 1 ? 1 : 0 ); vucomiss(xmm0, xmm2) // set ZF if beta_i == 0. sete(r15b) // r15b = ( ZF == 1 ? 1 : 0 ); and(r13b, r15b) // set ZF if r13b & r15b == 1. jne(.SBETAZERO) // if ZF = 1, jump to beta == 0 case lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) CGEMM_INPUT_SCALE_RS_BETA_NZ vaddps(ymm4, ymm0, ymm0) CGEMM_OUTPUT_RS CGEMM_INPUT_SCALE_RS_BETA_NZ_NEXT vaddps(ymm5, ymm0, ymm0) CGEMM_OUTPUT_RS_NEXT add(rdi, rcx) // rcx = c + 1*rs_c CGEMM_INPUT_SCALE_RS_BETA_NZ vaddps(ymm8, ymm0, ymm0) CGEMM_OUTPUT_RS CGEMM_INPUT_SCALE_RS_BETA_NZ_NEXT vaddps(ymm9, ymm0, ymm0) CGEMM_OUTPUT_RS_NEXT add(rdi, rcx) // rcx = c + 2*rs_c jmp(.SDONE) // jump to end. label(.SCOLSTORED) /*|----------------| |-------| | | | | | | 2x4 | 2x4 | | 4x2 | | | | |-------| |----------------| | | | 4x2 | |-------| */ mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(dt) lea(mem(rsi, rsi, 2), r13) // r13 = 3*rs_a CGEMM_INPUT_SCALE_CS_BETA_NZ vaddps(ymm4, ymm0, ymm4) add(rdi, rcx) CGEMM_INPUT_SCALE_CS_BETA_NZ vaddps(ymm8, ymm0, ymm8) add(rdi, rcx) lea(mem(r12, rsi, 4), rcx) CGEMM_INPUT_SCALE_CS_BETA_NZ vaddps(ymm5, ymm0, ymm5) add(rdi, rcx) CGEMM_INPUT_SCALE_CS_BETA_NZ vaddps(ymm9, ymm0, ymm9) add(rdi, rcx) mov(r12, rcx) // reset rcx to current utile of c. vunpcklpd(ymm8, ymm4, ymm0) //a0a1b0b1 a4a4b4b5 //gamma00-10 gamma02-12 vunpckhpd(ymm8, ymm4, ymm2) //a2a3b2b3 a6a7b6b7 //gamma01-11 gamma03-13 /******************Transpose top tile 4x3***************************/ vmovups(xmm0, mem(rcx)) // store (gamma00-10) lea(mem(rcx, rsi, 1), rcx) vmovups(xmm2, mem(rcx)) // store (gamma01-11) lea(mem(rcx, rsi, 1), rcx) vextractf128(imm(0x1), ymm0, xmm0) vextractf128(imm(0x1), ymm2, xmm2) vmovups(xmm0, mem(rcx)) // store (gamma02-12) lea(mem(rcx, rsi, 1), rcx) vmovups(xmm2, mem(rcx)) // store (gamma03-13) lea(mem(rcx, rsi, 1), rcx) /******************Transpose bottom tile 4x3***************************/ vunpcklpd(ymm9, ymm5, ymm0) //a8a9b8b9 a12a13b12b13 //gamma04-14 gamma06-16 vunpckhpd(ymm9, ymm5, ymm2) //a10a11b10b11 a14a15b14b15 //gamma05-15 gamma07-17 vmovups(xmm0, mem(rcx)) // store (gamma04-14) lea(mem(rcx, rsi, 1), rcx) vmovups(xmm2, mem(rcx)) // store (gamma05-15) lea(mem(rcx, rsi, 1), rcx) vextractf128(imm(0x1), ymm0, xmm0) vextractf128(imm(0x1), ymm2, xmm2) vmovups(xmm0, mem(rcx)) // store (gamma06-16) lea(mem(rcx, rsi, 1), rcx) vmovups(xmm2, mem(rcx)) // store (gamma07-17) jmp(.SDONE) // jump to end. label(.SBETAZERO) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovups(ymm4, mem(rcx)) vmovups(ymm5, mem(rcx, rsi, 8)) add(rdi, rcx) vmovups(ymm8, mem(rcx)) vmovups(ymm9, mem(rcx, rsi, 8)) add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) /****2x8 tile going to save into 8x2 tile in C*****/ mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(dt) vunpcklpd(ymm8, ymm4, ymm0) //a0a1b0b1 a4a4b4b5 vunpckhpd(ymm8, ymm4, ymm2) //a2a3b2b3 a6a7b6b7 /******************Transpose top tile 4x2***************************/ vmovups(xmm0, mem(rcx)) lea(mem(rcx, rsi, 1), rcx) vmovups(xmm2, mem(rcx)) lea(mem(rcx, rsi, 1), rcx) vextractf128(imm(0x1), ymm0, xmm0) vextractf128(imm(0x1), ymm2, xmm2) vmovups(xmm0, mem(rcx)) lea(mem(rcx, rsi, 1), rcx) vmovups(xmm2, mem(rcx)) lea(mem(rcx, rsi, 1), rcx) /******************Transpose bottom tile 4x2***************************/ vunpcklpd(ymm9, ymm5, ymm0) //a8a9b8b9 a12a13b12b13 vunpckhpd(ymm9, ymm5, ymm2) //a10a11b10b11 a14a15b14b15 vmovups(xmm0, mem(rcx)) lea(mem(rcx, rsi, 1), rcx) vmovups(xmm2, mem(rcx)) lea(mem(rcx, rsi, 1), rcx) vextractf128(imm(0x1), ymm0, xmm0) vextractf128(imm(0x1), ymm2, xmm2) vmovups(xmm0, mem(rcx)) lea(mem(rcx, rsi, 1), rcx) vmovups(xmm2, mem(rcx)) label(.SDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_cgemmsup_rv_zen_asm_1x8 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, scomplex* restrict alpha, scomplex* restrict a, inc_t rs_a0, inc_t cs_a0, scomplex* restrict b, inc_t rs_b0, inc_t cs_b0, scomplex* restrict beta, scomplex* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* data, cntx_t* cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() mov(var(a), r14) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(dt) lea(mem(, r9, 8), r9) // cs_a *= sizeof(dt) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(rs_b), r10) // load rs_b lea(mem(, r10, 8), r10) // rs_b *= sizeof(dt) mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(dt) mov(var(b), rbx) // load address of b. //mov(r12, rcx) // reset rcx to current utile of c. mov(r14, rax) // reset rax to current upanel of a. vzeroall() // zero all xmm/ymm registers. cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored pre-fetching on c // not used lea(mem(r12, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; jmp(.SPOSTPFETCH) // jump to end of pre-fetching c label(.SCOLPFETCH) // column-stored pre-fetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(dt) lea(mem(r12, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; lea(mem(rdx, rsi, 2), rdx) // rdx = c + 5*cs_c; label(.SPOSTPFETCH) // done prefetching c lea(mem(r9, r9, 2), rcx) // rcx = 3*cs_a; lea(mem(rax, r8, 4), rdx) // use rdx for pre-fetching lines lea(mem(rdx, r8, 2), rdx) // from next upanel of a. mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vbroadcastss(mem(rax, 4), ymm3) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) add(r9, rax) // a += cs_a; // ---------------------------------- iteration 1 vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vbroadcastss(mem(rax, 4), ymm3) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) add(r9, rax) // a += cs_a; // ---------------------------------- iteration 2 vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vbroadcastss(mem(rax, 4), ymm3) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) add(r9, rax) // a += cs_a; // ---------------------------------- iteration 3 lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vbroadcastss(mem(rax, 4), ymm3) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) add(r9, rax) // a += cs_a; dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vbroadcastss(mem(rax, 4), ymm3) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) add(r9, rax) // a += cs_a; dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(r12, rcx) // reset rcx to current utile of c. // permute even and odd elements // of ymm6/7 vpermilps(imm(0xb1), ymm6, ymm6) vpermilps(imm(0xb1), ymm7, ymm7) // subtract/add even/odd elements vaddsubps(ymm6, ymm4, ymm4) vaddsubps(ymm7, ymm5, ymm5) /* (ar + ai) x AB */ mov(var(alpha), rax) // load address of alpha vbroadcastss(mem(rax), ymm0) // load alpha_r and duplicate vbroadcastss(mem(rax, 4), ymm1) // load alpha_i and duplicate vpermilps(imm(0xb1), ymm4, ymm3) vmulps(ymm0, ymm4, ymm4) vmulps(ymm1, ymm3, ymm3) vaddsubps(ymm3, ymm4, ymm4) vpermilps(imm(0xb1), ymm5, ymm3) vmulps(ymm0, ymm5, ymm5) vmulps(ymm1, ymm3, ymm3) vaddsubps(ymm3, ymm5, ymm5) /* (ßr + ßi)x C + ((ar + ai) x AB) */ mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rbx), ymm1) // load beta_r and duplicate vbroadcastss(mem(rbx, 4), ymm2) // load beta_i and duplicate mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(dt) lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm1) // set ZF if beta_r == 0. sete(r13b) // r13b = ( ZF == 1 ? 1 : 0 ); vucomiss(xmm0, xmm2) // set ZF if beta_i == 0. sete(r15b) // r15b = ( ZF == 1 ? 1 : 0 ); and(r13b, r15b) // set ZF if r13b & r15b == 1. jne(.SBETAZERO) // if ZF = 1, jump to beta == 0 case lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) CGEMM_INPUT_SCALE_RS_BETA_NZ vaddps(ymm4, ymm0, ymm0) CGEMM_OUTPUT_RS CGEMM_INPUT_SCALE_RS_BETA_NZ_NEXT vaddps(ymm5, ymm0, ymm0) CGEMM_OUTPUT_RS_NEXT add(rdi, rcx) // rcx = c + 1*rs_c jmp(.SDONE) // jump to end. label(.SCOLSTORED) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(dt) lea(mem(rsi, rsi, 2), r13) // r13 = 3*rs_a CGEMM_INPUT_SCALE_CS_BETA_NZ vaddps(ymm4, ymm0, ymm4) lea(mem(r12, rsi, 4), rcx) CGEMM_INPUT_SCALE_CS_BETA_NZ vaddps(ymm5, ymm0, ymm5) mov(r12, rcx) // reset rcx to current utile of c. /******************Transpose top tile 4x1***************************/ vmovlpd(xmm4, mem(rcx)) // store (gamma40) lea(mem(rcx, rsi, 1), rcx) vmovhpd(xmm4, mem(rcx)) // store (gamma41) lea(mem(rcx, rsi, 1), rcx) vextractf128(imm(0x1), ymm4, xmm4) vmovlpd(xmm4, mem(rcx)) // store (gamma42) lea(mem(rcx, rsi, 1), rcx) vmovhpd(xmm4, mem(rcx)) // store (gamma43) lea(mem(rcx, rsi, 1), rcx) /******************Transpose bottom tile 4x1***************************/ vmovlpd(xmm5, mem(rcx)) // store (gamma44) lea(mem(rcx, rsi, 1), rcx) vmovhpd(xmm5, mem(rcx)) // store (gamma45) lea(mem(rcx, rsi, 1), rcx) vextractf128(imm(0x1), ymm5, xmm5) vmovlpd(xmm5, mem(rcx)) // store (gamma46) lea(mem(rcx, rsi, 1), rcx) vmovhpd(xmm5, mem(rcx)) // store (gamma47) jmp(.SDONE) // jump to end. label(.SBETAZERO) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovups(ymm4, mem(rcx)) vmovups(ymm5, mem(rcx, rsi, 8)) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) /****1x8 tile going to save into 8x1 tile in C*****/ mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(dt) /******************Transpose top tile 4x1***************************/ vmovlpd(xmm4, mem(rcx)) // store (gamma40) lea(mem(rcx, rsi, 1), rcx) vmovhpd(xmm4, mem(rcx)) // store (gamma41) lea(mem(rcx, rsi, 1), rcx) vextractf128(imm(0x1), ymm4, xmm4) vmovlpd(xmm4, mem(rcx)) // store (gamma42) lea(mem(rcx, rsi, 1), rcx) vmovhpd(xmm4, mem(rcx)) // store (gamma43) lea(mem(rcx, rsi, 1), rcx) /******************Transpose bottom tile 4x1***************************/ vmovlpd(xmm5, mem(rcx)) // store (gamma44) lea(mem(rcx, rsi, 1), rcx) vmovhpd(xmm5, mem(rcx)) // store (gamma45) lea(mem(rcx, rsi, 1), rcx) vextractf128(imm(0x1), ymm5, xmm5) vmovlpd(xmm5, mem(rcx)) // store (gamma46) lea(mem(rcx, rsi, 1), rcx) vmovhpd(xmm5, mem(rcx)) // store (gamma47) label(.SDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_cgemmsup_rv_zen_asm_2x4 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, scomplex* restrict alpha, scomplex* restrict a, inc_t rs_a0, inc_t cs_a0, scomplex* restrict b, inc_t rs_b0, inc_t cs_b0, scomplex* restrict beta, scomplex* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* data, cntx_t* cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t m_iter = m0 / 3; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() mov(var(a), r14) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(dt) lea(mem(, r9, 8), r9) // cs_a *= sizeof(dt) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(rs_b), r10) // load rs_b lea(mem(, r10, 8), r10) // rs_b *= sizeof(dt) mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(dt) // During preamble and loops: // r12 = rcx = c // r14 = rax = a // read rbx from var(b) near beginning of loop // r11 = m dim index ii mov(var(m_iter), r11) // ii = m_iter; label(.SLOOP3X8I) // LOOP OVER ii = [ m_iter ... 1 0 ] vzeroall() // zero all xmm/ymm registers. mov(var(b), rbx) // load address of b. //mov(r12, rcx) // reset rcx to current utile of c. mov(r14, rax) // reset rax to current upanel of a. cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored pre-fetching on c // not used lea(mem(r12, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; jmp(.SPOSTPFETCH) // jump to end of pre-fetching c label(.SCOLPFETCH) // column-stored pre-fetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(dt) lea(mem(r12, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; label(.SPOSTPFETCH) // done prefetching c lea(mem(r9, r9, 2), rcx) // rcx = 3*cs_a; lea(mem(rax, r8, 4), rdx) // use rdx for pre-fetching lines lea(mem(rdx, r8, 2), rdx) // from next upanel of a. mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 vmovups(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vfmadd231ps(ymm0, ymm2, ymm4) vbroadcastss(mem(rax, r8, 1), ymm2) vfmadd231ps(ymm0, ymm2, ymm8) vbroadcastss(mem(rax, 4), ymm3) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 1, 4), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) add(r9, rax) // a += cs_a; // ---------------------------------- iteration 1 vmovups(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vfmadd231ps(ymm0, ymm2, ymm4) vbroadcastss(mem(rax, r8, 1), ymm2) vfmadd231ps(ymm0, ymm2, ymm8) vbroadcastss(mem(rax, 4), ymm3) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 1, 4), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) add(r9, rax) // a += cs_a; // ---------------------------------- iteration 2 vmovups(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vfmadd231ps(ymm0, ymm2, ymm4) vbroadcastss(mem(rax, r8, 1), ymm2) vfmadd231ps(ymm0, ymm2, ymm8) vbroadcastss(mem(rax, 4), ymm3) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 1, 4), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) add(r9, rax) // a += cs_a; // ---------------------------------- iteration 3 lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; vmovups(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vfmadd231ps(ymm0, ymm2, ymm4) vbroadcastss(mem(rax, r8, 1), ymm2) vfmadd231ps(ymm0, ymm2, ymm8) vbroadcastss(mem(rax, 4), ymm3) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 1, 4), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) add(r9, rax) // a += cs_a; dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP vmovups(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vfmadd231ps(ymm0, ymm2, ymm4) vbroadcastss(mem(rax, r8, 1), ymm2) vfmadd231ps(ymm0, ymm2, ymm8) vbroadcastss(mem(rax, 4), ymm3) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 1, 4), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) add(r9, rax) // a += cs_a; dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(r12, rcx) // reset rcx to current utile of c. // permute even and odd elements // of ymm6/7 vpermilps(imm(0xb1), ymm6, ymm6) vpermilps(imm(0xb1), ymm10, ymm10) // subtract/add even/odd elements vaddsubps(ymm6, ymm4, ymm4) vaddsubps(ymm10, ymm8, ymm8) /* (ar + ai) x AB */ mov(var(alpha), rax) // load address of alpha vbroadcastss(mem(rax), ymm0) // load alpha_r and duplicate vbroadcastss(mem(rax, 4), ymm1) // load alpha_i and duplicate vpermilps(imm(0xb1), ymm4, ymm3) vmulps(ymm0, ymm4, ymm4) vmulps(ymm1, ymm3, ymm3) vaddsubps(ymm3, ymm4, ymm4) vpermilps(imm(0xb1), ymm8, ymm3) vmulps(ymm0, ymm8, ymm8) vmulps(ymm1, ymm3, ymm3) vaddsubps(ymm3, ymm8, ymm8) /* (ßr + ßi)x C + ((ar + ai) x AB) */ mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rbx), ymm1) // load beta_r and duplicate vbroadcastss(mem(rbx, 4), ymm2) // load beta_i and duplicate mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(dt) lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm1) // set ZF if beta_r == 0. sete(r13b) // r13b = ( ZF == 1 ? 1 : 0 ); vucomiss(xmm0, xmm2) // set ZF if beta_i == 0. sete(r15b) // r15b = ( ZF == 1 ? 1 : 0 ); and(r13b, r15b) // set ZF if r13b & r15b == 1. jne(.SBETAZERO) // if ZF = 1, jump to beta == 0 case lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) CGEMM_INPUT_SCALE_RS_BETA_NZ vaddps(ymm4, ymm0, ymm0) CGEMM_OUTPUT_RS add(rdi, rcx) // rcx = c + 1*rs_c CGEMM_INPUT_SCALE_RS_BETA_NZ vaddps(ymm8, ymm0, ymm0) CGEMM_OUTPUT_RS jmp(.SDONE) // jump to end. label(.SCOLSTORED) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(dt) lea(mem(rsi, rsi, 2), r13) // r13 = 3*rs_a CGEMM_INPUT_SCALE_CS_BETA_NZ vaddps(ymm4, ymm0, ymm4) add(rdi, rcx) CGEMM_INPUT_SCALE_CS_BETA_NZ vaddps(ymm8, ymm0, ymm8) mov(r12, rcx) // reset rcx to current utile of c. vunpcklpd(ymm8, ymm4, ymm0) //a0a1b0b1 a4a4b4b5 //gamma00-10 gamma02-12 vunpckhpd(ymm8, ymm4, ymm2) //a2a3b2b3 a6a7b6b7 //gamma01-11 gamma03-13 /******************Transpose top tile 4x2***************************/ vmovups(xmm0, mem(rcx)) // store (gamma00-10) lea(mem(rcx, rsi, 1), rcx) vmovups(xmm2, mem(rcx)) // store (gamma01-11) lea(mem(rcx, rsi, 1), rcx) vextractf128(imm(0x1), ymm0, xmm0) vextractf128(imm(0x1), ymm2, xmm2) vmovups(xmm0, mem(rcx)) // store (gamma02-12) lea(mem(rcx, rsi, 1), rcx) vmovups(xmm2, mem(rcx)) // store (gamma03-13) lea(mem(rcx, rsi, 1), rcx) jmp(.SDONE) // jump to end. label(.SBETAZERO) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovups(ymm4, mem(rcx)) add(rdi, rcx) vmovups(ymm8, mem(rcx)) add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) /****2x4 tile going to save into 4x2 tile in C*****/ mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(dt) vunpcklpd(ymm8, ymm4, ymm0) //a0a1b0b1 a4a4b4b5 //gamma00-10 gamma02-12 vunpckhpd(ymm8, ymm4, ymm2) //a2a3b2b3 a6a7b6b7 //gamma01-11 gamma03-13 /******************Transpose top tile 4x3***************************/ vmovups(xmm0, mem(rcx)) // store (gamma00-10) lea(mem(rcx, rsi, 1), rcx) vmovups(xmm2, mem(rcx)) // store (gamma01-11) lea(mem(rcx, rsi, 1), rcx) vextractf128(imm(0x1), ymm0, xmm0) vextractf128(imm(0x1), ymm2, xmm2) vmovups(xmm0, mem(rcx)) // store (gamma02-12) lea(mem(rcx, rsi, 1), rcx) vmovups(xmm2, mem(rcx)) // store (gamma03-13) label(.SDONE) end_asm( : // output operands (none) : // input operands [m_iter] "m" (m_iter), [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_cgemmsup_rv_zen_asm_1x4 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, scomplex* restrict alpha, scomplex* restrict a, inc_t rs_a0, inc_t cs_a0, scomplex* restrict b, inc_t rs_b0, inc_t cs_b0, scomplex* restrict beta, scomplex* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* data, cntx_t* cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t m_iter = m0 / 3; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() mov(var(a), r14) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(dt) lea(mem(, r9, 8), r9) // cs_a *= sizeof(dt) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(rs_b), r10) // load rs_b lea(mem(, r10, 8), r10) // rs_b *= sizeof(dt) mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(dt) // During preamble and loops: // r12 = rcx = c // r14 = rax = a // read rbx from var(b) near beginning of loop // r11 = m dim index ii mov(var(m_iter), r11) // ii = m_iter; label(.SLOOP3X8I) // LOOP OVER ii = [ m_iter ... 1 0 ] vxorps(ymm4, ymm4, ymm4) vxorps(ymm6, ymm6, ymm6) vxorps(ymm8, ymm8, ymm8) vxorps(ymm10, ymm10, ymm10) mov(var(b), rbx) // load address of b. //mov(r12, rcx) // reset rcx to current utile of c. mov(r14, rax) // reset rax to current upanel of a. cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored pre-fetching on c // not used lea(mem(r12, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; jmp(.SPOSTPFETCH) // jump to end of pre-fetching c label(.SCOLPFETCH) // column-stored pre-fetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(dt) lea(mem(r12, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; label(.SPOSTPFETCH) // done prefetching c lea(mem(r9, r9, 2), rcx) // rcx = 3*cs_a; lea(mem(rax, r8, 4), rdx) // use rdx for pre-fetching lines lea(mem(rdx, r8, 2), rdx) // from next upanel of a. mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 vmovups(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vfmadd231ps(ymm0, ymm2, ymm4) vbroadcastss(mem(rax, 4), ymm3) vfmadd231ps(ymm0, ymm3, ymm6) add(r9, rax) // a += cs_a; // ---------------------------------- iteration 1 vmovups(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vfmadd231ps(ymm0, ymm2, ymm4) vbroadcastss(mem(rax, 4), ymm3) vfmadd231ps(ymm0, ymm3, ymm6) add(r9, rax) // a += cs_a; // ---------------------------------- iteration 2 vmovups(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vfmadd231ps(ymm0, ymm2, ymm4) vbroadcastss(mem(rax, 4), ymm3) vfmadd231ps(ymm0, ymm3, ymm6) add(r9, rax) // a += cs_a; // ---------------------------------- iteration 3 lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; vmovups(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vfmadd231ps(ymm0, ymm2, ymm4) vbroadcastss(mem(rax, 4), ymm3) vfmadd231ps(ymm0, ymm3, ymm6) add(r9, rax) // a += cs_a; dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP vmovups(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vfmadd231ps(ymm0, ymm2, ymm4) vbroadcastss(mem(rax, 4), ymm3) vfmadd231ps(ymm0, ymm3, ymm6) add(r9, rax) // a += cs_a; dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(r12, rcx) // reset rcx to current utile of c. // permute even and odd elements // of ymm6/7, ymm10/11, ymm/14/15 vpermilps(imm(0xb1), ymm6, ymm6) // subtract/add even/odd elements vaddsubps(ymm6, ymm4, ymm4) /* (ar + ai) x AB */ mov(var(alpha), rax) // load address of alpha vbroadcastss(mem(rax), ymm0) // load alpha_r and duplicate vbroadcastss(mem(rax, 4), ymm1) // load alpha_i and duplicate vpermilps(imm(0xb1), ymm4, ymm3) vmulps(ymm0, ymm4, ymm4) vmulps(ymm1, ymm3, ymm3) vaddsubps(ymm3, ymm4, ymm4) /* (ßr + ßi)x C + ((ar + ai) x AB) */ mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rbx), ymm1) // load beta_r and duplicate vbroadcastss(mem(rbx, 4), ymm2) // load beta_i and duplicate mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(dt) lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm1) // set ZF if beta_r == 0. sete(r13b) // r13b = ( ZF == 1 ? 1 : 0 ); vucomiss(xmm0, xmm2) // set ZF if beta_i == 0. sete(r15b) // r15b = ( ZF == 1 ? 1 : 0 ); and(r13b, r15b) // set ZF if r13b & r15b == 1. jne(.SBETAZERO) // if ZF = 1, jump to beta == 0 case lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) CGEMM_INPUT_SCALE_RS_BETA_NZ vaddps(ymm4, ymm0, ymm0) CGEMM_OUTPUT_RS jmp(.SDONE) // jump to end. label(.SCOLSTORED) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(dt) lea(mem(rsi, rsi, 2), r13) // r13 = 3*rs_a CGEMM_INPUT_SCALE_CS_BETA_NZ vaddps(ymm4, ymm0, ymm4) mov(r12, rcx) // reset rcx to current utile of c. vmovlpd(xmm4, mem(rcx)) // store (gamma00-10) lea(mem(rcx, rsi, 1), rcx) vmovhpd(xmm4, mem(rcx)) // store (gamma01-11) lea(mem(rcx, rsi, 1), rcx) vextractf128(imm(0x1), ymm4, xmm4) vmovlpd(xmm4, mem(rcx)) // store (gamma02-12) lea(mem(rcx, rsi, 1), rcx) vmovhpd(xmm4, mem(rcx)) // store (gamma03-13) jmp(.SDONE) // jump to end. label(.SBETAZERO) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovups(ymm4, mem(rcx)) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) /****1x4 tile going to save into 4x1 tile in C*****/ mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(dt) vmovlpd(xmm4, mem(rcx)) // store (gamma40) lea(mem(rcx, rsi, 1), rcx) vmovhpd(xmm4, mem(rcx)) // store (gamma41) lea(mem(rcx, rsi, 1), rcx) vextractf128(imm(0x1), ymm4, xmm4) vmovlpd(xmm4, mem(rcx)) // store (gamma42) lea(mem(rcx, rsi, 1), rcx) vmovhpd(xmm4, mem(rcx)) // store (gamma43) lea(mem(rcx, rsi, 1), rcx) label(.SDONE) end_asm( : // output operands (none) : // input operands [m_iter] "m" (m_iter), [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_cgemmsup_rv_zen_asm_2x2 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, scomplex* restrict alpha, scomplex* restrict a, inc_t rs_a0, inc_t cs_a0, scomplex* restrict b, inc_t rs_b0, inc_t cs_b0, scomplex* restrict beta, scomplex* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* data, cntx_t* cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t m_iter = m0 / 3; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() mov(var(a), r14) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(dt) lea(mem(, r9, 8), r9) // cs_a *= sizeof(dt) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(rs_b), r10) // load rs_b lea(mem(, r10, 8), r10) // rs_b *= sizeof(dt) mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(dt) // During preamble and loops: // r12 = rcx = c // r14 = rax = a // read rbx from var(b) near beginning of loop // r11 = m dim index ii mov(var(m_iter), r11) // ii = m_iter; label(.SLOOP3X8I) // LOOP OVER ii = [ m_iter ... 1 0 ] vxorps(xmm4, xmm4, xmm4) vxorps(xmm6, xmm6, xmm6) vxorps(xmm8, xmm8, xmm8) vxorps(xmm10, xmm10, xmm10) vxorps(xmm12, xmm12, xmm12) vxorps(xmm14, xmm14, xmm14) mov(var(b), rbx) // load address of b. //mov(r12, rcx) // reset rcx to current utile of c. mov(r14, rax) // reset rax to current upanel of a. cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored pre-fetching on c // not used lea(mem(r12, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; jmp(.SPOSTPFETCH) // jump to end of pre-fetching c label(.SCOLPFETCH) // column-stored pre-fetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(dt) lea(mem(r12, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; label(.SPOSTPFETCH) // done prefetching c lea(mem(r9, r9, 2), rcx) // rcx = 3*cs_a; lea(mem(rax, r8, 4), rdx) // use rdx for pre-fetching lines lea(mem(rdx, r8, 2), rdx) // from next upanel of a. mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vfmadd231ps(xmm0, xmm2, xmm4) vbroadcastss(mem(rax, r8, 1), xmm2) vfmadd231ps(xmm0, xmm2, xmm8) vbroadcastss(mem(rax, 4), xmm3) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 1, 4), xmm3) vfmadd231ps(xmm0, xmm3, xmm10) add(r9, rax) // a += cs_a; // ---------------------------------- iteration 1 vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vfmadd231ps(xmm0, xmm2, xmm4) vbroadcastss(mem(rax, r8, 1), xmm2) vfmadd231ps(xmm0, xmm2, xmm8) vbroadcastss(mem(rax, 4), xmm3) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 1, 4), xmm3) vfmadd231ps(xmm0, xmm3, xmm10) add(r9, rax) // a += cs_a; // ---------------------------------- iteration 2 vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vfmadd231ps(xmm0, xmm2, xmm4) vbroadcastss(mem(rax, r8, 1), xmm2) vfmadd231ps(xmm0, xmm2, xmm8) vbroadcastss(mem(rax, 4), xmm3) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 1, 4), xmm3) vfmadd231ps(xmm0, xmm3, xmm10) add(r9, rax) // a += cs_a; // ---------------------------------- iteration 3 lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vfmadd231ps(xmm0, xmm2, xmm4) vbroadcastss(mem(rax, r8, 1), xmm2) vfmadd231ps(xmm0, xmm2, xmm8) vbroadcastss(mem(rax, 4), xmm3) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 1, 4), xmm3) vfmadd231ps(xmm0, xmm3, xmm10) add(r9, rax) // a += cs_a; dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vfmadd231ps(xmm0, xmm2, xmm4) vbroadcastss(mem(rax, r8, 1), xmm2) vfmadd231ps(xmm0, xmm2, xmm8) vbroadcastss(mem(rax, 4), xmm3) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 1, 4), xmm3) vfmadd231ps(xmm0, xmm3, xmm10) add(r9, rax) // a += cs_a; dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(r12, rcx) // reset rcx to current utile of c. // permute even and odd elements // of xmm6/7 vpermilps(imm(0xb1), xmm6, xmm6) vpermilps(imm(0xb1), xmm10, xmm10) // subtract/add even/odd elements vaddsubps(xmm6, xmm4, xmm4) vaddsubps(xmm10, xmm8, xmm8) /* (ar + ai) x AB */ mov(var(alpha), rax) // load address of alpha vbroadcastss(mem(rax), xmm0) // load alpha_r and duplicate vbroadcastss(mem(rax, 4), xmm1) // load alpha_i and duplicate vpermilps(imm(0xb1), xmm4, xmm3) vmulps(xmm0, xmm4, xmm4) vmulps(xmm1, xmm3, xmm3) vaddsubps(xmm3, xmm4, xmm4) vpermilps(imm(0xb1), xmm8, xmm3) vmulps(xmm0, xmm8, xmm8) vmulps(xmm1, xmm3, xmm3) vaddsubps(xmm3, xmm8, xmm8) /* (ßr + ßi)x C + ((ar + ai) x AB) */ mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rbx), xmm1) // load beta_r and duplicate vbroadcastss(mem(rbx, 4), xmm2) // load beta_i and duplicate mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(dt) lea(mem(rcx, rdi, 2), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorps(xmm0, xmm0, xmm0) // set xmm0 to zero. vucomiss(xmm0, xmm1) // set ZF if beta_r == 0. sete(r13b) // r13b = ( ZF == 1 ? 1 : 0 ); vucomiss(xmm0, xmm2) // set ZF if beta_i == 0. sete(r15b) // r15b = ( ZF == 1 ? 1 : 0 ); and(r13b, r15b) // set ZF if r13b & r15b == 1. jne(.SBETAZERO) // if ZF = 1, jump to beta == 0 case lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vmovlpd(mem(rcx), xmm0, xmm0) vmovhpd(mem(rcx, rsi, 1), xmm0, xmm0) vpermilps(imm(0xb1), xmm0, xmm3) vmulps(xmm1, xmm0, xmm0) vmulps(xmm2, xmm3, xmm3) vaddsubps(xmm3, xmm0, xmm0) vaddps(xmm4, xmm0, xmm0) vmovlpd(xmm0, mem(rcx)) vmovhpd(xmm0, mem(rcx, rsi, 1)) add(rdi, rcx) // rcx = c + 1*rs_c vmovlpd(mem(rcx), xmm0, xmm0) vmovhpd(mem(rcx, rsi, 1), xmm0, xmm0) vpermilps(imm(0xb1), xmm0, xmm3) vmulps(xmm1, xmm0, xmm0) vmulps(xmm2, xmm3, xmm3) vaddsubps(xmm3, xmm0, xmm0) vaddps(xmm8, xmm0, xmm0) vmovlpd(xmm0, mem(rcx)) vmovhpd(xmm0, mem(rcx, rsi, 1)) jmp(.SDONE) // jump to end. label(.SCOLSTORED) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(dt) lea(mem(rsi, rsi, 2), r13) // r13 = 3*rs_a CGEMM_INPUT_SCALE_CS_BETA_NZ_128 vaddps(xmm4, xmm0, xmm4) add(rdi, rcx) CGEMM_INPUT_SCALE_CS_BETA_NZ_128 vaddps(xmm8, xmm0, xmm8) mov(r12, rcx) // reset rcx to current utile of c. vunpcklpd(xmm8, xmm4, xmm0) //a0a1b0b1 //gamma00-10 vunpckhpd(xmm8, xmm4, xmm2) //a2a3b2b3 //gamma01-11 /******************Transpose top tile 4x3***************************/ vmovups(xmm0, mem(rcx)) // store (gamma00-10) lea(mem(rcx, rsi, 1), rcx) vmovups(xmm2, mem(rcx)) // store (gamma01-11) jmp(.SDONE) // jump to end. label(.SBETAZERO) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovups(xmm4, mem(rcx)) add(rdi, rcx) vmovups(xmm8, mem(rcx)) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) /****2x2 tile going to save into 4x2 tile in C*****/ mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(dt) vunpcklpd(xmm8, xmm4, xmm0) //a0a1b0b1 //gamma00-10 vunpckhpd(xmm8, xmm4, xmm2) //a2a3b2b3 //gamma01-11 /******************Transpose top tile 2x2***************************/ vmovups(xmm0, mem(rcx)) // store (gamma00-10) lea(mem(rcx, rsi, 1), rcx) vmovups(xmm2, mem(rcx)) // store (gamma01-11) label(.SDONE) end_asm( : // output operands (none) : // input operands [m_iter] "m" (m_iter), [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_cgemmsup_rv_zen_asm_1x2 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, scomplex* restrict alpha, scomplex* restrict a, inc_t rs_a0, inc_t cs_a0, scomplex* restrict b, inc_t rs_b0, inc_t cs_b0, scomplex* restrict beta, scomplex* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* data, cntx_t* cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t m_iter = m0 / 3; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() mov(var(a), r14) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(dt) lea(mem(, r9, 8), r9) // cs_a *= sizeof(dt) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(rs_b), r10) // load rs_b lea(mem(, r10, 8), r10) // rs_b *= sizeof(dt) mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(dt) // During preamble and loops: // r12 = rcx = c // r14 = rax = a // read rbx from var(b) near beginning of loop // r11 = m dim index ii mov(var(m_iter), r11) // ii = m_iter; label(.SLOOP3X8I) // LOOP OVER ii = [ m_iter ... 1 0 ] vxorps(xmm4, xmm4, xmm4) vxorps(xmm6, xmm6, xmm6) vxorps(xmm8, xmm8, xmm8) vxorps(xmm10, xmm10, xmm10) vxorps(xmm12, xmm12, xmm12) vxorps(xmm14, xmm14, xmm14) mov(var(b), rbx) // load address of b. //mov(r12, rcx) // reset rcx to current utile of c. mov(r14, rax) // reset rax to current upanel of a. cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored pre-fetching on c // not used lea(mem(r12, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; jmp(.SPOSTPFETCH) // jump to end of pre-fetching c label(.SCOLPFETCH) // column-stored pre-fetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(dt) lea(mem(r12, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; label(.SPOSTPFETCH) // done prefetching c lea(mem(r9, r9, 2), rcx) // rcx = 3*cs_a; lea(mem(rax, r8, 4), rdx) // use rdx for pre-fetching lines lea(mem(rdx, r8, 2), rdx) // from next upanel of a. mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 vmovups(mem(rbx), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vfmadd231ps(xmm0, xmm2, xmm4) vbroadcastss(mem(rax, 4 ), xmm3) vfmadd231ps(xmm0, xmm3, xmm6) add(r9, rax) // a += cs_a; // ---------------------------------- iteration 1 vmovups(mem(rbx), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vfmadd231ps(xmm0, xmm2, xmm4) vbroadcastss(mem(rax, 4 ), xmm3) vfmadd231ps(xmm0, xmm3, xmm6) add(r9, rax) // a += cs_a; // ---------------------------------- iteration 2 vmovups(mem(rbx), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vfmadd231ps(xmm0, xmm2, xmm4) vbroadcastss(mem(rax, 4 ), xmm3) vfmadd231ps(xmm0, xmm3, xmm6) add(r9, rax) // a += cs_a; // ---------------------------------- iteration 3 lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; vmovups(mem(rbx), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vfmadd231ps(xmm0, xmm2, xmm4) vbroadcastss(mem(rax, 4 ), xmm3) vfmadd231ps(xmm0, xmm3, xmm6) add(r9, rax) // a += cs_a; dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP vmovups(mem(rbx), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vfmadd231ps(xmm0, xmm2, xmm4) vbroadcastss(mem(rax, 4 ), xmm3) vfmadd231ps(xmm0, xmm3, xmm6) add(r9, rax) // a += cs_a; dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(r12, rcx) // reset rcx to current utile of c. // permute even and odd elements // of xmm6 vpermilps(imm(0xb1), xmm6, xmm6) // subtract/add even/odd elements vaddsubps(xmm6, xmm4, xmm4) /* (ar + ai) x AB */ mov(var(alpha), rax) // load address of alpha vbroadcastss(mem(rax), xmm0) // load alpha_r and duplicate vbroadcastss(mem(rax, 4), xmm1) // load alpha_i and duplicate vpermilps(imm(0xb1), xmm4, xmm3) vmulps(xmm0, xmm4, xmm4) vmulps(xmm1, xmm3, xmm3) vaddsubps(xmm3, xmm4, xmm4) /* (ßr + ßi)x C + ((ar + ai) x AB) */ mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rbx), xmm1) // load beta_r and duplicate vbroadcastss(mem(rbx, 4), xmm2) // load beta_i and duplicate mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(dt) lea(mem(rcx, rdi, 2), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorps(xmm0, xmm0, xmm0) // set xmm0 to zero. vucomiss(xmm0, xmm1) // set ZF if beta_r == 0. sete(r13b) // r13b = ( ZF == 1 ? 1 : 0 ); vucomiss(xmm0, xmm2) // set ZF if beta_i == 0. sete(r15b) // r15b = ( ZF == 1 ? 1 : 0 ); and(r13b, r15b) // set ZF if r13b & r15b == 1. jne(.SBETAZERO) // if ZF = 1, jump to beta == 0 case lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vmovlpd(mem(rcx), xmm0, xmm0) vmovhpd(mem(rcx, rsi, 1), xmm0, xmm0) vpermilps(imm(0xb1), xmm0, xmm3) vmulps(xmm1, xmm0, xmm0) vmulps(xmm2, xmm3, xmm3) vaddsubps(xmm3, xmm0, xmm0) vaddps(xmm4, xmm0, xmm0) vmovlpd(xmm0, mem(rcx)) vmovhpd(xmm0, mem(rcx, rsi, 1)) jmp(.SDONE) // jump to end. label(.SCOLSTORED) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(dt) lea(mem(rsi, rsi, 2), r13) // r13 = 3*rs_a CGEMM_INPUT_SCALE_CS_BETA_NZ_128 vaddps(xmm4, xmm0, xmm4) mov(r12, rcx) // reset rcx to current utile of c. vmovlpd(xmm4, mem(rcx)) // store (gamma40-50) lea(mem(rcx, rsi, 1), rcx) vmovhpd(xmm4, mem(rcx)) // store (gamma41-51) jmp(.SDONE) // jump to end. label(.SBETAZERO) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovups(xmm4, mem(rcx)) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) /****1x2 tile going to save into 2x1 tile in C*****/ mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(dt) vmovlpd(xmm4, mem(rcx)) // store (gamma40) lea(mem(rcx, rsi, 1), rcx) vmovhpd(xmm4, mem(rcx)) // store (gamma41) label(.SDONE) end_asm( : // output operands (none) : // input operands [m_iter] "m" (m_iter), [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } blis-0.9.0/kernels/zen/3/sup/broken/bli_gemmsup_rv_zen_asm_c3x8m.c000066400000000000000000001446011422157504600250710ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define BLIS_ASM_SYNTAX_ATT #include "bli_x86_asm_macros.h" // assumes beta.r, beta.i have been broadcast into ymm1, ymm2. // outputs to ymm0 #define CGEMM_INPUT_SCALE_CS_BETA_NZ \ vmovlpd(mem(rcx), xmm0, xmm0) \ vmovhpd(mem(rcx, rsi, 1), xmm0, xmm0) \ vmovlpd(mem(rcx, rsi, 2), xmm3, xmm3) \ vmovhpd(mem(rcx, r13, 1), xmm3, xmm3) \ vinsertf128(imm(1), xmm3, ymm0, ymm0) \ vpermilps(imm(0xb1), ymm0, ymm3) \ vmulps(ymm1, ymm0, ymm0) \ vmulps(ymm2, ymm3, ymm3) \ vaddsubps(ymm3, ymm0, ymm0) #define CGEMM_INPUT_SCALE_CS_BETA_NZ_128 \ vmovlpd(mem(rcx), xmm0, xmm0) \ vmovhpd(mem(rcx, rsi, 1), xmm0, xmm0) \ vpermilps(imm(0xb1), xmm0, xmm3) \ vmulps(xmm1, xmm0, xmm0) \ vmulps(xmm2, xmm3, xmm3) \ vaddsubps(xmm3, xmm0, xmm0) #define CGEMM_INPUT_SCALE_RS_BETA_NZ \ vmovups(mem(rcx), ymm0) \ vpermilps(imm(0xb1), ymm0, ymm3) \ vmulps(ymm1, ymm0, ymm0) \ vmulps(ymm2, ymm3, ymm3) \ vaddsubps(ymm3, ymm0, ymm0) #define CGEMM_OUTPUT_RS \ vmovups(ymm0, mem(rcx)) \ #define CGEMM_INPUT_SCALE_RS_BETA_NZ_NEXT \ vmovups(mem(rcx, rsi, 8), ymm0) \ vpermilps(imm(0xb1), ymm0, ymm3) \ vmulps(ymm1, ymm0, ymm0) \ vmulps(ymm2, ymm3, ymm3) \ vaddsubps(ymm3, ymm0, ymm0) #define CGEMM_OUTPUT_RS_NEXT \ vmovups(ymm0, mem(rcx, rsi, 8)) \ /* rrr: -------- ------ -------- -------- += ------ ... -------- -------- ------ -------- -------- ------ : rcr: -------- | | | | -------- -------- += | | | | ... -------- -------- | | | | -------- -------- | | | | : Assumptions: - B is row-stored; - A is row- or column-stored; - m0 and n0 are at most MR and NR, respectively. Therefore, this (r)ow-preferential kernel is well-suited for contiguous (v)ector loads on B and single-element broadcasts from A. NOTE: These kernels explicitly support column-oriented IO, implemented via an in-register transpose. And thus they also support the crr and ccr cases, though only crr is ever utilized (because ccr is handled by transposing the operation and executing rcr, which does not incur the cost of the in-register transpose). crr: | | | | | | | | ------ -------- | | | | | | | | += ------ ... -------- | | | | | | | | ------ -------- | | | | | | | | ------ : */ void bli_cgemmsup_rv_zen_asm_3x8m ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, scomplex* restrict alpha, scomplex* restrict a, inc_t rs_a0, inc_t cs_a0, scomplex* restrict b, inc_t rs_b0, inc_t cs_b0, scomplex* restrict beta, scomplex* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { uint64_t n_left = n0 % 8; // First check whether this is a edge case in the n dimension. If so, // dispatch other 3x?m kernels, as needed. if (n_left ) { scomplex* cij = c; scomplex* bj = b; scomplex* ai = a; if ( 4 <= n_left ) { const dim_t nr_cur = 4; bli_cgemmsup_rv_zen_asm_3x4m ( conja, conjb, m0, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 2 <= n_left ) { const dim_t nr_cur = 2; bli_cgemmsup_rv_zen_asm_3x2m ( conja, conjb, m0, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 1 == n_left ) { bli_cgemv_ex ( BLIS_NO_TRANSPOSE, conjb, m0, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, beta, cij, rs_c0, cntx, NULL ); } return; } //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t m_iter = m0 / 3; uint64_t m_left = m0 % 3; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; if ( m_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() mov(var(a), r14) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(dt) lea(mem(, r9, 8), r9) // cs_a *= sizeof(dt) mov(var(rs_b), r10) // load rs_b lea(mem(, r10, 8), r10) // rs_b *= sizeof(dt) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(dt) // During preamble and loops: // r12 = rcx = c // r14 = rax = a // read rbx from var(b) near beginning of loop // r11 = m dim index ii mov(var(m_iter), r11) // ii = m_iter; label(.SLOOP3X8I) // LOOP OVER ii = [ m_iter ... 1 0 ] vzeroall() // zero all xmm/ymm registers. mov(var(b), rbx) // load address of b. //mov(r12, rcx) // reset rcx to current utile of c. mov(r14, rax) // reset rax to current upanel of a. cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored pre-fetching on c // not used lea(mem(r12, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; jmp(.SPOSTPFETCH) // jump to end of pre-fetching c label(.SCOLPFETCH) // column-stored pre-fetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(dt) lea(mem(r12, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; label(.SPOSTPFETCH) // done prefetching c lea(mem(r9, r9, 2), rcx) // rcx = 3*cs_a; lea(mem(rax, r8, 4), rdx) // use rdx for pre-fetching lines lea(mem(rdx, r8, 2), rdx) // from next upanel of a. mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vbroadcastss(mem(rax, r8, 1), ymm2) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vbroadcastss(mem(rax, r8, 2), ymm2) vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) vbroadcastss(mem(rax, 4), ymm3) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 1, 4), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, r8, 2, 4), ymm3) vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) add(r9, rax) // a += cs_a; // ---------------------------------- iteration 1 vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vbroadcastss(mem(rax, r8, 1), ymm2) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vbroadcastss(mem(rax, r8, 2), ymm2) vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) vbroadcastss(mem(rax, 4), ymm3) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 1, 4), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, r8, 2, 4), ymm3) vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) add(r9, rax) // a += cs_a; // ---------------------------------- iteration 2 vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vbroadcastss(mem(rax, r8, 1), ymm2) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vbroadcastss(mem(rax, r8, 2), ymm2) vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) vbroadcastss(mem(rax, 4), ymm3) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 1, 4), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, r8, 2, 4), ymm3) vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) add(r9, rax) // a += cs_a; // ---------------------------------- iteration 3 lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vbroadcastss(mem(rax, r8, 1), ymm2) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vbroadcastss(mem(rax, r8, 2), ymm2) vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) vbroadcastss(mem(rax, 4), ymm3) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 1, 4), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, r8, 2, 4), ymm3) vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) add(r9, rax) // a += cs_a; dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vbroadcastss(mem(rax, r8, 1), ymm2) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vbroadcastss(mem(rax, r8, 2), ymm2) vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) vbroadcastss(mem(rax, 4 ), ymm3) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 1, 4), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, r8, 2, 4), ymm3) vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) add(r9, rax) // a += cs_a; dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(r12, rcx) // reset rcx to current utile of c. // permute even and odd elements // of ymm6/7, ymm10/11, ymm/14/15 vpermilps(imm(0xb1), ymm6, ymm6) vpermilps(imm(0xb1), ymm7, ymm7) vpermilps(imm(0xb1), ymm10, ymm10) vpermilps(imm(0xb1), ymm11, ymm11) vpermilps(imm(0xb1), ymm14, ymm14) vpermilps(imm(0xb1), ymm15, ymm15) // subtract/add even/odd elements vaddsubps(ymm6, ymm4, ymm4) vaddsubps(ymm7, ymm5, ymm5) vaddsubps(ymm10, ymm8, ymm8) vaddsubps(ymm11, ymm9, ymm9) vaddsubps(ymm14, ymm12, ymm12) vaddsubps(ymm15, ymm13, ymm13) /* (ar + ai) x AB */ mov(var(alpha), rax) // load address of alpha vbroadcastss(mem(rax), ymm0) // load alpha_r and duplicate vbroadcastss(mem(rax, 4), ymm1) // load alpha_i and duplicate vpermilps(imm(0xb1), ymm4, ymm3) vmulps(ymm0, ymm4, ymm4) vmulps(ymm1, ymm3, ymm3) vaddsubps(ymm3, ymm4, ymm4) vpermilps(imm(0xb1), ymm5, ymm3) vmulps(ymm0, ymm5, ymm5) vmulps(ymm1, ymm3, ymm3) vaddsubps(ymm3, ymm5, ymm5) vpermilps(imm(0xb1), ymm8, ymm3) vmulps(ymm0, ymm8, ymm8) vmulps(ymm1, ymm3, ymm3) vaddsubps(ymm3, ymm8, ymm8) vpermilps(imm(0xb1), ymm9, ymm3) vmulps(ymm0, ymm9, ymm9) vmulps(ymm1, ymm3, ymm3) vaddsubps(ymm3, ymm9, ymm9) vpermilps(imm(0xb1), ymm12, ymm3) vmulps(ymm0, ymm12, ymm12) vmulps(ymm1, ymm3, ymm3) vaddsubps(ymm3, ymm12, ymm12) vpermilps(imm(0xb1), ymm13, ymm3) vmulps(ymm0, ymm13, ymm13) vmulps(ymm1, ymm3, ymm3) vaddsubps(ymm3, ymm13, ymm13) /* (ßr + ßi)x C + ((ar + ai) x AB) */ mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rbx), ymm1) // load beta_r and duplicate vbroadcastss(mem(rbx, 4), ymm2) // load beta_i and duplicate mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(dt) lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm1) // set ZF if beta_r == 0. sete(r13b) // r13b = ( ZF == 1 ? 1 : 0 ); vucomiss(xmm0, xmm2) // set ZF if beta_i == 0. sete(r15b) // r15b = ( ZF == 1 ? 1 : 0 ); and(r13b, r15b) // set ZF if r13b & r15b == 1. jne(.SBETAZERO) // if ZF = 1, jump to beta == 0 case lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) CGEMM_INPUT_SCALE_RS_BETA_NZ vaddps(ymm4, ymm0, ymm0) CGEMM_OUTPUT_RS CGEMM_INPUT_SCALE_RS_BETA_NZ_NEXT vaddps(ymm5, ymm0, ymm0) CGEMM_OUTPUT_RS_NEXT add(rdi, rcx) // rcx = c + 1*rs_c CGEMM_INPUT_SCALE_RS_BETA_NZ vaddps(ymm8, ymm0, ymm0) CGEMM_OUTPUT_RS CGEMM_INPUT_SCALE_RS_BETA_NZ_NEXT vaddps(ymm9, ymm0, ymm0) CGEMM_OUTPUT_RS_NEXT add(rdi, rcx) // rcx = c + 2*rs_c CGEMM_INPUT_SCALE_RS_BETA_NZ vaddps(ymm12, ymm0, ymm0) CGEMM_OUTPUT_RS CGEMM_INPUT_SCALE_RS_BETA_NZ_NEXT vaddps(ymm13, ymm0, ymm0) CGEMM_OUTPUT_RS_NEXT jmp(.SDONE) // jump to end. label(.SCOLSTORED) /*|----------------| |-------| | | | | | | 3x4 | 3x4 | | 4x3 | | | | |-------| |----------------| | | | 4x3 | |-------| */ mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(dt) lea(mem(rsi, rsi, 2), r13) // r13 = 3*rs_a CGEMM_INPUT_SCALE_CS_BETA_NZ vaddps(ymm4, ymm0, ymm4) add(rdi, rcx) CGEMM_INPUT_SCALE_CS_BETA_NZ vaddps(ymm8, ymm0, ymm8) add(rdi, rcx) CGEMM_INPUT_SCALE_CS_BETA_NZ vaddps(ymm12, ymm0, ymm12) lea(mem(r12, rsi, 4), rcx) CGEMM_INPUT_SCALE_CS_BETA_NZ vaddps(ymm5, ymm0, ymm5) add(rdi, rcx) CGEMM_INPUT_SCALE_CS_BETA_NZ vaddps(ymm9, ymm0, ymm9) add(rdi, rcx) CGEMM_INPUT_SCALE_CS_BETA_NZ vaddps(ymm13, ymm0, ymm13) mov(r12, rcx) // reset rcx to current utile of c. vunpcklpd(ymm8, ymm4, ymm0) //a0a1b0b1 a4a4b4b5 //gamma00-10 gamma02-12 vunpckhpd(ymm8, ymm4, ymm2) //a2a3b2b3 a6a7b6b7 //gamma01-11 gamma03-13 /******************Transpose top tile 4x3***************************/ vmovups(xmm0, mem(rcx)) // store (gamma00-10) vmovlpd(xmm12, mem(rcx, 16)) // store (gamma20) lea(mem(rcx, rsi, 1), rcx) vmovups(xmm2, mem(rcx)) // store (gamma01-11) vmovhpd(xmm12, mem(rcx, 16)) // store (gamma21) lea(mem(rcx, rsi, 1), rcx) vextractf128(imm(0x1), ymm0, xmm0) vextractf128(imm(0x1), ymm2, xmm2) vextractf128(imm(0x1), ymm12, xmm12) vmovups(xmm0, mem(rcx)) // store (gamma02-12) vmovlpd(xmm12, mem(rcx, 16)) // store (gamma22) lea(mem(rcx, rsi, 1), rcx) vmovups(xmm2, mem(rcx)) // store (gamma03-13) vmovhpd(xmm12, mem(rcx, 16)) // store (gamma33) lea(mem(rcx, rsi, 1), rcx) /******************Transpose bottom tile 4x3***************************/ vunpcklpd(ymm9, ymm5, ymm0) //a8a9b8b9 a12a13b12b13 //gamma04-14 gamma06-16 vunpckhpd(ymm9, ymm5, ymm2) //a10a11b10b11 a14a15b14b15 //gamma05-15 gamma07-17 vmovups(xmm0, mem(rcx)) // store (gamma04-14) vmovlpd(xmm13, mem(rcx, 16)) // store (gamma24) lea(mem(rcx, rsi, 1), rcx) vmovups(xmm2, mem(rcx)) // store (gamma05-15) vmovhpd(xmm13, mem(rcx, 16)) // store (gamma25) lea(mem(rcx, rsi, 1), rcx) vextractf128(imm(0x1), ymm0, xmm0) vextractf128(imm(0x1), ymm2, xmm2) vextractf128(imm(0x1), ymm13, xmm13) vmovups(xmm0, mem(rcx)) // store (gamma06-16) vmovlpd(xmm13, mem(rcx, 16)) // store (gamma26) lea(mem(rcx, rsi, 1), rcx) vmovups(xmm2, mem(rcx)) // store (gamma07-17) vmovhpd(xmm13, mem(rcx, 16)) // store (gamma27) jmp(.SDONE) // jump to end. label(.SBETAZERO) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovups(ymm4, mem(rcx)) vmovups(ymm5, mem(rcx, rsi, 8)) add(rdi, rcx) vmovups(ymm8, mem(rcx)) vmovups(ymm9, mem(rcx, rsi, 8)) add(rdi, rcx) vmovups(ymm12, mem(rcx)) vmovups(ymm13, mem(rcx, rsi, 8)) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) /****3x8 tile going to save into 8x3 tile in C*****/ mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(dt) vunpcklpd(ymm8, ymm4, ymm0) //a0a1b0b1 a4a4b4b5 vunpckhpd(ymm8, ymm4, ymm2) //a2a3b2b3 a6a7b6b7 /******************Transpose top tile 4x3***************************/ vmovups(xmm0, mem(rcx)) vmovlpd(xmm12, mem(rcx,16)) lea(mem(rcx, rsi, 1), rcx) vmovups(xmm2, mem(rcx)) vmovhpd(xmm12,mem(rcx,16)) lea(mem(rcx, rsi, 1), rcx) vextractf128(imm(0x1), ymm0, xmm0) vextractf128(imm(0x1), ymm2, xmm2) vextractf128(imm(0x1), ymm12, xmm12) vmovups(xmm0, mem(rcx)) vmovlpd(xmm12, mem(rcx, 16)) lea(mem(rcx, rsi, 1), rcx) vmovups(xmm2, mem(rcx)) vmovhpd(xmm12, mem(rcx, 16)) lea(mem(rcx, rsi, 1), rcx) /******************Transpose bottom tile 4x3***************************/ vunpcklpd(ymm9, ymm5, ymm0) //a8a9b8b9 a12a13b12b13 vunpckhpd(ymm9, ymm5, ymm2) //a10a11b10b11 a14a15b14b15 vmovups(xmm0, mem(rcx)) vmovlpd(xmm13, mem(rcx, 16)) lea(mem(rcx, rsi, 1), rcx) vmovups(xmm2, mem(rcx)) vmovhpd(xmm13, mem(rcx, 16)) lea(mem(rcx, rsi, 1), rcx) vextractf128(imm(0x1), ymm0, xmm0) vextractf128(imm(0x1), ymm2, xmm2) vextractf128(imm(0x1), ymm13, xmm13) vmovups(xmm0, mem(rcx)) vmovlpd(xmm13, mem(rcx, 16)) lea(mem(rcx, rsi, 1), rcx) vmovups(xmm2, mem(rcx)) vmovhpd(xmm13, mem(rcx, 16)) label(.SDONE) lea(mem(r12, rdi, 2), r12) lea(mem(r12, rdi, 1), r12) // c_ii = r12 += 3*rs_c lea(mem(r14, r8, 2), r14) lea(mem(r14, r8, 1), r14) //a_ii = r14 += 3*rs_a dec(r11) // ii -= 1; jne(.SLOOP3X8I) // iterate again if ii != 0. label(.SRETURN) end_asm( : // output operands (none) : // input operands [m_iter] "m" (m_iter), [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the m dimension, if they exist. if ( m_left ) { const dim_t nr_cur = 8; const dim_t i_edge = m0 - ( dim_t )m_left; scomplex* cij = c + i_edge*rs_c; scomplex* ai = a + i_edge*rs_a; scomplex* bj = b; cgemmsup_ker_ft ker_fps[3] = { NULL, bli_cgemmsup_rv_zen_asm_1x8, bli_cgemmsup_rv_zen_asm_2x8, }; cgemmsup_ker_ft ker_fp = ker_fps[ m_left ]; ker_fp ( conja, conjb, m_left, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); return; } } void bli_cgemmsup_rv_zen_asm_3x4m ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, scomplex* restrict alpha, scomplex* restrict a, inc_t rs_a0, inc_t cs_a0, scomplex* restrict b, inc_t rs_b0, inc_t cs_b0, scomplex* restrict beta, scomplex* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t m_iter = m0 / 3; uint64_t m_left = m0 % 3; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; if ( m_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() mov(var(a), r14) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(dt) lea(mem(, r9, 8), r9) // cs_a *= sizeof(dt) mov(var(rs_b), r10) // load rs_b lea(mem(, r10, 8), r10) // rs_b *= sizeof(dt) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(dt) // During preamble and loops: // r12 = rcx = c // r14 = rax = a // read rbx from var(b) near beginning of loop // r11 = m dim index ii mov(var(m_iter), r11) // ii = m_iter; label(.SLOOP3X4I) // LOOP OVER ii = [ m_iter ... 1 0 ] vzeroall() // zero all xmm/ymm registers. mov(var(b), rbx) // load address of b. //mov(r12, rcx) // reset rcx to current utile of c. mov(r14, rax) // reset rax to current upanel of a. cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored pre-fetching on c // not used lea(mem(r12, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; jmp(.SPOSTPFETCH) // jump to end of pre-fetching c label(.SCOLPFETCH) // column-stored pre-fetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(dt) lea(mem(r12, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; label(.SPOSTPFETCH) // done prefetching c lea(mem(r9, r9, 2), rcx) // rcx = 3*cs_a; lea(mem(rax, r8, 4), rdx) // use rdx for pre-fetching lines lea(mem(rdx, r8, 2), rdx) // from next upanel of a. mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 vmovups(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vfmadd231ps(ymm0, ymm2, ymm4) vbroadcastss(mem(rax, r8, 1), ymm2) vfmadd231ps(ymm0, ymm2, ymm8) vbroadcastss(mem(rax, r8, 2), ymm2) vfmadd231ps(ymm0, ymm2, ymm12) vbroadcastss(mem(rax, 4), ymm3) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 1, 4), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vbroadcastss(mem(rax, r8, 2, 4), ymm3) vfmadd231ps(ymm0, ymm3, ymm14) add(r9, rax) // a += cs_a; // ---------------------------------- iteration 1 vmovups(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vfmadd231ps(ymm0, ymm2, ymm4) vbroadcastss(mem(rax, r8, 1), ymm2) vfmadd231ps(ymm0, ymm2, ymm8) vbroadcastss(mem(rax, r8, 2), ymm2) vfmadd231ps(ymm0, ymm2, ymm12) vbroadcastss(mem(rax, 4), ymm3) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 1, 4), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vbroadcastss(mem(rax, r8, 2, 4), ymm3) vfmadd231ps(ymm0, ymm3, ymm14) add(r9, rax) // a += cs_a; // ---------------------------------- iteration 2 vmovups(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vfmadd231ps(ymm0, ymm2, ymm4) vbroadcastss(mem(rax, r8, 1), ymm2) vfmadd231ps(ymm0, ymm2, ymm8) vbroadcastss(mem(rax, r8, 2), ymm2) vfmadd231ps(ymm0, ymm2, ymm12) vbroadcastss(mem(rax, 4), ymm3) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 1, 4), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vbroadcastss(mem(rax, r8, 2, 4), ymm3) vfmadd231ps(ymm0, ymm3, ymm14) add(r9, rax) // a += cs_a; // ---------------------------------- iteration 3 lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; vmovups(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vfmadd231ps(ymm0, ymm2, ymm4) vbroadcastss(mem(rax, r8, 1), ymm2) vfmadd231ps(ymm0, ymm2, ymm8) vbroadcastss(mem(rax, r8, 2), ymm2) vfmadd231ps(ymm0, ymm2, ymm12) vbroadcastss(mem(rax, 4), ymm3) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 1, 4), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vbroadcastss(mem(rax, r8, 2, 4), ymm3) vfmadd231ps(ymm0, ymm3, ymm14) add(r9, rax) // a += cs_a; dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP vmovups(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vfmadd231ps(ymm0, ymm2, ymm4) vbroadcastss(mem(rax, r8, 1), ymm2) vfmadd231ps(ymm0, ymm2, ymm8) vbroadcastss(mem(rax, r8, 2), ymm2) vfmadd231ps(ymm0, ymm2, ymm12) vbroadcastss(mem(rax, 4), ymm3) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 1, 4), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vbroadcastss(mem(rax, r8, 2, 4), ymm3) vfmadd231ps(ymm0, ymm3, ymm14) add(r9, rax) // a += cs_a; dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(r12, rcx) // reset rcx to current utile of c. // permute even and odd elements // of ymm6/7, ymm10/11, ymm/14/15 vpermilps(imm(0xb1), ymm6, ymm6) vpermilps(imm(0xb1), ymm10, ymm10) vpermilps(imm(0xb1), ymm14, ymm14) // subtract/add even/odd elements vaddsubps(ymm6, ymm4, ymm4) vaddsubps(ymm10, ymm8, ymm8) vaddsubps(ymm14, ymm12, ymm12) /* (ar + ai) x AB */ mov(var(alpha), rax) // load address of alpha vbroadcastss(mem(rax), ymm0) // load alpha_r and duplicate vbroadcastss(mem(rax, 4), ymm1) // load alpha_i and duplicate vpermilps(imm(0xb1), ymm4, ymm3) vmulps(ymm0, ymm4, ymm4) vmulps(ymm1, ymm3, ymm3) vaddsubps(ymm3, ymm4, ymm4) vpermilps(imm(0xb1), ymm8, ymm3) vmulps(ymm0, ymm8, ymm8) vmulps(ymm1, ymm3, ymm3) vaddsubps(ymm3, ymm8, ymm8) vpermilps(imm(0xb1), ymm12, ymm3) vmulps(ymm0, ymm12, ymm12) vmulps(ymm1, ymm3, ymm3) vaddsubps(ymm3, ymm12, ymm12) /* (ßr + ßi)x C + ((ar + ai) x AB) */ mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rbx), ymm1) // load beta_r and duplicate vbroadcastss(mem(rbx, 4), ymm2) // load beta_i and duplicate mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(dt) lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm1) // set ZF if beta_r == 0. sete(r13b) // r13b = ( ZF == 1 ? 1 : 0 ); vucomiss(xmm0, xmm2) // set ZF if beta_i == 0. sete(r15b) // r15b = ( ZF == 1 ? 1 : 0 ); and(r13b, r15b) // set ZF if r13b & r15b == 1. jne(.SBETAZERO) // if ZF = 1, jump to beta == 0 case lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) CGEMM_INPUT_SCALE_RS_BETA_NZ vaddps(ymm4, ymm0, ymm0) CGEMM_OUTPUT_RS add(rdi, rcx) // rcx = c + 1*rs_c CGEMM_INPUT_SCALE_RS_BETA_NZ vaddps(ymm8, ymm0, ymm0) CGEMM_OUTPUT_RS add(rdi, rcx) // rcx = c + 2*rs_c CGEMM_INPUT_SCALE_RS_BETA_NZ vaddps(ymm12, ymm0, ymm0) CGEMM_OUTPUT_RS jmp(.SDONE) // jump to end. label(.SCOLSTORED) /*|--------| |-------| | | | | | 3x4 | | 4x3 | |--------| |-------| */ mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(dt) lea(mem(rsi, rsi, 2), r13) // r13 = 3*rs_a CGEMM_INPUT_SCALE_CS_BETA_NZ vaddps(ymm4, ymm0, ymm4) add(rdi, rcx) CGEMM_INPUT_SCALE_CS_BETA_NZ vaddps(ymm8, ymm0, ymm8) add(rdi, rcx) CGEMM_INPUT_SCALE_CS_BETA_NZ vaddps(ymm12, ymm0, ymm12) mov(r12, rcx) // reset rcx to current utile of c. vunpcklpd(ymm8, ymm4, ymm0) //a0a1b0b1 a4a4b4b5 //gamma00-10 gamma02-12 vunpckhpd(ymm8, ymm4, ymm2) //a2a3b2b3 a6a7b6b7 //gamma01-11 gamma03-13 /******************Transpose tile 4x3***************************/ vmovups(xmm0, mem(rcx)) // store (gamma00-10) vmovlpd(xmm12, mem(rcx, 16)) // store (gamma20) lea(mem(rcx, rsi, 1), rcx) vmovups(xmm2, mem(rcx)) // store (gamma01-11) vmovhpd(xmm12, mem(rcx, 16)) // store (gamma21) lea(mem(rcx, rsi, 1), rcx) vextractf128(imm(0x1), ymm0, xmm0) vextractf128(imm(0x1), ymm2, xmm2) vextractf128(imm(0x1), ymm12, xmm12) vmovups(xmm0, mem(rcx)) // store (gamma02-12) vmovlpd(xmm12, mem(rcx, 16)) // store (gamma22) lea(mem(rcx, rsi, 1), rcx) vmovups(xmm2, mem(rcx)) // store (gamma03-13) vmovhpd(xmm12, mem(rcx, 16)) // store (gamma33) lea(mem(rcx, rsi, 1), rcx) jmp(.SDONE) // jump to end. label(.SBETAZERO) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovups(ymm4, mem(rcx)) add(rdi, rcx) vmovups(ymm8, mem(rcx)) add(rdi, rcx) vmovups(ymm12, mem(rcx)) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) /****3x4 tile going to save into 4x3 tile in C*****/ mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(dt) vunpcklpd(ymm8, ymm4, ymm0) //a0a1b0b1 a4a4b4b5 vunpckhpd(ymm8, ymm4, ymm2) //a2a3b2b3 a6a7b6b7 vmovups(xmm0, mem(rcx)) vmovlpd(xmm12, mem(rcx, 16)) lea(mem(rcx, rsi, 1), rcx) vmovups(xmm2, mem(rcx)) vmovhpd(xmm12, mem(rcx, 16)) lea(mem(rcx, rsi, 1), rcx) vextractf128(imm(0x1), ymm0, xmm0) vextractf128(imm(0x1), ymm2, xmm2) vextractf128(imm(0x1), ymm12, xmm12) vmovups(xmm0, mem(rcx)) vmovlpd(xmm12, mem(rcx, 16)) lea(mem(rcx, rsi, 1), rcx) vmovups(xmm2, mem(rcx)) vmovhpd(xmm12, mem(rcx, 16)) label(.SDONE) lea(mem(r12, rdi, 2), r12) lea(mem(r12, rdi, 1), r12) // c_ii = r12 += 3*rs_c lea(mem(r14, r8, 2), r14) lea(mem(r14, r8, 1), r14) //a_ii = r14 += 3*rs_a dec(r11) // ii -= 1; jne(.SLOOP3X4I) // iterate again if ii != 0. label(.SRETURN) end_asm( : // output operands (none) : // input operands [m_iter] "m" (m_iter), [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the m dimension, if they exist. if ( m_left ) { const dim_t nr_cur = 4; const dim_t i_edge = m0 - ( dim_t )m_left; scomplex* cij = c + i_edge*rs_c; scomplex* ai = a + i_edge*rs_a; scomplex* bj = b; cgemmsup_ker_ft ker_fps[3] = { NULL, bli_cgemmsup_rv_zen_asm_1x4, bli_cgemmsup_rv_zen_asm_2x4, }; cgemmsup_ker_ft ker_fp = ker_fps[ m_left ]; ker_fp ( conja, conjb, m_left, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); return; } } void bli_cgemmsup_rv_zen_asm_3x2m ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, scomplex* restrict alpha, scomplex* restrict a, inc_t rs_a0, inc_t cs_a0, scomplex* restrict b, inc_t rs_b0, inc_t cs_b0, scomplex* restrict beta, scomplex* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t m_iter = m0 / 3; uint64_t m_left = m0 % 3; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; if ( m_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() mov(var(a), r14) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(dt) lea(mem(, r9, 8), r9) // cs_a *= sizeof(dt) mov(var(rs_b), r10) // load rs_b lea(mem(, r10, 8), r10) // rs_b *= sizeof(dt) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(dt) // During preamble and loops: // r12 = rcx = c // r14 = rax = a // read rbx from var(b) near beginning of loop // r11 = m dim index ii mov(var(m_iter), r11) // ii = m_iter; label(.SLOOP3X2I) // LOOP OVER ii = [ m_iter ... 1 0 ] vzeroall() // zero all xmm/ymm registers. mov(var(b), rbx) // load address of b. //mov(r12, rcx) // reset rcx to current utile of c. mov(r14, rax) // reset rax to current upanel of a. cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored pre-fetching on c // not used lea(mem(r12, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; jmp(.SPOSTPFETCH) // jump to end of pre-fetching c label(.SCOLPFETCH) // column-stored pre-fetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(dt) lea(mem(r12, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; label(.SPOSTPFETCH) // done prefetching c lea(mem(r9, r9, 2), rcx) // rcx = 3*cs_a; lea(mem(rax, r8, 4), rdx) // use rdx for pre-fetching lines lea(mem(rdx, r8, 2), rdx) // from next upanel of a. mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vfmadd231ps(xmm0, xmm2, xmm4) vbroadcastss(mem(rax, r8, 1), xmm2) vfmadd231ps(xmm0, xmm2, xmm8) vbroadcastss(mem(rax, r8, 2), xmm2) vfmadd231ps(xmm0, xmm2, xmm12) vbroadcastss(mem(rax, 4), xmm3) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 1, 4), xmm3) vfmadd231ps(xmm0, xmm3, xmm10) vbroadcastss(mem(rax, r8, 2, 4), xmm3) vfmadd231ps(xmm0, xmm3, xmm14) add(r9, rax) // a += cs_a; // ---------------------------------- iteration 1 vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vfmadd231ps(xmm0, xmm2, xmm4) vbroadcastss(mem(rax, r8, 1), xmm2) vfmadd231ps(xmm0, xmm2, xmm8) vbroadcastss(mem(rax, r8, 2), xmm2) vfmadd231ps(xmm0, xmm2, xmm12) vbroadcastss(mem(rax, 4), xmm3) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 1, 4), xmm3) vfmadd231ps(xmm0, xmm3, xmm10) vbroadcastss(mem(rax, r8, 2, 4), xmm3) vfmadd231ps(xmm0, xmm3, xmm14) add(r9, rax) // a += cs_a; // ---------------------------------- iteration 2 vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vfmadd231ps(xmm0, xmm2, xmm4) vbroadcastss(mem(rax, r8, 1), xmm2) vfmadd231ps(xmm0, xmm2, xmm8) vbroadcastss(mem(rax, r8, 2), xmm2) vfmadd231ps(xmm0, xmm2, xmm12) vbroadcastss(mem(rax, 4), xmm3) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 1, 4), xmm3) vfmadd231ps(xmm0, xmm3, xmm10) vbroadcastss(mem(rax, r8, 2, 4), xmm3) vfmadd231ps(xmm0, xmm3, xmm14) add(r9, rax) // a += cs_a; // ---------------------------------- iteration 3 lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vfmadd231ps(xmm0, xmm2, xmm4) vbroadcastss(mem(rax, r8, 1), xmm2) vfmadd231ps(xmm0, xmm2, xmm8) vbroadcastss(mem(rax, r8, 2), xmm2) vfmadd231ps(xmm0, xmm2, xmm12) vbroadcastss(mem(rax, 4), xmm3) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 1, 4), xmm3) vfmadd231ps(xmm0, xmm3, xmm10) vbroadcastss(mem(rax, r8, 2, 4), xmm3) vfmadd231ps(xmm0, xmm3, xmm14) add(r9, rax) // a += cs_a; dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vfmadd231ps(xmm0, xmm2, xmm4) vbroadcastss(mem(rax, r8, 1), xmm2) vfmadd231ps(xmm0, xmm2, xmm8) vbroadcastss(mem(rax, r8, 2), xmm2) vfmadd231ps(xmm0, xmm2, xmm12) vbroadcastss(mem(rax, 4), xmm3) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 1, 4), xmm3) vfmadd231ps(xmm0, xmm3, xmm10) vbroadcastss(mem(rax, r8, 2, 4), xmm3) vfmadd231ps(xmm0, xmm3, xmm14) add(r9, rax) // a += cs_a; dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(r12, rcx) // reset rcx to current utile of c. // permute even and odd elements // of xmm6/7, xmm10/11, xmm/14/15 vpermilps(imm(0xb1), xmm6, xmm6) vpermilps(imm(0xb1), xmm10, xmm10) vpermilps(imm(0xb1), xmm14, xmm14) // subtract/add even/odd elements vaddsubps(xmm6, xmm4, xmm4) vaddsubps(xmm10, xmm8, xmm8) vaddsubps(xmm14, xmm12, xmm12) /* (ar + ai) x AB */ mov(var(alpha), rax) // load address of alpha vbroadcastss(mem(rax), xmm0) // load alpha_r and duplicate vbroadcastss(mem(rax, 4), xmm1) // load alpha_i and duplicate vpermilps(imm(0xb1), xmm4, xmm3) vmulps(xmm0, xmm4, xmm4) vmulps(xmm1, xmm3, xmm3) vaddsubps(xmm3, xmm4, xmm4) vpermilps(imm(0xb1), xmm8, xmm3) vmulps(xmm0, xmm8, xmm8) vmulps(xmm1, xmm3, xmm3) vaddsubps(xmm3, xmm8, xmm8) vpermilps(imm(0xb1), xmm12, xmm3) vmulps(xmm0, xmm12, xmm12) vmulps(xmm1, xmm3, xmm3) vaddsubps(xmm3, xmm12, xmm12) /* (ßr + ßi)x C + ((ar + ai) x AB) */ mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rbx), xmm1) // load beta_r and duplicate vbroadcastss(mem(rbx, 4), xmm2) // load beta_i and duplicate mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(dt) lea(mem(rcx, rdi, 2), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorps(xmm0, xmm0, xmm0) // set xmm0 to zero. vucomiss(xmm0, xmm1) // set ZF if beta_r == 0. sete(r13b) // r13b = ( ZF == 1 ? 1 : 0 ); vucomiss(xmm0, xmm2) // set ZF if beta_i == 0. sete(r15b) // r15b = ( ZF == 1 ? 1 : 0 ); and(r13b, r15b) // set ZF if r13b & r15b == 1. jne(.SBETAZERO) // if ZF = 1, jump to beta == 0 case lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vmovlpd(mem(rcx), xmm0, xmm0) vmovhpd(mem(rcx, rsi, 1), xmm0, xmm0) vpermilps(imm(0xb1), xmm0, xmm3) vmulps(xmm1, xmm0, xmm0) vmulps(xmm2, xmm3, xmm3) vaddsubps(xmm3, xmm0, xmm0) vaddps(xmm4, xmm0, xmm0) vmovlpd(xmm0, mem(rcx)) vmovhpd(xmm0, mem(rcx, rsi, 1)) add(rdi, rcx) // rcx = c + 1*rs_c vmovlpd(mem(rcx), xmm0, xmm0) vmovhpd(mem(rcx, rsi, 1), xmm0, xmm0) vpermilps(imm(0xb1), xmm0, xmm3) vmulps(xmm1, xmm0, xmm0) vmulps(xmm2, xmm3, xmm3) vaddsubps(xmm3, xmm0, xmm0) vaddps(xmm8, xmm0, xmm0) vmovlpd(xmm0, mem(rcx)) vmovhpd(xmm0, mem(rcx, rsi, 1)) add(rdi, rcx) // rcx = c + 2*rs_c vmovlpd(mem(rcx), xmm0, xmm0) vmovhpd(mem(rcx, rsi, 1), xmm0, xmm0) vpermilps(imm(0xb1), xmm0, xmm3) vmulps(xmm1, xmm0, xmm0) vmulps(xmm2, xmm3, xmm3) vaddsubps(xmm3, xmm0, xmm0) vaddps(xmm12, xmm0, xmm0) vmovlpd(xmm0, mem(rcx)) vmovhpd(xmm0, mem(rcx, rsi, 1)) jmp(.SDONE) // jump to end. label(.SCOLSTORED) /*|--------| |-------| | | | | | 3x2 | | 2x3 | | | |-------| |--------| */ mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(dt) lea(mem(rsi, rsi, 2), r13) // r13 = 3*rs_a CGEMM_INPUT_SCALE_CS_BETA_NZ_128 vaddps(xmm4, xmm0, xmm4) add(rdi, rcx) CGEMM_INPUT_SCALE_CS_BETA_NZ_128 vaddps(xmm8, xmm0, xmm8) add(rdi, rcx) CGEMM_INPUT_SCALE_CS_BETA_NZ_128 vaddps(xmm12, xmm0, xmm12) mov(r12, rcx) // reset rcx to current utile of c. vunpcklpd(xmm8, xmm4, xmm0) //a0a1b0b1 a4a4b4b5 //gamma00-10 gamma02-02 vunpckhpd(xmm8, xmm4, xmm2) //a2a3b2b3 a6a7b6b7 //gamma01-11 gamma03-13 vmovups(xmm0, mem(rcx)) // store (gamma00-10) vmovlpd(xmm12, mem(rcx, 16)) // store (gamma20) lea(mem(rcx, rsi, 1), rcx) vmovups(xmm2, mem(rcx)) // store (gamma01-11) vmovhpd(xmm12, mem(rcx, 16)) // store (gamma21) jmp(.SDONE) // jump to end. label(.SBETAZERO) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a cmp(imm(8), rdi) // set ZF if (8*rs_c) == 8. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovups(xmm4, mem(rcx)) add(rdi, rcx) vmovups(xmm8, mem(rcx)) add(rdi, rcx) vmovups(xmm12, mem(rcx)) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) /****3x2 tile going to save into 2x3 tile in C*****/ mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(dt) vunpcklpd(xmm8, xmm4, xmm0) //a0a1b0b1 a4a4b4b5 //gamma00-10 gamma02-02 vunpckhpd(xmm8, xmm4, xmm2) //a2a3b2b3 a6a7b6b7 //gamma01-11 gamma03-13 vmovups(xmm0, mem(rcx)) // store (gamma00-10) vmovlpd(xmm12, mem(rcx, 16)) // store (gamma20) lea(mem(rcx, rsi, 1), rcx) vmovups(xmm2, mem(rcx)) // store (gamma01-11) vmovhpd(xmm12, mem(rcx, 16)) // store (gamma21) label(.SDONE) lea(mem(r12, rdi, 2), r12) lea(mem(r12, rdi, 1), r12) // c_ii = r12 += 3*rs_c lea(mem(r14, r8, 2), r14) lea(mem(r14, r8, 1), r14) //a_ii = r14 += 3*rs_a dec(r11) // ii -= 1; jne(.SLOOP3X2I) // iterate again if ii != 0. label(.SRETURN) end_asm( : // output operands (none) : // input operands [m_iter] "m" (m_iter), [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the m dimension, if they exist. if ( m_left ) { const dim_t nr_cur = 2; const dim_t i_edge = m0 - ( dim_t )m_left; scomplex* cij = c + i_edge*rs_c; scomplex* ai = a + i_edge*rs_a; scomplex* bj = b; cgemmsup_ker_ft ker_fps[3] = { NULL, bli_cgemmsup_rv_zen_asm_1x2, bli_cgemmsup_rv_zen_asm_2x2, }; cgemmsup_ker_ft ker_fp = ker_fps[ m_left ]; ker_fp ( conja, conjb, m_left, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); return; } } blis-0.9.0/kernels/zen/3/sup/broken/bli_gemmsup_rv_zen_asm_c3x8n.c000066400000000000000000001501151422157504600250670ustar00rootroot00000000000000 /* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "immintrin.h" /* rrr: -------- ------ -------- -------- += ------ ... -------- -------- ------ -------- -------- ------ : rcr: -------- | | | | -------- -------- += | | | | ... -------- -------- | | | | -------- -------- | | | | : Assumptions: - B is row-stored; - A is row- or column-stored; - m0 and n0 are at most MR and NR, respectively. Therefore, this (r)ow-preferential kernel is well-suited for contiguous (v)ector loads on B and single-element broadcasts from A. NOTE: These kernels explicitly support column-oriented IO, implemented via an in-register transpose. And thus they also support the crr and ccr cases, though only crr is ever utilized (because ccr is handled by transposing the operation and executing rcr, which does not incur the cost of the in-register transpose). crr: | | | | | | | | ------ -------- | | | | | | | | += ------ ... -------- | | | | | | | | ------ -------- | | | | | | | | ------ : */ void bli_cgemmsup_rv_zen_asm_3x8n ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, scomplex* restrict alpha, scomplex* restrict a, inc_t rs_a0, inc_t cs_a0, scomplex* restrict b, inc_t rs_b0, inc_t cs_b0, scomplex* restrict beta, scomplex* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { uint64_t m_left = m0 % 3; if ( m_left ) { cgemmsup_ker_ft ker_fps[3] = { NULL, bli_cgemmsup_rv_zen_asm_1x8n, bli_cgemmsup_rv_zen_asm_2x8n, }; cgemmsup_ker_ft ker_fp = ker_fps[ m_left ]; ker_fp ( conja, conjb, m_left, n0, k0, alpha, a, rs_a0, cs_a0, b, rs_b0, cs_b0, beta, c, rs_c0, cs_c0, data, cntx ); return; } //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t n_iter = n0 / 8; uint64_t n_left = n0 % 8; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; if ( n_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- //scratch registers __m256 ymm0, ymm1, ymm2, ymm3; __m256 ymm4, ymm5, ymm6, ymm7; __m256 ymm8, ymm9, ymm10, ymm11; __m256 ymm12, ymm13, ymm14, ymm15; __m128 xmm0, xmm3; scomplex *tA = a; float *tAimag = &a->imag; scomplex *tB = b; scomplex *tC = c; for (n_iter = 0; n_iter < n0 / 8; n_iter++) { // clear scratch registers. ymm4 = _mm256_setzero_ps(); ymm5 = _mm256_setzero_ps(); ymm6 = _mm256_setzero_ps(); ymm7 = _mm256_setzero_ps(); ymm8 = _mm256_setzero_ps(); ymm9 = _mm256_setzero_ps(); ymm10 = _mm256_setzero_ps(); ymm11 = _mm256_setzero_ps(); ymm12 = _mm256_setzero_ps(); ymm13 = _mm256_setzero_ps(); ymm14 = _mm256_setzero_ps(); ymm15 = _mm256_setzero_ps(); dim_t ta_inc_row = rs_a; dim_t tb_inc_row = rs_b; dim_t tc_inc_row = rs_c; dim_t ta_inc_col = cs_a; dim_t tb_inc_col = cs_b; dim_t tc_inc_col = cs_c; tA = a; tAimag = &a->imag; tB = b + n_iter*tb_inc_col*8; tC = c + n_iter*tc_inc_col*8; for (k_iter = 0; k_iter imag)); // load alpha_i and duplicate ymm3 = _mm256_permute_ps(ymm4, 0xb1); ymm4 = _mm256_mul_ps(ymm0, ymm4); ymm3 =_mm256_mul_ps(ymm1, ymm3); ymm4 = _mm256_addsub_ps(ymm4, ymm3); ymm3 = _mm256_permute_ps(ymm5, 0xb1); ymm5 = _mm256_mul_ps(ymm0, ymm5); ymm3 = _mm256_mul_ps(ymm1, ymm3); ymm5 = _mm256_addsub_ps(ymm5, ymm3); ymm3 = _mm256_permute_ps(ymm8, 0xb1); ymm8 = _mm256_mul_ps(ymm0, ymm8); ymm3 = _mm256_mul_ps(ymm1, ymm3); ymm8 = _mm256_addsub_ps(ymm8, ymm3); ymm3 = _mm256_permute_ps(ymm9, 0xb1); ymm9 = _mm256_mul_ps(ymm0, ymm9); ymm3 = _mm256_mul_ps(ymm1, ymm3); ymm9 = _mm256_addsub_ps(ymm9, ymm3); ymm3 = _mm256_permute_ps(ymm12, 0xb1); ymm12 = _mm256_mul_ps(ymm0, ymm12); ymm3 = _mm256_mul_ps(ymm1, ymm3); ymm12 = _mm256_addsub_ps(ymm12, ymm3); ymm3 = _mm256_permute_ps(ymm13, 0xb1); ymm13 = _mm256_mul_ps(ymm0, ymm13); ymm3 = _mm256_mul_ps(ymm1, ymm3); ymm13 = _mm256_addsub_ps(ymm13, ymm3); if(tc_inc_row == 1) //col stored { if(beta->real == 0.0 && beta->imag == 0.0) { //transpose left 3x4 ymm0 = _mm256_castpd_ps(_mm256_unpacklo_pd(_mm256_castps_pd (ymm4), _mm256_castps_pd (ymm8))); _mm_storeu_ps((float *)(tC), _mm256_castps256_ps128(ymm0)); _mm_storel_pi((__m64 *)(tC+2), _mm256_castps256_ps128(ymm12)); ymm1 = _mm256_castpd_ps(_mm256_unpackhi_pd(_mm256_castps_pd (ymm4) , _mm256_castps_pd(ymm8))); tC += tc_inc_col; _mm_storeu_ps((float *)(tC), _mm256_castps256_ps128(ymm1)); _mm_storeh_pi((__m64 *)(tC+2), _mm256_castps256_ps128(ymm12)); tC += tc_inc_col; _mm_storeu_ps((float *)(tC ) ,_mm256_extractf128_ps (ymm0,1)); _mm_storel_pi((__m64 *)(tC+2), _mm256_extractf128_ps(ymm12, 1)); tC += tc_inc_col; _mm_storeu_ps((float *)(tC) ,_mm256_extractf128_ps (ymm1,1)); _mm_storeh_pi((__m64 *)(tC+2), _mm256_extractf128_ps(ymm12,1)); //transpose right 3x4 tC += tc_inc_col; ymm0 = _mm256_castpd_ps(_mm256_unpacklo_pd(_mm256_castps_pd (ymm5), _mm256_castps_pd(ymm9))); _mm_storeu_ps((float *)(tC ),_mm256_castps256_ps128(ymm0)); _mm_storel_pi((__m64 *)(tC+2), _mm256_castps256_ps128(ymm13)); ymm1 = _mm256_castpd_ps(_mm256_unpackhi_pd(_mm256_castps_pd(ymm5), _mm256_castps_pd(ymm9))); tC += tc_inc_col; _mm_storeu_ps((float *)(tC), _mm256_castps256_ps128(ymm1)); _mm_storeh_pi((__m64 *)(tC+2), _mm256_castps256_ps128(ymm13)); tC += tc_inc_col; _mm_storeu_ps((float *)(tC ),_mm256_extractf128_ps (ymm0,1)); _mm_storel_pi((__m64 *)(tC+2), _mm256_extractf128_ps(ymm13,1)); tC += tc_inc_col; _mm_storeu_ps((float *)(tC ),_mm256_extractf128_ps (ymm1,1)); _mm_storeh_pi((__m64 *)(tC+2), _mm256_extractf128_ps(ymm13,1)); } else{ ymm1 = _mm256_broadcast_ss((float const *)(beta)); // load alpha_r and duplicate ymm2 = _mm256_broadcast_ss((float const *)(&beta->imag)); // load alpha_i and duplicate //Multiply ymm4 with beta xmm0 = _mm_loadl_pi(xmm0, (__m64 const *) (tC) ); xmm0 = _mm_loadh_pi(xmm0, (__m64 const *) (tC + tc_inc_col)); xmm3 = _mm_loadl_pi(xmm3, (__m64 const *) (tC + tc_inc_col*2)); xmm3 = _mm_loadh_pi(xmm3, (__m64 const *)(tC + tc_inc_col*3)) ; ymm0 = _mm256_insertf128_ps(_mm256_castps128_ps256(xmm0), xmm3, 1) ; ymm3 = _mm256_permute_ps(ymm0, 0xb1); ymm0 = _mm256_mul_ps(ymm1, ymm0); ymm3 = _mm256_mul_ps(ymm2, ymm3); ymm0 = _mm256_addsub_ps(ymm0, ymm3); ymm4 = _mm256_add_ps(ymm4, ymm0); //Multiply ymm8 with beta xmm0 = _mm_loadl_pi(xmm0, (__m64 const *)(tC + 1)) ; xmm0 = _mm_loadh_pi(xmm0, (__m64 const *)(tC + 1 + tc_inc_col)) ; xmm3 = _mm_loadl_pi(xmm3, (__m64 const *)(tC + 1 + tc_inc_col*2)) ; xmm3 = _mm_loadh_pi(xmm3, (__m64 const *)(tC + 1 + tc_inc_col*3)) ; ymm0 = _mm256_insertf128_ps(_mm256_castps128_ps256(xmm0), xmm3, 1) ; ymm3 = _mm256_permute_ps(ymm0, 0xb1); ymm0 = _mm256_mul_ps(ymm1, ymm0); ymm3 = _mm256_mul_ps(ymm2, ymm3); ymm0 = _mm256_addsub_ps(ymm0, ymm3); ymm8 = _mm256_add_ps(ymm8, ymm0); //Multiply ymm12 with beta xmm0 = _mm_loadl_pi(xmm0, (__m64 const *)(tC + 2)) ; xmm0 = _mm_loadh_pi(xmm0, (__m64 const *)(tC + 2 + tc_inc_col)) ; xmm3 = _mm_loadl_pi(xmm3, (__m64 const *)(tC + 2 + tc_inc_col*2)) ; xmm3 = _mm_loadh_pi(xmm3, (__m64 const *)(tC + 2 + tc_inc_col*3)) ; ymm0 = _mm256_insertf128_ps(_mm256_castps128_ps256(xmm0), xmm3, 1) ; ymm3 = _mm256_permute_ps(ymm0, 0xb1); ymm0 = _mm256_mul_ps(ymm1, ymm0); ymm3 = _mm256_mul_ps(ymm2, ymm3); ymm0 = _mm256_addsub_ps(ymm0, ymm3); ymm12 = _mm256_add_ps(ymm12, ymm0); //transpose left 3x4 ymm0 = _mm256_castpd_ps(_mm256_unpacklo_pd(_mm256_castps_pd (ymm4), _mm256_castps_pd (ymm8))); _mm_storeu_ps((float *)(tC), _mm256_castps256_ps128(ymm0)); _mm_storeu_ps((float *)(tC), _mm256_castps256_ps128(ymm0)); _mm_storel_pi((__m64 *)(tC+2), _mm256_castps256_ps128(ymm12)); ymm3 = _mm256_castpd_ps(_mm256_unpackhi_pd(_mm256_castps_pd (ymm4) , _mm256_castps_pd(ymm8))); tC += tc_inc_col; _mm_storeu_ps((float *)(tC), _mm256_castps256_ps128(ymm3)); _mm_storeh_pi((__m64 *)(tC+2), _mm256_castps256_ps128(ymm12)); tC += tc_inc_col; _mm_storeu_ps((float *)(tC) ,_mm256_extractf128_ps (ymm0,1)); _mm_storel_pi((__m64 *)(tC+2), _mm256_extractf128_ps(ymm12, 1)); tC += tc_inc_col; _mm_storeu_ps((float *)(tC ),_mm256_extractf128_ps (ymm3,1)); _mm_storeh_pi((__m64 *)(tC+2), _mm256_extractf128_ps(ymm12,1)); //Multiply ymm5 with beta tC += tc_inc_col; xmm0 = _mm_loadl_pi(xmm0, (__m64 const *) (tC)) ; xmm0 = _mm_loadh_pi(xmm0, (__m64 const *) (tC + tc_inc_col)); xmm3 = _mm_loadl_pi(xmm3, (__m64 const *) (tC + tc_inc_col*2)); xmm3 = _mm_loadh_pi(xmm3, (__m64 const *)(tC + tc_inc_col*3)) ; ymm0 = _mm256_insertf128_ps(_mm256_castps128_ps256(xmm0), xmm3, 1) ; ymm3 = _mm256_permute_ps(ymm0, 0xb1); ymm0 = _mm256_mul_ps(ymm1, ymm0); ymm3 = _mm256_mul_ps(ymm2, ymm3); ymm0 = _mm256_addsub_ps(ymm0, ymm3); ymm5 = _mm256_add_ps(ymm5, ymm0); //Multiply ymm9 with beta xmm0 = _mm_loadl_pi(xmm0, (__m64 const *)(tC+ 1)) ; xmm0 = _mm_loadh_pi(xmm0, (__m64 const *)(tC+ 1 + tc_inc_col)) ; xmm3 = _mm_loadl_pi(xmm3, (__m64 const *)(tC+ 1 + tc_inc_col*2)) ; xmm3 = _mm_loadh_pi(xmm3, (__m64 const *)(tC+ 1 + tc_inc_col*3)) ; ymm0 = _mm256_insertf128_ps(_mm256_castps128_ps256(xmm0), xmm3, 1) ; ymm3 = _mm256_permute_ps(ymm0, 0xb1); ymm0 = _mm256_mul_ps(ymm1, ymm0); ymm3 = _mm256_mul_ps(ymm2, ymm3); ymm0 = _mm256_addsub_ps(ymm0, ymm3); ymm9 = _mm256_add_ps(ymm9, ymm0); //Multiply ymm13 with beta xmm0 = _mm_loadl_pi(xmm0, (__m64 const *)(tC + 2)) ; xmm0 = _mm_loadh_pi(xmm0, (__m64 const *)(tC + 2 + tc_inc_col)) ; xmm3 = _mm_loadl_pi(xmm3, (__m64 const *)(tC + 2 + tc_inc_col*2)) ; xmm3 = _mm_loadh_pi(xmm3, (__m64 const *)(tC + 2 + tc_inc_col*3)) ; ymm0 = _mm256_insertf128_ps(_mm256_castps128_ps256(xmm0), xmm3, 1) ; ymm3 = _mm256_permute_ps(ymm0, 0xb1); ymm0 = _mm256_mul_ps(ymm1, ymm0); ymm3 = _mm256_mul_ps(ymm2, ymm3); ymm0 = _mm256_addsub_ps(ymm0, ymm3); ymm13 = _mm256_add_ps(ymm13, ymm0); //transpose right 3x4 ymm0 = _mm256_castpd_ps(_mm256_unpacklo_pd(_mm256_castps_pd (ymm5), _mm256_castps_pd(ymm9))); _mm_storeu_ps((float *)(tC), _mm256_castps256_ps128(ymm0)); _mm_storel_pi((__m64 *)(tC+2), _mm256_castps256_ps128(ymm13)); ymm3 = _mm256_castpd_ps(_mm256_unpackhi_pd(_mm256_castps_pd(ymm5), _mm256_castps_pd(ymm9))); tC += tc_inc_col; _mm_storeu_ps((float *)(tC ), _mm256_castps256_ps128(ymm3)); _mm_storeh_pi((__m64 *)(tC+2), _mm256_castps256_ps128(ymm13)); tC += tc_inc_col; _mm_storeu_ps((float *)(tC ),_mm256_extractf128_ps (ymm0,1)); _mm_storel_pi((__m64 *)(tC+2), _mm256_extractf128_ps(ymm13,1)); tC += tc_inc_col; _mm_storeu_ps((float *)(tC ),_mm256_extractf128_ps (ymm3,1)); _mm_storeh_pi((__m64 *)(tC+2), _mm256_extractf128_ps(ymm13,1)); } } else { if(beta->real == 0.0 && beta->imag == 0.0) { _mm256_storeu_ps((float*)(tC), ymm4); _mm256_storeu_ps((float*)(tC + 4), ymm5); _mm256_storeu_ps((float*)(tC + tc_inc_row ), ymm8); _mm256_storeu_ps((float*)(tC + tc_inc_row + 4), ymm9); _mm256_storeu_ps((float*)(tC + tc_inc_row *2), ymm12); _mm256_storeu_ps((float*)(tC + tc_inc_row *2+ 4), ymm13); } else{ /* (br + bi) C + (ar + ai) AB */ ymm0 = _mm256_broadcast_ss((float const *)(beta)); // load beta_r and duplicate ymm1 = _mm256_broadcast_ss((float const *)(&beta->imag)); // load beta_i and duplicate ymm2 = _mm256_loadu_ps((float const *)(tC)); ymm3 = _mm256_permute_ps(ymm2, 0xb1); ymm2 = _mm256_mul_ps(ymm0, ymm2); ymm3 =_mm256_mul_ps(ymm1, ymm3); ymm4 = _mm256_add_ps(ymm4, _mm256_addsub_ps(ymm2, ymm3)); ymm2 = _mm256_loadu_ps((float const *)(tC+4)); ymm3 = _mm256_permute_ps(ymm2, 0xb1); ymm2 = _mm256_mul_ps(ymm0, ymm2); ymm3 = _mm256_mul_ps(ymm1, ymm3); ymm5 = _mm256_add_ps(ymm5, _mm256_addsub_ps(ymm2, ymm3)); ymm2 = _mm256_loadu_ps((float const *)(tC+tc_inc_row)); ymm3 = _mm256_permute_ps(ymm2, 0xb1); ymm2 = _mm256_mul_ps(ymm0, ymm2); ymm3 = _mm256_mul_ps(ymm1, ymm3); ymm8 = _mm256_add_ps(ymm8, _mm256_addsub_ps(ymm2, ymm3)); ymm2 = _mm256_loadu_ps((float const *)(tC+tc_inc_row + 4)); ymm3 = _mm256_permute_ps(ymm2, 0xb1); ymm2 = _mm256_mul_ps(ymm0, ymm2); ymm3 = _mm256_mul_ps(ymm1, ymm3); ymm9 = _mm256_add_ps(ymm9, _mm256_addsub_ps(ymm2, ymm3)); ymm2 = _mm256_loadu_ps((float const *)(tC+tc_inc_row*2)); ymm3 = _mm256_permute_ps(ymm2, 0xb1); ymm2 = _mm256_mul_ps(ymm0, ymm2); ymm3 = _mm256_mul_ps(ymm1, ymm3); ymm12 = _mm256_add_ps(ymm12, _mm256_addsub_ps(ymm2, ymm3)); ymm2 = _mm256_loadu_ps((float const *)(tC+tc_inc_row*2 +4)); ymm3 = _mm256_permute_ps(ymm2, 0xb1); ymm2 = _mm256_mul_ps(ymm0, ymm2); ymm3 = _mm256_mul_ps(ymm1, ymm3); ymm13 = _mm256_add_ps(ymm13, _mm256_addsub_ps(ymm2, ymm3)); _mm256_storeu_ps((float*)(tC), ymm4); _mm256_storeu_ps((float*)(tC + 4), ymm5); _mm256_storeu_ps((float*)(tC + tc_inc_row) , ymm8); _mm256_storeu_ps((float*)(tC + tc_inc_row + 4), ymm9); _mm256_storeu_ps((float*)(tC + tc_inc_row *2), ymm12); _mm256_storeu_ps((float*)(tC + tc_inc_row *2+ 4), ymm13); } } } consider_edge_cases: // Handle edge cases in the m dimension, if they exist. if ( n_left ) { const dim_t mr_cur = 3; const dim_t j_edge = n0 - ( dim_t )n_left; scomplex* restrict cij = c + j_edge*cs_c; scomplex* restrict ai = a; scomplex* restrict bj = b + n_iter*8; if ( 4 <= n_left ) { const dim_t nr_cur = 4; bli_cgemmsup_rv_zen_asm_3x4 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 2 <= n_left ) { const dim_t nr_cur = 2; bli_cgemmsup_rv_zen_asm_3x2 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 1 == n_left ) { bli_cgemv_ex ( BLIS_NO_TRANSPOSE, conjb, m0, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, beta, cij, rs_c0, cntx, NULL ); } } } void bli_cgemmsup_rv_zen_asm_2x8n ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, scomplex* restrict alpha, scomplex* restrict a, inc_t rs_a0, inc_t cs_a0, scomplex* restrict b, inc_t rs_b0, inc_t cs_b0, scomplex* restrict beta, scomplex* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = 0; uint64_t n_iter = n0 / 8; uint64_t n_left = n0 % 8; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; if ( n_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- //scratch registers __m256 ymm0, ymm1, ymm2, ymm3; __m256 ymm4, ymm5, ymm6, ymm7; __m256 ymm8, ymm9, ymm10, ymm11; __m128 xmm0, xmm3; scomplex *tA = a; float *tAimag = &a->imag; scomplex *tB = b; scomplex *tC = c; for (n_iter = 0; n_iter < n0 / 8; n_iter++) { // clear scratch registers. ymm4 = _mm256_setzero_ps(); ymm5 = _mm256_setzero_ps(); ymm6 = _mm256_setzero_ps(); ymm7 = _mm256_setzero_ps(); ymm8 = _mm256_setzero_ps(); ymm9 = _mm256_setzero_ps(); ymm10 = _mm256_setzero_ps(); ymm11 = _mm256_setzero_ps(); dim_t ta_inc_row = rs_a; dim_t tb_inc_row = rs_b; dim_t tc_inc_row = rs_c; dim_t ta_inc_col = cs_a; dim_t tb_inc_col = cs_b; dim_t tc_inc_col = cs_c; tA = a; tAimag = &a->imag; tB = b + n_iter*tb_inc_col*8; tC = c + n_iter*tc_inc_col*8; for (k_iter = 0; k_iter imag)); // load alpha_i and duplicate ymm3 = _mm256_permute_ps(ymm4, 0xb1); ymm4 = _mm256_mul_ps(ymm0, ymm4); ymm3 =_mm256_mul_ps(ymm1, ymm3); ymm4 = _mm256_addsub_ps(ymm4, ymm3); ymm3 = _mm256_permute_ps(ymm5, 0xb1); ymm5 = _mm256_mul_ps(ymm0, ymm5); ymm3 = _mm256_mul_ps(ymm1, ymm3); ymm5 = _mm256_addsub_ps(ymm5, ymm3); ymm3 = _mm256_permute_ps(ymm8, 0xb1); ymm8 = _mm256_mul_ps(ymm0, ymm8); ymm3 = _mm256_mul_ps(ymm1, ymm3); ymm8 = _mm256_addsub_ps(ymm8, ymm3); ymm3 = _mm256_permute_ps(ymm9, 0xb1); ymm9 = _mm256_mul_ps(ymm0, ymm9); ymm3 = _mm256_mul_ps(ymm1, ymm3); ymm9 = _mm256_addsub_ps(ymm9, ymm3); if(tc_inc_row == 1) //col stored { if(beta->real == 0.0 && beta->imag == 0.0) { //transpose left 2x4 ymm0 = _mm256_castpd_ps(_mm256_unpacklo_pd(_mm256_castps_pd (ymm4), _mm256_castps_pd (ymm8))); _mm_storeu_ps((float *)(tC), _mm256_castps256_ps128(ymm0)); ymm1 = _mm256_castpd_ps(_mm256_unpackhi_pd(_mm256_castps_pd (ymm4) , _mm256_castps_pd(ymm8))); tC += tc_inc_col; _mm_storeu_ps((float *)(tC), _mm256_castps256_ps128(ymm1)); tC += tc_inc_col; _mm_storeu_ps((float *)(tC) ,_mm256_extractf128_ps (ymm0,1)); tC += tc_inc_col; _mm_storeu_ps((float *)(tC) ,_mm256_extractf128_ps (ymm1,1)); //transpose right 2x4 tC += tc_inc_col; ymm0 = _mm256_castpd_ps(_mm256_unpacklo_pd(_mm256_castps_pd (ymm5), _mm256_castps_pd(ymm9))); _mm_storeu_ps((float *)(tC), _mm256_castps256_ps128(ymm0)); ymm1 = _mm256_castpd_ps(_mm256_unpackhi_pd(_mm256_castps_pd(ymm5), _mm256_castps_pd(ymm9))); tC += tc_inc_col; _mm_storeu_ps((float *)(tC), _mm256_castps256_ps128(ymm1)); tC += tc_inc_col; _mm_storeu_ps((float *)(tC) ,_mm256_extractf128_ps (ymm0,1)); tC += tc_inc_col; _mm_storeu_ps((float *)(tC) ,_mm256_extractf128_ps (ymm1,1)); } else{ ymm1 = _mm256_broadcast_ss((float const *)(beta)); // load alpha_r and duplicate ymm2 = _mm256_broadcast_ss((float const *)(&beta->imag)); // load alpha_i and duplicate //Multiply ymm4 with beta xmm0 = _mm_loadl_pi(xmm0, (__m64 const *) (tC)) ; xmm0 = _mm_loadh_pi(xmm0, (__m64 const *) (tC + tc_inc_col)); xmm3 = _mm_loadl_pi(xmm3, (__m64 const *) (tC + tc_inc_col*2)); xmm3 = _mm_loadh_pi(xmm3, (__m64 const *)(tC + tc_inc_col*3)) ; ymm0 = _mm256_insertf128_ps(_mm256_castps128_ps256(xmm0), xmm3, 1) ; ymm3 = _mm256_permute_ps(ymm0, 0xb1); ymm0 = _mm256_mul_ps(ymm1, ymm0); ymm3 = _mm256_mul_ps(ymm2, ymm3); ymm0 = _mm256_addsub_ps(ymm0, ymm3); ymm4 = _mm256_add_ps(ymm4, ymm0); //Multiply ymm8 with beta xmm0 = _mm_loadl_pi(xmm0, (__m64 const *)(tC + 1)) ; xmm0 = _mm_loadh_pi(xmm0, (__m64 const *)(tC + 1 + tc_inc_col)) ; xmm3 = _mm_loadl_pi(xmm3, (__m64 const *)(tC + 1 + tc_inc_col*2)) ; xmm3 = _mm_loadh_pi(xmm3, (__m64 const *)(tC + 1 + tc_inc_col*3)) ; ymm0 = _mm256_insertf128_ps(_mm256_castps128_ps256(xmm0), xmm3, 1); ymm3 = _mm256_permute_ps(ymm0, 0xb1); ymm0 = _mm256_mul_ps(ymm1, ymm0); ymm3 = _mm256_mul_ps(ymm2, ymm3); ymm0 = _mm256_addsub_ps(ymm0, ymm3); ymm8 = _mm256_add_ps(ymm8, ymm0); //transpose left 2x4 ymm0 = _mm256_castpd_ps(_mm256_unpacklo_pd(_mm256_castps_pd (ymm4), _mm256_castps_pd (ymm8))); _mm_storeu_ps((float *)(tC), _mm256_castps256_ps128(ymm0)); ymm3 = _mm256_castpd_ps(_mm256_unpackhi_pd(_mm256_castps_pd (ymm4) , _mm256_castps_pd(ymm8))); tC += tc_inc_col; _mm_storeu_ps((float *)(tC), _mm256_castps256_ps128(ymm3)); tC += tc_inc_col; _mm_storeu_ps((float *)(tC) ,_mm256_extractf128_ps (ymm0,1)); tC += tc_inc_col; _mm_storeu_ps((float *)(tC) ,_mm256_extractf128_ps (ymm3,1)); //Multiply ymm5 with beta tC += tc_inc_col; xmm0 = _mm_loadl_pi(xmm0, (__m64 const *) (tC)) ; xmm0 = _mm_loadh_pi(xmm0, (__m64 const *) (tC + tc_inc_col)); xmm3 = _mm_loadl_pi(xmm3, (__m64 const *) (tC + tc_inc_col*2)); xmm3 = _mm_loadh_pi(xmm3, (__m64 const *)(tC + tc_inc_col*3)) ; ymm0 = _mm256_insertf128_ps(_mm256_castps128_ps256(xmm0), xmm3, 1) ; ymm3 = _mm256_permute_ps(ymm0, 0xb1); ymm0 = _mm256_mul_ps(ymm1, ymm0); ymm3 = _mm256_mul_ps(ymm2, ymm3); ymm0 = _mm256_addsub_ps(ymm0, ymm3); ymm5 = _mm256_add_ps(ymm5, ymm0); //Multiply ymm9 with beta xmm0 = _mm_loadl_pi(xmm0, (__m64 const *)(tC+ 1)) ; xmm0 = _mm_loadh_pi(xmm0, (__m64 const *)(tC+ 1 + tc_inc_col)) ; xmm3 = _mm_loadl_pi(xmm3, (__m64 const *)(tC+ 1 + tc_inc_col*2)) ; xmm3 = _mm_loadh_pi(xmm3, (__m64 const *)(tC+ 1 + tc_inc_col*3)) ; ymm0 = _mm256_insertf128_ps(_mm256_castps128_ps256(xmm0), xmm3, 1) ; ymm3 = _mm256_permute_ps(ymm0, 0xb1); ymm0 = _mm256_mul_ps(ymm1, ymm0); ymm3 = _mm256_mul_ps(ymm2, ymm3); ymm0 = _mm256_addsub_ps(ymm0, ymm3); ymm9 = _mm256_add_ps(ymm9, ymm0); //transpose right 2x4 ymm0 = _mm256_castpd_ps(_mm256_unpacklo_pd(_mm256_castps_pd (ymm5), _mm256_castps_pd(ymm9))); _mm_storeu_ps((float *)(tC), _mm256_castps256_ps128(ymm0)); ymm3 = _mm256_castpd_ps(_mm256_unpackhi_pd(_mm256_castps_pd(ymm5), _mm256_castps_pd(ymm9))); tC += tc_inc_col; _mm_storeu_ps((float *)(tC), _mm256_castps256_ps128(ymm3)); tC += tc_inc_col; _mm_storeu_ps((float *)(tC) ,_mm256_extractf128_ps (ymm0,1)); tC += tc_inc_col; _mm_storeu_ps((float *)(tC) ,_mm256_extractf128_ps (ymm3,1)); } } else { if(beta->real == 0.0 && beta->imag == 0.0) { _mm256_storeu_ps((float*)(tC), ymm4); _mm256_storeu_ps((float*)(tC + 4), ymm5); _mm256_storeu_ps((float*)(tC + tc_inc_row) , ymm8); _mm256_storeu_ps((float*)(tC + tc_inc_row + 4), ymm9); } else{ /* (br + bi) C + (ar + ai) AB */ ymm0 = _mm256_broadcast_ss((float const *)(beta)); // load beta_r and duplicate ymm1 = _mm256_broadcast_ss((float const *)(&beta->imag)); // load beta_i and duplicate ymm2 = _mm256_loadu_ps((float const *)(tC)); ymm3 = _mm256_permute_ps(ymm2, 0xb1); ymm2 = _mm256_mul_ps(ymm0, ymm2); ymm3 =_mm256_mul_ps(ymm1, ymm3); ymm4 = _mm256_add_ps(ymm4, _mm256_addsub_ps(ymm2, ymm3)); ymm2 = _mm256_loadu_ps((float const *)(tC+4)); ymm3 = _mm256_permute_ps(ymm2, 0xb1); ymm2 = _mm256_mul_ps(ymm0, ymm2); ymm3 = _mm256_mul_ps(ymm1, ymm3); ymm5 = _mm256_add_ps(ymm5, _mm256_addsub_ps(ymm2, ymm3)); ymm2 = _mm256_loadu_ps((float const *)(tC+tc_inc_row)); ymm3 = _mm256_permute_ps(ymm2, 0xb1); ymm2 = _mm256_mul_ps(ymm0, ymm2); ymm3 = _mm256_mul_ps(ymm1, ymm3); ymm8 = _mm256_add_ps(ymm8, _mm256_addsub_ps(ymm2, ymm3)); ymm2 = _mm256_loadu_ps((float const *)(tC+tc_inc_row + 4)); ymm3 = _mm256_permute_ps(ymm2, 0xb1); ymm2 = _mm256_mul_ps(ymm0, ymm2); ymm3 = _mm256_mul_ps(ymm1, ymm3); ymm9 = _mm256_add_ps(ymm9, _mm256_addsub_ps(ymm2, ymm3)); _mm256_storeu_ps((float*)(tC), ymm4); _mm256_storeu_ps((float*)(tC + 4), ymm5); _mm256_storeu_ps((float*)(tC + tc_inc_row) , ymm8); _mm256_storeu_ps((float*)(tC + tc_inc_row + 4), ymm9); } } } consider_edge_cases: // Handle edge cases in the m dimension, if they exist. if ( n_left ) { const dim_t mr_cur = 3; const dim_t j_edge = n0 - ( dim_t )n_left; scomplex* restrict cij = c + j_edge*cs_c; scomplex* restrict ai = a; scomplex* restrict bj = b + n_iter * 8 ; if ( 4 <= n_left ) { const dim_t nr_cur = 4; bli_cgemmsup_rv_zen_asm_2x4 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 2 <= n_left ) { const dim_t nr_cur = 2; bli_cgemmsup_rv_zen_asm_2x2 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 1 == n_left ) { bli_cgemv_ex ( BLIS_NO_TRANSPOSE, conjb, m0, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, beta, cij, rs_c0, cntx, NULL ); } } } void bli_cgemmsup_rv_zen_asm_1x8n ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, scomplex* restrict alpha, scomplex* restrict a, inc_t rs_a0, inc_t cs_a0, scomplex* restrict b, inc_t rs_b0, inc_t cs_b0, scomplex* restrict beta, scomplex* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = 0; uint64_t n_iter = n0 / 8; uint64_t n_left = n0 % 8; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; if ( n_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- //scratch registers __m256 ymm0, ymm1, ymm2, ymm3; __m256 ymm4, ymm5, ymm6, ymm7; __m128 xmm0, xmm3; scomplex *tA = a; float *tAimag = &a->imag; scomplex *tB = b; scomplex *tC = c; for (n_iter = 0; n_iter < n0 / 8; n_iter++) { // clear scratch registers. ymm4 = _mm256_setzero_ps(); ymm5 = _mm256_setzero_ps(); ymm6 = _mm256_setzero_ps(); ymm7 = _mm256_setzero_ps(); dim_t tb_inc_row = rs_b; dim_t tc_inc_row = rs_c; dim_t ta_inc_col = cs_a; dim_t tb_inc_col = cs_b; dim_t tc_inc_col = cs_c; tA = a; tAimag = &a->imag; tB = b + n_iter*tb_inc_col*8; tC = c + n_iter*tc_inc_col*8; for (k_iter = 0; k_iter imag)); // load alpha_i and duplicate ymm3 = _mm256_permute_ps(ymm4, 0xb1); ymm4 = _mm256_mul_ps(ymm0, ymm4); ymm3 =_mm256_mul_ps(ymm1, ymm3); ymm4 = _mm256_addsub_ps(ymm4, ymm3); ymm3 = _mm256_permute_ps(ymm5, 0xb1); ymm5 = _mm256_mul_ps(ymm0, ymm5); ymm3 = _mm256_mul_ps(ymm1, ymm3); ymm5 = _mm256_addsub_ps(ymm5, ymm3); if(tc_inc_row == 1) //col stored { if(beta->real == 0.0 && beta->imag == 0.0) { //transpose left 1x4 _mm_storel_pi((__m64 *)(tC), _mm256_castps256_ps128(ymm4)); tC += tc_inc_col; _mm_storeh_pi((__m64 *)(tC), _mm256_castps256_ps128(ymm4)); tC += tc_inc_col; _mm_storel_pi((__m64 *)(tC) ,_mm256_extractf128_ps (ymm4,1)); tC += tc_inc_col; _mm_storeh_pi((__m64 *)(tC) ,_mm256_extractf128_ps (ymm4,1)); //transpose right 1x4 tC += tc_inc_col; _mm_storel_pi((__m64 *)(tC), _mm256_castps256_ps128(ymm5)); tC += tc_inc_col; _mm_storeh_pi((__m64 *)(tC), _mm256_castps256_ps128(ymm5)); tC += tc_inc_col; _mm_storel_pi((__m64 *)(tC) ,_mm256_extractf128_ps (ymm5,1)); tC += tc_inc_col; _mm_storeh_pi((__m64 *)(tC) ,_mm256_extractf128_ps (ymm5,1)); } else{ ymm1 = _mm256_broadcast_ss((float const *)(beta)); // load alpha_r and duplicate ymm2 = _mm256_broadcast_ss((float const *)(&beta->imag)); // load alpha_i and duplicate //Multiply ymm4 with beta xmm0 = _mm_loadl_pi(xmm0, (__m64 const *) (tC)) ; xmm0 = _mm_loadh_pi(xmm0, (__m64 const *) (tC + tc_inc_col)); xmm3 = _mm_loadl_pi(xmm3, (__m64 const *) (tC + tc_inc_col*2)); xmm3 = _mm_loadh_pi(xmm3, (__m64 const *)(tC + tc_inc_col*3)) ; ymm0 = _mm256_insertf128_ps(_mm256_castps128_ps256(xmm0), xmm3, 1) ; ymm3 = _mm256_permute_ps(ymm0, 0xb1); ymm0 = _mm256_mul_ps(ymm1, ymm0); ymm3 = _mm256_mul_ps(ymm2, ymm3); ymm0 = _mm256_addsub_ps(ymm0, ymm3); ymm4 = _mm256_add_ps(ymm4, ymm0); _mm_storel_pi((__m64 *)(tC), _mm256_castps256_ps128(ymm4)); tC += tc_inc_col; _mm_storeh_pi((__m64 *)(tC), _mm256_castps256_ps128(ymm4)); tC += tc_inc_col; _mm_storel_pi((__m64 *)(tC) ,_mm256_extractf128_ps (ymm4,1)); tC += tc_inc_col; _mm_storeh_pi((__m64 *)(tC) ,_mm256_extractf128_ps (ymm4,1)); //Multiply ymm5 with beta tC += tc_inc_col; xmm0 = _mm_loadl_pi(xmm0, (__m64 const *) (tC)) ; xmm0 = _mm_loadh_pi(xmm0, (__m64 const *) (tC + tc_inc_col)); xmm3 = _mm_loadl_pi(xmm3, (__m64 const *) (tC + tc_inc_col*2)); xmm3 = _mm_loadh_pi(xmm3, (__m64 const *)(tC + tc_inc_col*3)) ; ymm0 = _mm256_insertf128_ps(_mm256_castps128_ps256(xmm0), xmm3, 1) ; ymm3 = _mm256_permute_ps(ymm0, 0xb1); ymm0 = _mm256_mul_ps(ymm1, ymm0); ymm3 = _mm256_mul_ps(ymm2, ymm3); ymm0 = _mm256_addsub_ps(ymm0, ymm3); ymm5 = _mm256_add_ps(ymm5, ymm0); _mm_storel_pi((__m64 *)(tC), _mm256_castps256_ps128(ymm5)); tC += tc_inc_col; _mm_storeh_pi((__m64 *)(tC), _mm256_castps256_ps128(ymm5)); tC += tc_inc_col; _mm_storel_pi((__m64 *)(tC) ,_mm256_extractf128_ps (ymm5,1)); tC += tc_inc_col; _mm_storeh_pi((__m64 *)(tC) ,_mm256_extractf128_ps (ymm5,1)); } } else { if(beta->real == 0.0 && beta->imag == 0.0) { _mm256_storeu_ps((float*)(tC), ymm4); _mm256_storeu_ps((float*)(tC + 4), ymm5); } else{ /* (br + bi) C + (ar + ai) AB */ ymm0 = _mm256_broadcast_ss((float const *)(beta)); // load beta_r and duplicate ymm1 = _mm256_broadcast_ss((float const *)(&beta->imag)); // load beta_i and duplicate ymm2 = _mm256_loadu_ps((float const *)(tC)); ymm3 = _mm256_permute_ps(ymm2, 0xb1); ymm2 = _mm256_mul_ps(ymm0, ymm2); ymm3 =_mm256_mul_ps(ymm1, ymm3); ymm4 = _mm256_add_ps(ymm4, _mm256_addsub_ps(ymm2, ymm3)); ymm2 = _mm256_loadu_ps((float const *)(tC+4)); ymm3 = _mm256_permute_ps(ymm2, 0xb1); ymm2 = _mm256_mul_ps(ymm0, ymm2); ymm3 = _mm256_mul_ps(ymm1, ymm3); ymm5 = _mm256_add_ps(ymm5, _mm256_addsub_ps(ymm2, ymm3)); _mm256_storeu_ps((float*)(tC), ymm4); _mm256_storeu_ps((float*)(tC + 4), ymm5); } } } consider_edge_cases: // Handle edge cases in the m dimension, if they exist. if ( n_left ) { const dim_t mr_cur = 3; const dim_t j_edge = n0 - ( dim_t )n_left; scomplex* restrict cij = c + j_edge*cs_c; scomplex* restrict ai = a; scomplex* restrict bj = b + n_iter * 8; if ( 4 <= n_left ) { const dim_t nr_cur = 4; bli_cgemmsup_rv_zen_asm_1x4 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 2 <= n_left ) { const dim_t nr_cur = 2; bli_cgemmsup_rv_zen_asm_1x2 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 1 == n_left ){ bli_cgemv_ex ( BLIS_NO_TRANSPOSE, conjb, m0, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, beta, cij, rs_c0, cntx, NULL ); } } } void bli_cgemmsup_rv_zen_asm_3x4 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, scomplex* restrict alpha, scomplex* restrict a, inc_t rs_a0, inc_t cs_a0, scomplex* restrict b, inc_t rs_b0, inc_t cs_b0, scomplex* restrict beta, scomplex* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { uint64_t k_iter = 0; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- //scratch registers __m256 ymm0, ymm1, ymm2, ymm3; __m256 ymm4, ymm6; __m256 ymm8, ymm10; __m256 ymm12, ymm14; __m128 xmm0, xmm3; scomplex *tA = a; float *tAimag = &a->imag; scomplex *tB = b; scomplex *tC = c; // clear scratch registers. ymm4 = _mm256_setzero_ps(); ymm6 = _mm256_setzero_ps(); ymm8 = _mm256_setzero_ps(); ymm10 = _mm256_setzero_ps(); ymm12 = _mm256_setzero_ps(); ymm14 = _mm256_setzero_ps(); dim_t ta_inc_row = rs_a; dim_t tb_inc_row = rs_b; dim_t tc_inc_row = rs_c; dim_t ta_inc_col = cs_a; dim_t tc_inc_col = cs_c; for (k_iter = 0; k_iter imag)); // load alpha_i and duplicate ymm3 = _mm256_permute_ps(ymm4, 0xb1); ymm4 = _mm256_mul_ps(ymm0, ymm4); ymm3 =_mm256_mul_ps(ymm1, ymm3); ymm4 = _mm256_addsub_ps(ymm4, ymm3); ymm3 = _mm256_permute_ps(ymm8, 0xb1); ymm8 = _mm256_mul_ps(ymm0, ymm8); ymm3 = _mm256_mul_ps(ymm1, ymm3); ymm8 = _mm256_addsub_ps(ymm8, ymm3); ymm3 = _mm256_permute_ps(ymm12, 0xb1); ymm12 = _mm256_mul_ps(ymm0, ymm12); ymm3 = _mm256_mul_ps(ymm1, ymm3); ymm12 = _mm256_addsub_ps(ymm12, ymm3); if(tc_inc_row == 1) //col stored { if(beta->real == 0.0 && beta->imag == 0.0) { //transpose 3x4 ymm0 = _mm256_castpd_ps(_mm256_unpacklo_pd(_mm256_castps_pd (ymm4), _mm256_castps_pd (ymm8))); _mm_storeu_ps((float *)(tC), _mm256_castps256_ps128(ymm0)); _mm_storel_pi((__m64 *)(tC+2), _mm256_castps256_ps128(ymm12)); ymm1 = _mm256_castpd_ps(_mm256_unpackhi_pd(_mm256_castps_pd (ymm4) , _mm256_castps_pd(ymm8))); tC += tc_inc_col; _mm_storeu_ps((float *)(tC), _mm256_castps256_ps128(ymm1)); _mm_storeh_pi((__m64 *)(tC+2), _mm256_castps256_ps128(ymm12)); tC += tc_inc_col; _mm_storeu_ps((float *)(tC),_mm256_extractf128_ps (ymm0,1)); _mm_storel_pi((__m64 *)(tC+2), _mm256_extractf128_ps(ymm12, 1)); tC += tc_inc_col; _mm_storeu_ps((float *)(tC ) ,_mm256_extractf128_ps (ymm1,1)); _mm_storeh_pi((__m64 *)(tC+2), _mm256_extractf128_ps(ymm12,1)); } else{ ymm1 = _mm256_broadcast_ss((float const *)(beta)); // load alpha_r and duplicate ymm2 = _mm256_broadcast_ss((float const *)(&beta->imag)); // load alpha_i and duplicate //Multiply ymm4 with beta xmm0 = _mm_loadl_pi(xmm0, (__m64 const *) (tC)) ; xmm0 = _mm_loadh_pi(xmm0, (__m64 const *) (tC + tc_inc_col)); xmm3 = _mm_loadl_pi(xmm3, (__m64 const *) (tC + tc_inc_col*2)); xmm3 = _mm_loadh_pi(xmm3, (__m64 const *)(tC + tc_inc_col*3)) ; ymm0 = _mm256_insertf128_ps(_mm256_castps128_ps256(xmm0), xmm3, 1) ; ymm3 = _mm256_permute_ps(ymm0, 0xb1); ymm0 = _mm256_mul_ps(ymm1, ymm0); ymm3 = _mm256_mul_ps(ymm2, ymm3); ymm0 = _mm256_addsub_ps(ymm0, ymm3); ymm4 = _mm256_add_ps(ymm4, ymm0); //Multiply ymm8 with beta xmm0 = _mm_loadl_pi(xmm0, (__m64 const *)(tC + 1)) ; xmm0 = _mm_loadh_pi(xmm0, (__m64 const *)(tC + 1 + tc_inc_col)) ; xmm3 = _mm_loadl_pi(xmm3, (__m64 const *)(tC + 1 + tc_inc_col*2)) ; xmm3 = _mm_loadh_pi(xmm3, (__m64 const *)(tC + 1 + tc_inc_col*3)) ; ymm0 = _mm256_insertf128_ps(_mm256_castps128_ps256(xmm0), xmm3, 1) ; ymm3 = _mm256_permute_ps(ymm0, 0xb1); ymm0 = _mm256_mul_ps(ymm1, ymm0); ymm3 = _mm256_mul_ps(ymm2, ymm3); ymm0 = _mm256_addsub_ps(ymm0, ymm3); ymm8 = _mm256_add_ps(ymm8, ymm0); //Multiply ymm12 with beta xmm0 = _mm_loadl_pi(xmm0, (__m64 const *)(tC + 2)) ; xmm0 = _mm_loadh_pi(xmm0, (__m64 const *)(tC + 2 + tc_inc_col)) ; xmm3 = _mm_loadl_pi(xmm3, (__m64 const *)(tC + 2 + tc_inc_col*2)) ; xmm3 = _mm_loadh_pi(xmm3, (__m64 const *)(tC + 2 + tc_inc_col*3)) ; ymm0 = _mm256_insertf128_ps(_mm256_castps128_ps256(xmm0), xmm3, 1) ; ymm3 = _mm256_permute_ps(ymm0, 0xb1); ymm0 = _mm256_mul_ps(ymm1, ymm0); ymm3 = _mm256_mul_ps(ymm2, ymm3); ymm0 = _mm256_addsub_ps(ymm0, ymm3); ymm12 = _mm256_add_ps(ymm12, ymm0); //transpose 3x4 ymm0 = _mm256_castpd_ps(_mm256_unpacklo_pd(_mm256_castps_pd (ymm4), _mm256_castps_pd (ymm8))); _mm_storeu_ps((float *)(tC), _mm256_castps256_ps128(ymm0)); _mm_storel_pi((__m64 *)(tC+2), _mm256_castps256_ps128(ymm12)); ymm3 = _mm256_castpd_ps(_mm256_unpackhi_pd(_mm256_castps_pd (ymm4) , _mm256_castps_pd(ymm8))); tC += tc_inc_col; _mm_storeu_ps((float *)(tC), _mm256_castps256_ps128(ymm3)); _mm_storeh_pi((__m64 *)(tC+2), _mm256_castps256_ps128(ymm12)); tC += tc_inc_col; _mm_storeu_ps((float *)(tC) ,_mm256_extractf128_ps (ymm0,1)); _mm_storel_pi((__m64 *)(tC+2), _mm256_extractf128_ps(ymm12, 1)); tC += tc_inc_col; _mm_storeu_ps((float *)(tC ),_mm256_extractf128_ps (ymm3,1)); _mm_storeh_pi((__m64 *)(tC+2), _mm256_extractf128_ps(ymm12,1)); } } else { if(beta->real == 0.0 && beta->imag == 0.0) { _mm256_storeu_ps((float*)(tC), ymm4); _mm256_storeu_ps((float*)(tC + tc_inc_row) , ymm8); _mm256_storeu_ps((float*)(tC + tc_inc_row *2), ymm12); } else{ /* (br + bi) C + (ar + ai) AB */ ymm0 = _mm256_broadcast_ss((float const *)(beta)); // load beta_r and duplicate ymm1 = _mm256_broadcast_ss((float const *)(&beta->imag)); // load beta_i and duplicate ymm2 = _mm256_loadu_ps((float const *)(tC)); ymm3 = _mm256_permute_ps(ymm2, 0xb1); ymm2 = _mm256_mul_ps(ymm0, ymm2); ymm3 =_mm256_mul_ps(ymm1, ymm3); ymm4 = _mm256_add_ps(ymm4, _mm256_addsub_ps(ymm2, ymm3)); ymm2 = _mm256_loadu_ps((float const *)(tC+tc_inc_row)); ymm3 = _mm256_permute_ps(ymm2, 0xb1); ymm2 = _mm256_mul_ps(ymm0, ymm2); ymm3 = _mm256_mul_ps(ymm1, ymm3); ymm8 = _mm256_add_ps(ymm8, _mm256_addsub_ps(ymm2, ymm3)); ymm2 = _mm256_loadu_ps((float const *)(tC+tc_inc_row*2)); ymm3 = _mm256_permute_ps(ymm2, 0xb1); ymm2 = _mm256_mul_ps(ymm0, ymm2); ymm3 = _mm256_mul_ps(ymm1, ymm3); ymm12 = _mm256_add_ps(ymm12, _mm256_addsub_ps(ymm2, ymm3)); _mm256_storeu_ps((float*)(tC), ymm4); _mm256_storeu_ps((float*)(tC + tc_inc_row) , ymm8); _mm256_storeu_ps((float*)(tC + tc_inc_row *2), ymm12);; } } } void bli_cgemmsup_rv_zen_asm_3x2 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, scomplex* restrict alpha, scomplex* restrict a, inc_t rs_a0, inc_t cs_a0, scomplex* restrict b, inc_t rs_b0, inc_t cs_b0, scomplex* restrict beta, scomplex* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = 0; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; scomplex *tA = a; float *tAimag = &a->imag; scomplex *tB = b; scomplex *tC = c; // clear scratch registers. __m128 xmm0, xmm1, xmm2, xmm3; __m128 xmm4 = _mm_setzero_ps(); __m128 xmm6 = _mm_setzero_ps(); __m128 xmm8 = _mm_setzero_ps(); __m128 xmm10 = _mm_setzero_ps(); __m128 xmm12 = _mm_setzero_ps(); __m128 xmm14 = _mm_setzero_ps(); dim_t ta_inc_row = rs_a; dim_t tb_inc_row = rs_b; dim_t tc_inc_row = rs_c; dim_t ta_inc_col = cs_a; dim_t tc_inc_col = cs_c; for (k_iter = 0; k_iter imag)); // load alpha_i and duplicate xmm3 = _mm_permute_ps(xmm4, 0xb1); xmm4 = _mm_mul_ps(xmm0, xmm4); xmm3 =_mm_mul_ps(xmm1, xmm3); xmm4 = _mm_addsub_ps(xmm4, xmm3); xmm3 = _mm_permute_ps(xmm8, 0xb1); xmm8 = _mm_mul_ps(xmm0, xmm8); xmm3 = _mm_mul_ps(xmm1, xmm3); xmm8 = _mm_addsub_ps(xmm8, xmm3); xmm3 = _mm_permute_ps(xmm12, 0xb1); xmm12 = _mm_mul_ps(xmm0, xmm12); xmm3 = _mm_mul_ps(xmm1, xmm3); xmm12 = _mm_addsub_ps(xmm12, xmm3); if(tc_inc_row == 1) //col stored { if(beta->real == 0.0 && beta->imag == 0.0) { //transpose 3x2 xmm0 = _mm_castpd_ps(_mm_unpacklo_pd(_mm_castps_pd (xmm4), _mm_castps_pd (xmm8))); _mm_storeu_ps((float *)(tC ), xmm0); _mm_storel_pi((__m64 *)(tC+2), xmm12); xmm1 = _mm_castpd_ps(_mm_unpackhi_pd(_mm_castps_pd (xmm4) , _mm_castps_pd(xmm8))); tC += tc_inc_col; _mm_storeu_ps((float *)(tC ), xmm1); _mm_storeh_pi((__m64 *)(tC+2), xmm12); } else{ xmm1 = _mm_broadcast_ss((float const *)(beta)); // load alpha_r and duplicate xmm2 = _mm_broadcast_ss((float const *)(&beta->imag)); // load alpha_i and duplicate //Multiply xmm4 with beta xmm0 = _mm_loadl_pi(xmm0, (__m64 const *) (tC)) ; xmm0 = _mm_loadh_pi(xmm0, (__m64 const *) (tC + tc_inc_col)); xmm3 = _mm_permute_ps(xmm0, 0xb1); xmm0 = _mm_mul_ps(xmm1, xmm0); xmm3 = _mm_mul_ps(xmm2, xmm3); xmm0 = _mm_addsub_ps(xmm0, xmm3); xmm4 = _mm_add_ps(xmm4, xmm0); //Multiply xmm8 with beta xmm0 = _mm_loadl_pi(xmm0, (__m64 const *)(tC + 1)) ; xmm0 = _mm_loadh_pi(xmm0, (__m64 const *)(tC + 1 + tc_inc_col)) ; xmm3 = _mm_permute_ps(xmm0, 0xb1); xmm0 = _mm_mul_ps(xmm1, xmm0); xmm3 = _mm_mul_ps(xmm2, xmm3); xmm0 = _mm_addsub_ps(xmm0, xmm3); xmm8 = _mm_add_ps(xmm8, xmm0); //Multiply xmm12 with beta xmm0 = _mm_loadl_pi(xmm0, (__m64 const *)(tC + 2)) ; xmm0 = _mm_loadh_pi(xmm0, (__m64 const *)(tC + 2 + tc_inc_col)) ; xmm3 = _mm_permute_ps(xmm0, 0xb1); xmm0 = _mm_mul_ps(xmm1, xmm0); xmm3 = _mm_mul_ps(xmm2, xmm3); xmm0 = _mm_addsub_ps(xmm0, xmm3); xmm12 = _mm_add_ps(xmm12, xmm0); //transpose 3x2 xmm0 = _mm_castpd_ps(_mm_unpacklo_pd(_mm_castps_pd (xmm4), _mm_castps_pd (xmm8))); _mm_storeu_ps((float *)(tC ), xmm0); _mm_storel_pi((__m64 *)(tC+2), xmm12); xmm3 = _mm_castpd_ps(_mm_unpackhi_pd(_mm_castps_pd (xmm4) , _mm_castps_pd(xmm8))); tC += tc_inc_col; _mm_storeu_ps((float *)(tC ), xmm3); _mm_storeh_pi((__m64 *)(tC+2), xmm12); } } else { if(beta->real == 0.0 && beta->imag == 0.0) { _mm_storeu_ps((float *)(tC), xmm4); _mm_storeu_ps((float *)(tC + tc_inc_row) , xmm8); _mm_storeu_ps((float *)(tC + tc_inc_row *2), xmm12); } else{ /* (br + bi) C + (ar + ai) AB */ xmm0 = _mm_broadcast_ss((float const *)(beta)); // load beta_r and duplicate xmm1 = _mm_broadcast_ss((float const *)(&beta->imag)); // load beta_i and duplicate xmm2 = _mm_loadu_ps((float const *)(tC)); xmm3 = _mm_permute_ps(xmm2, 0xb1); xmm2 = _mm_mul_ps(xmm0, xmm2); xmm3 = _mm_mul_ps(xmm1, xmm3); xmm4 = _mm_add_ps(xmm4, _mm_addsub_ps(xmm2, xmm3)); xmm2 = _mm_loadu_ps((float const *)(tC+tc_inc_row)); xmm3 = _mm_permute_ps(xmm2, 0xb1); xmm2 = _mm_mul_ps(xmm0, xmm2); xmm3 = _mm_mul_ps(xmm1, xmm3); xmm8 = _mm_add_ps(xmm8, _mm_addsub_ps(xmm2, xmm3)); xmm2 = _mm_loadu_ps((float const *)(tC+tc_inc_row*2)); xmm3 = _mm_permute_ps(xmm2, 0xb1); xmm2 = _mm_mul_ps(xmm0, xmm2); xmm3 = _mm_mul_ps(xmm1, xmm3); xmm12 = _mm_add_ps(xmm12, _mm_addsub_ps(xmm2, xmm3)); _mm_storeu_ps((float *)(tC), xmm4); _mm_storeu_ps((float *)(tC + tc_inc_row) , xmm8); _mm_storeu_ps((float *)(tC + tc_inc_row *2), xmm12);; } } } blis-0.9.0/kernels/zen/3/sup/broken/bli_gemmsup_rv_zen_asm_z3x4.c000066400000000000000000001404411422157504600247350ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define BLIS_ASM_SYNTAX_ATT #include "bli_x86_asm_macros.h" // assumes beta.r, beta.i have been broadcast into ymm1, ymm2. // outputs to ymm0 #define ZGEMM_INPUT_SCALE_CS_BETA_NZ \ vmovupd(mem(rcx), xmm0) \ vmovupd(mem(rcx, rsi, 1), xmm3) \ vinsertf128(imm(1), xmm3, ymm0, ymm0) \ vpermilpd(imm(0x5), ymm0, ymm3) \ vmulpd(ymm1, ymm0, ymm0) \ vmulpd(ymm2, ymm3, ymm3) \ vaddsubpd(ymm3, ymm0, ymm0) #define ZGEMM_INPUT_SCALE_RS_BETA_NZ \ vmovupd(mem(rcx), ymm0) \ vpermilpd(imm(0x5), ymm0, ymm3) \ vmulpd(ymm1, ymm0, ymm0) \ vmulpd(ymm2, ymm3, ymm3) \ vaddsubpd(ymm3, ymm0, ymm0) #define ZGEMM_OUTPUT_RS \ vmovupd(ymm0, mem(rcx)) \ #define ZGEMM_INPUT_SCALE_RS_BETA_NZ_NEXT \ vmovupd(mem(rcx, rsi, 8), ymm0) \ vpermilpd(imm(0x5), ymm0, ymm3) \ vmulpd(ymm1, ymm0, ymm0) \ vmulpd(ymm2, ymm3, ymm3) \ vaddsubpd(ymm3, ymm0, ymm0) #define ZGEMM_OUTPUT_RS_NEXT \ vmovupd(ymm0, mem(rcx, rsi, 8)) \ void bli_zgemmsup_rv_zen_asm_2x4 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, dcomplex* restrict alpha, dcomplex* restrict a, inc_t rs_a0, inc_t cs_a0, dcomplex* restrict b, inc_t rs_b0, inc_t cs_b0, dcomplex* restrict beta, dcomplex* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t m_iter = m0 / 3; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() mov(var(a), r14) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(dt) lea(mem(, r8, 2), r8) // rs_a *= sizeof(dt) lea(mem(, r9, 8), r9) // cs_a *= sizeof(dt) lea(mem(, r9, 2), r9) // cs_a *= sizeof(dt) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a mov(var(rs_b), r10) // load rs_b lea(mem(, r10, 8), r10) // rs_b *= sizeof(dt) lea(mem(, r10, 2), r10) // rs_b *= sizeof(dt) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(dt) lea(mem(, rdi, 2), rdi) // rs_c *= sizeof(dt) // During preamble and loops: // r12 = rcx = c // r14 = rax = a // read rbx from var(b) near beginning of loop // r11 = m dim index ii mov(var(m_iter), r11) // ii = m_iter; label(.SLOOP3X8I) // LOOP OVER ii = [ m_iter ... 1 0 ] vzeroall() // zero all xmm/ymm registers. mov(var(b), rbx) // load address of b. //mov(r12, rcx) // reset rcx to current utile of c. mov(r14, rax) // reset rax to current upanel of a. cmp(imm(16), rdi) // set ZF if (16*rs_c) == 16. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored pre-fetching on c // not used lea(mem(r12, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; jmp(.SPOSTPFETCH) // jump to end of pre-fetching c label(.SCOLPFETCH) // column-stored pre-fetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 8), rsi) // cs_c *= sizeof(dt) lea(mem(r12, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; label(.SPOSTPFETCH) // done prefetching c lea(mem(r9, r9, 2), rcx) // rcx = 3*cs_a; lea(mem(rax, r8, 4), rdx) // use rdx for pre-fetching lines lea(mem(rdx, r8, 2), rdx) // from next upanel of a. mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vbroadcastsd(mem(rax, r8, 1), ymm2) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vbroadcastsd(mem(rax, 8), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 1, 8), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) add(r9, rax) // a += cs_a; // ---------------------------------- iteration 1 vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vbroadcastsd(mem(rax, r8, 1), ymm2) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vbroadcastsd(mem(rax , 8), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 1, 8), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) add(r9, rax) // a += cs_a; // ---------------------------------- iteration 2 vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vbroadcastsd(mem(rax, r8, 1), ymm2) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vbroadcastsd(mem(rax, 8), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 1, 8), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) add(r9, rax) // a += cs_a; // ---------------------------------- iteration 3 lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vbroadcastsd(mem(rax, r8, 1), ymm2) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vbroadcastsd(mem(rax, 8), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 1, 8), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) add(r9, rax) // a += cs_a; dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vbroadcastsd(mem(rax, r8, 1), ymm2) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vbroadcastsd(mem(rax, 8), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 1, 8), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) add(r9, rax) // a += cs_a; dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(r12, rcx) // reset rcx to current utile of c. // permute even and odd elements // of ymm6/7, ymm10/11, ymm/14/15 vpermilpd(imm(0x5), ymm6, ymm6) vpermilpd(imm(0x5), ymm7, ymm7) vpermilpd(imm(0x5), ymm10, ymm10) vpermilpd(imm(0x5), ymm11, ymm11) // subtract/add even/odd elements vaddsubpd(ymm6, ymm4, ymm4) vaddsubpd(ymm7, ymm5, ymm5) vaddsubpd(ymm10, ymm8, ymm8) vaddsubpd(ymm11, ymm9, ymm9) /* (ar + ai) x AB */ mov(var(alpha), rax) // load address of alpha vbroadcastsd(mem(rax), ymm0) // load alpha_r and duplicate vbroadcastsd(mem(rax, 8), ymm1) // load alpha_i and duplicate vpermilpd(imm(0x5), ymm4, ymm3) vmulpd(ymm0, ymm4, ymm4) vmulpd(ymm1, ymm3, ymm3) vaddsubpd(ymm3, ymm4, ymm4) vpermilpd(imm(0x5), ymm5, ymm3) vmulpd(ymm0, ymm5, ymm5) vmulpd(ymm1, ymm3, ymm3) vaddsubpd(ymm3, ymm5, ymm5) vpermilpd(imm(0x5), ymm8, ymm3) vmulpd(ymm0, ymm8, ymm8) vmulpd(ymm1, ymm3, ymm3) vaddsubpd(ymm3, ymm8, ymm8) vpermilpd(imm(0x5), ymm9, ymm3) vmulpd(ymm0, ymm9, ymm9) vmulpd(ymm1, ymm3, ymm3) vaddsubpd(ymm3, ymm9, ymm9) /* (ßr + ßi)x C + ((ar + ai) x AB) */ mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rbx), ymm1) // load beta_r and duplicate vbroadcastsd(mem(rbx, 8), ymm2) // load beta_i and duplicate mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(dt) lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm1) // set ZF if beta_r == 0. sete(r13b) // r13b = ( ZF == 1 ? 1 : 0 ); vucomisd(xmm0, xmm2) // set ZF if beta_i == 0. sete(r15b) // r15b = ( ZF == 1 ? 1 : 0 ); and(r13b, r15b) // set ZF if r13b & r15b == 1. jne(.SBETAZERO) // if ZF = 1, jump to beta == 0 case lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a cmp(imm(16), rdi) // set ZF if (16*rs_c) ==16. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) ZGEMM_INPUT_SCALE_RS_BETA_NZ vaddpd(ymm4, ymm0, ymm0) ZGEMM_OUTPUT_RS ZGEMM_INPUT_SCALE_RS_BETA_NZ_NEXT vaddpd(ymm5, ymm0, ymm0) ZGEMM_OUTPUT_RS_NEXT add(rdi, rcx) // rcx = c + 1*rs_c ZGEMM_INPUT_SCALE_RS_BETA_NZ vaddpd(ymm8, ymm0, ymm0) ZGEMM_OUTPUT_RS ZGEMM_INPUT_SCALE_RS_BETA_NZ_NEXT vaddpd(ymm9, ymm0, ymm0) ZGEMM_OUTPUT_RS_NEXT jmp(.SDONE) // jump to end. label(.SCOLSTORED) /*|--------| |-------| | | | | | 2x4 | | 4x2 | |--------| |-------| */ mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(real dt) lea(mem(, rsi, 2), rsi) // rsi = cs_c * sizeof((real+imag) dt) lea(mem(rsi, rsi, 2), r13) // r13 = 3*rs_a ZGEMM_INPUT_SCALE_CS_BETA_NZ vaddpd(ymm4, ymm0, ymm4) add(rdi, rcx) ZGEMM_INPUT_SCALE_CS_BETA_NZ vaddpd(ymm8, ymm0, ymm8) add(rdi, rcx) lea(mem(r12, rsi, 2), rcx) ZGEMM_INPUT_SCALE_CS_BETA_NZ vaddpd(ymm5, ymm0, ymm5) add(rdi, rcx) ZGEMM_INPUT_SCALE_CS_BETA_NZ vaddpd(ymm9, ymm0, ymm9) add(rdi, rcx) mov(r12, rcx) // reset rcx to current utile of c. /****3x4 tile going to save into 4x2 tile in C*****/ mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(dt) lea(mem(, rsi, 2), rsi) // rsi = cs_c * sizeof(dt) /******************Transpose top tile 4x3***************************/ vmovups(xmm4, mem(rcx)) vmovups(xmm8, mem(rcx, 16)) add(rsi, rcx) vextractf128(imm(0x1), ymm4, xmm4) vextractf128(imm(0x1), ymm8, xmm8) vmovups(xmm4, mem(rcx)) vmovups(xmm8, mem(rcx, 16)) add(rsi, rcx) vmovups(xmm5, mem(rcx)) vmovups(xmm9, mem(rcx, 16)) add(rsi, rcx) vextractf128(imm(0x1), ymm5, xmm5) vextractf128(imm(0x1), ymm9, xmm9) vmovups(xmm5, mem(rcx)) vmovups(xmm9, mem(rcx, 16)) jmp(.SDONE) // jump to end. label(.SBETAZERO) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a cmp(imm(16), rdi) // set ZF if (16*rs_c) == 16. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovupd(ymm4, mem(rcx)) vmovupd(ymm5, mem(rcx, rsi, 8)) add(rdi, rcx) vmovupd(ymm8, mem(rcx)) vmovupd(ymm9, mem(rcx, rsi, 8)) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) /****2x4 tile going to save into 4x2 tile in C*****/ mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(dt) lea(mem(, rsi, 2), rsi) // rsi = cs_c * sizeof(dt) /******************Transpose tile 2x4***************************/ vmovups(xmm4, mem(rcx)) vmovups(xmm8, mem(rcx, 16)) add(rsi, rcx) vextractf128(imm(0x1), ymm4, xmm4) vextractf128(imm(0x1), ymm8, xmm8) vmovups(xmm4, mem(rcx)) vmovups(xmm8, mem(rcx, 16)) add(rsi, rcx) vmovups(xmm5, mem(rcx)) vmovups(xmm9, mem(rcx, 16)) add(rsi, rcx) vextractf128(imm(0x1), ymm5, xmm5) vextractf128(imm(0x1), ymm9, xmm9) vmovups(xmm5, mem(rcx)) vmovups(xmm9, mem(rcx, 16)) label(.SDONE) end_asm( : // output operands (none) : // input operands [m_iter] "m" (m_iter), [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_zgemmsup_rv_zen_asm_1x4 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, dcomplex* restrict alpha, dcomplex* restrict a, inc_t rs_a0, inc_t cs_a0, dcomplex* restrict b, inc_t rs_b0, inc_t cs_b0, dcomplex* restrict beta, dcomplex* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t m_iter = m0 / 3; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() mov(var(a), r14) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(dt) lea(mem(, r8, 2), r8) // rs_a *= sizeof(dt) lea(mem(, r9, 8), r9) // cs_a *= sizeof(dt) lea(mem(, r9, 2), r9) // cs_a *= sizeof(dt) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a mov(var(rs_b), r10) // load rs_b lea(mem(, r10, 8), r10) // rs_b *= sizeof(dt) lea(mem(, r10, 2), r10) // rs_b *= sizeof(dt) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(dt) lea(mem(, rdi, 2), rdi) // rs_c *= sizeof(dt) // During preamble and loops: // r12 = rcx = c // r14 = rax = a // read rbx from var(b) near beginning of loop // r11 = m dim index ii mov(var(m_iter), r11) // ii = m_iter; label(.SLOOP3X8I) // LOOP OVER ii = [ m_iter ... 1 0 ] vzeroall() // zero all xmm/ymm registers. mov(var(b), rbx) // load address of b. //mov(r12, rcx) // reset rcx to current utile of c. mov(r14, rax) // reset rax to current upanel of a. cmp(imm(16), rdi) // set ZF if (16*rs_c) == 16. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored pre-fetching on c // not used lea(mem(r12, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; jmp(.SPOSTPFETCH) // jump to end of pre-fetching c label(.SCOLPFETCH) // column-stored pre-fetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 8), rsi) // cs_c *= sizeof(dt) lea(mem(r12, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; label(.SPOSTPFETCH) // done prefetching c lea(mem(r9, r9, 2), rcx) // rcx = 3*cs_a; lea(mem(rax, r8, 4), rdx) // use rdx for pre-fetching lines lea(mem(rdx, r8, 2), rdx) // from next upanel of a. mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vbroadcastsd(mem(rax, 8), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) add(r9, rax) // a += cs_a; // ---------------------------------- iteration 1 vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vbroadcastsd(mem(rax , 8), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) add(r9, rax) // a += cs_a; // ---------------------------------- iteration 2 vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vbroadcastsd(mem(rax, 8), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) add(r9, rax) // a += cs_a; // ---------------------------------- iteration 3 lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vbroadcastsd(mem(rax, 8), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) add(r9, rax) // a += cs_a; dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vbroadcastsd(mem(rax, 8), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) add(r9, rax) // a += cs_a; dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(r12, rcx) // reset rcx to current utile of c. // permute even and odd elements // of ymm6/7, ymm10/11, ymm/14/15 vpermilpd(imm(0x5), ymm6, ymm6) vpermilpd(imm(0x5), ymm7, ymm7) // subtract/add even/odd elements vaddsubpd(ymm6, ymm4, ymm4) vaddsubpd(ymm7, ymm5, ymm5) /* (ar + ai) x AB */ mov(var(alpha), rax) // load address of alpha vbroadcastsd(mem(rax), ymm0) // load alpha_r and duplicate vbroadcastsd(mem(rax, 8), ymm1) // load alpha_i and duplicate vpermilpd(imm(0x5), ymm4, ymm3) vmulpd(ymm0, ymm4, ymm4) vmulpd(ymm1, ymm3, ymm3) vaddsubpd(ymm3, ymm4, ymm4) vpermilpd(imm(0x5), ymm5, ymm3) vmulpd(ymm0, ymm5, ymm5) vmulpd(ymm1, ymm3, ymm3) vaddsubpd(ymm3, ymm5, ymm5) /* (ßr + ßi)x C + ((ar + ai) x AB) */ mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rbx), ymm1) // load beta_r and duplicate vbroadcastsd(mem(rbx, 8), ymm2) // load beta_i and duplicate mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(dt) lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm1) // set ZF if beta_r == 0. sete(r13b) // r13b = ( ZF == 1 ? 1 : 0 ); vucomisd(xmm0, xmm2) // set ZF if beta_i == 0. sete(r15b) // r15b = ( ZF == 1 ? 1 : 0 ); and(r13b, r15b) // set ZF if r13b & r15b == 1. jne(.SBETAZERO) // if ZF = 1, jump to beta == 0 case lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a cmp(imm(16), rdi) // set ZF if (16*rs_c) ==16. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) ZGEMM_INPUT_SCALE_RS_BETA_NZ vaddpd(ymm4, ymm0, ymm0) ZGEMM_OUTPUT_RS ZGEMM_INPUT_SCALE_RS_BETA_NZ_NEXT vaddpd(ymm5, ymm0, ymm0) ZGEMM_OUTPUT_RS_NEXT jmp(.SDONE) // jump to end. label(.SCOLSTORED) /*|--------| |-------| | | | | | 1x4 | | 4x1 | |--------| |-------| */ mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(real dt) lea(mem(, rsi, 2), rsi) // rsi = cs_c * sizeof((real+imag) dt) lea(mem(rsi, rsi, 2), r13) // r13 = 3*rs_a ZGEMM_INPUT_SCALE_CS_BETA_NZ vaddpd(ymm4, ymm0, ymm4) lea(mem(r12, rsi, 2), rcx) ZGEMM_INPUT_SCALE_CS_BETA_NZ vaddpd(ymm5, ymm0, ymm5) mov(r12, rcx) // reset rcx to current utile of c. /****1x4 tile going to save into 4x1 tile in C*****/ mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(dt) lea(mem(, rsi, 2), rsi) // rsi = cs_c * sizeof(dt) vmovups(xmm4, mem(rcx)) add(rsi, rcx) vextractf128(imm(0x1), ymm4, xmm4) vmovups(xmm4, mem(rcx)) add(rsi, rcx) vmovups(xmm5, mem(rcx)) add(rsi, rcx) vextractf128(imm(0x1), ymm5, xmm5) vmovups(xmm5, mem(rcx)) jmp(.SDONE) // jump to end. label(.SBETAZERO) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a cmp(imm(16), rdi) // set ZF if (16*rs_c) == 16. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovupd(ymm4, mem(rcx)) vmovupd(ymm5, mem(rcx, rsi, 8)) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) /****1x4 tile going to save into 4x1 tile in C*****/ mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(dt) lea(mem(, rsi, 2), rsi) // rsi = cs_c * sizeof(dt) vmovups(xmm4, mem(rcx)) add(rsi, rcx) vextractf128(imm(0x1), ymm4, xmm4) vmovups(xmm4, mem(rcx)) add(rsi, rcx) vmovups(xmm5, mem(rcx)) add(rsi, rcx) vextractf128(imm(0x1), ymm5, xmm5) vmovups(xmm5, mem(rcx)) label(.SDONE) end_asm( : // output operands (none) : // input operands [m_iter] "m" (m_iter), [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_zgemmsup_rv_zen_asm_2x2 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, dcomplex* restrict alpha, dcomplex* restrict a, inc_t rs_a0, inc_t cs_a0, dcomplex* restrict b, inc_t rs_b0, inc_t cs_b0, dcomplex* restrict beta, dcomplex* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t m_iter = m0 / 3; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() mov(var(a), r14) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(dt) lea(mem(, r8, 2), r8) // rs_a *= sizeof(dt) lea(mem(, r9, 8), r9) // cs_a *= sizeof(dt) lea(mem(, r9, 2), r9) // cs_a *= sizeof(dt) mov(var(rs_b), r10) // load rs_b lea(mem(, r10, 8), r10) // rs_b *= sizeof(dt) lea(mem(, r10, 2), r10) // rs_b *= sizeof(dt) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(dt) lea(mem(, rdi, 2), rdi) // rs_c *= sizeof(dt) // During preamble and loops: // r12 = rcx = c // r14 = rax = a // read rbx from var(b) near beginning of loop // r11 = m dim index ii mov(var(m_iter), r11) // ii = m_iter; label(.SLOOP3X8I) // LOOP OVER ii = [ m_iter ... 1 0 ] vzeroall() // zero all xmm/ymm registers. mov(var(b), rbx) // load address of b. //mov(r12, rcx) // reset rcx to current utile of c. mov(r14, rax) // reset rax to current upanel of a. cmp(imm(16), rdi) // set ZF if (16*rs_c) == 16. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored pre-fetching on c // not used lea(mem(r12, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; jmp(.SPOSTPFETCH) // jump to end of pre-fetching c label(.SCOLPFETCH) // column-stored pre-fetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 8), rsi) // cs_c *= sizeof(dt) lea(mem(r12, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; label(.SPOSTPFETCH) // done prefetching c lea(mem(r9, r9, 2), rcx) // rcx = 3*cs_a; lea(mem(rax, r8, 4), rdx) // use rdx for pre-fetching lines lea(mem(rdx, r8, 2), rdx) // from next upanel of a. mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vfmadd231pd(ymm0, ymm2, ymm4) vbroadcastsd(mem(rax, r8, 1), ymm2) vfmadd231pd(ymm0, ymm2, ymm8) vbroadcastsd(mem(rax, 8), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vbroadcastsd(mem(rax, r8, 1, 8), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) add(r9, rax) // a += cs_a; // ---------------------------------- iteration 1 vmovupd(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vfmadd231pd(ymm0, ymm2, ymm4) vbroadcastsd(mem(rax, r8, 1), ymm2) vfmadd231pd(ymm0, ymm2, ymm8) vbroadcastsd(mem(rax, 8), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vbroadcastsd(mem(rax, r8, 1, 8), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) add(r9, rax) // a += cs_a; // ---------------------------------- iteration 2 vmovupd(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vfmadd231pd(ymm0, ymm2, ymm4) vbroadcastsd(mem(rax, r8, 1), ymm2) vfmadd231pd(ymm0, ymm2, ymm8) vbroadcastsd(mem(rax, 8), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vbroadcastsd(mem(rax, r8, 1, 8), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) add(r9, rax) // a += cs_a; // ---------------------------------- iteration 3 lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; vmovupd(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vfmadd231pd(ymm0, ymm2, ymm4) vbroadcastsd(mem(rax, r8, 1), ymm2) vfmadd231pd(ymm0, ymm2, ymm8) vbroadcastsd(mem(rax, 8), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vbroadcastsd(mem(rax, r8, 1, 8), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) add(r9, rax) // a += cs_a; dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP vmovupd(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vfmadd231pd(ymm0, ymm2, ymm4) vbroadcastsd(mem(rax, r8, 1), ymm2) vfmadd231pd(ymm0, ymm2, ymm8) vbroadcastsd(mem(rax, 8), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vbroadcastsd(mem(rax, r8, 1, 8), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) add(r9, rax) // a += cs_a; dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(r12, rcx) // reset rcx to current utile of c. // permute even and odd elements // of ymm6/7, ymm10/11, ymm/14/15 vpermilpd(imm(0x5), ymm6, ymm6) vpermilpd(imm(0x5), ymm10, ymm10) // subtract/add even/odd elements vaddsubpd(ymm6, ymm4, ymm4) vaddsubpd(ymm10, ymm8, ymm8) /* (ar + ai) x AB */ mov(var(alpha), rax) // load address of alpha vbroadcastsd(mem(rax), ymm0) // load alpha_r and duplicate vbroadcastsd(mem(rax, 8), ymm1) // load alpha_i and duplicate vpermilpd(imm(0x5), ymm4, ymm3) vmulpd(ymm0, ymm4, ymm4) vmulpd(ymm1, ymm3, ymm3) vaddsubpd(ymm3, ymm4, ymm4) vpermilpd(imm(0x5), ymm8, ymm3) vmulpd(ymm0, ymm8, ymm8) vmulpd(ymm1, ymm3, ymm3) vaddsubpd(ymm3, ymm8, ymm8) /* (ßr + ßi)x C + ((ar + ai) x AB) */ mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rbx), ymm1) // load beta_r and duplicate vbroadcastsd(mem(rbx, 8), ymm2) // load beta_i and duplicate mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(dt) lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm1) // set ZF if beta_r == 0. sete(r13b) // r13b = ( ZF == 1 ? 1 : 0 ); vucomisd(xmm0, xmm2) // set ZF if beta_i == 0. sete(r15b) // r15b = ( ZF == 1 ? 1 : 0 ); and(r13b, r15b) // set ZF if r13b & r15b == 1. jne(.SBETAZERO) // if ZF = 1, jump to beta == 0 case lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a cmp(imm(16), rdi) // set ZF if (16*rs_c) == 16. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) ZGEMM_INPUT_SCALE_RS_BETA_NZ vaddpd(ymm4, ymm0, ymm0) ZGEMM_OUTPUT_RS add(rdi, rcx) // rcx = c + 1*rs_c ZGEMM_INPUT_SCALE_RS_BETA_NZ vaddpd(ymm8, ymm0, ymm0) ZGEMM_OUTPUT_RS jmp(.SDONE) // jump to end. label(.SCOLSTORED) /*|--------| |-------| | | | | | 2x2 | | 2x2 | |--------| |-------| */ mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(real dt) lea(mem(, rsi, 2), rsi) // rsi = cs_c * sizeof((real+imag) dt) lea(mem(rsi, rsi, 2), r13) // r13 = 3*rs_a ZGEMM_INPUT_SCALE_CS_BETA_NZ vaddpd(ymm4, ymm0, ymm4) add(rdi, rcx) ZGEMM_INPUT_SCALE_CS_BETA_NZ vaddpd(ymm8, ymm0, ymm8) mov(r12, rcx) // reset rcx to current utile of c. /****2x2 tile going to save into 2x2 tile in C*****/ mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(dt) lea(mem(, rsi, 2), rsi) // rsi = cs_c * sizeof(dt) vmovups(xmm4, mem(rcx)) vmovups(xmm8, mem(rcx, 16)) add(rsi, rcx) vextractf128(imm(0x1), ymm4, xmm4) vextractf128(imm(0x1), ymm8, xmm8) vmovups(xmm4, mem(rcx)) vmovups(xmm8, mem(rcx, 16)) jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(16), rdi) // set ZF if (8*rs_c) == 8. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vmovupd(ymm8, mem(rcx)) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) /****2x2 tile going to save into 2x2 tile in C*****/ mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(dt) lea(mem(, rsi, 2), rsi) // rsi = cs_c * sizeof(dt) vmovups(xmm4, mem(rcx)) vmovups(xmm8, mem(rcx, 16)) add(rsi, rcx) vextractf128(imm(0x1), ymm4, xmm4) vextractf128(imm(0x1), ymm8, xmm8) vmovups(xmm4, mem(rcx)) vmovups(xmm8, mem(rcx, 16)) label(.SDONE) end_asm( : // output operands (none) : // input operands [m_iter] "m" (m_iter), [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_zgemmsup_rv_zen_asm_1x2 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, dcomplex* restrict alpha, dcomplex* restrict a, inc_t rs_a0, inc_t cs_a0, dcomplex* restrict b, inc_t rs_b0, inc_t cs_b0, dcomplex* restrict beta, dcomplex* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t m_iter = m0 / 3; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() mov(var(a), r14) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(dt) lea(mem(, r8, 2), r8) // rs_a *= sizeof(dt) lea(mem(, r9, 8), r9) // cs_a *= sizeof(dt) lea(mem(, r9, 2), r9) // cs_a *= sizeof(dt) // lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a mov(var(rs_b), r10) // load rs_b lea(mem(, r10, 8), r10) // rs_b *= sizeof(dt) lea(mem(, r10, 2), r10) // rs_b *= sizeof(dt) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(dt) lea(mem(, rdi, 2), rdi) // rs_c *= sizeof(dt) // During preamble and loops: // r12 = rcx = c // r14 = rax = a // read rbx from var(b) near beginning of loop // r11 = m dim index ii mov(var(m_iter), r11) // ii = m_iter; label(.SLOOP3X8I) // LOOP OVER ii = [ m_iter ... 1 0 ] vzeroall() // zero all xmm/ymm registers. mov(var(b), rbx) // load address of b. //mov(r12, rcx) // reset rcx to current utile of c. mov(r14, rax) // reset rax to current upanel of a. cmp(imm(16), rdi) // set ZF if (16*rs_c) == 16. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored pre-fetching on c // not used lea(mem(r12, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; jmp(.SPOSTPFETCH) // jump to end of pre-fetching c label(.SCOLPFETCH) // column-stored pre-fetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 8), rsi) // cs_c *= sizeof(dt) lea(mem(r12, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; label(.SPOSTPFETCH) // done prefetching c lea(mem(r9, r9, 2), rcx) // rcx = 3*cs_a; lea(mem(rax, r8, 4), rdx) // use rdx for pre-fetching lines lea(mem(rdx, r8, 2), rdx) // from next upanel of a. mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vfmadd231pd(ymm0, ymm2, ymm4) vbroadcastsd(mem(rax, 8), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) add(r9, rax) // a += cs_a; // ---------------------------------- iteration 1 vmovupd(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vfmadd231pd(ymm0, ymm2, ymm4) vbroadcastsd(mem(rax, 8), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) add(r9, rax) // a += cs_a; // ---------------------------------- iteration 2 vmovupd(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vfmadd231pd(ymm0, ymm2, ymm4) vbroadcastsd(mem(rax, 8), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) add(r9, rax) // a += cs_a; // ---------------------------------- iteration 3 lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; vmovupd(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vfmadd231pd(ymm0, ymm2, ymm4) vbroadcastsd(mem(rax, 8), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) add(r9, rax) // a += cs_a; dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP vmovupd(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vfmadd231pd(ymm0, ymm2, ymm4) vbroadcastsd(mem(rax, 8), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) add(r9, rax) // a += cs_a; dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(r12, rcx) // reset rcx to current utile of c. // permute even and odd elements // of ymm6/7, ymm10/11, ymm/14/15 vpermilpd(imm(0x5), ymm6, ymm6) // subtract/add even/odd elements vaddsubpd(ymm6, ymm4, ymm4) /* (ar + ai) x AB */ mov(var(alpha), rax) // load address of alpha vbroadcastsd(mem(rax), ymm0) // load alpha_r and duplicate vbroadcastsd(mem(rax, 8), ymm1) // load alpha_i and duplicate vpermilpd(imm(0x5), ymm4, ymm3) vmulpd(ymm0, ymm4, ymm4) vmulpd(ymm1, ymm3, ymm3) vaddsubpd(ymm3, ymm4, ymm4) /* (ßr + ßi)x C + ((ar + ai) x AB) */ mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rbx), ymm1) // load beta_r and duplicate vbroadcastsd(mem(rbx, 8), ymm2) // load beta_i and duplicate mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(dt) lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm1) // set ZF if beta_r == 0. sete(r13b) // r13b = ( ZF == 1 ? 1 : 0 ); vucomisd(xmm0, xmm2) // set ZF if beta_i == 0. sete(r15b) // r15b = ( ZF == 1 ? 1 : 0 ); and(r13b, r15b) // set ZF if r13b & r15b == 1. jne(.SBETAZERO) // if ZF = 1, jump to beta == 0 case lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a cmp(imm(16), rdi) // set ZF if (16*rs_c) == 16. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) ZGEMM_INPUT_SCALE_RS_BETA_NZ vaddpd(ymm4, ymm0, ymm0) ZGEMM_OUTPUT_RS jmp(.SDONE) // jump to end. label(.SCOLSTORED) /*|--------| |-------| | | | | | 1x2 | | 2x1 | |--------| |-------| */ mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(real dt) lea(mem(, rsi, 2), rsi) // rsi = cs_c * sizeof((real+imag) dt) lea(mem(rsi, rsi, 2), r13) // r13 = 3*rs_a ZGEMM_INPUT_SCALE_CS_BETA_NZ vaddpd(ymm4, ymm0, ymm4) /****3x4 tile going to save into 4x3 tile in C*****/ mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(dt) lea(mem(, rsi, 2), rsi) // rsi = cs_c * sizeof(dt) /******************Transpose tile 1x2***************************/ vmovups(xmm4, mem(rcx)) add(rsi, rcx) vextractf128(imm(0x1), ymm4, xmm4) vmovups(xmm4, mem(rcx)) jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(16), rdi) // set ZF if (8*rs_c) == 8. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) /****1x2 tile going to save into 2x1 tile in C*****/ mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(dt) lea(mem(, rsi, 2), rsi) // rsi = cs_c * sizeof(dt) /******************Transpose top tile 4x3***************************/ vmovups(xmm4, mem(rcx)) add(rsi, rcx) vextractf128(imm(0x1), ymm4, xmm4) vmovups(xmm4, mem(rcx)) label(.SDONE) end_asm( : // output operands (none) : // input operands [m_iter] "m" (m_iter), [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } blis-0.9.0/kernels/zen/3/sup/broken/bli_gemmsup_rv_zen_asm_z3x4m.c000066400000000000000000001073071422157504600251160ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define BLIS_ASM_SYNTAX_ATT #include "bli_x86_asm_macros.h" // assumes beta.r, beta.i have been broadcast into ymm1, ymm2. // outputs to ymm0 #define ZGEMM_INPUT_SCALE_CS_BETA_NZ \ vmovupd(mem(rcx), xmm0) \ vmovupd(mem(rcx, rsi, 1), xmm3) \ vinsertf128(imm(1), xmm3, ymm0, ymm0) \ vpermilpd(imm(0x5), ymm0, ymm3) \ vmulpd(ymm1, ymm0, ymm0) \ vmulpd(ymm2, ymm3, ymm3) \ vaddsubpd(ymm3, ymm0, ymm0) #define ZGEMM_INPUT_SCALE_RS_BETA_NZ \ vmovupd(mem(rcx), ymm0) \ vpermilpd(imm(0x5), ymm0, ymm3) \ vmulpd(ymm1, ymm0, ymm0) \ vmulpd(ymm2, ymm3, ymm3) \ vaddsubpd(ymm3, ymm0, ymm0) #define ZGEMM_OUTPUT_RS \ vmovupd(ymm0, mem(rcx)) \ #define ZGEMM_INPUT_SCALE_RS_BETA_NZ_NEXT \ vmovupd(mem(rcx, rsi, 8), ymm0) \ vpermilpd(imm(0x5), ymm0, ymm3) \ vmulpd(ymm1, ymm0, ymm0) \ vmulpd(ymm2, ymm3, ymm3) \ vaddsubpd(ymm3, ymm0, ymm0) #define ZGEMM_OUTPUT_RS_NEXT \ vmovupd(ymm0, mem(rcx, rsi, 8)) \ /* rrr: -------- ------ -------- -------- += ------ ... -------- -------- ------ -------- -------- ------ : rcr: -------- | | | | -------- -------- += | | | | ... -------- -------- | | | | -------- -------- | | | | : Assumptions: - B is row-stored; - A is row- or column-stored; - m0 and n0 are at most MR and NR, respectively. Therefore, this (r)ow-preferential kernel is well-suited for contiguous (v)ector loads on B and single-element broadcasts from A. NOTE: These kernels explicitly support column-oriented IO, implemented via an in-register transpose. And thus they also support the crr and ccr cases, though only crr is ever utilized (because ccr is handled by transposing the operation and executing rcr, which does not incur the cost of the in-register transpose). crr: | | | | | | | | ------ -------- | | | | | | | | += ------ -------- | | | | | | | | ------ -------- | | | | | | | | ------ : */ void bli_zgemmsup_rv_zen_asm_3x4m ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, dcomplex* restrict alpha, dcomplex* restrict a, inc_t rs_a0, inc_t cs_a0, dcomplex* restrict b, inc_t rs_b0, inc_t cs_b0, dcomplex* restrict beta, dcomplex* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { uint64_t n_left = n0 % 4; // First check whether this is a edge case in the n dimension. If so, // dispatch other 3x?m kernels, as needed. if (n_left ) { dcomplex* cij = c; dcomplex* bj = b; dcomplex* ai = a; if ( 2 <= n_left ) { const dim_t nr_cur = 2; bli_zgemmsup_rv_zen_asm_3x2m ( conja, conjb, m0, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 1 == n_left ) { bli_zgemv_ex ( BLIS_NO_TRANSPOSE, conjb, m0, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, beta, cij, rs_c0, cntx, NULL ); } return; } //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t m_iter = m0 / 3; uint64_t m_left = m0 % 3; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; if ( m_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() mov(var(a), r14) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(real dt) lea(mem(, r8, 2), r8) // rs_a *= sizeof((real + imag) dt) lea(mem(, r9, 8), r9) // cs_a *= sizeof( real dt) lea(mem(, r9, 2), r9) // cs_a *= sizeof((real + imag) dt) //lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a mov(var(rs_b), r10) // load rs_b lea(mem(, r10, 8), r10) // rs_b *= sizeof(real dt) lea(mem(, r10, 2), r10) // rs_b *= sizeof((real +imag) dt) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(dt) lea(mem(, rdi, 2), rdi) // rs_c *= sizeof(dt) // During preamble and loops: // r12 = rcx = c // r14 = rax = a // read rbx from var(b) near beginning of loop // r11 = m dim index ii mov(var(m_iter), r11) // ii = m_iter; label(.SLOOP3X8I) // LOOP OVER ii = [ m_iter ... 1 0 ] vzeroall() // zero all xmm/ymm registers. mov(var(b), rbx) // load address of b. mov(r14, rax) // reset rax to current upanel of a. cmp(imm(16), rdi) // set ZF if (16*rs_c) == 16. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored pre-fetching on c // not used lea(mem(r12, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; jmp(.SPOSTPFETCH) // jump to end of pre-fetching c label(.SCOLPFETCH) // column-stored pre-fetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 8), rsi) // cs_c *= sizeof(dt) lea(mem(r12, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; label(.SPOSTPFETCH) // done prefetching c lea(mem(r9, r9, 2), rcx) // rcx = 3*cs_a; lea(mem(rax, r8, 4), rdx) // use rdx for pre-fetching lines lea(mem(rdx, r8, 2), rdx) // from next upanel of a. mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vbroadcastsd(mem(rax, r8, 1), ymm2) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vbroadcastsd(mem(rax, r8, 2), ymm2) vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) vbroadcastsd(mem(rax, 8), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 1, 8), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, r8, 2, 8), ymm3) vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) add(r9, rax) // a += cs_a; // ---------------------------------- iteration 1 vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vbroadcastsd(mem(rax, r8, 1), ymm2) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vbroadcastsd(mem(rax, r8, 2), ymm2) vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) vbroadcastsd(mem(rax, 8 ), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 1, 8), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, r8, 2, 8), ymm3) vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) add(r9, rax) // a += cs_a; // ---------------------------------- iteration 2 vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vbroadcastsd(mem(rax, r8, 1), ymm2) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vbroadcastsd(mem(rax, r8, 2), ymm2) vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) vbroadcastsd(mem(rax, 8 ), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 1, 8), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, r8, 2, 8), ymm3) vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) add(r9, rax) // a += cs_a; // ---------------------------------- iteration 3 lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vbroadcastsd(mem(rax, r8, 1), ymm2) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vbroadcastsd(mem(rax, r8, 2), ymm2) vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) vbroadcastsd(mem(rax, 8), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 1, 8), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, r8, 2, 8), ymm3) vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) add(r9, rax) // a += cs_a; dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP vmovupd(mem(rbx, 0*32), ymm0) vmovupd(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vfmadd231pd(ymm0, ymm2, ymm4) vfmadd231pd(ymm1, ymm2, ymm5) vbroadcastsd(mem(rax, r8, 1), ymm2) vfmadd231pd(ymm0, ymm2, ymm8) vfmadd231pd(ymm1, ymm2, ymm9) vbroadcastsd(mem(rax, r8, 2), ymm2) vfmadd231pd(ymm0, ymm2, ymm12) vfmadd231pd(ymm1, ymm2, ymm13) vbroadcastsd(mem(rax, 8), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vfmadd231pd(ymm1, ymm3, ymm7) vbroadcastsd(mem(rax, r8, 1, 8), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vfmadd231pd(ymm1, ymm3, ymm11) vbroadcastsd(mem(rax, r8, 2, 8), ymm3) vfmadd231pd(ymm0, ymm3, ymm14) vfmadd231pd(ymm1, ymm3, ymm15) add(r9, rax) // a += cs_a; dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(r12, rcx) // reset rcx to current utile of c. // permute even and odd elements // of ymm6/7, ymm10/11, ymm/14/15 vpermilpd(imm(0x5), ymm6, ymm6) vpermilpd(imm(0x5), ymm7, ymm7) vpermilpd(imm(0x5), ymm10, ymm10) vpermilpd(imm(0x5), ymm11, ymm11) vpermilpd(imm(0x5), ymm14, ymm14) vpermilpd(imm(0x5), ymm15, ymm15) // subtract/add even/odd elements vaddsubpd(ymm6, ymm4, ymm4) vaddsubpd(ymm7, ymm5, ymm5) vaddsubpd(ymm10, ymm8, ymm8) vaddsubpd(ymm11, ymm9, ymm9) vaddsubpd(ymm14, ymm12, ymm12) vaddsubpd(ymm15, ymm13, ymm13) /* (ar + ai) x AB */ mov(var(alpha), rax) // load address of alpha vbroadcastsd(mem(rax), ymm0) // load alpha_r and duplicate vbroadcastsd(mem(rax, 8), ymm1) // load alpha_i and duplicate vpermilpd(imm(0x5), ymm4, ymm3) vmulpd(ymm0, ymm4, ymm4) vmulpd(ymm1, ymm3, ymm3) vaddsubpd(ymm3, ymm4, ymm4) vpermilpd(imm(0x5), ymm5, ymm3) vmulpd(ymm0, ymm5, ymm5) vmulpd(ymm1, ymm3, ymm3) vaddsubpd(ymm3, ymm5, ymm5) vpermilpd(imm(0x5), ymm8, ymm3) vmulpd(ymm0, ymm8, ymm8) vmulpd(ymm1, ymm3, ymm3) vaddsubpd(ymm3, ymm8, ymm8) vpermilpd(imm(0x5), ymm9, ymm3) vmulpd(ymm0, ymm9, ymm9) vmulpd(ymm1, ymm3, ymm3) vaddsubpd(ymm3, ymm9, ymm9) vpermilpd(imm(0x5), ymm12, ymm3) vmulpd(ymm0, ymm12, ymm12) vmulpd(ymm1, ymm3, ymm3) vaddsubpd(ymm3, ymm12, ymm12) vpermilpd(imm(0x5), ymm13, ymm3) vmulpd(ymm0, ymm13, ymm13) vmulpd(ymm1, ymm3, ymm3) vaddsubpd(ymm3, ymm13, ymm13) /* (ßr + ßi)x C + ((ar + ai) x AB) */ mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rbx), ymm1) // load beta_r and duplicate vbroadcastsd(mem(rbx, 8), ymm2) // load beta_i and duplicate mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(dt) lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm1) // set ZF if beta_r == 0. sete(r13b) // r13b = ( ZF == 1 ? 1 : 0 ); vucomisd(xmm0, xmm2) // set ZF if beta_i == 0. sete(r15b) // r15b = ( ZF == 1 ? 1 : 0 ); and(r13b, r15b) // set ZF if r13b & r15b == 1. jne(.SBETAZERO) // if ZF = 1, jump to beta == 0 case lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a cmp(imm(16), rdi) // set ZF if (16*rs_c) ==16. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) ZGEMM_INPUT_SCALE_RS_BETA_NZ vaddpd(ymm4, ymm0, ymm0) ZGEMM_OUTPUT_RS ZGEMM_INPUT_SCALE_RS_BETA_NZ_NEXT vaddpd(ymm5, ymm0, ymm0) ZGEMM_OUTPUT_RS_NEXT add(rdi, rcx) // rcx = c + 1*rs_c ZGEMM_INPUT_SCALE_RS_BETA_NZ vaddpd(ymm8, ymm0, ymm0) ZGEMM_OUTPUT_RS ZGEMM_INPUT_SCALE_RS_BETA_NZ_NEXT vaddpd(ymm9, ymm0, ymm0) ZGEMM_OUTPUT_RS_NEXT add(rdi, rcx) // rcx = c + 2*rs_c ZGEMM_INPUT_SCALE_RS_BETA_NZ vaddpd(ymm12, ymm0, ymm0) ZGEMM_OUTPUT_RS ZGEMM_INPUT_SCALE_RS_BETA_NZ_NEXT vaddpd(ymm13, ymm0, ymm0) ZGEMM_OUTPUT_RS_NEXT jmp(.SDONE) // jump to end. label(.SCOLSTORED) /*|--------| |-------| | | | | | 3x4 | | 4x3 | |--------| |-------| */ mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(real dt) lea(mem(, rsi, 2), rsi) // rsi = cs_c * sizeof((real +imag)dt) lea(mem(rsi, rsi, 2), r13) // r13 = 3*rs_a ZGEMM_INPUT_SCALE_CS_BETA_NZ vaddpd(ymm4, ymm0, ymm4) add(rdi, rcx) ZGEMM_INPUT_SCALE_CS_BETA_NZ vaddpd(ymm8, ymm0, ymm8) add(rdi, rcx) ZGEMM_INPUT_SCALE_CS_BETA_NZ vaddpd(ymm12, ymm0, ymm12) lea(mem(r12, rsi, 2), rcx) ZGEMM_INPUT_SCALE_CS_BETA_NZ vaddpd(ymm5, ymm0, ymm5) add(rdi, rcx) ZGEMM_INPUT_SCALE_CS_BETA_NZ vaddpd(ymm9, ymm0, ymm9) add(rdi, rcx) ZGEMM_INPUT_SCALE_CS_BETA_NZ vaddpd(ymm13, ymm0, ymm13) mov(r12, rcx) // reset rcx to current utile of c. /****3x4 tile going to save into 4x3 tile in C*****/ mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(real dt) lea(mem(, rsi, 2), rsi) // rsi = cs_c * sizeof((real +imag)dt) /******************Transpose top tile 4x3***************************/ vmovups(xmm4, mem(rcx)) vmovups(xmm8, mem(rcx, 16)) vmovups(xmm12, mem(rcx,32)) add(rsi, rcx) vextractf128(imm(0x1), ymm4, xmm4) vextractf128(imm(0x1), ymm8, xmm8) vextractf128(imm(0x1), ymm12, xmm12) vmovups(xmm4, mem(rcx)) vmovups(xmm8, mem(rcx, 16)) vmovups(xmm12, mem(rcx,32)) add(rsi, rcx) vmovups(xmm5, mem(rcx)) vmovups(xmm9, mem(rcx, 16)) vmovups(xmm13,mem(rcx,32)) add(rsi, rcx) vextractf128(imm(0x1), ymm5, xmm5) vextractf128(imm(0x1), ymm9, xmm9) vextractf128(imm(0x1), ymm13, xmm13) vmovups(xmm5, mem(rcx)) vmovups(xmm9, mem(rcx, 16)) vmovups(xmm13,mem(rcx,32)) jmp(.SDONE) // jump to end. label(.SBETAZERO) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a cmp(imm(16), rdi) // set ZF if (16*rs_c) == 16. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovupd(ymm4, mem(rcx)) vmovupd(ymm5, mem(rcx, rsi, 8)) add(rdi, rcx) vmovupd(ymm8, mem(rcx)) vmovupd(ymm9, mem(rcx, rsi, 8)) add(rdi, rcx) vmovupd(ymm12, mem(rcx)) vmovupd(ymm13, mem(rcx, rsi, 8)) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) /****3x4 tile going to save into 4x3 tile in C*****/ mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(dt) lea(mem(, rsi, 2), rsi) // rsi = cs_c * sizeof(dt) /******************Transpose top tile 4x3***************************/ vmovups(xmm4, mem(rcx)) vmovups(xmm8, mem(rcx, 16)) vmovups(xmm12, mem(rcx,32)) add(rsi, rcx) vextractf128(imm(0x1), ymm4, xmm4) vextractf128(imm(0x1), ymm8, xmm8) vextractf128(imm(0x1), ymm12, xmm12) vmovups(xmm4, mem(rcx)) vmovups(xmm8, mem(rcx, 16)) vmovups(xmm12, mem(rcx,32)) add(rsi, rcx) vmovups(xmm5, mem(rcx)) vmovups(xmm9, mem(rcx, 16)) vmovups(xmm13,mem(rcx,32)) add(rsi, rcx) vextractf128(imm(0x1), ymm5, xmm5) vextractf128(imm(0x1), ymm9, xmm9) vextractf128(imm(0x1), ymm13, xmm13) vmovups(xmm5, mem(rcx)) vmovups(xmm9, mem(rcx, 16)) vmovups(xmm13,mem(rcx,32)) label(.SDONE) lea(mem(r12, rdi, 2), r12) lea(mem(r12, rdi, 1), r12) // c_ii = r12 += 3*rs_c lea(mem(r14, r8, 2), r14) lea(mem(r14, r8, 1), r14) //a_ii = r14 += 3*rs_a dec(r11) // ii -= 1; jne(.SLOOP3X8I) // iterate again if ii != 0. label(.SRETURN) end_asm( : // output operands (none) : // input operands [m_iter] "m" (m_iter), [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the m dimension, if they exist. if ( m_left ) { const dim_t nr_cur = 4; const dim_t i_edge = m0 - ( dim_t )m_left; dcomplex* cij = c + i_edge*rs_c; dcomplex* ai = a + i_edge*rs_a; dcomplex* bj = b; zgemmsup_ker_ft ker_fps[3] = { NULL, bli_zgemmsup_rv_zen_asm_1x4, bli_zgemmsup_rv_zen_asm_2x4, }; zgemmsup_ker_ft ker_fp = ker_fps[ m_left ]; ker_fp ( conja, conjb, m_left, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); return; } } void bli_zgemmsup_rv_zen_asm_3x2m ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, dcomplex* restrict alpha, dcomplex* restrict a, inc_t rs_a0, inc_t cs_a0, dcomplex* restrict b, inc_t rs_b0, inc_t cs_b0, dcomplex* restrict beta, dcomplex* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t m_iter = m0 / 3; uint64_t m_left = m0 % 3; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; if ( m_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() mov(var(a), r14) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 8), r8) // rs_a *= sizeof(dt) lea(mem(, r8, 2), r8) // rs_a *= sizeof(dt) lea(mem(, r9, 8), r9) // cs_a *= sizeof(dt) lea(mem(, r9, 2), r9) // cs_a *= sizeof(dt) // lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a mov(var(rs_b), r10) // load rs_b lea(mem(, r10, 8), r10) // rs_b *= sizeof(dt) lea(mem(, r10, 2), r10) // rs_b *= sizeof(dt) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 8), rdi) // rs_c *= sizeof(dt) lea(mem(, rdi, 2), rdi) // rs_c *= sizeof(dt) // During preamble and loops: // r12 = rcx = c // r14 = rax = a // read rbx from var(b) near beginning of loop // r11 = m dim index ii mov(var(m_iter), r11) // ii = m_iter; label(.SLOOP3X8I) // LOOP OVER ii = [ m_iter ... 1 0 ] vzeroall() // zero all xmm/ymm registers. mov(var(b), rbx) // load address of b. //mov(r12, rcx) // reset rcx to current utile of c. mov(r14, rax) // reset rax to current upanel of a. cmp(imm(16), rdi) // set ZF if (16*rs_c) == 16. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored pre-fetching on c // not used lea(mem(r12, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; jmp(.SPOSTPFETCH) // jump to end of pre-fetching c label(.SCOLPFETCH) // column-stored pre-fetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 8), rsi) // cs_c *= sizeof(dt) lea(mem(r12, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; label(.SPOSTPFETCH) // done prefetching c lea(mem(r9, r9, 2), rcx) // rcx = 3*cs_a; lea(mem(rax, r8, 4), rdx) // use rdx for pre-fetching lines lea(mem(rdx, r8, 2), rdx) // from next upanel of a. mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 vmovupd(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vfmadd231pd(ymm0, ymm2, ymm4) vbroadcastsd(mem(rax, r8, 1), ymm2) vfmadd231pd(ymm0, ymm2, ymm8) vbroadcastsd(mem(rax, r8, 2), ymm2) vfmadd231pd(ymm0, ymm2, ymm12) vbroadcastsd(mem(rax, 8), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vbroadcastsd(mem(rax, r8, 1, 8), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vbroadcastsd(mem(rax, r8, 2, 8), ymm3) vfmadd231pd(ymm0, ymm3, ymm14) add(r9, rax) // a += cs_a; // ---------------------------------- iteration 1 vmovupd(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vfmadd231pd(ymm0, ymm2, ymm4) vbroadcastsd(mem(rax, r8, 1), ymm2) vfmadd231pd(ymm0, ymm2, ymm8) vbroadcastsd(mem(rax, r8, 2), ymm2) vfmadd231pd(ymm0, ymm2, ymm12) vbroadcastsd(mem(rax, 8), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vbroadcastsd(mem(rax, r8, 1, 8), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vbroadcastsd(mem(rax, r8, 2, 8), ymm3) vfmadd231pd(ymm0, ymm3, ymm14) add(r9, rax) // a += cs_a; // ---------------------------------- iteration 2 vmovupd(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vfmadd231pd(ymm0, ymm2, ymm4) vbroadcastsd(mem(rax, r8, 1), ymm2) vfmadd231pd(ymm0, ymm2, ymm8) vbroadcastsd(mem(rax, r8, 2), ymm2) vfmadd231pd(ymm0, ymm2, ymm12) vbroadcastsd(mem(rax, 8), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vbroadcastsd(mem(rax, r8, 1, 8), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vbroadcastsd(mem(rax, r8, 2, 8), ymm3) vfmadd231pd(ymm0, ymm3, ymm14) add(r9, rax) // a += cs_a; // ---------------------------------- iteration 3 lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; vmovupd(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vfmadd231pd(ymm0, ymm2, ymm4) vbroadcastsd(mem(rax, r8, 1), ymm2) vfmadd231pd(ymm0, ymm2, ymm8) vbroadcastsd(mem(rax, r8, 2), ymm2) vfmadd231pd(ymm0, ymm2, ymm12) vbroadcastsd(mem(rax, 8), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vbroadcastsd(mem(rax, r8, 1, 8), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vbroadcastsd(mem(rax, r8, 2, 8), ymm3) vfmadd231pd(ymm0, ymm3, ymm14) add(r9, rax) // a += cs_a; dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP vmovupd(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastsd(mem(rax ), ymm2) vfmadd231pd(ymm0, ymm2, ymm4) vbroadcastsd(mem(rax, r8, 1), ymm2) vfmadd231pd(ymm0, ymm2, ymm8) vbroadcastsd(mem(rax, r8, 2), ymm2) vfmadd231pd(ymm0, ymm2, ymm12) vbroadcastsd(mem(rax, 8), ymm3) vfmadd231pd(ymm0, ymm3, ymm6) vbroadcastsd(mem(rax, r8, 1, 8), ymm3) vfmadd231pd(ymm0, ymm3, ymm10) vbroadcastsd(mem(rax, r8, 2, 8), ymm3) vfmadd231pd(ymm0, ymm3, ymm14) add(r9, rax) // a += cs_a; dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(r12, rcx) // reset rcx to current utile of c. // permute even and odd elements // of ymm6/7, ymm10/11, ymm/14/15 vpermilpd(imm(0x5), ymm6, ymm6) vpermilpd(imm(0x5), ymm10, ymm10) vpermilpd(imm(0x5), ymm14, ymm14) // subtract/add even/odd elements vaddsubpd(ymm6, ymm4, ymm4) vaddsubpd(ymm10, ymm8, ymm8) vaddsubpd(ymm14, ymm12, ymm12) /* (ar + ai) x AB */ mov(var(alpha), rax) // load address of alpha vbroadcastsd(mem(rax), ymm0) // load alpha_r and duplicate vbroadcastsd(mem(rax, 8), ymm1) // load alpha_i and duplicate vpermilpd(imm(0x5), ymm4, ymm3) vmulpd(ymm0, ymm4, ymm4) vmulpd(ymm1, ymm3, ymm3) vaddsubpd(ymm3, ymm4, ymm4) vpermilpd(imm(0x5), ymm8, ymm3) vmulpd(ymm0, ymm8, ymm8) vmulpd(ymm1, ymm3, ymm3) vaddsubpd(ymm3, ymm8, ymm8) vpermilpd(imm(0x5), ymm12, ymm3) vmulpd(ymm0, ymm12, ymm12) vmulpd(ymm1, ymm3, ymm3) vaddsubpd(ymm3, ymm12, ymm12) /* (ßr + ßi)x C + ((ar + ai) x AB) */ mov(var(beta), rbx) // load address of beta vbroadcastsd(mem(rbx), ymm1) // load beta_r and duplicate vbroadcastsd(mem(rbx, 8), ymm2) // load beta_i and duplicate mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(dt) lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorpd(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm1) // set ZF if beta_r == 0. sete(r13b) // r13b = ( ZF == 1 ? 1 : 0 ); vucomisd(xmm0, xmm2) // set ZF if beta_i == 0. sete(r15b) // r15b = ( ZF == 1 ? 1 : 0 ); and(r13b, r15b) // set ZF if r13b & r15b == 1. jne(.SBETAZERO) // if ZF = 1, jump to beta == 0 case lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a cmp(imm(16), rdi) // set ZF if (16*rs_c) == 16. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) ZGEMM_INPUT_SCALE_RS_BETA_NZ vaddpd(ymm4, ymm0, ymm0) ZGEMM_OUTPUT_RS add(rdi, rcx) // rcx = c + 1*rs_c ZGEMM_INPUT_SCALE_RS_BETA_NZ vaddpd(ymm8, ymm0, ymm0) ZGEMM_OUTPUT_RS add(rdi, rcx) // rcx = c + 2*rs_c ZGEMM_INPUT_SCALE_RS_BETA_NZ vaddpd(ymm12, ymm0, ymm0) ZGEMM_OUTPUT_RS jmp(.SDONE) // jump to end. label(.SCOLSTORED) /*|--------| |-------| | | | | | 3x2 | | 2x3 | |--------| |-------| */ mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(real dt) lea(mem(, rsi, 2), rsi) // rsi = cs_c * sizeof((real+imag) dt) lea(mem(rsi, rsi, 2), r13) // r13 = 3*rs_a ZGEMM_INPUT_SCALE_CS_BETA_NZ vaddpd(ymm4, ymm0, ymm4) add(rdi, rcx) ZGEMM_INPUT_SCALE_CS_BETA_NZ vaddpd(ymm8, ymm0, ymm8) add(rdi, rcx) ZGEMM_INPUT_SCALE_CS_BETA_NZ vaddpd(ymm12, ymm0, ymm12) mov(r12, rcx) // reset rcx to current utile of c. /****3x2 tile going to save into 2x3 tile in C*****/ mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(dt) lea(mem(, rsi, 2), rsi) // rsi = cs_c * sizeof(dt) /******************Transpose top tile 2x3***************************/ vmovups(xmm4, mem(rcx)) vmovups(xmm8, mem(rcx, 16)) vmovups(xmm12, mem(rcx,32)) add(rsi, rcx) vextractf128(imm(0x1), ymm4, xmm4) vextractf128(imm(0x1), ymm8, xmm8) vextractf128(imm(0x1), ymm12, xmm12) vmovups(xmm4, mem(rcx)) vmovups(xmm8, mem(rcx, 16)) vmovups(xmm12, mem(rcx,32)) jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(16), rdi) // set ZF if (8*rs_c) == 8. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovupd(ymm4, mem(rcx)) add(rdi, rcx) vmovupd(ymm8, mem(rcx)) add(rdi, rcx) vmovupd(ymm12, mem(rcx)) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) /****3x2 tile going to save into 2x3 tile in C*****/ mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 8), rsi) // rsi = cs_c * sizeof(dt) lea(mem(, rsi, 2), rsi) // rsi = cs_c * sizeof(dt) /******************Transpose tile 3x2***************************/ vmovups(xmm4, mem(rcx)) vmovups(xmm8, mem(rcx, 16)) vmovups(xmm12, mem(rcx,32)) add(rsi, rcx) vextractf128(imm(0x1), ymm4, xmm4) vextractf128(imm(0x1), ymm8, xmm8) vextractf128(imm(0x1), ymm12, xmm12) vmovups(xmm4, mem(rcx)) vmovups(xmm8, mem(rcx, 16)) vmovups(xmm12, mem(rcx,32)) label(.SDONE) lea(mem(r12, rdi, 2), r12) lea(mem(r12, rdi, 1), r12) // c_ii = r12 += 3*rs_c lea(mem(r14, r8, 2), r14) lea(mem(r14, r8, 1), r14) //a_ii = r14 += 3*rs_a dec(r11) // ii -= 1; jne(.SLOOP3X8I) // iterate again if ii != 0. label(.SRETURN) end_asm( : // output operands (none) : // input operands [m_iter] "m" (m_iter), [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the m dimension, if they exist. if ( m_left ) { const dim_t nr_cur = 4; const dim_t i_edge = m0 - ( dim_t )m_left; dcomplex* cij = c + i_edge*rs_c; dcomplex* ai = a + i_edge*rs_a; dcomplex* bj = b; zgemmsup_ker_ft ker_fps[3] = { NULL, bli_zgemmsup_rv_zen_asm_1x2, bli_zgemmsup_rv_zen_asm_2x2, }; zgemmsup_ker_ft ker_fp = ker_fps[ m_left ]; ker_fp ( conja, conjb, m_left, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); return; } } blis-0.9.0/kernels/zen/3/sup/broken/bli_gemmsup_rv_zen_asm_z3x4n.c000066400000000000000000001147731422157504600251240ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "immintrin.h" /* rrr: -------- ------ -------- -------- += ------ ... -------- -------- ------ -------- -------- ------ : rcr: -------- | | | | -------- -------- += | | | | ... -------- -------- | | | | -------- -------- | | | | : Assumptions: - B is row-stored; - A is row- or column-stored; - m0 and n0 are at most MR and NR, respectively. Therefore, this (r)ow-preferential kernel is well-suited for contiguous (v)ector loads on B and single-element broadcasts from A. NOTE: These kernels explicitly support column-oriented IO, implemented via an in-register transpose. And thus they also support the crr and ccr cases, though only crr is ever utilized (because ccr is handled by transposing the operation and executing rcr, which does not incur the cost of the in-register transpose). crr: | | | | | | | | ------ -------- | | | | | | | | += ------ ... -------- | | | | | | | | ------ -------- | | | | | | | | ------ : */ void bli_zgemmsup_rv_zen_asm_3x4n ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, dcomplex* restrict alpha, dcomplex* restrict a, inc_t rs_a0, inc_t cs_a0, dcomplex* restrict b, inc_t rs_b0, inc_t cs_b0, dcomplex* restrict beta, dcomplex* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { uint64_t m_left = m0 % 3; if ( m_left ) { zgemmsup_ker_ft ker_fps[3] = { NULL, bli_zgemmsup_rv_zen_asm_1x4n, bli_zgemmsup_rv_zen_asm_2x4n, }; zgemmsup_ker_ft ker_fp = ker_fps[ m_left ]; ker_fp ( conja, conjb, m_left, n0, k0, alpha, a, rs_a0, cs_a0, b, rs_b0, cs_b0, beta, c, rs_c0, cs_c0, data, cntx ); return; } //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = 0; uint64_t n_iter = n0 / 4; uint64_t n_left = n0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; if ( n_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- //scratch registers __m256d ymm0, ymm1, ymm2, ymm3; __m256d ymm4, ymm5, ymm6, ymm7; __m256d ymm8, ymm9, ymm10, ymm11; __m256d ymm12, ymm13, ymm14, ymm15; __m128d xmm0, xmm3; dcomplex *tA = a; double *tAimag = &a->imag; dcomplex *tB = b; dcomplex *tC = c; for (n_iter = 0; n_iter < n0 / 4; n_iter++) { // clear scratch registers. ymm4 = _mm256_setzero_pd(); ymm5 = _mm256_setzero_pd(); ymm6 = _mm256_setzero_pd(); ymm7 = _mm256_setzero_pd(); ymm8 = _mm256_setzero_pd(); ymm9 = _mm256_setzero_pd(); ymm10 = _mm256_setzero_pd(); ymm11 = _mm256_setzero_pd(); ymm12 = _mm256_setzero_pd(); ymm13 = _mm256_setzero_pd(); ymm14 = _mm256_setzero_pd(); ymm15 = _mm256_setzero_pd(); dim_t ta_inc_row = rs_a; dim_t tb_inc_row = rs_b; dim_t tc_inc_row = rs_c; dim_t ta_inc_col = cs_a; dim_t tb_inc_col = cs_b; dim_t tc_inc_col = cs_c; tA = a; tAimag = &a->imag; tB = b + n_iter*tb_inc_col*4; tC = c + n_iter*tc_inc_col*4; for (k_iter = 0; k_iter imag)); // load alpha_i and duplicate ymm3 = _mm256_permute_pd(ymm4, 5); ymm4 = _mm256_mul_pd(ymm0, ymm4); ymm3 =_mm256_mul_pd(ymm1, ymm3); ymm4 = _mm256_addsub_pd(ymm4, ymm3); ymm3 = _mm256_permute_pd(ymm5, 5); ymm5 = _mm256_mul_pd(ymm0, ymm5); ymm3 = _mm256_mul_pd(ymm1, ymm3); ymm5 = _mm256_addsub_pd(ymm5, ymm3); ymm3 = _mm256_permute_pd(ymm8, 5); ymm8 = _mm256_mul_pd(ymm0, ymm8); ymm3 = _mm256_mul_pd(ymm1, ymm3); ymm8 = _mm256_addsub_pd(ymm8, ymm3); ymm3 = _mm256_permute_pd(ymm9, 5); ymm9 = _mm256_mul_pd(ymm0, ymm9); ymm3 = _mm256_mul_pd(ymm1, ymm3); ymm9 = _mm256_addsub_pd(ymm9, ymm3); ymm3 = _mm256_permute_pd(ymm12, 5); ymm12 = _mm256_mul_pd(ymm0, ymm12); ymm3 = _mm256_mul_pd(ymm1, ymm3); ymm12 = _mm256_addsub_pd(ymm12, ymm3); ymm3 = _mm256_permute_pd(ymm13, 5); ymm13 = _mm256_mul_pd(ymm0, ymm13); ymm3 = _mm256_mul_pd(ymm1, ymm3); ymm13 = _mm256_addsub_pd(ymm13, ymm3); if(tc_inc_row == 1) //col stored { if(beta->real == 0.0 && beta->imag == 0.0) { //transpose left 3x2 _mm_storeu_pd((double *)(tC ), _mm256_castpd256_pd128(ymm4)); _mm_storeu_pd((double *)(tC+1), _mm256_castpd256_pd128(ymm8)); _mm_storeu_pd((double *)(tC+2), _mm256_castpd256_pd128(ymm12)); tC += tc_inc_col; _mm_storeu_pd((double *)(tC ),_mm256_extractf128_pd (ymm4,1)); _mm_storeu_pd((double *)(tC+1) ,_mm256_extractf128_pd (ymm8,1)); _mm_storeu_pd((double *)(tC+2), _mm256_extractf128_pd(ymm12, 1)); tC += tc_inc_col; //transpose right 3x2 _mm_storeu_pd((double *)(tC ), _mm256_castpd256_pd128(ymm5)); _mm_storeu_pd((double *)(tC+1), _mm256_castpd256_pd128(ymm9)); _mm_storeu_pd((double *)(tC+2), _mm256_castpd256_pd128(ymm13)); tC += tc_inc_col; _mm_storeu_pd((double *)(tC ),_mm256_extractf128_pd (ymm5,1)); _mm_storeu_pd((double *)(tC+1) ,_mm256_extractf128_pd (ymm9,1)); _mm_storeu_pd((double *)(tC+2), _mm256_extractf128_pd(ymm13, 1)); } else{ ymm1 = _mm256_broadcast_sd((double const *)(beta)); // load alpha_r and duplicate ymm2 = _mm256_broadcast_sd((double const *)(&beta->imag)); // load alpha_i and duplicate //Multiply ymm4 with beta xmm0 = _mm_loadu_pd((double *)(tC)) ; xmm3 = _mm_loadu_pd((double *)(tC + tc_inc_col)) ; ymm0 = _mm256_insertf128_pd(_mm256_castpd128_pd256(xmm0), xmm3, 1) ; ymm3 = _mm256_permute_pd(ymm0, 5); ymm0 = _mm256_mul_pd(ymm1, ymm0); ymm3 = _mm256_mul_pd(ymm2, ymm3); ymm0 = _mm256_addsub_pd(ymm0, ymm3); ymm4 = _mm256_add_pd(ymm4, ymm0); //Multiply ymm8 with beta xmm0 = _mm_loadu_pd((double *)(tC + 1)) ; xmm3 = _mm_loadu_pd((double *)(tC + 1 + tc_inc_col)) ; ymm0 = _mm256_insertf128_pd(_mm256_castpd128_pd256(xmm0), xmm3, 1) ; ymm3 = _mm256_permute_pd(ymm0, 5); ymm0 = _mm256_mul_pd(ymm1, ymm0); ymm3 = _mm256_mul_pd(ymm2, ymm3); ymm0 = _mm256_addsub_pd(ymm0, ymm3); ymm8 = _mm256_add_pd(ymm8, ymm0); //Multiply ymm12 with beta xmm0 = _mm_loadu_pd((double *)(tC + 2)) ; xmm3 = _mm_loadu_pd((double *)(tC + 2 + tc_inc_col)) ; ymm0 = _mm256_insertf128_pd(_mm256_castpd128_pd256(xmm0), xmm3, 1) ; ymm3 = _mm256_permute_pd(ymm0, 5); ymm0 = _mm256_mul_pd(ymm1, ymm0); ymm3 = _mm256_mul_pd(ymm2, ymm3); ymm0 = _mm256_addsub_pd(ymm0, ymm3); ymm12 = _mm256_add_pd(ymm12, ymm0); //transpose left 3x2 _mm_storeu_pd((double *)(tC ), _mm256_castpd256_pd128(ymm4)); _mm_storeu_pd((double *)(tC+1), _mm256_castpd256_pd128(ymm8)); _mm_storeu_pd((double *)(tC+2), _mm256_castpd256_pd128(ymm12)); tC += tc_inc_col; _mm_storeu_pd((double *)(tC ),_mm256_extractf128_pd (ymm4,1)); _mm_storeu_pd((double *)(tC+1) ,_mm256_extractf128_pd (ymm8,1)); _mm_storeu_pd((double *)(tC+2), _mm256_extractf128_pd(ymm12, 1)); tC += tc_inc_col; //Multiply ymm5 with beta xmm0 = _mm_loadu_pd((double *)(tC)) ; xmm3 = _mm_loadu_pd((double *)(tC + tc_inc_col)) ; ymm0 = _mm256_insertf128_pd(_mm256_castpd128_pd256(xmm0), xmm3, 1) ; ymm3 = _mm256_permute_pd(ymm0, 5); ymm0 = _mm256_mul_pd(ymm1, ymm0); ymm3 = _mm256_mul_pd(ymm2, ymm3); ymm0 = _mm256_addsub_pd(ymm0, ymm3); ymm5 = _mm256_add_pd(ymm5, ymm0); //Multiply ymm9 with beta xmm0 = _mm_loadu_pd((double *)(tC + 1)) ; xmm3 = _mm_loadu_pd((double *)(tC + 1 + tc_inc_col)) ; ymm0 = _mm256_insertf128_pd(_mm256_castpd128_pd256(xmm0), xmm3, 1) ; ymm3 = _mm256_permute_pd(ymm0, 5); ymm0 = _mm256_mul_pd(ymm1, ymm0); ymm3 = _mm256_mul_pd(ymm2, ymm3); ymm0 = _mm256_addsub_pd(ymm0, ymm3); ymm9 = _mm256_add_pd(ymm9, ymm0); //Multiply ymm13 with beta xmm0 = _mm_loadu_pd((double *)(tC + 2)) ; xmm3 = _mm_loadu_pd((double *)(tC + 2 + tc_inc_col)) ; ymm0 = _mm256_insertf128_pd(_mm256_castpd128_pd256(xmm0), xmm3, 1) ; ymm3 = _mm256_permute_pd(ymm0, 5); ymm0 = _mm256_mul_pd(ymm1, ymm0); ymm3 = _mm256_mul_pd(ymm2, ymm3); ymm0 = _mm256_addsub_pd(ymm0, ymm3); ymm13 = _mm256_add_pd(ymm13, ymm0); //transpose right 3x2 _mm_storeu_pd((double *)(tC ), _mm256_castpd256_pd128(ymm5)); _mm_storeu_pd((double *)(tC+1), _mm256_castpd256_pd128(ymm9)); _mm_storeu_pd((double *)(tC+2), _mm256_castpd256_pd128(ymm13)); tC += tc_inc_col; _mm_storeu_pd((double *)(tC ),_mm256_extractf128_pd (ymm5,1)); _mm_storeu_pd((double *)(tC+1) ,_mm256_extractf128_pd (ymm9,1)); _mm_storeu_pd((double *)(tC+2), _mm256_extractf128_pd(ymm13, 1)); } } else { if(beta->real == 0.0 && beta->imag == 0.0) { _mm256_storeu_pd((double *)(tC), ymm4); _mm256_storeu_pd((double *)(tC + 2), ymm5); _mm256_storeu_pd((double *)(tC + tc_inc_row) , ymm8); _mm256_storeu_pd((double *)(tC + tc_inc_row + 2), ymm9); _mm256_storeu_pd((double *)(tC + tc_inc_row *2), ymm12); _mm256_storeu_pd((double *)(tC + tc_inc_row *2+ 2), ymm13); } else{ /* (br + bi) C + (ar + ai) AB */ ymm0 = _mm256_broadcast_sd((double const *)(beta)); // load beta_r and duplicate ymm1 = _mm256_broadcast_sd((double const *)(&beta->imag)); // load beta_i and duplicate ymm2 = _mm256_loadu_pd((double const *)(tC)); ymm3 = _mm256_permute_pd(ymm2, 5); ymm2 = _mm256_mul_pd(ymm0, ymm2); ymm3 =_mm256_mul_pd(ymm1, ymm3); ymm4 = _mm256_add_pd(ymm4, _mm256_addsub_pd(ymm2, ymm3)); ymm2 = _mm256_loadu_pd((double const *)(tC+2)); ymm3 = _mm256_permute_pd(ymm2, 5); ymm2 = _mm256_mul_pd(ymm0, ymm2); ymm3 = _mm256_mul_pd(ymm1, ymm3); ymm5 = _mm256_add_pd(ymm5, _mm256_addsub_pd(ymm2, ymm3)); ymm2 = _mm256_loadu_pd((double const *)(tC+tc_inc_row)); ymm3 = _mm256_permute_pd(ymm2, 5); ymm2 = _mm256_mul_pd(ymm0, ymm2); ymm3 = _mm256_mul_pd(ymm1, ymm3); ymm8 = _mm256_add_pd(ymm8, _mm256_addsub_pd(ymm2, ymm3)); ymm2 = _mm256_loadu_pd((double const *)(tC+tc_inc_row + 2)); ymm3 = _mm256_permute_pd(ymm2, 5); ymm2 = _mm256_mul_pd(ymm0, ymm2); ymm3 = _mm256_mul_pd(ymm1, ymm3); ymm9 = _mm256_add_pd(ymm9, _mm256_addsub_pd(ymm2, ymm3)); ymm2 = _mm256_loadu_pd((double const *)(tC+tc_inc_row*2)); ymm3 = _mm256_permute_pd(ymm2, 5); ymm2 = _mm256_mul_pd(ymm0, ymm2); ymm3 = _mm256_mul_pd(ymm1, ymm3); ymm12 = _mm256_add_pd(ymm12, _mm256_addsub_pd(ymm2, ymm3)); ymm2 = _mm256_loadu_pd((double const *)(tC+tc_inc_row*2 +2)); ymm3 = _mm256_permute_pd(ymm2, 5); ymm2 = _mm256_mul_pd(ymm0, ymm2); ymm3 = _mm256_mul_pd(ymm1, ymm3); ymm13 = _mm256_add_pd(ymm13, _mm256_addsub_pd(ymm2, ymm3)); _mm256_storeu_pd((double *)(tC), ymm4); _mm256_storeu_pd((double *)(tC + 2), ymm5); _mm256_storeu_pd((double *)(tC + tc_inc_row) , ymm8); _mm256_storeu_pd((double *)(tC + tc_inc_row + 2), ymm9); _mm256_storeu_pd((double *)(tC + tc_inc_row *2), ymm12); _mm256_storeu_pd((double *)(tC + tc_inc_row *2+ 2), ymm13); } } } consider_edge_cases: // Handle edge cases in the m dimension, if they exist. if ( n_left ) { const dim_t mr_cur = 3; const dim_t j_edge = n0 - ( dim_t )n_left; dcomplex* restrict cij = c + j_edge*cs_c; dcomplex* restrict ai = a; dcomplex* restrict bj = b + n_iter * 4; if ( 2 <= n_left ) { const dim_t nr_cur = 2; bli_zgemmsup_rv_zen_asm_3x2 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 1 == n_left ) { bli_zgemv_ex ( BLIS_NO_TRANSPOSE, conjb, m0, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, beta, cij, rs_c0, cntx, NULL ); } } } void bli_zgemmsup_rv_zen_asm_2x4n ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, dcomplex* restrict alpha, dcomplex* restrict a, inc_t rs_a0, inc_t cs_a0, dcomplex* restrict b, inc_t rs_b0, inc_t cs_b0, dcomplex* restrict beta, dcomplex* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { uint64_t k_iter = 0; uint64_t n_iter = n0 / 4; uint64_t n_left = n0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; if ( n_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- //scratch registers __m256d ymm0, ymm1, ymm2, ymm3; __m256d ymm4, ymm5, ymm6, ymm7; __m256d ymm8, ymm9, ymm10, ymm11; __m128d xmm0, xmm3; dcomplex *tA = a; double *tAimag = &a->imag; dcomplex *tB = b; dcomplex *tC = c; for (n_iter = 0; n_iter < n0 / 4; n_iter++) { // clear scratch registers. ymm4 = _mm256_setzero_pd(); ymm5 = _mm256_setzero_pd(); ymm6 = _mm256_setzero_pd(); ymm7 = _mm256_setzero_pd(); ymm8 = _mm256_setzero_pd(); ymm9 = _mm256_setzero_pd(); ymm10 = _mm256_setzero_pd(); ymm11 = _mm256_setzero_pd(); dim_t ta_inc_row = rs_a; dim_t tb_inc_row = rs_b; dim_t tc_inc_row = rs_c; dim_t ta_inc_col = cs_a; dim_t tb_inc_col = cs_b; dim_t tc_inc_col = cs_c; tA = a; tAimag = &a->imag; tB = b + n_iter*tb_inc_col*4; tC = c + n_iter*tc_inc_col*4; for (k_iter = 0; k_iter imag)); // load alpha_i and duplicate ymm3 = _mm256_permute_pd(ymm4, 5); ymm4 = _mm256_mul_pd(ymm0, ymm4); ymm3 =_mm256_mul_pd(ymm1, ymm3); ymm4 = _mm256_addsub_pd(ymm4, ymm3); ymm3 = _mm256_permute_pd(ymm5, 5); ymm5 = _mm256_mul_pd(ymm0, ymm5); ymm3 = _mm256_mul_pd(ymm1, ymm3); ymm5 = _mm256_addsub_pd(ymm5, ymm3); ymm3 = _mm256_permute_pd(ymm8, 5); ymm8 = _mm256_mul_pd(ymm0, ymm8); ymm3 = _mm256_mul_pd(ymm1, ymm3); ymm8 = _mm256_addsub_pd(ymm8, ymm3); ymm3 = _mm256_permute_pd(ymm9, 5); ymm9 = _mm256_mul_pd(ymm0, ymm9); ymm3 = _mm256_mul_pd(ymm1, ymm3); ymm9 = _mm256_addsub_pd(ymm9, ymm3); if(tc_inc_row == 1) //col stored { if(beta->real == 0.0 && beta->imag == 0.0) { //transpose left 2x2 _mm_storeu_pd((double *)(tC ), _mm256_castpd256_pd128(ymm4)); _mm_storeu_pd((double *)(tC+1), _mm256_castpd256_pd128(ymm8)); tC += tc_inc_col; _mm_storeu_pd((double *)(tC ),_mm256_extractf128_pd (ymm4,1)); _mm_storeu_pd((double *)(tC+1) ,_mm256_extractf128_pd (ymm8,1)); tC += tc_inc_col; //transpose right 2x2 _mm_storeu_pd((double *)(tC ), _mm256_castpd256_pd128(ymm5)); _mm_storeu_pd((double *)(tC+1), _mm256_castpd256_pd128(ymm9)); tC += tc_inc_col; _mm_storeu_pd((double *)(tC ),_mm256_extractf128_pd (ymm5,1)); _mm_storeu_pd((double *)(tC+1) ,_mm256_extractf128_pd (ymm9,1)); } else{ ymm1 = _mm256_broadcast_sd((double const *)(beta)); // load alpha_r and duplicate ymm2 = _mm256_broadcast_sd((double const *)(&beta->imag)); // load alpha_i and duplicate //Multiply ymm4 with beta xmm0 = _mm_loadu_pd((double *)(tC)) ; xmm3 = _mm_loadu_pd((double *)(tC + tc_inc_col)) ; ymm0 = _mm256_insertf128_pd(_mm256_castpd128_pd256(xmm0), xmm3, 1) ; ymm3 = _mm256_permute_pd(ymm0, 5); ymm0 = _mm256_mul_pd(ymm1, ymm0); ymm3 = _mm256_mul_pd(ymm2, ymm3); ymm0 = _mm256_addsub_pd(ymm0, ymm3); ymm4 = _mm256_add_pd(ymm4, ymm0); //Multiply ymm8 with beta xmm0 = _mm_loadu_pd((double *)(tC + 1)) ; xmm3 = _mm_loadu_pd((double *)(tC + 1 + tc_inc_col)) ; ymm0 = _mm256_insertf128_pd(_mm256_castpd128_pd256(xmm0), xmm3, 1) ; ymm3 = _mm256_permute_pd(ymm0, 5); ymm0 = _mm256_mul_pd(ymm1, ymm0); ymm3 = _mm256_mul_pd(ymm2, ymm3); ymm0 = _mm256_addsub_pd(ymm0, ymm3); ymm8 = _mm256_add_pd(ymm8, ymm0); //transpose left 2x2 _mm_storeu_pd((double *)(tC), _mm256_castpd256_pd128(ymm4)); _mm_storeu_pd((double *)(tC+1), _mm256_castpd256_pd128(ymm8)); tC += tc_inc_col; _mm_storeu_pd((double *)(tC ) ,_mm256_extractf128_pd (ymm4,1)); _mm_storeu_pd((double *)(tC+1) ,_mm256_extractf128_pd (ymm8,1)); tC += tc_inc_col; //Multiply ymm5 with beta xmm0 = _mm_loadu_pd((double *)(tC)) ; xmm3 = _mm_loadu_pd((double *)(tC + tc_inc_col)) ; ymm0 = _mm256_insertf128_pd(_mm256_castpd128_pd256(xmm0), xmm3, 1) ; ymm3 = _mm256_permute_pd(ymm0, 5); ymm0 = _mm256_mul_pd(ymm1, ymm0); ymm3 = _mm256_mul_pd(ymm2, ymm3); ymm0 = _mm256_addsub_pd(ymm0, ymm3); ymm5 = _mm256_add_pd(ymm5, ymm0); //Multiply ymm9 with beta xmm0 = _mm_loadu_pd((double *)(tC + 1)) ; xmm3 = _mm_loadu_pd((double *)(tC + 1 + tc_inc_col)) ; ymm0 = _mm256_insertf128_pd(_mm256_castpd128_pd256(xmm0), xmm3, 1) ; ymm3 = _mm256_permute_pd(ymm0, 5); ymm0 = _mm256_mul_pd(ymm1, ymm0); ymm3 = _mm256_mul_pd(ymm2, ymm3); ymm0 = _mm256_addsub_pd(ymm0, ymm3); ymm9 = _mm256_add_pd(ymm9, ymm0); //transpose right 2x2 _mm_storeu_pd((double *)(tC), _mm256_castpd256_pd128(ymm5)); _mm_storeu_pd((double *)(tC+1), _mm256_castpd256_pd128(ymm9)); tC += tc_inc_col; _mm_storeu_pd((double *)(tC ) ,_mm256_extractf128_pd (ymm5,1)); _mm_storeu_pd((double *)(tC+1) ,_mm256_extractf128_pd (ymm9,1)); } } else { if(beta->real == 0.0 && beta->imag == 0.0) { _mm256_storeu_pd((double *)(tC), ymm4); _mm256_storeu_pd((double *)(tC + 2), ymm5); _mm256_storeu_pd((double *)(tC + tc_inc_row) , ymm8); _mm256_storeu_pd((double *)(tC + tc_inc_row + 2), ymm9); } else{ /* (br + bi) C + (ar + ai) AB */ ymm0 = _mm256_broadcast_sd((double const *)(beta)); // load beta_r and duplicate ymm1 = _mm256_broadcast_sd((double const *)(&beta->imag)); // load beta_i and duplicate ymm2 = _mm256_loadu_pd((double const *)(tC)); ymm3 = _mm256_permute_pd(ymm2, 5); ymm2 = _mm256_mul_pd(ymm0, ymm2); ymm3 =_mm256_mul_pd(ymm1, ymm3); ymm4 = _mm256_add_pd(ymm4, _mm256_addsub_pd(ymm2, ymm3)); ymm2 = _mm256_loadu_pd((double const *)(tC+2)); ymm3 = _mm256_permute_pd(ymm2, 5); ymm2 = _mm256_mul_pd(ymm0, ymm2); ymm3 = _mm256_mul_pd(ymm1, ymm3); ymm5 = _mm256_add_pd(ymm5, _mm256_addsub_pd(ymm2, ymm3)); ymm2 = _mm256_loadu_pd((double const *)(tC+tc_inc_row)); ymm3 = _mm256_permute_pd(ymm2, 5); ymm2 = _mm256_mul_pd(ymm0, ymm2); ymm3 = _mm256_mul_pd(ymm1, ymm3); ymm8 = _mm256_add_pd(ymm8, _mm256_addsub_pd(ymm2, ymm3)); ymm2 = _mm256_loadu_pd((double const *)(tC+tc_inc_row + 2)); ymm3 = _mm256_permute_pd(ymm2, 5); ymm2 = _mm256_mul_pd(ymm0, ymm2); ymm3 = _mm256_mul_pd(ymm1, ymm3); ymm9 = _mm256_add_pd(ymm9, _mm256_addsub_pd(ymm2, ymm3)); _mm256_storeu_pd((double *)(tC), ymm4); _mm256_storeu_pd((double *)(tC + 2), ymm5); _mm256_storeu_pd((double *)(tC + tc_inc_row) , ymm8); _mm256_storeu_pd((double *)(tC + tc_inc_row + 2), ymm9); } } } consider_edge_cases: // Handle edge cases in the m dimension, if they exist. if ( n_left ) { const dim_t mr_cur = 3; const dim_t j_edge = n0 - ( dim_t )n_left; dcomplex* restrict cij = c + j_edge*cs_c; dcomplex* restrict ai = a; dcomplex* restrict bj = b + n_iter * 4; if ( 2 <= n_left ) { const dim_t nr_cur = 2; bli_zgemmsup_rv_zen_asm_2x2 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 1 == n_left ) { bli_zgemv_ex ( BLIS_NO_TRANSPOSE, conjb, m0, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, beta, cij, rs_c0, cntx, NULL ); } } } void bli_zgemmsup_rv_zen_asm_1x4n ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, dcomplex* restrict alpha, dcomplex* restrict a, inc_t rs_a0, inc_t cs_a0, dcomplex* restrict b, inc_t rs_b0, inc_t cs_b0, dcomplex* restrict beta, dcomplex* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = 0; uint64_t n_iter = n0 / 4; uint64_t n_left = n0 % 4; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; if ( n_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- //scratch registers __m256d ymm0, ymm1, ymm2, ymm3; __m256d ymm4, ymm5, ymm6, ymm7; __m128d xmm0, xmm3; dcomplex *tA = a; double *tAimag = &a->imag; dcomplex *tB = b; dcomplex *tC = c; for (n_iter = 0; n_iter < n0 / 4; n_iter++) { // clear scratch registers. ymm4 = _mm256_setzero_pd(); ymm5 = _mm256_setzero_pd(); ymm6 = _mm256_setzero_pd(); ymm7 = _mm256_setzero_pd(); dim_t tb_inc_row = rs_b; dim_t tc_inc_row = rs_c; dim_t ta_inc_col = cs_a; dim_t tb_inc_col = cs_b; dim_t tc_inc_col = cs_c; tA = a; tAimag = &a->imag; tB = b + n_iter*tb_inc_col*4; tC = c + n_iter*tc_inc_col*4; for (k_iter = 0; k_iter imag)); // load alpha_i and duplicate ymm3 = _mm256_permute_pd(ymm4, 5); ymm4 = _mm256_mul_pd(ymm0, ymm4); ymm3 =_mm256_mul_pd(ymm1, ymm3); ymm4 = _mm256_addsub_pd(ymm4, ymm3); ymm3 = _mm256_permute_pd(ymm5, 5); ymm5 = _mm256_mul_pd(ymm0, ymm5); ymm3 = _mm256_mul_pd(ymm1, ymm3); ymm5 = _mm256_addsub_pd(ymm5, ymm3); if(tc_inc_row == 1) //col stored { if(beta->real == 0.0 && beta->imag == 0.0) { //transpose left 1x2 _mm_storeu_pd((double *)(tC), _mm256_castpd256_pd128(ymm4)); tC += tc_inc_col; _mm_storeu_pd((double *)(tC) ,_mm256_extractf128_pd (ymm4,1)); tC += tc_inc_col; //transpose right 1x2 _mm_storeu_pd((double *)(tC), _mm256_castpd256_pd128(ymm5)); tC += tc_inc_col; _mm_storeu_pd((double *)(tC) ,_mm256_extractf128_pd (ymm5,1)); } else{ ymm1 = _mm256_broadcast_sd((double const *)(beta)); // load alpha_r and duplicate ymm2 = _mm256_broadcast_sd((double const *)(&beta->imag)); // load alpha_i and duplicate //Multiply ymm4 with beta xmm0 = _mm_loadu_pd((double *)(tC)) ; xmm3 = _mm_loadu_pd((double *)(tC + tc_inc_col)) ; ymm0 = _mm256_insertf128_pd(_mm256_castpd128_pd256(xmm0), xmm3, 1) ; ymm3 = _mm256_permute_pd(ymm0, 5); ymm0 = _mm256_mul_pd(ymm1, ymm0); ymm3 = _mm256_mul_pd(ymm2, ymm3); ymm0 = _mm256_addsub_pd(ymm0, ymm3); ymm4 = _mm256_add_pd(ymm4, ymm0); _mm_storeu_pd((double *)(tC), _mm256_castpd256_pd128(ymm4)); tC += tc_inc_col; _mm_storeu_pd((double *)(tC ) ,_mm256_extractf128_pd (ymm4,1)); tC += tc_inc_col; //Multiply ymm5 with beta xmm0 = _mm_loadu_pd((double *)(tC)) ; xmm3 = _mm_loadu_pd((double *)(tC + tc_inc_col)) ; ymm0 = _mm256_insertf128_pd(_mm256_castpd128_pd256(xmm0), xmm3, 1) ; ymm3 = _mm256_permute_pd(ymm0, 5); ymm0 = _mm256_mul_pd(ymm1, ymm0); ymm3 = _mm256_mul_pd(ymm2, ymm3); ymm0 = _mm256_addsub_pd(ymm0, ymm3); ymm5 = _mm256_add_pd(ymm5, ymm0); _mm_storeu_pd((double *)(tC), _mm256_castpd256_pd128(ymm5)); tC += tc_inc_col; _mm_storeu_pd((double *)(tC) ,_mm256_extractf128_pd (ymm5,1)); } } else { if(beta->real == 0.0 && beta->imag == 0.0) { _mm256_storeu_pd((double *)(tC), ymm4); _mm256_storeu_pd((double *)(tC + 2), ymm5); } else{ /* (br + bi) C + (ar + ai) AB */ ymm0 = _mm256_broadcast_sd((double const *)(beta)); // load beta_r and duplicate ymm1 = _mm256_broadcast_sd((double const *)(&beta->imag)); // load beta_i and duplicate ymm2 = _mm256_loadu_pd((double const *)(tC)); ymm3 = _mm256_permute_pd(ymm2, 5); ymm2 = _mm256_mul_pd(ymm0, ymm2); ymm3 =_mm256_mul_pd(ymm1, ymm3); ymm4 = _mm256_add_pd(ymm4, _mm256_addsub_pd(ymm2, ymm3)); ymm2 = _mm256_loadu_pd((double const *)(tC+2)); ymm3 = _mm256_permute_pd(ymm2, 5); ymm2 = _mm256_mul_pd(ymm0, ymm2); ymm3 = _mm256_mul_pd(ymm1, ymm3); ymm5 = _mm256_add_pd(ymm5, _mm256_addsub_pd(ymm2, ymm3)); _mm256_storeu_pd((double *)(tC), ymm4); _mm256_storeu_pd((double *)(tC + 2), ymm5); } } } consider_edge_cases: // Handle edge cases in the m dimension, if they exist. if ( n_left ) { const dim_t mr_cur = 3; const dim_t j_edge = n0 - ( dim_t )n_left; dcomplex* restrict cij = c + j_edge*cs_c; dcomplex* restrict ai = a; dcomplex* restrict bj = b + n_iter * 4; if ( 2 <= n_left ) { const dim_t nr_cur = 2; bli_zgemmsup_rv_zen_asm_1x2 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 1 == n_left ) { bli_zgemv_ex ( BLIS_NO_TRANSPOSE, conjb, m0, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, beta, cij, rs_c0, cntx, NULL ); } } } void bli_zgemmsup_rv_zen_asm_3x2 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, dcomplex* restrict alpha, dcomplex* restrict a, inc_t rs_a0, inc_t cs_a0, dcomplex* restrict b, inc_t rs_b0, inc_t cs_b0, dcomplex* restrict beta, dcomplex* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { uint64_t k_iter = 0; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- //scratch registers __m256d ymm0, ymm1, ymm2, ymm3; __m256d ymm4, ymm6; __m256d ymm8, ymm10; __m256d ymm12, ymm14; __m128d xmm0, xmm3; dcomplex *tA = a; double *tAimag = &a->imag; dcomplex *tB = b; dcomplex *tC = c; // clear scratch registers. ymm4 = _mm256_setzero_pd(); ymm6 = _mm256_setzero_pd(); ymm8 = _mm256_setzero_pd(); ymm10 = _mm256_setzero_pd(); ymm12 = _mm256_setzero_pd(); ymm14 = _mm256_setzero_pd(); dim_t ta_inc_row = rs_a; dim_t tb_inc_row = rs_b; dim_t tc_inc_row = rs_c; dim_t ta_inc_col = cs_a; dim_t tc_inc_col = cs_c; for (k_iter = 0; k_iter imag)); // load alpha_i and duplicate ymm3 = _mm256_permute_pd(ymm4, 5); ymm4 = _mm256_mul_pd(ymm0, ymm4); ymm3 =_mm256_mul_pd(ymm1, ymm3); ymm4 = _mm256_addsub_pd(ymm4, ymm3); ymm3 = _mm256_permute_pd(ymm8, 5); ymm8 = _mm256_mul_pd(ymm0, ymm8); ymm3 = _mm256_mul_pd(ymm1, ymm3); ymm8 = _mm256_addsub_pd(ymm8, ymm3); ymm3 = _mm256_permute_pd(ymm12, 5); ymm12 = _mm256_mul_pd(ymm0, ymm12); ymm3 = _mm256_mul_pd(ymm1, ymm3); ymm12 = _mm256_addsub_pd(ymm12, ymm3); if(tc_inc_row == 1) //col stored { if(beta->real == 0.0 && beta->imag == 0.0) { //transpose left 3x2 _mm_storeu_pd((double *)(tC), _mm256_castpd256_pd128(ymm4)); _mm_storeu_pd((double *)(tC+1), _mm256_castpd256_pd128(ymm8)); _mm_storeu_pd((double *)(tC+2), _mm256_castpd256_pd128(ymm12)); tC += tc_inc_col; _mm_storeu_pd((double *)(tC ),_mm256_extractf128_pd (ymm4,1)); _mm_storeu_pd((double *)(tC+1) ,_mm256_extractf128_pd (ymm8,1)); _mm_storeu_pd((double *)(tC+2), _mm256_extractf128_pd(ymm12, 1)); } else{ ymm1 = _mm256_broadcast_sd((double const *)(beta)); // load alpha_r and duplicate ymm2 = _mm256_broadcast_sd((double const *)(&beta->imag)); // load alpha_i and duplicate //Multiply ymm4 with beta xmm0 = _mm_loadu_pd((double *)(tC)) ; xmm3 = _mm_loadu_pd((double *)(tC + tc_inc_col)) ; ymm0 = _mm256_insertf128_pd(_mm256_castpd128_pd256(xmm0), xmm3, 1) ; ymm3 = _mm256_permute_pd(ymm0, 5); ymm0 = _mm256_mul_pd(ymm1, ymm0); ymm3 = _mm256_mul_pd(ymm2, ymm3); ymm0 = _mm256_addsub_pd(ymm0, ymm3); ymm4 = _mm256_add_pd(ymm4, ymm0); //Multiply ymm8 with beta xmm0 = _mm_loadu_pd((double *)(tC + 1)) ; xmm3 = _mm_loadu_pd((double *)(tC + 1 + tc_inc_col)) ; ymm0 = _mm256_insertf128_pd(_mm256_castpd128_pd256(xmm0), xmm3, 1) ; ymm3 = _mm256_permute_pd(ymm0, 5); ymm0 = _mm256_mul_pd(ymm1, ymm0); ymm3 = _mm256_mul_pd(ymm2, ymm3); ymm0 = _mm256_addsub_pd(ymm0, ymm3); ymm8 = _mm256_add_pd(ymm8, ymm0); //Multiply ymm12 with beta xmm0 = _mm_loadu_pd((double *)(tC + 2)) ; xmm3 = _mm_loadu_pd((double *)(tC + 2 + tc_inc_col)) ; ymm0 = _mm256_insertf128_pd(_mm256_castpd128_pd256(xmm0), xmm3, 1) ; ymm3 = _mm256_permute_pd(ymm0, 5); ymm0 = _mm256_mul_pd(ymm1, ymm0); ymm3 = _mm256_mul_pd(ymm2, ymm3); ymm0 = _mm256_addsub_pd(ymm0, ymm3); ymm12 = _mm256_add_pd(ymm12, ymm0); _mm_storeu_pd((double *)(tC), _mm256_castpd256_pd128(ymm4)); _mm_storeu_pd((double *)(tC+1), _mm256_castpd256_pd128(ymm8)); _mm_storeu_pd((double *)(tC+2), _mm256_castpd256_pd128(ymm12)); tC += tc_inc_col; _mm_storeu_pd((double *)(tC ),_mm256_extractf128_pd (ymm4,1)); _mm_storeu_pd((double *)(tC+1) ,_mm256_extractf128_pd (ymm8,1)); _mm_storeu_pd((double *)(tC+2), _mm256_extractf128_pd(ymm12, 1)); } } else { if(beta->real == 0.0 && beta->imag == 0.0) { _mm256_storeu_pd((double *)(tC), ymm4); _mm256_storeu_pd((double *)(tC + tc_inc_row ), ymm8); _mm256_storeu_pd((double *)(tC + tc_inc_row *2), ymm12); } else{ /* (br + bi) C + (ar + ai) AB */ ymm0 = _mm256_broadcast_sd((double const *)(beta)); // load beta_r and duplicate ymm1 = _mm256_broadcast_sd((double const *)(&beta->imag)); // load beta_i and duplicate ymm2 = _mm256_loadu_pd((double const *)(tC)); ymm3 = _mm256_permute_pd(ymm2, 5); ymm2 = _mm256_mul_pd(ymm0, ymm2); ymm3 =_mm256_mul_pd(ymm1, ymm3); ymm4 = _mm256_add_pd(ymm4, _mm256_addsub_pd(ymm2, ymm3)); ymm2 = _mm256_loadu_pd((double const *)(tC+tc_inc_row)); ymm3 = _mm256_permute_pd(ymm2, 5); ymm2 = _mm256_mul_pd(ymm0, ymm2); ymm3 = _mm256_mul_pd(ymm1, ymm3); ymm8 = _mm256_add_pd(ymm8, _mm256_addsub_pd(ymm2, ymm3)); ymm2 = _mm256_loadu_pd((double const *)(tC+tc_inc_row*2)); ymm3 = _mm256_permute_pd(ymm2, 5); ymm2 = _mm256_mul_pd(ymm0, ymm2); ymm3 = _mm256_mul_pd(ymm1, ymm3); ymm12 = _mm256_add_pd(ymm12, _mm256_addsub_pd(ymm2, ymm3)); _mm256_storeu_pd((double *)(tC), ymm4); _mm256_storeu_pd((double *)(tC + tc_inc_row) , ymm8); _mm256_storeu_pd((double *)(tC + tc_inc_row *2), ymm12); } } } blis-0.9.0/kernels/zen/3/sup/other/000077500000000000000000000000001422157504600170105ustar00rootroot00000000000000blis-0.9.0/kernels/zen/3/sup/other/bli_gemmsup_rd_zen_asm_s6x16.c000066400000000000000000003204101422157504600246270ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define BLIS_ASM_SYNTAX_ATT #include "bli_x86_asm_macros.h" /* rrc: -------- ------ | | | | | | | | -------- ------ | | | | | | | | -------- += ------ ... | | | | | | | | -------- ------ | | | | | | | | -------- ------ : -------- ------ : Assumptions: - C is row-stored and B is column-stored; - A is row-stored; - m0 and n0 are at most MR and NR, respectively. Therefore, this (r)ow-preferential microkernel is well-suited for a dot-product-based accumulation that performs vector loads from both A and B. */ void bli_sgemmsup_rd_zen_asm_2x16 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter32 = k0 / 32; uint64_t k_left32 = k0 % 32; uint64_t k_iter8 = k_left32 / 8; uint64_t k_left1 = k_left32 % 8; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() mov(var(a), r14) // load address of a. mov(var(rs_a), r8) // load rs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) mov(var(b), rdx) // load address of b. mov(var(cs_b), r11) // load cs_b lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) // r12 = rcx = c // r14 = rax = a // rdx = rbx = b // r9 = unused // r15 = n dim index jj // r10 = unused mov(imm(0), r15) // jj = 0; label(.SLOOP3X4J) // LOOP OVER jj = [ 0 1 ... ] // zen2 can execute 4 vxorpd ipc with // a latency of 1 cycle. vxorps(ymm4, ymm4, ymm4) vxorps(ymm5, ymm5, ymm5) vxorps(ymm7, ymm7, ymm7) vxorps(ymm8, ymm8, ymm8) vxorps(ymm10, ymm10, ymm10) vxorps(ymm11, ymm11, ymm11) vxorps(ymm13, ymm13, ymm13) vxorps(ymm14, ymm14, ymm14) lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(imm(1*4), rsi) // rsi *= cs_c = 1*8 lea(mem(r12, rsi, 1), rcx) // rcx = c + 4*jj*cs_c; lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(r11, rsi) // rsi *= cs_b; lea(mem(rdx, rsi, 1), rbx) // rbx = b + 4*jj*cs_b; lea(mem(r14), rax) // rax = a; prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 3*8)) // prefetch c + 1*rs_c mov(var(k_iter32), rsi) // i = k_iter32; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKITER8) // if i == 0, jump to code that // contains the k_iter8 loop. label(.SLOOPKITER32) // MAIN LOOP // ---------------------------------- iteration 0 vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) add(imm(8*4), rax) // a += 4*cs_b = 4*8; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) // ---------------------------------- iteration 1 vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) add(imm(8*4), rax) // a += 4*cs_b = 4*8; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) // ---------------------------------- iteration 2 vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) add(imm(8*4), rax) // a += 4*cs_b = 4*8; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) // ---------------------------------- iteration 3 vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) add(imm(8*4), rax) // a += 4*cs_b = 4*8; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) dec(rsi) // i -= 1; jne(.SLOOPKITER32) // iterate again if i != 0. label(.SCONSIDKITER8) mov(var(k_iter8), rsi) // i = k_iter8; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter8 loop. label(.SLOOPKITER8) // EDGE LOOP (ymm) vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) add(imm(8*4), rax) // a += 4*cs_b = 4*8; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) dec(rsi) // i -= 1; jne(.SLOOPKITER8) // iterate again if i != 0. label(.SCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.SLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovss(mem(rax ), xmm0) vmovss(mem(rax, r8, 1), xmm1) add(imm(1*4), rax) // a += 1*cs_b = 1*8; vmovss(mem(rbx ), xmm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovss(mem(rbx, r11, 1), xmm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vmovss(mem(rbx, r11, 2), xmm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vmovss(mem(rbx, r13, 1), xmm3) add(imm(1*4), rbx) // b += 1*rs_b = 1*8; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) dec(rsi) // i -= 1; jne(.SLOOPKLEFT1) // iterate again if i != 0. label(.SPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 // ymm5 ymm8 ymm11 ymm14 vhaddps( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddps( xmm0, xmm1, xmm0 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm7) vhaddps( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddps( xmm2, xmm1, xmm2 ) // xmm2[0] = sum(ymm10); xmm2[1] = sum(ymm13) vhaddps(xmm2,xmm0,xmm4) vhaddps( ymm8, ymm5, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddps( xmm0, xmm1, xmm0 ) vhaddps( ymm14, ymm11, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddps( xmm2, xmm1, xmm2 ) vhaddps(xmm2,xmm0,xmm5) // ymm4 = sum(ymm4) sum(ymm7) sum(ymm10) sum(ymm13) // ymm5 = sum(ymm5) sum(ymm8) sum(ymm11) sum(ymm14) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), ymm0) // load alpha and duplicate vbroadcastss(mem(rbx), ymm3) // load beta and duplicate vmulps(xmm0, xmm4, xmm4) // scale by alpha vmulps(xmm0, xmm5, xmm5) // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case label(.SROWSTORED) vfmadd231ps(mem(rcx), xmm3,xmm4) vmovups(xmm4, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), xmm3, xmm5) vmovups(xmm5, mem(rcx)) jmp(.SDONE) // jump to end. label(.SBETAZERO) label(.SROWSTORBZ) vmovups(xmm4, mem(rcx)) add(rdi, rcx) vmovups(xmm5, mem(rcx)) label(.SDONE) add(imm(4), r15) // jj += 4; cmp(imm(16), r15) // compare jj to 4 jl(.SLOOP3X4J) // if jj <= 4, jump to beginning // of jj loop; otherwise, loop ends. label(.SRETURN) end_asm( : // output operands (none) : // input operands [k_iter32] "m" (k_iter32), [k_iter8] "m" (k_iter8), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_sgemmsup_rd_zen_asm_1x16 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter32 = k0 / 32; uint64_t k_left32 = k0 % 32; uint64_t k_iter8 = k_left32 / 8; uint64_t k_left1 = k_left32 % 8; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() mov(var(a), r14) // load address of a. mov(var(b), rdx) // load address of b. mov(var(cs_b), r11) // load cs_b lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b mov(var(c), r12) // load address of c // r12 = rcx = c // r14 = rax = a // rdx = rbx = b // r9 = m dim index ii // r15 = n dim index jj mov(imm(0), r15) // jj = 0; label(.SLOOP3X4J) // LOOP OVER jj = [ 0 1 ... ] // zen2 can execute 4 vxorpd ipc with // a latency of 1 cycle. vxorps(ymm4, ymm4, ymm4) vxorps(ymm7, ymm7, ymm7) vxorps(ymm10, ymm10, ymm10) vxorps(ymm13, ymm13, ymm13) lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(imm(1*4), rsi) // rsi *= cs_c = 1*8 lea(mem(r12, rsi, 1), rcx) // rcx = c + 4*jj*cs_c; lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(r11, rsi) // rsi *= cs_b; lea(mem(rdx, rsi, 1), rbx) // rbx = b + 4*jj*cs_b; lea(mem(r14), rax) // rax = a; prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c mov(var(k_iter32), rsi) // i = k_iter32; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKITER8) // if i == 0, jump to code that // contains the k_iter8 loop. label(.SLOOPKITER32) // MAIN LOOP // ---------------------------------- iteration 0 vmovups(mem(rax ), ymm0) add(imm(8*4), rax) // a += 4*cs_b = 4*8; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vfmadd231ps(ymm0, ymm3, ymm13) // ---------------------------------- iteration 1 vmovups(mem(rax ), ymm0) add(imm(8*4), rax) // a += 4*cs_b = 4*8; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vfmadd231ps(ymm0, ymm3, ymm13) // ---------------------------------- iteration 2 vmovups(mem(rax ), ymm0) add(imm(8*4), rax) // a += 4*cs_b = 4*8; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vfmadd231ps(ymm0, ymm3, ymm13) // ---------------------------------- iteration 3 vmovups(mem(rax ), ymm0) add(imm(8*4), rax) // a += 4*cs_b = 4*8; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vfmadd231ps(ymm0, ymm3, ymm13) dec(rsi) // i -= 1; jne(.SLOOPKITER32) // iterate again if i != 0. label(.SCONSIDKITER8) mov(var(k_iter8), rsi) // i = k_iter8; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter8 loop. label(.SLOOPKITER8) // EDGE LOOP (ymm) vmovups(mem(rax ), ymm0) add(imm(8*4), rax) // a += 4*cs_b = 4*8; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vfmadd231ps(ymm0, ymm3, ymm13) dec(rsi) // i -= 1; jne(.SLOOPKITER8) // iterate again if i != 0. label(.SCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.SLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovss(mem(rax ), xmm0) add(imm(1*4), rax) // a += 1*cs_b = 1*8; vmovss(mem(rbx ), xmm3) vfmadd231ps(ymm0, ymm3, ymm4) vmovss(mem(rbx, r11, 1), xmm3) vfmadd231ps(ymm0, ymm3, ymm7) vmovss(mem(rbx, r11, 2), xmm3) vfmadd231ps(ymm0, ymm3, ymm10) vmovss(mem(rbx, r13, 1), xmm3) add(imm(1*4), rbx) // b += 1*rs_b = 1*8; vfmadd231ps(ymm0, ymm3, ymm13) dec(rsi) // i -= 1; jne(.SLOOPKLEFT1) // iterate again if i != 0. label(.SPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 vhaddps( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddps( xmm0, xmm1, xmm0 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm7) vhaddps( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddps( xmm2, xmm1, xmm2 ) // xmm2[0] = sum(ymm10); xmm2[1] = sum(ymm13) vhaddps(xmm2,xmm0,xmm4) // ymm4 = sum(ymm4) sum(ymm7) sum(ymm10) sum(ymm13) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), ymm0) // load alpha and duplicate vbroadcastss(mem(rbx), ymm3) // load beta and duplicate vmulps(xmm0, xmm4, xmm4) // scale by alpha // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case label(.SROWSTORED) vfmadd231ps(mem(rcx), ymm3, ymm4) vmovups(xmm4, mem(rcx)) jmp(.SDONE) // jump to end. label(.SBETAZERO) label(.SROWSTORBZ) vmovups(xmm4, mem(rcx)) label(.SDONE) add(imm(4), r15) // jj += 4; cmp(imm(16), r15) // compare jj to 4 jl(.SLOOP3X4J) // if jj <= 4, jump to beginning // of jj loop; otherwise, loop ends. label(.SRETURN) end_asm( : // output operands (none) : // input operands [k_iter32] "m" (k_iter32), [k_iter8] "m" (k_iter8), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_sgemmsup_rd_zen_asm_2x8 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter32 = k0 / 32; uint64_t k_left32 = k0 % 32; uint64_t k_iter8 = k_left32 / 8; uint64_t k_left1 = k_left32 % 8; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() mov(var(a), r14) // load address of a. mov(var(rs_a), r8) // load rs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) mov(var(b), rdx) // load address of b. mov(var(cs_b), r11) // load cs_b lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) // r12 = rcx = c // r14 = rax = a // rdx = rbx = b // r9 = unused // r15 = n dim index jj // r10 = unused mov(imm(0), r15) // jj = 0; label(.SLOOP3X4J) // LOOP OVER jj = [ 0 1 ... ] // zen2 can execute 4 vxorpd ipc with // a latency of 1 cycle. vxorps(ymm4, ymm4, ymm4) vxorps(ymm5, ymm5, ymm5) vxorps(ymm7, ymm7, ymm7) vxorps(ymm8, ymm8, ymm8) vxorps(ymm10, ymm10, ymm10) vxorps(ymm11, ymm11, ymm11) vxorps(ymm13, ymm13, ymm13) vxorps(ymm14, ymm14, ymm14) lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(imm(1*4), rsi) // rsi *= cs_c = 1*8 lea(mem(r12, rsi, 1), rcx) // rcx = c + 4*jj*cs_c; lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(r11, rsi) // rsi *= cs_b; lea(mem(rdx, rsi, 1), rbx) // rbx = b + 4*jj*cs_b; lea(mem(r14), rax) // rax = a; prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 3*8)) // prefetch c + 1*rs_c mov(var(k_iter32), rsi) // i = k_iter32; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKITER8) // if i == 0, jump to code that // contains the k_iter8 loop. label(.SLOOPKITER32) // MAIN LOOP // ---------------------------------- iteration 0 vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) add(imm(8*4), rax) // a += 4*cs_b = 4*8; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) // ---------------------------------- iteration 1 vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) add(imm(8*4), rax) // a += 4*cs_b = 4*8; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) // ---------------------------------- iteration 2 vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) add(imm(8*4), rax) // a += 4*cs_b = 4*8; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) // ---------------------------------- iteration 3 vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) add(imm(8*4), rax) // a += 4*cs_b = 4*8; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) dec(rsi) // i -= 1; jne(.SLOOPKITER32) // iterate again if i != 0. label(.SCONSIDKITER8) mov(var(k_iter8), rsi) // i = k_iter8; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter8 loop. label(.SLOOPKITER8) // EDGE LOOP (ymm) vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) add(imm(8*4), rax) // a += 4*cs_b = 4*8; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) dec(rsi) // i -= 1; jne(.SLOOPKITER8) // iterate again if i != 0. label(.SCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.SLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovss(mem(rax ), xmm0) vmovss(mem(rax, r8, 1), xmm1) add(imm(1*4), rax) // a += 1*cs_b = 1*8; vmovss(mem(rbx ), xmm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovss(mem(rbx, r11, 1), xmm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vmovss(mem(rbx, r11, 2), xmm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vmovss(mem(rbx, r13, 1), xmm3) add(imm(1*4), rbx) // b += 1*rs_b = 1*8; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) dec(rsi) // i -= 1; jne(.SLOOPKLEFT1) // iterate again if i != 0. label(.SPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 // ymm5 ymm8 ymm11 ymm14 vhaddps( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddps( xmm0, xmm1, xmm0 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm7) vhaddps( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddps( xmm2, xmm1, xmm2 ) // xmm2[0] = sum(ymm10); xmm2[1] = sum(ymm13) vhaddps(xmm2,xmm0,xmm4) vhaddps( ymm8, ymm5, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddps( xmm0, xmm1, xmm0 ) vhaddps( ymm14, ymm11, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddps( xmm2, xmm1, xmm2 ) vhaddps(xmm2,xmm0,xmm5) // ymm4 = sum(ymm4) sum(ymm7) sum(ymm10) sum(ymm13) // ymm5 = sum(ymm5) sum(ymm8) sum(ymm11) sum(ymm14) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), ymm0) // load alpha and duplicate vbroadcastss(mem(rbx), ymm3) // load beta and duplicate vmulps(xmm0, xmm4, xmm4) // scale by alpha vmulps(xmm0, xmm5, xmm5) // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case label(.SROWSTORED) vfmadd231ps(mem(rcx), xmm3,xmm4) vmovups(xmm4, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), xmm3, xmm5) vmovups(xmm5, mem(rcx)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SBETAZERO) label(.SROWSTORBZ) vmovups(xmm4, mem(rcx)) add(rdi, rcx) vmovups(xmm5, mem(rcx)) label(.SDONE) add(imm(4), r15) // jj += 4; cmp(imm(8), r15) // compare jj to 4 jl(.SLOOP3X4J) // if jj <= 4, jump to beginning // of jj loop; otherwise, loop ends. label(.SRETURN) end_asm( : // output operands (none) : // input operands [k_iter32] "m" (k_iter32), [k_iter8] "m" (k_iter8), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_sgemmsup_rd_zen_asm_1x8 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter32 = k0 / 32; uint64_t k_left32 = k0 % 32; uint64_t k_iter8 = k_left32 / 8; uint64_t k_left1 = k_left32 % 8; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() mov(var(a), r14) // load address of a. mov(var(b), rdx) // load address of b. mov(var(cs_b), r11) // load cs_b lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b mov(var(c), r12) // load address of c // r12 = rcx = c // r14 = rax = a // rdx = rbx = b // r9 = m dim index ii // r15 = n dim index jj mov(imm(0), r15) // jj = 0; label(.SLOOP3X4J) // LOOP OVER jj = [ 0 1 ... ] // zen2 can execute 4 vxorpd ipc with // a latency of 1 cycle. vxorps(ymm4, ymm4, ymm4) vxorps(ymm7, ymm7, ymm7) vxorps(ymm10, ymm10, ymm10) vxorps(ymm13, ymm13, ymm13) lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(imm(1*4), rsi) // rsi *= cs_c = 1*8 lea(mem(r12, rsi, 1), rcx) // rcx = c + 4*jj*cs_c; lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(r11, rsi) // rsi *= cs_b; lea(mem(rdx, rsi, 1), rbx) // rbx = b + 4*jj*cs_b; lea(mem(r14), rax) // rax = a; prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c mov(var(k_iter32), rsi) // i = k_iter32; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKITER8) // if i == 0, jump to code that // contains the k_iter8 loop. label(.SLOOPKITER32) // MAIN LOOP // ---------------------------------- iteration 0 vmovups(mem(rax ), ymm0) add(imm(8*4), rax) // a += 4*cs_b = 4*8; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vfmadd231ps(ymm0, ymm3, ymm13) // ---------------------------------- iteration 1 vmovups(mem(rax ), ymm0) add(imm(8*4), rax) // a += 4*cs_b = 4*8; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vfmadd231ps(ymm0, ymm3, ymm13) // ---------------------------------- iteration 2 vmovups(mem(rax ), ymm0) add(imm(8*4), rax) // a += 4*cs_b = 4*8; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vfmadd231ps(ymm0, ymm3, ymm13) // ---------------------------------- iteration 3 vmovups(mem(rax ), ymm0) add(imm(8*4), rax) // a += 4*cs_b = 4*8; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vfmadd231ps(ymm0, ymm3, ymm13) dec(rsi) // i -= 1; jne(.SLOOPKITER32) // iterate again if i != 0. label(.SCONSIDKITER8) mov(var(k_iter8), rsi) // i = k_iter8; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter8 loop. label(.SLOOPKITER8) // EDGE LOOP (ymm) vmovups(mem(rax ), ymm0) add(imm(8*4), rax) // a += 4*cs_b = 4*8; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vfmadd231ps(ymm0, ymm3, ymm13) dec(rsi) // i -= 1; jne(.SLOOPKITER8) // iterate again if i != 0. label(.SCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.SLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovss(mem(rax ), xmm0) add(imm(1*4), rax) // a += 1*cs_b = 1*8; vmovss(mem(rbx ), xmm3) vfmadd231ps(ymm0, ymm3, ymm4) vmovss(mem(rbx, r11, 1), xmm3) vfmadd231ps(ymm0, ymm3, ymm7) vmovss(mem(rbx, r11, 2), xmm3) vfmadd231ps(ymm0, ymm3, ymm10) vmovss(mem(rbx, r13, 1), xmm3) add(imm(1*4), rbx) // b += 1*rs_b = 1*8; vfmadd231ps(ymm0, ymm3, ymm13) dec(rsi) // i -= 1; jne(.SLOOPKLEFT1) // iterate again if i != 0. label(.SPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 vhaddps( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddps( xmm0, xmm1, xmm0 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm7) vhaddps( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddps( xmm2, xmm1, xmm2 ) // xmm2[0] = sum(ymm10); xmm2[1] = sum(ymm13) vhaddps(xmm2,xmm0,xmm4) // ymm4 = sum(ymm4) sum(ymm7) sum(ymm10) sum(ymm13) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), ymm0) // load alpha and duplicate vbroadcastss(mem(rbx), ymm3) // load beta and duplicate vmulps(xmm0, xmm4, xmm4) // scale by alpha // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case label(.SROWSTORED) vfmadd231ps(mem(rcx), xmm3,xmm4) vmovups(xmm4, mem(rcx)) jmp(.SDONE) // jump to end. label(.SBETAZERO) label(.SROWSTORBZ) vmovups(xmm4, mem(rcx)) label(.SDONE) add(imm(4), r15) // jj += 4; cmp(imm(4), r15) // compare jj to 4 jle(.SLOOP3X4J) // if jj <= 4, jump to beginning // of jj loop; otherwise, loop ends. label(.SRETURN) end_asm( : // output operands (none) : // input operands [k_iter32] "m" (k_iter32), [k_iter8] "m" (k_iter8), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_sgemmsup_rd_zen_asm_2x4 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter32 = k0 / 32; uint64_t k_left32 = k0 % 32; uint64_t k_iter8 = k_left32 / 8; uint64_t k_left1 = k_left32 % 8; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() // zen2 can execute 4 vxorpd ipc with // a latency of 1 cycle vxorps(ymm4, ymm4, ymm4) vxorps(ymm5, ymm5, ymm5) vxorps(ymm7, ymm7, ymm7) vxorps(ymm8, ymm8, ymm8) vxorps(ymm10, ymm10, ymm10) vxorps(ymm11, ymm11, ymm11) vxorps(ymm13, ymm13, ymm13) vxorps(ymm14, ymm14, ymm14) mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) mov(var(b), rbx) // load address of b. mov(var(cs_b), r11) // load cs_b lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 3*8)) // prefetch c + 1*rs_c mov(var(k_iter32), rsi) // i = k_iter32; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKITER8) // if i == 0, jump to code that // contains the k_iter8 loop. label(.SLOOPKITER32) // MAIN LOOP // ---------------------------------- iteration 0 vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) add(imm(8*4), rax) // a += 4*cs_b = 4*8; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) // ---------------------------------- iteration 1 vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) add(imm(8*4), rax) // a += 4*cs_b = 4*8; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) // ---------------------------------- iteration 2 vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) add(imm(8*4), rax) // a += 4*cs_b = 4*8; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) // ---------------------------------- iteration 3 vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) add(imm(8*4), rax) // a += 4*cs_b = 4*8; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) dec(rsi) // i -= 1; jne(.SLOOPKITER32) // iterate again if i != 0. label(.SCONSIDKITER8) mov(var(k_iter8), rsi) // i = k_iter8; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter8 loop. label(.SLOOPKITER8) // EDGE LOOP (ymm) vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) add(imm(8*4), rax) // a += 4*cs_b = 4*8; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) dec(rsi) // i -= 1; jne(.SLOOPKITER8) // iterate again if i != 0. label(.SCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.SLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovss(mem(rax ), xmm0) vmovss(mem(rax, r8, 1), xmm1) add(imm(1*4), rax) // a += 1*cs_b = 1*8; vmovss(mem(rbx ), xmm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovss(mem(rbx, r11, 1), xmm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vmovss(mem(rbx, r11, 2), xmm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vmovss(mem(rbx, r13, 1), xmm3) add(imm(1*4), rbx) // b += 1*rs_b = 1*8; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) dec(rsi) // i -= 1; jne(.SLOOPKLEFT1) // iterate again if i != 0. label(.SPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 // ymm5 ymm8 ymm11 ymm14 vhaddps( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddps( xmm0, xmm1, xmm0 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm7) vhaddps( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddps( xmm2, xmm1, xmm2 ) // xmm2[0] = sum(ymm10); xmm2[1] = sum(ymm13) vhaddps(xmm2,xmm0,xmm4) vhaddps( ymm8, ymm5, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddps( xmm0, xmm1, xmm0 ) vhaddps( ymm14, ymm11, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddps( xmm2, xmm1, xmm2 ) vhaddps(xmm2,xmm0,xmm5) // ymm4 = sum(ymm4) sum(ymm7) sum(ymm10) sum(ymm13) // ymm5 = sum(ymm5) sum(ymm8) sum(ymm11) sum(ymm14) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), ymm0) // load alpha and duplicate vbroadcastss(mem(rbx), ymm3) // load beta and duplicate vmulps(xmm0, xmm4, xmm4) // scale by alpha vmulps(xmm0, xmm5, xmm5) // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case label(.SROWSTORED) vfmadd231ps(mem(rcx), xmm3,xmm4) vmovups(xmm4, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), xmm3, xmm5) vmovups(xmm5, mem(rcx)) jmp(.SDONE) // jump to end. label(.SBETAZERO) label(.SROWSTORBZ) vmovups(xmm4, mem(rcx)) add(rdi, rcx) vmovups(xmm5, mem(rcx)) label(.SDONE) end_asm( : // output operands (none) : // input operands [k_iter32] "m" (k_iter32), [k_iter8] "m" (k_iter8), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_sgemmsup_rd_zen_asm_1x4 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter32 = k0 / 32; uint64_t k_left32 = k0 % 32; uint64_t k_iter8 = k_left32 / 8; uint64_t k_left1 = k_left32 % 8; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() // zen2 can execute 4 vxorpd ipc with // a latency of 1 cycle vxorps(ymm4, ymm4, ymm4) vxorps(ymm7, ymm7, ymm7) vxorps(ymm10, ymm10, ymm10) vxorps(ymm13, ymm13, ymm13) mov(var(a), rax) // load address of a. mov(var(b), rbx) // load address of b. mov(var(cs_b), r11) // load cs_b lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b mov(var(c), rcx) // load address of c prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c mov(var(k_iter32), rsi) // i = k_iter32; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKITER8) // if i == 0, jump to code that // contains the k_iter8 loop. label(.SLOOPKITER32) // MAIN LOOP // ---------------------------------- iteration 0 vmovups(mem(rax ), ymm0) add(imm(8*4), rax) // a += 4*cs_b = 4*8; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vfmadd231ps(ymm0, ymm3, ymm13) // ---------------------------------- iteration 1 vmovups(mem(rax ), ymm0) add(imm(8*4), rax) // a += 4*cs_b = 4*8; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vfmadd231ps(ymm0, ymm3, ymm13) // ---------------------------------- iteration 2 vmovups(mem(rax ), ymm0) add(imm(8*4), rax) // a += 4*cs_b = 4*8; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vfmadd231ps(ymm0, ymm3, ymm13) // ---------------------------------- iteration 3 vmovups(mem(rax ), ymm0) add(imm(8*4), rax) // a += 4*cs_b = 4*8; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vfmadd231ps(ymm0, ymm3, ymm13) dec(rsi) // i -= 1; jne(.SLOOPKITER32) // iterate again if i != 0. label(.SCONSIDKITER8) mov(var(k_iter8), rsi) // i = k_iter8; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter8 loop. label(.SLOOPKITER8) // EDGE LOOP (ymm) vmovups(mem(rax ), ymm0) add(imm(8*4), rax) // a += 4*cs_b = 4*8; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vfmadd231ps(ymm0, ymm3, ymm13) dec(rsi) // i -= 1; jne(.SLOOPKITER8) // iterate again if i != 0. label(.SCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.SLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovss(mem(rax ), xmm0) add(imm(1*4), rax) // a += 1*cs_b = 1*8; vmovss(mem(rbx ), xmm3) vfmadd231ps(ymm0, ymm3, ymm4) vmovss(mem(rbx, r11, 1), xmm3) vfmadd231ps(ymm0, ymm3, ymm7) vmovss(mem(rbx, r11, 2), xmm3) vfmadd231ps(ymm0, ymm3, ymm10) vmovss(mem(rbx, r13, 1), xmm3) add(imm(1*4), rbx) // b += 1*rs_b = 1*8; vfmadd231ps(ymm0, ymm3, ymm13) dec(rsi) // i -= 1; jne(.SLOOPKLEFT1) // iterate again if i != 0. label(.SPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 vhaddps( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddps( xmm0, xmm1, xmm0 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm7) vhaddps( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddps( xmm2, xmm1, xmm2 ) // xmm2[0] = sum(ymm10); xmm2[1] = sum(ymm13) vhaddps(xmm2,xmm0,xmm4) // ymm4 = sum(ymm4) sum(ymm7) sum(ymm10) sum(ymm13) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), ymm0) // load alpha and duplicate vbroadcastss(mem(rbx), ymm3) // load beta and duplicate vmulps(xmm0, xmm4, xmm4) // scale by alpha // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case label(.SROWSTORED) vfmadd231ps(mem(rcx), xmm3,xmm4) vmovups(xmm4, mem(rcx)) jmp(.SDONE) // jump to end. label(.SBETAZERO) label(.SROWSTORBZ) vmovups(xmm4, mem(rcx)) label(.SDONE) end_asm( : // output operands (none) : // input operands [k_iter32] "m" (k_iter32), [k_iter8] "m" (k_iter8), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_sgemmsup_rd_zen_asm_2x2 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter32 = k0 / 32; uint64_t k_left32 = k0 % 32; uint64_t k_iter8 = k_left32 / 8; uint64_t k_left1 = k_left32 % 8; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() // zen2 can execute 4 vxorpd ipc with // a latency of 1 cycle vxorps(ymm4, ymm4, ymm4) vxorps(ymm5, ymm5, ymm5) vxorps(ymm6, ymm6, ymm6) vxorps(ymm7, ymm7, ymm7) mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) mov(var(b), rbx) // load address of b. mov(var(cs_b), r11) // load cs_b lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) // initialize loop by pre-loading // a column of a. mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) prefetch(0, mem(rcx, 1*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 1*8)) // prefetch c + 1*rs_c mov(var(k_iter32), rsi) // i = k_iter32; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKITER8) // if i == 0, jump to code that // contains the k_iter8 loop. label(.SLOOPKITER32) // MAIN LOOP // ---------------------------------- iteration 0 vmovups(mem(rbx ), ymm0) vmovups(mem(rbx, r11, 1), ymm1) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vmovups(mem(rax ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovups(mem(rax, r8, 1), ymm3) add(imm(8*4), rax) // a += 4*cs_a = 4*8; vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) // ---------------------------------- iteration 1 vmovups(mem(rbx ), ymm0) vmovups(mem(rbx, r11, 1), ymm1) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vmovups(mem(rax ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovups(mem(rax, r8, 1), ymm3) add(imm(8*4), rax) // a += 4*cs_a = 4*8; vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) // ---------------------------------- iteration 2 vmovups(mem(rbx ), ymm0) vmovups(mem(rbx, r11, 1), ymm1) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vmovups(mem(rax ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovups(mem(rax, r8, 1), ymm3) add(imm(8*4), rax) // a += 4*cs_a = 4*8; vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) // ---------------------------------- iteration 3 vmovups(mem(rbx ), ymm0) vmovups(mem(rbx, r11, 1), ymm1) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vmovups(mem(rax ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovups(mem(rax, r8, 1), ymm3) add(imm(8*4), rax) // a += 4*cs_a = 4*8; vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) dec(rsi) // i -= 1; jne(.SLOOPKITER32) // iterate again if i != 0. label(.SCONSIDKITER8) mov(var(k_iter8), rsi) // i = k_iter8; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter8 loop. label(.SLOOPKITER8) // EDGE LOOP (ymm) vmovups(mem(rbx ), ymm0) vmovups(mem(rbx, r11, 1), ymm1) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vmovups(mem(rax ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovups(mem(rax, r8, 1), ymm3) add(imm(8*4), rax) // a += 4*cs_a = 4*8; vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) dec(rsi) // i -= 1; jne(.SLOOPKITER8) // iterate again if i != 0. label(.SCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.SLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovss(mem(rbx ), xmm0) vmovss(mem(rbx, r11, 1), xmm1) add(imm(1*4), rbx) // b += 1*rs_b = 1*8; vmovss(mem(rax ), xmm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovss(mem(rax, r8, 1), xmm3) add(imm(1*4), rax) // a += 1*cs_a = 1*8; vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) dec(rsi) // i -= 1; jne(.SLOOPKLEFT1) // iterate again if i != 0. label(.SPOSTACCUM) // ymm4 ymm5 // ymm6 ymm7 vhaddps( ymm5, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddps( xmm0, xmm1, xmm0 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm5) vhaddps(xmm0,xmm0,xmm4) vhaddps( ymm7, ymm6, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddps( xmm0, xmm1, xmm0 ) vhaddps(xmm0,xmm0,xmm6) // xmm4 = sum(ymm4) sum(ymm5) // xmm6 = sum(ymm6) sum(ymm7) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), ymm0) // load alpha and duplicate vbroadcastss(mem(rbx), ymm3) // load beta and duplicate vmulps(xmm0, xmm4, xmm4) // scale by alpha vmulps(xmm0, xmm6, xmm6) // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case label(.SROWSTORED) vmovsd(mem(rcx), xmm0)////a0a1 vfmadd231ps(xmm0, xmm3, xmm4)//c*beta+(a0a1) vmovsd(xmm4, mem(rcx))//a0a1 add(rdi, rcx) vmovsd(mem(rcx), xmm0) vfmadd231ps(xmm0, xmm3, xmm6) vmovsd(xmm6, mem(rcx)) jmp(.SDONE) // jump to end. label(.SBETAZERO) label(.SROWSTORBZ) vmovsd(xmm4, mem(rcx)) add(rdi, rcx) vmovsd(xmm6, mem(rcx)) label(.SDONE) end_asm( : // output operands (none) : // input operands [k_iter32] "m" (k_iter32), [k_iter8] "m" (k_iter8), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_sgemmsup_rd_zen_asm_1x2 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter32 = k0 / 32; uint64_t k_left32 = k0 % 32; uint64_t k_iter8 = k_left32 / 8; uint64_t k_left1 = k_left32 % 8; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() // zen2 can execute 4 vxorpd ipc with // a latency of 1 cycle. vxorps(ymm4, ymm4, ymm4) vxorps(ymm5, ymm5, ymm5) mov(var(a), rax) // load address of a. mov(var(b), rbx) // load address of b. mov(var(cs_b), r11) // load cs_b lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) // initialize loop by pre-loading // a column of a. mov(var(c), rcx) // load address of c prefetch(0, mem(rcx, 1*8)) // prefetch c + 0*rs_c mov(var(k_iter32), rsi) // i = k_iter32; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKITER8) // if i == 0, jump to code that // contains the k_iter8 loop. label(.SLOOPKITER32) // MAIN LOOP // ---------------------------------- iteration 0 vmovups(mem(rbx ), ymm0) vmovups(mem(rbx, r11, 1), ymm1) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vmovups(mem(rax ), ymm3) add(imm(8*4), rax) // a += 4*cs_a = 4*8; vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) // ---------------------------------- iteration 1 vmovups(mem(rbx ), ymm0) vmovups(mem(rbx, r11, 1), ymm1) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vmovups(mem(rax ), ymm3) add(imm(8*4), rax) // a += 4*cs_a = 4*8; vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) // ---------------------------------- iteration 2 vmovups(mem(rbx ), ymm0) vmovups(mem(rbx, r11, 1), ymm1) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vmovups(mem(rax ), ymm3) add(imm(8*4), rax) // a += 4*cs_a = 4*8; vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) // ---------------------------------- iteration 3 vmovups(mem(rbx ), ymm0) vmovups(mem(rbx, r11, 1), ymm1) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vmovups(mem(rax ), ymm3) add(imm(8*4), rax) // a += 4*cs_a = 4*8; vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) dec(rsi) // i -= 1; jne(.SLOOPKITER32) // iterate again if i != 0. label(.SCONSIDKITER8) mov(var(k_iter8), rsi) // i = k_iter8; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter8 loop. label(.SLOOPKITER8) // EDGE LOOP (ymm) vmovups(mem(rbx ), ymm0) vmovups(mem(rbx, r11, 1), ymm1) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vmovups(mem(rax ), ymm3) add(imm(8*4), rax) // a += 4*cs_a = 4*8; vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) dec(rsi) // i -= 1; jne(.SLOOPKITER8) // iterate again if i != 0. label(.SCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.SLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovss(mem(rbx ), xmm0) vmovss(mem(rbx, r11, 1), xmm1) add(imm(1*4), rbx) // b += 1*rs_b = 1*8; vmovss(mem(rax ), xmm3) add(imm(1*4), rax) // a += 1*cs_a = 1*8; vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) dec(rsi) // i -= 1; jne(.SLOOPKLEFT1) // iterate again if i != 0. label(.SPOSTACCUM) // ymm4 ymm5 vhaddps( ymm5, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddps( xmm0, xmm1, xmm0 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm5) vhaddps(xmm0,xmm0,xmm4) // xmm4 = sum(ymm4) sum(ymm5) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), ymm0) // load alpha and duplicate vbroadcastss(mem(rbx), ymm3) // load beta and duplicate vmulps(xmm0, xmm4, xmm4) // scale by alpha // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case label(.SROWSTORED) vmovsd(mem(rcx), xmm0)////a0a1 vfmadd231ps(xmm0, xmm3, xmm4)//c*beta+(a0a1) vmovsd(xmm4, mem(rcx))//a0a1 jmp(.SDONE) // jump to end. label(.SBETAZERO) label(.SROWSTORBZ) vmovsd(xmm4, mem(rcx)) label(.SDONE) end_asm( : // output operands (none) : // input operands [k_iter32] "m" (k_iter32), [k_iter8] "m" (k_iter8), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_sgemmsup_rd_zen_asm_6x2 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter32 = k0 / 32; uint64_t k_left32 = k0 % 32; uint64_t k_iter8 = k_left32 / 8; uint64_t k_left1 = k_left32 % 8; uint64_t m_iter = m0 / 6; uint64_t m_left = m0 % 6; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; if ( m_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() mov(var(a), r14) // load address of a. mov(var(rs_a), r8) // load rs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rdx) // load address of b. mov(var(cs_b), r11) // load cs_b lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) // r12 = rcx = c // r14 = rax = a // rdx = rbx = b // r9 = m dim index ii mov(var(m_iter), r9) // ii = m_iter; label(.SLOOP3X4I) // LOOP OVER ii = [ m_iter ... 1 0 ] // zen2 can execute 4 vxorpd ipc with // a latency of 1 cycle, vxorps(ymm4, ymm4, ymm4) vxorps(ymm5, ymm5, ymm5) vxorps(ymm6, ymm6, ymm6) vxorps(ymm7, ymm7, ymm7) vxorps(ymm8, ymm8, ymm8) vxorps(ymm9, ymm9, ymm9) vxorps(ymm10, ymm10, ymm10) vxorps(ymm11, ymm11, ymm11) vxorps(ymm12, ymm12, ymm12) vxorps(ymm13, ymm13, ymm13) vxorps(ymm14, ymm14, ymm14) vxorps(ymm15, ymm15, ymm15) lea(mem(r12), rcx) // rcx = c + 6*ii*rs_c; lea(mem(r14), rax) // rax = a + 6*ii*rs_a; lea(mem(rdx), rbx) // rbx = b; lea(mem(rcx, rdi, 2), r10) // lea(mem(r10, rdi, 1), r10) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 1*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 1*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 1*8)) // prefetch c + 2*rs_c prefetch(0, mem(r10, 1*8)) // prefetch c + 3*rs_c prefetch(0, mem(r10, rdi, 1, 1*8)) // prefetch c + 4*rs_c prefetch(0, mem(r10, rdi, 2, 1*8)) // prefetch c + 5*rs_c mov(var(k_iter32), rsi) // i = k_iter32; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKITER8) // if i == 0, jump to code that // contains the k_iter8 loop. label(.SLOOPKITER32) // MAIN LOOP // ---------------------------------- iteration 0 vmovups(mem(rbx ), ymm0) vmovups(mem(rbx, r11, 1), ymm1) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vmovups(mem(rax ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovups(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vmovups(mem(rax, r8, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm8) vfmadd231ps(ymm1, ymm3, ymm9) vmovups(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vmovups(mem(rax, r8, 4), ymm3) vfmadd231ps(ymm0, ymm3, ymm12) vfmadd231ps(ymm1, ymm3, ymm13) vmovups(mem(rax, r15, 1), ymm3) add(imm(8*4), rax) // a += 4*cs_a = 4*8; vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) // ---------------------------------- iteration 1 vmovups(mem(rbx ), ymm0) vmovups(mem(rbx, r11, 1), ymm1) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vmovups(mem(rax ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovups(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vmovups(mem(rax, r8, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm8) vfmadd231ps(ymm1, ymm3, ymm9) vmovups(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vmovups(mem(rax, r8, 4), ymm3) vfmadd231ps(ymm0, ymm3, ymm12) vfmadd231ps(ymm1, ymm3, ymm13) vmovups(mem(rax, r15, 1), ymm3) add(imm(8*4), rax) // a += 4*cs_a = 4*8; vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) // ---------------------------------- iteration 2 vmovups(mem(rbx ), ymm0) vmovups(mem(rbx, r11, 1), ymm1) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vmovups(mem(rax ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovups(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vmovups(mem(rax, r8, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm8) vfmadd231ps(ymm1, ymm3, ymm9) vmovups(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vmovups(mem(rax, r8, 4), ymm3) vfmadd231ps(ymm0, ymm3, ymm12) vfmadd231ps(ymm1, ymm3, ymm13) vmovups(mem(rax, r15, 1), ymm3) add(imm(8*4), rax) // a += 4*cs_a = 4*8; vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) // ---------------------------------- iteration 3 vmovups(mem(rbx ), ymm0) vmovups(mem(rbx, r11, 1), ymm1) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vmovups(mem(rax ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovups(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vmovups(mem(rax, r8, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm8) vfmadd231ps(ymm1, ymm3, ymm9) vmovups(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vmovups(mem(rax, r8, 4), ymm3) vfmadd231ps(ymm0, ymm3, ymm12) vfmadd231ps(ymm1, ymm3, ymm13) vmovups(mem(rax, r15, 1), ymm3) add(imm(8*4), rax) // a += 4*cs_a = 4*8; vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) dec(rsi) // i -= 1; jne(.SLOOPKITER32) // iterate again if i != 0. label(.SCONSIDKITER8) mov(var(k_iter8), rsi) // i = k_iter8; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter8 loop. label(.SLOOPKITER8) // EDGE LOOP (ymm) vmovups(mem(rbx ), ymm0) vmovups(mem(rbx, r11, 1), ymm1) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vmovups(mem(rax ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovups(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vmovups(mem(rax, r8, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm8) vfmadd231ps(ymm1, ymm3, ymm9) vmovups(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vmovups(mem(rax, r8, 4), ymm3) vfmadd231ps(ymm0, ymm3, ymm12) vfmadd231ps(ymm1, ymm3, ymm13) vmovups(mem(rax, r15, 1), ymm3) add(imm(8*4), rax) // a += 4*cs_a = 4*8; vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) dec(rsi) // i -= 1; jne(.SLOOPKITER8) // iterate again if i != 0. label(.SCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.SLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovss(mem(rbx ), xmm0) vmovss(mem(rbx, r11, 1), xmm1) add(imm(1*4), rbx) // b += 1*rs_b = 1*8; vmovss(mem(rax ), xmm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovss(mem(rax, r8, 1), xmm3) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vmovss(mem(rax, r8, 2), xmm3) vfmadd231ps(ymm0, ymm3, ymm8) vfmadd231ps(ymm1, ymm3, ymm9) vmovss(mem(rax, r13, 1), xmm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vmovss(mem(rax, r8, 4), xmm3) vfmadd231ps(ymm0, ymm3, ymm12) vfmadd231ps(ymm1, ymm3, ymm13) vmovss(mem(rax, r15, 1), xmm3) add(imm(1*4), rax) // a += 1*cs_a = 1*8; vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) dec(rsi) // i -= 1; jne(.SLOOPKLEFT1) // iterate again if i != 0. label(.SPOSTACCUM) // ymm4 ymm5 // ymm6 ymm7 // ymm8 ymm9 // ymm10 ymm11 // ymm12 ymm13 // ymm14 ymm15 vhaddps( ymm5, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddps( xmm0, xmm1, xmm0 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm5) vhaddps(xmm0,xmm0,xmm4) vhaddps( ymm7, ymm6, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddps( xmm0, xmm1, xmm0 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm5) vhaddps(xmm0,xmm0,xmm6) vhaddps( ymm9, ymm8, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddps( xmm0, xmm1, xmm0 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm5) vhaddps(xmm0,xmm0,xmm8) vhaddps( ymm11, ymm10, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddps( xmm0, xmm1, xmm0 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm5) vhaddps(xmm0,xmm0,xmm10) vhaddps( ymm13, ymm12, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddps( xmm0, xmm1, xmm0 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm5) vhaddps(xmm0,xmm0,xmm12) vhaddps( ymm15, ymm14, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddps( xmm0, xmm1, xmm0 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm5) vhaddps(xmm0,xmm0,xmm14) // xmm4 = sum(ymm4) sum(ymm5) // xmm6 = sum(ymm6) sum(ymm7) // xmm8 = sum(ymm8) sum(ymm9) // xmm10 = sum(ymm10) sum(ymm11) // xmm12 = sum(ymm12) sum(ymm13) // xmm14 = sum(ymm14) sum(ymm15) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), ymm0) // load alpha and duplicate vbroadcastss(mem(rbx), ymm3) // load beta and duplicate vmulps(xmm0, xmm4, xmm4) // scale by alpha vmulps(xmm0, xmm6, xmm6) vmulps(xmm0, xmm8, xmm8) vmulps(xmm0, xmm10, xmm10) vmulps(xmm0, xmm12, xmm12) vmulps(xmm0, xmm14, xmm14) // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case label(.SROWSTORED) vmovsd(mem(rcx), xmm0)////a0a1 vfmadd231ps(xmm0, xmm3, xmm4)//c*beta+(a0a1) vmovsd(xmm4, mem(rcx))//a0a1 add(rdi, rcx) vmovsd(mem(rcx), xmm0)////a0a1 vfmadd231ps(xmm0, xmm3, xmm6)//c*beta+(a0a1) vmovsd(xmm6, mem(rcx))//a0a1 add(rdi, rcx) vmovsd(mem(rcx), xmm0)////a0a1 vfmadd231ps(xmm0, xmm3, xmm8)//c*beta+(a0a1) vmovsd(xmm8, mem(rcx))//a0a1 add(rdi, rcx) vmovsd(mem(rcx), xmm0)////a0a1 vfmadd231ps(xmm0, xmm3, xmm10)//c*beta+(a0a1) vmovsd(xmm10, mem(rcx))//a0a1 add(rdi, rcx) vmovsd(mem(rcx), xmm0)////a0a1 vfmadd231ps(xmm0, xmm3, xmm12)//c*beta+(a0a1) vmovsd(xmm12, mem(rcx))//a0a1 add(rdi, rcx) vmovsd(mem(rcx), xmm0)////a0a1 vfmadd231ps(xmm0, xmm3, xmm14)//c*beta+(a0a1) vmovsd(xmm14, mem(rcx))//a0a1 //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SBETAZERO) label(.SROWSTORBZ) vmovsd(xmm4, mem(rcx)) add(rdi, rcx) vmovsd(xmm6, mem(rcx)) add(rdi, rcx) vmovsd(xmm8, mem(rcx)) add(rdi, rcx) vmovsd(xmm10, mem(rcx)) add(rdi, rcx) vmovsd(xmm12, mem(rcx)) add(rdi, rcx) vmovsd(xmm14, mem(rcx)) label(.SDONE) lea(mem(r12, rdi, 4), r12) // lea(mem(r12, rdi, 2), r12) // c_ii = r12 += 6*rs_c lea(mem(r14, r8, 4), r14) // lea(mem(r14, r8, 2), r14) // a_ii = r14 += 6*rs_a dec(r9) // ii -= 1; jne(.SLOOP3X4I) // iterate again if ii != 0. label(.SRETURN) end_asm( : // output operands (none) : // input operands [m_iter] "m" (m_iter), [k_iter32] "m" (k_iter32), [k_iter8] "m" (k_iter8), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the m dimension, if they exist. if ( m_left ) { const dim_t nr_cur = 2; const dim_t i_edge = m0 - ( dim_t )m_left; float* restrict cij = c + i_edge*rs_c; float* restrict bj = b; float* restrict ai = a + i_edge*rs_a; if ( 3 <= m_left ) { const dim_t mr_cur = 3; bli_sgemmsup_rd_zen_asm_3x2 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += mr_cur*rs_c0; ai += mr_cur*rs_a0; m_left -= mr_cur; } if ( 2 <= m_left ) { const dim_t mr_cur = 2; bli_sgemmsup_rd_zen_asm_2x2 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += mr_cur*rs_c0; ai += mr_cur*rs_a0; m_left -= mr_cur; } if ( 1 == m_left ) { const dim_t mr_cur = 1; bli_sgemmsup_rd_zen_asm_1x2 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); } } } void bli_sgemmsup_rd_zen_asm_3x2 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter32 = k0 / 32; uint64_t k_left32 = k0 % 32; uint64_t k_iter8 = k_left32 / 8; uint64_t k_left1 = k_left32 % 8; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vzeroall() // zero all xmm/ymm registers. mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) mov(var(b), rbx) // load address of b. mov(var(cs_b), r11) // load cs_b lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) // initialize loop by pre-loading // a column of a. mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 7*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 7*8)) // prefetch c + 2*rs_c mov(var(k_iter32), rsi) // i = k_iter32; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKITER8) // if i == 0, jump to code that // contains the k_iter8 loop. label(.SLOOPKITER32) // MAIN LOOP // ---------------------------------- iteration 0 vmovups(mem(rbx ), ymm0) vmovups(mem(rbx, r11, 1), ymm1) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vmovups(mem(rax ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovups(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vmovups(mem(rax, r8, 2), ymm3) add(imm(8*4), rax) // a += 4*cs_a = 4*8; vfmadd231ps(ymm0, ymm3, ymm8) vfmadd231ps(ymm1, ymm3, ymm9) // ---------------------------------- iteration 1 vmovups(mem(rbx ), ymm0) vmovups(mem(rbx, r11, 1), ymm1) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vmovups(mem(rax ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovups(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vmovups(mem(rax, r8, 2), ymm3) add(imm(8*4), rax) // a += 4*cs_a = 4*8; vfmadd231ps(ymm0, ymm3, ymm8) vfmadd231ps(ymm1, ymm3, ymm9) // ---------------------------------- iteration 2 vmovups(mem(rbx ), ymm0) vmovups(mem(rbx, r11, 1), ymm1) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vmovups(mem(rax ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovups(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vmovups(mem(rax, r8, 2), ymm3) add(imm(8*4), rax) // a += 4*cs_a = 4*8; vfmadd231ps(ymm0, ymm3, ymm8) vfmadd231ps(ymm1, ymm3, ymm9) // ---------------------------------- iteration 3 vmovups(mem(rbx ), ymm0) vmovups(mem(rbx, r11, 1), ymm1) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vmovups(mem(rax ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovups(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vmovups(mem(rax, r8, 2), ymm3) add(imm(8*4), rax) // a += 4*cs_a = 4*8; vfmadd231ps(ymm0, ymm3, ymm8) vfmadd231ps(ymm1, ymm3, ymm9) dec(rsi) // i -= 1; jne(.SLOOPKITER32) // iterate again if i != 0. label(.SCONSIDKITER8) mov(var(k_iter8), rsi) // i = k_iter8; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter8 loop. label(.SLOOPKITER8) // EDGE LOOP (ymm) vmovups(mem(rbx ), ymm0) vmovups(mem(rbx, r11, 1), ymm1) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vmovups(mem(rax ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovups(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vmovups(mem(rax, r8, 2), ymm3) add(imm(8*4), rax) // a += 4*cs_a = 4*8; vfmadd231ps(ymm0, ymm3, ymm8) vfmadd231ps(ymm1, ymm3, ymm9) dec(rsi) // i -= 1; jne(.SLOOPKITER8) // iterate again if i != 0. label(.SCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.SLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovss(mem(rbx ), xmm0) vmovss(mem(rbx, r11, 1), xmm1) add(imm(1*4), rbx) // b += 1*rs_b = 1*8; vmovss(mem(rax ), xmm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovss(mem(rax, r8, 1), xmm3) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vmovss(mem(rax, r8, 2), xmm3) add(imm(1*4), rax) // a += 1*cs_a = 1*8; vfmadd231ps(ymm0, ymm3, ymm8) vfmadd231ps(ymm1, ymm3, ymm9) dec(rsi) // i -= 1; jne(.SLOOPKLEFT1) // iterate again if i != 0. label(.SPOSTACCUM) // ymm4 ymm5 // ymm6 ymm7 // ymm8 ymm9 vhaddps( ymm5, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddps( xmm0, xmm1, xmm0 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm5) vhaddps(xmm0,xmm0,xmm4) vhaddps( ymm7, ymm6, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddps( xmm0, xmm1, xmm0 ) vhaddps(xmm0,xmm0,xmm6) vhaddps( ymm9, ymm8, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddps( xmm0, xmm1, xmm0 ) vhaddps(xmm0,xmm0,xmm8) // xmm4 = sum(ymm4) sum(ymm5) // xmm6 = sum(ymm6) sum(ymm7) // xmm8 = sum(ymm8) sum(ymm9) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), ymm0) // load alpha and duplicate vbroadcastss(mem(rbx), ymm3) // load beta and duplicate vmulps(xmm0, xmm4, xmm4) // scale by alpha vmulps(xmm0, xmm6, xmm6) vmulps(xmm0, xmm8, xmm8) // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case label(.SROWSTORED) vmovsd(mem(rcx), xmm0) vfmadd231ps(xmm0, xmm3, xmm4) vmovsd(xmm4, mem(rcx)) add(rdi, rcx) vmovsd(mem(rcx), xmm0) vfmadd231ps(xmm0, xmm3, xmm6) vmovsd(xmm6, mem(rcx)) add(rdi, rcx) vmovsd(mem(rcx), xmm0) vfmadd231ps(xmm0, xmm3, xmm8) vmovsd(xmm8, mem(rcx)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SBETAZERO) label(.SROWSTORBZ) vmovsd(xmm4, mem(rcx)) add(rdi, rcx) vmovsd(xmm6, mem(rcx)) add(rdi, rcx) vmovsd(xmm8, mem(rcx)) label(.SDONE) end_asm( : // output operands (none) : // input operands [k_iter32] "m" (k_iter32), [k_iter8] "m" (k_iter8), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } blis-0.9.0/kernels/zen/3/sup/other/bli_gemmsup_rd_zen_asm_s6x16m.c000066400000000000000000002024561422157504600250150ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define BLIS_ASM_SYNTAX_ATT #include "bli_x86_asm_macros.h" /* rrc: -------- ------ | | | | | | | | -------- ------ | | | | | | | | -------- += ------ ... | | | | | | | | -------- ------ | | | | | | | | -------- ------ : -------- ------ : Assumptions: - C is row-stored and B is column-stored; - A is row-stored; - m0 and n0 are at most MR and NR, respectively. Therefore, this (r)ow-preferential microkernel is well-suited for a dot-product-based accumulation that performs vector loads from both A and B. NOTE: These kernels implicitly support column-oriented IO, implemented via an a high-level transposition of the entire operation. A and B will effectively remain row- and column-stored, respectively, but C will then effectively appear column-stored. Thus, this kernel may be used for both rrc and crc cases. */ // Prototype reference microkernels. void bli_sgemmsup_rd_zen_asm_6x16m ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { uint64_t n_left = n0 % 16; // First check whether this is a edge case in the n dimension. If so, // dispatch other 6x?m kernels, as needed. if ( n_left ) { float* restrict cij = c; float* restrict bj = b; float* restrict ai = a; if ( 8 <= n_left ) { const dim_t nr_cur = 8; bli_sgemmsup_rd_zen_asm_6x8m ( conja, conjb, m0, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 4 <= n_left ) { const dim_t nr_cur = 4; bli_sgemmsup_rd_zen_asm_6x4m ( conja, conjb, m0, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 2 <= n_left ) { const dim_t nr_cur = 2; bli_sgemmsup_rd_zen_asm_6x2m ( conja, conjb, m0, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 1 == n_left ) { bli_sgemv_ex ( BLIS_NO_TRANSPOSE, conjb, m0, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, beta, cij, rs_c0, cntx, NULL ); } return; } // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter32 = k0 / 32; uint64_t k_left32 = k0 % 32; uint64_t k_iter8 = k_left32 / 8; uint64_t k_left1 = k_left32 % 8; uint64_t m_iter = m0 / 3; uint64_t m_left = m0 % 3; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; if ( m_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() mov(var(rs_a), r8) // load rs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) mov(var(b), rdx) // load address of b. mov(var(cs_b), r11) // load cs_b lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b lea(mem(r8, r8, 2), r10) // r10 = 3*rs_a // r12 = rcx = c // r14 = rax = a // rdx = rbx = b // r9 = m dim index ii // r15 = n dim index jj mov(imm(0), r15) // jj = 0; label(.SLOOP3X4J) // LOOP OVER jj = [ 0 1 ... ] mov(var(a), r14) // load address of a mov(var(c), r12) // load address of c mov(var(b), rdx) lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(imm(1*4), rsi) // rsi *= cs_c = 1*8 lea(mem(r12, rsi, 1), r12) // r12 = c + 4*jj*cs_c; lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(r11, rsi) // rsi *= cs_b; lea(mem(rdx, rsi, 1), rdx) // rbx = b + 4*jj*cs_b; mov(var(m_iter), r9) // ii = m_iter; label(.SLOOP3X4I) // LOOP OVER ii = [ m_iter ... 1 0 ] // zen2 can execute 4 vxorpd ipc with // a latency of 1 cycle vxorps(ymm4, ymm4, ymm4) vxorps(ymm5, ymm5, ymm5) vxorps(ymm6, ymm6, ymm6) vxorps(ymm7, ymm7, ymm7) vxorps(ymm8, ymm8, ymm8) vxorps(ymm9, ymm9, ymm9) vxorps(ymm10, ymm10, ymm10) vxorps(ymm11, ymm11, ymm11) vxorps(ymm12, ymm12, ymm12) vxorps(ymm13, ymm13, ymm13) vxorps(ymm14, ymm14, ymm14) vxorps(ymm15, ymm15, ymm15) lea(mem(r12), rcx) // rcx = c_iijj; lea(mem(r14), rax) // rax = a_ii; lea(mem(rdx), rbx) // rbx = b_jj; lea(mem(r8, r8, 4), rdi) // rdi = 5*rs_a mov(var(k_iter32), rsi) // i = k_iter32; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKITER8) // if i == 0, jump to code that // contains the k_iter8 loop. label(.SLOOPKITER32) // MAIN LOOP // ---------------------------------- iteration 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rdi, 1, 0*8)) // prefetch rax + 5*cs_a vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) vmovups(mem(rax, r8, 2), ymm2) add(imm(8*4), rax) // a += 4*cs_b = 4*8; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) // ---------------------------------- iteration 1 vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) vmovups(mem(rax, r8, 2), ymm2) add(imm(8*4), rax) // a += 4*cs_b = 4*8; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) // ---------------------------------- iteration 2 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rdi, 1, 0*8)) // prefetch rax + 5*cs_a vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) vmovups(mem(rax, r8, 2), ymm2) add(imm(8*4), rax) // a += 4*cs_b = 4*8; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) // ---------------------------------- iteration 3 vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) vmovups(mem(rax, r8, 2), ymm2) add(imm(8*4), rax) // a += 4*cs_b = 4*8; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.SLOOPKITER32) // iterate again if i != 0. label(.SCONSIDKITER8) mov(var(k_iter8), rsi) // i = k_iter8; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter8 loop. label(.SLOOPKITER8) // EDGE LOOP (ymm) prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rdi, 1, 0*8)) // prefetch rax + 5*cs_a vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) vmovups(mem(rax, r8, 2), ymm2) add(imm(8*4), rax) // a += 4*cs_b = 4*8; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.SLOOPKITER8) // iterate again if i != 0. label(.SCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.SLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovss(mem(rax ), xmm0) vmovss(mem(rax, r8, 1), xmm1) vmovss(mem(rax, r8, 2), xmm2) add(imm(1*4), rax) // a += 1*cs_b = 1*4; vmovss(mem(rbx ), xmm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovss(mem(rbx, r11, 1), xmm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovss(mem(rbx, r11, 2), xmm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovss(mem(rbx, r13, 1), xmm3) add(imm(1*4), rbx) // b += 1*rs_b = 1*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.SLOOPKLEFT1) // iterate again if i != 0. label(.SPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 // ymm5 ymm8 ymm11 ymm14 // ymm6 ymm9 ymm12 ymm15 vhaddps( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddps( xmm0, xmm1, xmm0 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm7) vhaddps( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddps( xmm2, xmm1, xmm2 ) // xmm2[0] = sum(ymm10); xmm2[1] = sum(ymm13) vhaddps(xmm2,xmm0,xmm4) vhaddps( ymm8, ymm5, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddps( xmm0, xmm1, xmm0 ) vhaddps( ymm14, ymm11, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddps( xmm2, xmm1, xmm2 ) vhaddps(xmm2,xmm0,xmm5) vhaddps( ymm9, ymm6, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddps( xmm0, xmm1, xmm0 ) vhaddps( ymm15, ymm12, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddps( xmm2, xmm1, xmm2 ) vhaddps(xmm2,xmm0,xmm6) // ymm4 = sum(ymm4) sum(ymm7) sum(ymm10) sum(ymm13) // ymm5 = sum(ymm5) sum(ymm8) sum(ymm11) sum(ymm14) // ymm6 = sum(ymm6) sum(ymm9) sum(ymm12) sum(ymm15) mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), xmm0) // load alpha and duplicate vbroadcastss(mem(rbx), xmm3) // load beta and duplicate vmulps(xmm0, xmm4, xmm4) // scale by alpha vmulps(xmm0, xmm5, xmm5) vmulps(xmm0, xmm6, xmm6) // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case label(.SROWSTORED) vfmadd231ps(mem(rcx), xmm3, xmm4) vmovups(xmm4, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), xmm3, xmm5) vmovups(xmm5, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), xmm3, xmm6) vmovups(xmm6, mem(rcx)) jmp(.SDONE) // jump to end. label(.SBETAZERO) label(.SROWSTORBZ) vmovups(xmm4, mem(rcx)) add(rdi, rcx) vmovups(xmm5, mem(rcx)) add(rdi, rcx) vmovups(xmm6, mem(rcx)) label(.SDONE) lea(mem(r12, rdi, 2), r12) // lea(mem(r12, rdi, 1), r12) // c_ii = r12 += 3*rs_c lea(mem(r14, r8, 2), r14) // lea(mem(r14, r8, 1), r14) // a_ii = r14 += 3*rs_a dec(r9) // ii -= 1; jne(.SLOOP3X4I) // iterate again if ii != 0. add(imm(4), r15) // jj += 4; cmp(imm(16), r15) // compare jj to 4 jl(.SLOOP3X4J) // if jj <= 4, jump to beginning // of jj loop; otherwise, loop ends. label(.SRETURN) end_asm( : // output operands (none) : // input operands [m_iter] "m" (m_iter), [k_iter32] "m" (k_iter32), [k_iter8] "m" (k_iter8), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the m dimension, if they exist. if ( m_left ) { const dim_t nr_cur = 16; const dim_t i_edge = m0 - ( dim_t )m_left; float* restrict cij = c + i_edge*rs_c; float* restrict bj = b; float* restrict ai = a + i_edge*rs_a; if ( 2 == m_left ) { const dim_t mr_cur = 2; bli_sgemmsup_rd_zen_asm_2x16 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); //cij += mr_cur*rs_c0; ai += mr_cur*rs_a0; m_left -= mr_cur; } if ( 1 == m_left ) { const dim_t mr_cur = 1; bli_sgemmsup_rd_zen_asm_1x16 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); } } } void bli_sgemmsup_rd_zen_asm_6x8m ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter32 = k0 / 32; uint64_t k_left32 = k0 % 32; uint64_t k_iter8 = k_left32 / 8; uint64_t k_left1 = k_left32 % 8; uint64_t m_iter = m0 / 3; uint64_t m_left = m0 % 3; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; if ( m_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() mov(var(rs_a), r8) // load rs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) mov(var(b), rdx) // load address of b. mov(var(cs_b), r11) // load cs_b lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b lea(mem(r8, r8, 2), r10) // r10 = 3*rs_a // r12 = rcx = c // r14 = rax = a // rdx = rbx = b // r9 = m dim index ii // r15 = n dim index jj mov(imm(0), r15) // jj = 0; label(.SLOOP3X4J) // LOOP OVER jj = [ 0 1 ... ] mov(var(a), r14) // load address of a mov(var(c), r12) // load address of c mov(var(b), rdx) lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(imm(1*4), rsi) // rsi *= cs_c = 1*8 lea(mem(r12, rsi, 1), r12) // r12 = c + 4*jj*cs_c; lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(r11, rsi) // rsi *= cs_b; lea(mem(rdx, rsi, 1), rdx) // rbx = b + 4*jj*cs_b; mov(var(m_iter), r9) // ii = m_iter; label(.SLOOP3X4I) // LOOP OVER ii = [ m_iter ... 1 0 ] // zen2 can execute 4 vxorpd ipc with // a latency of 1 cycle vxorps(ymm4, ymm4, ymm4) vxorps(ymm5, ymm5, ymm5) vxorps(ymm6, ymm6, ymm6) vxorps(ymm7, ymm7, ymm7) vxorps(ymm8, ymm8, ymm8) vxorps(ymm9, ymm9, ymm9) vxorps(ymm10, ymm10, ymm10) vxorps(ymm11, ymm11, ymm11) vxorps(ymm12, ymm12, ymm12) vxorps(ymm13, ymm13, ymm13) vxorps(ymm14, ymm14, ymm14) vxorps(ymm15, ymm15, ymm15) lea(mem(r12), rcx) // rcx = c_iijj; lea(mem(r14), rax) // rax = a_ii; lea(mem(rdx), rbx) // rbx = b_jj; lea(mem(r8, r8, 4), rdi) // rdi = 5*rs_a mov(var(k_iter32), rsi) // i = k_iter32; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKITER8) // if i == 0, jump to code that // contains the k_iter8 loop. label(.SLOOPKITER32) // MAIN LOOP // ---------------------------------- iteration 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rdi, 1, 0*8)) // prefetch rax + 5*cs_a vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) vmovups(mem(rax, r8, 2), ymm2) add(imm(8*4), rax) // a += 4*cs_b = 4*8; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) // ---------------------------------- iteration 1 vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) vmovups(mem(rax, r8, 2), ymm2) add(imm(8*4), rax) // a += 4*cs_b = 4*8; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) // ---------------------------------- iteration 2 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rdi, 1, 0*8)) // prefetch rax + 5*cs_a vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) vmovups(mem(rax, r8, 2), ymm2) add(imm(8*4), rax) // a += 4*cs_b = 4*8; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) // ---------------------------------- iteration 3 vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) vmovups(mem(rax, r8, 2), ymm2) add(imm(8*4), rax) // a += 4*cs_b = 4*8; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.SLOOPKITER32) // iterate again if i != 0. label(.SCONSIDKITER8) mov(var(k_iter8), rsi) // i = k_iter8; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter8 loop. label(.SLOOPKITER8) // EDGE LOOP (ymm) prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rdi, 1, 0*8)) // prefetch rax + 5*cs_a vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) vmovups(mem(rax, r8, 2), ymm2) add(imm(8*4), rax) // a += 4*cs_b = 4*8; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.SLOOPKITER8) // iterate again if i != 0. label(.SCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.SLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovss(mem(rax ), xmm0) vmovss(mem(rax, r8, 1), xmm1) vmovss(mem(rax, r8, 2), xmm2) add(imm(1*4), rax) // a += 1*cs_b = 1*4; vmovss(mem(rbx ), xmm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovss(mem(rbx, r11, 1), xmm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovss(mem(rbx, r11, 2), xmm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovss(mem(rbx, r13, 1), xmm3) add(imm(1*4), rbx) // b += 1*rs_b = 1*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.SLOOPKLEFT1) // iterate again if i != 0. label(.SPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 // ymm5 ymm8 ymm11 ymm14 // ymm6 ymm9 ymm12 ymm15 vhaddps( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddps( xmm0, xmm1, xmm0 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm7) vhaddps( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddps( xmm2, xmm1, xmm2 ) // xmm2[0] = sum(ymm10); xmm2[1] = sum(ymm13) vhaddps(xmm2,xmm0,xmm4) vhaddps( ymm8, ymm5, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddps( xmm0, xmm1, xmm0 ) vhaddps( ymm14, ymm11, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddps( xmm2, xmm1, xmm2 ) vhaddps(xmm2,xmm0,xmm5) vhaddps( ymm9, ymm6, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddps( xmm0, xmm1, xmm0 ) vhaddps( ymm15, ymm12, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddps( xmm2, xmm1, xmm2 ) vhaddps(xmm2,xmm0,xmm6) // ymm4 = sum(ymm4) sum(ymm7) sum(ymm10) sum(ymm13) // ymm5 = sum(ymm5) sum(ymm8) sum(ymm11) sum(ymm14) // ymm6 = sum(ymm6) sum(ymm9) sum(ymm12) sum(ymm15) mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), xmm0) // load alpha and duplicate vbroadcastss(mem(rbx), xmm3) // load beta and duplicate vmulps(xmm0, xmm4, xmm4) // scale by alpha vmulps(xmm0, xmm5, xmm5) vmulps(xmm0, xmm6, xmm6) // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case label(.SROWSTORED) vfmadd231ps(mem(rcx), xmm3, xmm4) vmovups(xmm4, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), xmm3, xmm5) vmovups(xmm5, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), xmm3, xmm6) vmovups(xmm6, mem(rcx)) jmp(.SDONE) // jump to end. label(.SBETAZERO) label(.SROWSTORBZ) vmovups(xmm4, mem(rcx)) add(rdi, rcx) vmovups(xmm5, mem(rcx)) add(rdi, rcx) vmovups(xmm6, mem(rcx)) label(.SDONE) lea(mem(r12, rdi, 2), r12) // lea(mem(r12, rdi, 1), r12) // c_ii = r12 += 3*rs_c lea(mem(r14, r8, 2), r14) // lea(mem(r14, r8, 1), r14) // a_ii = r14 += 3*rs_a dec(r9) // ii -= 1; jne(.SLOOP3X4I) // iterate again if ii != 0. add(imm(4), r15) // jj += 4; cmp(imm(8), r15) // compare jj to 4 jl(.SLOOP3X4J) // if jj <= 4, jump to beginning // of jj loop; otherwise, loop ends. label(.SRETURN) end_asm( : // output operands (none) : // input operands [m_iter] "m" (m_iter), [k_iter32] "m" (k_iter32), [k_iter8] "m" (k_iter8), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the m dimension, if they exist. if ( m_left ) { const dim_t nr_cur = 8; const dim_t i_edge = m0 - ( dim_t )m_left; float* restrict cij = c + i_edge*rs_c; float* restrict bj = b; float* restrict ai = a + i_edge*rs_a; if ( 2 == m_left ) { const dim_t mr_cur = 2; bli_sgemmsup_rd_zen_asm_2x8 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); //cij += mr_cur*rs_c0; ai += mr_cur*rs_a0; m_left -= mr_cur; } if ( 1 == m_left ) { const dim_t mr_cur = 1; bli_sgemmsup_rd_zen_asm_1x8 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); } } } void bli_sgemmsup_rd_zen_asm_6x4m ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter32 = k0 / 32; uint64_t k_left32 = k0 % 32; uint64_t k_iter8 = k_left32 / 8; uint64_t k_left1 = k_left32 % 8; uint64_t m_iter = m0 / 3; uint64_t m_left = m0 % 3; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; if ( m_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() mov(var(rs_a), r8) // load rs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) mov(var(b), rdx) // load address of b. mov(var(cs_b), r11) // load cs_b lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b lea(mem(r8, r8, 2), r10) // r10 = 3*rs_a // r12 = rcx = c // r14 = rax = a // rdx = rbx = b // r9 = m dim index ii // r15 = n dim index jj mov(imm(0), r15) // jj = 0; label(.SLOOP3X4J) // LOOP OVER jj = [ 0 1 ... ] mov(var(a), r14) // load address of a mov(var(c), r12) // load address of c mov(var(b), rdx) lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(imm(1*4), rsi) // rsi *= cs_c = 1*8 lea(mem(r12, rsi, 1), r12) // r12 = c + 4*jj*cs_c; lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(r11, rsi) // rsi *= cs_b; lea(mem(rdx, rsi, 1), rdx) // rbx = b + 4*jj*cs_b; mov(var(m_iter), r9) // ii = m_iter; label(.SLOOP3X4I) // LOOP OVER ii = [ m_iter ... 1 0 ] // zen2 can execute 4 vxorpd ipc with // a latency of 1 cycle vxorps(ymm4, ymm4, ymm4) vxorps(ymm5, ymm5, ymm5) vxorps(ymm6, ymm6, ymm6) vxorps(ymm7, ymm7, ymm7) vxorps(ymm8, ymm8, ymm8) vxorps(ymm9, ymm9, ymm9) vxorps(ymm10, ymm10, ymm10) vxorps(ymm11, ymm11, ymm11) vxorps(ymm12, ymm12, ymm12) vxorps(ymm13, ymm13, ymm13) vxorps(ymm14, ymm14, ymm14) vxorps(ymm15, ymm15, ymm15) lea(mem(r12), rcx) // rcx = c_iijj; lea(mem(r14), rax) // rax = a_ii; lea(mem(rdx), rbx) // rbx = b_jj; lea(mem(r8, r8, 4), rdi) // rdi = 5*rs_a mov(var(k_iter32), rsi) // i = k_iter32; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKITER8) // if i == 0, jump to code that // contains the k_iter8 loop. label(.SLOOPKITER32) // MAIN LOOP // ---------------------------------- iteration 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rdi, 1, 0*8)) // prefetch rax + 5*cs_a vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) vmovups(mem(rax, r8, 2), ymm2) add(imm(8*4), rax) // a += 4*cs_b = 4*8; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) // ---------------------------------- iteration 1 vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) vmovups(mem(rax, r8, 2), ymm2) add(imm(8*4), rax) // a += 4*cs_b = 4*8; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) // ---------------------------------- iteration 2 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rdi, 1, 0*8)) // prefetch rax + 5*cs_a vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) vmovups(mem(rax, r8, 2), ymm2) add(imm(8*4), rax) // a += 4*cs_b = 4*8; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) // ---------------------------------- iteration 3 vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) vmovups(mem(rax, r8, 2), ymm2) add(imm(8*4), rax) // a += 4*cs_b = 4*8; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.SLOOPKITER32) // iterate again if i != 0. label(.SCONSIDKITER8) mov(var(k_iter8), rsi) // i = k_iter8; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter8 loop. label(.SLOOPKITER8) // EDGE LOOP (ymm) prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rdi, 1, 0*8)) // prefetch rax + 5*cs_a vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) vmovups(mem(rax, r8, 2), ymm2) add(imm(8*4), rax) // a += 4*cs_b = 4*8; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.SLOOPKITER8) // iterate again if i != 0. label(.SCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.SLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovss(mem(rax ), xmm0) vmovss(mem(rax, r8, 1), xmm1) vmovss(mem(rax, r8, 2), xmm2) add(imm(1*4), rax) // a += 1*cs_b = 1*4; vmovss(mem(rbx ), xmm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovss(mem(rbx, r11, 1), xmm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovss(mem(rbx, r11, 2), xmm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovss(mem(rbx, r13, 1), xmm3) add(imm(1*4), rbx) // b += 1*rs_b = 1*4; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.SLOOPKLEFT1) // iterate again if i != 0. label(.SPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 // ymm5 ymm8 ymm11 ymm14 // ymm6 ymm9 ymm12 ymm15 vhaddps( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddps( xmm0, xmm1, xmm0 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm7) vhaddps( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddps( xmm2, xmm1, xmm2 ) // xmm2[0] = sum(ymm10); xmm2[1] = sum(ymm13) vhaddps(xmm2,xmm0,xmm4) vhaddps( ymm8, ymm5, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddps( xmm0, xmm1, xmm0 ) vhaddps( ymm14, ymm11, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddps( xmm2, xmm1, xmm2 ) vhaddps(xmm2,xmm0,xmm5) vhaddps( ymm9, ymm6, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddps( xmm0, xmm1, xmm0 ) vhaddps( ymm15, ymm12, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddps( xmm2, xmm1, xmm2 ) vhaddps(xmm2,xmm0,xmm6) // ymm4 = sum(ymm4) sum(ymm7) sum(ymm10) sum(ymm13) // ymm5 = sum(ymm5) sum(ymm8) sum(ymm11) sum(ymm14) // ymm6 = sum(ymm6) sum(ymm9) sum(ymm12) sum(ymm15) mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), xmm0) // load alpha and duplicate vbroadcastss(mem(rbx), xmm3) // load beta and duplicate vmulps(xmm0, xmm4, xmm4) // scale by alpha vmulps(xmm0, xmm5, xmm5) vmulps(xmm0, xmm6, xmm6) // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case label(.SROWSTORED) vfmadd231ps(mem(rcx), xmm3, xmm4) vmovups(xmm4, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), xmm3, xmm5) vmovups(xmm5, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), xmm3, xmm6) vmovups(xmm6, mem(rcx)) jmp(.SDONE) // jump to end. label(.SBETAZERO) label(.SROWSTORBZ) vmovups(xmm4, mem(rcx)) add(rdi, rcx) vmovups(xmm5, mem(rcx)) add(rdi, rcx) vmovups(xmm6, mem(rcx)) label(.SDONE) lea(mem(r12, rdi, 2), r12) // lea(mem(r12, rdi, 1), r12) // c_ii = r12 += 3*rs_c lea(mem(r14, r8, 2), r14) // lea(mem(r14, r8, 1), r14) // a_ii = r14 += 3*rs_a dec(r9) // ii -= 1; jne(.SLOOP3X4I) // iterate again if ii != 0. add(imm(4), r15) // jj += 4; cmp(imm(4), r15) // compare jj to 4 jl(.SLOOP3X4J) // if jj <= 4, jump to beginning // of jj loop; otherwise, loop ends. label(.SRETURN) end_asm( : // output operands (none) : // input operands [m_iter] "m" (m_iter), [k_iter32] "m" (k_iter32), [k_iter8] "m" (k_iter8), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the m dimension, if they exist. if ( m_left ) { const dim_t nr_cur = 4; const dim_t i_edge = m0 - ( dim_t )m_left; float* restrict cij = c + i_edge*rs_c; float* restrict bj = b; float* restrict ai = a + i_edge*rs_a; if ( 2 == m_left ) { const dim_t mr_cur = 2; bli_sgemmsup_rd_zen_asm_2x4 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); //cij += mr_cur*rs_c0; ai += mr_cur*rs_a0; m_left -= mr_cur; } if ( 1 == m_left ) { const dim_t mr_cur = 1; bli_sgemmsup_rd_zen_asm_1x4 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); } } } void bli_sgemmsup_rd_zen_asm_6x2m ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter32 = k0 / 32; uint64_t k_left32 = k0 % 32; uint64_t k_iter8 = k_left32 / 8; uint64_t k_left1 = k_left32 % 8; uint64_t m_iter = m0 / 3; uint64_t m_left = m0 % 3; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; if ( m_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() mov(var(rs_a), r8) // load rs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) mov(var(b), rdx) // load address of b. mov(var(cs_b), r11) // load cs_b lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b lea(mem(r8, r8, 2), r10) // r10 = 3*rs_a // r12 = rcx = c // r14 = rax = a // rdx = rbx = b // r9 = m dim index ii // r15 = n dim index jj mov(imm(0), r15) // jj = 0; label(.SLOOP3X4J) // LOOP OVER jj = [ 0 1 ... ] mov(var(a), r14) // load address of a mov(var(c), r12) // load address of c mov(var(b), rdx) lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(imm(1*4), rsi) // rsi *= cs_c = 1*8 lea(mem(r12, rsi, 1), r12) // r12 = c + 4*jj*cs_c; lea(mem( , r15, 1), rsi) // rsi = r15 = 4*jj; imul(r11, rsi) // rsi *= cs_b; lea(mem(rdx, rsi, 1), rdx) // rbx = b + 4*jj*cs_b; mov(var(m_iter), r9) // ii = m_iter; label(.SLOOP3X4I) // LOOP OVER ii = [ m_iter ... 1 0 ] // zen2 can execute 4 vxorpd ipc with // a latency of 1 cycle vxorps(ymm4, ymm4, ymm4) vxorps(ymm5, ymm5, ymm5) vxorps(ymm6, ymm6, ymm6) vxorps(ymm7, ymm7, ymm7) vxorps(ymm8, ymm8, ymm8) vxorps(ymm9, ymm9, ymm9) vxorps(ymm10, ymm10, ymm10) vxorps(ymm11, ymm11, ymm11) vxorps(ymm12, ymm12, ymm12) vxorps(ymm13, ymm13, ymm13) vxorps(ymm14, ymm14, ymm14) vxorps(ymm15, ymm15, ymm15) lea(mem(r12), rcx) // rcx = c_iijj; lea(mem(r14), rax) // rax = a_ii; lea(mem(rdx), rbx) // rbx = b_jj; lea(mem(r8, r8, 4), rdi) // rdi = 5*rs_a mov(var(k_iter32), rsi) // i = k_iter32; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKITER8) // if i == 0, jump to code that // contains the k_iter8 loop. label(.SLOOPKITER32) // MAIN LOOP // ---------------------------------- iteration 0 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rdi, 1, 0*8)) // prefetch rax + 5*cs_a vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) vmovups(mem(rax, r8, 2), ymm2) add(imm(8*4), rax) // a += 4*cs_b = 4*8; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; // ---------------------------------- iteration 1 vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) vmovups(mem(rax, r8, 2), ymm2) add(imm(8*4), rax) // a += 4*cs_b = 4*8; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; // ---------------------------------- iteration 2 prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rdi, 1, 0*8)) // prefetch rax + 5*cs_a vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) vmovups(mem(rax, r8, 2), ymm2) add(imm(8*4), rax) // a += 4*cs_b = 4*8; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; // ---------------------------------- iteration 3 vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) vmovups(mem(rax, r8, 2), ymm2) add(imm(8*4), rax) // a += 4*cs_b = 4*8; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; dec(rsi) // i -= 1; jne(.SLOOPKITER32) // iterate again if i != 0. label(.SCONSIDKITER8) mov(var(k_iter8), rsi) // i = k_iter8; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter8 loop. label(.SLOOPKITER8) // EDGE LOOP (ymm) prefetch(0, mem(rax, r10, 1, 0*8)) // prefetch rax + 3*cs_a prefetch(0, mem(rax, r8, 4, 0*8)) // prefetch rax + 4*cs_a prefetch(0, mem(rax, rdi, 1, 0*8)) // prefetch rax + 5*cs_a vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) vmovups(mem(rax, r8, 2), ymm2) add(imm(8*4), rax) // a += 4*cs_b = 4*8; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; dec(rsi) // i -= 1; jne(.SLOOPKITER8) // iterate again if i != 0. label(.SCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.SLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovss(mem(rax ), xmm0) vmovss(mem(rax, r8, 1), xmm1) vmovss(mem(rax, r8, 2), xmm2) add(imm(1*4), rax) // a += 1*cs_b = 1*4; vmovss(mem(rbx ), xmm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovss(mem(rbx, r11, 1), xmm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) add(imm(1*4), rbx) // b += 1*rs_b = 1*4; dec(rsi) // i -= 1; jne(.SLOOPKLEFT1) // iterate again if i != 0. label(.SPOSTACCUM) // ymm4 ymm7 // ymm5 ymm8 // ymm6 ymm9 vhaddps( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddps( xmm0, xmm1, xmm0 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm7) vhaddps(xmm0,xmm0,xmm4) vhaddps( ymm8, ymm5, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddps( xmm0, xmm1, xmm0 ) vhaddps(xmm0,xmm0,xmm5) vhaddps( ymm9, ymm6, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddps( xmm0, xmm1, xmm0 ) vhaddps(xmm0,xmm0,xmm6) // ymm4 = sum(ymm4) sum(ymm7) // ymm5 = sum(ymm5) sum(ymm8) // ymm6 = sum(ymm6) sum(ymm9) mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), xmm0) // load alpha and duplicate vbroadcastss(mem(rbx), xmm3) // load beta and duplicate vmulps(xmm0, xmm4, xmm4) // scale by alpha vmulps(xmm0, xmm5, xmm5) vmulps(xmm0, xmm6, xmm6) // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case label(.SROWSTORED) vmovsd(mem(rcx), xmm0)////a0a1 vfmadd231ps(xmm0, xmm3, xmm4)//c*beta+(a0a1) vmovsd(xmm4, mem(rcx))//a0a1 add(rdi, rcx) vmovsd(mem(rcx), xmm0) vfmadd231ps(xmm0, xmm3, xmm5) vmovsd(xmm5, mem(rcx)) add(rdi, rcx) vmovsd(mem(rcx), xmm0) vfmadd231ps(xmm0, xmm3, xmm6) vmovsd(xmm6, mem(rcx)) jmp(.SDONE) // jump to end. label(.SBETAZERO) label(.SROWSTORBZ) vmovsd(xmm4, mem(rcx)) add(rdi, rcx) vmovsd(xmm5, mem(rcx)) add(rdi, rcx) vmovsd(xmm6, mem(rcx)) label(.SDONE) lea(mem(r12, rdi, 2), r12) // lea(mem(r12, rdi, 1), r12) // c_ii = r12 += 3*rs_c lea(mem(r14, r8, 2), r14) // lea(mem(r14, r8, 1), r14) // a_ii = r14 += 3*rs_a dec(r9) // ii -= 1; jne(.SLOOP3X4I) // iterate again if ii != 0. add(imm(4), r15) // jj += 4; cmp(imm(4), r15) // compare jj to 4 jl(.SLOOP3X4J) // if jj <= 4, jump to beginning // of jj loop; otherwise, loop ends. label(.SRETURN) end_asm( : // output operands (none) : // input operands [m_iter] "m" (m_iter), [k_iter32] "m" (k_iter32), [k_iter8] "m" (k_iter8), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the m dimension, if they exist. if ( m_left ) { const dim_t nr_cur = 2; const dim_t i_edge = m0 - ( dim_t )m_left; float* restrict cij = c + i_edge*rs_c; float* restrict bj = b; float* restrict ai = a + i_edge*rs_a; if ( 2 == m_left ) { const dim_t mr_cur = 2; bli_sgemmsup_rd_zen_asm_2x2 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); //cij += mr_cur*rs_c0; ai += mr_cur*rs_a0; m_left -= mr_cur; } if ( 1 == m_left ) { const dim_t mr_cur = 1; bli_sgemmsup_rd_zen_asm_1x2 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); } } } blis-0.9.0/kernels/zen/3/sup/other/bli_gemmsup_rd_zen_asm_s6x16n.c000066400000000000000000001732421422157504600250160ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define BLIS_ASM_SYNTAX_ATT #include "bli_x86_asm_macros.h" /* rrc: -------- ------ | | | | | | | | -------- ------ | | | | | | | | -------- += ------ ... | | | | | | | | -------- ------ | | | | | | | | -------- ------ : -------- ------ : Assumptions: - C is row-stored and B is column-stored; - A is row-stored; - m0 and n0 are at most MR and NR, respectively. Therefore, this (r)ow-preferential microkernel is well-suited for a dot-product-based accumulation that performs vector loads from both A and B. NOTE: These kernels implicitly support column-oriented IO, implemented via an a high-level transposition of the entire operation. A and B will effectively remain row- and column-stored, respectively, but C will then effectively appear column-stored. Thus, this kernel may be used for both rrc and crc cases. */ void bli_sgemmsup_rd_zen_asm_6x16n ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { uint64_t m_left = m0 % 6; // First check whether this is a edge case in the n dimension. If so, // dispatch other ?x8m kernels, as needed. if ( m_left ) { float* restrict cij = c; float* restrict bj = b; float* restrict ai = a; // We add special handling for slightly inflated MR blocksizes // at edge cases, up to a maximum of 9. if ( 6 < m0 ) { sgemmsup_ker_ft ker_fp1 = NULL; sgemmsup_ker_ft ker_fp2 = NULL; dim_t mr1, mr2; if ( m0 == 7 ) { mr1 = 6; mr2 = 1; ker_fp1 = bli_sgemmsup_rd_zen_asm_6x16n; ker_fp2 = bli_sgemmsup_rd_zen_asm_1x16n; } else if ( m0 == 8 ) { mr1 = 6; mr2 = 2; ker_fp1 = bli_sgemmsup_rd_zen_asm_6x16n; ker_fp2 = bli_sgemmsup_rd_zen_asm_2x16n; } else // if ( m0 == 9 ) { mr1 = 6; mr2 = 3; ker_fp1 = bli_sgemmsup_rd_zen_asm_6x16n; ker_fp2 = bli_sgemmsup_rd_zen_asm_3x16n; } ker_fp1 ( conja, conjb, mr1, n0, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += mr1*rs_c0; ai += mr1*rs_a0; ker_fp2 ( conja, conjb, mr2, n0, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); return; } if ( 3 <= m_left ) { const dim_t mr_cur = 3; bli_sgemmsup_rd_zen_asm_3x16n ( conja, conjb, mr_cur, n0, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += mr_cur*rs_c0; ai += mr_cur*rs_a0; m_left -= mr_cur; } if ( 2 <= m_left ) { const dim_t mr_cur = 2; bli_sgemmsup_rd_zen_asm_2x16n ( conja, conjb, mr_cur, n0, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += mr_cur*rs_c0; ai += mr_cur*rs_a0; m_left -= mr_cur; } if ( 1 == m_left ) { bli_sgemv_ex ( BLIS_TRANSPOSE, conja, k0, n0, alpha, bj, rs_b0, cs_b0, ai, cs_a0, beta, cij, cs_c0, cntx, NULL ); } return; } // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter32 = k0 / 32; uint64_t k_left32 = k0 % 32; uint64_t k_iter8 = k_left32 / 8; uint64_t k_left1 = k_left32 % 8; uint64_t n_iter = n0 / 4; uint64_t n_left = n0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; if ( n_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() mov(var(a), rdx) // load address of a. mov(var(rs_a), r8) // load rs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) mov(var(cs_b), r11) // load cs_b lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b // r12 = rcx = c // rdx = rax = a // r14 = rbx = b // r9 = m dim index ii // r15 = n dim index jj mov(imm(0), r9) // ii = 0; label(.SLOOP3X4I) // LOOP OVER ii = [ 0 1 ... ] mov(var(b), r14) // load address of b mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) lea(mem( , r9, 1), rsi) // rsi = r9 = 3*ii; imul(rdi, rsi) // rsi *= rs_c lea(mem(r12, rsi, 1), r12) // r12 = c + 3*ii*rs_c; lea(mem( , r9, 1), rsi) // rsi = r9 = 3*ii; imul(r8, rsi) // rsi *= rs_a; lea(mem(rdx, rsi, 1), rdx) // rax = a + 3*ii*rs_a; mov(var(n_iter), r15) // jj = n_iter; label(.SLOOP3X4J) // LOOP OVER jj = [ n_iter ... 1 0 ] vxorps(ymm4, ymm4, ymm4) vxorps(ymm5, ymm5, ymm5) vxorps(ymm6, ymm6, ymm6) vxorps(ymm7, ymm7, ymm7) vxorps(ymm8, ymm8, ymm8) vxorps(ymm9, ymm9, ymm9) vxorps(ymm10, ymm10, ymm10) vxorps(ymm11, ymm11, ymm11) vxorps(ymm12, ymm12, ymm12) vxorps(ymm13, ymm13, ymm13) vxorps(ymm14, ymm14, ymm14) vxorps(ymm15, ymm15, ymm15) lea(mem(r12), rcx) // rcx = c_iijj; lea(mem(rdx), rax) // rax = a_ii; lea(mem(r14), rbx) // rbx = b_jj; mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 3*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 3*8)) // prefetch c + 2*rs_c lea(mem(r11, r11, 2), rdi) // rdi = 3*cs_b lea(mem(rbx, r11, 4), r10) // r10 = rbx + 4*cs_b mov(var(k_iter32), rsi) // i = k_iter32; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKITER8) // if i == 0, jump to code that // contains the k_iter8 loop. label(.SLOOPKITER32) // MAIN LOOP // ---------------------------------- iteration 0 prefetch(0, mem(r10, 0*8)) // prefetch rbx + 4*cs_b prefetch(0, mem(r10, r11, 1, 0*8)) // prefetch rbx + 5*cs_b vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) vmovups(mem(rax, r8, 2), ymm2) add(imm(8*4), rax) // a += 4*cs_b = 4*8; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) // ---------------------------------- iteration 1 prefetch(0, mem(r10, r11, 2, 0*8)) // prefetch rbx + 6*cs_b prefetch(0, mem(r10, r13, 1, 0*8)) // prefetch rbx + 7*cs_b vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) vmovups(mem(rax, r8, 2), ymm2) add(imm(8*4), rax) // a += 4*cs_b = 4*8; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) // ---------------------------------- iteration 2 prefetch(0, mem(r10, 8*8)) // prefetch rbx + 4*cs_b + 8*rs_b prefetch(0, mem(r10, r11, 1, 8*8)) // prefetch rbx + 5*cs_b + 8*rs_b vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) vmovups(mem(rax, r8, 2), ymm2) add(imm(8*4), rax) // a += 4*cs_b = 4*8; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) // ---------------------------------- iteration 3 prefetch(0, mem(r10, r11, 2, 8*8)) // prefetch rbx + 6*cs_b + 8*rs_b prefetch(0, mem(r10, r13, 1, 8*8)) // prefetch rbx + 7*cs_b + 8*rs_b add(imm(16*8), r10) // r10 += 8*rs_b = 8*8; vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) vmovups(mem(rax, r8, 2), ymm2) add(imm(8*4), rax) // a += 4*cs_b = 4*8; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.SLOOPKITER32) // iterate again if i != 0. label(.SCONSIDKITER8) mov(var(k_iter8), rsi) // i = k_iter8; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter8 loop. label(.SLOOPKITER8) // EDGE LOOP (ymm) vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) vmovups(mem(rax, r8, 2), ymm2) add(imm(8*4), rax) // a += 4*cs_b = 4*8; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.SLOOPKITER8) // iterate again if i != 0. label(.SCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.SLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovss(mem(rax ), xmm0) vmovss(mem(rax, r8, 1), xmm1) vmovss(mem(rax, r8, 2), xmm2) add(imm(1*4), rax) // a += 1*cs_b = 1*8; vmovss(mem(rbx ), xmm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovss(mem(rbx, r11, 1), xmm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovss(mem(rbx, r11, 2), xmm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovss(mem(rbx, r13, 1), xmm3) add(imm(1*4), rbx) // b += 1*rs_b = 1*8; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.SLOOPKLEFT1) // iterate again if i != 0. label(.SPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 // ymm5 ymm8 ymm11 ymm14 // ymm6 ymm9 ymm12 ymm15 vhaddps( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddps( xmm0, xmm1, xmm0 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm7) vhaddps( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddps( xmm2, xmm1, xmm2 ) // xmm2[0] = sum(ymm10); xmm2[1] = sum(ymm13) vhaddps(xmm2,xmm0,xmm4) vhaddps( ymm8, ymm5, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddps( xmm0, xmm1, xmm0 ) vhaddps( ymm14, ymm11, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddps( xmm2, xmm1, xmm2 ) vhaddps(xmm2,xmm0,xmm5) vhaddps( ymm9, ymm6, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddps( xmm0, xmm1, xmm0 ) vhaddps( ymm15, ymm12, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddps( xmm2, xmm1, xmm2 ) vhaddps(xmm2,xmm0,xmm6) // ymm4 = sum(ymm4) sum(ymm7) sum(ymm10) sum(ymm13) // ymm5 = sum(ymm5) sum(ymm8) sum(ymm11) sum(ymm14) // ymm6 = sum(ymm6) sum(ymm9) sum(ymm12) sum(ymm15) mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), ymm0) // load alpha and duplicate vbroadcastss(mem(rbx), ymm3) // load beta and duplicate vmulps(xmm0, xmm4, xmm4) // scale by alpha vmulps(xmm0, xmm5, xmm5) vmulps(xmm0, xmm6, xmm6) // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case label(.SROWSTORED) vfmadd231ps(mem(rcx), xmm3, xmm4) vmovups(xmm4, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), xmm3, xmm5) vmovups(xmm5, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), xmm3, xmm6) vmovups(xmm6, mem(rcx)) jmp(.SDONE) // jump to end. label(.SBETAZERO) label(.SROWSTORBZ) vmovups(xmm4, mem(rcx)) add(rdi, rcx) vmovups(xmm5, mem(rcx)) add(rdi, rcx) vmovups(xmm6, mem(rcx)) label(.SDONE) add(imm(4*4), r12) // c_jj = r12 += 4*cs_c lea(mem(r14, r11, 4), r14) // b_jj = r14 += 4*cs_b dec(r15) // jj -= 1; jne(.SLOOP3X4J) // iterate again if jj != 0. add(imm(3), r9) // ii += 3; cmp(imm(3), r9) // compare ii to 3 jle(.SLOOP3X4I) // if ii <= 3, jump to beginning // of ii loop; otherwise, loop ends. label(.SRETURN) end_asm( : // output operands (none) : // input operands [n_iter] "m" (n_iter), [k_iter32] "m" (k_iter32), [k_iter8] "m" (k_iter8), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the m dimension, if they exist. if ( n_left ) { const dim_t mr_cur = 6; const dim_t j_edge = n0 - ( dim_t )n_left; float* restrict cij = c + j_edge*cs_c; float* restrict ai = a; float* restrict bj = b + j_edge*cs_b; if ( 2 <= n_left ) { const dim_t nr_cur = 2; bli_sgemmsup_rd_zen_asm_6x2 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 1 == n_left ) { bli_sgemv_ex ( BLIS_NO_TRANSPOSE, conjb, mr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, beta, cij, rs_c0, cntx, NULL ); } } } void bli_sgemmsup_rd_zen_asm_3x16n ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter32 = k0 / 32; uint64_t k_left32 = k0 % 32; uint64_t k_iter8 = k_left32 / 8; uint64_t k_left1 = k_left32 % 8; uint64_t n_iter = n0 / 4; uint64_t n_left = n0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; if ( n_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() mov(var(a), rdx) // load address of a. mov(var(rs_a), r8) // load rs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) mov(var(b), r14) // load address of b. mov(var(cs_b), r11) // load cs_b lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b mov(var(c), r12) // load address of c // r12 = rcx = c // rdx = rax = a // r14 = rbx = b // r9 = unused // r15 = n dim index jj mov(var(n_iter), r15) // jj = n_iter; label(.SLOOP3X4J) // LOOP OVER jj = [ n_iter ... 1 0 ] // zen2 can execute 4 vxorpd ipc with // a latency of 1 cycle vxorps(ymm4, ymm4, ymm4) vxorps(ymm5, ymm5, ymm5) vxorps(ymm6, ymm6, ymm6) vxorps(ymm7, ymm7, ymm7) vxorps(ymm8, ymm8, ymm8) vxorps(ymm9, ymm9, ymm9) vxorps(ymm10, ymm10, ymm10) vxorps(ymm11, ymm11, ymm11) vxorps(ymm12, ymm12, ymm12) vxorps(ymm13, ymm13, ymm13) vxorps(ymm14, ymm14, ymm14) vxorps(ymm15, ymm15, ymm15) lea(mem(r12), rcx) // rcx = c_iijj; lea(mem(rdx), rax) // rax = a_ii; lea(mem(r14), rbx) // rbx = b_jj; mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 3*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 3*8)) // prefetch c + 2*rs_c lea(mem(r11, r11, 2), rdi) // rdi = 3*cs_b lea(mem(rbx, r11, 4), r10) // r10 = rbx + 4*cs_b mov(var(k_iter32), rsi) // i = k_iter32; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKITER8) // if i == 0, jump to code that // contains the k_iter8 loop. label(.SLOOPKITER32) // MAIN LOOP // ---------------------------------- iteration 0 prefetch(0, mem(r10, 0*8)) // prefetch rbx + 4*cs_b prefetch(0, mem(r10, r11, 1, 0*8)) // prefetch rbx + 5*cs_b vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) vmovups(mem(rax, r8, 2), ymm2) add(imm(8*4), rax) // a += 4*cs_b = 4*8; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) // ---------------------------------- iteration 1 prefetch(0, mem(r10, r11, 2, 0*8)) // prefetch rbx + 6*cs_b prefetch(0, mem(r10, r13, 1, 0*8)) // prefetch rbx + 7*cs_b vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) vmovups(mem(rax, r8, 2), ymm2) add(imm(8*4), rax) // a += 4*cs_b = 4*8; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) // ---------------------------------- iteration 2 prefetch(0, mem(r10, 8*8)) // prefetch rbx + 4*cs_b + 8*rs_b prefetch(0, mem(r10, r11, 1, 8*8)) // prefetch rbx + 5*cs_b + 8*rs_b vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) vmovups(mem(rax, r8, 2), ymm2) add(imm(8*4), rax) // a += 4*cs_b = 4*8; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) // ---------------------------------- iteration 3 prefetch(0, mem(r10, r11, 2, 8*8)) // prefetch rbx + 6*cs_b + 8*rs_b prefetch(0, mem(r10, r13, 1, 8*8)) // prefetch rbx + 7*cs_b + 8*rs_b add(imm(16*8), r10) // r10 += 8*rs_b = 8*8; vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) vmovups(mem(rax, r8, 2), ymm2) add(imm(8*4), rax) // a += 4*cs_b = 4*8; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.SLOOPKITER32) // iterate again if i != 0. label(.SCONSIDKITER8) mov(var(k_iter8), rsi) // i = k_iter8; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter8 loop. label(.SLOOPKITER8) // EDGE LOOP (ymm) vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) vmovups(mem(rax, r8, 2), ymm2) add(imm(8*4), rax) // a += 4*cs_b = 4*8; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.SLOOPKITER8) // iterate again if i != 0. label(.SCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.SLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovss(mem(rax ), xmm0) vmovss(mem(rax, r8, 1), xmm1) vmovss(mem(rax, r8, 2), xmm2) add(imm(1*4), rax) // a += 1*cs_b = 1*8; vmovss(mem(rbx ), xmm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vfmadd231ps(ymm2, ymm3, ymm6) vmovss(mem(rbx, r11, 1), xmm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vfmadd231ps(ymm2, ymm3, ymm9) vmovss(mem(rbx, r11, 2), xmm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vfmadd231ps(ymm2, ymm3, ymm12) vmovss(mem(rbx, r13, 1), xmm3) add(imm(1*4), rbx) // b += 1*rs_b = 1*8; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) vfmadd231ps(ymm2, ymm3, ymm15) dec(rsi) // i -= 1; jne(.SLOOPKLEFT1) // iterate again if i != 0. label(.SPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 // ymm5 ymm8 ymm11 ymm14 // ymm6 ymm9 ymm12 ymm15 vhaddps( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddps( xmm0, xmm1, xmm0 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm7) vhaddps( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddps( xmm2, xmm1, xmm2 ) // xmm2[0] = sum(ymm10); xmm2[1] = sum(ymm13) vhaddps(xmm2,xmm0,xmm4) vhaddps( ymm8, ymm5, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddps( xmm0, xmm1, xmm0 ) vhaddps( ymm14, ymm11, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddps( xmm2, xmm1, xmm2 ) vhaddps(xmm2,xmm0,xmm5) vhaddps( ymm9, ymm6, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddps( xmm0, xmm1, xmm0 ) vhaddps( ymm15, ymm12, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddps( xmm2, xmm1, xmm2 ) vhaddps(xmm2,xmm0,xmm6) // ymm4 = sum(ymm4) sum(ymm7) sum(ymm10) sum(ymm13) // ymm5 = sum(ymm5) sum(ymm8) sum(ymm11) sum(ymm14) // ymm6 = sum(ymm6) sum(ymm9) sum(ymm12) sum(ymm15) mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), ymm0) // load alpha and duplicate vbroadcastss(mem(rbx), ymm3) // load beta and duplicate vmulps(xmm0, xmm4, xmm4) // scale by alpha vmulps(xmm0, xmm5, xmm5) vmulps(xmm0, xmm6, xmm6) // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case label(.SROWSTORED) vfmadd231ps(mem(rcx), xmm3, xmm4) vmovups(xmm4, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), xmm3, xmm5) vmovups(xmm5, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), xmm3, xmm6) vmovups(xmm6, mem(rcx)) jmp(.SDONE) // jump to end. label(.SBETAZERO) label(.SROWSTORBZ) vmovups(xmm4, mem(rcx)) add(rdi, rcx) vmovups(xmm5, mem(rcx)) add(rdi, rcx) vmovups(xmm6, mem(rcx)) label(.SDONE) add(imm(4*4), r12) // c_jj = r12 += 4*cs_c lea(mem(r14, r11, 4), r14) // b_jj = r14 += 4*cs_b dec(r15) // jj -= 1; jne(.SLOOP3X4J) // iterate again if jj != 0. label(.SRETURN) end_asm( : // output operands (none) : // input operands [n_iter] "m" (n_iter), [k_iter32] "m" (k_iter32), [k_iter8] "m" (k_iter8), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the m dimension, if they exist. if ( n_left ) { const dim_t mr_cur = 3; const dim_t j_edge = n0 - ( dim_t )n_left; float* restrict cij = c + j_edge*cs_c; float* restrict ai = a; float* restrict bj = b + j_edge*cs_b; if ( 2 <= n_left ) { const dim_t nr_cur = 2; bli_sgemmsup_rd_zen_asm_3x2 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 1 == n_left ) { bli_sgemv_ex ( BLIS_NO_TRANSPOSE, conjb, mr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, beta, cij, rs_c0, cntx, NULL ); } } } void bli_sgemmsup_rd_zen_asm_2x16n ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter32 = k0 / 32; uint64_t k_left32 = k0 % 32; uint64_t k_iter8 = k_left32 / 8; uint64_t k_left1 = k_left32 % 8; uint64_t n_iter = n0 / 4; uint64_t n_left = n0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; if ( n_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() mov(var(a), rdx) // load address of a. mov(var(rs_a), r8) // load rs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) mov(var(b), r14) // load address of b. mov(var(cs_b), r11) // load cs_b lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b mov(var(c), r12) // load address of c // r12 = rcx = c // rdx = rax = a // r14 = rbx = b // r9 = unused // r15 = n dim index jj mov(var(n_iter), r15) // jj = n_iter; label(.SLOOP3X4J) // LOOP OVER jj = [ n_iter ... 1 0 ] // zen2 can execute 4 vxorpd ipc with // a latency of 1 cycle vxorps(ymm4, ymm4, ymm4) vxorps(ymm5, ymm5, ymm5) vxorps(ymm7, ymm7, ymm7) vxorps(ymm8, ymm8, ymm8) vxorps(ymm10, ymm10, ymm10) vxorps(ymm11, ymm11, ymm11) vxorps(ymm13, ymm13, ymm13) vxorps(ymm14, ymm14, ymm14) lea(mem(r12), rcx) // rcx = c_iijj; lea(mem(rdx), rax) // rax = a_ii; lea(mem(r14), rbx) // rbx = b_jj; mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 3*8)) // prefetch c + 1*rs_c lea(mem(r11, r11, 2), rdi) // rdi = 3*cs_b lea(mem(rbx, r11, 4), r10) // r10 = rbx + 4*cs_b mov(var(k_iter32), rsi) // i = k_iter32; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKITER8) // if i == 0, jump to code that // contains the k_iter8 loop. label(.SLOOPKITER32) // MAIN LOOP // ---------------------------------- iteration 0 prefetch(0, mem(r10, 0*8)) // prefetch rbx + 4*cs_b prefetch(0, mem(r10, r11, 1, 0*8)) // prefetch rbx + 5*cs_b vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) add(imm(8*4), rax) // a += 4*cs_b = 4*8; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) // ---------------------------------- iteration 1 prefetch(0, mem(r10, r11, 2, 0*8)) // prefetch rbx + 6*cs_b prefetch(0, mem(r10, r13, 1, 0*8)) // prefetch rbx + 7*cs_b vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) add(imm(8*4), rax) // a += 4*cs_b = 4*8; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) // ---------------------------------- iteration 2 prefetch(0, mem(r10, 8*8)) // prefetch rbx + 4*cs_b + 8*rs_b prefetch(0, mem(r10, r11, 1, 8*8)) // prefetch rbx + 5*cs_b + 8*rs_b vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) add(imm(8*4), rax) // a += 4*cs_b = 4*8; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) // ---------------------------------- iteration 3 prefetch(0, mem(r10, r11, 2, 8*8)) // prefetch rbx + 6*cs_b + 8*rs_b prefetch(0, mem(r10, r13, 1, 8*8)) // prefetch rbx + 7*cs_b + 8*rs_b add(imm(16*8), r10) // r10 += 8*rs_b = 8*8; vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) add(imm(8*4), rax) // a += 4*cs_b = 4*8; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) dec(rsi) // i -= 1; jne(.SLOOPKITER32) // iterate again if i != 0. label(.SCONSIDKITER8) mov(var(k_iter8), rsi) // i = k_iter8; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter8 loop. label(.SLOOPKITER8) // EDGE LOOP (ymm) vmovups(mem(rax ), ymm0) vmovups(mem(rax, r8, 1), ymm1) add(imm(8*4), rax) // a += 4*cs_b = 4*8; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) dec(rsi) // i -= 1; jne(.SLOOPKITER8) // iterate again if i != 0. label(.SCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.SLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovss(mem(rax ), xmm0) vmovss(mem(rax, r8, 1), xmm1) add(imm(1*4), rax) // a += 1*cs_b = 1*8; vmovss(mem(rbx ), xmm3) vfmadd231ps(ymm0, ymm3, ymm4) vfmadd231ps(ymm1, ymm3, ymm5) vmovss(mem(rbx, r11, 1), xmm3) vfmadd231ps(ymm0, ymm3, ymm7) vfmadd231ps(ymm1, ymm3, ymm8) vmovss(mem(rbx, r11, 2), xmm3) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vmovss(mem(rbx, r13, 1), xmm3) add(imm(1*4), rbx) // b += 1*rs_b = 1*8; vfmadd231ps(ymm0, ymm3, ymm13) vfmadd231ps(ymm1, ymm3, ymm14) dec(rsi) // i -= 1; jne(.SLOOPKLEFT1) // iterate again if i != 0. label(.SPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 // ymm5 ymm8 ymm11 ymm14 // ymm6 ymm9 ymm12 ymm15 vhaddps( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddps( xmm0, xmm1, xmm0 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm7) vhaddps( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddps( xmm2, xmm1, xmm2 ) // xmm2[0] = sum(ymm10); xmm2[1] = sum(ymm13) vhaddps(xmm2,xmm0,xmm4) vhaddps( ymm8, ymm5, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddps( xmm0, xmm1, xmm0 ) vhaddps( ymm14, ymm11, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddps( xmm2, xmm1, xmm2 ) vhaddps(xmm2,xmm0,xmm5) // ymm4 = sum(ymm4) sum(ymm7) sum(ymm10) sum(ymm13) // ymm5 = sum(ymm5) sum(ymm8) sum(ymm11) sum(ymm14) mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), ymm0) // load alpha and duplicate vbroadcastss(mem(rbx), ymm3) // load beta and duplicate vmulps(xmm0, xmm4, xmm4) // scale by alpha vmulps(xmm0, xmm5, xmm5) vmulps(xmm0, xmm6, xmm6) // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case label(.SROWSTORED) vfmadd231ps(mem(rcx), xmm3, xmm4) vmovups(xmm4, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), xmm3, xmm5) vmovups(xmm5, mem(rcx)) jmp(.SDONE) // jump to end. label(.SBETAZERO) label(.SROWSTORBZ) vmovups(xmm4, mem(rcx)) add(rdi, rcx) vmovups(xmm5, mem(rcx)) label(.SDONE) add(imm(4*4), r12) // c_jj = r12 += 4*cs_c lea(mem(r14, r11, 4), r14) // b_jj = r14 += 4*cs_b dec(r15) // jj -= 1; jne(.SLOOP3X4J) // iterate again if jj != 0. label(.SRETURN) end_asm( : // output operands (none) : // input operands [n_iter] "m" (n_iter), [k_iter32] "m" (k_iter32), [k_iter8] "m" (k_iter8), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the m dimension, if they exist. if ( n_left ) { const dim_t mr_cur = 2; const dim_t j_edge = n0 - ( dim_t )n_left; float* restrict cij = c + j_edge*cs_c; float* restrict ai = a; float* restrict bj = b + j_edge*cs_b; if ( 2 <= n_left ) { const dim_t nr_cur = 2; bli_sgemmsup_rd_zen_asm_2x2 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 1 == n_left ) { bli_sgemv_ex ( BLIS_NO_TRANSPOSE, conjb, mr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, beta, cij, rs_c0, cntx, NULL ); } } } void bli_sgemmsup_rd_zen_asm_1x16n ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter32 = k0 / 32; uint64_t k_left32 = k0 % 32; uint64_t k_iter8 = k_left32 / 8; uint64_t k_left1 = k_left32 % 8; uint64_t n_iter = n0 / 4; uint64_t n_left = n0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; if ( n_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() mov(var(a), rdx) // load address of a. mov(var(b), r14) // load address of b. mov(var(cs_b), r11) // load cs_b lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) lea(mem(r11, r11, 2), r13) // r13 = 3*cs_b mov(var(c), r12) // load address of c // r12 = rcx = c // rdx = rax = a // r14 = rbx = b // r9 = unused // r15 = n dim index jj mov(var(n_iter), r15) // jj = n_iter; label(.SLOOP3X4J) // LOOP OVER jj = [ n_iter ... 1 0 ] // zen2 can execute 4 vxorpd ipc with // a latency of 1 cycle vxorps(ymm4, ymm4, ymm4) vxorps(ymm7, ymm7, ymm7) vxorps(ymm10, ymm10, ymm10) vxorps(ymm13, ymm13, ymm13) lea(mem(r12), rcx) // rcx = c_iijj; lea(mem(rdx), rax) // rax = a_ii; lea(mem(r14), rbx) // rbx = b_jj; mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 3*8)) // prefetch c + 1*rs_c lea(mem(r11, r11, 2), rdi) // rdi = 3*cs_b lea(mem(rbx, r11, 4), r10) // r10 = rbx + 4*cs_b mov(var(k_iter32), rsi) // i = k_iter32; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKITER8) // if i == 0, jump to code that // contains the k_iter8 loop. label(.SLOOPKITER32) // MAIN LOOP // ---------------------------------- iteration 0 prefetch(0, mem(r10, 0*8)) // prefetch rbx + 4*cs_b prefetch(0, mem(r10, r11, 1, 0*8)) // prefetch rbx + 5*cs_b vmovups(mem(rax ), ymm0) add(imm(8*4), rax) // a += 4*cs_b = 4*8; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vfmadd231ps(ymm0, ymm3, ymm13) // ---------------------------------- iteration 1 prefetch(0, mem(r10, r11, 2, 0*8)) // prefetch rbx + 6*cs_b prefetch(0, mem(r10, r13, 1, 0*8)) // prefetch rbx + 7*cs_b vmovups(mem(rax ), ymm0) add(imm(8*4), rax) // a += 4*cs_b = 4*8; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vfmadd231ps(ymm0, ymm3, ymm13) // ---------------------------------- iteration 2 prefetch(0, mem(r10, 8*8)) // prefetch rbx + 4*cs_b + 8*rs_b prefetch(0, mem(r10, r11, 1, 8*8)) // prefetch rbx + 5*cs_b + 8*rs_b vmovups(mem(rax ), ymm0) add(imm(8*4), rax) // a += 4*cs_b = 4*8; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vfmadd231ps(ymm0, ymm3, ymm13) // ---------------------------------- iteration 3 prefetch(0, mem(r10, r11, 2, 8*8)) // prefetch rbx + 6*cs_b + 8*rs_b prefetch(0, mem(r10, r13, 1, 8*8)) // prefetch rbx + 7*cs_b + 8*rs_b add(imm(16*8), r10) // r10 += 8*rs_b = 8*8; vmovups(mem(rax ), ymm0) add(imm(8*4), rax) // a += 4*cs_b = 4*8; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vfmadd231ps(ymm0, ymm3, ymm13) dec(rsi) // i -= 1; jne(.SLOOPKITER32) // iterate again if i != 0. label(.SCONSIDKITER8) mov(var(k_iter8), rsi) // i = k_iter8; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT1) // if i == 0, jump to code that // considers k_left1 loop. // else, we prepare to enter k_iter8 loop. label(.SLOOPKITER8) // EDGE LOOP (ymm) vmovups(mem(rax ), ymm0) add(imm(8*4), rax) // a += 4*cs_b = 4*8; vmovups(mem(rbx ), ymm3) vfmadd231ps(ymm0, ymm3, ymm4) vmovups(mem(rbx, r11, 1), ymm3) vfmadd231ps(ymm0, ymm3, ymm7) vmovups(mem(rbx, r11, 2), ymm3) vfmadd231ps(ymm0, ymm3, ymm10) vmovups(mem(rbx, r13, 1), ymm3) add(imm(8*4), rbx) // b += 4*rs_b = 4*8; vfmadd231ps(ymm0, ymm3, ymm13) dec(rsi) // i -= 1; jne(.SLOOPKITER8) // iterate again if i != 0. label(.SCONSIDKLEFT1) mov(var(k_left1), rsi) // i = k_left1; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left1 loop. label(.SLOOPKLEFT1) // EDGE LOOP (scalar) // NOTE: We must use ymm registers here bc // using the xmm registers would zero out the // high bits of the destination registers, // which would destory intermediate results. vmovss(mem(rax ), xmm0) add(imm(1*4), rax) // a += 1*cs_b = 1*8; vmovss(mem(rbx ), xmm3) vfmadd231ps(ymm0, ymm3, ymm4) vmovss(mem(rbx, r11, 1), xmm3) vfmadd231ps(ymm0, ymm3, ymm7) vmovss(mem(rbx, r11, 2), xmm3) vfmadd231ps(ymm0, ymm3, ymm10) vmovss(mem(rbx, r13, 1), xmm3) add(imm(1*4), rbx) // b += 1*rs_b = 1*8; vfmadd231ps(ymm0, ymm3, ymm13) dec(rsi) // i -= 1; jne(.SLOOPKLEFT1) // iterate again if i != 0. label(.SPOSTACCUM) // ymm4 ymm7 ymm10 ymm13 // ymm5 ymm8 ymm11 ymm14 // ymm6 ymm9 ymm12 ymm15 vhaddps( ymm7, ymm4, ymm0 ) vextractf128(imm(1), ymm0, xmm1 ) vaddps( xmm0, xmm1, xmm0 ) // xmm0[0] = sum(ymm4); xmm0[1] = sum(ymm7) vhaddps( ymm13, ymm10, ymm2 ) vextractf128(imm(1), ymm2, xmm1 ) vaddps( xmm2, xmm1, xmm2 ) // xmm2[0] = sum(ymm10); xmm2[1] = sum(ymm13) vhaddps(xmm2,xmm0,xmm4) // ymm4 = sum(ymm4) sum(ymm7) sum(ymm10) sum(ymm13) mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), ymm0) // load alpha and duplicate vbroadcastss(mem(rbx), ymm3) // load beta and duplicate vmulps(xmm0, xmm4, xmm4) // scale by alpha // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomisd(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case label(.SROWSTORED) vfmadd231ps(mem(rcx), xmm3, xmm4) vmovups(xmm4, mem(rcx)) jmp(.SDONE) // jump to end. label(.SBETAZERO) label(.SROWSTORBZ) vmovups(xmm4, mem(rcx)) label(.SDONE) add(imm(4*4), r12) // c_jj = r12 += 4*cs_c lea(mem(r14, r11, 4), r14) // b_jj = r14 += 4*cs_b dec(r15) // jj -= 1; jne(.SLOOP3X4J) // iterate again if jj != 0. label(.SRETURN) end_asm( : // output operands (none) : // input operands [n_iter] "m" (n_iter), [k_iter32] "m" (k_iter32), [k_iter8] "m" (k_iter8), [k_left1] "m" (k_left1), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the m dimension, if they exist. if ( n_left ) { const dim_t mr_cur = 1; const dim_t j_edge = n0 - ( dim_t )n_left; float* restrict cij = c + j_edge*cs_c; float* restrict ai = a; float* restrict bj = b + j_edge*cs_b; if ( 2 <= n_left ) { const dim_t nr_cur = 2; bli_sgemmsup_rd_zen_asm_1x2 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 1 == n_left ) { bli_sdotxv_ex ( conja, conjb, k0, alpha, ai, cs_a0, bj, rs_b0, beta, cij, cntx, NULL ); } } } blis-0.9.0/kernels/zen/3/sup/other/bli_gemmsup_rv_zen_asm_s6x16.c000066400000000000000000011275071422157504600246660ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define BLIS_ASM_SYNTAX_ATT #include "bli_x86_asm_macros.h" /* rrr: -------- ------ -------- -------- ------ -------- -------- += ------ ... -------- -------- ------ -------- -------- ------ : -------- ------ : rcr: -------- | | | | -------- -------- | | | | -------- -------- += | | | | ... -------- -------- | | | | -------- -------- | | | | : -------- | | | | : Assumptions: - B is row-stored; - A is row- or column-stored; - m0 and n0 are at most MR and NR, respectively. Therefore, this (r)ow-preferential kernel is well-suited for contiguous (v)ector loads on B and single-element broadcasts from A. NOTE: These kernels explicitly support column-oriented IO, implemented via an in-register transpose. And thus they also support the crr and ccr cases, though only crr is ever utilized (because ccr is handled by transposing the operation and executing rcr, which does not incur the cost of the in-register transpose). crr: | | | | | | | | ------ -------- | | | | | | | | ------ -------- | | | | | | | | += ------ ... -------- | | | | | | | | ------ -------- | | | | | | | | ------ : | | | | | | | | ------ : */ // Prototype reference microkernels. GEMMSUP_KER_PROT( float, s, gemmsup_r_zen_ref ) void bli_sgemmsup_rv_zen_asm_5x16 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vxorps(ymm4, ymm4, ymm4) vxorps(ymm5, ymm5, ymm5) vxorps(ymm6, ymm6, ymm6) vxorps(ymm7, ymm7, ymm7) vxorps(ymm8, ymm8, ymm8) vxorps(ymm9, ymm9, ymm9) vxorps(ymm10, ymm10, ymm10) vxorps(ymm11, ymm11, ymm11) vxorps(ymm12, ymm12, ymm12) vxorps(ymm13, ymm13, ymm13) vxorps(ymm14, ymm14, ymm14) vxorps(ymm15, ymm15, ymm15) mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored prefetching on c lea(mem(rcx, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 7*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 7*8)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 7*8)) // prefetch c + 3*rs_c prefetch(0, mem(rdx, rdi, 1, 7*8)) // prefetch c + 4*rs_c jmp(.SPOSTPFETCH) // jump to end of prefetching c label(.SCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) lea(mem(rcx, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; prefetch(0, mem(rcx, 4*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 4*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 4*8)) // prefetch c + 2*cs_c prefetch(0, mem(rdx, 4*8)) // prefetch c + 3*cs_c prefetch(0, mem(rdx, rsi, 1, 4*8)) // prefetch c + 4*cs_c prefetch(0, mem(rdx, rsi, 2, 4*8)) // prefetch c + 5*cs_c lea(mem(rdx, rsi, 2), rdx) // rdx = c + 5*cs_c; prefetch(0, mem(rdx, rsi, 1, 4*8)) // prefetch c + 6*cs_c prefetch(0, mem(rdx, rsi, 2, 4*8)) // prefetch c + 7*cs_c label(.SPOSTPFETCH) // done prefetching c mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) // ---------------------------------- iteration 1 vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) // ---------------------------------- iteration 2 vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) // ---------------------------------- iteration 3 vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), ymm0) // load alpha and duplicate vbroadcastss(mem(rbx), ymm3) // load beta and duplicate vmulps(ymm0, ymm4, ymm4) // scale by alpha vmulps(ymm0, ymm5, ymm5) vmulps(ymm0, ymm6, ymm6) vmulps(ymm0, ymm7, ymm7) vmulps(ymm0, ymm8, ymm8) vmulps(ymm0, ymm9, ymm9) vmulps(ymm0, ymm10, ymm10) vmulps(ymm0, ymm11, ymm11) vmulps(ymm0, ymm12, ymm12) vmulps(ymm0, ymm13, ymm13) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vfmadd231ps(mem(rcx), ymm3, ymm4) vmovups(ymm4, mem(rcx)) vfmadd231ps(mem(rcx, rsi, 8), ymm3, ymm5) vmovups(ymm5, mem(rcx, rsi, 8)) add(rdi, rcx) vfmadd231ps(mem(rcx), ymm3, ymm6) vmovups(ymm6, mem(rcx)) vfmadd231ps(mem(rcx, rsi, 8), ymm3, ymm7) vmovups(ymm7, mem(rcx, rsi, 8)) add(rdi, rcx) vfmadd231ps(mem(rcx), ymm3, ymm8) vmovups(ymm8, mem(rcx)) vfmadd231ps(mem(rcx, rsi, 8), ymm3, ymm9) vmovups(ymm9, mem(rcx, rsi, 8)) add(rdi, rcx) vfmadd231ps(mem(rcx), ymm3, ymm10) vmovups(ymm10, mem(rcx)) vfmadd231ps(mem(rcx, rsi, 8), ymm3, ymm11) vmovups(ymm11, mem(rcx, rsi, 8)) add(rdi, rcx) vfmadd231ps(mem(rcx), ymm3, ymm12) vmovups(ymm12, mem(rcx)) vfmadd231ps(mem(rcx, rsi, 8), ymm3, ymm13) vmovups(ymm13, mem(rcx, rsi, 8)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORED) vunpcklps(ymm6, ymm4, ymm0) //a0b0a1b1 a4b4a5b5 vunpcklps(ymm10, ymm8, ymm1) //c0d0c1d1 c4d4c5d5 vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx), xmm3, xmm0) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm0, mem(rcx)) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx), xmm3, xmm1) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm1, mem(rcx)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma05..gamma35 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c vunpckhps(ymm6, ymm4, ymm0) vunpckhps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx), xmm3, xmm0) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm0, mem(rcx)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma06..gamma36 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx), xmm3, xmm1) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm1, mem(rcx)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma07..gamma37 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c lea(mem(rcx, rsi, 4), rcx) // rcx += 4*cs_c /********************************************/ vextractf128(imm(0x0), ymm12, xmm0)//e0-e3 vmovss(mem(rdx),xmm4) vmovss(mem(rdx, rsi, 1),xmm6) vmovss(mem(rdx, rsi, 2),xmm8) vmovss(mem(rdx, rax, 1),xmm10) vshufps(imm(0x01), xmm0, xmm0,xmm1) vshufps(imm(0x02), xmm0, xmm0,xmm2) vshufps(imm(0x03), xmm0, xmm0,xmm14) vfmadd231ps(xmm4, xmm3, xmm0)//e0 vfmadd231ps(xmm6, xmm3, xmm1)//e1 vfmadd231ps(xmm8, xmm3, xmm2)//e2 vfmadd231ps(xmm10, xmm3, xmm14)//e3 vmovss(xmm0, mem(rdx)) vmovss(xmm1, mem(rdx, rsi, 1)) vmovss(xmm2, mem(rdx, rsi, 2)) vmovss(xmm14, mem(rdx, rax, 1)) lea(mem(rdx, rsi, 4), rdx) // rdx += 4*cs_c vextractf128(imm(0x1), ymm12, xmm0)//e4-e7 vmovss(mem(rdx),xmm4) vmovss(mem(rdx, rsi, 1),xmm6) vmovss(mem(rdx, rsi, 2),xmm8) vmovss(mem(rdx, rax, 1),xmm10) vshufps(imm(0x01), xmm0, xmm0,xmm1) vshufps(imm(0x02), xmm0, xmm0,xmm2) vshufps(imm(0x03), xmm0, xmm0,xmm14) vfmadd231ps(xmm4, xmm3, xmm0)//e0 vfmadd231ps(xmm6, xmm3, xmm1)//e1 vfmadd231ps(xmm8, xmm3, xmm2)//e2 vfmadd231ps(xmm10, xmm3, xmm14)//e3 vmovss(xmm0, mem(rdx)) vmovss(xmm1, mem(rdx, rsi, 1)) vmovss(xmm2, mem(rdx, rsi, 2)) vmovss(xmm14, mem(rdx, rax, 1)) lea(mem(rdx, rsi, 4), rdx) // rdx += 4*cs_c /*********************************************/ vunpcklps(ymm7, ymm5, ymm0) vunpcklps(ymm11, ymm9, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx), xmm3, xmm0) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm0, mem(rcx)) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx), xmm3, xmm1) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm1, mem(rcx)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma05..gamma35 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c vunpckhps(ymm7, ymm5, ymm0) vunpckhps(ymm11, ymm9, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx), xmm3, xmm0) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm0, mem(rcx)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma06..gamma36 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx), xmm3, xmm1) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm1, mem(rcx)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma07..gamma37 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vextractf128(imm(0x0), ymm13, xmm0)//e0-e3 vmovss(mem(rdx),xmm4) vmovss(mem(rdx, rsi, 1),xmm6) vmovss(mem(rdx, rsi, 2),xmm8) vmovss(mem(rdx, rax, 1),xmm10) vshufps(imm(0x01), xmm0,xmm0, xmm1) vshufps(imm(0x02), xmm0,xmm0, xmm2) vshufps(imm(0x03), xmm0,xmm0, xmm14) vfmadd231ps(xmm4, xmm3, xmm0)//e0 vfmadd231ps(xmm6, xmm3, xmm1)//e1 vfmadd231ps(xmm8, xmm3, xmm2)//e2 vfmadd231ps(xmm10, xmm3, xmm14)//e3 vmovss(xmm0, mem(rdx)) vmovss(xmm1, mem(rdx, rsi, 1)) vmovss(xmm2, mem(rdx, rsi, 2)) vmovss(xmm14, mem(rdx, rax, 1)) lea(mem(rdx, rsi, 4), rdx) // rdx += 4*cs_c vextractf128(imm(0x1), ymm13, xmm0)//e4-e7 vmovss(mem(rdx),xmm4) vmovss(mem(rdx, rsi, 1),xmm6) vmovss(mem(rdx, rsi, 2),xmm8) vmovss(mem(rdx, rax, 1),xmm10) vshufps(imm(0x01), xmm0,xmm0, xmm1) vshufps(imm(0x02), xmm0,xmm0, xmm2) vshufps(imm(0x03), xmm0,xmm0, xmm14) vfmadd231ps(xmm4, xmm3, xmm0)//e0 vfmadd231ps(xmm6, xmm3, xmm1)//e1 vfmadd231ps(xmm8, xmm3, xmm2)//e2 vfmadd231ps(xmm10, xmm3, xmm14)//e3 vmovss(xmm0, mem(rdx)) vmovss(xmm1, mem(rdx, rsi, 1)) vmovss(xmm2, mem(rdx, rsi, 2)) vmovss(xmm14, mem(rdx, rax, 1)) jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovups(ymm4, mem(rcx)) vmovups(ymm5, mem(rcx, rsi, 8)) add(rdi, rcx) vmovups(ymm6, mem(rcx)) vmovups(ymm7, mem(rcx, rsi, 8)) add(rdi, rcx) vmovups(ymm8, mem(rcx)) vmovups(ymm9, mem(rcx, rsi, 8)) add(rdi, rcx) vmovups(ymm10, mem(rcx)) vmovups(ymm11, mem(rcx, rsi, 8)) add(rdi, rcx) vmovups(ymm12, mem(rcx)) vmovups(ymm13, mem(rcx, rsi, 8)) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) vunpcklps(ymm6, ymm4, ymm0) //a0b0a1b1 a4b4a5b5 vunpcklps(ymm10, ymm8, ymm1) //c0d0c1d1 c4d4c5d5 vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx)) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma05..gamma35 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c vunpckhps(ymm6, ymm4, ymm0) vunpckhps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma06..gamma36 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma07..gamma37 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c lea(mem(rcx, rsi, 4), rcx) // rcx += 4*cs_c /********************************************/ vextractf128(imm(0x0), ymm12, xmm0)//e0-e3 vshufps(imm(0x01), xmm0, xmm0,xmm1) vshufps(imm(0x02), xmm0, xmm0,xmm2) vshufps(imm(0x03), xmm0, xmm0,xmm14) vmovss(xmm0, mem(rdx)) vmovss(xmm1, mem(rdx, rsi, 1)) vmovss(xmm2, mem(rdx, rsi, 2)) vmovss(xmm14, mem(rdx, rax, 1)) lea(mem(rdx, rsi, 4), rdx) // rdx += 4*cs_c vextractf128(imm(0x1), ymm12, xmm0)//e4-e7 vshufps(imm(0x01), xmm0, xmm0,xmm1) vshufps(imm(0x02), xmm0, xmm0,xmm2) vshufps(imm(0x03), xmm0, xmm0,xmm14) vmovss(xmm0, mem(rdx)) vmovss(xmm1, mem(rdx, rsi, 1)) vmovss(xmm2, mem(rdx, rsi, 2)) vmovss(xmm14, mem(rdx, rax, 1)) lea(mem(rdx, rsi, 4), rdx) // rdx += 4*cs_c /*********************************************/ vunpcklps(ymm7, ymm5, ymm0) vunpcklps(ymm11, ymm9, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx)) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma05..gamma35 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c vunpckhps(ymm7, ymm5, ymm0) vunpckhps(ymm11, ymm9, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma06..gamma36 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma07..gamma37 ) vextractf128(imm(0x0), ymm13, xmm0)//e0-e3 vshufps(imm(0x01), xmm0,xmm0, xmm1) vshufps(imm(0x02), xmm0,xmm0, xmm2) vshufps(imm(0x03), xmm0,xmm0, xmm14) vmovss(xmm0, mem(rdx)) vmovss(xmm1, mem(rdx, rsi, 1)) vmovss(xmm2, mem(rdx, rsi, 2)) vmovss(xmm14, mem(rdx, rax, 1)) lea(mem(rdx, rsi, 4), rdx) // rdx += 4*cs_c vextractf128(imm(0x1), ymm13, xmm0)//e4-e7 vshufps(imm(0x01), xmm0,xmm0, xmm1) vshufps(imm(0x02), xmm0,xmm0, xmm2) vshufps(imm(0x03), xmm0,xmm0, xmm14) vmovss(xmm0, mem(rdx)) vmovss(xmm1, mem(rdx, rsi, 1)) vmovss(xmm2, mem(rdx, rsi, 2)) vmovss(xmm14, mem(rdx, rax, 1)) label(.SDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_sgemmsup_rv_zen_asm_4x16 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vxorps(ymm4, ymm4, ymm4) vxorps(ymm5, ymm5, ymm5) vxorps(ymm6, ymm6, ymm6) vxorps(ymm7, ymm7, ymm7) vxorps(ymm8, ymm8, ymm8) vxorps(ymm9, ymm9, ymm9) vxorps(ymm10, ymm10, ymm10) vxorps(ymm11, ymm11, ymm11) vxorps(ymm12, ymm12, ymm12) vxorps(ymm13, ymm13, ymm13) vxorps(ymm14, ymm14, ymm14) vxorps(ymm15, ymm15, ymm15) mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored prefetching on c lea(mem(rcx, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 7*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 7*8)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 7*8)) // prefetch c + 3*rs_c jmp(.SPOSTPFETCH) // jump to end of prefetching c label(.SCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) lea(mem(rcx, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 3*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 3*8)) // prefetch c + 2*cs_c prefetch(0, mem(rdx, 3*8)) // prefetch c + 3*cs_c prefetch(0, mem(rdx, rsi, 1, 3*8)) // prefetch c + 4*cs_c prefetch(0, mem(rdx, rsi, 2, 3*8)) // prefetch c + 5*cs_c lea(mem(rdx, rsi, 2), rdx) // rdx = c + 5*cs_c; prefetch(0, mem(rdx, rsi, 1, 3*8)) // prefetch c + 6*cs_c prefetch(0, mem(rdx, rsi, 2, 3*8)) // prefetch c + 7*cs_c label(.SPOSTPFETCH) // done prefetching c mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) // ---------------------------------- iteration 1 vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) // ---------------------------------- iteration 2 vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) // ---------------------------------- iteration 3 vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), ymm0) // load alpha and duplicate vbroadcastss(mem(rbx), ymm3) // load beta and duplicate vmulps(ymm0, ymm4, ymm4) // scale by alpha vmulps(ymm0, ymm5, ymm5) vmulps(ymm0, ymm6, ymm6) vmulps(ymm0, ymm7, ymm7) vmulps(ymm0, ymm8, ymm8) vmulps(ymm0, ymm9, ymm9) vmulps(ymm0, ymm10, ymm10) vmulps(ymm0, ymm11, ymm11) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vfmadd231ps(mem(rcx), ymm3, ymm4) vmovups(ymm4, mem(rcx)) vfmadd231ps(mem(rcx, rsi, 8), ymm3, ymm5) vmovups(ymm5, mem(rcx, rsi, 8)) add(rdi, rcx) vfmadd231ps(mem(rcx), ymm3, ymm6) vmovups(ymm6, mem(rcx)) vfmadd231ps(mem(rcx, rsi, 8), ymm3, ymm7) vmovups(ymm7, mem(rcx, rsi, 8)) add(rdi, rcx) vfmadd231ps(mem(rcx), ymm3, ymm8) vmovups(ymm8, mem(rcx)) vfmadd231ps(mem(rcx, rsi, 8), ymm3, ymm9) vmovups(ymm9, mem(rcx, rsi, 8)) add(rdi, rcx) vfmadd231ps(mem(rcx), ymm3, ymm10) vmovups(ymm10, mem(rcx)) vfmadd231ps(mem(rcx, rsi, 8), ymm3, ymm11) vmovups(ymm11, mem(rcx, rsi, 8)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORED) vunpcklps(ymm6, ymm4, ymm0) //a0b0a1b1 a4b4a5b5 vunpcklps(ymm10, ymm8, ymm1) //c0d0c1d1 c4d4c5d5 vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx), xmm3, xmm0) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm0, mem(rcx)) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx), xmm3, xmm1) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm1, mem(rcx)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma05..gamma35 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c vunpckhps(ymm6, ymm4, ymm0) vunpckhps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx), xmm3, xmm0) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm0, mem(rcx)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma06..gamma36 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx), xmm3, xmm1) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm1, mem(rcx)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma07..gamma37 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c lea(mem(rcx, rsi, 4), rcx) // rcx += 4*cs_c vunpcklps(ymm7, ymm5, ymm0) vunpcklps(ymm11, ymm9, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx), xmm3, xmm0) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm0, mem(rcx)) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx), xmm3, xmm1) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm1, mem(rcx)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma05..gamma35 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c vunpckhps(ymm7, ymm5, ymm0) vunpckhps(ymm11, ymm9, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx), xmm3, xmm0) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm0, mem(rcx)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma06..gamma36 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx), xmm3, xmm1) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm1, mem(rcx)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma07..gamma37 ) jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovups(ymm4, mem(rcx)) vmovups(ymm5, mem(rcx, rsi, 8)) add(rdi, rcx) vmovups(ymm6, mem(rcx)) vmovups(ymm7, mem(rcx, rsi, 8)) add(rdi, rcx) vmovups(ymm8, mem(rcx)) vmovups(ymm9, mem(rcx, rsi, 8)) add(rdi, rcx) vmovups(ymm10, mem(rcx)) vmovups(ymm11, mem(rcx, rsi, 8)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) vunpcklps(ymm6, ymm4, ymm0) //a0b0a1b1 a4b4a5b5 vunpcklps(ymm10, ymm8, ymm1) //c0d0c1d1 c4d4c5d5 vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx)) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma05..gamma35 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c vunpckhps(ymm6, ymm4, ymm0) vunpckhps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma06..gamma36 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma07..gamma37 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c lea(mem(rcx, rsi, 4), rcx) // rcx += 4*cs_c vunpcklps(ymm7, ymm5, ymm0) vunpcklps(ymm11, ymm9, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx)) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma05..gamma35 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c vunpckhps(ymm7, ymm5, ymm0) vunpckhps(ymm11, ymm9, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma06..gamma36 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma07..gamma37 ) label(.SDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_sgemmsup_rv_zen_asm_3x16 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vxorps(ymm4, ymm4, ymm4) vxorps(ymm5, ymm5, ymm5) vxorps(ymm6, ymm6, ymm6) vxorps(ymm7, ymm7, ymm7) vxorps(ymm8, ymm8, ymm8) vxorps(ymm9, ymm9, ymm9) vxorps(ymm10, ymm10, ymm10) vxorps(ymm11, ymm11, ymm11) vxorps(ymm12, ymm12, ymm12) vxorps(ymm13, ymm13, ymm13) vxorps(ymm14, ymm14, ymm14) vxorps(ymm15, ymm15, ymm15) mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored prefetching on c //lea(mem(rcx, rdi, 2), rdx) // //lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 7*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 7*8)) // prefetch c + 2*rs_c jmp(.SPOSTPFETCH) // jump to end of prefetching c label(.SCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) lea(mem(rcx, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; prefetch(0, mem(rcx, 2*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 2*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 2*8)) // prefetch c + 2*cs_c prefetch(0, mem(rdx, 2*8)) // prefetch c + 3*cs_c prefetch(0, mem(rdx, rsi, 1, 2*8)) // prefetch c + 4*cs_c prefetch(0, mem(rdx, rsi, 2, 2*8)) // prefetch c + 5*cs_c lea(mem(rdx, rsi, 2), rdx) // rdx = c + 5*cs_c; prefetch(0, mem(rdx, rsi, 1, 2*8)) // prefetch c + 6*cs_c prefetch(0, mem(rdx, rsi, 2, 2*8)) // prefetch c + 7*cs_c label(.SPOSTPFETCH) // done prefetching c mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) // ---------------------------------- iteration 1 vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) // ---------------------------------- iteration 2 vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) // ---------------------------------- iteration 3 vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), ymm0) // load alpha and duplicate vbroadcastss(mem(rbx), ymm3) // load beta and duplicate vmulps(ymm0, ymm4, ymm4) // scale by alpha vmulps(ymm0, ymm5, ymm5) vmulps(ymm0, ymm6, ymm6) vmulps(ymm0, ymm7, ymm7) vmulps(ymm0, ymm8, ymm8) vmulps(ymm0, ymm9, ymm9) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; lea(mem(rcx, rdi, 2), rdx) // load address of c + 2*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vfmadd231ps(mem(rcx), ymm3, ymm4) vmovups(ymm4, mem(rcx)) vfmadd231ps(mem(rcx, rsi, 8), ymm3, ymm5) vmovups(ymm5, mem(rcx, rsi, 8)) add(rdi, rcx) vfmadd231ps(mem(rcx), ymm3, ymm6) vmovups(ymm6, mem(rcx)) vfmadd231ps(mem(rcx, rsi, 8), ymm3, ymm7) vmovups(ymm7, mem(rcx, rsi, 8)) add(rdi, rcx) vfmadd231ps(mem(rcx), ymm3, ymm8) vmovups(ymm8, mem(rcx)) vfmadd231ps(mem(rcx, rsi, 8), ymm3, ymm9) vmovups(ymm9, mem(rcx, rsi, 8)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORED) vunpcklps(ymm6, ymm4, ymm0) //a0b0a1b1 a2b2a3b3 vunpckhps(ymm6, ymm4, ymm2) //a2b2a3b3 a6b6a7b7 vperm2f128(imm(0x01),ymm0,ymm0,ymm11) vperm2f128(imm(0x01),ymm2,ymm2,ymm12) vshufpd(imm(0x01), xmm0, xmm0, xmm1)//a1b1 vshufpd(imm(0x01), xmm2, xmm2, xmm10)//a3b3 vmovsd(mem(rcx),xmm4) vmovsd(mem(rcx, rsi, 1),xmm6) vfmadd231ps(xmm4, xmm3, xmm0) vfmadd231ps(xmm6, xmm3, xmm1) vmovsd(xmm0, mem(rcx)) // store ( gamma00..gamma10 ) vmovsd(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma11 ) vmovsd(mem(rcx, rsi, 2),xmm4) vmovsd(mem(rcx, rax, 1),xmm6) vfmadd231ps(xmm4, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm10) vmovsd(xmm2, mem(rcx, rsi, 2)) // store ( gamma02..gamma12 ) vmovsd(xmm10, mem(rcx, rax, 1)) // store ( gamma03..gamma13 ) lea(mem(rcx, rsi, 4), rcx) // rcx += cs_c vshufpd(imm(0x01), xmm11, xmm11, xmm1)//a1b1 vshufpd(imm(0x01), xmm12, xmm12, xmm10)//a3b3 vmovsd(mem(rcx),xmm4) vmovsd(mem(rcx, rsi, 1),xmm6) vfmadd231ps(xmm4, xmm3, xmm11) vfmadd231ps(xmm6, xmm3, xmm1) vmovsd(xmm11, mem(rcx)) // store ( gamma00..gamma10 ) vmovsd(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma11 ) vmovsd(mem(rcx, rsi, 2),xmm4) vmovsd(mem(rcx, rax, 1),xmm6) vfmadd231ps(xmm4, xmm3, xmm12) vfmadd231ps(xmm6, xmm3, xmm10) vmovsd(xmm12, mem(rcx, rsi, 2)) // store ( gamma02..gamma12 ) vmovsd(xmm10, mem(rcx, rax, 1)) // store ( gamma03..gamma13 ) lea(mem(rcx, rsi, 4), rcx) // rcx += 4*cs_c /********************************************/ vextractf128(imm(0x0), ymm8, xmm0)//c0-c3 vmovss(mem(rdx),xmm4) vmovss(mem(rdx, rsi, 1),xmm6) vmovss(mem(rdx, rsi, 2),xmm11) vmovss(mem(rdx, rax, 1),xmm10) vshufps(imm(0x01), xmm0, xmm0,xmm1) vshufps(imm(0x02), xmm0, xmm0,xmm2) vshufps(imm(0x03), xmm0, xmm0,xmm14) vfmadd231ps(xmm4, xmm3, xmm0)//e0 vfmadd231ps(xmm6, xmm3, xmm1)//e1 vfmadd231ps(xmm11, xmm3, xmm2)//e2 vfmadd231ps(xmm10, xmm3, xmm14)//e3 vmovss(xmm0, mem(rdx)) vmovss(xmm1, mem(rdx, rsi, 1)) vmovss(xmm2, mem(rdx, rsi, 2)) vmovss(xmm14, mem(rdx, rax, 1)) lea(mem(rdx, rsi, 4), rdx) // rdx += 4*cs_c vextractf128(imm(0x1), ymm8, xmm0)//e4-e7 vmovss(mem(rdx),xmm4) vmovss(mem(rdx, rsi, 1),xmm6) vmovss(mem(rdx, rsi, 2),xmm8) vmovss(mem(rdx, rax, 1),xmm10) vshufps(imm(0x01), xmm0, xmm0,xmm1) vshufps(imm(0x02), xmm0, xmm0,xmm2) vshufps(imm(0x03), xmm0, xmm0,xmm14) vfmadd231ps(xmm4, xmm3, xmm0)//e4 vfmadd231ps(xmm6, xmm3, xmm1)//e5 vfmadd231ps(xmm8, xmm3, xmm2)//e6 vfmadd231ps(xmm10, xmm3, xmm14)//e7 vmovss(xmm0, mem(rdx)) vmovss(xmm1, mem(rdx, rsi, 1)) vmovss(xmm2, mem(rdx, rsi, 2)) vmovss(xmm14, mem(rdx, rax, 1)) lea(mem(rdx, rsi, 4), rdx) // rdx += 4*cs_c /*********************************************/ vunpcklps(ymm7, ymm5, ymm0) //a0b0a1b1 a2b2a3b3 vunpckhps(ymm7, ymm5, ymm2) //a2b2a3b3 a6b6a7b7 vperm2f128(imm(0x01),ymm0,ymm0,ymm11) vperm2f128(imm(0x01),ymm2,ymm2,ymm12) vshufpd(imm(0x01), xmm0, xmm0, xmm1)//a1b1 vshufpd(imm(0x01), xmm2, xmm2, xmm10)//a3b3 vmovsd(mem(rcx),xmm4) vmovsd(mem(rcx, rsi, 1),xmm6) vfmadd231ps(xmm4, xmm3, xmm0) vfmadd231ps(xmm6, xmm3, xmm1) vmovsd(xmm0, mem(rcx)) // store ( gamma00..gamma10 ) vmovsd(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma11 ) vmovsd(mem(rcx, rsi, 2),xmm4) vmovsd(mem(rcx, rax, 1),xmm6) vfmadd231ps(xmm4, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm10) vmovsd(xmm2, mem(rcx, rsi, 2)) // store ( gamma02..gamma12 ) vmovsd(xmm10, mem(rcx, rax, 1)) // store ( gamma03..gamma13 ) lea(mem(rcx, rsi, 4), rcx) // rcx += cs_c vshufpd(imm(0x01), xmm11, xmm11, xmm1)//a1b1 vshufpd(imm(0x01), xmm12, xmm12, xmm10)//a3b3 vmovsd(mem(rcx),xmm4) vmovsd(mem(rcx, rsi, 1),xmm6) vfmadd231ps(xmm4, xmm3, xmm11) vfmadd231ps(xmm6, xmm3, xmm1) vmovsd(xmm11, mem(rcx)) // store ( gamma00..gamma10 ) vmovsd(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma11 ) vmovsd(mem(rcx, rsi, 2),xmm4) vmovsd(mem(rcx, rax, 1),xmm6) vfmadd231ps(xmm4, xmm3, xmm12) vfmadd231ps(xmm6, xmm3, xmm10) vmovsd(xmm12, mem(rcx, rsi, 2)) // store ( gamma02..gamma12 ) vmovsd(xmm10, mem(rcx, rax, 1)) // store ( gamma03..gamma13 ) /********************************************/ vextractf128(imm(0x0), ymm9, xmm0)//c0-c3 vmovss(mem(rdx),xmm4) vmovss(mem(rdx, rsi, 1),xmm6) vmovss(mem(rdx, rsi, 2),xmm8) vmovss(mem(rdx, rax, 1),xmm10) vshufps(imm(0x01), xmm0, xmm0,xmm1) vshufps(imm(0x02), xmm0, xmm0,xmm2) vshufps(imm(0x03), xmm0, xmm0,xmm14) vfmadd231ps(xmm4, xmm3, xmm0)//e0 vfmadd231ps(xmm6, xmm3, xmm1)//e1 vfmadd231ps(xmm8, xmm3, xmm2)//e2 vfmadd231ps(xmm10, xmm3, xmm14)//e3 vmovss(xmm0, mem(rdx)) vmovss(xmm1, mem(rdx, rsi, 1)) vmovss(xmm2, mem(rdx, rsi, 2)) vmovss(xmm14, mem(rdx, rax, 1)) lea(mem(rdx, rsi, 4), rdx) // rdx += 4*cs_c vextractf128(imm(0x1), ymm9, xmm0)//e4-e7 vmovss(mem(rdx),xmm4) vmovss(mem(rdx, rsi, 1),xmm6) vmovss(mem(rdx, rsi, 2),xmm8) vmovss(mem(rdx, rax, 1),xmm10) vshufps(imm(0x01), xmm0, xmm0,xmm1) vshufps(imm(0x02), xmm0, xmm0,xmm2) vshufps(imm(0x03), xmm0, xmm0,xmm14) vfmadd231ps(xmm4, xmm3, xmm0)//e0 vfmadd231ps(xmm6, xmm3, xmm1)//e1 vfmadd231ps(xmm8, xmm3, xmm2)//e2 vfmadd231ps(xmm10, xmm3, xmm14)//e3 vmovss(xmm0, mem(rdx)) vmovss(xmm1, mem(rdx, rsi, 1)) vmovss(xmm2, mem(rdx, rsi, 2)) vmovss(xmm14, mem(rdx, rax, 1)) jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovups(ymm4, mem(rcx)) vmovups(ymm5, mem(rcx, rsi, 8)) add(rdi, rcx) vmovups(ymm6, mem(rcx)) vmovups(ymm7, mem(rcx, rsi, 8)) add(rdi, rcx) vmovups(ymm8, mem(rcx)) vmovups(ymm9, mem(rcx, rsi, 8)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) vunpcklps(ymm6, ymm4, ymm0) //a0b0a1b1 a2b2a3b3 vunpckhps(ymm6, ymm4, ymm2) //a2b2a3b3 a6b6a7b7 vshufpd(imm(0x01), xmm0, xmm0, xmm1)//a1b1 vshufpd(imm(0x01), xmm2, xmm2, xmm10)//a3b3 vmovsd(xmm0, mem(rcx)) // store ( gamma00..gamma10 ) vmovsd(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma11 ) vmovsd(xmm2, mem(rcx, rsi, 2)) // store ( gamma02..gamma12 ) vmovsd(xmm10, mem(rcx, rax, 1)) // store ( gamma03..gamma13 ) lea(mem(rcx, rsi, 4), rcx) // rcx += cs_c vperm2f128(imm(0x01),ymm0,ymm0,ymm0) vperm2f128(imm(0x01),ymm2,ymm2,ymm2) vshufpd(imm(0x01), xmm0, xmm0, xmm1)//a2b2 vshufpd(imm(0x01), xmm2, xmm2, xmm10)//a3b3 vmovsd(xmm0, mem(rcx)) // store ( gamma00..gamma10 ) vmovsd(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma11 ) vmovsd(xmm2, mem(rcx, rsi, 2)) // store ( gamma02..gamma12 ) vmovsd(xmm10, mem(rcx, rax, 1)) // store ( gamma03..gamma13 ) lea(mem(rcx, rsi, 4), rcx) // rcx += 4*cs_c /********************************************/ vextractf128(imm(0x0), ymm8, xmm0)//c0-c3 vshufps(imm(0x01), xmm0, xmm0,xmm1) vshufps(imm(0x02), xmm0, xmm0,xmm2) vshufps(imm(0x03), xmm0, xmm0,xmm14) vmovss(xmm0, mem(rdx)) vmovss(xmm1, mem(rdx, rsi, 1)) vmovss(xmm2, mem(rdx, rsi, 2)) vmovss(xmm14, mem(rdx, rax, 1)) lea(mem(rdx, rsi, 4), rdx) // rdx += 4*cs_c vextractf128(imm(0x1), ymm8, xmm0)//c4-c7 vshufps(imm(0x01), xmm0, xmm0,xmm1) vshufps(imm(0x02), xmm0, xmm0,xmm2) vshufps(imm(0x03), xmm0, xmm0,xmm14) vmovss(xmm0, mem(rdx)) vmovss(xmm1, mem(rdx, rsi, 1)) vmovss(xmm2, mem(rdx, rsi, 2)) vmovss(xmm14, mem(rdx, rax, 1)) lea(mem(rdx, rsi, 4), rdx) // rdx += 4*cs_c /*********************************************/ vunpcklps(ymm7, ymm5, ymm0) //a0b0a1b1 a2b2a3b3 vunpckhps(ymm7, ymm5, ymm2) //a2b2a3b3 a6b6a7b7 vshufpd(imm(0x01), xmm0, xmm0, xmm1)//a1b1 vshufpd(imm(0x01), xmm2, xmm2, xmm10)//a3b3 vmovsd(xmm0, mem(rcx)) // store ( gamma00..gamma10 ) vmovsd(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma11 ) vmovsd(xmm2, mem(rcx, rsi, 2)) // store ( gamma02..gamma12 ) vmovsd(xmm10, mem(rcx, rax, 1)) // store ( gamma03..gamma13 ) lea(mem(rcx, rsi, 4), rcx) // rcx += cs_c vperm2f128(imm(0x01),ymm0,ymm0,ymm0) vperm2f128(imm(0x01),ymm2,ymm2,ymm2) vshufpd(imm(0x01), xmm0, xmm0, xmm1)//a2b2 vshufpd(imm(0x01), xmm2, xmm2, xmm10)//a3b3 vmovsd(xmm0, mem(rcx)) // store ( gamma00..gamma10 ) vmovsd(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma11 ) vmovsd(xmm2, mem(rcx, rsi, 2)) // store ( gamma02..gamma12 ) vmovsd(xmm10, mem(rcx, rax, 1)) // store ( gamma03..gamma13 ) /********************************************/ vextractf128(imm(0x0), ymm9, xmm0)//c0-c3 vshufps(imm(0x01), xmm0, xmm0,xmm1) vshufps(imm(0x02), xmm0, xmm0,xmm2) vshufps(imm(0x03), xmm0, xmm0,xmm14) vmovss(xmm0, mem(rdx)) vmovss(xmm1, mem(rdx, rsi, 1)) vmovss(xmm2, mem(rdx, rsi, 2)) vmovss(xmm14, mem(rdx, rax, 1)) lea(mem(rdx, rsi, 4), rdx) // rdx += 4*cs_c vextractf128(imm(0x1), ymm9, xmm0)//c4-c7 vshufps(imm(0x01), xmm0, xmm0,xmm1) vshufps(imm(0x02), xmm0, xmm0,xmm2) vshufps(imm(0x03), xmm0, xmm0,xmm14) vmovss(xmm0, mem(rdx)) vmovss(xmm1, mem(rdx, rsi, 1)) vmovss(xmm2, mem(rdx, rsi, 2)) vmovss(xmm14, mem(rdx, rax, 1)) label(.SDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_sgemmsup_rv_zen_asm_2x16 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vxorps(ymm4, ymm4, ymm4) vxorps(ymm5, ymm5, ymm5) vxorps(ymm6, ymm6, ymm6) vxorps(ymm7, ymm7, ymm7) vxorps(ymm8, ymm8, ymm8) vxorps(ymm9, ymm9, ymm9) vxorps(ymm10, ymm10, ymm10) vxorps(ymm11, ymm11, ymm11) vxorps(ymm12, ymm12, ymm12) vxorps(ymm13, ymm13, ymm13) vxorps(ymm14, ymm14, ymm14) vxorps(ymm15, ymm15, ymm15) mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored prefetching on c prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 7*8)) // prefetch c + 1*rs_c jmp(.SPOSTPFETCH) // jump to end of prefetching c label(.SCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) lea(mem(rcx, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; prefetch(0, mem(rcx, 1*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 1*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 1*8)) // prefetch c + 2*cs_c prefetch(0, mem(rdx, 1*8)) // prefetch c + 3*cs_c prefetch(0, mem(rdx, rsi, 1, 1*8)) // prefetch c + 4*cs_c prefetch(0, mem(rdx, rsi, 2, 1*8)) // prefetch c + 5*cs_c lea(mem(rdx, rsi, 2), rdx) // rdx = c + 5*cs_c; prefetch(0, mem(rdx, rsi, 1, 1*8)) // prefetch c + 6*cs_c prefetch(0, mem(rdx, rsi, 2, 1*8)) // prefetch c + 7*cs_c label(.SPOSTPFETCH) // done prefetching c mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) // ---------------------------------- iteration 1 vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) // ---------------------------------- iteration 2 vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) // ---------------------------------- iteration 3 vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), ymm0) // load alpha and duplicate vbroadcastss(mem(rbx), ymm3) // load beta and duplicate vmulps(ymm0, ymm4, ymm4) // scale by alpha vmulps(ymm0, ymm5, ymm5) vmulps(ymm0, ymm6, ymm6) vmulps(ymm0, ymm7, ymm7) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) //lea(mem(rcx, rsi, 4), rdx) // load address of c + 4*cs_c; //lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vfmadd231ps(mem(rcx), ymm3, ymm4) vmovups(ymm4, mem(rcx)) vfmadd231ps(mem(rcx, rsi, 8), ymm3, ymm5) vmovups(ymm5, mem(rcx, rsi, 8)) add(rdi, rcx) vfmadd231ps(mem(rcx), ymm3, ymm6) vmovups(ymm6, mem(rcx)) vfmadd231ps(mem(rcx, rsi, 8), ymm3, ymm7) vmovups(ymm7, mem(rcx, rsi, 8)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORED) vunpcklps(ymm6, ymm4, ymm0) //a0b0a1b1 a2b2a3b3 vunpckhps(ymm6, ymm4, ymm2) //a2b2a3b3 a6b6a7b7 vperm2f128(imm(0x01),ymm0,ymm0,ymm11) vperm2f128(imm(0x01),ymm2,ymm2,ymm12) vshufpd(imm(0x01), xmm0, xmm0, xmm1)//a1b1 vshufpd(imm(0x01), xmm2, xmm2, xmm10)//a3b3 vmovsd(mem(rcx),xmm4) vmovsd(mem(rcx, rsi, 1),xmm6) vfmadd231ps(xmm4, xmm3, xmm0) vfmadd231ps(xmm6, xmm3, xmm1) vmovsd(xmm0, mem(rcx)) // store ( gamma00..gamma10 ) vmovsd(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma11 ) vmovsd(mem(rcx, rsi, 2),xmm4) vmovsd(mem(rcx, rax, 1),xmm6) vfmadd231ps(xmm4, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm10) vmovsd(xmm2, mem(rcx, rsi, 2)) // store ( gamma02..gamma12 ) vmovsd(xmm10, mem(rcx, rax, 1)) // store ( gamma03..gamma13 ) lea(mem(rcx, rsi, 4), rcx) // rcx += cs_c vshufpd(imm(0x01), xmm11, xmm11, xmm1)//a1b1 vshufpd(imm(0x01), xmm12, xmm12, xmm10)//a3b3 vmovsd(mem(rcx),xmm4) vmovsd(mem(rcx, rsi, 1),xmm6) vfmadd231ps(xmm4, xmm3, xmm11) vfmadd231ps(xmm6, xmm3, xmm1) vmovsd(xmm11, mem(rcx)) // store ( gamma00..gamma10 ) vmovsd(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma11 ) vmovsd(mem(rcx, rsi, 2),xmm4) vmovsd(mem(rcx, rax, 1),xmm6) vfmadd231ps(xmm4, xmm3, xmm12) vfmadd231ps(xmm6, xmm3, xmm10) vmovsd(xmm12, mem(rcx, rsi, 2)) // store ( gamma02..gamma12 ) vmovsd(xmm10, mem(rcx, rax, 1)) // store ( gamma03..gamma13 ) lea(mem(rcx, rsi, 4), rcx) // rcx += 4*cs_c vunpcklps(ymm7, ymm5, ymm0) //a0b0a1b1 a2b2a3b3 vunpckhps(ymm7, ymm5, ymm2) //a2b2a3b3 a6b6a7b7 vperm2f128(imm(0x01),ymm0,ymm0,ymm11) vperm2f128(imm(0x01),ymm2,ymm2,ymm12) vshufpd(imm(0x01), xmm0, xmm0, xmm1)//a1b1 vshufpd(imm(0x01), xmm2, xmm2, xmm10)//a3b3 vmovsd(mem(rcx),xmm4) vmovsd(mem(rcx, rsi, 1),xmm6) vfmadd231ps(xmm4, xmm3, xmm0) vfmadd231ps(xmm6, xmm3, xmm1) vmovsd(xmm0, mem(rcx)) // store ( gamma00..gamma10 ) vmovsd(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma11 ) vmovsd(mem(rcx, rsi, 2),xmm4) vmovsd(mem(rcx, rax, 1),xmm6) vfmadd231ps(xmm4, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm10) vmovsd(xmm2, mem(rcx, rsi, 2)) // store ( gamma02..gamma12 ) vmovsd(xmm10, mem(rcx, rax, 1)) // store ( gamma03..gamma13 ) lea(mem(rcx, rsi, 4), rcx) // rcx += cs_c vshufpd(imm(0x01), xmm11, xmm11, xmm1)//a1b1 vshufpd(imm(0x01), xmm12, xmm12, xmm10)//a3b3 vmovsd(mem(rcx),xmm4) vmovsd(mem(rcx, rsi, 1),xmm6) vfmadd231ps(xmm4, xmm3, xmm11) vfmadd231ps(xmm6, xmm3, xmm1) vmovsd(xmm11, mem(rcx)) // store ( gamma00..gamma10 ) vmovsd(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma11 ) vmovsd(mem(rcx, rsi, 2),xmm4) vmovsd(mem(rcx, rax, 1),xmm6) vfmadd231ps(xmm4, xmm3, xmm12) vfmadd231ps(xmm6, xmm3, xmm10) vmovsd(xmm12, mem(rcx, rsi, 2)) // store ( gamma02..gamma12 ) vmovsd(xmm10, mem(rcx, rax, 1)) // store ( gamma03..gamma13 ) jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovups(ymm4, mem(rcx)) vmovups(ymm5, mem(rcx, rsi, 8)) add(rdi, rcx) vmovups(ymm6, mem(rcx)) vmovups(ymm7, mem(rcx, rsi, 8)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) vunpcklps(ymm6, ymm4, ymm0) //a0b0a1b1 a2b2a3b3 vunpckhps(ymm6, ymm4, ymm2) //a2b2a3b3 a6b6a7b7 vshufpd(imm(0x01), xmm0, xmm0, xmm1)//a1b1 vshufpd(imm(0x01), xmm2, xmm2, xmm10)//a3b3 vmovsd(xmm0, mem(rcx)) // store ( gamma00..gamma10 ) vmovsd(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma11 ) vmovsd(xmm2, mem(rcx, rsi, 2)) // store ( gamma02..gamma12 ) vmovsd(xmm10, mem(rcx, rax, 1)) // store ( gamma03..gamma13 ) lea(mem(rcx, rsi, 4), rcx) // rcx += cs_c vperm2f128(imm(0x01),ymm0,ymm0,ymm0) vperm2f128(imm(0x01),ymm2,ymm2,ymm2) vshufpd(imm(0x01), xmm0, xmm0, xmm1)//a2b2 vshufpd(imm(0x01), xmm2, xmm2, xmm10)//a3b3 vmovsd(xmm0, mem(rcx)) // store ( gamma00..gamma10 ) vmovsd(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma11 ) vmovsd(xmm2, mem(rcx, rsi, 2)) // store ( gamma02..gamma12 ) vmovsd(xmm10, mem(rcx, rax, 1)) // store ( gamma03..gamma13 ) lea(mem(rcx, rsi, 4), rcx) // rcx += 4*cs_c vunpcklps(ymm7, ymm5, ymm0) //a0b0a1b1 a2b2a3b3 vunpckhps(ymm7, ymm5, ymm2) //a2b2a3b3 a6b6a7b7 vshufpd(imm(0x01), xmm0, xmm0, xmm1)//a1b1 vshufpd(imm(0x01), xmm2, xmm2, xmm10)//a3b3 vmovsd(xmm0, mem(rcx)) // store ( gamma00..gamma10 ) vmovsd(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma11 ) vmovsd(xmm2, mem(rcx, rsi, 2)) // store ( gamma02..gamma12 ) vmovsd(xmm10, mem(rcx, rax, 1)) // store ( gamma03..gamma13 ) lea(mem(rcx, rsi, 4), rcx) // rcx += cs_c vperm2f128(imm(0x01),ymm0,ymm0,ymm0) vperm2f128(imm(0x01),ymm2,ymm2,ymm2) vshufpd(imm(0x01), xmm0, xmm0, xmm1)//a2b2 vshufpd(imm(0x01), xmm2, xmm2, xmm10)//a3b3 vmovsd(xmm0, mem(rcx)) // store ( gamma00..gamma10 ) vmovsd(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma11 ) vmovsd(xmm2, mem(rcx, rsi, 2)) // store ( gamma02..gamma12 ) vmovsd(xmm10, mem(rcx, rax, 1)) // store ( gamma03..gamma13 ) label(.SDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_sgemmsup_rv_zen_asm_1x16 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vxorps(ymm4, ymm4, ymm4) vxorps(ymm5, ymm5, ymm5) vxorps(ymm6, ymm6, ymm6) vxorps(ymm7, ymm7, ymm7) vxorps(ymm8, ymm8, ymm8) vxorps(ymm9, ymm9, ymm9) vxorps(ymm10, ymm10, ymm10) vxorps(ymm11, ymm11, ymm11) vxorps(ymm12, ymm12, ymm12) vxorps(ymm13, ymm13, ymm13) vxorps(ymm14, ymm14, ymm14) vxorps(ymm15, ymm15, ymm15) mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored prefetching on c prefetch(0, mem(rcx, 7*8)) // prefetch c + 0*rs_c jmp(.SPOSTPFETCH) // jump to end of prefetching c label(.SCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) lea(mem(rcx, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; prefetch(0, mem(rcx, 0*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 0*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 0*8)) // prefetch c + 2*cs_c prefetch(0, mem(rdx, 0*8)) // prefetch c + 3*cs_c prefetch(0, mem(rdx, rsi, 1, 0*8)) // prefetch c + 4*cs_c prefetch(0, mem(rdx, rsi, 2, 0*8)) // prefetch c + 5*cs_c lea(mem(rdx, rsi, 2), rdx) // rdx = c + 5*cs_c; prefetch(0, mem(rdx, rsi, 1, 0*8)) // prefetch c + 6*cs_c prefetch(0, mem(rdx, rsi, 2, 0*8)) // prefetch c + 7*cs_c label(.SPOSTPFETCH) // done prefetching c mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) // ---------------------------------- iteration 1 vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) // ---------------------------------- iteration 2 vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) // ---------------------------------- iteration 3 vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), ymm0) // load alpha and duplicate vbroadcastss(mem(rbx), ymm3) // load beta and duplicate vmulps(ymm0, ymm4, ymm4) // scale by alpha vmulps(ymm0, ymm5, ymm5) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vfmadd231ps(mem(rcx), ymm3, ymm4) vmovups(ymm4, mem(rcx)) vfmadd231ps(mem(rcx, rsi, 8), ymm3, ymm5) vmovups(ymm5, mem(rcx, rsi, 8)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORED) vextractf128(imm(0x0), ymm4, xmm0)//c0-c3 vmovss(mem(rcx),xmm7) vmovss(mem(rcx, rsi, 1),xmm6) vmovss(mem(rcx, rsi, 2),xmm11) vmovss(mem(rcx, rax, 1),xmm10) vshufps(imm(0x01), xmm0, xmm0,xmm1) vshufps(imm(0x02), xmm0, xmm0,xmm2) vshufps(imm(0x03), xmm0, xmm0,xmm14) vfmadd231ps(xmm7, xmm3, xmm0)//e0 vfmadd231ps(xmm6, xmm3, xmm1)//e1 vfmadd231ps(xmm11, xmm3, xmm2)//e2 vfmadd231ps(xmm10, xmm3, xmm14)//e3 vmovss(xmm0, mem(rcx)) vmovss(xmm1, mem(rcx, rsi, 1)) vmovss(xmm2, mem(rcx, rsi, 2)) vmovss(xmm14, mem(rcx, rax, 1)) lea(mem(rcx, rsi, 4), rcx) // rcx += cs_c vextractf128(imm(0x1), ymm4, xmm0)//e4-e7 vmovss(mem(rcx),xmm4) vmovss(mem(rcx, rsi, 1),xmm6) vmovss(mem(rcx, rsi, 2),xmm8) vmovss(mem(rcx, rax, 1),xmm10) vshufps(imm(0x01), xmm0, xmm0,xmm1) vshufps(imm(0x02), xmm0, xmm0,xmm2) vshufps(imm(0x03), xmm0, xmm0,xmm14) vfmadd231ps(xmm4, xmm3, xmm0)//e4 vfmadd231ps(xmm6, xmm3, xmm1)//e5 vfmadd231ps(xmm8, xmm3, xmm2)//e6 vfmadd231ps(xmm10, xmm3, xmm14)//e7 vmovss(xmm0, mem(rcx)) vmovss(xmm1, mem(rcx, rsi, 1)) vmovss(xmm2, mem(rcx, rsi, 2)) vmovss(xmm14, mem(rcx, rax, 1)) lea(mem(rcx, rsi, 4), rcx) // rcx += 4*cs_c vextractf128(imm(0x0), ymm5, xmm0)//c0-c3 vmovss(mem(rcx),xmm4) vmovss(mem(rcx, rsi, 1),xmm6) vmovss(mem(rcx, rsi, 2),xmm11) vmovss(mem(rcx, rax, 1),xmm10) vshufps(imm(0x01), xmm0, xmm0,xmm1) vshufps(imm(0x02), xmm0, xmm0,xmm2) vshufps(imm(0x03), xmm0, xmm0,xmm14) vfmadd231ps(xmm4, xmm3, xmm0)//e0 vfmadd231ps(xmm6, xmm3, xmm1)//e1 vfmadd231ps(xmm11, xmm3, xmm2)//e2 vfmadd231ps(xmm10, xmm3, xmm14)//e3 vmovss(xmm0, mem(rcx)) vmovss(xmm1, mem(rcx, rsi, 1)) vmovss(xmm2, mem(rcx, rsi, 2)) vmovss(xmm14, mem(rcx, rax, 1)) lea(mem(rcx, rsi, 4), rcx) // rcx += 4*cs_c vextractf128(imm(0x1), ymm5, xmm0)//e4-e7 vmovss(mem(rcx),xmm4) vmovss(mem(rcx, rsi, 1),xmm6) vmovss(mem(rcx, rsi, 2),xmm8) vmovss(mem(rcx, rax, 1),xmm10) vshufps(imm(0x01), xmm0, xmm0,xmm1) vshufps(imm(0x02), xmm0, xmm0,xmm2) vshufps(imm(0x03), xmm0, xmm0,xmm14) vfmadd231ps(xmm4, xmm3, xmm0)//e4 vfmadd231ps(xmm6, xmm3, xmm1)//e5 vfmadd231ps(xmm8, xmm3, xmm2)//e6 vfmadd231ps(xmm10, xmm3, xmm14)//e7 vmovss(xmm0, mem(rcx)) vmovss(xmm1, mem(rcx, rsi, 1)) vmovss(xmm2, mem(rcx, rsi, 2)) vmovss(xmm14, mem(rcx, rax, 1)) jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovups(ymm4, mem(rcx)) vmovups(ymm5, mem(rcx, rsi, 8)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) vextractf128(imm(0x0), ymm4, xmm0)//c0-c3 vshufps(imm(0x01), xmm0, xmm0,xmm1) vshufps(imm(0x02), xmm0, xmm0,xmm2) vshufps(imm(0x03), xmm0, xmm0,xmm14) vmovss(xmm0, mem(rcx)) vmovss(xmm1, mem(rcx, rsi, 1)) vmovss(xmm2, mem(rcx, rsi, 2)) vmovss(xmm14, mem(rcx, rax, 1)) lea(mem(rcx, rsi, 4), rcx) // rcx += cs_c vextractf128(imm(0x1), ymm4, xmm0)//e4-e7 vshufps(imm(0x01), xmm0, xmm0,xmm1) vshufps(imm(0x02), xmm0, xmm0,xmm2) vshufps(imm(0x03), xmm0, xmm0,xmm14) vmovss(xmm0, mem(rcx)) vmovss(xmm1, mem(rcx, rsi, 1)) vmovss(xmm2, mem(rcx, rsi, 2)) vmovss(xmm14, mem(rcx, rax, 1)) vextractf128(imm(0x0), ymm5, xmm0)//c0-c3 vshufps(imm(0x01), xmm0, xmm0,xmm1) vshufps(imm(0x02), xmm0, xmm0,xmm2) vshufps(imm(0x03), xmm0, xmm0,xmm14) vmovss(xmm0, mem(rcx)) vmovss(xmm1, mem(rcx, rsi, 1)) vmovss(xmm2, mem(rcx, rsi, 2)) vmovss(xmm14, mem(rcx, rax, 1)) lea(mem(rcx, rsi, 4), rcx) // rcx += cs_c vextractf128(imm(0x1), ymm5, xmm0)//e4-e7 vshufps(imm(0x01), xmm0, xmm0,xmm1) vshufps(imm(0x02), xmm0, xmm0,xmm2) vshufps(imm(0x03), xmm0, xmm0,xmm14) vmovss(xmm0, mem(rcx)) vmovss(xmm1, mem(rcx, rsi, 1)) vmovss(xmm2, mem(rcx, rsi, 2)) vmovss(xmm14, mem(rcx, rax, 1)) label(.SDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_sgemmsup_rv_zen_asm_6x8 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vxorps(ymm4, ymm4, ymm4) vxorps(ymm5, ymm5, ymm5) vxorps(ymm6, ymm6, ymm6) vxorps(ymm7, ymm7, ymm7) vxorps(ymm8, ymm8, ymm8) vxorps(ymm9, ymm9, ymm9) vxorps(ymm10, ymm10, ymm10) vxorps(ymm11, ymm11, ymm11) vxorps(ymm12, ymm12, ymm12) vxorps(ymm13, ymm13, ymm13) vxorps(ymm14, ymm14, ymm14) vxorps(ymm15, ymm15, ymm15) mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored prefetching on c lea(mem(rcx, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 5*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 5*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 5*8)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 5*8)) // prefetch c + 3*rs_c prefetch(0, mem(rdx, rdi, 1, 5*8)) // prefetch c + 4*rs_c prefetch(0, mem(rdx, rdi, 2, 5*8)) // prefetch c + 5*rs_c jmp(.SPOSTPFETCH) // jump to end of prefetching c label(.SCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) lea(mem(rcx, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; prefetch(0, mem(rcx, 5*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 5*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 5*8)) // prefetch c + 2*cs_c prefetch(0, mem(rdx, 5*8)) // prefetch c + 3*cs_c prefetch(0, mem(rdx, rsi, 1, 5*8)) // prefetch c + 4*cs_c prefetch(0, mem(rdx, rsi, 2, 5*8)) // prefetch c + 5*cs_c label(.SPOSTPFETCH) // done prefetching c mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 vmovups(mem(rbx, 0*16), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm0, ymm3, ymm10) vbroadcastss(mem(rax, r8, 4), ymm2) vbroadcastss(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm0, ymm3, ymm14) // ---------------------------------- iteration 1 vmovups(mem(rbx, 0*16), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm0, ymm3, ymm10) vbroadcastss(mem(rax, r8, 4), ymm2) vbroadcastss(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm0, ymm3, ymm14) // ---------------------------------- iteration 2 vmovups(mem(rbx, 0*16), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm0, ymm3, ymm10) vbroadcastss(mem(rax, r8, 4), ymm2) vbroadcastss(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm0, ymm3, ymm14) // ---------------------------------- iteration 3 vmovups(mem(rbx, 0*16), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm0, ymm3, ymm10) vbroadcastss(mem(rax, r8, 4), ymm2) vbroadcastss(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm0, ymm3, ymm14) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP vmovups(mem(rbx, 0*16), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm0, ymm3, ymm10) vbroadcastss(mem(rax, r8, 4), ymm2) vbroadcastss(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm0, ymm3, ymm14) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), ymm0) // load alpha and duplicate vbroadcastss(mem(rbx), ymm3) // load beta and duplicate vmulps(ymm0, ymm4, ymm4) // scale by alpha vmulps(ymm0, ymm6, ymm6) vmulps(ymm0, ymm8, ymm8) vmulps(ymm0, ymm10, ymm10) vmulps(ymm0, ymm12, ymm12) vmulps(ymm0, ymm14, ymm14) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vfmadd231ps(mem(rcx), ymm3, ymm4) vmovups(ymm4, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), ymm3, ymm6) vmovups(ymm6, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), ymm3, ymm8) vmovups(ymm8, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), ymm3, ymm10) vmovups(ymm10, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), ymm3, ymm12) vmovups(ymm12, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), ymm3, ymm14) vmovups(ymm14, mem(rcx)) jmp(.SDONE) // jump to end. label(.SCOLSTORED) /****6x8 tile is transposed and saved in col major as 8x6*****/ vunpcklps(ymm6, ymm4, ymm0) vunpcklps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx), xmm3, xmm0) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm0, mem(rcx)) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) lea(mem(rcx, rsi, 1), rcx) // rcx += 1*cs_c vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx), xmm3, xmm1) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm1, mem(rcx)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma05..gamma35 ) lea(mem(rcx, rsi, 1), rcx) // rcx += 1*cs_c vunpckhps(ymm6, ymm4, ymm0) vunpckhps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx), xmm3, xmm0) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm0, mem(rcx)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma06..gamma36 ) lea(mem(rcx, rsi, 1), rcx) // rcx += 1*cs_c vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx), xmm3, xmm1) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm1, mem(rcx)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma07..gamma37 ) vunpcklps(ymm14, ymm12, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vpermilpd(imm(1),xmm0,xmm5)//e1f1 vpermilpd(imm(1),xmm2,xmm6)//e5f5 vfmadd231ps(mem(rdx), xmm3, xmm0) vfmadd231ps(mem(rdx, rsi, 4), xmm3, xmm2) vmovlpd(xmm0, mem(rdx)) // store ( gamma40..gamma50 ) vmovlpd(xmm2, mem(rdx, rsi, 4)) // store ( gamma44..gamma54 ) lea(mem(rdx, rsi, 1), rdx) vfmadd231ps(mem(rdx), xmm3, xmm5) vfmadd231ps(mem(rdx, rsi, 4), xmm3, xmm6) vmovlpd(xmm5, mem(rdx)) // store ( gamma41..gamma51 ) vmovlpd(xmm6, mem(rdx, rsi, 4)) // store ( gamma45..gamma55 ) lea(mem(rdx, rsi, 1), rdx) vunpckhps(ymm14, ymm12, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vpermilpd(imm(1),xmm0,xmm5) vpermilpd(imm(1),xmm2,xmm6) vfmadd231ps(mem(rdx), xmm3, xmm0) vfmadd231ps(mem(rdx, rsi, 4), xmm3, xmm2) vmovlpd(xmm0, mem(rdx)) // store ( gamma42..gamma52 ) vmovlpd(xmm2, mem(rdx, rsi, 4)) // store ( gamma46..gamma56 ) lea(mem(rdx, rsi, 1), rdx) vfmadd231ps(mem(rdx), xmm3, xmm5) vfmadd231ps(mem(rdx, rsi, 4), xmm3, xmm6) vmovlpd(xmm5, mem(rdx)) // store ( gamma43..gamma53 ) vmovlpd(xmm6, mem(rdx, rsi, 4)) // store ( gamma47..gamma57 ) jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovups(ymm4, mem(rcx)) add(rdi, rcx) vmovups(ymm6, mem(rcx)) add(rdi, rcx) vmovups(ymm8, mem(rcx)) add(rdi, rcx) vmovups(ymm10, mem(rcx)) add(rdi, rcx) vmovups(ymm12, mem(rcx)) add(rdi, rcx) vmovups(ymm14, mem(rcx)) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) vunpcklps(ymm6, ymm4, ymm0) vunpcklps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx)) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) lea(mem(rcx, rsi, 1), rcx) // rcx += 1*cs_c vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma05..gamma35 ) lea(mem(rcx, rsi, 1), rcx) // rcx += 1*cs_c vunpckhps(ymm6, ymm4, ymm0) vunpckhps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma06..gamma36 ) lea(mem(rcx, rsi, 1), rcx) // rcx += 1*cs_c vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma07..gamma37 ) /******************top right tile 8x2***************************/ vunpcklps(ymm14, ymm12, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(xmm0, mem(rdx)) // store ( gamma40..gamma50 ) vmovlpd(xmm2, mem(rdx, rsi, 4)) // store ( gamma44..gamma54 ) lea(mem(rdx, rsi, 1), rdx) vmovhpd(xmm0, mem(rdx)) // store ( gamma41..gamma51 ) vmovhpd(xmm2, mem(rdx, rsi, 4)) // store ( gamma45..gamma55 ) lea(mem(rdx, rsi, 1), rdx) vunpckhps(ymm14, ymm12, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(xmm0, mem(rdx)) // store ( gamma42..gamma52 ) vmovlpd(xmm2, mem(rdx, rsi, 4)) // store ( gamma46..gamma56 ) lea(mem(rdx, rsi, 1), rdx) vmovhpd(xmm0, mem(rdx)) // store ( gamma43..gamma53 ) vmovhpd(xmm2, mem(rdx, rsi, 4)) // store ( gamma47..gamma57 ) label(.SDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_sgemmsup_rv_zen_asm_5x8 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vxorps(ymm4, ymm4, ymm4) vxorps(ymm5, ymm5, ymm5) vxorps(ymm6, ymm6, ymm6) vxorps(ymm7, ymm7, ymm7) vxorps(ymm8, ymm8, ymm8) vxorps(ymm9, ymm9, ymm9) vxorps(ymm10, ymm10, ymm10) vxorps(ymm11, ymm11, ymm11) vxorps(ymm12, ymm12, ymm12) vxorps(ymm13, ymm13, ymm13) vxorps(ymm14, ymm14, ymm14) vxorps(ymm15, ymm15, ymm15) mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored prefetching on c lea(mem(rcx, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 5*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 5*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 5*8)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 5*8)) // prefetch c + 3*rs_c prefetch(0, mem(rdx, rdi, 1, 5*8)) // prefetch c + 4*rs_c jmp(.SPOSTPFETCH) // jump to end of prefetching c label(.SCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) lea(mem(rcx, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; prefetch(0, mem(rcx, 4*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 4*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 4*8)) // prefetch c + 2*cs_c prefetch(0, mem(rdx, 4*8)) // prefetch c + 3*cs_c prefetch(0, mem(rdx, rsi, 1, 4*8)) // prefetch c + 4*cs_c prefetch(0, mem(rdx, rsi, 2, 4*8)) // prefetch c + 5*cs_c label(.SPOSTPFETCH) // done prefetching c mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 vmovups(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm0, ymm3, ymm10) vbroadcastss(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) // ---------------------------------- iteration 1 vmovups(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm0, ymm3, ymm10) vbroadcastss(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) // ---------------------------------- iteration 2 vmovups(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm0, ymm3, ymm10) vbroadcastss(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) // ---------------------------------- iteration 3 vmovups(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm0, ymm3, ymm10) vbroadcastss(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP vmovups(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm0, ymm3, ymm10) vbroadcastss(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), ymm0) // load alpha and duplicate vbroadcastss(mem(rbx), ymm3) // load beta and duplicate vmulps(ymm0, ymm4, ymm4) // scale by alpha vmulps(ymm0, ymm6, ymm6) vmulps(ymm0, ymm8, ymm8) vmulps(ymm0, ymm10, ymm10) vmulps(ymm0, ymm12, ymm12) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vfmadd231ps(mem(rcx), ymm3, ymm4) vmovups(ymm4, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), ymm3, ymm6) vmovups(ymm6, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), ymm3, ymm8) vmovups(ymm8, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), ymm3, ymm10) vmovups(ymm10, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), ymm3, ymm12) vmovups(ymm12, mem(rcx)) jmp(.SDONE) // jump to end. label(.SCOLSTORED) vunpcklps(ymm6, ymm4, ymm0) //a0b0a1b1 a4b4a5b5 vunpcklps(ymm10, ymm8, ymm1) //c0d0c1d1 c4d4c5d5 vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx), xmm3, xmm0) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm0, mem(rcx)) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx), xmm3, xmm1) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm1, mem(rcx)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma05..gamma35 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c vunpckhps(ymm6, ymm4, ymm0) vunpckhps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx), xmm3, xmm0) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm0, mem(rcx)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma06..gamma36 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx), xmm3, xmm1) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm1, mem(rcx)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma07..gamma37 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c lea(mem(rcx, rsi, 4), rcx) // rcx += 4*cs_c /********************************************/ vextractf128(imm(0x0), ymm12, xmm0)//e0-e3 vmovss(mem(rdx),xmm4) vmovss(mem(rdx, rsi, 1),xmm6) vmovss(mem(rdx, rsi, 2),xmm8) vmovss(mem(rdx, rax, 1),xmm10) vshufps(imm(0x01), xmm0, xmm0,xmm1) vshufps(imm(0x02), xmm0, xmm0,xmm2) vshufps(imm(0x03), xmm0, xmm0,xmm14) vfmadd231ps(xmm4, xmm3, xmm0)//e0 vfmadd231ps(xmm6, xmm3, xmm1)//e1 vfmadd231ps(xmm8, xmm3, xmm2)//e2 vfmadd231ps(xmm10, xmm3, xmm14)//e3 vmovss(xmm0, mem(rdx)) vmovss(xmm1, mem(rdx, rsi, 1)) vmovss(xmm2, mem(rdx, rsi, 2)) vmovss(xmm14, mem(rdx, rax, 1)) lea(mem(rdx, rsi, 4), rdx) // rdx += 4*cs_c vextractf128(imm(0x1), ymm12, xmm0)//e4-e7 vmovss(mem(rdx),xmm4) vmovss(mem(rdx, rsi, 1),xmm6) vmovss(mem(rdx, rsi, 2),xmm8) vmovss(mem(rdx, rax, 1),xmm10) vshufps(imm(0x01), xmm0, xmm0,xmm1) vshufps(imm(0x02), xmm0, xmm0,xmm2) vshufps(imm(0x03), xmm0, xmm0,xmm14) vfmadd231ps(xmm4, xmm3, xmm0)//e0 vfmadd231ps(xmm6, xmm3, xmm1)//e1 vfmadd231ps(xmm8, xmm3, xmm2)//e2 vfmadd231ps(xmm10, xmm3, xmm14)//e3 vmovss(xmm0, mem(rdx)) vmovss(xmm1, mem(rdx, rsi, 1)) vmovss(xmm2, mem(rdx, rsi, 2)) vmovss(xmm14, mem(rdx, rax, 1)) jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovups(ymm4, mem(rcx)) add(rdi, rcx) vmovups(ymm6, mem(rcx)) add(rdi, rcx) vmovups(ymm8, mem(rcx)) add(rdi, rcx) vmovups(ymm10, mem(rcx)) add(rdi, rcx) vmovups(ymm12, mem(rcx)) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) vunpcklps(ymm6, ymm4, ymm0) //a0b0a1b1 a4b4a5b5 vunpcklps(ymm10, ymm8, ymm1) //c0d0c1d1 c4d4c5d5 vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx)) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma05..gamma35 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c vunpckhps(ymm6, ymm4, ymm0) vunpckhps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma06..gamma36 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma07..gamma37 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c lea(mem(rcx, rsi, 4), rcx) // rcx += 4*cs_c /********************************************/ vextractf128(imm(0x0), ymm12, xmm0)//e0-e3 vshufps(imm(0x01), xmm0, xmm0,xmm1) vshufps(imm(0x02), xmm0, xmm0,xmm2) vshufps(imm(0x03), xmm0, xmm0,xmm14) vmovss(xmm0, mem(rdx)) vmovss(xmm1, mem(rdx, rsi, 1)) vmovss(xmm2, mem(rdx, rsi, 2)) vmovss(xmm14, mem(rdx, rax, 1)) lea(mem(rdx, rsi, 4), rdx) // rdx += 4*cs_c vextractf128(imm(0x1), ymm12, xmm0)//e4-e7 vshufps(imm(0x01), xmm0, xmm0,xmm1) vshufps(imm(0x02), xmm0, xmm0,xmm2) vshufps(imm(0x03), xmm0, xmm0,xmm14) vmovss(xmm0, mem(rdx)) vmovss(xmm1, mem(rdx, rsi, 1)) vmovss(xmm2, mem(rdx, rsi, 2)) vmovss(xmm14, mem(rdx, rax, 1)) label(.SDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_sgemmsup_rv_zen_asm_4x8 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vxorps(ymm4, ymm4, ymm4) vxorps(ymm5, ymm5, ymm5) vxorps(ymm6, ymm6, ymm6) vxorps(ymm7, ymm7, ymm7) vxorps(ymm8, ymm8, ymm8) vxorps(ymm9, ymm9, ymm9) vxorps(ymm10, ymm10, ymm10) vxorps(ymm11, ymm11, ymm11) vxorps(ymm12, ymm12, ymm12) vxorps(ymm13, ymm13, ymm13) vxorps(ymm14, ymm14, ymm14) vxorps(ymm15, ymm15, ymm15) mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored prefetching on c lea(mem(rcx, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 5*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 5*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 5*8)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 5*8)) // prefetch c + 3*rs_c jmp(.SPOSTPFETCH) // jump to end of prefetching c label(.SCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) lea(mem(rcx, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 3*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 3*8)) // prefetch c + 2*cs_c prefetch(0, mem(rdx, 3*8)) // prefetch c + 3*cs_c prefetch(0, mem(rdx, rsi, 1, 3*8)) // prefetch c + 4*cs_c prefetch(0, mem(rdx, rsi, 2, 3*8)) // prefetch c + 5*cs_c label(.SPOSTPFETCH) // done prefetching c mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 vmovups(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm0, ymm3, ymm10) // ---------------------------------- iteration 1 vmovups(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm0, ymm3, ymm10) // ---------------------------------- iteration 2 vmovups(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm0, ymm3, ymm10) // ---------------------------------- iteration 3 vmovups(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm0, ymm3, ymm10) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP vmovups(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm0, ymm3, ymm10) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), ymm0) // load alpha and duplicate vbroadcastss(mem(rbx), ymm3) // load beta and duplicate vmulps(ymm0, ymm4, ymm4) // scale by alpha vmulps(ymm0, ymm6, ymm6) vmulps(ymm0, ymm8, ymm8) vmulps(ymm0, ymm10, ymm10) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vfmadd231ps(mem(rcx), ymm3, ymm4) vmovups(ymm4, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), ymm3, ymm6) vmovups(ymm6, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), ymm3, ymm8) vmovups(ymm8, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), ymm3, ymm10) vmovups(ymm10, mem(rcx)) jmp(.SDONE) // jump to end. label(.SCOLSTORED) vunpcklps(ymm6, ymm4, ymm0) //a0b0a1b1 a4b4a5b5 vunpcklps(ymm10, ymm8, ymm1) //c0d0c1d1 c4d4c5d5 vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx), xmm3, xmm0) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm0, mem(rcx)) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx), xmm3, xmm1) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm1, mem(rcx)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma05..gamma35 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c vunpckhps(ymm6, ymm4, ymm0) vunpckhps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx), xmm3, xmm0) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm0, mem(rcx)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma06..gamma36 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx), xmm3, xmm1) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm1, mem(rcx)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma07..gamma37 ) jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovups(ymm4, mem(rcx)) add(rdi, rcx) vmovups(ymm6, mem(rcx)) add(rdi, rcx) vmovups(ymm8, mem(rcx)) add(rdi, rcx) vmovups(ymm10, mem(rcx)) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) vunpcklps(ymm6, ymm4, ymm0) //a0b0a1b1 a4b4a5b5 vunpcklps(ymm10, ymm8, ymm1) //c0d0c1d1 c4d4c5d5 vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx)) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma05..gamma35 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c vunpckhps(ymm6, ymm4, ymm0) vunpckhps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma06..gamma36 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma07..gamma37 ) label(.SDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_sgemmsup_rv_zen_asm_3x8 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vxorps(ymm4, ymm4, ymm4) vxorps(ymm5, ymm5, ymm5) vxorps(ymm6, ymm6, ymm6) vxorps(ymm7, ymm7, ymm7) vxorps(ymm8, ymm8, ymm8) vxorps(ymm9, ymm9, ymm9) vxorps(ymm10, ymm10, ymm10) vxorps(ymm11, ymm11, ymm11) vxorps(ymm12, ymm12, ymm12) vxorps(ymm13, ymm13, ymm13) vxorps(ymm14, ymm14, ymm14) vxorps(ymm15, ymm15, ymm15) mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored prefetching on c prefetch(0, mem(rcx, 5*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 5*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 5*8)) // prefetch c + 2*rs_c jmp(.SPOSTPFETCH) // jump to end of prefetching c label(.SCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) lea(mem(rcx, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; prefetch(0, mem(rcx, 2*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 2*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 2*8)) // prefetch c + 2*cs_c prefetch(0, mem(rdx, 2*8)) // prefetch c + 3*cs_c prefetch(0, mem(rdx, rsi, 1, 2*8)) // prefetch c + 4*cs_c prefetch(0, mem(rdx, rsi, 2, 2*8)) // prefetch c + 5*cs_c label(.SPOSTPFETCH) // done prefetching c mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 vmovups(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm8) // ---------------------------------- iteration 1 vmovups(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm8) // ---------------------------------- iteration 2 vmovups(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm8) // ---------------------------------- iteration 3 vmovups(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm8) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP vmovups(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm8) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), ymm0) // load alpha and duplicate vbroadcastss(mem(rbx), ymm3) // load beta and duplicate vmulps(ymm0, ymm4, ymm4) // scale by alpha vmulps(ymm0, ymm6, ymm6) vmulps(ymm0, ymm8, ymm8) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) lea(mem(rcx, rdi, 2), rdx) // load address of c + 2*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vfmadd231ps(mem(rcx), ymm3, ymm4) vmovups(ymm4, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), ymm3, ymm6) vmovups(ymm6, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), ymm3, ymm8) vmovups(ymm8, mem(rcx)) jmp(.SDONE) // jump to end. label(.SCOLSTORED) vunpcklps(ymm6, ymm4, ymm0) //a0b0a1b1 a2b2a3b3 vunpckhps(ymm6, ymm4, ymm2) //a2b2a3b3 a6b6a7b7 vperm2f128(imm(0x01),ymm0,ymm0,ymm11) vperm2f128(imm(0x01),ymm2,ymm2,ymm12) vshufpd(imm(0x01), xmm0, xmm0, xmm1)//a1b1 vshufpd(imm(0x01), xmm2, xmm2, xmm10)//a3b3 vmovsd(mem(rcx),xmm4) vmovsd(mem(rcx, rsi, 1),xmm6) vfmadd231ps(xmm4, xmm3, xmm0) vfmadd231ps(xmm6, xmm3, xmm1) vmovsd(xmm0, mem(rcx)) // store ( gamma00..gamma10 ) vmovsd(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma11 ) vmovsd(mem(rcx, rsi, 2),xmm4) vmovsd(mem(rcx, rax, 1),xmm6) vfmadd231ps(xmm4, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm10) vmovsd(xmm2, mem(rcx, rsi, 2)) // store ( gamma02..gamma12 ) vmovsd(xmm10, mem(rcx, rax, 1)) // store ( gamma03..gamma13 ) lea(mem(rcx, rsi, 4), rcx) // rcx += cs_c vshufpd(imm(0x01), xmm11, xmm11, xmm1)//a1b1 vshufpd(imm(0x01), xmm12, xmm12, xmm10)//a3b3 vmovsd(mem(rcx),xmm4) vmovsd(mem(rcx, rsi, 1),xmm6) vfmadd231ps(xmm4, xmm3, xmm11) vfmadd231ps(xmm6, xmm3, xmm1) vmovsd(xmm11, mem(rcx)) // store ( gamma00..gamma10 ) vmovsd(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma11 ) vmovsd(mem(rcx, rsi, 2),xmm4) vmovsd(mem(rcx, rax, 1),xmm6) vfmadd231ps(xmm4, xmm3, xmm12) vfmadd231ps(xmm6, xmm3, xmm10) vmovsd(xmm12, mem(rcx, rsi, 2)) // store ( gamma02..gamma12 ) vmovsd(xmm10, mem(rcx, rax, 1)) // store ( gamma03..gamma13 ) /********************************************/ vextractf128(imm(0x0), ymm8, xmm0)//c0-c3 vmovss(mem(rdx),xmm4) vmovss(mem(rdx, rsi, 1),xmm6) vmovss(mem(rdx, rsi, 2),xmm11) vmovss(mem(rdx, rax, 1),xmm10) vshufps(imm(0x01), xmm0, xmm0,xmm1) vshufps(imm(0x02), xmm0, xmm0,xmm2) vshufps(imm(0x03), xmm0, xmm0,xmm14) vfmadd231ps(xmm4, xmm3, xmm0)//e0 vfmadd231ps(xmm6, xmm3, xmm1)//e1 vfmadd231ps(xmm11, xmm3, xmm2)//e2 vfmadd231ps(xmm10, xmm3, xmm14)//e3 vmovss(xmm0, mem(rdx)) vmovss(xmm1, mem(rdx, rsi, 1)) vmovss(xmm2, mem(rdx, rsi, 2)) vmovss(xmm14, mem(rdx, rax, 1)) lea(mem(rdx, rsi, 4), rdx) // rcx += cs_c vextractf128(imm(0x1), ymm8, xmm0)//c0-c3 vmovss(mem(rdx),xmm4) vmovss(mem(rdx, rsi, 1),xmm6) vmovss(mem(rdx, rsi, 2),xmm11) vmovss(mem(rdx, rax, 1),xmm10) vshufps(imm(0x01), xmm0, xmm0,xmm1) vshufps(imm(0x02), xmm0, xmm0,xmm2) vshufps(imm(0x03), xmm0, xmm0,xmm14) vfmadd231ps(xmm4, xmm3, xmm0)//e0 vfmadd231ps(xmm6, xmm3, xmm1)//e1 vfmadd231ps(xmm11, xmm3, xmm2)//e2 vfmadd231ps(xmm10, xmm3, xmm14)//e3 vmovss(xmm0, mem(rdx)) vmovss(xmm1, mem(rdx, rsi, 1)) vmovss(xmm2, mem(rdx, rsi, 2)) vmovss(xmm14, mem(rdx, rax, 1)) jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovups(ymm4, mem(rcx)) add(rdi, rcx) vmovups(ymm6, mem(rcx)) add(rdi, rcx) vmovups(ymm8, mem(rcx)) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) vunpcklps(ymm6, ymm4, ymm0) //a0b0a1b1 a2b2a3b3 vunpckhps(ymm6, ymm4, ymm2) //a2b2a3b3 a6b6a7b7 vperm2f128(imm(0x01),ymm0,ymm0,ymm11) vperm2f128(imm(0x01),ymm2,ymm2,ymm12) vshufpd(imm(0x01), xmm0, xmm0, xmm1)//a1b1 vshufpd(imm(0x01), xmm2, xmm2, xmm10)//a3b3 vmovsd(mem(rcx),xmm4) vmovsd(mem(rcx, rsi, 1),xmm6) vfmadd231ps(xmm4, xmm3, xmm0) vfmadd231ps(xmm6, xmm3, xmm1) vmovsd(xmm0, mem(rcx)) // store ( gamma00..gamma10 ) vmovsd(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma11 ) vmovsd(mem(rcx, rsi, 2),xmm4) vmovsd(mem(rcx, rax, 1),xmm6) vfmadd231ps(xmm4, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm10) vmovsd(xmm2, mem(rcx, rsi, 2)) // store ( gamma02..gamma12 ) vmovsd(xmm10, mem(rcx, rax, 1)) // store ( gamma03..gamma13 ) lea(mem(rcx, rsi, 4), rcx) // rcx += cs_c vshufpd(imm(0x01), xmm11, xmm11, xmm1)//a1b1 vshufpd(imm(0x01), xmm12, xmm12, xmm10)//a3b3 vmovsd(mem(rcx),xmm4) vmovsd(mem(rcx, rsi, 1),xmm6) vfmadd231ps(xmm4, xmm3, xmm11) vfmadd231ps(xmm6, xmm3, xmm1) vmovsd(xmm11, mem(rcx)) // store ( gamma00..gamma10 ) vmovsd(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma11 ) vmovsd(mem(rcx, rsi, 2),xmm4) vmovsd(mem(rcx, rax, 1),xmm6) vfmadd231ps(xmm4, xmm3, xmm12) vfmadd231ps(xmm6, xmm3, xmm10) vmovsd(xmm12, mem(rcx, rsi, 2)) // store ( gamma02..gamma12 ) vmovsd(xmm10, mem(rcx, rax, 1)) // store ( gamma03..gamma13 ) /********************************************/ vextractf128(imm(0x0), ymm8, xmm0)//c0-c3 vshufps(imm(0x01), xmm0, xmm0,xmm1) vshufps(imm(0x02), xmm0, xmm0,xmm2) vshufps(imm(0x03), xmm0, xmm0,xmm14) vmovss(xmm0, mem(rdx)) vmovss(xmm1, mem(rdx, rsi, 1)) vmovss(xmm2, mem(rdx, rsi, 2)) vmovss(xmm14, mem(rdx, rax, 1)) lea(mem(rdx, rsi, 4), rdx) // rdx += 4*cs_c vextractf128(imm(0x1), ymm8, xmm0)//c4-c7 vshufps(imm(0x01), xmm0, xmm0,xmm1) vshufps(imm(0x02), xmm0, xmm0,xmm2) vshufps(imm(0x03), xmm0, xmm0,xmm14) vmovss(xmm0, mem(rdx)) vmovss(xmm1, mem(rdx, rsi, 1)) vmovss(xmm2, mem(rdx, rsi, 2)) vmovss(xmm14, mem(rdx, rax, 1)) label(.SDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_sgemmsup_rv_zen_asm_2x8 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vxorps(ymm4, ymm4, ymm4) vxorps(ymm5, ymm5, ymm5) vxorps(ymm6, ymm6, ymm6) vxorps(ymm7, ymm7, ymm7) vxorps(ymm8, ymm8, ymm8) vxorps(ymm9, ymm9, ymm9) vxorps(ymm10, ymm10, ymm10) vxorps(ymm11, ymm11, ymm11) vxorps(ymm12, ymm12, ymm12) vxorps(ymm13, ymm13, ymm13) vxorps(ymm14, ymm14, ymm14) vxorps(ymm15, ymm15, ymm15) mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored prefetching on c prefetch(0, mem(rcx, 5*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 5*8)) // prefetch c + 1*rs_c jmp(.SPOSTPFETCH) // jump to end of prefetching c label(.SCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) lea(mem(rcx, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; prefetch(0, mem(rcx, 1*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 1*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 1*8)) // prefetch c + 2*cs_c prefetch(0, mem(rdx, 1*8)) // prefetch c + 3*cs_c prefetch(0, mem(rdx, rsi, 1, 1*8)) // prefetch c + 4*cs_c prefetch(0, mem(rdx, rsi, 2, 1*8)) // prefetch c + 5*cs_c label(.SPOSTPFETCH) // done prefetching c mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 vmovups(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) // ---------------------------------- iteration 1 vmovups(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) // ---------------------------------- iteration 2 vmovups(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) // ---------------------------------- iteration 3 vmovups(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP vmovups(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), ymm0) // load alpha and duplicate vbroadcastss(mem(rbx), ymm3) // load beta and duplicate vmulps(ymm0, ymm4, ymm4) // scale by alpha vmulps(ymm0, ymm6, ymm6) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorps(xmm0,xmm0,xmm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vfmadd231ps(mem(rcx), ymm3, ymm4) vmovups(ymm4, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), ymm3, ymm6) vmovups(ymm6, mem(rcx)) jmp(.SDONE) // jump to end. label(.SCOLSTORED) vunpcklps(ymm6, ymm4, ymm0) //a0b0a1b1 a2b2a3b3 vunpckhps(ymm6, ymm4, ymm2) //a2b2a3b3 a6b6a7b7 vperm2f128(imm(0x01),ymm0,ymm0,ymm11) vperm2f128(imm(0x01),ymm2,ymm2,ymm12) vshufpd(imm(0x01), xmm0, xmm0, xmm1)//a1b1 vshufpd(imm(0x01), xmm2, xmm2, xmm10)//a3b3 vmovsd(mem(rcx),xmm4) vmovsd(mem(rcx, rsi, 1),xmm6) vfmadd231ps(xmm4, xmm3, xmm0) vfmadd231ps(xmm6, xmm3, xmm1) vmovsd(xmm0, mem(rcx)) // store ( gamma00..gamma10 ) vmovsd(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma11 ) vmovsd(mem(rcx, rsi, 2),xmm4) vmovsd(mem(rcx, rax, 1),xmm6) vfmadd231ps(xmm4, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm10) vmovsd(xmm2, mem(rcx, rsi, 2)) // store ( gamma02..gamma12 ) vmovsd(xmm10, mem(rcx, rax, 1)) // store ( gamma03..gamma13 ) lea(mem(rcx, rsi, 4), rcx) // rcx += cs_c vshufpd(imm(0x01), xmm11, xmm11, xmm1)//a1b1 vshufpd(imm(0x01), xmm12, xmm12, xmm10)//a3b3 vmovsd(mem(rcx),xmm4) vmovsd(mem(rcx, rsi, 1),xmm6) vfmadd231ps(xmm4, xmm3, xmm11) vfmadd231ps(xmm6, xmm3, xmm1) vmovsd(xmm11, mem(rcx)) // store ( gamma00..gamma10 ) vmovsd(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma11 ) vmovsd(mem(rcx, rsi, 2),xmm4) vmovsd(mem(rcx, rax, 1),xmm6) vfmadd231ps(xmm4, xmm3, xmm12) vfmadd231ps(xmm6, xmm3, xmm10) vmovsd(xmm12, mem(rcx, rsi, 2)) // store ( gamma02..gamma12 ) vmovsd(xmm10, mem(rcx, rax, 1)) // store ( gamma03..gamma13 ) jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovups(ymm4, mem(rcx)) add(rdi, rcx) vmovups(ymm6, mem(rcx)) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) vunpcklps(ymm6, ymm4, ymm0) //a0b0a1b1 a2b2a3b3 vunpckhps(ymm6, ymm4, ymm2) //a2b2a3b3 a6b6a7b7 vperm2f128(imm(0x01),ymm0,ymm0,ymm11) vperm2f128(imm(0x01),ymm2,ymm2,ymm12) vshufpd(imm(0x01), xmm0, xmm0, xmm1)//a1b1 vshufpd(imm(0x01), xmm2, xmm2, xmm10)//a3b3 vmovsd(mem(rcx),xmm4) vmovsd(mem(rcx, rsi, 1),xmm6) vfmadd231ps(xmm4, xmm3, xmm0) vfmadd231ps(xmm6, xmm3, xmm1) vmovsd(xmm0, mem(rcx)) // store ( gamma00..gamma10 ) vmovsd(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma11 ) vmovsd(mem(rcx, rsi, 2),xmm4) vmovsd(mem(rcx, rax, 1),xmm6) vfmadd231ps(xmm4, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm10) vmovsd(xmm2, mem(rcx, rsi, 2)) // store ( gamma02..gamma12 ) vmovsd(xmm10, mem(rcx, rax, 1)) // store ( gamma03..gamma13 ) lea(mem(rcx, rsi, 4), rcx) // rcx += cs_c vshufpd(imm(0x01), xmm11, xmm11, xmm1)//a1b1 vshufpd(imm(0x01), xmm12, xmm12, xmm10)//a3b3 vmovsd(mem(rcx),xmm4) vmovsd(mem(rcx, rsi, 1),xmm6) vfmadd231ps(xmm4, xmm3, xmm11) vfmadd231ps(xmm6, xmm3, xmm1) vmovsd(xmm11, mem(rcx)) // store ( gamma00..gamma10 ) vmovsd(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma11 ) vmovsd(mem(rcx, rsi, 2),xmm4) vmovsd(mem(rcx, rax, 1),xmm6) vfmadd231ps(xmm4, xmm3, xmm12) vfmadd231ps(xmm6, xmm3, xmm10) vmovsd(xmm12, mem(rcx, rsi, 2)) // store ( gamma02..gamma12 ) vmovsd(xmm10, mem(rcx, rax, 1)) // store ( gamma03..gamma13 ) label(.SDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_sgemmsup_rv_zen_asm_1x8 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vxorps(ymm4, ymm4, ymm4) vxorps(ymm5, ymm5, ymm5) vxorps(ymm6, ymm6, ymm6) vxorps(ymm7, ymm7, ymm7) vxorps(ymm8, ymm8, ymm8) vxorps(ymm9, ymm9, ymm9) vxorps(ymm10, ymm10, ymm10) vxorps(ymm11, ymm11, ymm11) vxorps(ymm12, ymm12, ymm12) vxorps(ymm13, ymm13, ymm13) vxorps(ymm14, ymm14, ymm14) vxorps(ymm15, ymm15, ymm15) mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) prefetch(0, mem(rcx, 5*8)) // prefetch c + 0*rs_c mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 vmovups(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) // ---------------------------------- iteration 1 vmovups(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) // ---------------------------------- iteration 2 vmovups(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) // ---------------------------------- iteration 3 vmovups(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP vmovups(mem(rbx, 0*32), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), ymm0) // load alpha and duplicate vbroadcastss(mem(rbx), ymm3) // load beta and duplicate vmulps(ymm0, ymm4, ymm4) // scale by alpha mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorps(xmm0,xmm0,xmm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vfmadd231ps(mem(rcx), ymm3, ymm4) vmovups(ymm4, mem(rcx)) jmp(.SDONE) // jump to end. label(.SCOLSTORED) /********************************************/ vextractf128(imm(0x0), ymm4, xmm0)//c0-c3 vmovss(mem(rcx),xmm8) vmovss(mem(rcx, rsi, 1),xmm6) vmovss(mem(rcx, rsi, 2),xmm11) vmovss(mem(rcx, rax, 1),xmm10) vshufps(imm(0x01), xmm0, xmm0,xmm1) vshufps(imm(0x02), xmm0, xmm0,xmm2) vshufps(imm(0x03), xmm0, xmm0,xmm14) vfmadd231ps(xmm8, xmm3, xmm0)//e0 vfmadd231ps(xmm6, xmm3, xmm1)//e1 vfmadd231ps(xmm11, xmm3, xmm2)//e2 vfmadd231ps(xmm10, xmm3, xmm14)//e3 vmovss(xmm0, mem(rcx)) vmovss(xmm1, mem(rcx, rsi, 1)) vmovss(xmm2, mem(rcx, rsi, 2)) vmovss(xmm14, mem(rcx, rax, 1)) lea(mem(rcx, rsi, 4), rcx) // rdx += 4*cs_c vextractf128(imm(0x1), ymm4, xmm0)//e4-e7 vmovss(mem(rcx),xmm4) vmovss(mem(rcx, rsi, 1),xmm6) vmovss(mem(rcx, rsi, 2),xmm8) vmovss(mem(rcx, rax, 1),xmm10) vshufps(imm(0x01), xmm0, xmm0,xmm1) vshufps(imm(0x02), xmm0, xmm0,xmm2) vshufps(imm(0x03), xmm0, xmm0,xmm14) vfmadd231ps(xmm4, xmm3, xmm0)//e4 vfmadd231ps(xmm6, xmm3, xmm1)//e5 vfmadd231ps(xmm8, xmm3, xmm2)//e6 vfmadd231ps(xmm10, xmm3, xmm14)//e7 vmovss(xmm0, mem(rcx)) vmovss(xmm1, mem(rcx, rsi, 1)) vmovss(xmm2, mem(rcx, rsi, 2)) vmovss(xmm14, mem(rcx, rax, 1)) jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovups(ymm4, mem(rcx)) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) vextractf128(imm(0x0), ymm4, xmm0)//c0-c3 vshufps(imm(0x01), xmm0, xmm0,xmm1) vshufps(imm(0x02), xmm0, xmm0,xmm2) vshufps(imm(0x03), xmm0, xmm0,xmm14) vmovss(xmm0, mem(rcx)) vmovss(xmm1, mem(rcx, rsi, 1)) vmovss(xmm2, mem(rcx, rsi, 2)) vmovss(xmm14, mem(rcx, rax, 1)) lea(mem(rcx, rsi, 4), rcx) // rdx += 4*cs_c vextractf128(imm(0x1), ymm4, xmm0)//c4-c7 vshufps(imm(0x01), xmm0, xmm0,xmm1) vshufps(imm(0x02), xmm0, xmm0,xmm2) vshufps(imm(0x03), xmm0, xmm0,xmm14) vmovss(xmm0, mem(rcx)) vmovss(xmm1, mem(rcx, rsi, 1)) vmovss(xmm2, mem(rcx, rsi, 2)) vmovss(xmm14, mem(rcx, rax, 1)) label(.SDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_sgemmsup_rv_zen_asm_6x4 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vxorps(ymm4, ymm4, ymm4) vxorps(ymm5, ymm5, ymm5) vxorps(ymm6, ymm6, ymm6) vxorps(ymm7, ymm7, ymm7) vxorps(ymm8, ymm8, ymm8) vxorps(ymm9, ymm9, ymm9) vxorps(ymm10, ymm10, ymm10) vxorps(ymm11, ymm11, ymm11) vxorps(ymm12, ymm12, ymm12) vxorps(ymm13, ymm13, ymm13) vxorps(ymm14, ymm14, ymm14) vxorps(ymm15, ymm15, ymm15) mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored prefetching on c lea(mem(rcx, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 3*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 3*8)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 3*8)) // prefetch c + 3*rs_c prefetch(0, mem(rdx, rdi, 1, 3*8)) // prefetch c + 4*rs_c prefetch(0, mem(rdx, rdi, 2, 3*8)) // prefetch c + 5*rs_c jmp(.SPOSTPFETCH) // jump to end of prefetching c label(.SCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) lea(mem(rcx, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; prefetch(0, mem(rcx, 5*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 5*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 5*8)) // prefetch c + 2*cs_c prefetch(0, mem(rdx, 5*8)) // prefetch c + 3*cs_c label(.SPOSTPFETCH) // done prefetching c mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) vbroadcastss(mem(rax, r13, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm8) vfmadd231ps(xmm0, xmm3, xmm10) vbroadcastss(mem(rax, r8, 4), xmm2) vbroadcastss(mem(rax, r15, 1), xmm3) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm12) vfmadd231ps(xmm0, xmm3, xmm14) // ---------------------------------- iteration 1 vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) vbroadcastss(mem(rax, r13, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm8) vfmadd231ps(xmm0, xmm3, xmm10) vbroadcastss(mem(rax, r8, 4), xmm2) vbroadcastss(mem(rax, r15, 1), xmm3) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm12) vfmadd231ps(xmm0, xmm3, xmm14) // ---------------------------------- iteration 2 vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) vbroadcastss(mem(rax, r13, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm8) vfmadd231ps(xmm0, xmm3, xmm10) vbroadcastss(mem(rax, r8, 4), xmm2) vbroadcastss(mem(rax, r15, 1), xmm3) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm12) vfmadd231ps(xmm0, xmm3, xmm14) // ---------------------------------- iteration 3 vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) vbroadcastss(mem(rax, r13, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm8) vfmadd231ps(xmm0, xmm3, xmm10) vbroadcastss(mem(rax, r8, 4), xmm2) vbroadcastss(mem(rax, r15, 1), xmm3) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm12) vfmadd231ps(xmm0, xmm3, xmm14) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) vbroadcastss(mem(rax, r13, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm8) vfmadd231ps(xmm0, xmm3, xmm10) vbroadcastss(mem(rax, r8, 4), xmm2) vbroadcastss(mem(rax, r15, 1), xmm3) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm12) vfmadd231ps(xmm0, xmm3, xmm14) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), ymm0) // load alpha and duplicate vbroadcastss(mem(rbx), ymm3) // load beta and duplicate vmulps(xmm0, xmm4, xmm4) // scale by alpha vmulps(xmm0, xmm6, xmm6) vmulps(xmm0, xmm8, xmm8) vmulps(xmm0, xmm10, xmm10) vmulps(xmm0, xmm12, xmm12) vmulps(xmm0, xmm14, xmm14) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorps(xmm0, xmm0, xmm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vfmadd231ps(mem(rcx), xmm3, xmm4) vmovups(xmm4, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), xmm3, xmm6) vmovups(xmm6, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), xmm3, xmm8) vmovups(xmm8, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), xmm3, xmm10) vmovups(xmm10, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), xmm3, xmm12) vmovups(xmm12, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), xmm3, xmm14) vmovups(xmm14, mem(rcx)) jmp(.SDONE) // jump to end. label(.SCOLSTORED) vunpcklps(xmm6, xmm4, xmm0)//a0b0a1b1 vunpcklps(xmm10, xmm8, xmm1)//c0d0c1d1 vunpcklpd(xmm1, xmm0, xmm2)//a0b0c0d0 vunpckhpd(xmm1, xmm0, xmm5)//a1b1c1d1 vfmadd231ps(mem(rcx), xmm3, xmm2) vfmadd231ps(mem(rcx, rsi, 1), xmm3, xmm5) vmovups(xmm2, mem(rcx)) vmovups(xmm5, mem(rcx, rsi, 1)) lea(mem(rcx, rsi, 2), rcx) // rcx += 2*cs_c vunpckhps(xmm6, xmm4, xmm0)//a2b2a3b3 vunpckhps(xmm10, xmm8, xmm1)//c2d2c3d3 vunpcklpd(xmm1, xmm0, xmm7)//a2b2c2d2 vunpckhpd(xmm1, xmm0, xmm9)//a3b3c3d3 vfmadd231ps(mem(rcx), xmm3, xmm7) vfmadd231ps(mem(rcx, rsi, 1), xmm3, xmm9) vmovups(xmm7, mem(rcx)) vmovups(xmm9, mem(rcx, rsi, 1)) vunpcklps(xmm14, xmm12, xmm0)//e0f0e1f1 vunpckhps(xmm14, xmm12, xmm1)//e2f2e3f3 vmovsd(mem(rdx),xmm2) vmovsd(mem(rdx, rsi, 1),xmm4) vmovsd(mem(rdx, rsi, 2),xmm6) vmovsd(mem(rdx, rax, 1),xmm8) vshufpd(imm(0x01), xmm0, xmm0, xmm5)//e1f1 vshufpd(imm(0x01), xmm1, xmm1, xmm7)//e3f3 vfmadd231ps(xmm2, xmm3, xmm0) vfmadd231ps(xmm4, xmm3, xmm5) vfmadd231ps(xmm6, xmm3, xmm1) vfmadd231ps(xmm8, xmm3, xmm7) vmovsd(xmm0, mem(rdx)) //e0f0 vmovsd(xmm5, mem(rdx, rsi, 1)) //e1f1 vmovsd(xmm1, mem(rdx, rsi, 2)) //e2f2 vmovsd(xmm7, mem(rdx, rax, 1)) //e3f3 jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovups(xmm4, mem(rcx)) add(rdi, rcx) vmovups(xmm6, mem(rcx)) add(rdi, rcx) vmovups(xmm8, mem(rcx)) add(rdi, rcx) vmovups(xmm10, mem(rcx)) add(rdi, rcx) vmovups(xmm12, mem(rcx)) add(rdi, rcx) vmovups(xmm14, mem(rcx)) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) vunpcklps(xmm6, xmm4, xmm0)//a0b0a1b1 vunpcklps(xmm10, xmm8, xmm1)//c0d0c1d1 vunpcklpd(xmm1, xmm0, xmm2)//a0b0c0d0 vunpckhpd(xmm1, xmm0, xmm5)//a1b1c1d1 vmovups(xmm2, mem(rcx)) vmovups(xmm5, mem(rcx, rsi, 1)) lea(mem(rcx, rsi, 2), rcx) // rcx += 2*cs_c vunpckhps(xmm6, xmm4, xmm0)//a2b2a3b3 vunpckhps(xmm10, xmm8, xmm1)//c2d2c3d3 vunpcklpd(xmm1, xmm0, xmm7)//a2b2c2d2 vunpckhpd(xmm1, xmm0, xmm9)//a3b3c3d3 vmovups(xmm7, mem(rcx)) vmovups(xmm9, mem(rcx, rsi, 1)) vunpcklps(xmm14, xmm12, xmm0)//e0f0e1f1 vunpckhps(xmm14, xmm12, xmm1)//e2f2e3f3 vshufpd(imm(0x01), xmm0, xmm0, xmm5)//e1f1 vshufpd(imm(0x01), xmm1, xmm1, xmm7)//e3f3 vmovsd(xmm0, mem(rdx)) //e0f0 vmovsd(xmm5, mem(rdx, rsi, 1)) //e1f1 vmovsd(xmm1, mem(rdx, rsi, 2)) //e2f2 vmovsd(xmm7, mem(rdx, rax, 1)) //e3f3 label(.SDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_sgemmsup_rv_zen_asm_5x4 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vxorps(ymm4, ymm4, ymm4) vxorps(ymm5, ymm5, ymm5) vxorps(ymm6, ymm6, ymm6) vxorps(ymm7, ymm7, ymm7) vxorps(ymm8, ymm8, ymm8) vxorps(ymm9, ymm9, ymm9) vxorps(ymm10, ymm10, ymm10) vxorps(ymm11, ymm11, ymm11) vxorps(ymm12, ymm12, ymm12) vxorps(ymm13, ymm13, ymm13) vxorps(ymm14, ymm14, ymm14) vxorps(ymm15, ymm15, ymm15) mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored prefetching on c lea(mem(rcx, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 3*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 3*8)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 3*8)) // prefetch c + 3*rs_c prefetch(0, mem(rdx, rdi, 1, 3*8)) // prefetch c + 4*rs_c jmp(.SPOSTPFETCH) // jump to end of prefetching c label(.SCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) lea(mem(rcx, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; prefetch(0, mem(rcx, 4*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 4*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 4*8)) // prefetch c + 2*cs_c prefetch(0, mem(rdx, 4*8)) // prefetch c + 3*cs_c label(.SPOSTPFETCH) // done prefetching c mov(r9, rsi) // rsi = rs_b; sal(imm(5), rsi) // rsi = 16*rs_b; lea(mem(rax, rsi, 1), rdx) // rdx = b + 16*rs_b; mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) vbroadcastss(mem(rax, r13, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm8) vfmadd231ps(xmm0, xmm3, xmm10) vbroadcastss(mem(rax, r8, 4), xmm2) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm12) // ---------------------------------- iteration 1 vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) vbroadcastss(mem(rax, r13, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm8) vfmadd231ps(xmm0, xmm3, xmm10) vbroadcastss(mem(rax, r8, 4), xmm2) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm12) // ---------------------------------- iteration 2 vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) vbroadcastss(mem(rax, r13, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm8) vfmadd231ps(xmm0, xmm3, xmm10) vbroadcastss(mem(rax, r8, 4), xmm2) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm12) // ---------------------------------- iteration 3 vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) vbroadcastss(mem(rax, r13, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm8) vfmadd231ps(xmm0, xmm3, xmm10) vbroadcastss(mem(rax, r8, 4), xmm2) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm12) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) vbroadcastss(mem(rax, r13, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm8) vfmadd231ps(xmm0, xmm3, xmm10) vbroadcastss(mem(rax, r8, 4), xmm2) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm12) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), ymm0) // load alpha and duplicate vbroadcastss(mem(rbx), ymm3) // load beta and duplicate vmulps(xmm0, xmm4, xmm4) // scale by alpha vmulps(xmm0, xmm6, xmm6) vmulps(xmm0, xmm8, xmm8) vmulps(xmm0, xmm10, xmm10) vmulps(xmm0, xmm12, xmm12) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorps(xmm0, xmm0, xmm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vfmadd231ps(mem(rcx), xmm3, xmm4) vmovups(xmm4, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), xmm3, xmm6) vmovups(xmm6, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), xmm3, xmm8) vmovups(xmm8, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), xmm3, xmm10) vmovups(xmm10, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), xmm3, xmm12) vmovups(xmm12, mem(rcx)) jmp(.SDONE) // jump to end. label(.SCOLSTORED) vunpcklps(xmm6, xmm4, xmm0)//a0b0a1b1 vunpcklps(xmm10, xmm8, xmm1)//c0d0c1d1 vunpcklpd(xmm1, xmm0, xmm2)//a0b0c0d0 vunpckhpd(xmm1, xmm0, xmm5)//a1b1c1d1 vfmadd231ps(mem(rcx), xmm3, xmm2) vfmadd231ps(mem(rcx, rsi, 1), xmm3, xmm5) vmovups(xmm2, mem(rcx)) vmovups(xmm5, mem(rcx, rsi, 1)) lea(mem(rcx, rsi, 2), rcx) // rcx += 2*cs_c vunpckhps(xmm6, xmm4, xmm0)//a2b2a3b3 vunpckhps(xmm10, xmm8, xmm1)//c2d2c3d3 vunpcklpd(xmm1, xmm0, xmm7)//a2b2c2d2 vunpckhpd(xmm1, xmm0, xmm9)//a3b3c3d3 vfmadd231ps(mem(rcx), xmm3, xmm7) vfmadd231ps(mem(rcx, rsi, 1), xmm3, xmm9) vmovups(xmm7, mem(rcx)) vmovups(xmm9, mem(rcx, rsi, 1)) vmovss(mem(rdx),xmm2) vmovss(mem(rdx, rsi, 1),xmm4) vmovss(mem(rdx, rsi, 2),xmm6) vmovss(mem(rdx, rax, 1),xmm8) vshufps(imm(0x01), xmm12, xmm12,xmm1) vshufps(imm(0x02), xmm12, xmm12,xmm5) vshufps(imm(0x03), xmm12, xmm12,xmm7) vfmadd231ps(xmm2, xmm3, xmm12) vfmadd231ps(xmm4, xmm3, xmm1) vfmadd231ps(xmm6, xmm3, xmm5) vfmadd231ps(xmm8, xmm3, xmm7) vmovss(xmm12, mem(rdx)) //e0 vmovss(xmm1, mem(rdx, rsi, 1)) //e1 vmovss(xmm5, mem(rdx, rsi, 2)) //e2 vmovss(xmm7, mem(rdx, rax, 1)) //e3 jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovups(xmm4, mem(rcx)) add(rdi, rcx) vmovups(xmm6, mem(rcx)) add(rdi, rcx) vmovups(xmm8, mem(rcx)) add(rdi, rcx) vmovups(xmm10, mem(rcx)) add(rdi, rcx) vmovups(xmm12, mem(rcx)) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) vunpcklps(xmm6, xmm4, xmm0)//a0b0a1b1 vunpcklps(xmm10, xmm8, xmm1)//c0d0c1d1 vunpcklpd(xmm1, xmm0, xmm2)//a0b0c0d0 vunpckhpd(xmm1, xmm0, xmm5)//a1b1c1d1 vmovups(xmm2, mem(rcx)) vmovups(xmm5, mem(rcx, rsi, 1)) lea(mem(rcx, rsi, 2), rcx) // rcx += 2*cs_c vunpckhps(xmm6, xmm4, xmm0)//a2b2a3b3 vunpckhps(xmm10, xmm8, xmm1)//c2d2c3d3 vunpcklpd(xmm1, xmm0, xmm7)//a2b2c2d2 vunpckhpd(xmm1, xmm0, xmm9)//a3b3c3d3 vmovups(xmm7, mem(rcx)) vmovups(xmm9, mem(rcx, rsi, 1)) vshufps(imm(0x01), xmm12, xmm12,xmm1) vshufps(imm(0x02), xmm12, xmm12,xmm5) vshufps(imm(0x03), xmm12, xmm12,xmm7) vmovss(xmm12, mem(rdx)) //e0 vmovss(xmm1, mem(rdx, rsi, 1)) //e1 vmovss(xmm5, mem(rdx, rsi, 2)) //e2 vmovss(xmm7, mem(rdx, rax, 1)) //e3 label(.SDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_sgemmsup_rv_zen_asm_4x4 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vxorps(ymm4, ymm4, ymm4) vxorps(ymm5, ymm5, ymm5) vxorps(ymm6, ymm6, ymm6) vxorps(ymm7, ymm7, ymm7) vxorps(ymm8, ymm8, ymm8) vxorps(ymm9, ymm9, ymm9) vxorps(ymm10, ymm10, ymm10) vxorps(ymm11, ymm11, ymm11) vxorps(ymm12, ymm12, ymm12) vxorps(ymm13, ymm13, ymm13) vxorps(ymm14, ymm14, ymm14) vxorps(ymm15, ymm15, ymm15) mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored prefetching on c lea(mem(rcx, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 3*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 3*8)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 3*8)) // prefetch c + 3*rs_c jmp(.SPOSTPFETCH) // jump to end of prefetching c label(.SCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) lea(mem(rcx, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 3*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 3*8)) // prefetch c + 2*cs_c prefetch(0, mem(rdx, 3*8)) // prefetch c + 3*cs_c label(.SPOSTPFETCH) // done prefetching c mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) vbroadcastss(mem(rax, r13, 1), xmm3) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm8) vfmadd231ps(xmm0, xmm3, xmm10) // ---------------------------------- iteration 1 vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) vbroadcastss(mem(rax, r13, 1), xmm3) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm8) vfmadd231ps(xmm0, xmm3, xmm10) // ---------------------------------- iteration 2 vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) vbroadcastss(mem(rax, r13, 1), xmm3) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm8) vfmadd231ps(xmm0, xmm3, xmm10) // ---------------------------------- iteration 3 vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) vbroadcastss(mem(rax, r13, 1), xmm3) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm8) vfmadd231ps(xmm0, xmm3, xmm10) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) vbroadcastss(mem(rax, r13, 1), xmm3) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm8) vfmadd231ps(xmm0, xmm3, xmm10) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), xmm0) // load alpha and duplicate vbroadcastss(mem(rbx), xmm3) // load beta and duplicate vmulps(xmm0, xmm4, xmm4) // scale by alpha vmulps(xmm0, xmm6, xmm6) vmulps(xmm0, xmm8, xmm8) vmulps(xmm0, xmm10, xmm10) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorps(xmm0, xmm0, xmm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vfmadd231ps(mem(rcx), xmm3, xmm4) vmovups(xmm4, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), xmm3, xmm6) vmovups(xmm6, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), xmm3, xmm8) vmovups(xmm8, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), xmm3, xmm10) vmovups(xmm10, mem(rcx)) jmp(.SDONE) // jump to end. label(.SCOLSTORED) vunpcklps(xmm6, xmm4, xmm0)//a0b0a1b1 vunpcklps(xmm10, xmm8, xmm1)//c0d0c1d1 vunpcklpd(xmm1, xmm0, xmm2)//a0b0c0d0 vunpckhpd(xmm1, xmm0, xmm5)//a1b1c1d1 vfmadd231ps(mem(rcx), xmm3, xmm2) vfmadd231ps(mem(rcx, rsi, 1), xmm3, xmm5) vmovups(xmm2, mem(rcx)) vmovups(xmm5, mem(rcx, rsi, 1)) lea(mem(rcx, rsi, 2), rcx) // rcx += 2*cs_c vunpckhps(xmm6, xmm4, xmm0)//a2b2a3b3 vunpckhps(xmm10, xmm8, xmm1)//c2d2c3d3 vunpcklpd(xmm1, xmm0, xmm7)//a2b2c2d2 vunpckhpd(xmm1, xmm0, xmm9)//a3b3c3d3 vfmadd231ps(mem(rcx), xmm3, xmm7) vfmadd231ps(mem(rcx, rsi, 1), xmm3, xmm9) vmovups(xmm7, mem(rcx)) vmovups(xmm9, mem(rcx, rsi, 1)) jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovups(xmm4, mem(rcx)) add(rdi, rcx) vmovups(xmm6, mem(rcx)) add(rdi, rcx) vmovups(xmm8, mem(rcx)) add(rdi, rcx) vmovups(xmm10, mem(rcx)) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) vunpcklps(xmm6, xmm4, xmm0)//a0b0a1b1 vunpcklps(xmm10, xmm8, xmm1)//c0d0c1d1 vunpcklpd(xmm1, xmm0, xmm2)//a0b0c0d0 vunpckhpd(xmm1, xmm0, xmm5)//a1b1c1d1 vmovups(xmm2, mem(rcx)) vmovups(xmm5, mem(rcx, rsi, 1)) lea(mem(rcx, rsi, 2), rcx) // rcx += 2*cs_c vunpckhps(xmm6, xmm4, xmm0)//a2b2a3b3 vunpckhps(xmm10, xmm8, xmm1)//c2d2c3d3 vunpcklpd(xmm1, xmm0, xmm7)//a2b2c2d2 vunpckhpd(xmm1, xmm0, xmm9)//a3b3c3d3 vmovups(xmm7, mem(rcx)) vmovups(xmm9, mem(rcx, rsi, 1)) label(.SDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_sgemmsup_rv_zen_asm_3x4 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vxorps(ymm4, ymm4, ymm4) vxorps(ymm5, ymm5, ymm5) vxorps(ymm6, ymm6, ymm6) vxorps(ymm7, ymm7, ymm7) vxorps(ymm8, ymm8, ymm8) vxorps(ymm9, ymm9, ymm9) vxorps(ymm10, ymm10, ymm10) vxorps(ymm11, ymm11, ymm11) vxorps(ymm12, ymm12, ymm12) vxorps(ymm13, ymm13, ymm13) vxorps(ymm14, ymm14, ymm14) vxorps(ymm15, ymm15, ymm15) mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored prefetching on c prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 3*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 3*8)) // prefetch c + 2*rs_c jmp(.SPOSTPFETCH) // jump to end of prefetching c label(.SCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) lea(mem(rcx, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; prefetch(0, mem(rcx, 2*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 2*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 2*8)) // prefetch c + 2*cs_c prefetch(0, mem(rdx, 2*8)) // prefetch c + 3*cs_c label(.SPOSTPFETCH) // done prefetching c mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm8) // ---------------------------------- iteration 1 vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm8) // ---------------------------------- iteration 2 vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm8) // ---------------------------------- iteration 3 vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm8) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm8) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), xmm0) // load alpha and duplicate vbroadcastss(mem(rbx), xmm3) // load beta and duplicate vmulps(xmm0, xmm4, xmm4) // scale by alpha vmulps(xmm0, xmm6, xmm6) vmulps(xmm0, xmm8, xmm8) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) lea(mem(rcx, rdi, 2), rdx) // load address of c + 2*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorps(xmm0, xmm0, xmm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vfmadd231ps(mem(rcx), xmm3, xmm4) vmovups(xmm4, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), xmm3, xmm6) vmovups(xmm6, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), xmm3, xmm8) vmovups(xmm8, mem(rcx)) jmp(.SDONE) // jump to end. label(.SCOLSTORED) vunpcklps(xmm6, xmm4, xmm0)//e0f0e1f1 vunpckhps(xmm6, xmm4, xmm1)//e2f2e3f3 vmovsd(mem(rcx),xmm2) vmovsd(mem(rcx, rsi, 1),xmm4) vmovsd(mem(rcx, rsi, 2),xmm6) vmovsd(mem(rcx, rax, 1),xmm10) vshufpd(imm(0x01), xmm0, xmm0, xmm5)//e1f1 vshufpd(imm(0x01), xmm1, xmm1, xmm7)//e3f3 vfmadd231ps(xmm2, xmm3, xmm0) vfmadd231ps(xmm4, xmm3, xmm5) vfmadd231ps(xmm6, xmm3, xmm1) vfmadd231ps(xmm10, xmm3, xmm7) vmovsd(xmm0, mem(rcx)) //e0f0 vmovsd(xmm5, mem(rcx, rsi, 1)) //e1f1 vmovsd(xmm1, mem(rcx, rsi, 2)) //e2f2 vmovsd(xmm7, mem(rcx, rax, 1)) //e3f3 vmovss(mem(rdx),xmm2) vmovss(mem(rdx, rsi, 1),xmm4) vmovss(mem(rdx, rsi, 2),xmm6) vmovss(mem(rdx, rax, 1),xmm10) vshufps(imm(0x01), xmm8, xmm8,xmm1) vshufps(imm(0x02), xmm8, xmm8,xmm5) vshufps(imm(0x03), xmm8, xmm8,xmm7) vfmadd231ps(xmm2, xmm3, xmm8) vfmadd231ps(xmm4, xmm3, xmm1) vfmadd231ps(xmm6, xmm3, xmm5) vfmadd231ps(xmm10, xmm3, xmm7) vmovss(xmm8, mem(rdx)) //e0 vmovss(xmm1, mem(rdx, rsi, 1)) //e1 vmovss(xmm5, mem(rdx, rsi, 2)) //e2 vmovss(xmm7, mem(rdx, rax, 1)) //e3 jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovups(xmm4, mem(rcx)) add(rdi, rcx) vmovups(xmm6, mem(rcx)) add(rdi, rcx) vmovups(xmm8, mem(rcx)) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) vunpcklps(xmm6, xmm4, xmm0)//e0f0e1f1 vunpckhps(xmm6, xmm4, xmm1)//e2f2e3f3 vshufpd(imm(0x01), xmm0, xmm0, xmm5)//e1f1 vshufpd(imm(0x01), xmm1, xmm1, xmm7)//e3f3 vmovsd(xmm0, mem(rcx)) //e0f0 vmovsd(xmm5, mem(rcx, rsi, 1)) //e1f1 vmovsd(xmm1, mem(rcx, rsi, 2)) //e2f2 vmovsd(xmm7, mem(rcx, rax, 1)) //e3f3 vshufps(imm(0x01), xmm8, xmm8,xmm1) vshufps(imm(0x02), xmm8, xmm8,xmm5) vshufps(imm(0x03), xmm8, xmm8,xmm7) vmovss(xmm8, mem(rdx)) //e0 vmovss(xmm1, mem(rdx, rsi, 1)) //e1 vmovss(xmm5, mem(rdx, rsi, 2)) //e2 vmovss(xmm7, mem(rdx, rax, 1)) //e3 label(.SDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_sgemmsup_rv_zen_asm_2x4 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vxorps(ymm4, ymm4, ymm4) vxorps(ymm5, ymm5, ymm5) vxorps(ymm6, ymm6, ymm6) vxorps(ymm7, ymm7, ymm7) vxorps(ymm8, ymm8, ymm8) vxorps(ymm9, ymm9, ymm9) vxorps(ymm10, ymm10, ymm10) vxorps(ymm11, ymm11, ymm11) vxorps(ymm12, ymm12, ymm12) vxorps(ymm13, ymm13, ymm13) vxorps(ymm14, ymm14, ymm14) vxorps(ymm15, ymm15, ymm15) mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored prefetching on c prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 3*8)) // prefetch c + 1*rs_c jmp(.SPOSTPFETCH) // jump to end of prefetching c label(.SCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) lea(mem(rcx, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; prefetch(0, mem(rcx, 1*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 1*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 1*8)) // prefetch c + 2*cs_c prefetch(0, mem(rdx, 1*8)) // prefetch c + 3*cs_c label(.SPOSTPFETCH) // done prefetching c mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) // ---------------------------------- iteration 1 vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) // ---------------------------------- iteration 2 vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) // ---------------------------------- iteration 3 vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), xmm0) // load alpha and duplicate vbroadcastss(mem(rbx), xmm3) // load beta and duplicate vmulps(xmm0, xmm4, xmm4) // scale by alpha vmulps(xmm0, xmm6, xmm6) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorps(xmm0, xmm0, xmm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vfmadd231ps(mem(rcx), xmm3, xmm4) vmovups(xmm4, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), xmm3, xmm6) vmovups(xmm6, mem(rcx)) jmp(.SDONE) // jump to end. label(.SCOLSTORED) vunpcklps(xmm6, xmm4, xmm0)//e0f0e1f1 vunpckhps(xmm6, xmm4, xmm1)//e2f2e3f3 vmovsd(mem(rcx),xmm2) vmovsd(mem(rcx, rsi, 1),xmm4) vmovsd(mem(rcx, rsi, 2),xmm6) vmovsd(mem(rcx, rax, 1),xmm10) vshufpd(imm(0x01), xmm0, xmm0, xmm5)//e1f1 vshufpd(imm(0x01), xmm1, xmm1, xmm7)//e3f3 vfmadd231ps(xmm2, xmm3, xmm0) vfmadd231ps(xmm4, xmm3, xmm5) vfmadd231ps(xmm6, xmm3, xmm1) vfmadd231ps(xmm10, xmm3, xmm7) vmovsd(xmm0, mem(rcx)) //e0f0 vmovsd(xmm5, mem(rcx, rsi, 1)) //e1f1 vmovsd(xmm1, mem(rcx, rsi, 2)) //e2f2 vmovsd(xmm7, mem(rcx, rax, 1)) //e3f3 jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovups(xmm4, mem(rcx)) add(rdi, rcx) vmovups(xmm6, mem(rcx)) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) vunpcklps(xmm6, xmm4, xmm0)//e0f0e1f1 vunpckhps(xmm6, xmm4, xmm1)//e2f2e3f3 vshufpd(imm(0x01), xmm0, xmm0, xmm5)//e1f1 vshufpd(imm(0x01), xmm1, xmm1, xmm7)//e3f3 vmovsd(xmm0, mem(rcx)) //e0f0 vmovsd(xmm5, mem(rcx, rsi, 1)) //e1f1 vmovsd(xmm1, mem(rcx, rsi, 2)) //e2f2 vmovsd(xmm7, mem(rcx, rax, 1)) //e3f3 label(.SDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_sgemmsup_rv_zen_asm_1x4 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vxorps(ymm4, ymm4, ymm4) vxorps(ymm5, ymm5, ymm5) vxorps(ymm6, ymm6, ymm6) vxorps(ymm7, ymm7, ymm7) vxorps(ymm8, ymm8, ymm8) vxorps(ymm9, ymm9, ymm9) vxorps(ymm10, ymm10, ymm10) vxorps(ymm11, ymm11, ymm11) vxorps(ymm12, ymm12, ymm12) vxorps(ymm13, ymm13, ymm13) vxorps(ymm14, ymm14, ymm14) vxorps(ymm15, ymm15, ymm15) mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored prefetching on c prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*rs_c jmp(.SPOSTPFETCH) // jump to end of prefetching c label(.SCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) lea(mem(rcx, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; prefetch(0, mem(rcx, 0*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 0*8)) // prefetch c + 1*cs_c prefetch(0, mem(rcx, rsi, 2, 0*8)) // prefetch c + 2*cs_c prefetch(0, mem(rdx, 0*8)) // prefetch c + 3*cs_c label(.SPOSTPFETCH) // done prefetching c mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm4) // ---------------------------------- iteration 1 vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm4) // ---------------------------------- iteration 2 vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm4) // ---------------------------------- iteration 3 vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm4) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm4) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), ymm0) // load alpha and duplicate vbroadcastss(mem(rbx), ymm3) // load beta and duplicate vmulps(xmm0, xmm4, xmm4) // scale by alpha mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorps(xmm0, xmm0, xmm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vfmadd231ps(mem(rcx), xmm3, xmm4) vmovups(xmm4, mem(rcx)) jmp(.SDONE) // jump to end. label(.SCOLSTORED) vmovss(mem(rcx),xmm2) vmovss(mem(rcx, rsi, 1),xmm6) vmovss(mem(rcx, rsi, 2),xmm8) vmovss(mem(rcx, rax, 1),xmm10) vshufps(imm(0x01), xmm4, xmm4,xmm1) vshufps(imm(0x02), xmm4, xmm4,xmm5) vshufps(imm(0x03), xmm4, xmm4,xmm7) vfmadd231ps(xmm2, xmm3, xmm4) vfmadd231ps(xmm6, xmm3, xmm1) vfmadd231ps(xmm8, xmm3, xmm5) vfmadd231ps(xmm10, xmm3, xmm7) vmovss(xmm4, mem(rcx)) //e0 vmovss(xmm1, mem(rcx, rsi, 1)) //e1 vmovss(xmm5, mem(rcx, rsi, 2)) //e2 vmovss(xmm7, mem(rcx, rax, 1)) //e3 jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovups(xmm4, mem(rcx)) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) vshufps(imm(0x01), xmm4, xmm4,xmm1) vshufps(imm(0x02), xmm4, xmm4,xmm5) vshufps(imm(0x03), xmm4, xmm4,xmm7) vmovss(xmm4, mem(rcx)) //e0 vmovss(xmm1, mem(rcx, rsi, 1)) //e1 vmovss(xmm5, mem(rcx, rsi, 2)) //e2 vmovss(xmm7, mem(rcx, rax, 1)) //e3 label(.SDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_sgemmsup_rv_zen_asm_6x2 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vxorps(ymm4, ymm4, ymm4) vxorps(ymm5, ymm5, ymm5) vxorps(ymm6, ymm6, ymm6) vxorps(ymm7, ymm7, ymm7) vxorps(ymm8, ymm8, ymm8) vxorps(ymm9, ymm9, ymm9) vxorps(ymm10, ymm10, ymm10) vxorps(ymm11, ymm11, ymm11) vxorps(ymm12, ymm12, ymm12) vxorps(ymm13, ymm13, ymm13) vxorps(ymm14, ymm14, ymm14) vxorps(ymm15, ymm15, ymm15) mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored prefetching on c lea(mem(rcx, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 1*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 1*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 1*8)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 1*8)) // prefetch c + 3*rs_c prefetch(0, mem(rdx, rdi, 1, 1*8)) // prefetch c + 4*rs_c prefetch(0, mem(rdx, rdi, 2, 1*8)) // prefetch c + 5*rs_c jmp(.SPOSTPFETCH) // jump to end of prefetching c label(.SCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) prefetch(0, mem(rcx, 5*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 5*8)) // prefetch c + 1*cs_c label(.SPOSTPFETCH) // done prefetching c mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) vbroadcastss(mem(rax, r13, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm8) vfmadd231ps(xmm0, xmm3, xmm10) vbroadcastss(mem(rax, r8, 4), xmm2) vbroadcastss(mem(rax, r15, 1), xmm3) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm12) vfmadd231ps(xmm0, xmm3, xmm14) // ---------------------------------- iteration 1 vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) vbroadcastss(mem(rax, r13, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm8) vfmadd231ps(xmm0, xmm3, xmm10) vbroadcastss(mem(rax, r8, 4), xmm2) vbroadcastss(mem(rax, r15, 1), xmm3) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm12) vfmadd231ps(xmm0, xmm3, xmm14) // ---------------------------------- iteration 2 vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) vbroadcastss(mem(rax, r13, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm8) vfmadd231ps(xmm0, xmm3, xmm10) vbroadcastss(mem(rax, r8, 4), xmm2) vbroadcastss(mem(rax, r15, 1), xmm3) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm12) vfmadd231ps(xmm0, xmm3, xmm14) // ---------------------------------- iteration 3 vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) vbroadcastss(mem(rax, r13, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm8) vfmadd231ps(xmm0, xmm3, xmm10) vbroadcastss(mem(rax, r8, 4), xmm2) vbroadcastss(mem(rax, r15, 1), xmm3) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm12) vfmadd231ps(xmm0, xmm3, xmm14) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) vbroadcastss(mem(rax, r13, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm8) vfmadd231ps(xmm0, xmm3, xmm10) vbroadcastss(mem(rax, r8, 4), xmm2) vbroadcastss(mem(rax, r15, 1), xmm3) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm12) vfmadd231ps(xmm0, xmm3, xmm14) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), xmm0) // load alpha and duplicate vbroadcastss(mem(rbx), xmm3) // load beta and duplicate vmulps(xmm0, xmm4, xmm4) // scale by alpha vmulps(xmm0, xmm6, xmm6) vmulps(xmm0, xmm8, xmm8) vmulps(xmm0, xmm10, xmm10) vmulps(xmm0, xmm12, xmm12) vmulps(xmm0, xmm14, xmm14) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) // now avoid loading C if beta == 0 vxorps(xmm0, xmm0, xmm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vmovsd(mem(rcx), xmm0)////a0a1 vfmadd231ps(xmm0, xmm3, xmm4)//c*beta+(a0a1) vmovsd(xmm4, mem(rcx))//a0a1 add(rdi, rcx) vmovsd(mem(rcx), xmm0) vfmadd231ps(xmm0, xmm3, xmm6) vmovsd(xmm6, mem(rcx)) add(rdi, rcx) vmovsd(mem(rcx), xmm0) vfmadd231ps(xmm0, xmm3, xmm8) vmovsd(xmm8, mem(rcx)) add(rdi, rcx) vmovsd(mem(rcx), xmm0) vfmadd231ps(xmm0, xmm3, xmm10) vmovsd(xmm10, mem(rcx)) add(rdi, rcx) vmovsd(mem(rcx), xmm0) vfmadd231ps(xmm0, xmm3, xmm12) vmovsd(xmm12, mem(rcx)) add(rdi, rcx) vmovsd(mem(rcx), xmm0) vfmadd231ps(xmm0, xmm3, xmm14) vmovsd(xmm14, mem(rcx)) jmp(.SDONE) // jump to end. label(.SCOLSTORED) vunpcklps(xmm6, xmm4, xmm0)//a0b0a1b1 vunpcklps(xmm10, xmm8, xmm1)//c0d0c1d1 vunpcklps(xmm14, xmm12, xmm2)//e0f0 vmovsd(mem(rcx),xmm4) vmovsd(mem(rcx, rdi, 2),xmm6) vmovsd(mem(rcx, rdi, 4),xmm8) vshufpd(imm(0x01), xmm0, xmm0, xmm5)//a1b1 vshufpd(imm(0x01), xmm1, xmm1, xmm7)//c1d1 vshufpd(imm(0x01), xmm2, xmm2, xmm9)//e1f1 vfmadd231ps(xmm4, xmm3, xmm0) vfmadd231ps(xmm6, xmm3, xmm1) vfmadd231ps(xmm8, xmm3, xmm2) vmovsd(xmm0, mem(rcx)) //a0b0 vmovsd(xmm1, mem(rcx, rdi, 2)) //c0d0 vmovsd(xmm2, mem(rcx, rdi, 4)) //e0f0 lea(mem(rcx, rsi, 1), rcx) vmovsd(mem(rcx),xmm4) vmovsd(mem(rcx, rdi, 2),xmm6) vmovsd(mem(rcx, rdi, 4),xmm8) vfmadd231ps(xmm4, xmm3, xmm5) vfmadd231ps(xmm6, xmm3, xmm7) vfmadd231ps(xmm8, xmm3, xmm9) vmovsd(xmm5, mem(rcx)) //a1b1 vmovsd(xmm7, mem(rcx, rdi, 2)) //c1d1 vmovsd(xmm9, mem(rcx, rdi, 4)) //e1f1 jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovsd(xmm4, mem(rcx)) add(rdi, rcx) vmovsd(xmm6, mem(rcx)) add(rdi, rcx) vmovsd(xmm8, mem(rcx)) add(rdi, rcx) vmovsd(xmm10, mem(rcx)) add(rdi, rcx) vmovsd(xmm12, mem(rcx)) add(rdi, rcx) vmovsd(xmm14, mem(rcx)) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) vunpcklps(xmm6, xmm4, xmm0)//a0b0a1b1 vunpcklps(xmm10, xmm8, xmm1)//c0d0c1d1 vunpcklps(xmm14, xmm12, xmm2)//e0f0 vshufpd(imm(0x01), xmm0, xmm0, xmm5)//a1b1 vshufpd(imm(0x01), xmm1, xmm1, xmm7)//c1d1 vshufpd(imm(0x01), xmm2, xmm2, xmm9)//e1f1 vmovsd(xmm0, mem(rcx)) //a0b0 vmovsd(xmm1, mem(rcx, rdi, 2)) //c0d0 vmovsd(xmm2, mem(rcx, rdi, 4)) //e0f0 lea(mem(rcx, rsi, 1), rcx) vmovsd(xmm5, mem(rcx)) //e0f0 vmovsd(xmm7, mem(rcx, rdi, 2)) //e1f1 vmovsd(xmm9, mem(rcx, rdi, 4)) //e0f0 label(.SDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_sgemmsup_rv_zen_asm_5x2 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vxorps(ymm4, ymm4, ymm4) vxorps(ymm5, ymm5, ymm5) vxorps(ymm6, ymm6, ymm6) vxorps(ymm7, ymm7, ymm7) vxorps(ymm8, ymm8, ymm8) vxorps(ymm9, ymm9, ymm9) vxorps(ymm10, ymm10, ymm10) vxorps(ymm11, ymm11, ymm11) vxorps(ymm12, ymm12, ymm12) vxorps(ymm13, ymm13, ymm13) vxorps(ymm14, ymm14, ymm14) vxorps(ymm15, ymm15, ymm15) mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored prefetching on c lea(mem(rcx, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 1*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 1*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 1*8)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 1*8)) // prefetch c + 3*rs_c prefetch(0, mem(rdx, rdi, 1, 1*8)) // prefetch c + 4*rs_c jmp(.SPOSTPFETCH) // jump to end of prefetching c label(.SCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) prefetch(0, mem(rcx, 4*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 4*8)) // prefetch c + 1*cs_c label(.SPOSTPFETCH) // done prefetching c mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) vbroadcastss(mem(rax, r13, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm8) vfmadd231ps(xmm0, xmm3, xmm10) vbroadcastss(mem(rax, r8, 4), xmm2) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm12) // ---------------------------------- iteration 1 vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) vbroadcastss(mem(rax, r13, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm8) vfmadd231ps(xmm0, xmm3, xmm10) vbroadcastss(mem(rax, r8, 4), xmm2) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm12) // ---------------------------------- iteration 2 vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) vbroadcastss(mem(rax, r13, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm8) vfmadd231ps(xmm0, xmm3, xmm10) vbroadcastss(mem(rax, r8, 4), xmm2) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm12) // ---------------------------------- iteration 3 vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) vbroadcastss(mem(rax, r13, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm8) vfmadd231ps(xmm0, xmm3, xmm10) vbroadcastss(mem(rax, r8, 4), xmm2) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm12) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) vbroadcastss(mem(rax, r13, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm8) vfmadd231ps(xmm0, xmm3, xmm10) vbroadcastss(mem(rax, r8, 4), xmm2) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm12) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), xmm0) // load alpha and duplicate vbroadcastss(mem(rbx), xmm3) // load beta and duplicate vmulps(xmm0, xmm4, xmm4) // scale by alpha vmulps(xmm0, xmm6, xmm6) vmulps(xmm0, xmm8, xmm8) vmulps(xmm0, xmm10, xmm10) vmulps(xmm0, xmm12, xmm12) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; // now avoid loading C if beta == 0 vxorps(xmm0, xmm0, xmm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vmovsd(mem(rcx), xmm0)////a0a1 vfmadd231ps(xmm0, xmm3, xmm4)//c*beta+(a0a1) vmovsd(xmm4, mem(rcx))//a0a1 add(rdi, rcx) vmovsd(mem(rcx), xmm0) vfmadd231ps(xmm0, xmm3, xmm6) vmovsd(xmm6, mem(rcx)) add(rdi, rcx) vmovsd(mem(rcx), xmm0) vfmadd231ps(xmm0, xmm3, xmm8) vmovsd(xmm8, mem(rcx)) add(rdi, rcx) vmovsd(mem(rcx), xmm0) vfmadd231ps(xmm0, xmm3, xmm10) vmovsd(xmm10, mem(rcx)) add(rdi, rcx) vmovsd(mem(rcx), xmm0) vfmadd231ps(xmm0, xmm3, xmm12) vmovsd(xmm12, mem(rcx)) add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORED) vunpcklps(xmm6, xmm4, xmm0)//a0b0a1b1 vunpcklps(xmm10, xmm8, xmm1)//c0d0c1d1 vmovsd(mem(rcx),xmm4) vmovsd(mem(rcx, rdi, 2),xmm6) vshufpd(imm(0x01), xmm0, xmm0, xmm5)//a1b1 vshufpd(imm(0x01), xmm1, xmm1, xmm7)//c1d1 vfmadd231ps(xmm4, xmm3, xmm0) vfmadd231ps(xmm6, xmm3, xmm1) vmovsd(xmm0, mem(rcx)) //a0b0 vmovsd(xmm1, mem(rcx, rdi, 2)) //c0d0 vmovss(mem(rcx, rdi, 4),xmm4) vshufps(imm(0x01), xmm12, xmm12, xmm9)//e1 vfmadd231ps(xmm4, xmm3, xmm12) vmovss(xmm12,mem(rcx,rdi,4))//e0 lea(mem(rcx, rsi, 1), rcx) vmovsd(mem(rcx),xmm4) vmovsd(mem(rcx, rdi, 2),xmm6) vfmadd231ps(xmm4, xmm3, xmm5) vfmadd231ps(xmm6, xmm3, xmm7) vmovsd(xmm5, mem(rcx)) //a1b1 vmovsd(xmm7, mem(rcx, rdi, 2)) //c1d1 vmovss( mem(rcx, rdi, 4),xmm4) vfmadd231ps(xmm4, xmm3, xmm9) vmovss(xmm9,mem(rcx,rdi,4))//e1 jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovsd(xmm4, mem(rcx))//a0a1 add(rdi, rcx) vmovsd(xmm6, mem(rcx)) add(rdi, rcx) vmovsd(xmm8, mem(rcx)) add(rdi, rcx) vmovsd(xmm10, mem(rcx)) add(rdi, rcx) vmovsd(xmm12, mem(rcx)) add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) vunpcklps(xmm6, xmm4, xmm0)//a0b0a1b1 vunpcklps(xmm10, xmm8, xmm1)//c0d0c1d1 vshufpd(imm(0x01), xmm0, xmm0, xmm5)//a1b1 vshufpd(imm(0x01), xmm1, xmm1, xmm7)//c1d1 vmovsd(xmm0, mem(rcx)) //a0b0 vmovsd(xmm1, mem(rcx, rdi, 2)) //c0d0 vshufps(imm(0x01), xmm12, xmm12, xmm9)//e1 vmovss(xmm12,mem(rcx,rdi,4))//e0 lea(mem(rcx, rsi, 1), rcx) vmovsd(xmm5, mem(rcx)) //a1b1 vmovsd(xmm7, mem(rcx, rdi, 2)) //c1d1 vmovss(xmm9,mem(rcx,rdi,4))//e1 label(.SDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_sgemmsup_rv_zen_asm_4x2 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vxorps(ymm4, ymm4, ymm4) vxorps(ymm5, ymm5, ymm5) vxorps(ymm6, ymm6, ymm6) vxorps(ymm7, ymm7, ymm7) vxorps(ymm8, ymm8, ymm8) vxorps(ymm9, ymm9, ymm9) vxorps(ymm10, ymm10, ymm10) vxorps(ymm11, ymm11, ymm11) vxorps(ymm12, ymm12, ymm12) vxorps(ymm13, ymm13, ymm13) vxorps(ymm14, ymm14, ymm14) vxorps(ymm15, ymm15, ymm15) mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored prefetching on c lea(mem(rcx, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(rcx, 1*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 1*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 1*8)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 1*8)) // prefetch c + 3*rs_c jmp(.SPOSTPFETCH) // jump to end of prefetching c label(.SCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) lea(mem(rcx, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; prefetch(0, mem(rcx, 3*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 3*8)) // prefetch c + 1*cs_c label(.SPOSTPFETCH) // done prefetching c mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm8) vfmadd231ps(xmm0, xmm3, xmm10) // ---------------------------------- iteration 1 vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm8) vfmadd231ps(xmm0, xmm3, xmm10) // ---------------------------------- iteration 2 vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm8) vfmadd231ps(xmm0, xmm3, xmm10) // ---------------------------------- iteration 3 vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm8) vfmadd231ps(xmm0, xmm3, xmm10) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm8) vfmadd231ps(xmm0, xmm3, xmm10) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), ymm0) // load alpha and duplicate vbroadcastss(mem(rbx), ymm3) // load beta and duplicate vmulps(xmm0, xmm4, xmm4) // scale by alpha vmulps(xmm0, xmm6, xmm6) vmulps(xmm0, xmm8, xmm8) vmulps(xmm0, xmm10, xmm10) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) // now avoid loading C if beta == 0 vxorps(xmm0,xmm0,xmm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vmovsd(mem(rcx), xmm0)////a0a1 vfmadd231ps(xmm0, xmm3, xmm4)//c*beta+(a0a1) vmovsd(xmm4, mem(rcx)) add(rdi, rcx) vmovsd(mem(rcx), xmm0) vfmadd231ps(xmm0, xmm3, xmm6) vmovsd(xmm6, mem(rcx)) add(rdi, rcx) vmovsd(mem(rcx), xmm0) vfmadd231ps(xmm0, xmm3, xmm8) vmovsd(xmm8, mem(rcx)) add(rdi, rcx) vmovsd(mem(rcx), xmm0) vfmadd231ps(xmm0, xmm3, xmm10) vmovsd(xmm10, mem(rcx)) jmp(.SDONE) // jump to end. label(.SCOLSTORED) vunpcklps(xmm6, xmm4, xmm0)//a0b0a1b1 vunpcklps(xmm10, xmm8, xmm1)//c0d0c1d1 vmovsd(mem(rcx),xmm4) vmovsd(mem(rcx, rdi, 2),xmm6) vshufpd(imm(0x01), xmm0, xmm0, xmm5)//a1b1 vshufpd(imm(0x01), xmm1, xmm1, xmm7)//c1d1 vfmadd231ps(xmm4, xmm3, xmm0) vfmadd231ps(xmm6, xmm3, xmm1) vmovsd(xmm0, mem(rcx)) //a0b0 vmovsd(xmm1, mem(rcx, rdi, 2)) //c0d0 lea(mem(rcx, rsi, 1), rcx) vmovsd(mem(rcx),xmm4) vmovsd(mem(rcx, rdi, 2),xmm6) vfmadd231ps(xmm4, xmm3, xmm5) vfmadd231ps(xmm6, xmm3, xmm7) vmovsd(xmm5, mem(rcx)) //a1b1 vmovsd(xmm7, mem(rcx, rdi, 2)) //c1d1 jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovsd(xmm4, mem(rcx)) add(rdi, rcx) vmovsd(xmm6, mem(rcx)) add(rdi, rcx) vmovsd(xmm8, mem(rcx)) add(rdi, rcx) vmovsd(xmm10, mem(rcx)) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) vunpcklps(xmm6, xmm4, xmm0)//a0b0a1b1 vunpcklps(xmm10, xmm8, xmm1)//c0d0c1d1 vshufpd(imm(0x01), xmm0, xmm0, xmm5)//a1b1 vshufpd(imm(0x01), xmm1, xmm1, xmm7)//c1d1 vmovsd(xmm0, mem(rcx)) //a0b0 vmovsd(xmm1, mem(rcx, rdi, 2)) //c0d0 lea(mem(rcx, rsi, 1), rcx) vmovsd(xmm5, mem(rcx)) //a1b1 vmovsd(xmm7, mem(rcx, rdi, 2)) //c1d1 label(.SDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_sgemmsup_rv_zen_asm_3x2 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vxorps(ymm4, ymm4, ymm4) vxorps(ymm5, ymm5, ymm5) vxorps(ymm6, ymm6, ymm6) vxorps(ymm7, ymm7, ymm7) vxorps(ymm8, ymm8, ymm8) vxorps(ymm9, ymm9, ymm9) vxorps(ymm10, ymm10, ymm10) vxorps(ymm11, ymm11, ymm11) vxorps(ymm12, ymm12, ymm12) vxorps(ymm13, ymm13, ymm13) vxorps(ymm14, ymm14, ymm14) vxorps(ymm15, ymm15, ymm15) mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored prefetching on c prefetch(0, mem(rcx, 1*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 1*8)) // prefetch c + 1*rs_c prefetch(0, mem(rcx, rdi, 2, 1*8)) // prefetch c + 2*rs_c jmp(.SPOSTPFETCH) // jump to end of prefetching c label(.SCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) prefetch(0, mem(rcx, 2*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 2*8)) // prefetch c + 1*cs_c label(.SPOSTPFETCH) // done prefetching c mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm8) // ---------------------------------- iteration 1 vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm8) // ---------------------------------- iteration 2 vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm8) // ---------------------------------- iteration 3 vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm8) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm8) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), ymm0) // load alpha and duplicate vbroadcastss(mem(rbx), ymm3) // load beta and duplicate vmulps(xmm0, xmm4, xmm4) // scale by alpha vmulps(xmm0, xmm6, xmm6) vmulps(xmm0, xmm8, xmm8) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) lea(mem(rcx, rdi, 2), rdx) // load address of c + 2*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vfmadd231ps(mem(rcx), xmm3, xmm4) vmovsd(xmm4, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), xmm3, xmm6) vmovsd(xmm6, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), xmm3, xmm8) vmovsd(xmm8, mem(rcx)) jmp(.SDONE) // jump to end. label(.SCOLSTORED) vunpcklps(xmm6, xmm4, xmm0)//a0b0a1b1 vmovsd(mem(rcx),xmm4) vshufpd(imm(0x01), xmm0, xmm0, xmm5)//a1b1 vfmadd231ps(xmm4, xmm3, xmm0) vmovsd(xmm0, mem(rcx)) //a0b0 vmovss(mem(rcx,rdi,2),xmm4) vshufps(imm(0x01), xmm8, xmm8, xmm9)//c1 vfmadd231ps(xmm4, xmm3, xmm8) vmovss(xmm8,mem(rcx,rdi,2))//c0 lea(mem(rcx, rsi, 1), rcx) vmovsd(mem(rcx),xmm4) vfmadd231ps(xmm4, xmm3, xmm5) vmovsd(xmm5, mem(rcx)) //a1b1 vmovss(mem(rcx,rdi,2),xmm4) vfmadd231ps(xmm4, xmm3, xmm9) vmovss(xmm9,mem(rcx,rdi,2))//c1 jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovsd(xmm4, mem(rcx)) add(rdi, rcx) vmovsd(xmm6, mem(rcx)) add(rdi, rcx) vmovsd(xmm8, mem(rcx)) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) vunpcklps(xmm6, xmm4, xmm0)//a0b0a1b1 vshufpd(imm(0x01), xmm0, xmm0, xmm5)//a1b1 vmovsd(xmm0, mem(rcx)) //a0b0 vshufps(imm(0x01), xmm8, xmm8, xmm9)//c1 vmovss(xmm8,mem(rcx,rdi,2))//c0 lea(mem(rcx, rsi, 1), rcx) vmovsd(xmm5, mem(rcx)) //a1b1 vmovss(xmm9,mem(rcx,rdi,2))//c1 label(.SDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_sgemmsup_rv_zen_asm_2x2 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vxorps(ymm4, ymm4, ymm4) vxorps(ymm5, ymm5, ymm5) vxorps(ymm6, ymm6, ymm6) vxorps(ymm7, ymm7, ymm7) vxorps(ymm8, ymm8, ymm8) vxorps(ymm9, ymm9, ymm9) vxorps(ymm10, ymm10, ymm10) vxorps(ymm11, ymm11, ymm11) vxorps(ymm12, ymm12, ymm12) vxorps(ymm13, ymm13, ymm13) vxorps(ymm14, ymm14, ymm14) vxorps(ymm15, ymm15, ymm15) mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored prefetching on c prefetch(0, mem(rcx, 1*8)) // prefetch c + 0*rs_c prefetch(0, mem(rcx, rdi, 1, 1*8)) // prefetch c + 1*rs_c jmp(.SPOSTPFETCH) // jump to end of prefetching c label(.SCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) prefetch(0, mem(rcx, 1*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 1*8)) // prefetch c + 1*cs_c label(.SPOSTPFETCH) // done prefetching c mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) // ---------------------------------- iteration 1 vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) // ---------------------------------- iteration 2 vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) // ---------------------------------- iteration 3 vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), ymm0) // load alpha and duplicate vbroadcastss(mem(rbx), ymm3) // load beta and duplicate vmulps(xmm0, xmm4, xmm4) // scale by alpha vmulps(xmm0, xmm6, xmm6) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vfmadd231ps(mem(rcx), xmm3, xmm4) vmovsd(xmm4, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), xmm3, xmm6) vmovsd(xmm6, mem(rcx)) jmp(.SDONE) // jump to end. label(.SCOLSTORED) vunpcklps(xmm6, xmm4, xmm0)//a0b0a1b1 vmovsd(mem(rcx),xmm4) vshufpd(imm(0x01), xmm0, xmm0, xmm5)//a1b1 vfmadd231ps(xmm4, xmm3, xmm0) vmovsd(xmm0, mem(rcx)) //a0b0 lea(mem(rcx, rsi, 1), rcx) vmovsd(mem(rcx),xmm4) vfmadd231ps(xmm4, xmm3, xmm5) vmovsd(xmm5, mem(rcx)) //a1b1 jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovsd(xmm4, mem(rcx)) add(rdi, rcx) vmovsd(xmm6, mem(rcx)) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) vunpcklps(xmm6, xmm4, xmm0)//a0b0a1b1 vshufpd(imm(0x01), xmm0, xmm0, xmm5)//a1b1 vmovsd(xmm0, mem(rcx)) //a0b0 vmovsd(xmm5, mem(rcx, rsi, 1)) //a1b1 label(.SDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } void bli_sgemmsup_rv_zen_asm_1x2 ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // ------------------------------------------------------------------------- begin_asm() vxorps(ymm4, ymm4, ymm4) vxorps(ymm5, ymm5, ymm5) vxorps(ymm6, ymm6, ymm6) vxorps(ymm7, ymm7, ymm7) vxorps(ymm8, ymm8, ymm8) vxorps(ymm9, ymm9, ymm9) vxorps(ymm10, ymm10, ymm10) vxorps(ymm11, ymm11, ymm11) vxorps(ymm12, ymm12, ymm12) vxorps(ymm13, ymm13, ymm13) vxorps(ymm14, ymm14, ymm14) vxorps(ymm15, ymm15, ymm15) mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) mov(var(b), rbx) // load address of b. mov(var(rs_b), r10) // load rs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), rcx) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored prefetching on c prefetch(0, mem(rcx, 1*8)) // prefetch c + 0*rs_c jmp(.SPOSTPFETCH) // jump to end of prefetching c label(.SCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) prefetch(0, mem(rcx, 0*8)) // prefetch c + 0*cs_c prefetch(0, mem(rcx, rsi, 1, 0*8)) // prefetch c + 1*cs_c label(.SPOSTPFETCH) // done prefetching c mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm4) // ---------------------------------- iteration 1 vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm4) // ---------------------------------- iteration 2 vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm4) // ---------------------------------- iteration 3 vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm4) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP vmovups(mem(rbx, 0*32), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm4) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), xmm0) // load alpha and duplicate vbroadcastss(mem(rbx), xmm3) // load beta and duplicate vmulps(xmm0, xmm4, xmm4) // scale by alpha mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vfmadd231ps(mem(rcx), xmm3, xmm4) vmovsd(xmm4, mem(rcx)) jmp(.SDONE) // jump to end. label(.SCOLSTORED) vshufps(imm(0x01), xmm4, xmm4, xmm9)//c1 vmovss(mem(rcx),xmm6) vfmadd231ps(xmm6, xmm3, xmm4) vmovss(xmm4,mem(rcx))//c0 vmovss(mem(rcx,rsi,1),xmm6) vfmadd231ps(xmm6, xmm3, xmm9) vmovss(xmm9,mem(rcx,rsi,1))//c1 jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovsd(xmm4, mem(rcx)) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) vshufps(imm(0x01), xmm4, xmm4, xmm9)//c1 vmovss(xmm4,mem(rcx))//c0 vmovss(xmm9,mem(rcx,rsi,1))//c1 label(.SDONE) end_asm( : // output operands (none) : // input operands [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) } // ----------------------------------------------------------------------------- // NOTE: Normally, for any "?x1" kernel, we would call the reference kernel. // However, at least one other subconfiguration (zen) uses this kernel set, so // we need to be able to call a set of "?x1" kernels that we know will actually // exist regardless of which subconfiguration these kernels were used by. Thus, // the compromise employed here is to inline the reference kernel so it gets // compiled as part of the zen kernel set, and hence can unconditionally be // called by other kernels within that kernel set. #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, mdim ) \ \ void PASTEMAC(ch,opname) \ ( \ conj_t conja, \ conj_t conjb, \ dim_t m, \ dim_t n, \ dim_t k, \ ctype* restrict alpha, \ ctype* restrict a, inc_t rs_a, inc_t cs_a, \ ctype* restrict b, inc_t rs_b, inc_t cs_b, \ ctype* restrict beta, \ ctype* restrict c, inc_t rs_c, inc_t cs_c, \ auxinfo_t* restrict data, \ cntx_t* restrict cntx \ ) \ { \ for ( dim_t i = 0; i < mdim; ++i ) \ { \ ctype* restrict ci = &c[ i*rs_c ]; \ ctype* restrict ai = &a[ i*rs_a ]; \ \ /* for ( dim_t j = 0; j < 1; ++j ) */ \ { \ ctype* restrict cij = ci /*[ j*cs_c ]*/ ; \ ctype* restrict bj = b /*[ j*cs_b ]*/ ; \ ctype ab; \ \ PASTEMAC(ch,set0s)( ab ); \ \ /* Perform a dot product to update the (i,j) element of c. */ \ for ( dim_t l = 0; l < k; ++l ) \ { \ ctype* restrict aij = &ai[ l*cs_a ]; \ ctype* restrict bij = &bj[ l*rs_b ]; \ \ PASTEMAC(ch,dots)( *aij, *bij, ab ); \ } \ \ /* If beta is one, add ab into c. If beta is zero, overwrite c with the result in ab. Otherwise, scale by beta and accumulate ab to c. */ \ if ( PASTEMAC(ch,eq1)( *beta ) ) \ { \ PASTEMAC(ch,axpys)( *alpha, ab, *cij ); \ } \ else if ( PASTEMAC(d,eq0)( *beta ) ) \ { \ PASTEMAC(ch,scal2s)( *alpha, ab, *cij ); \ } \ else \ { \ PASTEMAC(ch,axpbys)( *alpha, ab, *beta, *cij ); \ } \ } \ } \ } GENTFUNC( float, s, gemmsup_r_zen_ref_6x1, 6 ) GENTFUNC( float, s, gemmsup_r_zen_ref_5x1, 5 ) GENTFUNC( float, s, gemmsup_r_zen_ref_4x1, 4 ) GENTFUNC( float, s, gemmsup_r_zen_ref_3x1, 3 ) GENTFUNC( float, s, gemmsup_r_zen_ref_2x1, 2 ) GENTFUNC( float, s, gemmsup_r_zen_ref_1x1, 1 ) blis-0.9.0/kernels/zen/3/sup/other/bli_gemmsup_rv_zen_asm_s6x16m.c000066400000000000000000002303111422157504600250260ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define BLIS_ASM_SYNTAX_ATT #include "bli_x86_asm_macros.h" /* rrr: -------- ------ -------- -------- ------ -------- -------- += ------ ... -------- -------- ------ -------- -------- ------ : -------- ------ : rcr: -------- | | | | -------- -------- | | | | -------- -------- += | | | | ... -------- -------- | | | | -------- -------- | | | | : -------- | | | | : Assumptions: - B is row-stored; - A is row- or column-stored; - m0 and n0 are at most MR and NR, respectively. Therefore, this (r)ow-preferential kernel is well-suited for contiguous (v)ector loads on B and single-element broadcasts from A. NOTE: These kernels explicitly support column-oriented IO, implemented via an in-register transpose. And thus they also support the crr and ccr cases, though only crr is ever utilized (because ccr is handled by transposing the operation and executing rcr, which does not incur the cost of the in-register transpose). crr: | | | | | | | | ------ -------- | | | | | | | | ------ -------- | | | | | | | | += ------ ... -------- | | | | | | | | ------ -------- | | | | | | | | ------ : | | | | | | | | ------ : */ void bli_sgemmsup_rv_zen_asm_6x16m ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { uint64_t n_left = n0 % 16; // First check whether this is a edge case in the n dimension. If so, // dispatch other 6x?m kernels, as needed. if (n_left ) { float* cij = c; float* bj = b; float* ai = a; if ( 8 <= n_left ) { const dim_t nr_cur = 8; bli_sgemmsup_rv_zen_asm_6x8m ( conja, conjb, m0, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 4 <= n_left ) { const dim_t nr_cur = 4; bli_sgemmsup_rv_zen_asm_6x4m ( conja, conjb, m0, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 2 <= n_left ) { const dim_t nr_cur = 2; bli_sgemmsup_rv_zen_asm_6x2m ( conja, conjb, m0, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 1 == n_left ) { dim_t ps_a0 = bli_auxinfo_ps_a( data ); if ( ps_a0 == 6 * rs_a0 ) { bli_sgemv_ex ( BLIS_NO_TRANSPOSE, conjb, m0, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, beta, cij, rs_c0, cntx, NULL ); } else { const dim_t mr = 6; // Since A is packed into row panels, we must use a loop over // gemv. dim_t m_iter = ( m0 + mr - 1 ) / mr; dim_t m_left = m0 % mr; float* restrict ai_ii = ai; float* restrict cij_ii = cij; for ( dim_t ii = 0; ii < m_iter; ii += 1 ) { dim_t mr_cur = ( bli_is_not_edge_f( ii, m_iter, m_left ) ? mr : m_left ); bli_sgemv_ex ( BLIS_NO_TRANSPOSE, conjb, mr_cur, k0, alpha, ai_ii, rs_a0, cs_a0, bj, rs_b0, beta, cij_ii, rs_c0, cntx, NULL ); cij_ii += mr*rs_c0; ai_ii += ps_a0; } } } return; } //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t m_iter = m0 / 6; uint64_t m_left = m0 % 6; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // Query the panel stride of A and convert it to units of bytes. uint64_t ps_a = bli_auxinfo_ps_a( data ); uint64_t ps_a4 = ps_a * sizeof( float ); if ( m_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() mov(var(a), r14) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(dt) lea(mem(, r9, 4), r9) // cs_a *= sizeof(dt) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(rs_b), r10) // load rs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(dt) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(dt) // During preamble and loops: // r12 = rcx = c // r14 = rax = a // read rbx from var(b) near beginning of loop // r11 = m dim index ii mov(var(m_iter), r11) // ii = m_iter; label(.SLOOP6X16I) // LOOP OVER ii = [ m_iter ... 1 0 ] vxorps(ymm4, ymm4, ymm4) vxorps(ymm5, ymm5, ymm5) vxorps(ymm6, ymm6, ymm6) vxorps(ymm7, ymm7, ymm7) vxorps(ymm8, ymm8, ymm8) vxorps(ymm9, ymm9, ymm9) vxorps(ymm10, ymm10, ymm10) vxorps(ymm11, ymm11, ymm11) vxorps(ymm12, ymm12, ymm12) vxorps(ymm13, ymm13, ymm13) vxorps(ymm14, ymm14, ymm14) vxorps(ymm15, ymm15, ymm15) mov(var(b), rbx) // load address of b. //mov(r12, rcx) // reset rcx to current utile of c. mov(r14, rax) // reset rax to current upanel of a. cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored pre-fetching on c // not used lea(mem(r12, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(r12, 7*8)) // prefetch c + 0*rs_c prefetch(0, mem(r12, rdi, 1, 7*8)) // prefetch c + 1*rs_c prefetch(0, mem(r12, rdi, 2, 7*8)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 7*8)) // prefetch c + 3*rs_c prefetch(0, mem(rdx, rdi, 1, 7*8)) // prefetch c + 4*rs_c prefetch(0, mem(rdx, rdi, 2, 7*8)) // prefetch c + 5*rs_c jmp(.SPOSTPFETCH) // jump to end of pre-fetching c label(.SCOLPFETCH) // column-stored pre-fetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(dt) lea(mem(r12, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; prefetch(0, mem(r12, 5*8)) // prefetch c + 0*cs_c prefetch(0, mem(r12, rsi, 1, 5*8)) // prefetch c + 1*cs_c prefetch(0, mem(r12, rsi, 2, 5*8)) // prefetch c + 2*cs_c prefetch(0, mem(rdx, 5*8)) // prefetch c + 3*cs_c prefetch(0, mem(rdx, rsi, 1, 5*8)) // prefetch c + 4*cs_c prefetch(0, mem(rdx, rsi, 2, 5*8)) // prefetch c + 5*cs_c lea(mem(rdx, rsi, 2), rdx) // rdx = c + 5*cs_c; prefetch(0, mem(rdx, rsi, 1, 5*8)) // prefetch c + 6*cs_c prefetch(0, mem(rdx, rsi, 2, 5*8)) // prefetch c + 7*cs_c label(.SPOSTPFETCH) // done prefetching c lea(mem(r9, r9, 2), rcx) // rcx = 3*cs_a; lea(mem(rax, r8, 4), rdx) // use rdx for pre-fetching lines lea(mem(rdx, r8, 2), rdx) // from next upanel of a. mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 prefetch(0, mem(rdx, 5*8)) vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, r8, 4), ymm2) vbroadcastss(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) // ---------------------------------- iteration 1 prefetch(0, mem(rdx, r9, 1, 5*8)) vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, r8, 4), ymm2) vbroadcastss(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) // ---------------------------------- iteration 2 prefetch(0, mem(rdx, r9, 2, 5*8)) vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, r8, 4), ymm2) vbroadcastss(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) // ---------------------------------- iteration 3 prefetch(0, mem(rdx, rcx, 1, 5*8)) lea(mem(rdx, r9, 4), rdx) // a_prefetch += 4*cs_a; vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, r8, 4), ymm2) vbroadcastss(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, r8, 4), ymm2) vbroadcastss(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(r12, rcx) // reset rcx to current utile of c. mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), ymm0) // load alpha and duplicate vbroadcastss(mem(rbx), ymm3) // load beta and duplicate vmulps(ymm0, ymm4, ymm4) // scale by alpha vmulps(ymm0, ymm5, ymm5) vmulps(ymm0, ymm6, ymm6) vmulps(ymm0, ymm7, ymm7) vmulps(ymm0, ymm8, ymm8) vmulps(ymm0, ymm9, ymm9) vmulps(ymm0, ymm10, ymm10) vmulps(ymm0, ymm11, ymm11) vmulps(ymm0, ymm12, ymm12) vmulps(ymm0, ymm13, ymm13) vmulps(ymm0, ymm14, ymm14) vmulps(ymm0, ymm15, ymm15) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(dt) lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vfmadd231ps(mem(rcx), ymm3, ymm4) vmovups(ymm4, mem(rcx)) vfmadd231ps(mem(rcx, rsi, 8), ymm3, ymm5) vmovups(ymm5, mem(rcx, rsi, 8)) add(rdi, rcx) vfmadd231ps(mem(rcx), ymm3, ymm6) vmovups(ymm6, mem(rcx)) vfmadd231ps(mem(rcx, rsi, 8), ymm3, ymm7) vmovups(ymm7, mem(rcx, rsi, 8)) add(rdi, rcx) vfmadd231ps(mem(rcx), ymm3, ymm8) vmovups(ymm8, mem(rcx)) vfmadd231ps(mem(rcx, rsi, 8), ymm3, ymm9) vmovups(ymm9, mem(rcx, rsi, 8)) add(rdi, rcx) vfmadd231ps(mem(rcx), ymm3, ymm10) vmovups(ymm10, mem(rcx)) vfmadd231ps(mem(rcx, rsi, 8), ymm3, ymm11) vmovups(ymm11, mem(rcx, rsi, 8)) add(rdi, rcx) vfmadd231ps(mem(rcx), ymm3, ymm12) vmovups(ymm12, mem(rcx)) vfmadd231ps(mem(rcx, rsi, 8), ymm3, ymm13) vmovups(ymm13, mem(rcx, rsi, 8)) add(rdi, rcx) vfmadd231ps(mem(rcx), ymm3, ymm14) vmovups(ymm14, mem(rcx)) vfmadd231ps(mem(rcx, rsi, 8), ymm3, ymm15) vmovups(ymm15, mem(rcx, rsi, 8)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORED) /*|-----------------| |-----|----| | | | | 8x4 | 8x2| | 4x8 | 4x8 | | | | | | | |-----|----| |-----------------| | 8x4 | 8x2| | 2x8 | 2x8 | | | | |------------------ |----------|*/ /****6x16 tile is transposed and saved in col major as 6x16*****/ /****top left tile 4x8 transposed to top left tile 8x4**********/ vunpcklps(ymm6, ymm4, ymm0)//a0b0a1b1 a4b4a5b5 vunpcklps(ymm10, ymm8, ymm1)//c0d0c1d1 c4d4c5d5 vshufps(imm(0x4e), ymm1, ymm0, ymm2)//a1b1c0d0 a5b5c4d4 vblendps(imm(0xcc), ymm2, ymm0, ymm0)//a0b0c0d0 a4b4c4d4 vblendps(imm(0x33), ymm2, ymm1, ymm1)//a1b1c1d1 a5b5c5d5 vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx), xmm3, xmm0) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm0, mem(rcx)) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx), xmm3, xmm1) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm1, mem(rcx)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma05..gamma35 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c vunpckhps(ymm6, ymm4, ymm0) vunpckhps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx), xmm3, xmm0) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm0, mem(rcx)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma06..gamma36 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx), xmm3, xmm1) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm1, mem(rcx)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma07..gamma37 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c lea(mem(rcx, rsi, 4), rcx) // rcx += 4*cs_c /***bottom left tile - 2x8 is transposed to top right tile 8x2**********/ vunpcklps(ymm14, ymm12, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(mem(rdx), xmm1, xmm1) vmovhpd(mem(rdx, rsi, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(rdx)) // store ( gamma40..gamma50 ) vmovhpd(xmm0, mem(rdx, rsi, 1)) // store ( gamma41..gamma51 ) lea(mem(rdx, rsi, 4), rax) // rax += 4*cs_c vmovlpd(mem(rax), xmm1, xmm1) vmovhpd(mem(rax, rsi, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm2) vmovlpd(xmm2, mem(rax)) // store ( gamma44..gamma54 ) vmovhpd(xmm2, mem(rax, rsi, 1)) // store ( gamma45..gamma55 ) lea(mem(rdx, rsi, 2), rdx) // rdx += 2*cs_c vunpckhps(ymm14, ymm12, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(mem(rdx), xmm1, xmm1) vmovhpd(mem(rdx, rsi, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(rdx)) // store ( gamma42..gamma52 ) vmovhpd(xmm0, mem(rdx, rsi, 1)) // store ( gamma43..gamma53 ) lea(mem(rdx, rsi, 4), rdx) // rdx += 4*cs_c vmovlpd(mem(rdx), xmm1, xmm1) vmovhpd(mem(rdx, rsi, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm2) vmovlpd(xmm2, mem(rdx)) // store ( gamma46..gamma56 ) vmovhpd(xmm2, mem(rdx, rsi, 1)) // store ( gamma47..gamma57 ) lea(mem(rdx, rsi, 2), rdx) // rdx += 2*cs_c /***top right tile 4x8 is transposed to bottom left tile 8x4**********/ vunpcklps(ymm7, ymm5, ymm0) vunpcklps(ymm11, ymm9, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx), xmm3, xmm0) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm0, mem(rcx)) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx), xmm3, xmm1) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm1, mem(rcx)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma05..gamma35 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c vunpckhps(ymm7, ymm5, ymm0) vunpckhps(ymm11, ymm9, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx), xmm3, xmm0) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm0, mem(rcx)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma06..gamma36 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx), xmm3, xmm1) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm1, mem(rcx)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma07..gamma37 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c /*** bottom right 2x8 is transposed to bottom right tile 8x2*******/ vunpcklps(ymm15, ymm13, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(mem(rdx), xmm1, xmm1) vmovhpd(mem(rdx, rsi, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(rdx)) // store ( gamma40..gamma50 ) vmovhpd(xmm0, mem(rdx, rsi, 1)) // store ( gamma41..gamma51 ) lea(mem(rdx, rsi, 4), rax) // rax += 4*cs_c vmovlpd(mem(rax), xmm1, xmm1) vmovhpd(mem(rax, rsi, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm2) vmovlpd(xmm2, mem(rax)) // store ( gamma44..gamma54 ) vmovhpd(xmm2, mem(rax, rsi, 1)) // store ( gamma45..gamma55 ) lea(mem(rdx, rsi, 2), rdx) // rdx += 2*cs_c vunpckhps(ymm15, ymm13, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(mem(rdx), xmm1, xmm1) vmovhpd(mem(rdx, rsi, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(rdx)) // store ( gamma42..gamma52 ) vmovhpd(xmm0, mem(rdx, rsi, 1)) // store ( gamma43..gamma53 ) lea(mem(rdx, rsi, 4), rdx) // rdx += 4*cs_c vmovlpd(mem(rdx), xmm1, xmm1) vmovhpd(mem(rdx, rsi, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm2) vmovlpd(xmm2, mem(rdx)) // store ( gamma46..gamma56 ) vmovhpd(xmm2, mem(rdx, rsi, 1)) // store ( gamma47..gamma57 ) jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovups(ymm4, mem(rcx)) vmovups(ymm5, mem(rcx, rsi, 8)) add(rdi, rcx) vmovups(ymm6, mem(rcx)) vmovups(ymm7, mem(rcx, rsi, 8)) add(rdi, rcx) vmovups(ymm8, mem(rcx)) vmovups(ymm9, mem(rcx, rsi, 8)) add(rdi, rcx) vmovups(ymm10, mem(rcx)) vmovups(ymm11, mem(rcx, rsi, 8)) add(rdi, rcx) vmovups(ymm12, mem(rcx)) vmovups(ymm13, mem(rcx, rsi, 8)) add(rdi, rcx) vmovups(ymm14, mem(rcx)) vmovups(ymm15, mem(rcx, rsi, 8)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) /****6x16 tile going to save into 16x6 tile in C*****/ /******************top left tile 8x4***************************/ vunpcklps(ymm6, ymm4, ymm0) vunpcklps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx)) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) lea(mem(rcx, rsi, 1), rcx) // rcx += 1*cs_c vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma05..gamma35 ) lea(mem(rcx, rsi, 1), rcx) // rcx += 1*cs_c vunpckhps(ymm6, ymm4, ymm0) vunpckhps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma06..gamma36 ) lea(mem(rcx, rsi, 1), rcx) // rcx += 1*cs_c vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma07..gamma37 ) lea(mem(rcx, rsi, 1), rcx) // rcx += 1*cs_c lea(mem(rcx, rsi, 4), rcx) // rcx += 4*cs_c /******************top right tile 8x2***************************/ vunpcklps(ymm14, ymm12, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(xmm0, mem(rdx)) // store ( gamma40..gamma50 ) vmovlpd(xmm2, mem(rdx, rsi, 4)) // store ( gamma44..gamma54 ) lea(mem(rdx, rsi, 1), rdx) vmovhpd(xmm0, mem(rdx)) // store ( gamma41..gamma51 ) vmovhpd(xmm2, mem(rdx, rsi, 4)) // store ( gamma45..gamma55 ) lea(mem(rdx, rsi, 1), rdx) vunpckhps(ymm14, ymm12, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(xmm0, mem(rdx)) // store ( gamma42..gamma52 ) vmovlpd(xmm2, mem(rdx, rsi, 4)) // store ( gamma46..gamma56 ) lea(mem(rdx, rsi, 1), rdx) vmovhpd(xmm0, mem(rdx)) // store ( gamma43..gamma53 ) vmovhpd(xmm2, mem(rdx, rsi, 4)) // store ( gamma47..gamma57 ) lea(mem(rdx, rsi, 1), rdx) lea(mem(rdx, rsi, 4), rdx) // rdx += 8*cs_c /******************bottom left tile 8x4***************************/ vunpcklps(ymm7, ymm5, ymm0) vunpcklps(ymm11, ymm9, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx)) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) lea(mem(rcx, rsi, 1), rcx) // rcx += 1*cs_c vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma05..gamma35 ) lea(mem(rcx, rsi, 1), rcx) // rcx += 1*cs_c vunpckhps(ymm7, ymm5, ymm0) vunpckhps(ymm11, ymm9, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma06..gamma36 ) lea(mem(rcx, rsi, 1), rcx) // rcx += 1*cs_c vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma07..gamma37 ) /******************bottom right tile 8x2***************************/ vunpcklps(ymm15, ymm13, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(xmm0, mem(rdx)) // store ( gamma40..gamma50 ) vmovlpd(xmm2, mem(rdx, rsi, 4)) // store ( gamma44..gamma54 ) lea(mem(rdx, rsi, 1), rdx) vmovhpd(xmm0, mem(rdx)) // store ( gamma41..gamma51 ) vmovhpd(xmm2, mem(rdx, rsi, 4)) // store ( gamma45..gamma55 ) lea(mem(rdx, rsi, 1), rdx) vunpckhps(ymm15, ymm13, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(xmm0, mem(rdx)) // store ( gamma42..gamma52 ) vmovlpd(xmm2, mem(rdx, rsi, 4)) // store ( gamma46..gamma56 ) lea(mem(rdx, rsi, 1), rdx) vmovhpd(xmm0, mem(rdx)) // store ( gamma43..gamma53 ) vmovhpd(xmm2, mem(rdx, rsi, 4)) // store ( gamma47..gamma57 ) label(.SDONE) lea(mem(r12, rdi, 4), r12) // lea(mem(r12, rdi, 2), r12) // c_ii = r12 += 6*rs_c //lea(mem(r14, r8, 4), r14) // //lea(mem(r14, r8, 2), r14) // a_ii = r14 += 6*rs_a mov(var(ps_a4), rax) // load ps_a4 lea(mem(r14, rax, 1), r14) // a_ii = r14 += ps_a4 dec(r11) // ii -= 1; jne(.SLOOP6X16I) // iterate again if ii != 0. label(.SRETURN) end_asm( : // output operands (none) : // input operands [m_iter] "m" (m_iter), [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [ps_a4] "m" (ps_a4), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the m dimension, if they exist. if ( m_left ) { const dim_t nr_cur = 16; const dim_t i_edge = m0 - ( dim_t )m_left; float* restrict cij = c + i_edge*rs_c; float* restrict ai = a + m_iter*ps_a; float* restrict bj = b; sgemmsup_ker_ft ker_fps[6] = { NULL, bli_sgemmsup_rv_zen_asm_1x16, bli_sgemmsup_rv_zen_asm_2x16, bli_sgemmsup_rv_zen_asm_3x16, bli_sgemmsup_rv_zen_asm_4x16, bli_sgemmsup_rv_zen_asm_5x16 }; sgemmsup_ker_ft ker_fp = ker_fps[ m_left ]; ker_fp ( conja, conjb, m_left, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); return; } } void bli_sgemmsup_rv_zen_asm_6x8m ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t m_iter = m0 / 6; uint64_t m_left = m0 % 6; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // Query the panel stride of A and convert it to units of bytes. uint64_t ps_a = bli_auxinfo_ps_a( data ); uint64_t ps_a4 = ps_a * sizeof( float ); if ( m_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() mov(var(a), r14) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(rs_b), r10) // load rs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) // During preamble and loops: // r12 = rcx = c // r14 = rax = a // read rbx from var(b) near beginning of loop // r11 = m dim index ii mov(var(m_iter), r11) // ii = m_iter; label(.SLOOP6X8I) // LOOP OVER ii = [ m_iter ... 1 0 ] // skylake can execute 3 vxorpd ipc with // a latency of 1 cycle, while vzeroall // has a latency of 12 cycles. vxorps(ymm1, ymm1, ymm1) // zero ymm1 since we only use the lower vxorps(ymm4, ymm4, ymm4) // half (xmm1), and nans/infs may slow us down. vxorps(ymm6, ymm6, ymm6) vxorps(ymm8, ymm8, ymm8) vxorps(ymm10, ymm10, ymm10) vxorps(ymm12, ymm12, ymm12) vxorps(ymm14, ymm14, ymm14) mov(var(b), rbx) // load address of b. mov(r14, rax) // reset rax to current upanel of a. cmp(imm(4), rdi) // set ZF if (8*rs_c) == 8. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored prefetching on c lea(mem(r12, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(r12, 5*8)) // prefetch c + 0*rs_c prefetch(0, mem(r12, rdi, 1, 5*8)) // prefetch c + 1*rs_c prefetch(0, mem(r12, rdi, 2, 5*8)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 5*8)) // prefetch c + 3*rs_c prefetch(0, mem(rdx, rdi, 1, 5*8)) // prefetch c + 4*rs_c prefetch(0, mem(rdx, rdi, 2, 5*8)) // prefetch c + 5*rs_c jmp(.SPOSTPFETCH) // jump to end of prefetching c label(.SCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) lea(mem(r12, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; prefetch(0, mem(r12, 5*8)) // prefetch c + 0*cs_c prefetch(0, mem(r12, rsi, 1, 5*8)) // prefetch c + 1*cs_c prefetch(0, mem(r12, rsi, 2, 5*8)) // prefetch c + 2*cs_c prefetch(0, mem(rdx, 5*8)) // prefetch c + 3*cs_c prefetch(0, mem(rdx, rsi, 1, 5*8)) // prefetch c + 4*cs_c prefetch(0, mem(rdx, rsi, 2, 5*8)) // prefetch c + 5*cs_c label(.SPOSTPFETCH) // done prefetching c lea(mem(r9, r9, 2), rcx) // rcx = 3*cs_a; lea(mem(rax, r8, 4), rdx) // use rdx for prefetching lines lea(mem(rdx, r8, 2), rdx) // from next upanel of a. mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 prefetch(0, mem(rdx, 5*8)) vmovups(mem(rbx), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm0, ymm3, ymm10) vbroadcastss(mem(rax, r8, 4), ymm2) vbroadcastss(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm0, ymm3, ymm14) // ---------------------------------- iteration 1 prefetch(0, mem(rdx, r9, 1, 5*8)) vmovups(mem(rbx), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm0, ymm3, ymm10) vbroadcastss(mem(rax, r8, 4), ymm2) vbroadcastss(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm0, ymm3, ymm14) // ---------------------------------- iteration 2 prefetch(0, mem(rdx, r9, 2, 5*8)) vmovups(mem(rbx), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm0, ymm3, ymm10) vbroadcastss(mem(rax, r8, 4), ymm2) vbroadcastss(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm0, ymm3, ymm14) // ---------------------------------- iteration 3 prefetch(0, mem(rdx, rcx, 1, 5*8)) vmovups(mem(rbx), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm0, ymm3, ymm10) vbroadcastss(mem(rax, r8, 4), ymm2) vbroadcastss(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm0, ymm3, ymm14) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP vmovups(mem(rbx), ymm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm0, ymm3, ymm6) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm0, ymm3, ymm10) vbroadcastss(mem(rax, r8, 4), ymm2) vbroadcastss(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm0, ymm3, ymm14) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(r12, rcx) // reset rcx to current utile of c. mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), ymm0) // load alpha and duplicate vbroadcastss(mem(rbx), ymm3) // load beta and duplicate vmulps(ymm0, ymm4, ymm4) // scale by alpha vmulps(ymm0, ymm6, ymm6) vmulps(ymm0, ymm8, ymm8) vmulps(ymm0, ymm10, ymm10) vmulps(ymm0, ymm12, ymm12) vmulps(ymm0, ymm14, ymm14) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (8*rs_c) == 8. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vfmadd231ps(mem(rcx), ymm3, ymm4) vmovups(ymm4, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), ymm3, ymm6) vmovups(ymm6, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), ymm3, ymm8) vmovups(ymm8, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), ymm3, ymm10) vmovups(ymm10, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), ymm3, ymm12) vmovups(ymm12, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), ymm3, ymm14) vmovups(ymm14, mem(rcx)) jmp(.SDONE) // jump to end. label(.SCOLSTORED) /****6x8 tile is transposed and saved in col major as 8x6*****/ vunpcklps(ymm6, ymm4, ymm0) vunpcklps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx), xmm3, xmm0) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm0, mem(rcx)) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) lea(mem(rcx, rsi, 1), rcx) // rcx += 1*cs_c vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx), xmm3, xmm1) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm1, mem(rcx)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma05..gamma35 ) lea(mem(rcx, rsi, 1), rcx) // rcx += 1*cs_c vunpckhps(ymm6, ymm4, ymm0) vunpckhps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx), xmm3, xmm0) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm0, mem(rcx)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma06..gamma36 ) lea(mem(rcx, rsi, 1), rcx) // rcx += 1*cs_c vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx), xmm3, xmm1) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm1, mem(rcx)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma07..gamma37 ) vunpcklps(ymm14, ymm12, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vpermilps(imm(0xe),xmm0,xmm5) vpermilps(imm(0xe),xmm2,xmm6) vfmadd231ps(mem(rdx), xmm3, xmm0) vfmadd231ps(mem(rdx, rsi, 4), xmm3, xmm2) vmovlpd(xmm0, mem(rdx)) // store ( gamma40..gamma50 ) vmovlpd(xmm2, mem(rdx, rsi, 4)) // store ( gamma44..gamma54 ) lea(mem(rdx, rsi, 1), rdx) vfmadd231ps(mem(rdx), xmm3, xmm5) vfmadd231ps(mem(rdx, rsi, 4), xmm3, xmm6) vmovlpd(xmm5, mem(rdx)) // store ( gamma41..gamma51 ) vmovlpd(xmm6, mem(rdx, rsi, 4)) // store ( gamma45..gamma55 ) lea(mem(rdx, rsi, 1), rdx) vunpckhps(ymm14, ymm12, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vpermilps(imm(0xe),xmm0,xmm5) vpermilps(imm(0xe),xmm2,xmm6) vfmadd231ps(mem(rdx), xmm3, xmm0) vfmadd231ps(mem(rdx, rsi, 4), xmm3, xmm2) vmovlpd(xmm0, mem(rdx)) // store ( gamma42..gamma52 ) vmovlpd(xmm2, mem(rdx, rsi, 4)) // store ( gamma46..gamma56 ) lea(mem(rdx, rsi, 1), rdx) vfmadd231ps(mem(rdx), xmm3, xmm5) vfmadd231ps(mem(rdx, rsi, 4), xmm3, xmm6) vmovlpd(xmm5, mem(rdx)) // store ( gamma43..gamma53 ) vmovlpd(xmm6, mem(rdx, rsi, 4)) // store ( gamma47..gamma57 ) jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (8*rs_c) == 8. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovups(ymm4, mem(rcx)) add(rdi, rcx) vmovups(ymm6, mem(rcx)) add(rdi, rcx) vmovups(ymm8, mem(rcx)) add(rdi, rcx) vmovups(ymm10, mem(rcx)) add(rdi, rcx) vmovups(ymm12, mem(rcx)) add(rdi, rcx) vmovups(ymm14, mem(rcx)) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) vunpcklps(ymm6, ymm4, ymm0) vunpcklps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx)) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) lea(mem(rcx, rsi, 1), rcx) // rcx += 1*cs_c vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma05..gamma35 ) lea(mem(rcx, rsi, 1), rcx) // rcx += 1*cs_c vunpckhps(ymm6, ymm4, ymm0) vunpckhps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma06..gamma36 ) lea(mem(rcx, rsi, 1), rcx) // rcx += 1*cs_c vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma07..gamma37 ) /******************top right tile 8x2***************************/ vunpcklps(ymm14, ymm12, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(xmm0, mem(rdx)) // store ( gamma40..gamma50 ) vmovlpd(xmm2, mem(rdx, rsi, 4)) // store ( gamma44..gamma54 ) lea(mem(rdx, rsi, 1), rdx) vmovhpd(xmm0, mem(rdx)) // store ( gamma41..gamma51 ) vmovhpd(xmm2, mem(rdx, rsi, 4)) // store ( gamma45..gamma55 ) lea(mem(rdx, rsi, 1), rdx) vunpckhps(ymm14, ymm12, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(xmm0, mem(rdx)) // store ( gamma42..gamma52 ) vmovlpd(xmm2, mem(rdx, rsi, 4)) // store ( gamma46..gamma56 ) lea(mem(rdx, rsi, 1), rdx) vmovhpd(xmm0, mem(rdx)) // store ( gamma43..gamma53 ) vmovhpd(xmm2, mem(rdx, rsi, 4)) // store ( gamma47..gamma57 ) label(.SDONE) lea(mem(r12, rdi, 4), r12) // lea(mem(r12, rdi, 2), r12) // c_ii = r12 += 6*rs_c //lea(mem(r14, r8, 4), r14) // //lea(mem(r14, r8, 2), r14) // a_ii = r14 += 6*rs_a mov(var(ps_a4), rax) // load ps_a4 lea(mem(r14, rax, 1), r14) // a_ii = r14 += ps_a4 dec(r11) // ii -= 1; jne(.SLOOP6X8I) // iterate again if ii != 0. label(.SRETURN) end_asm( : // output operands (none) : // input operands [m_iter] "m" (m_iter), [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [ps_a4] "m" (ps_a4), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the m dimension, if they exist. if ( m_left ) { const dim_t nr_cur = 8; const dim_t i_edge = m0 - ( dim_t )m_left; float* restrict cij = c + i_edge*rs_c; float* restrict ai = a + m_iter*ps_a; float* restrict bj = b; sgemmsup_ker_ft ker_fps[6] = { NULL, bli_sgemmsup_rv_zen_asm_1x8, bli_sgemmsup_rv_zen_asm_2x8, bli_sgemmsup_rv_zen_asm_3x8, bli_sgemmsup_rv_zen_asm_4x8, bli_sgemmsup_rv_zen_asm_5x8 }; sgemmsup_ker_ft ker_fp = ker_fps[ m_left ]; ker_fp ( conja, conjb, m_left, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); return; } } void bli_sgemmsup_rv_zen_asm_6x4m ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t m_iter = m0 / 6; uint64_t m_left = m0 % 6; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // Query the panel stride of A and convert it to units of bytes. uint64_t ps_a = bli_auxinfo_ps_a( data ); uint64_t ps_a4 = ps_a * sizeof( float ); if ( m_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() mov(var(a), r14) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(rs_b), r10) // load rs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) // During preamble and loops: // r12 = rcx = c // r14 = rax = a // read rbx from var(b) near beginning of loop // r11 = m dim index ii mov(var(m_iter), r11) // ii = m_iter; label(.SLOOP6X4I) // LOOP OVER ii = [ m_iter ... 1 0 ] vxorps(xmm1, xmm1, xmm1) vxorps(xmm4, xmm4, xmm4) vxorps(xmm6, xmm6, xmm6) vxorps(xmm8, xmm8, xmm8) vxorps(xmm10, xmm10, xmm10) vxorps(xmm12, xmm12, xmm12) vxorps(xmm14, xmm14, xmm14) mov(var(b), rbx) // load address of b. mov(r14, rax) // reset rax to current upanel of a. cmp(imm(4), rdi) // set ZF if (8*rs_c) == 8. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored prefetching on c lea(mem(r12, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(r12, 5*8)) // prefetch c + 0*rs_c prefetch(0, mem(r12, rdi, 1, 5*8)) // prefetch c + 1*rs_c prefetch(0, mem(r12, rdi, 2, 5*8)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 5*8)) // prefetch c + 3*rs_c prefetch(0, mem(rdx, rdi, 1, 5*8)) // prefetch c + 4*rs_c prefetch(0, mem(rdx, rdi, 2, 5*8)) // prefetch c + 5*rs_c jmp(.SPOSTPFETCH) // jump to end of prefetching c label(.SCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) lea(mem(r12, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; prefetch(0, mem(r12, 5*8)) // prefetch c + 0*cs_c prefetch(0, mem(r12, rsi, 1, 5*8)) // prefetch c + 1*cs_c prefetch(0, mem(r12, rsi, 2, 5*8)) // prefetch c + 2*cs_c prefetch(0, mem(rdx, 5*8)) // prefetch c + 3*cs_c prefetch(0, mem(rdx, rsi, 1, 5*8)) // prefetch c + 4*cs_c prefetch(0, mem(rdx, rsi, 2, 5*8)) // prefetch c + 5*cs_c label(.SPOSTPFETCH) // done prefetching c lea(mem(r9, r9, 2), rcx) // rcx = 3*cs_a; lea(mem(rax, r8, 4), rdx) // use rdx for prefetching lines lea(mem(rdx, r8, 2), rdx) // from next upanel of a. mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 prefetch(0, mem(rdx, 5*8)) vmovups(mem(rbx), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) vbroadcastss(mem(rax, r13, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm8) vfmadd231ps(xmm0, xmm3, xmm10) vbroadcastss(mem(rax, r8, 4), xmm2) vbroadcastss(mem(rax, r15, 1), xmm3) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm12) vfmadd231ps(xmm0, xmm3, xmm14) // ---------------------------------- iteration 1 prefetch(0, mem(rdx, r9, 1, 5*8)) vmovups(mem(rbx), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) vbroadcastss(mem(rax, r13, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm8) vfmadd231ps(xmm0, xmm3, xmm10) vbroadcastss(mem(rax, r8, 4), xmm2) vbroadcastss(mem(rax, r15, 1), xmm3) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm12) vfmadd231ps(xmm0, xmm3, xmm14) // ---------------------------------- iteration 2 prefetch(0, mem(rdx, r9, 2, 5*8)) vmovups(mem(rbx), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) vbroadcastss(mem(rax, r13, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm8) vfmadd231ps(xmm0, xmm3, xmm10) vbroadcastss(mem(rax, r8, 4), xmm2) vbroadcastss(mem(rax, r15, 1), xmm3) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm12) vfmadd231ps(xmm0, xmm3, xmm14) // ---------------------------------- iteration 3 prefetch(0, mem(rdx, rcx, 1, 5*8)) vmovups(mem(rbx), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) vbroadcastss(mem(rax, r13, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm8) vfmadd231ps(xmm0, xmm3, xmm10) vbroadcastss(mem(rax, r8, 4), xmm2) vbroadcastss(mem(rax, r15, 1), xmm3) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm12) vfmadd231ps(xmm0, xmm3, xmm14) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP vmovups(mem(rbx), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) vbroadcastss(mem(rax, r13, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm8) vfmadd231ps(xmm0, xmm3, xmm10) vbroadcastss(mem(rax, r8, 4), xmm2) vbroadcastss(mem(rax, r15, 1), xmm3) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm12) vfmadd231ps(xmm0, xmm3, xmm14) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(r12, rcx) // reset rcx to current utile of c. mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), xmm0) // load alpha and duplicate vbroadcastss(mem(rbx), xmm3) // load beta and duplicate vmulps(xmm0, xmm4, xmm4) // scale by alpha vmulps(xmm0, xmm6, xmm6) vmulps(xmm0, xmm8, xmm8) vmulps(xmm0, xmm10, xmm10) vmulps(xmm0, xmm12, xmm12) vmulps(xmm0, xmm14, xmm14) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorps(xmm0, xmm0, xmm0) // set xmm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (8*rs_c) == 8. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vfmadd231ps(mem(rcx), xmm3, xmm4) vmovups(xmm4, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), xmm3, xmm6) vmovups(xmm6, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), xmm3, xmm8) vmovups(xmm8, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), xmm3, xmm10) vmovups(xmm10, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), xmm3, xmm12) vmovups(xmm12, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), xmm3, xmm14) vmovups(xmm14, mem(rcx)) jmp(.SDONE) // jump to end. label(.SCOLSTORED) /****6x4 tile is transposed and saved in col major as 4x6*****/ vunpcklps(xmm6, xmm4, xmm0) vunpcklps(xmm10, xmm8, xmm1) vshufps(imm(0x4e), xmm1, xmm0, xmm2) vblendps(imm(0xcc), xmm2, xmm0, xmm0) vblendps(imm(0x33), xmm2, xmm1, xmm1) vfmadd231ps(mem(rcx), xmm3, xmm0) vmovups(xmm0, mem(rcx)) // store ( gamma00..gamma30 ) lea(mem(rcx, rsi, 1), rcx) // rcx += 1*cs_c vfmadd231ps(mem(rcx), xmm3, xmm1) vmovups(xmm1, mem(rcx)) // store ( gamma01..gamma31 ) lea(mem(rcx, rsi, 1), rcx) // rcx += 1*cs_c vunpckhps(xmm6, xmm4, xmm0) vunpckhps(xmm10, xmm8, xmm1) vshufps(imm(0x4e), xmm1, xmm0, xmm2) vblendps(imm(0xcc), xmm2, xmm0, xmm0) vblendps(imm(0x33), xmm2, xmm1, xmm1) vfmadd231ps(mem(rcx), xmm3, xmm0) vmovups(xmm0, mem(rcx)) // store ( gamma02..gamma32 ) lea(mem(rcx, rsi, 1), rcx) // rcx += 1*cs_c vfmadd231ps(mem(rcx), xmm3, xmm1) vmovups(xmm1, mem(rcx)) // store ( gamma03..gamma33 ) vunpcklps(xmm14, xmm12, xmm0) vpermilps(imm(0x4e), xmm0, xmm5) vmovq(mem(rdx),xmm4) vfmadd231ps(xmm4, xmm3, xmm0) vmovlpd(xmm0, mem(rdx)) // store ( gamma40..gamma50 ) lea(mem(rdx, rsi, 1), rdx) vmovq(mem(rdx),xmm4) vfmadd231ps(xmm4, xmm3, xmm5) vmovlpd(xmm5, mem(rdx)) // store ( gamma41..gamma51 ) lea(mem(rdx, rsi, 1), rdx) vunpckhps(xmm14, xmm12, xmm0) vpermilps(imm(0x4e), xmm0, xmm5) vfmadd231ps(mem(rdx), xmm3, xmm0) vmovlpd(xmm0, mem(rdx)) // store ( gamma42..gamma52 ) lea(mem(rdx, rsi, 1), rdx) vfmadd231ps(mem(rdx), xmm3, xmm5) vmovlpd(xmm5, mem(rdx)) // store ( gamma43..gamma53 ) jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (8*rs_c) == 8. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovups(xmm4, mem(rcx)) add(rdi, rcx) vmovups(xmm6, mem(rcx)) add(rdi, rcx) vmovups(xmm8, mem(rcx)) add(rdi, rcx) vmovups(xmm10, mem(rcx)) add(rdi, rcx) vmovups(xmm12, mem(rcx)) add(rdi, rcx) vmovups(xmm14, mem(rcx)) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) vunpcklps(xmm6, xmm4, xmm0) vunpcklps(xmm10, xmm8, xmm1) vshufps(imm(0x4e), xmm1, xmm0, xmm2) vblendps(imm(0xcc), xmm2, xmm0, xmm0) vblendps(imm(0x33), xmm2, xmm1, xmm1) vmovups(xmm0, mem(rcx)) // store ( gamma00..gamma30 ) lea(mem(rcx, rsi, 1), rcx) // rcx += 1*cs_c vmovups(xmm1, mem(rcx)) // store ( gamma01..gamma31 ) lea(mem(rcx, rsi, 1), rcx) // rcx += 1*cs_c vunpckhps(xmm6, xmm4, xmm0) vunpckhps(xmm10, xmm8, xmm1) vshufps(imm(0x4e), xmm1, xmm0, xmm2) vblendps(imm(0xcc), xmm2, xmm0, xmm0) vblendps(imm(0x33), xmm2, xmm1, xmm1) vmovups(xmm0, mem(rcx)) // store ( gamma02..gamma32 ) lea(mem(rcx, rsi, 1), rcx) // rcx += 1*cs_c vmovups(xmm1, mem(rcx)) // store ( gamma03..gamma33 ) vunpcklps(xmm14, xmm12, xmm0) vmovlpd(xmm0, mem(rdx)) // store ( gamma40..gamma50 ) lea(mem(rdx, rsi, 1), rdx) vmovhpd(xmm0, mem(rdx)) // store ( gamma41..gamma51 ) lea(mem(rdx, rsi, 1), rdx) vunpckhps(xmm14, xmm12, xmm0) vmovlpd(xmm0, mem(rdx)) // store ( gamma42..gamma52 ) lea(mem(rdx, rsi, 1), rdx) vmovhpd(xmm0, mem(rdx)) // store ( gamma43..gamma53 ) label(.SDONE) lea(mem(r12, rdi, 4), r12) // lea(mem(r12, rdi, 2), r12) // c_ii = r12 += 6*rs_c //lea(mem(r14, r8, 4), r14) // //lea(mem(r14, r8, 2), r14) // a_ii = r14 += 6*rs_a mov(var(ps_a4), rax) // load ps_a4 lea(mem(r14, rax, 1), r14) // a_ii = r14 += ps_a4 dec(r11) // ii -= 1; jne(.SLOOP6X4I) // iterate again if ii != 0. label(.SRETURN) end_asm( : // output operands (none) : // input operands [m_iter] "m" (m_iter), [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [ps_a4] "m" (ps_a4), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the m dimension, if they exist. if ( m_left ) { const dim_t nr_cur = 4; const dim_t i_edge = m0 - ( dim_t )m_left; float* restrict cij = c + i_edge*rs_c; float* restrict ai = a + m_iter*ps_a; float* restrict bj = b; sgemmsup_ker_ft ker_fps[6] = { NULL, bli_sgemmsup_rv_zen_asm_1x4, bli_sgemmsup_rv_zen_asm_2x4, bli_sgemmsup_rv_zen_asm_3x4, bli_sgemmsup_rv_zen_asm_4x4, bli_sgemmsup_rv_zen_asm_5x4 }; sgemmsup_ker_ft ker_fp = ker_fps[ m_left ]; ker_fp ( conja, conjb, m_left, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); return; } } void bli_sgemmsup_rv_zen_asm_6x2m ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t m_iter = m0 / 6; uint64_t m_left = m0 % 6; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // Query the panel stride of A and convert it to units of bytes. uint64_t ps_a = bli_auxinfo_ps_a( data ); uint64_t ps_a4 = ps_a * sizeof( float ); if ( m_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() mov(var(a), r14) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(rs_b), r10) // load rs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) // During preamble and loops: // r12 = rcx = c // r14 = rax = a // read rbx from var(b) near beginning of loop // r11 = m dim index ii mov(var(m_iter), r11) // ii = m_iter; label(.SLOOP6X2I) // LOOP OVER ii = [ m_iter ... 1 0 ] vxorps(xmm1, xmm1, xmm1) vxorps(xmm4, xmm4, xmm4) vxorps(xmm6, xmm6, xmm6) vxorps(xmm8, xmm8, xmm8) vxorps(xmm10, xmm10, xmm10) vxorps(xmm12, xmm12, xmm12) vxorps(xmm14, xmm14, xmm14) mov(var(b), rbx) // load address of b. mov(r14, rax) // reset rax to current upanel of a. cmp(imm(4), rdi) // set ZF if (8*rs_c) == 8. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored prefetching on c lea(mem(r12, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(r12, 5*8)) // prefetch c + 0*rs_c prefetch(0, mem(r12, rdi, 1, 5*8)) // prefetch c + 1*rs_c prefetch(0, mem(r12, rdi, 2, 5*8)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 5*8)) // prefetch c + 3*rs_c prefetch(0, mem(rdx, rdi, 1, 5*8)) // prefetch c + 4*rs_c prefetch(0, mem(rdx, rdi, 2, 5*8)) // prefetch c + 5*rs_c jmp(.SPOSTPFETCH) // jump to end of prefetching c label(.SCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) lea(mem(r12, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; prefetch(0, mem(r12, 5*8)) // prefetch c + 0*cs_c prefetch(0, mem(r12, rsi, 1, 5*8)) // prefetch c + 1*cs_c prefetch(0, mem(r12, rsi, 2, 5*8)) // prefetch c + 2*cs_c prefetch(0, mem(rdx, 5*8)) // prefetch c + 3*cs_c prefetch(0, mem(rdx, rsi, 1, 5*8)) // prefetch c + 4*cs_c prefetch(0, mem(rdx, rsi, 2, 5*8)) // prefetch c + 5*cs_c label(.SPOSTPFETCH) // done prefetching c lea(mem(r9, r9, 2), rcx) // rcx = 3*cs_a; lea(mem(rax, r8, 4), rdx) // use rdx for prefetching lines lea(mem(rdx, r8, 2), rdx) // from next upanel of a. mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 prefetch(0, mem(rdx, 5*8)) vmovq(mem(rbx), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) vbroadcastss(mem(rax, r13, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm8) vfmadd231ps(xmm0, xmm3, xmm10) vbroadcastss(mem(rax, r8, 4), xmm2) vbroadcastss(mem(rax, r15, 1), xmm3) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm12) vfmadd231ps(xmm0, xmm3, xmm14) // ---------------------------------- iteration 1 prefetch(0, mem(rdx, r9, 1, 5*8)) vmovq(mem(rbx), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) vbroadcastss(mem(rax, r13, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm8) vfmadd231ps(xmm0, xmm3, xmm10) vbroadcastss(mem(rax, r8, 4), xmm2) vbroadcastss(mem(rax, r15, 1), xmm3) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm12) vfmadd231ps(xmm0, xmm3, xmm14) // ---------------------------------- iteration 2 prefetch(0, mem(rdx, r9, 2, 5*8)) vmovq(mem(rbx), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) vbroadcastss(mem(rax, r13, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm8) vfmadd231ps(xmm0, xmm3, xmm10) vbroadcastss(mem(rax, r8, 4), xmm2) vbroadcastss(mem(rax, r15, 1), xmm3) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm12) vfmadd231ps(xmm0, xmm3, xmm14) // ---------------------------------- iteration 3 prefetch(0, mem(rdx, rcx, 1, 5*8)) vmovq(mem(rbx), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) vbroadcastss(mem(rax, r13, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm8) vfmadd231ps(xmm0, xmm3, xmm10) vbroadcastss(mem(rax, r8, 4), xmm2) vbroadcastss(mem(rax, r15, 1), xmm3) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm12) vfmadd231ps(xmm0, xmm3, xmm14) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP vmovq(mem(rbx), xmm0) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), xmm2) vbroadcastss(mem(rax, r8, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm4) vfmadd231ps(xmm0, xmm3, xmm6) vbroadcastss(mem(rax, r8, 2), xmm2) vbroadcastss(mem(rax, r13, 1), xmm3) vfmadd231ps(xmm0, xmm2, xmm8) vfmadd231ps(xmm0, xmm3, xmm10) vbroadcastss(mem(rax, r8, 4), xmm2) vbroadcastss(mem(rax, r15, 1), xmm3) add(r9, rax) // a += cs_a; vfmadd231ps(xmm0, xmm2, xmm12) vfmadd231ps(xmm0, xmm3, xmm14) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(r12, rcx) // reset rcx to current utile of c. mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), xmm0) // load alpha and duplicate vbroadcastss(mem(rbx), xmm3) // load beta and duplicate vmulps(xmm0, xmm4, xmm4) // scale by alpha vmulps(xmm0, xmm6, xmm6) vmulps(xmm0, xmm8, xmm8) vmulps(xmm0, xmm10, xmm10) vmulps(xmm0, xmm12, xmm12) vmulps(xmm0, xmm14, xmm14) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorps(xmm0, xmm0, xmm0) // set xmm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (8*rs_c) == 8. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vfmadd231ps(mem(rcx), xmm3, xmm4) vmovlpd(xmm4, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), xmm3, xmm6) vmovlpd(xmm6, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), xmm3, xmm8) vmovlpd(xmm8, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), xmm3, xmm10) vmovlpd(xmm10, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), xmm3, xmm12) vmovlpd(xmm12, mem(rcx)) add(rdi, rcx) vfmadd231ps(mem(rcx), xmm3, xmm14) vmovlpd(xmm14, mem(rcx)) jmp(.SDONE) // jump to end. label(.SCOLSTORED) /****6x2 tile is transposed and saved in col major as 2x6*****/ vunpcklps(xmm6, xmm4, xmm0)//a0b0a1b1 vunpcklps(xmm10, xmm8, xmm1)//c0d0c1d1 vshufps(imm(0x44), xmm1, xmm0, xmm2) //01-00-01-00 vshufps(imm(0xee), xmm1, xmm0, xmm4) //11-10-11-10 vfmadd231ps(mem(rcx), xmm3, xmm2) vmovupd(xmm2, mem(rcx)) // store ( gamma00..gamma30 ) lea(mem(rcx, rsi, 1), rcx) // rcx += 1*cs_c vfmadd231ps(mem(rcx), xmm3, xmm4) vmovupd(xmm4, mem(rcx)) // store ( gamma01..gamma31 ) vunpcklps(xmm14, xmm12, xmm0)//eof0e1f1 vpermilps(imm(0x4e),xmm0,xmm5) vmovq(mem(rdx), xmm4) vfmadd231ps(xmm4, xmm3, xmm0) vmovlpd(xmm0, mem(rdx)) // store ( gamma40..gamma50 ) lea(mem(rdx, rsi, 1), rdx) vmovq(mem(rdx), xmm4) vfmadd231ps(xmm4, xmm3, xmm5) vmovlpd(xmm5, mem(rdx)) // store ( gamma41..gamma51 ) jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (8*rs_c) == 8. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovlpd(xmm4, mem(rcx)) add(rdi, rcx) vmovlpd(xmm6, mem(rcx)) add(rdi, rcx) vmovlpd(xmm8, mem(rcx)) add(rdi, rcx) vmovlpd(xmm10, mem(rcx)) add(rdi, rcx) vmovlpd(xmm12, mem(rcx)) add(rdi, rcx) vmovlpd(xmm14, mem(rcx)) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) vunpcklps(xmm6, xmm4, xmm0)//a0b0a1b1 vunpcklps(xmm10, xmm8, xmm1)//c0d0c1d1 vshufps(imm(0x44), xmm1, xmm0, xmm2) //01-00-01-00 vshufps(imm(0xee), xmm1, xmm0, xmm4) //11-10-11-10 vmovupd(xmm2, mem(rcx)) // store ( gamma00..gamma30 ) lea(mem(rcx, rsi, 1), rcx) // rcx += 1*cs_c vmovupd(xmm4, mem(rcx)) // store ( gamma01..gamma31 ) vunpcklps(xmm14, xmm12, xmm0)//eof0e1f1 vmovlpd(xmm0, mem(rdx)) // store ( gamma40..gamma50 ) lea(mem(rdx, rsi, 1), rdx) vmovhpd(xmm0, mem(rdx)) // store ( gamma41..gamma51 ) label(.SDONE) lea(mem(r12, rdi, 4), r12) // lea(mem(r12, rdi, 2), r12) // c_ii = r12 += 6*rs_c //lea(mem(r14, r8, 4), r14) // //lea(mem(r14, r8, 2), r14) // a_ii = r14 += 6*rs_a mov(var(ps_a4), rax) // load ps_a4 lea(mem(r14, rax, 1), r14) // a_ii = r14 += ps_a4 dec(r11) // ii -= 1; jne(.SLOOP6X2I) // iterate again if ii != 0. label(.SRETURN) end_asm( : // output operands (none) : // input operands [m_iter] "m" (m_iter), [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [ps_a4] "m" (ps_a4), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the m dimension, if they exist. if ( m_left ) { const dim_t nr_cur = 2; const dim_t i_edge = m0 - ( dim_t )m_left; float* restrict cij = c + i_edge*rs_c; float* restrict ai = a + m_iter*ps_a; float* restrict bj = b; sgemmsup_ker_ft ker_fps[6] = { NULL, bli_sgemmsup_rv_zen_asm_1x2, bli_sgemmsup_rv_zen_asm_2x2, bli_sgemmsup_rv_zen_asm_3x2, bli_sgemmsup_rv_zen_asm_4x2, bli_sgemmsup_rv_zen_asm_5x2 }; sgemmsup_ker_ft ker_fp = ker_fps[ m_left ]; ker_fp ( conja, conjb, m_left, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); return; } } blis-0.9.0/kernels/zen/3/sup/other/bli_gemmsup_rv_zen_asm_s6x16n.c000066400000000000000000003662251422157504600250450ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define BLIS_ASM_SYNTAX_ATT #include "bli_x86_asm_macros.h" /* rrr: -------- ------ -------- -------- ------ -------- -------- += ------ ... -------- -------- ------ -------- -------- ------ : -------- ------ : rcr: -------- | | | | -------- -------- | | | | -------- -------- += | | | | ... -------- -------- | | | | -------- -------- | | | | : -------- | | | | : Assumptions: - B is row-stored; - A is row- or column-stored; - m0 and n0 are at most MR and NR, respectively. Therefore, this (r)ow-preferential kernel is well-suited for contiguous (v)ector loads on B and single-element broadcasts from A. NOTE: These kernels explicitly support column-oriented IO, implemented via an in-register transpose. And thus they also support the crr and ccr cases, though only crr is ever utilized (because ccr is handled by transposing the operation and executing rcr, which does not incur the cost of the in-register transpose). crr: | | | | | | | | ------ -------- | | | | | | | | ------ -------- | | | | | | | | += ------ ... -------- | | | | | | | | ------ -------- | | | | | | | | ------ : | | | | | | | | ------ : */ // Prototype reference microkernels. //GEMMSUP_KER_PROT( float, f, semmsup_r_zen_ref ) void bli_sgemmsup_rv_zen_asm_6x16n ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { uint64_t m_left = m0 % 6; if ( m_left ) { float* restrict cij = c; float* restrict bj = b; float* restrict ai = a; // We add special handling for slightly inflated MR blocksizes // at edge cases, up to a maximum of 9. if ( 6 < m0 ) { sgemmsup_ker_ft ker_fp1 = NULL; sgemmsup_ker_ft ker_fp2 = NULL; dim_t mr1, mr2; if ( m0 == 7 ) { mr1 = 4; mr2 = 3; ker_fp1 = bli_sgemmsup_rv_zen_asm_4x16n; ker_fp2 = bli_sgemmsup_rv_zen_asm_3x16n; } else if ( m0 == 8 ) { mr1 = 4; mr2 = 4; ker_fp1 = bli_sgemmsup_rv_zen_asm_4x16n; ker_fp2 = bli_sgemmsup_rv_zen_asm_4x16n; } else // if ( m0 == 9 ) { mr1 = 4; mr2 = 5; ker_fp1 = bli_sgemmsup_rv_zen_asm_4x16n; ker_fp2 = bli_sgemmsup_rv_zen_asm_5x16n; } ker_fp1 ( conja, conjb, mr1, n0, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += mr1*rs_c0; ai += mr1*rs_a0; ker_fp2 ( conja, conjb, mr2, n0, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); return; } sgemmsup_ker_ft ker_fps[6] = { NULL, bli_sgemmsup_rv_zen_asm_1x16n, bli_sgemmsup_rv_zen_asm_2x16n, bli_sgemmsup_rv_zen_asm_3x16n, bli_sgemmsup_rv_zen_asm_4x16n, bli_sgemmsup_rv_zen_asm_5x16n }; sgemmsup_ker_ft ker_fp = ker_fps[ m_left ]; ker_fp ( conja, conjb, m_left, n0, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); return; } //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t n_iter = n0 /16; uint64_t n_left = n0 % 16; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // Query the panel stride of B and convert it to units of bytes. uint64_t ps_b = bli_auxinfo_ps_b( data ); uint64_t ps_b4 = ps_b * sizeof( float ); if ( n_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. //mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), r14) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) //lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) // During preamble and loops: // r12 = rcx = c // r14 = rbx = b // read rax from var(a) near beginning of loop // r11 = m dim index ii mov(var(n_iter), r11) // jj = n_iter; label(.SLOOP6X16J) // LOOP OVER jj = [ n_iter ... 1 0 ] vxorps(ymm4, ymm4, ymm4) vxorps(ymm5, ymm5, ymm5) vxorps(ymm6, ymm6, ymm6) vxorps(ymm7, ymm7, ymm7) vxorps(ymm8, ymm8, ymm8) vxorps(ymm9, ymm9, ymm9) vxorps(ymm10, ymm10, ymm10) vxorps(ymm11, ymm11, ymm11) vxorps(ymm12, ymm12, ymm12) vxorps(ymm13, ymm13, ymm13) vxorps(ymm14, ymm14, ymm14) vxorps(ymm15, ymm15, ymm15) mov(var(a), rax) // load address of a. //mov(r12, rcx) // reset rcx to current utile of c. mov(r14, rbx) // reset rbx to current upanel of b. cmp(imm(4), rdi) // set ZF if (8*rs_c) == 8. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored prefetching on c lea(mem(r12, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(r12, 7*8)) // prefetch c + 0*rs_c prefetch(0, mem(r12, rdi, 1, 7*8)) // prefetch c + 1*rs_c prefetch(0, mem(r12, rdi, 2, 7*8)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 7*8)) // prefetch c + 3*rs_c prefetch(0, mem(rdx, rdi, 1, 7*8)) // prefetch c + 4*rs_c prefetch(0, mem(rdx, rdi, 2, 7*8)) // prefetch c + 5*rs_c jmp(.SPOSTPFETCH) // jump to end of prefetching c label(.SCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) lea(mem(r12, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; prefetch(0, mem(r12, 5*8)) // prefetch c + 0*cs_c prefetch(0, mem(r12, rsi, 1, 5*8)) // prefetch c + 1*cs_c prefetch(0, mem(r12, rsi, 2, 5*8)) // prefetch c + 2*cs_c prefetch(0, mem(rdx, 5*8)) // prefetch c + 3*cs_c prefetch(0, mem(rdx, rsi, 1, 5*8)) // prefetch c + 4*cs_c prefetch(0, mem(rdx, rsi, 2, 5*8)) // prefetch c + 5*cs_c lea(mem(rdx, rsi, 2), rdx) // rdx = c + 5*cs_c; prefetch(0, mem(rdx, rsi, 1, 5*8)) // prefetch c + 6*cs_c prefetch(0, mem(rdx, rsi, 2, 5*8)) // prefetch c + 7*cs_c label(.SPOSTPFETCH) // done pre-fetching c mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 prefetch(0, mem(rbx, 11*4)) // pre-fetch line of next upanel of b vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, r8, 4), ymm2) vbroadcastss(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) // ---------------------------------- iteration 1 prefetch(0, mem(rbx, 11*8)) vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, r8, 4), ymm2) vbroadcastss(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) // ---------------------------------- iteration 2 prefetch(0, mem(rbx, 11*8)) vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, r8, 4), ymm2) vbroadcastss(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) // ---------------------------------- iteration 3 prefetch(0, mem(rbx, 11*8)) vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, r8, 4), ymm2) vbroadcastss(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP prefetch(0, mem(rbx, 11*8)) vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, r8, 4), ymm2) vbroadcastss(mem(rax, r15, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) vfmadd231ps(ymm0, ymm3, ymm14) vfmadd231ps(ymm1, ymm3, ymm15) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(r12, rcx) // reset rcx to current utile of c. mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), ymm0) // load alpha and duplicate vbroadcastss(mem(rbx), ymm3) // load beta and duplicate vmulps(ymm0, ymm4, ymm4) // scale by alpha vmulps(ymm0, ymm5, ymm5) vmulps(ymm0, ymm6, ymm6) vmulps(ymm0, ymm7, ymm7) vmulps(ymm0, ymm8, ymm8) vmulps(ymm0, ymm9, ymm9) vmulps(ymm0, ymm10, ymm10) vmulps(ymm0, ymm11, ymm11) vmulps(ymm0, ymm12, ymm12) vmulps(ymm0, ymm13, ymm13) vmulps(ymm0, ymm14, ymm14) vmulps(ymm0, ymm15, ymm15) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vfmadd231ps(mem(rcx), ymm3, ymm4) vmovups(ymm4, mem(rcx)) vfmadd231ps(mem(rcx, rsi,8), ymm3, ymm5) vmovups(ymm5, mem(rcx, rsi,8)) add(rdi, rcx) vfmadd231ps(mem(rcx), ymm3, ymm6) vmovups(ymm6, mem(rcx)) vfmadd231ps(mem(rcx, rsi,8), ymm3, ymm7) vmovups(ymm7, mem(rcx, rsi,8)) add(rdi, rcx) vfmadd231ps(mem(rcx), ymm3, ymm8) vmovups(ymm8, mem(rcx)) vfmadd231ps(mem(rcx, rsi,8), ymm3, ymm9) vmovups(ymm9, mem(rcx, rsi,8)) add(rdi, rcx) vfmadd231ps(mem(rcx), ymm3, ymm10) vmovups(ymm10, mem(rcx)) vfmadd231ps(mem(rcx, rsi,8), ymm3, ymm11) vmovups(ymm11, mem(rcx, rsi,8)) add(rdi, rcx) vfmadd231ps(mem(rcx), ymm3, ymm12) vmovups(ymm12, mem(rcx)) vfmadd231ps(mem(rcx, rsi,8), ymm3, ymm13) vmovups(ymm13, mem(rcx, rsi,8)) add(rdi, rcx) vfmadd231ps(mem(rcx), ymm3, ymm14) vmovups(ymm14, mem(rcx)) vfmadd231ps(mem(rcx, rsi,8), ymm3, ymm15) vmovups(ymm15, mem(rcx, rsi,8)) jmp(.SDONE) // jump to end. label(.SCOLSTORED) vunpcklps(ymm6, ymm4, ymm0) //a0b0a1b1 a4b4a5b5 vunpcklps(ymm10, ymm8, ymm1) //c0d0c1d1 c4d4c5d5 vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx), xmm3, xmm0) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm0, mem(rcx)) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx), xmm3, xmm1) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm1, mem(rcx)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma05..gamma35 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c vunpckhps(ymm6, ymm4, ymm0) vunpckhps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx), xmm3, xmm0) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm0, mem(rcx)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma06..gamma36 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx), xmm3, xmm1) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm1, mem(rcx)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma07..gamma37 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c lea(mem(rcx, rsi, 4), rcx) // rcx += 4*cs_c /***bottom left tile - 2x8 is transposed to top right tile 8x2**********/ vunpcklps(ymm14, ymm12, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(mem(rdx), xmm1, xmm1) vmovhpd(mem(rdx, rsi, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(rdx)) // store ( gamma40..gamma50 ) vmovhpd(xmm0, mem(rdx, rsi, 1)) // store ( gamma41..gamma51 ) lea(mem(rdx, rsi, 4), rax) // rax += 4*cs_c vmovlpd(mem(rax), xmm1, xmm1) vmovhpd(mem(rax, rsi, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm2) vmovlpd(xmm2, mem(rax)) // store ( gamma44..gamma54 ) vmovhpd(xmm2, mem(rax, rsi, 1)) // store ( gamma45..gamma55 ) lea(mem(rdx, rsi, 2), rdx) // rdx += 2*cs_c vunpckhps(ymm14, ymm12, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(mem(rdx), xmm1, xmm1) vmovhpd(mem(rdx, rsi, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(rdx)) // store ( gamma42..gamma52 ) vmovhpd(xmm0, mem(rdx, rsi, 1)) // store ( gamma43..gamma53 ) lea(mem(rdx, rsi, 4), rdx) // rdx += 4*cs_c vmovlpd(mem(rdx), xmm1, xmm1) vmovhpd(mem(rdx, rsi, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm2) vmovlpd(xmm2, mem(rdx)) // store ( gamma46..gamma56 ) vmovhpd(xmm2, mem(rdx, rsi, 1)) // store ( gamma47..gamma57 ) lea(mem(rdx, rsi, 2), rdx) // rdx += 2*cs_c /***top right tile 4x8 is transposed to bottom left tile 8x4**********/ vunpcklps(ymm7, ymm5, ymm0) vunpcklps(ymm11, ymm9, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx), xmm3, xmm0) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm0, mem(rcx)) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx), xmm3, xmm1) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm1, mem(rcx)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma05..gamma35 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c vunpckhps(ymm7, ymm5, ymm0) vunpckhps(ymm11, ymm9, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx), xmm3, xmm0) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm0, mem(rcx)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma06..gamma36 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx), xmm3, xmm1) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm1, mem(rcx)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma07..gamma37 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c /*** bottom right 2x8 is transposed to bottom right tile 8x2*******/ vunpcklps(ymm15, ymm13, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(mem(rdx), xmm1, xmm1) vmovhpd(mem(rdx, rsi, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(rdx)) // store ( gamma40..gamma50 ) vmovhpd(xmm0, mem(rdx, rsi, 1)) // store ( gamma41..gamma51 ) lea(mem(rdx, rsi, 4), rax) // rax += 4*cs_c vmovlpd(mem(rax), xmm1, xmm1) vmovhpd(mem(rax, rsi, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm2) vmovlpd(xmm2, mem(rax)) // store ( gamma44..gamma54 ) vmovhpd(xmm2, mem(rax, rsi, 1)) // store ( gamma45..gamma55 ) lea(mem(rdx, rsi, 2), rdx) // rdx += 2*cs_c vunpckhps(ymm15, ymm13, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(mem(rdx), xmm1, xmm1) vmovhpd(mem(rdx, rsi, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm0) vmovlpd(xmm0, mem(rdx)) // store ( gamma42..gamma52 ) vmovhpd(xmm0, mem(rdx, rsi, 1)) // store ( gamma43..gamma53 ) lea(mem(rdx, rsi, 4), rdx) // rdx += 4*cs_c vmovlpd(mem(rdx), xmm1, xmm1) vmovhpd(mem(rdx, rsi, 1), xmm1, xmm1) vfmadd231ps(xmm1, xmm3, xmm2) vmovlpd(xmm2, mem(rdx)) // store ( gamma46..gamma56 ) vmovhpd(xmm2, mem(rdx, rsi, 1)) // store ( gamma47..gamma57 ) jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (8*rs_c) == 8. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovups(ymm4, mem(rcx)) vmovups(ymm5, mem(rcx, rsi, 8)) add(rdi, rcx) vmovups(ymm6, mem(rcx)) vmovups(ymm7, mem(rcx, rsi, 8)) add(rdi, rcx) vmovups(ymm8, mem(rcx)) vmovups(ymm9, mem(rcx, rsi, 8)) add(rdi, rcx) vmovups(ymm10, mem(rcx)) vmovups(ymm11, mem(rcx, rsi, 8)) add(rdi, rcx) vmovups(ymm12, mem(rcx)) vmovups(ymm13, mem(rcx, rsi, 8)) add(rdi, rcx) vmovups(ymm14, mem(rcx)) vmovups(ymm15, mem(rcx, rsi, 8)) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) /****6x16 tile going to save into 16x6 tile in C*****/ /******************top left tile 8x4***************************/ vunpcklps(ymm6, ymm4, ymm0) vunpcklps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx)) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) lea(mem(rcx, rsi, 1), rcx) // rcx += 1*cs_c vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma05..gamma35 ) lea(mem(rcx, rsi, 1), rcx) // rcx += 1*cs_c vunpckhps(ymm6, ymm4, ymm0) vunpckhps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma06..gamma36 ) lea(mem(rcx, rsi, 1), rcx) // rcx += 1*cs_c vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma07..gamma37 ) lea(mem(rcx, rsi, 1), rcx) // rcx += 1*cs_c lea(mem(rcx, rsi, 4), rcx) // rcx += 4*cs_c /******************top right tile 8x2***************************/ vunpcklps(ymm14, ymm12, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(xmm0, mem(rdx)) // store ( gamma40..gamma50 ) vmovlpd(xmm2, mem(rdx, rsi, 4)) // store ( gamma44..gamma54 ) lea(mem(rdx, rsi, 1), rdx) vmovhpd(xmm0, mem(rdx)) // store ( gamma41..gamma51 ) vmovhpd(xmm2, mem(rdx, rsi, 4)) // store ( gamma45..gamma55 ) lea(mem(rdx, rsi, 1), rdx) vunpckhps(ymm14, ymm12, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(xmm0, mem(rdx)) // store ( gamma42..gamma52 ) vmovlpd(xmm2, mem(rdx, rsi, 4)) // store ( gamma46..gamma56 ) lea(mem(rdx, rsi, 1), rdx) vmovhpd(xmm0, mem(rdx)) // store ( gamma43..gamma53 ) vmovhpd(xmm2, mem(rdx, rsi, 4)) // store ( gamma47..gamma57 ) lea(mem(rdx, rsi, 1), rdx) lea(mem(rdx, rsi, 4), rdx) // rdx += 8*cs_c /******************bottom left tile 8x4***************************/ vunpcklps(ymm7, ymm5, ymm0) vunpcklps(ymm11, ymm9, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx)) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) lea(mem(rcx, rsi, 1), rcx) // rcx += 1*cs_c vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma05..gamma35 ) lea(mem(rcx, rsi, 1), rcx) // rcx += 1*cs_c vunpckhps(ymm7, ymm5, ymm0) vunpckhps(ymm11, ymm9, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma06..gamma36 ) lea(mem(rcx, rsi, 1), rcx) // rcx += 1*cs_c vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma07..gamma37 ) /******************bottom right tile 8x2***************************/ vunpcklps(ymm15, ymm13, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(xmm0, mem(rdx)) // store ( gamma40..gamma50 ) vmovlpd(xmm2, mem(rdx, rsi, 4)) // store ( gamma44..gamma54 ) lea(mem(rdx, rsi, 1), rdx) vmovhpd(xmm0, mem(rdx)) // store ( gamma41..gamma51 ) vmovhpd(xmm2, mem(rdx, rsi, 4)) // store ( gamma45..gamma55 ) lea(mem(rdx, rsi, 1), rdx) vunpckhps(ymm15, ymm13, ymm0) vextractf128(imm(0x1), ymm0, xmm2) vmovlpd(xmm0, mem(rdx)) // store ( gamma42..gamma52 ) vmovlpd(xmm2, mem(rdx, rsi, 4)) // store ( gamma46..gamma56 ) lea(mem(rdx, rsi, 1), rdx) vmovhpd(xmm0, mem(rdx)) // store ( gamma43..gamma53 ) vmovhpd(xmm2, mem(rdx, rsi, 4)) // store ( gamma47..gamma57 ) label(.SDONE) lea(mem(r12, rsi, 8), r12) // c_jj = r12 += 8*cs_c lea(mem(r12, rsi, 8), r12) // c_jj = r12 += 8*cs_c //add(imm(4*16), r14) // b_jj = r14 += 8*cs_b mov(var(ps_b4), rbx) // load ps_b4 lea(mem(r14, rbx, 1), r14) // a_ii = r14 += ps_b4 dec(r11) // jj -= 1; jne(.SLOOP6X16J) // iterate again if jj != 0. label(.SRETURN) end_asm( : // output operands (none) : // input operands [n_iter] "m" (n_iter), [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [ps_b4] "m" (ps_b4), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the m dimension, if they exist. if ( n_left ) { const dim_t mr_cur = 6; const dim_t j_edge = n0 - ( dim_t )n_left; float* restrict cij = c + j_edge*cs_c; float* restrict ai = a; float* restrict bj = b + n_iter * ps_b; if ( 8 <= n_left ) { const dim_t nr_cur = 8; bli_sgemmsup_rv_zen_asm_6x8 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 4 <= n_left ) { const dim_t nr_cur = 4; bli_sgemmsup_rv_zen_asm_6x4 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 2 <= n_left ) { const dim_t nr_cur = 2; bli_sgemmsup_rv_zen_asm_6x2 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 1 == n_left ) { #if 1 const dim_t nr_cur = 1; bli_sgemmsup_r_zen_ref_6x1 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); #else bli_sgemv_ex ( BLIS_NO_TRANSPOSE, conjb, m0, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, beta, cij, rs_c0, cntx, NULL ); #endif } } } void bli_sgemmsup_rv_zen_asm_5x16n ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t n_iter = n0 /16; uint64_t n_left = n0 % 16; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // Query the panel stride of B and convert it to units of bytes. uint64_t ps_b = bli_auxinfo_ps_b( data ); uint64_t ps_b4 = ps_b * sizeof( float ); if ( n_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() //mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a mov(var(b), r14) // load address of b. mov(var(rs_b), r10) // load rs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) // During preamble and loops: // r12 = rcx = c // r14 = rbx = b // read rax from var(a) near beginning of loop // r11 = m dim index ii mov(var(n_iter), r11) // jj = n_iter; label(.SLOOP6X16J) // LOOP OVER jj = [ n_iter ... 1 0 ] vxorps(ymm4, ymm4, ymm4) vxorps(ymm5, ymm5, ymm5) vxorps(ymm6, ymm6, ymm6) vxorps(ymm7, ymm7, ymm7) vxorps(ymm8, ymm8, ymm8) vxorps(ymm9, ymm9, ymm9) vxorps(ymm10, ymm10, ymm10) vxorps(ymm11, ymm11, ymm11) vxorps(ymm12, ymm12, ymm12) vxorps(ymm13, ymm13, ymm13) mov(var(a), rax) // load address of a. //mov(r12, rcx) // reset rcx to current utile of c. mov(r14, rbx) // reset rbx to current upanel of b. cmp(imm(4), rdi) // set ZF if (8*rs_c) == 8. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored prefetching on c lea(mem(r12, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(r12, 7*8)) // prefetch c + 0*rs_c prefetch(0, mem(r12, rdi, 1, 7*8)) // prefetch c + 1*rs_c prefetch(0, mem(r12, rdi, 2, 7*8)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 7*8)) // prefetch c + 3*rs_c prefetch(0, mem(rdx, rdi, 1, 7*8)) // prefetch c + 4*rs_c jmp(.SPOSTPFETCH) // jump to end of prefetching c label(.SCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) lea(mem(r12, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; prefetch(0, mem(r12, 4*8)) // prefetch c + 0*cs_c prefetch(0, mem(r12, rsi, 1, 4*8)) // prefetch c + 1*cs_c prefetch(0, mem(r12, rsi, 2, 4*8)) // prefetch c + 2*cs_c prefetch(0, mem(rdx, 4*8)) // prefetch c + 3*cs_c prefetch(0, mem(rdx, rsi, 1, 4*8)) // prefetch c + 4*cs_c prefetch(0, mem(rdx, rsi, 2, 4*8)) // prefetch c + 5*cs_c lea(mem(rdx, rsi, 2), rdx) // rdx = c + 5*cs_c; prefetch(0, mem(rdx, rsi, 1, 4*8)) // prefetch c + 6*cs_c prefetch(0, mem(rdx, rsi, 2, 4*8)) // prefetch c + 7*cs_c label(.SPOSTPFETCH) // done prefetching c lea(mem(r10, r10, 2), rcx) // rcx = 3*rs_b; //lea(mem(rbx, r10, 8), rdx) // use rdx for prefetching b. //lea(mem(rdx, r10, 8), rdx) // rdx = b + 16*rs_b; mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 prefetch(0, mem(rbx, 11*8)) // prefetch line of next upanel of b vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) // ---------------------------------- iteration 1 prefetch(0, mem(rbx, 11*8)) vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) // ---------------------------------- iteration 2 prefetch(0, mem(rbx, 11*8)) vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) // ---------------------------------- iteration 3 prefetch(0, mem(rbx, 11*8)) vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP prefetch(0, mem(rbx, 11*8)) vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) vbroadcastss(mem(rax, r8, 4), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm12) vfmadd231ps(ymm1, ymm2, ymm13) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(r12, rcx) // reset rcx to current utile of c. mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), ymm0) // load alpha and duplicate vbroadcastss(mem(rbx), ymm3) // load beta and duplicate vmulps(ymm0, ymm4, ymm4) // scale by alpha vmulps(ymm0, ymm5, ymm5) vmulps(ymm0, ymm6, ymm6) vmulps(ymm0, ymm7, ymm7) vmulps(ymm0, ymm8, ymm8) vmulps(ymm0, ymm9, ymm9) vmulps(ymm0, ymm10, ymm10) vmulps(ymm0, ymm11, ymm11) vmulps(ymm0, ymm12, ymm12) vmulps(ymm0, ymm13, ymm13) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) lea(mem(rcx, rdi, 4), rdx) // load address of c + 4*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (8*rs_c) == 8. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vfmadd231ps(mem(rcx), ymm3, ymm4) vmovups(ymm4, mem(rcx)) vfmadd231ps(mem(rcx, rsi,8), ymm3, ymm5) vmovups(ymm5, mem(rcx, rsi,8)) add(rdi, rcx) vfmadd231ps(mem(rcx), ymm3, ymm6) vmovups(ymm6, mem(rcx)) vfmadd231ps(mem(rcx, rsi,8), ymm3, ymm7) vmovups(ymm7, mem(rcx, rsi,8)) add(rdi, rcx) vfmadd231ps(mem(rcx), ymm3, ymm8) vmovups(ymm8, mem(rcx)) vfmadd231ps(mem(rcx, rsi,8), ymm3, ymm9) vmovups(ymm9, mem(rcx, rsi,8)) add(rdi, rcx) vfmadd231ps(mem(rcx), ymm3, ymm10) vmovups(ymm10, mem(rcx)) vfmadd231ps(mem(rcx, rsi,8), ymm3, ymm11) vmovups(ymm11, mem(rcx, rsi,8)) add(rdi, rcx) vfmadd231ps(mem(rcx), ymm3, ymm12) vmovups(ymm12, mem(rcx)) vfmadd231ps(mem(rcx, rsi,8), ymm3, ymm13) vmovups(ymm13, mem(rcx, rsi,8)) jmp(.SDONE) // jump to end. label(.SCOLSTORED) vunpcklps(ymm6, ymm4, ymm0) //a0b0a1b1 a4b4a5b5 vunpcklps(ymm10, ymm8, ymm1) //c0d0c1d1 c4d4c5d5 vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx), xmm3, xmm0) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm0, mem(rcx)) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx), xmm3, xmm1) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm1, mem(rcx)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma05..gamma35 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c vunpckhps(ymm6, ymm4, ymm0) vunpckhps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx), xmm3, xmm0) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm0, mem(rcx)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma06..gamma36 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx), xmm3, xmm1) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm1, mem(rcx)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma07..gamma37 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c lea(mem(rcx, rsi, 4), rcx) // rcx += 4*cs_c /********************************************/ vextractf128(imm(0x0), ymm12, xmm0)//e0-e3 vmovss(mem(rdx),xmm4) vmovss(mem(rdx, rsi, 1),xmm6) vmovss(mem(rdx, rsi, 2),xmm8) vmovss(mem(rdx, rax, 1),xmm10) vshufps(imm(0x01), xmm0, xmm0,xmm1) vshufps(imm(0x02), xmm0, xmm0,xmm2) vshufps(imm(0x03), xmm0, xmm0,xmm14) vfmadd231ps(xmm4, xmm3, xmm0)//e0 vfmadd231ps(xmm6, xmm3, xmm1)//e1 vfmadd231ps(xmm8, xmm3, xmm2)//e2 vfmadd231ps(xmm10, xmm3, xmm14)//e3 vmovss(xmm0, mem(rdx)) vmovss(xmm1, mem(rdx, rsi, 1)) vmovss(xmm2, mem(rdx, rsi, 2)) vmovss(xmm14, mem(rdx, rax, 1)) lea(mem(rdx, rsi, 4), rdx) // rdx += 4*cs_c vextractf128(imm(0x1), ymm12, xmm0)//e4-e7 vmovss(mem(rdx),xmm4) vmovss(mem(rdx, rsi, 1),xmm6) vmovss(mem(rdx, rsi, 2),xmm8) vmovss(mem(rdx, rax, 1),xmm10) vshufps(imm(0x01), xmm0, xmm0,xmm1) vshufps(imm(0x02), xmm0, xmm0,xmm2) vshufps(imm(0x03), xmm0, xmm0,xmm14) vfmadd231ps(xmm4, xmm3, xmm0)//e0 vfmadd231ps(xmm6, xmm3, xmm1)//e1 vfmadd231ps(xmm8, xmm3, xmm2)//e2 vfmadd231ps(xmm10, xmm3, xmm14)//e3 vmovss(xmm0, mem(rdx)) vmovss(xmm1, mem(rdx, rsi, 1)) vmovss(xmm2, mem(rdx, rsi, 2)) vmovss(xmm14, mem(rdx, rax, 1)) lea(mem(rdx, rsi, 4), rdx) // rdx += 4*cs_c /*********************************************/ vunpcklps(ymm7, ymm5, ymm0) vunpcklps(ymm11, ymm9, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx), xmm3, xmm0) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm0, mem(rcx)) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx), xmm3, xmm1) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm1, mem(rcx)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma05..gamma35 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c vunpckhps(ymm7, ymm5, ymm0) vunpckhps(ymm11, ymm9, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx), xmm3, xmm0) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm0, mem(rcx)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma06..gamma36 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx), xmm3, xmm1) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm1, mem(rcx)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma07..gamma37 ) //lea(mem(rcx, rsi, 8), rcx) // rcx += 8*cs_c vextractf128(imm(0x0), ymm13, xmm0)//e0-e3 vmovss(mem(rdx),xmm4) vmovss(mem(rdx, rsi, 1),xmm6) vmovss(mem(rdx, rsi, 2),xmm8) vmovss(mem(rdx, rax, 1),xmm10) vshufps(imm(0x01), xmm0,xmm0, xmm1) vshufps(imm(0x02), xmm0,xmm0, xmm2) vshufps(imm(0x03), xmm0,xmm0, xmm14) vfmadd231ps(xmm4, xmm3, xmm0)//e0 vfmadd231ps(xmm6, xmm3, xmm1)//e1 vfmadd231ps(xmm8, xmm3, xmm2)//e2 vfmadd231ps(xmm10, xmm3, xmm14)//e3 vmovss(xmm0, mem(rdx)) vmovss(xmm1, mem(rdx, rsi, 1)) vmovss(xmm2, mem(rdx, rsi, 2)) vmovss(xmm14, mem(rdx, rax, 1)) lea(mem(rdx, rsi, 4), rdx) // rdx += 4*cs_c vextractf128(imm(0x1), ymm13, xmm0)//e4-e7 vmovss(mem(rdx),xmm4) vmovss(mem(rdx, rsi, 1),xmm6) vmovss(mem(rdx, rsi, 2),xmm8) vmovss(mem(rdx, rax, 1),xmm10) vshufps(imm(0x01), xmm0,xmm0, xmm1) vshufps(imm(0x02), xmm0,xmm0, xmm2) vshufps(imm(0x03), xmm0,xmm0, xmm14) vfmadd231ps(xmm4, xmm3, xmm0)//e0 vfmadd231ps(xmm6, xmm3, xmm1)//e1 vfmadd231ps(xmm8, xmm3, xmm2)//e2 vfmadd231ps(xmm10, xmm3, xmm14)//e3 vmovss(xmm0, mem(rdx)) vmovss(xmm1, mem(rdx, rsi, 1)) vmovss(xmm2, mem(rdx, rsi, 2)) vmovss(xmm14, mem(rdx, rax, 1)) jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (8*rs_c) == 8. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovups(ymm4, mem(rcx)) vmovups(ymm5, mem(rcx, rsi,8)) add(rdi, rcx) vmovups(ymm6, mem(rcx)) vmovups(ymm7, mem(rcx, rsi,8)) add(rdi, rcx) vmovups(ymm8, mem(rcx)) vmovups(ymm9, mem(rcx, rsi,8)) add(rdi, rcx) vmovups(ymm10, mem(rcx)) vmovups(ymm11, mem(rcx, rsi,8)) add(rdi, rcx) vmovups(ymm12, mem(rcx)) vmovups(ymm13, mem(rcx, rsi,8)) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) vunpcklps(ymm6, ymm4, ymm0) //a0b0a1b1 a4b4a5b5 vunpcklps(ymm10, ymm8, ymm1) //c0d0c1d1 c4d4c5d5 vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx)) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma05..gamma35 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c vunpckhps(ymm6, ymm4, ymm0) vunpckhps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma06..gamma36 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma07..gamma37 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c lea(mem(rcx, rsi, 4), rcx) // rcx += 4*cs_c /********************************************/ vextractf128(imm(0x0), ymm12, xmm0)//e0-e3 vshufps(imm(0x01), xmm0, xmm0,xmm1) vshufps(imm(0x02), xmm0, xmm0,xmm2) vshufps(imm(0x03), xmm0, xmm0,xmm14) vmovss(xmm0, mem(rdx)) vmovss(xmm1, mem(rdx, rsi, 1)) vmovss(xmm2, mem(rdx, rsi, 2)) vmovss(xmm14, mem(rdx, rax, 1)) lea(mem(rdx, rsi, 4), rdx) // rdx += 4*cs_c vextractf128(imm(0x1), ymm12, xmm0)//e4-e7 vshufps(imm(0x01), xmm0, xmm0,xmm1) vshufps(imm(0x02), xmm0, xmm0,xmm2) vshufps(imm(0x03), xmm0, xmm0,xmm14) vmovss(xmm0, mem(rdx)) vmovss(xmm1, mem(rdx, rsi, 1)) vmovss(xmm2, mem(rdx, rsi, 2)) vmovss(xmm14, mem(rdx, rax, 1)) lea(mem(rdx, rsi, 4), rdx) // rdx += 4*cs_c /*********************************************/ vunpcklps(ymm7, ymm5, ymm0) vunpcklps(ymm11, ymm9, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx)) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma05..gamma35 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c vunpckhps(ymm7, ymm5, ymm0) vunpckhps(ymm11, ymm9, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma06..gamma36 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma07..gamma37 ) vextractf128(imm(0x0), ymm13, xmm0)//e0-e3 vshufps(imm(0x01), xmm0,xmm0, xmm1) vshufps(imm(0x02), xmm0,xmm0, xmm2) vshufps(imm(0x03), xmm0,xmm0, xmm14) vmovss(xmm0, mem(rdx)) vmovss(xmm1, mem(rdx, rsi, 1)) vmovss(xmm2, mem(rdx, rsi, 2)) vmovss(xmm14, mem(rdx, rax, 1)) lea(mem(rdx, rsi, 4), rdx) // rdx += 4*cs_c vextractf128(imm(0x1), ymm13, xmm0)//e4-e7 vshufps(imm(0x01), xmm0,xmm0, xmm1) vshufps(imm(0x02), xmm0,xmm0, xmm2) vshufps(imm(0x03), xmm0,xmm0, xmm14) vmovss(xmm0, mem(rdx)) vmovss(xmm1, mem(rdx, rsi, 1)) vmovss(xmm2, mem(rdx, rsi, 2)) vmovss(xmm14, mem(rdx, rax, 1)) label(.SDONE) lea(mem(r12, rsi, 8), r12) // c_jj = r12 += 8*cs_c lea(mem(r12, rsi, 8), r12) // c_jj = r12 += 8*cs_c //add(imm(4*16), r14) // b_jj = r14 += 8*cs_b mov(var(ps_b4), rbx) // load ps_b4 lea(mem(r14, rbx, 1), r14) // a_ii = r14 += ps_b4 dec(r11) // jj -= 1; jne(.SLOOP6X16J) // iterate again if jj != 0. label(.SRETURN) end_asm( : // output operands (none) : // input operands [n_iter] "m" (n_iter), [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [ps_b4] "m" (ps_b4), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the m dimension, if they exist. if ( n_left ) { const dim_t mr_cur = 5; const dim_t j_edge = n0 - ( dim_t )n_left; float* restrict cij = c + j_edge*cs_c; float* restrict ai = a; float* restrict bj = b + n_iter * ps_b; if ( 8 <= n_left ) { const dim_t nr_cur = 8; bli_sgemmsup_rv_zen_asm_5x8 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 4 <= n_left ) { const dim_t nr_cur = 4; bli_sgemmsup_rv_zen_asm_5x4 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 2 <= n_left ) { const dim_t nr_cur = 2; bli_sgemmsup_rv_zen_asm_5x2 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 1 == n_left ) { #if 1 const dim_t nr_cur = 1; bli_sgemmsup_r_zen_ref_5x1 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); #else bli_sgemv_ex ( BLIS_NO_TRANSPOSE, conjb, m0, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, beta, cij, rs_c0, cntx, NULL ); #endif } } } void bli_sgemmsup_rv_zen_asm_4x16n ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t n_iter = n0 /16; uint64_t n_left = n0 % 16; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // Query the panel stride of B and convert it to units of bytes. uint64_t ps_b = bli_auxinfo_ps_b( data ); uint64_t ps_b4 = ps_b * sizeof( float ); if ( n_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() //vzeroall() // zero all xmm/ymm registers. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) lea(mem(r8, r8, 2), r13) // r13 = 3*rs_a //lea(mem(r8, r8, 4), r15) // r15 = 5*rs_a mov(var(b), r14) // load address of b. mov(var(rs_b), r10) // load rs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) // During preamble and loops: // r12 = rcx = c // r14 = rbx = b // read rax from var(a) near beginning of loop // r11 = m dim index ii mov(var(n_iter), r11) // jj = n_iter; label(.SLOOP4X16J) // LOOP OVER jj = [ n_iter ... 1 0 ] vxorps(ymm4, ymm4, ymm4) vxorps(ymm5, ymm5, ymm5) vxorps(ymm6, ymm6, ymm6) vxorps(ymm7, ymm7, ymm7) vxorps(ymm8, ymm8, ymm8) vxorps(ymm9, ymm9, ymm9) vxorps(ymm10, ymm10, ymm10) vxorps(ymm11, ymm11, ymm11) mov(var(a), rax) // load address of a. mov(r14, rbx) // reset rbx to current upanel of b. cmp(imm(4), rdi) // set ZF if (8*rs_c) == 8. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored prefetching on c lea(mem(r12, rdi, 2), rdx) // lea(mem(rdx, rdi, 1), rdx) // rdx = c + 3*rs_c; prefetch(0, mem(r12, 7*8)) // prefetch c + 0*rs_c prefetch(0, mem(r12, rdi, 1, 7*8)) // prefetch c + 1*rs_c prefetch(0, mem(r12, rdi, 2, 7*8)) // prefetch c + 2*rs_c prefetch(0, mem(rdx, 7*8)) // prefetch c + 3*rs_c jmp(.SPOSTPFETCH) // jump to end of prefetching c label(.SCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) lea(mem(r12, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; prefetch(0, mem(r12, 3*8)) // prefetch c + 0*cs_c prefetch(0, mem(r12, rsi, 1, 3*8)) // prefetch c + 1*cs_c prefetch(0, mem(r12, rsi, 2, 3*8)) // prefetch c + 2*cs_c prefetch(0, mem(rdx, 3*8)) // prefetch c + 3*cs_c prefetch(0, mem(rdx, rsi, 1, 3*8)) // prefetch c + 4*cs_c prefetch(0, mem(rdx, rsi, 2, 3*8)) // prefetch c + 5*cs_c lea(mem(rdx, rsi, 2), rdx) // rdx = c + 5*cs_c; prefetch(0, mem(rdx, rsi, 1, 3*8)) // prefetch c + 6*cs_c prefetch(0, mem(rdx, rsi, 2, 3*8)) // prefetch c + 7*cs_c label(.SPOSTPFETCH) // done prefetching c mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 prefetch(0, mem(rbx, 11*8)) // prefetch line of next upanel of b vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) // ---------------------------------- iteration 1 prefetch(0, mem(rbx, 11*8)) vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) // ---------------------------------- iteration 2 prefetch(0, mem(rbx, 11*8)) vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) // ---------------------------------- iteration 3 prefetch(0, mem(rbx, 11*8)) vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP prefetch(0, mem(rbx, 11*8)) vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) vbroadcastss(mem(rax, r13, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) vfmadd231ps(ymm0, ymm3, ymm10) vfmadd231ps(ymm1, ymm3, ymm11) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(r12, rcx) // reset rcx to current utile of c. mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), ymm0) // load alpha and duplicate vbroadcastss(mem(rbx), ymm3) // load beta and duplicate vmulps(ymm0, ymm4, ymm4) // scale by alpha vmulps(ymm0, ymm5, ymm5) vmulps(ymm0, ymm6, ymm6) vmulps(ymm0, ymm7, ymm7) vmulps(ymm0, ymm8, ymm8) vmulps(ymm0, ymm9, ymm9) vmulps(ymm0, ymm10, ymm10) vmulps(ymm0, ymm11, ymm11) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vfmadd231ps(mem(rcx), ymm3, ymm4) vmovups(ymm4, mem(rcx)) vfmadd231ps(mem(rcx, rsi,8), ymm3, ymm5) vmovups(ymm5, mem(rcx, rsi,8)) add(rdi, rcx) vfmadd231ps(mem(rcx), ymm3, ymm6) vmovups(ymm6, mem(rcx)) vfmadd231ps(mem(rcx, rsi,8), ymm3, ymm7) vmovups(ymm7, mem(rcx, rsi,8)) add(rdi, rcx) vfmadd231ps(mem(rcx), ymm3, ymm8) vmovups(ymm8, mem(rcx)) vfmadd231ps(mem(rcx, rsi,8), ymm3, ymm9) vmovups(ymm9, mem(rcx, rsi,8)) add(rdi, rcx) vfmadd231ps(mem(rcx), ymm3, ymm10) vmovups(ymm10, mem(rcx)) vfmadd231ps(mem(rcx, rsi,8), ymm3, ymm11) vmovups(ymm11, mem(rcx, rsi,8)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORED) vunpcklps(ymm6, ymm4, ymm0) //a0b0a1b1 a4b4a5b5 vunpcklps(ymm10, ymm8, ymm1) //c0d0c1d1 c4d4c5d5 vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx), xmm3, xmm0) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm0, mem(rcx)) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx), xmm3, xmm1) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm1, mem(rcx)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma05..gamma35 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c vunpckhps(ymm6, ymm4, ymm0) vunpckhps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx), xmm3, xmm0) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm0, mem(rcx)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma06..gamma36 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx), xmm3, xmm1) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm1, mem(rcx)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma07..gamma37 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c lea(mem(rcx, rsi, 4), rcx) // rcx += 4*cs_c vunpcklps(ymm7, ymm5, ymm0) vunpcklps(ymm11, ymm9, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx), xmm3, xmm0) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm0, mem(rcx)) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx), xmm3, xmm1) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm1, mem(rcx)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma05..gamma35 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c vunpckhps(ymm7, ymm5, ymm0) vunpckhps(ymm11, ymm9, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vfmadd231ps(mem(rcx), xmm3, xmm0) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm0, mem(rcx)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma06..gamma36 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c vextractf128(imm(0x1), ymm1, xmm2) vfmadd231ps(mem(rcx), xmm3, xmm1) vfmadd231ps(mem(rcx, rsi, 4), xmm3, xmm2) vmovups(xmm1, mem(rcx)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma07..gamma37 ) jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (8*rs_c) == 8. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovups(ymm4, mem(rcx)) vmovups(ymm5, mem(rcx, rsi,8)) add(rdi, rcx) vmovups(ymm6, mem(rcx)) vmovups(ymm7, mem(rcx, rsi,8)) add(rdi, rcx) vmovups(ymm8, mem(rcx)) vmovups(ymm9, mem(rcx, rsi,8)) add(rdi, rcx) vmovups(ymm10, mem(rcx)) vmovups(ymm11, mem(rcx, rsi,8)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) vunpcklps(ymm6, ymm4, ymm0) //a0b0a1b1 a4b4a5b5 vunpcklps(ymm10, ymm8, ymm1) //c0d0c1d1 c4d4c5d5 vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx)) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma05..gamma35 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c vunpckhps(ymm6, ymm4, ymm0) vunpckhps(ymm10, ymm8, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma06..gamma36 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma07..gamma37 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c lea(mem(rcx, rsi, 4), rcx) // rcx += 4*cs_c vunpcklps(ymm7, ymm5, ymm0) vunpcklps(ymm11, ymm9, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx)) // store ( gamma00..gamma30 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma04..gamma34 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx)) // store ( gamma01..gamma31 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma05..gamma35 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c vunpckhps(ymm7, ymm5, ymm0) vunpckhps(ymm11, ymm9, ymm1) vshufps(imm(0x4e), ymm1, ymm0, ymm2) vblendps(imm(0xcc), ymm2, ymm0, ymm0) vblendps(imm(0x33), ymm2, ymm1, ymm1) vextractf128(imm(0x1), ymm0, xmm2) vmovups(xmm0, mem(rcx)) // store ( gamma02..gamma32 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma06..gamma36 ) lea(mem(rcx, rsi, 1), rcx) // rcx += cs_c vextractf128(imm(0x1), ymm1, xmm2) vmovups(xmm1, mem(rcx)) // store ( gamma03..gamma33 ) vmovups(xmm2, mem(rcx, rsi, 4)) // store ( gamma07..gamma37 ) label(.SDONE) lea(mem(r12, rsi, 8), r12) // c_jj = r12 += 8*cs_c lea(mem(r12, rsi, 8), r12) // c_jj = r12 += 8*cs_c //add(imm(4*16), r14) // b_jj = r14 += 8*cs_b mov(var(ps_b4), rbx) // load ps_b4 lea(mem(r14, rbx, 1), r14) // a_ii = r14 += ps_b4 dec(r11) // jj -= 1; jne(.SLOOP4X16J) // iterate again if jj != 0. label(.SRETURN) end_asm( : // output operands (none) : // input operands [n_iter] "m" (n_iter), [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [ps_b4] "m" (ps_b4), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the m dimension, if they exist. if ( n_left ) { const dim_t mr_cur = 4; const dim_t j_edge = n0 - ( dim_t )n_left; float* restrict cij = c + j_edge*cs_c; float* restrict ai = a; float* restrict bj = b + n_iter * ps_b; if ( 8 <= n_left ) { const dim_t nr_cur = 8; bli_sgemmsup_rv_zen_asm_4x8 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 4 <= n_left ) { const dim_t nr_cur = 4; bli_sgemmsup_rv_zen_asm_4x4 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 2 <= n_left ) { const dim_t nr_cur = 2; bli_sgemmsup_rv_zen_asm_4x2 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 1 == n_left ) { const dim_t nr_cur = 1; bli_sgemmsup_r_zen_ref_4x1 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); } } } void bli_sgemmsup_rv_zen_asm_3x16n ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t n_iter = n0 /16; uint64_t n_left = n0 % 16; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // Query the panel stride of B and convert it to units of bytes. uint64_t ps_b = bli_auxinfo_ps_b( data ); uint64_t ps_b4 = ps_b * sizeof( float ); if ( n_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() //mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) mov(var(b), r14) // load address of b. mov(var(rs_b), r10) // load rs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) // During preamble and loops: // r12 = rcx = c // r14 = rbx = b // read rax from var(a) near beginning of loop // r11 = m dim index ii mov(var(n_iter), r11) // jj = n_iter; label(.SLOOP4X16J) // LOOP OVER jj = [ n_iter ... 1 0 ] vxorps(ymm4, ymm4, ymm4) vxorps(ymm5, ymm5, ymm5) vxorps(ymm6, ymm6, ymm6) vxorps(ymm7, ymm7, ymm7) vxorps(ymm8, ymm8, ymm8) vxorps(ymm9, ymm9, ymm9) vxorps(ymm10, ymm10, ymm10) vxorps(ymm11, ymm11, ymm11) vxorps(ymm12, ymm12, ymm12) vxorps(ymm13, ymm13, ymm13) vxorps(ymm14, ymm14, ymm14) vxorps(ymm15, ymm15, ymm15) mov(var(a), rax) // load address of a. mov(r14, rbx) // reset rbx to current upanel of b. cmp(imm(4), rdi) // set ZF if (8*rs_c) == 8. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored prefetching on c prefetch(0, mem(r12, 7*8)) // prefetch c + 0*rs_c prefetch(0, mem(r12, rdi, 1, 7*8)) // prefetch c + 1*rs_c prefetch(0, mem(r12, rdi, 2, 7*8)) // prefetch c + 2*rs_c jmp(.SPOSTPFETCH) // jump to end of prefetching c label(.SCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) lea(mem(r12, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; prefetch(0, mem(r12, 2*8)) // prefetch c + 0*cs_c prefetch(0, mem(r12, rsi, 1, 2*8)) // prefetch c + 1*cs_c prefetch(0, mem(r12, rsi, 2, 2*8)) // prefetch c + 2*cs_c prefetch(0, mem(rdx, 2*8)) // prefetch c + 3*cs_c prefetch(0, mem(rdx, rsi, 1, 2*8)) // prefetch c + 4*cs_c prefetch(0, mem(rdx, rsi, 2, 2*8)) // prefetch c + 5*cs_c lea(mem(rdx, rsi, 2), rdx) // rdx = c + 5*cs_c; prefetch(0, mem(rdx, rsi, 1, 2*8)) // prefetch c + 6*cs_c prefetch(0, mem(rdx, rsi, 2, 2*8)) // prefetch c + 7*cs_c label(.SPOSTPFETCH) // done prefetching c mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 prefetch(0, mem(rbx, 11*8)) // prefetch line of next upanel of b vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) // ---------------------------------- iteration 1 prefetch(0, mem(rbx, 11*8)) vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) // ---------------------------------- iteration 2 prefetch(0, mem(rbx, 11*8)) vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) // ---------------------------------- iteration 3 prefetch(0, mem(rbx, 11*8)) vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP prefetch(0, mem(rbx, 11*8)) vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) vbroadcastss(mem(rax, r8, 2), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm8) vfmadd231ps(ymm1, ymm2, ymm9) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(r12, rcx) // reset rcx to current utile of c. mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), ymm0) // load alpha and duplicate vbroadcastss(mem(rbx), ymm3) // load beta and duplicate vmulps(ymm0, ymm4, ymm4) // scale by alpha vmulps(ymm0, ymm5, ymm5) vmulps(ymm0, ymm6, ymm6) vmulps(ymm0, ymm7, ymm7) vmulps(ymm0, ymm8, ymm8) vmulps(ymm0, ymm9, ymm9) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) lea(mem(rcx, rdi, 2), rdx) // load address of c + 2*rs_c; lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vfmadd231ps(mem(rcx), ymm3, ymm4) vmovups(ymm4, mem(rcx)) vfmadd231ps(mem(rcx, rsi,8), ymm3, ymm5) vmovups(ymm5, mem(rcx, rsi,8)) add(rdi, rcx) vfmadd231ps(mem(rcx), ymm3, ymm6) vmovups(ymm6, mem(rcx)) vfmadd231ps(mem(rcx, rsi,8), ymm3, ymm7) vmovups(ymm7, mem(rcx, rsi,8)) add(rdi, rcx) vfmadd231ps(mem(rcx), ymm3, ymm8) vmovups(ymm8, mem(rcx)) vfmadd231ps(mem(rcx, rsi,8), ymm3, ymm9) vmovups(ymm9, mem(rcx, rsi,8)) jmp(.SDONE) // jump to end. label(.SCOLSTORED) vunpcklps(ymm6, ymm4, ymm0) //a0b0a1b1 a2b2a3b3 vunpckhps(ymm6, ymm4, ymm2) //a2b2a3b3 a6b6a7b7 vperm2f128(imm(0x01),ymm0,ymm0,ymm11) vperm2f128(imm(0x01),ymm2,ymm2,ymm12) vshufpd(imm(0x01), xmm0, xmm0, xmm1)//a1b1 vshufpd(imm(0x01), xmm2, xmm2, xmm10)//a3b3 vmovsd(mem(rcx),xmm4) vmovsd(mem(rcx, rsi, 1),xmm6) vfmadd231ps(xmm4, xmm3, xmm0) vfmadd231ps(xmm6, xmm3, xmm1) vmovsd(xmm0, mem(rcx)) // store ( gamma00..gamma10 ) vmovsd(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma11 ) vmovsd(mem(rcx, rsi, 2),xmm4) vmovsd(mem(rcx, rax, 1),xmm6) vfmadd231ps(xmm4, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm10) vmovsd(xmm2, mem(rcx, rsi, 2)) // store ( gamma02..gamma12 ) vmovsd(xmm10, mem(rcx, rax, 1)) // store ( gamma03..gamma13 ) lea(mem(rcx, rsi, 4), rcx) // rcx += cs_c vshufpd(imm(0x01), xmm11, xmm11, xmm1)//a1b1 vshufpd(imm(0x01), xmm12, xmm12, xmm10)//a3b3 vmovsd(mem(rcx),xmm4) vmovsd(mem(rcx, rsi, 1),xmm6) vfmadd231ps(xmm4, xmm3, xmm11) vfmadd231ps(xmm6, xmm3, xmm1) vmovsd(xmm11, mem(rcx)) // store ( gamma00..gamma10 ) vmovsd(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma11 ) vmovsd(mem(rcx, rsi, 2),xmm4) vmovsd(mem(rcx, rax, 1),xmm6) vfmadd231ps(xmm4, xmm3, xmm12) vfmadd231ps(xmm6, xmm3, xmm10) vmovsd(xmm12, mem(rcx, rsi, 2)) // store ( gamma02..gamma12 ) vmovsd(xmm10, mem(rcx, rax, 1)) // store ( gamma03..gamma13 ) lea(mem(rcx, rsi, 4), rcx) // rcx += 4*cs_c /********************************************/ vextractf128(imm(0x0), ymm8, xmm0)//c0-c3 vmovss(mem(rdx),xmm4) vmovss(mem(rdx, rsi, 1),xmm6) vmovss(mem(rdx, rsi, 2),xmm11) vmovss(mem(rdx, rax, 1),xmm10) vshufps(imm(0x01), xmm0, xmm0,xmm1) vshufps(imm(0x02), xmm0, xmm0,xmm2) vshufps(imm(0x03), xmm0, xmm0,xmm14) vfmadd231ps(xmm4, xmm3, xmm0)//e0 vfmadd231ps(xmm6, xmm3, xmm1)//e1 vfmadd231ps(xmm11, xmm3, xmm2)//e2 vfmadd231ps(xmm10, xmm3, xmm14)//e3 vmovss(xmm0, mem(rdx)) vmovss(xmm1, mem(rdx, rsi, 1)) vmovss(xmm2, mem(rdx, rsi, 2)) vmovss(xmm14, mem(rdx, rax, 1)) lea(mem(rdx, rsi, 4), rdx) // rdx += 4*cs_c vextractf128(imm(0x1), ymm8, xmm0)//e4-e7 vmovss(mem(rdx),xmm4) vmovss(mem(rdx, rsi, 1),xmm6) vmovss(mem(rdx, rsi, 2),xmm8) vmovss(mem(rdx, rax, 1),xmm10) vshufps(imm(0x01), xmm0, xmm0,xmm1) vshufps(imm(0x02), xmm0, xmm0,xmm2) vshufps(imm(0x03), xmm0, xmm0,xmm14) vfmadd231ps(xmm4, xmm3, xmm0)//e4 vfmadd231ps(xmm6, xmm3, xmm1)//e5 vfmadd231ps(xmm8, xmm3, xmm2)//e6 vfmadd231ps(xmm10, xmm3, xmm14)//e7 vmovss(xmm0, mem(rdx)) vmovss(xmm1, mem(rdx, rsi, 1)) vmovss(xmm2, mem(rdx, rsi, 2)) vmovss(xmm14, mem(rdx, rax, 1)) lea(mem(rdx, rsi, 4), rdx) // rdx += 4*cs_c /*********************************************/ vunpcklps(ymm7, ymm5, ymm0) //a0b0a1b1 a2b2a3b3 vunpckhps(ymm7, ymm5, ymm2) //a2b2a3b3 a6b6a7b7 vperm2f128(imm(0x01),ymm0,ymm0,ymm11) vperm2f128(imm(0x01),ymm2,ymm2,ymm12) vshufpd(imm(0x01), xmm0, xmm0, xmm1)//a1b1 vshufpd(imm(0x01), xmm2, xmm2, xmm10)//a3b3 vmovsd(mem(rcx),xmm4) vmovsd(mem(rcx, rsi, 1),xmm6) vfmadd231ps(xmm4, xmm3, xmm0) vfmadd231ps(xmm6, xmm3, xmm1) vmovsd(xmm0, mem(rcx)) // store ( gamma00..gamma10 ) vmovsd(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma11 ) vmovsd(mem(rcx, rsi, 2),xmm4) vmovsd(mem(rcx, rax, 1),xmm6) vfmadd231ps(xmm4, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm10) vmovsd(xmm2, mem(rcx, rsi, 2)) // store ( gamma02..gamma12 ) vmovsd(xmm10, mem(rcx, rax, 1)) // store ( gamma03..gamma13 ) lea(mem(rcx, rsi, 4), rcx) // rcx += cs_c vshufpd(imm(0x01), xmm11, xmm11, xmm1)//a1b1 vshufpd(imm(0x01), xmm12, xmm12, xmm10)//a3b3 vmovsd(mem(rcx),xmm4) vmovsd(mem(rcx, rsi, 1),xmm6) vfmadd231ps(xmm4, xmm3, xmm11) vfmadd231ps(xmm6, xmm3, xmm1) vmovsd(xmm11, mem(rcx)) // store ( gamma00..gamma10 ) vmovsd(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma11 ) vmovsd(mem(rcx, rsi, 2),xmm4) vmovsd(mem(rcx, rax, 1),xmm6) vfmadd231ps(xmm4, xmm3, xmm12) vfmadd231ps(xmm6, xmm3, xmm10) vmovsd(xmm12, mem(rcx, rsi, 2)) // store ( gamma02..gamma12 ) vmovsd(xmm10, mem(rcx, rax, 1)) // store ( gamma03..gamma13 ) /********************************************/ vextractf128(imm(0x0), ymm9, xmm0)//c0-c3 vmovss(mem(rdx),xmm4) vmovss(mem(rdx, rsi, 1),xmm6) vmovss(mem(rdx, rsi, 2),xmm8) vmovss(mem(rdx, rax, 1),xmm10) vshufps(imm(0x01), xmm0, xmm0,xmm1) vshufps(imm(0x02), xmm0, xmm0,xmm2) vshufps(imm(0x03), xmm0, xmm0,xmm14) vfmadd231ps(xmm4, xmm3, xmm0)//e0 vfmadd231ps(xmm6, xmm3, xmm1)//e1 vfmadd231ps(xmm8, xmm3, xmm2)//e2 vfmadd231ps(xmm10, xmm3, xmm14)//e3 vmovss(xmm0, mem(rdx)) vmovss(xmm1, mem(rdx, rsi, 1)) vmovss(xmm2, mem(rdx, rsi, 2)) vmovss(xmm14, mem(rdx, rax, 1)) lea(mem(rdx, rsi, 4), rdx) // rdx += 4*cs_c vextractf128(imm(0x1), ymm9, xmm0)//e4-e7 vmovss(mem(rdx),xmm4) vmovss(mem(rdx, rsi, 1),xmm6) vmovss(mem(rdx, rsi, 2),xmm8) vmovss(mem(rdx, rax, 1),xmm10) vshufps(imm(0x01), xmm0, xmm0,xmm1) vshufps(imm(0x02), xmm0, xmm0,xmm2) vshufps(imm(0x03), xmm0, xmm0,xmm14) vfmadd231ps(xmm4, xmm3, xmm0)//e0 vfmadd231ps(xmm6, xmm3, xmm1)//e1 vfmadd231ps(xmm8, xmm3, xmm2)//e2 vfmadd231ps(xmm10, xmm3, xmm14)//e3 vmovss(xmm0, mem(rdx)) vmovss(xmm1, mem(rdx, rsi, 1)) vmovss(xmm2, mem(rdx, rsi, 2)) vmovss(xmm14, mem(rdx, rax, 1)) jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (8*rs_c) == 8. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovups(ymm4, mem(rcx)) vmovups(ymm5, mem(rcx, rsi,8)) add(rdi, rcx) vmovups(ymm6, mem(rcx)) vmovups(ymm7, mem(rcx, rsi,8)) add(rdi, rcx) vmovups(ymm8, mem(rcx)) vmovups(ymm9, mem(rcx, rsi,8)) //add(rdi, rcx) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) vunpcklps(ymm6, ymm4, ymm0) //a0b0a1b1 a2b2a3b3 vunpckhps(ymm6, ymm4, ymm2) //a2b2a3b3 a6b6a7b7 vshufpd(imm(0x01), xmm0, xmm0, xmm1)//a1b1 vshufpd(imm(0x01), xmm2, xmm2, xmm10)//a3b3 vmovsd(xmm0, mem(rcx)) // store ( gamma00..gamma10 ) vmovsd(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma11 ) vmovsd(xmm2, mem(rcx, rsi, 2)) // store ( gamma02..gamma12 ) vmovsd(xmm10, mem(rcx, rax, 1)) // store ( gamma03..gamma13 ) lea(mem(rcx, rsi, 4), rcx) // rcx += cs_c vperm2f128(imm(0x01),ymm0,ymm0,ymm0) vperm2f128(imm(0x01),ymm2,ymm2,ymm2) vshufpd(imm(0x01), xmm0, xmm0, xmm1)//a2b2 vshufpd(imm(0x01), xmm2, xmm2, xmm10)//a3b3 vmovsd(xmm0, mem(rcx)) // store ( gamma00..gamma10 ) vmovsd(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma11 ) vmovsd(xmm2, mem(rcx, rsi, 2)) // store ( gamma02..gamma12 ) vmovsd(xmm10, mem(rcx, rax, 1)) // store ( gamma03..gamma13 ) lea(mem(rcx, rsi, 4), rcx) // rcx += 4*cs_c /********************************************/ vextractf128(imm(0x0), ymm8, xmm0)//c0-c3 vshufps(imm(0x01), xmm0, xmm0,xmm1) vshufps(imm(0x02), xmm0, xmm0,xmm2) vshufps(imm(0x03), xmm0, xmm0,xmm14) vmovss(xmm0, mem(rdx)) vmovss(xmm1, mem(rdx, rsi, 1)) vmovss(xmm2, mem(rdx, rsi, 2)) vmovss(xmm14, mem(rdx, rax, 1)) lea(mem(rdx, rsi, 4), rdx) // rdx += 4*cs_c vextractf128(imm(0x1), ymm8, xmm0)//c4-c7 vshufps(imm(0x01), xmm0, xmm0,xmm1) vshufps(imm(0x02), xmm0, xmm0,xmm2) vshufps(imm(0x03), xmm0, xmm0,xmm14) vmovss(xmm0, mem(rdx)) vmovss(xmm1, mem(rdx, rsi, 1)) vmovss(xmm2, mem(rdx, rsi, 2)) vmovss(xmm14, mem(rdx, rax, 1)) lea(mem(rdx, rsi, 4), rdx) // rdx += 4*cs_c /*********************************************/ vunpcklps(ymm7, ymm5, ymm0) //a0b0a1b1 a2b2a3b3 vunpckhps(ymm7, ymm5, ymm2) //a2b2a3b3 a6b6a7b7 vshufpd(imm(0x01), xmm0, xmm0, xmm1)//a1b1 vshufpd(imm(0x01), xmm2, xmm2, xmm10)//a3b3 vmovsd(xmm0, mem(rcx)) // store ( gamma00..gamma10 ) vmovsd(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma11 ) vmovsd(xmm2, mem(rcx, rsi, 2)) // store ( gamma02..gamma12 ) vmovsd(xmm10, mem(rcx, rax, 1)) // store ( gamma03..gamma13 ) lea(mem(rcx, rsi, 4), rcx) // rcx += cs_c vperm2f128(imm(0x01),ymm0,ymm0,ymm0) vperm2f128(imm(0x01),ymm2,ymm2,ymm2) vshufpd(imm(0x01), xmm0, xmm0, xmm1)//a2b2 vshufpd(imm(0x01), xmm2, xmm2, xmm10)//a3b3 vmovsd(xmm0, mem(rcx)) // store ( gamma00..gamma10 ) vmovsd(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma11 ) vmovsd(xmm2, mem(rcx, rsi, 2)) // store ( gamma02..gamma12 ) vmovsd(xmm10, mem(rcx, rax, 1)) // store ( gamma03..gamma13 ) /********************************************/ vextractf128(imm(0x0), ymm9, xmm0)//c0-c3 vshufps(imm(0x01), xmm0, xmm0,xmm1) vshufps(imm(0x02), xmm0, xmm0,xmm2) vshufps(imm(0x03), xmm0, xmm0,xmm14) vmovss(xmm0, mem(rdx)) vmovss(xmm1, mem(rdx, rsi, 1)) vmovss(xmm2, mem(rdx, rsi, 2)) vmovss(xmm14, mem(rdx, rax, 1)) lea(mem(rdx, rsi, 4), rdx) // rdx += 4*cs_c vextractf128(imm(0x1), ymm9, xmm0)//c4-c7 vshufps(imm(0x01), xmm0, xmm0,xmm1) vshufps(imm(0x02), xmm0, xmm0,xmm2) vshufps(imm(0x03), xmm0, xmm0,xmm14) vmovss(xmm0, mem(rdx)) vmovss(xmm1, mem(rdx, rsi, 1)) vmovss(xmm2, mem(rdx, rsi, 2)) vmovss(xmm14, mem(rdx, rax, 1)) label(.SDONE) lea(mem(r12, rsi, 8), r12) // c_jj = r12 += 8*cs_c lea(mem(r12, rsi, 8), r12) //add(imm(4*16), r14) // b_jj = r14 += 8*cs_b mov(var(ps_b4), rbx) // load ps_b4 lea(mem(r14, rbx, 1), r14) // a_ii = r14 += ps_b4 dec(r11) // jj -= 1; jne(.SLOOP4X16J) // iterate again if jj != 0. label(.SRETURN) end_asm( : // output operands (none) : // input operands [n_iter] "m" (n_iter), [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [ps_b4] "m" (ps_b4), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the m dimension, if they exist. if ( n_left ) { const dim_t mr_cur = 3; const dim_t j_edge = n0 - ( dim_t )n_left; float* restrict cij = c + j_edge*cs_c; float* restrict ai = a; float* restrict bj = b + n_iter * ps_b; if ( 8 <= n_left ) { const dim_t nr_cur = 8; bli_sgemmsup_rv_zen_asm_3x8 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 4 <= n_left ) { const dim_t nr_cur = 4; bli_sgemmsup_rv_zen_asm_3x4 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 2 <= n_left ) { const dim_t nr_cur = 2; bli_sgemmsup_rv_zen_asm_3x2 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 1 == n_left ) { const dim_t nr_cur = 1; bli_sgemmsup_r_zen_ref_3x1 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); } } } void bli_sgemmsup_rv_zen_asm_2x16n ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t n_iter = n0 /16; uint64_t n_left = n0 % 16; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // Query the panel stride of B and convert it to units of bytes. uint64_t ps_b = bli_auxinfo_ps_b( data ); uint64_t ps_b4 = ps_b * sizeof( float ); if ( n_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() //mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) mov(var(b), r14) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) //lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) // During preamble and loops: // r12 = rcx = c // r14 = rbx = b // read rax from var(a) near beginning of loop // r11 = m dim index ii mov(var(n_iter), r11) // jj = n_iter; label(.SLOOP2X16J) // LOOP OVER jj = [ n_iter ... 1 0 ] vxorps(ymm4, ymm4, ymm4) vxorps(ymm5, ymm5, ymm5) vxorps(ymm6, ymm6, ymm6) vxorps(ymm7, ymm7, ymm7) mov(var(a), rax) // load address of a. //mov(r12, rcx) // reset rcx to current utile of c. mov(r14, rbx) // reset rbx to current upanel of b. cmp(imm(4), rdi) // set ZF if (8*rs_c) == 8. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored prefetching on c prefetch(0, mem(r12, 7*8)) // prefetch c + 0*rs_c prefetch(0, mem(r12, rdi, 1, 7*8)) // prefetch c + 1*rs_c jmp(.SPOSTPFETCH) // jump to end of prefetching c label(.SCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) lea(mem(r12, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; prefetch(0, mem(r12, 1*8)) // prefetch c + 0*cs_c prefetch(0, mem(r12, rsi, 1, 1*8)) // prefetch c + 1*cs_c prefetch(0, mem(r12, rsi, 2, 1*8)) // prefetch c + 2*cs_c prefetch(0, mem(rdx, 1*8)) // prefetch c + 3*cs_c prefetch(0, mem(rdx, rsi, 1, 1*8)) // prefetch c + 4*cs_c prefetch(0, mem(rdx, rsi, 2, 1*8)) // prefetch c + 5*cs_c lea(mem(rdx, rsi, 2), rdx) // rdx = c + 5*cs_c; prefetch(0, mem(rdx, rsi, 1, 1*8)) // prefetch c + 6*cs_c prefetch(0, mem(rdx, rsi, 2, 1*8)) // prefetch c + 7*cs_c label(.SPOSTPFETCH) // done prefetching c mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 prefetch(0, mem(rbx, 11*8)) // prefetch line of next upanel of b vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) // ---------------------------------- iteration 1 prefetch(0, mem(rbx, 11*8)) vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) // ---------------------------------- iteration 2 prefetch(0, mem(rbx, 11*8)) vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) // ---------------------------------- iteration 3 prefetch(0, mem(rbx, 11*8)) vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP prefetch(0, mem(rbx, 11*8)) vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) vbroadcastss(mem(rax, r8, 1), ymm3) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) vfmadd231ps(ymm0, ymm3, ymm6) vfmadd231ps(ymm1, ymm3, ymm7) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(r12, rcx) // reset rcx to current utile of c. mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), ymm0) // load alpha and duplicate vbroadcastss(mem(rbx), ymm3) // load beta and duplicate vmulps(ymm0, ymm4, ymm4) // scale by alpha vmulps(ymm0, ymm5, ymm5) vmulps(ymm0, ymm6, ymm6) vmulps(ymm0, ymm7, ymm7) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (8*rs_c) == 8. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vfmadd231ps(mem(rcx), ymm3, ymm4) vmovups(ymm4, mem(rcx)) vfmadd231ps(mem(rcx, rsi,8), ymm3, ymm5) vmovups(ymm5, mem(rcx, rsi,8)) add(rdi, rcx) vfmadd231ps(mem(rcx), ymm3, ymm6) vmovups(ymm6, mem(rcx)) vfmadd231ps(mem(rcx, rsi,8), ymm3, ymm7) vmovups(ymm7, mem(rcx, rsi,8)) jmp(.SDONE) // jump to end. label(.SCOLSTORED) vunpcklps(ymm6, ymm4, ymm0) //a0b0a1b1 a2b2a3b3 vunpckhps(ymm6, ymm4, ymm2) //a2b2a3b3 a6b6a7b7 vperm2f128(imm(0x01),ymm0,ymm0,ymm11) vperm2f128(imm(0x01),ymm2,ymm2,ymm12) vshufpd(imm(0x01), xmm0, xmm0, xmm1)//a1b1 vshufpd(imm(0x01), xmm2, xmm2, xmm10)//a3b3 vmovsd(mem(rcx),xmm4) vmovsd(mem(rcx, rsi, 1),xmm6) vfmadd231ps(xmm4, xmm3, xmm0) vfmadd231ps(xmm6, xmm3, xmm1) vmovsd(xmm0, mem(rcx)) // store ( gamma00..gamma10 ) vmovsd(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma11 ) vmovsd(mem(rcx, rsi, 2),xmm4) vmovsd(mem(rcx, rax, 1),xmm6) vfmadd231ps(xmm4, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm10) vmovsd(xmm2, mem(rcx, rsi, 2)) // store ( gamma02..gamma12 ) vmovsd(xmm10, mem(rcx, rax, 1)) // store ( gamma03..gamma13 ) lea(mem(rcx, rsi, 4), rcx) // rcx += cs_c vshufpd(imm(0x01), xmm11, xmm11, xmm1)//a1b1 vshufpd(imm(0x01), xmm12, xmm12, xmm10)//a3b3 vmovsd(mem(rcx),xmm4) vmovsd(mem(rcx, rsi, 1),xmm6) vfmadd231ps(xmm4, xmm3, xmm11) vfmadd231ps(xmm6, xmm3, xmm1) vmovsd(xmm11, mem(rcx)) // store ( gamma00..gamma10 ) vmovsd(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma11 ) vmovsd(mem(rcx, rsi, 2),xmm4) vmovsd(mem(rcx, rax, 1),xmm6) vfmadd231ps(xmm4, xmm3, xmm12) vfmadd231ps(xmm6, xmm3, xmm10) vmovsd(xmm12, mem(rcx, rsi, 2)) // store ( gamma02..gamma12 ) vmovsd(xmm10, mem(rcx, rax, 1)) // store ( gamma03..gamma13 ) lea(mem(rcx, rsi, 4), rcx) // rcx += 4*cs_c vunpcklps(ymm7, ymm5, ymm0) //a0b0a1b1 a2b2a3b3 vunpckhps(ymm7, ymm5, ymm2) //a2b2a3b3 a6b6a7b7 vperm2f128(imm(0x01),ymm0,ymm0,ymm11) vperm2f128(imm(0x01),ymm2,ymm2,ymm12) vshufpd(imm(0x01), xmm0, xmm0, xmm1)//a1b1 vshufpd(imm(0x01), xmm2, xmm2, xmm10)//a3b3 vmovsd(mem(rcx),xmm4) vmovsd(mem(rcx, rsi, 1),xmm6) vfmadd231ps(xmm4, xmm3, xmm0) vfmadd231ps(xmm6, xmm3, xmm1) vmovsd(xmm0, mem(rcx)) // store ( gamma00..gamma10 ) vmovsd(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma11 ) vmovsd(mem(rcx, rsi, 2),xmm4) vmovsd(mem(rcx, rax, 1),xmm6) vfmadd231ps(xmm4, xmm3, xmm2) vfmadd231ps(xmm6, xmm3, xmm10) vmovsd(xmm2, mem(rcx, rsi, 2)) // store ( gamma02..gamma12 ) vmovsd(xmm10, mem(rcx, rax, 1)) // store ( gamma03..gamma13 ) lea(mem(rcx, rsi, 4), rcx) // rcx += cs_c vshufpd(imm(0x01), xmm11, xmm11, xmm1)//a1b1 vshufpd(imm(0x01), xmm12, xmm12, xmm10)//a3b3 vmovsd(mem(rcx),xmm4) vmovsd(mem(rcx, rsi, 1),xmm6) vfmadd231ps(xmm4, xmm3, xmm11) vfmadd231ps(xmm6, xmm3, xmm1) vmovsd(xmm11, mem(rcx)) // store ( gamma00..gamma10 ) vmovsd(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma11 ) vmovsd(mem(rcx, rsi, 2),xmm4) vmovsd(mem(rcx, rax, 1),xmm6) vfmadd231ps(xmm4, xmm3, xmm12) vfmadd231ps(xmm6, xmm3, xmm10) vmovsd(xmm12, mem(rcx, rsi, 2)) // store ( gamma02..gamma12 ) vmovsd(xmm10, mem(rcx, rax, 1)) // store ( gamma03..gamma13 ) jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (8*rs_c) == 8. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovups(ymm4, mem(rcx)) vmovups(ymm5, mem(rcx, rsi,8)) add(rdi, rcx) vmovups(ymm6, mem(rcx)) vmovups(ymm7, mem(rcx, rsi,8)) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) vunpcklps(ymm6, ymm4, ymm0) //a0b0a1b1 a2b2a3b3 vunpckhps(ymm6, ymm4, ymm2) //a2b2a3b3 a6b6a7b7 vshufpd(imm(0x01), xmm0, xmm0, xmm1)//a1b1 vshufpd(imm(0x01), xmm2, xmm2, xmm10)//a3b3 vmovsd(xmm0, mem(rcx)) // store ( gamma00..gamma10 ) vmovsd(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma11 ) vmovsd(xmm2, mem(rcx, rsi, 2)) // store ( gamma02..gamma12 ) vmovsd(xmm10, mem(rcx, rax, 1)) // store ( gamma03..gamma13 ) lea(mem(rcx, rsi, 4), rcx) // rcx += cs_c vperm2f128(imm(0x01),ymm0,ymm0,ymm0) vperm2f128(imm(0x01),ymm2,ymm2,ymm2) vshufpd(imm(0x01), xmm0, xmm0, xmm1)//a2b2 vshufpd(imm(0x01), xmm2, xmm2, xmm10)//a3b3 vmovsd(xmm0, mem(rcx)) // store ( gamma00..gamma10 ) vmovsd(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma11 ) vmovsd(xmm2, mem(rcx, rsi, 2)) // store ( gamma02..gamma12 ) vmovsd(xmm10, mem(rcx, rax, 1)) // store ( gamma03..gamma13 ) lea(mem(rcx, rsi, 4), rcx) // rcx += 4*cs_c vunpcklps(ymm7, ymm5, ymm0) //a0b0a1b1 a2b2a3b3 vunpckhps(ymm7, ymm5, ymm2) //a2b2a3b3 a6b6a7b7 vshufpd(imm(0x01), xmm0, xmm0, xmm1)//a1b1 vshufpd(imm(0x01), xmm2, xmm2, xmm10)//a3b3 vmovsd(xmm0, mem(rcx)) // store ( gamma00..gamma10 ) vmovsd(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma11 ) vmovsd(xmm2, mem(rcx, rsi, 2)) // store ( gamma02..gamma12 ) vmovsd(xmm10, mem(rcx, rax, 1)) // store ( gamma03..gamma13 ) lea(mem(rcx, rsi, 4), rcx) // rcx += cs_c vperm2f128(imm(0x01),ymm0,ymm0,ymm0) vperm2f128(imm(0x01),ymm2,ymm2,ymm2) vshufpd(imm(0x01), xmm0, xmm0, xmm1)//a2b2 vshufpd(imm(0x01), xmm2, xmm2, xmm10)//a3b3 vmovsd(xmm0, mem(rcx)) // store ( gamma00..gamma10 ) vmovsd(xmm1, mem(rcx, rsi, 1)) // store ( gamma01..gamma11 ) vmovsd(xmm2, mem(rcx, rsi, 2)) // store ( gamma02..gamma12 ) vmovsd(xmm10, mem(rcx, rax, 1)) // store ( gamma03..gamma13 ) label(.SDONE) lea(mem(r12, rsi, 8), r12) // c_jj = r12 += 8*cs_c lea(mem(r12, rsi, 8), r12) //add(imm(4*16), r14) // b_jj = r14 += 8*cs_b mov(var(ps_b4), rbx) // load ps_b4 lea(mem(r14, rbx, 1), r14) // a_ii = r14 += ps_b4 dec(r11) // jj -= 1; jne(.SLOOP2X16J) // iterate again if jj != 0. label(.SRETURN) end_asm( : // output operands (none) : // input operands [n_iter] "m" (n_iter), [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [ps_b4] "m" (ps_b4), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the m dimension, if they exist. if ( n_left ) { const dim_t mr_cur = 2; const dim_t j_edge = n0 - ( dim_t )n_left; float* restrict cij = c + j_edge*cs_c; float* restrict ai = a; float* restrict bj = b + n_iter * ps_b; if ( 8 <= n_left ) { const dim_t nr_cur = 8; bli_sgemmsup_rv_zen_asm_2x8 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 4 <= n_left ) { const dim_t nr_cur = 4; bli_sgemmsup_rv_zen_asm_2x4 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 2 <= n_left ) { const dim_t nr_cur = 2; bli_sgemmsup_rv_zen_asm_2x2 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 1 == n_left ) { const dim_t nr_cur = 1; bli_sgemmsup_r_zen_ref_2x1 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); } } } void bli_sgemmsup_rv_zen_asm_1x16n ( conj_t conja, conj_t conjb, dim_t m0, dim_t n0, dim_t k0, float* restrict alpha, float* restrict a, inc_t rs_a0, inc_t cs_a0, float* restrict b, inc_t rs_b0, inc_t cs_b0, float* restrict beta, float* restrict c, inc_t rs_c0, inc_t cs_c0, auxinfo_t* restrict data, cntx_t* restrict cntx ) { //void* a_next = bli_auxinfo_next_a( data ); //void* b_next = bli_auxinfo_next_b( data ); // Typecast local copies of integers in case dim_t and inc_t are a // different size than is expected by load instructions. uint64_t k_iter = k0 / 4; uint64_t k_left = k0 % 4; uint64_t n_iter = n0 /16; uint64_t n_left = n0 % 16; uint64_t rs_a = rs_a0; uint64_t cs_a = cs_a0; uint64_t rs_b = rs_b0; uint64_t cs_b = cs_b0; uint64_t rs_c = rs_c0; uint64_t cs_c = cs_c0; // Query the panel stride of B and convert it to units of bytes. uint64_t ps_b = bli_auxinfo_ps_b( data ); uint64_t ps_b4 = ps_b * sizeof( float ); if ( n_iter == 0 ) goto consider_edge_cases; // ------------------------------------------------------------------------- begin_asm() //mov(var(a), rax) // load address of a. mov(var(rs_a), r8) // load rs_a mov(var(cs_a), r9) // load cs_a lea(mem(, r8, 4), r8) // rs_a *= sizeof(float) lea(mem(, r9, 4), r9) // cs_a *= sizeof(float) mov(var(b), r14) // load address of b. mov(var(rs_b), r10) // load rs_b //mov(var(cs_b), r11) // load cs_b lea(mem(, r10, 4), r10) // rs_b *= sizeof(float) //lea(mem(, r11, 4), r11) // cs_b *= sizeof(float) // NOTE: We cannot pre-load elements of a or b // because it could eventually, in the last // unrolled iter or the cleanup loop, result // in reading beyond the bounds allocated mem // (the likely result: a segmentation fault). mov(var(c), r12) // load address of c mov(var(rs_c), rdi) // load rs_c lea(mem(, rdi, 4), rdi) // rs_c *= sizeof(float) // During preamble and loops: // r12 = rcx = c // r14 = rbx = b // read rax from var(a) near beginning of loop // r11 = m dim index ii mov(var(n_iter), r11) // jj = n_iter; label(.SLOOP1X16J) // LOOP OVER jj = [ n_iter ... 1 0 ] vxorps(ymm4, ymm4, ymm4) vxorps(ymm5, ymm5, ymm5) mov(var(a), rax) // load address of a. //mov(r12, rcx) // reset rcx to current utile of c. mov(r14, rbx) // reset rbx to current upanel of b. cmp(imm(4), rdi) // set ZF if (8*rs_c) == 8. jz(.SCOLPFETCH) // jump to column storage case label(.SROWPFETCH) // row-stored prefetching on c prefetch(0, mem(r12, 7*8)) // prefetch c + 0*rs_c jmp(.SPOSTPFETCH) // jump to end of prefetching c label(.SCOLPFETCH) // column-stored prefetching c mov(var(cs_c), rsi) // load cs_c to rsi (temporarily) lea(mem(, rsi, 4), rsi) // cs_c *= sizeof(float) lea(mem(r12, rsi, 2), rdx) // lea(mem(rdx, rsi, 1), rdx) // rdx = c + 3*cs_c; prefetch(0, mem(r12, 0*8)) // prefetch c + 0*cs_c prefetch(0, mem(r12, rsi, 1, 0*8)) // prefetch c + 1*cs_c prefetch(0, mem(r12, rsi, 2, 0*8)) // prefetch c + 2*cs_c prefetch(0, mem(rdx, 1*8)) // prefetch c + 3*cs_c prefetch(0, mem(rdx, rsi, 1, 0*8)) // prefetch c + 4*cs_c prefetch(0, mem(rdx, rsi, 2, 0*8)) // prefetch c + 5*cs_c lea(mem(rdx, rsi, 2), rdx) // rdx = c + 5*cs_c; prefetch(0, mem(rdx, rsi, 1, 0*8)) // prefetch c + 6*cs_c prefetch(0, mem(rdx, rsi, 2, 0*8)) // prefetch c + 7*cs_c label(.SPOSTPFETCH) // done prefetching c mov(var(k_iter), rsi) // i = k_iter; test(rsi, rsi) // check i via logical AND. je(.SCONSIDKLEFT) // if i == 0, jump to code that // contains the k_left loop. label(.SLOOPKITER) // MAIN LOOP // ---------------------------------- iteration 0 prefetch(0, mem(rbx, 11*8)) // prefetch line of next upanel of b vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) // ---------------------------------- iteration 1 prefetch(0, mem(rbx, 11*8)) vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) // ---------------------------------- iteration 2 prefetch(0, mem(rbx, 11*8)) vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) // ---------------------------------- iteration 3 prefetch(0, mem(rbx, 11*8)) vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) dec(rsi) // i -= 1; jne(.SLOOPKITER) // iterate again if i != 0. label(.SCONSIDKLEFT) mov(var(k_left), rsi) // i = k_left; test(rsi, rsi) // check i via logical AND. je(.SPOSTACCUM) // if i == 0, we're done; jump to end. // else, we prepare to enter k_left loop. label(.SLOOPKLEFT) // EDGE LOOP prefetch(0, mem(rbx, 11*8)) vmovups(mem(rbx, 0*32), ymm0) vmovups(mem(rbx, 1*32), ymm1) add(r10, rbx) // b += rs_b; vbroadcastss(mem(rax ), ymm2) add(r9, rax) // a += cs_a; vfmadd231ps(ymm0, ymm2, ymm4) vfmadd231ps(ymm1, ymm2, ymm5) dec(rsi) // i -= 1; jne(.SLOOPKLEFT) // iterate again if i != 0. label(.SPOSTACCUM) mov(r12, rcx) // reset rcx to current utile of c. mov(var(alpha), rax) // load address of alpha mov(var(beta), rbx) // load address of beta vbroadcastss(mem(rax), ymm0) // load alpha and duplicate vbroadcastss(mem(rbx), ymm3) // load beta and duplicate vmulps(ymm0, ymm4, ymm4) // scale by alpha vmulps(ymm0, ymm5, ymm5) mov(var(cs_c), rsi) // load cs_c lea(mem(, rsi, 4), rsi) // rsi = cs_c * sizeof(float) lea(mem(rsi, rsi, 2), rax) // rax = 3*cs_c; // now avoid loading C if beta == 0 vxorps(ymm0, ymm0, ymm0) // set ymm0 to zero. vucomiss(xmm0, xmm3) // set ZF if beta == 0. je(.SBETAZERO) // if ZF = 1, jump to beta == 0 case cmp(imm(4), rdi) // set ZF if (4*rs_c) == 4. jz(.SCOLSTORED) // jump to column storage case label(.SROWSTORED) vfmadd231ps(mem(rcx), ymm3, ymm4) vmovups(ymm4, mem(rcx)) vfmadd231ps(mem(rcx, rsi,8), ymm3, ymm5) vmovups(ymm5, mem(rcx, rsi,8)) jmp(.SDONE) // jump to end. label(.SCOLSTORED) vextractf128(imm(0x0), ymm4, xmm0)//c0-c3 vmovss(mem(rcx),xmm7) vmovss(mem(rcx, rsi, 1),xmm6) vmovss(mem(rcx, rsi, 2),xmm11) vmovss(mem(rcx, rax, 1),xmm10) vshufps(imm(0x01), xmm0, xmm0,xmm1) vshufps(imm(0x02), xmm0, xmm0,xmm2) vshufps(imm(0x03), xmm0, xmm0,xmm14) vfmadd231ps(xmm7, xmm3, xmm0)//e0 vfmadd231ps(xmm6, xmm3, xmm1)//e1 vfmadd231ps(xmm11, xmm3, xmm2)//e2 vfmadd231ps(xmm10, xmm3, xmm14)//e3 vmovss(xmm0, mem(rcx)) vmovss(xmm1, mem(rcx, rsi, 1)) vmovss(xmm2, mem(rcx, rsi, 2)) vmovss(xmm14, mem(rcx, rax, 1)) lea(mem(rcx, rsi, 4), rcx) // rcx += cs_c vextractf128(imm(0x1), ymm4, xmm0)//e4-e7 vmovss(mem(rcx),xmm4) vmovss(mem(rcx, rsi, 1),xmm6) vmovss(mem(rcx, rsi, 2),xmm8) vmovss(mem(rcx, rax, 1),xmm10) vshufps(imm(0x01), xmm0, xmm0,xmm1) vshufps(imm(0x02), xmm0, xmm0,xmm2) vshufps(imm(0x03), xmm0, xmm0,xmm14) vfmadd231ps(xmm4, xmm3, xmm0)//e4 vfmadd231ps(xmm6, xmm3, xmm1)//e5 vfmadd231ps(xmm8, xmm3, xmm2)//e6 vfmadd231ps(xmm10, xmm3, xmm14)//e7 vmovss(xmm0, mem(rcx)) vmovss(xmm1, mem(rcx, rsi, 1)) vmovss(xmm2, mem(rcx, rsi, 2)) vmovss(xmm14, mem(rcx, rax, 1)) lea(mem(rcx, rsi, 4), rcx) // rcx += 4*cs_c vextractf128(imm(0x0), ymm5, xmm0)//c0-c3 vmovss(mem(rcx),xmm4) vmovss(mem(rcx, rsi, 1),xmm6) vmovss(mem(rcx, rsi, 2),xmm11) vmovss(mem(rcx, rax, 1),xmm10) vshufps(imm(0x01), xmm0, xmm0,xmm1) vshufps(imm(0x02), xmm0, xmm0,xmm2) vshufps(imm(0x03), xmm0, xmm0,xmm14) vfmadd231ps(xmm4, xmm3, xmm0)//e0 vfmadd231ps(xmm6, xmm3, xmm1)//e1 vfmadd231ps(xmm11, xmm3, xmm2)//e2 vfmadd231ps(xmm10, xmm3, xmm14)//e3 vmovss(xmm0, mem(rcx)) vmovss(xmm1, mem(rcx, rsi, 1)) vmovss(xmm2, mem(rcx, rsi, 2)) vmovss(xmm14, mem(rcx, rax, 1)) lea(mem(rcx, rsi, 4), rcx) // rcx += 4*cs_c vextractf128(imm(0x1), ymm5, xmm0)//e4-e7 vmovss(mem(rcx),xmm4) vmovss(mem(rcx, rsi, 1),xmm6) vmovss(mem(rcx, rsi, 2),xmm8) vmovss(mem(rcx, rax, 1),xmm10) vshufps(imm(0x01), xmm0, xmm0,xmm1) vshufps(imm(0x02), xmm0, xmm0,xmm2) vshufps(imm(0x03), xmm0, xmm0,xmm14) vfmadd231ps(xmm4, xmm3, xmm0)//e4 vfmadd231ps(xmm6, xmm3, xmm1)//e5 vfmadd231ps(xmm8, xmm3, xmm2)//e6 vfmadd231ps(xmm10, xmm3, xmm14)//e7 vmovss(xmm0, mem(rcx)) vmovss(xmm1, mem(rcx, rsi, 1)) vmovss(xmm2, mem(rcx, rsi, 2)) vmovss(xmm14, mem(rcx, rax, 1)) jmp(.SDONE) // jump to end. label(.SBETAZERO) cmp(imm(4), rdi) // set ZF if (8*rs_c) == 8. jz(.SCOLSTORBZ) // jump to column storage case label(.SROWSTORBZ) vmovups(ymm4, mem(rcx)) vmovups(ymm5, mem(rcx, rsi,8)) jmp(.SDONE) // jump to end. label(.SCOLSTORBZ) vextractf128(imm(0x0), ymm4, xmm0)//c0-c3 vshufps(imm(0x01), xmm0, xmm0,xmm1) vshufps(imm(0x02), xmm0, xmm0,xmm2) vshufps(imm(0x03), xmm0, xmm0,xmm14) vmovss(xmm0, mem(rcx)) vmovss(xmm1, mem(rcx, rsi, 1)) vmovss(xmm2, mem(rcx, rsi, 2)) vmovss(xmm14, mem(rcx, rax, 1)) lea(mem(rcx, rsi, 4), rcx) // rcx += cs_c vextractf128(imm(0x1), ymm4, xmm0)//e4-e7 vshufps(imm(0x01), xmm0, xmm0,xmm1) vshufps(imm(0x02), xmm0, xmm0,xmm2) vshufps(imm(0x03), xmm0, xmm0,xmm14) vmovss(xmm0, mem(rcx)) vmovss(xmm1, mem(rcx, rsi, 1)) vmovss(xmm2, mem(rcx, rsi, 2)) vmovss(xmm14, mem(rcx, rax, 1)) vextractf128(imm(0x0), ymm5, xmm0)//c0-c3 vshufps(imm(0x01), xmm0, xmm0,xmm1) vshufps(imm(0x02), xmm0, xmm0,xmm2) vshufps(imm(0x03), xmm0, xmm0,xmm14) vmovss(xmm0, mem(rcx)) vmovss(xmm1, mem(rcx, rsi, 1)) vmovss(xmm2, mem(rcx, rsi, 2)) vmovss(xmm14, mem(rcx, rax, 1)) lea(mem(rcx, rsi, 4), rcx) // rcx += cs_c vextractf128(imm(0x1), ymm5, xmm0)//e4-e7 vshufps(imm(0x01), xmm0, xmm0,xmm1) vshufps(imm(0x02), xmm0, xmm0,xmm2) vshufps(imm(0x03), xmm0, xmm0,xmm14) vmovss(xmm0, mem(rcx)) vmovss(xmm1, mem(rcx, rsi, 1)) vmovss(xmm2, mem(rcx, rsi, 2)) vmovss(xmm14, mem(rcx, rax, 1)) label(.SDONE) lea(mem(r12, rsi, 8), r12) // c_jj = r12 += 8*cs_c lea(mem(r12, rsi, 8), r12) //add(imm(4*16), r14) // b_jj = r14 += 8*cs_b mov(var(ps_b4), rbx) // load ps_b4 lea(mem(r14, rbx, 1), r14) // a_ii = r14 += ps_b4 dec(r11) // jj -= 1; jne(.SLOOP1X16J) // iterate again if jj != 0. label(.SRETURN) end_asm( : // output operands (none) : // input operands [n_iter] "m" (n_iter), [k_iter] "m" (k_iter), [k_left] "m" (k_left), [a] "m" (a), [rs_a] "m" (rs_a), [cs_a] "m" (cs_a), [b] "m" (b), [rs_b] "m" (rs_b), [cs_b] "m" (cs_b), [ps_b4] "m" (ps_b4), [alpha] "m" (alpha), [beta] "m" (beta), [c] "m" (c), [rs_c] "m" (rs_c), [cs_c] "m" (cs_c)/*, [a_next] "m" (a_next), [b_next] "m" (b_next)*/ : // register clobber list "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory" ) consider_edge_cases: // Handle edge cases in the m dimension, if they exist. if ( n_left ) { const dim_t mr_cur = 1; const dim_t j_edge = n0 - ( dim_t )n_left; float* restrict cij = c + j_edge*cs_c; float* restrict ai = a; float* restrict bj = b + n_iter * ps_b; if ( 8 <= n_left ) { const dim_t nr_cur = 8; bli_sgemmsup_rv_zen_asm_1x8 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 4 <= n_left ) { const dim_t nr_cur = 4; bli_sgemmsup_rv_zen_asm_1x4 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 2 <= n_left ) { const dim_t nr_cur = 2; bli_sgemmsup_rv_zen_asm_1x2 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); cij += nr_cur*cs_c0; bj += nr_cur*cs_b0; n_left -= nr_cur; } if ( 1 == n_left ) { const dim_t nr_cur = 1; bli_sgemmsup_r_zen_ref_1x1 ( conja, conjb, mr_cur, nr_cur, k0, alpha, ai, rs_a0, cs_a0, bj, rs_b0, cs_b0, beta, cij, rs_c0, cs_c0, data, cntx ); } } } blis-0.9.0/kernels/zen/bli_kernels_zen.h000066400000000000000000000211061422157504600202340ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2020 - 2022, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // -- level-1m -- PACKM_KER_PROT(double, d, packm_8xk_gen_zen) PACKM_KER_PROT(double, d, packm_6xk_gen_zen) PACKM_KER_PROT(double, d, packm_8xk_nn_zen) PACKM_KER_PROT(double, d, packm_6xk_nn_zen) // -- level-1v -- // amaxv (intrinsics) AMAXV_KER_PROT( float, s, amaxv_zen_int ) AMAXV_KER_PROT( double, d, amaxv_zen_int ) // axpyv (intrinsics) AXPYV_KER_PROT( float, s, axpyv_zen_int ) AXPYV_KER_PROT( double, d, axpyv_zen_int ) // axpyv (intrinsics unrolled x10) AXPYV_KER_PROT( float, s, axpyv_zen_int10 ) AXPYV_KER_PROT( double, d, axpyv_zen_int10 ) // dotv (intrinsics) DOTV_KER_PROT( float, s, dotv_zen_int ) DOTV_KER_PROT( double, d, dotv_zen_int ) // dotv (intrinsics, unrolled x10) DOTV_KER_PROT( float, s, dotv_zen_int10 ) DOTV_KER_PROT( double, d, dotv_zen_int10 ) // dotxv (intrinsics) DOTXV_KER_PROT( float, s, dotxv_zen_int ) DOTXV_KER_PROT( double, d, dotxv_zen_int ) // scalv (intrinsics) SCALV_KER_PROT( float, s, scalv_zen_int ) SCALV_KER_PROT( double, d, scalv_zen_int ) // scalv (intrinsics unrolled x10) SCALV_KER_PROT( float, s, scalv_zen_int10 ) SCALV_KER_PROT( double, d, scalv_zen_int10 ) SCALV_KER_PROT( scomplex, c, scalv_zen_int10 ) // swapv (intrinsics) SWAPV_KER_PROT(float, s, swapv_zen_int8 ) SWAPV_KER_PROT(double, d, swapv_zen_int8 ) // copyv (intrinsics) COPYV_KER_PROT( float, s, copyv_zen_int ) COPYV_KER_PROT( double, d, copyv_zen_int ) // SETV_KER_PROT(float, s, setv_zen_int) SETV_KER_PROT(double, d, setv_zen_int) // swapv (intrinsics) SWAPV_KER_PROT(float, s, swapv_zen_int8 ) SWAPV_KER_PROT(double, d, swapv_zen_int8 ) // -- level-1f -- // axpyf (intrinsics) AXPYF_KER_PROT( float, s, axpyf_zen_int_8 ) AXPYF_KER_PROT( double, d, axpyf_zen_int_8 ) AXPYF_KER_PROT( float, s, axpyf_zen_int_5 ) AXPYF_KER_PROT( double, d, axpyf_zen_int_5 ) AXPYF_KER_PROT( double, d, axpyf_zen_int_16x4 ) AXPYF_KER_PROT( scomplex, c, axpyf_zen_int_4 ) // dotxf (intrinsics) DOTXF_KER_PROT( float, s, dotxf_zen_int_8 ) DOTXF_KER_PROT( double, d, dotxf_zen_int_8 ) // -- level-3 sup -------------------------------------------------------------- // semmsup_rv //GEMMSUP_KER_PROT( float, s, gemmsup_rv_zen_asm_6x16 ) GEMMSUP_KER_PROT( float, s, gemmsup_rv_zen_asm_5x16 ) GEMMSUP_KER_PROT( float, s, gemmsup_rv_zen_asm_4x16 ) GEMMSUP_KER_PROT( float, s, gemmsup_rv_zen_asm_3x16 ) GEMMSUP_KER_PROT( float, s, gemmsup_rv_zen_asm_2x16 ) GEMMSUP_KER_PROT( float, s, gemmsup_rv_zen_asm_1x16 ) GEMMSUP_KER_PROT( float, s, gemmsup_rv_zen_asm_6x8 ) GEMMSUP_KER_PROT( float, s, gemmsup_rv_zen_asm_5x8 ) GEMMSUP_KER_PROT( float, s, gemmsup_rv_zen_asm_4x8 ) GEMMSUP_KER_PROT( float, s, gemmsup_rv_zen_asm_3x8 ) GEMMSUP_KER_PROT( float, s, gemmsup_rv_zen_asm_2x8 ) GEMMSUP_KER_PROT( float, s, gemmsup_rv_zen_asm_1x8 ) GEMMSUP_KER_PROT( float, s, gemmsup_rv_zen_asm_6x4 ) GEMMSUP_KER_PROT( float, s, gemmsup_rv_zen_asm_5x4 ) GEMMSUP_KER_PROT( float, s, gemmsup_rv_zen_asm_4x4 ) GEMMSUP_KER_PROT( float, s, gemmsup_rv_zen_asm_3x4 ) GEMMSUP_KER_PROT( float, s, gemmsup_rv_zen_asm_2x4 ) GEMMSUP_KER_PROT( float, s, gemmsup_rv_zen_asm_1x4 ) GEMMSUP_KER_PROT( float, s, gemmsup_rv_zen_asm_6x2 ) GEMMSUP_KER_PROT( float, s, gemmsup_rv_zen_asm_5x2 ) GEMMSUP_KER_PROT( float, s, gemmsup_rv_zen_asm_4x2 ) GEMMSUP_KER_PROT( float, s, gemmsup_rv_zen_asm_3x2 ) GEMMSUP_KER_PROT( float, s, gemmsup_rv_zen_asm_2x2 ) GEMMSUP_KER_PROT( float, s, gemmsup_rv_zen_asm_1x2 ) GEMMSUP_KER_PROT( float, s, gemmsup_r_zen_ref_6x1 ) GEMMSUP_KER_PROT( float, s, gemmsup_r_zen_ref_5x1 ) GEMMSUP_KER_PROT( float, s, gemmsup_r_zen_ref_4x1 ) GEMMSUP_KER_PROT( float, s, gemmsup_r_zen_ref_3x1 ) GEMMSUP_KER_PROT( float, s, gemmsup_r_zen_ref_2x1 ) GEMMSUP_KER_PROT( float, s, gemmsup_r_zen_ref_1x1 ) // gemmsup_rv (mkernel in m dim) GEMMSUP_KER_PROT( float, s, gemmsup_rv_zen_asm_6x16m ) GEMMSUP_KER_PROT( float, s, gemmsup_rv_zen_asm_6x8m ) GEMMSUP_KER_PROT( float, s, gemmsup_rv_zen_asm_6x4m ) GEMMSUP_KER_PROT( float, s, gemmsup_rv_zen_asm_6x2m ) // gemmsup_rv (mkernel in n dim) GEMMSUP_KER_PROT( float, s, gemmsup_rv_zen_asm_6x16n ) GEMMSUP_KER_PROT( float, s, gemmsup_rv_zen_asm_5x16n ) GEMMSUP_KER_PROT( float, s, gemmsup_rv_zen_asm_4x16n ) GEMMSUP_KER_PROT( float, s, gemmsup_rv_zen_asm_3x16n ) GEMMSUP_KER_PROT( float, s, gemmsup_rv_zen_asm_2x16n ) GEMMSUP_KER_PROT( float, s, gemmsup_rv_zen_asm_1x16n ) // gemmsup_rd GEMMSUP_KER_PROT( float, s, gemmsup_rd_zen_asm_2x8) GEMMSUP_KER_PROT( float, s, gemmsup_rd_zen_asm_2x16) GEMMSUP_KER_PROT( float, s, gemmsup_rd_zen_asm_1x8) GEMMSUP_KER_PROT( float, s, gemmsup_rd_zen_asm_1x16) GEMMSUP_KER_PROT( float, s, gemmsup_rd_zen_asm_6x4) GEMMSUP_KER_PROT( float, s, gemmsup_rd_zen_asm_2x4) GEMMSUP_KER_PROT( float, s, gemmsup_rd_zen_asm_1x4) GEMMSUP_KER_PROT( float, s, gemmsup_rd_zen_asm_6x2) GEMMSUP_KER_PROT( float, s, gemmsup_rd_zen_asm_3x2) GEMMSUP_KER_PROT( float, s, gemmsup_rd_zen_asm_2x2) GEMMSUP_KER_PROT( float, s, gemmsup_rd_zen_asm_1x2) GEMMSUP_KER_PROT( float, s, gemmsup_rd_zen_asm_6x16m) GEMMSUP_KER_PROT( float, s, gemmsup_rd_zen_asm_6x8m) GEMMSUP_KER_PROT( float, s, gemmsup_rd_zen_asm_6x4m) GEMMSUP_KER_PROT( float, s, gemmsup_rd_zen_asm_6x2m) GEMMSUP_KER_PROT( float, s, gemmsup_rd_zen_asm_6x16n) GEMMSUP_KER_PROT( float, s, gemmsup_rd_zen_asm_3x16n) GEMMSUP_KER_PROT( float, s, gemmsup_rd_zen_asm_2x16n) GEMMSUP_KER_PROT( float, s, gemmsup_rd_zen_asm_1x16n) GEMMSUP_KER_PROT( scomplex, c, gemmsup_rv_zen_asm_3x8m ) GEMMSUP_KER_PROT( scomplex, c, gemmsup_rv_zen_asm_3x4m ) GEMMSUP_KER_PROT( scomplex, c, gemmsup_rv_zen_asm_3x2m ) GEMMSUP_KER_PROT( scomplex, c, gemmsup_rv_zen_asm_2x8 ) GEMMSUP_KER_PROT( scomplex, c, gemmsup_rv_zen_asm_1x8 ) GEMMSUP_KER_PROT( scomplex, c, gemmsup_rv_zen_asm_2x4 ) GEMMSUP_KER_PROT( scomplex, c, gemmsup_rv_zen_asm_1x4 ) GEMMSUP_KER_PROT( scomplex, c, gemmsup_rv_zen_asm_2x2 ) GEMMSUP_KER_PROT( scomplex, c, gemmsup_rv_zen_asm_1x2 ) GEMMSUP_KER_PROT( dcomplex, z, gemmsup_rv_zen_asm_3x4m ) GEMMSUP_KER_PROT( dcomplex, z, gemmsup_rv_zen_asm_3x2m ) GEMMSUP_KER_PROT( dcomplex, z, gemmsup_rv_zen_asm_2x4 ) GEMMSUP_KER_PROT( dcomplex, z, gemmsup_rv_zen_asm_1x4 ) GEMMSUP_KER_PROT( dcomplex, z, gemmsup_rv_zen_asm_2x2 ) GEMMSUP_KER_PROT( dcomplex, z, gemmsup_rv_zen_asm_1x2 ) // gemmsup_rv (mkernel in n dim) GEMMSUP_KER_PROT( scomplex, c, gemmsup_rv_zen_asm_3x8n ) GEMMSUP_KER_PROT( scomplex, c, gemmsup_rv_zen_asm_2x8n ) GEMMSUP_KER_PROT( scomplex, c, gemmsup_rv_zen_asm_1x8n ) GEMMSUP_KER_PROT( scomplex, c, gemmsup_rv_zen_asm_3x4 ) GEMMSUP_KER_PROT( scomplex, c, gemmsup_rv_zen_asm_3x2 ) GEMMSUP_KER_PROT( dcomplex, z, gemmsup_rv_zen_asm_3x4n ) GEMMSUP_KER_PROT( dcomplex, z, gemmsup_rv_zen_asm_2x4n ) GEMMSUP_KER_PROT( dcomplex, z, gemmsup_rv_zen_asm_1x4n ) GEMMSUP_KER_PROT( dcomplex, z, gemmsup_rv_zen_asm_3x2 ) GEMMSUP_KER_PROT( dcomplex, z, gemmsup_rv_zen_asm_3x1 ) blis-0.9.0/kernels/zen2/000077500000000000000000000000001422157504600150005ustar00rootroot00000000000000blis-0.9.0/kernels/zen2/bli_kernels_zen2.h000066400000000000000000000034571422157504600204110ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // -- level-1f -- AXPYF_KER_PROT( float, s, axpyf_zen_int_5 ) AXPYF_KER_PROT( double, d, axpyf_zen_int_5 ) blis-0.9.0/kernels/zen3/000077500000000000000000000000001422157504600150015ustar00rootroot00000000000000blis-0.9.0/kernels/zen3/.gitignore000066400000000000000000000001071422157504600167670ustar00rootroot00000000000000# Ignore everything in this directory * # Except this file !.gitignore blis-0.9.0/mpi_test/000077500000000000000000000000001422157504600143035ustar00rootroot00000000000000blis-0.9.0/mpi_test/Makefile000066400000000000000000000172041422157504600157470ustar00rootroot00000000000000# # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2014, The University of Texas at Austin # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # # # Makefile # # Field G. Van Zee # # Makefile for standalone BLIS test drivers. # # # --- Makefile PHONY target definitions ---------------------------------------- # .PHONY: all \ blis essl \ clean cleanx # Comments: # - DIST_PATH is assumed to not exist if BLIS_INSTALL_PATH is given. # - We must use recursively expanded assignment for LIB_PATH and INC_PATH in # the second case because CONFIG_NAME is not yet set. ifneq ($(strip $(BLIS_INSTALL_PATH)),) LIB_PATH := $(BLIS_INSTALL_PATH)/lib INC_PATH := $(BLIS_INSTALL_PATH)/include/blis SHARE_PATH := $(BLIS_INSTALL_PATH)/share/blis else DIST_PATH := .. LIB_PATH = ../lib/$(CONFIG_NAME) INC_PATH = ../include/$(CONFIG_NAME) SHARE_PATH := .. endif # # --- Include common makefile definitions -------------------------------------- # # Include the common makefile fragment. -include $(SHARE_PATH)/common.mk # # --- BLAS and LAPACK implementations ------------------------------------------ # # BLAS library path(s). This is where the BLAS libraries reside. BLAS_LIB_PATH := $(HOME)/flame/lib MKL_LIB_PATH := $(HOME)/intel/mkl/lib/intel64/ ESSL_LIB_PATH := /soft/libraries/essl/current/lib64 # OpenBLAS OPENBLAS_LIB := $(BLAS_LIB_PATH)/libopenblas.a # ATLAS ATLAS_LIB := $(BLAS_LIB_PATH)/libf77blas.a \ $(BLAS_LIB_PATH)/libatlas.a # MKL MKL_LIB := -L$(MKL_LIB_PATH) \ -lmkl_sequential \ -lmkl_core \ -lmkl_intel_lp64 # ESSL # Note: ESSL is named differently for SMP and/or BG ESSL_LIB := $(ESSL_LIB_PATH)/libesslsmpbg.a \ -L$(IBM_MAIN_DIR)/xlsmp/bg/3.1/bglib64/ \ -L$(IBM_MAIN_DIR)/xlf/bg/14.1/bglib64/ \ -lxlsmp -lxlf90_r -lxlfmath -lxl # Accelerate MAC_LIB := -framework Accelerate # # --- General build definitions ------------------------------------------------ # TEST_SRC_PATH := . TEST_OBJ_PATH := . # Gather all local object files. TEST_OBJS := $(patsubst $(TEST_SRC_PATH)/%.c, \ $(TEST_OBJ_PATH)/%.o, \ $(wildcard $(TEST_SRC_PATH)/*.c)) # Override the value of CINCFLAGS so that the value of CFLAGS returned by # get-user-cflags-for() is not cluttered up with include paths needed only # while building BLIS. CINCFLAGS := -I$(INC_PATH) # Use the "framework" CFLAGS for the configuration family. CFLAGS := $(call get-user-cflags-for,$(CONFIG_NAME)) # Add local header paths to CFLAGS CFLAGS += -I$(TEST_SRC_PATH) # Locate the libblis library to which we will link. #LIBBLIS_LINK := $(LIB_PATH)/$(LIBBLIS_L) # # --- Targets/rules ------------------------------------------------------------ # # Complete list of possible targets when defining 'all': # # blis openblas atlas mkl mac essl # all: blis essl blis: test_gemm_blis.x \ test_hemm_blis.x \ test_herk_blis.x \ test_her2k_blis.x \ test_trmm_blis.x \ test_trsm_blis.x essl: test_gemm_essl.x \ test_hemm_essl.x \ test_herk_essl.x \ test_her2k_essl.x \ test_trmm_essl.x \ test_trsm_essl.x openblas: test_gemv_openblas.x \ test_ger_openblas.x \ test_hemv_openblas.x \ test_her_openblas.x \ test_her2_openblas.x \ test_trmv_openblas.x \ test_trsv_openblas.x \ \ test_gemm_openblas.x \ test_hemm_openblas.x \ test_herk_openblas.x \ test_her2k_openblas.x \ test_trmm_openblas.x \ test_trsm_openblas.x atlas: test_gemv_atlas.x \ test_ger_atlas.x \ test_hemv_atlas.x \ test_her_atlas.x \ test_her2_atlas.x \ test_trmv_atlas.x \ test_trsv_atlas.x \ \ test_gemm_atlas.x \ test_hemm_atlas.x \ test_herk_atlas.x \ test_her2k_atlas.x \ test_trmm_atlas.x \ test_trsm_atlas.x mkl: test_gemv_mkl.x \ test_ger_mkl.x \ test_hemv_mkl.x \ test_her_mkl.x \ test_her2_mkl.x \ test_trmv_mkl.x \ test_trsv_mkl.x \ \ test_gemm_mkl.x \ test_hemm_mkl.x \ test_herk_mkl.x \ test_her2k_mkl.x \ test_trmm_mkl.x \ test_trsm_mkl.x mac: test_gemv_mac.x \ test_ger_mac.x \ test_hemv_mac.x \ test_her_mac.x \ test_her2_mac.x \ test_trmv_mac.x \ test_trsv_mac.x \ \ test_gemm_mac.x \ test_hemm_mac.x \ test_herk_mac.x \ test_her2k_mac.x \ test_trmm_mac.x \ test_trsm_mac.x # --Object file rules -- $(TEST_OBJ_PATH)/%.o: $(TEST_SRC_PATH)/%.c $(CC) $(CFLAGS) -c $< -o $@ test_%_openblas.o: test_%.c $(CC) $(CFLAGS) -DBLAS=\"openblas\" -c $< -o $@ test_%_atlas.o: test_%.c $(CC) $(CFLAGS) -DBLAS=\"atlas\" -c $< -o $@ test_%_mkl.o: test_%.c $(CC) $(CFLAGS) -DBLAS=\"mkl\" -c $< -o $@ test_%_essl.o: test_%.c $(CC) $(CFLAGS) -DBLAS=\"essl\" -c $< -o $@ test_%_mac.o: test_%.c $(CC) $(CFLAGS) -DBLAS=\"mac\" -c $< -o $@ test_%_blis.o: test_%.c $(CC) $(CFLAGS) -DBLIS -c $< -o $@ # -- Executable file rules -- # NOTE: For the BLAS test drivers, we place the BLAS libraries before BLIS # on the link command line in case BLIS was configured with the BLAS # compatibility layer. This prevents BLIS from inadvertently getting called # for the BLAS routines we are trying to test with. test_%_openblas.x: test_%_openblas.o $(LIBBLIS_LINK) $(LINKER) $< $(OPENBLAS_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $@ test_%_atlas.x: test_%_atlas.o $(LIBBLIS_LINK) $(LINKER) $< $(ATLAS_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $@ test_%_mkl.x: test_%_mkl.o $(LIBBLIS_LINK) $(LINKER) $< $(MKL_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $@ test_%_essl.x: test_%_essl.o $(LIBBLIS_LINK) $(LINKER) $< $(ESSL_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $@ test_%_mac.x: test_%_mac.o $(LIBBLIS_LINK) $(LINKER) $< $(MAC_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $@ test_%_blis.x: test_%_blis.o $(LIBBLIS_LINK) $(LINKER) $< $(LIBBLIS_LINK) $(LDFLAGS) -o $@ # -- Clean rules -- clean: cleanx cleanx: - $(RM_F) *.o *.x blis-0.9.0/mpi_test/test_gemm.c000066400000000000000000000145501422157504600164400ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include #include "blis.h" #include // transa transb m n k alpha a lda b ldb beta c ldc //void dgemm_( char*, char*, int*, int*, int*, double*, double*, int*, double*, int*, double*, double*, int* ); //#define PRINT int main( int argc, char** argv ) { obj_t a, b, c; obj_t c_save; obj_t alpha, beta; dim_t m, n, k; dim_t p; dim_t p_begin, p_end, p_inc; int m_input, n_input, k_input; num_t dt_a, dt_b, dt_c; num_t dt_alpha, dt_beta; int r, n_repeats; double dtime; double dtime_save; double gflops; bli_init(); n_repeats = 3; if( argc < 7 ) { printf("Usage:\n"); printf("test_foo.x m n k p_begin p_inc p_end:\n"); exit; } int world_size, world_rank, provided; MPI_Init_thread( NULL, NULL, MPI_THREAD_FUNNELED, &provided ); MPI_Comm_size( MPI_COMM_WORLD, &world_size ); MPI_Comm_rank( MPI_COMM_WORLD, &world_rank ); m_input = strtol( argv[1], NULL, 10 ); n_input = strtol( argv[2], NULL, 10 ); k_input = strtol( argv[3], NULL, 10 ); p_begin = strtol( argv[4], NULL, 10 ); p_inc = strtol( argv[5], NULL, 10 ); p_end = strtol( argv[6], NULL, 10 ); #if 1 dt_a = BLIS_DOUBLE; dt_b = BLIS_DOUBLE; dt_c = BLIS_DOUBLE; dt_alpha = BLIS_DOUBLE; dt_beta = BLIS_DOUBLE; #else dt_a = dt_b = dt_c = dt_alpha = dt_beta = BLIS_DCOMPLEX; #endif for ( p = p_begin + world_rank * p_inc; p <= p_end; p += p_inc * world_size ) { if ( m_input < 0 ) m = p * ( dim_t )abs(m_input); else m = ( dim_t ) m_input; if ( n_input < 0 ) n = p * ( dim_t )abs(n_input); else n = ( dim_t ) n_input; if ( k_input < 0 ) k = p * ( dim_t )abs(k_input); else k = ( dim_t ) k_input; bli_obj_create( dt_alpha, 1, 1, 0, 0, &alpha ); bli_obj_create( dt_beta, 1, 1, 0, 0, &beta ); bli_obj_create( dt_a, m, k, 0, 0, &a ); bli_obj_create( dt_b, k, n, 0, 0, &b ); bli_obj_create( dt_c, m, n, 0, 0, &c ); bli_obj_create( dt_c, m, n, 0, 0, &c_save ); bli_randm( &a ); bli_randm( &b ); bli_randm( &c ); bli_setsc( (0.9/1.0), 0.2, &alpha ); bli_setsc( (1.0/1.0), 0.0, &beta ); bli_copym( &c, &c_save ); dtime_save = 1.0e9; for ( r = 0; r < n_repeats; ++r ) { bli_copym( &c_save, &c ); dtime = bli_clock(); #ifdef BLIS //bli_error_checking_level_set( BLIS_NO_ERROR_CHECKING ); bli_gemm( &alpha, //bli_gemm4m( &alpha, &a, &b, &beta, &c ); #else if ( bli_is_real( dt_a ) ) { f77_char transa = 'N'; f77_char transb = 'N'; f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); double* alphap = bli_obj_buffer( &alpha ); double* ap = bli_obj_buffer( &a ); double* bp = bli_obj_buffer( &b ); double* betap = bli_obj_buffer( &beta ); double* cp = bli_obj_buffer( &c ); dgemm_( &transa, &transb, &mm, &nn, &kk, alphap, ap, &lda, bp, &ldb, betap, cp, &ldc ); } else { f77_char transa = 'N'; f77_char transb = 'N'; f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); dcomplex* alphap = bli_obj_buffer( &alpha ); dcomplex* ap = bli_obj_buffer( &a ); dcomplex* bp = bli_obj_buffer( &b ); dcomplex* betap = bli_obj_buffer( &beta ); dcomplex* cp = bli_obj_buffer( &c ); zgemm_( &transa, //zgemm3m_( &transa, &transb, &mm, &nn, &kk, alphap, ap, &lda, bp, &ldb, betap, cp, &ldc ); } #endif dtime_save = bli_clock_min_diff( dtime_save, dtime ); } gflops = ( 2.0 * m * k * n ) / ( dtime_save * 1.0e9 ); if ( bli_is_complex( dt_a ) ) gflops *= 4.0; #ifdef BLIS printf( "data_gemm_blis" ); #else printf( "data_gemm_%s", BLAS ); #endif printf( "( %2lu, 1:5 ) = [ %4lu %4lu %4lu %10.3e %6.3f ];\n", ( unsigned long )(p - p_begin + 1)/p_inc + 1, ( unsigned long )m, ( unsigned long )k, ( unsigned long )n, dtime_save, gflops ); bli_obj_free( &alpha ); bli_obj_free( &beta ); bli_obj_free( &a ); bli_obj_free( &b ); bli_obj_free( &c ); bli_obj_free( &c_save ); } bli_finalize(); return 0; } blis-0.9.0/mpi_test/test_hemm.c000066400000000000000000000152411422157504600164370ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include #include "blis.h" #include // side uploa m n alpha a lda b ldb beta c ldc //void dsymm_( char*, char*, int*, int*, double*, double*, int*, double*, int*, double*, double*, int* ); //#define PRINT int main( int argc, char** argv ) { obj_t a, b, c; obj_t c_save; obj_t alpha, beta; dim_t m, n; dim_t p; dim_t p_begin, p_end, p_inc; int m_input, n_input; num_t dt_a, dt_b, dt_c; num_t dt_alpha, dt_beta; int r, n_repeats; side_t side; uplo_t uplo; double dtime; double dtime_save; double gflops; bli_init(); n_repeats = 3; if( argc < 7 ) { printf("Usage:\n"); printf("test_foo.x m n k p_begin p_inc p_end:\n"); exit; } int world_size, world_rank, provided; MPI_Init_thread( NULL, NULL, MPI_THREAD_FUNNELED, &provided ); MPI_Comm_size( MPI_COMM_WORLD, &world_size ); MPI_Comm_rank( MPI_COMM_WORLD, &world_rank ); m_input = strtol( argv[1], NULL, 10 ); n_input = strtol( argv[2], NULL, 10 ); p_begin = strtol( argv[4], NULL, 10 ); p_inc = strtol( argv[5], NULL, 10 ); p_end = strtol( argv[6], NULL, 10 ); #if 1 dt_a = BLIS_DOUBLE; dt_b = BLIS_DOUBLE; dt_c = BLIS_DOUBLE; dt_alpha = BLIS_DOUBLE; dt_beta = BLIS_DOUBLE; #else dt_a = dt_b = dt_c = dt_alpha = dt_beta = BLIS_DCOMPLEX; #endif side = BLIS_LEFT; //side = BLIS_RIGHT; uplo = BLIS_LOWER; //uplo = BLIS_UPPER; for ( p = p_begin + world_rank * p_inc; p <= p_end; p += p_inc * world_size ) { if ( m_input < 0 ) m = p * ( dim_t )abs(m_input); else m = ( dim_t ) m_input; if ( n_input < 0 ) n = p * ( dim_t )abs(n_input); else n = ( dim_t ) n_input; bli_obj_create( dt_alpha, 1, 1, 0, 0, &alpha ); bli_obj_create( dt_beta, 1, 1, 0, 0, &beta ); if ( bli_is_left( side ) ) bli_obj_create( dt_a, m, m, 0, 0, &a ); else bli_obj_create( dt_a, n, n, 0, 0, &a ); bli_obj_create( dt_b, m, n, 0, 0, &b ); bli_obj_create( dt_c, m, n, 0, 0, &c ); bli_obj_create( dt_c, m, n, 0, 0, &c_save ); bli_randm( &a ); bli_randm( &b ); bli_randm( &c ); bli_obj_set_struc( BLIS_HERMITIAN, &a ); bli_obj_set_uplo( uplo, &a ); // Randomize A, make it densely Hermitian, and zero the unstored // triangle to ensure the implementation reads only from the stored // region. bli_randm( &a ); bli_mkherm( &a ); bli_mktrim( &a ); /* bli_obj_toggle_uplo( &a ); bli_obj_inc_diag_offset( 1, &a ); bli_setm( &BLIS_ZERO, &a ); bli_obj_inc_diag_offset( -1, &a ); bli_obj_toggle_uplo( &a ); bli_obj_set_diag( BLIS_NONUNIT_DIAG, &a ); bli_scalm( &BLIS_TWO, &a ); bli_scalm( &BLIS_TWO, &a ); */ bli_setsc( (2.0/1.0), 1.0, &alpha ); bli_setsc( (1.0/1.0), 0.0, &beta ); bli_copym( &c, &c_save ); dtime_save = 1.0e9; for ( r = 0; r < n_repeats; ++r ) { bli_copym( &c_save, &c ); dtime = bli_clock(); #ifdef PRINT /* obj_t ar, ai; bli_obj_alias_to( &a, &ar ); bli_obj_alias_to( &a, &ai ); bli_obj_set_dt( BLIS_DOUBLE, &ar ); ar.rs *= 2; ar.cs *= 2; bli_obj_set_dt( BLIS_DOUBLE, &ai ); ai.rs *= 2; ai.cs *= 2; ai.buffer = ( double* )ai.buffer + 1; bli_printm( "ar", &ar, "%4.1f", "" ); bli_printm( "ai", &ai, "%4.1f", "" ); */ bli_printm( "a", &a, "%4.1f", "" ); bli_printm( "b", &b, "%4.1f", "" ); bli_printm( "c", &c, "%4.1f", "" ); #endif #ifdef BLIS //bli_error_checking_level_set( BLIS_NO_ERROR_CHECKING ); bli_hemm( side, //bli_hemm4m( side, &alpha, &a, &b, &beta, &c ); #else f77_char side = 'L'; f77_char uplo = 'L'; f77_int mm = bli_obj_length( &c ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); double* alphap = bli_obj_buffer( &alpha ); double* ap = bli_obj_buffer( &a ); double* bp = bli_obj_buffer( &b ); double* betap = bli_obj_buffer( &beta ); double* cp = bli_obj_buffer( &c ); dsymm_( &side, &uplo, &mm, &nn, alphap, ap, &lda, bp, &ldb, betap, cp, &ldc ); #endif #ifdef PRINT bli_printm( "c after", &c, "%9.5f", "" ); exit(1); #endif dtime_save = bli_clock_min_diff( dtime_save, dtime ); } if ( bli_is_left( side ) ) gflops = ( 2.0 * m * m * n ) / ( dtime_save * 1.0e9 ); else gflops = ( 2.0 * m * n * n ) / ( dtime_save * 1.0e9 ); if ( bli_is_complex( dt_a ) ) gflops *= 4.0; #ifdef BLIS printf( "data_hemm_blis" ); #else printf( "data_hemm_%s", BLAS ); #endif printf( "( %2lu, 1:4 ) = [ %4lu %4lu %10.3e %6.3f ];\n", ( unsigned long )(p - p_begin + 1)/p_inc + 1, ( unsigned long )m, ( unsigned long )n, dtime_save, gflops ); bli_obj_free( &alpha ); bli_obj_free( &beta ); bli_obj_free( &a ); bli_obj_free( &b ); bli_obj_free( &c ); bli_obj_free( &c_save ); } bli_finalize(); return 0; } blis-0.9.0/mpi_test/test_her2k.c000066400000000000000000000127621422157504600165310ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include #include "blis.h" #include // uploa transa m k alpha a lda b ldb beta c ldc //void dsyr2k_( char*, char*, int*, int*, double*, double*, int*, double*, int*, double*, double*, int* ); //#define PRINT int main( int argc, char** argv ) { obj_t a, b, c; obj_t c_save; obj_t alpha, beta; dim_t m, k; dim_t p; dim_t p_begin, p_end, p_inc; int m_input, k_input; num_t dt_a, dt_b, dt_c; num_t dt_alpha, dt_beta; int r, n_repeats; uplo_t uplo; double dtime; double dtime_save; double gflops; bli_init(); n_repeats = 3; if( argc < 7 ) { printf("Usage:\n"); printf("test_foo.x m n k p_begin p_inc p_end:\n"); exit; } int world_size, world_rank, provided; MPI_Init_thread( NULL, NULL, MPI_THREAD_FUNNELED, &provided ); MPI_Comm_size( MPI_COMM_WORLD, &world_size ); MPI_Comm_rank( MPI_COMM_WORLD, &world_rank ); m_input = strtol( argv[1], NULL, 10 ); k_input = strtol( argv[3], NULL, 10 ); p_begin = strtol( argv[4], NULL, 10 ); p_inc = strtol( argv[5], NULL, 10 ); p_end = strtol( argv[6], NULL, 10 ); dt_a = BLIS_DOUBLE; dt_b = BLIS_DOUBLE; dt_c = BLIS_DOUBLE; dt_alpha = BLIS_DOUBLE; dt_beta = BLIS_DOUBLE; uplo = BLIS_LOWER; for ( p = p_begin + world_rank * p_inc; p <= p_end; p += p_inc * world_size ) { if ( m_input < 0 ) m = p * ( dim_t )abs(m_input); else m = ( dim_t ) m_input; if ( k_input < 0 ) k = p * ( dim_t )abs(k_input); else k = ( dim_t ) k_input; bli_obj_create( dt_alpha, 1, 1, 0, 0, &alpha ); bli_obj_create( dt_beta, 1, 1, 0, 0, &beta ); bli_obj_create( dt_a, m, k, 0, 0, &a ); bli_obj_create( dt_b, m, k, 0, 0, &b ); bli_obj_create( dt_c, m, m, 0, 0, &c ); bli_obj_create( dt_c, m, m, 0, 0, &c_save ); bli_randm( &a ); bli_randm( &b ); bli_randm( &c ); bli_obj_set_struc( BLIS_HERMITIAN, &c ); bli_obj_set_uplo( uplo, &c ); bli_setsc( (2.0/1.0), 0.0, &alpha ); bli_setsc( (1.0/1.0), 0.0, &beta ); bli_copym( &c, &c_save ); dtime_save = 1.0e9; for ( r = 0; r < n_repeats; ++r ) { bli_copym( &c_save, &c ); dtime = bli_clock(); #ifdef PRINT bli_printm( "a", &a, "%4.1f", "" ); bli_printm( "b", &b, "%4.1f", "" ); bli_printm( "c", &c, "%4.1f", "" ); #endif #ifdef BLIS //bli_error_checking_level_set( BLIS_NO_ERROR_CHECKING ); bli_her2k( &alpha, &a, &b, &beta, &c ); #else f77_char uploa = 'L'; f77_char transa = 'N'; f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); double* alphap = bli_obj_buffer( &alpha ); double* ap = bli_obj_buffer( &a ); double* bp = bli_obj_buffer( &b ); double* betap = bli_obj_buffer( &beta ); double* cp = bli_obj_buffer( &c ); dsyr2k_( &uploa, &transa, &mm, &kk, alphap, ap, &lda, bp, &ldb, betap, cp, &ldc ); #endif #ifdef PRINT bli_printm( "c after", &c, "%4.1f", "" ); exit(1); #endif dtime_save = bli_clock_min_diff( dtime_save, dtime ); } gflops = ( 2.0 * m * k * m ) / ( dtime_save * 1.0e9 ); #ifdef BLIS printf( "data_her2k_blis" ); #else printf( "data_her2k_%s", BLAS ); #endif printf( "( %2lu, 1:4 ) = [ %4lu %4lu %10.3e %6.3f ];\n", ( unsigned long )(p - p_begin + 1)/p_inc + 1, ( unsigned long )m, ( unsigned long )k, dtime_save, gflops ); bli_obj_free( &alpha ); bli_obj_free( &beta ); bli_obj_free( &a ); bli_obj_free( &b ); bli_obj_free( &c ); bli_obj_free( &c_save ); } bli_finalize(); return 0; } blis-0.9.0/mpi_test/test_herk.c000066400000000000000000000122521422157504600164410ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include #include "blis.h" #include // uploa transa m k alpha a lda beta c ldc //void dsyrk_( char*, char*, int*, int*, double*, double*, int*, double*, double*, int* ); //#define PRINT int main( int argc, char** argv ) { obj_t a, c; obj_t c_save; obj_t alpha, beta; dim_t m, k; dim_t p; dim_t p_begin, p_end, p_inc; int m_input, k_input; num_t dt_a, dt_c; num_t dt_alpha, dt_beta; int r, n_repeats; uplo_t uplo; double dtime; double dtime_save; double gflops; bli_init(); n_repeats = 3; if( argc < 7 ) { printf("Usage:\n"); printf("test_foo.x m n k p_begin p_inc p_end:\n"); exit; } int world_size, world_rank, provided; MPI_Init_thread( NULL, NULL, MPI_THREAD_FUNNELED, &provided ); MPI_Comm_size( MPI_COMM_WORLD, &world_size ); MPI_Comm_rank( MPI_COMM_WORLD, &world_rank ); m_input = strtol( argv[1], NULL, 10 ); k_input = strtol( argv[3], NULL, 10 ); p_begin = strtol( argv[4], NULL, 10 ); p_inc = strtol( argv[5], NULL, 10 ); p_end = strtol( argv[6], NULL, 10 ); dt_a = BLIS_DOUBLE; dt_c = BLIS_DOUBLE; dt_alpha = BLIS_DOUBLE; dt_beta = BLIS_DOUBLE; uplo = BLIS_LOWER; for ( p = p_begin + world_rank * p_inc; p <= p_end; p += p_inc * world_size ) { if ( m_input < 0 ) m = p * ( dim_t )abs(m_input); else m = ( dim_t ) m_input; if ( k_input < 0 ) k = p * ( dim_t )abs(k_input); else k = ( dim_t ) k_input; bli_obj_create( dt_alpha, 1, 1, 0, 0, &alpha ); bli_obj_create( dt_beta, 1, 1, 0, 0, &beta ); bli_obj_create( dt_a, m, k, 0, 0, &a ); bli_obj_create( dt_c, m, m, 0, 0, &c ); bli_obj_create( dt_c, m, m, 0, 0, &c_save ); bli_randm( &a ); bli_randm( &c ); bli_obj_set_struc( BLIS_HERMITIAN, &c ); bli_obj_set_uplo( uplo, &c ); bli_setsc( (2.0/1.0), 0.0, &alpha ); bli_setsc( (1.0/1.0), 0.0, &beta ); bli_copym( &c, &c_save ); dtime_save = 1.0e9; for ( r = 0; r < n_repeats; ++r ) { bli_copym( &c_save, &c ); dtime = bli_clock(); #ifdef PRINT bli_printm( "a", &a, "%4.1f", "" ); bli_printm( "c", &c, "%4.1f", "" ); #endif #ifdef BLIS //bli_error_checking_level_set( BLIS_NO_ERROR_CHECKING ); bli_herk( &alpha, &a, &beta, &c ); #else f77_char uploa = 'L'; f77_char transa = 'N'; f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldc = bli_obj_col_stride( &c ); double* alphap = bli_obj_buffer( &alpha ); double* ap = bli_obj_buffer( &a ); double* betap = bli_obj_buffer( &beta ); double* cp = bli_obj_buffer( &c ); dsyrk_( &uploa, &transa, &mm, &kk, alphap, ap, &lda, betap, cp, &ldc ); #endif #ifdef PRINT bli_printm( "c after", &c, "%4.1f", "" ); exit(1); #endif dtime_save = bli_clock_min_diff( dtime_save, dtime ); } gflops = ( 1.0 * m * k * m ) / ( dtime_save * 1.0e9 ); #ifdef BLIS printf( "data_herk_blis" ); #else printf( "data_herk_%s", BLAS ); #endif printf( "( %2lu, 1:4 ) = [ %4lu %4lu %10.3e %6.3f ];\n", ( unsigned long )(p - p_begin + 1)/p_inc + 1, ( unsigned long )m, ( unsigned long )k, dtime_save, gflops ); bli_obj_free( &alpha ); bli_obj_free( &beta ); bli_obj_free( &a ); bli_obj_free( &c ); bli_obj_free( &c_save ); } bli_finalize(); return 0; } blis-0.9.0/mpi_test/test_trmm.c000066400000000000000000000144371422157504600164760ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include #include "blis.h" #include // side uplo trans diag m n alpha a lda b ldb //void dtrmm_( char*, char*, char*, char*, int*, int*, double*, double*, int*, double*, int* ); //#define PRINT int main( int argc, char** argv ) { obj_t a, b, c; obj_t c_save; obj_t alpha, beta; dim_t m, n; dim_t p; dim_t p_begin, p_end, p_inc; int m_input, n_input; num_t dt_a, dt_b, dt_c; num_t dt_alpha, dt_beta; int r, n_repeats; side_t side; uplo_t uplo; double dtime; double dtime_save; double gflops; bli_init(); n_repeats = 3; if( argc < 7 ) { printf("Usage:\n"); printf("test_foo.x m n p_begin p_inc p_end:\n"); exit; } int world_size, world_rank, provided; MPI_Init_thread( NULL, NULL, MPI_THREAD_FUNNELED, &provided ); MPI_Comm_size( MPI_COMM_WORLD, &world_size ); MPI_Comm_rank( MPI_COMM_WORLD, &world_rank ); m_input = strtol( argv[1], NULL, 10 ); n_input = strtol( argv[2], NULL, 10 ); p_begin = strtol( argv[4], NULL, 10 ); p_inc = strtol( argv[5], NULL, 10 ); p_end = strtol( argv[6], NULL, 10 ); #if 1 dt_a = BLIS_DOUBLE; dt_b = BLIS_DOUBLE; dt_c = BLIS_DOUBLE; dt_alpha = BLIS_DOUBLE; dt_beta = BLIS_DOUBLE; #else dt_a = dt_b = dt_c = dt_alpha = dt_beta = BLIS_DCOMPLEX; #endif side = BLIS_LEFT; //side = BLIS_RIGHT; uplo = BLIS_LOWER; //uplo = BLIS_UPPER; for ( p = p_begin + world_rank * p_inc; p <= p_end; p += p_inc * world_size ) { if ( m_input < 0 ) m = p * ( dim_t )abs(m_input); else m = ( dim_t ) m_input; if ( n_input < 0 ) n = p * ( dim_t )abs(n_input); else n = ( dim_t ) n_input; bli_obj_create( dt_alpha, 1, 1, 0, 0, &alpha ); bli_obj_create( dt_beta, 1, 1, 0, 0, &beta ); if ( bli_is_left( side ) ) bli_obj_create( dt_a, m, m, 0, 0, &a ); else bli_obj_create( dt_a, n, n, 0, 0, &a ); bli_obj_create( dt_b, m, n, 0, 0, &b ); bli_obj_create( dt_c, m, n, 0, 0, &c ); bli_obj_create( dt_c, m, n, 0, 0, &c_save ); bli_obj_set_struc( BLIS_TRIANGULAR, &a ); bli_obj_set_uplo( uplo, &a ); bli_randm( &a ); bli_randm( &c ); bli_randm( &b ); /* bli_obj_toggle_uplo( &a ); bli_obj_inc_diag_offset( -1, &a ); bli_setm( &BLIS_ZERO, &a ); bli_obj_inc_diag_offset( 1, &a ); bli_obj_toggle_uplo( &a ); bli_obj_set_diag( BLIS_NONUNIT_DIAG, &a ); bli_scalm( &BLIS_TWO, &a ); //bli_scalm( &BLIS_TWO, &a ); */ bli_setsc( (2.0/1.0), 0.0, &alpha ); bli_setsc( (1.0/1.0), 0.0, &beta ); bli_copym( &c, &c_save ); dtime_save = 1.0e9; for ( r = 0; r < n_repeats; ++r ) { bli_copym( &c_save, &c ); dtime = bli_clock(); #ifdef PRINT /* obj_t ar, ai; bli_obj_alias_to( &a, &ar ); bli_obj_alias_to( &a, &ai ); bli_obj_set_dt( BLIS_DOUBLE, &ar ); ar.rs *= 2; ar.cs *= 2; bli_obj_set_dt( BLIS_DOUBLE, &ai ); ai.rs *= 2; ai.cs *= 2; ai.buffer = ( double* )ai.buffer + 1; bli_printm( "ar", &ar, "%4.1f", "" ); bli_printm( "ai", &ai, "%4.1f", "" ); */ bli_printm( "a", &a, "%4.1f", "" ); bli_printm( "c", &c, "%4.1f", "" ); #endif #ifdef BLIS bli_error_checking_level_set( BLIS_NO_ERROR_CHECKING ); bli_trmm( side, //bli_trmm4m( side, &alpha, &a, &c ); #else f77_char side = 'L'; f77_char uplo = 'L'; f77_char transa = 'N'; f77_char diag = 'N'; f77_int mm = bli_obj_length( &c ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldc = bli_obj_col_stride( &c ); double* alphap = bli_obj_buffer( &alpha ); double* ap = bli_obj_buffer( &a ); double* cp = bli_obj_buffer( &c ); dtrmm_( &side, &uplo, &transa, &diag, &mm, &nn, alphap, ap, &lda, cp, &ldc ); #endif #ifdef PRINT bli_printm( "c after", &c, "%4.1f", "" ); exit(1); #endif dtime_save = bli_clock_min_diff( dtime_save, dtime ); } if ( bli_is_left( side ) ) gflops = ( 1.0 * m * m * n ) / ( dtime_save * 1.0e9 ); else gflops = ( 1.0 * m * n * n ) / ( dtime_save * 1.0e9 ); if ( bli_is_complex( dt_a ) ) gflops *= 4.0; #ifdef BLIS printf( "data_trmm_blis" ); #else printf( "data_trmm_%s", BLAS ); #endif printf( "( %2lu, 1:4 ) = [ %4lu %4lu %10.3e %6.3f ];\n", ( unsigned long )(p - p_begin + 1)/p_inc + 1, ( unsigned long )m, ( unsigned long )n, dtime_save, gflops ); bli_obj_free( &alpha ); bli_obj_free( &beta ); bli_obj_free( &a ); bli_obj_free( &b ); bli_obj_free( &c ); bli_obj_free( &c_save ); } bli_finalize(); return 0; } blis-0.9.0/mpi_test/test_trsm.c000066400000000000000000000163221422157504600164770ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include #include "blis.h" #include // side uplo trans diag m n alpha a lda b ldb //void dtrsm_( char*, char*, char*, char*, int*, int*, double*, double*, int*, double*, int* ); //#define PRINT int main( int argc, char** argv ) { obj_t a, b, c; obj_t c_save; obj_t alpha, beta; dim_t m, n; dim_t p; dim_t p_begin, p_end, p_inc; int m_input, n_input; num_t dt_a, dt_b, dt_c; num_t dt_alpha, dt_beta; int r, n_repeats; side_t side; uplo_t uplo; double dtime; double dtime_save; double gflops; bli_init(); n_repeats = 3; if( argc < 7 ) { printf("Usage:\n"); printf("test_foo.x m n k p_begin p_inc p_end:\n"); exit; } int world_size, world_rank, provided; MPI_Init_thread( NULL, NULL, MPI_THREAD_FUNNELED, &provided ); MPI_Comm_size( MPI_COMM_WORLD, &world_size ); MPI_Comm_rank( MPI_COMM_WORLD, &world_rank ); m_input = strtol( argv[1], NULL, 10 ); n_input = strtol( argv[2], NULL, 10 ); p_begin = strtol( argv[4], NULL, 10 ); p_inc = strtol( argv[5], NULL, 10 ); p_end = strtol( argv[6], NULL, 10 ); #if 1 dt_a = BLIS_DOUBLE; dt_b = BLIS_DOUBLE; dt_c = BLIS_DOUBLE; dt_alpha = BLIS_DOUBLE; dt_beta = BLIS_DOUBLE; #else dt_a = dt_b = dt_c = dt_alpha = dt_beta = BLIS_FLOAT; //dt_a = dt_b = dt_c = dt_alpha = dt_beta = BLIS_SCOMPLEX; #endif side = BLIS_LEFT; //side = BLIS_RIGHT; uplo = BLIS_LOWER; //uplo = BLIS_UPPER; for ( p = p_begin + world_rank * p_inc; p <= p_end; p += p_inc * world_size ) { if ( m_input < 0 ) m = p * ( dim_t )abs(m_input); else m = ( dim_t ) m_input; if ( n_input < 0 ) n = p * ( dim_t )abs(n_input); else n = ( dim_t ) n_input; bli_obj_create( dt_alpha, 1, 1, 0, 0, &alpha ); bli_obj_create( dt_beta, 1, 1, 0, 0, &beta ); if ( bli_is_left( side ) ) bli_obj_create( dt_a, m, m, 0, 0, &a ); else bli_obj_create( dt_a, n, n, 0, 0, &a ); bli_obj_create( dt_b, m, n, 0, 0, &b ); bli_obj_create( dt_c, m, n, 0, 0, &c ); bli_obj_create( dt_c, m, n, 0, 0, &c_save ); bli_obj_set_struc( BLIS_TRIANGULAR, &a ); bli_obj_set_uplo( uplo, &a ); //bli_obj_set_diag( BLIS_UNIT_DIAG, &a ); bli_randm( &a ); bli_randm( &c ); bli_randm( &b ); /* { obj_t a2; bli_obj_alias_to( &a, &a2 ); bli_obj_toggle_uplo( &a2 ); bli_obj_inc_diag_offset( 1, &a2 ); bli_setm( &BLIS_ZERO, &a2 ); bli_obj_inc_diag_offset( -2, &a2 ); bli_obj_toggle_uplo( &a2 ); bli_obj_set_diag( BLIS_NONUNIT_DIAG, &a2 ); bli_scalm( &BLIS_TWO, &a2 ); //bli_scalm( &BLIS_TWO, &a ); } */ bli_setsc( (2.0/1.0), 0.0, &alpha ); bli_setsc( (1.0/1.0), 0.0, &beta ); bli_copym( &c, &c_save ); dtime_save = 1.0e9; for ( r = 0; r < n_repeats; ++r ) { bli_copym( &c_save, &c ); dtime = bli_clock(); #ifdef PRINT /* obj_t ar, ai; bli_obj_alias_to( &a, &ar ); bli_obj_alias_to( &a, &ai ); bli_obj_set_dt( BLIS_DOUBLE, &ar ); ar.rs *= 2; ar.cs *= 2; bli_obj_set_dt( BLIS_DOUBLE, &ai ); ai.rs *= 2; ai.cs *= 2; ai.buffer = ( double* )ai.buffer + 1; bli_printm( "ar", &ar, "%4.1f", "" ); bli_printm( "ai", &ai, "%4.1f", "" ); */ bli_invertd( &a ); bli_printm( "a", &a, "%4.1f", "" ); bli_invertd( &a ); bli_printm( "c", &c, "%4.1f", "" ); #endif #ifdef BLIS //bli_error_checking_level_set( BLIS_NO_ERROR_CHECKING ); bli_trsm( side, //bli_trsm4m( side, //bli_trsm3m( side, &alpha, &a, &c ); #else if ( bli_is_real( dt_a ) ) { f77_char side = 'L'; f77_char uplo = 'L'; f77_char transa = 'N'; f77_char diag = 'N'; f77_int mm = bli_obj_length( &c ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldc = bli_obj_col_stride( &c ); float * alphap = bli_obj_buffer( &alpha ); float * ap = bli_obj_buffer( &a ); float * cp = bli_obj_buffer( &c ); strsm_( &side, &uplo, &transa, &diag, &mm, &nn, alphap, ap, &lda, cp, &ldc ); } else // if ( bli_is_complex( dt_a ) ) { f77_char side = 'L'; f77_char uplo = 'L'; f77_char transa = 'N'; f77_char diag = 'N'; f77_int mm = bli_obj_length( &c ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldc = bli_obj_col_stride( &c ); scomplex* alphap = bli_obj_buffer( &alpha ); scomplex* ap = bli_obj_buffer( &a ); scomplex* cp = bli_obj_buffer( &c ); ctrsm_( &side, //ztrsm_( &side, &uplo, &transa, &diag, &mm, &nn, alphap, ap, &lda, cp, &ldc ); } #endif #ifdef PRINT bli_printm( "c after", &c, "%4.1f", "" ); exit(1); #endif dtime_save = bli_clock_min_diff( dtime_save, dtime ); } if ( bli_is_left( side ) ) gflops = ( 1.0 * m * m * n ) / ( dtime_save * 1.0e9 ); else gflops = ( 1.0 * m * n * n ) / ( dtime_save * 1.0e9 ); if ( bli_is_complex( dt_a ) ) gflops *= 4.0; #ifdef BLIS printf( "data_trsm_blis" ); #else printf( "data_trsm_%s", BLAS ); #endif printf( "( %2lu, 1:4 ) = [ %4lu %4lu %10.3e %6.3f ];\n", ( unsigned long )(p - p_begin + 1)/p_inc + 1, ( unsigned long )m, ( unsigned long )n, dtime_save, gflops ); bli_obj_free( &alpha ); bli_obj_free( &beta ); bli_obj_free( &a ); bli_obj_free( &b ); bli_obj_free( &c ); bli_obj_free( &c_save ); } bli_finalize(); return 0; } blis-0.9.0/ref_kernels/000077500000000000000000000000001422157504600147565ustar00rootroot00000000000000blis-0.9.0/ref_kernels/1/000077500000000000000000000000001422157504600151165ustar00rootroot00000000000000blis-0.9.0/ref_kernels/1/bli_addv_ref.c000066400000000000000000000054471422157504600176740ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, arch, suf ) \ \ void PASTEMAC3(ch,opname,arch,suf) \ ( \ conj_t conjx, \ dim_t n, \ ctype* restrict x, inc_t incx, \ ctype* restrict y, inc_t incy, \ cntx_t* restrict cntx \ ) \ { \ if ( bli_zero_dim1( n ) ) return; \ \ ctype* restrict chi1 = x; \ ctype* restrict psi1 = y; \ \ if ( bli_is_conj( conjx ) ) \ { \ if ( incx == 1 && incy == 1 ) \ { \ PRAGMA_SIMD \ for ( dim_t i = 0; i < n; ++i ) \ { \ PASTEMAC(ch,addjs)( chi1[i], psi1[i] ); \ } \ } \ else \ { \ for ( dim_t i = 0; i < n; ++i ) \ { \ PASTEMAC(ch,addjs)( *chi1, *psi1 ); \ \ chi1 += incx; \ psi1 += incy; \ } \ } \ } \ else \ { \ if ( incx == 1 && incy == 1 ) \ { \ PRAGMA_SIMD \ for ( dim_t i = 0; i < n; ++i ) \ { \ PASTEMAC(ch,adds)( chi1[i], psi1[i] ); \ } \ } \ else \ { \ for ( dim_t i = 0; i < n; ++i ) \ { \ PASTEMAC(ch,adds)( *chi1, *psi1 ); \ \ chi1 += incx; \ psi1 += incy; \ } \ } \ } \ } INSERT_GENTFUNC_BASIC2( addv, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX ) blis-0.9.0/ref_kernels/1/bli_amaxv_ref.c000066400000000000000000000116431422157504600200650ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // Define BLAS-like interfaces with typed operands. // #undef GENTFUNCR #define GENTFUNCR( ctype, ctype_r, ch, chr, opname, arch, suf ) \ \ void PASTEMAC3(ch,opname,arch,suf) \ ( \ dim_t n, \ ctype* restrict x, inc_t incx, \ dim_t* restrict i_max, \ cntx_t* restrict cntx \ ) \ { \ ctype_r* minus_one = PASTEMAC(chr,m1); \ dim_t* zero_i = PASTEMAC(i,0); \ \ ctype_r chi1_r; \ ctype_r chi1_i; \ ctype_r abs_chi1; \ ctype_r abs_chi1_max; \ dim_t i_max_l; \ \ /* If the vector length is zero, return early. This directly emulates the behavior of netlib BLAS's i?amax() routines. */ \ if ( bli_zero_dim1( n ) ) \ { \ PASTEMAC(i,copys)( *zero_i, *i_max ); \ return; \ } \ \ /* Initialize the index of the maximum absolute value to zero. */ \ PASTEMAC(i,copys)( *zero_i, i_max_l ); \ \ /* Initialize the maximum absolute value search candidate with -1, which is guaranteed to be less than all values we will compute. */ \ PASTEMAC(chr,copys)( *minus_one, abs_chi1_max ); \ \ if ( incx == 1 ) \ { \ ctype* chi1 = x; \ \ for ( dim_t i = 0; i < n; ++i ) \ { \ /* Get the real and imaginary components of chi1. */ \ PASTEMAC2(ch,chr,gets)( *chi1, chi1_r, chi1_i ); \ \ /* Replace chi1_r and chi1_i with their absolute values. */ \ PASTEMAC(chr,abval2s)( chi1_r, chi1_r ); \ PASTEMAC(chr,abval2s)( chi1_i, chi1_i ); \ \ /* Add the real and imaginary absolute values together. */ \ PASTEMAC(chr,set0s)( abs_chi1 ); \ PASTEMAC(chr,adds)( chi1_r, abs_chi1 ); \ PASTEMAC(chr,adds)( chi1_i, abs_chi1 ); \ \ /* If the absolute value of the current element exceeds that of the previous largest, save it and its index. If NaN is encountered, then treat it the same as if it were a valid value that was smaller than any previously seen. This behavior mimics that of LAPACK's ?lange(). */ \ if ( abs_chi1_max < abs_chi1 || ( bli_isnan( abs_chi1 ) && !bli_isnan( abs_chi1_max ) ) ) \ { \ abs_chi1_max = abs_chi1; \ i_max_l = i; \ } \ \ chi1 += 1; \ } \ } \ else \ { \ for ( dim_t i = 0; i < n; ++i ) \ { \ ctype* chi1 = x + (i )*incx; \ \ /* Get the real and imaginary components of chi1. */ \ PASTEMAC2(ch,chr,gets)( *chi1, chi1_r, chi1_i ); \ \ /* Replace chi1_r and chi1_i with their absolute values. */ \ PASTEMAC(chr,abval2s)( chi1_r, chi1_r ); \ PASTEMAC(chr,abval2s)( chi1_i, chi1_i ); \ \ /* Add the real and imaginary absolute values together. */ \ PASTEMAC(chr,set0s)( abs_chi1 ); \ PASTEMAC(chr,adds)( chi1_r, abs_chi1 ); \ PASTEMAC(chr,adds)( chi1_i, abs_chi1 ); \ \ /* If the absolute value of the current element exceeds that of the previous largest, save it and its index. If NaN is encountered, then treat it the same as if it were a valid value that was smaller than any previously seen. This behavior mimics that of LAPACK's ?lange(). */ \ if ( abs_chi1_max < abs_chi1 || ( bli_isnan( abs_chi1 ) && !bli_isnan( abs_chi1_max ) ) ) \ { \ abs_chi1_max = abs_chi1; \ i_max_l = i; \ } \ } \ } \ \ /* Store the final index to the output variable. */ \ PASTEMAC(i,copys)( i_max_l, *i_max ); \ } INSERT_GENTFUNCR_BASIC2( amaxv, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX ) blis-0.9.0/ref_kernels/1/bli_axpbyv_ref.c000066400000000000000000000142501422157504600202570ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, arch, suf ) \ \ void PASTEMAC3(ch,opname,arch,suf) \ ( \ conj_t conjx, \ dim_t n, \ ctype* restrict alpha, \ ctype* restrict x, inc_t incx, \ ctype* restrict beta, \ ctype* restrict y, inc_t incy, \ cntx_t* restrict cntx \ ) \ { \ if ( bli_zero_dim1( n ) ) return; \ \ if ( PASTEMAC(ch,eq0)( *alpha ) ) \ { \ if ( PASTEMAC(ch,eq0)( *beta ) ) \ { \ /* If alpha is zero and beta is zero, set to zero. */ \ \ ctype* zero = PASTEMAC(ch,0); \ \ /* Query the context for the kernel function pointer. */ \ const num_t dt = PASTEMAC(ch,type); \ PASTECH(ch,setv_ker_ft) setv_p = bli_cntx_get_l1v_ker_dt( dt, BLIS_SETV_KER, cntx ); \ \ setv_p \ ( \ BLIS_NO_CONJUGATE, \ n, \ zero, \ y, incy, \ cntx \ ); \ return; \ } \ else if ( PASTEMAC(ch,eq1)( *beta ) ) \ { \ /* If alpha is zero and beta is one, return. */ \ return; \ } \ else \ { \ /* If alpha is zero, scale by beta. */ \ \ /* Query the context for the kernel function pointer. */ \ const num_t dt = PASTEMAC(ch,type); \ PASTECH(ch,scalv_ker_ft) scalv_p = bli_cntx_get_l1v_ker_dt( dt, BLIS_SCALV_KER, cntx ); \ \ scalv_p \ ( \ BLIS_NO_CONJUGATE, \ n, \ beta, \ y, incy, \ cntx \ ); \ return; \ } \ \ } \ else if ( PASTEMAC(ch,eq1)( *alpha ) ) \ { \ if ( PASTEMAC(ch,eq0)( *beta ) ) \ { \ /* If alpha is one and beta is zero, use copyv. */ \ \ /* Query the context for the kernel function pointer. */ \ const num_t dt = PASTEMAC(ch,type); \ PASTECH(ch,copyv_ker_ft) copyv_p = bli_cntx_get_l1v_ker_dt( dt, BLIS_COPYV_KER, cntx ); \ \ copyv_p \ ( \ conjx, \ n, \ x, incx, \ y, incy, \ cntx \ ); \ return; \ } \ else if ( PASTEMAC(ch,eq1)( *beta ) ) \ { \ /* If alpha is one and beta is one, use addv. */ \ \ /* Query the context for the kernel function pointer. */ \ const num_t dt = PASTEMAC(ch,type); \ PASTECH(ch,addv_ker_ft) addv_p = bli_cntx_get_l1v_ker_dt( dt, BLIS_ADDV_KER, cntx ); \ \ addv_p \ ( \ conjx, \ n, \ x, incx, \ y, incy, \ cntx \ ); \ return; \ } \ else \ { \ /* If alpha is one and beta is something else, use xpbyv. */ \ \ /* Query the context for the kernel function pointer. */ \ const num_t dt = PASTEMAC(ch,type); \ PASTECH(ch,xpbyv_ker_ft) xpbyv_p = bli_cntx_get_l1v_ker_dt( dt, BLIS_XPBYV_KER, cntx ); \ \ xpbyv_p \ ( \ conjx, \ n, \ x, incx, \ beta, \ y, incy, \ cntx \ ); \ return; \ } \ } \ else \ { \ if ( PASTEMAC(ch,eq0)( *beta ) ) \ { \ /* If alpha is something else and beta is zero, use scal2v. */ \ \ /* Query the context for the kernel function pointer. */ \ const num_t dt = PASTEMAC(ch,type); \ PASTECH(ch,scal2v_ker_ft) scal2v_p = bli_cntx_get_l1v_ker_dt( dt, BLIS_SCAL2V_KER, cntx ); \ \ scal2v_p \ ( \ conjx, \ n, \ alpha, \ x, incx, \ y, incy, \ cntx \ ); \ return; \ } \ else if ( PASTEMAC(ch,eq1)( *beta ) ) \ { \ /* If alpha is something else and beta is one, use axpyv. */ \ \ /* Query the context for the kernel function pointer. */ \ const num_t dt = PASTEMAC(ch,type); \ PASTECH(ch,axpyv_ker_ft) axpyv_p = bli_cntx_get_l1v_ker_dt( dt, BLIS_AXPYV_KER, cntx ); \ \ axpyv_p \ ( \ conjx, \ n, \ alpha, \ x, incx, \ y, incy, \ cntx \ ); \ return; \ } \ } \ \ /* If execution reaches here, alpha and beta are both non-zero/non-unit. */ \ \ if ( bli_is_conj( conjx ) ) \ { \ if ( incx == 1 && incy == 1 ) \ { \ PRAGMA_SIMD \ for ( dim_t i = 0; i < n; ++i ) \ { \ PASTEMAC(ch,axpbyjs)( *alpha, x[i], *beta, y[i] ); \ } \ } \ else \ { \ for ( dim_t i = 0; i < n; ++i ) \ { \ PASTEMAC(ch,axpbyjs)( *alpha, *x, *beta, *y ); \ \ x += incx; \ y += incy; \ } \ } \ } \ else \ { \ if ( incx == 1 && incy == 1 ) \ { \ PRAGMA_SIMD \ for ( dim_t i = 0; i < n; ++i ) \ { \ PASTEMAC(ch,axpbys)( *alpha, x[i], *beta, y[i] ); \ } \ } \ else \ { \ for ( dim_t i = 0; i < n; ++i ) \ { \ PASTEMAC(ch,axpbys)( *alpha, *x, *beta, *y ); \ \ x += incx; \ y += incy; \ } \ } \ } \ } INSERT_GENTFUNC_BASIC2( axpbyv, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX ) blis-0.9.0/ref_kernels/1/bli_axpyv_ref.c000066400000000000000000000122211422157504600201110ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #if 0 #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, arch, suf ) \ \ void PASTEMAC3(ch,opname,arch,suf) \ ( \ conj_t conjx, \ dim_t n, \ ctype* restrict alpha, \ ctype* restrict x, inc_t incx, \ ctype* restrict y, inc_t incy, \ cntx_t* restrict cntx \ ) \ { \ if ( bli_zero_dim1( n ) ) return; \ \ /* If alpha is zero, return. */ \ if ( PASTEMAC(ch,eq0)( *alpha ) ) return; \ \ /* If alpha is one, use addv. */ \ if ( PASTEMAC(ch,eq1)( *alpha ) ) \ { \ /* Query the context for the kernel function pointer. */ \ const num_t dt = PASTEMAC(ch,type); \ PASTECH(ch,addv_ker_ft) addv_p = bli_cntx_get_l1v_ker_dt( dt, BLIS_ADDV_KER, cntx ); \ \ addv_p \ ( \ conjx, \ n, \ x, incx, \ y, incy, \ cntx \ ); \ return; \ } \ \ ctype* restrict chi1 = x; \ ctype* restrict psi1 = y; \ \ if ( bli_is_conj( conjx ) ) \ { \ if ( incx == 1 && incy == 1 ) \ { \ PRAGMA_SIMD \ for ( dim_t i = 0; i < n; ++i ) \ { \ /*PASTEMAC(ch,axpyjs)( *alpha, chi1[i], psi1[i] );*/ \ psi1[i] = fma( *alpha, chi1[i], psi1[i] ); \ } \ } \ else \ { \ for ( dim_t i = 0; i < n; ++i ) \ { \ PASTEMAC(ch,axpyjs)( *alpha, *chi1, *psi1 ); \ \ chi1 += incx; \ psi1 += incy; \ } \ } \ } \ else \ { \ if ( incx == 1 && incy == 1 ) \ { \ PRAGMA_SIMD \ for ( dim_t i = 0; i < n; ++i ) \ { \ /*PASTEMAC(ch,axpys)( *alpha, chi1[i], psi1[i] );*/ \ psi1[i] = fma( *alpha, chi1[i], psi1[i] ); \ } \ } \ else \ { \ for ( dim_t i = 0; i < n; ++i ) \ { \ PASTEMAC(ch,axpys)( *alpha, *chi1, *psi1 ); \ \ chi1 += incx; \ psi1 += incy; \ } \ } \ } \ } //INSERT_GENTFUNC_BASIC2( axpyv, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX ) GENTFUNC( float, s, axpyv, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX ) GENTFUNC( double, d, axpyv, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX ) #endif #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, arch, suf ) \ \ void PASTEMAC3(ch,opname,arch,suf) \ ( \ conj_t conjx, \ dim_t n, \ ctype* restrict alpha, \ ctype* restrict x, inc_t incx, \ ctype* restrict y, inc_t incy, \ cntx_t* restrict cntx \ ) \ { \ if ( bli_zero_dim1( n ) ) return; \ \ /* If alpha is zero, return. */ \ if ( PASTEMAC(ch,eq0)( *alpha ) ) return; \ \ /* If alpha is one, use addv. */ \ if ( PASTEMAC(ch,eq1)( *alpha ) ) \ { \ /* Query the context for the kernel function pointer. */ \ const num_t dt = PASTEMAC(ch,type); \ PASTECH(ch,addv_ker_ft) addv_p = bli_cntx_get_l1v_ker_dt( dt, BLIS_ADDV_KER, cntx ); \ \ addv_p \ ( \ conjx, \ n, \ x, incx, \ y, incy, \ cntx \ ); \ return; \ } \ \ if ( bli_is_conj( conjx ) ) \ { \ if ( incx == 1 && incy == 1 ) \ { \ PRAGMA_SIMD \ for ( dim_t i = 0; i < n; ++i ) \ { \ PASTEMAC(ch,axpyjs)( *alpha, x[i], y[i] ); \ } \ } \ else \ { \ for ( dim_t i = 0; i < n; ++i ) \ { \ PASTEMAC(ch,axpyjs)( *alpha, *x, *y ); \ \ x += incx; \ y += incy; \ } \ } \ } \ else \ { \ if ( incx == 1 && incy == 1 ) \ { \ PRAGMA_SIMD \ for ( dim_t i = 0; i < n; ++i ) \ { \ PASTEMAC(ch,axpys)( *alpha, x[i], y[i] ); \ } \ } \ else \ { \ for ( dim_t i = 0; i < n; ++i ) \ { \ PASTEMAC(ch,axpys)( *alpha, *x, *y ); \ \ x += incx; \ y += incy; \ } \ } \ } \ } INSERT_GENTFUNC_BASIC2( axpyv, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX ) blis-0.9.0/ref_kernels/1/bli_copyv_ref.c000066400000000000000000000053141422157504600201070ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, arch, suf ) \ \ void PASTEMAC3(ch,opname,arch,suf) \ ( \ conj_t conjx, \ dim_t n, \ ctype* restrict x, inc_t incx, \ ctype* restrict y, inc_t incy, \ cntx_t* restrict cntx \ ) \ { \ if ( bli_zero_dim1( n ) ) return; \ \ if ( bli_is_conj( conjx ) ) \ { \ if ( incx == 1 && incy == 1 ) \ { \ PRAGMA_SIMD \ for ( dim_t i = 0; i < n; ++i ) \ { \ PASTEMAC(ch,copyjs)( x[i], y[i] ); \ } \ } \ else \ { \ for ( dim_t i = 0; i < n; ++i ) \ { \ PASTEMAC(ch,copyjs)( *x, *y ); \ \ x += incx; \ y += incy; \ } \ } \ } \ else \ { \ if ( incx == 1 && incy == 1 ) \ { \ PRAGMA_SIMD \ for ( dim_t i = 0; i < n; ++i ) \ { \ PASTEMAC(ch,copys)( x[i], y[i] ); \ } \ } \ else \ { \ for ( dim_t i = 0; i < n; ++i ) \ { \ PASTEMAC(ch,copys)( *x, *y ); \ \ x += incx; \ y += incy; \ } \ } \ } \ } INSERT_GENTFUNC_BASIC2( copyv, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX ) blis-0.9.0/ref_kernels/1/bli_dotv_ref.c000066400000000000000000000063651422157504600177320ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, arch, suf ) \ \ void PASTEMAC3(ch,opname,arch,suf) \ ( \ conj_t conjx, \ conj_t conjy, \ dim_t n, \ ctype* restrict x, inc_t incx, \ ctype* restrict y, inc_t incy, \ ctype* restrict rho, \ cntx_t* restrict cntx \ ) \ { \ ctype dotxy; \ \ if ( bli_zero_dim1( n ) ) \ { \ PASTEMAC(ch,set0s)( *rho ); \ return; \ } \ \ PASTEMAC(ch,set0s)( dotxy ); \ \ conj_t conjx_use = conjx; \ \ /* If y must be conjugated, we do so indirectly by first toggling the effective conjugation of x and then conjugating the resulting dot product. */ \ if ( bli_is_conj( conjy ) ) \ bli_toggle_conj( &conjx_use ); \ \ if ( bli_is_conj( conjx_use ) ) \ { \ if ( incx == 1 && incy == 1 ) \ { \ PRAGMA_SIMD \ for ( dim_t i = 0; i < n; ++i ) \ { \ PASTEMAC(ch,dotjs)( x[i], y[i], dotxy ); \ } \ } \ else \ { \ for ( dim_t i = 0; i < n; ++i ) \ { \ PASTEMAC(ch,dotjs)( *x, *y, dotxy ); \ \ x += incx; \ y += incy; \ } \ } \ } \ else \ { \ if ( incx == 1 && incy == 1 ) \ { \ PRAGMA_SIMD \ for ( dim_t i = 0; i < n; ++i ) \ { \ PASTEMAC(ch,dots)( x[i], y[i], dotxy ); \ } \ } \ else \ { \ for ( dim_t i = 0; i < n; ++i ) \ { \ PASTEMAC(ch,dots)( *x, *y, dotxy ); \ \ x += incx; \ y += incy; \ } \ } \ } \ \ if ( bli_is_conj( conjy ) ) \ PASTEMAC(ch,conjs)( dotxy ); \ \ PASTEMAC(ch,copys)( dotxy, *rho ); \ } INSERT_GENTFUNC_BASIC2( dotv, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX ) blis-0.9.0/ref_kernels/1/bli_dotxv_ref.c000066400000000000000000000070741422157504600201200ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, arch, suf ) \ \ void PASTEMAC3(ch,opname,arch,suf) \ ( \ conj_t conjx, \ conj_t conjy, \ dim_t n, \ ctype* restrict alpha, \ ctype* restrict x, inc_t incx, \ ctype* restrict y, inc_t incy, \ ctype* restrict beta, \ ctype* restrict rho, \ cntx_t* restrict cntx \ ) \ { \ ctype dotxy; \ \ /* If beta is zero, clear rho. Otherwise, scale by beta. */ \ if ( PASTEMAC(ch,eq0)( *beta ) ) \ { \ PASTEMAC(ch,set0s)( *rho ); \ } \ else \ { \ PASTEMAC(ch,scals)( *beta, *rho ); \ } \ \ /* If the vectors are empty or if alpha is zero, return early. */ \ if ( bli_zero_dim1( n ) || PASTEMAC(ch,eq0)( *alpha ) ) return; \ \ PASTEMAC(ch,set0s)( dotxy ); \ \ /* If y must be conjugated, we do so indirectly by first toggling the effective conjugation of x and then conjugating the resulting dot product. */ \ conj_t conjx_use = conjx; \ \ if ( bli_is_conj( conjy ) ) \ bli_toggle_conj( &conjx_use ); \ \ if ( bli_is_conj( conjx_use ) ) \ { \ if ( incx == 1 && incy == 1 ) \ { \ PRAGMA_SIMD \ for ( dim_t i = 0; i < n; ++i ) \ { \ PASTEMAC(ch,dotjs)( x[i], y[i], dotxy ); \ } \ } \ else \ { \ for ( dim_t i = 0; i < n; ++i ) \ { \ PASTEMAC(ch,dotjs)( *x, *y, dotxy ); \ \ x += incx; \ y += incy; \ } \ } \ } \ else \ { \ if ( incx == 1 && incy == 1 ) \ { \ PRAGMA_SIMD \ for ( dim_t i = 0; i < n; ++i ) \ { \ PASTEMAC(ch,dots)( x[i], y[i], dotxy ); \ } \ } \ else \ { \ for ( dim_t i = 0; i < n; ++i ) \ { \ PASTEMAC(ch,dots)( *x, *y, dotxy ); \ \ x += incx; \ y += incy; \ } \ } \ } \ \ if ( bli_is_conj( conjy ) ) \ PASTEMAC(ch,conjs)( dotxy ); \ \ PASTEMAC(ch,axpys)( *alpha, dotxy, *rho ); \ } INSERT_GENTFUNC_BASIC2( dotxv, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX ) blis-0.9.0/ref_kernels/1/bli_invertv_ref.c000066400000000000000000000043511422157504600204440ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, arch, suf ) \ \ void PASTEMAC3(ch,opname,arch,suf) \ ( \ dim_t n, \ ctype* restrict x, inc_t incx, \ cntx_t* restrict cntx \ ) \ { \ if ( bli_zero_dim1( n ) ) return; \ \ if ( incx == 1 ) \ { \ PRAGMA_SIMD \ for ( dim_t i = 0; i < n; ++i ) \ { \ PASTEMAC(ch,inverts)( x[i] ); \ } \ } \ else \ { \ for ( dim_t i = 0; i < n; ++i ) \ { \ PASTEMAC(ch,inverts)( *x ); \ \ x += incx; \ } \ } \ } INSERT_GENTFUNC_BASIC2( invertv, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX ) blis-0.9.0/ref_kernels/1/bli_scal2v_ref.c000066400000000000000000000071561422157504600201470ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, arch, suf ) \ \ void PASTEMAC3(ch,opname,arch,suf) \ ( \ conj_t conjx, \ dim_t n, \ ctype* restrict alpha, \ ctype* restrict x, inc_t incx, \ ctype* restrict y, inc_t incy, \ cntx_t* restrict cntx \ ) \ { \ if ( bli_zero_dim1( n ) ) return; \ \ if ( PASTEMAC(ch,eq0)( *alpha ) ) \ { \ /* If alpha is zero, use setv. */ \ \ ctype* zero = PASTEMAC(ch,0); \ \ /* Query the context for the kernel function pointer. */ \ const num_t dt = PASTEMAC(ch,type); \ PASTECH(ch,setv_ker_ft) setv_p = bli_cntx_get_l1v_ker_dt( dt, BLIS_SETV_KER, cntx ); \ \ setv_p \ ( \ BLIS_NO_CONJUGATE, \ n, \ zero, \ y, incy, \ cntx \ ); \ return; \ } \ else if ( PASTEMAC(ch,eq0)( *alpha ) ) \ { \ /* If alpha is one, use copyv. */ \ \ /* Query the context for the kernel function pointer. */ \ const num_t dt = PASTEMAC(ch,type); \ PASTECH(ch,copyv_ker_ft) copyv_p = bli_cntx_get_l1v_ker_dt( dt, BLIS_COPYV_KER, cntx ); \ \ copyv_p \ ( \ BLIS_NO_CONJUGATE, \ n, \ x, incx, \ y, incy, \ cntx \ ); \ return; \ } \ \ if ( bli_is_conj( conjx ) ) \ { \ if ( incx == 1 && incy == 1 ) \ { \ PRAGMA_SIMD \ for ( dim_t i = 0; i < n; ++i ) \ { \ PASTEMAC(ch,scal2js)( *alpha, x[i], y[i] ); \ } \ } \ else \ { \ for ( dim_t i = 0; i < n; ++i ) \ { \ PASTEMAC(ch,scal2js)( *alpha, *x, *y ); \ \ x += incx; \ y += incy; \ } \ } \ } \ else \ { \ if ( incx == 1 && incy == 1 ) \ { \ PRAGMA_SIMD \ for ( dim_t i = 0; i < n; ++i ) \ { \ PASTEMAC(ch,scal2s)( *alpha, x[i], y[i] ); \ } \ } \ else \ { \ for ( dim_t i = 0; i < n; ++i ) \ { \ PASTEMAC(ch,scal2s)( *alpha, *x, *y ); \ \ x += incx; \ y += incy; \ } \ } \ } \ } INSERT_GENTFUNC_BASIC2( scal2v, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX ) blis-0.9.0/ref_kernels/1/bli_scalv_ref.c000066400000000000000000000056341422157504600200640ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, arch, suf ) \ \ void PASTEMAC3(ch,opname,arch,suf) \ ( \ conj_t conjalpha, \ dim_t n, \ ctype* restrict alpha, \ ctype* restrict x, inc_t incx, \ cntx_t* restrict cntx \ ) \ { \ if ( bli_zero_dim1( n ) ) return; \ \ /* If alpha is one, return. */ \ if ( PASTEMAC(ch,eq1)( *alpha ) ) return; \ \ /* If alpha is zero, use setv. */ \ if ( PASTEMAC(ch,eq0)( *alpha ) ) \ { \ ctype* zero = PASTEMAC(ch,0); \ \ /* Query the context for the kernel function pointer. */ \ const num_t dt = PASTEMAC(ch,type); \ PASTECH(ch,setv_ker_ft) setv_p = bli_cntx_get_l1v_ker_dt( dt, BLIS_SETV_KER, cntx ); \ \ setv_p \ ( \ BLIS_NO_CONJUGATE, \ n, \ zero, \ x, incx, \ cntx \ ); \ return; \ } \ \ ctype alpha_conj; \ \ PASTEMAC(ch,copycjs)( conjalpha, *alpha, alpha_conj ); \ \ if ( incx == 1 ) \ { \ PRAGMA_SIMD \ for ( dim_t i = 0; i < n; ++i ) \ { \ PASTEMAC(ch,scals)( alpha_conj, x[i] ); \ } \ } \ else \ { \ for ( dim_t i = 0; i < n; ++i ) \ { \ PASTEMAC(ch,scals)( alpha_conj, *x ); \ \ x += incx; \ } \ } \ } INSERT_GENTFUNC_BASIC2( scalv, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX ) blis-0.9.0/ref_kernels/1/bli_setv_ref.c000066400000000000000000000053501422157504600177300ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, arch, suf ) \ \ void PASTEMAC3(ch,opname,arch,suf) \ ( \ conj_t conjalpha, \ dim_t n, \ ctype* restrict alpha, \ ctype* restrict x, inc_t incx, \ cntx_t* restrict cntx \ ) \ { \ if ( bli_zero_dim1( n ) ) return; \ \ if ( PASTEMAC(ch,eq0)( *alpha ) ) \ { \ if ( incx == 1 ) \ { \ PRAGMA_SIMD \ for ( dim_t i = 0; i < n; ++i ) \ { \ PASTEMAC(ch,set0s)( x[i] ); \ } \ } \ else \ { \ for ( dim_t i = 0; i < n; ++i ) \ { \ PASTEMAC(ch,set0s)( *x ); \ \ x += incx; \ } \ } \ } \ else \ { \ ctype alpha_conj; \ \ PASTEMAC(ch,copycjs)( conjalpha, *alpha, alpha_conj ); \ \ if ( incx == 1 ) \ { \ PRAGMA_SIMD \ for ( dim_t i = 0; i < n; ++i ) \ { \ PASTEMAC(ch,copys)( alpha_conj, x[i] ); \ } \ } \ else \ { \ for ( dim_t i = 0; i < n; ++i ) \ { \ PASTEMAC(ch,copys)( alpha_conj, *x ); \ \ x += incx; \ } \ } \ } \ } INSERT_GENTFUNC_BASIC2( setv, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX ) blis-0.9.0/ref_kernels/1/bli_subv_ref.c000066400000000000000000000053071422157504600177300ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, arch, suf ) \ \ void PASTEMAC3(ch,opname,arch,suf) \ ( \ conj_t conjx, \ dim_t n, \ ctype* restrict x, inc_t incx, \ ctype* restrict y, inc_t incy, \ cntx_t* restrict cntx \ ) \ { \ if ( bli_zero_dim1( n ) ) return; \ \ if ( bli_is_conj( conjx ) ) \ { \ if ( incx == 1 && incy == 1 ) \ { \ PRAGMA_SIMD \ for ( dim_t i = 0; i < n; ++i ) \ { \ PASTEMAC(ch,subjs)( x[i], y[i] ); \ } \ } \ else \ { \ for ( dim_t i = 0; i < n; ++i ) \ { \ PASTEMAC(ch,subjs)( *x, *y ); \ \ x += incx; \ y += incy; \ } \ } \ } \ else \ { \ if ( incx == 1 && incy == 1 ) \ { \ PRAGMA_SIMD \ for ( dim_t i = 0; i < n; ++i ) \ { \ PASTEMAC(ch,subs)( x[i], y[i] ); \ } \ } \ else \ { \ for ( dim_t i = 0; i < n; ++i ) \ { \ PASTEMAC(ch,subs)( *x, *y ); \ \ x += incx; \ y += incy; \ } \ } \ } \ } INSERT_GENTFUNC_BASIC2( subv, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX ) blis-0.9.0/ref_kernels/1/bli_swapv_ref.c000066400000000000000000000044631422157504600201130ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, arch, suf ) \ \ void PASTEMAC3(ch,opname,arch,suf) \ ( \ dim_t n, \ ctype* restrict x, inc_t incx, \ ctype* restrict y, inc_t incy, \ cntx_t* restrict cntx \ ) \ { \ if ( bli_zero_dim1( n ) ) return; \ \ if ( incx == 1 && incy == 1 ) \ { \ PRAGMA_SIMD \ for ( dim_t i = 0; i < n; ++i ) \ { \ PASTEMAC(ch,swaps)( x[i], y[i] ); \ } \ } \ else \ { \ for ( dim_t i = 0; i < n; ++i ) \ { \ PASTEMAC(ch,swaps)( *x, *y ); \ \ x += incx; \ y += incy; \ } \ } \ } INSERT_GENTFUNC_BASIC2( swapv, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX ) blis-0.9.0/ref_kernels/1/bli_xpbyv_ref.c000066400000000000000000000070421422157504600201170ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, arch, suf ) \ \ void PASTEMAC3(ch,opname,arch,suf) \ ( \ conj_t conjx, \ dim_t n, \ ctype* restrict x, inc_t incx, \ ctype* restrict beta, \ ctype* restrict y, inc_t incy, \ cntx_t* restrict cntx \ ) \ { \ if ( bli_zero_dim1( n ) ) return; \ \ /* If beta is zero, use copyv. */ \ if ( PASTEMAC(ch,eq0)( *beta ) ) \ { \ /* Query the context for the kernel function pointer. */ \ const num_t dt = PASTEMAC(ch,type); \ PASTECH(ch,copyv_ker_ft) copyv_p = bli_cntx_get_l1v_ker_dt( dt, BLIS_COPYV_KER, cntx ); \ \ copyv_p \ ( \ conjx, \ n, \ x, incx, \ y, incy, \ cntx \ ); \ return; \ } \ /* If alpha is one, use addv. */ \ else if ( PASTEMAC(ch,eq1)( *beta ) ) \ { \ /* Query the context for the kernel function pointer. */ \ const num_t dt = PASTEMAC(ch,type); \ PASTECH(ch,addv_ker_ft) addv_p = bli_cntx_get_l1v_ker_dt( dt, BLIS_ADDV_KER, cntx ); \ \ addv_p \ ( \ conjx, \ n, \ x, incx, \ y, incy, \ cntx \ ); \ return; \ } \ \ if ( bli_is_conj( conjx ) ) \ { \ if ( incx == 1 && incy == 1 ) \ { \ PRAGMA_SIMD \ for ( dim_t i = 0; i < n; ++i ) \ { \ PASTEMAC(ch,xpbyjs)( x[i], *beta, y[i] ); \ } \ } \ else \ { \ for ( dim_t i = 0; i < n; ++i ) \ { \ PASTEMAC(ch,xpbyjs)( *x, *beta, *y ); \ \ x += incx; \ y += incy; \ } \ } \ } \ else \ { \ if ( incx == 1 && incy == 1 ) \ { \ PRAGMA_SIMD \ for ( dim_t i = 0; i < n; ++i ) \ { \ PASTEMAC(ch,xpbys)( x[i], *beta, y[i] ); \ } \ } \ else \ { \ for ( dim_t i = 0; i < n; ++i ) \ { \ PASTEMAC(ch,xpbys)( *x, *beta, *y ); \ \ x += incx; \ y += incy; \ } \ } \ } \ } INSERT_GENTFUNC_BASIC2( xpbyv, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX ) blis-0.9.0/ref_kernels/1f/000077500000000000000000000000001422157504600152645ustar00rootroot00000000000000blis-0.9.0/ref_kernels/1f/bli_axpy2v_ref.c000066400000000000000000000075511422157504600203530ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, arch, suf ) \ \ void PASTEMAC3(ch,opname,arch,suf) \ ( \ conj_t conjx, \ conj_t conjy, \ dim_t n, \ ctype* restrict alphax, \ ctype* restrict alphay, \ ctype* restrict x, inc_t incx, \ ctype* restrict y, inc_t incy, \ ctype* restrict z, inc_t incz, \ cntx_t* restrict cntx \ ) \ { \ if ( bli_zero_dim1( n ) ) return; \ \ if ( incz == 1 && incx == 1 && incy == 1 ) \ { \ ctype chic, psic; \ \ if ( bli_is_noconj( conjx ) ) \ { \ if ( bli_is_noconj( conjy ) ) \ { \ PRAGMA_SIMD \ for ( dim_t i = 0; i < n; ++i ) \ { \ PASTEMAC(ch,axpys)( *alphax, x[i], z[i] ); \ PASTEMAC(ch,axpys)( *alphay, y[i], z[i] ); \ } \ } \ else /* if ( bli_is_conj( conjy ) ) */ \ { \ PRAGMA_SIMD \ for ( dim_t i = 0; i < n; ++i ) \ { \ PASTEMAC(ch,axpys)( *alphax, x[i], z[i] ); \ PASTEMAC(ch,copyjs)( y[i], psic ); \ PASTEMAC(ch,axpys)( *alphay, psic, z[i] ); \ } \ } \ } \ else /* if ( bli_is_conj( conjx ) ) */ \ { \ if ( bli_is_noconj( conjy ) ) \ { \ PRAGMA_SIMD \ for ( dim_t i = 0; i < n; ++i ) \ { \ PASTEMAC(ch,copyjs)( x[i], chic ); \ PASTEMAC(ch,axpys)( *alphax, chic, z[i] ); \ PASTEMAC(ch,axpys)( *alphay, y[i], z[i] ); \ } \ } \ else /* if ( bli_is_conj( conjy ) ) */ \ { \ PRAGMA_SIMD \ for ( dim_t i = 0; i < n; ++i ) \ { \ PASTEMAC(ch,copyjs)( x[i], chic ); \ PASTEMAC(ch,axpys)( *alphax, chic, z[i] ); \ PASTEMAC(ch,copyjs)( y[i], psic ); \ PASTEMAC(ch,axpys)( *alphay, psic, z[i] ); \ } \ } \ } \ } \ else \ { \ /* Query the context for the kernel function pointer. */ \ const num_t dt = PASTEMAC(ch,type); \ PASTECH(ch,axpyv_ker_ft) kfp_av \ = \ bli_cntx_get_l1v_ker_dt( dt, BLIS_AXPYV_KER, cntx ); \ \ kfp_av \ ( \ conjx, \ n, \ alphax, \ x, incx, \ z, incz, \ cntx \ ); \ \ kfp_av \ ( \ conjy, \ n, \ alphay, \ y, incy, \ z, incz, \ cntx \ ); \ } \ } INSERT_GENTFUNC_BASIC2( axpy2v, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX ) blis-0.9.0/ref_kernels/1f/bli_axpyf_ref.c000066400000000000000000000077701422157504600202540ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, arch, suf, ff ) \ \ void PASTEMAC3(ch,opname,arch,suf) \ ( \ conj_t conja, \ conj_t conjx, \ dim_t m, \ dim_t b_n, \ ctype* restrict alpha, \ ctype* restrict a, inc_t inca, inc_t lda, \ ctype* restrict x, inc_t incx, \ ctype* restrict y, inc_t incy, \ cntx_t* restrict cntx \ ) \ { \ if ( bli_zero_dim1( m ) ) return; \ \ if ( inca == 1 && incx == 1 && incy == 1 && b_n == ff ) \ { \ ctype ax[ ff ]; \ \ /* Scale x by alpha, storing to a temporary array ax. */ \ if ( bli_is_conj( conjx ) ) \ { \ PRAGMA_SIMD \ for ( dim_t j = 0; j < ff; ++j ) \ PASTEMAC(ch,scal2js)( *alpha, x[j], ax[j] ); \ } \ else \ { \ PRAGMA_SIMD \ for ( dim_t j = 0; j < ff; ++j ) \ PASTEMAC(ch,scal2s)( *alpha, x[j], ax[j] ); \ } \ \ /* Accumulate ff separate axpyv's into y. */ \ if ( bli_is_noconj( conja ) ) \ { \ PRAGMA_SIMD \ for ( dim_t i = 0; i < m; ++i ) \ for ( dim_t j = 0; j < ff; ++j ) \ { \ PASTEMAC(ch,axpys)( ax[j], a[i + j*lda], y[i] ); \ } \ } \ else \ { \ PRAGMA_SIMD \ for ( dim_t i = 0; i < m; ++i ) \ for ( dim_t j = 0; j < ff; ++j ) \ { \ PASTEMAC(ch,axpyjs)( ax[j], a[i + j*lda], y[i] ); \ } \ } \ } \ else \ { \ /* Query the context for the kernel function pointer. */ \ const num_t dt = PASTEMAC(ch,type); \ PASTECH(ch,axpyv_ker_ft) kfp_av \ = \ bli_cntx_get_l1v_ker_dt( dt, BLIS_AXPYV_KER, cntx ); \ \ for ( dim_t i = 0; i < b_n; ++i ) \ { \ ctype* restrict a1 = a + (0 )*inca + (i )*lda; \ ctype* restrict chi1 = x + (i )*incx; \ ctype* restrict y1 = y + (0 )*incy; \ \ ctype alpha_chi1; \ \ PASTEMAC(ch,copycjs)( conjx, *chi1, alpha_chi1 ); \ PASTEMAC(ch,scals)( *alpha, alpha_chi1 ); \ \ kfp_av \ ( \ conja, \ m, \ &alpha_chi1, \ a1, inca, \ y1, incy, \ cntx \ ); \ } \ } \ } //INSERT_GENTFUNC_BASIC2( axpyf, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX ) GENTFUNC( float, s, axpyf, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX, 8 ) GENTFUNC( double, d, axpyf, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX, 8 ) GENTFUNC( scomplex, c, axpyf, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX, 8 ) GENTFUNC( dcomplex, z, axpyf, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX, 8 ) blis-0.9.0/ref_kernels/1f/bli_dotaxpyv_ref.c000066400000000000000000000105261422157504600207740ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, arch, suf ) \ \ void PASTEMAC3(ch,opname,arch,suf) \ ( \ conj_t conjxt, \ conj_t conjx, \ conj_t conjy, \ dim_t m, \ ctype* restrict alpha, \ ctype* restrict x, inc_t incx, \ ctype* restrict y, inc_t incy, \ ctype* restrict rho, \ ctype* restrict z, inc_t incz, \ cntx_t* restrict cntx \ ) \ { \ if ( bli_zero_dim1( m ) ) return; \ \ if ( incz == 1 && incx == 1 && incy == 1 ) \ { \ if ( bli_is_noconj( conjx ) ) \ { \ conj_t conjxt_use = conjxt; \ ctype dotxy; \ \ PASTEMAC(ch,set0s)( dotxy ); \ \ if ( bli_is_conj( conjy ) ) \ bli_toggle_conj( &conjxt_use ); \ \ if ( bli_is_noconj( conjxt_use ) ) \ { \ PRAGMA_SIMD \ for ( dim_t i = 0; i < m; ++i ) \ { \ PASTEMAC(ch,dots)( x[i], y[i], dotxy ); \ PASTEMAC(ch,axpys)( *alpha, x[i], z[i] ); \ } \ } \ else /* bli_is_conj( conjxt_use ) ) */ \ { \ PRAGMA_SIMD \ for ( dim_t i = 0; i < m; ++i ) \ { \ PASTEMAC(ch,dotjs)( x[i], y[i], dotxy ); \ PASTEMAC(ch,axpys)( *alpha, x[i], z[i] ); \ } \ } \ \ if ( bli_is_conj( conjy ) ) \ PASTEMAC(ch,conjs)( dotxy ); \ \ PASTEMAC(ch,copys)( dotxy, *rho ); \ } \ else /* bli_is_conj( conjx ) ) */ \ { \ conj_t conjxt_use = conjxt; \ ctype dotxy; \ \ PASTEMAC(ch,set0s)( dotxy ); \ \ if ( bli_is_conj( conjy ) ) \ bli_toggle_conj( &conjxt_use ); \ \ if ( bli_is_noconj( conjxt_use ) ) \ { \ PRAGMA_SIMD \ for ( dim_t i = 0; i < m; ++i ) \ { \ PASTEMAC(ch,dots)( x[i], y[i], dotxy ); \ PASTEMAC(ch,axpyjs)( *alpha, x[i], z[i] ); \ } \ } \ else /* bli_is_conj( conjxt_use ) ) */ \ { \ PRAGMA_SIMD \ for ( dim_t i = 0; i < m; ++i ) \ { \ PASTEMAC(ch,dotjs)( x[i], y[i], dotxy ); \ PASTEMAC(ch,axpyjs)( *alpha, x[i], z[i] ); \ } \ } \ \ if ( bli_is_conj( conjy ) ) \ PASTEMAC(ch,conjs)( dotxy ); \ \ PASTEMAC(ch,copys)( dotxy, *rho ); \ } \ } \ else \ { \ \ /* Query the context for the kernel function pointer. */ \ const num_t dt = PASTEMAC(ch,type); \ PASTECH(ch,dotv_ker_ft) kfp_dv \ = \ bli_cntx_get_l1v_ker_dt( dt, BLIS_DOTV_KER, cntx ); \ PASTECH(ch,axpyv_ker_ft) kfp_av \ = \ bli_cntx_get_l1v_ker_dt( dt, BLIS_AXPYV_KER, cntx ); \ \ kfp_dv \ ( \ conjxt, \ conjy, \ m, \ x, incx, \ y, incy, \ rho, \ cntx \ ); \ \ kfp_av \ ( \ conjx, \ m, \ alpha, \ x, incx, \ z, incz, \ cntx \ ); \ } \ } INSERT_GENTFUNC_BASIC2( dotaxpyv, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX ) blis-0.9.0/ref_kernels/1f/bli_dotxaxpyf_ref.c000066400000000000000000000136261422157504600211500ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, arch, suf, ff ) \ \ void PASTEMAC3(ch,opname,arch,suf) \ ( \ conj_t conjat, \ conj_t conja, \ conj_t conjw, \ conj_t conjx, \ dim_t m, \ dim_t b_n, \ ctype* restrict alpha, \ ctype* restrict a, inc_t inca, inc_t lda, \ ctype* restrict w, inc_t incw, \ ctype* restrict x, inc_t incx, \ ctype* restrict beta, \ ctype* restrict y, inc_t incy, \ ctype* restrict z, inc_t incz, \ cntx_t* restrict cntx \ ) \ { \ /* A is m x n. */ \ /* y = beta * y + alpha * A^T w; */ \ /* z = z + alpha * A x; */ \ \ if ( 1 && inca == 1 && incw == 1 && incx == 1 && \ incy == 1 && incz == 1 && b_n == ff ) \ { \ ctype r[ ff ]; \ ctype ax[ ff ]; \ \ /* If beta is zero, clear y. Otherwise, scale by beta. */ \ if ( PASTEMAC(ch,eq0)( *beta ) ) \ { \ for ( dim_t i = 0; i < ff; ++i ) PASTEMAC(ch,set0s)( y[i] ); \ } \ else \ { \ for ( dim_t i = 0; i < ff; ++i ) PASTEMAC(ch,scals)( *beta, y[i] ); \ } \ \ /* If the vectors are empty or if alpha is zero, return early. */ \ if ( bli_zero_dim1( m ) || PASTEMAC(ch,eq0)( *alpha ) ) return; \ \ /* Initialize r vector to 0. */ \ for ( dim_t i = 0; i < ff; ++i ) PASTEMAC(ch,set0s)( r[i] ); \ \ /* Scale x by alpha, storing to a temporary array ax. */ \ if ( bli_is_conj( conjx ) ) \ { \ PRAGMA_SIMD \ for ( dim_t i = 0; i < ff; ++i ) \ PASTEMAC(ch,scal2js)( *alpha, x[i], ax[i] ); \ } \ else \ { \ PRAGMA_SIMD \ for ( dim_t i = 0; i < ff; ++i ) \ PASTEMAC(ch,scal2s)( *alpha, x[i], ax[i] ); \ } \ \ /* If a must be conjugated, we do so indirectly by first toggling the effective conjugation of w and then conjugating the resulting dot products. */ \ conj_t conjw_use = conjw; \ \ if ( bli_is_conj( conjat ) ) \ bli_toggle_conj( &conjw_use ); \ \ if ( bli_is_noconj( conjw_use ) ) \ { \ if ( bli_is_noconj( conja ) ) \ { \ PRAGMA_SIMD \ for ( dim_t p = 0; p < m; ++p ) \ for ( dim_t i = 0; i < ff; ++i ) \ { \ PASTEMAC(ch,axpys)( a[p + i*lda], w[p], r[i] ); \ PASTEMAC(ch,axpys)( ax[i], a[p + i*lda], z[p] ); \ } \ } \ else \ { \ PRAGMA_SIMD \ for ( dim_t p = 0; p < m; ++p ) \ for ( dim_t i = 0; i < ff; ++i ) \ { \ PASTEMAC(ch,axpys)( a[p + i*lda], w[p], r[i] ); \ PASTEMAC(ch,axpyjs)( ax[i], a[p + i*lda], z[p] ); \ } \ } \ } \ else \ { \ if ( bli_is_noconj( conja ) ) \ { \ PRAGMA_SIMD \ for ( dim_t p = 0; p < m; ++p ) \ for ( dim_t i = 0; i < ff; ++i ) \ { \ PASTEMAC(ch,axpyjs)( a[p + i*lda], w[p], r[i] ); \ PASTEMAC(ch,axpys)( ax[i], a[p + i*lda], z[p] ); \ } \ } \ else \ { \ PRAGMA_SIMD \ for ( dim_t p = 0; p < m; ++p ) \ for ( dim_t i = 0; i < ff; ++i ) \ { \ PASTEMAC(ch,axpyjs)( a[p + i*lda], w[p], r[i] ); \ PASTEMAC(ch,axpyjs)( ax[i], a[p + i*lda], z[p] ); \ } \ } \ } \ \ if ( bli_is_conj( conjat ) ) \ for ( dim_t i = 0; i < ff; ++i ) PASTEMAC(ch,conjs)( r[i] ); \ \ for ( dim_t i = 0; i < ff; ++i ) \ { \ PASTEMAC(ch,axpys)( *alpha, r[i], y[i] ); \ } \ } \ else \ { \ /* Query the context for the kernel function pointer. */ \ const num_t dt = PASTEMAC(ch,type); \ PASTECH(ch,dotxf_ker_ft) kfp_df \ = \ bli_cntx_get_l1f_ker_dt( dt, BLIS_DOTXF_KER, cntx ); \ PASTECH(ch,axpyf_ker_ft) kfp_af \ = \ bli_cntx_get_l1f_ker_dt( dt, BLIS_AXPYF_KER, cntx ); \ \ kfp_df \ ( \ conjat, \ conjw, \ m, \ b_n, \ alpha, \ a, inca, lda, \ w, incw, \ beta, \ y, incy, \ cntx \ ); \ \ kfp_af \ ( \ conja, \ conjx, \ m, \ b_n, \ alpha, \ a, inca, lda, \ x, incx, \ z, incz, \ cntx \ ); \ } \ } //INSERT_GENTFUNC_BASIC2( dotxaxpyf, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX ) GENTFUNC( float, s, dotxaxpyf, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX, 4 ) GENTFUNC( double, d, dotxaxpyf, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX, 4 ) GENTFUNC( scomplex, c, dotxaxpyf, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX, 4 ) GENTFUNC( dcomplex, z, dotxaxpyf, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX, 4 ) blis-0.9.0/ref_kernels/1f/bli_dotxf_ref.c000066400000000000000000000107461422157504600202460ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, arch, suf, ff ) \ \ void PASTEMAC3(ch,opname,arch,suf) \ ( \ conj_t conjat, \ conj_t conjx, \ dim_t m, \ dim_t b_n, \ ctype* restrict alpha, \ ctype* restrict a, inc_t inca, inc_t lda, \ ctype* restrict x, inc_t incx, \ ctype* restrict beta, \ ctype* restrict y, inc_t incy, \ cntx_t* restrict cntx \ ) \ { \ if ( inca == 1 && incx == 1 && incy == 1 && b_n == ff ) \ { \ ctype r[ ff ]; \ \ /* If beta is zero, clear y. Otherwise, scale by beta. */ \ if ( PASTEMAC(ch,eq0)( *beta ) ) \ { \ for ( dim_t i = 0; i < ff; ++i ) PASTEMAC(ch,set0s)( y[i] ); \ } \ else \ { \ for ( dim_t i = 0; i < ff; ++i ) PASTEMAC(ch,scals)( *beta, y[i] ); \ } \ \ /* If the vectors are empty or if alpha is zero, return early. */ \ if ( bli_zero_dim1( m ) || PASTEMAC(ch,eq0)( *alpha ) ) return; \ \ /* Initialize r vector to 0. */ \ for ( dim_t i = 0; i < ff; ++i ) PASTEMAC(ch,set0s)( r[i] ); \ \ /* If a must be conjugated, we do so indirectly by first toggling the effective conjugation of x and then conjugating the resulting dot products. */ \ conj_t conjx_use = conjx; \ \ if ( bli_is_conj( conjat ) ) \ bli_toggle_conj( &conjx_use ); \ \ if ( bli_is_noconj( conjx_use ) ) \ { \ PRAGMA_SIMD \ for ( dim_t p = 0; p < m; ++p ) \ for ( dim_t i = 0; i < ff; ++i ) \ { \ PASTEMAC(ch,axpys)( a[p + i*lda], x[p], r[i] ); \ } \ } \ else \ { \ PRAGMA_SIMD \ for ( dim_t p = 0; p < m; ++p ) \ for ( dim_t i = 0; i < ff; ++i ) \ { \ PASTEMAC(ch,axpyjs)( a[p + i*lda], x[p], r[i] ); \ } \ } \ \ if ( bli_is_conj( conjat ) ) \ for ( dim_t i = 0; i < ff; ++i ) PASTEMAC(ch,conjs)( r[i] ); \ \ for ( dim_t i = 0; i < ff; ++i ) \ { \ PASTEMAC(ch,axpys)( *alpha, r[i], y[i] ); \ } \ } \ else \ { \ /* Query the context for the kernel function pointer. */ \ const num_t dt = PASTEMAC(ch,type); \ PASTECH(ch,dotxv_ker_ft) kfp_dv \ = \ bli_cntx_get_l1v_ker_dt( dt, BLIS_DOTXV_KER, cntx ); \ \ for ( dim_t i = 0; i < b_n; ++i ) \ { \ ctype* restrict a1 = a + (0 )*inca + (i )*lda; \ ctype* restrict x1 = x + (0 )*incx; \ ctype* restrict psi1 = y + (i )*incy; \ \ kfp_dv \ ( \ conjat, \ conjx, \ m, \ alpha, \ a1, inca, \ x1, incx, \ beta, \ psi1, \ cntx \ ); \ } \ } \ } //INSERT_GENTFUNC_BASIC2( dotxf, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX ) GENTFUNC( float, s, dotxf, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX, 6 ) GENTFUNC( double, d, dotxf, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX, 6 ) GENTFUNC( scomplex, c, dotxf, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX, 6 ) GENTFUNC( dcomplex, z, dotxf, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX, 6 ) blis-0.9.0/ref_kernels/1f/other/000077500000000000000000000000001422157504600164055ustar00rootroot00000000000000blis-0.9.0/ref_kernels/1f/other/bli_dotxaxpyf_ref_alt.c000066400000000000000000000066771422157504600231410ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ conj_t conjat, \ conj_t conja, \ conj_t conjw, \ conj_t conjx, \ dim_t m, \ dim_t b_n, \ ctype* restrict alpha, \ ctype* restrict a, inc_t inca, inc_t lda, \ ctype* restrict w, inc_t incw, \ ctype* restrict x, inc_t incx, \ ctype* restrict beta, \ ctype* restrict y, inc_t incy, \ ctype* restrict z, inc_t incz, \ cntx_t* cntx \ ) \ { \ ctype* a1; \ ctype* chi1; \ ctype* w1; \ ctype* psi1; \ ctype* z1; \ ctype conjx_chi1; \ ctype alpha_chi1; \ dim_t i; \ \ /* Query the context for the kernel function pointer. */ \ const num_t dt = PASTEMAC(ch,type); \ PASTECH(ch,dotxv_ft) kfp_dv = bli_cntx_get_l1v_ker_dt( dt, BLIS_DOTXV_KER, cntx ); \ PASTECH(ch,axpyv_ft) kfp_av = bli_cntx_get_l1v_ker_dt( dt, BLIS_AXPYV_KER, cntx ); \ \ /* A is m x n. */ \ /* y = beta * y + alpha * A^T w; */ \ /* z = z + alpha * A x; */ \ for ( i = 0; i < b_n; ++i ) \ { \ a1 = a + (0 )*inca + (i )*lda; \ w1 = w + (0 )*incw; \ psi1 = y + (i )*incy; \ \ kfp_dv \ ( \ conjat, \ conjw, \ m, \ alpha, \ a1, inca, \ w1, incw, \ beta, \ psi1, \ cntx \ ); \ } \ \ for ( i = 0; i < b_n; ++i ) \ { \ a1 = a + (0 )*inca + (i )*lda; \ chi1 = x + (i )*incx; \ z1 = z + (0 )*incz; \ \ PASTEMAC(ch,copycjs)( conjx, *chi1, conjx_chi1 ); \ PASTEMAC(ch,scal2s)( *alpha, conjx_chi1, alpha_chi1 ); \ \ kfp_av \ ( \ conja, \ m, \ &alpha_chi1, \ a1, inca, \ z1, incz, \ cntx \ ); \ } \ } INSERT_GENTFUNC_BASIC0( dotxaxpyf_ref_var1 ) blis-0.9.0/ref_kernels/1m/000077500000000000000000000000001422157504600152735ustar00rootroot00000000000000blis-0.9.0/ref_kernels/1m/bli_packm_cxk_1er_ref.c000066400000000000000000002732721422157504600216450ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENTFUNCCO #define GENTFUNCCO( ctype, ctype_r, ch, chr, opname, mnr, arch, suf ) \ \ void PASTEMAC3(ch,opname,arch,suf) \ ( \ conj_t conja, \ pack_t schema, \ dim_t cdim, \ dim_t n, \ dim_t n_max, \ ctype* restrict kappa, \ ctype* restrict a, inc_t inca, inc_t lda, \ ctype* restrict p, inc_t ldp, \ cntx_t* restrict cntx \ ) \ { \ if ( cdim == mnr ) \ { \ if ( bli_is_1e_packed( schema ) ) \ { \ const inc_t inca1 = inca; \ const inc_t lda1 = lda; \ const inc_t ldp1 = ldp; \ \ ctype* restrict kappa_cast = ( ctype* )kappa; \ ctype* restrict alpha1_ri = ( ctype* )a; \ ctype* restrict pi1_ri = ( ctype* )p; \ ctype* restrict pi1_ir = ( ctype* )p + ldp1/2; \ \ if ( PASTEMAC(ch,eq1)( *kappa_cast ) ) \ { \ if ( bli_is_conj( conja ) ) \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,copyj1es)( *(alpha1_ri + 0*inca1), *(pi1_ri + 0), *(pi1_ir + 0) ); \ PASTEMAC(ch,copyj1es)( *(alpha1_ri + 1*inca1), *(pi1_ri + 1), *(pi1_ir + 1) ); \ \ alpha1_ri += lda1; \ pi1_ri += ldp1; \ pi1_ir += ldp1; \ } \ } \ else \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,copy1es)( *(alpha1_ri + 0*inca1), *(pi1_ri + 0), *(pi1_ir + 0) ); \ PASTEMAC(ch,copy1es)( *(alpha1_ri + 1*inca1), *(pi1_ri + 1), *(pi1_ir + 1) ); \ \ alpha1_ri += lda1; \ pi1_ri += ldp1; \ pi1_ir += ldp1; \ } \ } \ } \ else \ { \ if ( bli_is_conj( conja ) ) \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,scal2j1es)( *kappa_cast, *(alpha1_ri + 0*inca1), *(pi1_ri + 0), *(pi1_ir + 0) ); \ PASTEMAC(ch,scal2j1es)( *kappa_cast, *(alpha1_ri + 1*inca1), *(pi1_ri + 1), *(pi1_ir + 1) ); \ \ alpha1_ri += lda1; \ pi1_ri += ldp1; \ pi1_ir += ldp1; \ } \ } \ else \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,scal21es)( *kappa_cast, *(alpha1_ri + 0*inca1), *(pi1_ri + 0), *(pi1_ir + 0) ); \ PASTEMAC(ch,scal21es)( *kappa_cast, *(alpha1_ri + 1*inca1), *(pi1_ri + 1), *(pi1_ir + 1) ); \ \ alpha1_ri += lda1; \ pi1_ri += ldp1; \ pi1_ir += ldp1; \ } \ } \ } \ } \ else /* if ( bli_is_1r_packed( schema ) ) */ \ { \ const inc_t inca2 = 2 * inca; \ const inc_t lda2 = 2 * lda; \ const inc_t ldp2 = 2 * ldp; \ \ ctype* kappa_cast = kappa; \ ctype_r* restrict kappa_r = ( ctype_r* )kappa; \ ctype_r* restrict kappa_i = ( ctype_r* )kappa + 1; \ ctype_r* restrict alpha1_r = ( ctype_r* )a; \ ctype_r* restrict alpha1_i = ( ctype_r* )a + 1; \ ctype_r* restrict pi1_r = ( ctype_r* )p; \ ctype_r* restrict pi1_i = ( ctype_r* )p + ldp; \ \ if ( PASTEMAC(ch,eq1)( *kappa_cast ) ) \ { \ if ( bli_is_conj( conja ) ) \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,copyjris)( *(alpha1_r + 0*inca2), *(alpha1_i + 0*inca2), *(pi1_r + 0), *(pi1_i + 0) ); \ PASTEMAC(ch,copyjris)( *(alpha1_r + 1*inca2), *(alpha1_i + 1*inca2), *(pi1_r + 1), *(pi1_i + 1) ); \ \ alpha1_r += lda2; \ alpha1_i += lda2; \ pi1_r += ldp2; \ pi1_i += ldp2; \ } \ } \ else \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,copyris)( *(alpha1_r + 0*inca2), *(alpha1_i + 0*inca2), *(pi1_r + 0), *(pi1_i + 0) ); \ PASTEMAC(ch,copyris)( *(alpha1_r + 1*inca2), *(alpha1_i + 1*inca2), *(pi1_r + 1), *(pi1_i + 1) ); \ \ alpha1_r += lda2; \ alpha1_i += lda2; \ pi1_r += ldp2; \ pi1_i += ldp2; \ } \ } \ } \ else \ { \ if ( bli_is_conj( conja ) ) \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,scal2jris)( *kappa_r, *kappa_i, *(alpha1_r + 0*inca2), *(alpha1_i + 0*inca2), *(pi1_r + 0), *(pi1_i + 0) ); \ PASTEMAC(ch,scal2jris)( *kappa_r, *kappa_i, *(alpha1_r + 1*inca2), *(alpha1_i + 1*inca2), *(pi1_r + 1), *(pi1_i + 1) ); \ \ alpha1_r += lda2; \ alpha1_i += lda2; \ pi1_r += ldp2; \ pi1_i += ldp2; \ } \ } \ else \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,scal2ris)( *kappa_r, *kappa_i, *(alpha1_r + 0*inca2), *(alpha1_i + 0*inca2), *(pi1_r + 0), *(pi1_i + 0) ); \ PASTEMAC(ch,scal2ris)( *kappa_r, *kappa_i, *(alpha1_r + 1*inca2), *(alpha1_i + 1*inca2), *(pi1_r + 1), *(pi1_i + 1) ); \ \ alpha1_r += lda2; \ alpha1_i += lda2; \ pi1_r += ldp2; \ pi1_i += ldp2; \ } \ } \ } \ } \ } \ else /* if ( cdim < mnr ) */ \ { \ PASTEMAC(ch,scal21ms_mxn) \ ( \ schema, \ conja, \ cdim, \ n, \ kappa, \ a, inca, lda, \ p, 1, ldp, ldp \ ); \ \ /* if ( cdim < mnr ) */ \ { \ ctype* restrict zero = PASTEMAC(ch,0); \ const dim_t offm = cdim; \ const dim_t offn = 0; \ const dim_t m_edge = mnr - cdim; \ const dim_t n_edge = n_max; \ \ PASTEMAC(ch,set1ms_mxn) \ ( \ schema, \ offm, \ offn, \ m_edge, \ n_edge, \ zero, \ p, 1, ldp, ldp \ ); \ } \ } \ \ if ( n < n_max ) \ { \ ctype* restrict zero = PASTEMAC(ch,0); \ const dim_t offm = 0; \ const dim_t offn = n; \ const dim_t m_edge = mnr; \ const dim_t n_edge = n_max - n; \ \ PASTEMAC(ch,set1ms_mxn) \ ( \ schema, \ offm, \ offn, \ m_edge, \ n_edge, \ zero, \ p, 1, ldp, ldp \ ); \ } \ } INSERT_GENTFUNCCO_BASIC3( packm_2xk_1er, 2, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX ) #undef GENTFUNCCO #define GENTFUNCCO( ctype, ctype_r, ch, chr, opname, mnr, arch, suf ) \ \ void PASTEMAC3(ch,opname,arch,suf) \ ( \ conj_t conja, \ pack_t schema, \ dim_t cdim, \ dim_t n, \ dim_t n_max, \ ctype* restrict kappa, \ ctype* restrict a, inc_t inca, inc_t lda, \ ctype* restrict p, inc_t ldp, \ cntx_t* restrict cntx \ ) \ { \ if ( cdim == mnr ) \ { \ if ( bli_is_1e_packed( schema ) ) \ { \ const inc_t inca1 = inca; \ const inc_t lda1 = lda; \ const inc_t ldp1 = ldp; \ \ ctype* restrict kappa_cast = ( ctype* )kappa; \ ctype* restrict alpha1_ri = ( ctype* )a; \ ctype* restrict pi1_ri = ( ctype* )p; \ ctype* restrict pi1_ir = ( ctype* )p + ldp1/2; \ \ if ( PASTEMAC(ch,eq1)( *kappa_cast ) ) \ { \ if ( bli_is_conj( conja ) ) \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,copyj1es)( *(alpha1_ri + 0*inca1), *(pi1_ri + 0), *(pi1_ir + 0) ); \ PASTEMAC(ch,copyj1es)( *(alpha1_ri + 1*inca1), *(pi1_ri + 1), *(pi1_ir + 1) ); \ PASTEMAC(ch,copyj1es)( *(alpha1_ri + 2*inca1), *(pi1_ri + 2), *(pi1_ir + 2) ); \ PASTEMAC(ch,copyj1es)( *(alpha1_ri + 3*inca1), *(pi1_ri + 3), *(pi1_ir + 3) ); \ \ alpha1_ri += lda1; \ pi1_ri += ldp1; \ pi1_ir += ldp1; \ } \ } \ else \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,copy1es)( *(alpha1_ri + 0*inca1), *(pi1_ri + 0), *(pi1_ir + 0) ); \ PASTEMAC(ch,copy1es)( *(alpha1_ri + 1*inca1), *(pi1_ri + 1), *(pi1_ir + 1) ); \ PASTEMAC(ch,copy1es)( *(alpha1_ri + 2*inca1), *(pi1_ri + 2), *(pi1_ir + 2) ); \ PASTEMAC(ch,copy1es)( *(alpha1_ri + 3*inca1), *(pi1_ri + 3), *(pi1_ir + 3) ); \ \ alpha1_ri += lda1; \ pi1_ri += ldp1; \ pi1_ir += ldp1; \ } \ } \ } \ else \ { \ if ( bli_is_conj( conja ) ) \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,scal2j1es)( *kappa_cast, *(alpha1_ri + 0*inca1), *(pi1_ri + 0), *(pi1_ir + 0) ); \ PASTEMAC(ch,scal2j1es)( *kappa_cast, *(alpha1_ri + 1*inca1), *(pi1_ri + 1), *(pi1_ir + 1) ); \ PASTEMAC(ch,scal2j1es)( *kappa_cast, *(alpha1_ri + 2*inca1), *(pi1_ri + 2), *(pi1_ir + 2) ); \ PASTEMAC(ch,scal2j1es)( *kappa_cast, *(alpha1_ri + 3*inca1), *(pi1_ri + 3), *(pi1_ir + 3) ); \ \ alpha1_ri += lda1; \ pi1_ri += ldp1; \ pi1_ir += ldp1; \ } \ } \ else \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,scal21es)( *kappa_cast, *(alpha1_ri + 0*inca1), *(pi1_ri + 0), *(pi1_ir + 0) ); \ PASTEMAC(ch,scal21es)( *kappa_cast, *(alpha1_ri + 1*inca1), *(pi1_ri + 1), *(pi1_ir + 1) ); \ PASTEMAC(ch,scal21es)( *kappa_cast, *(alpha1_ri + 2*inca1), *(pi1_ri + 2), *(pi1_ir + 2) ); \ PASTEMAC(ch,scal21es)( *kappa_cast, *(alpha1_ri + 3*inca1), *(pi1_ri + 3), *(pi1_ir + 3) ); \ \ alpha1_ri += lda1; \ pi1_ri += ldp1; \ pi1_ir += ldp1; \ } \ } \ } \ } \ else /* if ( bli_is_1r_packed( schema ) ) */ \ { \ const inc_t inca2 = 2 * inca; \ const inc_t lda2 = 2 * lda; \ const inc_t ldp2 = 2 * ldp; \ \ ctype* kappa_cast = kappa; \ ctype_r* restrict kappa_r = ( ctype_r* )kappa; \ ctype_r* restrict kappa_i = ( ctype_r* )kappa + 1; \ ctype_r* restrict alpha1_r = ( ctype_r* )a; \ ctype_r* restrict alpha1_i = ( ctype_r* )a + 1; \ ctype_r* restrict pi1_r = ( ctype_r* )p; \ ctype_r* restrict pi1_i = ( ctype_r* )p + ldp; \ \ if ( PASTEMAC(ch,eq1)( *kappa_cast ) ) \ { \ if ( bli_is_conj( conja ) ) \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,copyjris)( *(alpha1_r + 0*inca2), *(alpha1_i + 0*inca2), *(pi1_r + 0), *(pi1_i + 0) ); \ PASTEMAC(ch,copyjris)( *(alpha1_r + 1*inca2), *(alpha1_i + 1*inca2), *(pi1_r + 1), *(pi1_i + 1) ); \ PASTEMAC(ch,copyjris)( *(alpha1_r + 2*inca2), *(alpha1_i + 2*inca2), *(pi1_r + 2), *(pi1_i + 2) ); \ PASTEMAC(ch,copyjris)( *(alpha1_r + 3*inca2), *(alpha1_i + 3*inca2), *(pi1_r + 3), *(pi1_i + 3) ); \ \ alpha1_r += lda2; \ alpha1_i += lda2; \ pi1_r += ldp2; \ pi1_i += ldp2; \ } \ } \ else \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,copyris)( *(alpha1_r + 0*inca2), *(alpha1_i + 0*inca2), *(pi1_r + 0), *(pi1_i + 0) ); \ PASTEMAC(ch,copyris)( *(alpha1_r + 1*inca2), *(alpha1_i + 1*inca2), *(pi1_r + 1), *(pi1_i + 1) ); \ PASTEMAC(ch,copyris)( *(alpha1_r + 2*inca2), *(alpha1_i + 2*inca2), *(pi1_r + 2), *(pi1_i + 2) ); \ PASTEMAC(ch,copyris)( *(alpha1_r + 3*inca2), *(alpha1_i + 3*inca2), *(pi1_r + 3), *(pi1_i + 3) ); \ \ alpha1_r += lda2; \ alpha1_i += lda2; \ pi1_r += ldp2; \ pi1_i += ldp2; \ } \ } \ } \ else \ { \ if ( bli_is_conj( conja ) ) \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,scal2jris)( *kappa_r, *kappa_i, *(alpha1_r + 0*inca2), *(alpha1_i + 0*inca2), *(pi1_r + 0), *(pi1_i + 0) ); \ PASTEMAC(ch,scal2jris)( *kappa_r, *kappa_i, *(alpha1_r + 1*inca2), *(alpha1_i + 1*inca2), *(pi1_r + 1), *(pi1_i + 1) ); \ PASTEMAC(ch,scal2jris)( *kappa_r, *kappa_i, *(alpha1_r + 2*inca2), *(alpha1_i + 2*inca2), *(pi1_r + 2), *(pi1_i + 2) ); \ PASTEMAC(ch,scal2jris)( *kappa_r, *kappa_i, *(alpha1_r + 3*inca2), *(alpha1_i + 3*inca2), *(pi1_r + 3), *(pi1_i + 3) ); \ \ alpha1_r += lda2; \ alpha1_i += lda2; \ pi1_r += ldp2; \ pi1_i += ldp2; \ } \ } \ else \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,scal2ris)( *kappa_r, *kappa_i, *(alpha1_r + 0*inca2), *(alpha1_i + 0*inca2), *(pi1_r + 0), *(pi1_i + 0) ); \ PASTEMAC(ch,scal2ris)( *kappa_r, *kappa_i, *(alpha1_r + 1*inca2), *(alpha1_i + 1*inca2), *(pi1_r + 1), *(pi1_i + 1) ); \ PASTEMAC(ch,scal2ris)( *kappa_r, *kappa_i, *(alpha1_r + 2*inca2), *(alpha1_i + 2*inca2), *(pi1_r + 2), *(pi1_i + 2) ); \ PASTEMAC(ch,scal2ris)( *kappa_r, *kappa_i, *(alpha1_r + 3*inca2), *(alpha1_i + 3*inca2), *(pi1_r + 3), *(pi1_i + 3) ); \ \ alpha1_r += lda2; \ alpha1_i += lda2; \ pi1_r += ldp2; \ pi1_i += ldp2; \ } \ } \ } \ } \ } \ else /* if ( cdim < mnr ) */ \ { \ PASTEMAC(ch,scal21ms_mxn) \ ( \ schema, \ conja, \ cdim, \ n, \ kappa, \ a, inca, lda, \ p, 1, ldp, ldp \ ); \ \ /* if ( cdim < mnr ) */ \ { \ ctype* restrict zero = PASTEMAC(ch,0); \ const dim_t offm = cdim; \ const dim_t offn = 0; \ const dim_t m_edge = mnr - cdim; \ const dim_t n_edge = n_max; \ \ PASTEMAC(ch,set1ms_mxn) \ ( \ schema, \ offm, \ offn, \ m_edge, \ n_edge, \ zero, \ p, 1, ldp, ldp \ ); \ } \ } \ \ if ( n < n_max ) \ { \ ctype* restrict zero = PASTEMAC(ch,0); \ const dim_t offm = 0; \ const dim_t offn = n; \ const dim_t m_edge = mnr; \ const dim_t n_edge = n_max - n; \ \ PASTEMAC(ch,set1ms_mxn) \ ( \ schema, \ offm, \ offn, \ m_edge, \ n_edge, \ zero, \ p, 1, ldp, ldp \ ); \ } \ } INSERT_GENTFUNCCO_BASIC3( packm_4xk_1er, 4, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX ) #undef GENTFUNCCO #define GENTFUNCCO( ctype, ctype_r, ch, chr, opname, mnr, arch, suf ) \ \ void PASTEMAC3(ch,opname,arch,suf) \ ( \ conj_t conja, \ pack_t schema, \ dim_t cdim, \ dim_t n, \ dim_t n_max, \ ctype* restrict kappa, \ ctype* restrict a, inc_t inca, inc_t lda, \ ctype* restrict p, inc_t ldp, \ cntx_t* restrict cntx \ ) \ { \ if ( cdim == mnr ) \ { \ if ( bli_is_1e_packed( schema ) ) \ { \ const inc_t inca1 = inca; \ const inc_t lda1 = lda; \ const inc_t ldp1 = ldp; \ \ ctype* restrict kappa_cast = ( ctype* )kappa; \ ctype* restrict alpha1_ri = ( ctype* )a; \ ctype* restrict pi1_ri = ( ctype* )p; \ ctype* restrict pi1_ir = ( ctype* )p + ldp1/2; \ \ if ( PASTEMAC(ch,eq1)( *kappa_cast ) ) \ { \ if ( bli_is_conj( conja ) ) \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,copyj1es)( *(alpha1_ri + 0*inca1), *(pi1_ri + 0), *(pi1_ir + 0) ); \ PASTEMAC(ch,copyj1es)( *(alpha1_ri + 1*inca1), *(pi1_ri + 1), *(pi1_ir + 1) ); \ PASTEMAC(ch,copyj1es)( *(alpha1_ri + 2*inca1), *(pi1_ri + 2), *(pi1_ir + 2) ); \ PASTEMAC(ch,copyj1es)( *(alpha1_ri + 3*inca1), *(pi1_ri + 3), *(pi1_ir + 3) ); \ PASTEMAC(ch,copyj1es)( *(alpha1_ri + 4*inca1), *(pi1_ri + 4), *(pi1_ir + 4) ); \ PASTEMAC(ch,copyj1es)( *(alpha1_ri + 5*inca1), *(pi1_ri + 5), *(pi1_ir + 5) ); \ \ alpha1_ri += lda1; \ pi1_ri += ldp1; \ pi1_ir += ldp1; \ } \ } \ else \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,copy1es)( *(alpha1_ri + 0*inca1), *(pi1_ri + 0), *(pi1_ir + 0) ); \ PASTEMAC(ch,copy1es)( *(alpha1_ri + 1*inca1), *(pi1_ri + 1), *(pi1_ir + 1) ); \ PASTEMAC(ch,copy1es)( *(alpha1_ri + 2*inca1), *(pi1_ri + 2), *(pi1_ir + 2) ); \ PASTEMAC(ch,copy1es)( *(alpha1_ri + 3*inca1), *(pi1_ri + 3), *(pi1_ir + 3) ); \ PASTEMAC(ch,copy1es)( *(alpha1_ri + 4*inca1), *(pi1_ri + 4), *(pi1_ir + 4) ); \ PASTEMAC(ch,copy1es)( *(alpha1_ri + 5*inca1), *(pi1_ri + 5), *(pi1_ir + 5) ); \ \ alpha1_ri += lda1; \ pi1_ri += ldp1; \ pi1_ir += ldp1; \ } \ } \ } \ else \ { \ if ( bli_is_conj( conja ) ) \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,scal2j1es)( *kappa_cast, *(alpha1_ri + 0*inca1), *(pi1_ri + 0), *(pi1_ir + 0) ); \ PASTEMAC(ch,scal2j1es)( *kappa_cast, *(alpha1_ri + 1*inca1), *(pi1_ri + 1), *(pi1_ir + 1) ); \ PASTEMAC(ch,scal2j1es)( *kappa_cast, *(alpha1_ri + 2*inca1), *(pi1_ri + 2), *(pi1_ir + 2) ); \ PASTEMAC(ch,scal2j1es)( *kappa_cast, *(alpha1_ri + 3*inca1), *(pi1_ri + 3), *(pi1_ir + 3) ); \ PASTEMAC(ch,scal2j1es)( *kappa_cast, *(alpha1_ri + 4*inca1), *(pi1_ri + 4), *(pi1_ir + 4) ); \ PASTEMAC(ch,scal2j1es)( *kappa_cast, *(alpha1_ri + 5*inca1), *(pi1_ri + 5), *(pi1_ir + 5) ); \ \ alpha1_ri += lda1; \ pi1_ri += ldp1; \ pi1_ir += ldp1; \ } \ } \ else \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,scal21es)( *kappa_cast, *(alpha1_ri + 0*inca1), *(pi1_ri + 0), *(pi1_ir + 0) ); \ PASTEMAC(ch,scal21es)( *kappa_cast, *(alpha1_ri + 1*inca1), *(pi1_ri + 1), *(pi1_ir + 1) ); \ PASTEMAC(ch,scal21es)( *kappa_cast, *(alpha1_ri + 2*inca1), *(pi1_ri + 2), *(pi1_ir + 2) ); \ PASTEMAC(ch,scal21es)( *kappa_cast, *(alpha1_ri + 3*inca1), *(pi1_ri + 3), *(pi1_ir + 3) ); \ PASTEMAC(ch,scal21es)( *kappa_cast, *(alpha1_ri + 4*inca1), *(pi1_ri + 4), *(pi1_ir + 4) ); \ PASTEMAC(ch,scal21es)( *kappa_cast, *(alpha1_ri + 5*inca1), *(pi1_ri + 5), *(pi1_ir + 5) ); \ \ alpha1_ri += lda1; \ pi1_ri += ldp1; \ pi1_ir += ldp1; \ } \ } \ } \ } \ else /* if ( bli_is_1r_packed( schema ) ) */ \ { \ const inc_t inca2 = 2 * inca; \ const inc_t lda2 = 2 * lda; \ const inc_t ldp2 = 2 * ldp; \ \ ctype* kappa_cast = kappa; \ ctype_r* restrict kappa_r = ( ctype_r* )kappa; \ ctype_r* restrict kappa_i = ( ctype_r* )kappa + 1; \ ctype_r* restrict alpha1_r = ( ctype_r* )a; \ ctype_r* restrict alpha1_i = ( ctype_r* )a + 1; \ ctype_r* restrict pi1_r = ( ctype_r* )p; \ ctype_r* restrict pi1_i = ( ctype_r* )p + ldp; \ \ if ( PASTEMAC(ch,eq1)( *kappa_cast ) ) \ { \ if ( bli_is_conj( conja ) ) \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,copyjris)( *(alpha1_r + 0*inca2), *(alpha1_i + 0*inca2), *(pi1_r + 0), *(pi1_i + 0) ); \ PASTEMAC(ch,copyjris)( *(alpha1_r + 1*inca2), *(alpha1_i + 1*inca2), *(pi1_r + 1), *(pi1_i + 1) ); \ PASTEMAC(ch,copyjris)( *(alpha1_r + 2*inca2), *(alpha1_i + 2*inca2), *(pi1_r + 2), *(pi1_i + 2) ); \ PASTEMAC(ch,copyjris)( *(alpha1_r + 3*inca2), *(alpha1_i + 3*inca2), *(pi1_r + 3), *(pi1_i + 3) ); \ PASTEMAC(ch,copyjris)( *(alpha1_r + 4*inca2), *(alpha1_i + 4*inca2), *(pi1_r + 4), *(pi1_i + 4) ); \ PASTEMAC(ch,copyjris)( *(alpha1_r + 5*inca2), *(alpha1_i + 5*inca2), *(pi1_r + 5), *(pi1_i + 5) ); \ \ alpha1_r += lda2; \ alpha1_i += lda2; \ pi1_r += ldp2; \ pi1_i += ldp2; \ } \ } \ else \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,copyris)( *(alpha1_r + 0*inca2), *(alpha1_i + 0*inca2), *(pi1_r + 0), *(pi1_i + 0) ); \ PASTEMAC(ch,copyris)( *(alpha1_r + 1*inca2), *(alpha1_i + 1*inca2), *(pi1_r + 1), *(pi1_i + 1) ); \ PASTEMAC(ch,copyris)( *(alpha1_r + 2*inca2), *(alpha1_i + 2*inca2), *(pi1_r + 2), *(pi1_i + 2) ); \ PASTEMAC(ch,copyris)( *(alpha1_r + 3*inca2), *(alpha1_i + 3*inca2), *(pi1_r + 3), *(pi1_i + 3) ); \ PASTEMAC(ch,copyris)( *(alpha1_r + 4*inca2), *(alpha1_i + 4*inca2), *(pi1_r + 4), *(pi1_i + 4) ); \ PASTEMAC(ch,copyris)( *(alpha1_r + 5*inca2), *(alpha1_i + 5*inca2), *(pi1_r + 5), *(pi1_i + 5) ); \ \ alpha1_r += lda2; \ alpha1_i += lda2; \ pi1_r += ldp2; \ pi1_i += ldp2; \ } \ } \ } \ else \ { \ if ( bli_is_conj( conja ) ) \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,scal2jris)( *kappa_r, *kappa_i, *(alpha1_r + 0*inca2), *(alpha1_i + 0*inca2), *(pi1_r + 0), *(pi1_i + 0) ); \ PASTEMAC(ch,scal2jris)( *kappa_r, *kappa_i, *(alpha1_r + 1*inca2), *(alpha1_i + 1*inca2), *(pi1_r + 1), *(pi1_i + 1) ); \ PASTEMAC(ch,scal2jris)( *kappa_r, *kappa_i, *(alpha1_r + 2*inca2), *(alpha1_i + 2*inca2), *(pi1_r + 2), *(pi1_i + 2) ); \ PASTEMAC(ch,scal2jris)( *kappa_r, *kappa_i, *(alpha1_r + 3*inca2), *(alpha1_i + 3*inca2), *(pi1_r + 3), *(pi1_i + 3) ); \ PASTEMAC(ch,scal2jris)( *kappa_r, *kappa_i, *(alpha1_r + 4*inca2), *(alpha1_i + 4*inca2), *(pi1_r + 4), *(pi1_i + 4) ); \ PASTEMAC(ch,scal2jris)( *kappa_r, *kappa_i, *(alpha1_r + 5*inca2), *(alpha1_i + 5*inca2), *(pi1_r + 5), *(pi1_i + 5) ); \ \ alpha1_r += lda2; \ alpha1_i += lda2; \ pi1_r += ldp2; \ pi1_i += ldp2; \ } \ } \ else \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,scal2ris)( *kappa_r, *kappa_i, *(alpha1_r + 0*inca2), *(alpha1_i + 0*inca2), *(pi1_r + 0), *(pi1_i + 0) ); \ PASTEMAC(ch,scal2ris)( *kappa_r, *kappa_i, *(alpha1_r + 1*inca2), *(alpha1_i + 1*inca2), *(pi1_r + 1), *(pi1_i + 1) ); \ PASTEMAC(ch,scal2ris)( *kappa_r, *kappa_i, *(alpha1_r + 2*inca2), *(alpha1_i + 2*inca2), *(pi1_r + 2), *(pi1_i + 2) ); \ PASTEMAC(ch,scal2ris)( *kappa_r, *kappa_i, *(alpha1_r + 3*inca2), *(alpha1_i + 3*inca2), *(pi1_r + 3), *(pi1_i + 3) ); \ PASTEMAC(ch,scal2ris)( *kappa_r, *kappa_i, *(alpha1_r + 4*inca2), *(alpha1_i + 4*inca2), *(pi1_r + 4), *(pi1_i + 4) ); \ PASTEMAC(ch,scal2ris)( *kappa_r, *kappa_i, *(alpha1_r + 5*inca2), *(alpha1_i + 5*inca2), *(pi1_r + 5), *(pi1_i + 5) ); \ \ alpha1_r += lda2; \ alpha1_i += lda2; \ pi1_r += ldp2; \ pi1_i += ldp2; \ } \ } \ } \ } \ } \ else /* if ( cdim < mnr ) */ \ { \ PASTEMAC(ch,scal21ms_mxn) \ ( \ schema, \ conja, \ cdim, \ n, \ kappa, \ a, inca, lda, \ p, 1, ldp, ldp \ ); \ \ /* if ( cdim < mnr ) */ \ { \ ctype* restrict zero = PASTEMAC(ch,0); \ const dim_t offm = cdim; \ const dim_t offn = 0; \ const dim_t m_edge = mnr - cdim; \ const dim_t n_edge = n_max; \ \ PASTEMAC(ch,set1ms_mxn) \ ( \ schema, \ offm, \ offn, \ m_edge, \ n_edge, \ zero, \ p, 1, ldp, ldp \ ); \ } \ } \ \ if ( n < n_max ) \ { \ ctype* restrict zero = PASTEMAC(ch,0); \ const dim_t offm = 0; \ const dim_t offn = n; \ const dim_t m_edge = mnr; \ const dim_t n_edge = n_max - n; \ \ PASTEMAC(ch,set1ms_mxn) \ ( \ schema, \ offm, \ offn, \ m_edge, \ n_edge, \ zero, \ p, 1, ldp, ldp \ ); \ } \ } INSERT_GENTFUNCCO_BASIC3( packm_6xk_1er, 6, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX ) #undef GENTFUNCCO #define GENTFUNCCO( ctype, ctype_r, ch, chr, opname, mnr, arch, suf ) \ \ void PASTEMAC3(ch,opname,arch,suf) \ ( \ conj_t conja, \ pack_t schema, \ dim_t cdim, \ dim_t n, \ dim_t n_max, \ ctype* restrict kappa, \ ctype* restrict a, inc_t inca, inc_t lda, \ ctype* restrict p, inc_t ldp, \ cntx_t* restrict cntx \ ) \ { \ if ( cdim == mnr ) \ { \ if ( bli_is_1e_packed( schema ) ) \ { \ const inc_t inca1 = inca; \ const inc_t lda1 = lda; \ const inc_t ldp1 = ldp; \ \ ctype* restrict kappa_cast = ( ctype* )kappa; \ ctype* restrict alpha1_ri = ( ctype* )a; \ ctype* restrict pi1_ri = ( ctype* )p; \ ctype* restrict pi1_ir = ( ctype* )p + ldp1/2; \ \ if ( PASTEMAC(ch,eq1)( *kappa_cast ) ) \ { \ if ( bli_is_conj( conja ) ) \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,copyj1es)( *(alpha1_ri + 0*inca1), *(pi1_ri + 0), *(pi1_ir + 0) ); \ PASTEMAC(ch,copyj1es)( *(alpha1_ri + 1*inca1), *(pi1_ri + 1), *(pi1_ir + 1) ); \ PASTEMAC(ch,copyj1es)( *(alpha1_ri + 2*inca1), *(pi1_ri + 2), *(pi1_ir + 2) ); \ PASTEMAC(ch,copyj1es)( *(alpha1_ri + 3*inca1), *(pi1_ri + 3), *(pi1_ir + 3) ); \ PASTEMAC(ch,copyj1es)( *(alpha1_ri + 4*inca1), *(pi1_ri + 4), *(pi1_ir + 4) ); \ PASTEMAC(ch,copyj1es)( *(alpha1_ri + 5*inca1), *(pi1_ri + 5), *(pi1_ir + 5) ); \ PASTEMAC(ch,copyj1es)( *(alpha1_ri + 6*inca1), *(pi1_ri + 6), *(pi1_ir + 6) ); \ PASTEMAC(ch,copyj1es)( *(alpha1_ri + 7*inca1), *(pi1_ri + 7), *(pi1_ir + 7) ); \ \ alpha1_ri += lda1; \ pi1_ri += ldp1; \ pi1_ir += ldp1; \ } \ } \ else \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,copy1es)( *(alpha1_ri + 0*inca1), *(pi1_ri + 0), *(pi1_ir + 0) ); \ PASTEMAC(ch,copy1es)( *(alpha1_ri + 1*inca1), *(pi1_ri + 1), *(pi1_ir + 1) ); \ PASTEMAC(ch,copy1es)( *(alpha1_ri + 2*inca1), *(pi1_ri + 2), *(pi1_ir + 2) ); \ PASTEMAC(ch,copy1es)( *(alpha1_ri + 3*inca1), *(pi1_ri + 3), *(pi1_ir + 3) ); \ PASTEMAC(ch,copy1es)( *(alpha1_ri + 4*inca1), *(pi1_ri + 4), *(pi1_ir + 4) ); \ PASTEMAC(ch,copy1es)( *(alpha1_ri + 5*inca1), *(pi1_ri + 5), *(pi1_ir + 5) ); \ PASTEMAC(ch,copy1es)( *(alpha1_ri + 6*inca1), *(pi1_ri + 6), *(pi1_ir + 6) ); \ PASTEMAC(ch,copy1es)( *(alpha1_ri + 7*inca1), *(pi1_ri + 7), *(pi1_ir + 7) ); \ \ alpha1_ri += lda1; \ pi1_ri += ldp1; \ pi1_ir += ldp1; \ } \ } \ } \ else \ { \ if ( bli_is_conj( conja ) ) \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,scal2j1es)( *kappa_cast, *(alpha1_ri + 0*inca1), *(pi1_ri + 0), *(pi1_ir + 0) ); \ PASTEMAC(ch,scal2j1es)( *kappa_cast, *(alpha1_ri + 1*inca1), *(pi1_ri + 1), *(pi1_ir + 1) ); \ PASTEMAC(ch,scal2j1es)( *kappa_cast, *(alpha1_ri + 2*inca1), *(pi1_ri + 2), *(pi1_ir + 2) ); \ PASTEMAC(ch,scal2j1es)( *kappa_cast, *(alpha1_ri + 3*inca1), *(pi1_ri + 3), *(pi1_ir + 3) ); \ PASTEMAC(ch,scal2j1es)( *kappa_cast, *(alpha1_ri + 4*inca1), *(pi1_ri + 4), *(pi1_ir + 4) ); \ PASTEMAC(ch,scal2j1es)( *kappa_cast, *(alpha1_ri + 5*inca1), *(pi1_ri + 5), *(pi1_ir + 5) ); \ PASTEMAC(ch,scal2j1es)( *kappa_cast, *(alpha1_ri + 6*inca1), *(pi1_ri + 6), *(pi1_ir + 6) ); \ PASTEMAC(ch,scal2j1es)( *kappa_cast, *(alpha1_ri + 7*inca1), *(pi1_ri + 7), *(pi1_ir + 7) ); \ \ alpha1_ri += lda1; \ pi1_ri += ldp1; \ pi1_ir += ldp1; \ } \ } \ else \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,scal21es)( *kappa_cast, *(alpha1_ri + 0*inca1), *(pi1_ri + 0), *(pi1_ir + 0) ); \ PASTEMAC(ch,scal21es)( *kappa_cast, *(alpha1_ri + 1*inca1), *(pi1_ri + 1), *(pi1_ir + 1) ); \ PASTEMAC(ch,scal21es)( *kappa_cast, *(alpha1_ri + 2*inca1), *(pi1_ri + 2), *(pi1_ir + 2) ); \ PASTEMAC(ch,scal21es)( *kappa_cast, *(alpha1_ri + 3*inca1), *(pi1_ri + 3), *(pi1_ir + 3) ); \ PASTEMAC(ch,scal21es)( *kappa_cast, *(alpha1_ri + 4*inca1), *(pi1_ri + 4), *(pi1_ir + 4) ); \ PASTEMAC(ch,scal21es)( *kappa_cast, *(alpha1_ri + 5*inca1), *(pi1_ri + 5), *(pi1_ir + 5) ); \ PASTEMAC(ch,scal21es)( *kappa_cast, *(alpha1_ri + 6*inca1), *(pi1_ri + 6), *(pi1_ir + 6) ); \ PASTEMAC(ch,scal21es)( *kappa_cast, *(alpha1_ri + 7*inca1), *(pi1_ri + 7), *(pi1_ir + 7) ); \ \ alpha1_ri += lda1; \ pi1_ri += ldp1; \ pi1_ir += ldp1; \ } \ } \ } \ } \ else /* if ( bli_is_1r_packed( schema ) ) */ \ { \ const inc_t inca2 = 2 * inca; \ const inc_t lda2 = 2 * lda; \ const inc_t ldp2 = 2 * ldp; \ \ ctype* kappa_cast = kappa; \ ctype_r* restrict kappa_r = ( ctype_r* )kappa; \ ctype_r* restrict kappa_i = ( ctype_r* )kappa + 1; \ ctype_r* restrict alpha1_r = ( ctype_r* )a; \ ctype_r* restrict alpha1_i = ( ctype_r* )a + 1; \ ctype_r* restrict pi1_r = ( ctype_r* )p; \ ctype_r* restrict pi1_i = ( ctype_r* )p + ldp; \ \ if ( PASTEMAC(ch,eq1)( *kappa_cast ) ) \ { \ if ( bli_is_conj( conja ) ) \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,copyjris)( *(alpha1_r + 0*inca2), *(alpha1_i + 0*inca2), *(pi1_r + 0), *(pi1_i + 0) ); \ PASTEMAC(ch,copyjris)( *(alpha1_r + 1*inca2), *(alpha1_i + 1*inca2), *(pi1_r + 1), *(pi1_i + 1) ); \ PASTEMAC(ch,copyjris)( *(alpha1_r + 2*inca2), *(alpha1_i + 2*inca2), *(pi1_r + 2), *(pi1_i + 2) ); \ PASTEMAC(ch,copyjris)( *(alpha1_r + 3*inca2), *(alpha1_i + 3*inca2), *(pi1_r + 3), *(pi1_i + 3) ); \ PASTEMAC(ch,copyjris)( *(alpha1_r + 4*inca2), *(alpha1_i + 4*inca2), *(pi1_r + 4), *(pi1_i + 4) ); \ PASTEMAC(ch,copyjris)( *(alpha1_r + 5*inca2), *(alpha1_i + 5*inca2), *(pi1_r + 5), *(pi1_i + 5) ); \ PASTEMAC(ch,copyjris)( *(alpha1_r + 6*inca2), *(alpha1_i + 6*inca2), *(pi1_r + 6), *(pi1_i + 6) ); \ PASTEMAC(ch,copyjris)( *(alpha1_r + 7*inca2), *(alpha1_i + 7*inca2), *(pi1_r + 7), *(pi1_i + 7) ); \ \ alpha1_r += lda2; \ alpha1_i += lda2; \ pi1_r += ldp2; \ pi1_i += ldp2; \ } \ } \ else \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,copyris)( *(alpha1_r + 0*inca2), *(alpha1_i + 0*inca2), *(pi1_r + 0), *(pi1_i + 0) ); \ PASTEMAC(ch,copyris)( *(alpha1_r + 1*inca2), *(alpha1_i + 1*inca2), *(pi1_r + 1), *(pi1_i + 1) ); \ PASTEMAC(ch,copyris)( *(alpha1_r + 2*inca2), *(alpha1_i + 2*inca2), *(pi1_r + 2), *(pi1_i + 2) ); \ PASTEMAC(ch,copyris)( *(alpha1_r + 3*inca2), *(alpha1_i + 3*inca2), *(pi1_r + 3), *(pi1_i + 3) ); \ PASTEMAC(ch,copyris)( *(alpha1_r + 4*inca2), *(alpha1_i + 4*inca2), *(pi1_r + 4), *(pi1_i + 4) ); \ PASTEMAC(ch,copyris)( *(alpha1_r + 5*inca2), *(alpha1_i + 5*inca2), *(pi1_r + 5), *(pi1_i + 5) ); \ PASTEMAC(ch,copyris)( *(alpha1_r + 6*inca2), *(alpha1_i + 6*inca2), *(pi1_r + 6), *(pi1_i + 6) ); \ PASTEMAC(ch,copyris)( *(alpha1_r + 7*inca2), *(alpha1_i + 7*inca2), *(pi1_r + 7), *(pi1_i + 7) ); \ \ alpha1_r += lda2; \ alpha1_i += lda2; \ pi1_r += ldp2; \ pi1_i += ldp2; \ } \ } \ } \ else \ { \ if ( bli_is_conj( conja ) ) \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,scal2jris)( *kappa_r, *kappa_i, *(alpha1_r + 0*inca2), *(alpha1_i + 0*inca2), *(pi1_r + 0), *(pi1_i + 0) ); \ PASTEMAC(ch,scal2jris)( *kappa_r, *kappa_i, *(alpha1_r + 1*inca2), *(alpha1_i + 1*inca2), *(pi1_r + 1), *(pi1_i + 1) ); \ PASTEMAC(ch,scal2jris)( *kappa_r, *kappa_i, *(alpha1_r + 2*inca2), *(alpha1_i + 2*inca2), *(pi1_r + 2), *(pi1_i + 2) ); \ PASTEMAC(ch,scal2jris)( *kappa_r, *kappa_i, *(alpha1_r + 3*inca2), *(alpha1_i + 3*inca2), *(pi1_r + 3), *(pi1_i + 3) ); \ PASTEMAC(ch,scal2jris)( *kappa_r, *kappa_i, *(alpha1_r + 4*inca2), *(alpha1_i + 4*inca2), *(pi1_r + 4), *(pi1_i + 4) ); \ PASTEMAC(ch,scal2jris)( *kappa_r, *kappa_i, *(alpha1_r + 5*inca2), *(alpha1_i + 5*inca2), *(pi1_r + 5), *(pi1_i + 5) ); \ PASTEMAC(ch,scal2jris)( *kappa_r, *kappa_i, *(alpha1_r + 6*inca2), *(alpha1_i + 6*inca2), *(pi1_r + 6), *(pi1_i + 6) ); \ PASTEMAC(ch,scal2jris)( *kappa_r, *kappa_i, *(alpha1_r + 7*inca2), *(alpha1_i + 7*inca2), *(pi1_r + 7), *(pi1_i + 7) ); \ \ alpha1_r += lda2; \ alpha1_i += lda2; \ pi1_r += ldp2; \ pi1_i += ldp2; \ } \ } \ else \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,scal2ris)( *kappa_r, *kappa_i, *(alpha1_r + 0*inca2), *(alpha1_i + 0*inca2), *(pi1_r + 0), *(pi1_i + 0) ); \ PASTEMAC(ch,scal2ris)( *kappa_r, *kappa_i, *(alpha1_r + 1*inca2), *(alpha1_i + 1*inca2), *(pi1_r + 1), *(pi1_i + 1) ); \ PASTEMAC(ch,scal2ris)( *kappa_r, *kappa_i, *(alpha1_r + 2*inca2), *(alpha1_i + 2*inca2), *(pi1_r + 2), *(pi1_i + 2) ); \ PASTEMAC(ch,scal2ris)( *kappa_r, *kappa_i, *(alpha1_r + 3*inca2), *(alpha1_i + 3*inca2), *(pi1_r + 3), *(pi1_i + 3) ); \ PASTEMAC(ch,scal2ris)( *kappa_r, *kappa_i, *(alpha1_r + 4*inca2), *(alpha1_i + 4*inca2), *(pi1_r + 4), *(pi1_i + 4) ); \ PASTEMAC(ch,scal2ris)( *kappa_r, *kappa_i, *(alpha1_r + 5*inca2), *(alpha1_i + 5*inca2), *(pi1_r + 5), *(pi1_i + 5) ); \ PASTEMAC(ch,scal2ris)( *kappa_r, *kappa_i, *(alpha1_r + 6*inca2), *(alpha1_i + 6*inca2), *(pi1_r + 6), *(pi1_i + 6) ); \ PASTEMAC(ch,scal2ris)( *kappa_r, *kappa_i, *(alpha1_r + 7*inca2), *(alpha1_i + 7*inca2), *(pi1_r + 7), *(pi1_i + 7) ); \ \ alpha1_r += lda2; \ alpha1_i += lda2; \ pi1_r += ldp2; \ pi1_i += ldp2; \ } \ } \ } \ } \ } \ else /* if ( cdim < mnr ) */ \ { \ PASTEMAC(ch,scal21ms_mxn) \ ( \ schema, \ conja, \ cdim, \ n, \ kappa, \ a, inca, lda, \ p, 1, ldp, ldp \ ); \ \ /* if ( cdim < mnr ) */ \ { \ ctype* restrict zero = PASTEMAC(ch,0); \ const dim_t offm = cdim; \ const dim_t offn = 0; \ const dim_t m_edge = mnr - cdim; \ const dim_t n_edge = n_max; \ \ PASTEMAC(ch,set1ms_mxn) \ ( \ schema, \ offm, \ offn, \ m_edge, \ n_edge, \ zero, \ p, 1, ldp, ldp \ ); \ } \ } \ \ if ( n < n_max ) \ { \ ctype* restrict zero = PASTEMAC(ch,0); \ const dim_t offm = 0; \ const dim_t offn = n; \ const dim_t m_edge = mnr; \ const dim_t n_edge = n_max - n; \ \ PASTEMAC(ch,set1ms_mxn) \ ( \ schema, \ offm, \ offn, \ m_edge, \ n_edge, \ zero, \ p, 1, ldp, ldp \ ); \ } \ } INSERT_GENTFUNCCO_BASIC3( packm_8xk_1er, 8, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX ) #undef GENTFUNCCO #define GENTFUNCCO( ctype, ctype_r, ch, chr, opname, mnr, arch, suf ) \ \ void PASTEMAC3(ch,opname,arch,suf) \ ( \ conj_t conja, \ pack_t schema, \ dim_t cdim, \ dim_t n, \ dim_t n_max, \ ctype* restrict kappa, \ ctype* restrict a, inc_t inca, inc_t lda, \ ctype* restrict p, inc_t ldp, \ cntx_t* restrict cntx \ ) \ { \ if ( cdim == mnr ) \ { \ if ( bli_is_1e_packed( schema ) ) \ { \ const inc_t inca1 = inca; \ const inc_t lda1 = lda; \ const inc_t ldp1 = ldp; \ \ ctype* restrict kappa_cast = ( ctype* )kappa; \ ctype* restrict alpha1_ri = ( ctype* )a; \ ctype* restrict pi1_ri = ( ctype* )p; \ ctype* restrict pi1_ir = ( ctype* )p + ldp1/2; \ \ if ( PASTEMAC(ch,eq1)( *kappa_cast ) ) \ { \ if ( bli_is_conj( conja ) ) \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,copyj1es)( *(alpha1_ri + 0*inca1), *(pi1_ri + 0), *(pi1_ir + 0) ); \ PASTEMAC(ch,copyj1es)( *(alpha1_ri + 1*inca1), *(pi1_ri + 1), *(pi1_ir + 1) ); \ PASTEMAC(ch,copyj1es)( *(alpha1_ri + 2*inca1), *(pi1_ri + 2), *(pi1_ir + 2) ); \ PASTEMAC(ch,copyj1es)( *(alpha1_ri + 3*inca1), *(pi1_ri + 3), *(pi1_ir + 3) ); \ PASTEMAC(ch,copyj1es)( *(alpha1_ri + 4*inca1), *(pi1_ri + 4), *(pi1_ir + 4) ); \ PASTEMAC(ch,copyj1es)( *(alpha1_ri + 5*inca1), *(pi1_ri + 5), *(pi1_ir + 5) ); \ PASTEMAC(ch,copyj1es)( *(alpha1_ri + 6*inca1), *(pi1_ri + 6), *(pi1_ir + 6) ); \ PASTEMAC(ch,copyj1es)( *(alpha1_ri + 7*inca1), *(pi1_ri + 7), *(pi1_ir + 7) ); \ PASTEMAC(ch,copyj1es)( *(alpha1_ri + 8*inca1), *(pi1_ri + 8), *(pi1_ir + 8) ); \ PASTEMAC(ch,copyj1es)( *(alpha1_ri + 9*inca1), *(pi1_ri + 9), *(pi1_ir + 9) ); \ \ alpha1_ri += lda1; \ pi1_ri += ldp1; \ pi1_ir += ldp1; \ } \ } \ else \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,copy1es)( *(alpha1_ri + 0*inca1), *(pi1_ri + 0), *(pi1_ir + 0) ); \ PASTEMAC(ch,copy1es)( *(alpha1_ri + 1*inca1), *(pi1_ri + 1), *(pi1_ir + 1) ); \ PASTEMAC(ch,copy1es)( *(alpha1_ri + 2*inca1), *(pi1_ri + 2), *(pi1_ir + 2) ); \ PASTEMAC(ch,copy1es)( *(alpha1_ri + 3*inca1), *(pi1_ri + 3), *(pi1_ir + 3) ); \ PASTEMAC(ch,copy1es)( *(alpha1_ri + 4*inca1), *(pi1_ri + 4), *(pi1_ir + 4) ); \ PASTEMAC(ch,copy1es)( *(alpha1_ri + 5*inca1), *(pi1_ri + 5), *(pi1_ir + 5) ); \ PASTEMAC(ch,copy1es)( *(alpha1_ri + 6*inca1), *(pi1_ri + 6), *(pi1_ir + 6) ); \ PASTEMAC(ch,copy1es)( *(alpha1_ri + 7*inca1), *(pi1_ri + 7), *(pi1_ir + 7) ); \ PASTEMAC(ch,copy1es)( *(alpha1_ri + 8*inca1), *(pi1_ri + 8), *(pi1_ir + 8) ); \ PASTEMAC(ch,copy1es)( *(alpha1_ri + 9*inca1), *(pi1_ri + 9), *(pi1_ir + 9) ); \ \ alpha1_ri += lda1; \ pi1_ri += ldp1; \ pi1_ir += ldp1; \ } \ } \ } \ else \ { \ if ( bli_is_conj( conja ) ) \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,scal2j1es)( *kappa_cast, *(alpha1_ri + 0*inca1), *(pi1_ri + 0), *(pi1_ir + 0) ); \ PASTEMAC(ch,scal2j1es)( *kappa_cast, *(alpha1_ri + 1*inca1), *(pi1_ri + 1), *(pi1_ir + 1) ); \ PASTEMAC(ch,scal2j1es)( *kappa_cast, *(alpha1_ri + 2*inca1), *(pi1_ri + 2), *(pi1_ir + 2) ); \ PASTEMAC(ch,scal2j1es)( *kappa_cast, *(alpha1_ri + 3*inca1), *(pi1_ri + 3), *(pi1_ir + 3) ); \ PASTEMAC(ch,scal2j1es)( *kappa_cast, *(alpha1_ri + 4*inca1), *(pi1_ri + 4), *(pi1_ir + 4) ); \ PASTEMAC(ch,scal2j1es)( *kappa_cast, *(alpha1_ri + 5*inca1), *(pi1_ri + 5), *(pi1_ir + 5) ); \ PASTEMAC(ch,scal2j1es)( *kappa_cast, *(alpha1_ri + 6*inca1), *(pi1_ri + 6), *(pi1_ir + 6) ); \ PASTEMAC(ch,scal2j1es)( *kappa_cast, *(alpha1_ri + 7*inca1), *(pi1_ri + 7), *(pi1_ir + 7) ); \ PASTEMAC(ch,scal2j1es)( *kappa_cast, *(alpha1_ri + 8*inca1), *(pi1_ri + 8), *(pi1_ir + 8) ); \ PASTEMAC(ch,scal2j1es)( *kappa_cast, *(alpha1_ri + 9*inca1), *(pi1_ri + 9), *(pi1_ir + 9) ); \ \ alpha1_ri += lda1; \ pi1_ri += ldp1; \ pi1_ir += ldp1; \ } \ } \ else \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,scal21es)( *kappa_cast, *(alpha1_ri + 0*inca1), *(pi1_ri + 0), *(pi1_ir + 0) ); \ PASTEMAC(ch,scal21es)( *kappa_cast, *(alpha1_ri + 1*inca1), *(pi1_ri + 1), *(pi1_ir + 1) ); \ PASTEMAC(ch,scal21es)( *kappa_cast, *(alpha1_ri + 2*inca1), *(pi1_ri + 2), *(pi1_ir + 2) ); \ PASTEMAC(ch,scal21es)( *kappa_cast, *(alpha1_ri + 3*inca1), *(pi1_ri + 3), *(pi1_ir + 3) ); \ PASTEMAC(ch,scal21es)( *kappa_cast, *(alpha1_ri + 4*inca1), *(pi1_ri + 4), *(pi1_ir + 4) ); \ PASTEMAC(ch,scal21es)( *kappa_cast, *(alpha1_ri + 5*inca1), *(pi1_ri + 5), *(pi1_ir + 5) ); \ PASTEMAC(ch,scal21es)( *kappa_cast, *(alpha1_ri + 6*inca1), *(pi1_ri + 6), *(pi1_ir + 6) ); \ PASTEMAC(ch,scal21es)( *kappa_cast, *(alpha1_ri + 7*inca1), *(pi1_ri + 7), *(pi1_ir + 7) ); \ PASTEMAC(ch,scal21es)( *kappa_cast, *(alpha1_ri + 8*inca1), *(pi1_ri + 8), *(pi1_ir + 8) ); \ PASTEMAC(ch,scal21es)( *kappa_cast, *(alpha1_ri + 9*inca1), *(pi1_ri + 9), *(pi1_ir + 9) ); \ \ alpha1_ri += lda1; \ pi1_ri += ldp1; \ pi1_ir += ldp1; \ } \ } \ } \ } \ else /* if ( bli_is_1r_packed( schema ) ) */ \ { \ const inc_t inca2 = 2 * inca; \ const inc_t lda2 = 2 * lda; \ const inc_t ldp2 = 2 * ldp; \ \ ctype* kappa_cast = kappa; \ ctype_r* restrict kappa_r = ( ctype_r* )kappa; \ ctype_r* restrict kappa_i = ( ctype_r* )kappa + 1; \ ctype_r* restrict alpha1_r = ( ctype_r* )a; \ ctype_r* restrict alpha1_i = ( ctype_r* )a + 1; \ ctype_r* restrict pi1_r = ( ctype_r* )p; \ ctype_r* restrict pi1_i = ( ctype_r* )p + ldp; \ \ if ( PASTEMAC(ch,eq1)( *kappa_cast ) ) \ { \ if ( bli_is_conj( conja ) ) \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,copyjris)( *(alpha1_r + 0*inca2), *(alpha1_i + 0*inca2), *(pi1_r + 0), *(pi1_i + 0) ); \ PASTEMAC(ch,copyjris)( *(alpha1_r + 1*inca2), *(alpha1_i + 1*inca2), *(pi1_r + 1), *(pi1_i + 1) ); \ PASTEMAC(ch,copyjris)( *(alpha1_r + 2*inca2), *(alpha1_i + 2*inca2), *(pi1_r + 2), *(pi1_i + 2) ); \ PASTEMAC(ch,copyjris)( *(alpha1_r + 3*inca2), *(alpha1_i + 3*inca2), *(pi1_r + 3), *(pi1_i + 3) ); \ PASTEMAC(ch,copyjris)( *(alpha1_r + 4*inca2), *(alpha1_i + 4*inca2), *(pi1_r + 4), *(pi1_i + 4) ); \ PASTEMAC(ch,copyjris)( *(alpha1_r + 5*inca2), *(alpha1_i + 5*inca2), *(pi1_r + 5), *(pi1_i + 5) ); \ PASTEMAC(ch,copyjris)( *(alpha1_r + 6*inca2), *(alpha1_i + 6*inca2), *(pi1_r + 6), *(pi1_i + 6) ); \ PASTEMAC(ch,copyjris)( *(alpha1_r + 7*inca2), *(alpha1_i + 7*inca2), *(pi1_r + 7), *(pi1_i + 7) ); \ PASTEMAC(ch,copyjris)( *(alpha1_r + 8*inca2), *(alpha1_i + 8*inca2), *(pi1_r + 8), *(pi1_i + 8) ); \ PASTEMAC(ch,copyjris)( *(alpha1_r + 9*inca2), *(alpha1_i + 9*inca2), *(pi1_r + 9), *(pi1_i + 9) ); \ \ alpha1_r += lda2; \ alpha1_i += lda2; \ pi1_r += ldp2; \ pi1_i += ldp2; \ } \ } \ else \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,copyris)( *(alpha1_r + 0*inca2), *(alpha1_i + 0*inca2), *(pi1_r + 0), *(pi1_i + 0) ); \ PASTEMAC(ch,copyris)( *(alpha1_r + 1*inca2), *(alpha1_i + 1*inca2), *(pi1_r + 1), *(pi1_i + 1) ); \ PASTEMAC(ch,copyris)( *(alpha1_r + 2*inca2), *(alpha1_i + 2*inca2), *(pi1_r + 2), *(pi1_i + 2) ); \ PASTEMAC(ch,copyris)( *(alpha1_r + 3*inca2), *(alpha1_i + 3*inca2), *(pi1_r + 3), *(pi1_i + 3) ); \ PASTEMAC(ch,copyris)( *(alpha1_r + 4*inca2), *(alpha1_i + 4*inca2), *(pi1_r + 4), *(pi1_i + 4) ); \ PASTEMAC(ch,copyris)( *(alpha1_r + 5*inca2), *(alpha1_i + 5*inca2), *(pi1_r + 5), *(pi1_i + 5) ); \ PASTEMAC(ch,copyris)( *(alpha1_r + 6*inca2), *(alpha1_i + 6*inca2), *(pi1_r + 6), *(pi1_i + 6) ); \ PASTEMAC(ch,copyris)( *(alpha1_r + 7*inca2), *(alpha1_i + 7*inca2), *(pi1_r + 7), *(pi1_i + 7) ); \ PASTEMAC(ch,copyris)( *(alpha1_r + 8*inca2), *(alpha1_i + 8*inca2), *(pi1_r + 8), *(pi1_i + 8) ); \ PASTEMAC(ch,copyris)( *(alpha1_r + 9*inca2), *(alpha1_i + 9*inca2), *(pi1_r + 9), *(pi1_i + 9) ); \ \ alpha1_r += lda2; \ alpha1_i += lda2; \ pi1_r += ldp2; \ pi1_i += ldp2; \ } \ } \ } \ else \ { \ if ( bli_is_conj( conja ) ) \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,scal2jris)( *kappa_r, *kappa_i, *(alpha1_r + 0*inca2), *(alpha1_i + 0*inca2), *(pi1_r + 0), *(pi1_i + 0) ); \ PASTEMAC(ch,scal2jris)( *kappa_r, *kappa_i, *(alpha1_r + 1*inca2), *(alpha1_i + 1*inca2), *(pi1_r + 1), *(pi1_i + 1) ); \ PASTEMAC(ch,scal2jris)( *kappa_r, *kappa_i, *(alpha1_r + 2*inca2), *(alpha1_i + 2*inca2), *(pi1_r + 2), *(pi1_i + 2) ); \ PASTEMAC(ch,scal2jris)( *kappa_r, *kappa_i, *(alpha1_r + 3*inca2), *(alpha1_i + 3*inca2), *(pi1_r + 3), *(pi1_i + 3) ); \ PASTEMAC(ch,scal2jris)( *kappa_r, *kappa_i, *(alpha1_r + 4*inca2), *(alpha1_i + 4*inca2), *(pi1_r + 4), *(pi1_i + 4) ); \ PASTEMAC(ch,scal2jris)( *kappa_r, *kappa_i, *(alpha1_r + 5*inca2), *(alpha1_i + 5*inca2), *(pi1_r + 5), *(pi1_i + 5) ); \ PASTEMAC(ch,scal2jris)( *kappa_r, *kappa_i, *(alpha1_r + 6*inca2), *(alpha1_i + 6*inca2), *(pi1_r + 6), *(pi1_i + 6) ); \ PASTEMAC(ch,scal2jris)( *kappa_r, *kappa_i, *(alpha1_r + 7*inca2), *(alpha1_i + 7*inca2), *(pi1_r + 7), *(pi1_i + 7) ); \ PASTEMAC(ch,scal2jris)( *kappa_r, *kappa_i, *(alpha1_r + 8*inca2), *(alpha1_i + 8*inca2), *(pi1_r + 8), *(pi1_i + 8) ); \ PASTEMAC(ch,scal2jris)( *kappa_r, *kappa_i, *(alpha1_r + 9*inca2), *(alpha1_i + 9*inca2), *(pi1_r + 9), *(pi1_i + 9) ); \ \ alpha1_r += lda2; \ alpha1_i += lda2; \ pi1_r += ldp2; \ pi1_i += ldp2; \ } \ } \ else \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,scal2ris)( *kappa_r, *kappa_i, *(alpha1_r + 0*inca2), *(alpha1_i + 0*inca2), *(pi1_r + 0), *(pi1_i + 0) ); \ PASTEMAC(ch,scal2ris)( *kappa_r, *kappa_i, *(alpha1_r + 1*inca2), *(alpha1_i + 1*inca2), *(pi1_r + 1), *(pi1_i + 1) ); \ PASTEMAC(ch,scal2ris)( *kappa_r, *kappa_i, *(alpha1_r + 2*inca2), *(alpha1_i + 2*inca2), *(pi1_r + 2), *(pi1_i + 2) ); \ PASTEMAC(ch,scal2ris)( *kappa_r, *kappa_i, *(alpha1_r + 3*inca2), *(alpha1_i + 3*inca2), *(pi1_r + 3), *(pi1_i + 3) ); \ PASTEMAC(ch,scal2ris)( *kappa_r, *kappa_i, *(alpha1_r + 4*inca2), *(alpha1_i + 4*inca2), *(pi1_r + 4), *(pi1_i + 4) ); \ PASTEMAC(ch,scal2ris)( *kappa_r, *kappa_i, *(alpha1_r + 5*inca2), *(alpha1_i + 5*inca2), *(pi1_r + 5), *(pi1_i + 5) ); \ PASTEMAC(ch,scal2ris)( *kappa_r, *kappa_i, *(alpha1_r + 6*inca2), *(alpha1_i + 6*inca2), *(pi1_r + 6), *(pi1_i + 6) ); \ PASTEMAC(ch,scal2ris)( *kappa_r, *kappa_i, *(alpha1_r + 7*inca2), *(alpha1_i + 7*inca2), *(pi1_r + 7), *(pi1_i + 7) ); \ PASTEMAC(ch,scal2ris)( *kappa_r, *kappa_i, *(alpha1_r + 8*inca2), *(alpha1_i + 8*inca2), *(pi1_r + 8), *(pi1_i + 8) ); \ PASTEMAC(ch,scal2ris)( *kappa_r, *kappa_i, *(alpha1_r + 9*inca2), *(alpha1_i + 9*inca2), *(pi1_r + 9), *(pi1_i + 9) ); \ \ alpha1_r += lda2; \ alpha1_i += lda2; \ pi1_r += ldp2; \ pi1_i += ldp2; \ } \ } \ } \ } \ } \ else /* if ( cdim < mnr ) */ \ { \ PASTEMAC(ch,scal21ms_mxn) \ ( \ schema, \ conja, \ cdim, \ n, \ kappa, \ a, inca, lda, \ p, 1, ldp, ldp \ ); \ \ /* if ( cdim < mnr ) */ \ { \ ctype* restrict zero = PASTEMAC(ch,0); \ const dim_t offm = cdim; \ const dim_t offn = 0; \ const dim_t m_edge = mnr - cdim; \ const dim_t n_edge = n_max; \ \ PASTEMAC(ch,set1ms_mxn) \ ( \ schema, \ offm, \ offn, \ m_edge, \ n_edge, \ zero, \ p, 1, ldp, ldp \ ); \ } \ } \ \ if ( n < n_max ) \ { \ ctype* restrict zero = PASTEMAC(ch,0); \ const dim_t offm = 0; \ const dim_t offn = n; \ const dim_t m_edge = mnr; \ const dim_t n_edge = n_max - n; \ \ PASTEMAC(ch,set1ms_mxn) \ ( \ schema, \ offm, \ offn, \ m_edge, \ n_edge, \ zero, \ p, 1, ldp, ldp \ ); \ } \ } INSERT_GENTFUNCCO_BASIC3( packm_10xk_1er, 10, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX ) #undef GENTFUNCCO #define GENTFUNCCO( ctype, ctype_r, ch, chr, opname, mnr, arch, suf ) \ \ void PASTEMAC3(ch,opname,arch,suf) \ ( \ conj_t conja, \ pack_t schema, \ dim_t cdim, \ dim_t n, \ dim_t n_max, \ ctype* restrict kappa, \ ctype* restrict a, inc_t inca, inc_t lda, \ ctype* restrict p, inc_t ldp, \ cntx_t* restrict cntx \ ) \ { \ if ( cdim == mnr ) \ { \ if ( bli_is_1e_packed( schema ) ) \ { \ const inc_t inca1 = inca; \ const inc_t lda1 = lda; \ const inc_t ldp1 = ldp; \ \ ctype* restrict kappa_cast = ( ctype* )kappa; \ ctype* restrict alpha1_ri = ( ctype* )a; \ ctype* restrict pi1_ri = ( ctype* )p; \ ctype* restrict pi1_ir = ( ctype* )p + ldp1/2; \ \ if ( PASTEMAC(ch,eq1)( *kappa_cast ) ) \ { \ if ( bli_is_conj( conja ) ) \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,copyj1es)( *(alpha1_ri + 0*inca1), *(pi1_ri + 0), *(pi1_ir + 0) ); \ PASTEMAC(ch,copyj1es)( *(alpha1_ri + 1*inca1), *(pi1_ri + 1), *(pi1_ir + 1) ); \ PASTEMAC(ch,copyj1es)( *(alpha1_ri + 2*inca1), *(pi1_ri + 2), *(pi1_ir + 2) ); \ PASTEMAC(ch,copyj1es)( *(alpha1_ri + 3*inca1), *(pi1_ri + 3), *(pi1_ir + 3) ); \ PASTEMAC(ch,copyj1es)( *(alpha1_ri + 4*inca1), *(pi1_ri + 4), *(pi1_ir + 4) ); \ PASTEMAC(ch,copyj1es)( *(alpha1_ri + 5*inca1), *(pi1_ri + 5), *(pi1_ir + 5) ); \ PASTEMAC(ch,copyj1es)( *(alpha1_ri + 6*inca1), *(pi1_ri + 6), *(pi1_ir + 6) ); \ PASTEMAC(ch,copyj1es)( *(alpha1_ri + 7*inca1), *(pi1_ri + 7), *(pi1_ir + 7) ); \ PASTEMAC(ch,copyj1es)( *(alpha1_ri + 8*inca1), *(pi1_ri + 8), *(pi1_ir + 8) ); \ PASTEMAC(ch,copyj1es)( *(alpha1_ri + 9*inca1), *(pi1_ri + 9), *(pi1_ir + 9) ); \ PASTEMAC(ch,copyj1es)( *(alpha1_ri +10*inca1), *(pi1_ri +10), *(pi1_ir +10) ); \ PASTEMAC(ch,copyj1es)( *(alpha1_ri +11*inca1), *(pi1_ri +11), *(pi1_ir +11) ); \ \ alpha1_ri += lda1; \ pi1_ri += ldp1; \ pi1_ir += ldp1; \ } \ } \ else \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,copy1es)( *(alpha1_ri + 0*inca1), *(pi1_ri + 0), *(pi1_ir + 0) ); \ PASTEMAC(ch,copy1es)( *(alpha1_ri + 1*inca1), *(pi1_ri + 1), *(pi1_ir + 1) ); \ PASTEMAC(ch,copy1es)( *(alpha1_ri + 2*inca1), *(pi1_ri + 2), *(pi1_ir + 2) ); \ PASTEMAC(ch,copy1es)( *(alpha1_ri + 3*inca1), *(pi1_ri + 3), *(pi1_ir + 3) ); \ PASTEMAC(ch,copy1es)( *(alpha1_ri + 4*inca1), *(pi1_ri + 4), *(pi1_ir + 4) ); \ PASTEMAC(ch,copy1es)( *(alpha1_ri + 5*inca1), *(pi1_ri + 5), *(pi1_ir + 5) ); \ PASTEMAC(ch,copy1es)( *(alpha1_ri + 6*inca1), *(pi1_ri + 6), *(pi1_ir + 6) ); \ PASTEMAC(ch,copy1es)( *(alpha1_ri + 7*inca1), *(pi1_ri + 7), *(pi1_ir + 7) ); \ PASTEMAC(ch,copy1es)( *(alpha1_ri + 8*inca1), *(pi1_ri + 8), *(pi1_ir + 8) ); \ PASTEMAC(ch,copy1es)( *(alpha1_ri + 9*inca1), *(pi1_ri + 9), *(pi1_ir + 9) ); \ PASTEMAC(ch,copy1es)( *(alpha1_ri +10*inca1), *(pi1_ri +10), *(pi1_ir +10) ); \ PASTEMAC(ch,copy1es)( *(alpha1_ri +11*inca1), *(pi1_ri +11), *(pi1_ir +11) ); \ \ alpha1_ri += lda1; \ pi1_ri += ldp1; \ pi1_ir += ldp1; \ } \ } \ } \ else \ { \ if ( bli_is_conj( conja ) ) \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,scal2j1es)( *kappa_cast, *(alpha1_ri + 0*inca1), *(pi1_ri + 0), *(pi1_ir + 0) ); \ PASTEMAC(ch,scal2j1es)( *kappa_cast, *(alpha1_ri + 1*inca1), *(pi1_ri + 1), *(pi1_ir + 1) ); \ PASTEMAC(ch,scal2j1es)( *kappa_cast, *(alpha1_ri + 2*inca1), *(pi1_ri + 2), *(pi1_ir + 2) ); \ PASTEMAC(ch,scal2j1es)( *kappa_cast, *(alpha1_ri + 3*inca1), *(pi1_ri + 3), *(pi1_ir + 3) ); \ PASTEMAC(ch,scal2j1es)( *kappa_cast, *(alpha1_ri + 4*inca1), *(pi1_ri + 4), *(pi1_ir + 4) ); \ PASTEMAC(ch,scal2j1es)( *kappa_cast, *(alpha1_ri + 5*inca1), *(pi1_ri + 5), *(pi1_ir + 5) ); \ PASTEMAC(ch,scal2j1es)( *kappa_cast, *(alpha1_ri + 6*inca1), *(pi1_ri + 6), *(pi1_ir + 6) ); \ PASTEMAC(ch,scal2j1es)( *kappa_cast, *(alpha1_ri + 7*inca1), *(pi1_ri + 7), *(pi1_ir + 7) ); \ PASTEMAC(ch,scal2j1es)( *kappa_cast, *(alpha1_ri + 8*inca1), *(pi1_ri + 8), *(pi1_ir + 8) ); \ PASTEMAC(ch,scal2j1es)( *kappa_cast, *(alpha1_ri + 9*inca1), *(pi1_ri + 9), *(pi1_ir + 9) ); \ PASTEMAC(ch,scal2j1es)( *kappa_cast, *(alpha1_ri +10*inca1), *(pi1_ri +10), *(pi1_ir +10) ); \ PASTEMAC(ch,scal2j1es)( *kappa_cast, *(alpha1_ri +11*inca1), *(pi1_ri +11), *(pi1_ir +11) ); \ \ alpha1_ri += lda1; \ pi1_ri += ldp1; \ pi1_ir += ldp1; \ } \ } \ else \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,scal21es)( *kappa_cast, *(alpha1_ri + 0*inca1), *(pi1_ri + 0), *(pi1_ir + 0) ); \ PASTEMAC(ch,scal21es)( *kappa_cast, *(alpha1_ri + 1*inca1), *(pi1_ri + 1), *(pi1_ir + 1) ); \ PASTEMAC(ch,scal21es)( *kappa_cast, *(alpha1_ri + 2*inca1), *(pi1_ri + 2), *(pi1_ir + 2) ); \ PASTEMAC(ch,scal21es)( *kappa_cast, *(alpha1_ri + 3*inca1), *(pi1_ri + 3), *(pi1_ir + 3) ); \ PASTEMAC(ch,scal21es)( *kappa_cast, *(alpha1_ri + 4*inca1), *(pi1_ri + 4), *(pi1_ir + 4) ); \ PASTEMAC(ch,scal21es)( *kappa_cast, *(alpha1_ri + 5*inca1), *(pi1_ri + 5), *(pi1_ir + 5) ); \ PASTEMAC(ch,scal21es)( *kappa_cast, *(alpha1_ri + 6*inca1), *(pi1_ri + 6), *(pi1_ir + 6) ); \ PASTEMAC(ch,scal21es)( *kappa_cast, *(alpha1_ri + 7*inca1), *(pi1_ri + 7), *(pi1_ir + 7) ); \ PASTEMAC(ch,scal21es)( *kappa_cast, *(alpha1_ri + 8*inca1), *(pi1_ri + 8), *(pi1_ir + 8) ); \ PASTEMAC(ch,scal21es)( *kappa_cast, *(alpha1_ri + 9*inca1), *(pi1_ri + 9), *(pi1_ir + 9) ); \ PASTEMAC(ch,scal21es)( *kappa_cast, *(alpha1_ri +10*inca1), *(pi1_ri +10), *(pi1_ir +10) ); \ PASTEMAC(ch,scal21es)( *kappa_cast, *(alpha1_ri +11*inca1), *(pi1_ri +11), *(pi1_ir +11) ); \ \ alpha1_ri += lda1; \ pi1_ri += ldp1; \ pi1_ir += ldp1; \ } \ } \ } \ } \ else /* if ( bli_is_1r_packed( schema ) ) */ \ { \ const inc_t inca2 = 2 * inca; \ const inc_t lda2 = 2 * lda; \ const inc_t ldp2 = 2 * ldp; \ \ ctype* kappa_cast = kappa; \ ctype_r* restrict kappa_r = ( ctype_r* )kappa; \ ctype_r* restrict kappa_i = ( ctype_r* )kappa + 1; \ ctype_r* restrict alpha1_r = ( ctype_r* )a; \ ctype_r* restrict alpha1_i = ( ctype_r* )a + 1; \ ctype_r* restrict pi1_r = ( ctype_r* )p; \ ctype_r* restrict pi1_i = ( ctype_r* )p + ldp; \ \ if ( PASTEMAC(ch,eq1)( *kappa_cast ) ) \ { \ if ( bli_is_conj( conja ) ) \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,copyjris)( *(alpha1_r + 0*inca2), *(alpha1_i + 0*inca2), *(pi1_r + 0), *(pi1_i + 0) ); \ PASTEMAC(ch,copyjris)( *(alpha1_r + 1*inca2), *(alpha1_i + 1*inca2), *(pi1_r + 1), *(pi1_i + 1) ); \ PASTEMAC(ch,copyjris)( *(alpha1_r + 2*inca2), *(alpha1_i + 2*inca2), *(pi1_r + 2), *(pi1_i + 2) ); \ PASTEMAC(ch,copyjris)( *(alpha1_r + 3*inca2), *(alpha1_i + 3*inca2), *(pi1_r + 3), *(pi1_i + 3) ); \ PASTEMAC(ch,copyjris)( *(alpha1_r + 4*inca2), *(alpha1_i + 4*inca2), *(pi1_r + 4), *(pi1_i + 4) ); \ PASTEMAC(ch,copyjris)( *(alpha1_r + 5*inca2), *(alpha1_i + 5*inca2), *(pi1_r + 5), *(pi1_i + 5) ); \ PASTEMAC(ch,copyjris)( *(alpha1_r + 6*inca2), *(alpha1_i + 6*inca2), *(pi1_r + 6), *(pi1_i + 6) ); \ PASTEMAC(ch,copyjris)( *(alpha1_r + 7*inca2), *(alpha1_i + 7*inca2), *(pi1_r + 7), *(pi1_i + 7) ); \ PASTEMAC(ch,copyjris)( *(alpha1_r + 8*inca2), *(alpha1_i + 8*inca2), *(pi1_r + 8), *(pi1_i + 8) ); \ PASTEMAC(ch,copyjris)( *(alpha1_r + 9*inca2), *(alpha1_i + 9*inca2), *(pi1_r + 9), *(pi1_i + 9) ); \ PASTEMAC(ch,copyjris)( *(alpha1_r +10*inca2), *(alpha1_i +10*inca2), *(pi1_r +10), *(pi1_i +10) ); \ PASTEMAC(ch,copyjris)( *(alpha1_r +11*inca2), *(alpha1_i +11*inca2), *(pi1_r +11), *(pi1_i +11) ); \ \ alpha1_r += lda2; \ alpha1_i += lda2; \ pi1_r += ldp2; \ pi1_i += ldp2; \ } \ } \ else \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,copyris)( *(alpha1_r + 0*inca2), *(alpha1_i + 0*inca2), *(pi1_r + 0), *(pi1_i + 0) ); \ PASTEMAC(ch,copyris)( *(alpha1_r + 1*inca2), *(alpha1_i + 1*inca2), *(pi1_r + 1), *(pi1_i + 1) ); \ PASTEMAC(ch,copyris)( *(alpha1_r + 2*inca2), *(alpha1_i + 2*inca2), *(pi1_r + 2), *(pi1_i + 2) ); \ PASTEMAC(ch,copyris)( *(alpha1_r + 3*inca2), *(alpha1_i + 3*inca2), *(pi1_r + 3), *(pi1_i + 3) ); \ PASTEMAC(ch,copyris)( *(alpha1_r + 4*inca2), *(alpha1_i + 4*inca2), *(pi1_r + 4), *(pi1_i + 4) ); \ PASTEMAC(ch,copyris)( *(alpha1_r + 5*inca2), *(alpha1_i + 5*inca2), *(pi1_r + 5), *(pi1_i + 5) ); \ PASTEMAC(ch,copyris)( *(alpha1_r + 6*inca2), *(alpha1_i + 6*inca2), *(pi1_r + 6), *(pi1_i + 6) ); \ PASTEMAC(ch,copyris)( *(alpha1_r + 7*inca2), *(alpha1_i + 7*inca2), *(pi1_r + 7), *(pi1_i + 7) ); \ PASTEMAC(ch,copyris)( *(alpha1_r + 8*inca2), *(alpha1_i + 8*inca2), *(pi1_r + 8), *(pi1_i + 8) ); \ PASTEMAC(ch,copyris)( *(alpha1_r + 9*inca2), *(alpha1_i + 9*inca2), *(pi1_r + 9), *(pi1_i + 9) ); \ PASTEMAC(ch,copyris)( *(alpha1_r +10*inca2), *(alpha1_i +10*inca2), *(pi1_r +10), *(pi1_i +10) ); \ PASTEMAC(ch,copyris)( *(alpha1_r +11*inca2), *(alpha1_i +11*inca2), *(pi1_r +11), *(pi1_i +11) ); \ \ alpha1_r += lda2; \ alpha1_i += lda2; \ pi1_r += ldp2; \ pi1_i += ldp2; \ } \ } \ } \ else \ { \ if ( bli_is_conj( conja ) ) \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,scal2jris)( *kappa_r, *kappa_i, *(alpha1_r + 0*inca2), *(alpha1_i + 0*inca2), *(pi1_r + 0), *(pi1_i + 0) ); \ PASTEMAC(ch,scal2jris)( *kappa_r, *kappa_i, *(alpha1_r + 1*inca2), *(alpha1_i + 1*inca2), *(pi1_r + 1), *(pi1_i + 1) ); \ PASTEMAC(ch,scal2jris)( *kappa_r, *kappa_i, *(alpha1_r + 2*inca2), *(alpha1_i + 2*inca2), *(pi1_r + 2), *(pi1_i + 2) ); \ PASTEMAC(ch,scal2jris)( *kappa_r, *kappa_i, *(alpha1_r + 3*inca2), *(alpha1_i + 3*inca2), *(pi1_r + 3), *(pi1_i + 3) ); \ PASTEMAC(ch,scal2jris)( *kappa_r, *kappa_i, *(alpha1_r + 4*inca2), *(alpha1_i + 4*inca2), *(pi1_r + 4), *(pi1_i + 4) ); \ PASTEMAC(ch,scal2jris)( *kappa_r, *kappa_i, *(alpha1_r + 5*inca2), *(alpha1_i + 5*inca2), *(pi1_r + 5), *(pi1_i + 5) ); \ PASTEMAC(ch,scal2jris)( *kappa_r, *kappa_i, *(alpha1_r + 6*inca2), *(alpha1_i + 6*inca2), *(pi1_r + 6), *(pi1_i + 6) ); \ PASTEMAC(ch,scal2jris)( *kappa_r, *kappa_i, *(alpha1_r + 7*inca2), *(alpha1_i + 7*inca2), *(pi1_r + 7), *(pi1_i + 7) ); \ PASTEMAC(ch,scal2jris)( *kappa_r, *kappa_i, *(alpha1_r + 8*inca2), *(alpha1_i + 8*inca2), *(pi1_r + 8), *(pi1_i + 8) ); \ PASTEMAC(ch,scal2jris)( *kappa_r, *kappa_i, *(alpha1_r + 9*inca2), *(alpha1_i + 9*inca2), *(pi1_r + 9), *(pi1_i + 9) ); \ PASTEMAC(ch,scal2jris)( *kappa_r, *kappa_i, *(alpha1_r +10*inca2), *(alpha1_i +10*inca2), *(pi1_r +10), *(pi1_i +10) ); \ PASTEMAC(ch,scal2jris)( *kappa_r, *kappa_i, *(alpha1_r +11*inca2), *(alpha1_i +11*inca2), *(pi1_r +11), *(pi1_i +11) ); \ \ alpha1_r += lda2; \ alpha1_i += lda2; \ pi1_r += ldp2; \ pi1_i += ldp2; \ } \ } \ else \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,scal2ris)( *kappa_r, *kappa_i, *(alpha1_r + 0*inca2), *(alpha1_i + 0*inca2), *(pi1_r + 0), *(pi1_i + 0) ); \ PASTEMAC(ch,scal2ris)( *kappa_r, *kappa_i, *(alpha1_r + 1*inca2), *(alpha1_i + 1*inca2), *(pi1_r + 1), *(pi1_i + 1) ); \ PASTEMAC(ch,scal2ris)( *kappa_r, *kappa_i, *(alpha1_r + 2*inca2), *(alpha1_i + 2*inca2), *(pi1_r + 2), *(pi1_i + 2) ); \ PASTEMAC(ch,scal2ris)( *kappa_r, *kappa_i, *(alpha1_r + 3*inca2), *(alpha1_i + 3*inca2), *(pi1_r + 3), *(pi1_i + 3) ); \ PASTEMAC(ch,scal2ris)( *kappa_r, *kappa_i, *(alpha1_r + 4*inca2), *(alpha1_i + 4*inca2), *(pi1_r + 4), *(pi1_i + 4) ); \ PASTEMAC(ch,scal2ris)( *kappa_r, *kappa_i, *(alpha1_r + 5*inca2), *(alpha1_i + 5*inca2), *(pi1_r + 5), *(pi1_i + 5) ); \ PASTEMAC(ch,scal2ris)( *kappa_r, *kappa_i, *(alpha1_r + 6*inca2), *(alpha1_i + 6*inca2), *(pi1_r + 6), *(pi1_i + 6) ); \ PASTEMAC(ch,scal2ris)( *kappa_r, *kappa_i, *(alpha1_r + 7*inca2), *(alpha1_i + 7*inca2), *(pi1_r + 7), *(pi1_i + 7) ); \ PASTEMAC(ch,scal2ris)( *kappa_r, *kappa_i, *(alpha1_r + 8*inca2), *(alpha1_i + 8*inca2), *(pi1_r + 8), *(pi1_i + 8) ); \ PASTEMAC(ch,scal2ris)( *kappa_r, *kappa_i, *(alpha1_r + 9*inca2), *(alpha1_i + 9*inca2), *(pi1_r + 9), *(pi1_i + 9) ); \ PASTEMAC(ch,scal2ris)( *kappa_r, *kappa_i, *(alpha1_r +10*inca2), *(alpha1_i +10*inca2), *(pi1_r +10), *(pi1_i +10) ); \ PASTEMAC(ch,scal2ris)( *kappa_r, *kappa_i, *(alpha1_r +11*inca2), *(alpha1_i +11*inca2), *(pi1_r +11), *(pi1_i +11) ); \ \ alpha1_r += lda2; \ alpha1_i += lda2; \ pi1_r += ldp2; \ pi1_i += ldp2; \ } \ } \ } \ } \ } \ else /* if ( cdim < mnr ) */ \ { \ PASTEMAC(ch,scal21ms_mxn) \ ( \ schema, \ conja, \ cdim, \ n, \ kappa, \ a, inca, lda, \ p, 1, ldp, ldp \ ); \ \ /* if ( cdim < mnr ) */ \ { \ ctype* restrict zero = PASTEMAC(ch,0); \ const dim_t offm = cdim; \ const dim_t offn = 0; \ const dim_t m_edge = mnr - cdim; \ const dim_t n_edge = n_max; \ \ PASTEMAC(ch,set1ms_mxn) \ ( \ schema, \ offm, \ offn, \ m_edge, \ n_edge, \ zero, \ p, 1, ldp, ldp \ ); \ } \ } \ \ if ( n < n_max ) \ { \ ctype* restrict zero = PASTEMAC(ch,0); \ const dim_t offm = 0; \ const dim_t offn = n; \ const dim_t m_edge = mnr; \ const dim_t n_edge = n_max - n; \ \ PASTEMAC(ch,set1ms_mxn) \ ( \ schema, \ offm, \ offn, \ m_edge, \ n_edge, \ zero, \ p, 1, ldp, ldp \ ); \ } \ } INSERT_GENTFUNCCO_BASIC3( packm_12xk_1er, 12, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX ) #undef GENTFUNCCO #define GENTFUNCCO( ctype, ctype_r, ch, chr, opname, mnr, arch, suf ) \ \ void PASTEMAC3(ch,opname,arch,suf) \ ( \ conj_t conja, \ pack_t schema, \ dim_t cdim, \ dim_t n, \ dim_t n_max, \ ctype* restrict kappa, \ ctype* restrict a, inc_t inca, inc_t lda, \ ctype* restrict p, inc_t ldp, \ cntx_t* restrict cntx \ ) \ { \ if ( cdim == mnr ) \ { \ if ( bli_is_1e_packed( schema ) ) \ { \ const inc_t inca1 = inca; \ const inc_t lda1 = lda; \ const inc_t ldp1 = ldp; \ \ ctype* restrict kappa_cast = ( ctype* )kappa; \ ctype* restrict alpha1_ri = ( ctype* )a; \ ctype* restrict pi1_ri = ( ctype* )p; \ ctype* restrict pi1_ir = ( ctype* )p + ldp1/2; \ \ if ( PASTEMAC(ch,eq1)( *kappa_cast ) ) \ { \ if ( bli_is_conj( conja ) ) \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,copyj1es)( *(alpha1_ri + 0*inca1), *(pi1_ri + 0), *(pi1_ir + 0) ); \ PASTEMAC(ch,copyj1es)( *(alpha1_ri + 1*inca1), *(pi1_ri + 1), *(pi1_ir + 1) ); \ PASTEMAC(ch,copyj1es)( *(alpha1_ri + 2*inca1), *(pi1_ri + 2), *(pi1_ir + 2) ); \ PASTEMAC(ch,copyj1es)( *(alpha1_ri + 3*inca1), *(pi1_ri + 3), *(pi1_ir + 3) ); \ PASTEMAC(ch,copyj1es)( *(alpha1_ri + 4*inca1), *(pi1_ri + 4), *(pi1_ir + 4) ); \ PASTEMAC(ch,copyj1es)( *(alpha1_ri + 5*inca1), *(pi1_ri + 5), *(pi1_ir + 5) ); \ PASTEMAC(ch,copyj1es)( *(alpha1_ri + 6*inca1), *(pi1_ri + 6), *(pi1_ir + 6) ); \ PASTEMAC(ch,copyj1es)( *(alpha1_ri + 7*inca1), *(pi1_ri + 7), *(pi1_ir + 7) ); \ PASTEMAC(ch,copyj1es)( *(alpha1_ri + 8*inca1), *(pi1_ri + 8), *(pi1_ir + 8) ); \ PASTEMAC(ch,copyj1es)( *(alpha1_ri + 9*inca1), *(pi1_ri + 9), *(pi1_ir + 9) ); \ PASTEMAC(ch,copyj1es)( *(alpha1_ri +10*inca1), *(pi1_ri +10), *(pi1_ir +10) ); \ PASTEMAC(ch,copyj1es)( *(alpha1_ri +11*inca1), *(pi1_ri +11), *(pi1_ir +11) ); \ PASTEMAC(ch,copyj1es)( *(alpha1_ri +12*inca1), *(pi1_ri +12), *(pi1_ir +12) ); \ PASTEMAC(ch,copyj1es)( *(alpha1_ri +13*inca1), *(pi1_ri +13), *(pi1_ir +13) ); \ \ alpha1_ri += lda1; \ pi1_ri += ldp1; \ pi1_ir += ldp1; \ } \ } \ else \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,copy1es)( *(alpha1_ri + 0*inca1), *(pi1_ri + 0), *(pi1_ir + 0) ); \ PASTEMAC(ch,copy1es)( *(alpha1_ri + 1*inca1), *(pi1_ri + 1), *(pi1_ir + 1) ); \ PASTEMAC(ch,copy1es)( *(alpha1_ri + 2*inca1), *(pi1_ri + 2), *(pi1_ir + 2) ); \ PASTEMAC(ch,copy1es)( *(alpha1_ri + 3*inca1), *(pi1_ri + 3), *(pi1_ir + 3) ); \ PASTEMAC(ch,copy1es)( *(alpha1_ri + 4*inca1), *(pi1_ri + 4), *(pi1_ir + 4) ); \ PASTEMAC(ch,copy1es)( *(alpha1_ri + 5*inca1), *(pi1_ri + 5), *(pi1_ir + 5) ); \ PASTEMAC(ch,copy1es)( *(alpha1_ri + 6*inca1), *(pi1_ri + 6), *(pi1_ir + 6) ); \ PASTEMAC(ch,copy1es)( *(alpha1_ri + 7*inca1), *(pi1_ri + 7), *(pi1_ir + 7) ); \ PASTEMAC(ch,copy1es)( *(alpha1_ri + 8*inca1), *(pi1_ri + 8), *(pi1_ir + 8) ); \ PASTEMAC(ch,copy1es)( *(alpha1_ri + 9*inca1), *(pi1_ri + 9), *(pi1_ir + 9) ); \ PASTEMAC(ch,copy1es)( *(alpha1_ri +10*inca1), *(pi1_ri +10), *(pi1_ir +10) ); \ PASTEMAC(ch,copy1es)( *(alpha1_ri +11*inca1), *(pi1_ri +11), *(pi1_ir +11) ); \ PASTEMAC(ch,copy1es)( *(alpha1_ri +12*inca1), *(pi1_ri +12), *(pi1_ir +12) ); \ PASTEMAC(ch,copy1es)( *(alpha1_ri +13*inca1), *(pi1_ri +13), *(pi1_ir +13) ); \ \ alpha1_ri += lda1; \ pi1_ri += ldp1; \ pi1_ir += ldp1; \ } \ } \ } \ else \ { \ if ( bli_is_conj( conja ) ) \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,scal2j1es)( *kappa_cast, *(alpha1_ri + 0*inca1), *(pi1_ri + 0), *(pi1_ir + 0) ); \ PASTEMAC(ch,scal2j1es)( *kappa_cast, *(alpha1_ri + 1*inca1), *(pi1_ri + 1), *(pi1_ir + 1) ); \ PASTEMAC(ch,scal2j1es)( *kappa_cast, *(alpha1_ri + 2*inca1), *(pi1_ri + 2), *(pi1_ir + 2) ); \ PASTEMAC(ch,scal2j1es)( *kappa_cast, *(alpha1_ri + 3*inca1), *(pi1_ri + 3), *(pi1_ir + 3) ); \ PASTEMAC(ch,scal2j1es)( *kappa_cast, *(alpha1_ri + 4*inca1), *(pi1_ri + 4), *(pi1_ir + 4) ); \ PASTEMAC(ch,scal2j1es)( *kappa_cast, *(alpha1_ri + 5*inca1), *(pi1_ri + 5), *(pi1_ir + 5) ); \ PASTEMAC(ch,scal2j1es)( *kappa_cast, *(alpha1_ri + 6*inca1), *(pi1_ri + 6), *(pi1_ir + 6) ); \ PASTEMAC(ch,scal2j1es)( *kappa_cast, *(alpha1_ri + 7*inca1), *(pi1_ri + 7), *(pi1_ir + 7) ); \ PASTEMAC(ch,scal2j1es)( *kappa_cast, *(alpha1_ri + 8*inca1), *(pi1_ri + 8), *(pi1_ir + 8) ); \ PASTEMAC(ch,scal2j1es)( *kappa_cast, *(alpha1_ri + 9*inca1), *(pi1_ri + 9), *(pi1_ir + 9) ); \ PASTEMAC(ch,scal2j1es)( *kappa_cast, *(alpha1_ri +10*inca1), *(pi1_ri +10), *(pi1_ir +10) ); \ PASTEMAC(ch,scal2j1es)( *kappa_cast, *(alpha1_ri +11*inca1), *(pi1_ri +11), *(pi1_ir +11) ); \ PASTEMAC(ch,scal2j1es)( *kappa_cast, *(alpha1_ri +12*inca1), *(pi1_ri +12), *(pi1_ir +12) ); \ PASTEMAC(ch,scal2j1es)( *kappa_cast, *(alpha1_ri +13*inca1), *(pi1_ri +13), *(pi1_ir +13) ); \ \ alpha1_ri += lda1; \ pi1_ri += ldp1; \ pi1_ir += ldp1; \ } \ } \ else \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,scal21es)( *kappa_cast, *(alpha1_ri + 0*inca1), *(pi1_ri + 0), *(pi1_ir + 0) ); \ PASTEMAC(ch,scal21es)( *kappa_cast, *(alpha1_ri + 1*inca1), *(pi1_ri + 1), *(pi1_ir + 1) ); \ PASTEMAC(ch,scal21es)( *kappa_cast, *(alpha1_ri + 2*inca1), *(pi1_ri + 2), *(pi1_ir + 2) ); \ PASTEMAC(ch,scal21es)( *kappa_cast, *(alpha1_ri + 3*inca1), *(pi1_ri + 3), *(pi1_ir + 3) ); \ PASTEMAC(ch,scal21es)( *kappa_cast, *(alpha1_ri + 4*inca1), *(pi1_ri + 4), *(pi1_ir + 4) ); \ PASTEMAC(ch,scal21es)( *kappa_cast, *(alpha1_ri + 5*inca1), *(pi1_ri + 5), *(pi1_ir + 5) ); \ PASTEMAC(ch,scal21es)( *kappa_cast, *(alpha1_ri + 6*inca1), *(pi1_ri + 6), *(pi1_ir + 6) ); \ PASTEMAC(ch,scal21es)( *kappa_cast, *(alpha1_ri + 7*inca1), *(pi1_ri + 7), *(pi1_ir + 7) ); \ PASTEMAC(ch,scal21es)( *kappa_cast, *(alpha1_ri + 8*inca1), *(pi1_ri + 8), *(pi1_ir + 8) ); \ PASTEMAC(ch,scal21es)( *kappa_cast, *(alpha1_ri + 9*inca1), *(pi1_ri + 9), *(pi1_ir + 9) ); \ PASTEMAC(ch,scal21es)( *kappa_cast, *(alpha1_ri +10*inca1), *(pi1_ri +10), *(pi1_ir +10) ); \ PASTEMAC(ch,scal21es)( *kappa_cast, *(alpha1_ri +11*inca1), *(pi1_ri +11), *(pi1_ir +11) ); \ PASTEMAC(ch,scal21es)( *kappa_cast, *(alpha1_ri +12*inca1), *(pi1_ri +12), *(pi1_ir +12) ); \ PASTEMAC(ch,scal21es)( *kappa_cast, *(alpha1_ri +13*inca1), *(pi1_ri +13), *(pi1_ir +13) ); \ \ alpha1_ri += lda1; \ pi1_ri += ldp1; \ pi1_ir += ldp1; \ } \ } \ } \ } \ else /* if ( bli_is_1r_packed( schema ) ) */ \ { \ const inc_t inca2 = 2 * inca; \ const inc_t lda2 = 2 * lda; \ const inc_t ldp2 = 2 * ldp; \ \ ctype* kappa_cast = kappa; \ ctype_r* restrict kappa_r = ( ctype_r* )kappa; \ ctype_r* restrict kappa_i = ( ctype_r* )kappa + 1; \ ctype_r* restrict alpha1_r = ( ctype_r* )a; \ ctype_r* restrict alpha1_i = ( ctype_r* )a + 1; \ ctype_r* restrict pi1_r = ( ctype_r* )p; \ ctype_r* restrict pi1_i = ( ctype_r* )p + ldp; \ \ if ( PASTEMAC(ch,eq1)( *kappa_cast ) ) \ { \ if ( bli_is_conj( conja ) ) \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,copyjris)( *(alpha1_r + 0*inca2), *(alpha1_i + 0*inca2), *(pi1_r + 0), *(pi1_i + 0) ); \ PASTEMAC(ch,copyjris)( *(alpha1_r + 1*inca2), *(alpha1_i + 1*inca2), *(pi1_r + 1), *(pi1_i + 1) ); \ PASTEMAC(ch,copyjris)( *(alpha1_r + 2*inca2), *(alpha1_i + 2*inca2), *(pi1_r + 2), *(pi1_i + 2) ); \ PASTEMAC(ch,copyjris)( *(alpha1_r + 3*inca2), *(alpha1_i + 3*inca2), *(pi1_r + 3), *(pi1_i + 3) ); \ PASTEMAC(ch,copyjris)( *(alpha1_r + 4*inca2), *(alpha1_i + 4*inca2), *(pi1_r + 4), *(pi1_i + 4) ); \ PASTEMAC(ch,copyjris)( *(alpha1_r + 5*inca2), *(alpha1_i + 5*inca2), *(pi1_r + 5), *(pi1_i + 5) ); \ PASTEMAC(ch,copyjris)( *(alpha1_r + 6*inca2), *(alpha1_i + 6*inca2), *(pi1_r + 6), *(pi1_i + 6) ); \ PASTEMAC(ch,copyjris)( *(alpha1_r + 7*inca2), *(alpha1_i + 7*inca2), *(pi1_r + 7), *(pi1_i + 7) ); \ PASTEMAC(ch,copyjris)( *(alpha1_r + 8*inca2), *(alpha1_i + 8*inca2), *(pi1_r + 8), *(pi1_i + 8) ); \ PASTEMAC(ch,copyjris)( *(alpha1_r + 9*inca2), *(alpha1_i + 9*inca2), *(pi1_r + 9), *(pi1_i + 9) ); \ PASTEMAC(ch,copyjris)( *(alpha1_r +10*inca2), *(alpha1_i +10*inca2), *(pi1_r +10), *(pi1_i +10) ); \ PASTEMAC(ch,copyjris)( *(alpha1_r +11*inca2), *(alpha1_i +11*inca2), *(pi1_r +11), *(pi1_i +11) ); \ PASTEMAC(ch,copyjris)( *(alpha1_r +12*inca2), *(alpha1_i +12*inca2), *(pi1_r +12), *(pi1_i +12) ); \ PASTEMAC(ch,copyjris)( *(alpha1_r +13*inca2), *(alpha1_i +13*inca2), *(pi1_r +13), *(pi1_i +13) ); \ \ alpha1_r += lda2; \ alpha1_i += lda2; \ pi1_r += ldp2; \ pi1_i += ldp2; \ } \ } \ else \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,copyris)( *(alpha1_r + 0*inca2), *(alpha1_i + 0*inca2), *(pi1_r + 0), *(pi1_i + 0) ); \ PASTEMAC(ch,copyris)( *(alpha1_r + 1*inca2), *(alpha1_i + 1*inca2), *(pi1_r + 1), *(pi1_i + 1) ); \ PASTEMAC(ch,copyris)( *(alpha1_r + 2*inca2), *(alpha1_i + 2*inca2), *(pi1_r + 2), *(pi1_i + 2) ); \ PASTEMAC(ch,copyris)( *(alpha1_r + 3*inca2), *(alpha1_i + 3*inca2), *(pi1_r + 3), *(pi1_i + 3) ); \ PASTEMAC(ch,copyris)( *(alpha1_r + 4*inca2), *(alpha1_i + 4*inca2), *(pi1_r + 4), *(pi1_i + 4) ); \ PASTEMAC(ch,copyris)( *(alpha1_r + 5*inca2), *(alpha1_i + 5*inca2), *(pi1_r + 5), *(pi1_i + 5) ); \ PASTEMAC(ch,copyris)( *(alpha1_r + 6*inca2), *(alpha1_i + 6*inca2), *(pi1_r + 6), *(pi1_i + 6) ); \ PASTEMAC(ch,copyris)( *(alpha1_r + 7*inca2), *(alpha1_i + 7*inca2), *(pi1_r + 7), *(pi1_i + 7) ); \ PASTEMAC(ch,copyris)( *(alpha1_r + 8*inca2), *(alpha1_i + 8*inca2), *(pi1_r + 8), *(pi1_i + 8) ); \ PASTEMAC(ch,copyris)( *(alpha1_r + 9*inca2), *(alpha1_i + 9*inca2), *(pi1_r + 9), *(pi1_i + 9) ); \ PASTEMAC(ch,copyris)( *(alpha1_r +10*inca2), *(alpha1_i +10*inca2), *(pi1_r +10), *(pi1_i +10) ); \ PASTEMAC(ch,copyris)( *(alpha1_r +11*inca2), *(alpha1_i +11*inca2), *(pi1_r +11), *(pi1_i +11) ); \ PASTEMAC(ch,copyris)( *(alpha1_r +12*inca2), *(alpha1_i +12*inca2), *(pi1_r +12), *(pi1_i +12) ); \ PASTEMAC(ch,copyris)( *(alpha1_r +13*inca2), *(alpha1_i +13*inca2), *(pi1_r +13), *(pi1_i +13) ); \ \ alpha1_r += lda2; \ alpha1_i += lda2; \ pi1_r += ldp2; \ pi1_i += ldp2; \ } \ } \ } \ else \ { \ if ( bli_is_conj( conja ) ) \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,scal2jris)( *kappa_r, *kappa_i, *(alpha1_r + 0*inca2), *(alpha1_i + 0*inca2), *(pi1_r + 0), *(pi1_i + 0) ); \ PASTEMAC(ch,scal2jris)( *kappa_r, *kappa_i, *(alpha1_r + 1*inca2), *(alpha1_i + 1*inca2), *(pi1_r + 1), *(pi1_i + 1) ); \ PASTEMAC(ch,scal2jris)( *kappa_r, *kappa_i, *(alpha1_r + 2*inca2), *(alpha1_i + 2*inca2), *(pi1_r + 2), *(pi1_i + 2) ); \ PASTEMAC(ch,scal2jris)( *kappa_r, *kappa_i, *(alpha1_r + 3*inca2), *(alpha1_i + 3*inca2), *(pi1_r + 3), *(pi1_i + 3) ); \ PASTEMAC(ch,scal2jris)( *kappa_r, *kappa_i, *(alpha1_r + 4*inca2), *(alpha1_i + 4*inca2), *(pi1_r + 4), *(pi1_i + 4) ); \ PASTEMAC(ch,scal2jris)( *kappa_r, *kappa_i, *(alpha1_r + 5*inca2), *(alpha1_i + 5*inca2), *(pi1_r + 5), *(pi1_i + 5) ); \ PASTEMAC(ch,scal2jris)( *kappa_r, *kappa_i, *(alpha1_r + 6*inca2), *(alpha1_i + 6*inca2), *(pi1_r + 6), *(pi1_i + 6) ); \ PASTEMAC(ch,scal2jris)( *kappa_r, *kappa_i, *(alpha1_r + 7*inca2), *(alpha1_i + 7*inca2), *(pi1_r + 7), *(pi1_i + 7) ); \ PASTEMAC(ch,scal2jris)( *kappa_r, *kappa_i, *(alpha1_r + 8*inca2), *(alpha1_i + 8*inca2), *(pi1_r + 8), *(pi1_i + 8) ); \ PASTEMAC(ch,scal2jris)( *kappa_r, *kappa_i, *(alpha1_r + 9*inca2), *(alpha1_i + 9*inca2), *(pi1_r + 9), *(pi1_i + 9) ); \ PASTEMAC(ch,scal2jris)( *kappa_r, *kappa_i, *(alpha1_r +10*inca2), *(alpha1_i +10*inca2), *(pi1_r +10), *(pi1_i +10) ); \ PASTEMAC(ch,scal2jris)( *kappa_r, *kappa_i, *(alpha1_r +11*inca2), *(alpha1_i +11*inca2), *(pi1_r +11), *(pi1_i +11) ); \ PASTEMAC(ch,scal2jris)( *kappa_r, *kappa_i, *(alpha1_r +12*inca2), *(alpha1_i +12*inca2), *(pi1_r +12), *(pi1_i +12) ); \ PASTEMAC(ch,scal2jris)( *kappa_r, *kappa_i, *(alpha1_r +13*inca2), *(alpha1_i +13*inca2), *(pi1_r +13), *(pi1_i +13) ); \ \ alpha1_r += lda2; \ alpha1_i += lda2; \ pi1_r += ldp2; \ pi1_i += ldp2; \ } \ } \ else \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,scal2ris)( *kappa_r, *kappa_i, *(alpha1_r + 0*inca2), *(alpha1_i + 0*inca2), *(pi1_r + 0), *(pi1_i + 0) ); \ PASTEMAC(ch,scal2ris)( *kappa_r, *kappa_i, *(alpha1_r + 1*inca2), *(alpha1_i + 1*inca2), *(pi1_r + 1), *(pi1_i + 1) ); \ PASTEMAC(ch,scal2ris)( *kappa_r, *kappa_i, *(alpha1_r + 2*inca2), *(alpha1_i + 2*inca2), *(pi1_r + 2), *(pi1_i + 2) ); \ PASTEMAC(ch,scal2ris)( *kappa_r, *kappa_i, *(alpha1_r + 3*inca2), *(alpha1_i + 3*inca2), *(pi1_r + 3), *(pi1_i + 3) ); \ PASTEMAC(ch,scal2ris)( *kappa_r, *kappa_i, *(alpha1_r + 4*inca2), *(alpha1_i + 4*inca2), *(pi1_r + 4), *(pi1_i + 4) ); \ PASTEMAC(ch,scal2ris)( *kappa_r, *kappa_i, *(alpha1_r + 5*inca2), *(alpha1_i + 5*inca2), *(pi1_r + 5), *(pi1_i + 5) ); \ PASTEMAC(ch,scal2ris)( *kappa_r, *kappa_i, *(alpha1_r + 6*inca2), *(alpha1_i + 6*inca2), *(pi1_r + 6), *(pi1_i + 6) ); \ PASTEMAC(ch,scal2ris)( *kappa_r, *kappa_i, *(alpha1_r + 7*inca2), *(alpha1_i + 7*inca2), *(pi1_r + 7), *(pi1_i + 7) ); \ PASTEMAC(ch,scal2ris)( *kappa_r, *kappa_i, *(alpha1_r + 8*inca2), *(alpha1_i + 8*inca2), *(pi1_r + 8), *(pi1_i + 8) ); \ PASTEMAC(ch,scal2ris)( *kappa_r, *kappa_i, *(alpha1_r + 9*inca2), *(alpha1_i + 9*inca2), *(pi1_r + 9), *(pi1_i + 9) ); \ PASTEMAC(ch,scal2ris)( *kappa_r, *kappa_i, *(alpha1_r +10*inca2), *(alpha1_i +10*inca2), *(pi1_r +10), *(pi1_i +10) ); \ PASTEMAC(ch,scal2ris)( *kappa_r, *kappa_i, *(alpha1_r +11*inca2), *(alpha1_i +11*inca2), *(pi1_r +11), *(pi1_i +11) ); \ PASTEMAC(ch,scal2ris)( *kappa_r, *kappa_i, *(alpha1_r +12*inca2), *(alpha1_i +12*inca2), *(pi1_r +12), *(pi1_i +12) ); \ PASTEMAC(ch,scal2ris)( *kappa_r, *kappa_i, *(alpha1_r +13*inca2), *(alpha1_i +13*inca2), *(pi1_r +13), *(pi1_i +13) ); \ \ alpha1_r += lda2; \ alpha1_i += lda2; \ pi1_r += ldp2; \ pi1_i += ldp2; \ } \ } \ } \ } \ } \ else /* if ( cdim < mnr ) */ \ { \ PASTEMAC(ch,scal21ms_mxn) \ ( \ schema, \ conja, \ cdim, \ n, \ kappa, \ a, inca, lda, \ p, 1, ldp, ldp \ ); \ \ /* if ( cdim < mnr ) */ \ { \ ctype* restrict zero = PASTEMAC(ch,0); \ const dim_t offm = cdim; \ const dim_t offn = 0; \ const dim_t m_edge = mnr - cdim; \ const dim_t n_edge = n_max; \ \ PASTEMAC(ch,set1ms_mxn) \ ( \ schema, \ offm, \ offn, \ m_edge, \ n_edge, \ zero, \ p, 1, ldp, ldp \ ); \ } \ } \ \ if ( n < n_max ) \ { \ ctype* restrict zero = PASTEMAC(ch,0); \ const dim_t offm = 0; \ const dim_t offn = n; \ const dim_t m_edge = mnr; \ const dim_t n_edge = n_max - n; \ \ PASTEMAC(ch,set1ms_mxn) \ ( \ schema, \ offm, \ offn, \ m_edge, \ n_edge, \ zero, \ p, 1, ldp, ldp \ ); \ } \ } INSERT_GENTFUNCCO_BASIC3( packm_14xk_1er, 14, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX ) #undef GENTFUNCCO #define GENTFUNCCO( ctype, ctype_r, ch, chr, opname, mnr, arch, suf ) \ \ void PASTEMAC3(ch,opname,arch,suf) \ ( \ conj_t conja, \ pack_t schema, \ dim_t cdim, \ dim_t n, \ dim_t n_max, \ ctype* restrict kappa, \ ctype* restrict a, inc_t inca, inc_t lda, \ ctype* restrict p, inc_t ldp, \ cntx_t* restrict cntx \ ) \ { \ if ( cdim == mnr ) \ { \ if ( bli_is_1e_packed( schema ) ) \ { \ const inc_t inca1 = inca; \ const inc_t lda1 = lda; \ const inc_t ldp1 = ldp; \ \ ctype* restrict kappa_cast = ( ctype* )kappa; \ ctype* restrict alpha1_ri = ( ctype* )a; \ ctype* restrict pi1_ri = ( ctype* )p; \ ctype* restrict pi1_ir = ( ctype* )p + ldp1/2; \ \ if ( PASTEMAC(ch,eq1)( *kappa_cast ) ) \ { \ if ( bli_is_conj( conja ) ) \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,copyj1es)( *(alpha1_ri + 0*inca1), *(pi1_ri + 0), *(pi1_ir + 0) ); \ PASTEMAC(ch,copyj1es)( *(alpha1_ri + 1*inca1), *(pi1_ri + 1), *(pi1_ir + 1) ); \ PASTEMAC(ch,copyj1es)( *(alpha1_ri + 2*inca1), *(pi1_ri + 2), *(pi1_ir + 2) ); \ PASTEMAC(ch,copyj1es)( *(alpha1_ri + 3*inca1), *(pi1_ri + 3), *(pi1_ir + 3) ); \ PASTEMAC(ch,copyj1es)( *(alpha1_ri + 4*inca1), *(pi1_ri + 4), *(pi1_ir + 4) ); \ PASTEMAC(ch,copyj1es)( *(alpha1_ri + 5*inca1), *(pi1_ri + 5), *(pi1_ir + 5) ); \ PASTEMAC(ch,copyj1es)( *(alpha1_ri + 6*inca1), *(pi1_ri + 6), *(pi1_ir + 6) ); \ PASTEMAC(ch,copyj1es)( *(alpha1_ri + 7*inca1), *(pi1_ri + 7), *(pi1_ir + 7) ); \ PASTEMAC(ch,copyj1es)( *(alpha1_ri + 8*inca1), *(pi1_ri + 8), *(pi1_ir + 8) ); \ PASTEMAC(ch,copyj1es)( *(alpha1_ri + 9*inca1), *(pi1_ri + 9), *(pi1_ir + 9) ); \ PASTEMAC(ch,copyj1es)( *(alpha1_ri +10*inca1), *(pi1_ri +10), *(pi1_ir +10) ); \ PASTEMAC(ch,copyj1es)( *(alpha1_ri +11*inca1), *(pi1_ri +11), *(pi1_ir +11) ); \ PASTEMAC(ch,copyj1es)( *(alpha1_ri +12*inca1), *(pi1_ri +12), *(pi1_ir +12) ); \ PASTEMAC(ch,copyj1es)( *(alpha1_ri +13*inca1), *(pi1_ri +13), *(pi1_ir +13) ); \ PASTEMAC(ch,copyj1es)( *(alpha1_ri +14*inca1), *(pi1_ri +14), *(pi1_ir +14) ); \ PASTEMAC(ch,copyj1es)( *(alpha1_ri +15*inca1), *(pi1_ri +15), *(pi1_ir +15) ); \ \ alpha1_ri += lda1; \ pi1_ri += ldp1; \ pi1_ir += ldp1; \ } \ } \ else \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,copy1es)( *(alpha1_ri + 0*inca1), *(pi1_ri + 0), *(pi1_ir + 0) ); \ PASTEMAC(ch,copy1es)( *(alpha1_ri + 1*inca1), *(pi1_ri + 1), *(pi1_ir + 1) ); \ PASTEMAC(ch,copy1es)( *(alpha1_ri + 2*inca1), *(pi1_ri + 2), *(pi1_ir + 2) ); \ PASTEMAC(ch,copy1es)( *(alpha1_ri + 3*inca1), *(pi1_ri + 3), *(pi1_ir + 3) ); \ PASTEMAC(ch,copy1es)( *(alpha1_ri + 4*inca1), *(pi1_ri + 4), *(pi1_ir + 4) ); \ PASTEMAC(ch,copy1es)( *(alpha1_ri + 5*inca1), *(pi1_ri + 5), *(pi1_ir + 5) ); \ PASTEMAC(ch,copy1es)( *(alpha1_ri + 6*inca1), *(pi1_ri + 6), *(pi1_ir + 6) ); \ PASTEMAC(ch,copy1es)( *(alpha1_ri + 7*inca1), *(pi1_ri + 7), *(pi1_ir + 7) ); \ PASTEMAC(ch,copy1es)( *(alpha1_ri + 8*inca1), *(pi1_ri + 8), *(pi1_ir + 8) ); \ PASTEMAC(ch,copy1es)( *(alpha1_ri + 9*inca1), *(pi1_ri + 9), *(pi1_ir + 9) ); \ PASTEMAC(ch,copy1es)( *(alpha1_ri +10*inca1), *(pi1_ri +10), *(pi1_ir +10) ); \ PASTEMAC(ch,copy1es)( *(alpha1_ri +11*inca1), *(pi1_ri +11), *(pi1_ir +11) ); \ PASTEMAC(ch,copy1es)( *(alpha1_ri +12*inca1), *(pi1_ri +12), *(pi1_ir +12) ); \ PASTEMAC(ch,copy1es)( *(alpha1_ri +13*inca1), *(pi1_ri +13), *(pi1_ir +13) ); \ PASTEMAC(ch,copy1es)( *(alpha1_ri +14*inca1), *(pi1_ri +14), *(pi1_ir +14) ); \ PASTEMAC(ch,copy1es)( *(alpha1_ri +15*inca1), *(pi1_ri +15), *(pi1_ir +15) ); \ \ alpha1_ri += lda1; \ pi1_ri += ldp1; \ pi1_ir += ldp1; \ } \ } \ } \ else \ { \ if ( bli_is_conj( conja ) ) \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,scal2j1es)( *kappa_cast, *(alpha1_ri + 0*inca1), *(pi1_ri + 0), *(pi1_ir + 0) ); \ PASTEMAC(ch,scal2j1es)( *kappa_cast, *(alpha1_ri + 1*inca1), *(pi1_ri + 1), *(pi1_ir + 1) ); \ PASTEMAC(ch,scal2j1es)( *kappa_cast, *(alpha1_ri + 2*inca1), *(pi1_ri + 2), *(pi1_ir + 2) ); \ PASTEMAC(ch,scal2j1es)( *kappa_cast, *(alpha1_ri + 3*inca1), *(pi1_ri + 3), *(pi1_ir + 3) ); \ PASTEMAC(ch,scal2j1es)( *kappa_cast, *(alpha1_ri + 4*inca1), *(pi1_ri + 4), *(pi1_ir + 4) ); \ PASTEMAC(ch,scal2j1es)( *kappa_cast, *(alpha1_ri + 5*inca1), *(pi1_ri + 5), *(pi1_ir + 5) ); \ PASTEMAC(ch,scal2j1es)( *kappa_cast, *(alpha1_ri + 6*inca1), *(pi1_ri + 6), *(pi1_ir + 6) ); \ PASTEMAC(ch,scal2j1es)( *kappa_cast, *(alpha1_ri + 7*inca1), *(pi1_ri + 7), *(pi1_ir + 7) ); \ PASTEMAC(ch,scal2j1es)( *kappa_cast, *(alpha1_ri + 8*inca1), *(pi1_ri + 8), *(pi1_ir + 8) ); \ PASTEMAC(ch,scal2j1es)( *kappa_cast, *(alpha1_ri + 9*inca1), *(pi1_ri + 9), *(pi1_ir + 9) ); \ PASTEMAC(ch,scal2j1es)( *kappa_cast, *(alpha1_ri +10*inca1), *(pi1_ri +10), *(pi1_ir +10) ); \ PASTEMAC(ch,scal2j1es)( *kappa_cast, *(alpha1_ri +11*inca1), *(pi1_ri +11), *(pi1_ir +11) ); \ PASTEMAC(ch,scal2j1es)( *kappa_cast, *(alpha1_ri +12*inca1), *(pi1_ri +12), *(pi1_ir +12) ); \ PASTEMAC(ch,scal2j1es)( *kappa_cast, *(alpha1_ri +13*inca1), *(pi1_ri +13), *(pi1_ir +13) ); \ PASTEMAC(ch,scal2j1es)( *kappa_cast, *(alpha1_ri +14*inca1), *(pi1_ri +14), *(pi1_ir +14) ); \ PASTEMAC(ch,scal2j1es)( *kappa_cast, *(alpha1_ri +15*inca1), *(pi1_ri +15), *(pi1_ir +15) ); \ \ alpha1_ri += lda1; \ pi1_ri += ldp1; \ pi1_ir += ldp1; \ } \ } \ else \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,scal21es)( *kappa_cast, *(alpha1_ri + 0*inca1), *(pi1_ri + 0), *(pi1_ir + 0) ); \ PASTEMAC(ch,scal21es)( *kappa_cast, *(alpha1_ri + 1*inca1), *(pi1_ri + 1), *(pi1_ir + 1) ); \ PASTEMAC(ch,scal21es)( *kappa_cast, *(alpha1_ri + 2*inca1), *(pi1_ri + 2), *(pi1_ir + 2) ); \ PASTEMAC(ch,scal21es)( *kappa_cast, *(alpha1_ri + 3*inca1), *(pi1_ri + 3), *(pi1_ir + 3) ); \ PASTEMAC(ch,scal21es)( *kappa_cast, *(alpha1_ri + 4*inca1), *(pi1_ri + 4), *(pi1_ir + 4) ); \ PASTEMAC(ch,scal21es)( *kappa_cast, *(alpha1_ri + 5*inca1), *(pi1_ri + 5), *(pi1_ir + 5) ); \ PASTEMAC(ch,scal21es)( *kappa_cast, *(alpha1_ri + 6*inca1), *(pi1_ri + 6), *(pi1_ir + 6) ); \ PASTEMAC(ch,scal21es)( *kappa_cast, *(alpha1_ri + 7*inca1), *(pi1_ri + 7), *(pi1_ir + 7) ); \ PASTEMAC(ch,scal21es)( *kappa_cast, *(alpha1_ri + 8*inca1), *(pi1_ri + 8), *(pi1_ir + 8) ); \ PASTEMAC(ch,scal21es)( *kappa_cast, *(alpha1_ri + 9*inca1), *(pi1_ri + 9), *(pi1_ir + 9) ); \ PASTEMAC(ch,scal21es)( *kappa_cast, *(alpha1_ri +10*inca1), *(pi1_ri +10), *(pi1_ir +10) ); \ PASTEMAC(ch,scal21es)( *kappa_cast, *(alpha1_ri +11*inca1), *(pi1_ri +11), *(pi1_ir +11) ); \ PASTEMAC(ch,scal21es)( *kappa_cast, *(alpha1_ri +12*inca1), *(pi1_ri +12), *(pi1_ir +12) ); \ PASTEMAC(ch,scal21es)( *kappa_cast, *(alpha1_ri +13*inca1), *(pi1_ri +13), *(pi1_ir +13) ); \ PASTEMAC(ch,scal21es)( *kappa_cast, *(alpha1_ri +14*inca1), *(pi1_ri +14), *(pi1_ir +14) ); \ PASTEMAC(ch,scal21es)( *kappa_cast, *(alpha1_ri +15*inca1), *(pi1_ri +15), *(pi1_ir +15) ); \ \ alpha1_ri += lda1; \ pi1_ri += ldp1; \ pi1_ir += ldp1; \ } \ } \ } \ } \ else /* if ( bli_is_1r_packed( schema ) ) */ \ { \ const inc_t inca2 = 2 * inca; \ const inc_t lda2 = 2 * lda; \ const inc_t ldp2 = 2 * ldp; \ \ ctype* kappa_cast = kappa; \ ctype_r* restrict kappa_r = ( ctype_r* )kappa; \ ctype_r* restrict kappa_i = ( ctype_r* )kappa + 1; \ ctype_r* restrict alpha1_r = ( ctype_r* )a; \ ctype_r* restrict alpha1_i = ( ctype_r* )a + 1; \ ctype_r* restrict pi1_r = ( ctype_r* )p; \ ctype_r* restrict pi1_i = ( ctype_r* )p + ldp; \ \ if ( PASTEMAC(ch,eq1)( *kappa_cast ) ) \ { \ if ( bli_is_conj( conja ) ) \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,copyjris)( *(alpha1_r + 0*inca2), *(alpha1_i + 0*inca2), *(pi1_r + 0), *(pi1_i + 0) ); \ PASTEMAC(ch,copyjris)( *(alpha1_r + 1*inca2), *(alpha1_i + 1*inca2), *(pi1_r + 1), *(pi1_i + 1) ); \ PASTEMAC(ch,copyjris)( *(alpha1_r + 2*inca2), *(alpha1_i + 2*inca2), *(pi1_r + 2), *(pi1_i + 2) ); \ PASTEMAC(ch,copyjris)( *(alpha1_r + 3*inca2), *(alpha1_i + 3*inca2), *(pi1_r + 3), *(pi1_i + 3) ); \ PASTEMAC(ch,copyjris)( *(alpha1_r + 4*inca2), *(alpha1_i + 4*inca2), *(pi1_r + 4), *(pi1_i + 4) ); \ PASTEMAC(ch,copyjris)( *(alpha1_r + 5*inca2), *(alpha1_i + 5*inca2), *(pi1_r + 5), *(pi1_i + 5) ); \ PASTEMAC(ch,copyjris)( *(alpha1_r + 6*inca2), *(alpha1_i + 6*inca2), *(pi1_r + 6), *(pi1_i + 6) ); \ PASTEMAC(ch,copyjris)( *(alpha1_r + 7*inca2), *(alpha1_i + 7*inca2), *(pi1_r + 7), *(pi1_i + 7) ); \ PASTEMAC(ch,copyjris)( *(alpha1_r + 8*inca2), *(alpha1_i + 8*inca2), *(pi1_r + 8), *(pi1_i + 8) ); \ PASTEMAC(ch,copyjris)( *(alpha1_r + 9*inca2), *(alpha1_i + 9*inca2), *(pi1_r + 9), *(pi1_i + 9) ); \ PASTEMAC(ch,copyjris)( *(alpha1_r +10*inca2), *(alpha1_i +10*inca2), *(pi1_r +10), *(pi1_i +10) ); \ PASTEMAC(ch,copyjris)( *(alpha1_r +11*inca2), *(alpha1_i +11*inca2), *(pi1_r +11), *(pi1_i +11) ); \ PASTEMAC(ch,copyjris)( *(alpha1_r +12*inca2), *(alpha1_i +12*inca2), *(pi1_r +12), *(pi1_i +12) ); \ PASTEMAC(ch,copyjris)( *(alpha1_r +13*inca2), *(alpha1_i +13*inca2), *(pi1_r +13), *(pi1_i +13) ); \ PASTEMAC(ch,copyjris)( *(alpha1_r +14*inca2), *(alpha1_i +14*inca2), *(pi1_r +14), *(pi1_i +14) ); \ PASTEMAC(ch,copyjris)( *(alpha1_r +15*inca2), *(alpha1_i +15*inca2), *(pi1_r +15), *(pi1_i +15) ); \ \ alpha1_r += lda2; \ alpha1_i += lda2; \ pi1_r += ldp2; \ pi1_i += ldp2; \ } \ } \ else \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,copyris)( *(alpha1_r + 0*inca2), *(alpha1_i + 0*inca2), *(pi1_r + 0), *(pi1_i + 0) ); \ PASTEMAC(ch,copyris)( *(alpha1_r + 1*inca2), *(alpha1_i + 1*inca2), *(pi1_r + 1), *(pi1_i + 1) ); \ PASTEMAC(ch,copyris)( *(alpha1_r + 2*inca2), *(alpha1_i + 2*inca2), *(pi1_r + 2), *(pi1_i + 2) ); \ PASTEMAC(ch,copyris)( *(alpha1_r + 3*inca2), *(alpha1_i + 3*inca2), *(pi1_r + 3), *(pi1_i + 3) ); \ PASTEMAC(ch,copyris)( *(alpha1_r + 4*inca2), *(alpha1_i + 4*inca2), *(pi1_r + 4), *(pi1_i + 4) ); \ PASTEMAC(ch,copyris)( *(alpha1_r + 5*inca2), *(alpha1_i + 5*inca2), *(pi1_r + 5), *(pi1_i + 5) ); \ PASTEMAC(ch,copyris)( *(alpha1_r + 6*inca2), *(alpha1_i + 6*inca2), *(pi1_r + 6), *(pi1_i + 6) ); \ PASTEMAC(ch,copyris)( *(alpha1_r + 7*inca2), *(alpha1_i + 7*inca2), *(pi1_r + 7), *(pi1_i + 7) ); \ PASTEMAC(ch,copyris)( *(alpha1_r + 8*inca2), *(alpha1_i + 8*inca2), *(pi1_r + 8), *(pi1_i + 8) ); \ PASTEMAC(ch,copyris)( *(alpha1_r + 9*inca2), *(alpha1_i + 9*inca2), *(pi1_r + 9), *(pi1_i + 9) ); \ PASTEMAC(ch,copyris)( *(alpha1_r +10*inca2), *(alpha1_i +10*inca2), *(pi1_r +10), *(pi1_i +10) ); \ PASTEMAC(ch,copyris)( *(alpha1_r +11*inca2), *(alpha1_i +11*inca2), *(pi1_r +11), *(pi1_i +11) ); \ PASTEMAC(ch,copyris)( *(alpha1_r +12*inca2), *(alpha1_i +12*inca2), *(pi1_r +12), *(pi1_i +12) ); \ PASTEMAC(ch,copyris)( *(alpha1_r +13*inca2), *(alpha1_i +13*inca2), *(pi1_r +13), *(pi1_i +13) ); \ PASTEMAC(ch,copyris)( *(alpha1_r +14*inca2), *(alpha1_i +14*inca2), *(pi1_r +14), *(pi1_i +14) ); \ PASTEMAC(ch,copyris)( *(alpha1_r +15*inca2), *(alpha1_i +15*inca2), *(pi1_r +15), *(pi1_i +15) ); \ \ alpha1_r += lda2; \ alpha1_i += lda2; \ pi1_r += ldp2; \ pi1_i += ldp2; \ } \ } \ } \ else \ { \ if ( bli_is_conj( conja ) ) \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,scal2jris)( *kappa_r, *kappa_i, *(alpha1_r + 0*inca2), *(alpha1_i + 0*inca2), *(pi1_r + 0), *(pi1_i + 0) ); \ PASTEMAC(ch,scal2jris)( *kappa_r, *kappa_i, *(alpha1_r + 1*inca2), *(alpha1_i + 1*inca2), *(pi1_r + 1), *(pi1_i + 1) ); \ PASTEMAC(ch,scal2jris)( *kappa_r, *kappa_i, *(alpha1_r + 2*inca2), *(alpha1_i + 2*inca2), *(pi1_r + 2), *(pi1_i + 2) ); \ PASTEMAC(ch,scal2jris)( *kappa_r, *kappa_i, *(alpha1_r + 3*inca2), *(alpha1_i + 3*inca2), *(pi1_r + 3), *(pi1_i + 3) ); \ PASTEMAC(ch,scal2jris)( *kappa_r, *kappa_i, *(alpha1_r + 4*inca2), *(alpha1_i + 4*inca2), *(pi1_r + 4), *(pi1_i + 4) ); \ PASTEMAC(ch,scal2jris)( *kappa_r, *kappa_i, *(alpha1_r + 5*inca2), *(alpha1_i + 5*inca2), *(pi1_r + 5), *(pi1_i + 5) ); \ PASTEMAC(ch,scal2jris)( *kappa_r, *kappa_i, *(alpha1_r + 6*inca2), *(alpha1_i + 6*inca2), *(pi1_r + 6), *(pi1_i + 6) ); \ PASTEMAC(ch,scal2jris)( *kappa_r, *kappa_i, *(alpha1_r + 7*inca2), *(alpha1_i + 7*inca2), *(pi1_r + 7), *(pi1_i + 7) ); \ PASTEMAC(ch,scal2jris)( *kappa_r, *kappa_i, *(alpha1_r + 8*inca2), *(alpha1_i + 8*inca2), *(pi1_r + 8), *(pi1_i + 8) ); \ PASTEMAC(ch,scal2jris)( *kappa_r, *kappa_i, *(alpha1_r + 9*inca2), *(alpha1_i + 9*inca2), *(pi1_r + 9), *(pi1_i + 9) ); \ PASTEMAC(ch,scal2jris)( *kappa_r, *kappa_i, *(alpha1_r +10*inca2), *(alpha1_i +10*inca2), *(pi1_r +10), *(pi1_i +10) ); \ PASTEMAC(ch,scal2jris)( *kappa_r, *kappa_i, *(alpha1_r +11*inca2), *(alpha1_i +11*inca2), *(pi1_r +11), *(pi1_i +11) ); \ PASTEMAC(ch,scal2jris)( *kappa_r, *kappa_i, *(alpha1_r +12*inca2), *(alpha1_i +12*inca2), *(pi1_r +12), *(pi1_i +12) ); \ PASTEMAC(ch,scal2jris)( *kappa_r, *kappa_i, *(alpha1_r +13*inca2), *(alpha1_i +13*inca2), *(pi1_r +13), *(pi1_i +13) ); \ PASTEMAC(ch,scal2jris)( *kappa_r, *kappa_i, *(alpha1_r +14*inca2), *(alpha1_i +14*inca2), *(pi1_r +14), *(pi1_i +14) ); \ PASTEMAC(ch,scal2jris)( *kappa_r, *kappa_i, *(alpha1_r +15*inca2), *(alpha1_i +15*inca2), *(pi1_r +15), *(pi1_i +15) ); \ \ alpha1_r += lda2; \ alpha1_i += lda2; \ pi1_r += ldp2; \ pi1_i += ldp2; \ } \ } \ else \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,scal2ris)( *kappa_r, *kappa_i, *(alpha1_r + 0*inca2), *(alpha1_i + 0*inca2), *(pi1_r + 0), *(pi1_i + 0) ); \ PASTEMAC(ch,scal2ris)( *kappa_r, *kappa_i, *(alpha1_r + 1*inca2), *(alpha1_i + 1*inca2), *(pi1_r + 1), *(pi1_i + 1) ); \ PASTEMAC(ch,scal2ris)( *kappa_r, *kappa_i, *(alpha1_r + 2*inca2), *(alpha1_i + 2*inca2), *(pi1_r + 2), *(pi1_i + 2) ); \ PASTEMAC(ch,scal2ris)( *kappa_r, *kappa_i, *(alpha1_r + 3*inca2), *(alpha1_i + 3*inca2), *(pi1_r + 3), *(pi1_i + 3) ); \ PASTEMAC(ch,scal2ris)( *kappa_r, *kappa_i, *(alpha1_r + 4*inca2), *(alpha1_i + 4*inca2), *(pi1_r + 4), *(pi1_i + 4) ); \ PASTEMAC(ch,scal2ris)( *kappa_r, *kappa_i, *(alpha1_r + 5*inca2), *(alpha1_i + 5*inca2), *(pi1_r + 5), *(pi1_i + 5) ); \ PASTEMAC(ch,scal2ris)( *kappa_r, *kappa_i, *(alpha1_r + 6*inca2), *(alpha1_i + 6*inca2), *(pi1_r + 6), *(pi1_i + 6) ); \ PASTEMAC(ch,scal2ris)( *kappa_r, *kappa_i, *(alpha1_r + 7*inca2), *(alpha1_i + 7*inca2), *(pi1_r + 7), *(pi1_i + 7) ); \ PASTEMAC(ch,scal2ris)( *kappa_r, *kappa_i, *(alpha1_r + 8*inca2), *(alpha1_i + 8*inca2), *(pi1_r + 8), *(pi1_i + 8) ); \ PASTEMAC(ch,scal2ris)( *kappa_r, *kappa_i, *(alpha1_r + 9*inca2), *(alpha1_i + 9*inca2), *(pi1_r + 9), *(pi1_i + 9) ); \ PASTEMAC(ch,scal2ris)( *kappa_r, *kappa_i, *(alpha1_r +10*inca2), *(alpha1_i +10*inca2), *(pi1_r +10), *(pi1_i +10) ); \ PASTEMAC(ch,scal2ris)( *kappa_r, *kappa_i, *(alpha1_r +11*inca2), *(alpha1_i +11*inca2), *(pi1_r +11), *(pi1_i +11) ); \ PASTEMAC(ch,scal2ris)( *kappa_r, *kappa_i, *(alpha1_r +12*inca2), *(alpha1_i +12*inca2), *(pi1_r +12), *(pi1_i +12) ); \ PASTEMAC(ch,scal2ris)( *kappa_r, *kappa_i, *(alpha1_r +13*inca2), *(alpha1_i +13*inca2), *(pi1_r +13), *(pi1_i +13) ); \ PASTEMAC(ch,scal2ris)( *kappa_r, *kappa_i, *(alpha1_r +14*inca2), *(alpha1_i +14*inca2), *(pi1_r +14), *(pi1_i +14) ); \ PASTEMAC(ch,scal2ris)( *kappa_r, *kappa_i, *(alpha1_r +15*inca2), *(alpha1_i +15*inca2), *(pi1_r +15), *(pi1_i +15) ); \ \ alpha1_r += lda2; \ alpha1_i += lda2; \ pi1_r += ldp2; \ pi1_i += ldp2; \ } \ } \ } \ } \ } \ else /* if ( cdim < mnr ) */ \ { \ PASTEMAC(ch,scal21ms_mxn) \ ( \ schema, \ conja, \ cdim, \ n, \ kappa, \ a, inca, lda, \ p, 1, ldp, ldp \ ); \ \ /* if ( cdim < mnr ) */ \ { \ ctype* restrict zero = PASTEMAC(ch,0); \ const dim_t offm = cdim; \ const dim_t offn = 0; \ const dim_t m_edge = mnr - cdim; \ const dim_t n_edge = n_max; \ \ PASTEMAC(ch,set1ms_mxn) \ ( \ schema, \ offm, \ offn, \ m_edge, \ n_edge, \ zero, \ p, 1, ldp, ldp \ ); \ } \ } \ \ if ( n < n_max ) \ { \ ctype* restrict zero = PASTEMAC(ch,0); \ const dim_t offm = 0; \ const dim_t offn = n; \ const dim_t m_edge = mnr; \ const dim_t n_edge = n_max - n; \ \ PASTEMAC(ch,set1ms_mxn) \ ( \ schema, \ offm, \ offn, \ m_edge, \ n_edge, \ zero, \ p, 1, ldp, ldp \ ); \ } \ } INSERT_GENTFUNCCO_BASIC3( packm_16xk_1er, 16, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX ) blis-0.9.0/ref_kernels/1m/bli_packm_cxk_bb_ref.c000066400000000000000000000565021422157504600215340ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // -- 6xk, duplication factor 2 ------------------------------------------------ #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, mnr, arch, suf ) \ \ void PASTEMAC3(ch,opname,arch,suf) \ ( \ conj_t conja, \ pack_t schema, \ dim_t cdim, \ dim_t n, \ dim_t n_max, \ ctype* restrict kappa, \ ctype* restrict a, inc_t inca, inc_t lda, \ ctype* restrict p, inc_t ldp, \ cntx_t* restrict cntx \ ) \ { \ ctype* restrict kappa_cast = kappa; \ ctype* restrict alpha1 = a; \ ctype* restrict pi1 = p; \ \ const dim_t dfac = 2; \ \ /* Handle the packing of B (column panel schemas) separately from packing of A (row panel schemas). */ \ if ( bli_is_col_packed( schema ) ) \ { \ if ( cdim == mnr ) \ { \ if ( PASTEMAC(ch,eq1)( *kappa_cast ) ) \ { \ if ( bli_is_conj( conja ) ) \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,copyjs)( *(alpha1 + 0*inca), *(pi1 + 0) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 0*inca), *(pi1 + 1) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 1*inca), *(pi1 + 2) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 1*inca), *(pi1 + 3) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 2*inca), *(pi1 + 4) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 2*inca), *(pi1 + 5) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 3*inca), *(pi1 + 6) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 3*inca), *(pi1 + 7) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 4*inca), *(pi1 + 8) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 4*inca), *(pi1 + 9) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 5*inca), *(pi1 + 10) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 5*inca), *(pi1 + 11) ); \ \ alpha1 += lda; \ pi1 += ldp; \ } \ } \ else /* if ( bli_is_noconj( conja ) ) */ \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,copys)( *(alpha1 + 0*inca), *(pi1 + 0) ); \ PASTEMAC(ch,copys)( *(alpha1 + 0*inca), *(pi1 + 1) ); \ PASTEMAC(ch,copys)( *(alpha1 + 1*inca), *(pi1 + 2) ); \ PASTEMAC(ch,copys)( *(alpha1 + 1*inca), *(pi1 + 3) ); \ PASTEMAC(ch,copys)( *(alpha1 + 2*inca), *(pi1 + 4) ); \ PASTEMAC(ch,copys)( *(alpha1 + 2*inca), *(pi1 + 5) ); \ PASTEMAC(ch,copys)( *(alpha1 + 3*inca), *(pi1 + 6) ); \ PASTEMAC(ch,copys)( *(alpha1 + 3*inca), *(pi1 + 7) ); \ PASTEMAC(ch,copys)( *(alpha1 + 4*inca), *(pi1 + 8) ); \ PASTEMAC(ch,copys)( *(alpha1 + 4*inca), *(pi1 + 9) ); \ PASTEMAC(ch,copys)( *(alpha1 + 5*inca), *(pi1 + 10) ); \ PASTEMAC(ch,copys)( *(alpha1 + 5*inca), *(pi1 + 11) ); \ \ alpha1 += lda; \ pi1 += ldp; \ } \ } \ } \ else /* if ( !PASTEMAC(ch,eq1)( *kappa_cast ) ) */ \ { \ if ( bli_is_conj( conja ) ) \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 0*inca), *(pi1 + 0) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 0*inca), *(pi1 + 1) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 1*inca), *(pi1 + 2) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 1*inca), *(pi1 + 3) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 2*inca), *(pi1 + 4) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 2*inca), *(pi1 + 5) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 3*inca), *(pi1 + 6) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 3*inca), *(pi1 + 7) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 4*inca), *(pi1 + 8) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 4*inca), *(pi1 + 9) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 5*inca), *(pi1 + 10) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 5*inca), *(pi1 + 11) ); \ \ alpha1 += lda; \ pi1 += ldp; \ } \ } \ else /* if ( bli_is_noconj( conja ) ) */ \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 0*inca), *(pi1 + 0) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 0*inca), *(pi1 + 1) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 1*inca), *(pi1 + 2) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 1*inca), *(pi1 + 3) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 2*inca), *(pi1 + 4) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 2*inca), *(pi1 + 5) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 3*inca), *(pi1 + 6) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 3*inca), *(pi1 + 7) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 4*inca), *(pi1 + 8) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 4*inca), *(pi1 + 9) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 5*inca), *(pi1 + 10) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 5*inca), *(pi1 + 11) ); \ \ alpha1 += lda; \ pi1 += ldp; \ } \ } \ } \ } \ else /* if ( cdim < mnr ) */ \ { \ PASTEMAC(ch,scal2bbs_mxn) \ ( \ conja, \ cdim, \ n, \ kappa, \ a, inca, lda, \ p, dfac, ldp \ ); \ \ /* if ( cdim < mnr ) */ \ { \ const dim_t i = cdim; \ const dim_t m_edge = mnr - cdim; \ const dim_t n_edge = n_max; \ ctype* restrict p_cast = p; \ ctype* restrict p_edge = p_cast + (i )*dfac; \ \ PASTEMAC(ch,set0bbs_mxn) \ ( \ m_edge, \ n_edge, \ p_edge, dfac, ldp \ ); \ } \ } \ \ if ( n < n_max ) \ { \ const dim_t j = n; \ const dim_t m_edge = mnr; \ const dim_t n_edge = n_max - n; \ ctype* restrict p_cast = p; \ ctype* restrict p_edge = p_cast + (j )*ldp; \ \ PASTEMAC(ch,set0bbs_mxn) \ ( \ m_edge, \ n_edge, \ p_edge, dfac, ldp \ ); \ } \ } \ else /* if ( bli_is_row_packed( schema ) ) */ \ { \ if ( cdim == mnr ) \ { \ if ( PASTEMAC(ch,eq1)( *kappa_cast ) ) \ { \ if ( bli_is_conj( conja ) ) \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,copyjs)( *(alpha1 + 0*inca), *(pi1 + 0) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 1*inca), *(pi1 + 1) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 2*inca), *(pi1 + 2) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 3*inca), *(pi1 + 3) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 4*inca), *(pi1 + 4) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 5*inca), *(pi1 + 5) ); \ \ alpha1 += lda; \ pi1 += ldp; \ } \ } \ else /* if ( bli_is_noconj( conja ) ) */ \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,copys)( *(alpha1 + 0*inca), *(pi1 + 0) ); \ PASTEMAC(ch,copys)( *(alpha1 + 1*inca), *(pi1 + 1) ); \ PASTEMAC(ch,copys)( *(alpha1 + 2*inca), *(pi1 + 2) ); \ PASTEMAC(ch,copys)( *(alpha1 + 3*inca), *(pi1 + 3) ); \ PASTEMAC(ch,copys)( *(alpha1 + 4*inca), *(pi1 + 4) ); \ PASTEMAC(ch,copys)( *(alpha1 + 5*inca), *(pi1 + 5) ); \ \ alpha1 += lda; \ pi1 += ldp; \ } \ } \ } \ else /* if ( !PASTEMAC(ch,eq1)( *kappa_cast ) ) */ \ { \ if ( bli_is_conj( conja ) ) \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 0*inca), *(pi1 + 0) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 1*inca), *(pi1 + 1) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 2*inca), *(pi1 + 2) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 3*inca), *(pi1 + 3) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 4*inca), *(pi1 + 4) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 5*inca), *(pi1 + 5) ); \ \ alpha1 += lda; \ pi1 += ldp; \ } \ } \ else /* if ( bli_is_noconj( conja ) ) */ \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 0*inca), *(pi1 + 0) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 1*inca), *(pi1 + 1) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 2*inca), *(pi1 + 2) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 3*inca), *(pi1 + 3) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 4*inca), *(pi1 + 4) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 5*inca), *(pi1 + 5) ); \ \ alpha1 += lda; \ pi1 += ldp; \ } \ } \ } \ } \ else /* if ( cdim < mnr ) */ \ { \ PASTEMAC(ch,scal2s_mxn) \ ( \ conja, \ cdim, \ n, \ kappa, \ a, inca, lda, \ p, 1, ldp \ ); \ \ /* if ( cdim < mnr ) */ \ { \ const dim_t i = cdim; \ const dim_t m_edge = mnr - cdim; \ const dim_t n_edge = n_max; \ ctype* restrict p_cast = p; \ ctype* restrict p_edge = p_cast + (i )*1; \ \ PASTEMAC(ch,set0s_mxn) \ ( \ m_edge, \ n_edge, \ p_edge, 1, ldp \ ); \ } \ } \ \ if ( n < n_max ) \ { \ const dim_t j = n; \ const dim_t m_edge = mnr; \ const dim_t n_edge = n_max - n; \ ctype* restrict p_cast = p; \ ctype* restrict p_edge = p_cast + (j )*ldp; \ \ PASTEMAC(ch,set0s_mxn) \ ( \ m_edge, \ n_edge, \ p_edge, 1, ldp \ ); \ } \ } \ } INSERT_GENTFUNC_BASIC3( packm_6xk_bb2, 6, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX ) // -- 6xk, duplication factor 4 ------------------------------------------------ #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, mnr, arch, suf ) \ \ void PASTEMAC3(ch,opname,arch,suf) \ ( \ conj_t conja, \ pack_t schema, \ dim_t cdim, \ dim_t n, \ dim_t n_max, \ ctype* restrict kappa, \ ctype* restrict a, inc_t inca, inc_t lda, \ ctype* restrict p, inc_t ldp, \ cntx_t* restrict cntx \ ) \ { \ ctype* restrict kappa_cast = kappa; \ ctype* restrict alpha1 = a; \ ctype* restrict pi1 = p; \ \ const dim_t dfac = 4; \ \ /* Handle the packing of B (column panel schemas) separately from packing of A (row panel schemas). */ \ if ( bli_is_col_packed( schema ) ) \ { \ if ( cdim == mnr ) \ { \ if ( PASTEMAC(ch,eq1)( *kappa_cast ) ) \ { \ if ( bli_is_conj( conja ) ) \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,copyjs)( *(alpha1 + 0*inca), *(pi1 + 0) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 0*inca), *(pi1 + 1) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 0*inca), *(pi1 + 2) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 0*inca), *(pi1 + 3) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 1*inca), *(pi1 + 4) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 1*inca), *(pi1 + 5) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 1*inca), *(pi1 + 6) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 1*inca), *(pi1 + 7) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 2*inca), *(pi1 + 8) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 2*inca), *(pi1 + 9) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 2*inca), *(pi1 + 10) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 2*inca), *(pi1 + 11) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 3*inca), *(pi1 + 12) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 3*inca), *(pi1 + 13) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 3*inca), *(pi1 + 14) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 3*inca), *(pi1 + 15) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 4*inca), *(pi1 + 16) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 4*inca), *(pi1 + 17) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 4*inca), *(pi1 + 18) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 4*inca), *(pi1 + 19) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 5*inca), *(pi1 + 20) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 5*inca), *(pi1 + 21) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 5*inca), *(pi1 + 22) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 5*inca), *(pi1 + 23) ); \ \ alpha1 += lda; \ pi1 += ldp; \ } \ } \ else /* if ( bli_is_noconj( conja ) ) */ \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,copys)( *(alpha1 + 0*inca), *(pi1 + 0) ); \ PASTEMAC(ch,copys)( *(alpha1 + 0*inca), *(pi1 + 1) ); \ PASTEMAC(ch,copys)( *(alpha1 + 0*inca), *(pi1 + 2) ); \ PASTEMAC(ch,copys)( *(alpha1 + 0*inca), *(pi1 + 3) ); \ PASTEMAC(ch,copys)( *(alpha1 + 1*inca), *(pi1 + 4) ); \ PASTEMAC(ch,copys)( *(alpha1 + 1*inca), *(pi1 + 5) ); \ PASTEMAC(ch,copys)( *(alpha1 + 1*inca), *(pi1 + 6) ); \ PASTEMAC(ch,copys)( *(alpha1 + 1*inca), *(pi1 + 7) ); \ PASTEMAC(ch,copys)( *(alpha1 + 2*inca), *(pi1 + 8) ); \ PASTEMAC(ch,copys)( *(alpha1 + 2*inca), *(pi1 + 9) ); \ PASTEMAC(ch,copys)( *(alpha1 + 2*inca), *(pi1 + 10) ); \ PASTEMAC(ch,copys)( *(alpha1 + 2*inca), *(pi1 + 11) ); \ PASTEMAC(ch,copys)( *(alpha1 + 3*inca), *(pi1 + 12) ); \ PASTEMAC(ch,copys)( *(alpha1 + 3*inca), *(pi1 + 13) ); \ PASTEMAC(ch,copys)( *(alpha1 + 3*inca), *(pi1 + 14) ); \ PASTEMAC(ch,copys)( *(alpha1 + 3*inca), *(pi1 + 15) ); \ PASTEMAC(ch,copys)( *(alpha1 + 4*inca), *(pi1 + 16) ); \ PASTEMAC(ch,copys)( *(alpha1 + 4*inca), *(pi1 + 17) ); \ PASTEMAC(ch,copys)( *(alpha1 + 4*inca), *(pi1 + 18) ); \ PASTEMAC(ch,copys)( *(alpha1 + 4*inca), *(pi1 + 19) ); \ PASTEMAC(ch,copys)( *(alpha1 + 5*inca), *(pi1 + 20) ); \ PASTEMAC(ch,copys)( *(alpha1 + 5*inca), *(pi1 + 21) ); \ PASTEMAC(ch,copys)( *(alpha1 + 5*inca), *(pi1 + 22) ); \ PASTEMAC(ch,copys)( *(alpha1 + 5*inca), *(pi1 + 23) ); \ \ alpha1 += lda; \ pi1 += ldp; \ } \ } \ } \ else /* if ( !PASTEMAC(ch,eq1)( *kappa_cast ) ) */ \ { \ if ( bli_is_conj( conja ) ) \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 0*inca), *(pi1 + 0) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 0*inca), *(pi1 + 1) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 0*inca), *(pi1 + 2) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 0*inca), *(pi1 + 3) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 1*inca), *(pi1 + 4) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 1*inca), *(pi1 + 5) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 1*inca), *(pi1 + 6) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 1*inca), *(pi1 + 7) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 2*inca), *(pi1 + 8) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 2*inca), *(pi1 + 9) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 2*inca), *(pi1 + 10) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 2*inca), *(pi1 + 11) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 3*inca), *(pi1 + 12) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 3*inca), *(pi1 + 13) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 3*inca), *(pi1 + 14) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 3*inca), *(pi1 + 15) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 4*inca), *(pi1 + 16) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 4*inca), *(pi1 + 17) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 4*inca), *(pi1 + 18) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 4*inca), *(pi1 + 19) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 5*inca), *(pi1 + 20) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 5*inca), *(pi1 + 21) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 5*inca), *(pi1 + 22) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 5*inca), *(pi1 + 23) ); \ \ alpha1 += lda; \ pi1 += ldp; \ } \ } \ else /* if ( bli_is_noconj( conja ) ) */ \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 0*inca), *(pi1 + 0) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 0*inca), *(pi1 + 1) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 0*inca), *(pi1 + 2) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 0*inca), *(pi1 + 3) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 1*inca), *(pi1 + 4) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 1*inca), *(pi1 + 5) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 1*inca), *(pi1 + 6) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 1*inca), *(pi1 + 7) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 2*inca), *(pi1 + 8) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 2*inca), *(pi1 + 9) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 2*inca), *(pi1 + 10) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 2*inca), *(pi1 + 11) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 3*inca), *(pi1 + 12) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 3*inca), *(pi1 + 13) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 3*inca), *(pi1 + 14) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 3*inca), *(pi1 + 15) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 4*inca), *(pi1 + 16) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 4*inca), *(pi1 + 17) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 4*inca), *(pi1 + 18) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 4*inca), *(pi1 + 19) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 5*inca), *(pi1 + 20) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 5*inca), *(pi1 + 21) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 5*inca), *(pi1 + 22) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 5*inca), *(pi1 + 23) ); \ \ alpha1 += lda; \ pi1 += ldp; \ } \ } \ } \ } \ else /* if ( cdim < mnr ) */ \ { \ PASTEMAC(ch,scal2bbs_mxn) \ ( \ conja, \ cdim, \ n, \ kappa, \ a, inca, lda, \ p, dfac, ldp \ ); \ \ /* if ( cdim < mnr ) */ \ { \ const dim_t i = cdim; \ const dim_t m_edge = mnr - cdim; \ const dim_t n_edge = n_max; \ ctype* restrict p_cast = p; \ ctype* restrict p_edge = p_cast + (i )*dfac; \ \ PASTEMAC(ch,set0bbs_mxn) \ ( \ m_edge, \ n_edge, \ p_edge, dfac, ldp \ ); \ } \ } \ \ if ( n < n_max ) \ { \ const dim_t j = n; \ const dim_t m_edge = mnr; \ const dim_t n_edge = n_max - n; \ ctype* restrict p_cast = p; \ ctype* restrict p_edge = p_cast + (j )*ldp; \ \ PASTEMAC(ch,set0bbs_mxn) \ ( \ m_edge, \ n_edge, \ p_edge, dfac, ldp \ ); \ } \ } \ else /* if ( bli_is_row_packed( schema ) ) */ \ { \ if ( cdim == mnr ) \ { \ if ( PASTEMAC(ch,eq1)( *kappa_cast ) ) \ { \ if ( bli_is_conj( conja ) ) \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,copyjs)( *(alpha1 + 0*inca), *(pi1 + 0) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 1*inca), *(pi1 + 1) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 2*inca), *(pi1 + 2) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 3*inca), *(pi1 + 3) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 4*inca), *(pi1 + 4) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 5*inca), *(pi1 + 5) ); \ \ alpha1 += lda; \ pi1 += ldp; \ } \ } \ else /* if ( bli_is_noconj( conja ) ) */ \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,copys)( *(alpha1 + 0*inca), *(pi1 + 0) ); \ PASTEMAC(ch,copys)( *(alpha1 + 1*inca), *(pi1 + 1) ); \ PASTEMAC(ch,copys)( *(alpha1 + 2*inca), *(pi1 + 2) ); \ PASTEMAC(ch,copys)( *(alpha1 + 3*inca), *(pi1 + 3) ); \ PASTEMAC(ch,copys)( *(alpha1 + 4*inca), *(pi1 + 4) ); \ PASTEMAC(ch,copys)( *(alpha1 + 5*inca), *(pi1 + 5) ); \ \ alpha1 += lda; \ pi1 += ldp; \ } \ } \ } \ else /* if ( !PASTEMAC(ch,eq1)( *kappa_cast ) ) */ \ { \ if ( bli_is_conj( conja ) ) \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 0*inca), *(pi1 + 0) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 1*inca), *(pi1 + 1) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 2*inca), *(pi1 + 2) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 3*inca), *(pi1 + 3) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 4*inca), *(pi1 + 4) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 5*inca), *(pi1 + 5) ); \ \ alpha1 += lda; \ pi1 += ldp; \ } \ } \ else /* if ( bli_is_noconj( conja ) ) */ \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 0*inca), *(pi1 + 0) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 1*inca), *(pi1 + 1) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 2*inca), *(pi1 + 2) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 3*inca), *(pi1 + 3) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 4*inca), *(pi1 + 4) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 5*inca), *(pi1 + 5) ); \ \ alpha1 += lda; \ pi1 += ldp; \ } \ } \ } \ } \ else /* if ( cdim < mnr ) */ \ { \ PASTEMAC(ch,scal2s_mxn) \ ( \ conja, \ cdim, \ n, \ kappa, \ a, inca, lda, \ p, 1, ldp \ ); \ \ /* if ( cdim < mnr ) */ \ { \ const dim_t i = cdim; \ const dim_t m_edge = mnr - cdim; \ const dim_t n_edge = n_max; \ ctype* restrict p_cast = p; \ ctype* restrict p_edge = p_cast + (i )*1; \ \ PASTEMAC(ch,set0s_mxn) \ ( \ m_edge, \ n_edge, \ p_edge, 1, ldp \ ); \ } \ } \ \ if ( n < n_max ) \ { \ const dim_t j = n; \ const dim_t m_edge = mnr; \ const dim_t n_edge = n_max - n; \ ctype* restrict p_cast = p; \ ctype* restrict p_edge = p_cast + (j )*ldp; \ \ PASTEMAC(ch,set0s_mxn) \ ( \ m_edge, \ n_edge, \ p_edge, 1, ldp \ ); \ } \ } \ } INSERT_GENTFUNC_BASIC3( packm_6xk_bb4, 6, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX ) blis-0.9.0/ref_kernels/1m/bli_packm_cxk_ref.c000066400000000000000000001543311422157504600210700ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, mnr, arch, suf ) \ \ void PASTEMAC3(ch,opname,arch,suf) \ ( \ conj_t conja, \ pack_t schema, \ dim_t cdim, \ dim_t n, \ dim_t n_max, \ ctype* restrict kappa, \ ctype* restrict a, inc_t inca, inc_t lda, \ ctype* restrict p, inc_t ldp, \ cntx_t* restrict cntx \ ) \ { \ ctype* restrict kappa_cast = kappa; \ ctype* restrict alpha1 = a; \ ctype* restrict pi1 = p; \ \ dim_t n_iter = n / 4; \ dim_t n_left = n % 4; \ \ if ( cdim == mnr ) \ { \ if ( PASTEMAC(ch,eq1)( *kappa_cast ) ) \ { \ if ( bli_is_conj( conja ) ) \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,copyjs)( *(alpha1 + 0*inca), *(pi1 + 0) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 1*inca), *(pi1 + 1) ); \ \ alpha1 += lda; \ pi1 += ldp; \ } \ } \ else \ { \ for ( ; n_iter != 0; --n_iter ) \ { \ PASTEMAC2(ch,ch,copys)( *(alpha1 + 0*inca + 0*lda), *(pi1 + 0 + 0*ldp) ); \ PASTEMAC2(ch,ch,copys)( *(alpha1 + 1*inca + 0*lda), *(pi1 + 1 + 0*ldp) ); \ \ PASTEMAC2(ch,ch,copys)( *(alpha1 + 0*inca + 1*lda), *(pi1 + 0 + 1*ldp) ); \ PASTEMAC2(ch,ch,copys)( *(alpha1 + 1*inca + 1*lda), *(pi1 + 1 + 1*ldp) ); \ \ PASTEMAC2(ch,ch,copys)( *(alpha1 + 0*inca + 2*lda), *(pi1 + 0 + 2*ldp) ); \ PASTEMAC2(ch,ch,copys)( *(alpha1 + 1*inca + 2*lda), *(pi1 + 1 + 2*ldp) ); \ \ PASTEMAC2(ch,ch,copys)( *(alpha1 + 0*inca + 3*lda), *(pi1 + 0 + 3*ldp) ); \ PASTEMAC2(ch,ch,copys)( *(alpha1 + 1*inca + 3*lda), *(pi1 + 1 + 3*ldp) ); \ \ alpha1 += 4*lda; \ pi1 += 4*ldp; \ } \ \ for ( ; n_left != 0; --n_left ) \ { \ PASTEMAC2(ch,ch,copys)( *(alpha1 + 0*inca), *(pi1 + 0) ); \ PASTEMAC2(ch,ch,copys)( *(alpha1 + 1*inca), *(pi1 + 1) ); \ \ alpha1 += lda; \ pi1 += ldp; \ } \ } \ } \ else \ { \ if ( bli_is_conj( conja ) ) \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 0*inca), *(pi1 + 0) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 1*inca), *(pi1 + 1) ); \ \ alpha1 += lda; \ pi1 += ldp; \ } \ } \ else \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 0*inca), *(pi1 + 0) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 1*inca), *(pi1 + 1) ); \ \ alpha1 += lda; \ pi1 += ldp; \ } \ } \ } \ } \ else /* if ( cdim < mnr ) */ \ { \ PASTEMAC2(ch,scal2m,BLIS_TAPI_EX_SUF) \ ( \ 0, \ BLIS_NONUNIT_DIAG, \ BLIS_DENSE, \ ( trans_t )conja, \ cdim, \ n, \ kappa, \ a, inca, lda, \ p, 1, ldp, \ cntx, \ NULL \ ); \ \ /* if ( cdim < mnr ) */ \ { \ const dim_t i = cdim; \ const dim_t m_edge = mnr - cdim; \ const dim_t n_edge = n_max; \ ctype* restrict p_cast = p; \ ctype* restrict p_edge = p_cast + (i )*1; \ \ PASTEMAC(ch,set0s_mxn) \ ( \ m_edge, \ n_edge, \ p_edge, 1, ldp \ ); \ } \ } \ \ if ( n < n_max ) \ { \ const dim_t j = n; \ const dim_t m_edge = mnr; \ const dim_t n_edge = n_max - n; \ ctype* restrict p_cast = p; \ ctype* restrict p_edge = p_cast + (j )*ldp; \ \ PASTEMAC(ch,set0s_mxn) \ ( \ m_edge, \ n_edge, \ p_edge, 1, ldp \ ); \ } \ } INSERT_GENTFUNC_BASIC3( packm_2xk, 2, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, mnr, arch, suf ) \ \ void PASTEMAC3(ch,opname,arch,suf) \ ( \ conj_t conja, \ pack_t schema, \ dim_t cdim, \ dim_t n, \ dim_t n_max, \ ctype* restrict kappa, \ ctype* restrict a, inc_t inca, inc_t lda, \ ctype* restrict p, inc_t ldp, \ cntx_t* restrict cntx \ ) \ { \ ctype* restrict kappa_cast = kappa; \ ctype* restrict alpha1 = a; \ ctype* restrict pi1 = p; \ \ dim_t n_iter = n / 4; \ dim_t n_left = n % 4; \ \ if ( cdim == mnr ) \ { \ if ( PASTEMAC(ch,eq1)( *kappa_cast ) ) \ { \ if ( bli_is_conj( conja ) ) \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC2(ch,ch,copyjs)( *(alpha1 + 0*inca), *(pi1 + 0) ); \ PASTEMAC2(ch,ch,copyjs)( *(alpha1 + 1*inca), *(pi1 + 1) ); \ PASTEMAC2(ch,ch,copyjs)( *(alpha1 + 2*inca), *(pi1 + 2) ); \ \ alpha1 += lda; \ pi1 += ldp; \ } \ } \ else \ { \ for ( ; n_iter != 0; --n_iter ) \ { \ PASTEMAC2(ch,ch,copys)( *(alpha1 + 0*inca + 0*lda), *(pi1 + 0 + 0*ldp) ); \ PASTEMAC2(ch,ch,copys)( *(alpha1 + 1*inca + 0*lda), *(pi1 + 1 + 0*ldp) ); \ PASTEMAC2(ch,ch,copys)( *(alpha1 + 2*inca + 0*lda), *(pi1 + 2 + 0*ldp) ); \ \ PASTEMAC2(ch,ch,copys)( *(alpha1 + 0*inca + 1*lda), *(pi1 + 0 + 1*ldp) ); \ PASTEMAC2(ch,ch,copys)( *(alpha1 + 1*inca + 1*lda), *(pi1 + 1 + 1*ldp) ); \ PASTEMAC2(ch,ch,copys)( *(alpha1 + 2*inca + 1*lda), *(pi1 + 2 + 1*ldp) ); \ \ PASTEMAC2(ch,ch,copys)( *(alpha1 + 0*inca + 2*lda), *(pi1 + 0 + 2*ldp) ); \ PASTEMAC2(ch,ch,copys)( *(alpha1 + 1*inca + 2*lda), *(pi1 + 1 + 2*ldp) ); \ PASTEMAC2(ch,ch,copys)( *(alpha1 + 2*inca + 2*lda), *(pi1 + 2 + 2*ldp) ); \ \ PASTEMAC2(ch,ch,copys)( *(alpha1 + 0*inca + 3*lda), *(pi1 + 0 + 3*ldp) ); \ PASTEMAC2(ch,ch,copys)( *(alpha1 + 1*inca + 3*lda), *(pi1 + 1 + 3*ldp) ); \ PASTEMAC2(ch,ch,copys)( *(alpha1 + 2*inca + 3*lda), *(pi1 + 2 + 3*ldp) ); \ \ alpha1 += 4*lda; \ pi1 += 4*ldp; \ } \ \ for ( ; n_left != 0; --n_left ) \ { \ PASTEMAC2(ch,ch,copys)( *(alpha1 + 0*inca), *(pi1 + 0) ); \ PASTEMAC2(ch,ch,copys)( *(alpha1 + 1*inca), *(pi1 + 1) ); \ PASTEMAC2(ch,ch,copys)( *(alpha1 + 2*inca), *(pi1 + 2) ); \ \ alpha1 += lda; \ pi1 += ldp; \ } \ } \ } \ else \ { \ if ( bli_is_conj( conja ) ) \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC3(ch,ch,ch,scal2js)( *kappa_cast, *(alpha1 + 0*inca), *(pi1 + 0) ); \ PASTEMAC3(ch,ch,ch,scal2js)( *kappa_cast, *(alpha1 + 1*inca), *(pi1 + 1) ); \ PASTEMAC3(ch,ch,ch,scal2js)( *kappa_cast, *(alpha1 + 2*inca), *(pi1 + 2) ); \ \ alpha1 += lda; \ pi1 += ldp; \ } \ } \ else \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC3(ch,ch,ch,scal2s)( *kappa_cast, *(alpha1 + 0*inca), *(pi1 + 0) ); \ PASTEMAC3(ch,ch,ch,scal2s)( *kappa_cast, *(alpha1 + 1*inca), *(pi1 + 1) ); \ PASTEMAC3(ch,ch,ch,scal2s)( *kappa_cast, *(alpha1 + 2*inca), *(pi1 + 2) ); \ \ alpha1 += lda; \ pi1 += ldp; \ } \ } \ } \ } \ else /* if ( cdim < mnr ) */ \ { \ PASTEMAC2(ch,scal2m,BLIS_TAPI_EX_SUF) \ ( \ 0, \ BLIS_NONUNIT_DIAG, \ BLIS_DENSE, \ ( trans_t )conja, \ cdim, \ n, \ kappa, \ a, inca, lda, \ p, 1, ldp, \ cntx, \ NULL \ ); \ \ /* if ( cdim < mnr ) */ \ { \ const dim_t i = cdim; \ const dim_t m_edge = mnr - cdim; \ const dim_t n_edge = n_max; \ ctype* restrict p_cast = p; \ ctype* restrict p_edge = p_cast + (i )*1; \ \ PASTEMAC(ch,set0s_mxn) \ ( \ m_edge, \ n_edge, \ p_edge, 1, ldp \ ); \ } \ } \ \ if ( n < n_max ) \ { \ const dim_t j = n; \ const dim_t m_edge = mnr; \ const dim_t n_edge = n_max - n; \ ctype* restrict p_cast = p; \ ctype* restrict p_edge = p_cast + (j )*ldp; \ \ PASTEMAC(ch,set0s_mxn) \ ( \ m_edge, \ n_edge, \ p_edge, 1, ldp \ ); \ } \ } INSERT_GENTFUNC_BASIC3( packm_3xk, 3, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, mnr, arch, suf ) \ \ void PASTEMAC3(ch,opname,arch,suf) \ ( \ conj_t conja, \ pack_t schema, \ dim_t cdim, \ dim_t n, \ dim_t n_max, \ ctype* restrict kappa, \ ctype* restrict a, inc_t inca, inc_t lda, \ ctype* restrict p, inc_t ldp, \ cntx_t* restrict cntx \ ) \ { \ ctype* restrict kappa_cast = kappa; \ ctype* restrict alpha1 = a; \ ctype* restrict pi1 = p; \ \ dim_t n_iter = n / 2; \ dim_t n_left = n % 2; \ \ if ( cdim == mnr ) \ { \ if ( PASTEMAC(ch,eq1)( *kappa_cast ) ) \ { \ if ( bli_is_conj( conja ) ) \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC2(ch,ch,copyjs)( *(alpha1 + 0*inca), *(pi1 + 0) ); \ PASTEMAC2(ch,ch,copyjs)( *(alpha1 + 1*inca), *(pi1 + 1) ); \ PASTEMAC2(ch,ch,copyjs)( *(alpha1 + 2*inca), *(pi1 + 2) ); \ PASTEMAC2(ch,ch,copyjs)( *(alpha1 + 3*inca), *(pi1 + 3) ); \ \ alpha1 += lda; \ pi1 += ldp; \ } \ } \ else \ { \ for ( ; n_iter != 0; --n_iter ) \ { \ PASTEMAC2(ch,ch,copys)( *(alpha1 + 0*inca + 0*lda), *(pi1 + 0 + 0*ldp) ); \ PASTEMAC2(ch,ch,copys)( *(alpha1 + 1*inca + 0*lda), *(pi1 + 1 + 0*ldp) ); \ PASTEMAC2(ch,ch,copys)( *(alpha1 + 2*inca + 0*lda), *(pi1 + 2 + 0*ldp) ); \ PASTEMAC2(ch,ch,copys)( *(alpha1 + 3*inca + 0*lda), *(pi1 + 3 + 0*ldp) ); \ \ PASTEMAC2(ch,ch,copys)( *(alpha1 + 0*inca + 1*lda), *(pi1 + 0 + 1*ldp) ); \ PASTEMAC2(ch,ch,copys)( *(alpha1 + 1*inca + 1*lda), *(pi1 + 1 + 1*ldp) ); \ PASTEMAC2(ch,ch,copys)( *(alpha1 + 2*inca + 1*lda), *(pi1 + 2 + 1*ldp) ); \ PASTEMAC2(ch,ch,copys)( *(alpha1 + 3*inca + 1*lda), *(pi1 + 3 + 1*ldp) ); \ \ alpha1 += 2*lda; \ pi1 += 2*ldp; \ } \ \ for ( ; n_left != 0; --n_left ) \ { \ PASTEMAC2(ch,ch,copys)( *(alpha1 + 0*inca), *(pi1 + 0) ); \ PASTEMAC2(ch,ch,copys)( *(alpha1 + 1*inca), *(pi1 + 1) ); \ PASTEMAC2(ch,ch,copys)( *(alpha1 + 2*inca), *(pi1 + 2) ); \ PASTEMAC2(ch,ch,copys)( *(alpha1 + 3*inca), *(pi1 + 3) ); \ \ alpha1 += lda; \ pi1 += ldp; \ } \ } \ } \ else \ { \ if ( bli_is_conj( conja ) ) \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC3(ch,ch,ch,scal2js)( *kappa_cast, *(alpha1 + 0*inca), *(pi1 + 0) ); \ PASTEMAC3(ch,ch,ch,scal2js)( *kappa_cast, *(alpha1 + 1*inca), *(pi1 + 1) ); \ PASTEMAC3(ch,ch,ch,scal2js)( *kappa_cast, *(alpha1 + 2*inca), *(pi1 + 2) ); \ PASTEMAC3(ch,ch,ch,scal2js)( *kappa_cast, *(alpha1 + 3*inca), *(pi1 + 3) ); \ \ alpha1 += lda; \ pi1 += ldp; \ } \ } \ else \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC3(ch,ch,ch,scal2s)( *kappa_cast, *(alpha1 + 0*inca), *(pi1 + 0) ); \ PASTEMAC3(ch,ch,ch,scal2s)( *kappa_cast, *(alpha1 + 1*inca), *(pi1 + 1) ); \ PASTEMAC3(ch,ch,ch,scal2s)( *kappa_cast, *(alpha1 + 2*inca), *(pi1 + 2) ); \ PASTEMAC3(ch,ch,ch,scal2s)( *kappa_cast, *(alpha1 + 3*inca), *(pi1 + 3) ); \ \ alpha1 += lda; \ pi1 += ldp; \ } \ } \ } \ } \ else /* if ( cdim < mnr ) */ \ { \ PASTEMAC2(ch,scal2m,BLIS_TAPI_EX_SUF) \ ( \ 0, \ BLIS_NONUNIT_DIAG, \ BLIS_DENSE, \ ( trans_t )conja, \ cdim, \ n, \ kappa, \ a, inca, lda, \ p, 1, ldp, \ cntx, \ NULL \ ); \ \ /* if ( cdim < mnr ) */ \ { \ const dim_t i = cdim; \ const dim_t m_edge = mnr - cdim; \ const dim_t n_edge = n_max; \ ctype* restrict p_cast = p; \ ctype* restrict p_edge = p_cast + (i )*1; \ \ PASTEMAC(ch,set0s_mxn) \ ( \ m_edge, \ n_edge, \ p_edge, 1, ldp \ ); \ } \ } \ \ if ( n < n_max ) \ { \ const dim_t j = n; \ const dim_t m_edge = mnr; \ const dim_t n_edge = n_max - n; \ ctype* restrict p_cast = p; \ ctype* restrict p_edge = p_cast + (j )*ldp; \ \ PASTEMAC(ch,set0s_mxn) \ ( \ m_edge, \ n_edge, \ p_edge, 1, ldp \ ); \ } \ } INSERT_GENTFUNC_BASIC3( packm_4xk, 4, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, mnr, arch, suf ) \ \ void PASTEMAC3(ch,opname,arch,suf) \ ( \ conj_t conja, \ pack_t schema, \ dim_t cdim, \ dim_t n, \ dim_t n_max, \ ctype* restrict kappa, \ ctype* restrict a, inc_t inca, inc_t lda, \ ctype* restrict p, inc_t ldp, \ cntx_t* restrict cntx \ ) \ { \ ctype* restrict kappa_cast = kappa; \ ctype* restrict alpha1 = a; \ ctype* restrict pi1 = p; \ \ if ( cdim == mnr ) \ { \ if ( PASTEMAC(ch,eq1)( *kappa_cast ) ) \ { \ if ( bli_is_conj( conja ) ) \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,copyjs)( *(alpha1 + 0*inca), *(pi1 + 0) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 1*inca), *(pi1 + 1) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 2*inca), *(pi1 + 2) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 3*inca), *(pi1 + 3) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 4*inca), *(pi1 + 4) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 5*inca), *(pi1 + 5) ); \ \ alpha1 += lda; \ pi1 += ldp; \ } \ } \ else \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,copys)( *(alpha1 + 0*inca), *(pi1 + 0) ); \ PASTEMAC(ch,copys)( *(alpha1 + 1*inca), *(pi1 + 1) ); \ PASTEMAC(ch,copys)( *(alpha1 + 2*inca), *(pi1 + 2) ); \ PASTEMAC(ch,copys)( *(alpha1 + 3*inca), *(pi1 + 3) ); \ PASTEMAC(ch,copys)( *(alpha1 + 4*inca), *(pi1 + 4) ); \ PASTEMAC(ch,copys)( *(alpha1 + 5*inca), *(pi1 + 5) ); \ \ alpha1 += lda; \ pi1 += ldp; \ } \ } \ } \ else \ { \ if ( bli_is_conj( conja ) ) \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 0*inca), *(pi1 + 0) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 1*inca), *(pi1 + 1) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 2*inca), *(pi1 + 2) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 3*inca), *(pi1 + 3) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 4*inca), *(pi1 + 4) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 5*inca), *(pi1 + 5) ); \ \ alpha1 += lda; \ pi1 += ldp; \ } \ } \ else \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 0*inca), *(pi1 + 0) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 1*inca), *(pi1 + 1) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 2*inca), *(pi1 + 2) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 3*inca), *(pi1 + 3) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 4*inca), *(pi1 + 4) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 5*inca), *(pi1 + 5) ); \ \ alpha1 += lda; \ pi1 += ldp; \ } \ } \ } \ } \ else /* if ( cdim < mnr ) */ \ { \ PASTEMAC2(ch,scal2m,BLIS_TAPI_EX_SUF) \ ( \ 0, \ BLIS_NONUNIT_DIAG, \ BLIS_DENSE, \ ( trans_t )conja, \ cdim, \ n, \ kappa, \ a, inca, lda, \ p, 1, ldp, \ cntx, \ NULL \ ); \ \ /* if ( cdim < mnr ) */ \ { \ const dim_t i = cdim; \ const dim_t m_edge = mnr - cdim; \ const dim_t n_edge = n_max; \ ctype* restrict p_cast = p; \ ctype* restrict p_edge = p_cast + (i )*1; \ \ PASTEMAC(ch,set0s_mxn) \ ( \ m_edge, \ n_edge, \ p_edge, 1, ldp \ ); \ } \ } \ \ if ( n < n_max ) \ { \ const dim_t j = n; \ const dim_t m_edge = mnr; \ const dim_t n_edge = n_max - n; \ ctype* restrict p_cast = p; \ ctype* restrict p_edge = p_cast + (j )*ldp; \ \ PASTEMAC(ch,set0s_mxn) \ ( \ m_edge, \ n_edge, \ p_edge, 1, ldp \ ); \ } \ } INSERT_GENTFUNC_BASIC3( packm_6xk, 6, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, mnr, arch, suf ) \ \ void PASTEMAC3(ch,opname,arch,suf) \ ( \ conj_t conja, \ pack_t schema, \ dim_t cdim, \ dim_t n, \ dim_t n_max, \ ctype* restrict kappa, \ ctype* restrict a, inc_t inca, inc_t lda, \ ctype* restrict p, inc_t ldp, \ cntx_t* restrict cntx \ ) \ { \ ctype* restrict kappa_cast = kappa; \ ctype* restrict alpha1 = a; \ ctype* restrict pi1 = p; \ \ dim_t n_iter = n / 2; \ dim_t n_left = n % 2; \ \ if ( cdim == mnr ) \ { \ if ( PASTEMAC(ch,eq1)( *kappa_cast ) ) \ { \ if ( bli_is_conj( conja ) ) \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,copyjs)( *(alpha1 + 0*inca), *(pi1 + 0) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 1*inca), *(pi1 + 1) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 2*inca), *(pi1 + 2) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 3*inca), *(pi1 + 3) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 4*inca), *(pi1 + 4) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 5*inca), *(pi1 + 5) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 6*inca), *(pi1 + 6) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 7*inca), *(pi1 + 7) ); \ \ alpha1 += lda; \ pi1 += ldp; \ } \ } \ else \ { \ for ( ; n_iter != 0; --n_iter ) \ { \ PASTEMAC(ch,copys)( *(alpha1 + 0*inca + 0*lda), *(pi1 + 0 + 0*ldp) ); \ PASTEMAC(ch,copys)( *(alpha1 + 1*inca + 0*lda), *(pi1 + 1 + 0*ldp) ); \ PASTEMAC(ch,copys)( *(alpha1 + 2*inca + 0*lda), *(pi1 + 2 + 0*ldp) ); \ PASTEMAC(ch,copys)( *(alpha1 + 3*inca + 0*lda), *(pi1 + 3 + 0*ldp) ); \ PASTEMAC(ch,copys)( *(alpha1 + 4*inca + 0*lda), *(pi1 + 4 + 0*ldp) ); \ PASTEMAC(ch,copys)( *(alpha1 + 5*inca + 0*lda), *(pi1 + 5 + 0*ldp) ); \ PASTEMAC(ch,copys)( *(alpha1 + 6*inca + 0*lda), *(pi1 + 6 + 0*ldp) ); \ PASTEMAC(ch,copys)( *(alpha1 + 7*inca + 0*lda), *(pi1 + 7 + 0*ldp) ); \ \ PASTEMAC(ch,copys)( *(alpha1 + 0*inca + 1*lda), *(pi1 + 0 + 1*ldp) ); \ PASTEMAC(ch,copys)( *(alpha1 + 1*inca + 1*lda), *(pi1 + 1 + 1*ldp) ); \ PASTEMAC(ch,copys)( *(alpha1 + 2*inca + 1*lda), *(pi1 + 2 + 1*ldp) ); \ PASTEMAC(ch,copys)( *(alpha1 + 3*inca + 1*lda), *(pi1 + 3 + 1*ldp) ); \ PASTEMAC(ch,copys)( *(alpha1 + 4*inca + 1*lda), *(pi1 + 4 + 1*ldp) ); \ PASTEMAC(ch,copys)( *(alpha1 + 5*inca + 1*lda), *(pi1 + 5 + 1*ldp) ); \ PASTEMAC(ch,copys)( *(alpha1 + 6*inca + 1*lda), *(pi1 + 6 + 1*ldp) ); \ PASTEMAC(ch,copys)( *(alpha1 + 7*inca + 1*lda), *(pi1 + 7 + 1*ldp) ); \ \ alpha1 += 2*lda; \ pi1 += 2*ldp; \ } \ \ for ( ; n_left != 0; --n_left ) \ { \ PASTEMAC(ch,copys)( *(alpha1 + 0*inca), *(pi1 + 0) ); \ PASTEMAC(ch,copys)( *(alpha1 + 1*inca), *(pi1 + 1) ); \ PASTEMAC(ch,copys)( *(alpha1 + 2*inca), *(pi1 + 2) ); \ PASTEMAC(ch,copys)( *(alpha1 + 3*inca), *(pi1 + 3) ); \ PASTEMAC(ch,copys)( *(alpha1 + 4*inca), *(pi1 + 4) ); \ PASTEMAC(ch,copys)( *(alpha1 + 5*inca), *(pi1 + 5) ); \ PASTEMAC(ch,copys)( *(alpha1 + 6*inca), *(pi1 + 6) ); \ PASTEMAC(ch,copys)( *(alpha1 + 7*inca), *(pi1 + 7) ); \ \ alpha1 += lda; \ pi1 += ldp; \ } \ } \ } \ else \ { \ if ( bli_is_conj( conja ) ) \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 0*inca), *(pi1 + 0) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 1*inca), *(pi1 + 1) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 2*inca), *(pi1 + 2) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 3*inca), *(pi1 + 3) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 4*inca), *(pi1 + 4) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 5*inca), *(pi1 + 5) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 6*inca), *(pi1 + 6) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 7*inca), *(pi1 + 7) ); \ \ alpha1 += lda; \ pi1 += ldp; \ } \ } \ else \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 0*inca), *(pi1 + 0) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 1*inca), *(pi1 + 1) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 2*inca), *(pi1 + 2) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 3*inca), *(pi1 + 3) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 4*inca), *(pi1 + 4) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 5*inca), *(pi1 + 5) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 6*inca), *(pi1 + 6) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 7*inca), *(pi1 + 7) ); \ \ alpha1 += lda; \ pi1 += ldp; \ } \ } \ } \ } \ else /* if ( cdim < mnr ) */ \ { \ PASTEMAC2(ch,scal2m,BLIS_TAPI_EX_SUF) \ ( \ 0, \ BLIS_NONUNIT_DIAG, \ BLIS_DENSE, \ ( trans_t )conja, \ cdim, \ n, \ kappa, \ a, inca, lda, \ p, 1, ldp, \ cntx, \ NULL \ ); \ \ /* if ( cdim < mnr ) */ \ { \ const dim_t i = cdim; \ const dim_t m_edge = mnr - cdim; \ const dim_t n_edge = n_max; \ ctype* restrict p_cast = p; \ ctype* restrict p_edge = p_cast + (i )*1; \ \ PASTEMAC(ch,set0s_mxn) \ ( \ m_edge, \ n_edge, \ p_edge, 1, ldp \ ); \ } \ } \ \ if ( n < n_max ) \ { \ const dim_t j = n; \ const dim_t m_edge = mnr; \ const dim_t n_edge = n_max - n; \ ctype* restrict p_cast = p; \ ctype* restrict p_edge = p_cast + (j )*ldp; \ \ PASTEMAC(ch,set0s_mxn) \ ( \ m_edge, \ n_edge, \ p_edge, 1, ldp \ ); \ } \ } INSERT_GENTFUNC_BASIC3( packm_8xk, 8, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, mnr, arch, suf ) \ \ void PASTEMAC3(ch,opname,arch,suf) \ ( \ conj_t conja, \ pack_t schema, \ dim_t cdim, \ dim_t n, \ dim_t n_max, \ ctype* restrict kappa, \ ctype* restrict a, inc_t inca, inc_t lda, \ ctype* restrict p, inc_t ldp, \ cntx_t* restrict cntx \ ) \ { \ ctype* restrict kappa_cast = kappa; \ ctype* restrict alpha1 = a; \ ctype* restrict pi1 = p; \ \ if ( cdim == mnr ) \ { \ if ( PASTEMAC(ch,eq1)( *kappa_cast ) ) \ { \ if ( bli_is_conj( conja ) ) \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,copyjs)( *(alpha1 + 0*inca), *(pi1 + 0) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 1*inca), *(pi1 + 1) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 2*inca), *(pi1 + 2) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 3*inca), *(pi1 + 3) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 4*inca), *(pi1 + 4) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 5*inca), *(pi1 + 5) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 6*inca), *(pi1 + 6) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 7*inca), *(pi1 + 7) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 8*inca), *(pi1 + 8) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 9*inca), *(pi1 + 9) ); \ \ alpha1 += lda; \ pi1 += ldp; \ } \ } \ else \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,copys)( *(alpha1 + 0*inca), *(pi1 + 0) ); \ PASTEMAC(ch,copys)( *(alpha1 + 1*inca), *(pi1 + 1) ); \ PASTEMAC(ch,copys)( *(alpha1 + 2*inca), *(pi1 + 2) ); \ PASTEMAC(ch,copys)( *(alpha1 + 3*inca), *(pi1 + 3) ); \ PASTEMAC(ch,copys)( *(alpha1 + 4*inca), *(pi1 + 4) ); \ PASTEMAC(ch,copys)( *(alpha1 + 5*inca), *(pi1 + 5) ); \ PASTEMAC(ch,copys)( *(alpha1 + 6*inca), *(pi1 + 6) ); \ PASTEMAC(ch,copys)( *(alpha1 + 7*inca), *(pi1 + 7) ); \ PASTEMAC(ch,copys)( *(alpha1 + 8*inca), *(pi1 + 8) ); \ PASTEMAC(ch,copys)( *(alpha1 + 9*inca), *(pi1 + 9) ); \ \ alpha1 += lda; \ pi1 += ldp; \ } \ } \ } \ else \ { \ if ( bli_is_conj( conja ) ) \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 0*inca), *(pi1 + 0) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 1*inca), *(pi1 + 1) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 2*inca), *(pi1 + 2) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 3*inca), *(pi1 + 3) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 4*inca), *(pi1 + 4) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 5*inca), *(pi1 + 5) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 6*inca), *(pi1 + 6) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 7*inca), *(pi1 + 7) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 8*inca), *(pi1 + 8) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 9*inca), *(pi1 + 9) ); \ \ alpha1 += lda; \ pi1 += ldp; \ } \ } \ else \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 0*inca), *(pi1 + 0) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 1*inca), *(pi1 + 1) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 2*inca), *(pi1 + 2) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 3*inca), *(pi1 + 3) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 4*inca), *(pi1 + 4) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 5*inca), *(pi1 + 5) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 6*inca), *(pi1 + 6) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 7*inca), *(pi1 + 7) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 8*inca), *(pi1 + 8) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 9*inca), *(pi1 + 9) ); \ \ alpha1 += lda; \ pi1 += ldp; \ } \ } \ } \ } \ else /* if ( cdim < mnr ) */ \ { \ PASTEMAC2(ch,scal2m,BLIS_TAPI_EX_SUF) \ ( \ 0, \ BLIS_NONUNIT_DIAG, \ BLIS_DENSE, \ ( trans_t )conja, \ cdim, \ n, \ kappa, \ a, inca, lda, \ p, 1, ldp, \ cntx, \ NULL \ ); \ \ /* if ( cdim < mnr ) */ \ { \ const dim_t i = cdim; \ const dim_t m_edge = mnr - cdim; \ const dim_t n_edge = n_max; \ ctype* restrict p_cast = p; \ ctype* restrict p_edge = p_cast + (i )*1; \ \ PASTEMAC(ch,set0s_mxn) \ ( \ m_edge, \ n_edge, \ p_edge, 1, ldp \ ); \ } \ } \ \ if ( n < n_max ) \ { \ const dim_t j = n; \ const dim_t m_edge = mnr; \ const dim_t n_edge = n_max - n; \ ctype* restrict p_cast = p; \ ctype* restrict p_edge = p_cast + (j )*ldp; \ \ PASTEMAC(ch,set0s_mxn) \ ( \ m_edge, \ n_edge, \ p_edge, 1, ldp \ ); \ } \ } INSERT_GENTFUNC_BASIC3( packm_10xk, 10, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, mnr, arch, suf ) \ \ void PASTEMAC3(ch,opname,arch,suf) \ ( \ conj_t conja, \ pack_t schema, \ dim_t cdim, \ dim_t n, \ dim_t n_max, \ ctype* restrict kappa, \ ctype* restrict a, inc_t inca, inc_t lda, \ ctype* restrict p, inc_t ldp, \ cntx_t* restrict cntx \ ) \ { \ ctype* restrict kappa_cast = kappa; \ ctype* restrict alpha1 = a; \ ctype* restrict pi1 = p; \ \ if ( cdim == mnr ) \ { \ if ( PASTEMAC(ch,eq1)( *kappa_cast ) ) \ { \ if ( bli_is_conj( conja ) ) \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,copyjs)( *(alpha1 + 0*inca), *(pi1 + 0) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 1*inca), *(pi1 + 1) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 2*inca), *(pi1 + 2) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 3*inca), *(pi1 + 3) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 4*inca), *(pi1 + 4) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 5*inca), *(pi1 + 5) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 6*inca), *(pi1 + 6) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 7*inca), *(pi1 + 7) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 8*inca), *(pi1 + 8) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 9*inca), *(pi1 + 9) ); \ PASTEMAC(ch,copyjs)( *(alpha1 +10*inca), *(pi1 +10) ); \ PASTEMAC(ch,copyjs)( *(alpha1 +11*inca), *(pi1 +11) ); \ \ alpha1 += lda; \ pi1 += ldp; \ } \ } \ else \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,copys)( *(alpha1 + 0*inca), *(pi1 + 0) ); \ PASTEMAC(ch,copys)( *(alpha1 + 1*inca), *(pi1 + 1) ); \ PASTEMAC(ch,copys)( *(alpha1 + 2*inca), *(pi1 + 2) ); \ PASTEMAC(ch,copys)( *(alpha1 + 3*inca), *(pi1 + 3) ); \ PASTEMAC(ch,copys)( *(alpha1 + 4*inca), *(pi1 + 4) ); \ PASTEMAC(ch,copys)( *(alpha1 + 5*inca), *(pi1 + 5) ); \ PASTEMAC(ch,copys)( *(alpha1 + 6*inca), *(pi1 + 6) ); \ PASTEMAC(ch,copys)( *(alpha1 + 7*inca), *(pi1 + 7) ); \ PASTEMAC(ch,copys)( *(alpha1 + 8*inca), *(pi1 + 8) ); \ PASTEMAC(ch,copys)( *(alpha1 + 9*inca), *(pi1 + 9) ); \ PASTEMAC(ch,copys)( *(alpha1 +10*inca), *(pi1 +10) ); \ PASTEMAC(ch,copys)( *(alpha1 +11*inca), *(pi1 +11) ); \ \ alpha1 += lda; \ pi1 += ldp; \ } \ } \ } \ else \ { \ if ( bli_is_conj( conja ) ) \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 0*inca), *(pi1 + 0) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 1*inca), *(pi1 + 1) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 2*inca), *(pi1 + 2) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 3*inca), *(pi1 + 3) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 4*inca), *(pi1 + 4) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 5*inca), *(pi1 + 5) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 6*inca), *(pi1 + 6) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 7*inca), *(pi1 + 7) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 8*inca), *(pi1 + 8) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 9*inca), *(pi1 + 9) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 +10*inca), *(pi1 +10) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 +11*inca), *(pi1 +11) ); \ \ alpha1 += lda; \ pi1 += ldp; \ } \ } \ else \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 0*inca), *(pi1 + 0) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 1*inca), *(pi1 + 1) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 2*inca), *(pi1 + 2) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 3*inca), *(pi1 + 3) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 4*inca), *(pi1 + 4) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 5*inca), *(pi1 + 5) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 6*inca), *(pi1 + 6) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 7*inca), *(pi1 + 7) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 8*inca), *(pi1 + 8) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 9*inca), *(pi1 + 9) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 +10*inca), *(pi1 +10) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 +11*inca), *(pi1 +11) ); \ \ alpha1 += lda; \ pi1 += ldp; \ } \ } \ } \ } \ else /* if ( cdim < mnr ) */ \ { \ PASTEMAC2(ch,scal2m,BLIS_TAPI_EX_SUF) \ ( \ 0, \ BLIS_NONUNIT_DIAG, \ BLIS_DENSE, \ ( trans_t )conja, \ cdim, \ n, \ kappa, \ a, inca, lda, \ p, 1, ldp, \ cntx, \ NULL \ ); \ \ /* if ( cdim < mnr ) */ \ { \ const dim_t i = cdim; \ const dim_t m_edge = mnr - cdim; \ const dim_t n_edge = n_max; \ ctype* restrict p_cast = p; \ ctype* restrict p_edge = p_cast + (i )*1; \ \ PASTEMAC(ch,set0s_mxn) \ ( \ m_edge, \ n_edge, \ p_edge, 1, ldp \ ); \ } \ } \ \ if ( n < n_max ) \ { \ const dim_t j = n; \ const dim_t m_edge = mnr; \ const dim_t n_edge = n_max - n; \ ctype* restrict p_cast = p; \ ctype* restrict p_edge = p_cast + (j )*ldp; \ \ PASTEMAC(ch,set0s_mxn) \ ( \ m_edge, \ n_edge, \ p_edge, 1, ldp \ ); \ } \ } INSERT_GENTFUNC_BASIC3( packm_12xk, 12, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, mnr, arch, suf ) \ \ void PASTEMAC3(ch,opname,arch,suf) \ ( \ conj_t conja, \ pack_t schema, \ dim_t cdim, \ dim_t n, \ dim_t n_max, \ ctype* restrict kappa, \ ctype* restrict a, inc_t inca, inc_t lda, \ ctype* restrict p, inc_t ldp, \ cntx_t* restrict cntx \ ) \ { \ ctype* restrict kappa_cast = kappa; \ ctype* restrict alpha1 = a; \ ctype* restrict pi1 = p; \ \ if ( cdim == mnr ) \ { \ if ( PASTEMAC(ch,eq1)( *kappa_cast ) ) \ { \ if ( bli_is_conj( conja ) ) \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,copyjs)( *(alpha1 + 0*inca), *(pi1 + 0) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 1*inca), *(pi1 + 1) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 2*inca), *(pi1 + 2) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 3*inca), *(pi1 + 3) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 4*inca), *(pi1 + 4) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 5*inca), *(pi1 + 5) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 6*inca), *(pi1 + 6) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 7*inca), *(pi1 + 7) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 8*inca), *(pi1 + 8) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 9*inca), *(pi1 + 9) ); \ PASTEMAC(ch,copyjs)( *(alpha1 +10*inca), *(pi1 +10) ); \ PASTEMAC(ch,copyjs)( *(alpha1 +11*inca), *(pi1 +11) ); \ PASTEMAC(ch,copyjs)( *(alpha1 +12*inca), *(pi1 +12) ); \ PASTEMAC(ch,copyjs)( *(alpha1 +13*inca), *(pi1 +13) ); \ \ alpha1 += lda; \ pi1 += ldp; \ } \ } \ else \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,copys)( *(alpha1 + 0*inca), *(pi1 + 0) ); \ PASTEMAC(ch,copys)( *(alpha1 + 1*inca), *(pi1 + 1) ); \ PASTEMAC(ch,copys)( *(alpha1 + 2*inca), *(pi1 + 2) ); \ PASTEMAC(ch,copys)( *(alpha1 + 3*inca), *(pi1 + 3) ); \ PASTEMAC(ch,copys)( *(alpha1 + 4*inca), *(pi1 + 4) ); \ PASTEMAC(ch,copys)( *(alpha1 + 5*inca), *(pi1 + 5) ); \ PASTEMAC(ch,copys)( *(alpha1 + 6*inca), *(pi1 + 6) ); \ PASTEMAC(ch,copys)( *(alpha1 + 7*inca), *(pi1 + 7) ); \ PASTEMAC(ch,copys)( *(alpha1 + 8*inca), *(pi1 + 8) ); \ PASTEMAC(ch,copys)( *(alpha1 + 9*inca), *(pi1 + 9) ); \ PASTEMAC(ch,copys)( *(alpha1 +10*inca), *(pi1 +10) ); \ PASTEMAC(ch,copys)( *(alpha1 +11*inca), *(pi1 +11) ); \ PASTEMAC(ch,copys)( *(alpha1 +12*inca), *(pi1 +12) ); \ PASTEMAC(ch,copys)( *(alpha1 +13*inca), *(pi1 +13) ); \ \ alpha1 += lda; \ pi1 += ldp; \ } \ } \ } \ else \ { \ if ( bli_is_conj( conja ) ) \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 0*inca), *(pi1 + 0) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 1*inca), *(pi1 + 1) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 2*inca), *(pi1 + 2) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 3*inca), *(pi1 + 3) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 4*inca), *(pi1 + 4) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 5*inca), *(pi1 + 5) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 6*inca), *(pi1 + 6) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 7*inca), *(pi1 + 7) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 8*inca), *(pi1 + 8) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 9*inca), *(pi1 + 9) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 +10*inca), *(pi1 +10) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 +11*inca), *(pi1 +11) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 +12*inca), *(pi1 +12) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 +13*inca), *(pi1 +13) ); \ \ alpha1 += lda; \ pi1 += ldp; \ } \ } \ else \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 0*inca), *(pi1 + 0) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 1*inca), *(pi1 + 1) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 2*inca), *(pi1 + 2) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 3*inca), *(pi1 + 3) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 4*inca), *(pi1 + 4) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 5*inca), *(pi1 + 5) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 6*inca), *(pi1 + 6) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 7*inca), *(pi1 + 7) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 8*inca), *(pi1 + 8) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 9*inca), *(pi1 + 9) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 +10*inca), *(pi1 +10) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 +11*inca), *(pi1 +11) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 +12*inca), *(pi1 +12) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 +13*inca), *(pi1 +13) ); \ \ alpha1 += lda; \ pi1 += ldp; \ } \ } \ } \ } \ else /* if ( cdim < mnr ) */ \ { \ PASTEMAC2(ch,scal2m,BLIS_TAPI_EX_SUF) \ ( \ 0, \ BLIS_NONUNIT_DIAG, \ BLIS_DENSE, \ ( trans_t )conja, \ cdim, \ n, \ kappa, \ a, inca, lda, \ p, 1, ldp, \ cntx, \ NULL \ ); \ \ /* if ( cdim < mnr ) */ \ { \ const dim_t i = cdim; \ const dim_t m_edge = mnr - cdim; \ const dim_t n_edge = n_max; \ ctype* restrict p_cast = p; \ ctype* restrict p_edge = p_cast + (i )*1; \ \ PASTEMAC(ch,set0s_mxn) \ ( \ m_edge, \ n_edge, \ p_edge, 1, ldp \ ); \ } \ } \ \ if ( n < n_max ) \ { \ const dim_t j = n; \ const dim_t m_edge = mnr; \ const dim_t n_edge = n_max - n; \ ctype* restrict p_cast = p; \ ctype* restrict p_edge = p_cast + (j )*ldp; \ \ PASTEMAC(ch,set0s_mxn) \ ( \ m_edge, \ n_edge, \ p_edge, 1, ldp \ ); \ } \ } INSERT_GENTFUNC_BASIC3( packm_14xk, 14, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, mnr, arch, suf ) \ \ void PASTEMAC3(ch,opname,arch,suf) \ ( \ conj_t conja, \ pack_t schema, \ dim_t cdim, \ dim_t n, \ dim_t n_max, \ ctype* restrict kappa, \ ctype* restrict a, inc_t inca, inc_t lda, \ ctype* restrict p, inc_t ldp, \ cntx_t* restrict cntx \ ) \ { \ ctype* restrict kappa_cast = kappa; \ ctype* restrict alpha1 = a; \ ctype* restrict pi1 = p; \ \ if ( cdim == mnr ) \ { \ if ( PASTEMAC(ch,eq1)( *kappa_cast ) ) \ { \ if ( bli_is_conj( conja ) ) \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,copyjs)( *(alpha1 + 0*inca), *(pi1 + 0) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 1*inca), *(pi1 + 1) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 2*inca), *(pi1 + 2) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 3*inca), *(pi1 + 3) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 4*inca), *(pi1 + 4) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 5*inca), *(pi1 + 5) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 6*inca), *(pi1 + 6) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 7*inca), *(pi1 + 7) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 8*inca), *(pi1 + 8) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 9*inca), *(pi1 + 9) ); \ PASTEMAC(ch,copyjs)( *(alpha1 +10*inca), *(pi1 +10) ); \ PASTEMAC(ch,copyjs)( *(alpha1 +11*inca), *(pi1 +11) ); \ PASTEMAC(ch,copyjs)( *(alpha1 +12*inca), *(pi1 +12) ); \ PASTEMAC(ch,copyjs)( *(alpha1 +13*inca), *(pi1 +13) ); \ PASTEMAC(ch,copyjs)( *(alpha1 +14*inca), *(pi1 +14) ); \ PASTEMAC(ch,copyjs)( *(alpha1 +15*inca), *(pi1 +15) ); \ \ alpha1 += lda; \ pi1 += ldp; \ } \ } \ else \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,copys)( *(alpha1 + 0*inca), *(pi1 + 0) ); \ PASTEMAC(ch,copys)( *(alpha1 + 1*inca), *(pi1 + 1) ); \ PASTEMAC(ch,copys)( *(alpha1 + 2*inca), *(pi1 + 2) ); \ PASTEMAC(ch,copys)( *(alpha1 + 3*inca), *(pi1 + 3) ); \ PASTEMAC(ch,copys)( *(alpha1 + 4*inca), *(pi1 + 4) ); \ PASTEMAC(ch,copys)( *(alpha1 + 5*inca), *(pi1 + 5) ); \ PASTEMAC(ch,copys)( *(alpha1 + 6*inca), *(pi1 + 6) ); \ PASTEMAC(ch,copys)( *(alpha1 + 7*inca), *(pi1 + 7) ); \ PASTEMAC(ch,copys)( *(alpha1 + 8*inca), *(pi1 + 8) ); \ PASTEMAC(ch,copys)( *(alpha1 + 9*inca), *(pi1 + 9) ); \ PASTEMAC(ch,copys)( *(alpha1 +10*inca), *(pi1 +10) ); \ PASTEMAC(ch,copys)( *(alpha1 +11*inca), *(pi1 +11) ); \ PASTEMAC(ch,copys)( *(alpha1 +12*inca), *(pi1 +12) ); \ PASTEMAC(ch,copys)( *(alpha1 +13*inca), *(pi1 +13) ); \ PASTEMAC(ch,copys)( *(alpha1 +14*inca), *(pi1 +14) ); \ PASTEMAC(ch,copys)( *(alpha1 +15*inca), *(pi1 +15) ); \ \ alpha1 += lda; \ pi1 += ldp; \ } \ } \ } \ else \ { \ if ( bli_is_conj( conja ) ) \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 0*inca), *(pi1 + 0) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 1*inca), *(pi1 + 1) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 2*inca), *(pi1 + 2) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 3*inca), *(pi1 + 3) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 4*inca), *(pi1 + 4) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 5*inca), *(pi1 + 5) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 6*inca), *(pi1 + 6) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 7*inca), *(pi1 + 7) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 8*inca), *(pi1 + 8) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 9*inca), *(pi1 + 9) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 +10*inca), *(pi1 +10) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 +11*inca), *(pi1 +11) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 +12*inca), *(pi1 +12) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 +13*inca), *(pi1 +13) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 +14*inca), *(pi1 +14) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 +15*inca), *(pi1 +15) ); \ \ alpha1 += lda; \ pi1 += ldp; \ } \ } \ else \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 0*inca), *(pi1 + 0) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 1*inca), *(pi1 + 1) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 2*inca), *(pi1 + 2) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 3*inca), *(pi1 + 3) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 4*inca), *(pi1 + 4) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 5*inca), *(pi1 + 5) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 6*inca), *(pi1 + 6) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 7*inca), *(pi1 + 7) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 8*inca), *(pi1 + 8) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 9*inca), *(pi1 + 9) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 +10*inca), *(pi1 +10) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 +11*inca), *(pi1 +11) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 +12*inca), *(pi1 +12) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 +13*inca), *(pi1 +13) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 +14*inca), *(pi1 +14) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 +15*inca), *(pi1 +15) ); \ \ alpha1 += lda; \ pi1 += ldp; \ } \ } \ } \ } \ else /* if ( cdim < mnr ) */ \ { \ PASTEMAC2(ch,scal2m,BLIS_TAPI_EX_SUF) \ ( \ 0, \ BLIS_NONUNIT_DIAG, \ BLIS_DENSE, \ ( trans_t )conja, \ cdim, \ n, \ kappa, \ a, inca, lda, \ p, 1, ldp, \ cntx, \ NULL \ ); \ \ /* if ( cdim < mnr ) */ \ { \ const dim_t i = cdim; \ const dim_t m_edge = mnr - cdim; \ const dim_t n_edge = n_max; \ ctype* restrict p_cast = p; \ ctype* restrict p_edge = p_cast + (i )*1; \ \ PASTEMAC(ch,set0s_mxn) \ ( \ m_edge, \ n_edge, \ p_edge, 1, ldp \ ); \ } \ } \ \ if ( n < n_max ) \ { \ const dim_t j = n; \ const dim_t m_edge = mnr; \ const dim_t n_edge = n_max - n; \ ctype* restrict p_cast = p; \ ctype* restrict p_edge = p_cast + (j )*ldp; \ \ PASTEMAC(ch,set0s_mxn) \ ( \ m_edge, \ n_edge, \ p_edge, 1, ldp \ ); \ } \ } INSERT_GENTFUNC_BASIC3( packm_16xk, 16, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, mnr, arch, suf ) \ \ void PASTEMAC3(ch,opname,arch,suf) \ ( \ conj_t conja, \ pack_t schema, \ dim_t cdim, \ dim_t n, \ dim_t n_max, \ ctype* restrict kappa, \ ctype* restrict a, inc_t inca, inc_t lda, \ ctype* restrict p, inc_t ldp, \ cntx_t* restrict cntx \ ) \ { \ ctype* restrict kappa_cast = kappa; \ ctype* restrict alpha1 = a; \ ctype* restrict pi1 = p; \ \ if ( cdim == mnr ) \ { \ if ( PASTEMAC(ch,eq1)( *kappa_cast ) ) \ { \ if ( bli_is_conj( conja ) ) \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,copyjs)( *(alpha1 + 0*inca), *(pi1 + 0) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 1*inca), *(pi1 + 1) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 2*inca), *(pi1 + 2) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 3*inca), *(pi1 + 3) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 4*inca), *(pi1 + 4) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 5*inca), *(pi1 + 5) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 6*inca), *(pi1 + 6) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 7*inca), *(pi1 + 7) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 8*inca), *(pi1 + 8) ); \ PASTEMAC(ch,copyjs)( *(alpha1 + 9*inca), *(pi1 + 9) ); \ PASTEMAC(ch,copyjs)( *(alpha1 +10*inca), *(pi1 +10) ); \ PASTEMAC(ch,copyjs)( *(alpha1 +11*inca), *(pi1 +11) ); \ PASTEMAC(ch,copyjs)( *(alpha1 +12*inca), *(pi1 +12) ); \ PASTEMAC(ch,copyjs)( *(alpha1 +13*inca), *(pi1 +13) ); \ PASTEMAC(ch,copyjs)( *(alpha1 +14*inca), *(pi1 +14) ); \ PASTEMAC(ch,copyjs)( *(alpha1 +15*inca), *(pi1 +15) ); \ PASTEMAC(ch,copyjs)( *(alpha1 +16*inca), *(pi1 +16) ); \ PASTEMAC(ch,copyjs)( *(alpha1 +17*inca), *(pi1 +17) ); \ PASTEMAC(ch,copyjs)( *(alpha1 +18*inca), *(pi1 +18) ); \ PASTEMAC(ch,copyjs)( *(alpha1 +19*inca), *(pi1 +19) ); \ PASTEMAC(ch,copyjs)( *(alpha1 +20*inca), *(pi1 +20) ); \ PASTEMAC(ch,copyjs)( *(alpha1 +21*inca), *(pi1 +21) ); \ PASTEMAC(ch,copyjs)( *(alpha1 +22*inca), *(pi1 +22) ); \ PASTEMAC(ch,copyjs)( *(alpha1 +23*inca), *(pi1 +23) ); \ \ alpha1 += lda; \ pi1 += ldp; \ } \ } \ else \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,copys)( *(alpha1 + 0*inca), *(pi1 + 0) ); \ PASTEMAC(ch,copys)( *(alpha1 + 1*inca), *(pi1 + 1) ); \ PASTEMAC(ch,copys)( *(alpha1 + 2*inca), *(pi1 + 2) ); \ PASTEMAC(ch,copys)( *(alpha1 + 3*inca), *(pi1 + 3) ); \ PASTEMAC(ch,copys)( *(alpha1 + 4*inca), *(pi1 + 4) ); \ PASTEMAC(ch,copys)( *(alpha1 + 5*inca), *(pi1 + 5) ); \ PASTEMAC(ch,copys)( *(alpha1 + 6*inca), *(pi1 + 6) ); \ PASTEMAC(ch,copys)( *(alpha1 + 7*inca), *(pi1 + 7) ); \ PASTEMAC(ch,copys)( *(alpha1 + 8*inca), *(pi1 + 8) ); \ PASTEMAC(ch,copys)( *(alpha1 + 9*inca), *(pi1 + 9) ); \ PASTEMAC(ch,copys)( *(alpha1 +10*inca), *(pi1 +10) ); \ PASTEMAC(ch,copys)( *(alpha1 +11*inca), *(pi1 +11) ); \ PASTEMAC(ch,copys)( *(alpha1 +12*inca), *(pi1 +12) ); \ PASTEMAC(ch,copys)( *(alpha1 +13*inca), *(pi1 +13) ); \ PASTEMAC(ch,copys)( *(alpha1 +14*inca), *(pi1 +14) ); \ PASTEMAC(ch,copys)( *(alpha1 +15*inca), *(pi1 +15) ); \ PASTEMAC(ch,copys)( *(alpha1 +16*inca), *(pi1 +16) ); \ PASTEMAC(ch,copys)( *(alpha1 +17*inca), *(pi1 +17) ); \ PASTEMAC(ch,copys)( *(alpha1 +18*inca), *(pi1 +18) ); \ PASTEMAC(ch,copys)( *(alpha1 +19*inca), *(pi1 +19) ); \ PASTEMAC(ch,copys)( *(alpha1 +20*inca), *(pi1 +20) ); \ PASTEMAC(ch,copys)( *(alpha1 +21*inca), *(pi1 +21) ); \ PASTEMAC(ch,copys)( *(alpha1 +22*inca), *(pi1 +22) ); \ PASTEMAC(ch,copys)( *(alpha1 +23*inca), *(pi1 +23) ); \ \ alpha1 += lda; \ pi1 += ldp; \ } \ } \ } \ else \ { \ if ( bli_is_conj( conja ) ) \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 0*inca), *(pi1 + 0) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 1*inca), *(pi1 + 1) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 2*inca), *(pi1 + 2) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 3*inca), *(pi1 + 3) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 4*inca), *(pi1 + 4) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 5*inca), *(pi1 + 5) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 6*inca), *(pi1 + 6) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 7*inca), *(pi1 + 7) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 8*inca), *(pi1 + 8) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 + 9*inca), *(pi1 + 9) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 +10*inca), *(pi1 +10) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 +11*inca), *(pi1 +11) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 +12*inca), *(pi1 +12) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 +13*inca), *(pi1 +13) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 +14*inca), *(pi1 +14) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 +15*inca), *(pi1 +15) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 +16*inca), *(pi1 +16) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 +17*inca), *(pi1 +17) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 +18*inca), *(pi1 +18) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 +19*inca), *(pi1 +19) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 +20*inca), *(pi1 +20) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 +21*inca), *(pi1 +21) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 +22*inca), *(pi1 +22) ); \ PASTEMAC(ch,scal2js)( *kappa_cast, *(alpha1 +23*inca), *(pi1 +23) ); \ \ alpha1 += lda; \ pi1 += ldp; \ } \ } \ else \ { \ for ( dim_t k = n; k != 0; --k ) \ { \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 0*inca), *(pi1 + 0) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 1*inca), *(pi1 + 1) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 2*inca), *(pi1 + 2) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 3*inca), *(pi1 + 3) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 4*inca), *(pi1 + 4) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 5*inca), *(pi1 + 5) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 6*inca), *(pi1 + 6) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 7*inca), *(pi1 + 7) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 8*inca), *(pi1 + 8) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 + 9*inca), *(pi1 + 9) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 +10*inca), *(pi1 +10) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 +11*inca), *(pi1 +11) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 +12*inca), *(pi1 +12) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 +13*inca), *(pi1 +13) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 +14*inca), *(pi1 +14) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 +15*inca), *(pi1 +15) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 +16*inca), *(pi1 +16) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 +17*inca), *(pi1 +17) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 +18*inca), *(pi1 +18) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 +19*inca), *(pi1 +19) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 +20*inca), *(pi1 +20) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 +21*inca), *(pi1 +21) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 +22*inca), *(pi1 +22) ); \ PASTEMAC(ch,scal2s)( *kappa_cast, *(alpha1 +23*inca), *(pi1 +23) ); \ \ alpha1 += lda; \ pi1 += ldp; \ } \ } \ } \ } \ else /* if ( cdim < mnr ) */ \ { \ PASTEMAC2(ch,scal2m,BLIS_TAPI_EX_SUF) \ ( \ 0, \ BLIS_NONUNIT_DIAG, \ BLIS_DENSE, \ ( trans_t )conja, \ cdim, \ n, \ kappa, \ a, inca, lda, \ p, 1, ldp, \ cntx, \ NULL \ ); \ \ /* if ( cdim < mnr ) */ \ { \ const dim_t i = cdim; \ const dim_t m_edge = mnr - cdim; \ const dim_t n_edge = n_max; \ ctype* restrict p_cast = p; \ ctype* restrict p_edge = p_cast + (i )*1; \ \ PASTEMAC(ch,set0s_mxn) \ ( \ m_edge, \ n_edge, \ p_edge, 1, ldp \ ); \ } \ } \ \ if ( n < n_max ) \ { \ const dim_t j = n; \ const dim_t m_edge = mnr; \ const dim_t n_edge = n_max - n; \ ctype* restrict p_cast = p; \ ctype* restrict p_edge = p_cast + (j )*ldp; \ \ PASTEMAC(ch,set0s_mxn) \ ( \ m_edge, \ n_edge, \ p_edge, 1, ldp \ ); \ } \ } INSERT_GENTFUNC_BASIC3( packm_24xk, 24, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX ) blis-0.9.0/ref_kernels/1m/bli_unpackm_cxk_ref.c000066400000000000000000000754651422157504600214450ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, arch, suf ) \ \ void PASTEMAC3(ch,opname,arch,suf) \ ( \ conj_t conjp, \ dim_t n, \ void* restrict kappa, \ void* restrict p, inc_t ldp, \ void* restrict a, inc_t inca, inc_t lda, \ cntx_t* restrict cntx \ ) \ { \ ctype* restrict kappa_cast = kappa; \ ctype* restrict pi1 = p; \ ctype* restrict alpha1 = a; \ \ if ( PASTEMAC(ch,eq1)( *kappa_cast ) ) \ { \ if ( bli_is_conj( conjp ) ) \ { \ for ( ; n != 0; --n ) \ { \ PASTEMAC2(ch,ch,copyjs)( *(pi1 + 0), *(alpha1 + 0*inca) ); \ PASTEMAC2(ch,ch,copyjs)( *(pi1 + 1), *(alpha1 + 1*inca) ); \ \ pi1 += ldp; \ alpha1 += lda; \ } \ } \ else \ { \ for ( ; n != 0; --n ) \ { \ PASTEMAC2(ch,ch,copys)( *(pi1 + 0), *(alpha1 + 0*inca) ); \ PASTEMAC2(ch,ch,copys)( *(pi1 + 1), *(alpha1 + 1*inca) ); \ \ pi1 += ldp; \ alpha1 += lda; \ } \ } \ } \ else \ { \ if ( bli_is_conj( conjp ) ) \ { \ for ( ; n != 0; --n ) \ { \ PASTEMAC3(ch,ch,ch,scal2js)( *kappa_cast, *(pi1 + 0), *(alpha1 + 0*inca) ); \ PASTEMAC3(ch,ch,ch,scal2js)( *kappa_cast, *(pi1 + 1), *(alpha1 + 1*inca) ); \ \ pi1 += ldp; \ alpha1 += lda; \ } \ } \ else \ { \ for ( ; n != 0; --n ) \ { \ PASTEMAC3(ch,ch,ch,scal2s)( *kappa_cast, *(pi1 + 0), *(alpha1 + 0*inca) ); \ PASTEMAC3(ch,ch,ch,scal2s)( *kappa_cast, *(pi1 + 1), *(alpha1 + 1*inca) ); \ \ pi1 += ldp; \ alpha1 += lda; \ } \ } \ } \ } INSERT_GENTFUNC_BASIC2( unpackm_2xk, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, arch, suf ) \ \ void PASTEMAC3(ch,opname,arch,suf) \ ( \ conj_t conjp, \ dim_t n, \ void* restrict kappa, \ void* restrict p, inc_t ldp, \ void* restrict a, inc_t inca, inc_t lda, \ cntx_t* restrict cntx \ ) \ { \ ctype* restrict kappa_cast = kappa; \ ctype* restrict pi1 = p; \ ctype* restrict alpha1 = a; \ \ if ( PASTEMAC(ch,eq1)( *kappa_cast ) ) \ { \ if ( bli_is_conj( conjp ) ) \ { \ for ( ; n != 0; --n ) \ { \ PASTEMAC2(ch,ch,copyjs)( *(pi1 + 0), *(alpha1 + 0*inca) ); \ PASTEMAC2(ch,ch,copyjs)( *(pi1 + 1), *(alpha1 + 1*inca) ); \ PASTEMAC2(ch,ch,copyjs)( *(pi1 + 2), *(alpha1 + 2*inca) ); \ PASTEMAC2(ch,ch,copyjs)( *(pi1 + 3), *(alpha1 + 3*inca) ); \ \ pi1 += ldp; \ alpha1 += lda; \ } \ } \ else \ { \ for ( ; n != 0; --n ) \ { \ PASTEMAC2(ch,ch,copys)( *(pi1 + 0), *(alpha1 + 0*inca) ); \ PASTEMAC2(ch,ch,copys)( *(pi1 + 1), *(alpha1 + 1*inca) ); \ PASTEMAC2(ch,ch,copys)( *(pi1 + 2), *(alpha1 + 2*inca) ); \ PASTEMAC2(ch,ch,copys)( *(pi1 + 3), *(alpha1 + 3*inca) ); \ \ pi1 += ldp; \ alpha1 += lda; \ } \ } \ } \ else \ { \ if ( bli_is_conj( conjp ) ) \ { \ for ( ; n != 0; --n ) \ { \ PASTEMAC3(ch,ch,ch,scal2js)( *kappa_cast, *(pi1 + 0), *(alpha1 + 0*inca) ); \ PASTEMAC3(ch,ch,ch,scal2js)( *kappa_cast, *(pi1 + 1), *(alpha1 + 1*inca) ); \ PASTEMAC3(ch,ch,ch,scal2js)( *kappa_cast, *(pi1 + 2), *(alpha1 + 2*inca) ); \ PASTEMAC3(ch,ch,ch,scal2js)( *kappa_cast, *(pi1 + 3), *(alpha1 + 3*inca) ); \ \ pi1 += ldp; \ alpha1 += lda; \ } \ } \ else \ { \ for ( ; n != 0; --n ) \ { \ PASTEMAC3(ch,ch,ch,scal2s)( *kappa_cast, *(pi1 + 0), *(alpha1 + 0*inca) ); \ PASTEMAC3(ch,ch,ch,scal2s)( *kappa_cast, *(pi1 + 1), *(alpha1 + 1*inca) ); \ PASTEMAC3(ch,ch,ch,scal2s)( *kappa_cast, *(pi1 + 2), *(alpha1 + 2*inca) ); \ PASTEMAC3(ch,ch,ch,scal2s)( *kappa_cast, *(pi1 + 3), *(alpha1 + 3*inca) ); \ \ pi1 += ldp; \ alpha1 += lda; \ } \ } \ } \ } INSERT_GENTFUNC_BASIC2( unpackm_4xk, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, arch, suf ) \ \ void PASTEMAC3(ch,opname,arch,suf) \ ( \ conj_t conjp, \ dim_t n, \ void* restrict kappa, \ void* restrict p, inc_t ldp, \ void* restrict a, inc_t inca, inc_t lda, \ cntx_t* restrict cntx \ ) \ { \ ctype* restrict kappa_cast = kappa; \ ctype* restrict pi1 = p; \ ctype* restrict alpha1 = a; \ \ if ( PASTEMAC(ch,eq1)( *kappa_cast ) ) \ { \ if ( bli_is_conj( conjp ) ) \ { \ for ( ; n != 0; --n ) \ { \ PASTEMAC2(ch,ch,copyjs)( *(pi1 + 0), *(alpha1 + 0*inca) ); \ PASTEMAC2(ch,ch,copyjs)( *(pi1 + 1), *(alpha1 + 1*inca) ); \ PASTEMAC2(ch,ch,copyjs)( *(pi1 + 2), *(alpha1 + 2*inca) ); \ PASTEMAC2(ch,ch,copyjs)( *(pi1 + 3), *(alpha1 + 3*inca) ); \ PASTEMAC2(ch,ch,copyjs)( *(pi1 + 4), *(alpha1 + 4*inca) ); \ PASTEMAC2(ch,ch,copyjs)( *(pi1 + 5), *(alpha1 + 5*inca) ); \ \ pi1 += ldp; \ alpha1 += lda; \ } \ } \ else \ { \ for ( ; n != 0; --n ) \ { \ PASTEMAC2(ch,ch,copys)( *(pi1 + 0), *(alpha1 + 0*inca) ); \ PASTEMAC2(ch,ch,copys)( *(pi1 + 1), *(alpha1 + 1*inca) ); \ PASTEMAC2(ch,ch,copys)( *(pi1 + 2), *(alpha1 + 2*inca) ); \ PASTEMAC2(ch,ch,copys)( *(pi1 + 3), *(alpha1 + 3*inca) ); \ PASTEMAC2(ch,ch,copys)( *(pi1 + 4), *(alpha1 + 4*inca) ); \ PASTEMAC2(ch,ch,copys)( *(pi1 + 5), *(alpha1 + 5*inca) ); \ \ pi1 += ldp; \ alpha1 += lda; \ } \ } \ } \ else \ { \ if ( bli_is_conj( conjp ) ) \ { \ for ( ; n != 0; --n ) \ { \ PASTEMAC3(ch,ch,ch,scal2js)( *kappa_cast, *(pi1 + 0), *(alpha1 + 0*inca) ); \ PASTEMAC3(ch,ch,ch,scal2js)( *kappa_cast, *(pi1 + 1), *(alpha1 + 1*inca) ); \ PASTEMAC3(ch,ch,ch,scal2js)( *kappa_cast, *(pi1 + 2), *(alpha1 + 2*inca) ); \ PASTEMAC3(ch,ch,ch,scal2js)( *kappa_cast, *(pi1 + 3), *(alpha1 + 3*inca) ); \ PASTEMAC3(ch,ch,ch,scal2js)( *kappa_cast, *(pi1 + 4), *(alpha1 + 4*inca) ); \ PASTEMAC3(ch,ch,ch,scal2js)( *kappa_cast, *(pi1 + 5), *(alpha1 + 5*inca) ); \ \ pi1 += ldp; \ alpha1 += lda; \ } \ } \ else \ { \ for ( ; n != 0; --n ) \ { \ PASTEMAC3(ch,ch,ch,scal2s)( *kappa_cast, *(pi1 + 0), *(alpha1 + 0*inca) ); \ PASTEMAC3(ch,ch,ch,scal2s)( *kappa_cast, *(pi1 + 1), *(alpha1 + 1*inca) ); \ PASTEMAC3(ch,ch,ch,scal2s)( *kappa_cast, *(pi1 + 2), *(alpha1 + 2*inca) ); \ PASTEMAC3(ch,ch,ch,scal2s)( *kappa_cast, *(pi1 + 3), *(alpha1 + 3*inca) ); \ PASTEMAC3(ch,ch,ch,scal2s)( *kappa_cast, *(pi1 + 4), *(alpha1 + 4*inca) ); \ PASTEMAC3(ch,ch,ch,scal2s)( *kappa_cast, *(pi1 + 5), *(alpha1 + 5*inca) ); \ \ pi1 += ldp; \ alpha1 += lda; \ } \ } \ } \ } INSERT_GENTFUNC_BASIC2( unpackm_6xk, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, arch, suf ) \ \ void PASTEMAC3(ch,opname,arch,suf) \ ( \ conj_t conjp, \ dim_t n, \ void* restrict kappa, \ void* restrict p, inc_t ldp, \ void* restrict a, inc_t inca, inc_t lda, \ cntx_t* restrict cntx \ ) \ { \ ctype* restrict kappa_cast = kappa; \ ctype* restrict pi1 = p; \ ctype* restrict alpha1 = a; \ \ if ( PASTEMAC(ch,eq1)( *kappa_cast ) ) \ { \ if ( bli_is_conj( conjp ) ) \ { \ for ( ; n != 0; --n ) \ { \ PASTEMAC2(ch,ch,copyjs)( *(pi1 + 0), *(alpha1 + 0*inca) ); \ PASTEMAC2(ch,ch,copyjs)( *(pi1 + 1), *(alpha1 + 1*inca) ); \ PASTEMAC2(ch,ch,copyjs)( *(pi1 + 2), *(alpha1 + 2*inca) ); \ PASTEMAC2(ch,ch,copyjs)( *(pi1 + 3), *(alpha1 + 3*inca) ); \ PASTEMAC2(ch,ch,copyjs)( *(pi1 + 4), *(alpha1 + 4*inca) ); \ PASTEMAC2(ch,ch,copyjs)( *(pi1 + 5), *(alpha1 + 5*inca) ); \ PASTEMAC2(ch,ch,copyjs)( *(pi1 + 6), *(alpha1 + 6*inca) ); \ PASTEMAC2(ch,ch,copyjs)( *(pi1 + 7), *(alpha1 + 7*inca) ); \ \ pi1 += ldp; \ alpha1 += lda; \ } \ } \ else \ { \ for ( ; n != 0; --n ) \ { \ PASTEMAC2(ch,ch,copys)( *(pi1 + 0), *(alpha1 + 0*inca) ); \ PASTEMAC2(ch,ch,copys)( *(pi1 + 1), *(alpha1 + 1*inca) ); \ PASTEMAC2(ch,ch,copys)( *(pi1 + 2), *(alpha1 + 2*inca) ); \ PASTEMAC2(ch,ch,copys)( *(pi1 + 3), *(alpha1 + 3*inca) ); \ PASTEMAC2(ch,ch,copys)( *(pi1 + 4), *(alpha1 + 4*inca) ); \ PASTEMAC2(ch,ch,copys)( *(pi1 + 5), *(alpha1 + 5*inca) ); \ PASTEMAC2(ch,ch,copys)( *(pi1 + 6), *(alpha1 + 6*inca) ); \ PASTEMAC2(ch,ch,copys)( *(pi1 + 7), *(alpha1 + 7*inca) ); \ \ pi1 += ldp; \ alpha1 += lda; \ } \ } \ } \ else \ { \ if ( bli_is_conj( conjp ) ) \ { \ for ( ; n != 0; --n ) \ { \ PASTEMAC3(ch,ch,ch,scal2js)( *kappa_cast, *(pi1 + 0), *(alpha1 + 0*inca) ); \ PASTEMAC3(ch,ch,ch,scal2js)( *kappa_cast, *(pi1 + 1), *(alpha1 + 1*inca) ); \ PASTEMAC3(ch,ch,ch,scal2js)( *kappa_cast, *(pi1 + 2), *(alpha1 + 2*inca) ); \ PASTEMAC3(ch,ch,ch,scal2js)( *kappa_cast, *(pi1 + 3), *(alpha1 + 3*inca) ); \ PASTEMAC3(ch,ch,ch,scal2js)( *kappa_cast, *(pi1 + 4), *(alpha1 + 4*inca) ); \ PASTEMAC3(ch,ch,ch,scal2js)( *kappa_cast, *(pi1 + 5), *(alpha1 + 5*inca) ); \ PASTEMAC3(ch,ch,ch,scal2js)( *kappa_cast, *(pi1 + 6), *(alpha1 + 6*inca) ); \ PASTEMAC3(ch,ch,ch,scal2js)( *kappa_cast, *(pi1 + 7), *(alpha1 + 7*inca) ); \ \ pi1 += ldp; \ alpha1 += lda; \ } \ } \ else \ { \ for ( ; n != 0; --n ) \ { \ PASTEMAC3(ch,ch,ch,scal2s)( *kappa_cast, *(pi1 + 0), *(alpha1 + 0*inca) ); \ PASTEMAC3(ch,ch,ch,scal2s)( *kappa_cast, *(pi1 + 1), *(alpha1 + 1*inca) ); \ PASTEMAC3(ch,ch,ch,scal2s)( *kappa_cast, *(pi1 + 2), *(alpha1 + 2*inca) ); \ PASTEMAC3(ch,ch,ch,scal2s)( *kappa_cast, *(pi1 + 3), *(alpha1 + 3*inca) ); \ PASTEMAC3(ch,ch,ch,scal2s)( *kappa_cast, *(pi1 + 4), *(alpha1 + 4*inca) ); \ PASTEMAC3(ch,ch,ch,scal2s)( *kappa_cast, *(pi1 + 5), *(alpha1 + 5*inca) ); \ PASTEMAC3(ch,ch,ch,scal2s)( *kappa_cast, *(pi1 + 6), *(alpha1 + 6*inca) ); \ PASTEMAC3(ch,ch,ch,scal2s)( *kappa_cast, *(pi1 + 7), *(alpha1 + 7*inca) ); \ \ pi1 += ldp; \ alpha1 += lda; \ } \ } \ } \ } INSERT_GENTFUNC_BASIC2( unpackm_8xk, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, arch, suf ) \ \ void PASTEMAC3(ch,opname,arch,suf) \ ( \ conj_t conjp, \ dim_t n, \ void* restrict kappa, \ void* restrict p, inc_t ldp, \ void* restrict a, inc_t inca, inc_t lda, \ cntx_t* restrict cntx \ ) \ { \ ctype* restrict kappa_cast = kappa; \ ctype* restrict pi1 = p; \ ctype* restrict alpha1 = a; \ \ if ( PASTEMAC(ch,eq1)( *kappa_cast ) ) \ { \ if ( bli_is_conj( conjp ) ) \ { \ for ( ; n != 0; --n ) \ { \ PASTEMAC2(ch,ch,copyjs)( *(pi1 + 0), *(alpha1 + 0*inca) ); \ PASTEMAC2(ch,ch,copyjs)( *(pi1 + 1), *(alpha1 + 1*inca) ); \ PASTEMAC2(ch,ch,copyjs)( *(pi1 + 2), *(alpha1 + 2*inca) ); \ PASTEMAC2(ch,ch,copyjs)( *(pi1 + 3), *(alpha1 + 3*inca) ); \ PASTEMAC2(ch,ch,copyjs)( *(pi1 + 4), *(alpha1 + 4*inca) ); \ PASTEMAC2(ch,ch,copyjs)( *(pi1 + 5), *(alpha1 + 5*inca) ); \ PASTEMAC2(ch,ch,copyjs)( *(pi1 + 6), *(alpha1 + 6*inca) ); \ PASTEMAC2(ch,ch,copyjs)( *(pi1 + 7), *(alpha1 + 7*inca) ); \ PASTEMAC2(ch,ch,copyjs)( *(pi1 + 8), *(alpha1 + 8*inca) ); \ PASTEMAC2(ch,ch,copyjs)( *(pi1 + 9), *(alpha1 + 9*inca) ); \ \ pi1 += ldp; \ alpha1 += lda; \ } \ } \ else \ { \ for ( ; n != 0; --n ) \ { \ PASTEMAC2(ch,ch,copys)( *(pi1 + 0), *(alpha1 + 0*inca) ); \ PASTEMAC2(ch,ch,copys)( *(pi1 + 1), *(alpha1 + 1*inca) ); \ PASTEMAC2(ch,ch,copys)( *(pi1 + 2), *(alpha1 + 2*inca) ); \ PASTEMAC2(ch,ch,copys)( *(pi1 + 3), *(alpha1 + 3*inca) ); \ PASTEMAC2(ch,ch,copys)( *(pi1 + 4), *(alpha1 + 4*inca) ); \ PASTEMAC2(ch,ch,copys)( *(pi1 + 5), *(alpha1 + 5*inca) ); \ PASTEMAC2(ch,ch,copys)( *(pi1 + 6), *(alpha1 + 6*inca) ); \ PASTEMAC2(ch,ch,copys)( *(pi1 + 7), *(alpha1 + 7*inca) ); \ PASTEMAC2(ch,ch,copys)( *(pi1 + 8), *(alpha1 + 8*inca) ); \ PASTEMAC2(ch,ch,copys)( *(pi1 + 9), *(alpha1 + 9*inca) ); \ \ pi1 += ldp; \ alpha1 += lda; \ } \ } \ } \ else \ { \ if ( bli_is_conj( conjp ) ) \ { \ for ( ; n != 0; --n ) \ { \ PASTEMAC3(ch,ch,ch,scal2js)( *kappa_cast, *(pi1 + 0), *(alpha1 + 0*inca) ); \ PASTEMAC3(ch,ch,ch,scal2js)( *kappa_cast, *(pi1 + 1), *(alpha1 + 1*inca) ); \ PASTEMAC3(ch,ch,ch,scal2js)( *kappa_cast, *(pi1 + 2), *(alpha1 + 2*inca) ); \ PASTEMAC3(ch,ch,ch,scal2js)( *kappa_cast, *(pi1 + 3), *(alpha1 + 3*inca) ); \ PASTEMAC3(ch,ch,ch,scal2js)( *kappa_cast, *(pi1 + 4), *(alpha1 + 4*inca) ); \ PASTEMAC3(ch,ch,ch,scal2js)( *kappa_cast, *(pi1 + 5), *(alpha1 + 5*inca) ); \ PASTEMAC3(ch,ch,ch,scal2js)( *kappa_cast, *(pi1 + 6), *(alpha1 + 6*inca) ); \ PASTEMAC3(ch,ch,ch,scal2js)( *kappa_cast, *(pi1 + 7), *(alpha1 + 7*inca) ); \ PASTEMAC3(ch,ch,ch,scal2js)( *kappa_cast, *(pi1 + 8), *(alpha1 + 8*inca) ); \ PASTEMAC3(ch,ch,ch,scal2js)( *kappa_cast, *(pi1 + 9), *(alpha1 + 9*inca) ); \ \ pi1 += ldp; \ alpha1 += lda; \ } \ } \ else \ { \ for ( ; n != 0; --n ) \ { \ PASTEMAC3(ch,ch,ch,scal2s)( *kappa_cast, *(pi1 + 0), *(alpha1 + 0*inca) ); \ PASTEMAC3(ch,ch,ch,scal2s)( *kappa_cast, *(pi1 + 1), *(alpha1 + 1*inca) ); \ PASTEMAC3(ch,ch,ch,scal2s)( *kappa_cast, *(pi1 + 2), *(alpha1 + 2*inca) ); \ PASTEMAC3(ch,ch,ch,scal2s)( *kappa_cast, *(pi1 + 3), *(alpha1 + 3*inca) ); \ PASTEMAC3(ch,ch,ch,scal2s)( *kappa_cast, *(pi1 + 4), *(alpha1 + 4*inca) ); \ PASTEMAC3(ch,ch,ch,scal2s)( *kappa_cast, *(pi1 + 5), *(alpha1 + 5*inca) ); \ PASTEMAC3(ch,ch,ch,scal2s)( *kappa_cast, *(pi1 + 6), *(alpha1 + 6*inca) ); \ PASTEMAC3(ch,ch,ch,scal2s)( *kappa_cast, *(pi1 + 7), *(alpha1 + 7*inca) ); \ PASTEMAC3(ch,ch,ch,scal2s)( *kappa_cast, *(pi1 + 8), *(alpha1 + 8*inca) ); \ PASTEMAC3(ch,ch,ch,scal2s)( *kappa_cast, *(pi1 + 9), *(alpha1 + 9*inca) ); \ \ pi1 += ldp; \ alpha1 += lda; \ } \ } \ } \ } INSERT_GENTFUNC_BASIC2( unpackm_10xk, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, arch, suf ) \ \ void PASTEMAC3(ch,opname,arch,suf) \ ( \ conj_t conjp, \ dim_t n, \ void* restrict kappa, \ void* restrict p, inc_t ldp, \ void* restrict a, inc_t inca, inc_t lda, \ cntx_t* restrict cntx \ ) \ { \ ctype* restrict kappa_cast = kappa; \ ctype* restrict pi1 = p; \ ctype* restrict alpha1 = a; \ \ if ( PASTEMAC(ch,eq1)( *kappa_cast ) ) \ { \ if ( bli_is_conj( conjp ) ) \ { \ for ( ; n != 0; --n ) \ { \ PASTEMAC2(ch,ch,copyjs)( *(pi1 + 0), *(alpha1 + 0*inca) ); \ PASTEMAC2(ch,ch,copyjs)( *(pi1 + 1), *(alpha1 + 1*inca) ); \ PASTEMAC2(ch,ch,copyjs)( *(pi1 + 2), *(alpha1 + 2*inca) ); \ PASTEMAC2(ch,ch,copyjs)( *(pi1 + 3), *(alpha1 + 3*inca) ); \ PASTEMAC2(ch,ch,copyjs)( *(pi1 + 4), *(alpha1 + 4*inca) ); \ PASTEMAC2(ch,ch,copyjs)( *(pi1 + 5), *(alpha1 + 5*inca) ); \ PASTEMAC2(ch,ch,copyjs)( *(pi1 + 6), *(alpha1 + 6*inca) ); \ PASTEMAC2(ch,ch,copyjs)( *(pi1 + 7), *(alpha1 + 7*inca) ); \ PASTEMAC2(ch,ch,copyjs)( *(pi1 + 8), *(alpha1 + 8*inca) ); \ PASTEMAC2(ch,ch,copyjs)( *(pi1 + 9), *(alpha1 + 9*inca) ); \ PASTEMAC2(ch,ch,copyjs)( *(pi1 + 10), *(alpha1 + 10*inca) ); \ PASTEMAC2(ch,ch,copyjs)( *(pi1 + 11), *(alpha1 + 11*inca) ); \ \ pi1 += ldp; \ alpha1 += lda; \ } \ } \ else \ { \ for ( ; n != 0; --n ) \ { \ PASTEMAC2(ch,ch,copys)( *(pi1 + 0), *(alpha1 + 0*inca) ); \ PASTEMAC2(ch,ch,copys)( *(pi1 + 1), *(alpha1 + 1*inca) ); \ PASTEMAC2(ch,ch,copys)( *(pi1 + 2), *(alpha1 + 2*inca) ); \ PASTEMAC2(ch,ch,copys)( *(pi1 + 3), *(alpha1 + 3*inca) ); \ PASTEMAC2(ch,ch,copys)( *(pi1 + 4), *(alpha1 + 4*inca) ); \ PASTEMAC2(ch,ch,copys)( *(pi1 + 5), *(alpha1 + 5*inca) ); \ PASTEMAC2(ch,ch,copys)( *(pi1 + 6), *(alpha1 + 6*inca) ); \ PASTEMAC2(ch,ch,copys)( *(pi1 + 7), *(alpha1 + 7*inca) ); \ PASTEMAC2(ch,ch,copys)( *(pi1 + 8), *(alpha1 + 8*inca) ); \ PASTEMAC2(ch,ch,copys)( *(pi1 + 9), *(alpha1 + 9*inca) ); \ PASTEMAC2(ch,ch,copys)( *(pi1 + 10), *(alpha1 + 10*inca) ); \ PASTEMAC2(ch,ch,copys)( *(pi1 + 11), *(alpha1 + 11*inca) ); \ \ pi1 += ldp; \ alpha1 += lda; \ } \ } \ } \ else \ { \ if ( bli_is_conj( conjp ) ) \ { \ for ( ; n != 0; --n ) \ { \ PASTEMAC3(ch,ch,ch,scal2js)( *kappa_cast, *(pi1 + 0), *(alpha1 + 0*inca) ); \ PASTEMAC3(ch,ch,ch,scal2js)( *kappa_cast, *(pi1 + 1), *(alpha1 + 1*inca) ); \ PASTEMAC3(ch,ch,ch,scal2js)( *kappa_cast, *(pi1 + 2), *(alpha1 + 2*inca) ); \ PASTEMAC3(ch,ch,ch,scal2js)( *kappa_cast, *(pi1 + 3), *(alpha1 + 3*inca) ); \ PASTEMAC3(ch,ch,ch,scal2js)( *kappa_cast, *(pi1 + 4), *(alpha1 + 4*inca) ); \ PASTEMAC3(ch,ch,ch,scal2js)( *kappa_cast, *(pi1 + 5), *(alpha1 + 5*inca) ); \ PASTEMAC3(ch,ch,ch,scal2js)( *kappa_cast, *(pi1 + 6), *(alpha1 + 6*inca) ); \ PASTEMAC3(ch,ch,ch,scal2js)( *kappa_cast, *(pi1 + 7), *(alpha1 + 7*inca) ); \ PASTEMAC3(ch,ch,ch,scal2js)( *kappa_cast, *(pi1 + 8), *(alpha1 + 8*inca) ); \ PASTEMAC3(ch,ch,ch,scal2js)( *kappa_cast, *(pi1 + 9), *(alpha1 + 9*inca) ); \ PASTEMAC3(ch,ch,ch,scal2js)( *kappa_cast, *(pi1 + 10), *(alpha1 + 10*inca) ); \ PASTEMAC3(ch,ch,ch,scal2js)( *kappa_cast, *(pi1 + 11), *(alpha1 + 11*inca) ); \ \ pi1 += ldp; \ alpha1 += lda; \ } \ } \ else \ { \ for ( ; n != 0; --n ) \ { \ PASTEMAC3(ch,ch,ch,scal2s)( *kappa_cast, *(pi1 + 0), *(alpha1 + 0*inca) ); \ PASTEMAC3(ch,ch,ch,scal2s)( *kappa_cast, *(pi1 + 1), *(alpha1 + 1*inca) ); \ PASTEMAC3(ch,ch,ch,scal2s)( *kappa_cast, *(pi1 + 2), *(alpha1 + 2*inca) ); \ PASTEMAC3(ch,ch,ch,scal2s)( *kappa_cast, *(pi1 + 3), *(alpha1 + 3*inca) ); \ PASTEMAC3(ch,ch,ch,scal2s)( *kappa_cast, *(pi1 + 4), *(alpha1 + 4*inca) ); \ PASTEMAC3(ch,ch,ch,scal2s)( *kappa_cast, *(pi1 + 5), *(alpha1 + 5*inca) ); \ PASTEMAC3(ch,ch,ch,scal2s)( *kappa_cast, *(pi1 + 6), *(alpha1 + 6*inca) ); \ PASTEMAC3(ch,ch,ch,scal2s)( *kappa_cast, *(pi1 + 7), *(alpha1 + 7*inca) ); \ PASTEMAC3(ch,ch,ch,scal2s)( *kappa_cast, *(pi1 + 8), *(alpha1 + 8*inca) ); \ PASTEMAC3(ch,ch,ch,scal2s)( *kappa_cast, *(pi1 + 9), *(alpha1 + 9*inca) ); \ PASTEMAC3(ch,ch,ch,scal2s)( *kappa_cast, *(pi1 + 10), *(alpha1 + 10*inca) ); \ PASTEMAC3(ch,ch,ch,scal2s)( *kappa_cast, *(pi1 + 11), *(alpha1 + 11*inca) ); \ \ pi1 += ldp; \ alpha1 += lda; \ } \ } \ } \ } INSERT_GENTFUNC_BASIC2( unpackm_12xk, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, arch, suf ) \ \ void PASTEMAC3(ch,opname,arch,suf) \ ( \ conj_t conjp, \ dim_t n, \ void* restrict kappa, \ void* restrict p, inc_t ldp, \ void* restrict a, inc_t inca, inc_t lda, \ cntx_t* restrict cntx \ ) \ { \ ctype* restrict kappa_cast = kappa; \ ctype* restrict pi1 = p; \ ctype* restrict alpha1 = a; \ \ if ( PASTEMAC(ch,eq1)( *kappa_cast ) ) \ { \ if ( bli_is_conj( conjp ) ) \ { \ for ( ; n != 0; --n ) \ { \ PASTEMAC2(ch,ch,copyjs)( *(pi1 + 0), *(alpha1 + 0*inca) ); \ PASTEMAC2(ch,ch,copyjs)( *(pi1 + 1), *(alpha1 + 1*inca) ); \ PASTEMAC2(ch,ch,copyjs)( *(pi1 + 2), *(alpha1 + 2*inca) ); \ PASTEMAC2(ch,ch,copyjs)( *(pi1 + 3), *(alpha1 + 3*inca) ); \ PASTEMAC2(ch,ch,copyjs)( *(pi1 + 4), *(alpha1 + 4*inca) ); \ PASTEMAC2(ch,ch,copyjs)( *(pi1 + 5), *(alpha1 + 5*inca) ); \ PASTEMAC2(ch,ch,copyjs)( *(pi1 + 6), *(alpha1 + 6*inca) ); \ PASTEMAC2(ch,ch,copyjs)( *(pi1 + 7), *(alpha1 + 7*inca) ); \ PASTEMAC2(ch,ch,copyjs)( *(pi1 + 8), *(alpha1 + 8*inca) ); \ PASTEMAC2(ch,ch,copyjs)( *(pi1 + 9), *(alpha1 + 9*inca) ); \ PASTEMAC2(ch,ch,copyjs)( *(pi1 + 10), *(alpha1 + 10*inca) ); \ PASTEMAC2(ch,ch,copyjs)( *(pi1 + 11), *(alpha1 + 11*inca) ); \ PASTEMAC2(ch,ch,copyjs)( *(pi1 + 12), *(alpha1 + 12*inca) ); \ PASTEMAC2(ch,ch,copyjs)( *(pi1 + 13), *(alpha1 + 13*inca) ); \ \ pi1 += ldp; \ alpha1 += lda; \ } \ } \ else \ { \ for ( ; n != 0; --n ) \ { \ PASTEMAC2(ch,ch,copys)( *(pi1 + 0), *(alpha1 + 0*inca) ); \ PASTEMAC2(ch,ch,copys)( *(pi1 + 1), *(alpha1 + 1*inca) ); \ PASTEMAC2(ch,ch,copys)( *(pi1 + 2), *(alpha1 + 2*inca) ); \ PASTEMAC2(ch,ch,copys)( *(pi1 + 3), *(alpha1 + 3*inca) ); \ PASTEMAC2(ch,ch,copys)( *(pi1 + 4), *(alpha1 + 4*inca) ); \ PASTEMAC2(ch,ch,copys)( *(pi1 + 5), *(alpha1 + 5*inca) ); \ PASTEMAC2(ch,ch,copys)( *(pi1 + 6), *(alpha1 + 6*inca) ); \ PASTEMAC2(ch,ch,copys)( *(pi1 + 7), *(alpha1 + 7*inca) ); \ PASTEMAC2(ch,ch,copys)( *(pi1 + 8), *(alpha1 + 8*inca) ); \ PASTEMAC2(ch,ch,copys)( *(pi1 + 9), *(alpha1 + 9*inca) ); \ PASTEMAC2(ch,ch,copys)( *(pi1 + 10), *(alpha1 + 10*inca) ); \ PASTEMAC2(ch,ch,copys)( *(pi1 + 11), *(alpha1 + 11*inca) ); \ PASTEMAC2(ch,ch,copys)( *(pi1 + 12), *(alpha1 + 12*inca) ); \ PASTEMAC2(ch,ch,copys)( *(pi1 + 13), *(alpha1 + 13*inca) ); \ \ pi1 += ldp; \ alpha1 += lda; \ } \ } \ } \ else \ { \ if ( bli_is_conj( conjp ) ) \ { \ for ( ; n != 0; --n ) \ { \ PASTEMAC3(ch,ch,ch,scal2js)( *kappa_cast, *(pi1 + 0), *(alpha1 + 0*inca) ); \ PASTEMAC3(ch,ch,ch,scal2js)( *kappa_cast, *(pi1 + 1), *(alpha1 + 1*inca) ); \ PASTEMAC3(ch,ch,ch,scal2js)( *kappa_cast, *(pi1 + 2), *(alpha1 + 2*inca) ); \ PASTEMAC3(ch,ch,ch,scal2js)( *kappa_cast, *(pi1 + 3), *(alpha1 + 3*inca) ); \ PASTEMAC3(ch,ch,ch,scal2js)( *kappa_cast, *(pi1 + 4), *(alpha1 + 4*inca) ); \ PASTEMAC3(ch,ch,ch,scal2js)( *kappa_cast, *(pi1 + 5), *(alpha1 + 5*inca) ); \ PASTEMAC3(ch,ch,ch,scal2js)( *kappa_cast, *(pi1 + 6), *(alpha1 + 6*inca) ); \ PASTEMAC3(ch,ch,ch,scal2js)( *kappa_cast, *(pi1 + 7), *(alpha1 + 7*inca) ); \ PASTEMAC3(ch,ch,ch,scal2js)( *kappa_cast, *(pi1 + 8), *(alpha1 + 8*inca) ); \ PASTEMAC3(ch,ch,ch,scal2js)( *kappa_cast, *(pi1 + 9), *(alpha1 + 9*inca) ); \ PASTEMAC3(ch,ch,ch,scal2js)( *kappa_cast, *(pi1 + 10), *(alpha1 + 10*inca) ); \ PASTEMAC3(ch,ch,ch,scal2js)( *kappa_cast, *(pi1 + 11), *(alpha1 + 11*inca) ); \ PASTEMAC3(ch,ch,ch,scal2js)( *kappa_cast, *(pi1 + 12), *(alpha1 + 12*inca) ); \ PASTEMAC3(ch,ch,ch,scal2js)( *kappa_cast, *(pi1 + 13), *(alpha1 + 13*inca) ); \ \ pi1 += ldp; \ alpha1 += lda; \ } \ } \ else \ { \ for ( ; n != 0; --n ) \ { \ PASTEMAC3(ch,ch,ch,scal2s)( *kappa_cast, *(pi1 + 0), *(alpha1 + 0*inca) ); \ PASTEMAC3(ch,ch,ch,scal2s)( *kappa_cast, *(pi1 + 1), *(alpha1 + 1*inca) ); \ PASTEMAC3(ch,ch,ch,scal2s)( *kappa_cast, *(pi1 + 2), *(alpha1 + 2*inca) ); \ PASTEMAC3(ch,ch,ch,scal2s)( *kappa_cast, *(pi1 + 3), *(alpha1 + 3*inca) ); \ PASTEMAC3(ch,ch,ch,scal2s)( *kappa_cast, *(pi1 + 4), *(alpha1 + 4*inca) ); \ PASTEMAC3(ch,ch,ch,scal2s)( *kappa_cast, *(pi1 + 5), *(alpha1 + 5*inca) ); \ PASTEMAC3(ch,ch,ch,scal2s)( *kappa_cast, *(pi1 + 6), *(alpha1 + 6*inca) ); \ PASTEMAC3(ch,ch,ch,scal2s)( *kappa_cast, *(pi1 + 7), *(alpha1 + 7*inca) ); \ PASTEMAC3(ch,ch,ch,scal2s)( *kappa_cast, *(pi1 + 8), *(alpha1 + 8*inca) ); \ PASTEMAC3(ch,ch,ch,scal2s)( *kappa_cast, *(pi1 + 9), *(alpha1 + 9*inca) ); \ PASTEMAC3(ch,ch,ch,scal2s)( *kappa_cast, *(pi1 + 10), *(alpha1 + 10*inca) ); \ PASTEMAC3(ch,ch,ch,scal2s)( *kappa_cast, *(pi1 + 11), *(alpha1 + 11*inca) ); \ PASTEMAC3(ch,ch,ch,scal2s)( *kappa_cast, *(pi1 + 12), *(alpha1 + 12*inca) ); \ PASTEMAC3(ch,ch,ch,scal2s)( *kappa_cast, *(pi1 + 13), *(alpha1 + 13*inca) ); \ \ pi1 += ldp; \ alpha1 += lda; \ } \ } \ } \ } INSERT_GENTFUNC_BASIC2( unpackm_14xk, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, arch, suf ) \ \ void PASTEMAC3(ch,opname,arch,suf) \ ( \ conj_t conjp, \ dim_t n, \ void* restrict kappa, \ void* restrict p, inc_t ldp, \ void* restrict a, inc_t inca, inc_t lda, \ cntx_t* restrict cntx \ ) \ { \ ctype* restrict kappa_cast = kappa; \ ctype* restrict pi1 = p; \ ctype* restrict alpha1 = a; \ \ if ( PASTEMAC(ch,eq1)( *kappa_cast ) ) \ { \ if ( bli_is_conj( conjp ) ) \ { \ for ( ; n != 0; --n ) \ { \ PASTEMAC2(ch,ch,copyjs)( *(pi1 + 0), *(alpha1 + 0*inca) ); \ PASTEMAC2(ch,ch,copyjs)( *(pi1 + 1), *(alpha1 + 1*inca) ); \ PASTEMAC2(ch,ch,copyjs)( *(pi1 + 2), *(alpha1 + 2*inca) ); \ PASTEMAC2(ch,ch,copyjs)( *(pi1 + 3), *(alpha1 + 3*inca) ); \ PASTEMAC2(ch,ch,copyjs)( *(pi1 + 4), *(alpha1 + 4*inca) ); \ PASTEMAC2(ch,ch,copyjs)( *(pi1 + 5), *(alpha1 + 5*inca) ); \ PASTEMAC2(ch,ch,copyjs)( *(pi1 + 6), *(alpha1 + 6*inca) ); \ PASTEMAC2(ch,ch,copyjs)( *(pi1 + 7), *(alpha1 + 7*inca) ); \ PASTEMAC2(ch,ch,copyjs)( *(pi1 + 8), *(alpha1 + 8*inca) ); \ PASTEMAC2(ch,ch,copyjs)( *(pi1 + 9), *(alpha1 + 9*inca) ); \ PASTEMAC2(ch,ch,copyjs)( *(pi1 + 10), *(alpha1 + 10*inca) ); \ PASTEMAC2(ch,ch,copyjs)( *(pi1 + 11), *(alpha1 + 11*inca) ); \ PASTEMAC2(ch,ch,copyjs)( *(pi1 + 12), *(alpha1 + 12*inca) ); \ PASTEMAC2(ch,ch,copyjs)( *(pi1 + 13), *(alpha1 + 13*inca) ); \ PASTEMAC2(ch,ch,copyjs)( *(pi1 + 14), *(alpha1 + 14*inca) ); \ PASTEMAC2(ch,ch,copyjs)( *(pi1 + 15), *(alpha1 + 15*inca) ); \ \ pi1 += ldp; \ alpha1 += lda; \ } \ } \ else \ { \ for ( ; n != 0; --n ) \ { \ PASTEMAC2(ch,ch,copys)( *(pi1 + 0), *(alpha1 + 0*inca) ); \ PASTEMAC2(ch,ch,copys)( *(pi1 + 1), *(alpha1 + 1*inca) ); \ PASTEMAC2(ch,ch,copys)( *(pi1 + 2), *(alpha1 + 2*inca) ); \ PASTEMAC2(ch,ch,copys)( *(pi1 + 3), *(alpha1 + 3*inca) ); \ PASTEMAC2(ch,ch,copys)( *(pi1 + 4), *(alpha1 + 4*inca) ); \ PASTEMAC2(ch,ch,copys)( *(pi1 + 5), *(alpha1 + 5*inca) ); \ PASTEMAC2(ch,ch,copys)( *(pi1 + 6), *(alpha1 + 6*inca) ); \ PASTEMAC2(ch,ch,copys)( *(pi1 + 7), *(alpha1 + 7*inca) ); \ PASTEMAC2(ch,ch,copys)( *(pi1 + 8), *(alpha1 + 8*inca) ); \ PASTEMAC2(ch,ch,copys)( *(pi1 + 9), *(alpha1 + 9*inca) ); \ PASTEMAC2(ch,ch,copys)( *(pi1 + 10), *(alpha1 + 10*inca) ); \ PASTEMAC2(ch,ch,copys)( *(pi1 + 11), *(alpha1 + 11*inca) ); \ PASTEMAC2(ch,ch,copys)( *(pi1 + 12), *(alpha1 + 12*inca) ); \ PASTEMAC2(ch,ch,copys)( *(pi1 + 13), *(alpha1 + 13*inca) ); \ PASTEMAC2(ch,ch,copys)( *(pi1 + 14), *(alpha1 + 14*inca) ); \ PASTEMAC2(ch,ch,copys)( *(pi1 + 15), *(alpha1 + 15*inca) ); \ \ pi1 += ldp; \ alpha1 += lda; \ } \ } \ } \ else \ { \ if ( bli_is_conj( conjp ) ) \ { \ for ( ; n != 0; --n ) \ { \ PASTEMAC3(ch,ch,ch,scal2js)( *kappa_cast, *(pi1 + 0), *(alpha1 + 0*inca) ); \ PASTEMAC3(ch,ch,ch,scal2js)( *kappa_cast, *(pi1 + 1), *(alpha1 + 1*inca) ); \ PASTEMAC3(ch,ch,ch,scal2js)( *kappa_cast, *(pi1 + 2), *(alpha1 + 2*inca) ); \ PASTEMAC3(ch,ch,ch,scal2js)( *kappa_cast, *(pi1 + 3), *(alpha1 + 3*inca) ); \ PASTEMAC3(ch,ch,ch,scal2js)( *kappa_cast, *(pi1 + 4), *(alpha1 + 4*inca) ); \ PASTEMAC3(ch,ch,ch,scal2js)( *kappa_cast, *(pi1 + 5), *(alpha1 + 5*inca) ); \ PASTEMAC3(ch,ch,ch,scal2js)( *kappa_cast, *(pi1 + 6), *(alpha1 + 6*inca) ); \ PASTEMAC3(ch,ch,ch,scal2js)( *kappa_cast, *(pi1 + 7), *(alpha1 + 7*inca) ); \ PASTEMAC3(ch,ch,ch,scal2js)( *kappa_cast, *(pi1 + 8), *(alpha1 + 8*inca) ); \ PASTEMAC3(ch,ch,ch,scal2js)( *kappa_cast, *(pi1 + 9), *(alpha1 + 9*inca) ); \ PASTEMAC3(ch,ch,ch,scal2js)( *kappa_cast, *(pi1 + 10), *(alpha1 + 10*inca) ); \ PASTEMAC3(ch,ch,ch,scal2js)( *kappa_cast, *(pi1 + 11), *(alpha1 + 11*inca) ); \ PASTEMAC3(ch,ch,ch,scal2js)( *kappa_cast, *(pi1 + 12), *(alpha1 + 12*inca) ); \ PASTEMAC3(ch,ch,ch,scal2js)( *kappa_cast, *(pi1 + 13), *(alpha1 + 13*inca) ); \ PASTEMAC3(ch,ch,ch,scal2js)( *kappa_cast, *(pi1 + 14), *(alpha1 + 14*inca) ); \ PASTEMAC3(ch,ch,ch,scal2js)( *kappa_cast, *(pi1 + 15), *(alpha1 + 15*inca) ); \ \ pi1 += ldp; \ alpha1 += lda; \ } \ } \ else \ { \ for ( ; n != 0; --n ) \ { \ PASTEMAC3(ch,ch,ch,scal2s)( *kappa_cast, *(pi1 + 0), *(alpha1 + 0*inca) ); \ PASTEMAC3(ch,ch,ch,scal2s)( *kappa_cast, *(pi1 + 1), *(alpha1 + 1*inca) ); \ PASTEMAC3(ch,ch,ch,scal2s)( *kappa_cast, *(pi1 + 2), *(alpha1 + 2*inca) ); \ PASTEMAC3(ch,ch,ch,scal2s)( *kappa_cast, *(pi1 + 3), *(alpha1 + 3*inca) ); \ PASTEMAC3(ch,ch,ch,scal2s)( *kappa_cast, *(pi1 + 4), *(alpha1 + 4*inca) ); \ PASTEMAC3(ch,ch,ch,scal2s)( *kappa_cast, *(pi1 + 5), *(alpha1 + 5*inca) ); \ PASTEMAC3(ch,ch,ch,scal2s)( *kappa_cast, *(pi1 + 6), *(alpha1 + 6*inca) ); \ PASTEMAC3(ch,ch,ch,scal2s)( *kappa_cast, *(pi1 + 7), *(alpha1 + 7*inca) ); \ PASTEMAC3(ch,ch,ch,scal2s)( *kappa_cast, *(pi1 + 8), *(alpha1 + 8*inca) ); \ PASTEMAC3(ch,ch,ch,scal2s)( *kappa_cast, *(pi1 + 9), *(alpha1 + 9*inca) ); \ PASTEMAC3(ch,ch,ch,scal2s)( *kappa_cast, *(pi1 + 10), *(alpha1 + 10*inca) ); \ PASTEMAC3(ch,ch,ch,scal2s)( *kappa_cast, *(pi1 + 11), *(alpha1 + 11*inca) ); \ PASTEMAC3(ch,ch,ch,scal2s)( *kappa_cast, *(pi1 + 12), *(alpha1 + 12*inca) ); \ PASTEMAC3(ch,ch,ch,scal2s)( *kappa_cast, *(pi1 + 13), *(alpha1 + 13*inca) ); \ PASTEMAC3(ch,ch,ch,scal2s)( *kappa_cast, *(pi1 + 14), *(alpha1 + 14*inca) ); \ PASTEMAC3(ch,ch,ch,scal2s)( *kappa_cast, *(pi1 + 15), *(alpha1 + 15*inca) ); \ \ pi1 += ldp; \ alpha1 += lda; \ } \ } \ } \ } INSERT_GENTFUNC_BASIC2( unpackm_16xk, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX ) blis-0.9.0/ref_kernels/3/000077500000000000000000000000001422157504600151205ustar00rootroot00000000000000blis-0.9.0/ref_kernels/3/bb/000077500000000000000000000000001422157504600155035ustar00rootroot00000000000000blis-0.9.0/ref_kernels/3/bb/bli_gemmbb_ref.c000066400000000000000000000106651422157504600205720ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // An implementation that indexes through B with the assumption that all // elements were broadcast (duplicated) by a factor of NP/NR. #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, arch, suf ) \ \ void PASTEMAC3(ch,opname,arch,suf) \ ( \ dim_t m, \ dim_t n, \ dim_t k, \ ctype* restrict alpha, \ ctype* restrict a, \ ctype* restrict b, \ ctype* restrict beta, \ ctype* restrict c, inc_t rs_c, inc_t cs_c, \ auxinfo_t* restrict data, \ cntx_t* restrict cntx \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ const dim_t mr = bli_cntx_get_blksz_def_dt( dt, BLIS_MR, cntx ); \ const dim_t nr = bli_cntx_get_blksz_def_dt( dt, BLIS_NR, cntx ); \ \ const inc_t packmr = bli_cntx_get_blksz_max_dt( dt, BLIS_MR, cntx ); \ const inc_t packnr = bli_cntx_get_blksz_max_dt( dt, BLIS_NR, cntx ); \ \ const inc_t cs_a = packmr; \ \ const inc_t rs_b = packnr; \ \ /* Assume that the degree of duplication is equal to packnr / nr. */ \ const inc_t cs_b = packnr / nr; \ \ ctype ab[ BLIS_STACK_BUF_MAX_SIZE \ / sizeof( ctype ) ] \ __attribute__((aligned(BLIS_STACK_BUF_ALIGN_SIZE))); \ const inc_t rs_ab = 1; \ const inc_t cs_ab = mr; \ \ dim_t l, j, i; \ \ ctype ai; \ ctype bj; \ \ \ /* Initialize the accumulator elements in ab to zero. */ \ for ( i = 0; i < m * n; ++i ) \ { \ PASTEMAC(ch,set0s)( *(ab + i) ); \ } \ \ /* Perform a series of k rank-1 updates into ab. */ \ for ( l = 0; l < k; ++l ) \ { \ ctype* restrict abij = ab; \ \ /* In an optimized implementation, these two loops over MR and NR are typically fully unrolled. */ \ for ( j = 0; j < n; ++j ) \ { \ bj = *(b + j*cs_b); \ \ for ( i = 0; i < m; ++i ) \ { \ ai = *(a + i); \ \ PASTEMAC(ch,dots)( ai, bj, *abij ); \ \ abij += rs_ab; \ } \ } \ \ a += cs_a; \ b += rs_b; \ } \ \ /* Scale the result in ab by alpha. */ \ for ( i = 0; i < m * n; ++i ) \ { \ PASTEMAC(ch,scals)( *alpha, *(ab + i) ); \ } \ \ /* If beta is zero, overwrite c with the scaled result in ab. Otherwise, scale by beta and then add the scaled redult in ab. */ \ if ( PASTEMAC(ch,eq0)( *beta ) ) \ { \ PASTEMAC(ch,copys_mxn)( m, \ n, \ ab, rs_ab, cs_ab, \ c, rs_c, cs_c ); \ } \ else \ { \ PASTEMAC(ch,xpbys_mxn)( m, \ n, \ ab, rs_ab, cs_ab, \ beta, \ c, rs_c, cs_c ); \ } \ } INSERT_GENTFUNC_BASIC2( gemmbb, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX ) blis-0.9.0/ref_kernels/3/bb/bli_gemmtrsmbb_ref.c000066400000000000000000000111751422157504600214750ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // An implementation that indexes through B with the assumption that all // elements were broadcast (duplicated) by a factor of NP/NR. #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, arch, suf, trsmkerid ) \ \ void PASTEMAC3(ch,opname,arch,suf) \ ( \ dim_t k, \ ctype* restrict alpha, \ ctype* restrict a1x, \ ctype* restrict a11, \ ctype* restrict bx1, \ ctype* restrict b11, \ ctype* restrict c11, inc_t rs_c, inc_t cs_c, \ auxinfo_t* restrict data, \ cntx_t* restrict cntx \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ const inc_t mr = bli_cntx_get_blksz_def_dt( dt, BLIS_MR, cntx ); \ const inc_t nr = bli_cntx_get_blksz_def_dt( dt, BLIS_NR, cntx ); \ \ const inc_t packnr = bli_cntx_get_blksz_max_dt( dt, BLIS_NR, cntx ); \ \ const inc_t rs_b = packnr; \ \ /* Assume that the degree of duplication is equal to packnr / nr. */ \ const inc_t cs_b = packnr / nr; \ /* printf( "bli_gemmtrsmbb_ref(): cs_b = %d\n", (int)cs_b ); \ printf( "bli_gemmtrsmbb_ref(): k nr = %d %d\n", (int)k, (int)nr ); \ */ \ \ ctype* minus_one = PASTEMAC(ch,m1); \ \ PASTECH(ch,gemm_ukr_ft) \ gemm_ukr = bli_cntx_get_l3_nat_ukr_dt( dt, BLIS_GEMM_UKR, cntx ); \ PASTECH(ch,trsm_ukr_ft) \ trsm_ukr = bli_cntx_get_l3_nat_ukr_dt( dt, trsmkerid, cntx ); \ \ /* PASTEMAC(d,fprintm)( stdout, "gemmtrsm_ukr: b01", k, nr, \ (double*)bx1, rs_b, cs_b, "%5.2f", "" ); \ PASTEMAC(d,fprintm)( stdout, "gemmtrsm_ukr: b11", mr, 2*nr, \ (double*)b11, rs_b, 1, "%5.2f", "" ); \ */ \ \ /* lower: b11 = alpha * b11 - a10 * b01; */ \ /* upper: b11 = alpha * b11 - a12 * b21; */ \ gemm_ukr \ ( \ mr, \ nr, \ k, \ minus_one, \ a1x, \ bx1, \ alpha, \ b11, rs_b, cs_b, \ data, \ cntx \ ); \ /* PASTEMAC(d,fprintm)( stdout, "gemmtrsm_ukr: b11 after gemm", mr, 2*nr, \ (double*)b11, rs_b, 1, "%5.2f", "" ); \ */ \ \ /* b11 = inv(a11) * b11; c11 = b11; */ \ trsm_ukr \ ( \ a11, \ b11, \ c11, rs_c, cs_c, \ data, \ cntx \ ); \ /* PASTEMAC(d,fprintm)( stdout, "gemmtrsm_ukr: b11 after trsm", mr, 2*nr, \ (double*)b11, rs_b, 1, "%5.2f", "" ); \ */ \ \ /* Broadcast the elements of the updated b11 submatrix to their duplicated neighbors. */ \ PASTEMAC(ch,bcastbbs_mxn) \ ( \ mr, \ nr, \ b11, rs_b, cs_b \ ); \ \ /* PASTEMAC(d,fprintm)( stdout, "gemmtrsm_ukr: b0111p_r after", k+3, 8, \ ( double* )b01, 2*PASTEMAC(ch,packnr), 2, "%4.1f", "" ); \ PASTEMAC(d,fprintm)( stdout, "gemmtrsm_ukr: b0111p_i after", k+3, 8, \ ( double* )b01 + 1, 2*PASTEMAC(ch,packnr), 2, "%4.1f", "" ); \ */ \ } INSERT_GENTFUNC_BASIC3( gemmtrsmbb_l, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX, BLIS_TRSM_L_UKR ) INSERT_GENTFUNC_BASIC3( gemmtrsmbb_u, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX, BLIS_TRSM_U_UKR ) blis-0.9.0/ref_kernels/3/bb/bli_trsmbb_ref.c000066400000000000000000000164251422157504600206320ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // An implementation that indexes through B with the assumption that all // elements were broadcast (duplicated) by a factor of NP/NR. #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, arch, suf, diagop ) \ \ void PASTEMAC3(ch,opname,arch,suf) \ ( \ ctype* restrict a, \ ctype* restrict b, \ ctype* restrict c, inc_t rs_c, inc_t cs_c, \ auxinfo_t* restrict data, \ cntx_t* restrict cntx \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ const dim_t mr = bli_cntx_get_blksz_def_dt( dt, BLIS_MR, cntx ); \ const dim_t nr = bli_cntx_get_blksz_def_dt( dt, BLIS_NR, cntx ); \ \ const inc_t packmr = bli_cntx_get_blksz_max_dt( dt, BLIS_MR, cntx ); \ const inc_t packnr = bli_cntx_get_blksz_max_dt( dt, BLIS_NR, cntx ); \ \ const dim_t m = mr; \ const dim_t n = nr; \ \ const inc_t rs_a = 1; \ const inc_t cs_a = packmr; \ \ const inc_t rs_b = packnr; \ \ /* Assume that the degree of duplication is equal to packnr / nr. */ \ const inc_t cs_b = packnr / nr; \ \ dim_t iter, i, j, l; \ dim_t n_behind; \ \ for ( iter = 0; iter < m; ++iter ) \ { \ i = iter; \ n_behind = i; \ \ ctype* restrict alpha11 = a + (i )*rs_a + (i )*cs_a; \ ctype* restrict a10t = a + (i )*rs_a + (0 )*cs_a; \ ctype* restrict B0 = b + (0 )*rs_b + (0 )*cs_b; \ ctype* restrict b1 = b + (i )*rs_b + (0 )*cs_b; \ \ /* b1 = b1 - a10t * B0; */ \ /* b1 = b1 / alpha11; */ \ for ( j = 0; j < n; ++j ) \ { \ ctype* restrict b01 = B0 + (0 )*rs_b + (j )*cs_b; \ ctype* restrict beta11 = b1 + (0 )*rs_b + (j )*cs_b; \ ctype* restrict gamma11 = c + (i )*rs_c + (j )*cs_c; \ ctype beta11c = *beta11; \ ctype rho11; \ \ /* beta11 = beta11 - a10t * b01; */ \ PASTEMAC(ch,set0s)( rho11 ); \ for ( l = 0; l < n_behind; ++l ) \ { \ ctype* restrict alpha10 = a10t + (l )*cs_a; \ ctype* restrict beta01 = b01 + (l )*rs_b; \ \ PASTEMAC(ch,axpys)( *alpha10, *beta01, rho11 ); \ } \ PASTEMAC(ch,subs)( rho11, beta11c ); \ \ /* beta11 = beta11 / alpha11; */ \ /* NOTE: When preinversion is enabled, the INVERSE of alpha11 (1.0/alpha11) is stored during packing instead alpha11 so we can multiply rather than divide. When preinversion is disabled, alpha11 is stored and division happens below explicitly. */ \ PASTEMAC(ch,scals)( *alpha11, beta11c ); \ \ /* Output final result to matrix c. */ \ PASTEMAC(ch,copys)( beta11c, *gamma11 ); \ \ /* Store the local value back to b11. */ \ PASTEMAC(ch,copys)( beta11c, *beta11 ); \ } \ } \ } #ifdef BLIS_ENABLE_TRSM_PREINVERSION INSERT_GENTFUNC_BASIC3( trsmbb_l, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX, scals ) #else INSERT_GENTFUNC_BASIC3( trsmbb_l, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX, invscals ) #endif #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, arch, suf, diagop ) \ \ void PASTEMAC3(ch,opname,arch,suf) \ ( \ ctype* restrict a, \ ctype* restrict b, \ ctype* restrict c, inc_t rs_c, inc_t cs_c, \ auxinfo_t* restrict data, \ cntx_t* restrict cntx \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ const dim_t mr = bli_cntx_get_blksz_def_dt( dt, BLIS_MR, cntx ); \ const dim_t nr = bli_cntx_get_blksz_def_dt( dt, BLIS_NR, cntx ); \ \ const inc_t packmr = bli_cntx_get_blksz_max_dt( dt, BLIS_MR, cntx ); \ const inc_t packnr = bli_cntx_get_blksz_max_dt( dt, BLIS_NR, cntx ); \ \ const dim_t m = mr; \ const dim_t n = nr; \ \ const inc_t rs_a = 1; \ const inc_t cs_a = packmr; \ \ const inc_t rs_b = packnr; \ \ /* Assume that the degree of duplication is equal to packnr / nr. */ \ const inc_t cs_b = packnr / nr; \ \ dim_t iter, i, j, l; \ dim_t n_behind; \ \ for ( iter = 0; iter < m; ++iter ) \ { \ i = m - iter - 1; \ n_behind = iter; \ \ ctype* restrict alpha11 = a + (i )*rs_a + (i )*cs_a; \ ctype* restrict a12t = a + (i )*rs_a + (i+1)*cs_a; \ ctype* restrict b1 = b + (i )*rs_b + (0 )*cs_b; \ ctype* restrict B2 = b + (i+1)*rs_b + (0 )*cs_b; \ \ /* b1 = b1 - a12t * B2; */ \ /* b1 = b1 / alpha11; */ \ for ( j = 0; j < n; ++j ) \ { \ ctype* restrict beta11 = b1 + (0 )*rs_b + (j )*cs_b; \ ctype* restrict b21 = B2 + (0 )*rs_b + (j )*cs_b; \ ctype* restrict gamma11 = c + (i )*rs_c + (j )*cs_c; \ ctype beta11c = *beta11; \ ctype rho11; \ \ /* beta11 = beta11 - a12t * b21; */ \ PASTEMAC(ch,set0s)( rho11 ); \ for ( l = 0; l < n_behind; ++l ) \ { \ ctype* restrict alpha12 = a12t + (l )*cs_a; \ ctype* restrict beta21 = b21 + (l )*rs_b; \ \ PASTEMAC(ch,axpys)( *alpha12, *beta21, rho11 ); \ } \ PASTEMAC(ch,subs)( rho11, beta11c ); \ \ /* beta11 = beta11 / alpha11; */ \ /* NOTE: When preinversion is enabled, the INVERSE of alpha11 (1.0/alpha11) is stored during packing instead alpha11 so we can multiply rather than divide. When preinversion is disabled, alpha11 is stored and division happens below explicitly. */ \ PASTEMAC(ch,diagop)( *alpha11, beta11c ); \ \ /* Output final result to matrix c. */ \ PASTEMAC(ch,copys)( beta11c, *gamma11 ); \ \ /* Store the local value back to b11. */ \ PASTEMAC(ch,copys)( beta11c, *beta11 ); \ } \ } \ } #ifdef BLIS_ENABLE_TRSM_PREINVERSION INSERT_GENTFUNC_BASIC3( trsmbb_u, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX, scals ) #else INSERT_GENTFUNC_BASIC3( trsmbb_u, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX, invscals ) #endif blis-0.9.0/ref_kernels/3/bli_gemm_ref.c000066400000000000000000000165051422157504600177020ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #if 1 // An implementation that attempts to facilitate emission of vectorized // instructions via constant loop bounds + #pragma omp simd directives. #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, arch, suf, mr, nr ) \ \ void PASTEMAC3(ch,opname,arch,suf) \ ( \ dim_t m, \ dim_t n, \ dim_t k, \ ctype* restrict alpha, \ ctype* restrict a, \ ctype* restrict b, \ ctype* restrict beta, \ ctype* restrict c, inc_t rs_c, inc_t cs_c, \ auxinfo_t* restrict data, \ cntx_t* restrict cntx \ ) \ { \ ctype ab[ BLIS_STACK_BUF_MAX_SIZE \ / sizeof( ctype ) ] \ __attribute__((aligned(BLIS_STACK_BUF_ALIGN_SIZE))); \ const inc_t rs_ab = nr; \ const inc_t cs_ab = 1; \ \ const inc_t cs_a = mr; \ const inc_t rs_b = nr; \ \ \ /* Initialize the accumulator elements in ab to zero. */ \ PRAGMA_SIMD \ for ( dim_t i = 0; i < mr * nr; ++i ) \ { \ PASTEMAC(ch,set0s)( ab[ i ] ); \ } \ \ /* Perform a series of k rank-1 updates into ab. */ \ for ( dim_t l = 0; l < k; ++l ) \ { \ for ( dim_t i = 0; i < mr; ++i ) \ { \ PRAGMA_SIMD \ for ( dim_t j = 0; j < nr; ++j ) \ { \ PASTEMAC(ch,dots) \ ( \ a[ i ], \ b[ j ], \ ab[ i*rs_ab + j*cs_ab ] \ ); \ } \ } \ \ a += cs_a; \ b += rs_b; \ } \ \ /* Scale the result in ab by alpha. */ \ PRAGMA_SIMD \ for ( dim_t i = 0; i < mr * nr; ++i ) \ { \ PASTEMAC(ch,scals)( *alpha, ab[ i ] ); \ } \ \ /* Output/accumulate intermediate result ab based on the storage of c and the value of beta. */ \ if ( cs_c == 1 ) \ { \ /* C is row-stored. */ \ \ if ( PASTEMAC(ch,eq0)( *beta ) ) \ { \ for ( dim_t i = 0; i < m; ++i ) \ for ( dim_t j = 0; j < n; ++j ) \ PASTEMAC(ch,copys) \ ( \ ab[ i*rs_ab + j*cs_ab ], \ c [ i*rs_c + j*1 ] \ ); \ } \ else \ { \ for ( dim_t i = 0; i < m; ++i ) \ for ( dim_t j = 0; j < n; ++j ) \ PASTEMAC(ch,xpbys) \ ( \ ab[ i*rs_ab + j*cs_ab ], \ *beta, \ c [ i*rs_c + j*1 ] \ ); \ } \ } \ else \ { \ /* C is column-stored or general-stored. */ \ \ if ( PASTEMAC(ch,eq0)( *beta ) ) \ { \ for ( dim_t j = 0; j < n; ++j ) \ for ( dim_t i = 0; i < m; ++i ) \ PASTEMAC(ch,copys) \ ( \ ab[ i*rs_ab + j*cs_ab ], \ c [ i*rs_c + j*cs_c ] \ ); \ } \ else \ { \ for ( dim_t j = 0; j < n; ++j ) \ for ( dim_t i = 0; i < m; ++i ) \ PASTEMAC(ch,xpbys) \ ( \ ab[ i*rs_ab + j*cs_ab ], \ *beta, \ c [ i*rs_c + j*cs_c ] \ ); \ } \ } \ } //INSERT_GENTFUNC_BASIC2( gemm, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX ) GENTFUNC( float, s, gemm, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX, 4, 16 ) GENTFUNC( double, d, gemm, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX, 4, 8 ) GENTFUNC( scomplex, c, gemm, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX, 4, 8 ) GENTFUNC( dcomplex, z, gemm, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX, 4, 4 ) #else // An implementation that uses variable loop bounds (queried from the context) // and makes no use of #pragma omp simd. #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, arch, suf ) \ \ void PASTEMAC3(ch,opname,arch,suf) \ ( \ dim_t m, \ dim_t n, \ dim_t k, \ ctype* restrict alpha, \ ctype* restrict a, \ ctype* restrict b, \ ctype* restrict beta, \ ctype* restrict c, inc_t rs_c, inc_t cs_c, \ auxinfo_t* restrict data, \ cntx_t* restrict cntx \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ const dim_t mr = bli_cntx_get_blksz_def_dt( dt, BLIS_MR, cntx ); \ const dim_t nr = bli_cntx_get_blksz_def_dt( dt, BLIS_NR, cntx ); \ \ const inc_t packmr = bli_cntx_get_blksz_max_dt( dt, BLIS_MR, cntx ); \ const inc_t packnr = bli_cntx_get_blksz_max_dt( dt, BLIS_NR, cntx ); \ \ const inc_t cs_a = packmr; \ \ const inc_t rs_b = packnr; \ \ ctype ab[ BLIS_STACK_BUF_MAX_SIZE \ / sizeof( ctype ) ] \ __attribute__((aligned(BLIS_STACK_BUF_ALIGN_SIZE))); \ const inc_t rs_ab = 1; \ const inc_t cs_ab = mr; \ \ dim_t l, j, i; \ \ ctype ai; \ ctype bj; \ \ \ /* Initialize the accumulator elements in ab to zero. */ \ for ( i = 0; i < m * n; ++i ) \ { \ PASTEMAC(ch,set0s)( *(ab + i) ); \ } \ \ /* Perform a series of k rank-1 updates into ab. */ \ for ( l = 0; l < k; ++l ) \ { \ ctype* restrict abij = ab; \ \ /* In an optimized implementation, these two loops over MR and NR are typically fully unrolled. */ \ for ( j = 0; j < n; ++j ) \ { \ bj = *(b + j); \ \ for ( i = 0; i < m; ++i ) \ { \ ai = *(a + i); \ \ PASTEMAC(ch,dots)( ai, bj, *abij ); \ \ abij += rs_ab; \ } \ } \ \ a += cs_a; \ b += rs_b; \ } \ \ /* Scale the result in ab by alpha. */ \ for ( i = 0; i < m * n; ++i ) \ { \ PASTEMAC(ch,scals)( *alpha, *(ab + i) ); \ } \ \ /* If beta is zero, overwrite c with the scaled result in ab. Otherwise, scale by beta and then add the scaled redult in ab. */ \ if ( PASTEMAC(ch,eq0)( *beta ) ) \ { \ PASTEMAC(ch,copys_mxn)( m, \ n, \ ab, rs_ab, cs_ab, \ c, rs_c, cs_c ); \ } \ else \ { \ PASTEMAC(ch,xpbys_mxn)( m, \ n, \ ab, rs_ab, cs_ab, \ beta, \ c, rs_c, cs_c ); \ } \ } INSERT_GENTFUNC_BASIC2( gemm, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX ) #endif blis-0.9.0/ref_kernels/3/bli_gemmsup_ref.c000066400000000000000000000544231422157504600204330ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // -- Row storage case --------------------------------------------------------- // #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, arch, suf ) \ \ void PASTEMAC3(ch,opname,arch,suf) \ ( \ conj_t conja, \ conj_t conjb, \ dim_t m, \ dim_t n, \ dim_t k, \ ctype* restrict alpha, \ ctype* restrict a, inc_t rs_a, inc_t cs_a, \ ctype* restrict b, inc_t rs_b, inc_t cs_b, \ ctype* restrict beta, \ ctype* restrict c, inc_t rs_c, inc_t cs_c, \ auxinfo_t* restrict data, \ cntx_t* restrict cntx \ ) \ { \ /* NOTE: This microkernel can actually handle arbitrarily large values of m, n, and k. */ \ \ if ( bli_is_noconj( conja ) && bli_is_noconj( conjb ) ) \ { \ /* Traverse c by rows. */ \ for ( dim_t i = 0; i < m; ++i ) \ { \ ctype* restrict ci = &c[ i*rs_c ]; \ ctype* restrict ai = &a[ i*rs_a ]; \ \ for ( dim_t j = 0; j < n; ++j ) \ { \ ctype* restrict cij = &ci[ j*cs_c ]; \ ctype* restrict bj = &b [ j*cs_b ]; \ ctype ab; \ \ PASTEMAC(ch,set0s)( ab ); \ \ /* Perform a dot product to update the (i,j) element of c. */ \ for ( dim_t l = 0; l < k; ++l ) \ { \ ctype* restrict aij = &ai[ l*cs_a ]; \ ctype* restrict bij = &bj[ l*rs_b ]; \ \ PASTEMAC(ch,dots)( *aij, *bij, ab ); \ } \ \ /* If beta is one, add ab into c. If beta is zero, overwrite c with the result in ab. Otherwise, scale by beta and accumulate ab to c. */ \ if ( PASTEMAC(ch,eq1)( *beta ) ) \ { \ PASTEMAC(ch,axpys)( *alpha, ab, *cij ); \ } \ else if ( PASTEMAC(ch,eq0)( *beta ) ) \ { \ PASTEMAC(ch,scal2s)( *alpha, ab, *cij ); \ } \ else \ { \ PASTEMAC(ch,axpbys)( *alpha, ab, *beta, *cij ); \ } \ } \ } \ } \ else if ( bli_is_noconj( conja ) && bli_is_conj( conjb ) ) \ { \ /* Traverse c by rows. */ \ for ( dim_t i = 0; i < m; ++i ) \ { \ ctype* restrict ci = &c[ i*rs_c ]; \ ctype* restrict ai = &a[ i*rs_a ]; \ \ for ( dim_t j = 0; j < n; ++j ) \ { \ ctype* restrict cij = &ci[ j*cs_c ]; \ ctype* restrict bj = &b [ j*cs_b ]; \ ctype ab; \ \ PASTEMAC(ch,set0s)( ab ); \ \ /* Perform a dot product to update the (i,j) element of c. */ \ for ( dim_t l = 0; l < k; ++l ) \ { \ ctype* restrict aij = &ai[ l*cs_a ]; \ ctype* restrict bij = &bj[ l*rs_b ]; \ \ PASTEMAC(ch,axpyjs)( *aij, *bij, ab ); \ } \ \ /* If beta is one, add ab into c. If beta is zero, overwrite c with the result in ab. Otherwise, scale by beta and accumulate ab to c. */ \ if ( PASTEMAC(ch,eq1)( *beta ) ) \ { \ PASTEMAC(ch,axpys)( *alpha, ab, *cij ); \ } \ else if ( PASTEMAC(ch,eq0)( *beta ) ) \ { \ PASTEMAC(ch,scal2s)( *alpha, ab, *cij ); \ } \ else \ { \ PASTEMAC(ch,axpbys)( *alpha, ab, *beta, *cij ); \ } \ } \ } \ } \ else if ( bli_is_conj( conja ) && bli_is_noconj( conjb ) ) \ { \ /* Traverse c by rows. */ \ for ( dim_t i = 0; i < m; ++i ) \ { \ ctype* restrict ci = &c[ i*rs_c ]; \ ctype* restrict ai = &a[ i*rs_a ]; \ \ for ( dim_t j = 0; j < n; ++j ) \ { \ ctype* restrict cij = &ci[ j*cs_c ]; \ ctype* restrict bj = &b [ j*cs_b ]; \ ctype ab; \ \ PASTEMAC(ch,set0s)( ab ); \ \ /* Perform a dot product to update the (i,j) element of c. */ \ for ( dim_t l = 0; l < k; ++l ) \ { \ ctype* restrict aij = &ai[ l*cs_a ]; \ ctype* restrict bij = &bj[ l*rs_b ]; \ \ PASTEMAC(ch,dotjs)( *aij, *bij, ab ); \ } \ \ /* If beta is one, add ab into c. If beta is zero, overwrite c with the result in ab. Otherwise, scale by beta and accumulate ab to c. */ \ if ( PASTEMAC(ch,eq1)( *beta ) ) \ { \ PASTEMAC(ch,axpys)( *alpha, ab, *cij ); \ } \ else if ( PASTEMAC(ch,eq0)( *beta ) ) \ { \ PASTEMAC(ch,scal2s)( *alpha, ab, *cij ); \ } \ else \ { \ PASTEMAC(ch,axpbys)( *alpha, ab, *beta, *cij ); \ } \ } \ } \ } \ else /* if ( bli_is_conj( conja ) && bli_is_conj( conjb ) ) */ \ { \ /* Traverse c by rows. */ \ for ( dim_t i = 0; i < m; ++i ) \ { \ ctype* restrict ci = &c[ i*rs_c ]; \ ctype* restrict ai = &a[ i*rs_a ]; \ \ for ( dim_t j = 0; j < n; ++j ) \ { \ ctype* restrict cij = &ci[ j*cs_c ]; \ ctype* restrict bj = &b [ j*cs_b ]; \ ctype ab; \ \ PASTEMAC(ch,set0s)( ab ); \ \ /* Perform a dot product to update the (i,j) element of c. */ \ for ( dim_t l = 0; l < k; ++l ) \ { \ ctype* restrict aij = &ai[ l*cs_a ]; \ ctype* restrict bij = &bj[ l*rs_b ]; \ \ PASTEMAC(ch,dots)( *aij, *bij, ab ); \ } \ \ /* Conjugate the result to simulate conj(a^T) * conj(b). */ \ PASTEMAC(ch,conjs)( ab ); \ \ /* If beta is one, add ab into c. If beta is zero, overwrite c with the result in ab. Otherwise, scale by beta and accumulate ab to c. */ \ if ( PASTEMAC(ch,eq1)( *beta ) ) \ { \ PASTEMAC(ch,axpys)( *alpha, ab, *cij ); \ } \ else if ( PASTEMAC(ch,eq0)( *beta ) ) \ { \ PASTEMAC(ch,scal2s)( *alpha, ab, *cij ); \ } \ else \ { \ PASTEMAC(ch,axpbys)( *alpha, ab, *beta, *cij ); \ } \ } \ } \ } \ } INSERT_GENTFUNC_BASIC2( gemmsup_r, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX ) // // -- Column storage case ------------------------------------------------------ // #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, arch, suf ) \ \ void PASTEMAC3(ch,opname,arch,suf) \ ( \ conj_t conja, \ conj_t conjb, \ dim_t m, \ dim_t n, \ dim_t k, \ ctype* restrict alpha, \ ctype* restrict a, inc_t rs_a, inc_t cs_a, \ ctype* restrict b, inc_t rs_b, inc_t cs_b, \ ctype* restrict beta, \ ctype* restrict c, inc_t rs_c, inc_t cs_c, \ auxinfo_t* restrict data, \ cntx_t* restrict cntx \ ) \ { \ /* NOTE: This microkernel can actually handle arbitrarily large values of m, n, and k. */ \ \ if ( bli_is_noconj( conja ) && bli_is_noconj( conjb ) ) \ { \ /* Traverse c by columns. */ \ for ( dim_t j = 0; j < n; ++j ) \ { \ ctype* restrict cj = &c[ j*cs_c ]; \ ctype* restrict bj = &b[ j*cs_b ]; \ \ for ( dim_t i = 0; i < m; ++i ) \ { \ ctype* restrict cij = &cj[ i*rs_c ]; \ ctype* restrict ai = &a [ i*rs_a ]; \ ctype ab; \ \ PASTEMAC(ch,set0s)( ab ); \ \ /* Perform a dot product to update the (i,j) element of c. */ \ for ( dim_t l = 0; l < k; ++l ) \ { \ ctype* restrict aij = &ai[ l*cs_a ]; \ ctype* restrict bij = &bj[ l*rs_b ]; \ \ PASTEMAC(ch,dots)( *aij, *bij, ab ); \ } \ \ /* If beta is one, add ab into c. If beta is zero, overwrite c with the result in ab. Otherwise, scale by beta and accumulate ab to c. */ \ if ( PASTEMAC(ch,eq1)( *beta ) ) \ { \ PASTEMAC(ch,axpys)( *alpha, ab, *cij ); \ } \ else if ( PASTEMAC(ch,eq0)( *beta ) ) \ { \ PASTEMAC(ch,scal2s)( *alpha, ab, *cij ); \ } \ else \ { \ PASTEMAC(ch,axpbys)( *alpha, ab, *beta, *cij ); \ } \ } \ } \ } \ else if ( bli_is_noconj( conja ) && bli_is_conj( conjb ) ) \ { \ /* Traverse c by columns. */ \ for ( dim_t j = 0; j < n; ++j ) \ { \ ctype* restrict cj = &c[ j*cs_c ]; \ ctype* restrict bj = &b[ j*cs_b ]; \ \ for ( dim_t i = 0; i < m; ++i ) \ { \ ctype* restrict cij = &cj[ i*rs_c ]; \ ctype* restrict ai = &a [ i*rs_a ]; \ ctype ab; \ \ PASTEMAC(ch,set0s)( ab ); \ \ /* Perform a dot product to update the (i,j) element of c. */ \ for ( dim_t l = 0; l < k; ++l ) \ { \ ctype* restrict aij = &ai[ l*cs_a ]; \ ctype* restrict bij = &bj[ l*rs_b ]; \ \ PASTEMAC(ch,axpyjs)( *aij, *bij, ab ); \ } \ \ /* If beta is one, add ab into c. If beta is zero, overwrite c with the result in ab. Otherwise, scale by beta and accumulate ab to c. */ \ if ( PASTEMAC(ch,eq1)( *beta ) ) \ { \ PASTEMAC(ch,axpys)( *alpha, ab, *cij ); \ } \ else if ( PASTEMAC(ch,eq0)( *beta ) ) \ { \ PASTEMAC(ch,scal2s)( *alpha, ab, *cij ); \ } \ else \ { \ PASTEMAC(ch,axpbys)( *alpha, ab, *beta, *cij ); \ } \ } \ } \ } \ else if ( bli_is_conj( conja ) && bli_is_noconj( conjb ) ) \ { \ /* Traverse c by columns. */ \ for ( dim_t j = 0; j < n; ++j ) \ { \ ctype* restrict cj = &c[ j*cs_c ]; \ ctype* restrict bj = &b[ j*cs_b ]; \ \ for ( dim_t i = 0; i < m; ++i ) \ { \ ctype* restrict cij = &cj[ i*rs_c ]; \ ctype* restrict ai = &a [ i*rs_a ]; \ ctype ab; \ \ PASTEMAC(ch,set0s)( ab ); \ \ /* Perform a dot product to update the (i,j) element of c. */ \ for ( dim_t l = 0; l < k; ++l ) \ { \ ctype* restrict aij = &ai[ l*cs_a ]; \ ctype* restrict bij = &bj[ l*rs_b ]; \ \ PASTEMAC(ch,dotjs)( *aij, *bij, ab ); \ } \ \ /* If beta is one, add ab into c. If beta is zero, overwrite c with the result in ab. Otherwise, scale by beta and accumulate ab to c. */ \ if ( PASTEMAC(ch,eq1)( *beta ) ) \ { \ PASTEMAC(ch,axpys)( *alpha, ab, *cij ); \ } \ else if ( PASTEMAC(ch,eq0)( *beta ) ) \ { \ PASTEMAC(ch,scal2s)( *alpha, ab, *cij ); \ } \ else \ { \ PASTEMAC(ch,axpbys)( *alpha, ab, *beta, *cij ); \ } \ } \ } \ } \ else /* if ( bli_is_conj( conja ) && bli_is_conj( conjb ) ) */ \ { \ /* Traverse c by columns. */ \ for ( dim_t j = 0; j < n; ++j ) \ { \ ctype* restrict cj = &c[ j*cs_c ]; \ ctype* restrict bj = &b[ j*cs_b ]; \ \ for ( dim_t i = 0; i < m; ++i ) \ { \ ctype* restrict cij = &cj[ i*rs_c ]; \ ctype* restrict ai = &a [ i*rs_a ]; \ ctype ab; \ \ PASTEMAC(ch,set0s)( ab ); \ \ /* Perform a dot product to update the (i,j) element of c. */ \ for ( dim_t l = 0; l < k; ++l ) \ { \ ctype* restrict aij = &ai[ l*cs_a ]; \ ctype* restrict bij = &bj[ l*rs_b ]; \ \ PASTEMAC(ch,dots)( *aij, *bij, ab ); \ } \ \ /* Conjugate the result to simulate conj(a^T) * conj(b). */ \ PASTEMAC(ch,conjs)( ab ); \ \ /* If beta is one, add ab into c. If beta is zero, overwrite c with the result in ab. Otherwise, scale by beta and accumulate ab to c. */ \ if ( PASTEMAC(ch,eq1)( *beta ) ) \ { \ PASTEMAC(ch,axpys)( *alpha, ab, *cij ); \ } \ else if ( PASTEMAC(ch,eq0)( *beta ) ) \ { \ PASTEMAC(ch,scal2s)( *alpha, ab, *cij ); \ } \ else \ { \ PASTEMAC(ch,axpbys)( *alpha, ab, *beta, *cij ); \ } \ } \ } \ } \ } INSERT_GENTFUNC_BASIC2( gemmsup_c, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX ) // // -- General storage case ----------------------------------------------------- // INSERT_GENTFUNC_BASIC2( gemmsup_g, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX ) #if 0 // // -- Row storage case --------------------------------------------------------- // #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, arch, suf ) \ \ void PASTEMAC3(ch,opname,arch,suf) \ ( \ conj_t conja, \ conj_t conjb, \ dim_t m, \ dim_t n, \ dim_t k, \ ctype* restrict alpha, \ ctype* restrict a, inc_t rs_a, inc_t cs_a, \ ctype* restrict b, inc_t rs_b, inc_t cs_b, \ ctype* restrict beta, \ ctype* restrict c, inc_t rs_c, inc_t cs_c, \ auxinfo_t* restrict data, \ cntx_t* restrict cntx \ ) \ { \ const dim_t mn = m * n; \ \ ctype ab[ BLIS_STACK_BUF_MAX_SIZE \ / sizeof( ctype ) ] \ __attribute__((aligned(BLIS_STACK_BUF_ALIGN_SIZE))); \ const inc_t rs_ab = n; \ const inc_t cs_ab = 1; \ \ \ /* Assumptions: m <= mr, n <= nr so that the temporary array ab is sufficiently large enough to hold the m x n microtile. The ability to handle m < mr and n < nr is being provided so that optimized ukernels can call one of these reference implementations for their edge cases, if they choose. When they do so, they will need to call the function directly, by its configuration-mangled name, since it will have been overwritten in the context when the optimized ukernel functions are registered. */ \ \ \ /* Initialize the accumulator elements in ab to zero. */ \ for ( dim_t i = 0; i < mn; ++i ) \ { \ PASTEMAC(ch,set0s)( ab[i] ); \ } \ \ /* Perform a series of k rank-1 updates into ab. */ \ for ( dim_t l = 0; l < k; ++l ) \ { \ /* Traverse ab by rows; assume cs_ab = 1. */ \ for ( dim_t i = 0; i < m; ++i ) \ { \ for ( dim_t j = 0; j < n; ++j ) \ { \ PASTEMAC(ch,dots) \ ( \ a[ i*rs_a ], \ b[ j*cs_b ], \ ab[ i*rs_ab + j*cs_ab ] \ ); \ } \ } \ \ a += cs_a; \ b += rs_b; \ } \ \ /* Scale the result in ab by alpha. */ \ for ( dim_t i = 0; i < mn; ++i ) \ { \ PASTEMAC(ch,scals)( *alpha, ab[i] ); \ } \ \ \ /* If beta is one, add ab into c. If beta is zero, overwrite c with the result in ab. Otherwise, scale by beta and accumulate ab to c. */ \ if ( PASTEMAC(ch,eq1)( *beta ) ) \ { \ /* Traverse ab and c by rows; assume cs_a = cs_a = 1. */ \ for ( dim_t i = 0; i < m; ++i ) \ for ( dim_t j = 0; j < n; ++j ) \ { \ PASTEMAC(ch,adds) \ ( \ ab[ i*rs_ab + j*1 ], \ c[ i*rs_c + j*1 ] \ ) \ } \ } \ else if ( PASTEMAC(ch,eq0)( *beta ) ) \ { \ \ /* Traverse ab and c by rows; assume cs_a = cs_a = 1. */ \ for ( dim_t i = 0; i < m; ++i ) \ for ( dim_t j = 0; j < n; ++j ) \ { \ PASTEMAC(ch,copys) \ ( \ ab[ i*rs_ab + j*1 ], \ c[ i*rs_c + j*1 ] \ ) \ } \ } \ else /* beta != 0 && beta != 1 */ \ { \ /* Traverse ab and c by rows; assume cs_a = cs_a = 1. */ \ for ( dim_t i = 0; i < m; ++i ) \ for ( dim_t j = 0; j < n; ++j ) \ { \ PASTEMAC(ch,xpbys) \ ( \ ab[ i*rs_ab + j*1 ], \ *beta, \ c[ i*rs_c + j*1 ] \ ) \ } \ } \ } INSERT_GENTFUNC_BASIC2( gemmsup_r, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX ) // // -- Column storage case ------------------------------------------------------ // #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, arch, suf ) \ \ void PASTEMAC3(ch,opname,arch,suf) \ ( \ conj_t conja, \ conj_t conjb, \ dim_t m, \ dim_t n, \ dim_t k, \ ctype* restrict alpha, \ ctype* restrict a, inc_t rs_a, inc_t cs_a, \ ctype* restrict b, inc_t rs_b, inc_t cs_b, \ ctype* restrict beta, \ ctype* restrict c, inc_t rs_c, inc_t cs_c, \ auxinfo_t* restrict data, \ cntx_t* restrict cntx \ ) \ { \ const dim_t mn = m * n; \ \ ctype ab[ BLIS_STACK_BUF_MAX_SIZE \ / sizeof( ctype ) ] \ __attribute__((aligned(BLIS_STACK_BUF_ALIGN_SIZE))); \ const inc_t rs_ab = 1; \ const inc_t cs_ab = m; \ \ \ /* Assumptions: m <= mr, n <= nr so that the temporary array ab is sufficiently large enough to hold the m x n microtile. The ability to handle m < mr and n < nr is being provided so that optimized ukernels can call one of these reference implementations for their edge cases, if they choose. When they do so, they will need to call the function directly, by its configuration-mangled name, since it will have been overwritten in the context when the optimized ukernel functions are registered. */ \ \ \ /* Initialize the accumulator elements in ab to zero. */ \ for ( dim_t i = 0; i < mn; ++i ) \ { \ PASTEMAC(ch,set0s)( ab[i] ); \ } \ \ /* Perform a series of k rank-1 updates into ab. */ \ for ( dim_t l = 0; l < k; ++l ) \ { \ /* Traverse ab by columns; assume rs_ab = 1. */ \ for ( dim_t j = 0; j < n; ++j ) \ { \ for ( dim_t i = 0; i < m; ++i ) \ { \ PASTEMAC(ch,dots) \ ( \ a[ i*rs_a ], \ b[ j*cs_b ], \ ab[ i*rs_ab + j*cs_ab ] \ ); \ } \ } \ \ a += cs_a; \ b += rs_b; \ } \ \ /* Scale the result in ab by alpha. */ \ for ( dim_t i = 0; i < mn; ++i ) \ { \ PASTEMAC(ch,scals)( *alpha, ab[i] ); \ } \ \ \ /* If beta is one, add ab into c. If beta is zero, overwrite c with the result in ab. Otherwise, scale by beta and accumulate ab to c. */ \ if ( PASTEMAC(ch,eq1)( *beta ) ) \ { \ /* Traverse ab and c by columns; assume rs_a = rs_a = 1. */ \ for ( dim_t j = 0; j < n; ++j ) \ for ( dim_t i = 0; i < m; ++i ) \ { \ PASTEMAC(ch,adds) \ ( \ ab[ i*1 + j*cs_ab ], \ c[ i*1 + j*cs_c ] \ ) \ } \ } \ else if ( PASTEMAC(ch,eq0)( *beta ) ) \ { \ /* Traverse ab and c by columns; assume rs_a = rs_a = 1. */ \ for ( dim_t j = 0; j < n; ++j ) \ for ( dim_t i = 0; i < m; ++i ) \ { \ PASTEMAC(ch,copys) \ ( \ ab[ i*1 + j*cs_ab ], \ c[ i*1 + j*cs_c ] \ ) \ } \ } \ else /* beta != 0 && beta != 1 */ \ { \ /* Traverse ab and c by columns; assume rs_a = rs_a = 1. */ \ for ( dim_t j = 0; j < n; ++j ) \ for ( dim_t i = 0; i < m; ++i ) \ { \ PASTEMAC(ch,xpbys) \ ( \ ab[ i*1 + j*cs_ab ], \ *beta, \ c[ i*1 + j*cs_c ] \ ) \ } \ } \ } INSERT_GENTFUNC_BASIC2( gemmsup_c, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX ) // // -- General storage case ----------------------------------------------------- // #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, arch, suf ) \ \ void PASTEMAC3(ch,opname,arch,suf) \ ( \ conj_t conja, \ conj_t conjb, \ dim_t m, \ dim_t n, \ dim_t k, \ ctype* restrict alpha, \ ctype* restrict a, inc_t rs_a, inc_t cs_a, \ ctype* restrict b, inc_t rs_b, inc_t cs_b, \ ctype* restrict beta, \ ctype* restrict c, inc_t rs_c, inc_t cs_c, \ auxinfo_t* restrict data, \ cntx_t* restrict cntx \ ) \ { \ const dim_t mn = m * n; \ \ ctype ab[ BLIS_STACK_BUF_MAX_SIZE \ / sizeof( ctype ) ] \ __attribute__((aligned(BLIS_STACK_BUF_ALIGN_SIZE))); \ const inc_t rs_ab = 1; \ const inc_t cs_ab = m; \ \ \ /* Assumptions: m <= mr, n <= nr so that the temporary array ab is sufficiently large enough to hold the m x n microtile. The ability to handle m < mr and n < nr is being provided so that optimized ukernels can call one of these reference implementations for their edge cases, if they choose. When they do so, they will need to call the function directly, by its configuration-mangled name, since it will have been overwritten in the context when the optimized ukernel functions are registered. */ \ \ \ /* Initialize the accumulator elements in ab to zero. */ \ for ( dim_t i = 0; i < mn; ++i ) \ { \ PASTEMAC(ch,set0s)( ab[i] ); \ } \ \ /* Perform a series of k rank-1 updates into ab. */ \ for ( dim_t l = 0; l < k; ++l ) \ { \ /* General storage: doesn't matter how we traverse ab. */ \ for ( dim_t j = 0; j < n; ++j ) \ { \ for ( dim_t i = 0; i < m; ++i ) \ { \ PASTEMAC(ch,dots) \ ( \ a[ i*rs_a ], \ b[ j*cs_b ], \ ab[ i*rs_ab + j*cs_ab ] \ ); \ } \ } \ \ a += cs_a; \ b += rs_b; \ } \ \ /* Scale the result in ab by alpha. */ \ for ( dim_t i = 0; i < mn; ++i ) \ { \ PASTEMAC(ch,scals)( *alpha, ab[i] ); \ } \ \ \ /* If beta is one, add ab into c. If beta is zero, overwrite c with the result in ab. Otherwise, scale by beta and accumulate ab to c. */ \ if ( PASTEMAC(ch,eq1)( *beta ) ) \ { \ /* General storage: doesn't matter how we traverse ab and c. */ \ for ( dim_t j = 0; j < n; ++j ) \ for ( dim_t i = 0; i < m; ++i ) \ { \ PASTEMAC(ch,adds) \ ( \ ab[ i*rs_ab + j*cs_ab ], \ c[ i*rs_c + j*cs_c ] \ ) \ } \ } \ else if ( PASTEMAC(ch,eq0)( *beta ) ) \ { \ /* General storage: doesn't matter how we traverse ab and c. */ \ for ( dim_t j = 0; j < n; ++j ) \ for ( dim_t i = 0; i < m; ++i ) \ { \ PASTEMAC(ch,copys) \ ( \ ab[ i*rs_ab + j*cs_ab ], \ c[ i*rs_c + j*cs_c ] \ ) \ } \ } \ else /* beta != 0 && beta != 1 */ \ { \ /* General storage: doesn't matter how we traverse ab and c. */ \ for ( dim_t j = 0; j < n; ++j ) \ for ( dim_t i = 0; i < m; ++i ) \ { \ PASTEMAC(ch,xpbys) \ ( \ ab[ i*rs_ab + j*cs_ab ], \ *beta, \ c[ i*rs_c + j*cs_c ] \ ) \ } \ } \ } INSERT_GENTFUNC_BASIC2( gemmsup_g, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX ) #endif blis-0.9.0/ref_kernels/3/bli_gemmtrsm_ref.c000066400000000000000000000107561422157504600206120ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, arch, suf, trsmkerid ) \ \ void PASTEMAC3(ch,opname,arch,suf) \ ( \ dim_t m, \ dim_t n, \ dim_t k, \ ctype* restrict alpha, \ ctype* restrict a1x, \ ctype* restrict a11, \ ctype* restrict bx1, \ ctype* restrict b11, \ ctype* restrict c11, inc_t rs_c, inc_t cs_c, \ auxinfo_t* restrict data, \ cntx_t* restrict cntx \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ const dim_t mr = bli_cntx_get_blksz_def_dt( dt, BLIS_MR, cntx ); \ const dim_t nr = bli_cntx_get_blksz_def_dt( dt, BLIS_NR, cntx ); \ \ const inc_t packnr = bli_cntx_get_blksz_max_dt( dt, BLIS_NR, cntx ); \ \ const inc_t rs_b = packnr; \ const inc_t cs_b = 1; \ \ ctype* minus_one = PASTEMAC(ch,m1); \ \ PASTECH(ch,gemm_ukr_ft) \ gemm_ukr = bli_cntx_get_l3_nat_ukr_dt( dt, BLIS_GEMM_UKR, cntx ); \ PASTECH(ch,trsm_ukr_ft) \ trsm_ukr = bli_cntx_get_l3_nat_ukr_dt( dt, trsmkerid, cntx ); \ \ ctype ct[ BLIS_STACK_BUF_MAX_SIZE \ / sizeof( ctype ) ] \ __attribute__((aligned(BLIS_STACK_BUF_ALIGN_SIZE))); \ /* FGVZ: Should we be querying the preference of BLIS_GEMMTRSM_?_UKR instead? */ \ const bool col_pref = bli_cntx_l3_vir_ukr_prefers_cols_dt( dt, BLIS_GEMM_UKR, cntx ); \ const inc_t rs_ct = ( col_pref ? 1 : nr ); \ const inc_t cs_ct = ( col_pref ? mr : 1 ); \ \ const bool use_ct = ( m < mr || n < nr ); \ \ ctype* restrict c11_use = c11; \ inc_t rs_c_use = rs_c; \ inc_t cs_c_use = cs_c; \ \ if ( use_ct ) \ { \ c11_use = ct; \ rs_c_use = rs_ct; \ cs_c_use = cs_ct; \ } \ \ /* lower: b11 = alpha * b11 - a10 * b01; */ \ /* upper: b11 = alpha * b11 - a12 * b21; */ \ gemm_ukr \ ( \ m, \ n, \ k, \ minus_one, \ a1x, \ bx1, \ alpha, \ b11, rs_b, cs_b, \ data, \ cntx \ ); \ \ /* b11 = inv(a11) * b11; c11 = b11; */ \ trsm_ukr \ ( \ a11, \ b11, \ c11_use, rs_c_use, cs_c_use, \ data, \ cntx \ ); \ \ if ( use_ct ) \ { \ PASTEMAC(ch,copys_mxn) \ ( \ m, n, \ ct, rs_ct, cs_ct, \ c11, rs_c, cs_c \ ); \ } \ \ /* PASTEMAC(d,fprintm)( stdout, "gemmtrsm_ukr: b0111p_r after", k+3, 8, \ ( double* )b01, 2*PASTEMAC(ch,packnr), 2, "%4.1f", "" ); \ PASTEMAC(d,fprintm)( stdout, "gemmtrsm_ukr: b0111p_i after", k+3, 8, \ ( double* )b01 + 1, 2*PASTEMAC(ch,packnr), 2, "%4.1f", "" ); \ */ \ } INSERT_GENTFUNC_BASIC3( gemmtrsm_l, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX, BLIS_TRSM_L_UKR ) INSERT_GENTFUNC_BASIC3( gemmtrsm_u, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX, BLIS_TRSM_U_UKR ) blis-0.9.0/ref_kernels/3/bli_trsm_ref.c000066400000000000000000000164411422157504600177410ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #if 0 // An implementation that attempts to facilitate emission of vectorized // instructions via constant loop bounds + #pragma omp simd directives. // (Deleted. See 'old' directory.) #else // An implementation that uses variable loop bounds (queried from the context) // and makes no use of #pragma omp simd. #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, arch, suf, diagop ) \ \ void PASTEMAC3(ch,opname,arch,suf) \ ( \ ctype* restrict a, \ ctype* restrict b, \ ctype* restrict c, inc_t rs_c, inc_t cs_c, \ auxinfo_t* restrict data, \ cntx_t* restrict cntx \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ const dim_t mr = bli_cntx_get_blksz_def_dt( dt, BLIS_MR, cntx ); \ const dim_t nr = bli_cntx_get_blksz_def_dt( dt, BLIS_NR, cntx ); \ \ const inc_t packmr = bli_cntx_get_blksz_max_dt( dt, BLIS_MR, cntx ); \ const inc_t packnr = bli_cntx_get_blksz_max_dt( dt, BLIS_NR, cntx ); \ \ const dim_t m = mr; \ const dim_t n = nr; \ \ const inc_t rs_a = 1; \ const inc_t cs_a = packmr; \ \ const inc_t rs_b = packnr; \ const inc_t cs_b = 1; \ \ dim_t iter, i, j, l; \ dim_t n_behind; \ \ for ( iter = 0; iter < m; ++iter ) \ { \ i = iter; \ n_behind = i; \ \ ctype* restrict alpha11 = a + (i )*rs_a + (i )*cs_a; \ ctype* restrict a10t = a + (i )*rs_a + (0 )*cs_a; \ ctype* restrict B0 = b + (0 )*rs_b + (0 )*cs_b; \ ctype* restrict b1 = b + (i )*rs_b + (0 )*cs_b; \ \ /* b1 = b1 - a10t * B0; */ \ /* b1 = b1 / alpha11; */ \ for ( j = 0; j < n; ++j ) \ { \ ctype* restrict b01 = B0 + (0 )*rs_b + (j )*cs_b; \ ctype* restrict beta11 = b1 + (0 )*rs_b + (j )*cs_b; \ ctype* restrict gamma11 = c + (i )*rs_c + (j )*cs_c; \ ctype beta11c = *beta11; \ ctype rho11; \ \ /* beta11 = beta11 - a10t * b01; */ \ PASTEMAC(ch,set0s)( rho11 ); \ for ( l = 0; l < n_behind; ++l ) \ { \ ctype* restrict alpha10 = a10t + (l )*cs_a; \ ctype* restrict beta01 = b01 + (l )*rs_b; \ \ PASTEMAC(ch,axpys)( *alpha10, *beta01, rho11 ); \ } \ PASTEMAC(ch,subs)( rho11, beta11c ); \ \ /* beta11 = beta11 / alpha11; */ \ /* NOTE: When preinversion is enabled, the INVERSE of alpha11 (1.0/alpha11) is stored during packing instead alpha11 so we can multiply rather than divide. When preinversion is disabled, alpha11 is stored and division happens below explicitly. */ \ PASTEMAC(ch,diagop)( *alpha11, beta11c ); \ \ /* Output final result to matrix c. */ \ PASTEMAC(ch,copys)( beta11c, *gamma11 ); \ \ /* Store the local value back to b11. */ \ PASTEMAC(ch,copys)( beta11c, *beta11 ); \ } \ } \ } #ifdef BLIS_ENABLE_TRSM_PREINVERSION INSERT_GENTFUNC_BASIC3( trsm_l, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX, scals ) #else INSERT_GENTFUNC_BASIC3( trsm_l, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX, invscals ) #endif #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, arch, suf, diagop ) \ \ void PASTEMAC3(ch,opname,arch,suf) \ ( \ ctype* restrict a, \ ctype* restrict b, \ ctype* restrict c, inc_t rs_c, inc_t cs_c, \ auxinfo_t* restrict data, \ cntx_t* restrict cntx \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ const dim_t mr = bli_cntx_get_blksz_def_dt( dt, BLIS_MR, cntx ); \ const dim_t nr = bli_cntx_get_blksz_def_dt( dt, BLIS_NR, cntx ); \ \ const inc_t packmr = bli_cntx_get_blksz_max_dt( dt, BLIS_MR, cntx ); \ const inc_t packnr = bli_cntx_get_blksz_max_dt( dt, BLIS_NR, cntx ); \ \ const dim_t m = mr; \ const dim_t n = nr; \ \ const inc_t rs_a = 1; \ const inc_t cs_a = packmr; \ \ const inc_t rs_b = packnr; \ const inc_t cs_b = 1; \ \ dim_t iter, i, j, l; \ dim_t n_behind; \ \ for ( iter = 0; iter < m; ++iter ) \ { \ i = m - iter - 1; \ n_behind = iter; \ \ ctype* restrict alpha11 = a + (i )*rs_a + (i )*cs_a; \ ctype* restrict a12t = a + (i )*rs_a + (i+1)*cs_a; \ ctype* restrict b1 = b + (i )*rs_b + (0 )*cs_b; \ ctype* restrict B2 = b + (i+1)*rs_b + (0 )*cs_b; \ \ /* b1 = b1 - a12t * B2; */ \ /* b1 = b1 / alpha11; */ \ for ( j = 0; j < n; ++j ) \ { \ ctype* restrict beta11 = b1 + (0 )*rs_b + (j )*cs_b; \ ctype* restrict b21 = B2 + (0 )*rs_b + (j )*cs_b; \ ctype* restrict gamma11 = c + (i )*rs_c + (j )*cs_c; \ ctype beta11c = *beta11; \ ctype rho11; \ \ /* beta11 = beta11 - a12t * b21; */ \ PASTEMAC(ch,set0s)( rho11 ); \ for ( l = 0; l < n_behind; ++l ) \ { \ ctype* restrict alpha12 = a12t + (l )*cs_a; \ ctype* restrict beta21 = b21 + (l )*rs_b; \ \ PASTEMAC(ch,axpys)( *alpha12, *beta21, rho11 ); \ } \ PASTEMAC(ch,subs)( rho11, beta11c ); \ \ /* beta11 = beta11 / alpha11; */ \ /* NOTE: When preinversion is enabled, the INVERSE of alpha11 (1.0/alpha11) is stored during packing instead alpha11 so we can multiply rather than divide. When preinversion is disabled, alpha11 is stored and division happens below explicitly. */ \ PASTEMAC(ch,diagop)( *alpha11, beta11c ); \ \ /* Output final result to matrix c. */ \ PASTEMAC(ch,copys)( beta11c, *gamma11 ); \ \ /* Store the local value back to b11. */ \ PASTEMAC(ch,copys)( beta11c, *beta11 ); \ } \ } \ } #ifdef BLIS_ENABLE_TRSM_PREINVERSION INSERT_GENTFUNC_BASIC3( trsm_u, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX, scals ) #else INSERT_GENTFUNC_BASIC3( trsm_u, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX, invscals ) #endif #endif blis-0.9.0/ref_kernels/3/old/000077500000000000000000000000001422157504600156765ustar00rootroot00000000000000blis-0.9.0/ref_kernels/3/old/bli_gemm_simd_ref.c000066400000000000000000000121121422157504600214620ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, arch, suf, mr, nr ) \ \ void PASTEMAC4(ch,opname,arch,_simd,suf) \ ( \ dim_t k, \ ctype* restrict alpha, \ ctype* restrict a, \ ctype* restrict b, \ ctype* restrict beta, \ ctype* restrict c, inc_t rs_c, inc_t cs_c, \ auxinfo_t* restrict data, \ cntx_t* restrict cntx \ ) \ { \ ctype ab[ BLIS_STACK_BUF_MAX_SIZE \ / sizeof( ctype ) ] \ __attribute__((aligned(BLIS_STACK_BUF_ALIGN_SIZE))); \ const inc_t rs_ab = nr; \ const inc_t cs_ab = 1; \ \ const inc_t cs_a = mr; \ const inc_t rs_b = nr; \ \ \ /* Initialize the accumulator elements in ab to zero. */ \ PRAGMA_SIMD \ for ( dim_t i = 0; i < mr * nr; ++i ) \ { \ PASTEMAC(ch,set0s)( ab[ i ] ); \ } \ \ /* const dim_t pre = 16; \ dim_t k16; \ if ( k >= pre ) { k16 = k - pre; k = pre; } \ else { k16 = 0; } \ \ for ( dim_t l = 0; l < k16; ++l ) \ { \ for ( dim_t i = 0; i < mr; ++i ) \ { \ PRAGMA_SIMD \ for ( dim_t j = 0; j < nr; ++j ) \ { \ PASTEMAC(ch,dots) \ ( \ a[ i ], \ b[ j ], \ ab[ i*rs_ab + j*cs_ab ] \ ); \ } \ } \ \ a += cs_a; \ b += rs_b; \ } \ \ __builtin_prefetch( c + 0*cs_c, 1, 0 ); \ __builtin_prefetch( c + 1*cs_c, 1, 0 ); \ __builtin_prefetch( c + 2*cs_c, 1, 0 ); \ __builtin_prefetch( c + 3*cs_c, 1, 0 ); \ */ \ \ /* Perform a series of k rank-1 updates into ab. */ \ for ( dim_t l = 0; l < k; ++l ) \ { \ for ( dim_t i = 0; i < mr; ++i ) \ { \ PRAGMA_SIMD \ for ( dim_t j = 0; j < nr; ++j ) \ { \ PASTEMAC(ch,dots) \ ( \ a[ i ], \ b[ j ], \ ab[ i*rs_ab + j*cs_ab ] \ ); \ } \ } \ \ a += cs_a; \ b += rs_b; \ } \ \ /* Scale the result in ab by alpha. */ \ PRAGMA_SIMD \ for ( dim_t i = 0; i < mr * nr; ++i ) \ { \ PASTEMAC(ch,scals)( *alpha, ab[ i ] ); \ } \ \ /* Output/accumulate intermediate result ab based on the storage of c and the value of beta. */ \ if ( cs_c == 1 ) \ { \ /* C is row-stored. */ \ \ if ( PASTEMAC(ch,eq0)( *beta ) ) \ { \ for ( dim_t i = 0; i < mr; ++i ) \ for ( dim_t j = 0; j < nr; ++j ) \ PASTEMAC(ch,copys) \ ( \ ab[ i*rs_ab + j*cs_ab ], \ c [ i*rs_c + j*1 ] \ ); \ } \ else \ { \ for ( dim_t i = 0; i < mr; ++i ) \ for ( dim_t j = 0; j < nr; ++j ) \ PASTEMAC(ch,xpbys) \ ( \ ab[ i*rs_ab + j*cs_ab ], \ *beta, \ c [ i*rs_c + j*1 ] \ ); \ } \ } \ else \ { \ /* C is column-stored or general-stored. */ \ \ if ( PASTEMAC(ch,eq0)( *beta ) ) \ { \ for ( dim_t j = 0; j < nr; ++j ) \ for ( dim_t i = 0; i < mr; ++i ) \ PASTEMAC(ch,copys) \ ( \ ab[ i*rs_ab + j*cs_ab ], \ c [ i*rs_c + j*1 ] \ ); \ } \ else \ { \ for ( dim_t j = 0; j < nr; ++j ) \ for ( dim_t i = 0; i < mr; ++i ) \ PASTEMAC(ch,xpbys) \ ( \ ab[ i*rs_ab + j*cs_ab ], \ *beta, \ c [ i*rs_c + j*1 ] \ ); \ } \ } \ } //INSERT_GENTFUNC_BASIC2( gemm, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX ) GENTFUNC( float, s, gemm, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX, 4, 16 ) GENTFUNC( double, d, gemm, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX, 4, 8 ) GENTFUNC( scomplex, c, gemm, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX, 4, 8 ) GENTFUNC( dcomplex, z, gemm, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX, 4, 4 ) blis-0.9.0/ref_kernels/3/old/bli_gemm_unrl_ref.c000066400000000000000000000302671422157504600215210ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // -- dgemm -------------------------------------------------------------------- // #undef CH #define CH d #undef CTYPE #define CTYPE double #undef ZERO #define ZERO 0.0 #undef MR #define MR 4 #undef NR #define NR 8 //void PASTEMAC4(CH,gemm,BLIS_CNAME_INFIX,BLIS_REF_SUF,_4x8) void PASTEMAC6(CH,gemm,BLIS_CNAME_REF_SUFFIX,_,MR,x,NR) ( dim_t k, CTYPE* restrict alpha, CTYPE* restrict a, CTYPE* restrict b, CTYPE* restrict beta, CTYPE* restrict c, inc_t rs_c, inc_t cs_c, auxinfo_t* restrict data, cntx_t* restrict cntx ) { const dim_t cs_a = MR; const dim_t rs_b = NR; CTYPE ab00 = ZERO, ab01 = ZERO, ab02 = ZERO, ab03 = ZERO; CTYPE ab10 = ZERO, ab11 = ZERO, ab12 = ZERO, ab13 = ZERO; CTYPE ab20 = ZERO, ab21 = ZERO, ab22 = ZERO, ab23 = ZERO; CTYPE ab30 = ZERO, ab31 = ZERO, ab32 = ZERO, ab33 = ZERO; CTYPE ab04 = ZERO, ab05 = ZERO, ab06 = ZERO, ab07 = ZERO; CTYPE ab14 = ZERO, ab15 = ZERO, ab16 = ZERO, ab17 = ZERO; CTYPE ab24 = ZERO, ab25 = ZERO, ab26 = ZERO, ab27 = ZERO; CTYPE ab34 = ZERO, ab35 = ZERO, ab36 = ZERO, ab37 = ZERO; // Perform a series of k rank-1 updates into ab. for ( ; k != 0; --k ) { const CTYPE a0 = a[0]; ab00 += a0*b[0]; ab01 += a0*b[1]; ab02 += a0*b[2]; ab03 += a0*b[3]; ab04 += a0*b[4]; ab05 += a0*b[5]; ab06 += a0*b[6]; ab07 += a0*b[7]; const CTYPE a1 = a[1]; ab10 += a1*b[0]; ab11 += a1*b[1]; ab12 += a1*b[2]; ab13 += a1*b[3]; ab14 += a1*b[4]; ab15 += a1*b[5]; ab16 += a1*b[6]; ab17 += a1*b[7]; const CTYPE a2 = a[2]; ab20 += a2*b[0]; ab21 += a2*b[1]; ab22 += a2*b[2]; ab23 += a2*b[3]; ab24 += a2*b[4]; ab25 += a2*b[5]; ab26 += a2*b[6]; ab27 += a2*b[7]; const CTYPE a3 = a[3]; ab30 += a3*b[0]; ab31 += a3*b[1]; ab32 += a3*b[2]; ab33 += a3*b[3]; ab34 += a3*b[4]; ab35 += a3*b[5]; ab36 += a3*b[6]; ab37 += a3*b[7]; a += cs_a; b += rs_b; } // Scale each element of ab by alpha. if ( !PASTEMAC(CH,eq1)( *alpha ) ) { const CTYPE alpha0 = *alpha; PASTEMAC(CH,scals)( alpha0, ab00 ); PASTEMAC(CH,scals)( alpha0, ab01 ); PASTEMAC(CH,scals)( alpha0, ab02 ); PASTEMAC(CH,scals)( alpha0, ab02 ); PASTEMAC(CH,scals)( alpha0, ab04 ); PASTEMAC(CH,scals)( alpha0, ab05 ); PASTEMAC(CH,scals)( alpha0, ab06 ); PASTEMAC(CH,scals)( alpha0, ab07 ); PASTEMAC(CH,scals)( alpha0, ab10 ); PASTEMAC(CH,scals)( alpha0, ab11 ); PASTEMAC(CH,scals)( alpha0, ab12 ); PASTEMAC(CH,scals)( alpha0, ab12 ); PASTEMAC(CH,scals)( alpha0, ab14 ); PASTEMAC(CH,scals)( alpha0, ab15 ); PASTEMAC(CH,scals)( alpha0, ab16 ); PASTEMAC(CH,scals)( alpha0, ab17 ); PASTEMAC(CH,scals)( alpha0, ab20 ); PASTEMAC(CH,scals)( alpha0, ab21 ); PASTEMAC(CH,scals)( alpha0, ab22 ); PASTEMAC(CH,scals)( alpha0, ab22 ); PASTEMAC(CH,scals)( alpha0, ab24 ); PASTEMAC(CH,scals)( alpha0, ab25 ); PASTEMAC(CH,scals)( alpha0, ab26 ); PASTEMAC(CH,scals)( alpha0, ab27 ); PASTEMAC(CH,scals)( alpha0, ab30 ); PASTEMAC(CH,scals)( alpha0, ab31 ); PASTEMAC(CH,scals)( alpha0, ab32 ); PASTEMAC(CH,scals)( alpha0, ab32 ); PASTEMAC(CH,scals)( alpha0, ab34 ); PASTEMAC(CH,scals)( alpha0, ab35 ); PASTEMAC(CH,scals)( alpha0, ab36 ); PASTEMAC(CH,scals)( alpha0, ab37 ); } // Output/accumulate intermediate result ab based on the storage // of c and the value of beta. if ( cs_c == 1 ) { // C is row-stored. if ( PASTEMAC(CH,eq0)( *beta ) ) { // beta == 0: // c := ab PASTEMAC(CH,copys)( ab00, c[ 0*rs_c + 0 ] ); PASTEMAC(CH,copys)( ab01, c[ 0*rs_c + 1 ] ); PASTEMAC(CH,copys)( ab02, c[ 0*rs_c + 2 ] ); PASTEMAC(CH,copys)( ab03, c[ 0*rs_c + 3 ] ); PASTEMAC(CH,copys)( ab04, c[ 0*rs_c + 4 ] ); PASTEMAC(CH,copys)( ab05, c[ 0*rs_c + 5 ] ); PASTEMAC(CH,copys)( ab06, c[ 0*rs_c + 6 ] ); PASTEMAC(CH,copys)( ab07, c[ 0*rs_c + 7 ] ); PASTEMAC(CH,copys)( ab10, c[ 1*rs_c + 0 ] ); PASTEMAC(CH,copys)( ab11, c[ 1*rs_c + 1 ] ); PASTEMAC(CH,copys)( ab12, c[ 1*rs_c + 2 ] ); PASTEMAC(CH,copys)( ab13, c[ 1*rs_c + 3 ] ); PASTEMAC(CH,copys)( ab14, c[ 1*rs_c + 4 ] ); PASTEMAC(CH,copys)( ab15, c[ 1*rs_c + 5 ] ); PASTEMAC(CH,copys)( ab16, c[ 1*rs_c + 6 ] ); PASTEMAC(CH,copys)( ab17, c[ 1*rs_c + 7 ] ); PASTEMAC(CH,copys)( ab20, c[ 2*rs_c + 0 ] ); PASTEMAC(CH,copys)( ab21, c[ 2*rs_c + 1 ] ); PASTEMAC(CH,copys)( ab22, c[ 2*rs_c + 2 ] ); PASTEMAC(CH,copys)( ab23, c[ 2*rs_c + 3 ] ); PASTEMAC(CH,copys)( ab24, c[ 2*rs_c + 4 ] ); PASTEMAC(CH,copys)( ab25, c[ 2*rs_c + 5 ] ); PASTEMAC(CH,copys)( ab26, c[ 2*rs_c + 6 ] ); PASTEMAC(CH,copys)( ab27, c[ 2*rs_c + 7 ] ); PASTEMAC(CH,copys)( ab30, c[ 3*rs_c + 0 ] ); PASTEMAC(CH,copys)( ab31, c[ 3*rs_c + 1 ] ); PASTEMAC(CH,copys)( ab32, c[ 3*rs_c + 2 ] ); PASTEMAC(CH,copys)( ab33, c[ 3*rs_c + 3 ] ); PASTEMAC(CH,copys)( ab34, c[ 3*rs_c + 4 ] ); PASTEMAC(CH,copys)( ab35, c[ 3*rs_c + 5 ] ); PASTEMAC(CH,copys)( ab36, c[ 3*rs_c + 6 ] ); PASTEMAC(CH,copys)( ab37, c[ 3*rs_c + 7 ] ); } else { const CTYPE beta0 = *beta; // beta != 0: // c := beta * c + ab PASTEMAC(CH,xpbys)( ab00, beta0, c[ 0*rs_c + 0 ] ); PASTEMAC(CH,xpbys)( ab01, beta0, c[ 0*rs_c + 1 ] ); PASTEMAC(CH,xpbys)( ab02, beta0, c[ 0*rs_c + 2 ] ); PASTEMAC(CH,xpbys)( ab03, beta0, c[ 0*rs_c + 3 ] ); PASTEMAC(CH,xpbys)( ab04, beta0, c[ 0*rs_c + 4 ] ); PASTEMAC(CH,xpbys)( ab05, beta0, c[ 0*rs_c + 5 ] ); PASTEMAC(CH,xpbys)( ab06, beta0, c[ 0*rs_c + 6 ] ); PASTEMAC(CH,xpbys)( ab07, beta0, c[ 0*rs_c + 7 ] ); PASTEMAC(CH,xpbys)( ab10, beta0, c[ 1*rs_c + 0 ] ); PASTEMAC(CH,xpbys)( ab11, beta0, c[ 1*rs_c + 1 ] ); PASTEMAC(CH,xpbys)( ab12, beta0, c[ 1*rs_c + 2 ] ); PASTEMAC(CH,xpbys)( ab13, beta0, c[ 1*rs_c + 3 ] ); PASTEMAC(CH,xpbys)( ab14, beta0, c[ 1*rs_c + 4 ] ); PASTEMAC(CH,xpbys)( ab15, beta0, c[ 1*rs_c + 5 ] ); PASTEMAC(CH,xpbys)( ab16, beta0, c[ 1*rs_c + 6 ] ); PASTEMAC(CH,xpbys)( ab17, beta0, c[ 1*rs_c + 7 ] ); PASTEMAC(CH,xpbys)( ab20, beta0, c[ 2*rs_c + 0 ] ); PASTEMAC(CH,xpbys)( ab21, beta0, c[ 2*rs_c + 1 ] ); PASTEMAC(CH,xpbys)( ab22, beta0, c[ 2*rs_c + 2 ] ); PASTEMAC(CH,xpbys)( ab23, beta0, c[ 2*rs_c + 3 ] ); PASTEMAC(CH,xpbys)( ab24, beta0, c[ 2*rs_c + 4 ] ); PASTEMAC(CH,xpbys)( ab25, beta0, c[ 2*rs_c + 5 ] ); PASTEMAC(CH,xpbys)( ab26, beta0, c[ 2*rs_c + 6 ] ); PASTEMAC(CH,xpbys)( ab27, beta0, c[ 2*rs_c + 7 ] ); PASTEMAC(CH,xpbys)( ab30, beta0, c[ 3*rs_c + 0 ] ); PASTEMAC(CH,xpbys)( ab31, beta0, c[ 3*rs_c + 1 ] ); PASTEMAC(CH,xpbys)( ab32, beta0, c[ 3*rs_c + 2 ] ); PASTEMAC(CH,xpbys)( ab33, beta0, c[ 3*rs_c + 3 ] ); PASTEMAC(CH,xpbys)( ab34, beta0, c[ 3*rs_c + 4 ] ); PASTEMAC(CH,xpbys)( ab35, beta0, c[ 3*rs_c + 5 ] ); PASTEMAC(CH,xpbys)( ab36, beta0, c[ 3*rs_c + 6 ] ); PASTEMAC(CH,xpbys)( ab37, beta0, c[ 3*rs_c + 7 ] ); } } else { // C is general-stored (or column-stored). if ( PASTEMAC(CH,eq0)( *beta ) ) { // beta == 0: // c := ab PASTEMAC(CH,copys)( ab00, c[ 0*rs_c + 0*cs_c ] ); PASTEMAC(CH,copys)( ab01, c[ 0*rs_c + 1*cs_c ] ); PASTEMAC(CH,copys)( ab02, c[ 0*rs_c + 2*cs_c ] ); PASTEMAC(CH,copys)( ab03, c[ 0*rs_c + 3*cs_c ] ); PASTEMAC(CH,copys)( ab04, c[ 0*rs_c + 4*cs_c ] ); PASTEMAC(CH,copys)( ab05, c[ 0*rs_c + 5*cs_c ] ); PASTEMAC(CH,copys)( ab06, c[ 0*rs_c + 6*cs_c ] ); PASTEMAC(CH,copys)( ab07, c[ 0*rs_c + 7*cs_c ] ); PASTEMAC(CH,copys)( ab10, c[ 1*rs_c + 0*cs_c ] ); PASTEMAC(CH,copys)( ab11, c[ 1*rs_c + 1*cs_c ] ); PASTEMAC(CH,copys)( ab12, c[ 1*rs_c + 2*cs_c ] ); PASTEMAC(CH,copys)( ab13, c[ 1*rs_c + 3*cs_c ] ); PASTEMAC(CH,copys)( ab14, c[ 1*rs_c + 4*cs_c ] ); PASTEMAC(CH,copys)( ab15, c[ 1*rs_c + 5*cs_c ] ); PASTEMAC(CH,copys)( ab16, c[ 1*rs_c + 6*cs_c ] ); PASTEMAC(CH,copys)( ab17, c[ 1*rs_c + 7*cs_c ] ); PASTEMAC(CH,copys)( ab20, c[ 2*rs_c + 0*cs_c ] ); PASTEMAC(CH,copys)( ab21, c[ 2*rs_c + 1*cs_c ] ); PASTEMAC(CH,copys)( ab22, c[ 2*rs_c + 2*cs_c ] ); PASTEMAC(CH,copys)( ab23, c[ 2*rs_c + 3*cs_c ] ); PASTEMAC(CH,copys)( ab24, c[ 2*rs_c + 4*cs_c ] ); PASTEMAC(CH,copys)( ab25, c[ 2*rs_c + 5*cs_c ] ); PASTEMAC(CH,copys)( ab26, c[ 2*rs_c + 6*cs_c ] ); PASTEMAC(CH,copys)( ab27, c[ 2*rs_c + 7*cs_c ] ); PASTEMAC(CH,copys)( ab30, c[ 3*rs_c + 0*cs_c ] ); PASTEMAC(CH,copys)( ab31, c[ 3*rs_c + 1*cs_c ] ); PASTEMAC(CH,copys)( ab32, c[ 3*rs_c + 2*cs_c ] ); PASTEMAC(CH,copys)( ab33, c[ 3*rs_c + 3*cs_c ] ); PASTEMAC(CH,copys)( ab34, c[ 3*rs_c + 4*cs_c ] ); PASTEMAC(CH,copys)( ab35, c[ 3*rs_c + 5*cs_c ] ); PASTEMAC(CH,copys)( ab36, c[ 3*rs_c + 6*cs_c ] ); PASTEMAC(CH,copys)( ab37, c[ 3*rs_c + 7*cs_c ] ); } else { const CTYPE beta0 = *beta; // beta != 0: // c := beta * c + ab PASTEMAC(CH,xpbys)( ab00, beta0, c[ 0*rs_c + 0*cs_c ] ); PASTEMAC(CH,xpbys)( ab01, beta0, c[ 0*rs_c + 1*cs_c ] ); PASTEMAC(CH,xpbys)( ab02, beta0, c[ 0*rs_c + 2*cs_c ] ); PASTEMAC(CH,xpbys)( ab03, beta0, c[ 0*rs_c + 3*cs_c ] ); PASTEMAC(CH,xpbys)( ab04, beta0, c[ 0*rs_c + 4*cs_c ] ); PASTEMAC(CH,xpbys)( ab05, beta0, c[ 0*rs_c + 5*cs_c ] ); PASTEMAC(CH,xpbys)( ab06, beta0, c[ 0*rs_c + 6*cs_c ] ); PASTEMAC(CH,xpbys)( ab07, beta0, c[ 0*rs_c + 7*cs_c ] ); PASTEMAC(CH,xpbys)( ab10, beta0, c[ 1*rs_c + 0*cs_c ] ); PASTEMAC(CH,xpbys)( ab11, beta0, c[ 1*rs_c + 1*cs_c ] ); PASTEMAC(CH,xpbys)( ab12, beta0, c[ 1*rs_c + 2*cs_c ] ); PASTEMAC(CH,xpbys)( ab13, beta0, c[ 1*rs_c + 3*cs_c ] ); PASTEMAC(CH,xpbys)( ab14, beta0, c[ 1*rs_c + 4*cs_c ] ); PASTEMAC(CH,xpbys)( ab15, beta0, c[ 1*rs_c + 5*cs_c ] ); PASTEMAC(CH,xpbys)( ab16, beta0, c[ 1*rs_c + 6*cs_c ] ); PASTEMAC(CH,xpbys)( ab17, beta0, c[ 1*rs_c + 7*cs_c ] ); PASTEMAC(CH,xpbys)( ab20, beta0, c[ 2*rs_c + 0*cs_c ] ); PASTEMAC(CH,xpbys)( ab21, beta0, c[ 2*rs_c + 1*cs_c ] ); PASTEMAC(CH,xpbys)( ab22, beta0, c[ 2*rs_c + 2*cs_c ] ); PASTEMAC(CH,xpbys)( ab23, beta0, c[ 2*rs_c + 3*cs_c ] ); PASTEMAC(CH,xpbys)( ab24, beta0, c[ 2*rs_c + 4*cs_c ] ); PASTEMAC(CH,xpbys)( ab25, beta0, c[ 2*rs_c + 5*cs_c ] ); PASTEMAC(CH,xpbys)( ab26, beta0, c[ 2*rs_c + 6*cs_c ] ); PASTEMAC(CH,xpbys)( ab27, beta0, c[ 2*rs_c + 7*cs_c ] ); PASTEMAC(CH,xpbys)( ab30, beta0, c[ 3*rs_c + 0*cs_c ] ); PASTEMAC(CH,xpbys)( ab31, beta0, c[ 3*rs_c + 1*cs_c ] ); PASTEMAC(CH,xpbys)( ab32, beta0, c[ 3*rs_c + 2*cs_c ] ); PASTEMAC(CH,xpbys)( ab33, beta0, c[ 3*rs_c + 3*cs_c ] ); PASTEMAC(CH,xpbys)( ab34, beta0, c[ 3*rs_c + 4*cs_c ] ); PASTEMAC(CH,xpbys)( ab35, beta0, c[ 3*rs_c + 5*cs_c ] ); PASTEMAC(CH,xpbys)( ab36, beta0, c[ 3*rs_c + 6*cs_c ] ); PASTEMAC(CH,xpbys)( ab37, beta0, c[ 3*rs_c + 7*cs_c ] ); } } } blis-0.9.0/ref_kernels/3/old/bli_trsm_simd_ref.c000066400000000000000000000130501422157504600215240ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #if 1 // An implementation that attempts to facilitate emission of vectorized // instructions via constant loop bounds + #pragma omp simd directives. #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, arch, suf, mr, nr ) \ \ void PASTEMAC3(ch,opname,arch,suf) \ ( \ ctype* restrict a, \ ctype* restrict b, \ ctype* restrict c, inc_t rs_c, inc_t cs_c, \ auxinfo_t* restrict data, \ cntx_t* restrict cntx \ ) \ { \ const inc_t rs_a = 1; \ const inc_t cs_a = mr; \ \ const inc_t rs_b = nr; \ const inc_t cs_b = 1; \ \ PRAGMA_SIMD \ for ( dim_t i = 0; i < mr; ++i ) \ { \ /* b1 = b1 - a10t * B0; */ \ /* b1 = b1 / alpha11; */ \ for ( dim_t j = 0; j < nr; ++j ) \ { \ ctype beta11c = b[i*rs_b + j*cs_b]; \ ctype rho11; \ \ /* beta11 = beta11 - a10t * b01; */ \ PASTEMAC(ch,set0s)( rho11 ); \ for ( dim_t l = 0; l < i; ++l ) \ { \ PASTEMAC(ch,axpys)( a[i*rs_a + l*cs_a], \ b[l*rs_b + j*cs_b], rho11 ); \ } \ PASTEMAC(ch,subs)( rho11, beta11c ); \ \ /* beta11 = beta11 / alpha11; */ \ /* NOTE: The INVERSE of alpha11 (1.0/alpha11) is stored instead of alpha11, so we can multiply rather than divide. We store the inverse of alpha11 intentionally to avoid expensive division instructions within the micro-kernel. */ \ PASTEMAC(ch,scals)( a[i*rs_a + i*cs_a], beta11c ); \ \ /* Output final result to matrix c. */ \ PASTEMAC(ch,copys)( beta11c, c[i*rs_c + j*cs_c] ); \ \ /* Store the local value back to b11. */ \ PASTEMAC(ch,copys)( beta11c, b[i*rs_b + j*cs_b] ); \ } \ } \ } //INSERT_GENTFUNC_BASIC2( trsm_l, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX ) GENTFUNC( float, s, trsm_l, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX, 4, 16 ) GENTFUNC( double, d, trsm_l, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX, 4, 8 ) GENTFUNC( scomplex, c, trsm_l, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX, 4, 8 ) GENTFUNC( dcomplex, z, trsm_l, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX, 4, 4 ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname, arch, suf, mr, nr ) \ \ void PASTEMAC3(ch,opname,arch,suf) \ ( \ ctype* restrict a, \ ctype* restrict b, \ ctype* restrict c, inc_t rs_c, inc_t cs_c, \ auxinfo_t* restrict data, \ cntx_t* restrict cntx \ ) \ { \ const inc_t rs_a = 1; \ const inc_t cs_a = mr; \ \ const inc_t rs_b = nr; \ const inc_t cs_b = 1; \ \ PRAGMA_SIMD \ for ( dim_t iter = 0; iter < mr; ++iter ) \ { \ dim_t i = mr - iter - 1; \ \ /* b1 = b1 - a12t * B2; */ \ /* b1 = b1 / alpha11; */ \ for ( dim_t j = 0; j < nr; ++j ) \ { \ ctype beta11c = b[i*rs_b + j*cs_b]; \ ctype rho11; \ \ /* beta11 = beta11 - a12t * b21; */ \ PASTEMAC(ch,set0s)( rho11 ); \ for ( dim_t l = 0; l < iter; ++l ) \ { \ PASTEMAC(ch,axpys)( a[i*rs_a + (i+1+l)*cs_a], \ b[(i+1+l)*rs_b + j*cs_b], rho11 ); \ } \ PASTEMAC(ch,subs)( rho11, beta11c ); \ \ /* beta11 = beta11 / alpha11; */ \ /* NOTE: The INVERSE of alpha11 (1.0/alpha11) is stored instead of alpha11, so we can multiply rather than divide. We store the inverse of alpha11 intentionally to avoid expensive division instructions within the micro-kernel. */ \ PASTEMAC(ch,scals)( a[i*rs_a + i*cs_a], beta11c ); \ \ /* Output final result to matrix c. */ \ PASTEMAC(ch,copys)( beta11c, c[i*rs_c + j*cs_c] ); \ \ /* Store the local value back to b11. */ \ PASTEMAC(ch,copys)( beta11c, b[i*rs_b + j*cs_b] ); \ } \ } \ } //INSERT_GENTFUNC_BASIC2( trsm_u, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX ) GENTFUNC( float, s, trsm_u, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX, 4, 16 ) GENTFUNC( double, d, trsm_u, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX, 4, 8 ) GENTFUNC( scomplex, c, trsm_u, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX, 4, 8 ) GENTFUNC( dcomplex, z, trsm_u, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX, 4, 4 ) #else #endif blis-0.9.0/ref_kernels/bli_cntx_ref.c000066400000000000000000000643311422157504600175670ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // -- Instantiate kernel prototypes for the current architecture --------------- // Define macros to construct the full symbol name from the operation name. #undef GENARNAME // architecture, _ref (no bli_) #define GENARNAME(opname) PASTECH2(opname,BLIS_CNAME_INFIX,BLIS_REF_SUFFIX) #undef GENBARNAME // bli_, architecture, _ref #define GENBARNAME(opname) PASTEMAC2(opname,BLIS_CNAME_INFIX,BLIS_REF_SUFFIX) #undef GENBAINAME // bli_, architecture, _ind #define GENBAINAME(opname) PASTEMAC2(opname,BLIS_CNAME_INFIX,BLIS_IND_SUFFIX) // -- Level-3 native micro-kernel prototype redefinitions ---------------------- // -- Prototypes for completely generic level-3 microkernels -- #undef gemm_ukr_name #define gemm_ukr_name GENARNAME(gemm) #undef gemmtrsm_l_ukr_name #define gemmtrsm_l_ukr_name GENARNAME(gemmtrsm_l) #undef gemmtrsm_u_ukr_name #define gemmtrsm_u_ukr_name GENARNAME(gemmtrsm_u) #undef trsm_l_ukr_name #define trsm_l_ukr_name GENARNAME(trsm_l) #undef trsm_u_ukr_name #define trsm_u_ukr_name GENARNAME(trsm_u) // Instantiate prototypes for above functions via the native micro-kernel API // template. #include "bli_l3_ukr.h" // -- Level-3 virtual micro-kernel prototype redefinitions --------------------- // -- Prototypes for induced method level-3 microkernels -- // -- 1m -- #undef gemm1m_ukr_name #define gemm1m_ukr_name GENARNAME(gemm1m) #undef gemmtrsm1m_l_ukr_name #define gemmtrsm1m_l_ukr_name GENARNAME(gemmtrsm1m_l) #undef gemmtrsm1m_u_ukr_name #define gemmtrsm1m_u_ukr_name GENARNAME(gemmtrsm1m_u) #undef trsm1m_l_ukr_name #define trsm1m_l_ukr_name GENARNAME(trsm1m_l) #undef trsm1m_u_ukr_name #define trsm1m_u_ukr_name GENARNAME(trsm1m_u) // Instantiate prototypes for above functions via the virtual micro-kernel API // template. #include "bli_l3_ind_ukr.h" // -- Level-3 small/unpacked micro-kernel prototype definitions ---------------- // NOTE: This results in redundant prototypes for gemmsup_r and gemmsup_c // kernels, but since they will be identical the compiler won't complain. #undef gemmsup_rv_ukr_name #define gemmsup_rv_ukr_name GENARNAME(gemmsup_r) #undef gemmsup_rg_ukr_name #define gemmsup_rg_ukr_name GENARNAME(gemmsup_r) #undef gemmsup_cv_ukr_name #define gemmsup_cv_ukr_name GENARNAME(gemmsup_c) #undef gemmsup_cg_ukr_name #define gemmsup_cg_ukr_name GENARNAME(gemmsup_c) #undef gemmsup_gx_ukr_name #define gemmsup_gx_ukr_name GENARNAME(gemmsup_g) // Include the small/unpacked kernel API template. #include "bli_l3_sup_ker.h" // -- Level-1m (packm/unpackm) kernel prototype redefinitions ------------------ #undef packm_2xk_ker_name #define packm_2xk_ker_name GENARNAME(packm_2xk) #undef packm_3xk_ker_name #define packm_3xk_ker_name GENARNAME(packm_3xk) #undef packm_4xk_ker_name #define packm_4xk_ker_name GENARNAME(packm_4xk) #undef packm_6xk_ker_name #define packm_6xk_ker_name GENARNAME(packm_6xk) #undef packm_8xk_ker_name #define packm_8xk_ker_name GENARNAME(packm_8xk) #undef packm_10xk_ker_name #define packm_10xk_ker_name GENARNAME(packm_10xk) #undef packm_12xk_ker_name #define packm_12xk_ker_name GENARNAME(packm_12xk) #undef packm_14xk_ker_name #define packm_14xk_ker_name GENARNAME(packm_14xk) #undef packm_16xk_ker_name #define packm_16xk_ker_name GENARNAME(packm_16xk) #undef packm_24xk_ker_name #define packm_24xk_ker_name GENARNAME(packm_24xk) #undef unpackm_2xk_ker_name #define unpackm_2xk_ker_name GENARNAME(unpackm_2xk) #undef unpackm_4xk_ker_name #define unpackm_4xk_ker_name GENARNAME(unpackm_4xk) #undef unpackm_6xk_ker_name #define unpackm_6xk_ker_name GENARNAME(unpackm_6xk) #undef unpackm_8xk_ker_name #define unpackm_8xk_ker_name GENARNAME(unpackm_8xk) #undef unpackm_10xk_ker_name #define unpackm_10xk_ker_name GENARNAME(unpackm_10xk) #undef unpackm_12xk_ker_name #define unpackm_12xk_ker_name GENARNAME(unpackm_12xk) #undef unpackm_14xk_ker_name #define unpackm_14xk_ker_name GENARNAME(unpackm_14xk) #undef unpackm_16xk_ker_name #define unpackm_16xk_ker_name GENARNAME(unpackm_16xk) #undef packm_2xk_1er_ker_name #define packm_2xk_1er_ker_name GENARNAME(packm_2xk_1er) #undef packm_4xk_1er_ker_name #define packm_4xk_1er_ker_name GENARNAME(packm_4xk_1er) #undef packm_6xk_1er_ker_name #define packm_6xk_1er_ker_name GENARNAME(packm_6xk_1er) #undef packm_8xk_1er_ker_name #define packm_8xk_1er_ker_name GENARNAME(packm_8xk_1er) #undef packm_10xk_1er_ker_name #define packm_10xk_1er_ker_name GENARNAME(packm_10xk_1er) #undef packm_12xk_1er_ker_name #define packm_12xk_1er_ker_name GENARNAME(packm_12xk_1er) #undef packm_14xk_1er_ker_name #define packm_14xk_1er_ker_name GENARNAME(packm_14xk_1er) #undef packm_16xk_1er_ker_name #define packm_16xk_1er_ker_name GENARNAME(packm_16xk_1er) // Instantiate prototypes for above functions via the level-1m kernel API // template. #include "bli_l1m_ker.h" // -- Level-1f kernel prototype redefinitions ---------------------------------- #undef axpy2v_ker_name #define axpy2v_ker_name GENARNAME(axpy2v) #undef dotaxpyv_ker_name #define dotaxpyv_ker_name GENARNAME(dotaxpyv) #undef axpyf_ker_name #define axpyf_ker_name GENARNAME(axpyf) #undef dotxf_ker_name #define dotxf_ker_name GENARNAME(dotxf) #undef dotxaxpyf_ker_name #define dotxaxpyf_ker_name GENARNAME(dotxaxpyf) // Instantiate prototypes for above functions via the level-1f kernel API // template. #include "bli_l1f_ker.h" // -- Level-1v kernel prototype redefinitions ---------------------------------- // -- prototypes for completely generic level-1v kernels -- #undef addv_ker_name #define addv_ker_name GENARNAME(addv) #undef amaxv_ker_name #define amaxv_ker_name GENARNAME(amaxv) #undef axpbyv_ker_name #define axpbyv_ker_name GENARNAME(axpbyv) #undef axpyv_ker_name #define axpyv_ker_name GENARNAME(axpyv) #undef copyv_ker_name #define copyv_ker_name GENARNAME(copyv) #undef dotv_ker_name #define dotv_ker_name GENARNAME(dotv) #undef dotxv_ker_name #define dotxv_ker_name GENARNAME(dotxv) #undef invertv_ker_name #define invertv_ker_name GENARNAME(invertv) #undef scalv_ker_name #define scalv_ker_name GENARNAME(scalv) #undef scal2v_ker_name #define scal2v_ker_name GENARNAME(scal2v) #undef setv_ker_name #define setv_ker_name GENARNAME(setv) #undef subv_ker_name #define subv_ker_name GENARNAME(subv) #undef swapv_ker_name #define swapv_ker_name GENARNAME(swapv) #undef xpbyv_ker_name #define xpbyv_ker_name GENARNAME(xpbyv) // Instantiate prototypes for above functions via the level-1v kernel API // template. #include "bli_l1v_ker.h" // -- Macros to help concisely instantiate bli_func_init() --------------------- #define gen_func_init_co( func_p, opname ) \ { \ bli_func_init( func_p, NULL, NULL, \ PASTEMAC(c,opname), PASTEMAC(z,opname) ); \ } #define gen_func_init( func_p, opname ) \ { \ bli_func_init( func_p, PASTEMAC(s,opname), PASTEMAC(d,opname), \ PASTEMAC(c,opname), PASTEMAC(z,opname) ); \ } #define gen_sup_func_init( func0_p, func1_p, opname ) \ { \ bli_func_init( func0_p, PASTEMAC(s,opname), PASTEMAC(d,opname), \ PASTEMAC(c,opname), PASTEMAC(z,opname) ); \ bli_func_init( func1_p, PASTEMAC(s,opname), PASTEMAC(d,opname), \ PASTEMAC(c,opname), PASTEMAC(z,opname) ); \ } // -- Helper function for 1m --------------------------------------------------- void GENBAINAME(cntx_init_blkszs) ( ind_t method, num_t dt, cntx_t* cntx ); // ----------------------------------------------------------------------------- void GENBARNAME(cntx_init) ( cntx_t* cntx ) { blksz_t blkszs[ BLIS_NUM_BLKSZS ]; blksz_t thresh[ BLIS_NUM_THRESH ]; func_t* funcs; mbool_t* mbools; dim_t i; void** vfuncs; // -- Clear the context ---------------------------------------------------- bli_cntx_clear( cntx ); // -- Set blocksizes ------------------------------------------------------- // s d c z bli_blksz_init_easy( &blkszs[ BLIS_KR ], 1, 1, 1, 1 ); bli_blksz_init_easy( &blkszs[ BLIS_MR ], 4, 4, 4, 4 ); bli_blksz_init_easy( &blkszs[ BLIS_NR ], 16, 8, 8, 4 ); bli_blksz_init_easy( &blkszs[ BLIS_MC ], 256, 128, 128, 64 ); bli_blksz_init_easy( &blkszs[ BLIS_KC ], 256, 256, 256, 256 ); bli_blksz_init_easy( &blkszs[ BLIS_NC ], 4096, 4096, 4096, 4096 ); bli_blksz_init_easy( &blkszs[ BLIS_M2 ], 1000, 1000, 1000, 1000 ); bli_blksz_init_easy( &blkszs[ BLIS_N2 ], 1000, 1000, 1000, 1000 ); bli_blksz_init_easy( &blkszs[ BLIS_AF ], 8, 8, 8, 8 ); bli_blksz_init_easy( &blkszs[ BLIS_DF ], 6, 6, 6, 6 ); bli_blksz_init_easy( &blkszs[ BLIS_XF ], 4, 4, 4, 4 ); // Initialize the context with the default blocksize objects and their // multiples. bli_cntx_set_blkszs ( BLIS_NAT, 11, BLIS_NC, &blkszs[ BLIS_NC ], BLIS_NR, BLIS_KC, &blkszs[ BLIS_KC ], BLIS_KR, BLIS_MC, &blkszs[ BLIS_MC ], BLIS_MR, BLIS_NR, &blkszs[ BLIS_NR ], BLIS_NR, BLIS_MR, &blkszs[ BLIS_MR ], BLIS_MR, BLIS_KR, &blkszs[ BLIS_KR ], BLIS_KR, BLIS_M2, &blkszs[ BLIS_M2 ], BLIS_M2, BLIS_N2, &blkszs[ BLIS_N2 ], BLIS_N2, BLIS_AF, &blkszs[ BLIS_AF ], BLIS_AF, BLIS_DF, &blkszs[ BLIS_DF ], BLIS_DF, BLIS_XF, &blkszs[ BLIS_XF ], BLIS_XF, cntx ); // -- Set level-3 virtual micro-kernels ------------------------------------ funcs = bli_cntx_l3_vir_ukrs_buf( cntx ); // NOTE: We set the virtual micro-kernel slots to contain the addresses // of the native micro-kernels. In general, the ukernels in the virtual // ukernel slots are always called, and if the function called happens to // be a virtual micro-kernel, it will then know to find its native ukernel // (i.e., in the native ukernel slots). gen_func_init( &funcs[ BLIS_GEMM_UKR ], gemm_ukr_name ); gen_func_init( &funcs[ BLIS_GEMMTRSM_L_UKR ], gemmtrsm_l_ukr_name ); gen_func_init( &funcs[ BLIS_GEMMTRSM_U_UKR ], gemmtrsm_u_ukr_name ); gen_func_init( &funcs[ BLIS_TRSM_L_UKR ], trsm_l_ukr_name ); gen_func_init( &funcs[ BLIS_TRSM_U_UKR ], trsm_u_ukr_name ); // -- Set level-3 native micro-kernels and preferences --------------------- funcs = bli_cntx_l3_nat_ukrs_buf( cntx ); mbools = bli_cntx_l3_nat_ukrs_prefs_buf( cntx ); gen_func_init( &funcs[ BLIS_GEMM_UKR ], gemm_ukr_name ); gen_func_init( &funcs[ BLIS_GEMMTRSM_L_UKR ], gemmtrsm_l_ukr_name ); gen_func_init( &funcs[ BLIS_GEMMTRSM_U_UKR ], gemmtrsm_u_ukr_name ); gen_func_init( &funcs[ BLIS_TRSM_L_UKR ], trsm_l_ukr_name ); gen_func_init( &funcs[ BLIS_TRSM_U_UKR ], trsm_u_ukr_name ); // s d c z bli_mbool_init( &mbools[ BLIS_GEMM_UKR ], TRUE, TRUE, TRUE, TRUE ); bli_mbool_init( &mbools[ BLIS_GEMMTRSM_L_UKR ], FALSE, FALSE, FALSE, FALSE ); bli_mbool_init( &mbools[ BLIS_GEMMTRSM_U_UKR ], FALSE, FALSE, FALSE, FALSE ); bli_mbool_init( &mbools[ BLIS_TRSM_L_UKR ], FALSE, FALSE, FALSE, FALSE ); bli_mbool_init( &mbools[ BLIS_TRSM_U_UKR ], FALSE, FALSE, FALSE, FALSE ); // -- Set level-3 small/unpacked thresholds -------------------------------- // NOTE: The default thresholds are set to zero so that the sup framework // does not activate by default. Note that the semantic meaning of the // thresholds is that the sup code path is executed if a dimension is // strictly less than its corresponding threshold. So actually, the // thresholds specify the minimum dimension size that will still dispatch // the non-sup/large code path. This "strictly less than" behavior was // chosen over "less than or equal to" so that threshold values of 0 would // effectively disable sup (even for matrix dimensions of 0). // s d c z bli_blksz_init_easy( &thresh[ BLIS_MT ], 0, 0, 0, 0 ); bli_blksz_init_easy( &thresh[ BLIS_NT ], 0, 0, 0, 0 ); bli_blksz_init_easy( &thresh[ BLIS_KT ], 0, 0, 0, 0 ); // Initialize the context with the default thresholds. bli_cntx_set_l3_sup_thresh ( 3, BLIS_MT, &thresh[ BLIS_MT ], BLIS_NT, &thresh[ BLIS_NT ], BLIS_KT, &thresh[ BLIS_KT ], cntx ); // -- Set level-3 small/unpacked handlers ---------------------------------- vfuncs = bli_cntx_l3_sup_handlers_buf( cntx ); // Initialize all of the function pointers to NULL; for ( i = 0; i < BLIS_NUM_LEVEL3_OPS; ++i ) vfuncs[ i ] = NULL; // The level-3 sup handlers are oapi-based, so we only set one slot per // operation. // Set the gemm slot to the default gemm sup handler. vfuncs[ BLIS_GEMM ] = bli_gemmsup_ref; vfuncs[ BLIS_GEMMT ] = bli_gemmtsup_ref; // -- Set level-3 small/unpacked micro-kernels and preferences ------------- funcs = bli_cntx_l3_sup_kers_buf( cntx ); mbools = bli_cntx_l3_sup_kers_prefs_buf( cntx ); #if 0 // Adhere to the small/unpacked ukernel mappings: // - rv -> rrr, rcr // - rg -> rrc, rcc // - cv -> ccr, ccc // - cg -> crr, crc gen_sup_func_init( &funcs[ BLIS_RRR ], &funcs[ BLIS_RCR ], gemmsup_rv_ukr_name ); gen_sup_func_init( &funcs[ BLIS_RRC ], &funcs[ BLIS_RCC ], gemmsup_rg_ukr_name ); gen_sup_func_init( &funcs[ BLIS_CCR ], &funcs[ BLIS_CCC ], gemmsup_cv_ukr_name ); gen_sup_func_init( &funcs[ BLIS_CRR ], &funcs[ BLIS_CRC ], gemmsup_cg_ukr_name ); #endif gen_func_init( &funcs[ BLIS_RRR ], gemmsup_rv_ukr_name ); gen_func_init( &funcs[ BLIS_RRC ], gemmsup_rv_ukr_name ); gen_func_init( &funcs[ BLIS_RCR ], gemmsup_rv_ukr_name ); gen_func_init( &funcs[ BLIS_RCC ], gemmsup_rv_ukr_name ); gen_func_init( &funcs[ BLIS_CRR ], gemmsup_rv_ukr_name ); gen_func_init( &funcs[ BLIS_CRC ], gemmsup_rv_ukr_name ); gen_func_init( &funcs[ BLIS_CCR ], gemmsup_rv_ukr_name ); gen_func_init( &funcs[ BLIS_CCC ], gemmsup_rv_ukr_name ); // Register the general-stride/generic ukernel to the "catch-all" slot // associated with the BLIS_XXX enum value. This slot will be queried if // *any* operand is stored with general stride. gen_func_init( &funcs[ BLIS_XXX ], gemmsup_gx_ukr_name ); // Set the l3 sup ukernel storage preferences. // s d c z bli_mbool_init( &mbools[ BLIS_RRR ], TRUE, TRUE, TRUE, TRUE ); bli_mbool_init( &mbools[ BLIS_RRC ], TRUE, TRUE, TRUE, TRUE ); bli_mbool_init( &mbools[ BLIS_RCR ], TRUE, TRUE, TRUE, TRUE ); bli_mbool_init( &mbools[ BLIS_RCC ], TRUE, TRUE, TRUE, TRUE ); bli_mbool_init( &mbools[ BLIS_CRR ], TRUE, TRUE, TRUE, TRUE ); bli_mbool_init( &mbools[ BLIS_CRC ], TRUE, TRUE, TRUE, TRUE ); bli_mbool_init( &mbools[ BLIS_CCR ], TRUE, TRUE, TRUE, TRUE ); bli_mbool_init( &mbools[ BLIS_CCC ], TRUE, TRUE, TRUE, TRUE ); bli_mbool_init( &mbools[ BLIS_XXX ], TRUE, TRUE, TRUE, TRUE ); // -- Set level-1f kernels ------------------------------------------------- funcs = bli_cntx_l1f_kers_buf( cntx ); gen_func_init( &funcs[ BLIS_AXPY2V_KER ], axpy2v_ker_name ); gen_func_init( &funcs[ BLIS_DOTAXPYV_KER ], dotaxpyv_ker_name ); gen_func_init( &funcs[ BLIS_AXPYF_KER ], axpyf_ker_name ); gen_func_init( &funcs[ BLIS_DOTXF_KER ], dotxf_ker_name ); gen_func_init( &funcs[ BLIS_DOTXAXPYF_KER ], dotxaxpyf_ker_name ); // -- Set level-1v kernels ------------------------------------------------- funcs = bli_cntx_l1v_kers_buf( cntx ); gen_func_init( &funcs[ BLIS_ADDV_KER ], addv_ker_name ); gen_func_init( &funcs[ BLIS_AMAXV_KER ], amaxv_ker_name ); gen_func_init( &funcs[ BLIS_AXPBYV_KER ], axpbyv_ker_name ); gen_func_init( &funcs[ BLIS_AXPYV_KER ], axpyv_ker_name ); gen_func_init( &funcs[ BLIS_COPYV_KER ], copyv_ker_name ); gen_func_init( &funcs[ BLIS_DOTV_KER ], dotv_ker_name ); gen_func_init( &funcs[ BLIS_DOTXV_KER ], dotxv_ker_name ); gen_func_init( &funcs[ BLIS_INVERTV_KER ], invertv_ker_name ); gen_func_init( &funcs[ BLIS_SCALV_KER ], scalv_ker_name ); gen_func_init( &funcs[ BLIS_SCAL2V_KER ], scal2v_ker_name ); gen_func_init( &funcs[ BLIS_SETV_KER ], setv_ker_name ); gen_func_init( &funcs[ BLIS_SUBV_KER ], subv_ker_name ); gen_func_init( &funcs[ BLIS_SWAPV_KER ], swapv_ker_name ); gen_func_init( &funcs[ BLIS_XPBYV_KER ], xpbyv_ker_name ); // -- Set level-1m (packm/unpackm) kernels --------------------------------- funcs = bli_cntx_packm_kers_buf( cntx ); // Initialize all packm kernel func_t entries to NULL. for ( i = BLIS_PACKM_0XK_KER; i <= BLIS_PACKM_31XK_KER; ++i ) { bli_func_init_null( &funcs[ i ] ); } gen_func_init( &funcs[ BLIS_PACKM_2XK_KER ], packm_2xk_ker_name ); gen_func_init( &funcs[ BLIS_PACKM_3XK_KER ], packm_3xk_ker_name ); gen_func_init( &funcs[ BLIS_PACKM_4XK_KER ], packm_4xk_ker_name ); gen_func_init( &funcs[ BLIS_PACKM_6XK_KER ], packm_6xk_ker_name ); gen_func_init( &funcs[ BLIS_PACKM_8XK_KER ], packm_8xk_ker_name ); gen_func_init( &funcs[ BLIS_PACKM_10XK_KER ], packm_10xk_ker_name ); gen_func_init( &funcs[ BLIS_PACKM_12XK_KER ], packm_12xk_ker_name ); gen_func_init( &funcs[ BLIS_PACKM_14XK_KER ], packm_14xk_ker_name ); gen_func_init( &funcs[ BLIS_PACKM_16XK_KER ], packm_16xk_ker_name ); gen_func_init( &funcs[ BLIS_PACKM_24XK_KER ], packm_24xk_ker_name ); funcs = bli_cntx_unpackm_kers_buf( cntx ); // Initialize all packm kernel func_t entries to NULL. for ( i = BLIS_UNPACKM_0XK_KER; i <= BLIS_UNPACKM_31XK_KER; ++i ) { bli_func_init_null( &funcs[ i ] ); } gen_func_init( &funcs[ BLIS_UNPACKM_2XK_KER ], unpackm_2xk_ker_name ); gen_func_init( &funcs[ BLIS_UNPACKM_4XK_KER ], unpackm_4xk_ker_name ); gen_func_init( &funcs[ BLIS_UNPACKM_6XK_KER ], unpackm_6xk_ker_name ); gen_func_init( &funcs[ BLIS_UNPACKM_8XK_KER ], unpackm_8xk_ker_name ); gen_func_init( &funcs[ BLIS_UNPACKM_10XK_KER ], unpackm_10xk_ker_name ); gen_func_init( &funcs[ BLIS_UNPACKM_12XK_KER ], unpackm_12xk_ker_name ); gen_func_init( &funcs[ BLIS_UNPACKM_14XK_KER ], unpackm_14xk_ker_name ); gen_func_init( &funcs[ BLIS_UNPACKM_16XK_KER ], unpackm_16xk_ker_name ); // -- Set miscellaneous fields --------------------------------------------- bli_cntx_set_method( BLIS_NAT, cntx ); } // ----------------------------------------------------------------------------- void GENBAINAME(cntx_init) ( ind_t method, cntx_t* cntx ) { func_t* funcs; dim_t i; // This function is designed to modify a copy of an existing native // context to enable computation via an induced method for complex // domain level-3 operations. It is called by bli_gks_query_ind_cntx() // on a context after its contexts are set by copying from the // architecture's native context. // -- Set induced method level-3 virtual micro-kernels --------------------- funcs = bli_cntx_l3_vir_ukrs_buf( cntx ); if ( method == BLIS_1M ) { gen_func_init_co( &funcs[ BLIS_GEMM_UKR ], gemm1m_ukr_name ); gen_func_init_co( &funcs[ BLIS_GEMMTRSM_L_UKR ], gemmtrsm1m_l_ukr_name ); gen_func_init_co( &funcs[ BLIS_GEMMTRSM_U_UKR ], gemmtrsm1m_u_ukr_name ); gen_func_init_co( &funcs[ BLIS_TRSM_L_UKR ], trsm1m_l_ukr_name ); gen_func_init_co( &funcs[ BLIS_TRSM_U_UKR ], trsm1m_u_ukr_name ); } else // if ( method == BLIS_NAT ) { gen_func_init_co( &funcs[ BLIS_GEMM_UKR ], gemm_ukr_name ); gen_func_init_co( &funcs[ BLIS_GEMMTRSM_L_UKR ], gemmtrsm_l_ukr_name ); gen_func_init_co( &funcs[ BLIS_GEMMTRSM_U_UKR ], gemmtrsm_u_ukr_name ); gen_func_init_co( &funcs[ BLIS_TRSM_L_UKR ], trsm_l_ukr_name ); gen_func_init_co( &funcs[ BLIS_TRSM_U_UKR ], trsm_u_ukr_name ); } // For 1m, we employ an optimization which requires that we copy the native // real domain gemm ukernel function pointers to the corresponding real // domain slots in the virtual gemm ukernel func_t. This optimization allows // us to, under certain conditions, adjust various parameters within the gemm // macrokernel so that the real-domain macrokernel (which will query and use // the real-domain virtual gemm ukernel) can be called instead of calling the // complex-domain macrokernel and the corresponding complex-domain virtual // microkernel. The non-optimized code path would require an extra level of // function call overhead, which can be avoided in most cases (i.e., when // beta has a zero imaginary component and C is either row- or column-stored). if ( method == BLIS_1M ) { func_t* gemm_nat_ukrs = bli_cntx_get_l3_nat_ukrs( BLIS_GEMM_UKR, cntx ); func_t* gemm_vir_ukrs = bli_cntx_get_l3_vir_ukrs( BLIS_GEMM_UKR, cntx ); bli_func_copy_dt( BLIS_FLOAT, gemm_nat_ukrs, BLIS_FLOAT, gemm_vir_ukrs ); bli_func_copy_dt( BLIS_DOUBLE, gemm_nat_ukrs, BLIS_DOUBLE, gemm_vir_ukrs ); } // -- Set induced method packm kernels ------------------------------------- funcs = bli_cntx_packm_kers_buf( cntx ); // Initialize all packm kernel func_t entries to NULL. for ( i = BLIS_PACKM_0XK_KER; i <= BLIS_PACKM_31XK_KER; ++i ) { bli_func_init_null( &funcs[ i ] ); } if ( method == BLIS_1M ) { gen_func_init_co( &funcs[ BLIS_PACKM_2XK_KER ], packm_2xk_1er_ker_name ); gen_func_init_co( &funcs[ BLIS_PACKM_4XK_KER ], packm_4xk_1er_ker_name ); gen_func_init_co( &funcs[ BLIS_PACKM_6XK_KER ], packm_6xk_1er_ker_name ); gen_func_init_co( &funcs[ BLIS_PACKM_8XK_KER ], packm_8xk_1er_ker_name ); gen_func_init_co( &funcs[ BLIS_PACKM_10XK_KER ], packm_10xk_1er_ker_name ); gen_func_init_co( &funcs[ BLIS_PACKM_12XK_KER ], packm_12xk_1er_ker_name ); gen_func_init_co( &funcs[ BLIS_PACKM_14XK_KER ], packm_14xk_1er_ker_name ); gen_func_init_co( &funcs[ BLIS_PACKM_16XK_KER ], packm_16xk_1er_ker_name ); } else // if ( method == BLIS_NAT ) { gen_func_init( &funcs[ BLIS_PACKM_2XK_KER ], packm_2xk_ker_name ); gen_func_init( &funcs[ BLIS_PACKM_3XK_KER ], packm_3xk_ker_name ); gen_func_init( &funcs[ BLIS_PACKM_4XK_KER ], packm_4xk_ker_name ); gen_func_init( &funcs[ BLIS_PACKM_6XK_KER ], packm_6xk_ker_name ); gen_func_init( &funcs[ BLIS_PACKM_8XK_KER ], packm_8xk_ker_name ); gen_func_init( &funcs[ BLIS_PACKM_10XK_KER ], packm_10xk_ker_name ); gen_func_init( &funcs[ BLIS_PACKM_12XK_KER ], packm_12xk_ker_name ); gen_func_init( &funcs[ BLIS_PACKM_14XK_KER ], packm_14xk_ker_name ); gen_func_init( &funcs[ BLIS_PACKM_16XK_KER ], packm_16xk_ker_name ); gen_func_init( &funcs[ BLIS_PACKM_24XK_KER ], packm_24xk_ker_name ); } // -- Set induced method cache and register blocksizes --------------------- // Modify the context with cache and register blocksizes (and multiples) // appropriate for the current induced method. if ( method == BLIS_1M ) { //const bool is_pb = FALSE; // Call a helper function to initialize blocksizes for each complex // datatype. GENBAINAME(cntx_init_blkszs)( method, BLIS_SCOMPLEX, cntx ); GENBAINAME(cntx_init_blkszs)( method, BLIS_DCOMPLEX, cntx ); } else // if ( method == BLIS_NAT ) { // No change in blocksizes needed for native execution. } } // ----------------------------------------------------------------------------- void GENBAINAME(cntx_init_blkszs) ( ind_t method, num_t dt, cntx_t* cntx ) { // We MUST set the induced method in the context prior to calling // bli_cntx_l3_vir_ukr_prefers_cols_dt() because that function queries // the induced method. That function needs the induced method value in // order to determine whether to evaluate the "prefers column storage" // predicate using the storage preference of the kernel for dt, or // the storage preference of the kernel for the real projection of // dt. Failing to set the induced method here can lead to strange // undefined behavior at runtime if the native complex kernel's // storage preference happens to not equal that of the native real // kernel. bli_cntx_set_method( method, cntx ); // Initialize the blocksizes according to the micro-kernel preference as // well as the algorithm. if ( bli_cntx_l3_vir_ukr_prefers_cols_dt( dt, BLIS_GEMM_UKR, cntx ) ) { // This branch is used for algorithm 1m_c_bp. bli_cntx_set_ind_blkszs ( method, dt, 6, BLIS_NC, 1.0, 1.0, BLIS_KC, 2.0, 2.0, // halve kc... BLIS_MC, 2.0, 2.0, // halve mc... BLIS_NR, 1.0, 1.0, BLIS_MR, 2.0, 1.0, // ...and mr (but NOT packmr) BLIS_KR, 1.0, 1.0, cntx ); } else // if ( bli_cntx_l3_vir_ukr_prefers_rows_dt( dt, BLIS_GEMM_UKR, cntx ) ) { // This branch is used for algorithm 1m_r_bp. bli_cntx_set_ind_blkszs ( method, dt, 6, BLIS_NC, 2.0, 2.0, // halve nc... BLIS_KC, 2.0, 2.0, // halve kc... BLIS_MC, 1.0, 1.0, BLIS_NR, 2.0, 1.0, // ...and nr (but NOT packnr) BLIS_MR, 1.0, 1.0, BLIS_KR, 1.0, 1.0, cntx ); } } blis-0.9.0/ref_kernels/ind/000077500000000000000000000000001422157504600155305ustar00rootroot00000000000000blis-0.9.0/ref_kernels/ind/bli_gemm1m_ref.c000066400000000000000000000213671422157504600205520ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENTFUNCCO #define GENTFUNCCO( ctype, ctype_r, ch, chr, opname, arch, suf ) \ \ void PASTEMAC3(ch,opname,arch,suf) \ ( \ dim_t m, \ dim_t n, \ dim_t k, \ ctype* restrict alpha, \ ctype* restrict a, \ ctype* restrict b, \ ctype* restrict beta, \ ctype* restrict c, inc_t rs_c, inc_t cs_c, \ auxinfo_t* restrict data, \ cntx_t* restrict cntx \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ const num_t dt_r = PASTEMAC(chr,type); \ \ PASTECH(chr,gemm_ukr_ft) \ rgemm_ukr = bli_cntx_get_l3_nat_ukr_dt( dt_r, BLIS_GEMM_UKR, cntx ); \ const bool col_pref = bli_cntx_l3_nat_ukr_prefers_cols_dt( dt_r, BLIS_GEMM_UKR, cntx ); \ const bool row_pref = !col_pref; \ \ const dim_t mr = bli_cntx_get_blksz_def_dt( dt, BLIS_MR, cntx ); \ const dim_t nr = bli_cntx_get_blksz_def_dt( dt, BLIS_NR, cntx ); \ \ const dim_t mr_r = bli_cntx_get_blksz_def_dt( dt_r, BLIS_MR, cntx ); \ const dim_t nr_r = bli_cntx_get_blksz_def_dt( dt_r, BLIS_NR, cntx ); \ \ const dim_t k2 = 2 * k; \ \ ctype ct[ BLIS_STACK_BUF_MAX_SIZE \ / sizeof( ctype_r ) ] \ __attribute__((aligned(BLIS_STACK_BUF_ALIGN_SIZE))); \ inc_t rs_ct; \ inc_t cs_ct; \ \ ctype_r* restrict a_r = ( ctype_r* )a; \ \ ctype_r* restrict b_r = ( ctype_r* )b; \ \ ctype_r* restrict zero_r = PASTEMAC(chr,0); \ \ ctype_r* restrict alpha_r = &PASTEMAC(ch,real)( *alpha ); \ ctype_r* restrict alpha_i = &PASTEMAC(ch,imag)( *alpha ); \ \ ctype_r* restrict beta_r = &PASTEMAC(ch,real)( *beta ); \ ctype_r* restrict beta_i = &PASTEMAC(ch,imag)( *beta ); \ \ ctype_r* c_use; \ inc_t rs_c_use; \ inc_t cs_c_use; \ \ bool using_ct; \ \ /* PASTEMAC(chr,fprintm)( stdout, "gemm_ukr: a", mr, 2*k, \ a_r, 1, mr, "%5.2f", "" ); \ PASTEMAC(chr,fprintm)( stdout, "gemm_ukr: b", 2*k, 2*nr, \ b_r, 2*nr, 1, "%5.2f", "" ); \ PASTEMAC(chr,fprintm)( stdout, "gemm_ukr: c after", mr, 2*nr, \ c_use, rs_c_use, cs_c_use, "%5.2f", "" ); \ */ \ \ /* SAFETY CHECK: The higher level implementation should never allow an alpha with non-zero imaginary component to be passed in, because it can't be applied properly using the 1m method. If alpha is not real, then something is very wrong. */ \ if ( !PASTEMAC(chr,eq0)( *alpha_i ) ) \ bli_check_error_code( BLIS_NOT_YET_IMPLEMENTED ); \ \ \ /* If beta has a non-zero imaginary component OR if c is stored with general stride, then we compute the alpha*a*b product into temporary storage and then accumulate that result into c afterwards. Note that the other two cases concerning disagreement between the storage of C and the output preference of the micro-kernel, should ONLY occur in the context of trsm, whereby this virtual micro-kernel is called directly from the trsm macro-kernel to update the micro-tile b11 that exists within the packed row-panel of B. Indeed that is the reason those cases MUST be explicitly handled. */ \ if ( !PASTEMAC(chr,eq0)( *beta_i ) ) using_ct = TRUE; \ else if ( bli_is_col_stored( rs_c, cs_c ) && row_pref ) using_ct = TRUE; \ else if ( bli_is_row_stored( rs_c, cs_c ) && col_pref ) using_ct = TRUE; \ else if ( bli_is_gen_stored( rs_c, cs_c ) ) using_ct = TRUE; \ else using_ct = FALSE; \ \ \ /* If we are not computing a full micro-tile, then we must write to ct and then accumulate to c afterwards. */ \ if ( mr != m || nr != n ) using_ct = TRUE; \ \ \ if ( using_ct ) \ { \ /* In the atypical cases, we compute the result into temporary workspace ct and then accumulated it back to c at the end. */ \ \ /* Set the strides of ct based on the preference of the underlying native real domain gemm micro-kernel. Note that we set the ct strides in units of complex elements. */ \ if ( col_pref ) { rs_ct = 1; cs_ct = mr; } \ else { rs_ct = nr; cs_ct = 1; } \ \ c_use = ( ctype_r* )ct; \ rs_c_use = rs_ct; \ cs_c_use = cs_ct; \ \ /* Convert the strides from being in units of complex elements to be in units of real elements. Note that we don't need to check for general storage here because that case corresponds to the scenario where we are using the ct buffer and its rs_ct/cs_ct strides. */ \ if ( bli_is_col_stored( rs_c_use, cs_c_use ) ) cs_c_use *= 2; \ else rs_c_use *= 2; \ \ /* The following gemm micro-kernel call implements the 1m method, which induces a complex matrix multiplication by calling the real matrix micro-kernel on micro-panels that have been packed according to the 1e and 1r formats. */ \ \ /* c = beta * c + alpha_r * a * b; */ \ rgemm_ukr \ ( \ mr_r, \ nr_r, \ k2, \ alpha_r, \ a_r, \ b_r, \ zero_r, \ c_use, rs_c_use, cs_c_use, \ data, \ cntx \ ); \ \ dim_t i, j; \ \ /* Accumulate the final result in ct back to c. */ \ if ( PASTEMAC(ch,eq1)( *beta ) ) \ { \ for ( j = 0; j < n; ++j ) \ for ( i = 0; i < m; ++i ) \ { \ PASTEMAC(ch,adds)( *(ct + i*rs_ct + j*cs_ct), \ *(c + i*rs_c + j*cs_c ) ); \ } \ } \ else if ( PASTEMAC(ch,eq0)( *beta ) ) \ { \ for ( j = 0; j < n; ++j ) \ for ( i = 0; i < m; ++i ) \ { \ PASTEMAC(ch,copys)( *(ct + i*rs_ct + j*cs_ct), \ *(c + i*rs_c + j*cs_c ) ); \ } \ } \ else \ { \ for ( j = 0; j < n; ++j ) \ for ( i = 0; i < m; ++i ) \ { \ PASTEMAC(ch,xpbys)( *(ct + i*rs_ct + j*cs_ct), \ *beta, \ *(c + i*rs_c + j*cs_c ) ); \ } \ } \ } \ else \ { \ /* In the typical cases, we use the real part of beta and accumulate directly into the output matrix c. */ \ \ c_use = ( ctype_r* )c; \ rs_c_use = rs_c; \ cs_c_use = cs_c; \ \ /* Convert the strides from being in units of complex elements to be in units of real elements. Note that we don't need to check for general storage here because that case corresponds to the scenario where we are using the ct buffer and its rs_ct/cs_ct strides. */ \ if ( bli_is_col_stored( rs_c_use, cs_c_use ) ) cs_c_use *= 2; \ else rs_c_use *= 2; \ \ /* The following gemm micro-kernel call implements the 1m method, which induces a complex matrix multiplication by calling the real matrix micro-kernel on micro-panels that have been packed according to the 1e and 1r formats. */ \ \ /* c = beta * c + alpha_r * a * b; */ \ rgemm_ukr \ ( \ mr_r, \ nr_r, \ k2, \ alpha_r, \ a_r, \ b_r, \ beta_r, \ c_use, rs_c_use, cs_c_use, \ data, \ cntx \ ); \ } \ } INSERT_GENTFUNCCO_BASIC2( gemm1m, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX ) blis-0.9.0/ref_kernels/ind/bli_gemmtrsm1m_ref.c000066400000000000000000000214721422157504600214550ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENTFUNCCO #define GENTFUNCCO( ctype, ctype_r, ch, chr, opname, arch, suf, trsmkerid ) \ \ void PASTEMAC3(ch,opname,arch,suf) \ ( \ dim_t m, \ dim_t n, \ dim_t k, \ ctype* restrict alpha, \ ctype* restrict a1x, \ ctype* restrict a11, \ ctype* restrict bx1, \ ctype* restrict b11, \ ctype* restrict c11, inc_t rs_c, inc_t cs_c, \ auxinfo_t* restrict data, \ cntx_t* restrict cntx \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ const num_t dt_r = PASTEMAC(chr,type); \ \ PASTECH(chr,gemm_ukr_ft) \ rgemm_ukr = bli_cntx_get_l3_nat_ukr_dt( dt_r, BLIS_GEMM_UKR, cntx ); \ \ PASTECH(ch,trsm_ukr_ft) \ ctrsm_vir_ukr = bli_cntx_get_l3_vir_ukr_dt( dt, trsmkerid, cntx ); \ \ const bool col_pref_r = bli_cntx_l3_nat_ukr_prefers_cols_dt( dt_r, BLIS_GEMM_UKR, cntx ); \ \ const dim_t mr = bli_cntx_get_blksz_def_dt( dt, BLIS_MR, cntx ); \ const dim_t nr = bli_cntx_get_blksz_def_dt( dt, BLIS_NR, cntx ); \ \ const dim_t mr_r = bli_cntx_get_blksz_def_dt( dt_r, BLIS_MR, cntx ); \ const dim_t nr_r = bli_cntx_get_blksz_def_dt( dt_r, BLIS_NR, cntx ); \ \ ctype bt[ BLIS_STACK_BUF_MAX_SIZE \ / sizeof( ctype ) ] \ __attribute__((aligned(BLIS_STACK_BUF_ALIGN_SIZE))); \ inc_t rs_bt; \ inc_t cs_bt; \ \ inc_t rs_bt_r; \ inc_t cs_bt_r; \ \ const dim_t packnr = bli_cntx_get_blksz_max_dt( dt, BLIS_NR, cntx ); \ \ const pack_t schema_b = bli_auxinfo_schema_b( data ); \ \ const dim_t k2 = 2 * k; \ \ ctype_r* restrict a1x_r = ( ctype_r* )a1x; \ \ ctype_r* restrict bx1_r = ( ctype_r* )bx1; \ \ const inc_t rs_b = packnr; \ const inc_t cs_b = 1; \ \ ctype_r* restrict zero_r = PASTEMAC(chr,0); \ ctype_r* restrict minus_one_r = PASTEMAC(chr,m1); \ \ const ctype_r alpha_r = PASTEMAC(ch,real)( *alpha ); \ const ctype_r alpha_i = PASTEMAC(ch,imag)( *alpha ); \ \ ctype_r* b_use; \ inc_t rs_b_use; \ inc_t cs_b_use; \ \ ctype ct[ BLIS_STACK_BUF_MAX_SIZE \ / sizeof( ctype ) ] \ __attribute__((aligned(BLIS_STACK_BUF_ALIGN_SIZE))); \ /* FGVZ: Should we be querying the preference of BLIS_GEMMTRSM_?_UKR instead? */ \ const bool col_pref = bli_cntx_l3_vir_ukr_prefers_cols_dt( dt, BLIS_GEMM_UKR, cntx ); \ const inc_t rs_ct = ( col_pref ? 1 : nr ); \ const inc_t cs_ct = ( col_pref ? mr : 1 ); \ \ const bool use_ct = ( m < mr || n < nr ); \ \ ctype* restrict c11_use = c11; \ inc_t rs_c_use = rs_c; \ inc_t cs_c_use = cs_c; \ \ if ( use_ct ) \ { \ c11_use = ct; \ rs_c_use = rs_ct; \ cs_c_use = cs_ct; \ } \ \ \ /* Handle alphas with non-zero imaginary components. */ \ /* NOTE: This branch should never execute because alphas with non-zero imaginary components should be applied during packing, and so the only alphas we should see here are those exclusively in the real domain, either because the value originally had no imaginary compoent (e.g. 4.0) or because a 1.0 was sent in as a placeholder since the alpha was applied during packing. */ \ if ( 0 ) \ if ( !PASTEMAC(chr,eq0)( alpha_i ) ) \ { \ bli_abort(); \ \ /* ctype_r* restrict one_r = PASTEMAC(chr,1); \ \ const inc_t ld_b = rs_b; \ \ PASTEMAC(ch,scal1ms_mxn)( schema_b, \ mr, \ nr, \ alpha, \ b11, rs_b, cs_b, ld_b ); \ \ alpha_r = *one_r; \ */ \ } \ \ \ { \ /* Set the strides for the temporary bt matrix based on the native real domain micro-kernel storage preferences. */ \ if ( col_pref_r ) { rs_bt = 1; cs_bt = mr; \ rs_bt_r = 1; cs_bt_r = mr_r; } \ else { rs_bt = nr; cs_bt = 1; \ rs_bt_r = nr_r; cs_bt_r = 1; } \ \ b_use = ( ctype_r* )bt; \ rs_b_use = rs_bt_r; \ cs_b_use = cs_bt_r; \ } \ \ \ /* Since b11 is stored in the 1e or 1r schema, we cannot update it directly, and instead must compute the matrix product in a local temporary microtile and then accumulate it into b11 according to its schema. */ \ \ \ /* lower: bt = -1.0 * a10 * b01; upper: bt = -1.0 * a12 * b21; */ \ rgemm_ukr \ ( \ mr_r, \ nr_r, \ k2, \ minus_one_r, \ a1x_r, \ bx1_r, \ zero_r, \ b_use, rs_b_use, cs_b_use, \ data, \ cntx \ ); \ \ \ if ( bli_is_1e_packed( schema_b ) ) \ { \ const inc_t ld_b = rs_b; \ \ ctype* restrict b11_ri = ( ctype* )b11; \ ctype* restrict b11_ir = ( ctype* )b11 + ld_b/2; \ \ dim_t i, j; \ \ /* b11 = alpha * b11 + bt; */ \ for ( j = 0; j < nr; ++j ) \ for ( i = 0; i < mr; ++i ) \ { \ ctype* restrict beta11t = bt + i*rs_bt + j*cs_bt; \ ctype_r* restrict beta11t_r = &PASTEMAC(ch,real)( *beta11t ); \ ctype_r* restrict beta11t_i = &PASTEMAC(ch,imag)( *beta11t ); \ ctype* restrict beta11_ri = b11_ri + i*rs_b + j*cs_b; \ ctype_r* restrict beta11_r = &PASTEMAC(ch,real)( *beta11_ri ); \ ctype_r* restrict beta11_i = &PASTEMAC(ch,imag)( *beta11_ri ); \ ctype* restrict beta11_ir = b11_ir + i*rs_b + j*cs_b; \ \ PASTEMAC3(ch,chr,ch,xpbyris) \ ( \ *beta11t_r, \ *beta11t_i, \ alpha_r, \ alpha_i, /* alpha_i not referenced */ \ *beta11_r, \ *beta11_i \ ); \ \ PASTEMAC(ch,sets)( -*beta11_i, \ *beta11_r, *beta11_ir ); \ } \ } \ else /* if ( bli_is_1r_packed( schema_b ) ) */ \ { \ const inc_t ld_b = rs_b; \ const inc_t rs_b2 = 2 * rs_b; \ const inc_t cs_b2 = cs_b; \ \ ctype_r* restrict b11_r = ( ctype_r* )b11; \ ctype_r* restrict b11_i = ( ctype_r* )b11 + ld_b; \ \ dim_t i, j; \ \ /* b11 = alpha * b11 + bt; */ \ for ( j = 0; j < nr; ++j ) \ for ( i = 0; i < mr; ++i ) \ { \ ctype* restrict beta11t = bt + i*rs_bt + j*cs_bt; \ ctype_r* restrict beta11t_r = &PASTEMAC(ch,real)( *beta11t ); \ ctype_r* restrict beta11t_i = &PASTEMAC(ch,imag)( *beta11t ); \ ctype_r* restrict beta11_r = b11_r + i*rs_b2 + j*cs_b2; \ ctype_r* restrict beta11_i = b11_i + i*rs_b2 + j*cs_b2; \ \ PASTEMAC3(ch,chr,ch,xpbyris) \ ( \ *beta11t_r, \ *beta11t_i, \ alpha_r, \ alpha_i, /* alpha_i not referenced */ \ *beta11_r, \ *beta11_i \ ); \ } \ } \ \ \ /* b11 = inv(a11) * b11; c11 = b11; */ \ ctrsm_vir_ukr \ ( \ a11, \ b11, \ c11_use, rs_c_use, cs_c_use, \ data, \ cntx \ ); \ \ if ( use_ct ) \ { \ PASTEMAC(ch,copys_mxn) \ ( \ m, n, \ ct, rs_ct, cs_ct, \ c11, rs_c, cs_c \ ); \ } \ } INSERT_GENTFUNCCO_BASIC3( gemmtrsm1m_l, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX, BLIS_TRSM_L_UKR ) INSERT_GENTFUNCCO_BASIC3( gemmtrsm1m_u, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX, BLIS_TRSM_U_UKR ) blis-0.9.0/ref_kernels/ind/bli_trsm1m_ref.c000066400000000000000000000417041422157504600206070ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENTFUNCCO #define GENTFUNCCO( ctype, ctype_r, ch, chr, opname, arch, suf, diagop ) \ \ void PASTEMAC3(ch,opname,arch,suf) \ ( \ ctype* restrict a, \ ctype* restrict b, \ ctype* restrict c, inc_t rs_c, inc_t cs_c, \ auxinfo_t* restrict data, \ cntx_t* restrict cntx \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ const dim_t mr = bli_cntx_get_blksz_def_dt( dt, BLIS_MR, cntx ); \ const dim_t nr = bli_cntx_get_blksz_def_dt( dt, BLIS_NR, cntx ); \ \ const inc_t packmr = bli_cntx_get_blksz_max_dt( dt, BLIS_MR, cntx ); \ const inc_t packnr = bli_cntx_get_blksz_max_dt( dt, BLIS_NR, cntx ); \ \ const dim_t m = mr; \ const dim_t n = nr; \ \ const inc_t rs_a = 1; \ const inc_t cs_a = packmr; \ \ const inc_t rs_b = packnr; \ const inc_t cs_b = 1; \ \ const inc_t ld_a = cs_a; \ const inc_t ld_b = rs_b; \ \ const pack_t schema_b = bli_auxinfo_schema_b( data ); \ \ dim_t iter, i, j, l; \ dim_t n_behind; \ \ \ if ( bli_is_1e_packed( schema_b ) ) \ { \ const inc_t rs_a2 = 1 * rs_a; \ const inc_t cs_a2 = 2 * cs_a; \ \ ctype_r* restrict a_r = ( ctype_r* )a; \ ctype_r* restrict a_i = ( ctype_r* )a + ld_a; \ \ ctype* restrict b_ri = ( ctype* )b; \ ctype* restrict b_ir = ( ctype* )b + ld_b/2; \ \ for ( iter = 0; iter < m; ++iter ) \ { \ i = iter; \ n_behind = i; \ \ ctype_r* restrict alpha11_r = a_r + (i )*rs_a2 + (i )*cs_a2; \ ctype_r* restrict alpha11_i = a_i + (i )*rs_a2 + (i )*cs_a2; \ ctype_r* restrict a10t_r = a_r + (i )*rs_a2 + (0 )*cs_a2; \ ctype_r* restrict a10t_i = a_i + (i )*rs_a2 + (0 )*cs_a2; \ ctype* restrict b1_ri = b_ri + (i )*rs_b + (0 )*cs_b; \ ctype* restrict b1_ir = b_ir + (i )*rs_b + (0 )*cs_b; \ ctype* restrict B0_ri = b_ri + (0 )*rs_b + (0 )*cs_b; \ \ /* b1 = b1 - a10t * B0; */ \ /* b1 = b1 / alpha11; */ \ for ( j = 0; j < n; ++j ) \ { \ ctype* restrict beta11_ri = b1_ri + (0 )*rs_b + (j )*cs_b; \ ctype* restrict beta11_ir = b1_ir + (0 )*rs_b + (j )*cs_b; \ ctype* restrict b01_ri = B0_ri + (0 )*rs_b + (j )*cs_b; \ ctype* restrict gamma11 = c + (i )*rs_c + (j )*cs_c; \ ctype_r beta11c_r = PASTEMAC(ch,real)( *beta11_ri ); \ ctype_r beta11c_i = PASTEMAC(ch,imag)( *beta11_ri ); \ ctype_r rho11_r; \ ctype_r rho11_i; \ \ /* beta11 = beta11 - a10t * b01; */ \ PASTEMAC(ch,set0ris)( rho11_r, \ rho11_i ); \ for ( l = 0; l < n_behind; ++l ) \ { \ ctype_r* restrict alpha10_r = a10t_r + (l )*cs_a2; \ ctype_r* restrict alpha10_i = a10t_i + (l )*cs_a2; \ ctype* restrict beta01_ri = b01_ri + (l )*rs_b; \ ctype_r* restrict beta01_r = &PASTEMAC(ch,real)( *beta01_ri ); \ ctype_r* restrict beta01_i = &PASTEMAC(ch,imag)( *beta01_ri ); \ \ PASTEMAC(ch,axpyris)( *alpha10_r, \ *alpha10_i, \ *beta01_r, \ *beta01_i, \ rho11_r, \ rho11_i ); \ } \ PASTEMAC(ch,subris)( rho11_r, \ rho11_i, \ beta11c_r, \ beta11c_i ); \ \ /* beta11 = beta11 / alpha11; */ \ /* NOTE: When preinversion is enabled, the INVERSE of alpha11 (1.0/alpha11) is stored during packing instead alpha11 so we can multiply rather than divide. When preinversion is disabled, alpha11 is stored and division happens below explicitly. */ \ PASTEMAC(ch,diagop)( *alpha11_r, \ *alpha11_i, \ beta11c_r, \ beta11c_i ); \ \ /* Output final result to matrix c. */ \ PASTEMAC(ch,sets)( beta11c_r, beta11c_i, *gamma11 ); \ \ /* Store the local values back to b11. */ \ PASTEMAC(ch,sets)( beta11c_r, beta11c_i, *beta11_ri ); \ PASTEMAC(ch,sets)( -beta11c_i, beta11c_r, *beta11_ir ); \ } \ } \ } \ else /* ( bli_is_1r_packed( schema_b ) ) */ \ { \ const inc_t rs_b2 = 2 * rs_b; \ const inc_t cs_b2 = 1 * cs_b; \ \ ctype* restrict a_ri = ( ctype* )a; \ /*ctype* restrict a_ir = ( ctype* )a + ld_a/2;*/ \ \ ctype_r* restrict b_r = ( ctype_r* )b; \ ctype_r* restrict b_i = ( ctype_r* )b + ld_b; \ \ for ( iter = 0; iter < m; ++iter ) \ { \ i = iter; \ n_behind = i; \ \ ctype* restrict alpha11_ri = a_ri + (i )*rs_a + (i )*cs_a; \ ctype_r* restrict alpha11_r = &PASTEMAC(ch,real)( *alpha11_ri ); \ ctype_r* restrict alpha11_i = &PASTEMAC(ch,imag)( *alpha11_ri ); \ ctype* restrict a10t_ri = a_ri + (i )*rs_a + (0 )*cs_a; \ ctype_r* restrict b1_r = b_r + (i )*rs_b2 + (0 )*cs_b2; \ ctype_r* restrict b1_i = b_i + (i )*rs_b2 + (0 )*cs_b2; \ ctype_r* restrict B0_r = b_r + (0 )*rs_b2 + (0 )*cs_b2; \ ctype_r* restrict B0_i = b_i + (0 )*rs_b2 + (0 )*cs_b2; \ \ /* b1 = b1 - a10t * B0; */ \ /* b1 = b1 / alpha11; */ \ for ( j = 0; j < n; ++j ) \ { \ ctype_r* restrict beta11_r = b1_r + (0 )*rs_b2 + (j )*cs_b2; \ ctype_r* restrict beta11_i = b1_i + (0 )*rs_b2 + (j )*cs_b2; \ ctype_r* restrict b01_r = B0_r + (0 )*rs_b2 + (j )*cs_b2; \ ctype_r* restrict b01_i = B0_i + (0 )*rs_b2 + (j )*cs_b2; \ ctype* restrict gamma11 = c + (i )*rs_c + (j )*cs_c; \ ctype_r beta11c_r = *beta11_r; \ ctype_r beta11c_i = *beta11_i; \ ctype_r rho11_r; \ ctype_r rho11_i; \ \ /* beta11 = beta11 - a10t * b01; */ \ PASTEMAC(ch,set0ris)( rho11_r, \ rho11_i ); \ for ( l = 0; l < n_behind; ++l ) \ { \ ctype* restrict alpha10_ri = a10t_ri + (l )*cs_a; \ ctype_r* restrict alpha10_r = &PASTEMAC(ch,real)( *alpha10_ri ); \ ctype_r* restrict alpha10_i = &PASTEMAC(ch,imag)( *alpha10_ri ); \ ctype_r* restrict beta01_r = b01_r + (l )*rs_b2; \ ctype_r* restrict beta01_i = b01_i + (l )*rs_b2; \ \ PASTEMAC(ch,axpyris)( *alpha10_r, \ *alpha10_i, \ *beta01_r, \ *beta01_i, \ rho11_r, \ rho11_i ); \ } \ PASTEMAC(ch,subris)( rho11_r, \ rho11_i, \ beta11c_r, \ beta11c_i ); \ \ /* beta11 = beta11 / alpha11; */ \ /* NOTE: When preinversion is enabled, the INVERSE of alpha11 (1.0/alpha11) is stored during packing instead alpha11 so we can multiply rather than divide. When preinversion is disabled, alpha11 is stored and division happens below explicitly. */ \ PASTEMAC(ch,diagop)( *alpha11_r, \ *alpha11_i, \ beta11c_r, \ beta11c_i ); \ \ /* Output final result to matrix c. */ \ PASTEMAC(ch,sets)( beta11c_r, \ beta11c_i, *gamma11 ); \ \ /* Store the local values back to b11. */ \ PASTEMAC(ch,copyris)( beta11c_r, \ beta11c_i, \ *beta11_r, \ *beta11_i ); \ } \ } \ } \ } #ifdef BLIS_ENABLE_TRSM_PREINVERSION INSERT_GENTFUNCCO_BASIC3( trsm1m_l, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX, scalris ) #else INSERT_GENTFUNCCO_BASIC3( trsm1m_l, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX, invscalris ) #endif #undef GENTFUNCCO #define GENTFUNCCO( ctype, ctype_r, ch, chr, opname, arch, suf, diagop ) \ \ void PASTEMAC3(ch,opname,arch,suf) \ ( \ ctype* restrict a, \ ctype* restrict b, \ ctype* restrict c, inc_t rs_c, inc_t cs_c, \ auxinfo_t* restrict data, \ cntx_t* restrict cntx \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ const dim_t mr = bli_cntx_get_blksz_def_dt( dt, BLIS_MR, cntx ); \ const dim_t nr = bli_cntx_get_blksz_def_dt( dt, BLIS_NR, cntx ); \ \ const inc_t packmr = bli_cntx_get_blksz_max_dt( dt, BLIS_MR, cntx ); \ const inc_t packnr = bli_cntx_get_blksz_max_dt( dt, BLIS_NR, cntx ); \ \ const dim_t m = mr; \ const dim_t n = nr; \ \ const inc_t rs_a = 1; \ const inc_t cs_a = packmr; \ \ const inc_t rs_b = packnr; \ const inc_t cs_b = 1; \ \ const inc_t ld_a = cs_a; \ const inc_t ld_b = rs_b; \ \ const pack_t schema_b = bli_auxinfo_schema_b( data ); \ \ dim_t iter, i, j, l; \ dim_t n_behind; \ \ \ if ( bli_is_1e_packed( schema_b ) ) \ { \ const inc_t rs_a2 = 1 * rs_a; \ const inc_t cs_a2 = 2 * cs_a; \ \ ctype_r* restrict a_r = ( ctype_r* )a; \ ctype_r* restrict a_i = ( ctype_r* )a + ld_a; \ \ ctype* restrict b_ri = ( ctype* )b; \ ctype* restrict b_ir = ( ctype* )b + ld_b/2; \ \ for ( iter = 0; iter < m; ++iter ) \ { \ i = m - iter - 1; \ n_behind = iter; \ \ ctype_r* restrict alpha11_r = a_r + (i )*rs_a2 + (i )*cs_a2; \ ctype_r* restrict alpha11_i = a_i + (i )*rs_a2 + (i )*cs_a2; \ ctype_r* restrict a12t_r = a_r + (i )*rs_a2 + (i+1)*cs_a2; \ ctype_r* restrict a12t_i = a_i + (i )*rs_a2 + (i+1)*cs_a2; \ ctype* restrict b1_ri = b_ri + (i )*rs_b + (0 )*cs_b; \ ctype* restrict b1_ir = b_ir + (i )*rs_b + (0 )*cs_b; \ ctype* restrict B2_ri = b_ri + (i+1)*rs_b + (0 )*cs_b; \ \ /* b1 = b1 - a12t * B2; */ \ /* b1 = b1 / alpha11; */ \ for ( j = 0; j < n; ++j ) \ { \ ctype* restrict beta11_ri = b1_ri + (0 )*rs_b + (j )*cs_b; \ ctype* restrict beta11_ir = b1_ir + (0 )*rs_b + (j )*cs_b; \ ctype* restrict b21_ri = B2_ri + (0 )*rs_b + (j )*cs_b; \ ctype* restrict gamma11 = c + (i )*rs_c + (j )*cs_c; \ ctype_r beta11c_r = PASTEMAC(ch,real)( *beta11_ri ); \ ctype_r beta11c_i = PASTEMAC(ch,imag)( *beta11_ri ); \ ctype_r rho11_r; \ ctype_r rho11_i; \ \ /* beta11 = beta11 - a10t * b01; */ \ PASTEMAC(ch,set0ris)( rho11_r, \ rho11_i ); \ for ( l = 0; l < n_behind; ++l ) \ { \ ctype_r* restrict alpha12_r = a12t_r + (l )*cs_a2; \ ctype_r* restrict alpha12_i = a12t_i + (l )*cs_a2; \ ctype* restrict beta21_ri = b21_ri + (l )*rs_b; \ ctype_r* restrict beta21_r = &PASTEMAC(ch,real)( *beta21_ri ); \ ctype_r* restrict beta21_i = &PASTEMAC(ch,imag)( *beta21_ri ); \ \ PASTEMAC(ch,axpyris)( *alpha12_r, \ *alpha12_i, \ *beta21_r, \ *beta21_i, \ rho11_r, \ rho11_i ); \ } \ PASTEMAC(ch,subris)( rho11_r, \ rho11_i, \ beta11c_r, \ beta11c_i ); \ \ /* beta11 = beta11 / alpha11; */ \ /* NOTE: When preinversion is enabled, the INVERSE of alpha11 (1.0/alpha11) is stored during packing instead alpha11 so we can multiply rather than divide. When preinversion is disabled, alpha11 is stored and division happens below explicitly. */ \ PASTEMAC(ch,diagop)( *alpha11_r, \ *alpha11_i, \ beta11c_r, \ beta11c_i ); \ \ /* Output final result to matrix c. */ \ PASTEMAC(ch,sets)( beta11c_r, beta11c_i, *gamma11 ); \ \ /* Store the local values back to b11. */ \ PASTEMAC(ch,sets)( beta11c_r, beta11c_i, *beta11_ri ); \ PASTEMAC(ch,sets)( -beta11c_i, beta11c_r, *beta11_ir ); \ } \ } \ } \ else /* if ( bli_is_1r_packed( schema_b ) ) */ \ { \ const inc_t rs_b2 = 2 * rs_b; \ const inc_t cs_b2 = 1 * cs_b; \ \ ctype* restrict a_ri = ( ctype* )a; \ /*ctype* restrict a_ir = ( ctype* )a + ld_a/2;*/ \ \ ctype_r* restrict b_r = ( ctype_r* )b; \ ctype_r* restrict b_i = ( ctype_r* )b + ld_b; \ \ for ( iter = 0; iter < m; ++iter ) \ { \ i = m - iter - 1; \ n_behind = iter; \ \ ctype* restrict alpha11_ri = a_ri + (i )*rs_a + (i )*cs_a; \ ctype_r* restrict alpha11_r = &PASTEMAC(ch,real)( *alpha11_ri ); \ ctype_r* restrict alpha11_i = &PASTEMAC(ch,imag)( *alpha11_ri ); \ ctype* restrict a12t_ri = a_ri + (i )*rs_a + (i+1)*cs_a; \ ctype_r* restrict b1_r = b_r + (i )*rs_b2 + (0 )*cs_b2; \ ctype_r* restrict b1_i = b_i + (i )*rs_b2 + (0 )*cs_b2; \ ctype_r* restrict B2_r = b_r + (i+1)*rs_b2 + (0 )*cs_b2; \ ctype_r* restrict B2_i = b_i + (i+1)*rs_b2 + (0 )*cs_b2; \ \ /* b1 = b1 - a12t * B2; */ \ /* b1 = b1 / alpha11; */ \ for ( j = 0; j < n; ++j ) \ { \ ctype_r* restrict beta11_r = b1_r + (0 )*rs_b2 + (j )*cs_b2; \ ctype_r* restrict beta11_i = b1_i + (0 )*rs_b2 + (j )*cs_b2; \ ctype_r* restrict b21_r = B2_r + (0 )*rs_b2 + (j )*cs_b2; \ ctype_r* restrict b21_i = B2_i + (0 )*rs_b2 + (j )*cs_b2; \ ctype* restrict gamma11 = c + (i )*rs_c + (j )*cs_c; \ ctype_r beta11c_r = *beta11_r; \ ctype_r beta11c_i = *beta11_i; \ ctype_r rho11_r; \ ctype_r rho11_i; \ \ /* beta11 = beta11 - a10t * b01; */ \ PASTEMAC(ch,set0ris)( rho11_r, \ rho11_i ); \ for ( l = 0; l < n_behind; ++l ) \ { \ ctype* restrict alpha12_ri = a12t_ri + (l )*cs_a; \ ctype_r* restrict alpha12_r = &PASTEMAC(ch,real)( *alpha12_ri ); \ ctype_r* restrict alpha12_i = &PASTEMAC(ch,imag)( *alpha12_ri ); \ ctype_r* restrict beta21_r = b21_r + (l )*rs_b2; \ ctype_r* restrict beta21_i = b21_i + (l )*rs_b2; \ \ PASTEMAC(ch,axpyris)( *alpha12_r, \ *alpha12_i, \ *beta21_r, \ *beta21_i, \ rho11_r, \ rho11_i ); \ } \ PASTEMAC(ch,subris)( rho11_r, \ rho11_i, \ beta11c_r, \ beta11c_i ); \ \ /* beta11 = beta11 / alpha11; */ \ /* NOTE: When preinversion is enabled, the INVERSE of alpha11 (1.0/alpha11) is stored during packing instead alpha11 so we can multiply rather than divide. When preinversion is disabled, alpha11 is stored and division happens below explicitly. */ \ PASTEMAC(ch,diagop)( *alpha11_r, \ *alpha11_i, \ beta11c_r, \ beta11c_i ); \ \ /* Output final result to matrix c. */ \ PASTEMAC(ch,sets)( beta11c_r, \ beta11c_i, *gamma11 ); \ \ /* Store the local values back to b11. */ \ PASTEMAC(ch,copyris)( beta11c_r, \ beta11c_i, \ *beta11_r, \ *beta11_i ); \ } \ } \ } \ } #ifdef BLIS_ENABLE_TRSM_PREINVERSION INSERT_GENTFUNCCO_BASIC3( trsm1m_u, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX, scalris ) #else INSERT_GENTFUNCCO_BASIC3( trsm1m_u, BLIS_CNAME_INFIX, BLIS_REF_SUFFIX, invscalris ) #endif blis-0.9.0/sandbox/000077500000000000000000000000001422157504600141155ustar00rootroot00000000000000blis-0.9.0/sandbox/gemmlike/000077500000000000000000000000001422157504600157075ustar00rootroot00000000000000blis-0.9.0/sandbox/gemmlike/attic/000077500000000000000000000000001422157504600170135ustar00rootroot00000000000000blis-0.9.0/sandbox/gemmlike/attic/bls_gemm_bp_var2.c000066400000000000000000000467361422157504600223770ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2021, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define FUNCPTR_T gemm_fp typedef void (*FUNCPTR_T) ( conj_t conja, conj_t conjb, dim_t m, dim_t n, dim_t k, void* restrict alpha, void* restrict a, inc_t rs_a, inc_t cs_a, void* restrict b, inc_t rs_b, inc_t cs_b, void* restrict beta, void* restrict c, inc_t rs_c, inc_t cs_c, cntx_t* restrict cntx, rntm_t* restrict rntm, thrinfo_t* restrict thread ); // // -- gemm-like block-panel algorithm (object interface) ----------------------- // // Define a function pointer array named ftypes and initialize its contents with // the addresses of the typed functions defined below, bls_?gemm_bp_var2(). static FUNCPTR_T GENARRAY_PREF(ftypes,bls_,gemm_bp_var2); void bls_gemm_bp_var2 ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, rntm_t* rntm, thrinfo_t* thread ) { const num_t dt = bli_obj_dt( c ); const conj_t conja = bli_obj_conj_status( a ); const conj_t conjb = bli_obj_conj_status( b ); const dim_t m = bli_obj_length( c ); const dim_t n = bli_obj_width( c ); const dim_t k = bli_obj_width( a ); void* restrict buf_a = bli_obj_buffer_at_off( a ); const inc_t rs_a = bli_obj_row_stride( a ); const inc_t cs_a = bli_obj_col_stride( a ); void* restrict buf_b = bli_obj_buffer_at_off( b ); const inc_t rs_b = bli_obj_row_stride( b ); const inc_t cs_b = bli_obj_col_stride( b ); void* restrict buf_c = bli_obj_buffer_at_off( c ); const inc_t rs_c = bli_obj_row_stride( c ); const inc_t cs_c = bli_obj_col_stride( c ); void* restrict buf_alpha = bli_obj_buffer_for_1x1( dt, alpha ); void* restrict buf_beta = bli_obj_buffer_for_1x1( dt, beta ); // Index into the function pointer array to extract the correct // typed function pointer based on the chosen datatype. FUNCPTR_T f = ftypes[dt]; // Invoke the function. f ( conja, conjb, m, n, k, buf_alpha, buf_a, rs_a, cs_a, buf_b, rs_b, cs_b, buf_beta, buf_c, rs_c, cs_c, cntx, rntm, thread ); } // // -- gemm-like block-panel algorithm (typed interface) ------------------------ // #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTECH2(bls_,ch,varname) \ ( \ conj_t conja, \ conj_t conjb, \ dim_t m, \ dim_t n, \ dim_t k, \ void* restrict alpha, \ void* restrict a, inc_t rs_a, inc_t cs_a, \ void* restrict b, inc_t rs_b, inc_t cs_b, \ void* restrict beta, \ void* restrict c, inc_t rs_c, inc_t cs_c, \ cntx_t* restrict cntx, \ rntm_t* restrict rntm, \ thrinfo_t* restrict thread \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ /* Query the context for various blocksizes. */ \ const dim_t NR = bli_cntx_get_blksz_def_dt( dt, BLIS_NR, cntx ); \ const dim_t MR = bli_cntx_get_blksz_def_dt( dt, BLIS_MR, cntx ); \ const dim_t NC = bli_cntx_get_blksz_def_dt( dt, BLIS_NC, cntx ); \ const dim_t MC = bli_cntx_get_blksz_def_dt( dt, BLIS_MC, cntx ); \ const dim_t KC = bli_cntx_get_blksz_def_dt( dt, BLIS_KC, cntx ); \ \ /* Query the context for the microkernel address and cast it to its function pointer type. */ \ /* PASTECH(ch,gemm_ukr_ft) \ gemm_ukr = bli_cntx_get_l3_nat_ukr_dt( dt, BLIS_GEMM_UKR, cntx ); \ */ \ \ /* Temporary C buffer for edge cases. Note that the strides of this temporary buffer are set so that they match the storage of the original C matrix. For example, if C is column-stored, ct will be column-stored as well. */ \ /* ctype ct[ BLIS_STACK_BUF_MAX_SIZE \ / sizeof( ctype ) ] \ __attribute__((aligned(BLIS_STACK_BUF_ALIGN_SIZE))); \ const bool col_pref = bli_cntx_l3_nat_ukr_prefers_cols_dt( dt, BLIS_GEMM_UKR, cntx ); \ const inc_t rs_ct = ( col_pref ? 1 : NR ); \ const inc_t cs_ct = ( col_pref ? MR : 1 ); \ */ \ \ /* Compute partitioning step values for each matrix of each loop. */ \ const inc_t jcstep_c = cs_c; \ const inc_t jcstep_b = cs_b; \ \ const inc_t pcstep_a = cs_a; \ const inc_t pcstep_b = rs_b; \ \ const inc_t icstep_c = rs_c; \ const inc_t icstep_a = rs_a; \ \ const inc_t jrstep_c = cs_c * NR; \ \ const inc_t irstep_c = rs_c * MR; \ \ ctype* restrict a_00 = a; \ ctype* restrict b_00 = b; \ ctype* restrict c_00 = c; \ ctype* restrict alpha_cast = alpha; \ ctype* restrict beta_cast = beta; \ \ /* Make local copies of the scalars to prevent any unnecessary sharing of cache lines between the cores' caches. */ \ ctype alpha_local = *alpha_cast; \ ctype beta_local = *beta_cast; \ ctype one_local = *PASTEMAC(ch,1); \ /*ctype zero_local = *PASTEMAC(ch,0);*/ \ \ auxinfo_t aux; \ \ /* Initialize a mem_t entry for A and B. Strictly speaking, this is only needed for the matrix we will be packing (if any), but we do it unconditionally to be safe. */ \ mem_t mem_a = BLIS_MEM_INITIALIZER; \ mem_t mem_b = BLIS_MEM_INITIALIZER; \ \ /* Define an array of bszid_t ids, which will act as our substitute for the cntl_t tree. */ \ bszid_t bszids[8] = { BLIS_NC, /* 5th loop */ \ BLIS_KC, /* 4th loop */ \ BLIS_NO_PART, /* pack B */ \ BLIS_MC, /* 3rd loop */ \ BLIS_NO_PART, /* pack A */ \ BLIS_NR, /* 2nd loop */ \ BLIS_MR, /* 1st loop */ \ BLIS_KR }; /* microkernel loop */ \ \ bszid_t* restrict bszids_jc = &bszids[0]; \ bszid_t* restrict bszids_pc = &bszids[1]; \ /*bszid_t* restrict bszids_pb = &bszids[2];*/ \ bszid_t* restrict bszids_ic = &bszids[3]; \ /*bszid_t* restrict bszids_pa = &bszids[4];*/ \ bszid_t* restrict bszids_jr = &bszids[5]; \ /*bszid_t* restrict bszids_ir = &bszids[6];*/ \ \ thrinfo_t* restrict thread_jc = NULL; \ thrinfo_t* restrict thread_pc = NULL; \ thrinfo_t* restrict thread_pb = NULL; \ thrinfo_t* restrict thread_ic = NULL; \ thrinfo_t* restrict thread_pa = NULL; \ thrinfo_t* restrict thread_jr = NULL; \ thrinfo_t* restrict thread_ir = NULL; \ \ /* Identify the current thrinfo_t node and then grow the tree. */ \ thread_jc = thread; \ bli_thrinfo_sup_grow( rntm, bszids_jc, thread_jc ); \ \ /* Compute the JC loop thread range for the current thread. */ \ dim_t jc_start, jc_end; \ bli_thread_range_sub( thread_jc, n, NR, FALSE, &jc_start, &jc_end ); \ const dim_t n_local = jc_end - jc_start; \ \ /* Compute number of primary and leftover components of the JC loop. */ \ /*const dim_t jc_iter = ( n_local + NC - 1 ) / NC;*/ \ const dim_t jc_left = n_local % NC; \ \ /* Loop over the n dimension (NC rows/columns at a time). */ \ for ( dim_t jj = jc_start; jj < jc_end; jj += NC ) \ { \ /* Calculate the thread's current JC block dimension. */ \ const dim_t nc_cur = ( NC <= jc_end - jj ? NC : jc_left ); \ \ ctype* restrict b_jc = b_00 + jj * jcstep_b; \ ctype* restrict c_jc = c_00 + jj * jcstep_c; \ \ /* Identify the current thrinfo_t node and then grow the tree. */ \ thread_pc = bli_thrinfo_sub_node( thread_jc ); \ bli_thrinfo_sup_grow( rntm, bszids_pc, thread_pc ); \ \ /* Compute the PC loop thread range for the current thread. */ \ const dim_t pc_start = 0, pc_end = k; \ const dim_t k_local = k; \ \ /* Compute number of primary and leftover components of the PC loop. */ \ /*const dim_t pc_iter = ( k_local + KC - 1 ) / KC;*/ \ const dim_t pc_left = k_local % KC; \ \ /* Loop over the k dimension (KC rows/columns at a time). */ \ for ( dim_t pp = pc_start; pp < pc_end; pp += KC ) \ { \ /* Calculate the thread's current PC block dimension. */ \ const dim_t kc_cur = ( KC <= pc_end - pp ? KC : pc_left ); \ \ ctype* restrict a_pc = a_00 + pp * pcstep_a; \ ctype* restrict b_pc = b_jc + pp * pcstep_b; \ \ /* Only apply beta to the first iteration of the pc loop. */ \ ctype* restrict beta_use = ( pp == 0 ? &beta_local : &one_local ); \ \ ctype* b_use; \ inc_t rs_b_use, cs_b_use, ps_b_use; \ \ /* Identify the current thrinfo_t node. Note that the thrinfo_t node will have already been created by a previous call to bli_thrinfo_sup_grow() since bszid_t values of BLIS_NO_PART cause the tree to grow by two (e.g. to the next bszid that is a normal bszid_t value). */ \ thread_pb = bli_thrinfo_sub_node( thread_pc ); \ /*bli_thrinfo_sup_grow( rntm, bszids_pb, thread_pb );*/ \ \ /* Determine the packing buffer and related parameters for matrix B. Then call the packm implementation. */ \ PASTECH2(bls_,ch,packm_b) \ ( \ conjb, \ KC, NC, \ kc_cur, nc_cur, NR, \ &one_local, \ b_pc, rs_b, cs_b, \ &b_use, &rs_b_use, &cs_b_use, \ &ps_b_use, \ cntx, \ rntm, \ &mem_b, \ thread_pb \ ); \ \ /* Alias b_use so that it's clear this is our current block of matrix B. */ \ ctype* restrict b_pc_use = b_use; \ \ /* Identify the current thrinfo_t node and then grow the tree. */ \ thread_ic = bli_thrinfo_sub_node( thread_pb ); \ bli_thrinfo_sup_grow( rntm, bszids_ic, thread_ic ); \ \ /* Compute the IC loop thread range for the current thread. */ \ dim_t ic_start, ic_end; \ bli_thread_range_sub( thread_ic, m, MR, FALSE, &ic_start, &ic_end ); \ const dim_t m_local = ic_end - ic_start; \ \ /* Compute number of primary and leftover components of the IC loop. */ \ /*const dim_t ic_iter = ( m_local + MC - 1 ) / MC;*/ \ const dim_t ic_left = m_local % MC; \ \ /* Loop over the m dimension (MC rows at a time). */ \ for ( dim_t ii = ic_start; ii < ic_end; ii += MC ) \ { \ /* Calculate the thread's current IC block dimension. */ \ const dim_t mc_cur = ( MC <= ic_end - ii ? MC : ic_left ); \ \ ctype* restrict a_ic = a_pc + ii * icstep_a; \ ctype* restrict c_ic = c_jc + ii * icstep_c; \ \ ctype* a_use; \ inc_t rs_a_use, cs_a_use, ps_a_use; \ \ /* Identify the current thrinfo_t node. Note that the thrinfo_t node will have already been created by a previous call to bli_thrinfo_sup_grow() since bszid_t values of BLIS_NO_PART cause the tree to grow by two (e.g. to the next bszid that is a normal bszid_t value). */ \ thread_pa = bli_thrinfo_sub_node( thread_ic ); \ /*bli_thrinfo_sup_grow( rntm, bszids_pa, thread_pa );*/ \ \ /* Determine the packing buffer and related parameters for matrix A. Then call the packm implementation. */ \ PASTECH2(bls_,ch,packm_a) \ ( \ conja, \ MC, KC, \ mc_cur, kc_cur, MR, \ &one_local, \ a_ic, rs_a, cs_a, \ &a_use, &rs_a_use, &cs_a_use, \ &ps_a_use, \ cntx, \ rntm, \ &mem_a, \ thread_pa \ ); \ \ /* Alias a_use so that it's clear this is our current block of matrix A. */ \ ctype* restrict a_ic_use = a_use; \ \ /* Identify the current thrinfo_t node and then grow the tree. */ \ thread_jr = bli_thrinfo_sub_node( thread_pa ); \ bli_thrinfo_sup_grow( rntm, bszids_jr, thread_jr ); \ \ /* Query the number of threads and thread ids for the JR loop. NOTE: These values are only needed when computing the next micropanel of B. */ \ const dim_t jr_nt = bli_thread_n_way( thread_jr ); \ const dim_t jr_tid = bli_thread_work_id( thread_jr ); \ \ /* Compute number of primary and leftover components of the JR loop. */ \ dim_t jr_iter = ( nc_cur + NR - 1 ) / NR; \ dim_t jr_left = nc_cur % NR; \ \ /* Compute the JR loop thread range for the current thread. */ \ dim_t jr_start, jr_end; \ bli_thread_range_sub( thread_jr, jr_iter, 1, FALSE, &jr_start, &jr_end ); \ \ /* Loop over the n dimension (NR columns at a time). */ \ for ( dim_t j = jr_start; j < jr_end; j += 1 ) \ { \ const dim_t nr_cur \ = ( bli_is_not_edge_f( j, jr_iter, jr_left ) ? NR : jr_left ); \ \ ctype* restrict b_jr = b_pc_use + j * ps_b_use; \ ctype* restrict c_jr = c_ic + j * jrstep_c; \ \ /* Assume for now that our next panel of B to be the current panel of B. */ \ ctype* restrict b2 = b_jr; \ \ /* Identify the current thrinfo_t node. */ \ thread_ir = bli_thrinfo_sub_node( thread_jr ); \ \ /* Query the number of threads and thread ids for the IR loop. NOTE: These values are only needed when computing the next micropanel of A. */ \ const dim_t ir_nt = bli_thread_n_way( thread_ir ); \ const dim_t ir_tid = bli_thread_work_id( thread_ir ); \ \ /* Compute number of primary and leftover components of the IR loop. */ \ dim_t ir_iter = ( mc_cur + MR - 1 ) / MR; \ dim_t ir_left = mc_cur % MR; \ \ /* Compute the IR loop thread range for the current thread. */ \ dim_t ir_start, ir_end; \ bli_thread_range_sub( thread_ir, ir_iter, 1, FALSE, &ir_start, &ir_end ); \ \ /* Loop over the m dimension (MR rows at a time). */ \ for ( dim_t i = ir_start; i < ir_end; i += 1 ) \ { \ const dim_t mr_cur \ = ( bli_is_not_edge_f( i, ir_iter, ir_left ) ? MR : ir_left ); \ \ ctype* restrict a_ir = a_ic_use + i * ps_a_use; \ ctype* restrict c_ir = c_jr + i * irstep_c; \ \ ctype* restrict a2; \ \ /* Compute the addresses of the next micropanels of A and B. */ \ a2 = bli_gemm_get_next_a_upanel( a_ir, ps_a_use, 1 ); \ if ( bli_is_last_iter( i, ir_end, ir_tid, ir_nt ) ) \ { \ a2 = a_ic_use; \ b2 = bli_gemm_get_next_b_upanel( b_jr, ps_b_use, 1 ); \ if ( bli_is_last_iter( j, jr_end, jr_tid, jr_nt ) ) \ b2 = b_pc_use; \ } \ \ /* Save the addresses of next micropanels of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_next_a( a2, &aux ); \ bli_auxinfo_set_next_b( b2, &aux ); \ \ /* Call a wrapper to the kernel (which handles edge cases). */ \ PASTECH2(bls_,ch,gemm_kernel) \ ( \ MR, \ NR, \ mr_cur, \ nr_cur, \ kc_cur, \ &alpha_local, \ a_ir, rs_a_use, cs_a_use, \ b_jr, rs_b_use, cs_b_use, \ beta_use, \ c_ir, rs_c, cs_c, \ &aux, \ cntx \ ); \ } \ } \ } \ \ /* This barrier is needed to prevent threads from starting to pack the next row panel of B before the current row panel is fully computed upon. */ \ bli_thread_barrier( thread_pb ); \ } \ } \ \ /* Release any memory that was acquired for packing matrices A and B. */ \ PASTECH2(bls_,ch,packm_finalize_mem_a) \ ( \ rntm, \ &mem_a, \ thread_pa \ ); \ PASTECH2(bls_,ch,packm_finalize_mem_b) \ ( \ rntm, \ &mem_b, \ thread_pb \ ); \ \ /* PASTEMAC(ch,fprintm)( stdout, "gemm_bp_var2: a1_packed", mr_cur, kc_cur, a_ir, rs_a_use, cs_a_use, "%5.2f", "" ); \ PASTEMAC(ch,fprintm)( stdout, "gemm_bp_var2: b1_packed", kc_cur, nr_cur, b_jr, rs_b_use, cs_b_use, "%5.2f", "" ); \ PASTEMAC(ch,fprintm)( stdout, "gemm_bp_var2: c ", mr_cur, nr_cur, c_ir, rs_c, cs_c, "%5.2f", "" ); \ */ \ } //INSERT_GENTFUNC_BASIC0( gemm_bp_var2 ) GENTFUNC( float, s, gemm_bp_var2 ) GENTFUNC( double, d, gemm_bp_var2 ) GENTFUNC( scomplex, c, gemm_bp_var2 ) GENTFUNC( dcomplex, z, gemm_bp_var2 ) // // -- gemm-like microkernel wrapper -------------------------------------------- // #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTECH2(bls_,ch,varname) \ ( \ const dim_t MR, \ const dim_t NR, \ dim_t mr_cur, \ dim_t nr_cur, \ dim_t kc_cur, \ ctype* restrict alpha, \ ctype* restrict a, inc_t rs_a, inc_t cs_a, \ ctype* restrict b, inc_t rs_b, inc_t cs_b, \ ctype* restrict beta, \ ctype* restrict c, inc_t rs_c, inc_t cs_c, \ auxinfo_t* restrict aux, \ cntx_t* restrict cntx \ ) \ { \ /* Infer the datatype from the ctype. */ \ const num_t dt = PASTEMAC(ch,type); \ \ /* Query the context for the microkernel address and cast it to its function pointer type. */ \ PASTECH(ch,gemm_ukr_ft) \ gemm_ukr = bli_cntx_get_l3_nat_ukr_dt( dt, BLIS_GEMM_UKR, cntx ); \ \ /* Temporary C buffer for edge cases. Note that the strides of this temporary buffer are set so that they match the storage of the original C matrix. For example, if C is column-stored, ct will be column-stored as well. */ \ ctype ct[ BLIS_STACK_BUF_MAX_SIZE \ / sizeof( ctype ) ] \ __attribute__((aligned(BLIS_STACK_BUF_ALIGN_SIZE))); \ const bool col_pref = bli_cntx_l3_nat_ukr_prefers_cols_dt( dt, BLIS_GEMM_UKR, cntx ); \ const inc_t rs_ct = ( col_pref ? 1 : NR ); \ const inc_t cs_ct = ( col_pref ? MR : 1 ); \ \ ctype zero = *PASTEMAC(ch,0); \ \ /* Handle interior and edge cases separately. */ \ if ( mr_cur == MR && nr_cur == NR ) \ { \ /* Invoke the gemm microkernel. */ \ gemm_ukr \ ( \ kc_cur, \ alpha, \ a, \ b, \ beta, \ c, rs_c, cs_c, \ aux, \ cntx \ ); \ } \ else \ { \ /* Invoke the gemm microkernel. */ \ gemm_ukr \ ( \ kc_cur, \ alpha, \ a, \ b, \ &zero, \ ct, rs_ct, cs_ct, \ aux, \ cntx \ ); \ \ /* Scale the bottom edge of C and add the result from above. */ \ PASTEMAC(ch,xpbys_mxn) \ ( \ mr_cur, \ nr_cur, \ ct, rs_ct, cs_ct, \ beta, \ c, rs_c, cs_c \ ); \ } \ } //INSERT_GENTFUNC_BASIC0( gemm_kernel ) GENTFUNC( float, s, gemm_kernel ) GENTFUNC( double, d, gemm_kernel ) GENTFUNC( scomplex, c, gemm_kernel ) GENTFUNC( dcomplex, z, gemm_kernel ) blis-0.9.0/sandbox/gemmlike/bli_gemm_ex.c000066400000000000000000000066471422157504600203370ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // Given the current architecture of BLIS sandboxes, bli_gemm_ex() is the // entry point to any sandbox implementation. // NOTE: This function is implemented functionally identically to the // function that it overrides in frame/3/bli_l3_oapi_ex.c. This means that // we are forgoing the option of customizing the implementations that // underlie bli_gemm() and bli_?gemm() (which both call bli_gemm_ex()). // Any new code defined in this sandbox directory, however, will be // included in the BLIS. #include "blis.h" void bli_gemm_ex ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, rntm_t* rntm ) { bli_init_once(); // A switch to easily toggle whether we use the sandbox implementation // of bls_gemm() as the implementation for bli_gemm(). (This allows for // easy testing of bls_gemm() via the testsuite.) Changing the conditional // to "0" will cause bli_gemm()/bli_gemm_ex() to *not* call the local // sandbox implementation, though that implementation may still be called // directly. if ( 1 ) { bls_gemm_ex( alpha, a, b, beta, c, cntx, rntm ); return; } // Initialize a local runtime with global settings if necessary. Note // that in the case that a runtime is passed in, we make a local copy. rntm_t rntm_l; if ( rntm == NULL ) { bli_rntm_init_from_global( &rntm_l ); rntm = &rntm_l; } else { rntm_l = *rntm; rntm = &rntm_l; } // Obtain a valid (native) context from the gks if necessary. if ( cntx == NULL ) cntx = bli_gks_query_cntx(); // Check the operands. if ( bli_error_checking_is_enabled() ) bli_gemm_check( alpha, a, b, beta, c, cntx ); // Invoke the operation's front end. bli_gemm_front ( alpha, a, b, beta, c, cntx, rntm, NULL ); } blis-0.9.0/sandbox/gemmlike/bli_sandbox.h000066400000000000000000000044361422157504600203530ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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 copyright holder(s) nor the names 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_SANDBOX_H #define BLIS_SANDBOX_H // NOTE: This header is the only header required to be present in the sandbox // implementation directory. // This header should contain (or #include) any definitions that must be // folded into blis.h. Typically, it will remain empty since any header // definitions specific to the sandbox implementation will not need to be // made available to applications (or the framework) during compilation. #include "bls_gemm.h" #include "bls_gemm_check.h" #include "bls_gemm_var.h" #include "bls_l3_packm_a.h" #include "bls_l3_packm_b.h" #include "bls_l3_packm_var.h" #include "bls_packm_cxk.h" #include "bls_l3_decor.h" #endif blis-0.9.0/sandbox/gemmlike/bls_gemm.c000066400000000000000000000172531422157504600176500ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2021, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // -- Define the gemm-like operation's object API ------------------------------ // void bls_gemm ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c ) { bls_gemm_ex ( alpha, a, b, beta, c, NULL, NULL ); } void bls_gemm_ex ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, rntm_t* rntm ) { bli_init_once(); // Initialize a local runtime with global settings if necessary. Note // that in the case that a runtime is passed in, we make a local copy. rntm_t rntm_l; if ( rntm == NULL ) { bli_rntm_init_from_global( &rntm_l ); rntm = &rntm_l; } else { rntm_l = *rntm; rntm = &rntm_l; } // Obtain a valid (native) context from the gks if necessary. // NOTE: This must be done before calling the _check() function, since // that function assumes the context pointer is valid. if ( cntx == NULL ) cntx = bli_gks_query_cntx(); // Check parameters. if ( bli_error_checking_is_enabled() ) bls_gemm_check( alpha, a, b, beta, c, cntx ); // -- bli_gemm_front() ----------------------------------------------------- obj_t a_local; obj_t b_local; obj_t c_local; // If C has a zero dimension, return early. if ( bli_obj_has_zero_dim( c ) ) { return; } // If alpha is zero, or if A or B has a zero dimension, scale C by beta // and return early. if ( bli_obj_equals( alpha, &BLIS_ZERO ) || bli_obj_has_zero_dim( a ) || bli_obj_has_zero_dim( b ) ) { bli_scalm( beta, c ); return; } // Alias A, B, and C in case we need to apply transformations. bli_obj_alias_to( a, &a_local ); bli_obj_alias_to( b, &b_local ); bli_obj_alias_to( c, &c_local ); // Induce a transposition of A if it has its transposition property set. // Then clear the transposition bit in the object. if ( bli_obj_has_trans( &a_local ) ) { bli_obj_induce_trans( &a_local ); bli_obj_set_onlytrans( BLIS_NO_TRANSPOSE, &a_local ); } // Induce a transposition of B if it has its transposition property set. // Then clear the transposition bit in the object. if ( bli_obj_has_trans( &b_local ) ) { bli_obj_induce_trans( &b_local ); bli_obj_set_onlytrans( BLIS_NO_TRANSPOSE, &b_local ); } // An optimization: If C is stored by rows and the micro-kernel prefers // contiguous columns, or if C is stored by columns and the micro-kernel // prefers contiguous rows, transpose the entire operation to allow the // micro-kernel to access elements of C in its preferred manner. if ( bli_cntx_l3_vir_ukr_dislikes_storage_of( &c_local, BLIS_GEMM_UKR, cntx ) ) { bli_obj_swap( &a_local, &b_local ); bli_obj_induce_trans( &a_local ); bli_obj_induce_trans( &b_local ); bli_obj_induce_trans( &c_local ); } // Parse and interpret the contents of the rntm_t object to properly // set the ways of parallelism for each loop, and then make any // additional modifications necessary for the current operation. bli_rntm_set_ways_for_op ( BLIS_GEMM, BLIS_LEFT, // ignored for gemm/hemm/symm bli_obj_length( &c_local ), bli_obj_width( &c_local ), bli_obj_width( &a_local ), rntm ); // Spawn threads (if applicable), where bls_gemm_int() is the thread entry // point function for each thread. This also begins the process of creating // the thrinfo_t tree, which contains thread communicators. bls_l3_thread_decorator ( bls_gemm_int, BLIS_GEMM, // operation family id alpha, &a_local, &b_local, beta, &c_local, cntx, rntm ); } // // -- Define the gemm-like operation's thread entry point ---------------------- // void bls_gemm_int ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, rntm_t* rntm, thrinfo_t* thread ) { // In this function, we choose the gemm implementation that is executed // on each thread. // Call the block-panel algorithm. bls_gemm_bp_var1 ( alpha, a, b, beta, c, cntx, rntm, thread ); } // // -- Define the gemm-like operation's typed API ------------------------------- // #undef GENTFUNC #define GENTFUNC( ctype, ch, opname ) \ \ void PASTECH2(bls_,ch,opname) \ ( \ trans_t transa, \ trans_t transb, \ dim_t m, \ dim_t n, \ dim_t k, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* b, inc_t rs_b, inc_t cs_b, \ ctype* beta, \ ctype* c, inc_t rs_c, inc_t cs_c \ ) \ { \ bli_init_once(); \ \ /* Determine the datatype (e.g. BLIS_FLOAT, BLIS_DOUBLE, etc.) based on the macro parameter 'ch' (e.g. s, d, etc). */ \ const num_t dt = PASTEMAC(ch,type); \ \ obj_t alphao, ao, bo, betao, co; \ \ dim_t m_a, n_a; \ dim_t m_b, n_b; \ \ /* Adjust the dimensions of matrices A and B according to the transa and transb parameters. */ \ bli_set_dims_with_trans( transa, m, k, &m_a, &n_a ); \ bli_set_dims_with_trans( transb, k, n, &m_b, &n_b ); \ \ /* Create bufferless scalar objects and attach the provided scalar pointers to those scalar objects. */ \ bli_obj_create_1x1_with_attached_buffer( dt, alpha, &alphao ); \ bli_obj_create_1x1_with_attached_buffer( dt, beta, &betao ); \ \ /* Create bufferless matrix objects and attach the provided matrix pointers to those matrix objects. */ \ bli_obj_create_with_attached_buffer( dt, m_a, n_a, a, rs_a, cs_a, &ao ); \ bli_obj_create_with_attached_buffer( dt, m_b, n_b, b, rs_b, cs_b, &bo ); \ bli_obj_create_with_attached_buffer( dt, m, n, c, rs_c, cs_c, &co ); \ \ /* Set the transposition/conjugation properties of the objects for matrices A and B. */ \ bli_obj_set_conjtrans( transa, &ao ); \ bli_obj_set_conjtrans( transb, &bo ); \ \ /* Call the object interface. */ \ PASTECH(bls_,opname) \ ( \ &alphao, \ &ao, \ &bo, \ &betao, \ &co \ ); \ } //INSERT_GENTFUNC_BASIC0( gemm ) GENTFUNC( float, s, gemm ) GENTFUNC( double, d, gemm ) GENTFUNC( scomplex, c, gemm ) GENTFUNC( dcomplex, z, gemm ) blis-0.9.0/sandbox/gemmlike/bls_gemm.h000066400000000000000000000056501422157504600176530ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2021, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // -- Prototype the gemm-like operation's object API --------------------------- // void bls_gemm ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c ); void bls_gemm_ex ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, rntm_t* rntm ); // // -- Prototype the gemm-like operation's thread entry point ------------------- // void bls_gemm_int ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, rntm_t* rntm, thrinfo_t* thread ); // // -- Prototype the gemm-like operation's typed API ---------------------------- // #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ void PASTECH2(bls_,ch,opname) \ ( \ trans_t transa, \ trans_t transb, \ dim_t m, \ dim_t n, \ dim_t k, \ ctype* alpha, \ ctype* a, inc_t rs_a, inc_t cs_a, \ ctype* b, inc_t rs_b, inc_t cs_b, \ ctype* beta, \ ctype* c, inc_t rs_c, inc_t cs_c \ ); //INSERT_GENTPROT_BASIC0( gemm ) GENTPROT( float, s, gemm ) GENTPROT( double, d, gemm ) GENTPROT( scomplex, c, gemm ) GENTPROT( dcomplex, z, gemm ) blis-0.9.0/sandbox/gemmlike/bls_gemm_bp_var1.c000066400000000000000000000405041422157504600212550ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2021, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #define FUNCPTR_T gemm_fp typedef void (*FUNCPTR_T) ( conj_t conja, conj_t conjb, dim_t m, dim_t n, dim_t k, void* restrict alpha, void* restrict a, inc_t rs_a, inc_t cs_a, void* restrict b, inc_t rs_b, inc_t cs_b, void* restrict beta, void* restrict c, inc_t rs_c, inc_t cs_c, cntx_t* restrict cntx, rntm_t* restrict rntm, thrinfo_t* restrict thread ); // // -- gemm-like block-panel algorithm (object interface) ----------------------- // // Define a function pointer array named ftypes and initialize its contents with // the addresses of the typed functions defined below, bls_?gemm_bp_var1(). static FUNCPTR_T GENARRAY_PREF(ftypes,bls_,gemm_bp_var1); void bls_gemm_bp_var1 ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, rntm_t* rntm, thrinfo_t* thread ) { const num_t dt = bli_obj_dt( c ); const conj_t conja = bli_obj_conj_status( a ); const conj_t conjb = bli_obj_conj_status( b ); const dim_t m = bli_obj_length( c ); const dim_t n = bli_obj_width( c ); const dim_t k = bli_obj_width( a ); void* restrict buf_a = bli_obj_buffer_at_off( a ); const inc_t rs_a = bli_obj_row_stride( a ); const inc_t cs_a = bli_obj_col_stride( a ); void* restrict buf_b = bli_obj_buffer_at_off( b ); const inc_t rs_b = bli_obj_row_stride( b ); const inc_t cs_b = bli_obj_col_stride( b ); void* restrict buf_c = bli_obj_buffer_at_off( c ); const inc_t rs_c = bli_obj_row_stride( c ); const inc_t cs_c = bli_obj_col_stride( c ); void* restrict buf_alpha = bli_obj_buffer_for_1x1( dt, alpha ); void* restrict buf_beta = bli_obj_buffer_for_1x1( dt, beta ); // Index into the function pointer array to extract the correct // typed function pointer based on the chosen datatype. FUNCPTR_T f = ftypes[dt]; // Invoke the function. f ( conja, conjb, m, n, k, buf_alpha, buf_a, rs_a, cs_a, buf_b, rs_b, cs_b, buf_beta, buf_c, rs_c, cs_c, cntx, rntm, thread ); } // // -- gemm-like block-panel algorithm (typed interface) ------------------------ // #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTECH2(bls_,ch,varname) \ ( \ conj_t conja, \ conj_t conjb, \ dim_t m, \ dim_t n, \ dim_t k, \ void* restrict alpha, \ void* restrict a, inc_t rs_a, inc_t cs_a, \ void* restrict b, inc_t rs_b, inc_t cs_b, \ void* restrict beta, \ void* restrict c, inc_t rs_c, inc_t cs_c, \ cntx_t* restrict cntx, \ rntm_t* restrict rntm, \ thrinfo_t* restrict thread \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ /* Query the context for various blocksizes. */ \ const dim_t NR = bli_cntx_get_blksz_def_dt( dt, BLIS_NR, cntx ); \ const dim_t MR = bli_cntx_get_blksz_def_dt( dt, BLIS_MR, cntx ); \ const dim_t NC = bli_cntx_get_blksz_def_dt( dt, BLIS_NC, cntx ); \ const dim_t MC = bli_cntx_get_blksz_def_dt( dt, BLIS_MC, cntx ); \ const dim_t KC = bli_cntx_get_blksz_def_dt( dt, BLIS_KC, cntx ); \ \ /* Query the context for the microkernel address and cast it to its function pointer type. */ \ PASTECH(ch,gemm_ukr_ft) \ gemm_ukr = bli_cntx_get_l3_nat_ukr_dt( dt, BLIS_GEMM_UKR, cntx ); \ \ /* Compute partitioning step values for each matrix of each loop. */ \ const inc_t jcstep_c = cs_c; \ const inc_t jcstep_b = cs_b; \ \ const inc_t pcstep_a = cs_a; \ const inc_t pcstep_b = rs_b; \ \ const inc_t icstep_c = rs_c; \ const inc_t icstep_a = rs_a; \ \ const inc_t jrstep_c = cs_c * NR; \ \ const inc_t irstep_c = rs_c * MR; \ \ ctype* restrict a_00 = a; \ ctype* restrict b_00 = b; \ ctype* restrict c_00 = c; \ ctype* restrict alpha_cast = alpha; \ ctype* restrict beta_cast = beta; \ \ /* Make local copies of the scalars to prevent any unnecessary sharing of cache lines between the cores' caches. */ \ ctype alpha_local = *alpha_cast; \ ctype beta_local = *beta_cast; \ ctype one_local = *PASTEMAC(ch,1); \ \ auxinfo_t aux; \ \ /* Initialize a mem_t entry for A and B. Strictly speaking, this is only needed for the matrix we will be packing (if any), but we do it unconditionally to be safe. */ \ mem_t mem_a = BLIS_MEM_INITIALIZER; \ mem_t mem_b = BLIS_MEM_INITIALIZER; \ \ /* Define an array of bszid_t ids, which will act as our substitute for the cntl_t tree. */ \ bszid_t bszids[8] = { BLIS_NC, /* 5th loop */ \ BLIS_KC, /* 4th loop */ \ BLIS_NO_PART, /* pack B */ \ BLIS_MC, /* 3rd loop */ \ BLIS_NO_PART, /* pack A */ \ BLIS_NR, /* 2nd loop */ \ BLIS_MR, /* 1st loop */ \ BLIS_KR }; /* microkernel loop */ \ \ bszid_t* restrict bszids_jc = &bszids[0]; \ bszid_t* restrict bszids_pc = &bszids[1]; \ /*bszid_t* restrict bszids_pb = &bszids[2];*/ \ bszid_t* restrict bszids_ic = &bszids[3]; \ /*bszid_t* restrict bszids_pa = &bszids[4];*/ \ bszid_t* restrict bszids_jr = &bszids[5]; \ /*bszid_t* restrict bszids_ir = &bszids[6];*/ \ \ thrinfo_t* restrict thread_jc = NULL; \ thrinfo_t* restrict thread_pc = NULL; \ thrinfo_t* restrict thread_pb = NULL; \ thrinfo_t* restrict thread_ic = NULL; \ thrinfo_t* restrict thread_pa = NULL; \ thrinfo_t* restrict thread_jr = NULL; \ thrinfo_t* restrict thread_ir = NULL; \ \ /* Identify the current thrinfo_t node and then grow the tree. */ \ thread_jc = thread; \ bli_thrinfo_sup_grow( rntm, bszids_jc, thread_jc ); \ \ /* Compute the JC loop thread range for the current thread. */ \ dim_t jc_start, jc_end; \ bli_thread_range_sub( thread_jc, n, NR, FALSE, &jc_start, &jc_end ); \ const dim_t n_local = jc_end - jc_start; \ \ /* Compute number of primary and leftover components of the JC loop. */ \ /*const dim_t jc_iter = ( n_local + NC - 1 ) / NC;*/ \ const dim_t jc_left = n_local % NC; \ \ /* Loop over the n dimension (NC rows/columns at a time). */ \ for ( dim_t jj = jc_start; jj < jc_end; jj += NC ) \ { \ /* Calculate the thread's current JC block dimension. */ \ const dim_t nc_cur = ( NC <= jc_end - jj ? NC : jc_left ); \ \ ctype* restrict b_jc = b_00 + jj * jcstep_b; \ ctype* restrict c_jc = c_00 + jj * jcstep_c; \ \ /* Identify the current thrinfo_t node and then grow the tree. */ \ thread_pc = bli_thrinfo_sub_node( thread_jc ); \ bli_thrinfo_sup_grow( rntm, bszids_pc, thread_pc ); \ \ /* Compute the PC loop thread range for the current thread. */ \ const dim_t pc_start = 0, pc_end = k; \ const dim_t k_local = k; \ \ /* Compute number of primary and leftover components of the PC loop. */ \ /*const dim_t pc_iter = ( k_local + KC - 1 ) / KC;*/ \ const dim_t pc_left = k_local % KC; \ \ /* Loop over the k dimension (KC rows/columns at a time). */ \ for ( dim_t pp = pc_start; pp < pc_end; pp += KC ) \ { \ /* Calculate the thread's current PC block dimension. */ \ const dim_t kc_cur = ( KC <= pc_end - pp ? KC : pc_left ); \ \ ctype* restrict a_pc = a_00 + pp * pcstep_a; \ ctype* restrict b_pc = b_jc + pp * pcstep_b; \ \ /* Only apply beta to the first iteration of the pc loop. */ \ ctype* restrict beta_use = ( pp == 0 ? &beta_local : &one_local ); \ \ ctype* b_use; \ inc_t rs_b_use, cs_b_use, ps_b_use; \ \ /* Identify the current thrinfo_t node. Note that the thrinfo_t node will have already been created by a previous call to bli_thrinfo_sup_grow() since bszid_t values of BLIS_NO_PART cause the tree to grow by two (e.g. to the next bszid that is a normal bszid_t value). */ \ thread_pb = bli_thrinfo_sub_node( thread_pc ); \ /*bli_thrinfo_sup_grow( rntm, bszids_pb, thread_pb );*/ \ \ /* Determine the packing buffer and related parameters for matrix B. Then call the packm implementation. */ \ PASTECH2(bls_,ch,packm_b) \ ( \ conjb, \ KC, NC, \ kc_cur, nc_cur, NR, \ &one_local, \ b_pc, rs_b, cs_b, \ &b_use, &rs_b_use, &cs_b_use, \ &ps_b_use, \ cntx, \ rntm, \ &mem_b, \ thread_pb \ ); \ \ /* Alias b_use so that it's clear this is our current block of matrix B. */ \ ctype* restrict b_pc_use = b_use; \ \ /* Identify the current thrinfo_t node and then grow the tree. */ \ thread_ic = bli_thrinfo_sub_node( thread_pb ); \ bli_thrinfo_sup_grow( rntm, bszids_ic, thread_ic ); \ \ /* Compute the IC loop thread range for the current thread. */ \ dim_t ic_start, ic_end; \ bli_thread_range_sub( thread_ic, m, MR, FALSE, &ic_start, &ic_end ); \ const dim_t m_local = ic_end - ic_start; \ \ /* Compute number of primary and leftover components of the IC loop. */ \ /*const dim_t ic_iter = ( m_local + MC - 1 ) / MC;*/ \ const dim_t ic_left = m_local % MC; \ \ /* Loop over the m dimension (MC rows at a time). */ \ for ( dim_t ii = ic_start; ii < ic_end; ii += MC ) \ { \ /* Calculate the thread's current IC block dimension. */ \ const dim_t mc_cur = ( MC <= ic_end - ii ? MC : ic_left ); \ \ ctype* restrict a_ic = a_pc + ii * icstep_a; \ ctype* restrict c_ic = c_jc + ii * icstep_c; \ \ ctype* a_use; \ inc_t rs_a_use, cs_a_use, ps_a_use; \ \ /* Identify the current thrinfo_t node. Note that the thrinfo_t node will have already been created by a previous call to bli_thrinfo_sup_grow() since bszid_t values of BLIS_NO_PART cause the tree to grow by two (e.g. to the next bszid that is a normal bszid_t value). */ \ thread_pa = bli_thrinfo_sub_node( thread_ic ); \ /*bli_thrinfo_sup_grow( rntm, bszids_pa, thread_pa );*/ \ \ /* Determine the packing buffer and related parameters for matrix A. Then call the packm implementation. */ \ PASTECH2(bls_,ch,packm_a) \ ( \ conja, \ MC, KC, \ mc_cur, kc_cur, MR, \ &one_local, \ a_ic, rs_a, cs_a, \ &a_use, &rs_a_use, &cs_a_use, \ &ps_a_use, \ cntx, \ rntm, \ &mem_a, \ thread_pa \ ); \ \ /* Alias a_use so that it's clear this is our current block of matrix A. */ \ ctype* restrict a_ic_use = a_use; \ \ /* Identify the current thrinfo_t node and then grow the tree. */ \ thread_jr = bli_thrinfo_sub_node( thread_pa ); \ bli_thrinfo_sup_grow( rntm, bszids_jr, thread_jr ); \ \ /* Query the number of threads and thread ids for the JR loop. NOTE: These values are only needed when computing the next micropanel of B. */ \ const dim_t jr_nt = bli_thread_n_way( thread_jr ); \ const dim_t jr_tid = bli_thread_work_id( thread_jr ); \ \ /* Compute number of primary and leftover components of the JR loop. */ \ dim_t jr_iter = ( nc_cur + NR - 1 ) / NR; \ dim_t jr_left = nc_cur % NR; \ \ /* Compute the JR loop thread range for the current thread. */ \ dim_t jr_start, jr_end; \ bli_thread_range_sub( thread_jr, jr_iter, 1, FALSE, &jr_start, &jr_end ); \ \ /* Loop over the n dimension (NR columns at a time). */ \ for ( dim_t j = jr_start; j < jr_end; j += 1 ) \ { \ const dim_t nr_cur \ = ( bli_is_not_edge_f( j, jr_iter, jr_left ) ? NR : jr_left ); \ \ ctype* restrict b_jr = b_pc_use + j * ps_b_use; \ ctype* restrict c_jr = c_ic + j * jrstep_c; \ \ /* Assume for now that our next panel of B to be the current panel of B. */ \ ctype* restrict b2 = b_jr; \ \ /* Identify the current thrinfo_t node. */ \ thread_ir = bli_thrinfo_sub_node( thread_jr ); \ \ /* Query the number of threads and thread ids for the IR loop. NOTE: These values are only needed when computing the next micropanel of A. */ \ const dim_t ir_nt = bli_thread_n_way( thread_ir ); \ const dim_t ir_tid = bli_thread_work_id( thread_ir ); \ \ /* Compute number of primary and leftover components of the IR loop. */ \ dim_t ir_iter = ( mc_cur + MR - 1 ) / MR; \ dim_t ir_left = mc_cur % MR; \ \ /* Compute the IR loop thread range for the current thread. */ \ dim_t ir_start, ir_end; \ bli_thread_range_sub( thread_ir, ir_iter, 1, FALSE, &ir_start, &ir_end ); \ \ /* Loop over the m dimension (MR rows at a time). */ \ for ( dim_t i = ir_start; i < ir_end; i += 1 ) \ { \ const dim_t mr_cur \ = ( bli_is_not_edge_f( i, ir_iter, ir_left ) ? MR : ir_left ); \ \ ctype* restrict a_ir = a_ic_use + i * ps_a_use; \ ctype* restrict c_ir = c_jr + i * irstep_c; \ \ ctype* restrict a2; \ \ /* Compute the addresses of the next micropanels of A and B. */ \ a2 = bli_gemm_get_next_a_upanel( a_ir, ps_a_use, 1 ); \ if ( bli_is_last_iter( i, ir_end, ir_tid, ir_nt ) ) \ { \ a2 = a_ic_use; \ b2 = bli_gemm_get_next_b_upanel( b_jr, ps_b_use, 1 ); \ if ( bli_is_last_iter( j, jr_end, jr_tid, jr_nt ) ) \ b2 = b_pc_use; \ } \ \ /* Save the addresses of next micropanels of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_next_a( a2, &aux ); \ bli_auxinfo_set_next_b( b2, &aux ); \ \ /* Invoke the gemm microkernel. */ \ gemm_ukr \ ( \ mr_cur, \ nr_cur, \ kc_cur, \ &alpha_local, \ a_ir, \ b_jr, \ beta_use, \ c_ir, rs_c, cs_c, \ &aux, \ cntx \ ); \ } \ } \ } \ \ /* This barrier is needed to prevent threads from starting to pack the next row panel of B before the current row panel is fully computed upon. */ \ bli_thread_barrier( thread_pb ); \ } \ } \ \ /* Release any memory that was acquired for packing matrices A and B. */ \ PASTECH2(bls_,ch,packm_finalize_mem_a) \ ( \ rntm, \ &mem_a, \ thread_pa \ ); \ PASTECH2(bls_,ch,packm_finalize_mem_b) \ ( \ rntm, \ &mem_b, \ thread_pb \ ); \ \ /* PASTEMAC(ch,fprintm)( stdout, "gemm_bp_var1: a1_packed", mr_cur, kc_cur, a_ir, rs_a_use, cs_a_use, "%5.2f", "" ); \ PASTEMAC(ch,fprintm)( stdout, "gemm_bp_var1: b1_packed", kc_cur, nr_cur, b_jr, rs_b_use, cs_b_use, "%5.2f", "" ); \ PASTEMAC(ch,fprintm)( stdout, "gemm_bp_var1: c ", mr_cur, nr_cur, c_ir, rs_c, cs_c, "%5.2f", "" ); \ */ \ } //INSERT_GENTFUNC_BASIC0( gemm_bp_var1 ) GENTFUNC( float, s, gemm_bp_var1 ) GENTFUNC( double, d, gemm_bp_var1 ) GENTFUNC( scomplex, c, gemm_bp_var1 ) GENTFUNC( dcomplex, z, gemm_bp_var1 ) blis-0.9.0/sandbox/gemmlike/bls_gemm_check.c000066400000000000000000000067341422157504600210070ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" void bls_gemm_check ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx ) { //bli_check_error_code( BLIS_NOT_YET_IMPLEMENTED ); err_t e_val; // Check object datatypes. e_val = bli_check_noninteger_object( alpha ); bli_check_error_code( e_val ); e_val = bli_check_noninteger_object( beta ); bli_check_error_code( e_val ); e_val = bli_check_floating_object( a ); bli_check_error_code( e_val ); e_val = bli_check_floating_object( b ); bli_check_error_code( e_val ); e_val = bli_check_floating_object( c ); bli_check_error_code( e_val ); // Check scalar/vector/matrix type. e_val = bli_check_scalar_object( alpha ); bli_check_error_code( e_val ); e_val = bli_check_scalar_object( beta ); bli_check_error_code( e_val ); e_val = bli_check_matrix_object( a ); bli_check_error_code( e_val ); e_val = bli_check_matrix_object( b ); bli_check_error_code( e_val ); e_val = bli_check_matrix_object( c ); bli_check_error_code( e_val ); // Check object buffers (for non-NULLness). e_val = bli_check_object_buffer( alpha ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( a ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( b ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( beta ); bli_check_error_code( e_val ); e_val = bli_check_object_buffer( c ); bli_check_error_code( e_val ); // Check object dimensions. e_val = bli_check_level3_dims( a, b, c ); bli_check_error_code( e_val ); // Check for consistent datatypes. // NOTE: We only perform these tests when mixed datatype support is // disabled. e_val = bli_check_consistent_object_datatypes( c, a ); bli_check_error_code( e_val ); e_val = bli_check_consistent_object_datatypes( c, b ); bli_check_error_code( e_val ); } blis-0.9.0/sandbox/gemmlike/bls_gemm_check.h000066400000000000000000000035241422157504600210060ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype object-based check functions. // void bls_gemm_check ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx ); blis-0.9.0/sandbox/gemmlike/bls_gemm_var.h000066400000000000000000000071551422157504600205250ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2021, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype the object-based variant interfaces. // #undef GENPROT #define GENPROT( opname ) \ \ void PASTECH(bls_,opname) \ ( \ obj_t* alpha, \ obj_t* a, \ obj_t* b, \ obj_t* beta, \ obj_t* c, \ cntx_t* cntx, \ rntm_t* rntm, \ thrinfo_t* thread \ ); GENPROT( gemm_bp_var1 ) // // Prototype the typed variant interfaces. // #undef GENTPROT #define GENTPROT( ctype, ch, varname ) \ \ void PASTECH2(bls_,ch,varname) \ ( \ conj_t conja, \ conj_t conjb, \ dim_t m, \ dim_t n, \ dim_t k, \ void* restrict alpha, \ void* restrict a, inc_t rs_a, inc_t cs_a, \ void* restrict b, inc_t rs_b, inc_t cs_b, \ void* restrict beta, \ void* restrict c, inc_t rs_c, inc_t cs_c, \ cntx_t* restrict cntx, \ rntm_t* restrict rntm, \ thrinfo_t* restrict thread \ ); //INSERT_GENTPROT_BASIC0( gemm_bp_var1 ) GENTPROT( float, s, gemm_bp_var1 ) GENTPROT( double, d, gemm_bp_var1 ) GENTPROT( scomplex, c, gemm_bp_var1 ) GENTPROT( dcomplex, z, gemm_bp_var1 ) // // Prototype the typed kernel interfaces. // #undef GENTPROT #define GENTPROT( ctype, ch, varname ) \ \ void PASTECH2(bls_,ch,varname) \ ( \ const dim_t MR, \ const dim_t NR, \ dim_t mr_cur, \ dim_t nr_cur, \ dim_t k, \ ctype* restrict alpha, \ ctype* restrict a, inc_t rs_a, inc_t cs_a, \ ctype* restrict b, inc_t rs_b, inc_t cs_b, \ ctype* restrict beta, \ ctype* restrict c, inc_t rs_c, inc_t cs_c, \ auxinfo_t* restrict aux, \ cntx_t* restrict cntx \ ); //INSERT_GENTPROT_BASIC0( gemm_kernel ) GENTPROT( float, s, gemm_kernel ) GENTPROT( double, d, gemm_kernel ) GENTPROT( scomplex, c, gemm_kernel ) GENTPROT( dcomplex, z, gemm_kernel ) blis-0.9.0/sandbox/gemmlike/bls_l3_packm_a.c000066400000000000000000000240001422157504600207000ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2021, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENTFUNC #define GENTFUNC( ctype, ch, opname ) \ \ void PASTECH2(bls_,ch,opname) \ ( \ dim_t m, \ dim_t k, \ dim_t mr, \ cntx_t* restrict cntx, \ rntm_t* restrict rntm, \ mem_t* restrict mem, \ thrinfo_t* restrict thread \ ) \ { \ /* Set the pack buffer type so that we are obtaining memory blocks from the pool dedicated to blocks of A. */ \ const packbuf_t pack_buf_type = BLIS_BUFFER_FOR_A_BLOCK; \ \ /* NOTE: This "rounding up" of the last upanel is absolutely necessary since we NEED that last micropanel to have the same ldim (cs_p) as the other micropanels. Why? Because the microkernel assumes that the register (MR, NR) AND storage (PACKMR, PACKNR) blocksizes do not change. */ \ const dim_t m_pack = ( m / mr + ( m % mr ? 1 : 0 ) ) * mr; \ const dim_t k_pack = k; \ \ /* Barrier to make sure all threads are caught up and ready to begin the packm stage. */ \ bli_thread_barrier( thread ); \ \ /* Compute the size of the memory block eneded. */ \ siz_t size_needed = sizeof( ctype ) * m_pack * k_pack; \ \ /* Check the mem_t entry provided by the caller. If it is unallocated, then we need to acquire a block from the packed block allocator. */ \ if ( bli_mem_is_unalloc( mem ) ) \ { \ if ( bli_thread_am_ochief( thread ) ) \ { \ /* Acquire directly to the chief thread's mem_t that was passed in. It needs to be that mem_t struct, and not a local (temporary) mem_t, since there is no barrier until after packing is finished, which could allow a race condition whereby the chief thread exits the current function before the other threads have a chance to copy from it. (A barrier would fix that race condition, but then again, I prefer to keep barriers to a minimum.) */ \ bli_pba_acquire_m \ ( \ rntm, \ size_needed, \ pack_buf_type, \ mem \ ); \ } \ \ /* Broadcast the address of the chief thread's passed-in mem_t to all threads. */ \ mem_t* mem_p = bli_thread_broadcast( thread, mem ); \ \ /* Non-chief threads: Copy the contents of the chief thread's passed-in mem_t to the passed-in mem_t for this thread. (The chief thread already has the mem_t, so it does not need to perform any copy.) */ \ if ( !bli_thread_am_ochief( thread ) ) \ { \ *mem = *mem_p; \ } \ } \ else /* if ( bli_mem_is_alloc( mem ) ) */ \ { \ /* If the mem_t entry provided by the caller does NOT contain a NULL buffer, then a block has already been acquired from the packed block allocator and cached by the caller. */ \ \ /* As a sanity check, we should make sure that the mem_t object isn't associated with a block that is too small compared to the size of the packed matrix buffer that is needed, according to the value computed above. */ \ siz_t mem_size = bli_mem_size( mem ); \ \ if ( mem_size < size_needed ) \ { \ if ( bli_thread_am_ochief( thread ) ) \ { \ /* The chief thread releases the existing block associated with the mem_t, and then re-acquires a new block, saving the associated mem_t to its passed-in mem_t. (See coment above for why the acquisition needs to be directly to the chief thread's passed-in mem_t and not a local (temporary) mem_t. */ \ bli_pba_release \ ( \ rntm, \ mem \ ); \ bli_pba_acquire_m \ ( \ rntm, \ size_needed, \ pack_buf_type, \ mem \ ); \ } \ \ /* Broadcast the address of the chief thread's passed-in mem_t to all threads. */ \ mem_t* mem_p = bli_thread_broadcast( thread, mem ); \ \ /* Non-chief threads: Copy the contents of the chief thread's passed-in mem_t to the passed-in mem_t for this thread. (The chief thread already has the mem_t, so it does not need to perform any copy.) */ \ if ( !bli_thread_am_ochief( thread ) ) \ { \ *mem = *mem_p; \ } \ } \ else \ { \ /* If the mem_t entry is already allocated and sufficiently large, then we use it as-is. No action is needed. */ \ } \ } \ } //INSERT_GENTFUNC_BASIC0( packm_init_mem_a ) GENTFUNC( float, s, packm_init_mem_a ) GENTFUNC( double, d, packm_init_mem_a ) GENTFUNC( scomplex, c, packm_init_mem_a ) GENTFUNC( dcomplex, z, packm_init_mem_a ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname ) \ \ void PASTECH2(bls_,ch,opname) \ ( \ rntm_t* restrict rntm, \ mem_t* restrict mem, \ thrinfo_t* restrict thread \ ) \ { \ if ( thread != NULL ) \ if ( bli_thread_am_ochief( thread ) ) \ { \ /* Check the mem_t entry provided by the caller. Only proceed if it is allocated, which it should be. */ \ if ( bli_mem_is_alloc( mem ) ) \ { \ bli_pba_release \ ( \ rntm, \ mem \ ); \ } \ } \ } //INSERT_GENTFUNC_BASIC0( packm_finalize_mem_a ) GENTFUNC( float, s, packm_finalize_mem_a ) GENTFUNC( double, d, packm_finalize_mem_a ) GENTFUNC( scomplex, c, packm_finalize_mem_a ) GENTFUNC( dcomplex, z, packm_finalize_mem_a ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname ) \ \ void PASTECH2(bls_,ch,opname) \ ( \ pack_t* restrict schema, \ dim_t m, \ dim_t k, \ dim_t mr, \ dim_t* restrict m_max, \ dim_t* restrict k_max, \ ctype** p, inc_t* restrict rs_p, inc_t* restrict cs_p, \ dim_t* restrict pd_p, inc_t* restrict ps_p, \ mem_t* restrict mem \ ) \ { \ /* NOTE: This "rounding up" of the last upanel is absolutely necessary since we NEED that last micropanel to have the same ldim (cs_p) as the other micropanels. Why? Because the microkernel assumes that the register (MR, NR) AND storage (PACKMR, PACKNR) blocksizes do not change. */ \ *m_max = ( m / mr + ( m % mr ? 1 : 0 ) ) * mr; \ *k_max = k; \ \ /* Determine the dimensions and strides for the packed matrix A. */ \ { \ /* Pack A to column-stored row-panels. */ \ *rs_p = 1; \ *cs_p = mr; \ \ *pd_p = mr; \ *ps_p = mr * k; \ \ /* Set the schema to "packed row panels" to indicate packing to conventional column-stored row panels. */ \ *schema = BLIS_PACKED_ROW_PANELS; \ } \ \ /* Set the buffer address provided by the caller to point to the memory associated with the mem_t entry acquired from the memory pool. */ \ *p = bli_mem_buffer( mem ); \ } //INSERT_GENTFUNC_BASIC0( packm_init_a ) GENTFUNC( float, s, packm_init_a ) GENTFUNC( double, d, packm_init_a ) GENTFUNC( scomplex, c, packm_init_a ) GENTFUNC( dcomplex, z, packm_init_a ) // // Define BLAS-like interfaces to the variant chooser. // #undef GENTFUNC #define GENTFUNC( ctype, ch, opname ) \ \ void PASTECH2(bls_,ch,opname) \ ( \ conj_t conj, \ dim_t m_alloc, \ dim_t k_alloc, \ dim_t m, \ dim_t k, \ dim_t mr, \ ctype* restrict kappa, \ ctype* restrict a, inc_t rs_a, inc_t cs_a, \ ctype** restrict p, inc_t* restrict rs_p, inc_t* restrict cs_p, \ inc_t* restrict ps_p, \ cntx_t* restrict cntx, \ rntm_t* restrict rntm, \ mem_t* restrict mem, \ thrinfo_t* restrict thread \ ) \ { \ pack_t schema; \ dim_t m_max; \ dim_t k_max; \ dim_t pd_p; \ \ /* Prepare the packing destination buffer. */ \ PASTECH2(bls_,ch,packm_init_mem_a) \ ( \ m_alloc, k_alloc, mr, \ cntx, \ rntm, \ mem, \ thread \ ); \ \ /* Determine the packing buffer and related parameters for matrix A. */ \ PASTECH2(bls_,ch,packm_init_a) \ ( \ &schema, \ m, k, mr, \ &m_max, &k_max, \ p, rs_p, cs_p, \ &pd_p, ps_p, \ mem \ ); \ \ /* Pack matrix A to the destination buffer chosen above. Here, the packed matrix is stored to column-stored MR x k micropanels. */ \ PASTECH2(bls_,ch,packm_var1) \ ( \ conj, \ schema, \ m, \ k, \ m_max, \ k_max, \ kappa, \ a, rs_a, cs_a, \ *p, *rs_p, *cs_p, \ pd_p, *ps_p, \ cntx, \ thread \ ); \ \ /* Barrier so that packing is done before computation. */ \ bli_thread_barrier( thread ); \ } //INSERT_GENTFUNC_BASIC0( packm_a ) GENTFUNC( float, s, packm_a ) GENTFUNC( double, d, packm_a ) GENTFUNC( scomplex, c, packm_a ) GENTFUNC( dcomplex, z, packm_a ) blis-0.9.0/sandbox/gemmlike/bls_l3_packm_a.h000066400000000000000000000101361422157504600207120ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2021, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ void PASTECH2(bls_,ch,opname) \ ( \ dim_t m, \ dim_t k, \ dim_t mr, \ cntx_t* restrict cntx, \ rntm_t* restrict rntm, \ mem_t* restrict mem, \ thrinfo_t* restrict thread \ ); \ //INSERT_GENTPROT_BASIC0( packm_init_mem_a ) GENTPROT( float, s, packm_init_mem_a ) GENTPROT( double, d, packm_init_mem_a ) GENTPROT( scomplex, c, packm_init_mem_a ) GENTPROT( dcomplex, z, packm_init_mem_a ) #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ void PASTECH2(bls_,ch,opname) \ ( \ rntm_t* restrict rntm, \ mem_t* restrict mem, \ thrinfo_t* restrict thread \ ); \ //INSERT_GENTPROT_BASIC0( packm_finalize_mem_a ) GENTPROT( float, s, packm_finalize_mem_a ) GENTPROT( double, d, packm_finalize_mem_a ) GENTPROT( scomplex, c, packm_finalize_mem_a ) GENTPROT( dcomplex, z, packm_finalize_mem_a ) #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ void PASTECH2(bls_,ch,opname) \ ( \ pack_t* restrict schema, \ dim_t m, \ dim_t k, \ dim_t mr, \ dim_t* restrict m_max, \ dim_t* restrict k_max, \ ctype** p, inc_t* restrict rs_p, inc_t* restrict cs_p, \ dim_t* restrict pd_p, inc_t* restrict ps_p, \ mem_t* restrict mem \ ); \ //INSERT_GENTPROT_BASIC0( packm_init_a ) GENTPROT( float, s, packm_init_a ) GENTPROT( double, d, packm_init_a ) GENTPROT( scomplex, c, packm_init_a ) GENTPROT( dcomplex, z, packm_init_a ) #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ void PASTECH2(bls_,ch,opname) \ ( \ conj_t conj, \ dim_t m_alloc, \ dim_t k_alloc, \ dim_t m, \ dim_t k, \ dim_t mr, \ ctype* restrict kappa, \ ctype* restrict a, inc_t rs_a, inc_t cs_a, \ ctype** restrict p, inc_t* restrict rs_p, inc_t* restrict cs_p, \ inc_t* restrict ps_p, \ cntx_t* restrict cntx, \ rntm_t* restrict rntm, \ mem_t* restrict mem, \ thrinfo_t* restrict thread \ ); \ //INSERT_GENTPROT_BASIC0( packm_a ) GENTPROT( float, s, packm_a ) GENTPROT( double, d, packm_a ) GENTPROT( scomplex, c, packm_a ) GENTPROT( dcomplex, z, packm_a ) blis-0.9.0/sandbox/gemmlike/bls_l3_packm_b.c000066400000000000000000000240001422157504600207010ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2021, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENTFUNC #define GENTFUNC( ctype, ch, opname ) \ \ void PASTECH2(bls_,ch,opname) \ ( \ dim_t k, \ dim_t n, \ dim_t nr, \ cntx_t* restrict cntx, \ rntm_t* restrict rntm, \ mem_t* restrict mem, \ thrinfo_t* restrict thread \ ) \ { \ /* Set the pack buffer type so that we are obtaining memory blocks from the pool dedicated to panels of B. */ \ const packbuf_t pack_buf_type = BLIS_BUFFER_FOR_B_PANEL; \ \ /* NOTE: This "rounding up" of the last upanel is absolutely necessary since we NEED that last micropanel to have the same ldim (cs_p) as the other micropanels. Why? Because the microkernel assumes that the register (MR, NR) AND storage (PACKMR, PACKNR) blocksizes do not change. */ \ const dim_t k_pack = k; \ const dim_t n_pack = ( n / nr + ( n % nr ? 1 : 0 ) ) * nr; \ \ /* Barrier to make sure all threads are caught up and ready to begin the packm stage. */ \ bli_thread_barrier( thread ); \ \ /* Compute the size of the memory block eneded. */ \ siz_t size_needed = sizeof( ctype ) * k_pack * n_pack; \ \ /* Check the mem_t entry provided by the caller. If it is unallocated, then we need to acquire a block from the packed block allocator. */ \ if ( bli_mem_is_unalloc( mem ) ) \ { \ if ( bli_thread_am_ochief( thread ) ) \ { \ /* Acquire directly to the chief thread's mem_t that was passed in. It needs to be that mem_t struct, and not a local (temporary) mem_t, since there is no barrier until after packing is finished, which could allow a race condition whereby the chief thread exits the current function before the other threads have a chance to copy from it. (A barrier would fix that race condition, but then again, I prefer to keep barriers to a minimum.) */ \ bli_pba_acquire_m \ ( \ rntm, \ size_needed, \ pack_buf_type, \ mem \ ); \ } \ \ /* Broadcast the address of the chief thread's passed-in mem_t to all threads. */ \ mem_t* mem_p = bli_thread_broadcast( thread, mem ); \ \ /* Non-chief threads: Copy the contents of the chief thread's passed-in mem_t to the passed-in mem_t for this thread. (The chief thread already has the mem_t, so it does not need to perform any copy.) */ \ if ( !bli_thread_am_ochief( thread ) ) \ { \ *mem = *mem_p; \ } \ } \ else /* if ( bli_mem_is_alloc( mem ) ) */ \ { \ /* If the mem_t entry provided by the caller does NOT contain a NULL buffer, then a block has already been acquired from the packed block allocator and cached by the caller. */ \ \ /* As a sanity check, we should make sure that the mem_t object isn't associated with a block that is too small compared to the size of the packed matrix buffer that is needed, according to the value computed above. */ \ siz_t mem_size = bli_mem_size( mem ); \ \ if ( mem_size < size_needed ) \ { \ if ( bli_thread_am_ochief( thread ) ) \ { \ /* The chief thread releases the existing block associated with the mem_t, and then re-acquires a new block, saving the associated mem_t to its passed-in mem_t. (See coment above for why the acquisition needs to be directly to the chief thread's passed-in mem_t and not a local (temporary) mem_t. */ \ bli_pba_release \ ( \ rntm, \ mem \ ); \ bli_pba_acquire_m \ ( \ rntm, \ size_needed, \ pack_buf_type, \ mem \ ); \ } \ \ /* Broadcast the address of the chief thread's passed-in mem_t to all threads. */ \ mem_t* mem_p = bli_thread_broadcast( thread, mem ); \ \ /* Non-chief threads: Copy the contents of the chief thread's passed-in mem_t to the passed-in mem_t for this thread. (The chief thread already has the mem_t, so it does not need to perform any copy.) */ \ if ( !bli_thread_am_ochief( thread ) ) \ { \ *mem = *mem_p; \ } \ } \ else \ { \ /* If the mem_t entry is already allocated and sufficiently large, then we use it as-is. No action is needed. */ \ } \ } \ } //INSERT_GENTFUNC_BASIC0( packm_init_mem_b ) GENTFUNC( float, s, packm_init_mem_b ) GENTFUNC( double, d, packm_init_mem_b ) GENTFUNC( scomplex, c, packm_init_mem_b ) GENTFUNC( dcomplex, z, packm_init_mem_b ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname ) \ \ void PASTECH2(bls_,ch,opname) \ ( \ rntm_t* restrict rntm, \ mem_t* restrict mem, \ thrinfo_t* restrict thread \ ) \ { \ if ( thread != NULL ) \ if ( bli_thread_am_ochief( thread ) ) \ { \ /* Check the mem_t entry provided by the caller. Only proceed if it is allocated, which it should be. */ \ if ( bli_mem_is_alloc( mem ) ) \ { \ bli_pba_release \ ( \ rntm, \ mem \ ); \ } \ } \ } //INSERT_GENTFUNC_BASIC0( packm_finalize_mem_b ) GENTFUNC( float, s, packm_finalize_mem_b ) GENTFUNC( double, d, packm_finalize_mem_b ) GENTFUNC( scomplex, c, packm_finalize_mem_b ) GENTFUNC( dcomplex, z, packm_finalize_mem_b ) #undef GENTFUNC #define GENTFUNC( ctype, ch, opname ) \ \ void PASTECH2(bls_,ch,opname) \ ( \ pack_t* restrict schema, \ dim_t k, \ dim_t n, \ dim_t nr, \ dim_t* restrict k_max, \ dim_t* restrict n_max, \ ctype** p, inc_t* restrict rs_p, inc_t* restrict cs_p, \ dim_t* restrict pd_p, inc_t* restrict ps_p, \ mem_t* restrict mem \ ) \ { \ /* NOTE: This "rounding up" of the last upanel is absolutely necessary since we NEED that last micropanel to have the same ldim (cs_p) as the other micropanels. Why? Because the microkernel assumes that the register (MR, NR) AND storage (PACKMR, PACKNR) blocksizes do not change. */ \ *k_max = k; \ *n_max = ( n / nr + ( n % nr ? 1 : 0 ) ) * nr; \ \ /* Determine the dimensions and strides for the packed matrix B. */ \ { \ /* Pack B to row-stored column-panels. */ \ *rs_p = nr; \ *cs_p = 1; \ \ *pd_p = nr; \ *ps_p = k * nr; \ \ /* Set the schema to "packed column panels" to indicate packing to conventional row-stored column panels. */ \ *schema = BLIS_PACKED_COL_PANELS; \ } \ \ /* Set the buffer address provided by the caller to point to the memory associated with the mem_t entry acquired from the memory pool. */ \ *p = bli_mem_buffer( mem ); \ } //INSERT_GENTFUNC_BASIC0( packm_init_b ) GENTFUNC( float, s, packm_init_b ) GENTFUNC( double, d, packm_init_b ) GENTFUNC( scomplex, c, packm_init_b ) GENTFUNC( dcomplex, z, packm_init_b ) // // Define BLAS-like interfaces to the variant chooser. // #undef GENTFUNC #define GENTFUNC( ctype, ch, opname ) \ \ void PASTECH2(bls_,ch,opname) \ ( \ conj_t conj, \ dim_t k_alloc, \ dim_t n_alloc, \ dim_t k, \ dim_t n, \ dim_t nr, \ ctype* restrict kappa, \ ctype* restrict b, inc_t rs_b, inc_t cs_b, \ ctype** restrict p, inc_t* restrict rs_p, inc_t* restrict cs_p, \ inc_t* restrict ps_p, \ cntx_t* restrict cntx, \ rntm_t* restrict rntm, \ mem_t* restrict mem, \ thrinfo_t* restrict thread \ ) \ { \ pack_t schema; \ dim_t k_max; \ dim_t n_max; \ dim_t pd_p; \ \ /* Prepare the packing destination buffer. */ \ PASTECH2(bls_,ch,packm_init_mem_b) \ ( \ k_alloc, n_alloc, nr, \ cntx, \ rntm, \ mem, \ thread \ ); \ \ /* Determine the packing buffer and related parameters for matrix B. */ \ PASTECH2(bls_,ch,packm_init_b) \ ( \ &schema, \ k, n, nr, \ &k_max, &n_max, \ p, rs_p, cs_p, \ &pd_p, ps_p, \ mem \ ); \ \ /* Pack matrix B to the destination buffer chosen above. Here, the packed matrix is stored to row-stored k x NR micropanels. */ \ PASTECH2(bls_,ch,packm_var1) \ ( \ conj, \ schema, \ k, \ n, \ k_max, \ n_max, \ kappa, \ b, rs_b, cs_b, \ *p, *rs_p, *cs_p, \ pd_p, *ps_p, \ cntx, \ thread \ ); \ \ /* Barrier so that packing is done before computation. */ \ bli_thread_barrier( thread ); \ } //INSERT_GENTFUNC_BASIC0( packm_b ) GENTFUNC( float, s, packm_b ) GENTFUNC( double, d, packm_b ) GENTFUNC( scomplex, c, packm_b ) GENTFUNC( dcomplex, z, packm_b ) blis-0.9.0/sandbox/gemmlike/bls_l3_packm_b.h000066400000000000000000000101361422157504600207130ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2021, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ void PASTECH2(bls_,ch,opname) \ ( \ dim_t k, \ dim_t n, \ dim_t nr, \ cntx_t* restrict cntx, \ rntm_t* restrict rntm, \ mem_t* restrict mem, \ thrinfo_t* restrict thread \ ); \ //INSERT_GENTPROT_BASIC0( packm_init_mem_b ) GENTPROT( float, s, packm_init_mem_b ) GENTPROT( double, d, packm_init_mem_b ) GENTPROT( scomplex, c, packm_init_mem_b ) GENTPROT( dcomplex, z, packm_init_mem_b ) #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ void PASTECH2(bls_,ch,opname) \ ( \ rntm_t* restrict rntm, \ mem_t* restrict mem, \ thrinfo_t* restrict thread \ ); \ //INSERT_GENTPROT_BASIC0( packm_finalize_mem_b ) GENTPROT( float, s, packm_finalize_mem_b ) GENTPROT( double, d, packm_finalize_mem_b ) GENTPROT( scomplex, c, packm_finalize_mem_b ) GENTPROT( dcomplex, z, packm_finalize_mem_b ) #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ void PASTECH2(bls_,ch,opname) \ ( \ pack_t* restrict schema, \ dim_t k, \ dim_t n, \ dim_t nr, \ dim_t* restrict k_max, \ dim_t* restrict n_max, \ ctype** p, inc_t* restrict rs_p, inc_t* restrict cs_p, \ dim_t* restrict pd_p, inc_t* restrict ps_p, \ mem_t* restrict mem \ ); \ //INSERT_GENTPROT_BASIC0( packm_init_b ) GENTPROT( float, s, packm_init_b ) GENTPROT( double, d, packm_init_b ) GENTPROT( scomplex, c, packm_init_b ) GENTPROT( dcomplex, z, packm_init_b ) #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ void PASTECH2(bls_,ch,opname) \ ( \ conj_t conj, \ dim_t k_alloc, \ dim_t n_alloc, \ dim_t k, \ dim_t n, \ dim_t nr, \ ctype* restrict kappa, \ ctype* restrict b, inc_t rs_b, inc_t cs_b, \ ctype** restrict p, inc_t* restrict rs_p, inc_t* restrict cs_p, \ inc_t* restrict ps_p, \ cntx_t* restrict cntx, \ rntm_t* restrict rntm, \ mem_t* restrict mem, \ thrinfo_t* restrict thread \ ); \ //INSERT_GENTPROT_BASIC0( packm_b ) GENTPROT( float, s, packm_b ) GENTPROT( double, d, packm_b ) GENTPROT( scomplex, c, packm_b ) GENTPROT( dcomplex, z, packm_b ) blis-0.9.0/sandbox/gemmlike/bls_l3_packm_var.h000066400000000000000000000054361422157504600212710ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2021, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype BLAS-like interfaces to the variants. // #undef GENTPROT #define GENTPROT( ctype, ch, varname ) \ \ void PASTECH2(bls_,ch,varname) \ ( \ trans_t transc, \ pack_t schema, \ dim_t m, \ dim_t n, \ dim_t m_max, \ dim_t n_max, \ ctype* restrict kappa, \ ctype* restrict c, inc_t rs_c, inc_t cs_c, \ ctype* restrict p, inc_t rs_p, inc_t cs_p, \ dim_t pd_p, inc_t ps_p, \ cntx_t* restrict cntx, \ thrinfo_t* restrict thread \ ); //INSERT_GENTPROT_BASIC0( packm_var1 ) GENTPROT( float, s, packm_var1 ) GENTPROT( double, d, packm_var1 ) GENTPROT( scomplex, c, packm_var1 ) GENTPROT( dcomplex, z, packm_var1 ) //INSERT_GENTPROT_BASIC0( packm_var2 ) GENTPROT( float, s, packm_var2 ) GENTPROT( double, d, packm_var2 ) GENTPROT( scomplex, c, packm_var2 ) GENTPROT( dcomplex, z, packm_var2 ) //INSERT_GENTPROT_BASIC0( packm_var3 ) GENTPROT( float, s, packm_var3 ) GENTPROT( double, d, packm_var3 ) GENTPROT( scomplex, c, packm_var3 ) GENTPROT( dcomplex, z, packm_var3 ) blis-0.9.0/sandbox/gemmlike/bls_l3_packm_var1.c000066400000000000000000000144711422157504600213440ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2021, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // Variant 1 provides basic support for packing by calling packm_cxk(). // #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTECH2(bls_,ch,varname) \ ( \ trans_t transc, \ pack_t schema, \ dim_t m, \ dim_t n, \ dim_t m_max, \ dim_t n_max, \ ctype* restrict kappa, \ ctype* restrict c, inc_t rs_c, inc_t cs_c, \ ctype* restrict p, inc_t rs_p, inc_t cs_p, \ dim_t pd_p, inc_t ps_p, \ cntx_t* restrict cntx, \ thrinfo_t* restrict thread \ ) \ { \ ctype* restrict kappa_cast = kappa; \ ctype* restrict c_cast = c; \ ctype* restrict p_cast = p; \ \ dim_t iter_dim; \ dim_t n_iter; \ dim_t it, ic; \ dim_t ic0; \ doff_t ic_inc; \ dim_t panel_len; \ dim_t panel_len_max; \ dim_t panel_dim; \ dim_t panel_dim_max; \ inc_t incc; \ inc_t ldc; \ inc_t ldp; \ conj_t conjc; \ \ \ /* Extract the conjugation bit from the transposition argument. */ \ conjc = bli_extract_conj( transc ); \ \ /* Create flags to incidate row or column storage. Note that the schema bit that encodes row or column is describing the form of micro-panel, not the storage in the micro-panel. Hence the mismatch in "row" and "column" semantics. */ \ bool row_stored = bli_is_col_packed( schema ); \ /*bool col_stored = bli_is_row_packed( schema );*/ \ \ /* If the row storage flag indicates row storage, then we are packing to column panels; otherwise, if the strides indicate column storage, we are packing to row panels. */ \ if ( row_stored ) \ { \ /* Prepare to pack to row-stored column panels. */ \ iter_dim = n; \ panel_len = m; \ panel_len_max = m_max; \ panel_dim_max = pd_p; \ incc = cs_c; \ ldc = rs_c; \ ldp = rs_p; \ } \ else /* if ( col_stored ) */ \ { \ /* Prepare to pack to column-stored row panels. */ \ iter_dim = m; \ panel_len = n; \ panel_len_max = n_max; \ panel_dim_max = pd_p; \ incc = rs_c; \ ldc = cs_c; \ ldp = cs_p; \ } \ \ /* Compute the total number of iterations we'll need. */ \ n_iter = iter_dim / panel_dim_max + ( iter_dim % panel_dim_max ? 1 : 0 ); \ \ /* Set the initial values and increments for indices related to C and P based on whether reverse iteration was requested. */ \ { \ ic0 = 0; \ ic_inc = panel_dim_max; \ } \ \ ctype* restrict p_begin = p_cast; \ \ /* Query the number of threads and thread ids from the current thread's packm thrinfo_t node. */ \ const dim_t nt = bli_thread_n_way( thread ); \ const dim_t tid = bli_thread_work_id( thread ); \ \ /* Suppress warnings in case tid isn't used (ie: as in slab partitioning). */ \ ( void )nt; \ ( void )tid; \ \ dim_t it_start, it_end, it_inc; \ \ /* Determine the thread range and increment using the current thread's packm thrinfo_t node. NOTE: The definition of bli_thread_range_jrir() will depend on whether slab or round-robin partitioning was requested at configure-time. */ \ bli_thread_range_jrir( thread, n_iter, 1, FALSE, &it_start, &it_end, &it_inc ); \ \ /* Iterate over every logical micropanel in the source matrix. */ \ for ( ic = ic0, it = 0; it < n_iter; \ ic += ic_inc, it += 1 ) \ { \ panel_dim = bli_min( panel_dim_max, iter_dim - ic ); \ \ ctype* restrict c_begin = c_cast + (ic )*incc; \ \ ctype* restrict c_use = c_begin; \ ctype* restrict p_use = p_begin; \ \ /* The definition of bli_packm_my_iter() will depend on whether slab or round-robin partitioning was requested at configure-time. (The default is slab.) */ \ if ( bli_packm_my_iter( it, it_start, it_end, tid, nt ) ) \ { \ PASTECH2(bls_,ch,packm_cxk) \ ( \ conjc, \ schema, \ panel_dim, \ panel_dim_max, \ panel_len, \ panel_len_max, \ kappa_cast, \ c_use, incc, ldc, \ p_use, ldp, \ cntx \ ); \ } \ \ /* if ( !row_stored ) \ PASTEMAC(ch,fprintm)( stdout, "packm_var1: a packed", panel_dim_max, panel_len_max, \ p_use, rs_p, cs_p, "%5.2f", "" ); \ else \ PASTEMAC(ch,fprintm)( stdout, "packm_var1: b packed", panel_len_max, panel_dim_max, \ p_use, rs_p, cs_p, "%5.2f", "" ); \ */ \ \ p_begin += ps_p; \ } \ } //INSERT_GENTFUNC_BASIC0( packm_var1 ) GENTFUNC( float, s, packm_var1 ) GENTFUNC( double, d, packm_var1 ) GENTFUNC( scomplex, c, packm_var1 ) GENTFUNC( dcomplex, z, packm_var1 ) blis-0.9.0/sandbox/gemmlike/bls_l3_packm_var2.c000066400000000000000000000174221422157504600213440ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2021, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // Variant 2 is similar to variant 1, but inlines the contents of packm_cxk(). // #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTECH2(bls_,ch,varname) \ ( \ trans_t transc, \ pack_t schema, \ dim_t m, \ dim_t n, \ dim_t m_max, \ dim_t n_max, \ ctype* restrict kappa, \ ctype* restrict c, inc_t rs_c, inc_t cs_c, \ ctype* restrict p, inc_t rs_p, inc_t cs_p, \ dim_t pd_p, inc_t ps_p, \ cntx_t* restrict cntx, \ thrinfo_t* restrict thread \ ) \ { \ ctype* restrict kappa_cast = kappa; \ ctype* restrict c_cast = c; \ ctype* restrict p_cast = p; \ \ dim_t iter_dim; \ dim_t n_iter; \ dim_t it, ic; \ dim_t ic0; \ doff_t ic_inc; \ dim_t panel_len; \ dim_t panel_len_max; \ dim_t panel_dim; \ dim_t panel_dim_max; \ inc_t incc; \ inc_t ldc; \ inc_t ldp; \ conj_t conjc; \ \ \ /* Extract the conjugation bit from the transposition argument. */ \ conjc = bli_extract_conj( transc ); \ \ /* Create flags to incidate row or column storage. Note that the schema bit that encodes row or column is describing the form of micro-panel, not the storage in the micro-panel. Hence the mismatch in "row" and "column" semantics. */ \ bool row_stored = bli_is_col_packed( schema ); \ /*bool col_stored = bli_is_row_packed( schema );*/ \ \ /* If the row storage flag indicates row storage, then we are packing to column panels; otherwise, if the strides indicate column storage, we are packing to row panels. */ \ if ( row_stored ) \ { \ /* Prepare to pack to row-stored column panels. */ \ iter_dim = n; \ panel_len = m; \ panel_len_max = m_max; \ panel_dim_max = pd_p; \ incc = cs_c; \ ldc = rs_c; \ ldp = rs_p; \ } \ else /* if ( col_stored ) */ \ { \ /* Prepare to pack to column-stored row panels. */ \ iter_dim = m; \ panel_len = n; \ panel_len_max = n_max; \ panel_dim_max = pd_p; \ incc = rs_c; \ ldc = cs_c; \ ldp = cs_p; \ } \ \ /* Compute the total number of iterations we'll need. */ \ n_iter = iter_dim / panel_dim_max + ( iter_dim % panel_dim_max ? 1 : 0 ); \ \ /* Set the initial values and increments for indices related to C and P based on whether reverse iteration was requested. */ \ { \ ic0 = 0; \ ic_inc = panel_dim_max; \ } \ \ ctype* restrict p_begin = p_cast; \ \ /* Query the number of threads and thread ids from the current thread's packm thrinfo_t node. */ \ const dim_t nt = bli_thread_n_way( thread ); \ const dim_t tid = bli_thread_work_id( thread ); \ \ /* Suppress warnings in case tid isn't used (ie: as in slab partitioning). */ \ ( void )nt; \ ( void )tid; \ \ dim_t it_start, it_end, it_inc; \ \ /* Determine the thread range and increment using the current thread's packm thrinfo_t node. NOTE: The definition of bli_thread_range_jrir() will depend on whether slab or round-robin partitioning was requested at configure-time. */ \ bli_thread_range_jrir( thread, n_iter, 1, FALSE, &it_start, &it_end, &it_inc ); \ \ /* Iterate over every logical micropanel in the source matrix. */ \ for ( ic = ic0, it = 0; it < n_iter; \ ic += ic_inc, it += 1 ) \ { \ panel_dim = bli_min( panel_dim_max, iter_dim - ic ); \ \ ctype* restrict c_begin = c_cast + (ic )*incc; \ \ ctype* restrict c_use = c_begin; \ ctype* restrict p_use = p_begin; \ \ /* The definition of bli_packm_my_iter() will depend on whether slab or round-robin partitioning was requested at configure-time. (The default is slab.) */ \ if ( bli_packm_my_iter( it, it_start, it_end, tid, nt ) ) \ { \ /* NOTE: We assume here that kappa = 1 and therefore ignore it. If we're wrong, this will get someone's attention. */ \ if ( !PASTEMAC(ch,eq1)( *kappa_cast ) ) \ bli_abort(); \ \ /* Perform the packing, taking conjc into account. */ \ if ( bli_is_conj( conjc ) ) \ { \ for ( dim_t l = 0; l < panel_len; ++l ) \ { \ for ( dim_t i = 0; i < panel_dim; ++i ) \ { \ ctype* cli = c_use + (l )*ldc + (i )*incc; \ ctype* pli = p_use + (l )*ldp + (i )*1; \ \ PASTEMAC(ch,copyjs)( *cli, *pli ); \ } \ } \ } \ else \ { \ for ( dim_t l = 0; l < panel_len; ++l ) \ { \ for ( dim_t i = 0; i < panel_dim; ++i ) \ { \ ctype* cli = c_use + (l )*ldc + (i )*incc; \ ctype* pli = p_use + (l )*ldp + (i )*1; \ \ PASTEMAC(ch,copys)( *cli, *pli ); \ } \ } \ } \ \ /* If panel_dim < panel_dim_max, then we zero those unused rows. */ \ if ( panel_dim < panel_dim_max ) \ { \ const dim_t i = panel_dim; \ const dim_t m_edge = panel_dim_max - panel_dim; \ const dim_t n_edge = panel_len_max; \ ctype* restrict p_edge = p_use + (i )*1; \ \ PASTEMAC(ch,set0s_mxn) \ ( \ m_edge, \ n_edge, \ p_edge, 1, ldp \ ); \ } \ \ /* If panel_len < panel_len_max, then we zero those unused columns. */ \ if ( panel_len < panel_len_max ) \ { \ const dim_t j = panel_len; \ const dim_t m_edge = panel_dim_max; \ const dim_t n_edge = panel_len_max - panel_len; \ ctype* restrict p_edge = p_use + (j )*ldp; \ \ PASTEMAC(ch,set0s_mxn) \ ( \ m_edge, \ n_edge, \ p_edge, 1, ldp \ ); \ } \ } \ \ /* if ( !row_stored ) \ PASTEMAC(ch,fprintm)( stdout, "packm_var1: a packed", panel_dim_max, panel_len_max, \ p_use, rs_p, cs_p, "%5.2f", "" ); \ else \ PASTEMAC(ch,fprintm)( stdout, "packm_var1: b packed", panel_len_max, panel_dim_max, \ p_use, rs_p, cs_p, "%5.2f", "" ); \ */ \ \ p_begin += ps_p; \ } \ } //INSERT_GENTFUNC_BASIC0( packm_var1 ) GENTFUNC( float, s, packm_var2 ) GENTFUNC( double, d, packm_var2 ) GENTFUNC( scomplex, c, packm_var2 ) GENTFUNC( dcomplex, z, packm_var2 ) blis-0.9.0/sandbox/gemmlike/bls_l3_packm_var3.c000066400000000000000000000153261422157504600213460ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2021, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" // // Variant 3 is similar to variant 1, except that it parallelizes packing // along the k dimension. (Our current hypothesis is that this method of // parallelizing the operation may perform better on some NUMA systems.) // #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTECH2(bls_,ch,varname) \ ( \ trans_t transc, \ pack_t schema, \ dim_t m, \ dim_t n, \ dim_t m_max, \ dim_t n_max, \ ctype* restrict kappa, \ ctype* restrict c, inc_t rs_c, inc_t cs_c, \ ctype* restrict p, inc_t rs_p, inc_t cs_p, \ dim_t pd_p, inc_t ps_p, \ cntx_t* restrict cntx, \ thrinfo_t* restrict thread \ ) \ { \ ctype* restrict kappa_cast = kappa; \ ctype* restrict c_cast = c; \ ctype* restrict p_cast = p; \ \ dim_t iter_dim; \ dim_t n_iter; \ dim_t it, ic; \ dim_t ic0; \ doff_t ic_inc; \ dim_t panel_len; \ dim_t panel_len_max; \ dim_t panel_dim; \ dim_t panel_dim_max; \ inc_t incc; \ inc_t ldc; \ inc_t ldp; \ conj_t conjc; \ \ \ /* Extract the conjugation bit from the transposition argument. */ \ conjc = bli_extract_conj( transc ); \ \ /* Create flags to incidate row or column storage. Note that the schema bit that encodes row or column is describing the form of micro-panel, not the storage in the micro-panel. Hence the mismatch in "row" and "column" semantics. */ \ bool row_stored = bli_is_col_packed( schema ); \ /*bool col_stored = bli_is_row_packed( schema );*/ \ \ /* If the row storage flag indicates row storage, then we are packing to column panels; otherwise, if the strides indicate column storage, we are packing to row panels. */ \ if ( row_stored ) \ { \ /* Prepare to pack to row-stored column panels. */ \ iter_dim = n; \ panel_len = m; \ panel_len_max = m_max; \ panel_dim_max = pd_p; \ incc = cs_c; \ ldc = rs_c; \ ldp = rs_p; \ } \ else /* if ( col_stored ) */ \ { \ /* Prepare to pack to column-stored row panels. */ \ iter_dim = m; \ panel_len = n; \ panel_len_max = n_max; \ panel_dim_max = pd_p; \ incc = rs_c; \ ldc = cs_c; \ ldp = cs_p; \ } \ \ /* Compute the total number of iterations we'll need. */ \ n_iter = iter_dim / panel_dim_max + ( iter_dim % panel_dim_max ? 1 : 0 ); \ \ /* Set the initial values and increments for indices related to C and P based on whether reverse iteration was requested. */ \ { \ ic0 = 0; \ ic_inc = panel_dim_max; \ } \ \ /* Query the number of threads and thread ids from the current thread's packm thrinfo_t node. */ \ const dim_t nt = bli_thread_n_way( thread ); \ const dim_t tid = bli_thread_work_id( thread ); \ \ /* Suppress warnings in case tid isn't used (ie: as in slab partitioning). */ \ ( void )nt; \ ( void )tid; \ \ dim_t pr_start, pr_end; \ \ /* Determine the thread range and increment using the current thread's packm thrinfo_t node. */ \ bli_thread_range_sub( thread, panel_len, 1, FALSE, &pr_start, &pr_end ); \ \ /* Define instances of panel_len and panel_len_max that are specific to the local thread. */ \ dim_t panel_len_loc = pr_end - pr_start; \ dim_t panel_len_max_loc = panel_len_loc; \ \ /* If panel_len_max > panel_len, then there are some columns in p that need to be zeroed. Of course, only the last thread will be responsible for this edge region. */ \ dim_t panel_len_zero = panel_len_max - panel_len; \ if ( tid == nt - 1 ) panel_len_max_loc += panel_len_zero; \ \ /* Shift the pointer for c and p to the appropriate locations within the first micropanel. */ \ dim_t off_loc = pr_start; \ ctype* restrict c_begin_loc = c_cast + off_loc * ldc; \ ctype* restrict p_begin_loc = p_cast + off_loc * ldp; \ \ /* Iterate over every logical micropanel in the source matrix. */ \ for ( ic = ic0, it = 0; it < n_iter; \ ic += ic_inc, it += 1 ) \ { \ panel_dim = bli_min( panel_dim_max, iter_dim - ic ); \ \ ctype* restrict c_use = c_begin_loc + (ic )*incc; \ ctype* restrict p_use = p_begin_loc + (it )*ps_p; \ \ { \ PASTECH2(bls_,ch,packm_cxk) \ ( \ conjc, \ schema, \ panel_dim, \ panel_dim_max, \ panel_len_loc, \ panel_len_max_loc, \ kappa_cast, \ c_use, incc, ldc, \ p_use, ldp, \ cntx \ ); \ } \ } \ } //INSERT_GENTFUNC_BASIC0( packm_var3 ) GENTFUNC( float, s, packm_var3 ) GENTFUNC( double, d, packm_var3 ) GENTFUNC( scomplex, c, packm_var3 ) GENTFUNC( dcomplex, z, packm_var3 ) /* if ( !row_stored ) \ PASTEMAC(ch,fprintm)( stdout, "packm_var3: a packed", panel_dim_max, panel_len_max, \ p_use, rs_p, cs_p, "%5.2f", "" ); \ else \ PASTEMAC(ch,fprintm)( stdout, "packm_var3: b packed", panel_len_max, panel_dim_max, \ p_use, rs_p, cs_p, "%5.2f", "" ); \ */ blis-0.9.0/sandbox/gemmlike/bls_packm_cxk.c000066400000000000000000000115761422157504600206650ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #undef GENTFUNC #define GENTFUNC( ctype, ch, opname ) \ \ void PASTECH2(bls_,ch,opname) \ ( \ conj_t conja, \ pack_t schema, \ dim_t panel_dim, \ dim_t panel_dim_max, \ dim_t panel_len, \ dim_t panel_len_max, \ ctype* kappa, \ ctype* a, inc_t inca, inc_t lda, \ ctype* p, inc_t ldp, \ cntx_t* cntx \ ) \ { \ /* Note that we use panel_dim_max, not panel_dim, to query the packm kernel function pointer. This means that we always use the same kernel, even for edge cases. */ \ num_t dt = PASTEMAC(ch,type); \ l1mkr_t ker_id = panel_dim_max; \ \ PASTECH2(ch,opname,_ker_ft) f; \ \ /* Query the context for the packm kernel corresponding to the current panel dimension, or kernel id. If the id is invalid, the function will return NULL. */ \ f = bli_cntx_get_packm_ker_dt( dt, ker_id, cntx ); \ \ /* If there exists a kernel implementation for the micro-panel dimension provided, we invoke the implementation. Otherwise, we use scal2m. */ \ /* NOTE: We've disabled calling packm micro-kernels from the context for this implementation. To re-enable, change FALSE to TRUE in the conditional below. */ \ if ( f != NULL && FALSE ) \ { \ f \ ( \ conja, \ schema, \ panel_dim, \ panel_len, \ panel_len_max, \ kappa, \ a, inca, lda, \ p, ldp, \ cntx \ ); \ } \ else \ { \ /* NOTE: We assume here that kappa = 1 and therefore ignore it. If we're wrong, this will get someone's attention. */ \ if ( !PASTEMAC(ch,eq1)( *kappa ) ) \ bli_abort(); \ \ /* Perform the packing, taking conja into account. */ \ if ( bli_is_conj( conja ) ) \ { \ for ( dim_t l = 0; l < panel_len; ++l ) \ { \ for ( dim_t i = 0; i < panel_dim; ++i ) \ { \ ctype* ali = a + (l )*lda + (i )*inca; \ ctype* pli = p + (l )*ldp + (i )*1; \ \ PASTEMAC(ch,copyjs)( *ali, *pli ); \ } \ } \ } \ else \ { \ for ( dim_t l = 0; l < panel_len; ++l ) \ { \ for ( dim_t i = 0; i < panel_dim; ++i ) \ { \ ctype* ali = a + (l )*lda + (i )*inca; \ ctype* pli = p + (l )*ldp + (i )*1; \ \ PASTEMAC(ch,copys)( *ali, *pli ); \ } \ } \ } \ \ /* If panel_dim < panel_dim_max, then we zero those unused rows. */ \ if ( panel_dim < panel_dim_max ) \ { \ const dim_t i = panel_dim; \ const dim_t m_edge = panel_dim_max - panel_dim; \ const dim_t n_edge = panel_len_max; \ ctype* restrict p_edge = p + (i )*1; \ \ PASTEMAC(ch,set0s_mxn) \ ( \ m_edge, \ n_edge, \ p_edge, 1, ldp \ ); \ } \ \ /* If panel_len < panel_len_max, then we zero those unused columns. */ \ if ( panel_len < panel_len_max ) \ { \ const dim_t j = panel_len; \ const dim_t m_edge = panel_dim_max; \ const dim_t n_edge = panel_len_max - panel_len; \ ctype* restrict p_edge = p + (j )*ldp; \ \ PASTEMAC(ch,set0s_mxn) \ ( \ m_edge, \ n_edge, \ p_edge, 1, ldp \ ); \ } \ } \ } //INSERT_GENTFUNC_BASIC0( packm_cxk ) GENTFUNC( float, s, packm_cxk ) GENTFUNC( double, d, packm_cxk ) GENTFUNC( scomplex, c, packm_cxk ) GENTFUNC( dcomplex, z, packm_cxk ) blis-0.9.0/sandbox/gemmlike/bls_packm_cxk.h000066400000000000000000000043321422157504600206620ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #undef GENTPROT #define GENTPROT( ctype, ch, varname ) \ \ void PASTECH2(bls_,ch,varname) \ ( \ conj_t conja, \ pack_t schema, \ dim_t panel_dim, \ dim_t panel_dim_max, \ dim_t panel_len, \ dim_t panel_len_max, \ ctype* kappa, \ ctype* a, inc_t inca, inc_t lda, \ ctype* p, inc_t ldp, \ cntx_t* cntx \ ); //INSERT_GENTPROT_BASIC0( packm_cxk ) GENTPROT( float, s, packm_cxk ) GENTPROT( double, d, packm_cxk ) GENTPROT( scomplex, c, packm_cxk ) GENTPROT( dcomplex, z, packm_cxk ) blis-0.9.0/sandbox/gemmlike/thread/000077500000000000000000000000001422157504600171565ustar00rootroot00000000000000blis-0.9.0/sandbox/gemmlike/thread/bls_l3_decor.h000066400000000000000000000047671422157504600216770ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2021, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_SBX_L3_DECOR_H #define BLIS_SBX_L3_DECOR_H // -- sup definitions ---------------------------------------------------------- // Level-3 sup internal function type. typedef void (*l3sbxint_t) ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, rntm_t* rntm, thrinfo_t* thread ); // Level-3 sup thread decorator prototype. void bls_l3_thread_decorator ( l3sbxint_t func, opid_t family, obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, rntm_t* rntm ); // Include definitions specific to the method of multithreading. #include "bls_l3_decor_single.h" #include "bls_l3_decor_openmp.h" #include "bls_l3_decor_pthreads.h" #endif blis-0.9.0/sandbox/gemmlike/thread/bls_l3_decor_openmp.c000066400000000000000000000116471422157504600232430ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2021, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #ifdef BLIS_ENABLE_OPENMP // Define a dummy thread entry function, which is needed in the pthreads // version, so that when building Windows DLLs (with OpenMP enabled or with // no multithreading) we don't risk having an unresolved symbol. void* bls_l3_thread_entry( void* data_void ) { return NULL; } //#define PRINT_THRINFO void bls_l3_thread_decorator ( l3sbxint_t func, opid_t family, obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, rntm_t* rntm ) { // Query the total number of threads from the rntm_t object. const dim_t n_threads = bli_rntm_num_threads( rntm ); // NOTE: The sba was initialized in bli_init(). // Check out an array_t from the small block allocator. This is done // with an internal lock to ensure only one application thread accesses // the sba at a time. bli_sba_checkout_array() will also automatically // resize the array_t, if necessary. array_t* restrict array = bli_sba_checkout_array( n_threads ); // Access the pool_t* for thread 0 and embed it into the rntm. We do // this up-front only so that we have the rntm_t.sba_pool field // initialized and ready for the global communicator creation below. bli_sba_rntm_set_pool( 0, array, rntm ); // Set the packing block allocator field of the rntm. This will be // inherited by all of the child threads when they make local copies of // the rntm below. bli_pba_rntm_set_pba( rntm ); // Allcoate a global communicator for the root thrinfo_t structures. thrcomm_t* restrict gl_comm = bli_thrcomm_create( rntm, n_threads ); _Pragma( "omp parallel num_threads(n_threads)" ) { // Create a thread-local copy of the master thread's rntm_t. This is // necessary since we want each thread to be able to track its own // small block pool_t as it executes down the function stack. rntm_t rntm_l = *rntm; rntm_t* restrict rntm_p = &rntm_l; // Query the thread's id from OpenMP. const dim_t tid = omp_get_thread_num(); // Check for a somewhat obscure OpenMP thread-mistmatch issue. // NOTE: This calls the same function used for the conventional/large // code path. bli_l3_thread_decorator_thread_check( n_threads, tid, gl_comm, rntm_p ); // Use the thread id to access the appropriate pool_t* within the // array_t, and use it to set the sba_pool field within the rntm_t. // If the pool_t* element within the array_t is NULL, it will first // be allocated/initialized. bli_sba_rntm_set_pool( tid, array, rntm_p ); thrinfo_t* thread = NULL; // Create the root node of the thread's thrinfo_t structure. bli_l3_sup_thrinfo_create_root( tid, gl_comm, rntm_p, &thread ); func ( alpha, a, b, beta, c, cntx, rntm_p, thread ); // Free the current thread's thrinfo_t structure. bli_l3_sup_thrinfo_free( rntm_p, thread ); } // We shouldn't free the global communicator since it was already freed // by the global communicator's chief thread in bli_l3_thrinfo_free() // (called from the thread entry function). // Check the array_t back into the small block allocator. Similar to the // check-out, this is done using a lock embedded within the sba to ensure // mutual exclusion. bli_sba_checkin_array( array ); } #endif blis-0.9.0/sandbox/gemmlike/thread/bls_l3_decor_openmp.h000066400000000000000000000035101422157504600232360ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2021, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_SBX_L3_DECOR_OPENMP_H #define BLIS_SBX_L3_DECOR_OPENMP_H // Definitions specific to situations when OpenMP multithreading is enabled. #ifdef BLIS_ENABLE_OPENMP #endif #endif blis-0.9.0/sandbox/gemmlike/thread/bls_l3_decor_pthreads.c000066400000000000000000000155411422157504600235540ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2021, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #ifdef BLIS_ENABLE_PTHREADS // A data structure to assist in passing operands to additional threads. typedef struct thread_data { l3sbxint_t func; opid_t family; obj_t* alpha; obj_t* a; obj_t* b; obj_t* beta; obj_t* c; cntx_t* cntx; rntm_t* rntm; dim_t tid; thrcomm_t* gl_comm; array_t* array; } thread_data_t; // Entry point function for additional threads. void* bls_l3_thread_entry( void* data_void ) { thread_data_t* data = data_void; l3sbxint_t func = data->func; opid_t family = data->family; obj_t* alpha = data->alpha; obj_t* a = data->a; obj_t* b = data->b; obj_t* beta = data->beta; obj_t* c = data->c; cntx_t* cntx = data->cntx; rntm_t* rntm = data->rntm; dim_t tid = data->tid; array_t* array = data->array; thrcomm_t* gl_comm = data->gl_comm; ( void )family; // Create a thread-local copy of the master thread's rntm_t. This is // necessary since we want each thread to be able to track its own // small block pool_t as it executes down the function stack. rntm_t rntm_l = *rntm; rntm_t* restrict rntm_p = &rntm_l; // Use the thread id to access the appropriate pool_t* within the // array_t, and use it to set the sba_pool field within the rntm_t. // If the pool_t* element within the array_t is NULL, it will first // be allocated/initialized. bli_sba_rntm_set_pool( tid, array, rntm_p ); thrinfo_t* thread = NULL; // Create the root node of the current thread's thrinfo_t structure. bli_l3_sup_thrinfo_create_root( tid, gl_comm, rntm_p, &thread ); func ( alpha, a, b, beta, c, cntx, rntm_p, thread ); // Free the current thread's thrinfo_t structure. bli_l3_sup_thrinfo_free( rntm_p, thread ); return NULL; } void bls_l3_thread_decorator ( l3sbxint_t func, opid_t family, obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, rntm_t* rntm ) { err_t r_val; // Query the total number of threads from the context. const dim_t n_threads = bli_rntm_num_threads( rntm ); // NOTE: The sba was initialized in bli_init(). // Check out an array_t from the small block allocator. This is done // with an internal lock to ensure only one application thread accesses // the sba at a time. bli_sba_checkout_array() will also automatically // resize the array_t, if necessary. array_t* restrict array = bli_sba_checkout_array( n_threads ); // Access the pool_t* for thread 0 and embed it into the rntm. We do // this up-front only so that we have the rntm_t.sba_pool field // initialized and ready for the global communicator creation below. bli_sba_rntm_set_pool( 0, array, rntm ); // Set the packing block allocator field of the rntm. This will be // inherited by all of the child threads when they make local copies of // the rntm below. bli_pba_rntm_set_pba( rntm ); // Allocate a global communicator for the root thrinfo_t structures. thrcomm_t* restrict gl_comm = bli_thrcomm_create( rntm, n_threads ); // Allocate an array of pthread objects and auxiliary data structs to pass // to the thread entry functions. #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_l3_thread_decorator().pth: " ); #endif bli_pthread_t* pthreads = bli_malloc_intl( sizeof( bli_pthread_t ) * n_threads, &r_val ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_l3_thread_decorator().pth: " ); #endif thread_data_t* datas = bli_malloc_intl( sizeof( thread_data_t ) * n_threads, &r_val ); // NOTE: We must iterate backwards so that the chief thread (thread id 0) // can spawn all other threads before proceeding with its own computation. for ( dim_t tid = n_threads - 1; 0 <= tid; tid-- ) { // Set up thread data for additional threads (beyond thread 0). datas[tid].func = func; datas[tid].family = family; datas[tid].alpha = alpha; datas[tid].a = a; datas[tid].b = b; datas[tid].beta = beta; datas[tid].c = c; datas[tid].cntx = cntx; datas[tid].rntm = rntm; datas[tid].tid = tid; datas[tid].gl_comm = gl_comm; datas[tid].array = array; // Spawn additional threads for ids greater than 1. if ( tid != 0 ) bli_pthread_create( &pthreads[tid], NULL, &bls_l3_thread_entry, &datas[tid] ); else bls_l3_thread_entry( ( void* )(&datas[0]) ); } // We shouldn't free the global communicator since it was already freed // by the global communicator's chief thread in bli_l3_thrinfo_free() // (called from the thread entry function). // Thread 0 waits for additional threads to finish. for ( dim_t tid = 1; tid < n_threads; tid++ ) { bli_pthread_join( pthreads[tid], NULL ); } // Check the array_t back into the small block allocator. Similar to the // check-out, this is done using a lock embedded within the sba to ensure // mutual exclusion. bli_sba_checkin_array( array ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_l3_thread_decorator().pth: " ); #endif bli_free_intl( pthreads ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "bli_l3_thread_decorator().pth: " ); #endif bli_free_intl( datas ); } #endif blis-0.9.0/sandbox/gemmlike/thread/bls_l3_decor_pthreads.h000066400000000000000000000036351422157504600235620ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2021, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_SBX_L3_DECOR_PTHREADS_H #define BLIS_SBX_L3_DECOR_PTHREADS_H // Definitions specific to situations when POSIX multithreading is enabled. #ifdef BLIS_ENABLE_PTHREADS // Thread entry point prototype. void* bls_l3_thread_entry( void* data_void ); #endif #endif blis-0.9.0/sandbox/gemmlike/thread/bls_l3_decor_single.c000066400000000000000000000113301422157504600232130ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2021, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #ifndef BLIS_ENABLE_MULTITHREADING #define SKIP_THRINFO_TREE void bls_l3_thread_decorator ( l3sbxint_t func, opid_t family, //pack_t schema_a, //pack_t schema_b, obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, rntm_t* rntm ) { // For sequential execution, we use only one thread. const dim_t n_threads = 1; // NOTE: The sba was initialized in bli_init(). // Check out an array_t from the small block allocator. This is done // with an internal lock to ensure only one application thread accesses // the sba at a time. bli_sba_checkout_array() will also automatically // resize the array_t, if necessary. array_t* restrict array = bli_sba_checkout_array( n_threads ); // Access the pool_t* for thread 0 and embed it into the rntm. bli_sba_rntm_set_pool( 0, array, rntm ); // Set the packing block allocator field of the rntm. bli_pba_rntm_set_pba( rntm ); #ifndef SKIP_THRINFO_TREE // Allcoate a global communicator for the root thrinfo_t structures. thrcomm_t* restrict gl_comm = bli_thrcomm_create( rntm, n_threads ); #endif { // NOTE: We don't need to create another copy of the rntm_t since // it was already copied in one of the high-level oapi functions. rntm_t* restrict rntm_p = rntm; // There is only one thread id (for the thief thread). const dim_t tid = 0; // Use the thread id to access the appropriate pool_t* within the // array_t, and use it to set the sba_pool field within the rntm_t. // If the pool_t* element within the array_t is NULL, it will first // be allocated/initialized. // NOTE: This is commented out because, in the single-threaded case, // this is redundant since it's already been done above. //bli_sba_rntm_set_pool( tid, array, rntm_p ); #ifndef SKIP_THRINFO_TREE thrinfo_t* thread = NULL; // Create the root node of the thread's thrinfo_t structure. bli_l3_sup_thrinfo_create_root( tid, gl_comm, rntm_p, &thread ); #else // This optimization allows us to use one of the global thrinfo_t // objects for single-threaded execution rather than grow one from // scratch. The key is that bli_thrinfo_sup_grow(), which is called // from within the variants, will immediately return if it detects // that the thrinfo_t* passed into it is either // &BLIS_GEMM_SINGLE_THREADED or &BLIS_PACKM_SINGLE_THREADED. thrinfo_t* thread = &BLIS_GEMM_SINGLE_THREADED; ( void )tid; #endif func ( alpha, a, b, beta, c, cntx, rntm_p, thread ); #ifndef SKIP_THRINFO_TREE // Free the current thread's thrinfo_t structure. bli_l3_sup_thrinfo_free( rntm_p, thread ); #endif } // We shouldn't free the global communicator since it was already freed // by the global communicator's chief thread in bli_l3_thrinfo_free() // (called above). // Check the array_t back into the small block allocator. Similar to the // check-out, this is done using a lock embedded within the sba to ensure // mutual exclusion. bli_sba_checkin_array( array ); } #endif blis-0.9.0/sandbox/gemmlike/thread/bls_l3_decor_single.h000066400000000000000000000035131422157504600232240ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2021, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_SBX_L3_DECOR_SINGLE_H #define BLIS_SBX_L3_DECOR_SINGLE_H // Definitions specific to situations when multithreading is disabled. #ifndef BLIS_ENABLE_MULTITHREADING #endif #endif blis-0.9.0/sandbox/old/000077500000000000000000000000001422157504600146735ustar00rootroot00000000000000blis-0.9.0/sandbox/old/ref99/000077500000000000000000000000001422157504600156315ustar00rootroot00000000000000blis-0.9.0/sandbox/old/ref99/bli_gemmnat.c000066400000000000000000000055561422157504600202660ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2017 - 2019, Advanced Micro Devices, Inc. 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 copyright holder(s) nor the names 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "blix.h" // Given the current architecture of BLIS sandboxes, bli_gemmnat() is the // entry point to any sandbox implementation. // NOTE: We must keep this function named bli_gemmnat() since this is the BLIS // API function for which we are providing an alternative implementation via // the sandbox. void bli_gemmnat ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, rntm_t* rntm ) { bli_init_once(); // Obtain a valid (native) context from the gks if necessary. if ( cntx == NULL ) cntx = bli_gks_query_cntx(); // Initialize a local runtime with global settings if necessary. Note // that in the case that a runtime is passed in, we make a local copy. rntm_t rntm_l; if ( rntm == NULL ) { bli_rntm_init_from_global( &rntm_l ); rntm = &rntm_l; } else { rntm_l = *rntm; rntm = &rntm_l; } // Invoke the operation's front end. //blx_gemm_front( alpha, a, b, beta, c, cntx, rntm, NULL ); blx_gemm_ref_var2( BLIS_NO_TRANSPOSE, alpha, a, b, beta, c, BLIS_XXX, cntx, rntm, NULL ); } blis-0.9.0/sandbox/old/ref99/bli_sandbox.h000066400000000000000000000041021422157504600202630ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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 copyright holder(s) nor the names 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_SANDBOX_H #define BLIS_SANDBOX_H // NOTE: This header is the only header required to be present in the sandbox // implementation directory. // This header should contain (or #include) any definitions that must be // folded into blis.h. Typically, it will remain empty since any header // definitions specific to the sandbox implementation will not need to be // made available to applications (or the framework) during compilation. #endif blis-0.9.0/sandbox/old/ref99/blix.h000066400000000000000000000036051422157504600167440ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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 copyright holder(s) nor the names 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 COPYRIGHT HOLDER 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. */ #ifndef BLIX_H #define BLIX_H // This header is #included by every file in the ref99 sandbox, and so here // we #include any headers that would define prototypes or types that are // needed by the ref99 sandbox source code. #include "blx_gemm_ref_var2.h" #endif blis-0.9.0/sandbox/old/ref99/blx_gemm_ref_var2.c000066400000000000000000000252221422157504600213600ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "blix.h" #define FUNCPTR_T gemmsup_fp typedef void (*FUNCPTR_T) ( bool packa, bool packb, conj_t conja, conj_t conjb, dim_t m, dim_t n, dim_t k, void* restrict alpha, void* restrict a, inc_t rs_a, inc_t cs_a, void* restrict b, inc_t rs_b, inc_t cs_b, void* restrict beta, void* restrict c, inc_t rs_c, inc_t cs_c, stor3_t eff_id, cntx_t* restrict cntx, rntm_t* restrict rntm, thrinfo_t* restrict thread ); // // -- var2 --------------------------------------------------------------------- // static FUNCPTR_T GENARRAY(ftypes_var2,gemm_ref_var2); void blx_gemm_ref_var2 ( trans_t trans, obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, stor3_t eff_id, cntx_t* cntx, rntm_t* rntm, thrinfo_t* thread ) { const num_t dt = bli_obj_dt( c ); const bool packa = bli_rntm_pack_a( rntm ); const bool packb = bli_rntm_pack_b( rntm ); const conj_t conja = bli_obj_conj_status( a ); const conj_t conjb = bli_obj_conj_status( b ); const dim_t m = bli_obj_length( c ); const dim_t n = bli_obj_width( c ); dim_t k; void* restrict buf_a = bli_obj_buffer_at_off( a ); inc_t rs_a; inc_t cs_a; void* restrict buf_b = bli_obj_buffer_at_off( b ); inc_t rs_b; inc_t cs_b; if ( bli_obj_has_notrans( a ) ) { k = bli_obj_width( a ); rs_a = bli_obj_row_stride( a ); cs_a = bli_obj_col_stride( a ); } else // if ( bli_obj_has_trans( a ) ) { // Assign the variables with an implicit transposition. k = bli_obj_length( a ); rs_a = bli_obj_col_stride( a ); cs_a = bli_obj_row_stride( a ); } if ( bli_obj_has_notrans( b ) ) { rs_b = bli_obj_row_stride( b ); cs_b = bli_obj_col_stride( b ); } else // if ( bli_obj_has_trans( b ) ) { // Assign the variables with an implicit transposition. rs_b = bli_obj_col_stride( b ); cs_b = bli_obj_row_stride( b ); } void* restrict buf_c = bli_obj_buffer_at_off( c ); const inc_t rs_c = bli_obj_row_stride( c ); const inc_t cs_c = bli_obj_col_stride( c ); void* restrict buf_alpha = bli_obj_buffer_for_1x1( dt, alpha ); void* restrict buf_beta = bli_obj_buffer_for_1x1( dt, beta ); // Index into the type combination array to extract the correct // function pointer. FUNCPTR_T f = ftypes_var2[dt]; if ( bli_is_notrans( trans ) ) { // Invoke the function. f ( packa, packb, conja, conjb, m, n, k, buf_alpha, buf_a, rs_a, cs_a, buf_b, rs_b, cs_b, buf_beta, buf_c, rs_c, cs_c, eff_id, cntx, rntm, thread ); } else { bli_abort(); } } #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ bool packa, \ bool packb, \ conj_t conja, \ conj_t conjb, \ dim_t m, \ dim_t n, \ dim_t k, \ void* restrict alpha, \ void* restrict a, inc_t rs_a, inc_t cs_a, \ void* restrict b, inc_t rs_b, inc_t cs_b, \ void* restrict beta, \ void* restrict c, inc_t rs_c, inc_t cs_c, \ stor3_t stor_id, \ cntx_t* restrict cntx, \ rntm_t* restrict rntm, \ thrinfo_t* restrict thread \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ /* If m or n is zero, return immediately. */ \ if ( bli_zero_dim2( m, n ) ) return; \ \ /* If k < 1 or alpha is zero, scale by beta and return. */ \ if ( k < 1 || PASTEMAC(ch,eq0)( *(( ctype* )alpha) ) ) \ { \ PASTEMAC(ch,scalm) \ ( \ BLIS_NO_CONJUGATE, \ 0, \ BLIS_NONUNIT_DIAG, \ BLIS_DENSE, \ m, n, \ beta, \ c, rs_c, cs_c \ ); \ return; \ } \ \ /* Query the context for various blocksizes. NOTE: We query the regular blocksizes since the sup blocksizes are not guaranteed to have default values. */ \ const dim_t NR = bli_cntx_get_blksz_def_dt( dt, BLIS_NR, cntx ); \ const dim_t MR = bli_cntx_get_blksz_def_dt( dt, BLIS_MR, cntx ); \ const dim_t NC = bli_cntx_get_blksz_def_dt( dt, BLIS_NC, cntx ); \ const dim_t MC = bli_cntx_get_blksz_def_dt( dt, BLIS_MC, cntx ); \ const dim_t KC = bli_cntx_get_blksz_def_dt( dt, BLIS_KC, cntx ); \ \ /* Compute partitioning step values for each matrix of each loop. */ \ const inc_t jcstep_c = cs_c; \ const inc_t jcstep_b = cs_b; \ \ const inc_t pcstep_a = cs_a; \ const inc_t pcstep_b = rs_b; \ \ const inc_t icstep_c = rs_c; \ const inc_t icstep_a = rs_a; \ \ const inc_t jrstep_c = cs_c * NR; \ const inc_t jrstep_b = cs_b * NR; \ \ const inc_t irstep_c = rs_c * MR; \ const inc_t irstep_a = rs_a * MR; \ \ /* Query the context for the sup microkernel address and cast it to its function pointer type. */ \ PASTECH(ch,gemmsup_ker_ft) \ gemmsup_ker = bli_cntx_get_l3_sup_ker_dt( dt, stor_id, cntx ); \ \ ctype* restrict a_00 = a; \ ctype* restrict b_00 = b; \ ctype* restrict c_00 = c; \ ctype* restrict alpha_cast = alpha; \ ctype* restrict beta_cast = beta; \ \ /* Make local copies of beta and one scalars to prevent any unnecessary sharing of cache lines between the cores' caches. */ \ ctype beta_local = *beta_cast; \ ctype one_local = *PASTEMAC(ch,1); \ \ auxinfo_t aux; \ \ /* Compute number of primary and leftover components of the JC loop. */ \ /*const dim_t jc_iter = ( n + NC - 1 ) / NC;*/ \ const dim_t jc_left = n % NC; \ \ /* Loop over the n dimension (NC rows/columns at a time). */ \ for ( dim_t jj = 0; jj < n; jj += NC ) \ { \ /* Calculate the thread's current JC block dimension. */ \ const dim_t nc_cur = ( NC <= n - jj ? NC : jc_left ); \ \ ctype* restrict b_jc = b_00 + jj * jcstep_b; \ ctype* restrict c_jc = c_00 + jj * jcstep_c; \ \ /* Compute number of primary and leftover components of the PC loop. */ \ /*const dim_t pc_iter = ( k + KC - 1 ) / KC;*/ \ const dim_t pc_left = k % KC; \ \ /* Loop over the k dimension (KC rows/columns at a time). */ \ for ( dim_t pp = 0; pp < k; pp += KC ) \ { \ /* Calculate the thread's current PC block dimension. */ \ const dim_t kc_cur = ( KC <= k - pp ? KC : pc_left ); \ \ ctype* restrict a_pc = a_00 + pp * pcstep_a; \ ctype* restrict b_pc = b_jc + pp * pcstep_b; \ \ /* Only apply beta to the first iteration of the pc loop. */ \ ctype* restrict beta_use = ( pp == 0 ? &beta_local : &one_local ); \ \ /*bli_auxinfo_set_ps_b( ps_b_use, &aux );*/ \ \ /* Compute number of primary and leftover components of the IC loop. */ \ /*const dim_t ic_iter = ( m + MC - 1 ) / MC;*/ \ const dim_t ic_left = m % MC; \ \ /* Loop over the m dimension (MC rows at a time). */ \ for ( dim_t ii = 0; ii < m; ii += MC ) \ { \ /* Calculate the thread's current IC block dimension. */ \ const dim_t mc_cur = ( MC <= m - ii ? MC : ic_left ); \ \ ctype* restrict a_ic = a_pc + ii * icstep_a; \ ctype* restrict c_ic = c_jc + ii * icstep_c; \ \ /*bli_auxinfo_set_ps_a( ps_a_use, &aux );*/ \ \ /* Compute number of primary and leftover components of the JR loop. */ \ dim_t jr_iter = ( nc_cur + NR - 1 ) / NR; \ dim_t jr_left = nc_cur % NR; \ \ /* Loop over the n dimension (NR columns at a time). */ \ for ( dim_t j = 0; j < jr_iter; j += 1 ) \ { \ const dim_t nr_cur = ( bli_is_not_edge_f( j, jr_iter, jr_left ) ? NR : jr_left ); \ \ ctype* restrict b_jr = b_pc + j * jrstep_b; \ ctype* restrict c_jr = c_ic + j * jrstep_c; \ \ /* Compute number of primary and leftover components of the IR loop. */ \ const dim_t ir_iter = ( mc_cur + MR - 1 ) / MR; \ const dim_t ir_left = mc_cur % MR; \ \ /* Loop over the m dimension (MR columns at a time). */ \ for ( dim_t i = 0; i < ir_iter; i += 1 ) \ { \ const dim_t mr_cur = ( bli_is_not_edge_f( i, ir_iter, ir_left ) ? MR : ir_left ); \ \ ctype* restrict a_ir = a_ic + i * irstep_a; \ ctype* restrict c_ir = c_jr + i * irstep_c; \ \ /* bli_auxinfo_set_next_a( a2, &aux ); \ bli_auxinfo_set_next_b( b2, &aux ); \ */ \ \ /* Invoke the kernel. */ \ gemmsup_ker \ ( \ conja, \ conjb, \ mr_cur, \ nr_cur, \ kc_cur, \ alpha_cast, \ a_ir, rs_a, cs_a, \ b_jr, rs_b, cs_b, \ beta_use, \ c_ir, rs_c, cs_c, \ &aux, \ cntx \ ); \ } \ } \ } \ } \ } \ \ /* PASTEMAC(ch,fprintm)( stdout, "gemm_ref_var2: b1", kc_cur, nr_cur, b_jr, rs_b, cs_b, "%4.1f", "" ); \ PASTEMAC(ch,fprintm)( stdout, "gemm_ref_var2: a1", mr_cur, kc_cur, a_ir, rs_a, cs_a, "%4.1f", "" ); \ PASTEMAC(ch,fprintm)( stdout, "gemm_ref_var2: c ", mr_cur, nr_cur, c_ir, rs_c, cs_c, "%4.1f", "" ); \ */ \ } INSERT_GENTFUNC_BASIC0( gemm_ref_var2 ) blis-0.9.0/sandbox/old/ref99/blx_gemm_ref_var2.h000066400000000000000000000051221422157504600213620ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void blx_gemm_ref_var2 ( trans_t trans, obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, stor3_t eff_id, cntx_t* cntx, rntm_t* rntm, thrinfo_t* thread ); #undef GENTPROT #define GENTPROT( ctype, ch, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ bool packa, \ bool packb, \ conj_t conja, \ conj_t conjb, \ dim_t m, \ dim_t n, \ dim_t k, \ void* restrict alpha, \ void* restrict a, inc_t rs_a, inc_t cs_a, \ void* restrict b, inc_t rs_b, inc_t cs_b, \ void* restrict beta, \ void* restrict c, inc_t rs_c, inc_t cs_c, \ stor3_t stor_id, \ cntx_t* restrict cntx, \ rntm_t* restrict rntm, \ thrinfo_t* restrict thread \ ); INSERT_GENTPROT_BASIC0( gemm_ref_var2 ) blis-0.9.0/sandbox/old/ref99/old/000077500000000000000000000000001422157504600164075ustar00rootroot00000000000000blis-0.9.0/sandbox/old/ref99/old/base/000077500000000000000000000000001422157504600173215ustar00rootroot00000000000000blis-0.9.0/sandbox/old/ref99/old/base/blx_blksz.c000066400000000000000000000057751422157504600214750ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "blix.h" dim_t blx_determine_blocksize_f ( dim_t i, dim_t dim, obj_t* obj, bszid_t bszid, cntx_t* cntx ) { num_t dt; blksz_t* bsize; dim_t b_alg, b_max; dim_t b_use; // Extract the execution datatype and use it to query the corresponding // blocksize and blocksize maximum values from the blksz_t object. dt = bli_obj_exec_dt( obj ); bsize = bli_cntx_get_blksz( bszid, cntx ); b_alg = bli_blksz_get_def( dt, bsize ); b_max = bli_blksz_get_max( dt, bsize ); b_use = blx_determine_blocksize_f_sub( i, dim, b_alg, b_max ); return b_use; } dim_t blx_determine_blocksize_f_sub ( dim_t i, dim_t dim, dim_t b_alg, dim_t b_max ) { dim_t b_now; dim_t dim_left_now; // We assume that this function is being called from an algorithm that // is moving "forward" (ie: top to bottom, left to right, top-left // to bottom-right). // Compute how much of the matrix dimension is left, including the // chunk that will correspond to the blocksize we are computing now. dim_left_now = dim - i; // If the dimension currently remaining is less than the maximum // blocksize, use it instead of the default blocksize b_alg. // Otherwise, use b_alg. if ( dim_left_now <= b_max ) { b_now = dim_left_now; } else { b_now = b_alg; } return b_now; } blis-0.9.0/sandbox/old/ref99/old/base/blx_blksz.h000066400000000000000000000045341422157504600214720ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ dim_t blx_determine_blocksize ( dir_t direct, dim_t i, dim_t dim, obj_t* obj, bszid_t bszid, cntx_t* cntx ); dim_t blx_determine_blocksize_f ( dim_t i, dim_t dim, obj_t* obj, bszid_t bszid, cntx_t* cntx ); dim_t blx_determine_blocksize_b ( dim_t i, dim_t dim, obj_t* obj, bszid_t bszid, cntx_t* cntx ); dim_t blx_determine_blocksize_f_sub ( dim_t i, dim_t dim, dim_t b_alg, dim_t b_max ); dim_t blx_determine_blocksize_b_sub ( dim_t i, dim_t dim, dim_t b_alg, dim_t b_max ); blis-0.9.0/sandbox/old/ref99/old/blx_gemm.h000066400000000000000000000036561422157504600203640ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // core gemm #include "blx_gemm_front.h" #include "blx_gemm_int.h" #include "blx_gemm_var.h" // base #include "blx_blksz.h" // cntl #include "blx_packm_cntl.h" #include "blx_gemm_cntl.h" #include "blx_l3_cntl_if.h" // thread #include "blx_gemm_thread.h" // packm #include "blx_l3_packm.h" blis-0.9.0/sandbox/old/ref99/old/blx_gemm_front.c000066400000000000000000000111361422157504600215570ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2017 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "blix.h" void blx_gemm_front ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl ) { bli_init_once(); obj_t a_local; obj_t b_local; obj_t c_local; // Check parameters. if ( bli_error_checking_is_enabled() ) bli_gemm_check( alpha, a, b, beta, c, cntx ); // If alpha is zero, scale by beta and return. if ( bli_obj_equals( alpha, &BLIS_ZERO ) ) { bli_scalm( beta, c ); return; } // Alias A, B, and C in case we need to apply transformations. bli_obj_alias_to( a, &a_local ); bli_obj_alias_to( b, &b_local ); bli_obj_alias_to( c, &c_local ); // If alpha is non-unit, typecast and apply it to the scalar attached // to B. if ( !bli_obj_equals( alpha, &BLIS_ONE ) ) { bli_obj_scalar_apply_scalar( alpha, &b_local ); } // If beta is non-unit, typecast and apply it to the scalar attached // to C. if ( !bli_obj_equals( beta, &BLIS_ONE ) ) { bli_obj_scalar_apply_scalar( beta, &c_local ); } // An optimization: If C is stored by rows and the micro-kernel prefers // contiguous columns, or if C is stored by columns and the micro-kernel // prefers contiguous rows, transpose the entire operation to allow the // micro-kernel to access elements of C in its preferred manner. if ( bli_cntx_l3_vir_ukr_dislikes_storage_of( &c_local, BLIS_GEMM_UKR, cntx ) ) { bli_obj_swap( &a_local, &b_local ); bli_obj_induce_trans( &a_local ); bli_obj_induce_trans( &b_local ); bli_obj_induce_trans( &c_local ); } { // A sort of hack for communicating the desired pach schemas for A and // B to bli_gemm_cntl_create() (via bli_l3_thread_decorator() and // bli_l3_cntl_create_if()). This allows us to access the schemas from // the control tree, which hopefully reduces some confusion, // particularly in bli_packm_init(). if ( bli_cntx_method( cntx ) == BLIS_NAT ) { bli_obj_set_pack_schema( BLIS_PACKED_ROW_PANELS, &a_local ); bli_obj_set_pack_schema( BLIS_PACKED_COL_PANELS, &b_local ); } else // if ( bli_cntx_method( cntx ) != BLIS_NAT ) { pack_t schema_a = bli_cntx_schema_a_block( cntx ); pack_t schema_b = bli_cntx_schema_b_panel( cntx ); bli_obj_set_pack_schema( schema_a, &a_local ); bli_obj_set_pack_schema( schema_b, &b_local ); } } // Parse and interpret the contents of the rntm_t object to properly // set the ways of parallelism for each loop, and then make any // additional modifications necessary for the current operation. bli_rntm_set_ways_for_op ( BLIS_GEMM, BLIS_LEFT, // ignored for gemm bli_obj_length( &c_local ), bli_obj_width( &c_local ), bli_obj_width( &a_local ), rntm ); // Invoke the internal back-end via the thread handler. blx_gemm_thread ( blx_gemm_int, BLIS_GEMM, // operation family id &a_local, &b_local, &c_local, cntx, rntm, cntl ); } blis-0.9.0/sandbox/old/ref99/old/blx_gemm_front.h000066400000000000000000000035141422157504600215650ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void blx_gemm_front ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl ); blis-0.9.0/sandbox/old/ref99/old/blx_gemm_int.c000066400000000000000000000047221422157504600212240ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "blix.h" void blx_gemm_int ( obj_t* a, obj_t* b, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ) { obj_t a_local; obj_t b_local; obj_t c_local; gemm_var_oft f; // Alias A, B, and C in case we need to update attached scalars. bli_obj_alias_to( a, &a_local ); bli_obj_alias_to( b, &b_local ); bli_obj_alias_to( c, &c_local ); // Create the next node in the thrinfo_t structure. bli_thrinfo_grow( rntm, cntl, thread ); // Extract the function pointer from the current control tree node. f = bli_cntl_var_func( cntl ); // Invoke the variant. f ( &a_local, &b_local, &c_local, cntx, rntm, cntl, thread ); } blis-0.9.0/sandbox/old/ref99/old/blx_gemm_int.h000066400000000000000000000034711422157504600212310ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void blx_gemm_int ( obj_t* a, obj_t* b, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ); blis-0.9.0/sandbox/old/ref99/old/cntl/000077500000000000000000000000001422157504600173475ustar00rootroot00000000000000blis-0.9.0/sandbox/old/ref99/old/cntl/blx_gemm_cntl.c000066400000000000000000000115161422157504600223310ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "blix.h" cntl_t* blx_gemm_cntl_create ( rntm_t* rntm, opid_t family, pack_t schema_a, pack_t schema_b ) { return blx_gemmbp_cntl_create( rntm, family, schema_a, schema_b ); } // ----------------------------------------------------------------------------- cntl_t* blx_gemmbp_cntl_create ( rntm_t* rntm, opid_t family, pack_t schema_a, pack_t schema_b ) { void_fp macro_kernel_fp; void_fp packa_fp; void_fp packb_fp; macro_kernel_fp = blx_gemm_ker_var2; packa_fp = bli_packm_blk_var1; packb_fp = bli_packm_blk_var1; // Create two nodes for the macro-kernel. cntl_t* gemm_cntl_bu_ke = blx_gemm_cntl_create_node ( rntm, // the thread's runtime structure family, // the operation family BLIS_MR, // needed for bli_thrinfo_rgrow() NULL, // variant function pointer not used NULL // no sub-node; this is the leaf of the tree. ); cntl_t* gemm_cntl_bp_bu = blx_gemm_cntl_create_node ( rntm, // the thread's runtime structure family, BLIS_NR, // not used by macro-kernel, but needed for bli_thrinfo_rgrow() macro_kernel_fp, gemm_cntl_bu_ke ); // Create a node for packing matrix A. cntl_t* gemm_cntl_packa = blx_packm_cntl_create_node ( rntm, blx_gemm_packa, // pack the left-hand operand packa_fp, BLIS_MR, BLIS_KR, FALSE, // do NOT invert diagonal FALSE, // reverse iteration if upper? FALSE, // reverse iteration if lower? schema_a, // normally BLIS_PACKED_ROW_PANELS BLIS_BUFFER_FOR_A_BLOCK, gemm_cntl_bp_bu ); // Create a node for partitioning the m dimension by MC. cntl_t* gemm_cntl_op_bp = blx_gemm_cntl_create_node ( rntm, family, BLIS_MC, blx_gemm_blk_var1, gemm_cntl_packa ); // Create a node for packing matrix B. cntl_t* gemm_cntl_packb = blx_packm_cntl_create_node ( rntm, blx_gemm_packb, // pack the right-hand operand packb_fp, BLIS_KR, BLIS_NR, FALSE, // do NOT invert diagonal FALSE, // reverse iteration if upper? FALSE, // reverse iteration if lower? schema_b, // normally BLIS_PACKED_COL_PANELS BLIS_BUFFER_FOR_B_PANEL, gemm_cntl_op_bp ); // Create a node for partitioning the k dimension by KC. cntl_t* gemm_cntl_mm_op = blx_gemm_cntl_create_node ( rntm, family, BLIS_KC, blx_gemm_blk_var3, gemm_cntl_packb ); // Create a node for partitioning the n dimension by NC. cntl_t* gemm_cntl_vl_mm = blx_gemm_cntl_create_node ( rntm, family, BLIS_NC, blx_gemm_blk_var2, gemm_cntl_mm_op ); return gemm_cntl_vl_mm; } // ----------------------------------------------------------------------------- void blx_gemm_cntl_free ( rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ) { bli_cntl_free( rntm, cntl, thread ); } // ----------------------------------------------------------------------------- cntl_t* blx_gemm_cntl_create_node ( rntm_t* rntm, opid_t family, bszid_t bszid, void_fp var_func, cntl_t* sub_node ) { return bli_cntl_create_node( rntm, family, bszid, var_func, NULL, sub_node ); } blis-0.9.0/sandbox/old/ref99/old/cntl/blx_gemm_cntl.h000066400000000000000000000046531422157504600223420ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ cntl_t* blx_gemm_cntl_create ( rntm_t* rntm, opid_t family, pack_t schema_a, pack_t schema_b ); // ----------------------------------------------------------------------------- cntl_t* blx_gemmbp_cntl_create ( rntm_t* rntm, opid_t family, pack_t schema_a, pack_t schema_b ); // ----------------------------------------------------------------------------- void blx_gemm_cntl_free ( rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ); // ----------------------------------------------------------------------------- cntl_t* blx_gemm_cntl_create_node ( rntm_t* rntm, opid_t family, bszid_t bszid, void_fp var_func, cntl_t* sub_node ); blis-0.9.0/sandbox/old/ref99/old/cntl/blx_l3_cntl_if.c000066400000000000000000000056451422157504600224060ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "blix.h" void blx_l3_cntl_create_if ( opid_t family, pack_t schema_a, pack_t schema_b, obj_t* a, obj_t* b, obj_t* c, rntm_t* rntm, cntl_t* cntl_orig, cntl_t** cntl_use ) { // If the control tree pointer is NULL, we construct a default // tree as a function of the operation family. if ( cntl_orig == NULL ) { *cntl_use = blx_gemm_cntl_create( family, schema_a, schema_b ); } else { // If the user provided a control tree, create a copy and use it // instead (so that threads can use its local tree as a place to // cache things like pack mem_t entries). *cntl_use = bli_cntl_copy( rntm, cntl_orig ); // Recursively set the family fields of the newly copied control tree // nodes. bli_cntl_mark_family( family, *cntl_use ); } } void blx_l3_cntl_free ( rntm_t rntm, cntl_t* cntl_use, thrinfo_t* thread ) { // If the control tree pointer is NULL, a default tree would have // been created, so we now must free it. if ( cntl_orig == NULL ) { blx_gemm_cntl_free( rntm, cntl_use, thread ); } else { // If the user provided a control tree, free the copy of it that // was created. bli_cntl_free( rntm, cntl_use ); } } blis-0.9.0/sandbox/old/ref99/old/cntl/blx_l3_cntl_if.h000066400000000000000000000037651422157504600224140ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void blx_l3_cntl_create_if ( opid_t family, pack_t schema_a, pack_t schema_b, obj_t* a, obj_t* b, obj_t* c, rntm_t* rntm, cntl_t* cntl_orig, cntl_t** cntl_use ); void blx_l3_cntl_free ( rntm_t rntm, cntl_t* cntl_use, thrinfo_t* thread ); blis-0.9.0/sandbox/old/ref99/old/cntl/blx_packm_cntl.c000066400000000000000000000057311422157504600225010ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" cntl_t* blx_packm_cntl_create_node ( rntm_t* rntm, void_fp var_func, void_fp packm_var_func, bszid_t bmid_m, bszid_t bmid_n, bool_t does_invert_diag, bool_t rev_iter_if_upper, bool_t rev_iter_if_lower, pack_t pack_schema, packbuf_t pack_buf_type, cntl_t* sub_node ) { cntl_t* cntl; packm_params_t* params; // Allocate a packm_params_t struct. params = bli_malloc_intl( sizeof( packm_params_t ) ); // Initialize the packm_params_t struct. params->size = sizeof( packm_params_t ); params->var_func = packm_var_func; params->bmid_m = bmid_m; params->bmid_n = bmid_n; params->does_invert_diag = does_invert_diag; params->rev_iter_if_upper = rev_iter_if_upper; params->rev_iter_if_lower = rev_iter_if_lower; params->pack_schema = pack_schema; params->pack_buf_type = pack_buf_type; // It's important that we set the bszid field to BLIS_NO_PART to indicate // that no blocksize partitioning is performed. bli_cntl_free() will rely // on this information to know how to step through the thrinfo_t tree in // sync with the cntl_t tree. cntl = bli_cntl_create_node ( BLIS_NOID, BLIS_NO_PART, var_func, params, sub_node ); return cntl; } blis-0.9.0/sandbox/old/ref99/old/cntl/blx_packm_cntl.h000066400000000000000000000040011422157504600224730ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ cntl_t* blx_packm_cntl_create_node ( rntm_t* rntm, void_fp var_func, void_fp packm_var_func, bszid_t bmid_m, bszid_t bmid_n, bool_t does_invert_diag, bool_t rev_iter_if_upper, bool_t rev_iter_if_lower, pack_t pack_schema, packbuf_t pack_buf_type, cntl_t* sub_node ); blis-0.9.0/sandbox/old/ref99/old/packm/000077500000000000000000000000001422157504600175025ustar00rootroot00000000000000blis-0.9.0/sandbox/old/ref99/old/packm/blx_l3_packm.c000066400000000000000000000130721422157504600222070ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "blix.h" void blx_l3_packm ( obj_t* x, obj_t* x_pack, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ) { pba_t* pba; packbuf_t pack_buf_type; mem_t* cntl_mem_p; siz_t size_needed; // FGVZ: Not sure why we need this barrier, but we do. bli_thread_barrier( thread ); // Every thread initializes x_pack and determines the size of memory // block needed (which gets embedded into the otherwise "blank" mem_t // entry in the control tree node). size_needed = bli_packm_init ( x, x_pack, cntx, cntl ); // If zero was returned, no memory needs to be allocated and so we can // return early. if ( size_needed == 0 ) return; // Query the memory broker from the context. pba = bli_cntx_get_pba( cntx ); // Query the pack buffer type from the control tree node. pack_buf_type = bli_cntl_packm_params_pack_buf_type( cntl ); // Query the address of the mem_t entry within the control tree node. cntl_mem_p = bli_cntl_pack_mem( cntl ); // Check the mem_t field in the control tree. If it is unallocated, then // we need to acquire a block from the memory broker and broadcast it to // all threads in the chief's thread group. if ( bli_mem_is_unalloc( cntl_mem_p ) ) { mem_t* local_mem_p; mem_t local_mem_s; if ( bli_thread_am_ochief( thread ) ) { // The chief thread acquires a block from the memory broker // and saves the associated mem_t entry to local_mem_s. bli_pba_acquire_m ( pba, size_needed, pack_buf_type, &local_mem_s ); } // Broadcast the address of the chief thread's local mem_t entry to // all threads. local_mem_p = bli_thread_broadcast( thread, &local_mem_s ); // Save the contents of the chief thread's local mem_t entry to the // mem_t field in this thread's control tree node. *cntl_mem_p = *local_mem_p; } else // ( bli_mem_is_alloc( cntl_mem_p ) ) { mem_t* local_mem_p; mem_t local_mem_s; // If the mem_t entry in the control tree does NOT contain a NULL // buffer, then a block has already been acquired from the memory // broker and cached in the control tree. // As a sanity check, we should make sure that the mem_t object isn't // associated with a block that is too small compared to the size of // the packed matrix buffer that is needed, according to the return // value from packm_init(). siz_t cntl_mem_size = bli_mem_size( cntl_mem_p ); if ( cntl_mem_size < size_needed ) { if ( bli_thread_am_ochief( thread ) ) { // The chief thread releases the existing block associated with // the mem_t entry in the control tree, and then re-acquires a // new block, saving the associated mem_t entry to local_mem_s. bli_pba_release( cntl_mem_p ); bli_pba_acquire_m ( pba, size_needed, pack_buf_type, &local_mem_s ); } // Broadcast the address of the chief thread's local mem_t entry to // all threads. local_mem_p = bli_thread_broadcast( thread, &local_mem_s ); // Save the chief thread's local mem_t entry to the mem_t field in // this thread's control tree node. *cntl_mem_p = *local_mem_p; } else { // If the mem_t entry is already allocated and sufficiently large, // then we use it as-is. No action is needed, because all threads // will already have the cached values in their local control // trees' mem_t entries, currently pointed to by cntl_mem_p. bli_thread_barrier( thread ); } } // Update the buffer address in x_pack to point to the buffer associated // with the mem_t entry acquired from the memory broker (now cached in // the control tree node). void* buf = bli_mem_buffer( cntl_mem_p ); bli_obj_set_buffer( buf, x_pack ); // Pack the contents of object x to object x_pack. bli_packm_int ( x, x_pack, cntx, cntl, thread ); // Barrier so that packing is done before computation. bli_thread_barrier( thread ); } blis-0.9.0/sandbox/old/ref99/old/packm/blx_l3_packm.h000066400000000000000000000034541422157504600222170ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void blx_l3_packm ( obj_t* x, obj_t* x_pack, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ); blis-0.9.0/sandbox/old/ref99/old/thread/000077500000000000000000000000001422157504600176565ustar00rootroot00000000000000blis-0.9.0/sandbox/old/ref99/old/thread/blx_gemm_thread.c000066400000000000000000000220471422157504600231500ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "blix.h" // This code is enabled only when multithreading is enabled via OpenMP. #ifdef BLIS_ENABLE_OPENMP #if 0 void blx_gemm_thread ( gemmint_t func, opid_t family, obj_t* a, obj_t* b, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl ) { // Query the total number of threads from the context. dim_t n_threads = bli_rntm_num_threads( rntm ); // Allcoate a global communicator for the root thrinfo_t structures. thrcomm_t* gl_comm = bli_thrcomm_create( n_threads ); _Pragma( "omp parallel num_threads(n_threads)" ) { dim_t id = omp_get_thread_num(); obj_t a_t, b_t, c_t; cntl_t* cntl_use; thrinfo_t* thread; // Alias thread-local copies of A, B, and C. These will be the objects // we pass down the algorithmic function stack. Making thread-local // alaises IS ABSOLUTELY IMPORTANT and MUST BE DONE because each thread // will read the schemas from A and B and then reset the schemas to // their expected unpacked state (in blx_l3_cntl_create_if()). bli_obj_alias_to( a, &a_t ); bli_obj_alias_to( b, &b_t ); bli_obj_alias_to( c, &c_t ); // Create a default control tree for the operation, if needed. blx_l3_cntl_create_if( family, &a_t, &b_t, &c_t, cntl, &cntl_use ); // Create the root node of the current thread's thrinfo_t structure. bli_l3_thrinfo_create_root( id, gl_comm, rntm, cntl_use, &thread ); func ( &a_t, &b_t, &c_t, cntx, rntm, cntl_use, thread ); // Free the control tree, if one was created locally. blx_l3_cntl_free_if( &a_t, &b_t, &c_t, cntl, cntl_use, thread ); // Free the current thread's thrinfo_t structure. bli_l3_thrinfo_free( thread ); } // We shouldn't free the global communicator since it was already freed // by the global communicator's chief thread in bli_l3_thrinfo_free() // (called above). } #endif void blx_gemm_thread ( gemmint_t func, opid_t family, obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl ) { // This is part of a hack to support mixed domain in bli_gemm_front(). // Sometimes we need to specify a non-standard schema for A and B, and // we decided to transmit them via the schema field in the obj_t's // rather than pass them in as function parameters. Once the values // have been read, we immediately reset them back to their expected // values for unpacked objects. pack_t schema_a = bli_obj_pack_schema( a ); pack_t schema_b = bli_obj_pack_schema( b ); bli_obj_set_pack_schema( BLIS_NOT_PACKED, a ); bli_obj_set_pack_schema( BLIS_NOT_PACKED, b ); // Query the total number of threads from the rntm_t object. const dim_t n_threads = bli_rntm_num_threads( rntm ); // NOTE: The sba was initialized in bli_init(). // Check out an array_t from the small block allocator. This is done // with an internal lock to ensure only one application thread accesses // the sba at a time. bli_sba_checkout_array() will also automatically // resize the array_t, if necessary. array_t* restrict array = bli_sba_checkout_array( n_threads ); // Access the pool_t* for thread 0 and embed it into the rntm. We do // this up-front only so that we have the rntm_t.sba_pool field // initialized and ready for the global communicator creation below. bli_sba_rntm_set_pool( 0, array, rntm ); // Set the packing block allocator field of the rntm. This will be // inherited by all of the child threads when they make local copies of // the rntm below. bli_pba_rntm_set_pba( rntm ); // Allocate a global communicator for the root thrinfo_t structures. thrcomm_t* restrict gl_comm = bli_thrcomm_create( rntm, n_threads ); _Pragma( "omp parallel num_threads(n_threads)" ) { // Create a thread-local copy of the master thread's rntm_t. This is // necessary since we want each thread to be able to track its own // small block pool_t as it executes down the function stack. rntm_t rntm_l = *rntm; rntm_t* restrict rntm_p = &rntm_l; // Query the thread's id from OpenMP. const dim_t tid = omp_get_thread_num(); // Check for a somewhat obscure OpenMP thread-mistmatch issue. //bli_l3_thread_decorator_thread_check( n_threads, tid, gl_comm, rntm_p ); // Use the thread id to access the appropriate pool_t* within the // array_t, and use it to set the sba_pool field within the rntm_t. // If the pool_t* element within the array_t is NULL, it will first // be allocated/initialized. bli_sba_rntm_set_pool( tid, array, rntm_p ); obj_t a_t, b_t, c_t; cntl_t* cntl_use; thrinfo_t* thread; // Alias thread-local copies of A, B, and C. These will be the objects // we pass down the algorithmic function stack. Making thread-local // aliases is highly recommended in case a thread needs to change any // of the properties of an object without affecting other threads' // objects. bli_obj_alias_to( a, &a_t ); bli_obj_alias_to( b, &b_t ); bli_obj_alias_to( c, &c_t ); // Create a default control tree for the operation, if needed. blx_l3_cntl_create_if( family, schema_a, schema_b, &a_t, &b_t, &c_t, rntm_p, cntl, &cntl_use ); // Create the root node of the current thread's thrinfo_t structure. blx_l3_thrinfo_create_root( tid, gl_comm, rntm_p, cntl_use, &thread ); func ( alpha, &a_t, &b_t, beta, &c_t, cntx, rntm_p, cntl_use, thread ); // Free the thread's local control tree. blx_l3_cntl_free( rntm_p, cntl_use, thread ); // Free the current thread's thrinfo_t structure. bli_l3_thrinfo_free( rntm_p, thread ); } // We shouldn't free the global communicator since it was already freed // by the global communicator's chief thread in bli_l3_thrinfo_free() // (called above). // Check the array_t back into the small block allocator. Similar to the // check-out, this is done using a lock embedded within the sba to ensure // mutual exclusion. bli_sba_checkin_array( array ); } #endif #ifdef BLIS_ENABLE_PTHREADS #error "Sandbox does not yet implement pthreads." #endif // This code is enabled only when multithreading is disabled. #ifndef BLIS_ENABLE_MULTITHREADING void blx_gemm_thread ( gemmint_t func, opid_t family, obj_t* a, obj_t* b, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl ) { // For sequential execution, we use only one thread. dim_t n_threads = 1; dim_t id = 0; // Allcoate a global communicator for the root thrinfo_t structures. thrcomm_t* gl_comm = bli_thrcomm_create( n_threads ); cntl_t* cntl_use; thrinfo_t* thread; // Create a default control tree for the operation, if needed. blx_l3_cntl_create_if( family, a, b, c, cntl, &cntl_use ); // Create the root node of the thread's thrinfo_t structure. bli_l3_thrinfo_create_root( id, gl_comm, rntm, cntl_use, &thread ); func ( a, b, c, cntx, rntm, cntl_use, thread ); // Free the control tree, if one was created locally. blx_l3_cntl_free_if( a, b, c, cntl, cntl_use, thread ); // Free the current thread's thrinfo_t structure. bli_l3_thrinfo_free( thread ); // We shouldn't free the global communicator since it was already freed // by the global communicator's chief thread in bli_l3_thrinfo_free() // (called above). } #endif blis-0.9.0/sandbox/old/ref99/old/thread/blx_gemm_thread.h000066400000000000000000000041701422157504600231520ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // gemm internal function type typedef void (*gemmint_t) ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ); void blx_gemm_thread ( gemmint_t func, opid_t family, obj_t* a, obj_t* b, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl ); blis-0.9.0/sandbox/old/ref99/old/vars/000077500000000000000000000000001422157504600173625ustar00rootroot00000000000000blis-0.9.0/sandbox/old/ref99/old/vars/blx_gemm_blk_var1.c000066400000000000000000000053071422157504600231060ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "blix.h" void blx_gemm_blk_var1 ( obj_t* a, obj_t* b, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ) { obj_t a1, c1; dim_t i; dim_t b_alg; dim_t my_start, my_end; // Determine the current thread's subpartition range. bli_thread_range_mdim ( BLIS_FWD, thread, a, b, c, cntl, cntx, &my_start, &my_end ); // Partition along the m dimension. for ( i = my_start; i < my_end; i += b_alg ) { // Determine the current algorithmic blocksize. b_alg = blx_determine_blocksize_f( i, my_end, c, bli_cntl_bszid( cntl ), cntx ); // Acquire partitions for A1 and C1. bli_acquire_mpart_mdim( BLIS_FWD, BLIS_SUBPART1, i, b_alg, a, &a1 ); bli_acquire_mpart_mdim( BLIS_FWD, BLIS_SUBPART1, i, b_alg, c, &c1 ); // Perform gemm subproblem. blx_gemm_int ( &a1, b, &c1, cntx, rntm, bli_cntl_sub_node( cntl ), bli_thrinfo_sub_node( thread ) ); } } blis-0.9.0/sandbox/old/ref99/old/vars/blx_gemm_blk_var2.c000066400000000000000000000053071422157504600231070ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "blix.h" void blx_gemm_blk_var2 ( obj_t* a, obj_t* b, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ) { obj_t b1, c1; dim_t i; dim_t b_alg; dim_t my_start, my_end; // Determine the current thread's subpartition range. bli_thread_range_ndim ( BLIS_FWD, thread, a, b, c, cntl, cntx, &my_start, &my_end ); // Partition along the n dimension. for ( i = my_start; i < my_end; i += b_alg ) { // Determine the current algorithmic blocksize. b_alg = blx_determine_blocksize_f( i, my_end, c, bli_cntl_bszid( cntl ), cntx ); // Acquire partitions for B1 and C1. bli_acquire_mpart_ndim( BLIS_FWD, BLIS_SUBPART1, i, b_alg, b, &b1 ); bli_acquire_mpart_ndim( BLIS_FWD, BLIS_SUBPART1, i, b_alg, c, &c1 ); // Perform gemm subproblem. blx_gemm_int ( a, &b1, &c1, cntx, rntm, bli_cntl_sub_node( cntl ), bli_thrinfo_sub_node( thread ) ); } } blis-0.9.0/sandbox/old/ref99/old/vars/blx_gemm_blk_var3.c000066400000000000000000000060331422157504600231050ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "blix.h" void blx_gemm_blk_var3 ( obj_t* a, obj_t* b, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ) { obj_t a1, b1; dim_t i; dim_t b_alg; dim_t k_trans; // Query dimension in partitioning direction. k_trans = bli_obj_width_after_trans( a ); // Partition along the k dimension. for ( i = 0; i < k_trans; i += b_alg ) { // Determine the current algorithmic blocksize. b_alg = blx_determine_blocksize_f( i, k_trans, c, bli_cntl_bszid( cntl ), cntx ); // Acquire partitions for A1 and B1. bli_acquire_mpart_ndim( BLIS_FWD, BLIS_SUBPART1, i, b_alg, a, &a1 ); bli_acquire_mpart_mdim( BLIS_FWD, BLIS_SUBPART1, i, b_alg, b, &b1 ); // Perform gemm subproblem. blx_gemm_int ( &a1, &b1, c, cntx, rntm, bli_cntl_sub_node( cntl ), bli_thrinfo_sub_node( thread ) ); bli_thread_barrier( bli_thrinfo_sub_node( thread ) ); // This variant executes multiple rank-k updates. Therefore, if the // internal beta scalar on matrix C is non-zero, we must use it // only for the first iteration (and then BLIS_ONE for all others). // And since c is a locally aliased obj_t, we can simply overwrite // the internal beta scalar with BLIS_ONE once it has been used in // the first iteration. if ( i == 0 ) bli_obj_scalar_reset( c ); } } blis-0.9.0/sandbox/old/ref99/old/vars/blx_gemm_ker_var2.c000066400000000000000000000265151422157504600231240ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "blix.h" // Function pointer type for datatype-specific functions. typedef void (*gemm_fp) ( pack_t schema_a, pack_t schema_b, dim_t m, dim_t n, dim_t k, void* alpha, void* a, inc_t cs_a, inc_t is_a, dim_t pd_a, inc_t ps_a, void* b, inc_t rs_b, inc_t is_b, dim_t pd_b, inc_t ps_b, void* beta, void* c, inc_t rs_c, inc_t cs_c, cntx_t* cntx, rntm_t* rntm, thrinfo_t* thread ); // Function pointer array for datatype-specific functions. static gemm_fp ftypes[BLIS_NUM_FP_TYPES] = { PASTECH2(blx_,s,gemm_ker_var2), PASTECH2(blx_,c,gemm_ker_var2), PASTECH2(blx_,d,gemm_ker_var2), PASTECH2(blx_,z,gemm_ker_var2) }; void blx_gemm_ker_var2 ( obj_t* a, obj_t* b, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ) { num_t dt_exec = bli_obj_exec_dt( c ); pack_t schema_a = bli_obj_pack_schema( a ); pack_t schema_b = bli_obj_pack_schema( b ); dim_t m = bli_obj_length( c ); dim_t n = bli_obj_width( c ); dim_t k = bli_obj_width( a ); void* buf_a = bli_obj_buffer_at_off( a ); inc_t cs_a = bli_obj_col_stride( a ); inc_t is_a = bli_obj_imag_stride( a ); dim_t pd_a = bli_obj_panel_dim( a ); inc_t ps_a = bli_obj_panel_stride( a ); void* buf_b = bli_obj_buffer_at_off( b ); inc_t rs_b = bli_obj_row_stride( b ); inc_t is_b = bli_obj_imag_stride( b ); dim_t pd_b = bli_obj_panel_dim( b ); inc_t ps_b = bli_obj_panel_stride( b ); void* buf_c = bli_obj_buffer_at_off( c ); inc_t rs_c = bli_obj_row_stride( c ); inc_t cs_c = bli_obj_col_stride( c ); obj_t scalar_a; obj_t scalar_b; void* buf_alpha; void* buf_beta; gemm_fp f; // Detach and multiply the scalars attached to A and B. bli_obj_scalar_detach( a, &scalar_a ); bli_obj_scalar_detach( b, &scalar_b ); bli_mulsc( &scalar_a, &scalar_b ); // Grab the addresses of the internal scalar buffers for the scalar // merged above and the scalar attached to C. buf_alpha = bli_obj_internal_scalar_buffer( &scalar_b ); buf_beta = bli_obj_internal_scalar_buffer( c ); // Index into the type combination array to extract the correct // function pointer. f = ftypes[dt_exec]; // Invoke the function. f( schema_a, schema_b, m, n, k, buf_alpha, buf_a, cs_a, is_a, pd_a, ps_a, buf_b, rs_b, is_b, pd_b, ps_b, buf_beta, buf_c, rs_c, cs_c, cntx, rntm, thread ); } #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTECH2(blx_,ch,varname) \ ( \ pack_t schema_a, \ pack_t schema_b, \ dim_t m, \ dim_t n, \ dim_t k, \ void* alpha, \ void* a, inc_t cs_a, inc_t is_a, \ dim_t pd_a, inc_t ps_a, \ void* b, inc_t rs_b, inc_t is_b, \ dim_t pd_b, inc_t ps_b, \ void* beta, \ void* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx, \ rntm_t* rntm, \ thrinfo_t* thread \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ /* Alias some constants to simpler names. */ \ const dim_t MR = pd_a; \ const dim_t NR = pd_b; \ /*const dim_t PACKMR = cs_a;*/ \ /*const dim_t PACKNR = rs_b;*/ \ \ /* Query the context for the micro-kernel address and cast it to its function pointer type. */ \ PASTECH(ch,gemm_ukr_ft) \ gemm_ukr = bli_cntx_get_l3_vir_ukr_dt( dt, BLIS_GEMM_UKR, cntx ); \ \ /* Temporary C buffer for edge cases. Note that the strides of this temporary buffer are set so that they match the storage of the original C matrix. For example, if C is column-stored, ct will be column-stored as well. */ \ ctype ct[ BLIS_STACK_BUF_MAX_SIZE \ / sizeof( ctype ) ] \ __attribute__((aligned(BLIS_STACK_BUF_ALIGN_SIZE))); \ const bool_t col_pref = bli_cntx_l3_vir_ukr_prefers_cols_dt( dt, BLIS_GEMM_UKR, cntx ); \ const inc_t rs_ct = ( col_pref ? 1 : NR ); \ const inc_t cs_ct = ( col_pref ? MR : 1 ); \ \ ctype* restrict zero = PASTEMAC(ch,0); \ ctype* restrict a_cast = a; \ ctype* restrict b_cast = b; \ ctype* restrict c_cast = c; \ ctype* restrict alpha_cast = alpha; \ ctype* restrict beta_cast = beta; \ ctype* restrict b1; \ ctype* restrict c1; \ \ dim_t m_iter, m_left; \ dim_t n_iter, n_left; \ dim_t i, j; \ dim_t m_cur; \ dim_t n_cur; \ inc_t rstep_a; \ inc_t cstep_b; \ inc_t rstep_c, cstep_c; \ auxinfo_t aux; \ \ /* Assumptions/assertions: rs_a == 1 cs_a == PACKMR pd_a == MR ps_a == stride to next micro-panel of A rs_b == PACKNR cs_b == 1 pd_b == NR ps_b == stride to next micro-panel of B rs_c == (no assumptions) cs_c == (no assumptions) */ \ \ /* If any dimension is zero, return immediately. */ \ if ( bli_zero_dim3( m, n, k ) ) return; \ \ /* Clear the temporary C buffer in case it has any infs or NaNs. */ \ PASTEMAC(ch,set0s_mxn)( MR, NR, \ ct, rs_ct, cs_ct ); \ \ /* Compute number of primary and leftover components of the m and n dimensions. */ \ n_iter = n / NR; \ n_left = n % NR; \ \ m_iter = m / MR; \ m_left = m % MR; \ \ if ( n_left ) ++n_iter; \ if ( m_left ) ++m_iter; \ \ /* Determine some increments used to step through A, B, and C. */ \ rstep_a = ps_a; \ \ cstep_b = ps_b; \ \ rstep_c = rs_c * MR; \ cstep_c = cs_c * NR; \ \ /* Save the pack schemas of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_schema_a( schema_a, &aux ); \ bli_auxinfo_set_schema_b( schema_b, &aux ); \ \ /* Save the imaginary stride of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_is_a( is_a, &aux ); \ bli_auxinfo_set_is_b( is_b, &aux ); \ \ /* Save the desired output datatype (indicating no typecasting). */ \ /*bli_auxinfo_set_dt_on_output( dt, &aux );*/ \ \ /* The 'thread' argument points to the thrinfo_t node for the 2nd (jr) loop around the microkernel. Here we query the thrinfo_t node for the 1st (ir) loop around the microkernel. */ \ thrinfo_t* caucus = bli_thrinfo_sub_node( thread ); \ \ /* Query the number of threads and thread ids for each loop. */ \ dim_t jr_nt = bli_thread_n_way( thread ); \ dim_t jr_tid = bli_thread_work_id( thread ); \ dim_t ir_nt = bli_thread_n_way( caucus ); \ dim_t ir_tid = bli_thread_work_id( caucus ); \ \ dim_t jr_start, jr_end; \ dim_t ir_start, ir_end; \ dim_t jr_inc, ir_inc; \ \ /* Determine the thread range and increment for the 2nd and 1st loops. NOTE: The definition of bli_thread_range_jrir() will depend on whether slab or round-robin partitioning was requested at configure-time. */ \ bli_thread_range_jrir( thread, n_iter, 1, FALSE, &jr_start, &jr_end, &jr_inc ); \ bli_thread_range_jrir( caucus, m_iter, 1, FALSE, &ir_start, &ir_end, &ir_inc ); \ \ /* Loop over the n dimension (NR columns at a time). */ \ for ( j = jr_start; j < jr_end; j += jr_inc ) \ { \ ctype* restrict a1; \ ctype* restrict c11; \ ctype* restrict b2; \ \ b1 = b_cast + j * cstep_b; \ c1 = c_cast + j * cstep_c; \ \ n_cur = ( bli_is_not_edge_f( j, n_iter, n_left ) ? NR : n_left ); \ \ /* Initialize our next panel of B to be the current panel of B. */ \ b2 = b1; \ \ /* Loop over the m dimension (MR rows at a time). */ \ for ( i = ir_start; i < ir_end; i += ir_inc ) \ { \ ctype* restrict a2; \ \ a1 = a_cast + i * rstep_a; \ c11 = c1 + i * rstep_c; \ \ m_cur = ( bli_is_not_edge_f( i, m_iter, m_left ) ? MR : m_left ); \ \ /* Compute the addresses of the next panels of A and B. */ \ a2 = bli_gemm_get_next_a_upanel( a1, rstep_a, ir_inc ); \ if ( bli_is_last_iter( i, ir_end, ir_tid, ir_nt ) ) \ { \ a2 = a_cast; \ b2 = bli_gemm_get_next_b_upanel( b1, cstep_b, jr_inc ); \ if ( bli_is_last_iter( j, jr_end, jr_tid, jr_nt ) ) \ b2 = b_cast; \ } \ \ /* Save addresses of next panels of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_next_a( a2, &aux ); \ bli_auxinfo_set_next_b( b2, &aux ); \ \ /* Handle interior and edge cases separately. */ \ if ( m_cur == MR && n_cur == NR ) \ { \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k, \ alpha_cast, \ a1, \ b1, \ beta_cast, \ c11, rs_c, cs_c, \ &aux, \ cntx \ ); \ } \ else \ { \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k, \ alpha_cast, \ a1, \ b1, \ zero, \ ct, rs_ct, cs_ct, \ &aux, \ cntx \ ); \ \ /* Scale the bottom edge of C and add the result from above. */ \ PASTEMAC(ch,xpbys_mxn)( m_cur, n_cur, \ ct, rs_ct, cs_ct, \ beta_cast, \ c11, rs_c, cs_c ); \ } \ } \ } \ \ /* PASTEMAC(ch,fprintm)( stdout, "gemm_ker_var2: b1", k, NR, b1, NR, 1, "%4.1f", "" ); \ PASTEMAC(ch,fprintm)( stdout, "gemm_ker_var2: a1", MR, k, a1, 1, MR, "%4.1f", "" ); \ PASTEMAC(ch,fprintm)( stdout, "gemm_ker_var2: c after", m_cur, n_cur, c11, rs_c, cs_c, "%4.1f", "" ); \ */ \ } #if 0 GENTFUNC( float, s, gemm_ker_var2 ) GENTFUNC( double, d, gemm_ker_var2 ) GENTFUNC( scomplex, c, gemm_ker_var2 ) GENTFUNC( dcomplex, z, gemm_ker_var2 ) #else INSERT_GENTFUNC_BASIC0( gemm_ker_var2 ) #endif blis-0.9.0/sandbox/old/ref99/old/vars/blx_gemm_packab.c000066400000000000000000000053621422157504600226270ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "blix.h" void blx_gemm_packa ( obj_t* a, obj_t* b, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ) { obj_t a_pack; // Pack matrix A according to the control tree node. blx_l3_packm ( a, &a_pack, cntx, rntm, cntl, thread ); // Proceed with execution using packed matrix A. blx_gemm_int ( &a_pack, b, c, cntx, rntm, bli_cntl_sub_node( cntl ), bli_thrinfo_sub_node( thread ) ); } // ----------------------------------------------------------------------------- void blx_gemm_packb ( obj_t* a, obj_t* b, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ) { obj_t b_pack; // Pack matrix B according to the control tree node. blx_l3_packm ( b, &b_pack, cntx, rntm, cntl, thread ); // Proceed with execution using packed matrix B. blx_gemm_int ( a, &b_pack, c, cntx, rntm, bli_cntl_sub_node( cntl ), bli_thrinfo_sub_node( thread ) ); } blis-0.9.0/sandbox/old/ref99/old/vars/blx_gemm_var.h000066400000000000000000000054411422157504600222010ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // Prototype object-based interfaces. // #undef GENPROT #define GENPROT( opname ) \ \ void PASTECH(blx_,opname) \ ( \ obj_t* a, \ obj_t* b, \ obj_t* c, \ cntx_t* cntx, \ rntm_t* rntm, \ cntl_t* cntl, \ thrinfo_t* thread \ ); GENPROT( gemm_blk_var1 ) GENPROT( gemm_blk_var2 ) GENPROT( gemm_blk_var3 ) GENPROT( gemm_packa ) GENPROT( gemm_packb ) GENPROT( gemm_ker_var2 ) // // Prototype BLAS-like interfaces with void pointer operands. // #undef GENTPROT #define GENTPROT( ctype, ch, varname ) \ \ void PASTECH2(blx_,ch,varname) \ ( \ pack_t schema_a, \ pack_t schema_b, \ dim_t m, \ dim_t n, \ dim_t k, \ void* alpha, \ void* a, inc_t cs_a, inc_t is_a, \ dim_t pd_a, inc_t ps_a, \ void* b, inc_t rs_b, inc_t is_b, \ dim_t pd_b, inc_t ps_b, \ void* beta, \ void* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx, \ rntm_t* rntm, \ thrinfo_t* thread \ ); INSERT_GENTPROT_BASIC0( gemm_ker_var2 ) blis-0.9.0/sandbox/old/ref99/old/vars/other/000077500000000000000000000000001422157504600205035ustar00rootroot00000000000000blis-0.9.0/sandbox/old/ref99/old/vars/other/blx_gemm_ker_var2rr.c000066400000000000000000000261401422157504600246030ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "blix.h" // Function pointer type for datatype-specific functions. typedef void (*gemm_fp) ( pack_t schema_a, pack_t schema_b, dim_t m, dim_t n, dim_t k, void* alpha, void* a, inc_t cs_a, inc_t is_a, dim_t pd_a, inc_t ps_a, void* b, inc_t rs_b, inc_t is_b, dim_t pd_b, inc_t ps_b, void* beta, void* c, inc_t rs_c, inc_t cs_c, cntx_t* cntx, rntm_t* rntm, thrinfo_t* thread ); // Function pointer array for datatype-specific functions. static gemm_fp ftypes[BLIS_NUM_FP_TYPES] = { PASTECH2(blx_,s,gemm_ker_var2rr), PASTECH2(blx_,c,gemm_ker_var2rr), PASTECH2(blx_,d,gemm_ker_var2rr), PASTECH2(blx_,z,gemm_ker_var2rr) }; void blx_gemm_ker_var2rr ( obj_t* a, obj_t* b, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ) { num_t dt_exec = bli_obj_exec_dt( c ); pack_t schema_a = bli_obj_pack_schema( a ); pack_t schema_b = bli_obj_pack_schema( b ); dim_t m = bli_obj_length( c ); dim_t n = bli_obj_width( c ); dim_t k = bli_obj_width( a ); void* buf_a = bli_obj_buffer_at_off( a ); inc_t cs_a = bli_obj_col_stride( a ); inc_t is_a = bli_obj_imag_stride( a ); dim_t pd_a = bli_obj_panel_dim( a ); inc_t ps_a = bli_obj_panel_stride( a ); void* buf_b = bli_obj_buffer_at_off( b ); inc_t rs_b = bli_obj_row_stride( b ); inc_t is_b = bli_obj_imag_stride( b ); dim_t pd_b = bli_obj_panel_dim( b ); inc_t ps_b = bli_obj_panel_stride( b ); void* buf_c = bli_obj_buffer_at_off( c ); inc_t rs_c = bli_obj_row_stride( c ); inc_t cs_c = bli_obj_col_stride( c ); obj_t scalar_a; obj_t scalar_b; void* buf_alpha; void* buf_beta; gemm_fp f; // Detach and multiply the scalars attached to A and B. bli_obj_scalar_detach( a, &scalar_a ); bli_obj_scalar_detach( b, &scalar_b ); bli_mulsc( &scalar_a, &scalar_b ); // Grab the addresses of the internal scalar buffers for the scalar // merged above and the scalar attached to C. buf_alpha = bli_obj_internal_scalar_buffer( &scalar_b ); buf_beta = bli_obj_internal_scalar_buffer( c ); // Index into the type combination array to extract the correct // function pointer. f = ftypes[dt_exec]; // Invoke the function. f( schema_a, schema_b, m, n, k, buf_alpha, buf_a, cs_a, is_a, pd_a, ps_a, buf_b, rs_b, is_b, pd_b, ps_b, buf_beta, buf_c, rs_c, cs_c, cntx, rntm, thread ); } #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTECH2(blx_,ch,varname) \ ( \ pack_t schema_a, \ pack_t schema_b, \ dim_t m, \ dim_t n, \ dim_t k, \ void* alpha, \ void* a, inc_t cs_a, inc_t is_a, \ dim_t pd_a, inc_t ps_a, \ void* b, inc_t rs_b, inc_t is_b, \ dim_t pd_b, inc_t ps_b, \ void* beta, \ void* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx, \ rntm_t* rntm, \ thrinfo_t* thread \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ /* Alias some constants to simpler names. */ \ const dim_t MR = pd_a; \ const dim_t NR = pd_b; \ /*const dim_t PACKMR = cs_a;*/ \ /*const dim_t PACKNR = rs_b;*/ \ \ /* Query the context for the micro-kernel address and cast it to its function pointer type. */ \ PASTECH(ch,gemm_ukr_ft) \ gemm_ukr = bli_cntx_get_l3_vir_ukr_dt( dt, BLIS_GEMM_UKR, cntx ); \ \ /* Temporary C buffer for edge cases. Note that the strides of this temporary buffer are set so that they match the storage of the original C matrix. For example, if C is column-stored, ct will be column-stored as well. */ \ ctype ct[ BLIS_STACK_BUF_MAX_SIZE \ / sizeof( ctype ) ] \ __attribute__((aligned(BLIS_STACK_BUF_ALIGN_SIZE))); \ const bool_t col_pref = bli_cntx_l3_vir_ukr_prefers_cols_dt( dt, BLIS_GEMM_UKR, cntx ); \ const inc_t rs_ct = ( col_pref ? 1 : NR ); \ const inc_t cs_ct = ( col_pref ? MR : 1 ); \ \ ctype* restrict zero = PASTEMAC(ch,0); \ ctype* restrict a_cast = a; \ ctype* restrict b_cast = b; \ ctype* restrict c_cast = c; \ ctype* restrict alpha_cast = alpha; \ ctype* restrict beta_cast = beta; \ ctype* restrict b1; \ ctype* restrict c1; \ \ dim_t m_iter, m_left; \ dim_t n_iter, n_left; \ dim_t i, j; \ dim_t m_cur; \ dim_t n_cur; \ inc_t rstep_a; \ inc_t cstep_b; \ inc_t rstep_c, cstep_c; \ auxinfo_t aux; \ \ /* Assumptions/assertions: rs_a == 1 cs_a == PACKMR pd_a == MR ps_a == stride to next micro-panel of A rs_b == PACKNR cs_b == 1 pd_b == NR ps_b == stride to next micro-panel of B rs_c == (no assumptions) cs_c == (no assumptions) */ \ \ /* If any dimension is zero, return immediately. */ \ if ( bli_zero_dim3( m, n, k ) ) return; \ \ /* Clear the temporary C buffer in case it has any infs or NaNs. */ \ PASTEMAC(ch,set0s_mxn)( MR, NR, \ ct, rs_ct, cs_ct ); \ \ /* Compute number of primary and leftover components of the m and n dimensions. */ \ n_iter = n / NR; \ n_left = n % NR; \ \ m_iter = m / MR; \ m_left = m % MR; \ \ if ( n_left ) ++n_iter; \ if ( m_left ) ++m_iter; \ \ /* Determine some increments used to step through A, B, and C. */ \ rstep_a = ps_a; \ \ cstep_b = ps_b; \ \ rstep_c = rs_c * MR; \ cstep_c = cs_c * NR; \ \ /* Save the pack schemas of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_schema_a( schema_a, &aux ); \ bli_auxinfo_set_schema_b( schema_b, &aux ); \ \ /* Save the imaginary stride of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_is_a( is_a, &aux ); \ bli_auxinfo_set_is_b( is_b, &aux ); \ \ /* The 'thread' argument points to the thrinfo_t node for the 2nd (jr) loop around the microkernel. Here we query the thrinfo_t node for the 1st (ir) loop around the microkernel. */ \ thrinfo_t* caucus = bli_thrinfo_sub_node( thread ); \ \ /* Query the number of threads and thread ids for each loop. */ \ dim_t jr_nt = bli_thread_n_way( thread ); \ dim_t jr_tid = bli_thread_work_id( thread ); \ dim_t ir_nt = bli_thread_n_way( caucus ); \ dim_t ir_tid = bli_thread_work_id( caucus ); \ \ dim_t jr_start, jr_end; \ dim_t ir_start, ir_end; \ dim_t jr_inc, ir_inc; \ \ /* Determine the thread range and increment for each thrinfo_t node. */ \ bli_thread_range_jrir_rr( thread, n_iter, 1, FALSE, &jr_start, &jr_end, &jr_inc ); \ bli_thread_range_jrir_rr( caucus, m_iter, 1, FALSE, &ir_start, &ir_end, &ir_inc ); \ \ /* Loop over the n dimension (NR columns at a time). */ \ for ( j = jr_start; j < jr_end; j += jr_inc ) \ { \ ctype* restrict a1; \ ctype* restrict c11; \ ctype* restrict b2; \ \ b1 = b_cast + j * cstep_b; \ c1 = c_cast + j * cstep_c; \ \ n_cur = ( bli_is_not_edge_f( j, n_iter, n_left ) ? NR : n_left ); \ \ /* Initialize our next panel of B to be the current panel of B. */ \ b2 = b1; \ \ /* Loop over the m dimension (MR rows at a time). */ \ for ( i = ir_start; i < ir_end; i += ir_inc ) \ { \ ctype* restrict a2; \ \ a1 = a_cast + i * rstep_a; \ c11 = c1 + i * rstep_c; \ \ m_cur = ( bli_is_not_edge_f( i, m_iter, m_left ) ? MR : m_left ); \ \ /* Compute the addresses of the next panels of A and B. */ \ a2 = bli_gemm_get_next_a_upanel( a1, rstep_a, ir_inc ); \ if ( bli_is_last_iter_rr( i, ir_end, ir_tid, ir_nt ) ) \ { \ a2 = a_cast; \ b2 = bli_gemm_get_next_b_upanel( b1, cstep_b, jr_inc ); \ if ( bli_is_last_iter_rr( j, jr_end, jr_tid, jr_nt ) ) \ b2 = b_cast; \ } \ \ /* Save addresses of next panels of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_next_a( a2, &aux ); \ bli_auxinfo_set_next_b( b2, &aux ); \ \ /* Handle interior and edge cases separately. */ \ if ( m_cur == MR && n_cur == NR ) \ { \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k, \ alpha_cast, \ a1, \ b1, \ beta_cast, \ c11, rs_c, cs_c, \ &aux, \ cntx \ ); \ } \ else \ { \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k, \ alpha_cast, \ a1, \ b1, \ zero, \ ct, rs_ct, cs_ct, \ &aux, \ cntx \ ); \ \ /* Scale the bottom edge of C and add the result from above. */ \ PASTEMAC(ch,xpbys_mxn)( m_cur, n_cur, \ ct, rs_ct, cs_ct, \ beta_cast, \ c11, rs_c, cs_c ); \ } \ } \ } \ \ /* PASTEMAC(ch,fprintm)( stdout, "gemm_ker_var2: b1", k, NR, b1, NR, 1, "%4.1f", "" ); \ PASTEMAC(ch,fprintm)( stdout, "gemm_ker_var2: a1", MR, k, a1, 1, MR, "%4.1f", "" ); \ PASTEMAC(ch,fprintm)( stdout, "gemm_ker_var2: c after", m_cur, n_cur, c11, rs_c, cs_c, "%4.1f", "" ); \ */ \ } #if 0 GENTFUNC( float, s, gemm_ker_var2rr ) GENTFUNC( double, d, gemm_ker_var2rr ) GENTFUNC( scomplex, c, gemm_ker_var2rr ) GENTFUNC( dcomplex, z, gemm_ker_var2rr ) #else INSERT_GENTFUNC_BASIC0( gemm_ker_var2rr ) #endif blis-0.9.0/sandbox/old/ref99/old/vars/other/blx_gemm_ker_var2sl.c000066400000000000000000000261401422157504600245760ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "blix.h" // Function pointer type for datatype-specific functions. typedef void (*gemm_fp) ( pack_t schema_a, pack_t schema_b, dim_t m, dim_t n, dim_t k, void* alpha, void* a, inc_t cs_a, inc_t is_a, dim_t pd_a, inc_t ps_a, void* b, inc_t rs_b, inc_t is_b, dim_t pd_b, inc_t ps_b, void* beta, void* c, inc_t rs_c, inc_t cs_c, cntx_t* cntx, rntm_t* rntm, thrinfo_t* thread ); // Function pointer array for datatype-specific functions. static gemm_fp ftypes[BLIS_NUM_FP_TYPES] = { PASTECH2(blx_,s,gemm_ker_var2sl), PASTECH2(blx_,c,gemm_ker_var2sl), PASTECH2(blx_,d,gemm_ker_var2sl), PASTECH2(blx_,z,gemm_ker_var2sl) }; void blx_gemm_ker_var2sl ( obj_t* a, obj_t* b, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ) { num_t dt_exec = bli_obj_exec_dt( c ); pack_t schema_a = bli_obj_pack_schema( a ); pack_t schema_b = bli_obj_pack_schema( b ); dim_t m = bli_obj_length( c ); dim_t n = bli_obj_width( c ); dim_t k = bli_obj_width( a ); void* buf_a = bli_obj_buffer_at_off( a ); inc_t cs_a = bli_obj_col_stride( a ); inc_t is_a = bli_obj_imag_stride( a ); dim_t pd_a = bli_obj_panel_dim( a ); inc_t ps_a = bli_obj_panel_stride( a ); void* buf_b = bli_obj_buffer_at_off( b ); inc_t rs_b = bli_obj_row_stride( b ); inc_t is_b = bli_obj_imag_stride( b ); dim_t pd_b = bli_obj_panel_dim( b ); inc_t ps_b = bli_obj_panel_stride( b ); void* buf_c = bli_obj_buffer_at_off( c ); inc_t rs_c = bli_obj_row_stride( c ); inc_t cs_c = bli_obj_col_stride( c ); obj_t scalar_a; obj_t scalar_b; void* buf_alpha; void* buf_beta; gemm_fp f; // Detach and multiply the scalars attached to A and B. bli_obj_scalar_detach( a, &scalar_a ); bli_obj_scalar_detach( b, &scalar_b ); bli_mulsc( &scalar_a, &scalar_b ); // Grab the addresses of the internal scalar buffers for the scalar // merged above and the scalar attached to C. buf_alpha = bli_obj_internal_scalar_buffer( &scalar_b ); buf_beta = bli_obj_internal_scalar_buffer( c ); // Index into the type combination array to extract the correct // function pointer. f = ftypes[dt_exec]; // Invoke the function. f( schema_a, schema_b, m, n, k, buf_alpha, buf_a, cs_a, is_a, pd_a, ps_a, buf_b, rs_b, is_b, pd_b, ps_b, buf_beta, buf_c, rs_c, cs_c, cntx, rntm, thread ); } #undef GENTFUNC #define GENTFUNC( ctype, ch, varname ) \ \ void PASTECH2(blx_,ch,varname) \ ( \ pack_t schema_a, \ pack_t schema_b, \ dim_t m, \ dim_t n, \ dim_t k, \ void* alpha, \ void* a, inc_t cs_a, inc_t is_a, \ dim_t pd_a, inc_t ps_a, \ void* b, inc_t rs_b, inc_t is_b, \ dim_t pd_b, inc_t ps_b, \ void* beta, \ void* c, inc_t rs_c, inc_t cs_c, \ cntx_t* cntx, \ rntm_t* rntm, \ thrinfo_t* thread \ ) \ { \ const num_t dt = PASTEMAC(ch,type); \ \ /* Alias some constants to simpler names. */ \ const dim_t MR = pd_a; \ const dim_t NR = pd_b; \ /*const dim_t PACKMR = cs_a;*/ \ /*const dim_t PACKNR = rs_b;*/ \ \ /* Query the context for the micro-kernel address and cast it to its function pointer type. */ \ PASTECH(ch,gemm_ukr_ft) \ gemm_ukr = bli_cntx_get_l3_vir_ukr_dt( dt, BLIS_GEMM_UKR, cntx ); \ \ /* Temporary C buffer for edge cases. Note that the strides of this temporary buffer are set so that they match the storage of the original C matrix. For example, if C is column-stored, ct will be column-stored as well. */ \ ctype ct[ BLIS_STACK_BUF_MAX_SIZE \ / sizeof( ctype ) ] \ __attribute__((aligned(BLIS_STACK_BUF_ALIGN_SIZE))); \ const bool_t col_pref = bli_cntx_l3_vir_ukr_prefers_cols_dt( dt, BLIS_GEMM_UKR, cntx ); \ const inc_t rs_ct = ( col_pref ? 1 : NR ); \ const inc_t cs_ct = ( col_pref ? MR : 1 ); \ \ ctype* restrict zero = PASTEMAC(ch,0); \ ctype* restrict a_cast = a; \ ctype* restrict b_cast = b; \ ctype* restrict c_cast = c; \ ctype* restrict alpha_cast = alpha; \ ctype* restrict beta_cast = beta; \ ctype* restrict b1; \ ctype* restrict c1; \ \ dim_t m_iter, m_left; \ dim_t n_iter, n_left; \ dim_t i, j; \ dim_t m_cur; \ dim_t n_cur; \ inc_t rstep_a; \ inc_t cstep_b; \ inc_t rstep_c, cstep_c; \ auxinfo_t aux; \ \ /* Assumptions/assertions: rs_a == 1 cs_a == PACKMR pd_a == MR ps_a == stride to next micro-panel of A rs_b == PACKNR cs_b == 1 pd_b == NR ps_b == stride to next micro-panel of B rs_c == (no assumptions) cs_c == (no assumptions) */ \ \ /* If any dimension is zero, return immediately. */ \ if ( bli_zero_dim3( m, n, k ) ) return; \ \ /* Clear the temporary C buffer in case it has any infs or NaNs. */ \ PASTEMAC(ch,set0s_mxn)( MR, NR, \ ct, rs_ct, cs_ct ); \ \ /* Compute number of primary and leftover components of the m and n dimensions. */ \ n_iter = n / NR; \ n_left = n % NR; \ \ m_iter = m / MR; \ m_left = m % MR; \ \ if ( n_left ) ++n_iter; \ if ( m_left ) ++m_iter; \ \ /* Determine some increments used to step through A, B, and C. */ \ rstep_a = ps_a; \ \ cstep_b = ps_b; \ \ rstep_c = rs_c * MR; \ cstep_c = cs_c * NR; \ \ /* Save the pack schemas of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_schema_a( schema_a, &aux ); \ bli_auxinfo_set_schema_b( schema_b, &aux ); \ \ /* Save the imaginary stride of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_is_a( is_a, &aux ); \ bli_auxinfo_set_is_b( is_b, &aux ); \ \ /* The 'thread' argument points to the thrinfo_t node for the 2nd (jr) loop around the microkernel. Here we query the thrinfo_t node for the 1st (ir) loop around the microkernel. */ \ thrinfo_t* caucus = bli_thrinfo_sub_node( thread ); \ \ /* Query the number of threads and thread ids for each loop. */ \ dim_t jr_nt = bli_thread_n_way( thread ); \ dim_t jr_tid = bli_thread_work_id( thread ); \ dim_t ir_nt = bli_thread_n_way( caucus ); \ dim_t ir_tid = bli_thread_work_id( caucus ); \ \ dim_t jr_start, jr_end; \ dim_t ir_start, ir_end; \ dim_t jr_inc, ir_inc; \ \ /* Determine the thread range and increment for each thrinfo_t node. */ \ bli_thread_range_jrir_sl( thread, n_iter, 1, FALSE, &jr_start, &jr_end, &jr_inc ); \ bli_thread_range_jrir_sl( caucus, m_iter, 1, FALSE, &ir_start, &ir_end, &ir_inc ); \ \ /* Loop over the n dimension (NR columns at a time). */ \ for ( j = jr_start; j < jr_end; j += jr_inc ) \ { \ ctype* restrict a1; \ ctype* restrict c11; \ ctype* restrict b2; \ \ b1 = b_cast + j * cstep_b; \ c1 = c_cast + j * cstep_c; \ \ n_cur = ( bli_is_not_edge_f( j, n_iter, n_left ) ? NR : n_left ); \ \ /* Initialize our next panel of B to be the current panel of B. */ \ b2 = b1; \ \ /* Loop over the m dimension (MR rows at a time). */ \ for ( i = ir_start; i < ir_end; i += ir_inc ) \ { \ ctype* restrict a2; \ \ a1 = a_cast + i * rstep_a; \ c11 = c1 + i * rstep_c; \ \ m_cur = ( bli_is_not_edge_f( i, m_iter, m_left ) ? MR : m_left ); \ \ /* Compute the addresses of the next panels of A and B. */ \ a2 = bli_gemm_get_next_a_upanel( a1, rstep_a, ir_inc ); \ if ( bli_is_last_iter_sl( i, ir_end, ir_tid, ir_nt ) ) \ { \ a2 = a_cast; \ b2 = bli_gemm_get_next_b_upanel( b1, cstep_b, jr_inc ); \ if ( bli_is_last_iter_sl( j, jr_end, jr_tid, jr_nt ) ) \ b2 = b_cast; \ } \ \ /* Save addresses of next panels of A and B to the auxinfo_t object. */ \ bli_auxinfo_set_next_a( a2, &aux ); \ bli_auxinfo_set_next_b( b2, &aux ); \ \ /* Handle interior and edge cases separately. */ \ if ( m_cur == MR && n_cur == NR ) \ { \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k, \ alpha_cast, \ a1, \ b1, \ beta_cast, \ c11, rs_c, cs_c, \ &aux, \ cntx \ ); \ } \ else \ { \ /* Invoke the gemm micro-kernel. */ \ gemm_ukr \ ( \ k, \ alpha_cast, \ a1, \ b1, \ zero, \ ct, rs_ct, cs_ct, \ &aux, \ cntx \ ); \ \ /* Scale the bottom edge of C and add the result from above. */ \ PASTEMAC(ch,xpbys_mxn)( m_cur, n_cur, \ ct, rs_ct, cs_ct, \ beta_cast, \ c11, rs_c, cs_c ); \ } \ } \ } \ \ /* PASTEMAC(ch,fprintm)( stdout, "gemm_ker_var2: b1", k, NR, b1, NR, 1, "%4.1f", "" ); \ PASTEMAC(ch,fprintm)( stdout, "gemm_ker_var2: a1", MR, k, a1, 1, MR, "%4.1f", "" ); \ PASTEMAC(ch,fprintm)( stdout, "gemm_ker_var2: c after", m_cur, n_cur, c11, rs_c, cs_c, "%4.1f", "" ); \ */ \ } #if 0 GENTFUNC( float, s, gemm_ker_var2sl ) GENTFUNC( double, d, gemm_ker_var2sl ) GENTFUNC( scomplex, c, gemm_ker_var2sl ) GENTFUNC( dcomplex, z, gemm_ker_var2sl ) #else INSERT_GENTFUNC_BASIC0( gemm_ker_var2sl ) #endif blis-0.9.0/sandbox/power10/000077500000000000000000000000001422157504600154125ustar00rootroot00000000000000blis-0.9.0/sandbox/power10/POWER10.md000066400000000000000000000062051422157504600167740ustar00rootroot00000000000000### Low Precision POWER10 Kernels This is a special BLIS Sandbox that allows users to call POWER10 reduced precision/integer `GEMM` kernels. Supported kernels: `IEEE float16 (bli_shgemm), bfloat16 (bli_sbgemm), int16 (bli_i16gemm), int8 (bli_i8gemm), int4 (bli_i4gemm)`. #### Introduction This document describes how the low precision POWER10 `gemm` kernels are implemented and explains how to call the POWER10 `GEMM` kernels. **Important: These kernels does not have the full functionality of BLIS. The kernels can only perform single threaded, no transpose, GEMM.** #### Implementation The kernels are implemented in `gemm.c`. They are instantiated with macro templates. The main template is called `GENERIC_GEMM`. This template is used to create the 5-loop `gemm` function. #### Reduced precision/integer Types | BLIS type | BLIS char | Type definition | Used to represent... | |:-----------|:----------|:---------------------------------------|:-------------------------------------| | `float16` | `h` | `typedef union { uint16_t v; struct { uint16_t m:10; uint16_t e:5; uint16_t s:1} bits; }` | IEEE half-precision real numbers | | `bfloat16` | `b` | `typedef union { uint16_t v; struct { uint16_t m:7; uint16_t e:8; uint16_t s:1; } bits; }` | Google's half-precision real numbers | | `int16` | `i16` | `int16_t` | 16 bit integers | | `int8` | `i8` | `int8_t` | 8 bit integers | | `int4` | `i4` | `typedef union{ uint8_t v; struct { uint8_t nib1:4; uint8_t nib2:4; } bits; }` | 4 bit integers | #### Reduced Precision/Integer API The API that is used for the reduced precision/integer POWER10 `GEMM` kernels is similar to the existing [BLIS basic typed API](https://github.com/flame/blis/blob/master/docs/BLISTypedAPI.md). The main difference is the POWER10 kernels expect two types: `ctype_in` and `ctype_out`. Thus the new `gemm` call looks like the following: ``` void bli_??gemm ( trans_t transa, trans_t transb, dim_t m, dim_t n, dim_t k, ctype_out* alpha, ctype_in* a, inc_t rsa, inc_t csa, ctype_in* b, inc_t rsb, inc_t csb, ctype_out* beta, ctype_out* c, inc_t rsc, inc_t csc ); ``` `??` is meant to replaced with the kernel prefix. #### How To Build The Sandbox Add the following flags when running the configure script to build BLIS correctly. `CFLAGS="-fPIC -std=c99 -D_ISOC11_SOURCE -D_POSIX_C_SOURCE=200112L" -s power10` Ensure that you have GCC 10.2 or greater. #### P10 Testsuite In `p10_testsuite`, there are performance gathering and correctness checking programs for the POWER10 reduced precision/integer `GEMM` kernels. By default, the performance gathering and correctness checking is done over square matrices ranging from 80 to 4000 in increments of 80. Performance is measured in GFLOPs, and correctness is measured using the BLIS method (detailed in `blis/testsuite/test_gemm.c`). #### References * [bfloat16 wiki](https://en.wikipedia.org/wiki/Bfloat16_floating-point_format) * [IEEE float16 wiki](https://en.wikipedia.org/wiki/Half-precision_floating-point_format)blis-0.9.0/sandbox/power10/bli_gemm_ex.c000066400000000000000000000057341422157504600200360ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // Given the current architecture of BLIS sandboxes, bli_gemm_ex() is the // entry point to any sandbox implementation. // NOTE: This function is implemented functionally identically to the // function that it overrides in frame/3/bli_l3_oapi_ex.c. This means that // we are forgoing the option of customizing the implementations that // underlie bli_gemm() and bli_?gemm() (which both call bli_gemm_ex()). // Any new code defined in this sandbox directory, however, will be // included in the BLIS. #include "blis.h" void bli_gemm_ex ( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx, rntm_t* rntm ) { bli_init_once(); // Initialize a local runtime with global settings if necessary. Note // that in the case that a runtime is passed in, we make a local copy. rntm_t rntm_l; if ( rntm == NULL ) { bli_rntm_init_from_global( &rntm_l ); rntm = &rntm_l; } else { rntm_l = *rntm; rntm = &rntm_l; } // Obtain a valid (native) context from the gks if necessary. if ( cntx == NULL ) cntx = bli_gks_query_cntx(); // Check the operands. if ( bli_error_checking_is_enabled() ) bli_gemm_check( alpha, a, b, beta, c, cntx ); // Invoke the operation's front end. bli_gemm_front ( alpha, a, b, beta, c, cntx, rntm, NULL ); } blis-0.9.0/sandbox/power10/bli_sandbox.h000066400000000000000000000060271422157504600200540ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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 copyright holder(s) nor the names 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 COPYRIGHT HOLDER 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. */ #ifndef BLIS_SANDBOX_H #define BLIS_SANDBOX_H #include "blis.h" #include "gemm_prototypes.h" // NOTE: This header is the only header required to be present in the sandbox // implementation directory. // int4 typedef union { uint8_t v; struct { uint8_t nib1:4; uint8_t nib2:4; } bits; } nibbles; // brain float16 typedef union { uint16_t v; struct { uint16_t m:7; uint16_t e:8; uint16_t s:1; } bits; } bfloat16; // ieee float16 typedef union { uint16_t v; struct { uint16_t m:10; uint16_t e:5; uint16_t s:1; } bits; } float16; #define P10_PG_SIZE 4096 // microkernel prototypes GEMM_UKR_PROT2( bfloat16, float, sb, gemm_power10_mma_8x16 ) GEMM_UKR_PROT2( float16, float, sh, gemm_power10_mma_8x16 ) GEMM_UKR_PROT2( int16_t, int32_t, i16, gemm_power10_mma_8x16 ) GEMM_UKR_PROT2( int8_t, int32_t, i8, gemm_power10_mma_8x16 ) GEMM_UKR_PROT2( nibbles, int32_t, i4, gemm_power10_mma_8x16 ) // gemm kernel prototypes GEMM_FUNC_PROT( float16, float, sh); GEMM_FUNC_PROT( bfloat16, float, sb); GEMM_FUNC_PROT( int16_t, int32_t, i16); GEMM_FUNC_PROT( int8_t, int32_t, i8); GEMM_FUNC_PROT( nibbles, int32_t, i4); // pack kernel prototypes PACK_MACRO_PROTO(sb, bfloat16) PACK_MACRO_PROTO(sh, float16) PACK_MACRO_PROTO(i16, int16_t) PACK_MACRO_PROTO(i8, int8_t) PACK_MACRO_PROTO(i4, nibbles) #endif blis-0.9.0/sandbox/power10/gemm.c000066400000000000000000000073061422157504600165110ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "gemm_template.h" #include "bli_sandbox.h" GENERIC_GEMM( sb, // kernel name prefix bfloat16, // input type float, // output type (pb/2 + pb%2), // innermost loop iterations sb_pack_a, sb_pack_b, // pack kernel for B bli_sbgemm_power10_mma_8x16, // microkernel function name 2, // K_MMA 8, // MR 16, // NR 384, // MC 3328, // KC 4096, // NC 0, // A_ALIGN 0 // B_ALIGN ); GENERIC_GEMM( sh, // kernel name prefix float16, // input type float, // output type (pb/2 + pb%2), // innermost loop iterations sh_pack_a, // pack kernel for A sh_pack_b, // pack kernel for B bli_shgemm_power10_mma_8x16, // microkernel function name 2, // K_MMA 8, // MR 16, // NR 384, // MC 3328, // KC 4096, // NC 0, // A_ALIGN 0 // B_ALIGN ); GENERIC_GEMM( i16, // kernel name prefix int16_t, // input type int, // output type (pb/2 + pb%2), // innermost loop iterations i16_pack_a, // pack kernel for A i16_pack_b, // pack kernel for B bli_i16gemm_power10_mma_8x16, // microkernel function name 2, // K_MMA 8, // MR 16, // NR 384, // MC 3328, // KC 4096, // NC 0, // A_ALIGN 0 // B_ALIGN ); GENERIC_GEMM( i8, // kernel name prefix int8_t, // input type int, // output type (pb/4 + (pb%4>0)), // innermost loop iterations i8_pack_a, // pack kernel for A i8_pack_b, // pack kernel for B bli_i8gemm_power10_mma_8x16, // microkernel function name 4, // K_MMA 8, // MR 16, // NR 384, // MC 6656, // KC 4096, // NC 0, // A_ALIGN 0 // B_ALIGN ); GENERIC_GEMM( i4, // kernel name prefix nibbles, // input type int, // output type (pb/8 + (pb%8>0)), // innermost loop iterations i4_pack_a, // pack kernel for A i4_pack_b, // pack kernel for B bli_i4gemm_power10_mma_8x16, // microkernel function name 8, // K_MMA 8, // MR 16, // NR 384, // MC 6656, // KC 4096, // NC 0, // A_ALIGN 0 // B_ALIGN ); blis-0.9.0/sandbox/power10/gemm_prototypes.h000066400000000000000000000054241422157504600210250ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // BLIS GEMM function naming scheme #define GEMM_FUNC_NAME_(ch) bli_ ## ch ## gemm #define GEMM_FUNC_NAME(ch) GEMM_FUNC_NAME_(ch) // BLIS GEMM function prototype macro #define GEMM_FUNC_PROT(DTYPE_IN, DTYPE_OUT, ch) \ void GEMM_FUNC_NAME(ch) \ ( \ trans_t transa, \ trans_t transb, \ dim_t m, \ dim_t n, \ dim_t k, \ DTYPE_OUT* alpha, \ DTYPE_IN* a, inc_t rsa, inc_t csa, \ DTYPE_IN* b, inc_t rsb, inc_t csb, \ DTYPE_OUT* beta, \ DTYPE_OUT* c, inc_t rsc, inc_t csc \ ) // Pack routine naming scheme #define PACK_FUNC_NAME_(ch, mat) ch ## _pack_ ## mat #define PACK_FUNC_NAME(ch, mat) PACK_FUNC_NAME_(ch, mat) // Pack routine prototype #define PACK_MACRO_PROTO(ch, DTYPE_IN) \ \ void PACK_FUNC_NAME(ch, a) \ ( \ dim_t MR, \ int m, int k, \ DTYPE_IN* ap, int rs_a, int cs_a, \ DTYPE_IN* apack \ ); \ \ void PACK_FUNC_NAME(ch, b) \ ( \ dim_t NR, \ int k, int n, \ DTYPE_IN* bp, int rs_b, int cs_b, \ DTYPE_IN* bpack \ ); blis-0.9.0/sandbox/power10/gemm_template.h000066400000000000000000000136071422157504600204120ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" /* Macro function template for creating BLIS GEMM kernels using the Goto method. This GEMM template assumes that the matrices are both not transposed. ch - kernel name prefix DTYPE_IN, DTYPE_OUT - datatypes of the input and output operands respectively NEW_PB - number of iterations of the innermost loop PACK_A, PACK_B - pack kernels names MICROKERNEL - microkernel function name K_MMA - number of outer products performed by an instruction MR, NR, MC, KC, NC - Cache blocking parameters B_ALIGN, A_ALIGN - Extra byte alignment for the pack matrix buffers */ #define GENERIC_GEMM( \ ch, \ DTYPE_IN, \ DTYPE_OUT, \ NEW_PB, \ PACK_A, \ PACK_B, \ MICROKERNEL, \ K_MMA, \ MR, \ NR, \ MC, \ KC, \ NC, \ B_ALIGN, \ A_ALIGN \ ) \ \ void GEMM_FUNC_NAME(ch) \ ( \ trans_t transa, \ trans_t transb, \ dim_t m, \ dim_t n, \ dim_t k, \ DTYPE_OUT* alpha, \ DTYPE_IN* a, inc_t rsa, inc_t csa, \ DTYPE_IN* b, inc_t rsb, inc_t csb, \ DTYPE_OUT* beta, \ DTYPE_OUT* c, inc_t rsc, inc_t csc \ ) \ { \ DTYPE_IN * restrict btilde_sys = ( DTYPE_IN *) aligned_alloc( P10_PG_SIZE, B_ALIGN + KC * NC * sizeof( DTYPE_IN ) ); \ DTYPE_IN * restrict atilde_sys = ( DTYPE_IN *) aligned_alloc( P10_PG_SIZE, A_ALIGN + MC * KC * sizeof( DTYPE_IN ) ); \ \ DTYPE_IN * restrict btilde_usr = ( DTYPE_IN *)((char *)btilde_sys + B_ALIGN); \ DTYPE_IN * restrict atilde_usr = ( DTYPE_IN *)((char *)atilde_sys + A_ALIGN); \ \ const int rstep_c = MC * rsc; \ const int cstep_c = NC * csc; \ \ const int rstep_a = MC * rsa; \ const int cstep_a = KC * csa; \ \ const int rstep_b = KC * rsb; \ const int cstep_b = NC * csb; \ \ const int rstep_mt_c = MR * rsc; \ const int cstep_mt_c = NR * csc; \ \ DTYPE_OUT * restrict cblock = c; \ DTYPE_IN * restrict bblock = b; \ \ for ( int jc=0; jcv = 0; \ dest++; // zero out 4 nibbles struct #define zero_out_dest(dest) \ memset(dest, 0, 4); //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////// Col Major Order Macros //////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// /* The following macros handle the case when there is a full size panel (ib/jb == MR/NR) and no edge case (k%8 == 0). */ #define col_m_order_1(dest, matrix, rs_mul, rs, cs) \ dest->bits.nib1 = matrix[rs_mul*rs + (p_idx+0)*cs].bits.nib1; \ dest->bits.nib2 = matrix[rs_mul*rs + (p_idx+1)*cs].bits.nib1; \ dest++; \ dest->bits.nib1 = matrix[rs_mul*rs + (p_idx+2)*cs].bits.nib1; \ dest->bits.nib2 = matrix[rs_mul*rs + (p_idx+3)*cs].bits.nib1; \ dest++; \ dest->bits.nib1 = matrix[rs_mul*rs + (p_idx+4)*cs].bits.nib1; \ dest->bits.nib2 = matrix[rs_mul*rs + (p_idx+5)*cs].bits.nib1; \ dest++; \ dest->bits.nib1 = matrix[rs_mul*rs + (p_idx+6)*cs].bits.nib1; \ dest->bits.nib2 = matrix[rs_mul*rs + (p_idx+7)*cs].bits.nib1; \ dest++; #define col_m_order_2(dest, matrix, rs_mul, rs, cs) \ dest->bits.nib1 = matrix[rs_mul*rs + (p_idx+0)*cs].bits.nib2; \ dest->bits.nib2 = matrix[rs_mul*rs + (p_idx+1)*cs].bits.nib2; \ dest++; \ dest->bits.nib1 = matrix[rs_mul*rs + (p_idx+2)*cs].bits.nib2; \ dest->bits.nib2 = matrix[rs_mul*rs + (p_idx+3)*cs].bits.nib2; \ dest++; \ dest->bits.nib1 = matrix[rs_mul*rs + (p_idx+4)*cs].bits.nib2; \ dest->bits.nib2 = matrix[rs_mul*rs + (p_idx+5)*cs].bits.nib2; \ dest++; \ dest->bits.nib1 = matrix[rs_mul*rs + (p_idx+6)*cs].bits.nib2; \ dest->bits.nib2 = matrix[rs_mul*rs + (p_idx+7)*cs].bits.nib2; \ dest++; /* The following macros handle the case when there is a full size panel (ib/jb == MR/NR) and there is an edge case (k%8 != 0). */ #define col_m_order_1_kleft7(dest, matrix, rs_mul, rs, cs) \ dest->bits.nib1 = matrix[rs_mul*rs + (k-7)*cs].bits.nib1; \ dest->bits.nib2 = matrix[rs_mul*rs + (k-6)*cs].bits.nib1; \ dest++; \ dest->bits.nib1 = matrix[rs_mul*rs + (k-5)*cs].bits.nib1; \ dest->bits.nib2 = matrix[rs_mul*rs + (k-4)*cs].bits.nib1; \ dest++; \ dest->bits.nib1 = matrix[rs_mul*rs + (k-3)*cs].bits.nib1; \ dest->bits.nib2 = matrix[rs_mul*rs + (k-2)*cs].bits.nib1; \ dest++; \ dest->bits.nib1 = matrix[rs_mul*rs + (k-1)*cs].bits.nib1; \ dest->bits.nib2 = 0; \ dest++; #define col_m_order_2_kleft7(dest, matrix, rs_mul, rs, cs) \ dest->bits.nib1 = matrix[rs_mul*rs + (k-7)*cs].bits.nib2; \ dest->bits.nib2 = matrix[rs_mul*rs + (k-6)*cs].bits.nib2; \ dest++; \ dest->bits.nib1 = matrix[rs_mul*rs + (k-5)*cs].bits.nib2; \ dest->bits.nib2 = matrix[rs_mul*rs + (k-4)*cs].bits.nib2; \ dest++; \ dest->bits.nib1 = matrix[rs_mul*rs + (k-3)*cs].bits.nib2; \ dest->bits.nib2 = matrix[rs_mul*rs + (k-2)*cs].bits.nib2; \ dest++; \ dest->bits.nib1 = matrix[rs_mul*rs + (k-1)*cs].bits.nib2; \ dest->bits.nib2 = 0; \ dest++; #define col_m_order_1_kleft6(dest, matrix, rs_mul, rs, cs) \ dest->bits.nib1 = matrix[rs_mul*rs + (k-6)*cs].bits.nib1; \ dest->bits.nib2 = matrix[rs_mul*rs + (k-5)*cs].bits.nib1; \ dest++; \ dest->bits.nib1 = matrix[rs_mul*rs + (k-4)*cs].bits.nib1; \ dest->bits.nib2 = matrix[rs_mul*rs + (k-3)*cs].bits.nib1; \ dest++; \ dest->bits.nib1 = matrix[rs_mul*rs + (k-2)*cs].bits.nib1; \ dest->bits.nib2 = matrix[rs_mul*rs + (k-1)*cs].bits.nib1; \ dest++; \ zero_out_full(dest); #define col_m_order_2_kleft6(dest, matrix, rs_mul, rs, cs) \ dest->bits.nib1 = matrix[rs_mul*rs + (k-6)*cs].bits.nib2; \ dest->bits.nib2 = matrix[rs_mul*rs + (k-5)*cs].bits.nib2; \ dest++; \ dest->bits.nib1 = matrix[rs_mul*rs + (k-4)*cs].bits.nib2; \ dest->bits.nib2 = matrix[rs_mul*rs + (k-3)*cs].bits.nib2; \ dest++; \ dest->bits.nib1 = matrix[rs_mul*rs + (k-2)*cs].bits.nib2; \ dest->bits.nib2 = matrix[rs_mul*rs + (k-1)*cs].bits.nib2; \ dest++; \ zero_out_full(dest); #define col_m_order_1_kleft5(dest, matrix, rs_mul, rs, cs) \ dest->bits.nib1 = matrix[rs_mul*rs + (k-5)*cs].bits.nib1; \ dest->bits.nib2 = matrix[rs_mul*rs + (k-4)*cs].bits.nib1; \ dest++; \ dest->bits.nib1 = matrix[rs_mul*rs + (k-3)*cs].bits.nib1; \ dest->bits.nib2 = matrix[rs_mul*rs + (k-2)*cs].bits.nib1; \ dest++; \ dest->bits.nib1 = matrix[rs_mul*rs + (k-1)*cs].bits.nib1; \ dest->bits.nib2 = 0; \ dest++; \ zero_out_full(dest); #define col_m_order_2_kleft5(dest, matrix, rs_mul, rs, cs) \ dest->bits.nib1 = matrix[rs_mul*rs + (k-5)*cs].bits.nib2; \ dest->bits.nib2 = matrix[rs_mul*rs + (k-4)*cs].bits.nib2; \ dest++; \ dest->bits.nib1 = matrix[rs_mul*rs + (k-3)*cs].bits.nib2; \ dest->bits.nib2 = matrix[rs_mul*rs + (k-2)*cs].bits.nib2; \ dest++; \ dest->bits.nib1 = matrix[rs_mul*rs + (k-1)*cs].bits.nib2; \ dest->bits.nib2 = 0; \ dest++; \ zero_out_full(dest); #define col_m_order_1_kleft4(dest, matrix, rs_mul, rs, cs) \ dest->bits.nib1 = matrix[rs_mul*rs + (k-4)*cs].bits.nib1; \ dest->bits.nib2 = matrix[rs_mul*rs + (k-3)*cs].bits.nib1; \ dest++; \ dest->bits.nib1 = matrix[rs_mul*rs + (k-2)*cs].bits.nib1; \ dest->bits.nib2 = matrix[rs_mul*rs + (k-1)*cs].bits.nib1; \ dest++; \ zero_out_full(dest); \ zero_out_full(dest); #define col_m_order_2_kleft4(dest, matrix, rs_mul, rs, cs) \ dest->bits.nib1 = matrix[rs_mul*rs + (k-4)*cs].bits.nib2; \ dest->bits.nib2 = matrix[rs_mul*rs + (k-3)*cs].bits.nib2; \ dest++; \ dest->bits.nib1 = matrix[rs_mul*rs + (k-2)*cs].bits.nib2; \ dest->bits.nib2 = matrix[rs_mul*rs + (k-1)*cs].bits.nib2; \ dest++; \ zero_out_full(dest); \ zero_out_full(dest); #define col_m_order_1_kleft3(dest, matrix, rs_mul, rs, cs) \ dest->bits.nib1 = matrix[rs_mul*rs + (k-3)*cs].bits.nib1; \ dest->bits.nib2 = matrix[rs_mul*rs + (k-2)*cs].bits.nib1; \ dest++; \ dest->bits.nib1 = matrix[rs_mul*rs + (k-1)*cs].bits.nib1; \ dest->bits.nib2 = 0; \ dest++; \ zero_out_full(dest); \ zero_out_full(dest); #define col_m_order_2_kleft3(dest, matrix, rs_mul, rs, cs) \ dest->bits.nib1 = matrix[rs_mul*rs + (k-3)*cs].bits.nib2; \ dest->bits.nib2 = matrix[rs_mul*rs + (k-2)*cs].bits.nib2; \ dest++; \ dest->bits.nib1 = matrix[rs_mul*rs + (k-1)*cs].bits.nib2; \ dest->bits.nib2 = 0; \ dest++; \ zero_out_full(dest); \ zero_out_full(dest); #define col_m_order_1_kleft2(dest, matrix, rs_mul, rs, cs) \ dest->bits.nib1 = matrix[rs_mul*rs + (k-2)*cs].bits.nib1; \ dest->bits.nib2 = matrix[rs_mul*rs + (k-1)*cs].bits.nib1; \ dest++; \ zero_out_full(dest); \ zero_out_full(dest); \ zero_out_full(dest); #define col_m_order_2_kleft2(dest, matrix, rs_mul, rs, cs) \ dest->bits.nib1 = matrix[rs_mul*rs + (k-2)*cs].bits.nib2; \ dest->bits.nib2 = matrix[rs_mul*rs + (k-1)*cs].bits.nib2; \ dest++; \ zero_out_full(dest); \ zero_out_full(dest); \ zero_out_full(dest); #define col_m_order_1_kleft1(dest, matrix, rs_mul, rs, cs) \ dest->bits.nib1 = matrix[rs_mul*rs + (k-1)*cs].bits.nib1; \ dest->bits.nib2 = 0; \ dest++; \ zero_out_full(dest); \ zero_out_full(dest); \ zero_out_full(dest); #define col_m_order_2_kleft1(dest, matrix, rs_mul, rs, cs) \ dest->bits.nib1 = matrix[rs_mul*rs + (k-1)*cs].bits.nib2; \ dest->bits.nib2 = 0; \ dest++; \ zero_out_full(dest); \ zero_out_full(dest); \ zero_out_full(dest); /* The following macros are used when we have a full panel (ib == MR) and we need to handle an edge case (k%8 != 0). The MR loop is unrolled resulting in the stream of macros. */ #define apad_col_kleft7(dest, matrix, rs, cs) \ col_m_order_1_kleft7(dest, matrix, (i ), rs, cs); \ col_m_order_2_kleft7(dest, matrix, (i ), rs, cs); \ col_m_order_1_kleft7(dest, matrix, (i+1), rs, cs); \ col_m_order_2_kleft7(dest, matrix, (i+1), rs, cs); \ col_m_order_1_kleft7(dest, matrix, (i+2), rs, cs); \ col_m_order_2_kleft7(dest, matrix, (i+2), rs, cs); \ col_m_order_1_kleft7(dest, matrix, (i+3), rs, cs); \ col_m_order_2_kleft7(dest, matrix, (i+3), rs, cs); #define apad_col_kleft6(dest, matrix, rs, cs) \ col_m_order_1_kleft6(dest, matrix, (i ), rs, cs); \ col_m_order_2_kleft6(dest, matrix, (i ), rs, cs); \ col_m_order_1_kleft6(dest, matrix, (i+1), rs, cs); \ col_m_order_2_kleft6(dest, matrix, (i+1), rs, cs); \ col_m_order_1_kleft6(dest, matrix, (i+2), rs, cs); \ col_m_order_2_kleft6(dest, matrix, (i+2), rs, cs); \ col_m_order_1_kleft6(dest, matrix, (i+3), rs, cs); \ col_m_order_2_kleft6(dest, matrix, (i+3), rs, cs); #define apad_col_kleft5(dest, matrix, rs, cs) \ col_m_order_1_kleft5(dest, matrix, (i ), rs, cs); \ col_m_order_2_kleft5(dest, matrix, (i ), rs, cs); \ col_m_order_1_kleft5(dest, matrix, (i+1), rs, cs); \ col_m_order_2_kleft5(dest, matrix, (i+1), rs, cs); \ col_m_order_1_kleft5(dest, matrix, (i+2), rs, cs); \ col_m_order_2_kleft5(dest, matrix, (i+2), rs, cs); \ col_m_order_1_kleft5(dest, matrix, (i+3), rs, cs); \ col_m_order_2_kleft5(dest, matrix, (i+3), rs, cs); #define apad_col_kleft4(dest, matrix, rs, cs) \ col_m_order_1_kleft4(dest, matrix, (i ), rs, cs); \ col_m_order_2_kleft4(dest, matrix, (i ), rs, cs); \ col_m_order_1_kleft4(dest, matrix, (i+1), rs, cs); \ col_m_order_2_kleft4(dest, matrix, (i+1), rs, cs); \ col_m_order_1_kleft4(dest, matrix, (i+2), rs, cs); \ col_m_order_2_kleft4(dest, matrix, (i+2), rs, cs); \ col_m_order_1_kleft4(dest, matrix, (i+3), rs, cs); \ col_m_order_2_kleft4(dest, matrix, (i+3), rs, cs); #define apad_col_kleft3(dest, matrix, rs, cs) \ col_m_order_1_kleft3(dest, matrix, (i ), rs, cs); \ col_m_order_2_kleft3(dest, matrix, (i ), rs, cs); \ col_m_order_1_kleft3(dest, matrix, (i+1), rs, cs); \ col_m_order_2_kleft3(dest, matrix, (i+1), rs, cs); \ col_m_order_1_kleft3(dest, matrix, (i+2), rs, cs); \ col_m_order_2_kleft3(dest, matrix, (i+2), rs, cs); \ col_m_order_1_kleft3(dest, matrix, (i+3), rs, cs); \ col_m_order_2_kleft3(dest, matrix, (i+3), rs, cs); #define apad_col_kleft2(dest, matrix, rs, cs) \ col_m_order_1_kleft2(dest, matrix, (i ), rs, cs); \ col_m_order_2_kleft2(dest, matrix, (i ), rs, cs); \ col_m_order_1_kleft2(dest, matrix, (i+1), rs, cs); \ col_m_order_2_kleft2(dest, matrix, (i+1), rs, cs); \ col_m_order_1_kleft2(dest, matrix, (i+2), rs, cs); \ col_m_order_2_kleft2(dest, matrix, (i+2), rs, cs); \ col_m_order_1_kleft2(dest, matrix, (i+3), rs, cs); \ col_m_order_2_kleft2(dest, matrix, (i+3), rs, cs); #define apad_col_kleft1(dest, matrix, rs, cs) \ col_m_order_1_kleft1(dest, matrix, (i ), rs, cs); \ col_m_order_2_kleft1(dest, matrix, (i ), rs, cs); \ col_m_order_1_kleft1(dest, matrix, (i+1), rs, cs); \ col_m_order_2_kleft1(dest, matrix, (i+1), rs, cs); \ col_m_order_1_kleft1(dest, matrix, (i+2), rs, cs); \ col_m_order_2_kleft1(dest, matrix, (i+2), rs, cs); \ col_m_order_1_kleft1(dest, matrix, (i+3), rs, cs); \ col_m_order_2_kleft1(dest, matrix, (i+3), rs, cs); /* The following macros are used when we have a full panel (jb == NR) and we need to handle an edge case (k%8 != 0). The NR loop is unrolled resulting in the stream of macros. */ #define bpad_col_kleft7(dest, matrix, rs, cs) \ col_m_order_1_kleft7(dest, matrix, (j ), rs, cs); \ col_m_order_2_kleft7(dest, matrix, (j ), rs, cs); \ col_m_order_1_kleft7(dest, matrix, (j+1), rs, cs); \ col_m_order_2_kleft7(dest, matrix, (j+1), rs, cs); \ col_m_order_1_kleft7(dest, matrix, (j+2), rs, cs); \ col_m_order_2_kleft7(dest, matrix, (j+2), rs, cs); \ col_m_order_1_kleft7(dest, matrix, (j+3), rs, cs); \ col_m_order_2_kleft7(dest, matrix, (j+3), rs, cs); \ col_m_order_1_kleft7(dest, matrix, (j+4), rs, cs); \ col_m_order_2_kleft7(dest, matrix, (j+4), rs, cs); \ col_m_order_1_kleft7(dest, matrix, (j+5), rs, cs); \ col_m_order_2_kleft7(dest, matrix, (j+5), rs, cs); \ col_m_order_1_kleft7(dest, matrix, (j+6), rs, cs); \ col_m_order_2_kleft7(dest, matrix, (j+6), rs, cs); \ col_m_order_1_kleft7(dest, matrix, (j+7), rs, cs); \ col_m_order_2_kleft7(dest, matrix, (j+7), rs, cs); #define bpad_col_kleft6(dest, matrix, rs, cs) \ col_m_order_1_kleft6(dest, matrix, (j ), rs, cs); \ col_m_order_2_kleft6(dest, matrix, (j ), rs, cs); \ col_m_order_1_kleft6(dest, matrix, (j+1), rs, cs); \ col_m_order_2_kleft6(dest, matrix, (j+1), rs, cs); \ col_m_order_1_kleft6(dest, matrix, (j+2), rs, cs); \ col_m_order_2_kleft6(dest, matrix, (j+2), rs, cs); \ col_m_order_1_kleft6(dest, matrix, (j+3), rs, cs); \ col_m_order_2_kleft6(dest, matrix, (j+3), rs, cs); \ col_m_order_1_kleft6(dest, matrix, (j+4), rs, cs); \ col_m_order_2_kleft6(dest, matrix, (j+4), rs, cs); \ col_m_order_1_kleft6(dest, matrix, (j+5), rs, cs); \ col_m_order_2_kleft6(dest, matrix, (j+5), rs, cs); \ col_m_order_1_kleft6(dest, matrix, (j+6), rs, cs); \ col_m_order_2_kleft6(dest, matrix, (j+6), rs, cs); \ col_m_order_1_kleft6(dest, matrix, (j+7), rs, cs); \ col_m_order_2_kleft6(dest, matrix, (j+7), rs, cs); #define bpad_col_kleft5(dest, matrix, rs, cs) \ col_m_order_1_kleft5(dest, matrix, (j ), rs, cs); \ col_m_order_2_kleft5(dest, matrix, (j ), rs, cs); \ col_m_order_1_kleft5(dest, matrix, (j+1), rs, cs); \ col_m_order_2_kleft5(dest, matrix, (j+1), rs, cs); \ col_m_order_1_kleft5(dest, matrix, (j+2), rs, cs); \ col_m_order_2_kleft5(dest, matrix, (j+2), rs, cs); \ col_m_order_1_kleft5(dest, matrix, (j+3), rs, cs); \ col_m_order_2_kleft5(dest, matrix, (j+3), rs, cs); \ col_m_order_1_kleft5(dest, matrix, (j+4), rs, cs); \ col_m_order_2_kleft5(dest, matrix, (j+4), rs, cs); \ col_m_order_1_kleft5(dest, matrix, (j+5), rs, cs); \ col_m_order_2_kleft5(dest, matrix, (j+5), rs, cs); \ col_m_order_1_kleft5(dest, matrix, (j+6), rs, cs); \ col_m_order_2_kleft5(dest, matrix, (j+6), rs, cs); \ col_m_order_1_kleft5(dest, matrix, (j+7), rs, cs); \ col_m_order_2_kleft5(dest, matrix, (j+7), rs, cs); #define bpad_col_kleft4(dest, matrix, rs, cs) \ col_m_order_1_kleft4(dest, matrix, (j ), rs, cs); \ col_m_order_2_kleft4(dest, matrix, (j ), rs, cs); \ col_m_order_1_kleft4(dest, matrix, (j+1), rs, cs); \ col_m_order_2_kleft4(dest, matrix, (j+1), rs, cs); \ col_m_order_1_kleft4(dest, matrix, (j+2), rs, cs); \ col_m_order_2_kleft4(dest, matrix, (j+2), rs, cs); \ col_m_order_1_kleft4(dest, matrix, (j+3), rs, cs); \ col_m_order_2_kleft4(dest, matrix, (j+3), rs, cs); \ col_m_order_1_kleft4(dest, matrix, (j+4), rs, cs); \ col_m_order_2_kleft4(dest, matrix, (j+4), rs, cs); \ col_m_order_1_kleft4(dest, matrix, (j+5), rs, cs); \ col_m_order_2_kleft4(dest, matrix, (j+5), rs, cs); \ col_m_order_1_kleft4(dest, matrix, (j+6), rs, cs); \ col_m_order_2_kleft4(dest, matrix, (j+6), rs, cs); \ col_m_order_1_kleft4(dest, matrix, (j+7), rs, cs); \ col_m_order_2_kleft4(dest, matrix, (j+7), rs, cs); #define bpad_col_kleft3(dest, matrix, rs, cs) \ col_m_order_1_kleft3(dest, matrix, (j ), rs, cs); \ col_m_order_2_kleft3(dest, matrix, (j ), rs, cs); \ col_m_order_1_kleft3(dest, matrix, (j+1), rs, cs); \ col_m_order_2_kleft3(dest, matrix, (j+1), rs, cs); \ col_m_order_1_kleft3(dest, matrix, (j+2), rs, cs); \ col_m_order_2_kleft3(dest, matrix, (j+2), rs, cs); \ col_m_order_1_kleft3(dest, matrix, (j+3), rs, cs); \ col_m_order_2_kleft3(dest, matrix, (j+3), rs, cs); \ col_m_order_1_kleft3(dest, matrix, (j+4), rs, cs); \ col_m_order_2_kleft3(dest, matrix, (j+4), rs, cs); \ col_m_order_1_kleft3(dest, matrix, (j+5), rs, cs); \ col_m_order_2_kleft3(dest, matrix, (j+5), rs, cs); \ col_m_order_1_kleft3(dest, matrix, (j+6), rs, cs); \ col_m_order_2_kleft3(dest, matrix, (j+6), rs, cs); \ col_m_order_1_kleft3(dest, matrix, (j+7), rs, cs); \ col_m_order_2_kleft3(dest, matrix, (j+7), rs, cs); #define bpad_col_kleft2(dest, matrix, rs, cs) \ col_m_order_1_kleft2(dest, matrix, (j ), rs, cs); \ col_m_order_2_kleft2(dest, matrix, (j ), rs, cs); \ col_m_order_1_kleft2(dest, matrix, (j+1), rs, cs); \ col_m_order_2_kleft2(dest, matrix, (j+1), rs, cs); \ col_m_order_1_kleft2(dest, matrix, (j+2), rs, cs); \ col_m_order_2_kleft2(dest, matrix, (j+2), rs, cs); \ col_m_order_1_kleft2(dest, matrix, (j+3), rs, cs); \ col_m_order_2_kleft2(dest, matrix, (j+3), rs, cs); \ col_m_order_1_kleft2(dest, matrix, (j+4), rs, cs); \ col_m_order_2_kleft2(dest, matrix, (j+4), rs, cs); \ col_m_order_1_kleft2(dest, matrix, (j+5), rs, cs); \ col_m_order_2_kleft2(dest, matrix, (j+5), rs, cs); \ col_m_order_1_kleft2(dest, matrix, (j+6), rs, cs); \ col_m_order_2_kleft2(dest, matrix, (j+6), rs, cs); \ col_m_order_1_kleft2(dest, matrix, (j+7), rs, cs); \ col_m_order_2_kleft2(dest, matrix, (j+7), rs, cs); #define bpad_col_kleft1(dest, matrix, rs, cs) \ col_m_order_1_kleft1(dest, matrix, (j ), rs, cs); \ col_m_order_2_kleft1(dest, matrix, (j ), rs, cs); \ col_m_order_1_kleft1(dest, matrix, (j+1), rs, cs); \ col_m_order_2_kleft1(dest, matrix, (j+1), rs, cs); \ col_m_order_1_kleft1(dest, matrix, (j+2), rs, cs); \ col_m_order_2_kleft1(dest, matrix, (j+2), rs, cs); \ col_m_order_1_kleft1(dest, matrix, (j+3), rs, cs); \ col_m_order_2_kleft1(dest, matrix, (j+3), rs, cs); \ col_m_order_1_kleft1(dest, matrix, (j+4), rs, cs); \ col_m_order_2_kleft1(dest, matrix, (j+4), rs, cs); \ col_m_order_1_kleft1(dest, matrix, (j+5), rs, cs); \ col_m_order_2_kleft1(dest, matrix, (j+5), rs, cs); \ col_m_order_1_kleft1(dest, matrix, (j+6), rs, cs); \ col_m_order_2_kleft1(dest, matrix, (j+6), rs, cs); \ col_m_order_1_kleft1(dest, matrix, (j+7), rs, cs); \ col_m_order_2_kleft1(dest, matrix, (j+7), rs, cs); /* The following macros handle non full size panels (ib/jb != MR/NR) and edge cases (k%8 != 0). */ #define edge(edgefun, dest, matrix, panel, left, rs, cs) \ for (int ir=0; ir>= 13; // Align mantissa on MSB t2 >>= 16; // Shift sign bit into position t1 -= 0x1c000; // Adjust bias t1 = (t3 < 0x38800000) ? 0 : t1; t1 = (t3 > 0x47000000) ? 0x7bff : t1; t1 = (t3 == 0 ? 0 : t1); // Denormals-as-zero t1 |= t2; // Re-insert sign bit f16_out.v = t1; return f16_out; } // cast float to bfloat16 bfloat16 cast_f32_to_bf16 (float val) { bfloat16 bf16; float32_s f32; f32.v = val; bf16.bits.s = f32.bits.s; bf16.bits.e = f32.bits.e; bf16.bits.m = f32.bits.m >> 16; return bf16; } // cast bfloat16 to float float cast_bf16_to_f32(bfloat16 val) { float32_s f32; f32.bits.s = val.bits.s; f32.bits.e = val.bits.e; f32.bits.m = val.bits.m << 16; return f32.v; } // cast a nibbles struct to a float array void cast_i4_to_f32(float *fvals, nibbles vals) { int8_t val0 = vals.bits.nib1; int8_t val1 = vals.bits.nib2; val0 = (val0 >= 8 ? val0 - 16 : val0); val1 = (val1 >= 8 ? val1 - 16 : val1); fvals[0] = (float) val0; fvals[1] = (float) val1; } // condense two float vals to a nibbles struct nibbles cast_f32_to_i4(float val0, float val1) { nibbles vals; int8_t val0_ = ((int8_t)val0) & 0xf0; int8_t val1_ = ((int8_t)val1) & 0xf0; vals.bits.nib1 = val0_; vals.bits.nib2 = val1_; return vals; } // cast float matrix to float nibbles void cast_f32_to_i4m(float *a_float, nibbles *a, int num_elems) { int j=0; for(int i=0; i // print kernel name const char* get_kernel_name(int kernel_id) { switch (kernel_id) { case FLOAT16 : return "bli_shgemm"; case BFLOAT16: return "bli_sbgemm"; case INT16 : return "bli_i16gemm"; case INT8 : return "bli_i8gemm"; case INT4 : return "bli_i4gemm"; default: printf("INCORRECT KERNEL ID\n"); exit(-1); } } // normalize the vector using the forbenious norm void normalize_vec(float *t, int n) { // normalize t float norm_factor; bli_snormfv(n, t, 1, &norm_factor); // round up to closest power of 2 norm_factor = 1 / (pow( 2.0, ceil( log2( norm_factor ) ) )); bli_sscalv(BLIS_NO_CONJUGATE, n, &norm_factor, t, 1); } // Pre-conditions: // - a is randomized. // - b is randomized. // - c_orig is randomized. // Note: // - alpha and beta should have non-zero imaginary components in the // complex cases in order to more fully exercise the implementation. // // Under these conditions, we assume that the implementation for // // C := beta * C_orig + alpha * transa(A) * transb(B) // // is functioning correctly if // // normfv( v - z ) // // is negligible, where // // v = C * t // z = ( beta * C_orig + alpha * transa(A) * transb(B) ) * t // = beta * C_orig * t + alpha * transa(A) * transb(B) * t // = beta * C_orig * t + alpha * transa(A) * w // = beta * C_orig * t + z float get_resid( int m, int n, int k, float *a, int rsa, int csa, float *b, int rsb, int csb, float *c, int rsc, int csc, float *c_orig, float *alpha, float *beta ) { float t[n], v[m], w[k], z[m]; float one = 1.0, zero = 0.0; bli_srandv(n, t, 1); // normalize so that the values are at the same precision of the input values normalize_vec(t, n); // v = C * t bli_sgemv( BLIS_NO_TRANSPOSE, BLIS_NO_CONJUGATE, m, n, &one, c, rsc, csc, t, 1, &zero, v, 1 ); // w = B * t bli_sgemv( BLIS_NO_TRANSPOSE, BLIS_NO_CONJUGATE, k, n, &one, b, rsb, csb, t, 1, &zero, w, 1 ); // z = alpha * A * w bli_sgemv( BLIS_NO_TRANSPOSE, BLIS_NO_CONJUGATE, m, k, alpha, a, rsa, csa, w, 1, &zero, z, 1 ); // z += beta * C_orig * t bli_sgemv( BLIS_NO_TRANSPOSE, BLIS_NO_CONJUGATE, m, n, beta, c_orig, rsc, csc, t, 1, &one, z, 1 ); // v = v - z bli_ssubv ( BLIS_NO_CONJUGATE, m, z, 1, v, 1 ); // norm = normfv(v) float norm; bli_snormfv ( m, v, 1, &norm ); return norm; } // test to see if the result from a BLIS GEMM kernel is correct for a given m x n x k mat-mul // assumes the matrices are of type float // assumes the matrices were randomized and normalized void correctness_checker( int m, int n, int k, float *a, int rsa, int csa, float *b, int rsb, int csb, float *c_orig, int rsc, int csc, float *c_ans, float alpha, float beta ) { double start, end; start = bli_clock(); float resid = get_resid ( m, n, k, a, rsa, csa, b, rsb, csb, c_ans, rsc, csc, c_orig, &alpha, &beta ); end = bli_clock(); printf("%d, %d, %d, %8.4le\n", m,n,k, resid); } // create all the correctness checking functions for each kernel GEN_FP_COR_KERNEL(sb, bli_sbgemm, bfloat16, cast_f32_to_bf16m, cast_bf16_to_f32m); GEN_FP_COR_KERNEL(sh, bli_shgemm, float16, cast_f32_to_f16m, cast_f16_to_f32m); GEN_I_COR_KERNEL(i16, bli_i16gemm, int16_t, cast_f32_to_i16m, cast_i16_to_f32m); GEN_I_COR_KERNEL(i8, bli_i8gemm, int8_t, cast_f32_to_i8m, cast_i8_to_f32m); // correctness template for int types void i4correctness_kernel (int m, int n, int k) { if(n%2 != 0) { printf("int4 can't handle odd sizes in the data-order dimension"); exit(-1); } int rsa = k, csa = 1, rsb = n, csb = 1, rsc = n, csc = 1; nibbles *a, *b; int32_t *c_ans, *c_orig, alpha, beta; float *a_float, *b_float, *c_ans_float, *c_orig_float; /* buffers that will be passed into the kernel */ // int4 buffers only need half the space to store all the elements a = (nibbles *) malloc (m * (k/2) * sizeof(nibbles)); b = (nibbles *) malloc (k * (n/2) * sizeof(nibbles)); c_ans = (int32_t *) malloc (m * n * sizeof(int32_t)); c_orig = (int32_t *) malloc (m * n * sizeof(int32_t)); /* std format buffers that will be used by the correctness checker */ a_float = (float *) malloc (m * k * sizeof(float)); b_float = (float *) malloc (k * n * sizeof(float)); c_ans_float = (float *) malloc (m * n * sizeof(float)); c_orig_float = (float *) malloc (m * n * sizeof(float)); /* randomize matrices with float vals */ bli_srandv(m*k, a_float, 1); bli_srandv(k*n, b_float, 1); bli_srandv(m*n, c_orig_float, 1); /* normalize the matrices */ normalize_vec(a_float, m*k); normalize_vec(b_float, k*n); normalize_vec(c_orig_float, m*n); /* cast the float buffers into the buffers for the kernel */ cast_f32_to_i4m (a_float, a, m*k); cast_f32_to_i4m (b_float, b, k*n); /* cast float buffers to support int values */ cast_f32_to_i32m(c_orig_float, c_orig, m*n); cast_i32_to_f32m(c_orig, c_orig_float, m*n); /* cast the kernel buffers into the float buffers to ensure that the values match */ cast_i4_to_f32m (a, a_float, m*k); cast_i4_to_f32m (b, b_float, k*n); /* init alpha and beta */ alpha = 1; beta = 1; /* run kernel to get result in c_ans */ // strides need to be adjusted since 1 element stores 2 values memcpy(c_ans, c_orig, m * n * sizeof(int)); bli_i4gemm( BLIS_NO_TRANSPOSE, BLIS_NO_TRANSPOSE, m, n, k, &alpha, a, rsa/2, csa, b, rsb/2, csb, &beta, c_ans, rsc, csc ); /* cast integer result into float buffer since float is our std format for correctness checking */ cast_i32_to_f32m(c_ans, c_ans_float, m*n); /* using the BLIS GEMM correctness check method, get the resid */ correctness_checker( m, n, k, a_float, rsa, csa, b_float, rsb, csb, c_orig_float, rsc, csc, c_ans_float, (float) alpha, (float) beta ); free(a); free(b); free(c_ans); free(c_orig); free(a_float); free(b_float); free(c_ans_float); free(c_orig_float); } // using the DATATYPE enum, gather test the correctness of the respective GEMM kernel void run_correctness_kernel(int kernel_id, int m, int n, int k) { switch (kernel_id) { case FLOAT16 : shcorrectness_kernel(m, n, k); break; case BFLOAT16: sbcorrectness_kernel(m, n, k); break; case INT16 : i16correctness_kernel(m, n, k); break; case INT8 : i8correctness_kernel(m, n, k); break; case INT4 : i4correctness_kernel(m, n, k); break; default: break; } } void test_correctness(int kernel_id, int start, int end, int inc) { printf("%s correctness test\n", get_kernel_name(kernel_id)); printf("m, n, k, resid\n"); int m,n,k; for (int p=start; p<=end; p+=inc) { m=n=k=p; run_correctness_kernel(kernel_id, m, n, k); } } // correctness test for bfloat16 gemm int main(int argc, char *argv[]) { test_correctness(FLOAT16, 80, 4000, 80); test_correctness(BFLOAT16, 80, 4000, 80); test_correctness(INT16, 80, 4000, 80); test_correctness(INT8, 80, 4000, 80); test_correctness(INT4, 80, 4000, 80); } blis-0.9.0/sandbox/power10/p10_testsuite/correctness.h000066400000000000000000000121761422157504600226350ustar00rootroot00000000000000// templates for generating correctness checking functions that check the correctness of GEMM kernels // using the BLIS GEMM correctness method #define COR_KERNEL_NAME_(ch) ch ## correctness_kernel #define COR_KERNEL_NAME(ch) COR_KERNEL_NAME_(ch) // correctness template for float types #define GEN_FP_COR_KERNEL(ch, kernel, input_t, DOWN_CAST, UP_CAST) \ void COR_KERNEL_NAME(ch) (int m, int n, int k) \ { \ int rsa = k, csa = 1, \ rsb = n, csb = 1, \ rsc = n, csc = 1; \ \ input_t *a, *b; \ \ float *a_float, *b_float, \ *c_ans_float, *c_orig_float, \ alpha, beta; \ \ /* buffers that will be passed into the kernel */ \ a = (input_t *) malloc (m * k * sizeof(input_t)); \ b = (input_t *) malloc (k * n * sizeof(input_t)); \ \ /* std format buffers that will be used by the correctness checker */ \ a_float = (float *) malloc (m * k * sizeof(float)); \ b_float = (float *) malloc (k * n * sizeof(float)); \ c_ans_float = (float *) malloc (m * n * sizeof(float)); \ c_orig_float = (float *) malloc (m * n * sizeof(float)); \ \ /* randomize matrices with float vals */ \ bli_srandv(m*k, a_float, 1); \ bli_srandv(k*n, b_float, 1); \ bli_srandv(m*n, c_orig_float, 1); \ \ /* normalize the matrices */ \ normalize_vec(a_float, m*k); \ normalize_vec(b_float, k*n); \ normalize_vec(c_orig_float, m*n); \ \ /* cast the float buffers into the buffers for the kernel */ \ DOWN_CAST (a_float, a, m*k); \ DOWN_CAST (b_float, b, k*n); \ \ /* cast the kernel buffers into the float buffers to ensure that the values match */ \ UP_CAST (a, a_float, m*k); \ UP_CAST (b, b_float, k*n); \ \ /* init alpha and beta */ \ alpha = 1; \ beta = 1; \ \ memcpy(c_ans_float, c_orig_float, m * n * sizeof(float)); \ kernel( \ BLIS_NO_TRANSPOSE, \ BLIS_NO_TRANSPOSE, \ m, \ n, \ k, \ &alpha, \ a, rsa, csa, \ b, rsb, csb, \ &beta, \ c_ans_float, rsc, csc \ ); \ \ correctness_checker( \ m, n, k, \ a_float, rsa, csa, \ b_float, rsb, csb, \ c_orig_float, rsc, csc, \ c_ans_float, \ alpha, beta \ ); \ \ free(a); \ free(b); \ free(a_float); \ free(b_float); \ free(c_ans_float); \ free(c_orig_float); \ \ } // correctness template for int types #define GEN_I_COR_KERNEL(ch, kernel, input_t, DOWN_CAST, UP_CAST) \ void COR_KERNEL_NAME(ch) (int m, int n, int k) \ { \ int rsa = k, csa = 1, \ rsb = n, csb = 1, \ rsc = n, csc = 1; \ \ input_t *a, *b; \ \ int32_t *c_ans, *c_orig, alpha, beta; \ \ float *a_float, *b_float, \ *c_ans_float, *c_orig_float; \ \ /* buffers that will be passed into the kernel */ \ a = (input_t *) malloc (m * k * sizeof(input_t)); \ b = (input_t *) malloc (k * n * sizeof(input_t)); \ c_ans = (int32_t *) malloc (m * n * sizeof(int32_t)); \ c_orig = (int32_t *) malloc (m * n * sizeof(int32_t)); \ \ /* std format buffers that will be used by the correctness checker */ \ a_float = (float *) malloc (m * k * sizeof(float)); \ b_float = (float *) malloc (k * n * sizeof(float)); \ c_ans_float = (float *) malloc (m * n * sizeof(float)); \ c_orig_float = (float *) malloc (m * n * sizeof(float)); \ \ /* randomize matrices with float vals */ \ bli_srandv(m*k, a_float, 1); \ bli_srandv(k*n, b_float, 1); \ bli_srandv(m*n, c_orig_float, 1); \ \ /* normalize the matrices */ \ normalize_vec(a_float, m*k); \ normalize_vec(b_float, k*n); \ normalize_vec(c_orig_float, m*n); \ \ /* cast the float buffers into the buffers for the kernel */ \ DOWN_CAST (a_float, a, m*k); \ DOWN_CAST (b_float, b, k*n); \ \ /* cast float buffers to support int values */ \ cast_f32_to_i32m(c_orig_float, c_orig, m*n); \ cast_i32_to_f32m(c_orig, c_orig_float, m*n); \ \ /* cast the kernel buffers into the float buffers to ensure that the values match */ \ UP_CAST (a, a_float, m*k); \ UP_CAST (b, b_float, k*n); \ \ /* init alpha and beta */ \ alpha = 1; \ beta = 1; \ \ /* run kernel to get result in c_ans */ \ memcpy(c_ans, c_orig, m * n * sizeof(int)); \ kernel( \ BLIS_NO_TRANSPOSE, \ BLIS_NO_TRANSPOSE, \ m, \ n, \ k, \ &alpha, \ a, rsa, csa, \ b, rsb, csb, \ &beta, \ c_ans, rsc, csc \ ); \ \ /* cast integer result into float buffer since float is our std format for correctness checking */ \ cast_i32_to_f32m(c_ans, c_ans_float, m*n); \ \ /* using the BLIS GEMM correctness check method, get the resid */ \ correctness_checker( \ m, n, k, \ a_float, rsa, csa, \ b_float, rsb, csb, \ c_orig_float, rsc, csc, \ c_ans_float, \ (float) alpha, (float) beta \ ); \ \ free(a); \ free(b); \ free(c_ans); \ free(c_orig); \ free(a_float); \ free(b_float); \ free(c_ans_float); \ free(c_orig_float); \ \ } blis-0.9.0/sandbox/power10/p10_testsuite/performance.c000066400000000000000000000055341422157504600225770ustar00rootroot00000000000000/* This program is designed to gather the performance data of the POWER10 GEMM kernels in `blis/sandbox/power10`. By default, the performance of the kernels is gather over a set of square matrices. The perfromance results are reported in GFLOPS, and outputted in CSV format. */ #include "performance.h" #include "blis.h" #include "../bli_sandbox.h" #include "common.h" #include // print kernel name const char* get_kernel_name(int kernel_id) { switch (kernel_id) { case FLOAT16 : return "bli_shgemm"; case BFLOAT16: return "bli_sbgemm"; case INT16 : return "bli_i16gemm"; case INT8 : return "bli_i8gemm"; case INT4 : return "bli_i4gemm"; default: printf("INCORRECT KERNEL ID\n"); exit(-1); } } // create all the performance gathering functions for each kernel GET_PERF_API_TEMP(sb, bli_sbgemm, bfloat16, float); GET_PERF_API_TEMP(sh, bli_shgemm, float16, float); GET_PERF_API_TEMP(i16, bli_i16gemm, int16_t, int); GET_PERF_API_TEMP(i8, bli_i8gemm, int8_t, int); GET_PERF_API_TEMP(i4, bli_i4gemm, nibbles, int); // using the DATATYPE enum, gather the performance of the respective GEMM kernel double run_kernel(int kernel_id, int nreps, int m, int n, int k) { switch (kernel_id) { case FLOAT16 : return test_shapi(nreps, m, n, k); case BFLOAT16: return test_sbapi(nreps, m, n, k); case INT16 : return test_i16api(nreps, m, n, k); case INT8 : return test_i8api(nreps, m, n, k); case INT4 : return test_i4api(nreps, m, n, k); default: return -1.0; } } // print the performance data in CSV format // performance is measured in terms of GFLOPs void print_perf_data(int m, int n, int k, double best_time) { double GFLOPS = (2.0 * m * n * k) / (1e9 * best_time); printf("%d, %d, %d, %.2f\n", m, n, k, GFLOPS); } // get performance data void get_perf(int kernel_id, int nreps, int start, int end, int inc) { // csv header printf("%s performance\n", get_kernel_name(kernel_id)); printf("m, n, k, GFLOPS\n"); int m,n,k; // run over all problem sizes for (int p=start; p<=end; p+=inc) { // change here to adjust problem size m = p, n = p, k = p; double best_run_time = run_kernel(kernel_id, nreps, m, n, k); print_perf_data(m, n, k, best_run_time); } } int main(int argc, char *argv[]) { // initialize a square problem set range int start = 80; int end = 4000; int inc = 80; // number of times the kernel will be run int nreps = 5; // run a respective kernel get_perf( FLOAT16, nreps, start, end, inc); get_perf(BFLOAT16, nreps, start, end, inc); get_perf( INT16, nreps, start, end, inc); get_perf( INT8, nreps, start, end, inc); get_perf( INT4, nreps, start, end, inc); return 0; } blis-0.9.0/sandbox/power10/p10_testsuite/performance.h000066400000000000000000000024141422157504600225760ustar00rootroot00000000000000 // function name template // each function that will gather perform will be named test_api #define GEN_PERF_FUNC_NAME_(ch) test_ ## ch ## api #define GEN_PERF_FUNC_NAME(ch) GEN_PERF_FUNC_NAME_(ch) /* Macro template for getting the best GEMM kernel runtime out of `num_runs` for matrices of size (m x n x k). */ #define GET_PERF_API_TEMP(ch, kernel, input_t, output_t) \ double GEN_PERF_FUNC_NAME(ch) ( \ int num_runs, \ int m, \ int n, \ int k \ ) \ { \ input_t *A,*B; \ output_t *C; \ output_t alpha,beta; \ \ A = (input_t*) malloc(m*k*sizeof(input_t)); \ B = (input_t*) malloc(n*k*sizeof(input_t)); \ C = (output_t*) malloc(m*n*sizeof(output_t)); \ \ alpha = 1; \ beta = 1; \ \ double best = 1e9; \ \ for (int irep=0; irep 1, we skip this test. if [ "${im}" = "eigen" ] && \ [ "${op}" != "gemm" ] && \ [ "${nt}" != "1" ]; then continue; fi # Find the threading suffix by probing the executable. binname=$(ls ${exec_root}_${dt}${op}_${psize}_${im}_*.x) suf_ext=${binname##*_} suf=${suf_ext%%.*} #echo "found file: ${binname} with suffix ${suf}" # Set the number of threads according to th. if [ "${suf}" = "1s" ] || [ "${suf}" = "2s" ]; then # Set the threading parameters based on the implementation # that we are preparing to run. if [ "${im}" = "asm_blis" ] || \ [ "${im}" = "1m_blis" ]; then unset OMP_NUM_THREADS export BLIS_JC_NT=${jc_nt} export BLIS_PC_NT=${pc_nt} export BLIS_IC_NT=${ic_nt} export BLIS_JR_NT=${jr_nt} export BLIS_IR_NT=${ir_nt} elif [ "${im}" = "openblas" ]; then unset OMP_NUM_THREADS export OPENBLAS_NUM_THREADS=${nt} elif [ "${im}" = "eigen" ]; then export OMP_NUM_THREADS=${nt} elif [ "${im}" = "vendor" ]; then unset OMP_NUM_THREADS export MKL_NUM_THREADS=${nt} fi export nt_use=${nt} # Multithreaded OpenBLAS seems to have a problem running # properly if GOMP_CPU_AFFINITY is set. So we temporarily # unset it here if we are about to execute OpenBLAS, but # otherwise restore it. if [ ${im} = "openblas" ]; then unset GOMP_CPU_AFFINITY else export GOMP_CPU_AFFINITY="${GOMP_CPU_AFFINITYsave}" fi else export BLIS_JC_NT=1 export BLIS_PC_NT=1 export BLIS_IC_NT=1 export BLIS_JR_NT=1 export BLIS_IR_NT=1 export OMP_NUM_THREADS=1 export OPENBLAS_NUM_THREADS=1 export MKL_NUM_THREADS=1 export nt_use=1 fi # Construct the name of the test executable. exec_name="${exec_root}_${dt}${op}_${psize}_${im}_${suf}.x" # Construct the name of the output file. out_file="${out_root}_${suf}_${dt}${op}_${im}.m" #echo "Running (nt = ${nt_use}) ./${exec_name} > ${out_file}" echo "Running: ${runcmd} ./${exec_name} > ${out_file}" # Run executable. #./${exec_name} > ${out_file} #numactl -i all ./${exec_name} > ${out_file} eval "${runcmd} ./${exec_name} > ${out_file}" sleep ${delay} done done done done blis-0.9.0/test/1m4m/test_gemm.c000066400000000000000000000277101422157504600163530ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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 The University of Texas 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 COPYRIGHT HOLDER 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. */ #include #ifdef EIGEN #define BLIS_DISABLE_BLAS_DEFS #include "blis.h" #include #include using namespace Eigen; #else #include "blis.h" #endif #define COL_STORAGE //#define ROW_STORAGE //#define PRINT int main( int argc, char** argv ) { obj_t a, b, c; obj_t c_save; obj_t alpha, beta; dim_t m, n, k; dim_t p; dim_t p_begin, p_max, p_inc; int m_input, n_input, k_input; ind_t ind; num_t dt; char dt_ch; int r, n_repeats; trans_t transa; trans_t transb; f77_char f77_transa; f77_char f77_transb; double dtime; double dtime_save; double gflops; //bli_init(); bli_error_checking_level_set( BLIS_NO_ERROR_CHECKING ); n_repeats = 3; dt = DT; ind = IND; #if 1 p_begin = P_BEGIN; p_max = P_MAX; p_inc = P_INC; m_input = -1; n_input = -1; k_input = -1; #else p_begin = 40; p_max = 2000; p_inc = 40; m_input = -1; n_input = -1; k_input = -1; #endif // Supress compiler warnings about unused variable 'ind'. ( void )ind; #if 0 cntx_t* cntx; ind_t ind_mod = ind; // Initialize a context for the current induced method and datatype. cntx = bli_gks_query_ind_cntx( ind_mod, dt ); // Set k to the kc blocksize for the current datatype. k_input = bli_cntx_get_blksz_def_dt( dt, BLIS_KC, cntx ); #elif 0 #ifdef BLIS if ( ind == BLIS_1M ) k_input = 128; else k_input = 256; #else k_input = 192; #endif #endif // Choose the char corresponding to the requested datatype. if ( bli_is_float( dt ) ) dt_ch = 's'; else if ( bli_is_double( dt ) ) dt_ch = 'd'; else if ( bli_is_scomplex( dt ) ) dt_ch = 'c'; else dt_ch = 'z'; transa = BLIS_NO_TRANSPOSE; transb = BLIS_NO_TRANSPOSE; bli_param_map_blis_to_netlib_trans( transa, &f77_transa ); bli_param_map_blis_to_netlib_trans( transb, &f77_transb ); // Begin with initializing the last entry to zero so that // matlab allocates space for the entire array once up-front. for ( p = p_begin; p + p_inc <= p_max; p += p_inc ) ; printf( "data_%s_%cgemm_%s", THR_STR, dt_ch, STR ); printf( "( %2lu, 1:4 ) = [ %4lu %4lu %4lu %7.2f ];\n", ( unsigned long )(p - p_begin)/p_inc + 1, ( unsigned long )0, ( unsigned long )0, ( unsigned long )0, 0.0 ); //for ( p = p_begin; p <= p_max; p += p_inc ) for ( p = p_max; p_begin <= p; p -= p_inc ) { if ( m_input < 0 ) m = p / ( dim_t )abs(m_input); else m = ( dim_t ) m_input; if ( n_input < 0 ) n = p / ( dim_t )abs(n_input); else n = ( dim_t ) n_input; if ( k_input < 0 ) k = p / ( dim_t )abs(k_input); else k = ( dim_t ) k_input; bli_obj_create( dt, 1, 1, 0, 0, &alpha ); bli_obj_create( dt, 1, 1, 0, 0, &beta ); #ifdef COL_STORAGE bli_obj_create( dt, m, k, 0, 0, &a ); bli_obj_create( dt, k, n, 0, 0, &b ); bli_obj_create( dt, m, n, 0, 0, &c ); bli_obj_create( dt, m, n, 0, 0, &c_save ); #else bli_obj_create( dt, m, k, k, 1, &a ); bli_obj_create( dt, k, n, n, 1, &b ); bli_obj_create( dt, m, n, n, 1, &c ); bli_obj_create( dt, m, n, n, 1, &c_save ); #endif bli_randm( &a ); bli_randm( &b ); bli_randm( &c ); bli_obj_set_conjtrans( transa, &a ); bli_obj_set_conjtrans( transb, &b ); bli_setsc( (1.0/1.0), 0.0, &alpha ); bli_setsc( (1.0/1.0), 0.0, &beta ); bli_copym( &c, &c_save ); #ifdef BLIS bli_ind_disable_all_dt( dt ); bli_ind_enable_dt( ind, dt ); #endif #ifdef EIGEN double alpha_r, alpha_i; bli_getsc( &alpha, &alpha_r, &alpha_i ); void* ap = bli_obj_buffer_at_off( &a ); void* bp = bli_obj_buffer_at_off( &b ); void* cp = bli_obj_buffer_at_off( &c ); #ifdef COL_STORAGE const int os_a = bli_obj_col_stride( &a ); const int os_b = bli_obj_col_stride( &b ); const int os_c = bli_obj_col_stride( &c ); #else const int os_a = bli_obj_row_stride( &a ); const int os_b = bli_obj_row_stride( &b ); const int os_c = bli_obj_row_stride( &c ); #endif Stride stride_a( os_a, 1 ); Stride stride_b( os_b, 1 ); Stride stride_c( os_c, 1 ); #ifdef COL_STORAGE #if defined(IS_FLOAT) typedef Matrix MatrixXf_; #elif defined (IS_DOUBLE) typedef Matrix MatrixXd_; #elif defined (IS_SCOMPLEX) typedef Matrix, Dynamic, Dynamic, ColMajor> MatrixXcf_; #elif defined (IS_DCOMPLEX) typedef Matrix, Dynamic, Dynamic, ColMajor> MatrixXcd_; #endif #else #if defined(IS_FLOAT) typedef Matrix MatrixXf_; #elif defined (IS_DOUBLE) typedef Matrix MatrixXd_; #elif defined (IS_SCOMPLEX) typedef Matrix, Dynamic, Dynamic, RowMajor> MatrixXcf_; #elif defined (IS_DCOMPLEX) typedef Matrix, Dynamic, Dynamic, RowMajor> MatrixXcd_; #endif #endif #if defined(IS_FLOAT) Map > A( ( float* )ap, m, k, stride_a ); Map > B( ( float* )bp, k, n, stride_b ); Map > C( ( float* )cp, m, n, stride_c ); #elif defined (IS_DOUBLE) Map > A( ( double* )ap, m, k, stride_a ); Map > B( ( double* )bp, k, n, stride_b ); Map > C( ( double* )cp, m, n, stride_c ); #elif defined (IS_SCOMPLEX) Map > A( ( std::complex* )ap, m, k, stride_a ); Map > B( ( std::complex* )bp, k, n, stride_b ); Map > C( ( std::complex* )cp, m, n, stride_c ); #elif defined (IS_DCOMPLEX) Map > A( ( std::complex* )ap, m, k, stride_a ); Map > B( ( std::complex* )bp, k, n, stride_b ); Map > C( ( std::complex* )cp, m, n, stride_c ); #endif #endif dtime_save = DBL_MAX; for ( r = 0; r < n_repeats; ++r ) { bli_copym( &c_save, &c ); dtime = bli_clock(); #ifdef PRINT bli_printm( "a", &a, "%4.1f", "" ); bli_printm( "b", &b, "%4.1f", "" ); bli_printm( "c", &c, "%4.1f", "" ); #endif #if defined(BLIS) bli_gemm( &alpha, &a, &b, &beta, &c ); #elif defined(EIGEN) C.noalias() += alpha_r * A * B; #else // if defined(BLAS) if ( bli_is_float( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); float* alphap = ( float* )bli_obj_buffer( &alpha ); float* ap = ( float* )bli_obj_buffer( &a ); float* bp = ( float* )bli_obj_buffer( &b ); float* betap = ( float* )bli_obj_buffer( &beta ); float* cp = ( float* )bli_obj_buffer( &c ); sgemm_( &f77_transa, &f77_transb, &mm, &nn, &kk, alphap, ap, &lda, bp, &ldb, betap, cp, &ldc ); } else if ( bli_is_double( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); double* alphap = ( double* )bli_obj_buffer( &alpha ); double* ap = ( double* )bli_obj_buffer( &a ); double* bp = ( double* )bli_obj_buffer( &b ); double* betap = ( double* )bli_obj_buffer( &beta ); double* cp = ( double* )bli_obj_buffer( &c ); dgemm_( &f77_transa, &f77_transb, &mm, &nn, &kk, alphap, ap, &lda, bp, &ldb, betap, cp, &ldc ); } else if ( bli_is_scomplex( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); scomplex* alphap = ( scomplex* )bli_obj_buffer( &alpha ); scomplex* ap = ( scomplex* )bli_obj_buffer( &a ); scomplex* bp = ( scomplex* )bli_obj_buffer( &b ); scomplex* betap = ( scomplex* )bli_obj_buffer( &beta ); scomplex* cp = ( scomplex* )bli_obj_buffer( &c ); cgemm_( &f77_transa, &f77_transb, &mm, &nn, &kk, alphap, ap, &lda, bp, &ldb, betap, cp, &ldc ); } else if ( bli_is_dcomplex( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); dcomplex* alphap = ( dcomplex* )bli_obj_buffer( &alpha ); dcomplex* ap = ( dcomplex* )bli_obj_buffer( &a ); dcomplex* bp = ( dcomplex* )bli_obj_buffer( &b ); dcomplex* betap = ( dcomplex* )bli_obj_buffer( &beta ); dcomplex* cp = ( dcomplex* )bli_obj_buffer( &c ); zgemm_( &f77_transa, &f77_transb, &mm, &nn, &kk, alphap, ap, &lda, bp, &ldb, betap, cp, &ldc ); } #endif #ifdef PRINT bli_printm( "c after", &c, "%4.1f", "" ); exit(1); #endif dtime_save = bli_clock_min_diff( dtime_save, dtime ); } gflops = ( 2.0 * m * k * n ) / ( dtime_save * 1.0e9 ); if ( bli_is_complex( dt ) ) gflops *= 4.0; printf( "data_%s_%cgemm_%s", THR_STR, dt_ch, STR ); printf( "( %2lu, 1:4 ) = [ %4lu %4lu %4lu %7.2f ];\n", ( unsigned long )(p - p_begin)/p_inc + 1, ( unsigned long )m, ( unsigned long )k, ( unsigned long )n, gflops ); //fflush( stdout ); bli_obj_free( &alpha ); bli_obj_free( &beta ); bli_obj_free( &a ); bli_obj_free( &b ); bli_obj_free( &c ); bli_obj_free( &c_save ); } //bli_finalize(); return 0; } blis-0.9.0/test/3/000077500000000000000000000000001422157504600136005ustar00rootroot00000000000000blis-0.9.0/test/3/Makefile000066400000000000000000000372361422157504600152530ustar00rootroot00000000000000#!/bin/bash # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2014, The University of Texas at Austin # Copyright (C) 2018, Advanced Micro Devices, Inc. # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # # # Makefile # # Field G. Van Zee # # Makefile for standalone BLIS test drivers. # # # --- Makefile PHONY target definitions ---------------------------------------- # .PHONY: all \ check-env check-env-mk check-lib \ clean cleanx # # --- Determine makefile fragment location ------------------------------------- # # Comments: # - DIST_PATH is assumed to not exist if BLIS_INSTALL_PATH is given. # - We must use recursively expanded assignment for LIB_PATH and INC_PATH in # the second case because CONFIG_NAME is not yet set. ifneq ($(strip $(BLIS_INSTALL_PATH)),) LIB_PATH := $(BLIS_INSTALL_PATH)/lib INC_PATH := $(BLIS_INSTALL_PATH)/include/blis SHARE_PATH := $(BLIS_INSTALL_PATH)/share/blis else DIST_PATH := ../.. LIB_PATH = ../../lib/$(CONFIG_NAME) INC_PATH = ../../include/$(CONFIG_NAME) SHARE_PATH := ../.. endif # # --- Include common makefile definitions -------------------------------------- # # Include the common makefile fragment. -include $(SHARE_PATH)/common.mk # # --- BLAS implementations ----------------------------------------------------- # # BLAS library path(s). This is where the BLAS libraries reside. HOME_LIB_PATH := $(HOME)/flame/lib # OpenBLAS OPENBLAS_LIB := $(HOME_LIB_PATH)/libopenblas.a OPENBLASP_LIB := $(HOME_LIB_PATH)/libopenblasp.a # ATLAS #ATLAS_LIB := $(HOME_LIB_PATH)/libf77blas.a \ # $(HOME_LIB_PATH)/libatlas.a # Eigen EIGEN_INC := $(HOME)/flame/eigen/include/eigen3 EIGEN_LIB := $(HOME_LIB_PATH)/libeigen_blas_static.a EIGENP_LIB := $(EIGEN_LIB) # MKL MKL_LIB_PATH := $(HOME)/intel/mkl/lib/intel64 MKL_LIB := -L$(MKL_LIB_PATH) \ -lmkl_intel_lp64 \ -lmkl_core \ -lmkl_sequential \ -lpthread -lm -ldl #MKLP_LIB := -L$(MKL_LIB_PATH) \ # -lmkl_intel_thread \ # -lmkl_core \ # -lmkl_intel_ilp64 \ # -L$(ICC_LIB_PATH) \ # -liomp5 MKLP_LIB := -L$(MKL_LIB_PATH) \ -lmkl_intel_lp64 \ -lmkl_core \ -lmkl_gnu_thread \ -lpthread -lm -ldl -fopenmp #-L$(ICC_LIB_PATH) \ #-lgomp VENDOR_LIB := $(MKL_LIB) VENDORP_LIB := $(MKLP_LIB) # # --- Problem size definitions ------------------------------------------------- # # Single core (single-threaded) PS_BEGIN := 48 PS_MAX := 2400 PS_INC := 48 # Single-socket (multithreaded) P1_BEGIN := 120 P1_MAX := 6000 P1_INC := 120 # Dual-socket (multithreaded) P2_BEGIN := 160 P2_MAX := 8000 P2_INC := 160 # # --- General build definitions ------------------------------------------------ # TEST_SRC_PATH := . TEST_OBJ_PATH := . # Gather all local object files. TEST_OBJS := $(sort $(patsubst $(TEST_SRC_PATH)/%.c, \ $(TEST_OBJ_PATH)/%.o, \ $(wildcard $(TEST_SRC_PATH)/*.c))) # Override the value of CINCFLAGS so that the value of CFLAGS returned by # get-user-cflags-for() is not cluttered up with include paths needed only # while building BLIS. CINCFLAGS := -I$(INC_PATH) # Use the "framework" CFLAGS for the configuration family. CFLAGS := $(call get-user-cflags-for,$(CONFIG_NAME)) # Add local header paths to CFLAGS. CFLAGS += -I$(TEST_SRC_PATH) # Locate the libblis library to which we will link. #LIBBLIS_LINK := $(LIB_PATH)/$(LIBBLIS_L) # Define a set of CFLAGS for use with C++ and Eigen. CXXFLAGS := $(subst -std=c99,-std=c++11,$(CFLAGS)) CXXFLAGS += -I$(EIGEN_INC) # Create a copy of CXXFLAGS without -fopenmp in order to disable multithreading. CXXFLAGS_ST := -march=native $(subst -fopenmp,,$(CXXFLAGS)) CXXFLAGS_MT := -march=native $(CXXFLAGS) # Which library? BLI_DEF := -DBLIS BLA_DEF := -DBLAS EIG_DEF := -DEIGEN # Complex implementation type D1M := -DIND=BLIS_1M DNAT := -DIND=BLIS_NAT # Implementation string #STR_1M := -DSTR=\"1m\" STR_NAT := -DSTR=\"asm_blis\" STR_OBL := -DSTR=\"openblas\" STR_EIG := -DSTR=\"eigen\" STR_VEN := -DSTR=\"vendor\" # Single or multithreaded string STR_ST := -DTHR_STR=\"st\" STR_1S := -DTHR_STR=\"1s\" STR_2S := -DTHR_STR=\"2s\" # Problem size specification PDEF_ST := -DP_BEGIN=$(PS_BEGIN) -DP_INC=$(PS_INC) -DP_MAX=$(PS_MAX) PDEF_1S := -DP_BEGIN=$(P1_BEGIN) -DP_INC=$(P1_INC) -DP_MAX=$(P1_MAX) PDEF_2S := -DP_BEGIN=$(P2_BEGIN) -DP_INC=$(P2_INC) -DP_MAX=$(P2_MAX) # # --- Targets/rules ------------------------------------------------------------ # all: all-st all-1s all-2s blis: blis-st blis-1s blis-2s openblas: openblas-st openblas-1s openblas-2s eigen: eigen-st eigen-1s eigen-2s vendor: vendor-st vendor-1s vendor-2s mkl: vendor armpl: vendor all-st: blis-st openblas-st mkl-st eigen-st all-1s: blis-1s openblas-1s mkl-1s eigen-1s all-2s: blis-2s openblas-2s mkl-2s eigen-2s blis-st: blis-nat-st blis-1s: blis-nat-1s blis-2s: blis-nat-2s #blis-ind: blis-ind-st blis-ind-mt blis-nat: blis-nat-st blis-nat-1s blis-nat-2s # Define the datatypes, operations, and implementations. DTS := s d c z OPS := gemm hemm herk trmm trsm BIMPLS := asm_blis openblas vendor EIMPLS := eigen # Define functions to construct object filenames from the datatypes and # operations given an implementation. We define one function for single- # threaded, single-socket, and dual-socket filenames. get-st-objs = $(foreach dt,$(DTS),$(foreach op,$(OPS),test_$(dt)$(op)_$(PS_MAX)_$(1)_st.o)) get-1s-objs = $(foreach dt,$(DTS),$(foreach op,$(OPS),test_$(dt)$(op)_$(P1_MAX)_$(1)_1s.o)) get-2s-objs = $(foreach dt,$(DTS),$(foreach op,$(OPS),test_$(dt)$(op)_$(P2_MAX)_$(1)_2s.o)) # Construct object and binary names for single-threaded, single-socket, and # dual-socket files for BLIS, OpenBLAS, and a vendor library (e.g. MKL). BLIS_NAT_ST_OBJS := $(call get-st-objs,asm_blis) BLIS_NAT_ST_BINS := $(patsubst %.o,%.x,$(BLIS_NAT_ST_OBJS)) BLIS_NAT_1S_OBJS := $(call get-1s-objs,asm_blis) BLIS_NAT_1S_BINS := $(patsubst %.o,%.x,$(BLIS_NAT_1S_OBJS)) BLIS_NAT_2S_OBJS := $(call get-2s-objs,asm_blis) BLIS_NAT_2S_BINS := $(patsubst %.o,%.x,$(BLIS_NAT_2S_OBJS)) OPENBLAS_ST_OBJS := $(call get-st-objs,openblas) OPENBLAS_ST_BINS := $(patsubst %.o,%.x,$(OPENBLAS_ST_OBJS)) OPENBLAS_1S_OBJS := $(call get-1s-objs,openblas) OPENBLAS_1S_BINS := $(patsubst %.o,%.x,$(OPENBLAS_1S_OBJS)) OPENBLAS_2S_OBJS := $(call get-2s-objs,openblas) OPENBLAS_2S_BINS := $(patsubst %.o,%.x,$(OPENBLAS_2S_OBJS)) EIGEN_ST_OBJS := $(call get-st-objs,eigen) EIGEN_ST_BINS := $(patsubst %.o,%.x,$(EIGEN_ST_OBJS)) EIGEN_1S_OBJS := $(call get-1s-objs,eigen) EIGEN_1S_BINS := $(patsubst %.o,%.x,$(EIGEN_1S_OBJS)) EIGEN_2S_OBJS := $(call get-2s-objs,eigen) EIGEN_2S_BINS := $(patsubst %.o,%.x,$(EIGEN_2S_OBJS)) VENDOR_ST_OBJS := $(call get-st-objs,vendor) VENDOR_ST_BINS := $(patsubst %.o,%.x,$(VENDOR_ST_OBJS)) VENDOR_1S_OBJS := $(call get-1s-objs,vendor) VENDOR_1S_BINS := $(patsubst %.o,%.x,$(VENDOR_1S_OBJS)) VENDOR_2S_OBJS := $(call get-2s-objs,vendor) VENDOR_2S_BINS := $(patsubst %.o,%.x,$(VENDOR_2S_OBJS)) # Define some targets associated with the above object/binary files. blis-nat-st: check-env $(BLIS_NAT_ST_BINS) blis-nat-1s: check-env $(BLIS_NAT_1S_BINS) blis-nat-2s: check-env $(BLIS_NAT_2S_BINS) openblas-st: check-env $(OPENBLAS_ST_BINS) openblas-1s: check-env $(OPENBLAS_1S_BINS) openblas-2s: check-env $(OPENBLAS_2S_BINS) eigen-st: check-env $(EIGEN_ST_BINS) eigen-1s: check-env $(EIGEN_1S_BINS) eigen-2s: check-env $(EIGEN_2S_BINS) vendor-st: check-env $(VENDOR_ST_BINS) vendor-1s: check-env $(VENDOR_1S_BINS) vendor-2s: check-env $(VENDOR_2S_BINS) mkl-st: vendor-st mkl-1s: vendor-1s mkl-2s: vendor-2s armpl-st: vendor-st armpl-1s: vendor-1s armpl-2s: vendor-2s # Mark the object files as intermediate so that make will remove them # automatically after building the binaries on which they depend. .INTERMEDIATE: $(BLIS_NAT_ST_OBJS) $(BLIS_NAT_1S_OBJS) $(BLIS_NAT_2S_OBJS) .INTERMEDIATE: $(OPENBLAS_ST_OBJS) $(OPENBLAS_1S_OBJS) $(OPENBLAS_2S_OBJS) .INTERMEDIATE: $(EIGEN_ST_OBJS) $(EIGEN_1S_OBJS) $(EIGEN_2S_OBJS) .INTERMEDIATE: $(VENDOR_ST_OBJS) $(VENDOR_1S_OBJS) $(VENDOR_2S_OBJS) # -- Object file rules -- #$(TEST_OBJ_PATH)/%.o: $(TEST_SRC_PATH)/%.c # $(CC) $(CFLAGS) -c $< -o $@ # A function to return the datatype cpp macro def from the datatype # character. get-dt-cpp = $(strip \ $(if $(findstring s,$(1)),-DDT=BLIS_FLOAT -DIS_FLOAT,\ $(if $(findstring d,$(1)),-DDT=BLIS_DOUBLE -DIS_DOUBLE,\ $(if $(findstring c,$(1)),-DDT=BLIS_SCOMPLEX -DIS_SCOMPLEX,\ -DDT=BLIS_DCOMPLEX -DIS_DCOMPLEX)))) # A function to return other cpp macros that help the test driver # identify the implementation. #get-bl-cpp = $(strip \ # $(if $(findstring blis,$(1)),$(STR_NAT) $(BLI_DEF),\ # $(if $(findstring openblas,$(1)),$(STR_OBL) $(BLA_DEF),\ # $(if $(findstring eigen,$(1)),$(STR_EIG) $(EIG_DEF),\ # $(STR_VEN) $(BLA_DEF))))) get-bl-cpp = $(strip \ $(if $(findstring blis,$(1)),$(STR_NAT) $(BLI_DEF),\ $(if $(findstring openblas,$(1)),$(STR_OBL) $(BLA_DEF),\ $(if $(and $(findstring eigen,$(1)),\ $(findstring gemm,$(2))),\ $(STR_EIG) $(EIG_DEF),\ $(if $(findstring eigen,$(1)),\ $(STR_EIG) $(BLA_DEF),\ $(STR_VEN) $(BLA_DEF)))))) # Rules for BLIS and BLAS libraries. define make-st-rule test_$(1)$(2)_$(PS_MAX)_$(3)_st.o: test_$(op).c Makefile $(CC) $(CFLAGS) $(PDEF_ST) $(call get-dt-cpp,$(1)) $(call get-bl-cpp,$(3),$(2)) $(DNAT) $(STR_ST) -c $$< -o $$@ endef define make-1s-rule test_$(1)$(2)_$(P1_MAX)_$(3)_1s.o: test_$(op).c Makefile $(CC) $(CFLAGS) $(PDEF_1S) $(call get-dt-cpp,$(1)) $(call get-bl-cpp,$(3),$(2)) $(DNAT) $(STR_1S) -c $$< -o $$@ endef define make-2s-rule test_$(1)$(2)_$(P2_MAX)_$(3)_2s.o: test_$(op).c Makefile $(CC) $(CFLAGS) $(PDEF_2S) $(call get-dt-cpp,$(1)) $(call get-bl-cpp,$(3),$(2)) $(DNAT) $(STR_2S) -c $$< -o $$@ endef $(foreach dt,$(DTS), \ $(foreach op,$(OPS), \ $(foreach im,$(BIMPLS),$(eval $(call make-st-rule,$(dt),$(op),$(im)))))) $(foreach dt,$(DTS), \ $(foreach op,$(OPS), \ $(foreach im,$(BIMPLS),$(eval $(call make-1s-rule,$(dt),$(op),$(im)))))) $(foreach dt,$(DTS), \ $(foreach op,$(OPS), \ $(foreach im,$(BIMPLS),$(eval $(call make-2s-rule,$(dt),$(op),$(im)))))) # Rules for Eigen. define make-eigst-rule test_$(1)$(2)_$(PS_MAX)_$(3)_st.o: test_$(op).c Makefile $(CXX) $(CXXFLAGS_ST) $(PDEF_ST) $(call get-dt-cpp,$(1)) $(call get-bl-cpp,$(3),$(2)) $(DNAT) $(STR_ST) -c $$< -o $$@ endef define make-eig1s-rule test_$(1)$(2)_$(P1_MAX)_$(3)_1s.o: test_$(op).c Makefile $(CXX) $(CXXFLAGS_MT) $(PDEF_1S) $(call get-dt-cpp,$(1)) $(call get-bl-cpp,$(3),$(2)) $(DNAT) $(STR_1S) -c $$< -o $$@ endef define make-eig2s-rule test_$(1)$(2)_$(P2_MAX)_$(3)_2s.o: test_$(op).c Makefile $(CXX) $(CXXFLAGS_MT) $(PDEF_2S) $(call get-dt-cpp,$(1)) $(call get-bl-cpp,$(3),$(2)) $(DNAT) $(STR_2S) -c $$< -o $$@ endef $(foreach dt,$(DTS), \ $(foreach op,$(OPS), \ $(foreach im,$(EIMPLS),$(eval $(call make-eigst-rule,$(dt),$(op),$(im)))))) $(foreach dt,$(DTS), \ $(foreach op,$(OPS), \ $(foreach im,$(EIMPLS),$(eval $(call make-eig1s-rule,$(dt),$(op),$(im)))))) $(foreach dt,$(DTS), \ $(foreach op,$(OPS), \ $(foreach im,$(EIMPLS),$(eval $(call make-eig2s-rule,$(dt),$(op),$(im)))))) # -- Executable file rules -- # NOTE: For the BLAS test drivers, we place the BLAS libraries before BLIS # on the link command line in case BLIS was configured with the BLAS # compatibility layer. This prevents BLIS from inadvertently getting called # for the BLAS routines we are trying to test with. test_%_$(PS_MAX)_asm_blis_st.x: test_%_$(PS_MAX)_asm_blis_st.o $(LIBBLIS_LINK) $(CC) $(strip $< $(LIBBLIS_LINK) $(LDFLAGS) -o $@) test_%_$(P1_MAX)_asm_blis_1s.x: test_%_$(P1_MAX)_asm_blis_1s.o $(LIBBLIS_LINK) $(CC) $(strip $< $(LIBBLIS_LINK) $(LDFLAGS) -o $@) test_%_$(P2_MAX)_asm_blis_2s.x: test_%_$(P2_MAX)_asm_blis_2s.o $(LIBBLIS_LINK) $(CC) $(strip $< $(LIBBLIS_LINK) $(LDFLAGS) -o $@) test_%_$(PS_MAX)_openblas_st.x: test_%_$(PS_MAX)_openblas_st.o $(LIBBLIS_LINK) $(CC) $(strip $< $(OPENBLAS_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $@) test_%_$(P1_MAX)_openblas_1s.x: test_%_$(P1_MAX)_openblas_1s.o $(LIBBLIS_LINK) $(CC) $(strip $< $(OPENBLASP_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $@) test_%_$(P2_MAX)_openblas_2s.x: test_%_$(P2_MAX)_openblas_2s.o $(LIBBLIS_LINK) $(CC) $(strip $< $(OPENBLASP_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $@) test_%_$(PS_MAX)_eigen_st.x: test_%_$(PS_MAX)_eigen_st.o $(LIBBLIS_LINK) $(CXX) $(strip $< $(EIGEN_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $@) test_%_$(P1_MAX)_eigen_1s.x: test_%_$(P1_MAX)_eigen_1s.o $(LIBBLIS_LINK) $(CXX) $(strip $< $(EIGENP_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $@) test_%_$(P2_MAX)_eigen_2s.x: test_%_$(P2_MAX)_eigen_2s.o $(LIBBLIS_LINK) $(CXX) $(strip $< $(EIGENP_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $@) test_%_$(PS_MAX)_vendor_st.x: test_%_$(PS_MAX)_vendor_st.o $(LIBBLIS_LINK) $(CC) $(strip $< $(VENDOR_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $@) test_%_$(P1_MAX)_vendor_1s.x: test_%_$(P1_MAX)_vendor_1s.o $(LIBBLIS_LINK) $(CC) $(strip $< $(VENDORP_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $@) test_%_$(P2_MAX)_vendor_2s.x: test_%_$(P2_MAX)_vendor_2s.o $(LIBBLIS_LINK) $(CC) $(strip $< $(VENDORP_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $@) # -- Environment check rules -- check-env: check-lib check-env-mk: ifeq ($(CONFIG_MK_PRESENT),no) $(error Cannot proceed: config.mk not detected! Run configure first) endif check-lib: check-env-mk ifeq ($(wildcard $(LIBBLIS_LINK)),) $(error Cannot proceed: BLIS library not yet built! Run make first) endif # -- Clean rules -- clean: cleanx cleanx: - $(RM_F) *.o *.x blis-0.9.0/test/3/octave/000077500000000000000000000000001422157504600150615ustar00rootroot00000000000000blis-0.9.0/test/3/octave/gen_opnames.m000066400000000000000000000004041422157504600175300ustar00rootroot00000000000000function r_val = gen_opnames( ops, dts ) nops = size( ops, 1 ); ndts = size( dts, 2 ); i = 1; for id = 1:ndts dt = dts( id ); for io = 1:nops op = ops( io, : ); opnames( i, : ) = sprintf( '%c%s', dt, op ); i = i + 1; end end r_val = opnames; blis-0.9.0/test/3/octave/plot_l3_perf.m000066400000000000000000000135721422157504600176370ustar00rootroot00000000000000function r_val = plot_l3_perf( opname, ... data_blis, ... data_open, ... data_eige, ... data_vend, vend_str, ... nth, ... rows, cols, ... cfreq, ... dfps, ... theid, ... leg_pos_st, leg_pos_mt, ... sp_margins ) % Define the column in which the performance rates are found. flopscol = size( data_blis, 2 ); % Define which plot id will have the legend. % NOTE: We can draw the legend on any graph as long as it has already been % rendered. Since the coordinates are global, we can simply always wait until % the final graph to draw the legend. legend_plot_id = cols*rows; % Set line properties. color_blis = 'k'; lines_blis = '-'; markr_blis = ''; color_open = 'r'; lines_open = '--'; markr_open = 'o'; color_eige = 'm'; lines_eige = '-.'; markr_eige = 'x'; color_vend = 'b'; lines_vend = '-.'; markr_vend = '.'; % Compute the peak performance in terms of the number of double flops % executable per cycle and the clock rate. if opname(1) == 's' || opname(1) == 'c' flopspercycle = dfps * 2; else flopspercycle = dfps; end max_perf_core = (flopspercycle * cfreq) * 1; % Adjust title for real domain hemm and herk. title_opname = opname; if opname(1) == 's' || opname(1) == 'd' % if strcmp( extractAfter( opname, 1 ), 'hemm' ) || ... % strcmp( extractAfter( opname, 1 ), 'herk' ) % title_opname(2:3) = 'sy'; % end opname_u = opname; opname_u(1) = '_'; if strcmp( opname_u, '_hemm' ) || ... strcmp( opname_u, '_herk' ) title_opname(2:3) = 'sy'; end end % Print the title to a string. titlename = '%s'; titlename = sprintf( titlename, title_opname ); % Set the legend strings. blis_legend = sprintf( 'BLIS' ); open_legend = sprintf( 'OpenBLAS' ); eige_legend = sprintf( 'Eigen' ); %vend_legend = sprintf( 'MKL' ); %vend_legend = sprintf( 'ARMPL' ); vend_legend = vend_str; % Set axes range values. y_scale = 1.00; x_begin = 0; x_end = data_blis( size( data_blis, 1 ), 1 ); y_begin = 0; y_end = max_perf_core * y_scale; % Set axes names. if nth == 1 yaxisname = 'GFLOPS'; else yaxisname = 'GFLOPS/core'; end % Set the marker size, font size, and other items. msize = 5; if 0 xaxisname = ' m = n = k'; fontsize = 12; else xaxisname = 'm = n = k'; fontsize = 20; end linesize = 0.8; legend_loc = 'southeast'; %ax1 = subplot( rows, cols, theid ); ax1 = subplot_tight( rows, cols, theid, sp_margins ); % Hold the axes. hold( ax1, 'on' ); % -------------------------------------------------------------------- x_axis( :, 1 ) = data_blis( :, 1 ); data_peak( 1, 1:2 ) = [ 0 max_perf_core ]; data_peak( 2, 1:2 ) = [ x_end max_perf_core ]; % Plot the data series for BLIS, which is required. blis_ln = line( x_axis( :, 1 ), data_blis( :, flopscol ) / nth, ... 'Color',color_blis, 'LineStyle',lines_blis, ... 'LineWidth',linesize ); % Plot the data series for OpenBLAS, if applicable. if data_open(1,1) ~= -1 open_ln = line( x_axis( :, 1 ), data_open( :, flopscol ) / nth, ... 'Color',color_open, 'LineStyle',lines_open, ... 'LineWidth',linesize ); else open_ln = line( nan, nan, ... 'Color',color_open, 'LineStyle',lines_open, ... 'LineWidth',linesize ); end % Plot the data series for a vendor library, if applicable. if data_vend(1,1) ~= -1 vend_ln = line( x_axis( :, 1 ), data_vend( :, flopscol ) / nth, ... 'Color',color_vend, 'LineStyle',lines_vend, ... 'LineWidth',linesize ); else vend_ln = line( nan, nan, ... 'Color',color_vend, 'LineStyle',lines_vend, ... 'LineWidth',linesize ); end % Plot the data series for Eigen, if applicable. if data_eige(1,1) ~= -1 eige_ln = line( x_axis( :, 1 ), data_eige( :, flopscol ) / nth, ... 'Color',color_eige, 'LineStyle',lines_eige, ... 'LineWidth',linesize ); else eige_ln = line( nan, nan, ... 'Color',color_eige, 'LineStyle',lines_eige, ... 'LineWidth',linesize ); end xlim( ax1, [x_begin x_end] ); ylim( ax1, [y_begin y_end] ); if 6000 <= x_end && x_end < 10000 x_tick2 = x_end - 2000; x_tick1 = x_tick2/2; xticks( ax1, [ x_tick1 x_tick2 ] ); elseif 4000 <= x_end && x_end < 6000 x_tick2 = x_end - 1000; x_tick1 = x_tick2/2; xticks( ax1, [ x_tick1 x_tick2 ] ); elseif 2000 <= x_end && x_end < 3000 x_tick2 = x_end - 400; x_tick1 = x_tick2/2; xticks( ax1, [ x_tick1 x_tick2 ] ); end if rows == 4 && cols == 5 if nth == 1 && theid == legend_plot_id leg = legend( [ blis_ln vend_ln open_ln eige_ln ], ... blis_legend, vend_legend, open_legend, eige_legend, ... 'Location', legend_loc ); set( leg,'Box','off','Color','none','Units','inches','FontSize',fontsize ); set( leg,'Position',leg_pos_st ); elseif nth > 1 && theid == legend_plot_id leg = legend( [ blis_ln vend_ln open_ln eige_ln ], ... blis_legend, vend_legend, open_legend, eige_legend, ... 'Location', legend_loc ); set( leg,'Box','off','Color','none','Units','inches','FontSize',fontsize ); set( leg,'Position',leg_pos_mt ); end end set( ax1,'FontSize',fontsize ); set( ax1,'TitleFontSizeMultiplier',1.0 ); % default is 1.1. box( ax1, 'on' ); titl = title( titlename ); set( titl, 'FontWeight', 'normal' ); % default font style is now 'bold'. tpos = get( titl, 'Position' ); % default is to align across whole figure, not box. %tpos(1) = tpos(1) + 100; tpos(1) = tpos(1) + 40; set( titl, 'Position', tpos ); % here we nudge it back to centered with box. set( titl, 'FontSize', fontsize ); if theid > (rows-1)*cols %tpos = get( xlab, 'Position' ) %tpos(2) = tpos(2) + 10; %set( xlab, 'Position', tpos ); xlab = xlabel( ax1,xaxisname ); end if mod(theid-1,cols) == 0 ylab = ylabel( ax1,yaxisname ); end r_val = 0; blis-0.9.0/test/3/octave/plot_panel_4x5.m000066400000000000000000000075101422157504600200770ustar00rootroot00000000000000function r_val = plot_panel_4x5 ... ( ... cfreq, ... dflopspercycle, ... nth, ... thr_str, ... dirpath, ... arch_str, ... vend_leg_str ... ) impl = 'octave'; %impl = 'matlab'; %sp = 'default'; subp = 'tight'; if strcmp( subp, 'default' ) position = [100 100 2000 1500]; papersize = [14.2 19.0]; leg_pos_st = [3.40 8.70 1.9 1.0 ]; % (0,2br) leg_pos_mt = [13.08 13.09 1.9 1.0 ]; % (0,3tr) sp_margins = [ 0.070 0.049 ]; else position = [100 100 1864 1540]; papersize = [15.6 19.4]; %leg_pos_st = [1.15 8.70 2.1 1.2 ]; % (dgemm) %leg_pos_st = [1.60 8.80 2.1 1.2 ]; % (dgemm) leg_pos_st = [15.90 13.60 2.1 1.2 ]; % (strsm) %leg_pos_mt = [12.20 13.60 2.1 1.2 ]; % (strmm) %leg_pos_mt = [5.30 12.60 2.1 1.2 ]; % (ssymm) %leg_pos_mt = [8.50 13.62 2.1 1.2 ]; % (ssyrk) %leg_pos_mt = [5.30 5.10 2.1 1.2 ]; % (chemm) leg_pos_mt = [15.90 13.60 2.1 1.2 ]; % (strsm) sp_margins = [ 0.068 0.051 ]; end %fig = figure('Position', [100, 100, 2000, 1500]); fig = figure('Position', position); orient( fig, 'portrait' ); set(gcf,'PaperUnits', 'inches'); if strcmp( impl, 'octave' ) %set(gcf,'PaperSize', [14.2 19.0]); set(gcf,'PaperSize', papersize); %set(gcf,'PaperPositionMode','auto'); set(gcf,'PaperPositionMode','auto'); else % impl == 'matlab' set(gcf,'PaperSize', [13 20.0]); set(gcf,'PaperPosition', [0 0 13 20.0]); set(gcf,'PaperPositionMode','manual'); end set(gcf,'PaperOrientation','landscape'); % Define the implementation strings. These appear in both the filenames of the % files that contain the performance results as well as the variable names % within those files. blis_str = 'asm_blis'; open_str = 'openblas'; vend_str = 'vendor'; eige_str = 'eigen'; % Create filename "templates" for the files that contain the performance % results. filetemp = '%s/output_%s_%s_%s.m'; filetemp_blis = sprintf( filetemp, '%s', '%s', '%s', blis_str ); filetemp_open = sprintf( filetemp, '%s', '%s', '%s', open_str ); filetemp_vend = sprintf( filetemp, '%s', '%s', '%s', vend_str ); filetemp_eige = sprintf( filetemp, '%s', '%s', '%s', eige_str ); % Create a variable name "template" for the variables contained in the % files outlined above. vartemp = 'data_%s_%s_%s( :, : )'; % Define the datatypes and operations we will be plotting. dts = [ 's' 'd' 'c' 'z' ]; ops( 1, : ) = 'gemm'; ops( 2, : ) = 'hemm'; ops( 3, : ) = 'herk'; ops( 4, : ) = 'trmm'; ops( 5, : ) = 'trsm'; % Generate datatype-specific operation names from the set of operations % and datatypes. opnames = gen_opnames( ops, dts ); n_opnames = size( opnames, 1 ); % Iterate over the list of datatype-specific operation names. for opi = 1:n_opnames %for opi = 1:1 % Grab the current datatype combination. opname = opnames( opi, : ); str = sprintf( 'Plotting %d: %s', opi, opname ); disp(str); data_blis = read_data( filetemp_blis, dirpath, vartemp, thr_str, opname, blis_str ); data_open = read_data( filetemp_open, dirpath, vartemp, thr_str, opname, open_str ); data_vend = read_data( filetemp_vend, dirpath, vartemp, thr_str, opname, vend_str ); data_eige = read_data( filetemp_eige, dirpath, vartemp, thr_str, opname, eige_str ); % Plot one result in an m x n grid of plots, via the subplot() % function. plot_l3_perf( opname, ... data_blis, ... data_open, ... data_eige, ... data_vend, vend_leg_str, ... nth, ... 4, 5, ... cfreq, ... dflopspercycle, ... opi, ... leg_pos_st, leg_pos_mt, ... sp_margins ); end % Construct the name of the file to which we will output the graph. outfile = sprintf( 'l3_perf_%s_nt%d.pdf', arch_str, nth ); % Output the graph to pdf format. if strcmp( impl, 'octave' ) print( gcf, outfile ); else print( gcf, outfile, '-bestfit', '-dpdf' ); end blis-0.9.0/test/3/octave/read_data.m000066400000000000000000000025171422157504600171500ustar00rootroot00000000000000function data = read_data ... ( ... filetemp, ... dirpath, ... var_templ, ... thr_str, ... opname, ... impl_str ... ) % Construct the full filepath for the data file from the template. filepath = sprintf( filetemp, dirpath, thr_str, opname ); % Attempt to open the file. fid = fopen( filepath ); if fid == -1 % If the file was not opened successfully, it's probably because % the file is missing altogether. In these sitautions, we set the % first element of the data to -1, which will be a signal to the % plotting function to omit this curve from the graph. data(1,1) = -1; else % If the file was opened successfully, we assume that it either % contains valid data, or it adheres to the "missing data" format % whereby the (1,1) element contains -1. In either case, we can % process it normally and we begin by closing the file since we % don't need the file descriptor. fclose( fid ); % Load the data file. run( filepath ) % Construct variable names for the variables in the data file. % Examples: data_st_dgemm_asm_blis % data_1s_zherk_vendor var_name = sprintf( var_templ, thr_str, opname, impl_str ); % Use eval() to instantiate the variable names constructed above, % copying each to a simplified name. data = eval( var_name ); end % Return the 'data' variable. blis-0.9.0/test/3/octave/runthese.m000066400000000000000000000044241422157504600171000ustar00rootroot00000000000000% tx2 plot_panel_4x5(2.20,8,1, 'st','../results/tx2/20190205/st', 'tx2', 'ARMPL'); close; clear all; plot_panel_4x5(2.20,8,28,'1s','../results/tx2/20190205/jc4ic7','tx2_jc4ic7','ARMPL'); close; clear all; plot_panel_4x5(2.20,8,56,'2s','../results/tx2/20190205/jc8ic7','tx2_jc8ic7','ARMPL'); close; clear all; % skx plot_panel_4x5(2.00,32,1, 'st','../results/skx/merged20190306_0328/st', 'skx', 'MKL'); close; clear all; plot_panel_4x5(2.00,32,26,'1s','../results/skx/merged20190306_0328/jc2ic13','skx_jc2ic13','MKL'); close; clear all; plot_panel_4x5(2.00,32,52,'2s','../results/skx/merged20190306_0328/jc4ic13','skx_jc4ic13','MKL'); close; clear all; % has plot_panel_4x5(3.25,16,1, 'st','../results/has/merged20190206_0328/st', 'has', 'MKL'); close; clear all; plot_panel_4x5(3.00,16,12,'1s','../results/has/merged20190206_0328/jc2ic3jr2','has_jc2ic3jr2','MKL'); close; clear all; plot_panel_4x5(3.00,16,24,'2s','../results/has/merged20190206_0328/jc4ic3jr2','has_jc4ic3jr2','MKL'); close; clear all; % zen plot_panel_4x5(3.00,8,1, 'st','../results/epyc/merged20190306_0319_0328/st', 'epyc', 'MKL'); close; clear all; plot_panel_4x5(2.55,8,32,'1s','../results/epyc/merged20190306_0319_0328/jc1ic8jr4','epyc_jc1ic8jr4','MKL'); close; clear all; plot_panel_4x5(2.55,8,64,'2s','../results/epyc/merged20190306_0319_0328/jc2ic8jr4','epyc_jc2ic8jr4','MKL'); close; clear all; % zen2 plot_panel_4x5(3.40,16,1, 'st','../results/zen2/20200929/st', 'zen2','MKL'); close all; clear all; plot_panel_4x5(2.60,16,64, '1s','../results/zen2/20200929/jc4ic4jr4','zen2','MKL'); close all; clear all; plot_panel_4x5(2.60,16,128,'2s','../results/zen2/20200929/jc8ic4jr4','zen2','MKL'); close all; clear all; % a64fx plot_panel_4x5(2.20,32,1, 'st','../results/a64fx/20210520/st', 'a64fx','Fujitsu SSL2'); close all; clear all; plot_panel_4x5(2.20,32,12,'1s','../results/a64fx/20210520/jc1ic1jr12','a64fx','Fujitsu SSL2'); close all; clear all; plot_panel_4x5(2.20,32,48,'2s','../results/a64fx/20210520/jc1ic4jr12','a64fx','Fujitsu SSL2'); close all; clear all; % nn1 plot_panel_4x5(2.50,8,1, 'st','../results/neoverse_n1/20210715/st', 'nn1','ARMPL'); close; clear all; plot_panel_4x5(2.50,8,64,'1s','../results/neoverse_n1/20210715/nt64','nn1','ARMPL'); close; clear all; blis-0.9.0/test/3/octave/subplot_tight.m000066400000000000000000000120171422157504600201270ustar00rootroot00000000000000% % Copyright (c) 2016, Nikolay S. % 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 % % 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 COPYRIGHT OWNER 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. % function vargout=subplot_tight(m, n, p, margins, varargin) %% subplot_tight % A subplot function substitude with margins user tunabble parameter. % %% Syntax % h=subplot_tight(m, n, p); % h=subplot_tight(m, n, p, margins); % h=subplot_tight(m, n, p, margins, subplotArgs...); % %% Description % Our goal is to grant the user the ability to define the margins between neighbouring % subplots. Unfotrtunately Matlab subplot function lacks this functionality, and the % margins between subplots can reach 40% of figure area, which is pretty lavish. While at % the begining the function was implememnted as wrapper function for Matlab function % subplot, it was modified due to axes del;etion resulting from what Matlab subplot % detected as overlapping. Therefore, the current implmenetation makes no use of Matlab % subplot function, using axes instead. This can be problematic, as axis and subplot % parameters are quie different. Set isWrapper to "True" to return to wrapper mode, which % fully supports subplot format. % %% Input arguments (defaults exist): % margins- two elements vector [vertical,horizontal] defining the margins between % neighbouring axes. Default value is 0.04 % %% Output arguments % same as subplot- none, or axes handle according to function call. % %% Issues & Comments % - Note that if additional elements are used in order to be passed to subplot, margins % parameter must be defined. For default margins value use empty element- []. % - % %% Example % close all; % img=imread('peppers.png'); % figSubplotH=figure('Name', 'subplot'); % figSubplotTightH=figure('Name', 'subplot_tight'); % nElems=17; % subplotRows=ceil(sqrt(nElems)-1); % subplotRows=max(1, subplotRows); % subplotCols=ceil(nElems/subplotRows); % for iElem=1:nElems % figure(figSubplotH); % subplot(subplotRows, subplotCols, iElem); % imshow(img); % figure(figSubplotTightH); % subplot_tight(subplotRows, subplotCols, iElem, [0.0001]); % imshow(img); % end % %% See also % - subplot % %% Revision history % First version: Nikolay S. 2011-03-29. % Last update: Nikolay S. 2012-05-24. % % *List of Changes:* % 2012-05-24 % Non wrapping mode (based on axes command) added, to deal with an issue of disappearing % subplots occuring with massive axes. %% Default params isWrapper=false; if (nargin<4) || isempty(margins) margins=[0.04,0.04]; % default margins value- 4% of figure end if length(margins)==1 margins(2)=margins; end %note n and m are switched as Matlab indexing is column-wise, while subplot indexing is row-wise :( [subplot_col,subplot_row]=ind2sub([n,m],p); height=(1-(m+1)*margins(1))/m; % single subplot height width=(1-(n+1)*margins(2))/n; % single subplot width % note subplot suppors vector p inputs- so a merged subplot of higher dimentions will be created subplot_cols=1+max(subplot_col)-min(subplot_col); % number of column elements in merged subplot subplot_rows=1+max(subplot_row)-min(subplot_row); % number of row elements in merged subplot merged_height=subplot_rows*( height+margins(1) )- margins(1); % merged subplot height merged_width= subplot_cols*( width +margins(2) )- margins(2); % merged subplot width merged_bottom=(m-max(subplot_row))*(height+margins(1)) +margins(1); % merged subplot bottom position merged_left=min(subplot_col)*(width+margins(2))-width; % merged subplot left position pos=[merged_left, merged_bottom, merged_width, merged_height]; if isWrapper h=subplot(m, n, p, varargin{:}, 'Units', 'Normalized', 'Position', pos); else h=axes('Position', pos, varargin{:}); end if nargout==1 vargout=h; end blis-0.9.0/test/3/runme.sh000077500000000000000000000152331422157504600152710ustar00rootroot00000000000000#!/bin/bash # File pefixes. exec_root="test" out_root="output" delay=0.1 #sys="blis" #sys="stampede2" #sys="lonestar5" #sys="ul252" #sys="ul264" sys="ul2128" # Bind threads to processors. #export OMP_PROC_BIND=true #export GOMP_CPU_AFFINITY="0 2 4 6 8 10 12 14 16 18 20 22 1 3 5 7 9 11 13 15 17 19 21 23" #export GOMP_CPU_AFFINITY="0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103" if [ ${sys} = "blis" ]; then export GOMP_CPU_AFFINITY="0-3" numactl="" threads="jc1ic1jr1_2400 jc2ic3jr2_6000 jc4ic3jr2_8000" elif [ ${sys} = "stampede2" ]; then echo "Need to set GOMP_CPU_AFFINITY." exit 1 numactl="" threads="jc1ic1jr1_2400 jc4ic6jr1_6000 jc4ic12jr1_8000" elif [ ${sys} = "lonestar5" ]; then export GOMP_CPU_AFFINITY="0-23" # A hack to use libiomp5 with gcc. #export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/opt/apps/intel/16.0.1.150/compilers_and_libraries_2016.1.150/linux/compiler/lib/intel64" numactl="" threads="jc1ic1jr1_2400 jc2ic3jr2_6000 jc4ic3jr2_8000" elif [ ${sys} = "ul252" ]; then export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/home/field/intel/mkl/lib/intel64" export GOMP_CPU_AFFINITY="0-51" numactl="" threads="jc1ic1jr1_2400 jc2ic13jr1_6000 jc4ic13jr1_8000" elif [ ${sys} = "ul264" ]; then export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/home/field/intel/mkl/lib/intel64" export GOMP_CPU_AFFINITY="0-63" numactl="numactl --interleave=all" threads="jc1ic1jr1_2400 jc1ic8jr4_6000 jc2ic8jr4_8000" elif [ ${sys} = "ul2128" ]; then export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/home/field/intel/mkl/lib/intel64" export GOMP_CPU_AFFINITY="0-127" numactl="numactl --interleave=all" threads="jc1ic1jr1_2400 jc4ic4jr4_6000 jc8ic4jr4_8000" #threads="jc4ic4jr4_6000 # jc8ic4jr4_8000" #threads="jc1ic1jr1_2400" #threads="jc4ic4jr4_6000" #threads="jc8ic4jr4_8000" fi # Datatypes to test. test_dts="d s z c" #test_dts="s" # Operations to test. test_ops="gemm hemm herk trmm trsm" #test_ops="herk" # Implementations to test. #impls="blis" #impls="openblas" #impls="vendor" #impls="other" #impls="eigen" impls="all" if [ "${impls}" = "blis" ]; then test_impls="asm_blis" elif [ "${impls}" = "openblas" ]; then test_impls="openblas" elif [ "${impls}" = "vendor" ]; then test_impls="vendor" elif [ "${impls}" = "eigen" ]; then test_impls="eigen" elif [ "${impls}" = "other" ]; then test_impls="openblas vendor eigen" else test_impls="openblas asm_blis vendor eigen" fi # Save a copy of GOMP_CPU_AFFINITY so that if we have to unset it, we can # restore the value. GOMP_CPU_AFFINITYsave=${GOMP_CPU_AFFINITY} # First perform real test cases. for th in ${threads}; do # Start with one way of parallelism in each loop. We will now begin # parsing the 'th' variable to update one or more of these threading # parameters. jc_nt=1; pc_nt=1; ic_nt=1; jr_nt=1; ir_nt=1 # Strip everything before and after the underscore so that what remains # is the problem size and threading parameter string, respectively. psize=${th##*_}; thinfo=${th%%_*} # Identify each threading parameter and insert a space before it. thsep=$(echo -e ${thinfo} | sed -e "s/\([jip][cr]\)/ \1/g" ) nt=1 for loopnum in ${thsep}; do # Given the current string, which identifies a loop and the # number of ways of parallelism for that loop, strip out # the ways and loop separately to identify each. loop=$(echo -e ${loopnum} | sed -e "s/[0-9]//g" ) num=$(echo -e ${loopnum} | sed -e "s/[a-z]//g" ) # Construct a string that we can evaluate to set the number # of ways of parallelism for the current loop. loop_nt_eq_num="${loop}_nt=${num}" # Update the total number of threads. nt=$(expr ${nt} \* ${num}) # Evaluate the string to assign the ways to the variable. eval ${loop_nt_eq_num} done echo "Switching to: jc${jc_nt} pc${pc_nt} ic${ic_nt} jr${jr_nt} ir${ir_nt} (nt = ${nt}) p_max${psize}" for dt in ${test_dts}; do for im in ${test_impls}; do for op in ${test_ops}; do # Eigen does not support multithreading for hemm, herk, trmm, # or trsm. So if we're getting ready to execute an Eigen driver # for one of these operations and nt > 1, we skip this test. if [ "${im}" = "eigen" ] && \ [ "${op}" != "gemm" ] && \ [ "${nt}" != "1" ]; then continue; fi # Find the threading suffix by probing the executable. binname=$(ls ${exec_root}_${dt}${op}_${psize}_${im}_*.x) suf_ext=${binname##*_} suf=${suf_ext%%.*} #echo "found file: ${binname} with suffix ${suf}" # Set the number of threads according to th. if [ "${suf}" = "1s" ] || [ "${suf}" = "2s" ]; then # Set the threading parameters based on the implementation # that we are preparing to run. if [ "${im}" = "asm_blis" ]; then unset OMP_NUM_THREADS export BLIS_JC_NT=${jc_nt} export BLIS_PC_NT=${pc_nt} export BLIS_IC_NT=${ic_nt} export BLIS_JR_NT=${jr_nt} export BLIS_IR_NT=${ir_nt} elif [ "${im}" = "openblas" ]; then unset OMP_NUM_THREADS export OPENBLAS_NUM_THREADS=${nt} elif [ "${im}" = "eigen" ]; then export OMP_NUM_THREADS=${nt} elif [ "${im}" = "vendor" ]; then unset OMP_NUM_THREADS export MKL_NUM_THREADS=${nt} fi export nt_use=${nt} # Multithreaded OpenBLAS seems to have a problem running # properly if GOMP_CPU_AFFINITY is set. So we temporarily # unset it here if we are about to execute OpenBLAS, but # otherwise restore it. if [ ${im} = "openblas" ]; then unset GOMP_CPU_AFFINITY else export GOMP_CPU_AFFINITY="${GOMP_CPU_AFFINITYsave}" fi else export BLIS_JC_NT=1 export BLIS_PC_NT=1 export BLIS_IC_NT=1 export BLIS_JR_NT=1 export BLIS_IR_NT=1 export OMP_NUM_THREADS=1 export OPENBLAS_NUM_THREADS=1 export MKL_NUM_THREADS=1 export nt_use=1 fi # Construct the name of the test executable. exec_name="${exec_root}_${dt}${op}_${psize}_${im}_${suf}.x" # Construct the name of the output file. out_file="${out_root}_${suf}_${dt}${op}_${im}.m" #echo "Running (nt = ${nt_use}) ./${exec_name} > ${out_file}" echo "Running ${numactl} ./${exec_name} > ${out_file}" # Run executable with or without numactl, depending on how # the numactl variable was set. ${numactl} ./${exec_name} > ${out_file} # Bedtime! sleep ${delay} done done done done blis-0.9.0/test/3/test_gemm.c000066400000000000000000000275041422157504600157400ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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 The University of Texas 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 COPYRIGHT HOLDER 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. */ #include #ifdef EIGEN #define BLIS_DISABLE_BLAS_DEFS #include "blis.h" #include #include using namespace Eigen; #else #include "blis.h" #endif #define COL_STORAGE //#define ROW_STORAGE //#define PRINT int main( int argc, char** argv ) { obj_t a, b, c; obj_t c_save; obj_t alpha, beta; dim_t m, n, k; dim_t p; dim_t p_begin, p_max, p_inc; int m_input, n_input, k_input; ind_t ind; num_t dt; char dt_ch; int r, n_repeats; trans_t transa; trans_t transb; f77_char f77_transa; f77_char f77_transb; double dtime; double dtime_save; double gflops; //bli_init(); //bli_error_checking_level_set( BLIS_NO_ERROR_CHECKING ); n_repeats = 3; dt = DT; ind = IND; #if 1 p_begin = P_BEGIN; p_max = P_MAX; p_inc = P_INC; m_input = -1; n_input = -1; k_input = -1; #else p_begin = 40; p_max = 1000; p_inc = 40; m_input = -1; n_input = -1; k_input = -1; #endif // Supress compiler warnings about unused variable 'ind'. ( void )ind; #if 0 cntx_t* cntx; ind_t ind_mod = ind; // Initialize a context for the current induced method and datatype. cntx = bli_gks_query_ind_cntx( ind_mod, dt ); // Set k to the kc blocksize for the current datatype. k_input = bli_cntx_get_blksz_def_dt( dt, BLIS_KC, cntx ); #elif 1 //k_input = 256; #endif // Choose the char corresponding to the requested datatype. if ( bli_is_float( dt ) ) dt_ch = 's'; else if ( bli_is_double( dt ) ) dt_ch = 'd'; else if ( bli_is_scomplex( dt ) ) dt_ch = 'c'; else dt_ch = 'z'; transa = BLIS_NO_TRANSPOSE; transb = BLIS_NO_TRANSPOSE; bli_param_map_blis_to_netlib_trans( transa, &f77_transa ); bli_param_map_blis_to_netlib_trans( transb, &f77_transb ); // Begin with initializing the last entry to zero so that // matlab allocates space for the entire array once up-front. for ( p = p_begin; p + p_inc <= p_max; p += p_inc ) ; printf( "data_%s_%cgemm_%s", THR_STR, dt_ch, STR ); printf( "( %2lu, 1:4 ) = [ %4lu %4lu %4lu %7.2f ];\n", ( unsigned long )(p - p_begin)/p_inc + 1, ( unsigned long )0, ( unsigned long )0, ( unsigned long )0, 0.0 ); //for ( p = p_begin; p <= p_max; p += p_inc ) for ( p = p_max; p_begin <= p; p -= p_inc ) { if ( m_input < 0 ) m = p / ( dim_t )abs(m_input); else m = ( dim_t ) m_input; if ( n_input < 0 ) n = p / ( dim_t )abs(n_input); else n = ( dim_t ) n_input; if ( k_input < 0 ) k = p / ( dim_t )abs(k_input); else k = ( dim_t ) k_input; bli_obj_create( dt, 1, 1, 0, 0, &alpha ); bli_obj_create( dt, 1, 1, 0, 0, &beta ); #ifdef COL_STORAGE bli_obj_create( dt, m, k, 0, 0, &a ); bli_obj_create( dt, k, n, 0, 0, &b ); bli_obj_create( dt, m, n, 0, 0, &c ); bli_obj_create( dt, m, n, 0, 0, &c_save ); #else bli_obj_create( dt, m, k, k, 1, &a ); bli_obj_create( dt, k, n, n, 1, &b ); bli_obj_create( dt, m, n, n, 1, &c ); bli_obj_create( dt, m, n, n, 1, &c_save ); #endif bli_randm( &a ); bli_randm( &b ); bli_randm( &c ); bli_obj_set_conjtrans( transa, &a ); bli_obj_set_conjtrans( transb, &b ); bli_setsc( (2.0/1.0), 0.0, &alpha ); bli_setsc( (1.0/1.0), 0.0, &beta ); bli_copym( &c, &c_save ); #if 0 //def BLIS bli_ind_disable_all_dt( dt ); bli_ind_enable_dt( ind, dt ); #endif #ifdef EIGEN double alpha_r, alpha_i; bli_getsc( &alpha, &alpha_r, &alpha_i ); void* ap = bli_obj_buffer_at_off( &a ); void* bp = bli_obj_buffer_at_off( &b ); void* cp = bli_obj_buffer_at_off( &c ); #ifdef COL_STORAGE const int os_a = bli_obj_col_stride( &a ); const int os_b = bli_obj_col_stride( &b ); const int os_c = bli_obj_col_stride( &c ); #else const int os_a = bli_obj_row_stride( &a ); const int os_b = bli_obj_row_stride( &b ); const int os_c = bli_obj_row_stride( &c ); #endif Stride stride_a( os_a, 1 ); Stride stride_b( os_b, 1 ); Stride stride_c( os_c, 1 ); #ifdef COL_STORAGE #if defined(IS_FLOAT) typedef Matrix MatrixXf_; #elif defined (IS_DOUBLE) typedef Matrix MatrixXd_; #elif defined (IS_SCOMPLEX) typedef Matrix, Dynamic, Dynamic, ColMajor> MatrixXcf_; #elif defined (IS_DCOMPLEX) typedef Matrix, Dynamic, Dynamic, ColMajor> MatrixXcd_; #endif #else #if defined(IS_FLOAT) typedef Matrix MatrixXf_; #elif defined (IS_DOUBLE) typedef Matrix MatrixXd_; #elif defined (IS_SCOMPLEX) typedef Matrix, Dynamic, Dynamic, RowMajor> MatrixXcf_; #elif defined (IS_DCOMPLEX) typedef Matrix, Dynamic, Dynamic, RowMajor> MatrixXcd_; #endif #endif #if defined(IS_FLOAT) Map > A( ( float* )ap, m, k, stride_a ); Map > B( ( float* )bp, k, n, stride_b ); Map > C( ( float* )cp, m, n, stride_c ); #elif defined (IS_DOUBLE) Map > A( ( double* )ap, m, k, stride_a ); Map > B( ( double* )bp, k, n, stride_b ); Map > C( ( double* )cp, m, n, stride_c ); #elif defined (IS_SCOMPLEX) Map > A( ( std::complex* )ap, m, k, stride_a ); Map > B( ( std::complex* )bp, k, n, stride_b ); Map > C( ( std::complex* )cp, m, n, stride_c ); #elif defined (IS_DCOMPLEX) Map > A( ( std::complex* )ap, m, k, stride_a ); Map > B( ( std::complex* )bp, k, n, stride_b ); Map > C( ( std::complex* )cp, m, n, stride_c ); #endif #endif dtime_save = DBL_MAX; for ( r = 0; r < n_repeats; ++r ) { bli_copym( &c_save, &c ); dtime = bli_clock(); #ifdef PRINT bli_printm( "a", &a, "%4.1f", "" ); bli_printm( "b", &b, "%4.1f", "" ); bli_printm( "c", &c, "%4.1f", "" ); #endif #if defined(BLIS) bli_gemm( &alpha, &a, &b, &beta, &c ); #elif defined(EIGEN) C.noalias() += alpha_r * A * B; #else // if defined(BLAS) if ( bli_is_float( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); float* alphap = ( float* )bli_obj_buffer( &alpha ); float* ap = ( float* )bli_obj_buffer( &a ); float* bp = ( float* )bli_obj_buffer( &b ); float* betap = ( float* )bli_obj_buffer( &beta ); float* cp = ( float* )bli_obj_buffer( &c ); sgemm_( &f77_transa, &f77_transb, &mm, &nn, &kk, alphap, ap, &lda, bp, &ldb, betap, cp, &ldc ); } else if ( bli_is_double( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); double* alphap = ( double* )bli_obj_buffer( &alpha ); double* ap = ( double* )bli_obj_buffer( &a ); double* bp = ( double* )bli_obj_buffer( &b ); double* betap = ( double* )bli_obj_buffer( &beta ); double* cp = ( double* )bli_obj_buffer( &c ); dgemm_( &f77_transa, &f77_transb, &mm, &nn, &kk, alphap, ap, &lda, bp, &ldb, betap, cp, &ldc ); } else if ( bli_is_scomplex( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); scomplex* alphap = ( scomplex* )bli_obj_buffer( &alpha ); scomplex* ap = ( scomplex* )bli_obj_buffer( &a ); scomplex* bp = ( scomplex* )bli_obj_buffer( &b ); scomplex* betap = ( scomplex* )bli_obj_buffer( &beta ); scomplex* cp = ( scomplex* )bli_obj_buffer( &c ); cgemm_( &f77_transa, &f77_transb, &mm, &nn, &kk, alphap, ap, &lda, bp, &ldb, betap, cp, &ldc ); } else if ( bli_is_dcomplex( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); dcomplex* alphap = ( dcomplex* )bli_obj_buffer( &alpha ); dcomplex* ap = ( dcomplex* )bli_obj_buffer( &a ); dcomplex* bp = ( dcomplex* )bli_obj_buffer( &b ); dcomplex* betap = ( dcomplex* )bli_obj_buffer( &beta ); dcomplex* cp = ( dcomplex* )bli_obj_buffer( &c ); zgemm_( &f77_transa, &f77_transb, &mm, &nn, &kk, alphap, ap, &lda, bp, &ldb, betap, cp, &ldc ); } #endif #ifdef PRINT bli_printm( "c after", &c, "%4.1f", "" ); exit(1); #endif dtime_save = bli_clock_min_diff( dtime_save, dtime ); } gflops = ( 2.0 * m * k * n ) / ( dtime_save * 1.0e9 ); if ( bli_is_complex( dt ) ) gflops *= 4.0; printf( "data_%s_%cgemm_%s", THR_STR, dt_ch, STR ); printf( "( %2lu, 1:4 ) = [ %4lu %4lu %4lu %7.2f ];\n", ( unsigned long )(p - p_begin)/p_inc + 1, ( unsigned long )m, ( unsigned long )k, ( unsigned long )n, gflops ); bli_obj_free( &alpha ); bli_obj_free( &beta ); bli_obj_free( &a ); bli_obj_free( &b ); bli_obj_free( &c ); bli_obj_free( &c_save ); } //bli_finalize(); return 0; } blis-0.9.0/test/3/test_hemm.c000066400000000000000000000221441422157504600157340ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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 The University of Texas 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 COPYRIGHT HOLDER 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. */ #include #include "blis.h" //#define PRINT int main( int argc, char** argv ) { obj_t a, b, c; obj_t c_save; obj_t alpha, beta; dim_t m, n; dim_t p; dim_t p_begin, p_max, p_inc; int m_input, n_input; ind_t ind; num_t dt; char dt_ch; int r, n_repeats; side_t side; uplo_t uploa; f77_char f77_side; f77_char f77_uploa; double dtime; double dtime_save; double gflops; //bli_init(); //bli_error_checking_level_set( BLIS_NO_ERROR_CHECKING ); n_repeats = 3; dt = DT; ind = IND; p_begin = P_BEGIN; p_max = P_MAX; p_inc = P_INC; m_input = -1; n_input = -1; // Supress compiler warnings about unused variable 'ind'. ( void )ind; #if 0 cntx_t* cntx; ind_t ind_mod = ind; // Initialize a context for the current induced method and datatype. cntx = bli_gks_query_ind_cntx( ind_mod, dt ); // Set k to the kc blocksize for the current datatype. k_input = bli_cntx_get_blksz_def_dt( dt, BLIS_KC, cntx ); #elif 1 //k_input = 256; #endif // Choose the char corresponding to the requested datatype. if ( bli_is_float( dt ) ) dt_ch = 's'; else if ( bli_is_double( dt ) ) dt_ch = 'd'; else if ( bli_is_scomplex( dt ) ) dt_ch = 'c'; else dt_ch = 'z'; side = BLIS_LEFT; uploa = BLIS_LOWER; bli_param_map_blis_to_netlib_side( side, &f77_side ); bli_param_map_blis_to_netlib_uplo( uploa, &f77_uploa ); // Begin with initializing the last entry to zero so that // matlab allocates space for the entire array once up-front. for ( p = p_begin; p + p_inc <= p_max; p += p_inc ) ; printf( "data_%s_%chemm_%s", THR_STR, dt_ch, STR ); printf( "( %2lu, 1:3 ) = [ %4lu %4lu %7.2f ];\n", ( unsigned long )(p - p_begin)/p_inc + 1, ( unsigned long )0, ( unsigned long )0, 0.0 ); //for ( p = p_begin; p <= p_max; p += p_inc ) for ( p = p_max; p_begin <= p; p -= p_inc ) { if ( m_input < 0 ) m = p / ( dim_t )abs(m_input); else m = ( dim_t ) m_input; if ( n_input < 0 ) n = p / ( dim_t )abs(n_input); else n = ( dim_t ) n_input; bli_obj_create( dt, 1, 1, 0, 0, &alpha ); bli_obj_create( dt, 1, 1, 0, 0, &beta ); if ( bli_is_left( side ) ) bli_obj_create( dt, m, m, 0, 0, &a ); else bli_obj_create( dt, n, n, 0, 0, &a ); bli_obj_create( dt, m, n, 0, 0, &b ); bli_obj_create( dt, m, n, 0, 0, &c ); bli_obj_create( dt, m, n, 0, 0, &c_save ); bli_randm( &a ); bli_randm( &b ); bli_randm( &c ); bli_obj_set_struc( BLIS_HERMITIAN, &a ); bli_obj_set_uplo( uploa, &a ); // Make A densely Hermitian, and zero the unstored triangle to // ensure the implementation reads only from the stored region. bli_mkherm( &a ); bli_mktrim( &a ); bli_setsc( (2.0/1.0), 0.0, &alpha ); bli_setsc( (1.0/1.0), 0.0, &beta ); bli_copym( &c, &c_save ); #if 0 //def BLIS bli_ind_disable_all_dt( dt ); bli_ind_enable_dt( ind, dt ); #endif dtime_save = DBL_MAX; for ( r = 0; r < n_repeats; ++r ) { bli_copym( &c_save, &c ); dtime = bli_clock(); #ifdef PRINT bli_printm( "a", &a, "%4.1f", "" ); bli_printm( "b", &b, "%4.1f", "" ); bli_printm( "c", &c, "%4.1f", "" ); #endif #ifdef BLIS bli_hemm( side, &alpha, &a, &b, &beta, &c ); #else if ( bli_is_float( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); float* alphap = ( float* )bli_obj_buffer( &alpha ); float* ap = ( float* )bli_obj_buffer( &a ); float* bp = ( float* )bli_obj_buffer( &b ); float* betap = ( float* )bli_obj_buffer( &beta ); float* cp = ( float* )bli_obj_buffer( &c ); ssymm_( &f77_side, &f77_uploa, &mm, &nn, alphap, ap, &lda, bp, &ldb, betap, cp, &ldc ); } else if ( bli_is_double( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); double* alphap = ( double* )bli_obj_buffer( &alpha ); double* ap = ( double* )bli_obj_buffer( &a ); double* bp = ( double* )bli_obj_buffer( &b ); double* betap = ( double* )bli_obj_buffer( &beta ); double* cp = ( double* )bli_obj_buffer( &c ); dsymm_( &f77_side, &f77_uploa, &mm, &nn, alphap, ap, &lda, bp, &ldb, betap, cp, &ldc ); } else if ( bli_is_scomplex( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); #ifdef EIGEN float* alphap = ( float* )bli_obj_buffer( &alpha ); float* ap = ( float* )bli_obj_buffer( &a ); float* bp = ( float* )bli_obj_buffer( &b ); float* betap = ( float* )bli_obj_buffer( &beta ); float* cp = ( float* )bli_obj_buffer( &c ); #else scomplex* alphap = ( scomplex* )bli_obj_buffer( &alpha ); scomplex* ap = ( scomplex* )bli_obj_buffer( &a ); scomplex* bp = ( scomplex* )bli_obj_buffer( &b ); scomplex* betap = ( scomplex* )bli_obj_buffer( &beta ); scomplex* cp = ( scomplex* )bli_obj_buffer( &c ); #endif chemm_( &f77_side, &f77_uploa, &mm, &nn, alphap, ap, &lda, bp, &ldb, betap, cp, &ldc ); } else if ( bli_is_dcomplex( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); #ifdef EIGEN double* alphap = ( double* )bli_obj_buffer( &alpha ); double* ap = ( double* )bli_obj_buffer( &a ); double* bp = ( double* )bli_obj_buffer( &b ); double* betap = ( double* )bli_obj_buffer( &beta ); double* cp = ( double* )bli_obj_buffer( &c ); #else dcomplex* alphap = ( dcomplex* )bli_obj_buffer( &alpha ); dcomplex* ap = ( dcomplex* )bli_obj_buffer( &a ); dcomplex* bp = ( dcomplex* )bli_obj_buffer( &b ); dcomplex* betap = ( dcomplex* )bli_obj_buffer( &beta ); dcomplex* cp = ( dcomplex* )bli_obj_buffer( &c ); #endif zhemm_( &f77_side, &f77_uploa, &mm, &nn, alphap, ap, &lda, bp, &ldb, betap, cp, &ldc ); } #endif #ifdef PRINT bli_printm( "c after", &c, "%4.1f", "" ); exit(1); #endif dtime_save = bli_clock_min_diff( dtime_save, dtime ); } if ( bli_is_left( side ) ) gflops = ( 2.0 * m * m * n ) / ( dtime_save * 1.0e9 ); else gflops = ( 2.0 * m * n * n ) / ( dtime_save * 1.0e9 ); if ( bli_is_complex( dt ) ) gflops *= 4.0; printf( "data_%s_%chemm_%s", THR_STR, dt_ch, STR ); printf( "( %2lu, 1:3 ) = [ %4lu %4lu %7.2f ];\n", ( unsigned long )(p - p_begin)/p_inc + 1, ( unsigned long )m, ( unsigned long )n, gflops ); bli_obj_free( &alpha ); bli_obj_free( &beta ); bli_obj_free( &a ); bli_obj_free( &b ); bli_obj_free( &c ); bli_obj_free( &c_save ); } //bli_finalize(); return 0; } blis-0.9.0/test/3/test_herk.c000066400000000000000000000207251422157504600157420ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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 The University of Texas 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 COPYRIGHT HOLDER 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. */ #include #include "blis.h" //#define PRINT int main( int argc, char** argv ) { obj_t a, c; obj_t c_save; obj_t alpha, beta; dim_t m, k; dim_t p; dim_t p_begin, p_max, p_inc; int m_input, k_input; ind_t ind; num_t dt, dt_real; char dt_ch; int r, n_repeats; uplo_t uploc; trans_t transa; f77_char f77_uploc; f77_char f77_transa; double dtime; double dtime_save; double gflops; //bli_init(); //bli_error_checking_level_set( BLIS_NO_ERROR_CHECKING ); n_repeats = 3; dt = DT; dt_real = bli_dt_proj_to_real( DT ); ind = IND; p_begin = P_BEGIN; p_max = P_MAX; p_inc = P_INC; m_input = -1; k_input = -1; // Supress compiler warnings about unused variable 'ind'. ( void )ind; #if 0 cntx_t* cntx; ind_t ind_mod = ind; // Initialize a context for the current induced method and datatype. cntx = bli_gks_query_ind_cntx( ind_mod, dt ); // Set k to the kc blocksize for the current datatype. k_input = bli_cntx_get_blksz_def_dt( dt, BLIS_KC, cntx ); #elif 1 //k_input = 256; #endif // Choose the char corresponding to the requested datatype. if ( bli_is_float( dt ) ) dt_ch = 's'; else if ( bli_is_double( dt ) ) dt_ch = 'd'; else if ( bli_is_scomplex( dt ) ) dt_ch = 'c'; else dt_ch = 'z'; uploc = BLIS_LOWER; transa = BLIS_NO_TRANSPOSE; bli_param_map_blis_to_netlib_uplo( uploc, &f77_uploc ); bli_param_map_blis_to_netlib_trans( transa, &f77_transa ); // Begin with initializing the last entry to zero so that // matlab allocates space for the entire array once up-front. for ( p = p_begin; p + p_inc <= p_max; p += p_inc ) ; printf( "data_%s_%cherk_%s", THR_STR, dt_ch, STR ); printf( "( %2lu, 1:3 ) = [ %4lu %4lu %7.2f ];\n", ( unsigned long )(p - p_begin)/p_inc + 1, ( unsigned long )0, ( unsigned long )0, 0.0 ); //for ( p = p_begin; p <= p_max; p += p_inc ) for ( p = p_max; p_begin <= p; p -= p_inc ) { if ( m_input < 0 ) m = p / ( dim_t )abs(m_input); else m = ( dim_t ) m_input; if ( k_input < 0 ) k = p / ( dim_t )abs(k_input); else k = ( dim_t ) k_input; bli_obj_create( dt_real, 1, 1, 0, 0, &alpha ); bli_obj_create( dt, 1, 1, 0, 0, &beta ); if ( bli_does_trans( transa ) ) bli_obj_create( dt, k, m, 0, 0, &a ); else bli_obj_create( dt, m, k, 0, 0, &a ); bli_obj_create( dt, m, m, 0, 0, &c ); //bli_obj_create( dt, m, k, 2, 2*m, &a ); //bli_obj_create( dt, k, n, 2, 2*k, &b ); //bli_obj_create( dt, m, n, 2, 2*m, &c ); bli_obj_create( dt, m, m, 0, 0, &c_save ); bli_randm( &a ); bli_randm( &c ); bli_obj_set_struc( BLIS_HERMITIAN, &c ); bli_obj_set_uplo( uploc, &c ); bli_obj_set_conjtrans( transa, &a ); bli_setsc( (2.0/1.0), 0.0, &alpha ); bli_setsc( (1.0/1.0), 0.0, &beta ); bli_copym( &c, &c_save ); #if 0 //def BLIS bli_ind_disable_all_dt( dt ); bli_ind_enable_dt( ind, dt ); #endif dtime_save = DBL_MAX; for ( r = 0; r < n_repeats; ++r ) { bli_copym( &c_save, &c ); dtime = bli_clock(); #ifdef PRINT bli_printm( "a", &a, "%4.1f", "" ); bli_printm( "c", &c, "%4.1f", "" ); #endif #ifdef BLIS bli_herk( &alpha, &a, &beta, &c ); #else if ( bli_is_float( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldc = bli_obj_col_stride( &c ); float* alphap = ( float* )bli_obj_buffer( &alpha ); float* ap = ( float* )bli_obj_buffer( &a ); float* betap = ( float* )bli_obj_buffer( &beta ); float* cp = ( float* )bli_obj_buffer( &c ); ssyrk_( &f77_uploc, &f77_transa, &mm, &kk, alphap, ap, &lda, betap, cp, &ldc ); } else if ( bli_is_double( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldc = bli_obj_col_stride( &c ); double* alphap = ( double* )bli_obj_buffer( &alpha ); double* ap = ( double* )bli_obj_buffer( &a ); double* betap = ( double* )bli_obj_buffer( &beta ); double* cp = ( double* )bli_obj_buffer( &c ); dsyrk_( &f77_uploc, &f77_transa, &mm, &kk, alphap, ap, &lda, betap, cp, &ldc ); } else if ( bli_is_scomplex( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldc = bli_obj_col_stride( &c ); #ifdef EIGEN float* alphap = ( float* )bli_obj_buffer( &alpha ); float* ap = ( float* )bli_obj_buffer( &a ); float* betap = ( float* )bli_obj_buffer( &beta ); float* cp = ( float* )bli_obj_buffer( &c ); #else float* alphap = ( float* )bli_obj_buffer( &alpha ); scomplex* ap = ( scomplex* )bli_obj_buffer( &a ); float* betap = ( float* )bli_obj_buffer( &beta ); scomplex* cp = ( scomplex* )bli_obj_buffer( &c ); #endif cherk_( &f77_uploc, &f77_transa, &mm, &kk, alphap, ap, &lda, betap, cp, &ldc ); } else if ( bli_is_dcomplex( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldc = bli_obj_col_stride( &c ); #ifdef EIGEN double* alphap = ( double* )bli_obj_buffer( &alpha ); double* ap = ( double* )bli_obj_buffer( &a ); double* betap = ( double* )bli_obj_buffer( &beta ); double* cp = ( double* )bli_obj_buffer( &c ); #else double* alphap = ( double* )bli_obj_buffer( &alpha ); dcomplex* ap = ( dcomplex* )bli_obj_buffer( &a ); double* betap = ( double* )bli_obj_buffer( &beta ); dcomplex* cp = ( dcomplex* )bli_obj_buffer( &c ); #endif zherk_( &f77_uploc, &f77_transa, &mm, &kk, alphap, ap, &lda, betap, cp, &ldc ); } #endif #ifdef PRINT bli_printm( "c after", &c, "%4.1f", "" ); exit(1); #endif dtime_save = bli_clock_min_diff( dtime_save, dtime ); } gflops = ( 1.0 * m * k * m ) / ( dtime_save * 1.0e9 ); if ( bli_is_complex( dt ) ) gflops *= 4.0; printf( "data_%s_%cherk_%s", THR_STR, dt_ch, STR ); printf( "( %2lu, 1:3 ) = [ %4lu %4lu %7.2f ];\n", ( unsigned long )(p - p_begin)/p_inc + 1, ( unsigned long )m, ( unsigned long )k, gflops ); bli_obj_free( &alpha ); bli_obj_free( &beta ); bli_obj_free( &a ); bli_obj_free( &c ); bli_obj_free( &c_save ); } //bli_finalize(); return 0; } blis-0.9.0/test/3/test_trmm.c000066400000000000000000000205061422157504600157650ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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 The University of Texas 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 COPYRIGHT HOLDER 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. */ #include #include "blis.h" //#define PRINT int main( int argc, char** argv ) { obj_t a, c; obj_t c_save; obj_t alpha; dim_t m, n; dim_t p; dim_t p_begin, p_max, p_inc; int m_input, n_input; ind_t ind; num_t dt; char dt_ch; int r, n_repeats; side_t side; uplo_t uploa; trans_t transa; diag_t diaga; f77_char f77_side; f77_char f77_uploa; f77_char f77_transa; f77_char f77_diaga; double dtime; double dtime_save; double gflops; //bli_init(); //bli_error_checking_level_set( BLIS_NO_ERROR_CHECKING ); n_repeats = 3; dt = DT; ind = IND; p_begin = P_BEGIN; p_max = P_MAX; p_inc = P_INC; m_input = -1; n_input = -1; // Supress compiler warnings about unused variable 'ind'. ( void )ind; #if 0 cntx_t* cntx; ind_t ind_mod = ind; // Initialize a context for the current induced method and datatype. cntx = bli_gks_query_ind_cntx( ind_mod, dt ); // Set k to the kc blocksize for the current datatype. k_input = bli_cntx_get_blksz_def_dt( dt, BLIS_KC, cntx ); #elif 1 //k_input = 256; #endif // Choose the char corresponding to the requested datatype. if ( bli_is_float( dt ) ) dt_ch = 's'; else if ( bli_is_double( dt ) ) dt_ch = 'd'; else if ( bli_is_scomplex( dt ) ) dt_ch = 'c'; else dt_ch = 'z'; #if 0 side = BLIS_LEFT; #else side = BLIS_RIGHT; #endif #if 0 uploa = BLIS_LOWER; #else uploa = BLIS_UPPER; #endif transa = BLIS_NO_TRANSPOSE; diaga = BLIS_NONUNIT_DIAG; bli_param_map_blis_to_netlib_side( side, &f77_side ); bli_param_map_blis_to_netlib_uplo( uploa, &f77_uploa ); bli_param_map_blis_to_netlib_trans( transa, &f77_transa ); bli_param_map_blis_to_netlib_diag( diaga, &f77_diaga ); // Begin with initializing the last entry to zero so that // matlab allocates space for the entire array once up-front. for ( p = p_begin; p + p_inc <= p_max; p += p_inc ) ; printf( "data_%s_%ctrmm_%s", THR_STR, dt_ch, STR ); printf( "( %2lu, 1:3 ) = [ %4lu %4lu %7.2f ];\n", ( unsigned long )(p - p_begin)/p_inc + 1, ( unsigned long )0, ( unsigned long )0, 0.0 ); //for ( p = p_begin; p <= p_max; p += p_inc ) for ( p = p_max; p_begin <= p; p -= p_inc ) { if ( m_input < 0 ) m = p / ( dim_t )abs(m_input); else m = ( dim_t ) m_input; if ( n_input < 0 ) n = p / ( dim_t )abs(n_input); else n = ( dim_t ) n_input; bli_obj_create( dt, 1, 1, 0, 0, &alpha ); if ( bli_is_left( side ) ) bli_obj_create( dt, m, m, 0, 0, &a ); else bli_obj_create( dt, n, n, 0, 0, &a ); bli_obj_create( dt, m, n, 0, 0, &c ); bli_obj_create( dt, m, n, 0, 0, &c_save ); bli_randm( &a ); bli_randm( &c ); bli_obj_set_struc( BLIS_TRIANGULAR, &a ); bli_obj_set_uplo( uploa, &a ); bli_obj_set_conjtrans( transa, &a ); bli_obj_set_diag( diaga, &a ); bli_randm( &a ); bli_mktrim( &a ); bli_setsc( (2.0/1.0), 0.0, &alpha ); bli_copym( &c, &c_save ); #if 0 //def BLIS bli_ind_disable_all_dt( dt ); bli_ind_enable_dt( ind, dt ); #endif dtime_save = DBL_MAX; for ( r = 0; r < n_repeats; ++r ) { bli_copym( &c_save, &c ); dtime = bli_clock(); #ifdef PRINT bli_printm( "a", &a, "%4.1f", "" ); bli_printm( "c", &c, "%4.1f", "" ); #endif #ifdef BLIS bli_trmm( side, &alpha, &a, &c ); #else if ( bli_is_float( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldc = bli_obj_col_stride( &c ); float* alphap = ( float* )bli_obj_buffer( &alpha ); float* ap = ( float* )bli_obj_buffer( &a ); float* cp = ( float* )bli_obj_buffer( &c ); strmm_( &f77_side, &f77_uploa, &f77_transa, &f77_diaga, &mm, &kk, alphap, ap, &lda, cp, &ldc ); } else if ( bli_is_double( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldc = bli_obj_col_stride( &c ); double* alphap = ( double* )bli_obj_buffer( &alpha ); double* ap = ( double* )bli_obj_buffer( &a ); double* cp = ( double* )bli_obj_buffer( &c ); dtrmm_( &f77_side, &f77_uploa, &f77_transa, &f77_diaga, &mm, &kk, alphap, ap, &lda, cp, &ldc ); } else if ( bli_is_scomplex( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldc = bli_obj_col_stride( &c ); #ifdef EIGEN float* alphap = ( float* )bli_obj_buffer( &alpha ); float* ap = ( float* )bli_obj_buffer( &a ); float* cp = ( float* )bli_obj_buffer( &c ); #else scomplex* alphap = ( scomplex* )bli_obj_buffer( &alpha ); scomplex* ap = ( scomplex* )bli_obj_buffer( &a ); scomplex* cp = ( scomplex* )bli_obj_buffer( &c ); #endif ctrmm_( &f77_side, &f77_uploa, &f77_transa, &f77_diaga, &mm, &kk, alphap, ap, &lda, cp, &ldc ); } else if ( bli_is_dcomplex( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldc = bli_obj_col_stride( &c ); #ifdef EIGEN double* alphap = ( double* )bli_obj_buffer( &alpha ); double* ap = ( double* )bli_obj_buffer( &a ); double* cp = ( double* )bli_obj_buffer( &c ); #else dcomplex* alphap = ( dcomplex* )bli_obj_buffer( &alpha ); dcomplex* ap = ( dcomplex* )bli_obj_buffer( &a ); dcomplex* cp = ( dcomplex* )bli_obj_buffer( &c ); #endif ztrmm_( &f77_side, &f77_uploa, &f77_transa, &f77_diaga, &mm, &kk, alphap, ap, &lda, cp, &ldc ); } #endif #ifdef PRINT bli_printm( "c after", &c, "%4.1f", "" ); exit(1); #endif dtime_save = bli_clock_min_diff( dtime_save, dtime ); } if ( bli_is_left( side ) ) gflops = ( 1.0 * m * m * n ) / ( dtime_save * 1.0e9 ); else gflops = ( 1.0 * m * n * n ) / ( dtime_save * 1.0e9 ); if ( bli_is_complex( dt ) ) gflops *= 4.0; printf( "data_%s_%ctrmm_%s", THR_STR, dt_ch, STR ); printf( "( %2lu, 1:3 ) = [ %4lu %4lu %7.2f ];\n", ( unsigned long )(p - p_begin)/p_inc + 1, ( unsigned long )m, ( unsigned long )n, gflops ); bli_obj_free( &alpha ); bli_obj_free( &a ); bli_obj_free( &c ); bli_obj_free( &c_save ); } //bli_finalize(); return 0; } blis-0.9.0/test/3/test_trsm.c000066400000000000000000000207251422157504600157760ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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 The University of Texas 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 COPYRIGHT HOLDER 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. */ #include #include "blis.h" //#define PRINT int main( int argc, char** argv ) { obj_t a, c; obj_t c_save; obj_t alpha; dim_t m, n; dim_t p; dim_t p_begin, p_max, p_inc; int m_input, n_input; ind_t ind; num_t dt; char dt_ch; int r, n_repeats; side_t side; uplo_t uploa; trans_t transa; diag_t diaga; f77_char f77_side; f77_char f77_uploa; f77_char f77_transa; f77_char f77_diaga; double dtime; double dtime_save; double gflops; //bli_init(); //bli_error_checking_level_set( BLIS_NO_ERROR_CHECKING ); n_repeats = 3; dt = DT; ind = IND; p_begin = P_BEGIN; p_max = P_MAX; p_inc = P_INC; m_input = -1; n_input = -1; // Supress compiler warnings about unused variable 'ind'. ( void )ind; #if 0 cntx_t* cntx; ind_t ind_mod = ind; // Initialize a context for the current induced method and datatype. cntx = bli_gks_query_ind_cntx( ind_mod, dt ); // Set k to the kc blocksize for the current datatype. k_input = bli_cntx_get_blksz_def_dt( dt, BLIS_KC, cntx ); #elif 1 //k_input = 256; #endif // Choose the char corresponding to the requested datatype. if ( bli_is_float( dt ) ) dt_ch = 's'; else if ( bli_is_double( dt ) ) dt_ch = 'd'; else if ( bli_is_scomplex( dt ) ) dt_ch = 'c'; else dt_ch = 'z'; #if 0 side = BLIS_LEFT; #else side = BLIS_RIGHT; #endif #if 0 uploa = BLIS_LOWER; #else uploa = BLIS_UPPER; #endif transa = BLIS_NO_TRANSPOSE; diaga = BLIS_NONUNIT_DIAG; bli_param_map_blis_to_netlib_side( side, &f77_side ); bli_param_map_blis_to_netlib_uplo( uploa, &f77_uploa ); bli_param_map_blis_to_netlib_trans( transa, &f77_transa ); bli_param_map_blis_to_netlib_diag( diaga, &f77_diaga ); // Begin with initializing the last entry to zero so that // matlab allocates space for the entire array once up-front. for ( p = p_begin; p + p_inc <= p_max; p += p_inc ) ; printf( "data_%s_%ctrsm_%s", THR_STR, dt_ch, STR ); printf( "( %2lu, 1:3 ) = [ %4lu %4lu %7.2f ];\n", ( unsigned long )(p - p_begin)/p_inc + 1, ( unsigned long )0, ( unsigned long )0, 0.0 ); //for ( p = p_begin; p <= p_max; p += p_inc ) for ( p = p_max; p_begin <= p; p -= p_inc ) { if ( m_input < 0 ) m = p / ( dim_t )abs(m_input); else m = ( dim_t ) m_input; if ( n_input < 0 ) n = p / ( dim_t )abs(n_input); else n = ( dim_t ) n_input; bli_obj_create( dt, 1, 1, 0, 0, &alpha ); if ( bli_is_left( side ) ) bli_obj_create( dt, m, m, 0, 0, &a ); else bli_obj_create( dt, n, n, 0, 0, &a ); bli_obj_create( dt, m, n, 0, 0, &c ); //bli_obj_create( dt, m, n, n, 1, &c ); bli_obj_create( dt, m, n, 0, 0, &c_save ); bli_randm( &a ); bli_randm( &c ); bli_obj_set_struc( BLIS_TRIANGULAR, &a ); bli_obj_set_uplo( uploa, &a ); bli_obj_set_conjtrans( transa, &a ); bli_obj_set_diag( diaga, &a ); bli_randm( &a ); bli_mktrim( &a ); // Load the diagonal of A to make it more likely to be invertible. bli_shiftd( &BLIS_TWO, &a ); bli_setsc( (2.0/1.0), 0.0, &alpha ); bli_copym( &c, &c_save ); #if 0 //def BLIS bli_ind_disable_all_dt( dt ); bli_ind_enable_dt( ind, dt ); #endif dtime_save = DBL_MAX; for ( r = 0; r < n_repeats; ++r ) { bli_copym( &c_save, &c ); dtime = bli_clock(); #ifdef PRINT bli_printm( "a", &a, "%4.1f", "" ); bli_printm( "c", &c, "%4.1f", "" ); #endif #ifdef BLIS bli_trsm( side, &alpha, &a, &c ); #else if ( bli_is_float( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldc = bli_obj_col_stride( &c ); float* alphap = ( float* )bli_obj_buffer( &alpha ); float* ap = ( float* )bli_obj_buffer( &a ); float* cp = ( float* )bli_obj_buffer( &c ); strsm_( &f77_side, &f77_uploa, &f77_transa, &f77_diaga, &mm, &kk, alphap, ap, &lda, cp, &ldc ); } else if ( bli_is_double( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldc = bli_obj_col_stride( &c ); double* alphap = ( double* )bli_obj_buffer( &alpha ); double* ap = ( double* )bli_obj_buffer( &a ); double* cp = ( double* )bli_obj_buffer( &c ); dtrsm_( &f77_side, &f77_uploa, &f77_transa, &f77_diaga, &mm, &kk, alphap, ap, &lda, cp, &ldc ); } else if ( bli_is_scomplex( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldc = bli_obj_col_stride( &c ); #ifdef EIGEN float* alphap = ( float* )bli_obj_buffer( &alpha ); float* ap = ( float* )bli_obj_buffer( &a ); float* cp = ( float* )bli_obj_buffer( &c ); #else scomplex* alphap = ( scomplex* )bli_obj_buffer( &alpha ); scomplex* ap = ( scomplex* )bli_obj_buffer( &a ); scomplex* cp = ( scomplex* )bli_obj_buffer( &c ); #endif ctrsm_( &f77_side, &f77_uploa, &f77_transa, &f77_diaga, &mm, &kk, alphap, ap, &lda, cp, &ldc ); } else if ( bli_is_dcomplex( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldc = bli_obj_col_stride( &c ); #ifdef EIGEN double* alphap = ( double* )bli_obj_buffer( &alpha ); double* ap = ( double* )bli_obj_buffer( &a ); double* cp = ( double* )bli_obj_buffer( &c ); #else dcomplex* alphap = ( dcomplex* )bli_obj_buffer( &alpha ); dcomplex* ap = ( dcomplex* )bli_obj_buffer( &a ); dcomplex* cp = ( dcomplex* )bli_obj_buffer( &c ); #endif ztrsm_( &f77_side, &f77_uploa, &f77_transa, &f77_diaga, &mm, &kk, alphap, ap, &lda, cp, &ldc ); } #endif #ifdef PRINT bli_printm( "c after", &c, "%4.1f", "" ); exit(1); #endif dtime_save = bli_clock_min_diff( dtime_save, dtime ); } if ( bli_is_left( side ) ) gflops = ( 1.0 * m * m * n ) / ( dtime_save * 1.0e9 ); else gflops = ( 1.0 * m * n * n ) / ( dtime_save * 1.0e9 ); if ( bli_is_complex( dt ) ) gflops *= 4.0; printf( "data_%s_%ctrsm_%s", THR_STR, dt_ch, STR ); printf( "( %2lu, 1:3 ) = [ %4lu %4lu %7.2f ];\n", ( unsigned long )(p - p_begin)/p_inc + 1, ( unsigned long )m, ( unsigned long )n, gflops ); bli_obj_free( &alpha ); bli_obj_free( &a ); bli_obj_free( &c ); bli_obj_free( &c_save ); } //bli_finalize(); return 0; } blis-0.9.0/test/Makefile000066400000000000000000000147771422157504600151160ustar00rootroot00000000000000# # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2014, The University of Texas at Austin # Copyright (C) 2017 - 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # # # Makefile # # Field G. Van Zee # # Makefile for standalone BLIS test drivers. # # # --- Makefile PHONY target definitions ---------------------------------------- # .PHONY: all \ blis openblas atlas mkl \ check-env check-env-mk check-lib \ clean cleanx # # --- Determine makefile fragment location ------------------------------------- # # Comments: # - DIST_PATH is assumed to not exist if BLIS_INSTALL_PATH is given. # - We must use recursively expanded assignment for LIB_PATH and INC_PATH in # the second case because CONFIG_NAME is not yet set. ifneq ($(strip $(BLIS_INSTALL_PATH)),) LIB_PATH := $(BLIS_INSTALL_PATH)/lib INC_PATH := $(BLIS_INSTALL_PATH)/include/blis SHARE_PATH := $(BLIS_INSTALL_PATH)/share/blis else DIST_PATH := .. LIB_PATH = ../lib/$(CONFIG_NAME) INC_PATH = ../include/$(CONFIG_NAME) SHARE_PATH := .. endif # # --- Include common makefile definitions -------------------------------------- # # Include the common makefile fragment. -include $(SHARE_PATH)/common.mk # # --- BLAS and LAPACK implementations ------------------------------------------ # # BLIS library and header path. This is simply wherever it was installed. #BLIS_LIB_PATH := $(INSTALL_PREFIX)/lib #BLIS_INC_PATH := $(INSTALL_PREFIX)/include/blis # BLIS library. #BLIS_LIB := $(BLIS_LIB_PATH)/libblis.a # BLAS library path(s). This is where the BLAS libraries reside. BLAS_LIB_PATH := $(HOME)/flame/lib #MKL_LIB_PATH := /opt/apps/intel/13/composer_xe_2013.2.146/mkl/lib/intel64 #MKL_LIB_PATH := $(HOME)/intel/mkl/lib/intel64 MKL_LIB_PATH := $(HOME)/intel/mkl/lib/intel64 # OpenBLAS OPENBLAS_LIB := $(BLAS_LIB_PATH)/libopenblas.a # MKL MKL_LIB := -L$(MKL_LIB_PATH) \ -lmkl_intel_lp64 \ -lmkl_core \ -lmkl_sequential \ -lpthread -lm -ldl # # --- General build definitions ------------------------------------------------ # TEST_SRC_PATH := . TEST_OBJ_PATH := . # Gather all local object files. TEST_OBJS := $(patsubst $(TEST_SRC_PATH)/%.c, \ $(TEST_OBJ_PATH)/%.o, \ $(wildcard $(TEST_SRC_PATH)/*.c)) # Override the value of CINCFLAGS so that the value of CFLAGS returned by # get-user-cflags-for() is not cluttered up with include paths needed only # while building BLIS. CINCFLAGS := -I$(INC_PATH) # Use the CFLAGS for the configuration family. CFLAGS := $(call get-user-cflags-for,$(CONFIG_NAME)) # Add local header paths to CFLAGS CFLAGS += -I$(TEST_SRC_PATH) # Locate the libblis library to which we will link. #LIBBLIS_LINK := $(LIB_PATH)/$(LIBBLIS_L) # # --- Targets/rules ------------------------------------------------------------ # # Define the operations we will test. TEST_OPS := dotv axpyv axpbyv\ gemv ger hemv her her2 trmv trsv \ gemm gemm3m gemm_batch hemm herk her2k trmm trsm # Optionally test gemmt, which some libraries might not implement. ifeq ($(BUILD_GEMMT),yes) TEST_OPS := $(TEST_OPS) gemmt endif # Define a function to create the executable names. test-bins = $(foreach op, $(TEST_OPS), test_$(op)_$(1).x) # Create the list of executables for each implementation. TEST_BINS_BLIS := $(call test-bins,blis) TEST_BINS_OPENBLAS := $(call test-bins,openblas) TEST_BINS_MKL := $(call test-bins,mkl) all: blis openblas mkl blis: check-env $(TEST_BINS_BLIS) openblas: check-env $(TEST_BINS_OPENBLAS) mkl: check-env $(TEST_BINS_MKL) # --Object file rules -- $(TEST_OBJ_PATH)/%.o: $(TEST_SRC_PATH)/%.c $(CC) $(CFLAGS) -c $< -o $@ test_%_openblas.o: test_%.c $(CC) $(CFLAGS) -DBLAS=\"openblas\" -c $< -o $@ test_%_mkl.o: test_%.c $(CC) $(CFLAGS) -DBLAS=\"mkl\" -c $< -o $@ test_%_blis.o: test_%.c $(CC) $(CFLAGS) -DBLIS -c $< -o $@ # -- Executable file rules -- # NOTE: For the BLAS test drivers, we place the BLAS libraries before BLIS # on the link command line in case BLIS was configured with the BLAS # compatibility layer. This prevents BLIS from inadvertently getting called # for the BLAS routines we are trying to test with. test_%_openblas.x: test_%_openblas.o $(LIBBLIS_LINK) $(LINKER) $< $(OPENBLAS_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $@ test_%_mkl.x: test_%_mkl.o $(LIBBLIS_LINK) $(LINKER) $< $(MKL_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $@ test_%_blis.x: test_%_blis.o $(LIBBLIS_LINK) $(LINKER) $< $(LIBBLIS_LINK) $(LDFLAGS) -o $@ # -- Environment check rules -- check-env: check-lib check-env-mk: ifeq ($(CONFIG_MK_PRESENT),no) $(error Cannot proceed: config.mk not detected! Run configure first) endif check-lib: check-env-mk ifeq ($(wildcard $(LIBBLIS_LINK)),) $(error Cannot proceed: BLIS library not yet built! Run make first) endif # -- Clean rules -- clean: cleanx cleanx: - $(RM_F) *.o *.x blis-0.9.0/test/exec_sizes/000077500000000000000000000000001422157504600155775ustar00rootroot00000000000000blis-0.9.0/test/exec_sizes/Makefile000066400000000000000000000274061422157504600172500ustar00rootroot00000000000000#!/bin/bash # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2014, The University of Texas at Austin # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # # # Makefile # # Field G. Van Zee # # Makefile for standalone BLIS test drivers. # # # --- Makefile PHONY target definitions ---------------------------------------- # .PHONY: all \ blis openblas atlas mkl \ clean cleanx # # --- Determine makefile fragment location ------------------------------------- # # Comments: # - DIST_PATH is assumed to not exist if BLIS_INSTALL_PATH is given. # - We must use recursively expanded assignment for LIB_PATH and INC_PATH in # the second case because CONFIG_NAME is not yet set. ifneq ($(strip $(BLIS_INSTALL_PATH)),) LIB_PATH := $(BLIS_INSTALL_PATH)/lib INC_PATH := $(BLIS_INSTALL_PATH)/include/blis SHARE_PATH := $(BLIS_INSTALL_PATH)/share/blis else DIST_PATH := ../.. LIB_PATH = ../../lib/$(CONFIG_NAME) INC_PATH = ../../include/$(CONFIG_NAME) SHARE_PATH := ../.. endif # # --- Include common makefile definitions -------------------------------------- # # Include the common makefile fragment. -include $(SHARE_PATH)/common.mk # # --- BLAS and LAPACK implementations ------------------------------------------ # # BLIS library and header path. This is simply wherever it was installed. #BLIS_LIB_PATH := $(INSTALL_PREFIX)/lib #BLIS_INC_PATH := $(INSTALL_PREFIX)/include/blis # BLIS library. #BLIS_LIB := $(BLIS_LIB_PATH)/libblis.a # BLAS library path(s). This is where the BLAS libraries reside. BLAS_LIB_PATH := $(HOME)/flame/lib #MKL_LIB_PATH := $(HOME)/intel/mkl/lib/intel64/ MKL_LIB_PATH := ${MKLROOT}/lib/intel64 # OpenBLAS, ATLAS, and MKL libraries. #BLAS_LIB := $(LIB_PATH)/libblas.a #BLAS_LIB := $(LIB_PATH)/libgoto.a #BLAS_LIB := $(LIB_PATH)/libgoto2.a OBLAS_LIB := $(BLAS_LIB_PATH)/libopenblas.a ABLAS_LIB := $(BLAS_LIB_PATH)/libf77blas.a \ $(BLAS_LIB_PATH)/libatlas.a #MBLAS_LIB := -L$(MKL_LIB_PATH) \ # -lmkl_sequential \ # -lmkl_core \ # -lmkl_intel_lp64 #MBLAS_LIB := -Wl,--start-group \ # $(MKL_LIB_PATH)/libmkl_sequential.a \ # $(MKL_LIB_PATH)/libmkl_core.a \ # $(MKL_LIB_PATH)/libmkl_intel_ilp64.a \ # -Wl,--end-group \ # -lpthread -lm MBLAS_LIB := -L$(MKL_LIB_PATH) \ -lmkl_intel_lp64 \ -lmkl_core \ -lmkl_sequential \ -lpthread -lm -ldl # # --- General build definitions ------------------------------------------------ # TEST_SRC_PATH := . TEST_OBJ_PATH := . ## Gather all local source files. TEST_SIZES_SRC := test_size.c # Override the value of CINCFLAGS so that the value of CFLAGS returned by # get-user-cflags-for() is not cluttered up with include paths needed only # while building BLIS. CINCFLAGS := -I$(INC_PATH) # Use the CFLAGS for the configuration family. CFLAGS := $(call get-user-cflags-for,$(CONFIG_NAME)) # Add local header paths to CFLAGS CFLAGS += -I$(TEST_SRC_PATH) # Locate the libblis library to which we will link. #LIBBLIS_LINK := $(LIB_PATH)/$(LIBBLIS_L) # # --- Targets/rules ------------------------------------------------------------ # MAKE_BLIS := yes MAKE_OPENBLAS := yes MAKE_MKL := yes MAKE_ATLAS := no MAKE_DCOMPLEX := yes ifeq ($(MAKE_BLIS),yes) TEST_BINS += test_blis01 \ test_blis02 \ test_blis03 \ test_blis04 \ test_blis05 \ test_blis06 ifeq ($(MAKE_DCOMPLEX),yes) TEST_BINS += test_blis07 \ test_blis08 \ test_blis09 \ test_blis10 \ test_blis11 \ test_blis12 endif endif ifeq ($(MAKE_OPENBLAS),yes) TEST_BINS += test_oblas01 \ test_oblas02 \ test_oblas03 \ test_oblas04 \ test_oblas05 \ test_oblas06 ifeq ($(MAKE_DCOMPLEX),yes) TEST_BINS += test_oblas07 \ test_oblas08 \ test_oblas09 \ test_oblas10 \ test_oblas11 \ test_oblas12 endif endif ifeq ($(MAKE_ATLAS),yes) TEST_BINS += test_ablas01 \ test_ablas02 \ test_ablas03 \ test_ablas04 \ test_ablas05 \ test_ablas06 ifeq ($(MAKE_DCOMPLEX),yes) TEST_BINS += test_ablas07 \ test_ablas08 \ test_ablas09 \ test_ablas10 \ test_ablas11 \ test_ablas12 endif endif ifeq ($(MAKE_MKL),yes) TEST_BINS += test_mblas01 \ test_mblas02 \ test_mblas03 \ test_mblas04 \ test_mblas05 \ test_mblas06 ifeq ($(MAKE_DCOMPLEX),yes) TEST_BINS += test_mblas07 \ test_mblas08 \ test_mblas09 \ test_mblas10 \ test_mblas11 \ test_mblas12 endif endif # --Object file rules -- all: $(TEST_BINS) $(TEST_OBJ_PATH)/%.o: $(TEST_SRC_PATH)/%.c $(CC) $(CFLAGS) -c $< -o $@ # -- Executable file rules -- # BLIS rules test_blis01: $(CC) $(CFLAGS) -DNBLIS=1 $(TEST_SIZES_SRC) $(LIBBLIS_LINK) $(LDFLAGS) -o $@.x test_blis02: $(CC) $(CFLAGS) -DNBLIS=2 $(TEST_SIZES_SRC) $(LIBBLIS_LINK) $(LDFLAGS) -o $@.x test_blis03: $(CC) $(CFLAGS) -DNBLIS=3 $(TEST_SIZES_SRC) $(LIBBLIS_LINK) $(LDFLAGS) -o $@.x test_blis04: $(CC) $(CFLAGS) -DNBLIS=4 $(TEST_SIZES_SRC) $(LIBBLIS_LINK) $(LDFLAGS) -o $@.x test_blis05: $(CC) $(CFLAGS) -DNBLIS=5 $(TEST_SIZES_SRC) $(LIBBLIS_LINK) $(LDFLAGS) -o $@.x test_blis06: $(CC) $(CFLAGS) -DNBLIS=6 $(TEST_SIZES_SRC) $(LIBBLIS_LINK) $(LDFLAGS) -o $@.x test_blis07: $(CC) $(CFLAGS) -DNBLIS=7 $(TEST_SIZES_SRC) $(LIBBLIS_LINK) $(LDFLAGS) -o $@.x test_blis08: $(CC) $(CFLAGS) -DNBLIS=8 $(TEST_SIZES_SRC) $(LIBBLIS_LINK) $(LDFLAGS) -o $@.x test_blis09: $(CC) $(CFLAGS) -DNBLIS=9 $(TEST_SIZES_SRC) $(LIBBLIS_LINK) $(LDFLAGS) -o $@.x test_blis10: $(CC) $(CFLAGS) -DNBLIS=10 $(TEST_SIZES_SRC) $(LIBBLIS_LINK) $(LDFLAGS) -o $@.x test_blis11: $(CC) $(CFLAGS) -DNBLIS=11 $(TEST_SIZES_SRC) $(LIBBLIS_LINK) $(LDFLAGS) -o $@.x test_blis12: $(CC) $(CFLAGS) -DNBLIS=12 $(TEST_SIZES_SRC) $(LIBBLIS_LINK) $(LDFLAGS) -o $@.x # OpenBLAS rules test_oblas01: $(CC) $(CFLAGS) -DNBLAS=1 $(TEST_SIZES_SRC) $(OBLAS_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $@.x test_oblas02: $(CC) $(CFLAGS) -DNBLAS=2 $(TEST_SIZES_SRC) $(OBLAS_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $@.x test_oblas03: $(CC) $(CFLAGS) -DNBLAS=3 $(TEST_SIZES_SRC) $(OBLAS_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $@.x test_oblas04: $(CC) $(CFLAGS) -DNBLAS=4 $(TEST_SIZES_SRC) $(OBLAS_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $@.x test_oblas05: $(CC) $(CFLAGS) -DNBLAS=5 $(TEST_SIZES_SRC) $(OBLAS_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $@.x test_oblas06: $(CC) $(CFLAGS) -DNBLAS=6 $(TEST_SIZES_SRC) $(OBLAS_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $@.x test_oblas07: $(CC) $(CFLAGS) -DNBLAS=7 $(TEST_SIZES_SRC) $(OBLAS_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $@.x test_oblas08: $(CC) $(CFLAGS) -DNBLAS=8 $(TEST_SIZES_SRC) $(OBLAS_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $@.x test_oblas09: $(CC) $(CFLAGS) -DNBLAS=9 $(TEST_SIZES_SRC) $(OBLAS_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $@.x test_oblas10: $(CC) $(CFLAGS) -DNBLAS=10 $(TEST_SIZES_SRC) $(OBLAS_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $@.x test_oblas11: $(CC) $(CFLAGS) -DNBLAS=11 $(TEST_SIZES_SRC) $(OBLAS_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $@.x test_oblas12: $(CC) $(CFLAGS) -DNBLAS=12 $(TEST_SIZES_SRC) $(OBLAS_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $@.x # ATLAS BLAS rules test_ablas01: $(CC) $(CFLAGS) -DNBLAS=1 $(TEST_SIZES_SRC) $(ABLAS_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $@.x test_ablas02: $(CC) $(CFLAGS) -DNBLAS=2 $(TEST_SIZES_SRC) $(ABLAS_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $@.x test_ablas03: $(CC) $(CFLAGS) -DNBLAS=3 $(TEST_SIZES_SRC) $(ABLAS_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $@.x test_ablas04: $(CC) $(CFLAGS) -DNBLAS=4 $(TEST_SIZES_SRC) $(ABLAS_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $@.x test_ablas05: $(CC) $(CFLAGS) -DNBLAS=5 $(TEST_SIZES_SRC) $(ABLAS_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $@.x test_ablas06: $(CC) $(CFLAGS) -DNBLAS=6 $(TEST_SIZES_SRC) $(ABLAS_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $@.x test_ablas07: $(CC) $(CFLAGS) -DNBLAS=7 $(TEST_SIZES_SRC) $(ABLAS_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $@.x test_ablas08: $(CC) $(CFLAGS) -DNBLAS=8 $(TEST_SIZES_SRC) $(ABLAS_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $@.x test_ablas09: $(CC) $(CFLAGS) -DNBLAS=9 $(TEST_SIZES_SRC) $(ABLAS_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $@.x test_ablas10: $(CC) $(CFLAGS) -DNBLAS=10 $(TEST_SIZES_SRC) $(ABLAS_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $@.x test_ablas11: $(CC) $(CFLAGS) -DNBLAS=11 $(TEST_SIZES_SRC) $(ABLAS_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $@.x test_ablas12: $(CC) $(CFLAGS) -DNBLAS=12 $(TEST_SIZES_SRC) $(ABLAS_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $@.x # MKL BLAS rules test_mblas01: $(CC) $(CFLAGS) -DNBLAS=1 $(TEST_SIZES_SRC) $(MBLAS_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $@.x test_mblas02: $(CC) $(CFLAGS) -DNBLAS=2 $(TEST_SIZES_SRC) $(MBLAS_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $@.x test_mblas03: $(CC) $(CFLAGS) -DNBLAS=3 $(TEST_SIZES_SRC) $(MBLAS_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $@.x test_mblas04: $(CC) $(CFLAGS) -DNBLAS=4 $(TEST_SIZES_SRC) $(MBLAS_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $@.x test_mblas05: $(CC) $(CFLAGS) -DNBLAS=5 $(TEST_SIZES_SRC) $(MBLAS_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $@.x test_mblas06: $(CC) $(CFLAGS) -DNBLAS=6 $(TEST_SIZES_SRC) $(MBLAS_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $@.x test_mblas07: $(CC) $(CFLAGS) -DNBLAS=7 $(TEST_SIZES_SRC) $(MBLAS_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $@.x test_mblas08: $(CC) $(CFLAGS) -DNBLAS=8 $(TEST_SIZES_SRC) $(MBLAS_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $@.x test_mblas09: $(CC) $(CFLAGS) -DNBLAS=9 $(TEST_SIZES_SRC) $(MBLAS_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $@.x test_mblas10: $(CC) $(CFLAGS) -DNBLAS=10 $(TEST_SIZES_SRC) $(MBLAS_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $@.x test_mblas11: $(CC) $(CFLAGS) -DNBLAS=11 $(TEST_SIZES_SRC) $(MBLAS_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $@.x test_mblas12: $(CC) $(CFLAGS) -DNBLAS=12 $(TEST_SIZES_SRC) $(MBLAS_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $@.x # -- Clean rules -- clean: cleanx cleanx: - $(RM_F) *.x blis-0.9.0/test/exec_sizes/grab_top_outputs.sh000077500000000000000000000044331422157504600215420ustar00rootroot00000000000000#!/bin/bash # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2014, The University of Texas at Austin # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # # output_file="output_mem_sizes.txt" exec_prefix="test" exec_blis="blis1 blis2 blis3 blis4 blis5 blis6" exec_oblas="oblas1 oblas2 oblas3 oblas4 oblas5 oblas6" exec_ablas="ablas1 ablas2 ablas3 ablas4 ablas5 ablas6" exec_mblas="mblas1 mblas2 mblas3 mblas4 mblas5 mblas6" execs="${exec_blis} ${exec_oblas} ${exec_ablas} ${exec_mblas}" # Send column labels to the output file. top -n 1 -b | grep COMMAND >> ${output_file} for e in ${execs}; do exec_name="${exec_prefix}_${e}.x" echo "Capturing ${exec_name}..." ./${exec_name} & sleep 1 top -n 1 -b | grep "${exec_prefix}" >> ${output_file} pkill "${exec_name}" > /dev/null done blis-0.9.0/test/exec_sizes/makefile.prev000066400000000000000000000116431422157504600202570ustar00rootroot00000000000000# # test directory makefile # MAKE_BLIS := yes MAKE_OPEN := yes MAKE_ATLAS := yes MAKE_MKL := yes BLIS_LIB := $(HOME)/blis/lib/libblis.a INC_PATH := $(HOME)/blis/include LIB_PATH := $(HOME)/flame/lib MKL_PATH := /opt/intel/mkl/10.2.2.025 OBLAS_LIB := $(LIB_PATH)/libopenblas.a ABLAS_LIB := $(LIB_PATH)/libf77blas.a \ $(LIB_PATH)/libatlas.a #BLAS_LIB := -L/opt/intel/mkl/10.2.2.025/lib/em64t/ \ # -lmkl_sequential -lmkl_core -lmkl_intel_lp64 MBLAS_LIB := $(MKL_PATH)/lib/em64t/libmkl_solver_lp64_sequential.a \ -Wl,--start-group \ $(MKL_PATH)/lib/em64t/libmkl_intel_lp64.a \ $(MKL_PATH)/lib/em64t/libmkl_sequential.a \ $(MKL_PATH)/lib/em64t/libmkl_core.a \ -Wl,--end-group \ -lpthread -lm CC := gcc CFLAGS := -I$(INC_PATH) \ -O2 -fomit-frame-pointer \ -std=c99 \ -Wall -Wno-comment #-pg #-g LINKER := $(CC) LDFLAGS := -L/usr/lib/gcc/x86_64-redhat-linux/4.1.2 -L/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../lib64 -L/lib/../lib64 -L/usr/lib/../lib64 -lgfortranbegin -lgfortran -lm LDFLAGS += -lpthread TEST_SIZES_SRC := test_size.c TEST_BINS := ifeq ($(MAKE_BLIS),yes) TEST_BINS += test_blis1 \ test_blis2 \ test_blis3 \ test_blis4 \ test_blis5 \ test_blis6 endif ifeq ($(MAKE_OPEN),yes) TEST_BINS += test_oblas1 \ test_oblas2 \ test_oblas3 \ test_oblas4 \ test_oblas5 \ test_oblas6 endif ifeq ($(MAKE_ATLAS),yes) TEST_BINS += test_ablas1 \ test_ablas2 \ test_ablas3 \ test_ablas4 \ test_ablas5 \ test_ablas6 endif ifeq ($(MAKE_MKL),yes) TEST_BINS += test_mblas1 \ test_mblas2 \ test_mblas3 \ test_mblas4 \ test_mblas5 \ test_mblas6 endif %.o: %.c $(CC) $(CFLAGS) -c $< -o $@ all: $(TEST_BINS) # @echo "$(TEST_BINS)" # BLIS rules test_blis1: $(BLIS_LIB) $(CC) $(CFLAGS) -DNBLIS=1 $(TEST_SIZES_SRC) $(BLIS_LIB) $(LDFLAGS) -o $@.x test_blis2: $(BLIS_LIB) $(CC) $(CFLAGS) -DNBLIS=2 $(TEST_SIZES_SRC) $(BLIS_LIB) $(LDFLAGS) -o $@.x test_blis3: $(BLIS_LIB) $(CC) $(CFLAGS) -DNBLIS=3 $(TEST_SIZES_SRC) $(BLIS_LIB) $(LDFLAGS) -o $@.x test_blis4: $(BLIS_LIB) $(CC) $(CFLAGS) -DNBLIS=4 $(TEST_SIZES_SRC) $(BLIS_LIB) $(LDFLAGS) -o $@.x test_blis5: $(BLIS_LIB) $(CC) $(CFLAGS) -DNBLIS=5 $(TEST_SIZES_SRC) $(BLIS_LIB) $(LDFLAGS) -o $@.x test_blis6: $(BLIS_LIB) $(CC) $(CFLAGS) -DNBLIS=6 $(TEST_SIZES_SRC) $(BLIS_LIB) $(LDFLAGS) -o $@.x # OpenBLAS rules test_oblas1: $(BLIS_LIB) $(CC) $(CFLAGS) -DNBLAS=1 $(TEST_SIZES_SRC) $(BLIS_LIB) $(OBLAS_LIB) $(LDFLAGS) -o $@.x test_oblas2: $(BLIS_LIB) $(CC) $(CFLAGS) -DNBLAS=2 $(TEST_SIZES_SRC) $(BLIS_LIB) $(OBLAS_LIB) $(LDFLAGS) -o $@.x test_oblas3: $(BLIS_LIB) $(CC) $(CFLAGS) -DNBLAS=3 $(TEST_SIZES_SRC) $(BLIS_LIB) $(OBLAS_LIB) $(LDFLAGS) -o $@.x test_oblas4: $(BLIS_LIB) $(CC) $(CFLAGS) -DNBLAS=4 $(TEST_SIZES_SRC) $(BLIS_LIB) $(OBLAS_LIB) $(LDFLAGS) -o $@.x test_oblas5: $(BLIS_LIB) $(CC) $(CFLAGS) -DNBLAS=5 $(TEST_SIZES_SRC) $(BLIS_LIB) $(OBLAS_LIB) $(LDFLAGS) -o $@.x test_oblas6: $(BLIS_LIB) $(CC) $(CFLAGS) -DNBLAS=6 $(TEST_SIZES_SRC) $(BLIS_LIB) $(OBLAS_LIB) $(LDFLAGS) -o $@.x # ATLAS BLAS rules test_ablas1: $(BLIS_LIB) $(CC) $(CFLAGS) -DNBLAS=1 $(TEST_SIZES_SRC) $(BLIS_LIB) $(ABLAS_LIB) $(LDFLAGS) -o $@.x test_ablas2: $(BLIS_LIB) $(CC) $(CFLAGS) -DNBLAS=2 $(TEST_SIZES_SRC) $(BLIS_LIB) $(ABLAS_LIB) $(LDFLAGS) -o $@.x test_ablas3: $(BLIS_LIB) $(CC) $(CFLAGS) -DNBLAS=3 $(TEST_SIZES_SRC) $(BLIS_LIB) $(ABLAS_LIB) $(LDFLAGS) -o $@.x test_ablas4: $(BLIS_LIB) $(CC) $(CFLAGS) -DNBLAS=4 $(TEST_SIZES_SRC) $(BLIS_LIB) $(ABLAS_LIB) $(LDFLAGS) -o $@.x test_ablas5: $(BLIS_LIB) $(CC) $(CFLAGS) -DNBLAS=5 $(TEST_SIZES_SRC) $(BLIS_LIB) $(ABLAS_LIB) $(LDFLAGS) -o $@.x test_ablas6: $(BLIS_LIB) $(CC) $(CFLAGS) -DNBLAS=6 $(TEST_SIZES_SRC) $(BLIS_LIB) $(ABLAS_LIB) $(LDFLAGS) -o $@.x # MKL BLAS rules test_mblas1: $(BLIS_LIB) $(CC) $(CFLAGS) -DNBLAS=1 $(TEST_SIZES_SRC) $(BLIS_LIB) $(MBLAS_LIB) $(LDFLAGS) -o $@.x test_mblas2: $(BLIS_LIB) $(CC) $(CFLAGS) -DNBLAS=2 $(TEST_SIZES_SRC) $(BLIS_LIB) $(MBLAS_LIB) $(LDFLAGS) -o $@.x test_mblas3: $(BLIS_LIB) $(CC) $(CFLAGS) -DNBLAS=3 $(TEST_SIZES_SRC) $(BLIS_LIB) $(MBLAS_LIB) $(LDFLAGS) -o $@.x test_mblas4: $(BLIS_LIB) $(CC) $(CFLAGS) -DNBLAS=4 $(TEST_SIZES_SRC) $(BLIS_LIB) $(MBLAS_LIB) $(LDFLAGS) -o $@.x test_mblas5: $(BLIS_LIB) $(CC) $(CFLAGS) -DNBLAS=5 $(TEST_SIZES_SRC) $(BLIS_LIB) $(MBLAS_LIB) $(LDFLAGS) -o $@.x test_mblas6: $(BLIS_LIB) $(CC) $(CFLAGS) -DNBLAS=6 $(TEST_SIZES_SRC) $(BLIS_LIB) $(MBLAS_LIB) $(LDFLAGS) -o $@.x clean: rm -f *.x blis-0.9.0/test/exec_sizes/test_size.c000066400000000000000000000333061422157504600177610ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include #include "blis.h" /* void dgemm_ ( char* transa, char* transb, int* m, int* n, int* k, double* alpha, double* a, int* lda, double* b, int* ldb, double* beta, double* c, int* ldc ); void zhemm_ ( char* side, char* uplo, int* m, int* n, dcomplex* alpha, dcomplex* a, int* lda, dcomplex* b, int* ldb, dcomplex* beta, dcomplex* c, int* ldc ); void zherk_ ( char* uplo, char* transa, int* n, int* k, double* alpha, dcomplex* a, int* lda, double* beta, dcomplex* c, int* ldc ); void zher2k_( char* uplo, char* transa, int* n, int* k, dcomplex* alpha, dcomplex* a, int* lda, dcomplex* b, int* ldb, double* beta, dcomplex* c, int* ldc ); void dsymm_ ( char* side, char* uplo, int* m, int* n, double* alpha, double* a, int* lda, double* b, int* ldb, double* beta, double* c, int* ldc ); void dsyrk_ ( char* uplo, char* transa, int* n, int* k, double* alpha, double* a, int* lda, double* beta, double* c, int* ldc ); void dsyr2k_( char* uplo, char* transa, int* n, int* k, double* alpha, double* a, int* lda, double* b, int* ldb, double* beta, double* c, int* ldc ); void dtrmm_ ( char* side, char* uplo, char* transa, char* diag, int* m, int* n, double* alpha, double* a, int* lda, double* b, int* ldb ); void dtrsm_ ( char* side, char* uplo, char* transa, char* diag, int* m, int* n, double* alpha, double* a, int* lda, double* b, int* ldb ); */ int main( int argc, char** argv ) { obj_t a, b, c; obj_t x, y; obj_t alpha, beta; dim_t m; num_t dt_a, dt_b, dt_c; num_t dt_alpha, dt_beta; int ii; #ifdef NBLIS //bli_init(); #endif m = 4000; dt_a = BLIS_DOUBLE; dt_b = BLIS_DOUBLE; dt_c = BLIS_DOUBLE; dt_alpha = BLIS_DOUBLE; dt_beta = BLIS_DOUBLE; { #ifdef NBLIS bli_obj_create( dt_alpha, 1, 1, 0, 0, &alpha ); bli_obj_create( dt_beta, 1, 1, 0, 0, &beta ); bli_obj_create( dt_a, m, 1, 0, 0, &x ); bli_obj_create( dt_a, m, 1, 0, 0, &y ); bli_obj_create( dt_a, m, m, 0, 0, &a ); bli_obj_create( dt_b, m, m, 0, 0, &b ); bli_obj_create( dt_c, m, m, 0, 0, &c ); bli_randm( &a ); bli_randm( &b ); bli_randm( &c ); bli_setsc( (2.0/1.0), 0.0, &alpha ); bli_setsc( (1.0/1.0), 0.0, &beta ); #endif #ifdef NBLAS x.buffer = malloc( m * 1 * sizeof( double ) ); y.buffer = malloc( m * 1 * sizeof( double ) ); alpha.buffer = malloc( 1 * sizeof( double ) ); beta.buffer = malloc( 1 * sizeof( double ) ); a.buffer = malloc( m * m * sizeof( double ) ); bli_obj_set_dims( m, m, &a ); bli_obj_set_strides( m, 1, &a ); b.buffer = malloc( m * m * sizeof( double ) ); bli_obj_set_dims( m, m, &b ); bli_obj_set_strides( m, 1, &b ); c.buffer = malloc( m * m * sizeof( double ) ); bli_obj_set_dims( m, m, &c ); bli_obj_set_strides( m, 1, &c ); *((double*)alpha.buffer) = 2.0; *((double*)beta.buffer) = -1.0; #endif #ifdef NBLIS #if NBLIS >= 1 for ( ii = 0; ii < 2000000000; ++ii ) { bli_gemm( &BLIS_ONE, &a, &b, &BLIS_ONE, &c ); } #endif #if NBLIS >= 2 { bli_hemm( BLIS_LEFT, &BLIS_ONE, &a, &b, &BLIS_ONE, &c ); } #endif #if NBLIS >= 3 { bli_herk( &BLIS_ONE, &a, &BLIS_ONE, &c ); } #endif #if NBLIS >= 4 { bli_her2k( &BLIS_ONE, &a, &b, &BLIS_ONE, &c ); } #endif #if NBLIS >= 5 { bli_trmm( BLIS_LEFT, &BLIS_ONE, &a, &c ); } #endif #if NBLIS >= 6 { bli_trsm( BLIS_LEFT, &BLIS_ONE, &a, &c ); } #endif #endif #ifdef NBLAS #if NBLAS >= 1 for ( ii = 0; ii < 2000000000; ++ii ) { f77_char transa = 'N'; f77_char transb = 'N'; f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); double* alphap = bli_obj_buffer( &alpha ); double* ap = bli_obj_buffer( &a ); double* bp = bli_obj_buffer( &b ); double* betap = bli_obj_buffer( &beta ); double* cp = bli_obj_buffer( &c ); dgemm_( &transa, &transb, &mm, &nn, &kk, alphap, ap, &lda, bp, &ldb, betap, cp, &ldc ); } #endif #if NBLAS >= 2 { f77_char side = 'L'; f77_char uplo = 'L'; f77_int mm = bli_obj_length( &c ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); double* alphap = bli_obj_buffer( &alpha ); double* ap = bli_obj_buffer( &a ); double* bp = bli_obj_buffer( &b ); double* betap = bli_obj_buffer( &beta ); double* cp = bli_obj_buffer( &c ); dsymm_( &side, &uplo, &mm, &nn, alphap, ap, &lda, bp, &ldb, betap, cp, &ldc ); } #endif #if NBLAS >= 3 { f77_char uplo = 'L'; f77_char trans = 'N'; f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width( &a ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldc = bli_obj_col_stride( &c ); double* alphap = bli_obj_buffer( &alpha ); double* ap = bli_obj_buffer( &a ); double* betap = bli_obj_buffer( &beta ); double* cp = bli_obj_buffer( &c ); dsyrk_( &uplo, &trans, &mm, &kk, alphap, ap, &lda, betap, cp, &ldc ); } #endif #if NBLAS >= 4 { f77_char uplo = 'L'; f77_char trans = 'N'; f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width( &a ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); double* alphap = bli_obj_buffer( &alpha ); double* ap = bli_obj_buffer( &a ); double* bp = bli_obj_buffer( &b ); double* betap = bli_obj_buffer( &beta ); double* cp = bli_obj_buffer( &c ); dsyr2k_( &uplo, &trans, &mm, &kk, alphap, ap, &lda, bp, &ldb, betap, cp, &ldc ); } #endif #if NBLAS >= 5 { f77_char side = 'L'; f77_char uplo = 'L'; f77_char trans = 'N'; f77_char diag = 'N'; f77_int mm = bli_obj_length( &c ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldc = bli_obj_col_stride( &c ); double* alphap = bli_obj_buffer( &alpha ); double* ap = bli_obj_buffer( &a ); double* cp = bli_obj_buffer( &c ); dtrmm_( &side, &uplo, &trans, &diag, &mm, &nn, alphap, ap, &lda, cp, &ldc ); } #endif #if NBLAS >= 6 { f77_char side = 'L'; f77_char uplo = 'L'; f77_char trans = 'N'; f77_char diag = 'N'; f77_int mm = bli_obj_length( &c ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldc = bli_obj_col_stride( &c ); double* alphap = bli_obj_buffer( &alpha ); double* ap = bli_obj_buffer( &a ); double* cp = bli_obj_buffer( &c ); dtrsm_( &side, &uplo, &trans, &diag, &mm, &nn, alphap, ap, &lda, cp, &ldc ); } #endif #if NBLAS >= 7 { f77_char transa = 'N'; f77_char transb = 'N'; f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); dcomplex* alphap = bli_obj_buffer( &alpha ); dcomplex* ap = bli_obj_buffer( &a ); dcomplex* bp = bli_obj_buffer( &b ); dcomplex* betap = bli_obj_buffer( &beta ); dcomplex* cp = bli_obj_buffer( &c ); zgemm_( &transa, &transb, &mm, &nn, &kk, alphap, ap, &lda, bp, &ldb, betap, cp, &ldc ); } #endif #if NBLAS >= 8 { f77_char side = 'L'; f77_char uplo = 'L'; f77_int mm = bli_obj_length( &c ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); dcomplex* alphap = bli_obj_buffer( &alpha ); dcomplex* ap = bli_obj_buffer( &a ); dcomplex* bp = bli_obj_buffer( &b ); dcomplex* betap = bli_obj_buffer( &beta ); dcomplex* cp = bli_obj_buffer( &c ); zhemm_( &side, &uplo, &mm, &nn, alphap, ap, &lda, bp, &ldb, betap, cp, &ldc ); } #endif #if NBLAS >= 9 { f77_char uplo = 'L'; f77_char trans = 'N'; f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width( &a ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldc = bli_obj_col_stride( &c ); double* alphap = bli_obj_buffer( &alpha ); dcomplex* ap = bli_obj_buffer( &a ); double* betap = bli_obj_buffer( &beta ); dcomplex* cp = bli_obj_buffer( &c ); zherk_( &uplo, &trans, &mm, &kk, alphap, ap, &lda, betap, cp, &ldc ); } #endif #if NBLAS >= 10 { f77_char uplo = 'L'; f77_char trans = 'N'; f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width( &a ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); dcomplex* alphap = bli_obj_buffer( &alpha ); dcomplex* ap = bli_obj_buffer( &a ); dcomplex* bp = bli_obj_buffer( &b ); double* betap = bli_obj_buffer( &beta ); dcomplex* cp = bli_obj_buffer( &c ); zher2k_( &uplo, &trans, &mm, &kk, alphap, ap, &lda, bp, &ldb, betap, cp, &ldc ); } #endif #if NBLAS >= 11 { f77_char side = 'L'; f77_char uplo = 'L'; f77_char trans = 'N'; f77_char diag = 'N'; f77_int mm = bli_obj_length( &c ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldc = bli_obj_col_stride( &c ); dcomplex* alphap = bli_obj_buffer( &alpha ); dcomplex* ap = bli_obj_buffer( &a ); dcomplex* cp = bli_obj_buffer( &c ); ztrmm_( &side, &uplo, &trans, &diag, &mm, &nn, alphap, ap, &lda, cp, &ldc ); } #endif #if NBLAS >= 12 { f77_char side = 'L'; f77_char uplo = 'L'; f77_char trans = 'N'; f77_char diag = 'N'; f77_int mm = bli_obj_length( &c ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldc = bli_obj_col_stride( &c ); dcomplex* alphap = bli_obj_buffer( &alpha ); dcomplex* ap = bli_obj_buffer( &a ); dcomplex* cp = bli_obj_buffer( &c ); ztrsm_( &side, &uplo, &trans, &diag, &mm, &nn, alphap, ap, &lda, cp, &ldc ); } #endif #endif #ifdef NBLIS bli_obj_free( &x ); bli_obj_free( &y ); bli_obj_free( &alpha ); bli_obj_free( &beta ); bli_obj_free( &a ); bli_obj_free( &b ); bli_obj_free( &c ); #endif #ifdef NBLAS free( x.buffer ); free( y.buffer ); free( alpha.buffer ); free( beta.buffer ); free( a.buffer ); free( b.buffer ); free( c.buffer ); #endif } #ifdef NBLIS //bli_finalize(); #endif return 0; } blis-0.9.0/test/mixeddt/000077500000000000000000000000001422157504600150745ustar00rootroot00000000000000blis-0.9.0/test/mixeddt/Makefile000066400000000000000000000244071422157504600165430ustar00rootroot00000000000000#!/bin/bash # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2014, The University of Texas at Austin # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # # # Makefile # # Field G. Van Zee # # Makefile for standalone BLIS test drivers. # # # --- Makefile PHONY target definitions ---------------------------------------- # .PHONY: all all-st all-mt \ blis blis-st blis-mt \ blis-nat blis-nat-st blis-nat-mt \ openblas openblas-st openblas-mt \ mkl mkl-st mkl-mt \ blis-gemm-st blis-gemm-mt \ blis-gemm-nat-st blis-gemm-nat-mt \ openblas-gemm-st openblas-gemm-mt \ mkl-gemm-st mkl-gemm-mt \ clean cleanx # # --- Determine makefile fragment location ------------------------------------- # # Comments: # - DIST_PATH is assumed to not exist if BLIS_INSTALL_PATH is given. # - We must use recursively expanded assignment for LIB_PATH and INC_PATH in # the second case because CONFIG_NAME is not yet set. ifneq ($(strip $(BLIS_INSTALL_PATH)),) LIB_PATH := $(BLIS_INSTALL_PATH)/lib INC_PATH := $(BLIS_INSTALL_PATH)/include/blis SHARE_PATH := $(BLIS_INSTALL_PATH)/share/blis else DIST_PATH := ../.. LIB_PATH = ../../lib/$(CONFIG_NAME) INC_PATH = ../../include/$(CONFIG_NAME) SHARE_PATH := ../.. endif # # --- Include common makefile definitions -------------------------------------- # # Include the common makefile fragment. -include $(SHARE_PATH)/common.mk # # --- BLAS and LAPACK implementations ------------------------------------------ # # BLIS library and header path. This is simply wherever it was installed. #BLIS_LIB_PATH := $(INSTALL_PREFIX)/lib #BLIS_INC_PATH := $(INSTALL_PREFIX)/include/blis # BLIS library. #BLIS_LIB := $(BLIS_LIB_PATH)/libblis.a # BLAS library path(s). This is where the BLAS libraries reside. HOME_LIB_PATH := $(HOME)/flame/lib # # --- General build definitions ------------------------------------------------ # TEST_SRC_PATH := . TEST_OBJ_PATH := . # Gather all local object files. TEST_OBJS := $(sort $(patsubst $(TEST_SRC_PATH)/%.c, \ $(TEST_OBJ_PATH)/%.o, \ $(wildcard $(TEST_SRC_PATH)/*.c))) # Override the value of CINCFLAGS so that the value of CFLAGS returned by # get-frame-cflags-for() is not cluttered up with include paths needed only # while building BLIS. CINCFLAGS := -I$(INC_PATH) # Use the "framework" CFLAGS for the configuration family. CFLAGS := $(call get-user-cflags-for,$(CONFIG_NAME)) # Add local header paths to CFLAGS. CFLAGS += -I$(TEST_SRC_PATH) # Locate the libblis library to which we will link. #LIBBLIS_LINK := $(LIB_PATH)/$(LIBBLIS_L) # Which library? BLI_DEF := -DBLIS BLA_DEF := -DBLAS # Single or multithreaded string STR_ST := -DTHR_STR=\"st\" STR_MT := -DTHR_STR=\"mt\" # Problem size specification PDEF_ST := -DP_BEGIN=40 \ -DP_MAX=2000 \ -DP_INC=40 PDEF_MT := -DP_BEGIN=160 \ -DP_MAX=8000 \ -DP_INC=160 # Enumerate possible datatypes and computation precisions. dts := s d c z prs := s d # Various functions that help us construct the datatype combinations and then # extract the needed datatype strings and C preprocessor define flags. get-char-c = $(word 1,$(subst _, ,$(1))) get-char-a = $(word 2,$(subst _, ,$(1))) get-char-b = $(word 3,$(subst _, ,$(1))) get-char-x = $(word 4,$(subst _, ,$(1))) get-cstr = $(call get-char-c,$(1))$(call get-char-a,$(1))$(call get-char-b,$(1))$(call get-char-x,$(1)) get-cdef-a = $(strip $(subst s,-DDTA=BLIS_FLOAT, \ $(subst d,-DDTA=BLIS_DOUBLE, \ $(subst c,-DDTA=BLIS_SCOMPLEX, \ $(subst z,-DDTA=BLIS_DCOMPLEX,$(call get-char-a,$(1))))))) get-cdef-b = $(strip $(subst s,-DDTB=BLIS_FLOAT, \ $(subst d,-DDTB=BLIS_DOUBLE, \ $(subst c,-DDTB=BLIS_SCOMPLEX, \ $(subst z,-DDTB=BLIS_DCOMPLEX,$(call get-char-b,$(1))))))) get-cdef-c = $(strip $(subst s,-DDTC=BLIS_FLOAT, \ $(subst d,-DDTC=BLIS_DOUBLE, \ $(subst c,-DDTC=BLIS_SCOMPLEX, \ $(subst z,-DDTC=BLIS_DCOMPLEX,$(call get-char-c,$(1))))))) get-cdef-x = $(strip $(subst s,-DDTX=BLIS_FLOAT, \ $(subst d,-DDTX=BLIS_DOUBLE,$(call get-char-x,$(1))))) get-cdefs = $(call get-cdef-c,$(1)) $(call get-cdef-a,$(1)) $(call get-cdef-b,$(1)) $(call get-cdef-x,$(1)) # Define a function to return the appropriate -DSTR= and -D[BLIS|BLAS] flags. get-idefs = $(strip $(subst intern,-DSTR=\"$(1)\" -DBLIS, \ $(subst ad_hoc,-DSTR=\"$(1)\" -DBLAS, \ $(subst mkl,-DSTR=\"$(1)\" -DBLAS,$(1))))) # Enumerate all possible datatype combinations. DT_CODES := $(foreach dt0,$(dts),$(foreach dt1,$(dts),$(foreach dt2,$(dts),$(foreach pr,$(prs),$(dt0)_$(dt1)_$(dt2)_$(pr))))) # Build a list of the datatype strings. DT_COMBOS := $(foreach code,$(DT_CODES),$(call get-cstr,$(code))) # Build a list of BLIS, OpenBLAS, and MKL executables. INTERN_OBJS_ST := $(foreach combo,$(DT_COMBOS),test_$(combo)gemm_intern_st.o) INTERN_BINS_ST := $(patsubst %.o,%.x,$(INTERN_OBJS_ST)) AD_HOC_OBJS_ST := $(foreach combo,$(DT_COMBOS),test_$(combo)gemm_ad_hoc_st.o) AD_HOC_BINS_ST := $(patsubst %.o,%.x,$(AD_HOC_OBJS_ST)) INTERN_OBJS_MT := $(foreach combo,$(DT_COMBOS),test_$(combo)gemm_intern_mt.o) INTERN_BINS_MT := $(patsubst %.o,%.x,$(INTERN_OBJS_MT)) AD_HOC_OBJS_MT := $(foreach combo,$(DT_COMBOS),test_$(combo)gemm_ad_hoc_mt.o) AD_HOC_BINS_MT := $(patsubst %.o,%.x,$(AD_HOC_OBJS_MT)) # # --- Targets/rules ------------------------------------------------------------ # all: st st: intern-st ad_hoc-st mt: intern-mt ad_hoc-mt intern-st: $(INTERN_BINS_ST) ad_hoc-st: $(AD_HOC_BINS_ST) intern-mt: $(INTERN_BINS_MT) ad_hoc-mt: $(AD_HOC_BINS_MT) #blis: test_ssssgemm_asm_blis_st.x \ # test_sssdgemm_asm_blis_st.x \ # test_ssdsgemm_asm_blis_st.x \ # test_sdssgemm_asm_blis_st.x \ # test_dsssgemm_asm_blis_st.x \ # test_dddsgemm_asm_blis_st.x \ # test_ddddgemm_asm_blis_st.x # --Object file rules -- # Define the function that will be used to instantiate compilation rules # for the various implementations. define make-st-rule test_$(call get-cstr,$(1))gemm_$(2)_st.o: test_gemm.c Makefile ifeq ($(ENABLE_VERBOSE),yes) $(CC) $(CFLAGS) $(PDEF_ST) $(call get-cdefs,$(1)) $(call get-idefs,$(2)) $(STR_ST) -c $$< -o $$@ else @echo "Compiling $$@" @$(CC) $(CFLAGS) $(PDEF_ST) $(call get-cdefs,$(1)) $(call get-idefs,$(2)) $(STR_ST) -c $$< -o $$@ endif endef define make-mt-rule test_$(call get-cstr,$(1))gemm_$(2)_mt.o: test_gemm.c Makefile ifeq ($(ENABLE_VERBOSE),yes) $(CC) $(CFLAGS) $(PDEF_MT) $(call get-cdefs,$(1)) $(call get-idefs,$(2)) $(STR_MT) -c $$< -o $$@ else @echo "Compiling $$@" @$(CC) $(CFLAGS) $(PDEF_MT) $(call get-cdefs,$(1)) $(call get-idefs,$(2)) $(STR_MT) -c $$< -o $$@ endif endef # Define the implementations for which we will instantiate compilation rules. IMPLS := intern ad_hoc # Instantiate the rule function make-st-rule() and make-mt-rule for each # implementation in IMPLS and each of the datatype "codes" in DT_CODES. $(foreach impl,$(IMPLS), \ $(foreach code,$(DT_CODES),$(eval $(call make-st-rule,$(code),$(impl))))) $(foreach impl,$(IMPLS), \ $(foreach code,$(DT_CODES),$(eval $(call make-mt-rule,$(code),$(impl))))) # -- Executable file rules -- # NOTE: For the BLAS test drivers, we place the BLAS libraries before BLIS # on the link command line in case BLIS was configured with the BLAS # compatibility layer. This prevents BLIS from inadvertently getting called # for the BLAS routines we are trying to test with. test_%_ad_hoc_st.x: test_%_ad_hoc_st.o $(LIBBLIS_LINK) ifeq ($(ENABLE_VERBOSE),yes) $(LINKER) $< $(LIBBLIS_LINK) $(LDFLAGS) -o $@ $(RM_F) $< else @@echo "Linking $@ to '$(LIBBLIS_LINK)'" @$(LINKER) $< $(LIBBLIS_LINK) $(LDFLAGS) -o $@ @$(RM_F) $< endif test_%_ad_hoc_mt.x: test_%_ad_hoc_mt.o $(LIBBLIS_LINK) ifeq ($(ENABLE_VERBOSE),yes) $(LINKER) $< $(LIBBLIS_LINK) $(LDFLAGS) -o $@ $(RM_F) $< else @@echo "Linking $@ to '$(LIBBLIS_LINK)'" @$(LINKER) $< $(LIBBLIS_LINK) $(LDFLAGS) -o $@ @$(RM_F) $< endif test_%_intern_st.x: test_%_intern_st.o $(LIBBLIS_LINK) ifeq ($(ENABLE_VERBOSE),yes) $(LINKER) $< $(LIBBLIS_LINK) $(LDFLAGS) -o $@ $(RM_F) $< else @@echo "Linking $@ to '$(LIBBLIS_LINK)'" @$(LINKER) $< $(LIBBLIS_LINK) $(LDFLAGS) -o $@ @$(RM_F) $< endif test_%_intern_mt.x: test_%_intern_mt.o $(LIBBLIS_LINK) ifeq ($(ENABLE_VERBOSE),yes) $(LINKER) $< $(LIBBLIS_LINK) $(LDFLAGS) -o $@ $(RM_F) $< else @@echo "Linking $@ to '$(LIBBLIS_LINK)'" @$(LINKER) $< $(LIBBLIS_LINK) $(LDFLAGS) -o $@ @$(RM_F) $< endif # -- Clean rules -- clean: cleanx cleanx: - $(RM_F) *.o *.x cleanout: - $(RM_F) *.m blis-0.9.0/test/mixeddt/matlab/000077500000000000000000000000001422157504600163345ustar00rootroot00000000000000blis-0.9.0/test/mixeddt/matlab/gen_dt_combos.m000066400000000000000000000101531422157504600213140ustar00rootroot00000000000000function r_val = gen_dt_combos() dt_chars = [ 's' 'd' 'c' 'z' ]; pr_chars = [ 's' 'd' ]; if 0 i = 1; for dtc = dt_chars for dta = dt_chars for dtb = dt_chars for pr = pr_chars dt_combos( i, : ) = sprintf( '%c%c%c%c', dtc, dta, dtb, pr ); i = i + 1; end end end end end %n_combos = size(temp,1); if 1 dt_combos( 1, : ) = 'ssss'; dt_combos( 2, : ) = 'ssds'; dt_combos( 3, : ) = 'sscs'; dt_combos( 4, : ) = 'sszs'; dt_combos( 5, : ) = 'sdss'; dt_combos( 6, : ) = 'sdds'; dt_combos( 7, : ) = 'sdcs'; dt_combos( 8, : ) = 'sdzs'; dt_combos( 9, : ) = 'sssd'; dt_combos( 10, : ) = 'ssdd'; dt_combos( 11, : ) = 'sscd'; dt_combos( 12, : ) = 'sszd'; dt_combos( 13, : ) = 'sdsd'; dt_combos( 14, : ) = 'sddd'; dt_combos( 15, : ) = 'sdcd'; dt_combos( 16, : ) = 'sdzd'; dt_combos( 17, : ) = 'scss'; dt_combos( 18, : ) = 'scds'; dt_combos( 19, : ) = 'sccs'; dt_combos( 20, : ) = 'sczs'; dt_combos( 21, : ) = 'szss'; dt_combos( 22, : ) = 'szds'; dt_combos( 23, : ) = 'szcs'; dt_combos( 24, : ) = 'szzs'; dt_combos( 25, : ) = 'scsd'; dt_combos( 26, : ) = 'scdd'; dt_combos( 27, : ) = 'sccd'; dt_combos( 28, : ) = 'sczd'; dt_combos( 29, : ) = 'szsd'; dt_combos( 30, : ) = 'szdd'; dt_combos( 31, : ) = 'szcd'; dt_combos( 32, : ) = 'szzd'; dt_combos( 33, : ) = 'dsss'; dt_combos( 34, : ) = 'dsds'; dt_combos( 35, : ) = 'dscs'; dt_combos( 36, : ) = 'dszs'; dt_combos( 37, : ) = 'ddss'; dt_combos( 38, : ) = 'ddds'; dt_combos( 39, : ) = 'ddcs'; dt_combos( 40, : ) = 'ddzs'; dt_combos( 41, : ) = 'dssd'; dt_combos( 42, : ) = 'dsdd'; dt_combos( 43, : ) = 'dscd'; dt_combos( 44, : ) = 'dszd'; dt_combos( 45, : ) = 'ddsd'; dt_combos( 46, : ) = 'dddd'; dt_combos( 47, : ) = 'ddcd'; dt_combos( 48, : ) = 'ddzd'; dt_combos( 49, : ) = 'dcss'; dt_combos( 50, : ) = 'dcds'; dt_combos( 51, : ) = 'dccs'; dt_combos( 52, : ) = 'dczs'; dt_combos( 53, : ) = 'dzss'; dt_combos( 54, : ) = 'dzds'; dt_combos( 55, : ) = 'dzcs'; dt_combos( 56, : ) = 'dzzs'; dt_combos( 57, : ) = 'dcsd'; dt_combos( 58, : ) = 'dcdd'; dt_combos( 59, : ) = 'dccd'; dt_combos( 60, : ) = 'dczd'; dt_combos( 61, : ) = 'dzsd'; dt_combos( 62, : ) = 'dzdd'; dt_combos( 63, : ) = 'dzcd'; dt_combos( 64, : ) = 'dzzd'; dt_combos( 65, : ) = 'csss'; dt_combos( 66, : ) = 'csds'; dt_combos( 67, : ) = 'cscs'; dt_combos( 68, : ) = 'cszs'; dt_combos( 69, : ) = 'cdss'; dt_combos( 70, : ) = 'cdds'; dt_combos( 71, : ) = 'cdcs'; dt_combos( 72, : ) = 'cdzs'; dt_combos( 73, : ) = 'cssd'; dt_combos( 74, : ) = 'csdd'; dt_combos( 75, : ) = 'cscd'; dt_combos( 76, : ) = 'cszd'; dt_combos( 77, : ) = 'cdsd'; dt_combos( 78, : ) = 'cddd'; dt_combos( 79, : ) = 'cdcd'; dt_combos( 80, : ) = 'cdzd'; dt_combos( 81, : ) = 'ccss'; dt_combos( 82, : ) = 'ccds'; dt_combos( 83, : ) = 'cccs'; dt_combos( 84, : ) = 'cczs'; dt_combos( 85, : ) = 'czss'; dt_combos( 86, : ) = 'czds'; dt_combos( 87, : ) = 'czcs'; dt_combos( 88, : ) = 'czzs'; dt_combos( 89, : ) = 'ccsd'; dt_combos( 90, : ) = 'ccdd'; dt_combos( 91, : ) = 'cccd'; dt_combos( 92, : ) = 'cczd'; dt_combos( 93, : ) = 'czsd'; dt_combos( 94, : ) = 'czdd'; dt_combos( 95, : ) = 'czcd'; dt_combos( 96, : ) = 'czzd'; dt_combos( 97, : ) = 'zsss'; dt_combos( 98, : ) = 'zsds'; dt_combos( 99, : ) = 'zscs'; dt_combos( 100, : ) = 'zszs'; dt_combos( 101, : ) = 'zdss'; dt_combos( 102, : ) = 'zdds'; dt_combos( 103, : ) = 'zdcs'; dt_combos( 104, : ) = 'zdzs'; dt_combos( 105, : ) = 'zssd'; dt_combos( 106, : ) = 'zsdd'; dt_combos( 107, : ) = 'zscd'; dt_combos( 108, : ) = 'zszd'; dt_combos( 109, : ) = 'zdsd'; dt_combos( 110, : ) = 'zddd'; dt_combos( 111, : ) = 'zdcd'; dt_combos( 112, : ) = 'zdzd'; dt_combos( 113, : ) = 'zcss'; dt_combos( 114, : ) = 'zcds'; dt_combos( 115, : ) = 'zccs'; dt_combos( 116, : ) = 'zczs'; dt_combos( 117, : ) = 'zzss'; dt_combos( 118, : ) = 'zzds'; dt_combos( 119, : ) = 'zzcs'; dt_combos( 120, : ) = 'zzzs'; dt_combos( 121, : ) = 'zcsd'; dt_combos( 122, : ) = 'zcdd'; dt_combos( 123, : ) = 'zccd'; dt_combos( 124, : ) = 'zczd'; dt_combos( 125, : ) = 'zzsd'; dt_combos( 126, : ) = 'zzdd'; dt_combos( 127, : ) = 'zzcd'; dt_combos( 128, : ) = 'zzzd'; end r_val = dt_combos; end blis-0.9.0/test/mixeddt/matlab/gen_prec_combos.m000066400000000000000000000041171422157504600216410ustar00rootroot00000000000000function r_val = gen_prec_combos( mdcase ) dt_chars = [ 's' 'd' 'c' 'z' ]; pr_chars = [ 's' 'd' ]; dm_chars = [ 'r' 'c' ]; dmc = mdcase( 1 ); dma = mdcase( 2 ); dmb = mdcase( 3 ); if 0 pr_combos( 1, : ) = 'ssss'; pr_combos( 2, : ) = 'ssds'; pr_combos( 3, : ) = 'sdss'; pr_combos( 4, : ) = 'sdds'; pr_combos( 5, : ) = 'dsss'; pr_combos( 6, : ) = 'dsds'; pr_combos( 7, : ) = 'ddss'; pr_combos( 8, : ) = 'ddds'; pr_combos( 9, : ) = 'dddd'; pr_combos( 10, : ) = 'ddsd'; pr_combos( 11, : ) = 'dsdd'; pr_combos( 12, : ) = 'dssd'; pr_combos( 13, : ) = 'sddd'; pr_combos( 14, : ) = 'sdsd'; pr_combos( 15, : ) = 'ssdd'; pr_combos( 16, : ) = 'sssd'; end pr_combos( 1, : ) = 'ssss'; pr_combos( 2, : ) = 'ssds'; pr_combos( 3, : ) = 'dddd'; pr_combos( 4, : ) = 'ddsd'; pr_combos( 5, : ) = 'sdss'; pr_combos( 6, : ) = 'sdds'; pr_combos( 7, : ) = 'dsdd'; pr_combos( 8, : ) = 'dssd'; pr_combos( 9, : ) = 'dsss'; pr_combos( 10, : ) = 'dsds'; pr_combos( 11, : ) = 'sddd'; pr_combos( 12, : ) = 'sdsd'; pr_combos( 13, : ) = 'ddss'; pr_combos( 14, : ) = 'ddds'; pr_combos( 15, : ) = 'ssdd'; pr_combos( 16, : ) = 'sssd'; for i = 1:16 pr_combo = pr_combos( i, : ); %str = sprintf( '%s', pr_combo ); disp(str); prc = pr_combo( 1 ); pra = pr_combo( 2 ); prb = pr_combo( 3 ); pr = pr_combo( 4 ); dtc = prec_dom_to_dt( prc, dmc ); dta = prec_dom_to_dt( pra, dma ); dtb = prec_dom_to_dt( prb, dmb ); dt_combos( i, : ) = sprintf( '%c%c%c%c', dtc, dta, dtb, pr ); end %if 0 %i = 1; %pr = 's'; %for prc = pr_chars % for pra = pr_chars % for prb = pr_chars % dtc = prec_dom_to_dt( prc, dmc ); % dta = prec_dom_to_dt( pra, dma ); % dtb = prec_dom_to_dt( prb, dmb ); % dt_combos( i, : ) = sprintf( '%c%c%c%c', dtc, dta, dtb, pr ); % i = i + 1; % end % end %end % %pr = 'd'; %for prc = flip( pr_chars ) % for pra = flip( pr_chars ) % for prb = flip( pr_chars ) % dtc = prec_dom_to_dt( prc, dmc ); % dta = prec_dom_to_dt( pra, dma ); % dtb = prec_dom_to_dt( prb, dmb ); % dt_combos( i, : ) = sprintf( '%c%c%c%c', dtc, dta, dtb, pr ); % i = i + 1; % end % end %end %end r_val = dt_combos; end blis-0.9.0/test/mixeddt/matlab/output/000077500000000000000000000000001422157504600176745ustar00rootroot00000000000000blis-0.9.0/test/mixeddt/matlab/output/.gitkeep000066400000000000000000000000001422157504600213130ustar00rootroot00000000000000blis-0.9.0/test/mixeddt/matlab/plot_all.m000066400000000000000000000030221422157504600203150ustar00rootroot00000000000000 % skx plot_dom_all(2.0,32,1,'../../skx/st', '../../skx/st_noxmem', '../../skx/st_merged', 'skx_t1');close all;clear all plot_dom_all(2.0,32,26,'../../skx/jc2ic13','../../skx/jc2ic13_noxmem','../../skx/jc2ic13_merged','skx_t26');close all;clear all plot_dom_all(2.0,32,52,'../../skx/jc4ic13','../../skx/jc4ic13_noxmem','../../skx/jc4ic13_merged','skx_t52');close all;clear all plot_dt_select(2.0,32,1,'../../skx/st', '../../skx/st_noxmem', '../../skx/st_merged', 'skx_t1');close all;clear all plot_dt_select(2.0,32,26,'../../skx/jc2ic13','../../skx/jc2ic13_noxmem','../../skx/jc2ic13_merged','skx_t26');close all;clear all plot_dt_select(2.0,32,52,'../../skx/jc4ic13','../../skx/jc4ic13_noxmem','../../skx/jc4ic13_merged','skx_t52');close all;clear all % tx2 plot_dom_all(2.2,8,1,'../../tx2/st', '../../tx2/st_noxmem', '../../tx2/st_merged', 'tx2_t1');close all;clear all plot_dom_all(2.2,8,28,'../../tx2/jc4ic7','../../tx2/jc4ic7_noxmem','../../tx2/jc4ic7_merged','tx2_t28');close all;clear all plot_dom_all(2.2,8,56,'../../tx2/jc8ic7','../../tx2/jc8ic7_noxmem','../../tx2/jc8ic7_merged','tx2_t56');close all;clear all plot_dt_select(2.2,8,1,'../../tx2/st', '../../tx2/st_noxmem', '../../tx2/st_merged', 'tx2_t1');close all;clear all plot_dt_select(2.2,8,28,'../../tx2/jc4ic7','../../tx2/jc4ic7_noxmem','../../tx2/jc4ic7_merged','tx2_t28');close all;clear all plot_dt_select(2.2,8,56,'../../tx2/jc8ic7','../../tx2/jc8ic7_noxmem','../../tx2/jc8ic7_merged','tx2_t56');close all;clear all blis-0.9.0/test/mixeddt/matlab/plot_dom_all.m000066400000000000000000000014211422157504600211550ustar00rootroot00000000000000function r_val = plot_dom_all( cfreq, ... dflopspercycle, ... nth, ... dirpath, ... dirpath_out, ... arch_str ) cases( 1, : ) = [ 'rrr' ]; cases( 2, : ) = [ 'rrc' ]; cases( 3, : ) = [ 'rcr' ]; cases( 4, : ) = [ 'rcc' ]; cases( 5, : ) = [ 'crr' ]; cases( 6, : ) = [ 'crc' ]; cases( 7, : ) = [ 'ccr' ]; cases( 8, : ) = [ 'ccc' ]; n_cases = size(cases,1); for i = 1:n_cases thecase = cases( i, : ); plot_dom_case( thecase, ... cfreq, ... dflopspercycle, ... nth, ... dirpath, ... dirpath_out, ... arch_str ); end r_val = 0; end blis-0.9.0/test/mixeddt/matlab/plot_dom_case.m000066400000000000000000000104351422157504600213250ustar00rootroot00000000000000function r_val = plot_dom_case( mdcase, ... cfreq, ... dflopspercycle, ... nth, ... dirpath, ... dirpath_out, ... arch_str ) % Create filename "templates" for the files that contain the performance % results. filetemp_intern = '%s/output_%s_%sgemm_intern.m'; filetemp_ad_hoc = '%s/output_%s_%sgemm_ad_hoc.m'; if nth == 1 thr_str = 'st'; else thr_str = 'mt'; end if 1 dt_combos = gen_prec_combos( mdcase ); else dt_combos( 1, : ) = [ 'ssss' ]; dt_combos( 2, : ) = [ 'sssd' ]; dt_combos( 3, : ) = [ 'ssds' ]; dt_combos( 4, : ) = [ 'sdss' ]; dt_combos( 5, : ) = [ 'dsss' ]; dt_combos( 6, : ) = [ 'ddds' ]; dt_combos( 7, : ) = [ 'dddd' ]; end n_combos = size(dt_combos,1); % Construct filenames for the "reference" (single real) data, then load % the data files, and finally save the results to different variable names. file_blis_sref = sprintf( filetemp_intern, dirpath, thr_str, 'ssss' ); run( file_blis_sref ) data_gemm_intern_sref( :, : ) = data_gemm_intern( :, : ); % Construct filenames for the "reference" (double real) data, then load % the data files, and finally save the results to different variable names. file_blis_dref = sprintf( filetemp_intern, dirpath, thr_str, 'dddd' ); run( file_blis_dref ) data_gemm_intern_dref( :, : ) = data_gemm_intern( :, : ); % Construct filenames for the "reference" (single complex) data, then load % the data files, and finally save the results to different variable names. file_blis_cref = sprintf( filetemp_intern, dirpath, thr_str, 'cccs' ); run( file_blis_cref ) data_gemm_intern_cref( :, : ) = data_gemm_intern( :, : ); % Construct filenames for the "reference" (double complex) data, then load % the data files, and finally save the results to different variable names. file_blis_zref = sprintf( filetemp_intern, dirpath, thr_str, 'zzzd' ); run( file_blis_zref ) data_gemm_intern_zref( :, : ) = data_gemm_intern( :, : ); fig = figure; orient( fig, 'portrait' ); %set(gcf,'Position',[0 0 2000 900]); set(gcf,'PaperUnits', 'inches'); %set(gcf,'PaperSize', [16 12.4]); %set(gcf,'PaperPosition', [0 0 16 12.4]); set(gcf,'PaperSize', [14 11.0]); set(gcf,'PaperPosition', [0 0 14 11.0]); %set(gcf,'PaperPositionMode','auto'); set(gcf,'PaperPositionMode','manual'); set(gcf,'PaperOrientation','portrait'); for dti = 1:n_combos %for dti = 1:1 % Grab the current datatype combination. combo = dt_combos( dti, : ); %str = sprintf( 'Plotting %d: %s', dti, combo ); disp(str); fprintf( '%d (%s) ', dti, combo ); if combo(4) == 's' data_gemm_ref( :, : ) = data_gemm_intern_sref( :, : ); refch = 's'; else %if combo(4) == 'd' data_gemm_ref( :, : ) = data_gemm_intern_dref( :, : ); refch = 'd'; end if ( combo(1) == 'c' || combo(1) == 'z' ) && ... ( combo(2) == 'c' || combo(2) == 'z' ) && ... ( combo(3) == 'c' || combo(3) == 'z' ) if combo(4) == 's' data_gemm_ref( :, : ) = data_gemm_intern_cref( :, : ); refch = 'c'; else %if combo(4) == 'd' data_gemm_ref( :, : ) = data_gemm_intern_zref( :, : ); refch = 'z'; end end % Construct filenames for the data files from templates. file_intern = sprintf( filetemp_intern, dirpath, thr_str, combo ); file_ad_hoc = sprintf( filetemp_ad_hoc, dirpath, thr_str, combo ); % Load the data files. %str = sprintf( ' Loading %s', file_intern ); disp(str); run( file_intern ) %str = sprintf( ' Loading %s', file_ad_hoc ); disp(str); run( file_ad_hoc ) % Plot the result. plot_gemm_perf( combo, ... data_gemm_ref, ... data_gemm_intern, ... data_gemm_ad_hoc, ... refch, ... nth, ... 4, 4, ... cfreq, ... dflopspercycle, ... dti ); end fprintf( '\n' ); %if 0 %set(gcf,'Position',[0 0 2000 900]); %set(gcf,'PaperUnits', 'inches'); %set(gcf,'PaperSize', [48 22]); %set(gcf,'PaperPosition', [0 0 48 22]); %%set(gcf,'PaperPositionMode','auto'); %set(gcf,'PaperPositionMode','manual'); %set(gcf,'PaperOrientation','landscape'); %end outfile = sprintf( '%s/gemm_%s_%s', dirpath_out, mdcase, arch_str ); print(gcf, outfile,'-bestfit','-dpdf'); %print(gcf, 'gemm_md','-fillpage','-dpdf'); blis-0.9.0/test/mixeddt/matlab/plot_dt_all.m000066400000000000000000000117141422157504600210130ustar00rootroot00000000000000function r_val = plot_dt_all( is_mt ) if is_mt == 1 thr_str = 'mt'; else thr_str = 'st'; end if 1 dt_combos = gen_dt_combos(); else dt_combos( 1, : ) = [ 'ssss' ]; dt_combos( 2, : ) = [ 'sssd' ]; dt_combos( 3, : ) = [ 'ssds' ]; dt_combos( 4, : ) = [ 'sdss' ]; dt_combos( 5, : ) = [ 'dsss' ]; dt_combos( 6, : ) = [ 'ddds' ]; dt_combos( 7, : ) = [ 'dddd' ]; end n_combos = size(dt_combos,1); filetemp_blis = '../output_%s_%sgemm_asm_blis.m'; filetemp_open = '../output_%s_%sgemm_openblas.m'; % Construct filenames for the "reference" (single real) data, then load % the data files, and finally save the results to different variable names. file_blis_sref = sprintf( filetemp_blis, thr_str, 'ssss' ); file_open_sref = sprintf( filetemp_open, thr_str, 'ssss' ); %str = sprintf( ' Loading %s', file_blis_sref ); disp(str); run( file_blis_sref ) %str = sprintf( ' Loading %s', file_open_sref ); disp(str); run( file_open_sref ) data_gemm_asm_blis_sref( :, : ) = data_gemm_asm_blis( :, : ); data_gemm_openblas_sref( :, : ) = data_gemm_openblas( :, : ); % Construct filenames for the "reference" (double real) data, then load % the data files, and finally save the results to different variable names. file_blis_dref = sprintf( filetemp_blis, thr_str, 'dddd' ); file_open_dref = sprintf( filetemp_open, thr_str, 'dddd' ); %str = sprintf( ' Loading %s', file_blis_dref ); disp(str); run( file_blis_dref ) %str = sprintf( ' Loading %s', file_open_dref ); disp(str); run( file_open_dref ) data_gemm_asm_blis_dref( :, : ) = data_gemm_asm_blis( :, : ); data_gemm_openblas_dref( :, : ) = data_gemm_openblas( :, : ); % Construct filenames for the "reference" (single complex) data, then load % the data files, and finally save the results to different variable names. file_blis_cref = sprintf( filetemp_blis, thr_str, 'cccs' ); file_open_cref = sprintf( filetemp_open, thr_str, 'cccs' ); %str = sprintf( ' Loading %s', file_blis_cref ); disp(str); run( file_blis_cref ) %str = sprintf( ' Loading %s', file_open_cref ); disp(str); run( file_open_cref ) data_gemm_asm_blis_cref( :, : ) = data_gemm_asm_blis( :, : ); data_gemm_openblas_cref( :, : ) = data_gemm_openblas( :, : ); % Construct filenames for the "reference" (double complex) data, then load % the data files, and finally save the results to different variable names. file_blis_zref = sprintf( filetemp_blis, thr_str, 'zzzd' ); file_open_zref = sprintf( filetemp_open, thr_str, 'zzzd' ); %str = sprintf( ' Loading %s', file_blis_zref ); disp(str); run( file_blis_zref ) %str = sprintf( ' Loading %s', file_open_zref ); disp(str); run( file_open_zref ) data_gemm_asm_blis_zref( :, : ) = data_gemm_asm_blis( :, : ); data_gemm_openblas_zref( :, : ) = data_gemm_openblas( :, : ); fig = figure; orient( fig, 'landscape' ); set(gcf,'Position',[0 0 2000 900]); set(gcf,'PaperUnits', 'inches'); set(gcf,'PaperSize', [64 33]); set(gcf,'PaperPosition', [0 0 64 33]); %set(gcf,'PaperPositionMode','auto'); set(gcf,'PaperPositionMode','manual'); set(gcf,'PaperOrientation','landscape'); for dti = 1:n_combos %for dti = 1:1 % Grab the current datatype combination. combo = dt_combos( dti, : ); str = sprintf( 'Plotting %d: %s', dti, combo ); disp(str); if combo(4) == 's' data_gemm_asm_blis_ref( :, : ) = data_gemm_asm_blis_sref( :, : ); data_gemm_openblas_ref( :, : ) = data_gemm_openblas_sref( :, : ); refch = 's'; else %if combo(4) == 'd' data_gemm_asm_blis_ref( :, : ) = data_gemm_asm_blis_dref( :, : ); data_gemm_openblas_ref( :, : ) = data_gemm_openblas_dref( :, : ); refch = 'd'; end if ( combo(1) == 'c' || combo(1) == 'z' ) && ... ( combo(2) == 'c' || combo(2) == 'z' ) && ... ( combo(3) == 'c' || combo(3) == 'z' ) if combo(4) == 's' data_gemm_asm_blis_ref( :, : ) = data_gemm_asm_blis_cref( :, : ); data_gemm_openblas_ref( :, : ) = data_gemm_openblas_cref( :, : ); refch = 'c'; else %if combo(4) == 'd' data_gemm_asm_blis_ref( :, : ) = data_gemm_asm_blis_zref( :, : ); data_gemm_openblas_ref( :, : ) = data_gemm_openblas_zref( :, : ); refch = 'z'; end end % Construct filenames for the data files from templates. file_blis = sprintf( filetemp_blis, thr_str, combo ); file_open = sprintf( filetemp_open, thr_str, combo ); % Load the data files. %str = sprintf( ' Loading %s', file_blis ); disp(str); run( file_blis ) %str = sprintf( ' Loading %s', file_open ); disp(str); run( file_open ) % Plot the result. plot_gemm_perf( combo, ... data_gemm_asm_blis, ... data_gemm_asm_blis_ref, ... data_gemm_openblas, ... data_gemm_openblas_ref, ... is_mt, refch, 8, 16, dti ); end if 0 set(gcf,'Position',[0 0 2000 900]); set(gcf,'PaperUnits', 'inches'); set(gcf,'PaperSize', [48 22]); set(gcf,'PaperPosition', [0 0 48 22]); %set(gcf,'PaperPositionMode','auto'); set(gcf,'PaperPositionMode','manual'); set(gcf,'PaperOrientation','landscape'); end print(gcf, 'output/gemm_md','-bestfit','-dpdf'); %print(gcf, 'gemm_md','-fillpage','-dpdf'); blis-0.9.0/test/mixeddt/matlab/plot_dt_select.m000066400000000000000000000114651422157504600215250ustar00rootroot00000000000000function r_val = plot_dt_select( dom, is_mt ) if is_mt == 1 thr_str = 'mt'; else thr_str = 'st'; end if dom == 'r' dt_combos( 1, : ) = [ 'dsss' ]; dt_combos( 2, : ) = [ 'sddd' ]; dt_combos( 3, : ) = [ 'sdds' ]; dt_combos( 4, : ) = [ 'dssd' ]; dt_combos( 5, : ) = [ 'ddds' ]; dt_combos( 6, : ) = [ 'sssd' ]; else dt_combos( 1, : ) = [ 'csss' ]; dt_combos( 2, : ) = [ 'zddd' ]; dt_combos( 3, : ) = [ 'ccss' ]; dt_combos( 4, : ) = [ 'zzdd' ]; dt_combos( 5, : ) = [ 'cscs' ]; dt_combos( 6, : ) = [ 'zdzd' ]; end n_combos = size(dt_combos,1); filetemp_blis = '../output_%s_%sgemm_asm_blis.m'; filetemp_open = '../output_%s_%sgemm_openblas.m'; % Construct filenames for the "reference" (single real) data, then load % the data files, and finally save the results to different variable names. file_blis_sref = sprintf( filetemp_blis, thr_str, 'ssss' ); file_open_sref = sprintf( filetemp_open, thr_str, 'ssss' ); run( file_blis_sref ) run( file_open_sref ) data_gemm_asm_blis_sref( :, : ) = data_gemm_asm_blis( :, : ); data_gemm_openblas_sref( :, : ) = data_gemm_openblas( :, : ); % Construct filenames for the "reference" (double real) data, then load % the data files, and finally save the results to different variable names. file_blis_dref = sprintf( filetemp_blis, thr_str, 'dddd' ); file_open_dref = sprintf( filetemp_open, thr_str, 'dddd' ); run( file_blis_dref ) run( file_open_dref ) data_gemm_asm_blis_dref( :, : ) = data_gemm_asm_blis( :, : ); data_gemm_openblas_dref( :, : ) = data_gemm_openblas( :, : ); % Construct filenames for the "reference" (single complex) data, then load % the data files, and finally save the results to different variable names. file_blis_cref = sprintf( filetemp_blis, thr_str, 'cccs' ); file_open_cref = sprintf( filetemp_open, thr_str, 'cccs' ); run( file_blis_cref ) run( file_open_cref ) data_gemm_asm_blis_cref( :, : ) = data_gemm_asm_blis( :, : ); data_gemm_openblas_cref( :, : ) = data_gemm_openblas( :, : ); % Construct filenames for the "reference" (double complex) data, then load % the data files, and finally save the results to different variable names. file_blis_zref = sprintf( filetemp_blis, thr_str, 'zzzd' ); file_open_zref = sprintf( filetemp_open, thr_str, 'zzzd' ); run( file_blis_zref ) run( file_open_zref ) data_gemm_asm_blis_zref( :, : ) = data_gemm_asm_blis( :, : ); data_gemm_openblas_zref( :, : ) = data_gemm_openblas( :, : ); %fig = figure; fig = figure('Position', [100, 100, 1024, 1300]); orient( fig, 'portrait' ); %set(gcf,'Position',[0 0 2000 900]); set(gcf,'PaperUnits', 'inches'); %set(gcf,'PaperSize', [16 12.4]); %set(gcf,'PaperPosition', [0 0 16 12.4]); set(gcf,'PaperSize', [9 11.0]); set(gcf,'PaperPosition', [0 0 9 11.0]); %set(gcf,'PaperPositionMode','auto'); set(gcf,'PaperPositionMode','manual'); set(gcf,'PaperOrientation','portrait'); for dti = 1:n_combos %for dti = 1:1 % Grab the current datatype combination. combo = dt_combos( dti, : ); str = sprintf( 'Plotting %d: %s', dti, combo ); disp(str); if combo(4) == 's' data_gemm_asm_blis_ref( :, : ) = data_gemm_asm_blis_sref( :, : ); data_gemm_openblas_ref( :, : ) = data_gemm_openblas_sref( :, : ); refch = 's'; else %if combo(4) == 'd' data_gemm_asm_blis_ref( :, : ) = data_gemm_asm_blis_dref( :, : ); data_gemm_openblas_ref( :, : ) = data_gemm_openblas_dref( :, : ); refch = 'd'; end if ( combo(1) == 'c' || combo(1) == 'z' ) && ... ( combo(2) == 'c' || combo(2) == 'z' ) && ... ( combo(3) == 'c' || combo(3) == 'z' ) if combo(4) == 's' data_gemm_asm_blis_ref( :, : ) = data_gemm_asm_blis_cref( :, : ); data_gemm_openblas_ref( :, : ) = data_gemm_openblas_cref( :, : ); refch = 'c'; else %if combo(4) == 'd' data_gemm_asm_blis_ref( :, : ) = data_gemm_asm_blis_zref( :, : ); data_gemm_openblas_ref( :, : ) = data_gemm_openblas_zref( :, : ); refch = 'z'; end end % Construct filenames for the data files from templates. file_blis = sprintf( filetemp_blis, thr_str, combo ); file_open = sprintf( filetemp_open, thr_str, combo ); % Load the data files. %str = sprintf( ' Loading %s', file_blis ); disp(str); run( file_blis ) %str = sprintf( ' Loading %s', file_open ); disp(str); run( file_open ) % Plot the result. plot_gemm_perf( combo, ... data_gemm_asm_blis, ... data_gemm_asm_blis_ref, ... data_gemm_openblas, ... data_gemm_openblas_ref, ... is_mt, refch, 3, 2, dti ); end %if 0 %set(gcf,'Position',[0 0 2000 900]); %set(gcf,'PaperUnits', 'inches'); %set(gcf,'PaperSize', [48 22]); %set(gcf,'PaperPosition', [0 0 48 22]); %%set(gcf,'PaperPositionMode','auto'); %set(gcf,'PaperPositionMode','manual'); %set(gcf,'PaperOrientation','landscape'); %end outfile = sprintf( 'output/gemm_select_%c', dom ); print(gcf, outfile,'-bestfit','-dpdf'); %print(gcf, 'gemm_md','-fillpage','-dpdf'); blis-0.9.0/test/mixeddt/matlab/plot_gemm_perf.m000066400000000000000000000107731422157504600215210ustar00rootroot00000000000000function r_val = plot_gemm_perf( dt_str, ... data_ref, ... data_intern, ... data_ad_hoc, ... refch, ... nth, ... rows, cols, ... cfreq, ... dfps, ... theid ) if 1 ax1 = subplot( rows, cols, theid ); hold( ax1, 'on' ); end % Set line properties. color_ref = 'b'; lines_ref = ':'; markr_ref = ''; color_intern = 'b'; lines_intern = '-'; markr_intern = ''; color_ad_hoc = 'k'; lines_ad_hoc = '-.'; markr_ad_hoc = ''; % Compute the peak performance in terms of the number of double flops % executable per cycle and the clock rate. if dt_str(4) == 's' flopspercycle = dfps * 2; else flopspercycle = dfps; end max_perf_core = (flopspercycle * cfreq) * 1; % Print the title to a string. titlename = '%s'; titlename = sprintf( titlename, dt_str ); % Set the legend strings. if refch == 's' ref_legend = sprintf( 'Ref (sgemm)' ); elseif refch == 'd' ref_legend = sprintf( 'Ref (dgemm)' ); elseif refch == 'c' ref_legend = sprintf( 'Ref (cgemm)' ); elseif refch == 'z' ref_legend = sprintf( 'Ref (zgemm)' ); end intern_legend = sprintf( 'Internal' ); ad_hoc_legend = sprintf( 'Ad-hoc' ); % Set axes range values. y_scale = 1.00; x_begin = 0; x_end = data_ref( size( data_ref, 1 ), 1 ); y_begin = 0; y_end = max_perf_core * y_scale; % Set axes names. xaxisname = ' m = n = k'; if nth == 1 yaxisname = 'GFLOPS'; else yaxisname = 'GFLOPS/core'; end flopscol = 4; msize = 5; if 1 fontsize = 13; else fontsize = 16; end linesize = 0.5; legend_loc = 'southeast'; % -------------------------------------------------------------------- x_axis( :, 1 ) = data_intern( :, 1 ); data_peak( 1, 1:2 ) = [ 0 max_perf_core ]; data_peak( 2, 1:2 ) = [ x_end max_perf_core ]; ref = line( x_axis( :, 1 ), data_ref( :, flopscol ) / nth, ... 'Color',color_ref, 'LineStyle',lines_ref, ... 'LineWidth',linesize ); intern = line( x_axis( :, 1 ), data_intern( :, flopscol ) / nth, ... 'Color',color_intern, 'LineStyle',lines_intern, ... 'LineWidth',linesize ); ad_hoc = line( x_axis( :, 1 ), data_ad_hoc( :, flopscol ) / nth, ... 'Color',color_ad_hoc, 'LineStyle',lines_ad_hoc, ... 'LineWidth',linesize ); xlim( ax1, [x_begin x_end] ); ylim( ax1, [y_begin y_end] ); if rows == 8 && cols == 16 refs_legend = sprintf( 'Ref [sc]gemm' ); refd_legend = sprintf( 'Ref [dz]gemm' ); if theid == 1 leg = legend( ... [ ... ref ... intern ... ad_hoc ... ], ... refs_legend, ... intern_legend, ... ad_hoc_legend, ... 'Location', 'best' ); %'Location', legend_loc ); set( leg,'Box','off' ); set( leg,'Color','none' ); set( leg,'FontSize',fontsize-2 ); set( leg,'Units','inches' ); elseif theid == 9 leg = legend( ... [ ... ref ... intern ... ad_hoc ... ], ... refd_legend, ... intern_legend, ... ad_hoc_legend, ... 'Location', 'best' ); %'Location', legend_loc ); set( leg,'Box','off' ); set( leg,'Color','none' ); set( leg,'FontSize',fontsize-2 ); set( leg,'Units','inches' ); end elseif rows == 4 && cols == 4 if theid == 2 || theid == 4 leg = legend( ... [ ... ref ... intern ... ad_hoc ... ], ... ref_legend, ... intern_legend, ... ad_hoc_legend, ... 'Location', legend_loc ); %'Location', 'best' ); set( leg,'Box','off' ); set( leg,'Color','none' ); set( leg,'FontSize',fontsize-2 ); set( leg,'Units','inches' ); if theid == 2 set( leg,'Position',[2.31 3.52 0.7 0.3 ] ); elseif theid == 4 set( leg,'Position',[4.80 3.52 0.7 0.3 ] ); end %set( leg,'Position',[1.03 3.46 0.7 0.3 ] ); end end set( ax1,'FontSize',fontsize ); set( ax1,'TitleFontSizeMultiplier',1.0 ); % default is 1.1. box( ax1, 'on' ); titl = title( titlename ); set( titl, 'FontWeight', 'normal' ); % default font style is now 'bold'. tpos = get( titl, 'Position' ); % default is to align across whole figure, not box. %tpos(1) = tpos(1) + 100; tpos(1) = tpos(1) + 40; set( titl, 'Position', tpos ); % here we nudge it back to centered with box. if theid > (rows-1)*cols xlab = xlabel( ax1,xaxisname ); %tpos = get( xlab, 'Position' ) %tpos(2) = tpos(2) + 10; %set( xlab, 'Position', tpos ); end if mod(theid-1,cols) == 0 ylab = ylabel( ax1,yaxisname ); end r_val = 0; end blis-0.9.0/test/mixeddt/matlab/prec_dom_to_dt.m000066400000000000000000000002641422157504600214750ustar00rootroot00000000000000function r_val = prec_dom_to_dt( pc, dc ) if dc == 'r' if pc == 's' r_val = 's'; else r_val = 'd'; end else if pc == 's' r_val = 'c'; else r_val = 'z'; end end end blis-0.9.0/test/mixeddt/matlab/testrand.m000066400000000000000000000017201422157504600203360ustar00rootroot00000000000000fig1 = figure(1); clf; %orient(fig1,'landscape') orient(gcf,'landscape') for i = 1:128 subplot(8,16,i); xx = 400:400:2000; aa = rand(size(xx)); plot(xx,aa); end % broken. if 0 set(gcf, 'PaperUnits', 'inches'); set(gcf, 'PaperSize', [60 36]); set(fig1,'PaperUnits','normalized'); set(fig1,'PaperPosition', [0 0 1 1]); print(fig1, 'testrand', '-dpdf'); end if 0 % works okay. set(gcf,'PaperUnits', 'inches'); set(gcf,'PaperSize', [72 36]); set(gcf,'PaperPositionMode','auto'); set(gcf,'PaperOrientation','landscape'); set(gcf,'Position',[50 50 4000 1800]); print(gcf, 'testrand','-bestfit','-dpdf'); end if 1 % works better? set(gcf,'Position',[0 0 2000 900]); set(gcf,'PaperUnits', 'inches'); set(gcf,'PaperSize', [48 22]); set(gcf,'PaperPosition', [0 0 48 22]); %set(gcf,'PaperPositionMode','auto'); set(gcf,'PaperPositionMode','manual'); set(gcf,'PaperOrientation','landscape'); print(gcf, 'testrand','-bestfit','-dpdf'); end blis-0.9.0/test/mixeddt/matlab/wawoxmem/000077500000000000000000000000001422157504600202005ustar00rootroot00000000000000blis-0.9.0/test/mixeddt/matlab/wawoxmem/dt_to_dom.m000066400000000000000000000002241422157504600223240ustar00rootroot00000000000000function r_val = dt_to_dom( dt ) dom = 'rrr'; for ch = 1:3 if dt(ch) == 'c' || dt(ch) == 'z' dom(ch) = 'c'; end end r_val = dom; end blis-0.9.0/test/mixeddt/matlab/wawoxmem/gen_prec_combos.m000066400000000000000000000041171422157504600235050ustar00rootroot00000000000000function r_val = gen_prec_combos( mdcase ) dt_chars = [ 's' 'd' 'c' 'z' ]; pr_chars = [ 's' 'd' ]; dm_chars = [ 'r' 'c' ]; dmc = mdcase( 1 ); dma = mdcase( 2 ); dmb = mdcase( 3 ); if 0 pr_combos( 1, : ) = 'ssss'; pr_combos( 2, : ) = 'ssds'; pr_combos( 3, : ) = 'sdss'; pr_combos( 4, : ) = 'sdds'; pr_combos( 5, : ) = 'dsss'; pr_combos( 6, : ) = 'dsds'; pr_combos( 7, : ) = 'ddss'; pr_combos( 8, : ) = 'ddds'; pr_combos( 9, : ) = 'dddd'; pr_combos( 10, : ) = 'ddsd'; pr_combos( 11, : ) = 'dsdd'; pr_combos( 12, : ) = 'dssd'; pr_combos( 13, : ) = 'sddd'; pr_combos( 14, : ) = 'sdsd'; pr_combos( 15, : ) = 'ssdd'; pr_combos( 16, : ) = 'sssd'; end pr_combos( 1, : ) = 'ssss'; pr_combos( 2, : ) = 'ssds'; pr_combos( 3, : ) = 'dddd'; pr_combos( 4, : ) = 'ddsd'; pr_combos( 5, : ) = 'sdss'; pr_combos( 6, : ) = 'sdds'; pr_combos( 7, : ) = 'dsdd'; pr_combos( 8, : ) = 'dssd'; pr_combos( 9, : ) = 'dsss'; pr_combos( 10, : ) = 'dsds'; pr_combos( 11, : ) = 'sddd'; pr_combos( 12, : ) = 'sdsd'; pr_combos( 13, : ) = 'ddss'; pr_combos( 14, : ) = 'ddds'; pr_combos( 15, : ) = 'ssdd'; pr_combos( 16, : ) = 'sssd'; for i = 1:16 pr_combo = pr_combos( i, : ); %str = sprintf( '%s', pr_combo ); disp(str); prc = pr_combo( 1 ); pra = pr_combo( 2 ); prb = pr_combo( 3 ); pr = pr_combo( 4 ); dtc = prec_dom_to_dt( prc, dmc ); dta = prec_dom_to_dt( pra, dma ); dtb = prec_dom_to_dt( prb, dmb ); dt_combos( i, : ) = sprintf( '%c%c%c%c', dtc, dta, dtb, pr ); end %if 0 %i = 1; %pr = 's'; %for prc = pr_chars % for pra = pr_chars % for prb = pr_chars % dtc = prec_dom_to_dt( prc, dmc ); % dta = prec_dom_to_dt( pra, dma ); % dtb = prec_dom_to_dt( prb, dmb ); % dt_combos( i, : ) = sprintf( '%c%c%c%c', dtc, dta, dtb, pr ); % i = i + 1; % end % end %end % %pr = 'd'; %for prc = flip( pr_chars ) % for pra = flip( pr_chars ) % for prb = flip( pr_chars ) % dtc = prec_dom_to_dt( prc, dmc ); % dta = prec_dom_to_dt( pra, dma ); % dtb = prec_dom_to_dt( prb, dmb ); % dt_combos( i, : ) = sprintf( '%c%c%c%c', dtc, dta, dtb, pr ); % i = i + 1; % end % end %end %end r_val = dt_combos; end blis-0.9.0/test/mixeddt/matlab/wawoxmem/plot_dom_all.m000066400000000000000000000015441422157504600230270ustar00rootroot00000000000000function r_val = plot_dom_all( cfreq, ... dflopspercycle, ... nth, ... dirpath_w, ... dirpath_wo, ... dirpath_out, ... arch_str ) cases( 1, : ) = [ 'rrr' ]; cases( 2, : ) = [ 'rrc' ]; cases( 3, : ) = [ 'rcr' ]; cases( 4, : ) = [ 'rcc' ]; cases( 5, : ) = [ 'crr' ]; cases( 6, : ) = [ 'crc' ]; cases( 7, : ) = [ 'ccr' ]; cases( 8, : ) = [ 'ccc' ]; n_cases = size(cases,1); for i = 1:n_cases thecase = cases( i, : ); plot_dom_case( thecase, ... cfreq, ... dflopspercycle, ... nth, ... dirpath_w, ... dirpath_wo, ... dirpath_out, ... arch_str ); end r_val = 0; end blis-0.9.0/test/mixeddt/matlab/wawoxmem/plot_dom_case.m000066400000000000000000000113011422157504600231620ustar00rootroot00000000000000function r_val = plot_dom_case( mdcase, ... cfreq, ... dflopspercycle, ... nth, ... dirpath_w, ... dirpath_wo, ... dirpath_out, ... arch_str ) % Create filename "templates" for the files that contain the performance % results. filetemp_intern = '%s/output_%s_%sgemm_intern.m'; filetemp_ad_hoc = '%s/output_%s_%sgemm_ad_hoc.m'; if nth == 1 thr_str = 'st'; else thr_str = 'mt'; end if 1 dt_combos = gen_prec_combos( mdcase ); else dt_combos( 1, : ) = [ 'ssss' ]; dt_combos( 2, : ) = [ 'sssd' ]; dt_combos( 3, : ) = [ 'ssds' ]; dt_combos( 4, : ) = [ 'sdss' ]; dt_combos( 5, : ) = [ 'dsss' ]; dt_combos( 6, : ) = [ 'ddds' ]; dt_combos( 7, : ) = [ 'dddd' ]; end n_combos = size(dt_combos,1); % Construct filenames for the "reference" (single real) data, then load % the data files, and finally save the results to different variable names. file_blis_sref = sprintf( filetemp_intern, dirpath_w, thr_str, 'ssss' ); run( file_blis_sref ) data_gemm_intern_sref( :, : ) = data_gemm_intern( :, : ); % Construct filenames for the "reference" (double real) data, then load % the data files, and finally save the results to different variable names. file_blis_dref = sprintf( filetemp_intern, dirpath_w, thr_str, 'dddd' ); run( file_blis_dref ) data_gemm_intern_dref( :, : ) = data_gemm_intern( :, : ); % Construct filenames for the "reference" (single complex) data, then load % the data files, and finally save the results to different variable names. file_blis_cref = sprintf( filetemp_intern, dirpath_w, thr_str, 'cccs' ); run( file_blis_cref ) data_gemm_intern_cref( :, : ) = data_gemm_intern( :, : ); % Construct filenames for the "reference" (double complex) data, then load % the data files, and finally save the results to different variable names. file_blis_zref = sprintf( filetemp_intern, dirpath_w, thr_str, 'zzzd' ); run( file_blis_zref ) data_gemm_intern_zref( :, : ) = data_gemm_intern( :, : ); fig = figure; orient( fig, 'portrait' ); %set(gcf,'Position',[0 0 2000 900]); set(gcf,'PaperUnits', 'inches'); %set(gcf,'PaperSize', [16 12.4]); %set(gcf,'PaperPosition', [0 0 16 12.4]); set(gcf,'PaperSize', [14 11.0]); set(gcf,'PaperPosition', [0 0 14 11.0]); %set(gcf,'PaperPositionMode','auto'); set(gcf,'PaperPositionMode','manual'); set(gcf,'PaperOrientation','portrait'); fprintf( 'Plotting... ' ); for dti = 1:n_combos %for dti = 1:1 % Grab the current datatype combination. combo = dt_combos( dti, : ); %str = sprintf( 'Plotting %d: %s', dti, combo ); disp(str); fprintf( '%d (%s) ', dti, combo ); if combo(4) == 's' data_gemm_ref( :, : ) = data_gemm_intern_sref( :, : ); refch = 's'; else %if combo(4) == 'd' data_gemm_ref( :, : ) = data_gemm_intern_dref( :, : ); refch = 'd'; end if ( combo(1) == 'c' || combo(1) == 'z' ) && ... ( combo(2) == 'c' || combo(2) == 'z' ) && ... ( combo(3) == 'c' || combo(3) == 'z' ) if combo(4) == 's' data_gemm_ref( :, : ) = data_gemm_intern_cref( :, : ); refch = 'c'; else %if combo(4) == 'd' data_gemm_ref( :, : ) = data_gemm_intern_zref( :, : ); refch = 'z'; end end % Construct filenames for the data files from templates. file_intern_w = sprintf( filetemp_intern, dirpath_w, thr_str, combo ); file_intern_wo = sprintf( filetemp_intern, dirpath_wo, thr_str, combo ); file_ad_hoc = sprintf( filetemp_ad_hoc, dirpath_w, thr_str, combo ); % Load the data files. %str = sprintf( ' Loading %s', file_intern_w ); disp(str); run( file_intern_w ) data_gemm_intern_w( :, : ) = data_gemm_intern( :, : ); %str = sprintf( ' Loading %s', file_intern_wo ); disp(str); run( file_intern_wo ) data_gemm_intern_wo( :, : ) = data_gemm_intern( :, : ); %str = sprintf( ' Loading %s', file_ad_hoc ); disp(str); run( file_ad_hoc ) % Plot the result. plot_gemm_perf( combo, ... data_gemm_ref, ... data_gemm_intern_w, ... data_gemm_intern_wo, ... data_gemm_ad_hoc, ... refch, ... nth, ... 4, 4, ... cfreq, ... dflopspercycle, ... dti ); end fprintf( '\n' ); %if 0 %set(gcf,'Position',[0 0 2000 900]); %set(gcf,'PaperUnits', 'inches'); %set(gcf,'PaperSize', [48 22]); %set(gcf,'PaperPosition', [0 0 48 22]); %%set(gcf,'PaperPositionMode','auto'); %set(gcf,'PaperPositionMode','manual'); %set(gcf,'PaperOrientation','landscape'); %end outfile = sprintf( '%s/gemm_%s_%s', dirpath_out, mdcase, arch_str ); print(gcf, outfile,'-bestfit','-dpdf'); %print(gcf, 'gemm_md','-fillpage','-dpdf'); blis-0.9.0/test/mixeddt/matlab/wawoxmem/plot_dt_select.m000066400000000000000000000114711422157504600233660ustar00rootroot00000000000000function r_val = plot_dt_select( cfreq, ... dflopspercycle, ... nth, ... dirpath_w, ... dirpath_wo, ... dirpath_out, ... arch_str ) % Create filename "templates" for the files that contain the performance % results. filetemp_intern = '%s/output_%s_%sgemm_intern.m'; filetemp_ad_hoc = '%s/output_%s_%sgemm_ad_hoc.m'; if nth == 1 thr_str = 'st'; else thr_str = 'mt'; end dt_combos( 1, : ) = [ 'sdds' ]; dt_combos( 2, : ) = [ 'ccss' ]; dt_combos( 3, : ) = [ 'dssd' ]; dt_combos( 4, : ) = [ 'zzdd' ]; dt_combos( 5, : ) = [ 'ddds' ]; dt_combos( 6, : ) = [ 'cscs' ]; dt_combos( 7, : ) = [ 'sssd' ]; dt_combos( 8, : ) = [ 'zdzd' ]; dt_combos( 9, : ) = [ 'dsss' ]; dt_combos( 10, : ) = [ 'csss' ]; dt_combos( 11, : ) = [ 'sddd' ]; dt_combos( 12, : ) = [ 'zddd' ]; n_combos = size(dt_combos,1); % Construct filenames for the "reference" (single real) data, then load % the data files, and finally save the results to different variable names. file_blis_sref = sprintf( filetemp_intern, dirpath_w, thr_str, 'ssss' ); run( file_blis_sref ) data_gemm_intern_sref( :, : ) = data_gemm_intern( :, : ); % Construct filenames for the "reference" (double real) data, then load % the data files, and finally save the results to different variable names. file_blis_dref = sprintf( filetemp_intern, dirpath_w, thr_str, 'dddd' ); run( file_blis_dref ) data_gemm_intern_dref( :, : ) = data_gemm_intern( :, : ); % Construct filenames for the "reference" (single complex) data, then load % the data files, and finally save the results to different variable names. file_blis_cref = sprintf( filetemp_intern, dirpath_w, thr_str, 'cccs' ); run( file_blis_cref ) data_gemm_intern_cref( :, : ) = data_gemm_intern( :, : ); % Construct filenames for the "reference" (double complex) data, then load % the data files, and finally save the results to different variable names. file_blis_zref = sprintf( filetemp_intern, dirpath_w, thr_str, 'zzzd' ); run( file_blis_zref ) data_gemm_intern_zref( :, : ) = data_gemm_intern( :, : ); %fig = figure; fig = figure('Position', [100, 100, 1000, 600]); orient( fig, 'portrait' ); %set(gcf,'Position',[0 0 2000 900]); set(gcf,'PaperUnits', 'inches'); %set(gcf,'PaperSize', [16 12.4]); %set(gcf,'PaperPosition', [0 0 16 12.4]); set(gcf,'PaperSize', [14 9.5]); set(gcf,'PaperPosition', [0 0 14 9.5]); %set(gcf,'PaperPositionMode','auto'); set(gcf,'PaperPositionMode','manual'); set(gcf,'PaperOrientation','portrait'); fprintf( 'Plotting... ' ); for dti = 1:n_combos %for dti = 1:1 % Grab the current datatype combination. combo = dt_combos( dti, : ); %str = sprintf( 'Plotting %d: %s', dti, combo ); disp(str); fprintf( '%d (%s) ', dti, combo ); if combo(4) == 's' data_gemm_ref( :, : ) = data_gemm_intern_sref( :, : ); refch = 's'; else %if combo(4) == 'd' data_gemm_ref( :, : ) = data_gemm_intern_dref( :, : ); refch = 'd'; end if ( combo(1) == 'c' || combo(1) == 'z' ) && ... ( combo(2) == 'c' || combo(2) == 'z' ) && ... ( combo(3) == 'c' || combo(3) == 'z' ) if combo(4) == 's' data_gemm_ref( :, : ) = data_gemm_intern_cref( :, : ); refch = 'c'; else %if combo(4) == 'd' data_gemm_ref( :, : ) = data_gemm_intern_zref( :, : ); refch = 'z'; end end % Construct filenames for the data files from templates. file_intern_w = sprintf( filetemp_intern, dirpath_w, thr_str, combo ); file_intern_wo = sprintf( filetemp_intern, dirpath_wo, thr_str, combo ); file_ad_hoc = sprintf( filetemp_ad_hoc, dirpath_w, thr_str, combo ); % Load the data files. %str = sprintf( ' Loading %s', file_intern_w ); disp(str); run( file_intern_w ) data_gemm_intern_w( :, : ) = data_gemm_intern( :, : ); %str = sprintf( ' Loading %s', file_intern_wo ); disp(str); run( file_intern_wo ) data_gemm_intern_wo( :, : ) = data_gemm_intern( :, : ); %str = sprintf( ' Loading %s', file_ad_hoc ); disp(str); run( file_ad_hoc ) % Plot the result. plot_gemm_perf( combo, ... data_gemm_ref, ... data_gemm_intern_w, ... data_gemm_intern_wo, ... data_gemm_ad_hoc, ... refch, ... nth, ... 3, 4, ... cfreq, ... dflopspercycle, ... dti ); end fprintf( '\n' ); %if 0 %set(gcf,'Position',[0 0 2000 900]); %set(gcf,'PaperUnits', 'inches'); %set(gcf,'PaperSize', [48 22]); %set(gcf,'PaperPosition', [0 0 48 22]); %%set(gcf,'PaperPositionMode','auto'); %set(gcf,'PaperPositionMode','manual'); %set(gcf,'PaperOrientation','landscape'); %end outfile = sprintf( '%s/gemm_select_%s', dirpath_out, arch_str ); print(gcf, outfile,'-bestfit','-dpdf'); %print(gcf, 'gemm_md','-fillpage','-dpdf'); blis-0.9.0/test/mixeddt/matlab/wawoxmem/plot_gemm_perf.m000066400000000000000000000122741422157504600233630ustar00rootroot00000000000000function r_val = plot_gemm_perf( dt_str, ... data_ref, ... data_intern_w, ... data_intern_wo, ... data_ad_hoc, ... refch, ... nth, ... rows, cols, ... cfreq, ... dfps, ... theid ) if 1 ax1 = subplot( rows, cols, theid ); hold( ax1, 'on' ); end % Set line properties. color_ref = 'b'; lines_ref = ':'; markr_ref = ''; color_intern_w = 'r'; lines_intern_w = '-'; markr_intern_w = ''; color_intern_wo = 'b'; lines_intern_wo = '--'; markr_intern_wo = '.'; color_ad_hoc = 'k'; lines_ad_hoc = '-.'; markr_ad_hoc = ''; % Compute the peak performance in terms of the number of double flops % executable per cycle and the clock rate. if dt_str(4) == 's' flopspercycle = dfps * 2; else flopspercycle = dfps; end max_perf_core = (flopspercycle * cfreq) * 1; % Print the title to a string. %titlename = '%sgemm'; titlename = '%s'; titlename = sprintf( titlename, dt_str ); % Set the legend strings. if refch == 's' ref_legend = sprintf( 'Ref (sgemm)' ); elseif refch == 'd' ref_legend = sprintf( 'Ref (dgemm)' ); elseif refch == 'c' ref_legend = sprintf( 'Ref (cgemm)' ); elseif refch == 'z' ref_legend = sprintf( 'Ref (zgemm)' ); end internw_legend = sprintf( 'Intern (+xm)' ); internwo_legend = sprintf( 'Intern (-xm)' ); ad_hoc_legend = sprintf( 'Ad-hoc' ); % Set axes range values. y_scale = 1.00; x_begin = 0; x_end = data_ref( size( data_ref, 1 ), 1 ); y_begin = 0; y_end = max_perf_core * y_scale; % Set axes names. xaxisname = ' m = n = k'; if nth == 1 yaxisname = 'GFLOPS'; else yaxisname = 'GFLOPS/core'; end flopscol = 4; msize = 5; if 1 fontsize = 13; else fontsize = 16; end linesize = 0.5; legend_loc = 'southeast'; % -------------------------------------------------------------------- x_axis( :, 1 ) = data_intern_w( :, 1 ); data_peak( 1, 1:2 ) = [ 0 max_perf_core ]; data_peak( 2, 1:2 ) = [ x_end max_perf_core ]; ref = line( x_axis( :, 1 ), data_ref( :, flopscol ) / nth, ... 'Color',color_ref, 'LineStyle',lines_ref, ... 'LineWidth',linesize ); if ( uses_xmem( dt_str ) ) intern_w = line( x_axis( :, 1 ), data_intern_w( :, flopscol ) / nth, ... 'Color',color_intern_w, 'LineStyle',lines_intern_w, ... 'LineWidth',linesize ); else %set( intern_w, 'visible', 'off' ); intern_w = line( nan, nan, ... 'Color',color_intern_w, 'LineStyle',lines_intern_w, ... 'LineWidth',linesize ); end intern_wo = line( x_axis( :, 1 ), data_intern_wo( :, flopscol ) / nth, ... 'Color',color_intern_wo, 'LineStyle',lines_intern_wo, ... 'LineWidth',linesize ); ad_hoc = line( x_axis( :, 1 ), data_ad_hoc( :, flopscol ) / nth, ... 'Color',color_ad_hoc, 'LineStyle',lines_ad_hoc, ... 'LineWidth',linesize ); xlim( ax1, [x_begin x_end] ); ylim( ax1, [y_begin y_end] ); if x_end == 6000 x_tick2 = x_end - 1000; x_tick1 = x_tick2/2; xticks( ax1, [ x_tick1 x_tick2 ] ); elseif x_end == 2000 x_tick2 = x_end - 400; x_tick1 = x_tick2/2; xticks( ax1, [ x_tick1 x_tick2 ] ); end % full domain case if rows == 4 && cols == 4 if theid == 2 || theid == 4 leg = legend( ... [ ... ref ... intern_w ... intern_wo ... ad_hoc ... ], ... ref_legend, ... internw_legend, ... internwo_legend, ... ad_hoc_legend, ... 'Location', legend_loc ); %'Location', 'best' ); set( leg,'Box','off' ); set( leg,'Color','none' ); set( leg,'FontSize',fontsize-2 ); set( leg,'Units','inches' ); if theid == 2 set( leg,'Position',[2.31 3.52 0.7 0.3 ] ); elseif theid == 4 set( leg,'Position',[4.80 3.52 0.7 0.3 ] ); end end % select graphs elseif rows == 3 && cols == 4 if theid == 2 || theid == 4 leg = legend( ... [ ... ref ... intern_w ... intern_wo ... ad_hoc ... ], ... ref_legend, ... internw_legend, ... internwo_legend, ... ad_hoc_legend, ... 'Location', legend_loc ); %'Location', 'best' ); set( leg,'Box','off' ); set( leg,'Color','none' ); set( leg,'FontSize',fontsize-2 ); set( leg,'Units','inches' ); if theid == 2 set( leg,'Position',[4.38 4.78 0.7 0.3 ] ); elseif theid == 4 set( leg,'Position',[8.82 4.78 0.7 0.3 ] ); end end end set( ax1,'FontSize',fontsize ); set( ax1,'TitleFontSizeMultiplier',1.0 ); % default is 1.1. box( ax1, 'on' ); titl = title( titlename ); set( titl, 'FontWeight', 'normal' ); % default font style is now 'bold'. tpos = get( titl, 'Position' ); % default is to align across whole figure, not box. %tpos(1) = tpos(1) + 100; tpos(1) = tpos(1) + 40; set( titl, 'Position', tpos ); % here we nudge it back to centered with box. if theid > (rows-1)*cols xlab = xlabel( ax1,xaxisname ); %tpos = get( xlab, 'Position' ) %tpos(2) = tpos(2) + 10; %set( xlab, 'Position', tpos ); end if mod(theid-1,cols) == 0 ylab = ylabel( ax1,yaxisname ); end r_val = 0; end blis-0.9.0/test/mixeddt/matlab/wawoxmem/prec_dom_to_dt.m000066400000000000000000000003011422157504600233310ustar00rootroot00000000000000function r_val = prec_dom_to_dt( pc, dc ) if dc == 'r' if pc == 's' r_val = 's'; else r_val = 'd'; end else if pc == 's' r_val = 'c'; else r_val = 'z'; end end end blis-0.9.0/test/mixeddt/matlab/wawoxmem/uses_xmem.m000066400000000000000000000006231422157504600223640ustar00rootroot00000000000000function r_val = uses_xmem( dt_str ) a = dt_str(1); b = dt_str(4); a_prec = 'd'; b_prec = 'd'; if ( a == 's' || a == 'c' ) a_prec = 's'; end if ( b == 's' || b == 'c' ) b_prec = 's'; end dom_str = dt_to_dom( dt_str ); r_val = 0; if ( a_prec ~= b_prec ) r_val = 1; elseif ( strcmp( dom_str, 'crr' ) ) r_val = 1; elseif ( strcmp( dom_str, 'crc' ) ) r_val = 1; end end blis-0.9.0/test/mixeddt/runme.sh000077500000000000000000000107231422157504600165640ustar00rootroot00000000000000#!/bin/bash # File pefixes. exec_root="test" out_root="output" sys="blis" #sys="stampede2" #sys="lonestar5" #sys="ul252" sys="tx2" # Bind threads to processors. #export OMP_PROC_BIND=true #export GOMP_CPU_AFFINITY="0 2 4 6 8 10 12 14 1 3 5 7 9 11 13 15" #export GOMP_CPU_AFFINITY="0 1 2 3 4 5 6 7" #export GOMP_CPU_AFFINITY="0 1 2 3 4 5 6 7" #export GOMP_CPU_AFFINITY="0 2 4 6 1 3 5 7" #export GOMP_CPU_AFFINITY="0 4 1 5 2 6 3 7" #export GOMP_CPU_AFFINITY="0 1 4 5 8 9 12 13 16 17 20 21 24 25 28 29 32 33 36 37 40 41 44 45" #export GOMP_CPU_AFFINITY="0 2 4 6 8 10 12 14 16 18 20 22 1 3 5 7 9 11 13 15 17 19 21 23" #export GOMP_CPU_AFFINITY="0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23" export GOMP_CPU_AFFINITY="0 1 2 3" # Modify LD_LIBRARY_PATH. if [ ${sys} = "blis" ]; then export LD_LIBRARY_PATH="$LD_LIBRARY_PATH" export GOMP_CPU_AFFINITY="0 1 2 3" jc_nt=1 # 5th loop ic_nt=4 # 3rd loop jr_nt=1 # 2nd loop ir_nt=1 # 1st loop nt=4 elif [ ${sys} = "stampede2" ]; then echo "Need to set GOMP_CPU_AFFINITY." exit 1 jc_nt=4 # 5th loop ic_nt=12 # 3rd loop jr_nt=1 # 2nd loop ir_nt=1 # 1st loop nt=48 elif [ ${sys} = "lonestar5" ]; then echo "Need to set GOMP_CPU_AFFINITY." exit 1 # A hack to use libiomp5 with gcc. export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/opt/apps/intel/16.0.1.150/compilers_and_libraries_2016.1.150/linux/compiler/lib/intel64" jc_nt=2 # 5th loop ic_nt=12 # 3rd loop jr_nt=1 # 2nd loop ir_nt=1 # 1st loop nt=24 elif [ ${sys} = "ul252" ]; then export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/home/field/intel/mkl/lib/intel64" #export GOMP_CPU_AFFINITY="0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103" export GOMP_CPU_AFFINITY="0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51" #jc_nt=4 # 5th loop jc_nt=2 # 5th loop ic_nt=13 # 3rd loop jr_nt=1 # 2nd loop ir_nt=1 # 1st loop #nt=52 nt=26 elif [ ${sys} = "tx2" ]; then export GOMP_CPU_AFFINITY="0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55" jc_nt=8 # 5th loop ic_nt=7 # 3rd loop jr_nt=1 # 2nd loop ir_nt=1 # 1st loop nt=56 fi # Save a copy of GOMP_CPU_AFFINITY so that if we have to unset it, we can # restore the value. GOMP_CPU_AFFINITYsave=${GOMP_CPU_AFFINITY} # Datatypes to test. #dts="s d c z" # Threadedness to test. threads="mt" #threads="st" # Implementations to test. test_impls="ad_hoc intern" # Operations to test. l3_ops="gemm" test_ops="${l3_ops}" # Define the list of datatype chars and precision chars. dt_chars="s d c z" pr_chars="s d" # Construct the datatype combination strings. dt_combos="" for dtc in ${dt_chars}; do for dta in ${dt_chars}; do for dtb in ${dt_chars}; do for pre in ${pr_chars}; do dt_combos="${dt_combos} ${dtc}${dta}${dtb}${pre}" done done done done # Overrides, in case something goes wrong for a subset of tests. #test_impls="ad_hoc" #dt_combos="ssss sssd ssds sdss dsss ddds dddd" # Now perform complex test cases. for th in ${threads}; do for dt in ${dt_combos}; do for im in ${test_impls}; do for op in ${test_ops}; do # Set the number of threads according to th. if [ ${th} = "mt" ]; then export BLIS_JC_NT=${jc_nt} export BLIS_IC_NT=${ic_nt} export BLIS_JR_NT=${jr_nt} export BLIS_IR_NT=${ir_nt} export OMP_NUM_THREADS=${nt} export OPENBLAS_NUM_THREADS=${nt} # Unset GOMP_CPU_AFFINITY for OpenBLAS. if [ ${im} = "openblas" ]; then unset GOMP_CPU_AFFINITY else export GOMP_CPU_AFFINITY=${GOMP_CPU_AFFINITYsave} fi else export BLIS_JC_NT=1 export BLIS_IC_NT=1 export BLIS_JR_NT=1 export BLIS_IR_NT=1 export OMP_NUM_THREADS=1 export OPENBLAS_NUM_THREADS=1 fi # Construct the name of the test executable. exec_name="${exec_root}_${dt}${op}_${im}_${th}.x" # Construct the name of the output file. out_file="${out_root}_${th}_${dt}${op}_${im}.m" echo "Running (nt = ${OMP_NUM_THREADS}) ./${exec_name} > ${out_file}" # Run executable. ./${exec_name} > ${out_file} #sleep 1 done done done done blis-0.9.0/test/mixeddt/test_gemm.c000066400000000000000000000374661422157504600172440ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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 The University of Texas 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 COPYRIGHT HOLDER 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. */ #include #include "blis.h" void blas_gemm_md( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c ); void blas_gemm( trans_t transa, trans_t transb, num_t dt, obj_t* ao, obj_t* alpha, obj_t* bo, obj_t* beta, obj_t* co ); //#define PRINT int main( int argc, char** argv ) { obj_t a, b, c; obj_t c_save; obj_t* alphao; obj_t* betao; dim_t m, n, k; dim_t p; int r; double dtime; double dtime_save; double gflops; double flopsmul; //bli_init(); //bli_error_checking_level_set( BLIS_NO_ERROR_CHECKING ); int n_repeats = 3; num_t dta = DTA; num_t dtb = DTB; num_t dtc = DTC; num_t dtx = DTX; const bool a_real = bli_is_real( dta ); const bool b_real = bli_is_real( dtb ); const bool c_real = bli_is_real( dtc ); const bool a_complex = bli_is_complex( dta ); const bool b_complex = bli_is_complex( dtb ); const bool c_complex = bli_is_complex( dtc ); // Extract the precision component of the computation datatype. prec_t comp_prec = bli_dt_prec( dtx ); dim_t p_begin = P_BEGIN; dim_t p_max = P_MAX; dim_t p_inc = P_INC; int m_input = -1; int n_input = -1; int k_input = -1; #if 0 k_input = 256; #endif #if 0 char dta_ch, dtb_ch, dtc_ch, dtx_ch; // Choose the char corresponding to the requested datatype. if ( bli_is_float( dta ) ) dta_ch = 's'; else if ( bli_is_double( dta ) ) dta_ch = 'd'; else if ( bli_is_scomplex( dta ) ) dta_ch = 'c'; else dta_ch = 'z'; if ( bli_is_float( dtb ) ) dtb_ch = 's'; else if ( bli_is_double( dtb ) ) dtb_ch = 'd'; else if ( bli_is_scomplex( dtb ) ) dtb_ch = 'c'; else dtb_ch = 'z'; if ( bli_is_float( dtc ) ) dtc_ch = 's'; else if ( bli_is_double( dtc ) ) dtc_ch = 'd'; else if ( bli_is_scomplex( dtc ) ) dtc_ch = 'c'; else dtc_ch = 'z'; if ( bli_is_float( dtx ) ) dtx_ch = 's'; else dtx_ch = 'd'; ( void )dta_ch; ( void )dtb_ch; ( void )dtc_ch; ( void )dtx_ch; #endif trans_t transa = BLIS_NO_TRANSPOSE; trans_t transb = BLIS_NO_TRANSPOSE; // Begin with initializing the last entry to zero so that // matlab allocates space for the entire array once up-front. for ( p = p_begin; p + p_inc <= p_max; p += p_inc ) ; //printf( "data_%s_%c%c%c%cgemm_%s", THR_STR, dtc_ch, dta_ch, dtb_ch, dtx_ch, STR ); printf( "data_gemm_%s", STR ); printf( "( %2lu, 1:4 ) = [ %4lu %4lu %4lu %7.2f ];\n", ( unsigned long )(p - p_begin)/p_inc + 1, ( unsigned long )0, ( unsigned long )0, ( unsigned long )0, 0.0 ); // Adjust the flops scaling based on which domain case is being executed. if ( c_real && a_real && b_real ) flopsmul = 2.0; else if ( c_real && a_real && b_complex ) flopsmul = 2.0; else if ( c_real && a_complex && b_real ) flopsmul = 2.0; else if ( c_real && a_complex && b_complex ) flopsmul = 4.0; else if ( c_complex && a_real && b_real ) flopsmul = 2.0; else if ( c_complex && a_real && b_complex ) flopsmul = 4.0; else if ( c_complex && a_complex && b_real ) flopsmul = 4.0; else if ( c_complex && a_complex && b_complex ) flopsmul = 8.0; //for ( p = p_begin; p <= p_max; p += p_inc ) for ( p = p_max; p_begin <= p; p -= p_inc ) { if ( m_input < 0 ) m = p * ( dim_t )abs(m_input); else m = ( dim_t ) m_input; if ( n_input < 0 ) n = p * ( dim_t )abs(n_input); else n = ( dim_t ) n_input; if ( k_input < 0 ) k = p * ( dim_t )abs(k_input); else k = ( dim_t ) k_input; bli_obj_create( dta, m, k, 0, 0, &a ); bli_obj_create( dtb, k, n, 0, 0, &b ); bli_obj_create( dtc, m, n, 0, 0, &c ); bli_obj_create( dtc, m, n, 0, 0, &c_save ); bli_obj_set_comp_prec( comp_prec, &c ); alphao = &BLIS_ONE; betao = &BLIS_ONE; bli_randm( &a ); bli_randm( &b ); bli_randm( &c ); bli_obj_set_conjtrans( transa, &a ); bli_obj_set_conjtrans( transb, &b ); bli_copym( &c, &c_save ); dtime_save = DBL_MAX; for ( r = 0; r < n_repeats; ++r ) { bli_copym( &c_save, &c ); dtime = bli_clock(); #ifdef PRINT bli_printm( "a", &a, "%4.1f", "" ); bli_printm( "b", &b, "%4.1f", "" ); bli_printm( "c", &c, "%4.1f", "" ); #endif #ifdef BLIS bli_gemm ( alphao, &a, &b, betao, &c ); #else blas_gemm_md ( alphao, &a, &b, betao, &c ); #endif #ifdef PRINT bli_printm( "c after", &c, "%4.1f", "" ); exit(1); #endif dtime_save = bli_clock_min_diff( dtime_save, dtime ); } gflops = ( flopsmul * m * k * n ) / ( dtime_save * 1.0e9 ); //printf( "data_%s_%c%c%c%cgemm_%s", THR_STR, dtc_ch, dta_ch, dtb_ch, dtx_ch, STR ); printf( "data_gemm_%s", STR ); printf( "( %2lu, 1:4 ) = [ %4lu %4lu %4lu %7.2f ];\n", ( unsigned long )(p - p_begin)/p_inc + 1, ( unsigned long )m, ( unsigned long )k, ( unsigned long )n, gflops ); bli_obj_free( &a ); bli_obj_free( &b ); bli_obj_free( &c ); bli_obj_free( &c_save ); } //bli_finalize(); return 0; } void blas_gemm_md( obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c ) { trans_t transa = bli_obj_conjtrans_status( a ); trans_t transb = bli_obj_conjtrans_status( b ); prec_t comp_prec = bli_obj_comp_prec( c ); if ( bli_obj_dt( a ) == bli_obj_dt( b ) && bli_obj_dt( b ) == bli_obj_dt( c ) && //bli_obj_dt( c ) == ( num_t )comp_prec ) bli_obj_prec( c ) == comp_prec ) { blas_gemm( transa, transb, bli_obj_dt( c ), alpha, a, b, beta, c ); return; } num_t dtc = bli_obj_dt( c ); num_t dta = bli_obj_dt( a ); num_t dtb = bli_obj_dt( b ); dim_t m = bli_obj_length( c ); dim_t n = bli_obj_width( c ); dim_t k = bli_obj_width_after_trans( a ); obj_t* ao = a; obj_t* bo = b; obj_t* co = c; num_t targ_dt_c, targ_dt_a, targ_dt_b; dom_t targ_dom_c, targ_dom_a, targ_dom_b; num_t dt_comp; dom_t comp_dom; obj_t at, bt, ct; obj_t ar, cr; bool needacc; bool force_proj_a = FALSE; bool force_proj_b = FALSE; if ( bli_is_real( dtc ) && bli_is_real( dta ) && bli_is_real( dtb ) ) { // rrr comp_dom = BLIS_REAL; targ_dom_c = BLIS_REAL; targ_dom_a = BLIS_REAL; targ_dom_b = BLIS_REAL; needacc = FALSE; } else if ( bli_is_real( dtc ) && bli_is_real( dta ) && bli_is_complex( dtb ) ) { // rrc comp_dom = BLIS_REAL; targ_dom_c = BLIS_REAL; targ_dom_a = BLIS_REAL; targ_dom_b = BLIS_REAL; needacc = FALSE; force_proj_b = TRUE; } else if ( bli_is_real( dtc ) && bli_is_complex( dta ) && bli_is_real( dtb ) ) { // rcr comp_dom = BLIS_REAL; targ_dom_c = BLIS_REAL; targ_dom_a = BLIS_REAL; targ_dom_b = BLIS_REAL; needacc = FALSE; force_proj_a = TRUE; } else if ( bli_is_real( dtc ) && bli_is_complex( dta ) && bli_is_complex( dtb ) ) { // rcc comp_dom = BLIS_COMPLEX; targ_dom_c = BLIS_COMPLEX; targ_dom_a = BLIS_COMPLEX; targ_dom_b = BLIS_COMPLEX; needacc = TRUE; } else if ( bli_is_complex( dtc ) && bli_is_real( dta ) && bli_is_real( dtb ) ) { // crr comp_dom = BLIS_REAL; targ_dom_c = BLIS_REAL; targ_dom_a = BLIS_REAL; targ_dom_b = BLIS_REAL; needacc = TRUE; } else if ( bli_is_complex( dtc ) && bli_is_real( dta ) && bli_is_complex( dtb ) ) { // crc comp_dom = BLIS_COMPLEX; targ_dom_c = BLIS_COMPLEX; targ_dom_a = BLIS_COMPLEX; targ_dom_b = BLIS_COMPLEX; needacc = FALSE; force_proj_a = TRUE; } else if ( bli_is_complex( dtc ) && bli_is_complex( dta ) && bli_is_real( dtb ) ) { // ccr comp_dom = BLIS_REAL; targ_dom_c = BLIS_COMPLEX; targ_dom_a = BLIS_COMPLEX; targ_dom_b = BLIS_REAL; needacc = FALSE; } else if ( bli_is_complex( dtc ) && bli_is_complex( dta ) && bli_is_complex( dtb ) ) { // ccc comp_dom = BLIS_COMPLEX; targ_dom_c = BLIS_COMPLEX; targ_dom_a = BLIS_COMPLEX; targ_dom_b = BLIS_COMPLEX; needacc = FALSE; } else { comp_dom = BLIS_REAL; targ_dom_c = BLIS_REAL; targ_dom_a = BLIS_REAL; targ_dom_b = BLIS_REAL; needacc = FALSE; } // ---------------------------------------------------------------------------- // Merge the computation domain with the computation precision. dt_comp = comp_dom | comp_prec; targ_dt_a = targ_dom_a | comp_prec; targ_dt_b = targ_dom_b | comp_prec; targ_dt_c = targ_dom_c | comp_prec; // Copy-cast A, if needed. if ( bli_dt_prec( dta ) != comp_prec || force_proj_a ) { bli_obj_create( targ_dt_a, m, k, 0, 0, &at ); bli_castm( ao, &at ); ao = &at; } // Copy-cast B, if needed. if ( bli_dt_prec( dtb ) != comp_prec || force_proj_b ) { bli_obj_create( targ_dt_b, k, n, 0, 0, &bt ); bli_castm( bo, &bt ); bo = &bt; } if ( bli_dt_prec( dtc ) != comp_prec ) { needacc = TRUE; } // Copy-cast C, if needed. if ( needacc ) { //bli_obj_create( dt_comp, m, n, 0, 0, &ct ); bli_obj_create( targ_dt_c, m, n, 0, 0, &ct ); bli_castm( c, &ct ); co = &ct; } // ---------------------------------------------------------------------------- if ( bli_is_real( dtc ) && bli_is_real( dta ) && bli_is_real( dtb ) ) { } else if ( bli_is_real( dtc ) && bli_is_real( dta ) && bli_is_complex( dtb ) ) { } else if ( bli_is_real( dtc ) && bli_is_complex( dta ) && bli_is_real( dtb ) ) { } else if ( bli_is_real( dtc ) && bli_is_complex( dta ) && bli_is_complex( dtb ) ) { } else if ( bli_is_complex( dtc ) && bli_is_real( dta ) && bli_is_real( dtb ) ) { } else if ( bli_is_complex( dtc ) && bli_is_real( dta ) && bli_is_complex( dtb ) ) { } else if ( bli_is_complex( dtc ) && bli_is_complex( dta ) && bli_is_real( dtb ) ) { inc_t rsa = bli_obj_row_stride( ao ); inc_t csa = bli_obj_col_stride( ao ); inc_t ma = bli_obj_length( ao ); inc_t na = bli_obj_width( ao ); siz_t ela = bli_obj_elem_size( ao ); num_t dtap = bli_obj_dt_proj_to_real( ao ); bli_obj_alias_to( ao, &ar ); ao = &ar; bli_obj_set_strides( rsa, 2*csa, ao ); bli_obj_set_dims( 2*ma, na, ao ); bli_obj_set_dt( dtap, ao ); bli_obj_set_elem_size( ela/2, ao ); inc_t rsc = bli_obj_row_stride( co ); inc_t csc = bli_obj_col_stride( co ); inc_t mc = bli_obj_length( co ); inc_t nc = bli_obj_width( co ); siz_t elc = bli_obj_elem_size( co ); num_t dtcp = bli_obj_dt_proj_to_real( co ); bli_obj_alias_to( co, &cr ); co = &cr; bli_obj_set_strides( rsc, 2*csc, co ); bli_obj_set_dims( 2*mc, nc, co ); bli_obj_set_dt( dtcp, co ); bli_obj_set_elem_size( elc/2, co ); } else if ( bli_is_complex( dtc ) && bli_is_complex( dta ) && bli_is_complex( dtb ) ) { } else { } // ---------------------------------------------------------------------------- // Call the BLAS. blas_gemm( transa, transb, dt_comp, alpha, ao, bo, beta, co ); // Accumulate back to C, if needed. if ( needacc ) { bli_castm( &ct, c ); } if ( bli_dt_prec( dta ) != comp_prec || force_proj_a ) { bli_obj_free( &at ); } if ( bli_dt_prec( dtb ) != comp_prec || force_proj_b ) { bli_obj_free( &bt ); } if ( needacc ) { bli_obj_free( &ct ); } } void blas_gemm( trans_t transa, trans_t transb, num_t dt, obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c ) { char f77_transa = 'N'; char f77_transb = 'N'; //bli_param_map_blis_to_netlib_trans( transa, &f77_transa ); //bli_param_map_blis_to_netlib_trans( transb, &f77_transb ); if ( bli_is_float( dt ) ) { f77_int mm = bli_obj_length( c ); f77_int kk = bli_obj_width_after_trans( a ); f77_int nn = bli_obj_width( c ); f77_int lda = bli_obj_col_stride( a ); f77_int ldb = bli_obj_col_stride( b ); f77_int ldc = bli_obj_col_stride( c ); float* alphap = bli_obj_buffer_for_1x1( dt, alpha ); float* ap = bli_obj_buffer( a ); float* bp = bli_obj_buffer( b ); float* betap = bli_obj_buffer_for_1x1( dt, beta ); float* cp = bli_obj_buffer( c ); sgemm_( &f77_transa, &f77_transb, &mm, &nn, &kk, alphap, ap, &lda, bp, &ldb, betap, cp, &ldc ); } else if ( bli_is_double( dt ) ) { f77_int mm = bli_obj_length( c ); f77_int kk = bli_obj_width_after_trans( a ); f77_int nn = bli_obj_width( c ); f77_int lda = bli_obj_col_stride( a ); f77_int ldb = bli_obj_col_stride( b ); f77_int ldc = bli_obj_col_stride( c ); double* alphap = bli_obj_buffer_for_1x1( dt, alpha ); double* ap = bli_obj_buffer( a ); double* bp = bli_obj_buffer( b ); double* betap = bli_obj_buffer_for_1x1( dt, beta ); double* cp = bli_obj_buffer( c ); dgemm_( &f77_transa, &f77_transb, &mm, &nn, &kk, alphap, ap, &lda, bp, &ldb, betap, cp, &ldc ); } else if ( bli_is_scomplex( dt ) ) { f77_int mm = bli_obj_length( c ); f77_int kk = bli_obj_width_after_trans( a ); f77_int nn = bli_obj_width( c ); f77_int lda = bli_obj_col_stride( a ); f77_int ldb = bli_obj_col_stride( b ); f77_int ldc = bli_obj_col_stride( c ); scomplex* alphap = bli_obj_buffer_for_1x1( dt, alpha ); scomplex* ap = bli_obj_buffer( a ); scomplex* bp = bli_obj_buffer( b ); scomplex* betap = bli_obj_buffer_for_1x1( dt, beta ); scomplex* cp = bli_obj_buffer( c ); cgemm_( &f77_transa, &f77_transb, &mm, &nn, &kk, alphap, ap, &lda, bp, &ldb, betap, cp, &ldc ); } else if ( bli_is_dcomplex( dt ) ) { f77_int mm = bli_obj_length( c ); f77_int kk = bli_obj_width_after_trans( a ); f77_int nn = bli_obj_width( c ); f77_int lda = bli_obj_col_stride( a ); f77_int ldb = bli_obj_col_stride( b ); f77_int ldc = bli_obj_col_stride( c ); dcomplex* alphap = bli_obj_buffer_for_1x1( dt, alpha ); dcomplex* ap = bli_obj_buffer( a ); dcomplex* bp = bli_obj_buffer( b ); dcomplex* betap = bli_obj_buffer_for_1x1( dt, beta ); dcomplex* cp = bli_obj_buffer( c ); zgemm_( &f77_transa, &f77_transb, &mm, &nn, &kk, alphap, ap, &lda, bp, &ldb, betap, cp, &ldc ); } } blis-0.9.0/test/other/000077500000000000000000000000001422157504600145575ustar00rootroot00000000000000blis-0.9.0/test/other/test_copyv.c000066400000000000000000000117731422157504600171330ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2019 - 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifdef WIN32 #include #else #include #endif #include "blis.h" //#define BLIS_ACCURACY_TEST #ifdef BLIS_ACCURACY_TEST bool_t scompare_result(int n, float *x, int incx, float *y, int incy) { for (int i = 0; i < n; i++) { if ((*x) != (*y)) { printf("%4f != %4f at location %d\n", *x, *y, i); return FALSE; } x += incx; y += incy; } return TRUE; } bool_t dcompare_result(int n, double *x, int incx, double *y, int incy) { for (int i = 0; i < n; i++) { if ((*x) != (*y)) { printf("%4f != %4f at location %d\n", *x, *y, i); return FALSE; } x += incx; y += incy; } return TRUE; } #endif int main(int argc, char** argv) { obj_t x, y; dim_t n; dim_t p; dim_t p_begin, p_end, p_inc; int n_input, sizeof_dt; int r, n_repeats; num_t dt; double dtime; double dtime_save; double Gbps; //bli_init(); n_repeats = 100000; #ifndef PRINT p_begin = 200; p_end = 100000; p_inc = 200; n_input = -1; #else p_begin = 16; p_end = 16; p_inc = 1; n_input = 16; #endif #if 1 // dt = BLIS_FLOAT; dt = BLIS_DOUBLE; #else //dt = BLIS_SCOMPLEX; dt = BLIS_DCOMPLEX; #endif if (dt == BLIS_DOUBLE) sizeof_dt = sizeof(double); else if (dt == BLIS_FLOAT) sizeof_dt = sizeof(float); printf("executable\t n\t GBs per sec\n"); for (p = p_begin; p <= p_end; p += p_inc) { if (n_input < 0) n = p * (dim_t)abs(n_input); else n = (dim_t)n_input; bli_obj_create(dt, n, 1, 0, 0, &x); bli_obj_create(dt, n, 1, 0, 0, &y); bli_randm(&x); dtime_save = DBL_MAX; for (r = 0; r < n_repeats; ++r) { dtime = bli_clock(); #ifdef BLIS bli_copyv(&x, &y ); #else if (bli_is_float(dt)) { f77_int nn = bli_obj_length(&x); f77_int incx = bli_obj_vector_inc(&x); float* xp = bli_obj_buffer(&x); f77_int incy = bli_obj_vector_inc(&y); float* yp = bli_obj_buffer(&y); scopy_(&nn, xp, &incx, yp, &incy); } else if (bli_is_double(dt)) { f77_int nn = bli_obj_length(&x); f77_int incx = bli_obj_vector_inc(&x); double* xp = bli_obj_buffer(&x); f77_int incy = bli_obj_vector_inc(&y); double* yp = bli_obj_buffer(&y); dcopy_(&nn, xp, &incx, yp, &incy ); } #endif dtime_save = bli_clock_min_diff(dtime_save, dtime); #ifdef BLIS_ACCURACY_TEST if (dt == BLIS_FLOAT) { int nn = bli_obj_length(&x); int incx = bli_obj_vector_inc(&x); float* xp = bli_obj_buffer(&x); int incy = bli_obj_vector_inc(&y); float* yp = bli_obj_buffer(&y); if (scompare_result(nn, xp, incx, yp, incy)) printf("Copy Successful\n"); else printf("ALERT!!! Copy Failed\n"); } if (dt == BLIS_DOUBLE) { int nn = bli_obj_length(&x); int incx = bli_obj_vector_inc(&x); double* xp = bli_obj_buffer(&x); int incy = bli_obj_vector_inc(&y); double* yp = bli_obj_buffer(&y); if (dcompare_result(nn, xp, incx, yp, incy)) printf("Copy Successful\n"); else printf("ALERT!!! Copy Failed\n"); } #endif } // Size of the vectors are incrementd by 1000, to test wide range of inputs. if (p >= 1000) p_inc = 1000; if (p >= 10000) p_inc = 10000; Gbps = (n * sizeof_dt) / (dtime_save * 1.0e9); #ifdef BLIS printf("data_copyv_blis\t"); #else printf("data_copyv_%s\t", BLAS); #endif printf("%4lu\t %7.2f\n", (unsigned long)n, Gbps); bli_obj_free(&x); bli_obj_free(&y); } // bli_finalize(); return 0; } blis-0.9.0/test/other/test_gemm.c000066400000000000000000000242131422157504600167110ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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 The University of Texas 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 COPYRIGHT HOLDER 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. */ #ifdef WIN32 #include #else #include #endif #include "blis.h" //#define FILE_IN_OUT //#define PRINT //#define MATRIX_INITIALISATION int main( int argc, char** argv ) { obj_t a, b, c; obj_t c_save; obj_t alpha, beta; dim_t m, n, k; dim_t p; dim_t p_begin, p_end, p_inc; int m_input, n_input, k_input; num_t dt; int r, n_repeats; trans_t transa; trans_t transb; f77_char f77_transa; f77_char f77_transb; double dtime; double dtime_save; double gflops; #ifdef FILE_IN_OUT FILE* fin = NULL; FILE* fout = NULL; char gemm = 's'; #endif //bli_init(); //bli_error_checking_level_set( BLIS_NO_ERROR_CHECKING ); n_repeats = 3; #ifndef PRINT p_begin = 200; p_end = 2000; p_inc = 200; m_input = -1; n_input = -1; k_input = -1; #else p_begin = 16; p_end = 16; p_inc = 1; m_input = 5; k_input = 6; n_input = 4; #endif #if 1 //dt = BLIS_FLOAT; dt = BLIS_DOUBLE; #else //dt = BLIS_SCOMPLEX; dt = BLIS_DCOMPLEX; #endif transa = BLIS_NO_TRANSPOSE; transb = BLIS_NO_TRANSPOSE; bli_param_map_blis_to_netlib_trans( transa, &f77_transa ); bli_param_map_blis_to_netlib_trans( transb, &f77_transb ); #ifdef FILE_IN_OUT if (argc < 3) { printf("Usage: ./test_gemm_XX.x input.csv output.csv\n"); exit(1); } fin = fopen(argv[1], "r"); if (fin == NULL) { printf("Error opening the file %s\n", argv[1]); exit(1); } fout = fopen(argv[2], "w"); if (fout == NULL) { printf("Error opening output file %s\n", argv[2]); exit(1); } fprintf(fout, "m\t k\t n\t cs_a\t cs_b\t cs_c\t gflops\t GEMM_Algo\n"); printf("~~~~~~~~~~_BLAS\t m\t k\t n\t cs_a\t cs_b\t cs_c \t gflops\t GEMM_Algo\n"); inc_t cs_a; inc_t cs_b; inc_t cs_c; while (fscanf(fin, "%lld %lld %lld %lld %lld %lld\n", &m, &k, &n, &cs_a, &cs_b, &cs_c) == 6) { if ((m > cs_a) || (k > cs_b) || (m > cs_c)) continue; // leading dimension should be greater than number of rows bli_obj_create( dt, 1, 1, 0, 0, &alpha); bli_obj_create( dt, 1, 1, 0, 0, &beta ); bli_obj_create( dt, m, k, 1, cs_a, &a ); bli_obj_create( dt, k, n, 1, cs_b, &b ); bli_obj_create( dt, m, n, 1, cs_c, &c ); bli_obj_create( dt, m, n, 1, cs_c, &c_save ); #ifdef MATRIX_INITIALISATION bli_randm( &a ); bli_randm( &b ); bli_randm( &c ); #endif bli_obj_set_conjtrans( transa, &a); bli_obj_set_conjtrans( transb, &b); //bli_setsc( 0.0, -1, &alpha ); //bli_setsc( 0.0, 1, &beta ); bli_setsc( -1, 0.0, &alpha ); bli_setsc( 1, 0.0, &beta ); #else for ( p = p_begin; p <= p_end; p += p_inc ) { if ( m_input < 0 ) m = p * ( dim_t )abs(m_input); else m = ( dim_t ) m_input; if ( n_input < 0 ) n = p * ( dim_t )abs(n_input); else n = ( dim_t ) n_input; if ( k_input < 0 ) k = p * ( dim_t )abs(k_input); else k = ( dim_t ) k_input; bli_obj_create( dt, 1, 1, 0, 0, &alpha ); bli_obj_create( dt, 1, 1, 0, 0, &beta ); bli_obj_create( dt, m, k, 0, 0, &a ); bli_obj_create( dt, k, n, 0, 0, &b ); bli_obj_create( dt, m, n, 0, 0, &c ); bli_obj_create( dt, m, n, 0, 0, &c_save ); bli_randm( &a ); bli_randm( &b ); bli_randm( &c ); bli_obj_set_conjtrans( transa, &a ); bli_obj_set_conjtrans( transb, &b ); bli_setsc( (0.9/1.0), 0.2, &alpha ); bli_setsc( -(1.1/1.0), 0.3, &beta ); #endif bli_copym( &c, &c_save ); dtime_save = DBL_MAX; for ( r = 0; r < n_repeats; ++r ) { bli_copym( &c_save, &c ); dtime = bli_clock(); #ifdef PRINT bli_printm( "a", &a, "%4.1f", "" ); bli_printm( "b", &b, "%4.1f", "" ); bli_printm( "c", &c, "%4.1f", "" ); #endif #ifdef BLIS bli_gemm( &alpha, &a, &b, &beta, &c ); #else if ( bli_is_float( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); float* alphap = bli_obj_buffer( &alpha ); float* ap = bli_obj_buffer( &a ); float* bp = bli_obj_buffer( &b ); float* betap = bli_obj_buffer( &beta ); float* cp = bli_obj_buffer( &c ); sgemm_( &f77_transa, &f77_transb, &mm, &nn, &kk, alphap, ap, &lda, bp, &ldb, betap, cp, &ldc ); } else if ( bli_is_double( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); double* alphap = bli_obj_buffer( &alpha ); double* ap = bli_obj_buffer( &a ); double* bp = bli_obj_buffer( &b ); double* betap = bli_obj_buffer( &beta ); double* cp = bli_obj_buffer( &c ); dgemm_( &f77_transa, &f77_transb, &mm, &nn, &kk, alphap, ap, &lda, bp, &ldb, betap, cp, &ldc ); } else if ( bli_is_scomplex( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); scomplex* alphap = bli_obj_buffer( &alpha ); scomplex* ap = bli_obj_buffer( &a ); scomplex* bp = bli_obj_buffer( &b ); scomplex* betap = bli_obj_buffer( &beta ); scomplex* cp = bli_obj_buffer( &c ); cgemm_( &f77_transa, &f77_transb, &mm, &nn, &kk, alphap, ap, &lda, bp, &ldb, betap, cp, &ldc ); } else if ( bli_is_dcomplex( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); dcomplex* alphap = bli_obj_buffer( &alpha ); dcomplex* ap = bli_obj_buffer( &a ); dcomplex* bp = bli_obj_buffer( &b ); dcomplex* betap = bli_obj_buffer( &beta ); dcomplex* cp = bli_obj_buffer( &c ); zgemm_( &f77_transa, &f77_transb, &mm, &nn, &kk, alphap, ap, &lda, bp, &ldb, betap, cp, &ldc ); } #endif #ifdef PRINT bli_printm( "c after", &c, "%4.1f", "" ); exit(1); #endif dtime_save = bli_clock_min_diff( dtime_save, dtime ); } gflops = ( 2.0 * m * k * n ) / ( dtime_save * 1.0e9 ); if ( bli_is_complex( dt ) ) gflops *= 4.0; #ifdef BLIS printf( "data_gemm_blis" ); #else printf( "data_gemm_%s", BLAS ); #endif #ifdef FILE_IN_OUT if ( bli_is_double( dt ) ) { if (((m * n) < (BLIS_SMALL_MATRIX_THRES * BLIS_SMALL_MATRIX_THRES/4)) || ((m < (BLIS_SMALL_M_RECT_MATRIX_THRES/2) ) && (k < (BLIS_SMALL_K_RECT_MATRIX_THRES/2) ))) gemm = 'S'; // small gemm else gemm = 'N'; // Normal blis gemm } else if (bli_is_float( dt )) { if (((m * n) < (BLIS_SMALL_MATRIX_THRES * BLIS_SMALL_MATRIX_THRES)) || ((m < BLIS_SMALL_M_RECT_MATRIX_THRES) && (k < BLIS_SMALL_K_RECT_MATRIX_THRES))) gemm = 'S'; // small gemm else gemm = 'N'; // normal blis gemm } printf("%6lu \t %4lu \t %4lu \t %4lu \t %4lu \t %4lu \t %6.3f \t %c\n", \ ( unsigned long )m, ( unsigned long )k, ( unsigned long )n, (unsigned long)cs_a, (unsigned long)cs_b, (unsigned long)cs_c, gflops, gemm ); fprintf(fout, "%6lu \t %4lu \t %4lu \t %4lu \t %4lu \t %4lu \t %6.3f \t %c\n", \ ( unsigned long )m, ( unsigned long )k, ( unsigned long )n, (unsigned long)cs_a, (unsigned long)cs_b, (unsigned long)cs_c, gflops, gemm ); fflush(fout); #else printf( "( %2lu, 1:4 ) = [ %4lu %4lu %4lu %7.2f ];\n", ( unsigned long )(p - p_begin)/p_inc + 1, ( unsigned long )m, ( unsigned long )k, ( unsigned long )n, gflops ); #endif bli_obj_free( &alpha ); bli_obj_free( &beta ); bli_obj_free( &a ); bli_obj_free( &b ); bli_obj_free( &c ); bli_obj_free( &c_save ); } //bli_finalize(); #ifdef FILE_IN_OUT fclose(fin); fclose(fout); #endif return 0; } blis-0.9.0/test/other/test_scalv.c000066400000000000000000000073511422157504600171000ustar00rootroot00000000000000/* An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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 The University of Texas at Austin 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 COPYRIGHT HOLDER 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. */ #ifdef WIN32 #include #else #include #endif #include "blis.h" //#define PRINT int main(int argc, char** argv) { obj_t a, alpha; dim_t n, p; dim_t p_begin, p_end, p_inc; int n_input; num_t dt; int r, n_repeats; double dtime; double dtime_save; double gflops; //bli_init(); //bli_error_checking_level_set( BLIS_NO_ERROR_CHECKING ); n_repeats = 100000; #ifndef PRINT p_begin = 200; p_end = 100000; p_inc = 200; n_input = -1; #else p_begin = 16; p_end = 16; p_inc = 1; n_input = 4; #endif #if 1 dt = BLIS_FLOAT; //dt = BLIS_DOUBLE; #else //dt = BLIS_SCOMPLEX; dt = BLIS_DCOMPLEX; #endif #ifdef BLIS printf( "data_scalv_blis\t n\t gflops\n" ); #else printf( "data_scalv_%s\t n\t gflops\n", BLAS ); #endif for (p = p_begin; p <= p_end; p += p_inc) { if (n_input < 0) n = p * (dim_t)abs(n_input); else n = (dim_t)n_input; bli_obj_create(dt, 1, 1, 0, 0, &alpha); bli_obj_create(dt, 1, n, 0, 0, &a); bli_randm(&a); bli_setsc((2.0), 0.0, &alpha); dtime_save = DBL_MAX; for (r = 0; r < n_repeats; ++r) { dtime = bli_clock(); #ifdef BLIS bli_scalm(&BLIS_TWO, &a); #else if ( bli_is_float( dt ) ) { f77_int nn = bli_obj_length( &a ); f77_int inca = bli_obj_vector_inc( &a ); float* scalar = bli_obj_buffer( &alpha ); float* ap = bli_obj_buffer( &a ); sscal_( &nn, scalar, ap, &inca ); } else if ( bli_is_double( dt ) ) { f77_int nn = bli_obj_length( &a ); f77_int inca = bli_obj_vector_inc( &a ); double* scalar = bli_obj_buffer( &alpha ); double* ap = bli_obj_buffer( &a ); dscal_( &nn, scalar, ap, &inca ); } #endif dtime_save = bli_clock_min_diff(dtime_save, dtime); } // Size of the vectors are incrementd by 1000, to test wide range of inputs. if (p == 10000) p_inc = 10000; if (p == 1000) p_inc = 1000; gflops = n / (dtime_save * 1.0e9); #ifdef BLIS printf( "data_scalv_blis\t" ); #else printf( "data_scalv_%s\t", BLAS ); #endif printf(" %4lu\t %7.2f \n", (unsigned long)n, gflops); bli_obj_free(&alpha); bli_obj_free(&a); } return 0; } blis-0.9.0/test/other/test_swapv.c000066400000000000000000000120211422157504600171160ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifdef WIN32 #include #else #include #endif #include "blis.h" // n x incx y incy //void dswap_( int*, double*, int*, double*, int* ); //#define PRINT int main( int argc, char** argv ) { obj_t x, y; dim_t n; dim_t p; dim_t p_begin, p_end, p_inc; int n_input; int r, n_repeats; num_t dt; double dtime; double dtime_save; double gflops; bli_init(); n_repeats = 3; #ifndef PRINT p_begin = 40; p_end = 8000; p_inc = 40; n_input = -1; #else p_begin = 16; p_end = 16; p_inc = 1; n_input = -1; #endif #if 1 dt = BLIS_FLOAT; //dt = BLIS_DOUBLE; #else //dt = BLIS_SCOMPLEX; dt = BLIS_DCOMPLEX; #endif // Begin with initializing the last entry to zero so that // matlab allocates space for the entire array once up-front. for ( p = p_begin; p + p_inc <= p_end; p += p_inc ) ; #ifdef BLIS printf( "data_swapv_blis" ); #else printf( "data_swapv_%s", BLAS ); #endif printf( "( %2lu, 1:2 ) = [ %4lu %7.2f ];\n", ( unsigned long )(p - p_begin)/p_inc + 1, ( unsigned long )0, 0.0 ); //for ( p = p_begin; p <= p_end; p += p_inc ) for ( p = p_end; p_begin <= p; p -= p_inc ) { if ( n_input < 0 ) n = p * ( dim_t )abs(n_input); else n = ( dim_t ) n_input; bli_obj_create( dt, n, 1, 0, 0, &x ); bli_obj_create( dt, n, 1, 0, 0, &y ); bli_randm( &x ); bli_randm( &y ); dtime_save = 1.0e9; for ( r = 0; r < n_repeats; ++r ) { dtime = bli_clock(); #ifdef PRINT bli_printm( "x", &x, "%4.1f", "" ); bli_printm( "y", &y, "%4.1f", "" ); #endif #ifdef BLIS bli_swapv( &x, &y ); #else if ( bli_is_float( dt ) ) { f77_int nn = bli_obj_length( &x ); f77_int incx = bli_obj_vector_inc( &x ); f77_int incy = bli_obj_vector_inc( &y ); float* xp = bli_obj_buffer( &x ); float* yp = bli_obj_buffer( &y ); sswap_( &nn, xp, &incx, yp, &incy ); } else if ( bli_is_double( dt ) ) { f77_int nn = bli_obj_length( &x ); f77_int incx = bli_obj_vector_inc( &x ); f77_int incy = bli_obj_vector_inc( &y ); double* xp = bli_obj_buffer( &x ); double* yp = bli_obj_buffer( &y ); dswap_( &nn, xp, &incx, yp, &incy ); } #endif #ifdef PRINT bli_printm( "X after", &x, "%4.1f", "" ); bli_printm( "Y after", &y, "%4.1f", "" ); exit(1); #endif dtime_save = bli_clock_min_diff( dtime_save, dtime ); } gflops = ( n ) / ( dtime_save * 1.0e9 ); #ifdef BLIS printf( "data_swapv_blis" ); #else printf( "data_swapv_%s", BLAS ); #endif printf( "( %2lu, 1:2 ) = [ %4lu %7.2f ];\n", ( unsigned long )(p - p_begin)/p_inc + 1, ( unsigned long )n, gflops ); bli_obj_free( &x ); bli_obj_free( &y ); } bli_finalize(); return 0; } blis-0.9.0/test/other/test_trsm.c000066400000000000000000000255521422157504600167600ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifdef WIN32 #include #else #include #endif #include "blis.h" //#define FILE_IN_OUT #ifdef FILE_IN_OUT //#define READ_ALL_PARAMS_FROM_FILE #endif //#define PRINT int main( int argc, char** argv ) { obj_t a, c; obj_t c_save; obj_t alpha; dim_t m, n; num_t dt; int r, n_repeats; side_t side; uplo_t uploa; trans_t transa; diag_t diaga; f77_char f77_side; f77_char f77_uploa; f77_char f77_transa; f77_char f77_diaga; double dtime; double dtime_save; double gflops; #ifdef FILE_IN_OUT FILE* fin = NULL; FILE* fout = NULL; #else dim_t p; dim_t p_begin, p_end, p_inc; int m_input, n_input; //bli_init(); //bli_error_checking_level_set( BLIS_NO_ERROR_CHECKING ); #ifndef PRINT p_begin = 200; p_end = 2000; p_inc = 200; m_input = -1; n_input = -1; #else p_begin = 16; p_end = 16; p_inc = 1; m_input = 4; n_input = 4; #endif #endif n_repeats = 3; #if 1 //dt = BLIS_FLOAT; dt = BLIS_DOUBLE; #else //dt = BLIS_SCOMPLEX; dt = BLIS_DCOMPLEX; #endif #ifdef FILE_IN_OUT if(argc < 3) { printf("Usage: ./test_trsm_XX.x input.csv output.csv\n"); exit(1); } fin = fopen(argv[1], "r"); if(fin == NULL) { printf("Error opening the file %s\n", argv[1]); exit(1); } fout = fopen(argv[2], "w"); if(fout == NULL) { printf("Error opening the file %s\n", argv[2]); exit(1); } inc_t cs_a; inc_t cs_b; #ifdef READ_ALL_PARAMS_FROM_FILE char side_c, uploa_c, transa_c, diaga_c; fprintf(fout, "side, uploa, transa, diaga, m\t n\t cs_a\t cs_b\t gflops\n"); printf("~~~~~~~_BLAS\t side, uploa, transa, diaga, m\t n\t cs_a\t cs_b\t gflops\n"); while(fscanf(fin, "%c %c %c %c %ld %ld %ld %ld\n", &side_c, &uploa_c, &transa_c, &diaga_c, &m, &n, &cs_a, &cs_b) == 8) { if( 'l' == side_c|| 'L' == side_c) side = BLIS_LEFT; else if('r' == side_c || 'R' == side_c) side = BLIS_RIGHT; else { printf("Invalid entry for the argument 'side':%c\n",side_c); continue; } if('l' == uploa_c || 'L' == uploa_c) uploa = BLIS_LOWER; else if('u' == uploa_c || 'U' == uploa_c) uploa = BLIS_UPPER; else { printf("Invalid entry for the argument 'uplo':%c\n",uploa_c); continue; } if('t' == transa_c || 'T' == transa_c) transa = BLIS_TRANSPOSE; else if('n' == transa_c || 'N' == transa_c) transa = BLIS_NO_TRANSPOSE; else { printf("Invalid entry for the argument 'transa':%c\n",transa_c); continue; } if('u' == diaga_c || 'U' == diaga_c) diaga = BLIS_UNIT_DIAG; else if('n' == diaga_c || 'N' == diaga_c) diaga = BLIS_NONUNIT_DIAG; else { printf("Invalid entry for the argument 'diaga':%c\n", diaga_c); continue; } #else fprintf(fout, "m\t n\t cs_a\t cs_b\t gflops\n"); printf("~~~~~~~_BLAS\t m\t n\t cs_a\t cs_b\t gflops\n"); while(fscanf(fin, "%ld %ld %ld %ld\n", &m, &n, &cs_a, &cs_b) == 4) { side = BLIS_LEFT; //side = BLIS_RIGHT; uploa = BLIS_LOWER; //uploa = BLIS_UPPER; transa = BLIS_NO_TRANSPOSE; diaga = BLIS_NONUNIT_DIAG; #endif bli_param_map_blis_to_netlib_side( side, &f77_side ); bli_param_map_blis_to_netlib_uplo( uploa, &f77_uploa ); bli_param_map_blis_to_netlib_trans( transa, &f77_transa ); bli_param_map_blis_to_netlib_diag( diaga, &f77_diaga ); if(bli_is_left(side) && ((m > cs_a) || (m > cs_b))) continue; //leading dimension should be greater than number of rows if(bli_is_right(side) && ((n > cs_a) || (m > cs_b))) continue; //leading dimension should be greater than number of rows if ( bli_is_left( side ) ) bli_obj_create( dt, m, m, 1, m, &a ); else bli_obj_create( dt, n, n, 1, n, &a ); bli_obj_create( dt, m, n, 1, m, &c ); bli_obj_create( dt, m, n, 1, m, &c_save ); #else for ( p = p_end; p >= p_begin; p -= p_inc ) { if ( m_input < 0 ) m = p * ( dim_t )abs(m_input); else m = ( dim_t ) m_input; if ( n_input < 0 ) n = p * ( dim_t )abs(n_input); else n = ( dim_t ) n_input; side = BLIS_LEFT; //side = BLIS_RIGHT; uploa = BLIS_LOWER; //uploa = BLIS_UPPER; transa = BLIS_NO_TRANSPOSE; diaga = BLIS_NONUNIT_DIAG; bli_param_map_blis_to_netlib_side( side, &f77_side ); bli_param_map_blis_to_netlib_uplo( uploa, &f77_uploa ); bli_param_map_blis_to_netlib_trans( transa, &f77_transa ); bli_param_map_blis_to_netlib_diag( diaga, &f77_diaga ); if ( bli_is_left( side ) ) bli_obj_create( dt, m, m, 0, 0, &a ); else bli_obj_create( dt, n, n, 0, 0, &a ); bli_obj_create( dt, m, n, 0, 0, &c ); bli_obj_create( dt, m, n, 0, 0, &c_save ); #endif bli_randm( &a ); bli_randm( &c ); bli_obj_set_struc( BLIS_TRIANGULAR, &a ); bli_obj_set_uplo( uploa, &a ); bli_obj_set_conjtrans( transa, &a ); bli_obj_set_diag( diaga, &a ); // Randomize A and zero the unstored triangle to ensure the // implementation reads only from the stored region. bli_randm( &a ); bli_mktrim( &a ); // Load the diagonal of A to make it more likely to be invertible. bli_shiftd( &BLIS_TWO, &a ); bli_obj_create( dt, 1, 1, 0, 0, &alpha ); bli_setsc( (2.0/1.0), 1.0, &alpha ); bli_copym( &c, &c_save ); dtime_save = DBL_MAX; for ( r = 0; r < n_repeats; ++r ) { bli_copym( &c_save, &c ); dtime = bli_clock(); #ifdef PRINT bli_invertd( &a ); bli_printm( "a", &a, "%4.1f", "" ); bli_invertd( &a ); bli_printm( "c", &c, "%4.1f", "" ); #endif #ifdef BLIS bli_trsm( side, &alpha, &a, &c ); #else if ( bli_is_float( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldc = bli_obj_col_stride( &c ); float* alphap = bli_obj_buffer( &alpha ); float* ap = bli_obj_buffer( &a ); float* cp = bli_obj_buffer( &c ); strsm_( &f77_side, &f77_uploa, &f77_transa, &f77_diaga, &mm, &nn, alphap, ap, &lda, cp, &ldc ); } else if ( bli_is_double( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldc = bli_obj_col_stride( &c ); double* alphap = bli_obj_buffer( &alpha ); double* ap = bli_obj_buffer( &a ); double* cp = bli_obj_buffer( &c ); dtrsm_( &f77_side, &f77_uploa, &f77_transa, &f77_diaga, &mm, &nn, alphap, ap, &lda, cp, &ldc ); } else if ( bli_is_scomplex( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldc = bli_obj_col_stride( &c ); scomplex* alphap = bli_obj_buffer( &alpha ); scomplex* ap = bli_obj_buffer( &a ); scomplex* cp = bli_obj_buffer( &c ); ctrsm_( &f77_side, &f77_uploa, &f77_transa, &f77_diaga, &mm, &nn, alphap, ap, &lda, cp, &ldc ); } else if ( bli_is_dcomplex( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldc = bli_obj_col_stride( &c ); dcomplex* alphap = bli_obj_buffer( &alpha ); dcomplex* ap = bli_obj_buffer( &a ); dcomplex* cp = bli_obj_buffer( &c ); ztrsm_( &f77_side, &f77_uploa, &f77_transa, &f77_diaga, &mm, &nn, alphap, ap, &lda, cp, &ldc ); } #endif #ifdef PRINT bli_printm( "c after", &c, "%9.5f", "" ); exit(1); #endif dtime_save = bli_clock_min_diff( dtime_save, dtime ); } if ( bli_is_left( side ) ) gflops = ( 1.0 * m * m * n ) / ( dtime_save * 1.0e9 ); else gflops = ( 1.0 * m * n * n ) / ( dtime_save * 1.0e9 ); if ( bli_is_complex( dt ) ) gflops *= 4.0; #ifdef BLIS printf( "data_trsm_blis" ); #else printf( "data_trsm_%s", BLAS ); #endif #ifdef FILE_IN_OUT #ifdef READ_ALL_PARAMS_FROM_FILE printf("%c\t %c\t %c\t %c\t %4lu\t %4lu\t %4lu\t %4lu\t %6.3f\n",side_c, uploa_c, transa_c, diaga_c, (unsigned long )m, (unsigned long ) n, (unsigned long )cs_a, (unsigned long )cs_b, gflops); fprintf(fout,"%c\t %c\t %c\t %c\t %4lu\t %4lu\t %4lu\t %4lu\t %6.3f\n", side_c, uploa_c, transa_c, diaga_c, (unsigned long )m, (unsigned long ) n, (unsigned long )cs_a, (unsigned long )cs_b, gflops); #else printf("%4lu\t %4lu\t %4lu\t %4lu\t %6.3f\n", (unsigned long )m, (unsigned long ) n, (unsigned long )cs_a, (unsigned long )cs_b, gflops); fprintf(fout,"%4lu\t %4lu\t %4lu\t %4lu\t %6.3f\n", (unsigned long )m, (unsigned long ) n, (unsigned long )cs_a, (unsigned long )cs_b, gflops); #endif fflush(fout); #else printf( "( %2lu, 1:3 ) = [ %4lu %4lu %7.2f ];\n", ( unsigned long )(p - p_begin)/p_inc + 1, ( unsigned long )m, ( unsigned long )n, gflops ); #endif bli_obj_free( &alpha ); bli_obj_free( &a ); bli_obj_free( &c ); bli_obj_free( &c_save ); } #ifdef FILE_IN_OUT fclose(fin); fclose(fout); #endif //bli_finalize(); return 0; } blis-0.9.0/test/runme.sh000077500000000000000000000011751422157504600151270ustar00rootroot00000000000000#!/bin/bash exec_root="test" out_root="output" #out_root="output_square" # Operations to test. l2_ops="gemv ger hemv her her2 trmv trsv" l3_ops="gemm hemm herk her2k trmm trsm" test_ops="${l2_ops} ${l3_ops}" # Implementations to test. #test_impls="openblas mkl blis" test_impls="blis" for im in ${test_impls}; do for op in ${test_ops}; do # Construct the name of the test executable. exec_name="${exec_root}_${op}_${im}.x" # Construct the name of the output file. out_file="${out_root}_${op}_${im}.m" echo "Running ${exec_name} > ${out_file}" # Run executable. ./${exec_name} > ${out_file} sleep 1 done done blis-0.9.0/test/studies/000077500000000000000000000000001422157504600151165ustar00rootroot00000000000000blis-0.9.0/test/studies/skx/000077500000000000000000000000001422157504600157235ustar00rootroot00000000000000blis-0.9.0/test/studies/skx/Makefile000066400000000000000000000504721422157504600173730ustar00rootroot00000000000000#!/bin/bash # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2014, The University of Texas at Austin # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # # # Makefile # # Field G. Van Zee # # Makefile for standalone BLIS test drivers. # # # --- Makefile PHONY target definitions ---------------------------------------- # .PHONY: all \ blis-gemm-st openblas-gemm-st mkl-gemm-st acml-gemm-st \ blis-gemm-mt openblas-gemm-mt mkl-gemm-mt acml-gemm-mt \ blis-syrk-st openblas-syrk-st mkl-syrk-st armpl-syrk-st \ blis-syrk-mt openblas-syrk-mt mkl-syrk-mt armpl-syrk-mt \ blis-hemm-st openblas-hemm-st mkl-hemm-st armpl-hemm-st \ blis-hemm-mt openblas-hemm-mt mkl-hemm-mt armpl-hemm-mt \ blis-trmm-st openblas-trmm-st mkl-trmm-st armpl-trmm-st \ blis-trmm-mt openblas-trmm-mt mkl-trmm-mt armpl-trmm-mt \ clean cleanx # Comments: # - DIST_PATH is assumed to not exist if BLIS_INSTALL_PATH is given. # - We must use recursively expanded assignment for LIB_PATH and INC_PATH in # the second case because CONFIG_NAME is not yet set. ifneq ($(strip $(BLIS_INSTALL_PATH)),) LIB_PATH := $(BLIS_INSTALL_PATH)/lib INC_PATH := $(BLIS_INSTALL_PATH)/include/blis SHARE_PATH := $(BLIS_INSTALL_PATH)/share/blis else DIST_PATH := ../../.. LIB_PATH = ../../../lib/$(CONFIG_NAME) INC_PATH = ../../../include/$(CONFIG_NAME) SHARE_PATH := ../../.. endif # # --- Include common makefile definitions -------------------------------------- # # Include the common makefile fragment. -include $(SHARE_PATH)/common.mk # # --- BLAS and LAPACK implementations ------------------------------------------ # # BLIS library and header path. This is simply wherever it was installed. #BLIS_LIB_PATH := $(INSTALL_PREFIX)/lib BLIS_INC_PATH := $(INSTALL_PREFIX)/include/blis # BLIS library. #BLIS_LIB := $(BLIS_LIB_PATH)/libblis.a # BLAS library path(s). This is where the BLAS libraries reside. HOME_LIB_PATH := $(HOME)/OpenBLAS/lib #MKL_LIB_PATH := /opt/apps/intel/13/composer_xe_2013.2.146/mkl/lib/intel64 #MKL_LIB_PATH := $(HOME)/intel/mkl/lib/intel64 MKL_LIB_PATH := ${MKLROOT}/lib/intel64 ARMPL_LIB_PATH := /opt/arm/armpl-18.3.0_Cortex-A57_Ubuntu-16.04_gcc_7.1.0_aarch64-linux/lib #ICC_LIB_PATH := /opt/apps/intel/13/composer_xe_2013.2.146/compiler/lib/intel64 ACML_LIB_PATH := $(HOME_LIB_PATH)/acml/5.3.1/gfortran64_fma4_int64/lib ACMLP_LIB_PATH := $(HOME_LIB_PATH)/acml/5.3.1/gfortran64_fma4_mp_int64/lib # OpenBLAS OPENBLAS_LIB := $(HOME_LIB_PATH)/libopenblas.a OPENBLASP_LIB := $(HOME_LIB_PATH)/libopenblas.a # ATLAS ATLAS_LIB := $(HOME_LIB_PATH)/libf77blas.a \ $(HOME_LIB_PATH)/libatlas.a # For ARMPL ARMPL_LIB := $(ARMPL_LIB_PATH)/libarmpl_lp64.a ARMPLP_LIB := $(ARMPL_LIB_PATH)/libarmpl_lp64_mp.a # MKL MKL_LIB := -L$(MKL_LIB_PATH) \ -lmkl_intel_lp64 \ -lmkl_core \ -lmkl_sequential \ -lpthread -lm -ldl #MKLP_LIB := -L$(MKL_LIB_PATH) \ # -lmkl_intel_thread \ # -lmkl_core \ # -lmkl_intel_ilp64 \ # -L$(ICC_LIB_PATH) \ # -liomp5 MKLP_LIB := -L$(MKL_LIB_PATH) \ -lmkl_intel_lp64 \ -lmkl_core \ -lmkl_gnu_thread \ -lpthread -lm -ldl -fopenmp #-L$(ICC_LIB_PATH) \ #-lgomp # ACML ACML_LIB := -L$(ACML_LIB_PATH) \ -lgfortran -lm -lrt -ldl -lacml ACMLP_LIB := -L$(ACMLP_LIB_PATH) \ -lgfortran -lm -lrt -ldl -lacml_mp # # --- General build definitions ------------------------------------------------ # TEST_SRC_PATH := . TEST_OBJ_PATH := . # Gather all local object files. TEST_OBJS := $(sort $(patsubst $(TEST_SRC_PATH)/%.c, \ $(TEST_OBJ_PATH)/%.o, \ $(wildcard $(TEST_SRC_PATH)/*.c))) # Override the value of CINCFLAGS so that the value of CFLAGS returned by # get-user-cflags-for() is not cluttered up with include paths needed only # while building BLIS. CINCFLAGS := -I$(INC_PATH) # Use the "framework" CFLAGS for the configuration family. CFLAGS := $(call get-user-cflags-for,$(CONFIG_NAME)) # Add local header paths to CFLAGS. CFLAGS += -g -I$(TEST_SRC_PATH) # Locate the libblis library to which we will link. #LIBBLIS_LINK := $(LIB_PATH)/$(LIBBLIS_L) # Datatype DT_S := -DDT=BLIS_FLOAT DT_D := -DDT=BLIS_DOUBLE DT_C := -DDT=BLIS_SCOMPLEX DT_Z := -DDT=BLIS_DCOMPLEX # Which library? BLI_DEF := -DBLIS BLA_DEF := -DBLAS # Complex implementation type D3MHW := -DIND=BLIS_3MH D3M1 := -DIND=BLIS_3M1 D4MHW := -DIND=BLIS_4MH D4M1B := -DIND=BLIS_4M1B D4M1A := -DIND=BLIS_4M1A D1M := -DIND=BLIS_1M DNAT := -DIND=BLIS_NAT # Implementation string STR_3MHW := -DSTR=\"3mhw\" STR_3M1 := -DSTR=\"3m1\" STR_4MHW := -DSTR=\"4mhw\" STR_4M1B := -DSTR=\"4m1b\" STR_4M1A := -DSTR=\"4m1a\" STR_1M := -DSTR=\"1m\" STR_NAT := -DSTR=\"asm\" STR_OBL := -DSTR=\"openblas\" STR_MKL := -DSTR=\"mkl\" STR_ACML := -DSTR=\"acml\" STR_ARMPL:= -DSTR=\"armpl\" # Single or multithreaded string STR_ST := -DTHR_STR=\"st\" STR_MT := -DTHR_STR=\"mt\" # Problem size specification PDEF_ST := -DP_BEGIN=40 \ -DP_END=2000 \ -DP_INC=40 PDEF_MT := -DP_BEGIN=200 \ -DP_END=5000 \ -DP_INC=200 # # --- Targets/rules ------------------------------------------------------------ # all-st: blis-st openblas-st mkl-st all-mt: blis-mt openblas-mt mkl-mt blis-st: blis-gemm-st blis-syrk-st blis-hemm-st blis-trmm-st blis-mt: blis-gemm-mt blis-syrk-mt blis-hemm-mt blis-trmm-mt openblas-st: openblas-gemm-st openblas-syrk-st openblas-hemm-st openblas-trmm-st openblas-mt: openblas-gemm-mt openblas-syrk-mt openblas-hemm-mt openblas-trmm-mt mkl-st: mkl-gemm-st mkl-syrk-st mkl-hemm-st mkl-trmm-st mkl-mt: mkl-gemm-mt mkl-syrk-mt mkl-hemm-mt mkl-trmm-mt armpl-st: armpl-gemm-st armpl-syrk-st armpl-hemm-st armpl-trmm-st armpl-mt: armpl-gemm-mt armpl-syrk-mt armpl-hemm-mt armpl-trmm-mt blis-gemm-st: \ test_sgemm_asm_blis_st.x \ test_dgemm_asm_blis_st.x \ \ test_cgemm_1m_blis_st.x \ test_zgemm_1m_blis_st.x \ test_cgemm_asm_blis_st.x \ test_zgemm_asm_blis_st.x blis-syrk-st: \ test_ssyrk_asm_blis_st.x \ test_dsyrk_asm_blis_st.x \ test_csyrk_1m_blis_st.x \ test_zsyrk_1m_blis_st.x blis-syrk-mt: \ test_ssyrk_asm_blis_mt.x \ test_dsyrk_asm_blis_mt.x \ test_csyrk_1m_blis_mt.x \ test_zsyrk_1m_blis_mt.x blis-hemm-st: \ test_shemm_asm_blis_st.x \ test_dhemm_asm_blis_st.x \ test_chemm_1m_blis_st.x \ test_zhemm_1m_blis_st.x blis-hemm-mt: \ test_shemm_asm_blis_mt.x \ test_dhemm_asm_blis_mt.x \ test_chemm_1m_blis_mt.x \ test_zhemm_1m_blis_mt.x blis-trmm-st: \ test_strmm_asm_blis_st.x \ test_dtrmm_asm_blis_st.x \ test_ctrmm_1m_blis_st.x \ test_ztrmm_1m_blis_st.x blis-trmm-mt: \ test_strmm_asm_blis_mt.x \ test_dtrmm_asm_blis_mt.x \ test_ctrmm_1m_blis_mt.x \ test_ztrmm_1m_blis_mt.x blis-gemm-mt: \ test_sgemm_asm_blis_mt.x \ test_dgemm_asm_blis_mt.x \ \ test_cgemm_1m_blis_mt.x \ test_zgemm_1m_blis_mt.x \ test_cgemm_asm_blis_mt.x \ test_zgemm_asm_blis_mt.x openblas-gemm-st: \ test_sgemm_openblas_st.x \ test_dgemm_openblas_st.x \ test_cgemm_openblas_st.x \ test_zgemm_openblas_st.x openblas-gemm-mt: \ test_sgemm_openblas_mt.x \ test_dgemm_openblas_mt.x \ test_cgemm_openblas_mt.x \ test_zgemm_openblas_mt.x openblas-syrk-st: \ test_ssyrk_openblas_st.x \ test_dsyrk_openblas_st.x \ test_csyrk_openblas_st.x \ test_zsyrk_openblas_st.x openblas-syrk-mt: \ test_ssyrk_openblas_mt.x \ test_dsyrk_openblas_mt.x \ test_csyrk_openblas_mt.x \ test_zsyrk_openblas_mt.x openblas-hemm-st: \ test_shemm_openblas_st.x \ test_dhemm_openblas_st.x \ test_chemm_openblas_st.x \ test_zhemm_openblas_st.x openblas-hemm-mt: \ test_shemm_openblas_mt.x \ test_dhemm_openblas_mt.x \ test_chemm_openblas_mt.x \ test_zhemm_openblas_mt.x openblas-trmm-st: \ test_strmm_openblas_st.x \ test_dtrmm_openblas_st.x \ test_ctrmm_openblas_st.x \ test_ztrmm_openblas_st.x openblas-trmm-mt: \ test_strmm_openblas_mt.x \ test_dtrmm_openblas_mt.x \ test_ctrmm_openblas_mt.x \ test_ztrmm_openblas_mt.x mkl-gemm-st: \ test_sgemm_mkl_st.x \ test_dgemm_mkl_st.x \ test_cgemm_mkl_st.x \ test_zgemm_mkl_st.x mkl-gemm-mt: \ test_sgemm_mkl_mt.x \ test_dgemm_mkl_mt.x \ test_cgemm_mkl_mt.x \ test_zgemm_mkl_mt.x mkl-syrk-st: \ test_ssyrk_mkl_st.x \ test_dsyrk_mkl_st.x \ test_csyrk_mkl_st.x \ test_zsyrk_mkl_st.x mkl-syrk-mt: \ test_ssyrk_mkl_mt.x \ test_dsyrk_mkl_mt.x \ test_csyrk_mkl_mt.x \ test_zsyrk_mkl_mt.x mkl-hemm-st: \ test_shemm_mkl_st.x \ test_dhemm_mkl_st.x \ test_chemm_mkl_st.x \ test_zhemm_mkl_st.x mkl-hemm-mt: \ test_shemm_mkl_mt.x \ test_dhemm_mkl_mt.x \ test_chemm_mkl_mt.x \ test_zhemm_mkl_mt.x mkl-trmm-st: \ test_strmm_mkl_st.x \ test_dtrmm_mkl_st.x \ test_ctrmm_mkl_st.x \ test_ztrmm_mkl_st.x mkl-trmm-mt: \ test_strmm_mkl_mt.x \ test_dtrmm_mkl_mt.x \ test_ctrmm_mkl_mt.x \ test_ztrmm_mkl_mt.x armpl-gemm-st: \ test_sgemm_armpl_st.x \ test_dgemm_armpl_st.x \ test_cgemm_armpl_st.x \ test_zgemm_armpl_st.x armpl-gemm-mt: \ test_sgemm_armpl_mt.x \ test_dgemm_armpl_mt.x \ test_cgemm_armpl_mt.x \ test_zgemm_armpl_mt.x armpl-syrk-st: \ test_ssyrk_armpl_st.x \ test_dsyrk_armpl_st.x \ test_csyrk_armpl_st.x \ test_zsyrk_armpl_st.x armpl-syrk-mt: \ test_ssyrk_armpl_mt.x \ test_dsyrk_armpl_mt.x \ test_csyrk_armpl_mt.x \ test_zsyrk_armpl_mt.x armpl-hemm-st: \ test_shemm_armpl_st.x \ test_dhemm_armpl_st.x \ test_chemm_armpl_st.x \ test_zhemm_armpl_st.x armpl-hemm-mt: \ test_shemm_armpl_mt.x \ test_dhemm_armpl_mt.x \ test_chemm_armpl_mt.x \ test_zhemm_armpl_mt.x armpl-trmm-st: \ test_strmm_armpl_st.x \ test_dtrmm_armpl_st.x \ test_ctrmm_armpl_st.x \ test_ztrmm_armpl_st.x armpl-trmm-mt: \ test_strmm_armpl_mt.x \ test_dtrmm_armpl_mt.x \ test_ctrmm_armpl_mt.x \ test_ztrmm_armpl_mt.x # --Object file rules -- $(TEST_OBJ_PATH)/%.o: $(TEST_SRC_PATH)/%.c $(CC) $(CFLAGS) -c $< -o $@ # blis 3mhw test_z%_3mhw_blis_st.o: test_%.c $(CC) $(CFLAGS) $(PDEF_ST) $(DT_Z) $(BLI_DEF) $(D3MHW) $(STR_3MHW) $(STR_ST) -c $< -o $@ test_c%_3mhw_blis_st.o: test_%.c $(CC) $(CFLAGS) $(PDEF_ST) $(DT_C) $(BLI_DEF) $(D3MHW) $(STR_3MHW) $(STR_ST) -c $< -o $@ test_z%_3mhw_blis_mt.o: test_%.c $(CC) $(CFLAGS) $(PDEF_MT) $(DT_Z) $(BLI_DEF) $(D3MHW) $(STR_3MHW) $(STR_MT) -c $< -o $@ test_c%_3mhw_blis_mt.o: test_%.c $(CC) $(CFLAGS) $(PDEF_MT) $(DT_C) $(BLI_DEF) $(D3MHW) $(STR_3MHW) $(STR_MT) -c $< -o $@ # blis 3m1 test_z%_3m1_blis_st.o: test_%.c $(CC) $(CFLAGS) $(PDEF_ST) $(DT_Z) $(BLI_DEF) $(D3M1) $(STR_3M1) $(STR_ST) -c $< -o $@ test_c%_3m1_blis_st.o: test_%.c $(CC) $(CFLAGS) $(PDEF_ST) $(DT_C) $(BLI_DEF) $(D3M1) $(STR_3M1) $(STR_ST) -c $< -o $@ test_z%_3m1_blis_mt.o: test_%.c $(CC) $(CFLAGS) $(PDEF_MT) $(DT_Z) $(BLI_DEF) $(D3M1) $(STR_3M1) $(STR_MT) -c $< -o $@ test_c%_3m1_blis_mt.o: test_%.c $(CC) $(CFLAGS) $(PDEF_MT) $(DT_C) $(BLI_DEF) $(D3M1) $(STR_3M1) $(STR_MT) -c $< -o $@ # blis 4mhw test_z%_4mhw_blis_st.o: test_%.c $(CC) $(CFLAGS) $(PDEF_ST) $(DT_Z) $(BLI_DEF) $(D4MHW) $(STR_4MHW) $(STR_ST) -c $< -o $@ test_c%_4mhw_blis_st.o: test_%.c $(CC) $(CFLAGS) $(PDEF_ST) $(DT_C) $(BLI_DEF) $(D4MHW) $(STR_4MHW) $(STR_ST) -c $< -o $@ test_z%_4mhw_blis_mt.o: test_%.c $(CC) $(CFLAGS) $(PDEF_MT) $(DT_Z) $(BLI_DEF) $(D4MHW) $(STR_4MHW) $(STR_MT) -c $< -o $@ test_c%_4mhw_blis_mt.o: test_%.c $(CC) $(CFLAGS) $(PDEF_MT) $(DT_C) $(BLI_DEF) $(D4MHW) $(STR_4MHW) $(STR_MT) -c $< -o $@ # blis 4m1b test_z%_4m1b_blis_st.o: test_%.c $(CC) $(CFLAGS) $(PDEF_ST) $(DT_Z) $(BLI_DEF) $(D4M1B) $(STR_4M1B) $(STR_ST) -c $< -o $@ test_c%_4m1b_blis_st.o: test_%.c $(CC) $(CFLAGS) $(PDEF_ST) $(DT_C) $(BLI_DEF) $(D4M1B) $(STR_4M1B) $(STR_ST) -c $< -o $@ test_z%_4m1b_blis_mt.o: test_%.c $(CC) $(CFLAGS) $(PDEF_MT) $(DT_Z) $(BLI_DEF) $(D4M1B) $(STR_4M1B) $(STR_MT) -c $< -o $@ test_c%_4m1b_blis_mt.o: test_%.c $(CC) $(CFLAGS) $(PDEF_MT) $(DT_C) $(BLI_DEF) $(D4M1B) $(STR_4M1B) $(STR_MT) -c $< -o $@ # blis 4m1a test_z%_4m1a_blis_st.o: test_%.c $(CC) $(CFLAGS) $(PDEF_ST) $(DT_Z) $(BLI_DEF) $(D4M1A) $(STR_4M1A) $(STR_ST) -c $< -o $@ test_c%_4m1a_blis_st.o: test_%.c $(CC) $(CFLAGS) $(PDEF_ST) $(DT_C) $(BLI_DEF) $(D4M1A) $(STR_4M1A) $(STR_ST) -c $< -o $@ test_z%_4m1a_blis_mt.o: test_%.c $(CC) $(CFLAGS) $(PDEF_MT) $(DT_Z) $(BLI_DEF) $(D4M1A) $(STR_4M1A) $(STR_MT) -c $< -o $@ test_c%_4m1a_blis_mt.o: test_%.c $(CC) $(CFLAGS) $(PDEF_MT) $(DT_C) $(BLI_DEF) $(D4M1A) $(STR_4M1A) $(STR_MT) -c $< -o $@ # blis 1m test_z%_1m_blis_st.o: test_%.c $(CC) $(CFLAGS) $(PDEF_ST) $(DT_Z) $(BLI_DEF) $(D1M) $(STR_1M) $(STR_ST) -c $< -o $@ test_c%_1m_blis_st.o: test_%.c $(CC) $(CFLAGS) $(PDEF_ST) $(DT_C) $(BLI_DEF) $(D1M) $(STR_1M) $(STR_ST) -c $< -o $@ test_z%_1m_blis_mt.o: test_%.c $(CC) $(CFLAGS) $(PDEF_MT) $(DT_Z) $(BLI_DEF) $(D1M) $(STR_1M) $(STR_MT) -c $< -o $@ test_c%_1m_blis_mt.o: test_%.c $(CC) $(CFLAGS) $(PDEF_MT) $(DT_C) $(BLI_DEF) $(D1M) $(STR_1M) $(STR_MT) -c $< -o $@ # blis asm test_d%_asm_blis_st.o: test_%.c $(CC) $(CFLAGS) $(PDEF_ST) $(DT_D) $(BLI_DEF) $(DNAT) $(STR_NAT) $(STR_ST) -c $< -o $@ test_s%_asm_blis_st.o: test_%.c $(CC) $(CFLAGS) $(PDEF_ST) $(DT_S) $(BLI_DEF) $(DNAT) $(STR_NAT) $(STR_ST) -c $< -o $@ test_z%_asm_blis_st.o: test_%.c $(CC) $(CFLAGS) $(PDEF_ST) $(DT_Z) $(BLI_DEF) $(DNAT) $(STR_NAT) $(STR_ST) -c $< -o $@ test_c%_asm_blis_st.o: test_%.c $(CC) $(CFLAGS) $(PDEF_ST) $(DT_C) $(BLI_DEF) $(DNAT) $(STR_NAT) $(STR_ST) -c $< -o $@ test_d%_asm_blis_mt.o: test_%.c $(CC) $(CFLAGS) $(PDEF_MT) $(DT_D) $(BLI_DEF) $(DNAT) $(STR_NAT) $(STR_MT) -c $< -o $@ test_s%_asm_blis_mt.o: test_%.c $(CC) $(CFLAGS) $(PDEF_MT) $(DT_S) $(BLI_DEF) $(DNAT) $(STR_NAT) $(STR_MT) -c $< -o $@ test_z%_asm_blis_mt.o: test_%.c $(CC) $(CFLAGS) $(PDEF_MT) $(DT_Z) $(BLI_DEF) $(DNAT) $(STR_NAT) $(STR_MT) -c $< -o $@ test_c%_asm_blis_mt.o: test_%.c $(CC) $(CFLAGS) $(PDEF_MT) $(DT_C) $(BLI_DEF) $(DNAT) $(STR_NAT) $(STR_MT) -c $< -o $@ # openblas test_d%_openblas_st.o: test_%.c $(CC) $(CFLAGS) $(PDEF_ST) $(DT_D) $(BLA_DEF) $(DNAT) $(STR_OBL) $(STR_ST) -c $< -o $@ test_s%_openblas_st.o: test_%.c $(CC) $(CFLAGS) $(PDEF_ST) $(DT_S) $(BLA_DEF) $(DNAT) $(STR_OBL) $(STR_ST) -c $< -o $@ test_z%_openblas_st.o: test_%.c $(CC) $(CFLAGS) $(PDEF_ST) $(DT_Z) $(BLA_DEF) $(DNAT) $(STR_OBL) $(STR_ST) -c $< -o $@ test_c%_openblas_st.o: test_%.c $(CC) $(CFLAGS) $(PDEF_ST) $(DT_C) $(BLA_DEF) $(DNAT) $(STR_OBL) $(STR_ST) -c $< -o $@ test_d%_openblas_mt.o: test_%.c $(CC) $(CFLAGS) $(PDEF_MT) $(DT_D) $(BLA_DEF) $(DNAT) $(STR_OBL) $(STR_MT) -c $< -o $@ test_s%_openblas_mt.o: test_%.c $(CC) $(CFLAGS) $(PDEF_MT) $(DT_S) $(BLA_DEF) $(DNAT) $(STR_OBL) $(STR_MT) -c $< -o $@ test_z%_openblas_mt.o: test_%.c $(CC) $(CFLAGS) $(PDEF_MT) $(DT_Z) $(BLA_DEF) $(DNAT) $(STR_OBL) $(STR_MT) -c $< -o $@ test_c%_openblas_mt.o: test_%.c $(CC) $(CFLAGS) $(PDEF_MT) $(DT_C) $(BLA_DEF) $(DNAT) $(STR_OBL) $(STR_MT) -c $< -o $@ # mkl test_d%_mkl_st.o: test_%.c $(CC) $(CFLAGS) $(PDEF_ST) $(DT_D) $(BLA_DEF) $(DNAT) $(STR_MKL) $(STR_ST) -c $< -o $@ test_s%_mkl_st.o: test_%.c $(CC) $(CFLAGS) $(PDEF_ST) $(DT_S) $(BLA_DEF) $(DNAT) $(STR_MKL) $(STR_ST) -c $< -o $@ test_z%_mkl_st.o: test_%.c $(CC) $(CFLAGS) $(PDEF_ST) $(DT_Z) $(BLA_DEF) $(DNAT) $(STR_MKL) $(STR_ST) -c $< -o $@ test_c%_mkl_st.o: test_%.c $(CC) $(CFLAGS) $(PDEF_ST) $(DT_C) $(BLA_DEF) $(DNAT) $(STR_MKL) $(STR_ST) -c $< -o $@ test_d%_mkl_mt.o: test_%.c $(CC) $(CFLAGS) $(PDEF_MT) $(DT_D) $(BLA_DEF) $(DNAT) $(STR_MKL) $(STR_MT) -c $< -o $@ test_s%_mkl_mt.o: test_%.c $(CC) $(CFLAGS) $(PDEF_MT) $(DT_S) $(BLA_DEF) $(DNAT) $(STR_MKL) $(STR_MT) -c $< -o $@ test_z%_mkl_mt.o: test_%.c $(CC) $(CFLAGS) $(PDEF_MT) $(DT_Z) $(BLA_DEF) $(DNAT) $(STR_MKL) $(STR_MT) -c $< -o $@ test_c%_mkl_mt.o: test_%.c $(CC) $(CFLAGS) $(PDEF_MT) $(DT_C) $(BLA_DEF) $(DNAT) $(STR_MKL) $(STR_MT) -c $< -o $@ # armpl test_d%_armpl_st.o: test_%.c $(CC) $(CFLAGS) $(PDEF_ST) $(DT_D) $(BLA_DEF) $(DNAT) $(STR_ARMPL) $(STR_ST) -c $< -o $@ test_s%_armpl_st.o: test_%.c $(CC) $(CFLAGS) $(PDEF_ST) $(DT_S) $(BLA_DEF) $(DNAT) $(STR_ARMPL) $(STR_ST) -c $< -o $@ test_z%_armpl_st.o: test_%.c $(CC) $(CFLAGS) $(PDEF_ST) $(DT_Z) $(BLA_DEF) $(DNAT) $(STR_ARMPL) $(STR_ST) -c $< -o $@ test_c%_armpl_st.o: test_%.c $(CC) $(CFLAGS) $(PDEF_ST) $(DT_C) $(BLA_DEF) $(DNAT) $(STR_ARMPL) $(STR_ST) -c $< -o $@ test_d%_armpl_mt.o: test_%.c $(CC) $(CFLAGS) $(PDEF_MT) $(DT_D) $(BLA_DEF) $(DNAT) $(STR_ARMPL) $(STR_MT) -c $< -o $@ test_s%_armpl_mt.o: test_%.c $(CC) $(CFLAGS) $(PDEF_MT) $(DT_S) $(BLA_DEF) $(DNAT) $(STR_ARMPL) $(STR_MT) -c $< -o $@ test_z%_armpl_mt.o: test_%.c $(CC) $(CFLAGS) $(PDEF_MT) $(DT_Z) $(BLA_DEF) $(DNAT) $(STR_ARMPL) $(STR_MT) -c $< -o $@ test_c%_armpl_mt.o: test_%.c $(CC) $(CFLAGS) $(PDEF_MT) $(DT_C) $(BLA_DEF) $(DNAT) $(STR_ARMPL) $(STR_MT) -c $< -o $@ # mkl # -- Executable file rules -- # NOTE: For the BLAS test drivers, we place the BLAS libraries before BLIS # on the link command line in case BLIS was configured with the BLAS # compatibility layer. This prevents BLIS from inadvertently getting called # for the BLAS routines we are trying to test with. test_%_openblas_st.x: test_%_openblas_st.o $(LIBBLIS_LINK) $(LINKER) $< $(OPENBLAS_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $@ test_%_openblas_mt.x: test_%_openblas_mt.o $(LIBBLIS_LINK) $(LINKER) $< $(OPENBLASP_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $@ test_%_mkl_st.x: test_%_mkl_st.o $(LIBBLIS_LINK) $(LINKER) $< $(MKL_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $@ test_%_mkl_mt.x: test_%_mkl_mt.o $(LIBBLIS_LINK) $(LINKER) $< $(MKLP_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $@ test_%_armpl_st.x: test_%_armpl_st.o $(LIBBLIS_LINK) $(LINKER) $< $(ARMPL_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $@ test_%_armpl_mt.x: test_%_armpl_mt.o $(LIBBLIS_LINK) $(LINKER) $< $(ARMPL_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $@ test_%_blis_st.x: test_%_blis_st.o $(LIBBLIS_LINK) $(LINKER) $< $(LIBBLIS_LINK) $(LDFLAGS) -o $@ test_%_blis_mt.x: test_%_blis_mt.o $(LIBBLIS_LINK) $(LINKER) $< $(LIBBLIS_LINK) $(LDFLAGS) -o $@ # -- Clean rules -- clean: cleanx cleanx: - $(RM_F) *.o *.x blis-0.9.0/test/studies/skx/plot_gemm_mt_perf.m000066400000000000000000000076731422157504600216150ustar00rootroot00000000000000addpath(pathname) output_mt_sgemm_asm_blis output_mt_dgemm_asm_blis output_mt_cgemm_1m_blis output_mt_zgemm_1m_blis output_mt_sgemm_openblas output_mt_dgemm_openblas output_mt_cgemm_openblas output_mt_zgemm_openblas output_mt_sgemm_mkl output_mt_dgemm_mkl output_mt_cgemm_mkl output_mt_zgemm_mkl % SGEMM multi threaded axes1 = subplot(4, 4, 1); hold(axes1,'on'); plot(data_mt_sgemm_asm_blis(:,1), data_mt_sgemm_asm_blis(:,4), 'LineWidth', 1.25,'Color', [0 0 1]); plot(data_mt_sgemm_openblas(:,1), data_mt_sgemm_openblas(:,4), 'LineWidth', 1.25,'Color', [0 1 0]); plot(data_mt_sgemm_mkl(:,1), data_mt_sgemm_mkl(:,4), '--', 'LineWidth', 1.25,'Color', [1 0 0]); ylabel( 'GFLOPS', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); %xlabel( 'matrix dimension m=n=k', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue' ); title('SGEMM (multi-threaded)','FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); box(axes1,'on'); set(axes1,'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); v = axis; % extract the current ranges axis( [ 0 xmax_mt 0 speak*numcores] ) % DGEMM multi threaded axes1 = subplot(4, 4, 5); hold(axes1,'on'); plot(data_mt_dgemm_asm_blis(:,1), data_mt_dgemm_asm_blis(:,4), 'LineWidth', 1.25,'Color', [0 0 1]); plot(data_mt_dgemm_openblas(:,1), data_mt_dgemm_openblas(:,4), 'LineWidth', 1.25,'Color', [0 1 0]); plot(data_mt_dgemm_mkl(:,1), data_mt_dgemm_mkl(:,4), '--', 'LineWidth', 1.25,'Color', [1 0 0]); ylabel( 'GFLOPS', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); %xlabel( 'matrix dimension m=n=k', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue' ); title('DGEMM (multi-threaded)','FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); box(axes1,'on'); set(axes1,'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); %legend({'BLIS', 'OpenBLAS', 'ARMPL'},'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue', 'Location', 'bemt'); v = axis; % extract the current ranges axis( [ 0 xmax_mt 0 dpeak*numcores ] ) % CGEMM multi threaded axes1 = subplot(4, 4, 9); hold(axes1,'on'); plot(data_mt_cgemm_1m_blis(:,1), data_mt_cgemm_1m_blis(:,4), 'LineWidth', 1.25,'Color', [0 0 1]); plot(data_mt_cgemm_openblas(:,1), data_mt_cgemm_openblas(:,4), 'LineWidth', 1.25,'Color', [0 1 0]); plot(data_mt_cgemm_mkl(:,1), data_mt_cgemm_mkl(:,4), '--', 'LineWidth', 1.25,'Color', [1 0 0]); ylabel( 'GFLOPS', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); %xlabel( 'matrix dimension m=n=k', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue' ); title('CGEMM (multi-threaded)','FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); box(axes1,'on'); set(axes1,'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); v = axis; % extract the current ranges axis( [ 0 xmax_mt 0 speak*numcores ] ) % ZGEMM multi threaded axes1 = subplot(4, 4, 13); hold(axes1,'on'); plot(data_mt_zgemm_1m_blis(:,1), data_mt_zgemm_1m_blis(:,4), 'LineWidth', 1.25,'Color', [0 0 1]); plot(data_mt_zgemm_openblas(:,1), data_mt_zgemm_openblas(:,4), 'LineWidth', 1.25,'Color', [0 1 0]); plot(data_mt_zgemm_mkl(:,1), data_mt_zgemm_mkl(:,4), '--', 'LineWidth', 1.25,'Color', [1 0 0]); ylabel( 'GFLOPS', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); xlabel( 'matrix dimension m=n=k', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue' ); title('ZGEMM (multi-threaded)','FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); box(axes1,'on'); set(axes1,'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); legend({'BLIS', 'OpenBLAS', 'MKL'},'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue', 'Location', 'best'); v = axis; % extract the current ranges axis( [ 0 xmax_mt 0 dpeak*numcores ] ) clear *gemm* rmpath(pathname) blis-0.9.0/test/studies/skx/plot_gemm_st_perf.m000066400000000000000000000076321422157504600216160ustar00rootroot00000000000000addpath(pathname) output_st_sgemm_asm_blis output_st_dgemm_asm_blis output_st_cgemm_1m_blis output_st_zgemm_1m_blis output_st_sgemm_openblas output_st_dgemm_openblas output_st_cgemm_openblas output_st_zgemm_openblas output_st_sgemm_mkl output_st_dgemm_mkl output_st_cgemm_mkl output_st_zgemm_mkl % SGEMM Single threaded axes1 = subplot(4, 4, 1); hold(axes1,'on'); plot(data_st_sgemm_asm_blis(:,1), data_st_sgemm_asm_blis(:,4), 'LineWidth', 1.25,'Color', [0 0 1]); plot(data_st_sgemm_openblas(:,1), data_st_sgemm_openblas(:,4), 'LineWidth', 1.25,'Color', [0 1 0]); plot(data_st_sgemm_mkl(:,1), data_st_sgemm_mkl(:,4), '--', 'LineWidth', 1.25,'Color', [1 0 0]); ylabel( 'GFLOPS', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); %xlabel( 'matrix dimension m=n=k', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue' ); title('SGEMM (single-threaded)','FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); box(axes1,'on'); set(axes1,'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); v = axis; % extract the current ranges axis( [ 0 v(2) 0 speak ] ) % DGEMM Single threaded axes1 = subplot(4, 4, 5); hold(axes1,'on'); plot(data_st_dgemm_asm_blis(:,1), data_st_dgemm_asm_blis(:,4), 'LineWidth', 1.25,'Color', [0 0 1]); plot(data_st_dgemm_openblas(:,1), data_st_dgemm_openblas(:,4), 'LineWidth', 1.25,'Color', [0 1 0]); plot(data_st_dgemm_mkl(:,1), data_st_dgemm_mkl(:,4), '--', 'LineWidth', 1.25,'Color', [1 0 0]); ylabel( 'GFLOPS', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); %xlabel( 'matrix dimension m=n=k', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue' ); title('DGEMM (single-threaded)','FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); box(axes1,'on'); set(axes1,'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); %legend({'BLIS', 'OpenBLAS', 'ARMPL'},'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue', 'Location', 'best'); v = axis; % extract the current ranges axis( [ 0 v(2) 0 dpeak ] ) % CGEMM Single threaded axes1 = subplot(4, 4, 9); hold(axes1,'on'); plot(data_st_cgemm_1m_blis(:,1), data_st_cgemm_1m_blis(:,4), 'LineWidth', 1.25,'Color', [0 0 1]); plot(data_st_cgemm_openblas(:,1), data_st_cgemm_openblas(:,4),'--', 'LineWidth', 1.25,'Color', [0 1 0]); plot(data_st_cgemm_mkl(:,1), data_st_cgemm_mkl(:,4), '--', 'LineWidth', 1.25,'Color', [1 0 0]); ylabel( 'GFLOPS', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); %xlabel( 'matrix dimension m=n=k', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue' ); title('CGEMM (single-threaded)','FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); box(axes1,'on'); set(axes1,'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); v = axis; % extract the current ranges axis( [ 0 v(2) 0 speak ] ) % ZGEMM Single threaded axes1 = subplot(4, 4, 13); hold(axes1,'on'); plot(data_st_zgemm_1m_blis(:,1), data_st_zgemm_1m_blis(:,4), 'LineWidth', 1.25,'Color', [0 0 1]); plot(data_st_zgemm_openblas(:,1), data_st_zgemm_openblas(:,4), 'LineWidth', 1.25,'Color', [0 1 0]); plot(data_st_zgemm_mkl(:,1), data_st_zgemm_mkl(:,4), '--', 'LineWidth', 1.25,'Color', [1 0 0]); ylabel( 'GFLOPS', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); xlabel( 'matrix dimension m=n=k', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue' ); title('ZGEMM (single-threaded)','FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); box(axes1,'on'); set(axes1,'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); %legend({'BLIS', 'OpenBLAS', 'MKL'},'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue', 'Location', 'South'); v = axis; % extract the current ranges axis( [ 0 v(2) 0 dpeak ] ) clear *gemm* rmpath(pathname) blis-0.9.0/test/studies/skx/plot_hemm_mt_perf.m000066400000000000000000000077011422157504600216060ustar00rootroot00000000000000addpath(pathname) output_mt_shemm_asm_blis output_mt_dhemm_asm_blis output_mt_chemm_1m_blis output_mt_zhemm_1m_blis output_mt_shemm_openblas output_mt_dhemm_openblas output_mt_chemm_openblas output_mt_zhemm_openblas output_mt_shemm_mkl output_mt_dhemm_mkl output_mt_chemm_mkl output_mt_zhemm_mkl % SSYMM multi threaded axes1 = subplot(4, 4, 3); hold(axes1,'on'); plot(data_mt_shemm_asm_blis(:,1), data_mt_shemm_asm_blis(:,3), 'LineWidth', 1.25,'Color', [0 0 1]); plot(data_mt_shemm_openblas(:,1), data_mt_shemm_openblas(:,3), 'LineWidth', 1.25,'Color', [0 1 0]); plot(data_mt_shemm_mkl(:,1), data_mt_shemm_mkl(:,3), '--', 'LineWidth', 1.25,'Color', [1 0 0]); ylabel( 'GFLOPS', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); %xlabel( 'matrix dimension m=n=k', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue' ); title('SSYMM (multi-threaded)','FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); box(axes1,'on'); set(axes1,'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); v = axis; % extract the current ranges axis( [ 0 xmax_mt 0 speak*numcores ] ) % DSYMM multi threaded axes1 = subplot(4, 4, 7); hold(axes1,'on'); plot(data_mt_dhemm_asm_blis(:,1), data_mt_dhemm_asm_blis(:,3), 'LineWidth', 1.25,'Color', [0 0 1]); plot(data_mt_dhemm_openblas(:,1), data_mt_dhemm_openblas(:,3), 'LineWidth', 1.25,'Color', [0 1 0]); plot(data_mt_dhemm_mkl(:,1), data_mt_dhemm_mkl(:,3), '--', 'LineWidth', 1.25,'Color', [1 0 0]); ylabel( 'GFLOPS', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); %xlabel( 'matrix dimension m=n=k', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue' ); title('DSYMM (multi-threaded)','FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); box(axes1,'on'); set(axes1,'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); %legend({'BLIS', 'OpenBLAS', 'ARMPL'},'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue', 'Location', 'bemt'); v = axis; % extract the current ranges axis( [ 0 xmax_mt 0 dpeak*numcores ] ) % CHEMM multi threaded axes1 = subplot(4, 4, 11); hold(axes1,'on'); plot(data_mt_chemm_1m_blis(:,1), data_mt_chemm_1m_blis(:,3), 'LineWidth', 1.25,'Color', [0 0 1]); plot(data_mt_chemm_openblas(:,1), data_mt_chemm_openblas(:,3), 'LineWidth', 1.25,'Color', [0 1 0]); plot(data_mt_chemm_mkl(:,1), data_mt_chemm_mkl(:,3), '--', 'LineWidth', 1.25,'Color', [1 0 0]); ylabel( 'GFLOPS', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); %xlabel( 'matrix dimension m=n=k', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue' ); title('CHEMM (multi-threaded)','FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); box(axes1,'on'); set(axes1,'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); v = axis; % extract the current ranges axis( [ 0 xmax_mt 0 speak*numcores ] ) % ZHEMM multi threaded axes1 = subplot(4, 4, 15); hold(axes1,'on'); plot(data_mt_zhemm_1m_blis(:,1), data_mt_zhemm_1m_blis(:,3), 'LineWidth', 1.25,'Color', [0 0 1]); plot(data_mt_zhemm_openblas(:,1), data_mt_zhemm_openblas(:,3), 'LineWidth', 1.25,'Color', [0 1 0]); plot(data_mt_zhemm_mkl(:,1), data_mt_zhemm_mkl(:,3),'--', 'LineWidth', 1.25,'Color', [1 0 0]); ylabel( 'GFLOPS', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); xlabel( 'matrix dimension m=n=k', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue' ); title('ZHEMM (multi-threaded)','FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); box(axes1,'on'); set(axes1,'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); legend({'BLIS', 'OpenBLAS', 'ARMPL'},'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue', 'Location', 'best'); v = axis; % extract the current ranges axis( [ 0 xmax_mt 0 dpeak*numcores ] ) clear *hemm* rmpath(pathname) blis-0.9.0/test/studies/skx/plot_hemm_st_perf.m000066400000000000000000000076511422157504600216200ustar00rootroot00000000000000addpath(pathname) output_st_shemm_asm_blis output_st_dhemm_asm_blis output_st_chemm_1m_blis output_st_zhemm_1m_blis output_st_shemm_openblas output_st_dhemm_openblas output_st_chemm_openblas output_st_zhemm_openblas output_st_shemm_mkl output_st_dhemm_mkl output_st_chemm_mkl output_st_zhemm_mkl % SSYMM Single threaded axes1 = subplot(4, 4, 3); hold(axes1,'on'); plot(data_st_shemm_asm_blis(:,1), data_st_shemm_asm_blis(:,3), 'LineWidth', 1.25,'Color', [0 0 1]); plot(data_st_shemm_openblas(:,1), data_st_shemm_openblas(:,3), 'LineWidth', 1.25,'Color', [0 1 0]); plot(data_st_shemm_mkl(:,1), data_st_shemm_mkl(:,3), '--', 'LineWidth', 1.25,'Color', [1 0 0]); ylabel( 'GFLOPS', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); %xlabel( 'matrix dimension m=n=k', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue' ); title('SSYMM (single-threaded)','FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); box(axes1,'on'); set(axes1,'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); v = axis; % extract the current ranges axis( [ 0 v(2) 0 speak ] ) % DSYMM Single threaded axes1 = subplot(4, 4, 7); hold(axes1,'on'); plot(data_st_dhemm_asm_blis(:,1), data_st_dhemm_asm_blis(:,3), 'LineWidth', 1.25,'Color', [0 0 1]); plot(data_st_dhemm_openblas(:,1), data_st_dhemm_openblas(:,3), 'LineWidth', 1.25,'Color', [0 1 0]); plot(data_st_dhemm_mkl(:,1), data_st_dhemm_mkl(:,3), '--', 'LineWidth', 1.25,'Color', [1 0 0]); ylabel( 'GFLOPS', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); %xlabel( 'matrix dimension m=n=k', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue' ); title('DSYMM (single-threaded)','FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); box(axes1,'on'); set(axes1,'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); %legend({'BLIS', 'OpenBLAS', 'ARMPL'},'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue', 'Location', 'best'); v = axis; % extract the current ranges axis( [ 0 v(2) 0 dpeak ] ) % CHEMM Single threaded axes1 = subplot(4, 4, 11); hold(axes1,'on'); plot(data_st_chemm_1m_blis(:,1), data_st_chemm_1m_blis(:,3), 'LineWidth', 1.25,'Color', [0 0 1]); plot(data_st_chemm_openblas(:,1), data_st_chemm_openblas(:,3), 'LineWidth', 1.25,'Color', [0 1 0]); plot(data_st_chemm_mkl(:,1), data_st_chemm_mkl(:,3), '--', 'LineWidth', 1.25,'Color', [1 0 0]); ylabel( 'GFLOPS', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); %xlabel( 'matrix dimension m=n=k', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue' ); title('CHEMM (single-threaded)','FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); box(axes1,'on'); set(axes1,'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); v = axis; % extract the current ranges axis( [ 0 v(2) 0 speak ] ) % ZHEMM Single threaded axes1 = subplot(4, 4, 15); hold(axes1,'on'); plot(data_st_zhemm_1m_blis(:,1), data_st_zhemm_1m_blis(:,3), 'LineWidth', 1.25,'Color', [0 0 1]); plot(data_st_zhemm_openblas(:,1), data_st_zhemm_openblas(:,3), 'LineWidth', 1.25,'Color', [0 1 0]); plot(data_st_zhemm_mkl(:,1), data_st_zhemm_mkl(:,3),'--', 'LineWidth', 1.25,'Color', [1 0 0]); ylabel( 'GFLOPS', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); xlabel( 'matrix dimension m=n=k', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue' ); title('ZHEMM (single-threaded)','FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); box(axes1,'on'); set(axes1,'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); % legend({'BLIS', 'BLIS (AVX2)', 'OpenBLAS', 'MKL'},'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue', 'Location', 'South'); v = axis; % extract the current ranges axis( [ 0 v(2) 0 dpeak ] ) clear *hemm* rmpath(pathname) blis-0.9.0/test/studies/skx/plot_skx_perf.m000066400000000000000000000011441422157504600207600ustar00rootroot00000000000000fontsize = 6; numcores = 4; freq = 3.5; sflopspercycle = 64; dflopspercycle = 32; speak = sflopspercycle*freq; dpeak = dflopspercycle*freq; xmax_mt = 5000; fig1 = figure(1); clf(fig1) % pathname = './20180711/'; plot_gemm_st_perf plot_syrk_st_perf plot_hemm_st_perf plot_trmm_st_perf fig1.PaperPositionMode = 'auto'; orient(fig1,'landscape') print(fig1, 'skx-st', '-dpdf','-fillpage') % fig1 = figure(2); % clf; % % plot_gemm_mt_perf % plot_syrk_mt_perf % plot_hemm_mt_perf % plot_trmm_mt_perf % % fig1.PaperPositionMode = 'auto'; % orient(fig1,'landscape') % print(fig1, 'A57-mt', '-dpdf','-fillpage') blis-0.9.0/test/studies/skx/plot_syrk_mt_perf.m000066400000000000000000000134101422157504600216420ustar00rootroot00000000000000addpath(pathname) output_mt_ssyrk_asm_blis output_mt_dsyrk_asm_blis output_mt_csyrk_1m_blis output_mt_zsyrk_1m_blis output_mt_ssyrk_openblas output_mt_dsyrk_openblas output_mt_csyrk_openblas output_mt_zsyrk_openblas output_mt_ssyrk_mkl output_mt_dsyrk_mkl output_mt_csyrk_mkl output_mt_zsyrk_mkl plot_lower=0; if(plot_lower) output_mt_ssyrk_asm_blis output_mt_dsyrk_asm_blis output_mt_csyrk_1m_blis output_mt_zsyrk_1m_blis output_mt_ssyrk_openblas output_mt_dsyrk_openblas output_mt_csyrk_openblas output_mt_zsyrk_openblas output_mt_ssyrk_mkl output_mt_dsyrk_mkl output_mt_csyrk_mkl output_mt_zsyrk_mkl end % SSYRK multi threaded axes1 = subplot(4, 4, 2); hold(axes1,'on'); plot(data_mt_ssyrk_asm_blis(:,1), data_mt_ssyrk_asm_blis(:,3), 'LineWidth', 1.25,'Color', [0 0 1]); plot(data_mt_ssyrk_openblas(:,1), data_mt_ssyrk_openblas(:,3), 'LineWidth', 1.25,'Color', [0 1 0]); plot(data_mt_ssyrk_mkl(:,1), data_mt_ssyrk_mkl(:,3), '--', 'LineWidth', 1.25,'Color', [1 0 0]); if(plot_lower) plot(data_mt_ssyrk_l_asm_blis(:,1), data_mt_ssyrk_l_asm_blis(:,3), '-.','LineWidth', 1.25,'Color', [0 0 1]); plot(data_mt_ssyrk_l_openblas(:,1), data_mt_ssyrk_l_openblas(:,3), '-.', 'LineWidth', 1.25,'Color', [0 1 0]); plot(data_mt_ssyrk_l_mkl(:,1), data_mt_ssyrk_l_mkl(:,3), '-.', 'LineWidth', 1.25,'Color', [1 0 0]); end ylabel( 'GFLOPS', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); %xlabel( 'matrix dimension m=n=k', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue' ); title('SSYRK (multi-threaded)','FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); box(axes1,'on'); set(axes1,'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); v = axis; % extract the current ranges axis( [ 0 xmax_mt 0 speak*numcores ] ) % DSYRK multi threaded axes1 = subplot(4, 4, 6); hold(axes1,'on'); plot(data_mt_dsyrk_asm_blis(:,1), data_mt_dsyrk_asm_blis(:,3), 'LineWidth', 1.25,'Color', [0 0 1]); plot(data_mt_dsyrk_openblas(:,1), data_mt_dsyrk_openblas(:,3), 'LineWidth', 1.25,'Color', [0 1 0]); plot(data_mt_dsyrk_mkl(:,1), data_mt_dsyrk_mkl(:,3), '--', 'LineWidth', 1.25,'Color', [1 0 0]); if(plot_lower) plot(data_mt_dsyrk_l_asm_blis(:,1), data_mt_dsyrk_l_asm_blis(:,3), '-.', 'LineWidth', 1.25,'Color', [0 0 1]); plot(data_mt_dsyrk_l_openblas(:,1), data_mt_dsyrk_l_openblas(:,3), '-.', 'LineWidth', 1.25,'Color', [0 1 0]); plot(data_mt_dsyrk_l_mkl(:,1), data_mt_dsyrk_l_mkl(:,3), '-.', 'LineWidth', 1.25,'Color', [1 0 0]); end ylabel( 'GFLOPS', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); %xlabel( 'matrix dimension m=n=k', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue' ); title('DSYRK (multi-threaded)','FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); box(axes1,'on'); set(axes1,'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); %legend({'BLIS', 'OpenBLAS', 'ARMPL'},'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue', 'Location', 'bemt'); v = axis; % extract the current ranges axis( [ 0 xmax_mt 0 dpeak*numcores ] ) % CSYRK multi threaded axes1 = subplot(4, 4, 10); hold(axes1,'on'); plot(data_mt_csyrk_1m_blis(:,1), data_mt_csyrk_1m_blis(:,3), 'LineWidth', 1.25,'Color', [0 0 1]); plot(data_mt_csyrk_openblas(:,1), data_mt_csyrk_openblas(:,3), 'LineWidth', 1.25,'Color', [0 1 0]); plot(data_mt_csyrk_mkl(:,1), data_mt_csyrk_mkl(:,3), '--', 'LineWidth', 1.25,'Color', [1 0 0]); if(plot_lower) plot(data_mt_csyrk_l_1m_blis(:,1), data_mt_csyrk_l_1m_blis(:,3),'-.', 'LineWidth', 1.25,'Color', [0 0 1]); plot(data_mt_csyrk_l_openblas(:,1), data_mt_csyrk_l_openblas(:,3), '-.', 'LineWidth', 1.25,'Color', [0 1 0]); plot(data_mt_csyrk_l_mkl(:,1), data_mt_csyrk_l_mkl(:,3), '-.', 'LineWidth', 1.25,'Color', [1 0 0]); end ylabel( 'GFLOPS', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); %xlabel( 'matrix dimension m=n=k', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue' ); title('CSYRK (multi-threaded)','FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); box(axes1,'on'); set(axes1,'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); v = axis; % extract the current ranges axis( [ 0 xmax_mt 0 speak*numcores ] ) % ZSYRK multi threaded axes1 = subplot(4, 4, 14); hold(axes1,'on'); plot(data_mt_zsyrk_1m_blis(:,1), data_mt_zsyrk_1m_blis(:,3), 'LineWidth', 1.25,'Color', [0 0 1]); plot(data_mt_zsyrk_openblas(:,1), data_mt_zsyrk_openblas(:,3), 'LineWidth', 1.25,'Color', [0 1 0]); plot(data_mt_zsyrk_mkl(:,1), data_mt_zsyrk_mkl(:,3), '--', 'LineWidth', 1.25,'Color', [1 0 0]); if(plot_lower) plot(data_mt_zsyrk_l_1m_blis(:,1), data_mt_zsyrk_l_1m_blis(:,3), '-.', 'LineWidth', 1.25,'Color', [0 0 1]); plot(data_mt_zsyrk_l_openblas(:,1), data_mt_zsyrk_l_openblas(:,3), '-.', 'LineWidth', 1.25,'Color', [0 1 0]); plot(data_mt_zsyrk_l_mkl(:,1), data_mt_zsyrk_l_mkl(:,3), '-.', 'LineWidth', 1.25,'Color', [1 0 0]); end ylabel( 'GFLOPS', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); xlabel( 'matrix dimension m=n=k', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue' ); title('ZSYRK (multi-threaded)','FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); box(axes1,'on'); set(axes1,'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); legend({'BLIS (Upper)', 'OpenBLAS (Upper)', 'ARMPL (Upper)', 'BLIS (Lower)', 'OpenBLAS (Lower) ', 'ARMPL (Lower)'},'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue', 'Location', 'best'); v = axis; % extract the current ranges axis( [ 0 xmax_mt 0 dpeak*numcores ] ) clear *syrk* rmpath(pathname) blis-0.9.0/test/studies/skx/plot_syrk_st_perf.m000066400000000000000000000125001422157504600216470ustar00rootroot00000000000000addpath(pathname) output_st_ssyrk_asm_blis output_st_dsyrk_asm_blis output_st_csyrk_1m_blis output_st_zsyrk_1m_blis output_st_ssyrk_openblas output_st_dsyrk_openblas output_st_csyrk_openblas output_st_zsyrk_openblas output_st_ssyrk_mkl output_st_dsyrk_mkl output_st_csyrk_mkl output_st_zsyrk_mkl plot_lower = 0; % SSYRK Single threaded axes1 = subplot(4, 4, 2); hold(axes1,'on'); plot(data_st_ssyrk_asm_blis(:,1), data_st_ssyrk_asm_blis(:,3), 'LineWidth', 1.25,'Color', [0 0 1]); plot(data_st_ssyrk_openblas(:,1), data_st_ssyrk_openblas(:,3), 'LineWidth', 1.25,'Color', [0 1 0]); plot(data_st_ssyrk_mkl(:,1), data_st_ssyrk_mkl(:,3), '--', 'LineWidth', 1.25,'Color', [1 0 0]); if(plot_lower) plot(data_st_ssyrk_l_asm_blis(:,1), data_st_ssyrk_l_asm_blis(:,3), '-.','LineWidth', 1.25,'Color', [0 0 1]); plot(data_st_ssyrk_l_openblas(:,1), data_st_ssyrk_l_openblas(:,3), '-.', 'LineWidth', 1.25,'Color', [0 1 0]); plot(data_st_ssyrk_l_mkl(:,1), data_st_ssyrk_l_mkl(:,3), '-.', 'LineWidth', 1.25,'Color', [1 0 0]); end ylabel( 'GFLOPS', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); %xlabel( 'matrix dimension m=n=k', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue' ); title('SSYRK (single-threaded)','FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); box(axes1,'on'); set(axes1,'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); v = axis; % extract the current ranges axis( [ 0 v(2) 0 speak ] ) % DSYRK single threaded axes1 = subplot(4, 4, 6); hold(axes1,'on'); plot(data_st_dsyrk_asm_blis(:,1), data_st_dsyrk_asm_blis(:,3), 'LineWidth', 1.25,'Color', [0 0 1]); plot(data_st_dsyrk_openblas(:,1), data_st_dsyrk_openblas(:,3), 'LineWidth', 1.25,'Color', [0 1 0]); plot(data_st_dsyrk_mkl(:,1), data_st_dsyrk_mkl(:,3), '--', 'LineWidth', 1.25,'Color', [1 0 0]); if(plot_lower) plot(data_st_dsyrk_l_asm_blis(:,1), data_st_dsyrk_l_asm_blis(:,3), '-.', 'LineWidth', 1.25,'Color', [0 0 1]); plot(data_st_dsyrk_l_openblas(:,1), data_st_dsyrk_l_openblas(:,3), '-.', 'LineWidth', 1.25,'Color', [0 1 0]); plot(data_st_dsyrk_l_mkl(:,1), data_st_dsyrk_l_mkl(:,3), '-.', 'LineWidth', 1.25,'Color', [1 0 0]); end ylabel( 'GFLOPS', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); %xlabel( 'matrix dimension m=n=k', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue' ); title('DSYRK (single-threaded)','FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); box(axes1,'on'); set(axes1,'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); %legend({'BLIS', 'OpenBLAS', 'ARMPL'},'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue', 'Location', 'best'); v = axis; % extract the current ranges axis( [ 0 v(2) 0 dpeak ] ) % CSYRK single threaded axes1 = subplot(4, 4, 10); hold(axes1,'on'); plot(data_st_csyrk_1m_blis(:,1), data_st_csyrk_1m_blis(:,3), 'LineWidth', 1.25,'Color', [0 0 1]); plot(data_st_csyrk_openblas(:,1), data_st_csyrk_openblas(:,3), 'LineWidth', 1.25,'Color', [0 1 0]); plot(data_st_csyrk_mkl(:,1), data_st_csyrk_mkl(:,3), '--', 'LineWidth', 1.25,'Color', [1 0 0]); if(plot_lower) plot(data_st_csyrk_l_1m_blis(:,1), data_st_csyrk_l_1m_blis(:,3),'-.', 'LineWidth', 1.25,'Color', [0 0 1]); plot(data_st_csyrk_l_openblas(:,1), data_st_csyrk_l_openblas(:,3), '-.', 'LineWidth', 1.25,'Color', [0 1 0]); plot(data_st_csyrk_l_mkl(:,1), data_st_csyrk_l_mkl(:,3), '-.', 'LineWidth', 1.25,'Color', [1 0 0]); end ylabel( 'GFLOPS', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); %xlabel( 'matrix dimension m=n=k', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue' ); title('CSYRK (single-threaded)','FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); box(axes1,'on'); set(axes1,'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); v = axis; % extract the current ranges axis( [ 0 v(2) 0 speak ] ) % ZSYRK single threaded axes1 = subplot(4, 4, 14); hold(axes1,'on'); plot(data_st_zsyrk_1m_blis(:,1), data_st_zsyrk_1m_blis(:,3), 'LineWidth', 1.25,'Color', [0 0 1]); plot(data_st_zsyrk_openblas(:,1), data_st_zsyrk_openblas(:,3), 'LineWidth', 1.25,'Color', [0 1 0]); plot(data_st_zsyrk_mkl(:,1), data_st_zsyrk_mkl(:,3), '--', 'LineWidth', 1.25,'Color', [1 0 0]); if(plot_lower) plot(data_st_zsyrk_l_1m_blis(:,1), data_st_zsyrk_l_1m_blis(:,3), '-.', 'LineWidth', 1.25,'Color', [0 0 1]); plot(data_st_zsyrk_l_openblas(:,1), data_st_zsyrk_l_openblas(:,3), '-.', 'LineWidth', 1.25,'Color', [0 1 0]); plot(data_st_zsyrk_l_mkl(:,1), data_st_zsyrk_l_mkl(:,3), '-.', 'LineWidth', 1.25,'Color', [1 0 0]); end ylabel( 'GFLOPS', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); xlabel( 'matrix dimension m=n=k', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue' ); title('ZSYRK (single-threaded)','FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); box(axes1,'on'); set(axes1,'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); % legend({'BLIS', 'BLIS (AVX2)','OpenBLAS', 'MKL'},'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue', 'Location', 'South'); v = axis; % extract the current ranges axis( [ 0 v(2) 0 dpeak ] ) clear *syrk* rmpath(pathname) blis-0.9.0/test/studies/skx/plot_trmm_mt_perf.m000066400000000000000000000076771422157504600216530ustar00rootroot00000000000000addpath(pathname) output_mt_strmm_asm_blis output_mt_dtrmm_asm_blis output_mt_ctrmm_1m_blis output_mt_ztrmm_1m_blis output_mt_strmm_openblas output_mt_dtrmm_openblas output_mt_ctrmm_openblas output_mt_ztrmm_openblas output_mt_strmm_mkl output_mt_dtrmm_mkl output_mt_ctrmm_mkl output_mt_ztrmm_mkl % mtRMM multi threaded axes1 = subplot(4, 4, 4); hold(axes1,'on'); plot(data_mt_strmm_asm_blis(:,1), data_mt_strmm_asm_blis(:,3), 'LineWidth', 1.25,'Color', [0 0 1]); plot(data_mt_strmm_openblas(:,1), data_mt_strmm_openblas(:,3), 'LineWidth', 1.25,'Color', [0 1 0]); plot(data_mt_strmm_mkl(:,1), data_mt_strmm_mkl(:,3), '--', 'LineWidth', 1.25,'Color', [1 0 0]); ylabel( 'GFLOPS', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); %xlabel( 'matrix dimension m=n=k', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue' ); title('STRMM (multi-threaded)','FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); box(axes1,'on'); set(axes1,'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); v = axis; % extract the current ranges axis( [ 0 xmax_mt 0 speak*numcores ] ) % DTRMM multi threaded axes1 = subplot(4, 4, 8); hold(axes1,'on'); plot(data_mt_dtrmm_asm_blis(:,1), data_mt_dtrmm_asm_blis(:,3), 'LineWidth', 1.25,'Color', [0 0 1]); plot(data_mt_dtrmm_openblas(:,1), data_mt_dtrmm_openblas(:,3), 'LineWidth', 1.25,'Color', [0 1 0]); plot(data_mt_dtrmm_mkl(:,1), data_mt_dtrmm_mkl(:,3), '--', 'LineWidth', 1.25,'Color', [1 0 0]); ylabel( 'GFLOPS', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); %xlabel( 'matrix dimension m=n=k', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue' ); title('DTRMM (multi-threaded)','FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); box(axes1,'on'); set(axes1,'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); %legend({'BLIS', 'OpenBLAS', 'ARMPL'},'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue', 'Location', 'bemt'); v = axis; % extract the current ranges axis( [ 0 xmax_mt 0 dpeak*numcores ] ) % CTRMM multi threaded axes1 = subplot(4, 4, 12); hold(axes1,'on'); plot(data_mt_ctrmm_1m_blis(:,1), data_mt_ctrmm_1m_blis(:,3), 'LineWidth', 1.25,'Color', [0 0 1]); plot(data_mt_ctrmm_openblas(:,1), data_mt_ctrmm_openblas(:,3), 'LineWidth', 1.25,'Color', [0 1 0]); plot(data_mt_ctrmm_mkl(:,1), data_mt_ctrmm_mkl(:,3),'--', 'LineWidth', 1.25,'Color', [1 0 0]); ylabel( 'GFLOPS', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); %xlabel( 'matrix dimension m=n=k', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue' ); title('CTRMM (multi-threaded)','FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); box(axes1,'on'); set(axes1,'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); v = axis; % extract the current ranges axis( [ 0 xmax_mt 0 speak*numcores ] ) % ZTRMM multi threaded axes1 = subplot(4, 4, 16); hold(axes1,'on'); plot(data_mt_ztrmm_1m_blis(:,1), data_mt_ztrmm_1m_blis(:,3), 'LineWidth', 1.25,'Color', [0 0 1]); plot(data_mt_ztrmm_openblas(:,1), data_mt_ztrmm_openblas(:,3), 'LineWidth', 1.25,'Color', [0 1 0]); plot(data_mt_ztrmm_mkl(:,1), data_mt_ztrmm_mkl(:,3), '--', 'LineWidth', 1.25,'Color', [1 0 0]); ylabel( 'GFLOPS', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); xlabel( 'matrix dimension m=n=k', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue' ); title('ZTRMM (multi-threaded)','FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); box(axes1,'on'); set(axes1,'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); legend({'BLIS', 'OpenBLAS', 'ARMPL'},'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue', 'Location', 'best'); v = axis; % extract the current ranges axis( [ 0 xmax_mt 0 dpeak*numcores ] ) clear *trmm* rmpath(pathname) blis-0.9.0/test/studies/skx/plot_trmm_st_perf.m000066400000000000000000000076441422157504600216530ustar00rootroot00000000000000addpath(pathname) output_st_strmm_asm_blis output_st_dtrmm_asm_blis output_st_ctrmm_1m_blis output_st_ztrmm_1m_blis output_st_strmm_openblas output_st_dtrmm_openblas output_st_ctrmm_openblas output_st_ztrmm_openblas output_st_strmm_mkl output_st_dtrmm_mkl output_st_ctrmm_mkl output_st_ztrmm_mkl % STRMM Single threaded axes1 = subplot(4, 4, 4); hold(axes1,'on'); plot(data_st_strmm_asm_blis(:,1), data_st_strmm_asm_blis(:,3), 'LineWidth', 1.25,'Color', [0 0 1]); plot(data_st_strmm_openblas(:,1), data_st_strmm_openblas(:,3), 'LineWidth', 1.25,'Color', [0 1 0]); plot(data_st_strmm_mkl(:,1), data_st_strmm_mkl(:,3), '--', 'LineWidth', 1.25,'Color', [1 0 0]); ylabel( 'GFLOPS', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); %xlabel( 'matrix dimension m=n=k', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue' ); title('STRMM (single-threaded)','FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); box(axes1,'on'); set(axes1,'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); v = axis; % extract the current ranges axis( [ 0 v(2) 0 speak ] ) % DTRMM Single threaded axes1 = subplot(4, 4, 8); hold(axes1,'on'); plot(data_st_dtrmm_asm_blis(:,1), data_st_dtrmm_asm_blis(:,3), 'LineWidth', 1.25,'Color', [0 0 1]); plot(data_st_dtrmm_openblas(:,1), data_st_dtrmm_openblas(:,3), 'LineWidth', 1.25,'Color', [0 1 0]); plot(data_st_dtrmm_mkl(:,1), data_st_dtrmm_mkl(:,3), '--', 'LineWidth', 1.25,'Color', [1 0 0]); ylabel( 'GFLOPS', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); %xlabel( 'matrix dimension m=n=k', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue' ); title('DTRMM (single-threaded)','FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); box(axes1,'on'); set(axes1,'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); %legend({'BLIS', 'OpenBLAS', 'ARMPL'},'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue', 'Location', 'best'); v = axis; % extract the current ranges axis( [ 0 v(2) 0 dpeak ] ) % CTRMM Single threaded axes1 = subplot(4, 4, 12); hold(axes1,'on'); plot(data_st_ctrmm_1m_blis(:,1), data_st_ctrmm_1m_blis(:,3), 'LineWidth', 1.25,'Color', [0 0 1]); plot(data_st_ctrmm_openblas(:,1), data_st_ctrmm_openblas(:,3), 'LineWidth', 1.25,'Color', [0 1 0]); plot(data_st_ctrmm_mkl(:,1), data_st_ctrmm_mkl(:,3),'--', 'LineWidth', 1.25,'Color', [1 0 0]); ylabel( 'GFLOPS', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); %xlabel( 'matrix dimension m=n=k', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue' ); title('CTRMM (single-threaded)','FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); box(axes1,'on'); set(axes1,'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); v = axis; % extract the current ranges axis( [ 0 v(2) 0 speak ] ) % ZTRMM Single threaded axes1 = subplot(4, 4, 16); hold(axes1,'on'); plot(data_st_ztrmm_1m_blis(:,1), data_st_ztrmm_1m_blis(:,3), 'LineWidth', 1.25,'Color', [0 0 1]); plot(data_st_ztrmm_openblas(:,1), data_st_ztrmm_openblas(:,3), 'LineWidth', 1.25,'Color', [0 1 0]); plot(data_st_ztrmm_mkl(:,1), data_st_ztrmm_mkl(:,3), '--', 'LineWidth', 1.25,'Color', [1 0 0]); ylabel( 'GFLOPS', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); xlabel( 'matrix dimension m=n=k', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue' ); title('ZTRMM (single-threaded)','FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); box(axes1,'on'); set(axes1,'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); legend({'BLIS', 'BLIS (AVX2)','OpenBLAS', 'MKL'},'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue', 'Location', 'South'); v = axis; % extract the current ranges axis( [ 0 v(2) 0 dpeak ] ) clear *trmm* rmpath(pathname) blis-0.9.0/test/studies/skx/runme.sh000077500000000000000000000224441422157504600174160ustar00rootroot00000000000000#!/bin/bash # File pefixes. exec_root="test" out_root="output" out_rootdir=$(date +%Y%m%d) mkdir -p $out_rootdir #sys="blis" #sys="stampede" #sys="stampede2" #sys="lonestar" #sys="wahlberg" #sys="arm-softiron" sys="skx" # Bind threads to processors. #export OMP_PROC_BIND=true #export GOMP_CPU_AFFINITY="0 2 4 6 8 10 12 14 1 3 5 7 9 11 13 15" #export GOMP_CPU_AFFINITY="0 1 2 3 4 5 6 7" #export GOMP_CPU_AFFINITY="0 1 2 3 4 5 6 7" #export GOMP_CPU_AFFINITY="0 2 4 6 1 3 5 7" #export GOMP_CPU_AFFINITY="0 4 1 5 2 6 3 7" #export GOMP_CPU_AFFINITY="0 1 4 5 8 9 12 13 16 17 20 21 24 25 28 29 32 33 36 37 40 41 44 45" #export GOMP_CPU_AFFINITY="0 2 4 6 8 10 12 14 16 18 20 22 1 3 5 7 9 11 13 15 17 19 21 23" export GOMP_CPU_AFFINITY="0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39" # Modify LD_LIBRARY_PATH. if [ ${sys} = "blis" ]; then export LD_LIBRARY_PATH="$LD_LIBRARY_PATH" elif [ ${sys} = "stampede" ]; then # A hack to use libiomp5 with gcc. export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/opt/apps/intel/13/composer_xe_2013.2.146/compiler/lib/intel64" elif [ ${sys} = "stampede2" ]; then : elif [ ${sys} = "lonestar" ]; then # A hack to use libiomp5 with gcc. export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/opt/apps/intel/16.0.1.150/compilers_and_libraries_2016.1.150/linux/compiler/lib/intel64" elif [ ${sys} = "wahlberg" ]; then export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$HOME/flame/lib/acml/5.3.1/gfortran64_int64/lib" export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$HOME/flame/lib/acml/5.3.1/gfortran64_mp_int64/lib" fi # Threading scheme to use when multithreading if [ ${sys} = "blis" ]; then jc_nt=1 # 5th loop ic_nt=4 # 3rd loop jr_nt=1 # 2nd loop ir_nt=1 # 1st loop nt=4 elif [ ${sys} = "stampede" ]; then jc_nt=2 # 5th loop ic_nt=8 # 3rd loop jr_nt=1 # 2nd loop ir_nt=1 # 1st loop nt=16 elif [ ${sys} = "lonestar" ]; then jc_nt=2 # 5th loop ic_nt=12 # 3rd loop jr_nt=1 # 2nd loop ir_nt=1 # 1st loop nt=24 elif [ ${sys} = "wahlberg" ]; then jc_nt=1 # 5th loop ic_nt=2 # 3rd loop jr_nt=2 # 2nd loop ir_nt=1 # 1st loop nt=4 elif [ ${sys} = "arm-softiron" ]; then #jc_nt=1 # 5th loop #ic_nt=2 # 3rd loop #jr_nt=2 # 2nd loop #ir_nt=1 # 1st loop nt=4 elif [ ${sys} = "stampede2" ]; then jc_nt=2 # 5th loop ic_nt=1 # 3rd loop jr_nt=10 # 2nd loop ir_nt=1 # 1st loop nt=20 elif [ ${sys} = "skx" ]; then jc_1_nt=1 # 5th loop ic_1_nt=20 # 3rd loop jr_1_nt=1 # 2nd loop ir_1_nt=1 # 1st loop nt_1=20 jc_2_nt=2 # 5th loop ic_2_nt=20 # 3rd loop jr_2_nt=1 # 2nd loop ir_2_nt=1 # 1st loop nt_2=40 fi # Threadedness to test. #threads="mt" #threads_r="mt" threads="st mt" threads_r="st mt" # Datatypes to test. dts="c z " #dts="c z" #dts_r="s d" dts_r="s d" # Operations to test. l3_ops="gemm syrk hemm trmm" #l3_ops="gemm" test_ops="${l3_ops}" test_ops_r="${l3_ops}" # Complex domain implementations to test. if [ ${sys} = "blis" ]; then #test_impls="openblas mkl 3mhw_blis 3m3_blis 3m2_blis 3m1_blis 4mhw_blis 4m1b_blis 4m1a_blis" test_impls="openblas 3mhw_blis 3m3_blis 3m2_blis 3m1_blis 4mhw_blis 4m1b_blis 4m1a_blis 1m_blis" elif [ ${sys} = "stampede" ]; then test_impls="openblas mkl asm_blis 3mhw_blis 3m3_blis 3m2_blis 3m1_blis 4mhw_blis 4m1b_blis 4m1a_blis 1m_blis" #test_impls="openblas mkl asm_blis" elif [ ${sys} = "stampede2" ]; then test_impls="openblas mkl 1m_blis" #test_impls="1m_blis" elif [ ${sys} = "lonestar" ]; then test_impls="asm_blis 4mhw_blis 4m1a_blis 1m_blis 3m1_blis" #test_impls="1m_blis 3m1_blis" #test_impls="4m1a_blis" #test_impls="mkl" #test_impls="openblas mkl asm_blis" elif [ ${sys} = "wahlberg" ]; then test_impls="openblas acml asm_blis 3mhw_blis 3m3_blis 3m2_blis 3m1_blis 4mhw_blis 4m1b_blis 4m1a_blis 1m_blis" test_impls="openblas acml asm_blis" elif [ ${sys} = "arm-softiron" ]; then test_impls="openblas 1m_blis mkl" elif [ ${sys} = "skx" ]; then test_impls="openblas 1m_blis mkl" fi # Real domain implementations to test. test_impls_r="openblas mkl asm_blis" cores_r="20 40" cores="20 40" # First perform real test cases. for nc in ${cores_r}; do for dt in ${dts_r}; do for im in ${test_impls_r}; do for op in ${test_ops_r}; do if [ ${nc} -gt 1 ]; then # Unset GOMP_CPU_AFFINITY for MKL when using mkl_intel_thread. if [ ${im} = "openblas" ]; then unset GOMP_CPU_AFFINITY else export GOMP_CPU_AFFINITY="0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39" fi if [ ${nc} -eq 20 ]; then export BLIS_JC_NT=${jc_1_nt} export BLIS_IC_NT=${ic_1_nt} export BLIS_JR_NT=${jr_1_nt} export BLIS_IR_NT=${ir_1_nt} export OMP_NUM_THREADS=${nt_1} out_dir="${out_rootdir}/1socket" mkdir -p $out_rootdir/1socket elif [ ${nc} -eq 40 ]; then export BLIS_JC_NT=${jc_2_nt} export BLIS_IC_NT=${ic_2_nt} export BLIS_JR_NT=${jr_2_nt} export BLIS_IR_NT=${ir_2_nt} export OMP_NUM_THREADS=${nt_2} out_dir="${out_rootdir}/2sockets" mkdir -p $out_rootdir/2sockets fi th="mt" else export BLIS_NUM_THREADS=1 export OMP_NUM_THREADS=1 out_dir="${out_rootdir}/st" mkdir -p $out_rootdir/st th="st" fi # Construct the name of the test executable. exec_name="${exec_root}_${dt}${op}_${im}_${th}.x" # Construct the name of the output file. out_file="${out_dir}/${out_root}_${th}_${dt}${op}_${im}.m" echo "Running (nt = ${OMP_NUM_THREADS}) ./${exec_name} > ${out_file}" # Run executable. ./${exec_name} > ${out_file} sleep 1 done done done done # Now perform complex test cases. for nc in ${cores_r}; do for dt in ${dts}; do for im in ${test_impls}; do for op in ${test_ops}; do if [ ${nc} -gt 1 ]; then # Unset GOMP_CPU_AFFINITY for MKL when using mkl_intel_thread. if [ ${im} = "openblas" ]; then unset GOMP_CPU_AFFINITY else export GOMP_CPU_AFFINITY="0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39" fi if [ ${nc} -eq 20 ]; then export BLIS_JC_NT=${jc_1_nt} export BLIS_IC_NT=${ic_1_nt} export BLIS_JR_NT=${jr_1_nt} export BLIS_IR_NT=${ir_1_nt} export OMP_NUM_THREADS=${nt_1} out_dir="${out_rootdir}/1socket" elif [ ${nc} -eq 40 ]; then export BLIS_JC_NT=${jc_2_nt} export BLIS_IC_NT=${ic_2_nt} export BLIS_JR_NT=${jr_2_nt} export BLIS_IR_NT=${ir_2_nt} export OMP_NUM_THREADS=${nt_2} out_dir="${out_rootdir}/2sockets" fi th="mt" else export BLIS_NUM_THREADS=1 export OMP_NUM_THREADS=1 out_dir="${out_rootdir}/st" th="st" fi # Construct the name of the test executable. exec_name="${exec_root}_${dt}${op}_${im}_${th}.x" # Construct the name of the output file. out_file="${out_dir}/${out_root}_${th}_${dt}${op}_${im}.m" echo "Running (nt = ${OMP_NUM_THREADS}) ./${exec_name} > ${out_file}" # Run executable. ./${exec_name} > ${out_file} sleep 1 done done done done blis-0.9.0/test/studies/skx/test_gemm.c000066400000000000000000000220101422157504600200460ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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 The University of Texas 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 COPYRIGHT HOLDER 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. */ #include #include "blis.h" void zgemm3m_( f77_char*, f77_char*, f77_int*, f77_int*, f77_int*, dcomplex*, dcomplex*, f77_int*, dcomplex*, f77_int*, dcomplex*, dcomplex*, f77_int* ); //#define PRINT int main( int argc, char** argv ) { obj_t a, b, c; obj_t c_save; obj_t alpha, beta; dim_t m, n, k; dim_t p; dim_t p_begin, p_end, p_inc; int m_input, n_input, k_input; ind_t ind; num_t dt; char dt_ch; int r, n_repeats; trans_t transa; trans_t transb; f77_char f77_transa; f77_char f77_transb; double dtime; double dtime_save; double gflops; //bli_init(); //bli_error_checking_level_set( BLIS_NO_ERROR_CHECKING ); n_repeats = 3; dt = DT; ind = IND; p_begin = P_BEGIN; p_end = P_END; p_inc = P_INC; m_input = -1; n_input = -1; k_input = -1; // Supress compiler warnings about unused variable 'ind'. ( void )ind; #if 0 cntx_t* cntx; ind_t ind_mod = ind; // A hack to use 3m1 as 1mpb (with 1m as 1mbp). if ( ind == BLIS_3M1 ) ind_mod = BLIS_1M; // Initialize a context for the current induced method and datatype. cntx = bli_gks_query_ind_cntx( ind_mod, dt ); // Set k to the kc blocksize for the current datatype. k_input = bli_cntx_get_blksz_def_dt( dt, BLIS_KC, cntx ); #elif 1 //k_input = 256; #endif // Choose the char corresponding to the requested datatype. if ( bli_is_float( dt ) ) dt_ch = 's'; else if ( bli_is_double( dt ) ) dt_ch = 'd'; else if ( bli_is_scomplex( dt ) ) dt_ch = 'c'; else dt_ch = 'z'; transa = BLIS_NO_TRANSPOSE; transb = BLIS_NO_TRANSPOSE; bli_param_map_blis_to_netlib_trans( transa, &f77_transa ); bli_param_map_blis_to_netlib_trans( transb, &f77_transb ); // Begin with initializing the last entry to zero so that // matlab allocates space for the entire array once up-front. for ( p = p_begin; p + p_inc <= p_end; p += p_inc ) ; #ifdef BLIS printf( "data_%s_%cgemm_%s_blis", THR_STR, dt_ch, STR ); #else printf( "data_%s_%cgemm_%s", THR_STR, dt_ch, STR ); #endif printf( "( %2lu, 1:4 ) = [ %4lu %4lu %4lu %7.2f ];\n", ( unsigned long )(p - p_begin + 1)/p_inc + 1, ( unsigned long )0, ( unsigned long )0, ( unsigned long )0, 0.0 ); for ( p = p_begin; p <= p_end; p += p_inc ) { if ( m_input < 0 ) m = p / ( dim_t )abs(m_input); else m = ( dim_t ) m_input; if ( n_input < 0 ) n = p / ( dim_t )abs(n_input); else n = ( dim_t ) n_input; if ( k_input < 0 ) k = p / ( dim_t )abs(k_input); else k = ( dim_t ) k_input; bli_obj_create( dt, 1, 1, 0, 0, &alpha ); bli_obj_create( dt, 1, 1, 0, 0, &beta ); bli_obj_create( dt, m, k, 0, 0, &a ); bli_obj_create( dt, k, n, 0, 0, &b ); bli_obj_create( dt, m, n, 0, 0, &c ); //bli_obj_create( dt, m, k, 2, 2*m, &a ); //bli_obj_create( dt, k, n, 2, 2*k, &b ); //bli_obj_create( dt, m, n, 2, 2*m, &c ); bli_obj_create( dt, m, n, 0, 0, &c_save ); bli_randm( &a ); bli_randm( &b ); bli_randm( &c ); bli_obj_set_conjtrans( transa, &a ); bli_obj_set_conjtrans( transb, &b ); bli_setsc( (2.0/1.0), 0.0, &alpha ); bli_setsc( (1.0/1.0), 0.0, &beta ); bli_copym( &c, &c_save ); #ifdef BLIS bli_ind_disable_all_dt( dt ); bli_ind_enable_dt( ind, dt ); #endif dtime_save = DBL_MAX; for ( r = 0; r < n_repeats; ++r ) { bli_copym( &c_save, &c ); dtime = bli_clock(); #ifdef PRINT bli_printm( "a", &a, "%4.1f", "" ); bli_printm( "b", &b, "%4.1f", "" ); bli_printm( "c", &c, "%4.1f", "" ); #endif #ifdef BLIS bli_gemm( &alpha, &a, &b, &beta, &c ); #else if ( bli_is_float( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); float* alphap = bli_obj_buffer( &alpha ); float* ap = bli_obj_buffer( &a ); float* bp = bli_obj_buffer( &b ); float* betap = bli_obj_buffer( &beta ); float* cp = bli_obj_buffer( &c ); sgemm_( &f77_transa, &f77_transb, &mm, &nn, &kk, alphap, ap, &lda, bp, &ldb, betap, cp, &ldc ); } else if ( bli_is_double( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); double* alphap = bli_obj_buffer( &alpha ); double* ap = bli_obj_buffer( &a ); double* bp = bli_obj_buffer( &b ); double* betap = bli_obj_buffer( &beta ); double* cp = bli_obj_buffer( &c ); dgemm_( &f77_transa, &f77_transb, &mm, &nn, &kk, alphap, ap, &lda, bp, &ldb, betap, cp, &ldc ); } else if ( bli_is_scomplex( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); scomplex* alphap = bli_obj_buffer( &alpha ); scomplex* ap = bli_obj_buffer( &a ); scomplex* bp = bli_obj_buffer( &b ); scomplex* betap = bli_obj_buffer( &beta ); scomplex* cp = bli_obj_buffer( &c ); cgemm_( &f77_transa, &f77_transb, &mm, &nn, &kk, alphap, ap, &lda, bp, &ldb, betap, cp, &ldc ); } else if ( bli_is_dcomplex( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); dcomplex* alphap = bli_obj_buffer( &alpha ); dcomplex* ap = bli_obj_buffer( &a ); dcomplex* bp = bli_obj_buffer( &b ); dcomplex* betap = bli_obj_buffer( &beta ); dcomplex* cp = bli_obj_buffer( &c ); zgemm_( &f77_transa, //zgemm3m_( &f77_transa, &f77_transb, &mm, &nn, &kk, alphap, ap, &lda, bp, &ldb, betap, cp, &ldc ); } #endif #ifdef PRINT bli_printm( "c after", &c, "%4.1f", "" ); exit(1); #endif dtime_save = bli_clock_min_diff( dtime_save, dtime ); } gflops = ( 2.0 * m * k * n ) / ( dtime_save * 1.0e9 ); if ( bli_is_complex( dt ) ) gflops *= 4.0; #ifdef BLIS printf( "data_%s_%cgemm_%s_blis", THR_STR, dt_ch, STR ); #else printf( "data_%s_%cgemm_%s", THR_STR, dt_ch, STR ); #endif printf( "( %2lu, 1:4 ) = [ %4lu %4lu %4lu %7.2f ];\n", ( unsigned long )(p - p_begin + 1)/p_inc + 1, ( unsigned long )m, ( unsigned long )k, ( unsigned long )n, gflops ); bli_obj_free( &alpha ); bli_obj_free( &beta ); bli_obj_free( &a ); bli_obj_free( &b ); bli_obj_free( &c ); bli_obj_free( &c_save ); } //bli_finalize(); return 0; } blis-0.9.0/test/studies/skx/test_hemm.c000066400000000000000000000210761422157504600200620ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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 The University of Texas 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 COPYRIGHT HOLDER 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. */ #include #include "blis.h" void zgemm3m_( f77_char*, f77_char*, f77_int*, f77_int*, f77_int*, dcomplex*, dcomplex*, f77_int*, dcomplex*, f77_int*, dcomplex*, dcomplex*, f77_int* ); //#define PRINT int main( int argc, char** argv ) { obj_t a, b, c; obj_t c_save; obj_t alpha, beta; dim_t m, n; dim_t p; dim_t p_begin, p_end, p_inc; int m_input, n_input; ind_t ind; num_t dt; char dt_ch; int r, n_repeats; side_t side; uplo_t uploa; f77_char f77_side; f77_char f77_uploa; double dtime; double dtime_save; double gflops; //bli_init(); //bli_error_checking_level_set( BLIS_NO_ERROR_CHECKING ); n_repeats = 3; dt = DT; ind = IND; p_begin = P_BEGIN; p_end = P_END; p_inc = P_INC; m_input = -1; n_input = -1; // Supress compiler warnings about unused variable 'ind'. ( void )ind; #if 0 cntx_t* cntx; ind_t ind_mod = ind; // A hack to use 3m1 as 1mpb (with 1m as 1mbp). if ( ind == BLIS_3M1 ) ind_mod = BLIS_1M; // Initialize a context for the current induced method and datatype. cntx = bli_gks_query_ind_cntx( ind_mod, dt ); // Set k to the kc blocksize for the current datatype. k_input = bli_cntx_get_blksz_def_dt( dt, BLIS_KC, cntx ); #elif 1 //k_input = 256; #endif // Choose the char corresponding to the requested datatype. if ( bli_is_float( dt ) ) dt_ch = 's'; else if ( bli_is_double( dt ) ) dt_ch = 'd'; else if ( bli_is_scomplex( dt ) ) dt_ch = 'c'; else dt_ch = 'z'; side = BLIS_LEFT; uploa = BLIS_LOWER; bli_param_map_blis_to_netlib_side( side, &f77_side ); bli_param_map_blis_to_netlib_uplo( uploa, &f77_uploa ); // Begin with initializing the last entry to zero so that // matlab allocates space for the entire array once up-front. for ( p = p_begin; p + p_inc <= p_end; p += p_inc ) ; #ifdef BLIS printf( "data_%s_%chemm_%s_blis", THR_STR, dt_ch, STR ); #else printf( "data_%s_%chemm_%s", THR_STR, dt_ch, STR ); #endif printf( "( %2lu, 1:3 ) = [ %4lu %4lu %7.2f ];\n", ( unsigned long )(p - p_begin + 1)/p_inc + 1, ( unsigned long )0, ( unsigned long )0, 0.0 ); for ( p = p_begin; p <= p_end; p += p_inc ) { if ( m_input < 0 ) m = p / ( dim_t )abs(m_input); else m = ( dim_t ) m_input; if ( n_input < 0 ) n = p / ( dim_t )abs(n_input); else n = ( dim_t ) n_input; bli_obj_create( dt, 1, 1, 0, 0, &alpha ); bli_obj_create( dt, 1, 1, 0, 0, &beta ); if (bli_is_left(side)) bli_obj_create( dt, m, m, 0, 0, &a ); else bli_obj_create( dt, n, n, 0, 0, &a ); bli_obj_create( dt, m, n, 0, 0, &b ); bli_obj_create( dt, m, n, 0, 0, &c ); bli_obj_create( dt, m, n, 0, 0, &c_save ); bli_randm( &a ); bli_randm( &b ); bli_randm( &c ); bli_obj_set_struc( BLIS_HERMITIAN, &a ); bli_obj_set_uplo( uploa, &a ); bli_mkherm( &a ); bli_mktrim( &a ); bli_setsc( (2.0/1.0), 0.0, &alpha ); bli_setsc( (1.0/1.0), 0.0, &beta ); bli_copym( &c, &c_save ); #ifdef BLIS bli_ind_disable_all_dt( dt ); bli_ind_enable_dt( ind, dt ); #endif dtime_save = DBL_MAX; for ( r = 0; r < n_repeats; ++r ) { bli_copym( &c_save, &c ); dtime = bli_clock(); #ifdef PRINT bli_printm( "a", &a, "%4.1f", "" ); bli_printm( "b", &b, "%4.1f", "" ); bli_printm( "c", &c, "%4.1f", "" ); #endif #ifdef BLIS bli_hemm( side, &alpha, &a, &b, &beta, &c ); #else if ( bli_is_float( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); float* alphap = bli_obj_buffer( &alpha ); float* ap = bli_obj_buffer( &a ); float* bp = bli_obj_buffer( &b ); float* betap = bli_obj_buffer( &beta ); float* cp = bli_obj_buffer( &c ); ssymm_( &f77_side, &f77_uploa, &mm, &nn, alphap, ap, &lda, bp, &ldb, betap, cp, &ldc ); } else if ( bli_is_double( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); double* alphap = bli_obj_buffer( &alpha ); double* ap = bli_obj_buffer( &a ); double* bp = bli_obj_buffer( &b ); double* betap = bli_obj_buffer( &beta ); double* cp = bli_obj_buffer( &c ); dsymm_( &f77_side, &f77_uploa, &mm, &nn, alphap, ap, &lda, bp, &ldb, betap, cp, &ldc ); } else if ( bli_is_scomplex( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); scomplex* alphap = bli_obj_buffer( &alpha ); scomplex* ap = bli_obj_buffer( &a ); scomplex* bp = bli_obj_buffer( &b ); scomplex* betap = bli_obj_buffer( &beta ); scomplex* cp = bli_obj_buffer( &c ); chemm_( &f77_side, &f77_uploa, &mm, &nn, alphap, ap, &lda, bp, &ldb, betap, cp, &ldc ); } else if ( bli_is_dcomplex( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); dcomplex* alphap = bli_obj_buffer( &alpha ); dcomplex* ap = bli_obj_buffer( &a ); dcomplex* bp = bli_obj_buffer( &b ); dcomplex* betap = bli_obj_buffer( &beta ); dcomplex* cp = bli_obj_buffer( &c ); zhemm_( &f77_side, &f77_uploa, &mm, &nn, alphap, ap, &lda, bp, &ldb, betap, cp, &ldc ); } #endif #ifdef PRINT bli_printm( "c after", &c, "%4.1f", "" ); exit(1); #endif dtime_save = bli_clock_min_diff( dtime_save, dtime ); } if ( bli_is_left(side) ) gflops = ( 2.0 * m * m * n ) / ( dtime_save * 1.0e9 ); else gflops = ( 2.0 * m * n * n ) / ( dtime_save * 1.0e9 ); if ( bli_is_complex( dt ) ) gflops *= 4.0; #ifdef BLIS printf( "data_%s_%chemm_%s_blis", THR_STR, dt_ch, STR ); #else printf( "data_%s_%chemm_%s", THR_STR, dt_ch, STR ); #endif printf( "( %2lu, 1:3 ) = [ %4lu %4lu %7.2f ];\n", ( unsigned long )(p - p_begin + 1)/p_inc + 1, ( unsigned long )m, ( unsigned long )n, gflops ); bli_obj_free( &alpha ); bli_obj_free( &beta ); bli_obj_free( &a ); bli_obj_free( &b ); bli_obj_free( &c ); bli_obj_free( &c_save ); } //bli_finalize(); return 0; } blis-0.9.0/test/studies/skx/test_syrk.c000066400000000000000000000176141422157504600201270ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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 The University of Texas 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 COPYRIGHT HOLDER 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. */ #include #include "blis.h" //#define PRINT int main( int argc, char** argv ) { obj_t a, c; obj_t c_save; obj_t alpha, beta; dim_t m, k; dim_t p; dim_t p_begin, p_end, p_inc; int m_input, k_input; ind_t ind; num_t dt; char dt_ch; int r, n_repeats; trans_t transa; uplo_t uploc; f77_char f77_transa; f77_char f77_uploc; double dtime; double dtime_save; double gflops; //bli_init(); //bli_error_checking_level_set( BLIS_NO_ERROR_CHECKING ); n_repeats = 3; dt = DT; ind = IND; p_begin = P_BEGIN; p_end = P_END; p_inc = P_INC; m_input = -1; k_input = -1; // Supress compiler warnings about unused variable 'ind'. ( void )ind; #if 0 cntx_t* cntx; ind_t ind_mod = ind; // A hack to use 3m1 as 1mpb (with 1m as 1mbp). if ( ind == BLIS_3M1 ) ind_mod = BLIS_1M; // Initialize a context for the current induced method and datatype. cntx = bli_gks_query_ind_cntx( ind_mod, dt ); // Set k to the kc blocksize for the current datatype. k_input = bli_cntx_get_blksz_def_dt( dt, BLIS_KC, cntx ); #elif 1 //k_input = 256; #endif // Choose the char corresponding to the requested datatype. if ( bli_is_float( dt ) ) dt_ch = 's'; else if ( bli_is_double( dt ) ) dt_ch = 'd'; else if ( bli_is_scomplex( dt ) ) dt_ch = 'c'; else dt_ch = 'z'; transa = BLIS_NO_TRANSPOSE; uploc = BLIS_LOWER; bli_param_map_blis_to_netlib_trans( transa, &f77_transa ); bli_param_map_blis_to_netlib_uplo ( uploc, &f77_uploc ); // Begin with initializing the last entry to zero so that // matlab allocates space for the entire array once up-front. for ( p = p_begin; p + p_inc <= p_end; p += p_inc ) ; #ifdef BLIS printf( "data_%s_%csyrk_%s_blis", THR_STR, dt_ch, STR ); #else printf( "data_%s_%csyrk_%s", THR_STR, dt_ch, STR ); #endif printf( "( %2lu, 1:3 ) = [ %4lu %4lu %7.2f ];\n", ( unsigned long )(p - p_begin + 1)/p_inc + 1, ( unsigned long )0, ( unsigned long )0, 0.0 ); for ( p = p_begin; p <= p_end; p += p_inc ) { if ( m_input < 0 ) m = p / ( dim_t )abs(m_input); else m = ( dim_t ) m_input; if ( k_input < 0 ) k = p / ( dim_t )abs(k_input); else k = ( dim_t ) k_input; bli_obj_create( dt, 1, 1, 0, 0, &alpha ); bli_obj_create( dt, 1, 1, 0, 0, &beta ); bli_obj_create( dt, m, k, 0, 0, &a ); bli_obj_create( dt, m, m, 0, 0, &c ); //bli_obj_create( dt, m, k, 2, 2*m, &a ); //bli_obj_create( dt, k, n, 2, 2*k, &b ); //bli_obj_create( dt, m, n, 2, 2*m, &c ); bli_obj_create( dt, m, m, 0, 0, &c_save ); bli_randm( &a ); bli_obj_set_struc( BLIS_SYMMETRIC, &c ); bli_obj_set_uplo ( uploc, &c ); bli_randm( &c ); bli_obj_set_conjtrans( transa, &a ); bli_setsc( (2.0/1.0), 0.0, &alpha ); bli_setsc( (1.0/1.0), 0.0, &beta ); bli_copym( &c, &c_save ); #ifdef BLIS bli_ind_disable_all_dt( dt ); bli_ind_enable_dt( ind, dt ); #endif dtime_save = DBL_MAX; for ( r = 0; r < n_repeats; ++r ) { bli_copym( &c_save, &c ); dtime = bli_clock(); #ifdef PRINT bli_printm( "a", &a, "%4.1f", "" ); bli_printm( "c", &c, "%4.1f", "" ); #endif #ifdef BLIS bli_syrk( &alpha, &a, &beta, &c ); #else if ( bli_is_float( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldc = bli_obj_col_stride( &c ); float* alphap = bli_obj_buffer( &alpha ); float* ap = bli_obj_buffer( &a ); float* betap = bli_obj_buffer( &beta ); float* cp = bli_obj_buffer( &c ); ssyrk_( &f77_uploc, &f77_transa, &mm, &kk, alphap, ap, &lda, betap, cp, &ldc ); } else if ( bli_is_double( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldc = bli_obj_col_stride( &c ); double* alphap = bli_obj_buffer( &alpha ); double* ap = bli_obj_buffer( &a ); double* betap = bli_obj_buffer( &beta ); double* cp = bli_obj_buffer( &c ); dsyrk_( &f77_uploc, &f77_transa, &mm, &kk, alphap, ap, &lda, betap, cp, &ldc ); } else if ( bli_is_scomplex( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldc = bli_obj_col_stride( &c ); scomplex* alphap = bli_obj_buffer( &alpha ); scomplex* ap = bli_obj_buffer( &a ); scomplex* betap = bli_obj_buffer( &beta ); scomplex* cp = bli_obj_buffer( &c ); csyrk_( &f77_uploc, &f77_transa, &mm, &kk, alphap, ap, &lda, betap, cp, &ldc ); } else if ( bli_is_dcomplex( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldc = bli_obj_col_stride( &c ); dcomplex* alphap = bli_obj_buffer( &alpha ); dcomplex* ap = bli_obj_buffer( &a ); dcomplex* betap = bli_obj_buffer( &beta ); dcomplex* cp = bli_obj_buffer( &c ); zsyrk_( &f77_uploc, &f77_transa, &mm, &kk, alphap, ap, &lda, betap, cp, &ldc ); } #endif #ifdef PRINT bli_printm( "c after", &c, "%4.1f", "" ); exit(1); #endif dtime_save = bli_clock_min_diff( dtime_save, dtime ); } gflops = ( 1.0 * m * m * k ) / ( dtime_save * 1.0e9 ); if ( bli_is_complex( dt ) ) gflops *= 4.0; #ifdef BLIS printf( "data_%s_%csyrk_%s_blis", THR_STR, dt_ch, STR ); #else printf( "data_%s_%csyrk_%s", THR_STR, dt_ch, STR ); #endif printf( "( %2lu, 1:3 ) = [ %4lu %4lu %7.2f ];\n", ( unsigned long )(p - p_begin + 1)/p_inc + 1, ( unsigned long )m, ( unsigned long )k, gflops ); bli_obj_free( &alpha ); bli_obj_free( &beta ); bli_obj_free( &a ); bli_obj_free( &c ); bli_obj_free( &c_save ); } //bli_finalize(); return 0; } blis-0.9.0/test/studies/skx/test_trmm.c000066400000000000000000000176341422157504600201200ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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 The University of Texas 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 COPYRIGHT HOLDER 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. */ #include #include "blis.h" //#define PRINT int main( int argc, char** argv ) { obj_t a, c; obj_t c_save; obj_t alpha; dim_t m, n; dim_t p; dim_t p_begin, p_end, p_inc; int m_input, n_input; ind_t ind; num_t dt; char dt_ch; int r, n_repeats; side_t side; uplo_t uploa; trans_t transa; diag_t diaga; f77_char f77_side; f77_char f77_uploa; f77_char f77_transa; f77_char f77_diaga; double dtime; double dtime_save; double gflops; //bli_init(); //bli_error_checking_level_set( BLIS_NO_ERROR_CHECKING ); n_repeats = 3; dt = DT; ind = IND; p_begin = P_BEGIN; p_end = P_END; p_inc = P_INC; m_input = -1; n_input = -1; // Supress compiler warnings about unused variable 'ind'. ( void )ind; #if 0 cntx_t* cntx; ind_t ind_mod = ind; // A hack to use 3m1 as 1mpb (with 1m as 1mbp). if ( ind == BLIS_3M1 ) ind_mod = BLIS_1M; // Initialize a context for the current induced method and datatype. cntx = bli_gks_query_ind_cntx( ind_mod, dt ); // Set k to the kc blocksize for the current datatype. k_input = bli_cntx_get_blksz_def_dt( dt, BLIS_KC, cntx ); #elif 1 //k_input = 256; #endif // Choose the char corresponding to the requested datatype. if ( bli_is_float( dt ) ) dt_ch = 's'; else if ( bli_is_double( dt ) ) dt_ch = 'd'; else if ( bli_is_scomplex( dt ) ) dt_ch = 'c'; else dt_ch = 'z'; side = BLIS_LEFT; uploa = BLIS_LOWER; transa = BLIS_NO_TRANSPOSE; diaga = BLIS_NONUNIT_DIAG; bli_param_map_blis_to_netlib_side( side, &f77_side ); bli_param_map_blis_to_netlib_uplo( uploa, &f77_uploa ); bli_param_map_blis_to_netlib_trans( transa, &f77_transa ); bli_param_map_blis_to_netlib_diag( diaga, &f77_diaga ); // Begin with initializing the last entry to zero so that // matlab allocates space for the entire array once up-front. for ( p = p_begin; p + p_inc <= p_end; p += p_inc ) ; #ifdef BLIS printf( "data_%s_%ctrmm_%s_blis", THR_STR, dt_ch, STR ); #else printf( "data_%s_%ctrmm_%s", THR_STR, dt_ch, STR ); #endif printf( "( %2lu, 1:3 ) = [ %4lu %4lu %7.2f ];\n", ( unsigned long )(p - p_begin + 1)/p_inc + 1, ( unsigned long )0, ( unsigned long )0, 0.0 ); for ( p = p_begin; p <= p_end; p += p_inc ) { if ( m_input < 0 ) m = p / ( dim_t )abs(m_input); else m = ( dim_t ) m_input; if ( n_input < 0 ) n = p / ( dim_t )abs(n_input); else n = ( dim_t ) n_input; bli_obj_create( dt, 1, 1, 0, 0, &alpha ); if ( bli_is_left( side ) ) bli_obj_create( dt, m, m, 0, 0, &a ); else bli_obj_create( dt, n, n, 0, 0, &a ); bli_obj_create( dt, m, n, 0, 0, &c ); bli_obj_create( dt, m, n, 0, 0, &c_save ); bli_randm( &a ); bli_randm( &c ); bli_obj_set_struc( BLIS_TRIANGULAR, &a ); bli_obj_set_uplo( uploa, &a ); bli_obj_set_conjtrans( transa, &a ); bli_obj_set_diag( diaga, &a ); bli_setsc( (2.0/1.0), 0.0, &alpha ); bli_copym( &c, &c_save ); #ifdef BLIS bli_ind_disable_all_dt( dt ); bli_ind_enable_dt( ind, dt ); #endif dtime_save = DBL_MAX; for ( r = 0; r < n_repeats; ++r ) { bli_copym( &c_save, &c ); dtime = bli_clock(); #ifdef PRINT bli_printm( "a", &a, "%4.1f", "" ); bli_printm( "b", &b, "%4.1f", "" ); bli_printm( "c", &c, "%4.1f", "" ); #endif #ifdef BLIS bli_trmm( side, &alpha, &a, &c ); #else if ( bli_is_float( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldc = bli_obj_col_stride( &c ); float* alphap = bli_obj_buffer( &alpha ); float* ap = bli_obj_buffer( &a ); float* cp = bli_obj_buffer( &c ); strmm_( &f77_side, &f77_uploa, &f77_transa, &f77_diaga, &mm, &nn, alphap, ap, &lda, cp, &ldc ); } else if ( bli_is_double( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldc = bli_obj_col_stride( &c ); double* alphap = bli_obj_buffer( &alpha ); double* ap = bli_obj_buffer( &a ); double* cp = bli_obj_buffer( &c ); dtrmm_( &f77_side, &f77_uploa, &f77_transa, &f77_diaga, &mm, &nn, alphap, ap, &lda, cp, &ldc ); } else if ( bli_is_scomplex( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldc = bli_obj_col_stride( &c ); scomplex* alphap = bli_obj_buffer( &alpha ); scomplex* ap = bli_obj_buffer( &a ); scomplex* cp = bli_obj_buffer( &c ); ctrmm_( &f77_side, &f77_uploa, &f77_transa, &f77_diaga, &mm, &nn, alphap, ap, &lda, cp, &ldc ); } else if ( bli_is_dcomplex( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldc = bli_obj_col_stride( &c ); dcomplex* alphap = bli_obj_buffer( &alpha ); dcomplex* ap = bli_obj_buffer( &a ); dcomplex* cp = bli_obj_buffer( &c ); ztrmm_( &f77_side, &f77_uploa, &f77_transa, &f77_diaga, &mm, &nn, alphap, ap, &lda, cp, &ldc ); } #endif #ifdef PRINT bli_printm( "c after", &c, "%4.1f", "" ); exit(1); #endif dtime_save = bli_clock_min_diff( dtime_save, dtime ); } if ( bli_is_left(side) ) gflops = ( 1.0 * m * m * n ) / ( dtime_save * 1.0e9 ); else gflops = ( 1.0 * m * n * n ) / ( dtime_save * 1.0e9 ); if ( bli_is_complex( dt ) ) gflops *= 4.0; #ifdef BLIS printf( "data_%s_%ctrmm_%s_blis", THR_STR, dt_ch, STR ); #else printf( "data_%s_%ctrmm_%s", THR_STR, dt_ch, STR ); #endif printf( "( %2lu, 1:3 ) = [ %4lu %4lu %7.2f ];\n", ( unsigned long )(p - p_begin + 1)/p_inc + 1, ( unsigned long )m, ( unsigned long )n, gflops ); bli_obj_free( &alpha ); bli_obj_free( &a ); bli_obj_free( &c ); bli_obj_free( &c_save ); } //bli_finalize(); return 0; } blis-0.9.0/test/studies/thunderx2/000077500000000000000000000000001422157504600170415ustar00rootroot00000000000000blis-0.9.0/test/studies/thunderx2/Makefile000066400000000000000000000476461422157504600205220ustar00rootroot00000000000000#!/bin/bash # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2014, The University of Texas at Austin # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # # # Makefile # # Field G. Van Zee # # Makefile for standalone BLIS test drivers. # # # --- Makefile PHONY target definitions ---------------------------------------- # .PHONY: all \ blis-gemm-st openblas-gemm-st mkl-gemm-st acml-gemm-st \ blis-gemm-mt openblas-gemm-mt mkl-gemm-mt acml-gemm-mt \ blis-syrk-st openblas-syrk-st mkl-syrk-st armpl-syrk-st \ blis-syrk-mt openblas-syrk-mt mkl-syrk-mt armpl-syrk-mt \ blis-hemm-st openblas-hemm-st mkl-hemm-st armpl-hemm-st \ blis-hemm-mt openblas-hemm-mt mkl-hemm-mt armpl-hemm-mt \ blis-trmm-st openblas-trmm-st mkl-trmm-st armpl-trmm-st \ blis-trmm-mt openblas-trmm-mt mkl-trmm-mt armpl-trmm-mt \ clean cleanx # Comments: # - DIST_PATH is assumed to not exist if BLIS_INSTALL_PATH is given. # - We must use recursively expanded assignment for LIB_PATH and INC_PATH in # the second case because CONFIG_NAME is not yet set. ifneq ($(strip $(BLIS_INSTALL_PATH)),) LIB_PATH := $(BLIS_INSTALL_PATH)/lib INC_PATH := $(BLIS_INSTALL_PATH)/include/blis SHARE_PATH := $(BLIS_INSTALL_PATH)/share/blis else DIST_PATH := ../../.. LIB_PATH = ../../../lib/$(CONFIG_NAME) INC_PATH = ../../../include/$(CONFIG_NAME) SHARE_PATH := ../../.. endif # # --- Include common makefile definitions -------------------------------------- # # Include the common makefile fragment. -include $(SHARE_PATH)/common.mk # # --- BLAS and LAPACK implementations ------------------------------------------ # # BLIS library and header path. This is simply wherever it was installed. #BLIS_LIB_PATH := $(INSTALL_PREFIX)/lib BLIS_INC_PATH := $(INSTALL_PREFIX)/include/blis # BLIS library. #BLIS_LIB := $(BLIS_LIB_PATH)/libblis.a # BLAS library path(s). This is where the BLAS libraries reside. HOME_LIB_PATH := $(HOME)/OpenBLAS/lib MKL_LIB_PATH := ${MKLROOT}/lib/intel64 ARMPL_LIB_PATH := /opt/arm/armpl-18.4.0_ThunderX2CN99_Ubuntu-16.04_gcc_7.1.0_aarch64-linux/lib/ ACML_LIB_PATH := $(HOME_LIB_PATH)/acml/5.3.1/gfortran64_fma4_int64/lib ACMLP_LIB_PATH := $(HOME_LIB_PATH)/acml/5.3.1/gfortran64_fma4_mp_int64/lib # OpenBLAS OPENBLAS_LIB := $(HOME_LIB_PATH)/libopenblas.a OPENBLASP_LIB := $(HOME_LIB_PATH)/libopenblas.a # ATLAS ATLAS_LIB := $(HOME_LIB_PATH)/libf77blas.a \ $(HOME_LIB_PATH)/libatlas.a # For ARMPL ARMPL_LIB := $(ARMPL_LIB_PATH)/libarmpl_lp64.a ARMPLP_LIB := $(ARMPL_LIB_PATH)/libarmpl_lp64_mp.a # MKL MKL_LIB := -L$(MKL_LIB_PATH) \ -lmkl_intel_lp64 \ -lmkl_core \ -lmkl_sequential \ -lpthread -lm -ldl #MKLP_LIB := -L$(MKL_LIB_PATH) \ # -lmkl_intel_thread \ # -lmkl_core \ # -lmkl_intel_ilp64 \ # -L$(ICC_LIB_PATH) \ # -liomp5 MKLP_LIB := -L$(MKL_LIB_PATH) \ -lmkl_intel_lp64 \ -lmkl_core \ -lmkl_gnu_thread \ -lpthread -lm -ldl -fopenmp #-L$(ICC_LIB_PATH) \ #-lgomp # ACML ACML_LIB := -L$(ACML_LIB_PATH) \ -lgfortran -lm -lrt -ldl -lacml ACMLP_LIB := -L$(ACMLP_LIB_PATH) \ -lgfortran -lm -lrt -ldl -lacml_mp # # --- General build definitions ------------------------------------------------ # TEST_SRC_PATH := . TEST_OBJ_PATH := . # Gather all local object files. TEST_OBJS := $(sort $(patsubst $(TEST_SRC_PATH)/%.c, \ $(TEST_OBJ_PATH)/%.o, \ $(wildcard $(TEST_SRC_PATH)/*.c))) # Use the "framework" CFLAGS for the configuration family. CFLAGS := $(call get-frame-cflags-for,$(CONFIG_NAME)) # Add local header paths to CFLAGS. CFLAGS += -g -I$(TEST_SRC_PATH) # Locate the libblis library to which we will link. #LIBBLIS_LINK := $(LIB_PATH)/$(LIBBLIS_L) # Datatype DT_S := -DDT=BLIS_FLOAT DT_D := -DDT=BLIS_DOUBLE DT_C := -DDT=BLIS_SCOMPLEX DT_Z := -DDT=BLIS_DCOMPLEX # Which library? BLI_DEF := -DBLIS BLA_DEF := -DBLAS # Complex implementation type D3MHW := -DIND=BLIS_3MH D3M1 := -DIND=BLIS_3M1 D4MHW := -DIND=BLIS_4MH D4M1B := -DIND=BLIS_4M1B D4M1A := -DIND=BLIS_4M1A D1M := -DIND=BLIS_1M DNAT := -DIND=BLIS_NAT # Implementation string STR_3MHW := -DSTR=\"3mhw\" STR_3M1 := -DSTR=\"3m1\" STR_4MHW := -DSTR=\"4mhw\" STR_4M1B := -DSTR=\"4m1b\" STR_4M1A := -DSTR=\"4m1a\" STR_1M := -DSTR=\"1m\" STR_NAT := -DSTR=\"asm\" STR_OBL := -DSTR=\"openblas\" STR_MKL := -DSTR=\"mkl\" STR_ACML := -DSTR=\"acml\" STR_ARMPL:= -DSTR=\"armpl\" # Single or multithreaded string STR_ST := -DTHR_STR=\"st\" STR_MT := -DTHR_STR=\"mt\" # Problem size specification PDEF_ST := -DP_BEGIN=40 \ -DP_END=2000 \ -DP_INC=40 PDEF_MT := -DP_BEGIN=200 \ -DP_END=10000 \ -DP_INC=200 # # --- Targets/rules ------------------------------------------------------------ # all-st: blis-st openblas-st armpl-st all-mt: blis-mt openblas-mt armpl-mt blis-st: blis-gemm-st blis-syrk-st blis-hemm-st blis-trmm-st blis-mt: blis-gemm-mt blis-syrk-mt blis-hemm-mt blis-trmm-mt openblas-st: openblas-gemm-st openblas-syrk-st openblas-hemm-st openblas-trmm-st openblas-mt: openblas-gemm-mt openblas-syrk-mt openblas-hemm-mt openblas-trmm-mt mkl-st: mkl-gemm-st mkl-syrk-st mkl-hemm-st mkl-trmm-st mkl-mt: mkl-gemm-mt mkl-syrk-mt mkl-hemm-mt mkl-trmm-mt armpl-st: armpl-gemm-st armpl-syrk-st armpl-hemm-st armpl-trmm-st armpl-mt: armpl-gemm-mt armpl-syrk-mt armpl-hemm-mt armpl-trmm-mt blis-gemm-st: \ test_sgemm_asm_blis_st.x \ test_dgemm_asm_blis_st.x \ \ test_cgemm_1m_blis_st.x \ test_zgemm_1m_blis_st.x \ test_cgemm_asm_blis_st.x \ test_zgemm_asm_blis_st.x blis-syrk-st: \ test_ssyrk_asm_blis_st.x \ test_dsyrk_asm_blis_st.x \ test_csyrk_1m_blis_st.x \ test_zsyrk_1m_blis_st.x blis-syrk-mt: \ test_ssyrk_asm_blis_mt.x \ test_dsyrk_asm_blis_mt.x \ test_csyrk_1m_blis_mt.x \ test_zsyrk_1m_blis_mt.x blis-hemm-st: \ test_shemm_asm_blis_st.x \ test_dhemm_asm_blis_st.x \ test_chemm_1m_blis_st.x \ test_zhemm_1m_blis_st.x blis-hemm-mt: \ test_shemm_asm_blis_mt.x \ test_dhemm_asm_blis_mt.x \ test_chemm_1m_blis_mt.x \ test_zhemm_1m_blis_mt.x blis-trmm-st: \ test_strmm_asm_blis_st.x \ test_dtrmm_asm_blis_st.x \ test_ctrmm_1m_blis_st.x \ test_ztrmm_1m_blis_st.x blis-trmm-mt: \ test_strmm_asm_blis_mt.x \ test_dtrmm_asm_blis_mt.x \ test_ctrmm_1m_blis_mt.x \ test_ztrmm_1m_blis_mt.x blis-gemm-mt: \ test_sgemm_asm_blis_mt.x \ test_dgemm_asm_blis_mt.x \ \ test_cgemm_1m_blis_mt.x \ test_zgemm_1m_blis_mt.x \ test_cgemm_asm_blis_mt.x \ test_zgemm_asm_blis_mt.x openblas-gemm-st: \ test_sgemm_openblas_st.x \ test_dgemm_openblas_st.x \ test_cgemm_openblas_st.x \ test_zgemm_openblas_st.x openblas-gemm-mt: \ test_sgemm_openblas_mt.x \ test_dgemm_openblas_mt.x \ test_cgemm_openblas_mt.x \ test_zgemm_openblas_mt.x openblas-syrk-st: \ test_ssyrk_openblas_st.x \ test_dsyrk_openblas_st.x \ test_csyrk_openblas_st.x \ test_zsyrk_openblas_st.x openblas-syrk-mt: \ test_ssyrk_openblas_mt.x \ test_dsyrk_openblas_mt.x \ test_csyrk_openblas_mt.x \ test_zsyrk_openblas_mt.x openblas-hemm-st: \ test_shemm_openblas_st.x \ test_dhemm_openblas_st.x \ test_chemm_openblas_st.x \ test_zhemm_openblas_st.x openblas-hemm-mt: \ test_shemm_openblas_mt.x \ test_dhemm_openblas_mt.x \ test_chemm_openblas_mt.x \ test_zhemm_openblas_mt.x openblas-trmm-st: \ test_strmm_openblas_st.x \ test_dtrmm_openblas_st.x \ test_ctrmm_openblas_st.x \ test_ztrmm_openblas_st.x openblas-trmm-mt: \ test_strmm_openblas_mt.x \ test_dtrmm_openblas_mt.x \ test_ctrmm_openblas_mt.x \ test_ztrmm_openblas_mt.x mkl-gemm-st: \ test_sgemm_mkl_st.x \ test_dgemm_mkl_st.x \ test_cgemm_mkl_st.x \ test_zgemm_mkl_st.x mkl-gemm-mt: \ test_sgemm_mkl_mt.x \ test_dgemm_mkl_mt.x \ test_cgemm_mkl_mt.x \ test_zgemm_mkl_mt.x mkl-syrk-st: \ test_ssyrk_mkl_st.x \ test_dsyrk_mkl_st.x \ test_csyrk_mkl_st.x \ test_zsyrk_mkl_st.x mkl-syrk-mt: \ test_ssyrk_mkl_mt.x \ test_dsyrk_mkl_mt.x \ test_csyrk_mkl_mt.x \ test_zsyrk_mkl_mt.x mkl-hemm-st: \ test_shemm_mkl_st.x \ test_dhemm_mkl_st.x \ test_chemm_mkl_st.x \ test_zhemm_mkl_st.x mkl-hemm-mt: \ test_shemm_mkl_mt.x \ test_dhemm_mkl_mt.x \ test_chemm_mkl_mt.x \ test_zhemm_mkl_mt.x mkl-trmm-st: \ test_strmm_mkl_st.x \ test_dtrmm_mkl_st.x \ test_ctrmm_mkl_st.x \ test_ztrmm_mkl_st.x mkl-trmm-mt: \ test_strmm_mkl_mt.x \ test_dtrmm_mkl_mt.x \ test_ctrmm_mkl_mt.x \ test_ztrmm_mkl_mt.x armpl-gemm-st: \ test_sgemm_armpl_st.x \ test_dgemm_armpl_st.x \ test_cgemm_armpl_st.x \ test_zgemm_armpl_st.x armpl-gemm-mt: \ test_sgemm_armpl_mt.x \ test_dgemm_armpl_mt.x \ test_cgemm_armpl_mt.x \ test_zgemm_armpl_mt.x armpl-syrk-st: \ test_ssyrk_armpl_st.x \ test_dsyrk_armpl_st.x \ test_csyrk_armpl_st.x \ test_zsyrk_armpl_st.x armpl-syrk-mt: \ test_ssyrk_armpl_mt.x \ test_dsyrk_armpl_mt.x \ test_csyrk_armpl_mt.x \ test_zsyrk_armpl_mt.x armpl-hemm-st: \ test_shemm_armpl_st.x \ test_dhemm_armpl_st.x \ test_chemm_armpl_st.x \ test_zhemm_armpl_st.x armpl-hemm-mt: \ test_shemm_armpl_mt.x \ test_dhemm_armpl_mt.x \ test_chemm_armpl_mt.x \ test_zhemm_armpl_mt.x armpl-trmm-st: \ test_strmm_armpl_st.x \ test_dtrmm_armpl_st.x \ test_ctrmm_armpl_st.x \ test_ztrmm_armpl_st.x armpl-trmm-mt: \ test_strmm_armpl_mt.x \ test_dtrmm_armpl_mt.x \ test_ctrmm_armpl_mt.x \ test_ztrmm_armpl_mt.x # --Object file rules -- $(TEST_OBJ_PATH)/%.o: $(TEST_SRC_PATH)/%.c $(CC) $(CFLAGS) -c $< -o $@ # blis 3mhw test_z%_3mhw_blis_st.o: test_%.c $(CC) $(CFLAGS) $(PDEF_ST) $(DT_Z) $(BLI_DEF) $(D3MHW) $(STR_3MHW) $(STR_ST) -c $< -o $@ test_c%_3mhw_blis_st.o: test_%.c $(CC) $(CFLAGS) $(PDEF_ST) $(DT_C) $(BLI_DEF) $(D3MHW) $(STR_3MHW) $(STR_ST) -c $< -o $@ test_z%_3mhw_blis_mt.o: test_%.c $(CC) $(CFLAGS) $(PDEF_MT) $(DT_Z) $(BLI_DEF) $(D3MHW) $(STR_3MHW) $(STR_MT) -c $< -o $@ test_c%_3mhw_blis_mt.o: test_%.c $(CC) $(CFLAGS) $(PDEF_MT) $(DT_C) $(BLI_DEF) $(D3MHW) $(STR_3MHW) $(STR_MT) -c $< -o $@ # blis 3m1 test_z%_3m1_blis_st.o: test_%.c $(CC) $(CFLAGS) $(PDEF_ST) $(DT_Z) $(BLI_DEF) $(D3M1) $(STR_3M1) $(STR_ST) -c $< -o $@ test_c%_3m1_blis_st.o: test_%.c $(CC) $(CFLAGS) $(PDEF_ST) $(DT_C) $(BLI_DEF) $(D3M1) $(STR_3M1) $(STR_ST) -c $< -o $@ test_z%_3m1_blis_mt.o: test_%.c $(CC) $(CFLAGS) $(PDEF_MT) $(DT_Z) $(BLI_DEF) $(D3M1) $(STR_3M1) $(STR_MT) -c $< -o $@ test_c%_3m1_blis_mt.o: test_%.c $(CC) $(CFLAGS) $(PDEF_MT) $(DT_C) $(BLI_DEF) $(D3M1) $(STR_3M1) $(STR_MT) -c $< -o $@ # blis 4mhw test_z%_4mhw_blis_st.o: test_%.c $(CC) $(CFLAGS) $(PDEF_ST) $(DT_Z) $(BLI_DEF) $(D4MHW) $(STR_4MHW) $(STR_ST) -c $< -o $@ test_c%_4mhw_blis_st.o: test_%.c $(CC) $(CFLAGS) $(PDEF_ST) $(DT_C) $(BLI_DEF) $(D4MHW) $(STR_4MHW) $(STR_ST) -c $< -o $@ test_z%_4mhw_blis_mt.o: test_%.c $(CC) $(CFLAGS) $(PDEF_MT) $(DT_Z) $(BLI_DEF) $(D4MHW) $(STR_4MHW) $(STR_MT) -c $< -o $@ test_c%_4mhw_blis_mt.o: test_%.c $(CC) $(CFLAGS) $(PDEF_MT) $(DT_C) $(BLI_DEF) $(D4MHW) $(STR_4MHW) $(STR_MT) -c $< -o $@ # blis 4m1b test_z%_4m1b_blis_st.o: test_%.c $(CC) $(CFLAGS) $(PDEF_ST) $(DT_Z) $(BLI_DEF) $(D4M1B) $(STR_4M1B) $(STR_ST) -c $< -o $@ test_c%_4m1b_blis_st.o: test_%.c $(CC) $(CFLAGS) $(PDEF_ST) $(DT_C) $(BLI_DEF) $(D4M1B) $(STR_4M1B) $(STR_ST) -c $< -o $@ test_z%_4m1b_blis_mt.o: test_%.c $(CC) $(CFLAGS) $(PDEF_MT) $(DT_Z) $(BLI_DEF) $(D4M1B) $(STR_4M1B) $(STR_MT) -c $< -o $@ test_c%_4m1b_blis_mt.o: test_%.c $(CC) $(CFLAGS) $(PDEF_MT) $(DT_C) $(BLI_DEF) $(D4M1B) $(STR_4M1B) $(STR_MT) -c $< -o $@ # blis 4m1a test_z%_4m1a_blis_st.o: test_%.c $(CC) $(CFLAGS) $(PDEF_ST) $(DT_Z) $(BLI_DEF) $(D4M1A) $(STR_4M1A) $(STR_ST) -c $< -o $@ test_c%_4m1a_blis_st.o: test_%.c $(CC) $(CFLAGS) $(PDEF_ST) $(DT_C) $(BLI_DEF) $(D4M1A) $(STR_4M1A) $(STR_ST) -c $< -o $@ test_z%_4m1a_blis_mt.o: test_%.c $(CC) $(CFLAGS) $(PDEF_MT) $(DT_Z) $(BLI_DEF) $(D4M1A) $(STR_4M1A) $(STR_MT) -c $< -o $@ test_c%_4m1a_blis_mt.o: test_%.c $(CC) $(CFLAGS) $(PDEF_MT) $(DT_C) $(BLI_DEF) $(D4M1A) $(STR_4M1A) $(STR_MT) -c $< -o $@ # blis 1m test_z%_1m_blis_st.o: test_%.c $(CC) $(CFLAGS) $(PDEF_ST) $(DT_Z) $(BLI_DEF) $(D1M) $(STR_1M) $(STR_ST) -c $< -o $@ test_c%_1m_blis_st.o: test_%.c $(CC) $(CFLAGS) $(PDEF_ST) $(DT_C) $(BLI_DEF) $(D1M) $(STR_1M) $(STR_ST) -c $< -o $@ test_z%_1m_blis_mt.o: test_%.c $(CC) $(CFLAGS) $(PDEF_MT) $(DT_Z) $(BLI_DEF) $(D1M) $(STR_1M) $(STR_MT) -c $< -o $@ test_c%_1m_blis_mt.o: test_%.c $(CC) $(CFLAGS) $(PDEF_MT) $(DT_C) $(BLI_DEF) $(D1M) $(STR_1M) $(STR_MT) -c $< -o $@ # blis asm test_d%_asm_blis_st.o: test_%.c $(CC) $(CFLAGS) $(PDEF_ST) $(DT_D) $(BLI_DEF) $(DNAT) $(STR_NAT) $(STR_ST) -c $< -o $@ test_s%_asm_blis_st.o: test_%.c $(CC) $(CFLAGS) $(PDEF_ST) $(DT_S) $(BLI_DEF) $(DNAT) $(STR_NAT) $(STR_ST) -c $< -o $@ test_z%_asm_blis_st.o: test_%.c $(CC) $(CFLAGS) $(PDEF_ST) $(DT_Z) $(BLI_DEF) $(DNAT) $(STR_NAT) $(STR_ST) -c $< -o $@ test_c%_asm_blis_st.o: test_%.c $(CC) $(CFLAGS) $(PDEF_ST) $(DT_C) $(BLI_DEF) $(DNAT) $(STR_NAT) $(STR_ST) -c $< -o $@ test_d%_asm_blis_mt.o: test_%.c $(CC) $(CFLAGS) $(PDEF_MT) $(DT_D) $(BLI_DEF) $(DNAT) $(STR_NAT) $(STR_MT) -c $< -o $@ test_s%_asm_blis_mt.o: test_%.c $(CC) $(CFLAGS) $(PDEF_MT) $(DT_S) $(BLI_DEF) $(DNAT) $(STR_NAT) $(STR_MT) -c $< -o $@ test_z%_asm_blis_mt.o: test_%.c $(CC) $(CFLAGS) $(PDEF_MT) $(DT_Z) $(BLI_DEF) $(DNAT) $(STR_NAT) $(STR_MT) -c $< -o $@ test_c%_asm_blis_mt.o: test_%.c $(CC) $(CFLAGS) $(PDEF_MT) $(DT_C) $(BLI_DEF) $(DNAT) $(STR_NAT) $(STR_MT) -c $< -o $@ # openblas test_d%_openblas_st.o: test_%.c $(CC) $(CFLAGS) $(PDEF_ST) $(DT_D) $(BLA_DEF) $(DNAT) $(STR_OBL) $(STR_ST) -c $< -o $@ test_s%_openblas_st.o: test_%.c $(CC) $(CFLAGS) $(PDEF_ST) $(DT_S) $(BLA_DEF) $(DNAT) $(STR_OBL) $(STR_ST) -c $< -o $@ test_z%_openblas_st.o: test_%.c $(CC) $(CFLAGS) $(PDEF_ST) $(DT_Z) $(BLA_DEF) $(DNAT) $(STR_OBL) $(STR_ST) -c $< -o $@ test_c%_openblas_st.o: test_%.c $(CC) $(CFLAGS) $(PDEF_ST) $(DT_C) $(BLA_DEF) $(DNAT) $(STR_OBL) $(STR_ST) -c $< -o $@ test_d%_openblas_mt.o: test_%.c $(CC) $(CFLAGS) $(PDEF_MT) $(DT_D) $(BLA_DEF) $(DNAT) $(STR_OBL) $(STR_MT) -c $< -o $@ test_s%_openblas_mt.o: test_%.c $(CC) $(CFLAGS) $(PDEF_MT) $(DT_S) $(BLA_DEF) $(DNAT) $(STR_OBL) $(STR_MT) -c $< -o $@ test_z%_openblas_mt.o: test_%.c $(CC) $(CFLAGS) $(PDEF_MT) $(DT_Z) $(BLA_DEF) $(DNAT) $(STR_OBL) $(STR_MT) -c $< -o $@ test_c%_openblas_mt.o: test_%.c $(CC) $(CFLAGS) $(PDEF_MT) $(DT_C) $(BLA_DEF) $(DNAT) $(STR_OBL) $(STR_MT) -c $< -o $@ # mkl test_d%_mkl_st.o: test_%.c $(CC) $(CFLAGS) $(PDEF_ST) $(DT_D) $(BLA_DEF) $(DNAT) $(STR_MKL) $(STR_ST) -c $< -o $@ test_s%_mkl_st.o: test_%.c $(CC) $(CFLAGS) $(PDEF_ST) $(DT_S) $(BLA_DEF) $(DNAT) $(STR_MKL) $(STR_ST) -c $< -o $@ test_z%_mkl_st.o: test_%.c $(CC) $(CFLAGS) $(PDEF_ST) $(DT_Z) $(BLA_DEF) $(DNAT) $(STR_MKL) $(STR_ST) -c $< -o $@ test_c%_mkl_st.o: test_%.c $(CC) $(CFLAGS) $(PDEF_ST) $(DT_C) $(BLA_DEF) $(DNAT) $(STR_MKL) $(STR_ST) -c $< -o $@ test_d%_mkl_mt.o: test_%.c $(CC) $(CFLAGS) $(PDEF_MT) $(DT_D) $(BLA_DEF) $(DNAT) $(STR_MKL) $(STR_MT) -c $< -o $@ test_s%_mkl_mt.o: test_%.c $(CC) $(CFLAGS) $(PDEF_MT) $(DT_S) $(BLA_DEF) $(DNAT) $(STR_MKL) $(STR_MT) -c $< -o $@ test_z%_mkl_mt.o: test_%.c $(CC) $(CFLAGS) $(PDEF_MT) $(DT_Z) $(BLA_DEF) $(DNAT) $(STR_MKL) $(STR_MT) -c $< -o $@ test_c%_mkl_mt.o: test_%.c $(CC) $(CFLAGS) $(PDEF_MT) $(DT_C) $(BLA_DEF) $(DNAT) $(STR_MKL) $(STR_MT) -c $< -o $@ # armpl test_d%_armpl_st.o: test_%.c $(CC) $(CFLAGS) $(PDEF_ST) $(DT_D) $(BLA_DEF) $(DNAT) $(STR_ARMPL) $(STR_ST) -c $< -o $@ test_s%_armpl_st.o: test_%.c $(CC) $(CFLAGS) $(PDEF_ST) $(DT_S) $(BLA_DEF) $(DNAT) $(STR_ARMPL) $(STR_ST) -c $< -o $@ test_z%_armpl_st.o: test_%.c $(CC) $(CFLAGS) $(PDEF_ST) $(DT_Z) $(BLA_DEF) $(DNAT) $(STR_ARMPL) $(STR_ST) -c $< -o $@ test_c%_armpl_st.o: test_%.c $(CC) $(CFLAGS) $(PDEF_ST) $(DT_C) $(BLA_DEF) $(DNAT) $(STR_ARMPL) $(STR_ST) -c $< -o $@ test_d%_armpl_mt.o: test_%.c $(CC) $(CFLAGS) $(PDEF_MT) $(DT_D) $(BLA_DEF) $(DNAT) $(STR_ARMPL) $(STR_MT) -c $< -o $@ test_s%_armpl_mt.o: test_%.c $(CC) $(CFLAGS) $(PDEF_MT) $(DT_S) $(BLA_DEF) $(DNAT) $(STR_ARMPL) $(STR_MT) -c $< -o $@ test_z%_armpl_mt.o: test_%.c $(CC) $(CFLAGS) $(PDEF_MT) $(DT_Z) $(BLA_DEF) $(DNAT) $(STR_ARMPL) $(STR_MT) -c $< -o $@ test_c%_armpl_mt.o: test_%.c $(CC) $(CFLAGS) $(PDEF_MT) $(DT_C) $(BLA_DEF) $(DNAT) $(STR_ARMPL) $(STR_MT) -c $< -o $@ # mkl # -- Executable file rules -- # NOTE: For the BLAS test drivers, we place the BLAS libraries before BLIS # on the link command line in case BLIS was configured with the BLAS # compatibility layer. This prevents BLIS from inadvertently getting called # for the BLAS routines we are trying to test with. test_%_openblas_st.x: test_%_openblas_st.o $(LIBBLIS_LINK) $(LINKER) $< $(OPENBLAS_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $@ test_%_openblas_mt.x: test_%_openblas_mt.o $(LIBBLIS_LINK) $(LINKER) $< $(OPENBLASP_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $@ test_%_mkl_st.x: test_%_mkl_st.o $(LIBBLIS_LINK) $(LINKER) $< $(MKL_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $@ test_%_mkl_mt.x: test_%_mkl_mt.o $(LIBBLIS_LINK) $(LINKER) $< $(MKLP_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $@ test_%_armpl_st.x: test_%_armpl_st.o $(LIBBLIS_LINK) $(LINKER) $< $(ARMPL_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $@ test_%_armpl_mt.x: test_%_armpl_mt.o $(LIBBLIS_LINK) $(LINKER) $< $(ARMPLP_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $@ test_%_blis_st.x: test_%_blis_st.o $(LIBBLIS_LINK) $(LINKER) $< $(LIBBLIS_LINK) $(LDFLAGS) -o $@ test_%_blis_mt.x: test_%_blis_mt.o $(LIBBLIS_LINK) $(LINKER) $< $(LIBBLIS_LINK) $(LDFLAGS) -o $@ # -- Clean rules -- clean: cleanx cleanx: - $(RM_F) *.o *.x blis-0.9.0/test/studies/thunderx2/plot_gemm_mt_perf.m000066400000000000000000000112421422157504600227160ustar00rootroot00000000000000axes1 = subplot(4, 4, 1); hold(axes1,'on'); axes2 = subplot(4, 4, 5); hold(axes2,'on'); axes3 = subplot(4, 4, 9); hold(axes3,'on'); axes4 = subplot(4, 4, 13); hold(axes4,'on'); addpath(pathname_blis) if(plot_s) % SGEMM multi threaded axes(axes1); output_mt_sgemm_asm_blis plot(data_mt_sgemm_asm_blis(:,1), data_mt_sgemm_asm_blis(:,4), 'LineWidth', 1.25,'Color', [0 0 1]); end % DGEMM multi threaded if(plot_d) axes(axes2); output_mt_dgemm_asm_blis plot(data_mt_dgemm_asm_blis(:,1), data_mt_dgemm_asm_blis(:,4), 'LineWidth', 1.25,'Color', [0 0 1]); end % CGEMM multi threaded if(plot_c) axes(axes3); output_mt_cgemm_1m_blis plot(data_mt_cgemm_1m_blis(:,1), data_mt_cgemm_1m_blis(:,4), 'LineWidth', 1.25,'Color', [0 0 1]); end % ZGEMM multi threaded if(plot_z) axes(axes4); output_mt_zgemm_1m_blis plot(data_mt_zgemm_1m_blis(:,1), data_mt_zgemm_1m_blis(:,4), 'LineWidth', 1.25,'Color', [0 0 1]); end clear *gemm* rmpath(pathname_blis) % OpenBLAS addpath(pathname_openblas) if(plot_s) axes(axes1); output_mt_sgemm_openblas plot(data_mt_sgemm_openblas(:,1), data_mt_sgemm_openblas(:,4), 'LineWidth', 1.25,'Color', [0 1 0]); end if(plot_d) axes(axes2); output_mt_dgemm_openblas plot(data_mt_dgemm_openblas(:,1), data_mt_dgemm_openblas(:,4), 'LineWidth', 1.25,'Color', [0 1 0]); end if(plot_c) axes(axes3); output_mt_cgemm_openblas plot(data_mt_cgemm_openblas(:,1), data_mt_cgemm_openblas(:,4), 'LineWidth', 1.25,'Color', [0 1 0]); end if(plot_z) axes(axes4); output_mt_zgemm_openblas plot(data_mt_zgemm_openblas(:,1), data_mt_zgemm_openblas(:,4), 'LineWidth', 1.25,'Color', [0 1 0]); end clear *gemm* rmpath(pathname_openblas) % ARMPL addpath(pathname_armpl) if(plot_s) axes(axes1); output_mt_sgemm_armpl plot(data_mt_sgemm_armpl(:,1), data_mt_sgemm_armpl(:,4), '--', 'LineWidth', 1.25,'Color', [1 0 1]); end if(plot_d) axes(axes2); output_mt_dgemm_armpl plot(data_mt_dgemm_armpl(:,1), data_mt_dgemm_armpl(:,4), '--', 'LineWidth', 1.25,'Color', [1 0 1]); end if(plot_c) axes(axes3); output_mt_cgemm_armpl plot(data_mt_cgemm_armpl(:,1), data_mt_cgemm_armpl(:,4), '--', 'LineWidth', 1.25,'Color', [1 0 1]); end if(plot_z) axes(axes4); output_mt_zgemm_armpl plot(data_mt_zgemm_armpl(:,1), data_mt_zgemm_armpl(:,4), '--', 'LineWidth', 1.25,'Color', [1 0 1]); end clear *gemm* rmpath(pathname_armpl) axes(axes1); ylabel( 'GFLOPS', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); %xlabel( 'matrix dimension m=n=k', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue' ); title('SGEMM (multi-threaded)','FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); box(axes1,'on'); set(axes1,'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); v = axis; % extract the current ranges axis( [ 0 xmax_mt 0 speak*numcores] ) axes(axes2); ylabel( 'GFLOPS', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); %xlabel( 'matrix dimension m=n=k', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue' ); title('DGEMM (multi-threaded)','FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); box(axes2,'on'); set(axes2,'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); %legend({'BLIS', 'OpenBLAS', 'ARMPL'},'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue', 'Location', 'best'); v = axis; % extract the current ranges axis( [ 0 xmax_mt 0 dpeak*numcores ] ) axes(axes3); ylabel( 'GFLOPS', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); %xlabel( 'matrix dimension m=n=k', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue' ); title('CGEMM (multi-threaded)','FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); box(axes3,'on'); set(axes3,'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); v = axis; % extract the current ranges axis( [ 0 xmax_mt 0 speak*numcores ] ) axes(axes4); ylabel( 'GFLOPS', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); xlabel( 'matrix dimension m=n=k', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue' ); title('ZGEMM (multi-threaded)','FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); box(axes4,'on'); set(axes4,'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); %legend({'BLIS', 'OpenBLAS', 'MKL'},'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue', 'Location', 'South'); v = axis; % extract the current ranges axis( [ 0 xmax_mt 0 dpeak*numcores ] ) blis-0.9.0/test/studies/thunderx2/plot_gemm_st_perf.m000066400000000000000000000101251422157504600227230ustar00rootroot00000000000000addpath(pathname) output_st_sgemm_asm_blis output_st_dgemm_asm_blis output_st_cgemm_1m_blis output_st_zgemm_1m_blis output_st_sgemm_openblas output_st_dgemm_openblas output_st_cgemm_openblas output_st_zgemm_openblas % SGEMM Single threaded axes1 = subplot(4, 4, 1); hold(axes1,'on'); plot(data_st_sgemm_asm_blis(:,1), data_st_sgemm_asm_blis(:,4), 'LineWidth', 1.25,'Color', [0 0 1]); plot(data_st_sgemm_openblas(:,1), data_st_sgemm_openblas(:,4), 'LineWidth', 1.25,'Color', [0 1 0]); ylabel( 'GFLOPS', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); %xlabel( 'matrix dimension m=n=k', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue' ); title('SGEMM (single-threaded)','FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); box(axes1,'on'); set(axes1,'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); v = axis; % extract the current ranges axis( [ 0 v(2) 0 speak ] ) % DGEMM Single threaded axes1 = subplot(4, 4, 5); hold(axes1,'on'); plot(data_st_dgemm_asm_blis(:,1), data_st_dgemm_asm_blis(:,4), 'LineWidth', 1.25,'Color', [0 0 1]); plot(data_st_dgemm_openblas(:,1), data_st_dgemm_openblas(:,4), 'LineWidth', 1.25,'Color', [0 1 0]); ylabel( 'GFLOPS', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); %xlabel( 'matrix dimension m=n=k', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue' ); title('DGEMM (single-threaded)','FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); box(axes1,'on'); set(axes1,'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); %legend({'BLIS', 'OpenBLAS', 'ARMPL'},'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue', 'Location', 'best'); v = axis; % extract the current ranges axis( [ 0 v(2) 0 dpeak ] ) % CGEMM Single threaded axes1 = subplot(4, 4, 9); hold(axes1,'on'); plot(data_st_cgemm_1m_blis(:,1), data_st_cgemm_1m_blis(:,4), 'LineWidth', 1.25,'Color', [0 0 1]); plot(data_st_cgemm_openblas(:,1), data_st_cgemm_openblas(:,4), 'LineWidth', 1.25,'Color', [0 1 0]); ylabel( 'GFLOPS', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); %xlabel( 'matrix dimension m=n=k', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue' ); title('CGEMM (single-threaded)','FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); box(axes1,'on'); set(axes1,'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); v = axis; % extract the current ranges axis( [ 0 v(2) 0 speak ] ) % ZGEMM Single threaded axes1 = subplot(4, 4, 13); hold(axes1,'on'); plot(data_st_zgemm_1m_blis(:,1), data_st_zgemm_1m_blis(:,4), 'LineWidth', 1.25,'Color', [0 0 1]); plot(data_st_zgemm_openblas(:,1), data_st_zgemm_openblas(:,4), 'LineWidth', 1.25,'Color', [0 1 0]); ylabel( 'GFLOPS', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); xlabel( 'matrix dimension m=n=k', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue' ); title('ZGEMM (single-threaded)','FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); box(axes1,'on'); set(axes1,'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); %legend({'BLIS', 'OpenBLAS', 'MKL'},'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue', 'Location', 'South'); v = axis; % extract the current ranges axis( [ 0 v(2) 0 dpeak ] ) clear *gemm* rmpath(pathname) addpath(pathname_armpl) output_st_sgemm_armpl output_st_dgemm_armpl output_st_cgemm_armpl output_st_zgemm_armpl % SGEMM Single threaded subplot(4, 4, 1); plot(data_st_sgemm_armpl(:,1), data_st_sgemm_armpl(:,4), '--', 'LineWidth', 1.25,'Color', [1 0 1]); subplot(4, 4, 5); plot(data_st_dgemm_armpl(:,1), data_st_dgemm_armpl(:,4), '--', 'LineWidth', 1.25,'Color', [1 0 1]); subplot(4, 4, 9); plot(data_st_cgemm_armpl(:,1), data_st_cgemm_armpl(:,4), '--', 'LineWidth', 1.25,'Color', [1 0 1]); subplot(4, 4, 13); plot(data_st_zgemm_armpl(:,1), data_st_zgemm_armpl(:,4), '--', 'LineWidth', 1.25,'Color', [1 0 1]); clear *gemm* rmpath(pathname_armpl) blis-0.9.0/test/studies/thunderx2/plot_hemm_mt_perf.m000066400000000000000000000112161422157504600227200ustar00rootroot00000000000000axes3 = subplot(4, 4, 3); hold(axes3,'on'); axes7 = subplot(4, 4, 7); hold(axes7,'on'); axes11 = subplot(4, 4, 11); hold(axes11,'on'); axes15 = subplot(4, 4, 15); hold(axes15,'on'); addpath(pathname_blis) if(plot_s) axes(axes3); output_mt_shemm_asm_blis plot(data_mt_shemm_asm_blis(:,1), data_mt_shemm_asm_blis(:,3), 'LineWidth', 1.25,'Color', [0 0 1]); end if(plot_d) axes(axes7); output_mt_dhemm_asm_blis plot(data_mt_dhemm_asm_blis(:,1), data_mt_dhemm_asm_blis(:,3), 'LineWidth', 1.25,'Color', [0 0 1]); end if(plot_c) axes(axes11); output_mt_chemm_1m_blis plot(data_mt_chemm_1m_blis(:,1), data_mt_chemm_1m_blis(:,3), 'LineWidth', 1.25,'Color', [0 0 1]); end if(plot_z) axes(axes15); output_mt_zhemm_1m_blis plot(data_mt_zhemm_1m_blis(:,1), data_mt_zhemm_1m_blis(:,3), 'LineWidth', 1.25,'Color', [0 0 1]); end clear *hemm* rmpath(pathname_blis) addpath(pathname_openblas) if(plot_s) axes(axes3); output_mt_shemm_openblas plot(data_mt_shemm_openblas(:,1), data_mt_shemm_openblas(:,3), 'LineWidth', 1.25,'Color', [0 1 0]); end if(plot_d) axes(axes7); output_mt_dhemm_openblas plot(data_mt_dhemm_openblas(:,1), data_mt_dhemm_openblas(:,3), 'LineWidth', 1.25,'Color', [0 1 0]); end if(plot_c) axes(axes11); output_mt_chemm_openblas plot(data_mt_chemm_openblas(:,1), data_mt_chemm_openblas(:,3), 'LineWidth', 1.25,'Color', [0 1 0]); end if(plot_z) axes(axes15); output_mt_zhemm_openblas plot(data_mt_zhemm_openblas(:,1), data_mt_zhemm_openblas(:,3), 'LineWidth', 1.25,'Color', [0 1 0]); end clear *hemm* rmpath(pathname_openblas) addpath(pathname_armpl); if(plot_s) axes(axes3); output_mt_shemm_armpl plot(data_mt_shemm_armpl(:,1), data_mt_shemm_armpl(:,3), '--', 'LineWidth', 1.25,'Color', [1 0 1]); end if(plot_d) axes(axes7); output_mt_dhemm_armpl plot(data_mt_dhemm_armpl(:,1), data_mt_dhemm_armpl(:,3), '--', 'LineWidth', 1.25,'Color', [1 0 1]); end if(plot_c) axes(axes11); output_mt_chemm_armpl plot(data_mt_chemm_armpl(:,1), data_mt_chemm_armpl(:,3), '--', 'LineWidth', 1.25,'Color', [1 0 1]); end if(plot_z) axes(axes15); output_mt_zhemm_armpl plot(data_mt_zhemm_armpl(:,1), data_mt_zhemm_armpl(:,3), '--', 'LineWidth', 1.25,'Color', [1 0 1]); end clear *hemm* rmpath(pathname_armpl) % SSYMM multi threaded axes(axes3); ylabel( 'GFLOPS', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); %xlabel( 'matrix dimension m=n=k', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue' ); title('SSYMM (multi-threaded)','FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); box(axes3,'on'); set(axes3,'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); v = axis; % extract the current ranges axis( [ 0 xmax_mt 0 speak*numcores ] ) axes(axes7); ylabel( 'GFLOPS', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); %xlabel( 'matrix dimension m=n=k', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue' ); title('DSYMM (multi-threaded)','FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); box(axes7,'on'); set(axes7,'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); %legend({'BLIS', 'OpenBLAS', 'ARMPL'},'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue', 'Location', 'best'); v = axis; % extract the current ranges axis( [ 0 xmax_mt 0 dpeak*numcores ] ) % CHEMM multi threaded axes(axes11); ylabel( 'GFLOPS', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); %xlabel( 'matrix dimension m=n=k', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue' ); title('CHEMM (multi-threaded)','FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); box(axes11,'on'); set(axes11,'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); v = axis; % extract the current ranges axis( [ 0 xmax_mt 0 speak*numcores ] ) % ZHEMM multi threaded axes(axes15); ylabel( 'GFLOPS', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); xlabel( 'matrix dimension m=n=k', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue' ); title('ZHEMM (multi-threaded)','FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); box(axes15,'on'); set(axes15,'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); % legend({'BLIS', 'BLIS (AVX2)', 'OpenBLAS', 'MKL'},'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue', 'Location', 'South'); v = axis; % extract the current ranges axis( [ 0 xmax_mt 0 dpeak*numcores ] ) blis-0.9.0/test/studies/thunderx2/plot_hemm_st_perf.m000066400000000000000000000077201422157504600227330ustar00rootroot00000000000000addpath(pathname) output_st_shemm_asm_blis output_st_dhemm_asm_blis output_st_chemm_1m_blis output_st_zhemm_1m_blis output_st_shemm_openblas output_st_dhemm_openblas output_st_chemm_openblas output_st_zhemm_openblas % SSYMM Single threaded axes1 = subplot(4, 4, 3); hold(axes1,'on'); plot(data_st_shemm_asm_blis(:,1), data_st_shemm_asm_blis(:,3), 'LineWidth', 1.25,'Color', [0 0 1]); plot(data_st_shemm_openblas(:,1), data_st_shemm_openblas(:,3), 'LineWidth', 1.25,'Color', [0 1 0]); ylabel( 'GFLOPS', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); %xlabel( 'matrix dimension m=n=k', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue' ); title('SSYMM (single-threaded)','FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); box(axes1,'on'); set(axes1,'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); v = axis; % extract the current ranges axis( [ 0 v(2) 0 speak ] ) % DSYMM Single threaded axes1 = subplot(4, 4, 7); hold(axes1,'on'); plot(data_st_dhemm_asm_blis(:,1), data_st_dhemm_asm_blis(:,3), 'LineWidth', 1.25,'Color', [0 0 1]); plot(data_st_dhemm_openblas(:,1), data_st_dhemm_openblas(:,3), 'LineWidth', 1.25,'Color', [0 1 0]); ylabel( 'GFLOPS', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); %xlabel( 'matrix dimension m=n=k', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue' ); title('DSYMM (single-threaded)','FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); box(axes1,'on'); set(axes1,'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); %legend({'BLIS', 'OpenBLAS', 'ARMPL'},'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue', 'Location', 'best'); v = axis; % extract the current ranges axis( [ 0 v(2) 0 dpeak ] ) % CHEMM Single threaded axes1 = subplot(4, 4, 11); hold(axes1,'on'); plot(data_st_chemm_1m_blis(:,1), data_st_chemm_1m_blis(:,3), 'LineWidth', 1.25,'Color', [0 0 1]); plot(data_st_chemm_openblas(:,1), data_st_chemm_openblas(:,3), 'LineWidth', 1.25,'Color', [0 1 0]); ylabel( 'GFLOPS', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); %xlabel( 'matrix dimension m=n=k', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue' ); title('CHEMM (single-threaded)','FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); box(axes1,'on'); set(axes1,'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); v = axis; % extract the current ranges axis( [ 0 v(2) 0 speak ] ) % ZHEMM Single threaded axes1 = subplot(4, 4, 15); hold(axes1,'on'); plot(data_st_zhemm_1m_blis(:,1), data_st_zhemm_1m_blis(:,3), 'LineWidth', 1.25,'Color', [0 0 1]); plot(data_st_zhemm_openblas(:,1), data_st_zhemm_openblas(:,3), 'LineWidth', 1.25,'Color', [0 1 0]); ylabel( 'GFLOPS', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); xlabel( 'matrix dimension m=n=k', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue' ); title('ZHEMM (single-threaded)','FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); box(axes1,'on'); set(axes1,'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); v = axis; % extract the current ranges axis( [ 0 v(2) 0 dpeak ] ) clear *hemm* rmpath(pathname) addpath(pathname_armpl) output_st_shemm_armpl output_st_dhemm_armpl output_st_chemm_armpl output_st_zhemm_armpl % Shemm Single threaded subplot(4, 4, 3); plot(data_st_shemm_armpl(:,1), data_st_shemm_armpl(:,3), '--', 'LineWidth', 1.25,'Color', [1 0 1]); subplot(4, 4, 7); plot(data_st_dhemm_armpl(:,1), data_st_dhemm_armpl(:,3), '--', 'LineWidth', 1.25,'Color', [1 0 1]); subplot(4, 4, 11); plot(data_st_chemm_armpl(:,1), data_st_chemm_armpl(:,3), '--', 'LineWidth', 1.25,'Color', [1 0 1]); subplot(4, 4, 15); plot(data_st_zhemm_armpl(:,1), data_st_zhemm_armpl(:,3), '--', 'LineWidth', 1.25,'Color', [1 0 1]); clear *hemm* rmpath(pathname_armpl) blis-0.9.0/test/studies/thunderx2/plot_syrk_mt_perf.m000066400000000000000000000106101422157504600227570ustar00rootroot00000000000000 axes2 = subplot(4, 4, 2); hold(axes2,'on'); axes6 = subplot(4, 4, 6); hold(axes6,'on'); axes10 = subplot(4, 4, 10); hold(axes10,'on'); axes14 = subplot(4, 4, 14); hold(axes14,'on'); addpath(pathname_blis) if(plot_s) axes(axes2); output_mt_ssyrk_asm_blis plot(data_mt_ssyrk_asm_blis(:,1), data_mt_ssyrk_asm_blis(:,3), 'LineWidth', 1.25,'Color', [0 0 1]); end if(plot_d) axes(axes6); output_mt_dsyrk_asm_blis plot(data_mt_dsyrk_asm_blis(:,1), data_mt_dsyrk_asm_blis(:,3), 'LineWidth', 1.25,'Color', [0 0 1]); end if(plot_c) axes(axes10); output_mt_csyrk_1m_blis plot(data_mt_csyrk_1m_blis(:,1), data_mt_csyrk_1m_blis(:,3), 'LineWidth', 1.25,'Color', [0 0 1]); end if(plot_z) axes(axes14); output_mt_zsyrk_1m_blis plot(data_mt_zsyrk_1m_blis(:,1), data_mt_zsyrk_1m_blis(:,3), 'LineWidth', 1.25,'Color', [0 0 1]); end clear *syrk* rmpath(pathname_blis) % OpenBLAS addpath(pathname_openblas) if(plot_s) axes(axes2); output_mt_ssyrk_openblas plot(data_mt_ssyrk_openblas(:,1), data_mt_ssyrk_openblas(:,3), 'LineWidth', 1.25,'Color', [0 1 0]); end if(plot_d) axes(axes6); output_mt_dsyrk_openblas plot(data_mt_dsyrk_openblas(:,1), data_mt_dsyrk_openblas(:,3), 'LineWidth', 1.25,'Color', [0 1 0]); end if(plot_c) axes(axes10); output_mt_csyrk_openblas plot(data_mt_csyrk_openblas(:,1), data_mt_csyrk_openblas(:,3), 'LineWidth', 1.25,'Color', [0 1 0]); end if(plot_z) axes(axes14); output_mt_zsyrk_openblas plot(data_mt_zsyrk_openblas(:,1), data_mt_zsyrk_openblas(:,3), 'LineWidth', 1.25,'Color', [0 1 0]); end clear *syrk* rmpath(pathname_openblas) % ARMPL addpath(pathname_armpl) if(plot_s) axes(axes2); output_mt_ssyrk_armpl plot(data_mt_ssyrk_armpl(:,1), data_mt_ssyrk_armpl(:,3), '--', 'LineWidth', 1.25,'Color', [1 0 1]); end if(plot_d) axes(axes6); output_mt_dsyrk_armpl plot(data_mt_dsyrk_armpl(:,1), data_mt_dsyrk_armpl(:,3), '--', 'LineWidth', 1.25,'Color', [1 0 1]); end if(plot_c) axes(axes10); output_mt_csyrk_armpl plot(data_mt_csyrk_armpl(:,1), data_mt_csyrk_armpl(:,3), '--', 'LineWidth', 1.25,'Color', [1 0 1]); end if(plot_z) axes(axes14); output_mt_zsyrk_armpl plot(data_mt_zsyrk_armpl(:,1), data_mt_zsyrk_armpl(:,3), '--', 'LineWidth', 1.25,'Color', [1 0 1]); end clear *syrk* rmpath(pathname_armpl) axes(axes2); ylabel( 'GFLOPS', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); %xlabel( 'matrix dimension m=n=k', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue' ); title('SSYRK (multi-threaded)','FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); box(axes2,'on'); set(axes2,'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); v = axis; % extract the current ranges axis( [ 0 xmax_mt 0 speak*numcores ] ) % DSYRK multi threaded axes(axes6); ylabel( 'GFLOPS', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); %xlabel( 'matrix dimension m=n=k', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue' ); title('DSYRK (multi-threaded)','FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); box(axes6,'on'); set(axes6,'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); v = axis; % extract the current ranges axis( [ 0 xmax_mt 0 dpeak*numcores ] ) % CSYRK multi threaded axes(axes10); ylabel( 'GFLOPS', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); %xlabel( 'matrix dimension m=n=k', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue' ); title('CSYRK (multi-threaded)','FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); box(axes10,'on'); set(axes10,'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); v = axis; % extract the current ranges axis( [ 0 xmax_mt 0 speak*numcores ] ) % ZSYRK multi threaded axes(axes14); ylabel( 'GFLOPS', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); xlabel( 'matrix dimension m=n=k', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue' ); title('ZSYRK (multi-threaded)','FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); box(axes14,'on'); set(axes14,'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); % legend({'BLIS', 'BLIS (AVX2)','OpenBLAS', 'MKL'},'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue', 'Location', 'South'); v = axis; % extract the current ranges axis( [ 0 xmax_mt 0 dpeak*numcores ] ) blis-0.9.0/test/studies/thunderx2/plot_syrk_st_perf.m000066400000000000000000000101661422157504600227730ustar00rootroot00000000000000addpath(pathname) output_st_ssyrk_asm_blis output_st_dsyrk_asm_blis output_st_csyrk_1m_blis output_st_zsyrk_1m_blis output_st_ssyrk_openblas output_st_dsyrk_openblas output_st_csyrk_openblas output_st_zsyrk_openblas plot_lower = 0; % SSYRK Single threaded axes1 = subplot(4, 4, 2); hold(axes1,'on'); plot(data_st_ssyrk_asm_blis(:,1), data_st_ssyrk_asm_blis(:,3), 'LineWidth', 1.25,'Color', [0 0 1]); plot(data_st_ssyrk_openblas(:,1), data_st_ssyrk_openblas(:,3), 'LineWidth', 1.25,'Color', [0 1 0]); ylabel( 'GFLOPS', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); %xlabel( 'matrix dimension m=n=k', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue' ); title('SSYRK (single-threaded)','FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); box(axes1,'on'); set(axes1,'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); v = axis; % extract the current ranges axis( [ 0 v(2) 0 speak ] ) % DSYRK single threaded axes1 = subplot(4, 4, 6); hold(axes1,'on'); plot(data_st_dsyrk_asm_blis(:,1), data_st_dsyrk_asm_blis(:,3), 'LineWidth', 1.25,'Color', [0 0 1]); plot(data_st_dsyrk_openblas(:,1), data_st_dsyrk_openblas(:,3), 'LineWidth', 1.25,'Color', [0 1 0]); ylabel( 'GFLOPS', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); %xlabel( 'matrix dimension m=n=k', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue' ); title('DSYRK (single-threaded)','FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); box(axes1,'on'); set(axes1,'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); %legend({'BLIS', 'OpenBLAS', 'ARMPL'},'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue', 'Location', 'best'); v = axis; % extract the current ranges axis( [ 0 v(2) 0 dpeak ] ) % CSYRK single threaded axes1 = subplot(4, 4, 10); hold(axes1,'on'); plot(data_st_csyrk_1m_blis(:,1), data_st_csyrk_1m_blis(:,3), 'LineWidth', 1.25,'Color', [0 0 1]); plot(data_st_csyrk_openblas(:,1), data_st_csyrk_openblas(:,3), 'LineWidth', 1.25,'Color', [0 1 0]); ylabel( 'GFLOPS', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); %xlabel( 'matrix dimension m=n=k', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue' ); title('CSYRK (single-threaded)','FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); box(axes1,'on'); set(axes1,'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); v = axis; % extract the current ranges axis( [ 0 v(2) 0 speak ] ) % ZSYRK single threaded axes1 = subplot(4, 4, 14); hold(axes1,'on'); plot(data_st_zsyrk_1m_blis(:,1), data_st_zsyrk_1m_blis(:,3), 'LineWidth', 1.25,'Color', [0 0 1]); plot(data_st_zsyrk_openblas(:,1), data_st_zsyrk_openblas(:,3), 'LineWidth', 1.25,'Color', [0 1 0]); ylabel( 'GFLOPS', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); xlabel( 'matrix dimension m=n=k', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue' ); title('ZSYRK (single-threaded)','FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); box(axes1,'on'); set(axes1,'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); % legend({'BLIS', 'BLIS (AVX2)','OpenBLAS', 'MKL'},'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue', 'Location', 'South'); v = axis; % extract the current ranges axis( [ 0 v(2) 0 dpeak ] ) clear *syrk* rmpath(pathname) addpath(pathname_armpl) output_st_ssyrk_armpl output_st_dsyrk_armpl output_st_csyrk_armpl output_st_zsyrk_armpl % Ssyrk Single threaded subplot(4, 4, 2); plot(data_st_ssyrk_armpl(:,1), data_st_ssyrk_armpl(:,3), '--', 'LineWidth', 1.25,'Color', [1 0 1]); subplot(4, 4, 6); plot(data_st_dsyrk_armpl(:,1), data_st_dsyrk_armpl(:,3), '--', 'LineWidth', 1.25,'Color', [1 0 1]); subplot(4, 4, 10); plot(data_st_csyrk_armpl(:,1), data_st_csyrk_armpl(:,3), '--', 'LineWidth', 1.25,'Color', [1 0 1]); subplot(4, 4, 14); plot(data_st_zsyrk_armpl(:,1), data_st_zsyrk_armpl(:,3), '--', 'LineWidth', 1.25,'Color', [1 0 1]); clear *syrk* rmpath(pathname_armpl) blis-0.9.0/test/studies/thunderx2/plot_thunderx2_perf.m000066400000000000000000000040611422157504600232150ustar00rootroot00000000000000plot_st = 1; plot_1s = 1; plot_2s = 1; plot_s = 1; plot_d = 1; plot_c = 1; plot_z = 1; plot_armpl = 1; fontsize = 6; freq = 2; sflopspercycle = 16; dflopspercycle = 8; speak = sflopspercycle*freq; dpeak = dflopspercycle*freq; xmax_mt = 5000; if(plot_st) numcores = 1; fig1 = figure(1); clf(fig1) % pathname = './20180824/'; pathname_armpl = './20180829/'; plot_gemm_st_perf plot_syrk_st_perf plot_hemm_st_perf plot_trmm_st_perf %fig1.PaperPositionMode = 'auto'; orient(fig1,'landscape') set(fig1,'PaperUnits','normalized'); set(fig1,'PaperPosition', [0 0 1 1]); print(fig1, 'thunderx2-st-20180829', '-dpdf') clear pathname pathname_armpl end if (plot_1s) fig1 = figure(2); clf; numcores = 28; pathname_blis = './20180830/1socket'; pathname_armpl = './20180830/1socket'; pathname_openblas = './20180830/1socket'; %JC = 2, IC = 14 plot_gemm_mt_perf plot_syrk_mt_perf plot_hemm_mt_perf plot_trmm_mt_perf %fig1.PaperPositionMode = 'auto'; orient(fig1,'landscape') set(fig1,'PaperUnits','normalized'); set(fig1,'PaperPosition', [0 0 1 1]); print(fig1, 'thunderx2-mt-28cores-20180830', '-dpdf') end if(plot_2s) numcores = 56; %JC = 4, IC = 14 fig1 = figure(3); clf; plot_gemm = 1; plot_syrk = 1; plot_hemm = 1; plot_trmm = 1; plot_s = 1; plot_d = 1; plot_c = 1; plot_z = 1; pathname_blis = './20180830/2sockets'; pathname_openblas = './20180830/2sockets'; pathname_armpl = './20180830/2sockets'; if(plot_gemm) plot_gemm_mt_perf end if(plot_syrk) plot_syrk_mt_perf end if(plot_hemm) plot_hemm_mt_perf end if(plot_trmm) plot_trmm_mt_perf end %fig1.PaperPositionMode = 'auto'; orient(fig1,'landscape') set(fig1,'PaperUnits','normalized'); set(fig1,'PaperPosition', [0 0 1 1]); print(fig1, 'thunderx2-mt-56cores-20180830', '-dpdf') endblis-0.9.0/test/studies/thunderx2/plot_trmm_mt_perf.m000066400000000000000000000114711422157504600227540ustar00rootroot00000000000000axes4 = subplot(4, 4, 4); hold(axes4,'on'); axes8 = subplot(4, 4, 8); hold(axes8,'on'); axes12 = subplot(4, 4, 12); hold(axes12,'on'); axes16 = subplot(4, 4, 16); hold(axes16,'on'); addpath(pathname_blis) if(plot_s) axes(axes4); output_mt_strmm_asm_blis plot(data_mt_strmm_asm_blis(:,1), data_mt_strmm_asm_blis(:,3), 'LineWidth', 1.25,'Color', [0 0 1]); end if(plot_d) axes(axes8); output_mt_dtrmm_asm_blis plot(data_mt_dtrmm_asm_blis(:,1), data_mt_dtrmm_asm_blis(:,3), 'LineWidth', 1.25,'Color', [0 0 1]); end if(plot_c) axes(axes12); output_mt_ctrmm_1m_blis plot(data_mt_ctrmm_1m_blis(:,1), data_mt_ctrmm_1m_blis(:,3), 'LineWidth', 1.25,'Color', [0 0 1]); end if(plot_z) axes(axes16); output_mt_ztrmm_1m_blis plot(data_mt_ztrmm_1m_blis(:,1), data_mt_ztrmm_1m_blis(:,3), 'LineWidth', 1.25,'Color', [0 0 1]); end clear *trmm* rmpath(pathname_blis) addpath(pathname_openblas) if(plot_s) axes(axes4); output_mt_strmm_openblas plot(data_mt_strmm_openblas(:,1), data_mt_strmm_openblas(:,3), 'LineWidth', 1.25,'Color', [0 1 0]); end if(plot_d) axes(axes8); output_mt_dtrmm_openblas plot(data_mt_dtrmm_openblas(:,1), data_mt_dtrmm_openblas(:,3), 'LineWidth', 1.25,'Color', [0 1 0]); end if(plot_c) axes(axes12); output_mt_ctrmm_openblas plot(data_mt_ctrmm_openblas(:,1), data_mt_ctrmm_openblas(:,3), 'LineWidth', 1.25,'Color', [0 1 0]); end if(plot_z) axes(axes16); output_mt_ztrmm_openblas plot(data_mt_ztrmm_openblas(:,1), data_mt_ztrmm_openblas(:,3), 'LineWidth', 1.25,'Color', [0 1 0]); end clear *trmm* rmpath(pathname_openblas) if(plot_armpl) addpath(pathname_armpl) if(plot_s) axes(axes4); output_mt_strmm_armpl plot(data_mt_strmm_armpl(:,1), data_mt_strmm_armpl(:,3), '--', 'LineWidth', 1.25,'Color', [1 0 1]); end if(plot_d) axes(axes8); output_mt_dtrmm_armpl plot(data_mt_dtrmm_armpl(:,1), data_mt_dtrmm_armpl(:,3), '--', 'LineWidth', 1.25,'Color', [1 0 1]); end if(plot_c) axes(axes12); output_mt_ctrmm_armpl plot(data_mt_ctrmm_armpl(:,1), data_mt_ctrmm_armpl(:,3), '--', 'LineWidth', 1.25,'Color', [1 0 1]); end if(plot_z) axes(axes16); output_mt_ztrmm_armpl plot(data_mt_ztrmm_armpl(:,1), data_mt_ztrmm_armpl(:,3), '--', 'LineWidth', 1.25,'Color', [1 0 1]); end clear *trmm* rmpath(pathname_armpl) end axes(axes4); ylabel( 'GFLOPS', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); %xlabel( 'matrix dimension m=n=k', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue' ); title('STRMM (multi-threaded)','FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); box(axes4,'on'); set(axes4,'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); v = axis; % extract the current ranges axis( [ 0 xmax_mt 0 speak*numcores ] ) axes(axes8); ylabel( 'GFLOPS', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); %xlabel( 'matrix dimension m=n=k', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue' ); title('DTRMM (multi-threaded)','FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); box(axes8,'on'); set(axes8,'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); %legend({'BLIS', 'OpenBLAS', 'ARMPL'},'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue', 'Location', 'best'); v = axis; % extract the current ranges axis( [ 0 xmax_mt 0 dpeak*numcores ] ) axes(axes12); ylabel( 'GFLOPS', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); %xlabel( 'matrix dimension m=n=k', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue' ); title('CTRMM (multi-threaded)','FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); box(axes12,'on'); set(axes12,'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); v = axis; % extract the current ranges axis( [ 0 xmax_mt 0 speak*numcores ] ) axes(axes16); ylabel( 'GFLOPS', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); xlabel( 'matrix dimension m=n=k', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue' ); title('ZTRMM (multi-threaded)','FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); box(axes16,'on'); set(axes16,'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); legend({'BLIS','OpenBLAS'},'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue', 'Location', 'South'); v = axis; % extract the current ranges axis( [ 0 xmax_mt 0 dpeak*numcores ] ) legend({'BLIS','OpenBLAS', 'ARMPL'},'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue', 'Location', 'South'); blis-0.9.0/test/studies/thunderx2/plot_trmm_st_perf.m000066400000000000000000000101261422157504600227560ustar00rootroot00000000000000addpath(pathname) output_st_strmm_asm_blis output_st_dtrmm_asm_blis output_st_ctrmm_1m_blis output_st_ztrmm_1m_blis output_st_strmm_openblas output_st_dtrmm_openblas output_st_ctrmm_openblas output_st_ztrmm_openblas % STRMM Single threaded axes1 = subplot(4, 4, 4); hold(axes1,'on'); plot(data_st_strmm_asm_blis(:,1), data_st_strmm_asm_blis(:,3), 'LineWidth', 1.25,'Color', [0 0 1]); plot(data_st_strmm_openblas(:,1), data_st_strmm_openblas(:,3), 'LineWidth', 1.25,'Color', [0 1 0]); ylabel( 'GFLOPS', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); %xlabel( 'matrix dimension m=n=k', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue' ); title('STRMM (single-threaded)','FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); box(axes1,'on'); set(axes1,'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); v = axis; % extract the current ranges axis( [ 0 v(2) 0 speak ] ) % DTRMM Single threaded axes1 = subplot(4, 4, 8); hold(axes1,'on'); plot(data_st_dtrmm_asm_blis(:,1), data_st_dtrmm_asm_blis(:,3), 'LineWidth', 1.25,'Color', [0 0 1]); plot(data_st_dtrmm_openblas(:,1), data_st_dtrmm_openblas(:,3), 'LineWidth', 1.25,'Color', [0 1 0]); ylabel( 'GFLOPS', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); %xlabel( 'matrix dimension m=n=k', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue' ); title('DTRMM (single-threaded)','FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); box(axes1,'on'); set(axes1,'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); %legend({'BLIS', 'OpenBLAS', 'ARMPL'},'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue', 'Location', 'best'); v = axis; % extract the current ranges axis( [ 0 v(2) 0 dpeak ] ) % CTRMM Single threaded axes1 = subplot(4, 4, 12); hold(axes1,'on'); plot(data_st_ctrmm_1m_blis(:,1), data_st_ctrmm_1m_blis(:,3), 'LineWidth', 1.25,'Color', [0 0 1]); plot(data_st_ctrmm_openblas(:,1), data_st_ctrmm_openblas(:,3), 'LineWidth', 1.25,'Color', [0 1 0]); ylabel( 'GFLOPS', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); %xlabel( 'matrix dimension m=n=k', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue' ); title('CTRMM (single-threaded)','FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); box(axes1,'on'); set(axes1,'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); v = axis; % extract the current ranges axis( [ 0 v(2) 0 speak ] ) % ZTRMM Single threaded axes1 = subplot(4, 4, 16); hold(axes1,'on'); plot(data_st_ztrmm_1m_blis(:,1), data_st_ztrmm_1m_blis(:,3), 'LineWidth', 1.25,'Color', [0 0 1]); plot(data_st_ztrmm_openblas(:,1), data_st_ztrmm_openblas(:,3), 'LineWidth', 1.25,'Color', [0 1 0]); ylabel( 'GFLOPS', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); xlabel( 'matrix dimension m=n=k', 'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue' ); title('ZTRMM (single-threaded)','FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); box(axes1,'on'); set(axes1,'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue'); v = axis; % extract the current ranges axis( [ 0 v(2) 0 dpeak ] ) clear *trmm* rmpath(pathname) addpath(pathname_armpl) output_st_strmm_armpl output_st_dtrmm_armpl output_st_ctrmm_armpl output_st_ztrmm_armpl % Strmm Single threaded subplot(4, 4, 4); plot(data_st_strmm_armpl(:,1), data_st_strmm_armpl(:,3), '--', 'LineWidth', 1.25,'Color', [1 0 1]); subplot(4, 4, 8); plot(data_st_dtrmm_armpl(:,1), data_st_dtrmm_armpl(:,3), '--', 'LineWidth', 1.25,'Color', [1 0 1]); subplot(4, 4, 12); plot(data_st_ctrmm_armpl(:,1), data_st_ctrmm_armpl(:,3), '--', 'LineWidth', 1.25,'Color', [1 0 1]); subplot(4, 4, 16); plot(data_st_ztrmm_armpl(:,1), data_st_ztrmm_armpl(:,3), '--', 'LineWidth', 1.25,'Color', [1 0 1]); legend({'BLIS','OpenBLAS', 'ARMPL'},'FontSize', fontsize, 'FontWeight', 'bold', 'FontName', 'Helvetica Neue', 'Location', 'South'); clear *trmm* rmpath(pathname_armpl) blis-0.9.0/test/studies/thunderx2/runme.sh000077500000000000000000000131351422157504600205310ustar00rootroot00000000000000#!/bin/bash # File pefixes. exec_root="test" out_root="output" out_rootdir=$(date +%Y%m%d) #out_rootdir=20180830 mkdir -p $out_rootdir sys="thunderx2" # Bind threads to processors. #export OMP_PROC_BIND=true #export GOMP_CPU_AFFINITY="0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55" unset GOMP_CPU_AFFINITY # Threading scheme to use when multithreading if [ ${sys} = "blis" ]; then jc_nt=1 # 5th loop ic_nt=4 # 3rd loop jr_nt=1 # 2nd loop ir_nt=1 # 1st loop nt=4 elif [ ${sys} = "thunderx2" ]; then jc_1_nt=2 # 5th loop ic_1_nt=14 # 3rd loop jr_1_nt=1 # 2nd loop ir_1_nt=1 # 1st loop nt_1=28 jc_2_nt=4 # 5th loop ic_2_nt=14 # 3rd loop jr_2_nt=1 # 2nd loop ir_2_nt=1 # 1st loop nt_2=56 fi # Threadedness to test. #threads="mt1 mt2" #threads_r="mt" #threads="st" #threads_r="st" # Datatypes to test. dts="c z" dts_r="s d" # Operations to test. #l3_ops="gemm syrk hemm trmm" l3_ops="gemm" test_ops="${l3_ops}" test_ops_r="${l3_ops}" # Complex domain implementations to test. if [ ${sys} = "blis" ]; then #test_impls="openblas mkl 3mhw_blis 3m3_blis 3m2_blis 3m1_blis 4mhw_blis 4m1b_blis 4m1a_blis" test_impls="openblas 3mhw_blis 3m3_blis 3m2_blis 3m1_blis 4mhw_blis 4m1b_blis 4m1a_blis 1m_blis" elif [ ${sys} = "thunderx2" ]; then #test_impls="openblas" #test_impls="armpl" #test_impls="1m_blis armpl" test_impls="openblas armpl 1m_blis" fi # Real domain implementations to test. test_impls_r="openblas armpl asm_blis" #test_impls_r="openblas" #test_impls_r="asm_blis" #test_impls_r="armpl" cores_r="1 28 56" cores="1 28 56" # First perform real test cases. for nc in ${cores_r}; do for dt in ${dts_r}; do for im in ${test_impls_r}; do for op in ${test_ops_r}; do # Set the number of threads according to th. if [ ${nc} -gt 1 ]; then # Unset GOMP_CPU_AFFINITY for MKL when using mkl_intel_thread. if [ ${im} = "openblas" ]; then unset GOMP_CPU_AFFINITY elif [ ${im} = "armpl" ]; then unset GOMP_CPU_AFFINITY else export GOMP_CPU_AFFINITY="0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55" fi if [ ${nc} -eq 28 ]; then export BLIS_JC_NT=${jc_1_nt} export BLIS_IC_NT=${ic_1_nt} export BLIS_JR_NT=${jr_1_nt} export BLIS_IR_NT=${ir_1_nt} export OMP_NUM_THREADS=${nt_1} out_dir="${out_rootdir}/1socket" mkdir -p $out_rootdir/1socket elif [ ${nc} -eq 56 ]; then export BLIS_JC_NT=${jc_2_nt} export BLIS_IC_NT=${ic_2_nt} export BLIS_JR_NT=${jr_2_nt} export BLIS_IR_NT=${ir_2_nt} export OMP_NUM_THREADS=${nt_2} out_dir="${out_rootdir}/2sockets" mkdir -p $out_rootdir/2sockets fi th="mt" else export BLIS_JC_NT=1 export BLIS_IC_NT=1 export BLIS_JR_NT=1 export BLIS_IR_NT=1 export OMP_NUM_THREADS=1 out_dir="${out_rootdir}/st" mkdir -p $out_rootdir/st th="st" fi # Construct the name of the test executable. exec_name="${exec_root}_${dt}${op}_${im}_${th}.x" # Construct the name of the output file. out_file="${out_dir}/${out_root}_${th}_${dt}${op}_${im}.m" echo "Running (nt = ${OMP_NUM_THREADS}) ./${exec_name} > ${out_file}" # Run executable. ./${exec_name} > ${out_file} sleep 1 done done done done # Now perform complex test cases. for nc in ${cores}; do for dt in ${dts}; do for im in ${test_impls}; do for op in ${test_ops}; do # Set the number of threads according to th. if [ ${nc} -gt 1 ]; then # Unset GOMP_CPU_AFFINITY for MKL when using mkl_intel_thread. if [ ${im} = "openblas" ]; then unset GOMP_CPU_AFFINITY elif [ ${im} = "armpl" ]; then unset GOMP_CPU_AFFINITY else export GOMP_CPU_AFFINITY="0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55" fi if [ ${nc} -eq 28 ]; then export BLIS_JC_NT=${jc_1_nt} export BLIS_IC_NT=${ic_1_nt} export BLIS_JR_NT=${jr_1_nt} export BLIS_IR_NT=${ir_1_nt} export OMP_NUM_THREADS=${nt_1} out_dir="${out_rootdir}/1socket" elif [ ${nc} -eq 56 ]; then export BLIS_JC_NT=${jc_2_nt} export BLIS_IC_NT=${ic_2_nt} export BLIS_JR_NT=${jr_2_nt} export BLIS_IR_NT=${ir_2_nt} export OMP_NUM_THREADS=${nt_2} out_dir="${out_rootdir}/2sockets" fi th="mt" else export BLIS_JC_NT=1 export BLIS_IC_NT=1 export BLIS_JR_NT=1 export BLIS_IR_NT=1 export OMP_NUM_THREADS=1 out_dir="${out_rootdir}/st" th="st" fi # Construct the name of the test executable. exec_name="${exec_root}_${dt}${op}_${im}_${th}.x" # Construct the name of the output file. out_file="${out_dir}/${out_root}_${th}_${dt}${op}_${im}.m" echo "Running (nt = ${OMP_NUM_THREADS}) ./${exec_name} > ${out_file}" # Run executable. ./${exec_name} > ${out_file} sleep 1 done done done done blis-0.9.0/test/studies/thunderx2/test_gemm.c000066400000000000000000000217751422157504600212050ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas 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 The University of Texas 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 COPYRIGHT HOLDER 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. */ #include #include "blis.h" void zgemm3m_( f77_char*, f77_char*, f77_int*, f77_int*, f77_int*, dcomplex*, dcomplex*, f77_int*, dcomplex*, f77_int*, dcomplex*, dcomplex*, f77_int* ); //#define PRINT int main( int argc, char** argv ) { obj_t a, b, c; obj_t c_save; obj_t alpha, beta; dim_t m, n, k; dim_t p; dim_t p_begin, p_end, p_inc; int m_input, n_input, k_input; ind_t ind; num_t dt; char dt_ch; int r, n_repeats; trans_t transa; trans_t transb; f77_char f77_transa; f77_char f77_transb; double dtime; double dtime_save; double gflops; bli_init(); //bli_error_checking_level_set( BLIS_NO_ERROR_CHECKING ); n_repeats = 3; dt = DT; ind = IND; p_begin = P_BEGIN; p_end = P_END; p_inc = P_INC; m_input = -1; n_input = -1; k_input = -1; // Supress compiler warnings about unused variable 'ind'. ( void )ind; #if 0 cntx_t* cntx; ind_t ind_mod = ind; // A hack to use 3m1 as 1mpb (with 1m as 1mbp). if ( ind == BLIS_3M1 ) ind_mod = BLIS_1M; // Initialize a context for the current induced method and datatype. cntx = bli_gks_query_ind_cntx( ind_mod, dt ); // Set k to the kc blocksize for the current datatype. k_input = bli_cntx_get_blksz_def_dt( dt, BLIS_KC, cntx ); #elif 1 //k_input = 256; #endif // Choose the char corresponding to the requested datatype. if ( bli_is_float( dt ) ) dt_ch = 's'; else if ( bli_is_double( dt ) ) dt_ch = 'd'; else if ( bli_is_scomplex( dt ) ) dt_ch = 'c'; else dt_ch = 'z'; transa = BLIS_NO_TRANSPOSE; transb = BLIS_NO_TRANSPOSE; bli_param_map_blis_to_netlib_trans( transa, &f77_transa ); bli_param_map_blis_to_netlib_trans( transb, &f77_transb ); // Begin with initializing the last entry to zero so that // matlab allocates space for the entire array once up-front. for ( p = p_begin; p + p_inc <= p_end; p += p_inc ) ; #ifdef BLIS printf( "data_%s_%cgemm_%s_blis", THR_STR, dt_ch, STR ); #else printf( "data_%s_%cgemm_%s", THR_STR, dt_ch, STR ); #endif printf( "( %2lu, 1:4 ) = [ %4lu %4lu %4lu %7.2f ];\n", ( unsigned long )(p - p_begin + 1)/p_inc + 1, ( unsigned long )0, ( unsigned long )0, ( unsigned long )0, 0.0 ); for ( p = p_begin; p <= p_end; p += p_inc ) { if ( m_input < 0 ) m = p / ( dim_t )abs(m_input); else m = ( dim_t ) m_input; if ( n_input < 0 ) n = p / ( dim_t )abs(n_input); else n = ( dim_t ) n_input; if ( k_input < 0 ) k = p / ( dim_t )abs(k_input); else k = ( dim_t ) k_input; bli_obj_create( dt, 1, 1, 0, 0, &alpha ); bli_obj_create( dt, 1, 1, 0, 0, &beta ); bli_obj_create( dt, m, k, 0, 0, &a ); bli_obj_create( dt, k, n, 0, 0, &b ); bli_obj_create( dt, m, n, 0, 0, &c ); //bli_obj_create( dt, m, k, 2, 2*m, &a ); //bli_obj_create( dt, k, n, 2, 2*k, &b ); //bli_obj_create( dt, m, n, 2, 2*m, &c ); bli_obj_create( dt, m, n, 0, 0, &c_save ); bli_randm( &a ); bli_randm( &b ); bli_randm( &c ); bli_obj_set_conjtrans( transa, &a ); bli_obj_set_conjtrans( transb, &b ); bli_setsc( (2.0/1.0), 0.0, &alpha ); bli_setsc( (1.0/1.0), 0.0, &beta ); bli_copym( &c, &c_save ); #ifdef BLIS bli_ind_disable_all_dt( dt ); bli_ind_enable_dt( ind, dt ); #endif dtime_save = DBL_MAX; for ( r = 0; r < n_repeats; ++r ) { bli_copym( &c_save, &c ); dtime = bli_clock(); #ifdef PRINT bli_printm( "a", &a, "%4.1f", "" ); bli_printm( "b", &b, "%4.1f", "" ); bli_printm( "c", &c, "%4.1f", "" ); #endif #ifdef BLIS bli_gemm( &alpha, &a, &b, &beta, &c ); #else if ( bli_is_float( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); float* alphap = bli_obj_buffer( &alpha ); float* ap = bli_obj_buffer( &a ); float* bp = bli_obj_buffer( &b ); float* betap = bli_obj_buffer( &beta ); float* cp = bli_obj_buffer( &c ); sgemm_( &f77_transa, &f77_transb, &mm, &nn, &kk, alphap, ap, &lda, bp, &ldb, betap, cp, &ldc ); } else if ( bli_is_double( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); double* alphap = bli_obj_buffer( &alpha ); double* ap = bli_obj_buffer( &a ); double* bp = bli_obj_buffer( &b ); double* betap = bli_obj_buffer( &beta ); double* cp = bli_obj_buffer( &c ); dgemm_( &f77_transa, &f77_transb, &mm, &nn, &kk, alphap, ap, &lda, bp, &ldb, betap, cp, &ldc ); } else if ( bli_is_scomplex( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); scomplex* alphap = bli_obj_buffer( &alpha ); scomplex* ap = bli_obj_buffer( &a ); scomplex* bp = bli_obj_buffer( &b ); scomplex* betap = bli_obj_buffer( &beta ); scomplex* cp = bli_obj_buffer( &c ); cgemm_( &f77_transa, &f77_transb, &mm, &nn, &kk, alphap, ap, &lda, bp, &ldb, betap, cp, &ldc ); } else if ( bli_is_dcomplex( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); dcomplex* alphap = bli_obj_buffer( &alpha ); dcomplex* ap = bli_obj_buffer( &a ); dcomplex* bp = bli_obj_buffer( &b ); dcomplex* betap = bli_obj_buffer( &beta ); dcomplex* cp = bli_obj_buffer( &c ); zgemm_( &f77_transa, //zgemm3m_( &f77_transa, &f77_transb, &mm, &nn, &kk, alphap, ap, &lda, bp, &ldb, betap, cp, &ldc ); } #endif #ifdef PRINT bli_printm( "c after", &c, "%4.1f", "" ); exit(1); #endif dtime_save = bli_clock_min_diff( dtime_save, dtime ); } gflops = ( 2.0 * m * k * n ) / ( dtime_save * 1.0e9 ); if ( bli_is_complex( dt ) ) gflops *= 4.0; #ifdef BLIS printf( "data_%s_%cgemm_%s_blis", THR_STR, dt_ch, STR ); #else printf( "data_%s_%cgemm_%s", THR_STR, dt_ch, STR ); #endif printf( "( %2lu, 1:4 ) = [ %4lu %4lu %4lu %7.2f ];\n", ( unsigned long )(p - p_begin + 1)/p_inc + 1, ( unsigned long )m, ( unsigned long )k, ( unsigned long )n, gflops ); bli_obj_free( &alpha ); bli_obj_free( &beta ); bli_obj_free( &a ); bli_obj_free( &b ); bli_obj_free( &c ); bli_obj_free( &c_save ); } bli_finalize(); return 0; } blis-0.9.0/test/studies/thunderx2/test_hemm.c000066400000000000000000000210701422157504600211720ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas 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 The University of Texas 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 COPYRIGHT HOLDER 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. */ #include #include "blis.h" void zgemm3m_( f77_char*, f77_char*, f77_int*, f77_int*, f77_int*, dcomplex*, dcomplex*, f77_int*, dcomplex*, f77_int*, dcomplex*, dcomplex*, f77_int* ); //#define PRINT int main( int argc, char** argv ) { obj_t a, b, c; obj_t c_save; obj_t alpha, beta; dim_t m, n; dim_t p; dim_t p_begin, p_end, p_inc; int m_input, n_input; ind_t ind; num_t dt; char dt_ch; int r, n_repeats; side_t side; uplo_t uploa; f77_char f77_side; f77_char f77_uploa; double dtime; double dtime_save; double gflops; //bli_init(); //bli_error_checking_level_set( BLIS_NO_ERROR_CHECKING ); n_repeats = 3; dt = DT; ind = IND; p_begin = P_BEGIN; p_end = P_END; p_inc = P_INC; m_input = -1; n_input = -1; // Supress compiler warnings about unused variable 'ind'. ( void )ind; #if 0 cntx_t* cntx; ind_t ind_mod = ind; // A hack to use 3m1 as 1mpb (with 1m as 1mbp). if ( ind == BLIS_3M1 ) ind_mod = BLIS_1M; // Initialize a context for the current induced method and datatype. cntx = bli_gks_query_ind_cntx( ind_mod, dt ); // Set k to the kc blocksize for the current datatype. k_input = bli_cntx_get_blksz_def_dt( dt, BLIS_KC, cntx ); #elif 1 //k_input = 256; #endif // Choose the char corresponding to the requested datatype. if ( bli_is_float( dt ) ) dt_ch = 's'; else if ( bli_is_double( dt ) ) dt_ch = 'd'; else if ( bli_is_scomplex( dt ) ) dt_ch = 'c'; else dt_ch = 'z'; side = BLIS_LEFT; uploa = BLIS_LOWER; bli_param_map_blis_to_netlib_side( side, &f77_side ); bli_param_map_blis_to_netlib_uplo( uploa, &f77_uploa ); // Begin with initializing the last entry to zero so that // matlab allocates space for the entire array once up-front. for ( p = p_begin; p + p_inc <= p_end; p += p_inc ) ; #ifdef BLIS printf( "data_%s_%chemm_%s_blis", THR_STR, dt_ch, STR ); #else printf( "data_%s_%chemm_%s", THR_STR, dt_ch, STR ); #endif printf( "( %2lu, 1:3 ) = [ %4lu %4lu %7.2f ];\n", ( unsigned long )(p - p_begin + 1)/p_inc + 1, ( unsigned long )0, ( unsigned long )0, 0.0 ); for ( p = p_begin; p <= p_end; p += p_inc ) { if ( m_input < 0 ) m = p / ( dim_t )abs(m_input); else m = ( dim_t ) m_input; if ( n_input < 0 ) n = p / ( dim_t )abs(n_input); else n = ( dim_t ) n_input; bli_obj_create( dt, 1, 1, 0, 0, &alpha ); bli_obj_create( dt, 1, 1, 0, 0, &beta ); if (bli_is_left(side)) bli_obj_create( dt, m, m, 0, 0, &a ); else bli_obj_create( dt, n, n, 0, 0, &a ); bli_obj_create( dt, m, n, 0, 0, &b ); bli_obj_create( dt, m, n, 0, 0, &c ); bli_obj_create( dt, m, n, 0, 0, &c_save ); bli_randm( &a ); bli_randm( &b ); bli_randm( &c ); bli_obj_set_struc( BLIS_HERMITIAN, &a ); bli_obj_set_uplo( uploa, &a ); bli_mkherm( &a ); bli_mktrim( &a ); bli_setsc( (2.0/1.0), 0.0, &alpha ); bli_setsc( (1.0/1.0), 0.0, &beta ); bli_copym( &c, &c_save ); #ifdef BLIS bli_ind_disable_all_dt( dt ); bli_ind_enable_dt( ind, dt ); #endif dtime_save = DBL_MAX; for ( r = 0; r < n_repeats; ++r ) { bli_copym( &c_save, &c ); dtime = bli_clock(); #ifdef PRINT bli_printm( "a", &a, "%4.1f", "" ); bli_printm( "b", &b, "%4.1f", "" ); bli_printm( "c", &c, "%4.1f", "" ); #endif #ifdef BLIS bli_hemm( side, &alpha, &a, &b, &beta, &c ); #else if ( bli_is_float( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); float* alphap = bli_obj_buffer( &alpha ); float* ap = bli_obj_buffer( &a ); float* bp = bli_obj_buffer( &b ); float* betap = bli_obj_buffer( &beta ); float* cp = bli_obj_buffer( &c ); ssymm_( &f77_side, &f77_uploa, &mm, &nn, alphap, ap, &lda, bp, &ldb, betap, cp, &ldc ); } else if ( bli_is_double( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); double* alphap = bli_obj_buffer( &alpha ); double* ap = bli_obj_buffer( &a ); double* bp = bli_obj_buffer( &b ); double* betap = bli_obj_buffer( &beta ); double* cp = bli_obj_buffer( &c ); dsymm_( &f77_side, &f77_uploa, &mm, &nn, alphap, ap, &lda, bp, &ldb, betap, cp, &ldc ); } else if ( bli_is_scomplex( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); scomplex* alphap = bli_obj_buffer( &alpha ); scomplex* ap = bli_obj_buffer( &a ); scomplex* bp = bli_obj_buffer( &b ); scomplex* betap = bli_obj_buffer( &beta ); scomplex* cp = bli_obj_buffer( &c ); chemm_( &f77_side, &f77_uploa, &mm, &nn, alphap, ap, &lda, bp, &ldb, betap, cp, &ldc ); } else if ( bli_is_dcomplex( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); dcomplex* alphap = bli_obj_buffer( &alpha ); dcomplex* ap = bli_obj_buffer( &a ); dcomplex* bp = bli_obj_buffer( &b ); dcomplex* betap = bli_obj_buffer( &beta ); dcomplex* cp = bli_obj_buffer( &c ); zhemm_( &f77_side, &f77_uploa, &mm, &nn, alphap, ap, &lda, bp, &ldb, betap, cp, &ldc ); } #endif #ifdef PRINT bli_printm( "c after", &c, "%4.1f", "" ); exit(1); #endif dtime_save = bli_clock_min_diff( dtime_save, dtime ); } if ( bli_is_left(side) ) gflops = ( 2.0 * m * m * n ) / ( dtime_save * 1.0e9 ); else gflops = ( 2.0 * m * n * n ) / ( dtime_save * 1.0e9 ); if ( bli_is_complex( dt ) ) gflops *= 4.0; #ifdef BLIS printf( "data_%s_%chemm_%s_blis", THR_STR, dt_ch, STR ); #else printf( "data_%s_%chemm_%s", THR_STR, dt_ch, STR ); #endif printf( "( %2lu, 1:3 ) = [ %4lu %4lu %7.2f ];\n", ( unsigned long )(p - p_begin + 1)/p_inc + 1, ( unsigned long )m, ( unsigned long )n, gflops ); bli_obj_free( &alpha ); bli_obj_free( &beta ); bli_obj_free( &a ); bli_obj_free( &b ); bli_obj_free( &c ); bli_obj_free( &c_save ); } //bli_finalize(); return 0; } blis-0.9.0/test/studies/thunderx2/test_syrk.c000066400000000000000000000176061422157504600212460ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas 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 The University of Texas 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 COPYRIGHT HOLDER 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. */ #include #include "blis.h" //#define PRINT int main( int argc, char** argv ) { obj_t a, c; obj_t c_save; obj_t alpha, beta; dim_t m, k; dim_t p; dim_t p_begin, p_end, p_inc; int m_input, k_input; ind_t ind; num_t dt; char dt_ch; int r, n_repeats; trans_t transa; uplo_t uploc; f77_char f77_transa; f77_char f77_uploc; double dtime; double dtime_save; double gflops; //bli_init(); //bli_error_checking_level_set( BLIS_NO_ERROR_CHECKING ); n_repeats = 3; dt = DT; ind = IND; p_begin = P_BEGIN; p_end = P_END; p_inc = P_INC; m_input = -1; k_input = -1; // Supress compiler warnings about unused variable 'ind'. ( void )ind; #if 0 cntx_t* cntx; ind_t ind_mod = ind; // A hack to use 3m1 as 1mpb (with 1m as 1mbp). if ( ind == BLIS_3M1 ) ind_mod = BLIS_1M; // Initialize a context for the current induced method and datatype. cntx = bli_gks_query_ind_cntx( ind_mod, dt ); // Set k to the kc blocksize for the current datatype. k_input = bli_cntx_get_blksz_def_dt( dt, BLIS_KC, cntx ); #elif 1 //k_input = 256; #endif // Choose the char corresponding to the requested datatype. if ( bli_is_float( dt ) ) dt_ch = 's'; else if ( bli_is_double( dt ) ) dt_ch = 'd'; else if ( bli_is_scomplex( dt ) ) dt_ch = 'c'; else dt_ch = 'z'; transa = BLIS_NO_TRANSPOSE; uploc = BLIS_LOWER; bli_param_map_blis_to_netlib_trans( transa, &f77_transa ); bli_param_map_blis_to_netlib_uplo ( uploc, &f77_uploc ); // Begin with initializing the last entry to zero so that // matlab allocates space for the entire array once up-front. for ( p = p_begin; p + p_inc <= p_end; p += p_inc ) ; #ifdef BLIS printf( "data_%s_%csyrk_%s_blis", THR_STR, dt_ch, STR ); #else printf( "data_%s_%csyrk_%s", THR_STR, dt_ch, STR ); #endif printf( "( %2lu, 1:3 ) = [ %4lu %4lu %7.2f ];\n", ( unsigned long )(p - p_begin + 1)/p_inc + 1, ( unsigned long )0, ( unsigned long )0, 0.0 ); for ( p = p_begin; p <= p_end; p += p_inc ) { if ( m_input < 0 ) m = p / ( dim_t )abs(m_input); else m = ( dim_t ) m_input; if ( k_input < 0 ) k = p / ( dim_t )abs(k_input); else k = ( dim_t ) k_input; bli_obj_create( dt, 1, 1, 0, 0, &alpha ); bli_obj_create( dt, 1, 1, 0, 0, &beta ); bli_obj_create( dt, m, k, 0, 0, &a ); bli_obj_create( dt, m, m, 0, 0, &c ); //bli_obj_create( dt, m, k, 2, 2*m, &a ); //bli_obj_create( dt, k, n, 2, 2*k, &b ); //bli_obj_create( dt, m, n, 2, 2*m, &c ); bli_obj_create( dt, m, m, 0, 0, &c_save ); bli_randm( &a ); bli_obj_set_struc( BLIS_SYMMETRIC, &c ); bli_obj_set_uplo ( uploc, &c ); bli_randm( &c ); bli_obj_set_conjtrans( transa, &a ); bli_setsc( (2.0/1.0), 0.0, &alpha ); bli_setsc( (1.0/1.0), 0.0, &beta ); bli_copym( &c, &c_save ); #ifdef BLIS bli_ind_disable_all_dt( dt ); bli_ind_enable_dt( ind, dt ); #endif dtime_save = DBL_MAX; for ( r = 0; r < n_repeats; ++r ) { bli_copym( &c_save, &c ); dtime = bli_clock(); #ifdef PRINT bli_printm( "a", &a, "%4.1f", "" ); bli_printm( "c", &c, "%4.1f", "" ); #endif #ifdef BLIS bli_syrk( &alpha, &a, &beta, &c ); #else if ( bli_is_float( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldc = bli_obj_col_stride( &c ); float* alphap = bli_obj_buffer( &alpha ); float* ap = bli_obj_buffer( &a ); float* betap = bli_obj_buffer( &beta ); float* cp = bli_obj_buffer( &c ); ssyrk_( &f77_uploc, &f77_transa, &mm, &kk, alphap, ap, &lda, betap, cp, &ldc ); } else if ( bli_is_double( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldc = bli_obj_col_stride( &c ); double* alphap = bli_obj_buffer( &alpha ); double* ap = bli_obj_buffer( &a ); double* betap = bli_obj_buffer( &beta ); double* cp = bli_obj_buffer( &c ); dsyrk_( &f77_uploc, &f77_transa, &mm, &kk, alphap, ap, &lda, betap, cp, &ldc ); } else if ( bli_is_scomplex( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldc = bli_obj_col_stride( &c ); scomplex* alphap = bli_obj_buffer( &alpha ); scomplex* ap = bli_obj_buffer( &a ); scomplex* betap = bli_obj_buffer( &beta ); scomplex* cp = bli_obj_buffer( &c ); csyrk_( &f77_uploc, &f77_transa, &mm, &kk, alphap, ap, &lda, betap, cp, &ldc ); } else if ( bli_is_dcomplex( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldc = bli_obj_col_stride( &c ); dcomplex* alphap = bli_obj_buffer( &alpha ); dcomplex* ap = bli_obj_buffer( &a ); dcomplex* betap = bli_obj_buffer( &beta ); dcomplex* cp = bli_obj_buffer( &c ); zsyrk_( &f77_uploc, &f77_transa, &mm, &kk, alphap, ap, &lda, betap, cp, &ldc ); } #endif #ifdef PRINT bli_printm( "c after", &c, "%4.1f", "" ); exit(1); #endif dtime_save = bli_clock_min_diff( dtime_save, dtime ); } gflops = ( 1.0 * m * m * k ) / ( dtime_save * 1.0e9 ); if ( bli_is_complex( dt ) ) gflops *= 4.0; #ifdef BLIS printf( "data_%s_%csyrk_%s_blis", THR_STR, dt_ch, STR ); #else printf( "data_%s_%csyrk_%s", THR_STR, dt_ch, STR ); #endif printf( "( %2lu, 1:3 ) = [ %4lu %4lu %7.2f ];\n", ( unsigned long )(p - p_begin + 1)/p_inc + 1, ( unsigned long )m, ( unsigned long )k, gflops ); bli_obj_free( &alpha ); bli_obj_free( &beta ); bli_obj_free( &a ); bli_obj_free( &c ); bli_obj_free( &c_save ); } //bli_finalize(); return 0; } blis-0.9.0/test/studies/thunderx2/test_trmm.c000066400000000000000000000176261422157504600212370ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas 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 The University of Texas 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 COPYRIGHT HOLDER 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. */ #include #include "blis.h" //#define PRINT int main( int argc, char** argv ) { obj_t a, c; obj_t c_save; obj_t alpha; dim_t m, n; dim_t p; dim_t p_begin, p_end, p_inc; int m_input, n_input; ind_t ind; num_t dt; char dt_ch; int r, n_repeats; side_t side; uplo_t uploa; trans_t transa; diag_t diaga; f77_char f77_side; f77_char f77_uploa; f77_char f77_transa; f77_char f77_diaga; double dtime; double dtime_save; double gflops; //bli_init(); //bli_error_checking_level_set( BLIS_NO_ERROR_CHECKING ); n_repeats = 3; dt = DT; ind = IND; p_begin = P_BEGIN; p_end = P_END; p_inc = P_INC; m_input = -1; n_input = -1; // Supress compiler warnings about unused variable 'ind'. ( void )ind; #if 0 cntx_t* cntx; ind_t ind_mod = ind; // A hack to use 3m1 as 1mpb (with 1m as 1mbp). if ( ind == BLIS_3M1 ) ind_mod = BLIS_1M; // Initialize a context for the current induced method and datatype. cntx = bli_gks_query_ind_cntx( ind_mod, dt ); // Set k to the kc blocksize for the current datatype. k_input = bli_cntx_get_blksz_def_dt( dt, BLIS_KC, cntx ); #elif 1 //k_input = 256; #endif // Choose the char corresponding to the requested datatype. if ( bli_is_float( dt ) ) dt_ch = 's'; else if ( bli_is_double( dt ) ) dt_ch = 'd'; else if ( bli_is_scomplex( dt ) ) dt_ch = 'c'; else dt_ch = 'z'; side = BLIS_LEFT; uploa = BLIS_LOWER; transa = BLIS_NO_TRANSPOSE; diaga = BLIS_NONUNIT_DIAG; bli_param_map_blis_to_netlib_side( side, &f77_side ); bli_param_map_blis_to_netlib_uplo( uploa, &f77_uploa ); bli_param_map_blis_to_netlib_trans( transa, &f77_transa ); bli_param_map_blis_to_netlib_diag( diaga, &f77_diaga ); // Begin with initializing the last entry to zero so that // matlab allocates space for the entire array once up-front. for ( p = p_begin; p + p_inc <= p_end; p += p_inc ) ; #ifdef BLIS printf( "data_%s_%ctrmm_%s_blis", THR_STR, dt_ch, STR ); #else printf( "data_%s_%ctrmm_%s", THR_STR, dt_ch, STR ); #endif printf( "( %2lu, 1:3 ) = [ %4lu %4lu %7.2f ];\n", ( unsigned long )(p - p_begin + 1)/p_inc + 1, ( unsigned long )0, ( unsigned long )0, 0.0 ); for ( p = p_begin; p <= p_end; p += p_inc ) { if ( m_input < 0 ) m = p / ( dim_t )abs(m_input); else m = ( dim_t ) m_input; if ( n_input < 0 ) n = p / ( dim_t )abs(n_input); else n = ( dim_t ) n_input; bli_obj_create( dt, 1, 1, 0, 0, &alpha ); if ( bli_is_left( side ) ) bli_obj_create( dt, m, m, 0, 0, &a ); else bli_obj_create( dt, n, n, 0, 0, &a ); bli_obj_create( dt, m, n, 0, 0, &c ); bli_obj_create( dt, m, n, 0, 0, &c_save ); bli_randm( &a ); bli_randm( &c ); bli_obj_set_struc( BLIS_TRIANGULAR, &a ); bli_obj_set_uplo( uploa, &a ); bli_obj_set_conjtrans( transa, &a ); bli_obj_set_diag( diaga, &a ); bli_setsc( (2.0/1.0), 0.0, &alpha ); bli_copym( &c, &c_save ); #ifdef BLIS bli_ind_disable_all_dt( dt ); bli_ind_enable_dt( ind, dt ); #endif dtime_save = DBL_MAX; for ( r = 0; r < n_repeats; ++r ) { bli_copym( &c_save, &c ); dtime = bli_clock(); #ifdef PRINT bli_printm( "a", &a, "%4.1f", "" ); bli_printm( "b", &b, "%4.1f", "" ); bli_printm( "c", &c, "%4.1f", "" ); #endif #ifdef BLIS bli_trmm( side, &alpha, &a, &c ); #else if ( bli_is_float( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldc = bli_obj_col_stride( &c ); float* alphap = bli_obj_buffer( &alpha ); float* ap = bli_obj_buffer( &a ); float* cp = bli_obj_buffer( &c ); strmm_( &f77_side, &f77_uploa, &f77_transa, &f77_diaga, &mm, &nn, alphap, ap, &lda, cp, &ldc ); } else if ( bli_is_double( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldc = bli_obj_col_stride( &c ); double* alphap = bli_obj_buffer( &alpha ); double* ap = bli_obj_buffer( &a ); double* cp = bli_obj_buffer( &c ); dtrmm_( &f77_side, &f77_uploa, &f77_transa, &f77_diaga, &mm, &nn, alphap, ap, &lda, cp, &ldc ); } else if ( bli_is_scomplex( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldc = bli_obj_col_stride( &c ); scomplex* alphap = bli_obj_buffer( &alpha ); scomplex* ap = bli_obj_buffer( &a ); scomplex* cp = bli_obj_buffer( &c ); ctrmm_( &f77_side, &f77_uploa, &f77_transa, &f77_diaga, &mm, &nn, alphap, ap, &lda, cp, &ldc ); } else if ( bli_is_dcomplex( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldc = bli_obj_col_stride( &c ); dcomplex* alphap = bli_obj_buffer( &alpha ); dcomplex* ap = bli_obj_buffer( &a ); dcomplex* cp = bli_obj_buffer( &c ); ztrmm_( &f77_side, &f77_uploa, &f77_transa, &f77_diaga, &mm, &nn, alphap, ap, &lda, cp, &ldc ); } #endif #ifdef PRINT bli_printm( "c after", &c, "%4.1f", "" ); exit(1); #endif dtime_save = bli_clock_min_diff( dtime_save, dtime ); } if ( bli_is_left(side) ) gflops = ( 1.0 * m * m * n ) / ( dtime_save * 1.0e9 ); else gflops = ( 1.0 * m * n * n ) / ( dtime_save * 1.0e9 ); if ( bli_is_complex( dt ) ) gflops *= 4.0; #ifdef BLIS printf( "data_%s_%ctrmm_%s_blis", THR_STR, dt_ch, STR ); #else printf( "data_%s_%ctrmm_%s", THR_STR, dt_ch, STR ); #endif printf( "( %2lu, 1:3 ) = [ %4lu %4lu %7.2f ];\n", ( unsigned long )(p - p_begin + 1)/p_inc + 1, ( unsigned long )m, ( unsigned long )n, gflops ); bli_obj_free( &alpha ); bli_obj_free( &a ); bli_obj_free( &c ); bli_obj_free( &c_save ); } //bli_finalize(); return 0; } blis-0.9.0/test/sup/000077500000000000000000000000001422157504600142455ustar00rootroot00000000000000blis-0.9.0/test/sup/Makefile000066400000000000000000000633571422157504600157230ustar00rootroot00000000000000#!/bin/bash # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2014, The University of Texas at Austin # Copyright (C) 2019, Advanced Micro Devices, Inc. # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # # # Makefile # # Field G. Van Zee # # Makefile for standalone BLIS test drivers. # # # --- Makefile PHONY target definitions ---------------------------------------- # .PHONY: all \ st mt \ blissup-st blisconv-st eigen-st openblas-st vendor-st blasfeo-st libxsmm-st \ blissup-mt blisconv-mt eigen-mt openblas-mt vendor-mt \ check-env check-env-mk check-lib \ clean cleanx # # --- Determine makefile fragment location ------------------------------------- # # Comments: # - DIST_PATH is assumed to not exist if BLIS_INSTALL_PATH is given. # - We must use recursively expanded assignment for LIB_PATH and INC_PATH in # the second case because CONFIG_NAME is not yet set. ifneq ($(strip $(BLIS_INSTALL_PATH)),) LIB_PATH := $(BLIS_INSTALL_PATH)/lib INC_PATH := $(BLIS_INSTALL_PATH)/include/blis SHARE_PATH := $(BLIS_INSTALL_PATH)/share/blis else DIST_PATH := ../.. LIB_PATH = ../../lib/$(CONFIG_NAME) INC_PATH = ../../include/$(CONFIG_NAME) SHARE_PATH := ../.. endif # # --- Include common makefile definitions -------------------------------------- # # Include the common makefile fragment. -include $(SHARE_PATH)/common.mk # # --- BLAS and LAPACK implementations ------------------------------------------ # # BLIS library and header path. This is simply wherever it was installed. #BLIS_LIB_PATH := $(INSTALL_PREFIX)/lib #BLIS_INC_PATH := $(INSTALL_PREFIX)/include/blis # BLIS library. #BLIS_LIB := $(BLIS_LIB_PATH)/libblis.a # BLAS library path(s). This is where the BLAS libraries reside. HOME_LIB_PATH := $(HOME)/flame/lib MKL_LIB_PATH := $(HOME)/intel/mkl/lib/intel64 # netlib BLAS NETLIB_LIB := $(HOME_LIB_PATH)/libblas.a # OpenBLAS OPENBLAS_LIB := $(HOME_LIB_PATH)/libopenblas.a OPENBLASP_LIB := $(HOME_LIB_PATH)/libopenblasp.a # BLASFEO BLASFEO_LIB := $(HOME_LIB_PATH)/libblasfeo.a # libxsmm LIBXSMM_LIB := $(HOME_LIB_PATH)/libxsmm.a -ldl \ $(NETLIB_LIB) -lgfortran # ATLAS ATLAS_LIB := $(HOME_LIB_PATH)/libf77blas.a \ $(HOME_LIB_PATH)/libatlas.a # Eigen EIGEN_INC := $(HOME)/flame/eigen/include/eigen3 EIGEN_LIB := $(HOME_LIB_PATH)/libeigen_blas_static.a EIGENP_LIB := $(EIGEN_LIB) # MKL MKL_LIB := -L$(MKL_LIB_PATH) \ -lmkl_intel_lp64 \ -lmkl_core \ -lmkl_sequential \ -lpthread -lm -ldl MKLP_LIB := -L$(MKL_LIB_PATH) \ -lmkl_intel_lp64 \ -lmkl_core \ -lmkl_gnu_thread \ -lpthread -lm -ldl -fopenmp #-L$(ICC_LIB_PATH) \ #-lgomp VENDOR_LIB := $(MKL_LIB) VENDORP_LIB := $(MKLP_LIB) # # --- Problem size definitions ------------------------------------------------- # # The problem size range specification is done separately for single-threaded # and multithreaded execution. Within each threadedness scenario, we allow for # separate range specifications for cases with: # - 3L: three large/variable dimensions and no small/constant dimensions # - 2L: two large/variable dimensions and one small/constant dimension # - 1L: one large/variable dimension and two small/constant dimensions # -- Single-threaded -- PS_BEGIN_3L := 2 PS_MAX_3L := 400 PS_INC_3L := 2 PS_BEGIN_2L := 4 PS_MAX_2L := 800 PS_INC_2L := 4 PS_BEGIN_1L := 32 PS_MAX_1L := 6400 PS_INC_1L := 32 # -- Multithreaded -- P1_BEGIN_3L := 4 P1_MAX_3L := 800 P1_INC_3L := 4 P1_BEGIN_2L := 8 P1_MAX_2L := 1600 P1_INC_2L := 8 P1_BEGIN_1L := 64 P1_MAX_1L := 12800 P1_INC_1L := 64 # # --- General build definitions ------------------------------------------------ # TEST_SRC_PATH := . TEST_OBJ_PATH := . # Gather all local object files. TEST_OBJS := $(sort $(patsubst $(TEST_SRC_PATH)/%.c, \ $(TEST_OBJ_PATH)/%.o, \ $(wildcard $(TEST_SRC_PATH)/*.c))) # Override the value of CINCFLAGS so that the value of CFLAGS returned by # get-frame-cflags-for() is not cluttered up with include paths needed only # while building BLIS. CINCFLAGS := -I$(INC_PATH) # Use the "framework" CFLAGS for the configuration family. CFLAGS := $(call get-user-cflags-for,$(CONFIG_NAME)) # Add local header paths to CFLAGS. CFLAGS += -I$(TEST_SRC_PATH) # Locate the libblis library to which we will link. LIBBLIS_LINK := $(LIB_PATH)/$(LIBBLIS_L) # Define a set of CFLAGS for use with C++ and Eigen. CXXFLAGS := $(subst -std=c99,-std=c++11,$(CFLAGS)) CXXFLAGS += -I$(EIGEN_INC) # Create a copy of CXXFLAGS without -fopenmp in order to disable multithreading. CXXFLAGS_ST := -march=native $(subst -fopenmp,,$(CXXFLAGS)) CXXFLAGS_MT := -march=native $(CXXFLAGS) # Single or multithreaded string. STR_ST := -DTHR_STR=\"st\" STR_MT := -DTHR_STR=\"mt\" # Number of trials per problem size. N_TRIALS := -DN_TRIALS=3 # Problem size specification. PDEF_ST_1L := -DP_BEGIN=$(PS_BEGIN_1L) -DP_MAX=$(PS_MAX_1L) -DP_INC=$(PS_INC_1L) PDEF_ST_2L := -DP_BEGIN=$(PS_BEGIN_2L) -DP_MAX=$(PS_MAX_2L) -DP_INC=$(PS_INC_2L) PDEF_ST_3L := -DP_BEGIN=$(PS_BEGIN_3L) -DP_MAX=$(PS_MAX_3L) -DP_INC=$(PS_INC_3L) PDEF_MT_1L := -DP_BEGIN=$(P1_BEGIN_1L) -DP_MAX=$(P1_MAX_1L) -DP_INC=$(P1_INC_1L) PDEF_MT_2L := -DP_BEGIN=$(P1_BEGIN_2L) -DP_MAX=$(P1_MAX_2L) -DP_INC=$(P1_INC_2L) PDEF_MT_3L := -DP_BEGIN=$(P1_BEGIN_3L) -DP_MAX=$(P1_MAX_3L) -DP_INC=$(P1_INC_3L) ifeq ($(E),1) ERRCHK := -DERROR_CHECK else ERRCHK := -DNO_ERROR_CHECK endif # Enumerate possible datatypes and computation precisions. #dts := s d c z DTS := s d TRANS := n_n \ n_t \ t_n \ t_t # While BLIS supports all combinations of row and column storage for matrices # C, A, and B, the alternatives mostly only support CBLAS APIs, which inherently # support only "all row-storage" or "all column-storage". Thus, we disable the # building of those other drivers so that compilation/linking completes sooner. #STORS := r_r_r \ # r_r_c \ # r_c_r \ # r_c_c \ # c_r_r \ # c_r_c \ # c_c_r \ # c_c_c STORS := r_r_r \ c_c_c SHAPES := l_l_s \ l_s_l \ s_l_l \ s_s_l \ s_l_s \ l_s_s \ l_l_l #LDIMS := s l LDIMS := s # Define the small/constant m, n, and k dimensions for single core and multicore # experiments. # st, single real SMS_ST_S := 6 SNS_ST_S := 16 SKS_ST_S := 4 # mt, single real SMS_MT_S := 6 SNS_MT_S := 16 SKS_MT_S := 10 # st, double real SMS_ST_D := 6 SNS_ST_D := 8 SKS_ST_D := 4 # mt, double real SMS_MT_D := 6 SNS_MT_D := 8 SKS_MT_D := 10 # # --- Function definitions ----------------------------------------------------- # # A function to strip the underscores from a list of strings. Note that the # word 'a_b_c' is transformed into 'abc', NOT 'a b c'. stripu = $(subst _,,$(1)) # Various functions that help us construct the datatype combinations and then # extract the needed datatype strings and C preprocessor define flags. get-1of2 = $(word 1,$(subst _, ,$(1))) get-2of2 = $(word 2,$(subst _, ,$(1))) get-1of3 = $(word 1,$(subst _, ,$(1))) get-2of3 = $(word 2,$(subst _, ,$(1))) get-3of3 = $(word 3,$(subst _, ,$(1))) # A function to return the correct PDEFS variable given the shape string. # Note that we have different PDEFS for single-threaded and multithreaded. get-pdefs-st = $(strip $(subst l_l_l,$(PDEF_ST_3L), \ $(subst l_l_s,$(PDEF_ST_2L), \ $(subst l_s_l,$(PDEF_ST_2L), \ $(subst s_l_l,$(PDEF_ST_2L), \ $(subst s_s_l,$(PDEF_ST_1L), \ $(subst s_l_s,$(PDEF_ST_1L), \ $(subst l_s_s,$(PDEF_ST_1L),$(1))))))))) get-pdefs-mt = $(strip $(subst l_l_l,$(PDEF_MT_3L), \ $(subst l_l_s,$(PDEF_MT_2L), \ $(subst l_s_l,$(PDEF_MT_2L), \ $(subst s_l_l,$(PDEF_MT_2L), \ $(subst s_s_l,$(PDEF_MT_1L), \ $(subst s_l_s,$(PDEF_MT_1L), \ $(subst l_s_s,$(PDEF_MT_1L),$(1))))))))) # Datatype defs. get-dt-cpp = $(strip \ $(if $(findstring s,$(1)),-DDT=BLIS_FLOAT -DIS_FLOAT,\ $(if $(findstring d,$(1)),-DDT=BLIS_DOUBLE -DIS_DOUBLE,\ $(if $(findstring c,$(1)),-DDT=BLIS_SCOMPLEX -DIS_SCOMPLEX,\ -DDT=BLIS_DCOMPLEX -DIS_DCOMPLEX)))) # Transpose defs. get-tra-defs-a = $(strip $(subst n,-DTRANSA=BLIS_NO_TRANSPOSE -DA_NOTRANS, \ $(subst t,-DTRANSA=BLIS_TRANSPOSE -DA_TRANS,$(call get-1of2,$(1))))) get-tra-defs-b = $(strip $(subst n,-DTRANSB=BLIS_NO_TRANSPOSE -DB_NOTRANS, \ $(subst t,-DTRANSB=BLIS_TRANSPOSE -DB_TRANS,$(call get-2of2,$(1))))) get-tra-defs = $(call get-tra-defs-a,$(1)) $(call get-tra-defs-b,$(1)) # Storage defs. get-sto-uch-a = $(strip $(subst r,R, \ $(subst c,C,$(call get-1of3,$(1))))) get-sto-uch-b = $(strip $(subst r,R, \ $(subst c,C,$(call get-2of3,$(1))))) get-sto-uch-c = $(strip $(subst r,R, \ $(subst c,C,$(call get-3of3,$(1))))) get-sto-defs = $(strip \ -DSTOR3=BLIS_$(call get-sto-uch-a,$(1))$(call get-sto-uch-b,$(1))$(call get-sto-uch-c,$(1)) \ -DA_STOR_$(call get-sto-uch-a,$(1)) \ -DB_STOR_$(call get-sto-uch-b,$(1)) \ -DC_STOR_$(call get-sto-uch-c,$(1))) # Dimension defs. get-shape-defs-cm = $(if $(findstring l,$(1)),-DM_DIM=-1,-DM_DIM=$(2)) get-shape-defs-cn = $(if $(findstring l,$(1)),-DN_DIM=-1,-DN_DIM=$(2)) get-shape-defs-ck = $(if $(findstring l,$(1)),-DK_DIM=-1,-DK_DIM=$(2)) get-shape-defs-m = $(call get-shape-defs-cm,$(call get-1of3,$(1)),$(2)) get-shape-defs-n = $(call get-shape-defs-cn,$(call get-2of3,$(1)),$(2)) get-shape-defs-k = $(call get-shape-defs-ck,$(call get-3of3,$(1)),$(2)) # arguments: 1: shape (w/ underscores) 2: smallm 3: smalln 4: smallk get-shape-defs = $(strip $(call get-shape-defs-m,$(1),$(2)) \ $(call get-shape-defs-n,$(1),$(3)) \ $(call get-shape-defs-k,$(1),$(4))) #$(error l_l_s 6 8 4 = $(call get-shape-defs,l_l_s,6,8,4)) # Shape-dimension string. get-shape-str-ch = $(if $(findstring l,$(1)),p,$(2)) get-shape-str-m = $(call get-shape-str-ch,$(call get-1of3,$(1)),$(2)) get-shape-str-n = $(call get-shape-str-ch,$(call get-2of3,$(1)),$(2)) get-shape-str-k = $(call get-shape-str-ch,$(call get-3of3,$(1)),$(2)) # arguments: 1: shape (w/ underscores) 2: smallm 3: smalln 4: smallk get-shape-dim-str = m$(call get-shape-str-m,$(1),$(2))n$(call get-shape-str-n,$(1),$(3))k$(call get-shape-str-k,$(1),$(4)) # Implementation defs. # Define a function to return the appropriate -DSTR=, -D[BLIS|BLAS] cpp flags. get-imp-defs = $(strip $(subst blissup,-DSTR=\"$(1)\" -DBLIS -DSUP, \ $(subst blisconv,-DSTR=\"$(1)\" -DBLIS, \ $(subst eigen,-DSTR=\"$(1)\" -DEIGEN, \ $(subst openblas,-DSTR=\"$(1)\" -DCBLAS, \ $(subst blasfeo,-DSTR=\"$(1)\" -DCBLAS, \ $(subst libxsmm,-DSTR=\"$(1)\" -DBLAS -DXSMM, \ $(subst vendor,-DSTR=\"$(1)\" -DCBLAS,$(1))))))))) # Leading dimension defs. # Define a function to return the appropriate leading dimension cpp flag. get-ldim-defs = $(strip $(subst s,-DLDIM_SMALL, \ $(subst l,-DLDIM_LARGE,$(1)))) get-ldim-str = ld$(1) # Strip the underscores from the list of transposition and storage combinations. TRANS0 = $(call stripu,$(TRANS)) STORS0 = $(call stripu,$(STORS)) # Limit BLAS and Eigen to only using all row-stored, or all column-stored # matrices. Also, limit libxsmm to using all column-stored matrices since it # does not offer CBLAS interfaces. BSTORS0 = rrr ccc ESTORS0 = rrr ccc XSTORS0 = ccc # # --- Object and binary file definitons ---------------------------------------- # get-sms-st = $(strip $(if $(findstring s,$(1)),$(SMS_ST_S),\ $(if $(findstring d,$(1)),$(SMS_ST_D),0))) get-sks-st = $(strip $(if $(findstring s,$(1)),$(SKS_ST_S),\ $(if $(findstring d,$(1)),$(SKS_ST_D),0))) get-sns-st = $(strip $(if $(findstring s,$(1)),$(SNS_ST_S),\ $(if $(findstring d,$(1)),$(SNS_ST_D),0))) get-sms-mt = $(strip $(if $(findstring s,$(1)),$(SMS_MT_S),\ $(if $(findstring d,$(1)),$(SMS_MT_D),0))) get-sks-mt = $(strip $(if $(findstring s,$(1)),$(SKS_MT_S),\ $(if $(findstring d,$(1)),$(SKS_MT_D),0))) get-sns-mt = $(strip $(if $(findstring s,$(1)),$(SNS_MT_S),\ $(if $(findstring d,$(1)),$(SNS_MT_D),0))) get-sms = $(strip $(if $(findstring st,$(1)),$(call get-sms-st,$(2)),\ $(if $(findstring mt,$(1)),$(call get-sms-mt,$(2)),0))) get-sks = $(strip $(if $(findstring st,$(1)),$(call get-sks-st,$(2)),\ $(if $(findstring mt,$(1)),$(call get-sks-mt,$(2)),0))) get-sns = $(strip $(if $(findstring st,$(1)),$(call get-sns-st,$(2)),\ $(if $(findstring mt,$(1)),$(call get-sns-mt,$(2)),0))) # Define a function to generate an object file name using the various parameter # lists. get-objs = $(foreach dt,$(1),$(foreach tr,$(2),$(foreach st,$(3),$(foreach sh,$(4), \ $(foreach sm,$(call get-sms,$(7),$(dt)), \ $(foreach sn,$(call get-sns,$(7),$(dt)), \ $(foreach sk,$(call get-sks,$(7),$(dt)), \ $(foreach ld,$(5),test_$(dt)gemm_$(tr)_$(st)_$(call get-shape-dim-str,$(sh),$(sm),$(sn),$(sk))_$(call get-ldim-str,$(ld))_$(6)_$(7).o)))))))) # -- Single-threaded -- # Build a list of object files and binaries for each single-threaded # implementation using the get-st-objs() function defined above. BLISSUP_ST_OBJS := $(call get-objs,$(DTS),$(TRANS0),$(STORS0),$(SHAPES),$(LDIMS),blissup,st) BLISSUP_ST_BINS := $(patsubst %.o,%.x,$(BLISSUP_ST_OBJS)) BLISCONV_ST_OBJS := $(call get-objs,$(DTS),$(TRANS0),$(STORS0),$(SHAPES),$(LDIMS),blisconv,st) BLISCONV_ST_BINS := $(patsubst %.o,%.x,$(BLISCONV_ST_OBJS)) EIGEN_ST_OBJS := $(call get-objs,$(DTS),$(TRANS0),$(ESTORS0),$(SHAPES),$(LDIMS),eigen,st) EIGEN_ST_BINS := $(patsubst %.o,%.x,$(EIGEN_ST_OBJS)) OPENBLAS_ST_OBJS := $(call get-objs,$(DTS),$(TRANS0),$(BSTORS0),$(SHAPES),$(LDIMS),openblas,st) OPENBLAS_ST_BINS := $(patsubst %.o,%.x,$(OPENBLAS_ST_OBJS)) BLASFEO_ST_OBJS := $(call get-objs,$(DTS),$(TRANS0),$(BSTORS0),$(SHAPES),$(LDIMS),blasfeo,st) BLASFEO_ST_BINS := $(patsubst %.o,%.x,$(BLASFEO_ST_OBJS)) LIBXSMM_ST_OBJS := $(call get-objs,$(DTS),$(TRANS0),$(XSTORS0),$(SHAPES),$(LDIMS),libxsmm,st) LIBXSMM_ST_BINS := $(patsubst %.o,%.x,$(LIBXSMM_ST_OBJS)) VENDOR_ST_OBJS := $(call get-objs,$(DTS),$(TRANS0),$(BSTORS0),$(SHAPES),$(LDIMS),vendor,st) VENDOR_ST_BINS := $(patsubst %.o,%.x,$(VENDOR_ST_OBJS)) # Mark the object files as intermediate so that make will remove them # automatically after building the binaries on which they depend. .INTERMEDIATE: $(BLISSUP_ST_OBJS) \ $(BLISCONV_ST_OBJS) \ $(EIGEN_ST_OBJS) \ $(OPENBLAS_ST_OBJS) \ $(BLASFEO_ST_OBJS) \ $(LIBXSMM_ST_OBJS) \ $(VENDOR_ST_OBJS) # -- Multithreaded -- # Build a list of object files and binaries for each multithreaded # implementation using the get-st-objs() function defined above. BLISSUP_MT_OBJS := $(call get-objs,$(DTS),$(TRANS0),$(STORS0),$(SHAPES),$(LDIMS),blissup,mt) BLISSUP_MT_BINS := $(patsubst %.o,%.x,$(BLISSUP_MT_OBJS)) BLISCONV_MT_OBJS := $(call get-objs,$(DTS),$(TRANS0),$(STORS0),$(SHAPES),$(LDIMS),blisconv,mt) BLISCONV_MT_BINS := $(patsubst %.o,%.x,$(BLISCONV_MT_OBJS)) EIGEN_MT_OBJS := $(call get-objs,$(DTS),$(TRANS0),$(ESTORS0),$(SHAPES),$(LDIMS),eigen,mt) EIGEN_MT_BINS := $(patsubst %.o,%.x,$(EIGEN_MT_OBJS)) OPENBLAS_MT_OBJS := $(call get-objs,$(DTS),$(TRANS0),$(BSTORS0),$(SHAPES),$(LDIMS),openblas,mt) OPENBLAS_MT_BINS := $(patsubst %.o,%.x,$(OPENBLAS_MT_OBJS)) VENDOR_MT_OBJS := $(call get-objs,$(DTS),$(TRANS0),$(BSTORS0),$(SHAPES),$(LDIMS),vendor,mt) VENDOR_MT_BINS := $(patsubst %.o,%.x,$(VENDOR_MT_OBJS)) #$(error "objs = $(EIGEN_ST_BINS)" ) # Mark the object files as intermediate so that make will remove them # automatically after building the binaries on which they depend. .INTERMEDIATE: $(BLISSUP_MT_OBJS) \ $(BLISCONV_MT_OBJS) \ $(EIGEN_MT_OBJS) \ $(OPENBLAS_MT_OBJS) \ $(VENDOR_MT_OBJS) # # --- High-level targets/rules ------------------------------------------------- # all: st # -- Single-threaded -- st: blissup-st blisconv-st \ eigen-st openblas-st blasfeo-st libxsmm-st vendor-st blissup-st: check-env $(BLISSUP_ST_BINS) blisconv-st: check-env $(BLISCONV_ST_BINS) eigen-st: check-env $(EIGEN_ST_BINS) openblas-st: check-env $(OPENBLAS_ST_BINS) blasfeo-st: check-env $(BLASFEO_ST_BINS) libxsmm-st: check-env $(LIBXSMM_ST_BINS) vendor-st: check-env $(VENDOR_ST_BINS) # -- Multithreaded -- mt: blissup-mt blisconv-mt \ eigen-mt openblas-mt vendor-mt blissup-mt: check-env $(BLISSUP_MT_BINS) blisconv-mt: check-env $(BLISCONV_MT_BINS) eigen-mt: check-env $(EIGEN_MT_BINS) openblas-mt: check-env $(OPENBLAS_MT_BINS) vendor-mt: check-env $(VENDOR_MT_BINS) # --- Object file rules -------------------------------------------------------- # Define the implementations for which we will instantiate compilation rules. BIMPLS_ST := blissup blisconv openblas blasfeo libxsmm vendor BIMPLS_MT := blissup blisconv openblas vendor EIMPLS := eigen # -- Single-threaded BLAS -- # 1 2 3 4 567 8 9 # test_dgemm_nn_rrr_mpn6kp_lds_blissup_st.x # Define the function that will be used to instantiate compilation rules # for the various single-threaded implementations. define make-st-rule test_$(1)gemm_$(call stripu,$(2))_$(call stripu,$(3))_$(call get-shape-dim-str,$(4),$(5),$(6),$(7))_$(call get-ldim-str,$(8))_$(9)_st.o: test_gemm.c Makefile $(CC) $(CFLAGS) $(ERRCHK) $(N_TRIALS) $(call get-pdefs-st,$(4)) $(call get-dt-cpp,$(1)) $(call get-tra-defs,$(2)) $(call get-sto-defs,$(3)) $(call get-shape-defs,$(4),$(5),$(6),$(7)) $(call get-ldim-defs,$(8)) $(call get-imp-defs,$(9)) $(STR_ST) -c $$< -o $$@ endef # Instantiate the rule function make-st-rule() for each BLIS/BLAS/CBLAS # implementation. $(foreach dt,$(DTS), \ $(foreach tr,$(TRANS), \ $(foreach st,$(STORS), \ $(foreach sh,$(SHAPES), \ $(foreach sm,$(call get-sms,st,$(dt)), \ $(foreach sn,$(call get-sns,st,$(dt)), \ $(foreach sk,$(call get-sks,st,$(dt)), \ $(foreach ld,$(LDIMS), \ $(foreach impl,$(BIMPLS_ST), \ $(eval $(call make-st-rule,$(dt),$(tr),$(st),$(sh),$(sm),$(sn),$(sk),$(ld),$(impl)))))))))))) # -- Multithreaded BLAS -- # Define the function that will be used to instantiate compilation rules # for the various multithreaded implementations. define make-mt-rule test_$(1)gemm_$(call stripu,$(2))_$(call stripu,$(3))_$(call get-shape-dim-str,$(4),$(5),$(6),$(7))_$(call get-ldim-str,$(8))_$(9)_mt.o: test_gemm.c Makefile $(CC) $(CFLAGS) $(ERRCHK) $(N_TRIALS) $(call get-pdefs-mt,$(4)) $(call get-dt-cpp,$(1)) $(call get-tra-defs,$(2)) $(call get-sto-defs,$(3)) $(call get-shape-defs,$(4),$(5),$(6),$(7)) $(call get-ldim-defs,$(8)) $(call get-imp-defs,$(9)) $(STR_MT) -c $$< -o $$@ endef # Instantiate the rule function make-mt-rule() for each BLIS/BLAS/CBLAS # implementation. $(foreach dt,$(DTS), \ $(foreach tr,$(TRANS), \ $(foreach st,$(STORS), \ $(foreach sh,$(SHAPES), \ $(foreach sm,$(call get-sms,mt,$(dt)), \ $(foreach sn,$(call get-sns,mt,$(dt)), \ $(foreach sk,$(call get-sks,mt,$(dt)), \ $(foreach ld,$(LDIMS), \ $(foreach impl,$(BIMPLS_MT), \ $(eval $(call make-mt-rule,$(dt),$(tr),$(st),$(sh),$(sm),$(sn),$(sk),$(ld),$(impl)))))))))))) # -- Single-threaded Eigen -- # Define the function that will be used to instantiate compilation rules # for the single-threaded Eigen implementation. define make-eigst-rule test_$(1)gemm_$(call stripu,$(2))_$(call stripu,$(3))_$(call get-shape-dim-str,$(4),$(5),$(6),$(7))_$(call get-ldim-str,$(8))_$(9)_st.o: test_gemm.c Makefile $(CXX) $(CXXFLAGS_ST) $(ERRCHK) $(N_TRIALS) $(call get-pdefs-st,$(4)) $(call get-dt-cpp,$(1)) $(call get-tra-defs,$(2)) $(call get-sto-defs,$(3)) $(call get-shape-defs,$(4),$(5),$(6),$(7)) $(call get-ldim-defs,$(8)) $(call get-imp-defs,$(9)) $(STR_ST) -c $$< -o $$@ endef # Instantiate the rule function make-st-rule() for each Eigen implementation. $(foreach dt,$(DTS), \ $(foreach tr,$(TRANS), \ $(foreach st,$(STORS), \ $(foreach sh,$(SHAPES), \ $(foreach sm,$(call get-sms,st,$(dt)), \ $(foreach sn,$(call get-sns,st,$(dt)), \ $(foreach sk,$(call get-sks,st,$(dt)), \ $(foreach ld,$(LDIMS), \ $(foreach impl,$(EIMPLS), \ $(eval $(call make-eigst-rule,$(dt),$(tr),$(st),$(sh),$(sm),$(sn),$(sk),$(ld),$(impl)))))))))))) # -- Multithreaded Eigen -- # Define the function that will be used to instantiate compilation rules # for the multithreaded Eigen implementation. define make-eigmt-rule test_$(1)gemm_$(call stripu,$(2))_$(call stripu,$(3))_$(call get-shape-dim-str,$(4),$(5),$(6),$(7))_$(call get-ldim-str,$(8))_$(9)_mt.o: test_gemm.c Makefile $(CXX) $(CXXFLAGS_MT) $(ERRCHK) $(N_TRIALS) $(call get-pdefs-mt,$(4)) $(call get-dt-cpp,$(1)) $(call get-tra-defs,$(2)) $(call get-sto-defs,$(3)) $(call get-shape-defs,$(4),$(5),$(6),$(7)) $(call get-ldim-defs,$(8)) $(call get-imp-defs,$(9)) $(STR_MT) -c $$< -o $$@ endef # Instantiate the rule function make-st-rule() for each Eigen implementation. $(foreach dt,$(DTS), \ $(foreach tr,$(TRANS), \ $(foreach st,$(STORS), \ $(foreach sh,$(SHAPES), \ $(foreach sm,$(call get-sms,mt,$(dt)), \ $(foreach sn,$(call get-sns,mt,$(dt)), \ $(foreach sk,$(call get-sks,mt,$(dt)), \ $(foreach ld,$(LDIMS), \ $(foreach impl,$(EIMPLS), \ $(eval $(call make-eigmt-rule,$(dt),$(tr),$(st),$(sh),$(sm),$(sn),$(sk),$(ld),$(impl)))))))))))) # --- Executable file rules ---------------------------------------------------- # NOTE: For the BLAS test drivers, we place the BLAS libraries before BLIS # on the link command line in case BLIS was configured with the BLAS # compatibility layer. This prevents BLIS from inadvertently getting called # for the BLAS routines we are trying to test with. # -- Single-threaded -- test_%_blissup_st.x: test_%_blissup_st.o $(LIBBLIS_LINK) $(CC) $(strip $< $(LIBBLIS_LINK) $(LDFLAGS) -o $@) test_%_blisconv_st.x: test_%_blisconv_st.o $(LIBBLIS_LINK) $(CC) $(strip $< $(LIBBLIS_LINK) $(LDFLAGS) -o $@) test_%_eigen_st.x: test_%_eigen_st.o $(LIBBLIS_LINK) $(CXX) $(strip $< $(LIBBLIS_LINK) $(LDFLAGS) -o $@) test_%_openblas_st.x: test_%_openblas_st.o $(LIBBLIS_LINK) $(CC) $(strip $< $(OPENBLAS_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $@) test_%_blasfeo_st.x: test_%_blasfeo_st.o $(LIBBLIS_LINK) $(CC) $(strip $< $(BLASFEO_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $@) test_%_libxsmm_st.x: test_%_libxsmm_st.o $(LIBBLIS_LINK) $(CC) $(strip $< $(LIBXSMM_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $@) test_%_vendor_st.x: test_%_vendor_st.o $(LIBBLIS_LINK) $(CC) $(strip $< $(VENDOR_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $@) # -- Multithreaded -- test_%_blissup_mt.x: test_%_blissup_mt.o $(LIBBLIS_LINK) $(CC) $(strip $< $(LIBBLIS_LINK) $(LDFLAGS) -o $@) test_%_blisconv_mt.x: test_%_blisconv_mt.o $(LIBBLIS_LINK) $(CC) $(strip $< $(LIBBLIS_LINK) $(LDFLAGS) -o $@) test_%_eigen_mt.x: test_%_eigen_mt.o $(LIBBLIS_LINK) $(CXX) $(strip $< $(LIBBLIS_LINK) $(LDFLAGS) -o $@) test_%_openblas_mt.x: test_%_openblas_mt.o $(LIBBLIS_LINK) $(CC) $(strip $< $(OPENBLASP_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $@) test_%_vendor_mt.x: test_%_vendor_mt.o $(LIBBLIS_LINK) $(CC) $(strip $< $(VENDORP_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $@) # -- Environment check rules -- check-env: check-lib check-env-mk: ifeq ($(CONFIG_MK_PRESENT),no) $(error Cannot proceed: config.mk not detected! Run configure first) endif check-lib: check-env-mk ifeq ($(wildcard $(LIBBLIS_LINK)),) $(error Cannot proceed: BLIS library not yet built! Run make first) endif # -- Clean rules -- clean: cleanx cleanx: - $(RM_F) *.x *.o blis-0.9.0/test/sup/octave/000077500000000000000000000000001422157504600155265ustar00rootroot00000000000000blis-0.9.0/test/sup/octave/bkup/000077500000000000000000000000001422157504600164675ustar00rootroot00000000000000blis-0.9.0/test/sup/octave/bkup/gen_opsupnames.m000066400000000000000000000033161422157504600216730ustar00rootroot00000000000000function [ r_val1, r_val2 ] = gen_opsupnames( ops, stor, smalldims, ldim, pack ) nops = size( ops, 1 ); smallm = smalldims( 1 ); smalln = smalldims( 2 ); smallk = smalldims( 3 ); i = 1; for io = 1:nops op = ops( io, : ); % sprintf'ing directly into an array of strings, as in: % % opsupnames( i+0, : ) = sprintf( '%s_%s_m%dnpkp_%s_%s', ... ); % % doesn't work when the string lengths as they would if any of the constant % dimensions is greater than 9. str0 = sprintf( '%s_%s_m%dnpkp_%s_%s', op, stor, smallm, ldim, pack ); str1 = sprintf( '%s_%s_mpn%dkp_%s_%s', op, stor, smalln, ldim, pack ); str2 = sprintf( '%s_%s_mpnpk%d_%s_%s', op, stor, smallk, ldim, pack ); str3 = sprintf( '%s_%s_mpn%dk%d_%s_%s', op, stor, smalln, smallk, ldim, pack ); str4 = sprintf( '%s_%s_m%dnpk%d_%s_%s', op, stor, smallm, smallk, ldim, pack ); str5 = sprintf( '%s_%s_m%dn%dkp_%s_%s', op, stor, smallm, smalln, ldim, pack ); str6 = sprintf( '%s_%s_mpnpkp_%s_%s', op, stor, ldim, pack ); opsupnames( i+0, : ) = sprintf( '%-31s', str0 ); opsupnames( i+1, : ) = sprintf( '%-31s', str1 ); opsupnames( i+2, : ) = sprintf( '%-31s', str2 ); opsupnames( i+3, : ) = sprintf( '%-31s', str3 ); opsupnames( i+4, : ) = sprintf( '%-31s', str4 ); opsupnames( i+5, : ) = sprintf( '%-31s', str5 ); opsupnames( i+6, : ) = sprintf( '%-31s', str6 ); opnames( i+0, : ) = sprintf( '%s', op ); opnames( i+1, : ) = sprintf( '%s', op ); opnames( i+2, : ) = sprintf( '%s', op ); opnames( i+3, : ) = sprintf( '%s', op ); opnames( i+4, : ) = sprintf( '%s', op ); opnames( i+5, : ) = sprintf( '%s', op ); opnames( i+6, : ) = sprintf( '%s', op ); i = i + 7; end r_val1 = opsupnames; r_val2 = opnames; blis-0.9.0/test/sup/octave/bkup/plot_l3sup_perf.m000066400000000000000000000227751422157504600220020ustar00rootroot00000000000000function r_val = plot_l3sup_perf( opname, ... smalldims, ... data_blissup, ... data_blisconv, ... data_eigen, ... data_open, ... data_vend, vend_str, ... data_bfeo, ... data_xsmm, ... nth, ... rows, cols, ... cfreq, ... dfps, ... theid, impl ) % Define a single-/multithreadedness predicate for convenience. if nth == 1 is_st = 1; else is_st = 0; end % Define the column in which the performance rates are found. flopscol = size( data_blissup, 2 ); % Check if blasfeo data is available. has_bfeo = 1; if data_bfeo( 1, flopscol ) == 0.0 has_bfeo = 0; end % Check if libxsmm data is available. has_xsmm = 1; if data_xsmm( 1, flopscol ) == 0.0 has_xsmm = 0; end % Define which plot id will have the legend. %if is_st % if has_xsmm == 1 % legend_plot_id = 2*cols + 1*5; % else % legend_plot_id = 1*cols + 1*5; % end %else % legend_plot_id = 0*cols + 1*6; %end legend_plot_id = cols*rows; % Hold the axes. if 1 ax1 = subplot( rows, cols, theid ); hold( ax1, 'on' ); end % Set line properties. color_blissup = 'k'; lines_blissup = '-'; markr_blissup = ''; color_blisconv = 'k'; lines_blisconv = ':'; markr_blisconv = ''; color_eigen = 'm'; lines_eigen = '-.'; markr_eigen = 'o'; color_open = 'r'; lines_open = '--'; markr_open = 'o'; color_vend = 'b'; lines_vend = '-.'; markr_vend = '.'; color_bfeo = 'c'; lines_bfeo = '-'; markr_bfeo = 'o'; color_xsmm = 'g'; lines_xsmm = '-'; markr_xsmm = 'o'; % Compute the peak performance in terms of the number of double flops % executable per cycle and the clock rate. if opname(1) == 's' || opname(1) == 'c' flopspercycle = dfps * 2; else flopspercycle = dfps; end max_perf_core = (flopspercycle * cfreq) * 1; % Escape underscores in the title. title_opname = strrep( opname, '_', '\_' ); % Print the title to a string. titlename = '%s'; titlename = sprintf( titlename, title_opname ); % Set the legend strings. blissup_lg = sprintf( 'BLIS sup' ); blisconv_lg = sprintf( 'BLIS conv' ); eigen_lg = sprintf( 'Eigen' ); open_lg = sprintf( 'OpenBLAS' ); vend_lg = vend_str; bfeo_lg = sprintf( 'BLASFEO' ); xsmm_lg = sprintf( 'libxsmm' ); % Set axes range values. y_scale = 1.00; x_begin = 0; %x_end is set below. y_begin = 0; y_end = max_perf_core * y_scale; % Set axes names. if nth == 1 yaxisname = 'GFLOPS'; else yaxisname = 'GFLOPS/core'; end %flopscol = 4; msize = 5; if 1 fontsize = 12; else fontsize = 16; end linesize = 0.5; legend_loc = 'southeast'; % -------------------------------------------------------------------- % Automatically detect a column with the increasing problem size. % Then set the maximum x-axis value. for psize_col = 1:3 if data_blissup( 1, psize_col ) ~= data_blissup( 2, psize_col ) break; end end x_axis( :, 1 ) = data_blissup( :, psize_col ); % Compute the number of data points we have in the x-axis. Note that we % only use half the data points for the m = n = k column of graphs. %if mod(theid-1,cols) == 6 % np = size( data_blissup, 1 ) / 2; %else % np = size( data_blissup, 1 ); %end np = size( data_blissup, 1 ); % Grab the last x-axis value. x_end = data_blissup( np, psize_col ); %data_peak( 1, 1:2 ) = [ 0 max_perf_core ]; %data_peak( 2, 1:2 ) = [ x_end max_perf_core ]; blissup_ln = line( x_axis( 1:np, 1 ), data_blissup( 1:np, flopscol ) / nth, ... 'Color',color_blissup, 'LineStyle',lines_blissup, ... 'LineWidth',linesize ); blisconv_ln = line( x_axis( 1:np, 1 ), data_blisconv( 1:np, flopscol ) / nth, ... 'Color',color_blisconv, 'LineStyle',lines_blisconv, ... 'LineWidth',linesize ); eigen_ln = line( x_axis( 1:np, 1 ), data_eigen( 1:np, flopscol ) / nth, ... 'Color',color_eigen, 'LineStyle',lines_eigen, ... 'LineWidth',linesize ); open_ln = line( x_axis( 1:np, 1 ), data_open( 1:np, flopscol ) / nth, ... 'Color',color_open, 'LineStyle',lines_open, ... 'LineWidth',linesize ); vend_ln = line( x_axis( 1:np, 1 ), data_vend( 1:np, flopscol ) / nth, ... 'Color',color_vend, 'LineStyle',lines_vend, ... 'LineWidth',linesize ); if has_bfeo == 1 bfeo_ln = line( x_axis( 1:np, 1 ), data_bfeo( 1:np, flopscol ) / nth, ... 'Color',color_bfeo, 'LineStyle',lines_bfeo, ... 'LineWidth',linesize ); else bfeo_ln = line( nan, nan, ... 'Color',color_bfeo, 'LineStyle',lines_bfeo, ... 'LineWidth',linesize ); end if has_xsmm == 1 xsmm_ln = line( x_axis( 1:np, 1 ), data_xsmm( 1:np, flopscol ) / nth, ... 'Color',color_xsmm, 'LineStyle',lines_xsmm, ... 'LineWidth',linesize ); else xsmm_ln = line( nan, nan, ... 'Color',color_xsmm, 'LineStyle',lines_xsmm, ... 'LineWidth',linesize ); end xlim( ax1, [x_begin x_end] ); ylim( ax1, [y_begin y_end] ); if 10000 <= x_end && x_end < 15000 x_tick2 = x_end - 2000; x_tick1 = x_tick2/2; %xticks( ax1, [ x_tick1 x_tick2 ] ); xticks( ax1, [ 3000 6000 9000 12000 ] ); elseif 6000 <= x_end && x_end < 10000 x_tick2 = x_end - 2000; x_tick1 = x_tick2/2; %xticks( ax1, [ x_tick1 x_tick2 ] ); xticks( ax1, [ 2000 4000 6000 8000 ] ); elseif 4000 <= x_end && x_end < 6000 x_tick2 = x_end - 1000; x_tick1 = x_tick2/2; xticks( ax1, [ x_tick1 x_tick2 ] ); elseif 2000 <= x_end && x_end < 3000 x_tick2 = x_end - 400; x_tick1 = x_tick2/2; xticks( ax1, [ x_tick1 x_tick2 ] ); elseif 500 <= x_end && x_end < 1000 x_tick3 = x_end*(3/4); x_tick2 = x_end*(2/4); x_tick1 = x_end*(1/4); xticks( ax1, [ x_tick1 x_tick2 x_tick3 ] ); end % xpos ypos %set( leg,'Position',[11.32 6.36 1.15 0.7 ] ); % (1,4tl) if nth == 1 && theid == legend_plot_id if has_xsmm == 1 % single-threaded, with libxsmm (ccc) leg = legend( ... [ blissup_ln blisconv_ln eigen_ln open_ln vend_ln bfeo_ln xsmm_ln ], ... blissup_lg, blisconv_lg, eigen_lg, open_lg, vend_lg, bfeo_lg, xsmm_lg, ... 'Location', legend_loc ); set( leg,'Box','off','Color','none','Units','inches' ); if impl == 'octave' set( leg,'FontSize',fontsize ); set( leg,'Position',[15.35 4.62 1.9 1.20] ); % (1,4tl) else set( leg,'FontSize',fontsize-3 ); set( leg,'Position',[18.20 10.20 1.15 0.7 ] ); % (1,4tl) end else % single-threaded, without libxsmm (rrr, or other) leg = legend( ... [ blissup_ln blisconv_ln eigen_ln open_ln vend_ln bfeo_ln ], ... blissup_lg, blisconv_lg, eigen_lg, open_lg, vend_lg, bfeo_lg, ... 'Location', legend_loc ); set( leg,'Box','off','Color','none','Units','inches' ); if impl == 'octave' set( leg,'FontSize',fontsize ); set( leg,'Position',[15.35 7.40 1.9 1.10] ); % (1,4tl) else set( leg,'FontSize',fontsize-1 ); set( leg,'Position',[18.24 10.15 1.15 0.7] ); % (1,4tl) end end elseif nth > 1 && theid == legend_plot_id % multithreaded leg = legend( ... [ blissup_ln blisconv_ln eigen_ln open_ln vend_ln ], ... blissup_lg, blisconv_lg, eigen_lg, open_lg, vend_lg, ... 'Location', legend_loc ); set( leg,'Box','off','Color','none','Units','inches' ); if impl == 'octave' set( leg,'FontSize',fontsize ); set( leg,'Position',[18.20 10.30 1.9 0.95] ); % (1,4tl) else set( leg,'FontSize',fontsize-1 ); set( leg,'Position',[18.24 10.15 1.15 0.7] ); % (1,4tl) end end set( ax1,'FontSize',fontsize ); set( ax1,'TitleFontSizeMultiplier',1.0 ); % default is 1.1. box( ax1, 'on' ); titl = title( titlename ); set( titl, 'FontWeight', 'normal' ); % default font style is now 'bold'. % The default is to align the plot title across whole figure, not the box. % This is a hack to nudge the title back to the center of the box. if impl == 'octave' tpos = get( titl, 'Position' ); % For some reason, the titles in the graphs in the last column start % off in a different relative position than the graphs in the other % columns. Here, we manually account for that. if mod(theid-1,cols) == 6 tpos(1) = tpos(1) + -10; else tpos(1) = tpos(1) + -40; end set( titl, 'Position', tpos ); set( titl, 'FontSize', fontsize ); else % impl == 'matlab' tpos = get( titl, 'Position' ); tpos(1) = tpos(1) + 90; set( titl, 'Position', tpos ); end sll_str = sprintf( 'm = %u; n = k', smalldims(1) ); lsl_str = sprintf( 'n = %u; m = k', smalldims(2) ); lls_str = sprintf( 'k = %u; m = n', smalldims(3) ); lss_str = sprintf( 'm; n = %u, k = %u', smalldims(2), smalldims(3) ); sls_str = sprintf( 'n; m = %u, k = %u', smalldims(1), smalldims(3) ); ssl_str = sprintf( 'k; m = %u, n = %u', smalldims(1), smalldims(2) ); lll_str = sprintf( 'm = n = k' ); % Place labels on the bottom row of graphs. if theid > (rows-1)*cols %xlab = xlabel( ax1,xaxisname ); %tpos = get( xlab, 'Position' ) %tpos(2) = tpos(2) + 10; %set( xlab, 'Position', tpos ); if theid == rows*cols - 6 xlab = xlabel( ax1, sll_str ); elseif theid == rows*cols - 5 xlab = xlabel( ax1, lsl_str ); elseif theid == rows*cols - 4 xlab = xlabel( ax1, lls_str ); elseif theid == rows*cols - 3 xlab = xlabel( ax1, lss_str ); elseif theid == rows*cols - 2 xlab = xlabel( ax1, sls_str ); elseif theid == rows*cols - 1 xlab = xlabel( ax1, ssl_str ); elseif theid == rows*cols - 0 xlab = xlabel( ax1, lll_str ); end end % Place labels on the left-hand column of graphs. if mod(theid-1,cols) == 0 ylab = ylabel( ax1,yaxisname ); end r_val = 0; blis-0.9.0/test/sup/octave/bkup/plot_panel_trxsh.m000066400000000000000000000135461422157504600222430ustar00rootroot00000000000000function r_val = plot_panel_trxsh ... ( ... cfreq, ... dflopspercycle, ... nth, ... thr_str, ... dt_ch, ... stor_str, ... smalldims, ... ldim_str, ... pack_str, ... dirpath, ... arch_str, ... vend_str, ... impl ... ) if 1 == 1 %fig = figure('Position', [100, 100, 2400, 1500]); fig = figure('Position', [100, 100, 2400, 1200]); orient( fig, 'portrait' ); set(gcf,'PaperUnits', 'inches'); if impl == 'matlab' set(gcf,'PaperSize', [11.5 20.4]); set(gcf,'PaperPosition', [0 0 11.5 20.4]); set(gcf,'PaperPositionMode','manual'); else % impl == 'octave' % octave 4.x set(gcf,'PaperSize', [12 22.0]); set(gcf,'PaperPositionMode','auto'); end set(gcf,'PaperOrientation','landscape'); end %cfreq = 1.8; %dflopspercycle = 32; if nth == 1 is_st = 1; else is_st = 0; end % Create filename "templates" for the files that contain the performance % results. filetemp_blissup = '%s/output_%s_%s_blissup.m'; filetemp_blisconv = '%s/output_%s_%s_blisconv.m'; filetemp_eigen = '%s/output_%s_%s_eigen.m'; filetemp_open = '%s/output_%s_%s_openblas.m'; filetemp_vend = '%s/output_%s_%s_vendor.m'; filetemp_bfeo = '%s/output_%s_%s_blasfeo.m'; filetemp_xsmm = '%s/output_%s_%s_libxsmm.m'; % Create a variable name "template" for the variables contained in the % files outlined above. vartemp = 'data_%s_%s_%s( :, : )'; % Define the datatypes and operations we will be plotting. oproot = sprintf( '%cgemm', dt_ch ); ops( 1, : ) = sprintf( '%s_nn', oproot ); ops( 2, : ) = sprintf( '%s_nt', oproot ); ops( 3, : ) = sprintf( '%s_tn', oproot ); ops( 4, : ) = sprintf( '%s_tt', oproot ); % Generate datatype-specific operation names from the set of operations % and datatypes. [ opsupnames, opnames ] = gen_opsupnames( ops, stor_str, smalldims, ldim_str, pack_str ); n_opsupnames = size( opsupnames, 1 ); %opsupnames %opnames %return % Iterate over the list of datatype-specific operation names. for opi = 1:n_opsupnames %for opi = 1:1 % Grab the current datatype combination. opsupname = opsupnames( opi, : ); opname = opnames( opi, : ); % Remove leading and trailing whitespace. opsupname = strtrim( opsupname ); opname = strtrim( opname ); str = sprintf( 'Plotting %2d: %s', opi, opsupname ); disp(str); % Construct filenames for the data files from templates. file_blissup = sprintf( filetemp_blissup, dirpath, thr_str, opsupname ); file_blisconv = sprintf( filetemp_blisconv, dirpath, thr_str, opsupname ); file_eigen = sprintf( filetemp_eigen, dirpath, thr_str, opsupname ); file_open = sprintf( filetemp_open, dirpath, thr_str, opsupname ); file_vend = sprintf( filetemp_vend, dirpath, thr_str, opsupname ); file_bfeo = sprintf( filetemp_bfeo, dirpath, thr_str, opsupname ); % Load the data files. %str = sprintf( ' Loading %s', file_blissup ); disp(str); run( file_blissup ) run( file_blisconv ) run( file_eigen ) run( file_open ) run( file_vend ) if is_st run( file_bfeo ) end % Construct variable names for the variables in the data files. var_blissup = sprintf( vartemp, thr_str, opname, 'blissup' ); var_blisconv = sprintf( vartemp, thr_str, opname, 'blisconv' ); var_eigen = sprintf( vartemp, thr_str, opname, 'eigen' ); var_open = sprintf( vartemp, thr_str, opname, 'openblas' ); var_vend = sprintf( vartemp, thr_str, opname, 'vendor' ); var_bfeo = sprintf( vartemp, thr_str, opname, 'blasfeo' ); % Use eval() to instantiate the variable names constructed above, % copying each to a simplified name. data_blissup = eval( var_blissup ); % e.g. data_st_dgemm_blissup( :, : ); data_blisconv = eval( var_blisconv ); % e.g. data_st_dgemm_blisconv( :, : ); data_eigen = eval( var_eigen ); % e.g. data_st_dgemm_eigen( :, : ); data_open = eval( var_open ); % e.g. data_st_dgemm_openblas( :, : ); data_vend = eval( var_vend ); % e.g. data_st_dgemm_vendor( :, : ); if is_st data_bfeo = eval( var_bfeo ); % e.g. data_st_dgemm_blasfeo( :, : ); else % Set the data variable to zeros using the same dimensions as the other % variables. data_bfeo = zeros( size( data_blissup, 1 ), ... size( data_blissup, 2 ) ); end if is_st && stor_str == 'ccc' % Only read xsmm data for the column storage case, since that's the % only format that libxsmm supports. file_xsmm = sprintf( filetemp_xsmm, dirpath, thr_str, opsupname ); run( file_xsmm ) var_xsmm = sprintf( vartemp, thr_str, opname, 'libxsmm' ); data_xsmm = eval( var_xsmm ); % e.g. data_st_dgemm_libxsmm( :, : ); else % Set the data variable to zeros using the same dimensions as the other % variables. data_xsmm = zeros( size( data_blissup, 1 ), ... size( data_blissup, 2 ) ); end % Plot one result in an m x n grid of plots, via the subplot() % function. if 1 == 1 plot_l3sup_perf( opsupname, ... smalldims, ... data_blissup, ... data_blisconv, ... data_eigen, ... data_open, ... data_vend, vend_str, ... data_bfeo, ... data_xsmm, ... nth, ... 4, 7, ... cfreq, ... dflopspercycle, ... opi, impl ); clear data_st_*gemm_*; clear data_mt_*gemm_*; clear data_blissup; clear data_blisconv; clear data_eigen; clear data_open; clear data_vend; clear data_bfeo; clear data_xsmm; end end % Construct the name of the file to which we will output the graph. outfile = sprintf( 'l3sup_%s_%s_%s_nt%d.pdf', oproot, stor_str, arch_str, nth ); % Output the graph to pdf format. %print(gcf, 'gemm_md','-fillpage','-dpdf'); %print(gcf, outfile,'-bestfit','-dpdf'); if impl == 'octave' print(gcf, outfile); else % if impl == 'matlab' print(gcf, outfile,'-bestfit','-dpdf'); end blis-0.9.0/test/sup/octave/bkup/runthese.m000066400000000000000000000007361422157504600205100ustar00rootroot00000000000000% kabylake plot_panel_trxsh(3.80,16,1,'st','d','rrr',[ 6 8 4 ],'lds','uaub','../results/kabylake/20200302/mnkt100000_st','kbl','MKL','octave'); close; clear all; % haswell plot_panel_trxsh(3.5,16,1,'st','d','rrr',[ 6 8 4 ],'lds','uaub','../results/haswell/20200302/mnkt100000_st','has','MKL','octave'); close; clear all; % epyc plot_panel_trxsh(3.00, 8,1,'st','d','rrr',[ 6 8 4 ],'lds','uaub','../results/epyc/20200302/mnkt100000_st','epyc','MKL','octave'); close; clear all; blis-0.9.0/test/sup/octave/gen_opsupnames.m000066400000000000000000000033161422157504600207320ustar00rootroot00000000000000function [ r_val1, r_val2 ] = gen_opsupnames( ops, stor, smalldims, ldim, pack ) nops = size( ops, 1 ); smallm = smalldims( 1 ); smalln = smalldims( 2 ); smallk = smalldims( 3 ); i = 1; for io = 1:nops op = ops( io, : ); % sprintf'ing directly into an array of strings, as in: % % opsupnames( i+0, : ) = sprintf( '%s_%s_m%dnpkp_%s_%s', ... ); % % doesn't work when the string lengths as they would if any of the constant % dimensions is greater than 9. str0 = sprintf( '%s_%s_m%dnpkp_%s_%s', op, stor, smallm, ldim, pack ); str1 = sprintf( '%s_%s_mpn%dkp_%s_%s', op, stor, smalln, ldim, pack ); str2 = sprintf( '%s_%s_mpnpk%d_%s_%s', op, stor, smallk, ldim, pack ); str3 = sprintf( '%s_%s_mpn%dk%d_%s_%s', op, stor, smalln, smallk, ldim, pack ); str4 = sprintf( '%s_%s_m%dnpk%d_%s_%s', op, stor, smallm, smallk, ldim, pack ); str5 = sprintf( '%s_%s_m%dn%dkp_%s_%s', op, stor, smallm, smalln, ldim, pack ); str6 = sprintf( '%s_%s_mpnpkp_%s_%s', op, stor, ldim, pack ); opsupnames( i+0, : ) = sprintf( '%-31s', str0 ); opsupnames( i+1, : ) = sprintf( '%-31s', str1 ); opsupnames( i+2, : ) = sprintf( '%-31s', str2 ); opsupnames( i+3, : ) = sprintf( '%-31s', str3 ); opsupnames( i+4, : ) = sprintf( '%-31s', str4 ); opsupnames( i+5, : ) = sprintf( '%-31s', str5 ); opsupnames( i+6, : ) = sprintf( '%-31s', str6 ); opnames( i+0, : ) = sprintf( '%s', op ); opnames( i+1, : ) = sprintf( '%s', op ); opnames( i+2, : ) = sprintf( '%s', op ); opnames( i+3, : ) = sprintf( '%s', op ); opnames( i+4, : ) = sprintf( '%s', op ); opnames( i+5, : ) = sprintf( '%s', op ); opnames( i+6, : ) = sprintf( '%s', op ); i = i + 7; end r_val1 = opsupnames; r_val2 = opnames; blis-0.9.0/test/sup/octave/load_data.m000066400000000000000000000011271422157504600176150ustar00rootroot00000000000000function [ r_val ] = load_data( ... filetemp, ... dirpath, ... thr_str, ... opsupname, ... vartemp, ... opname, ... impl_str ... ) filepath = sprintf( filetemp, dirpath, thr_str, opsupname ); run( filepath ) varname = sprintf( vartemp, thr_str, opname, impl_str ); data = eval( varname ); % e.g. data_st_dgemm_blissup( :, : ); r_val = data; blis-0.9.0/test/sup/octave/plot_l3sup_perf.m000066400000000000000000000226321422157504600210310ustar00rootroot00000000000000function r_val = plot_l3sup_perf( opname, ... smalldims, ... data_blissup, ... data_blisconv, ... data_eigen, ... data_open, ... data_vend, vend_str, ... data_bfeo, ... data_xsmm, ... nth, ... rows, cols, ... cfreq, ... dfps, ... theid, impl, ... fontsize, ... leg_pos_st, leg_pos_st_x, leg_pos_mt, ... sp_margins ) % Define the column in which the performance rates are found. flopscol = size( data_blissup, 2 ); % Check if blasfeo data is available. has_bfeo = 1; if data_bfeo( 1, flopscol ) == 0.0 has_bfeo = 0; end % Check if libxsmm data is available. has_xsmm = 1; if data_xsmm( 1, flopscol ) == 0.0 has_xsmm = 0; end % Define which plot id will have the legend. % NOTE: We can draw the legend on any graph as long as it has already been % rendered. Since the coordinates are global, we can simply always wait until % the final graph to draw the legend. legend_plot_id = cols*rows; % Set line properties. color_blissup = 'k'; lines_blissup = '-'; markr_blissup = ''; color_blisconv = 'k'; lines_blisconv = ':'; markr_blisconv = ''; color_eigen = 'm'; lines_eigen = '-.'; markr_eigen = 'o'; color_open = 'r'; lines_open = '--'; markr_open = 'o'; color_vend = 'b'; lines_vend = '-.'; markr_vend = '.'; color_bfeo = 'c'; lines_bfeo = '-'; markr_bfeo = 'o'; color_xsmm = 'g'; lines_xsmm = '-'; markr_xsmm = 'o'; % Compute the peak performance in terms of the number of double flops % executable per cycle and the clock rate. if opname(1) == 's' || opname(1) == 'c' flopspercycle = dfps * 2; else flopspercycle = dfps; end max_perf_core = (flopspercycle * cfreq) * 1; % Escape underscores in the title. title_opname = strrep( opname, '_', '\_' ); % Print the title to a string. titlename = '%s'; titlename = sprintf( titlename, title_opname ); % Set the legend strings. blissup_lg = sprintf( 'BLIS sup' ); blisconv_lg = sprintf( 'BLIS conv' ); eigen_lg = sprintf( 'Eigen' ); open_lg = sprintf( 'OpenBLAS' ); vend_lg = vend_str; bfeo_lg = sprintf( 'BLASFEO' ); xsmm_lg = sprintf( 'libxsmm' ); % Set axes range values. y_scale = 1.00; x_begin = 0; %x_end is set below. y_begin = 0; y_end = max_perf_core * y_scale; % Set axes names. if nth == 1 yaxisname = 'GFLOPS'; else yaxisname = 'GFLOPS/core'; end % Set the marker size, line size, and other items. msize = 5; linesize = 0.8; legend_loc = 'southeast'; %ax1 = subplot( rows, cols, theid ); ax1 = subplot_tight( rows, cols, theid, sp_margins ); % Hold the axes. hold( ax1, 'on' ); % -------------------------------------------------------------------- % Automatically detect a column with the increasing problem size. % Then set the maximum x-axis value. for psize_col = 1:3 if data_blissup( 1, psize_col ) ~= data_blissup( 2, psize_col ) break; end end x_axis( :, 1 ) = data_blissup( :, psize_col ); % Compute the number of data points we have in the x-axis. Note that we % only use half the data points for the m = n = k column of graphs. %if mod(theid-1,cols) == 6 % np = size( data_blissup, 1 ) / 2; %else % np = size( data_blissup, 1 ); %end np = size( data_blissup, 1 ); % Grab the last x-axis value. x_end = data_blissup( np, psize_col ); %data_peak( 1, 1:2 ) = [ 0 max_perf_core ]; %data_peak( 2, 1:2 ) = [ x_end max_perf_core ]; blissup_ln = line( x_axis( 1:np, 1 ), data_blissup( 1:np, flopscol ) / nth, ... 'Color',color_blissup, 'LineStyle',lines_blissup, ... 'LineWidth',linesize ); blisconv_ln = line( x_axis( 1:np, 1 ), data_blisconv( 1:np, flopscol ) / nth, ... 'Color',color_blisconv, 'LineStyle',lines_blisconv, ... 'LineWidth',linesize ); eigen_ln = line( x_axis( 1:np, 1 ), data_eigen( 1:np, flopscol ) / nth, ... 'Color',color_eigen, 'LineStyle',lines_eigen, ... 'LineWidth',linesize ); open_ln = line( x_axis( 1:np, 1 ), data_open( 1:np, flopscol ) / nth, ... 'Color',color_open, 'LineStyle',lines_open, ... 'LineWidth',linesize ); vend_ln = line( x_axis( 1:np, 1 ), data_vend( 1:np, flopscol ) / nth, ... 'Color',color_vend, 'LineStyle',lines_vend, ... 'LineWidth',linesize ); if has_bfeo == 1 bfeo_ln = line( x_axis( 1:np, 1 ), data_bfeo( 1:np, flopscol ) / nth, ... 'Color',color_bfeo, 'LineStyle',lines_bfeo, ... 'LineWidth',linesize ); else bfeo_ln = line( nan, nan, ... 'Color',color_bfeo, 'LineStyle',lines_bfeo, ... 'LineWidth',linesize ); end if has_xsmm == 1 xsmm_ln = line( x_axis( 1:np, 1 ), data_xsmm( 1:np, flopscol ) / nth, ... 'Color',color_xsmm, 'LineStyle',lines_xsmm, ... 'LineWidth',linesize ); else xsmm_ln = line( nan, nan, ... 'Color',color_xsmm, 'LineStyle',lines_xsmm, ... 'LineWidth',linesize ); end xlim( ax1, [x_begin x_end] ); ylim( ax1, [y_begin y_end] ); if 10000 <= x_end && x_end < 15000 x_tick2 = x_end - 2000; x_tick1 = x_tick2/2; %xticks( ax1, [ x_tick1 x_tick2 ] ); xticks( ax1, [ 3000 6000 9000 12000 ] ); elseif 6000 <= x_end && x_end < 10000 x_tick2 = x_end - 2000; x_tick1 = x_tick2/2; %xticks( ax1, [ x_tick1 x_tick2 ] ); xticks( ax1, [ 2000 4000 6000 8000 ] ); elseif 4000 <= x_end && x_end < 6000 x_tick2 = x_end - 1000; x_tick1 = x_tick2/2; xticks( ax1, [ x_tick1 x_tick2 ] ); elseif 2000 <= x_end && x_end < 3000 x_tick2 = x_end - 400; x_tick1 = x_tick2/2; xticks( ax1, [ x_tick1 x_tick2 ] ); elseif 500 <= x_end && x_end < 1000 x_tick3 = x_end*(3/4); x_tick2 = x_end*(2/4); x_tick1 = x_end*(1/4); xticks( ax1, [ x_tick1 x_tick2 x_tick3 ] ); end % xpos ypos %set( leg,'Position',[11.32 6.36 1.15 0.7 ] ); % (1,4tl) if nth == 1 && theid == legend_plot_id if has_xsmm == 1 % single-threaded, with libxsmm (ccc) leg = legend( ... [ blissup_ln blisconv_ln eigen_ln open_ln vend_ln bfeo_ln xsmm_ln ], ... blissup_lg, blisconv_lg, eigen_lg, open_lg, vend_lg, bfeo_lg, xsmm_lg, ... 'Location', legend_loc ); set( leg,'Box','off','Color','none','Units','inches' ); set( leg,'FontSize',fontsize ); %set( leg,'Position',[15.35 4.62 1.9 1.20] ); set( leg,'Position',leg_pos_st_x ); else % single-threaded, without libxsmm (rrr, or other) leg = legend( ... [ blissup_ln blisconv_ln eigen_ln open_ln vend_ln bfeo_ln ], ... blissup_lg, blisconv_lg, eigen_lg, open_lg, vend_lg, bfeo_lg, ... 'Location', legend_loc ); set( leg,'Box','off','Color','none','Units','inches' ); set( leg,'FontSize',fontsize ); %set( leg,'Position',[15.35 7.40 1.9 1.10] ); set( leg,'Position',leg_pos_st ); end elseif nth > 1 && theid == legend_plot_id % multithreaded leg = legend( ... [ blissup_ln blisconv_ln eigen_ln open_ln vend_ln ], ... blissup_lg, blisconv_lg, eigen_lg, open_lg, vend_lg, ... 'Location', legend_loc ); set( leg,'Box','off','Color','none','Units','inches' ); set( leg,'FontSize',fontsize ); %set( leg,'Position',[18.20 10.30 1.9 0.95] ); set( leg,'Position',leg_pos_mt ); end set( ax1,'FontSize',fontsize ); set( ax1,'TitleFontSizeMultiplier',1.0 ); % default is 1.1. box( ax1, 'on' ); titl = title( titlename ); set( titl, 'FontWeight', 'normal' ); % default font style is now 'bold'. % The default is to align the plot title across whole figure, not the box. % This is a hack to nudge the title back to the center of the box. if impl == 'octave' tpos = get( titl, 'Position' ); % For some reason, the titles in the graphs in certain columns start % off in a different relative position. Here, we manually fix that. %modid = mod(theid-1,cols); %if modid == 0 || modid == 1 || modid == 2 % tpos(1) = tpos(1) + 0; %elseif modid == 3 || modid == 4 || modid == 5 % tpos(1) = tpos(1) + 0; %else % tpos(1) = tpos(1) + 0; %end set( titl, 'Position', tpos ); set( titl, 'FontSize', fontsize-1 ); else % impl == 'matlab' tpos = get( titl, 'Position' ); tpos(1) = tpos(1) + 90; set( titl, 'Position', tpos ); end sll_str = sprintf( 'm = %u; n = k', smalldims(1) ); lsl_str = sprintf( 'n = %u; m = k', smalldims(2) ); lls_str = sprintf( 'k = %u; m = n', smalldims(3) ); lss_str = sprintf( 'm; n = %u, k = %u', smalldims(2), smalldims(3) ); sls_str = sprintf( 'n; m = %u, k = %u', smalldims(1), smalldims(3) ); ssl_str = sprintf( 'k; m = %u, n = %u', smalldims(1), smalldims(2) ); lll_str = sprintf( 'm = n = k' ); % Place labels on the bottom row of graphs. if theid > (rows-1)*cols %xlab = xlabel( ax1,xaxisname ); %tpos = get( xlab, 'Position' ) %tpos(2) = tpos(2) + 10; %set( xlab, 'Position', tpos ); if theid == rows*cols - 6 xlab = xlabel( ax1, sll_str ); elseif theid == rows*cols - 5 xlab = xlabel( ax1, lsl_str ); elseif theid == rows*cols - 4 xlab = xlabel( ax1, lls_str ); elseif theid == rows*cols - 3 xlab = xlabel( ax1, lss_str ); elseif theid == rows*cols - 2 xlab = xlabel( ax1, sls_str ); elseif theid == rows*cols - 1 xlab = xlabel( ax1, ssl_str ); elseif theid == rows*cols - 0 xlab = xlabel( ax1, lll_str ); end end % Place labels on the left-hand column of graphs. if mod(theid-1,cols) == 0 ylab = ylabel( ax1,yaxisname ); end r_val = 0; blis-0.9.0/test/sup/octave/plot_panel_trxsh.m000066400000000000000000000113511422157504600212720ustar00rootroot00000000000000function r_val = plot_panel_trxsh ... ( ... cfreq, ... dflopspercycle, ... nth, ... thr_str, ... dt_ch, ... stor_str, ... smalldims, ... ldim_str, ... pack_str, ... dirpath, ... arch_str, ... vend_str ... ) impl = 'octave'; %subp = 'default'; subp = 'tight'; if strcmp( subp, 'default' ) position = [100 100 2400 1200]; papersize = [12 22.0]; sp_margins = [ 0.070 0.049 ]; else position = [100 100 2308 1202]; papersize = [12.5 24.0]; fontsize = 14; leg_pos_st = [10.85 7.43 1.3 1.2 ]; leg_pos_st_x = [14.15 4.35 1.3 1.4 ]; leg_pos_mt = [10.85 7.66 1.3 1.0 ]; sp_margins = [ 0.063 0.033 ]; end %fig = figure('Position', [100, 100, 2400, 1500]); fig = figure('Position', position); orient( fig, 'portrait' ); set(gcf,'PaperUnits', 'inches'); if impl == 'octave' set(gcf,'PaperSize', papersize); set(gcf,'PaperPositionMode','auto'); else % impl == 'matlab' set(gcf,'PaperSize', [11.5 20.4]); set(gcf,'PaperPosition', [0 0 11.5 20.4]); set(gcf,'PaperPositionMode','manual'); end set(gcf,'PaperOrientation','landscape'); % Create filename "templates" for the files that contain the performance % results. filetemp_blissup = '%s/output_%s_%s_blissup.m'; filetemp_blisconv = '%s/output_%s_%s_blisconv.m'; filetemp_eigen = '%s/output_%s_%s_eigen.m'; filetemp_open = '%s/output_%s_%s_openblas.m'; filetemp_vend = '%s/output_%s_%s_vendor.m'; filetemp_bfeo = '%s/output_%s_%s_blasfeo.m'; filetemp_xsmm = '%s/output_%s_%s_libxsmm.m'; % Create a variable name "template" for the variables contained in the % files outlined above. vartemp = 'data_%s_%s_%s( :, : )'; % Define the datatypes and operations we will be plotting. oproot = sprintf( '%cgemm', dt_ch ); ops( 1, : ) = sprintf( '%s_nn', oproot ); ops( 2, : ) = sprintf( '%s_nt', oproot ); ops( 3, : ) = sprintf( '%s_tn', oproot ); ops( 4, : ) = sprintf( '%s_tt', oproot ); % Generate datatype-specific operation names from the set of operations % and datatypes. [ opsupnames, opnames ] = gen_opsupnames( ops, stor_str, smalldims, ldim_str, pack_str ); n_opsupnames = size( opsupnames, 1 ); %opsupnames %opnames %return % Iterate over the list of datatype-specific operation names. for opi = 1:n_opsupnames %for opi = 1:1 % Grab the current datatype combination. opsupname = opsupnames( opi, : ); opname = opnames( opi, : ); % Remove leading and trailing whitespace. opsupname = strtrim( opsupname ); opname = strtrim( opname ); % Output progress through the loop. str = sprintf( 'Plotting %2d: %s', opi, opsupname ); disp(str); % Load the data for each dataset. data_blissup = load_data( filetemp_blissup, dirpath, thr_str, opsupname, vartemp, opname, 'blissup' ); data_blisconv = load_data( filetemp_blisconv, dirpath, thr_str, opsupname, vartemp, opname, 'blisconv' ); data_eigen = load_data( filetemp_eigen, dirpath, thr_str, opsupname, vartemp, opname, 'eigen' ); data_open = load_data( filetemp_open, dirpath, thr_str, opsupname, vartemp, opname, 'openblas' ); data_vend = load_data( filetemp_vend, dirpath, thr_str, opsupname, vartemp, opname, 'vendor' ); % Only read blasfeo data for single-threaded cases. if nth == 1 data_bfeo = load_data( filetemp_bfeo, dirpath, thr_str, opsupname, vartemp, opname, 'blasfeo' ); else data_bfeo = zeros( size( data_blissup, 1 ), size( data_blissup, 2 ) ); end % Only read libxsmm data for single-threaded cases, and cases that use column % storage since that's the only format that libxsmm supports. %if nth == 1 && stor_str == 'ccc' if nth == 1 && strcmp( stor_str, 'ccc' ) data_xsmm = load_data( filetemp_xsmm, dirpath, thr_str, opsupname, vartemp, opname, 'libxsmm' ); else data_xsmm = zeros( size( data_blissup, 1 ), size( data_blissup, 2 ) ); end % Plot one result in an m x n grid of plots, via the subplot() % function. plot_l3sup_perf( opsupname, ... smalldims, ... data_blissup, ... data_blisconv, ... data_eigen, ... data_open, ... data_vend, vend_str, ... data_bfeo, ... data_xsmm, ... nth, ... 4, 7, ... cfreq, ... dflopspercycle, ... opi, impl, ... fontsize, ... leg_pos_st, leg_pos_st_x, leg_pos_mt, ... sp_margins ); end % Construct the name of the file to which we will output the graph. outfile = sprintf( 'l3sup_%s_%s_%s_nt%d.pdf', oproot, stor_str, arch_str, nth ); % Output the graph to pdf format. if strcmp( impl, 'octave' ) print(gcf, outfile); else print(gcf, outfile,'-bestfit','-dpdf'); end blis-0.9.0/test/sup/octave/runthese.m000066400000000000000000000053161422157504600175460ustar00rootroot00000000000000% kabylake plot_panel_trxsh(3.80,16,1,'st','d','rrr',[ 6 8 4 ],'lds','uaub','../results/kabylake/20200302/mnkt100000_st','kbl','MKL'); close; clear all; % haswell plot_panel_trxsh(3.5,16,1,'st','d','rrr',[ 6 8 4 ],'lds','uaub','../results/haswell/20200302/mnkt100000_st','has','MKL'); close; clear all; % zen plot_panel_trxsh(3.00, 8,1,'st','d','rrr',[ 6 8 4 ],'lds','uaub','../results/epyc/20200302/mnkt100000_st','zen','MKL'); close; clear all; % zen2 plot_panel_trxsh(3.40,16, 1,'st','d','rrr',[ 6 8 4 ],'lds','uaub','../results/zen2/20201006/mnkt100000_st', 'zen2','MKL'); close; clear all; plot_panel_trxsh(3.40,16, 1,'st','d','ccc',[ 6 8 4 ],'lds','uaub','../results/zen2/20201006/mnkt100000_st', 'zen2','MKL'); close; clear all; plot_panel_trxsh(3.40,16, 1,'st','s','rrr',[ 6 16 4 ],'lds','uaub','../results/zen2/20201006/mnkt100000_st', 'zen2','MKL'); close; clear all; plot_panel_trxsh(3.40,16, 1,'st','s','ccc',[ 6 16 4 ],'lds','uaub','../results/zen2/20201006/mnkt100000_st', 'zen2','MKL'); close; clear all; plot_panel_trxsh(2.60,16,32,'mt','d','rrr',[ 6 8 10 ],'lds','uaub','../results/zen2/20201006/mnkt100000_mt32','zen2','MKL'); close; clear all; plot_panel_trxsh(2.60,16,32,'mt','d','ccc',[ 6 8 10 ],'lds','uaub','../results/zen2/20201006/mnkt100000_mt32','zen2','MKL'); close; clear all; plot_panel_trxsh(2.60,16,32,'mt','s','rrr',[ 6 16 10 ],'lds','uaub','../results/zen2/20201006/mnkt100000_mt32','zen2','MKL'); close; clear all; plot_panel_trxsh(2.60,16,32,'mt','s','ccc',[ 6 16 10 ],'lds','uaub','../results/zen2/20201006/mnkt100000_mt32','zen2','MKL'); close; clear all; plot_panel_trxsh(3.40,16, 1,'st','d','rrr',[ 6 8 4 ],'lds','uaub','../results/zen2/20201006/mnkt100000_st', 'zen2','MKL'); close; clear all; plot_panel_trxsh(3.40,16, 1,'st','d','ccc',[ 6 8 4 ],'lds','uaub','../results/zen2/20201006/mnkt100000_st', 'zen2','MKL'); close; clear all; plot_panel_trxsh(3.40,16, 1,'st','s','rrr',[ 6 16 4 ],'lds','uaub','../results/zen2/20201006/mnkt100000_st', 'zen2','MKL'); close; clear all; plot_panel_trxsh(3.40,16, 1,'st','s','ccc',[ 6 16 4 ],'lds','uaub','../results/zen2/20201006/mnkt100000_st', 'zen2','MKL'); close; clear all; plot_panel_trxsh(2.60,16,32,'mt','d','rrr',[ 6 8 10 ],'lds','uaub','../results/zen2/20201006/mnkt100000_mt32','zen2','MKL'); close; clear all; plot_panel_trxsh(2.60,16,32,'mt','d','ccc',[ 6 8 10 ],'lds','uaub','../results/zen2/20201006/mnkt100000_mt32','zen2','MKL'); close; clear all; plot_panel_trxsh(2.60,16,32,'mt','s','rrr',[ 6 16 10 ],'lds','uaub','../results/zen2/20201006/mnkt100000_mt32','zen2','MKL'); close; clear all; plot_panel_trxsh(2.60,16,32,'mt','s','ccc',[ 6 16 10 ],'lds','uaub','../results/zen2/20201006/mnkt100000_mt32','zen2','MKL'); close; clear all; blis-0.9.0/test/sup/octave/subplot_tight.m000066400000000000000000000120171422157504600205740ustar00rootroot00000000000000% % Copyright (c) 2016, Nikolay S. % 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 % % 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 COPYRIGHT OWNER 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. % function vargout=subplot_tight(m, n, p, margins, varargin) %% subplot_tight % A subplot function substitude with margins user tunabble parameter. % %% Syntax % h=subplot_tight(m, n, p); % h=subplot_tight(m, n, p, margins); % h=subplot_tight(m, n, p, margins, subplotArgs...); % %% Description % Our goal is to grant the user the ability to define the margins between neighbouring % subplots. Unfotrtunately Matlab subplot function lacks this functionality, and the % margins between subplots can reach 40% of figure area, which is pretty lavish. While at % the begining the function was implememnted as wrapper function for Matlab function % subplot, it was modified due to axes del;etion resulting from what Matlab subplot % detected as overlapping. Therefore, the current implmenetation makes no use of Matlab % subplot function, using axes instead. This can be problematic, as axis and subplot % parameters are quie different. Set isWrapper to "True" to return to wrapper mode, which % fully supports subplot format. % %% Input arguments (defaults exist): % margins- two elements vector [vertical,horizontal] defining the margins between % neighbouring axes. Default value is 0.04 % %% Output arguments % same as subplot- none, or axes handle according to function call. % %% Issues & Comments % - Note that if additional elements are used in order to be passed to subplot, margins % parameter must be defined. For default margins value use empty element- []. % - % %% Example % close all; % img=imread('peppers.png'); % figSubplotH=figure('Name', 'subplot'); % figSubplotTightH=figure('Name', 'subplot_tight'); % nElems=17; % subplotRows=ceil(sqrt(nElems)-1); % subplotRows=max(1, subplotRows); % subplotCols=ceil(nElems/subplotRows); % for iElem=1:nElems % figure(figSubplotH); % subplot(subplotRows, subplotCols, iElem); % imshow(img); % figure(figSubplotTightH); % subplot_tight(subplotRows, subplotCols, iElem, [0.0001]); % imshow(img); % end % %% See also % - subplot % %% Revision history % First version: Nikolay S. 2011-03-29. % Last update: Nikolay S. 2012-05-24. % % *List of Changes:* % 2012-05-24 % Non wrapping mode (based on axes command) added, to deal with an issue of disappearing % subplots occuring with massive axes. %% Default params isWrapper=false; if (nargin<4) || isempty(margins) margins=[0.04,0.04]; % default margins value- 4% of figure end if length(margins)==1 margins(2)=margins; end %note n and m are switched as Matlab indexing is column-wise, while subplot indexing is row-wise :( [subplot_col,subplot_row]=ind2sub([n,m],p); height=(1-(m+1)*margins(1))/m; % single subplot height width=(1-(n+1)*margins(2))/n; % single subplot width % note subplot suppors vector p inputs- so a merged subplot of higher dimentions will be created subplot_cols=1+max(subplot_col)-min(subplot_col); % number of column elements in merged subplot subplot_rows=1+max(subplot_row)-min(subplot_row); % number of row elements in merged subplot merged_height=subplot_rows*( height+margins(1) )- margins(1); % merged subplot height merged_width= subplot_cols*( width +margins(2) )- margins(2); % merged subplot width merged_bottom=(m-max(subplot_row))*(height+margins(1)) +margins(1); % merged subplot bottom position merged_left=min(subplot_col)*(width+margins(2))-width; % merged subplot left position pos=[merged_left, merged_bottom, merged_width, merged_height]; if isWrapper h=subplot(m, n, p, varargin{:}, 'Units', 'Normalized', 'Position', pos); else h=axes('Position', pos, varargin{:}); end if nargout==1 vargout=h; end blis-0.9.0/test/sup/old/000077500000000000000000000000001422157504600150235ustar00rootroot00000000000000blis-0.9.0/test/sup/old/octave_mt/000077500000000000000000000000001422157504600170045ustar00rootroot00000000000000blis-0.9.0/test/sup/old/octave_mt/gen_opsupnames.m000066400000000000000000000033161422157504600222100ustar00rootroot00000000000000function [ r_val1, r_val2 ] = gen_opsupnames( ops, stor, smalldims, ldim, pack ) nops = size( ops, 1 ); smallm = smalldims( 1 ); smalln = smalldims( 2 ); smallk = smalldims( 3 ); i = 1; for io = 1:nops op = ops( io, : ); % sprintf'ing directly into an array of strings, as in: % % opsupnames( i+0, : ) = sprintf( '%s_%s_m%dnpkp_%s_%s', ... ); % % doesn't work when the string lengths as they would if any of the constant % dimensions is greater than 9. str0 = sprintf( '%s_%s_m%dnpkp_%s_%s', op, stor, smallm, ldim, pack ); str1 = sprintf( '%s_%s_mpn%dkp_%s_%s', op, stor, smalln, ldim, pack ); str2 = sprintf( '%s_%s_mpnpk%d_%s_%s', op, stor, smallk, ldim, pack ); str3 = sprintf( '%s_%s_mpn%dk%d_%s_%s', op, stor, smalln, smallk, ldim, pack ); str4 = sprintf( '%s_%s_m%dnpk%d_%s_%s', op, stor, smallm, smallk, ldim, pack ); str5 = sprintf( '%s_%s_m%dn%dkp_%s_%s', op, stor, smallm, smalln, ldim, pack ); str6 = sprintf( '%s_%s_mpnpkp_%s_%s', op, stor, ldim, pack ); opsupnames( i+0, : ) = sprintf( '%-31s', str0 ); opsupnames( i+1, : ) = sprintf( '%-31s', str1 ); opsupnames( i+2, : ) = sprintf( '%-31s', str2 ); opsupnames( i+3, : ) = sprintf( '%-31s', str3 ); opsupnames( i+4, : ) = sprintf( '%-31s', str4 ); opsupnames( i+5, : ) = sprintf( '%-31s', str5 ); opsupnames( i+6, : ) = sprintf( '%-31s', str6 ); opnames( i+0, : ) = sprintf( '%s', op ); opnames( i+1, : ) = sprintf( '%s', op ); opnames( i+2, : ) = sprintf( '%s', op ); opnames( i+3, : ) = sprintf( '%s', op ); opnames( i+4, : ) = sprintf( '%s', op ); opnames( i+5, : ) = sprintf( '%s', op ); opnames( i+6, : ) = sprintf( '%s', op ); i = i + 7; end r_val1 = opsupnames; r_val2 = opnames; blis-0.9.0/test/sup/old/octave_mt/plot_l3sup_perf.m000066400000000000000000000201741422157504600223060ustar00rootroot00000000000000function r_val = plot_l3sup_perf( opname, ... data_blissup, ... data_blislpab, ... data_eigen, ... data_open, ... data_vend, vend_str, ... nth, ... rows, cols, ... cfreq, ... dfps, ... theid, impl ) %if ... %mod(theid-1,cols) == 2 || ... % ... %mod(theid-1,cols) == 3 || ... % ... %mod(theid-1,cols) == 4 || ... % 0 == 1 ... %theid >= 19 % show_plot = 0; %else show_plot = 1; %end %legend_plot_id = 11; legend_plot_id = 0*cols + 1*6; if 1 ax1 = subplot( rows, cols, theid ); hold( ax1, 'on' ); end % Set line properties. color_blissup = 'k'; lines_blissup = '-'; markr_blissup = ''; color_blislpab = 'k'; lines_blislpab = ':'; markr_blislpab = ''; color_eigen = 'm'; lines_eigen = '-.'; markr_eigen = 'o'; color_open = 'r'; lines_open = '--'; markr_open = 'o'; color_vend = 'b'; lines_vend = '-.'; markr_vend = '.'; % Compute the peak performance in terms of the number of double flops % executable per cycle and the clock rate. if opname(1) == 's' || opname(1) == 'c' flopspercycle = dfps * 2; else flopspercycle = dfps; end max_perf_core = (flopspercycle * cfreq) * 1; % Escape underscores in the title. title_opname = strrep( opname, '_', '\_' ); % Print the title to a string. titlename = '%s'; titlename = sprintf( titlename, title_opname ); % Set the legend strings. blissup_legend = sprintf( 'BLIS sup' ); blislpab_legend = sprintf( 'BLIS conv' ); eigen_legend = sprintf( 'Eigen' ); open_legend = sprintf( 'OpenBLAS' ); %vend_legend = sprintf( 'MKL' ); %vend_legend = sprintf( 'ARMPL' ); vend_legend = vend_str; % Set axes range values. y_scale = 1.00; x_begin = 0; %x_end is set below. y_begin = 0; y_end = max_perf_core * y_scale; % Set axes names. if nth == 1 yaxisname = 'GFLOPS'; else yaxisname = 'GFLOPS/core'; end %flopscol = 4; flopscol = size( data_blissup, 2 ); msize = 5; if 1 fontsize = 12; else fontsize = 16; end linesize = 0.5; legend_loc = 'southeast'; % -------------------------------------------------------------------- % Automatically detect a column with the increasing problem size. % Then set the maximum x-axis value. for psize_col = 1:3 if data_blissup( 1, psize_col ) ~= data_blissup( 2, psize_col ) break; end end x_axis( :, 1 ) = data_blissup( :, psize_col ); % Compute the number of data points we have in the x-axis. Note that we % only use half the data points for the m = n = k column of graphs. %if mod(theid-1,cols) == 6 % np = size( data_blissup, 1 ) / 2; %else % np = size( data_blissup, 1 ); %end np = size( data_blissup, 1 ); % Grab the last x-axis value. x_end = data_blissup( np, psize_col ); %data_peak( 1, 1:2 ) = [ 0 max_perf_core ]; %data_peak( 2, 1:2 ) = [ x_end max_perf_core ]; if show_plot == 1 blissup_ln = line( x_axis( 1:np, 1 ), data_blissup( 1:np, flopscol ) / nth, ... 'Color',color_blissup, 'LineStyle',lines_blissup, ... 'LineWidth',linesize ); blislpab_ln = line( x_axis( 1:np, 1 ), data_blislpab( 1:np, flopscol ) / nth, ... 'Color',color_blislpab, 'LineStyle',lines_blislpab, ... 'LineWidth',linesize ); eigen_ln = line( x_axis( 1:np, 1 ), data_eigen( 1:np, flopscol ) / nth, ... 'Color',color_eigen, 'LineStyle',lines_eigen, ... 'LineWidth',linesize ); open_ln = line( x_axis( 1:np, 1 ), data_open( 1:np, flopscol ) / nth, ... 'Color',color_open, 'LineStyle',lines_open, ... 'LineWidth',linesize ); vend_ln = line( x_axis( 1:np, 1 ), data_vend( 1:np, flopscol ) / nth, ... 'Color',color_vend, 'LineStyle',lines_vend, ... 'LineWidth',linesize ); elseif theid == legend_plot_id blissup_ln = line( nan, nan, ... 'Color',color_blissup, 'LineStyle',lines_blissup, ... 'LineWidth',linesize ); blislpab_ln = line( nan, nan, ... 'Color',color_blislpab, 'LineStyle',lines_blislpab, ... 'LineWidth',linesize ); eigen_ln = line( nan, nan, ... 'Color',color_eigen, 'LineStyle',lines_eigen, ... 'LineWidth',linesize ); open_ln = line( nan, nan, ... 'Color',color_open, 'LineStyle',lines_open, ... 'LineWidth',linesize ); vend_ln = line( nan, nan, ... 'Color',color_vend, 'LineStyle',lines_vend, ... 'LineWidth',linesize ); end xlim( ax1, [x_begin x_end] ); ylim( ax1, [y_begin y_end] ); if mod(theid-1,cols) == 3 || mod(theid-1,cols) == 4 || mod(theid-1,cols) == 5 if nth == 12 ylim( ax1, [y_begin y_end/2] ); elseif nth > 12 ylim( ax1, [y_begin y_end/6] ); end end if 10000 <= x_end && x_end < 15000 x_tick2 = x_end - 2000; x_tick1 = x_tick2/2; %xticks( ax1, [ x_tick1 x_tick2 ] ); xticks( ax1, [ 4000 8000 12000 ] ); elseif 6000 <= x_end && x_end < 10000 x_tick2 = x_end - 2000; x_tick1 = x_tick2/2; %xticks( ax1, [ x_tick1 x_tick2 ] ); xticks( ax1, [ x_tick1 x_tick2 ] ); elseif 4000 <= x_end && x_end < 6000 x_tick2 = x_end - 1000; x_tick1 = x_tick2/2; xticks( ax1, [ x_tick1 x_tick2 ] ); elseif 2000 <= x_end && x_end < 3000 x_tick2 = x_end - 400; x_tick1 = x_tick2/2; xticks( ax1, [ x_tick1 x_tick2 ] ); elseif 500 <= x_end && x_end < 1000 x_tick3 = x_end*(3/4); x_tick2 = x_end*(2/4); x_tick1 = x_end*(1/4); xticks( ax1, [ x_tick1 x_tick2 x_tick3 ] ); end if show_plot == 1 || theid == legend_plot_id if theid == legend_plot_id leg = legend( ... [ ... blissup_ln ... blislpab_ln ... eigen_ln ... open_ln ... vend_ln ... ], ... blissup_legend, ... blislpab_legend, ... eigen_legend, ... open_legend, ... vend_legend, ... 'Location', legend_loc ); set( leg,'Box','off' ); set( leg,'Color','none' ); set( leg,'Units','inches' ); if impl == 'octave' set( leg,'FontSize',fontsize ); %set( leg,'Position',[12.40 10.60 1.9 0.95 ] ); % (1,4tl) set( leg,'Position',[18.80 10.60 1.9 0.95 ] ); % (1,4tl) else set( leg,'FontSize',fontsize-1 ); set( leg,'Position',[18.24 10.15 1.15 0.7 ] ); % (1,4tl) end set( leg,'Box','off' ); set( leg,'Color','none' ); set( leg,'Units','inches' ); % xpos ypos %set( leg,'Position',[11.32 6.36 1.15 0.7 ] ); % (1,4tl) end end set( ax1,'FontSize',fontsize ); set( ax1,'TitleFontSizeMultiplier',1.0 ); % default is 1.1. box( ax1, 'on' ); titl = title( titlename ); set( titl, 'FontWeight', 'normal' ); % default font style is now 'bold'. % The default is to align the plot title across whole figure, not the box. % This is a hack to nudge the title back to the center of the box. if impl == 'octave' tpos = get( titl, 'Position' ); % For some reason, the titles in the graphs in the last column start % off in a different relative position than the graphs in the other % columns. Here, we manually account for that. if mod(theid-1,cols) == 6 tpos(1) = tpos(1) + -10; else tpos(1) = tpos(1) + -40; end set( titl, 'Position', tpos ); set( titl, 'FontSize', fontsize ); else % impl == 'matlab' tpos = get( titl, 'Position' ); tpos(1) = tpos(1) + 90; set( titl, 'Position', tpos ); end if theid > (rows-1)*cols %xlab = xlabel( ax1,xaxisname ); %tpos = get( xlab, 'Position' ) %tpos(2) = tpos(2) + 10; %set( xlab, 'Position', tpos ); if theid == rows*cols - 6 xlab = xlabel( ax1, 'm = 6; n = k' ); elseif theid == rows*cols - 5 xlab = xlabel( ax1, 'n = 8; m = k' ); elseif theid == rows*cols - 4 xlab = xlabel( ax1, 'k = 10; m = n' ); elseif theid == rows*cols - 3 xlab = xlabel( ax1, 'm; n = 8, k = 10' ); elseif theid == rows*cols - 2 xlab = xlabel( ax1, 'n; m = 6, k = 10' ); elseif theid == rows*cols - 1 xlab = xlabel( ax1, 'k; m = 6, n = 8' ); elseif theid == rows*cols - 0 xlab = xlabel( ax1, 'm = n = k' ); end end if mod(theid-1,cols) == 0 ylab = ylabel( ax1,yaxisname ); end r_val = 0; blis-0.9.0/test/sup/old/octave_mt/plot_panel_trxsh.m000066400000000000000000000110421422157504600225450ustar00rootroot00000000000000function r_val = plot_panel_trxsh ... ( ... cfreq, ... dflopspercycle, ... nth, ... thr_str, ... dt_ch, ... stor_str, ... smalldims, ... ldim_str, ... pack_str, ... dirpath, ... arch_str, ... vend_str, ... impl ... ) %cfreq = 1.8; %dflopspercycle = 32; % Create filename "templates" for the files that contain the performance % results. filetemp_blissup = '%s/output_%s_%s_blissup.m'; filetemp_blisconv = '%s/output_%s_%s_blisconv.m'; filetemp_eigen = '%s/output_%s_%s_eigen.m'; filetemp_open = '%s/output_%s_%s_openblas.m'; filetemp_vend = '%s/output_%s_%s_vendor.m'; % Create a variable name "template" for the variables contained in the % files outlined above. vartemp = 'data_%s_%s_%s( :, : )'; % Define the datatypes and operations we will be plotting. oproot = sprintf( '%cgemm', dt_ch ); ops( 1, : ) = sprintf( '%s_nn', oproot ); ops( 2, : ) = sprintf( '%s_nt', oproot ); ops( 3, : ) = sprintf( '%s_tn', oproot ); ops( 4, : ) = sprintf( '%s_tt', oproot ); % Generate datatype-specific operation names from the set of operations % and datatypes. [ opsupnames, opnames ] = gen_opsupnames( ops, stor_str, smalldims, ldim_str, pack_str ); n_opsupnames = size( opsupnames, 1 ); %opsupnames %opnames %return if 1 == 1 %fig = figure('Position', [100, 100, 2400, 1500]); fig = figure('Position', [100, 100, 2400, 1200]); orient( fig, 'portrait' ); set(gcf,'PaperUnits', 'inches'); if impl == 'matlab' set(gcf,'PaperSize', [11.5 20.4]); set(gcf,'PaperPosition', [0 0 11.5 20.4]); set(gcf,'PaperPositionMode','manual'); else % impl == 'octave' % octave 4.x set(gcf,'PaperSize', [12 22.0]); set(gcf,'PaperPositionMode','auto'); end set(gcf,'PaperOrientation','landscape'); end % Iterate over the list of datatype-specific operation names. for opi = 1:n_opsupnames %for opi = 1:1 % Grab the current datatype combination. opsupname = opsupnames( opi, : ); opname = opnames( opi, : ); opsupname = strtrim( opsupname ); opname = strtrim( opname ); str = sprintf( 'Plotting %2d: %s', opi, opsupname ); disp(str); % Construct filenames for the data files from templates. file_blissup = sprintf( filetemp_blissup, dirpath, thr_str, opsupname ); file_blisconv = sprintf( filetemp_blisconv, dirpath, thr_str, opsupname ); file_eigen = sprintf( filetemp_eigen, dirpath, thr_str, opsupname ); file_open = sprintf( filetemp_open, dirpath, thr_str, opsupname ); file_vend = sprintf( filetemp_vend, dirpath, thr_str, opsupname ); % Load the data files. %str = sprintf( ' Loading %s', file_blissup ); disp(str); run( file_blissup ) run( file_blisconv ) run( file_eigen ) run( file_open ) run( file_vend ) % Construct variable names for the variables in the data files. var_blissup = sprintf( vartemp, thr_str, opname, 'blissup' ); var_blisconv = sprintf( vartemp, thr_str, opname, 'blisconv' ); var_eigen = sprintf( vartemp, thr_str, opname, 'eigen' ); var_open = sprintf( vartemp, thr_str, opname, 'openblas' ); var_vend = sprintf( vartemp, thr_str, opname, 'vendor' ); % Use eval() to instantiate the variable names constructed above, % copying each to a simplified name. data_blissup = eval( var_blissup ); % e.g. data_st_dgemm_blissup( :, : ); data_blisconv = eval( var_blisconv ); % e.g. data_st_dgemm_blisconv( :, : ); data_eigen = eval( var_eigen ); % e.g. data_st_dgemm_eigen( :, : ); data_open = eval( var_open ); % e.g. data_st_dgemm_openblas( :, : ); data_vend = eval( var_vend ); % e.g. data_st_dgemm_vendor( :, : ); % Plot one result in an m x n grid of plots, via the subplot() % function. if 1 == 1 plot_l3sup_perf( opsupname, ... data_blissup, ... data_blisconv, ... data_eigen, ... data_open, ... data_vend, vend_str, ... nth, ... 4, 7, ... cfreq, ... dflopspercycle, ... opi, impl ); clear data_mt_*gemm_*; clear data_blissup; clear data_blisconv; clear data_eigen; clear data_open; clear data_vend; end end % Construct the name of the file to which we will output the graph. outfile = sprintf( 'l3sup_%s_%s_%s_nt%d.pdf', oproot, stor_str, arch_str, nth ); % Output the graph to pdf format. %print(gcf, 'gemm_md','-fillpage','-dpdf'); %print(gcf, outfile,'-bestfit','-dpdf'); if impl == 'octave' print(gcf, outfile); else % if impl == 'matlab' print(gcf, outfile,'-bestfit','-dpdf'); end blis-0.9.0/test/sup/old/octave_mt/runthese.m000066400000000000000000000007471422157504600210270ustar00rootroot00000000000000% kabylake plot_panel_trxsh(3.80,16,4,'mt','d','rrr',[ 6 8 10 ],'lds','uaub','../results/kabylake/20200302/mnkt100000_mt4','kbl','MKL','octave'); close; clear all; % haswell plot_panel_trxsh(3.1,16,12,'mt','d','rrr',[ 6 8 10 ],'lds','uaub','../results/haswell/20200302/mnkt100000_mt12','has','MKL','octave'); close; clear all; % epyc plot_panel_trxsh(2.55,8,32,'mt','d','rrr',[ 6 8 10 ],'lds','uaub','../results/epyc/20200302/mnkt100000_mt32','epyc','MKL','octave'); close; clear all; blis-0.9.0/test/sup/old/octave_st/000077500000000000000000000000001422157504600170125ustar00rootroot00000000000000blis-0.9.0/test/sup/old/octave_st/gen_opsupnames.m000066400000000000000000000023541422157504600222170ustar00rootroot00000000000000function [ r_val1, r_val2 ] = gen_opsupnames( ops, stor, smalldims, ldim, pack ) nops = size( ops, 1 ); smallm = smalldims( 1 ); smalln = smalldims( 2 ); smallk = smalldims( 3 ); i = 1; for io = 1:nops op = ops( io, : ); opsupnames( i+0, : ) = sprintf( '%s_%s_m%dnpkp_%s_%s', op, stor, smallm, ldim, pack ); opsupnames( i+1, : ) = sprintf( '%s_%s_mpn%dkp_%s_%s', op, stor, smalln, ldim, pack ); opsupnames( i+2, : ) = sprintf( '%s_%s_mpnpk%d_%s_%s', op, stor, smallk, ldim, pack ); opsupnames( i+3, : ) = sprintf( '%s_%s_mpn%dk%d_%s_%s', op, stor, smalln, smallk, ldim, pack ); opsupnames( i+4, : ) = sprintf( '%s_%s_m%dnpk%d_%s_%s', op, stor, smallm, smallk, ldim, pack ); opsupnames( i+5, : ) = sprintf( '%s_%s_m%dn%dkp_%s_%s', op, stor, smallm, smalln, ldim, pack ); opsupnames( i+6, : ) = sprintf( '%s_%s_mpnpkp_%s_%s', op, stor, ldim, pack ); opnames( i+0, : ) = sprintf( '%s', op ); opnames( i+1, : ) = sprintf( '%s', op ); opnames( i+2, : ) = sprintf( '%s', op ); opnames( i+3, : ) = sprintf( '%s', op ); opnames( i+4, : ) = sprintf( '%s', op ); opnames( i+5, : ) = sprintf( '%s', op ); opnames( i+6, : ) = sprintf( '%s', op ); i = i + 7; end r_val1 = opsupnames; r_val2 = opnames; blis-0.9.0/test/sup/old/octave_st/plot_l3sup_perf.m000066400000000000000000000235751422157504600223240ustar00rootroot00000000000000function r_val = plot_l3sup_perf( opname, ... data_blissup, ... data_blislpab, ... data_eigen, ... data_open, ... data_bfeo, ... data_xsmm, ... data_vend, vend_str, ... nth, ... rows, cols, ... cfreq, ... dfps, ... theid, impl ) %if ... %mod(theid-1,cols) == 2 || ... % ... %mod(theid-1,cols) == 3 || ... % ... %mod(theid-1,cols) == 4 || ... % 0 == 1 ... %theid >= 19 % show_plot = 0; %else show_plot = 1; %end %legend_plot_id = 11; legend_plot_id = 2*cols + 1*5; if 1 ax1 = subplot( rows, cols, theid ); hold( ax1, 'on' ); end % Set line properties. color_blissup = 'k'; lines_blissup = '-'; markr_blissup = ''; color_blislpab = 'k'; lines_blislpab = ':'; markr_blislpab = ''; color_eigen = 'm'; lines_eigen = '-.'; markr_eigen = 'o'; color_open = 'r'; lines_open = '--'; markr_open = 'o'; color_bfeo = 'c'; lines_bfeo = '-'; markr_bfeo = 'o'; color_xsmm = 'g'; lines_xsmm = '-'; markr_xsmm = 'o'; color_vend = 'b'; lines_vend = '-.'; markr_vend = '.'; % Compute the peak performance in terms of the number of double flops % executable per cycle and the clock rate. if opname(1) == 's' || opname(1) == 'c' flopspercycle = dfps * 2; else flopspercycle = dfps; end max_perf_core = (flopspercycle * cfreq) * 1; % Escape underscores in the title. title_opname = strrep( opname, '_', '\_' ); % Print the title to a string. titlename = '%s'; titlename = sprintf( titlename, title_opname ); % Set the legend strings. blissup_legend = sprintf( 'BLIS sup' ); blislpab_legend = sprintf( 'BLIS conv' ); eigen_legend = sprintf( 'Eigen' ); open_legend = sprintf( 'OpenBLAS' ); bfeo_legend = sprintf( 'BLASFEO' ); xsmm_legend = sprintf( 'libxsmm' ); %vend_legend = sprintf( 'MKL' ); %vend_legend = sprintf( 'ARMPL' ); vend_legend = vend_str; % Set axes range values. y_scale = 1.00; x_begin = 0; %x_end is set below. y_begin = 0; y_end = max_perf_core * y_scale; % Set axes names. if nth == 1 yaxisname = 'GFLOPS'; else yaxisname = 'GFLOPS/core'; end %flopscol = 4; flopscol = size( data_blissup, 2 ); msize = 5; if 1 fontsize = 12; else fontsize = 16; end linesize = 0.5; legend_loc = 'southeast'; % -------------------------------------------------------------------- % Automatically detect a column with the increasing problem size. % Then set the maximum x-axis value. for psize_col = 1:3 if data_blissup( 1, psize_col ) ~= data_blissup( 2, psize_col ) break; end end x_axis( :, 1 ) = data_blissup( :, psize_col ); % Compute the number of data points we have in the x-axis. Note that we % only use half the data points for the m = n = k column of graphs. %if mod(theid-1,cols) == 6 % np = size( data_blissup, 1 ) / 2; %else % np = size( data_blissup, 1 ); %end np = size( data_blissup, 1 ); has_xsmm = 1; if data_xsmm( 1, flopscol ) == 0.0 has_xsmm = 0; end % Grab the last x-axis value. x_end = data_blissup( np, psize_col ); %data_peak( 1, 1:2 ) = [ 0 max_perf_core ]; %data_peak( 2, 1:2 ) = [ x_end max_perf_core ]; if show_plot == 1 blissup_ln = line( x_axis( 1:np, 1 ), data_blissup( 1:np, flopscol ) / nth, ... 'Color',color_blissup, 'LineStyle',lines_blissup, ... 'LineWidth',linesize ); blislpab_ln = line( x_axis( 1:np, 1 ), data_blislpab( 1:np, flopscol ) / nth, ... 'Color',color_blislpab, 'LineStyle',lines_blislpab, ... 'LineWidth',linesize ); eigen_ln = line( x_axis( 1:np, 1 ), data_eigen( 1:np, flopscol ) / nth, ... 'Color',color_eigen, 'LineStyle',lines_eigen, ... 'LineWidth',linesize ); open_ln = line( x_axis( 1:np, 1 ), data_open( 1:np, flopscol ) / nth, ... 'Color',color_open, 'LineStyle',lines_open, ... 'LineWidth',linesize ); bfeo_ln = line( x_axis( 1:np, 1 ), data_bfeo( 1:np, flopscol ) / nth, ... 'Color',color_bfeo, 'LineStyle',lines_bfeo, ... 'LineWidth',linesize ); if has_xsmm == 1 xsmm_ln = line( x_axis( 1:np, 1 ), data_xsmm( 1:np, flopscol ) / nth, ... 'Color',color_xsmm, 'LineStyle',lines_xsmm, ... 'LineWidth',linesize ); else xsmm_ln = line( nan, nan, ... 'Color',color_xsmm, 'LineStyle',lines_xsmm, ... 'LineWidth',linesize ); end vend_ln = line( x_axis( 1:np, 1 ), data_vend( 1:np, flopscol ) / nth, ... 'Color',color_vend, 'LineStyle',lines_vend, ... 'LineWidth',linesize ); elseif theid == legend_plot_id blissup_ln = line( nan, nan, ... 'Color',color_blissup, 'LineStyle',lines_blissup, ... 'LineWidth',linesize ); blislpab_ln = line( nan, nan, ... 'Color',color_blislpab, 'LineStyle',lines_blislpab, ... 'LineWidth',linesize ); eigen_ln = line( nan, nan, ... 'Color',color_eigen, 'LineStyle',lines_eigen, ... 'LineWidth',linesize ); open_ln = line( nan, nan, ... 'Color',color_open, 'LineStyle',lines_open, ... 'LineWidth',linesize ); bfeo_ln = line( nan, nan, ... 'Color',color_bfeo, 'LineStyle',lines_bfeo, ... 'LineWidth',linesize ); xsmm_ln = line( nan, nan, ... 'Color',color_xsmm, 'LineStyle',lines_xsmm, ... 'LineWidth',linesize ); vend_ln = line( nan, nan, ... 'Color',color_vend, 'LineStyle',lines_vend, ... 'LineWidth',linesize ); end xlim( ax1, [x_begin x_end] ); ylim( ax1, [y_begin y_end] ); if 10000 <= x_end && x_end < 15000 x_tick2 = x_end - 2000; x_tick1 = x_tick2/2; %xticks( ax1, [ x_tick1 x_tick2 ] ); xticks( ax1, [ 3000 6000 9000 12000 ] ); elseif 6000 <= x_end && x_end < 10000 x_tick2 = x_end - 2000; x_tick1 = x_tick2/2; %xticks( ax1, [ x_tick1 x_tick2 ] ); xticks( ax1, [ 2000 4000 6000 8000 ] ); elseif 4000 <= x_end && x_end < 6000 x_tick2 = x_end - 1000; x_tick1 = x_tick2/2; xticks( ax1, [ x_tick1 x_tick2 ] ); elseif 2000 <= x_end && x_end < 3000 x_tick2 = x_end - 400; x_tick1 = x_tick2/2; xticks( ax1, [ x_tick1 x_tick2 ] ); elseif 500 <= x_end && x_end < 1000 x_tick3 = x_end*(3/4); x_tick2 = x_end*(2/4); x_tick1 = x_end*(1/4); xticks( ax1, [ x_tick1 x_tick2 x_tick3 ] ); end if show_plot == 1 || theid == legend_plot_id if nth == 1 && theid == legend_plot_id if has_xsmm == 1 leg = legend( ... [ ... blissup_ln ... blislpab_ln ... eigen_ln ... open_ln ... bfeo_ln ... xsmm_ln ... vend_ln ... ], ... blissup_legend, ... blislpab_legend, ... eigen_legend, ... open_legend, ... bfeo_legend, ... xsmm_legend, ... vend_legend, ... 'Location', legend_loc ); set( leg,'Box','off' ); set( leg,'Color','none' ); set( leg,'Units','inches' ); if impl == 'octave' set( leg,'FontSize',fontsize ); set( leg,'Position',[15.40 4.75 1.9 1.20] ); % (1,4tl) else set( leg,'FontSize',fontsize-3 ); set( leg,'Position',[18.20 10.20 1.15 0.7 ] ); % (1,4tl) end else leg = legend( ... [ ... blissup_ln ... blislpab_ln ... eigen_ln ... open_ln ... bfeo_ln ... vend_ln ... ], ... blissup_legend, ... blislpab_legend, ... eigen_legend, ... open_legend, ... bfeo_legend, ... vend_legend, ... 'Location', legend_loc ); set( leg,'Box','off' ); set( leg,'Color','none' ); set( leg,'Units','inches' ); if impl == 'octave' set( leg,'FontSize',fontsize ); set( leg,'Position',[15.40 7.65 1.9 1.10] ); % (1,4tl) else set( leg,'FontSize',fontsize-1 ); set( leg,'Position',[18.24 10.15 1.15 0.7] ); % (1,4tl) end end set( leg,'Box','off' ); set( leg,'Color','none' ); set( leg,'Units','inches' ); % xpos ypos %set( leg,'Position',[11.32 6.36 1.15 0.7 ] ); % (1,4tl) elseif nth > 1 && theid == legend_plot_id end end set( ax1,'FontSize',fontsize ); set( ax1,'TitleFontSizeMultiplier',1.0 ); % default is 1.1. box( ax1, 'on' ); titl = title( titlename ); set( titl, 'FontWeight', 'normal' ); % default font style is now 'bold'. % The default is to align the plot title across whole figure, not the box. % This is a hack to nudge the title back to the center of the box. if impl == 'octave' tpos = get( titl, 'Position' ); % For some reason, the titles in the graphs in the last column start % off in a different relative position than the graphs in the other % columns. Here, we manually account for that. if mod(theid-1,cols) == 6 tpos(1) = tpos(1) + -10; else tpos(1) = tpos(1) + -40; end set( titl, 'Position', tpos ); set( titl, 'FontSize', fontsize ); else % impl == 'matlab' tpos = get( titl, 'Position' ); tpos(1) = tpos(1) + 90; set( titl, 'Position', tpos ); end if theid > (rows-1)*cols %xlab = xlabel( ax1,xaxisname ); %tpos = get( xlab, 'Position' ) %tpos(2) = tpos(2) + 10; %set( xlab, 'Position', tpos ); if theid == rows*cols - 6 xlab = xlabel( ax1, 'm = 6; n = k' ); elseif theid == rows*cols - 5 xlab = xlabel( ax1, 'n = 8; m = k' ); elseif theid == rows*cols - 4 xlab = xlabel( ax1, 'k = 4; m = n' ); elseif theid == rows*cols - 3 xlab = xlabel( ax1, 'm; n = 8, k = 4' ); elseif theid == rows*cols - 2 xlab = xlabel( ax1, 'n; m = 6, k = 4' ); elseif theid == rows*cols - 1 xlab = xlabel( ax1, 'k; m = 6, n = 8' ); elseif theid == rows*cols - 0 xlab = xlabel( ax1, 'm = n = k' ); end end if mod(theid-1,cols) == 0 ylab = ylabel( ax1,yaxisname ); end r_val = 0; blis-0.9.0/test/sup/old/octave_st/plot_panel_trxsh.m000066400000000000000000000126771422157504600225720ustar00rootroot00000000000000function r_val = plot_panel_trxsh ... ( ... cfreq, ... dflopspercycle, ... nth, ... thr_str, ... dt_ch, ... stor_str, ... smalldims, ... ldim_str, ... pack_str, ... dirpath, ... arch_str, ... vend_str, ... impl ... ) %cfreq = 1.8; %dflopspercycle = 32; % Create filename "templates" for the files that contain the performance % results. filetemp_blissup = '%s/output_%s_%s_blissup.m'; filetemp_blisconv = '%s/output_%s_%s_blisconv.m'; filetemp_eigen = '%s/output_%s_%s_eigen.m'; filetemp_open = '%s/output_%s_%s_openblas.m'; filetemp_bfeo = '%s/output_%s_%s_blasfeo.m'; filetemp_xsmm = '%s/output_%s_%s_libxsmm.m'; filetemp_vend = '%s/output_%s_%s_vendor.m'; % Create a variable name "template" for the variables contained in the % files outlined above. vartemp = 'data_%s_%s_%s( :, : )'; % Define the datatypes and operations we will be plotting. oproot = sprintf( '%cgemm', dt_ch ); ops( 1, : ) = sprintf( '%s_nn', oproot ); ops( 2, : ) = sprintf( '%s_nt', oproot ); ops( 3, : ) = sprintf( '%s_tn', oproot ); ops( 4, : ) = sprintf( '%s_tt', oproot ); % Generate datatype-specific operation names from the set of operations % and datatypes. [ opsupnames, opnames ] = gen_opsupnames( ops, stor_str, smalldims, ldim_str, pack_str ); n_opsupnames = size( opsupnames, 1 ); %opsupnames %opnames %return if 1 == 1 %fig = figure('Position', [100, 100, 2400, 1500]); fig = figure('Position', [100, 100, 2400, 1200]); orient( fig, 'portrait' ); set(gcf,'PaperUnits', 'inches'); if impl == 'matlab' set(gcf,'PaperSize', [11.5 20.4]); set(gcf,'PaperPosition', [0 0 11.5 20.4]); set(gcf,'PaperPositionMode','manual'); else % impl == 'octave' % octave 4.x set(gcf,'PaperSize', [12 22.0]); set(gcf,'PaperPositionMode','auto'); end set(gcf,'PaperOrientation','landscape'); end % Iterate over the list of datatype-specific operation names. for opi = 1:n_opsupnames %for opi = 1:1 % Grab the current datatype combination. opsupname = opsupnames( opi, : ); opname = opnames( opi, : ); str = sprintf( 'Plotting %2d: %s', opi, opsupname ); disp(str); % Construct filenames for the data files from templates. file_blissup = sprintf( filetemp_blissup, dirpath, thr_str, opsupname ); file_blisconv = sprintf( filetemp_blisconv, dirpath, thr_str, opsupname ); file_eigen = sprintf( filetemp_eigen, dirpath, thr_str, opsupname ); file_open = sprintf( filetemp_open, dirpath, thr_str, opsupname ); file_bfeo = sprintf( filetemp_bfeo, dirpath, thr_str, opsupname ); file_vend = sprintf( filetemp_vend, dirpath, thr_str, opsupname ); % Load the data files. %str = sprintf( ' Loading %s', file_blissup ); disp(str); run( file_blissup ) run( file_blisconv ) run( file_eigen ) run( file_open ) run( file_bfeo ) run( file_vend ) % Construct variable names for the variables in the data files. var_blissup = sprintf( vartemp, thr_str, opname, 'blissup' ); var_blisconv = sprintf( vartemp, thr_str, opname, 'blisconv' ); var_eigen = sprintf( vartemp, thr_str, opname, 'eigen' ); var_open = sprintf( vartemp, thr_str, opname, 'openblas' ); var_bfeo = sprintf( vartemp, thr_str, opname, 'blasfeo' ); var_vend = sprintf( vartemp, thr_str, opname, 'vendor' ); % Use eval() to instantiate the variable names constructed above, % copying each to a simplified name. data_blissup = eval( var_blissup ); % e.g. data_st_dgemm_blissup( :, : ); data_blisconv = eval( var_blisconv ); % e.g. data_st_dgemm_blisconv( :, : ); data_eigen = eval( var_eigen ); % e.g. data_st_dgemm_eigen( :, : ); data_open = eval( var_open ); % e.g. data_st_dgemm_openblas( :, : ); data_bfeo = eval( var_bfeo ); % e.g. data_st_dgemm_blasfeo( :, : ); data_vend = eval( var_vend ); % e.g. data_st_dgemm_vendor( :, : ); if stor_str == 'ccc' % Only read xsmm data for the column storage case, since that's the % only format that libxsmm supports. file_xsmm = sprintf( filetemp_xsmm, dirpath, thr_str, opsupname ); run( file_xsmm ) var_xsmm = sprintf( vartemp, thr_str, opname, 'libxsmm' ); data_xsmm = eval( var_xsmm ); % e.g. data_st_dgemm_libxsmm( :, : ); else % Set the data variable to zeros using the same dimensions as the other % variables. data_xsmm = zeros( size( data_blissup, 1 ), ... size( data_blissup, 2 ) ); end % Plot one result in an m x n grid of plots, via the subplot() % function. if 1 == 1 plot_l3sup_perf( opsupname, ... data_blissup, ... data_blisconv, ... data_eigen, ... data_open, ... data_bfeo, ... data_xsmm, ... data_vend, vend_str, ... nth, ... 4, 7, ... cfreq, ... dflopspercycle, ... opi, impl ); clear data_st_*gemm_*; clear data_blissup; clear data_blisconv; clear data_eigen; clear data_open; clear data_bfeo; clear data_xsmm; clear data_vend; end end % Construct the name of the file to which we will output the graph. outfile = sprintf( 'l3sup_%s_%s_%s_nt%d.pdf', oproot, stor_str, arch_str, nth ); % Output the graph to pdf format. %print(gcf, 'gemm_md','-fillpage','-dpdf'); %print(gcf, outfile,'-bestfit','-dpdf'); if impl == 'octave' print(gcf, outfile); else % if impl == 'matlab' print(gcf, outfile,'-bestfit','-dpdf'); end blis-0.9.0/test/sup/old/octave_st/runthese.m000066400000000000000000000007361422157504600210330ustar00rootroot00000000000000% kabylake plot_panel_trxsh(3.80,16,1,'st','d','rrr',[ 6 8 4 ],'lds','uaub','../results/kabylake/20200302/mnkt100000_st','kbl','MKL','octave'); close; clear all; % haswell plot_panel_trxsh(3.5,16,1,'st','d','rrr',[ 6 8 4 ],'lds','uaub','../results/haswell/20200302/mnkt100000_st','has','MKL','octave'); close; clear all; % epyc plot_panel_trxsh(3.00, 8,1,'st','d','rrr',[ 6 8 4 ],'lds','uaub','../results/epyc/20200302/mnkt100000_st','epyc','MKL','octave'); close; clear all; blis-0.9.0/test/sup/old/supmt/000077500000000000000000000000001422157504600161735ustar00rootroot00000000000000blis-0.9.0/test/sup/old/supmt/Makefile000066400000000000000000000557311422157504600176460ustar00rootroot00000000000000#!/bin/bash # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2014, The University of Texas at Austin # Copyright (C) 2019, Advanced Micro Devices, Inc. # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # # # Makefile # # Field G. Van Zee # # Makefile for standalone BLIS test drivers. # # # --- Makefile PHONY target definitions ---------------------------------------- # .PHONY: all \ st mt \ blissup-st blislpab-st eigen-st openblas-st vendor-st blasfeo-st libxsmm-st \ blissup-mt blislpab-mt eigen-mt openblas-mt vendor-mt \ clean cleanx # # --- Determine makefile fragment location ------------------------------------- # # Comments: # - DIST_PATH is assumed to not exist if BLIS_INSTALL_PATH is given. # - We must use recursively expanded assignment for LIB_PATH and INC_PATH in # the second case because CONFIG_NAME is not yet set. ifneq ($(strip $(BLIS_INSTALL_PATH)),) LIB_PATH := $(BLIS_INSTALL_PATH)/lib INC_PATH := $(BLIS_INSTALL_PATH)/include/blis SHARE_PATH := $(BLIS_INSTALL_PATH)/share/blis else DIST_PATH := ../.. LIB_PATH = ../../lib/$(CONFIG_NAME) INC_PATH = ../../include/$(CONFIG_NAME) SHARE_PATH := ../.. endif # # --- Include common makefile definitions -------------------------------------- # # Include the common makefile fragment. -include $(SHARE_PATH)/common.mk # # --- BLAS and LAPACK implementations ------------------------------------------ # # BLIS library and header path. This is simply wherever it was installed. #BLIS_LIB_PATH := $(INSTALL_PREFIX)/lib #BLIS_INC_PATH := $(INSTALL_PREFIX)/include/blis # BLIS library. #BLIS_LIB := $(BLIS_LIB_PATH)/libblis.a # BLAS library path(s). This is where the BLAS libraries reside. HOME_LIB_PATH := $(HOME)/flame/lib MKL_LIB_PATH := $(HOME)/intel/mkl/lib/intel64 # netlib BLAS NETLIB_LIB := $(HOME_LIB_PATH)/libblas.a # OpenBLAS OPENBLAS_LIB := $(HOME_LIB_PATH)/libopenblas.a OPENBLASP_LIB := $(HOME_LIB_PATH)/libopenblasp.a # BLASFEO BLASFEO_LIB := $(HOME_LIB_PATH)/libblasfeo.a # libxsmm LIBXSMM_LIB := $(HOME_LIB_PATH)/libxsmm.a -ldl \ $(NETLIB_LIB) -lgfortran # ATLAS ATLAS_LIB := $(HOME_LIB_PATH)/libf77blas.a \ $(HOME_LIB_PATH)/libatlas.a # Eigen EIGEN_INC := $(HOME)/flame/eigen/include/eigen3 EIGEN_LIB := $(HOME_LIB_PATH)/libeigen_blas_static.a EIGENP_LIB := $(EIGEN_LIB) # MKL MKL_LIB := -L$(MKL_LIB_PATH) \ -lmkl_intel_lp64 \ -lmkl_core \ -lmkl_sequential \ -lpthread -lm -ldl MKLP_LIB := -L$(MKL_LIB_PATH) \ -lmkl_intel_lp64 \ -lmkl_core \ -lmkl_gnu_thread \ -lpthread -lm -ldl -fopenmp #-L$(ICC_LIB_PATH) \ #-lgomp VENDOR_LIB := $(MKL_LIB) VENDORP_LIB := $(MKLP_LIB) # # --- Problem size definitions ------------------------------------------------- # # The problem size range specification is done separately for single-threaded # and multithreaded execution. Within each threadedness scenario, we allow for # separate range specifications for cases with: # - 3L: three large/variable dimensions and no small/constant dimensions # - 2L: two large/variable dimensions and one small/constant dimension # - 1L: one large/variable dimension and two small/constant dimensions # -- Single-threaded -- PS_BEGIN_3L := 2 PS_MAX_3L := 400 PS_INC_3L := 2 PS_BEGIN_2L := 4 PS_MAX_2L := 800 PS_INC_2L := 4 PS_BEGIN_1L := 32 PS_MAX_1L := 6400 PS_INC_1L := 32 # -- Multithreaded -- P1_BEGIN_3L := 4 P1_MAX_3L := 800 P1_INC_3L := 4 P1_BEGIN_2L := 8 P1_MAX_2L := 1600 P1_INC_2L := 8 P1_BEGIN_1L := 64 P1_MAX_1L := 12800 P1_INC_1L := 64 # # --- General build definitions ------------------------------------------------ # TEST_SRC_PATH := . TEST_OBJ_PATH := . # Gather all local object files. TEST_OBJS := $(sort $(patsubst $(TEST_SRC_PATH)/%.c, \ $(TEST_OBJ_PATH)/%.o, \ $(wildcard $(TEST_SRC_PATH)/*.c))) # Override the value of CINCFLAGS so that the value of CFLAGS returned by # get-frame-cflags-for() is not cluttered up with include paths needed only # while building BLIS. CINCFLAGS := -I$(INC_PATH) # Use the "framework" CFLAGS for the configuration family. CFLAGS := $(call get-user-cflags-for,$(CONFIG_NAME)) # Add local header paths to CFLAGS. CFLAGS += -I$(TEST_SRC_PATH) # Locate the libblis library to which we will link. LIBBLIS_LINK := $(LIB_PATH)/$(LIBBLIS_L) # Define a set of CFLAGS for use with C++ and Eigen. CXXFLAGS := $(subst -std=c99,-std=c++11,$(CFLAGS)) CXXFLAGS += -I$(EIGEN_INC) # Create a copy of CXXFLAGS without -fopenmp in order to disable multithreading. CXXFLAGS_ST := -march=native $(subst -fopenmp,,$(CXXFLAGS)) CXXFLAGS_MT := -march=native $(CXXFLAGS) # Single or multithreaded string. STR_ST := -DTHR_STR=\"st\" STR_MT := -DTHR_STR=\"mt\" # Number of trials per problem size. N_TRIALS := -DN_TRIALS=3 # Problem size specification. PDEF_ST_1L := -DP_BEGIN=$(PS_BEGIN_1L) -DP_MAX=$(PS_MAX_1L) -DP_INC=$(PS_INC_1L) PDEF_ST_2L := -DP_BEGIN=$(PS_BEGIN_2L) -DP_MAX=$(PS_MAX_2L) -DP_INC=$(PS_INC_2L) PDEF_ST_3L := -DP_BEGIN=$(PS_BEGIN_3L) -DP_MAX=$(PS_MAX_3L) -DP_INC=$(PS_INC_3L) PDEF_MT_1L := -DP_BEGIN=$(P1_BEGIN_1L) -DP_MAX=$(P1_MAX_1L) -DP_INC=$(P1_INC_1L) PDEF_MT_2L := -DP_BEGIN=$(P1_BEGIN_2L) -DP_MAX=$(P1_MAX_2L) -DP_INC=$(P1_INC_2L) PDEF_MT_3L := -DP_BEGIN=$(P1_BEGIN_3L) -DP_MAX=$(P1_MAX_3L) -DP_INC=$(P1_INC_3L) ifeq ($(E),1) ERRCHK := -DERROR_CHECK else ERRCHK := -DNO_ERROR_CHECK endif # Enumerate possible datatypes and computation precisions. #dts := s d c z DTS := d TRANS := n_n \ n_t \ t_n \ t_t # While BLIS supports all combinations of row and column storage for matrices # C, A, and B, the alternatives mostly only support CBLAS APIs, which inherently # support only "all row-storage" or "all column-storage". Thus, we disable the # building of those other drivers so that compilation/linking completes sooner. #STORS := r_r_r \ # r_r_c \ # r_c_r \ # r_c_c \ # c_r_r \ # c_r_c \ # c_c_r \ # c_c_c STORS := r_r_r \ c_c_c SHAPES := l_l_s \ l_s_l \ s_l_l \ s_s_l \ s_l_s \ l_s_s \ l_l_l # Define the small/constant m, n, and k dimensions for single core and multicore # experiments. SMS_ST := 6 SNS_ST := 8 SKS_ST := 4 SMS_MT := 6 SNS_MT := 8 SKS_MT := 10 # # --- Function definitions ----------------------------------------------------- # # A function to strip the underscores from a list of strings. stripu = $(subst _,,$(1)) # Various functions that help us construct the datatype combinations and then # extract the needed datatype strings and C preprocessor define flags. get-1of2 = $(word 1,$(subst _, ,$(1))) get-2of2 = $(word 2,$(subst _, ,$(1))) get-1of3 = $(word 1,$(subst _, ,$(1))) get-2of3 = $(word 2,$(subst _, ,$(1))) get-3of3 = $(word 3,$(subst _, ,$(1))) # A function to return the correct PDEFS_ST variable given the shape string. get-pdefs = $(strip $(subst l_l_l,$(PDEF_MT_3L), \ $(subst l_l_s,$(PDEF_MT_2L), \ $(subst l_s_l,$(PDEF_MT_2L), \ $(subst s_l_l,$(PDEF_MT_2L), \ $(subst s_s_l,$(PDEF_MT_1L), \ $(subst s_l_s,$(PDEF_MT_1L), \ $(subst l_s_s,$(PDEF_MT_1L),$(1))))))))) # Datatype defs. get-dt-cpp = $(strip \ $(if $(findstring s,$(1)),-DDT=BLIS_FLOAT -DIS_FLOAT,\ $(if $(findstring d,$(1)),-DDT=BLIS_DOUBLE -DIS_DOUBLE,\ $(if $(findstring c,$(1)),-DDT=BLIS_SCOMPLEX -DIS_SCOMPLEX,\ -DDT=BLIS_DCOMPLEX -DIS_DCOMPLEX)))) # Transpose defs. get-tra-defs-a = $(strip $(subst n,-DTRANSA=BLIS_NO_TRANSPOSE -DA_NOTRANS, \ $(subst t,-DTRANSA=BLIS_TRANSPOSE -DA_TRANS,$(call get-1of2,$(1))))) get-tra-defs-b = $(strip $(subst n,-DTRANSB=BLIS_NO_TRANSPOSE -DB_NOTRANS, \ $(subst t,-DTRANSB=BLIS_TRANSPOSE -DB_TRANS,$(call get-2of2,$(1))))) get-tra-defs = $(call get-tra-defs-a,$(1)) $(call get-tra-defs-b,$(1)) # Storage defs. get-sto-uch-a = $(strip $(subst r,R, \ $(subst c,C,$(call get-1of3,$(1))))) get-sto-uch-b = $(strip $(subst r,R, \ $(subst c,C,$(call get-2of3,$(1))))) get-sto-uch-c = $(strip $(subst r,R, \ $(subst c,C,$(call get-3of3,$(1))))) get-sto-defs = $(strip \ -DSTOR3=BLIS_$(call get-sto-uch-a,$(1))$(call get-sto-uch-b,$(1))$(call get-sto-uch-c,$(1)) \ -DA_STOR_$(call get-sto-uch-a,$(1)) \ -DB_STOR_$(call get-sto-uch-b,$(1)) \ -DC_STOR_$(call get-sto-uch-c,$(1))) # Dimension defs. get-shape-defs-cm = $(if $(findstring l,$(1)),-DM_DIM=-1,-DM_DIM=$(2)) get-shape-defs-cn = $(if $(findstring l,$(1)),-DN_DIM=-1,-DN_DIM=$(2)) get-shape-defs-ck = $(if $(findstring l,$(1)),-DK_DIM=-1,-DK_DIM=$(2)) get-shape-defs-m = $(call get-shape-defs-cm,$(call get-1of3,$(1)),$(2)) get-shape-defs-n = $(call get-shape-defs-cn,$(call get-2of3,$(1)),$(2)) get-shape-defs-k = $(call get-shape-defs-ck,$(call get-3of3,$(1)),$(2)) # arguments: 1: shape (w/ underscores) 2: smallm 3: smalln 4: smallk get-shape-defs = $(strip $(call get-shape-defs-m,$(1),$(2)) \ $(call get-shape-defs-n,$(1),$(3)) \ $(call get-shape-defs-k,$(1),$(4))) #$(error l_l_s 6 8 4 = $(call get-shape-defs,l_l_s,6,8,4)) # Shape-dimension string. get-shape-str-ch = $(if $(findstring l,$(1)),p,$(2)) get-shape-str-m = $(call get-shape-str-ch,$(call get-1of3,$(1)),$(2)) get-shape-str-n = $(call get-shape-str-ch,$(call get-2of3,$(1)),$(2)) get-shape-str-k = $(call get-shape-str-ch,$(call get-3of3,$(1)),$(2)) # arguments: 1: shape (w/ underscores) 2: smallm 3: smalln 4: smallk get-shape-dim-str = m$(call get-shape-str-m,$(1),$(2))n$(call get-shape-str-n,$(1),$(3))k$(call get-shape-str-k,$(1),$(4)) # Implementation defs. # Define a function to return the appropriate -DSTR= and -D[BLIS|BLAS] flags. get-imp-defs = $(strip $(subst blissup,-DSTR=\"$(1)\" -DBLIS -DSUP, \ $(subst blislpab,-DSTR=\"$(1)\" -DBLIS, \ $(subst eigen,-DSTR=\"$(1)\" -DEIGEN, \ $(subst openblas,-DSTR=\"$(1)\" -DCBLAS, \ $(subst blasfeo,-DSTR=\"$(1)\" -DCBLAS, \ $(subst libxsmm,-DSTR=\"$(1)\" -DBLAS -DXSMM, \ $(subst vendor,-DSTR=\"$(1)\" -DCBLAS,$(1))))))))) TRANS0 = $(call stripu,$(TRANS)) STORS0 = $(call stripu,$(STORS)) # Limit BLAS and Eigen to only using all row-stored, or all column-stored matrices. # Also, limit libxsmm to using all column-stored matrices since it does not offer # CBLAS interfaces. BSTORS0 = rrr ccc ESTORS0 = rrr ccc XSTORS0 = ccc # # --- Object and binary file definitons ---------------------------------------- # # -- Single-threaded -- get-st-objs = $(foreach dt,$(1),$(foreach tr,$(2),$(foreach st,$(3),$(foreach sh,$(4),$(foreach sm,$(5),$(foreach sn,$(6),$(foreach sk,$(7),test_$(dt)gemm_$(tr)_$(st)_$(call get-shape-dim-str,$(sh),$(sm),$(sn),$(sk))_$(8)_st.o))))))) # Build a list of object files and binaries for each single-threaded # implementation using the get-st-objs() function defined above. BLISSUP_ST_OBJS := $(call get-st-objs,$(DTS),$(TRANS0),$(STORS0),$(SHAPES),$(SMS_ST),$(SNS_ST),$(SKS_ST),blissup) BLISSUP_ST_BINS := $(patsubst %.o,%.x,$(BLISSUP_ST_OBJS)) BLISLPAB_ST_OBJS := $(call get-st-objs,$(DTS),$(TRANS0),$(STORS0),$(SHAPES),$(SMS_ST),$(SNS_ST),$(SKS_ST),blislpab) BLISLPAB_ST_BINS := $(patsubst %.o,%.x,$(BLISLPAB_ST_OBJS)) EIGEN_ST_OBJS := $(call get-st-objs,$(DTS),$(TRANS0),$(ESTORS0),$(SHAPES),$(SMS_ST),$(SNS_ST),$(SKS_ST),eigen) EIGEN_ST_BINS := $(patsubst %.o,%.x,$(EIGEN_ST_OBJS)) OPENBLAS_ST_OBJS := $(call get-st-objs,$(DTS),$(TRANS0),$(BSTORS0),$(SHAPES),$(SMS_ST),$(SNS_ST),$(SKS_ST),openblas) OPENBLAS_ST_BINS := $(patsubst %.o,%.x,$(OPENBLAS_ST_OBJS)) BLASFEO_ST_OBJS := $(call get-st-objs,$(DTS),$(TRANS0),$(BSTORS0),$(SHAPES),$(SMS_ST),$(SNS_ST),$(SKS_ST),blasfeo) BLASFEO_ST_BINS := $(patsubst %.o,%.x,$(BLASFEO_ST_OBJS)) LIBXSMM_ST_OBJS := $(call get-st-objs,$(DTS),$(TRANS0),$(XSTORS0),$(SHAPES),$(SMS_ST),$(SNS_ST),$(SKS_ST),libxsmm) LIBXSMM_ST_BINS := $(patsubst %.o,%.x,$(LIBXSMM_ST_OBJS)) VENDOR_ST_OBJS := $(call get-st-objs,$(DTS),$(TRANS0),$(BSTORS0),$(SHAPES),$(SMS_ST),$(SNS_ST),$(SKS_ST),vendor) VENDOR_ST_BINS := $(patsubst %.o,%.x,$(VENDOR_ST_OBJS)) # Mark the object files as intermediate so that make will remove them # automatically after building the binaries on which they depend. .INTERMEDIATE: $(BLISSUP_ST_OBJS) \ $(BLISLPAB_ST_OBJS) \ $(EIGEN_ST_OBJS) \ $(OPENBLAS_ST_OBJS) \ $(BLASFEO_ST_OBJS) \ $(LIBXSMM_ST_OBJS) \ $(VENDOR_ST_OBJS) # -- Multithreaded -- get-mt-objs = $(foreach dt,$(1),$(foreach tr,$(2),$(foreach st,$(3),$(foreach sh,$(4),$(foreach sm,$(5),$(foreach sn,$(6),$(foreach sk,$(7),test_$(dt)gemm_$(tr)_$(st)_$(call get-shape-dim-str,$(sh),$(sm),$(sn),$(sk))_$(8)_mt.o))))))) # Build a list of object files and binaries for each multithreaded # implementation using the get-st-objs() function defined above. BLISSUP_MT_OBJS := $(call get-mt-objs,$(DTS),$(TRANS0),$(STORS0),$(SHAPES),$(SMS_MT),$(SNS_MT),$(SKS_MT),blissup) BLISSUP_MT_BINS := $(patsubst %.o,%.x,$(BLISSUP_MT_OBJS)) BLISLPAB_MT_OBJS := $(call get-mt-objs,$(DTS),$(TRANS0),$(STORS0),$(SHAPES),$(SMS_MT),$(SNS_MT),$(SKS_MT),blislpab) BLISLPAB_MT_BINS := $(patsubst %.o,%.x,$(BLISLPAB_MT_OBJS)) EIGEN_MT_OBJS := $(call get-mt-objs,$(DTS),$(TRANS0),$(ESTORS0),$(SHAPES),$(SMS_MT),$(SNS_MT),$(SKS_MT),eigen) EIGEN_MT_BINS := $(patsubst %.o,%.x,$(EIGEN_MT_OBJS)) OPENBLAS_MT_OBJS := $(call get-mt-objs,$(DTS),$(TRANS0),$(BSTORS0),$(SHAPES),$(SMS_MT),$(SNS_MT),$(SKS_MT),openblas) OPENBLAS_MT_BINS := $(patsubst %.o,%.x,$(OPENBLAS_MT_OBJS)) VENDOR_MT_OBJS := $(call get-mt-objs,$(DTS),$(TRANS0),$(BSTORS0),$(SHAPES),$(SMS_MT),$(SNS_MT),$(SKS_MT),vendor) VENDOR_MT_BINS := $(patsubst %.o,%.x,$(VENDOR_MT_OBJS)) #$(error "objs = $(EIGEN_ST_BINS)" ) # Mark the object files as intermediate so that make will remove them # automatically after building the binaries on which they depend. .INTERMEDIATE: $(BLISSUP_MT_OBJS) \ $(BLISLPAB_MT_OBJS) \ $(EIGEN_MT_OBJS) \ $(OPENBLAS_MT_OBJS) \ $(VENDOR_MT_OBJS) # # --- High-level targets/rules ------------------------------------------------- # all: st #blis: blissup-st blislpab-st #blissup: blissup-st #blislpab: blislpab-st #eigen: eigen-st #openblas: openblas-st #blasfeo: blasfeo-st #libxsmm: libxsmm-st #vendor: vendor-st # -- Single-threaded -- st: blissup-st blislpab-st \ eigen-st openblas-st blasfeo-st libxsmm-st vendor-st blissup-st: $(BLISSUP_ST_BINS) blislpab-st: $(BLISLPAB_ST_BINS) eigen-st: $(EIGEN_ST_BINS) openblas-st: $(OPENBLAS_ST_BINS) blasfeo-st: $(BLASFEO_ST_BINS) libxsmm-st: $(LIBXSMM_ST_BINS) vendor-st: $(VENDOR_ST_BINS) # -- Multithreaded -- mt: blissup-mt blislpab-mt \ eigen-mt openblas-mt vendor-mt blissup-mt: $(BLISSUP_MT_BINS) blislpab-mt: $(BLISLPAB_MT_BINS) eigen-mt: $(EIGEN_MT_BINS) openblas-mt: $(OPENBLAS_MT_BINS) vendor-mt: $(VENDOR_MT_BINS) # --- Object file rules -------------------------------------------------------- # Define the implementations for which we will instantiate compilation rules. BIMPLS_ST := blissup blislpab openblas blasfeo libxsmm vendor BIMPLS_MT := blissup blislpab openblas vendor EIMPLS := eigen # -- Single-threaded BLAS -- # 1 2 3 4 567 8 # test_dgemm_nn_rrr_mpn6kp_blissup_st.x # Define the function that will be used to instantiate compilation rules # for the various single-threaded implementations. define make-st-rule test_$(1)gemm_$(call stripu,$(2))_$(call stripu,$(3))_$(call get-shape-dim-str,$(4),$(5),$(6),$(7))_$(8)_st.o: test_gemm.c Makefile $(CC) $(CFLAGS) $(ERRCHK) $(N_TRIALS) $(call get-pdefs,$(4)) $(call get-dt-cpp,$(1)) $(call get-tra-defs,$(2)) $(call get-sto-defs,$(3)) $(call get-shape-defs,$(4),$(5),$(6),$(7)) $(call get-imp-defs,$(8)) $(STR_ST) -c $$< -o $$@ endef # Instantiate the rule function make-st-rule() for each BLIS/BLAS/CBLAS # implementation. $(foreach dt,$(DTS), \ $(foreach tr,$(TRANS), \ $(foreach st,$(STORS), \ $(foreach sh,$(SHAPES), \ $(foreach sm,$(SMS_ST), \ $(foreach sn,$(SNS_ST), \ $(foreach sk,$(SKS_ST), \ $(foreach impl,$(BIMPLS_ST), \ $(eval $(call make-st-rule,$(dt),$(tr),$(st),$(sh),$(sm),$(sn),$(sk),$(impl))))))))))) # -- Multithreaded BLAS -- # Define the function that will be used to instantiate compilation rules # for the various multithreaded implementations. define make-mt-rule test_$(1)gemm_$(call stripu,$(2))_$(call stripu,$(3))_$(call get-shape-dim-str,$(4),$(5),$(6),$(7))_$(8)_mt.o: test_gemm.c Makefile $(CC) $(CFLAGS) $(ERRCHK) $(N_TRIALS) $(call get-pdefs,$(4)) $(call get-dt-cpp,$(1)) $(call get-tra-defs,$(2)) $(call get-sto-defs,$(3)) $(call get-shape-defs,$(4),$(5),$(6),$(7)) $(call get-imp-defs,$(8)) $(STR_MT) -c $$< -o $$@ endef # Instantiate the rule function make-mt-rule() for each BLIS/BLAS/CBLAS # implementation. $(foreach dt,$(DTS), \ $(foreach tr,$(TRANS), \ $(foreach st,$(STORS), \ $(foreach sh,$(SHAPES), \ $(foreach sm,$(SMS_MT), \ $(foreach sn,$(SNS_MT), \ $(foreach sk,$(SKS_MT), \ $(foreach impl,$(BIMPLS_MT), \ $(eval $(call make-mt-rule,$(dt),$(tr),$(st),$(sh),$(sm),$(sn),$(sk),$(impl))))))))))) # -- Single-threaded Eigen -- # Define the function that will be used to instantiate compilation rules # for the single-threaded Eigen implementation. define make-eigst-rule test_$(1)gemm_$(call stripu,$(2))_$(call stripu,$(3))_$(call get-shape-dim-str,$(4),$(5),$(6),$(7))_$(8)_st.o: test_gemm.c Makefile $(CXX) $(CXXFLAGS_ST) $(ERRCHK) $(N_TRIALS) $(call get-pdefs,$(4)) $(call get-dt-cpp,$(1)) $(call get-tra-defs,$(2)) $(call get-sto-defs,$(3)) $(call get-shape-defs,$(4),$(5),$(6),$(7)) $(call get-imp-defs,$(8)) $(STR_ST) -c $$< -o $$@ endef # Instantiate the rule function make-st-rule() for each Eigen implementation. $(foreach dt,$(DTS), \ $(foreach tr,$(TRANS), \ $(foreach st,$(STORS), \ $(foreach sh,$(SHAPES), \ $(foreach sm,$(SMS_ST), \ $(foreach sn,$(SNS_ST), \ $(foreach sk,$(SKS_ST), \ $(foreach impl,$(EIMPLS), \ $(eval $(call make-eigst-rule,$(dt),$(tr),$(st),$(sh),$(sm),$(sn),$(sk),$(impl))))))))))) # -- Multithreaded Eigen -- # Define the function that will be used to instantiate compilation rules # for the multithreaded Eigen implementation. define make-eigmt-rule test_$(1)gemm_$(call stripu,$(2))_$(call stripu,$(3))_$(call get-shape-dim-str,$(4),$(5),$(6),$(7))_$(8)_mt.o: test_gemm.c Makefile $(CXX) $(CXXFLAGS_MT) $(ERRCHK) $(N_TRIALS) $(call get-pdefs,$(4)) $(call get-dt-cpp,$(1)) $(call get-tra-defs,$(2)) $(call get-sto-defs,$(3)) $(call get-shape-defs,$(4),$(5),$(6),$(7)) $(call get-imp-defs,$(8)) $(STR_MT) -c $$< -o $$@ endef # Instantiate the rule function make-st-rule() for each Eigen implementation. $(foreach dt,$(DTS), \ $(foreach tr,$(TRANS), \ $(foreach st,$(STORS), \ $(foreach sh,$(SHAPES), \ $(foreach sm,$(SMS_MT), \ $(foreach sn,$(SNS_MT), \ $(foreach sk,$(SKS_MT), \ $(foreach impl,$(EIMPLS), \ $(eval $(call make-eigmt-rule,$(dt),$(tr),$(st),$(sh),$(sm),$(sn),$(sk),$(impl))))))))))) # --- Executable file rules ---------------------------------------------------- # NOTE: For the BLAS test drivers, we place the BLAS libraries before BLIS # on the link command line in case BLIS was configured with the BLAS # compatibility layer. This prevents BLIS from inadvertently getting called # for the BLAS routines we are trying to test with. # -- Single-threaded -- test_%_blissup_st.x: test_%_blissup_st.o $(LIBBLIS_LINK) $(CC) $(strip $< $(LIBBLIS_LINK) $(LDFLAGS) -o $@) test_%_blislpab_st.x: test_%_blislpab_st.o $(LIBBLIS_LINK) $(CC) $(strip $< $(LIBBLIS_LINK) $(LDFLAGS) -o $@) test_%_eigen_st.x: test_%_eigen_st.o $(LIBBLIS_LINK) $(CXX) $(strip $< $(LIBBLIS_LINK) $(LDFLAGS) -o $@) test_%_openblas_st.x: test_%_openblas_st.o $(LIBBLIS_LINK) $(CC) $(strip $< $(OPENBLAS_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $@) test_%_blasfeo_st.x: test_%_blasfeo_st.o $(LIBBLIS_LINK) $(CC) $(strip $< $(BLASFEO_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $@) test_%_libxsmm_st.x: test_%_libxsmm_st.o $(LIBBLIS_LINK) $(CC) $(strip $< $(LIBXSMM_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $@) test_%_vendor_st.x: test_%_vendor_st.o $(LIBBLIS_LINK) $(CC) $(strip $< $(VENDOR_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $@) # -- Multithreaded -- test_%_blissup_mt.x: test_%_blissup_mt.o $(LIBBLIS_LINK) $(CC) $(strip $< $(LIBBLIS_LINK) $(LDFLAGS) -o $@) test_%_blislpab_mt.x: test_%_blislpab_mt.o $(LIBBLIS_LINK) $(CC) $(strip $< $(LIBBLIS_LINK) $(LDFLAGS) -o $@) test_%_eigen_mt.x: test_%_eigen_mt.o $(LIBBLIS_LINK) $(CXX) $(strip $< $(LIBBLIS_LINK) $(LDFLAGS) -o $@) test_%_openblas_mt.x: test_%_openblas_mt.o $(LIBBLIS_LINK) $(CC) $(strip $< $(OPENBLASP_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $@) test_%_vendor_mt.x: test_%_vendor_mt.o $(LIBBLIS_LINK) $(CC) $(strip $< $(VENDORP_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $@) # -- Clean rules -- clean: cleanx cleanx: - $(RM_F) *.x *.o blis-0.9.0/test/sup/old/supmt/octave/000077500000000000000000000000001422157504600174545ustar00rootroot00000000000000blis-0.9.0/test/sup/old/supmt/octave/gen_opsupnames.m000066400000000000000000000036721422157504600226650ustar00rootroot00000000000000function [ r_val1, r_val2 ] = gen_opsupnames( ops, stor, smalldims ) nops = size( ops, 1 ); smallm = smalldims( 1 ); smalln = smalldims( 2 ); smallk = smalldims( 3 ); i = 1; for io = 1:nops op = ops( io, : ); % NOTE: This way of sprintf'ing doesn't work when the string lengths % vary, as they would if any of the constant dimensions is greater % than 9. %opsupnames( i+0, : ) = sprintf( '%s_%s_m%dnpkp ', op, stor, smallm ) %opsupnames( i+1, : ) = sprintf( '%s_%s_mpn%dkp ', op, stor, smalln ) %opsupnames( i+2, : ) = sprintf( '%s_%s_mpnpk%d', op, stor, smallk ) %opsupnames( i+3, : ) = sprintf( '%s_%s_mpn%dk%d', op, stor, smalln, smallk ) %opsupnames( i+4, : ) = sprintf( '%s_%s_m%dnpk%d', op, stor, smallm, smallk ) %opsupnames( i+5, : ) = sprintf( '%s_%s_m%dn%dkp ', op, stor, smallm, smalln ) %opsupnames( i+6, : ) = sprintf( '%s_%s_mpnpkp ', op, stor ) str0 = sprintf( '%s_%s_m%dnpkp', op, stor, smallm ); str1 = sprintf( '%s_%s_mpn%dkp', op, stor, smalln ); str2 = sprintf( '%s_%s_mpnpk%d', op, stor, smallk ); str3 = sprintf( '%s_%s_mpn%dk%d', op, stor, smalln, smallk ); str4 = sprintf( '%s_%s_m%dnpk%d', op, stor, smallm, smallk ); str5 = sprintf( '%s_%s_m%dn%dkp', op, stor, smallm, smalln ); str6 = sprintf( '%s_%s_mpnpkp', op, stor ); opsupnames( i+0, : ) = sprintf( '%-22s', str0 ); opsupnames( i+1, : ) = sprintf( '%-22s', str1 ); opsupnames( i+2, : ) = sprintf( '%-22s', str2 ); opsupnames( i+3, : ) = sprintf( '%-22s', str3 ); opsupnames( i+4, : ) = sprintf( '%-22s', str4 ); opsupnames( i+5, : ) = sprintf( '%-22s', str5 ); opsupnames( i+6, : ) = sprintf( '%-22s', str6 ); opnames( i+0, : ) = sprintf( '%s', op ); opnames( i+1, : ) = sprintf( '%s', op ); opnames( i+2, : ) = sprintf( '%s', op ); opnames( i+3, : ) = sprintf( '%s', op ); opnames( i+4, : ) = sprintf( '%s', op ); opnames( i+5, : ) = sprintf( '%s', op ); opnames( i+6, : ) = sprintf( '%s', op ); i = i + 7; end r_val1 = opsupnames; r_val2 = opnames; blis-0.9.0/test/sup/old/supmt/octave/plot_l3sup_perf.m000066400000000000000000000172361422157504600227630ustar00rootroot00000000000000function r_val = plot_l3sup_perf( opname, ... data_blissup, ... data_blislpab, ... data_eigen, ... data_open, ... data_vend, vend_str, ... nth, ... rows, cols, ... cfreq, ... dfps, ... theid, impl ) %if ... %mod(theid-1,cols) == 2 || ... % ... %mod(theid-1,cols) == 3 || ... % ... %mod(theid-1,cols) == 4 || ... % 0 == 1 ... %theid >= 19 % show_plot = 0; %else show_plot = 1; %end %legend_plot_id = 11; legend_plot_id = 0*cols + 1*4; if 1 ax1 = subplot( rows, cols, theid ); hold( ax1, 'on' ); end % Set line properties. color_blissup = 'k'; lines_blissup = '-'; markr_blissup = ''; color_blislpab = 'k'; lines_blislpab = ':'; markr_blislpab = ''; color_eigen = 'm'; lines_eigen = '-.'; markr_eigen = 'o'; color_open = 'r'; lines_open = '--'; markr_open = 'o'; color_vend = 'b'; lines_vend = '-.'; markr_vend = '.'; % Compute the peak performance in terms of the number of double flops % executable per cycle and the clock rate. if opname(1) == 's' || opname(1) == 'c' flopspercycle = dfps * 2; else flopspercycle = dfps; end max_perf_core = (flopspercycle * cfreq) * 1; % Escape underscores in the title. title_opname = strrep( opname, '_', '\_' ); % Print the title to a string. titlename = '%s'; titlename = sprintf( titlename, title_opname ); % Set the legend strings. blissup_legend = sprintf( 'BLIS sup' ); blislpab_legend = sprintf( 'BLIS conv' ); eigen_legend = sprintf( 'Eigen' ); open_legend = sprintf( 'OpenBLAS' ); %vend_legend = sprintf( 'MKL' ); %vend_legend = sprintf( 'ARMPL' ); vend_legend = vend_str; % Set axes range values. y_scale = 1.00; x_begin = 0; %x_end is set below. y_begin = 0; y_end = max_perf_core * y_scale; % Set axes names. if nth == 1 yaxisname = 'GFLOPS'; else yaxisname = 'GFLOPS/core'; end %flopscol = 4; flopscol = size( data_blissup, 2 ); msize = 5; if 1 fontsize = 12; else fontsize = 16; end linesize = 0.5; legend_loc = 'southeast'; % -------------------------------------------------------------------- % Automatically detect a column with the increasing problem size. % Then set the maximum x-axis value. for psize_col = 1:3 if data_blissup( 1, psize_col ) ~= data_blissup( 2, psize_col ) break; end end x_axis( :, 1 ) = data_blissup( :, psize_col ); % Compute the number of data points we have in the x-axis. Note that % we only use quarter the data points for the m = n = k column of graphs. if mod(theid-1,cols) == 6 np = size( data_blissup, 1 ) / 4; else np = size( data_blissup, 1 ); end % Grab the last x-axis value. x_end = data_blissup( np, psize_col ); %data_peak( 1, 1:2 ) = [ 0 max_perf_core ]; %data_peak( 2, 1:2 ) = [ x_end max_perf_core ]; if show_plot == 1 blissup_ln = line( x_axis( 1:np, 1 ), data_blissup( 1:np, flopscol ) / nth, ... 'Color',color_blissup, 'LineStyle',lines_blissup, ... 'LineWidth',linesize ); blislpab_ln = line( x_axis( 1:np, 1 ), data_blislpab( 1:np, flopscol ) / nth, ... 'Color',color_blislpab, 'LineStyle',lines_blislpab, ... 'LineWidth',linesize ); eigen_ln = line( x_axis( 1:np, 1 ), data_eigen( 1:np, flopscol ) / nth, ... 'Color',color_eigen, 'LineStyle',lines_eigen, ... 'LineWidth',linesize ); open_ln = line( x_axis( 1:np, 1 ), data_open( 1:np, flopscol ) / nth, ... 'Color',color_open, 'LineStyle',lines_open, ... 'LineWidth',linesize ); vend_ln = line( x_axis( 1:np, 1 ), data_vend( 1:np, flopscol ) / nth, ... 'Color',color_vend, 'LineStyle',lines_vend, ... 'LineWidth',linesize ); elseif theid == legend_plot_id blissup_ln = line( nan, nan, ... 'Color',color_blissup, 'LineStyle',lines_blissup, ... 'LineWidth',linesize ); blislpab_ln = line( nan, nan, ... 'Color',color_blislpab, 'LineStyle',lines_blislpab, ... 'LineWidth',linesize ); eigen_ln = line( nan, nan, ... 'Color',color_eigen, 'LineStyle',lines_eigen, ... 'LineWidth',linesize ); open_ln = line( nan, nan, ... 'Color',color_open, 'LineStyle',lines_open, ... 'LineWidth',linesize ); vend_ln = line( nan, nan, ... 'Color',color_vend, 'LineStyle',lines_vend, ... 'LineWidth',linesize ); end xlim( ax1, [x_begin x_end] ); ylim( ax1, [y_begin y_end] ); if 6000 <= x_end && x_end < 10000 x_tick2 = x_end - 2000; x_tick1 = x_tick2/2; xticks( ax1, [ x_tick1 x_tick2 ] ); elseif 4000 <= x_end && x_end < 6000 x_tick2 = x_end - 1000; x_tick1 = x_tick2/2; xticks( ax1, [ x_tick1 x_tick2 ] ); elseif 2000 <= x_end && x_end < 3000 x_tick2 = x_end - 400; x_tick1 = x_tick2/2; xticks( ax1, [ x_tick1 x_tick2 ] ); elseif 500 <= x_end && x_end < 1000 x_tick3 = x_end*(3/4); x_tick2 = x_end*(2/4); x_tick1 = x_end*(1/4); xticks( ax1, [ x_tick1 x_tick2 x_tick3 ] ); end if show_plot == 1 || theid == legend_plot_id if theid == legend_plot_id leg = legend( ... [ ... blissup_ln ... blislpab_ln ... eigen_ln ... open_ln ... vend_ln ... ], ... blissup_legend, ... blislpab_legend, ... eigen_legend, ... open_legend, ... vend_legend, ... 'Location', legend_loc ); set( leg,'Box','off' ); set( leg,'Color','none' ); set( leg,'Units','inches' ); if impl == 'octave' set( leg,'FontSize',fontsize ); set( leg,'Position',[12.40 10.60 1.9 0.95 ] ); % (1,4tl) else set( leg,'FontSize',fontsize-1 ); set( leg,'Position',[18.24 10.15 1.15 0.7 ] ); % (1,4tl) end set( leg,'Box','off' ); set( leg,'Color','none' ); set( leg,'Units','inches' ); % xpos ypos %set( leg,'Position',[11.32 6.36 1.15 0.7 ] ); % (1,4tl) end end set( ax1,'FontSize',fontsize ); set( ax1,'TitleFontSizeMultiplier',1.0 ); % default is 1.1. box( ax1, 'on' ); titl = title( titlename ); set( titl, 'FontWeight', 'normal' ); % default font style is now 'bold'. % The default is to align the plot title across whole figure, not the box. % This is a hack to nudge the title back to the center of the box. if impl == 'octave' tpos = get( titl, 'Position' ); % For some reason, the titles in the graphs in the last column start % off in a different relative position than the graphs in the other % columns. Here, we manually account for that. if mod(theid-1,cols) == 6 tpos(1) = tpos(1) + -10; else tpos(1) = tpos(1) + -40; end set( titl, 'Position', tpos ); set( titl, 'FontSize', fontsize ); else % impl == 'matlab' tpos = get( titl, 'Position' ); tpos(1) = tpos(1) + 90; set( titl, 'Position', tpos ); end if theid > (rows-1)*cols %xlab = xlabel( ax1,xaxisname ); %tpos = get( xlab, 'Position' ) %tpos(2) = tpos(2) + 10; %set( xlab, 'Position', tpos ); if theid == rows*cols - 6 xlab = xlabel( ax1, 'm = 6; n = k' ); elseif theid == rows*cols - 5 xlab = xlabel( ax1, 'n = 8; m = k' ); elseif theid == rows*cols - 4 xlab = xlabel( ax1, 'k = 10; m = n' ); elseif theid == rows*cols - 3 xlab = xlabel( ax1, 'm; n = 8, k = 10' ); elseif theid == rows*cols - 2 xlab = xlabel( ax1, 'n; m = 6, k = 10' ); elseif theid == rows*cols - 1 xlab = xlabel( ax1, 'k; m = 6, n = 8' ); elseif theid == rows*cols - 0 xlab = xlabel( ax1, 'm = n = k' ); end end if mod(theid-1,cols) == 0 ylab = ylabel( ax1,yaxisname ); end r_val = 0; blis-0.9.0/test/sup/old/supmt/octave/plot_panel_trxsh.m000066400000000000000000000115651422157504600232270ustar00rootroot00000000000000function r_val = plot_panel_trxsh ... ( ... cfreq, ... dflopspercycle, ... nth, ... thr_str, ... dt_ch, ... stor_str, ... smalldims, ... dirpath, ... arch_str, ... vend_str, ... impl ... ) %cfreq = 1.8; %dflopspercycle = 32; % Create filename "templates" for the files that contain the performance % results. filetemp_blissup = '%s/output_%s_%s_blissup.m'; filetemp_blislpab = '%s/output_%s_%s_blislpab.m'; filetemp_eigen = '%s/output_%s_%s_eigen.m'; filetemp_open = '%s/output_%s_%s_openblas.m'; filetemp_vend = '%s/output_%s_%s_vendor.m'; % Create a variable name "template" for the variables contained in the % files outlined above. vartemp = 'data_%s_%s_%s( :, : )'; % Define the datatypes and operations we will be plotting. oproot = sprintf( '%cgemm', dt_ch ); ops( 1, : ) = sprintf( '%s_nn', oproot ); ops( 2, : ) = sprintf( '%s_nt', oproot ); ops( 3, : ) = sprintf( '%s_tn', oproot ); ops( 4, : ) = sprintf( '%s_tt', oproot ); % Generate datatype-specific operation names from the set of operations % and datatypes. [ opsupnames, opnames ] = gen_opsupnames( ops, stor_str, smalldims ); n_opsupnames = size( opsupnames, 1 ); %opsupnames %opnames %return if 1 == 1 %fig = figure('Position', [100, 100, 2400, 1500]); fig = figure('Position', [100, 100, 2400, 1200]); orient( fig, 'portrait' ); set(gcf,'PaperUnits', 'inches'); if impl == 'matlab' set(gcf,'PaperSize', [11.5 20.4]); set(gcf,'PaperPosition', [0 0 11.5 20.4]); set(gcf,'PaperPositionMode','manual'); else % impl == 'octave' % octave 4.x set(gcf,'PaperSize', [12 22.0]); set(gcf,'PaperPositionMode','auto'); end set(gcf,'PaperOrientation','landscape'); end % Iterate over the list of datatype-specific operation names. for opi = 1:n_opsupnames %for opi = 1:1 % Grab the current datatype combination. opsupname = opsupnames( opi, : ); opname = opnames( opi, : ); opsupname = strtrim( opsupname ); opname = strtrim( opname ); str = sprintf( 'Plotting %2d: %s', opi, opsupname ); disp(str); % Construct filenames for the data files from templates. file_blissup = sprintf( filetemp_blissup, dirpath, thr_str, opsupname ); file_blislpab = sprintf( filetemp_blislpab, dirpath, thr_str, opsupname ); file_eigen = sprintf( filetemp_eigen, dirpath, thr_str, opsupname ); file_open = sprintf( filetemp_open, dirpath, thr_str, opsupname ); file_vend = sprintf( filetemp_vend, dirpath, thr_str, opsupname ); % Load the data files. %str = sprintf( ' Loading %s', file_blissup ); disp(str); run( file_blissup ) run( file_blislpab ) run( file_eigen ) run( file_open ) run( file_vend ) % Construct variable names for the variables in the data files. var_blissup = sprintf( vartemp, thr_str, opname, 'blissup' ); var_blislpab = sprintf( vartemp, thr_str, opname, 'blislpab' ); var_eigen = sprintf( vartemp, thr_str, opname, 'eigen' ); var_open = sprintf( vartemp, thr_str, opname, 'openblas' ); var_vend = sprintf( vartemp, thr_str, opname, 'vendor' ); % Use eval() to instantiate the variable names constructed above, % copying each to a simplified name. data_blissup = eval( var_blissup ); % e.g. data_st_dgemm_blissup( :, : ); data_blislpab = eval( var_blislpab ); % e.g. data_st_dgemm_blislpab( :, : ); data_eigen = eval( var_eigen ); % e.g. data_st_dgemm_eigen( :, : ); data_open = eval( var_open ); % e.g. data_st_dgemm_openblas( :, : ); data_vend = eval( var_vend ); % e.g. data_st_dgemm_vendor( :, : ); %str = sprintf( ' Reading %s', var_blissup ); disp(str); %str = sprintf( ' Reading %s', var_blislpab ); disp(str); %str = sprintf( ' Reading %s', var_eigen ); disp(str); %str = sprintf( ' Reading %s', var_open ); disp(str); %str = sprintf( ' Reading %s', var_bfeo ); disp(str); %str = sprintf( ' Reading %s', var_xsmm ); disp(str); %str = sprintf( ' Reading %s', var_vend ); disp(str); % Plot one result in an m x n grid of plots, via the subplot() % function. if 1 == 1 plot_l3sup_perf( opsupname, ... data_blissup, ... data_blislpab, ... data_eigen, ... data_open, ... data_vend, vend_str, ... nth, ... 4, 7, ... cfreq, ... dflopspercycle, ... opi, impl ); clear data_mt_*gemm_*; clear data_blissup; clear data_blislpab; clear data_eigen; clear data_open; clear data_vend; end end % Construct the name of the file to which we will output the graph. outfile = sprintf( 'l3sup_%s_%s_%s_nt%d.pdf', oproot, stor_str, arch_str, nth ); % Output the graph to pdf format. %print(gcf, 'gemm_md','-fillpage','-dpdf'); %print(gcf, outfile,'-bestfit','-dpdf'); if impl == 'octave' print(gcf, outfile); else % if impl == 'matlab' print(gcf, outfile,'-bestfit','-dpdf'); end blis-0.9.0/test/sup/old/supmt/octave/runthese.m000066400000000000000000000007461422157504600214760ustar00rootroot00000000000000 % kabylake plot_panel_trxsh(3.80,16,4,'mt','d','rrr',[ 6 8 10 ],'../../sup/results/kabylake/20200302/mnkt100000_mt4','kbl','MKL','octave'); close; clear all; % haswell plot_panel_trxsh(3.1,16,12,'mt','d','rrr',[ 6 8 10 ],'../../sup/results/haswell/20200302/mnkt100000_mt12','has','MKL','octave'); close; clear all; % epyc plot_panel_trxsh(2.55,8,32,'mt','d','rrr',[ 6 8 10 ],'../../sup/results/epyc/20200302/mnkt100000_mt32','epyc','MKL','octave'); close; clear all; blis-0.9.0/test/sup/old/supmt/runme.sh000077500000000000000000000110631422157504600176610ustar00rootroot00000000000000#!/bin/bash # File pefixes. exec_root="test" out_root="output" sys="blis" #sys="lonestar5" #sys="ul252" #sys="ul264" if [ ${sys} = "blis" ]; then export GOMP_CPU_AFFINITY="0-3" nt=4 elif [ ${sys} = "lonestar5" ]; then export GOMP_CPU_AFFINITY="0-23" nt=12 elif [ ${sys} = "ul252" ]; then export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/home/field/intel/mkl/lib/intel64" export GOMP_CPU_AFFINITY="0-51" nt=26 elif [ ${sys} = "ul264" ]; then export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/home/field/intel/mkl/lib/intel64" export GOMP_CPU_AFFINITY="0-63" nt=32 fi # Delay between test cases. delay=0.02 # Threadedness to test. #threads="st mt" threads="st mt" # Datatypes to test. #dts="d s" dts="d" # Operations to test. ops="gemm" # Transpose combintions to test. trans="nn nt tn tt" # Storage combinations to test. #stors="rrr rrc rcr rcc crr crc ccr ccc" stors="rrr ccc" # Problem shapes to test. shapes="sll lsl lls lss sls ssl lll" # FGVZ: figure out how to probe what's in the directory and # execute everything that's there? sms="6" sns="8" sks="10" # Implementations to test. impls="vendor blissup blislpab openblas eigen" #impls="vendor" #impls="blissup" #impls="blislpab" #impls="openblas" #impls="eigen" # Save a copy of GOMP_CPU_AFFINITY so that if we have to unset it, we can # restore the value. GOMP_CPU_AFFINITYsave=${GOMP_CPU_AFFINITY} # Example: test_dgemm_nn_rrc_m6npkp_blissup_st.x for th in ${threads}; do for dt in ${dts}; do for op in ${ops}; do for tr in ${trans}; do for st in ${stors}; do for sh in ${shapes}; do for sm in ${sms}; do for sn in ${sns}; do for sk in ${sks}; do for im in ${impls}; do if [ "${th}" = "mt" ]; then # Specify the multithreading depending on which # implementation is about to be tested. if [ "${im:0:4}" = "blis" ]; then unset OMP_NUM_THREADS export BLIS_NUM_THREADS=${nt} elif [ "${im}" = "openblas" ]; then unset OMP_NUM_THREADS export OPENBLAS_NUM_THREADS=${nt} elif [ "${im}" = "eigen" ]; then export OMP_NUM_THREADS=${nt} elif [ "${im}" = "vendor" ]; then unset OMP_NUM_THREADS export MKL_NUM_THREADS=${nt} fi export nt_use=${nt} else # if [ "${th}" = "st" ]; # Use single-threaded execution. export OMP_NUM_THREADS=1 export BLIS_NUM_THREADS=1 export OPENBLAS_NUM_THREADS=1 export MKL_NUM_THREADS=1 export nt_use=1 fi # Multithreaded OpenBLAS seems to have a problem # running properly if GOMP_CPU_AFFINITY is set. # So we temporarily unset it here if we are about # to execute OpenBLAS, but otherwise restore it. if [ ${im} = "openblas" ]; then unset GOMP_CPU_AFFINITY else export GOMP_CPU_AFFINITY="${GOMP_CPU_AFFINITYsave}" fi # Limit execution of non-BLIS implementations to # rrr/ccc storage cases. if [ "${im:0:4}" != "blis" ] && \ [ "${st}" != "rrr" ] && \ [ "${st}" != "ccc" ]; then continue; fi # Further limit execution of libxsmm to # ccc storage cases. if [ "${im:0:7}" = "libxsmm" ] && \ [ "${st}" != "ccc" ]; then continue; fi # Extract the shape chars for m, n, k. chm=${sh:0:1} chn=${sh:1:1} chk=${sh:2:1} # Construct the shape substring (e.g. m6npkp) shstr="" if [ ${chm} = "s" ]; then shstr="${shstr}m${sm}" else shstr="${shstr}mp" fi if [ ${chn} = "s" ]; then shstr="${shstr}n${sn}" else shstr="${shstr}np" fi if [ ${chk} = "s" ]; then shstr="${shstr}k${sk}" else shstr="${shstr}kp" fi # Ex: test_dgemm_nn_rrc_m6npkp_blissup_st.x # Construct the name of the test executable. exec_name="${exec_root}_${dt}${op}_${tr}_${st}_${shstr}_${im}_${th}.x" # Construct the name of the output file. out_file="${out_root}_${th}_${dt}${op}_${tr}_${st}_${shstr}_${im}.m" echo "Running (nt = ${nt_use}) ./${exec_name} > ${out_file}" # Run executable. ./${exec_name} > ${out_file} sleep ${delay} done done done done done done done done done done blis-0.9.0/test/sup/old/supmt/test_gemm.c000066400000000000000000000433431422157504600203320ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2019, Advanced Micro Devices, Inc. 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 The University of Texas 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 COPYRIGHT HOLDER 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. */ #include #ifdef EIGEN #define BLIS_DISABLE_BLAS_DEFS #include "blis.h" #include //#include using namespace Eigen; #else #include "blis.h" #endif //#define PRINT int main( int argc, char** argv ) { rntm_t rntm_g; bli_init(); // Copy the global rntm_t object so that we can use it later when disabling // sup. Starting with a copy of the global rntm_t is actually necessary; // if we start off with a locally-initialized rntm_t, it will not contain // the ways of parallelism that were conveyed via environment variables, // which is necessary when running this driver with multiple BLIS threads. bli_rntm_init_from_global( &rntm_g ); #ifndef ERROR_CHECK bli_error_checking_level_set( BLIS_NO_ERROR_CHECKING ); #endif dim_t n_trials = N_TRIALS; num_t dt = DT; #if 1 dim_t p_begin = P_BEGIN; dim_t p_max = P_MAX; dim_t p_inc = P_INC; #else dim_t p_begin = 4; dim_t p_max = 40; dim_t p_inc = 4; #endif #if 1 dim_t m_input = M_DIM; dim_t n_input = N_DIM; dim_t k_input = K_DIM; #else p_begin = p_inc = 32; dim_t m_input = 6; dim_t n_input = -1; dim_t k_input = -1; #endif #if 1 trans_t transa = TRANSA; trans_t transb = TRANSB; #else trans_t transa = BLIS_NO_TRANSPOSE; trans_t transb = BLIS_NO_TRANSPOSE; #endif #if 1 stor3_t sc = STOR3; #else stor3_t sc = BLIS_RRR; #endif inc_t rs_c, cs_c; inc_t rs_a, cs_a; inc_t rs_b, cs_b; if ( sc == BLIS_RRR ) { rs_c = cs_c = -1; rs_a = cs_a = -1; rs_b = cs_b = -1; } else if ( sc == BLIS_RRC ) { rs_c = cs_c = -1; rs_a = cs_a = -1; rs_b = cs_b = 0; } else if ( sc == BLIS_RCR ) { rs_c = cs_c = -1; rs_a = cs_a = 0; rs_b = cs_b = -1; } else if ( sc == BLIS_RCC ) { rs_c = cs_c = -1; rs_a = cs_a = 0; rs_b = cs_b = 0; } else if ( sc == BLIS_CRR ) { rs_c = cs_c = 0; rs_a = cs_a = -1; rs_b = cs_b = -1; } else if ( sc == BLIS_CRC ) { rs_c = cs_c = 0; rs_a = cs_a = -1; rs_b = cs_b = 0; } else if ( sc == BLIS_CCR ) { rs_c = cs_c = 0; rs_a = cs_a = 0; rs_b = cs_b = -1; } else if ( sc == BLIS_CCC ) { rs_c = cs_c = 0; rs_a = cs_a = 0; rs_b = cs_b = 0; } else { bli_abort(); } f77_int cbla_storage; if ( sc == BLIS_RRR ) cbla_storage = CblasRowMajor; else if ( sc == BLIS_CCC ) cbla_storage = CblasColMajor; else cbla_storage = -1; ( void )cbla_storage; char dt_ch; // Choose the char corresponding to the requested datatype. if ( bli_is_float( dt ) ) dt_ch = 's'; else if ( bli_is_double( dt ) ) dt_ch = 'd'; else if ( bli_is_scomplex( dt ) ) dt_ch = 'c'; else dt_ch = 'z'; f77_char f77_transa; f77_char f77_transb; char transal, transbl; bli_param_map_blis_to_netlib_trans( transa, &f77_transa ); bli_param_map_blis_to_netlib_trans( transb, &f77_transb ); transal = tolower( f77_transa ); transbl = tolower( f77_transb ); f77_int cbla_transa = ( transal == 'n' ? CblasNoTrans : CblasTrans ); f77_int cbla_transb = ( transbl == 'n' ? CblasNoTrans : CblasTrans ); ( void )cbla_transa; ( void )cbla_transb; dim_t p; // Begin with initializing the last entry to zero so that // matlab allocates space for the entire array once up-front. for ( p = p_begin; p + p_inc <= p_max; p += p_inc ) ; printf( "data_%s_%cgemm_%c%c_%s", THR_STR, dt_ch, transal, transbl, STR ); printf( "( %2lu, 1:4 ) = [ %4lu %4lu %4lu %7.2f ];\n", ( unsigned long )(p - p_begin)/p_inc + 1, ( unsigned long )0, ( unsigned long )0, ( unsigned long )0, 0.0 ); //for ( p = p_begin; p <= p_max; p += p_inc ) for ( p = p_max; p_begin <= p; p -= p_inc ) { obj_t a, b, c; obj_t c_save; obj_t alpha, beta; dim_t m, n, k; if ( m_input < 0 ) m = p / ( dim_t )abs(m_input); else m = ( dim_t ) m_input; if ( n_input < 0 ) n = p / ( dim_t )abs(n_input); else n = ( dim_t ) n_input; if ( k_input < 0 ) k = p / ( dim_t )abs(k_input); else k = ( dim_t ) k_input; bli_obj_create( dt, 1, 1, 0, 0, &alpha ); bli_obj_create( dt, 1, 1, 0, 0, &beta ); bli_obj_create( dt, m, n, rs_c, cs_c, &c ); bli_obj_create( dt, m, n, rs_c, cs_c, &c_save ); if ( bli_does_notrans( transa ) ) bli_obj_create( dt, m, k, rs_a, cs_a, &a ); else bli_obj_create( dt, k, m, rs_a, cs_a, &a ); if ( bli_does_notrans( transb ) ) bli_obj_create( dt, k, n, rs_b, cs_b, &b ); else bli_obj_create( dt, n, k, rs_b, cs_b, &b ); bli_randm( &a ); bli_randm( &b ); bli_randm( &c ); bli_obj_set_conjtrans( transa, &a ); bli_obj_set_conjtrans( transb, &b ); bli_setsc( (1.0/1.0), 0.0, &alpha ); bli_setsc( (1.0/1.0), 0.0, &beta ); bli_copym( &c, &c_save ); #ifdef EIGEN double alpha_r, alpha_i; bli_getsc( &alpha, &alpha_r, &alpha_i ); void* ap = bli_obj_buffer_at_off( &a ); void* bp = bli_obj_buffer_at_off( &b ); void* cp = bli_obj_buffer_at_off( &c ); const int os_a = ( bli_obj_is_col_stored( &a ) ? bli_obj_col_stride( &a ) : bli_obj_row_stride( &a ) ); const int os_b = ( bli_obj_is_col_stored( &b ) ? bli_obj_col_stride( &b ) : bli_obj_row_stride( &b ) ); const int os_c = ( bli_obj_is_col_stored( &c ) ? bli_obj_col_stride( &c ) : bli_obj_row_stride( &c ) ); Stride stride_a( os_a, 1 ); Stride stride_b( os_b, 1 ); Stride stride_c( os_c, 1 ); #if defined(IS_FLOAT) #elif defined (IS_DOUBLE) #ifdef A_STOR_R typedef Matrix MatrixXd_A; #else typedef Matrix MatrixXd_A; #endif #ifdef B_STOR_R typedef Matrix MatrixXd_B; #else typedef Matrix MatrixXd_B; #endif #ifdef C_STOR_R typedef Matrix MatrixXd_C; #else typedef Matrix MatrixXd_C; #endif #ifdef A_NOTRANS // A is not transposed Map > A( ( double* )ap, m, k, stride_a ); #else // A is transposed Map > A( ( double* )ap, k, m, stride_a ); #endif #ifdef B_NOTRANS // B is not transposed Map > B( ( double* )bp, k, n, stride_b ); #else // B is transposed Map > B( ( double* )bp, n, k, stride_b ); #endif Map > C( ( double* )cp, m, n, stride_c ); #endif #endif double dtime_save = DBL_MAX; for ( dim_t r = 0; r < n_trials; ++r ) { bli_copym( &c_save, &c ); double dtime = bli_clock(); #ifdef EIGEN #ifdef A_NOTRANS #ifdef B_NOTRANS C.noalias() += alpha_r * A * B; #else // B_TRANS C.noalias() += alpha_r * A * B.transpose(); #endif #else // A_TRANS #ifdef B_NOTRANS C.noalias() += alpha_r * A.transpose() * B; #else // B_TRANS C.noalias() += alpha_r * A.transpose() * B.transpose(); #endif #endif #endif #ifdef BLIS #ifdef SUP // Allow sup. bli_gemm( &alpha, &a, &b, &beta, &c ); #else // NOTE: We can't use the static initializer and must instead // initialize the rntm_t with the copy from the global rntm_t we // made at the beginning of main(). Please see the comment there // for more info on why BLIS_RNTM_INITIALIZER doesn't work here. //rntm_t rntm = BLIS_RNTM_INITIALIZER; rntm_t rntm = rntm_g; // Disable sup and use the expert interface. bli_rntm_disable_l3_sup( &rntm ); bli_gemm_ex( &alpha, &a, &b, &beta, &c, NULL, &rntm ); #endif #endif #ifdef BLAS if ( bli_is_float( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); float* alphap = ( float* )bli_obj_buffer( &alpha ); float* ap = ( float* )bli_obj_buffer( &a ); float* bp = ( float* )bli_obj_buffer( &b ); float* betap = ( float* )bli_obj_buffer( &beta ); float* cp = ( float* )bli_obj_buffer( &c ); #ifdef XSMM libxsmm_sgemm( &f77_transa, #else sgemm_( &f77_transa, #endif &f77_transb, &mm, &nn, &kk, alphap, ap, &lda, bp, &ldb, betap, cp, &ldc ); } else if ( bli_is_double( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); double* alphap = ( double* )bli_obj_buffer( &alpha ); double* ap = ( double* )bli_obj_buffer( &a ); double* bp = ( double* )bli_obj_buffer( &b ); double* betap = ( double* )bli_obj_buffer( &beta ); double* cp = ( double* )bli_obj_buffer( &c ); #ifdef XSMM libxsmm_dgemm( &f77_transa, #else dgemm_( &f77_transa, #endif &f77_transb, &mm, &nn, &kk, alphap, ap, &lda, bp, &ldb, betap, cp, &ldc ); } else if ( bli_is_scomplex( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); scomplex* alphap = ( scomplex* )bli_obj_buffer( &alpha ); scomplex* ap = ( scomplex* )bli_obj_buffer( &a ); scomplex* bp = ( scomplex* )bli_obj_buffer( &b ); scomplex* betap = ( scomplex* )bli_obj_buffer( &beta ); scomplex* cp = ( scomplex* )bli_obj_buffer( &c ); #ifdef XSMM libxsmm_cgemm( &f77_transa, #else cgemm_( &f77_transa, #endif &f77_transb, &mm, &nn, &kk, alphap, ap, &lda, bp, &ldb, betap, cp, &ldc ); } else if ( bli_is_dcomplex( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); dcomplex* alphap = ( dcomplex* )bli_obj_buffer( &alpha ); dcomplex* ap = ( dcomplex* )bli_obj_buffer( &a ); dcomplex* bp = ( dcomplex* )bli_obj_buffer( &b ); dcomplex* betap = ( dcomplex* )bli_obj_buffer( &beta ); dcomplex* cp = ( dcomplex* )bli_obj_buffer( &c ); #ifdef XSMM libxsmm_zgemm( &f77_transa, #else zgemm_( &f77_transa, #endif &f77_transb, &mm, &nn, &kk, alphap, ap, &lda, bp, &ldb, betap, cp, &ldc ); } #endif #ifdef CBLAS if ( bli_is_float( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); f77_int nn = bli_obj_width( &c ); #ifdef C_STOR_R f77_int lda = bli_obj_row_stride( &a ); f77_int ldb = bli_obj_row_stride( &b ); f77_int ldc = bli_obj_row_stride( &c ); #else f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); #endif float* alphap = bli_obj_buffer( &alpha ); float* ap = bli_obj_buffer( &a ); float* bp = bli_obj_buffer( &b ); float* betap = bli_obj_buffer( &beta ); float* cp = bli_obj_buffer( &c ); cblas_sgemm( cbla_storage, cbla_transa, cbla_transb, mm, nn, kk, *alphap, ap, lda, bp, ldb, *betap, cp, ldc ); } else if ( bli_is_double( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); f77_int nn = bli_obj_width( &c ); #ifdef C_STOR_R f77_int lda = bli_obj_row_stride( &a ); f77_int ldb = bli_obj_row_stride( &b ); f77_int ldc = bli_obj_row_stride( &c ); #else f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); #endif double* alphap = bli_obj_buffer( &alpha ); double* ap = bli_obj_buffer( &a ); double* bp = bli_obj_buffer( &b ); double* betap = bli_obj_buffer( &beta ); double* cp = bli_obj_buffer( &c ); cblas_dgemm( cbla_storage, cbla_transa, cbla_transb, mm, nn, kk, *alphap, ap, lda, bp, ldb, *betap, cp, ldc ); } else if ( bli_is_scomplex( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); f77_int nn = bli_obj_width( &c ); #ifdef C_STOR_R f77_int lda = bli_obj_row_stride( &a ); f77_int ldb = bli_obj_row_stride( &b ); f77_int ldc = bli_obj_row_stride( &c ); #else f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); #endif scomplex* alphap = bli_obj_buffer( &alpha ); scomplex* ap = bli_obj_buffer( &a ); scomplex* bp = bli_obj_buffer( &b ); scomplex* betap = bli_obj_buffer( &beta ); scomplex* cp = bli_obj_buffer( &c ); cblas_cgemm( cbla_storage, cbla_transa, cbla_transb, mm, nn, kk, alphap, ap, lda, bp, ldb, betap, cp, ldc ); } else if ( bli_is_dcomplex( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); f77_int nn = bli_obj_width( &c ); #ifdef C_STOR_R f77_int lda = bli_obj_row_stride( &a ); f77_int ldb = bli_obj_row_stride( &b ); f77_int ldc = bli_obj_row_stride( &c ); #else f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); #endif dcomplex* alphap = bli_obj_buffer( &alpha ); dcomplex* ap = bli_obj_buffer( &a ); dcomplex* bp = bli_obj_buffer( &b ); dcomplex* betap = bli_obj_buffer( &beta ); dcomplex* cp = bli_obj_buffer( &c ); cblas_zgemm( cbla_storage, cbla_transa, cbla_transb, mm, nn, kk, alphap, ap, lda, bp, ldb, betap, cp, ldc ); } #endif dtime_save = bli_clock_min_diff( dtime_save, dtime ); } double gflops = ( 2.0 * m * k * n ) / ( dtime_save * 1.0e9 ); if ( bli_is_complex( dt ) ) gflops *= 4.0; printf( "data_%s_%cgemm_%c%c_%s", THR_STR, dt_ch, transal, transbl, STR ); printf( "( %2lu, 1:4 ) = [ %4lu %4lu %4lu %7.2f ];\n", ( unsigned long )(p - p_begin)/p_inc + 1, ( unsigned long )m, ( unsigned long )n, ( unsigned long )k, gflops ); bli_obj_free( &alpha ); bli_obj_free( &beta ); bli_obj_free( &a ); bli_obj_free( &b ); bli_obj_free( &c ); bli_obj_free( &c_save ); } //bli_finalize(); return 0; } blis-0.9.0/test/sup/old/supst/000077500000000000000000000000001422157504600162015ustar00rootroot00000000000000blis-0.9.0/test/sup/old/supst/Makefile000066400000000000000000000422401422157504600176430ustar00rootroot00000000000000#!/bin/bash # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2014, The University of Texas at Austin # Copyright (C) 2019, Advanced Micro Devices, Inc. # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # # # Makefile # # Field G. Van Zee # # Makefile for standalone BLIS test drivers. # # # --- Makefile PHONY target definitions ---------------------------------------- # .PHONY: all all-st all-mt \ blis blis-st blis-mt \ clean cleanx # # --- Determine makefile fragment location ------------------------------------- # # Comments: # - DIST_PATH is assumed to not exist if BLIS_INSTALL_PATH is given. # - We must use recursively expanded assignment for LIB_PATH and INC_PATH in # the second case because CONFIG_NAME is not yet set. ifneq ($(strip $(BLIS_INSTALL_PATH)),) LIB_PATH := $(BLIS_INSTALL_PATH)/lib INC_PATH := $(BLIS_INSTALL_PATH)/include/blis SHARE_PATH := $(BLIS_INSTALL_PATH)/share/blis else DIST_PATH := ../.. LIB_PATH = ../../lib/$(CONFIG_NAME) INC_PATH = ../../include/$(CONFIG_NAME) SHARE_PATH := ../.. endif # # --- Include common makefile definitions -------------------------------------- # # Include the common makefile fragment. -include $(SHARE_PATH)/common.mk # # --- BLAS and LAPACK implementations ------------------------------------------ # # BLIS library and header path. This is simply wherever it was installed. #BLIS_LIB_PATH := $(INSTALL_PREFIX)/lib #BLIS_INC_PATH := $(INSTALL_PREFIX)/include/blis # BLIS library. #BLIS_LIB := $(BLIS_LIB_PATH)/libblis.a # BLAS library path(s). This is where the BLAS libraries reside. HOME_LIB_PATH := $(HOME)/flame/lib MKL_LIB_PATH := $(HOME)/intel/mkl/lib/intel64 # netlib BLAS NETLIB_LIB := $(HOME_LIB_PATH)/libblas.a # OpenBLAS OPENBLAS_LIB := $(HOME_LIB_PATH)/libopenblas.a OPENBLASP_LIB := $(HOME_LIB_PATH)/libopenblasp.a # BLASFEO BLASFEO_LIB := $(HOME_LIB_PATH)/libblasfeo.a # libxsmm LIBXSMM_LIB := $(HOME_LIB_PATH)/libxsmm.a -ldl \ $(NETLIB_LIB) -lgfortran # ATLAS ATLAS_LIB := $(HOME_LIB_PATH)/libf77blas.a \ $(HOME_LIB_PATH)/libatlas.a # Eigen EIGEN_INC := $(HOME)/flame/eigen/include/eigen3 EIGEN_LIB := $(HOME_LIB_PATH)/libeigen_blas_static.a EIGENP_LIB := $(EIGEN_LIB) # MKL MKL_LIB := -L$(MKL_LIB_PATH) \ -lmkl_intel_lp64 \ -lmkl_core \ -lmkl_sequential \ -lpthread -lm -ldl MKLP_LIB := -L$(MKL_LIB_PATH) \ -lmkl_intel_lp64 \ -lmkl_core \ -lmkl_gnu_thread \ -lpthread -lm -ldl -fopenmp #-L$(ICC_LIB_PATH) \ #-lgomp VENDOR_LIB := $(MKL_LIB) VENDORP_LIB := $(MKLP_LIB) # # --- Problem size definitions ------------------------------------------------- # # Single core PS_BEGIN_3L := 2 PS_MAX_3L := 400 PS_INC_3L := 2 PS_BEGIN_2L := 4 PS_MAX_2L := 800 PS_INC_2L := 4 PS_BEGIN_1L := 32 PS_MAX_1L := 6400 PS_INC_1L := 32 # # --- General build definitions ------------------------------------------------ # TEST_SRC_PATH := . TEST_OBJ_PATH := . # Gather all local object files. TEST_OBJS := $(sort $(patsubst $(TEST_SRC_PATH)/%.c, \ $(TEST_OBJ_PATH)/%.o, \ $(wildcard $(TEST_SRC_PATH)/*.c))) # Override the value of CINCFLAGS so that the value of CFLAGS returned by # get-frame-cflags-for() is not cluttered up with include paths needed only # while building BLIS. CINCFLAGS := -I$(INC_PATH) # Use the "framework" CFLAGS for the configuration family. CFLAGS := $(call get-user-cflags-for,$(CONFIG_NAME)) # Add local header paths to CFLAGS. CFLAGS += -I$(TEST_SRC_PATH) # Locate the libblis library to which we will link. LIBBLIS_LINK := $(LIB_PATH)/$(LIBBLIS_L) # Define a set of CFLAGS for use with C++ and Eigen. CXXFLAGS := $(subst -std=c99,-std=c++11,$(CFLAGS)) CXXFLAGS += -I$(EIGEN_INC) # Create a copy of CXXFLAGS without -fopenmp in order to disable multithreading. CXXFLAGS_ST := -march=native $(subst -fopenmp,,$(CXXFLAGS)) CXXFLAGS_MT := -march=native $(CXXFLAGS) # Single or multithreaded string. STR_ST := -DTHR_STR=\"st\" STR_MT := -DTHR_STR=\"mt\" # Number of trials per problem size. N_TRIALS := -DN_TRIALS=3 # Problem size specification. PDEF_ST_1L := -DP_BEGIN=$(PS_BEGIN_1L) -DP_MAX=$(PS_MAX_1L) -DP_INC=$(PS_INC_1L) PDEF_ST_2L := -DP_BEGIN=$(PS_BEGIN_2L) -DP_MAX=$(PS_MAX_2L) -DP_INC=$(PS_INC_2L) PDEF_ST_3L := -DP_BEGIN=$(PS_BEGIN_3L) -DP_MAX=$(PS_MAX_3L) -DP_INC=$(PS_INC_3L) ifeq ($(E),1) ERRCHK := -DERROR_CHECK else ERRCHK := -DNO_ERROR_CHECK endif # Enumerate possible datatypes and computation precisions. #dts := s d c z DTS := d TRANS := n_n \ n_t \ t_n \ t_t # While BLIS supports all combinations of row and column storage for matrices # C, A, and B, the alternatives mostly only support CBLAS APIs, which inherently # support only "all row-storage" or "all column-storage". Thus, we disable the # building of those other drivers so that compilation/linking completes sooner. #STORS := r_r_r \ # r_r_c \ # r_c_r \ # r_c_c \ # c_r_r \ # c_r_c \ # c_c_r \ # c_c_c STORS := r_r_r \ c_c_c SHAPES := l_l_s \ l_s_l \ s_l_l \ s_s_l \ s_l_s \ l_s_s \ l_l_l SMS := 6 SNS := 8 SKS := 4 # # --- Function definitions ----------------------------------------------------- # # A function to strip the underscores from a list of strings. stripu = $(subst _,,$(1)) # Various functions that help us construct the datatype combinations and then # extract the needed datatype strings and C preprocessor define flags. get-1of2 = $(word 1,$(subst _, ,$(1))) get-2of2 = $(word 2,$(subst _, ,$(1))) get-1of3 = $(word 1,$(subst _, ,$(1))) get-2of3 = $(word 2,$(subst _, ,$(1))) get-3of3 = $(word 3,$(subst _, ,$(1))) # A function to return the correct PDEFS_ST variable given the shape string. get-pdefs = $(strip $(subst l_l_l,$(PDEF_ST_3L), \ $(subst l_l_s,$(PDEF_ST_2L), \ $(subst l_s_l,$(PDEF_ST_2L), \ $(subst s_l_l,$(PDEF_ST_2L), \ $(subst s_s_l,$(PDEF_ST_1L), \ $(subst s_l_s,$(PDEF_ST_1L), \ $(subst l_s_s,$(PDEF_ST_1L),$(1))))))))) # Datatype defs. get-dt-cpp = $(strip \ $(if $(findstring s,$(1)),-DDT=BLIS_FLOAT -DIS_FLOAT,\ $(if $(findstring d,$(1)),-DDT=BLIS_DOUBLE -DIS_DOUBLE,\ $(if $(findstring c,$(1)),-DDT=BLIS_SCOMPLEX -DIS_SCOMPLEX,\ -DDT=BLIS_DCOMPLEX -DIS_DCOMPLEX)))) # Transpose defs. get-tra-defs-a = $(strip $(subst n,-DTRANSA=BLIS_NO_TRANSPOSE -DA_NOTRANS, \ $(subst t,-DTRANSA=BLIS_TRANSPOSE -DA_TRANS,$(call get-1of2,$(1))))) get-tra-defs-b = $(strip $(subst n,-DTRANSB=BLIS_NO_TRANSPOSE -DB_NOTRANS, \ $(subst t,-DTRANSB=BLIS_TRANSPOSE -DB_TRANS,$(call get-2of2,$(1))))) get-tra-defs = $(call get-tra-defs-a,$(1)) $(call get-tra-defs-b,$(1)) # Storage defs. get-sto-uch-a = $(strip $(subst r,R, \ $(subst c,C,$(call get-1of3,$(1))))) get-sto-uch-b = $(strip $(subst r,R, \ $(subst c,C,$(call get-2of3,$(1))))) get-sto-uch-c = $(strip $(subst r,R, \ $(subst c,C,$(call get-3of3,$(1))))) get-sto-defs = $(strip \ -DSTOR3=BLIS_$(call get-sto-uch-a,$(1))$(call get-sto-uch-b,$(1))$(call get-sto-uch-c,$(1)) \ -DA_STOR_$(call get-sto-uch-a,$(1)) \ -DB_STOR_$(call get-sto-uch-b,$(1)) \ -DC_STOR_$(call get-sto-uch-c,$(1))) # Dimension defs. get-shape-defs-cm = $(if $(findstring l,$(1)),-DM_DIM=-1,-DM_DIM=$(2)) get-shape-defs-cn = $(if $(findstring l,$(1)),-DN_DIM=-1,-DN_DIM=$(2)) get-shape-defs-ck = $(if $(findstring l,$(1)),-DK_DIM=-1,-DK_DIM=$(2)) get-shape-defs-m = $(call get-shape-defs-cm,$(call get-1of3,$(1)),$(2)) get-shape-defs-n = $(call get-shape-defs-cn,$(call get-2of3,$(1)),$(2)) get-shape-defs-k = $(call get-shape-defs-ck,$(call get-3of3,$(1)),$(2)) # arguments: 1: shape (w/ underscores) 2: smallm 3: smalln 4: smallk get-shape-defs = $(strip $(call get-shape-defs-m,$(1),$(2)) \ $(call get-shape-defs-n,$(1),$(3)) \ $(call get-shape-defs-k,$(1),$(4))) #$(error l_l_s 6 8 4 = $(call get-shape-defs,l_l_s,6,8,4)) # Shape-dimension string. get-shape-str-ch = $(if $(findstring l,$(1)),p,$(2)) get-shape-str-m = $(call get-shape-str-ch,$(call get-1of3,$(1)),$(2)) get-shape-str-n = $(call get-shape-str-ch,$(call get-2of3,$(1)),$(2)) get-shape-str-k = $(call get-shape-str-ch,$(call get-3of3,$(1)),$(2)) # arguments: 1: shape (w/ underscores) 2: smallm 3: smalln 4: smallk get-shape-dim-str = m$(call get-shape-str-m,$(1),$(2))n$(call get-shape-str-n,$(1),$(3))k$(call get-shape-str-k,$(1),$(4)) # Implementation defs. # Define a function to return the appropriate -DSTR= and -D[BLIS|BLAS] flags. get-imp-defs = $(strip $(subst blissup,-DSTR=\"$(1)\" -DBLIS -DSUP, \ $(subst blislpab,-DSTR=\"$(1)\" -DBLIS, \ $(subst eigen,-DSTR=\"$(1)\" -DEIGEN, \ $(subst openblas,-DSTR=\"$(1)\" -DCBLAS, \ $(subst blasfeo,-DSTR=\"$(1)\" -DCBLAS, \ $(subst libxsmm,-DSTR=\"$(1)\" -DBLAS -DXSMM, \ $(subst vendor,-DSTR=\"$(1)\" -DCBLAS,$(1))))))))) TRANS0 = $(call stripu,$(TRANS)) STORS0 = $(call stripu,$(STORS)) # Limit BLAS and Eigen to only using all row-stored, or all column-stored matrices. # Also, limit libxsmm to using all column-stored matrices since it does not offer # CBLAS interfaces. BSTORS0 = rrr ccc ESTORS0 = rrr ccc XSTORS0 = ccc # # --- Object and binary file definitons ---------------------------------------- # get-st-objs = $(foreach dt,$(1),$(foreach tr,$(2),$(foreach st,$(3),$(foreach sh,$(4),$(foreach sm,$(5),$(foreach sn,$(6),$(foreach sk,$(7),test_$(dt)gemm_$(tr)_$(st)_$(call get-shape-dim-str,$(sh),$(sm),$(sn),$(sk))_$(8)_st.o))))))) # Build a list of object files and binaries for each single-threaded # implementation using the get-st-objs() function defined above. BLISSUP_ST_OBJS := $(call get-st-objs,$(DTS),$(TRANS0),$(STORS0),$(SHAPES),$(SMS),$(SNS),$(SKS),blissup) BLISSUP_ST_BINS := $(patsubst %.o,%.x,$(BLISSUP_ST_OBJS)) BLISLPAB_ST_OBJS := $(call get-st-objs,$(DTS),$(TRANS0),$(STORS0),$(SHAPES),$(SMS),$(SNS),$(SKS),blislpab) BLISLPAB_ST_BINS := $(patsubst %.o,%.x,$(BLISLPAB_ST_OBJS)) EIGEN_ST_OBJS := $(call get-st-objs,$(DTS),$(TRANS0),$(ESTORS0),$(SHAPES),$(SMS),$(SNS),$(SKS),eigen) EIGEN_ST_BINS := $(patsubst %.o,%.x,$(EIGEN_ST_OBJS)) OPENBLAS_ST_OBJS := $(call get-st-objs,$(DTS),$(TRANS0),$(BSTORS0),$(SHAPES),$(SMS),$(SNS),$(SKS),openblas) OPENBLAS_ST_BINS := $(patsubst %.o,%.x,$(OPENBLAS_ST_OBJS)) BLASFEO_ST_OBJS := $(call get-st-objs,$(DTS),$(TRANS0),$(BSTORS0),$(SHAPES),$(SMS),$(SNS),$(SKS),blasfeo) BLASFEO_ST_BINS := $(patsubst %.o,%.x,$(BLASFEO_ST_OBJS)) LIBXSMM_ST_OBJS := $(call get-st-objs,$(DTS),$(TRANS0),$(XSTORS0),$(SHAPES),$(SMS),$(SNS),$(SKS),libxsmm) LIBXSMM_ST_BINS := $(patsubst %.o,%.x,$(LIBXSMM_ST_OBJS)) VENDOR_ST_OBJS := $(call get-st-objs,$(DTS),$(TRANS0),$(BSTORS0),$(SHAPES),$(SMS),$(SNS),$(SKS),vendor) VENDOR_ST_BINS := $(patsubst %.o,%.x,$(VENDOR_ST_OBJS)) #$(error "objs = $(EIGEN_ST_BINS)" ) # Mark the object files as intermediate so that make will remove them # automatically after building the binaries on which they depend. .INTERMEDIATE: $(BLISSUP_ST_OBJS) \ $(BLISLPAB_ST_OBJS) \ $(EIGEN_ST_OBJS) \ $(OPENBLAS_ST_OBJS) \ $(BLASFEO_ST_OBJS) \ $(LIBXSMM_ST_OBJS) \ $(VENDOR_ST_OBJS) # # --- Targets/rules ------------------------------------------------------------ # all: st blissup: blissup-st blislpab: blislpab-st eigen: eigen-st openblas: openblas-st blasfeo: blasfeo-st libxsmm: libxsmm-st vendor: vendor-st st: blissup-st blislpab-st \ eigen-st openblas-st blasfeo-st libxsmm-st vendor-st blis: blissup-st blislpab-st blissup-st: $(BLISSUP_ST_BINS) blislpab-st: $(BLISLPAB_ST_BINS) eigen-st: $(EIGEN_ST_BINS) openblas-st: $(OPENBLAS_ST_BINS) blasfeo-st: $(BLASFEO_ST_BINS) libxsmm-st: $(LIBXSMM_ST_BINS) vendor-st: $(VENDOR_ST_BINS) # --Object file rules -- # Define the implementations for which we will instantiate compilation rules. BIMPLS := blissup blislpab openblas blasfeo libxsmm vendor EIMPLS := eigen # 1 2 3 4 567 8 # test_dgemm_nn_rrr_mpn6kp_blissup_st.x # Define the function that will be used to instantiate compilation rules # for the various implementations. define make-st-rule test_$(1)gemm_$(call stripu,$(2))_$(call stripu,$(3))_$(call get-shape-dim-str,$(4),$(5),$(6),$(7))_$(8)_st.o: test_gemm.c Makefile $(CC) $(CFLAGS) $(ERRCHK) $(N_TRIALS) $(call get-pdefs,$(4)) $(call get-dt-cpp,$(1)) $(call get-tra-defs,$(2)) $(call get-sto-defs,$(3)) $(call get-shape-defs,$(4),$(5),$(6),$(7)) $(call get-imp-defs,$(8)) $(STR_ST) -c $$< -o $$@ endef # Instantiate the rule function make-st-rule() for each BLIS/BLAS/CBLAS # implementation. $(foreach dt,$(DTS), \ $(foreach tr,$(TRANS), \ $(foreach st,$(STORS), \ $(foreach sh,$(SHAPES), \ $(foreach sm,$(SMS), \ $(foreach sn,$(SNS), \ $(foreach sk,$(SKS), \ $(foreach impl,$(BIMPLS), \ $(eval $(call make-st-rule,$(dt),$(tr),$(st),$(sh),$(sm),$(sn),$(sk),$(impl))))))))))) # Define the function that will be used to instantiate compilation rules # for the various implementations. define make-eigst-rule test_$(1)gemm_$(call stripu,$(2))_$(call stripu,$(3))_$(call get-shape-dim-str,$(4),$(5),$(6),$(7))_$(8)_st.o: test_gemm.c Makefile $(CXX) $(CXXFLAGS_ST) $(ERRCHK) $(N_TRIALS) $(call get-pdefs,$(4)) $(call get-dt-cpp,$(1)) $(call get-tra-defs,$(2)) $(call get-sto-defs,$(3)) $(call get-shape-defs,$(4),$(5),$(6),$(7)) $(call get-imp-defs,$(8)) $(STR_ST) -c $$< -o $$@ endef # Instantiate the rule function make-st-rule() for each Eigen implementation. $(foreach dt,$(DTS), \ $(foreach tr,$(TRANS), \ $(foreach st,$(STORS), \ $(foreach sh,$(SHAPES), \ $(foreach sm,$(SMS), \ $(foreach sn,$(SNS), \ $(foreach sk,$(SKS), \ $(foreach impl,$(EIMPLS), \ $(eval $(call make-eigst-rule,$(dt),$(tr),$(st),$(sh),$(sm),$(sn),$(sk),$(impl))))))))))) # -- Executable file rules -- # NOTE: For the BLAS test drivers, we place the BLAS libraries before BLIS # on the link command line in case BLIS was configured with the BLAS # compatibility layer. This prevents BLIS from inadvertently getting called # for the BLAS routines we are trying to test with. test_%_blissup_st.x: test_%_blissup_st.o $(LIBBLIS_LINK) $(CC) $(strip $< $(LIBBLIS_LINK) $(LDFLAGS) -o $@) test_%_blislpab_st.x: test_%_blislpab_st.o $(LIBBLIS_LINK) $(CC) $(strip $< $(LIBBLIS_LINK) $(LDFLAGS) -o $@) test_%_eigen_st.x: test_%_eigen_st.o $(LIBBLIS_LINK) $(CXX) $(strip $< $(LIBBLIS_LINK) $(LDFLAGS) -o $@) test_%_openblas_st.x: test_%_openblas_st.o $(LIBBLIS_LINK) $(CC) $(strip $< $(OPENBLAS_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $@) test_%_blasfeo_st.x: test_%_blasfeo_st.o $(LIBBLIS_LINK) $(CC) $(strip $< $(BLASFEO_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $@) test_%_libxsmm_st.x: test_%_libxsmm_st.o $(LIBBLIS_LINK) $(CC) $(strip $< $(LIBXSMM_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $@) test_%_vendor_st.x: test_%_vendor_st.o $(LIBBLIS_LINK) $(CC) $(strip $< $(VENDOR_LIB) $(LIBBLIS_LINK) $(LDFLAGS) -o $@) # -- Clean rules -- clean: cleanx cleanx: - $(RM_F) *.x *.o blis-0.9.0/test/sup/old/supst/octave/000077500000000000000000000000001422157504600174625ustar00rootroot00000000000000blis-0.9.0/test/sup/old/supst/octave/gen_opsupnames.m000066400000000000000000000020651422157504600226660ustar00rootroot00000000000000function [ r_val1, r_val2 ] = gen_opsupnames( ops, stor, smalldims ) nops = size( ops, 1 ); smallm = smalldims( 1 ); smalln = smalldims( 2 ); smallk = smalldims( 3 ); i = 1; for io = 1:nops op = ops( io, : ); opsupnames( i+0, : ) = sprintf( '%s_%s_m%dnpkp', op, stor, smallm ); opsupnames( i+1, : ) = sprintf( '%s_%s_mpn%dkp', op, stor, smalln ); opsupnames( i+2, : ) = sprintf( '%s_%s_mpnpk%d', op, stor, smallk ); opsupnames( i+3, : ) = sprintf( '%s_%s_mpn%dk%d', op, stor, smalln, smallk ); opsupnames( i+4, : ) = sprintf( '%s_%s_m%dnpk%d', op, stor, smallm, smallk ); opsupnames( i+5, : ) = sprintf( '%s_%s_m%dn%dkp', op, stor, smallm, smalln ); opsupnames( i+6, : ) = sprintf( '%s_%s_mpnpkp', op, stor ); opnames( i+0, : ) = sprintf( '%s', op ); opnames( i+1, : ) = sprintf( '%s', op ); opnames( i+2, : ) = sprintf( '%s', op ); opnames( i+3, : ) = sprintf( '%s', op ); opnames( i+4, : ) = sprintf( '%s', op ); opnames( i+5, : ) = sprintf( '%s', op ); opnames( i+6, : ) = sprintf( '%s', op ); i = i + 7; end r_val1 = opsupnames; r_val2 = opnames; blis-0.9.0/test/sup/old/supst/octave/plot_l3sup_perf.m000066400000000000000000000232131422157504600227610ustar00rootroot00000000000000function r_val = plot_l3sup_perf( opname, ... data_blissup, ... data_blislpab, ... data_eigen, ... data_open, ... data_bfeo, ... data_xsmm, ... data_vend, vend_str, ... nth, ... rows, cols, ... cfreq, ... dfps, ... theid, impl ) %if ... %mod(theid-1,cols) == 2 || ... % ... %mod(theid-1,cols) == 3 || ... % ... %mod(theid-1,cols) == 4 || ... % 0 == 1 ... %theid >= 19 % show_plot = 0; %else show_plot = 1; %end %legend_plot_id = 11; legend_plot_id = 2*cols + 1*5; if 1 ax1 = subplot( rows, cols, theid ); hold( ax1, 'on' ); end % Set line properties. color_blissup = 'k'; lines_blissup = '-'; markr_blissup = ''; color_blislpab = 'k'; lines_blislpab = ':'; markr_blislpab = ''; color_eigen = 'm'; lines_eigen = '-.'; markr_eigen = 'o'; color_open = 'r'; lines_open = '--'; markr_open = 'o'; color_bfeo = 'c'; lines_bfeo = '-'; markr_bfeo = 'o'; color_xsmm = 'g'; lines_xsmm = '-'; markr_xsmm = 'o'; color_vend = 'b'; lines_vend = '-.'; markr_vend = '.'; % Compute the peak performance in terms of the number of double flops % executable per cycle and the clock rate. if opname(1) == 's' || opname(1) == 'c' flopspercycle = dfps * 2; else flopspercycle = dfps; end max_perf_core = (flopspercycle * cfreq) * 1; % Escape underscores in the title. title_opname = strrep( opname, '_', '\_' ); % Print the title to a string. titlename = '%s'; titlename = sprintf( titlename, title_opname ); % Set the legend strings. blissup_legend = sprintf( 'BLIS sup' ); blislpab_legend = sprintf( 'BLIS conv' ); eigen_legend = sprintf( 'Eigen' ); open_legend = sprintf( 'OpenBLAS' ); bfeo_legend = sprintf( 'BLASFEO' ); xsmm_legend = sprintf( 'libxsmm' ); %vend_legend = sprintf( 'MKL' ); %vend_legend = sprintf( 'ARMPL' ); vend_legend = vend_str; % Set axes range values. y_scale = 1.00; x_begin = 0; %x_end is set below. y_begin = 0; y_end = max_perf_core * y_scale; % Set axes names. if nth == 1 yaxisname = 'GFLOPS'; else yaxisname = 'GFLOPS/core'; end %flopscol = 4; flopscol = size( data_blissup, 2 ); msize = 5; if 1 fontsize = 12; else fontsize = 16; end linesize = 0.5; legend_loc = 'southeast'; % -------------------------------------------------------------------- % Automatically detect a column with the increasing problem size. % Then set the maximum x-axis value. for psize_col = 1:3 if data_blissup( 1, psize_col ) ~= data_blissup( 2, psize_col ) break; end end x_axis( :, 1 ) = data_blissup( :, psize_col ); % Compute the number of data points we have in the x-axis. Note that % we only use half the data points for the m = n = k column of graphs. if mod(theid-1,cols) == 6 np = size( data_blissup, 1 ) / 2; else np = size( data_blissup, 1 ); end has_xsmm = 1; if data_xsmm( 1, flopscol ) == 0.0 has_xsmm = 0; end % Grab the last x-axis value. x_end = data_blissup( np, psize_col ); %data_peak( 1, 1:2 ) = [ 0 max_perf_core ]; %data_peak( 2, 1:2 ) = [ x_end max_perf_core ]; if show_plot == 1 blissup_ln = line( x_axis( 1:np, 1 ), data_blissup( 1:np, flopscol ) / nth, ... 'Color',color_blissup, 'LineStyle',lines_blissup, ... 'LineWidth',linesize ); blislpab_ln = line( x_axis( 1:np, 1 ), data_blislpab( 1:np, flopscol ) / nth, ... 'Color',color_blislpab, 'LineStyle',lines_blislpab, ... 'LineWidth',linesize ); eigen_ln = line( x_axis( 1:np, 1 ), data_eigen( 1:np, flopscol ) / nth, ... 'Color',color_eigen, 'LineStyle',lines_eigen, ... 'LineWidth',linesize ); open_ln = line( x_axis( 1:np, 1 ), data_open( 1:np, flopscol ) / nth, ... 'Color',color_open, 'LineStyle',lines_open, ... 'LineWidth',linesize ); bfeo_ln = line( x_axis( 1:np, 1 ), data_bfeo( 1:np, flopscol ) / nth, ... 'Color',color_bfeo, 'LineStyle',lines_bfeo, ... 'LineWidth',linesize ); if has_xsmm == 1 xsmm_ln = line( x_axis( 1:np, 1 ), data_xsmm( 1:np, flopscol ) / nth, ... 'Color',color_xsmm, 'LineStyle',lines_xsmm, ... 'LineWidth',linesize ); else xsmm_ln = line( nan, nan, ... 'Color',color_xsmm, 'LineStyle',lines_xsmm, ... 'LineWidth',linesize ); end vend_ln = line( x_axis( 1:np, 1 ), data_vend( 1:np, flopscol ) / nth, ... 'Color',color_vend, 'LineStyle',lines_vend, ... 'LineWidth',linesize ); elseif theid == legend_plot_id blissup_ln = line( nan, nan, ... 'Color',color_blissup, 'LineStyle',lines_blissup, ... 'LineWidth',linesize ); blislpab_ln = line( nan, nan, ... 'Color',color_blislpab, 'LineStyle',lines_blislpab, ... 'LineWidth',linesize ); eigen_ln = line( nan, nan, ... 'Color',color_eigen, 'LineStyle',lines_eigen, ... 'LineWidth',linesize ); open_ln = line( nan, nan, ... 'Color',color_open, 'LineStyle',lines_open, ... 'LineWidth',linesize ); bfeo_ln = line( nan, nan, ... 'Color',color_bfeo, 'LineStyle',lines_bfeo, ... 'LineWidth',linesize ); xsmm_ln = line( nan, nan, ... 'Color',color_xsmm, 'LineStyle',lines_xsmm, ... 'LineWidth',linesize ); vend_ln = line( nan, nan, ... 'Color',color_vend, 'LineStyle',lines_vend, ... 'LineWidth',linesize ); end xlim( ax1, [x_begin x_end] ); ylim( ax1, [y_begin y_end] ); if 6000 <= x_end && x_end < 10000 x_tick2 = x_end - 2000; x_tick1 = x_tick2/2; xticks( ax1, [ x_tick1 x_tick2 ] ); elseif 4000 <= x_end && x_end < 6000 x_tick2 = x_end - 1000; x_tick1 = x_tick2/2; xticks( ax1, [ x_tick1 x_tick2 ] ); elseif 2000 <= x_end && x_end < 3000 x_tick2 = x_end - 400; x_tick1 = x_tick2/2; xticks( ax1, [ x_tick1 x_tick2 ] ); elseif 500 <= x_end && x_end < 1000 x_tick3 = x_end*(3/4); x_tick2 = x_end*(2/4); x_tick1 = x_end*(1/4); xticks( ax1, [ x_tick1 x_tick2 x_tick3 ] ); end if show_plot == 1 || theid == legend_plot_id if nth == 1 && theid == legend_plot_id if has_xsmm == 1 leg = legend( ... [ ... blissup_ln ... blislpab_ln ... eigen_ln ... open_ln ... bfeo_ln ... xsmm_ln ... vend_ln ... ], ... blissup_legend, ... blislpab_legend, ... eigen_legend, ... open_legend, ... bfeo_legend, ... xsmm_legend, ... vend_legend, ... 'Location', legend_loc ); set( leg,'Box','off' ); set( leg,'Color','none' ); set( leg,'Units','inches' ); if impl == 'octave' set( leg,'FontSize',fontsize ); set( leg,'Position',[15.40 4.75 1.9 1.20] ); % (1,4tl) else set( leg,'FontSize',fontsize-3 ); set( leg,'Position',[18.20 10.20 1.15 0.7 ] ); % (1,4tl) end else leg = legend( ... [ ... blissup_ln ... blislpab_ln ... eigen_ln ... open_ln ... bfeo_ln ... vend_ln ... ], ... blissup_legend, ... blislpab_legend, ... eigen_legend, ... open_legend, ... bfeo_legend, ... vend_legend, ... 'Location', legend_loc ); set( leg,'Box','off' ); set( leg,'Color','none' ); set( leg,'Units','inches' ); if impl == 'octave' set( leg,'FontSize',fontsize ); set( leg,'Position',[15.40 7.65 1.9 1.10] ); % (1,4tl) else set( leg,'FontSize',fontsize-1 ); set( leg,'Position',[18.24 10.15 1.15 0.7] ); % (1,4tl) end end set( leg,'Box','off' ); set( leg,'Color','none' ); set( leg,'Units','inches' ); % xpos ypos %set( leg,'Position',[11.32 6.36 1.15 0.7 ] ); % (1,4tl) elseif nth > 1 && theid == legend_plot_id end end set( ax1,'FontSize',fontsize ); set( ax1,'TitleFontSizeMultiplier',1.0 ); % default is 1.1. box( ax1, 'on' ); titl = title( titlename ); set( titl, 'FontWeight', 'normal' ); % default font style is now 'bold'. % The default is to align the plot title across whole figure, not the box. % This is a hack to nudge the title back to the center of the box. if impl == 'octave' tpos = get( titl, 'Position' ); % For some reason, the titles in the graphs in the last column start % off in a different relative position than the graphs in the other % columns. Here, we manually account for that. if mod(theid-1,cols) == 6 tpos(1) = tpos(1) + -10; else tpos(1) = tpos(1) + -40; end set( titl, 'Position', tpos ); set( titl, 'FontSize', fontsize ); else % impl == 'matlab' tpos = get( titl, 'Position' ); tpos(1) = tpos(1) + 90; set( titl, 'Position', tpos ); end if theid > (rows-1)*cols %xlab = xlabel( ax1,xaxisname ); %tpos = get( xlab, 'Position' ) %tpos(2) = tpos(2) + 10; %set( xlab, 'Position', tpos ); if theid == rows*cols - 6 xlab = xlabel( ax1, 'm = 6; n = k' ); elseif theid == rows*cols - 5 xlab = xlabel( ax1, 'n = 8; m = k' ); elseif theid == rows*cols - 4 xlab = xlabel( ax1, 'k = 4; m = n' ); elseif theid == rows*cols - 3 xlab = xlabel( ax1, 'm; n = 8, k = 4' ); elseif theid == rows*cols - 2 xlab = xlabel( ax1, 'n; m = 6, k = 4' ); elseif theid == rows*cols - 1 xlab = xlabel( ax1, 'k; m = 6, n = 8' ); elseif theid == rows*cols - 0 xlab = xlabel( ax1, 'm = n = k' ); end end if mod(theid-1,cols) == 0 ylab = ylabel( ax1,yaxisname ); end r_val = 0; blis-0.9.0/test/sup/old/supst/octave/plot_panel_trxsh.m000066400000000000000000000134211422157504600232260ustar00rootroot00000000000000function r_val = plot_panel_trxsh ... ( ... cfreq, ... dflopspercycle, ... nth, ... thr_str, ... dt_ch, ... stor_str, ... smalldims, ... dirpath, ... arch_str, ... vend_str, ... impl ... ) %cfreq = 1.8; %dflopspercycle = 32; % Create filename "templates" for the files that contain the performance % results. filetemp_blissup = '%s/output_%s_%s_blissup.m'; filetemp_blislpab = '%s/output_%s_%s_blislpab.m'; filetemp_eigen = '%s/output_%s_%s_eigen.m'; filetemp_open = '%s/output_%s_%s_openblas.m'; filetemp_bfeo = '%s/output_%s_%s_blasfeo.m'; filetemp_xsmm = '%s/output_%s_%s_libxsmm.m'; filetemp_vend = '%s/output_%s_%s_vendor.m'; % Create a variable name "template" for the variables contained in the % files outlined above. vartemp = 'data_%s_%s_%s( :, : )'; % Define the datatypes and operations we will be plotting. oproot = sprintf( '%cgemm', dt_ch ); ops( 1, : ) = sprintf( '%s_nn', oproot ); ops( 2, : ) = sprintf( '%s_nt', oproot ); ops( 3, : ) = sprintf( '%s_tn', oproot ); ops( 4, : ) = sprintf( '%s_tt', oproot ); % Generate datatype-specific operation names from the set of operations % and datatypes. [ opsupnames, opnames ] = gen_opsupnames( ops, stor_str, smalldims ); n_opsupnames = size( opsupnames, 1 ); %opsupnames %opnames %return if 1 == 1 %fig = figure('Position', [100, 100, 2400, 1500]); fig = figure('Position', [100, 100, 2400, 1200]); orient( fig, 'portrait' ); set(gcf,'PaperUnits', 'inches'); if impl == 'matlab' set(gcf,'PaperSize', [11.5 20.4]); set(gcf,'PaperPosition', [0 0 11.5 20.4]); set(gcf,'PaperPositionMode','manual'); else % impl == 'octave' % octave 4.x set(gcf,'PaperSize', [12 22.0]); set(gcf,'PaperPositionMode','auto'); end set(gcf,'PaperOrientation','landscape'); end % Iterate over the list of datatype-specific operation names. for opi = 1:n_opsupnames %for opi = 1:1 % Grab the current datatype combination. opsupname = opsupnames( opi, : ); opname = opnames( opi, : ); str = sprintf( 'Plotting %2d: %s', opi, opsupname ); disp(str); % Construct filenames for the data files from templates. file_blissup = sprintf( filetemp_blissup, dirpath, thr_str, opsupname ); file_blislpab = sprintf( filetemp_blislpab, dirpath, thr_str, opsupname ); file_eigen = sprintf( filetemp_eigen, dirpath, thr_str, opsupname ); file_open = sprintf( filetemp_open, dirpath, thr_str, opsupname ); file_bfeo = sprintf( filetemp_bfeo, dirpath, thr_str, opsupname ); file_vend = sprintf( filetemp_vend, dirpath, thr_str, opsupname ); % Load the data files. %str = sprintf( ' Loading %s', file_blissup ); disp(str); run( file_blissup ) run( file_blislpab ) run( file_eigen ) run( file_open ) run( file_bfeo ) run( file_vend ) % Construct variable names for the variables in the data files. var_blissup = sprintf( vartemp, thr_str, opname, 'blissup' ); var_blislpab = sprintf( vartemp, thr_str, opname, 'blislpab' ); var_eigen = sprintf( vartemp, thr_str, opname, 'eigen' ); var_open = sprintf( vartemp, thr_str, opname, 'openblas' ); var_bfeo = sprintf( vartemp, thr_str, opname, 'blasfeo' ); var_vend = sprintf( vartemp, thr_str, opname, 'vendor' ); % Use eval() to instantiate the variable names constructed above, % copying each to a simplified name. data_blissup = eval( var_blissup ); % e.g. data_st_dgemm_blissup( :, : ); data_blislpab = eval( var_blislpab ); % e.g. data_st_dgemm_blislpab( :, : ); data_eigen = eval( var_eigen ); % e.g. data_st_dgemm_eigen( :, : ); data_open = eval( var_open ); % e.g. data_st_dgemm_openblas( :, : ); data_bfeo = eval( var_bfeo ); % e.g. data_st_dgemm_blasfeo( :, : ); data_vend = eval( var_vend ); % e.g. data_st_dgemm_vendor( :, : ); if stor_str == 'ccc' % Only read xsmm data for the column storage case, since that's the % only format that libxsmm supports. file_xsmm = sprintf( filetemp_xsmm, dirpath, thr_str, opsupname ); run( file_xsmm ) var_xsmm = sprintf( vartemp, thr_str, opname, 'libxsmm' ); data_xsmm = eval( var_xsmm ); % e.g. data_st_dgemm_libxsmm( :, : ); else % Set the data variable to zeros using the same dimensions as the other % variables. data_xsmm = zeros( size( data_blissup, 1 ), ... size( data_blissup, 2 ) ); end %str = sprintf( ' Reading %s', var_blissup ); disp(str); %str = sprintf( ' Reading %s', var_blislpab ); disp(str); %str = sprintf( ' Reading %s', var_eigen ); disp(str); %str = sprintf( ' Reading %s', var_open ); disp(str); %str = sprintf( ' Reading %s', var_bfeo ); disp(str); %str = sprintf( ' Reading %s', var_xsmm ); disp(str); %str = sprintf( ' Reading %s', var_vend ); disp(str); % Plot one result in an m x n grid of plots, via the subplot() % function. if 1 == 1 plot_l3sup_perf( opsupname, ... data_blissup, ... data_blislpab, ... data_eigen, ... data_open, ... data_bfeo, ... data_xsmm, ... data_vend, vend_str, ... nth, ... 4, 7, ... cfreq, ... dflopspercycle, ... opi, impl ); clear data_st_*gemm_*; clear data_blissup; clear data_blislpab; clear data_eigen; clear data_open; clear data_bfeo; clear data_xsmm; clear data_vend; end end % Construct the name of the file to which we will output the graph. outfile = sprintf( 'l3sup_%s_%s_%s_nt%d.pdf', oproot, stor_str, arch_str, nth ); % Output the graph to pdf format. %print(gcf, 'gemm_md','-fillpage','-dpdf'); %print(gcf, outfile,'-bestfit','-dpdf'); if impl == 'octave' print(gcf, outfile); else % if impl == 'matlab' print(gcf, outfile,'-bestfit','-dpdf'); end blis-0.9.0/test/sup/old/supst/octave/runthese.m000066400000000000000000000007101422157504600214730ustar00rootroot00000000000000 % kabylake plot_panel_trxsh(3.80,16,1,'st','d','rrr',[ 6 8 4 ],'../results/kabylake/20200302/mnkt100000_st','kbl','MKL','octave'); close; clear all; % haswell plot_panel_trxsh(3.5,16,1,'st','d','rrr',[ 6 8 4 ],'../results/haswell/20200302/mnkt100000_st','has','MKL','octave'); close; clear all; % epyc plot_panel_trxsh(3.00, 8,1,'st','d','rrr',[ 6 8 4 ],'../results/epyc/20200302/mnkt100000_st','epyc','MKL','octave'); close; clear all; blis-0.9.0/test/sup/old/supst/runme.sh000077500000000000000000000053001422157504600176640ustar00rootroot00000000000000#!/bin/bash # File pefixes. exec_root="test" out_root="output" # Placeholder until we add multithreading. nt=1 # Delay between test cases. delay=0.02 # Threadedness to test. threads="st" # Datatypes to test. #dts="d s" dts="d" # Operations to test. ops="gemm" # Transpose combintions to test. trans="nn nt tn tt" # Storage combinations to test. #stors="rrr rrc rcr rcc crr crc ccr ccc" stors="rrr ccc" # Problem shapes to test. shapes="sll lsl lls lss sls ssl lll" # FGVZ: figure out how to probe what's in the directory and # execute everything that's there? sms="6" sns="8" sks="4" # Implementations to test. impls="vendor blissup blislpab openblas eigen libxsmm blasfeo" #impls="vendor" #impls="blissup" #impls="blislpab" #impls="openblas" #impls="eigen" #impls="libxsmm" #impls="blasfeo" # Example: test_dgemm_nn_rrc_m6npkp_blissup_st.x for th in ${threads}; do for dt in ${dts}; do for op in ${ops}; do for tr in ${trans}; do for st in ${stors}; do for sh in ${shapes}; do for sm in ${sms}; do for sn in ${sns}; do for sk in ${sks}; do for im in ${impls}; do # Limit execution of non-BLIS implementations to # rrr/ccc storage cases. if [ "${im:0:4}" != "blis" ] && \ [ "${st}" != "rrr" ] && \ [ "${st}" != "ccc" ]; then continue; fi # Further limit execution of libxsmm to # ccc storage cases. if [ "${im:0:7}" = "libxsmm" ] && \ [ "${st}" != "ccc" ]; then continue; fi # Extract the shape chars for m, n, k. chm=${sh:0:1} chn=${sh:1:1} chk=${sh:2:1} # Construct the shape substring (e.g. m6npkp) shstr="" if [ ${chm} = "s" ]; then shstr="${shstr}m${sm}" else shstr="${shstr}mp" fi if [ ${chn} = "s" ]; then shstr="${shstr}n${sn}" else shstr="${shstr}np" fi if [ ${chk} = "s" ]; then shstr="${shstr}k${sk}" else shstr="${shstr}kp" fi # Ex: test_dgemm_nn_rrc_m6npkp_blissup_st.x # Construct the name of the test executable. exec_name="${exec_root}_${dt}${op}_${tr}_${st}_${shstr}_${im}_${th}.x" # Construct the name of the output file. out_file="${out_root}_${th}_${dt}${op}_${tr}_${st}_${shstr}_${im}.m" echo "Running (nt = ${nt}) ./${exec_name} > ${out_file}" # Run executable. ./${exec_name} > ${out_file} sleep ${delay} done done done done done done done done done done blis-0.9.0/test/sup/old/supst/test_gemm.c000066400000000000000000000420121422157504600203300ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2019, Advanced Micro Devices, Inc. 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 The University of Texas 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 COPYRIGHT HOLDER 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. */ #include #ifdef EIGEN #define BLIS_DISABLE_BLAS_DEFS #include "blis.h" #include //#include using namespace Eigen; #else #include "blis.h" #endif //#define PRINT int main( int argc, char** argv ) { bli_init(); #ifndef ERROR_CHECK bli_error_checking_level_set( BLIS_NO_ERROR_CHECKING ); #endif dim_t n_trials = N_TRIALS; num_t dt = DT; #if 1 dim_t p_begin = P_BEGIN; dim_t p_max = P_MAX; dim_t p_inc = P_INC; #else dim_t p_begin = 4; dim_t p_max = 40; dim_t p_inc = 4; #endif #if 1 dim_t m_input = M_DIM; dim_t n_input = N_DIM; dim_t k_input = K_DIM; #else p_begin = p_inc = 32; dim_t m_input = 6; dim_t n_input = -1; dim_t k_input = -1; #endif #if 1 trans_t transa = TRANSA; trans_t transb = TRANSB; #else trans_t transa = BLIS_NO_TRANSPOSE; trans_t transb = BLIS_NO_TRANSPOSE; #endif #if 1 stor3_t sc = STOR3; #else stor3_t sc = BLIS_RRR; #endif inc_t rs_c, cs_c; inc_t rs_a, cs_a; inc_t rs_b, cs_b; if ( sc == BLIS_RRR ) { rs_c = cs_c = -1; rs_a = cs_a = -1; rs_b = cs_b = -1; } else if ( sc == BLIS_RRC ) { rs_c = cs_c = -1; rs_a = cs_a = -1; rs_b = cs_b = 0; } else if ( sc == BLIS_RCR ) { rs_c = cs_c = -1; rs_a = cs_a = 0; rs_b = cs_b = -1; } else if ( sc == BLIS_RCC ) { rs_c = cs_c = -1; rs_a = cs_a = 0; rs_b = cs_b = 0; } else if ( sc == BLIS_CRR ) { rs_c = cs_c = 0; rs_a = cs_a = -1; rs_b = cs_b = -1; } else if ( sc == BLIS_CRC ) { rs_c = cs_c = 0; rs_a = cs_a = -1; rs_b = cs_b = 0; } else if ( sc == BLIS_CCR ) { rs_c = cs_c = 0; rs_a = cs_a = 0; rs_b = cs_b = -1; } else if ( sc == BLIS_CCC ) { rs_c = cs_c = 0; rs_a = cs_a = 0; rs_b = cs_b = 0; } else { bli_abort(); } f77_int cbla_storage; if ( sc == BLIS_RRR ) cbla_storage = CblasRowMajor; else if ( sc == BLIS_CCC ) cbla_storage = CblasColMajor; else cbla_storage = -1; ( void )cbla_storage; char dt_ch; // Choose the char corresponding to the requested datatype. if ( bli_is_float( dt ) ) dt_ch = 's'; else if ( bli_is_double( dt ) ) dt_ch = 'd'; else if ( bli_is_scomplex( dt ) ) dt_ch = 'c'; else dt_ch = 'z'; f77_char f77_transa; f77_char f77_transb; char transal, transbl; bli_param_map_blis_to_netlib_trans( transa, &f77_transa ); bli_param_map_blis_to_netlib_trans( transb, &f77_transb ); transal = tolower( f77_transa ); transbl = tolower( f77_transb ); f77_int cbla_transa = ( transal == 'n' ? CblasNoTrans : CblasTrans ); f77_int cbla_transb = ( transbl == 'n' ? CblasNoTrans : CblasTrans ); ( void )cbla_transa; ( void )cbla_transb; dim_t p; // Begin with initializing the last entry to zero so that // matlab allocates space for the entire array once up-front. for ( p = p_begin; p + p_inc <= p_max; p += p_inc ) ; printf( "data_%s_%cgemm_%c%c_%s", THR_STR, dt_ch, transal, transbl, STR ); printf( "( %2lu, 1:4 ) = [ %4lu %4lu %4lu %7.2f ];\n", ( unsigned long )(p - p_begin)/p_inc + 1, ( unsigned long )0, ( unsigned long )0, ( unsigned long )0, 0.0 ); //for ( p = p_begin; p <= p_max; p += p_inc ) for ( p = p_max; p_begin <= p; p -= p_inc ) { obj_t a, b, c; obj_t c_save; obj_t alpha, beta; dim_t m, n, k; if ( m_input < 0 ) m = p / ( dim_t )abs(m_input); else m = ( dim_t ) m_input; if ( n_input < 0 ) n = p / ( dim_t )abs(n_input); else n = ( dim_t ) n_input; if ( k_input < 0 ) k = p / ( dim_t )abs(k_input); else k = ( dim_t ) k_input; bli_obj_create( dt, 1, 1, 0, 0, &alpha ); bli_obj_create( dt, 1, 1, 0, 0, &beta ); bli_obj_create( dt, m, n, rs_c, cs_c, &c ); bli_obj_create( dt, m, n, rs_c, cs_c, &c_save ); if ( bli_does_notrans( transa ) ) bli_obj_create( dt, m, k, rs_a, cs_a, &a ); else bli_obj_create( dt, k, m, rs_a, cs_a, &a ); if ( bli_does_notrans( transb ) ) bli_obj_create( dt, k, n, rs_b, cs_b, &b ); else bli_obj_create( dt, n, k, rs_b, cs_b, &b ); bli_randm( &a ); bli_randm( &b ); bli_randm( &c ); bli_obj_set_conjtrans( transa, &a ); bli_obj_set_conjtrans( transb, &b ); bli_setsc( (1.0/1.0), 0.0, &alpha ); bli_setsc( (1.0/1.0), 0.0, &beta ); bli_copym( &c, &c_save ); #ifdef EIGEN double alpha_r, alpha_i; bli_getsc( &alpha, &alpha_r, &alpha_i ); void* ap = bli_obj_buffer_at_off( &a ); void* bp = bli_obj_buffer_at_off( &b ); void* cp = bli_obj_buffer_at_off( &c ); const int os_a = ( bli_obj_is_col_stored( &a ) ? bli_obj_col_stride( &a ) : bli_obj_row_stride( &a ) ); const int os_b = ( bli_obj_is_col_stored( &b ) ? bli_obj_col_stride( &b ) : bli_obj_row_stride( &b ) ); const int os_c = ( bli_obj_is_col_stored( &c ) ? bli_obj_col_stride( &c ) : bli_obj_row_stride( &c ) ); Stride stride_a( os_a, 1 ); Stride stride_b( os_b, 1 ); Stride stride_c( os_c, 1 ); #if defined(IS_FLOAT) #elif defined (IS_DOUBLE) #ifdef A_STOR_R typedef Matrix MatrixXd_A; #else typedef Matrix MatrixXd_A; #endif #ifdef B_STOR_R typedef Matrix MatrixXd_B; #else typedef Matrix MatrixXd_B; #endif #ifdef C_STOR_R typedef Matrix MatrixXd_C; #else typedef Matrix MatrixXd_C; #endif #ifdef A_NOTRANS // A is not transposed Map > A( ( double* )ap, m, k, stride_a ); #else // A is transposed Map > A( ( double* )ap, k, m, stride_a ); #endif #ifdef B_NOTRANS // B is not transposed Map > B( ( double* )bp, k, n, stride_b ); #else // B is transposed Map > B( ( double* )bp, n, k, stride_b ); #endif Map > C( ( double* )cp, m, n, stride_c ); #endif #endif double dtime_save = DBL_MAX; for ( dim_t r = 0; r < n_trials; ++r ) { bli_copym( &c_save, &c ); double dtime = bli_clock(); #ifdef EIGEN #ifdef A_NOTRANS #ifdef B_NOTRANS C.noalias() += alpha_r * A * B; #else // B_TRANS C.noalias() += alpha_r * A * B.transpose(); #endif #else // A_TRANS #ifdef B_NOTRANS C.noalias() += alpha_r * A.transpose() * B; #else // B_TRANS C.noalias() += alpha_r * A.transpose() * B.transpose(); #endif #endif #endif #ifdef BLIS #ifdef SUP // Allow sup. bli_gemm( &alpha, &a, &b, &beta, &c ); #else // Disable sup and use the expert interface. rntm_t rntm = BLIS_RNTM_INITIALIZER; bli_rntm_disable_l3_sup( &rntm ); bli_gemm_ex( &alpha, &a, &b, &beta, &c, NULL, &rntm ); #endif #endif #ifdef BLAS if ( bli_is_float( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); float* alphap = ( float* )bli_obj_buffer( &alpha ); float* ap = ( float* )bli_obj_buffer( &a ); float* bp = ( float* )bli_obj_buffer( &b ); float* betap = ( float* )bli_obj_buffer( &beta ); float* cp = ( float* )bli_obj_buffer( &c ); #ifdef XSMM libxsmm_sgemm( &f77_transa, #else sgemm_( &f77_transa, #endif &f77_transb, &mm, &nn, &kk, alphap, ap, &lda, bp, &ldb, betap, cp, &ldc ); } else if ( bli_is_double( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); double* alphap = ( double* )bli_obj_buffer( &alpha ); double* ap = ( double* )bli_obj_buffer( &a ); double* bp = ( double* )bli_obj_buffer( &b ); double* betap = ( double* )bli_obj_buffer( &beta ); double* cp = ( double* )bli_obj_buffer( &c ); #ifdef XSMM libxsmm_dgemm( &f77_transa, #else dgemm_( &f77_transa, #endif &f77_transb, &mm, &nn, &kk, alphap, ap, &lda, bp, &ldb, betap, cp, &ldc ); } else if ( bli_is_scomplex( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); scomplex* alphap = ( scomplex* )bli_obj_buffer( &alpha ); scomplex* ap = ( scomplex* )bli_obj_buffer( &a ); scomplex* bp = ( scomplex* )bli_obj_buffer( &b ); scomplex* betap = ( scomplex* )bli_obj_buffer( &beta ); scomplex* cp = ( scomplex* )bli_obj_buffer( &c ); #ifdef XSMM libxsmm_cgemm( &f77_transa, #else cgemm_( &f77_transa, #endif &f77_transb, &mm, &nn, &kk, alphap, ap, &lda, bp, &ldb, betap, cp, &ldc ); } else if ( bli_is_dcomplex( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); dcomplex* alphap = ( dcomplex* )bli_obj_buffer( &alpha ); dcomplex* ap = ( dcomplex* )bli_obj_buffer( &a ); dcomplex* bp = ( dcomplex* )bli_obj_buffer( &b ); dcomplex* betap = ( dcomplex* )bli_obj_buffer( &beta ); dcomplex* cp = ( dcomplex* )bli_obj_buffer( &c ); #ifdef XSMM libxsmm_zgemm( &f77_transa, #else zgemm_( &f77_transa, #endif &f77_transb, &mm, &nn, &kk, alphap, ap, &lda, bp, &ldb, betap, cp, &ldc ); } #endif #ifdef CBLAS if ( bli_is_float( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); f77_int nn = bli_obj_width( &c ); #ifdef C_STOR_R f77_int lda = bli_obj_row_stride( &a ); f77_int ldb = bli_obj_row_stride( &b ); f77_int ldc = bli_obj_row_stride( &c ); #else f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); #endif float* alphap = bli_obj_buffer( &alpha ); float* ap = bli_obj_buffer( &a ); float* bp = bli_obj_buffer( &b ); float* betap = bli_obj_buffer( &beta ); float* cp = bli_obj_buffer( &c ); cblas_sgemm( cbla_storage, cbla_transa, cbla_transb, mm, nn, kk, *alphap, ap, lda, bp, ldb, *betap, cp, ldc ); } else if ( bli_is_double( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); f77_int nn = bli_obj_width( &c ); #ifdef C_STOR_R f77_int lda = bli_obj_row_stride( &a ); f77_int ldb = bli_obj_row_stride( &b ); f77_int ldc = bli_obj_row_stride( &c ); #else f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); #endif double* alphap = bli_obj_buffer( &alpha ); double* ap = bli_obj_buffer( &a ); double* bp = bli_obj_buffer( &b ); double* betap = bli_obj_buffer( &beta ); double* cp = bli_obj_buffer( &c ); cblas_dgemm( cbla_storage, cbla_transa, cbla_transb, mm, nn, kk, *alphap, ap, lda, bp, ldb, *betap, cp, ldc ); } else if ( bli_is_scomplex( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); f77_int nn = bli_obj_width( &c ); #ifdef C_STOR_R f77_int lda = bli_obj_row_stride( &a ); f77_int ldb = bli_obj_row_stride( &b ); f77_int ldc = bli_obj_row_stride( &c ); #else f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); #endif scomplex* alphap = bli_obj_buffer( &alpha ); scomplex* ap = bli_obj_buffer( &a ); scomplex* bp = bli_obj_buffer( &b ); scomplex* betap = bli_obj_buffer( &beta ); scomplex* cp = bli_obj_buffer( &c ); cblas_cgemm( cbla_storage, cbla_transa, cbla_transb, mm, nn, kk, alphap, ap, lda, bp, ldb, betap, cp, ldc ); } else if ( bli_is_dcomplex( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); f77_int nn = bli_obj_width( &c ); #ifdef C_STOR_R f77_int lda = bli_obj_row_stride( &a ); f77_int ldb = bli_obj_row_stride( &b ); f77_int ldc = bli_obj_row_stride( &c ); #else f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); #endif dcomplex* alphap = bli_obj_buffer( &alpha ); dcomplex* ap = bli_obj_buffer( &a ); dcomplex* bp = bli_obj_buffer( &b ); dcomplex* betap = bli_obj_buffer( &beta ); dcomplex* cp = bli_obj_buffer( &c ); cblas_zgemm( cbla_storage, cbla_transa, cbla_transb, mm, nn, kk, alphap, ap, lda, bp, ldb, betap, cp, ldc ); } #endif dtime_save = bli_clock_min_diff( dtime_save, dtime ); } double gflops = ( 2.0 * m * k * n ) / ( dtime_save * 1.0e9 ); if ( bli_is_complex( dt ) ) gflops *= 4.0; printf( "data_%s_%cgemm_%c%c_%s", THR_STR, dt_ch, transal, transbl, STR ); printf( "( %2lu, 1:4 ) = [ %4lu %4lu %4lu %7.2f ];\n", ( unsigned long )(p - p_begin)/p_inc + 1, ( unsigned long )m, ( unsigned long )n, ( unsigned long )k, gflops ); bli_obj_free( &alpha ); bli_obj_free( &beta ); bli_obj_free( &a ); bli_obj_free( &b ); bli_obj_free( &c ); bli_obj_free( &c_save ); } //bli_finalize(); return 0; } blis-0.9.0/test/sup/runme.sh000077500000000000000000000221021422157504600157270ustar00rootroot00000000000000#!/bin/bash # File pefixes. exec_root="test" out_root="output" #sys="blis" #sys="lonestar5" #sys="ul252" #sys="ul264" sys="ul2128" if [ ${sys} = "blis" ]; then export GOMP_CPU_AFFINITY="0-3" numactl="" nt=4 elif [ ${sys} = "lonestar5" ]; then export GOMP_CPU_AFFINITY="0-23" numactl="" nt=12 elif [ ${sys} = "ul252" ]; then export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/home/field/intel/mkl/lib/intel64" export GOMP_CPU_AFFINITY="0-51" numactl="numactl --interleave=all" nt=26 elif [ ${sys} = "ul264" ]; then export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/home/field/intel/mkl/lib/intel64" export GOMP_CPU_AFFINITY="0-63" numactl="numactl --interleave=all" nt=32 elif [ ${sys} = "ul2128" ]; then export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/home/field/intel/mkl/lib/intel64" export GOMP_CPU_AFFINITY="0-127" numactl="numactl --interleave=all" nt=32 fi # Delay between test cases. delay=0.02 # Threadedness to test. #threads="st mt" threads="st" # Datatypes to test. dts="s d" # Operations to test. ops="gemm" # Transpose combintions to test. trans="nn nt tn tt" # Storage combinations to test. # NOTE: mixed storage cases are not yet implemented in test_gemm.c. #stors="rrr rrc rcr rcc crr crc ccr ccc" stors="rrr ccc" # Problem shapes to test. shapes="sll lsl lls lss sls ssl lll" # Small problem dimensions to use. # FGVZ: figure out how to probe what's in the directory and # execute everything that's there? # st, single real sms_st_s="6" sns_st_s="16" sks_st_s="4" # st, double real sms_st_d="6" sns_st_d="8" sks_st_d="4" # mt, single real sms_mt_s="6" sns_mt_s="16" sks_mt_s="10" # mt, double real sms_mt_d="6" sns_mt_d="8" sks_mt_d="10" # Leading dimensions to use (small or large). # When a leading dimension is large, it is constant and set to the largest # problem size that will be run. #ldims="s l" ldims="s" # Packing combinations for blissup. The first char encodes the packing status # of matrix A and the second char encodes the packing status of matrix B. # NOTE: This string must always contain 'uu' if other implementations are also # being tested at the same time. #pcombos="uu up pu pp" pcombos="uu" # Implementations to test. impls="vendor blissup blisconv openblas eigen blasfeo libxsmm" #impls="vendor blissup blisconv openblas eigen" #impls="vendor" #impls="blissup" #impls="blisconv" #impls="openblas" #impls="eigen" #impls="blasfeo" # Save a copy of GOMP_CPU_AFFINITY so that if we have to unset it, we can # restore the value. GOMP_CPU_AFFINITYsave=${GOMP_CPU_AFFINITY} # Example: test_dgemm_nn_rrc_m6npkp_blissup_st.x for th in ${threads}; do for dt in ${dts}; do # Choose the small m, n, and k values based on the threadedness and # datatype currently being executed. if [ ${th} = "st" ]; then if [ ${dt} = "s" ]; then sms=${sms_st_s} sns=${sns_st_s} sks=${sks_st_s} elif [ ${dt} = "d" ]; then sms=${sms_st_d} sns=${sns_st_d} sks=${sks_st_d} else exit 1 fi elif [ ${th} = "mt" ]; then if [ ${dt} = "s" ]; then sms=${sms_mt_s} sns=${sns_mt_s} sks=${sks_mt_s} elif [ ${dt} = "d" ]; then sms=${sms_mt_d} sns=${sns_mt_d} sks=${sks_mt_d} else exit 1 fi fi for op in ${ops}; do for tr in ${trans}; do for st in ${stors}; do for sh in ${shapes}; do for sm in ${sms}; do for sn in ${sns}; do for sk in ${sks}; do for ld in ${ldims}; do for im in ${impls}; do for pc in ${pcombos}; do if [ "${th}" = "mt" ]; then # Prohibit attempts to run blasfeo or libxsmm as # multithreaded. if [ "${im}" = "blasfeo" ] || \ [ "${im}" = "libxsmm" ]; then continue; fi # Specify the multithreading depending on which # implementation is about to be tested. if [ "${im:0:4}" = "blis" ]; then unset OMP_NUM_THREADS export BLIS_NUM_THREADS=${nt} elif [ "${im}" = "openblas" ]; then unset OMP_NUM_THREADS export OPENBLAS_NUM_THREADS=${nt} elif [ "${im}" = "eigen" ]; then export OMP_NUM_THREADS=${nt} elif [ "${im}" = "vendor" ]; then unset OMP_NUM_THREADS export MKL_NUM_THREADS=${nt} fi export nt_use=${nt} else # if [ "${th}" = "st" ]; # Use single-threaded execution. export OMP_NUM_THREADS=1 export BLIS_NUM_THREADS=1 export OPENBLAS_NUM_THREADS=1 export MKL_NUM_THREADS=1 export nt_use=1 fi # Isolate the individual chars in the current pcombo # string. packa=${pc:0:1} packb=${pc:1:1} # For blissup implementations, set the BLIS_PACK_A and # BLIS_PACK_B environment variables according to the # chars in the current pcombo string. if [ "${im:0:7}" = "blissup" ]; then # Set BLIS_PACK_A if the pcombo char is 'p'; otherwise # unset the variable altogether. if [ ${packa} = "p" ]; then export BLIS_PACK_A=1 else unset BLIS_PACK_A fi # Set BLIS_PACK_B if the pcombo char is 'p'; otherwise # unset the variable altogether. if [ ${packb} = "p" ]; then export BLIS_PACK_B=1 else unset BLIS_PACK_B fi else # Unset the variables for non-blissup implementations, # just to be paranoid-safe. unset BLIS_PACK_A unset BLIS_PACK_B fi # Limit execution of non-blissup implementations to the # 'uu' packing combination. (Those implementations don't # use the pcombos string, but since we iterate over its # words for all implementations, we have to designate one # of them as a placeholder to allow those implementations # to execute. The 'uu' string was chosen over the 'pp' # string because it's more likely that this script will be # used to run blissup on unpacked matrices, and so the # sorting for the output files is nicer if the non-blissup # implementations use the 'uu' string, even if it's more # likely that those implementations use packing. Think of # 'uu' as encoding the idea that explicit packing was not # requested.) if [ "${im:0:7}" != "blissup" ] && \ [ "${pc}" != "uu" ]; then continue; fi # Multithreaded OpenBLAS seems to have a problem # running properly if GOMP_CPU_AFFINITY is set. # So we temporarily unset it here if we are about # to execute OpenBLAS, but otherwise restore it. if [ ${im} = "openblas" ]; then unset GOMP_CPU_AFFINITY else export GOMP_CPU_AFFINITY="${GOMP_CPU_AFFINITYsave}" fi # Limit execution of non-BLIS implementations to # rrr/ccc storage cases. if [ "${im:0:4}" != "blis" ] && \ [ "${st}" != "rrr" ] && \ [ "${st}" != "ccc" ]; then continue; fi # Further limit execution of libxsmm to # ccc storage cases. if [ "${im:0:7}" = "libxsmm" ] && \ [ "${st}" != "ccc" ]; then continue; fi # Extract the shape chars for m, n, k. chm=${sh:0:1} chn=${sh:1:1} chk=${sh:2:1} # Construct the shape substring (e.g. m6npkp) shstr="" if [ ${chm} = "s" ]; then shstr="${shstr}m${sm}" else shstr="${shstr}mp" fi if [ ${chn} = "s" ]; then shstr="${shstr}n${sn}" else shstr="${shstr}np" fi if [ ${chk} = "s" ]; then shstr="${shstr}k${sk}" else shstr="${shstr}kp" fi # Construct the ldim substring (e.g. lds or ldl) ldstr="ld${ld}" # Construct the pack substring (e.g. uaub, uapb, paub, or papb) packstr="${packa}a${packb}b" # Ex: test_dgemm_nn_rrc_m6npkp_blissup_st.x # Ex: test_dgemm_nt_rrr_m6npkp_ldl_blissup_st.x # Construct the name of the test executable. exec_name="${exec_root}_${dt}${op}_${tr}_${st}_${shstr}_${ldstr}_${im}_${th}.x" # Construct the name of the output file. out_file="${out_root}_${th}_${dt}${op}_${tr}_${st}_${shstr}_${ldstr}_${packstr}_${im}.m" echo "Running (nt = ${nt_use}) ${numactl} ./${exec_name} > ${out_file}" # Run executable. ${numactl} ./${exec_name} > ${out_file} sleep ${delay} done done done done done done done done done done done done blis-0.9.0/test/sup/test_gemm.c000066400000000000000000000532041422157504600164010ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2019, Advanced Micro Devices, Inc. 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 The University of Texas 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 COPYRIGHT HOLDER 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. */ #include #ifdef EIGEN #define BLIS_DISABLE_BLAS_DEFS #include "blis.h" #include //#include using namespace Eigen; #else #include "blis.h" #endif //#define PRINT int main( int argc, char** argv ) { rntm_t rntm_g; bli_init(); // Copy the global rntm_t object so that we can use it later when disabling // sup. Starting with a copy of the global rntm_t is actually necessary; // if we start off with a locally-initialized rntm_t, it will not contain // the ways of parallelism that were conveyed via environment variables, // which is necessary when running this driver with multiple BLIS threads. bli_rntm_init_from_global( &rntm_g ); #ifndef ERROR_CHECK bli_error_checking_level_set( BLIS_NO_ERROR_CHECKING ); #endif dim_t n_trials = N_TRIALS; num_t dt = DT; #if 1 dim_t p_begin = P_BEGIN; dim_t p_max = P_MAX; dim_t p_inc = P_INC; #else dim_t p_begin = 4; dim_t p_max = 40; dim_t p_inc = 4; #endif #if 1 dim_t m_input = M_DIM; dim_t n_input = N_DIM; dim_t k_input = K_DIM; #else p_begin = p_inc = 32; dim_t m_input = 6; dim_t n_input = -1; dim_t k_input = -1; #endif #if 1 trans_t transa = TRANSA; trans_t transb = TRANSB; #else trans_t transa = BLIS_NO_TRANSPOSE; trans_t transb = BLIS_NO_TRANSPOSE; #endif #if 1 stor3_t sc = STOR3; #else stor3_t sc = BLIS_RRR; #endif inc_t rs_c, cs_c; inc_t rs_a, cs_a; inc_t rs_b, cs_b; f77_int cbla_storage; if ( sc == BLIS_RRR ) cbla_storage = CblasRowMajor; else if ( sc == BLIS_CCC ) cbla_storage = CblasColMajor; else cbla_storage = -1; ( void )cbla_storage; char dt_ch; // Choose the char corresponding to the requested datatype. if ( bli_is_float( dt ) ) dt_ch = 's'; else if ( bli_is_double( dt ) ) dt_ch = 'd'; else if ( bli_is_scomplex( dt ) ) dt_ch = 'c'; else dt_ch = 'z'; f77_char f77_transa; f77_char f77_transb; char transal, transbl; bli_param_map_blis_to_netlib_trans( transa, &f77_transa ); bli_param_map_blis_to_netlib_trans( transb, &f77_transb ); transal = tolower( f77_transa ); transbl = tolower( f77_transb ); f77_int cbla_transa = ( transal == 'n' ? CblasNoTrans : CblasTrans ); f77_int cbla_transb = ( transbl == 'n' ? CblasNoTrans : CblasTrans ); ( void )cbla_transa; ( void )cbla_transb; dim_t p; // Begin with initializing the last entry to zero so that // matlab allocates space for the entire array once up-front. for ( p = p_begin; p + p_inc <= p_max; p += p_inc ) ; printf( "data_%s_%cgemm_%c%c_%s", THR_STR, dt_ch, transal, transbl, STR ); printf( "( %2lu, 1:4 ) = [ %4lu %4lu %4lu %7.2f ];\n", ( unsigned long )(p - p_begin)/p_inc + 1, ( unsigned long )0, ( unsigned long )0, ( unsigned long )0, 0.0 ); // Flush the initialization-inducing statement above so there is // at least one line of output even if the implementation crashes. fflush( stdout ); //for ( p = p_begin; p <= p_max; p += p_inc ) for ( p = p_max; p_begin <= p; p -= p_inc ) { obj_t a, b, c; obj_t c_save; obj_t alpha, beta; dim_t m, n, k; if ( m_input < 0 ) m = p / ( dim_t )abs(m_input); else m = ( dim_t ) m_input; if ( n_input < 0 ) n = p / ( dim_t )abs(n_input); else n = ( dim_t ) n_input; if ( k_input < 0 ) k = p / ( dim_t )abs(k_input); else k = ( dim_t ) k_input; #ifdef LDIM_SMALL // Setting the row and column strides of a matrix to '0' is a shorthand // request for column storage; using '-1' is shorthand for row storage. //else if ( sc == BLIS_RRC ) { rs_c = cs_c = -1; rs_a = cs_a = -1; rs_b = cs_b = 0; } //else if ( sc == BLIS_RCR ) { rs_c = cs_c = -1; rs_a = cs_a = 0; rs_b = cs_b = -1; } //else if ( sc == BLIS_RCC ) { rs_c = cs_c = -1; rs_a = cs_a = 0; rs_b = cs_b = 0; } //else if ( sc == BLIS_CRR ) { rs_c = cs_c = 0; rs_a = cs_a = -1; rs_b = cs_b = -1; } //else if ( sc == BLIS_CRC ) { rs_c = cs_c = 0; rs_a = cs_a = -1; rs_b = cs_b = 0; } //else if ( sc == BLIS_CCR ) { rs_c = cs_c = 0; rs_a = cs_a = 0; rs_b = cs_b = -1; } if ( sc == BLIS_RRR ) { rs_c = -1; rs_a = -1; rs_b = -1; cs_c = -1; cs_a = -1; cs_b = -1; } else if ( sc == BLIS_RRC ) { rs_c = -1; rs_a = -1; rs_b = 0; cs_c = -1; cs_a = -1; cs_b = 0; } else if ( sc == BLIS_RCR ) { rs_c = -1; rs_a = 0; rs_b = -1; cs_c = -1; cs_a = 0; cs_b = -1; } else if ( sc == BLIS_RCC ) { rs_c = -1; rs_a = 0; rs_b = 0; cs_c = -1; cs_a = 0; cs_b = 0; } else if ( sc == BLIS_CRR ) { rs_c = 0; rs_a = -1; rs_b = -1; cs_c = 0; cs_a = -1; cs_b = -1; } else if ( sc == BLIS_CRC ) { rs_c = 0; rs_a = -1; rs_b = 0; cs_c = 0; cs_a = -1; cs_b = 0; } else if ( sc == BLIS_CCR ) { rs_c = 0; rs_a = 0; rs_b = -1; cs_c = 0; cs_a = 0; cs_b = -1; } else if ( sc == BLIS_CCC ) { rs_c = 0; rs_a = 0; rs_b = 0; cs_c = 0; cs_a = 0; cs_b = 0; } else { bli_abort(); } #else // LDIM_LARGE #if 0 const dim_t m_large = m; const dim_t n_large = n; const dim_t k_large = k; #else const dim_t m_large = p_max; const dim_t n_large = p_max; const dim_t k_large = p_max; #endif if ( sc == BLIS_RRR ) { rs_c = n_large; rs_a = k_large; rs_b = n_large; cs_c = 1; cs_a = 1; cs_b = 1; } else if ( sc == BLIS_RRC ) { rs_c = n_large; rs_a = k_large; rs_b = 1; cs_c = 1; cs_a = 1; cs_b = k_large; } else if ( sc == BLIS_RCR ) { rs_c = n_large; rs_a = 1; rs_b = n_large; cs_c = 1; cs_a = m_large; cs_b = 1; } else if ( sc == BLIS_RCC ) { rs_c = n_large; rs_a = 1; rs_b = 1; cs_c = 1; cs_a = m_large; cs_b = k_large; } else if ( sc == BLIS_CRR ) { rs_c = 1; rs_a = k_large; rs_b = n_large; cs_c = m_large; cs_a = 1; cs_b = 1; } else if ( sc == BLIS_CRC ) { rs_c = 1; rs_a = k_large; rs_b = 1; cs_c = m_large; cs_a = 1; cs_b = k_large; } else if ( sc == BLIS_CCR ) { rs_c = 1; rs_a = 1; rs_b = n_large; cs_c = m_large; cs_a = m_large; cs_b = 1; } else if ( sc == BLIS_CCC ) { rs_c = 1; rs_a = 1; rs_b = 1; cs_c = m_large; cs_a = m_large; cs_b = k_large; } else { bli_abort(); } #endif bli_obj_create( dt, 1, 1, 0, 0, &alpha ); bli_obj_create( dt, 1, 1, 0, 0, &beta ); bli_obj_create( dt, m, n, rs_c, cs_c, &c ); bli_obj_create( dt, m, n, rs_c, cs_c, &c_save ); if ( bli_does_notrans( transa ) ) bli_obj_create( dt, m, k, rs_a, cs_a, &a ); else bli_obj_create( dt, k, m, cs_a, rs_a, &a ); if ( bli_does_notrans( transb ) ) bli_obj_create( dt, k, n, rs_b, cs_b, &b ); else bli_obj_create( dt, n, k, cs_b, rs_b, &b ); bli_randm( &a ); bli_randm( &b ); bli_randm( &c ); bli_obj_set_conjtrans( transa, &a ); bli_obj_set_conjtrans( transb, &b ); bli_setsc( (1.0/1.0), 0.0, &alpha ); bli_setsc( (1.0/1.0), 0.0, &beta ); bli_copym( &c, &c_save ); #ifdef EIGEN double alpha_r, alpha_i; bli_getsc( &alpha, &alpha_r, &alpha_i ); void* ap = bli_obj_buffer_at_off( &a ); void* bp = bli_obj_buffer_at_off( &b ); void* cp = bli_obj_buffer_at_off( &c ); const int os_a = ( bli_obj_is_col_stored( &a ) ? bli_obj_col_stride( &a ) : bli_obj_row_stride( &a ) ); const int os_b = ( bli_obj_is_col_stored( &b ) ? bli_obj_col_stride( &b ) : bli_obj_row_stride( &b ) ); const int os_c = ( bli_obj_is_col_stored( &c ) ? bli_obj_col_stride( &c ) : bli_obj_row_stride( &c ) ); Stride stride_a( os_a, 1 ); Stride stride_b( os_b, 1 ); Stride stride_c( os_c, 1 ); #if defined(IS_FLOAT) #ifdef A_STOR_R typedef Matrix MatrixXs_A; #else typedef Matrix MatrixXs_A; #endif #ifdef B_STOR_R typedef Matrix MatrixXs_B; #else typedef Matrix MatrixXs_B; #endif #ifdef C_STOR_R typedef Matrix MatrixXs_C; #else typedef Matrix MatrixXs_C; #endif #ifdef A_NOTRANS // A is not transposed Map > A( ( float* )ap, m, k, stride_a ); #else // A is transposed Map > A( ( float* )ap, k, m, stride_a ); #endif #ifdef B_NOTRANS // B is not transposed Map > B( ( float* )bp, k, n, stride_b ); #else // B is transposed Map > B( ( float* )bp, n, k, stride_b ); #endif Map > C( ( float* )cp, m, n, stride_c ); #elif defined (IS_DOUBLE) #ifdef A_STOR_R typedef Matrix MatrixXd_A; #else typedef Matrix MatrixXd_A; #endif #ifdef B_STOR_R typedef Matrix MatrixXd_B; #else typedef Matrix MatrixXd_B; #endif #ifdef C_STOR_R typedef Matrix MatrixXd_C; #else typedef Matrix MatrixXd_C; #endif #ifdef A_NOTRANS // A is not transposed Map > A( ( double* )ap, m, k, stride_a ); #else // A is transposed Map > A( ( double* )ap, k, m, stride_a ); #endif #ifdef B_NOTRANS // B is not transposed Map > B( ( double* )bp, k, n, stride_b ); #else // B is transposed Map > B( ( double* )bp, n, k, stride_b ); #endif Map > C( ( double* )cp, m, n, stride_c ); #endif #endif double dtime_save = DBL_MAX; for ( dim_t r = 0; r < n_trials; ++r ) { bli_copym( &c_save, &c ); double dtime = bli_clock(); #ifdef EIGEN #ifdef A_NOTRANS #ifdef B_NOTRANS C.noalias() += alpha_r * A * B; #else // B_TRANS C.noalias() += alpha_r * A * B.transpose(); #endif #else // A_TRANS #ifdef B_NOTRANS C.noalias() += alpha_r * A.transpose() * B; #else // B_TRANS C.noalias() += alpha_r * A.transpose() * B.transpose(); #endif #endif #endif #ifdef BLIS #ifdef SUP // Allow sup. bli_gemm( &alpha, &a, &b, &beta, &c ); #else // NOTE: We can't use the static initializer and must instead // initialize the rntm_t with the copy from the global rntm_t we // made at the beginning of main(). Please see the comment there // for more info on why BLIS_RNTM_INITIALIZER doesn't work here. //rntm_t rntm = BLIS_RNTM_INITIALIZER; rntm_t rntm = rntm_g; // Disable sup and use the expert interface. bli_rntm_disable_l3_sup( &rntm ); bli_gemm_ex( &alpha, &a, &b, &beta, &c, NULL, &rntm ); #endif #endif #ifdef BLAS if ( bli_is_float( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); float* alphap = ( float* )bli_obj_buffer( &alpha ); float* ap = ( float* )bli_obj_buffer( &a ); float* bp = ( float* )bli_obj_buffer( &b ); float* betap = ( float* )bli_obj_buffer( &beta ); float* cp = ( float* )bli_obj_buffer( &c ); #ifdef XSMM libxsmm_sgemm( &f77_transa, #else sgemm_( &f77_transa, #endif &f77_transb, &mm, &nn, &kk, alphap, ap, &lda, bp, &ldb, betap, cp, &ldc ); } else if ( bli_is_double( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); double* alphap = ( double* )bli_obj_buffer( &alpha ); double* ap = ( double* )bli_obj_buffer( &a ); double* bp = ( double* )bli_obj_buffer( &b ); double* betap = ( double* )bli_obj_buffer( &beta ); double* cp = ( double* )bli_obj_buffer( &c ); #ifdef XSMM libxsmm_dgemm( &f77_transa, #else dgemm_( &f77_transa, #endif &f77_transb, &mm, &nn, &kk, alphap, ap, &lda, bp, &ldb, betap, cp, &ldc ); } else if ( bli_is_scomplex( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); scomplex* alphap = ( scomplex* )bli_obj_buffer( &alpha ); scomplex* ap = ( scomplex* )bli_obj_buffer( &a ); scomplex* bp = ( scomplex* )bli_obj_buffer( &b ); scomplex* betap = ( scomplex* )bli_obj_buffer( &beta ); scomplex* cp = ( scomplex* )bli_obj_buffer( &c ); #ifdef XSMM libxsmm_cgemm( &f77_transa, #else cgemm_( &f77_transa, #endif &f77_transb, &mm, &nn, &kk, alphap, ap, &lda, bp, &ldb, betap, cp, &ldc ); } else if ( bli_is_dcomplex( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); dcomplex* alphap = ( dcomplex* )bli_obj_buffer( &alpha ); dcomplex* ap = ( dcomplex* )bli_obj_buffer( &a ); dcomplex* bp = ( dcomplex* )bli_obj_buffer( &b ); dcomplex* betap = ( dcomplex* )bli_obj_buffer( &beta ); dcomplex* cp = ( dcomplex* )bli_obj_buffer( &c ); #ifdef XSMM libxsmm_zgemm( &f77_transa, #else zgemm_( &f77_transa, #endif &f77_transb, &mm, &nn, &kk, alphap, ap, &lda, bp, &ldb, betap, cp, &ldc ); } #endif #ifdef CBLAS if ( bli_is_float( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); f77_int nn = bli_obj_width( &c ); #ifdef C_STOR_R f77_int lda = bli_obj_row_stride( &a ); f77_int ldb = bli_obj_row_stride( &b ); f77_int ldc = bli_obj_row_stride( &c ); #else f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); #endif float* alphap = bli_obj_buffer( &alpha ); float* ap = bli_obj_buffer( &a ); float* bp = bli_obj_buffer( &b ); float* betap = bli_obj_buffer( &beta ); float* cp = bli_obj_buffer( &c ); cblas_sgemm( cbla_storage, cbla_transa, cbla_transb, mm, nn, kk, *alphap, ap, lda, bp, ldb, *betap, cp, ldc ); } else if ( bli_is_double( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); f77_int nn = bli_obj_width( &c ); #ifdef C_STOR_R f77_int lda = bli_obj_row_stride( &a ); f77_int ldb = bli_obj_row_stride( &b ); f77_int ldc = bli_obj_row_stride( &c ); #else f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); #endif double* alphap = bli_obj_buffer( &alpha ); double* ap = bli_obj_buffer( &a ); double* bp = bli_obj_buffer( &b ); double* betap = bli_obj_buffer( &beta ); double* cp = bli_obj_buffer( &c ); cblas_dgemm( cbla_storage, cbla_transa, cbla_transb, mm, nn, kk, *alphap, ap, lda, bp, ldb, *betap, cp, ldc ); } else if ( bli_is_scomplex( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); f77_int nn = bli_obj_width( &c ); #ifdef C_STOR_R f77_int lda = bli_obj_row_stride( &a ); f77_int ldb = bli_obj_row_stride( &b ); f77_int ldc = bli_obj_row_stride( &c ); #else f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); #endif scomplex* alphap = bli_obj_buffer( &alpha ); scomplex* ap = bli_obj_buffer( &a ); scomplex* bp = bli_obj_buffer( &b ); scomplex* betap = bli_obj_buffer( &beta ); scomplex* cp = bli_obj_buffer( &c ); cblas_cgemm( cbla_storage, cbla_transa, cbla_transb, mm, nn, kk, alphap, ap, lda, bp, ldb, betap, cp, ldc ); } else if ( bli_is_dcomplex( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); f77_int nn = bli_obj_width( &c ); #ifdef C_STOR_R f77_int lda = bli_obj_row_stride( &a ); f77_int ldb = bli_obj_row_stride( &b ); f77_int ldc = bli_obj_row_stride( &c ); #else f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); #endif dcomplex* alphap = bli_obj_buffer( &alpha ); dcomplex* ap = bli_obj_buffer( &a ); dcomplex* bp = bli_obj_buffer( &b ); dcomplex* betap = bli_obj_buffer( &beta ); dcomplex* cp = bli_obj_buffer( &c ); cblas_zgemm( cbla_storage, cbla_transa, cbla_transb, mm, nn, kk, alphap, ap, lda, bp, ldb, betap, cp, ldc ); } #endif dtime_save = bli_clock_min_diff( dtime_save, dtime ); } double gflops = ( 2.0 * m * k * n ) / ( dtime_save * 1.0e9 ); if ( bli_is_complex( dt ) ) gflops *= 4.0; printf( "data_%s_%cgemm_%c%c_%s", THR_STR, dt_ch, transal, transbl, STR ); printf( "( %2lu, 1:4 ) = [ %4lu %4lu %4lu %7.2f ];\n", ( unsigned long )(p - p_begin)/p_inc + 1, ( unsigned long )m, ( unsigned long )n, ( unsigned long )k, gflops ); bli_obj_free( &alpha ); bli_obj_free( &beta ); bli_obj_free( &a ); bli_obj_free( &b ); bli_obj_free( &c ); bli_obj_free( &c_save ); } //bli_finalize(); return 0; } blis-0.9.0/test/syrk_diagonal/000077500000000000000000000000001422157504600162645ustar00rootroot00000000000000blis-0.9.0/test/syrk_diagonal/complex_math.hpp000066400000000000000000000144531422157504600214640ustar00rootroot00000000000000#include #include #include #include "blis.h" template struct is_complex : std::false_type {}; template <> struct is_complex : std::true_type {}; template <> struct is_complex : std::true_type {}; template struct is_real : std::integral_constant::value> {}; template struct make_complex; template <> struct make_complex { using type = scomplex; }; template <> struct make_complex { using type = dcomplex; }; template <> struct make_complex { using type = scomplex; }; template <> struct make_complex { using type = dcomplex; }; template using make_complex_t = typename make_complex::type; template struct make_real; template <> struct make_real { using type = float; }; template <> struct make_real { using type = double; }; template <> struct make_real { using type = float; }; template <> struct make_real { using type = double; }; template using make_real_t = typename make_real::type; template struct make_complex_if : std::conditional,make_real_t> {}; template using make_complex_if_t = typename make_complex_if::type; template struct real_imag_part { real_imag_part& operator=(T) { return *this; } operator T() const { return T(); } }; template std::enable_if_t::type>::value,T&> real(T& x) { return x; } template std::enable_if_t::value,real_imag_part> imag(T x) { return {}; } inline float& real(scomplex& x) { return x.real; } inline float& imag(scomplex& x) { return x.imag; } inline double& real(dcomplex& x) { return x.real; } inline double& imag(dcomplex& x) { return x.imag; } inline const float& real(const scomplex& x) { return x.real; } inline const float& imag(const scomplex& x) { return x.imag; } inline const double& real(const dcomplex& x) { return x.real; } inline const double& imag(const dcomplex& x) { return x.imag; } template std::enable_if_t::value,T> conj(T x) { return x; } template std::enable_if_t::value,T> conj(const T& x) { return {x.real, -x.imag}; } template struct convert_impl; template struct convert_impl::value && is_real::value>> { void operator()(T x, U& y) const { y = x; } }; template struct convert_impl::value && is_complex::value>> { void operator()(T x, U& y) const { y.real = x; y.imag = 0; } }; template struct convert_impl::value && is_real::value>> { void operator()(T x, U& y) const { y = x.real; } }; template struct convert_impl::value && is_complex::value>> { void operator()(T x, U& y) const { y.real = x.real; y.imag = x.imag; } }; template U convert(T x) { U y; convert_impl{}(x,y); return y; } template auto convert_prec(T x) -> make_complex_if_t::value> { return convert::value>>(x); } #define COMPLEX_MATH_OPS(rtype, ctype) \ \ inline bool operator==(rtype x, ctype y) \ { \ return x == y.real && y.imag == 0; \ } \ \ inline bool operator==(ctype x, rtype y) \ { \ return y == x.real && x.imag == 0; \ } \ \ inline bool operator==(ctype x, ctype y) \ { \ return x.real == y.real && \ x.imag == y.imag; \ } \ \ inline ctype operator-(ctype x) \ { \ return {-x.real, -x.imag}; \ } \ \ inline ctype operator+(rtype x, ctype y) \ { \ return {x+y.real, y.imag}; \ } \ \ inline ctype operator+(ctype x, rtype y) \ { \ return {y+x.real, x.imag}; \ } \ \ inline ctype operator+(ctype x, ctype y) \ { \ return {x.real+y.real, x.imag+y.imag}; \ } \ \ inline ctype operator-(rtype x, ctype y) \ { \ return {x-y.real, -y.imag}; \ } \ \ inline ctype operator-(ctype x, rtype y) \ { \ return {x.real-y, x.imag}; \ } \ \ inline ctype operator-(ctype x, ctype y) \ { \ return {x.real-y.real, x.imag-y.imag}; \ } \ \ inline ctype operator*(rtype x, ctype y) \ { \ return {x*y.real, x*y.imag}; \ } \ \ inline ctype operator*(ctype x, rtype y) \ { \ return {y*x.real, y*x.imag}; \ } \ \ inline ctype operator*(ctype x, ctype y) \ { \ return {x.real*y.real - x.imag*y.imag, \ x.real*y.imag + x.imag*y.real}; \ } \ \ inline ctype operator/(rtype x, ctype y) \ { \ auto scale = std::max(std::abs(y.real), std::abs(y.imag)); \ auto n = std::ilogb(scale); \ auto yrs = std::scalbn(y.real, -n); \ auto yis = std::scalbn(y.imag, -n); \ auto denom = y.real*yrs + y.imag*yis; \ return {x*yrs/denom, -x*yis/denom}; \ } \ \ inline ctype operator/(ctype x, rtype y) \ { \ return {x.real/y, x.imag/y}; \ } \ \ inline ctype operator/(ctype x, ctype y) \ { \ auto scale = std::max(std::abs(y.real), std::abs(y.imag)); \ auto n = std::ilogb(scale); \ auto yrs = std::scalbn(y.real, -n); \ auto yis = std::scalbn(y.imag, -n); \ auto denom = y.real*yrs + y.imag*yis; \ return {(x.real*yrs + x.imag*yis)/denom, \ (x.imag*yrs - x.real*yis)/denom}; \ } \ \ inline ctype& operator+=(ctype& x, rtype y) \ { \ x.real += y; \ return x; \ } \ \ inline ctype& operator+=(ctype& x, ctype y) \ { \ x.real += y.real; x.imag += y.imag; \ return x; \ } \ \ inline ctype& operator-=(ctype& x, rtype y) \ { \ x.real -= y; \ return x; \ } \ \ inline ctype& operator-=(ctype& x, ctype y) \ { \ x.real -= y.real; x.imag -= y.imag; \ return x; \ } \ \ inline ctype& operator*=(ctype& x, rtype y) \ { \ x.real *= y; x.imag *= y; \ return x; \ } \ \ inline ctype& operator*=(ctype& x, ctype y) \ { \ x = x * y; \ return x; \ } \ \ inline ctype& operator/=(ctype& x, rtype y) \ { \ x.real /= y; x.imag /= y; \ return x; \ } \ \ inline ctype& operator/=(ctype& x, ctype y) \ { \ x = x / y; \ return x; \ } COMPLEX_MATH_OPS(float, scomplex); COMPLEX_MATH_OPS(double, dcomplex); blis-0.9.0/test/syrk_diagonal/syrk_diagonal_example.c000066400000000000000000000121711422157504600227730ustar00rootroot00000000000000#include "syrk_diagonal_ref.h" /* * Structure which includes all additional information beyond what is * already stored in the obj_t structure. * * This structure is **read-only** during the operation! */ typedef struct packm_diag_params_t { packm_blk_var1_params_t super; void* d; inc_t incd; } packm_diag_params_t; /* * Declare the pack kernel type and set up and array of * packing kernels, one for each data type. */ #undef GENTFUNC #define GENTFUNC(ctype,ch,op) \ void PASTEMAC(ch,op) \ ( \ struc_t struca, \ diag_t diaga, \ uplo_t uploa, \ conj_t conja, \ pack_t schema, \ bool invdiag, \ dim_t panel_dim, \ dim_t panel_len, \ dim_t panel_dim_max, \ dim_t panel_len_max, \ dim_t panel_dim_off, \ dim_t panel_len_off, \ void* restrict kappa, \ void* restrict a, inc_t inca, inc_t lda, \ void* restrict p, inc_t ldp, \ inc_t is_p, \ cntx_t* cntx, \ void* params \ ) \ { \ packm_diag_params_t* params_cast = params; \ ctype* restrict a_cast = a; \ ctype* restrict p_cast = p; \ ctype* restrict d_cast = params_cast->d; \ inc_t incd = params_cast->incd; \ ctype kappa_cast = *( ctype* )kappa; \ \ if ( schema != BLIS_PACKED_ROW_PANELS && \ schema != BLIS_PACKED_COL_PANELS ) \ bli_abort(); \ \ /* Apply the offset */ \ d_cast += panel_len_off * incd; \ \ if ( conja ) \ { \ for ( dim_t j = 0; j < panel_len; j++ ) \ { \ ctype kappa_d; \ PASTEMAC(ch,scal2s)( kappa_cast, d_cast[ j*incd ], kappa_d ); \ \ for (dim_t i = 0;i < panel_dim;i++) \ PASTEMAC(ch,scal2js)( kappa_d, a_cast[ i*inca + j*lda ], p_cast[ i + j*ldp ] ); \ \ for (dim_t i = panel_dim;i < panel_dim_max;i++) \ PASTEMAC(ch,set0s)( p_cast[ i + j*ldp ] ); \ } \ } \ else \ { \ for ( dim_t j = 0; j < panel_len; j++ ) \ { \ ctype kappa_d; \ PASTEMAC(ch,scal2s)( kappa_cast, d_cast[ j*incd ], kappa_d ); \ \ for (dim_t i = 0;i < panel_dim;i++) \ PASTEMAC(ch,scal2s)( kappa_d, a_cast[ i*inca + j*lda ], p_cast[ i + j*ldp ] ); \ \ for (dim_t i = panel_dim;i < panel_dim_max;i++) \ PASTEMAC(ch,set0s)( p_cast[ i + j*ldp ] ); \ } \ } \ \ for (dim_t j = panel_len;j < panel_len_max;j++) \ for (dim_t i = 0;i < panel_dim_max;i++) \ PASTEMAC(ch,set0s)( p_cast[ i + j*ldp ] ); \ } INSERT_GENTFUNC_BASIC0(packm_diag_ukr); static packm_ker_vft GENARRAY( packm_diag_ukrs, packm_diag_ukr ); /* * Modify the object A to include information about the diagonal D, * and imbue it with special function pointers which will take care * of the actual work of forming (D * A^T) */ void attach_diagonal_factor( packm_diag_params_t* params, obj_t* d, obj_t* a ) { memset( params, 0, sizeof(*params) ); // Assumes D is a column vector params->d = bli_obj_buffer_at_off( d ); params->incd = bli_obj_row_stride( d ); for ( int i = BLIS_DT_LO; i <= BLIS_DT_HI; i++ ) params->super.ukr_fn[i][i] = packm_diag_ukrs[i]; // Attach the parameters to the A object. bli_obj_set_pack_params( params, a ); } /* * Implements C := alpha * A * D * A^T + beta * C * * where D is a diagonal matrix with elements taken from the "d" vector. */ void syrk_diag( obj_t* alpha, obj_t* a, obj_t* d, obj_t* beta, obj_t* c ) { obj_t ad; // this is (D * A^T) packm_diag_params_t params; bli_obj_alias_to( a, &ad ); bli_obj_toggle_trans( &ad ); // because gemmt is A*B instead of A*B^T attach_diagonal_factor( ¶ms, d, &ad ); // Does C := alpha * A * B + beta * C using B = (D + A^T) bli_gemmtnat( alpha, a, &ad, beta, c, NULL, NULL ); } int main( void ) { obj_t a; obj_t d; obj_t c; obj_t c_copy; obj_t norm; dim_t m = 10; dim_t k = 10; for ( int dt_ = BLIS_DT_LO; dt_ <= BLIS_DT_HI; dt_++ ) for ( int upper = 0; upper <= 1; upper++ ) for ( int transa = 0; transa <= 1; transa++ ) for ( int transc = 0; transc <= 1; transc++ ) { num_t dt = dt_; uplo_t uplo = upper ? BLIS_UPPER : BLIS_LOWER; bli_obj_create( dt, m, k, transa ? k : 1, transa ? 1 : m, &a ); bli_obj_create( dt, k, 1, 1, 1, &d ); bli_obj_create( dt, m, m, transc ? m : 1, transc ? 1 : m, &c ); bli_obj_create( dt, m, m, transc ? m : 1, transc ? 1 : m, &c_copy ); bli_obj_set_struc( BLIS_SYMMETRIC , &c ); bli_obj_set_struc( BLIS_SYMMETRIC , &c_copy ); bli_obj_set_uplo( uplo , &c ); bli_obj_set_uplo( uplo , &c_copy ); bli_obj_create_1x1( bli_dt_proj_to_real( dt ), &norm ); bli_randm( &a ); bli_randm( &d ); bli_randm( &c ); bli_copym( &c, &c_copy ); syrk_diag( &BLIS_ONE, &a, &d, &BLIS_ONE, &c ); syrk_diag_ref( &BLIS_ONE, &a, &d, &BLIS_ONE, &c_copy ); bli_subm( &c_copy, &c ); bli_normfm( &c, &norm ); double normr, normi; bli_getsc( &norm, &normr, &normi ); printf( "dt: %d, upper: %d, transa: %d, transc: %d, norm: %g\n", dt, upper, transa, transc, normr ); bli_obj_free( &a ); bli_obj_free( &d ); bli_obj_free( &c ); bli_obj_free( &c_copy ); bli_obj_free( &norm ); } } blis-0.9.0/test/syrk_diagonal/syrk_diagonal_example.cxx000066400000000000000000000144651422157504600233630ustar00rootroot00000000000000#include "syrk_diagonal_ref.h" /* * Forward-declare the pack kernel type and set up and array of * packing kernels, one for each data type. */ template void packm_diag_ukr ( struc_t /*struca*/, diag_t /*diaga*/, uplo_t /*uploa*/, conj_t conja, pack_t schema, bool /*invdiag*/, dim_t panel_dim, dim_t panel_len, dim_t panel_dim_max, dim_t panel_len_max, dim_t /*panel_dim_off*/, dim_t panel_len_off, void* restrict kappa, void* restrict a, inc_t inca, inc_t lda, void* restrict p, inc_t ldp, inc_t /*is_p*/, cntx_t* /*cntx*/, void* params ); #undef GENTFUNC #define GENTFUNC(ctype,ch,op) \ static auto PASTEMAC(ch,op) = &packm_diag_ukr; INSERT_GENTFUNC_BASIC0(packm_diag_ukr); static packm_ker_vft GENARRAY( packm_diag_ukrs, packm_diag_ukr ); /* * Structure which includes all additional information beyond what is * already stored in the obj_t structure. * * This structure is **read-only** during the operation! */ struct packm_diag_params_t : packm_blk_var1_params_t { void* d; inc_t incd; packm_diag_params_t() {} packm_diag_params_t( void* d, inc_t incd ) : d(d), incd(incd) { for ( int i = BLIS_DT_LO; i <= BLIS_DT_HI; i++ ) ukr_fn[i][i] = packm_diag_ukrs[i]; } }; /* * Selecting a different kernel based on the current architecture is * currently not possible, but is something we plan to support. */ template void packm_diag_ukr ( struc_t /*struca*/, diag_t /*diaga*/, uplo_t /*uploa*/, conj_t conja, pack_t schema, bool /*invdiag*/, dim_t panel_dim, dim_t panel_len, dim_t panel_dim_max, dim_t panel_len_max, dim_t /*panel_dim_off*/, dim_t panel_len_off, void* restrict kappa, void* restrict a, inc_t inca, inc_t lda, void* restrict p, inc_t ldp, inc_t /*is_p*/, cntx_t* /*cntx*/, void* params ) { auto params_cast = ( packm_diag_params_t* )params; T* restrict a_cast = ( T* )a; T* restrict p_cast = ( T* )p; T* restrict d_cast = ( T* )params_cast->d; auto incd = params_cast->incd; auto kappa_cast = *( T* )kappa; if ( schema != BLIS_PACKED_ROW_PANELS && schema != BLIS_PACKED_COL_PANELS ) bli_abort(); /* Apply the offset */ d_cast += panel_len_off * incd; if ( conja ) { for ( dim_t j = 0; j < panel_len; j++ ) { auto kappa_d = kappa_cast * d_cast[ j*incd ]; for (dim_t i = 0;i < panel_dim;i++) p_cast[ i + j*ldp ] = kappa_d * conj( a_cast[ i*inca + j*lda ] ); for (dim_t i = panel_dim;i < panel_dim_max;i++) p_cast[ i + j*ldp ] = convert(0.0); } } else { for ( dim_t j = 0; j < panel_len; j++ ) { auto kappa_d = kappa_cast * d_cast[ j*incd ]; for (dim_t i = 0;i < panel_dim;i++) p_cast[ i + j*ldp ] = kappa_d * a_cast[ i*inca + j*lda ]; for (dim_t i = panel_dim;i < panel_dim_max;i++) p_cast[ i + j*ldp ] = convert(0.0); } } for (dim_t j = panel_len;j < panel_len_max;j++) for (dim_t i = 0;i < panel_dim_max;i++) p_cast[ i + j*ldp ] = convert(0.0); } /* * Modify the object A to include information about the diagonal D, * and imbue it with special function pointers which will take care * of the actual work of forming (D * A^T) */ void attach_diagonal_factor( packm_diag_params_t* params, obj_t* d, obj_t* a ) { // Assumes D is a column vector new (params) packm_diag_params_t ( bli_obj_buffer_at_off( d ), bli_obj_row_stride( d ) ); // Attach the parameters to the A object. bli_obj_set_pack_params( params, a ); } /* * Implements C := alpha * A * D * A^T + beta * C * * where D is a diagonal matrix with elements taken from the "d" vector. */ void syrk_diag( obj_t* alpha, obj_t* a, obj_t* d, obj_t* beta, obj_t* c ) { obj_t ad; // this is (D * A^T) packm_diag_params_t params; bli_obj_alias_to( a, &ad ); bli_obj_toggle_trans( &ad ); // because gemmt is A*B instead of A*B^T attach_diagonal_factor( ¶ms, d, &ad ); // Does C := alpha * A * B + beta * C using B = (D + A^T) bli_gemmtnat( alpha, a, &ad, beta, c, NULL, NULL ); } int main() { obj_t a; obj_t d; obj_t c; obj_t c_copy; obj_t norm; auto m = 10; auto k = 10; for ( int dt_ = BLIS_DT_LO; dt_ <= BLIS_DT_HI; dt_++ ) for ( int upper = 0; upper <= 1; upper++ ) for ( int transa = 0; transa <= 1; transa++ ) for ( int transc = 0; transc <= 1; transc++ ) { auto dt = ( num_t )dt_; auto uplo = upper ? BLIS_UPPER : BLIS_LOWER; bli_obj_create( dt, m, k, transa ? k : 1, transa ? 1 : m, &a ); bli_obj_create( dt, k, 1, 1, 1, &d ); bli_obj_create( dt, m, m, transc ? m : 1, transc ? 1 : m, &c ); bli_obj_create( dt, m, m, transc ? m : 1, transc ? 1 : m, &c_copy ); bli_obj_set_struc( BLIS_SYMMETRIC , &c ); bli_obj_set_struc( BLIS_SYMMETRIC , &c_copy ); bli_obj_set_uplo( uplo , &c ); bli_obj_set_uplo( uplo , &c_copy ); bli_obj_create_1x1( bli_dt_proj_to_real( dt ), &norm ); bli_randm( &a ); bli_randm( &d ); bli_randm( &c ); bli_copym( &c, &c_copy ); syrk_diag( &BLIS_ONE, &a, &d, &BLIS_ONE, &c ); syrk_diag_ref( &BLIS_ONE, &a, &d, &BLIS_ONE, &c_copy ); bli_subm( &c_copy, &c ); bli_normfm( &c, &norm ); double normr, normi; bli_getsc( &norm, &normr, &normi ); printf("dt: %d, upper: %d, transa: %d, transc: %d, norm: %g\n", dt, upper, transa, transc, normr); bli_obj_free( &a ); bli_obj_free( &d ); bli_obj_free( &c ); bli_obj_free( &c_copy ); bli_obj_free( &norm ); } } blis-0.9.0/test/syrk_diagonal/syrk_diagonal_example2.c000066400000000000000000000256751422157504600230720ustar00rootroot00000000000000#include "syrk_diagonal_ref.h" /* * Structure which includes all additional information beyond what is * already stored in the obj_t structure. * * This structure is **read-only** during the operation! */ typedef struct packm_diag_params_t { void* d; inc_t incd; } packm_diag_params_t; typedef void (*packm_diag_ukr_vft) ( bool conja, dim_t panel_dim, dim_t panel_len, dim_t panel_dim_max, dim_t panel_len_max, void* restrict kappa, void* restrict d, inc_t incd, void* restrict a, inc_t inca, inc_t lda, void* restrict p, inc_t ldp ); /* * Declare the pack kernel type and set up and array of * packing kernels, one for each data type. */ #undef GENTFUNC #define GENTFUNC(ctype,ch,op) \ void PASTEMAC(ch,op) \ ( \ bool conja, \ dim_t panel_dim, \ dim_t panel_len, \ dim_t panel_dim_max, \ dim_t panel_len_max, \ void* restrict kappa, \ void* restrict d, inc_t incd, \ void* restrict a, inc_t inca, inc_t lda, \ void* restrict p, inc_t ldp \ ) \ { \ ctype* restrict a_cast = a; \ ctype* restrict p_cast = p; \ ctype* restrict d_cast = d; \ ctype kappa_cast = *( ctype* )kappa; \ \ if ( conja ) \ { \ for ( dim_t j = 0; j < panel_len; j++ ) \ { \ ctype kappa_d; \ PASTEMAC(ch,scal2s)( kappa_cast, d_cast[ j*incd ], kappa_d ); \ \ for (dim_t i = 0;i < panel_dim;i++) \ PASTEMAC(ch,scal2js)( kappa_d, a_cast[ i*inca + j*lda ], p_cast[ i + j*ldp ] ); \ \ for (dim_t i = panel_dim;i < panel_dim_max;i++) \ PASTEMAC(ch,set0s)( p_cast[ i + j*ldp ] ); \ } \ } \ else \ { \ for ( dim_t j = 0; j < panel_len; j++ ) \ { \ ctype kappa_d; \ PASTEMAC(ch,scal2s)( kappa_cast, d_cast[ j*incd ], kappa_d ); \ \ for (dim_t i = 0;i < panel_dim;i++) \ PASTEMAC(ch,scal2s)( kappa_d, a_cast[ i*inca + j*lda ], p_cast[ i + j*ldp ] ); \ \ for (dim_t i = panel_dim;i < panel_dim_max;i++) \ PASTEMAC(ch,set0s)( p_cast[ i + j*ldp ] ); \ } \ } \ \ for (dim_t j = panel_len;j < panel_len_max;j++) \ for (dim_t i = 0;i < panel_dim_max;i++) \ PASTEMAC(ch,set0s)( p_cast[ i + j*ldp ] ); \ } INSERT_GENTFUNC_BASIC0(packm_diag_ukr); static packm_diag_ukr_vft GENARRAY( packm_diag_ukrs, packm_diag_ukr ); void packm_diag ( obj_t* a, obj_t* p, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ) { #if 1 // We begin by copying the fields of A. bli_obj_alias_to( a, p ); // Get information about data types. num_t dt = bli_obj_dt( a ); num_t dt_tar = bli_obj_target_dt( a ); num_t dt_scalar = bli_obj_scalar_dt( a ); dim_t dt_size = bli_dt_size( dt ); if ( dt_scalar != dt || dt_tar != dt ) bli_abort(); // Extract various fields from the control tree. bszid_t bmult_id_m = bli_cntl_packm_params_bmid_m( cntl ); bszid_t bmult_id_n = bli_cntl_packm_params_bmid_n( cntl ); pack_t schema = bli_cntl_packm_params_pack_schema( cntl ); dim_t bmult_m_def = bli_cntx_get_blksz_def_dt( dt_tar, bmult_id_m, cntx ); dim_t bmult_m_pack = bli_cntx_get_blksz_max_dt( dt_tar, bmult_id_m, cntx ); dim_t bmult_n_def = bli_cntx_get_blksz_def_dt( dt_tar, bmult_id_n, cntx ); if ( schema != BLIS_PACKED_ROW_PANELS && schema != BLIS_PACKED_COL_PANELS ) bli_abort(); // Store the pack schema to the object. bli_obj_set_pack_schema( schema, p ); // Clear the conjugation field from the object since matrix packing // in BLIS is deemed to take care of all conjugation necessary. bli_obj_set_conj( BLIS_NO_CONJUGATE, p ); // If we are packing micropanels, mark P as dense. bli_obj_set_uplo( BLIS_DENSE, p ); // Reset the view offsets to (0,0). bli_obj_set_offs( 0, 0, p ); // Compute the dimensions padded by the dimension multiples. These // dimensions will be the dimensions of the packed matrices, including // zero-padding, and will be used by the macro- and micro-kernels. // We compute them by starting with the effective dimensions of A (now // in P) and aligning them to the dimension multiples (typically equal // to register blocksizes). This does waste a little bit of space for // level-2 operations, but that's okay with us. dim_t m_p = bli_obj_length( p ); dim_t n_p = bli_obj_width( p ); dim_t m_p_pad = bli_align_dim_to_mult( m_p, bmult_m_def ); dim_t n_p_pad = bli_align_dim_to_mult( n_p, bmult_n_def ); // Save the padded dimensions into the packed object. It is important // to save these dimensions since they represent the actual dimensions // of the zero-padded matrix. bli_obj_set_padded_dims( m_p_pad, n_p_pad, p ); // The "panel stride" of a micropanel packed object is interpreted as // the distance between the (0,0) element of panel k and the (0,0) // element of panel k+1. We use the padded width computed above to // allow for zero-padding (if necessary/desired) along the far end // of each micropanel (ie: the right edge of the matrix). Zero-padding // can also occur along the long edge of the last micropanel if the m // dimension of the matrix is not a whole multiple of MR. inc_t ps_p = bmult_m_pack * n_p_pad; /* Compute the total number of iterations we'll need. */ dim_t n_iter = m_p_pad / bmult_m_def; // Store the strides and panel dimension in P. bli_obj_set_strides( 1, bmult_m_pack, p ); bli_obj_set_imag_stride( 1, p ); bli_obj_set_panel_dim( bmult_m_def, p ); bli_obj_set_panel_stride( ps_p, p ); bli_obj_set_panel_length( bmult_m_def, p ); bli_obj_set_panel_width( n_p, p ); // Compute the size of the packed buffer. siz_t size_p = ps_p * n_iter * dt_size; if ( size_p == 0 ) return; // Update the buffer address in p to point to the buffer associated // with the mem_t entry acquired from the memory broker (now cached in // the control tree node). char* p_cast = (char*)bli_packm_alloc( size_p, rntm, cntl, thread ); bli_obj_set_buffer( p_cast, p ); #else // Every thread initializes p and determines the size of memory // block needed (which gets embedded into the otherwise "blank" mem_t // entry in the control tree node). Return early if no packing is required. if ( !bli_packm_init( a, p, cntx, rntm, cntl, thread ) ) return; num_t dt = bli_obj_dt( a ); dim_t dt_size = bli_dt_size( dt ); bszid_t bmult_id_m = bli_cntl_packm_params_bmid_m( cntl ); dim_t bmult_m_def = bli_cntx_get_blksz_def_dt( dt, bmult_id_m, cntx ); dim_t bmult_m_pack = bli_cntx_get_blksz_max_dt( dt, bmult_id_m, cntx ); dim_t m_p = bli_obj_length( p ); dim_t n_p = bli_obj_width( p ); dim_t m_p_pad = bli_obj_padded_length( p ); dim_t n_p_pad = bli_obj_padded_width( p ); dim_t n_iter = m_p_pad / bmult_m_def; char* p_cast = bli_obj_buffer( p ); inc_t ps_p = bli_obj_panel_stride( p ); #endif char* a_cast = bli_obj_buffer_at_off( a ); inc_t inca = bli_obj_row_stride( a ); inc_t lda = bli_obj_col_stride( a ); dim_t panel_len_off = bli_obj_col_off( a ); conj_t conja = bli_obj_conj_status( a ); packm_diag_params_t* params = bli_obj_pack_params( a ); char* d_cast = params->d; inc_t incd = params->incd; obj_t kappa_local; char* kappa_cast = bli_packm_scalar( &kappa_local, p ); packm_diag_ukr_vft packm_ker_cast = packm_diag_ukrs[ dt ]; /* Query the number of threads and thread ids from the current thread's packm thrinfo_t node. */ const dim_t nt = bli_thread_n_way( thread ); const dim_t tid = bli_thread_work_id( thread ); /* Determine the thread range and increment using the current thread's packm thrinfo_t node. NOTE: The definition of bli_thread_range_jrir() will depend on whether slab or round-robin partitioning was requested at configure-time. */ dim_t it_start, it_end, it_inc; bli_thread_range_jrir( thread, n_iter, 1, FALSE, &it_start, &it_end, &it_inc ); /* Iterate over every logical micropanel in the source matrix. */ for ( dim_t it = 0; it < n_iter; it += 1 ) { dim_t panel_dim_i = bli_min( bmult_m_def, m_p - it*bmult_m_def ); char* d_begin = d_cast + panel_len_off*incd*dt_size; char* a_begin = a_cast + it* bmult_m_def*inca*dt_size; char* p_begin = p_cast + it* ps_p*dt_size; if ( bli_packm_my_iter( it, it_start, it_end, tid, nt ) ) { packm_ker_cast ( conja, panel_dim_i, n_p, bmult_m_def, n_p_pad, kappa_cast, d_begin, incd, a_begin, inca, lda, p_begin, bmult_m_pack ); } } } /* * Modify the object A to include information about the diagonal D, * and imbue it with special function pointers which will take care * of the actual work of forming (D * A^T) */ void attach_diagonal_factor( packm_diag_params_t* params, obj_t* d, obj_t* a ) { // Assumes D is a column vector params->d = bli_obj_buffer_at_off( d ); params->incd = bli_obj_row_stride( d ); // Set the custom pack function. bli_obj_set_pack_fn( packm_diag, a ); // Attach the parameters to the A object. bli_obj_set_pack_params( params, a ); } /* * Implements C := alpha * A * D * A^T + beta * C * * where D is a diagonal matrix with elements taken from the "d" vector. */ void syrk_diag( obj_t* alpha, obj_t* a, obj_t* d, obj_t* beta, obj_t* c ) { obj_t ad; // this is (D * A^T) packm_diag_params_t params; bli_obj_alias_to( a, &ad ); bli_obj_toggle_trans( &ad ); // because gemmt is A*B instead of A*B^T attach_diagonal_factor( ¶ms, d, &ad ); // Does C := alpha * A * B + beta * C using B = (D + A^T) bli_gemmt( alpha, a, &ad, beta, c ); } int main( void ) { obj_t a; obj_t d; obj_t c; obj_t c_copy; obj_t norm; dim_t m = 10; dim_t k = 10; for ( int dt_ = BLIS_DT_LO; dt_ <= BLIS_DT_HI; dt_++ ) for ( int upper = 0; upper <= 1; upper++ ) for ( int transa = 0; transa <= 1; transa++ ) for ( int transc = 0; transc <= 1; transc++ ) { num_t dt = dt_; uplo_t uplo = upper ? BLIS_UPPER : BLIS_LOWER; bli_obj_create( dt, m, k, transa ? k : 1, transa ? 1 : m, &a ); bli_obj_create( dt, k, 1, 1, 1, &d ); bli_obj_create( dt, m, m, transc ? m : 1, transc ? 1 : m, &c ); bli_obj_create( dt, m, m, transc ? m : 1, transc ? 1 : m, &c_copy ); bli_obj_set_struc( BLIS_SYMMETRIC , &c ); bli_obj_set_struc( BLIS_SYMMETRIC , &c_copy ); bli_obj_set_uplo( uplo , &c ); bli_obj_set_uplo( uplo , &c_copy ); bli_obj_create_1x1( bli_dt_proj_to_real( dt ), &norm ); bli_randm( &a ); bli_randm( &d ); bli_randm( &c ); bli_copym( &c, &c_copy ); syrk_diag( &BLIS_ONE, &a, &d, &BLIS_ONE, &c ); syrk_diag_ref( &BLIS_ONE, &a, &d, &BLIS_ONE, &c_copy ); bli_subm( &c_copy, &c ); bli_normfm( &c, &norm ); double normr, normi; bli_getsc( &norm, &normr, &normi ); printf( "dt: %d, upper: %d, transa: %d, transc: %d, norm: %g\n", dt, upper, transa, transc, normr ); bli_obj_free( &a ); bli_obj_free( &d ); bli_obj_free( &c ); bli_obj_free( &c_copy ); bli_obj_free( &norm ); } } blis-0.9.0/test/syrk_diagonal/syrk_diagonal_example2.cxx000066400000000000000000000256001422157504600234360ustar00rootroot00000000000000#include "syrk_diagonal_ref.h" /* * Forward-declare the pack kernel type and set up and array of * packing kernels, one for each data type. */ template void packm_diag_ukr ( bool conja, dim_t panel_dim, dim_t panel_len, dim_t panel_dim_max, dim_t panel_len_max, void* restrict kappa, void* restrict d, inc_t incd, void* restrict a, inc_t inca, inc_t lda, void* restrict p, inc_t ldp ); #undef GENTFUNC #define GENTFUNC(ctype,ch,op) \ static auto PASTEMAC(ch,op) = &packm_diag_ukr; INSERT_GENTFUNC_BASIC0(packm_diag_ukr); using packm_diag_ukr_vft = decltype(&packm_diag_ukr); static packm_diag_ukr_vft GENARRAY( packm_diag_ukrs, packm_diag_ukr ); /* * Structure which includes all additional information beyond what is * already stored in the obj_t structure. * * This structure is **read-only** during the operation! */ struct packm_diag_params_t { void* d; inc_t incd; packm_diag_params_t() {} packm_diag_params_t( void* d, inc_t incd ) : d(d), incd(incd) {} }; /* * Selecting a different kernel based on the current architecture is * currently not possible, but is something we plan to support. */ template void packm_diag_ukr ( bool conja, dim_t panel_dim, dim_t panel_len, dim_t panel_dim_max, dim_t panel_len_max, void* restrict kappa, void* restrict d, inc_t incd, void* restrict a, inc_t inca, inc_t lda, void* restrict p, inc_t ldp ) { T* restrict a_cast = ( T* )a; T* restrict p_cast = ( T* )p; T* restrict d_cast = ( T* )d; auto kappa_cast = *( T* )kappa; if ( conja ) { for ( dim_t j = 0; j < panel_len; j++ ) { auto kappa_d = kappa_cast * d_cast[ j*incd ]; for (dim_t i = 0;i < panel_dim;i++) p_cast[ i + j*ldp ] = kappa_d * conj( a_cast[ i*inca + j*lda ] ); for (dim_t i = panel_dim;i < panel_dim_max;i++) p_cast[ i + j*ldp ] = convert(0.0); } } else { for ( dim_t j = 0; j < panel_len; j++ ) { auto kappa_d = kappa_cast * d_cast[ j*incd ]; for (dim_t i = 0;i < panel_dim;i++) p_cast[ i + j*ldp ] = kappa_d * a_cast[ i*inca + j*lda ]; for (dim_t i = panel_dim;i < panel_dim_max;i++) p_cast[ i + j*ldp ] = convert(0.0); } } for (dim_t j = panel_len;j < panel_len_max;j++) for (dim_t i = 0;i < panel_dim_max;i++) p_cast[ i + j*ldp ] = convert(0.0); } void packm_diag ( obj_t* a, obj_t* p, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ) { // We begin by copying the fields of A. bli_obj_alias_to( a, p ); // Get information about data types. num_t dt = bli_obj_dt( a ); num_t dt_tar = bli_obj_target_dt( a ); num_t dt_scalar = bli_obj_scalar_dt( a ); dim_t dt_size = bli_dt_size( dt ); if ( dt_scalar != dt || dt_tar != dt ) bli_abort(); // Extract various fields from the control tree. bszid_t bmult_id_m = bli_cntl_packm_params_bmid_m( cntl ); bszid_t bmult_id_n = bli_cntl_packm_params_bmid_n( cntl ); pack_t schema = bli_cntl_packm_params_pack_schema( cntl ); dim_t bmult_m_def = bli_cntx_get_blksz_def_dt( dt_tar, bmult_id_m, cntx ); dim_t bmult_m_pack = bli_cntx_get_blksz_max_dt( dt_tar, bmult_id_m, cntx ); dim_t bmult_n_def = bli_cntx_get_blksz_def_dt( dt_tar, bmult_id_n, cntx ); if ( schema != BLIS_PACKED_ROW_PANELS && schema != BLIS_PACKED_COL_PANELS ) bli_abort(); // Store the pack schema to the object. bli_obj_set_pack_schema( schema, p ); // Clear the conjugation field from the object since matrix packing // in BLIS is deemed to take care of all conjugation necessary. bli_obj_set_conj( BLIS_NO_CONJUGATE, p ); // If we are packing micropanels, mark P as dense. bli_obj_set_uplo( BLIS_DENSE, p ); // Reset the view offsets to (0,0). bli_obj_set_offs( 0, 0, p ); // Compute the dimensions padded by the dimension multiples. These // dimensions will be the dimensions of the packed matrices, including // zero-padding, and will be used by the macro- and micro-kernels. // We compute them by starting with the effective dimensions of A (now // in P) and aligning them to the dimension multiples (typically equal // to register blocksizes). This does waste a little bit of space for // level-2 operations, but that's okay with us. dim_t m_p = bli_obj_length( p ); dim_t n_p = bli_obj_width( p ); dim_t m_p_pad = bli_align_dim_to_mult( m_p, bmult_m_def ); dim_t n_p_pad = bli_align_dim_to_mult( n_p, bmult_n_def ); // Save the padded dimensions into the packed object. It is important // to save these dimensions since they represent the actual dimensions // of the zero-padded matrix. bli_obj_set_padded_dims( m_p_pad, n_p_pad, p ); // The "panel stride" of a micropanel packed object is interpreted as // the distance between the (0,0) element of panel k and the (0,0) // element of panel k+1. We use the padded width computed above to // allow for zero-padding (if necessary/desired) along the far end // of each micropanel (ie: the right edge of the matrix). Zero-padding // can also occur along the long edge of the last micropanel if the m // dimension of the matrix is not a whole multiple of MR. inc_t ps_p = bmult_m_pack * n_p_pad; /* Compute the total number of iterations we'll need. */ dim_t n_iter = m_p_pad / bmult_m_def; // Store the strides and panel dimension in P. bli_obj_set_strides( 1, bmult_m_pack, p ); bli_obj_set_imag_stride( 1, p ); bli_obj_set_panel_dim( bmult_m_def, p ); bli_obj_set_panel_stride( ps_p, p ); bli_obj_set_panel_length( bmult_m_def, p ); bli_obj_set_panel_width( n_p, p ); // Compute the size of the packed buffer. siz_t size_p = ps_p * n_iter * dt_size; if ( size_p == 0 ) return; // Update the buffer address in p to point to the buffer associated // with the mem_t entry acquired from the memory broker (now cached in // the control tree node). char* p_cast = (char*)bli_packm_alloc( size_p, rntm, cntl, thread ); bli_obj_set_buffer( p_cast, p ); char* a_cast = (char*)bli_obj_buffer_at_off( a ); inc_t inca = bli_obj_row_stride( a ); inc_t lda = bli_obj_col_stride( a ); dim_t panel_len_off = bli_obj_col_off( a ); conj_t conja = bli_obj_conj_status( a ); auto params = (packm_diag_params_t*)bli_obj_pack_params( a ); char* d_cast = (char*)params->d; inc_t incd = params->incd; obj_t kappa_local; char* kappa_cast = (char*)bli_packm_scalar( &kappa_local, p ); auto packm_ker_cast = packm_diag_ukrs[ dt ]; /* Query the number of threads and thread ids from the current thread's packm thrinfo_t node. */ const dim_t nt = bli_thread_n_way( thread ); const dim_t tid = bli_thread_work_id( thread ); /* Determine the thread range and increment using the current thread's packm thrinfo_t node. NOTE: The definition of bli_thread_range_jrir() will depend on whether slab or round-robin partitioning was requested at configure-time. */ dim_t it_start, it_end, it_inc; bli_thread_range_jrir( thread, n_iter, 1, FALSE, &it_start, &it_end, &it_inc ); /* Iterate over every logical micropanel in the source matrix. */ for ( dim_t it = 0; it < n_iter; it += 1 ) { dim_t panel_dim_i = bli_min( bmult_m_def, m_p - it*bmult_m_def ); char* d_begin = d_cast + panel_len_off*incd*dt_size; char* a_begin = a_cast + it* bmult_m_def*inca*dt_size; char* p_begin = p_cast + it* ps_p*dt_size; if ( bli_packm_my_iter( it, it_start, it_end, tid, nt ) ) { packm_ker_cast( conja, panel_dim_i, n_p, bmult_m_def, n_p_pad, kappa_cast, d_begin, incd, a_begin, inca, lda, p_begin, bmult_m_pack ); } } } /* * Modify the object A to include information about the diagonal D, * and imbue it with special function pointers which will take care * of the actual work of forming (D * A^T) */ void attach_diagonal_factor( packm_diag_params_t* params, obj_t* d, obj_t* a ) { // Assumes D is a column vector new (params) packm_diag_params_t ( bli_obj_buffer_at_off( d ), bli_obj_row_stride( d ) ); // Set the custom pack function. bli_obj_set_pack_fn( packm_diag, a ); // Attach the parameters to the A object. bli_obj_set_pack_params( params, a ); } /* * Implements C := alpha * A * D * A^T + beta * C * * where D is a diagonal matrix with elements taken from the "d" vector. */ void syrk_diag( obj_t* alpha, obj_t* a, obj_t* d, obj_t* beta, obj_t* c ) { obj_t ad; // this is (D * A^T) packm_diag_params_t params; bli_obj_alias_to( a, &ad ); bli_obj_toggle_trans( &ad ); // because gemmt is A*B instead of A*B^T attach_diagonal_factor( ¶ms, d, &ad ); // Does C := alpha * A * B + beta * C using B = (D + A^T) bli_gemmt( alpha, a, &ad, beta, c ); } int main() { obj_t a; obj_t d; obj_t c; obj_t c_copy; obj_t norm; auto m = 10; auto k = 10; for ( int dt_ = BLIS_DT_LO; dt_ <= BLIS_DT_HI; dt_++ ) for ( int upper = 0; upper <= 1; upper++ ) for ( int transa = 0; transa <= 1; transa++ ) for ( int transc = 0; transc <= 1; transc++ ) { auto dt = ( num_t )dt_; auto uplo = upper ? BLIS_UPPER : BLIS_LOWER; bli_obj_create( dt, m, k, transa ? k : 1, transa ? 1 : m, &a ); bli_obj_create( dt, k, 1, 1, 1, &d ); bli_obj_create( dt, m, m, transc ? m : 1, transc ? 1 : m, &c ); bli_obj_create( dt, m, m, transc ? m : 1, transc ? 1 : m, &c_copy ); bli_obj_set_struc( BLIS_SYMMETRIC , &c ); bli_obj_set_struc( BLIS_SYMMETRIC , &c_copy ); bli_obj_set_uplo( uplo , &c ); bli_obj_set_uplo( uplo , &c_copy ); bli_obj_create_1x1( bli_dt_proj_to_real( dt ), &norm ); bli_randm( &a ); bli_randm( &d ); bli_randm( &c ); bli_copym( &c, &c_copy ); syrk_diag( &BLIS_ONE, &a, &d, &BLIS_ONE, &c ); syrk_diag_ref( &BLIS_ONE, &a, &d, &BLIS_ONE, &c_copy ); bli_subm( &c_copy, &c ); bli_normfm( &c, &norm ); double normr, normi; bli_getsc( &norm, &normr, &normi ); printf("dt: %d, upper: %d, transa: %d, transc: %d, norm: %g\n", dt, upper, transa, transc, normr); bli_obj_free( &a ); bli_obj_free( &d ); bli_obj_free( &c ); bli_obj_free( &c_copy ); bli_obj_free( &norm ); } } blis-0.9.0/test/syrk_diagonal/syrk_diagonal_ref.cxx000066400000000000000000000051151422157504600224740ustar00rootroot00000000000000#include "syrk_diagonal_ref.h" #include "complex_math.hpp" typedef void (*syrk_diag_ref_vft) ( uplo_t uplo, dim_t m, dim_t k, void* alpha, void* a, inc_t rs_a, inc_t cs_a, void* d, inc_t incd, void* beta, void* c, inc_t rs_c, inc_t cs_c ); template void syrk_diag_ref ( uplo_t uplo, dim_t m, dim_t k, void* alpha, void* a, inc_t rs_a, inc_t cs_a, void* d, inc_t incd, void* beta, void* c, inc_t rs_c, inc_t cs_c ) { auto alpha_cast = *( T* )alpha; auto beta_cast = *( T* )beta; auto a_cast = ( T* )a; auto d_cast = ( T* )d; auto c_cast = ( T* )c; for ( dim_t i = 0; i < m; i++ ) { dim_t j_min = uplo == BLIS_UPPER ? i : 0; dim_t j_max = uplo == BLIS_UPPER ? m : i+1; for ( dim_t j = j_min; j < j_max; j++ ) { auto ada = convert(0.0); for ( dim_t p = 0; p < k; p++ ) { ada += a_cast[ i*rs_a + p*cs_a ] * d_cast[ p*incd ] * a_cast[ j*rs_a + p*cs_a ]; } if ( beta_cast == convert(0.0) ) { c_cast[ i*rs_c + j*cs_c ] = alpha_cast * ada; } else { c_cast[ i*rs_c + j*cs_c ] = alpha_cast * ada + beta_cast * c_cast[ i*rs_c + j*cs_c ]; } } } } #undef GENTFUNC #define GENTFUNC(ctype,ch,op) \ static auto PASTEMAC(ch,op) = &syrk_diag_ref; INSERT_GENTFUNC_BASIC0(syrk_diag_ref); static syrk_diag_ref_vft GENARRAY( syrk_diag_ref_impl, syrk_diag_ref ); void syrk_diag_ref( obj_t* alpha, obj_t* a, obj_t* d, obj_t* beta, obj_t* c ) { num_t dt = bli_obj_dt( a ); dim_t m = bli_obj_length_after_trans( a ); dim_t k = bli_obj_width_after_trans( a ); inc_t rs_a = bli_obj_row_stride( a ); inc_t cs_a = bli_obj_col_stride( a ); inc_t rs_c = bli_obj_row_stride( c ); inc_t cs_c = bli_obj_col_stride( c ); inc_t incd = bli_obj_row_stride( d ); if ( bli_obj_has_trans( a ) ) bli_swap_incs( &rs_a, &cs_a ); if ( bli_obj_has_trans( c ) ) bli_swap_incs( &rs_c, &cs_c ); syrk_diag_ref_impl[ dt ] ( bli_obj_uplo( c ), m, k, bli_obj_buffer_for_1x1( dt, alpha ), bli_obj_buffer_at_off( a ), rs_a, cs_a, bli_obj_buffer_at_off( d ), incd, bli_obj_buffer_for_1x1( dt, beta ), bli_obj_buffer_at_off( c ), rs_c, cs_c ); } blis-0.9.0/test/syrk_diagonal/syrk_diagonal_ref.h000066400000000000000000000002441422157504600221170ustar00rootroot00000000000000#include "blis.h" #ifdef __cplusplus #include "complex_math.hpp" extern "C" #endif void syrk_diag_ref( obj_t* alpha, obj_t* a, obj_t* d, obj_t* beta, obj_t* c ); blis-0.9.0/test/tensor_contraction/000077500000000000000000000000001422157504600173535ustar00rootroot00000000000000blis-0.9.0/test/tensor_contraction/complex_math.hpp000066400000000000000000000144531422157504600225530ustar00rootroot00000000000000#include #include #include #include "blis.h" template struct is_complex : std::false_type {}; template <> struct is_complex : std::true_type {}; template <> struct is_complex : std::true_type {}; template struct is_real : std::integral_constant::value> {}; template struct make_complex; template <> struct make_complex { using type = scomplex; }; template <> struct make_complex { using type = dcomplex; }; template <> struct make_complex { using type = scomplex; }; template <> struct make_complex { using type = dcomplex; }; template using make_complex_t = typename make_complex::type; template struct make_real; template <> struct make_real { using type = float; }; template <> struct make_real { using type = double; }; template <> struct make_real { using type = float; }; template <> struct make_real { using type = double; }; template using make_real_t = typename make_real::type; template struct make_complex_if : std::conditional,make_real_t> {}; template using make_complex_if_t = typename make_complex_if::type; template struct real_imag_part { real_imag_part& operator=(T) { return *this; } operator T() const { return T(); } }; template std::enable_if_t::type>::value,T&> real(T& x) { return x; } template std::enable_if_t::value,real_imag_part> imag(T x) { return {}; } inline float& real(scomplex& x) { return x.real; } inline float& imag(scomplex& x) { return x.imag; } inline double& real(dcomplex& x) { return x.real; } inline double& imag(dcomplex& x) { return x.imag; } inline const float& real(const scomplex& x) { return x.real; } inline const float& imag(const scomplex& x) { return x.imag; } inline const double& real(const dcomplex& x) { return x.real; } inline const double& imag(const dcomplex& x) { return x.imag; } template std::enable_if_t::value,T> conj(T x) { return x; } template std::enable_if_t::value,T> conj(const T& x) { return {x.real, -x.imag}; } template struct convert_impl; template struct convert_impl::value && is_real::value>> { void operator()(T x, U& y) const { y = x; } }; template struct convert_impl::value && is_complex::value>> { void operator()(T x, U& y) const { y.real = x; y.imag = 0; } }; template struct convert_impl::value && is_real::value>> { void operator()(T x, U& y) const { y = x.real; } }; template struct convert_impl::value && is_complex::value>> { void operator()(T x, U& y) const { y.real = x.real; y.imag = x.imag; } }; template U convert(T x) { U y; convert_impl{}(x,y); return y; } template auto convert_prec(T x) -> make_complex_if_t::value> { return convert::value>>(x); } #define COMPLEX_MATH_OPS(rtype, ctype) \ \ inline bool operator==(rtype x, ctype y) \ { \ return x == y.real && y.imag == 0; \ } \ \ inline bool operator==(ctype x, rtype y) \ { \ return y == x.real && x.imag == 0; \ } \ \ inline bool operator==(ctype x, ctype y) \ { \ return x.real == y.real && \ x.imag == y.imag; \ } \ \ inline ctype operator-(ctype x) \ { \ return {-x.real, -x.imag}; \ } \ \ inline ctype operator+(rtype x, ctype y) \ { \ return {x+y.real, y.imag}; \ } \ \ inline ctype operator+(ctype x, rtype y) \ { \ return {y+x.real, x.imag}; \ } \ \ inline ctype operator+(ctype x, ctype y) \ { \ return {x.real+y.real, x.imag+y.imag}; \ } \ \ inline ctype operator-(rtype x, ctype y) \ { \ return {x-y.real, -y.imag}; \ } \ \ inline ctype operator-(ctype x, rtype y) \ { \ return {x.real-y, x.imag}; \ } \ \ inline ctype operator-(ctype x, ctype y) \ { \ return {x.real-y.real, x.imag-y.imag}; \ } \ \ inline ctype operator*(rtype x, ctype y) \ { \ return {x*y.real, x*y.imag}; \ } \ \ inline ctype operator*(ctype x, rtype y) \ { \ return {y*x.real, y*x.imag}; \ } \ \ inline ctype operator*(ctype x, ctype y) \ { \ return {x.real*y.real - x.imag*y.imag, \ x.real*y.imag + x.imag*y.real}; \ } \ \ inline ctype operator/(rtype x, ctype y) \ { \ auto scale = std::max(std::abs(y.real), std::abs(y.imag)); \ auto n = std::ilogb(scale); \ auto yrs = std::scalbn(y.real, -n); \ auto yis = std::scalbn(y.imag, -n); \ auto denom = y.real*yrs + y.imag*yis; \ return {x*yrs/denom, -x*yis/denom}; \ } \ \ inline ctype operator/(ctype x, rtype y) \ { \ return {x.real/y, x.imag/y}; \ } \ \ inline ctype operator/(ctype x, ctype y) \ { \ auto scale = std::max(std::abs(y.real), std::abs(y.imag)); \ auto n = std::ilogb(scale); \ auto yrs = std::scalbn(y.real, -n); \ auto yis = std::scalbn(y.imag, -n); \ auto denom = y.real*yrs + y.imag*yis; \ return {(x.real*yrs + x.imag*yis)/denom, \ (x.imag*yrs - x.real*yis)/denom}; \ } \ \ inline ctype& operator+=(ctype& x, rtype y) \ { \ x.real += y; \ return x; \ } \ \ inline ctype& operator+=(ctype& x, ctype y) \ { \ x.real += y.real; x.imag += y.imag; \ return x; \ } \ \ inline ctype& operator-=(ctype& x, rtype y) \ { \ x.real -= y; \ return x; \ } \ \ inline ctype& operator-=(ctype& x, ctype y) \ { \ x.real -= y.real; x.imag -= y.imag; \ return x; \ } \ \ inline ctype& operator*=(ctype& x, rtype y) \ { \ x.real *= y; x.imag *= y; \ return x; \ } \ \ inline ctype& operator*=(ctype& x, ctype y) \ { \ x = x * y; \ return x; \ } \ \ inline ctype& operator/=(ctype& x, rtype y) \ { \ x.real /= y; x.imag /= y; \ return x; \ } \ \ inline ctype& operator/=(ctype& x, ctype y) \ { \ x = x / y; \ return x; \ } COMPLEX_MATH_OPS(float, scomplex); COMPLEX_MATH_OPS(double, dcomplex); blis-0.9.0/test/tensor_contraction/tcontract_example.cxx000066400000000000000000000742641422157504600236300ustar00rootroot00000000000000 #include "tcontract_ref.hpp" #include #include static constexpr dim_t BS_K = 8; struct packm_tensor_params_t { gint_t ndim_m, ndim_n; const dim_t *len_m, *len_n; const inc_t *stride_m, *stride_n; packm_tensor_params_t() {} packm_tensor_params_t( gint_t ndim_m, const dim_t* len_m, const inc_t* stride_m, gint_t ndim_n, const dim_t* len_n, const inc_t* stride_n ) : ndim_m(ndim_m), ndim_n(ndim_n), len_m(len_m), len_n(len_n), stride_m(stride_m), stride_n(stride_n) {} }; using gemm_tensor_params_t = packm_tensor_params_t; template void packm_ckx_nb ( bool conja, dim_t panel_dim, dim_t panel_len, dim_t panel_dim_max, dim_t panel_len_max, void* kappa, void* a, inc_t inca, inc_t* bsa, inc_t* scata, void* p, inc_t ldp ) { T* restrict a_cast = ( T* )a; T* restrict p_cast = ( T* )p; auto kappa_cast = *( T* )kappa; if ( conja ) { for ( auto j0 = 0; j0 < panel_len; j0 += BS_K, bsa += BS_K, scata += BS_K ) { auto lda = *bsa; auto panel_len_j = std::min( panel_len-j0, BS_K ); if ( lda ) { T* restrict aj = a_cast + *scata; for ( auto j = 0; j < panel_len_j; j++ ) { for ( auto i = 0; i < panel_dim; i++ ) p_cast[ i ] = kappa_cast * conj( aj[ i*inca + j*lda ] ); for ( auto i = panel_dim; i < panel_dim_max; i++ ) p_cast[ i ] = convert(0.0); p_cast += ldp; } } else { for ( auto j = 0; j < panel_len_j; j++) { for ( auto i = 0; i < panel_dim; i++) p_cast[ i ] = kappa_cast * conj( a_cast[ i*inca + scata[j] ] ); for ( auto i = panel_dim; i < panel_dim_max; i++) p_cast[ i ] = convert(0.0); p_cast += ldp; } } } } else { for ( auto j0 = 0; j0 < panel_len; j0 += BS_K, bsa += BS_K, scata += BS_K ) { auto lda = *bsa; auto panel_len_j = std::min( panel_len-j0, BS_K ); if ( lda ) { T* restrict aj = a_cast + *scata; for ( auto j = 0; j < panel_len_j; j++ ) { for ( auto i = 0; i < panel_dim; i++ ) p_cast[ i ] = kappa_cast * aj[ i*inca + j*lda ]; for ( auto i = panel_dim; i < panel_dim_max; i++ ) p_cast[ i ] = convert(0.0); p_cast += ldp; } } else { for ( auto j = 0; j < panel_len_j; j++ ) { for ( auto i = 0; i < panel_dim; i++ ) p_cast[ i ] = kappa_cast * a_cast[ i*inca + scata[j] ]; for ( auto i = panel_dim; i < panel_dim_max; i++ ) p_cast[ i ] = convert(0.0); p_cast += ldp; } } } } for ( auto j = panel_len; j < panel_len_max; j++) { for ( auto i = 0; i < panel_dim_max; i++) p_cast[ i ] = convert(0.0); p_cast += ldp; } } template void packm_ckx_ss ( bool conja, dim_t panel_dim, dim_t panel_len, dim_t panel_dim_max, dim_t panel_len_max, void* kappa, void* a, inc_t* inca, inc_t* scata, void* p, inc_t ldp ) { T* restrict a_cast = ( T* )a; T* restrict p_cast = ( T* )p; auto kappa_cast = *( T* )kappa; if ( conja ) { for (dim_t j = 0;j < panel_len;j++) { for (dim_t i = 0;i < panel_dim;i++) p_cast[ i ] = kappa_cast * conj( a_cast[ inca[i] + scata[j] ] ); for (dim_t i = panel_dim;i < panel_dim_max;i++) p_cast[ i ] = convert(0.0); p_cast += ldp; } } else { for (dim_t j = 0;j < panel_len;j++) { for (dim_t i = 0;i < panel_dim;i++) p_cast[ i ] = kappa_cast * a_cast[ inca[i] + scata[j] ]; for (dim_t i = panel_dim;i < panel_dim_max;i++) p_cast[ i ] = convert(0.0); p_cast += ldp; } } for (dim_t j = panel_len;j < panel_len_max;j++) { for (dim_t i = 0;i < panel_dim_max;i++) p_cast[ i ] = convert(0.0); p_cast += ldp; } } #undef GENTFUNC #define GENTFUNC(ctype,ch,op) \ static auto PASTEMAC(ch,op) = &packm_ckx_nb; INSERT_GENTFUNC_BASIC0(packm_ckx_nb); #undef GENTFUNC #define GENTFUNC(ctype,ch,op) \ static auto PASTEMAC(ch,op) = &packm_ckx_ss; INSERT_GENTFUNC_BASIC0(packm_ckx_ss); static decltype(&packm_ckx_nb) GENARRAY( packm_ckx_nb_ukrs, packm_ckx_nb ); static decltype(&packm_ckx_ss) GENARRAY( packm_ckx_ss_ukrs, packm_ckx_ss ); static void fill_scatter ( gint_t ndim, const dim_t* restrict len, const inc_t* restrict stride, dim_t BS, inc_t off, dim_t size, inc_t* restrict scat, inc_t* restrict bs ) { if ( size == 0 ) return; if ( ndim == 0 ) { *scat = 0; *bs = 0; return; } if ( ndim == 1 ) { auto l = *len; auto s = *stride; for ( auto i = 0; i < l; i++ ) { scat[i] = i*s; bs[i] = s; } } dim_t tot_len = 1; for ( auto i = 0; i < ndim; i++ ) tot_len *= len[i]; assert(off >= 0); assert(size >= 0); assert(off+size <= tot_len); auto len0 = len[0]; auto stride0 = stride[0]; auto off0 = off % len0; auto off1 = off / len0; auto size1 = ( size + off0 + len0 - 1) / len0; inc_t pos1 = 0; inc_t idx = 0; for_each( ndim-1, len+1, off1, size1, pos1, stride+1, [&] { auto pos = pos1 + off0 * stride0; auto len_i = std::min( len0-off0, size-idx ); for ( auto i = 0; i < len_i; i++ ) { scat[idx++] = pos; pos += stride0; } off0 = 0; }); assert(idx == size); for ( idx = 0; idx < size; idx += BS ) { auto len_i = std::min( BS, size-idx ); auto s = stride0; for ( auto i = idx; i < idx+len_i-1; i++) { if (scat[i+1]-scat[i] != s) { s = 0; break; } } bs[idx] = s; } } void packm_tensor ( obj_t* a, obj_t* p, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ) { // We begin by copying the fields of A. bli_obj_alias_to( a, p ); // Get information about data types. auto dt = bli_obj_dt( a ); auto dt_tar = bli_obj_target_dt( a ); auto dt_scalar = bli_obj_scalar_dt( a ); auto dt_size = bli_dt_size( dt ); if ( dt_scalar != dt || dt_tar != dt ) bli_abort(); // Extract various fields from the control tree. auto bmult_id_m = bli_cntl_packm_params_bmid_m( cntl ); auto bmult_id_n = bli_cntl_packm_params_bmid_n( cntl ); auto schema = bli_cntl_packm_params_pack_schema( cntl ); auto bmult_m_def = bli_cntx_get_blksz_def_dt( dt_tar, bmult_id_m, cntx ); auto bmult_m_pack = bli_cntx_get_blksz_max_dt( dt_tar, bmult_id_m, cntx ); auto bmult_n_def = bli_cntx_get_blksz_def_dt( dt_tar, bmult_id_n, cntx ); if ( schema != BLIS_PACKED_ROW_PANELS && schema != BLIS_PACKED_COL_PANELS ) bli_abort(); // Store the pack schema to the object. bli_obj_set_pack_schema( schema, p ); // Clear the conjugation field from the object since matrix packing // in BLIS is deemed to take care of all conjugation necessary. bli_obj_set_conj( BLIS_NO_CONJUGATE, p ); // If we are packing micropanels, mark P as dense. bli_obj_set_uplo( BLIS_DENSE, p ); // Reset the view offsets to (0,0). bli_obj_set_offs( 0, 0, p ); // Compute the dimensions padded by the dimension multiples. These // dimensions will be the dimensions of the packed matrices, including // zero-padding, and will be used by the macro- and micro-kernels. // We compute them by starting with the effective dimensions of A (now // in P) and aligning them to the dimension multiples (typically equal // to register blocksizes). This does waste a little bit of space for // level-2 operations, but that's okay with us. auto m_p = bli_obj_length( p ); auto n_p = bli_obj_width( p ); auto m_p_pad = bli_align_dim_to_mult( m_p, bmult_m_def ); auto n_p_pad = bli_align_dim_to_mult( n_p, bmult_n_def ); // Save the padded dimensions into the packed object. It is important // to save these dimensions since they represent the actual dimensions // of the zero-padded matrix. bli_obj_set_padded_dims( m_p_pad, n_p_pad, p ); // The "panel stride" of a micropanel packed object is interpreted as // the distance between the (0,0) element of panel k and the (0,0) // element of panel k+1. We use the padded width computed above to // allow for zero-padding (if necessary/desired) along the far end // of each micropanel (ie: the right edge of the matrix). Zero-padding // can also occur along the long edge of the last micropanel if the m // dimension of the matrix is not a whole multiple of MR. auto ps_p = bmult_m_pack * n_p_pad; /* Compute the total number of iterations we'll need. */ auto n_iter = m_p_pad / bmult_m_def; // Store the strides and panel dimension in P. bli_obj_set_strides( 1, bmult_m_pack, p ); bli_obj_set_imag_stride( 1, p ); bli_obj_set_panel_dim( bmult_m_def, p ); bli_obj_set_panel_stride( ps_p, p ); bli_obj_set_panel_length( bmult_m_def, p ); bli_obj_set_panel_width( n_p, p ); // Compute the size of the packed buffer. auto size_p = ps_p * n_iter * dt_size; if ( size_p == 0 ) return; // Compute the size of the scatter and block-scatter vectors to the total. // It is never necessary to add padding for alignment because: // 1) ps_p is always even // 2) dt_size is a power of two >= 4 // 3) the alignment of the scatter vectors is at most 8 auto scat_size = 2 * (m_p + n_p) * sizeof(inc_t); // Update the buffer address in p to point to the buffer associated // with the mem_t entry acquired from the memory broker (now cached in // the control tree node). auto p_cast = (char*)bli_packm_alloc( size_p + scat_size, rntm, cntl, thread ); bli_obj_set_buffer( p_cast, p ); // Get the addresses of the scatter and block-scatter vectors. These are // placed directly after the packed matrix buffer. auto rscat = (inc_t*)(p_cast + size_p); auto rbs = rscat + m_p; auto cscat = rbs + m_p; auto cbs = cscat + n_p; auto a_cast = (char*)bli_obj_buffer_at_off( a ); auto panel_dim_off = bli_obj_row_off( a ); auto panel_len_off = bli_obj_col_off( a ); auto conja = bli_obj_conj_status( a ); auto params = (packm_tensor_params_t*)bli_obj_pack_params( a ); auto ndim_m = params->ndim_m; auto ndim_n = params->ndim_n; auto len_m = params->len_m; auto len_n = params->len_n; auto stride_m = params->stride_m; auto stride_n = params->stride_n; obj_t kappa_local; auto kappa_cast = (char*)bli_packm_scalar( &kappa_local, p ); auto packm_nb_ker = packm_ckx_nb_ukrs[ dt ]; auto packm_ss_ker = packm_ckx_ss_ukrs[ dt ]; a_cast -= ( panel_dim_off * stride_m[0] + panel_len_off * stride_n[0] ) * dt_size; /* Fill in the scatter and block-scatter vectors. This is done single-threaded for now. */ if ( bli_thread_am_ochief( thread ) ) { fill_scatter ( ndim_m, len_m, stride_m, bmult_m_def, panel_dim_off, m_p, rscat, rbs ); fill_scatter ( ndim_n, len_n, stride_n, BS_K, panel_len_off, n_p, cscat, cbs ); } /* Wait for the scatter vectors to be done. */ bli_thread_barrier( thread ); /* Query the number of threads and thread ids from the current thread's packm thrinfo_t node. */ auto nt = bli_thread_n_way( thread ); auto tid = bli_thread_work_id( thread ); /* Determine the thread range and increment using the current thread's packm thrinfo_t node. NOTE: The definition of bli_thread_range_jrir() will depend on whether slab or round-robin partitioning was requested at configure-time. */ dim_t it_start, it_end, it_inc; bli_thread_range_jrir( thread, n_iter, 1, FALSE, &it_start, &it_end, &it_inc ); /* Iterate over every logical micropanel in the source matrix. */ for ( auto it = 0; it < n_iter; it += 1 ) if ( bli_packm_my_iter( it, it_start, it_end, tid, nt ) ) { auto panel_dim_i = bli_min( bmult_m_def, m_p - it*bmult_m_def ); auto p_begin = p_cast + it*ps_p*dt_size; auto inca = rbs[ it*bmult_m_def ]; if ( inca ) { auto a_begin = a_cast + rscat[ it*bmult_m_def ]*dt_size; packm_nb_ker( conja, panel_dim_i, n_p, bmult_m_def, n_p_pad, kappa_cast, a_begin, inca, cbs, cscat, p_begin, bmult_m_pack ); } else { auto a_begin = a_cast; auto rscat_use = rscat + it*bmult_m_def; packm_ss_ker( conja, panel_dim_i, n_p, bmult_m_def, n_p_pad, kappa_cast, a_begin, rscat_use, cscat, p_begin, bmult_m_pack ); } } } #undef GENTFUNC #define GENTFUNC(ctype,ch,op) \ void PASTEMAC(ch,op) \ ( \ dim_t m, \ dim_t n, \ void* x, inc_t rs_x, inc_t cs_x, \ void* b, \ void* y, inc_t* rs_y, inc_t* cs_y \ ) \ { \ ctype* restrict x_cast = (ctype*)x; \ ctype b_cast = *(ctype*)b; \ ctype* restrict y_cast = (ctype*)y; \ \ if ( PASTEMAC(ch,eq0)( b_cast ) ) \ { \ for ( auto i = 0; i < m; i++ ) \ for ( auto j = 0; j < n; j++ ) \ PASTEMAC(ch,copys)( x_cast[ i*rs_x + j*cs_x ], y_cast[ rs_y[i] + cs_y[j] ] ); \ } \ else \ { \ for ( auto i = 0; i < m; i++ ) \ for ( auto j = 0; j < n; j++ ) \ PASTEMAC(ch,xpbys)( x_cast[ i*rs_x + j*cs_x ], b_cast, y_cast[ rs_y[i] + cs_y[j] ] ); \ } \ } INSERT_GENTFUNC_BASIC0(scatter_mxn); static decltype(&bli_sscatter_mxn) GENARRAY(scatter_mxn, scatter_mxn); void gemm_tensor ( obj_t* a, obj_t* b, obj_t* c, cntx_t* cntx, rntm_t* rntm, cntl_t* cntl, thrinfo_t* thread ) { auto dt = bli_obj_dt( c ); auto dt_size = bli_dt_size( dt ); auto m = bli_obj_length( c ); auto n = bli_obj_width( c ); auto k = bli_obj_width( a ); auto a_cast = (char*)bli_obj_buffer_at_off( a ); auto pd_a = bli_obj_panel_dim( a ); auto ps_a = bli_obj_panel_stride( a ); auto b_cast = (char*)bli_obj_buffer_at_off( b ); auto pd_b = bli_obj_panel_dim( b ); auto ps_b = bli_obj_panel_stride( b ); auto c_cast = (char*)bli_obj_buffer_at_off( c ); auto rs_c0 = bli_obj_row_stride( c ); auto cs_c0 = bli_obj_col_stride( c ); auto off_m = bli_obj_row_off( c ); auto off_n = bli_obj_col_off( c ); auto params = (gemm_tensor_params_t*)bli_obj_ker_params( c ); auto ndim_m = params->ndim_m; auto ndim_n = params->ndim_n; auto len_m = params->len_m; auto len_n = params->len_n; auto stride_m = params->stride_m; auto stride_n = params->stride_n; if ( rs_c0 != stride_m[0] || cs_c0 != stride_n[0] ) { std::swap( ndim_m, ndim_n ); std::swap( len_m, len_n ); std::swap( stride_m, stride_n ); } /* If any dimension is zero, return immediately. */ if ( bli_zero_dim3( m, n, k ) ) return; c_cast -= ( off_m * stride_m[0] + off_n * stride_n[0] ) * dt_size; // Detach and multiply the scalars attached to A and B. // NOTE: We know that the internal scalars of A and B are already of the // target datatypes because the necessary typecasting would have already // taken place during bli_packm_init(). obj_t scalar_a; obj_t scalar_b; bli_obj_scalar_detach( a, &scalar_a ); bli_obj_scalar_detach( b, &scalar_b ); bli_mulsc( &scalar_a, &scalar_b ); // Grab the addresses of the internal scalar buffers for the scalar // merged above and the scalar attached to C. // NOTE: We know that scalar_b is of type dt due to the above code // that casts the scalars of A and B to dt via scalar_a and scalar_b, // and we know that the internal scalar in C is already of the type dt // due to the casting in the implementation of bli_obj_scalar_attach(). auto alpha_cast = (char*)bli_obj_internal_scalar_buffer( &scalar_b ); auto beta_cast = (char*)bli_obj_internal_scalar_buffer( c ); /* Alias some constants to simpler names. */ auto MR = pd_a; auto NR = pd_b; /* Query the context for the micro-kernel address and cast it to its function pointer type. */ auto gemm_ukr = (gemm_ukr_vft)bli_cntx_get_l3_nat_ukr_dt( dt, BLIS_GEMM_UKR, cntx ); /* Temporary C buffer for edge cases. Note that the strides of this temporary buffer are set so that they match the storage of the original C matrix. For example, if C is column-stored, ct will be column-stored as well. */ char ct[ BLIS_STACK_BUF_MAX_SIZE ] __attribute__((aligned(BLIS_STACK_BUF_ALIGN_SIZE))); auto col_pref = bli_cntx_l3_vir_ukr_prefers_cols_dt( dt, BLIS_GEMM_UKR, cntx ); auto rs_ct = ( col_pref ? 1 : NR ); auto cs_ct = ( col_pref ? MR : 1 ); auto zero = (char*)bli_obj_buffer_for_const( dt, &BLIS_ZERO ); /* Assumptions/assertions: rs_a == 1 cs_a == PACKMR pd_a == MR ps_a == stride to next micro-panel of A rs_b == PACKNR cs_b == 1 pd_b == NR ps_b == stride to next micro-panel of B rs_c == (no assumptions) cs_c == (no assumptions) */ auto scat_size = 2 * (m + n) * sizeof(inc_t); auto rscat_c = (inc_t*)bli_packm_alloc_ex( scat_size, BLIS_BUFFER_FOR_GEN_USE, rntm, cntl, thread ); auto rbs_c = rscat_c + m; auto cscat_c = rbs_c + m; auto cbs_c = cscat_c + n; /* Fill in the scatter and block-scatter vectors. This is done single-threaded for now. */ if ( bli_thread_am_ochief( thread ) ) { fill_scatter ( ndim_m, len_m, stride_m, MR, off_m, m, rscat_c, rbs_c ); fill_scatter ( ndim_n, len_n, stride_n, NR, off_n, n, cscat_c, cbs_c ); } /* Wait for the scatter vectors to be done. */ bli_thread_barrier( thread ); /* Compute number of primary and leftover components of the m and n dimensions. */ auto n_iter = n / NR; auto n_left = n % NR; auto m_iter = m / MR; auto m_left = m % MR; if ( n_left ) ++n_iter; if ( m_left ) ++m_iter; /* Determine some increments used to step through A, B, and C. */ auto rstep_a = ps_a * dt_size; auto cstep_b = ps_b * dt_size; /* Save the virtual microkernel address and the params. */ auxinfo_t aux; bli_auxinfo_set_ukr( (void*)gemm_ukr, &aux ); bli_auxinfo_set_params( params, &aux ); /* The 'thread' argument points to the thrinfo_t node for the 2nd (jr) loop around the microkernel. Here we query the thrinfo_t node for the 1st (ir) loop around the microkernel. */ auto caucus = bli_thrinfo_sub_node( thread ); /* Query the number of threads and thread ids for each loop. */ auto jr_nt = bli_thread_n_way( thread ); auto jr_tid = bli_thread_work_id( thread ); auto ir_nt = bli_thread_n_way( caucus ); auto ir_tid = bli_thread_work_id( caucus ); /* Determine the thread range and increment for the 2nd and 1st loops. NOTE: The definition of bli_thread_range_jrir() will depend on whether slab or round-robin partitioning was requested at configure-time. */ dim_t jr_start, jr_end; dim_t ir_start, ir_end; dim_t jr_inc, ir_inc; bli_thread_range_jrir( thread, n_iter, 1, FALSE, &jr_start, &jr_end, &jr_inc ); bli_thread_range_jrir( caucus, m_iter, 1, FALSE, &ir_start, &ir_end, &ir_inc ); /* Loop over the n dimension (NR columns at a time). */ for ( auto j = jr_start; j < jr_end; j += jr_inc ) { auto b1 = b_cast + j * cstep_b; auto n_cur = ( bli_is_not_edge_f( j, n_iter, n_left ) ? NR : n_left ); /* Initialize our next panel of B to be the current panel of B. */ auto b2 = b1; /* Loop over the m dimension (MR rows at a time). */ for ( auto i = ir_start; i < ir_end; i += ir_inc ) { auto a1 = a_cast + i * rstep_a; auto rscat_c1 = rscat_c + i * MR; auto rbs_c1 = rbs_c + i * MR; auto cscat_c1 = cscat_c + j * NR; auto cbs_c1 = cbs_c + j * NR; auto m_cur = ( bli_is_not_edge_f( i, m_iter, m_left ) ? MR : m_left ); /* Compute the addresses of the next panels of A and B. */ auto a2 = bli_gemm_get_next_a_upanel( a1, rstep_a, ir_inc ); if ( bli_is_last_iter( i, ir_end, ir_tid, ir_nt ) ) { a2 = a_cast; b2 = bli_gemm_get_next_b_upanel( b1, cstep_b, jr_inc ); if ( bli_is_last_iter( j, jr_end, jr_tid, jr_nt ) ) b2 = b_cast; } /* Save addresses of next panels of A and B to the auxinfo_t object. */ bli_auxinfo_set_next_a( a2, &aux ); bli_auxinfo_set_next_b( b2, &aux ); auto rs_c = *rbs_c1; auto cs_c = *cbs_c1; if ( rs_c && cs_c ) { auto c11 = c_cast + ( *rscat_c1 + *cscat_c1 ) * dt_size; /* Invoke the gemm micro-kernel. */ gemm_ukr ( m_cur, n_cur, k, alpha_cast, a1, b1, beta_cast, c11, rs_c, cs_c, &aux, cntx ); } else { /* Invoke the gemm micro-kernel. */ gemm_ukr ( MR, NR, k, alpha_cast, a1, b1, zero, &ct, rs_ct, cs_ct, &aux, cntx ); /* Scatter to C. */ scatter_mxn[ dt ] ( m_cur, n_cur, &ct, rs_ct, cs_ct, beta_cast, c_cast, rscat_c1, cscat_c1 ); } } } } static bool has_unit_stride( const std::vector& stride ) { for ( auto s : stride ) if ( s == 1 ) return true; return false; } void tcontract( num_t dt, const std::vector& m, const std::vector& n, const std::vector& k, const void* alpha, const void* a, std::vector rs_a, std::vector cs_a, const void* b, std::vector rs_b, std::vector cs_b, const void* beta, void* c, std::vector rs_c, std::vector cs_c ) { if ( rs_a.size() != m.size() || rs_b.size() != k.size() || rs_c.size() != m.size() ) bli_check_error_code( BLIS_INVALID_ROW_STRIDE ); if ( cs_a.size() != k.size() || cs_b.size() != n.size() || cs_c.size() != n.size() ) bli_check_error_code( BLIS_INVALID_COL_STRIDE ); dim_t m_mat = 1; dim_t n_mat = 1; dim_t k_mat = 1; for ( auto& i : m ) m_mat *= i; for ( auto& i : n ) n_mat *= i; for ( auto& i : k ) k_mat *= i; auto& stride_m = has_unit_stride( rs_c ) ? rs_c : rs_a; for ( int i = 1;i < m.size(); i++ ) for ( int j = 0;j < m.size()-i; j++ ) if ( stride_m[j] > stride_m[j+1] ) { std::swap( rs_a[j], rs_a[j+1] ); std::swap( rs_c[j], rs_c[j+1] ); } auto& stride_n = has_unit_stride( cs_c ) ? cs_c : cs_b; for ( int i = 1;i < n.size(); i++ ) for ( int j = 0;j < n.size()-i; j++ ) if ( stride_n[j] > stride_n[j+1] ) { std::swap( cs_b[j], cs_b[j+1] ); std::swap( cs_c[j], cs_c[j+1] ); } auto& stride_k = has_unit_stride( cs_a ) ? cs_a : rs_b; for ( int i = 1;i < k.size(); i++ ) for ( int j = 0;j < k.size()-i; j++ ) if ( stride_k[j] > stride_k[j+1] ) { std::swap( cs_a[j], cs_a[j+1] ); std::swap( rs_b[j], rs_b[j+1] ); } if ( rs_a.empty() ) rs_a.push_back( 1 ); if ( cs_a.empty() ) cs_a.push_back( 1 ); if ( rs_b.empty() ) rs_b.push_back( 1 ); if ( cs_b.empty() ) cs_b.push_back( 1 ); if ( rs_c.empty() ) rs_c.push_back( 1 ); if ( cs_c.empty() ) cs_c.push_back( 1 ); obj_t a_o, b_o, c_o; bli_obj_create_with_attached_buffer( dt, m_mat, k_mat, const_cast(a), rs_a[0], cs_a[0], &a_o ); bli_obj_create_with_attached_buffer( dt, k_mat, n_mat, const_cast(b), rs_b[0], cs_b[0], &b_o ); bli_obj_create_with_attached_buffer( dt, m_mat, n_mat, c , rs_c[0], cs_c[0], &c_o ); packm_tensor_params_t params_a( m.size(), m.data(), rs_a.data(), k.size(), k.data(), cs_a.data() ); packm_tensor_params_t params_b( n.size(), n.data(), cs_b.data(), k.size(), k.data(), rs_b.data() ); gemm_tensor_params_t params_c( m.size(), m.data(), rs_c.data(), n.size(), n.data(), cs_c.data() ); bli_obj_set_pack_fn( packm_tensor, &a_o ); bli_obj_set_pack_fn( packm_tensor, &b_o ); bli_obj_set_ker_fn( gemm_tensor, &c_o ); bli_obj_set_pack_params( ¶ms_a, &a_o ); bli_obj_set_pack_params( ¶ms_b, &b_o ); bli_obj_set_ker_params( ¶ms_c, &c_o ); obj_t alpha_o, beta_o; bli_obj_create_1x1_with_attached_buffer( dt, const_cast(alpha), &alpha_o ); bli_obj_create_1x1_with_attached_buffer( dt, const_cast(beta), &beta_o ); rntm_t rntm; bli_rntm_init_from_global( &rntm ); bli_rntm_disable_l3_sup( &rntm ); bli_gemm_ex( &alpha_o, &a_o, &b_o, &beta_o, &c_o, NULL, &rntm ); } int main() { auto N = 5; gint_t ndim_a = 4; gint_t ndim_b = 4; gint_t ndim_c = 4; std::vector len_a(ndim_a, N); std::vector len_b(ndim_b, N); std::vector len_c(ndim_c, N); std::vector stride_a(ndim_a, 1); std::vector stride_b(ndim_b, 1); std::vector stride_c(ndim_c, 1); for ( gint_t i = 1; i < ndim_a; i++ ) stride_a[i] = stride_a[i-1] * len_a[i - 1]; for ( gint_t i = 1; i < ndim_b; i++ ) stride_b[i] = stride_b[i-1] * len_b[i - 1]; for ( gint_t i = 1; i < ndim_c; i++ ) stride_c[i] = stride_c[i-1] * len_c[i - 1]; std::vector dim_a(ndim_a); std::vector dim_b(ndim_b); std::vector dim_c(ndim_c); std::iota(dim_a.begin(), dim_a.end(), 0); std::iota(dim_b.begin(), dim_b.end(), 0); std::iota(dim_c.begin(), dim_c.end(), 0); for ( int dt_ = BLIS_DT_LO; dt_ <= BLIS_DT_HI; dt_++ ) do do do { auto dt = ( num_t )dt_; auto ndim_m = (ndim_a + ndim_c - ndim_b)/2; auto ndim_k = (ndim_a + ndim_b - ndim_c)/2; std::vector m(len_a.begin(), len_a.begin()+ndim_m); std::vector n(len_b.begin()+ndim_k, len_b.end()); std::vector k(len_b.begin(), len_b.begin()+ndim_k); std::vector rs_a(stride_a.begin(), stride_a.begin()+ndim_m); std::vector cs_a(stride_a.begin()+ndim_m, stride_a.end()); std::vector rs_b(stride_b.begin(), stride_b.begin()+ndim_k); std::vector cs_b(stride_b.begin()+ndim_k, stride_b.end()); std::vector rs_c(stride_c.begin(), stride_c.begin()+ndim_m); std::vector cs_c(stride_c.begin()+ndim_m, stride_c.end()); dim_t m_tot = 1; dim_t n_tot = 1; dim_t k_tot = 1; for ( auto i : m ) m_tot *= i; for ( auto i : n ) n_tot *= i; for ( auto i : k ) k_tot *= i; obj_t a, b, c, c_ref, norm; bli_obj_create( dt, m_tot*k_tot, 1, 1, 1, &a ); bli_obj_create( dt, k_tot*n_tot, 1, 1, 1, &b ); bli_obj_create( dt, m_tot*n_tot, 1, 1, 1, &c ); bli_obj_create( dt, m_tot*n_tot, 1, 1, 1, &c_ref ); bli_obj_create_1x1( bli_dt_proj_to_real( dt ), &norm ); bli_randv( &a ); bli_randv( &b ); bli_randv( &c ); bli_copyv( &c, &c_ref ); tcontract( dt, m, n, k, bli_obj_buffer_for_const( dt, &BLIS_ONE ), bli_obj_buffer( &a ), rs_a, cs_a, bli_obj_buffer( &b ), rs_b, cs_b, bli_obj_buffer_for_const( dt, &BLIS_ZERO ), bli_obj_buffer( &c ), rs_c, cs_c ); tcontract_ref( dt, m, n, k, bli_obj_buffer_for_const( dt, &BLIS_ONE ), bli_obj_buffer( &a ), rs_a, cs_a, bli_obj_buffer( &b ), rs_b, cs_b, bli_obj_buffer_for_const( dt, &BLIS_ZERO ), bli_obj_buffer( &c_ref ), rs_c, cs_c ); bli_subv( &c_ref, &c ); bli_normfv( &c, &norm ); double normr, normi; bli_getsc( &norm, &normr, &normi ); printf("dt: %d, dim_a: [%d,%d,%d,%d], dim_b: [%d,%d,%d,%d], dim_c: [%d,%d,%d,%d], norm: %g\n", dt, dim_a[0], dim_a[1], dim_a[2], dim_a[3], dim_b[0], dim_b[1], dim_b[2], dim_b[3], dim_c[0], dim_c[1], dim_c[2], dim_c[3], normr / std::sqrt( bli_obj_vector_dim( &c ) ) ); bli_obj_free( &a ); bli_obj_free( &b ); bli_obj_free( &c ); bli_obj_free( &c_ref ); } while (std::next_permutation(dim_a.begin(), dim_a.end())); while (std::next_permutation(dim_b.begin(), dim_b.end())); while (std::next_permutation(dim_c.begin(), dim_c.end())); } blis-0.9.0/test/tensor_contraction/tcontract_ref.cxx000066400000000000000000000043321422157504600227360ustar00rootroot00000000000000#include "tcontract_ref.hpp" template void tcontract_ref( const std::vector& m, const std::vector& n, const std::vector& k, const void* alpha, const void* a, const std::vector& rs_a, const std::vector& cs_a, const void* b, const std::vector& rs_b, const std::vector& cs_b, const void* beta, void* c, const std::vector& rs_c, const std::vector& cs_c ) { auto alpha_cast = *( T* )alpha; auto beta_cast = *( T* )beta; auto a_cast = ( T* )a; auto b_cast = ( T* )b; auto c_cast = ( T* )c; for_each(m.size(), m.data(), a_cast, rs_a.data(), c_cast, rs_c.data(), [&] { for_each(n.size(), n.data(), b_cast, cs_b.data(), c_cast, cs_c.data(), [&] { auto ab = convert(0.0); for_each(k.size(), k.data(), a_cast, cs_a.data(), b_cast, rs_b.data(), [&] { ab += (*a_cast) * (*b_cast); }); if ( beta_cast == convert(0.0) ) { *c_cast = alpha_cast * ab; } else { *c_cast = alpha_cast * ab + beta_cast * (*c_cast); } }); assert(b_cast == b); }); assert(a_cast == a); assert(c_cast == c); } #undef GENTFUNC #define GENTFUNC(ctype,ch,op) \ static auto PASTEMAC(ch,op) = &tcontract_ref; INSERT_GENTFUNC_BASIC0(tcontract_ref); static decltype(&tcontract_ref) GENARRAY( tcontract_ref_impl, tcontract_ref ); void tcontract_ref( num_t dt, const std::vector& m, const std::vector& n, const std::vector& k, const void* alpha, const void* a, const std::vector& rs_a, const std::vector& cs_a, const void* b, const std::vector& rs_b, const std::vector& cs_b, const void* beta, void* c, const std::vector& rs_c, const std::vector& cs_c ) { tcontract_ref_impl[ dt ] ( m, n, k, alpha, a, rs_a, cs_a, b, rs_b, cs_b, beta, c, rs_c, cs_c ); } blis-0.9.0/test/tensor_contraction/tcontract_ref.hpp000066400000000000000000000053101422157504600227200ustar00rootroot00000000000000#include "blis.h" #include "complex_math.hpp" #include #include #include inline void increment(inc_t, gint_t) {} template void increment(inc_t n, gint_t i, T& off, const inc_t* s, Args&... args) { off += s[i]*n; increment(n, i, args...); } template void for_each_impl(gint_t ndim, const dim_t* n, dim_t off, dim_t len, Body& body, Args&... args) { std::array i = {}; assert( ndim <= i.size() ); if ( off ) { for ( gint_t k = 0; k < ndim; k++ ) { i[k] = off % n[k]; off /= n[k]; increment(i[k], k, args...); } } for ( dim_t pos = 0; pos < len; pos++ ) { body(); for ( gint_t k = 0; k < ndim; k++ ) { if ( i[k] == n[k]-1 ) { increment(-i[k], k, args...); i[k] = 0; } else { increment(1, k, args...); i[k]++; break; } } } } template void for_each(gint_t ndim, const dim_t* n, dim_t off, dim_t len, T& a, const inc_t* s_a, Body&& body) { for_each_impl( ndim, n, off, len, body, a, s_a ); } template void for_each(gint_t ndim, const dim_t* n, dim_t off, dim_t len, T& a, const inc_t* s_a, T& b, const inc_t* s_b, Body&& body) { for_each_impl( ndim, n, off, len, body, a, s_a, b, s_b ); } template void for_each(gint_t ndim, const dim_t* n, T& a, const inc_t* s_a, Body&& body) { dim_t len = 1; for ( gint_t i = 0;i < ndim;i++ ) len *= n[i]; for_each_impl( ndim, n, 0, len, body, a, s_a ); } template void for_each(gint_t ndim, const dim_t* n, T& a, const inc_t* s_a, T& b, const inc_t* s_b, Body&& body) { dim_t len = 1; for ( gint_t i = 0;i < ndim;i++ ) len *= n[i]; for_each_impl( ndim, n, 0, len, body, a, s_a, b, s_b ); } void tcontract_ref( num_t dt, const std::vector& m, const std::vector& n, const std::vector& k, const void* alpha, const void* a, const std::vector& rs_a, const std::vector& cs_a, const void* b, const std::vector& rs_b, const std::vector& cs_b, const void* beta, void* c, const std::vector& rs_c, const std::vector& cs_c ); blis-0.9.0/test/test_axpbyv.c000066400000000000000000000213441422157504600161560ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifdef WIN32 #include #else #include #endif #include "blis.h" //#define PRINT #ifdef BLIS_ENABLE_CBLAS //#define CHECK_CBLAS #endif #ifdef CHECK_CBLAS #include "cblas.h" #endif /* * BLIS interface API will be called by default. * To call BLAS API, modify line 159 to '#if 0'. * To call cblas API, modify line 159 to '#if 0'and define the * macro 'CHECK_CBLAS' in line 44 * *Sample prototype for BLAS interface API is as follows: * n alpha x incx beta y incy *void daxpbyv_( int*, double*, double*, int*, double*, double*, int* ); */ int main( int argc, char** argv ) { obj_t x, y; obj_t y_save; obj_t alpha, beta; dim_t n; dim_t p; dim_t p_begin, p_end, p_inc; int n_input; num_t dt_x, dt_y; num_t dt_alpha, dt_beta; int r, n_repeats; num_t dt; double dtime; double dtime_save; double gflops; bli_init(); n_repeats = 3; #ifndef PRINT p_begin = 40; p_end = 4000; p_inc = 40; n_input = -1; #else p_begin = 16; p_end = 16; p_inc = 1; n_input = 15; #endif #if 1 dt = BLIS_FLOAT; //dt = BLIS_DOUBLE; #else //dt = BLIS_SCOMPLEX; dt = BLIS_DCOMPLEX; #endif dt_x = dt_y = dt_alpha = dt_beta = dt; // Begin with initializing the last entry to zero so that // matlab allocates space for the entire array once up-front. for ( p = p_begin; p + p_inc <= p_end; p += p_inc ) ; #ifdef BLIS printf( "data_axpbyv_blis" ); #else printf( "data_axpbyv_%s", BLAS ); #endif printf( "( %2lu, 1:2 ) = [ %4lu %7.2f ];\n", ( unsigned long )(p - p_begin)/p_inc + 1, ( unsigned long )0, 0.0 ); //for ( p = p_begin; p <= p_end; p += p_inc ) for ( p = p_end; p_begin <= p; p -= p_inc ) { if ( n_input < 0 ) n = p * ( dim_t )abs(n_input); else n = ( dim_t ) n_input; bli_obj_create( dt_alpha, 1, 1, 0, 0, &alpha ); bli_obj_create( dt_beta, 1, 1, 0, 0, &beta ); bli_obj_create( dt_x, n, 1, 0, 0, &x ); bli_obj_create( dt_y, n, 1, 0, 0, &y ); bli_obj_create( dt_y, n, 1, 0, 0, &y_save ); bli_randm( &x ); bli_randm( &y ); bli_setsc( (0.9/1.0), 0.2, &alpha ); bli_setsc( -(1.1/1.0), 0.3, &beta ); bli_copym( &y, &y_save ); dtime_save = 1.0e9; for ( r = 0; r < n_repeats; ++r ) { bli_copym( &y_save, &y ); dtime = bli_clock(); #ifdef PRINT bli_printm( "alpha", &alpha, "%4.1f", "" ); bli_printm( "beta" , &beta, "%4.1f", "" ); bli_printm( "x", &x, "%4.1f", "" ); bli_printm( "y", &y, "%4.1f", "" ); #endif #ifdef BLIS bli_axpbyv( &alpha, &x, &beta, &y ); #else if ( bli_is_float( dt ) ) { f77_int nn = bli_obj_length( &x ); f77_int incx = bli_obj_vector_inc( &x ); f77_int incy = bli_obj_vector_inc( &y ); float alphap = *(( float * )bli_obj_buffer( &alpha )); float betap = *(( float * )bli_obj_buffer( &beta )); float* xp = bli_obj_buffer( &x ); float* yp = bli_obj_buffer( &y ); #ifdef CHECK_CBLAS cblas_saxpby( nn, alphap, xp, incx, betap, yp, incy ); #else saxpby_( &nn, &alphap, xp, &incx, &betap, yp, &incy ); #endif } else if ( bli_is_double( dt ) ) { f77_int nn = bli_obj_length( &x ); f77_int incx = bli_obj_vector_inc( &x ); f77_int incy = bli_obj_vector_inc( &y ); double alphap = *(( double * )bli_obj_buffer( &alpha )); double betap = *(( double * )bli_obj_buffer( &beta )); double* xp = bli_obj_buffer( &x ); double* yp = bli_obj_buffer( &y ); #ifdef CHECK_CBLAS cblas_daxpby( nn, alphap, xp, incx, betap, yp, incy ); #else daxpby_( &nn, &alphap, xp, &incx, &betap, yp, &incy ); #endif } else if ( bli_is_scomplex( dt ) ) { f77_int nn = bli_obj_length( &x ); f77_int incx = bli_obj_vector_inc( &x ); f77_int incy = bli_obj_vector_inc( &y ); void* alphap = bli_obj_buffer( &alpha ); void* betap = bli_obj_buffer( &beta ); void* xp = bli_obj_buffer( &x ); void* yp = bli_obj_buffer( &y ); #ifdef CHECK_CBLAS cblas_caxpby( nn, alphap, xp, incx, betap, yp, incy ); #else caxpby_( &nn, ( scomplex* )alphap, ( scomplex* )xp, &incx, ( scomplex* )betap, ( scomplex* )yp, &incy ); #endif } else if ( bli_is_dcomplex( dt )) { f77_int nn = bli_obj_length( &x ); f77_int incx = bli_obj_vector_inc( &x ); f77_int incy = bli_obj_vector_inc( &y ); void* alphap = bli_obj_buffer( &alpha ); void* betap = bli_obj_buffer( &beta ); void* xp = bli_obj_buffer( &x ); void* yp = bli_obj_buffer( &y ); #ifdef CHECK_CBLAS cblas_zaxpby( nn, alphap, xp, incx, betap, yp, incy ); #else zaxpby_( &nn, ( dcomplex* )alphap, ( dcomplex* )xp, &incx, ( dcomplex* )betap, ( dcomplex* )yp, &incy ); #endif } #endif #ifdef PRINT bli_printm( "y after", &y, "%4.1f", "" ); exit(1); #endif dtime_save = bli_clock_min_diff( dtime_save, dtime ); } gflops = ( 3.0 * n ) / ( dtime_save * 1.0e9 ); #ifdef BLIS printf( "data_axpbyv_blis" ); #else printf( "data_axpbyv_%s", BLAS ); #endif printf( "( %2lu, 1:2 ) = [ %4lu %7.2f ];\n", ( unsigned long )(p - p_begin)/p_inc + 1, ( unsigned long )n, gflops ); bli_obj_free( &alpha ); bli_obj_free( &beta ); bli_obj_free( &x ); bli_obj_free( &y ); bli_obj_free( &y_save ); } bli_finalize(); return 0; } blis-0.9.0/test/test_axpyv.c000066400000000000000000000120151422157504600160070ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifdef WIN32 #include #else #include #endif #include "blis.h" // n alpha x incx y incy //void daxpyv_( int*, double*, double*, int*, double*, int* ); //#define PRINT int main( int argc, char** argv ) { obj_t x, y; obj_t y_save; obj_t alpha; dim_t n; dim_t p; dim_t p_begin, p_end, p_inc; int n_input; num_t dt_x, dt_y; num_t dt_alpha; int r, n_repeats; num_t dt; double dtime; double dtime_save; double gflops; bli_init(); n_repeats = 3; #ifndef PRINT p_begin = 40; p_end = 4000; p_inc = 40; n_input = -1; #else p_begin = 16; p_end = 16; p_inc = 1; n_input = 15; #endif #if 1 dt = BLIS_FLOAT; //dt = BLIS_DOUBLE; #else //dt = BLIS_SCOMPLEX; dt = BLIS_DCOMPLEX; #endif dt_x = dt_y = dt_alpha = dt; // Begin with initializing the last entry to zero so that // matlab allocates space for the entire array once up-front. for ( p = p_begin; p + p_inc <= p_end; p += p_inc ) ; #ifdef BLIS printf( "data_axpyv_blis" ); #else printf( "data_axpyv_%s", BLAS ); #endif printf( "( %2lu, 1:2 ) = [ %4lu %7.2f ];\n", ( unsigned long )(p - p_begin)/p_inc + 1, ( unsigned long )0, 0.0 ); //for ( p = p_begin; p <= p_end; p += p_inc ) for ( p = p_end; p_begin <= p; p -= p_inc ) { if ( n_input < 0 ) n = p * ( dim_t )abs(n_input); else n = ( dim_t ) n_input; bli_obj_create( dt_alpha, 1, 1, 0, 0, &alpha ); bli_obj_create( dt_x, n, 1, 0, 0, &x ); bli_obj_create( dt_y, n, 1, 0, 0, &y ); bli_obj_create( dt_y, n, 1, 0, 0, &y_save ); bli_randm( &x ); bli_randm( &y ); bli_setsc( (2.0/1.0), 0.0, &alpha ); bli_copym( &y, &y_save ); dtime_save = 1.0e9; for ( r = 0; r < n_repeats; ++r ) { bli_copym( &y_save, &y ); dtime = bli_clock(); #ifdef PRINT bli_printm( "alpha", &alpha, "%4.1f", "" ); bli_printm( "x", &x, "%4.1f", "" ); bli_printm( "y", &y, "%4.1f", "" ); #endif #ifdef BLIS bli_axpyv( &alpha, &x, &y ); #else if ( bli_is_float( dt ) ) { f77_int nn = bli_obj_length( &x ); f77_int incx = bli_obj_vector_inc( &x ); f77_int incy = bli_obj_vector_inc( &y ); float* alphap = bli_obj_buffer( &alpha ); float* xp = bli_obj_buffer( &x ); float* yp = bli_obj_buffer( &y ); saxpy_( &nn, alphap, xp, &incx, yp, &incy ); } else if ( bli_is_double( dt ) ) { f77_int nn = bli_obj_length( &x ); f77_int incx = bli_obj_vector_inc( &x ); f77_int incy = bli_obj_vector_inc( &y ); double* alphap = bli_obj_buffer( &alpha ); double* xp = bli_obj_buffer( &x ); double* yp = bli_obj_buffer( &y ); daxpy_( &nn, alphap, xp, &incx, yp, &incy ); } #endif #ifdef PRINT bli_printm( "y after", &y, "%4.1f", "" ); exit(1); #endif dtime_save = bli_clock_min_diff( dtime_save, dtime ); } gflops = ( 2.0 * n ) / ( dtime_save * 1.0e9 ); #ifdef BLIS printf( "data_axpyv_blis" ); #else printf( "data_axpyv_%s", BLAS ); #endif printf( "( %2lu, 1:2 ) = [ %4lu %7.2f ];\n", ( unsigned long )(p - p_begin)/p_inc + 1, ( unsigned long )n, gflops ); bli_obj_free( &alpha ); bli_obj_free( &x ); bli_obj_free( &y ); bli_obj_free( &y_save ); } bli_finalize(); return 0; } blis-0.9.0/test/test_copyv.c000066400000000000000000000122731422157504600160060ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2019 - 2022, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include #include "blis.h" //#define BLIS_ACCURACY_TEST #ifdef BLIS_ACCURACY_TEST bool scompare_result( int n, float *x, int incx, float *y, int incy ) { for ( int i = 0; i < n; i++ ) { if ( (*x) != (*y) ) { printf( "%4f != %4f at location %d\n", *x, *y, i ); return FALSE; } x += incx; y += incy; } return TRUE; } bool dcompare_result( int n, double *x, int incx, double *y, int incy ) { for ( int i = 0; i < n; i++ ) { if ( (*x) != (*y) ) { printf( "%4f != %4f at location %d\n", *x, *y, i ); return FALSE; } x += incx; y += incy; } return TRUE; } #endif int main( int argc, char** argv ) { obj_t x, y; dim_t n; dim_t p; dim_t p_begin, p_end, p_inc; int n_input, sizeof_dt; int r, n_repeats; num_t dt; double dtime; double dtime_save; double gbps; //bli_init(); n_repeats = 100000; #ifndef PRINT p_begin = 200; p_end = 100000; p_inc = 200; n_input = -1; #else p_begin = 16; p_end = 16; p_inc = 1; n_input = 16; #endif #if 1 // dt = BLIS_FLOAT; dt = BLIS_DOUBLE; #else //dt = BLIS_SCOMPLEX; dt = BLIS_DCOMPLEX; #endif if ( dt == BLIS_FLOAT ) sizeof_dt = sizeof( float ); else if ( dt == BLIS_DOUBLE ) sizeof_dt = sizeof( double ); printf( "executable\t n\t GBs per sec\n" ); for ( p = p_begin; p <= p_end; p += p_inc ) { if ( n_input < 0 ) n = p * ( dim_t )abs( n_input ); else n = ( dim_t ) n_input; bli_obj_create( dt, n, 1, 0, 0, &x ); bli_obj_create( dt, n, 1, 0, 0, &y ); bli_randm( &x ); dtime_save = DBL_MAX; for ( r = 0; r < n_repeats; ++r ) { dtime = bli_clock(); #ifdef BLIS bli_copyv( &x, &y ); #else if ( bli_is_float( dt ) ) { f77_int nn = bli_obj_length( &x ); f77_int incx = bli_obj_vector_inc( &x ); float* xp = bli_obj_buffer( &x ); f77_int incy = bli_obj_vector_inc( &y ); float* yp = bli_obj_buffer( &y ); scopy_( &nn, xp, &incx, yp, &incy ); } else if ( bli_is_double( dt ) ) { f77_int nn = bli_obj_length( &x ); f77_int incx = bli_obj_vector_inc( &x ); double* xp = bli_obj_buffer( &x ); f77_int incy = bli_obj_vector_inc( &y ); double* yp = bli_obj_buffer( &y ); dcopy_( &nn, xp, &incx, yp, &incy ); } #endif dtime_save = bli_clock_min_diff( dtime_save, dtime ); #ifdef BLIS_ACCURACY_TEST if ( dt == BLIS_FLOAT ) { int nn = bli_obj_length( &x ); int incx = bli_obj_vector_inc( &x ); float* xp = bli_obj_buffer( &x ); int incy = bli_obj_vector_inc( &y ); float* yp = bli_obj_buffer( &y ); if ( scompare_result( nn, xp, incx, yp, incy ) ) printf( "Copy Successful\n" ); else printf( "ALERT!!! Copy Failed\n" ); } if ( dt == BLIS_DOUBLE ) { int nn = bli_obj_length( &x ); int incx = bli_obj_vector_inc( &x ); double* xp = bli_obj_buffer( &x ); int incy = bli_obj_vector_inc( &y ); double* yp = bli_obj_buffer( &y ); if ( dcompare_result( nn, xp, incx, yp, incy ) ) printf( "Copy Successful\n" ); else printf( "ALERT!!! Copy Failed\n" ); } #endif } // Size of the vectors are incrementd by 1000, to test wide range of inputs. if ( p >= 1000 ) p_inc = 1000; if ( p >= 10000 ) p_inc = 10000; gbps = ( n * sizeof_dt ) / ( dtime_save * 1.0e9 ); #ifdef BLIS printf( "data_copyv_blis\t" ); #else printf( "data_copyv_%s\t", BLAS ); #endif printf( "%4lu\t %7.2f\n", ( unsigned long )n, gbps ); bli_obj_free( &x ); bli_obj_free( &y ); } //bli_finalize(); return 0; } blis-0.9.0/test/test_dotv.c000066400000000000000000000114151422157504600156170ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifdef WIN32 #include #else #include #endif #include "blis.h" // res n x incx y incy //double res = ddotv_( int*, double*, int*, double*, int* ); //#define PRINT int main( int argc, char** argv ) { obj_t x, y; obj_t res; dim_t n; dim_t p; dim_t p_begin, p_end, p_inc; int n_input; num_t dt_x, dt_y, dt_res; int r, n_repeats; num_t dt; double dtime; double dtime_save; double gflops; bli_init(); n_repeats = 10; #ifndef PRINT p_begin = 40; p_end = 4000; p_inc = 40; n_input = -1; #else p_begin = 16; p_end = 16; p_inc = 1; n_input = 16; #endif #if 1 dt = BLIS_FLOAT; //dt = BLIS_DOUBLE; #else //dt = BLIS_SCOMPLEX; dt = BLIS_DCOMPLEX; #endif dt_x = dt_y = dt_res = dt; // Begin with initializing the last entry to zero so that // matlab allocates space for the entire array once up-front. for ( p = p_begin; p + p_inc <= p_end; p += p_inc ) ; #ifdef BLIS printf( "data_dotv_blis" ); #else printf( "data_dotv_%s", BLAS ); #endif printf( "( %2lu, 1:2 ) = [ %4lu %7.2f ];\n", ( unsigned long )(p - p_begin)/p_inc + 1, ( unsigned long )0, 0.0 ); //for ( p = p_begin; p <= p_end; p += p_inc ) for ( p = p_end; p_begin <= p; p -= p_inc ) { if ( n_input < 0 ) n = p * ( dim_t )abs(n_input); else n = ( dim_t ) n_input; bli_obj_create( dt_x, n, 1, 0, 0, &x ); bli_obj_create( dt_y, n, 1, 0, 0, &y ); bli_obj_create( dt_res, 1, 1, 0, 0, &res ); bli_randm( &x ); bli_randm( &y ); dtime_save = 1.0e9; for ( r = 0; r < n_repeats; ++r ) { dtime = bli_clock(); #ifdef PRINT bli_printm( "x", &x, "%4.1f", "" ); bli_printm( "y", &y, "%4.1f", "" ); #endif #ifdef BLIS bli_dotv( &x, &y, &res); #else if ( bli_is_float( dt ) ) { f77_int nn = bli_obj_length( &x ); f77_int incx = bli_obj_vector_inc( &x ); f77_int incy = bli_obj_vector_inc( &y ); float* xp = bli_obj_buffer( &x ); float* yp = bli_obj_buffer( &y ); float* resp = bli_obj_buffer( &res ); *resp = sdot_( &nn, xp, &incx, yp, &incy ); } else if ( bli_is_double( dt ) ) { f77_int nn = bli_obj_length( &x ); f77_int incx = bli_obj_vector_inc( &x ); f77_int incy = bli_obj_vector_inc( &y ); double* xp = bli_obj_buffer( &x ); double* yp = bli_obj_buffer( &y ); double* resp = bli_obj_buffer( &res ); *resp = ddot_( &nn, xp, &incx, yp, &incy ); } #endif #ifdef PRINT bli_printm( "res after", &res, "%4.1f", "" ); exit(1); #endif dtime_save = bli_clock_min_diff( dtime_save, dtime ); } gflops = ( 2.0 * n ) / ( dtime_save * 1.0e9 ); #ifdef BLIS printf( "data_dotv_blis" ); #else printf( "data_dotv_%s", BLAS ); #endif printf( "( %2lu, 1:2 ) = [ %4lu %7.2f ];\n", ( unsigned long )(p - p_begin)/p_inc + 1, ( unsigned long )n, gflops ); bli_obj_free( &x ); bli_obj_free( &y ); bli_obj_free( &res ); } bli_finalize(); return 0; } blis-0.9.0/test/test_gemm.c000066400000000000000000000177521422157504600156020ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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 The University of Texas 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 COPYRIGHT HOLDER 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. */ #ifdef WIN32 #include #else #include #endif #include "blis.h" //#define PRINT int main( int argc, char** argv ) { obj_t a, b, c; obj_t c_save; obj_t alpha, beta; dim_t m, n, k; dim_t p; dim_t p_begin, p_end, p_inc; int m_input, n_input, k_input; num_t dt; int r, n_repeats; trans_t transa; trans_t transb; f77_char f77_transa; f77_char f77_transb; double dtime; double dtime_save; double gflops; //bli_init(); //bli_error_checking_level_set( BLIS_NO_ERROR_CHECKING ); n_repeats = 3; #ifndef PRINT p_begin = 200; p_end = 2000; p_inc = 200; m_input = -1; n_input = -1; k_input = -1; #else p_begin = 16; p_end = 16; p_inc = 1; m_input = 5; k_input = 6; n_input = 4; #endif #if 1 //dt = BLIS_FLOAT; dt = BLIS_DOUBLE; #else //dt = BLIS_SCOMPLEX; dt = BLIS_DCOMPLEX; #endif transa = BLIS_NO_TRANSPOSE; transb = BLIS_NO_TRANSPOSE; bli_param_map_blis_to_netlib_trans( transa, &f77_transa ); bli_param_map_blis_to_netlib_trans( transb, &f77_transb ); // Begin with initializing the last entry to zero so that // matlab allocates space for the entire array once up-front. for ( p = p_begin; p + p_inc <= p_end; p += p_inc ) ; #ifdef BLIS printf( "data_gemm_blis" ); #else printf( "data_gemm_%s", BLAS ); #endif printf( "( %2lu, 1:4 ) = [ %4lu %4lu %4lu %7.2f ];\n", ( unsigned long )(p - p_begin)/p_inc + 1, ( unsigned long )0, ( unsigned long )0, ( unsigned long )0, 0.0 ); //for ( p = p_begin; p <= p_end; p += p_inc ) for ( p = p_end; p_begin <= p; p -= p_inc ) { if ( m_input < 0 ) m = p * ( dim_t )abs(m_input); else m = ( dim_t ) m_input; if ( n_input < 0 ) n = p * ( dim_t )abs(n_input); else n = ( dim_t ) n_input; if ( k_input < 0 ) k = p * ( dim_t )abs(k_input); else k = ( dim_t ) k_input; bli_obj_create( dt, 1, 1, 0, 0, &alpha ); bli_obj_create( dt, 1, 1, 0, 0, &beta ); bli_obj_create( dt, m, k, 0, 0, &a ); bli_obj_create( dt, k, n, 0, 0, &b ); bli_obj_create( dt, m, n, 0, 0, &c ); bli_obj_create( dt, m, n, 0, 0, &c_save ); bli_randm( &a ); bli_randm( &b ); bli_randm( &c ); bli_obj_set_conjtrans( transa, &a ); bli_obj_set_conjtrans( transb, &b ); bli_setsc( (0.9/1.0), 0.2, &alpha ); bli_setsc( -(1.1/1.0), 0.3, &beta ); bli_copym( &c, &c_save ); dtime_save = DBL_MAX; for ( r = 0; r < n_repeats; ++r ) { bli_copym( &c_save, &c ); dtime = bli_clock(); #ifdef PRINT bli_printm( "a", &a, "%4.1f", "" ); bli_printm( "b", &b, "%4.1f", "" ); bli_printm( "c", &c, "%4.1f", "" ); #endif #ifdef BLIS bli_gemm( &alpha, &a, &b, &beta, &c ); #else if ( bli_is_float( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); float* alphap = bli_obj_buffer( &alpha ); float* ap = bli_obj_buffer( &a ); float* bp = bli_obj_buffer( &b ); float* betap = bli_obj_buffer( &beta ); float* cp = bli_obj_buffer( &c ); sgemm_( &f77_transa, &f77_transb, &mm, &nn, &kk, alphap, ap, &lda, bp, &ldb, betap, cp, &ldc ); } else if ( bli_is_double( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); double* alphap = bli_obj_buffer( &alpha ); double* ap = bli_obj_buffer( &a ); double* bp = bli_obj_buffer( &b ); double* betap = bli_obj_buffer( &beta ); double* cp = bli_obj_buffer( &c ); dgemm_( &f77_transa, &f77_transb, &mm, &nn, &kk, alphap, ap, &lda, bp, &ldb, betap, cp, &ldc ); } else if ( bli_is_scomplex( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); scomplex* alphap = bli_obj_buffer( &alpha ); scomplex* ap = bli_obj_buffer( &a ); scomplex* bp = bli_obj_buffer( &b ); scomplex* betap = bli_obj_buffer( &beta ); scomplex* cp = bli_obj_buffer( &c ); cgemm_( &f77_transa, &f77_transb, &mm, &nn, &kk, alphap, ap, &lda, bp, &ldb, betap, cp, &ldc ); } else if ( bli_is_dcomplex( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); dcomplex* alphap = bli_obj_buffer( &alpha ); dcomplex* ap = bli_obj_buffer( &a ); dcomplex* bp = bli_obj_buffer( &b ); dcomplex* betap = bli_obj_buffer( &beta ); dcomplex* cp = bli_obj_buffer( &c ); zgemm_( &f77_transa, &f77_transb, &mm, &nn, &kk, alphap, ap, &lda, bp, &ldb, betap, cp, &ldc ); } #endif #ifdef PRINT bli_printm( "c after", &c, "%4.1f", "" ); exit(1); #endif dtime_save = bli_clock_min_diff( dtime_save, dtime ); } gflops = ( 2.0 * m * k * n ) / ( dtime_save * 1.0e9 ); if ( bli_is_complex( dt ) ) gflops *= 4.0; #ifdef BLIS printf( "data_gemm_blis" ); #else printf( "data_gemm_%s", BLAS ); #endif printf( "( %2lu, 1:4 ) = [ %4lu %4lu %4lu %7.2f ];\n", ( unsigned long )(p - p_begin)/p_inc + 1, ( unsigned long )m, ( unsigned long )k, ( unsigned long )n, gflops ); bli_obj_free( &alpha ); bli_obj_free( &beta ); bli_obj_free( &a ); bli_obj_free( &b ); bli_obj_free( &c ); bli_obj_free( &c_save ); } //bli_finalize(); return 0; } blis-0.9.0/test/test_gemm3m.c000066400000000000000000000225121422157504600160300ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2020, Advanced Micro Devices, Inc. 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 The University of Texas 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 COPYRIGHT HOLDER 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. */ #ifdef WIN32 #include #else #include #endif #include "blis.h" #include "cblas.h" #define CBLAS //#define FILE_IN_OUT //#define PRINT #define MATRIX_INITIALISATION int main( int argc, char** argv ) { obj_t a, b, c; obj_t c_save; obj_t alpha, beta; dim_t m, n, k; dim_t p; dim_t p_begin, p_end, p_inc; int m_input, n_input, k_input; num_t dt; int r, n_repeats; trans_t transa; trans_t transb; f77_char f77_transa; f77_char f77_transb; double dtime; double dtime_save; double gflops; #ifdef FILE_IN_OUT FILE* fin = NULL; FILE* fout = NULL; #endif //bli_init(); //bli_error_checking_level_set( BLIS_NO_ERROR_CHECKING ); n_repeats = 3; #ifndef PRINT p_begin = 200; p_end = 2000; p_inc = 100; m_input = -1; n_input = -1; k_input = -1; #else p_begin = 16; p_end = 16; p_inc = 1; m_input = 5; k_input = 6; n_input = 4; #endif dt = BLIS_SCOMPLEX; //dt = BLIS_DCOMPLEX; transa = BLIS_NO_TRANSPOSE; transb = BLIS_NO_TRANSPOSE; bli_param_map_blis_to_netlib_trans( transa, &f77_transa ); bli_param_map_blis_to_netlib_trans( transb, &f77_transb ); // printf("BLIS Library version is : %s\n", bli_info_get_version_str()); #ifdef FILE_IN_OUT if ( argc < 3 ) { printf( "Usage: ./test_gemm_XX.x input.csv output.csv\n" ); exit(1); } fin = fopen( argv[1], "r" ); if ( fin == NULL ) { printf( "Error opening the file %s\n", argv[1] ); exit(1); } fout = fopen( argv[2], "w" ); if ( fout == NULL ) { printf( "Error opening output file %s\n", argv[2] ); exit(1); } fprintf( fout, "m\t k\t n\t cs_a\t cs_b\t cs_c\t gflops\t GEMM_Algo\n" ); printf( "~~~~~~~~~~_BLAS\t m\t k\t n\t cs_a\t cs_b\t cs_c \t gflops\t GEMM_Algo\n" ); inc_t cs_a; inc_t cs_b; inc_t cs_c; while ( fscanf(fin, "%lld %lld %lld %lld %lld %lld\n", &m, &k, &n, &cs_a, &cs_b, &cs_c) == 6 ) { if ( ( m > cs_a ) || ( k > cs_b ) || ( m > cs_c ) ) continue; // leading dimension should be greater than number of rows bli_obj_create( dt, 1, 1, 0, 0, &alpha); bli_obj_create( dt, 1, 1, 0, 0, &beta ); bli_obj_create( dt, m, k, 1, cs_a, &a ); bli_obj_create( dt, k, n, 1, cs_b, &b ); bli_obj_create( dt, m, n, 1, cs_c, &c ); bli_obj_create( dt, m, n, 1, cs_c, &c_save ); #ifdef MATRIX_INITIALISATION bli_randm( &a ); bli_randm( &b ); bli_randm( &c ); #endif bli_obj_set_conjtrans( transa, &a); bli_obj_set_conjtrans( transb, &b); //bli_setsc( 0.0, -1, &alpha ); //bli_setsc( 0.0, 1, &beta ); bli_setsc( -1, 0.0, &alpha ); bli_setsc( 1, 0.0, &beta ); #else for ( p = p_begin; p <= p_end; p += p_inc ) { if ( m_input < 0 ) m = p * ( dim_t )abs(m_input); else m = ( dim_t ) m_input; if ( n_input < 0 ) n = p * ( dim_t )abs(n_input); else n = ( dim_t ) n_input; if ( k_input < 0 ) k = p * ( dim_t )abs(k_input); else k = ( dim_t ) k_input; bli_obj_create( dt, 1, 1, 0, 0, &alpha ); bli_obj_create( dt, 1, 1, 0, 0, &beta ); bli_obj_create( dt, m, k, 0, 0, &a ); bli_obj_create( dt, k, n, 0, 0, &b ); bli_obj_create( dt, m, n, 0, 0, &c ); bli_obj_create( dt, m, n, 0, 0, &c_save ); #ifdef MATRIX_INITIALISATION bli_randm( &a ); bli_randm( &b ); bli_randm( &c ); #endif bli_obj_set_conjtrans( transa, &a ); bli_obj_set_conjtrans( transb, &b ); bli_setsc( (0.9/1.0), 0.2, &alpha ); bli_setsc( -(1.1/1.0), 0.3, &beta ); #endif bli_copym( &c, &c_save ); dtime_save = DBL_MAX; for ( r = 0; r < n_repeats; ++r ) { bli_copym( &c_save, &c ); dtime = bli_clock(); #ifdef PRINT bli_printm( "a", &a, "%4.1f", "" ); bli_printm( "b", &b, "%4.1f", "" ); bli_printm( "c", &c, "%4.1f", "" ); #endif #ifndef CBLAS if ( bli_is_scomplex( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); scomplex* alphap = bli_obj_buffer( &alpha ); scomplex* ap = bli_obj_buffer( &a ); scomplex* bp = bli_obj_buffer( &b ); scomplex* betap = bli_obj_buffer( &beta ); scomplex* cp = bli_obj_buffer( &c ); cgemm3m_( &f77_transa, &f77_transb, &mm, &nn, &kk, alphap, ap, &lda, bp, &ldb, betap, cp, &ldc ); } else if ( bli_is_dcomplex( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); dcomplex* alphap = bli_obj_buffer( &alpha ); dcomplex* ap = bli_obj_buffer( &a ); dcomplex* bp = bli_obj_buffer( &b ); dcomplex* betap = bli_obj_buffer( &beta ); dcomplex* cp = bli_obj_buffer( &c ); zgemm3m_( &f77_transa, &f77_transb, &mm, &nn, &kk, alphap, ap, &lda, bp, &ldb, betap, cp, &ldc ); } #else if ( bli_is_scomplex( dt ) ) { scomplex* ap = bli_obj_buffer( &a ); scomplex* bp = bli_obj_buffer( &b ); scomplex* cp = bli_obj_buffer( &c ); scomplex* alphap = bli_obj_buffer( &alpha ); scomplex* betap = bli_obj_buffer( &beta ); cblas_cgemm3m( CblasColMajor, CblasNoTrans, CblasNoTrans, m, n, k, (const void*)alphap, ap, m, bp, k, (const void*)betap, cp, m ); } else if (bli_is_dcomplex(dt)) { dcomplex* ap = bli_obj_buffer( &a ); dcomplex* bp = bli_obj_buffer( &b ); dcomplex* cp = bli_obj_buffer( &c ); dcomplex* alphap = bli_obj_buffer( &alpha ); dcomplex* betap = bli_obj_buffer( &beta ); cblas_zgemm3m( CblasColMajor, CblasNoTrans, CblasNoTrans, m, n, k, (const void*)alphap, ap, m, bp, k, (const void*)betap, cp, m ); } #endif #ifdef PRINT bli_printm( "c after", &c, "%4.6f", "" ); exit(1); #endif dtime_save = bli_clock_min_diff( dtime_save, dtime ); } gflops = ( 2.0 * m * k * n ) / ( dtime_save * 1.0e9 ); gflops *= 4.0; //to represent complex ops in gflops #ifdef BLIS printf( "data_gemm_blis" ); #else printf( "data_gemm_%s", BLAS ); #endif #ifdef FILE_IN_OUT printf("%6lu \t %4lu \t %4lu \t %4lu \t %4lu \t %4lu \t %6.3f\n", \ ( unsigned long )m, ( unsigned long )k, ( unsigned long )n, (unsigned long)cs_a, (unsigned long)cs_b, (unsigned long)cs_c, gflops); fprintf(fout, "%6lu \t %4lu \t %4lu \t %4lu \t %4lu \t %4lu \t %6.3f \n", \ ( unsigned long )m, ( unsigned long )k, ( unsigned long )n, (unsigned long)cs_a, (unsigned long)cs_b, (unsigned long)cs_c, gflops); fflush(fout); #else printf( "( %2lu, 1:4 ) = [ %4lu %4lu %4lu %7.2f ];\n", ( unsigned long )(p - p_begin)/p_inc + 1, ( unsigned long )m, ( unsigned long )k, ( unsigned long )n, gflops ); #endif bli_obj_free( &alpha ); bli_obj_free( &beta ); bli_obj_free( &a ); bli_obj_free( &b ); bli_obj_free( &c ); bli_obj_free( &c_save ); } //bli_finalize(); #ifdef FILE_IN_OUT fclose( fin ); fclose( fout ); #endif return 0; } blis-0.9.0/test/test_gemm_batch.c000066400000000000000000000441111422157504600167300ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved. 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 The University of Texas 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 COPYRIGHT HOLDER 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. */ #ifdef WIN32 #include #else #include #endif #include "blis.h" //#define CHECK_CBLAS #ifdef CHECK_CBLAS #include "cblas.h" #endif /* Format for FILE input * For each input set, first line contains 'storage scheme' * and 'group count' seperated by space. * Following 'group_count' number of lines contains all the parameters of * each group separated by space in each line in the following order: * tA tB m n k lda ldb ldc alpha_r alpha_i beta_r beta_i group_size * * Example: * c 2 * n n 4 8 4 4 4 4 1.1 0.0 0.9 0.0 2 * n n 3 3 6 3 6 3 1.0 0.0 2.0 0.0 2 * */ //#define FILE_IN_OUT #ifndef FILE_IN_OUT #define GRP_COUNT 2 #endif //#define PRINT int main( int argc, char** argv ) { num_t dt; char stor_scheme; dim_t i, j, idx; dim_t r, n_repeats; double dtime; double dtime_save; double gflops; dim_t total_count = 0; #if 1 dt = BLIS_FLOAT; //dt = BLIS_DOUBLE; #else dt = BLIS_SCOMPLEX; //dt = BLIS_DCOMPLEX; #endif n_repeats = 1; #ifdef FILE_IN_OUT FILE* fin = NULL; FILE* fout = NULL; if(argc < 3) { printf("Usage: ./test_gemm_batch_XX.x input.csv output.csv\n"); exit(1); } fin = fopen(argv[1], "r"); if( fin == NULL ) { printf("Error opening input file %s \n", argv[1]); exit(1); } fout = fopen(argv[2], "w"); if(fout == NULL) { printf("Error opening output file %s\n",argv[2]); exit(1); } dim_t GRP_COUNT; fprintf(fout, "m\t n\t k\t lda\t ldb\t ldc\t transa\t transb\t grp_size\n"); while(fscanf(fin, "%c %ld\n", &stor_scheme, &GRP_COUNT) == 2) { char transa[GRP_COUNT]; char transb[GRP_COUNT]; dim_t m[GRP_COUNT]; dim_t n[GRP_COUNT]; dim_t k[GRP_COUNT]; dim_t lda[GRP_COUNT]; dim_t ldb[GRP_COUNT]; dim_t ldc[GRP_COUNT]; double alpha_real[GRP_COUNT]; double alpha_imag[GRP_COUNT]; double beta_real[GRP_COUNT]; double beta_imag[GRP_COUNT]; dim_t group_size[GRP_COUNT]; obj_t alpha[GRP_COUNT], beta[GRP_COUNT]; total_count = 0; for(i = 0; i < GRP_COUNT; i++) { fscanf(fin, "%c %c %ld %ld %ld %ld %ld %ld %lf %lf %lf %lf %ld\n", &transa[i], &transb[i], &m[i], &n[i], &k[i], &lda[i], &ldb[i], &ldc[i], &alpha_real[i], &alpha_imag[i], &beta_real[i], &beta_imag[i], &group_size[i]); total_count += group_size[i]; } #else printf("m\t n\t k\t lda\t ldb\t ldc\t transa\t transb\t grp_size\n"); stor_scheme = 'c'; dim_t m[GRP_COUNT] = {4, 3}; dim_t n[GRP_COUNT] = {8, 3}; dim_t k[GRP_COUNT] = {4, 6}; dim_t lda[GRP_COUNT] = {4, 3}; dim_t ldb[GRP_COUNT] = {4, 6}; dim_t ldc[GRP_COUNT] = {4, 3}; char transa[GRP_COUNT] = {'N', 'N'}; char transb[GRP_COUNT] = {'N', 'N'}; double alpha_real[GRP_COUNT] = {1.1, 1.0}; double alpha_imag[GRP_COUNT] = {0.0, 0.0}; double beta_real[GRP_COUNT] = {0.9, 2.0}; double beta_imag[GRP_COUNT] = {0.0, 0.0}; dim_t group_size[GRP_COUNT] = {2,2}; obj_t alpha[GRP_COUNT], beta[GRP_COUNT]; total_count = 0; for(i = 0; i < GRP_COUNT; i++) total_count += group_size[i]; #endif obj_t a[total_count], b[total_count]; obj_t c[total_count], c_save[total_count]; f77_int f77_m[GRP_COUNT], f77_n[GRP_COUNT], f77_k[GRP_COUNT]; f77_int f77_lda[GRP_COUNT], f77_ldb[GRP_COUNT], f77_ldc[GRP_COUNT]; f77_int f77_group_size[GRP_COUNT]; f77_int f77_group_count = GRP_COUNT; #ifdef CHECK_CBLAS enum CBLAS_ORDER cblas_order; enum CBLAS_TRANSPOSE cblas_transa[GRP_COUNT]; enum CBLAS_TRANSPOSE cblas_transb[GRP_COUNT]; if(stor_scheme == 'R' || stor_scheme == 'r') cblas_order = CblasRowMajor; else cblas_order = CblasColMajor; #else f77_char f77_transa[GRP_COUNT]; f77_char f77_transb[GRP_COUNT]; if(stor_scheme == 'r' || stor_scheme == 'R' ) { printf("BLAS Interface doesn't support row-major order\n"); #ifdef FILE_IN_OUT continue; #else exit(1); #endif } #endif idx = 0; for(i = 0; i < GRP_COUNT; i++) { bli_obj_create(dt, 1, 1, 0, 0, &alpha[i]); bli_obj_create(dt, 1, 1, 0, 0, &beta[i] ); bli_setsc(alpha_real[i], alpha_imag[i], &alpha[i]); bli_setsc(beta_real[i], beta_imag[i], &beta[i] ); trans_t blis_transa, blis_transb; if(transa[i] == 't' || transa[i] == 'T') blis_transa = BLIS_TRANSPOSE; else if (transa[i] == 'c' || transa[i] == 'C') blis_transa = BLIS_CONJ_TRANSPOSE; else if ( transa[i] == 'n' || transa[i] == 'N') blis_transa = BLIS_NO_TRANSPOSE; else { printf("Illegal transA setting %c for group %ld\n", transa[i], i); exit(1); } if(transb[i] == 't' || transb[i] == 'T') blis_transb = BLIS_TRANSPOSE; else if (transb[i] == 'c' || transb[i] == 'C') blis_transb = BLIS_CONJ_TRANSPOSE; else if (transb[i] == 'n' || transb[i] == 'N') blis_transb = BLIS_NO_TRANSPOSE; else { printf("Illegal transB setting %c for group %ld\n", transb[i], i); exit(1); } #ifdef CHECK_CBLAS if(bli_is_trans( blis_transa )) cblas_transa[i] = CblasTrans; else if (bli_is_conjtrans( blis_transa )) cblas_transa[i] = CblasConjTrans; else cblas_transa[i] = CblasNoTrans; if(bli_is_trans( blis_transb )) cblas_transb[i] = CblasTrans; else if (bli_is_conjtrans( blis_transb )) cblas_transb[i] = CblasConjTrans; else cblas_transb[i] = CblasNoTrans; #else bli_param_map_blis_to_netlib_trans( blis_transa, &f77_transa[i]); bli_param_map_blis_to_netlib_trans( blis_transb, &f77_transb[i]); #endif dim_t m0_a, n0_a; dim_t m0_b, n0_b; bli_set_dims_with_trans( blis_transa, m[i], k[i], &m0_a, &n0_a ); bli_set_dims_with_trans( blis_transb, k[i], n[i], &m0_b, &n0_b ); if(stor_scheme == 'C' || stor_scheme == 'c') { for(j = 0; j < group_size[i]; j++) { bli_obj_create(dt, m0_a, n0_a, 1, lda[i], &a[idx]); bli_obj_create(dt, m0_b, n0_b, 1, ldb[i], &b[idx]); bli_obj_create(dt, m[i], n[i], 1, ldc[i], &c[idx]); bli_obj_create(dt, m[i], n[i], 1, ldc[i], &c_save[idx]); bli_randm( &a[idx] ); bli_randm( &b[idx] ); bli_randm( &c[idx] ); bli_obj_set_conjtrans(blis_transa, &a[idx]); bli_obj_set_conjtrans(blis_transb, &b[idx]); idx++; } } else if(stor_scheme == 'R' || stor_scheme == 'r') { for(j = 0; j < group_size[i]; j++) { bli_obj_create(dt, m0_a, n0_a, lda[i], 1, &a[idx]); bli_obj_create(dt, m0_b, n0_b, ldb[i], 1, &b[idx]); bli_obj_create(dt, m[i], n[i], ldc[i], 1, &c[idx]); bli_obj_create(dt, m[i], n[i], ldc[i], 1, &c_save[idx]); bli_randm( &a[idx] ); bli_randm( &b[idx] ); bli_randm( &c[idx] ); bli_obj_set_conjtrans(blis_transa, &a[idx]); bli_obj_set_conjtrans(blis_transb, &b[idx]); idx++; } } f77_m[i] = m[i]; f77_n[i] = n[i]; f77_k[i] = k[i]; f77_lda[i] = lda[i]; f77_ldb[i] = ldb[i]; f77_ldc[i] = ldc[i]; f77_group_size[i] = group_size[i]; } idx = 0; for(i = 0; i < GRP_COUNT; i++) for(j = 0; j < group_size[i]; j++) { bli_copym(&c[idx], &c_save[idx]); idx++; } dtime_save = DBL_MAX; for( r = 0; r < n_repeats; ++r ) { idx = 0; for(i = 0; i < GRP_COUNT; i++) for(j = 0; j < group_size[i]; j++) { bli_copym( &c_save[idx], &c[idx]); idx++; } dtime = bli_clock(); #ifdef PRINT idx = 0; for(i = 0; i < GRP_COUNT; i++) for(j = 0; j < group_size[i]; j++) { printf("Group: %ld Member: %ld\n", i, j); bli_printm("a", &a[idx], "%4.1f", ""); bli_printm("b", &b[idx], "%4.1f", ""); bli_printm("c", &c[idx], "%4.1f", ""); idx++; } #endif if(bli_is_float(dt)) { const float *ap[total_count], *bp[total_count]; float *cp[total_count]; float alphap[GRP_COUNT], betap[GRP_COUNT]; idx = 0; for(i = 0; i < GRP_COUNT; i++) { for(j = 0; j < group_size[i]; j++) { ap[idx] = bli_obj_buffer( &a[idx] ); bp[idx] = bli_obj_buffer( &b[idx] ); cp[idx] = bli_obj_buffer( &c[idx] ); idx++; } alphap[i] = *(float*)bli_obj_buffer_for_1x1(dt, &alpha[i]); betap[i] = *(float*)bli_obj_buffer_for_1x1(dt, &beta[i] ); } #ifdef CHECK_CBLAS cblas_sgemm_batch( cblas_order, cblas_transa, cblas_transb, f77_m, f77_n, f77_k, alphap, ap, f77_lda, bp, f77_ldb, betap, cp, f77_ldc, f77_group_count, f77_group_size ); #else sgemm_batch_( f77_transa, f77_transb, f77_m, f77_n, f77_k, alphap, ap, f77_lda, bp, f77_ldb, betap, cp, f77_ldc, &f77_group_count, f77_group_size ); #endif } else if(bli_is_double(dt)) { const double *ap[total_count], *bp[total_count]; double *cp[total_count]; double alphap[GRP_COUNT], betap[GRP_COUNT]; idx = 0; for(i = 0; i < GRP_COUNT; i++) { for(j = 0; j < group_size[i]; j++) { ap[idx] = bli_obj_buffer( &a[idx] ); bp[idx] = bli_obj_buffer( &b[idx] ); cp[idx] = bli_obj_buffer( &c[idx] ); idx++; } alphap[i] = *(double*)bli_obj_buffer_for_1x1(dt, &alpha[i]); betap[i] = *(double*)bli_obj_buffer_for_1x1(dt, &beta[i] ); } #ifdef CHECK_CBLAS cblas_dgemm_batch( cblas_order, cblas_transa, cblas_transb, f77_m, f77_n, f77_k, alphap, ap, f77_lda, bp, f77_ldb, betap, cp, f77_ldc, f77_group_count, f77_group_size ); #else dgemm_batch_( f77_transa, f77_transb, f77_m, f77_n, f77_k, alphap, ap, f77_lda, bp, f77_ldb, betap, cp, f77_ldc, &f77_group_count, f77_group_size ); #endif } else if(bli_is_scomplex(dt)) { const scomplex *ap[total_count], *bp[total_count]; scomplex *cp[total_count]; scomplex alphap[GRP_COUNT], betap[GRP_COUNT]; idx = 0; for(i = 0; i < GRP_COUNT; i++) { for(j = 0; j < group_size[i]; j++) { ap[idx] = bli_obj_buffer( &a[idx] ); bp[idx] = bli_obj_buffer( &b[idx] ); cp[idx] = bli_obj_buffer( &c[idx] ); idx++; } alphap[i] = *(scomplex*)bli_obj_buffer_for_1x1(dt, &alpha[i]); betap[i] = *(scomplex*)bli_obj_buffer_for_1x1(dt, &beta[i] ); } #ifdef CHECK_CBLAS cblas_cgemm_batch( cblas_order, cblas_transa, cblas_transb, f77_m, f77_n, f77_k, (const void*)alphap, (const void**)ap, f77_lda, (const void**)bp, f77_ldb, (const void*)betap, (void**)cp, f77_ldc, f77_group_count, f77_group_size ); #else cgemm_batch_( f77_transa, f77_transb, f77_m, f77_n, f77_k, alphap, ap, f77_lda, bp, f77_ldb, betap, cp, f77_ldc, &f77_group_count, f77_group_size ); #endif } else if(bli_is_dcomplex(dt)) { const dcomplex *ap[total_count], *bp[total_count]; dcomplex *cp[total_count]; dcomplex alphap[GRP_COUNT], betap[GRP_COUNT]; idx = 0; for(i = 0; i < GRP_COUNT; i++) { for(j = 0; j < group_size[i]; j++) { ap[idx] = bli_obj_buffer( &a[idx] ); bp[idx] = bli_obj_buffer( &b[idx] ); cp[idx] = bli_obj_buffer( &c[idx] ); idx++; } alphap[i] = *(dcomplex*)bli_obj_buffer_for_1x1(dt, &alpha[i]); betap[i] = *(dcomplex*)bli_obj_buffer_for_1x1(dt, &beta[i] ); } #ifdef CHECK_CBLAS cblas_zgemm_batch( cblas_order, cblas_transa, cblas_transb, f77_m, f77_n, f77_k, (const void*)alphap, (const void**)ap, f77_lda, (const void**)bp, f77_ldb, (const void*)betap, (void**)cp, f77_ldc, f77_group_count, f77_group_size ); #else zgemm_batch_( f77_transa, f77_transb, f77_m, f77_n, f77_k, alphap, ap, f77_lda, bp, f77_ldb, betap, cp, f77_ldc, &f77_group_count, f77_group_size ); #endif } #ifdef PRINT idx = 0; for(i = 0; i < GRP_COUNT; i++) for(j = 0; j < group_size[i]; j++) { printf("Group: %ld Member: %ld\n", i, j); bli_printm("c after", &c[idx], "%4.1f", ""); idx++; } #endif dtime_save = bli_clock_min_diff( dtime_save, dtime ); } dim_t fp_ops = 0; for(i = 0; i < GRP_COUNT; i++) fp_ops += 2.0 * m[i] * k[i] * n[i] * group_size[i]; gflops = fp_ops / (dtime_save * 1.0e9 ); if(bli_is_complex( dt ) ) gflops *= 4.0; #ifdef FILE_IN_OUT fprintf(fout, "Stor_scheme = %c, group_count = %lu, gflops = %7.2f\n", stor_scheme, GRP_COUNT, gflops); for(i = 0; i < GRP_COUNT; i++) fprintf(fout, "%4lu \t %4lu\t %4lu\t %4lu\t %4lu\t %4lu\t %c\t %c\t %4lu\n", m[i], n[i], k[i], lda[i], ldb[i], ldc[i], transa[i], transb[i], group_size[i]); fflush(fout); #else printf( "Stor_scheme = %c, group_count = %d, gflops = %7.2f\n", stor_scheme, GRP_COUNT, gflops); for(i = 0; i < GRP_COUNT; i++) printf("%4lu \t %4lu\t %4lu\t %4lu\t %4lu\t %4lu\t %c\t %c\t %4lu\n", m[i], n[i], k[i], lda[i], ldb[i], ldc[i], transa[i], transb[i], group_size[i]); #endif idx = 0; for(i = 0; i < GRP_COUNT; i++) { bli_obj_free( &alpha[i]); bli_obj_free( &beta[i] ); for(j = 0; j < group_size[i]; j++ ) { bli_obj_free( &a[idx]); bli_obj_free( &b[idx]); bli_obj_free( &c[idx]); bli_obj_free( &c_save[idx]); idx++; } } #ifdef FILE_IN_OUT } fclose(fin); fclose(fout); #endif return 0; } blis-0.9.0/test/test_gemmt.c000066400000000000000000000307501422157504600157570ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2019 - 2020, Advanced Micro Devices, Inc. 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 The University of Texas 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 COPYRIGHT HOLDER 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. */ #ifdef WIN32 #include #else #include #endif #include "blis.h" //#define CBLAS //#define C_STOR_R //#define PRINT int main( int argc, char** argv ) { obj_t a, b, c; obj_t c_save; obj_t alpha, beta; dim_t m, k; dim_t p; dim_t p_begin, p_end, p_inc; int m_input, k_input; num_t dt; int r, n_repeats; uplo_t uploc; trans_t transa; trans_t transb; f77_char f77_uploc; f77_char f77_transa; f77_char f77_transb; double dtime; double dtime_save; double gflops; //bli_init(); //bli_error_checking_level_set( BLIS_NO_ERROR_CHECKING ); n_repeats = 3; #ifndef PRINT p_begin = 200; p_end = 2000; p_inc = 200; m_input = -1; k_input = -1; #else p_begin = 16; p_end = 16; p_inc = 1; m_input = 5; k_input = 4; #endif #if 1 //dt = BLIS_FLOAT; dt = BLIS_DOUBLE; #else //dt = BLIS_SCOMPLEX; dt = BLIS_DCOMPLEX; #endif uploc = BLIS_LOWER; //uploc = BLIS_UPPER; transa = BLIS_NO_TRANSPOSE; transb = BLIS_NO_TRANSPOSE; bli_param_map_blis_to_netlib_uplo( uploc, &f77_uploc ); bli_param_map_blis_to_netlib_trans( transa, &f77_transa ); bli_param_map_blis_to_netlib_trans( transb, &f77_transb ); char uplocl = tolower( f77_uploc ); char transal = tolower( f77_transa ); char transbl = tolower( f77_transb ); f77_int cbla_uploc = ( uplocl == 'l' ? CblasLower : CblasUpper ); f77_int cbla_transa = ( transal == 'n' ? CblasNoTrans : CblasTrans ); f77_int cbla_transb = ( transbl == 'n' ? CblasNoTrans : CblasTrans ); ( void )cbla_uploc; ( void )cbla_transa; ( void )cbla_transb; // Begin with initializing the last entry to zero so that // matlab allocates space for the entire array once up-front. for ( p = p_begin; p + p_inc <= p_end; p += p_inc ) ; #ifdef BLIS printf( "data_gemmt_blis" ); #else printf( "data_gemmt_%s", BLAS ); #endif printf( "( %2lu, 1:3 ) = [ %4lu %4lu %7.2f ];\n", ( unsigned long )(p - p_begin)/p_inc + 1, ( unsigned long )0, ( unsigned long )0, 0.0 ); //for ( p = p_begin; p <= p_end; p += p_inc ) for ( p = p_end; p_begin <= p; p -= p_inc ) { if ( m_input < 0 ) m = p * ( dim_t )abs(m_input); else m = ( dim_t ) m_input; if ( k_input < 0 ) k = p * ( dim_t )abs(k_input); else k = ( dim_t ) k_input; bli_obj_create( dt, 1, 1, 0, 0, &alpha ); bli_obj_create( dt, 1, 1, 0, 0, &beta ); #ifndef C_STOR_R if ( bli_does_trans( transa ) ) bli_obj_create( dt, k, m, 0, 0, &a ); else bli_obj_create( dt, m, k, 0, 0, &a ); if ( bli_does_trans( transb ) ) bli_obj_create( dt, m, k, 0, 0, &b ); else bli_obj_create( dt, k, m, 0, 0, &b ); bli_obj_create( dt, m, m, 0, 0, &c ); bli_obj_create( dt, m, m, 0, 0, &c_save ); #else if ( bli_does_trans( transa ) ) bli_obj_create( dt, k, m, -1, -1, &a ); else bli_obj_create( dt, m, k, -1, -1, &a ); if ( bli_does_trans( transb ) ) bli_obj_create( dt, m, k, -1, -1, &b ); else bli_obj_create( dt, k, m, -1, -1, &b ); bli_obj_create( dt, m, m, -1, -1, &c ); bli_obj_create( dt, m, m, -1, -1, &c_save ); #endif bli_randm( &a ); bli_randm( &b ); bli_randm( &c ); bli_obj_set_uplo( uploc, &c ); bli_obj_set_conjtrans( transa, &a ); bli_obj_set_conjtrans( transb, &b ); bli_setsc( (0.9/1.0), 0.2, &alpha ); bli_setsc( -(1.1/1.0), 0.3, &beta ); bli_copym( &c, &c_save ); dtime_save = DBL_MAX; for ( r = 0; r < n_repeats; ++r ) { bli_copym( &c_save, &c ); dtime = bli_clock(); #ifdef PRINT bli_printm( "a", &a, "%4.1f", "" ); bli_printm( "b", &b, "%4.1f", "" ); bli_printm( "c", &c, "%4.1f", "" ); #endif #ifdef BLIS bli_gemmt( &alpha, &a, &b, &beta, &c ); #else #ifndef CBLAS if ( bli_is_float( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); float* alphap = bli_obj_buffer( &alpha ); float* ap = bli_obj_buffer( &a ); float* bp = bli_obj_buffer( &b ); float* betap = bli_obj_buffer( &beta ); float* cp = bli_obj_buffer( &c ); sgemmt_( &f77_uploc, &f77_transa, &f77_transb, &mm, &kk, alphap, ap, &lda, bp, &ldb, betap, cp, &ldc ); } else if ( bli_is_double( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); double* alphap = bli_obj_buffer( &alpha ); double* ap = bli_obj_buffer( &a ); double* bp = bli_obj_buffer( &b ); double* betap = bli_obj_buffer( &beta ); double* cp = bli_obj_buffer( &c ); dgemmt_( &f77_uploc, &f77_transa, &f77_transb, &mm, &kk, alphap, ap, &lda, bp, &ldb, betap, cp, &ldc ); } else if ( bli_is_scomplex( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); scomplex* alphap = bli_obj_buffer( &alpha ); scomplex* ap = bli_obj_buffer( &a ); scomplex* bp = bli_obj_buffer( &b ); scomplex* betap = bli_obj_buffer( &beta ); scomplex* cp = bli_obj_buffer( &c ); cgemmt_( &f77_uploc, &f77_transa, &f77_transb, &mm, &kk, alphap, ap, &lda, bp, &ldb, betap, cp, &ldc ); } else if ( bli_is_dcomplex( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); dcomplex* alphap = bli_obj_buffer( &alpha ); dcomplex* ap = bli_obj_buffer( &a ); dcomplex* bp = bli_obj_buffer( &b ); dcomplex* betap = bli_obj_buffer( &beta ); dcomplex* cp = bli_obj_buffer( &c ); zgemmt_( &f77_uploc, &f77_transa, &f77_transb, &mm, &kk, alphap, ap, &lda, bp, &ldb, betap, cp, &ldc ); } #else // #ifdef CBLAS f77_int cbla_storage = ( bli_obj_is_row_stored( &c ) ? CblasRowMajor : CblasColMajor ); if ( bli_is_float( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); #ifdef C_STOR_R f77_int lda = bli_obj_row_stride( &a ); f77_int ldb = bli_obj_row_stride( &b ); f77_int ldc = bli_obj_row_stride( &c ); #else f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); #endif float* alphap = bli_obj_buffer( &alpha ); float* ap = bli_obj_buffer( &a ); float* bp = bli_obj_buffer( &b ); float* betap = bli_obj_buffer( &beta ); float* cp = bli_obj_buffer( &c ); cblas_sgemmt( cbla_storage, cbla_uploc, cbla_transa, cbla_transb, mm, kk, *alphap, ap, lda, bp, ldb, *betap, cp, ldc ); } else if ( bli_is_double( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); #ifdef C_STOR_R f77_int lda = bli_obj_row_stride( &a ); f77_int ldb = bli_obj_row_stride( &b ); f77_int ldc = bli_obj_row_stride( &c ); #else f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); #endif double* alphap = bli_obj_buffer( &alpha ); double* ap = bli_obj_buffer( &a ); double* bp = bli_obj_buffer( &b ); double* betap = bli_obj_buffer( &beta ); double* cp = bli_obj_buffer( &c ); cblas_dgemmt( cbla_storage, cbla_uploc, cbla_transa, cbla_transb, mm, kk, *alphap, ap, lda, bp, ldb, *betap, cp, ldc ); } else if ( bli_is_scomplex( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); #ifdef C_STOR_R f77_int lda = bli_obj_row_stride( &a ); f77_int ldb = bli_obj_row_stride( &b ); f77_int ldc = bli_obj_row_stride( &c ); #else f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); #endif scomplex* alphap = bli_obj_buffer( &alpha ); scomplex* ap = bli_obj_buffer( &a ); scomplex* bp = bli_obj_buffer( &b ); scomplex* betap = bli_obj_buffer( &beta ); scomplex* cp = bli_obj_buffer( &c ); cblas_cgemmt( cbla_storage, cbla_uploc, cbla_transa, cbla_transb, mm, kk, alphap, ap, lda, bp, ldb, betap, cp, ldc ); } else if ( bli_is_dcomplex( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); #ifdef C_STOR_R f77_int lda = bli_obj_row_stride( &a ); f77_int ldb = bli_obj_row_stride( &b ); f77_int ldc = bli_obj_row_stride( &c ); #else f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); #endif dcomplex* alphap = bli_obj_buffer( &alpha ); dcomplex* ap = bli_obj_buffer( &a ); dcomplex* bp = bli_obj_buffer( &b ); dcomplex* betap = bli_obj_buffer( &beta ); dcomplex* cp = bli_obj_buffer( &c ); cblas_zgemmt( cbla_storage, cbla_uploc, cbla_transa, cbla_transb, mm, kk, alphap, ap, lda, bp, ldb, betap, cp, ldc ); } #endif #endif #ifdef PRINT bli_printm( "c after", &c, "%4.1f", "" ); exit(1); #endif dtime_save = bli_clock_min_diff( dtime_save, dtime ); } gflops = ( 1.0 * m * k * m ) / ( dtime_save * 1.0e9 ); if ( bli_is_complex( dt ) ) gflops *= 4.0; #ifdef BLIS printf( "data_gemmt_blis" ); #else printf( "data_gemmt_%s", BLAS ); #endif printf( "( %2lu, 1:3 ) = [ %4lu %4lu %7.2f ];\n", ( unsigned long )(p - p_begin)/p_inc + 1, ( unsigned long )m, ( unsigned long )k, gflops ); bli_obj_free( &alpha ); bli_obj_free( &beta ); bli_obj_free( &a ); bli_obj_free( &b ); bli_obj_free( &c ); bli_obj_free( &c_save ); } //bli_finalize(); return 0; } blis-0.9.0/test/test_gemv.c000066400000000000000000000123601422157504600156010ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifdef WIN32 #include #else #include #endif #include "blis.h" // transa m n alpha a lda x incx beta y incy //void dgemv_( char*, int*, int*, double*, double*, int*, double*, int*, double*, double*, int* ); //#define PRINT int main( int argc, char** argv ) { obj_t a, x, y; obj_t y_save; obj_t alpha, beta; dim_t m, n; dim_t p; dim_t p_begin, p_end, p_inc; int m_input, n_input; num_t dt_a, dt_x, dt_y; num_t dt_alpha, dt_beta; int r, n_repeats; double dtime; double dtime_save; double gflops; //bli_init(); n_repeats = 3; #ifndef PRINT p_begin = 40; p_end = 2000; p_inc = 40; m_input = -1; n_input = -1; #else p_begin = 16; p_end = 16; p_inc = 1; m_input = 15; n_input = 15; #endif dt_a = dt_x = dt_y = dt_alpha = dt_beta = BLIS_DOUBLE; // Begin with initializing the last entry to zero so that // matlab allocates space for the entire array once up-front. for ( p = p_begin; p + p_inc <= p_end; p += p_inc ) ; #ifdef BLIS printf( "data_gemv_blis" ); #else printf( "data_gemv_%s", BLAS ); #endif printf( "( %2lu, 1:3 ) = [ %4lu %4lu %7.2f ];\n", ( unsigned long )(p - p_begin)/p_inc + 1, ( unsigned long )0, ( unsigned long )0, 0.0 ); //for ( p = p_begin; p <= p_end; p += p_inc ) for ( p = p_end; p_begin <= p; p -= p_inc ) { if ( m_input < 0 ) m = p * ( dim_t )abs(m_input); else m = ( dim_t ) m_input; if ( n_input < 0 ) n = p * ( dim_t )abs(n_input); else n = ( dim_t ) n_input; bli_obj_create( dt_alpha, 1, 1, 0, 0, &alpha ); bli_obj_create( dt_beta, 1, 1, 0, 0, &beta ); bli_obj_create( dt_a, m, n, 0, 0, &a ); bli_obj_create( dt_x, n, 1, 0, 0, &x ); bli_obj_create( dt_y, m, 1, 0, 0, &y ); bli_obj_create( dt_y, m, 1, 0, 0, &y_save ); bli_randm( &a ); bli_randm( &x ); bli_randm( &y ); bli_setsc( (2.0/1.0), 0.0, &alpha ); bli_setsc( -(1.0/1.0), 0.0, &beta ); bli_copym( &y, &y_save ); dtime_save = DBL_MAX; for ( r = 0; r < n_repeats; ++r ) { bli_copym( &y_save, &y ); dtime = bli_clock(); #ifdef PRINT bli_printm( "a", &a, "%4.1f", "" ); bli_printm( "x", &x, "%4.1f", "" ); bli_printm( "y", &y, "%4.1f", "" ); #endif #ifdef BLIS bli_gemv( &alpha, &a, &x, &beta, &y ); #else f77_char transa = 'N'; f77_int mm = bli_obj_length( &a ); f77_int nn = bli_obj_width( &a ); f77_int lda = bli_obj_col_stride( &a ); f77_int incx = bli_obj_vector_inc( &x ); f77_int incy = bli_obj_vector_inc( &y ); double* alphap = bli_obj_buffer( &alpha ); double* ap = bli_obj_buffer( &a ); double* xp = bli_obj_buffer( &x ); double* betap = bli_obj_buffer( &beta ); double* yp = bli_obj_buffer( &y ); dgemv_( &transa, &mm, &nn, alphap, ap, &lda, xp, &incx, betap, yp, &incy ); #endif #ifdef PRINT bli_printm( "y after", &y, "%4.1f", "" ); exit(1); #endif dtime_save = bli_clock_min_diff( dtime_save, dtime ); } gflops = ( 2.0 * m * n ) / ( dtime_save * 1.0e9 ); #ifdef BLIS printf( "data_gemv_blis" ); #else printf( "data_gemv_%s", BLAS ); #endif printf( "( %2lu, 1:3 ) = [ %4lu %4lu %7.2f ];\n", ( unsigned long )(p - p_begin)/p_inc + 1, ( unsigned long )m, ( unsigned long )n, gflops ); bli_obj_free( &alpha ); bli_obj_free( &beta ); bli_obj_free( &a ); bli_obj_free( &x ); bli_obj_free( &y ); bli_obj_free( &y_save ); } //bli_finalize(); return 0; } blis-0.9.0/test/test_ger.c000066400000000000000000000116631422157504600154250ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifdef WIN32 #include #else #include #endif #include "blis.h" // m n alpha x incx y incy a lda //void dger_( int*, int*, double*, double*, int*, double*, int*, double*, int* ); //#define PRINT int main( int argc, char** argv ) { obj_t a, x, y; obj_t a_save; obj_t alpha; dim_t m, n; dim_t p; dim_t p_begin, p_end, p_inc; int m_input, n_input; num_t dt_a, dt_x, dt_y; num_t dt_alpha; int r, n_repeats; double dtime; double dtime_save; double gflops; //bli_init(); n_repeats = 3; #ifndef PRINT p_begin = 40; p_end = 2000; p_inc = 40; m_input = -1; n_input = -1; #else p_begin = 16; p_end = 16; p_inc = 1; m_input = 15; n_input = 15; #endif dt_alpha = dt_x = dt_y = dt_a = BLIS_DOUBLE; // Begin with initializing the last entry to zero so that // matlab allocates space for the entire array once up-front. for ( p = p_begin; p + p_inc <= p_end; p += p_inc ) ; #ifdef BLIS printf( "data_ger_blis" ); #else printf( "data_ger_%s", BLAS ); #endif printf( "( %2lu, 1:3 ) = [ %4lu %4lu %7.2f ];\n", ( unsigned long )(p - p_begin)/p_inc + 1, ( unsigned long )0, ( unsigned long )0, 0.0 ); //for ( p = p_begin; p <= p_end; p += p_inc ) for ( p = p_end; p_begin <= p; p -= p_inc ) { if ( m_input < 0 ) m = p * ( dim_t )abs(m_input); else m = ( dim_t ) m_input; if ( n_input < 0 ) n = p * ( dim_t )abs(n_input); else n = ( dim_t ) n_input; bli_obj_create( dt_alpha, 1, 1, 0, 0, &alpha ); bli_obj_create( dt_x, m, 1, 0, 0, &x ); bli_obj_create( dt_y, n, 1, 0, 0, &y ); bli_obj_create( dt_a, m, n, 0, 0, &a ); bli_obj_create( dt_a, m, n, 0, 0, &a_save ); bli_randm( &x ); bli_randm( &y ); bli_randm( &a ); bli_setsc( (2.0/1.0), 0.0, &alpha ); bli_copym( &a, &a_save ); dtime_save = DBL_MAX; for ( r = 0; r < n_repeats; ++r ) { bli_copym( &a_save, &a ); dtime = bli_clock(); #ifdef PRINT bli_printm( "x", &x, "%4.1f", "" ); bli_printm( "y", &y, "%4.1f", "" ); bli_printm( "a", &a, "%4.1f", "" ); #endif #ifdef BLIS bli_ger( &alpha, &x, &y, &a ); #else f77_int mm = bli_obj_length( &a ); f77_int nn = bli_obj_width( &a ); f77_int incx = bli_obj_vector_inc( &x ); f77_int incy = bli_obj_vector_inc( &y ); f77_int lda = bli_obj_col_stride( &a ); double* alphap = bli_obj_buffer( &alpha ); double* xp = bli_obj_buffer( &x ); double* yp = bli_obj_buffer( &y ); double* ap = bli_obj_buffer( &a ); dger_( &mm, &nn, alphap, xp, &incx, yp, &incy, ap, &lda ); #endif #ifdef PRINT bli_printm( "a after", &a, "%4.1f", "" ); exit(1); #endif dtime_save = bli_clock_min_diff( dtime_save, dtime ); } gflops = ( 2.0 * m * n ) / ( dtime_save * 1.0e9 ); #ifdef BLIS printf( "data_ger_blis" ); #else printf( "data_ger_%s", BLAS ); #endif printf( "( %2lu, 1:3 ) = [ %4lu %4lu %7.2f ];\n", ( unsigned long )(p - p_begin)/p_inc + 1, ( unsigned long )m, ( unsigned long )n, gflops ); bli_obj_free( &alpha ); bli_obj_free( &x ); bli_obj_free( &y ); bli_obj_free( &a ); bli_obj_free( &a_save ); } //bli_finalize(); return 0; } blis-0.9.0/test/test_hemm.c000066400000000000000000000202331422157504600155670ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifdef WIN32 #include #else #include #endif #include "blis.h" //#define PRINT int main( int argc, char** argv ) { obj_t a, b, c; obj_t c_save; obj_t alpha, beta; dim_t m, n; dim_t p; dim_t p_begin, p_end, p_inc; int m_input, n_input; num_t dt; int r, n_repeats; side_t side; uplo_t uploa; f77_char f77_side; f77_char f77_uploa; double dtime; double dtime_save; double gflops; //bli_init(); //bli_error_checking_level_set( BLIS_NO_ERROR_CHECKING ); n_repeats = 3; #ifndef PRINT p_begin = 200; p_end = 2000; p_inc = 200; m_input = -1; n_input = -1; #else p_begin = 16; p_end = 16; p_inc = 1; m_input = 4; n_input = 4; #endif #if 1 //dt = BLIS_FLOAT; dt = BLIS_DOUBLE; #else //dt = BLIS_SCOMPLEX; dt = BLIS_DCOMPLEX; #endif side = BLIS_LEFT; //side = BLIS_RIGHT; uploa = BLIS_LOWER; //uploa = BLIS_UPPER; bli_param_map_blis_to_netlib_side( side, &f77_side ); bli_param_map_blis_to_netlib_uplo( uploa, &f77_uploa ); // Begin with initializing the last entry to zero so that // matlab allocates space for the entire array once up-front. for ( p = p_begin; p + p_inc <= p_end; p += p_inc ) ; #ifdef BLIS printf( "data_hemm_blis" ); #else printf( "data_hemm_%s", BLAS ); #endif printf( "( %2lu, 1:3 ) = [ %4lu %4lu %7.2f ];\n", ( unsigned long )(p - p_begin)/p_inc + 1, ( unsigned long )0, ( unsigned long )0, 0.0 ); //for ( p = p_begin; p <= p_end; p += p_inc ) for ( p = p_end; p_begin <= p; p -= p_inc ) { if ( m_input < 0 ) m = p * ( dim_t )abs(m_input); else m = ( dim_t ) m_input; if ( n_input < 0 ) n = p * ( dim_t )abs(n_input); else n = ( dim_t ) n_input; bli_obj_create( dt, 1, 1, 0, 0, &alpha ); bli_obj_create( dt, 1, 1, 0, 0, &beta ); if ( bli_is_left( side ) ) bli_obj_create( dt, m, m, 0, 0, &a ); else bli_obj_create( dt, n, n, 0, 0, &a ); bli_obj_create( dt, m, n, 0, 0, &b ); bli_obj_create( dt, m, n, 0, 0, &c ); bli_obj_create( dt, m, n, 0, 0, &c_save ); bli_randm( &a ); bli_randm( &b ); bli_randm( &c ); bli_obj_set_struc( BLIS_HERMITIAN, &a ); bli_obj_set_uplo( uploa, &a ); // Randomize A, make it densely Hermitian, and zero the unstored // triangle to ensure the implementation reads only from the stored // region. bli_randm( &a ); bli_mkherm( &a ); bli_mktrim( &a ); /* bli_obj_toggle_uplo( &a ); bli_obj_inc_diag_offset( 1, &a ); bli_setm( &BLIS_ZERO, &a ); bli_obj_inc_diag_offset( -1, &a ); bli_obj_toggle_uplo( &a ); bli_obj_set_diag( BLIS_NONUNIT_DIAG, &a ); bli_scalm( &BLIS_TWO, &a ); bli_scalm( &BLIS_TWO, &a ); */ bli_setsc( (2.0/1.0), 1.0, &alpha ); bli_setsc( -(1.0/1.0), 0.0, &beta ); bli_copym( &c, &c_save ); dtime_save = DBL_MAX; for ( r = 0; r < n_repeats; ++r ) { bli_copym( &c_save, &c ); dtime = bli_clock(); #ifdef PRINT bli_printm( "a", &a, "%4.1f", "" ); bli_printm( "b", &b, "%4.1f", "" ); bli_printm( "c", &c, "%4.1f", "" ); #endif #ifdef BLIS bli_hemm( side, &alpha, &a, &b, &beta, &c ); #else if ( bli_is_float( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); float* alphap = bli_obj_buffer( &alpha ); float* ap = bli_obj_buffer( &a ); float* bp = bli_obj_buffer( &b ); float* betap = bli_obj_buffer( &beta ); float* cp = bli_obj_buffer( &c ); ssymm_( &f77_side, &f77_uploa, &mm, &nn, alphap, ap, &lda, bp, &ldb, betap, cp, &ldc ); } else if ( bli_is_double( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); double* alphap = bli_obj_buffer( &alpha ); double* ap = bli_obj_buffer( &a ); double* bp = bli_obj_buffer( &b ); double* betap = bli_obj_buffer( &beta ); double* cp = bli_obj_buffer( &c ); dsymm_( &f77_side, &f77_uploa, &mm, &nn, alphap, ap, &lda, bp, &ldb, betap, cp, &ldc ); } else if ( bli_is_scomplex( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); scomplex* alphap = bli_obj_buffer( &alpha ); scomplex* ap = bli_obj_buffer( &a ); scomplex* bp = bli_obj_buffer( &b ); scomplex* betap = bli_obj_buffer( &beta ); scomplex* cp = bli_obj_buffer( &c ); chemm_( &f77_side, &f77_uploa, &mm, &nn, alphap, ap, &lda, bp, &ldb, betap, cp, &ldc ); } else if ( bli_is_dcomplex( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); dcomplex* alphap = bli_obj_buffer( &alpha ); dcomplex* ap = bli_obj_buffer( &a ); dcomplex* bp = bli_obj_buffer( &b ); dcomplex* betap = bli_obj_buffer( &beta ); dcomplex* cp = bli_obj_buffer( &c ); zhemm_( &f77_side, &f77_uploa, &mm, &nn, alphap, ap, &lda, bp, &ldb, betap, cp, &ldc ); } #endif #ifdef PRINT bli_printm( "c after", &c, "%9.5f", "" ); exit(1); #endif dtime_save = bli_clock_min_diff( dtime_save, dtime ); } if ( bli_is_left( side ) ) gflops = ( 2.0 * m * m * n ) / ( dtime_save * 1.0e9 ); else gflops = ( 2.0 * m * n * n ) / ( dtime_save * 1.0e9 ); if ( bli_is_complex( dt ) ) gflops *= 4.0; #ifdef BLIS printf( "data_hemm_blis" ); #else printf( "data_hemm_%s", BLAS ); #endif printf( "( %2lu, 1:3 ) = [ %4lu %4lu %7.2f ];\n", ( unsigned long )(p - p_begin)/p_inc + 1, ( unsigned long )m, ( unsigned long )n, gflops ); bli_obj_free( &alpha ); bli_obj_free( &beta ); bli_obj_free( &a ); bli_obj_free( &b ); bli_obj_free( &c ); bli_obj_free( &c_save ); } //bli_finalize(); return 0; } blis-0.9.0/test/test_hemv.c000066400000000000000000000124221422157504600156010ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifdef WIN32 #include #else #include #endif #include "blis.h" // uploa m alpha a lda x incx beta y incy //void dsymv_( char*, int*, double*, double*, int*, double*, int*, double*, double*, int* ); //#define PRINT int main( int argc, char** argv ) { obj_t a, x, y; obj_t y_save; obj_t alpha, beta; dim_t m; dim_t p; dim_t p_begin, p_end, p_inc; int m_input; num_t dt_a, dt_x, dt_y; num_t dt_alpha, dt_beta; int r, n_repeats; uplo_t uplo; double dtime; double dtime_save; double gflops; //bli_init(); n_repeats = 3; #ifndef PRINT p_begin = 40; p_end = 2000; p_inc = 40; m_input = -1; #else p_begin = 16; p_end = 16; p_inc = 1; m_input = 6; #endif #if 1 dt_a = dt_x = dt_y = dt_alpha = dt_beta = BLIS_DOUBLE; #else dt_a = dt_x = dt_y = dt_alpha = dt_beta = BLIS_DCOMPLEX; #endif uplo = BLIS_LOWER; // Begin with initializing the last entry to zero so that // matlab allocates space for the entire array once up-front. for ( p = p_begin; p + p_inc <= p_end; p += p_inc ) ; #ifdef BLIS printf( "data_hemv_blis" ); #else printf( "data_hemv_%s", BLAS ); #endif printf( "( %2lu, 1:2 ) = [ %4lu %7.2f ];\n", ( unsigned long )(p - p_begin)/p_inc + 1, ( unsigned long )0, 0.0 ); //for ( p = p_begin; p <= p_end; p += p_inc ) for ( p = p_end; p_begin <= p; p -= p_inc ) { if ( m_input < 0 ) m = p * ( dim_t )abs(m_input); else m = ( dim_t ) m_input; bli_obj_create( dt_alpha, 1, 1, 0, 0, &alpha ); bli_obj_create( dt_beta, 1, 1, 0, 0, &beta ); bli_obj_create( dt_a, m, m, 0, 0, &a ); bli_obj_create( dt_x, m, 1, 0, 0, &x ); bli_obj_create( dt_y, m, 1, 0, 0, &y ); bli_obj_create( dt_y, m, 1, 0, 0, &y_save ); bli_randm( &a ); bli_randm( &x ); bli_randm( &y ); bli_obj_set_struc( BLIS_HERMITIAN, &a ); //bli_obj_set_struc( BLIS_SYMMETRIC, &a ); bli_obj_set_uplo( uplo, &a ); bli_setsc( (2.0/1.0), 0.0, &alpha ); bli_setsc( -(1.0/1.0), 0.0, &beta ); bli_copym( &y, &y_save ); dtime_save = DBL_MAX; for ( r = 0; r < n_repeats; ++r ) { bli_copym( &y_save, &y ); dtime = bli_clock(); #ifdef PRINT bli_printm( "a", &a, "%4.1f", "" ); bli_printm( "x", &x, "%4.1f", "" ); bli_printm( "y", &y, "%4.1f", "" ); #endif #ifdef BLIS //bli_obj_toggle_conj( &a ); //bli_obj_toggle_conj( &x ); //bli_symv( &alpha, bli_hemv( &alpha, &a, &x, &beta, &y ); #else f77_char uploa = 'L'; f77_int mm = bli_obj_length( &a ); f77_int lda = bli_obj_col_stride( &a ); f77_int incx = bli_obj_vector_inc( &x ); f77_int incy = bli_obj_vector_inc( &y ); double* alphap = bli_obj_buffer( &alpha ); double* ap = bli_obj_buffer( &a ); double* xp = bli_obj_buffer( &x ); double* betap = bli_obj_buffer( &beta ); double* yp = bli_obj_buffer( &y ); dsymv_( &uploa, &mm, alphap, ap, &lda, xp, &incx, betap, yp, &incy ); #endif #ifdef PRINT bli_printm( "y after", &y, "%4.1f", "" ); exit(1); #endif dtime_save = bli_clock_min_diff( dtime_save, dtime ); } gflops = ( 2.0 * m * m ) / ( dtime_save * 1.0e9 ); #ifdef BLIS printf( "data_hemv_blis" ); #else printf( "data_hemv_%s", BLAS ); #endif printf( "( %2lu, 1:2 ) = [ %4lu %7.2f ];\n", ( unsigned long )(p - p_begin)/p_inc + 1, ( unsigned long )m, gflops ); bli_obj_free( &alpha ); bli_obj_free( &beta ); bli_obj_free( &a ); bli_obj_free( &x ); bli_obj_free( &y ); bli_obj_free( &y_save ); } //bli_finalize(); return 0; } blis-0.9.0/test/test_her.c000066400000000000000000000142151422157504600154220ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifdef WIN32 #include #else #include #endif #include "blis.h" // uplo m alpha x incx a lda //void dsyr_( char*, int*, double*, double*, int*, double*, int* ); //void zher_( char*, int*, double*, dcomplex*, int*, dcomplex*, int* ); //#define PRINT int main( int argc, char** argv ) { obj_t a, x; obj_t a_save; obj_t alpha; dim_t m; dim_t p; dim_t p_begin, p_end, p_inc; int m_input; num_t dt_a, dt_x; num_t dt_alpha; int r, n_repeats; uplo_t uplo; double dtime; double dtime_save; double gflops; //bli_init(); n_repeats = 3; #ifndef PRINT p_begin = 40; p_end = 2000; p_inc = 40; m_input = -1; #else p_begin = 16; p_end = 16; p_inc = 1; m_input = 6; #endif // her supports complex and double complex dt_alpha = dt_x = dt_a = BLIS_DCOMPLEX; uplo = BLIS_LOWER; // Begin with initializing the last entry to zero so that // matlab allocates space for the entire array once up-front. for ( p = p_begin; p + p_inc <= p_end; p += p_inc ) ; #ifdef BLIS printf( "data_her_blis" ); #else printf( "data_her_%s", BLAS ); #endif printf( "( %2lu, 1:2 ) = [ %4lu %7.2f ];\n", ( unsigned long )(p - p_begin)/p_inc + 1, ( unsigned long )0, 0.0 ); //for ( p = p_begin; p <= p_end; p += p_inc ) for ( p = p_end; p_begin <= p; p -= p_inc ) { if ( m_input < 0 ) m = p * ( dim_t )abs(m_input); else m = ( dim_t ) m_input; bli_obj_create( dt_alpha, 1, 1, 0, 0, &alpha ); bli_obj_create( dt_x, m, 1, 0, 0, &x ); bli_obj_create( dt_a, m, m, 0, 0, &a ); bli_obj_create( dt_a, m, m, 0, 0, &a_save ); bli_randm( &x ); bli_randm( &a ); bli_obj_set_struc( BLIS_HERMITIAN, &a ); //bli_obj_set_struc( BLIS_SYMMETRIC, &a ); bli_obj_set_uplo( uplo, &a ); bli_setsc( (2.0/1.0), 0.0, &alpha ); bli_copym( &a, &a_save ); dtime_save = DBL_MAX; for ( r = 0; r < n_repeats; ++r ) { bli_copym( &a_save, &a ); dtime = bli_clock(); #ifdef PRINT bli_printm( "x", &x, "%4.1f", "" ); bli_printm( "a", &a, "%4.1f", "" ); #endif #ifdef BLIS bli_her( &alpha, &x, &a ); #else if ( bli_is_float( dt_a ) ) { f77_char uplo = 'L'; f77_int mm = bli_obj_length( &a ); f77_int incx = bli_obj_vector_inc( &x ); f77_int lda = bli_obj_col_stride( &a ); float* alphap = bli_obj_buffer( &alpha ); float* xp = bli_obj_buffer( &x ); float* ap = bli_obj_buffer( &a ); ssyr_( &uplo, &mm, alphap, xp, &incx, ap, &lda ); } else if ( bli_is_double( dt_a ) ) { f77_char uplo = 'L'; f77_int mm = bli_obj_length( &a ); f77_int incx = bli_obj_vector_inc( &x ); f77_int lda = bli_obj_col_stride( &a ); double* alphap = bli_obj_buffer( &alpha ); double* xp = bli_obj_buffer( &x ); double* ap = bli_obj_buffer( &a ); dsyr_( &uplo, &mm, alphap, xp, &incx, ap, &lda ); } else if ( bli_is_scomplex( dt_a ) ) { f77_char uplo = 'L'; f77_int mm = bli_obj_length( &a ); f77_int incx = bli_obj_vector_inc( &x ); f77_int lda = bli_obj_col_stride( &a ); float* alphap = bli_obj_buffer( &alpha ); scomplex* xp = bli_obj_buffer( &x ); scomplex* ap = bli_obj_buffer( &a ); cher_( &uplo, &mm, alphap, xp, &incx, ap, &lda ); } else if ( bli_is_dcomplex( dt_a ) ) { f77_char uplo = 'L'; f77_int mm = bli_obj_length( &a ); f77_int incx = bli_obj_vector_inc( &x ); f77_int lda = bli_obj_col_stride( &a ); double* alphap = bli_obj_buffer( &alpha ); dcomplex* xp = bli_obj_buffer( &x ); dcomplex* ap = bli_obj_buffer( &a ); zher_( &uplo, &mm, alphap, xp, &incx, ap, &lda ); } #endif #ifdef PRINT bli_printm( "a after", &a, "%4.1f", "" ); exit(1); #endif dtime_save = bli_clock_min_diff( dtime_save, dtime ); } gflops = ( 1.0 * m * m ) / ( dtime_save * 1.0e9 ); #ifdef BLIS printf( "data_her_blis" ); #else printf( "data_her_%s", BLAS ); #endif printf( "( %2lu, 1:2 ) = [ %4lu %7.2f ];\n", ( unsigned long )(p - p_begin)/p_inc + 1, ( unsigned long )m, gflops ); bli_obj_free( &alpha ); bli_obj_free( &x ); bli_obj_free( &a ); bli_obj_free( &a_save ); } //bli_finalize(); return 0; } blis-0.9.0/test/test_her2.c000066400000000000000000000153541422157504600155110ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifdef WIN32 #include #else #include #endif #include "blis.h" // uplo m alpha x incx y incy a lda //void dsyr2_( char*, int*, double*, double*, int*, double*, int*, double*, int* ); //#define PRINT int main( int argc, char** argv ) { obj_t a, x, y; obj_t a_save; obj_t alpha; dim_t m; dim_t p; dim_t p_begin, p_end, p_inc; int m_input; num_t dt_a, dt_x, dt_y; num_t dt_alpha; int r, n_repeats; uplo_t uplo; double dtime; double dtime_save; double gflops; //bli_init(); n_repeats = 3; #ifndef PRINT p_begin = 40; p_end = 2000; p_inc = 40; m_input = -1; #else p_begin = 16; p_end = 16; p_inc = 1; m_input = 6; #endif // her2 supports complex and double complex dt_alpha = dt_x = dt_y = dt_a = BLIS_SCOMPLEX; uplo = BLIS_LOWER; // Begin with initializing the last entry to zero so that // matlab allocates space for the entire array once up-front. for ( p = p_begin; p + p_inc <= p_end; p += p_inc ) ; #ifdef BLIS printf( "data_her2_blis" ); #else printf( "data_her2_%s", BLAS ); #endif printf( "( %2lu, 1:2 ) = [ %4lu %7.2f ];\n", ( unsigned long )(p - p_begin)/p_inc + 1, ( unsigned long )0, 0.0 ); //for ( p = p_begin; p <= p_end; p += p_inc ) for ( p = p_end; p_begin <= p; p -= p_inc ) { if ( m_input < 0 ) m = p * ( dim_t )abs(m_input); else m = ( dim_t ) m_input; bli_obj_create( dt_alpha, 1, 1, 0, 0, &alpha ); bli_obj_create( dt_x, m, 1, 0, 0, &x ); bli_obj_create( dt_y, m, 1, 0, 0, &y ); bli_obj_create( dt_a, m, m, 0, 0, &a ); bli_obj_create( dt_a, m, m, 0, 0, &a_save ); bli_randm( &x ); bli_randm( &y ); bli_randm( &a ); bli_obj_set_struc( BLIS_HERMITIAN, &a ); //bli_obj_set_struc( BLIS_SYMMETRIC, &a ); bli_obj_set_uplo( uplo, &a ); bli_setsc( (2.0/1.0), 0.0, &alpha ); bli_copym( &a, &a_save ); dtime_save = DBL_MAX; for ( r = 0; r < n_repeats; ++r ) { bli_copym( &a_save, &a ); dtime = bli_clock(); #ifdef PRINT bli_printm( "x", &x, "%4.1f", "" ); bli_printm( "y", &y, "%4.1f", "" ); bli_printm( "a", &a, "%4.1f", "" ); #endif #ifdef BLIS bli_her2( &alpha, &x, &y, &a ); #else if ( bli_is_float( dt_a ) ) { f77_char uplo = 'L'; f77_int mm = bli_obj_length( &a ); f77_int incx = bli_obj_vector_inc( &x ); f77_int incy = bli_obj_vector_inc( &y ); f77_int lda = bli_obj_col_stride( &a ); float* alphap = bli_obj_buffer( &alpha ); float* xp = bli_obj_buffer( &x ); float* yp = bli_obj_buffer( &y ); float* ap = bli_obj_buffer( &a ); ssyr2_( &uplo, &mm, alphap, xp, &incx, yp, &incy, ap, &lda ); } else if ( bli_is_double( dt_a ) ) { f77_char uplo = 'L'; f77_int mm = bli_obj_length( &a ); f77_int incx = bli_obj_vector_inc( &x ); f77_int incy = bli_obj_vector_inc( &y ); f77_int lda = bli_obj_col_stride( &a ); double* alphap = bli_obj_buffer( &alpha ); double* xp = bli_obj_buffer( &x ); double* yp = bli_obj_buffer( &y ); double* ap = bli_obj_buffer( &a ); dsyr2_( &uplo, &mm, alphap, xp, &incx, yp, &incy, ap, &lda ); } else if ( bli_is_scomplex( dt_a ) ) { f77_char uplo = 'L'; f77_int mm = bli_obj_length( &a ); f77_int incx = bli_obj_vector_inc( &x ); f77_int incy = bli_obj_vector_inc( &y ); f77_int lda = bli_obj_col_stride( &a ); scomplex* alphap = bli_obj_buffer( &alpha ); scomplex* xp = bli_obj_buffer( &x ); scomplex* yp = bli_obj_buffer( &y ); scomplex* ap = bli_obj_buffer( &a ); cher2_( &uplo, &mm, alphap, xp, &incx, yp, &incy, ap, &lda ); } else if ( bli_is_dcomplex( dt_a ) ) { f77_char uplo = 'L'; f77_int mm = bli_obj_length( &a ); f77_int incx = bli_obj_vector_inc( &x ); f77_int incy = bli_obj_vector_inc( &y ); f77_int lda = bli_obj_col_stride( &a ); dcomplex* alphap = bli_obj_buffer( &alpha ); dcomplex* xp = bli_obj_buffer( &x ); dcomplex* yp = bli_obj_buffer( &y ); dcomplex* ap = bli_obj_buffer( &a ); zher2_( &uplo, &mm, alphap, xp, &incx, yp, &incy, ap, &lda ); } #endif #ifdef PRINT bli_printm( "a after", &a, "%4.1f", "" ); exit(1); #endif dtime_save = bli_clock_min_diff( dtime_save, dtime ); } gflops = ( 2.0 * m * m ) / ( dtime_save * 1.0e9 ); #ifdef BLIS printf( "data_her2_blis" ); #else printf( "data_her2_%s", BLAS ); #endif printf( "( %2lu, 1:2 ) = [ %4lu %7.2f ];\n", ( unsigned long )(p - p_begin)/p_inc + 1, ( unsigned long )m, gflops ); bli_obj_free( &alpha ); bli_obj_free( &x ); bli_obj_free( &y ); bli_obj_free( &a ); bli_obj_free( &a_save ); } //bli_finalize(); return 0; } blis-0.9.0/test/test_her2k.c000066400000000000000000000175201422157504600156610ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifdef WIN32 #include #else #include #endif #include "blis.h" //#define PRINT int main( int argc, char** argv ) { obj_t a, b, c; obj_t c_save; obj_t alpha, beta; dim_t m, k; dim_t p; dim_t p_begin, p_end, p_inc; int m_input, k_input; num_t dt; int r, n_repeats; uplo_t uploc; trans_t transa; f77_char f77_uploc; f77_char f77_transa; double dtime; double dtime_save; double gflops; //bli_init(); //bli_error_checking_level_set( BLIS_NO_ERROR_CHECKING ); n_repeats = 3; #ifndef PRINT p_begin = 200; p_end = 2000; p_inc = 200; m_input = -1; k_input = -1; #else p_begin = 16; p_end = 16; p_inc = 1; m_input = 3; k_input = 1; #endif // her2k supports complex and double complex //dt = BLIS_SCOMPLEX; dt = BLIS_DCOMPLEX; uploc = BLIS_LOWER; //uploc = BLIS_UPPER; transa = BLIS_NO_TRANSPOSE; bli_param_map_blis_to_netlib_uplo( uploc, &f77_uploc ); bli_param_map_blis_to_netlib_trans( transa, &f77_transa ); // Begin with initializing the last entry to zero so that // matlab allocates space for the entire array once up-front. for ( p = p_begin; p + p_inc <= p_end; p += p_inc ) ; #ifdef BLIS printf( "data_her2k_blis" ); #else printf( "data_her2k_%s", BLAS ); #endif printf( "( %2lu, 1:3 ) = [ %4lu %4lu %7.2f ];\n", ( unsigned long )(p - p_begin)/p_inc + 1, ( unsigned long )0, ( unsigned long )0, 0.0 ); //for ( p = p_begin; p <= p_end; p += p_inc ) for ( p = p_end; p_begin <= p; p -= p_inc ) { if ( m_input < 0 ) m = p * ( dim_t )abs(m_input); else m = ( dim_t ) m_input; if ( k_input < 0 ) k = p * ( dim_t )abs(k_input); else k = ( dim_t ) k_input; bli_obj_create( dt, 1, 1, 0, 0, &alpha ); bli_obj_create( dt, 1, 1, 0, 0, &beta ); if ( bli_does_trans( transa ) ) { bli_obj_create( dt, k, m, 0, 0, &a ); bli_obj_create( dt, k, m, 0, 0, &b ); } else { bli_obj_create( dt, m, k, 0, 0, &a ); bli_obj_create( dt, m, k, 0, 0, &b ); } bli_obj_create( dt, m, m, 0, 0, &c ); bli_obj_create( dt, m, m, 0, 0, &c_save ); bli_randm( &a ); bli_randm( &b ); bli_randm( &c ); bli_obj_set_struc( BLIS_HERMITIAN, &c ); bli_obj_set_uplo( uploc, &c ); bli_obj_set_conjtrans( transa, &a ); bli_obj_set_conjtrans( transa, &b ); bli_setsc( (2.0/1.0), 0.0, &alpha ); bli_setsc( -(1.0/1.0), 0.0, &beta ); bli_copym( &c, &c_save ); dtime_save = DBL_MAX; for ( r = 0; r < n_repeats; ++r ) { bli_copym( &c_save, &c ); dtime = bli_clock(); #ifdef PRINT bli_printm( "a", &a, "%4.1f", "" ); bli_printm( "b", &b, "%4.1f", "" ); bli_printm( "c", &c, "%4.1f", "" ); #endif #ifdef BLIS bli_her2k( &alpha, &a, &b, &beta, &c ); #else if ( bli_is_float( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); float* alphap = bli_obj_buffer( &alpha ); float* ap = bli_obj_buffer( &a ); float* bp = bli_obj_buffer( &b ); float* betap = bli_obj_buffer( &beta ); float* cp = bli_obj_buffer( &c ); ssyr2k_( &f77_uploc, &f77_transa, &mm, &kk, alphap, ap, &lda, bp, &ldb, betap, cp, &ldc ); } else if ( bli_is_double( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); double* alphap = bli_obj_buffer( &alpha ); double* ap = bli_obj_buffer( &a ); double* bp = bli_obj_buffer( &b ); double* betap = bli_obj_buffer( &beta ); double* cp = bli_obj_buffer( &c ); dsyr2k_( &f77_uploc, &f77_transa, &mm, &kk, alphap, ap, &lda, bp, &ldb, betap, cp, &ldc ); } else if ( bli_is_scomplex( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); scomplex* alphap = bli_obj_buffer( &alpha ); scomplex* ap = bli_obj_buffer( &a ); scomplex* bp = bli_obj_buffer( &b ); float* betap = bli_obj_buffer( &beta ); scomplex* cp = bli_obj_buffer( &c ); cher2k_( &f77_uploc, &f77_transa, &mm, &kk, alphap, ap, &lda, bp, &ldb, betap, cp, &ldc ); } else if ( bli_is_dcomplex( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldb = bli_obj_col_stride( &b ); f77_int ldc = bli_obj_col_stride( &c ); dcomplex* alphap = bli_obj_buffer( &alpha ); dcomplex* ap = bli_obj_buffer( &a ); dcomplex* bp = bli_obj_buffer( &b ); double* betap = bli_obj_buffer( &beta ); dcomplex* cp = bli_obj_buffer( &c ); zher2k_( &f77_uploc, &f77_transa, &mm, &kk, alphap, ap, &lda, bp, &ldb, betap, cp, &ldc ); } #endif #ifdef PRINT bli_printm( "c after", &c, "%4.1f", "" ); exit(1); #endif dtime_save = bli_clock_min_diff( dtime_save, dtime ); } gflops = ( 2.0 * m * k * m ) / ( dtime_save * 1.0e9 ); if ( bli_is_complex( dt ) ) gflops *= 4.0; #ifdef BLIS printf( "data_her2k_blis" ); #else printf( "data_her2k_%s", BLAS ); #endif printf( "( %2lu, 1:3 ) = [ %4lu %4lu %7.2f ];\n", ( unsigned long )(p - p_begin)/p_inc + 1, ( unsigned long )m, ( unsigned long )k, gflops ); bli_obj_free( &alpha ); bli_obj_free( &beta ); bli_obj_free( &a ); bli_obj_free( &c ); bli_obj_free( &c_save ); } //bli_finalize(); return 0; } blis-0.9.0/test/test_herk.c000066400000000000000000000162171422157504600156010ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifdef WIN32 #include #else #include #endif #include "blis.h" //#define PRINT int main( int argc, char** argv ) { obj_t a, c; obj_t c_save; obj_t alpha, beta; dim_t m, k; dim_t p; dim_t p_begin, p_end, p_inc; int m_input, k_input; num_t dt; int r, n_repeats; uplo_t uploc; trans_t transa; f77_char f77_uploc; f77_char f77_transa; double dtime; double dtime_save; double gflops; //bli_init(); //bli_error_checking_level_set( BLIS_NO_ERROR_CHECKING ); n_repeats = 3; #ifndef PRINT p_begin = 200; p_end = 2000; p_inc = 200; m_input = -1; k_input = -1; #else p_begin = 16; p_end = 16; p_inc = 1; m_input = 3; k_input = 1; #endif // herk supports complex and double complex //dt = BLIS_SCOMPLEX; dt = BLIS_DCOMPLEX; uploc = BLIS_LOWER; //uploc = BLIS_UPPER; transa = BLIS_NO_TRANSPOSE; bli_param_map_blis_to_netlib_uplo( uploc, &f77_uploc ); bli_param_map_blis_to_netlib_trans( transa, &f77_transa ); // Begin with initializing the last entry to zero so that // matlab allocates space for the entire array once up-front. for ( p = p_begin; p + p_inc <= p_end; p += p_inc ) ; #ifdef BLIS printf( "data_herk_blis" ); #else printf( "data_herk_%s", BLAS ); #endif printf( "( %2lu, 1:3 ) = [ %4lu %4lu %7.2f ];\n", ( unsigned long )(p - p_begin)/p_inc + 1, ( unsigned long )0, ( unsigned long )0, 0.0 ); //for ( p = p_begin; p <= p_end; p += p_inc ) for ( p = p_end; p_begin <= p; p -= p_inc ) { if ( m_input < 0 ) m = p * ( dim_t )abs(m_input); else m = ( dim_t ) m_input; if ( k_input < 0 ) k = p * ( dim_t )abs(k_input); else k = ( dim_t ) k_input; bli_obj_create( dt, 1, 1, 0, 0, &alpha ); bli_obj_create( dt, 1, 1, 0, 0, &beta ); if ( bli_does_trans( transa ) ) bli_obj_create( dt, k, m, 0, 0, &a ); else bli_obj_create( dt, m, k, 0, 0, &a ); bli_obj_create( dt, m, m, 0, 0, &c ); bli_obj_create( dt, m, m, 0, 0, &c_save ); bli_randm( &a ); bli_randm( &c ); bli_obj_set_struc( BLIS_HERMITIAN, &c ); bli_obj_set_uplo( uploc, &c ); bli_obj_set_conjtrans( transa, &a ); bli_setsc( (2.0/1.0), 0.0, &alpha ); bli_setsc( -(1.0/1.0), 0.0, &beta ); bli_copym( &c, &c_save ); dtime_save = DBL_MAX; for ( r = 0; r < n_repeats; ++r ) { bli_copym( &c_save, &c ); dtime = bli_clock(); #ifdef PRINT bli_printm( "a", &a, "%4.1f", "" ); bli_printm( "c", &c, "%4.1f", "" ); #endif #ifdef BLIS bli_herk( &alpha, &a, &beta, &c ); #else if ( bli_is_float( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldc = bli_obj_col_stride( &c ); float* alphap = bli_obj_buffer( &alpha ); float* ap = bli_obj_buffer( &a ); float* betap = bli_obj_buffer( &beta ); float* cp = bli_obj_buffer( &c ); ssyrk_( &f77_uploc, &f77_transa, &mm, &kk, alphap, ap, &lda, betap, cp, &ldc ); } else if ( bli_is_double( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldc = bli_obj_col_stride( &c ); double* alphap = bli_obj_buffer( &alpha ); double* ap = bli_obj_buffer( &a ); double* betap = bli_obj_buffer( &beta ); double* cp = bli_obj_buffer( &c ); dsyrk_( &f77_uploc, &f77_transa, &mm, &kk, alphap, ap, &lda, betap, cp, &ldc ); } else if ( bli_is_scomplex( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldc = bli_obj_col_stride( &c ); float* alphap = bli_obj_buffer( &alpha ); scomplex* ap = bli_obj_buffer( &a ); float* betap = bli_obj_buffer( &beta ); scomplex* cp = bli_obj_buffer( &c ); cherk_( &f77_uploc, &f77_transa, &mm, &kk, alphap, ap, &lda, betap, cp, &ldc ); } else if ( bli_is_dcomplex( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int kk = bli_obj_width_after_trans( &a ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldc = bli_obj_col_stride( &c ); double* alphap = bli_obj_buffer( &alpha ); dcomplex* ap = bli_obj_buffer( &a ); double* betap = bli_obj_buffer( &beta ); dcomplex* cp = bli_obj_buffer( &c ); zherk_( &f77_uploc, &f77_transa, &mm, &kk, alphap, ap, &lda, betap, cp, &ldc ); } #endif #ifdef PRINT bli_printm( "c after", &c, "%4.1f", "" ); exit(1); #endif dtime_save = bli_clock_min_diff( dtime_save, dtime ); } gflops = ( 1.0 * m * k * m ) / ( dtime_save * 1.0e9 ); if ( bli_is_complex( dt ) ) gflops *= 4.0; #ifdef BLIS printf( "data_herk_blis" ); #else printf( "data_herk_%s", BLAS ); #endif printf( "( %2lu, 1:3 ) = [ %4lu %4lu %7.2f ];\n", ( unsigned long )(p - p_begin)/p_inc + 1, ( unsigned long )m, ( unsigned long )k, gflops ); bli_obj_free( &alpha ); bli_obj_free( &beta ); bli_obj_free( &a ); bli_obj_free( &c ); bli_obj_free( &c_save ); } //bli_finalize(); return 0; } blis-0.9.0/test/test_swapv.c000066400000000000000000000106161422157504600160050ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2020-2022, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include #include "blis.h" // n x incx y incy //void dswap_( int*, double*, int*, double*, int* ); //#define PRINT int main( int argc, char** argv ) { obj_t x, y; dim_t n; dim_t p; dim_t p_begin, p_end, p_inc; int n_input; int r, n_repeats; num_t dt; double dtime; double dtime_save; double gflops; bli_init(); n_repeats = 3; #ifndef PRINT p_begin = 40; p_end = 8000; p_inc = 40; n_input = -1; #else p_begin = 16; p_end = 16; p_inc = 1; n_input = -1; #endif #if 1 dt = BLIS_FLOAT; //dt = BLIS_DOUBLE; #else //dt = BLIS_SCOMPLEX; dt = BLIS_DCOMPLEX; #endif // Begin with initializing the last entry to zero so that // matlab allocates space for the entire array once up-front. for ( p = p_begin; p + p_inc <= p_end; p += p_inc ) ; #ifdef BLIS printf( "data_swapv_blis" ); #else printf( "data_swapv_%s", BLAS ); #endif printf( "( %2lu, 1:2 ) = [ %4lu %7.2f ];\n", ( unsigned long )(p - p_begin)/p_inc + 1, ( unsigned long )0, 0.0 ); //for ( p = p_begin; p <= p_end; p += p_inc ) for ( p = p_end; p_begin <= p; p -= p_inc ) { if ( n_input < 0 ) n = p * ( dim_t )abs(n_input); else n = ( dim_t ) n_input; bli_obj_create( dt, n, 1, 0, 0, &x ); bli_obj_create( dt, n, 1, 0, 0, &y ); bli_randm( &x ); bli_randm( &y ); dtime_save = 1.0e9; for ( r = 0; r < n_repeats; ++r ) { dtime = bli_clock(); #ifdef PRINT bli_printm( "x", &x, "%4.1f", "" ); bli_printm( "y", &y, "%4.1f", "" ); #endif #ifdef BLIS bli_swapv( &x, &y ); #else if ( bli_is_float( dt ) ) { f77_int nn = bli_obj_length( &x ); f77_int incx = bli_obj_vector_inc( &x ); f77_int incy = bli_obj_vector_inc( &y ); float* xp = bli_obj_buffer( &x ); float* yp = bli_obj_buffer( &y ); sswap_( &nn, xp, &incx, yp, &incy ); } else if ( bli_is_double( dt ) ) { f77_int nn = bli_obj_length( &x ); f77_int incx = bli_obj_vector_inc( &x ); f77_int incy = bli_obj_vector_inc( &y ); double* xp = bli_obj_buffer( &x ); double* yp = bli_obj_buffer( &y ); dswap_( &nn, xp, &incx, yp, &incy ); } #endif #ifdef PRINT bli_printm( "X after", &x, "%4.1f", "" ); bli_printm( "Y after", &y, "%4.1f", "" ); exit(1); #endif dtime_save = bli_clock_min_diff( dtime_save, dtime ); } gflops = ( n ) / ( dtime_save * 1.0e9 ); #ifdef BLIS printf( "data_swapv_blis" ); #else printf( "data_swapv_%s", BLAS ); #endif printf( "( %2lu, 1:2 ) = [ %4lu %7.2f ];\n", ( unsigned long )(p - p_begin)/p_inc + 1, ( unsigned long )n, gflops ); bli_obj_free( &x ); bli_obj_free( &y ); } bli_finalize(); return 0; } blis-0.9.0/test/test_trmm.c000066400000000000000000000166671422157504600156400ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifdef WIN32 #include #else #include #endif #include "blis.h" //#define PRINT int main( int argc, char** argv ) { obj_t a, c; obj_t c_save; obj_t alpha; dim_t m, n; dim_t p; dim_t p_begin, p_end, p_inc; int m_input, n_input; num_t dt; int r, n_repeats; side_t side; uplo_t uploa; trans_t transa; diag_t diaga; f77_char f77_side; f77_char f77_uploa; f77_char f77_transa; f77_char f77_diaga; double dtime; double dtime_save; double gflops; //bli_init(); //bli_error_checking_level_set( BLIS_NO_ERROR_CHECKING ); n_repeats = 3; #ifndef PRINT p_begin = 200; p_end = 2000; p_inc = 200; m_input = -1; n_input = -1; #else p_begin = 16; p_end = 16; p_inc = 1; m_input = 4; n_input = 4; #endif #if 1 //dt = BLIS_FLOAT; dt = BLIS_DOUBLE; #else //dt = BLIS_SCOMPLEX; dt = BLIS_DCOMPLEX; #endif side = BLIS_LEFT; //side = BLIS_RIGHT; uploa = BLIS_LOWER; //uploa = BLIS_UPPER; transa = BLIS_NO_TRANSPOSE; diaga = BLIS_NONUNIT_DIAG; bli_param_map_blis_to_netlib_side( side, &f77_side ); bli_param_map_blis_to_netlib_uplo( uploa, &f77_uploa ); bli_param_map_blis_to_netlib_trans( transa, &f77_transa ); bli_param_map_blis_to_netlib_diag( diaga, &f77_diaga ); // Begin with initializing the last entry to zero so that // matlab allocates space for the entire array once up-front. for ( p = p_begin; p + p_inc <= p_end; p += p_inc ) ; #ifdef BLIS printf( "data_trmm_blis" ); #else printf( "data_trmm_%s", BLAS ); #endif printf( "( %2lu, 1:3 ) = [ %4lu %4lu %7.2f ];\n", ( unsigned long )(p - p_begin)/p_inc + 1, ( unsigned long )0, ( unsigned long )0, 0.0 ); //for ( p = p_begin; p <= p_end; p += p_inc ) for ( p = p_end; p_begin <= p; p -= p_inc ) { if ( m_input < 0 ) m = p * ( dim_t )abs(m_input); else m = ( dim_t ) m_input; if ( n_input < 0 ) n = p * ( dim_t )abs(n_input); else n = ( dim_t ) n_input; bli_obj_create( dt, 1, 1, 0, 0, &alpha ); if ( bli_is_left( side ) ) bli_obj_create( dt, m, m, 0, 0, &a ); else bli_obj_create( dt, n, n, 0, 0, &a ); bli_obj_create( dt, m, n, 0, 0, &c ); bli_obj_create( dt, m, n, 0, 0, &c_save ); bli_randm( &a ); bli_randm( &c ); bli_obj_set_struc( BLIS_TRIANGULAR, &a ); bli_obj_set_uplo( uploa, &a ); bli_obj_set_conjtrans( transa, &a ); bli_obj_set_diag( diaga, &a ); // Randomize A, make it densely Hermitian, and zero the unstored // triangle to ensure the implementation reads only from the stored // region. bli_randm( &a ); bli_mkherm( &a ); bli_mktrim( &a ); bli_setsc( (2.0/1.0), 1.0, &alpha ); bli_copym( &c, &c_save ); dtime_save = DBL_MAX; for ( r = 0; r < n_repeats; ++r ) { bli_copym( &c_save, &c ); dtime = bli_clock(); #ifdef PRINT bli_printm( "a", &a, "%4.1f", "" ); bli_printm( "c", &c, "%4.1f", "" ); #endif #ifdef BLIS bli_trmm( side, &alpha, &a, &c ); #else if ( bli_is_float( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldc = bli_obj_col_stride( &c ); float* alphap = bli_obj_buffer( &alpha ); float* ap = bli_obj_buffer( &a ); float* cp = bli_obj_buffer( &c ); strmm_( &f77_side, &f77_uploa, &f77_transa, &f77_diaga, &mm, &nn, alphap, ap, &lda, cp, &ldc ); } else if ( bli_is_double( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldc = bli_obj_col_stride( &c ); double* alphap = bli_obj_buffer( &alpha ); double* ap = bli_obj_buffer( &a ); double* cp = bli_obj_buffer( &c ); dtrmm_( &f77_side, &f77_uploa, &f77_transa, &f77_diaga, &mm, &nn, alphap, ap, &lda, cp, &ldc ); } else if ( bli_is_scomplex( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldc = bli_obj_col_stride( &c ); scomplex* alphap = bli_obj_buffer( &alpha ); scomplex* ap = bli_obj_buffer( &a ); scomplex* cp = bli_obj_buffer( &c ); ctrmm_( &f77_side, &f77_uploa, &f77_transa, &f77_diaga, &mm, &nn, alphap, ap, &lda, cp, &ldc ); } else if ( bli_is_dcomplex( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldc = bli_obj_col_stride( &c ); dcomplex* alphap = bli_obj_buffer( &alpha ); dcomplex* ap = bli_obj_buffer( &a ); dcomplex* cp = bli_obj_buffer( &c ); ztrmm_( &f77_side, &f77_uploa, &f77_transa, &f77_diaga, &mm, &nn, alphap, ap, &lda, cp, &ldc ); } #endif #ifdef PRINT bli_printm( "c after", &c, "%9.5f", "" ); exit(1); #endif dtime_save = bli_clock_min_diff( dtime_save, dtime ); } if ( bli_is_left( side ) ) gflops = ( 1.0 * m * m * n ) / ( dtime_save * 1.0e9 ); else gflops = ( 1.0 * m * n * n ) / ( dtime_save * 1.0e9 ); if ( bli_is_complex( dt ) ) gflops *= 4.0; #ifdef BLIS printf( "data_trmm_blis" ); #else printf( "data_trmm_%s", BLAS ); #endif printf( "( %2lu, 1:3 ) = [ %4lu %4lu %7.2f ];\n", ( unsigned long )(p - p_begin)/p_inc + 1, ( unsigned long )m, ( unsigned long )n, gflops ); bli_obj_free( &alpha ); bli_obj_free( &a ); bli_obj_free( &c ); bli_obj_free( &c_save ); } //bli_finalize(); return 0; } blis-0.9.0/test/test_trmv.c000066400000000000000000000112771422157504600156410ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifdef WIN32 #include #else #include #endif #include "blis.h" // uploa trans, diag, m a lda x incx //void dtrmv_( char*, char*, char*, int*, double*, int*, double*, int* ); //#define PRINT int main( int argc, char** argv ) { obj_t a, x; obj_t x_save; obj_t alpha; dim_t m; dim_t p; dim_t p_begin, p_end, p_inc; int m_input; num_t dt_a, dt_x; num_t dt_alpha; int r, n_repeats; uplo_t uplo; double dtime; double dtime_save; double gflops; //bli_init(); n_repeats = 3; #ifndef PRINT p_begin = 40; p_end = 2000; p_inc = 40; m_input = -1; #else p_begin = 16; p_end = 16; p_inc = 1; m_input = 15; n_input = 15; #endif dt_alpha = dt_a = dt_x = BLIS_DOUBLE; uplo = BLIS_LOWER; // Begin with initializing the last entry to zero so that // matlab allocates space for the entire array once up-front. for ( p = p_begin; p + p_inc <= p_end; p += p_inc ) ; #ifdef BLIS printf( "data_trmv_blis" ); #else printf( "data_trmv_%s", BLAS ); #endif printf( "( %2lu, 1:2 ) = [ %4lu %7.2f ];\n", ( unsigned long )(p - p_begin)/p_inc + 1, ( unsigned long )0, 0.0 ); //for ( p = p_begin; p <= p_end; p += p_inc ) for ( p = p_end; p_begin <= p; p -= p_inc ) { if ( m_input < 0 ) m = p * ( dim_t )abs(m_input); else m = ( dim_t ) m_input; bli_obj_create( dt_alpha, 1, 1, 0, 0, &alpha ); bli_obj_create( dt_a, m, m, 0, 0, &a ); bli_obj_create( dt_x, m, 1, 0, 0, &x ); bli_obj_create( dt_x, m, 1, 0, 0, &x_save ); bli_randm( &a ); bli_randm( &x ); bli_obj_set_struc( BLIS_TRIANGULAR, &a ); bli_obj_set_uplo( uplo, &a ); bli_obj_set_onlytrans( BLIS_NO_TRANSPOSE, &a ); bli_obj_set_diag( BLIS_NONUNIT_DIAG, &a ); bli_setsc( (1.0/1.0), 0.0, &alpha ); bli_copym( &x, &x_save ); dtime_save = DBL_MAX; for ( r = 0; r < n_repeats; ++r ) { bli_copym( &x_save, &x ); dtime = bli_clock(); #ifdef PRINT bli_printm( "a", &a, "%4.1f", "" ); bli_printm( "x", &x, "%4.1f", "" ); #endif #ifdef BLIS bli_trmv( &BLIS_ONE, &a, &x ); #else f77_char uploa = 'L'; f77_char transa = 'N'; f77_char diaga = 'N'; f77_int mm = bli_obj_length( &a ); f77_int lda = bli_obj_col_stride( &a ); f77_int incx = bli_obj_vector_inc( &x ); double* ap = bli_obj_buffer( &a ); double* xp = bli_obj_buffer( &x ); dtrmv_( &uploa, &transa, &diaga, &mm, ap, &lda, xp, &incx ); #endif #ifdef PRINT bli_printm( "x after", &x, "%4.1f", "" ); exit(1); #endif dtime_save = bli_clock_min_diff( dtime_save, dtime ); } gflops = ( 1.0 * m * m ) / ( dtime_save * 1.0e9 ); #ifdef BLIS printf( "data_trmv_blis" ); #else printf( "data_trmv_%s", BLAS ); #endif printf( "( %2lu, 1:2 ) = [ %4lu %7.2f ];\n", ( unsigned long )(p - p_begin)/p_inc + 1, ( unsigned long )m, gflops ); bli_obj_free( &alpha ); bli_obj_free( &a ); bli_obj_free( &x ); bli_obj_free( &x_save ); } //bli_finalize(); return 0; } blis-0.9.0/test/test_trsm.c000066400000000000000000000170231422157504600156310ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifdef WIN32 #include #else #include #endif #include "blis.h" //#define PRINT int main( int argc, char** argv ) { obj_t a, c; obj_t c_save; obj_t alpha; dim_t m, n; dim_t p; dim_t p_begin, p_end, p_inc; int m_input, n_input; num_t dt; int r, n_repeats; side_t side; uplo_t uploa; trans_t transa; diag_t diaga; f77_char f77_side; f77_char f77_uploa; f77_char f77_transa; f77_char f77_diaga; double dtime; double dtime_save; double gflops; //bli_init(); //bli_error_checking_level_set( BLIS_NO_ERROR_CHECKING ); n_repeats = 3; #ifndef PRINT p_begin = 200; p_end = 2000; p_inc = 200; m_input = -1; n_input = -1; #else p_begin = 16; p_end = 16; p_inc = 1; m_input = 4; n_input = 4; #endif #if 1 //dt = BLIS_FLOAT; dt = BLIS_DOUBLE; #else //dt = BLIS_SCOMPLEX; dt = BLIS_DCOMPLEX; #endif side = BLIS_LEFT; //side = BLIS_RIGHT; uploa = BLIS_LOWER; //uploa = BLIS_UPPER; transa = BLIS_NO_TRANSPOSE; diaga = BLIS_NONUNIT_DIAG; bli_param_map_blis_to_netlib_side( side, &f77_side ); bli_param_map_blis_to_netlib_uplo( uploa, &f77_uploa ); bli_param_map_blis_to_netlib_trans( transa, &f77_transa ); bli_param_map_blis_to_netlib_diag( diaga, &f77_diaga ); // Begin with initializing the last entry to zero so that // matlab allocates space for the entire array once up-front. for ( p = p_begin; p + p_inc <= p_end; p += p_inc ) ; #ifdef BLIS printf( "data_trsm_blis" ); #else printf( "data_trsm_%s", BLAS ); #endif printf( "( %2lu, 1:3 ) = [ %4lu %4lu %7.2f ];\n", ( unsigned long )(p - p_begin)/p_inc + 1, ( unsigned long )0, ( unsigned long )0, 0.0 ); //for ( p = p_begin; p <= p_end; p += p_inc ) for ( p = p_end; p_begin <= p; p -= p_inc ) { if ( m_input < 0 ) m = p * ( dim_t )abs(m_input); else m = ( dim_t ) m_input; if ( n_input < 0 ) n = p * ( dim_t )abs(n_input); else n = ( dim_t ) n_input; bli_obj_create( dt, 1, 1, 0, 0, &alpha ); if ( bli_is_left( side ) ) bli_obj_create( dt, m, m, 0, 0, &a ); else bli_obj_create( dt, n, n, 0, 0, &a ); bli_obj_create( dt, m, n, 0, 0, &c ); bli_obj_create( dt, m, n, 0, 0, &c_save ); bli_randm( &a ); bli_randm( &c ); bli_obj_set_struc( BLIS_TRIANGULAR, &a ); bli_obj_set_uplo( uploa, &a ); bli_obj_set_conjtrans( transa, &a ); bli_obj_set_diag( diaga, &a ); // Randomize A and zero the unstored triangle to ensure the // implementation reads only from the stored region. bli_randm( &a ); bli_mktrim( &a ); // Load the diagonal of A to make it more likely to be invertible. bli_shiftd( &BLIS_TWO, &a ); bli_setsc( (2.0/1.0), 1.0, &alpha ); bli_copym( &c, &c_save ); dtime_save = DBL_MAX; for ( r = 0; r < n_repeats; ++r ) { bli_copym( &c_save, &c ); dtime = bli_clock(); #ifdef PRINT bli_invertd( &a ); bli_printm( "a", &a, "%4.1f", "" ); bli_invertd( &a ); bli_printm( "c", &c, "%4.1f", "" ); #endif #ifdef BLIS bli_trsm( side, &alpha, &a, &c ); #else if ( bli_is_float( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldc = bli_obj_col_stride( &c ); float* alphap = bli_obj_buffer( &alpha ); float* ap = bli_obj_buffer( &a ); float* cp = bli_obj_buffer( &c ); strsm_( &f77_side, &f77_uploa, &f77_transa, &f77_diaga, &mm, &nn, alphap, ap, &lda, cp, &ldc ); } else if ( bli_is_double( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldc = bli_obj_col_stride( &c ); double* alphap = bli_obj_buffer( &alpha ); double* ap = bli_obj_buffer( &a ); double* cp = bli_obj_buffer( &c ); dtrsm_( &f77_side, &f77_uploa, &f77_transa, &f77_diaga, &mm, &nn, alphap, ap, &lda, cp, &ldc ); } else if ( bli_is_scomplex( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldc = bli_obj_col_stride( &c ); scomplex* alphap = bli_obj_buffer( &alpha ); scomplex* ap = bli_obj_buffer( &a ); scomplex* cp = bli_obj_buffer( &c ); ctrsm_( &f77_side, &f77_uploa, &f77_transa, &f77_diaga, &mm, &nn, alphap, ap, &lda, cp, &ldc ); } else if ( bli_is_dcomplex( dt ) ) { f77_int mm = bli_obj_length( &c ); f77_int nn = bli_obj_width( &c ); f77_int lda = bli_obj_col_stride( &a ); f77_int ldc = bli_obj_col_stride( &c ); dcomplex* alphap = bli_obj_buffer( &alpha ); dcomplex* ap = bli_obj_buffer( &a ); dcomplex* cp = bli_obj_buffer( &c ); ztrsm_( &f77_side, &f77_uploa, &f77_transa, &f77_diaga, &mm, &nn, alphap, ap, &lda, cp, &ldc ); } #endif #ifdef PRINT bli_printm( "c after", &c, "%9.5f", "" ); exit(1); #endif dtime_save = bli_clock_min_diff( dtime_save, dtime ); } if ( bli_is_left( side ) ) gflops = ( 1.0 * m * m * n ) / ( dtime_save * 1.0e9 ); else gflops = ( 1.0 * m * n * n ) / ( dtime_save * 1.0e9 ); if ( bli_is_complex( dt ) ) gflops *= 4.0; #ifdef BLIS printf( "data_trsm_blis" ); #else printf( "data_trsm_%s", BLAS ); #endif printf( "( %2lu, 1:3 ) = [ %4lu %4lu %7.2f ];\n", ( unsigned long )(p - p_begin)/p_inc + 1, ( unsigned long )m, ( unsigned long )n, gflops ); bli_obj_free( &alpha ); bli_obj_free( &a ); bli_obj_free( &c ); bli_obj_free( &c_save ); } //bli_finalize(); return 0; } blis-0.9.0/test/test_trsv.c000066400000000000000000000116771422157504600156530ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #ifdef WIN32 #include #else #include #endif #include "blis.h" // uploa trans, diag, m a lda x incx //void dtrsv_( char*, char*, char*, int*, double*, int*, double*, int* ); //#define PRINT int main( int argc, char** argv ) { obj_t a, x; obj_t x_save; obj_t alpha; dim_t m; dim_t p; dim_t p_begin, p_end, p_inc; int m_input; num_t dt_a, dt_x; num_t dt_alpha; int r, n_repeats; uplo_t uplo; double dtime; double dtime_save; double gflops; //bli_init(); n_repeats = 3; #ifndef PRINT p_begin = 40; p_end = 2000; p_inc = 40; m_input = -1; #else p_begin = 16; p_end = 16; p_inc = 1; m_input = 15; n_input = 15; #endif dt_alpha = dt_a = dt_x = BLIS_DOUBLE; uplo = BLIS_LOWER; // Begin with initializing the last entry to zero so that // matlab allocates space for the entire array once up-front. for ( p = p_begin; p + p_inc <= p_end; p += p_inc ) ; #ifdef BLIS printf( "data_trsv_blis" ); #else printf( "data_trv_%s", BLAS ); #endif printf( "( %2lu, 1:2 ) = [ %4lu %7.2f ];\n", ( unsigned long )(p - p_begin)/p_inc + 1, ( unsigned long )0, 0.0 ); //for ( p = p_begin; p <= p_end; p += p_inc ) for ( p = p_end; p_begin <= p; p -= p_inc ) { if ( m_input < 0 ) m = p * ( dim_t )abs(m_input); else m = ( dim_t ) m_input; bli_obj_create( dt_alpha, 1, 1, 0, 0, &alpha ); bli_obj_create( dt_a, m, m, 0, 0, &a ); bli_obj_create( dt_x, m, 1, 0, 0, &x ); bli_obj_create( dt_x, m, 1, 0, 0, &x_save ); bli_randm( &a ); bli_randm( &x ); bli_obj_set_struc( BLIS_TRIANGULAR, &a ); bli_obj_set_uplo( uplo, &a ); bli_obj_set_onlytrans( BLIS_NO_TRANSPOSE, &a ); bli_obj_set_diag( BLIS_NONUNIT_DIAG, &a ); // Randomize A and zero the unstored triangle to ensure the // implementation reads only from the stored region. bli_randm( &a ); bli_mktrim( &a ); // Load the diagonal of A to make it more likely to be invertible. bli_shiftd( &BLIS_TWO, &a ); bli_setsc( (1.0/1.0), 0.0, &alpha ); bli_copym( &x, &x_save ); dtime_save = DBL_MAX; for ( r = 0; r < n_repeats; ++r ) { bli_copym( &x_save, &x ); dtime = bli_clock(); #ifdef PRINT bli_printm( "a", &a, "%4.1f", "" ); bli_printm( "x", &x, "%4.1f", "" ); #endif #ifdef BLIS bli_trsv( &BLIS_ONE, &a, &x ); #else f77_char uploa = 'L'; f77_char transa = 'N'; f77_char diaga = 'N'; f77_int mm = bli_obj_length( &a ); f77_int lda = bli_obj_col_stride( &a ); f77_int incx = bli_obj_vector_inc( &x ); double* ap = bli_obj_buffer( &a ); double* xp = bli_obj_buffer( &x ); dtrsv_( &uploa, &transa, &diaga, &mm, ap, &lda, xp, &incx ); #endif #ifdef PRINT bli_printm( "x after", &x, "%4.1f", "" ); exit(1); #endif dtime_save = bli_clock_min_diff( dtime_save, dtime ); } gflops = ( 1.0 * m * m ) / ( dtime_save * 1.0e9 ); #ifdef BLIS printf( "data_trsv_blis" ); #else printf( "data_trsv_%s", BLAS ); #endif printf( "( %2lu, 1:2 ) = [ %4lu %7.2f ];\n", ( unsigned long )(p - p_begin)/p_inc + 1, ( unsigned long )m, gflops ); bli_obj_free( &alpha ); bli_obj_free( &a ); bli_obj_free( &x ); bli_obj_free( &x_save ); } //bli_finalize(); return 0; } blis-0.9.0/test/thread_ranges/000077500000000000000000000000001422157504600162445ustar00rootroot00000000000000blis-0.9.0/test/thread_ranges/Makefile000066400000000000000000000107271422157504600177130ustar00rootroot00000000000000#!/bin/bash # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2014, The University of Texas at Austin # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # # # Makefile # # Field G. Van Zee # # Makefile for standalone BLIS test drivers. # # # --- Makefile PHONY target definitions ---------------------------------------- # .PHONY: all \ test-ranges \ clean cleanx # # --- Determine makefile fragment location ------------------------------------- # # Comments: # - DIST_PATH is assumed to not exist if BLIS_INSTALL_PATH is given. # - We must use recursively expanded assignment for LIB_PATH and INC_PATH in # the second case because CONFIG_NAME is not yet set. ifneq ($(strip $(BLIS_INSTALL_PATH)),) LIB_PATH := $(BLIS_INSTALL_PATH)/lib INC_PATH := $(BLIS_INSTALL_PATH)/include/blis SHARE_PATH := $(BLIS_INSTALL_PATH)/share/blis else DIST_PATH := ../.. LIB_PATH = ../../lib/$(CONFIG_NAME) INC_PATH = ../../include/$(CONFIG_NAME) SHARE_PATH := ../.. endif # # --- Include common makefile definitions -------------------------------------- # # Include the common makefile fragment. -include $(SHARE_PATH)/common.mk # # --- General build definitions ------------------------------------------------ # TEST_SRC_PATH := . TEST_OBJ_PATH := . # Gather all local object files. TEST_OBJS := $(sort $(patsubst $(TEST_SRC_PATH)/%.c, \ $(TEST_OBJ_PATH)/%.o, \ $(wildcard $(TEST_SRC_PATH)/*.c))) # Override the value of CINCFLAGS so that the value of CFLAGS returned by # get-user-cflags-for() is not cluttered up with include paths needed only # while building BLIS. CINCFLAGS := -I$(INC_PATH) # Use the CFLAGS for the configuration family. CFLAGS := $(call get-user-cflags-for,$(CONFIG_NAME)) # Add installed and local header paths to CFLAGS CFLAGS += -I$(TEST_SRC_PATH) # Locate the libblis library to which we will link. #LIBBLIS_LINK := $(LIB_PATH)/$(LIBBLIS_L) # Datatype DT_S := -DDT=BLIS_FLOAT DT_D := -DDT=BLIS_DOUBLE DT_C := -DDT=BLIS_SCOMPLEX DT_Z := -DDT=BLIS_DCOMPLEX # Problem size specification PDEF_MT := -DP_BEGIN=400 \ -DP_END=8000 \ -DP_INC=400 # # --- Targets/rules ------------------------------------------------------------ # all: test-ranges test-ranges: \ test_ranges.x # --Object file rules -- $(TEST_OBJ_PATH)/%.o: $(TEST_SRC_PATH)/%.c $(CC) $(CFLAGS) -c $< -o $@ # blis asm test_%.o: test_%.c $(CC) $(CFLAGS) $(PDEF_MT) $(DT_D) -c $< -o $@ # -- Executable file rules -- # NOTE: For the BLAS test drivers, we place the BLAS libraries before BLIS # on the link command line in case BLIS was configured with the BLAS # compatibility layer. This prevents BLIS from inadvertently getting called # for the BLAS routines we are trying to test with. test_ranges.x: test_ranges.o $(LIBBLIS_LINK) $(LINKER) $< $(LIBBLIS_LINK) $(LDFLAGS) -o $@ # -- Clean rules -- clean: cleanx cleanx: - $(RM_F) *.o *.x blis-0.9.0/test/thread_ranges/test_ranges.c000066400000000000000000000243361422157504600207360ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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 The University of Texas 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 COPYRIGHT HOLDER 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. */ #include #include "blis.h" //#define PRINT int main( int argc, char** argv ) { //bli_init(); #if 0 obj_t a, b, c; obj_t aa, bb, cc; dim_t m, n, k; num_t dt; uplo_t uploa, uplob, uploc; { dt = BLIS_DOUBLE; m = 6; k = 6; n = 6; bli_obj_create( dt, m, k, 0, 0, &a ); bli_obj_create( dt, k, n, 0, 0, &b ); bli_obj_create( dt, m, n, 0, 0, &c ); uploa = BLIS_UPPER; uploa = BLIS_LOWER; bli_obj_set_struc( BLIS_TRIANGULAR, &a ); bli_obj_set_uplo( uploa, &a ); bli_obj_set_diag_offset( -2, &a ); uplob = BLIS_UPPER; uplob = BLIS_LOWER; bli_obj_set_struc( BLIS_TRIANGULAR, &b ); bli_obj_set_uplo( uplob, &b ); bli_obj_set_diag_offset( -2, &b ); uploc = BLIS_UPPER; //uploc = BLIS_LOWER; //uploc = BLIS_ZEROS; //uploc = BLIS_DENSE; bli_obj_set_struc( BLIS_HERMITIAN, &c ); //bli_obj_set_struc( BLIS_TRIANGULAR, &c ); bli_obj_set_uplo( uploc, &c ); bli_obj_set_diag_offset( 1, &c ); bli_obj_alias_to( &a, &aa ); (void)aa; bli_obj_alias_to( &b, &bb ); (void)bb; bli_obj_alias_to( &c, &cc ); (void)cc; bli_randm( &a ); bli_randm( &b ); bli_randm( &c ); //bli_mkherm( &a ); //bli_mktrim( &a ); bli_prune_unref_mparts( &cc, BLIS_M, &aa, BLIS_N ); bli_printm( "c orig", &c, "%4.1f", "" ); bli_printm( "c alias", &cc, "%4.1f", "" ); bli_printm( "a orig", &a, "%4.1f", "" ); bli_printm( "a alias", &aa, "%4.1f", "" ); //bli_obj_print( "a struct", &a ); } #endif dim_t p_begin, p_max, p_inc; gint_t m_input, n_input; char uploa_ch; doff_t diagoffa; dim_t bf; dim_t n_way; char part_dim_ch; dim_t go_fwd; char out_ch; obj_t a; blksz_t bfs; thrinfo_t thrinfo; dim_t m, n; uplo_t uploa; dim_t part_m_dim, part_n_dim; dim_t go_bwd; dim_t p; num_t dt; dim_t start, end; dim_t width; siz_t area; gint_t t_begin, t_stop, t_inc; dim_t t; if ( argc == 13 ) { sscanf( argv[1], "%u", &p_begin ); sscanf( argv[2], "%u", &p_max ); sscanf( argv[3], "%u", &p_inc ); sscanf( argv[4], "%d", &m_input ); sscanf( argv[5], "%d", &n_input ); sscanf( argv[6], "%c", &uploa_ch ); sscanf( argv[7], "%d", &diagoffa ); sscanf( argv[8], "%u", &bf ); sscanf( argv[9], "%u", &n_way ); sscanf( argv[10], "%c", &part_dim_ch ); sscanf( argv[11], "%u", &go_fwd ); sscanf( argv[12], "%c", &out_ch ); } else { printf( "\n" ); printf( " %s\n", argv[0] ); printf( "\n" ); printf( " Simulate the dimension ranges assigned to threads when\n" ); printf( " partitioning a matrix for parallelism in BLIS.\n" ); printf( "\n" ); printf( " Usage:\n" ); printf( "\n" ); printf( " %s p_beg p_max p_inc m n uplo doff bf n_way part_dim go_fwd out\n", argv[0] ); printf( "\n" ); printf( " p_beg: the first problem size p to test.\n" ); printf( " p_max: the maximum problem size p to test.\n" ); printf( " p_inc: the increase in problem size p between tests.\n" ); printf( " m: the m dimension:\n" ); printf( " n: the n dimension:\n" ); printf( " if m,n = -1: bind m,n to problem size p.\n" ); printf( " if m,n = 0: bind m,n to p_max.\n" ); printf( " if m,n > 0: hold m,n = c constant for all p.\n" ); printf( " uplo: the uplo field of the matrix being partitioned:\n" ); printf( " 'l': lower-stored (BLIS_LOWER)\n" ); printf( " 'u': upper-stored (BLIS_UPPER)\n" ); printf( " 'd': densely-stored (BLIS_DENSE)\n" ); printf( " doff: the diagonal offset of the matrix being partitioned.\n" ); printf( " bf: the simulated blocking factor. all thread ranges must\n" ); printf( " be a multiple of bf, except for the range that contains\n" ); printf( " the edge case (if one exists). the blocking factor\n" ); printf( " would typically correspond to a register blocksize.\n" ); printf( " n_way: the number of ways of parallelism for which we are\n" ); printf( " partitioning (i.e.: the number of threads, or thread\n" ); printf( " groups).\n" ); printf( " part_dim: the dimension to partition:\n" ); printf( " 'm': partition the m dimension.\n" ); printf( " 'n': partition the n dimension.\n" ); printf( " go_fwd: the direction to partition:\n" ); printf( " '1': forward, e.g. left-to-right (part_dim = 'm') or\n" ); printf( " top-to-bottom (part_dim = 'n')\n" ); printf( " '0': backward, e.g. right-to-left (part_dim = 'm') or\n" ); printf( " bottom-to-top (part_dim = 'n')\n" ); printf( " NOTE: reversing the direction does not change the\n" ); printf( " subpartitions' widths, but it does change which end of\n" ); printf( " the index range receives the edge case, if it exists.\n" ); printf( " out: the type of output per thread-column:\n" ); printf( " 'w': the width (and area) of the thread's subpartition\n" ); printf( " 'r': the actual ranges of the thread's subpartition\n" ); printf( " where the start and end points of each range are\n" ); printf( " inclusive and exclusive, respectively.\n" ); printf( "\n" ); exit(1); } if ( m_input == 0 ) m_input = p_max; if ( n_input == 0 ) n_input = p_max; if ( part_dim_ch == 'm' ) { part_m_dim = TRUE; part_n_dim = FALSE; } else { part_m_dim = FALSE; part_n_dim = TRUE; } go_bwd = !go_fwd; if ( uploa_ch == 'l' ) uploa = BLIS_LOWER; else if ( uploa_ch == 'u' ) uploa = BLIS_UPPER; else uploa = BLIS_DENSE; if ( part_n_dim ) { if ( bli_is_upper( uploa ) ) { t_begin = n_way-1; t_stop = -1; t_inc = -1; } else /* if lower or dense */ { t_begin = 0; t_stop = n_way; t_inc = 1; } } else // if ( part_m_dim ) { if ( bli_is_lower( uploa ) ) { t_begin = n_way-1; t_stop = -1; t_inc = -1; } else /* if upper or dense */ { t_begin = 0; t_stop = n_way; t_inc = 1; } } printf( "\n" ); printf( " part: %3s doff: %3d bf: %3d output: %s\n", ( part_n_dim ? ( go_fwd ? "l2r" : "r2l" ) : ( go_fwd ? "t2b" : "b2t" ) ), ( int )diagoffa, ( int )bf, ( out_ch == 'w' ? "width(area)" : "ranges" ) ); printf( " uplo: %3c nt: %3u\n", uploa_ch, ( unsigned )n_way ); printf( "\n" ); printf( " " ); for ( t = t_begin; t != t_stop; t += t_inc ) { if ( part_n_dim ) { if ( t == t_begin ) printf( "left... " ); else if ( t == t_stop-t_inc ) printf( " ...right" ); else printf( " " ); } else // if ( part_m_dim ) { if ( t == t_begin ) printf( "top... " ); else if ( t == t_stop-t_inc ) printf( " ...bottom" ); else printf( " " ); } } printf( "\n" ); printf( "%4c x %4c ", 'm', 'n' ); for ( t = t_begin; t != t_stop; t += t_inc ) { printf( "%9s %u ", "thread", ( unsigned )t ); } printf( "\n" ); printf( "-------------" ); for ( t = t_begin; t != t_stop; t += t_inc ) { printf( "-------------" ); } printf( "\n" ); for ( p = p_begin; p <= p_max; p += p_inc ) { if ( m_input < 0 ) m = ( dim_t )p; else m = ( dim_t )m_input; if ( n_input < 0 ) n = ( dim_t )p; else n = ( dim_t )n_input; dt = BLIS_DOUBLE; bli_obj_create( dt, m, n, 0, 0, &a ); bli_obj_set_struc( BLIS_TRIANGULAR, &a ); bli_obj_set_uplo( uploa, &a ); bli_obj_set_diag_offset( diagoffa, &a ); bli_randm( &a ); bli_blksz_init_easy( &bfs, bf, bf, bf, bf ); printf( "%4u x %4u ", ( unsigned )m, ( unsigned )n ); for ( t = t_begin; t != t_stop; t += t_inc ) { thrinfo.n_way = n_way; thrinfo.work_id = t; if ( part_n_dim && go_fwd ) area = bli_thread_range_weighted_l2r( &thrinfo, &a, &bfs, &start, &end ); else if ( part_n_dim && go_bwd ) area = bli_thread_range_weighted_r2l( &thrinfo, &a, &bfs, &start, &end ); else if ( part_m_dim && go_fwd ) area = bli_thread_range_weighted_t2b( &thrinfo, &a, &bfs, &start, &end ); else // ( part_m_dim && go_bwd ) area = bli_thread_range_weighted_b2t( &thrinfo, &a, &bfs, &start, &end ); width = end - start; if ( out_ch == 'w' ) printf( "%4u(%6u) ", ( unsigned )width, ( unsigned )area ); else printf( "[%4u,%4u) ", ( unsigned )start, ( unsigned )end ); } printf( "\n" ); bli_obj_free( &a ); } //bli_finalize(); return 0; } blis-0.9.0/testsuite/000077500000000000000000000000001422157504600145105ustar00rootroot00000000000000blis-0.9.0/testsuite/Makefile000066400000000000000000000130731422157504600161540ustar00rootroot00000000000000# # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2014, The University of Texas at Austin # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # # # Makefile # # Field G. Van Zee # # Makefile for BLIS testsuite. # # # --- Makefile PHONY target definitions ---------------------------------------- # .PHONY: all bin clean \ check-env check-env-mk check-env-fragments check-env-make-defs \ run run-amd64 run-x86 run-arm # # --- Determine makefile fragment location ------------------------------------- # # Comments: # - DIST_PATH is assumed to not exist if BLIS_INSTALL_PATH is given. # - We must use recursively expanded assignment for LIB_PATH and INC_PATH in # the second case because CONFIG_NAME is not yet set. ifneq ($(strip $(BLIS_INSTALL_PATH)),) LIB_PATH := $(BLIS_INSTALL_PATH)/lib INC_PATH := $(BLIS_INSTALL_PATH)/include/blis SHARE_PATH := $(BLIS_INSTALL_PATH)/share/blis else DIST_PATH := .. LIB_PATH = ../lib/$(CONFIG_NAME) INC_PATH = ../include/$(CONFIG_NAME) SHARE_PATH := .. endif # # --- Include common makefile definitions -------------------------------------- # # Include the common makefile fragment. -include $(SHARE_PATH)/common.mk # # --- General build definitions ------------------------------------------------ # TEST_SRC_PATH := src TEST_OBJ_PATH := obj # Gather all local object files. TEST_OBJS := $(sort $(patsubst $(TEST_SRC_PATH)/%.c, \ $(TEST_OBJ_PATH)/%.o, \ $(wildcard $(TEST_SRC_PATH)/*.c))) # Override the value of CINCFLAGS so that the value of CFLAGS returned by # get-user-cflags-for() is not cluttered up with include paths needed only # while building BLIS. CINCFLAGS := -I$(INC_PATH) # Use the "framework" CFLAGS for the configuration family. CFLAGS := $(call get-user-cflags-for,$(CONFIG_NAME)) # Add local header paths to CFLAGS CFLAGS += -I$(TEST_SRC_PATH) # Locate the libblis library to which we will link. #LIBBLIS_LINK := $(LIB_PATH)/$(LIBBLIS_L) # Binary executable name. TESTSUITE_BIN := test_libblis.x # # --- Targets/rules ------------------------------------------------------------ # # --- Primary targets --- all: check-env bin bin: check-env $(TESTSUITE_BIN) # --- Environment check rules --- check-env: check-env-make-defs check-env-fragments check-env-config-mk check-env-config-mk: ifeq ($(CONFIG_MK_PRESENT),no) $(error Cannot proceed: config.mk not detected! Run configure first) endif check-env-make-defs: check-env-fragments ifeq ($(MAKE_DEFS_MK_PRESENT),no) $(error Cannot proceed: make_defs.mk not detected! Invalid configuration) endif # --Object file rules -- $(TEST_OBJ_PATH)/%.o: $(TEST_SRC_PATH)/%.c $(LIBBLIS_LINK) ifeq ($(ENABLE_VERBOSE),yes) $(CC) $(CFLAGS) -c $< -o $@ else @echo "Compiling $@" @$(CC) $(CFLAGS) -c $< -o $@ endif # -- Executable file rules -- $(TESTSUITE_BIN): $(TEST_OBJS) $(LIBBLIS_LINK) ifeq ($(ENABLE_VERBOSE),yes) $(LINKER) $(TEST_OBJS) $(LIBBLIS_LINK) $(LDFLAGS) -o $@ else @echo "Linking $@ against '$(LIBBLIS_LINK) $(LDFLAGS)'" @$(LINKER) $(TEST_OBJS) $(LIBBLIS_LINK) $(LDFLAGS) -o $@ endif # -- Test run/check rules -- run: $(TESTSUITE_BIN) ifeq ($(ENABLE_VERBOSE),yes) ./$(TESTSUITE_BIN) > $(TESTSUITE_OUT_FILE) else @echo "Running $(TESTSUITE_BIN) with output redirected to '$(TESTSUITE_OUT_FILE)'" @./$(TESTSUITE_BIN) > $(TESTSUITE_OUT_FILE) endif run-fast: $(TESTSUITE_BIN) ifeq ($(ENABLE_VERBOSE),yes) ./$(TESTSUITE_BIN) -g $(TESTSUITE_FAST_GEN) -o $(TESTSUITE_FAST_OPS) > $(TESTSUITE_OUT_FILE) else @echo "Running $(TESTSUITE_BIN) (fast) with output redirected to '$(TESTSUITE_OUT_FILE)'" @./$(TESTSUITE_BIN) -g $(TESTSUITE_FAST_GEN) -o $(TESTSUITE_FAST_OPS) > $(TESTSUITE_OUT_FILE) endif check: run ifeq ($(ENABLE_VERBOSE),yes) - $(TESTSUITE_CHECK) $(TESTSUITE_OUT_FILE) else @- $(TESTSUITE_CHECK) $(TESTSUITE_OUT_FILE) endif check-fast: run-fast ifeq ($(ENABLE_VERBOSE),yes) - $(TESTSUITE_CHECK) $(TESTSUITE_OUT_FILE) else @- $(TESTSUITE_CHECK) $(TESTSUITE_OUT_FILE) endif # -- Clean rules -- clean: - $(RM_F) $(TEST_OBJS) $(TESTSUITE_BIN) blis-0.9.0/testsuite/check-blistest.sh000077500000000000000000000042111422157504600177510ustar00rootroot00000000000000#!/bin/sh # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2018, The University of Texas at Austin # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # script_name=${0##*/} ansi_red="\033[0;31m" ansi_green="\033[0;32m" ansi_normal="\033[0m" passmsg="All BLIS tests passed!" failmsg0="At least one BLIS test failed. :(" failmsg1="Please see output.testsuite for details." grep -q FAILURE $1 if [ $? -eq 0 ]; then printf "${ansi_red}""${script_name}: ${failmsg0}""${ansi_normal}\n" printf "${ansi_red}""${script_name}: ${failmsg1}""${ansi_normal}\n" exit 1 else printf "${ansi_green}""${script_name}: ${passmsg}""${ansi_normal}\n" exit 0 fi blis-0.9.0/testsuite/input.general000066400000000000000000000040351422157504600172100ustar00rootroot00000000000000# ---------------------------------------------------------------------- # # input.general # BLIS test suite # # This file contains input values that control how BLIS operations are # tested. Comments explain the purpose of each parameter as well as # accepted values. # 1 # Number of repeats per experiment (best result is reported) rc # Matrix storage scheme(s) to test: # 'c' = col-major storage; 'g' = general stride storage; # 'r' = row-major storage cj # Vector storage scheme(s) to test: # 'c' = colvec / unit stride; 'j' = colvec / non-unit stride; # 'r' = rowvec / unit stride; 'i' = rowvec / non-unit stride 0 # Test all combinations of storage schemes? 1 # Perform all tests with alignment? # '0' = do NOT align buffers/ldims; '1' = align buffers/ldims 0 # Randomize vectors and matrices using: # '0' = real values on [-1,1]; # '1' = powers of 2 in narrow precision range 32 # General stride spacing (for cases when testing general stride) sdcz # Datatype(s) to test: # 's' = single real; 'c' = single complex; # 'd' = double real; 'z' = double complex 0 # Test gemm with mixed-domain operands? 0 # Test gemm with mixed-precision operands? 100 # Problem size: first to test 500 # Problem size: maximum to test 100 # Problem size: increment between experiments # Complex level-3 implementations to test: 1 # 1m ('1' = enable; '0' = disable) 1 # native ('1' = enable; '0' = disable) 1 # Simulate application-level threading: # '1' = disable / use one testsuite thread; # 'n' = enable and use n testsuite threads 1 # Error-checking level: # '0' = disable error checking; '1' = full error checking i # Reaction to test failure: # 'i' = ignore; 's' = sleep() and continue; 'a' = abort 0 # Output results in matlab/octave format? ('1' = yes; '0' = no) 0 # Output results to stdout AND files? ('1' = yes; '0' = no) blis-0.9.0/testsuite/input.general.fast000066400000000000000000000040421422157504600201420ustar00rootroot00000000000000# ---------------------------------------------------------------------- # # input.general.fast # BLIS test suite # # This file contains input values that control how BLIS operations are # tested. Comments explain the purpose of each parameter as well as # accepted values. # 1 # Number of repeats per experiment (best result is reported) rc # Matrix storage scheme(s) to test: # 'c' = col-major storage; 'g' = general stride storage; # 'r' = row-major storage cj # Vector storage scheme(s) to test: # 'c' = colvec / unit stride; 'j' = colvec / non-unit stride; # 'r' = rowvec / unit stride; 'i' = rowvec / non-unit stride 0 # Test all combinations of storage schemes? 1 # Perform all tests with alignment? # '0' = do NOT align buffers/ldims; '1' = align buffers/ldims 0 # Randomize vectors and matrices using: # '0' = real values on [-1,1]; # '1' = powers of 2 in narrow precision range 32 # General stride spacing (for cases when testing general stride) sdcz # Datatype(s) to test: # 's' = single real; 'c' = single complex; # 'd' = double real; 'z' = double complex 0 # Test gemm with mixed-domain operands? 0 # Test gemm with mixed-precision operands? 100 # Problem size: first to test 100 # Problem size: maximum to test 100 # Problem size: increment between experiments # Complex level-3 implementations to test: 1 # 1m ('1' = enable; '0' = disable) 1 # native ('1' = enable; '0' = disable) 1 # Simulate application-level threading: # '1' = disable / use one testsuite thread; # 'n' = enable and use n testsuite threads 1 # Error-checking level: # '0' = disable error checking; '1' = full error checking i # Reaction to test failure: # 'i' = ignore; 's' = sleep() and continue; 'a' = abort 0 # Output results in matlab/octave format? ('1' = yes; '0' = no) 0 # Output results to stdout AND files? ('1' = yes; '0' = no) blis-0.9.0/testsuite/input.general.mixed000066400000000000000000000040351422157504600203150ustar00rootroot00000000000000# ---------------------------------------------------------------------- # # input.general # BLIS test suite # # This file contains input values that control how BLIS operations are # tested. Comments explain the purpose of each parameter as well as # accepted values. # 1 # Number of repeats per experiment (best result is reported) rc # Matrix storage scheme(s) to test: # 'c' = col-major storage; 'g' = general stride storage; # 'r' = row-major storage cj # Vector storage scheme(s) to test: # 'c' = colvec / unit stride; 'j' = colvec / non-unit stride; # 'r' = rowvec / unit stride; 'i' = rowvec / non-unit stride 0 # Test all combinations of storage schemes? 1 # Perform all tests with alignment? # '0' = do NOT align buffers/ldims; '1' = align buffers/ldims 0 # Randomize vectors and matrices using: # '0' = real values on [-1,1]; # '1' = powers of 2 in narrow precision range 32 # General stride spacing (for cases when testing general stride) sdcz # Datatype(s) to test: # 's' = single real; 'c' = single complex; # 'd' = double real; 'z' = double complex 1 # Test gemm with mixed-domain operands? 1 # Test gemm with mixed-precision operands? 100 # Problem size: first to test 500 # Problem size: maximum to test 100 # Problem size: increment between experiments # Complex level-3 implementations to test: 1 # 1m ('1' = enable; '0' = disable) 1 # native ('1' = enable; '0' = disable) 1 # Simulate application-level threading: # '1' = disable / use one testsuite thread; # 'n' = enable and use n testsuite threads 1 # Error-checking level: # '0' = disable error checking; '1' = full error checking i # Reaction to test failure: # 'i' = ignore; 's' = sleep() and continue; 'a' = abort 0 # Output results in matlab/octave format? ('1' = yes; '0' = no) 0 # Output results to stdout AND files? ('1' = yes; '0' = no) blis-0.9.0/testsuite/input.general.salt000066400000000000000000000040351422157504600201520ustar00rootroot00000000000000# ---------------------------------------------------------------------- # # input.general # BLIS test suite # # This file contains input values that control how BLIS operations are # tested. Comments explain the purpose of each parameter as well as # accepted values. # 1 # Number of repeats per experiment (best result is reported) rc # Matrix storage scheme(s) to test: # 'c' = col-major storage; 'g' = general stride storage; # 'r' = row-major storage cj # Vector storage scheme(s) to test: # 'c' = colvec / unit stride; 'j' = colvec / non-unit stride; # 'r' = rowvec / unit stride; 'i' = rowvec / non-unit stride 0 # Test all combinations of storage schemes? 1 # Perform all tests with alignment? # '0' = do NOT align buffers/ldims; '1' = align buffers/ldims 0 # Randomize vectors and matrices using: # '0' = real values on [-1,1]; # '1' = powers of 2 in narrow precision range 32 # General stride spacing (for cases when testing general stride) sdcz # Datatype(s) to test: # 's' = single real; 'c' = single complex; # 'd' = double real; 'z' = double complex 0 # Test gemm with mixed-domain operands? 0 # Test gemm with mixed-precision operands? 100 # Problem size: first to test 100 # Problem size: maximum to test 100 # Problem size: increment between experiments # Complex level-3 implementations to test: 1 # 1m ('1' = enable; '0' = disable) 1 # native ('1' = enable; '0' = disable) 4 # Simulate application-level threading: # '1' = disable / use one testsuite thread; # 'n' = enable and use n testsuite threads 1 # Error-checking level: # '0' = disable error checking; '1' = full error checking i # Reaction to test failure: # 'i' = ignore; 's' = sleep() and continue; 'a' = abort 0 # Output results in matlab/octave format? ('1' = yes; '0' = no) 0 # Output results to stdout AND files? ('1' = yes; '0' = no) blis-0.9.0/testsuite/input.operations000066400000000000000000000222011422157504600177510ustar00rootroot00000000000000# -------------------------------------------------------------------------- # # input.operations # BLIS test suite # # This file contains input values that control which BLIS operations are # tested as well as how those test runs are parameterized. We will now # describe how each section or line type may be edited. # # ENABLING/DISABLING ENTIRE SECTIONS # The values in the "Section overrides" section allow you to disable # all operations in a given "level". Enabling a level here by itself # does not enable every operation in that level; it simply means that # the individual switches for each operation (in that level) determine # whether or not the tests are executed. Use 1 to enable a section, or # 0 to disable. # # ENABLING/DISABLING INDIVIDUAL OPERATION TESTS # Given that an operation's section override switch is set to 1 # (enabled), whether or not that operation will get tested is # determined by its local switch. For example, if the level-1v section # override is set to 1, and there is a 1 on the line marked "addv", # then the addv operation will be tested. Similarly, a 0 would cause # addv to not be tested. # # ENABLING ONLY SELECT OPERATIONS # If you would like to enable just a few (or even just one) operation # without adjusting any section overrides (or individual operation # switches), change the desired operation switch(es) to 2. This will # cause any operation that is not set to 2 to be disabled, regardless # of section override values. For example, setting the axpyv and gemv # operation switches to 2 will cause the test suite to test ONLY axpyv # and gemv, even if all other sections and operations are set to 1. # NOTE: As long as there is at least on operation switch set to 2, no # other operations will be tested. When you are done testing your # select operations, you should revert the operation switch(es) back # to 1. # # CHANGING PROBLEM SIZE/SHAPES TESTED # The problem sizes tested by an operation are determined by the # dimension specifiers on the line marked "dimensions: ". # If, for example, contains two dimension labels (e.g. # "m n"), then the line should begin with two dimension specifiers. # Dimension specifiers of -1 cause the corresponding dimension to be # bound to the problem size, which is determined by values set in # input.general. Positive values cause the corresponding dimension to # be fixed to that value and held constant. # # Examples of dimension specifiers (where the dimensions are m and n): # # -1 -1 Dimensions m and n grow with problem size (resulting in # square matrices). # -1 150 Dimension m grows with problem size and n is fixed at # 150. # -1 -2 Dimension m grows with problem size and n grows # proportional to half the problem size. # # CHANGING PARAMTER COMBINATIONS TESTED # The parameter combinations tested by an operation are determined by # the parameter specifier characters on the line marked "parameters: # ". If, for example, contains two # parameter labels (e.g. "transa conjx"), then the line should contain # two parameter specifier characters. The '?' specifier character # serves as a wildcard--it causes all possible values of that parameter # to be tested. A character such as 'n' or 't' causes only that value # to be tested. # # Examples of parameter specifiers (where the parameters are transa # and conjx): # # ?? All combinations of the transa and conjx parameters are # tested: nn, nc, tn, tc, cn, cc, hn, hc. # ?n conjx is fixed to "no conjugate" but transa is allowed # to vary: nn, tn, cn, hn. # hc Only the case where transa is "Hermitian-transpose" and # conjx is "conjugate" is tested. # # Here is a full list of the parameter types used by the various BLIS # operations along with their possible character encodings: # # side: l,r left, right # uplo: l,u lower, upper # trans: n,t,c,h no transpose, transpose, conjugate, Hermitian- # transpose (i.e. conjugate-transpose) # conj: n,c no conjugate, conjugate # diag: n,u non-unit diagonal, unit diagonal # # --- Section overrides ---------------------------------------------------- 1 # Utility 1 # Level-1v kernels 1 # Level-1m 1 # Level-1f kernels 1 # Level-2 1 # Level-3 micro-kernels 1 # Level-3 # --- Utility -------------------------------------------------------------- 1 # randv -1 # dimensions: m 1 # randm -1 -1 # dimensions: m n # --- Level-1v ------------------------------------------------------------- 1 # addv -1 # dimensions: m ? # parameters: conjx 1 # amaxv -1 # dimensions: m 1 # axpbyv -1 # dimensions: m ? # parameters: conjx 1 # axpyv -1 # dimensions: m ? # parameters: conjx 1 # copyv -1 # dimensions: m ? # parameters: conjx 1 # dotv -1 # dimensions: m ?? # parameters: conjx conjy 1 # dotxv -1 # dimensions: m ?? # parameters: conjx conjy 1 # normfv -1 # dimensions: m 1 # scalv -1 # dimensions: m ? # parameters: conjbeta 1 # scal2v -1 # dimensions: m ? # parameters: conjx 1 # setv -1 # dimensions: m 1 # subv -1 # dimensions: m ? # parameters: conjx 1 # xpbyv -1 # dimensions: m ? # parameters: conjx # --- Level-1m ------------------------------------------------------------- 1 # addm -1 -2 # dimensions: m n ? # parameters: transa 1 # axpym -1 -1 # dimensions: m n ? # parameters: transa 1 # copym -1 -2 # dimensions: m n ? # parameters: transa 1 # normfm -1 -2 # dimensions: m n 1 # scalm -1 -2 # dimensions: m n ? # parameters: conjbeta 1 # scal2m -1 -2 # dimensions: m n ? # parameters: transa 1 # setm -1 -2 # dimensions: m n 1 # subm -1 -2 # dimensions: m n ? # parameters: transa 1 # xpbym -1 -1 # dimensions: m n ? # parameters: transa # --- Level-1f kernels ----------------------------------------------------- 1 # axpy2v -1 # dimensions: m ?? # parameters: conjx conjy 1 # dotaxpyv -1 # dimensions: m ??? # parameters: conjxt conjx conjy 1 # axpyf -1 # dimensions: m ?? # parameters: conja conjx 1 # dotxf -1 # dimensions: m ?? # parameters: conjat conjx 1 # dotxaxpyf -1 # dimensions: m ???? # parameters: conjat conja conjw conjx # --- Level-2 -------------------------------------------------------------- 1 # gemv -1 -2 # dimensions: m n ?? # parameters: transa conjx 1 # ger -1 -2 # dimensions: m n ?? # parameters: conjx conjy 1 # hemv -1 # dimensions: m ??? # parameters: uploa conja conjx 1 # her -1 # dimensions: m ?? # parameters: uploc conjx 1 # her2 -1 # dimensions: m ??? # parameters: uploc conjx conjy 1 # symv -1 # dimensions: m ??? # parameters: uploa conja conjx 1 # syr -1 # dimensions: m ?? # parameters: uploc conjx 1 # syr2 -1 # dimensions: m ??? # parameters: uploc conjx conjy 1 # trmv -1 # dimensions: m ??? # parameters: uploa transa diaga 1 # trsv -1 # dimensions: m ??? # parameters: uploa transa diaga # --- Level-3 micro-kernels ------------------------------------------------ 1 # gemm -1 # dimensions: k 1 # trsm ? # parameters: uploa 1 # gemmtrsm -1 # dimensions: k ? # parameters: uploa # --- Level-3 -------------------------------------------------------------- 1 # gemm -1 -1 -1 # dimensions: m n k ?? # parameters: transa transb 1 # gemmt -1 -1 # dimensions: m k ??? # parameters: uploc transa transb 1 # hemm -1 -1 # dimensions: m n ???? # parameters: side uploa conja transb 1 # herk -1 -1 # dimensions: m k ?? # parameters: uploc transa 1 # her2k -1 -1 # dimensions: m k ??? # parameters: uploc transa transb 1 # symm -1 -1 # dimensions: m n ???? # parameters: side uploa conja transb 1 # syrk -1 -1 # dimensions: m k ?? # parameters: uploc transa 1 # syr2k -1 -1 # dimensions: m k ??? # parameters: uploc transa transb 1 # trmm -1 -1 # dimensions: m n ???? # parameters: side uploa transa diaga 1 # trmm3 -1 -1 # dimensions: m n ????n # parameters: side uploa transa diaga transb 1 # trsm -1 -1 # dimensions: m n ???? # parameters: side uploa transa diaga blis-0.9.0/testsuite/input.operations.fast000066400000000000000000000222011422157504600207050ustar00rootroot00000000000000# -------------------------------------------------------------------------- # # input.operations # BLIS test suite # # This file contains input values that control which BLIS operations are # tested as well as how those test runs are parameterized. We will now # describe how each section or line type may be edited. # # ENABLING/DISABLING ENTIRE SECTIONS # The values in the "Section overrides" section allow you to disable # all operations in a given "level". Enabling a level here by itself # does not enable every operation in that level; it simply means that # the individual switches for each operation (in that level) determine # whether or not the tests are executed. Use 1 to enable a section, or # 0 to disable. # # ENABLING/DISABLING INDIVIDUAL OPERATION TESTS # Given that an operation's section override switch is set to 1 # (enabled), whether or not that operation will get tested is # determined by its local switch. For example, if the level-1v section # override is set to 1, and there is a 1 on the line marked "addv", # then the addv operation will be tested. Similarly, a 0 would cause # addv to not be tested. # # ENABLING ONLY SELECT OPERATIONS # If you would like to enable just a few (or even just one) operation # without adjusting any section overrides (or individual operation # switches), change the desired operation switch(es) to 2. This will # cause any operation that is not set to 2 to be disabled, regardless # of section override values. For example, setting the axpyv and gemv # operation switches to 2 will cause the test suite to test ONLY axpyv # and gemv, even if all other sections and operations are set to 1. # NOTE: As long as there is at least on operation switch set to 2, no # other operations will be tested. When you are done testing your # select operations, you should revert the operation switch(es) back # to 1. # # CHANGING PROBLEM SIZE/SHAPES TESTED # The problem sizes tested by an operation are determined by the # dimension specifiers on the line marked "dimensions: ". # If, for example, contains two dimension labels (e.g. # "m n"), then the line should begin with two dimension specifiers. # Dimension specifiers of -1 cause the corresponding dimension to be # bound to the problem size, which is determined by values set in # input.general. Positive values cause the corresponding dimension to # be fixed to that value and held constant. # # Examples of dimension specifiers (where the dimensions are m and n): # # -1 -1 Dimensions m and n grow with problem size (resulting in # square matrices). # -1 150 Dimension m grows with problem size and n is fixed at # 150. # -1 -2 Dimension m grows with problem size and n grows # proportional to half the problem size. # # CHANGING PARAMTER COMBINATIONS TESTED # The parameter combinations tested by an operation are determined by # the parameter specifier characters on the line marked "parameters: # ". If, for example, contains two # parameter labels (e.g. "transa conjx"), then the line should contain # two parameter specifier characters. The '?' specifier character # serves as a wildcard--it causes all possible values of that parameter # to be tested. A character such as 'n' or 't' causes only that value # to be tested. # # Examples of parameter specifiers (where the parameters are transa # and conjx): # # ?? All combinations of the transa and conjx parameters are # tested: nn, nc, tn, tc, cn, cc, hn, hc. # ?n conjx is fixed to "no conjugate" but transa is allowed # to vary: nn, tn, cn, hn. # hc Only the case where transa is "Hermitian-transpose" and # conjx is "conjugate" is tested. # # Here is a full list of the parameter types used by the various BLIS # operations along with their possible character encodings: # # side: l,r left, right # uplo: l,u lower, upper # trans: n,t,c,h no transpose, transpose, conjugate, Hermitian- # transpose (i.e. conjugate-transpose) # conj: n,c no conjugate, conjugate # diag: n,u non-unit diagonal, unit diagonal # # --- Section overrides ---------------------------------------------------- 1 # Utility 1 # Level-1v kernels 1 # Level-1m 1 # Level-1f kernels 1 # Level-2 1 # Level-3 micro-kernels 1 # Level-3 # --- Utility -------------------------------------------------------------- 1 # randv -1 # dimensions: m 1 # randm -1 -1 # dimensions: m n # --- Level-1v ------------------------------------------------------------- 1 # addv -1 # dimensions: m ? # parameters: conjx 1 # amaxv -1 # dimensions: m 1 # axpbyv -1 # dimensions: m ? # parameters: conjx 1 # axpyv -1 # dimensions: m ? # parameters: conjx 1 # copyv -1 # dimensions: m ? # parameters: conjx 1 # dotv -1 # dimensions: m ?? # parameters: conjx conjy 1 # dotxv -1 # dimensions: m ?? # parameters: conjx conjy 1 # normfv -1 # dimensions: m 1 # scalv -1 # dimensions: m ? # parameters: conjbeta 1 # scal2v -1 # dimensions: m ? # parameters: conjx 1 # setv -1 # dimensions: m 1 # subv -1 # dimensions: m ? # parameters: conjx 1 # xpbyv -1 # dimensions: m ? # parameters: conjx # --- Level-1m ------------------------------------------------------------- 1 # addm -1 -2 # dimensions: m n ? # parameters: transa 1 # axpym -1 -1 # dimensions: m n ? # parameters: transa 1 # copym -1 -2 # dimensions: m n ? # parameters: transa 1 # normfm -1 -2 # dimensions: m n 1 # scalm -1 -2 # dimensions: m n ? # parameters: conjbeta 1 # scal2m -1 -2 # dimensions: m n ? # parameters: transa 1 # setm -1 -2 # dimensions: m n 1 # subm -1 -2 # dimensions: m n ? # parameters: transa 1 # xpbym -1 -1 # dimensions: m n ? # parameters: transa # --- Level-1f kernels ----------------------------------------------------- 1 # axpy2v -1 # dimensions: m ?? # parameters: conjx conjy 1 # dotaxpyv -1 # dimensions: m ??? # parameters: conjxt conjx conjy 1 # axpyf -1 # dimensions: m ?? # parameters: conja conjx 1 # dotxf -1 # dimensions: m ?? # parameters: conjat conjx 1 # dotxaxpyf -1 # dimensions: m ???? # parameters: conjat conja conjw conjx # --- Level-2 -------------------------------------------------------------- 1 # gemv -1 -2 # dimensions: m n ?? # parameters: transa conjx 1 # ger -1 -2 # dimensions: m n ?? # parameters: conjx conjy 1 # hemv -1 # dimensions: m ??? # parameters: uploa conja conjx 1 # her -1 # dimensions: m ?? # parameters: uploc conjx 1 # her2 -1 # dimensions: m ??? # parameters: uploc conjx conjy 1 # symv -1 # dimensions: m ??? # parameters: uploa conja conjx 1 # syr -1 # dimensions: m ?? # parameters: uploc conjx 1 # syr2 -1 # dimensions: m ??? # parameters: uploc conjx conjy 1 # trmv -1 # dimensions: m ??? # parameters: uploa transa diaga 1 # trsv -1 # dimensions: m ??? # parameters: uploa transa diaga # --- Level-3 micro-kernels ------------------------------------------------ 1 # gemm -1 # dimensions: k 1 # trsm ? # parameters: uploa 1 # gemmtrsm -1 # dimensions: k ? # parameters: uploa # --- Level-3 -------------------------------------------------------------- 1 # gemm -1 -1 -1 # dimensions: m n k nn # parameters: transa transb 1 # gemmt -1 -1 # dimensions: m k ?nn # parameters: uploc transa transb 1 # hemm -1 -1 # dimensions: m n ??nn # parameters: side uploa conja transb 1 # herk -1 -1 # dimensions: m k ?n # parameters: uploc transa 1 # her2k -1 -1 # dimensions: m k ?nn # parameters: uploc transa transb 1 # symm -1 -1 # dimensions: m n ??nn # parameters: side uploa conja transb 1 # syrk -1 -1 # dimensions: m k ?n # parameters: uploc transa 1 # syr2k -1 -1 # dimensions: m k ?nn # parameters: uploc transa transb 1 # trmm -1 -1 # dimensions: m n ??n? # parameters: side uploa transa diaga 0 # trmm3 -1 -1 # dimensions: m n ??n?n # parameters: side uploa transa diaga transb 1 # trsm -1 -1 # dimensions: m n ??n? # parameters: side uploa transa diaga blis-0.9.0/testsuite/input.operations.mixed000066400000000000000000000222011422157504600210560ustar00rootroot00000000000000# -------------------------------------------------------------------------- # # input.operations # BLIS test suite # # This file contains input values that control which BLIS operations are # tested as well as how those test runs are parameterized. We will now # describe how each section or line type may be edited. # # ENABLING/DISABLING ENTIRE SECTIONS # The values in the "Section overrides" section allow you to disable # all operations in a given "level". Enabling a level here by itself # does not enable every operation in that level; it simply means that # the individual switches for each operation (in that level) determine # whether or not the tests are executed. Use 1 to enable a section, or # 0 to disable. # # ENABLING/DISABLING INDIVIDUAL OPERATION TESTS # Given that an operation's section override switch is set to 1 # (enabled), whether or not that operation will get tested is # determined by its local switch. For example, if the level-1v section # override is set to 1, and there is a 1 on the line marked "addv", # then the addv operation will be tested. Similarly, a 0 would cause # addv to not be tested. # # ENABLING ONLY SELECT OPERATIONS # If you would like to enable just a few (or even just one) operation # without adjusting any section overrides (or individual operation # switches), change the desired operation switch(es) to 2. This will # cause any operation that is not set to 2 to be disabled, regardless # of section override values. For example, setting the axpyv and gemv # operation switches to 2 will cause the test suite to test ONLY axpyv # and gemv, even if all other sections and operations are set to 1. # NOTE: As long as there is at least on operation switch set to 2, no # other operations will be tested. When you are done testing your # select operations, you should revert the operation switch(es) back # to 1. # # CHANGING PROBLEM SIZE/SHAPES TESTED # The problem sizes tested by an operation are determined by the # dimension specifiers on the line marked "dimensions: ". # If, for example, contains two dimension labels (e.g. # "m n"), then the line should begin with two dimension specifiers. # Dimension specifiers of -1 cause the corresponding dimension to be # bound to the problem size, which is determined by values set in # input.general. Positive values cause the corresponding dimension to # be fixed to that value and held constant. # # Examples of dimension specifiers (where the dimensions are m and n): # # -1 -1 Dimensions m and n grow with problem size (resulting in # square matrices). # -1 150 Dimension m grows with problem size and n is fixed at # 150. # -1 -2 Dimension m grows with problem size and n grows # proportional to half the problem size. # # CHANGING PARAMTER COMBINATIONS TESTED # The parameter combinations tested by an operation are determined by # the parameter specifier characters on the line marked "parameters: # ". If, for example, contains two # parameter labels (e.g. "transa conjx"), then the line should contain # two parameter specifier characters. The '?' specifier character # serves as a wildcard--it causes all possible values of that parameter # to be tested. A character such as 'n' or 't' causes only that value # to be tested. # # Examples of parameter specifiers (where the parameters are transa # and conjx): # # ?? All combinations of the transa and conjx parameters are # tested: nn, nc, tn, tc, cn, cc, hn, hc. # ?n conjx is fixed to "no conjugate" but transa is allowed # to vary: nn, tn, cn, hn. # hc Only the case where transa is "Hermitian-transpose" and # conjx is "conjugate" is tested. # # Here is a full list of the parameter types used by the various BLIS # operations along with their possible character encodings: # # side: l,r left, right # uplo: l,u lower, upper # trans: n,t,c,h no transpose, transpose, conjugate, Hermitian- # transpose (i.e. conjugate-transpose) # conj: n,c no conjugate, conjugate # diag: n,u non-unit diagonal, unit diagonal # # --- Section overrides ---------------------------------------------------- 1 # Utility 1 # Level-1v kernels 1 # Level-1m 1 # Level-1f kernels 1 # Level-2 1 # Level-3 micro-kernels 1 # Level-3 # --- Utility -------------------------------------------------------------- 1 # randv -1 # dimensions: m 1 # randm -1 -1 # dimensions: m n # --- Level-1v ------------------------------------------------------------- 1 # addv -1 # dimensions: m ? # parameters: conjx 1 # amaxv -1 # dimensions: m 1 # axpbyv -1 # dimensions: m ? # parameters: conjx 1 # axpyv -1 # dimensions: m ? # parameters: conjx 1 # copyv -1 # dimensions: m ? # parameters: conjx 1 # dotv -1 # dimensions: m ?? # parameters: conjx conjy 1 # dotxv -1 # dimensions: m ?? # parameters: conjx conjy 1 # normfv -1 # dimensions: m 1 # scalv -1 # dimensions: m ? # parameters: conjbeta 1 # scal2v -1 # dimensions: m ? # parameters: conjx 1 # setv -1 # dimensions: m 1 # subv -1 # dimensions: m ? # parameters: conjx 1 # xpbyv -1 # dimensions: m ? # parameters: conjx # --- Level-1m ------------------------------------------------------------- 1 # addm -1 -2 # dimensions: m n ? # parameters: transa 1 # axpym -1 -1 # dimensions: m n ? # parameters: transa 1 # copym -1 -2 # dimensions: m n ? # parameters: transa 1 # normfm -1 -2 # dimensions: m n 1 # scalm -1 -2 # dimensions: m n ? # parameters: conjbeta 1 # scal2m -1 -2 # dimensions: m n ? # parameters: transa 1 # setm -1 -2 # dimensions: m n 1 # subm -1 -2 # dimensions: m n ? # parameters: transa 1 # xpbym -1 -1 # dimensions: m n ? # parameters: transa # --- Level-1f kernels ----------------------------------------------------- 1 # axpy2v -1 # dimensions: m ?? # parameters: conjx conjy 1 # dotaxpyv -1 # dimensions: m ??? # parameters: conjxt conjx conjy 1 # axpyf -1 # dimensions: m ?? # parameters: conja conjx 1 # dotxf -1 # dimensions: m ?? # parameters: conjat conjx 1 # dotxaxpyf -1 # dimensions: m ???? # parameters: conjat conja conjw conjx # --- Level-2 -------------------------------------------------------------- 1 # gemv -1 -2 # dimensions: m n ?? # parameters: transa conjx 1 # ger -1 -2 # dimensions: m n ?? # parameters: conjx conjy 1 # hemv -1 # dimensions: m ??? # parameters: uploa conja conjx 1 # her -1 # dimensions: m ?? # parameters: uploc conjx 1 # her2 -1 # dimensions: m ??? # parameters: uploc conjx conjy 1 # symv -1 # dimensions: m ??? # parameters: uploa conja conjx 1 # syr -1 # dimensions: m ?? # parameters: uploc conjx 1 # syr2 -1 # dimensions: m ??? # parameters: uploc conjx conjy 1 # trmv -1 # dimensions: m ??? # parameters: uploa transa diaga 1 # trsv -1 # dimensions: m ??? # parameters: uploa transa diaga # --- Level-3 micro-kernels ------------------------------------------------ 1 # gemm -1 # dimensions: k 1 # trsm ? # parameters: uploa 1 # gemmtrsm -1 # dimensions: k ? # parameters: uploa # --- Level-3 -------------------------------------------------------------- 2 # gemm -1 -1 -1 # dimensions: m n k nn # parameters: transa transb 1 # gemmt -1 -1 # dimensions: m k ??? # parameters: uploc transa transb 1 # hemm -1 -1 # dimensions: m n ???? # parameters: side uploa conja transb 1 # herk -1 -1 # dimensions: m k ?? # parameters: uploc transa 1 # her2k -1 -1 # dimensions: m k ??? # parameters: uploc transa transb 1 # symm -1 -1 # dimensions: m n ???? # parameters: side uploa conja transb 1 # syrk -1 -1 # dimensions: m k ?? # parameters: uploc transa 1 # syr2k -1 -1 # dimensions: m k ??? # parameters: uploc transa transb 1 # trmm -1 -1 # dimensions: m n ???? # parameters: side uploa transa diaga 1 # trmm3 -1 -1 # dimensions: m n ????n # parameters: side uploa transa diaga transb 1 # trsm -1 -1 # dimensions: m n ???? # parameters: side uploa transa diaga blis-0.9.0/testsuite/input.operations.salt000066400000000000000000000222011422157504600207130ustar00rootroot00000000000000# -------------------------------------------------------------------------- # # input.operations # BLIS test suite # # This file contains input values that control which BLIS operations are # tested as well as how those test runs are parameterized. We will now # describe how each section or line type may be edited. # # ENABLING/DISABLING ENTIRE SECTIONS # The values in the "Section overrides" section allow you to disable # all operations in a given "level". Enabling a level here by itself # does not enable every operation in that level; it simply means that # the individual switches for each operation (in that level) determine # whether or not the tests are executed. Use 1 to enable a section, or # 0 to disable. # # ENABLING/DISABLING INDIVIDUAL OPERATION TESTS # Given that an operation's section override switch is set to 1 # (enabled), whether or not that operation will get tested is # determined by its local switch. For example, if the level-1v section # override is set to 1, and there is a 1 on the line marked "addv", # then the addv operation will be tested. Similarly, a 0 would cause # addv to not be tested. # # ENABLING ONLY SELECT OPERATIONS # If you would like to enable just a few (or even just one) operation # without adjusting any section overrides (or individual operation # switches), change the desired operation switch(es) to 2. This will # cause any operation that is not set to 2 to be disabled, regardless # of section override values. For example, setting the axpyv and gemv # operation switches to 2 will cause the test suite to test ONLY axpyv # and gemv, even if all other sections and operations are set to 1. # NOTE: As long as there is at least on operation switch set to 2, no # other operations will be tested. When you are done testing your # select operations, you should revert the operation switch(es) back # to 1. # # CHANGING PROBLEM SIZE/SHAPES TESTED # The problem sizes tested by an operation are determined by the # dimension specifiers on the line marked "dimensions: ". # If, for example, contains two dimension labels (e.g. # "m n"), then the line should begin with two dimension specifiers. # Dimension specifiers of -1 cause the corresponding dimension to be # bound to the problem size, which is determined by values set in # input.general. Positive values cause the corresponding dimension to # be fixed to that value and held constant. # # Examples of dimension specifiers (where the dimensions are m and n): # # -1 -1 Dimensions m and n grow with problem size (resulting in # square matrices). # -1 150 Dimension m grows with problem size and n is fixed at # 150. # -1 -2 Dimension m grows with problem size and n grows # proportional to half the problem size. # # CHANGING PARAMTER COMBINATIONS TESTED # The parameter combinations tested by an operation are determined by # the parameter specifier characters on the line marked "parameters: # ". If, for example, contains two # parameter labels (e.g. "transa conjx"), then the line should contain # two parameter specifier characters. The '?' specifier character # serves as a wildcard--it causes all possible values of that parameter # to be tested. A character such as 'n' or 't' causes only that value # to be tested. # # Examples of parameter specifiers (where the parameters are transa # and conjx): # # ?? All combinations of the transa and conjx parameters are # tested: nn, nc, tn, tc, cn, cc, hn, hc. # ?n conjx is fixed to "no conjugate" but transa is allowed # to vary: nn, tn, cn, hn. # hc Only the case where transa is "Hermitian-transpose" and # conjx is "conjugate" is tested. # # Here is a full list of the parameter types used by the various BLIS # operations along with their possible character encodings: # # side: l,r left, right # uplo: l,u lower, upper # trans: n,t,c,h no transpose, transpose, conjugate, Hermitian- # transpose (i.e. conjugate-transpose) # conj: n,c no conjugate, conjugate # diag: n,u non-unit diagonal, unit diagonal # # --- Section overrides ---------------------------------------------------- 1 # Utility 1 # Level-1v kernels 1 # Level-1m 1 # Level-1f kernels 1 # Level-2 1 # Level-3 micro-kernels 1 # Level-3 # --- Utility -------------------------------------------------------------- 1 # randv -1 # dimensions: m 1 # randm -1 -1 # dimensions: m n # --- Level-1v ------------------------------------------------------------- 1 # addv -1 # dimensions: m ? # parameters: conjx 1 # amaxv -1 # dimensions: m 1 # axpbyv -1 # dimensions: m ? # parameters: conjx 1 # axpyv -1 # dimensions: m ? # parameters: conjx 1 # copyv -1 # dimensions: m ? # parameters: conjx 1 # dotv -1 # dimensions: m ?? # parameters: conjx conjy 1 # dotxv -1 # dimensions: m ?? # parameters: conjx conjy 1 # normfv -1 # dimensions: m 1 # scalv -1 # dimensions: m ? # parameters: conjbeta 1 # scal2v -1 # dimensions: m ? # parameters: conjx 1 # setv -1 # dimensions: m 1 # subv -1 # dimensions: m ? # parameters: conjx 1 # xpbyv -1 # dimensions: m ? # parameters: conjx # --- Level-1m ------------------------------------------------------------- 1 # addm -1 -2 # dimensions: m n ? # parameters: transa 1 # axpym -1 -1 # dimensions: m n ? # parameters: transa 1 # copym -1 -2 # dimensions: m n ? # parameters: transa 1 # normfm -1 -2 # dimensions: m n 1 # scalm -1 -2 # dimensions: m n ? # parameters: conjbeta 1 # scal2m -1 -2 # dimensions: m n ? # parameters: transa 1 # setm -1 -2 # dimensions: m n 1 # subm -1 -2 # dimensions: m n ? # parameters: transa 1 # xpbym -1 -1 # dimensions: m n ? # parameters: transa # --- Level-1f kernels ----------------------------------------------------- 1 # axpy2v -1 # dimensions: m ?? # parameters: conjx conjy 1 # dotaxpyv -1 # dimensions: m ??? # parameters: conjxt conjx conjy 1 # axpyf -1 # dimensions: m ?? # parameters: conja conjx 1 # dotxf -1 # dimensions: m ?? # parameters: conjat conjx 1 # dotxaxpyf -1 # dimensions: m ???? # parameters: conjat conja conjw conjx # --- Level-2 -------------------------------------------------------------- 1 # gemv -1 -2 # dimensions: m n ?? # parameters: transa conjx 1 # ger -1 -2 # dimensions: m n ?? # parameters: conjx conjy 1 # hemv -1 # dimensions: m ??? # parameters: uploa conja conjx 1 # her -1 # dimensions: m ?? # parameters: uploc conjx 1 # her2 -1 # dimensions: m ??? # parameters: uploc conjx conjy 1 # symv -1 # dimensions: m ??? # parameters: uploa conja conjx 1 # syr -1 # dimensions: m ?? # parameters: uploc conjx 1 # syr2 -1 # dimensions: m ??? # parameters: uploc conjx conjy 1 # trmv -1 # dimensions: m ??? # parameters: uploa transa diaga 1 # trsv -1 # dimensions: m ??? # parameters: uploa transa diaga # --- Level-3 micro-kernels ------------------------------------------------ 1 # gemm -1 # dimensions: k 1 # trsm ? # parameters: uploa 1 # gemmtrsm -1 # dimensions: k ? # parameters: uploa # --- Level-3 -------------------------------------------------------------- 1 # gemm -1 -1 -1 # dimensions: m n k nn # parameters: transa transb 1 # gemmt -1 -1 # dimensions: m k ?nn # parameters: uploc transa transb 1 # hemm -1 -1 # dimensions: m n ??nn # parameters: side uploa conja transb 1 # herk -1 -1 # dimensions: m k ?n # parameters: uploc transa 1 # her2k -1 -1 # dimensions: m k ?nn # parameters: uploc transa transb 1 # symm -1 -1 # dimensions: m n ??nn # parameters: side uploa conja transb 1 # syrk -1 -1 # dimensions: m k ?n # parameters: uploc transa 1 # syr2k -1 -1 # dimensions: m k ?nn # parameters: uploc transa transb 1 # trmm -1 -1 # dimensions: m n ??n? # parameters: side uploa transa diaga 0 # trmm3 -1 -1 # dimensions: m n ??n?n # parameters: side uploa transa diaga transb 1 # trsm -1 -1 # dimensions: m n ??n? # parameters: side uploa transa diaga blis-0.9.0/testsuite/obj/000077500000000000000000000000001422157504600152625ustar00rootroot00000000000000blis-0.9.0/testsuite/obj/.gitkeep000066400000000000000000000000001422157504600167010ustar00rootroot00000000000000blis-0.9.0/testsuite/old/000077500000000000000000000000001422157504600152665ustar00rootroot00000000000000blis-0.9.0/testsuite/old/jobscripts/000077500000000000000000000000001422157504600174505ustar00rootroot00000000000000blis-0.9.0/testsuite/old/jobscripts/cfig.out000066400000000000000000000136321422157504600211160ustar00rootroot00000000000000configure: detected Linux kernel version 4.14.0-115.6.1.el7a.ppc64le. configure: python interpeter search list is: python python3 python2. configure: using 'python' python interpreter. configure: found python version 2.7.5 (maj: 2, min: 7, rev: 5). configure: python 2.7.5 appears to be supported. configure: C compiler search list is: gcc clang cc. configure: using 'gcc' C compiler. configure: C++ compiler search list is: g++ clang++ c++. configure: using 'g++' C++ compiler (for sandbox only). configure: found gcc version 8.2.0 (maj: 8, min: 2, rev: 0). configure: checking for blacklisted configurations due to gcc 8.2.0. configure: found assembler ('as') version 2.27 (maj: 2, min: 27, rev: ). configure: checking for blacklisted configurations due to as 2.27. configure: warning: assembler ('as' 2.27) does not support 'bulldozer'; adding to blacklist. configure: warning: assembler ('as' 2.27) does not support 'sandybridge'; adding to blacklist. configure: warning: assembler ('as' 2.27) does not support 'haswell'; adding to blacklist. configure: warning: assembler ('as' 2.27) does not support 'piledriver'; adding to blacklist. configure: warning: assembler ('as' 2.27) does not support 'steamroller'; adding to blacklist. configure: warning: assembler ('as' 2.27) does not support 'excavator'; adding to blacklist. configure: warning: assembler ('as' 2.27) does not support 'skx'; adding to blacklist. configure: warning: assembler ('as' 2.27) does not support 'knl'; adding to blacklist. configure: configuration blacklist: configure: bulldozer sandybridge haswell piledriver steamroller excavator skx knl configure: reading configuration registry...done. configure: determining default version string. configure: found '.git' directory; assuming git clone. configure: executing: git describe --tags. configure: git returned an error: 'Unknown option: -C usage: git [--version] [--help] [-c name=value] [--exec-path[=]] [--html-path] [--man-path] [--info-path] [-p|--paginate|--no-pager] [--no-replace-objects] [--bare] [--git-dir=] [--work-tree=] [--namespace=] []'. configure: using string from unmodified version file. configure: starting configuration of BLIS 0.6.0. configure: configuring with official version string. configure: found shared library .so version '2.0.0'. configure: .so major version: 2 configure: .so minor.build version: 0.0 configure: manual configuration requested; configuring with 'power9'. configure: checking configuration against contents of 'config_registry'. configure: configuration 'power9' is registered. configure: 'power9' is defined as having the following sub-configurations: configure: power9 configure: which collectively require the following kernels: configure: power9 configure: checking sub-configurations: configure: 'power9' is registered...and exists. configure: checking sub-configurations' requisite kernels: configure: 'power9' kernels...exist. configure: no install prefix option given; defaulting to '/usr/local'. configure: no install exec_prefix option given; defaulting to PREFIX. configure: no install libdir option given; defaulting to EXECPREFIX/lib. configure: no install includedir option given; defaulting to PREFIX/include. configure: no install sharedir option given; defaulting to PREFIX/share. configure: final installation directories: configure: prefix: /usr/local configure: exec_prefix: ${prefix} configure: libdir: ${exec_prefix}/lib configure: includedir: ${prefix}/include configure: sharedir: ${prefix}/share configure: NOTE: the variables above can be overridden when running make. configure: no preset CFLAGS detected. configure: no preset LDFLAGS detected. configure: debug symbols disabled. configure: disabling verbose make output. (enable with 'make V=1'.) configure: disabling ARG_MAX hack. configure: building BLIS as both static and shared libraries. configure: exporting only public symbols within shared library. configure: threading is disabled. configure: requesting slab threading in jr and ir loops. configure: internal memory pools for packing blocks are enabled. configure: internal memory pools for small blocks are enabled. configure: memory tracing output is disabled. configure: libmemkind not found; disabling. configure: compiler appears to not support #pragma omp simd. configure: the BLAS compatibility layer is enabled. configure: the CBLAS compatibility layer is disabled. configure: mixed datatype support is enabled. configure: mixed datatype optimizations requiring extra memory are enabled. configure: small matrix handling is enabled. configure: the BLIS API integer size is automatically determined. configure: the BLAS/CBLAS API integer size is 32-bit. configure: configuring for conventional gemm implementation. configure: creating ./config.mk from ./build/config.mk.in configure: creating ./bli_config.h from ./build/bli_config.h.in configure: creating ./obj/power9 configure: creating ./obj/power9/config/power9 configure: creating ./obj/power9/kernels/power9 configure: creating ./obj/power9/ref_kernels/power9 configure: creating ./obj/power9/frame configure: creating ./obj/power9/blastest configure: creating ./obj/power9/testsuite configure: creating ./lib/power9 configure: creating ./include/power9 configure: mirroring ./config/power9 to ./obj/power9/config/power9 configure: mirroring ./kernels/power9 to ./obj/power9/kernels/power9 configure: mirroring ./ref_kernels to ./obj/power9/ref_kernels configure: mirroring ./ref_kernels to ./obj/power9/ref_kernels/power9 configure: mirroring ./frame to ./obj/power9/frame configure: creating makefile fragments in ./obj/power9/config/power9 configure: creating makefile fragments in ./obj/power9/kernels/power9 configure: creating makefile fragments in ./obj/power9/ref_kernels configure: creating makefile fragments in ./obj/power9/frame configure: configured to build within top-level directory of source distribution. CONFIGURE DONE blis-0.9.0/testsuite/old/jobscripts/cfig.sh000077500000000000000000000001001422157504600207060ustar00rootroot00000000000000#!/bin/bash cd ~/blis ./configure power9 echo "CONFIGURE DONE" blis-0.9.0/testsuite/old/jobscripts/jb-cfig.sh000066400000000000000000000007221422157504600213060ustar00rootroot00000000000000#!/bin/bash # execute in the general partition #SBATCH --partition=general # execute with 40 processes/tasks #SBATCH --ntasks=1 # maximum time is 30 minutes #SBATCH --time=00:30:00 # job name is my_job #SBATCH --job-name=blis # send email for status updates #SBATCH --mail-type=ALL,TIME_LIMIT #SBATCH --mail-user=ntukanov # change default output file name #SBATCH --output=cfig.out # load environment module load gcc/8.2 # application execution srun cfig.sh blis-0.9.0/testsuite/old/jobscripts/jb-mk.sh000066400000000000000000000007161422157504600210100ustar00rootroot00000000000000#!/bin/bash # execute in the general partition #SBATCH --partition=general # execute with 40 processes/tasks #SBATCH --ntasks=1 # maximum time is 30 minutes #SBATCH --time=00:30:00 # job name is my_job #SBATCH --job-name=blis # send email for status updates #SBATCH --mail-type=ALL,TIME_LIMIT #SBATCH --mail-user=ntukanov # change default output file name #SBATCH --output=mk.out # load environment module load gcc/8.2 # application execution srun mk.sh blis-0.9.0/testsuite/old/jobscripts/jb-runtest.sh000066400000000000000000000007301422157504600221010ustar00rootroot00000000000000#!/bin/bash # execute in the general partition #SBATCH --partition=general # execute with 40 processes/tasks #SBATCH --ntasks=1 # maximum time is 30 minutes #SBATCH --time=00:30:00 # job name is my_job #SBATCH --job-name=blis # send email for status updates #SBATCH --mail-type=ALL,TIME_LIMIT #SBATCH --mail-user=ntukanov # change default output file name #SBATCH --output=runtest.out # load environment module load gcc/8.2 # application execution srun runtest.sh blis-0.9.0/testsuite/old/jobscripts/mk.out000066400000000000000000000007071422157504600206140ustar00rootroot00000000000000Removing flattened header files from include/power9 Removing object files from ./obj/power9 srun: Job step aborted: Waiting up to 32 seconds for job step to finish. srun: got SIGCONT slurmstepd: error: *** JOB 1155 ON lookout00 CANCELLED AT 2019-06-10T17:29:07 *** srun: forcing job termination slurmstepd: error: *** STEP 1155.0 ON lookout00 CANCELLED AT 2019-06-10T17:29:07 *** make: *** [cleanlib] Terminated srun: error: lookout00: task 0: Terminated blis-0.9.0/testsuite/old/jobscripts/mk.sh000077500000000000000000000000711422157504600204140ustar00rootroot00000000000000#!/bin/bash cd ~/blis make clean make echo "MAKE DONE" blis-0.9.0/testsuite/old/jobscripts/runtest.sh000077500000000000000000000002021422157504600215050ustar00rootroot00000000000000#!/bin/bash cd ~/blis/testsuite rm -rf test_libblis.out make clean make -j ./test_libblis.x > test_libblis.out echo "TEST DONE" blis-0.9.0/testsuite/src/000077500000000000000000000000001422157504600152775ustar00rootroot00000000000000blis-0.9.0/testsuite/src/test_addm.c000066400000000000000000000203021422157504600174040ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "test_libblis.h" // Static variables. static char* op_str = "addm"; static char* o_types = "mm"; // x y static char* p_types = "h"; // transx static thresh_t thresh[BLIS_NUM_FP_TYPES] = { { 1e-04, 1e-05 }, // warn, pass for s { 1e-04, 1e-05 }, // warn, pass for c { 1e-13, 1e-14 }, // warn, pass for d { 1e-13, 1e-14 } }; // warn, pass for z // Local prototypes. void libblis_test_addm_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); void libblis_test_addm_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ); void libblis_test_addm_impl ( iface_t iface, obj_t* x, obj_t* y ); void libblis_test_addm_check ( test_params_t* params, obj_t* alpha, obj_t* beta, obj_t* x, obj_t* y, double* resid ); void libblis_test_addm_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { libblis_test_setm( tdata, params, &(op->ops->setm) ); libblis_test_normfm( tdata, params, &(op->ops->normfm) ); } void libblis_test_addm ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { // Return early if this test has already been done. if ( libblis_test_op_is_done( op ) ) return; // Return early if operation is disabled. if ( libblis_test_op_is_disabled( op ) || libblis_test_l1m_is_disabled( op ) ) return; // Call dependencies first. if ( TRUE ) libblis_test_addm_deps( tdata, params, op ); // Execute the test driver for each implementation requested. //if ( op->front_seq == ENABLE ) { libblis_test_op_driver( tdata, params, op, BLIS_TEST_SEQ_FRONT_END, op_str, p_types, o_types, thresh, libblis_test_addm_experiment ); } } void libblis_test_addm_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ) { double time_min = DBL_MAX; double time; num_t datatype; dim_t m, n; trans_t transx; obj_t alpha, beta; obj_t x, y; // Use the datatype of the first char in the datatype combination string. bli_param_map_char_to_blis_dt( dc_str[0], &datatype ); // Map the dimension specifier to actual dimensions. m = libblis_test_get_dim_from_prob_size( op->dim_spec[0], p_cur ); n = libblis_test_get_dim_from_prob_size( op->dim_spec[1], p_cur ); // Map parameter characters to BLIS constants. bli_param_map_char_to_blis_trans( pc_str[0], &transx ); // Create test scalars. bli_obj_scalar_init_detached( datatype, &alpha ); bli_obj_scalar_init_detached( datatype, &beta ); // Create test operands (vectors and/or matrices). libblis_test_mobj_create( params, datatype, transx, sc_str[0], m, n, &x ); libblis_test_mobj_create( params, datatype, BLIS_NO_TRANSPOSE, sc_str[1], m, n, &y ); // Initialize alpha and beta. bli_setsc( -1.0, -1.0, &alpha ); bli_setsc( 3.0, 3.0, &beta ); // Randomize x. bli_setm( &alpha, &x ); bli_setm( &beta, &y ); // Apply the parameters. bli_obj_set_conjtrans( transx, &x ); // Disable repeats since bli_copym() is not yet tested. //for ( i = 0; i < n_repeats; ++i ) { time = bli_clock(); libblis_test_addm_impl( iface, &x, &y ); time_min = bli_clock_min_diff( time_min, time ); } // Estimate the performance of the best experiment repeat. *perf = ( 1.0 * m * n ) / time_min / FLOPS_PER_UNIT_PERF; if ( bli_obj_is_complex( &x ) ) *perf *= 2.0; // Perform checks. libblis_test_addm_check( params, &alpha, &beta, &x, &y, resid ); // Zero out performance and residual if output matrix is empty. libblis_test_check_empty_problem( &y, perf, resid ); // Free the test objects. bli_obj_free( &x ); bli_obj_free( &y ); } void libblis_test_addm_impl ( iface_t iface, obj_t* x, obj_t* y ) { switch ( iface ) { case BLIS_TEST_SEQ_FRONT_END: bli_addm( x, y ); break; default: libblis_test_printf_error( "Invalid interface type.\n" ); } } void libblis_test_addm_check ( test_params_t* params, obj_t* alpha, obj_t* beta, obj_t* x, obj_t* y, double* resid ) { num_t dt = bli_obj_dt( y ); num_t dt_real = bli_obj_dt_proj_to_real( y ); dim_t m = bli_obj_length( y ); dim_t n = bli_obj_width( y ); conj_t conjx = bli_obj_conj_status( x ); obj_t aplusb; obj_t alpha_conj; obj_t norm_r, m_r, n_r, temp_r; double junk; // // Pre-conditions: // - x is set to alpha. // - y_orig is set to beta. // Note: // - alpha and beta should have non-zero imaginary components in the // complex cases in order to more fully exercise the implementation. // // Under these conditions, we assume that the implementation for // // y := y_orig + conjx(x) // // is functioning correctly if // // normfm(y) - sqrt( absqsc( beta + conjx(alpha) ) * m * n ) // // is negligible. // bli_obj_scalar_init_detached( dt, &aplusb ); bli_obj_scalar_init_detached( dt_real, &temp_r ); bli_obj_scalar_init_detached( dt_real, &norm_r ); bli_obj_scalar_init_detached( dt_real, &m_r ); bli_obj_scalar_init_detached( dt_real, &n_r ); bli_obj_scalar_init_detached_copy_of( dt, conjx, alpha, &alpha_conj ); bli_normfm( y, &norm_r ); bli_copysc( beta, &aplusb ); bli_addsc( &alpha_conj, &aplusb ); bli_setsc( ( double )m, 0.0, &m_r ); bli_setsc( ( double )n, 0.0, &n_r ); bli_absqsc( &aplusb, &temp_r ); bli_mulsc( &m_r, &temp_r ); bli_mulsc( &n_r, &temp_r ); bli_sqrtsc( &temp_r, &temp_r ); bli_subsc( &temp_r, &norm_r ); bli_getsc( &norm_r, resid, &junk ); } blis-0.9.0/testsuite/src/test_addm.h000066400000000000000000000034771422157504600174270ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void libblis_test_addm ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); blis-0.9.0/testsuite/src/test_addv.c000066400000000000000000000176321422157504600174310ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "test_libblis.h" // Static variables. static char* op_str = "addv"; static char* o_types = "vv"; // x y static char* p_types = "c"; // conjx static thresh_t thresh[BLIS_NUM_FP_TYPES] = { { 1e-04, 1e-05 }, // warn, pass for s { 1e-04, 1e-05 }, // warn, pass for c { 1e-13, 1e-14 }, // warn, pass for d { 1e-13, 1e-14 } }; // warn, pass for z // Local prototypes. void libblis_test_addv_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); void libblis_test_addv_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ); void libblis_test_addv_impl ( iface_t iface, obj_t* x, obj_t* y ); void libblis_test_addv_check ( test_params_t* params, obj_t* alpha, obj_t* beta, obj_t* x, obj_t* y, double* resid ); void libblis_test_addv_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { libblis_test_setv( tdata, params, &(op->ops->setv) ); libblis_test_normfv( tdata, params, &(op->ops->normfv) ); } void libblis_test_addv ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { // Return early if this test has already been done. if ( libblis_test_op_is_done( op ) ) return; // Return early if operation is disabled. if ( libblis_test_op_is_disabled( op ) || libblis_test_l1v_is_disabled( op ) ) return; // Call dependencies first. if ( TRUE ) libblis_test_addv_deps( tdata, params, op ); // Execute the test driver for each implementation requested. //if ( op->front_seq == ENABLE ) { libblis_test_op_driver( tdata, params, op, BLIS_TEST_SEQ_FRONT_END, op_str, p_types, o_types, thresh, libblis_test_addv_experiment ); } } void libblis_test_addv_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ) { double time_min = DBL_MAX; double time; num_t datatype; dim_t m; conj_t conjx; obj_t alpha, beta; obj_t x, y; // Use the datatype of the first char in the datatype combination string. bli_param_map_char_to_blis_dt( dc_str[0], &datatype ); // Map the dimension specifier to an actual dimension. m = libblis_test_get_dim_from_prob_size( op->dim_spec[0], p_cur ); // Map parameter characters to BLIS constants. bli_param_map_char_to_blis_conj( pc_str[0], &conjx ); // Create test scalars. bli_obj_scalar_init_detached( datatype, &alpha ); bli_obj_scalar_init_detached( datatype, &beta ); // Create test operands (vectors and/or matrices). libblis_test_vobj_create( params, datatype, sc_str[0], m, &x ); libblis_test_vobj_create( params, datatype, sc_str[1], m, &y ); // Initialize alpha and beta. bli_setsc( -1.0, -1.0, &alpha ); bli_setsc( 3.0, 3.0, &beta ); // Set x and y to alpha and beta, respectively. bli_setv( &alpha, &x ); bli_setv( &beta, &y ); // Apply the parameters. bli_obj_set_conj( conjx, &x ); // Disable repeats since bli_copyv() is not yet tested. //for ( i = 0; i < n_repeats; ++i ) { time = bli_clock(); libblis_test_addv_impl( iface, &x, &y ); time_min = bli_clock_min_diff( time_min, time ); } // Estimate the performance of the best experiment repeat. *perf = ( 1.0 * m ) / time_min / FLOPS_PER_UNIT_PERF; if ( bli_obj_is_complex( &x ) ) *perf *= 2.0; // Perform checks. libblis_test_addv_check( params, &alpha, &beta, &x, &y, resid ); // Zero out performance and residual if output vector is empty. libblis_test_check_empty_problem( &y, perf, resid ); // Free the test objects. bli_obj_free( &x ); bli_obj_free( &y ); } void libblis_test_addv_impl ( iface_t iface, obj_t* x, obj_t* y ) { switch ( iface ) { case BLIS_TEST_SEQ_FRONT_END: bli_addv( x, y ); break; default: libblis_test_printf_error( "Invalid interface type.\n" ); } } void libblis_test_addv_check ( test_params_t* params, obj_t* alpha, obj_t* beta, obj_t* x, obj_t* y, double* resid ) { num_t dt = bli_obj_dt( x ); num_t dt_real = bli_obj_dt_proj_to_real( x ); dim_t m = bli_obj_vector_dim( x ); conj_t conjx = bli_obj_conj_status( x ); obj_t aplusb; obj_t alpha_conj; obj_t norm_r, m_r, temp_r; double junk; // // Pre-conditions: // - x is set to alpha. // - y_orig is set to beta. // Note: // - alpha and beta should have non-zero imaginary components in the // complex cases in order to more fully exercise the implementation. // // Under these conditions, we assume that the implementation for // // y := y_orig + conjx(x) // // is functioning correctly if // // normfv(y) - sqrt( absqsc( beta + conjx(alpha) ) * m ) // // is negligible. // bli_obj_scalar_init_detached( dt, &aplusb ); bli_obj_scalar_init_detached( dt_real, &temp_r ); bli_obj_scalar_init_detached( dt_real, &norm_r ); bli_obj_scalar_init_detached( dt_real, &m_r ); bli_obj_scalar_init_detached_copy_of( dt, conjx, alpha, &alpha_conj ); bli_normfv( y, &norm_r ); bli_copysc( beta, &aplusb ); bli_addsc( &alpha_conj, &aplusb ); bli_setsc( ( double )m, 0.0, &m_r ); bli_absqsc( &aplusb, &temp_r ); bli_mulsc( &m_r, &temp_r ); bli_sqrtsc( &temp_r, &temp_r ); bli_subsc( &temp_r, &norm_r ); bli_getsc( &norm_r, resid, &junk ); } blis-0.9.0/testsuite/src/test_addv.h000066400000000000000000000034771422157504600174400ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void libblis_test_addv ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); blis-0.9.0/testsuite/src/test_amaxv.c000066400000000000000000000274051422157504600176260ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "test_libblis.h" // Static variables. static char* op_str = "amaxv"; static char* o_types = "v"; // x static char* p_types = ""; // (no parameters) static thresh_t thresh[BLIS_NUM_FP_TYPES] = { { 1e-04, 1e-05 }, // warn, pass for s { 1e-04, 1e-05 }, // warn, pass for c { 1e-13, 1e-14 }, // warn, pass for d { 1e-13, 1e-14 } }; // warn, pass for z // Local prototypes. void libblis_test_amaxv_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); void libblis_test_amaxv_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ); void libblis_test_amaxv_impl ( iface_t iface, obj_t* x, obj_t* index ); void libblis_test_amaxv_check ( test_params_t* params, obj_t* x, obj_t* index, double* resid ); void bli_amaxv_test ( obj_t* x, obj_t* index ); void libblis_test_amaxv_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { libblis_test_randv( tdata, params, &(op->ops->randv) ); } void libblis_test_amaxv ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { // Return early if this test has already been done. if ( libblis_test_op_is_done( op ) ) return; // Return early if operation is disabled. if ( libblis_test_op_is_disabled( op ) || libblis_test_l1v_is_disabled( op ) ) return; // Call dependencies first. if ( TRUE ) libblis_test_amaxv_deps( tdata, params, op ); // Execute the test driver for each implementation requested. //if ( op->front_seq == ENABLE ) { libblis_test_op_driver( tdata, params, op, BLIS_TEST_SEQ_FRONT_END, op_str, p_types, o_types, thresh, libblis_test_amaxv_experiment ); } } void libblis_test_amaxv_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ) { unsigned int n_repeats = params->n_repeats; unsigned int i; double time_min = DBL_MAX; double time; num_t datatype; dim_t m; obj_t x; obj_t index; // Use the datatype of the first char in the datatype combination string. bli_param_map_char_to_blis_dt( dc_str[0], &datatype ); // Map the dimension specifier to an actual dimension. m = libblis_test_get_dim_from_prob_size( op->dim_spec[0], p_cur ); // Map parameter characters to BLIS constants. // Create test scalars. bli_obj_scalar_init_detached( BLIS_INT, &index ); // Create test operands (vectors and/or matrices). libblis_test_vobj_create( params, datatype, sc_str[0], m, &x ); // Randomize x. libblis_test_vobj_randomize( params, FALSE, &x ); // Repeat the experiment n_repeats times and record results. for ( i = 0; i < n_repeats; ++i ) { time = bli_clock(); libblis_test_amaxv_impl( iface, &x, &index ); time_min = bli_clock_min_diff( time_min, time ); } // Estimate the performance of the best experiment repeat. *perf = ( 1.0 * m ) / time_min / FLOPS_PER_UNIT_PERF; if ( bli_obj_is_complex( &x ) ) *perf *= 2.0; // Perform checks. libblis_test_amaxv_check( params, &x, &index, resid ); // Zero out performance and residual if input vector is empty. libblis_test_check_empty_problem( &x, perf, resid ); // Free the test objects. bli_obj_free( &x ); } void libblis_test_amaxv_impl ( iface_t iface, obj_t* x, obj_t* index ) { switch ( iface ) { case BLIS_TEST_SEQ_FRONT_END: bli_amaxv( x, index ); break; default: libblis_test_printf_error( "Invalid interface type.\n" ); } } void libblis_test_amaxv_check ( test_params_t* params, obj_t* x, obj_t* index, double* resid ) { obj_t index_test; obj_t chi_i; obj_t chi_i_test; dim_t i; dim_t i_test; double i_d, junk; double i_d_test; // // Pre-conditions: // - x is randomized. // // Under these conditions, we assume that the implementation for // // index := amaxv( x ) // // is functioning correctly if // // x[ index ] = max( x ) // // where max() is implemented via the bli_?amaxv_test() function. // // The following two calls have already been made by the caller. That // is, the index object has already been created and the library's // amaxv implementation has already been tested. //bli_obj_scalar_init_detached( BLIS_INT, &index ); //bli_amaxv( x, &index ); bli_getsc( index, &i_d, &junk ); i = i_d; // If x is length 0, then we can't access any elements, and so we // return early with a good residual. if ( bli_obj_vector_dim( x ) == 0 ) { *resid = 0.0; return; } bli_acquire_vi( i, x, &chi_i ); bli_obj_scalar_init_detached( BLIS_INT, &index_test ); bli_amaxv_test( x, &index_test ); bli_getsc( &index_test, &i_d_test, &junk ); i_test = i_d_test; bli_acquire_vi( i_test, x, &chi_i_test ); // Verify that the values referenced by index and index_test are equal. if ( bli_obj_equals( &chi_i, &chi_i_test ) ) *resid = 0.0; else *resid = 1.0; } // ----------------------------------------------------------------------------- // // Prototype BLAS-like interfaces with typed operands for a local amaxv test // operation // #undef GENTPROT #define GENTPROT( ctype, ch, opname ) \ \ void PASTEMAC(ch,opname) \ ( \ dim_t n, \ ctype* restrict x, inc_t incx, \ dim_t* restrict index \ ); \ INSERT_GENTPROT_BASIC0( amaxv_test ) // // Prototype function pointer query interface. // #undef GENPROT #define GENPROT( tname, opname ) \ \ PASTECH(tname,_vft) \ PASTEMAC(opname,_qfp)( num_t dt ); GENPROT( amaxv, amaxv_test ) // // Define function pointer query interfaces. // #undef GENFRONT #define GENFRONT( tname, opname ) \ \ GENARRAY_FPA( PASTECH(tname,_vft), \ opname ); \ \ PASTECH(tname,_vft) \ PASTEMAC(opname,_qfp)( num_t dt ) \ { \ return PASTECH(opname,_fpa)[ dt ]; \ } GENFRONT( amaxv, amaxv_test ) // // Define object-based interface for a local amaxv test operation. // #undef GENFRONT #define GENFRONT( tname, opname ) \ \ void PASTEMAC0(opname) \ ( \ obj_t* x, \ obj_t* index \ ) \ { \ num_t dt = bli_obj_dt( x ); \ \ dim_t n = bli_obj_vector_dim( x ); \ void* buf_x = bli_obj_buffer_at_off( x ); \ inc_t incx = bli_obj_vector_inc( x ); \ \ void* buf_index = bli_obj_buffer_at_off( index ); \ \ /* FGVZ: Disabling this code since bli_amaxv_check() is supposed to be a non-public API function, and therefore unavailable unless all symbols are scheduled to be exported at configure-time (which is not currently the default behavior). if ( bli_error_checking_is_enabled() ) \ bli_amaxv_check( x, index ); \ */ \ \ /* Query a type-specific function pointer, except one that uses void* for function arguments instead of typed pointers. */ \ PASTECH(tname,_vft) f = \ PASTEMAC(opname,_qfp)( dt ); \ \ f \ ( \ n, \ buf_x, incx, \ buf_index \ ); \ } GENFRONT( amaxv, amaxv_test ) // // Define BLAS-like interfaces with typed operands for a local amaxv test // operation. // NOTE: This is based on a simplified version of the bli_?amaxv_ref() // reference kernel. // #undef GENTFUNCR #define GENTFUNCR( ctype, ctype_r, ch, chr, varname ) \ \ void PASTEMAC(ch,varname) \ ( \ dim_t n, \ ctype* x, inc_t incx, \ dim_t* index \ ) \ { \ ctype_r* minus_one = PASTEMAC(chr,m1); \ dim_t* zero_i = PASTEMAC(i,0); \ \ ctype_r chi1_r; \ ctype_r chi1_i; \ ctype_r abs_chi1; \ ctype_r abs_chi1_max; \ dim_t index_l; \ dim_t i; \ \ /* If the vector length is zero, return early. This directly emulates the behavior of netlib BLAS's i?amax() routines. */ \ if ( bli_zero_dim1( n ) ) \ { \ PASTEMAC(i,copys)( *zero_i, *index ); \ return; \ } \ \ /* Initialize the index of the maximum absolute value to zero. */ \ PASTEMAC(i,copys)( *zero_i, index_l ); \ \ /* Initialize the maximum absolute value search candidate with -1, which is guaranteed to be less than all values we will compute. */ \ PASTEMAC(chr,copys)( *minus_one, abs_chi1_max ); \ \ { \ for ( i = 0; i < n; ++i ) \ { \ ctype* chi1 = x + (i )*incx; \ \ /* Get the real and imaginary components of chi1. */ \ PASTEMAC2(ch,chr,gets)( *chi1, chi1_r, chi1_i ); \ \ /* Replace chi1_r and chi1_i with their absolute values. */ \ PASTEMAC(chr,abval2s)( chi1_r, chi1_r ); \ PASTEMAC(chr,abval2s)( chi1_i, chi1_i ); \ \ /* Add the real and imaginary absolute values together. */ \ PASTEMAC(chr,set0s)( abs_chi1 ); \ PASTEMAC(chr,adds)( chi1_r, abs_chi1 ); \ PASTEMAC(chr,adds)( chi1_i, abs_chi1 ); \ \ /* If the absolute value of the current element exceeds that of the previous largest, save it and its index. If NaN is encountered, then treat it the same as if it were a valid value that was smaller than any previously seen. This behavior mimics that of LAPACK's ?lange(). */ \ if ( abs_chi1_max < abs_chi1 || bli_isnan( abs_chi1 ) ) \ { \ abs_chi1_max = abs_chi1; \ index_l = i; \ } \ } \ } \ \ /* Store the final index to the output variable. */ \ PASTEMAC(i,copys)( index_l, *index ); \ } INSERT_GENTFUNCR_BASIC0( amaxv_test ) blis-0.9.0/testsuite/src/test_amaxv.h000066400000000000000000000035001422157504600176210ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void libblis_test_amaxv ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); blis-0.9.0/testsuite/src/test_axpbyv.c000066400000000000000000000213251422157504600200160ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "test_libblis.h" // Static variables. static char* op_str = "axpbyv"; static char* o_types = "vv"; // x y static char* p_types = "c"; // conjx static thresh_t thresh[BLIS_NUM_FP_TYPES] = { { 1e-04, 1e-05 }, // warn, pass for s { 1e-04, 1e-05 }, // warn, pass for c { 1e-13, 1e-14 }, // warn, pass for d { 1e-13, 1e-14 } }; // warn, pass for z // Local prototypes. void libblis_test_axpbyv_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); void libblis_test_axpbyv_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ); void libblis_test_axpbyv_impl ( iface_t iface, obj_t* alpha, obj_t* x, obj_t* beta, obj_t* y ); void libblis_test_axpbyv_check ( test_params_t* params, obj_t* alpha, obj_t* x, obj_t* beta, obj_t* y, obj_t* y_orig, double* resid ); void libblis_test_axpbyv_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { libblis_test_randv( tdata, params, &(op->ops->randv) ); libblis_test_normfv( tdata, params, &(op->ops->normfv) ); libblis_test_addv( tdata, params, &(op->ops->addv) ); libblis_test_axpyv( tdata, params, &(op->ops->axpyv) ); libblis_test_subv( tdata, params, &(op->ops->subv) ); libblis_test_copyv( tdata, params, &(op->ops->copyv) ); libblis_test_scalv( tdata, params, &(op->ops->scalv) ); libblis_test_scal2v( tdata, params, &(op->ops->scal2v) ); libblis_test_xpbyv( tdata, params, &(op->ops->xpbyv) ); } void libblis_test_axpbyv ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { // Return early if this test has already been done. if ( libblis_test_op_is_done( op ) ) return; // Return early if operation is disabled. if ( libblis_test_op_is_disabled( op ) || libblis_test_l1v_is_disabled( op ) ) return; // Call dependencies first. if ( TRUE ) libblis_test_axpbyv_deps( tdata, params, op ); // Execute the test driver for each implementation requested. //if ( op->front_seq == ENABLE ) { libblis_test_op_driver( tdata, params, op, BLIS_TEST_SEQ_FRONT_END, op_str, p_types, o_types, thresh, libblis_test_axpbyv_experiment ); } } void libblis_test_axpbyv_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ) { unsigned int n_repeats = params->n_repeats; unsigned int i; double time_min = DBL_MAX; double time; num_t datatype; dim_t m; conj_t conjx; obj_t alpha, beta, x, y; obj_t y_save; // Use the datatype of the first char in the datatype combination string. bli_param_map_char_to_blis_dt( dc_str[0], &datatype ); // Map the dimension specifier to an actual dimension. m = libblis_test_get_dim_from_prob_size( op->dim_spec[0], p_cur ); // Map parameter characters to BLIS constants. bli_param_map_char_to_blis_conj( pc_str[0], &conjx ); // Create test scalars. bli_obj_scalar_init_detached( datatype, &alpha ); bli_obj_scalar_init_detached( datatype, &beta ); // Create test operands (vectors and/or matrices). libblis_test_vobj_create( params, datatype, sc_str[0], m, &x ); libblis_test_vobj_create( params, datatype, sc_str[1], m, &y ); libblis_test_vobj_create( params, datatype, sc_str[1], m, &y_save ); // Set alpha. //bli_setsc( sqrt(2.0)/2.0, sqrt(2.0)/2.0, &alpha ); //bli_copysc( &BLIS_TWO, &alpha ); if ( bli_obj_is_real( &y ) ) bli_setsc( -2.0, 0.0, &alpha ); else bli_setsc( 0.0, -2.0, &alpha ); bli_setsc( -1.0, 0.0, &beta ); // Randomize x and y, and save y. libblis_test_vobj_randomize( params, FALSE, &x ); libblis_test_vobj_randomize( params, FALSE, &y ); bli_copyv( &y, &y_save ); // Apply the parameters. bli_obj_set_conj( conjx, &x ); // Repeat the experiment n_repeats times and record results. for ( i = 0; i < n_repeats; ++i ) { bli_copyv( &y_save, &y ); time = bli_clock(); libblis_test_axpbyv_impl( iface, &alpha, &x, &beta, &y ); time_min = bli_clock_min_diff( time_min, time ); } // Estimate the performance of the best experiment repeat. *perf = ( 3.0 * m ) / time_min / FLOPS_PER_UNIT_PERF; if ( bli_obj_is_complex( &y ) ) *perf *= 14.0 / 3.0; // Perform checks. libblis_test_axpbyv_check( params, &alpha, &x, &beta, &y, &y_save, resid ); // Zero out performance and residual if output vector is empty. libblis_test_check_empty_problem( &y, perf, resid ); // Free the test objects. bli_obj_free( &x ); bli_obj_free( &y ); bli_obj_free( &y_save ); } void libblis_test_axpbyv_impl ( iface_t iface, obj_t* alpha, obj_t* x, obj_t* beta, obj_t* y ) { switch ( iface ) { case BLIS_TEST_SEQ_FRONT_END: bli_axpbyv( alpha, x, beta, y ); break; default: libblis_test_printf_error( "Invalid interface type.\n" ); } } void libblis_test_axpbyv_check ( test_params_t* params, obj_t* alpha, obj_t* x, obj_t* beta, obj_t* y, obj_t* y_orig, double* resid ) { num_t dt = bli_obj_dt( y ); num_t dt_real = bli_obj_dt_proj_to_real( y ); dim_t m = bli_obj_vector_dim( y ); obj_t x_temp, y_temp; obj_t norm; double junk; // // Pre-conditions: // - x is randomized. // - y_orig is randomized. // Note: // - alpha should have a non-zero imaginary component in the complex // cases in order to more fully exercise the implementation. // // Under these conditions, we assume that the implementation for // // y := beta * y_orig + alpha * conjx(x) // // is functioning correctly if // // normfv( y - ( beta * y_orig + alpha * conjx(x) ) ) // // is negligible. // bli_obj_scalar_init_detached( dt_real, &norm ); bli_obj_create( dt, m, 1, 0, 0, &x_temp ); bli_obj_create( dt, m, 1, 0, 0, &y_temp ); bli_copyv( x, &x_temp ); bli_copyv( y_orig, &y_temp ); bli_scalv( alpha, &x_temp ); bli_scalv( beta, &y_temp ); bli_addv( &x_temp, &y_temp ); bli_subv( &y_temp, y ); bli_normfv( y, &norm ); bli_getsc( &norm, resid, &junk ); bli_obj_free( &x_temp ); bli_obj_free( &y_temp ); } blis-0.9.0/testsuite/src/test_axpbyv.h000066400000000000000000000035011422157504600200170ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void libblis_test_axpbyv ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); blis-0.9.0/testsuite/src/test_axpy2v.c000066400000000000000000000224111422157504600177330ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "test_libblis.h" // Static variables. static char* op_str = "axpy2v"; static char* o_types = "vvv"; // x y z static char* p_types = "cc"; // conjx conjy static thresh_t thresh[BLIS_NUM_FP_TYPES] = { { 1e-04, 1e-05 }, // warn, pass for s { 1e-04, 1e-05 }, // warn, pass for c { 1e-13, 1e-14 }, // warn, pass for d { 1e-13, 1e-14 } }; // warn, pass for z // Local prototypes. void libblis_test_axpy2v_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); void libblis_test_axpy2v_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ); void libblis_test_axpy2v_impl ( iface_t iface, obj_t* alpha1, obj_t* alpha2, obj_t* x, obj_t* y, obj_t* z, cntx_t* cntx ); void libblis_test_axpy2v_check ( test_params_t* params, obj_t* alpha1, obj_t* alpha2, obj_t* x, obj_t* y, obj_t* z, obj_t* z_orig, double* resid ); void libblis_test_axpy2v_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { libblis_test_randv( tdata, params, &(op->ops->randv) ); libblis_test_normfv( tdata, params, &(op->ops->normfv) ); libblis_test_addv( tdata, params, &(op->ops->addv) ); libblis_test_subv( tdata, params, &(op->ops->subv) ); libblis_test_copyv( tdata, params, &(op->ops->copyv) ); libblis_test_scalv( tdata, params, &(op->ops->scalv) ); } void libblis_test_axpy2v ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { // Return early if this test has already been done. if ( libblis_test_op_is_done( op ) ) return; // Return early if operation is disabled. if ( libblis_test_op_is_disabled( op ) || libblis_test_l1f_is_disabled( op ) ) return; // Call dependencies first. if ( TRUE ) libblis_test_axpy2v_deps( tdata, params, op ); // Execute the test driver for each implementation requested. //if ( op->front_seq == ENABLE ) { libblis_test_op_driver( tdata, params, op, BLIS_TEST_SEQ_FRONT_END, op_str, p_types, o_types, thresh, libblis_test_axpy2v_experiment ); } } void libblis_test_axpy2v_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ) { unsigned int n_repeats = params->n_repeats; unsigned int i; double time_min = DBL_MAX; double time; num_t datatype; dim_t m; conj_t conjx, conjy; obj_t alpha1, alpha2, x, y, z; obj_t z_save; cntx_t* cntx; // Query a context. cntx = bli_gks_query_cntx(); // Use the datatype of the first char in the datatype combination string. bli_param_map_char_to_blis_dt( dc_str[0], &datatype ); // Map the dimension specifier to an actual dimension. m = libblis_test_get_dim_from_prob_size( op->dim_spec[0], p_cur ); // Map parameter characters to BLIS constants. bli_param_map_char_to_blis_conj( pc_str[0], &conjx ); bli_param_map_char_to_blis_conj( pc_str[1], &conjy ); // Create test scalars. bli_obj_scalar_init_detached( datatype, &alpha1 ); bli_obj_scalar_init_detached( datatype, &alpha2 ); // Create test operands (vectors and/or matrices). libblis_test_vobj_create( params, datatype, sc_str[0], m, &x ); libblis_test_vobj_create( params, datatype, sc_str[1], m, &y ); libblis_test_vobj_create( params, datatype, sc_str[2], m, &z ); libblis_test_vobj_create( params, datatype, sc_str[2], m, &z_save ); // Set alpha. if ( bli_obj_is_real( &z ) ) { bli_setsc( -1.0, 0.0, &alpha1 ); bli_setsc( -0.9, 0.0, &alpha2 ); } else { bli_setsc( 0.0, -1.0, &alpha1 ); bli_setsc( 0.0, -0.9, &alpha2 ); } // Randomize x and y, and save y. libblis_test_vobj_randomize( params, TRUE, &x ); libblis_test_vobj_randomize( params, TRUE, &y ); libblis_test_vobj_randomize( params, TRUE, &z ); bli_copyv( &z, &z_save ); // Apply the parameters. bli_obj_set_conj( conjx, &x ); bli_obj_set_conj( conjy, &y ); // Repeat the experiment n_repeats times and record results. for ( i = 0; i < n_repeats; ++i ) { bli_copyv( &z_save, &z ); time = bli_clock(); libblis_test_axpy2v_impl( iface, &alpha1, &alpha2, &x, &y, &z, cntx ); time_min = bli_clock_min_diff( time_min, time ); } // Estimate the performance of the best experiment repeat. *perf = ( 2.0 * m + 2.0 * m ) / time_min / FLOPS_PER_UNIT_PERF; if ( bli_obj_is_complex( &z ) ) *perf *= 4.0; // Perform checks. libblis_test_axpy2v_check( params, &alpha1, &alpha2, &x, &y, &z, &z_save, resid ); // Zero out performance and residual if output vector is empty. libblis_test_check_empty_problem( &z, perf, resid ); // Free the test objects. bli_obj_free( &x ); bli_obj_free( &y ); bli_obj_free( &z ); bli_obj_free( &z_save ); } void libblis_test_axpy2v_impl ( iface_t iface, obj_t* alpha1, obj_t* alpha2, obj_t* x, obj_t* y, obj_t* z, cntx_t* cntx ) { switch ( iface ) { case BLIS_TEST_SEQ_FRONT_END: bli_axpy2v_ex( alpha1, alpha2, x, y, z, cntx, NULL ); break; default: libblis_test_printf_error( "Invalid interface type.\n" ); } } void libblis_test_axpy2v_check ( test_params_t* params, obj_t* alpha1, obj_t* alpha2, obj_t* x, obj_t* y, obj_t* z, obj_t* z_orig, double* resid ) { num_t dt = bli_obj_dt( z ); num_t dt_real = bli_obj_dt_proj_to_real( z ); dim_t m = bli_obj_vector_dim( z ); obj_t x_temp, y_temp, z_temp; obj_t norm; double junk; // // Pre-conditions: // - x is randomized. // - y is randomized. // - z_orig is randomized. // Note: // - alpha1, alpha2 should have a non-zero imaginary component in the // complex cases in order to more fully exercise the implementation. // // Under these conditions, we assume that the implementation for // // z := z_orig + alpha1 * conjx(x) + alpha2 * conjy(y) // // is functioning correctly if // // normfv( z - v ) // // is negligible, where v contains z as computed by two calls to axpyv. // bli_obj_scalar_init_detached( dt_real, &norm ); bli_obj_create( dt, m, 1, 0, 0, &x_temp ); bli_obj_create( dt, m, 1, 0, 0, &y_temp ); bli_obj_create( dt, m, 1, 0, 0, &z_temp ); bli_copyv( x, &x_temp ); bli_copyv( y, &y_temp ); bli_copyv( z_orig, &z_temp ); bli_scalv( alpha1, &x_temp ); bli_scalv( alpha2, &y_temp ); bli_addv( &x_temp, &z_temp ); bli_addv( &y_temp, &z_temp ); bli_subv( &z_temp, z ); bli_normfv( z, &norm ); bli_getsc( &norm, resid, &junk ); bli_obj_free( &x_temp ); bli_obj_free( &y_temp ); bli_obj_free( &z_temp ); } blis-0.9.0/testsuite/src/test_axpy2v.h000066400000000000000000000035011422157504600177370ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void libblis_test_axpy2v ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); blis-0.9.0/testsuite/src/test_axpyf.c000066400000000000000000000225001422157504600176300ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "test_libblis.h" // Static variables. static char* op_str = "axpyf"; static char* o_types = "mvv"; // A x y static char* p_types = "cc"; // conja conjx static thresh_t thresh[BLIS_NUM_FP_TYPES] = { { 1e-04, 1e-05 }, // warn, pass for s { 1e-04, 1e-05 }, // warn, pass for c { 1e-13, 1e-14 }, // warn, pass for d { 1e-13, 1e-14 } }; // warn, pass for z // Local prototypes. void libblis_test_axpyf_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); void libblis_test_axpyf_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ); void libblis_test_axpyf_impl ( iface_t iface, obj_t* alpha, obj_t* a, obj_t* x, obj_t* y, cntx_t* cntx ); void libblis_test_axpyf_check ( test_params_t* params, obj_t* alpha, obj_t* a, obj_t* x, obj_t* y, obj_t* y_orig, double* resid ); void libblis_test_axpyf_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { libblis_test_randv( tdata, params, &(op->ops->randv) ); libblis_test_randm( tdata, params, &(op->ops->randm) ); libblis_test_normfv( tdata, params, &(op->ops->normfv) ); libblis_test_subv( tdata, params, &(op->ops->subv) ); libblis_test_copyv( tdata, params, &(op->ops->copyv) ); libblis_test_axpyv( tdata, params, &(op->ops->axpyv) ); } void libblis_test_axpyf ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { // Return early if this test has already been done. if ( libblis_test_op_is_done( op ) ) return; // Return early if operation is disabled. if ( libblis_test_op_is_disabled( op ) || libblis_test_l1f_is_disabled( op ) ) return; // Call dependencies first. if ( TRUE ) libblis_test_axpyf_deps( tdata, params, op ); // Execute the test driver for each implementation requested. //if ( op->front_seq == ENABLE ) { libblis_test_op_driver( tdata, params, op, BLIS_TEST_SEQ_FRONT_END, op_str, p_types, o_types, thresh, libblis_test_axpyf_experiment ); } } void libblis_test_axpyf_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ) { unsigned int n_repeats = params->n_repeats; unsigned int i; double time_min = DBL_MAX; double time; num_t datatype; dim_t m, b_n; conj_t conja, conjx; obj_t alpha, a, x, y; obj_t y_save; cntx_t* cntx; // Query a context. cntx = bli_gks_query_cntx(); // Use the datatype of the first char in the datatype combination string. bli_param_map_char_to_blis_dt( dc_str[0], &datatype ); // Map the dimension specifier to an actual dimension. m = libblis_test_get_dim_from_prob_size( op->dim_spec[0], p_cur ); // Query the operation's fusing factor for the current datatype. b_n = bli_cntx_get_blksz_def_dt( datatype, BLIS_AF, cntx ); // Store the fusing factor so that the driver can retrieve the value // later when printing results. op->dim_aux[0] = b_n; // Map parameter characters to BLIS constants. bli_param_map_char_to_blis_conj( pc_str[0], &conja ); bli_param_map_char_to_blis_conj( pc_str[1], &conjx ); // Create test scalars. bli_obj_scalar_init_detached( datatype, &alpha ); // Create test operands (vectors and/or matrices). libblis_test_mobj_create( params, datatype, BLIS_NO_TRANSPOSE, sc_str[0], m, b_n, &a ); libblis_test_vobj_create( params, datatype, sc_str[1], b_n, &x ); libblis_test_vobj_create( params, datatype, sc_str[2], m, &y ); libblis_test_vobj_create( params, datatype, sc_str[2], m, &y_save ); // Set alpha. if ( bli_obj_is_real( &y ) ) { bli_setsc( -1.0, 0.0, &alpha ); } else { bli_setsc( 0.0, -1.0, &alpha ); } // Randomize A, x, and y, and save y. libblis_test_mobj_randomize( params, FALSE, &a ); libblis_test_vobj_randomize( params, FALSE, &x ); libblis_test_vobj_randomize( params, FALSE, &y ); bli_copyv( &y, &y_save ); // Apply the parameters. bli_obj_set_conj( conja, &a ); bli_obj_set_conj( conjx, &x ); // Repeat the experiment n_repeats times and record results. for ( i = 0; i < n_repeats; ++i ) { bli_copyv( &y_save, &y ); time = bli_clock(); libblis_test_axpyf_impl( iface, &alpha, &a, &x, &y, cntx ); time_min = bli_clock_min_diff( time_min, time ); } // Estimate the performance of the best experiment repeat. *perf = ( 2.0 * m * b_n ) / time_min / FLOPS_PER_UNIT_PERF; if ( bli_obj_is_complex( &y ) ) *perf *= 4.0; // Perform checks. libblis_test_axpyf_check( params, &alpha, &a, &x, &y, &y_save, resid ); // Zero out performance and residual if output vector is empty. libblis_test_check_empty_problem( &y, perf, resid ); // Free the test objects. bli_obj_free( &a ); bli_obj_free( &x ); bli_obj_free( &y ); bli_obj_free( &y_save ); } void libblis_test_axpyf_impl ( iface_t iface, obj_t* alpha, obj_t* a, obj_t* x, obj_t* y, cntx_t* cntx ) { switch ( iface ) { case BLIS_TEST_SEQ_FRONT_END: bli_axpyf_ex( alpha, a, x, y, cntx, NULL ); break; default: libblis_test_printf_error( "Invalid interface type.\n" ); } } void libblis_test_axpyf_check ( test_params_t* params, obj_t* alpha, obj_t* a, obj_t* x, obj_t* y, obj_t* y_orig, double* resid ) { num_t dt = bli_obj_dt( y ); num_t dt_real = bli_obj_dt_proj_to_real( y ); dim_t m = bli_obj_vector_dim( y ); dim_t b_n = bli_obj_width( a ); dim_t i; obj_t a1, chi1, v; obj_t alpha_chi1; obj_t norm; double junk; // // Pre-conditions: // - a is randomized. // - x is randomized. // - y is randomized. // Note: // - alpha should have a non-zero imaginary component in the complex // cases in order to more fully exercise the implementation. // // Under these conditions, we assume that the implementation for // // y := y_orig + alpha * conja(A) * conjx(x) // // is functioning correctly if // // normfv( y - v ) // // is negligible, where v contains y as computed by repeated calls to // axpyv. // bli_obj_scalar_init_detached( dt_real, &norm ); bli_obj_scalar_init_detached( dt, &alpha_chi1 ); bli_obj_create( dt, m, 1, 0, 0, &v ); bli_copyv( y_orig, &v ); for ( i = 0; i < b_n; ++i ) { bli_acquire_mpart_l2r( BLIS_SUBPART1, i, 1, a, &a1 ); bli_acquire_vpart_f2b( BLIS_SUBPART1, i, 1, x, &chi1 ); bli_copysc( &chi1, &alpha_chi1 ); bli_mulsc( alpha, &alpha_chi1 ); bli_axpyv( &alpha_chi1, &a1, &v ); } bli_subv( y, &v ); bli_normfv( &v, &norm ); bli_getsc( &norm, resid, &junk ); bli_obj_free( &v ); } blis-0.9.0/testsuite/src/test_axpyf.h000066400000000000000000000035001422157504600176340ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void libblis_test_axpyf ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); blis-0.9.0/testsuite/src/test_axpym.c000066400000000000000000000207121422157504600176420ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "test_libblis.h" // Static variables. static char* op_str = "axpym"; static char* o_types = "mm"; // x y static char* p_types = "h"; // transx static thresh_t thresh[BLIS_NUM_FP_TYPES] = { { 1e-04, 1e-05 }, // warn, pass for s { 1e-04, 1e-05 }, // warn, pass for c { 1e-13, 1e-14 }, // warn, pass for d { 1e-13, 1e-14 } }; // warn, pass for z // Local prototypes. void libblis_test_axpym_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); void libblis_test_axpym_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ); void libblis_test_axpym_impl ( iface_t iface, obj_t* alpha, obj_t* x, obj_t* y ); void libblis_test_axpym_check ( test_params_t* params, obj_t* alpha, obj_t* x, obj_t* y, obj_t* y_save, double* resid ); void libblis_test_axpym_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { libblis_test_randm( tdata, params, &(op->ops->randm) ); libblis_test_normfm( tdata, params, &(op->ops->normfm) ); libblis_test_addm( tdata, params, &(op->ops->addm) ); libblis_test_subm( tdata, params, &(op->ops->subm) ); libblis_test_copym( tdata, params, &(op->ops->copym) ); libblis_test_scalm( tdata, params, &(op->ops->scalm) ); } void libblis_test_axpym ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { // Return early if this test has already been done. if ( libblis_test_op_is_done( op ) ) return; // Return early if operation is disabled. if ( libblis_test_op_is_disabled( op ) || libblis_test_l1m_is_disabled( op ) ) return; // Call dependencies first. if ( TRUE ) libblis_test_axpym_deps( tdata, params, op ); // Execute the test driver for each implementation requested. //if ( op->front_seq == ENABLE ) { libblis_test_op_driver( tdata, params, op, BLIS_TEST_SEQ_FRONT_END, op_str, p_types, o_types, thresh, libblis_test_axpym_experiment ); } } void libblis_test_axpym_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ) { unsigned int n_repeats = params->n_repeats; unsigned int i; double time_min = DBL_MAX; double time; num_t datatype; dim_t m, n; trans_t transx; obj_t alpha, x, y; obj_t y_save; // Use the datatype of the first char in the datatype combination string. bli_param_map_char_to_blis_dt( dc_str[0], &datatype ); // Map the dimension specifier to actual dimensions. m = libblis_test_get_dim_from_prob_size( op->dim_spec[0], p_cur ); n = libblis_test_get_dim_from_prob_size( op->dim_spec[1], p_cur ); // Map parameter characters to BLIS constants. bli_param_map_char_to_blis_trans( pc_str[0], &transx ); // Create test scalars. bli_obj_scalar_init_detached( datatype, &alpha ); // Create test operands (vectors and/or matrices). libblis_test_mobj_create( params, datatype, transx, sc_str[0], m, n, &x ); libblis_test_mobj_create( params, datatype, BLIS_NO_TRANSPOSE, sc_str[0], m, n, &y ); libblis_test_mobj_create( params, datatype, BLIS_NO_TRANSPOSE, sc_str[0], m, n, &y_save ); // Set alpha. if ( bli_obj_is_real( &y ) ) bli_setsc( -2.0, 0.0, &alpha ); else bli_setsc( 0.0, -2.0, &alpha ); // Randomize and save y. libblis_test_mobj_randomize( params, FALSE, &x ); libblis_test_mobj_randomize( params, FALSE, &y ); bli_copym( &y, &y_save ); // Apply the parameters. bli_obj_set_conjtrans( transx, &x ); // Repeat the experiment n_repeats times and record results. for ( i = 0; i < n_repeats; ++i ) { bli_copym( &y_save, &y ); time = bli_clock(); libblis_test_axpym_impl( iface, &alpha, &x, &y ); time_min = bli_clock_min_diff( time_min, time ); } // Estimate the performance of the best experiment repeat. *perf = ( 2.0 * m * n ) / time_min / FLOPS_PER_UNIT_PERF; if ( bli_obj_is_complex( &y ) ) *perf *= 4.0; // Perform checks. libblis_test_axpym_check( params, &alpha, &x, &y, &y_save, resid ); // Zero out performance and residual if output matrix is empty. libblis_test_check_empty_problem( &y, perf, resid ); // Free the test objects. bli_obj_free( &x ); bli_obj_free( &y ); bli_obj_free( &y_save ); } void libblis_test_axpym_impl ( iface_t iface, obj_t* alpha, obj_t* x, obj_t* y ) { switch ( iface ) { case BLIS_TEST_SEQ_FRONT_END: bli_axpym( alpha, x, y ); break; default: libblis_test_printf_error( "Invalid interface type.\n" ); } } void libblis_test_axpym_check ( test_params_t* params, obj_t* alpha, obj_t* x, obj_t* y, obj_t* y_orig, double* resid ) { num_t dt = bli_obj_dt( y ); num_t dt_real = bli_obj_dt_proj_to_real( y ); dim_t m = bli_obj_length( y ); dim_t n = bli_obj_width( y ); obj_t x_temp, y_temp; obj_t norm; double junk; // // Pre-conditions: // - x is randomized. // - y_orig is randomized. // Note: // - alpha should have a non-zero imaginary component in the complex // cases in order to more fully exercise the implementation. // // Under these conditions, we assume that the implementation for // // y := y_orig + alpha * conjx(x) // // is functioning correctly if // // normfm( y - ( y_orig + alpha * conjx(x) ) ) // // is negligible. // bli_obj_scalar_init_detached( dt_real, &norm ); bli_obj_create( dt, m, n, 0, 0, &x_temp ); bli_obj_create( dt, m, n, 0, 0, &y_temp ); bli_copym( x, &x_temp ); bli_copym( y_orig, &y_temp ); bli_scalm( alpha, &x_temp ); bli_addm( &x_temp, &y_temp ); bli_subm( &y_temp, y ); bli_normfm( y, &norm ); bli_getsc( &norm, resid, &junk ); bli_obj_free( &x_temp ); bli_obj_free( &y_temp ); } blis-0.9.0/testsuite/src/test_axpym.h000066400000000000000000000035001422157504600176430ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void libblis_test_axpym ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); blis-0.9.0/testsuite/src/test_axpyv.c000066400000000000000000000204221422157504600176510ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "test_libblis.h" // Static variables. static char* op_str = "axpyv"; static char* o_types = "vv"; // x y static char* p_types = "c"; // conjx static thresh_t thresh[BLIS_NUM_FP_TYPES] = { { 1e-04, 1e-05 }, // warn, pass for s { 1e-04, 1e-05 }, // warn, pass for c { 1e-13, 1e-14 }, // warn, pass for d { 1e-13, 1e-14 } }; // warn, pass for z // Local prototypes. void libblis_test_axpyv_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); void libblis_test_axpyv_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ); void libblis_test_axpyv_impl ( iface_t iface, obj_t* alpha, obj_t* x, obj_t* y ); void libblis_test_axpyv_check ( test_params_t* params, obj_t* alpha, obj_t* x, obj_t* y, obj_t* y_orig, double* resid ); void libblis_test_axpyv_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { libblis_test_randv( tdata, params, &(op->ops->randv) ); libblis_test_normfv( tdata, params, &(op->ops->normfv) ); libblis_test_addv( tdata, params, &(op->ops->addv) ); libblis_test_subv( tdata, params, &(op->ops->subv) ); libblis_test_copyv( tdata, params, &(op->ops->copyv) ); libblis_test_scalv( tdata, params, &(op->ops->scalv) ); } void libblis_test_axpyv ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { // Return early if this test has already been done. if ( libblis_test_op_is_done( op ) ) return; // Return early if operation is disabled. if ( libblis_test_op_is_disabled( op ) || libblis_test_l1v_is_disabled( op ) ) return; // Call dependencies first. if ( TRUE ) libblis_test_axpyv_deps( tdata, params, op ); // Execute the test driver for each implementation requested. //if ( op->front_seq == ENABLE ) { libblis_test_op_driver( tdata, params, op, BLIS_TEST_SEQ_FRONT_END, op_str, p_types, o_types, thresh, libblis_test_axpyv_experiment ); } } void libblis_test_axpyv_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ) { unsigned int n_repeats = params->n_repeats; unsigned int i; double time_min = DBL_MAX; double time; num_t datatype; dim_t m; conj_t conjx; obj_t alpha, x, y; obj_t y_save; // Use the datatype of the first char in the datatype combination string. bli_param_map_char_to_blis_dt( dc_str[0], &datatype ); // Map the dimension specifier to an actual dimension. m = libblis_test_get_dim_from_prob_size( op->dim_spec[0], p_cur ); // Map parameter characters to BLIS constants. bli_param_map_char_to_blis_conj( pc_str[0], &conjx ); // Create test scalars. bli_obj_scalar_init_detached( datatype, &alpha ); // Create test operands (vectors and/or matrices). libblis_test_vobj_create( params, datatype, sc_str[0], m, &x ); libblis_test_vobj_create( params, datatype, sc_str[1], m, &y ); libblis_test_vobj_create( params, datatype, sc_str[1], m, &y_save ); // Set alpha. //bli_setsc( sqrt(2.0)/2.0, sqrt(2.0)/2.0, &alpha ); //bli_copysc( &BLIS_TWO, &alpha ); if ( bli_obj_is_real( &y ) ) bli_setsc( -2.0, 0.0, &alpha ); else bli_setsc( 0.0, -2.0, &alpha ); // Randomize x and y, and save y. libblis_test_vobj_randomize( params, FALSE, &x ); libblis_test_vobj_randomize( params, FALSE, &y ); bli_copyv( &y, &y_save ); // Apply the parameters. bli_obj_set_conj( conjx, &x ); // Repeat the experiment n_repeats times and record results. for ( i = 0; i < n_repeats; ++i ) { bli_copyv( &y_save, &y ); time = bli_clock(); libblis_test_axpyv_impl( iface, &alpha, &x, &y ); time_min = bli_clock_min_diff( time_min, time ); } // Estimate the performance of the best experiment repeat. *perf = ( 2.0 * m ) / time_min / FLOPS_PER_UNIT_PERF; if ( bli_obj_is_complex( &y ) ) *perf *= 4.0; // Perform checks. libblis_test_axpyv_check( params, &alpha, &x, &y, &y_save, resid ); // Zero out performance and residual if output vector is empty. libblis_test_check_empty_problem( &y, perf, resid ); // Free the test objects. bli_obj_free( &x ); bli_obj_free( &y ); bli_obj_free( &y_save ); } void libblis_test_axpyv_impl ( iface_t iface, obj_t* alpha, obj_t* x, obj_t* y ) { switch ( iface ) { case BLIS_TEST_SEQ_FRONT_END: bli_axpyv( alpha, x, y ); break; default: libblis_test_printf_error( "Invalid interface type.\n" ); } } void libblis_test_axpyv_check ( test_params_t* params, obj_t* alpha, obj_t* x, obj_t* y, obj_t* y_orig, double* resid ) { num_t dt = bli_obj_dt( y ); num_t dt_real = bli_obj_dt_proj_to_real( y ); dim_t m = bli_obj_vector_dim( y ); obj_t x_temp, y_temp; obj_t norm; double junk; // // Pre-conditions: // - x is randomized. // - y_orig is randomized. // Note: // - alpha should have a non-zero imaginary component in the complex // cases in order to more fully exercise the implementation. // // Under these conditions, we assume that the implementation for // // y := y_orig + alpha * conjx(x) // // is functioning correctly if // // normfv( y - ( y_orig + alpha * conjx(x) ) ) // // is negligible. // bli_obj_scalar_init_detached( dt_real, &norm ); bli_obj_create( dt, m, 1, 0, 0, &x_temp ); bli_obj_create( dt, m, 1, 0, 0, &y_temp ); bli_copyv( x, &x_temp ); bli_copyv( y_orig, &y_temp ); bli_scalv( alpha, &x_temp ); bli_addv( &x_temp, &y_temp ); bli_subv( &y_temp, y ); bli_normfv( y, &norm ); bli_getsc( &norm, resid, &junk ); bli_obj_free( &x_temp ); bli_obj_free( &y_temp ); } blis-0.9.0/testsuite/src/test_axpyv.h000066400000000000000000000035001422157504600176540ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void libblis_test_axpyv ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); blis-0.9.0/testsuite/src/test_copym.c000066400000000000000000000157441422157504600176440ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "test_libblis.h" // Static variables. static char* op_str = "copym"; static char* o_types = "mm"; // x y static char* p_types = "h"; // transx static thresh_t thresh[BLIS_NUM_FP_TYPES] = { { 1e-04, 1e-05 }, // warn, pass for s { 1e-04, 1e-05 }, // warn, pass for c { 1e-13, 1e-14 }, // warn, pass for d { 1e-13, 1e-14 } }; // warn, pass for z // Local prototypes. void libblis_test_copym_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); void libblis_test_copym_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ); void libblis_test_copym_impl ( iface_t iface, obj_t* x, obj_t* y ); void libblis_test_copym_check ( test_params_t* params, obj_t* x, obj_t* y, double* resid ); void libblis_test_copym_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { libblis_test_randm( tdata, params, &(op->ops->randm) ); libblis_test_subm( tdata, params, &(op->ops->subm) ); libblis_test_normfm( tdata, params, &(op->ops->normfm) ); } void libblis_test_copym ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { // Return early if this test has already been done. if ( libblis_test_op_is_done( op ) ) return; // Return early if operation is disabled. if ( libblis_test_op_is_disabled( op ) || libblis_test_l1m_is_disabled( op ) ) return; // Call dependencies first. if ( TRUE ) libblis_test_copym_deps( tdata, params, op ); // Execute the test driver for each implementation requested. //if ( op->front_seq == ENABLE ) { libblis_test_op_driver( tdata, params, op, BLIS_TEST_SEQ_FRONT_END, op_str, p_types, o_types, thresh, libblis_test_copym_experiment ); } } void libblis_test_copym_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ) { double time_min = DBL_MAX; double time; num_t datatype; dim_t m, n; trans_t transx; obj_t x, y; // Use the datatype of the first char in the datatype combination string. bli_param_map_char_to_blis_dt( dc_str[0], &datatype ); // Map the dimension specifier to actual dimensions. m = libblis_test_get_dim_from_prob_size( op->dim_spec[0], p_cur ); n = libblis_test_get_dim_from_prob_size( op->dim_spec[1], p_cur ); // Map parameter characters to BLIS constants. bli_param_map_char_to_blis_trans( pc_str[0], &transx ); // Create test operands (vectors and/or matrices). libblis_test_mobj_create( params, datatype, transx, sc_str[0], m, n, &x ); libblis_test_mobj_create( params, datatype, BLIS_NO_TRANSPOSE, sc_str[1], m, n, &y ); // Randomize x and set y to one. libblis_test_mobj_randomize( params, FALSE, &x ); bli_setm( &BLIS_ONE, &y ); // Apply the parameters. bli_obj_set_conjtrans( transx, &x ); // Disable repeats since bli_copym() is not yet tested. //for ( i = 0; i < n_repeats; ++i ) { time = bli_clock(); libblis_test_copym_impl( iface, &x, &y ); time_min = bli_clock_min_diff( time_min, time ); } // Estimate the performance of the best experiment repeat. *perf = ( 1.0 * m * n ) / time_min / FLOPS_PER_UNIT_PERF; if ( bli_obj_is_complex( &x ) ) *perf *= 2.0; // Perform checks. libblis_test_copym_check( params, &x, &y, resid ); // Zero out performance and residual if output matrix is empty. libblis_test_check_empty_problem( &y, perf, resid ); // Free the test objects. bli_obj_free( &x ); bli_obj_free( &y ); } void libblis_test_copym_impl ( iface_t iface, obj_t* x, obj_t* y ) { switch ( iface ) { case BLIS_TEST_SEQ_FRONT_END: bli_copym( x, y ); break; default: libblis_test_printf_error( "Invalid interface type.\n" ); } } void libblis_test_copym_check ( test_params_t* params, obj_t* x, obj_t* y, double* resid ) { num_t dt_real = bli_obj_dt_proj_to_real( x ); obj_t norm_y_r; double junk; // // Pre-conditions: // - x is randomized. // // Under these conditions, we assume that the implementation for // // y := conjx(x) // // is functioning correctly if // // normfm( y - conjx(x) ) // // is negligible. // bli_obj_scalar_init_detached( dt_real, &norm_y_r ); bli_subm( x, y ); bli_normfm( y, &norm_y_r ); bli_getsc( &norm_y_r, resid, &junk ); } blis-0.9.0/testsuite/src/test_copym.h000066400000000000000000000035001422157504600176340ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void libblis_test_copym ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); blis-0.9.0/testsuite/src/test_copyv.c000066400000000000000000000154731422157504600176540ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "test_libblis.h" // Static variables. static char* op_str = "copyv"; static char* o_types = "vv"; // x y static char* p_types = "c"; // conjx static thresh_t thresh[BLIS_NUM_FP_TYPES] = { { 1e-04, 1e-05 }, // warn, pass for s { 1e-04, 1e-05 }, // warn, pass for c { 1e-13, 1e-14 }, // warn, pass for d { 1e-13, 1e-14 } }; // warn, pass for z // Local prototypes. void libblis_test_copyv_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); void libblis_test_copyv_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ); void libblis_test_copyv_impl ( iface_t iface, obj_t* x, obj_t* y ); void libblis_test_copyv_check ( test_params_t* params, obj_t* x, obj_t* y, double* resid ); void libblis_test_copyv_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { libblis_test_randv( tdata, params, &(op->ops->randv) ); libblis_test_subv( tdata, params, &(op->ops->subv) ); libblis_test_normfv( tdata, params, &(op->ops->normfv) ); } void libblis_test_copyv ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { // Return early if this test has already been done. if ( libblis_test_op_is_done( op ) ) return; // Return early if operation is disabled. if ( libblis_test_op_is_disabled( op ) || libblis_test_l1v_is_disabled( op ) ) return; // Call dependencies first. if ( TRUE ) libblis_test_copyv_deps( tdata, params, op ); // Execute the test driver for each implementation requested. //if ( op->front_seq == ENABLE ) { libblis_test_op_driver( tdata, params, op, BLIS_TEST_SEQ_FRONT_END, op_str, p_types, o_types, thresh, libblis_test_copyv_experiment ); } } void libblis_test_copyv_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ) { double time_min = DBL_MAX; double time; num_t datatype; dim_t m; conj_t conjx; obj_t x, y; // Use the datatype of the first char in the datatype combination string. bli_param_map_char_to_blis_dt( dc_str[0], &datatype ); // Map the dimension specifier to an actual dimension. m = libblis_test_get_dim_from_prob_size( op->dim_spec[0], p_cur ); // Map parameter characters to BLIS constants. bli_param_map_char_to_blis_conj( pc_str[0], &conjx ); // Create test operands (vectors and/or matrices). libblis_test_vobj_create( params, datatype, sc_str[0], m, &x ); libblis_test_vobj_create( params, datatype, sc_str[1], m, &y ); // Randomize x and set y to one. libblis_test_vobj_randomize( params, FALSE, &x ); bli_setv( &BLIS_ONE, &y ); // Apply the parameters. bli_obj_set_conj( conjx, &x ); // Disable repeats since bli_copyv() is not yet tested. //for ( i = 0; i < n_repeats; ++i ) { time = bli_clock(); libblis_test_copyv_impl( iface, &x, &y ); time_min = bli_clock_min_diff( time_min, time ); } // Estimate the performance of the best experiment repeat. *perf = ( 1.0 * m ) / time_min / FLOPS_PER_UNIT_PERF; if ( bli_obj_is_complex( &x ) ) *perf *= 2.0; // Perform checks. libblis_test_copyv_check( params, &x, &y, resid ); // Zero out performance and residual if output vector is empty. libblis_test_check_empty_problem( &y, perf, resid ); // Free the test objects. bli_obj_free( &x ); bli_obj_free( &y ); } void libblis_test_copyv_impl ( iface_t iface, obj_t* x, obj_t* y ) { switch ( iface ) { case BLIS_TEST_SEQ_FRONT_END: bli_copyv( x, y ); break; default: libblis_test_printf_error( "Invalid interface type.\n" ); } } void libblis_test_copyv_check ( test_params_t* params, obj_t* x, obj_t* y, double* resid ) { num_t dt_real = bli_obj_dt_proj_to_real( x ); obj_t norm_y_r; double junk; // // Pre-conditions: // - x is randomized. // // Under these conditions, we assume that the implementation for // // y := conjx(x) // // is functioning correctly if // // normfv( y - conjx(x) ) // // is negligible. // bli_obj_scalar_init_detached( dt_real, &norm_y_r ); bli_subv( x, y ); bli_normfv( y, &norm_y_r ); bli_getsc( &norm_y_r, resid, &junk ); } blis-0.9.0/testsuite/src/test_copyv.h000066400000000000000000000035001422157504600176450ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void libblis_test_copyv ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); blis-0.9.0/testsuite/src/test_dotaxpyv.c000066400000000000000000000240531422157504600203640ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "test_libblis.h" // Static variables. static char* op_str = "dotaxpyv"; static char* o_types = "vvv"; // x y z static char* p_types = "ccc"; // conjxt conjx conjy static thresh_t thresh[BLIS_NUM_FP_TYPES] = { { 1e-04, 1e-05 }, // warn, pass for s { 1e-04, 1e-05 }, // warn, pass for c { 1e-13, 1e-14 }, // warn, pass for d { 1e-13, 1e-14 } }; // warn, pass for z // Local prototypes. void libblis_test_dotaxpyv_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); void libblis_test_dotaxpyv_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ); void libblis_test_dotaxpyv_impl ( iface_t iface, obj_t* alpha, obj_t* xt, obj_t* x, obj_t* y, obj_t* rho, obj_t* z, cntx_t* cntx ); void libblis_test_dotaxpyv_check ( test_params_t* params, obj_t* alpha, obj_t* xt, obj_t* x, obj_t* y, obj_t* rho, obj_t* z, obj_t* z_orig, double* resid ); void libblis_test_dotaxpyv_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { libblis_test_randv( tdata, params, &(op->ops->randv) ); libblis_test_normfv( tdata, params, &(op->ops->normfv) ); libblis_test_subv( tdata, params, &(op->ops->subv) ); libblis_test_copyv( tdata, params, &(op->ops->copyv) ); libblis_test_dotv( tdata, params, &(op->ops->dotv) ); libblis_test_axpyv( tdata, params, &(op->ops->axpyv) ); } void libblis_test_dotaxpyv ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { // Return early if this test has already been done. if ( libblis_test_op_is_done( op ) ) return; // Return early if operation is disabled. if ( libblis_test_op_is_disabled( op ) || libblis_test_l1f_is_disabled( op ) ) return; // Call dependencies first. if ( TRUE ) libblis_test_dotaxpyv_deps( tdata, params, op ); // Execute the test driver for each implementation requested. //if ( op->front_seq == ENABLE ) { libblis_test_op_driver( tdata, params, op, BLIS_TEST_SEQ_FRONT_END, op_str, p_types, o_types, thresh, libblis_test_dotaxpyv_experiment ); } } void libblis_test_dotaxpyv_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ) { unsigned int n_repeats = params->n_repeats; unsigned int i; double time_min = DBL_MAX; double time; num_t datatype; dim_t m; conj_t conjxt, conjx, conjy; conj_t conjconjxty; obj_t alpha, xt, x, y, rho, z; obj_t z_save; cntx_t* cntx; // Query a context. cntx = bli_gks_query_cntx(); // Use the datatype of the first char in the datatype combination string. bli_param_map_char_to_blis_dt( dc_str[0], &datatype ); // Map the dimension specifier to an actual dimension. m = libblis_test_get_dim_from_prob_size( op->dim_spec[0], p_cur ); // Map parameter characters to BLIS constants. bli_param_map_char_to_blis_conj( pc_str[0], &conjxt ); bli_param_map_char_to_blis_conj( pc_str[1], &conjx ); bli_param_map_char_to_blis_conj( pc_str[2], &conjy ); // Create test scalars. bli_obj_scalar_init_detached( datatype, &alpha ); bli_obj_scalar_init_detached( datatype, &rho ); // Create test operands (vectors and/or matrices). libblis_test_vobj_create( params, datatype, sc_str[0], m, &x ); libblis_test_vobj_create( params, datatype, sc_str[1], m, &y ); libblis_test_vobj_create( params, datatype, sc_str[2], m, &z ); libblis_test_vobj_create( params, datatype, sc_str[2], m, &z_save ); // Set alpha. if ( bli_obj_is_real( &z ) ) { bli_setsc( -0.8, 0.0, &alpha ); } else { bli_setsc( 0.7, -0.1, &alpha ); } // Randomize x and z, and save z. libblis_test_vobj_randomize( params, TRUE, &x ); libblis_test_vobj_randomize( params, TRUE, &z ); bli_copyv( &z, &z_save ); // Create an alias to x for xt. (Note that it doesn't actually need to be // transposed.) bli_obj_alias_to( &x, &xt ); // Determine whether to make a copy of x with or without conjugation. // // conjx conjy ~conjx^conjy y is initialized as // n n c y = conj(x) // n c n y = x // c n n y = x // c c c y = conj(x) // conjconjxty = bli_apply_conj( conjxt, conjy ); conjconjxty = bli_conj_toggled( conjconjxty ); bli_obj_set_conj( conjconjxty, &xt ); bli_copyv( &xt, &y ); // Apply the parameters. bli_obj_set_conj( conjxt, &xt ); bli_obj_set_conj( conjx, &x ); bli_obj_set_conj( conjy, &y ); // Repeat the experiment n_repeats times and record results. for ( i = 0; i < n_repeats; ++i ) { bli_copysc( &BLIS_MINUS_ONE, &rho ); bli_copyv( &z_save, &z ); time = bli_clock(); libblis_test_dotaxpyv_impl( iface, &alpha, &xt, &x, &y, &rho, &z, cntx ); time_min = bli_clock_min_diff( time_min, time ); } // Estimate the performance of the best experiment repeat. *perf = ( 2.0 * m + 2.0 * m ) / time_min / FLOPS_PER_UNIT_PERF; if ( bli_obj_is_complex( &z ) ) *perf *= 4.0; // Perform checks. libblis_test_dotaxpyv_check( params, &alpha, &xt, &x, &y, &rho, &z, &z_save, resid ); // Zero out performance and residual if output vector is empty. libblis_test_check_empty_problem( &z, perf, resid ); // Free the test objects. bli_obj_free( &x ); bli_obj_free( &y ); bli_obj_free( &z ); bli_obj_free( &z_save ); } void libblis_test_dotaxpyv_impl ( iface_t iface, obj_t* alpha, obj_t* xt, obj_t* x, obj_t* y, obj_t* rho, obj_t* z, cntx_t* cntx ) { switch ( iface ) { case BLIS_TEST_SEQ_FRONT_END: bli_dotaxpyv_ex( alpha, xt, x, y, rho, z, cntx, NULL ); break; default: libblis_test_printf_error( "Invalid interface type.\n" ); } } void libblis_test_dotaxpyv_check ( test_params_t* params, obj_t* alpha, obj_t* xt, obj_t* x, obj_t* y, obj_t* rho, obj_t* z, obj_t* z_orig, double* resid ) { num_t dt = bli_obj_dt( z ); num_t dt_real = bli_obj_dt_proj_to_real( z ); dim_t m = bli_obj_vector_dim( z ); obj_t rho_temp; obj_t z_temp; obj_t norm_z; double resid1, resid2; double junk; // // Pre-conditions: // - x is randomized. // - y is randomized. // - z_orig is randomized. // - xt is an alias to x. // Note: // - alpha should have a non-zero imaginary component in the complex // cases in order to more fully exercise the implementation. // // Under these conditions, we assume that the implementation for // // rho := conjxt(x^T) conjy(y) // z := z_orig + alpha * conjx(x) // // is functioning correctly if // // ( rho - rho_temp ) // // and // // normfv( z - z_temp ) // // are negligible, where rho_temp and z_temp contain rho and z as // computed by dotv and axpyv, respectively. // bli_obj_scalar_init_detached( dt, &rho_temp ); bli_obj_scalar_init_detached( dt_real, &norm_z ); bli_obj_create( dt, m, 1, 0, 0, &z_temp ); bli_copyv( z_orig, &z_temp ); bli_dotv( xt, y, &rho_temp ); bli_axpyv( alpha, x, &z_temp ); bli_subsc( rho, &rho_temp ); bli_getsc( &rho_temp, &resid1, &junk ); bli_subv( &z_temp, z ); bli_normfv( z, &norm_z ); bli_getsc( &norm_z, &resid2, &junk ); *resid = bli_fmaxabs( resid1, resid2 ); bli_obj_free( &z_temp ); } blis-0.9.0/testsuite/src/test_dotaxpyv.h000066400000000000000000000035031422157504600203660ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void libblis_test_dotaxpyv ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); blis-0.9.0/testsuite/src/test_dotv.c000066400000000000000000000200471422157504600174610ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "test_libblis.h" // Static variables. static char* op_str = "dotv"; static char* o_types = "vv"; // x y static char* p_types = "cc"; // conjx conjy static thresh_t thresh[BLIS_NUM_FP_TYPES] = { { 1e-04, 1e-05 }, // warn, pass for s { 1e-04, 1e-05 }, // warn, pass for c { 1e-13, 1e-14 }, // warn, pass for d { 1e-13, 1e-14 } }; // warn, pass for z // Local prototypes. void libblis_test_dotv_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); void libblis_test_dotv_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ); void libblis_test_dotv_impl ( iface_t iface, obj_t* x, obj_t* y, obj_t* rho ); void libblis_test_dotv_check ( test_params_t* params, obj_t* x, obj_t* y, obj_t* rho, double* resid ); void libblis_test_dotv_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { libblis_test_randv( tdata, params, &(op->ops->randv) ); libblis_test_normfv( tdata, params, &(op->ops->normfv) ); libblis_test_copyv( tdata, params, &(op->ops->copyv) ); } void libblis_test_dotv ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { // Return early if this test has already been done. if ( libblis_test_op_is_done( op ) ) return; // Return early if operation is disabled. if ( libblis_test_op_is_disabled( op ) || libblis_test_l1v_is_disabled( op ) ) return; // Call dependencies first. if ( TRUE ) libblis_test_dotv_deps( tdata, params, op ); // Execute the test driver for each implementation requested. //if ( op->front_seq == ENABLE ) { libblis_test_op_driver( tdata, params, op, BLIS_TEST_SEQ_FRONT_END, op_str, p_types, o_types, thresh, libblis_test_dotv_experiment ); } } void libblis_test_dotv_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ) { unsigned int n_repeats = params->n_repeats; unsigned int i; double time_min = DBL_MAX; double time; num_t datatype; dim_t m; conj_t conjx, conjy, conjconjxy; obj_t x, y, rho; // Use the datatype of the first char in the datatype combination string. bli_param_map_char_to_blis_dt( dc_str[0], &datatype ); // Map the dimension specifier to an actual dimension. m = libblis_test_get_dim_from_prob_size( op->dim_spec[0], p_cur ); // Map parameter characters to BLIS constants. bli_param_map_char_to_blis_conj( pc_str[0], &conjx ); bli_param_map_char_to_blis_conj( pc_str[1], &conjy ); // Create test scalars. bli_obj_scalar_init_detached( datatype, &rho ); // Create test operands (vectors and/or matrices). libblis_test_vobj_create( params, datatype, sc_str[0], m, &x ); libblis_test_vobj_create( params, datatype, sc_str[1], m, &y ); // Randomize x. libblis_test_vobj_randomize( params, TRUE, &x ); // Determine whether to make a copy of x with or without conjugation. // // conjx conjy ~conjx^conjy y is initialized as // n n c y = conj(x) // n c n y = x // c n n y = x // c c c y = conj(x) // conjconjxy = bli_apply_conj( conjx, conjy ); conjconjxy = bli_conj_toggled( conjconjxy ); bli_obj_set_conj( conjconjxy, &x ); bli_copyv( &x, &y ); // Apply the parameters. bli_obj_set_conj( conjx, &x ); bli_obj_set_conj( conjy, &y ); // Repeat the experiment n_repeats times and record results. for ( i = 0; i < n_repeats; ++i ) { bli_copysc( &BLIS_MINUS_ONE, &rho ); time = bli_clock(); libblis_test_dotv_impl( iface, &x, &y, &rho ); time_min = bli_clock_min_diff( time_min, time ); } // Estimate the performance of the best experiment repeat. *perf = ( 2.0 * m ) / time_min / FLOPS_PER_UNIT_PERF; if ( bli_obj_is_complex( &y ) ) *perf *= 4.0; // Perform checks. libblis_test_dotv_check( params, &x, &y, &rho, resid ); // Zero out performance and residual if output scalar is empty. libblis_test_check_empty_problem( &rho, perf, resid ); // Free the test objects. bli_obj_free( &x ); bli_obj_free( &y ); } void libblis_test_dotv_impl ( iface_t iface, obj_t* x, obj_t* y, obj_t* rho ) { switch ( iface ) { case BLIS_TEST_SEQ_FRONT_END: bli_dotv( x, y, rho ); break; default: libblis_test_printf_error( "Invalid interface type.\n" ); } } void libblis_test_dotv_check ( test_params_t* params, obj_t* x, obj_t* y, obj_t* rho, double* resid ) { num_t dt_real = bli_obj_dt_proj_to_real( y ); obj_t rho_r, rho_i; obj_t norm_x, norm_xy; double zero; double junk; // // Pre-conditions: // - x is randomized. // - y is equal to conj(conjx(conjy(x))). // // Under these conditions, we assume that the implementation for // // rho := conjx(x^T) conjy(y) // // is functioning correctly if // // sqrtsc( rho.real ) - normfv( x ) // // and // // rho.imag // // are negligible. // bli_obj_scalar_init_detached( dt_real, &rho_r ); bli_obj_scalar_init_detached( dt_real, &rho_i ); bli_obj_scalar_init_detached( dt_real, &norm_x ); bli_obj_scalar_init_detached( dt_real, &norm_xy ); bli_normfv( x, &norm_x ); bli_unzipsc( rho, &rho_r, &rho_i ); bli_sqrtsc( &rho_r, &norm_xy ); bli_subsc( &norm_x, &norm_xy ); bli_getsc( &norm_xy, resid, &junk ); bli_getsc( &rho_i, &zero, &junk ); *resid = bli_fmaxabs( *resid, zero ); } blis-0.9.0/testsuite/src/test_dotv.h000066400000000000000000000034771422157504600174760ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void libblis_test_dotv ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); blis-0.9.0/testsuite/src/test_dotxaxpyf.c000066400000000000000000000273321422157504600205370ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "test_libblis.h" // Static variables. static char* op_str = "dotxaxpyf"; static char* o_types = "mvvvv"; // A w x y z static char* p_types = "cccc"; // conjat conja conjw conjx static thresh_t thresh[BLIS_NUM_FP_TYPES] = { { 5e-04, 5e-05 }, // warn, pass for s { 5e-04, 5e-05 }, // warn, pass for c { 5e-13, 5e-14 }, // warn, pass for d { 5e-13, 5e-14 } }; // warn, pass for z // Local prototypes. void libblis_test_dotxaxpyf_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); void libblis_test_dotxaxpyf_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ); void libblis_test_dotxaxpyf_impl ( iface_t iface, obj_t* alpha, obj_t* at, obj_t* a, obj_t* w, obj_t* x, obj_t* beta, obj_t* y, obj_t* z, cntx_t* cntx ); void libblis_test_dotxaxpyf_check ( test_params_t* params, obj_t* alpha, obj_t* at, obj_t* a, obj_t* w, obj_t* x, obj_t* beta, obj_t* y, obj_t* z, obj_t* y_orig, obj_t* z_orig, double* resid ); void libblis_test_dotxaxpyf_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { libblis_test_randv( tdata, params, &(op->ops->randv) ); libblis_test_randm( tdata, params, &(op->ops->randm) ); libblis_test_normfv( tdata, params, &(op->ops->normfv) ); libblis_test_subv( tdata, params, &(op->ops->subv) ); libblis_test_copyv( tdata, params, &(op->ops->copyv) ); libblis_test_axpyv( tdata, params, &(op->ops->axpyv) ); libblis_test_dotxv( tdata, params, &(op->ops->dotxv) ); } void libblis_test_dotxaxpyf ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { // Return early if this test has already been done. if ( libblis_test_op_is_done( op ) ) return; // Return early if operation is disabled. if ( libblis_test_op_is_disabled( op ) || libblis_test_l1f_is_disabled( op ) ) return; // Call dependencies first. if ( TRUE ) libblis_test_dotxaxpyf_deps( tdata, params, op ); // Execute the test driver for each implementation requested. //if ( op->front_seq == ENABLE ) { libblis_test_op_driver( tdata, params, op, BLIS_TEST_SEQ_FRONT_END, op_str, p_types, o_types, thresh, libblis_test_dotxaxpyf_experiment ); } } void libblis_test_dotxaxpyf_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ) { unsigned int n_repeats = params->n_repeats; unsigned int i; double time_min = DBL_MAX; double time; num_t datatype; dim_t m, b_n; conj_t conjat, conja, conjw, conjx; obj_t alpha, at, a, w, x, beta, y, z; obj_t y_save, z_save; cntx_t* cntx; // Query a context. cntx = bli_gks_query_cntx(); // Use the datatype of the first char in the datatype combination string. bli_param_map_char_to_blis_dt( dc_str[0], &datatype ); // Map the dimension specifier to an actual dimension. m = libblis_test_get_dim_from_prob_size( op->dim_spec[0], p_cur ); // Query the operation's fusing factor for the current datatype. b_n = bli_cntx_get_blksz_def_dt( datatype, BLIS_XF, cntx ); // Store the fusing factor so that the driver can retrieve the value // later when printing results. op->dim_aux[0] = b_n; // Map parameter characters to BLIS constants. bli_param_map_char_to_blis_conj( pc_str[0], &conjat ); bli_param_map_char_to_blis_conj( pc_str[1], &conja ); bli_param_map_char_to_blis_conj( pc_str[2], &conjw ); bli_param_map_char_to_blis_conj( pc_str[3], &conjx ); // Create test scalars. bli_obj_scalar_init_detached( datatype, &alpha ); bli_obj_scalar_init_detached( datatype, &beta ); // Create test operands (vectors and/or matrices). libblis_test_mobj_create( params, datatype, BLIS_NO_TRANSPOSE, sc_str[0], m, b_n, &a ); libblis_test_vobj_create( params, datatype, sc_str[1], m, &w ); libblis_test_vobj_create( params, datatype, sc_str[2], b_n, &x ); libblis_test_vobj_create( params, datatype, sc_str[3], b_n, &y ); libblis_test_vobj_create( params, datatype, sc_str[3], b_n, &y_save ); libblis_test_vobj_create( params, datatype, sc_str[4], m, &z ); libblis_test_vobj_create( params, datatype, sc_str[4], m, &z_save ); // Set alpha. if ( bli_obj_is_real( &y ) ) { bli_setsc( 1.2, 0.0, &alpha ); bli_setsc( -1.0, 0.0, &beta ); } else { bli_setsc( 1.2, 0.1, &alpha ); bli_setsc( -1.0, -0.1, &beta ); } // Randomize A, w, x, y, and z, and save y and z. libblis_test_mobj_randomize( params, FALSE, &a ); libblis_test_vobj_randomize( params, FALSE, &w ); libblis_test_vobj_randomize( params, FALSE, &x ); libblis_test_vobj_randomize( params, FALSE, &y ); libblis_test_vobj_randomize( params, FALSE, &z ); bli_copyv( &y, &y_save ); bli_copyv( &z, &z_save ); // Create an alias to a for at. (Note that it should NOT actually be // marked for transposition since the transposition is part of the dotxf // subproblem.) bli_obj_alias_to( &a, &at ); // Apply the parameters. bli_obj_set_conj( conjat, &at ); bli_obj_set_conj( conja, &a ); bli_obj_set_conj( conjw, &w ); bli_obj_set_conj( conjx, &x ); // Repeat the experiment n_repeats times and record results. for ( i = 0; i < n_repeats; ++i ) { bli_copyv( &y_save, &y ); bli_copyv( &z_save, &z ); time = bli_clock(); libblis_test_dotxaxpyf_impl( iface, &alpha, &at, &a, &w, &x, &beta, &y, &z, cntx ); time_min = bli_clock_min_diff( time_min, time ); } // Estimate the performance of the best experiment repeat. *perf = ( 2.0 * m * b_n + 2.0 * m * b_n ) / time_min / FLOPS_PER_UNIT_PERF; if ( bli_obj_is_complex( &y ) ) *perf *= 4.0; // Perform checks. libblis_test_dotxaxpyf_check( params, &alpha, &at, &a, &w, &x, &beta, &y, &z, &y_save, &z_save, resid ); // Zero out performance and residual if either output vector is empty. libblis_test_check_empty_problem( &y, perf, resid ); libblis_test_check_empty_problem( &z, perf, resid ); // Free the test objects. bli_obj_free( &a ); bli_obj_free( &w ); bli_obj_free( &x ); bli_obj_free( &y ); bli_obj_free( &z ); bli_obj_free( &y_save ); bli_obj_free( &z_save ); } void libblis_test_dotxaxpyf_impl ( iface_t iface, obj_t* alpha, obj_t* at, obj_t* a, obj_t* w, obj_t* x, obj_t* beta, obj_t* y, obj_t* z, cntx_t* cntx ) { switch ( iface ) { case BLIS_TEST_SEQ_FRONT_END: bli_dotxaxpyf_ex( alpha, at, a, w, x, beta, y, z, cntx, NULL ); break; default: libblis_test_printf_error( "Invalid interface type.\n" ); } } void libblis_test_dotxaxpyf_check ( test_params_t* params, obj_t* alpha, obj_t* at, obj_t* a, obj_t* w, obj_t* x, obj_t* beta, obj_t* y, obj_t* z, obj_t* y_orig, obj_t* z_orig, double* resid ) { num_t dt = bli_obj_dt( y ); num_t dt_real = bli_obj_dt_proj_to_real( y ); dim_t m = bli_obj_vector_dim( z ); dim_t b_n = bli_obj_vector_dim( y ); dim_t i; obj_t a1, chi1, psi1, v, q; obj_t alpha_chi1; obj_t norm; double resid1, resid2; double junk; // // Pre-conditions: // - a is randomized. // - w is randomized. // - x is randomized. // - y is randomized. // - z is randomized. // - at is an alias to a. // Note: // - alpha and beta should have a non-zero imaginary component in the // complex cases in order to more fully exercise the implementation. // // Under these conditions, we assume that the implementation for // // y := beta * y_orig + alpha * conjat(A^T) * conjw(w) // z := z_orig + alpha * conja(A) * conjx(x) // // is functioning correctly if // // normfv( y - v ) // // and // // normfv( z - q ) // // are negligible, where v and q contain y and z as computed by repeated // calls to dotxv and axpyv, respectively. // bli_obj_scalar_init_detached( dt_real, &norm ); bli_obj_scalar_init_detached( dt, &alpha_chi1 ); bli_obj_create( dt, b_n, 1, 0, 0, &v ); bli_obj_create( dt, m, 1, 0, 0, &q ); bli_copyv( y_orig, &v ); bli_copyv( z_orig, &q ); // v := beta * v + alpha * conjat(at) * conjw(w) for ( i = 0; i < b_n; ++i ) { bli_acquire_mpart_l2r( BLIS_SUBPART1, i, 1, at, &a1 ); bli_acquire_vpart_f2b( BLIS_SUBPART1, i, 1, &v, &psi1 ); bli_dotxv( alpha, &a1, w, beta, &psi1 ); } // q := q + alpha * conja(a) * conjx(x) for ( i = 0; i < b_n; ++i ) { bli_acquire_mpart_l2r( BLIS_SUBPART1, i, 1, a, &a1 ); bli_acquire_vpart_f2b( BLIS_SUBPART1, i, 1, x, &chi1 ); bli_copysc( &chi1, &alpha_chi1 ); bli_mulsc( alpha, &alpha_chi1 ); bli_axpyv( &alpha_chi1, &a1, &q ); } bli_subv( y, &v ); bli_normfv( &v, &norm ); bli_getsc( &norm, &resid1, &junk ); bli_subv( z, &q ); bli_normfv( &q, &norm ); bli_getsc( &norm, &resid2, &junk ); *resid = bli_fmaxabs( resid1, resid2 ); bli_obj_free( &v ); bli_obj_free( &q ); } blis-0.9.0/testsuite/src/test_dotxaxpyf.h000066400000000000000000000035041422157504600205370ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void libblis_test_dotxaxpyf ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); blis-0.9.0/testsuite/src/test_dotxf.c000066400000000000000000000226361422157504600176370ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "test_libblis.h" // Static variables. static char* op_str = "dotxf"; static char* o_types = "mvv"; // A x y static char* p_types = "cc"; // conjat conjx static thresh_t thresh[BLIS_NUM_FP_TYPES] = { { 5e-04, 5e-05 }, // warn, pass for s { 1e-04, 1e-05 }, // warn, pass for c { 1e-12, 1e-13 }, // warn, pass for d { 1e-12, 1e-13 } }; // warn, pass for z // Local prototypes. void libblis_test_dotxf_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); void libblis_test_dotxf_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ); void libblis_test_dotxf_impl ( iface_t iface, obj_t* alpha, obj_t* a, obj_t* x, obj_t* beta, obj_t* y, cntx_t* cntx ); void libblis_test_dotxf_check ( test_params_t* params, obj_t* alpha, obj_t* a, obj_t* x, obj_t* beta, obj_t* y, obj_t* y_orig, double* resid ); void libblis_test_dotxf_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { libblis_test_randv( tdata, params, &(op->ops->randv) ); libblis_test_randm( tdata, params, &(op->ops->randm) ); libblis_test_normfv( tdata, params, &(op->ops->normfv) ); libblis_test_subv( tdata, params, &(op->ops->subv) ); libblis_test_copyv( tdata, params, &(op->ops->copyv) ); libblis_test_dotxv( tdata, params, &(op->ops->dotxv) ); } void libblis_test_dotxf ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { // Return early if this test has already been done. if ( libblis_test_op_is_done( op ) ) return; // Return early if operation is disabled. if ( libblis_test_op_is_disabled( op ) || libblis_test_l1f_is_disabled( op ) ) return; // Call dependencies first. if ( TRUE ) libblis_test_dotxf_deps( tdata, params, op ); // Execute the test driver for each implementation requested. //if ( op->front_seq == ENABLE ) { libblis_test_op_driver( tdata, params, op, BLIS_TEST_SEQ_FRONT_END, op_str, p_types, o_types, thresh, libblis_test_dotxf_experiment ); } } void libblis_test_dotxf_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ) { unsigned int n_repeats = params->n_repeats; unsigned int i; double time_min = DBL_MAX; double time; num_t datatype; dim_t m, b_n; conj_t conjat, conjx; obj_t alpha, a, x, beta, y; obj_t y_save; cntx_t* cntx; // Query a context. cntx = bli_gks_query_cntx(); // Use the datatype of the first char in the datatype combination string. bli_param_map_char_to_blis_dt( dc_str[0], &datatype ); // Map the dimension specifier to an actual dimension. m = libblis_test_get_dim_from_prob_size( op->dim_spec[0], p_cur ); // Query the operation's fusing factor for the current datatype. b_n = bli_cntx_get_blksz_def_dt( datatype, BLIS_DF, cntx ); // Store the fusing factor so that the driver can retrieve the value // later when printing results. op->dim_aux[0] = b_n; // Map parameter characters to BLIS constants. bli_param_map_char_to_blis_conj( pc_str[0], &conjat ); bli_param_map_char_to_blis_conj( pc_str[1], &conjx ); // Create test scalars. bli_obj_scalar_init_detached( datatype, &alpha ); bli_obj_scalar_init_detached( datatype, &beta ); // Create test operands (vectors and/or matrices). libblis_test_mobj_create( params, datatype, BLIS_NO_TRANSPOSE, sc_str[0], m, b_n, &a ); libblis_test_vobj_create( params, datatype, sc_str[1], m, &x ); libblis_test_vobj_create( params, datatype, sc_str[2], b_n, &y ); libblis_test_vobj_create( params, datatype, sc_str[2], b_n, &y_save ); // Set alpha. if ( bli_obj_is_real( &y ) ) { bli_setsc( 1.2, 0.0, &alpha ); bli_setsc( -1.0, 0.0, &beta ); } else { bli_setsc( 1.2, 0.1, &alpha ); bli_setsc( -1.0, -0.1, &beta ); } // Randomize A, x, and y, and save y. libblis_test_mobj_randomize( params, FALSE, &a ); libblis_test_vobj_randomize( params, FALSE, &x ); libblis_test_vobj_randomize( params, FALSE, &y ); bli_copyv( &y, &y_save ); // Apply the parameters. bli_obj_set_conj( conjat, &a ); bli_obj_set_conj( conjx, &x ); // Repeat the experiment n_repeats times and record results. for ( i = 0; i < n_repeats; ++i ) { bli_copyv( &y_save, &y ); time = bli_clock(); libblis_test_dotxf_impl( iface, &alpha, &a, &x, &beta, &y, cntx ); time_min = bli_clock_min_diff( time_min, time ); } // Estimate the performance of the best experiment repeat. *perf = ( 2.0 * m * b_n ) / time_min / FLOPS_PER_UNIT_PERF; if ( bli_obj_is_complex( &y ) ) *perf *= 4.0; // Perform checks. libblis_test_dotxf_check( params, &alpha, &a, &x, &beta, &y, &y_save, resid ); // Zero out performance and residual if output vector is empty. libblis_test_check_empty_problem( &y, perf, resid ); // Free the test objects. bli_obj_free( &a ); bli_obj_free( &x ); bli_obj_free( &y ); bli_obj_free( &y_save ); } void libblis_test_dotxf_impl ( iface_t iface, obj_t* alpha, obj_t* a, obj_t* x, obj_t* beta, obj_t* y, cntx_t* cntx ) { switch ( iface ) { case BLIS_TEST_SEQ_FRONT_END: bli_dotxf_ex( alpha, a, x, beta, y, cntx, NULL ); break; default: libblis_test_printf_error( "Invalid interface type.\n" ); } } void libblis_test_dotxf_check ( test_params_t* params, obj_t* alpha, obj_t* a, obj_t* x, obj_t* beta, obj_t* y, obj_t* y_orig, double* resid ) { num_t dt = bli_obj_dt( y ); num_t dt_real = bli_obj_dt_proj_to_real( y ); dim_t b_n = bli_obj_vector_dim( y ); dim_t i; obj_t a1, psi1, v; obj_t norm; double junk; // // Pre-conditions: // - a is randomized. // - x is randomized. // - y is randomized. // Note: // - alpha and beta should have a non-zero imaginary component in the // complex cases in order to more fully exercise the implementation. // // Under these conditions, we assume that the implementation for // // y := beta * y_orig + alpha * conjat(A^T) * conjx(x) // // is functioning correctly if // // normfv( y - v ) // // is negligible, where v contains y as computed by repeated calls to // dotxv. // bli_obj_scalar_init_detached( dt_real, &norm ); bli_obj_create( dt, b_n, 1, 0, 0, &v ); bli_copyv( y_orig, &v ); for ( i = 0; i < b_n; ++i ) { bli_acquire_mpart_l2r( BLIS_SUBPART1, i, 1, a, &a1 ); bli_acquire_vpart_f2b( BLIS_SUBPART1, i, 1, &v, &psi1 ); bli_dotxv( alpha, &a1, x, beta, &psi1 ); } bli_subv( y, &v ); bli_normfv( &v, &norm ); bli_getsc( &norm, resid, &junk ); bli_obj_free( &v ); } blis-0.9.0/testsuite/src/test_dotxf.h000066400000000000000000000035001422157504600176310ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void libblis_test_dotxf ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); blis-0.9.0/testsuite/src/test_dotxv.c000066400000000000000000000221341422157504600176500ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "test_libblis.h" // Static variables. static char* op_str = "dotxv"; static char* o_types = "vv"; // x y static char* p_types = "cc"; // conjx conjy static thresh_t thresh[BLIS_NUM_FP_TYPES] = { { 1e-04, 1e-05 }, // warn, pass for s { 1e-04, 1e-05 }, // warn, pass for c { 1e-13, 1e-14 }, // warn, pass for d { 1e-13, 1e-14 } }; // warn, pass for z // Local prototypes. void libblis_test_dotxv_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); void libblis_test_dotxv_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ); void libblis_test_dotxv_impl ( iface_t iface, obj_t* alpha, obj_t* x, obj_t* y, obj_t* beta, obj_t* rho ); void libblis_test_dotxv_check ( test_params_t* params, obj_t* alpha, obj_t* x, obj_t* y, obj_t* beta, obj_t* rho, obj_t* rho_orig, double* resid ); void libblis_test_dotxv_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { libblis_test_randv( tdata, params, &(op->ops->randv) ); libblis_test_normfv( tdata, params, &(op->ops->normfv) ); libblis_test_copyv( tdata, params, &(op->ops->copyv) ); } void libblis_test_dotxv ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { // Return early if this test has already been done. if ( libblis_test_op_is_done( op ) ) return; // Return early if operation is disabled. if ( libblis_test_op_is_disabled( op ) || libblis_test_l1v_is_disabled( op ) ) return; // Call dependencies first. if ( TRUE ) libblis_test_dotxv_deps( tdata, params, op ); // Execute the test driver for each implementation requested. //if ( op->front_seq == ENABLE ) { libblis_test_op_driver( tdata, params, op, BLIS_TEST_SEQ_FRONT_END, op_str, p_types, o_types, thresh, libblis_test_dotxv_experiment ); } } void libblis_test_dotxv_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ) { unsigned int n_repeats = params->n_repeats; unsigned int i; double time_min = DBL_MAX; double time; num_t datatype; dim_t m; conj_t conjx, conjy, conjconjxy; obj_t alpha, x, y, beta, rho; obj_t rho_save; // Use the datatype of the first char in the datatype combination string. bli_param_map_char_to_blis_dt( dc_str[0], &datatype ); // Map the dimension specifier to an actual dimension. m = libblis_test_get_dim_from_prob_size( op->dim_spec[0], p_cur ); // Map parameter characters to BLIS constants. bli_param_map_char_to_blis_conj( pc_str[0], &conjx ); bli_param_map_char_to_blis_conj( pc_str[1], &conjy ); // Create test scalars. bli_obj_scalar_init_detached( datatype, &alpha ); bli_obj_scalar_init_detached( datatype, &beta ); bli_obj_scalar_init_detached( datatype, &rho ); bli_obj_scalar_init_detached( datatype, &rho_save ); // Create test operands (vectors and/or matrices). libblis_test_vobj_create( params, datatype, sc_str[0], m, &x ); libblis_test_vobj_create( params, datatype, sc_str[1], m, &y ); // Initialize alpha, beta, and rho. bli_copysc( &BLIS_ONE, &alpha ); bli_copysc( &BLIS_ZERO, &beta ); bli_copysc( &BLIS_MINUS_ONE, &rho ); bli_copysc( &rho, &rho_save ); // Randomize x. libblis_test_vobj_randomize( params, TRUE, &x ); // Determine whether to make a copy of x with or without conjugation. // // conjx conjy ~conjx^conjy y is initialized as // n n c y = conj(x) // n c n y = x // c n n y = x // c c c y = conj(x) // conjconjxy = bli_apply_conj( conjx, conjy ); conjconjxy = bli_conj_toggled( conjconjxy ); bli_obj_set_conj( conjconjxy, &x ); bli_copyv( &x, &y ); // Apply the parameters. bli_obj_set_conj( conjx, &x ); bli_obj_set_conj( conjy, &y ); // Repeat the experiment n_repeats times and record results. for ( i = 0; i < n_repeats; ++i ) { bli_copysc( &rho_save, &rho ); time = bli_clock(); libblis_test_dotxv_impl( iface, &alpha, &x, &y, &beta, &rho ); time_min = bli_clock_min_diff( time_min, time ); } // Estimate the performance of the best experiment repeat. *perf = ( 2.0 * m ) / time_min / FLOPS_PER_UNIT_PERF; if ( bli_obj_is_complex( &y ) ) *perf *= 4.0; // Perform checks. libblis_test_dotxv_check( params, &alpha, &x, &y, &beta, &rho, &rho_save, resid ); // Zero out performance and residual if output scalar is empty. libblis_test_check_empty_problem( &rho, perf, resid ); // Free the test objects. bli_obj_free( &x ); bli_obj_free( &y ); } void libblis_test_dotxv_impl ( iface_t iface, obj_t* alpha, obj_t* x, obj_t* y, obj_t* beta, obj_t* rho ) { switch ( iface ) { case BLIS_TEST_SEQ_FRONT_END: bli_dotxv( alpha, x, y, beta, rho ); break; default: libblis_test_printf_error( "Invalid interface type.\n" ); } } void libblis_test_dotxv_check ( test_params_t* params, obj_t* alpha, obj_t* x, obj_t* y, obj_t* beta, obj_t* rho, obj_t* rho_orig, double* resid ) { num_t dt_real = bli_obj_dt_proj_to_real( y ); obj_t rho_r, rho_i; obj_t norm_x_r, norm_xy_r; obj_t temp_r; double zero; double junk; // // Pre-conditions: // - x is randomized. // - y is equal to conjx(conjy(x)). // - alpha must be real-valued. // - beta must be zero. // Note: // - We forgo fully exercising beta scaling in order to simplify the // test. // // Under these conditions, we assume that the implementation for // // rho := beta * rho_orig + alpha * conjx(x^T) conjy(y) // // is functioning correctly if // // sqrtsc( rho.real ) - sqrtsc( alpha ) * normfv( x ) // // and // // rho.imag // // are negligible. // bli_obj_scalar_init_detached( dt_real, &rho_r ); bli_obj_scalar_init_detached( dt_real, &rho_i ); bli_obj_scalar_init_detached( dt_real, &norm_x_r ); bli_obj_scalar_init_detached( dt_real, &norm_xy_r ); bli_obj_scalar_init_detached( dt_real, &temp_r ); bli_copysc( alpha, &temp_r ); bli_sqrtsc( &temp_r, &temp_r ); bli_normfv( x, &norm_x_r ); bli_mulsc( &temp_r, &norm_x_r ); bli_unzipsc( rho, &rho_r, &rho_i ); bli_sqrtsc( &rho_r, &norm_xy_r ); bli_subsc( &norm_x_r, &norm_xy_r ); bli_getsc( &norm_xy_r, resid, &junk ); bli_getsc( &rho_i, &zero, &junk ); *resid = bli_fmaxabs( *resid, zero ); } blis-0.9.0/testsuite/src/test_dotxv.h000066400000000000000000000035001422157504600176510ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void libblis_test_dotxv ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); blis-0.9.0/testsuite/src/test_gemm.c000066400000000000000000000461601422157504600174360ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "test_libblis.h" // Static variables. static char* op_str = "gemm"; static char* o_types = "mmm"; // a b c static char* p_types = "hh"; // transa transb static thresh_t thresh[BLIS_NUM_FP_TYPES] = { { 1e-04, 1e-05 }, // warn, pass for s { 1e-04, 1e-05 }, // warn, pass for c { 1e-13, 1e-14 }, // warn, pass for d { 1e-13, 1e-14 } }; // warn, pass for z // Local prototypes. void libblis_test_gemm_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); void libblis_test_gemm_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ); void libblis_test_gemm_md ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ); void libblis_test_gemm_impl ( iface_t iface, obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c ); void libblis_test_gemm_check ( test_params_t* params, obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, obj_t* c_orig, double* resid ); void libblis_test_gemm_md_check ( test_params_t* params, obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, obj_t* c_orig, double* resid ); double libblis_test_gemm_flops ( obj_t* a, obj_t* b, obj_t* c ); void libblis_test_gemm_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { libblis_test_randv( tdata, params, &(op->ops->randv) ); libblis_test_randm( tdata, params, &(op->ops->randm) ); libblis_test_setv( tdata, params, &(op->ops->setv) ); libblis_test_normfv( tdata, params, &(op->ops->normfv) ); libblis_test_subv( tdata, params, &(op->ops->subv) ); libblis_test_scalv( tdata, params, &(op->ops->scalv) ); libblis_test_copym( tdata, params, &(op->ops->copym) ); libblis_test_scalm( tdata, params, &(op->ops->scalm) ); libblis_test_gemv( tdata, params, &(op->ops->gemv) ); } void libblis_test_gemm ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { // Return early if this test has already been done. if ( libblis_test_op_is_done( op ) ) return; // Return early if operation is disabled. if ( libblis_test_op_is_disabled( op ) || libblis_test_l3_is_disabled( op ) ) return; // Call dependencies first. if ( TRUE ) libblis_test_gemm_deps( tdata, params, op ); // Execute the test driver for each implementation requested. //if ( op->front_seq == ENABLE ) { libblis_test_op_driver( tdata, params, op, BLIS_TEST_SEQ_FRONT_END, op_str, p_types, o_types, thresh, libblis_test_gemm_experiment ); } } void libblis_test_gemm_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ) { unsigned int n_repeats = params->n_repeats; unsigned int i; double time_min = DBL_MAX; double time; num_t datatype; dim_t m, n, k; trans_t transa; trans_t transb; obj_t alpha, a, b, beta, c; obj_t c_save; // Use a different function to handle mixed datatypes. if ( params->mixed_domain || params->mixed_precision ) { libblis_test_gemm_md( params, op, iface, dc_str, pc_str, sc_str, p_cur, perf, resid ); return; } // Use the datatype of the first char in the datatype combination string. bli_param_map_char_to_blis_dt( dc_str[0], &datatype ); // Map the dimension specifier to actual dimensions. m = libblis_test_get_dim_from_prob_size( op->dim_spec[0], p_cur ); n = libblis_test_get_dim_from_prob_size( op->dim_spec[1], p_cur ); k = libblis_test_get_dim_from_prob_size( op->dim_spec[2], p_cur ); // Map parameter characters to BLIS constants. bli_param_map_char_to_blis_trans( pc_str[0], &transa ); bli_param_map_char_to_blis_trans( pc_str[1], &transb ); // Create test scalars. bli_obj_scalar_init_detached( datatype, &alpha ); bli_obj_scalar_init_detached( datatype, &beta ); // Create test operands (vectors and/or matrices). libblis_test_mobj_create( params, datatype, transa, sc_str[1], m, k, &a ); libblis_test_mobj_create( params, datatype, transb, sc_str[2], k, n, &b ); libblis_test_mobj_create( params, datatype, BLIS_NO_TRANSPOSE, sc_str[0], m, n, &c ); libblis_test_mobj_create( params, datatype, BLIS_NO_TRANSPOSE, sc_str[0], m, n, &c_save ); // Set alpha and beta. if ( bli_obj_is_real( &c ) ) { bli_setsc( 1.2, 0.0, &alpha ); bli_setsc( 0.9, 0.0, &beta ); } else { bli_setsc( 1.2, 0.8, &alpha ); bli_setsc( 0.9, 1.0, &beta ); } #if 0 //bli_setm( &BLIS_ONE, &a ); bli_setsc( 1.0, 0.0, &alpha ); bli_setsc( 1.0, 0.0, &beta ); #endif // Randomize A, B, and C, and save C. libblis_test_mobj_randomize( params, TRUE, &a ); libblis_test_mobj_randomize( params, TRUE, &b ); libblis_test_mobj_randomize( params, TRUE, &c ); bli_copym( &c, &c_save ); // Apply the parameters. bli_obj_set_conjtrans( transa, &a ); bli_obj_set_conjtrans( transb, &b ); // Repeat the experiment n_repeats times and record results. for ( i = 0; i < n_repeats; ++i ) { bli_copym( &c_save, &c ); time = bli_clock(); libblis_test_gemm_impl( iface, &alpha, &a, &b, &beta, &c ); time_min = bli_clock_min_diff( time_min, time ); } // Estimate the performance of the best experiment repeat. *perf = ( 2.0 * m * n * k ) / time_min / FLOPS_PER_UNIT_PERF; if ( bli_obj_is_complex( &c ) ) *perf *= 4.0; // Perform checks. libblis_test_gemm_check( params, &alpha, &a, &b, &beta, &c, &c_save, resid ); // Zero out performance and residual if output matrix is empty. libblis_test_check_empty_problem( &c, perf, resid ); // Free the test objects. bli_obj_free( &a ); bli_obj_free( &b ); bli_obj_free( &c ); bli_obj_free( &c_save ); } void libblis_test_gemm_md ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ) { unsigned int n_repeats = params->n_repeats; unsigned int i; double time_min = DBL_MAX; double time; num_t dt_a, dt_b, dt_c; num_t dt_complex; dim_t m, n, k; trans_t transa; trans_t transb; obj_t alpha, a, b, beta, c; obj_t c_save; // Decode the datatype combination string. bli_param_map_char_to_blis_dt( dc_str[0], &dt_c ); bli_param_map_char_to_blis_dt( dc_str[1], &dt_a ); bli_param_map_char_to_blis_dt( dc_str[2], &dt_b ); // Project one of the datatypes (it doesn't matter which) to the // complex domain. dt_complex = bli_dt_proj_to_complex( dt_c ); // Map the dimension specifier to actual dimensions. m = libblis_test_get_dim_from_prob_size( op->dim_spec[0], p_cur ); n = libblis_test_get_dim_from_prob_size( op->dim_spec[1], p_cur ); k = libblis_test_get_dim_from_prob_size( op->dim_spec[2], p_cur ); // Map parameter characters to BLIS constants. bli_param_map_char_to_blis_trans( pc_str[0], &transa ); bli_param_map_char_to_blis_trans( pc_str[1], &transb ); // Create test scalars. bli_obj_scalar_init_detached( dt_complex, &alpha ); bli_obj_scalar_init_detached( dt_complex, &beta ); // Create test operands (vectors and/or matrices). libblis_test_mobj_create( params, dt_a, transa, sc_str[1], m, k, &a ); libblis_test_mobj_create( params, dt_b, transb, sc_str[2], k, n, &b ); libblis_test_mobj_create( params, dt_c, BLIS_NO_TRANSPOSE, sc_str[0], m, n, &c ); libblis_test_mobj_create( params, dt_c, BLIS_NO_TRANSPOSE, sc_str[0], m, n, &c_save ); // For mixed-precision, set the computation precision of C. if ( params->mixed_precision ) { num_t dt_comp; prec_t comp_prec; // The computation precision is encoded in the computation datatype, // which appears as an additional char in dc_str. bli_param_map_char_to_blis_dt( dc_str[3], &dt_comp ); // Extract the precision from the computation datatype. comp_prec = bli_dt_prec( dt_comp ); // Set the computation precision of C. bli_obj_set_comp_prec( comp_prec, &c ); } // Set alpha and beta. { bli_setsc( 2.0, 0.0, &alpha ); bli_setsc( 1.2, 0.5, &beta ); //bli_setsc( 1.0, 0.0, &alpha ); //bli_setsc( 1.0, 0.0, &beta ); } // Randomize A, B, and C, and save C. libblis_test_mobj_randomize( params, TRUE, &a ); libblis_test_mobj_randomize( params, TRUE, &b ); libblis_test_mobj_randomize( params, TRUE, &c ); bli_copym( &c, &c_save ); // Apply the parameters. bli_obj_set_conjtrans( transa, &a ); bli_obj_set_conjtrans( transb, &b ); // Repeat the experiment n_repeats times and record results. for ( i = 0; i < n_repeats; ++i ) { bli_copym( &c_save, &c ); time = bli_clock(); libblis_test_gemm_impl( iface, &alpha, &a, &b, &beta, &c ); time_min = bli_clock_min_diff( time_min, time ); } // Estimate the performance of the best experiment repeat. //*perf = ( 2.0 * m * n * k ) / time_min / FLOPS_PER_UNIT_PERF; //if ( bli_obj_is_complex( &c ) ) *perf *= 4.0; *perf = libblis_test_gemm_flops( &a, &b, &c ) / time_min / FLOPS_PER_UNIT_PERF; // Perform checks. libblis_test_gemm_md_check( params, &alpha, &a, &b, &beta, &c, &c_save, resid ); // Zero out performance and residual if output matrix is empty. libblis_test_check_empty_problem( &c, perf, resid ); // Free the test objects. bli_obj_free( &a ); bli_obj_free( &b ); bli_obj_free( &c ); bli_obj_free( &c_save ); } void libblis_test_gemm_impl ( iface_t iface, obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c ) { switch ( iface ) { case BLIS_TEST_SEQ_FRONT_END: #if 0 //bli_printm( "alpha", alpha, "%5.2f", "" ); //bli_printm( "beta", beta, "%5.2f", "" ); if ( bli_obj_dt( c ) == BLIS_DCOMPLEX ) { bli_printm( "a", a, "%5.2f", "" ); bli_printm( "b", b, "%5.2f", "" ); bli_printm( "c", c, "%5.2f", "" ); } #endif //if ( bli_obj_length( b ) == 16 && // bli_obj_stor3_from_strides( c, a, b ) == BLIS_CRR ) //bli_printm( "c before", c, "%6.3f", "" ); bli_gemm( alpha, a, b, beta, c ); //bls_gemm( alpha, a, b, beta, c ); #if 0 if ( bli_obj_dt( c ) == BLIS_DCOMPLEX ) bli_printm( "c after", c, "%6.3f", "" ); #endif //bli_printm( "c after", c, "%5.2f", "" ); break; default: libblis_test_printf_error( "Invalid interface type.\n" ); } } void libblis_test_gemm_md_check ( test_params_t* params, obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, obj_t* c_orig, double* resid ) { num_t dt_real = bli_obj_dt_proj_to_real( c ); num_t dt_comp = bli_obj_dt_proj_to_complex( c ); num_t dt; dim_t m = bli_obj_length( c ); dim_t n = bli_obj_width( c ); dim_t k = bli_obj_width_after_trans( a ); obj_t norm; obj_t t, v, w, z; double junk; // Compute our reference checksum in the real domain if all operands // are real, and in the complex domain otherwise. Also implicit in this // is that we use the storage precision of C to determine the precision // in which we perform the reference checksum. if ( bli_obj_is_real( a ) && bli_obj_is_real( b ) && bli_obj_is_real( c ) ) dt = dt_real; else dt = dt_comp; // This function works in a manner similar to that of the function // libblis_test_gemm_check(), except that we project a, b, and c into // the complex domain (regardless of their storage datatype), and then // proceed with the checking accordingly. obj_t a2, b2, c2, c0; bli_obj_scalar_init_detached( dt_real, &norm ); bli_obj_create( dt, n, 1, 0, 0, &t ); bli_obj_create( dt, m, 1, 0, 0, &v ); bli_obj_create( dt, k, 1, 0, 0, &w ); bli_obj_create( dt, m, 1, 0, 0, &z ); libblis_test_vobj_randomize( params, TRUE, &t ); // We need to zero out the imaginary part of t in order for our // checks to work in all cases. Otherwise, the imaginary parts // could affect intermediate products, depending on the order that // they are executed. bli_setiv( &BLIS_ZERO, &t ); // Create complex equivalents of a, b, c_orig, and c. bli_obj_create( dt, m, k, 0, 0, &a2 ); bli_obj_create( dt, k, n, 0, 0, &b2 ); bli_obj_create( dt, m, n, 0, 0, &c2 ); bli_obj_create( dt, m, n, 0, 0, &c0 ); // Cast a, b, c_orig, and c into the datatype of our temporary objects. bli_castm( a, &a2 ); bli_castm( b, &b2 ); bli_castm( c_orig, &c2 ); bli_castm( c, &c0 ); bli_gemv( &BLIS_ONE, &c0, &t, &BLIS_ZERO, &v ); #if 0 if ( bli_obj_is_scomplex( c ) && bli_obj_is_float( a ) && bli_obj_is_float( b ) ) { bli_printm( "test_gemm.c: a", a, "%7.3f", "" ); bli_printm( "test_gemm.c: b", b, "%7.3f", "" ); bli_printm( "test_gemm.c: c orig", c_orig, "%7.3f", "" ); bli_printm( "test_gemm.c: c computed", c, "%7.3f", "" ); } #endif #if 0 bli_gemm( alpha, &a2, &b2, beta, &c2 ); bli_gemv( &BLIS_ONE, &c2, &t, &BLIS_ZERO, &z ); if ( bli_obj_is_real( c ) ) bli_setiv( &BLIS_ZERO, &z ); #else bli_gemv( &BLIS_ONE, &b2, &t, &BLIS_ZERO, &w ); bli_gemv( alpha, &a2, &w, &BLIS_ZERO, &z ); bli_gemv( beta, &c2, &t, &BLIS_ONE, &z ); if ( bli_obj_is_real( c ) ) bli_setiv( &BLIS_ZERO, &z ); #endif bli_subv( &z, &v ); bli_normfv( &v, &norm ); bli_getsc( &norm, resid, &junk ); bli_obj_free( &t ); bli_obj_free( &v ); bli_obj_free( &w ); bli_obj_free( &z ); bli_obj_free( &a2 ); bli_obj_free( &b2 ); bli_obj_free( &c2 ); bli_obj_free( &c0 ); } void libblis_test_gemm_check ( test_params_t* params, obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, obj_t* c_orig, double* resid ) { num_t dt = bli_obj_dt( c ); num_t dt_real = bli_obj_dt_proj_to_real( c ); dim_t m = bli_obj_length( c ); dim_t n = bli_obj_width( c ); dim_t k = bli_obj_width_after_trans( a ); obj_t norm; obj_t t, v, w, z; double junk; // // Pre-conditions: // - a is randomized. // - b is randomized. // - c_orig is randomized. // Note: // - alpha and beta should have non-zero imaginary components in the // complex cases in order to more fully exercise the implementation. // // Under these conditions, we assume that the implementation for // // C := beta * C_orig + alpha * transa(A) * transb(B) // // is functioning correctly if // // normfv( v - z ) // // is negligible, where // // v = C * t // z = ( beta * C_orig + alpha * transa(A) * transb(B) ) * t // = beta * C_orig * t + alpha * transa(A) * transb(B) * t // = beta * C_orig * t + alpha * transa(A) * w // = beta * C_orig * t + z // bli_obj_scalar_init_detached( dt_real, &norm ); bli_obj_create( dt, n, 1, 0, 0, &t ); bli_obj_create( dt, m, 1, 0, 0, &v ); bli_obj_create( dt, k, 1, 0, 0, &w ); bli_obj_create( dt, m, 1, 0, 0, &z ); libblis_test_vobj_randomize( params, TRUE, &t ); bli_gemv( &BLIS_ONE, c, &t, &BLIS_ZERO, &v ); bli_gemv( &BLIS_ONE, b, &t, &BLIS_ZERO, &w ); bli_gemv( alpha, a, &w, &BLIS_ZERO, &z ); bli_gemv( beta, c_orig, &t, &BLIS_ONE, &z ); bli_subv( &z, &v ); bli_normfv( &v, &norm ); bli_getsc( &norm, resid, &junk ); bli_obj_free( &t ); bli_obj_free( &v ); bli_obj_free( &w ); bli_obj_free( &z ); } double libblis_test_gemm_flops ( obj_t* a, obj_t* b, obj_t* c ) { bool a_is_real = bli_obj_is_real( a ); bool a_is_complex = bli_obj_is_complex( a ); bool b_is_real = bli_obj_is_real( b ); bool b_is_complex = bli_obj_is_complex( b ); bool c_is_real = bli_obj_is_real( c ); bool c_is_complex = bli_obj_is_complex( c ); double m = ( double )bli_obj_length( c ); double n = ( double )bli_obj_width( c ); double k = ( double )bli_obj_width( a ); double flops; if ( ( c_is_complex && a_is_complex && b_is_complex ) ) { flops = 8.0 * m * n * k; } else if ( ( c_is_complex && a_is_complex && b_is_real ) || ( c_is_complex && a_is_real && b_is_complex ) || ( c_is_real && a_is_complex && b_is_complex ) ) { flops = 4.0 * m * n * k; } else { flops = 2.0 * m * n * k; } return flops; } blis-0.9.0/testsuite/src/test_gemm.h000066400000000000000000000034771422157504600174470ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void libblis_test_gemm ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); blis-0.9.0/testsuite/src/test_gemm_ukr.c000066400000000000000000000255271422157504600203230ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "test_libblis.h" // Static variables. static char* op_str = "gemm_ukr"; static char* o_types = "m"; // c static char* p_types = ""; static thresh_t thresh[BLIS_NUM_FP_TYPES] = { { 1e-04, 1e-05 }, // warn, pass for s { 1e-04, 1e-05 }, // warn, pass for c { 1e-13, 1e-14 }, // warn, pass for d { 1e-13, 1e-14 } }; // warn, pass for z // Local prototypes. void libblis_test_gemm_ukr_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); void libblis_test_gemm_ukr_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ); void libblis_test_gemm_ukr_impl ( iface_t iface, obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx ); void libblis_test_gemm_ukr_check ( test_params_t* params, obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, obj_t* c_orig, double* resid ); void libblis_test_gemm_ukr_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { libblis_test_randv( tdata, params, &(op->ops->randv) ); libblis_test_randm( tdata, params, &(op->ops->randm) ); libblis_test_setv( tdata, params, &(op->ops->setv) ); libblis_test_normfv( tdata, params, &(op->ops->normfv) ); libblis_test_subv( tdata, params, &(op->ops->subv) ); libblis_test_scalv( tdata, params, &(op->ops->scalv) ); libblis_test_copym( tdata, params, &(op->ops->copym) ); libblis_test_scalm( tdata, params, &(op->ops->scalm) ); libblis_test_gemv( tdata, params, &(op->ops->gemv) ); } void libblis_test_gemm_ukr ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { // Return early if this test has already been done. if ( libblis_test_op_is_done( op ) ) return; // Return early if operation is disabled. if ( libblis_test_op_is_disabled( op ) || libblis_test_l3ukr_is_disabled( op ) ) return; // Call dependencies first. if ( TRUE ) libblis_test_gemm_ukr_deps( tdata, params, op ); // Execute the test driver for each implementation requested. //if ( op->front_seq == ENABLE ) { libblis_test_op_driver( tdata, params, op, BLIS_TEST_SEQ_UKERNEL, op_str, p_types, o_types, thresh, libblis_test_gemm_ukr_experiment ); } } void libblis_test_gemm_ukr_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ) { unsigned int n_repeats = params->n_repeats; unsigned int i; double time_min = DBL_MAX; double time; num_t datatype; dim_t m, n, k; char sc_a = 'c'; char sc_b = 'r'; obj_t alpha, a, b, beta, c; obj_t ap, bp; obj_t c_save; cntx_t* cntx; // Query a context. cntx = bli_gks_query_cntx(); // Use the datatype of the first char in the datatype combination string. bli_param_map_char_to_blis_dt( dc_str[0], &datatype ); // Map the dimension specifier to actual dimensions. k = libblis_test_get_dim_from_prob_size( op->dim_spec[0], p_cur ); // Fix m and n to MR and NR, respectively. m = bli_cntx_get_blksz_def_dt( datatype, BLIS_MR, cntx ); n = bli_cntx_get_blksz_def_dt( datatype, BLIS_NR, cntx ); // Store the register blocksizes so that the driver can retrieve the // values later when printing results. op->dim_aux[0] = m; op->dim_aux[1] = n; // Create test scalars. bli_obj_scalar_init_detached( datatype, &alpha ); bli_obj_scalar_init_detached( datatype, &beta ); // Create test operands. libblis_test_mobj_create( params, datatype, BLIS_NO_TRANSPOSE, sc_a, m, k, &a ); libblis_test_mobj_create( params, datatype, BLIS_NO_TRANSPOSE, sc_b, k, n, &b ); libblis_test_mobj_create( params, datatype, BLIS_NO_TRANSPOSE, sc_str[0], m, n, &c ); libblis_test_mobj_create( params, datatype, BLIS_NO_TRANSPOSE, sc_str[0], m, n, &c_save ); // Set alpha and beta. if ( bli_obj_is_real( &c ) ) { bli_setsc( 1.2, 0.0, &alpha ); bli_setsc( -1.0, 0.0, &beta ); //bli_setsc( 0.0, 0.0, &beta ); } else { bli_setsc( 1.2, 0.8, &alpha ); bli_setsc( -1.0, 0.5, &beta ); } // Randomize A, B, and C, and save C. libblis_test_mobj_randomize( params, TRUE, &a ); libblis_test_mobj_randomize( params, TRUE, &b ); libblis_test_mobj_randomize( params, TRUE, &c ); bli_copym( &c, &c_save ); rntm_t rntm; bli_rntm_init( &rntm ); bli_pba_rntm_set_pba( &rntm ); // Transpose B to B^T for packing. bli_obj_induce_trans( &b ); // Create pack objects for a and b, and pack them to ap and bp, // respectively. cntl_t* cntl_a = libblis_test_pobj_create ( BLIS_MR, BLIS_KR, BLIS_NO_INVERT_DIAG, BLIS_PACKED_ROW_PANELS, BLIS_BUFFER_FOR_A_BLOCK, &a, &ap, cntx, &rntm ); cntl_t* cntl_b = libblis_test_pobj_create ( BLIS_NR, BLIS_KR, BLIS_NO_INVERT_DIAG, BLIS_PACKED_COL_PANELS, BLIS_BUFFER_FOR_B_PANEL, &b, &bp, cntx, &rntm ); // Transpose B^T back to B and Bp^T back to Bp. bli_obj_induce_trans( &b ); bli_obj_induce_trans( &bp ); // Repeat the experiment n_repeats times and record results. for ( i = 0; i < n_repeats; ++i ) { bli_copym( &c_save, &c ); time = bli_clock(); libblis_test_gemm_ukr_impl( iface, &alpha, &ap, &bp, &beta, &c, cntx ); time_min = bli_clock_min_diff( time_min, time ); } // Estimate the performance of the best experiment repeat. *perf = ( 2.0 * m * n * k ) / time_min / FLOPS_PER_UNIT_PERF; if ( bli_obj_is_complex( &c ) ) *perf *= 4.0; // Perform checks. libblis_test_gemm_ukr_check( params, &alpha, &a, &b, &beta, &c, &c_save, resid ); // Zero out performance and residual if output matrix is empty. libblis_test_check_empty_problem( &c, perf, resid ); // Free the control tree nodes and release their cached mem_t entries // back to the pba. bli_cntl_free( &rntm, cntl_a, &BLIS_PACKM_SINGLE_THREADED ); bli_cntl_free( &rntm, cntl_b, &BLIS_PACKM_SINGLE_THREADED ); // Free the test objects. bli_obj_free( &a ); bli_obj_free( &b ); bli_obj_free( &c ); bli_obj_free( &c_save ); } void libblis_test_gemm_ukr_impl ( iface_t iface, obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, cntx_t* cntx ) { switch ( iface ) { case BLIS_TEST_SEQ_UKERNEL: bli_gemm_ukernel( alpha, a, b, beta, c, cntx ); break; default: libblis_test_printf_error( "Invalid interface type.\n" ); } } void libblis_test_gemm_ukr_check ( test_params_t* params, obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, obj_t* c_orig, double* resid ) { num_t dt = bli_obj_dt( c ); num_t dt_real = bli_obj_dt_proj_to_real( c ); dim_t m = bli_obj_length( c ); dim_t n = bli_obj_width( c ); dim_t k = bli_obj_width( a ); obj_t norm; obj_t t, v, w, z; double junk; // // Pre-conditions: // - a is randomized. // - b is randomized. // - c_orig is randomized. // Note: // - alpha and beta should have non-zero imaginary components in the // complex cases in order to more fully exercise the implementation. // // Under these conditions, we assume that the implementation for // // C := beta * C_orig + alpha * A * B // // is functioning correctly if // // normfv( v - z ) // // is negligible, where // // v = C * t // z = ( beta * C_orig + alpha * A * B ) * t // = beta * C_orig * t + alpha * A * B * t // = beta * C_orig * t + alpha * A * w // = beta * C_orig * t + z // bli_obj_scalar_init_detached( dt_real, &norm ); bli_obj_create( dt, n, 1, 0, 0, &t ); bli_obj_create( dt, m, 1, 0, 0, &v ); bli_obj_create( dt, k, 1, 0, 0, &w ); bli_obj_create( dt, m, 1, 0, 0, &z ); libblis_test_vobj_randomize( params, TRUE, &t ); bli_gemv( &BLIS_ONE, c, &t, &BLIS_ZERO, &v ); bli_gemv( &BLIS_ONE, b, &t, &BLIS_ZERO, &w ); bli_gemv( alpha, a, &w, &BLIS_ZERO, &z ); bli_gemv( beta, c_orig, &t, &BLIS_ONE, &z ); bli_subv( &z, &v ); bli_normfv( &v, &norm ); bli_getsc( &norm, resid, &junk ); bli_obj_free( &t ); bli_obj_free( &v ); bli_obj_free( &w ); bli_obj_free( &z ); } blis-0.9.0/testsuite/src/test_gemm_ukr.h000066400000000000000000000035031422157504600203160ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void libblis_test_gemm_ukr ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); blis-0.9.0/testsuite/src/test_gemmt.c000066400000000000000000000257641422157504600176310ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "test_libblis.h" // Static variables. static char* op_str = "gemmt"; static char* o_types = "mmm"; // a b c static char* p_types = "uhh"; // uploc transa transb static thresh_t thresh[BLIS_NUM_FP_TYPES] = { { 1e-04, 1e-05 }, // warn, pass for s { 1e-04, 1e-05 }, // warn, pass for c { 1e-13, 1e-14 }, // warn, pass for d { 1e-13, 1e-14 } }; // warn, pass for z // Local prototypes. void libblis_test_gemmt_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); void libblis_test_gemmt_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ); void libblis_test_gemmt_impl ( iface_t iface, obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c ); void libblis_test_gemmt_check ( test_params_t* params, obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, obj_t* c_orig, double* resid ); void libblis_test_gemmt_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { libblis_test_randv( tdata, params, &(op->ops->randv) ); libblis_test_randm( tdata, params, &(op->ops->randm) ); libblis_test_setv( tdata, params, &(op->ops->setv) ); libblis_test_normfv( tdata, params, &(op->ops->normfv) ); libblis_test_subv( tdata, params, &(op->ops->subv) ); libblis_test_scalv( tdata, params, &(op->ops->scalv) ); libblis_test_copym( tdata, params, &(op->ops->copym) ); libblis_test_scalm( tdata, params, &(op->ops->scalm) ); libblis_test_gemv( tdata, params, &(op->ops->gemv) ); libblis_test_gemm( tdata, params, &(op->ops->gemm) ); } void libblis_test_gemmt ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { // Return early if this test has already been done. if ( libblis_test_op_is_done( op ) ) return; // Return early if operation is disabled. if ( libblis_test_op_is_disabled( op ) || libblis_test_l3_is_disabled( op ) ) return; // Call dependencies first. if ( TRUE ) libblis_test_gemmt_deps( tdata, params, op ); // Execute the test driver for each implementation requested. //if ( op->front_seq == ENABLE ) { libblis_test_op_driver( tdata, params, op, BLIS_TEST_SEQ_FRONT_END, op_str, p_types, o_types, thresh, libblis_test_gemmt_experiment ); } } void libblis_test_gemmt_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ) { unsigned int n_repeats = params->n_repeats; unsigned int i; double time_min = DBL_MAX; double time; num_t datatype; dim_t m, k; uplo_t uploc; trans_t transa; trans_t transb; obj_t alpha, a, b, beta, c; obj_t c_save; // Use the datatype of the first char in the datatype combination string. bli_param_map_char_to_blis_dt( dc_str[0], &datatype ); // Map the dimension specifier to actual dimensions. m = libblis_test_get_dim_from_prob_size( op->dim_spec[0], p_cur ); k = libblis_test_get_dim_from_prob_size( op->dim_spec[1], p_cur ); // Map parameter characters to BLIS constants. bli_param_map_char_to_blis_uplo( pc_str[0], &uploc ); bli_param_map_char_to_blis_trans( pc_str[1], &transa ); bli_param_map_char_to_blis_trans( pc_str[2], &transb ); // Create test scalars. bli_obj_scalar_init_detached( datatype, &alpha ); bli_obj_scalar_init_detached( datatype, &beta ); // Create test operands (vectors and/or matrices). libblis_test_mobj_create( params, datatype, transa, sc_str[1], m, k, &a ); libblis_test_mobj_create( params, datatype, transb, sc_str[2], k, m, &b ); libblis_test_mobj_create( params, datatype, BLIS_NO_TRANSPOSE, sc_str[0], m, m, &c ); libblis_test_mobj_create( params, datatype, BLIS_NO_TRANSPOSE, sc_str[0], m, m, &c_save ); // Set alpha and beta. if ( bli_obj_is_real( &c ) ) { bli_setsc( 1.2, 0.0, &alpha ); bli_setsc( 0.9, 0.0, &beta ); } else { bli_setsc( 1.2, 0.8, &alpha ); bli_setsc( 0.9, 1.0, &beta ); } // Randomize A and B. libblis_test_mobj_randomize( params, TRUE, &a ); libblis_test_mobj_randomize( params, TRUE, &b ); //bli_setm( &BLIS_ONE, &a ); //bli_setm( &BLIS_ONE, &b ); //bli_setsc( 1.0, 0.0, &alpha ); //bli_setsc( 0.0, 0.0, &beta ); // Set the uplo property of C. bli_obj_set_uplo( uploc, &c ); // Randomize C, make it densely symmetric, and zero the unstored triangle // to ensure the implementation reads only from the stored region. libblis_test_mobj_randomize( params, TRUE, &c ); bli_mksymm( &c ); bli_mktrim( &c ); // Save C and set its uplo property. bli_setm( &BLIS_ZERO, &c_save ); bli_obj_set_uplo( uploc, &c_save ); bli_copym( &c, &c_save ); // Apply the parameters. bli_obj_set_conjtrans( transa, &a ); bli_obj_set_conjtrans( transb, &b ); // Repeat the experiment n_repeats times and record results. for ( i = 0; i < n_repeats; ++i ) { bli_copym( &c_save, &c ); time = bli_clock(); libblis_test_gemmt_impl( iface, &alpha, &a, &b, &beta, &c ); time_min = bli_clock_min_diff( time_min, time ); } // Estimate the performance of the best experiment repeat. *perf = ( 1.0 * m * m * k ) / time_min / FLOPS_PER_UNIT_PERF; if ( bli_obj_is_complex( &c ) ) *perf *= 4.0; // Perform checks. libblis_test_gemmt_check( params, &alpha, &a, &b, &beta, &c, &c_save, resid ); // Zero out performance and residual if output matrix is empty. libblis_test_check_empty_problem( &c, perf, resid ); // Free the test objects. bli_obj_free( &a ); bli_obj_free( &b ); bli_obj_free( &c ); bli_obj_free( &c_save ); } void libblis_test_gemmt_impl ( iface_t iface, obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c ) { switch ( iface ) { case BLIS_TEST_SEQ_FRONT_END: #if 0 //bli_printm( "alpha", alpha, "%5.2f", "" ); //bli_printm( "beta", beta, "%5.2f", "" ); bli_printm( "a", a, "%5.2f", "" ); bli_printm( "b", b, "%5.2f", "" ); bli_printm( "c", c, "%5.2f", "" ); #endif //if ( bli_obj_length( b ) == 16 && // bli_obj_stor3_from_strides( c, a, b ) == BLIS_CRR ) //bli_printm( "c before", c, "%6.3f", "" ); bli_gemmt( alpha, a, b, beta, c ); #if 0 //if ( bli_obj_length( c ) == 12 && // bli_obj_stor3_from_strides( c, a, b ) == BLIS_RRR ) bli_printm( "c after", c, "%5.2f", "" ); #endif break; default: libblis_test_printf_error( "Invalid interface type.\n" ); } } void libblis_test_gemmt_check ( test_params_t* params, obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, obj_t* c_orig, double* resid ) { num_t dt = bli_obj_dt( c ); num_t dt_real = bli_obj_dt_proj_to_real( c ); uplo_t uploc = bli_obj_uplo( c ); dim_t m = bli_obj_length( c ); //dim_t k = bli_obj_width_after_trans( a ); obj_t norm; obj_t t, v, q, z; double junk; // // Pre-conditions: // - a is randomized. // - b is randomized. // - c_orig is randomized. // Note: // - alpha and beta should have non-zero imaginary components in the // complex cases in order to more fully exercise the implementation. // // Under these conditions, we assume that the implementation for // // C := beta * C_orig + alpha * transa(A) * transb(B) // // is functioning correctly if // // normfv( v - z ) // // is negligible, where // // v = C * t // z = ( beta * C_orig + alpha * transa(A) * transb(B) ) * t // = beta * C_orig * t + alpha * transa(A) * transb(B) * t // = beta * C_orig * t + alpha * uplo(Q) * t // = beta * C_orig * t + z // bli_obj_scalar_init_detached( dt_real, &norm ); bli_obj_create( dt, m, 1, 0, 0, &t ); bli_obj_create( dt, m, 1, 0, 0, &v ); bli_obj_create( dt, m, 1, 0, 0, &z ); bli_obj_create( dt, m, m, 0, 0, &q ); bli_obj_set_uplo( uploc, &q ); libblis_test_vobj_randomize( params, TRUE, &t ); bli_gemv( &BLIS_ONE, c, &t, &BLIS_ZERO, &v ); bli_gemm( &BLIS_ONE, a, b, &BLIS_ZERO, &q ); #if 1 bli_mktrim( &q ); bli_gemv( alpha, &q, &t, &BLIS_ZERO, &z ); #else bli_obj_set_struc( BLIS_TRIANGULAR, &q ); bli_copyv( &t, &z ); bli_trmv( alpha, &q, &z ); #endif bli_gemv( beta, c_orig, &t, &BLIS_ONE, &z ); bli_subv( &z, &v ); bli_normfv( &v, &norm ); bli_getsc( &norm, resid, &junk ); bli_obj_free( &t ); bli_obj_free( &v ); bli_obj_free( &z ); bli_obj_free( &q ); } blis-0.9.0/testsuite/src/test_gemmt.h000066400000000000000000000034711422157504600176250ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void libblis_test_gemmt ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); blis-0.9.0/testsuite/src/test_gemmtrsm_ukr.c000066400000000000000000000407621422157504600212270ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "test_libblis.h" // Static variables. static char* op_str = "gemmtrsm_ukr"; static char* o_types = "m"; // c11 static char* p_types = "u"; // uploa static thresh_t thresh[BLIS_NUM_FP_TYPES] = { { 1e-04, 1e-05 }, // warn, pass for s { 1e-04, 1e-05 }, // warn, pass for c { 1e-13, 1e-14 }, // warn, pass for d { 1e-13, 1e-14 } }; // warn, pass for z // Local prototypes. void libblis_test_gemmtrsm_ukr_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); void libblis_test_gemmtrsm_ukr_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ); void libblis_test_gemmtrsm_ukr_impl ( iface_t iface, side_t side, obj_t* alpha, obj_t* a1x, obj_t* a11, obj_t* bx1, obj_t* b11, obj_t* c11, cntx_t* cntx ); void libblis_test_gemmtrsm_ukr_check ( test_params_t* params, side_t side, obj_t* alpha, obj_t* a1x, obj_t* a11, obj_t* bx1, obj_t* b11, obj_t* c11, obj_t* c11_save, double* resid ); void bli_gemmtrsm_ukr_make_subparts ( dim_t k, obj_t* a, obj_t* b, obj_t* a1x, obj_t* a11, obj_t* bx1, obj_t* b11 ); void libblis_test_gemmtrsm_ukr_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { libblis_test_randv( tdata, params, &(op->ops->randv) ); libblis_test_randm( tdata, params, &(op->ops->randm) ); libblis_test_setv( tdata, params, &(op->ops->setv) ); libblis_test_normfv( tdata, params, &(op->ops->normfv) ); libblis_test_subv( tdata, params, &(op->ops->subv) ); libblis_test_scalv( tdata, params, &(op->ops->scalv) ); libblis_test_copym( tdata, params, &(op->ops->copym) ); libblis_test_scalm( tdata, params, &(op->ops->scalm) ); libblis_test_gemv( tdata, params, &(op->ops->gemv) ); libblis_test_trsv( tdata, params, &(op->ops->trsv) ); } void libblis_test_gemmtrsm_ukr ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { // Return early if this test has already been done. if ( libblis_test_op_is_done( op ) ) return; // Return early if operation is disabled. if ( libblis_test_op_is_disabled( op ) || libblis_test_l3ukr_is_disabled( op ) ) return; // Call dependencies first. if ( TRUE ) libblis_test_gemmtrsm_ukr_deps( tdata, params, op ); // Execute the test driver for each implementation requested. //if ( op->front_seq == ENABLE ) { libblis_test_op_driver( tdata, params, op, BLIS_TEST_SEQ_UKERNEL, op_str, p_types, o_types, thresh, libblis_test_gemmtrsm_ukr_experiment ); } } // Import the register blocksizes used by the micro-kernel(s). extern blksz_t* gemm_mr; extern blksz_t* gemm_nr; extern blksz_t* gemm_kr; void libblis_test_gemmtrsm_ukr_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ) { unsigned int n_repeats = params->n_repeats; unsigned int i; double time_min = DBL_MAX; double time; num_t datatype; dim_t m, n, k; inc_t ldap, ldbp; char sc_a = 'c'; char sc_b = 'r'; side_t side = BLIS_LEFT; uplo_t uploa; obj_t alpha; obj_t a_big, a, b; obj_t b11, c11; obj_t ap, bp; obj_t a1xp, a11p, bx1p, b11p; obj_t c11_save; cntx_t* cntx; // Query a context. cntx = bli_gks_query_cntx(); // Use the datatype of the first char in the datatype combination string. bli_param_map_char_to_blis_dt( dc_str[0], &datatype ); // Map the dimension specifier to actual dimensions. k = libblis_test_get_dim_from_prob_size( op->dim_spec[0], p_cur ); // Fix m and n to MR and NR, respectively. m = bli_cntx_get_blksz_def_dt( datatype, BLIS_MR, cntx ); n = bli_cntx_get_blksz_def_dt( datatype, BLIS_NR, cntx ); // Also query PACKMR and PACKNR as the leading dimensions to ap and bp, // respectively. ldap = bli_cntx_get_blksz_max_dt( datatype, BLIS_MR, cntx ); ldbp = bli_cntx_get_blksz_max_dt( datatype, BLIS_NR, cntx ); // Store the register blocksizes so that the driver can retrieve the // values later when printing results. op->dim_aux[0] = m; op->dim_aux[1] = n; // Map parameter characters to BLIS constants. bli_param_map_char_to_blis_uplo( pc_str[0], &uploa ); // Create test scalars. bli_obj_scalar_init_detached( datatype, &alpha ); // Create test operands (vectors and/or matrices). libblis_test_mobj_create( params, datatype, BLIS_NO_TRANSPOSE, sc_a, k+m, k+m, &a_big ); libblis_test_mobj_create( params, datatype, BLIS_NO_TRANSPOSE, sc_b, k+m, n, &b ); libblis_test_mobj_create( params, datatype, BLIS_NO_TRANSPOSE, sc_str[0], m, n, &c11 ); libblis_test_mobj_create( params, datatype, BLIS_NO_TRANSPOSE, sc_str[0], m, n, &c11_save ); // Set alpha. if ( bli_obj_is_real( &b ) ) { bli_setsc( 2.0, 0.0, &alpha ); } else { bli_setsc( 2.0, 0.0, &alpha ); } // Set the structure, uplo, and diagonal offset properties of A. bli_obj_set_struc( BLIS_TRIANGULAR, &a_big ); bli_obj_set_uplo( uploa, &a_big ); // Randomize A and make it densely triangular. libblis_test_mobj_randomize( params, TRUE, &a_big ); libblis_test_mobj_load_diag( params, &a_big ); // Normalize B and save. libblis_test_mobj_randomize( params, TRUE, &b ); // Locate A1x/A11 (lower) or Ax1/A11 (upper), and then locate the // corresponding B11 block of B. if ( bli_obj_is_lower( &a_big ) ) { bli_acquire_mpart_t2b( BLIS_SUBPART1, k, m, &a_big, &a ); bli_acquire_mpart_t2b( BLIS_SUBPART1, k, m, &b, &b11 ); } else { bli_acquire_mpart_t2b( BLIS_SUBPART1, 0, m, &a_big, &a ); bli_acquire_mpart_t2b( BLIS_SUBPART1, 0, m, &b, &b11 ); } // Copy B11 to C11, and save. bli_copym( &b11, &c11 ); bli_copym( &c11, &c11_save ); rntm_t rntm; bli_rntm_init( &rntm ); bli_pba_rntm_set_pba( &rntm ); // Create pack objects for a and b, and pack them to ap and bp, // respectively. cntl_t* cntl_a = libblis_test_pobj_create ( BLIS_MR, BLIS_MR, BLIS_INVERT_DIAG, BLIS_PACKED_ROW_PANELS, BLIS_BUFFER_FOR_A_BLOCK, &a, &ap, cntx, &rntm ); // Set the diagonal offset of ap. if ( bli_is_lower( uploa ) ) { bli_obj_set_diag_offset( k, &ap ); } else { bli_obj_set_diag_offset( 0, &ap ); } // Set the uplo field of ap since the default for packed objects is // BLIS_DENSE, and the _make_subparts() routine needs this information // to know how to initialize the subpartitions. bli_obj_set_uplo( uploa, &ap ); #if 0 bli_printm( "a", &a, "%5.2f", "" ); bli_printm( "ap", &ap, "%5.2f", "" ); #endif cntl_t* cntl_b = NULL; // Repeat the experiment n_repeats times and record results. for ( i = 0; i < n_repeats; ++i ) { bli_copym( &c11_save, &c11 ); // Transpose B to B^T for packing. bli_obj_induce_trans( &b ); cntl_b = libblis_test_pobj_create ( BLIS_NR, BLIS_MR, BLIS_NO_INVERT_DIAG, BLIS_PACKED_COL_PANELS, BLIS_BUFFER_FOR_B_PANEL, &b, &bp, cntx, &rntm ); // Transpose B^T back to B and Bp^T back to Bp. bli_obj_induce_trans( &b ); bli_obj_induce_trans( &bp ); // Create subpartitions from the a and b panels. bli_gemmtrsm_ukr_make_subparts( k, &ap, &bp, &a1xp, &a11p, &bx1p, &b11p ); // Set the uplo field of a11p since the default for packed objects is // BLIS_DENSE, and the _ukernel() wrapper needs this information to // know which set of micro-kernels (lower or upper) to choose from. bli_obj_set_uplo( uploa, &a11p ); time = bli_clock(); libblis_test_gemmtrsm_ukr_impl( iface, side, &alpha, &a1xp, &a11p, &bx1p, &b11p, &c11, cntx ); time_min = bli_clock_min_diff( time_min, time ); // On the last pass, we must keep the packed B buffer checked out in order // to perform the correctness check later. if ( i < n_repeats - 1 ) { // Free the control tree nodes and release their cached mem_t entries // back to the memory broker. bli_cntl_free( &rntm, cntl_b, &BLIS_PACKM_SINGLE_THREADED ); } } // Estimate the performance of the best experiment repeat. *perf = ( 2.0 * m * n * k + 1.0 * m * m * n ) / time_min / FLOPS_PER_UNIT_PERF; if ( bli_obj_is_complex( &b ) ) *perf *= 4.0; // A hack to support subconfigs such as power9, which duplicate/broadcast // more than one stored element per logical element in the packed copy of // B. We assume that the ratio ldbp/n gives us the duplication factor used // within B while the ratio ldap/m gives us the duplication factor used // within A (not entirely a safe assumption, though I think it holds for // all gemm ukernels currently supported within BLIS). This duplication // factor must be used as the column stride of B (or the row stride of A) // in order for the bli_gemmv() operation (called within the // libblis_test_gemmtrsm_ukr_check()) to operate properly. if ( ldbp / n > 1 ) { const dim_t bfac = ldbp / n; bli_obj_set_col_stride( bfac, &b11p ); bli_obj_set_col_stride( bfac, &bx1p ); } if ( ldap / m > 1 ) { const dim_t bfac = ldap / m; bli_obj_set_row_stride( bfac, &a11p ); bli_obj_set_row_stride( bfac, &a1xp ); } // Perform checks. libblis_test_gemmtrsm_ukr_check( params, side, &alpha, &a1xp, &a11p, &bx1p, &b11p, &c11, &c11_save, resid ); // Zero out performance and residual if output matrix is empty. //libblis_test_check_empty_problem( &c11, perf, resid ); // Free the control tree nodes and release their cached mem_t entries // back to the pba. bli_cntl_free( &rntm, cntl_a, &BLIS_PACKM_SINGLE_THREADED ); if ( cntl_b ) bli_cntl_free( &rntm, cntl_b, &BLIS_PACKM_SINGLE_THREADED ); // Free the test objects. bli_obj_free( &a_big ); bli_obj_free( &b ); bli_obj_free( &c11 ); bli_obj_free( &c11_save ); } void libblis_test_gemmtrsm_ukr_impl ( iface_t iface, side_t side, obj_t* alpha, obj_t* a1x, obj_t* a11, obj_t* bx1, obj_t* b11, obj_t* c11, cntx_t* cntx ) { switch ( iface ) { case BLIS_TEST_SEQ_UKERNEL: bli_gemmtrsm_ukernel( alpha, a1x, a11, bx1, b11, c11, cntx ); break; default: libblis_test_printf_error( "Invalid interface type.\n" ); } } void libblis_test_gemmtrsm_ukr_check ( test_params_t* params, side_t side, obj_t* alpha, obj_t* a1x, obj_t* a11, obj_t* bx1, obj_t* b11, obj_t* c11, obj_t* c11_orig, double* resid ) { num_t dt = bli_obj_dt( b11 ); num_t dt_real = bli_obj_dt_proj_to_real( b11 ); dim_t m = bli_obj_length( b11 ); dim_t n = bli_obj_width( b11 ); dim_t k = bli_obj_width( a1x ); obj_t norm; obj_t t, v, w, z; double junk; // // Pre-conditions: // - a1x, a11, bx1, c11_orig are randomized; a11 is triangular. // - contents of b11 == contents of c11. // - side == BLIS_LEFT. // // Under these conditions, we assume that the implementation for // // B := inv(A11) * ( alpha * B11 - A1x * Bx1 ) (side = left) // // is functioning correctly if // // normfv( v - z ) // // is negligible, where // // v = B11 * t // // z = ( inv(A11) * ( alpha * B11_orig - A1x * Bx1 ) ) * t // = inv(A11) * ( alpha * B11_orig * t - A1x * Bx1 * t ) // = inv(A11) * ( alpha * B11_orig * t - A1x * w ) // bli_obj_scalar_init_detached( dt_real, &norm ); if ( bli_is_left( side ) ) { bli_obj_create( dt, n, 1, 0, 0, &t ); bli_obj_create( dt, m, 1, 0, 0, &v ); bli_obj_create( dt, k, 1, 0, 0, &w ); bli_obj_create( dt, m, 1, 0, 0, &z ); } else // else if ( bli_is_left( side ) ) { // BLIS does not currently support right-side micro-kernels. bli_check_error_code( BLIS_NOT_YET_IMPLEMENTED ); } libblis_test_vobj_randomize( params, TRUE, &t ); bli_gemv( &BLIS_ONE, b11, &t, &BLIS_ZERO, &v ); #if 0 bli_printm( "a11", a11, "%5.2f", "" ); #endif // Restore the diagonal of a11 to its original, un-inverted state // (needed for trsv). bli_invertd( a11 ); if ( bli_is_left( side ) ) { bli_gemv( &BLIS_ONE, bx1, &t, &BLIS_ZERO, &w ); bli_gemv( alpha, c11_orig, &t, &BLIS_ZERO, &z ); bli_gemv( &BLIS_MINUS_ONE, a1x, &w, &BLIS_ONE, &z ); bli_trsv( &BLIS_ONE, a11, &z ); } else // else if ( bli_is_left( side ) ) { // BLIS does not currently support right-side micro-kernels. bli_check_error_code( BLIS_NOT_YET_IMPLEMENTED ); } bli_subv( &z, &v ); bli_normfv( &v, &norm ); bli_getsc( &norm, resid, &junk ); bli_obj_free( &t ); bli_obj_free( &v ); bli_obj_free( &w ); bli_obj_free( &z ); } void bli_gemmtrsm_ukr_make_subparts ( dim_t k, obj_t* a, obj_t* b, obj_t* a1x, obj_t* a11, obj_t* bx1, obj_t* b11 ) { dim_t mr = bli_obj_length( a ); dim_t nr = bli_obj_width( b ); dim_t off_a1x, off_a11; dim_t off_bx1, off_b11; if ( bli_obj_is_lower( a ) ) { off_a1x = 0; off_a11 = k; off_bx1 = 0; off_b11 = k; } else { off_a1x = mr; off_a11 = 0; off_bx1 = mr; off_b11 = 0; } bli_obj_init_subpart_from( a, a1x ); bli_obj_set_dims( mr, k, a1x ); bli_obj_inc_offs( 0, off_a1x, a1x ); bli_obj_init_subpart_from( a, a11 ); bli_obj_set_dims( mr, mr, a11 ); bli_obj_inc_offs( 0, off_a11, a11 ); bli_obj_init_subpart_from( b, bx1 ); bli_obj_set_dims( k, nr, bx1 ); bli_obj_inc_offs( off_bx1, 0, bx1 ); bli_obj_init_subpart_from( b, b11 ); bli_obj_set_dims( mr, nr, b11 ); bli_obj_inc_offs( off_b11, 0, b11 ); // Mark a1x as having general structure (which overwrites the triangular // property it inherited from a). bli_obj_set_struc( BLIS_GENERAL, a1x ); // Set the diagonal offset of a11 to 0 (which overwrites the diagonal // offset value it inherited from a). bli_obj_set_diag_offset( 0, a11 ); } blis-0.9.0/testsuite/src/test_gemmtrsm_ukr.h000066400000000000000000000035071422157504600212300ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void libblis_test_gemmtrsm_ukr ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); blis-0.9.0/testsuite/src/test_gemv.c000066400000000000000000000234651422157504600174520ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "test_libblis.h" // Static variables. static char* op_str = "gemv"; static char* o_types = "mvv"; // a x y static char* p_types = "hc"; // transa conjx static thresh_t thresh[BLIS_NUM_FP_TYPES] = { { 1e-04, 1e-05 }, // warn, pass for s { 1e-04, 1e-05 }, // warn, pass for c { 1e-13, 1e-14 }, // warn, pass for d { 1e-13, 1e-14 } }; // warn, pass for z // Local prototypes. void libblis_test_gemv_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); void libblis_test_gemv_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ); void libblis_test_gemv_impl ( iface_t iface, obj_t* alpha, obj_t* a, obj_t* x, obj_t* beta, obj_t* y ); void libblis_test_gemv_check ( test_params_t* params, obj_t* kappa, obj_t* alpha, obj_t* a, obj_t* x, obj_t* beta, obj_t* y, obj_t* y_orig, double* resid ); void libblis_test_gemv_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { libblis_test_randv( tdata, params, &(op->ops->randv) ); libblis_test_normfv( tdata, params, &(op->ops->normfv) ); libblis_test_subv( tdata, params, &(op->ops->subv) ); libblis_test_copyv( tdata, params, &(op->ops->copyv) ); libblis_test_scalv( tdata, params, &(op->ops->scalv) ); } void libblis_test_gemv ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { // Return early if this test has already been done. if ( libblis_test_op_is_done( op ) ) return; // Return early if operation is disabled. if ( libblis_test_op_is_disabled( op ) || libblis_test_l2_is_disabled( op ) ) return; // Call dependencies first. if ( TRUE ) libblis_test_gemv_deps( tdata, params, op ); // Execute the test driver for each implementation requested. //if ( op->front_seq == ENABLE ) { libblis_test_op_driver( tdata, params, op, BLIS_TEST_SEQ_FRONT_END, op_str, p_types, o_types, thresh, libblis_test_gemv_experiment ); } } void libblis_test_gemv_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ) { unsigned int n_repeats = params->n_repeats; unsigned int i; double time_min = DBL_MAX; double time; num_t datatype; dim_t m, n; trans_t transa; conj_t conjx; obj_t kappa; obj_t alpha, a, x, beta, y; obj_t y_save; // Use the datatype of the first char in the datatype combination string. bli_param_map_char_to_blis_dt( dc_str[0], &datatype ); // Map the dimension specifier to actual dimensions. m = libblis_test_get_dim_from_prob_size( op->dim_spec[0], p_cur ); n = libblis_test_get_dim_from_prob_size( op->dim_spec[1], p_cur ); // Map parameter characters to BLIS constants. bli_param_map_char_to_blis_trans( pc_str[0], &transa ); bli_param_map_char_to_blis_conj( pc_str[1], &conjx ); // Create test scalars. bli_obj_scalar_init_detached( datatype, &kappa ); bli_obj_scalar_init_detached( datatype, &alpha ); bli_obj_scalar_init_detached( datatype, &beta ); // Create test operands (vectors and/or matrices). libblis_test_mobj_create( params, datatype, transa, sc_str[0], m, n, &a ); libblis_test_vobj_create( params, datatype, sc_str[1], n, &x ); libblis_test_vobj_create( params, datatype, sc_str[2], m, &y ); libblis_test_vobj_create( params, datatype, sc_str[2], m, &y_save ); // Set alpha and beta. if ( bli_obj_is_real( &y ) ) { bli_setsc( 2.0, 0.0, &alpha ); bli_setsc( -1.0, 0.0, &beta ); } else { bli_setsc( 1.0, 2.0, &alpha ); bli_setsc( 1.0, -1.0, &beta ); } // Initialize diagonal of matrix A. bli_setsc( 2.0, -1.0, &kappa ); bli_setm( &BLIS_ZERO, &a ); bli_setd( &kappa, &a ); // Randomize x and y, and save y. libblis_test_vobj_randomize( params, TRUE, &x ); libblis_test_vobj_randomize( params, TRUE, &y ); bli_copyv( &y, &y_save ); // Apply the parameters. bli_obj_set_conjtrans( transa, &a ); bli_obj_set_conj( conjx, &x ); // Repeat the experiment n_repeats times and record results. for ( i = 0; i < n_repeats; ++i ) { bli_copym( &y_save, &y ); time = bli_clock(); libblis_test_gemv_impl( iface, &alpha, &a, &x, &beta, &y ); time_min = bli_clock_min_diff( time_min, time ); } // Estimate the performance of the best experiment repeat. *perf = ( 2.0 * m * n ) / time_min / FLOPS_PER_UNIT_PERF; if ( bli_obj_is_complex( &y ) ) *perf *= 4.0; // Perform checks. libblis_test_gemv_check( params, &kappa, &alpha, &a, &x, &beta, &y, &y_save, resid ); // Zero out performance and residual if output vector is empty. libblis_test_check_empty_problem( &y, perf, resid ); // Free the test objects. bli_obj_free( &a ); bli_obj_free( &x ); bli_obj_free( &y ); bli_obj_free( &y_save ); } void libblis_test_gemv_impl ( iface_t iface, obj_t* alpha, obj_t* a, obj_t* x, obj_t* beta, obj_t* y ) { switch ( iface ) { case BLIS_TEST_SEQ_FRONT_END: bli_gemv( alpha, a, x, beta, y ); break; default: libblis_test_printf_error( "Invalid interface type.\n" ); } } void libblis_test_gemv_check ( test_params_t* params, obj_t* kappa, obj_t* alpha, obj_t* a, obj_t* x, obj_t* beta, obj_t* y, obj_t* y_orig, double* resid ) { num_t dt = bli_obj_dt( y ); num_t dt_real = bli_obj_dt_proj_to_real( y ); conj_t conja = bli_obj_conj_status( a ); dim_t n_x = bli_obj_vector_dim( x ); dim_t m_y = bli_obj_vector_dim( y ); dim_t min_m_n = bli_min( m_y, n_x ); obj_t x_temp, y_temp; obj_t kappac, norm; obj_t xT_temp, yT_temp, yT; double junk; // // Pre-conditions: // - a is initialized to kappa along the diagonal. // - x is randomized. // - y_orig is randomized. // Note: // - alpha, beta, and kappa should have non-zero imaginary components in // the complex cases in order to more fully exercise the implementation. // // Under these conditions, we assume that the implementation for // // y := beta * y_orig + alpha * transa(A) * conjx(x) // // is functioning correctly if // // normfv( y - z ) // // is negligible, where // // z = beta * y_orig + alpha * conja(kappa) * x // bli_obj_scalar_init_detached_copy_of( dt, conja, kappa, &kappac ); bli_obj_scalar_init_detached( dt_real, &norm ); bli_obj_create( dt, n_x, 1, 0, 0, &x_temp ); bli_obj_create( dt, m_y, 1, 0, 0, &y_temp ); bli_copyv( x, &x_temp ); bli_copyv( y_orig, &y_temp ); bli_acquire_vpart_f2b( BLIS_SUBPART1, 0, min_m_n, &x_temp, &xT_temp ); bli_acquire_vpart_f2b( BLIS_SUBPART1, 0, min_m_n, &y_temp, &yT_temp ); bli_acquire_vpart_f2b( BLIS_SUBPART1, 0, min_m_n, y, &yT ); bli_scalv( &kappac, &xT_temp ); bli_scalv( beta, &yT_temp ); bli_axpyv( alpha, &xT_temp, &yT_temp ); bli_subv( &yT_temp, &yT ); bli_normfv( &yT, &norm ); bli_getsc( &norm, resid, &junk ); bli_obj_free( &x_temp ); bli_obj_free( &y_temp ); } blis-0.9.0/testsuite/src/test_gemv.h000066400000000000000000000034771422157504600174600ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void libblis_test_gemv ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); blis-0.9.0/testsuite/src/test_ger.c000066400000000000000000000222671422157504600172700ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "test_libblis.h" // Static variables. static char* op_str = "ger"; static char* o_types = "vvm"; // x y a static char* p_types = "cc"; // transa conjx static thresh_t thresh[BLIS_NUM_FP_TYPES] = { { 1e-04, 1e-05 }, // warn, pass for s { 1e-04, 1e-05 }, // warn, pass for c { 1e-13, 1e-14 }, // warn, pass for d { 1e-13, 1e-14 } }; // warn, pass for z // Local prototypes. void libblis_test_ger_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); void libblis_test_ger_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ); void libblis_test_ger_impl ( iface_t iface, obj_t* alpha, obj_t* x, obj_t* y, obj_t* a ); void libblis_test_ger_check ( test_params_t* params, obj_t* alpha, obj_t* x, obj_t* y, obj_t* a, obj_t* a_orig, double* resid ); void libblis_test_ger_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { libblis_test_randv( tdata, params, &(op->ops->randv) ); libblis_test_normfv( tdata, params, &(op->ops->normfv) ); libblis_test_subv( tdata, params, &(op->ops->subv) ); libblis_test_scal2v( tdata, params, &(op->ops->scal2v) ); libblis_test_dotv( tdata, params, &(op->ops->dotv) ); libblis_test_gemv( tdata, params, &(op->ops->gemv) ); } void libblis_test_ger ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { // Return early if this test has already been done. if ( libblis_test_op_is_done( op ) ) return; // Return early if operation is disabled. if ( libblis_test_op_is_disabled( op ) || libblis_test_l2_is_disabled( op ) ) return; // Call dependencies first. if ( TRUE ) libblis_test_ger_deps( tdata, params, op ); // Execute the test driver for each implementation requested. //if ( op->front_seq == ENABLE ) { libblis_test_op_driver( tdata, params, op, BLIS_TEST_SEQ_FRONT_END, op_str, p_types, o_types, thresh, libblis_test_ger_experiment ); } } void libblis_test_ger_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ) { unsigned int n_repeats = params->n_repeats; unsigned int i; double time_min = DBL_MAX; double time; num_t datatype; dim_t m, n; conj_t conjx, conjy; obj_t alpha, x, y, a; obj_t a_save; // Use the datatype of the first char in the datatype combination string. bli_param_map_char_to_blis_dt( dc_str[0], &datatype ); // Map the dimension specifier to actual dimensions. m = libblis_test_get_dim_from_prob_size( op->dim_spec[0], p_cur ); n = libblis_test_get_dim_from_prob_size( op->dim_spec[1], p_cur ); // Map parameter characters to BLIS constants. bli_param_map_char_to_blis_conj( pc_str[0], &conjx ); bli_param_map_char_to_blis_conj( pc_str[1], &conjy ); // Create test scalars. bli_obj_scalar_init_detached( datatype, &alpha ); // Create test operands (vectors and/or matrices). libblis_test_vobj_create( params, datatype, sc_str[0], m, &x ); libblis_test_vobj_create( params, datatype, sc_str[1], n, &y ); libblis_test_mobj_create( params, datatype, BLIS_NO_TRANSPOSE, sc_str[2], m, n, &a ); libblis_test_mobj_create( params, datatype, BLIS_NO_TRANSPOSE, sc_str[2], m, n, &a_save ); // Set alpha. if ( bli_obj_is_real( &a ) ) bli_setsc( -1.0, 1.0, &alpha ); else bli_setsc( -1.0, 1.0, &alpha ); // Randomize x and y. libblis_test_vobj_randomize( params, TRUE, &x ); libblis_test_vobj_randomize( params, TRUE, &y ); // Initialize A to identity and save. bli_setm( &BLIS_ZERO, &a ); bli_setd( &BLIS_ONE, &a ); bli_copym( &a, &a_save ); // Apply the parameters. bli_obj_set_conj( conjx, &x ); bli_obj_set_conj( conjy, &y ); // Repeat the experiment n_repeats times and record results. for ( i = 0; i < n_repeats; ++i ) { bli_copym( &a_save, &a ); time = bli_clock(); libblis_test_ger_impl( iface, &alpha, &x, &y, &a ); time_min = bli_clock_min_diff( time_min, time ); } // Estimate the performance of the best experiment repeat. *perf = ( 2.0 * m * n ) / time_min / FLOPS_PER_UNIT_PERF; if ( bli_obj_is_complex( &a ) ) *perf *= 4.0; // Perform checks. libblis_test_ger_check( params, &alpha, &x, &y, &a, &a_save, resid ); // Zero out performance and residual if output matrix is empty. libblis_test_check_empty_problem( &a, perf, resid ); // Free the test objects. bli_obj_free( &x ); bli_obj_free( &y ); bli_obj_free( &a ); bli_obj_free( &a_save ); } void libblis_test_ger_impl ( iface_t iface, obj_t* alpha, obj_t* x, obj_t* y, obj_t* a ) { switch ( iface ) { case BLIS_TEST_SEQ_FRONT_END: bli_ger( alpha, x, y, a ); break; default: libblis_test_printf_error( "Invalid interface type.\n" ); } } void libblis_test_ger_check ( test_params_t* params, obj_t* alpha, obj_t* x, obj_t* y, obj_t* a, obj_t* a_orig, double* resid ) { num_t dt = bli_obj_dt( a ); num_t dt_real = bli_obj_dt_proj_to_real( a ); dim_t m_a = bli_obj_length( a ); dim_t n_a = bli_obj_width( a ); obj_t t, v, w; obj_t rho, norm; double junk; // // Pre-conditions: // - x is randomized. // - y is randomized. // - a is identity. // Note: // - alpha should have a non-zero imaginary component in the // complex cases in order to more fully exercise the implementation. // // Under these conditions, we assume that the implementation for // // A := A_orig + alpha * conjx(x) * conjy(y) // // is functioning correctly if // // normfv( v - w ) // // is negligible, where // // v = A * t // w = ( A_orig + alpha * conjx(x) * conjy(y)^T ) * t // = A_orig * t + alpha * conjx(x) * conjy(y)^T * t // = A_orig * t + alpha * conjx(x) * rho // = A_orig * t + w // bli_obj_scalar_init_detached( dt, &rho ); bli_obj_scalar_init_detached( dt_real, &norm ); bli_obj_create( dt, n_a, 1, 0, 0, &t ); bli_obj_create( dt, m_a, 1, 0, 0, &v ); bli_obj_create( dt, m_a, 1, 0, 0, &w ); libblis_test_vobj_randomize( params, TRUE, &t ); bli_gemv( &BLIS_ONE, a, &t, &BLIS_ZERO, &v ); bli_dotv( y, &t, &rho ); bli_mulsc( alpha, &rho ); bli_scal2v( &rho, x, &w ); bli_gemv( &BLIS_ONE, a_orig, &t, &BLIS_ONE, &w ); bli_subv( &w, &v ); bli_normfv( &v, &norm ); bli_getsc( &norm, resid, &junk ); bli_obj_free( &t ); bli_obj_free( &v ); bli_obj_free( &w ); } blis-0.9.0/testsuite/src/test_ger.h000066400000000000000000000034761422157504600172760ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void libblis_test_ger ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); blis-0.9.0/testsuite/src/test_hemm.c000066400000000000000000000263251422157504600174400ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "test_libblis.h" // Static variables. static char* op_str = "hemm"; static char* o_types = "mmm"; // a b c static char* p_types = "such"; // side uploa conja transb static thresh_t thresh[BLIS_NUM_FP_TYPES] = { { 1e-04, 1e-05 }, // warn, pass for s { 1e-04, 1e-05 }, // warn, pass for c { 1e-13, 1e-14 }, // warn, pass for d { 1e-13, 1e-14 } }; // warn, pass for z // Local prototypes. void libblis_test_hemm_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); void libblis_test_hemm_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ); void libblis_test_hemm_impl ( iface_t iface, side_t side, obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c ); void libblis_test_hemm_check ( test_params_t* params, side_t side, obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, obj_t* c_orig, double* resid ); void libblis_test_hemm_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { libblis_test_randv( tdata, params, &(op->ops->randv) ); libblis_test_randm( tdata, params, &(op->ops->randm) ); libblis_test_setv( tdata, params, &(op->ops->setv) ); libblis_test_normfv( tdata, params, &(op->ops->normfv) ); libblis_test_subv( tdata, params, &(op->ops->subv) ); libblis_test_scalv( tdata, params, &(op->ops->scalv) ); libblis_test_copym( tdata, params, &(op->ops->copym) ); libblis_test_scalm( tdata, params, &(op->ops->scalm) ); libblis_test_gemv( tdata, params, &(op->ops->gemv) ); libblis_test_hemv( tdata, params, &(op->ops->hemv) ); } void libblis_test_hemm ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { // Return early if this test has already been done. if ( libblis_test_op_is_done( op ) ) return; // Return early if operation is disabled. if ( libblis_test_op_is_disabled( op ) || libblis_test_l3_is_disabled( op ) ) return; // Call dependencies first. if ( TRUE ) libblis_test_hemm_deps( tdata, params, op ); // Execute the test driver for each implementation requested. //if ( op->front_seq == ENABLE ) { libblis_test_op_driver( tdata, params, op, BLIS_TEST_SEQ_FRONT_END, op_str, p_types, o_types, thresh, libblis_test_hemm_experiment ); } } void libblis_test_hemm_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ) { unsigned int n_repeats = params->n_repeats; unsigned int i; double time_min = DBL_MAX; double time; num_t datatype; dim_t m, n; dim_t mn_side; side_t side; uplo_t uploa; conj_t conja; trans_t transb; obj_t alpha, a, b, beta, c; obj_t c_save; // Use the datatype of the first char in the datatype combination string. bli_param_map_char_to_blis_dt( dc_str[0], &datatype ); // Map the dimension specifier to actual dimensions. m = libblis_test_get_dim_from_prob_size( op->dim_spec[0], p_cur ); n = libblis_test_get_dim_from_prob_size( op->dim_spec[1], p_cur ); // Map parameter characters to BLIS constants. bli_param_map_char_to_blis_side( pc_str[0], &side ); bli_param_map_char_to_blis_uplo( pc_str[1], &uploa ); bli_param_map_char_to_blis_conj( pc_str[2], &conja ); bli_param_map_char_to_blis_trans( pc_str[3], &transb ); // Create test scalars. bli_obj_scalar_init_detached( datatype, &alpha ); bli_obj_scalar_init_detached( datatype, &beta ); // Create test operands (vectors and/or matrices). bli_set_dim_with_side( side, m, n, &mn_side ); libblis_test_mobj_create( params, datatype, BLIS_NO_TRANSPOSE, sc_str[1], mn_side, mn_side, &a ); libblis_test_mobj_create( params, datatype, transb, sc_str[2], m, n, &b ); libblis_test_mobj_create( params, datatype, BLIS_NO_TRANSPOSE, sc_str[0], m, n, &c ); libblis_test_mobj_create( params, datatype, BLIS_NO_TRANSPOSE, sc_str[0], m, n, &c_save ); // Set alpha and beta. if ( bli_obj_is_real( &c ) ) { bli_setsc( 1.2, 0.0, &alpha ); bli_setsc( -1.0, 0.0, &beta ); } else { bli_setsc( 1.2, 0.8, &alpha ); bli_setsc( -1.0, 1.0, &beta ); } // Set the structure and uplo properties of A. bli_obj_set_struc( BLIS_HERMITIAN, &a ); bli_obj_set_uplo( uploa, &a ); // Randomize A, make it densely Hermitian, and zero the unstored triangle // to ensure the implementation reads only from the stored region. libblis_test_mobj_randomize( params, TRUE, &a ); bli_mkherm( &a ); bli_mktrim( &a ); // Randomize B and C, and save C. libblis_test_mobj_randomize( params, TRUE, &b ); libblis_test_mobj_randomize( params, TRUE, &c ); bli_copym( &c, &c_save ); // Apply the remaining parameters. bli_obj_set_conj( conja, &a ); bli_obj_set_conjtrans( transb, &b ); // Repeat the experiment n_repeats times and record results. for ( i = 0; i < n_repeats; ++i ) { bli_copym( &c_save, &c ); time = bli_clock(); libblis_test_hemm_impl( iface, side, &alpha, &a, &b, &beta, &c ); time_min = bli_clock_min_diff( time_min, time ); } // Estimate the performance of the best experiment repeat. *perf = ( 2.0 * mn_side * m * n ) / time_min / FLOPS_PER_UNIT_PERF; if ( bli_obj_is_complex( &c ) ) *perf *= 4.0; // Perform checks. libblis_test_hemm_check( params, side, &alpha, &a, &b, &beta, &c, &c_save, resid ); // Zero out performance and residual if output matrix is empty. libblis_test_check_empty_problem( &c, perf, resid ); // Free the test objects. bli_obj_free( &a ); bli_obj_free( &b ); bli_obj_free( &c ); bli_obj_free( &c_save ); } void libblis_test_hemm_impl ( iface_t iface, side_t side, obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c ) { switch ( iface ) { case BLIS_TEST_SEQ_FRONT_END: bli_hemm( side, alpha, a, b, beta, c ); break; default: libblis_test_printf_error( "Invalid interface type.\n" ); } } void libblis_test_hemm_check ( test_params_t* params, side_t side, obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, obj_t* c_orig, double* resid ) { num_t dt = bli_obj_dt( c ); num_t dt_real = bli_obj_dt_proj_to_real( c ); dim_t m = bli_obj_length( c ); dim_t n = bli_obj_width( c ); obj_t norm; obj_t t, v, w, z; double junk; // // Pre-conditions: // - a is randomized and Hermitian. // - b is randomized. // - c_orig is randomized. // Note: // - alpha and beta should have non-zero imaginary components in the // complex cases in order to more fully exercise the implementation. // // Under these conditions, we assume that the implementation for // // C := beta * C_orig + alpha * conja(A) * transb(B) (side = left) // C := beta * C_orig + alpha * transb(B) * conja(A) (side = right) // // is functioning correctly if // // normfv( v - z ) // // is negligible, where // // v = C * t // // z = ( beta * C_orig + alpha * conja(A) * transb(B) ) * t (side = left) // = beta * C_orig * t + alpha * conja(A) * transb(B) * t // = beta * C_orig * t + alpha * conja(A) * w // = beta * C_orig * t + z // // z = ( beta * C_orig + alpha * transb(B) * conja(A) ) * t (side = right) // = beta * C_orig * t + alpha * transb(B) * conja(A) * t // = beta * C_orig * t + alpha * transb(B) * w // = beta * C_orig * t + z bli_obj_scalar_init_detached( dt_real, &norm ); if ( bli_is_left( side ) ) { bli_obj_create( dt, n, 1, 0, 0, &t ); bli_obj_create( dt, m, 1, 0, 0, &v ); bli_obj_create( dt, m, 1, 0, 0, &w ); bli_obj_create( dt, m, 1, 0, 0, &z ); } else // else if ( bli_is_right( side ) ) { bli_obj_create( dt, n, 1, 0, 0, &t ); bli_obj_create( dt, m, 1, 0, 0, &v ); bli_obj_create( dt, n, 1, 0, 0, &w ); bli_obj_create( dt, m, 1, 0, 0, &z ); } libblis_test_vobj_randomize( params, TRUE, &t ); bli_gemv( &BLIS_ONE, c, &t, &BLIS_ZERO, &v ); if ( bli_is_left( side ) ) { bli_gemv( &BLIS_ONE, b, &t, &BLIS_ZERO, &w ); bli_hemv( alpha, a, &w, &BLIS_ZERO, &z ); } else // else if ( bli_is_right( side ) ) { bli_hemv( &BLIS_ONE, a, &t, &BLIS_ZERO, &w ); bli_gemv( alpha, b, &w, &BLIS_ZERO, &z ); } bli_gemv( beta, c_orig, &t, &BLIS_ONE, &z ); bli_subv( &z, &v ); bli_normfv( &v, &norm ); bli_getsc( &norm, resid, &junk ); bli_obj_free( &t ); bli_obj_free( &v ); bli_obj_free( &w ); bli_obj_free( &z ); } blis-0.9.0/testsuite/src/test_hemm.h000066400000000000000000000034771422157504600174500ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void libblis_test_hemm ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); blis-0.9.0/testsuite/src/test_hemv.c000066400000000000000000000226151422157504600174470ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "test_libblis.h" // Static variables. static char* op_str = "hemv"; static char* o_types = "mvv"; // a x y static char* p_types = "ucc"; // uploa conja conjx static thresh_t thresh[BLIS_NUM_FP_TYPES] = { { 1e-04, 1e-05 }, // warn, pass for s { 1e-04, 1e-05 }, // warn, pass for c { 1e-13, 1e-14 }, // warn, pass for d { 1e-13, 1e-14 } }; // warn, pass for z // Local prototypes. void libblis_test_hemv_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); void libblis_test_hemv_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ); void libblis_test_hemv_impl ( iface_t iface, obj_t* alpha, obj_t* a, obj_t* x, obj_t* beta, obj_t* y ); void libblis_test_hemv_check ( test_params_t* params, obj_t* alpha, obj_t* a, obj_t* x, obj_t* beta, obj_t* y, obj_t* y_orig, double* resid ); void libblis_test_hemv_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { libblis_test_randv( tdata, params, &(op->ops->randv) ); libblis_test_randm( tdata, params, &(op->ops->randm) ); libblis_test_normfv( tdata, params, &(op->ops->normfv) ); libblis_test_subv( tdata, params, &(op->ops->subv) ); libblis_test_copyv( tdata, params, &(op->ops->copyv) ); libblis_test_scalv( tdata, params, &(op->ops->scalv) ); libblis_test_gemv( tdata, params, &(op->ops->gemv) ); } void libblis_test_hemv ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { // Return early if this test has already been done. if ( libblis_test_op_is_done( op ) ) return; // Return early if operation is disabled. if ( libblis_test_op_is_disabled( op ) || libblis_test_l2_is_disabled( op ) ) return; // Call dependencies first. if ( TRUE ) libblis_test_hemv_deps( tdata, params, op ); // Execute the test driver for each implementation requested. //if ( op->front_seq == ENABLE ) { libblis_test_op_driver( tdata, params, op, BLIS_TEST_SEQ_FRONT_END, op_str, p_types, o_types, thresh, libblis_test_hemv_experiment ); } } void libblis_test_hemv_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ) { unsigned int n_repeats = params->n_repeats; unsigned int i; double time_min = DBL_MAX; double time; num_t datatype; dim_t m; uplo_t uploa; conj_t conja; conj_t conjx; obj_t alpha, a, x, beta, y; obj_t y_save; // Use the datatype of the first char in the datatype combination string. bli_param_map_char_to_blis_dt( dc_str[0], &datatype ); // Map the dimension specifier to an actual dimension. m = libblis_test_get_dim_from_prob_size( op->dim_spec[0], p_cur ); // Map parameter characters to BLIS constants. bli_param_map_char_to_blis_uplo( pc_str[0], &uploa ); bli_param_map_char_to_blis_conj( pc_str[1], &conja ); bli_param_map_char_to_blis_conj( pc_str[2], &conjx ); // Create test scalars. bli_obj_scalar_init_detached( datatype, &alpha ); bli_obj_scalar_init_detached( datatype, &beta ); // Create test operands (vectors and/or matrices). libblis_test_mobj_create( params, datatype, BLIS_NO_TRANSPOSE, sc_str[0], m, m, &a ); libblis_test_vobj_create( params, datatype, sc_str[1], m, &x ); libblis_test_vobj_create( params, datatype, sc_str[2], m, &y ); libblis_test_vobj_create( params, datatype, sc_str[2], m, &y_save ); // Set alpha and beta. if ( bli_obj_is_real( &y ) ) { bli_setsc( 1.0, 0.0, &alpha ); bli_setsc( -1.0, 0.0, &beta ); } else { bli_setsc( 0.5, 0.5, &alpha ); bli_setsc( -0.5, 0.5, &beta ); } // Set the structure and uplo properties of A. bli_obj_set_struc( BLIS_HERMITIAN, &a ); bli_obj_set_uplo( uploa, &a ); // Randomize A, make it densely Hermitian, and zero the unstored triangle // to ensure the implementation reads only from the stored region. libblis_test_mobj_randomize( params, TRUE, &a ); bli_mkherm( &a ); bli_mktrim( &a ); // Randomize x and y, and save y. libblis_test_vobj_randomize( params, TRUE, &x ); libblis_test_vobj_randomize( params, TRUE, &y ); bli_copyv( &y, &y_save ); // Apply the remaining parameters. bli_obj_set_conj( conja, &a ); bli_obj_set_conj( conjx, &x ); // Repeat the experiment n_repeats times and record results. for ( i = 0; i < n_repeats; ++i ) { bli_copym( &y_save, &y ); time = bli_clock(); libblis_test_hemv_impl( iface, &alpha, &a, &x, &beta, &y ); time_min = bli_clock_min_diff( time_min, time ); } // Estimate the performance of the best experiment repeat. *perf = ( 1.0 * m * m ) / time_min / FLOPS_PER_UNIT_PERF; if ( bli_obj_is_complex( &y ) ) *perf *= 4.0; // Perform checks. libblis_test_hemv_check( params, &alpha, &a, &x, &beta, &y, &y_save, resid ); // Zero out performance and residual if output vector is empty. libblis_test_check_empty_problem( &y, perf, resid ); // Free the test objects. bli_obj_free( &a ); bli_obj_free( &x ); bli_obj_free( &y ); bli_obj_free( &y_save ); } void libblis_test_hemv_impl ( iface_t iface, obj_t* alpha, obj_t* a, obj_t* x, obj_t* beta, obj_t* y ) { switch ( iface ) { case BLIS_TEST_SEQ_FRONT_END: bli_hemv( alpha, a, x, beta, y ); break; default: libblis_test_printf_error( "Invalid interface type.\n" ); } } void libblis_test_hemv_check ( test_params_t* params, obj_t* alpha, obj_t* a, obj_t* x, obj_t* beta, obj_t* y, obj_t* y_orig, double* resid ) { num_t dt = bli_obj_dt( y ); num_t dt_real = bli_obj_dt_proj_to_real( y ); dim_t m = bli_obj_vector_dim( y ); obj_t v; obj_t norm; double junk; // // Pre-conditions: // - a is randomized and Hermitian. // - x is randomized. // - y_orig is randomized. // Note: // - alpha and beta should have non-zero imaginary components in the // complex cases in order to more fully exercise the implementation. // // Under these conditions, we assume that the implementation for // // y := beta * y_orig + alpha * conja(A) * conjx(x) // // is functioning correctly if // // normfv( y - v ) // // is negligible, where // // v = beta * y_orig + alpha * conja(A_dense) * x // bli_obj_scalar_init_detached( dt_real, &norm ); bli_obj_create( dt, m, 1, 0, 0, &v ); bli_copyv( y_orig, &v ); bli_mkherm( a ); bli_obj_set_struc( BLIS_GENERAL, a ); bli_obj_set_uplo( BLIS_DENSE, a ); bli_gemv( alpha, a, x, beta, &v ); bli_subv( &v, y ); bli_normfv( y, &norm ); bli_getsc( &norm, resid, &junk ); bli_obj_free( &v ); } blis-0.9.0/testsuite/src/test_hemv.h000066400000000000000000000034771422157504600174610ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void libblis_test_hemv ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); blis-0.9.0/testsuite/src/test_her.c000066400000000000000000000226521422157504600172670ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "test_libblis.h" // Static variables. static char* op_str = "her"; static char* o_types = "vm"; // x a static char* p_types = "uc"; // uploa conjx static thresh_t thresh[BLIS_NUM_FP_TYPES] = { { 1e-04, 1e-05 }, // warn, pass for s { 1e-04, 1e-05 }, // warn, pass for c { 1e-13, 1e-14 }, // warn, pass for d { 1e-13, 1e-14 } }; // warn, pass for z // Local prototypes. void libblis_test_her_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); void libblis_test_her_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ); void libblis_test_her_impl ( iface_t iface, obj_t* alpha, obj_t* x, obj_t* a ); void libblis_test_her_check ( test_params_t* params, obj_t* alpha, obj_t* x, obj_t* a, obj_t* a_orig, double* resid ); void libblis_test_her_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { libblis_test_randv( tdata, params, &(op->ops->randv) ); libblis_test_randm( tdata, params, &(op->ops->randm) ); libblis_test_normfv( tdata, params, &(op->ops->normfv) ); libblis_test_subv( tdata, params, &(op->ops->subv) ); libblis_test_copym( tdata, params, &(op->ops->copym) ); libblis_test_scal2v( tdata, params, &(op->ops->scal2v) ); libblis_test_dotv( tdata, params, &(op->ops->dotv) ); libblis_test_gemv( tdata, params, &(op->ops->gemv) ); } void libblis_test_her ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { // Return early if this test has already been done. if ( libblis_test_op_is_done( op ) ) return; // Return early if operation is disabled. if ( libblis_test_op_is_disabled( op ) || libblis_test_l2_is_disabled( op ) ) return; // Call dependencies first. if ( TRUE ) libblis_test_her_deps( tdata, params, op ); // Execute the test driver for each implementation requested. //if ( op->front_seq == ENABLE ) { libblis_test_op_driver( tdata, params, op, BLIS_TEST_SEQ_FRONT_END, op_str, p_types, o_types, thresh, libblis_test_her_experiment ); } } void libblis_test_her_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ) { unsigned int n_repeats = params->n_repeats; unsigned int i; double time_min = DBL_MAX; double time; num_t datatype; dim_t m; uplo_t uploa; conj_t conjx; obj_t alpha, x, a; obj_t a_save; // Use the datatype of the first char in the datatype combination string. bli_param_map_char_to_blis_dt( dc_str[0], &datatype ); // Map the dimension specifier to an actual dimension. m = libblis_test_get_dim_from_prob_size( op->dim_spec[0], p_cur ); // Map parameter characters to BLIS constants. bli_param_map_char_to_blis_uplo( pc_str[0], &uploa ); bli_param_map_char_to_blis_conj( pc_str[1], &conjx ); // Create test scalars. bli_obj_scalar_init_detached( datatype, &alpha ); // Create test operands (vectors and/or matrices). libblis_test_vobj_create( params, datatype, sc_str[0], m, &x ); libblis_test_mobj_create( params, datatype, BLIS_NO_TRANSPOSE, sc_str[1], m, m, &a ); libblis_test_mobj_create( params, datatype, BLIS_NO_TRANSPOSE, sc_str[1], m, m, &a_save ); // Set alpha. //bli_copysc( &BLIS_MINUS_ONE, &alpha ); bli_setsc( -1.0, 0.0, &alpha ); // Randomize x. libblis_test_vobj_randomize( params, TRUE, &x ); // Set the structure and uplo properties of A. bli_obj_set_struc( BLIS_HERMITIAN, &a ); bli_obj_set_uplo( uploa, &a ); // Randomize A, make it densely Hermitian, and zero the unstored triangle // to ensure the implementation is reads only from the stored region. libblis_test_mobj_randomize( params, TRUE, &a ); bli_mkherm( &a ); bli_mktrim( &a ); // Save A and set its structure and uplo properties. bli_obj_set_struc( BLIS_HERMITIAN, &a_save ); bli_obj_set_uplo( uploa, &a_save ); bli_copym( &a, &a_save ); // Apply the remaining parameters. bli_obj_set_conj( conjx, &x ); // Repeat the experiment n_repeats times and record results. for ( i = 0; i < n_repeats; ++i ) { bli_copym( &a_save, &a ); time = bli_clock(); libblis_test_her_impl( iface, &alpha, &x, &a ); time_min = bli_clock_min_diff( time_min, time ); } // Estimate the performance of the best experiment repeat. *perf = ( 1.0 * m * m ) / time_min / FLOPS_PER_UNIT_PERF; if ( bli_obj_is_complex( &a ) ) *perf *= 4.0; // Perform checks. libblis_test_her_check( params, &alpha, &x, &a, &a_save, resid ); // Zero out performance and residual if output matrix is empty. libblis_test_check_empty_problem( &a, perf, resid ); // Free the test objects. bli_obj_free( &x ); bli_obj_free( &a ); bli_obj_free( &a_save ); } void libblis_test_her_impl ( iface_t iface, obj_t* alpha, obj_t* x, obj_t* a ) { switch ( iface ) { case BLIS_TEST_SEQ_FRONT_END: bli_her( alpha, x, a ); break; default: libblis_test_printf_error( "Invalid interface type.\n" ); } } void libblis_test_her_check ( test_params_t* params, obj_t* alpha, obj_t* x, obj_t* a, obj_t* a_orig, double* resid ) { num_t dt = bli_obj_dt( a ); num_t dt_real = bli_obj_dt_proj_to_real( a ); dim_t m_a = bli_obj_length( a ); obj_t xh, t, v, w; obj_t rho, norm; double junk; // // Pre-conditions: // - x is randomized. // - a is randomized and Hermitian. // Note: // - alpha must be real-valued. // // Under these conditions, we assume that the implementation for // // A := A_orig + alpha * conjx(x) * conjx(x)^H // // is functioning correctly if // // normfv( v - w ) // // is negligible, where // // v = A * t // w = ( A_orig + alpha * conjx(x) * conjx(x)^H ) * t // = A_orig * t + alpha * conjx(x) * conjx(x)^H * t // = A_orig * t + alpha * conjx(x) * rho // = A_orig * t + w // bli_mkherm( a ); bli_mkherm( a_orig ); bli_obj_set_struc( BLIS_GENERAL, a ); bli_obj_set_struc( BLIS_GENERAL, a_orig ); bli_obj_set_uplo( BLIS_DENSE, a ); bli_obj_set_uplo( BLIS_DENSE, a_orig ); bli_obj_scalar_init_detached( dt, &rho ); bli_obj_scalar_init_detached( dt_real, &norm ); bli_obj_create( dt, m_a, 1, 0, 0, &t ); bli_obj_create( dt, m_a, 1, 0, 0, &v ); bli_obj_create( dt, m_a, 1, 0, 0, &w ); bli_obj_alias_with_conj( BLIS_CONJUGATE, x, &xh ); libblis_test_vobj_randomize( params, TRUE, &t ); bli_gemv( &BLIS_ONE, a, &t, &BLIS_ZERO, &v ); bli_dotv( &xh, &t, &rho ); bli_mulsc( alpha, &rho ); bli_scal2v( &rho, x, &w ); bli_gemv( &BLIS_ONE, a_orig, &t, &BLIS_ONE, &w ); bli_subv( &w, &v ); bli_normfv( &v, &norm ); bli_getsc( &norm, resid, &junk ); bli_obj_free( &t ); bli_obj_free( &v ); bli_obj_free( &w ); } blis-0.9.0/testsuite/src/test_her.h000066400000000000000000000034761422157504600172770ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void libblis_test_her ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); blis-0.9.0/testsuite/src/test_her2.c000066400000000000000000000247151422157504600173530ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "test_libblis.h" // Static variables. static char* op_str = "her2"; static char* o_types = "vvm"; // x y a static char* p_types = "ucc"; // uploa conjx conjy static thresh_t thresh[BLIS_NUM_FP_TYPES] = { { 1e-04, 1e-05 }, // warn, pass for s { 1e-04, 1e-05 }, // warn, pass for c { 1e-13, 1e-14 }, // warn, pass for d { 1e-13, 1e-14 } }; // warn, pass for z // Local prototypes. void libblis_test_her2_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); void libblis_test_her2_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ); void libblis_test_her2_impl ( iface_t iface, obj_t* alpha, obj_t* x, obj_t* y, obj_t* a ); void libblis_test_her2_check ( test_params_t* params, obj_t* alpha, obj_t* x, obj_t* y, obj_t* a, obj_t* a_orig, double* resid ); void libblis_test_her2_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { libblis_test_randv( tdata, params, &(op->ops->randv) ); libblis_test_randm( tdata, params, &(op->ops->randm) ); libblis_test_normfv( tdata, params, &(op->ops->normfv) ); libblis_test_subv( tdata, params, &(op->ops->subv) ); libblis_test_copym( tdata, params, &(op->ops->copym) ); libblis_test_scal2v( tdata, params, &(op->ops->scal2v) ); libblis_test_dotv( tdata, params, &(op->ops->dotv) ); libblis_test_gemv( tdata, params, &(op->ops->gemv) ); } void libblis_test_her2 ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { // Return early if this test has already been done. if ( libblis_test_op_is_done( op ) ) return; // Return early if operation is disabled. if ( libblis_test_op_is_disabled( op ) || libblis_test_l2_is_disabled( op ) ) return; // Call dependencies first. if ( TRUE ) libblis_test_her2_deps( tdata, params, op ); // Execute the test driver for each implementation requested. //if ( op->front_seq == ENABLE ) { libblis_test_op_driver( tdata, params, op, BLIS_TEST_SEQ_FRONT_END, op_str, p_types, o_types, thresh, libblis_test_her2_experiment ); } } void libblis_test_her2_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ) { unsigned int n_repeats = params->n_repeats; unsigned int i; double time_min = DBL_MAX; double time; num_t datatype; dim_t m; uplo_t uploa; conj_t conjx, conjy; obj_t alpha, x, y, a; obj_t a_save; // Use the datatype of the first char in the datatype combination string. bli_param_map_char_to_blis_dt( dc_str[0], &datatype ); // Map the dimension specifier to an actual dimension. m = libblis_test_get_dim_from_prob_size( op->dim_spec[0], p_cur ); // Map parameter characters to BLIS constants. bli_param_map_char_to_blis_uplo( pc_str[0], &uploa ); bli_param_map_char_to_blis_conj( pc_str[1], &conjx ); bli_param_map_char_to_blis_conj( pc_str[2], &conjy ); // Create test scalars. bli_obj_scalar_init_detached( datatype, &alpha ); // Create test operands (vectors and/or matrices). libblis_test_vobj_create( params, datatype, sc_str[0], m, &x ); libblis_test_vobj_create( params, datatype, sc_str[1], m, &y ); libblis_test_mobj_create( params, datatype, BLIS_NO_TRANSPOSE, sc_str[2], m, m, &a ); libblis_test_mobj_create( params, datatype, BLIS_NO_TRANSPOSE, sc_str[2], m, m, &a_save ); // Set alpha. //bli_copysc( &BLIS_MINUS_ONE, &alpha ); bli_setsc( -1.0, 1.0, &alpha ); // Randomize x and y. libblis_test_vobj_randomize( params, TRUE, &x ); libblis_test_vobj_randomize( params, TRUE, &y ); // Set the structure and uplo properties of A. bli_obj_set_struc( BLIS_HERMITIAN, &a ); bli_obj_set_uplo( uploa, &a ); // Randomize A, make it densely Hermitian, and zero the unstored triangle // to ensure the implementation is reads only from the stored region. libblis_test_mobj_randomize( params, TRUE, &a ); bli_mkherm( &a ); bli_mktrim( &a ); // Save A and set its structure and uplo properties. bli_obj_set_struc( BLIS_HERMITIAN, &a_save ); bli_obj_set_uplo( uploa, &a_save ); bli_copym( &a, &a_save ); // Apply the remaining parameters. bli_obj_set_conj( conjx, &x ); bli_obj_set_conj( conjy, &y ); // Repeat the experiment n_repeats times and record results. for ( i = 0; i < n_repeats; ++i ) { bli_copym( &a_save, &a ); time = bli_clock(); libblis_test_her2_impl( iface, &alpha, &x, &y, &a ); time_min = bli_clock_min_diff( time_min, time ); } // Estimate the performance of the best experiment repeat. *perf = ( 2.0 * m * m ) / time_min / FLOPS_PER_UNIT_PERF; if ( bli_obj_is_complex( &a ) ) *perf *= 4.0; // Perform checks. libblis_test_her2_check( params, &alpha, &x, &y, &a, &a_save, resid ); // Zero out performance and residual if output matrix is empty. libblis_test_check_empty_problem( &a, perf, resid ); // Free the test objects. bli_obj_free( &x ); bli_obj_free( &y ); bli_obj_free( &a ); bli_obj_free( &a_save ); } void libblis_test_her2_impl ( iface_t iface, obj_t* alpha, obj_t* x, obj_t* y, obj_t* a ) { switch ( iface ) { case BLIS_TEST_SEQ_FRONT_END: bli_her2( alpha, x, y, a ); break; default: libblis_test_printf_error( "Invalid interface type.\n" ); } } void libblis_test_her2_check ( test_params_t* params, obj_t* alpha, obj_t* x, obj_t* y, obj_t* a, obj_t* a_orig, double* resid ) { num_t dt = bli_obj_dt( a ); num_t dt_real = bli_obj_dt_proj_to_real( a ); dim_t m_a = bli_obj_length( a ); obj_t xh, yh, alphac; obj_t t, v, w1, w2; obj_t rho, norm; double junk; // // Pre-conditions: // - x is randomized. // - y is randomized. // - a is randomized and Hermitian. // // Under these conditions, we assume that the implementation for // // A := A_orig + alpha * conjx(x) * conjy(y)^H + conj(alpha) * conjy(y) * conjx(x)^H // // is functioning correctly if // // normfv( v - w ) // // is negligible, where // // v = A * t // w = ( A_orig + alpha * conjx(x) * conjy(y)^H + conj(alpha) * conjy(y) * conjx(x)^H ) * t // = A_orig * t + alpha * conjx(x) * conjy(y)^H * t + conj(alpha) * conjy(y) * conjx(x)^H * t // = A_orig * t + alpha * conjx(x) * conjy(y)^H * t + conj(alpha) * conjy(y) * rho // = A_orig * t + alpha * conjx(x) * conjy(y)^H * t + w1 // = A_orig * t + alpha * conjx(x) * rho + w1 // = A_orig * t + w2 + w1 // bli_mkherm( a ); bli_mkherm( a_orig ); bli_obj_set_struc( BLIS_GENERAL, a ); bli_obj_set_struc( BLIS_GENERAL, a_orig ); bli_obj_set_uplo( BLIS_DENSE, a ); bli_obj_set_uplo( BLIS_DENSE, a_orig ); bli_obj_scalar_init_detached( dt, &rho ); bli_obj_scalar_init_detached( dt, &alphac ); bli_obj_scalar_init_detached( dt_real, &norm ); bli_obj_create( dt, m_a, 1, 0, 0, &t ); bli_obj_create( dt, m_a, 1, 0, 0, &v ); bli_obj_create( dt, m_a, 1, 0, 0, &w1 ); bli_obj_create( dt, m_a, 1, 0, 0, &w2 ); bli_obj_alias_with_conj( BLIS_CONJUGATE, x, &xh ); bli_obj_alias_with_conj( BLIS_CONJUGATE, y, &yh ); bli_obj_alias_with_conj( BLIS_CONJUGATE, alpha, &alphac ); libblis_test_vobj_randomize( params, TRUE, &t ); bli_gemv( &BLIS_ONE, a, &t, &BLIS_ZERO, &v ); bli_dotv( &xh, &t, &rho ); bli_mulsc( &alphac, &rho ); bli_scal2v( &rho, y, &w1 ); bli_dotv( &yh, &t, &rho ); bli_mulsc( alpha, &rho ); bli_scal2v( &rho, x, &w2 ); bli_addv( &w2, &w1 ); bli_gemv( &BLIS_ONE, a_orig, &t, &BLIS_ONE, &w1 ); bli_subv( &w1, &v ); bli_normfv( &v, &norm ); bli_getsc( &norm, resid, &junk ); bli_obj_free( &t ); bli_obj_free( &v ); bli_obj_free( &w1 ); bli_obj_free( &w2 ); } blis-0.9.0/testsuite/src/test_her2.h000066400000000000000000000034771422157504600173620ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void libblis_test_her2 ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); blis-0.9.0/testsuite/src/test_her2k.c000066400000000000000000000262141422157504600175220ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "test_libblis.h" // Static variables. static char* op_str = "her2k"; static char* o_types = "mmm"; // a b c static char* p_types = "uhh"; // uploc transa transb static thresh_t thresh[BLIS_NUM_FP_TYPES] = { { 1e-04, 1e-05 }, // warn, pass for s { 1e-04, 1e-05 }, // warn, pass for c { 1e-13, 1e-14 }, // warn, pass for d { 1e-13, 1e-14 } }; // warn, pass for z // Local prototypes. void libblis_test_her2k_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); void libblis_test_her2k_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ); void libblis_test_her2k_impl ( iface_t iface, obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c ); void libblis_test_her2k_check ( test_params_t* params, obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, obj_t* c_orig, double* resid ); void libblis_test_her2k_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { libblis_test_randv( tdata, params, &(op->ops->randv) ); libblis_test_randm( tdata, params, &(op->ops->randm) ); libblis_test_setv( tdata, params, &(op->ops->setv) ); libblis_test_normfv( tdata, params, &(op->ops->normfv) ); libblis_test_subv( tdata, params, &(op->ops->subv) ); libblis_test_scalv( tdata, params, &(op->ops->scalv) ); libblis_test_copym( tdata, params, &(op->ops->copym) ); libblis_test_scalm( tdata, params, &(op->ops->scalm) ); libblis_test_gemv( tdata, params, &(op->ops->gemv) ); libblis_test_hemv( tdata, params, &(op->ops->hemv) ); } void libblis_test_her2k ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { // Return early if this test has already been done. if ( libblis_test_op_is_done( op ) ) return; // Return early if operation is disabled. if ( libblis_test_op_is_disabled( op ) || libblis_test_l3_is_disabled( op ) ) return; // Call dependencies first. if ( TRUE ) libblis_test_her2k_deps( tdata, params, op ); // Execute the test driver for each implementation requested. //if ( op->front_seq == ENABLE ) { libblis_test_op_driver( tdata, params, op, BLIS_TEST_SEQ_FRONT_END, op_str, p_types, o_types, thresh, libblis_test_her2k_experiment ); } } void libblis_test_her2k_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ) { unsigned int n_repeats = params->n_repeats; unsigned int i; double time_min = DBL_MAX; double time; num_t datatype; dim_t m, k; uplo_t uploc; trans_t transa, transb; obj_t alpha, a, b, beta, c; obj_t c_save; // Use the datatype of the first char in the datatype combination string. bli_param_map_char_to_blis_dt( dc_str[0], &datatype ); // Map the dimension specifier to actual dimensions. m = libblis_test_get_dim_from_prob_size( op->dim_spec[0], p_cur ); k = libblis_test_get_dim_from_prob_size( op->dim_spec[1], p_cur ); // Map parameter characters to BLIS constants. bli_param_map_char_to_blis_uplo( pc_str[0], &uploc ); bli_param_map_char_to_blis_trans( pc_str[1], &transa ); bli_param_map_char_to_blis_trans( pc_str[2], &transb ); // Create test scalars. bli_obj_scalar_init_detached( datatype, &alpha ); bli_obj_scalar_init_detached( datatype, &beta ); // Create test operands (vectors and/or matrices). libblis_test_mobj_create( params, datatype, transa, sc_str[1], m, k, &a ); libblis_test_mobj_create( params, datatype, transb, sc_str[2], m, k, &b ); libblis_test_mobj_create( params, datatype, BLIS_NO_TRANSPOSE, sc_str[0], m, m, &c ); libblis_test_mobj_create( params, datatype, BLIS_NO_TRANSPOSE, sc_str[0], m, m, &c_save ); // Set alpha and beta. if ( bli_obj_is_real( &c ) ) { bli_setsc( 0.8, 0.0, &alpha ); bli_setsc( -1.0, 0.0, &beta ); } else { // For her2k, alpha may be complex, but beta must be real-valued // (in order to preserve the Hermitian structure of C). bli_setsc( 0.8, 0.5, &alpha ); bli_setsc( -1.0, 0.0, &beta ); } // Randomize A and B. libblis_test_mobj_randomize( params, TRUE, &a ); libblis_test_mobj_randomize( params, TRUE, &b ); // Set the structure and uplo properties of C. bli_obj_set_struc( BLIS_HERMITIAN, &c ); bli_obj_set_uplo( uploc, &c ); // Randomize A, make it densely Hermitian, and zero the unstored triangle // to ensure the implementation is reads only from the stored region. libblis_test_mobj_randomize( params, TRUE, &c ); bli_mkherm( &c ); bli_mktrim( &c ); // Save C and set its structure and uplo properties. bli_obj_set_struc( BLIS_HERMITIAN, &c_save ); bli_obj_set_uplo( uploc, &c_save ); bli_copym( &c, &c_save ); // Apply the remaining parameters. bli_obj_set_conjtrans( transa, &a ); bli_obj_set_conjtrans( transb, &b ); // Repeat the experiment n_repeats times and record results. for ( i = 0; i < n_repeats; ++i ) { bli_copym( &c_save, &c ); time = bli_clock(); libblis_test_her2k_impl( iface, &alpha, &a, &b, &beta, &c ); time_min = bli_clock_min_diff( time_min, time ); } // Estimate the performance of the best experiment repeat. *perf = ( 2.0 * m * m * k ) / time_min / FLOPS_PER_UNIT_PERF; if ( bli_obj_is_complex( &c ) ) *perf *= 4.0; // Perform checks. libblis_test_her2k_check( params, &alpha, &a, &b, &beta, &c, &c_save, resid ); // Zero out performance and residual if output matrix is empty. libblis_test_check_empty_problem( &c, perf, resid ); // Free the test objects. bli_obj_free( &a ); bli_obj_free( &b ); bli_obj_free( &c ); bli_obj_free( &c_save ); } void libblis_test_her2k_impl ( iface_t iface, obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c ) { switch ( iface ) { case BLIS_TEST_SEQ_FRONT_END: bli_her2k( alpha, a, b, beta, c ); break; default: libblis_test_printf_error( "Invalid interface type.\n" ); } } void libblis_test_her2k_check ( test_params_t* params, obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, obj_t* c_orig, double* resid ) { num_t dt = bli_obj_dt( c ); num_t dt_real = bli_obj_dt_proj_to_real( c ); dim_t m = bli_obj_length( c ); dim_t k = bli_obj_width_after_trans( a ); obj_t alphac, ah, bh; obj_t norm; obj_t t, v, w1, w2, z; double junk; // // Pre-conditions: // - a is randomized. // - b is randomized. // - c_orig is randomized and Hermitian. // Note: // - alpha should have a non-zero imaginary component in the // complex cases in order to more fully exercise the implementation. // - beta must be real-valued. // // Under these conditions, we assume that the implementation for // // C := beta * C_orig + alpha * transa(A) * transb(B)^H + conj(alpha) * transb(B) * transa(A)^H // // is functioning correctly if // // normfv( v - z ) // // is negligible, where // // v = C * t // z = ( beta * C_orig + alpha * transa(A) * transb(B)^H + conj(alpha) * transb(B) * transa(A)^H ) * t // = beta * C_orig * t + alpha * transa(A) * transb(B)^H * t + conj(alpha) * transb(B) * transa(A)^H * t // = beta * C_orig * t + alpha * transa(A) * transb(B)^H * t + conj(alpha) * transb(B) * w2 // = beta * C_orig * t + alpha * transa(A) * w1 + conj(alpha) * transb(B) * w2 // = beta * C_orig * t + alpha * transa(A) * w1 + z // = beta * C_orig * t + z // bli_obj_alias_with_trans( BLIS_CONJ_TRANSPOSE, a, &ah ); bli_obj_alias_with_trans( BLIS_CONJ_TRANSPOSE, b, &bh ); bli_obj_scalar_init_detached( dt_real, &norm ); bli_obj_scalar_init_detached_copy_of( dt, BLIS_CONJUGATE, alpha, &alphac ); bli_obj_create( dt, m, 1, 0, 0, &t ); bli_obj_create( dt, m, 1, 0, 0, &v ); bli_obj_create( dt, k, 1, 0, 0, &w1 ); bli_obj_create( dt, k, 1, 0, 0, &w2 ); bli_obj_create( dt, m, 1, 0, 0, &z ); libblis_test_vobj_randomize( params, TRUE, &t ); bli_hemv( &BLIS_ONE, c, &t, &BLIS_ZERO, &v ); bli_gemv( &BLIS_ONE, &ah, &t, &BLIS_ZERO, &w2 ); bli_gemv( &BLIS_ONE, &bh, &t, &BLIS_ZERO, &w1 ); bli_gemv( alpha, a, &w1, &BLIS_ZERO, &z ); bli_gemv( &alphac, b, &w2, &BLIS_ONE, &z ); bli_hemv( beta, c_orig, &t, &BLIS_ONE, &z ); bli_subv( &z, &v ); bli_normfv( &v, &norm ); bli_getsc( &norm, resid, &junk ); bli_obj_free( &t ); bli_obj_free( &v ); bli_obj_free( &w1 ); bli_obj_free( &w2 ); bli_obj_free( &z ); } blis-0.9.0/testsuite/src/test_her2k.h000066400000000000000000000035001422157504600175200ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void libblis_test_her2k ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); blis-0.9.0/testsuite/src/test_herk.c000066400000000000000000000237411422157504600174420ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "test_libblis.h" // Static variables. static char* op_str = "herk"; static char* o_types = "mm"; // a c static char* p_types = "uh"; // uploc transa static thresh_t thresh[BLIS_NUM_FP_TYPES] = { { 1e-04, 1e-05 }, // warn, pass for s { 1e-04, 1e-05 }, // warn, pass for c { 1e-13, 1e-14 }, // warn, pass for d { 1e-13, 1e-14 } }; // warn, pass for z // Local prototypes. void libblis_test_herk_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); void libblis_test_herk_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ); void libblis_test_herk_impl ( iface_t iface, obj_t* alpha, obj_t* a, obj_t* beta, obj_t* c ); void libblis_test_herk_check ( test_params_t* params, obj_t* alpha, obj_t* a, obj_t* beta, obj_t* c, obj_t* c_orig, double* resid ); void libblis_test_herk_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { libblis_test_randv( tdata, params, &(op->ops->randv) ); libblis_test_randm( tdata, params, &(op->ops->randm) ); libblis_test_setv( tdata, params, &(op->ops->setv) ); libblis_test_normfv( tdata, params, &(op->ops->normfv) ); libblis_test_subv( tdata, params, &(op->ops->subv) ); libblis_test_scalv( tdata, params, &(op->ops->scalv) ); libblis_test_copym( tdata, params, &(op->ops->copym) ); libblis_test_scalm( tdata, params, &(op->ops->scalm) ); libblis_test_gemv( tdata, params, &(op->ops->gemv) ); libblis_test_hemv( tdata, params, &(op->ops->hemv) ); } void libblis_test_herk ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { // Return early if this test has already been done. if ( libblis_test_op_is_done( op ) ) return; // Return early if operation is disabled. if ( libblis_test_op_is_disabled( op ) || libblis_test_l3_is_disabled( op ) ) return; // Call dependencies first. if ( TRUE ) libblis_test_herk_deps( tdata, params, op ); // Execute the test driver for each implementation requested. //if ( op->front_seq == ENABLE ) { libblis_test_op_driver( tdata, params, op, BLIS_TEST_SEQ_FRONT_END, op_str, p_types, o_types, thresh, libblis_test_herk_experiment ); } } void libblis_test_herk_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ) { unsigned int n_repeats = params->n_repeats; unsigned int i; double time_min = DBL_MAX; double time; num_t datatype; dim_t m, k; uplo_t uploc; trans_t transa; obj_t alpha, a, beta, c; obj_t c_save; // Use the datatype of the first char in the datatype combination string. bli_param_map_char_to_blis_dt( dc_str[0], &datatype ); // Map the dimension specifier to actual dimensions. m = libblis_test_get_dim_from_prob_size( op->dim_spec[0], p_cur ); k = libblis_test_get_dim_from_prob_size( op->dim_spec[1], p_cur ); // Map parameter characters to BLIS constants. bli_param_map_char_to_blis_uplo( pc_str[0], &uploc ); bli_param_map_char_to_blis_trans( pc_str[1], &transa ); // Create test scalars. bli_obj_scalar_init_detached( datatype, &alpha ); bli_obj_scalar_init_detached( datatype, &beta ); // Create test operands (vectors and/or matrices). libblis_test_mobj_create( params, datatype, transa, sc_str[1], m, k, &a ); libblis_test_mobj_create( params, datatype, BLIS_NO_TRANSPOSE, sc_str[0], m, m, &c ); libblis_test_mobj_create( params, datatype, BLIS_NO_TRANSPOSE, sc_str[0], m, m, &c_save ); // Set alpha and beta. if ( bli_obj_is_real( &c ) ) { bli_setsc( 1.2, 0.0, &alpha ); bli_setsc( -1.0, 0.0, &beta ); } else { // For herk, alpha and beta must both be real-valued, even in the // complex case (in order to preserve the Hermitian structure of C). bli_setsc( 1.2, 0.0, &alpha ); bli_setsc( -1.0, 0.0, &beta ); } // Randomize A. libblis_test_mobj_randomize( params, TRUE, &a ); // Set the structure and uplo properties of C. bli_obj_set_struc( BLIS_HERMITIAN, &c ); bli_obj_set_uplo( uploc, &c ); // Randomize A, make it densely Hermitian, and zero the unstored triangle // to ensure the implementation is reads only from the stored region. libblis_test_mobj_randomize( params, TRUE, &c ); bli_mkherm( &c ); bli_mktrim( &c ); // Save C and set its structure and uplo properties. bli_obj_set_struc( BLIS_HERMITIAN, &c_save ); bli_obj_set_uplo( uploc, &c_save ); bli_copym( &c, &c_save ); // Apply the remaining parameters. bli_obj_set_conjtrans( transa, &a ); // Repeat the experiment n_repeats times and record results. for ( i = 0; i < n_repeats; ++i ) { bli_copym( &c_save, &c ); time = bli_clock(); libblis_test_herk_impl( iface, &alpha, &a, &beta, &c ); time_min = bli_clock_min_diff( time_min, time ); } // Estimate the performance of the best experiment repeat. *perf = ( 1.0 * m * m * k ) / time_min / FLOPS_PER_UNIT_PERF; if ( bli_obj_is_complex( &c ) ) *perf *= 4.0; // Perform checks. libblis_test_herk_check( params, &alpha, &a, &beta, &c, &c_save, resid ); // Zero out performance and residual if output matrix is empty. libblis_test_check_empty_problem( &c, perf, resid ); // Free the test objects. bli_obj_free( &a ); bli_obj_free( &c ); bli_obj_free( &c_save ); } void libblis_test_herk_impl ( iface_t iface, obj_t* alpha, obj_t* a, obj_t* beta, obj_t* c ) { switch ( iface ) { case BLIS_TEST_SEQ_FRONT_END: bli_herk( alpha, a, beta, c ); break; default: libblis_test_printf_error( "Invalid interface type.\n" ); } } void libblis_test_herk_check ( test_params_t* params, obj_t* alpha, obj_t* a, obj_t* beta, obj_t* c, obj_t* c_orig, double* resid ) { num_t dt = bli_obj_dt( c ); num_t dt_real = bli_obj_dt_proj_to_real( c ); dim_t m = bli_obj_length( c ); dim_t k = bli_obj_width_after_trans( a ); obj_t ah; obj_t norm; obj_t t, v, w, z; double junk; // // Pre-conditions: // - a is randomized. // - c_orig is randomized and Hermitian. // Note: // - alpha and beta must be real-valued. // // Under these conditions, we assume that the implementation for // // C := beta * C_orig + alpha * transa(A) * transa(A)^H // // is functioning correctly if // // normfv( v - z ) // // is negligible, where // // v = C * t // z = ( beta * C_orig + alpha * transa(A) * transa(A)^H ) * t // = beta * C_orig * t + alpha * transa(A) * transa(A)^H * t // = beta * C_orig * t + alpha * transa(A) * w // = beta * C_orig * t + z // bli_obj_alias_with_trans( BLIS_CONJ_TRANSPOSE, a, &ah ); bli_obj_scalar_init_detached( dt_real, &norm ); bli_obj_create( dt, m, 1, 0, 0, &t ); bli_obj_create( dt, m, 1, 0, 0, &v ); bli_obj_create( dt, k, 1, 0, 0, &w ); bli_obj_create( dt, m, 1, 0, 0, &z ); libblis_test_vobj_randomize( params, TRUE, &t ); bli_hemv( &BLIS_ONE, c, &t, &BLIS_ZERO, &v ); bli_gemv( &BLIS_ONE, &ah, &t, &BLIS_ZERO, &w ); bli_gemv( alpha, a, &w, &BLIS_ZERO, &z ); bli_hemv( beta, c_orig, &t, &BLIS_ONE, &z ); bli_subv( &z, &v ); bli_normfv( &v, &norm ); bli_getsc( &norm, resid, &junk ); bli_obj_free( &t ); bli_obj_free( &v ); bli_obj_free( &w ); bli_obj_free( &z ); } blis-0.9.0/testsuite/src/test_herk.h000066400000000000000000000034771422157504600174530ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void libblis_test_herk ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); blis-0.9.0/testsuite/src/test_libblis.c000066400000000000000000003632671422157504600201430ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "test_libblis.h" // Global variables. char libblis_test_binary_name[ MAX_BINARY_NAME_LENGTH + 1 ]; char libblis_test_parameters_filename[ MAX_FILENAME_LENGTH + 1 ]; char libblis_test_operations_filename[ MAX_FILENAME_LENGTH + 1 ]; char libblis_test_pass_string[ MAX_PASS_STRING_LENGTH + 1 ]; char libblis_test_warn_string[ MAX_PASS_STRING_LENGTH + 1 ]; char libblis_test_fail_string[ MAX_PASS_STRING_LENGTH + 1 ]; char libblis_test_store_chars[ NUM_OPERAND_TYPES ][ MAX_STORE_VALS_PER_TYPE + 1 ]; char libblis_test_param_chars[ NUM_PARAM_TYPES ][ MAX_PARAM_VALS_PER_TYPE + 1 ]; char libblis_test_sp_chars[ 2 + 1 ] = "sc"; char libblis_test_dp_chars[ 2 + 1 ] = "dz"; char libblis_test_rd_chars[ 2 + 1 ] = "sd"; char libblis_test_cd_chars[ 2 + 1 ] = "cz"; char libblis_test_dt_chars[ 4 + 1 ] = "sdcz"; int main( int argc, char** argv ) { test_params_t params; test_ops_t ops; // Initialize libblis. //bli_init(); // Initialize some strings. libblis_test_init_strings(); // Parse the command line parameters. libblis_test_parse_command_line( argc, argv ); // Read the global parameters file. libblis_test_read_params_file( libblis_test_parameters_filename, ¶ms ); // Read the operations parameter file. libblis_test_read_ops_file( libblis_test_operations_filename, &ops ); // Walk through all test modules. //libblis_test_all_ops( ¶ms, &ops ); libblis_test_thread_decorator( ¶ms, &ops ); // Finalize libblis. bli_finalize(); // Return peacefully. return 0; } #if 0 typedef struct thread_data { test_params_t* params; test_ops_t* ops; unsigned int nt; unsigned int id; unsigned int xc; //pthread_mutex_t* mutex; pthread_barrier_t* barrier; } thread_data_t; #endif void* libblis_test_thread_entry( void* tdata_void ) { thread_data_t* tdata = tdata_void; test_params_t* params = tdata->params; test_ops_t* ops = tdata->ops; // Walk through all test modules. libblis_test_all_ops( tdata, params, ops ); return NULL; } void libblis_test_thread_decorator( test_params_t* params, test_ops_t* ops ) { err_t r_val; // Query the total number of threads to simulate. size_t nt = ( size_t )params->n_app_threads; // Allocate an array of pthread objects and auxiliary data structs to pass // to the thread entry functions. #ifdef BLIS_ENABLE_MEM_TRACING printf( "libblis_test_thread_decorator(): " ); #endif bli_pthread_t* pthread = bli_malloc_user( sizeof( bli_pthread_t ) * nt, &r_val ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "libblis_test_thread_decorator(): " ); #endif thread_data_t* tdata = bli_malloc_user( sizeof( thread_data_t ) * nt, &r_val ); // Allocate a mutex for the threads to share. //bli_pthread_mutex_t* mutex = bli_malloc_user( sizeof( bli_pthread_mutex_t ) ); // Allocate a barrier for the threads to share. #ifdef BLIS_ENABLE_MEM_TRACING printf( "libblis_test_thread_decorator(): " ); #endif bli_pthread_barrier_t* barrier = bli_malloc_user( sizeof( bli_pthread_barrier_t ), &r_val ); // Initialize the mutex. //bli_pthread_mutex_init( mutex, NULL ); // Initialize the barrier for nt threads. bli_pthread_barrier_init( barrier, NULL, nt ); // NOTE: We must iterate backwards so that the chief thread (thread id 0) // can spawn all other threads before proceeding with its own computation. // ALSO: Since we need to let the counter go negative, id must be a signed // integer here. for ( signed int id = nt - 1; 0 <= id; id-- ) { tdata[id].params = params; tdata[id].ops = ops; tdata[id].nt = nt; tdata[id].id = id; tdata[id].xc = 0; //tdata[id].mutex = mutex; tdata[id].barrier = barrier; // Spawn additional threads for ids greater than 1. if ( id != 0 ) bli_pthread_create( &pthread[id], NULL, libblis_test_thread_entry, &tdata[id] ); else libblis_test_thread_entry( ( void* )(&tdata[0]) ); } // Thread 0 waits for additional threads to finish. for ( unsigned int id = 1; id < nt; id++ ) { bli_pthread_join( pthread[id], NULL ); } // Destroy the mutex. //bli_pthread_mutex_destroy( mutex ); // Destroy the barrier. bli_pthread_barrier_destroy( barrier ); // Free the pthread-related memory. #ifdef BLIS_ENABLE_MEM_TRACING printf( "libblis_test_thread_decorator(): " ); #endif bli_free_user( pthread ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "libblis_test_thread_decorator(): " ); #endif bli_free_user( tdata ); #ifdef BLIS_ENABLE_MEM_TRACING printf( "libblis_test_thread_decorator(): " ); #endif //bli_free_user( mutex ); bli_free_user( barrier ); } void libblis_test_all_ops( thread_data_t* tdata, test_params_t* params, test_ops_t* ops ) { // Test the utility operations. libblis_test_utility_ops( tdata, params, ops ); // Test the level-1v operations. libblis_test_level1v_ops( tdata, params, ops ); // Test the level-1m operations. libblis_test_level1m_ops( tdata, params, ops ); // Test the level-1f operations. libblis_test_level1f_ops( tdata, params, ops ); // Test the level-2 operations. libblis_test_level2_ops( tdata, params, ops ); // Test the level-3 micro-kernels. libblis_test_level3_ukrs( tdata, params, ops ); // Test the level-3 operations. libblis_test_level3_ops( tdata, params, ops ); } void libblis_test_utility_ops( thread_data_t* tdata, test_params_t* params, test_ops_t* ops ) { libblis_test_randv( tdata, params, &(ops->randv) ); libblis_test_randm( tdata, params, &(ops->randm) ); } void libblis_test_level1v_ops( thread_data_t* tdata, test_params_t* params, test_ops_t* ops ) { libblis_test_addv( tdata, params, &(ops->addv) ); libblis_test_amaxv( tdata, params, &(ops->amaxv) ); libblis_test_axpbyv( tdata, params, &(ops->axpbyv) ); libblis_test_axpyv( tdata, params, &(ops->axpyv) ); libblis_test_copyv( tdata, params, &(ops->copyv) ); libblis_test_dotv( tdata, params, &(ops->dotv) ); libblis_test_dotxv( tdata, params, &(ops->dotxv) ); libblis_test_normfv( tdata, params, &(ops->normfv) ); libblis_test_scalv( tdata, params, &(ops->scalv) ); libblis_test_scal2v( tdata, params, &(ops->scal2v) ); libblis_test_setv( tdata, params, &(ops->setv) ); libblis_test_subv( tdata, params, &(ops->subv) ); libblis_test_xpbyv( tdata, params, &(ops->xpbyv) ); } void libblis_test_level1m_ops( thread_data_t* tdata, test_params_t* params, test_ops_t* ops ) { libblis_test_addm( tdata, params, &(ops->addm) ); libblis_test_axpym( tdata, params, &(ops->axpym) ); libblis_test_copym( tdata, params, &(ops->copym) ); libblis_test_normfm( tdata, params, &(ops->normfm) ); libblis_test_scalm( tdata, params, &(ops->scalm) ); libblis_test_scal2m( tdata, params, &(ops->scal2m) ); libblis_test_setm( tdata, params, &(ops->setm) ); libblis_test_subm( tdata, params, &(ops->subm) ); libblis_test_xpbym( tdata, params, &(ops->xpbym) ); } void libblis_test_level1f_ops( thread_data_t* tdata, test_params_t* params, test_ops_t* ops ) { libblis_test_axpy2v( tdata, params, &(ops->axpy2v) ); libblis_test_dotaxpyv( tdata, params, &(ops->dotaxpyv) ); libblis_test_axpyf( tdata, params, &(ops->axpyf) ); libblis_test_dotxf( tdata, params, &(ops->dotxf) ); libblis_test_dotxaxpyf( tdata, params, &(ops->dotxaxpyf) ); } void libblis_test_level2_ops( thread_data_t* tdata, test_params_t* params, test_ops_t* ops ) { libblis_test_gemv( tdata, params, &(ops->gemv) ); libblis_test_ger( tdata, params, &(ops->ger) ); libblis_test_hemv( tdata, params, &(ops->hemv) ); libblis_test_her( tdata, params, &(ops->her) ); libblis_test_her2( tdata, params, &(ops->her2) ); libblis_test_symv( tdata, params, &(ops->symv) ); libblis_test_syr( tdata, params, &(ops->syr) ); libblis_test_syr2( tdata, params, &(ops->syr2) ); libblis_test_trmv( tdata, params, &(ops->trmv) ); libblis_test_trsv( tdata, params, &(ops->trsv) ); } void libblis_test_level3_ukrs( thread_data_t* tdata, test_params_t* params, test_ops_t* ops ) { libblis_test_gemm_ukr( tdata, params, &(ops->gemm_ukr) ); libblis_test_trsm_ukr( tdata, params, &(ops->trsm_ukr) ); libblis_test_gemmtrsm_ukr( tdata, params, &(ops->gemmtrsm_ukr) ); } void libblis_test_level3_ops( thread_data_t* tdata, test_params_t* params, test_ops_t* ops ) { libblis_test_gemm( tdata, params, &(ops->gemm) ); libblis_test_gemmt( tdata, params, &(ops->gemmt) ); libblis_test_hemm( tdata, params, &(ops->hemm) ); libblis_test_herk( tdata, params, &(ops->herk) ); libblis_test_her2k( tdata, params, &(ops->her2k) ); libblis_test_symm( tdata, params, &(ops->symm) ); libblis_test_syrk( tdata, params, &(ops->syrk) ); libblis_test_syr2k( tdata, params, &(ops->syr2k) ); libblis_test_trmm( tdata, params, &(ops->trmm) ); libblis_test_trmm3( tdata, params, &(ops->trmm3) ); libblis_test_trsm( tdata, params, &(ops->trsm) ); } void libblis_test_read_ops_file( char* input_filename, test_ops_t* ops ) { FILE* input_stream; // Attempt to open input file corresponding to input_filename as // read-only/binary. input_stream = fopen( input_filename, "rb" ); libblis_test_fopen_check_stream( input_filename, input_stream ); // Initialize the individual override field to FALSE. ops->indiv_over = FALSE; // Begin reading operations input file. // Section overrides libblis_test_read_section_override( ops, input_stream, &(ops->util_over) ); libblis_test_read_section_override( ops, input_stream, &(ops->l1v_over) ); libblis_test_read_section_override( ops, input_stream, &(ops->l1m_over) ); libblis_test_read_section_override( ops, input_stream, &(ops->l1f_over) ); libblis_test_read_section_override( ops, input_stream, &(ops->l2_over) ); libblis_test_read_section_override( ops, input_stream, &(ops->l3ukr_over) ); libblis_test_read_section_override( ops, input_stream, &(ops->l3_over) ); // dimensions n_param operation // Utility operations libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_DIMS_M, 0, &(ops->randv) ); libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_DIMS_MN, 0, &(ops->randm) ); // Level-1v libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_DIMS_M, 1, &(ops->addv) ); libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_DIMS_M, 0, &(ops->amaxv) ); libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_DIMS_M, 1, &(ops->axpbyv) ); libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_DIMS_M, 1, &(ops->axpyv) ); libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_DIMS_M, 1, &(ops->copyv) ); libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_DIMS_M, 2, &(ops->dotv) ); libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_DIMS_M, 2, &(ops->dotxv) ); libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_DIMS_M, 0, &(ops->normfv) ); libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_DIMS_M, 1, &(ops->scalv) ); libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_DIMS_M, 1, &(ops->scal2v) ); libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_DIMS_M, 0, &(ops->setv) ); libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_DIMS_M, 1, &(ops->subv) ); libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_DIMS_M, 1, &(ops->xpbyv) ); // Level-1m libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_DIMS_MN, 1, &(ops->addm) ); libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_DIMS_MN, 1, &(ops->axpym) ); libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_DIMS_MN, 1, &(ops->copym) ); libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_DIMS_MN, 0, &(ops->normfm) ); libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_DIMS_MN, 1, &(ops->scalm) ); libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_DIMS_MN, 1, &(ops->scal2m) ); libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_DIMS_MN, 0, &(ops->setm) ); libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_DIMS_MN, 1, &(ops->subm) ); libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_DIMS_MN, 1, &(ops->xpbym) ); // Level-1f libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_DIMS_M, 2, &(ops->axpy2v) ); libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_DIMS_M, 3, &(ops->dotaxpyv) ); libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_DIMS_MF, 2, &(ops->axpyf) ); libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_DIMS_MF, 2, &(ops->dotxf) ); libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_DIMS_MF, 4, &(ops->dotxaxpyf) ); // Level-2 libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_DIMS_MN, 2, &(ops->gemv) ); libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_DIMS_MN, 2, &(ops->ger) ); libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_DIMS_M, 3, &(ops->hemv) ); libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_DIMS_M, 2, &(ops->her) ); libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_DIMS_M, 3, &(ops->her2) ); libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_DIMS_M, 3, &(ops->symv) ); libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_DIMS_M, 2, &(ops->syr) ); libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_DIMS_M, 3, &(ops->syr2) ); libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_DIMS_M, 3, &(ops->trmv) ); libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_DIMS_M, 3, &(ops->trsv) ); // Level-3 micro-kernels libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_DIMS_K, 0, &(ops->gemm_ukr) ); libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_NO_DIMS, 1, &(ops->trsm_ukr) ); libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_DIMS_K, 1, &(ops->gemmtrsm_ukr) ); // Level-3 libblis_test_read_op_info( ops, input_stream, BLIS_GEMM, BLIS_TEST_DIMS_MNK, 2, &(ops->gemm) ); libblis_test_read_op_info( ops, input_stream, BLIS_GEMMT, BLIS_TEST_DIMS_MK, 3, &(ops->gemmt) ); libblis_test_read_op_info( ops, input_stream, BLIS_HEMM, BLIS_TEST_DIMS_MN, 4, &(ops->hemm) ); libblis_test_read_op_info( ops, input_stream, BLIS_HERK, BLIS_TEST_DIMS_MK, 2, &(ops->herk) ); libblis_test_read_op_info( ops, input_stream, BLIS_HER2K, BLIS_TEST_DIMS_MK, 3, &(ops->her2k) ); libblis_test_read_op_info( ops, input_stream, BLIS_SYMM, BLIS_TEST_DIMS_MN, 4, &(ops->symm) ); libblis_test_read_op_info( ops, input_stream, BLIS_SYRK, BLIS_TEST_DIMS_MK, 2, &(ops->syrk) ); libblis_test_read_op_info( ops, input_stream, BLIS_SYR2K, BLIS_TEST_DIMS_MK, 3, &(ops->syr2k) ); libblis_test_read_op_info( ops, input_stream, BLIS_TRMM, BLIS_TEST_DIMS_MN, 4, &(ops->trmm) ); libblis_test_read_op_info( ops, input_stream, BLIS_TRMM3, BLIS_TEST_DIMS_MN, 5, &(ops->trmm3) ); libblis_test_read_op_info( ops, input_stream, BLIS_TRSM, BLIS_TEST_DIMS_MN, 4, &(ops->trsm) ); // Output the section overrides. libblis_test_output_section_overrides( stdout, ops ); // Close the file. fclose( input_stream ); } void libblis_test_read_params_file( char* input_filename, test_params_t* params ) { FILE* input_stream; char buffer[ INPUT_BUFFER_SIZE ]; char temp[ INPUT_BUFFER_SIZE ]; int i; // Attempt to open input file corresponding to input_filename as // read-only/binary. input_stream = fopen( input_filename, "rb" ); libblis_test_fopen_check_stream( input_filename, input_stream ); // Read the number of repeats. libblis_test_read_next_line( buffer, input_stream ); sscanf( buffer, "%u ", &(params->n_repeats) ); // Read the matrix storage schemes to test. We should have at most three: // 'r' for row-major, 'c' for column-major, and 'g' for general strides. libblis_test_read_next_line( buffer, input_stream ); sscanf( buffer, "%s ", temp ); params->n_mstorage = strlen( temp ); if ( params->n_mstorage > MAX_NUM_MSTORAGE ) { libblis_test_printf_error( "Detected too many matrix storage schemes (%u) in input file.\n", params->n_mstorage ); } strcpy( params->storage[ BLIS_TEST_MATRIX_OPERAND ], temp ); // Read the vector storage schemes to test. We should have at most four: // 'r' for row vectors with unit stride, 'c' for column vectors with unit // stride, 'i' for row vectors with non-unit stride, and 'j' for column // vectors with non-unit stride. libblis_test_read_next_line( buffer, input_stream ); sscanf( buffer, "%s ", temp ); params->n_vstorage = strlen( temp ); if ( params->n_vstorage > MAX_NUM_VSTORAGE ) { libblis_test_printf_error( "Detected too many vector storage schemes (%u) in input file.\n", params->n_vstorage ); } strcpy( params->storage[ BLIS_TEST_VECTOR_OPERAND ], temp ); // Read whether to mix all storage combinations. libblis_test_read_next_line( buffer, input_stream ); sscanf( buffer, "%u ", &(params->mix_all_storage) ); // Read whether to perform all tests with aligned addresses and ldims. libblis_test_read_next_line( buffer, input_stream ); sscanf( buffer, "%u ", &(params->alignment) ); // Read the randomization method. libblis_test_read_next_line( buffer, input_stream ); sscanf( buffer, "%u ", &(params->rand_method) ); if ( params->rand_method != BLIS_TEST_RAND_REAL_VALUES && params->rand_method != BLIS_TEST_RAND_NARROW_POW2 ) { libblis_test_printf_error( "Invalid randomization method (%u) in input file.\n", params->rand_method ); } // Read the general stride "spacing". libblis_test_read_next_line( buffer, input_stream ); sscanf( buffer, "%u ", &(params->gs_spacing) ); // Overwrite the existing storage character arrays with the sets provided. strcpy( libblis_test_store_chars[BLIS_TEST_MATRIX_OPERAND], params->storage[BLIS_TEST_MATRIX_OPERAND] ); strcpy( libblis_test_store_chars[BLIS_TEST_VECTOR_OPERAND], params->storage[BLIS_TEST_VECTOR_OPERAND] ); // Read the datatypes to test. We should have at most four: 's', 'd', 'c', // and 'z'. libblis_test_read_next_line( buffer, input_stream ); sscanf( buffer, "%s ", temp ); params->n_datatypes = strlen( temp ); if ( params->n_datatypes > MAX_NUM_DATATYPES ) { libblis_test_printf_error( "Detected too many datatype requests (%u) in input file.\n", params->n_datatypes ); } for( i = 0; i < params->n_datatypes; ++i ) { //if ( temp[i] == 's' ) params->datatype[i] = BLIS_FLOAT; //else if ( temp[i] == 'd' ) params->datatype[i] = BLIS_DOUBLE; //else if ( temp[i] == 'c' ) params->datatype[i] = BLIS_SCOMPLEX; //else if ( temp[i] == 'z' ) params->datatype[i] = BLIS_DCOMPLEX; // Map the char in temp[i] to the corresponding num_t value. bli_param_map_char_to_blis_dt( temp[i], &(params->datatype[i]) ); params->datatype_char[i] = temp[i]; } // Read whether to test gemm with mixed-domain operands. libblis_test_read_next_line( buffer, input_stream ); sscanf( buffer, "%u ", &(params->mixed_domain) ); // Read whether to test gemm with mixed-precision operands. libblis_test_read_next_line( buffer, input_stream ); sscanf( buffer, "%u ", &(params->mixed_precision) ); // Read the initial problem size to test. libblis_test_read_next_line( buffer, input_stream ); sscanf( buffer, "%u ", &(params->p_first) ); // Read the maximum problem size to test. libblis_test_read_next_line( buffer, input_stream ); sscanf( buffer, "%u ", &(params->p_max) ); // Read the problem size increment to test. libblis_test_read_next_line( buffer, input_stream ); sscanf( buffer, "%u ", &(params->p_inc) ); // Read whether to enable 1m. libblis_test_read_next_line( buffer, input_stream ); sscanf( buffer, "%u ", &(params->ind_enable[ BLIS_1M ]) ); // Read whether to native (complex) execution. libblis_test_read_next_line( buffer, input_stream ); sscanf( buffer, "%u ", &(params->ind_enable[ BLIS_NAT ]) ); // Read whether to simulate application-level threading. libblis_test_read_next_line( buffer, input_stream ); sscanf( buffer, "%u ", &(params->n_app_threads) ); // Silently interpret non-positive numbers the same as 1. if ( params->n_app_threads < 1 ) params->n_app_threads = 1; // Disable induced methods when simulating more than one application // threads. if ( params->n_app_threads > 1 ) { if ( params->ind_enable[ BLIS_1M ] ) { // Due to an inherent race condition in the way induced methods // are enabled and disabled at runtime, all induced methods must be // disabled when simulating multiple application threads. libblis_test_printf_infoc( "simulating multiple application threads; disabling induced methods.\n" ); params->ind_enable[ BLIS_1M ] = 0; } } // Read the requested error-checking level. libblis_test_read_next_line( buffer, input_stream ); sscanf( buffer, "%u ", &(params->error_checking_level) ); // Read the requested course of action if a test fails. libblis_test_read_next_line( buffer, input_stream ); sscanf( buffer, "%c ", &(params->reaction_to_failure) ); if ( params->reaction_to_failure != ON_FAILURE_IGNORE_CHAR && params->reaction_to_failure != ON_FAILURE_SLEEP_CHAR && params->reaction_to_failure != ON_FAILURE_ABORT_CHAR ) { libblis_test_printf_error( "Invalid reaction-to-failure character code (%c) in input file.\n", params->reaction_to_failure ); } // Read whether to output in matlab format. libblis_test_read_next_line( buffer, input_stream ); sscanf( buffer, "%u ", &(params->output_matlab_format) ); // Read whether to output to files in addition to stdout. libblis_test_read_next_line( buffer, input_stream ); sscanf( buffer, "%u ", &(params->output_files) ); // Close the file. fclose( input_stream ); // Output the parameter struct. libblis_test_output_params_struct( stdout, params ); } void libblis_test_read_section_override( test_ops_t* ops, FILE* input_stream, int* override ) { char buffer[ INPUT_BUFFER_SIZE ]; // Read the line for the section override switch. libblis_test_read_next_line( buffer, input_stream ); sscanf( buffer, "%d ", override ); } void libblis_test_read_op_info( test_ops_t* ops, FILE* input_stream, opid_t opid, dimset_t dimset, unsigned int n_params, test_op_t* op ) { char buffer[ INPUT_BUFFER_SIZE ]; char temp[ INPUT_BUFFER_SIZE ]; int i, p; // Initialize the operation type field. op->opid = opid; // Read the line for the overall operation switch. libblis_test_read_next_line( buffer, input_stream ); sscanf( buffer, "%d ", &(op->op_switch) ); // Check the op_switch for the individual override value. if ( op->op_switch == ENABLE_ONLY ) { ops->indiv_over = TRUE; } op->n_dims = libblis_test_get_n_dims_from_dimset( dimset ); op->dimset = dimset; if ( op->n_dims > MAX_NUM_DIMENSIONS ) { libblis_test_printf_error( "Detected too many dimensions (%u) in input file to store.\n", op->n_dims ); } //printf( "n_dims = %u\n", op->n_dims ); // If there is at least one dimension for the current operation, read the // dimension specifications, which encode the actual dimensions or the // dimension ratios for each dimension. if ( op->n_dims > 0 ) { libblis_test_read_next_line( buffer, input_stream ); for ( i = 0, p = 0; i < op->n_dims; ++i ) { //printf( "buffer[p]: %s\n", &buffer[p] ); // Advance until we hit non-whitespace (ie: the next number). for ( ; isspace( buffer[p] ); ++p ) ; //printf( "buffer[p] after: %s\n", &buffer[p] ); sscanf( &buffer[p], "%d", &(op->dim_spec[i]) ); //printf( "dim[%d] = %d\n", i, op->dim_spec[i] ); // Advance until we hit whitespace (ie: the space before the next number). for ( ; !isspace( buffer[p] ); ++p ) ; } } // If there is at least one parameter for the current operation, read the // parameter chars, which encode which parameter combinations to test. if ( n_params > 0 ) { libblis_test_read_next_line( buffer, input_stream ); sscanf( buffer, "%s ", temp ); op->n_params = strlen( temp ); if ( op->n_params > MAX_NUM_PARAMETERS ) { libblis_test_printf_error( "Detected too many parameters (%u) in input file.\n", op->n_params ); } if ( op->n_params != n_params ) { libblis_test_printf_error( "Number of parameters specified by caller does not match length of parameter string in input file. strlen( temp ) = %u; n_params = %u\n", op->n_params, n_params ); } strcpy( op->params, temp ); } else { op->n_params = 0; strcpy( op->params, "" ); } // Initialize the "test done" switch. op->test_done = FALSE; // Initialize the parent pointer. op->ops = ops; } void libblis_test_output_section_overrides( FILE* os, test_ops_t* ops ) { libblis_test_fprintf_c( os, "\n" ); libblis_test_fprintf_c( os, "--- Section overrides ---\n" ); libblis_test_fprintf_c( os, "\n" ); libblis_test_fprintf_c( os, "Utility operations %d\n", ops->util_over ); libblis_test_fprintf_c( os, "Level-1v operations %d\n", ops->l1v_over ); libblis_test_fprintf_c( os, "Level-1m operations %d\n", ops->l1m_over ); libblis_test_fprintf_c( os, "Level-1f operations %d\n", ops->l1f_over ); libblis_test_fprintf_c( os, "Level-2 operations %d\n", ops->l2_over ); libblis_test_fprintf_c( os, "Level-3 micro-kernels %d\n", ops->l3ukr_over ); libblis_test_fprintf_c( os, "Level-3 operations %d\n", ops->l3_over ); libblis_test_fprintf_c( os, "\n" ); libblis_test_fprintf( os, "\n" ); } void libblis_test_output_params_struct( FILE* os, test_params_t* params ) { int i; //char int_type_size_str[8]; gint_t int_type_size; ind_t im; cntx_t* cntx; cntx_t* cntx_c; cntx_t* cntx_z; // If bli_info_get_int_type_size() returns 32 or 64, the size is forced. // Otherwise, the size is chosen automatically. We query the result of // that automatic choice via sizeof(gint_t). if ( bli_info_get_int_type_size() == 32 || bli_info_get_int_type_size() == 64 ) int_type_size = bli_info_get_int_type_size(); else int_type_size = sizeof(gint_t) * 8; char impl_str[16]; char jrir_str[16]; // Describe the threading implementation. if ( bli_info_get_enable_openmp() ) sprintf( impl_str, "openmp" ); else if ( bli_info_get_enable_pthreads() ) sprintf( impl_str, "pthreads" ); else /* threading disabled */ sprintf( impl_str, "disabled" ); // Describe the status of jrir thread partitioning. if ( bli_info_get_thread_part_jrir_slab() ) sprintf( jrir_str, "slab" ); else /*bli_info_get_thread_part_jrir_rr()*/ sprintf( jrir_str, "round-robin" ); char nt_str[16]; char jc_nt_str[16]; char pc_nt_str[16]; char ic_nt_str[16]; char jr_nt_str[16]; char ir_nt_str[16]; // Query the number of ways of parallelism per loop (and overall) and // convert these values into strings, with "unset" being used if the // value returned was -1 (indicating the environment variable was unset). dim_t nt = bli_thread_get_num_threads(); dim_t jc_nt = bli_thread_get_jc_nt(); dim_t pc_nt = bli_thread_get_pc_nt(); dim_t ic_nt = bli_thread_get_ic_nt(); dim_t jr_nt = bli_thread_get_jr_nt(); dim_t ir_nt = bli_thread_get_ir_nt(); if ( nt == -1 ) sprintf( nt_str, "unset" ); else sprintf( nt_str, "%d", ( int ) nt ); if ( jc_nt == -1 ) sprintf( jc_nt_str, "unset" ); else sprintf( jc_nt_str, "%d", ( int )jc_nt ); if ( pc_nt == -1 ) sprintf( pc_nt_str, "unset" ); else sprintf( pc_nt_str, "%d", ( int )pc_nt ); if ( ic_nt == -1 ) sprintf( ic_nt_str, "unset" ); else sprintf( ic_nt_str, "%d", ( int )ic_nt ); if ( jr_nt == -1 ) sprintf( jr_nt_str, "unset" ); else sprintf( jr_nt_str, "%d", ( int )jr_nt ); if ( ir_nt == -1 ) sprintf( ir_nt_str, "unset" ); else sprintf( ir_nt_str, "%d", ( int )ir_nt ); // Set up rntm_t objects for each of the four families: // gemm, herk, trmm, trsm. rntm_t gemm, herk, trmm_l, trmm_r, trsm_l, trsm_r; dim_t m = 1000, n = 1000, k = 1000; bli_rntm_init_from_global( &gemm ); bli_rntm_init_from_global( &herk ); bli_rntm_init_from_global( &trmm_l ); bli_rntm_init_from_global( &trmm_r ); bli_rntm_init_from_global( &trsm_l ); bli_rntm_init_from_global( &trsm_r ); bli_rntm_set_ways_for_op( BLIS_GEMM, BLIS_LEFT, m, n, k, &gemm ); bli_rntm_set_ways_for_op( BLIS_HERK, BLIS_LEFT, m, n, k, &herk ); bli_rntm_set_ways_for_op( BLIS_TRMM, BLIS_LEFT, m, n, k, &trmm_l ); bli_rntm_set_ways_for_op( BLIS_TRMM, BLIS_RIGHT, m, n, k, &trmm_r ); bli_rntm_set_ways_for_op( BLIS_TRSM, BLIS_LEFT, m, n, k, &trsm_l ); bli_rntm_set_ways_for_op( BLIS_TRSM, BLIS_RIGHT, m, n, k, &trsm_r ); // Output some system parameters. libblis_test_fprintf_c( os, "\n" ); libblis_test_fprintf_c( os, "--- BLIS library info -------------------------------------\n" ); libblis_test_fprintf_c( os, "\n" ); libblis_test_fprintf_c( os, "version string %s\n", bli_info_get_version_str() ); libblis_test_fprintf_c( os, "\n" ); libblis_test_fprintf_c( os, "--- BLIS configuration info ---\n" ); libblis_test_fprintf_c( os, "\n" ); libblis_test_fprintf_c( os, "active sub-configuration %s\n", bli_arch_string( bli_arch_query_id() ) ); libblis_test_fprintf_c( os, "\n" ); libblis_test_fprintf_c( os, "BLIS integer type size (bits) %d\n", ( int )int_type_size ); libblis_test_fprintf_c( os, "\n" ); libblis_test_fprintf_c( os, "Assumed max # of SIMD regs %d\n", ( int )bli_info_get_simd_num_registers() ); libblis_test_fprintf_c( os, "SIMD size (bytes) %d\n", ( int )bli_info_get_simd_size() ); libblis_test_fprintf_c( os, "SIMD alignment (bytes) %d\n", ( int )bli_info_get_simd_align_size() ); libblis_test_fprintf_c( os, "Max stack buffer size (bytes) %d\n", ( int )bli_info_get_stack_buf_max_size() ); libblis_test_fprintf_c( os, "Page size (bytes) %d\n", ( int )bli_info_get_page_size() ); libblis_test_fprintf_c( os, "\n" ); libblis_test_fprintf_c( os, "memory pools\n" ); libblis_test_fprintf_c( os, " enabled for packing blocks? %d\n", ( int )bli_info_get_enable_pba_pools() ); libblis_test_fprintf_c( os, " enabled for small blocks? %d\n", ( int )bli_info_get_enable_sba_pools() ); libblis_test_fprintf_c( os, "\n" ); libblis_test_fprintf_c( os, "memory alignment (bytes) \n" ); libblis_test_fprintf_c( os, " stack address %d\n", ( int )bli_info_get_stack_buf_align_size() ); libblis_test_fprintf_c( os, " obj_t address %d\n", ( int )bli_info_get_heap_addr_align_size() ); libblis_test_fprintf_c( os, " obj_t stride %d\n", ( int )bli_info_get_heap_stride_align_size() ); libblis_test_fprintf_c( os, " pool block addr A (+offset) %d (+%d)\n", ( int )bli_info_get_pool_addr_align_size_a(), ( int )bli_info_get_pool_addr_offset_size_a() ); libblis_test_fprintf_c( os, " pool block addr B (+offset) %d (+%d)\n", ( int )bli_info_get_pool_addr_align_size_b(), ( int )bli_info_get_pool_addr_offset_size_b() ); libblis_test_fprintf_c( os, "\n" ); libblis_test_fprintf_c( os, "BLAS/CBLAS compatibility layers \n" ); libblis_test_fprintf_c( os, " BLAS API enabled? %d\n", ( int )bli_info_get_enable_blas() ); libblis_test_fprintf_c( os, " CBLAS API enabled? %d\n", ( int )bli_info_get_enable_cblas() ); libblis_test_fprintf_c( os, " integer type size (bits) %d\n", ( int )bli_info_get_blas_int_type_size() ); libblis_test_fprintf_c( os, "\n" ); libblis_test_fprintf_c( os, "libmemkind \n" ); libblis_test_fprintf_c( os, " enabled? %d\n", ( int )bli_info_get_enable_memkind() ); libblis_test_fprintf_c( os, "\n" ); libblis_test_fprintf_c( os, "gemm sandbox \n" ); libblis_test_fprintf_c( os, " enabled? %d\n", ( int )bli_info_get_enable_sandbox() ); libblis_test_fprintf_c( os, "\n" ); libblis_test_fprintf_c( os, "floating-point types s d c z \n" ); libblis_test_fprintf_c( os, " sizes (bytes) %7u %7u %7u %7u\n", sizeof(float), sizeof(double), sizeof(scomplex), sizeof(dcomplex) ); libblis_test_fprintf_c( os, "\n" ); libblis_test_fprintf_c( os, "\n" ); libblis_test_fprintf_c( os, "--- BLIS parallelization info ---\n" ); libblis_test_fprintf_c( os, "\n" ); libblis_test_fprintf_c( os, "multithreading %s\n", impl_str ); libblis_test_fprintf_c( os, "\n" ); libblis_test_fprintf_c( os, "thread auto-factorization \n" ); libblis_test_fprintf_c( os, " m dim thread ratio %d\n", ( int )BLIS_THREAD_RATIO_M ); libblis_test_fprintf_c( os, " n dim thread ratio %d\n", ( int )BLIS_THREAD_RATIO_N ); libblis_test_fprintf_c( os, " jr max threads %d\n", ( int )BLIS_THREAD_MAX_JR ); libblis_test_fprintf_c( os, " ir max threads %d\n", ( int )BLIS_THREAD_MAX_IR ); libblis_test_fprintf_c( os, "\n" ); libblis_test_fprintf_c( os, "ways of parallelism nt jc pc ic jr ir\n" ); libblis_test_fprintf_c( os, " environment %5s %5s %5s %5s %5s %5s\n", nt_str, jc_nt_str, pc_nt_str, ic_nt_str, jr_nt_str, ir_nt_str ); libblis_test_fprintf_c( os, " gemm (m,n,k=1000) %5d %5d %5d %5d %5d\n", ( int )bli_rntm_jc_ways( &gemm ), ( int )bli_rntm_pc_ways( &gemm ), ( int )bli_rntm_ic_ways( &gemm ), ( int )bli_rntm_jr_ways( &gemm ), ( int )bli_rntm_ir_ways( &gemm ) ); libblis_test_fprintf_c( os, " herk (m,k=1000) %5d %5d %5d %5d %5d\n", ( int )bli_rntm_jc_ways( &herk ), ( int )bli_rntm_pc_ways( &herk ), ( int )bli_rntm_ic_ways( &herk ), ( int )bli_rntm_jr_ways( &herk ), ( int )bli_rntm_ir_ways( &herk ) ); libblis_test_fprintf_c( os, " trmm_l (m,n=1000) %5d %5d %5d %5d %5d\n", ( int )bli_rntm_jc_ways( &trmm_l ), ( int )bli_rntm_pc_ways( &trmm_l ), ( int )bli_rntm_ic_ways( &trmm_l ), ( int )bli_rntm_jr_ways( &trmm_l ), ( int )bli_rntm_ir_ways( &trmm_l ) ); libblis_test_fprintf_c( os, " trmm_r (m,n=1000) %5d %5d %5d %5d %5d\n", ( int )bli_rntm_jc_ways( &trmm_r ), ( int )bli_rntm_pc_ways( &trmm_r ), ( int )bli_rntm_ic_ways( &trmm_r ), ( int )bli_rntm_jr_ways( &trmm_r ), ( int )bli_rntm_ir_ways( &trmm_r ) ); libblis_test_fprintf_c( os, " trsm_l (m,n=1000) %5d %5d %5d %5d %5d\n", ( int )bli_rntm_jc_ways( &trsm_l ), ( int )bli_rntm_pc_ways( &trsm_l ), ( int )bli_rntm_ic_ways( &trsm_l ), ( int )bli_rntm_jr_ways( &trsm_l ), ( int )bli_rntm_ir_ways( &trsm_l ) ); libblis_test_fprintf_c( os, " trsm_r (m,n=1000) %5d %5d %5d %5d %5d\n", ( int )bli_rntm_jc_ways( &trsm_r ), ( int )bli_rntm_pc_ways( &trsm_r ), ( int )bli_rntm_ic_ways( &trsm_r ), ( int )bli_rntm_jr_ways( &trsm_r ), ( int )bli_rntm_ir_ways( &trsm_r ) ); libblis_test_fprintf_c( os, "\n" ); libblis_test_fprintf_c( os, "thread partitioning \n" ); //libblis_test_fprintf_c( os, " jc/ic loops %s\n", "slab" ); libblis_test_fprintf_c( os, " jr/ir loops %s\n", jrir_str ); libblis_test_fprintf_c( os, "\n" ); libblis_test_fprintf_c( os, "\n" ); libblis_test_fprintf_c( os, "--- BLIS default implementations ---\n" ); libblis_test_fprintf_c( os, "\n" ); libblis_test_fprintf_c( os, "level-3 implementations s d c z\n" ); libblis_test_fprintf_c( os, " gemm %7s %7s %7s %7s\n", bli_info_get_gemm_impl_string( BLIS_FLOAT ), bli_info_get_gemm_impl_string( BLIS_DOUBLE ), bli_info_get_gemm_impl_string( BLIS_SCOMPLEX ), bli_info_get_gemm_impl_string( BLIS_DCOMPLEX ) ); libblis_test_fprintf_c( os, " hemm %7s %7s %7s %7s\n", bli_info_get_hemm_impl_string( BLIS_FLOAT ), bli_info_get_hemm_impl_string( BLIS_DOUBLE ), bli_info_get_hemm_impl_string( BLIS_SCOMPLEX ), bli_info_get_hemm_impl_string( BLIS_DCOMPLEX ) ); libblis_test_fprintf_c( os, " herk %7s %7s %7s %7s\n", bli_info_get_herk_impl_string( BLIS_FLOAT ), bli_info_get_herk_impl_string( BLIS_DOUBLE ), bli_info_get_herk_impl_string( BLIS_SCOMPLEX ), bli_info_get_herk_impl_string( BLIS_DCOMPLEX ) ); libblis_test_fprintf_c( os, " her2k %7s %7s %7s %7s\n", bli_info_get_her2k_impl_string( BLIS_FLOAT ), bli_info_get_her2k_impl_string( BLIS_DOUBLE ), bli_info_get_her2k_impl_string( BLIS_SCOMPLEX ), bli_info_get_her2k_impl_string( BLIS_DCOMPLEX ) ); libblis_test_fprintf_c( os, " symm %7s %7s %7s %7s\n", bli_info_get_symm_impl_string( BLIS_FLOAT ), bli_info_get_symm_impl_string( BLIS_DOUBLE ), bli_info_get_symm_impl_string( BLIS_SCOMPLEX ), bli_info_get_symm_impl_string( BLIS_DCOMPLEX ) ); libblis_test_fprintf_c( os, " syrk %7s %7s %7s %7s\n", bli_info_get_syrk_impl_string( BLIS_FLOAT ), bli_info_get_syrk_impl_string( BLIS_DOUBLE ), bli_info_get_syrk_impl_string( BLIS_SCOMPLEX ), bli_info_get_syrk_impl_string( BLIS_DCOMPLEX ) ); libblis_test_fprintf_c( os, " syr2k %7s %7s %7s %7s\n", bli_info_get_syr2k_impl_string( BLIS_FLOAT ), bli_info_get_syr2k_impl_string( BLIS_DOUBLE ), bli_info_get_syr2k_impl_string( BLIS_SCOMPLEX ), bli_info_get_syr2k_impl_string( BLIS_DCOMPLEX ) ); libblis_test_fprintf_c( os, " trmm %7s %7s %7s %7s\n", bli_info_get_trmm_impl_string( BLIS_FLOAT ), bli_info_get_trmm_impl_string( BLIS_DOUBLE ), bli_info_get_trmm_impl_string( BLIS_SCOMPLEX ), bli_info_get_trmm_impl_string( BLIS_DCOMPLEX ) ); libblis_test_fprintf_c( os, " trmm3 %7s %7s %7s %7s\n", bli_info_get_trmm3_impl_string( BLIS_FLOAT ), bli_info_get_trmm3_impl_string( BLIS_DOUBLE ), bli_info_get_trmm3_impl_string( BLIS_SCOMPLEX ), bli_info_get_trmm3_impl_string( BLIS_DCOMPLEX ) ); libblis_test_fprintf_c( os, " trsm %7s %7s %7s %7s\n", bli_info_get_trsm_impl_string( BLIS_FLOAT ), bli_info_get_trsm_impl_string( BLIS_DOUBLE ), bli_info_get_trsm_impl_string( BLIS_SCOMPLEX ), bli_info_get_trsm_impl_string( BLIS_DCOMPLEX ) ); libblis_test_fprintf_c( os, "\n" ); //bli_ind_disable_all(); bli_ind_oper_enable_only( BLIS_GEMM, BLIS_NAT, BLIS_SCOMPLEX ); bli_ind_oper_enable_only( BLIS_GEMM, BLIS_NAT, BLIS_DCOMPLEX ); libblis_test_fprintf_c( os, "--- BLIS native implementation info ---\n" ); libblis_test_fprintf_c( os, "\n" ); libblis_test_fprintf_c( os, " c z \n" ); libblis_test_fprintf_c( os, "complex implementation %7s %7s\n", bli_ind_oper_get_avail_impl_string( BLIS_GEMM, BLIS_SCOMPLEX ), bli_ind_oper_get_avail_impl_string( BLIS_GEMM, BLIS_DCOMPLEX ) ); libblis_test_fprintf_c( os, "\n" ); // Query a native context. cntx = bli_gks_query_nat_cntx(); libblis_test_fprintf_c( os, "level-3 blocksizes s d c z \n" ); libblis_test_fprintf_c( os, " mc %7d %7d %7d %7d\n", ( int )bli_cntx_get_blksz_def_dt( BLIS_FLOAT, BLIS_MC, cntx ), ( int )bli_cntx_get_blksz_def_dt( BLIS_DOUBLE, BLIS_MC, cntx ), ( int )bli_cntx_get_blksz_def_dt( BLIS_SCOMPLEX, BLIS_MC, cntx ), ( int )bli_cntx_get_blksz_def_dt( BLIS_DCOMPLEX, BLIS_MC, cntx ) ); libblis_test_fprintf_c( os, " kc %7d %7d %7d %7d\n", ( int )bli_cntx_get_blksz_def_dt( BLIS_FLOAT, BLIS_KC, cntx ), ( int )bli_cntx_get_blksz_def_dt( BLIS_DOUBLE, BLIS_KC, cntx ), ( int )bli_cntx_get_blksz_def_dt( BLIS_SCOMPLEX, BLIS_KC, cntx ), ( int )bli_cntx_get_blksz_def_dt( BLIS_DCOMPLEX, BLIS_KC, cntx ) ); libblis_test_fprintf_c( os, " nc %7d %7d %7d %7d\n", ( int )bli_cntx_get_blksz_def_dt( BLIS_FLOAT, BLIS_NC, cntx ), ( int )bli_cntx_get_blksz_def_dt( BLIS_DOUBLE, BLIS_NC, cntx ), ( int )bli_cntx_get_blksz_def_dt( BLIS_SCOMPLEX, BLIS_NC, cntx ), ( int )bli_cntx_get_blksz_def_dt( BLIS_DCOMPLEX, BLIS_NC, cntx ) ); libblis_test_fprintf_c( os, "\n" ); libblis_test_fprintf_c( os, " mc maximum %7d %7d %7d %7d\n", ( int )bli_cntx_get_blksz_max_dt( BLIS_FLOAT, BLIS_MC, cntx ), ( int )bli_cntx_get_blksz_max_dt( BLIS_DOUBLE, BLIS_MC, cntx ), ( int )bli_cntx_get_blksz_max_dt( BLIS_SCOMPLEX, BLIS_MC, cntx ), ( int )bli_cntx_get_blksz_max_dt( BLIS_DCOMPLEX, BLIS_MC, cntx ) ); libblis_test_fprintf_c( os, " kc maximum %7d %7d %7d %7d\n", ( int )bli_cntx_get_blksz_max_dt( BLIS_FLOAT, BLIS_KC, cntx ), ( int )bli_cntx_get_blksz_max_dt( BLIS_DOUBLE, BLIS_KC, cntx ), ( int )bli_cntx_get_blksz_max_dt( BLIS_SCOMPLEX, BLIS_KC, cntx ), ( int )bli_cntx_get_blksz_max_dt( BLIS_DCOMPLEX, BLIS_KC, cntx ) ); libblis_test_fprintf_c( os, " nc maximum %7d %7d %7d %7d\n", ( int )bli_cntx_get_blksz_max_dt( BLIS_FLOAT, BLIS_NC, cntx ), ( int )bli_cntx_get_blksz_max_dt( BLIS_DOUBLE, BLIS_NC, cntx ), ( int )bli_cntx_get_blksz_max_dt( BLIS_SCOMPLEX, BLIS_NC, cntx ), ( int )bli_cntx_get_blksz_max_dt( BLIS_DCOMPLEX, BLIS_NC, cntx ) ); libblis_test_fprintf_c( os, "\n" ); libblis_test_fprintf_c( os, " mr %7d %7d %7d %7d\n", ( int )bli_cntx_get_blksz_def_dt( BLIS_FLOAT, BLIS_MR, cntx ), ( int )bli_cntx_get_blksz_def_dt( BLIS_DOUBLE, BLIS_MR, cntx ), ( int )bli_cntx_get_blksz_def_dt( BLIS_SCOMPLEX, BLIS_MR, cntx ), ( int )bli_cntx_get_blksz_def_dt( BLIS_DCOMPLEX, BLIS_MR, cntx ) ); libblis_test_fprintf_c( os, " nr %7d %7d %7d %7d\n", ( int )bli_cntx_get_blksz_def_dt( BLIS_FLOAT, BLIS_NR, cntx ), ( int )bli_cntx_get_blksz_def_dt( BLIS_DOUBLE, BLIS_NR, cntx ), ( int )bli_cntx_get_blksz_def_dt( BLIS_SCOMPLEX, BLIS_NR, cntx ), ( int )bli_cntx_get_blksz_def_dt( BLIS_DCOMPLEX, BLIS_NR, cntx ) ); libblis_test_fprintf_c( os, "\n" ); libblis_test_fprintf_c( os, " mr packdim %7d %7d %7d %7d\n", ( int )bli_cntx_get_blksz_max_dt( BLIS_FLOAT, BLIS_MR, cntx ), ( int )bli_cntx_get_blksz_max_dt( BLIS_DOUBLE, BLIS_MR, cntx ), ( int )bli_cntx_get_blksz_max_dt( BLIS_SCOMPLEX, BLIS_MR, cntx ), ( int )bli_cntx_get_blksz_max_dt( BLIS_DCOMPLEX, BLIS_MR, cntx ) ); libblis_test_fprintf_c( os, " nr packdim %7d %7d %7d %7d\n", ( int )bli_cntx_get_blksz_max_dt( BLIS_FLOAT, BLIS_NR, cntx ), ( int )bli_cntx_get_blksz_max_dt( BLIS_DOUBLE, BLIS_NR, cntx ), ( int )bli_cntx_get_blksz_max_dt( BLIS_SCOMPLEX, BLIS_NR, cntx ), ( int )bli_cntx_get_blksz_max_dt( BLIS_DCOMPLEX, BLIS_NR, cntx ) ); libblis_test_fprintf_c( os, "\n" ); libblis_test_fprintf_c( os, "micro-kernel types s d c z\n" ); libblis_test_fprintf_c( os, " gemm %7s %7s %7s %7s\n", bli_info_get_gemm_ukr_impl_string( BLIS_NAT, BLIS_FLOAT ), bli_info_get_gemm_ukr_impl_string( BLIS_NAT, BLIS_DOUBLE ), bli_info_get_gemm_ukr_impl_string( BLIS_NAT, BLIS_SCOMPLEX ), bli_info_get_gemm_ukr_impl_string( BLIS_NAT, BLIS_DCOMPLEX ) ); libblis_test_fprintf_c( os, " gemmtrsm_l %7s %7s %7s %7s\n", bli_info_get_gemmtrsm_l_ukr_impl_string( BLIS_NAT, BLIS_FLOAT ), bli_info_get_gemmtrsm_l_ukr_impl_string( BLIS_NAT, BLIS_DOUBLE ), bli_info_get_gemmtrsm_l_ukr_impl_string( BLIS_NAT, BLIS_SCOMPLEX ), bli_info_get_gemmtrsm_l_ukr_impl_string( BLIS_NAT, BLIS_DCOMPLEX ) ); libblis_test_fprintf_c( os, " gemmtrsm_u %7s %7s %7s %7s\n", bli_info_get_gemmtrsm_u_ukr_impl_string( BLIS_NAT, BLIS_FLOAT ), bli_info_get_gemmtrsm_u_ukr_impl_string( BLIS_NAT, BLIS_DOUBLE ), bli_info_get_gemmtrsm_u_ukr_impl_string( BLIS_NAT, BLIS_SCOMPLEX ), bli_info_get_gemmtrsm_u_ukr_impl_string( BLIS_NAT, BLIS_DCOMPLEX ) ); libblis_test_fprintf_c( os, " trsm_l %7s %7s %7s %7s\n", bli_info_get_trsm_l_ukr_impl_string( BLIS_NAT, BLIS_FLOAT ), bli_info_get_trsm_l_ukr_impl_string( BLIS_NAT, BLIS_DOUBLE ), bli_info_get_trsm_l_ukr_impl_string( BLIS_NAT, BLIS_SCOMPLEX ), bli_info_get_trsm_l_ukr_impl_string( BLIS_NAT, BLIS_DCOMPLEX ) ); libblis_test_fprintf_c( os, " trsm_u %7s %7s %7s %7s\n", bli_info_get_trsm_u_ukr_impl_string( BLIS_NAT, BLIS_FLOAT ), bli_info_get_trsm_u_ukr_impl_string( BLIS_NAT, BLIS_DOUBLE ), bli_info_get_trsm_u_ukr_impl_string( BLIS_NAT, BLIS_SCOMPLEX ), bli_info_get_trsm_u_ukr_impl_string( BLIS_NAT, BLIS_DCOMPLEX ) ); libblis_test_fprintf_c( os, "\n" ); libblis_test_fprintf_c( os, "\n" ); libblis_test_fprintf_c( os, "--- BLIS induced implementation info ---\n" ); libblis_test_fprintf_c( os, "\n" ); for ( im = 0; im < BLIS_NAT; ++im ) { if ( params->ind_enable[ im ] == 0 ) continue; bli_ind_oper_enable_only( BLIS_GEMM, im, BLIS_SCOMPLEX ); bli_ind_oper_enable_only( BLIS_GEMM, im, BLIS_DCOMPLEX ); //libblis_test_fprintf_c( os, " c z \n" ); libblis_test_fprintf_c( os, " c z \n" ); libblis_test_fprintf_c( os, "complex implementation %7s %7s\n", bli_ind_oper_get_avail_impl_string( BLIS_GEMM, BLIS_SCOMPLEX ), bli_ind_oper_get_avail_impl_string( BLIS_GEMM, BLIS_DCOMPLEX ) ); libblis_test_fprintf_c( os, "\n" ); // Query a native context. cntx_c = bli_gks_query_ind_cntx( im, BLIS_SCOMPLEX ); cntx_z = bli_gks_query_ind_cntx( im, BLIS_DCOMPLEX ); libblis_test_fprintf_c( os, "level-3 blocksizes c z \n" ); libblis_test_fprintf_c( os, " mc %7d %7d\n", ( int )bli_cntx_get_blksz_def_dt( BLIS_SCOMPLEX, BLIS_MC, cntx_c ), ( int )bli_cntx_get_blksz_def_dt( BLIS_DCOMPLEX, BLIS_MC, cntx_z ) ); libblis_test_fprintf_c( os, " kc %7d %7d\n", ( int )bli_cntx_get_blksz_def_dt( BLIS_SCOMPLEX, BLIS_KC, cntx_c ), ( int )bli_cntx_get_blksz_def_dt( BLIS_DCOMPLEX, BLIS_KC, cntx_z ) ); libblis_test_fprintf_c( os, " nc %7d %7d\n", ( int )bli_cntx_get_blksz_def_dt( BLIS_SCOMPLEX, BLIS_NC, cntx_c ), ( int )bli_cntx_get_blksz_def_dt( BLIS_DCOMPLEX, BLIS_NC, cntx_z ) ); libblis_test_fprintf_c( os, "\n" ); libblis_test_fprintf_c( os, " mc maximum %7d %7d\n", ( int )bli_cntx_get_blksz_max_dt( BLIS_SCOMPLEX, BLIS_MC, cntx_c ), ( int )bli_cntx_get_blksz_max_dt( BLIS_DCOMPLEX, BLIS_MC, cntx_z ) ); libblis_test_fprintf_c( os, " kc maximum %7d %7d\n", ( int )bli_cntx_get_blksz_max_dt( BLIS_SCOMPLEX, BLIS_KC, cntx_c ), ( int )bli_cntx_get_blksz_max_dt( BLIS_DCOMPLEX, BLIS_KC, cntx_z ) ); libblis_test_fprintf_c( os, " nc maximum %7d %7d\n", ( int )bli_cntx_get_blksz_max_dt( BLIS_SCOMPLEX, BLIS_NC, cntx_c ), ( int )bli_cntx_get_blksz_max_dt( BLIS_DCOMPLEX, BLIS_NC, cntx_z ) ); libblis_test_fprintf_c( os, "\n" ); libblis_test_fprintf_c( os, " mr %7d %7d\n", ( int )bli_cntx_get_blksz_def_dt( BLIS_SCOMPLEX, BLIS_MR, cntx_c ), ( int )bli_cntx_get_blksz_def_dt( BLIS_DCOMPLEX, BLIS_MR, cntx_z ) ); libblis_test_fprintf_c( os, " nr %7d %7d\n", ( int )bli_cntx_get_blksz_def_dt( BLIS_SCOMPLEX, BLIS_NR, cntx_c ), ( int )bli_cntx_get_blksz_def_dt( BLIS_DCOMPLEX, BLIS_NR, cntx_z ) ); libblis_test_fprintf_c( os, "\n" ); libblis_test_fprintf_c( os, " mr packdim %7d %7d\n", ( int )bli_cntx_get_blksz_max_dt( BLIS_SCOMPLEX, BLIS_MR, cntx_c ), ( int )bli_cntx_get_blksz_max_dt( BLIS_DCOMPLEX, BLIS_MR, cntx_z ) ); libblis_test_fprintf_c( os, " nr packdim %7d %7d\n", ( int )bli_cntx_get_blksz_max_dt( BLIS_SCOMPLEX, BLIS_NR, cntx_c ), ( int )bli_cntx_get_blksz_max_dt( BLIS_DCOMPLEX, BLIS_NR, cntx_z ) ); libblis_test_fprintf_c( os, "\n" ); libblis_test_fprintf_c( os, "micro-kernel types c z\n" ); libblis_test_fprintf_c( os, " gemm %7s %7s\n", bli_info_get_gemm_ukr_impl_string( im, BLIS_SCOMPLEX ), bli_info_get_gemm_ukr_impl_string( im, BLIS_DCOMPLEX ) ); libblis_test_fprintf_c( os, " gemmtrsm_l %7s %7s\n", bli_info_get_gemmtrsm_l_ukr_impl_string( im, BLIS_SCOMPLEX ), bli_info_get_gemmtrsm_l_ukr_impl_string( im, BLIS_DCOMPLEX ) ); libblis_test_fprintf_c( os, " gemmtrsm_u %7s %7s\n", bli_info_get_gemmtrsm_u_ukr_impl_string( im, BLIS_SCOMPLEX ), bli_info_get_gemmtrsm_u_ukr_impl_string( im, BLIS_DCOMPLEX ) ); libblis_test_fprintf_c( os, " trsm_l %7s %7s\n", bli_info_get_trsm_l_ukr_impl_string( im, BLIS_SCOMPLEX ), bli_info_get_trsm_l_ukr_impl_string( im, BLIS_DCOMPLEX ) ); libblis_test_fprintf_c( os, " trsm_u %7s %7s\n", bli_info_get_trsm_u_ukr_impl_string( im, BLIS_SCOMPLEX ), bli_info_get_trsm_u_ukr_impl_string( im, BLIS_DCOMPLEX ) ); libblis_test_fprintf_c( os, "\n" ); } bli_ind_disable_all(); libblis_test_fprintf_c( os, "\n" ); libblis_test_fprintf_c( os, "--- BLIS misc. other info ---\n" ); libblis_test_fprintf_c( os, "\n" ); libblis_test_fprintf_c( os, "level-2 cache blocksizes s d c z \n" ); libblis_test_fprintf_c( os, " m dimension %7d %7d %7d %7d\n", ( int )bli_cntx_get_blksz_def_dt( BLIS_FLOAT, BLIS_M2, cntx ), ( int )bli_cntx_get_blksz_def_dt( BLIS_DOUBLE, BLIS_M2, cntx ), ( int )bli_cntx_get_blksz_def_dt( BLIS_SCOMPLEX, BLIS_M2, cntx ), ( int )bli_cntx_get_blksz_def_dt( BLIS_DCOMPLEX, BLIS_M2, cntx ) ); libblis_test_fprintf_c( os, " n dimension %7d %7d %7d %7d\n", ( int )bli_cntx_get_blksz_def_dt( BLIS_FLOAT, BLIS_N2, cntx ), ( int )bli_cntx_get_blksz_def_dt( BLIS_DOUBLE, BLIS_N2, cntx ), ( int )bli_cntx_get_blksz_def_dt( BLIS_SCOMPLEX, BLIS_N2, cntx ), ( int )bli_cntx_get_blksz_def_dt( BLIS_DCOMPLEX, BLIS_N2, cntx ) ); libblis_test_fprintf_c( os, "\n" ); libblis_test_fprintf_c( os, "level-1f fusing factors s d c z \n" ); libblis_test_fprintf_c( os, " axpyf %7d %7d %7d %7d\n", ( int )bli_cntx_get_blksz_def_dt( BLIS_FLOAT, BLIS_AF, cntx ), ( int )bli_cntx_get_blksz_def_dt( BLIS_DOUBLE, BLIS_AF, cntx ), ( int )bli_cntx_get_blksz_def_dt( BLIS_SCOMPLEX, BLIS_AF, cntx ), ( int )bli_cntx_get_blksz_def_dt( BLIS_DCOMPLEX, BLIS_AF, cntx ) ); libblis_test_fprintf_c( os, " dotxf %7d %7d %7d %7d\n", ( int )bli_cntx_get_blksz_def_dt( BLIS_FLOAT, BLIS_DF, cntx ), ( int )bli_cntx_get_blksz_def_dt( BLIS_DOUBLE, BLIS_DF, cntx ), ( int )bli_cntx_get_blksz_def_dt( BLIS_SCOMPLEX, BLIS_DF, cntx ), ( int )bli_cntx_get_blksz_def_dt( BLIS_DCOMPLEX, BLIS_DF, cntx ) ); libblis_test_fprintf_c( os, " dotxaxpyf %7d %7d %7d %7d\n", ( int )bli_cntx_get_blksz_def_dt( BLIS_FLOAT, BLIS_XF, cntx ), ( int )bli_cntx_get_blksz_def_dt( BLIS_DOUBLE, BLIS_XF, cntx ), ( int )bli_cntx_get_blksz_def_dt( BLIS_SCOMPLEX, BLIS_XF, cntx ), ( int )bli_cntx_get_blksz_def_dt( BLIS_DCOMPLEX, BLIS_XF, cntx ) ); libblis_test_fprintf_c( os, "\n" ); libblis_test_fprintf( os, "\n" ); // Output the contents of the param struct. libblis_test_fprintf_c( os, "\n" ); libblis_test_fprintf_c( os, "--- BLIS test suite parameters ----------------------------\n" ); libblis_test_fprintf_c( os, "\n" ); libblis_test_fprintf_c( os, "num repeats per experiment %u\n", params->n_repeats ); libblis_test_fprintf_c( os, "num matrix storage schemes %u\n", params->n_mstorage ); libblis_test_fprintf_c( os, "storage[ matrix ] %s\n", params->storage[ BLIS_TEST_MATRIX_OPERAND ] ); libblis_test_fprintf_c( os, "num vector storage schemes %u\n", params->n_vstorage ); libblis_test_fprintf_c( os, "storage[ vector ] %s\n", params->storage[ BLIS_TEST_VECTOR_OPERAND ] ); libblis_test_fprintf_c( os, "mix all storage schemes? %u\n", params->mix_all_storage ); libblis_test_fprintf_c( os, "test with aligned memory? %u\n", params->alignment ); libblis_test_fprintf_c( os, "randomization method %u\n", params->rand_method ); libblis_test_fprintf_c( os, "general stride spacing %u\n", params->gs_spacing ); libblis_test_fprintf_c( os, "num datatypes %u\n", params->n_datatypes ); libblis_test_fprintf_c( os, "datatype[0] %d (%c)\n", params->datatype[0], params->datatype_char[0] ); for( i = 1; i < params->n_datatypes; ++i ) libblis_test_fprintf_c( os, " [%d] %d (%c)\n", i, params->datatype[i], params->datatype_char[i] ); libblis_test_fprintf_c( os, "mix domains for gemm? %u\n", params->mixed_domain ); libblis_test_fprintf_c( os, "mix precisions for gemm? %u\n", params->mixed_precision ); libblis_test_fprintf_c( os, "problem size: first to test %u\n", params->p_first ); libblis_test_fprintf_c( os, "problem size: max to test %u\n", params->p_max ); libblis_test_fprintf_c( os, "problem size increment %u\n", params->p_inc ); libblis_test_fprintf_c( os, "complex implementations \n" ); libblis_test_fprintf_c( os, " 1m? %u\n", params->ind_enable[ BLIS_1M ] ); libblis_test_fprintf_c( os, " native? %u\n", params->ind_enable[ BLIS_NAT ] ); libblis_test_fprintf_c( os, "simulated app-level threads %u\n", params->n_app_threads ); libblis_test_fprintf_c( os, "error-checking level %u\n", params->error_checking_level ); libblis_test_fprintf_c( os, "reaction to failure %c\n", params->reaction_to_failure ); libblis_test_fprintf_c( os, "output in matlab format? %u\n", params->output_matlab_format ); libblis_test_fprintf_c( os, "output to stdout AND files? %u\n", params->output_files ); libblis_test_fprintf_c( os, "\n" ); libblis_test_fprintf( os, "\n" ); #ifndef BLIS_ENABLE_GEMM_MD // Notify the user if mixed domain or mixed precision was requested. if ( params->mixed_domain || params->mixed_precision ) { libblis_test_printf_error( "mixed domain and/or mixed precision testing requested, but building against BLIS without mixed datatype support.\n" ); } #endif // If mixed domain or mixed precision was requested, we disable all // induced methods except 1m and native execution. if ( params->mixed_domain || params->mixed_precision ) { ind_t im; for ( im = BLIS_IND_FIRST; im < BLIS_IND_LAST+1; ++im ) { if ( im != BLIS_1M && im != BLIS_NAT ) params->ind_enable[ im ] = 0; } } } void libblis_test_output_op_struct( FILE* os, test_op_t* op, char* op_str ) { dimset_t dimset = op->dimset; if ( dimset == BLIS_TEST_DIMS_MNK ) { libblis_test_fprintf_c( os, "%s m n k %d %d %d\n", op_str, op->dim_spec[0], op->dim_spec[1], op->dim_spec[2] ); } else if ( dimset == BLIS_TEST_DIMS_MN ) { libblis_test_fprintf_c( os, "%s m n %d %d\n", op_str, op->dim_spec[0], op->dim_spec[1] ); } else if ( dimset == BLIS_TEST_DIMS_MK ) { libblis_test_fprintf_c( os, "%s m k %d %d\n", op_str, op->dim_spec[0], op->dim_spec[1] ); } else if ( dimset == BLIS_TEST_DIMS_M || dimset == BLIS_TEST_DIMS_MF ) { libblis_test_fprintf_c( os, "%s m %d\n", op_str, op->dim_spec[0] ); } else if ( dimset == BLIS_TEST_DIMS_K ) { libblis_test_fprintf_c( os, "%s k %d\n", op_str, op->dim_spec[0] ); } else if ( dimset == BLIS_TEST_NO_DIMS ) { // Do nothing. } else { libblis_test_printf_error( "Invalid dimension combination.\n" ); } if ( op->n_params > 0 ) libblis_test_fprintf_c( os, "%s operand params %s\n", op_str, op->params ); else libblis_test_fprintf_c( os, "%s operand params %s\n", op_str, "(none)" ); libblis_test_fprintf_c( os, "\n" ); libblis_test_fprintf( os, "\n" ); } char* libblis_test_get_string_for_result( double resid, num_t dt, thresh_t* thresh ) { char* r_val; // Before checking against the thresholds, make sure the residual is // neither NaN nor Inf. (Note that bli_isnan() and bli_isinf() are // both simply wrappers to the isnan() and isinf() macros defined // defined in math.h.) if ( bli_isnan( resid ) || bli_isinf( resid ) ) { r_val = libblis_test_fail_string; } else { // Check the result against the thresholds. if ( resid > thresh[dt].failwarn ) r_val = libblis_test_fail_string; else if ( resid > thresh[dt].warnpass ) r_val = libblis_test_warn_string; else r_val = libblis_test_pass_string; } return r_val; } param_t libblis_test_get_param_type_for_char( char p_type ) { param_t r_val; if ( p_type == 's' ) r_val = BLIS_TEST_PARAM_SIDE; else if ( p_type == 'u' ) r_val = BLIS_TEST_PARAM_UPLO; else if ( p_type == 'e' ) r_val = BLIS_TEST_PARAM_UPLODE; else if ( p_type == 'h' ) r_val = BLIS_TEST_PARAM_TRANS; else if ( p_type == 'c' ) r_val = BLIS_TEST_PARAM_CONJ; else if ( p_type == 'd' ) r_val = BLIS_TEST_PARAM_DIAG; else { r_val = 0; libblis_test_printf_error( "Invalid parameter character.\n" ); } return r_val; } operand_t libblis_test_get_operand_type_for_char( char o_type ) { operand_t r_val; if ( o_type == 'm' ) r_val = BLIS_TEST_MATRIX_OPERAND; else if ( o_type == 'v' ) r_val = BLIS_TEST_VECTOR_OPERAND; else { r_val = 0; libblis_test_printf_error( "Invalid operand character.\n" ); } return r_val; } unsigned int libblis_test_get_n_dims_from_dimset( dimset_t dimset ) { unsigned int n_dims; if ( dimset == BLIS_TEST_DIMS_MNK ) n_dims = 3; else if ( dimset == BLIS_TEST_DIMS_MN ) n_dims = 2; else if ( dimset == BLIS_TEST_DIMS_MK ) n_dims = 2; else if ( dimset == BLIS_TEST_DIMS_M ) n_dims = 1; else if ( dimset == BLIS_TEST_DIMS_MF ) n_dims = 1; else if ( dimset == BLIS_TEST_DIMS_K ) n_dims = 1; else if ( dimset == BLIS_TEST_NO_DIMS ) n_dims = 0; else { n_dims = 0; libblis_test_printf_error( "Invalid dimension combination.\n" ); } return n_dims; } unsigned int libblis_test_get_n_dims_from_string( char* dims_str ) { unsigned int n_dims; char* cp; cp = dims_str; for ( n_dims = 0; *cp != '\0'; ++n_dims ) { //printf( "n_dims = %u\n", n_dims ); while ( isspace( *cp ) ) { //printf( "current char: _%c_", *cp ); ++cp; } while ( isdigit( *cp ) ) { //printf( "current char: _%c_", *cp ); ++cp; } } //printf( "n_dims finally = %u\n", n_dims ); return n_dims; } dim_t libblis_test_get_dim_from_prob_size( int dim_spec, unsigned int p_size ) { dim_t dim; if ( dim_spec < 0 ) dim = p_size / bli_abs(dim_spec); else dim = dim_spec; return dim; } void libblis_test_fill_param_strings( char* p_spec_str, char** chars_for_param, unsigned int n_params, unsigned int n_param_combos, char** pc_str ) { unsigned int pci, pi, i; unsigned int* counter; unsigned int* n_vals_for_param; // Allocate an array that will store the number of parameter values // for each parameter. n_vals_for_param = ( unsigned int* ) malloc( n_params * sizeof( unsigned int ) ); // Fill n_vals_for_param[i] with the number of parameter values (chars) // in chars_for_param[i] (this is simply the string length). for ( i = 0; i < n_params; ++i ) { if ( p_spec_str[i] == '?' ) n_vals_for_param[i] = strlen( chars_for_param[i] ); else n_vals_for_param[i] = 1; } // Allocate an array with one digit per parameter. We will use // this array to keep track of our progress as we canonically move // though all possible parameter combinations. counter = ( unsigned int* ) malloc( n_params * sizeof( unsigned int ) ); // Initialize all values in c to zero. for ( i = 0; i < n_params; ++i ) counter[i] = 0; for ( pci = 0; pci < n_param_combos; ++pci ) { // Iterate backwards through each parameter string we create, since we // want to form (for example, if the parameters are transa and conjx: // (1) nn, (2) nc, (3) cn, (4) cc, (5) tn, (6) tc, (7) hn, (8) hc. for ( i = 0, pi = n_params - 1; i < n_params; --pi, ++i ) { // If the current parameter character, p_spec_str[pi] is fixed (ie: if // it is not '?'), then just copy it into the parameter combination // string. Otherwise, map the current integer value in c to the // corresponding character in char_for_param[pi]. if ( p_spec_str[pi] != '?' ) pc_str[pci][pi] = p_spec_str[pi]; else pc_str[pci][pi] = chars_for_param[ pi ][ counter[pi] ]; } // Terminate the current parameter combination string. pc_str[pci][n_params] = '\0'; // Only try to increment/carryover if this is NOT the last param // combo. if ( pci < n_param_combos - 1 ) { // Increment the least-most significant counter. counter[ n_params - 1 ]++; // Perform "carryover" if needed. carryover( &counter[ n_params - 1 ], &n_vals_for_param[ n_params - 1 ], n_params ); } } // Free the temporary arrays. free( counter ); // Free the array holding the number of parameter values for each // parameter. free( n_vals_for_param ); } void carryover( unsigned int* c, unsigned int* n_vals_for_param, unsigned int n_params ) { if ( n_params == 1 ) return; else { if ( *c == *n_vals_for_param ) { *c = 0; *(c-1) += 1; carryover( c-1, n_vals_for_param-1, n_params-1 ); } } } void libblis_test_op_driver ( thread_data_t* tdata, test_params_t* params, test_op_t* op, iface_t iface, char* op_str, char* p_types, char* o_types, thresh_t* thresh, void (*f_exp) (test_params_t*, // params struct test_op_t*, // op struct iface_t, // iface char*, // datatype (current datatype) char*, // pc_str (current param string) char*, // sc_str (current storage string) unsigned int, // p_cur (current problem size) double*, // perf double* ) // residual ) { unsigned int n_mstorage = params->n_mstorage; unsigned int n_vstorage = params->n_vstorage; unsigned int n_datatypes = params->n_datatypes; unsigned int p_first = params->p_first; unsigned int p_max = params->p_max; unsigned int p_inc = params->p_inc; unsigned int mix_all_storage = params->mix_all_storage; unsigned int mixed_domain = params->mixed_domain; unsigned int mixed_precision = params->mixed_precision; unsigned int reaction_to_failure = params->reaction_to_failure; num_t datatype; num_t dt_check; char dt_char; char* p_spec_str; unsigned int n_params; char** chars_for_param; unsigned int n_param_combos; char** pc_str; char s_spec_str[ MAX_NUM_OPERANDS + 1 ]; unsigned int n_operands; unsigned int n_operandsp1; char** chars_for_storage; unsigned int n_store_combos; char** sc_str; char d_spec_str[ MAX_NUM_OPERANDS + 1 ]; char** chars_for_spdt; char** chars_for_dpdt; unsigned int n_spdt_combos; unsigned int n_dpdt_combos; unsigned int n_dt_combos; char** dc_str; char** chars_for_dt; char** chars_for_rddt; char** chars_for_cddt; unsigned int n_rddt_combos; unsigned int n_cddt_combos; unsigned int p_cur, pi; unsigned int indi, pci, sci, dci, i, j, o; unsigned int is_mixed_dt; double perf, resid; char* pass_str; char* ind_str; char blank_str[32]; char funcname_str[64]; char dims_str[64]; char label_str[128]; unsigned int n_spaces; unsigned int n_dims_print; FILE* output_stream = NULL; // These arrays are malloc()'ed in select branches. Here, we set // them to NULL so they can be unconditionally free()'ed at the // end of the function. chars_for_rddt = NULL; chars_for_cddt = NULL; chars_for_spdt = NULL; chars_for_dpdt = NULL; // If output to files was requested, attempt to open a file stream. if ( params->output_files ) libblis_test_fopen_ofile( op_str, iface, &output_stream ); // Set the error-checking level according to what was specified in the // input file. if ( params->error_checking_level == 0 ) bli_error_checking_level_set( BLIS_NO_ERROR_CHECKING ); else bli_error_checking_level_set( BLIS_FULL_ERROR_CHECKING ); // Obtain the parameter specification (filter) string. p_spec_str = op->params; // Figure out how many parameters we have. n_params = strlen( p_types ); if ( strlen( p_types ) != strlen( p_spec_str) ) { libblis_test_printf_error( "Parameter specification string from input file does not match length of p_types string.\n" ); } // Allocate an array that stores pointers to the sets of possible parameter // chars for each parameter. chars_for_param = ( char** ) malloc( n_params * sizeof( char* ) ); // Set the values in chars_for_param to the appropriate string addresses. for ( i = 0; i < n_params; ++i ) { param_t param_type = libblis_test_get_param_type_for_char( p_types[i] ); chars_for_param[i] = libblis_test_param_chars[ param_type ]; } // Compute the total number of parameter combinations to test (which is // simply the product of the string lengths of chars_for_param[i]. n_param_combos = libblis_test_count_combos( n_params, p_spec_str, chars_for_param ); // Allocate an array of parameter combination strings, one for each // parameter combination that needs to be tested. pc_str = ( char** ) malloc( n_param_combos * sizeof( char* ) ); for ( i = 0; i < n_param_combos; ++i ) pc_str[i] = ( char* ) malloc( ( n_params + 1 ) * sizeof( char ) ); // Fill the parameter combination strings in pc_str with the parameter // combinations called for by the parameter string p_spec_str. libblis_test_fill_param_strings( p_spec_str, chars_for_param, n_params, n_param_combos, pc_str ); // Figure out how many operands we have. n_operands = strlen( o_types ); // If we are testing a micro-kernel, unconditionally disable the // "mix all storage" option. if ( iface == BLIS_TEST_SEQ_UKERNEL ) mix_all_storage = DISABLE; // Enumerate all combinations of storage schemes requested. if ( mix_all_storage ) { // Fill storage specification string with wildcard chars. for ( i = 0; i < n_operands; ++i ) s_spec_str[i] = '?'; s_spec_str[i] = '\0'; // Allocate an array that stores pointers to the sets of possible // storage chars for each operand. chars_for_storage = ( char** ) malloc( n_operands * sizeof( char* ) ); // Set the values in chars_for_storage to the address of the string // that holds the storage chars. for ( i = 0; i < n_operands; ++i ) { operand_t operand_type = libblis_test_get_operand_type_for_char( o_types[i] ); chars_for_storage[i] = libblis_test_store_chars[ operand_type ]; } // Compute the total number of storage combinations to test (which is // simply the product of the string lengths of chars_for_storage[i]. n_store_combos = libblis_test_count_combos( n_operands, s_spec_str, chars_for_storage ); // Allocate an array of storage combination strings, one for each // storage combination that needs to be tested. sc_str = ( char** ) malloc( n_store_combos * sizeof( char* ) ); for ( sci = 0; sci < n_store_combos; ++sci ) sc_str[sci] = ( char* ) malloc( ( n_operands + 1 ) * sizeof( char ) ); // Fill the storage combination strings in sc_str with the storage // combinations called for by the storage string p_spec_str. libblis_test_fill_param_strings( s_spec_str, chars_for_storage, n_operands, n_store_combos, sc_str ); } else // if ( !mix_all_storage ) { // Only run combinations where all operands of either type (matrices // or vectors) are stored in one storage scheme or another (no mixing // of schemes within the same operand type). unsigned int n_mat_operands = 0; unsigned int n_vec_operands = 0; for ( o = 0; o < n_operands; ++o ) { operand_t operand_type = libblis_test_get_operand_type_for_char( o_types[o] ); if ( operand_type == BLIS_TEST_MATRIX_OPERAND ) ++n_mat_operands; else if ( operand_type == BLIS_TEST_VECTOR_OPERAND ) ++n_vec_operands; } // We compute the total number of storage combinations based on whether // the current operation has only matrix operands, only vector operands, // or both. if ( n_vec_operands == 0 ) { n_store_combos = n_mstorage; n_vstorage = 1; } else if ( n_mat_operands == 0 ) { n_store_combos = n_vstorage; n_mstorage = 1; } else { n_store_combos = n_mstorage * n_vstorage; } sc_str = ( char** ) malloc( n_store_combos * sizeof( char* ) ); for ( j = 0; j < n_mstorage; ++j ) { for ( i = 0; i < n_vstorage; ++i ) { sci = j*n_vstorage + i; sc_str[ sci ] = ( char* ) malloc( ( n_operands + 1 ) * sizeof( char ) ); for ( o = 0; o < n_operands; ++o ) { unsigned int ij; operand_t operand_type = libblis_test_get_operand_type_for_char( o_types[o] ); if ( operand_type == BLIS_TEST_MATRIX_OPERAND ) ij = j; else ij = i; sc_str[sci][o] = params->storage[ operand_type ][ij]; } sc_str[sci][n_operands] = '\0'; } } } // Enumerate all combinations of datatypes requested, but only for the // gemm operation. if ( !mixed_domain && mixed_precision && op->opid == BLIS_GEMM ) { is_mixed_dt = TRUE; // Increment the number of operands by one to account for the // computation precision (or computation datatype, as we will encode // it in the char string). n_operandsp1 = n_operands + 1; unsigned int has_rd = libblis_test_dt_str_has_rd_char( params ); unsigned int has_cd = libblis_test_dt_str_has_cd_char( params ); // Fill datatype specification string with wildcard chars. for ( i = 0; i < n_operandsp1; ++i ) d_spec_str[i] = '?'; d_spec_str[i] = '\0'; // Allocate an array that stores pointers to the sets of possible // datatype chars for each operand. chars_for_rddt = ( char** ) malloc( n_operandsp1 * sizeof( char* ) ); chars_for_cddt = ( char** ) malloc( n_operandsp1 * sizeof( char* ) ); // Set the values in chars_for_rddt/cddt to the address of the string // that holds the datatype chars. for ( i = 0; i < n_operandsp1; ++i ) { chars_for_rddt[i] = libblis_test_rd_chars; chars_for_cddt[i] = libblis_test_cd_chars; } // Set the last set of chars in chars_for_cddt to the real domain // charset. This is because the last char will be the computation // precision. chars_for_cddt[i-1] = libblis_test_rd_chars; // Compute the total number of datatype combinations to test (which is // simply the product of the string lengths of chars_for_spdt/dpdt[i]). // NOTE: We skip inspecting/branching off of the d_spec_str chars since // we know they are all '?'. n_rddt_combos = 0; n_cddt_combos = 0; if ( has_rd ) n_rddt_combos = libblis_test_count_combos( n_operandsp1, d_spec_str, chars_for_rddt ); if ( has_cd ) n_cddt_combos = libblis_test_count_combos( n_operandsp1, d_spec_str, chars_for_cddt ); // Add real and complex domain combinations. n_dt_combos = n_rddt_combos + n_cddt_combos; // Allocate an array of datatype combination strings, one for each // datatype combination that needs to be tested. dc_str = ( char** ) malloc( n_dt_combos * sizeof( char* ) ); for ( dci = 0; dci < n_dt_combos; ++dci ) dc_str[dci] = ( char* ) malloc( ( n_operandsp1 + 1 ) * sizeof( char ) ); char** dc_str_p = dc_str; // Fill the datatype combination strings in dc_str with the datatype // combinations implied by chars_for_rddt/cddt. if ( has_rd ) { libblis_test_fill_param_strings( d_spec_str, chars_for_rddt, n_operandsp1, n_rddt_combos, dc_str_p ); dc_str_p += n_rddt_combos; } if ( has_cd ) { libblis_test_fill_param_strings( d_spec_str, chars_for_cddt, n_operandsp1, n_cddt_combos, dc_str_p ); dc_str_p += n_cddt_combos; } #if 0 printf( "n_rddt_combos = %d\n", n_rddt_combos ); printf( "n_cddt_combos = %d\n", n_cddt_combos ); printf( "n_dt_combos = %d\n\n", n_dt_combos ); for ( dci = 0; dci < n_dt_combos; ++dci ) printf( "dc_str[%2d] = %s\n", dci, dc_str[dci] ); bli_abort(); #endif } else if ( mixed_domain && !mixed_precision && op->opid == BLIS_GEMM ) { is_mixed_dt = TRUE; // Increment the number of operands by one to account for the // computation precision (or computation datatype, as we will encode // it in the char string). n_operandsp1 = n_operands + 1; unsigned int has_sp = libblis_test_dt_str_has_sp_char( params ); unsigned int has_dp = libblis_test_dt_str_has_dp_char( params ); // Fill datatype specification string with wildcard chars. for ( i = 0; i < n_operands; ++i ) d_spec_str[i] = '?'; d_spec_str[i] = '\0'; // Allocate an array that stores pointers to the sets of possible // datatype chars for each operand (plus the computation precision // char). chars_for_spdt = ( char** ) malloc( n_operands * sizeof( char* ) ); chars_for_dpdt = ( char** ) malloc( n_operands * sizeof( char* ) ); // Set the values in chars_for_spdt/dpdt to the address of the string // that holds the datatype chars. for ( i = 0; i < n_operands; ++i ) { chars_for_spdt[i] = libblis_test_sp_chars; chars_for_dpdt[i] = libblis_test_dp_chars; } // Compute the total number of datatype combinations to test (which is // simply the product of the string lengths of chars_for_spdt/dpdt[i]). // NOTE: We skip inspecting/branching off of the d_spec_str chars since // we know they are all '?'. n_spdt_combos = 0; n_dpdt_combos = 0; if ( has_sp ) n_spdt_combos = libblis_test_count_combos( n_operands, d_spec_str, chars_for_spdt ); if ( has_dp ) n_dpdt_combos = libblis_test_count_combos( n_operands, d_spec_str, chars_for_dpdt ); // Add single- and double-precision combinations. n_dt_combos = n_spdt_combos + n_dpdt_combos; // Allocate an array of datatype combination strings, one for each // datatype combination that needs to be tested. dc_str = ( char** ) malloc( n_dt_combos * sizeof( char* ) ); for ( dci = 0; dci < n_dt_combos; ++dci ) dc_str[dci] = ( char* ) malloc( ( n_operandsp1 + 1 ) * sizeof( char ) ); char** dc_str_p = dc_str; // Fill the datatype combination strings in dc_str with the datatype // combinations implied by chars_for_spdt/dpdt. if ( has_sp ) { libblis_test_fill_param_strings( d_spec_str, chars_for_spdt, n_operands, n_spdt_combos, dc_str_p ); dc_str_p += n_spdt_combos; } if ( has_dp ) { libblis_test_fill_param_strings( d_spec_str, chars_for_dpdt, n_operands, n_dpdt_combos, dc_str_p ); dc_str_p += n_dpdt_combos; } // Manually set the computation char to the real projection of the // first char of each combination. int prec_i = n_operands; for ( i = 0; i < n_dt_combos; ++i ) { dc_str[i][prec_i] = libblis_test_proj_dtchar_to_precchar( dc_str[i][0] ); dc_str[i][prec_i+1] = '\0'; } #if 0 printf( "n_spdt_combos = %d\n", n_spdt_combos ); printf( "n_dpdt_combos = %d\n", n_dpdt_combos ); printf( "n_dt_combos = %d\n\n", n_dt_combos ); for ( dci = 0; dci < n_dt_combos; ++dci ) printf( "dc_str[%2d] = %s\n", dci, dc_str[dci] ); bli_abort(); #endif } else if ( mixed_domain && mixed_precision && op->opid == BLIS_GEMM ) { is_mixed_dt = TRUE; // Increment the number of operands by one to account for the // computation precision (or computation datatype, as we will encode // it in the char string). n_operandsp1 = n_operands + 1; // Fill datatype specification string with wildcard chars. for ( i = 0; i < n_operandsp1; ++i ) d_spec_str[i] = '?'; d_spec_str[i] = '\0'; // Allocate an array that stores pointers to the sets of possible // datatype chars for each operand. chars_for_dt = ( char** ) malloc( n_operandsp1 * sizeof( char* ) ); // Set the values in chars_for_rddt/cddt to the address of the string // that holds the datatype chars. for ( i = 0; i < n_operandsp1; ++i ) { chars_for_dt[i] = libblis_test_dt_chars; } // Set the last set of chars in chars_for_dt to the real domain // charset. This is because the last char will be the computation // precision, with the computation domain implied by the operands' // storage datatypes. chars_for_dt[i-1] = libblis_test_rd_chars; // Compute the total number of datatype combinations to test (which is // simply the product of the string lengths of chars_for_dt[i]). // NOTE: We skip inspecting/branching off of the d_spec_str chars since // we know they are all '?'. n_dt_combos = libblis_test_count_combos( n_operandsp1, d_spec_str, chars_for_dt ); // Allocate an array of datatype combination strings, one for each // datatype combination that needs to be tested. dc_str = ( char** ) malloc( n_dt_combos * sizeof( char* ) ); for ( dci = 0; dci < n_dt_combos; ++dci ) dc_str[dci] = ( char* ) malloc( ( n_operandsp1 + 1 ) * sizeof( char ) ); // Fill the datatype combination strings in dc_str with the datatype // combinations implied by chars_for_rddt/cddt. libblis_test_fill_param_strings( d_spec_str, chars_for_dt, n_operandsp1, n_dt_combos, dc_str ); #if 0 printf( "n_dt_combos = %d\n\n", n_dt_combos ); for ( dci = 0; dci < n_dt_combos; ++dci ) printf( "dc_str[%3d] = %s\n", dci, dc_str[dci] ); bli_abort(); #endif } else // ( ( !mixed_domain && !mixed_precision ) || op->opid != BLIS_GEMM ) { is_mixed_dt = FALSE; // Increment the number of operands by one to account for the // computation precision (or computation datatype, as we will encode // it in the char string). n_operandsp1 = n_operands + 1; // Since we are not mixing domains, we only consider n_datatype // datatype combinations, where each combination is actually // homogeneous (e.g. "sss", "ddd", etc., if n_operands == 3). n_dt_combos = n_datatypes; // Allocate an array of datatype combination strings, one for each // datatype specified. dc_str = ( char** ) malloc( n_dt_combos * sizeof( char* ) ); for ( dci = 0; dci < n_dt_combos; ++dci ) dc_str[dci] = ( char* ) malloc( ( n_operandsp1 + 1 ) * sizeof( char ) ); // Fill each datatype combination string with the same dt char for // each operand in the current operation. for ( dci = 0; dci < n_dt_combos; ++dci ) { dt_char = params->datatype_char[dci]; for ( i = 0; i < n_operands; ++i ) dc_str[dci][i] = dt_char; // Encode the computation precision as the last char. dc_str[dci][i] = libblis_test_proj_dtchar_to_precchar( dc_str[dci][0] ); dc_str[dci][i+1] = '\0'; } #if 0 printf( "n_dt_combos = %d\n\n", n_dt_combos ); for ( dci = 0; dci < n_dt_combos; ++dci ) printf( "dc_str[%3d] = %s\n", dci, dc_str[dci] ); bli_abort(); #endif } // These statements should only be executed by one thread. if ( tdata->id == 0 ) { // Output a heading and the contents of the op struct. libblis_test_fprintf_c( stdout, "--- %s ---\n", op_str ); libblis_test_fprintf_c( stdout, "\n" ); libblis_test_output_op_struct( stdout, op, op_str ); // Also output to a matlab file if requested (and successfully opened). if ( output_stream ) { // For file output, we also include the contents of the global // parameter struct. We do this per operation so that the parameters // are included in each file, whereas we only output it once to // stdout (at the end of libblis_test_read_parameter_file()). libblis_test_output_params_struct( output_stream, params ); libblis_test_fprintf_c( output_stream, "--- %s ---\n", op_str ); libblis_test_fprintf_c( output_stream, "\n" ); libblis_test_output_op_struct( output_stream, op, op_str ); } } // Loop over the requested storage schemes. for ( sci = 0; sci < n_store_combos; ++sci ) //for ( sci = 0; sci < 5; ( sci == 0 || sci == 2 ? sci+=2 : ++sci ) ) //for ( sci = 0; sci < 5; ( sci == 2 ? sci+=2 : ++sci ) ) //for ( sci = 3; sci < 8; ( sci == 3 ? sci+=2 : ++sci ) ) //for ( sci = 0; sci < 1; ++sci ) //for ( sci = 7; sci < 8; ++sci ) { // Loop over the requested datatypes. for ( dci = 0; dci < n_dt_combos; ++dci ) //for ( dci = 14; dci < 15; ++dci ) //for ( dci = 6; dci < 7; dci += 1 ) //for ( dci = 12; dci < 13; ++dci ) //for ( dci = 4; dci < 5; ++dci ) //for ( dci = 8; dci < 9; ++dci ) //for ( dci = 0; dci < 1; ++dci ) { // We need a datatype to use for induced method related things // as well as to decide which set of residual thresholds to use. // We must choose the first operand's dt char since that's the // only operand we know is guaranteed to exist. bli_param_map_char_to_blis_dt( dc_str[dci][0], &datatype ); dt_check = datatype; int has_sp = libblis_test_dt_str_has_sp_char_str( n_operandsp1, dc_str[dci] ); int has_dp = libblis_test_dt_str_has_dp_char_str( n_operandsp1, dc_str[dci] ); int has_samep = (has_sp && !has_dp ) || (has_dp && !has_sp ); // Notice that we use n_operands here instead of // n_operandsp1 since we only want to chars for the // storage datatypes of the matrix operands, not the // computation precision char. int has_cd_only = !libblis_test_dt_str_has_rd_char_str( n_operands, dc_str[dci] ); if ( has_sp ) { // If any of the operands are single precision, ensure that // dt_check is also single precision so that the residual is // compared to datatype-appropriate thresholds. dt_check = bli_dt_proj_to_single_prec( datatype ); } // Build a commented column label string. libblis_test_build_col_labels_string( params, op, label_str ); // These statements should only be executed by one thread. if ( tdata->id == 0 ) { // Output the column label string. libblis_test_fprintf( stdout, "%s\n", label_str ); // Also output to a matlab file if requested (and successfully // opened). if ( output_stream ) libblis_test_fprintf( output_stream, "%s\n", label_str ); } // Start by assuming we will only test native execution. ind_t ind_first = BLIS_NAT; dim_t ind_last = BLIS_NAT; // If the operation is level-3, and all operand domains are complex, // then we iterate over all induced methods. if ( bli_opid_is_level3( op->opid ) && has_cd_only ) ind_first = 0; // Loop over induced methods (or just BLIS_NAT). for ( indi = ind_first; indi <= ind_last; ++indi ) { // If the current datatype is real, OR if the current // induced method is implemented (for the operation // being tested) AND it was requested, then we enable // ONLY that method and proceed. Otherwise, we skip the // current method and go to the next method. if ( bli_is_real( datatype ) ) { ; } else if ( bli_ind_oper_is_impl( op->opid, indi ) && params->ind_enable[ indi ] == 1 ) { // If the current induced method is 1m, make sure that // we only proceed for gemm where all operands are stored // in the complex domain. (This prevents 1m from being // executed on mixed-datatype combinations that contain // real domain datatypes.) if ( indi == BLIS_1M ) { if ( op->opid == BLIS_GEMM && has_cd_only ) { ; } else if ( has_samep && has_cd_only ) { ; } else { continue; } } else { ; } } else { continue; } bli_ind_oper_enable_only( op->opid, indi, datatype ); // Query the implementation string associated with the // current operation and datatype. If the operation is // not level-3, we will always get back the native string. ind_str = bli_ind_oper_get_avail_impl_string( op->opid, datatype ); // Loop over the requested parameter combinations. for ( pci = 0; pci < n_param_combos; ++pci ) { // Loop over the requested problem sizes. for ( p_cur = p_first, pi = 1; p_cur <= p_max; p_cur += p_inc, ++pi ) { // Skip this experiment (for this problem size) according to // to the counter, number of threads, and thread id. if ( tdata->xc % tdata->nt != tdata->id ) { tdata->xc++; continue; } // Call the given experiment function. perf and resid will // contain the resulting performance and residual values, // respectively. f_exp( params, op, iface, dc_str[dci], pc_str[pci], sc_str[sci], p_cur, &perf, &resid ); // Remove the sign of the residual, if there is one. resid = bli_fabs( resid ); if ( resid == -0.0 ) resid = 0.0; // Query the string corresponding to the residual's // position relative to the thresholds. pass_str = libblis_test_get_string_for_result( resid, dt_check, thresh ); // Build a string unique to the operation, datatype combo, // parameter combo, and storage combo being tested. libblis_test_build_function_string( BLIS_FILEDATA_PREFIX_STR, op->opid, indi, ind_str, op_str, is_mixed_dt, dc_str[dci], n_param_combos, pc_str[pci], sc_str[sci], funcname_str ); // Compute the number of spaces we have left to fill given // length of our operation's name. n_spaces = MAX_FUNC_STRING_LENGTH - strlen( funcname_str ); fill_string_with_n_spaces( blank_str, n_spaces ); // Print all dimensions to a single string. libblis_test_build_dims_string( op, p_cur, dims_str ); // Count the number of dimensions that were printed to the string. n_dims_print = libblis_test_get_n_dims_from_string( dims_str ); // Output the results of the test. Use matlab format if requested. // NOTE: Here we use fprintf() over libblis_test_fprintf() so // that on POSIX systems the output is not intermingled. If we // used libblis_test_fprintf(), we would need to enclose this // conditional with the acquisition of a mutex shared among all // threads to prevent intermingled output. if ( params->output_matlab_format ) { fprintf( stdout, "%s%s( %3u, 1:%u ) = [%s %7.2lf %8.2le ]; %c %s\n", funcname_str, blank_str, pi, n_dims_print + 2, dims_str, perf, resid, OUTPUT_COMMENT_CHAR, pass_str ); // Also output to a file if requested (and successfully // opened). if ( output_stream ) fprintf( output_stream, "%s%s( %3u, 1:%u ) = [%s %7.2lf %8.2le ]; %c %s\n", funcname_str, blank_str, pi, n_dims_print + 2, dims_str, perf, resid, OUTPUT_COMMENT_CHAR, pass_str ); } else { fprintf( stdout, "%s%s %s %7.2lf %8.2le %s\n", funcname_str, blank_str, dims_str, perf, resid, pass_str ); // Also output to a file if requested (and successfully // opened). if ( output_stream ) fprintf( output_stream, "%s%s %s %7.2lf %8.2le %s\n", funcname_str, blank_str, dims_str, perf, resid, pass_str ); } // If we need to check whether to do something on failure, // do so now. if ( reaction_to_failure == ON_FAILURE_SLEEP_CHAR ) { if ( strstr( pass_str, BLIS_TEST_FAIL_STRING ) == pass_str ) libblis_test_sleep(); } else if ( reaction_to_failure == ON_FAILURE_ABORT_CHAR ) { if ( strstr( pass_str, BLIS_TEST_FAIL_STRING ) == pass_str ) libblis_test_abort(); } // Increment the experiment counter (regardless of whether // the thread executed or skipped the current experiment). tdata->xc += 1; } } } // Wait for all other threads so that the output stays organized. bli_pthread_barrier_wait( tdata->barrier ); // These statements should only be executed by one thread. if ( tdata->id == 0 ) { libblis_test_fprintf( stdout, "\n" ); if ( output_stream ) libblis_test_fprintf( output_stream, "\n" ); } } } // Free the array that stored pointers to the sets of possible parameter // chars for each parameter. free( chars_for_param ); // Free the parameter combination strings and then the master pointer. for ( pci = 0; pci < n_param_combos; ++pci ) free( pc_str[pci] ); free( pc_str ); // Free the storage combination strings and then the master pointer. for ( sci = 0; sci < n_store_combos; ++sci ) free( sc_str[sci] ); free( sc_str ); // Free some auxiliary arrays used by the mixed-domain/mixed-precision // datatype-handling logic. free( chars_for_rddt ); free( chars_for_cddt ); free( chars_for_spdt ); free( chars_for_dpdt ); // Free the datatype combination strings and then the master pointer. for ( dci = 0; dci < n_dt_combos; ++dci ) free( dc_str[dci] ); free( dc_str ); // If the file was opened (successfully), close the output stream. if ( output_stream ) libblis_test_fclose_ofile( output_stream ); // Mark this operation as done. if ( tdata->id == 0 ) op->test_done = TRUE; // Wait here so that all threads know we are done bli_pthread_barrier_wait( tdata->barrier ); } void libblis_test_build_function_string ( char* prefix_str, opid_t opid, ind_t method, char* ind_str, char* op_str, unsigned int is_mixed_dt, char* dc_str, unsigned int n_param_combos, char* pc_str, char* sc_str, char* funcname_str ) { // We only print the full datatype combination string if is_mixed_dt // is set and the operation is gemm. Otherwise, we print only // the first char (since they are all the same). if ( is_mixed_dt == TRUE && opid == BLIS_GEMM ) sprintf( funcname_str, "%s_%s%s", prefix_str, dc_str, op_str ); else sprintf( funcname_str, "%s_%c%s", prefix_str, dc_str[0], op_str ); // If the method is non-native (ie: induced), append a string // identifying the induced method. if ( method != BLIS_NAT ) sprintf( &funcname_str[strlen(funcname_str)], "%s", ind_str ); // We check the string length of pc_str in case the user is running an // operation that has parameters (and thus generally more than one // parameter combination), but has fixed all parameters in the input // file, which would result in n_param_combos to equal one. This way, // the function string contains the parameter string associated with // the parameters that were fixed. if ( n_param_combos > 1 || strlen(pc_str) > 0 ) sprintf( &funcname_str[strlen(funcname_str)], "_%s_%s", pc_str, sc_str ); else sprintf( &funcname_str[strlen(funcname_str)], "_%s", sc_str ); if ( strlen( funcname_str ) > MAX_FUNC_STRING_LENGTH ) libblis_test_printf_error( "Function name string length (%d) exceeds maximum (%d).\n", strlen( funcname_str ), MAX_FUNC_STRING_LENGTH ); } void libblis_test_build_dims_string( test_op_t* op, dim_t p_cur, char* dims_str ) { unsigned int i; // For level-1f experiments with fusing factors, we grab the fusing // factor from the op struct. We do something similar for micro-kernel // calls. if ( op->dimset == BLIS_TEST_DIMS_MF ) { //sprintf( &dims_str[strlen(dims_str)], " %5u %5u", sprintf( dims_str, " %5u %5u", ( unsigned int ) libblis_test_get_dim_from_prob_size( op->dim_spec[0], p_cur ), ( unsigned int ) op->dim_aux[0] ); } else if ( op->dimset == BLIS_TEST_DIMS_K ) { //sprintf( &dims_str[strlen(dims_str)], " %5u %5u %5u", sprintf( dims_str, " %5u %5u %5u", ( unsigned int ) op->dim_aux[0], ( unsigned int ) op->dim_aux[1], ( unsigned int ) libblis_test_get_dim_from_prob_size( op->dim_spec[0], p_cur ) ); } else if ( op->dimset == BLIS_TEST_NO_DIMS ) { //sprintf( &dims_str[strlen(dims_str)], " %5u %5u", sprintf( dims_str, " %5u %5u", ( unsigned int ) op->dim_aux[0], ( unsigned int ) op->dim_aux[1] ); } else // For all other operations, we just use the dim_spec[] values // and the current problem size. { // Initialize the string as empty. sprintf( dims_str, "%s", "" ); // Print all dimensions to a single string. for ( i = 0; i < op->n_dims; ++i ) { sprintf( &dims_str[strlen(dims_str)], " %5u", ( unsigned int ) libblis_test_get_dim_from_prob_size( op->dim_spec[i], p_cur ) ); } } } // % dtoper_params_storage m n k gflops resid result void libblis_test_build_col_labels_string( test_params_t* params, test_op_t* op, char* l_str ) { unsigned int n_spaces; char blank_str[64]; strcpy( l_str, "" ); if ( op->n_params > 0 ) { sprintf( &l_str[strlen(l_str)], "%c %s_%s", OUTPUT_COMMENT_CHAR, BLIS_FILEDATA_PREFIX_STR, "

__" ); } else // ( n_params == 0 ) { sprintf( &l_str[strlen(l_str)], "%c %s_%s", OUTPUT_COMMENT_CHAR, BLIS_FILEDATA_PREFIX_STR, "
_ " ); } if ( params->output_matlab_format ) n_spaces = 11; else n_spaces = 1; fill_string_with_n_spaces( blank_str, n_spaces ); sprintf( &l_str[strlen(l_str)], "%s", blank_str ); if ( op->dimset == BLIS_TEST_DIMS_MNK || op->dimset == BLIS_TEST_DIMS_MN || op->dimset == BLIS_TEST_DIMS_MK || op->dimset == BLIS_TEST_DIMS_M || op->dimset == BLIS_TEST_DIMS_K || op->dimset == BLIS_TEST_DIMS_MF || op->dimset == BLIS_TEST_NO_DIMS ) sprintf( &l_str[strlen(l_str)], " %5s", "m" ); if ( op->dimset == BLIS_TEST_DIMS_MNK || op->dimset == BLIS_TEST_DIMS_MN || op->dimset == BLIS_TEST_DIMS_K || op->dimset == BLIS_TEST_DIMS_MF || op->dimset == BLIS_TEST_NO_DIMS ) sprintf( &l_str[strlen(l_str)], " %5s", "n" ); if ( op->dimset == BLIS_TEST_DIMS_MNK || op->dimset == BLIS_TEST_DIMS_MK || op->dimset == BLIS_TEST_DIMS_K ) sprintf( &l_str[strlen(l_str)], " %5s", "k" ); sprintf( &l_str[strlen(l_str)], "%s", " gflops resid result" ); } void libblis_test_build_filename_string( char* prefix_str, char* op_str, char* funcname_str ) { sprintf( funcname_str, "%s_%s.m", prefix_str, op_str ); } void fill_string_with_n_spaces( char* str, unsigned int n_spaces ) { unsigned int i; // Initialze to empty string in case n_spaces == 0. sprintf( str, "%s", "" ); for ( i = 0; i < n_spaces; ++i ) sprintf( &str[i], " " ); } void libblis_test_mobj_create( test_params_t* params, num_t dt, trans_t trans, char storage, dim_t m, dim_t n, obj_t* a ) { dim_t gs = params->gs_spacing; bool alignment = params->alignment; siz_t elem_size = bli_dt_size( dt ); dim_t m_trans = m; dim_t n_trans = n; dim_t rs = 1; // Initialization avoids a compiler warning. dim_t cs = 1; // Initialization avoids a compiler warning. // Apply the trans parameter to the dimensions (if needed). bli_set_dims_with_trans( trans, m, n, &m_trans, &n_trans ); // Compute unaligned strides according to the storage case encoded in // the storage char, and then align the leading dimension if alignment // was requested. if ( storage == 'c' ) { rs = 1; cs = m_trans; if ( alignment ) cs = bli_align_dim_to_size( cs, elem_size, BLIS_HEAP_STRIDE_ALIGN_SIZE ); } else if ( storage == 'r' ) { rs = n_trans; cs = 1; if ( alignment ) rs = bli_align_dim_to_size( rs, elem_size, BLIS_HEAP_STRIDE_ALIGN_SIZE ); } else if ( storage == 'g' ) { // We apply (arbitrarily) a column tilt, instead of a row tilt, to // all general stride cases. rs = gs; cs = gs * m_trans; if ( alignment ) cs = bli_align_dim_to_size( cs, elem_size, BLIS_HEAP_STRIDE_ALIGN_SIZE ); } else { libblis_test_printf_error( "Invalid storage character: %c\n", storage ); } // Create the object using the dimensions and strides computed above. bli_obj_create( dt, m_trans, n_trans, rs, cs, a ); } cntl_t* libblis_test_pobj_create( bszid_t bmult_id_m, bszid_t bmult_id_n, invdiag_t inv_diag, pack_t pack_schema, packbuf_t pack_buf, obj_t* a, obj_t* p, cntx_t* cntx, rntm_t* rntm ) { bool does_inv_diag; if ( inv_diag == BLIS_NO_INVERT_DIAG ) does_inv_diag = FALSE; else does_inv_diag = TRUE; // Create a control tree node for the packing operation. cntl_t* cntl = bli_packm_cntl_create_node ( NULL, // we don't need the small block allocator from the runtime. NULL, // func ptr is not referenced b/c we don't call via l3 _int(). bmult_id_m, bmult_id_n, does_inv_diag, FALSE, FALSE, pack_schema, pack_buf, NULL // no child node needed ); // Pack the contents of A to P. bli_packm_blk_var1( a, p, cntx, rntm, cntl, &BLIS_PACKM_SINGLE_THREADED ); // Return the control tree pointer so the caller can free the cntl_t and its // mem_t entry later on. return cntl; } void libblis_test_vobj_create( test_params_t* params, num_t dt, char storage, dim_t m, obj_t* x ) { dim_t gs = params->gs_spacing; // Column vector (unit stride) if ( storage == 'c' ) bli_obj_create( dt, m, 1, 1, m, x ); // Row vector (unit stride) else if ( storage == 'r' ) bli_obj_create( dt, 1, m, m, 1, x ); // Column vector (non-unit stride) else if ( storage == 'j' ) bli_obj_create( dt, m, 1, gs, gs*m, x ); // Row vector (non-unit stride) else if ( storage == 'i' ) bli_obj_create( dt, 1, m, gs*m, gs, x ); else { libblis_test_printf_error( "Invalid storage character: %c\n", storage ); } } void libblis_test_vobj_randomize( test_params_t* params, bool normalize, obj_t* x ) { if ( params->rand_method == BLIS_TEST_RAND_REAL_VALUES ) bli_randv( x ); else // if ( params->rand_method == BLIS_TEST_RAND_NARROW_POW2 ) bli_randnv( x ); if ( normalize ) { num_t dt = bli_obj_dt( x ); num_t dt_r = bli_obj_dt_proj_to_real( x ); obj_t kappa; obj_t kappa_r; bli_obj_scalar_init_detached( dt, &kappa ); bli_obj_scalar_init_detached( dt_r, &kappa_r ); // Normalize vector elements. The following code ensures that we // always invert-scale by whole power of two. bli_normfv( x, &kappa_r ); libblis_test_ceil_pow2( &kappa_r ); bli_copysc( &kappa_r, &kappa ); bli_invertsc( &kappa ); bli_scalv( &kappa, x ); } } void libblis_test_mobj_randomize( test_params_t* params, bool normalize, obj_t* a ) { if ( params->rand_method == BLIS_TEST_RAND_REAL_VALUES ) bli_randm( a ); else // if ( params->rand_method == BLIS_TEST_RAND_NARROW_POW2 ) bli_randnm( a ); if ( normalize ) { #if 0 num_t dt = bli_obj_dt( a ); dim_t max_m_n = bli_obj_max_dim( a ); obj_t kappa; bli_obj_scalar_init_detached( dt, &kappa ); // Normalize vector elements by maximum matrix dimension. bli_setsc( 1.0/( double )max_m_n, 0.0, &kappa ); bli_scalm( &kappa, a ); #endif num_t dt = bli_obj_dt( a ); num_t dt_r = bli_obj_dt_proj_to_real( a ); obj_t kappa; obj_t kappa_r; bli_obj_scalar_init_detached( dt, &kappa ); bli_obj_scalar_init_detached( dt_r, &kappa_r ); // Normalize matrix elements. bli_norm1m( a, &kappa_r ); libblis_test_ceil_pow2( &kappa_r ); bli_copysc( &kappa_r, &kappa ); bli_invertsc( &kappa ); bli_scalm( &kappa, a ); } } void libblis_test_ceil_pow2( obj_t* alpha ) { double alpha_r; double alpha_i; bli_getsc( alpha, &alpha_r, &alpha_i ); alpha_r = pow( 2.0, ceil( log2( alpha_r ) ) ); bli_setsc( alpha_r, alpha_i, alpha ); } void libblis_test_mobj_load_diag( test_params_t* params, obj_t* a ) { // We assume that all elements of a were intialized on interval [-1,1]. // Load the diagonal by 2.0. bli_shiftd( &BLIS_TWO, a ); } void libblis_test_init_strings( void ) { strcpy( libblis_test_pass_string, BLIS_TEST_PASS_STRING ); strcpy( libblis_test_warn_string, BLIS_TEST_WARN_STRING ); strcpy( libblis_test_fail_string, BLIS_TEST_FAIL_STRING ); strcpy( libblis_test_param_chars[BLIS_TEST_PARAM_SIDE], BLIS_TEST_PARAM_SIDE_CHARS ); strcpy( libblis_test_param_chars[BLIS_TEST_PARAM_UPLO], BLIS_TEST_PARAM_UPLO_CHARS ); strcpy( libblis_test_param_chars[BLIS_TEST_PARAM_UPLODE], BLIS_TEST_PARAM_UPLODE_CHARS ); strcpy( libblis_test_param_chars[BLIS_TEST_PARAM_TRANS], BLIS_TEST_PARAM_TRANS_CHARS ); strcpy( libblis_test_param_chars[BLIS_TEST_PARAM_CONJ], BLIS_TEST_PARAM_CONJ_CHARS ); strcpy( libblis_test_param_chars[BLIS_TEST_PARAM_DIAG], BLIS_TEST_PARAM_DIAG_CHARS ); strcpy( libblis_test_store_chars[BLIS_TEST_MATRIX_OPERAND], BLIS_TEST_MSTORE_CHARS ); strcpy( libblis_test_store_chars[BLIS_TEST_VECTOR_OPERAND], BLIS_TEST_VSTORE_CHARS ); } void libblis_test_sleep( void ) { int i; libblis_test_printf_infoc( "Resuming in " ); for ( i = SECONDS_TO_SLEEP; i > 0; --i ) { libblis_test_printf_info( "%d ", i ); bli_sleep(1); } libblis_test_printf_info( "\n" ); } void libblis_test_abort( void ) { abort(); } void libblis_test_fopen_ofile( char* op_str, iface_t iface, FILE** output_stream ) { char filename_str[ MAX_FILENAME_LENGTH ]; if ( iface == BLIS_TEST_MT_FRONT_END ) bli_check_error_code( BLIS_NOT_YET_IMPLEMENTED ); // Construct a filename string for the current operation. libblis_test_build_filename_string( BLIS_FILE_PREFIX_STR, op_str, filename_str ); // Open the output file (overwriting a previous instance, if it exists) // for writing (in binary mode). *output_stream = fopen( filename_str, "wb" ); // Check the output stream and report an error if something went wrong. libblis_test_fopen_check_stream( filename_str, *output_stream ); } void libblis_test_fclose_ofile( FILE* output_stream ) { fclose( output_stream ); } void libblis_test_fopen_check_stream( char* filename_str, FILE* stream ) { // Check for success. if ( stream == NULL ) { libblis_test_printf_error( "Failed to open file %s. Check existence (if file is being read), permissions (if file is being overwritten), and/or storage limit.\n", filename_str ); } } void libblis_test_read_next_line( char* buffer, FILE* input_stream ) { char temp[ INPUT_BUFFER_SIZE ]; // We want to read at least one line, so we use a do-while loop. do { // Read the next line into a temporary buffer and check success. if ( fgets( temp, INPUT_BUFFER_SIZE-1, input_stream ) == NULL ) { if ( feof( input_stream ) ) libblis_test_printf_error( "Error reading input file: encountered unexpected EOF." ); else libblis_test_printf_error( "Error (non-EOF) reading input file." ); } } // We continue to read lines into buffer until the line is neither // commented nor blank. while ( temp[0] == INPUT_COMMENT_CHAR || temp[0] == '\n' || temp[0] == ' ' || temp[0] == '\t' ); // Save the string in temp, up to first white space character, into buffer. //sscanf( temp, "%s ", buffer ); strcpy( buffer, temp ); //printf( "libblis_test_read_next_line() read: %s\n", buffer ); } void libblis_test_fprintf( FILE* output_stream, char* message, ... ) { va_list args; // Initialize variable argument environment. va_start( args, message ); // Parse the received message and print its components. libblis_test_parse_message( output_stream, message, args ); // Shutdown variable argument environment and clean up stack. va_end( args ); // Flush the output stream. fflush( output_stream ); } void libblis_test_fprintf_c( FILE* output_stream, char* message, ... ) { va_list args; fprintf( output_stream, "%c ", OUTPUT_COMMENT_CHAR ); // Initialize variable argument environment. va_start( args, message ); // Parse the received message and print its components. libblis_test_parse_message( output_stream, message, args ); // Shutdown variable argument environment and clean up stack. va_end( args ); // Flush the output stream. fflush( output_stream ); } void libblis_test_printf_info( char* message, ... ) { FILE* output_stream = stdout; va_list args; // Initialize variable argument environment. va_start( args, message ); // Parse the received message and print its components. libblis_test_parse_message( output_stream, message, args ); // Shutdown variable argument environment and clean up stack. va_end( args ); // Flush the output stream. fflush( output_stream ); } void libblis_test_printf_infoc( char* message, ... ) { FILE* output_stream = stdout; va_list args; fprintf( output_stream, "%c ", OUTPUT_COMMENT_CHAR ); // Initialize variable argument environment. va_start( args, message ); // Parse the received message and print its components. libblis_test_parse_message( output_stream, message, args ); // Shutdown variable argument environment and clean up stack. va_end( args ); // Flush the output stream. fflush( output_stream ); } void libblis_test_printf_error( char* message, ... ) { FILE* output_stream = stderr; va_list args; fprintf( output_stream, "%s: *** error ***: ", libblis_test_binary_name ); // Initialize variable argument environment. va_start( args, message ); // Parse the received message and print its components. libblis_test_parse_message( output_stream, message, args ); // Shutdown variable argument environment and clean up stack. va_end( args ); // Flush the output stream. fflush( output_stream ); // Exit. exit(1); } void libblis_test_parse_message( FILE* output_stream, char* message, va_list args ) { int c, cf; char format_spec[8]; unsigned int the_uint; int the_int; double the_double; char* the_string; char the_char; // Begin looping over message to insert variables wherever there are // format specifiers. for ( c = 0; message[c] != '\0'; ) { if ( message[c] != '%' ) { fprintf( output_stream, "%c", message[c] ); c += 1; } else if ( message[c] == '%' && message[c+1] == '%' ) // handle escaped '%' chars. { fprintf( output_stream, "%c", message[c] ); c += 2; } else { // Save the format string if there is one. format_spec[0] = '%'; for ( c += 1, cf = 1; strchr( "udefsc", message[c] ) == NULL; ++c, ++cf ) { format_spec[cf] = message[c]; } // Add the final type specifier, and null-terminate the string. format_spec[cf] = message[c]; format_spec[cf+1] = '\0'; // Switch based on type, since we can't predict what will // va_args() will return. switch ( message[c] ) { case 'u': the_uint = va_arg( args, unsigned int ); fprintf( output_stream, format_spec, the_uint ); break; case 'd': the_int = va_arg( args, int ); fprintf( output_stream, format_spec, the_int ); break; case 'e': the_double = va_arg( args, double ); fprintf( output_stream, format_spec, the_double ); break; case 'f': the_double = va_arg( args, double ); fprintf( output_stream, format_spec, the_double ); break; case 's': the_string = va_arg( args, char* ); //fprintf( output_stream, "%s", the_string ); fprintf( output_stream, format_spec, the_string ); break; case 'c': the_char = va_arg( args, int ); fprintf( output_stream, "%c", the_char ); break; } // Move to next character past type specifier. c += 1; } } } void libblis_test_parse_command_line( int argc, char** argv ) { bool gave_option_g = FALSE; bool gave_option_o = FALSE; int opt; char opt_ch; getopt_t state; // Copy the binary name to a global string so we can use it later. strncpy( libblis_test_binary_name, argv[0], MAX_BINARY_NAME_LENGTH ); // Initialize the state for running bli_getopt(). Here, 0 is the // initial value for opterr, which suppresses error messages. bli_getopt_init_state( 0, &state ); // Process all option arguments until we get a -1, which means we're done. while( (opt = bli_getopt( argc, argv, "g:o:", &state )) != -1 ) { // Explicitly typecast opt, which is an int, to a char. (Failing to // typecast resulted in at least one user-reported problem whereby // opt was being filled with garbage.) opt_ch = ( char )opt; switch( opt_ch ) { case 'g': libblis_test_printf_infoc( "detected -g option; using \"%s\" for parameters filename.\n", state.optarg ); strncpy( libblis_test_parameters_filename, state.optarg, MAX_FILENAME_LENGTH ); gave_option_g = TRUE; break; case 'o': libblis_test_printf_infoc( "detected -o option; using \"%s\" for operations filename.\n", state.optarg ); strncpy( libblis_test_operations_filename, state.optarg, MAX_FILENAME_LENGTH ); gave_option_o = TRUE; break; case '?': libblis_test_printf_error( "unexpected option '%c' given or missing option argument\n", state.optopt ); break; default: libblis_test_printf_error( "unexpected option chararcter returned from getopt: %c\n", opt_ch ); } } if ( gave_option_g == FALSE ) { libblis_test_printf_infoc( "no -g option given; defaulting to \"%s\" for parameters filename.\n", PARAMETERS_FILENAME ); // Copy default parameters filename into its global string. strncpy( libblis_test_parameters_filename, PARAMETERS_FILENAME, MAX_FILENAME_LENGTH ); } if ( gave_option_o == FALSE ) { libblis_test_printf_infoc( "no -o option given; defaulting to \"%s\" for operations filename.\n", OPERATIONS_FILENAME ); // Copy default operations filename into its global string. strncpy( libblis_test_operations_filename, OPERATIONS_FILENAME, MAX_FILENAME_LENGTH ); } // If there are still arguments remaining after getopt() processing is // complete, print an error. if ( state.optind < argc ) { libblis_test_printf_error( "Encountered unexpected non-option argument: %s\n", argv[ state.optind ] ); } } void libblis_test_check_empty_problem( obj_t* c, double* perf, double* resid ) { if ( bli_obj_has_zero_dim( c ) ) { *perf = 0.0; *resid = 0.0; } } int libblis_test_op_is_disabled( test_op_t* op ) { int r_val; // If there was at least one individual override, then an op test is // disabled if it is NOT equal to ENABLE_ONLY. If there were no // individual overrides, then an op test is disabled if it is equal // to DISABLE. if ( op->ops->indiv_over == TRUE ) { if ( op->op_switch != ENABLE_ONLY ) r_val = TRUE; else r_val = FALSE; } else // if ( op->ops->indiv_over == FALSE ) { if ( op->op_switch == DISABLE ) r_val = TRUE; else r_val = FALSE; } return r_val; } bool libblis_test_op_is_done( test_op_t* op ) { return op->test_done; } int libblis_test_util_is_disabled( test_op_t* op ) { if ( op->ops->util_over == DISABLE ) return TRUE; else return FALSE; } int libblis_test_l1v_is_disabled( test_op_t* op ) { if ( op->ops->l1v_over == DISABLE ) return TRUE; else return FALSE; } int libblis_test_l1m_is_disabled( test_op_t* op ) { if ( op->ops->l1m_over == DISABLE ) return TRUE; else return FALSE; } int libblis_test_l1f_is_disabled( test_op_t* op ) { if ( op->ops->l1f_over == DISABLE ) return TRUE; else return FALSE; } int libblis_test_l2_is_disabled( test_op_t* op ) { if ( op->ops->l2_over == DISABLE ) return TRUE; else return FALSE; } int libblis_test_l3ukr_is_disabled( test_op_t* op ) { if ( op->ops->l3ukr_over == DISABLE ) return TRUE; else return FALSE; } int libblis_test_l3_is_disabled( test_op_t* op ) { if ( op->ops->l3_over == DISABLE ) return TRUE; else return FALSE; } // --- int libblis_test_dt_str_has_sp_char( test_params_t* params ) { return libblis_test_dt_str_has_sp_char_str( params->n_datatypes, params->datatype_char ); } int libblis_test_dt_str_has_sp_char_str( int n, char* str ) { for ( int i = 0; i < n; ++i ) { if ( str[i] == 's' || str[i] == 'c' ) return TRUE; } return FALSE; } int libblis_test_dt_str_has_dp_char( test_params_t* params ) { return libblis_test_dt_str_has_dp_char_str( params->n_datatypes, params->datatype_char ); } int libblis_test_dt_str_has_dp_char_str( int n, char* str ) { for ( int i = 0; i < n; ++i ) { if ( str[i] == 'd' || str[i] == 'z' ) return TRUE; } return FALSE; } // --- int libblis_test_dt_str_has_rd_char( test_params_t* params ) { return libblis_test_dt_str_has_rd_char_str( params->n_datatypes, params->datatype_char ); } int libblis_test_dt_str_has_rd_char_str( int n, char* str ) { for ( int i = 0; i < n; ++i ) { if ( str[i] == 's' || str[i] == 'd' ) return TRUE; } return FALSE; } int libblis_test_dt_str_has_cd_char( test_params_t* params ) { return libblis_test_dt_str_has_cd_char_str( params->n_datatypes, params->datatype_char ); } int libblis_test_dt_str_has_cd_char_str( int n, char* str ) { for ( int i = 0; i < n; ++i ) { if ( str[i] == 'c' || str[i] == 'z' ) return TRUE; } return FALSE; } // --- unsigned int libblis_test_count_combos ( unsigned int n_operands, char* spec_str, char** char_sets ) { unsigned int n_combos = 1; for ( int i = 0; i < n_operands; ++i ) { if ( spec_str[i] == '?' ) n_combos *= strlen( char_sets[i] ); } return n_combos; } char libblis_test_proj_dtchar_to_precchar( char dt_char ) { char r_val = dt_char; if ( r_val == 'c' ) r_val = 's'; else if ( r_val == 'z' ) r_val = 'd'; return r_val; } blis-0.9.0/testsuite/src/test_libblis.h000066400000000000000000000404401422157504600201310ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2020, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ // // --- System headers ---------------------------------------------------------- // // For va_* functions. #include // For string manipulation functions. #include // For other string manipulation functions (e.g. isspace()). #include // For POSIX stuff. #ifndef _MSC_VER #include #endif // // --- Constants and types ----------------------------------------------------- // #define PARAMETERS_FILENAME "input.general" #define OPERATIONS_FILENAME "input.operations" #define INPUT_COMMENT_CHAR '#' #define OUTPUT_COMMENT_CHAR '%' #define BLIS_FILE_PREFIX_STR "libblis_test" #define BLIS_FILEDATA_PREFIX_STR "blis" #define INPUT_BUFFER_SIZE 256 #define MAX_FILENAME_LENGTH 1000 #define MAX_BINARY_NAME_LENGTH 256 #define MAX_FUNC_STRING_LENGTH 26 #define FLOPS_PER_UNIT_PERF 1e9 #define MAX_NUM_MSTORAGE 4 #define MAX_NUM_VSTORAGE 5 #define MAX_NUM_DATATYPES 4 #define MAX_NUM_PARAMETERS 7 #define MAX_NUM_DIMENSIONS 3 #define MAX_NUM_OPERANDS 5 #define MAX_PASS_STRING_LENGTH 32 #define BLIS_TEST_FAIL_STRING "FAILURE" #define BLIS_TEST_WARN_STRING "MARGINAL" #define BLIS_TEST_PASS_STRING "PASS" #define ON_FAILURE_IGNORE_CHAR 'i' #define ON_FAILURE_SLEEP_CHAR 's' #define ON_FAILURE_ABORT_CHAR 'a' #define SECONDS_TO_SLEEP 3 #define DISABLE 0 #define ENABLE 1 #define ENABLE_ONLY 2 #define MAX_PARAM_VALS_PER_TYPE 4 #define BLIS_TEST_PARAM_SIDE_CHARS "lr" #define BLIS_TEST_PARAM_UPLO_CHARS "lu" #define BLIS_TEST_PARAM_UPLODE_CHARS "dlu" #define BLIS_TEST_PARAM_TRANS_CHARS "ncth" #define BLIS_TEST_PARAM_CONJ_CHARS "nc" #define BLIS_TEST_PARAM_DIAG_CHARS "nu" #define NUM_PARAM_TYPES 6 typedef enum { BLIS_TEST_PARAM_SIDE = 0, BLIS_TEST_PARAM_UPLO = 1, BLIS_TEST_PARAM_UPLODE = 2, BLIS_TEST_PARAM_TRANS = 3, BLIS_TEST_PARAM_CONJ = 4, BLIS_TEST_PARAM_DIAG = 5, } param_t; #define MAX_STORE_VALS_PER_TYPE 4 #define BLIS_TEST_MSTORE_CHARS "crg" #define BLIS_TEST_VSTORE_CHARS "crji" #define NUM_OPERAND_TYPES 2 typedef enum { BLIS_TEST_MATRIX_OPERAND = 0, BLIS_TEST_VECTOR_OPERAND = 1, } operand_t; typedef enum { BLIS_TEST_DIMS_MNK = 0, BLIS_TEST_DIMS_MN = 1, BLIS_TEST_DIMS_MK = 2, BLIS_TEST_DIMS_M = 3, BLIS_TEST_DIMS_MF = 4, BLIS_TEST_DIMS_K = 5, BLIS_TEST_NO_DIMS = 6, } dimset_t; typedef enum { BLIS_TEST_SEQ_UKERNEL = 0, BLIS_TEST_SEQ_FRONT_END = 1, BLIS_TEST_MT_FRONT_END = 2, } iface_t; typedef enum { BLIS_TEST_RAND_REAL_VALUES = 0, BLIS_TEST_RAND_NARROW_POW2 = 1, } rand_t; typedef struct { unsigned int n_repeats; unsigned int n_mstorage; unsigned int n_vstorage; char storage[ NUM_OPERAND_TYPES ][ MAX_NUM_MSTORAGE + 1 ]; unsigned int mix_all_storage; unsigned int alignment; unsigned int rand_method; unsigned int gs_spacing; unsigned int n_datatypes; char datatype_char[ MAX_NUM_DATATYPES + 1 ]; num_t datatype[ MAX_NUM_DATATYPES + 1 ]; unsigned int mixed_domain; unsigned int mixed_precision; unsigned int p_first; unsigned int p_max; unsigned int p_inc; unsigned int ind_enable[ BLIS_NUM_IND_METHODS ]; unsigned int n_app_threads; char reaction_to_failure; unsigned int output_matlab_format; unsigned int output_files; unsigned int error_checking_level; } test_params_t; typedef struct { // parent test_ops_t struct struct test_ops_s* ops; opid_t opid; int op_switch; #if 0 int front_seq; #endif unsigned int n_dims; dimset_t dimset; int dim_spec[ MAX_NUM_DIMENSIONS ]; int dim_aux[ MAX_NUM_DIMENSIONS ]; unsigned int n_params; char params[ MAX_NUM_PARAMETERS ]; bool test_done; } test_op_t; typedef struct test_ops_s { // individual override int indiv_over; // section overrides int util_over; int l1v_over; int l1m_over; int l1f_over; int l2_over; int l3ukr_over; int l3_over; // util test_op_t randv; test_op_t randm; // level-1v test_op_t addv; test_op_t amaxv; test_op_t axpbyv; test_op_t axpyv; test_op_t copyv; test_op_t dotv; test_op_t dotxv; test_op_t normfv; test_op_t scalv; test_op_t scal2v; test_op_t setv; test_op_t subv; test_op_t xpbyv; // level-1m test_op_t addm; test_op_t axpym; test_op_t copym; test_op_t normfm; test_op_t scalm; test_op_t scal2m; test_op_t setm; test_op_t subm; test_op_t xpbym; // level-1f test_op_t axpy2v; test_op_t dotaxpyv; test_op_t axpyf; test_op_t dotxf; test_op_t dotxaxpyf; // level-2 test_op_t gemv; test_op_t ger; test_op_t hemv; test_op_t her; test_op_t her2; test_op_t symv; test_op_t syr; test_op_t syr2; test_op_t trmv; test_op_t trsv; // level-3 micro-kernels test_op_t gemm_ukr; test_op_t trsm_ukr; test_op_t gemmtrsm_ukr; // level-3 test_op_t gemm; test_op_t gemmt; test_op_t hemm; test_op_t herk; test_op_t her2k; test_op_t symm; test_op_t syrk; test_op_t syr2k; test_op_t trmm; test_op_t trmm3; test_op_t trsm; } test_ops_t; typedef struct { double failwarn; double warnpass; } thresh_t; typedef struct thread_data { test_params_t* params; test_ops_t* ops; unsigned int nt; unsigned int id; unsigned int xc; //bli_pthread_mutex_t* mutex; bli_pthread_barrier_t* barrier; } thread_data_t; // // --- Prototypes -------------------------------------------------------------- // void* libblis_test_thread_entry( void* tdata_void ); void libblis_test_thread_decorator( test_params_t* params, test_ops_t* ops ); void libblis_test_all_ops( thread_data_t* tdata, test_params_t* params, test_ops_t* ops ); void libblis_test_utility_ops( thread_data_t* tdata, test_params_t* params, test_ops_t* ops ); void libblis_test_level1m_ops( thread_data_t* tdata, test_params_t* params, test_ops_t* ops ); void libblis_test_level1v_ops( thread_data_t* tdata, test_params_t* params, test_ops_t* ops ); void libblis_test_level1f_ops( thread_data_t* tdata, test_params_t* params, test_ops_t* ops ); void libblis_test_level2_ops( thread_data_t* tdata, test_params_t* params, test_ops_t* ops ); void libblis_test_level3_ukrs( thread_data_t* tdata, test_params_t* params, test_ops_t* ops ); void libblis_test_level3_ops( thread_data_t* tdata, test_params_t* params, test_ops_t* ops ); void libblis_test_read_params_file( char* input_filename, test_params_t* params ); void libblis_test_read_ops_file( char* input_filename, test_ops_t* ops ); void libblis_test_read_section_override( test_ops_t* ops, FILE* input_stream, int* override ); void libblis_test_read_op_info( test_ops_t* ops, FILE* input_stream, opid_t opid, dimset_t dimset, unsigned int n_params, test_op_t* op ); // --- Struct output --- void libblis_test_output_section_overrides( FILE* os, test_ops_t* ops ); void libblis_test_output_params_struct( FILE* os, test_params_t* params ); void libblis_test_output_op_struct( FILE* os, test_op_t* op, char* op_str ); // --- Mapping --- char* libblis_test_get_string_for_result( double residual, num_t dt, thresh_t* thresh ); param_t libblis_test_get_param_type_for_char( char p_type ); operand_t libblis_test_get_operand_type_for_char( char o_type ); unsigned int libblis_test_get_n_dims_from_dimset( dimset_t dimset ); unsigned int libblis_test_get_n_dims_from_string( char* dims_str ); dim_t libblis_test_get_dim_from_prob_size( int dim_spec, unsigned int p_size ); // --- Parameter/storage string generation --- void libblis_test_fill_param_strings( char* p_str, char** chars_for_param, unsigned int n_params, unsigned int n_param_combos, char** pc_str ); void carryover( unsigned int* c, unsigned int* n_vals_for_param, unsigned int n_params ); // --- Operation driver --- void libblis_test_op_driver ( thread_data_t* tdata, test_params_t* params, test_op_t* op, iface_t iface, char* op_str, char* p_types, char* o_types, thresh_t* thresh, void (*f_exp) (test_params_t*, // params struct test_op_t*, // op struct iface_t, // iface char*, // dc_str (current datatype string) char*, // pc_str (current param string) char*, // sc_str (current storage string) unsigned int, // p_cur (current problem size) double*, // perf double*) // residual ); // --- Generate experiment string labels --- void libblis_test_build_function_string ( char* prefix_str, opid_t opid, ind_t method, char* ind_str, char* op_str, unsigned int is_mixed_dt, char* dc_str, unsigned int n_param_combos, char* pc_str, char* sc_str, char* funcname_str ); void libblis_test_build_dims_string( test_op_t* op, dim_t p_cur, char* dims_str ); void libblis_test_build_filename_string( char* prefix_str, char* op_str, char* funcname_str ); void libblis_test_build_col_labels_string( test_params_t* params, test_op_t* op, char* l_str ); void fill_string_with_n_spaces( char* str, unsigned int n_spaces ); // --- Create object --- void libblis_test_mobj_create( test_params_t* params, num_t dt, trans_t trans, char storage, dim_t m, dim_t n, obj_t* a ); cntl_t* libblis_test_pobj_create( bszid_t bmult_id_m, bszid_t bmult_id_n, invdiag_t inv_diag, pack_t pack_schema, packbuf_t pack_buf, obj_t* a, obj_t* p, cntx_t* cntx, rntm_t* rntm ); void libblis_test_vobj_create( test_params_t* params, num_t dt, char storage, dim_t m, obj_t* x ); // --- Randomize/initialize object --- void libblis_test_vobj_randomize( test_params_t* params, bool normalize, obj_t* x ); void libblis_test_mobj_randomize( test_params_t* params, bool normalize, obj_t* a ); void libblis_test_mobj_load_diag( test_params_t* params, obj_t* a ); void libblis_test_ceil_pow2( obj_t* alpha ); // --- Global string initialization --- void libblis_test_init_strings( void ); // --- System wrappers --- void libblis_test_sleep( void ); void libblis_test_abort( void ); // --- File I/O wrappers --- void libblis_test_fopen_ofile( char* op_str, iface_t iface, FILE** output_stream ); void libblis_test_fclose_ofile( FILE* output_stream ); void libblis_test_fopen_check_stream( char* filename_str, FILE* stream ); void libblis_test_read_next_line( char* buffer, FILE* input_stream ); // --- Custom fprintf-related --- void libblis_test_fprintf( FILE* output_stream, char* message, ... ); void libblis_test_fprintf_c( FILE* output_stream, char* message, ... ); void libblis_test_printf_info( char* message, ... ); void libblis_test_printf_infoc( char* message, ... ); void libblis_test_printf_error( char* message, ... ); void libblis_test_parse_message( FILE* output_stream, char* message, va_list args ); void libblis_test_parse_command_line( int argc, char** argv ); // --- Miscellaneous --- void libblis_test_check_empty_problem( obj_t* c, double* perf, double* resid ); int libblis_test_op_is_disabled( test_op_t* op ); bool libblis_test_op_is_done( test_op_t* op ); int libblis_test_util_is_disabled( test_op_t* op ); int libblis_test_l1v_is_disabled( test_op_t* op ); int libblis_test_l1m_is_disabled( test_op_t* op ); int libblis_test_l1f_is_disabled( test_op_t* op ); int libblis_test_l2_is_disabled( test_op_t* op ); int libblis_test_l3ukr_is_disabled( test_op_t* op ); int libblis_test_l3_is_disabled( test_op_t* op ); int libblis_test_dt_str_has_sp_char( test_params_t* params ); int libblis_test_dt_str_has_sp_char_str( int n, char* str ); int libblis_test_dt_str_has_dp_char( test_params_t* params ); int libblis_test_dt_str_has_dp_char_str( int n, char* str ); int libblis_test_dt_str_has_rd_char( test_params_t* params ); int libblis_test_dt_str_has_rd_char_str( int n, char* str ); int libblis_test_dt_str_has_cd_char( test_params_t* params ); int libblis_test_dt_str_has_cd_char_str( int n, char* str ); unsigned int libblis_test_count_combos ( unsigned int n_operands, char* spec_str, char** char_sets ); char libblis_test_proj_dtchar_to_precchar( char dt_char ); // // --- Test module headers ----------------------------------------------------- // // Utility operations #include "test_randv.h" #include "test_randm.h" // Level-1v #include "test_addv.h" #include "test_amaxv.h" #include "test_axpbyv.h" #include "test_axpyv.h" #include "test_copyv.h" #include "test_dotv.h" #include "test_dotxv.h" #include "test_normfv.h" #include "test_scalv.h" #include "test_scal2v.h" #include "test_setv.h" #include "test_subv.h" #include "test_xpbyv.h" // Level-1m #include "test_addm.h" #include "test_axpym.h" #include "test_copym.h" #include "test_normfm.h" #include "test_scalm.h" #include "test_scal2m.h" #include "test_setm.h" #include "test_subm.h" #include "test_xpbym.h" // Level-1f kernels #include "test_axpy2v.h" #include "test_dotaxpyv.h" #include "test_axpyf.h" #include "test_dotxf.h" #include "test_dotxaxpyf.h" // Level-2 #include "test_gemv.h" #include "test_ger.h" #include "test_hemv.h" #include "test_her.h" #include "test_her2.h" #include "test_symv.h" #include "test_syr.h" #include "test_syr2.h" #include "test_trmv.h" #include "test_trsv.h" // Level-3 micro-kernels #include "test_gemm_ukr.h" #include "test_trsm_ukr.h" #include "test_gemmtrsm_ukr.h" // Level-3 #include "test_gemm.h" #include "test_gemmt.h" #include "test_hemm.h" #include "test_herk.h" #include "test_her2k.h" #include "test_symm.h" #include "test_syrk.h" #include "test_syr2k.h" #include "test_trmm.h" #include "test_trmm3.h" #include "test_trsm.h" blis-0.9.0/testsuite/src/test_normfm.c000066400000000000000000000171061422157504600200050ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "test_libblis.h" // Static variables. static char* op_str = "normfm"; static char* o_types = "m"; // x static char* p_types = ""; // (no parameters) static thresh_t thresh[BLIS_NUM_FP_TYPES] = { { 1e-04, 1e-05 }, // warn, pass for s { 1e-04, 1e-05 }, // warn, pass for c { 1e-13, 1e-14 }, // warn, pass for d { 1e-13, 1e-14 } }; // warn, pass for z // Local prototypes. void libblis_test_normfm_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); void libblis_test_normfm_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ); void libblis_test_normfm_impl ( iface_t iface, obj_t* x, obj_t* norm ); void libblis_test_normfm_check ( test_params_t* params, obj_t* beta, obj_t* x, obj_t* norm, double* resid ); void libblis_test_normfm_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { libblis_test_setm( tdata, params, &(op->ops->setm) ); } void libblis_test_normfm ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { // Return early if this test has already been done. if ( libblis_test_op_is_done( op ) ) return; // Return early if operation is disabled. if ( libblis_test_op_is_disabled( op ) || libblis_test_l1m_is_disabled( op ) ) return; // Call dependencies first. if ( TRUE ) libblis_test_normfm_deps( tdata, params, op ); // Execute the test driver for each implementation requested. //if ( op->front_seq == ENABLE ) { libblis_test_op_driver( tdata, params, op, BLIS_TEST_SEQ_FRONT_END, op_str, p_types, o_types, thresh, libblis_test_normfm_experiment ); } } void libblis_test_normfm_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ) { unsigned int n_repeats = params->n_repeats; unsigned int i; double time_min = DBL_MAX; double time; num_t datatype; num_t dt_real; dim_t m, n; obj_t beta, norm; obj_t x; // Use the datatype of the first char in the datatype combination string. bli_param_map_char_to_blis_dt( dc_str[0], &datatype ); // Compute the real projection of the chosen datatype. dt_real = bli_dt_proj_to_real( datatype ); // Map the dimension specifier to actual dimensions. m = libblis_test_get_dim_from_prob_size( op->dim_spec[0], p_cur ); n = libblis_test_get_dim_from_prob_size( op->dim_spec[1], p_cur ); // Map parameter characters to BLIS constants. // Create test scalars. bli_obj_scalar_init_detached( datatype, &beta ); bli_obj_scalar_init_detached( dt_real, &norm ); // Create test operands (vectors and/or matrices). libblis_test_mobj_create( params, datatype, BLIS_NO_TRANSPOSE, sc_str[0], m, n, &x ); // Initialize beta to 2 - 2i. bli_setsc( 2.0, -2.0, &beta ); // Set all elements of x to beta. bli_setm( &beta, &x ); // Repeat the experiment n_repeats times and record results. for ( i = 0; i < n_repeats; ++i ) { time = bli_clock(); libblis_test_normfm_impl( iface, &x, &norm ); time_min = bli_clock_min_diff( time_min, time ); } // Estimate the performance of the best experiment repeat. *perf = ( 2.0 * m * n ) / time_min / FLOPS_PER_UNIT_PERF; if ( bli_obj_is_complex( &x ) ) *perf *= 2.0; // Perform checks. libblis_test_normfm_check( params, &beta, &x, &norm, resid ); // Zero out performance and residual if input matrix is empty. libblis_test_check_empty_problem( &x, perf, resid ); // Free the test objects. bli_obj_free( &x ); } void libblis_test_normfm_impl ( iface_t iface, obj_t* x, obj_t* norm ) { switch ( iface ) { case BLIS_TEST_SEQ_FRONT_END: bli_normfm( x, norm ); break; default: libblis_test_printf_error( "Invalid interface type.\n" ); } } void libblis_test_normfm_check ( test_params_t* params, obj_t* beta, obj_t* x, obj_t* norm, double* resid ) { num_t dt_real = bli_obj_dt_proj_to_real( x ); dim_t m = bli_obj_length( x ); dim_t n = bli_obj_width( x ); obj_t m_r, n_r, temp_r; double junk; // // Pre-conditions: // - x is set to beta. // Note: // - beta should have a non-zero imaginary component in the complex // cases in order to more fully exercise the implementation. // // Under these conditions, we assume that the implementation for // // norm := normfm( x ) // // is functioning correctly if // // norm = sqrt( absqsc( beta ) * m * n ) // // where m and n are the dimensions of x. // bli_obj_scalar_init_detached( dt_real, &temp_r ); bli_obj_scalar_init_detached( dt_real, &m_r ); bli_obj_scalar_init_detached( dt_real, &n_r ); bli_setsc( ( double )m, 0.0, &m_r ); bli_setsc( ( double )n, 0.0, &n_r ); bli_absqsc( beta, &temp_r ); bli_mulsc( &m_r, &temp_r ); bli_mulsc( &n_r, &temp_r ); bli_sqrtsc( &temp_r, &temp_r ); bli_subsc( &temp_r, norm ); bli_getsc( norm, resid, &junk ); } blis-0.9.0/testsuite/src/test_normfm.h000066400000000000000000000035011422157504600200040ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void libblis_test_normfm ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); blis-0.9.0/testsuite/src/test_normfv.c000066400000000000000000000164431422157504600200210ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "test_libblis.h" // Static variables. static char* op_str = "normfv"; static char* o_types = "v"; // x static char* p_types = ""; // (no parameters) static thresh_t thresh[BLIS_NUM_FP_TYPES] = { { 1e-04, 1e-05 }, // warn, pass for s { 1e-04, 1e-05 }, // warn, pass for c { 1e-13, 1e-14 }, // warn, pass for d { 1e-13, 1e-14 } }; // warn, pass for z // Local prototypes. void libblis_test_normfv_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); void libblis_test_normfv_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ); void libblis_test_normfv_impl ( iface_t iface, obj_t* x, obj_t* norm ); void libblis_test_normfv_check ( test_params_t* params, obj_t* beta, obj_t* x, obj_t* norm, double* resid ); void libblis_test_normfv_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { libblis_test_setv( tdata, params, &(op->ops->setv) ); } void libblis_test_normfv ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { // Return early if this test has already been done. if ( libblis_test_op_is_done( op ) ) return; // Return early if operation is disabled. if ( libblis_test_op_is_disabled( op ) || libblis_test_l1v_is_disabled( op ) ) return; // Call dependencies first. if ( TRUE ) libblis_test_normfv_deps( tdata, params, op ); // Execute the test driver for each implementation requested. //if ( op->front_seq == ENABLE ) { libblis_test_op_driver( tdata, params, op, BLIS_TEST_SEQ_FRONT_END, op_str, p_types, o_types, thresh, libblis_test_normfv_experiment ); } } void libblis_test_normfv_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ) { unsigned int n_repeats = params->n_repeats; unsigned int i; double time_min = DBL_MAX; double time; num_t datatype; num_t dt_real; dim_t m; obj_t beta, norm; obj_t x; // Use the datatype of the first char in the datatype combination string. bli_param_map_char_to_blis_dt( dc_str[0], &datatype ); // Compute the real projection of the chosen datatype. dt_real = bli_dt_proj_to_real( datatype ); // Map the dimension specifier to an actual dimension. m = libblis_test_get_dim_from_prob_size( op->dim_spec[0], p_cur ); // Map parameter characters to BLIS constants. // Create test scalars. bli_obj_scalar_init_detached( datatype, &beta ); bli_obj_scalar_init_detached( dt_real, &norm ); // Create test operands (vectors and/or matrices). libblis_test_vobj_create( params, datatype, sc_str[0], m, &x ); // Initialize beta to 2 - 2i. bli_setsc( 2.0, -2.0, &beta ); // Set all elements of x to beta. bli_setv( &beta, &x ); // Repeat the experiment n_repeats times and record results. for ( i = 0; i < n_repeats; ++i ) { time = bli_clock(); libblis_test_normfv_impl( iface, &x, &norm ); time_min = bli_clock_min_diff( time_min, time ); } // Estimate the performance of the best experiment repeat. *perf = ( 2.0 * m ) / time_min / FLOPS_PER_UNIT_PERF; if ( bli_obj_is_complex( &x ) ) *perf *= 2.0; // Perform checks. libblis_test_normfv_check( params, &beta, &x, &norm, resid ); // Zero out performance and residual if input vector is empty. libblis_test_check_empty_problem( &x, perf, resid ); // Free the test objects. bli_obj_free( &x ); } void libblis_test_normfv_impl ( iface_t iface, obj_t* x, obj_t* norm ) { switch ( iface ) { case BLIS_TEST_SEQ_FRONT_END: bli_normfv( x, norm ); break; default: libblis_test_printf_error( "Invalid interface type.\n" ); } } void libblis_test_normfv_check ( test_params_t* params, obj_t* beta, obj_t* x, obj_t* norm, double* resid ) { num_t dt_real = bli_obj_dt_proj_to_real( x ); dim_t m = bli_obj_vector_dim( x ); obj_t m_r, temp_r; double junk; // // Pre-conditions: // - x is set to beta. // Note: // - beta should have a non-zero imaginary component in the complex // cases in order to more fully exercise the implementation. // // Under these conditions, we assume that the implementation for // // norm := normfv( x ) // // is functioning correctly if // // norm = sqrt( absqsc( beta ) * m ) // // where m is the length of x. // bli_obj_scalar_init_detached( dt_real, &temp_r ); bli_obj_scalar_init_detached( dt_real, &m_r ); bli_setsc( ( double )m, 0.0, &m_r ); bli_absqsc( beta, &temp_r ); bli_mulsc( &m_r, &temp_r ); bli_sqrtsc( &temp_r, &temp_r ); bli_subsc( &temp_r, norm ); bli_getsc( norm, resid, &junk ); } blis-0.9.0/testsuite/src/test_normfv.h000066400000000000000000000035011422157504600200150ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void libblis_test_normfv ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); blis-0.9.0/testsuite/src/test_randm.c000066400000000000000000000214571422157504600176140ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "test_libblis.h" // Static variables. static char* op_str = "randm"; static char* o_types = "m"; // a static char* p_types = ""; // (no parameters) static thresh_t thresh[BLIS_NUM_FP_TYPES] = { { 1e-04, 1e-05 }, // warn, pass for s { 1e-04, 1e-05 }, // warn, pass for c { 1e-13, 1e-14 }, // warn, pass for d { 1e-13, 1e-14 } }; // warn, pass for z // Local prototypes. void libblis_test_randm_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); void libblis_test_randm_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ); void libblis_test_randm_impl ( iface_t iface, obj_t* x ); void libblis_test_randm_check ( test_params_t* params, obj_t* x, double* resid ); void libblis_test_randm_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { // No dependencies. } void libblis_test_randm ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { // Return early if this test has already been done. if ( libblis_test_op_is_done( op ) ) return; // Return early if operation is disabled. if ( libblis_test_op_is_disabled( op ) || libblis_test_util_is_disabled( op ) ) return; // Call dependencies first. if ( TRUE ) libblis_test_randm_deps( tdata, params, op ); // Execute the test driver for each implementation requested. //if ( op->front_seq == ENABLE ) { libblis_test_op_driver( tdata, params, op, BLIS_TEST_SEQ_FRONT_END, op_str, p_types, o_types, thresh, libblis_test_randm_experiment ); } } void libblis_test_randm_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ) { unsigned int n_repeats = params->n_repeats; unsigned int i; double time_min = DBL_MAX; double time; num_t datatype; dim_t m, n; char x_store; obj_t x; // Use the datatype of the first char in the datatype combination string. bli_param_map_char_to_blis_dt( dc_str[0], &datatype ); // Map the dimension specifier to actual dimensions. m = libblis_test_get_dim_from_prob_size( op->dim_spec[0], p_cur ); n = libblis_test_get_dim_from_prob_size( op->dim_spec[1], p_cur ); // Map parameter characters to BLIS constants. // Extract the storage character for each operand. x_store = sc_str[0]; // Create the test objects. libblis_test_mobj_create( params, datatype, BLIS_NO_TRANSPOSE, x_store, m, n, &x ); // Repeat the experiment n_repeats times and record results. for ( i = 0; i < n_repeats; ++i ) { time = bli_clock(); libblis_test_randm_impl( iface, &x ); time_min = bli_clock_min_diff( time_min, time ); } // Estimate the performance of the best experiment repeat. *perf = ( 2.0 * m * n ) / time_min / FLOPS_PER_UNIT_PERF; if ( bli_obj_is_complex( &x ) ) *perf *= 2.0; // Perform checks. // For randm(), we don't return a meaningful residual/diff, since we can't // really say for sure what is "random" and what is not, so instead we // manually perform some checks that will fail under some scenarios whic // we consider to be likely. libblis_test_randm_check( params, &x, resid ); // Zero out performance and residual if input matrix is empty. libblis_test_check_empty_problem( &x, perf, resid ); // Free the test objects. bli_obj_free( &x ); } void libblis_test_randm_impl ( iface_t iface, obj_t* x ) { switch ( iface ) { case BLIS_TEST_SEQ_FRONT_END: bli_randm( x ); break; default: libblis_test_printf_error( "Invalid interface type.\n" ); } } void libblis_test_randm_check ( test_params_t* params, obj_t* x, double* resid ) { num_t dt_real = bli_obj_dt_proj_to_real( x ); dim_t m_x = bli_obj_length( x ); dim_t n_x = bli_obj_width( x ); obj_t sum; // // The two most likely ways that randm would fail is if all elements // were zero, or if all elements were greater than or equal to one. // We check both of these conditions by computing the sum of the // absolute values of the elements of x. // *resid = 0.0; bli_obj_scalar_init_detached( dt_real, &sum ); bli_absumm( x, &sum ); if ( bli_is_float( dt_real ) ) { float* sum_x = bli_obj_buffer_at_off( &sum ); if ( *sum_x == *bli_d0 ) *resid = 1.0; else if ( *sum_x >= 2.0 * m_x * n_x ) *resid = 2.0; } else // if ( bli_is_double( dt_real ) ) { double* sum_x = bli_obj_buffer_at_off( &sum ); if ( *sum_x == *bli_d0 ) *resid = 1.0; else if ( *sum_x >= 2.0 * m_x * n_x ) *resid = 2.0; } } #define FUNCPTR_T absumm_fp typedef void (*FUNCPTR_T)( dim_t m, dim_t n, void* x, inc_t rs_x, inc_t cs_x, void* sum_x ); static FUNCPTR_T GENARRAY(ftypes,absumm); void bli_absumm ( obj_t* x, obj_t* sum_x ) { num_t dt = bli_obj_dt( x ); dim_t m = bli_obj_length( x ); dim_t n = bli_obj_width( x ); void* buf_x = bli_obj_buffer_at_off( x ); inc_t rs_x = bli_obj_row_stride( x ); inc_t cs_x = bli_obj_col_stride( x ); void* buf_sum_x = bli_obj_buffer_at_off( sum_x ); FUNCPTR_T f; // Index into the type combination array to extract the correct // function pointer. f = ftypes[dt]; // Invoke the function. f( m, n, buf_x, rs_x, cs_x, buf_sum_x ); } #undef GENTFUNCR #define GENTFUNCR( ctype, ctype_r, ch, chr, varname ) \ \ void PASTEMAC(ch,varname)( \ dim_t m, \ dim_t n, \ void* x, inc_t rs_x, inc_t cs_x, \ void* sum_x \ ) \ { \ ctype* x_cast = x; \ ctype_r* sum_x_cast = sum_x; \ ctype_r abs_chi1; \ ctype_r sum; \ dim_t i, j; \ \ PASTEMAC(chr,set0s)( sum ); \ \ for ( j = 0; j < n; j++ ) \ { \ for ( i = 0; i < m; i++ ) \ { \ ctype* chi1 = x_cast + (i )*rs_x + (j )*cs_x; \ \ PASTEMAC2(ch,chr,abval2s)( *chi1, abs_chi1 ); \ PASTEMAC2(chr,chr,adds)( abs_chi1, sum ); \ } \ } \ \ PASTEMAC2(chr,chr,copys)( sum, *sum_x_cast ); \ } INSERT_GENTFUNCR_BASIC0( absumm ) blis-0.9.0/testsuite/src/test_randm.h000066400000000000000000000043461422157504600176170ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void libblis_test_randm ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); void bli_absumm ( obj_t* x, obj_t* sum_x ); #undef GENTPROTR #define GENTPROTR( ctype, ctype_r, ch, chr, varname ) \ \ void PASTEMAC(ch,varname)( \ dim_t m, \ dim_t n, \ void* x, inc_t rs_x, inc_t cs_x, \ void* sum_x \ ); INSERT_GENTPROTR_BASIC0( absumm ) blis-0.9.0/testsuite/src/test_randv.c000066400000000000000000000157511422157504600176250ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "test_libblis.h" // Static variables. static char* op_str = "randv"; static char* o_types = "v"; // x static char* p_types = ""; // (no parameters) static thresh_t thresh[BLIS_NUM_FP_TYPES] = { { 1e-04, 1e-05 }, // warn, pass for s { 1e-04, 1e-05 }, // warn, pass for c { 1e-13, 1e-14 }, // warn, pass for d { 1e-13, 1e-14 } }; // warn, pass for z // Local prototypes. void libblis_test_randv_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); void libblis_test_randv_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ); void libblis_test_randv_impl ( iface_t iface, obj_t* x ); void libblis_test_randv_check ( test_params_t* params, obj_t* x, double* resid ); void libblis_test_randv_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { // No dependencies. } void libblis_test_randv ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { // Return early if this test has already been done. if ( libblis_test_op_is_done( op ) ) return; // Return early if operation is disabled. if ( libblis_test_op_is_disabled( op ) || libblis_test_util_is_disabled( op ) ) return; // Call dependencies first. if ( TRUE ) libblis_test_randv_deps( tdata, params, op ); // Execute the test driver for each implementation requested. //if ( op->front_seq == ENABLE ) { libblis_test_op_driver( tdata, params, op, BLIS_TEST_SEQ_FRONT_END, op_str, p_types, o_types, thresh, libblis_test_randv_experiment ); } } void libblis_test_randv_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ) { unsigned int n_repeats = params->n_repeats; unsigned int i; double time_min = DBL_MAX; double time; num_t datatype; dim_t m; char x_store; obj_t x; // Use the datatype of the first char in the datatype combination string. bli_param_map_char_to_blis_dt( dc_str[0], &datatype ); // Map the dimension specifier to an actual dimension. m = libblis_test_get_dim_from_prob_size( op->dim_spec[0], p_cur ); // Map parameter characters to BLIS constants. // Extract the storage character for each operand. x_store = sc_str[0]; // Create the test objects. libblis_test_vobj_create( params, datatype, x_store, m, &x ); // Repeat the experiment n_repeats times and record results. for ( i = 0; i < n_repeats; ++i ) { time = bli_clock(); libblis_test_randv_impl( iface, &x ); time_min = bli_clock_min_diff( time_min, time ); } // Estimate the performance of the best experiment repeat. *perf = ( 2.0 * m ) / time_min / FLOPS_PER_UNIT_PERF; if ( bli_obj_is_complex( &x ) ) *perf *= 2.0; // Perform checks. // For randv(), we don't return a meaningful residual/diff, since we can't // really say for sure what is "random" and what is not, so instead we // manually perform some checks that will fail under some scenarios whic // we consider to be likely. libblis_test_randv_check( params, &x, resid ); // Zero out performance and residual if output vector is empty. libblis_test_check_empty_problem( &x, perf, resid ); // Free the test objects. bli_obj_free( &x ); } void libblis_test_randv_impl ( iface_t iface, obj_t* x ) { switch ( iface ) { case BLIS_TEST_SEQ_FRONT_END: bli_randv( x ); break; default: libblis_test_printf_error( "Invalid interface type.\n" ); } } void libblis_test_randv_check ( test_params_t* params, obj_t* x, double* resid ) { num_t dt_real = bli_obj_dt_proj_to_real( x ); dim_t m_x = bli_obj_vector_dim( x ); obj_t sum; *resid = 0.0; // // The two most likely ways that randv would fail is if all elements // were zero, or if all elements were greater than or equal to one. // We check both of these conditions by computing the sum of the // absolute values of the elements of x. // bli_obj_scalar_init_detached( dt_real, &sum ); bli_norm1v( x, &sum ); if ( bli_is_float( dt_real ) ) { float* sum_x = bli_obj_buffer_at_off( &sum ); if ( *sum_x == *bli_d0 ) *resid = 1.0; else if ( *sum_x >= 2.0 * m_x ) *resid = 2.0; } else // if ( bli_is_double( dt_real ) ) { double* sum_x = bli_obj_buffer_at_off( &sum ); if ( *sum_x == *bli_d0 ) *resid = 1.0; else if ( *sum_x >= 2.0 * m_x ) *resid = 2.0; } } blis-0.9.0/testsuite/src/test_randv.h000066400000000000000000000035001422157504600176170ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void libblis_test_randv ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); blis-0.9.0/testsuite/src/test_scal2m.c000066400000000000000000000203321422157504600176630ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "test_libblis.h" // Static variables. static char* op_str = "scal2m"; static char* o_types = "mm"; // x y static char* p_types = "h"; // conjx static thresh_t thresh[BLIS_NUM_FP_TYPES] = { { 1e-04, 1e-05 }, // warn, pass for s { 1e-04, 1e-05 }, // warn, pass for c { 1e-13, 1e-14 }, // warn, pass for d { 1e-13, 1e-14 } }; // warn, pass for z // Local prototypes. void libblis_test_scal2m_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); void libblis_test_scal2m_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ); void libblis_test_scal2m_impl ( iface_t iface, obj_t* alpha, obj_t* x, obj_t* y ); void libblis_test_scal2m_check ( test_params_t* params, obj_t* alpha, obj_t* x, obj_t* y, obj_t* y_save, double* resid ); void libblis_test_scal2m_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { libblis_test_randm( tdata, params, &(op->ops->randm) ); libblis_test_normfm( tdata, params, &(op->ops->normfm) ); libblis_test_subm( tdata, params, &(op->ops->subm) ); libblis_test_copym( tdata, params, &(op->ops->copym) ); libblis_test_scalm( tdata, params, &(op->ops->scalm) ); } void libblis_test_scal2m ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { // Return early if this test has already been done. if ( libblis_test_op_is_done( op ) ) return; // Return early if operation is disabled. if ( libblis_test_op_is_disabled( op ) || libblis_test_l1m_is_disabled( op ) ) return; // Call dependencies first. if ( TRUE ) libblis_test_scal2m_deps( tdata, params, op ); // Execute the test driver for each implementation requested. //if ( op->front_seq == ENABLE ) { libblis_test_op_driver( tdata, params, op, BLIS_TEST_SEQ_FRONT_END, op_str, p_types, o_types, thresh, libblis_test_scal2m_experiment ); } } void libblis_test_scal2m_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ) { unsigned int n_repeats = params->n_repeats; unsigned int i; double time_min = DBL_MAX; double time; num_t datatype; dim_t m, n; trans_t transx; obj_t alpha, x, y; obj_t y_save; // Use the datatype of the first char in the datatype combination string. bli_param_map_char_to_blis_dt( dc_str[0], &datatype ); // Map the dimension specifier to actual dimensions. m = libblis_test_get_dim_from_prob_size( op->dim_spec[0], p_cur ); n = libblis_test_get_dim_from_prob_size( op->dim_spec[1], p_cur ); // Map parameter characters to BLIS constants. bli_param_map_char_to_blis_trans( pc_str[0], &transx ); // Create test scalars. bli_obj_scalar_init_detached( datatype, &alpha ); // Create test operands (vectors and/or matrices). libblis_test_mobj_create( params, datatype, transx, sc_str[0], m, n, &x ); libblis_test_mobj_create( params, datatype, BLIS_NO_TRANSPOSE, sc_str[0], m, n, &y ); libblis_test_mobj_create( params, datatype, BLIS_NO_TRANSPOSE, sc_str[0], m, n, &y_save ); // Set alpha. if ( bli_obj_is_real( &y ) ) bli_setsc( -2.0, 0.0, &alpha ); else bli_setsc( 0.0, -2.0, &alpha ); // Randomize and save y. libblis_test_mobj_randomize( params, FALSE, &x ); bli_setm( &BLIS_ONE, &y ); bli_copym( &y, &y_save ); // Apply the parameters. bli_obj_set_conjtrans( transx, &x ); // Repeat the experiment n_repeats times and record results. for ( i = 0; i < n_repeats; ++i ) { bli_copym( &y_save, &y ); time = bli_clock(); libblis_test_scal2m_impl( iface, &alpha, &x, &y ); time_min = bli_clock_min_diff( time_min, time ); } // Estimate the performance of the best experiment repeat. *perf = ( 1.0 * m * n ) / time_min / FLOPS_PER_UNIT_PERF; if ( bli_obj_is_complex( &y ) ) *perf *= 4.0; // Perform checks. libblis_test_scal2m_check( params, &alpha, &x, &y, &y_save, resid ); // Zero out performance and residual if output matrix is empty. libblis_test_check_empty_problem( &y, perf, resid ); // Free the test objects. bli_obj_free( &x ); bli_obj_free( &y ); bli_obj_free( &y_save ); } void libblis_test_scal2m_impl ( iface_t iface, obj_t* alpha, obj_t* x, obj_t* y ) { switch ( iface ) { case BLIS_TEST_SEQ_FRONT_END: bli_scal2m( alpha, x, y ); break; default: libblis_test_printf_error( "Invalid interface type.\n" ); } } void libblis_test_scal2m_check ( test_params_t* params, obj_t* alpha, obj_t* x, obj_t* y, obj_t* y_orig, double* resid ) { num_t dt = bli_obj_dt( y ); num_t dt_real = bli_obj_dt_proj_to_real( y ); dim_t m = bli_obj_length( y ); dim_t n = bli_obj_width( y ); obj_t x_temp; obj_t norm; double junk; // // Pre-conditions: // - x is randomized. // - y_orig is set to one. // Note: // - alpha should have a non-zero imaginary component in the complex // cases in order to more fully exercise the implementation. // // Under these conditions, we assume that the implementation for // // y := alpha * conjx(x) // // is functioning correctly if // // normfm( y - alpha * conjx(x) ) // // is negligible. // bli_obj_scalar_init_detached( dt_real, &norm ); bli_obj_create( dt, m, n, 0, 0, &x_temp ); bli_copym( x, &x_temp ); bli_scalm( alpha, &x_temp ); bli_subm( &x_temp, y ); bli_normfm( y, &norm ); bli_getsc( &norm, resid, &junk ); bli_obj_free( &x_temp ); } blis-0.9.0/testsuite/src/test_scal2m.h000066400000000000000000000035011422157504600176670ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void libblis_test_scal2m ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); blis-0.9.0/testsuite/src/test_scal2v.c000066400000000000000000000201031422157504600176700ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "test_libblis.h" // Static variables. static char* op_str = "scal2v"; static char* o_types = "vv"; // x y static char* p_types = "c"; // conjx static thresh_t thresh[BLIS_NUM_FP_TYPES] = { { 1e-04, 1e-05 }, // warn, pass for s { 1e-04, 1e-05 }, // warn, pass for c { 1e-13, 1e-14 }, // warn, pass for d { 1e-13, 1e-14 } }; // warn, pass for z // Local prototypes. void libblis_test_scal2v_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); void libblis_test_scal2v_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ); void libblis_test_scal2v_impl ( iface_t iface, obj_t* alpha, obj_t* x, obj_t* y ); void libblis_test_scal2v_check ( test_params_t* params, obj_t* alpha, obj_t* x, obj_t* y, obj_t* y_orig, double* resid ); void libblis_test_scal2v_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { libblis_test_randv( tdata, params, &(op->ops->randv) ); libblis_test_normfv( tdata, params, &(op->ops->normfv) ); libblis_test_subv( tdata, params, &(op->ops->subv) ); libblis_test_copyv( tdata, params, &(op->ops->copyv) ); libblis_test_scalv( tdata, params, &(op->ops->scalv) ); } void libblis_test_scal2v ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { // Return early if this test has already been done. if ( libblis_test_op_is_done( op ) ) return; // Return early if operation is disabled. if ( libblis_test_op_is_disabled( op ) || libblis_test_l1v_is_disabled( op ) ) return; // Call dependencies first. if ( TRUE ) libblis_test_scal2v_deps( tdata, params, op ); // Execute the test driver for each implementation requested. //if ( op->front_seq == ENABLE ) { libblis_test_op_driver( tdata, params, op, BLIS_TEST_SEQ_FRONT_END, op_str, p_types, o_types, thresh, libblis_test_scal2v_experiment ); } } void libblis_test_scal2v_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ) { unsigned int n_repeats = params->n_repeats; unsigned int i; double time_min = DBL_MAX; double time; num_t datatype; dim_t m; conj_t conjx; obj_t alpha, x, y; obj_t y_save; // Use the datatype of the first char in the datatype combination string. bli_param_map_char_to_blis_dt( dc_str[0], &datatype ); // Map the dimension specifier to an actual dimension. m = libblis_test_get_dim_from_prob_size( op->dim_spec[0], p_cur ); // Map parameter characters to BLIS constants. bli_param_map_char_to_blis_conj( pc_str[0], &conjx ); // Create test scalars. bli_obj_scalar_init_detached( datatype, &alpha ); // Create test operands (vectors and/or matrices). libblis_test_vobj_create( params, datatype, sc_str[0], m, &x ); libblis_test_vobj_create( params, datatype, sc_str[1], m, &y ); libblis_test_vobj_create( params, datatype, sc_str[1], m, &y_save ); // Set alpha. //bli_setsc( sqrt(2.0)/2.0, sqrt(2.0)/2.0, &alpha ); //bli_copysc( &BLIS_TWO, &alpha ); if ( bli_obj_is_real( &y ) ) bli_setsc( -2.0, 0.0, &alpha ); else bli_setsc( 0.0, -2.0, &alpha ); // Randomize x and y, and save y. libblis_test_vobj_randomize( params, FALSE, &x ); libblis_test_vobj_randomize( params, FALSE, &y ); bli_copyv( &y, &y_save ); // Apply the parameters. bli_obj_set_conj( conjx, &x ); // Repeat the experiment n_repeats times and record results. for ( i = 0; i < n_repeats; ++i ) { bli_copyv( &y_save, &y ); time = bli_clock(); libblis_test_scal2v_impl( iface, &alpha, &x, &y ); time_min = bli_clock_min_diff( time_min, time ); } // Estimate the performance of the best experiment repeat. *perf = ( 1.0 * m ) / time_min / FLOPS_PER_UNIT_PERF; if ( bli_obj_is_complex( &y ) ) *perf *= 4.0; // Perform checks. libblis_test_scal2v_check( params, &alpha, &x, &y, &y_save, resid ); // Zero out performance and residual if output vector is empty. libblis_test_check_empty_problem( &y, perf, resid ); // Free the test objects. bli_obj_free( &x ); bli_obj_free( &y ); bli_obj_free( &y_save ); } void libblis_test_scal2v_impl ( iface_t iface, obj_t* alpha, obj_t* x, obj_t* y ) { switch ( iface ) { case BLIS_TEST_SEQ_FRONT_END: bli_scal2v( alpha, x, y ); break; default: libblis_test_printf_error( "Invalid interface type.\n" ); } } void libblis_test_scal2v_check ( test_params_t* params, obj_t* alpha, obj_t* x, obj_t* y, obj_t* y_orig, double* resid ) { num_t dt = bli_obj_dt( y ); num_t dt_real = bli_obj_dt_proj_to_real( y ); dim_t m = bli_obj_vector_dim( y ); obj_t x_temp; obj_t norm; double junk; // // Pre-conditions: // - x is randomized. // - y_orig is set to one. // Note: // - alpha should have a non-zero imaginary component in the complex // cases in order to more fully exercise the implementation. // // Under these conditions, we assume that the implementation for // // y := alpha * conjx(x) // // is functioning correctly if // // normfv( y - alpha * conjx(x) ) // // is negligible. // bli_obj_scalar_init_detached( dt_real, &norm ); bli_obj_create( dt, m, 1, 0, 0, &x_temp ); bli_copyv( x, &x_temp ); bli_scalv( alpha, &x_temp ); bli_subv( &x_temp, y ); bli_normfv( y, &norm ); bli_getsc( &norm, resid, &junk ); bli_obj_free( &x_temp ); } blis-0.9.0/testsuite/src/test_scal2v.h000066400000000000000000000035011422157504600177000ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void libblis_test_scal2v ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); blis-0.9.0/testsuite/src/test_scalm.c000066400000000000000000000177431422157504600176150ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "test_libblis.h" // Static variables. static char* op_str = "scalm"; static char* o_types = "m"; // x static char* p_types = "c"; // conjbeta static thresh_t thresh[BLIS_NUM_FP_TYPES] = { { 1e-04, 1e-05 }, // warn, pass for s { 1e-04, 1e-05 }, // warn, pass for c { 1e-13, 1e-14 }, // warn, pass for d { 1e-13, 1e-14 } }; // warn, pass for z // Local prototypes. void libblis_test_scalm_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); void libblis_test_scalm_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ); void libblis_test_scalm_impl ( iface_t iface, obj_t* beta, obj_t* y ); void libblis_test_scalm_check ( test_params_t* params, obj_t* beta, obj_t* y, obj_t* y_save, double* resid ); void libblis_test_scalm_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { libblis_test_randm( tdata, params, &(op->ops->randm) ); libblis_test_normfm( tdata, params, &(op->ops->normfm) ); libblis_test_copym( tdata, params, &(op->ops->copym) ); } void libblis_test_scalm ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { // Return early if this test has already been done. if ( libblis_test_op_is_done( op ) ) return; // Return early if operation is disabled. if ( libblis_test_op_is_disabled( op ) || libblis_test_l1m_is_disabled( op ) ) return; // Call dependencies first. if ( TRUE ) libblis_test_scalm_deps( tdata, params, op ); // Execute the test driver for each implementation requested. //if ( op->front_seq == ENABLE ) { libblis_test_op_driver( tdata, params, op, BLIS_TEST_SEQ_FRONT_END, op_str, p_types, o_types, thresh, libblis_test_scalm_experiment ); } } void libblis_test_scalm_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ) { unsigned int n_repeats = params->n_repeats; unsigned int i; double time_min = DBL_MAX; double time; num_t datatype; dim_t m, n; conj_t conjbeta; obj_t beta, y; obj_t y_save; // Use the datatype of the first char in the datatype combination string. bli_param_map_char_to_blis_dt( dc_str[0], &datatype ); // Map the dimension specifier to actual dimensions. m = libblis_test_get_dim_from_prob_size( op->dim_spec[0], p_cur ); n = libblis_test_get_dim_from_prob_size( op->dim_spec[1], p_cur ); // Map parameter characters to BLIS constants. bli_param_map_char_to_blis_conj( pc_str[0], &conjbeta ); // Create test scalars. bli_obj_scalar_init_detached( datatype, &beta ); // Create test operands (vectors and/or matrices). libblis_test_mobj_create( params, datatype, BLIS_NO_TRANSPOSE, sc_str[0], m, n, &y ); libblis_test_mobj_create( params, datatype, BLIS_NO_TRANSPOSE, sc_str[0], m, n, &y_save ); // Set beta to 0 + i. //bli_setsc( 0.0, 1.0, &beta ); if ( bli_obj_is_real( &y ) ) bli_setsc( -2.0, 0.0, &beta ); else bli_setsc( 0.0, -2.0, &beta ); // Randomize and save y. libblis_test_mobj_randomize( params, FALSE, &y ); bli_copym( &y, &y_save ); // Apply the parameters. bli_obj_set_conj( conjbeta, &beta ); // Repeat the experiment n_repeats times and record results. for ( i = 0; i < n_repeats; ++i ) { bli_copym( &y_save, &y ); time = bli_clock(); libblis_test_scalm_impl( iface, &beta, &y ); time_min = bli_clock_min_diff( time_min, time ); } // Estimate the performance of the best experiment repeat. *perf = ( 1.0 * m * n ) / time_min / FLOPS_PER_UNIT_PERF; if ( bli_obj_is_complex( &y ) ) *perf *= 6.0; // Perform checks. libblis_test_scalm_check( params, &beta, &y, &y_save, resid ); // Zero out performance and residual if output matrix is empty. libblis_test_check_empty_problem( &y, perf, resid ); // Free the test objects. bli_obj_free( &y ); bli_obj_free( &y_save ); } void libblis_test_scalm_impl ( iface_t iface, obj_t* beta, obj_t* y ) { switch ( iface ) { case BLIS_TEST_SEQ_FRONT_END: bli_scalm( beta, y ); break; default: libblis_test_printf_error( "Invalid interface type.\n" ); } } void libblis_test_scalm_check ( test_params_t* params, obj_t* beta, obj_t* y, obj_t* y_orig, double* resid ) { num_t dt = bli_obj_dt( y ); num_t dt_real = bli_obj_dt_proj_to_real( y ); dim_t m = bli_obj_length( y ); dim_t n = bli_obj_width( y ); obj_t norm_y_r; obj_t nbeta; obj_t y2; double junk; // // Pre-conditions: // - y_orig is randomized. // Note: // - beta should have a non-zero imaginary component in the complex // cases in order to more fully exercise the implementation. // // Under these conditions, we assume that the implementation for // // y := conjbeta(beta) * y_orig // // is functioning correctly if // // normfm( y + -conjbeta(beta) * y_orig ) // // is negligible. // bli_obj_create( dt, m, n, 0, 0, &y2 ); bli_copym( y_orig, &y2 ); bli_obj_scalar_init_detached( dt, &nbeta ); bli_obj_scalar_init_detached( dt_real, &norm_y_r ); bli_copysc( beta, &nbeta ); bli_mulsc( &BLIS_MINUS_ONE, &nbeta ); bli_scalm( &nbeta, &y2 ); bli_addm( &y2, y ); bli_normfm( y, &norm_y_r ); bli_getsc( &norm_y_r, resid, &junk ); bli_obj_free( &y2 ); } blis-0.9.0/testsuite/src/test_scalm.h000066400000000000000000000035001422157504600176040ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void libblis_test_scalm ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); blis-0.9.0/testsuite/src/test_scalv.c000066400000000000000000000174611422157504600176230ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "test_libblis.h" // Static variables. static char* op_str = "scalv"; static char* o_types = "v"; // y static char* p_types = "c"; // conjbeta static thresh_t thresh[BLIS_NUM_FP_TYPES] = { { 1e-04, 1e-05 }, // warn, pass for s { 1e-04, 1e-05 }, // warn, pass for c { 1e-13, 1e-14 }, // warn, pass for d { 1e-13, 1e-14 } }; // warn, pass for z // Local prototypes. void libblis_test_scalv_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); void libblis_test_scalv_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ); void libblis_test_scalv_impl ( iface_t iface, obj_t* beta, obj_t* y ); void libblis_test_scalv_check ( test_params_t* params, obj_t* beta, obj_t* y, obj_t* y_orig, double* resid ); void libblis_test_scalv_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { libblis_test_randv( tdata, params, &(op->ops->randv) ); libblis_test_normfv( tdata, params, &(op->ops->normfv) ); libblis_test_addv( tdata, params, &(op->ops->addv) ); libblis_test_copyv( tdata, params, &(op->ops->copyv) ); } void libblis_test_scalv ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { // Return early if this test has already been done. if ( libblis_test_op_is_done( op ) ) return; // Return early if operation is disabled. if ( libblis_test_op_is_disabled( op ) || libblis_test_l1v_is_disabled( op ) ) return; // Call dependencies first. if ( TRUE ) libblis_test_scalv_deps( tdata, params, op ); // Execute the test driver for each implementation requested. //if ( op->front_seq == ENABLE ) { libblis_test_op_driver( tdata, params, op, BLIS_TEST_SEQ_FRONT_END, op_str, p_types, o_types, thresh, libblis_test_scalv_experiment ); } } void libblis_test_scalv_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ) { unsigned int n_repeats = params->n_repeats; unsigned int i; double time_min = DBL_MAX; double time; num_t datatype; dim_t m; conj_t conjbeta; obj_t beta, y; obj_t y_save; // Use the datatype of the first char in the datatype combination string. bli_param_map_char_to_blis_dt( dc_str[0], &datatype ); // Map the dimension specifier to an actual dimension. m = libblis_test_get_dim_from_prob_size( op->dim_spec[0], p_cur ); // Map parameter characters to BLIS constants. bli_param_map_char_to_blis_conj( pc_str[0], &conjbeta ); // Create test scalars. bli_obj_scalar_init_detached( datatype, &beta ); // Create test operands (vectors and/or matrices). libblis_test_vobj_create( params, datatype, sc_str[0], m, &y ); libblis_test_vobj_create( params, datatype, sc_str[0], m, &y_save ); // Set beta. if ( bli_obj_is_real( &y ) ) bli_setsc( -2.0, 0.0, &beta ); else bli_setsc( 0.0, -2.0, &beta ); // Randomize and save y. libblis_test_vobj_randomize( params, FALSE, &y ); bli_copyv( &y, &y_save ); // Apply the parameters. bli_obj_set_conj( conjbeta, &beta ); // Repeat the experiment n_repeats times and record results. for ( i = 0; i < n_repeats; ++i ) { bli_copyv( &y_save, &y ); time = bli_clock(); libblis_test_scalv_impl( iface, &beta, &y ); time_min = bli_clock_min_diff( time_min, time ); } // Estimate the performance of the best experiment repeat. *perf = ( 1.0 * m ) / time_min / FLOPS_PER_UNIT_PERF; if ( bli_obj_is_complex( &y ) ) *perf *= 6.0; // Perform checks. libblis_test_scalv_check( params, &beta, &y, &y_save, resid ); // Zero out performance and residual if output vector is empty. libblis_test_check_empty_problem( &y, perf, resid ); // Free the test objects. bli_obj_free( &y ); bli_obj_free( &y_save ); } void libblis_test_scalv_impl ( iface_t iface, obj_t* beta, obj_t* y ) { switch ( iface ) { case BLIS_TEST_SEQ_FRONT_END: bli_scalv( beta, y ); break; default: libblis_test_printf_error( "Invalid interface type.\n" ); } } void libblis_test_scalv_check ( test_params_t* params, obj_t* beta, obj_t* y, obj_t* y_orig, double* resid ) { num_t dt = bli_obj_dt( y ); num_t dt_real = bli_obj_dt_proj_to_real( y ); dim_t m = bli_obj_vector_dim( y ); obj_t norm_y_r; obj_t nbeta; obj_t y2; double junk; // // Pre-conditions: // - y_orig is randomized. // Note: // - beta should have a non-zero imaginary component in the complex // cases in order to more fully exercise the implementation. // // Under these conditions, we assume that the implementation for // // y := conjbeta(beta) * y_orig // // is functioning correctly if // // normfv( y + -conjbeta(beta) * y_orig ) // // is negligible. // bli_obj_create( dt, m, 1, 0, 0, &y2 ); bli_copyv( y_orig, &y2 ); bli_obj_scalar_init_detached( dt, &nbeta ); bli_obj_scalar_init_detached( dt_real, &norm_y_r ); bli_copysc( beta, &nbeta ); bli_mulsc( &BLIS_MINUS_ONE, &nbeta ); bli_scalv( &nbeta, &y2 ); bli_addv( &y2, y ); bli_normfv( y, &norm_y_r ); bli_getsc( &norm_y_r, resid, &junk ); bli_obj_free( &y2 ); } blis-0.9.0/testsuite/src/test_scalv.h000066400000000000000000000035001422157504600176150ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void libblis_test_scalv ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); blis-0.9.0/testsuite/src/test_setm.c000066400000000000000000000200551422157504600174540ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "test_libblis.h" // Static variables. static char* op_str = "setm"; static char* o_types = "m"; // x static char* p_types = ""; // (no parameters) static thresh_t thresh[BLIS_NUM_FP_TYPES] = { { 1e-04, 1e-05 }, // warn, pass for s { 1e-04, 1e-05 }, // warn, pass for c { 1e-13, 1e-14 }, // warn, pass for d { 1e-13, 1e-14 } }; // warn, pass for z // Local prototypes. void libblis_test_setm_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); void libblis_test_setm_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ); void libblis_test_setm_impl ( iface_t iface, obj_t* beta, obj_t* x ); void libblis_test_setm_check ( test_params_t* params, obj_t* beta, obj_t* x, double* resid ); void libblis_test_setm_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { libblis_test_randv( tdata, params, &(op->ops->randm) ); } void libblis_test_setm ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { // Return early if this test has already been done. if ( libblis_test_op_is_done( op ) ) return; // Return early if operation is disabled. if ( libblis_test_op_is_disabled( op ) || libblis_test_l1m_is_disabled( op ) ) return; // Call dependencies first. if ( TRUE ) libblis_test_setm_deps( tdata, params, op ); // Execute the test driver for each implementation requested. //if ( op->front_seq == ENABLE ) { libblis_test_op_driver( tdata, params, op, BLIS_TEST_SEQ_FRONT_END, op_str, p_types, o_types, thresh, libblis_test_setm_experiment ); } } void libblis_test_setm_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ) { unsigned int n_repeats = params->n_repeats; unsigned int i; double time_min = DBL_MAX; double time; num_t datatype; dim_t m, n; obj_t beta; obj_t x; // Use the datatype of the first char in the datatype combination string. bli_param_map_char_to_blis_dt( dc_str[0], &datatype ); // Map the dimension specifier to actual dimensions. m = libblis_test_get_dim_from_prob_size( op->dim_spec[0], p_cur ); n = libblis_test_get_dim_from_prob_size( op->dim_spec[1], p_cur ); // Map parameter characters to BLIS constants. // Create test scalars. bli_obj_scalar_init_detached( datatype, &beta ); // Create test operands (vectors and/or matrices). libblis_test_mobj_create( params, datatype, BLIS_NO_TRANSPOSE, sc_str[0], m, n, &x ); // Initialize beta to unit. bli_copysc( &BLIS_ONE, &beta ); // Randomize x. libblis_test_mobj_randomize( params, FALSE, &x ); // Repeat the experiment n_repeats times and record results. for ( i = 0; i < n_repeats; ++i ) { time = bli_clock(); libblis_test_setm_impl( iface, &beta, &x ); time_min = bli_clock_min_diff( time_min, time ); } // Estimate the performance of the best experiment repeat. *perf = ( 1.0 * m * n ) / time_min / FLOPS_PER_UNIT_PERF; if ( bli_obj_is_complex( &x ) ) *perf *= 2.0; // Perform checks. libblis_test_setm_check( params, &beta, &x, resid ); // Zero out performance and residual if output matrix is empty. libblis_test_check_empty_problem( &x, perf, resid ); // Free the test objects. bli_obj_free( &x ); } void libblis_test_setm_impl ( iface_t iface, obj_t* beta, obj_t* x ) { switch ( iface ) { case BLIS_TEST_SEQ_FRONT_END: bli_setm( beta, x ); break; default: libblis_test_printf_error( "Invalid interface type.\n" ); } } void libblis_test_setm_check ( test_params_t* params, obj_t* beta, obj_t* x, double* resid ) { num_t dt_x = bli_obj_dt( x ); dim_t m_x = bli_obj_length( x ); dim_t n_x = bli_obj_width( x ); inc_t rs_x = bli_obj_row_stride( x ); inc_t cs_x = bli_obj_col_stride( x ); void* buf_x = bli_obj_buffer_at_off( x ); void* buf_beta = bli_obj_buffer_for_1x1( dt_x, beta ); dim_t i, j; *resid = 0.0; // // The easiest way to check that setm was successful is to confirm // that each element of x is equal to beta. // if ( bli_obj_is_float( x ) ) { float* beta_cast = buf_beta; float* buf_x_cast = buf_x; float* chi1; for ( j = 0; j < n_x; ++j ) { for ( i = 0; i < m_x; ++i ) { chi1 = buf_x_cast + (i )*rs_x + (j )*cs_x; if ( !bli_seq( *chi1, *beta_cast ) ) { *resid = 1.0; return; } } } } else if ( bli_obj_is_double( x ) ) { double* beta_cast = buf_beta; double* buf_x_cast = buf_x; double* chi1; for ( j = 0; j < n_x; ++j ) { for ( i = 0; i < m_x; ++i ) { chi1 = buf_x_cast + (i )*rs_x + (j )*cs_x; if ( !bli_deq( *chi1, *beta_cast ) ) { *resid = 1.0; return; } } } } else if ( bli_obj_is_scomplex( x ) ) { scomplex* beta_cast = buf_beta; scomplex* buf_x_cast = buf_x; scomplex* chi1; for ( j = 0; j < n_x; ++j ) { for ( i = 0; i < m_x; ++i ) { chi1 = buf_x_cast + (i )*rs_x + (j )*cs_x; if ( !bli_ceq( *chi1, *beta_cast ) ) { *resid = 1.0; return; } } } } else // if ( bli_obj_is_dcomplex( x ) ) { dcomplex* beta_cast = buf_beta; dcomplex* buf_x_cast = buf_x; dcomplex* chi1; for ( j = 0; j < n_x; ++j ) { for ( i = 0; i < m_x; ++i ) { chi1 = buf_x_cast + (i )*rs_x + (j )*cs_x; if ( !bli_zeq( *chi1, *beta_cast ) ) { *resid = 1.0; return; } } } } } blis-0.9.0/testsuite/src/test_setm.h000066400000000000000000000034771422157504600174720ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void libblis_test_setm ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); blis-0.9.0/testsuite/src/test_setv.c000066400000000000000000000167731422157504600175010ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "test_libblis.h" // Static variables. static char* op_str = "setv"; static char* o_types = "v"; // x static char* p_types = ""; // (no parameters) static thresh_t thresh[BLIS_NUM_FP_TYPES] = { { 1e-04, 1e-05 }, // warn, pass for s { 1e-04, 1e-05 }, // warn, pass for c { 1e-13, 1e-14 }, // warn, pass for d { 1e-13, 1e-14 } }; // warn, pass for z // Local prototypes. void libblis_test_setv_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); void libblis_test_setv_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ); void libblis_test_setv_impl ( iface_t iface, obj_t* beta, obj_t* x ); void libblis_test_setv_check ( test_params_t* params, obj_t* beta, obj_t* x, double* resid ); void libblis_test_setv_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { libblis_test_randv( tdata, params, &(op->ops->randv) ); } void libblis_test_setv ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { // Return early if this test has already been done. if ( libblis_test_op_is_done( op ) ) return; // Return early if operation is disabled. if ( libblis_test_op_is_disabled( op ) || libblis_test_l1v_is_disabled( op ) ) return; // Call dependencies first. if ( TRUE ) libblis_test_setv_deps( tdata, params, op ); // Execute the test driver for each implementation requested. //if ( op->front_seq == ENABLE ) { libblis_test_op_driver( tdata, params, op, BLIS_TEST_SEQ_FRONT_END, op_str, p_types, o_types, thresh, libblis_test_setv_experiment ); } } void libblis_test_setv_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ) { unsigned int n_repeats = params->n_repeats; unsigned int i; double time_min = DBL_MAX; double time; num_t datatype; dim_t m; obj_t beta; obj_t x; // Use the datatype of the first char in the datatype combination string. bli_param_map_char_to_blis_dt( dc_str[0], &datatype ); // Map the dimension specifier to an actual dimension. m = libblis_test_get_dim_from_prob_size( op->dim_spec[0], p_cur ); // Map parameter characters to BLIS constants. // Create test scalars. bli_obj_scalar_init_detached( datatype, &beta ); // Create test operands (vectors and/or matrices). libblis_test_vobj_create( params, datatype, sc_str[0], m, &x ); // Initialize beta to unit. bli_copysc( &BLIS_ONE, &beta ); // Randomize x. libblis_test_vobj_randomize( params, FALSE, &x ); // Repeat the experiment n_repeats times and record results. for ( i = 0; i < n_repeats; ++i ) { time = bli_clock(); libblis_test_setv_impl( iface, &beta, &x ); time_min = bli_clock_min_diff( time_min, time ); } // Estimate the performance of the best experiment repeat. *perf = ( 1.0 * m ) / time_min / FLOPS_PER_UNIT_PERF; if ( bli_obj_is_complex( &x ) ) *perf *= 2.0; // Perform checks. libblis_test_setv_check( params, &beta, &x, resid ); // Zero out performance and residual if output vector is empty. libblis_test_check_empty_problem( &x, perf, resid ); // Free the test objects. bli_obj_free( &x ); } void libblis_test_setv_impl ( iface_t iface, obj_t* beta, obj_t* x ) { switch ( iface ) { case BLIS_TEST_SEQ_FRONT_END: bli_setv( beta, x ); break; default: libblis_test_printf_error( "Invalid interface type.\n" ); } } void libblis_test_setv_check ( test_params_t* params, obj_t* beta, obj_t* x, double* resid ) { num_t dt_x = bli_obj_dt( x ); dim_t m_x = bli_obj_vector_dim( x ); inc_t inc_x = bli_obj_vector_inc( x ); void* buf_x = bli_obj_buffer_at_off( x ); void* buf_beta = bli_obj_buffer_for_1x1( dt_x, beta ); dim_t i; *resid = 0.0; // // The easiest way to check that setv was successful is to confirm // that each element of x is equal to beta. // if ( bli_obj_is_float( x ) ) { float* chi1 = buf_x; float* beta_cast = buf_beta; for ( i = 0; i < m_x; ++i ) { if ( !bli_seq( *chi1, *beta_cast ) ) { *resid = 1.0; return; } chi1 += inc_x; } } else if ( bli_obj_is_double( x ) ) { double* chi1 = buf_x; double* beta_cast = buf_beta; for ( i = 0; i < m_x; ++i ) { if ( !bli_deq( *chi1, *beta_cast ) ) { *resid = 1.0; return; } chi1 += inc_x; } } else if ( bli_obj_is_scomplex( x ) ) { scomplex* chi1 = buf_x; scomplex* beta_cast = buf_beta; for ( i = 0; i < m_x; ++i ) { if ( !bli_ceq( *chi1, *beta_cast ) ) { *resid = 1.0; return; } chi1 += inc_x; } } else // if ( bli_obj_is_dcomplex( x ) ) { dcomplex* chi1 = buf_x; dcomplex* beta_cast = buf_beta; for ( i = 0; i < m_x; ++i ) { if ( !bli_zeq( *chi1, *beta_cast ) ) { *resid = 1.0; return; } chi1 += inc_x; } } } blis-0.9.0/testsuite/src/test_setv.h000066400000000000000000000034771422157504600175030ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void libblis_test_setv ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); blis-0.9.0/testsuite/src/test_subm.c000066400000000000000000000203071422157504600174520ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "test_libblis.h" // Static variables. static char* op_str = "subm"; static char* o_types = "mm"; // x y static char* p_types = "h"; // transx static thresh_t thresh[BLIS_NUM_FP_TYPES] = { { 1e-04, 1e-05 }, // warn, pass for s { 1e-04, 1e-05 }, // warn, pass for c { 1e-13, 1e-14 }, // warn, pass for d { 1e-13, 1e-14 } }; // warn, pass for z // Local prototypes. void libblis_test_subm_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); void libblis_test_subm_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ); void libblis_test_subm_impl ( iface_t iface, obj_t* x, obj_t* y ); void libblis_test_subm_check ( test_params_t* params, obj_t* alpha, obj_t* beta, obj_t* x, obj_t* y, double* resid ); void libblis_test_subm_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { libblis_test_setm( tdata, params, &(op->ops->setm) ); libblis_test_normfm( tdata, params, &(op->ops->normfm) ); } void libblis_test_subm ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { // Return early if this test has already been done. if ( libblis_test_op_is_done( op ) ) return; // Return early if operation is disabled. if ( libblis_test_op_is_disabled( op ) || libblis_test_l1m_is_disabled( op ) ) return; // Call dependencies first. if ( TRUE ) libblis_test_subm_deps( tdata, params, op ); // Execute the test driver for each implementation requested. //if ( op->front_seq == ENABLE ) { libblis_test_op_driver( tdata, params, op, BLIS_TEST_SEQ_FRONT_END, op_str, p_types, o_types, thresh, libblis_test_subm_experiment ); } } void libblis_test_subm_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ) { double time_min = DBL_MAX; double time; num_t datatype; dim_t m, n; trans_t transx; obj_t alpha, beta; obj_t x, y; // Use the datatype of the first char in the datatype combination string. bli_param_map_char_to_blis_dt( dc_str[0], &datatype ); // Map the dimension specifier to actual dimensions. m = libblis_test_get_dim_from_prob_size( op->dim_spec[0], p_cur ); n = libblis_test_get_dim_from_prob_size( op->dim_spec[1], p_cur ); // Map parameter characters to BLIS constants. bli_param_map_char_to_blis_trans( pc_str[0], &transx ); // Create test scalars. bli_obj_scalar_init_detached( datatype, &alpha ); bli_obj_scalar_init_detached( datatype, &beta ); // Create test operands (vectors and/or matrices). libblis_test_mobj_create( params, datatype, transx, sc_str[0], m, n, &x ); libblis_test_mobj_create( params, datatype, BLIS_NO_TRANSPOSE, sc_str[1], m, n, &y ); // Initialize alpha and beta. bli_setsc( 1.0, 1.0, &alpha ); bli_setsc( 3.0, 3.0, &beta ); // Randomize x. bli_setm( &alpha, &x ); bli_setm( &beta, &y ); // Apply the parameters. bli_obj_set_conjtrans( transx, &x ); // Disable repeats since bli_copym() is not yet tested. //for ( i = 0; i < n_repeats; ++i ) { time = bli_clock(); libblis_test_subm_impl( iface, &x, &y ); time_min = bli_clock_min_diff( time_min, time ); } // Estimate the performance of the best experiment repeat. *perf = ( 1.0 * m * n ) / time_min / FLOPS_PER_UNIT_PERF; if ( bli_obj_is_complex( &x ) ) *perf *= 2.0; // Perform checks. libblis_test_subm_check( params, &alpha, &beta, &x, &y, resid ); // Zero out performance and residual if output matrix is empty. libblis_test_check_empty_problem( &y, perf, resid ); // Free the test objects. bli_obj_free( &x ); bli_obj_free( &y ); } void libblis_test_subm_impl ( iface_t iface, obj_t* x, obj_t* y ) { switch ( iface ) { case BLIS_TEST_SEQ_FRONT_END: bli_subm( x, y ); break; default: libblis_test_printf_error( "Invalid interface type.\n" ); } } void libblis_test_subm_check ( test_params_t* params, obj_t* alpha, obj_t* beta, obj_t* x, obj_t* y, double* resid ) { num_t dt = bli_obj_dt( y ); num_t dt_real = bli_obj_dt_proj_to_real( y ); dim_t m = bli_obj_length( y ); dim_t n = bli_obj_width( y ); conj_t conjx = bli_obj_conj_status( x ); obj_t aminusb; obj_t alpha_conj; obj_t norm_r, m_r, n_r, temp_r; double junk; // // Pre-conditions: // - x is set to alpha. // - y_orig is set to beta. // Note: // - alpha and beta should have non-zero imaginary components in the // complex cases in order to more fully exercise the implementation. // // Under these conditions, we assume that the implementation for // // y := y_orig - conjx(x) // // is functioning correctly if // // normfm(y) - sqrt( absqsc( beta - conjx(alpha) ) * m * n ) // // is negligible. // bli_obj_scalar_init_detached( dt, &aminusb ); bli_obj_scalar_init_detached( dt_real, &temp_r ); bli_obj_scalar_init_detached( dt_real, &norm_r ); bli_obj_scalar_init_detached( dt_real, &m_r ); bli_obj_scalar_init_detached( dt_real, &n_r ); bli_obj_scalar_init_detached_copy_of( dt, conjx, alpha, &alpha_conj ); bli_normfm( y, &norm_r ); bli_copysc( beta, &aminusb ); bli_subsc( &alpha_conj, &aminusb ); bli_setsc( ( double )m, 0.0, &m_r ); bli_setsc( ( double )n, 0.0, &n_r ); bli_absqsc( &aminusb, &temp_r ); bli_mulsc( &m_r, &temp_r ); bli_mulsc( &n_r, &temp_r ); bli_sqrtsc( &temp_r, &temp_r ); bli_subsc( &temp_r, &norm_r ); bli_getsc( &norm_r, resid, &junk ); } blis-0.9.0/testsuite/src/test_subm.h000066400000000000000000000034771422157504600174700ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void libblis_test_subm ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); blis-0.9.0/testsuite/src/test_subv.c000066400000000000000000000176341422157504600174740ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "test_libblis.h" // Static variables. static char* op_str = "subv"; static char* o_types = "vv"; // x y static char* p_types = "c"; // conjx static thresh_t thresh[BLIS_NUM_FP_TYPES] = { { 1e-04, 1e-05 }, // warn, pass for s { 1e-04, 1e-05 }, // warn, pass for c { 1e-13, 1e-14 }, // warn, pass for d { 1e-13, 1e-14 } }; // warn, pass for z // Local prototypes. void libblis_test_subv_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); void libblis_test_subv_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ); void libblis_test_subv_impl ( iface_t iface, obj_t* x, obj_t* y ); void libblis_test_subv_check ( test_params_t* params, obj_t* alpha, obj_t* beta, obj_t* x, obj_t* y, double* resid ); void libblis_test_subv_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { libblis_test_setv( tdata, params, &(op->ops->setv) ); libblis_test_normfv( tdata, params, &(op->ops->normfv) ); } void libblis_test_subv ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { // Return early if this test has already been done. if ( libblis_test_op_is_done( op ) ) return; // Return early if operation is disabled. if ( libblis_test_op_is_disabled( op ) || libblis_test_l1v_is_disabled( op ) ) return; // Call dependencies first. if ( TRUE ) libblis_test_subv_deps( tdata, params, op ); // Execute the test driver for each implementation requested. //if ( op->front_seq == ENABLE ) { libblis_test_op_driver( tdata, params, op, BLIS_TEST_SEQ_FRONT_END, op_str, p_types, o_types, thresh, libblis_test_subv_experiment ); } } void libblis_test_subv_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ) { double time_min = DBL_MAX; double time; num_t datatype; dim_t m; conj_t conjx; obj_t alpha, beta; obj_t x, y; // Use the datatype of the first char in the datatype combination string. bli_param_map_char_to_blis_dt( dc_str[0], &datatype ); // Map the dimension specifier to an actual dimension. m = libblis_test_get_dim_from_prob_size( op->dim_spec[0], p_cur ); // Map parameter characters to BLIS constants. bli_param_map_char_to_blis_conj( pc_str[0], &conjx ); // Create test scalars. bli_obj_scalar_init_detached( datatype, &alpha ); bli_obj_scalar_init_detached( datatype, &beta ); // Create test operands (vectors and/or matrices). libblis_test_vobj_create( params, datatype, sc_str[0], m, &x ); libblis_test_vobj_create( params, datatype, sc_str[1], m, &y ); // Initialize alpha and beta. bli_setsc( 1.0, 1.0, &alpha ); bli_setsc( 3.0, 3.0, &beta ); // Set x and y to alpha and beta, respectively. bli_setv( &alpha, &x ); bli_setv( &beta, &y ); // Apply the parameters. bli_obj_set_conj( conjx, &x ); // Disable repeats since bli_copyv() is not yet tested. //for ( i = 0; i < n_repeats; ++i ) { time = bli_clock(); libblis_test_subv_impl( iface, &x, &y ); time_min = bli_clock_min_diff( time_min, time ); } // Estimate the performance of the best experiment repeat. *perf = ( 1.0 * m ) / time_min / FLOPS_PER_UNIT_PERF; if ( bli_obj_is_complex( &x ) ) *perf *= 2.0; // Perform checks. libblis_test_subv_check( params, &alpha, &beta, &x, &y, resid ); // Zero out performance and residual if output vector is empty. libblis_test_check_empty_problem( &y, perf, resid ); // Free the test objects. bli_obj_free( &x ); bli_obj_free( &y ); } void libblis_test_subv_impl ( iface_t iface, obj_t* x, obj_t* y ) { switch ( iface ) { case BLIS_TEST_SEQ_FRONT_END: bli_subv( x, y ); break; default: libblis_test_printf_error( "Invalid interface type.\n" ); } } void libblis_test_subv_check ( test_params_t* params, obj_t* alpha, obj_t* beta, obj_t* x, obj_t* y, double* resid ) { num_t dt = bli_obj_dt( x ); num_t dt_real = bli_obj_dt_proj_to_real( x ); dim_t m = bli_obj_vector_dim( x ); conj_t conjx = bli_obj_conj_status( x ); obj_t aminusb; obj_t alpha_conj; obj_t norm_r, m_r, temp_r; double junk; // // Pre-conditions: // - x is set to alpha. // - y_orig is set to beta. // Note: // - alpha and beta should have non-zero imaginary components in the // complex cases in order to more fully exercise the implementation. // // Under these conditions, we assume that the implementation for // // y := y_orig - conjx(x) // // is functioning correctly if // // normfv(y) - sqrt( absqsc( beta - conjx(alpha) ) * m ) // // is negligible. // bli_obj_scalar_init_detached( dt, &aminusb ); bli_obj_scalar_init_detached( dt_real, &temp_r ); bli_obj_scalar_init_detached( dt_real, &norm_r ); bli_obj_scalar_init_detached( dt_real, &m_r ); bli_obj_scalar_init_detached_copy_of( dt, conjx, alpha, &alpha_conj ); bli_normfv( y, &norm_r ); bli_copysc( beta, &aminusb ); bli_subsc( &alpha_conj, &aminusb ); bli_setsc( ( double )m, 0.0, &m_r ); bli_absqsc( &aminusb, &temp_r ); bli_mulsc( &m_r, &temp_r ); bli_sqrtsc( &temp_r, &temp_r ); bli_subsc( &temp_r, &norm_r ); bli_getsc( &norm_r, resid, &junk ); } blis-0.9.0/testsuite/src/test_subv.h000066400000000000000000000034771422157504600175010ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void libblis_test_subv ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); blis-0.9.0/testsuite/src/test_symm.c000066400000000000000000000262601422157504600174750ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "test_libblis.h" // Static variables. static char* op_str = "symm"; static char* o_types = "mmm"; // a b c static char* p_types = "such"; // side uploa conja transb static thresh_t thresh[BLIS_NUM_FP_TYPES] = { { 1e-04, 1e-05 }, // warn, pass for s { 1e-04, 1e-05 }, // warn, pass for c { 1e-13, 1e-14 }, // warn, pass for d { 1e-13, 1e-14 } }; // warn, pass for z // Local prototypes. void libblis_test_symm_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); void libblis_test_symm_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ); void libblis_test_symm_impl ( iface_t iface, side_t side, obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c ); void libblis_test_symm_check ( test_params_t* params, side_t side, obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, obj_t* c_orig, double* resid ); void libblis_test_symm_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { libblis_test_randv( tdata, params, &(op->ops->randv) ); libblis_test_randm( tdata, params, &(op->ops->randm) ); libblis_test_setv( tdata, params, &(op->ops->setv) ); libblis_test_normfv( tdata, params, &(op->ops->normfv) ); libblis_test_subv( tdata, params, &(op->ops->subv) ); libblis_test_scalv( tdata, params, &(op->ops->scalv) ); libblis_test_copym( tdata, params, &(op->ops->copym) ); libblis_test_scalm( tdata, params, &(op->ops->scalm) ); libblis_test_gemv( tdata, params, &(op->ops->gemv) ); libblis_test_symv( tdata, params, &(op->ops->symv) ); } void libblis_test_symm ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { // Return early if this test has already been done. if ( libblis_test_op_is_done( op ) ) return; // Return early if operation is disabled. if ( libblis_test_op_is_disabled( op ) || libblis_test_l3_is_disabled( op ) ) return; // Call dependencies first. if ( TRUE ) libblis_test_symm_deps( tdata, params, op ); // Execute the test driver for each implementation requested. //if ( op->front_seq == ENABLE ) { libblis_test_op_driver( tdata, params, op, BLIS_TEST_SEQ_FRONT_END, op_str, p_types, o_types, thresh, libblis_test_symm_experiment ); } } void libblis_test_symm_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ) { unsigned int n_repeats = params->n_repeats; unsigned int i; double time_min = DBL_MAX; double time; num_t datatype; dim_t m, n; dim_t mn_side; side_t side; uplo_t uploa; conj_t conja; trans_t transb; obj_t alpha, a, b, beta, c; obj_t c_save; // Use the datatype of the first char in the datatype combination string. bli_param_map_char_to_blis_dt( dc_str[0], &datatype ); // Map the dimension specifier to actual dimensions. m = libblis_test_get_dim_from_prob_size( op->dim_spec[0], p_cur ); n = libblis_test_get_dim_from_prob_size( op->dim_spec[1], p_cur ); // Map parameter characters to BLIS constants. bli_param_map_char_to_blis_side( pc_str[0], &side ); bli_param_map_char_to_blis_uplo( pc_str[1], &uploa ); bli_param_map_char_to_blis_conj( pc_str[2], &conja ); bli_param_map_char_to_blis_trans( pc_str[3], &transb ); // Create test scalars. bli_obj_scalar_init_detached( datatype, &alpha ); bli_obj_scalar_init_detached( datatype, &beta ); // Create test operands (vectors and/or matrices). bli_set_dim_with_side( side, m, n, &mn_side ); libblis_test_mobj_create( params, datatype, BLIS_NO_TRANSPOSE, sc_str[1], mn_side, mn_side, &a ); libblis_test_mobj_create( params, datatype, transb, sc_str[2], m, n, &b ); libblis_test_mobj_create( params, datatype, BLIS_NO_TRANSPOSE, sc_str[0], m, n, &c ); libblis_test_mobj_create( params, datatype, BLIS_NO_TRANSPOSE, sc_str[0], m, n, &c_save ); // Set alpha and beta. if ( bli_obj_is_real( &c ) ) { bli_setsc( 0.8, 0.0, &alpha ); bli_setsc( -1.0, 0.0, &beta ); } else { bli_setsc( 0.8, 0.6, &alpha ); bli_setsc( -1.0, 1.0, &beta ); } // Set the structure and uplo properties of A. bli_obj_set_struc( BLIS_SYMMETRIC, &a ); bli_obj_set_uplo( uploa, &a ); // Randomize A, make it densely symmetric, and zero the unstored triangle // to ensure the implementation reads only from the stored region. libblis_test_mobj_randomize( params, TRUE, &a ); bli_mksymm( &a ); bli_mktrim( &a ); // Randomize B and C, and save C. libblis_test_mobj_randomize( params, TRUE, &b ); libblis_test_mobj_randomize( params, TRUE, &c ); bli_copym( &c, &c_save ); // Apply the remaining parameters. bli_obj_set_conj( conja, &a ); bli_obj_set_conjtrans( transb, &b ); // Repeat the experiment n_repeats times and record results. for ( i = 0; i < n_repeats; ++i ) { bli_copym( &c_save, &c ); time = bli_clock(); libblis_test_symm_impl( iface, side, &alpha, &a, &b, &beta, &c ); time_min = bli_clock_min_diff( time_min, time ); } // Estimate the performance of the best experiment repeat. *perf = ( 2.0 * mn_side * m * n ) / time_min / FLOPS_PER_UNIT_PERF; if ( bli_obj_is_complex( &c ) ) *perf *= 4.0; // Perform checks. libblis_test_symm_check( params, side, &alpha, &a, &b, &beta, &c, &c_save, resid ); // Zero out performance and residual if output matrix is empty. libblis_test_check_empty_problem( &c, perf, resid ); // Free the test objects. bli_obj_free( &a ); bli_obj_free( &b ); bli_obj_free( &c ); bli_obj_free( &c_save ); } void libblis_test_symm_impl ( iface_t iface, side_t side, obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c ) { switch ( iface ) { case BLIS_TEST_SEQ_FRONT_END: bli_symm( side, alpha, a, b, beta, c ); break; default: libblis_test_printf_error( "Invalid interface type.\n" ); } } void libblis_test_symm_check ( test_params_t* params, side_t side, obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, obj_t* c_orig, double* resid ) { num_t dt = bli_obj_dt( c ); num_t dt_real = bli_obj_dt_proj_to_real( c ); dim_t m = bli_obj_length( c ); dim_t n = bli_obj_width( c ); obj_t norm; obj_t t, v, w, z; double junk; // // Pre-conditions: // - a is randomized and symmetric. // - b is randomized. // - c_orig is randomized. // Note: // - alpha and beta should have non-zero imaginary components in the // complex cases in order to more fully exercise the implementation. // // Under these conditions, we assume that the implementation for // // C := beta * C_orig + alpha * conja(A) * transb(B) (side = left) // C := beta * C_orig + alpha * transb(B) * conja(A) (side = right) // // is functioning correctly if // // normfv( v - z ) // // is negligible, where // // v = C * t // // z = ( beta * C_orig + alpha * conja(A) * transb(B) ) * t (side = left) // = beta * C_orig * t + alpha * conja(A) * transb(B) * t // = beta * C_orig * t + alpha * conja(A) * w // = beta * C_orig * t + z // // z = ( beta * C_orig + alpha * transb(B) * conja(A) ) * t (side = right) // = beta * C_orig * t + alpha * transb(B) * conja(A) * t // = beta * C_orig * t + alpha * transb(B) * w // = beta * C_orig * t + z bli_obj_scalar_init_detached( dt_real, &norm ); if ( bli_is_left( side ) ) { bli_obj_create( dt, n, 1, 0, 0, &t ); bli_obj_create( dt, m, 1, 0, 0, &v ); bli_obj_create( dt, m, 1, 0, 0, &w ); bli_obj_create( dt, m, 1, 0, 0, &z ); } else // else if ( bli_is_left( side ) ) { bli_obj_create( dt, n, 1, 0, 0, &t ); bli_obj_create( dt, m, 1, 0, 0, &v ); bli_obj_create( dt, n, 1, 0, 0, &w ); bli_obj_create( dt, m, 1, 0, 0, &z ); } libblis_test_vobj_randomize( params, TRUE, &t ); bli_gemv( &BLIS_ONE, c, &t, &BLIS_ZERO, &v ); if ( bli_is_left( side ) ) { bli_gemv( &BLIS_ONE, b, &t, &BLIS_ZERO, &w ); bli_symv( alpha, a, &w, &BLIS_ZERO, &z ); } else { bli_symv( &BLIS_ONE, a, &t, &BLIS_ZERO, &w ); bli_gemv( alpha, b, &w, &BLIS_ZERO, &z ); } bli_gemv( beta, c_orig, &t, &BLIS_ONE, &z ); bli_subv( &z, &v ); bli_normfv( &v, &norm ); bli_getsc( &norm, resid, &junk ); bli_obj_free( &t ); bli_obj_free( &v ); bli_obj_free( &w ); bli_obj_free( &z ); } blis-0.9.0/testsuite/src/test_symm.h000066400000000000000000000034771422157504600175070ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void libblis_test_symm ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); blis-0.9.0/testsuite/src/test_symv.c000066400000000000000000000226151422157504600175060ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "test_libblis.h" // Static variables. static char* op_str = "symv"; static char* o_types = "mvv"; // a x y static char* p_types = "ucc"; // uploa conja conjx static thresh_t thresh[BLIS_NUM_FP_TYPES] = { { 1e-04, 1e-05 }, // warn, pass for s { 1e-04, 1e-05 }, // warn, pass for c { 1e-13, 1e-14 }, // warn, pass for d { 1e-13, 1e-14 } }; // warn, pass for z // Local prototypes. void libblis_test_symv_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); void libblis_test_symv_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ); void libblis_test_symv_impl ( iface_t iface, obj_t* alpha, obj_t* a, obj_t* x, obj_t* beta, obj_t* y ); void libblis_test_symv_check ( test_params_t* params, obj_t* alpha, obj_t* a, obj_t* x, obj_t* beta, obj_t* y, obj_t* y_orig, double* resid ); void libblis_test_symv_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { libblis_test_randv( tdata, params, &(op->ops->randv) ); libblis_test_randm( tdata, params, &(op->ops->randm) ); libblis_test_normfv( tdata, params, &(op->ops->normfv) ); libblis_test_subv( tdata, params, &(op->ops->subv) ); libblis_test_copyv( tdata, params, &(op->ops->copyv) ); libblis_test_scalv( tdata, params, &(op->ops->scalv) ); libblis_test_gemv( tdata, params, &(op->ops->gemv) ); } void libblis_test_symv ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { // Return early if this test has already been done. if ( libblis_test_op_is_done( op ) ) return; // Return early if operation is disabled. if ( libblis_test_op_is_disabled( op ) || libblis_test_l2_is_disabled( op ) ) return; // Call dependencies first. if ( TRUE ) libblis_test_symv_deps( tdata, params, op ); // Execute the test driver for each implementation requested. //if ( op->front_seq == ENABLE ) { libblis_test_op_driver( tdata, params, op, BLIS_TEST_SEQ_FRONT_END, op_str, p_types, o_types, thresh, libblis_test_symv_experiment ); } } void libblis_test_symv_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ) { unsigned int n_repeats = params->n_repeats; unsigned int i; double time_min = DBL_MAX; double time; num_t datatype; dim_t m; uplo_t uploa; conj_t conja; conj_t conjx; obj_t alpha, a, x, beta, y; obj_t y_save; // Use the datatype of the first char in the datatype combination string. bli_param_map_char_to_blis_dt( dc_str[0], &datatype ); // Map the dimension specifier to an actual dimension. m = libblis_test_get_dim_from_prob_size( op->dim_spec[0], p_cur ); // Map parameter characters to BLIS constants. bli_param_map_char_to_blis_uplo( pc_str[0], &uploa ); bli_param_map_char_to_blis_conj( pc_str[1], &conja ); bli_param_map_char_to_blis_conj( pc_str[2], &conjx ); // Create test scalars. bli_obj_scalar_init_detached( datatype, &alpha ); bli_obj_scalar_init_detached( datatype, &beta ); // Create test operands (vectors and/or matrices). libblis_test_mobj_create( params, datatype, BLIS_NO_TRANSPOSE, sc_str[0], m, m, &a ); libblis_test_vobj_create( params, datatype, sc_str[1], m, &x ); libblis_test_vobj_create( params, datatype, sc_str[2], m, &y ); libblis_test_vobj_create( params, datatype, sc_str[2], m, &y_save ); // Set alpha and beta. if ( bli_obj_is_real( &y ) ) { bli_setsc( 1.0, 0.0, &alpha ); bli_setsc( -1.0, 0.0, &beta ); } else { bli_setsc( 0.5, 0.5, &alpha ); bli_setsc( -0.5, 0.5, &beta ); } // Set the structure and uplo properties of A. bli_obj_set_struc( BLIS_SYMMETRIC, &a ); bli_obj_set_uplo( uploa, &a ); // Randomize A, make it densely symmetric, and zero the unstored triangle // to ensure the implementation reads only from the stored region. libblis_test_mobj_randomize( params, TRUE, &a ); bli_mksymm( &a ); bli_mktrim( &a ); // Randomize x and y, and save y. libblis_test_vobj_randomize( params, TRUE, &x ); libblis_test_vobj_randomize( params, TRUE, &y ); bli_copyv( &y, &y_save ); // Apply the remaining parameters. bli_obj_set_conj( conja, &a ); bli_obj_set_conj( conjx, &x ); // Repeat the experiment n_repeats times and record results. for ( i = 0; i < n_repeats; ++i ) { bli_copym( &y_save, &y ); time = bli_clock(); libblis_test_symv_impl( iface, &alpha, &a, &x, &beta, &y ); time_min = bli_clock_min_diff( time_min, time ); } // Estimate the performance of the best experiment repeat. *perf = ( 1.0 * m * m ) / time_min / FLOPS_PER_UNIT_PERF; if ( bli_obj_is_complex( &y ) ) *perf *= 4.0; // Perform checks. libblis_test_symv_check( params, &alpha, &a, &x, &beta, &y, &y_save, resid ); // Zero out performance and residual if output vector is empty. libblis_test_check_empty_problem( &y, perf, resid ); // Free the test objects. bli_obj_free( &a ); bli_obj_free( &x ); bli_obj_free( &y ); bli_obj_free( &y_save ); } void libblis_test_symv_impl ( iface_t iface, obj_t* alpha, obj_t* a, obj_t* x, obj_t* beta, obj_t* y ) { switch ( iface ) { case BLIS_TEST_SEQ_FRONT_END: bli_symv( alpha, a, x, beta, y ); break; default: libblis_test_printf_error( "Invalid interface type.\n" ); } } void libblis_test_symv_check ( test_params_t* params, obj_t* alpha, obj_t* a, obj_t* x, obj_t* beta, obj_t* y, obj_t* y_orig, double* resid ) { num_t dt = bli_obj_dt( y ); num_t dt_real = bli_obj_dt_proj_to_real( y ); dim_t m = bli_obj_vector_dim( y ); obj_t v; obj_t norm; double junk; // // Pre-conditions: // - a is randomized and symmetric. // - x is randomized. // - y_orig is randomized. // Note: // - alpha and beta should have non-zero imaginary components in the // complex cases in order to more fully exercise the implementation. // // Under these conditions, we assume that the implementation for // // y := beta * y_orig + alpha * conja(A) * conjx(x) // // is functioning correctly if // // normfv( y - v ) // // is negligible, where // // v = beta * y_orig + alpha * conja(A_dense) * x // bli_obj_scalar_init_detached( dt_real, &norm ); bli_obj_create( dt, m, 1, 0, 0, &v ); bli_copyv( y_orig, &v ); bli_mksymm( a ); bli_obj_set_struc( BLIS_GENERAL, a ); bli_obj_set_uplo( BLIS_DENSE, a ); bli_gemv( alpha, a, x, beta, &v ); bli_subv( &v, y ); bli_normfv( y, &norm ); bli_getsc( &norm, resid, &junk ); bli_obj_free( &v ); } blis-0.9.0/testsuite/src/test_symv.h000066400000000000000000000034771422157504600175200ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void libblis_test_symv ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); blis-0.9.0/testsuite/src/test_syr.c000066400000000000000000000227021422157504600173220ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "test_libblis.h" // Static variables. static char* op_str = "syr"; static char* o_types = "vm"; // x a static char* p_types = "uc"; // uploa conjx static thresh_t thresh[BLIS_NUM_FP_TYPES] = { { 1e-04, 1e-05 }, // warn, pass for s { 1e-04, 1e-05 }, // warn, pass for c { 1e-13, 1e-14 }, // warn, pass for d { 1e-13, 1e-14 } }; // warn, pass for z // Local prototypes. void libblis_test_syr_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); void libblis_test_syr_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ); void libblis_test_syr_impl ( iface_t iface, obj_t* alpha, obj_t* x, obj_t* a ); void libblis_test_syr_check ( test_params_t* params, obj_t* alpha, obj_t* x, obj_t* a, obj_t* a_orig, double* resid ); void libblis_test_syr_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { libblis_test_randv( tdata, params, &(op->ops->randv) ); libblis_test_randm( tdata, params, &(op->ops->randm) ); libblis_test_normfv( tdata, params, &(op->ops->normfv) ); libblis_test_subv( tdata, params, &(op->ops->subv) ); libblis_test_copym( tdata, params, &(op->ops->copym) ); libblis_test_scal2v( tdata, params, &(op->ops->scal2v) ); libblis_test_dotv( tdata, params, &(op->ops->dotv) ); libblis_test_gemv( tdata, params, &(op->ops->gemv) ); } void libblis_test_syr ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { // Return early if this test has already been done. if ( libblis_test_op_is_done( op ) ) return; // Return early if operation is disabled. if ( libblis_test_op_is_disabled( op ) || libblis_test_l2_is_disabled( op ) ) return; // Call dependencies first. if ( TRUE ) libblis_test_syr_deps( tdata, params, op ); // Execute the test driver for each implementation requested. //if ( op->front_seq == ENABLE ) { libblis_test_op_driver( tdata, params, op, BLIS_TEST_SEQ_FRONT_END, op_str, p_types, o_types, thresh, libblis_test_syr_experiment ); } } void libblis_test_syr_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ) { unsigned int n_repeats = params->n_repeats; unsigned int i; double time_min = DBL_MAX; double time; num_t datatype; dim_t m; uplo_t uploa; conj_t conjx; obj_t alpha, x, a; obj_t a_save; // Use the datatype of the first char in the datatype combination string. bli_param_map_char_to_blis_dt( dc_str[0], &datatype ); // Map the dimension specifier to an actual dimension. m = libblis_test_get_dim_from_prob_size( op->dim_spec[0], p_cur ); // Map parameter characters to BLIS constants. bli_param_map_char_to_blis_uplo( pc_str[0], &uploa ); bli_param_map_char_to_blis_conj( pc_str[1], &conjx ); // Create test scalars. bli_obj_scalar_init_detached( datatype, &alpha ); // Create test operands (vectors and/or matrices). libblis_test_vobj_create( params, datatype, sc_str[0], m, &x ); libblis_test_mobj_create( params, datatype, BLIS_NO_TRANSPOSE, sc_str[1], m, m, &a ); libblis_test_mobj_create( params, datatype, BLIS_NO_TRANSPOSE, sc_str[1], m, m, &a_save ); // Set alpha. //bli_copysc( &BLIS_MINUS_ONE, &alpha ); bli_setsc( -1.0, 0.5, &alpha ); // Randomize x. libblis_test_vobj_randomize( params, TRUE, &x ); // Set the structure and uplo properties of A. bli_obj_set_struc( BLIS_SYMMETRIC, &a ); bli_obj_set_uplo( uploa, &a ); // Randomize A, make it densely symmetric, and zero the unstored triangle // to ensure the implementation is reads only from the stored region. libblis_test_mobj_randomize( params, TRUE, &a ); bli_mksymm( &a ); bli_mktrim( &a ); bli_obj_set_struc( BLIS_SYMMETRIC, &a_save ); bli_obj_set_uplo( uploa, &a_save ); bli_copym( &a, &a_save ); // Apply the remaining parameters. bli_obj_set_conj( conjx, &x ); // Repeat the experiment n_repeats times and record results. for ( i = 0; i < n_repeats; ++i ) { bli_copym( &a_save, &a ); time = bli_clock(); libblis_test_syr_impl( iface, &alpha, &x, &a ); time_min = bli_clock_min_diff( time_min, time ); } // Estimate the performance of the best experiment repeat. *perf = ( 1.0 * m * m ) / time_min / FLOPS_PER_UNIT_PERF; if ( bli_obj_is_complex( &a ) ) *perf *= 4.0; // Perform checks. libblis_test_syr_check( params, &alpha, &x, &a, &a_save, resid ); // Zero out performance and residual if output matrix is empty. libblis_test_check_empty_problem( &a, perf, resid ); // Free the test objects. bli_obj_free( &x ); bli_obj_free( &a ); bli_obj_free( &a_save ); } void libblis_test_syr_impl ( iface_t iface, obj_t* alpha, obj_t* x, obj_t* a ) { switch ( iface ) { case BLIS_TEST_SEQ_FRONT_END: bli_syr( alpha, x, a ); break; default: libblis_test_printf_error( "Invalid interface type.\n" ); } } void libblis_test_syr_check ( test_params_t* params, obj_t* alpha, obj_t* x, obj_t* a, obj_t* a_orig, double* resid ) { num_t dt = bli_obj_dt( a ); num_t dt_real = bli_obj_dt_proj_to_real( a ); dim_t m_a = bli_obj_length( a ); obj_t xt, t, v, w; obj_t rho, norm; double junk; // // Pre-conditions: // - x is randomized. // - a is randomized and symmetric. // Note: // - alpha should have a non-zero imaginary component in the // complex cases in order to more fully exercise the implementation. // // Under these conditions, we assume that the implementation for // // A := A_orig + alpha * conjx(x) * conjx(x)^T // // is functioning correctly if // // normfv( v - w ) // // is negligible, where // // v = A * t // w = ( A_orig + alpha * conjx(x) * conjx(x)^T ) * t // = A_orig * t + alpha * conjx(x) * conjx(x)^T * t // = A_orig * t + alpha * conjx(x) * rho // = A_orig * t + w // bli_mksymm( a ); bli_mksymm( a_orig ); bli_obj_set_struc( BLIS_GENERAL, a ); bli_obj_set_struc( BLIS_GENERAL, a_orig ); bli_obj_set_uplo( BLIS_DENSE, a ); bli_obj_set_uplo( BLIS_DENSE, a_orig ); bli_obj_scalar_init_detached( dt, &rho ); bli_obj_scalar_init_detached( dt_real, &norm ); bli_obj_create( dt, m_a, 1, 0, 0, &t ); bli_obj_create( dt, m_a, 1, 0, 0, &v ); bli_obj_create( dt, m_a, 1, 0, 0, &w ); bli_obj_alias_to( x, &xt ); libblis_test_vobj_randomize( params, TRUE, &t ); bli_gemv( &BLIS_ONE, a, &t, &BLIS_ZERO, &v ); bli_dotv( &xt, &t, &rho ); bli_mulsc( alpha, &rho ); bli_scal2v( &rho, x, &w ); bli_gemv( &BLIS_ONE, a_orig, &t, &BLIS_ONE, &w ); bli_subv( &w, &v ); bli_normfv( &v, &norm ); bli_getsc( &norm, resid, &junk ); bli_obj_free( &t ); bli_obj_free( &v ); bli_obj_free( &w ); } blis-0.9.0/testsuite/src/test_syr.h000066400000000000000000000034761422157504600173360ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void libblis_test_syr ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); blis-0.9.0/testsuite/src/test_syr2.c000066400000000000000000000245501422157504600174070ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "test_libblis.h" // Static variables. static char* op_str = "syr2"; static char* o_types = "vvm"; // x y a static char* p_types = "ucc"; // uploa conjx conjy static thresh_t thresh[BLIS_NUM_FP_TYPES] = { { 1e-04, 1e-05 }, // warn, pass for s { 1e-04, 1e-05 }, // warn, pass for c { 1e-13, 1e-14 }, // warn, pass for d { 1e-13, 1e-14 } }; // warn, pass for z // Local prototypes. void libblis_test_syr2_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); void libblis_test_syr2_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ); void libblis_test_syr2_impl ( iface_t iface, obj_t* alpha, obj_t* x, obj_t* y, obj_t* a ); void libblis_test_syr2_check ( test_params_t* params, obj_t* alpha, obj_t* x, obj_t* y, obj_t* a, obj_t* a_orig, double* resid ); void libblis_test_syr2_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { libblis_test_randv( tdata, params, &(op->ops->randv) ); libblis_test_randm( tdata, params, &(op->ops->randm) ); libblis_test_normfv( tdata, params, &(op->ops->normfv) ); libblis_test_subv( tdata, params, &(op->ops->subv) ); libblis_test_copym( tdata, params, &(op->ops->copym) ); libblis_test_scal2v( tdata, params, &(op->ops->scal2v) ); libblis_test_dotv( tdata, params, &(op->ops->dotv) ); libblis_test_gemv( tdata, params, &(op->ops->gemv) ); } void libblis_test_syr2 ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { // Return early if this test has already been done. if ( libblis_test_op_is_done( op ) ) return; // Return early if operation is disabled. if ( libblis_test_op_is_disabled( op ) || libblis_test_l2_is_disabled( op ) ) return; // Call dependencies first. if ( TRUE ) libblis_test_syr2_deps( tdata, params, op ); // Execute the test driver for each implementation requested. //if ( op->front_seq == ENABLE ) { libblis_test_op_driver( tdata, params, op, BLIS_TEST_SEQ_FRONT_END, op_str, p_types, o_types, thresh, libblis_test_syr2_experiment ); } } void libblis_test_syr2_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ) { unsigned int n_repeats = params->n_repeats; unsigned int i; double time_min = DBL_MAX; double time; num_t datatype; dim_t m; uplo_t uploa; conj_t conjx, conjy; obj_t alpha, x, y, a; obj_t a_save; // Use the datatype of the first char in the datatype combination string. bli_param_map_char_to_blis_dt( dc_str[0], &datatype ); // Map the dimension specifier to an actual dimension. m = libblis_test_get_dim_from_prob_size( op->dim_spec[0], p_cur ); // Map parameter characters to BLIS constants. bli_param_map_char_to_blis_uplo( pc_str[0], &uploa ); bli_param_map_char_to_blis_conj( pc_str[1], &conjx ); bli_param_map_char_to_blis_conj( pc_str[2], &conjy ); // Create test scalars. bli_obj_scalar_init_detached( datatype, &alpha ); // Create test operands (vectors and/or matrices). libblis_test_vobj_create( params, datatype, sc_str[0], m, &x ); libblis_test_vobj_create( params, datatype, sc_str[1], m, &y ); libblis_test_mobj_create( params, datatype, BLIS_NO_TRANSPOSE, sc_str[2], m, m, &a ); libblis_test_mobj_create( params, datatype, BLIS_NO_TRANSPOSE, sc_str[2], m, m, &a_save ); // Set alpha. //bli_copysc( &BLIS_MINUS_ONE, &alpha ); bli_setsc( -1.0, 1.0, &alpha ); // Randomize x and y. libblis_test_vobj_randomize( params, TRUE, &x ); libblis_test_vobj_randomize( params, TRUE, &y ); // Set the structure and uplo properties of A. bli_obj_set_struc( BLIS_SYMMETRIC, &a ); bli_obj_set_uplo( uploa, &a ); // Randomize A, make it densely symmetric, and zero the unstored triangle // to ensure the implementation is reads only from the stored region. libblis_test_mobj_randomize( params, TRUE, &a ); bli_mksymm( &a ); bli_mktrim( &a ); bli_obj_set_struc( BLIS_SYMMETRIC, &a_save ); bli_obj_set_uplo( uploa, &a_save ); bli_copym( &a, &a_save ); // Apply the remaining parameters. bli_obj_set_conj( conjx, &x ); bli_obj_set_conj( conjy, &y ); // Repeat the experiment n_repeats times and record results. for ( i = 0; i < n_repeats; ++i ) { bli_copym( &a_save, &a ); time = bli_clock(); libblis_test_syr2_impl( iface, &alpha, &x, &y, &a ); time_min = bli_clock_min_diff( time_min, time ); } // Estimate the performance of the best experiment repeat. *perf = ( 2.0 * m * m ) / time_min / FLOPS_PER_UNIT_PERF; if ( bli_obj_is_complex( &a ) ) *perf *= 4.0; // Perform checks. libblis_test_syr2_check( params, &alpha, &x, &y, &a, &a_save, resid ); // Zero out performance and residual if output matrix is empty. libblis_test_check_empty_problem( &a, perf, resid ); // Free the test objects. bli_obj_free( &x ); bli_obj_free( &y ); bli_obj_free( &a ); bli_obj_free( &a_save ); } void libblis_test_syr2_impl ( iface_t iface, obj_t* alpha, obj_t* x, obj_t* y, obj_t* a ) { switch ( iface ) { case BLIS_TEST_SEQ_FRONT_END: bli_syr2( alpha, x, y, a ); break; default: libblis_test_printf_error( "Invalid interface type.\n" ); } } void libblis_test_syr2_check ( test_params_t* params, obj_t* alpha, obj_t* x, obj_t* y, obj_t* a, obj_t* a_orig, double* resid ) { num_t dt = bli_obj_dt( a ); num_t dt_real = bli_obj_dt_proj_to_real( a ); dim_t m_a = bli_obj_length( a ); obj_t xt, yt; obj_t t, v, w1, w2; obj_t rho, norm; double junk; // // Pre-conditions: // - x is randomized. // - y is randomized. // - a is randomized and symmetric. // Note: // - alpha should have a non-zero imaginary component in the // complex cases in order to more fully exercise the implementation. // // Under these conditions, we assume that the implementation for // // A := A_orig + alpha * conjx(x) * conjy(y)^T + alpha * conjy(y) * conjx(x)^T // // is functioning correctly if // // normfv( v - w ) // // is negligible, where // // v = A * t // w = ( A_orig + alpha * conjx(x) * conjy(y)^T + alpha * conjy(y) * conjx(x)^T ) * t // = A_orig * t + alpha * conjx(x) * conjy(y)^T * t + alpha * conjy(y) * conjx(x)^T * t // = A_orig * t + alpha * conjx(x) * conjy(y)^T * t + alpha * conjy(y) * rho // = A_orig * t + alpha * conjx(x) * conjy(y)^T * t + w1 // = A_orig * t + alpha * conjx(x) * rho + w1 // = A_orig * t + w2 + w1 // bli_mksymm( a ); bli_mksymm( a_orig ); bli_obj_set_struc( BLIS_GENERAL, a ); bli_obj_set_struc( BLIS_GENERAL, a_orig ); bli_obj_set_uplo( BLIS_DENSE, a ); bli_obj_set_uplo( BLIS_DENSE, a_orig ); bli_obj_scalar_init_detached( dt, &rho ); bli_obj_scalar_init_detached( dt_real, &norm ); bli_obj_create( dt, m_a, 1, 0, 0, &t ); bli_obj_create( dt, m_a, 1, 0, 0, &v ); bli_obj_create( dt, m_a, 1, 0, 0, &w1 ); bli_obj_create( dt, m_a, 1, 0, 0, &w2 ); bli_obj_alias_to( x, &xt ); bli_obj_alias_to( y, &yt ); libblis_test_vobj_randomize( params, TRUE, &t ); bli_gemv( &BLIS_ONE, a, &t, &BLIS_ZERO, &v ); bli_dotv( &xt, &t, &rho ); bli_mulsc( alpha, &rho ); bli_scal2v( &rho, y, &w1 ); bli_dotv( &yt, &t, &rho ); bli_mulsc( alpha, &rho ); bli_scal2v( &rho, x, &w2 ); bli_addv( &w2, &w1 ); bli_gemv( &BLIS_ONE, a_orig, &t, &BLIS_ONE, &w1 ); bli_subv( &w1, &v ); bli_normfv( &v, &norm ); bli_getsc( &norm, resid, &junk ); bli_obj_free( &t ); bli_obj_free( &v ); bli_obj_free( &w1 ); bli_obj_free( &w2 ); } blis-0.9.0/testsuite/src/test_syr2.h000066400000000000000000000034771422157504600174210ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void libblis_test_syr2 ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); blis-0.9.0/testsuite/src/test_syr2k.c000066400000000000000000000257701422157504600175670ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "test_libblis.h" // Static variables. static char* op_str = "syr2k"; static char* o_types = "mmm"; // a b c static char* p_types = "uhh"; // uploc transa transb static thresh_t thresh[BLIS_NUM_FP_TYPES] = { { 1e-04, 1e-05 }, // warn, pass for s { 1e-04, 1e-05 }, // warn, pass for c { 1e-13, 1e-14 }, // warn, pass for d { 1e-13, 1e-14 } }; // warn, pass for z // Local prototypes. void libblis_test_syr2k_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); void libblis_test_syr2k_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ); void libblis_test_syr2k_impl ( iface_t iface, obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c ); void libblis_test_syr2k_check ( test_params_t* params, obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, obj_t* c_orig, double* resid ); void libblis_test_syr2k_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { libblis_test_randv( tdata, params, &(op->ops->randv) ); libblis_test_randm( tdata, params, &(op->ops->randm) ); libblis_test_setv( tdata, params, &(op->ops->setv) ); libblis_test_normfv( tdata, params, &(op->ops->normfv) ); libblis_test_subv( tdata, params, &(op->ops->subv) ); libblis_test_scalv( tdata, params, &(op->ops->scalv) ); libblis_test_copym( tdata, params, &(op->ops->copym) ); libblis_test_scalm( tdata, params, &(op->ops->scalm) ); libblis_test_gemv( tdata, params, &(op->ops->gemv) ); libblis_test_symv( tdata, params, &(op->ops->symv) ); } void libblis_test_syr2k ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { // Return early if this test has already been done. if ( libblis_test_op_is_done( op ) ) return; // Return early if operation is disabled. if ( libblis_test_op_is_disabled( op ) || libblis_test_l3_is_disabled( op ) ) return; // Call dependencies first. if ( TRUE ) libblis_test_syr2k_deps( tdata, params, op ); // Execute the test driver for each implementation requested. //if ( op->front_seq == ENABLE ) { libblis_test_op_driver( tdata, params, op, BLIS_TEST_SEQ_FRONT_END, op_str, p_types, o_types, thresh, libblis_test_syr2k_experiment ); } } void libblis_test_syr2k_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ) { unsigned int n_repeats = params->n_repeats; unsigned int i; double time_min = DBL_MAX; double time; num_t datatype; dim_t m, k; uplo_t uploc; trans_t transa, transb; obj_t alpha, a, b, beta, c; obj_t c_save; // Use the datatype of the first char in the datatype combination string. bli_param_map_char_to_blis_dt( dc_str[0], &datatype ); // Map the dimension specifier to actual dimensions. m = libblis_test_get_dim_from_prob_size( op->dim_spec[0], p_cur ); k = libblis_test_get_dim_from_prob_size( op->dim_spec[1], p_cur ); // Map parameter characters to BLIS constants. bli_param_map_char_to_blis_uplo( pc_str[0], &uploc ); bli_param_map_char_to_blis_trans( pc_str[1], &transa ); bli_param_map_char_to_blis_trans( pc_str[2], &transb ); // Create test scalars. bli_obj_scalar_init_detached( datatype, &alpha ); bli_obj_scalar_init_detached( datatype, &beta ); // Create test operands (vectors and/or matrices). libblis_test_mobj_create( params, datatype, transa, sc_str[1], m, k, &a ); libblis_test_mobj_create( params, datatype, transb, sc_str[2], m, k, &b ); libblis_test_mobj_create( params, datatype, BLIS_NO_TRANSPOSE, sc_str[0], m, m, &c ); libblis_test_mobj_create( params, datatype, BLIS_NO_TRANSPOSE, sc_str[0], m, m, &c_save ); // Set alpha and beta. if ( bli_obj_is_real( &c ) ) { bli_setsc( 0.8, 0.0, &alpha ); bli_setsc( -1.0, 0.0, &beta ); } else { // For syr2k, both alpha and beta may be complex since, unlike her2k, // C is symmetric in both the real and complex cases. bli_setsc( 0.8, 0.5, &alpha ); bli_setsc( -1.0, 0.5, &beta ); } // Randomize A and B. libblis_test_mobj_randomize( params, TRUE, &a ); libblis_test_mobj_randomize( params, TRUE, &b ); // Set the structure and uplo properties of C. bli_obj_set_struc( BLIS_SYMMETRIC, &c ); bli_obj_set_uplo( uploc, &c ); // Randomize A, make it densely symmetric, and zero the unstored triangle // to ensure the implementation is reads only from the stored region. libblis_test_mobj_randomize( params, TRUE, &c ); bli_mksymm( &c ); bli_mktrim( &c ); // Save C and set its structure and uplo properties. bli_obj_set_struc( BLIS_SYMMETRIC, &c_save ); bli_obj_set_uplo( uploc, &c_save ); bli_copym( &c, &c_save ); // Apply the remaining parameters. bli_obj_set_conjtrans( transa, &a ); bli_obj_set_conjtrans( transb, &b ); // Repeat the experiment n_repeats times and record results. for ( i = 0; i < n_repeats; ++i ) { bli_copym( &c_save, &c ); time = bli_clock(); libblis_test_syr2k_impl( iface, &alpha, &a, &b, &beta, &c ); time_min = bli_clock_min_diff( time_min, time ); } // Estimate the performance of the best experiment repeat. *perf = ( 2.0 * m * m * k ) / time_min / FLOPS_PER_UNIT_PERF; if ( bli_obj_is_complex( &c ) ) *perf *= 4.0; // Perform checks. libblis_test_syr2k_check( params, &alpha, &a, &b, &beta, &c, &c_save, resid ); // Zero out performance and residual if output matrix is empty. libblis_test_check_empty_problem( &c, perf, resid ); // Free the test objects. bli_obj_free( &a ); bli_obj_free( &b ); bli_obj_free( &c ); bli_obj_free( &c_save ); } void libblis_test_syr2k_impl ( iface_t iface, obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c ) { switch ( iface ) { case BLIS_TEST_SEQ_FRONT_END: bli_syr2k( alpha, a, b, beta, c ); break; default: libblis_test_printf_error( "Invalid interface type.\n" ); } } void libblis_test_syr2k_check ( test_params_t* params, obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, obj_t* c_orig, double* resid ) { num_t dt = bli_obj_dt( c ); num_t dt_real = bli_obj_dt_proj_to_real( c ); dim_t m = bli_obj_length( c ); dim_t k = bli_obj_width_after_trans( a ); obj_t at, bt; obj_t norm; obj_t t, v, w1, w2, z; double junk; // // Pre-conditions: // - a is randomized. // - b is randomized. // - c_orig is randomized and symmetric. // Note: // - alpha and beta should have non-zero imaginary components in the // complex cases in order to more fully exercise the implementation. // // Under these conditions, we assume that the implementation for // // C := beta * C_orig + alpha * transa(A) * transb(B)^T + alpha * transb(B) * transa(A)^T // // is functioning correctly if // // normfv( v - z ) // // is negligible, where // // v = C * t // z = ( beta * C_orig + alpha * transa(A) * transb(B)^T + alpha * transb(B) * transa(A)^T ) * t // = beta * C_orig * t + alpha * transa(A) * transb(B)^T * t + alpha * transb(B) * transa(A)^T * t // = beta * C_orig * t + alpha * transa(A) * transb(B)^T * t + alpha * transb(B) * w2 // = beta * C_orig * t + alpha * transa(A) * w1 + alpha * transb(B) * w2 // = beta * C_orig * t + alpha * transa(A) * w1 + z // = beta * C_orig * t + z // bli_obj_alias_with_trans( BLIS_TRANSPOSE, a, &at ); bli_obj_alias_with_trans( BLIS_TRANSPOSE, b, &bt ); bli_obj_scalar_init_detached( dt_real, &norm ); bli_obj_create( dt, m, 1, 0, 0, &t ); bli_obj_create( dt, m, 1, 0, 0, &v ); bli_obj_create( dt, k, 1, 0, 0, &w1 ); bli_obj_create( dt, k, 1, 0, 0, &w2 ); bli_obj_create( dt, m, 1, 0, 0, &z ); libblis_test_vobj_randomize( params, TRUE, &t ); bli_symv( &BLIS_ONE, c, &t, &BLIS_ZERO, &v ); bli_gemv( &BLIS_ONE, &at, &t, &BLIS_ZERO, &w2 ); bli_gemv( &BLIS_ONE, &bt, &t, &BLIS_ZERO, &w1 ); bli_gemv( alpha, a, &w1, &BLIS_ZERO, &z ); bli_gemv( alpha, b, &w2, &BLIS_ONE, &z ); bli_symv( beta, c_orig, &t, &BLIS_ONE, &z ); bli_subv( &z, &v ); bli_normfv( &v, &norm ); bli_getsc( &norm, resid, &junk ); bli_obj_free( &t ); bli_obj_free( &v ); bli_obj_free( &w1 ); bli_obj_free( &w2 ); bli_obj_free( &z ); } blis-0.9.0/testsuite/src/test_syr2k.h000066400000000000000000000035001422157504600175570ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void libblis_test_syr2k ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); blis-0.9.0/testsuite/src/test_syrk.c000066400000000000000000000240671422157504600175030ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "test_libblis.h" // Static variables. static char* op_str = "syrk"; static char* o_types = "mm"; // a c static char* p_types = "uh"; // uploc transa static thresh_t thresh[BLIS_NUM_FP_TYPES] = { { 1e-04, 1e-05 }, // warn, pass for s { 1e-04, 1e-05 }, // warn, pass for c { 1e-13, 1e-14 }, // warn, pass for d { 1e-13, 1e-14 } }; // warn, pass for z // Local prototypes. void libblis_test_syrk_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); void libblis_test_syrk_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ); void libblis_test_syrk_impl ( iface_t iface, obj_t* alpha, obj_t* a, obj_t* beta, obj_t* c ); void libblis_test_syrk_check ( test_params_t* params, obj_t* alpha, obj_t* a, obj_t* beta, obj_t* c, obj_t* c_orig, double* resid ); void libblis_test_syrk_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { libblis_test_randv( tdata, params, &(op->ops->randv) ); libblis_test_randm( tdata, params, &(op->ops->randm) ); libblis_test_setv( tdata, params, &(op->ops->setv) ); libblis_test_normfv( tdata, params, &(op->ops->normfv) ); libblis_test_subv( tdata, params, &(op->ops->subv) ); libblis_test_scalv( tdata, params, &(op->ops->scalv) ); libblis_test_copym( tdata, params, &(op->ops->copym) ); libblis_test_scalm( tdata, params, &(op->ops->scalm) ); libblis_test_gemv( tdata, params, &(op->ops->gemv) ); libblis_test_symv( tdata, params, &(op->ops->symv) ); } void libblis_test_syrk ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { // Return early if this test has already been done. if ( libblis_test_op_is_done( op ) ) return; // Return early if operation is disabled. if ( libblis_test_op_is_disabled( op ) || libblis_test_l3_is_disabled( op ) ) return; // Call dependencies first. if ( TRUE ) libblis_test_syrk_deps( tdata, params, op ); // Execute the test driver for each implementation requested. //if ( op->front_seq == ENABLE ) { libblis_test_op_driver( tdata, params, op, BLIS_TEST_SEQ_FRONT_END, op_str, p_types, o_types, thresh, libblis_test_syrk_experiment ); } } void libblis_test_syrk_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ) { unsigned int n_repeats = params->n_repeats; unsigned int i; double time_min = DBL_MAX; double time; num_t datatype; dim_t m, k; uplo_t uploc; trans_t transa; obj_t alpha, a, beta, c; obj_t c_save; // Use the datatype of the first char in the datatype combination string. bli_param_map_char_to_blis_dt( dc_str[0], &datatype ); // Map the dimension specifier to actual dimensions. m = libblis_test_get_dim_from_prob_size( op->dim_spec[0], p_cur ); k = libblis_test_get_dim_from_prob_size( op->dim_spec[1], p_cur ); // Map parameter characters to BLIS constants. bli_param_map_char_to_blis_uplo( pc_str[0], &uploc ); bli_param_map_char_to_blis_trans( pc_str[1], &transa ); // Create test scalars. bli_obj_scalar_init_detached( datatype, &alpha ); bli_obj_scalar_init_detached( datatype, &beta ); // Create test operands (vectors and/or matrices). libblis_test_mobj_create( params, datatype, transa, sc_str[1], m, k, &a ); libblis_test_mobj_create( params, datatype, BLIS_NO_TRANSPOSE, sc_str[0], m, m, &c ); libblis_test_mobj_create( params, datatype, BLIS_NO_TRANSPOSE, sc_str[0], m, m, &c_save ); // Set alpha and beta. if ( bli_obj_is_real( &c ) ) { bli_setsc( 1.2, 0.0, &alpha ); bli_setsc( -1.0, 0.0, &beta ); } else { // For syrk, both alpha and beta may be complex since, unlike herk, // C is symmetric in both the real and complex cases. bli_setsc( 1.2, 0.5, &alpha ); bli_setsc( -1.0, 0.5, &beta ); } // Randomize A. libblis_test_mobj_randomize( params, TRUE, &a ); // Set the structure and uplo properties of C. bli_obj_set_struc( BLIS_SYMMETRIC, &c ); bli_obj_set_uplo( uploc, &c ); // Randomize A, make it densely symmetric, and zero the unstored triangle // to ensure the implementation is reads only from the stored region. libblis_test_mobj_randomize( params, TRUE, &c ); bli_mksymm( &c ); bli_mktrim( &c ); // Save C and set its structure and uplo properties. bli_obj_set_struc( BLIS_SYMMETRIC, &c_save ); bli_obj_set_uplo( uploc, &c_save ); bli_copym( &c, &c_save ); // Apply the remaining parameters. bli_obj_set_conjtrans( transa, &a ); // Repeat the experiment n_repeats times and record results. for ( i = 0; i < n_repeats; ++i ) { bli_copym( &c_save, &c ); time = bli_clock(); libblis_test_syrk_impl( iface, &alpha, &a, &beta, &c ); time_min = bli_clock_min_diff( time_min, time ); } // Estimate the performance of the best experiment repeat. *perf = ( 1.0 * m * m * k ) / time_min / FLOPS_PER_UNIT_PERF; if ( bli_obj_is_complex( &c ) ) *perf *= 4.0; // Perform checks. libblis_test_syrk_check( params, &alpha, &a, &beta, &c, &c_save, resid ); // Zero out performance and residual if output matrix is empty. libblis_test_check_empty_problem( &c, perf, resid ); // Free the test objects. bli_obj_free( &a ); bli_obj_free( &c ); bli_obj_free( &c_save ); } void libblis_test_syrk_impl ( iface_t iface, obj_t* alpha, obj_t* a, obj_t* beta, obj_t* c ) { switch ( iface ) { case BLIS_TEST_SEQ_FRONT_END: bli_syrk( alpha, a, beta, c ); break; default: libblis_test_printf_error( "Invalid interface type.\n" ); } } void libblis_test_syrk_check ( test_params_t* params, obj_t* alpha, obj_t* a, obj_t* beta, obj_t* c, obj_t* c_orig, double* resid ) { num_t dt = bli_obj_dt( c ); num_t dt_real = bli_obj_dt_proj_to_real( c ); dim_t m = bli_obj_length( c ); dim_t k = bli_obj_width_after_trans( a ); obj_t at; obj_t norm; obj_t t, v, w, z; double junk; // // Pre-conditions: // - a is randomized. // - c_orig is randomized and symmetric. // Note: // - alpha and beta should have non-zero imaginary components in the // complex cases in order to more fully exercise the implementation. // // Under these conditions, we assume that the implementation for // // C := beta * C_orig + alpha * transa(A) * transa(A)^T // // is functioning correctly if // // normfv( v - z ) // // is negligible, where // // v = C * t // z = ( beta * C_orig + alpha * transa(A) * transa(A)^T ) * t // = beta * C_orig * t + alpha * transa(A) * transa(A)^T * t // = beta * C_orig * t + alpha * transa(A) * w // = beta * C_orig * t + z // bli_obj_alias_with_trans( BLIS_TRANSPOSE, a, &at ); bli_obj_scalar_init_detached( dt_real, &norm ); bli_obj_create( dt, m, 1, 0, 0, &t ); bli_obj_create( dt, m, 1, 0, 0, &v ); bli_obj_create( dt, k, 1, 0, 0, &w ); bli_obj_create( dt, m, 1, 0, 0, &z ); libblis_test_vobj_randomize( params, TRUE, &t ); bli_symv( &BLIS_ONE, c, &t, &BLIS_ZERO, &v ); bli_gemv( &BLIS_ONE, &at, &t, &BLIS_ZERO, &w ); bli_gemv( alpha, a, &w, &BLIS_ZERO, &z ); bli_symv( beta, c_orig, &t, &BLIS_ONE, &z ); bli_subv( &z, &v ); bli_normfv( &v, &norm ); bli_getsc( &norm, resid, &junk ); bli_obj_free( &t ); bli_obj_free( &v ); bli_obj_free( &w ); bli_obj_free( &z ); } blis-0.9.0/testsuite/src/test_syrk.h000066400000000000000000000034771422157504600175120ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void libblis_test_syrk ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); blis-0.9.0/testsuite/src/test_trmm.c000066400000000000000000000243411422157504600174650ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "test_libblis.h" // Static variables. static char* op_str = "trmm"; static char* o_types = "mm"; // a b static char* p_types = "suhd"; // side uploa transa diaga static thresh_t thresh[BLIS_NUM_FP_TYPES] = { { 1e-04, 1e-05 }, // warn, pass for s { 1e-04, 1e-05 }, // warn, pass for c { 1e-13, 1e-14 }, // warn, pass for d { 1e-13, 1e-14 } }; // warn, pass for z // Local prototypes. void libblis_test_trmm_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); void libblis_test_trmm_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ); void libblis_test_trmm_impl ( iface_t iface, side_t side, obj_t* alpha, obj_t* a, obj_t* b ); void libblis_test_trmm_check ( test_params_t* params, side_t side, obj_t* alpha, obj_t* a, obj_t* b, obj_t* b_orig, double* resid ); void libblis_test_trmm_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { libblis_test_randv( tdata, params, &(op->ops->randv) ); libblis_test_randm( tdata, params, &(op->ops->randm) ); libblis_test_setv( tdata, params, &(op->ops->setv) ); libblis_test_normfv( tdata, params, &(op->ops->normfv) ); libblis_test_subv( tdata, params, &(op->ops->subv) ); libblis_test_scalv( tdata, params, &(op->ops->scalv) ); libblis_test_copym( tdata, params, &(op->ops->copym) ); libblis_test_scalm( tdata, params, &(op->ops->scalm) ); libblis_test_gemv( tdata, params, &(op->ops->gemv) ); libblis_test_trmv( tdata, params, &(op->ops->trmv) ); } void libblis_test_trmm ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { // Return early if this test has already been done. if ( libblis_test_op_is_done( op ) ) return; // Return early if operation is disabled. if ( libblis_test_op_is_disabled( op ) || libblis_test_l3_is_disabled( op ) ) return; // Call dependencies first. if ( TRUE ) libblis_test_trmm_deps( tdata, params, op ); // Execute the test driver for each implementation requested. //if ( op->front_seq == ENABLE ) { libblis_test_op_driver( tdata, params, op, BLIS_TEST_SEQ_FRONT_END, op_str, p_types, o_types, thresh, libblis_test_trmm_experiment ); } } void libblis_test_trmm_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ) { unsigned int n_repeats = params->n_repeats; unsigned int i; double time_min = DBL_MAX; double time; num_t datatype; dim_t m, n; dim_t mn_side; side_t side; uplo_t uploa; trans_t transa; diag_t diaga; obj_t alpha, a, b; obj_t b_save; // Use the datatype of the first char in the datatype combination string. bli_param_map_char_to_blis_dt( dc_str[0], &datatype ); // Map the dimension specifier to actual dimensions. m = libblis_test_get_dim_from_prob_size( op->dim_spec[0], p_cur ); n = libblis_test_get_dim_from_prob_size( op->dim_spec[1], p_cur ); // Map parameter characters to BLIS constants. bli_param_map_char_to_blis_side( pc_str[0], &side ); bli_param_map_char_to_blis_uplo( pc_str[1], &uploa ); bli_param_map_char_to_blis_trans( pc_str[2], &transa ); bli_param_map_char_to_blis_diag( pc_str[3], &diaga ); // Create test scalars. bli_obj_scalar_init_detached( datatype, &alpha ); // Create test operands (vectors and/or matrices). bli_set_dim_with_side( side, m, n, &mn_side ); libblis_test_mobj_create( params, datatype, transa, sc_str[1], mn_side, mn_side, &a ); libblis_test_mobj_create( params, datatype, BLIS_NO_TRANSPOSE, sc_str[0], m, n, &b ); libblis_test_mobj_create( params, datatype, BLIS_NO_TRANSPOSE, sc_str[0], m, n, &b_save ); // Set alpha and beta. if ( bli_obj_is_real( &b ) ) { bli_setsc( 0.8, 0.0, &alpha ); } else { bli_setsc( 0.8, 0.5, &alpha ); } // Set the structure and uplo properties of A. bli_obj_set_struc( BLIS_TRIANGULAR, &a ); bli_obj_set_uplo( uploa, &a ); // Randomize A, make it densely triangular. libblis_test_mobj_randomize( params, TRUE, &a ); bli_mktrim( &a ); // Randomize B and save B. libblis_test_mobj_randomize( params, TRUE, &b ); bli_copym( &b, &b_save ); // Apply the remaining parameters. bli_obj_set_conjtrans( transa, &a ); bli_obj_set_diag( diaga, &a ); // Repeat the experiment n_repeats times and record results. for ( i = 0; i < n_repeats; ++i ) { bli_copym( &b_save, &b ); time = bli_clock(); libblis_test_trmm_impl( iface, side, &alpha, &a, &b ); time_min = bli_clock_min_diff( time_min, time ); } // Estimate the performance of the best experiment repeat. *perf = ( 1.0 * mn_side * m * n ) / time_min / FLOPS_PER_UNIT_PERF; if ( bli_obj_is_complex( &b ) ) *perf *= 4.0; // Perform checks. libblis_test_trmm_check( params, side, &alpha, &a, &b, &b_save, resid ); // Zero out performance and residual if output matrix is empty. libblis_test_check_empty_problem( &b, perf, resid ); // Free the test objects. bli_obj_free( &a ); bli_obj_free( &b ); bli_obj_free( &b_save ); } void libblis_test_trmm_impl ( iface_t iface, side_t side, obj_t* alpha, obj_t* a, obj_t* b ) { switch ( iface ) { case BLIS_TEST_SEQ_FRONT_END: bli_trmm( side, alpha, a, b ); break; default: libblis_test_printf_error( "Invalid interface type.\n" ); } } void libblis_test_trmm_check ( test_params_t* params, side_t side, obj_t* alpha, obj_t* a, obj_t* b, obj_t* b_orig, double* resid ) { num_t dt = bli_obj_dt( b ); num_t dt_real = bli_obj_dt_proj_to_real( b ); dim_t m = bli_obj_length( b ); dim_t n = bli_obj_width( b ); obj_t norm; obj_t t, v, w, z; double junk; // // Pre-conditions: // - a is randomized and triangular. // - b_orig is randomized. // Note: // - alpha should have a non-zero imaginary component in the // complex cases in order to more fully exercise the implementation. // // Under these conditions, we assume that the implementation for // // B := alpha * transa(A) * B_orig (side = left) // B := alpha * B_orig * transa(A) (side = right) // // is functioning correctly if // // normfv( v - z ) // // is negligible, where // // v = B * t // // z = ( alpha * transa(A) * B ) * t (side = left) // = alpha * transa(A) * B * t // = alpha * transa(A) * w // // z = ( alpha * B * transa(A) ) * t (side = right) // = alpha * B * transa(A) * t // = alpha * B * w bli_obj_scalar_init_detached( dt_real, &norm ); if ( bli_is_left( side ) ) { bli_obj_create( dt, n, 1, 0, 0, &t ); bli_obj_create( dt, m, 1, 0, 0, &v ); bli_obj_create( dt, m, 1, 0, 0, &w ); bli_obj_create( dt, m, 1, 0, 0, &z ); } else // else if ( bli_is_left( side ) ) { bli_obj_create( dt, n, 1, 0, 0, &t ); bli_obj_create( dt, m, 1, 0, 0, &v ); bli_obj_create( dt, n, 1, 0, 0, &w ); bli_obj_create( dt, m, 1, 0, 0, &z ); } libblis_test_vobj_randomize( params, TRUE, &t ); bli_gemv( &BLIS_ONE, b, &t, &BLIS_ZERO, &v ); if ( bli_is_left( side ) ) { bli_gemv( &BLIS_ONE, b_orig, &t, &BLIS_ZERO, &w ); bli_trmv( alpha, a, &w ); bli_copyv( &w, &z ); } else { bli_copyv( &t, &w ); bli_trmv( &BLIS_ONE, a, &w ); bli_gemv( alpha, b_orig, &w, &BLIS_ZERO, &z ); } bli_subv( &z, &v ); bli_normfv( &v, &norm ); bli_getsc( &norm, resid, &junk ); bli_obj_free( &t ); bli_obj_free( &v ); bli_obj_free( &w ); bli_obj_free( &z ); } blis-0.9.0/testsuite/src/test_trmm.h000066400000000000000000000034771422157504600175010ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void libblis_test_trmm ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); blis-0.9.0/testsuite/src/test_trmm3.c000066400000000000000000000263371422157504600175570ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "test_libblis.h" // Static variables. static char* op_str = "trmm3"; static char* o_types = "mmm"; // a b c static char* p_types = "suhdh"; // side uploa transa diaga transb static thresh_t thresh[BLIS_NUM_FP_TYPES] = { { 1e-04, 1e-05 }, // warn, pass for s { 1e-04, 1e-05 }, // warn, pass for c { 1e-13, 1e-14 }, // warn, pass for d { 1e-13, 1e-14 } }; // warn, pass for z // Local prototypes. void libblis_test_trmm3_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); void libblis_test_trmm3_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ); void libblis_test_trmm3_impl ( iface_t iface, side_t side, obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c ); void libblis_test_trmm3_check ( test_params_t* params, side_t side, obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, obj_t* c_orig, double* resid ); void libblis_test_trmm3_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { libblis_test_randv( tdata, params, &(op->ops->randv) ); libblis_test_randm( tdata, params, &(op->ops->randm) ); libblis_test_setv( tdata, params, &(op->ops->setv) ); libblis_test_normfv( tdata, params, &(op->ops->normfv) ); libblis_test_subv( tdata, params, &(op->ops->subv) ); libblis_test_scalv( tdata, params, &(op->ops->scalv) ); libblis_test_copym( tdata, params, &(op->ops->copym) ); libblis_test_scalm( tdata, params, &(op->ops->scalm) ); libblis_test_gemv( tdata, params, &(op->ops->gemv) ); libblis_test_trmv( tdata, params, &(op->ops->trmv) ); } void libblis_test_trmm3 ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { // Return early if this test has already been done. if ( libblis_test_op_is_done( op ) ) return; // Return early if operation is disabled. if ( libblis_test_op_is_disabled( op ) || libblis_test_l3_is_disabled( op ) ) return; // Call dependencies first. if ( TRUE ) libblis_test_trmm3_deps( tdata, params, op ); // Execute the test driver for each implementation requested. //if ( op->front_seq == ENABLE ) { libblis_test_op_driver( tdata, params, op, BLIS_TEST_SEQ_FRONT_END, op_str, p_types, o_types, thresh, libblis_test_trmm3_experiment ); } } void libblis_test_trmm3_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ) { unsigned int n_repeats = params->n_repeats; unsigned int i; double time_min = DBL_MAX; double time; num_t datatype; dim_t m, n; dim_t mn_side; side_t side; uplo_t uploa; trans_t transa; diag_t diaga; trans_t transb; obj_t alpha, a, b, beta, c; obj_t c_save; // Use the datatype of the first char in the datatype combination string. bli_param_map_char_to_blis_dt( dc_str[0], &datatype ); // Map the dimension specifier to actual dimensions. m = libblis_test_get_dim_from_prob_size( op->dim_spec[0], p_cur ); n = libblis_test_get_dim_from_prob_size( op->dim_spec[1], p_cur ); // Map parameter characters to BLIS constants. bli_param_map_char_to_blis_side( pc_str[0], &side ); bli_param_map_char_to_blis_uplo( pc_str[1], &uploa ); bli_param_map_char_to_blis_trans( pc_str[2], &transa ); bli_param_map_char_to_blis_diag( pc_str[3], &diaga ); bli_param_map_char_to_blis_trans( pc_str[4], &transb ); // Create test scalars. bli_obj_scalar_init_detached( datatype, &alpha ); bli_obj_scalar_init_detached( datatype, &beta ); // Create test operands (vectors and/or matrices). bli_set_dim_with_side( side, m, n, &mn_side ); libblis_test_mobj_create( params, datatype, BLIS_NO_TRANSPOSE, sc_str[1], mn_side, mn_side, &a ); libblis_test_mobj_create( params, datatype, transb, sc_str[2], m, n, &b ); libblis_test_mobj_create( params, datatype, BLIS_NO_TRANSPOSE, sc_str[0], m, n, &c ); libblis_test_mobj_create( params, datatype, BLIS_NO_TRANSPOSE, sc_str[0], m, n, &c_save ); // Set alpha and beta. if ( bli_obj_is_real( &c ) ) { bli_setsc( 0.8, 0.0, &alpha ); bli_setsc( -1.0, 0.0, &beta ); } else { bli_setsc( 0.8, 0.6, &alpha ); bli_setsc( -1.0, 0.5, &beta ); } // Set the structure and uplo properties of A. bli_obj_set_struc( BLIS_TRIANGULAR, &a ); bli_obj_set_uplo( uploa, &a ); // Randomize A, make it densely triangular. libblis_test_mobj_randomize( params, TRUE, &a ); bli_mktrim( &a ); // Randomize B and C, and save C. libblis_test_mobj_randomize( params, TRUE, &b ); libblis_test_mobj_randomize( params, TRUE, &c ); bli_copym( &c, &c_save ); // Apply the remaining parameters. bli_obj_set_conjtrans( transa, &a ); bli_obj_set_diag( diaga, &a ); bli_obj_set_conjtrans( transb, &b ); // Repeat the experiment n_repeats times and record results. for ( i = 0; i < n_repeats; ++i ) { bli_copym( &c_save, &c ); time = bli_clock(); libblis_test_trmm3_impl( iface, side, &alpha, &a, &b, &beta, &c ); time_min = bli_clock_min_diff( time_min, time ); } // Estimate the performance of the best experiment repeat. *perf = ( 1.0 * mn_side * m * n ) / time_min / FLOPS_PER_UNIT_PERF; if ( bli_obj_is_complex( &c ) ) *perf *= 4.0; // Perform checks. libblis_test_trmm3_check( params, side, &alpha, &a, &b, &beta, &c, &c_save, resid ); // Zero out performance and residual if output matrix is empty. libblis_test_check_empty_problem( &c, perf, resid ); // Free the test objects. bli_obj_free( &a ); bli_obj_free( &b ); bli_obj_free( &c ); bli_obj_free( &c_save ); } void libblis_test_trmm3_impl ( iface_t iface, side_t side, obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c ) { switch ( iface ) { case BLIS_TEST_SEQ_FRONT_END: bli_trmm3( side, alpha, a, b, beta, c ); break; default: libblis_test_printf_error( "Invalid interface type.\n" ); } } void libblis_test_trmm3_check ( test_params_t* params, side_t side, obj_t* alpha, obj_t* a, obj_t* b, obj_t* beta, obj_t* c, obj_t* c_orig, double* resid ) { num_t dt = bli_obj_dt( c ); num_t dt_real = bli_obj_dt_proj_to_real( c ); dim_t m = bli_obj_length( c ); dim_t n = bli_obj_width( c ); obj_t norm; obj_t t, v, w, z; double junk; // // Pre-conditions: // - a is randomized and triangular. // - b is randomized. // - c_orig is randomized. // Note: // - alpha and beta should have non-zero imaginary components in the // complex cases in order to more fully exercise the implementation. // // Under these conditions, we assume that the implementation for // // C := beta * C_orig + alpha * transa(A) * transb(B) (side = left) // C := beta * C_orig + alpha * transb(B) * transa(A) (side = right) // // is functioning correctly if // // normfv( v - z ) // // is negligible, where // // v = C * t // // z = ( beta * C_orig + alpha * transa(A) * transb(B) ) * t (side = left) // = beta * C_orig * t + alpha * transa(A) * transb(B) * t // = beta * C_orig * t + alpha * transa(A) * w // = beta * C_orig * t + z // // z = ( beta * C_orig + alpha * transb(B) * transa(A) ) * t (side = right) // = beta * C_orig * t + alpha * transb(B) * transa(A) * t // = beta * C_orig * t + alpha * transb(B) * w // = beta * C_orig * t + z bli_obj_scalar_init_detached( dt_real, &norm ); if ( bli_is_left( side ) ) { bli_obj_create( dt, n, 1, 0, 0, &t ); bli_obj_create( dt, m, 1, 0, 0, &v ); bli_obj_create( dt, m, 1, 0, 0, &w ); bli_obj_create( dt, m, 1, 0, 0, &z ); } else // else if ( bli_is_left( side ) ) { bli_obj_create( dt, n, 1, 0, 0, &t ); bli_obj_create( dt, m, 1, 0, 0, &v ); bli_obj_create( dt, n, 1, 0, 0, &w ); bli_obj_create( dt, m, 1, 0, 0, &z ); } libblis_test_vobj_randomize( params, TRUE, &t ); bli_gemv( &BLIS_ONE, c, &t, &BLIS_ZERO, &v ); if ( bli_is_left( side ) ) { bli_gemv( &BLIS_ONE, b, &t, &BLIS_ZERO, &w ); bli_trmv( alpha, a, &w ); bli_copyv( &w, &z ); } else { bli_copyv( &t, &w ); bli_trmv( &BLIS_ONE, a, &w ); bli_gemv( alpha, b, &w, &BLIS_ZERO, &z ); } bli_gemv( beta, c_orig, &t, &BLIS_ONE, &z ); bli_subv( &z, &v ); bli_normfv( &v, &norm ); bli_getsc( &norm, resid, &junk ); bli_obj_free( &t ); bli_obj_free( &v ); bli_obj_free( &w ); bli_obj_free( &z ); } blis-0.9.0/testsuite/src/test_trmm3.h000066400000000000000000000035001422157504600175470ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void libblis_test_trmm3 ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); blis-0.9.0/testsuite/src/test_trmv.c000066400000000000000000000221211422157504600174700ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "test_libblis.h" // Static variables. static char* op_str = "trmv"; static char* o_types = "mv"; // a x static char* p_types = "uhd"; // uploa transa diaga static thresh_t thresh[BLIS_NUM_FP_TYPES] = { { 1e-04, 1e-05 }, // warn, pass for s { 1e-04, 1e-05 }, // warn, pass for c { 1e-13, 1e-14 }, // warn, pass for d { 1e-13, 1e-14 } }; // warn, pass for z // Local prototypes. void libblis_test_trmv_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); void libblis_test_trmv_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ); void libblis_test_trmv_impl ( iface_t iface, obj_t* alpha, obj_t* a, obj_t* x ); void libblis_test_trmv_check ( test_params_t* params, obj_t* alpha, obj_t* a, obj_t* x, obj_t* x_orig, double* resid ); void libblis_test_trmv_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { libblis_test_randv( tdata, params, &(op->ops->randv) ); libblis_test_randm( tdata, params, &(op->ops->randm) ); libblis_test_normfv( tdata, params, &(op->ops->normfv) ); libblis_test_subv( tdata, params, &(op->ops->subv) ); libblis_test_copyv( tdata, params, &(op->ops->copyv) ); libblis_test_scalv( tdata, params, &(op->ops->scalv) ); libblis_test_gemv( tdata, params, &(op->ops->gemv) ); } void libblis_test_trmv ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { // Return early if this test has already been done. if ( libblis_test_op_is_done( op ) ) return; // Return early if operation is disabled. if ( libblis_test_op_is_disabled( op ) || libblis_test_l2_is_disabled( op ) ) return; // Call dependencies first. if ( TRUE ) libblis_test_trmv_deps( tdata, params, op ); // Execute the test driver for each implementation requested. //if ( op->front_seq == ENABLE ) { libblis_test_op_driver( tdata, params, op, BLIS_TEST_SEQ_FRONT_END, op_str, p_types, o_types, thresh, libblis_test_trmv_experiment ); } } void libblis_test_trmv_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ) { unsigned int n_repeats = params->n_repeats; unsigned int i; double time_min = DBL_MAX; double time; num_t datatype; dim_t m; uplo_t uploa; trans_t transa; diag_t diaga; obj_t alpha, a, x; obj_t x_save; // Use the datatype of the first char in the datatype combination string. bli_param_map_char_to_blis_dt( dc_str[0], &datatype ); // Map the dimension specifier to an actual dimension. m = libblis_test_get_dim_from_prob_size( op->dim_spec[0], p_cur ); // Map parameter characters to BLIS constants. bli_param_map_char_to_blis_uplo( pc_str[0], &uploa ); bli_param_map_char_to_blis_trans( pc_str[1], &transa ); bli_param_map_char_to_blis_diag( pc_str[2], &diaga ); // Create test scalars. bli_obj_scalar_init_detached( datatype, &alpha ); // Create test operands (vectors and/or matrices). libblis_test_mobj_create( params, datatype, BLIS_NO_TRANSPOSE, sc_str[0], m, m, &a ); libblis_test_vobj_create( params, datatype, sc_str[1], m, &x ); libblis_test_vobj_create( params, datatype, sc_str[1], m, &x_save ); // Set alpha. if ( bli_obj_is_real( &x ) ) bli_setsc( -1.0, 0.0, &alpha ); else bli_setsc( -0.5, 0.5, &alpha ); // Set the structure and uplo properties of A. bli_obj_set_struc( BLIS_TRIANGULAR, &a ); bli_obj_set_uplo( uploa, &a ); // Randomize A, make it densely triangular. libblis_test_mobj_randomize( params, TRUE, &a ); //libblis_test_mobj_load_diag( params, &a ); bli_mktrim( &a ); // Randomize x and save. libblis_test_vobj_randomize( params, TRUE, &x ); bli_copyv( &x, &x_save ); // Apply the remaining parameters. bli_obj_set_conjtrans( transa, &a ); bli_obj_set_diag( diaga, &a ); // Repeat the experiment n_repeats times and record results. for ( i = 0; i < n_repeats; ++i ) { bli_copym( &x_save, &x ); time = bli_clock(); libblis_test_trmv_impl( iface, &alpha, &a, &x ); time_min = bli_clock_min_diff( time_min, time ); } // Estimate the performance of the best experiment repeat. *perf = ( 1.0 * m * m ) / time_min / FLOPS_PER_UNIT_PERF; if ( bli_obj_is_complex( &x ) ) *perf *= 4.0; // Perform checks. libblis_test_trmv_check( params, &alpha, &a, &x, &x_save, resid ); // Zero out performance and residual if output vector is empty. libblis_test_check_empty_problem( &x, perf, resid ); // Free the test objects. bli_obj_free( &a ); bli_obj_free( &x ); bli_obj_free( &x_save ); } void libblis_test_trmv_impl ( iface_t iface, obj_t* alpha, obj_t* a, obj_t* x ) { switch ( iface ) { case BLIS_TEST_SEQ_FRONT_END: bli_trmv( alpha, a, x ); break; default: libblis_test_printf_error( "Invalid interface type.\n" ); } } void libblis_test_trmv_check ( test_params_t* params, obj_t* alpha, obj_t* a, obj_t* x, obj_t* x_orig, double* resid ) { num_t dt = bli_obj_dt( x ); num_t dt_real = bli_obj_dt_proj_to_real( x ); dim_t m = bli_obj_vector_dim( x ); uplo_t uploa = bli_obj_uplo( a ); trans_t transa = bli_obj_conjtrans_status( a ); obj_t a_local, y; obj_t norm; double junk; // // Pre-conditions: // - a is randomized and triangular. // - x is randomized. // Note: // - alpha should have a non-zero imaginary component in the // complex cases in order to more fully exercise the implementation. // // Under these conditions, we assume that the implementation for // // x := alpha * transa(A) * x_orig // // is functioning correctly if // // normfv( y - x ) // // is negligible, where // // y = alpha * conja(A_dense) * x_orig // bli_obj_scalar_init_detached( dt_real, &norm ); bli_obj_create( dt, m, 1, 0, 0, &y ); bli_obj_create( dt, m, m, 0, 0, &a_local ); bli_obj_set_struc( BLIS_TRIANGULAR, &a_local ); bli_obj_set_uplo( uploa, &a_local ); bli_obj_toggle_uplo_if_trans( transa, &a_local ); bli_copym( a, &a_local ); bli_mktrim( &a_local ); bli_obj_set_struc( BLIS_GENERAL, &a_local ); bli_obj_set_uplo( BLIS_DENSE, &a_local ); bli_gemv( alpha, &a_local, x_orig, &BLIS_ZERO, &y ); bli_subv( x, &y ); bli_normfv( &y, &norm ); bli_getsc( &norm, resid, &junk ); bli_obj_free( &y ); bli_obj_free( &a_local ); } blis-0.9.0/testsuite/src/test_trmv.h000066400000000000000000000034771422157504600175120ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void libblis_test_trmv ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); blis-0.9.0/testsuite/src/test_trsm.c000066400000000000000000000247601422157504600175000ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "test_libblis.h" // Static variables. static char* op_str = "trsm"; static char* o_types = "mm"; // a b static char* p_types = "suhd"; // side uploa transa diaga static thresh_t thresh[BLIS_NUM_FP_TYPES] = { { 1e-04, 1e-05 }, // warn, pass for s { 1e-04, 1e-05 }, // warn, pass for c { 1e-13, 1e-14 }, // warn, pass for d { 1e-13, 1e-14 } }; // warn, pass for z // Local prototypes. void libblis_test_trsm_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); void libblis_test_trsm_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ); void libblis_test_trsm_impl ( iface_t iface, side_t side, obj_t* alpha, obj_t* a, obj_t* b ); void libblis_test_trsm_check ( test_params_t* params, side_t side, obj_t* alpha, obj_t* a, obj_t* b, obj_t* b_orig, double* resid ); void libblis_test_trsm_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { libblis_test_randv( tdata, params, &(op->ops->randv) ); libblis_test_randm( tdata, params, &(op->ops->randm) ); libblis_test_setv( tdata, params, &(op->ops->setv) ); libblis_test_normfv( tdata, params, &(op->ops->normfv) ); libblis_test_subv( tdata, params, &(op->ops->subv) ); libblis_test_scalv( tdata, params, &(op->ops->scalv) ); libblis_test_copym( tdata, params, &(op->ops->copym) ); libblis_test_scalm( tdata, params, &(op->ops->scalm) ); libblis_test_gemv( tdata, params, &(op->ops->gemv) ); libblis_test_trsv( tdata, params, &(op->ops->trsv) ); } void libblis_test_trsm ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { // Return early if this test has already been done. if ( libblis_test_op_is_done( op ) ) return; // Return early if operation is disabled. if ( libblis_test_op_is_disabled( op ) || libblis_test_l3_is_disabled( op ) ) return; // Call dependencies first. if ( TRUE ) libblis_test_trsm_deps( tdata, params, op ); // Execute the test driver for each implementation requested. //if ( op->front_seq == ENABLE ) { libblis_test_op_driver( tdata, params, op, BLIS_TEST_SEQ_FRONT_END, op_str, p_types, o_types, thresh, libblis_test_trsm_experiment ); } } void libblis_test_trsm_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ) { unsigned int n_repeats = params->n_repeats; unsigned int i; double time_min = DBL_MAX; double time; num_t datatype; dim_t m, n; dim_t mn_side; side_t side; uplo_t uploa; trans_t transa; diag_t diaga; obj_t alpha, a, b; obj_t b_save; // Use the datatype of the first char in the datatype combination string. bli_param_map_char_to_blis_dt( dc_str[0], &datatype ); // Map the dimension specifier to actual dimensions. m = libblis_test_get_dim_from_prob_size( op->dim_spec[0], p_cur ); n = libblis_test_get_dim_from_prob_size( op->dim_spec[1], p_cur ); // Map parameter characters to BLIS constants. bli_param_map_char_to_blis_side( pc_str[0], &side ); bli_param_map_char_to_blis_uplo( pc_str[1], &uploa ); bli_param_map_char_to_blis_trans( pc_str[2], &transa ); bli_param_map_char_to_blis_diag( pc_str[3], &diaga ); // Create test scalars. bli_obj_scalar_init_detached( datatype, &alpha ); // Create test operands (vectors and/or matrices). bli_set_dim_with_side( side, m, n, &mn_side ); libblis_test_mobj_create( params, datatype, transa, sc_str[1], mn_side, mn_side, &a ); libblis_test_mobj_create( params, datatype, BLIS_NO_TRANSPOSE, sc_str[0], m, n, &b ); libblis_test_mobj_create( params, datatype, BLIS_NO_TRANSPOSE, sc_str[0], m, n, &b_save ); // Set alpha. if ( bli_obj_is_real( &b ) ) { bli_setsc( 2.0, 0.0, &alpha ); } else { bli_setsc( 2.0, 0.0, &alpha ); } // Set the structure and uplo properties of A. bli_obj_set_struc( BLIS_TRIANGULAR, &a ); bli_obj_set_uplo( uploa, &a ); // Randomize A, load the diagonal, make it densely triangular. libblis_test_mobj_randomize( params, TRUE, &a ); libblis_test_mobj_load_diag( params, &a ); bli_mktrim( &a ); // Randomize B and save B. libblis_test_mobj_randomize( params, TRUE, &b ); bli_copym( &b, &b_save ); // Apply the remaining parameters. bli_obj_set_conjtrans( transa, &a ); bli_obj_set_diag( diaga, &a ); // Repeat the experiment n_repeats times and record results. for ( i = 0; i < n_repeats; ++i ) { bli_copym( &b_save, &b ); time = bli_clock(); libblis_test_trsm_impl( iface, side, &alpha, &a, &b ); time_min = bli_clock_min_diff( time_min, time ); } // Estimate the performance of the best experiment repeat. *perf = ( 1.0 * mn_side * m * n ) / time_min / FLOPS_PER_UNIT_PERF; if ( bli_obj_is_complex( &b ) ) *perf *= 4.0; // Perform checks. libblis_test_trsm_check( params, side, &alpha, &a, &b, &b_save, resid ); // Zero out performance and residual if output matrix is empty. libblis_test_check_empty_problem( &b, perf, resid ); // Free the test objects. bli_obj_free( &a ); bli_obj_free( &b ); bli_obj_free( &b_save ); } void libblis_test_trsm_impl ( iface_t iface, side_t side, obj_t* alpha, obj_t* a, obj_t* b ) { switch ( iface ) { case BLIS_TEST_SEQ_FRONT_END: #if 0 bli_printm( "a", a, "%5.2f", "" ); bli_printm( "b", b, "%5.2f", "" ); //bli_printm( "alpha", alpha, "%5.2f", "" ); #endif bli_trsm( side, alpha, a, b ); #if 0 bli_printm( "b after", b, "%5.2f", "" ); #endif break; default: libblis_test_printf_error( "Invalid interface type.\n" ); } } void libblis_test_trsm_check ( test_params_t* params, side_t side, obj_t* alpha, obj_t* a, obj_t* b, obj_t* b_orig, double* resid ) { num_t dt = bli_obj_dt( b ); num_t dt_real = bli_obj_dt_proj_to_real( b ); dim_t m = bli_obj_length( b ); dim_t n = bli_obj_width( b ); obj_t norm; obj_t t, v, w, z; double junk; // // Pre-conditions: // - a is randomized and triangular. // - b_orig is randomized. // Note: // - alpha should have a non-zero imaginary component in the // complex cases in order to more fully exercise the implementation. // // Under these conditions, we assume that the implementation for // // B := alpha * inv(transa(A)) * B_orig (side = left) // B := alpha * B_orig * inv(transa(A)) (side = right) // // is functioning correctly if // // normfv( v - z ) // // is negligible, where // // v = B * t // // z = ( alpha * inv(transa(A)) * B ) * t (side = left) // = alpha * inv(transa(A)) * B * t // = alpha * inv(transa(A)) * w // // z = ( alpha * B * inv(transa(A)) ) * t (side = right) // = alpha * B * tinv(ransa(A)) * t // = alpha * B * w bli_obj_scalar_init_detached( dt_real, &norm ); if ( bli_is_left( side ) ) { bli_obj_create( dt, n, 1, 0, 0, &t ); bli_obj_create( dt, m, 1, 0, 0, &v ); bli_obj_create( dt, m, 1, 0, 0, &w ); bli_obj_create( dt, m, 1, 0, 0, &z ); } else // else if ( bli_is_left( side ) ) { bli_obj_create( dt, n, 1, 0, 0, &t ); bli_obj_create( dt, m, 1, 0, 0, &v ); bli_obj_create( dt, n, 1, 0, 0, &w ); bli_obj_create( dt, m, 1, 0, 0, &z ); } libblis_test_vobj_randomize( params, TRUE, &t ); bli_gemv( &BLIS_ONE, b, &t, &BLIS_ZERO, &v ); if ( bli_is_left( side ) ) { bli_gemv( alpha, b_orig, &t, &BLIS_ZERO, &w ); bli_trsv( &BLIS_ONE, a, &w ); bli_copyv( &w, &z ); } else { bli_copyv( &t, &w ); bli_trsv( &BLIS_ONE, a, &w ); bli_gemv( alpha, b_orig, &w, &BLIS_ZERO, &z ); } bli_subv( &z, &v ); bli_normfv( &v, &norm ); bli_getsc( &norm, resid, &junk ); bli_obj_free( &t ); bli_obj_free( &v ); bli_obj_free( &w ); bli_obj_free( &z ); } blis-0.9.0/testsuite/src/test_trsm.h000066400000000000000000000034771422157504600175070ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void libblis_test_trsm ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); blis-0.9.0/testsuite/src/test_trsm_ukr.c000066400000000000000000000274611422157504600203620ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "test_libblis.h" // Static variables. static char* op_str = "trsm_ukr"; static char* o_types = "m"; // c static char* p_types = "u"; // uploa static thresh_t thresh[BLIS_NUM_FP_TYPES] = { { 1e-04, 1e-05 }, // warn, pass for s { 1e-04, 1e-05 }, // warn, pass for c { 1e-13, 1e-14 }, // warn, pass for d { 1e-13, 1e-14 } }; // warn, pass for z // Local prototypes. void libblis_test_trsm_ukr_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); void libblis_test_trsm_ukr_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ); void libblis_test_trsm_ukr_impl ( iface_t iface, side_t side, obj_t* a, obj_t* b, obj_t* c, cntx_t* cntx ); void libblis_test_trsm_ukr_check ( test_params_t* params, side_t side, obj_t* a, obj_t* b, obj_t* b_orig, double* resid ); void libblis_test_trsm_ukr_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { libblis_test_randv( tdata, params, &(op->ops->randv) ); libblis_test_randm( tdata, params, &(op->ops->randm) ); libblis_test_setv( tdata, params, &(op->ops->setv) ); libblis_test_normfv( tdata, params, &(op->ops->normfv) ); libblis_test_subv( tdata, params, &(op->ops->subv) ); libblis_test_scalv( tdata, params, &(op->ops->scalv) ); libblis_test_copym( tdata, params, &(op->ops->copym) ); libblis_test_scalm( tdata, params, &(op->ops->scalm) ); libblis_test_gemv( tdata, params, &(op->ops->gemv) ); libblis_test_trsv( tdata, params, &(op->ops->trsv) ); } void libblis_test_trsm_ukr ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { // Return early if this test has already been done. if ( libblis_test_op_is_done( op ) ) return; // Return early if operation is disabled. if ( libblis_test_op_is_disabled( op ) || libblis_test_l3ukr_is_disabled( op ) ) return; // Call dependencies first. if ( TRUE ) libblis_test_trsm_ukr_deps( tdata, params, op ); // Execute the test driver for each implementation requested. //if ( op->front_seq == ENABLE ) { libblis_test_op_driver( tdata, params, op, BLIS_TEST_SEQ_UKERNEL, op_str, p_types, o_types, thresh, libblis_test_trsm_ukr_experiment ); } } // Import the register blocksizes used by the micro-kernel(s). extern blksz_t* gemm_mr; extern blksz_t* gemm_nr; extern blksz_t* gemm_kr; void libblis_test_trsm_ukr_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ) { unsigned int n_repeats = params->n_repeats; unsigned int i; double time_min = DBL_MAX; double time; num_t datatype; dim_t m, n; char sc_a = 'c'; char sc_b = 'r'; side_t side = BLIS_LEFT; uplo_t uploa; obj_t a, b, c; obj_t ap, bp; obj_t c_save; cntx_t* cntx; // Query a context. cntx = bli_gks_query_cntx(); // Use the datatype of the first char in the datatype combination string. bli_param_map_char_to_blis_dt( dc_str[0], &datatype ); // Fix m and n to MR and NR, respectively. m = bli_cntx_get_blksz_def_dt( datatype, BLIS_MR, cntx ); n = bli_cntx_get_blksz_def_dt( datatype, BLIS_NR, cntx ); // Store the register blocksizes so that the driver can retrieve the // values later when printing results. op->dim_aux[0] = m; op->dim_aux[1] = n; // Map parameter characters to BLIS constants. bli_param_map_char_to_blis_uplo( pc_str[0], &uploa ); // Create test scalars. // Create test operands (vectors and/or matrices). libblis_test_mobj_create( params, datatype, BLIS_NO_TRANSPOSE, sc_a, m, m, &a ); libblis_test_mobj_create( params, datatype, BLIS_NO_TRANSPOSE, sc_b, m, n, &b ); libblis_test_mobj_create( params, datatype, BLIS_NO_TRANSPOSE, sc_str[0], m, n, &c ); libblis_test_mobj_create( params, datatype, BLIS_NO_TRANSPOSE, sc_str[0], m, n, &c_save ); // Set the structure, uplo, and diagonal offset properties of A. bli_obj_set_struc( BLIS_TRIANGULAR, &a ); bli_obj_set_uplo( uploa, &a ); bli_obj_set_diag_offset( 0, &a ); // Randomize A, make it densely triangular. libblis_test_mobj_randomize( params, TRUE, &a ); libblis_test_mobj_load_diag( params, &a ); bli_mktrim( &a ); // Randomize B. libblis_test_mobj_randomize( params, TRUE, &b ); // Randomize C and save C. libblis_test_mobj_randomize( params, TRUE, &c ); bli_copym( &c, &c_save ); rntm_t rntm; bli_rntm_init( &rntm ); bli_pba_rntm_set_pba( &rntm ); // Create pack objects for a and b, and pack them to ap and bp, // respectively. cntl_t* cntl_a = libblis_test_pobj_create ( BLIS_MR, BLIS_MR, BLIS_INVERT_DIAG, BLIS_PACKED_ROW_PANELS, BLIS_BUFFER_FOR_A_BLOCK, &a, &ap, cntx, &rntm ); // Set the diagonal offset of ap. bli_obj_set_diag_offset( 0, &ap ); // Set the uplo field of ap since the default for packed objects is // BLIS_DENSE, and the _ukernel() wrapper needs this information to // know which set of micro-kernels (lower or upper) to choose from. bli_obj_set_uplo( uploa, &ap ); #if 0 bli_printm( "a", &a, "%5.2f", "" ); bli_printm( "ap", &ap, "%5.2f", "" ); #endif // Repeat the experiment n_repeats times and record results. for ( i = 0; i < n_repeats; ++i ) { bli_copym( &c_save, &c ); // Transpose B to B^T for packing. bli_obj_induce_trans( &b ); cntl_t* cntl_b = libblis_test_pobj_create ( BLIS_NR, BLIS_MR, BLIS_NO_INVERT_DIAG, BLIS_PACKED_COL_PANELS, BLIS_BUFFER_FOR_B_PANEL, &b, &bp, cntx, &rntm ); // Transpose B^T back to B and Bp^T back to Bp. bli_obj_induce_trans( &b ); bli_obj_induce_trans( &bp ); time = bli_clock(); libblis_test_trsm_ukr_impl( iface, side, &ap, &bp, &c, cntx ); time_min = bli_clock_min_diff( time_min, time ); // Free the control tree nodes and release their cached mem_t entries // back to the memory broker. bli_cntl_free( &rntm, cntl_b, &BLIS_PACKM_SINGLE_THREADED ); } // Estimate the performance of the best experiment repeat. *perf = ( 1.0 * m * m * n ) / time_min / FLOPS_PER_UNIT_PERF; if ( bli_obj_is_complex( &b ) ) *perf *= 4.0; // Perform checks. libblis_test_trsm_ukr_check( params, side, &ap, &c, &b, resid ); // Zero out performance and residual if output matrix is empty. //libblis_test_check_empty_problem( &c, perf, resid ); // Free the control tree nodes and release their cached mem_t entries // back to the memory broker. bli_cntl_free( &rntm, cntl_a, &BLIS_PACKM_SINGLE_THREADED ); // Free the test objects. bli_obj_free( &a ); bli_obj_free( &b ); bli_obj_free( &c ); bli_obj_free( &c_save ); } void libblis_test_trsm_ukr_impl ( iface_t iface, side_t side, obj_t* a, obj_t* b, obj_t* c, cntx_t* cntx ) { switch ( iface ) { case BLIS_TEST_SEQ_UKERNEL: bli_trsm_ukernel( a, b, c, cntx ); break; default: libblis_test_printf_error( "Invalid interface type.\n" ); } } void libblis_test_trsm_ukr_check ( test_params_t* params, side_t side, obj_t* a, obj_t* b, obj_t* b_orig, double* resid ) { num_t dt = bli_obj_dt( b ); num_t dt_real = bli_obj_dt_proj_to_real( b ); dim_t m = bli_obj_length( b ); dim_t n = bli_obj_width( b ); obj_t norm; obj_t t, v, w, z; double junk; // // Pre-conditions: // - a is randomized and triangular. // - b_orig is randomized. // // Under these conditions, we assume that the implementation for // // B := inv(transa(A)) * B_orig (side = left) // B := B_orig * inv(transa(A)) (side = right) // // is functioning correctly if // // normfv( v - z ) // // is negligible, where // // v = B * t // // z = ( inv(transa(A)) * B ) * t (side = left) // = inv(transa(A)) * B * t // = inv(transa(A)) * w // // z = ( B * inv(transa(A)) ) * t (side = right) // = B * tinv(ransa(A)) * t // = B * w bli_obj_scalar_init_detached( dt_real, &norm ); if ( bli_is_left( side ) ) { bli_obj_create( dt, n, 1, 0, 0, &t ); bli_obj_create( dt, m, 1, 0, 0, &v ); bli_obj_create( dt, m, 1, 0, 0, &w ); bli_obj_create( dt, m, 1, 0, 0, &z ); } else // else if ( bli_is_left( side ) ) { bli_obj_create( dt, n, 1, 0, 0, &t ); bli_obj_create( dt, m, 1, 0, 0, &v ); bli_obj_create( dt, n, 1, 0, 0, &w ); bli_obj_create( dt, m, 1, 0, 0, &z ); } libblis_test_vobj_randomize( params, TRUE, &t ); bli_gemv( &BLIS_ONE, b, &t, &BLIS_ZERO, &v ); #if 0 bli_printm( "a11", a, "%5.2f", "" ); #endif // Restore the diagonal of a11 to its original, un-inverted state // (needed for trsv). bli_invertd( a ); if ( bli_is_left( side ) ) { bli_gemv( &BLIS_ONE, b_orig, &t, &BLIS_ZERO, &w ); bli_trsv( &BLIS_ONE, a, &w ); bli_copyv( &w, &z ); } else { bli_copyv( &t, &w ); bli_trsv( &BLIS_ONE, a, &w ); bli_gemv( &BLIS_ONE, b_orig, &w, &BLIS_ZERO, &z ); } bli_subv( &z, &v ); bli_normfv( &v, &norm ); bli_getsc( &norm, resid, &junk ); bli_obj_free( &t ); bli_obj_free( &v ); bli_obj_free( &w ); bli_obj_free( &z ); } blis-0.9.0/testsuite/src/test_trsm_ukr.h000066400000000000000000000035031422157504600203560ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void libblis_test_trsm_ukr ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); blis-0.9.0/testsuite/src/test_trsv.c000066400000000000000000000224021422157504600175000ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "test_libblis.h" // Static variables. static char* op_str = "trsv"; static char* o_types = "mv"; // a x static char* p_types = "uhd"; // uploa transa diaga static thresh_t thresh[BLIS_NUM_FP_TYPES] = { { 1e-04, 1e-05 }, // warn, pass for s { 1e-04, 1e-05 }, // warn, pass for c { 1e-13, 1e-14 }, // warn, pass for d { 1e-13, 1e-14 } }; // warn, pass for z // Local prototypes. void libblis_test_trsv_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); void libblis_test_trsv_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ); void libblis_test_trsv_impl ( iface_t iface, obj_t* alpha, obj_t* a, obj_t* x ); void libblis_test_trsv_check ( test_params_t* params, obj_t* alpha, obj_t* a, obj_t* x, obj_t* x_orig, double* resid ); void libblis_test_trsv_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { libblis_test_randv( tdata, params, &(op->ops->randv) ); libblis_test_randm( tdata, params, &(op->ops->randm) ); libblis_test_normfv( tdata, params, &(op->ops->normfv) ); libblis_test_subv( tdata, params, &(op->ops->subv) ); libblis_test_copyv( tdata, params, &(op->ops->copyv) ); libblis_test_scalv( tdata, params, &(op->ops->scalv) ); libblis_test_gemv( tdata, params, &(op->ops->gemv) ); } void libblis_test_trsv ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { // Return early if this test has already been done. if ( libblis_test_op_is_done( op ) ) return; // Return early if operation is disabled. if ( libblis_test_op_is_disabled( op ) || libblis_test_l2_is_disabled( op ) ) return; // Call dependencies first. if ( TRUE ) libblis_test_trsv_deps( tdata, params, op ); // Execute the test driver for each implementation requested. //if ( op->front_seq == ENABLE ) { libblis_test_op_driver( tdata, params, op, BLIS_TEST_SEQ_FRONT_END, op_str, p_types, o_types, thresh, libblis_test_trsv_experiment ); } } void libblis_test_trsv_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ) { unsigned int n_repeats = params->n_repeats; unsigned int i; double time_min = DBL_MAX; double time; num_t datatype; dim_t m; uplo_t uploa; trans_t transa; diag_t diaga; obj_t alpha, a, x; obj_t x_save; // Use the datatype of the first char in the datatype combination string. bli_param_map_char_to_blis_dt( dc_str[0], &datatype ); // Map the dimension specifier to an actual dimension. m = libblis_test_get_dim_from_prob_size( op->dim_spec[0], p_cur ); // Map parameter characters to BLIS constants. bli_param_map_char_to_blis_uplo( pc_str[0], &uploa ); bli_param_map_char_to_blis_trans( pc_str[1], &transa ); bli_param_map_char_to_blis_diag( pc_str[2], &diaga ); // Create test scalars. bli_obj_scalar_init_detached( datatype, &alpha ); // Create test operands (vectors and/or matrices). libblis_test_mobj_create( params, datatype, BLIS_NO_TRANSPOSE, sc_str[0], m, m, &a ); libblis_test_vobj_create( params, datatype, sc_str[1], m, &x ); libblis_test_vobj_create( params, datatype, sc_str[1], m, &x_save ); // Set alpha. if ( bli_obj_is_real( &x ) ) bli_setsc( 2.0, 0.0, &alpha ); else bli_setsc( 2.0, -1.0, &alpha ); // Set the structure and uplo properties of A. bli_obj_set_struc( BLIS_TRIANGULAR, &a ); bli_obj_set_uplo( uploa, &a ); // Randomize A, load the diagonal, make it densely triangular. libblis_test_mobj_randomize( params, TRUE, &a ); libblis_test_mobj_load_diag( params, &a ); bli_mktrim( &a ); // Randomize x and save. libblis_test_vobj_randomize( params, TRUE, &x ); bli_copyv( &x, &x_save ); // Apply the remaining parameters. bli_obj_set_conjtrans( transa, &a ); bli_obj_set_diag( diaga, &a ); // Repeat the experiment n_repeats times and record results. for ( i = 0; i < n_repeats; ++i ) { bli_copym( &x_save, &x ); time = bli_clock(); libblis_test_trsv_impl( iface, &alpha, &a, &x ); time_min = bli_clock_min_diff( time_min, time ); } // Estimate the performance of the best experiment repeat. *perf = ( 1.0 * m * m ) / time_min / FLOPS_PER_UNIT_PERF; if ( bli_obj_is_complex( &x ) ) *perf *= 4.0; // Perform checks. libblis_test_trsv_check( params, &alpha, &a, &x, &x_save, resid ); // Zero out performance and residual if output vector is empty. libblis_test_check_empty_problem( &x, perf, resid ); // Free the test objects. bli_obj_free( &a ); bli_obj_free( &x ); bli_obj_free( &x_save ); } void libblis_test_trsv_impl ( iface_t iface, obj_t* alpha, obj_t* a, obj_t* x ) { switch ( iface ) { case BLIS_TEST_SEQ_FRONT_END: bli_trsv( alpha, a, x ); break; default: libblis_test_printf_error( "Invalid interface type.\n" ); } } void libblis_test_trsv_check ( test_params_t* params, obj_t* alpha, obj_t* a, obj_t* x, obj_t* x_orig, double* resid ) { num_t dt = bli_obj_dt( x ); num_t dt_real = bli_obj_dt_proj_to_real( x ); dim_t m = bli_obj_vector_dim( x ); uplo_t uploa = bli_obj_uplo( a ); trans_t transa = bli_obj_conjtrans_status( a ); obj_t alpha_inv; obj_t a_local, y; obj_t norm; double junk; // // Pre-conditions: // - a is randomized and triangular. // - x is randomized. // Note: // - alpha should have a non-zero imaginary component in the // complex cases in order to more fully exercise the implementation. // // Under these conditions, we assume that the implementation for // // x := alpha * inv(transa(A)) * x_orig // // is functioning correctly if // // normfv( y - x_orig ) // // is negligible, where // // y = inv(alpha) * transa(A_dense) * x // bli_obj_scalar_init_detached( dt, &alpha_inv ); bli_obj_scalar_init_detached( dt_real, &norm ); bli_copysc( &BLIS_ONE, &alpha_inv ); bli_divsc( alpha, &alpha_inv ); bli_obj_create( dt, m, 1, 0, 0, &y ); bli_obj_create( dt, m, m, 0, 0, &a_local ); bli_obj_set_struc( BLIS_TRIANGULAR, &a_local ); bli_obj_set_uplo( uploa, &a_local ); bli_obj_toggle_uplo_if_trans( transa, &a_local ); bli_copym( a, &a_local ); bli_mktrim( &a_local ); bli_obj_set_struc( BLIS_GENERAL, &a_local ); bli_obj_set_uplo( BLIS_DENSE, &a_local ); bli_gemv( &alpha_inv, &a_local, x, &BLIS_ZERO, &y ); bli_subv( x_orig, &y ); bli_normfv( &y, &norm ); bli_getsc( &norm, resid, &junk ); bli_obj_free( &y ); bli_obj_free( &a_local ); } blis-0.9.0/testsuite/src/test_trsv.h000066400000000000000000000034771422157504600175200ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void libblis_test_trsv ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); blis-0.9.0/testsuite/src/test_xpbym.c000066400000000000000000000206001422157504600176370ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2018, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "test_libblis.h" // Static variables. static char* op_str = "xpbym"; static char* o_types = "mm"; // x y static char* p_types = "h"; // transx static thresh_t thresh[BLIS_NUM_FP_TYPES] = { { 1e-04, 1e-05 }, // warn, pass for s { 1e-04, 1e-05 }, // warn, pass for c { 1e-13, 1e-14 }, // warn, pass for d { 1e-13, 1e-14 } }; // warn, pass for z // Local prototypes. void libblis_test_xpbym_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); void libblis_test_xpbym_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ); void libblis_test_xpbym_impl ( iface_t iface, obj_t* x, obj_t* beta, obj_t* y ); void libblis_test_xpbym_check ( test_params_t* params, obj_t* x, obj_t* beta, obj_t* y, obj_t* y_save, double* resid ); void libblis_test_xpbym_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { libblis_test_randm( tdata, params, &(op->ops->randm) ); libblis_test_normfm( tdata, params, &(op->ops->normfm) ); libblis_test_addm( tdata, params, &(op->ops->addm) ); libblis_test_subm( tdata, params, &(op->ops->subm) ); libblis_test_copym( tdata, params, &(op->ops->copym) ); libblis_test_scalm( tdata, params, &(op->ops->scalm) ); } void libblis_test_xpbym ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { // Return early if this test has already been done. if ( libblis_test_op_is_done( op ) ) return; // Return early if operation is disabled. if ( libblis_test_op_is_disabled( op ) || libblis_test_l1m_is_disabled( op ) ) return; // Call dependencies first. if ( TRUE ) libblis_test_xpbym_deps( tdata, params, op ); // Execute the test driver for each implementation requested. //if ( op->front_seq == ENABLE ) { libblis_test_op_driver( tdata, params, op, BLIS_TEST_SEQ_FRONT_END, op_str, p_types, o_types, thresh, libblis_test_xpbym_experiment ); } } void libblis_test_xpbym_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ) { unsigned int n_repeats = params->n_repeats; unsigned int i; double time_min = DBL_MAX; double time; num_t datatype; dim_t m, n; trans_t transx; obj_t x, beta, y; obj_t y_save; // Use the datatype of the first char in the datatype combination string. bli_param_map_char_to_blis_dt( dc_str[0], &datatype ); // Map the dimension specifier to actual dimensions. m = libblis_test_get_dim_from_prob_size( op->dim_spec[0], p_cur ); n = libblis_test_get_dim_from_prob_size( op->dim_spec[1], p_cur ); // Map parameter characters to BLIS constants. bli_param_map_char_to_blis_trans( pc_str[0], &transx ); // Create test scalars. bli_obj_scalar_init_detached( datatype, &beta ); // Create test operands (vectors and/or matrices). libblis_test_mobj_create( params, datatype, transx, sc_str[0], m, n, &x ); libblis_test_mobj_create( params, datatype, BLIS_NO_TRANSPOSE, sc_str[0], m, n, &y ); libblis_test_mobj_create( params, datatype, BLIS_NO_TRANSPOSE, sc_str[0], m, n, &y_save ); // Set beta. if ( bli_obj_is_real( &y ) ) bli_setsc( -2.0, 0.0, &beta ); else bli_setsc( 0.0, -2.0, &beta ); // Randomize and save y. libblis_test_mobj_randomize( params, FALSE, &x ); libblis_test_mobj_randomize( params, FALSE, &y ); bli_copym( &y, &y_save ); // Apply the parameters. bli_obj_set_conjtrans( transx, &x ); // Repeat the experiment n_repeats times and record results. for ( i = 0; i < n_repeats; ++i ) { bli_copym( &y_save, &y ); time = bli_clock(); libblis_test_xpbym_impl( iface, &x, &beta, &y ); time_min = bli_clock_min_diff( time_min, time ); } // Estimate the performance of the best experiment repeat. *perf = ( 2.0 * m * n ) / time_min / FLOPS_PER_UNIT_PERF; if ( bli_obj_is_complex( &y ) ) *perf *= 4.0; // Perform checks. libblis_test_xpbym_check( params, &x, &beta, &y, &y_save, resid ); // Zero out performance and residual if output matrix is empty. libblis_test_check_empty_problem( &y, perf, resid ); // Free the test objects. bli_obj_free( &x ); bli_obj_free( &y ); bli_obj_free( &y_save ); } void libblis_test_xpbym_impl ( iface_t iface, obj_t* x, obj_t* beta, obj_t* y ) { switch ( iface ) { case BLIS_TEST_SEQ_FRONT_END: bli_xpbym( x, beta, y ); break; default: libblis_test_printf_error( "Invalid interface type.\n" ); } } void libblis_test_xpbym_check ( test_params_t* params, obj_t* x, obj_t* beta, obj_t* y, obj_t* y_orig, double* resid ) { num_t dt = bli_obj_dt( y ); num_t dt_real = bli_obj_dt_proj_to_real( y ); dim_t m = bli_obj_length( y ); dim_t n = bli_obj_width( y ); obj_t x_temp, y_temp; obj_t norm; double junk; // // Pre-conditions: // - x is randomized. // - y_orig is randomized. // Note: // - alpha should have a non-zero imaginary component in the complex // cases in order to more fully exercise the implementation. // // Under these conditions, we assume that the implementation for // // y := beta * y_orig + conjx(x) // // is functioning correctly if // // normfm( y - ( beta * y_orig + conjx(x) ) ) // // is negligible. // bli_obj_scalar_init_detached( dt_real, &norm ); bli_obj_create( dt, m, n, 0, 0, &x_temp ); bli_obj_create( dt, m, n, 0, 0, &y_temp ); bli_copym( x, &x_temp ); bli_copym( y_orig, &y_temp ); bli_scalm( beta, &y_temp ); bli_addm( &x_temp, &y_temp ); bli_subm( &y_temp, y ); bli_normfm( y, &norm ); bli_getsc( &norm, resid, &junk ); bli_obj_free( &x_temp ); bli_obj_free( &y_temp ); } blis-0.9.0/testsuite/src/test_xpbym.h000066400000000000000000000034051422157504600176500ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2018, The University of Texas at Austin 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void libblis_test_xpbym ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); blis-0.9.0/testsuite/src/test_xpbyv.c000066400000000000000000000201571422157504600176570ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include "blis.h" #include "test_libblis.h" // Static variables. static char* op_str = "xpbyv"; static char* o_types = "vv"; // x y static char* p_types = "c"; // conjx static thresh_t thresh[BLIS_NUM_FP_TYPES] = { { 1e-04, 1e-05 }, // warn, pass for s { 1e-04, 1e-05 }, // warn, pass for c { 1e-13, 1e-14 }, // warn, pass for d { 1e-13, 1e-14 } }; // warn, pass for z // Local prototypes. void libblis_test_xpbyv_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); void libblis_test_xpbyv_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ); void libblis_test_xpbyv_impl ( iface_t iface, obj_t* x, obj_t* beta, obj_t* y ); void libblis_test_xpbyv_check ( test_params_t* params, obj_t* x, obj_t* beta, obj_t* y, obj_t* y_orig, double* resid ); void libblis_test_xpbyv_deps ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { libblis_test_randv( tdata, params, &(op->ops->randv) ); libblis_test_normfv( tdata, params, &(op->ops->normfv) ); libblis_test_addv( tdata, params, &(op->ops->addv) ); libblis_test_subv( tdata, params, &(op->ops->subv) ); libblis_test_copyv( tdata, params, &(op->ops->copyv) ); } void libblis_test_xpbyv ( thread_data_t* tdata, test_params_t* params, test_op_t* op ) { // Return early if this test has already been done. if ( libblis_test_op_is_done( op ) ) return; // Return early if operation is disabled. if ( libblis_test_op_is_disabled( op ) || libblis_test_l1v_is_disabled( op ) ) return; // Call dependencies first. if ( TRUE ) libblis_test_xpbyv_deps( tdata, params, op ); // Execute the test driver for each implementation requested. //if ( op->front_seq == ENABLE ) { libblis_test_op_driver( tdata, params, op, BLIS_TEST_SEQ_FRONT_END, op_str, p_types, o_types, thresh, libblis_test_xpbyv_experiment ); } } void libblis_test_xpbyv_experiment ( test_params_t* params, test_op_t* op, iface_t iface, char* dc_str, char* pc_str, char* sc_str, unsigned int p_cur, double* perf, double* resid ) { unsigned int n_repeats = params->n_repeats; unsigned int i; double time_min = DBL_MAX; double time; num_t datatype; dim_t m; conj_t conjx; obj_t beta, x, y; obj_t y_save; // Use the datatype of the first char in the datatype combination string. bli_param_map_char_to_blis_dt( dc_str[0], &datatype ); // Map the dimension specifier to an actual dimension. m = libblis_test_get_dim_from_prob_size( op->dim_spec[0], p_cur ); // Map parameter characters to BLIS constants. bli_param_map_char_to_blis_conj( pc_str[0], &conjx ); // Create test scalars. bli_obj_scalar_init_detached( datatype, &beta ); // Create test operands (vectors and/or matrices). libblis_test_vobj_create( params, datatype, sc_str[0], m, &x ); libblis_test_vobj_create( params, datatype, sc_str[1], m, &y ); libblis_test_vobj_create( params, datatype, sc_str[1], m, &y_save ); // Set beta. if ( bli_obj_is_real( &y ) ) bli_setsc( -2.0, 0.0, &beta ); else bli_setsc( 0.0, -2.0, &beta ); // Randomize x and y, and save y. libblis_test_vobj_randomize( params, FALSE, &x ); libblis_test_vobj_randomize( params, FALSE, &y ); bli_copyv( &y, &y_save ); // Apply the parameters. bli_obj_set_conj( conjx, &x ); // Repeat the experiment n_repeats times and record results. for ( i = 0; i < n_repeats; ++i ) { bli_copyv( &y_save, &y ); time = bli_clock(); libblis_test_xpbyv_impl( iface, &x, &beta, &y ); time_min = bli_clock_min_diff( time_min, time ); } // Estimate the performance of the best experiment repeat. *perf = ( 2.0 * m ) / time_min / FLOPS_PER_UNIT_PERF; if ( bli_obj_is_complex( &y ) ) *perf *= 4.0; // Perform checks. libblis_test_xpbyv_check( params, &x, &beta, &y, &y_save, resid ); // Zero out performance and residual if output vector is empty. libblis_test_check_empty_problem( &y, perf, resid ); // Free the test objects. bli_obj_free( &x ); bli_obj_free( &y ); bli_obj_free( &y_save ); } void libblis_test_xpbyv_impl ( iface_t iface, obj_t* x, obj_t* beta, obj_t* y ) { switch ( iface ) { case BLIS_TEST_SEQ_FRONT_END: bli_xpbyv( x, beta, y ); break; default: libblis_test_printf_error( "Invalid interface type.\n" ); } } void libblis_test_xpbyv_check ( test_params_t* params, obj_t* x, obj_t* beta, obj_t* y, obj_t* y_orig, double* resid ) { num_t dt = bli_obj_dt( y ); num_t dt_real = bli_obj_dt_proj_to_real( y ); dim_t m = bli_obj_vector_dim( y ); obj_t x_temp, y_temp; obj_t norm; double junk; // // Pre-conditions: // - x is randomized. // - y_orig is randomized. // Note: // - beta should have a non-zero imaginary component in the complex // cases in order to more fully exercise the implementation. // // Under these conditions, we assume that the implementation for // // y := beta * y_orig + conjx(x) // // is functioning correctly if // // normfv( y - ( beta * y_orig + conjx(x) ) ) // // is negligible. // bli_obj_scalar_init_detached( dt_real, &norm ); bli_obj_create( dt, m, 1, 0, 0, &x_temp ); bli_obj_create( dt, m, 1, 0, 0, &y_temp ); bli_copyv( x, &x_temp ); bli_copyv( y_orig, &y_temp ); bli_scalv( beta, &y_temp ); bli_addv( &x_temp, &y_temp ); bli_subv( &y_temp, y ); bli_normfv( y, &norm ); bli_getsc( &norm, resid, &junk ); bli_obj_free( &x_temp ); bli_obj_free( &y_temp ); } blis-0.9.0/testsuite/src/test_xpbyv.h000066400000000000000000000035001422157504600176550ustar00rootroot00000000000000/* BLIS An object-based framework for developing high-performance BLAS-like libraries. Copyright (C) 2014, The University of Texas at Austin Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ void libblis_test_xpbyv ( thread_data_t* tdata, test_params_t* params, test_op_t* op ); blis-0.9.0/travis/000077500000000000000000000000001422157504600137675ustar00rootroot00000000000000blis-0.9.0/travis/cpuid/000077500000000000000000000000001422157504600150735ustar00rootroot00000000000000blis-0.9.0/travis/cpuid/excavator.def000066400000000000000000000103061422157504600175470ustar00rootroot00000000000000# # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2018, The University of Texas at Austin # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # CPU: AMD A12-8870, 4000 MHz # 00000000 ******** => 0000000D 68747541 444D4163 69746E65 00000001 ******** => 00660F51 00040800 7ED8320B 178BFBFF 00000002 ******** => 00000000 00000000 00000000 00000000 00000003 ******** => 00000000 00000000 00000000 00000000 00000005 ******** => 00000040 00000040 00000003 00000000 00000006 ******** => 00000004 00000000 00000001 00000000 00000007 ******** => 00000000 000001A9 00000000 00000000 00000008 ******** => 00000000 00000000 00000000 00000000 00000009 ******** => 00000000 00000000 00000000 00000000 0000000A ******** => 00000000 00000000 00000000 00000000 0000000C ******** => 00000000 00000000 00000000 00000000 0000000D 00000000 => 00000007 00000340 000003C0 40000000 0000000D 00000001 => 00000001 00000000 00000000 00000000 0000000D 00000002 => 00000100 00000240 00000000 00000000 0000000D 0000003E => 00000080 00000340 00000000 00000000 80000000 ******** => 8000001E 68747541 444D4163 69746E65 80000001 ******** => 00660F51 20000000 2FABBFFF 2FD3FBFF 80000002 ******** => 20444D41 204F5250 2D323141 30373838 80000003 ******** => 2C375220 20323120 504D4F43 20455455 80000004 ******** => 45524F43 43342053 2047382B 00202020 80000005 ******** => FF40FF18 FF40FF30 20080140 60030140 80000006 ******** => 64006400 64004200 04008140 00000000 80000007 ******** => 00000000 00000005 00000400 000037D9 80000008 ******** => 00003030 00000000 00004003 00000000 80000009 ******** => 00000000 00000000 00000000 00000000 8000000A ******** => 00000001 00008000 00000000 0001BCFF 8000000B ******** => 00000000 00000000 00000000 00000000 8000000C ******** => 00000000 00000000 00000000 00000000 8000000D ******** => 00000000 00000000 00000000 00000000 8000000E ******** => 00000000 00000000 00000000 00000000 8000000F ******** => 00000000 00000000 00000000 00000000 80000010 ******** => 00000000 00000000 00000000 00000000 80000011 ******** => 00000000 00000000 00000000 00000000 80000012 ******** => 00000000 00000000 00000000 00000000 80000013 ******** => 00000000 00000000 00000000 00000000 80000014 ******** => 00000000 00000000 00000000 00000000 80000015 ******** => 00000000 00000000 00000000 00000000 80000016 ******** => 00000000 00000000 00000000 00000000 80000017 ******** => 00000000 00000000 00000000 00000000 80000018 ******** => 00000000 00000000 00000000 00000000 80000019 ******** => F040F018 64006400 00000000 00000000 8000001A ******** => 00000003 00000000 00000000 00000000 8000001B ******** => 000007FF 00000000 00000000 00000000 8000001C ******** => 00000000 80032013 00010200 E000000F 8000001E ******** => 00000010 00000100 00000000 00000000 blis-0.9.0/travis/cpuid/haswell.def000066400000000000000000000067521422157504600172240ustar00rootroot00000000000000# # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2018, The University of Texas at Austin # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # CPU: Intel Xeon E5-2660 v3, 2600 MHz # 00000000 ******** => 0000000F 756E6547 6C65746E 49656E69 00000001 ******** => 000306F2 00200800 7FFEFBFF BFEBFBFF 00000002 ******** => 76036301 00F0B5FF 00000000 00C10000 00000003 ******** => 00000000 00000000 00000000 00000000 00000004 00000000 => 3C004121 01C0003F 0000003F 00000000 00000004 00000001 => 3C004122 01C0003F 0000003F 00000000 00000004 00000002 => 3C004143 01C0003F 000001FF 00000000 00000004 00000003 => 3C07C163 04C0003F 00004FFF 00000006 00000005 ******** => 00000040 00000040 00000003 00002120 00000006 ******** => 00000075 00000002 00000009 00000000 00000007 ******** => 00000000 000037AB 00000000 00000000 00000008 ******** => 00000000 00000000 00000000 00000000 00000009 ******** => 00000001 00000000 00000000 00000000 0000000A ******** => 07300403 00000000 00000000 00000603 0000000B 00000000 => 00000001 00000002 00000100 00000000 0000000B 00000001 => 00000005 00000014 00000201 00000000 0000000C ******** => 00000000 00000000 00000000 00000000 0000000D 00000000 => 00000007 00000340 00000340 00000000 0000000D 00000001 => 00000001 00000000 00000000 00000000 0000000D 00000002 => 00000100 00000240 00000000 00000000 0000000E ******** => 00000000 00000000 00000000 00000000 0000000F 00000000 => 00000000 00000027 00000000 00000002 0000000F 00000001 => 00000000 0000A000 00000027 00000001 80000000 ******** => 80000008 00000000 00000000 00000000 80000001 ******** => 00000000 00000000 00000021 2C100000 80000002 ******** => 65746E49 2952286C 6F655820 2952286E 80000003 ******** => 55504320 2D354520 30363632 20337620 80000004 ******** => 2E322040 48473036 0000007A 00000000 80000005 ******** => 00000000 00000000 00000000 00000000 80000006 ******** => 00000000 00000000 01006040 00000000 80000007 ******** => 00000000 00000000 00000000 00000100 80000008 ******** => 0000302E 00000000 00000000 00000000 blis-0.9.0/travis/cpuid/penryn.def000066400000000000000000000054001422157504600170650ustar00rootroot00000000000000# # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2018, The University of Texas at Austin # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # CPU: Intel Xeon X5550, 2666 MHz # 00000000 ******** => 0000000B 756E6547 6C65746E 49656E69 00000001 ******** => 000106A2 00100800 00BCE3BD BFEBFBFF 00000002 ******** => 55035A01 00F0B2E4 00000000 09CA212C 00000003 ******** => 00000000 00000000 00000000 00000000 00000005 ******** => 00000040 00000040 00000003 00021120 00000006 ******** => 00000003 00000002 00000001 00000000 00000007 ******** => 00000000 00000000 00000000 00000000 00000008 ******** => 00000000 00000000 00000000 00000000 00000009 ******** => 00000000 00000000 00000000 00000000 0000000A ******** => 07300403 00000000 00000000 00000603 80000000 ******** => 80000008 00000000 00000000 00000000 80000001 ******** => 00000000 00000000 00000001 28100000 80000002 ******** => 756E6547 20656E69 65746E49 2952286C 80000003 ******** => 55504320 20202020 20202020 40202020 80000004 ******** => 30303020 20402030 37362E32 007A4847 80000005 ******** => 00000000 00000000 00000000 00000000 80000006 ******** => 00000000 00000000 01006040 00000000 80000007 ******** => 00000000 00000000 00000000 00000100 80000008 ******** => 00003028 00000000 00000000 00000000 blis-0.9.0/travis/cpuid/piledriver.def000066400000000000000000000106531422157504600177250ustar00rootroot00000000000000# # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2018, The University of Texas at Austin # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # CPU: AMD A10-6800K, 4300 MHz # 00000000 ******** => 0000000D 68747541 444D4163 69746E65 00000001 ******** => 00610F31 00040800 3E98320B 178BFBFF 00000002 ******** => 00000000 00000000 00000000 00000000 00000003 ******** => 00000000 00000000 00000000 00000000 00000005 ******** => 00000040 00000040 00000003 00000000 00000006 ******** => 00000000 00000000 00000001 00000000 00000007 ******** => 00000000 00000008 00000000 00000000 00000008 ******** => 00000000 00000000 00000000 00000000 00000009 ******** => 00000000 00000000 00000000 00000000 0000000A ******** => 00000000 00000000 00000000 00000000 0000000C ******** => 00000000 00000000 00000000 00000000 0000000D 00000000 => 00000007 00000340 000003C0 40000000 0000000D 00000001 => 00000000 00000000 00000000 00000000 0000000D 00000002 => 00000100 00000240 00000000 00000000 0000000D 0000003E => 00000080 00000340 00000000 00000000 80000000 ******** => 8000001E 68747541 444D4163 69746E65 80000001 ******** => 00610F31 20000000 01EBBFFF 2FD3FBFF 80000002 ******** => 20444D41 2D303141 30303836 5041204B 80000003 ******** => 69772055 52206874 6F656461 6D74286E 80000004 ******** => 44482029 61724720 63696870 00202073 80000005 ******** => FF40FF18 FF40FF30 10040140 40020140 80000006 ******** => 64006400 64004200 08008140 00000000 80000007 ******** => 00000000 00000000 00000000 000007D9 80000008 ******** => 00003030 00000000 00004003 00000000 80000009 ******** => 00000000 00000000 00000000 00000000 8000000A ******** => 00000001 00010000 00000000 00001CFF 8000000B ******** => 00000000 00000000 00000000 00000000 8000000C ******** => 00000000 00000000 00000000 00000000 8000000D ******** => 00000000 00000000 00000000 00000000 8000000E ******** => 00000000 00000000 00000000 00000000 8000000F ******** => 00000000 00000000 00000000 00000000 80000010 ******** => 00000000 00000000 00000000 00000000 80000011 ******** => 00000000 00000000 00000000 00000000 80000012 ******** => 00000000 00000000 00000000 00000000 80000013 ******** => 00000000 00000000 00000000 00000000 80000014 ******** => 00000000 00000000 00000000 00000000 80000015 ******** => 00000000 00000000 00000000 00000000 80000016 ******** => 00000000 00000000 00000000 00000000 80000017 ******** => 00000000 00000000 00000000 00000000 80000018 ******** => 00000000 00000000 00000000 00000000 80000019 ******** => F040F018 64006400 00000000 00000000 8000001A ******** => 00000003 00000000 00000000 00000000 8000001B ******** => 000000FF 00000000 00000000 00000000 8000001C ******** => 00000000 80032013 00010200 8000000F 8000001D 00000001 => 00000121 00C0003F 0000003F 00000000 8000001D 00000002 => 00004122 0040003F 000001FF 00000000 8000001D 00000003 => 00004143 03C0003F 000007FF 00000001 8000001E ******** => 00000010 00000100 00000000 00000000 8FFFFFFF ******** => 00000000 00000000 00000000 00000000 blis-0.9.0/travis/cpuid/sandybridge.def000066400000000000000000000056601422157504600200550ustar00rootroot00000000000000# # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2018, The University of Texas at Austin # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # CPU: Intel Xeon E3-1230 v2, 3700 MHz # 00000000 ******** => 0000000D 756E6547 6C65746E 49656E69 00000001 ******** => 000306A9 00100800 7FBAE3FF BFEBFBFF 00000002 ******** => 76035A01 00F0B2FF 00000000 00CA0000 00000003 ******** => 00000000 00000000 00000000 00000000 00000005 ******** => 00000040 00000040 00000003 00001120 00000006 ******** => 00000077 00000002 00000009 00000000 00000007 ******** => 00000000 00000281 00000000 00000000 00000008 ******** => 00000000 00000000 00000000 00000000 00000009 ******** => 00000000 00000000 00000000 00000000 0000000A ******** => 07300403 00000000 00000000 00000603 0000000C ******** => 00000000 00000000 00000000 00000000 0000000D 00000000 => 00000007 00000240 00000340 00000000 0000000D 00000001 => 00000100 00000240 00000000 00000000 80000000 ******** => 80000008 00000000 00000000 00000000 80000001 ******** => 00000000 00000000 00000001 28100000 80000002 ******** => 20202020 6E492020 286C6574 58202952 80000003 ******** => 286E6F65 43202952 45205550 32312D33 80000004 ******** => 56203033 20402032 30332E33 007A4847 80000005 ******** => 00000000 00000000 00000000 00000000 80000006 ******** => 00000000 00000000 01006040 00000000 80000007 ******** => 00000000 00000000 00000000 00000100 80000008 ******** => 00003024 00000000 00000000 00000000 blis-0.9.0/travis/cpuid/skx.def000066400000000000000000000106661422157504600163710ustar00rootroot00000000000000# # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2018, The University of Texas at Austin # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # CPU: Intel Xeon Platinum 8180, 2500 MHz # 00000000 ******** => 00000016 756E6547 6C65746E 49656E69 00000001 ******** => 00050654 00400800 7FFEFBFF BFEBFBFF 00000002 ******** => 76036301 00F0B5FF 00000000 00C30000 00000003 ******** => 00000000 00000000 00000000 00000000 00000004 00000000 => 7C004121 01C0003F 0000003F 00000000 00000004 00000001 => 7C004122 01C0003F 0000003F 00000000 00000004 00000002 => 7C004143 03C0003F 000003FF 00000000 00000004 00000003 => 7C0FC163 0280003F 0000DFFF 00000004 00000005 ******** => 00000040 00000040 00000003 00002020 00000006 ******** => 00000EF7 00000002 00000009 00000000 00000007 ******** => 00000000 D39FFFFB 00000008 00000000 00000008 ******** => 00000000 00000000 00000000 00000000 00000009 ******** => 00000000 00000000 00000000 00000000 0000000A ******** => 07300404 00000000 00000000 00000603 0000000B 00000000 => 00000001 00000002 00000100 00000000 0000000B 00000001 => 00000006 00000038 00000201 00000000 0000000C ******** => 00000000 00000000 00000000 00000000 0000000D 00000000 => 000002FF 00000A80 00000A88 00000000 0000000D 00000001 => 0000000F 00000A00 00000100 00000000 0000000D 00000002 => 00000100 00000240 00000000 00000000 0000000D 00000003 => 00000040 000003C0 00000000 00000000 0000000D 00000004 => 00000040 00000400 00000000 00000000 0000000D 00000005 => 00000040 00000440 00000000 00000000 0000000D 00000006 => 00000200 00000480 00000000 00000000 0000000D 00000007 => 00000400 00000680 00000000 00000000 0000000D 00000008 => 00000080 00000000 00000001 00000000 0000000D 00000009 => 00000008 00000A80 00000000 00000000 0000000E ******** => 00000000 00000000 00000000 00000000 0000000F 00000000 => 00000000 000000DF 00000000 00000002 0000000F 00000001 => 00000000 0001C000 000000DF 00000007 00000010 00000000 => 00000000 0000000A 00000000 00000000 00000010 00000001 => 0000000A 00000600 00000004 0000000F 00000011 ******** => 00000000 00000000 00000000 00000000 00000012 00000000 => 00000000 00000000 00000000 00000000 00000012 00000001 => 00000000 00000000 00000000 00000000 00000013 ******** => 00000000 00000000 00000000 00000000 00000014 00000000 => 00000001 0000000F 00000007 00000000 00000014 00000001 => 02490002 003F3FFF 00000000 00000000 00000015 ******** => 00000002 000000C8 00000000 00000000 00000016 ******** => 000009C4 00000ED8 00000064 00000000 80000000 ******** => 80000008 00000000 00000000 00000000 80000001 ******** => 00000000 00000000 00000121 2C100000 80000002 ******** => 65746E49 2952286C 6F655820 2952286E 80000003 ******** => 616C5020 756E6974 3138206D 43203038 80000004 ******** => 40205550 352E3220 7A484730 00000000 80000005 ******** => 00000000 00000000 00000000 00000000 80000006 ******** => 00000000 00000000 01006040 00000000 80000007 ******** => 00000000 00000000 00000000 00000100 80000008 ******** => 0000302E 00000000 00000000 00000000 blis-0.9.0/travis/cpuid/skx1.def000066400000000000000000000106521422157504600164450ustar00rootroot00000000000000# # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2018, The University of Texas at Austin # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # CPU: Intel Xeon Bronze 3106 # 00000000 ******** => 00000016 756E6547 6C65746E 49656E69 00000001 ******** => 00050654 00100800 7FFEFBFF BFEBFBFF 00000002 ******** => 76036301 00F0B6FF 00000000 00C30000 00000003 ******** => 00000000 00000000 00000000 00000000 00000004 00000000 => 1C004121 01C0003F 0000003F 00000000 00000004 00000001 => 1C004122 01C0003F 0000003F 00000000 00000004 00000002 => 1C004143 03C0003F 000003FF 00000000 00000004 00000003 => 1C03C163 0280003F 00002FFF 00000004 00000005 ******** => 00000040 00000040 00000003 00002020 00000006 ******** => 00000EF5 00000002 00000009 00000000 00000007 ******** => 00000000 D39FFFFB 00000008 00000000 00000008 ******** => 00000000 00000000 00000000 00000000 00000009 ******** => 00000000 00000000 00000000 00000000 0000000A ******** => 07300804 00000000 00000000 00000603 0000000B 00000000 => 00000001 00000001 00000100 00000000 0000000B 00000001 => 00000004 00000006 00000201 00000000 0000000C ******** => 00000000 00000000 00000000 00000000 0000000D 00000000 => 000002FF 00000340 00000A88 00000000 0000000D 00000001 => 0000000F 00000340 00000100 00000000 0000000D 00000002 => 00000100 00000240 00000000 00000000 0000000D 00000003 => 00000040 000003C0 00000000 00000000 0000000D 00000004 => 00000040 00000400 00000000 00000000 0000000D 00000005 => 00000040 00000440 00000000 00000000 0000000D 00000006 => 00000200 00000480 00000000 00000000 0000000D 00000007 => 00000400 00000680 00000000 00000000 0000000D 00000008 => 00000080 00000000 00000001 00000000 0000000D 00000009 => 00000008 00000A80 00000000 00000000 0000000E ******** => 00000000 00000000 00000000 00000000 0000000F 00000000 => 00000000 0000002F 00000000 00000002 0000000F 00000001 => 00000000 00006000 0000002F 00000007 00000010 00000000 => 00000000 0000000A 00000000 00000000 00000010 00000001 => 0000000A 00000600 00000004 0000000F 00000011 ******** => 00000000 00000000 00000000 00000000 00000012 00000000 => 00000000 00000000 00000000 00000000 00000012 00000001 => 00000000 00000000 00000000 00000000 00000013 ******** => 00000000 00000000 00000000 00000000 00000014 00000000 => 00000001 0000000F 00000007 00000000 00000014 00000001 => 02490002 003F3FFF 00000000 00000000 00000015 ******** => 00000002 00000088 00000000 00000000 00000016 ******** => 000006A4 000006A4 00000064 00000000 80000000 ******** => 80000008 00000000 00000000 00000000 80000001 ******** => 00000000 00000000 00000121 2C100000 80000002 ******** => 65746E49 2952286C 6F655820 2952286E 80000003 ******** => 6F724220 20657A6E 34303133 55504320 80000004 ******** => 31204020 4730372E 00007A48 00000000 80000005 ******** => 00000000 00000000 00000000 00000000 80000006 ******** => 00000000 00000000 01006040 00000000 80000007 ******** => 00000000 00000000 00000000 00000100 80000008 ******** => 0000302E 00000000 00000000 00000000 blis-0.9.0/travis/cpuid/steamroller.def000066400000000000000000000104711422157504600201070ustar00rootroot00000000000000# # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2018, The University of Texas at Austin # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # CPU: AMD A10-7850K, 4000 MHz # 00000000 ******** => 0000000D 68747541 444D4163 69746E65 00000001 ******** => 00630F01 00040800 3E98320B 178BFBFF 00000002 ******** => 00000000 00000000 00000000 00000000 00000003 ******** => 00000000 00000000 00000000 00000000 00000005 ******** => 00000040 00000040 00000003 00000000 00000006 ******** => 00000000 00000000 00000001 00000000 00000007 ******** => 00000000 00000009 00000000 00000000 00000008 ******** => 00000000 00000000 00000000 00000000 00000009 ******** => 00000000 00000000 00000000 00000000 0000000A ******** => 00000000 00000000 00000000 00000000 0000000C ******** => 00000000 00000000 00000000 00000000 0000000D 00000000 => 00000007 00000340 000003C0 40000000 0000000D 00000001 => 00000100 00000240 00000000 00000000 80000000 ******** => 8000001E 68747541 444D4163 69746E65 80000001 ******** => 00630F01 10000000 0FEBBFFF 2FD3FBFF 80000002 ******** => 20444D41 2D303141 30353837 5041204B 80000003 ******** => 69772055 52206874 6F656461 4D54286E 80000004 ******** => 37522029 61724720 63696870 00202073 80000005 ******** => FF40FF18 FF40FF30 10040140 60030140 80000006 ******** => 64006400 64004200 08008140 00000000 80000007 ******** => 00000000 00000001 00000000 000027D9 80000008 ******** => 00003030 00000000 00004003 00000000 80000009 ******** => 00000000 00000000 00000000 00000000 8000000A ******** => 00000001 00010000 00000000 00001CFF 8000000B ******** => 00000000 00000000 00000000 00000000 8000000C ******** => 00000000 00000000 00000000 00000000 8000000D ******** => 00000000 00000000 00000000 00000000 8000000E ******** => 00000000 00000000 00000000 00000000 8000000F ******** => 00000000 00000000 00000000 00000000 80000010 ******** => 00000000 00000000 00000000 00000000 80000011 ******** => 00000000 00000000 00000000 00000000 80000012 ******** => 00000000 00000000 00000000 00000000 80000013 ******** => 00000000 00000000 00000000 00000000 80000014 ******** => 00000000 00000000 00000000 00000000 80000015 ******** => 00000000 00000000 00000000 00000000 80000016 ******** => 00000000 00000000 00000000 00000000 80000017 ******** => 00000000 00000000 00000000 00000000 80000018 ******** => 00000000 00000000 00000000 00000000 80000019 ******** => F040F018 64006400 00000000 00000000 8000001A ******** => 00000003 00000000 00000000 00000000 8000001B ******** => 000001FF 00000000 00000000 00000000 8000001C ******** => 00000000 80032013 00010200 E000000F 8000001D 00000000 => 00000121 00C0003F 0000003F 00000000 8000001D 00000001 => 00004122 0080003F 000001FF 00000000 8000001D 00000002 => 00004143 03C0003F 000007FF 00000001 8000001E ******** => 00000010 00000100 00000000 00000000 8FFFFFFF ******** => 00000000 00000000 00000000 00000000 blis-0.9.0/travis/cpuid/zen.def000066400000000000000000000107451422157504600163560ustar00rootroot00000000000000# # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2018, The University of Texas at Austin # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # CPU: AMD EPYC 7551P, 3000 MHz # 00000000 ******** => 0000000D 68747541 444D4163 69746E65 00000001 ******** => 00800F12 00400800 7ED8320B 178BFBFF 00000002 ******** => 00000000 00000000 00000000 00000000 00000003 ******** => 00000000 00000000 00000000 00000000 00000005 ******** => 00000040 00000040 00000003 00000011 00000006 ******** => 00000004 00000000 00000001 00000000 00000007 ******** => 00000000 209C01A9 00000000 00000000 00000008 ******** => 00000000 00000000 00000000 00000000 00000009 ******** => 00000000 00000000 00000000 00000000 0000000A ******** => 00000000 00000000 00000000 00000000 0000000C ******** => 00000000 00000000 00000000 00000000 0000000D 00000000 => 00000007 00000340 00000340 00000000 0000000D 00000001 => 0000000F 00000340 00000000 00000000 0000000D 00000002 => 00000100 00000240 00000000 00000000 80000000 ******** => 8000001F 68747541 444D4163 69746E65 80000001 ******** => 00800F12 40000000 35C233FF 2FD3FBFF 80000002 ******** => 20444D41 43595045 35353720 33205031 80000003 ******** => 6F432D32 50206572 65636F72 726F7373 80000004 ******** => 20202020 20202020 20202020 00202020 80000005 ******** => FF40FF40 FF40FF40 20080140 40040140 80000006 ******** => 36006400 56006400 02006140 0200C140 80000007 ******** => 00000000 0000001B 00000000 00006799 80000008 ******** => 00003030 00000007 0000603F 00000000 80000009 ******** => 00000000 00000000 00000000 00000000 8000000A ******** => 00000001 00008000 00000000 0001BCFF 8000000B ******** => 00000000 00000000 00000000 00000000 8000000C ******** => 00000000 00000000 00000000 00000000 8000000D ******** => 00000000 00000000 00000000 00000000 8000000E ******** => 00000000 00000000 00000000 00000000 8000000F ******** => 00000000 00000000 00000000 00000000 80000010 ******** => 00000000 00000000 00000000 00000000 80000011 ******** => 00000000 00000000 00000000 00000000 80000012 ******** => 00000000 00000000 00000000 00000000 80000013 ******** => 00000000 00000000 00000000 00000000 80000014 ******** => 00000000 00000000 00000000 00000000 80000015 ******** => 00000000 00000000 00000000 00000000 80000016 ******** => 00000000 00000000 00000000 00000000 80000017 ******** => 00000000 00000000 00000000 00000000 80000018 ******** => 00000000 00000000 00000000 00000000 80000019 ******** => F040F040 00000000 00000000 00000000 8000001A ******** => 00000003 00000000 00000000 00000000 8000001B ******** => 000003FF 00000000 00000000 00000000 8000001C ******** => 00000000 00000000 00000000 00000000 8000001D 00000000 => 00004121 01C0003F 0000003F 00000000 8000001D 00000001 => 00004122 00C0003F 000000FF 00000000 8000001D 00000002 => 00004143 01C0003F 000003FF 00000002 8000001D 00000003 => 0001C163 03C0003F 00001FFF 00000001 8000001E ******** => 00000000 00000100 00000300 00000000 8000001F ******** => 0000000F 0000016F 0000000F 00000001 8FFFFFFF ******** => 00000000 00000000 00000000 00000000 blis-0.9.0/travis/cpuid/zen2.def000066400000000000000000000112761422157504600164400ustar00rootroot00000000000000# # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2018, The University of Texas at Austin # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # CPU: AMD EPYC 7742 # NOTE: This file was copied from zen.def and then the appropriate bits # in the first field (eax) of leaf 1 were updated to reflect the Zen2 # "Rome" processor. See [1] for details. # [1] https://en.wikichip.org/wiki/amd/cpuid # 00000000 ******** => 0000000D 68747541 444D4163 69746E65 00000001 ******** => 00830F12 00400800 7ED8320B 178BFBFF 00000002 ******** => 00000000 00000000 00000000 00000000 00000003 ******** => 00000000 00000000 00000000 00000000 00000005 ******** => 00000040 00000040 00000003 00000011 00000006 ******** => 00000004 00000000 00000001 00000000 00000007 ******** => 00000000 209C01A9 00000000 00000000 00000008 ******** => 00000000 00000000 00000000 00000000 00000009 ******** => 00000000 00000000 00000000 00000000 0000000A ******** => 00000000 00000000 00000000 00000000 0000000C ******** => 00000000 00000000 00000000 00000000 0000000D 00000000 => 00000007 00000340 00000340 00000000 0000000D 00000001 => 0000000F 00000340 00000000 00000000 0000000D 00000002 => 00000100 00000240 00000000 00000000 80000000 ******** => 8000001F 68747541 444D4163 69746E65 80000001 ******** => 00800F12 40000000 35C233FF 2FD3FBFF 80000002 ******** => 20444D41 43595045 35353720 33205031 80000003 ******** => 6F432D32 50206572 65636F72 726F7373 80000004 ******** => 20202020 20202020 20202020 00202020 80000005 ******** => FF40FF40 FF40FF40 20080140 40040140 80000006 ******** => 36006400 56006400 02006140 0200C140 80000007 ******** => 00000000 0000001B 00000000 00006799 80000008 ******** => 00003030 00000007 0000603F 00000000 80000009 ******** => 00000000 00000000 00000000 00000000 8000000A ******** => 00000001 00008000 00000000 0001BCFF 8000000B ******** => 00000000 00000000 00000000 00000000 8000000C ******** => 00000000 00000000 00000000 00000000 8000000D ******** => 00000000 00000000 00000000 00000000 8000000E ******** => 00000000 00000000 00000000 00000000 8000000F ******** => 00000000 00000000 00000000 00000000 80000010 ******** => 00000000 00000000 00000000 00000000 80000011 ******** => 00000000 00000000 00000000 00000000 80000012 ******** => 00000000 00000000 00000000 00000000 80000013 ******** => 00000000 00000000 00000000 00000000 80000014 ******** => 00000000 00000000 00000000 00000000 80000015 ******** => 00000000 00000000 00000000 00000000 80000016 ******** => 00000000 00000000 00000000 00000000 80000017 ******** => 00000000 00000000 00000000 00000000 80000018 ******** => 00000000 00000000 00000000 00000000 80000019 ******** => F040F040 00000000 00000000 00000000 8000001A ******** => 00000003 00000000 00000000 00000000 8000001B ******** => 000003FF 00000000 00000000 00000000 8000001C ******** => 00000000 00000000 00000000 00000000 8000001D 00000000 => 00004121 01C0003F 0000003F 00000000 8000001D 00000001 => 00004122 00C0003F 000000FF 00000000 8000001D 00000002 => 00004143 01C0003F 000003FF 00000002 8000001D 00000003 => 0001C163 03C0003F 00001FFF 00000001 8000001E ******** => 00000000 00000100 00000300 00000000 8000001F ******** => 0000000F 0000016F 0000000F 00000001 8FFFFFFF ******** => 00000000 00000000 00000000 00000000 blis-0.9.0/travis/cpuid/zen3.def000066400000000000000000000112771422157504600164420ustar00rootroot00000000000000# # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2018, The University of Texas at Austin # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # CPU: AMD EPYC 7xxx # NOTE: This file was copied from zen.def and then the appropriate bits # in the first field (eax) of leaf 1 were updated to reflect the Zen3 # "Milan" processor. See [1] for details. # [1] https://en.wikichip.org/wiki/amd/cpuid # 00000000 ******** => 0000000D 68747541 444D4163 69746E65 00000001 ******** => 00A00F12 00400800 7ED8320B 178BFBFF 00000002 ******** => 00000000 00000000 00000000 00000000 00000003 ******** => 00000000 00000000 00000000 00000000 00000005 ******** => 00000040 00000040 00000003 00000011 00000006 ******** => 00000004 00000000 00000001 00000000 00000007 ******** => 00000000 209C01A9 00000000 00000000 00000008 ******** => 00000000 00000000 00000000 00000000 00000009 ******** => 00000000 00000000 00000000 00000000 0000000A ******** => 00000000 00000000 00000000 00000000 0000000C ******** => 00000000 00000000 00000000 00000000 0000000D 00000000 => 00000007 00000340 00000340 00000000 0000000D 00000001 => 0000000F 00000340 00000000 00000000 0000000D 00000002 => 00000100 00000240 00000000 00000000 80000000 ******** => 8000001F 68747541 444D4163 69746E65 80000001 ******** => 00800F12 40000000 35C233FF 2FD3FBFF 80000002 ******** => 20444D41 43595045 35353720 33205031 80000003 ******** => 6F432D32 50206572 65636F72 726F7373 80000004 ******** => 20202020 20202020 20202020 00202020 80000005 ******** => FF40FF40 FF40FF40 20080140 40040140 80000006 ******** => 36006400 56006400 02006140 0200C140 80000007 ******** => 00000000 0000001B 00000000 00006799 80000008 ******** => 00003030 00000007 0000603F 00000000 80000009 ******** => 00000000 00000000 00000000 00000000 8000000A ******** => 00000001 00008000 00000000 0001BCFF 8000000B ******** => 00000000 00000000 00000000 00000000 8000000C ******** => 00000000 00000000 00000000 00000000 8000000D ******** => 00000000 00000000 00000000 00000000 8000000E ******** => 00000000 00000000 00000000 00000000 8000000F ******** => 00000000 00000000 00000000 00000000 80000010 ******** => 00000000 00000000 00000000 00000000 80000011 ******** => 00000000 00000000 00000000 00000000 80000012 ******** => 00000000 00000000 00000000 00000000 80000013 ******** => 00000000 00000000 00000000 00000000 80000014 ******** => 00000000 00000000 00000000 00000000 80000015 ******** => 00000000 00000000 00000000 00000000 80000016 ******** => 00000000 00000000 00000000 00000000 80000017 ******** => 00000000 00000000 00000000 00000000 80000018 ******** => 00000000 00000000 00000000 00000000 80000019 ******** => F040F040 00000000 00000000 00000000 8000001A ******** => 00000003 00000000 00000000 00000000 8000001B ******** => 000003FF 00000000 00000000 00000000 8000001C ******** => 00000000 00000000 00000000 00000000 8000001D 00000000 => 00004121 01C0003F 0000003F 00000000 8000001D 00000001 => 00004122 00C0003F 000000FF 00000000 8000001D 00000002 => 00004143 01C0003F 000003FF 00000002 8000001D 00000003 => 0001C163 03C0003F 00001FFF 00000001 8000001E ******** => 00000000 00000100 00000300 00000000 8000001F ******** => 0000000F 0000016F 0000000F 00000001 8FFFFFFF ******** => 00000000 00000000 00000000 00000000 blis-0.9.0/travis/cxx/000077500000000000000000000000001422157504600145715ustar00rootroot00000000000000blis-0.9.0/travis/cxx/Makefile000066400000000000000000000034141422157504600162330ustar00rootroot00000000000000# # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2021, Southern Methodist University # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # .PHONY: all cxx-test all: cxx-test $(CXX) -std=c++0x -o $(BUILD_DIR)/cxx-test.x -I$(INCLUDE_DIR) cxx-test.cxx -L$(LIB_DIR) -lblis blis-0.9.0/travis/cxx/cxx-test.cxx000066400000000000000000000040141422157504600170730ustar00rootroot00000000000000// // // BLIS // An object-based framework for developing high-performance BLAS-like // libraries. // // Copyright (C) 2021, Southern Methodist University // // 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(s) of the copyright holder(s) 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 COPYRIGHT // HOLDER 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. // // #include #include "blis.h" int main() { const int N = 5; std::vector A(N*N), B(N*N), C(N*N); scomplex one{1.0, 0.0}; scomplex zero{0.0, 0.0}; bli_cgemm(BLIS_NO_TRANSPOSE, BLIS_NO_TRANSPOSE, N, N, N, &one, A.data(), 1, N, B.data(), 1, N, &zero, C.data(), 1, N); } blis-0.9.0/travis/cxx/cxx-test.sh000077500000000000000000000042271422157504600167140ustar00rootroot00000000000000#!/bin/bash # # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2021, Southern Methodist University # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # SOURCE_DIR=$1 CONFIG=$2 if [ -z $SOURCE_DIR ] || [ -z $CONFIG ]; then echo "usage: cxx-test.sh " exit 1 fi BUILD_DIR=$(pwd) INCLUDE_DIR=$BUILD_DIR/include/$CONFIG LIB_DIR=$BUILD_DIR/lib/$CONFIG if [ ! -e $INCLUDE_DIR/blis.h ]; then echo "could not find blis.h" exit 1 fi if [ ! -e $SOURCE_DIR/travis/cxx/Makefile ]; then echo "could not find cxx-test Makefile" exit 1 fi make -C $SOURCE_DIR/travis/cxx INCLUDE_DIR=$INCLUDE_DIR LIB_DIR=$LIB_DIR BUILD_DIR=$BUILD_DIR blis-0.9.0/travis/do_sde.sh000077500000000000000000000040051422157504600155620ustar00rootroot00000000000000#!/bin/bash set -e set -x SDE_VERSION=sde-external-8.69.1-2021-07-18-lin SDE_TARBALL=$SDE_VERSION.tar.bz2 SDE=$SDE_VERSION/sde64 # # This doesn't seem to be necessary anymore # #curl --verbose --form accept_license=1 --form form_id=intel_licensed_dls_step_1 \ # --output /dev/null --cookie-jar jar.txt \ # --location https://software.intel.com/protected-download/267266/144917 #curl --verbose --cookie jar.txt --output $SDE_TARBALL \ # https://software.intel.com/system/files/managed/2a/1a/$SDE_TARBALL #curl --verbose --output $SDE_TARBALL \ # https://software.intel.com/content/dam/develop/external/us/en/documents/downloads/$SDE_TARBALL CI_UTILS=ci-utils CI_UTILS_URL=https://github.com/flame/${CI_UTILS}.git CI_UTILS_SDE_DIR=sde SDE_DIRPATH=$CI_UTILS/$CI_UTILS_SDE_DIR git clone $CI_UTILS_URL mv $SDE_DIRPATH/$SDE_TARBALL . tar xvf $SDE_TARBALL make -j2 testsuite-bin cp $DIST_PATH/testsuite/input.general.fast input.general cp $DIST_PATH/testsuite/input.operations.fast input.operations TMP=`ldd ./test_libblis.x | grep ld | sed 's/^.*=> //'` LD_SO=${TMP%% *} TMP=`ldd ./test_libblis.x | grep libc | sed 's/^.*=> //'` LIBC_SO=${TMP%% *} TMP=`ldd ./test_libblis.x | grep libm | sed 's/^.*=> //'` LIBM_SO=${TMP%% *} for LIB in $LD_SO $LIBC_SO $LIBM_SO; do $DIST_PATH/travis/patch-ld-so.py $LIB .tmp chmod a+x .tmp sudo mv .tmp $LIB done #for ARCH in penryn sandybridge haswell skx knl piledriver steamroller excavator zen; do for ARCH in penryn sandybridge haswell skx knl zen zen2 zen3; do if [ "$ARCH" = "knl" ]; then $SDE -knl -- ./test_libblis.x > output.testsuite else $SDE -cpuid_in $DIST_PATH/travis/cpuid/$ARCH.def -- ./test_libblis.x > output.testsuite fi $DIST_PATH/testsuite/check-blistest.sh ./output.testsuite TMP=`grep "active sub-configuration" output.testsuite` CONFIG=${TMP##* } if [ "$CONFIG" != "$ARCH" ]; then echo "Wrong configuration chosen:" echo " Expected: $ARCH" echo " Got: $CONFIG" exit 1 fi done blis-0.9.0/travis/do_testsuite.sh000077500000000000000000000014331422157504600170420ustar00rootroot00000000000000#!/bin/bash set -e set -x export BLIS_JC_NT=1 export BLIS_IC_NT=2 export BLIS_JR_NT=1 export BLIS_IR_NT=1 if [ "$TEST" = "FAST" -o "$TEST" = "ALL" ]; then make testblis-fast $DIST_PATH/testsuite/check-blistest.sh ./output.testsuite fi if [ "$TEST" = "MD" -o "$TEST" = "ALL" ]; then make testblis-md $DIST_PATH/testsuite/check-blistest.sh ./output.testsuite fi if [ "$TEST" = "SALT" -o "$TEST" = "ALL" ]; then # Disable multithreading within BLIS. export BLIS_JC_NT=1 BLIS_IC_NT=1 BLIS_JR_NT=1 BLIS_IR_NT=1 make testblis-salt $DIST_PATH/testsuite/check-blistest.sh ./output.testsuite fi if [ "$TEST" = "1" -o "$TEST" = "ALL" ]; then make testblis $DIST_PATH/testsuite/check-blistest.sh ./output.testsuite fi make testblas $DIST_PATH/blastest/check-blastest.sh blis-0.9.0/travis/patch-ld-so.py000077500000000000000000000005721422157504600164630ustar00rootroot00000000000000#!/usr/bin/env python # # Patch ld.so to disable runtime CPUID detection # Taken from https://stackoverflow.com/a/44483482 # import re import sys infile, outfile = sys.argv[1:] d = open(infile, 'rb').read() # Match CPUID(eax=0), "xor eax,eax" followed closely by "cpuid" o = re.sub(b'(\x31\xc0.{0,32})\x0f\xa2', b'\\1\x66\x90', d) #assert d != o open(outfile, 'wb').write(o) blis-0.9.0/vendor/000077500000000000000000000000001422157504600137545ustar00rootroot00000000000000blis-0.9.0/vendor/cpp/000077500000000000000000000000001422157504600145365ustar00rootroot00000000000000blis-0.9.0/vendor/cpp/blis.hh000066400000000000000000003570421422157504600160230ustar00rootroot00000000000000/****************************************************************************** * Copyright (c) 2019 - present Advanced Micro Devices, Inc. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. *******************************************************************************/ /*! @file blis.hh * blis.hh defines all the BLAS CPP templated public interfaces * */ #ifndef BLIS_HH #define BLIS_HH #include "cblas.hh" namespace blis { /*! \brief Construct plane rotation for arbitrary data types \b Purpose: ROTG construct plane rotation that eliminates b for arbitrary data types, such that \n [ z ] = [ c s ] [ a ] \n [ 0 ] [ -s c ] [ b ] \n Data precisions supported include SINGLE/DOUBLE PRECISION REAL \param[in, out] a SINGLE/DOUBLE PRECISION REAL On entry, scalar a. On exit, set to z. \param[in, out] b SINGLE/DOUBLE PRECISION REAL On entry, scalar b. On exit, set to s, 1/c, or 0. \param[out] c Cosine of rotation; SINGLE/DOUBLE PRECISION REAL. \param[out] s Sine of rotation; SINGLE/DOUBLE PRECISION REAL. */ template< typename T > void rotg( T *a, T *b, T *c, T *s ) { cblas_rotg(a, b, c, s); } /*! \brief Construct the modified givens transformation matrix for arbitrary data types \b Purpose: ROTMG construct modified (fast) plane rotation, H, that eliminates b, such that \n [ z ] = H [ sqrt(d1) 0 ] [ a ] \n [ 0 ] [ 0 sqrt(d2) ] [ b ] \n Data precisions supported include SINGLE/DOUBLE PRECISION REAL \param[in, out] d1 SINGLE/DOUBLE PRECISION REAL sqrt(d1) is scaling factor for vector x. \param[in, out] d2 SINGLE/DOUBLE PRECISION REAL sqrt(d2) is scaling factor for vector y. \param[in, out] a On entry, scalar a. On exit, set to z. SINGLE/DOUBLE PRECISION REAL. \param[in, out] b On entry, scalar b. SINGLE/DOUBLE PRECISION REAL. \param[out] param SINGLE/DOUBLE PRECISION REAL array, dimension (5),giving parameters of modified plane rotation param(1)=DFLAG param(2)=DH11 param(3)=DH21 param(4)=DH12 param(5)=DH22 */ template< typename T > void rotmg( T *d1, T *d2, T *a, T b, T param[5] ) { cblas_rotmg(d1, d2, a, b, param ); } /*! \brief Apply plane rotation for arbitrary data types \b Purpose: ROT applies a plane rotation: \n [ x^T ] [ c s ] [ x^T ] \n [ y^T ] = [ -s c ] [ y^T ] \n Data precisions supported include SINGLE/DOUBLE PRECISION REAL \param[in] n Number of elements in x and y. n >= 0. \param[in, out] x SINGLE/DOUBLE PRECISION REAL array The n-element vector x, in an array of length (n-1)*abs(incx) + 1. \param[in] incx incx is INTEGER Stride between elements of x. incx must not be zero. If incx < 0, uses elements of x in reverse order: x(n-1), ..., x(0). \param[in, out] y SINGLE/DOUBLE PRECISION REAL array The n-element vector y, in an array of length (n-1)*abs(incy) + 1. \param[in] incy incy is INTEGER Stride between elements of y. incy must not be zero. If incy < 0, uses elements of y in reverse order: y(n-1), ..., y(0). \param[in] c Cosine of rotation; SINGLE/DOUBLE PRECISION REAL. \param[in] s Sine of rotation; SINGLE/DOUBLE PRECISION REAL. */ template< typename T > void rot( int64_t n, T *x, int64_t incx, T *y, int64_t incy, T c, T s ) { cblas_rot( n, x, incx, y, incy, c, s ); } /*! \brief Apply the modified givens transformation for arbitrary data types \b Purpose: ROTM applies modified (fast) plane rotation, H: \n [ x^T ] = H [ x^T ] \n [ y^T ] [ y^T ] \n Data precisions supported include SINGLE/DOUBLE PRECISION REAL \param[in] n Number of elements in x and y. n >= 0. \param[in, out] x SINGLE/DOUBLE PRECISION REAL array The n-element vector x, in an array of length (n-1)*abs(incx) + 1. \param[in] incx incx is INTEGER Stride between elements of x. incx must not be zero. If incx < 0, uses elements of x in reverse order: x(n-1), ..., x(0). \param[in, out] y SINGLE/DOUBLE PRECISION REAL array The n-element vector y, in an array of length (n-1)*abs(incy) + 1. \param[in] incy incy is INTEGER Stride between elements of y. incy must not be zero. If incy < 0, uses elements of y in reverse order: y(n-1), ..., y(0). \param[in] P SINGLE/DOUBLE PRECISION REAL array, dimension (5),giving parameters of modified plane rotation param(1)=DFLAG param(2)=DH11 param(3)=DH21 param(4)=DH12 param(5)=DH22 */ template< typename T > void rotm( int64_t n, T *x, int64_t incx, T *y, int64_t incy, const T *P) { cblas_rotm( n, x, incx, y, incy, P ); } /*! \brief Interchanges two vectors of arbitrary data types \b Purpose: SWAP interchanges two vectors uses unrolled loops for increments equal to 1.\n x <=> y \n Data precisions supported include SINGLE/DOUBLE PRECISION REAL, SINGLE PRECISION COMPLEX, DOUBLE PRECISION COMPLEX(COMPLEX*16) \param[in] n n is INTEGER Number of elements in x and y. n >= 0. \param[in] x REAL/DOUBLE PRECISION/COMPLEX/COMPLEX*16 array. The n-element vector x, in an array of length (n-1)*abs(incx) + 1. \param[in] incx incx is INTEGER. Stride between elements of x. incx must not be zero. If incx < 0, uses elements of x in reverse order: x(n-1), ..., x(0). \param[in, out] y REAL/DOUBLE PRECISION/COMPLEX/COMPLEX*16 array. The n-element vector y, in an array of length (n-1)*abs(incy) + 1. \param[in] incy incy is INTEGER. Stride between elements of y. incy must not be zero. If incy < 0, uses elements of y in reverse order: y(n-1), ..., y(0). */ template< typename T > void swap( int64_t n, T *x, int64_t incx, T *y, int64_t incy ) { cblas_swap( n, x, incx, y, incy ); } /*! \brief Scales a vector of arbitrary data types by a constant. \b Purpose: SCAL scales a vector by a constant, uses unrolled loops for increment equal to 1.\n x = alpha * x \n Data precisions of vector & constant include SINGLE/DOUBLE PRECISION REAL, SINGLE PRECISION COMPLEX, DOUBLE PRECISION COMPLEX(COMPLEX*16) \param[in] n n is INTEGER Number of elements in x. n >= 0. \param[in] alpha alpha is REAL/DOUBLE PRECISION/COMPLEX/COMPLEX*16 On entry, alpha specifies the scalar alpha. \param[in ,out] x REAL/DOUBLE PRECISION/COMPLEX/COMPLEX*16 array The n-element vector x, in an array of length (n-1)*abs(incx) + 1. \param[in] incx incx is INTEGER Stride between elements of x. incx must not be zero. If incx < 0, uses elements of x in reverse order: x(n-1), ..., x(0). */ template< typename TA, typename TB > void scal( int64_t n, TA alpha, TB* x, int64_t incx ) { cblas_scal( n, alpha, x, incx ); } /*! \brief Copies a vector x to a vector y for arbitrary data types \b Purpose: COPY copies a vector x to a vector y.\n y = x \n Data precisions supported include SINGLE/DOUBLE PRECISION REAL, SINGLE PRECISION COMPLEX, DOUBLE PRECISION COMPLEX(COMPLEX*16) \param[in] n n is INTEGER Number of elements in x and y. n >= 0. \param[in] x REAL/DOUBLE PRECISION/COMPLEX/COMPLEX*16 array. The n-element vector x, in an array of length (n-1)*abs(incx) + 1. \param[in] incx incx is INTEGER. Stride between elements of x. incx must not be zero. If incx < 0, uses elements of x in reverse order: x(n-1), ..., x(0). \param[out] y REAL/DOUBLE PRECISION/COMPLEX/COMPLEX*16 array. The n-element vector y, in an array of length (n-1)*abs(incy) + 1. \param[in] incy incy is INTEGER. Stride between elements of y. incy must not be zero. If incy < 0, uses elements of y in reverse order: y(n-1), ..., y(0). */ template< typename T > void copy( int64_t n, T const *x, int64_t incx, T *y, int64_t incy ) { cblas_copy( n, x, incx, y, incy ); } /*! \brief Performs addition of scaled vector for arbitrary data types \b Purpose: AXPY constant times a vector plus a vector.\n y = alpha*x + y \n Data precisions supported include SINGLE/DOUBLE PRECISION REAL, SINGLE PRECISION COMPLEX, DOUBLE PRECISION COMPLEX(COMPLEX*16) \param[in] n n is INTEGER Number of elements in x and y. n >= 0. \param[in] alpha alpha is REAL/DOUBLE PRECISION/COMPLEX/COMPLEX*16 On entry, alpha specifies the scalar alpha.\n If alpha is zero, y is not updated. \param[in] x REAL/DOUBLE PRECISION/COMPLEX/COMPLEX*16 array. The n-element vector x, in an array of length (n-1)*abs(incx) + 1. \param[in] incx incx is INTEGER. Stride between elements of x. incx must not be zero. If incx < 0, uses elements of x in reverse order: x(n-1), ..., x(0). \param[out] y REAL/DOUBLE PRECISION/COMPLEX/COMPLEX*16 array. The n-element vector y, in an array of length (n-1)*abs(incy) + 1. \param[in] incy incy is INTEGER. Stride between elements of y. incy must not be zero. If incy < 0, uses elements of y in reverse order: y(n-1), ..., y(0). */ template< typename T > void axpy( int64_t n, T alpha, T const *x, int64_t incx, T *y, int64_t incy ) { cblas_axpy( n, alpha, x, incx, y, incy ); } /*! \brief Performs the dot product of two vectors for arbitrary data types \b Purpose: DOT forms the dot product of two vectors uses unrolled loops for increments equal to one.\n dot = x^T * y \n Data precisions supported include SINGLE/DOUBLE PRECISION REAL \param[in] n n is INTEGER Number of elements in x and y. n >= 0. \param[in] x REAL/DOUBLE PRECISION array. The n-element vector x, in an array of length (n-1)*abs(incx) + 1. \param[in] incx incx is INTEGER. Stride between elements of x. incx must not be zero. If incx < 0, uses elements of x in reverse order: x(n-1), ..., x(0). \param[in] y REAL/DOUBLE PRECISION array. The n-element vector y, in an array of length (n-1)*abs(incy) + 1. \param[in] incy incy is INTEGER. Stride between elements of y. incy must not be zero. If incy < 0, uses elements of y in reverse order: y(n-1), ..., y(0). \return Unconjugated dot product, x^T * y. REAL/DOUBLE PRECISION */ template< typename T, typename TR > TR dot( int64_t n, T const *x, int64_t incx, T const *y, int64_t incy ) { return cblas_dot( n, x, incx, y, incy ); } /*! \brief Performs the dot product of two complex vectors \b Purpose: DOTU forms the dot product of two complex vectors. \n CDOTU = X^T * Y \n Data precisions supported include SINGLE/DOUBLE PRECISION COMPLEX \param[in] n n is INTEGER Number of elements in x and y. n >= 0. \param[in] x REAL/DOUBLE PRECISION COMPLEX array. The n-element vector x, in an array of length (n-1)*abs(incx) + 1. \param[in] incx incx is INTEGER. Stride between elements of x. incx must not be zero. If incx < 0, uses elements of x in reverse order: x(n-1), ..., x(0). \param[in] y REAL/DOUBLE PRECISION COMPLEX array. The n-element vector y, in an array of length (n-1)*abs(incy) + 1. \param[in] incy incy is INTEGER. Stride between elements of y. incy must not be zero. If incy < 0, uses elements of y in reverse order: y(n-1), ..., y(0). \return Unconjugated dot product, x^T * y. REAL/DOUBLE PRECISION COMPLEX */ template< typename T > T dotu( int64_t n, T const *x, int64_t incx, T const *y, int64_t incy ) { return cblas_dotu( n, x, incx, y, incy ); } /*! \brief Performs the dot product of two complex vectors \b Purpose: DOTC forms the dot product of two complex vectors. \n CDOTU = X^H * Y \n Data precisions supported include SINGLE/DOUBLE PRECISION COMPLEX \param[in] n n is INTEGER Number of elements in x and y. n >= 0. \param[in] x REAL/DOUBLE PRECISION COMPLEX array. The n-element vector x, in an array of length (n-1)*abs(incx) + 1. \param[in] incx incx is INTEGER. Stride between elements of x. incx must not be zero. If incx < 0, uses elements of x in reverse order: x(n-1), ..., x(0). \param[in] y REAL/DOUBLE PRECISION COMPLEX array. The n-element vector y, in an array of length (n-1)*abs(incy) + 1. \param[in] incy incy is INTEGER. Stride between elements of y. incy must not be zero. If incy < 0, uses elements of y in reverse order: y(n-1), ..., y(0). \return Conjugated dot product, x^H * y. REAL/DOUBLE PRECISION COMPLEX */ template< typename T > T dotc( int64_t n, T const *x, int64_t incx, T const *y, int64_t incy ) { return cblas_dotc( n, x, incx, y, incy ); } /*! \brief Performs inner product of two vectors with extended precision accumulation \b Purpose: DOTC forms the inner product of two vectors with extended precision accumulation. \n Data precisions supported include SINGLE PRECISION REAL \param[in] n n is INTEGER\n number of elements in input vector(s) \param[in] alpha alpha is REAL\n single precision scalar to be added to inner product \param[in] x x is REAL array, dimension ( 1 + ( n - 1 )*abs( incx ) )\n single precision vector with n elements \param[in] incx incx is INTEGER\n storage spacing between elements of x \param[in] y y is REAL array, dimension ( 1 + ( n - 1 )*abs( incx ) )\n single precision vector with n elements \param[in] incy incy is INTEGER\n storage spacing between elements of y \return S.P. result with dot product accumulated in D.P. */ template< typename T > T sdsdot( int64_t n, T alpha, T const *x, int64_t incx, T const *y, int64_t incy ) { return cblas_sdsdot( n, alpha, x, incx, y, incy ); } /*! \brief return 2-norm of vectors of arbitrary data types \b Purpose: NRM2 returns the euclidean norm of a vector via the function name, so that SNRM2 := sqrt( x'*x ). \n Data precisions supported include SINGLE PRECISION REAL, DOUBLE PRECISION REAL, SINGLE PRECISION COMPLEX, DOUBLE PRECISION COMPLEX(COMPLEX*16) \param[in] n n is INTEGER\n number of elements in input vector(s) \param[in] x x is REAL/DOUBLE PRECISION/COMPLEX/COMPLEX*16 array, dimension ( 1 + ( n - 1 )*abs( incx ) )\n single precision vector with n elements \param[in] incx incx is INTEGER\n storage spacing between elements of x \return 2-norm of vector REAL SINGLE/DOUBLE PRECISION */ template< typename T > real_type nrm2( int64_t n, T const * x, int64_t incx ) { return cblas_nrm2( n, x, incx ); } /*! \brief return 1-norm of vector of arbitrary data types \b Purpose: ASUM takes the sum of the absolute values, uses unrolled loops for increment equal to one. \n ASUM := || Re(x) ||_1 + || Im(x) ||_1. \n Data precisions supported include SINGLE PRECISION REAL, DOUBLE PRECISION REAL, SINGLE PRECISION COMPLEX, DOUBLE PRECISION COMPLEX(COMPLEX*16) \param[in] n n is INTEGER\n number of elements in input vector(s) \param[in] x x is REAL/DOUBLE PRECISION/COMPLEX/COMPLEX*16 array, dimension ( 1 + ( n - 1 )*abs( incx ) )\n single precision vector with n elements \param[in] incx incx is INTEGER\n storage spacing between elements of x \return 1-norm of vector REAL SINGLE/DOUBLE PRECISION */ template< typename T > real_type asum( int64_t n, T const *x, int64_t incx ) { return cblas_asum( n, x, incx ); } /*! \brief Return Index of infinity-norm of vectors of arbitrary types. \b Purpose: IAMAX finds the index of the first element having maximum |Re(.)| + |Im(.)|. \n Data precisions supported include SINGLE PRECISION REAL, DOUBLE PRECISION REAL, SINGLE PRECISION COMPLEX, DOUBLE PRECISION COMPLEX(COMPLEX*16) \param[in] n n is INTEGER\n number of elements in input vector(s) \param[in] x x is REAL/DOUBLE PRECISION/COMPLEX/COMPLEX*16 array, dimension ( 1 + ( n - 1 )*abs( incx ) ) \n single precision vector with n elements \param[in] incx incx is INTEGER\n storage spacing between elements of x \return Index of infinity-norm of vector INTEGER */ template< typename T > int64_t iamax( int64_t n, T const *x, int64_t incx ) { return cblas_iamax( n, x, incx ); } /*! \brief Solve General matrix-vector multiply for arbitrary data types \b Purpose: GEMV performs one of the matrix-vector operations for arbitrary data types Data precisions supported include SINGLE PRECISION REAL, DOUBLE PRECISION REAL, SINGLE PRECISION COMPLEX, DOUBLE PRECISION COMPLEX(COMPLEX*16) y := alpha*A*x + beta*y, or y := alpha*A**T*x + beta*y, where alpha and beta are scalars, x and y are vectors and A is an m by n matrix. \param[in] layout layout is enum CBLAS_LAYOUT layout specifies Matrix storage as follows: layout = CBLAS_LAYOUT::CblasRowMajor or Layout::CblasColMajor. \param[in] trans trans is CBLAS_TRANSPOSE On entry, trans specifies the operation to be used as follows: \n trans = CBLAS_TRANSPOSE::CblasNoTrans,y := alpha*A*x + beta*y. \n trans = CBLAS_TRANSPOSE::CblasTrans, y := alpha*A**T*x + beta*y. \n trans = CBLAS_TRANSPOSE::CblasConjTrans, y := alpha*A**T*x + beta*y. \param[in] m m is INTEGER On entry, m specifies the number of rows of the matrix A. m must be at least zero. \param[in] n n is INTEGER On entry, n specifies the number of columns of the matrix A. n must be at least zero. \param[in] alpha alpha is REAL/DOUBLE PRECISION/COMPLEX/COMPLEX*16 On entry, alpha specifies the scalar alpha. \param[in] A A is REAL/DOUBLE PRECISION/COMPLEX/COMPLEX*16 array,dimension : m-by-n , stored in an lda-by-n array [RowMajor: m-by-lda]. \param[in] lda lda is INTEGER On entry, lda specifies the Leading dimension of A lda >= max(1, m) [RowMajor: lda >= max(1, n)]. \param[in] x x is REAL/DOUBLE PRECISION/COMPLEX/COMPLEX*16 array,dimension : \n If trans = CblasNoTrans: at least ( 1 + ( n - 1 )*abs( incx ) ). \n Otherwise: at least ( 1 + ( m - 1 )*abs( incx ) ). \param[in] incx incx is INTEGER On entry, incx specifies the increment for the elements of x. incx must not be zero. \param[in] beta beta is REAL/DOUBLE PRECISION/COMPLEX/COMPLEX*16 On entry, beta specifies the scalar alpha.When beta is supplied as zero then y need not be set on input. \param[in,out] y y is REAL/DOUBLE PRECISION/COMPLEX/COMPLEX*16 array, dimension : \n If trans = CblasNoTrans: at least ( 1 + ( m - 1 )*abs( incy ) ). \n Otherwise: at least ( 1 + ( n - 1 )*abs( incy ) ). \n Before entry with beta non-zero, the incremented array y must contain the vector y. On exit, y is overwritten by the updated vector y. \param[in] incy incy is INTEGER On entry, incy specifies the increment for the elements of y. incy must not be zero. */ template< typename T > void gemv( CBLAS_ORDER layout, CBLAS_TRANSPOSE trans, int64_t m, int64_t n, T alpha, T const *A, int64_t lda, T const *x, int64_t incx, T beta, T *y, int64_t incy ) { cblas_gemv(layout, trans, m, n, alpha, A, lda, x, incx, beta, y, incy); } /*! \brief Solve General matrix-vector multiply for arbitrary data types \b Purpose: GBMV performs one of the matrix-vector operations for arbitrary data types Data precisions supported include SINGLE PRECISION REAL, DOUBLE PRECISION REAL, SINGLE PRECISION COMPLEX, DOUBLE PRECISION COMPLEX(COMPLEX*16) y := alpha*A*x + beta*y, or y := alpha*A**T*x + beta*y, or y := alpha*A**H*x + beta*y, where alpha and beta are scalars, x and y are vectors and A is an m by n matrix with kl sub-diagonals and ku super-diagonals. \param[in] layout layout is enum CBLAS_LAYOUT layout specifies Matrix storage as follows: layout = CBLAS_LAYOUT::CblasRowMajor or Layout::CblasColMajor. \param[in] trans trans is CBLAS_TRANSPOSE On entry, trans specifies the operation to be used as follows: \n trans = CBLAS_TRANSPOSE::CblasNoTrans,y := alpha*A*x + beta*y. \n trans = CBLAS_TRANSPOSE::CblasTrans, y := alpha*A**T*x + beta*y. \n trans = CBLAS_TRANSPOSE::CblasConjTrans, y := alpha*A**H*x + beta*y. \param[in] m m is INTEGER On entry, m specifies the number of rows of the matrix A. m must be at least zero. \param[in] n n is INTEGER On entry, n specifies the number of columns of the matrix A. n must be at least zero. \param[in] kl kl is INTEGER On entry, kl specifies the number of sub-diagonals of the matrix A. kl must be at least zero. \param[in] ku ku is INTEGER On entry, ku specifies the number of super-diagonals of the matrix A. ku must be at least zero. \param[in] alpha alpha is REAL/DOUBLE PRECISION/COMPLEX/COMPLEX*16 On entry, alpha specifies the scalar alpha. \param[in] A A is REAL/DOUBLE PRECISION/COMPLEX/COMPLEX*16 array,dimension lda-by-n. Before entry, the leading ( kl + ku + 1 ) by n part of the array A must contain the matrix of coefficients, supplied column by column, with the leading diagonal of the matrix in row ( ku + 1 ) of the array, the first super-diagonal starting at position 2 in row ku, the first sub-diagonal starting at position 1 in row ( ku + 2 ), and so on. Elements in the array A that do not correspond to elements in the band matrix (such as the top left ku by ku triangle) are not referenced. \param[in] lda lda is INTEGER On entry, lda specifies the Leading dimension of A lda >= ( kl + ku + 1 ) \param[in] x x is REAL/DOUBLE PRECISION/COMPLEX/COMPLEX*16 array,dimension : \n If trans = CblasNoTrans: at least ( 1 + ( n - 1 )*abs( incx ) ). \n Otherwise: at least ( 1 + ( m - 1 )*abs( incx ) ). \n Before entry, the incremented array x must contain the vector x. \param[in] incx incx is INTEGER On entry, incx specifies the increment for the elements of x. incx must not be zero. \param[in] beta beta is REAL/DOUBLE PRECISION/COMPLEX/COMPLEX*16 On entry, beta specifies the scalar alpha.When beta is supplied as zero then y need not be set on input. \param[in,out] y y is REAL/DOUBLE PRECISION/COMPLEX/COMPLEX*16 array, dimension : \n If trans = CblasNoTrans: at least ( 1 + ( m - 1 )*abs( incy ) ). \n Otherwise: at least ( 1 + ( n - 1 )*abs( incy ) ). \n Before entry with beta non-zero, the incremented array y must contain the vector y. On exit, y is overwritten by the updated vector y. \param[in] incy incy is INTEGER On entry, incy specifies the increment for the elements of y. incy must not be zero. */ template< typename T > void gbmv( CBLAS_ORDER layout, CBLAS_TRANSPOSE trans, int64_t m, int64_t n, int64_t kl, int64_t ku, T alpha, T const *A, int64_t lda, T const *x, int64_t incx, T beta, T *y, int64_t incy ) { cblas_gbmv(layout, trans, m, n, kl, ku, alpha, A, lda, x, incx, beta, y, incy); } /*! \brief Solves Hermitian matrix-vector multiply for arbitrary data types \b Purpose: HEMV performs one of the matrix-vector operations for arbitrary data types Data precisions supported include SINGLE PRECISION COMPLEX, DOUBLE PRECISION COMPLEX(COMPLEX*16) y := alpha*A*x + beta*y, where alpha and beta are scalars, x and y are n element vectors and A is an n by n hermitian matrix. \param[in] layout layout is enum CBLAS_LAYOUT layout specifies Matrix storage as follows: layout = CBLAS_LAYOUT::CblasRowMajor or Layout::CblasColMajor. \param[in] uplo uplo is enum CBLAS_UPLO uplo specifies specifies whether the matrix A is an upper or lower triangular matrix as follows: \n uplo = CBLAS_UPLO::CblasUpper A is an upper triangular matrix. \n uplo = CBLAS_UPLO::CblasLower A is a lower triangular matrix. \param[in] n n is INTEGER On entry, n specifies the order of the matrix A.n must be at least zero. \param[in] alpha alpha is COMPLEX/COMPLEX*16 On entry, alpha specifies the scalar alpha. \param[in] A A is COMPLEX/COMPLEX*16 array,dimension lda-by-n. \n Before entry with UPLO = CblasUpper, the leading n by n upper triangular part of the array A must contain the upper triangular part of the hermitian matrix and the strictly lower triangular part of A is not referenced. Before entry with UPLO = CblasLower, the leading n by n lower triangular part of the array A must contain the lower triangular part of the hermitian matrix and the strictly upper triangular part of A is not referenced. \n Note that the imaginary parts of the diagonal elements need not be set and are assumed to be zero. \param[in] lda lda is INTEGER On entry, lda specifies the Leading dimension of A lda must be at least max( 1, n ). \param[in] x x is COMPLEX/COMPLEX*16 array,dimension : \n at least ( 1 + ( n - 1 )*abs( incx ) ). \n Before entry, the incremented array x must contain the vector x. \param[in] incx incx is INTEGER On entry, incx specifies the increment for the elements of x. incx must not be zero. \param[in] beta beta is COMPLEX/COMPLEX*16 On entry, beta specifies the scalar alpha.When beta is supplied as zero then y need not be set on input. \param[in,out] y y is COMPLEX/COMPLEX*16 array, dimension : \n at least ( 1 + ( n - 1 )*abs( incy ) ). \n Before entry with beta non-zero, the incremented array y must contain the vector y. On exit, y is overwritten by the updated vector y. \param[in] incy incy is INTEGER On entry, incy specifies the increment for the elements of y. incy must not be zero. */ template< typename T > void hemv( CBLAS_ORDER layout, CBLAS_UPLO uplo, int64_t n, T alpha, T const *A, int64_t lda, T const *x, int64_t incx, T beta, T *y, int64_t incy ) { cblas_hemv(layout, uplo, n, alpha, A, lda, x, incx, beta, y, incy); } /*! \brief Solves Hermitian matrix-vector multiply for arbitrary data types \b Purpose: HBMV performs one of the matrix-vector operations for arbitrary data types Data precisions supported include SINGLE PRECISION COMPLEX, DOUBLE PRECISION COMPLEX(COMPLEX*16) y := alpha*A*x + beta*y, where alpha and beta are scalars, x and y are n element vectors and A is an n by n hermitian matrix with k super-diagonals. \param[in] layout layout is enum CBLAS_LAYOUT layout specifies Matrix storage as follows: layout = CBLAS_LAYOUT::CblasRowMajor or Layout::CblasColMajor. \param[in] uplo uplo is enum CBLAS_UPLO uplo specifies specifies whether the the upper or lower triangular part of the band matrix A is being supplied as follows: \n uplo = CBLAS_UPLO::CblasUpper A is an upper triangular matrix. \n uplo = CBLAS_UPLO::CblasLower A is a lower triangular matrix. \param[in] n n is INTEGER On entry, n specifies the order of the matrix A.n must be at least zero. \param[in] k k is INTEGER On entry, k specifies the number of super-diagonals of the matrix A. k must be at least zero. \param[in] alpha alpha is COMPLEX/COMPLEX*16 On entry, alpha specifies the scalar alpha. \param[in] A A is COMPLEX/COMPLEX*16 array,dimension lda-by-n. \n Before entry with UPLO = CblasUpper, the leading ( k + 1 ) by n part of the array A must contain the upper triangular band part of the hermitian matrix, supplied column by column, with the leading diagonal of the matrix in row ( k + 1 ) of the array, the first super-diagonal starting at position 2 in row k, and so on. The top left k by k triangle of the array A is not referenced. \n Before entry with UPLO = CblasLower, the leading ( k + 1 ) by n part of the array A must contain the lower triangular band part of the hermitian matrix, supplied column by column, with the leading diagonal of the matrix in row 1 of the array, the first sub-diagonal starting at position 1 in row 2, and so on. The bottom right k by k triangle of the array A is not referenced. \n Note that the imaginary parts of the diagonal elements need not be set and are assumed to be zero. \param[in] lda lda is INTEGER On entry, lda specifies the Leading dimension of A lda must be at least ( k + 1 ). \param[in] x x is COMPLEX/COMPLEX*16 array,dimension : \n at least ( 1 + ( n - 1 )*abs( incx ) ). \n Before entry, the incremented array x must contain the vector x. \param[in] incx incx is INTEGER On entry, incx specifies the increment for the elements of x. incx must not be zero. \param[in] beta beta is COMPLEX/COMPLEX*16 On entry, beta specifies the scalar alpha. \param[in,out] y y is COMPLEX/COMPLEX*16 array, dimension : \n at least ( 1 + ( n - 1 )*abs( incy ) ). \n Before entry with beta non-zero, the incremented array y must contain the vector y. On exit, y is overwritten by the updated vector y. \param[in] incy incy is INTEGER On entry, incy specifies the increment for the elements of y. incy must not be zero. */ template< typename T > void hbmv( CBLAS_ORDER layout, CBLAS_UPLO uplo, int64_t n, int64_t k, T alpha, T const *A, int64_t lda, T const *x, int64_t incx, T beta, T *y, int64_t incy ) { cblas_hbmv(layout, uplo, n, k, alpha, A, lda, x, incx, beta, y, incy); } /*! \brief Solves Hermitian matrix-vector multiply for arbitrary data types \b Purpose: HPMV performs one of the matrix-vector operations for arbitrary data types Data precisions supported include SINGLE PRECISION COMPLEX, DOUBLE PRECISION COMPLEX(COMPLEX*16) y := alpha*A*x + beta*y, where alpha and beta are scalars, x and y are n element vectors and A is an n by n hermitian matrix, supplied in packed form. \param[in] layout layout is enum CBLAS_LAYOUT layout specifies Matrix storage as follows: layout = CBLAS_LAYOUT::CblasRowMajor or Layout::CblasColMajor. \param[in] uplo uplo is enum CBLAS_UPLO uplo specifies specifies whether the the upper or lower triangular part of the band matrix A is supplied in the packed array Ap as follows: \n uplo = CBLAS_UPLO::CblasUpper A is an upper triangular matrix. \n uplo = CBLAS_UPLO::CblasLower A is a lower triangular matrix. \param[in] n n is INTEGER On entry, n specifies the order of the matrix A.n must be at least zero. \param[in] alpha alpha is COMPLEX/COMPLEX*16 On entry, alpha specifies the scalar alpha. \param[in] Ap Ap is COMPLEX/COMPLEX*16 array,dimension atleast ( ( n*( n + 1 ) )/2 ). \n Before entry with UPLO = CblasUpper, the array Ap must contain the upper triangular part of the hermitian matrix packed sequentially, column by column, so that Ap( 1 ) contains a( 1, 1 ), Ap( 2 ) and Ap( 3 ) contain a( 1, 2 ) and a( 2, 2 ) respectively, and so on. \n Before entry with UPLO = CblasLower, the array Ap must contain the lower triangular part of the hermitian matrix packed sequentially, column by column, so that Ap( 1 ) contains a( 1, 1 ), Ap( 2 ) and Ap( 3 ) contain a( 2, 1 ) and a( 3, 1 ) respectively, and so on. \n Note that the imaginary parts of the diagonal elements need not be set and are assumed to be zero. \param[in] x x is COMPLEX/COMPLEX*16 array,dimension : \n at least ( 1 + ( n - 1 )*abs( incx ) ). \n Before entry, the incremented array x must contain the vector x. \param[in] incx incx is INTEGER On entry, incx specifies the increment for the elements of x. incx must not be zero. \param[in] beta beta is COMPLEX/COMPLEX*16 On entry, beta specifies the scalar alpha.When beta is supplied as zero then y need not be set on input. \param[in,out] y y is COMPLEX/COMPLEX*16 array, dimension : \n at least ( 1 + ( n - 1 )*abs( incy ) ). \n Before entry with beta non-zero, the incremented array y must contain the vector y. On exit, y is overwritten by the updated vector y. \param[in] incy incy is INTEGER On entry, incy specifies the increment for the elements of y. incy must not be zero. */ template< typename T > void hpmv( CBLAS_ORDER layout, CBLAS_UPLO uplo, int64_t n, T alpha, T const *Ap, T const *x, int64_t incx, T beta, T *y, int64_t incy ) { cblas_hpmv(layout, uplo, n, alpha, Ap, x, incx, beta, y, incy); } /*! \brief Solves Symmetric matrix-vector multiply for arbitrary data types \b Purpose: SYMV performs one of the matrix-vector operations for arbitrary data types Data precisions supported include SINGLE PRECISION REAL, DOUBLE PRECISION REAL y := alpha*A*x + beta*y, where alpha and beta are scalars, x and y are n element vectors and A is an n by n symmetric matrix. \param[in] layout layout is enum CBLAS_LAYOUT layout specifies Matrix storage as follows: layout = CBLAS_LAYOUT::CblasRowMajor or Layout::CblasColMajor. \param[in] uplo uplo is enum CBLAS_UPLO uplo specifies specifies whether the matrix A is an upper or lower triangular matrix as follows: \n uplo = CBLAS_UPLO::CblasUpper A is an upper triangular matrix. \n uplo = CBLAS_UPLO::CblasLower A is a lower triangular matrix. \param[in] n n is INTEGER On entry, n specifies the order of the matrix A.n must be at least zero. \param[in] alpha alpha is SINGLE/DOUBLE PRECISION REAL On entry, alpha specifies the scalar alpha. \param[in] A A is SINGLE/DOUBLE PRECISION REAL array,dimension lda-by-n. \n Before entry with UPLO = CblasUpper, the leading n by n upper triangular part of the array A must contain the upper triangular part of the symmetric matrix and the strictly lower triangular part of A is not referenced. Before entry with UPLO = CblasLower, the leading n by n lower triangular part of the array A must contain the lower triangular part of the symmetric matrix and the strictly upper triangular part of A is not referenced. \n \param[in] lda lda is INTEGER On entry, lda specifies the Leading dimension of A lda must be at least max( 1, n ). \param[in] x x is SINGLE/DOUBLE PRECISION REAL array,dimension : \n at least ( 1 + ( n - 1 )*abs( incx ) ). \n Before entry, the incremented array x must contain the vector x. \param[in] incx incx is INTEGER On entry, incx specifies the increment for the elements of x. incx must not be zero. \param[in] beta beta is SINGLE/DOUBLE PRECISION REAL On entry, beta specifies the scalar alpha.When beta is supplied as zero then y need not be set on input. \param[in,out] y y is SINGLE/DOUBLE PRECISION REAL array, dimension : \n at least ( 1 + ( n - 1 )*abs( incy ) ). \n Before entry with beta non-zero, the incremented array y must contain the vector y. On exit, y is overwritten by the updated vector y. \param[in] incy incy is INTEGER On entry, incy specifies the increment for the elements of y. incy must not be zero. */ template< typename T > void symv( CBLAS_ORDER layout, CBLAS_UPLO uplo, int64_t n, T alpha, T const *A, int64_t lda, T const *x, int64_t incx, T beta, T *y, int64_t incy ) { cblas_symv(layout, uplo, n, alpha, A, lda, x, incx, beta, y, incy); } /*! \brief Solves symmetric matrix-vector multiply for arbitrary data types \b Purpose: SBMV performs one of the matrix-vector operations for arbitrary data types Data precisions supported include SINGLE PRECISION REAL, DOUBLE PRECISION REAL y := alpha*A*x + beta*y, where alpha and beta are scalars, x and y are n element vectors and A is an n by n symmetric matrix with k super-diagonals. \param[in] layout layout is enum CBLAS_LAYOUT layout specifies Matrix storage as follows: layout = CBLAS_LAYOUT::CblasRowMajor or Layout::CblasColMajor. \param[in] uplo uplo is enum CBLAS_UPLO uplo specifies specifies whether the the upper or lower triangular part of the band matrix A is being supplied as follows: \n uplo = CBLAS_UPLO::CblasUpper A is an upper triangular matrix. \n uplo = CBLAS_UPLO::CblasLower A is a lower triangular matrix. \param[in] n n is INTEGER On entry, n specifies the order of the matrix A.n must be at least zero. \param[in] k k is INTEGER On entry, k specifies the number of super-diagonals of the matrix A. k must be at least zero. \param[in] alpha alpha is SINGLE/DOUBLE PRECISION REAL On entry, alpha specifies the scalar alpha. \param[in] A A is SINGLE/DOUBLE PRECISION REAL array,dimension lda-by-n. \n Before entry with UPLO = CblasUpper, the leading ( k + 1 ) by n part of the array A must contain the upper triangular band part of the symmetric matrix, supplied column by column, with the leading diagonal of the matrix in row ( k + 1 ) of the array, the first super-diagonal starting at position 2 in row k, and so on. The top left k by k triangle of the array A is not referenced. \n Before entry with UPLO = CblasLower, the leading ( k + 1 ) by n part of the array A must contain the lower triangular band part of the symmetric matrix, supplied column by column, with the leading diagonal of the matrix in row 1 of the array, the first sub-diagonal starting at position 1 in row 2, and so on. The bottom right k by k triangle of the array A is not referenced. \n Note that the imaginary parts of the diagonal elements need not be set and are assumed to be zero. \param[in] lda lda is INTEGER On entry, lda specifies the Leading dimension of A lda must be at least ( k + 1 ). \param[in] x x is SINGLE/DOUBLE PRECISION REAL array,dimension : \n at least ( 1 + ( n - 1 )*abs( incx ) ). \n Before entry, the incremented array x must contain the vector x. \param[in] incx incx is INTEGER On entry, incx specifies the increment for the elements of x. incx must not be zero. \param[in] beta beta is SINGLE/DOUBLE PRECISION REAL On entry, beta specifies the scalar alpha. \param[in,out] y y is SINGLE/DOUBLE PRECISION REAL array, dimension : \n at least ( 1 + ( n - 1 )*abs( incy ) ). \n Before entry with beta non-zero, the incremented array y must contain the vector y. On exit, y is overwritten by the updated vector y. \param[in] incy incy is INTEGER On entry, incy specifies the increment for the elements of y. incy must not be zero. */ template< typename T > void sbmv( CBLAS_ORDER layout, CBLAS_UPLO uplo, int64_t n, int64_t k, T alpha, T const *A, int64_t lda, T const *x, int64_t incx, T beta, T *y, int64_t incy ) { cblas_sbmv(layout, uplo, n, k, alpha, A, lda, x, incx, beta, y, incy); } /*! \brief Solves symmetric matrix-vector multiply for arbitrary data types \b Purpose: SPMV performs one of the matrix-vector operations for arbitrary data types Data precisions supported include SINGLE PRECISION REAL, DOUBLE PRECISION REAL y := alpha*A*x + beta*y, where alpha and beta are scalars, x and y are n element vectors and A is an n by n symmetric matrix, supplied in packed form. \param[in] layout layout is enum CBLAS_LAYOUT layout specifies Matrix storage as follows: layout = CBLAS_LAYOUT::CblasRowMajor or Layout::CblasColMajor. \param[in] uplo uplo is enum CBLAS_UPLO uplo specifies specifies whether the the upper or lower triangular part of the band matrix A is supplied in the packed array Ap as follows: \n uplo = CBLAS_UPLO::CblasUpper A is an upper triangular matrix. \n uplo = CBLAS_UPLO::CblasLower A is a lower triangular matrix. \param[in] n n is INTEGER On entry, n specifies the order of the matrix A.n must be at least zero. \param[in] alpha alpha is SINGLE/DOUBLE PRECISION REAL On entry, alpha specifies the scalar alpha. \param[in] Ap Ap is SINGLE/DOUBLE PRECISION REAL array,dimension atleast ( ( n*( n + 1 ) )/2 ). \n Before entry with UPLO = CblasUpper, the array Ap must contain the upper triangular part of the symmetric matrix packed sequentially, column by column, so that Ap( 1 ) contains a( 1, 1 ), Ap( 2 ) and Ap( 3 ) contain a( 1, 2 ) and a( 2, 2 ) respectively, and so on. \n Before entry with UPLO = CblasLower, the array Ap must contain the lower triangular part of the symmetric matrix packed sequentially, column by column, so that Ap( 1 ) contains a( 1, 1 ), Ap( 2 ) and Ap( 3 ) contain a( 2, 1 ) and a( 3, 1 ) respectively, and so on. \n Note that the imaginary parts of the diagonal elements need not be set and are assumed to be zero. \param[in] x x is SINGLE/DOUBLE PRECISION REAL array,dimension : \n at least ( 1 + ( n - 1 )*abs( incx ) ). \n Before entry, the incremented array x must contain the vector x. \param[in] incx incx is INTEGER On entry, incx specifies the increment for the elements of x. incx must not be zero. \param[in] beta beta is SINGLE/DOUBLE PRECISION REAL On entry, beta specifies the scalar alpha.When beta is supplied as zero then y need not be set on input. \param[in,out] y y is SINGLE/DOUBLE PRECISION REAL array, dimension : \n at least ( 1 + ( n - 1 )*abs( incy ) ). \n Before entry with beta non-zero, the incremented array y must contain the vector y. On exit, y is overwritten by the updated vector y. \param[in] incy incy is INTEGER On entry, incy specifies the increment for the elements of y. incy must not be zero. */ template< typename T > void spmv( CBLAS_ORDER layout, CBLAS_UPLO uplo, int64_t n, T alpha, T const *Ap, T const *x, int64_t incx, T beta, T *y, int64_t incy ) { cblas_spmv(layout, uplo, n, alpha, Ap, x, incx, beta, y, incy); } /*! \brief Solve the one of the matrix-vector operations for arbitrary data types \b Purpose: TRMV performs one of the matrix-vector operations for arbitrary data types Data precisions supported include SINGLE PRECISION REAL, DOUBLE PRECISION REAL, SINGLE PRECISION COMPLEX, DOUBLE PRECISION COMPLEX(COMPLEX*16) x := A*x, or x := A**T*x, where x is an n element vector and A is an n by n unit, or non-unit, upper or lower triangular matrix. \param[in] layout layout is enum CBLAS_ORDER layout specifies Matrix storage as follows: layout = CBLAS_ORDER::CblasRowMajor or Layout::CblasColMajor. \param[in] uplo uplo is enum CBLAS_UPLO. uplo specifies specifies whether the matrix A is an upper or lower triangular matrix as follows: \n uplo = CBLAS_UPLO::CblasUpper A is an upper triangular matrix. \n uplo = CBLAS_UPLO::CblasLower A is a lower triangular matrix. \param[in] trans trans is CBLAS_TRANSPOSE On entry, trans specifies the operation to be performed as follows: trans = CBLAS_TRANSPOSE::CblasNoTrans, x := A*x. \n trans = CBLAS_TRANSPOSE::CblasTrans, x := A**T*x. \n trans = CBLAS_TRANSPOSE::CblasConjTrans, x := A**T*x. \param[in] diag diag is enum CBLAS_DIAG diag specifies specifies whether or not A is unit triangular as follows: \n diag = CBLAS_DIAG::CblasUnit A is assumed to be unit triangular.\n diag = CBLAS_DIAG::CblasNonUnit A is not assumed to be unit triangular. \param[in] n n is INTEGER On entry, n specifies the order of the matrix A.n must be at least zero. \param[in] A A is REAL/DOUBLE PRECISION/COMPLEX/COMPLEX*16 array,dimension ( lda, n )\n Before entry with UPLO = CblasUpper, the leading n by n upper triangular part of the array A must contain the upper triangular matrix and the strictly lower triangular part of A is not referenced. \n Before entry with UPLO = CblasLower, the leading n by n lower triangular part of the array A must contain the lower triangular matrix and the strictly upper triangular part of A is not referenced. \n Note that when DIAG = CblasUnit, the diagonal elements of A are not referenced either, but are assumed to be unity. \param[in] lda lda is INTEGER On entry, lda specifies the Leading dimension of A lda must be at least max( 1, n ). \param[in, out] x x is REAL/DOUBLE PRECISION/COMPLEX/COMPLEX*16 array,dimension : \n at least ( 1 + ( n - 1 )*abs( incx ) ). \n Before entry, the incremented array x must contain the vector x.On exit, x is overwritten with the transformed vector x. \param[in] incx incx is INTEGER On entry, incx specifies the increment for the elements of x. incx must not be zero. */ template< typename T > void trmv( CBLAS_ORDER layout, CBLAS_UPLO uplo, CBLAS_TRANSPOSE trans, CBLAS_DIAG diag, int64_t n, T const *A, int64_t lda, T *x, int64_t incx ) { cblas_trmv(layout, uplo, trans, diag, n, A, lda, x, incx); } /*! \brief Solve the one of the matrix-vector operations for arbitrary data types \b Purpose: TBMV performs one of the matrix-vector operations for arbitrary data types Data precisions supported include SINGLE PRECISION REAL, DOUBLE PRECISION REAL, SINGLE PRECISION COMPLEX, DOUBLE PRECISION COMPLEX(COMPLEX*16) x := A*x, or x := A**T*x, where x is an n element vector and A is an n by n unit, or non-unit, upper or lower triangular band matrix, with ( k + 1 ) diagonals. \param[in] layout layout is enum CBLAS_ORDER layout specifies Matrix storage as follows: layout = CBLAS_ORDER::CblasRowMajor or Layout::CblasColMajor. \param[in] uplo uplo is enum CBLAS_UPLO. uplo specifies specifies whether the matrix A is an upper or lower triangular matrix as follows: \n uplo = CBLAS_UPLO::CblasUpper A is an upper triangular matrix. \n uplo = CBLAS_UPLO::CblasLower A is a lower triangular matrix. \param[in] trans trans is CBLAS_TRANSPOSE On entry, trans specifies the operation to be performed as follows: trans = CBLAS_TRANSPOSE::CblasNoTrans, x := A*x. \n trans = CBLAS_TRANSPOSE::CblasTrans, x := A**T*x. \n trans = CBLAS_TRANSPOSE::CblasConjTrans, x := A**T*x. \param[in] diag diag is enum CBLAS_DIAG diag specifies specifies whether or not A is unit triangular as follows: \n diag = CBLAS_DIAG::CblasUnit A is assumed to be unit triangular.\n diag = CBLAS_DIAG::CblasNonUnit A is not assumed to be unit triangular. \param[in] n n is INTEGER On entry, n specifies the order of the matrix A.n must be at least zero. \param[in] k k is INTEGER On entry with UPLO = CblasUpper, k specifies the number of super-diagonals of the matrix A. On entry with UPLO = CblasLower, k specifies the number of sub-diagonals of the matrix A. k must at least zero. \param[in] A A is REAL/DOUBLE PRECISION/COMPLEX/COMPLEX*16 array,dimension ( lda, n )\n Before entry with UPLO = CblasUpper, the leading ( k + 1 ) by n part of the array A must contain the upper triangular band part of the matrix of coefficients, supplied column by column, with the leading diagonal of the matrix in row ( k + 1 ) of the array, the first super-diagonal starting at position 2 in row k, and so on. The top left k by k triangle of the array A is not referenced. \n Before entry with UPLO = CblasLower, the leading ( k + 1 ) by n part of the array A must contain the lower triangular band part of the matrix of coefficients, supplied column by column, with the leading diagonal of the matrix in row 1 of the array, the first sub-diagonal starting at position 1 in row 2, and so on. The bottom right k by k triangle of the array A is not referenced. \n Note that when DIAG = CblasUnit the elements of the array A corresponding to the diagonal elements of the matrix are not referenced, but are assumed to be unity. \param[in] lda lda is INTEGER On entry, lda specifies the Leading dimension of A lda must be at least max( 1, ( k + 1 ) ). \param[in, out] x x is REAL/DOUBLE PRECISION/COMPLEX/COMPLEX*16 array,dimension : \n at least ( 1 + ( n - 1 )*abs( incx ) ). \n Before entry, the incremented array x must contain the vector x.On exit, x is overwritten with the transformed vector x. \param[in] incx incx is INTEGER On entry, incx specifies the increment for the elements of x. incx must not be zero. */ template< typename T > void tbmv( CBLAS_ORDER layout, CBLAS_UPLO uplo, CBLAS_TRANSPOSE trans, CBLAS_DIAG diag, int64_t n, int64_t k, T const *A, int64_t lda, T *x, int64_t incx ) { cblas_tbmv(layout, uplo, trans, diag, n, k, A, lda, x, incx); } /*! \brief Solve the one of the matrix-vector operations for arbitrary data types \b Purpose: TPMV performs one of the matrix-vector operations for arbitrary data types Data precisions supported include SINGLE PRECISION REAL, DOUBLE PRECISION REAL, SINGLE PRECISION COMPLEX, DOUBLE PRECISION COMPLEX(COMPLEX*16) x := A*x, or x := A**T*x, where x is an n element vector and A is an n by n unit, or non-unit, upper or lower triangular matrix, supplied in packed form. \param[in] layout layout is enum CBLAS_ORDER layout specifies Matrix storage as follows: layout = CBLAS_ORDER::CblasRowMajor or Layout::CblasColMajor. \param[in] uplo uplo is enum CBLAS_UPLO. uplo specifies specifies whether the matrix A is an upper or lower triangular matrix as follows: \n uplo = CBLAS_UPLO::CblasUpper A is an upper triangular matrix. \n uplo = CBLAS_UPLO::CblasLower A is a lower triangular matrix. \param[in] trans trans is CBLAS_TRANSPOSE On entry, trans specifies the operation to be performed as follows: trans = CBLAS_TRANSPOSE::CblasNoTrans, x := A*x. \n trans = CBLAS_TRANSPOSE::CblasTrans, x := A**T*x. \n trans = CBLAS_TRANSPOSE::CblasConjTrans, x := A**T*x. \param[in] diag diag is enum CBLAS_DIAG diag specifies specifies whether or not A is unit triangular as follows: \n diag = CBLAS_DIAG::CblasUnit A is assumed to be unit triangular.\n diag = CBLAS_DIAG::CblasNonUnit A is not assumed to be unit triangular. \param[in] n n is INTEGER On entry, n specifies the order of the matrix A.n must be at least zero. \param[in] Ap Ap is REAL/DOUBLE PRECISION/COMPLEX/COMPLEX*16 array,dimension ( ( n*( n + 1 ) )/2 ). \n Before entry with UPLO = CblasUpper, the array Ap must contain the upper triangular matrix packed sequentially, column by column, so that Ap( 1 ) contains a( 1, 1 ), Ap( 2 ) and Ap( 3 ) contain a( 1, 2 ) and a( 2, 2 ) respectively, and so on. \n Before entry with UPLO = CblasLower, the array Ap must contain the lower triangular matrix packed sequentially, column by column, so that Ap( 1 ) contains a( 1, 1 ), Ap( 2 ) and Ap( 3 ) contain a( 2, 1 ) and a( 3, 1 ) respectively, and so on. \n Note that when DIAG = CblasUnit, the diagonal elements of A are not referenced, but are assumed to be unity. \param[in, out] x x is REAL/DOUBLE PRECISION/COMPLEX/COMPLEX*16 array,dimension : \n at least ( 1 + ( n - 1 )*abs( incx ) ). \n Before entry, the incremented array x must contain the vector x.On exit, x is overwritten with the transformed vector x. \param[in] incx incx is INTEGER On entry, incx specifies the increment for the elements of x. incx must not be zero. */ template< typename T > void tpmv( CBLAS_ORDER layout, CBLAS_UPLO uplo, CBLAS_TRANSPOSE trans, CBLAS_DIAG diag, int64_t n, T const *Ap, T *x, int64_t incx ) { cblas_tpmv(layout, uplo, trans, diag, n, Ap, x, incx); } /*! \brief Solve the one of the triangular matrix-vector equation for arbitrary data types \b Purpose: TRSV solves one of the systems of equations for arbitrary data types Data precisions supported include SINGLE PRECISION REAL, DOUBLE PRECISION REAL, SINGLE PRECISION COMPLEX, DOUBLE PRECISION COMPLEX(COMPLEX*16) A*x = b, or A**T*x = b, where b and x are n element vectors and A is an n by n unit, or non-unit, upper or lower triangular matrix \param[in] layout layout is enum CBLAS_ORDER layout specifies Matrix storage as follows: layout = CBLAS_ORDER::CblasRowMajor or Layout::CblasColMajor. \param[in] uplo uplo is enum CBLAS_UPLO. uplo specifies specifies whether the matrix A is an upper or lower triangular matrix as follows: \n uplo = CBLAS_UPLO::CblasUpper A is an upper triangular matrix. \n uplo = CBLAS_UPLO::CblasLower A is a lower triangular matrix. \param[in] trans trans is CBLAS_TRANSPOSE On entry, trans specifies the operation to be performed as follows: trans = CBLAS_TRANSPOSE::CblasNoTrans, A*x = b. \n trans = CBLAS_TRANSPOSE::CblasTrans, A**T*x = b. \n trans = CBLAS_TRANSPOSE::CblasConjTrans, A**T*x = b. \param[in] diag diag is enum CBLAS_DIAG diag specifies specifies whether or not A is unit triangular as follows: \n diag = CBLAS_DIAG::CblasUnit A is assumed to be unit triangular.\n diag = CBLAS_DIAG::CblasNonUnit A is not assumed to be unit triangular. \param[in] n n is INTEGER On entry, n specifies the order of the matrix A.n must be at least zero. \param[in] A A is REAL/DOUBLE PRECISION/COMPLEX/COMPLEX*16 array,dimension ( lda, n )\n Before entry with UPLO = CblasUpper, the leading n by n upper triangular part of the array A must contain the upper triangular matrix and the strictly lower triangular part of A is not referenced. \n Before entry with UPLO = CblasLower, the leading n by n lower triangular part of the array A must contain the lower triangular matrix and the strictly upper triangular part of A is not referenced. \n Note that when DIAG = CblasUnit, the diagonal elements of A are not referenced either, but are assumed to be unity. \param[in] lda lda is INTEGER On entry, lda specifies the Leading dimension of A lda must be at least max( 1, n ). \param[in, out] x x is REAL/DOUBLE PRECISION/COMPLEX/COMPLEX*16 array,dimension : at least ( 1 + ( n - 1 )*abs( incx ) ). \n Before entry, the incremented array x must contain the element right-hand side vector b.On exit, x is overwritten with the transformed vector x. \param[in] incx incx is INTEGER On entry, incx specifies the increment for the elements of x. incx must not be zero. */ template< typename T > void trsv( CBLAS_ORDER layout, CBLAS_UPLO uplo, CBLAS_TRANSPOSE trans, CBLAS_DIAG diag, int64_t n, T const *A, int64_t lda, T *x, int64_t incx ) { cblas_trsv(layout, uplo, trans, diag, n, A, lda, x, incx); } /*! \brief Solve the one of the triangular matrix-vector equation for arbitrary data types \b Purpose: TBSV solves one of the systems of equations for arbitrary data types Data precisions supported include SINGLE PRECISION REAL, DOUBLE PRECISION REAL, SINGLE PRECISION COMPLEX, DOUBLE PRECISION COMPLEX(COMPLEX*16) A*x = b, or A**T*x = b, where b and x are n element vectors and A is an n by n unit, or non-unit, upper or lower triangular band matrix, with ( k + 1 ) diagonals. \param[in] layout layout is enum CBLAS_ORDER layout specifies Matrix storage as follows: layout = CBLAS_ORDER::CblasRowMajor or Layout::CblasColMajor. \param[in] uplo uplo is enum CBLAS_UPLO. uplo specifies specifies whether the matrix A is an upper or lower triangular matrix as follows: \n uplo = CBLAS_UPLO::CblasUpper A is an upper triangular matrix. \n uplo = CBLAS_UPLO::CblasLower A is a lower triangular matrix. \param[in] trans trans is CBLAS_TRANSPOSE On entry, trans specifies the operation to be performed as follows: trans = CBLAS_TRANSPOSE::CblasNoTrans, A*x = b. \n trans = CBLAS_TRANSPOSE::CblasTrans, A**T*x = b. \n trans = CBLAS_TRANSPOSE::CblasConjTrans, A**T*x = b. \param[in] diag diag is enum CBLAS_DIAG diag specifies specifies whether or not A is unit triangular as follows: \n diag = CBLAS_DIAG::CblasUnit A is assumed to be unit triangular.\n diag = CBLAS_DIAG::CblasNonUnit A is not assumed to be unit triangular. \param[in] n n is INTEGER On entry, n specifies the order of the matrix A.n must be at least zero. \param[in] k k is INTEGER On entry with UPLO = CblasUpper, k specifies the number of super-diagonals of the matrix A. On entry with UPLO = CblasLower, k specifies the number of sub-diagonals of the matrix A. k must at least zero. \param[in] A A is REAL/DOUBLE PRECISION/COMPLEX/COMPLEX*16 array,dimension ( lda, n )\n Before entry with UPLO = CblasUpper, the leading ( k + 1 ) by n part of the array A must contain the upper triangular band part of the matrix of coefficients, supplied column by column, with the leading diagonal of the matrix in row ( k + 1 ) of the array, the first super-diagonal starting at position 2 in row k, and so on. The top left k by k triangle of the array A is not referenced. \n Before entry with UPLO = CblasLower, the leading ( k + 1 ) by n part of the array A must contain the lower triangular band part of the matrix of coefficients, supplied column by column, with the leading diagonal of the matrix in row 1 of the array, the first sub-diagonal starting at position 1 in row 2, and so on. The bottom right k by k triangle of the array A is not referenced. \n Note that when DIAG = CblasUnit, the elements of the array A corresponding to the diagonal elements of the matrix are not referenced, but are assumed to be unity. \param[in] lda lda is INTEGER On entry, lda specifies the Leading dimension of A lda must be at least max( 1, k+1 ). \param[in, out] x x is REAL/DOUBLE PRECISION/COMPLEX/COMPLEX*16 array,dimension : at least ( 1 + ( n - 1 )*abs( incx ) ). \n Before entry, the incremented array x must contain the element right-hand side vector b.On exit, x is overwritten with the solution vector x. \param[in] incx incx is INTEGER On entry, incx specifies the increment for the elements of x. incx must not be zero. */ template< typename T > void tbsv( CBLAS_ORDER layout, CBLAS_UPLO uplo, CBLAS_TRANSPOSE trans, CBLAS_DIAG diag, int64_t n, int64_t k, T const *A, int64_t lda, T *x, int64_t incx ) { cblas_tbsv(layout, uplo, trans, diag, n, k, A, lda, x, incx); } /*! \brief Solve the one of the triangular matrix-vector equation for arbitrary data types \b Purpose: TPSV solves one of the systems of equations for arbitrary data types Data precisions supported include SINGLE PRECISION REAL, DOUBLE PRECISION REAL, SINGLE PRECISION COMPLEX, DOUBLE PRECISION COMPLEX(COMPLEX*16) A*x = b, or A**T*x = b, where b and x are n element vectors and A is an n by n unit, or non-unit, upper or lower triangular band matrix, supplied in packed form. \param[in] layout layout is enum CBLAS_ORDER layout specifies Matrix storage as follows: layout = CBLAS_ORDER::CblasRowMajor or Layout::CblasColMajor. \param[in] uplo uplo is enum CBLAS_UPLO. uplo specifies specifies whether the matrix A is an upper or lower triangular matrix as follows: \n uplo = CBLAS_UPLO::CblasUpper A is an upper triangular matrix. \n uplo = CBLAS_UPLO::CblasLower A is a lower triangular matrix. \param[in] trans trans is CBLAS_TRANSPOSE On entry, trans specifies the operation to be performed as follows: trans = CBLAS_TRANSPOSE::CblasNoTrans, A*x = b. \n trans = CBLAS_TRANSPOSE::CblasTrans, A**T*x = b. \n trans = CBLAS_TRANSPOSE::CblasConjTrans, A**T*x = b. \param[in] diag diag is enum CBLAS_DIAG diag specifies specifies whether or not A is unit triangular as follows: \n diag = CBLAS_DIAG::CblasUnit A is assumed to be unit triangular.\n diag = CBLAS_DIAG::CblasNonUnit A is not assumed to be unit triangular. \param[in] n n is INTEGER On entry, n specifies the order of the matrix A.n must be at least zero. \param[in] Ap Ap is REAL/DOUBLE PRECISION/COMPLEX/COMPLEX*16 array,dimension ( ( n*( n + 1 ) )/2 ). \n Before entry with UPLO = CblasUpper, the array Ap must contain the upper triangular matrix packed sequentially, column by column, so that Ap( 1 ) contains a( 1, 1 ), Ap( 2 ) and Ap( 3 ) contain a( 1, 2 ) and a( 2, 2 ) respectively, and so on. \n Before entry with UPLO = CblasLower, the array Ap must contain the lower triangular matrix packed sequentially, column by column, so that Ap( 1 ) contains a( 1, 1 ), Ap( 2 ) and Ap( 3 ) contain a( 2, 1 ) and a( 3, 1 ) respectively, and so on. \n Note that when DIAG = CblasUnit, the diagonal elements of A are not referenced, but are assumed to be unity. \param[in, out] x x is REAL/DOUBLE PRECISION/COMPLEX/COMPLEX*16 array,dimension : at least ( 1 + ( n - 1 )*abs( incx ) ). \n Before entry, the incremented array x must contain the element right-hand side vector b.On exit, x is overwritten with the solution vector x. \param[in] incx incx is INTEGER On entry, incx specifies the increment for the elements of x. incx must not be zero. */ template< typename T > void tpsv( CBLAS_ORDER layout, CBLAS_UPLO uplo, CBLAS_TRANSPOSE trans, CBLAS_DIAG diag, int64_t n, T const *Ap, T *x, int64_t incx ) { cblas_tpsv(layout, uplo, trans, diag, n, Ap, x, incx); } /*! \brief Perform the General matrix rank-1 update for arbitrary data types \b Purpose: GER performs the rank 1 operation for arbitrary data types Data precisions supported include SINGLE PRECISION REAL, DOUBLE PRECISION REAL, A := alpha*x*y**T + A, where alpha is a scalar, x is an m element vector, y is an n element vector and A is an m by n matrix. \param[in] layout layout is enum CBLAS_ORDER layout specifies Matrix storage as follows: layout = CBLAS_ORDER::CblasRowMajor or Layout::CblasColMajor. \param[in] m m is INTEGER On entry, m specifies the number of rows of the matrix A. m must be at least zero. \param[in] n n is INTEGER On entry, n specifies the number of columns of the matrix A. n must be at least zero. \param[in] alpha alpha is REAL/DOUBLE PRECISION On entry, alpha specifies the scalar alpha. \param[in] x x is REAL/DOUBLE PRECISION array,dimension : at least ( 1 + ( m - 1 )*abs( incx ) ). \n Before entry, the incremented array x must contain the m element vector x. \param[in] incx incx is INTEGER On entry, incx specifies the increment for the elements of x. incx must not be zero. \param[in] y y is REAL/DOUBLE PRECISION array,dimension : at least ( 1 + ( n - 1 )*abs( incy ) ). \n Before entry, the incremented array y must contain the n element vector y. \param[in] incy incy is INTEGER On entry, incy specifies the increment for the elements of y. incy must not be zero. \param[in,out] A A is REAL/DOUBLE PRECISION array,dimension ( lda, n )\n Before entry, the leading m by n part of the array A must contain the matrix of coefficients. On exit, A is overwritten by the updated matrix. \param[in] lda lda is INTEGER On entry, lda specifies the Leading dimension of A lda must be at least max( 1, m ). */ template< typename T > void ger( CBLAS_ORDER layout, int64_t m, int64_t n, T alpha, T const *x, int64_t incx, T const *y, int64_t incy, T *A, int64_t lda ) { cblas_ger(layout, m, n, alpha, x, incx, y, incy, A, lda); } /*! \brief Perform the General matrix rank-1 update for arbitrary data types \b Purpose: GERU performs the rank 1 operation for arbitrary data types Data precisions supported include SINGLE/DOUBLE PRECISION COMPLEX(COMPLEX*16) A := alpha*x*y**T + A, where alpha is a scalar, x is an m element vector, y is an n element vector and A is an m by n matrix. \param[in] layout layout is enum CBLAS_ORDER layout specifies Matrix storage as follows: layout = CBLAS_ORDER::CblasRowMajor or Layout::CblasColMajor. \param[in] m m is INTEGER On entry, m specifies the number of rows of the matrix A. m must be at least zero. \param[in] n n is INTEGER On entry, n specifies the number of columns of the matrix A. n must be at least zero. \param[in] alpha alpha is SINGLE/DOUBLE PRECISION COMPLEX On entry, alpha specifies the scalar alpha. \param[in] x x is SINGLE/DOUBLE PRECISION COMPLEX array,dimension : at least ( 1 + ( m - 1 )*abs( incx ) ). \n Before entry, the incremented array x must contain the m element vector x. \param[in] incx incx is INTEGER On entry, incx specifies the increment for the elements of x. incx must not be zero. \param[in] y y is SINGLE/DOUBLE PRECISION COMPLEX array,dimension : at least ( 1 + ( n - 1 )*abs( incy ) ). \n Before entry, the incremented array y must contain the n element vector y. \param[in] incy incy is INTEGER On entry, incy specifies the increment for the elements of y. incy must not be zero. \param[in,out] A A is SINGLE/DOUBLE PRECISION COMPLEX array,dimension ( lda, n )\n Before entry, the leading m by n part of the array A must contain the matrix of coefficients. On exit, A is overwritten by the updated matrix. \param[in] lda lda is INTEGER On entry, lda specifies the Leading dimension of A lda must be at least max( 1, m ). */ template< typename T > void geru( CBLAS_ORDER layout, int64_t m, int64_t n, T alpha, T const *x, int64_t incx, T const *y, int64_t incy, T *A, int64_t lda ) { cblas_geru(layout, m, n, alpha, x, incx, y, incy, A, lda); } /*! \brief Perform the General matrix rank-1 update for arbitrary data types \b Purpose: GERC performs the rank 1 operation for arbitrary data types Data precisions supported include SINGLE/DOUBLE PRECISION COMPLEX(COMPLEX*16) A := alpha*x*y**T + A, where alpha is a scalar, x is an m element vector, y is an n element vector and A is an m by n matrix. \param[in] layout layout is enum CBLAS_ORDER layout specifies Matrix storage as follows: layout = CBLAS_ORDER::CblasRowMajor or Layout::CblasColMajor. \param[in] m m is INTEGER On entry, m specifies the number of rows of the matrix A. m must be at least zero. \param[in] n n is INTEGER On entry, n specifies the number of columns of the matrix A. n must be at least zero. \param[in] alpha alpha is SINGLE/DOUBLE PRECISION COMPLEX On entry, alpha specifies the scalar alpha. \param[in] x x is SINGLE/DOUBLE PRECISION COMPLEX array,dimension : at least ( 1 + ( m - 1 )*abs( incx ) ). \n Before entry, the incremented array x must contain the m element vector x. \param[in] incx incx is INTEGER On entry, incx specifies the increment for the elements of x. incx must not be zero. \param[in] y y is SINGLE/DOUBLE PRECISION COMPLEX array,dimension : at least ( 1 + ( n - 1 )*abs( incy ) ). \n Before entry, the incremented array y must contain the n element vector y. \param[in] incy incy is INTEGER On entry, incy specifies the increment for the elements of y. incy must not be zero. \param[in,out] A A is SINGLE/DOUBLE PRECISION COMPLEX array,dimension ( lda, n )\n Before entry, the leading m by n part of the array A must contain the matrix of coefficients. On exit, A is overwritten by the updated matrix. \param[in] lda lda is INTEGER On entry, lda specifies the Leading dimension of A lda must be at least max( 1, m ). */ template< typename T > void gerc( CBLAS_ORDER layout, int64_t m, int64_t n, T alpha, T const *x, int64_t incx, T const *y, int64_t incy, T *A, int64_t lda ) { cblas_gerc(layout, m, n, alpha, x, incx, y, incy, A, lda); } /*! \brief Perform the hermitian rank 1 operation for arbitrary data types \b Purpose: HER performs the hermitian rank 1 operation for arbitrary data types Data precisions supported include SINGLE/DOUBLE PRECISION COMPLEX(COMPLEX*16) A := alpha*x*x**H + A, where alpha is a real scalar, x is an n element vector, A is an n by n hermitian matrix. \param[in] layout layout is enum CBLAS_ORDER layout specifies Matrix storage as follows: layout = CBLAS_ORDER::CblasRowMajor or Layout::CblasColMajor. \param[in] uplo uplo is enum CBLAS_UPLO. uplo specifies specifies whether the upper or lower triangular part of the array A is to be referenced as follows: \n uplo = CBLAS_UPLO::CblasUpper A is an upper triangular matrix. \n uplo = CBLAS_UPLO::CblasLower A is a lower triangular matrix. \param[in] n n is INTEGER On entry, n specifies the order of the matrix A. n must be at least zero. \param[in] alpha alpha is SINGLE/DOUBLE PRECISION REAL On entry, alpha specifies the scalar alpha. \param[in] x x is SINGLE/DOUBLE PRECISION COMPLEX array,dimension : at least ( 1 + ( n - 1 )*abs( incx ) ). \n Before entry, the incremented array x must contain the n element vector x. \param[in] incx incx is INTEGER On entry, incx specifies the increment for the elements of x. incx must not be zero. \param[in,out] A A is SINGLE/DOUBLE PRECISION COMPLEX array,dimension ( lda, n )\n Before entry with UPLO = CblasUpper, the leading n by n upper triangular part of the array A must contain the upper triangular part of the hermitian matrix and the strictly lower triangular part of A is not referenced. On exit, the upper triangular part of the array A is overwritten by the upper triangular part of the updated matrix. \n Before entry with UPLO = CblasLower, the leading n by n lower triangular part of the array A must contain the lower triangular part of the hermitian matrix and the strictly upper triangular part of A is not referenced. On exit, the lower triangular part of the array A is overwritten by the lower triangular part of the updated matrix. \n Note that the imaginary parts of the diagonal elements need not be set, they are assumed to be zero, and on exit they are set to zero. \param[in] lda lda is INTEGER On entry, lda specifies the Leading dimension of A lda must be at least max( 1, n ). */ template< typename T > void her( CBLAS_ORDER layout, CBLAS_UPLO uplo, int64_t n, real_type alpha, // zher takes double alpha; use real T const *x, int64_t incx, T *A, int64_t lda ) { cblas_her(layout, uplo, n, alpha, x, incx, A, lda); } /*! \brief Perform the hermitian rank 1 operation for arbitrary data types \b Purpose: HPR performs the hermitian rank 1 operation for arbitrary data types Data precisions supported include SINGLE/DOUBLE PRECISION COMPLEX(COMPLEX*16) A := alpha*x*x**H + A, where alpha is a real scalar, x is an n element vector, A is an n by n hermitian matrix, supplied in packed form. \param[in] layout layout is enum CBLAS_ORDER layout specifies Matrix storage as follows: layout = CBLAS_ORDER::CblasRowMajor or Layout::CblasColMajor. \param[in] uplo uplo is enum CBLAS_UPLO. uplo specifies specifies whether the upper or lower triangular part of the array A is to be referenced as follows: \n uplo = CBLAS_UPLO::CblasUpper The upper triangular part of A is supplied in Ap. \n uplo = CBLAS_UPLO::CblasLower The lower triangular part of A is supplied in Ap. \param[in] n n is INTEGER On entry, n specifies the order of the matrix A. n must be at least zero. \param[in] alpha alpha is SINGLE/DOUBLE PRECISION REAL On entry, alpha specifies the scalar alpha. \param[in] x x is SINGLE/DOUBLE PRECISION COMPLEX array,dimension : at least ( 1 + ( n - 1 )*abs( incx ) ). \n Before entry, the incremented array x must contain the n element vector x. \param[in] incx incx is INTEGER On entry, incx specifies the increment for the elements of x. incx must not be zero. \param[in,out] Ap Ap is SINGLE/DOUBLE PRECISION COMPLEX array,dimension atleast ( ( n*( n + 1 ) )/2 ).\n Before entry with UPLO = CblasUpper, the array Ap must contain the upper triangular part of the hermitian matrix packed sequentially, column by column, so that Ap( 1 ) contains a( 1, 1 ), Ap( 2 ) and Ap( 3 ) contain a( 1, 2 ) and a( 2, 2 ) respectively, and so on. On exit, the array Ap is overwritten by the upper triangular part of the updated matrix. \n Before entry with UPLO = CblasLower, the array Ap must contain the lower triangular part of the hermitian matrix packed sequentially, column by column, so that Ap( 1 ) contains a( 1, 1 ), Ap( 2 ) and Ap( 3 ) contain a( 2, 1 ) and a( 3, 1 ) respectively, and so on. On exit, the array Ap is overwritten by the lower triangular part of the updated matrix. \n Note that the imaginary parts of the diagonal elements need not be set, they are assumed to be zero, and on exit they are set to zero. */ template< typename T > void hpr( CBLAS_ORDER layout, CBLAS_UPLO uplo, int64_t n, real_type alpha, // zher takes double alpha; use real T const *x, int64_t incx, T *Ap ) { cblas_hpr(layout, uplo, n, alpha, x, incx, Ap); } /*! \brief Perform the hermitian rank 2 operation for arbitrary data types \b Purpose: HER2 performs the hermitian rank 2 operation for arbitrary data types Data precisions supported include SINGLE/DOUBLE PRECISION COMPLEX(COMPLEX*16) A := alpha*x*y**H + conjg( alpha )*y*x**H + A, where alpha is a scalar, x and y are n element vector, A is an n by n hermitian matrix. \param[in] layout layout is enum CBLAS_ORDER layout specifies Matrix storage as follows: layout = CBLAS_ORDER::CblasRowMajor or Layout::CblasColMajor. \param[in] uplo uplo is enum CBLAS_UPLO. uplo specifies whether the upper or lower triangular part of the array A is to be referenced as follows: \n UPLO = CblasUpper Only the upper triangular part of A is to be referenced. \n UPLO = CblasLower Only the lower triangular part of A is to be referenced. \param[in] n n is INTEGER On entry, n specifies the order of the matrix A. n must be at least zero. \param[in] alpha alpha is SINGLE/DOUBLE PRECISION COMPLEX On entry, alpha specifies the scalar alpha. \param[in] x x is SINGLE/DOUBLE PRECISION COMPLEX array,dimension : at least ( 1 + ( n - 1 )*abs( incx ) ). \n Before entry, the incremented array x must contain the n element vector x. \param[in] incx incx is INTEGER On entry, incx specifies the increment for the elements of x. incx must not be zero. \param[in] y y is SINGLE/DOUBLE PRECISION COMPLEX array,dimension : at least ( 1 + ( n - 1 )*abs( incy ) ). \n Before entry, the incremented array y must contain the n element vector y. \param[in] incy incy is INTEGER On entry, incy specifies the increment for the elements of y. incy must not be zero. \param[in,out] A A is SINGLE/DOUBLE PRECISION COMPLEX array,dimension ( lda, n )\n Before entry with UPLO = CblasUpper, the leading n by n upper triangular part of the array A must contain the upper triangular part of the hermitian matrix and the strictly lower triangular part of A is not referenced. On exit, the upper triangular part of the array A is overwritten by the upper triangular part of the updated matrix. \n Before entry with UPLO = CblasLower, the leading n by n lower triangular part of the array A must contain the lower triangular part of the hermitian matrix and the strictly upper triangular part of A is not referenced. On exit, the lower triangular part of the array A is overwritten by the lower triangular part of the updated matrix. \n Note that the imaginary parts of the diagonal elements need not be set, they are assumed to be zero, and on exit they are set to zero. \param[in] lda lda is INTEGER On entry, lda specifies the Leading dimension of A lda must be at least max( 1, n ). */ template< typename T > void her2( CBLAS_ORDER layout, CBLAS_UPLO uplo, int64_t n, T alpha, T const *x, int64_t incx, T const *y, int64_t incy, T *A, int64_t lda ) { cblas_her2(layout, uplo, n, alpha, x, incx, y, incy, A, lda); } /*! \brief Perform the hermitian rank 2 operation for arbitrary data types \b Purpose: HPR2 performs the hermitian rank 2 operation for arbitrary data types Data precisions supported include SINGLE/DOUBLE PRECISION COMPLEX(COMPLEX*16) A := alpha*x*y**H + conjg( alpha )*y*x**H + A, where alpha is a scalar, x and y are n element vector, A is an n by n hermitian matrix, supplied in packed form. \param[in] layout layout is enum CBLAS_ORDER layout specifies Matrix storage as follows: layout = CBLAS_ORDER::CblasRowMajor or Layout::CblasColMajor. \param[in] uplo uplo is enum CBLAS_UPLO. uplo specifies specifies whether the upper or lower triangular part of the array A is to be referenced as follows: \n uplo = CBLAS_UPLO::CblasUpper The upper triangular part of A is supplied in Ap. \n uplo = CBLAS_UPLO::CblasLower The lower triangular part of A is supplied in Ap. \param[in] n n is INTEGER On entry, n specifies the order of the matrix A. n must be at least zero. \param[in] alpha alpha is SINGLE/DOUBLE PRECISION COMPLEX On entry, alpha specifies the scalar alpha. \param[in] x x is SINGLE/DOUBLE PRECISION COMPLEX array,dimension : at least ( 1 + ( n - 1 )*abs( incx ) ). \n Before entry, the incremented array x must contain the n element vector x. \param[in] incx incx is INTEGER On entry, incx specifies the increment for the elements of x. incx must not be zero. \param[in] y y is SINGLE/DOUBLE PRECISION REAL array,dimension : at least ( 1 + ( n - 1 )*abs( incy ) ). \n Before entry, the incremented array y must contain the n element vector y. \param[in] incy incy is INTEGER On entry, incy specifies the increment for the elements of y. incy must not be zero. \param[in,out] Ap Ap is SINGLE/DOUBLE PRECISION COMPLEX array,dimension atleast ( ( n*( n + 1 ) )/2 ).\n Before entry with UPLO = CblasUpper, the array Ap must contain the upper triangular part of the hermitian matrix packed sequentially, column by column, so that Ap( 1 ) contains a( 1, 1 ), Ap( 2 ) and Ap( 3 ) contain a( 1, 2 ) and a( 2, 2 ) respectively, and so on. On exit, the array Ap is overwritten by the upper triangular part of the updated matrix. \n Before entry with UPLO = CblasLower, the array Ap must contain the lower triangular part of the hermitian matrix packed sequentially, column by column, so that Ap( 1 ) contains a( 1, 1 ), Ap( 2 ) and Ap( 3 ) contain a( 2, 1 ) and a( 3, 1 ) respectively, and so on. On exit, the array Ap is overwritten by the lower triangular part of the updated matrix. \n Note that the imaginary parts of the diagonal elements need not be set, they are assumed to be zero, and on exit they are set to zero. */ template< typename T > void hpr2( CBLAS_ORDER layout, CBLAS_UPLO uplo, int64_t n, T alpha, T const *x, int64_t incx, T const *y, int64_t incy, T *Ap ) { cblas_hpr2(layout, uplo, n, alpha, x, incx, y, incy, Ap); } /*! \brief Perform the symmetric rank 1 operation for arbitrary data types \b Purpose: SYR performs the symmetric rank 1 operation for arbitrary data types Data precisions supported include SINGLE/DOUBLE PRECISION REAL A := alpha*x*x**T + A, where alpha is a real scalar, x is an n element vector, A is an n by n symmetric matrix. \param[in] layout layout is enum CBLAS_ORDER layout specifies Matrix storage as follows: layout = CBLAS_ORDER::CblasRowMajor or Layout::CblasColMajor. \param[in] uplo uplo is enum CBLAS_UPLO. uplo specifies specifies whether the upper or lower triangular part of the array A is to be referenced as follows: \n uplo = CBLAS_UPLO::CblasUpper A is an upper triangular matrix. \n uplo = CBLAS_UPLO::CblasLower A is a lower triangular matrix. \param[in] n n is INTEGER On entry, n specifies the order of the matrix A. n must be at least zero. \param[in] alpha alpha is SINGLE/DOUBLE PRECISION REAL On entry, alpha specifies the scalar alpha. \param[in] x x is SINGLE/DOUBLE PRECISION REAL array,dimension : at least ( 1 + ( n - 1 )*abs( incx ) ). \n Before entry, the incremented array x must contain the n element vector x. \param[in] incx incx is INTEGER On entry, incx specifies the increment for the elements of x. incx must not be zero. \param[in,out] A A is SINGLE/DOUBLE PRECISION REAL array,dimension ( lda, n )\n Before entry with UPLO = CblasUpper, the leading n by n upper triangular part of the array A must contain the upper triangular part of the symmetric matrix and the strictly lower triangular part of A is not referenced. On exit, the upper triangular part of the array A is overwritten by the upper triangular part of the updated matrix. \n Before entry with UPLO = CblasLower, the leading n by n lower triangular part of the array A must contain the lower triangular part of the symmetric matrix and the strictly upper triangular part of A is not referenced. On exit, the lower triangular part of the array A is overwritten by the lower triangular part of the updated matrix. \n \param[in] lda lda is INTEGER On entry, lda specifies the Leading dimension of A lda must be at least max( 1, n ). */ template< typename T > void syr( CBLAS_ORDER layout, CBLAS_UPLO uplo, int64_t n, T alpha, T const *x, int64_t incx, T *A, int64_t lda ) { cblas_syr(layout, uplo, n, alpha, x, incx, A, lda); } /*! \brief Perform the symmetric rank 1 operation for arbitrary data types \b Purpose: SPR performs the symmetric rank 1 operation for arbitrary data types Data precisions supported include SINGLE PRECISION REAL, DOUBLE PRECISION REAL A := alpha*x*x**T + A, where alpha is a real scalar, x is an n element vector, A is an n by n symmetric matrix, supplied in packed form. \param[in] layout layout is enum CBLAS_ORDER layout specifies Matrix storage as follows: layout = CBLAS_ORDER::CblasRowMajor or Layout::CblasColMajor. \param[in] uplo uplo is enum CBLAS_UPLO. uplo specifies specifies whether the upper or lower triangular part of the array A is to be referenced as follows: \n uplo = CBLAS_UPLO::CblasUpper The upper triangular part of A is supplied in Ap. \n uplo = CBLAS_UPLO::CblasLower The lower triangular part of A is supplied in Ap. \param[in] n n is INTEGER On entry, n specifies the order of the matrix A. n must be at least zero. \param[in] alpha alpha is SINGLE/DOUBLE PRECISION REAL On entry, alpha specifies the scalar alpha. \param[in] x x is SINGLE/DOUBLE PRECISION REAL array,dimension : at least ( 1 + ( n - 1 )*abs( incx ) ). \n Before entry, the incremented array x must contain the n element vector x. \param[in] incx incx is INTEGER On entry, incx specifies the increment for the elements of x. incx must not be zero. \param[in,out] Ap Ap is SINGLE/DOUBLE PRECISION REAL array,dimension atleast ( ( n*( n + 1 ) )/2 ).\n Before entry with UPLO = CblasUpper, the array Ap must contain the upper triangular part of the symmetric matrix packed sequentially, column by column, so that Ap( 1 ) contains a( 1, 1 ), Ap( 2 ) and Ap( 3 ) contain a( 1, 2 ) and a( 2, 2 ) respectively, and so on. On exit, the array Ap is overwritten by the upper triangular part of the updated matrix. \n Before entry with UPLO = CblasLower, the array Ap must contain the lower triangular part of the symmetric matrix packed sequentially, column by column, so that Ap( 1 ) contains a( 1, 1 ), Ap( 2 ) and Ap( 3 ) contain a( 2, 1 ) and a( 3, 1 ) respectively, and so on. On exit, the array Ap is overwritten by the lower triangular part of the updated matrix. \n */ template< typename T > void spr( CBLAS_ORDER layout, CBLAS_UPLO uplo, int64_t n, T alpha, T const *x, int64_t incx, T *Ap ) { cblas_spr(layout, uplo, n, alpha, x, incx, Ap); } /*! \brief Perform the symmetric rank 2 operation for arbitrary data types \b Purpose: SYR2 performs the symmetric rank 2 operation for arbitrary data types Data precisions supported include SINGLE/DOUBLE PRECISION REAL A := alpha*x*y**T + alpha*y*x**T + A, where alpha is a scalar, x and y are n element vector, A is an n by n symmetric matrix. \param[in] layout layout is enum CBLAS_ORDER layout specifies Matrix storage as follows: layout = CBLAS_ORDER::CblasRowMajor or Layout::CblasColMajor. \param[in] uplo uplo is enum CBLAS_UPLO. uplo specifies whether the upper or lower triangular part of the array A is to be referenced as follows: \n UPLO = CblasUpper Only the upper triangular part of A is to be referenced. \n UPLO = CblasLower Only the lower triangular part of A is to be referenced. \param[in] n n is INTEGER On entry, n specifies the order of the matrix A. n must be at least zero. \param[in] alpha alpha is SINGLE/DOUBLE PRECISION REAL On entry, alpha specifies the scalar alpha. \param[in] x x is SINGLE/DOUBLE PRECISION REAL array,dimension : at least ( 1 + ( n - 1 )*abs( incx ) ). \n Before entry, the incremented array x must contain the n element vector x. \param[in] incx incx is INTEGER On entry, incx specifies the increment for the elements of x. incx must not be zero. \param[in] y y is SINGLE/DOUBLE PRECISION REAL array,dimension : at least ( 1 + ( n - 1 )*abs( incy ) ). \n Before entry, the incremented array y must contain the n element vector y. \param[in] incy incy is INTEGER On entry, incy specifies the increment for the elements of y. incy must not be zero. \param[in,out] A A is SINGLE/DOUBLE PRECISION REAL array,dimension ( lda, n )\n Before entry with UPLO = CblasUpper, the leading n by n upper triangular part of the array A must contain the upper triangular part of the symmetric matrix and the strictly lower triangular part of A is not referenced. On exit, the upper triangular part of the array A is overwritten by the upper triangular part of the updated matrix. \n Before entry with UPLO = CblasLower, the leading n by n lower triangular part of the array A must contain the lower triangular part of the symmetric matrix and the strictly upper triangular part of A is not referenced. On exit, the lower triangular part of the array A is overwritten by the lower triangular part of the updated matrix. \n \param[in] lda lda is INTEGER On entry, lda specifies the Leading dimension of A lda must be at least max( 1, n ). */ template< typename T > void syr2( CBLAS_ORDER layout, CBLAS_UPLO uplo, int64_t n, T alpha, T const *x, int64_t incx, T const *y, int64_t incy, T *A, int64_t lda ) { cblas_syr2(layout, uplo, n, alpha, x, incx, y, incy, A, lda); } /*! \brief Perform the symmetric rank 2 operation for arbitrary data types \b Purpose: SPR2 performs the symmetric rank 2 operation for arbitrary data types Data precisions supported include SINGLE/DOUBLE PRECISION REAL A := alpha*x*y**T + alpha*y*x**T + A, where alpha is a scalar, x and y are n element vector, A is an n by n symmetric matrix, supplied in packed form. \param[in] layout layout is enum CBLAS_ORDER layout specifies Matrix storage as follows: layout = CBLAS_ORDER::CblasRowMajor or Layout::CblasColMajor. \param[in] uplo uplo is enum CBLAS_UPLO. uplo specifies specifies whether the upper or lower triangular part of the array A is to be referenced as follows: \n uplo = CBLAS_UPLO::CblasUpper The upper triangular part of A is supplied in Ap. \n uplo = CBLAS_UPLO::CblasLower The lower triangular part of A is supplied in Ap. \param[in] n n is INTEGER On entry, n specifies the order of the matrix A. n must be at least zero. \param[in] alpha alpha is SINGLE/DOUBLE PRECISION REAL On entry, alpha specifies the scalar alpha. \param[in] x x is SINGLE/DOUBLE PRECISION REAL array,dimension : at least ( 1 + ( n - 1 )*abs( incx ) ). \n Before entry, the incremented array x must contain the n element vector x. \param[in] incx incx is INTEGER On entry, incx specifies the increment for the elements of x. incx must not be zero. \param[in] y y is SINGLE/DOUBLE PRECISION REAL array,dimension : at least ( 1 + ( n - 1 )*abs( incy ) ). \n Before entry, the incremented array y must contain the n element vector y. \param[in] incy incy is INTEGER On entry, incy specifies the increment for the elements of y. incy must not be zero. \param[in,out] Ap Ap is SINGLE/DOUBLE PRECISION REAL array,dimension atleast ( ( n*( n + 1 ) )/2 ).\n Before entry with UPLO = CblasUpper, the array Ap must contain the upper triangular part of the symmetric matrix packed sequentially, column by column, so that Ap( 1 ) contains a( 1, 1 ), Ap( 2 ) and Ap( 3 ) contain a( 1, 2 ) and a( 2, 2 ) respectively, and so on. On exit, the array Ap is overwritten by the upper triangular part of the updated matrix. \n Before entry with UPLO = CblasLower, the array Ap must contain the lower triangular part of the symmetric matrix packed sequentially, column by column, so that Ap( 1 ) contains a( 1, 1 ), Ap( 2 ) and Ap( 3 ) contain a( 2, 1 ) and a( 3, 1 ) respectively, and so on. On exit, the array Ap is overwritten by the lower triangular part of the updated matrix. \n */ template< typename T > void spr2( CBLAS_ORDER layout, CBLAS_UPLO uplo, int64_t n, T alpha, T const *x, int64_t incx, T const *y, int64_t incy, T *Ap ) { cblas_spr2(layout, uplo, n, alpha, x, incx, y, incy, Ap); } /*! \brief General matrix-matrix multiply for arbitrary data types \b Purpose: GEMM performs general matrix-matrix multiply for arbitrary data types Data precisions supported include SINGLE PRECISION REAL, DOUBLE PRECISION REAL, SINGLE PRECISION COMPLEX, DOUBLE PRECISION COMPLEX(COMPLEX*16) C := alpha*op( A )*op( B ) + beta*C, where op( X ) is one of op( X ) = X or op( X ) = X**T or op( X ) = X**H, alpha and beta are scalars, and A, B and C are matrices, with op( A ) an m by k matrix, op( B ) a k by n matrix and C an m by n matrix. \param[in] layout layout is enum CBLAS_ORDER layout specifies Matrix storage as follows: layout = CBLAS_ORDER::CblasRowMajor or Layout::CblasColMajor. \param[in] transA transA is CBLAS_TRANSPOSE On entry, transA specifies the form of op( A ) to be used in the matrix multiplication as follows: transA = CBLAS_TRANSPOSE::CblasNoTrans, op( A ) = A. transA = CBLAS_TRANSPOSE::CblasTrans, op( A ) = A**T. transA = CBLAS_TRANSPOSE::CblasConjTrans, op( A ) = A**H. \param[in] transB transB is CBLAS_TRANSPOSE On entry, transB specifies the form of op( B ) to be used in the matrix multiplication as follows: transB = CBLAS_TRANSPOSE::CblasNoTrans, op( B ) = B. transB = CBLAS_TRANSPOSE::CblasTrans, op( B ) = B**T. transB = CBLAS_TRANSPOSE::CblasConjTrans, op( B ) = B**H. \param[in] m m is INTEGER On entry, m specifies the number of rows of the matrix op( A ) and of the matrix C. m must be at least zero. \param[in] n n is INTEGER On entry, n specifies the number of columns of the matrix op( B ) and the number of columns of the matrix C. n must be at least zero. \param[in] k k is INTEGER On entry, k specifies the number of columns of the matrix op( A ) and the number of rows of the matrix op( B ). k must be at least zero. \param[in] alpha alpha is REAL/DOUBLE PRECISION/COMPLEX/COMPLEX*16 On entry, alpha specifies the scalar alpha. \param[in] A A is REAL/DOUBLE PRECISION/COMPLEX/COMPLEX*16 array,dimension : If transA = CblasNoTrans: m-by-k , stored in an lda-by-k array [RowMajor: m-by-lda]. Otherwise: k-by-m , stored in an lda-by-m array [RowMajor: k-by-lda]. \param[in] lda lda is INTEGER On entry, lda specifies the Leading dimension of A If transA = CblasNoTrans: lda >= max(1, m) [RowMajor: lda >= max(1, k)]. Otherwise: lda >= max(1, k) [RowMajor: lda >= max(1, m)]. \param[in] B B is REAL/DOUBLE PRECISION/COMPLEX/COMPLEX*16 array,dimension : If transA = CblasNoTrans: k-by-n , stored in an ldb-by-n array [RowMajor: k-by-ldb]. Otherwise: n-by-k , stored in an ldb-by-k array [RowMajor: n-by-ldb]. \param[in] ldb ldb is INTEGER On entry, ldb specifies the Leading dimension of B If transA = CblasNoTrans: ldb >= max(1, k) [RowMajor: ldb >= max(1, n)]. Otherwise: ldb >= max(1, n) [RowMajor: ldb >= max(1, k)]. \param[in] beta beta is REAL/DOUBLE PRECISION/COMPLEX/COMPLEX*16 On entry, beta specifies the scalar alpha.When beta is supplied as zero then C need not be set on input. \param[in,out] C C is REAL/DOUBLE PRECISION/COMPLEX/COMPLEX*16 array, dimension : m-by-n stored in an ldc-by-n array [RowMajor: m-by-ldc]. Before entry, the leading m by n part of the array C must contain the matrix C, except when beta is zero, in which case C need not be set on entry. On exit, the array C is overwritten by the m by n matrix ( alpha*op( A )*op( B ) + beta*C ). \param[in] ldc ldc is INTEGER On entry, ldc specifies the first dimension of C ldc >= max(1, m) [RowMajor: ldc >= max(1, n)]. */ template< typename T > void gemm( CBLAS_ORDER layout, CBLAS_TRANSPOSE transA, CBLAS_TRANSPOSE transB, int64_t m, int64_t n, int64_t k, T alpha, T const *A, int64_t lda, T const *B, int64_t ldb, T beta, T *C, int64_t ldc ) { cblas_gemm(layout, transA, transB, m, n, k, alpha, A,lda, B, ldb, beta, C, ldc); } /*! \brief Solve the triangular matrix-matrix equation for arbitrary data types \b Purpose: TRSM performs one of the matrix equations for arbitrary data types Data precisions supported include SINGLE PRECISION REAL, DOUBLE PRECISION REAL, SINGLE PRECISION COMPLEX, DOUBLE PRECISION COMPLEX(COMPLEX*16) op( A )*X = alpha*B, or X*op( A ) = alpha*B, where alpha is a scalar, X and B are m by n matrices, A is a unit, or non-unit, upper or lower triangular matrix and op( A ) is one of where op( X ) is one of op( A ) = A or op( A ) = A**T or op( A ) = A**H. The matrix X is overwritten on B. \param[in] layout layout is enum CBLAS_ORDER layout specifies Matrix storage as follows: layout = CBLAS_ORDER::CblasRowMajor or Layout::CblasColMajor. \param[in] side side is enum CBLAS_SIDE side specifies specifies whether op( A ) appears on the left or right of X as follows: side = CBLAS_SIDE::CblasLeft op( A )*X = alpha*B. side = CBLAS_SIDE::CblasRight op( A )*X = alpha*B. \param[in] uplo uplo is enum CBLAS_UPLO uplo specifies specifies whether the matrix A is an upper or lower triangular matrix as follows: uplo = CBLAS_UPLO::CblasUpper A is an upper triangular matrix. uplo = CBLAS_UPLO::CblasLower A is a lower triangular matrix. \param[in] trans trans is CBLAS_TRANSPOSE On entry, trans specifies the form of op( A ) to be used in the matrix multiplication as follows: trans = CBLAS_TRANSPOSE::CblasNoTrans, op( A ) = A. trans = CBLAS_TRANSPOSE::CblasTrans, op( A ) = A**T. trans = CBLAS_TRANSPOSE::CblasConjTrans, op( A ) = A**H. \param[in] diag diag is enum CBLAS_DIAG diag specifies specifies whether or not A is unit triangular as follows: diag = CBLAS_DIAG::CblasUnit A is assumed to be unit triangular. diag = CBLAS_DIAG::CblasNonUnit A is not assumed to be unit triangular. \param[in] m m is INTEGER On entry, m specifies the number of rows of the matrix B. m must be at least zero. \param[in] n n is INTEGER On entry, n specifies the number of columns of the matrix B. n must be at least zero. \param[in] alpha alpha is REAL/DOUBLE PRECISION/COMPLEX/COMPLEX*16 On entry, alpha specifies the scalar alpha. \param[in] A A is REAL/DOUBLE PRECISION/COMPLEX/COMPLEX*16 array,dimension : If side = CblasLeft: the m-by-m matrix A, stored in an lda-by-m array [RowMajor: m-by-lda]. If side = CblasRight: the n-by-n matrix A, stored in an lda-by-n array [RowMajor: n-by-lda]. \param[in] lda lda is INTEGER On entry, lda specifies the Leading dimension of A If side = CblasLeft: lda >= max(1, m) . If side = CblasRight:lda >= max(1, k) . \param[in,out] B B is REAL/DOUBLE PRECISION/COMPLEX/COMPLEX*16 array,dimension : m-by-n , stored in an ldb-by-n array [RowMajor: m-by-ldb]. on exit is overwritten by the solution matrix X. \param[in] ldb ldb is INTEGER On entry, ldb specifies the Leading dimension of B ldb >= max(1, m) [RowMajor: ldb >= max(1, n)]. */ template< typename T > void trsm( CBLAS_ORDER layout, CBLAS_SIDE side, CBLAS_UPLO uplo, CBLAS_TRANSPOSE trans, CBLAS_DIAG diag, int64_t m, int64_t n, T alpha, T const *A, int64_t lda, T *B, int64_t ldb ) { cblas_trsm( layout, side, uplo, trans, diag, m, n, alpha, A, lda, B, ldb); } /*! \brief Solve the Triangular matrix-matrix multiply for arbitrary data types \b Purpose: TRMM performs solves one of the matrix equations for arbitrary data types Data precisions supported include SINGLE PRECISION REAL, DOUBLE PRECISION REAL, SINGLE PRECISION COMPLEX, DOUBLE PRECISION COMPLEX(COMPLEX*16) B := alpha*op( A )*B, or B := alpha*B*op( A ), where alpha is a scalar, B is an m by n matrices, A is a unit, or non-unit, upper or lower triangular matrix and op( A ) is one of op( A ) = A or op( A ) = A**T. \param[in] layout layout is enum CBLAS_ORDER layout specifies Matrix storage as follows: layout = CBLAS_ORDER::CblasRowMajor or Layout::CblasColMajor. \param[in] side side is enum CBLAS_SIDE side specifies whether op( A ) multiplies B from left or right of X as follows: side = CBLAS_SIDE::CblasLeft B := alpha*op( A )*B. side = CBLAS_SIDE::CblasRight B := alpha*B*op( A ). \param[in] uplo uplo is enum CBLAS_UPLO uplo specifies whether the matrix A is an upper or lower triangular matrix as follows: uplo = CBLAS_UPLO::CblasUpper A is an upper triangular matrix. uplo = CBLAS_UPLO::CblasLower A is a lower triangular matrix. \param[in] trans trans is CBLAS_TRANSPOSE On entry, trans specifies the form of op( A ) to be used in the matrix multiplication as follows: trans = CBLAS_TRANSPOSE::CblasNoTrans, op( A ) = A. trans = CBLAS_TRANSPOSE::CblasTrans, op( A ) = A**T. trans = CBLAS_TRANSPOSE::CblasConjTrans, op( A ) = A**T. \param[in] diag diag is enum CBLAS_DIAG diag specifies specifies whether or not A is unit triangular as follows: diag = CBLAS_DIAG::CblasUnit A is assumed to be unit triangular. diag = CBLAS_DIAG::CblasNonUnit A is not assumed to be unit triangular. \param[in] m m is INTEGER On entry, m specifies the number of rows of the matrix B. m must be at least zero. \param[in] n n is INTEGER On entry, n specifies the number of columns of the matrix B. n must be at least zero. \param[in] alpha alpha is REAL/DOUBLE PRECISION/COMPLEX/COMPLEX*16 On entry, alpha specifies the scalar alpha.When alpha is zero then A is not referenced and B need not be set before entry. \param[in] A A is REAL/DOUBLE PRECISION/COMPLEX/COMPLEX*16 array,dimension : If side = CblasLeft: the m-by-m matrix A, stored in an lda-by-m array [RowMajor: m-by-lda]. If side = CblasRight: the n-by-n matrix A, stored in an lda-by-n array [RowMajor: n-by-lda]. \param[in] lda lda is INTEGER On entry, lda specifies the Leading dimension of A If side = CblasLeft: lda >= max(1, m) . If side = CblasRight:lda >= max(1, n) . \param[in,out] B B is REAL/DOUBLE PRECISION/COMPLEX/COMPLEX*16 array,dimension : m-by-n , stored in an ldb-by-n array [RowMajor: m-by-ldb]. \param[in] ldb ldb is INTEGER On entry, ldb specifies the Leading dimension of B ldb >= max(1, m) [RowMajor: ldb >= max(1, n)]. */ template< typename T > void trmm( CBLAS_ORDER layout, CBLAS_SIDE side, CBLAS_UPLO uplo, CBLAS_TRANSPOSE trans, CBLAS_DIAG diag, int64_t m, int64_t n, T alpha, T const *A, int64_t lda, T *B, int64_t ldb ) { cblas_trmm( layout, side, uplo, trans, diag, m, n, alpha, A, lda, B, ldb); } /*! \brief Solve the Hermitian matrix-matrix multiply for arbitrary data types \b Purpose: HEMM performs solves one of the matrix-matrix operations for arbitrary data types Data precisions supported include SINGLE PRECISION COMPLEX, DOUBLE PRECISION COMPLEX(COMPLEX*16) C := alpha*A*B + beta*C or C := alpha*B*A + beta*C, where alpha is a scalar, A is an hermitian matrix C and B are m by n matrices \param[in] layout layout is enum CBLAS_ORDER layout specifies Matrix storage as follows: layout = CBLAS_ORDER::CblasRowMajor or Layout::CblasColMajor. \param[in] side side is enum CBLAS_SIDE side specifies specifies whether the hermitian matrix A appears on the left or right in the operation as follows: side = CBLAS_SIDE::CblasLeft C := alpha*A*B + beta*C, side = CBLAS_SIDE::CblasRight C := alpha*B*A + beta*C \param[in] uplo uplo is enum CBLAS_UPLO uplo specifies specifies whether the upper or lower triangular part of the hermitian matrix A is to be referenced as follows: uplo = CBLAS_UPLO::CblasUpper Only the upper triangular part of the hermitian matrix is to be referenced. uplo = CBLAS_UPLO::CblasLower Only the lower triangular part of the hermitian matrix is to be referenced. \param[in] m m is INTEGER On entry, m specifies the number of rows of the matrix C. m must be at least zero. \param[in] n n is INTEGER On entry, n specifies the number of columns of the matrix C. n must be at least zero. \param[in] alpha alpha is COMPLEX/COMPLEX*16 On entry, alpha specifies the scalar alpha. \param[in] A A is COMPLEX/COMPLEX*16 array,dimension : If side = CblasLeft: the m-by-m matrix A, stored in an lda-by-m array [RowMajor: m-by-lda]. If side = CblasRight: the n-by-n matrix A, stored in an lda-by-n array [RowMajor: n-by-lda]. \param[in] lda lda is INTEGER On entry, lda specifies the Leading dimension of A If side = CblasLeft: lda >= max(1, m) . If side = CblasRight:lda >= max(1, k) . \param[in] B B is COMPLEX/COMPLEX*16 array,dimension : m-by-n , stored in an ldb-by-n array [RowMajor: m-by-ldb]. \param[in] ldb ldb is INTEGER On entry, ldb specifies the Leading dimension of B ldb >= max(1, m) [RowMajor: ldb >= max(1, n)]. \param[in] beta beta is COMPLEX/COMPLEX*16 On entry, beta specifies the scalar beta. If beta is zero, C need not be set on input \param[in,out] C C is COMPLEX/COMPLEX*16 array,dimension : m-by-n , stored in an ldc-by-n array [RowMajor: m-by-ldc]. \param[in] ldc ldc is INTEGER On entry, ldc specifies the Leading dimension of C ldc >= max(1, m) [RowMajor: ldc >= max(1, n)]. */ template< typename T > void hemm( CBLAS_ORDER layout, CBLAS_SIDE side, CBLAS_UPLO uplo, int64_t m, int64_t n, T alpha, T const *A, int64_t lda, T const *B, int64_t ldb, T beta, T *C, int64_t ldc ) { cblas_hemm( layout, side, uplo, m, n, alpha, A, lda, B, ldb, beta, C, ldc); } /*! \brief Solve the Symmetric matrix-matrix multiply for arbitrary data types \b Purpose: SYMM performs solves one of the matrix-matrix operations for arbitrary data types Data precisions supported include SINGLE PRECISION REAL, DOUBLE PRECISION REAL, SINGLE PRECISION COMPLEX, DOUBLE PRECISION COMPLEX(COMPLEX*16) C := alpha*A*B + beta*C or C := alpha*B*A + beta*C, where alpha is a scalar, A is an symmetric matrix C and B are m by n matrices \param[in] layout layout is enum CBLAS_ORDER layout specifies Matrix storage as follows: layout = CBLAS_ORDER::CblasRowMajor or Layout::CblasColMajor. \param[in] side side is enum CBLAS_SIDE side specifies specifies whether the symmetric matrix A appears on the left or right in the operation as follows: side = CBLAS_SIDE::CblasLeft C := alpha*A*B + beta*C, side = CBLAS_SIDE::CblasRight C := alpha*B*A + beta*C \param[in] uplo uplo is enum CBLAS_UPLO uplo specifies specifies whether the upper or lower triangular part of the symmetric matrix A is to be referenced as follows: uplo = CBLAS_UPLO::CblasUpper Only the upper triangular part of the symmetric matrix is to be referenced. uplo = CBLAS_UPLO::CblasLower Only the lower triangular part of the symmetric matrix is to be referenced. \param[in] m m is INTEGER On entry, m specifies the number of rows of the matrix C. m must be at least zero. \param[in] n n is INTEGER On entry, n specifies the number of columns of the matrix C. n must be at least zero. \param[in] alpha alpha is REAL/DOUBLE PRECISION/COMPLEX/COMPLEX*16 On entry, alpha specifies the scalar alpha. \param[in] A A is REAL/DOUBLE PRECISION/COMPLEX/COMPLEX*16 array,dimension : If side = CblasLeft: the m-by-m matrix A, stored in an lda-by-m array [RowMajor: m-by-lda]. If side = CblasRight: the n-by-n matrix A, stored in an lda-by-n array [RowMajor: n-by-lda]. \param[in] lda lda is INTEGER On entry, lda specifies the Leading dimension of A If side = CblasLeft: lda >= max(1, m) . If side = CblasRight:lda >= max(1, k) . \param[in] B B is REAL/DOUBLE PRECISION/COMPLEX/COMPLEX*16 array,dimension : m-by-n , stored in an ldb-by-n array [RowMajor: m-by-ldb]. \param[in] ldb ldb is INTEGER On entry, ldb specifies the Leading dimension of B ldb >= max(1, m) [RowMajor: ldb >= max(1, n)]. \param[in] beta beta is REAL/DOUBLE PRECISION/COMPLEX/COMPLEX*16 On entry, beta specifies the scalar beta. If beta is zero, C need not be set on input \param[in, out] C C is REAL/DOUBLE PRECISION/COMPLEX/COMPLEX*16 array,dimension : m-by-n , stored in an ldc-by-n array [RowMajor: m-by-ldc]. \param[in] ldc ldc is INTEGER On entry, ldc specifies the Leading dimension of C ldc >= max(1, m) [RowMajor: ldc >= max(1, n)]. */ template< typename T > void symm( CBLAS_ORDER layout, CBLAS_SIDE side, CBLAS_UPLO uplo, int64_t m, int64_t n, T alpha, T const *A, int64_t lda, T const *B, int64_t ldb, T beta, T *C, int64_t ldc ) { cblas_symm( layout, side, uplo, m, n, alpha, A, lda, B, ldb, beta, C, ldc); } /*! \brief Solve the Symmetric rank-k operations for arbitrary data types \b Purpose: SYRK performs one of the symmetric rank k operations for arbitrary data types Data precisions supported include SINGLE PRECISION REAL, DOUBLE PRECISION REAL, SINGLE PRECISION COMPLEX, DOUBLE PRECISION COMPLEX(COMPLEX*16) C := alpha*A*A**T + beta*C, or C := alpha*A**T*A + beta*C, where alpha and beta are scalars, C is an n by n symmetric matrix and A is an n by k matrix in the first case and a k by n matrix in the second case. \param[in] layout layout is enum CBLAS_LAYOUT layout specifies Matrix storage as follows: layout = CBLAS_LAYOUT::CblasRowMajor or Layout::CblasColMajor. \param[in] uplo uplo is enum CBLAS_UPLO uplo specifies specifies whether the upper or lower triangular part of the array C is to be referenced as follows: uplo = CBLAS_UPLO::CblasUpper Only the upper triangular part of C is to be referenced. uplo = CBLAS_UPLO::CblasLower Only the lower triangular part of C is to be referenced. \param[in] trans trans is CBLAS_TRANSPOSE On entry, trans specifies the operation to be used as follows: trans = CBLAS_TRANSPOSE::CblasNoTrans,C := alpha*A*A**T + beta*C. trans = CBLAS_TRANSPOSE::CblasTrans,C := alpha*A**T*A + beta*C. \param[in] n n is INTEGER On entry, n specifies the order of the matrix C. n must be at least zero. \param[in] k k is INTEGER If trans = CblasNoTrans: k is number of columns of the matrix A. Otherwise: k is number of rows of the matrix A. k must be at least zero. \param[in] alpha alpha is REAL/DOUBLE PRECISION/COMPLEX/COMPLEX*16 On entry, alpha specifies the scalar alpha. \param[in] A A is REAL/DOUBLE PRECISION/COMPLEX/COMPLEX*16 array,dimension : If transA = CblasNoTrans: n-by-k , stored in an lda-by-k array [RowMajor: n-by-lda]. Otherwise: k-by-n , stored in an lda-by-n array [RowMajor: k-by-lda]. \param[in] lda lda is INTEGER On entry, lda specifies the Leading dimension of A If transA = CblasNoTrans: lda >= max(1, n) [RowMajor: lda >= max(1, k)]. Otherwise: lda >= max(1, k) [RowMajor: lda >= max(1, n)]. \param[in] beta beta is REAL/DOUBLE PRECISION/COMPLEX/COMPLEX*16 On entry, beta specifies the scalar alpha.When beta is supplied as zero then C need not be set on input. \param[in,out] C C is REAL/DOUBLE PRECISION/COMPLEX/COMPLEX*16 array, dimension : The n-by-n symmetric matrix C, stored in an ldc-by-n array [RowMajor: n-by-ldc]. On exit, the array C is overwritten by the lower/upper triangular part of the updated matrix. \param[in] ldc ldc is INTEGER On entry, ldc specifies the first dimension of C ldc >= max(1, n) */ template< typename T > void syrk( CBLAS_ORDER layout, CBLAS_UPLO uplo, CBLAS_TRANSPOSE trans, int64_t n, int64_t k, T alpha, T const *A, int64_t lda, T beta, T *C, int64_t ldc ) { cblas_syrk( layout, uplo, trans, n, k, alpha, A, lda, beta, C, ldc); } /*! \brief Solve the Symmetric rank 2k operations for arbitrary data types \b Purpose: SYR2K performs one of the symmetric rank 2k operations for arbitrary data types Data precisions supported include SINGLE PRECISION REAL, DOUBLE PRECISION REAL, SINGLE PRECISION COMPLEX, DOUBLE PRECISION COMPLEX(COMPLEX*16) C := alpha*A*B**T + alpha*B*A**T + beta*C, or C := alpha*A**T*B + alpha*B**T*A + beta*C, where alpha and beta are scalars, C is an n by n symmetric matrix and A and B are n by k matrices in the first case and k by n matrices in the second case. \param[in] layout layout is enum CBLAS_LAYOUT layout specifies Matrix storage as follows: layout = CBLAS_LAYOUT::CblasRowMajor or Layout::CblasColMajor. \param[in] uplo uplo is enum CBLAS_UPLO uplo specifies specifies whether the upper or lower triangular part of the array C is to be referenced as follows: uplo = CBLAS_UPLO::CblasUpper Only the upper triangular part of C is to be referenced. uplo = CBLAS_UPLO::CblasLower Only the lower triangular part of C is to be referenced. \param[in] trans trans is CBLAS_TRANSPOSE On entry, trans specifies the operation to be used as follows: trans = CBLAS_TRANSPOSE::CblasNoTrans,C := alpha*A*B**T + alpha*B*A**T + beta*C. trans = CBLAS_TRANSPOSE::CblasTrans, C := alpha*A**T*B + alpha*B**T*A + beta*C. \param[in] n n is INTEGER On entry, n specifies the order of the matrix C. n must be at least zero. \param[in] k k is INTEGER If trans = CblasNoTrans: k is number of columns of the matrices A & B. Otherwise: k is number of rows of the matrices A & B. k must be at least zero. \param[in] alpha alpha is REAL/DOUBLE PRECISION/COMPLEX/COMPLEX*16 On entry, alpha specifies the scalar alpha. \param[in] A A is REAL/DOUBLE PRECISION/COMPLEX/COMPLEX*16 array,dimension : If trans = CblasNoTrans: n-by-k , stored in an lda-by-k array [RowMajor: n-by-lda]. Otherwise: k-by-n , stored in an lda-by-n array [RowMajor: k-by-lda]. \param[in] lda lda is INTEGER On entry, lda specifies the Leading dimension of A If trans = CblasNoTrans: lda >= max(1, n) [RowMajor: lda >= max(1, k)]. Otherwise: lda >= max(1, k) [RowMajor: lda >= max(1, n)]. \param[in] B B is REAL/DOUBLE PRECISION/COMPLEX/COMPLEX*16 array,dimension : If trans = CblasNoTrans: n-by-k , stored in an ldb-by-k array [RowMajor: n-by-ldb]. Otherwise: k-by-n , stored in an ldb-by-n array [RowMajor: k-by-ldb] \param[in] ldb ldb is INTEGER On entry, ldb specifies the Leading dimension of B If trans = CblasNoTrans: ldb >= max(1, n) [RowMajor: ldb >= max(1, k)]. Otherwise: ldb >= max(1, k) [RowMajor: ldb >= max(1, n)]. \param[in] beta beta is REAL/DOUBLE PRECISION/COMPLEX/COMPLEX*16 On entry, beta specifies the scalar alpha.When beta is supplied as zero then C need not be set on input. \param[in,out] C C is REAL/DOUBLE PRECISION/COMPLEX/COMPLEX*16 array, dimension : The n-by-n symmetric matrix C, stored in an ldc-by-n array [RowMajor: n-by-ldc]. On exit, the array C is overwritten by the lower/upper triangular part of the updated matrix. \param[in] ldc ldc is INTEGER On entry, ldc specifies the first dimension of C ldc >= max(1, n) */ template< typename T > void syr2k( CBLAS_ORDER layout, CBLAS_UPLO uplo, CBLAS_TRANSPOSE trans, int64_t n, int64_t k, T alpha, T const *A, int64_t lda, T const *B, int64_t ldb, T beta, T *C, int64_t ldc ) { cblas_syr2k( layout, uplo, trans, n, k, alpha, A, lda, B, ldb, beta, C, ldc ); } /*! \brief Solve the Hermitian rank k operations for arbitrary data types \b Purpose: HERK performs one of the hermitian rank k operations for arbitrary data types Data precisions supported include SINGLE PRECISION COMPLEX, DOUBLE PRECISION COMPLEX(COMPLEX*16) C := alpha*A*B**H + conjg( alpha )*B*A**H + beta*C, or C := alpha*A**H*B + conjg( alpha )*B**H*A + beta*C, where alpha and beta are real scalars, C is an n by n hermitian matrix and A is an n by k matrix in the first case and k by n matrix in the second case. \param[in] layout layout is enum CBLAS_LAYOUT layout specifies Matrix storage as follows: layout = CBLAS_LAYOUT::CblasRowMajor or Layout::CblasColMajor. \param[in] uplo uplo is enum CBLAS_UPLO uplo specifies specifies whether the upper or lower triangular part of the array C is to be referenced as follows: uplo = CBLAS_UPLO::CblasUpper Only the upper triangular part of C is to be referenced. uplo = CBLAS_UPLO::CblasLower Only the lower triangular part of C is to be referenced. \param[in] trans trans is CBLAS_TRANSPOSE On entry, trans specifies the operation to be used as follows: trans = CBLAS_TRANSPOSE::CblasNoTrans, C := alpha*A*A**H + beta*C. trans = CBLAS_TRANSPOSE::CblasConjTrans,C := alpha*A**H*A + beta*C. \param[in] n n is INTEGER On entry, n specifies the order of the matrix C. n must be at least zero. \param[in] k k is INTEGER If trans = CblasNoTrans: k is number of columns of the matrix A. Otherwise: k is number of rows of the matrix A. k must be at least zero. \param[in] alpha alpha is REAL/DOUBLE PRECISION On entry, alpha specifies the scalar alpha. \param[in] A A is COMPLEX/COMPLEX*16 array,dimension : If trans = CblasNoTrans: n-by-k , stored in an lda-by-k array [RowMajor: n-by-lda]. Otherwise: k-by-n , stored in an lda-by-n array [RowMajor: k-by-lda]. \param[in] lda lda is INTEGER On entry, lda specifies the Leading dimension of A If trans = CblasNoTrans: lda >= max(1, n) [RowMajor: lda >= max(1, k)]. Otherwise: lda >= max(1, k) [RowMajor: lda >= max(1, n)]. \param[in] beta beta is REAL/DOUBLE PRECISION On entry, beta specifies the scalar alpha.When beta is supplied as zero then C need not be set on input. \param[in,out] C C is COMPLEX/COMPLEX*16 array, dimension : The n-by-n Hermitian matrix C, stored in an ldc-by-n array [RowMajor: n-by-ldc]. On exit, the array C is overwritten by the lower/upper triangular part of the updated matrix. \param[in] ldc ldc is INTEGER On entry, ldc specifies the first dimension of C ldc >= max(1, n) */ template< typename T > void herk( CBLAS_ORDER layout, CBLAS_UPLO uplo, CBLAS_TRANSPOSE trans, int64_t n, int64_t k, real_type alpha, T const *A, int64_t lda, real_type beta, T *C, int64_t ldc ) { cblas_herk( layout, uplo, trans, n, k, alpha, A, lda, beta, C, ldc ); } /*! \brief Solve the Hermitian rank 2k operations for arbitrary data types \b Purpose: HER2K performs one of the hermitian rank 2k operations for arbitrary data types Data precisions supported include SINGLE PRECISION COMPLEX, DOUBLE PRECISION COMPLEX(COMPLEX*16) C := alpha*A*B**H + conjg( alpha )*B*A**H + beta*C, or C := alpha*A**H*B + conjg( alpha )*B**H*A + beta*C, where alpha and beta are scalars with beta real, C is an n by n hermitian matrix and A and B are n by k matrices in the first case and k by n matrices in the second case. \param[in] layout layout is enum CBLAS_LAYOUT layout specifies Matrix storage as follows: layout = CBLAS_LAYOUT::CblasRowMajor or Layout::CblasColMajor. \param[in] uplo uplo is enum CBLAS_UPLO uplo specifies specifies whether the upper or lower triangular part of the array C is to be referenced as follows: uplo = CBLAS_UPLO::CblasUpper Only the upper triangular part of C is to be referenced. uplo = CBLAS_UPLO::CblasLower Only the lower triangular part of C is to be referenced. \param[in] trans trans is CBLAS_TRANSPOSE On entry, trans specifies the operation to be used as follows: trans = CBLAS_TRANSPOSE::CblasNoTrans, C := alpha*A*B**H + conjg( alpha )*B*A**H + beta*C. trans = CBLAS_TRANSPOSE::CblasConjTrans,C := alpha*A**H*B + conjg( alpha )*B**H*A + beta*C. \param[in] n n is INTEGER On entry, n specifies the order of the matrix C. n must be at least zero. \param[in] k k is INTEGER If trans = CblasNoTrans: k is number of columns of the matrices A & B. Otherwise: k is number of rows of the matrices A & B. k must be at least zero. \param[in] alpha alpha is COMPLEX/COMPLEX*16 On entry, alpha specifies the scalar alpha. \param[in] A A is COMPLEX/COMPLEX*16 array,dimension : If trans = CblasNoTrans: n-by-k , stored in an lda-by-k array [RowMajor: n-by-lda]. Otherwise: k-by-n , stored in an lda-by-n array [RowMajor: k-by-lda]. \param[in] lda lda is INTEGER On entry, lda specifies the Leading dimension of A If trans = CblasNoTrans: lda >= max(1, n) [RowMajor: lda >= max(1, k)]. Otherwise: lda >= max(1, k) [RowMajor: lda >= max(1, n)]. \param[in] B B is COMPLEX/COMPLEX*16 array,dimension : If trans = CblasNoTrans: n-by-k , stored in an ldb-by-k array [RowMajor: n-by-ldb]. Otherwise: k-by-n , stored in an ldb-by-n array [RowMajor: k-by-ldb] \param[in] ldb ldb is INTEGER On entry, ldb specifies the Leading dimension of B If trans = CblasNoTrans: ldb >= max(1, n) [RowMajor: ldb >= max(1, k)]. Otherwise: ldb >= max(1, k) [RowMajor: ldb >= max(1, n)]. \param[in] beta beta is REAL/DOUBLE PRECISION On entry, beta specifies the scalar alpha.When beta is supplied as zero then C need not be set on input. \param[in,out] C C is COMPLEX/COMPLEX*16 array, dimension : The n-by-n Hermitian matrix C, stored in an ldc-by-n array [RowMajor: n-by-ldc]. On exit, the array C is overwritten by the lower/upper triangular part of the updated matrix. \param[in] ldc ldc is INTEGER On entry, ldc specifies the first dimension of C ldc >= max(1, n) */ template< typename T > void her2k( CBLAS_ORDER layout, CBLAS_UPLO uplo, CBLAS_TRANSPOSE trans, int64_t n, int64_t k, T alpha, T const *A, int64_t lda, T const *B, int64_t ldb, real_type beta, T *C, int64_t ldc ) { cblas_her2k( layout, uplo, trans, n, k, alpha, A, lda, B, ldb, beta, C, ldc ); } } // namespace blis #endif // #ifndef BLIS_HH blis-0.9.0/vendor/cpp/cblas.hh000066400000000000000000001261521422157504600161520ustar00rootroot00000000000000/****************************************************************************** * Copyright (c) 2019 - present Advanced Micro Devices, Inc. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. *******************************************************************************/ /*! @file cblas.hh * cblas.hh defines all the overloaded CPP functions to be invoked from * template interfaces * */ #ifndef CBLAS_HH #define CBLAS_HH extern "C" { #include } #include namespace blis{ template< typename... Types > struct real_type_traits; //define real_type<> type alias template< typename... Types > using real_type = typename real_type_traits< Types... >::real_t; // for one type template< typename T > struct real_type_traits { using real_t = T; }; // for one complex type, strip complex template< typename T > struct real_type_traits< std::complex > { using real_t = T; }; // ============================================================================= // Level 1 BLAS // ----------------------------------------------------------------------------- inline void cblas_rotg( float *a, float *b, float *c, float *s ) { cblas_srotg( a, b, c, s ); } inline void cblas_rotg( double *a, double *b, double *c, double *s ) { cblas_drotg( a, b, c, s ); } // ----------------------------------------------------------------------------- inline void cblas_rotmg( float *d1, float *d2, float *x1, float y1, float param[5] ) { cblas_srotmg( d1, d2, x1, y1, param ); } inline void cblas_rotmg( double *d1, double *d2, double *x1, double y1, double param[5] ) { cblas_drotmg( d1, d2, x1, y1, param ); } // ----------------------------------------------------------------------------- inline void cblas_rot( int n, float *x, int incx, float *y, int incy, float c, float s ) { cblas_srot( n, x, incx, y, incy, c, s ); } inline void cblas_rot( int n, double *x, int incx, double *y, int incy, double c, double s ) { cblas_drot( n, x, incx, y, incy, c, s ); } // ----------------------------------------------------------------------------- inline void cblas_rotm( int n, float *x, int incx, float *y, int incy, const float p[5] ) { cblas_srotm( n, x, incx, y, incy, p ); } inline void cblas_rotm( int n, double *x, int incx, double *y, int incy, const double p[5] ) { cblas_drotm( n, x, incx, y, incy, p ); } // ----------------------------------------------------------------------------- inline void cblas_swap( int n, float* x, int incx, float* y, int incy ) { cblas_sswap( n, x, incx, y, incy ); } inline void cblas_swap( int n, double* x, int incx, double* y, int incy ) { cblas_dswap( n, x, incx, y, incy ); } inline void cblas_swap( int n, std::complex* x, int incx, std::complex* y, int incy ) { cblas_cswap( n, x, incx, y, incy ); } inline void cblas_swap( int n, std::complex* x, int incx, std::complex* y, int incy ) { cblas_zswap( n, x, incx, y, incy ); } // ----------------------------------------------------------------------------- inline void cblas_scal( int n, float alpha, float* x, int incx ) { cblas_sscal( n, alpha, x, incx ); } inline void cblas_scal( int n, double alpha, double* x, int incx ) { cblas_dscal( n, alpha, x, incx ); } inline void cblas_scal( int n, std::complex alpha, std::complex* x, int incx ) { cblas_cscal( n, &alpha, x, incx ); } inline void cblas_scal( int n, std::complex alpha, std::complex* x, int incx ) { cblas_zscal( n, &alpha, x, incx ); } inline void cblas_scal( int n, float alpha, std::complex* x, int incx ) { cblas_csscal( n, alpha, x, incx ); } inline void cblas_scal( int n, double alpha, std::complex* x, int incx ) { cblas_zdscal( n, alpha, x, incx ); } // ----------------------------------------------------------------------------- inline void cblas_copy( int n, float const *x, int incx, float* y, int incy ) { cblas_scopy( n, x, incx, y, incy ); } inline void cblas_copy( int n, double const *x, int incx, double* y, int incy ) { cblas_dcopy( n, x, incx, y, incy ); } inline void cblas_copy( int n, std::complex const *x, int incx, std::complex* y, int incy ) { cblas_ccopy( n, x, incx, y, incy ); } inline void cblas_copy( int n, std::complex const *x, int incx, std::complex* y, int incy ) { cblas_zcopy( n, x, incx, y, incy ); } // ----------------------------------------------------------------------------- inline void cblas_axpy( int n, float alpha, float const *x, int incx, float* y, int incy ) { cblas_saxpy( n, alpha, x, incx, y, incy ); } inline void cblas_axpy( int n, double alpha, double const *x, int incx, double* y, int incy ) { cblas_daxpy( n, alpha, x, incx, y, incy ); } inline void cblas_axpy( int n, std::complex alpha, std::complex const *x, int incx, std::complex* y, int incy ) { cblas_caxpy( n, &alpha, x, incx, y, incy ); } inline void cblas_axpy( int n, std::complex alpha, std::complex const *x, int incx, std::complex* y, int incy ) { cblas_zaxpy( n, &alpha, x, incx, y, incy ); } // ----------------------------------------------------------------------------- inline float cblas_dot( int n, float const *x, int incx, float const *y, int incy ) { return cblas_sdot( n, x, incx, y, incy ); } inline double cblas_dot( int n, double const *x, int incx, double const *y, int incy ) { return cblas_ddot( n, x, incx, y, incy ); } // ----------------------------------------------------------------------------- inline std::complex cblas_dotu( int n, std::complex const *x, int incx, std::complex const *y, int incy ) { std::complex result; cblas_cdotu_sub( n, x, incx, y, incy, &result ); return result; } inline std::complex cblas_dotu( int n, std::complex const *x, int incx, std::complex const *y, int incy ) { std::complex result; cblas_zdotu_sub( n, x, incx, y, incy, &result ); return result; } // ----------------------------------------------------------------------------- inline std::complex cblas_dotc( int n, std::complex const *x, int incx, std::complex const *y, int incy ) { std::complex result; cblas_cdotc_sub( n, x, incx, y, incy, &result ); return result; } inline std::complex cblas_dotc( int n, std::complex const *x, int incx, std::complex const *y, int incy ) { std::complex result; cblas_zdotc_sub( n, x, incx, y, incy, &result ); return result; } // ----------------------------------------------------------------------------- inline int cblas_iamax( int n, float const *x, int incx ) { return cblas_isamax( n, x, incx ); } inline int cblas_iamax( int n, double const *x, int incx ) { return cblas_idamax( n, x, incx ); } inline int cblas_iamax( int n, std::complex const *x, int incx ) { return cblas_icamax( n, x, incx ); } inline int cblas_iamax( int n, std::complex const *x, int incx ) { return cblas_izamax( n, x, incx ); } // ----------------------------------------------------------------------------- inline float cblas_nrm2( int n, float const *x, int incx ) { return cblas_snrm2( n, x, incx ); } inline double cblas_nrm2( int n, double const *x, int incx ) { return cblas_dnrm2( n, x, incx ); } inline float cblas_nrm2( int n, std::complex const *x, int incx ) { return cblas_scnrm2( n, x, incx ); } inline double cblas_nrm2( int n, std::complex const *x, int incx ) { return cblas_dznrm2( n, x, incx ); } // ----------------------------------------------------------------------------- inline float cblas_asum( int n, float const *x, int incx ) { return cblas_sasum( n, x, incx ); } inline double cblas_asum( int n, double const *x, int incx ) { return cblas_dasum( n, x, incx ); } inline float cblas_asum( int n, std::complex const *x, int incx ) { return cblas_scasum( n, x, incx ); } inline double cblas_asum( int n, std::complex const *x, int incx ) { return cblas_dzasum( n, x, incx ); } // ============================================================================= // Level 2 BLAS // ----------------------------------------------------------------------------- inline void cblas_gemv( CBLAS_ORDER layout, CBLAS_TRANSPOSE trans, int m, int n, float alpha, float const *A, int lda, float const *x, int incx, float beta, float* y, int incy ) { cblas_sgemv( layout, trans, m, n, alpha, A, lda, x, incx, beta, y, incy ); } inline void cblas_gemv( CBLAS_ORDER layout, CBLAS_TRANSPOSE trans, int m, int n, double alpha, double const *A, int lda, double const *x, int incx, double beta, double* y, int incy ) { cblas_dgemv( layout, trans, m, n, alpha, A, lda, x, incx, beta, y, incy ); } inline void cblas_gemv( CBLAS_ORDER layout, CBLAS_TRANSPOSE trans, int m, int n, std::complex alpha, std::complex const *A, int lda, std::complex const *x, int incx, std::complex beta, std::complex* y, int incy ) { cblas_cgemv( layout, trans, m, n, &alpha, A, lda, x, incx, &beta, y, incy ); } inline void cblas_gemv( CBLAS_ORDER layout, CBLAS_TRANSPOSE trans, int m, int n, std::complex alpha, std::complex const *A, int lda, std::complex const *x, int incx, std::complex beta, std::complex* y, int incy ) { cblas_zgemv( layout, trans, m, n, &alpha, A, lda, x, incx, &beta, y, incy ); } inline void cblas_gbmv( CBLAS_ORDER layout, CBLAS_TRANSPOSE trans, int m, int n, int kl, int ku, float alpha, float const *A, int lda, float const *x, int incx, float beta, float* y, int incy ) { cblas_sgbmv( layout, trans, m, n, kl, ku, alpha, A, lda, x, incx, beta, y, incy ); } inline void cblas_gbmv( CBLAS_ORDER layout, CBLAS_TRANSPOSE trans, int m, int n, int kl, int ku, double alpha, double const *A, int lda, double const *x, int incx, double beta, double* y, int incy ) { cblas_dgbmv( layout, trans, m, n, kl, ku, alpha, A, lda, x, incx, beta, y, incy ); } inline void cblas_gbmv( CBLAS_ORDER layout, CBLAS_TRANSPOSE trans, int m, int n, int kl, int ku, std::complex alpha, std::complex const *A, int lda, std::complex const *x, int incx, std::complex beta, std::complex* y, int incy ) { cblas_cgbmv( layout, trans, m, n, kl, ku, &alpha, A, lda, x, incx, &beta, y, incy ); } inline void cblas_gbmv( CBLAS_ORDER layout, CBLAS_TRANSPOSE trans, int m, int n, int kl, int ku, std::complex alpha, std::complex const *A, int lda, std::complex const *x, int incx, std::complex beta, std::complex* y, int incy ) { cblas_zgbmv( layout, trans, m, n, kl, ku, &alpha, A, lda, x, incx, &beta, y, incy ); } // ----------------------------------------------------------------------------- inline void cblas_hemv( CBLAS_ORDER layout, CBLAS_UPLO uplo, int n, std::complex alpha, std::complex const *A, int lda, std::complex const *x, int incx, std::complex beta, std::complex* y, int incy ) { cblas_chemv( layout, uplo, n, &alpha, A, lda, x, incx, &beta, y, incy ); } inline void cblas_hemv( CBLAS_ORDER layout, CBLAS_UPLO uplo, int n, std::complex alpha, std::complex const *A, int lda, std::complex const *x, int incx, std::complex beta, std::complex* y, int incy ) { cblas_zhemv( layout, uplo, n, &alpha, A, lda, x, incx, &beta, y, incy ); } // ----------------------------------------------------------------------------- inline void cblas_hbmv( CBLAS_ORDER layout, CBLAS_UPLO uplo, int n, int k, std::complex alpha, std::complex const *A, int lda, std::complex const *x, int incx, std::complex beta, std::complex* y, int incy ) { cblas_chbmv( layout, uplo, n, k, &alpha, A, lda, x, incx, &beta, y, incy ); } inline void cblas_hbmv( CBLAS_ORDER layout, CBLAS_UPLO uplo, int n, int k, std::complex alpha, std::complex const *A, int lda, std::complex const *x, int incx, std::complex beta, std::complex* y, int incy ) { cblas_zhbmv( layout, uplo, n, k, &alpha, A, lda, x, incx, &beta, y, incy ); } // ----------------------------------------------------------------------------- inline void cblas_hpmv( CBLAS_ORDER layout, CBLAS_UPLO uplo, int n, std::complex alpha, std::complex const *Ap, std::complex const *x, int incx, std::complex beta, std::complex* y, int incy ) { cblas_chpmv( layout, uplo, n, &alpha, Ap, x, incx, &beta, y, incy ); } inline void cblas_hpmv( CBLAS_ORDER layout, CBLAS_UPLO uplo, int n, std::complex alpha, std::complex const *Ap, std::complex const *x, int incx, std::complex beta, std::complex* y, int incy ) { cblas_zhpmv( layout, uplo, n, &alpha, Ap, x, incx, &beta, y, incy ); } // ----------------------------------------------------------------------------- inline void cblas_symv( CBLAS_ORDER layout, CBLAS_UPLO uplo, int n, float alpha, float const *A, int lda, float const *x, int incx, float beta, float* y, int incy ) { cblas_ssymv( layout, uplo, n, alpha, A, lda, x, incx, beta, y, incy ); } inline void cblas_symv( CBLAS_ORDER layout, CBLAS_UPLO uplo, int n, double alpha, double const *A, int lda, double const *x, int incx, double beta, double* y, int incy ) { cblas_dsymv( layout, uplo, n, alpha, A, lda, x, incx, beta, y, incy ); } // ----------------------------------------------------------------------------- inline void cblas_sbmv( CBLAS_ORDER layout, CBLAS_UPLO uplo, int n, int k, float alpha, float const *A, int lda, float const *x, int incx, float beta, float* y, int incy ) { cblas_ssbmv( layout, uplo, n, k, alpha, A, lda, x, incx, beta, y, incy ); } inline void cblas_sbmv( CBLAS_ORDER layout, CBLAS_UPLO uplo, int n, int k, double alpha, double const *A, int lda, double const *x, int incx, double beta, double* y, int incy ) { cblas_dsbmv( layout, uplo, n, k, alpha, A, lda, x, incx, beta, y, incy ); } // ----------------------------------------------------------------------------- inline void cblas_spmv( CBLAS_ORDER layout, CBLAS_UPLO uplo, int n, float alpha, float const *Ap, float const *x, int incx, float beta, float* y, int incy ) { cblas_sspmv( layout, uplo, n, alpha, Ap, x, incx, beta, y, incy ); } inline void cblas_spmv( CBLAS_ORDER layout, CBLAS_UPLO uplo, int n, double alpha, double const *Ap, double const *x, int incx, double beta, double* y, int incy ) { cblas_dspmv( layout, uplo, n, alpha, Ap, x, incx, beta, y, incy ); } // ----------------------------------------------------------------------------- inline void cblas_trmv( CBLAS_ORDER layout, CBLAS_UPLO uplo, CBLAS_TRANSPOSE trans, CBLAS_DIAG diag, int n, float const *A, int lda, float* x, int incx ) { cblas_strmv( layout, uplo, trans, diag, n, A, lda, x, incx ); } inline void cblas_trmv( CBLAS_ORDER layout, CBLAS_UPLO uplo, CBLAS_TRANSPOSE trans, CBLAS_DIAG diag, int n, double const *A, int lda, double* x, int incx ) { cblas_dtrmv( layout, uplo, trans, diag, n, A, lda, x, incx ); } inline void cblas_trmv( CBLAS_ORDER layout, CBLAS_UPLO uplo, CBLAS_TRANSPOSE trans, CBLAS_DIAG diag, int n, std::complex const *A, int lda, std::complex* x, int incx ) { cblas_ctrmv( layout, uplo, trans, diag, n, A, lda, x, incx ); } inline void cblas_trmv( CBLAS_ORDER layout, CBLAS_UPLO uplo, CBLAS_TRANSPOSE trans, CBLAS_DIAG diag, int n, std::complex const *A, int lda, std::complex* x, int incx ) { cblas_ztrmv( layout, uplo, trans, diag, n, A, lda, x, incx ); } // ----------------------------------------------------------------------------- inline void cblas_tbmv( CBLAS_ORDER layout, CBLAS_UPLO uplo, CBLAS_TRANSPOSE trans, CBLAS_DIAG diag, int n, int k, float const *A, int lda, float* x, int incx ) { cblas_stbmv( layout, uplo, trans, diag, n, k, A, lda, x, incx ); } inline void cblas_tbmv( CBLAS_ORDER layout, CBLAS_UPLO uplo, CBLAS_TRANSPOSE trans, CBLAS_DIAG diag, int n, int k, double const *A, int lda, double* x, int incx ) { cblas_dtbmv( layout, uplo, trans, diag, n, k, A, lda, x, incx ); } inline void cblas_tbmv( CBLAS_ORDER layout, CBLAS_UPLO uplo, CBLAS_TRANSPOSE trans, CBLAS_DIAG diag, int n, int k, std::complex const *A, int lda, std::complex* x, int incx ) { cblas_ctbmv( layout, uplo, trans, diag, n, k, A, lda, x, incx ); } inline void cblas_tbmv( CBLAS_ORDER layout, CBLAS_UPLO uplo, CBLAS_TRANSPOSE trans, CBLAS_DIAG diag, int n, int k, std::complex const *A, int lda, std::complex* x, int incx ) { cblas_ztbmv( layout, uplo, trans, diag, n, k, A, lda, x, incx ); } // ----------------------------------------------------------------------------- inline void cblas_tpmv( CBLAS_ORDER layout, CBLAS_UPLO uplo, CBLAS_TRANSPOSE trans, CBLAS_DIAG diag, int n, float const *Ap, float* x, int incx ) { cblas_stpmv( layout, uplo, trans, diag, n, Ap, x, incx ); } inline void cblas_tpmv( CBLAS_ORDER layout, CBLAS_UPLO uplo, CBLAS_TRANSPOSE trans, CBLAS_DIAG diag, int n, double const *Ap, double* x, int incx ) { cblas_dtpmv( layout, uplo, trans, diag, n, Ap, x, incx ); } inline void cblas_tpmv( CBLAS_ORDER layout, CBLAS_UPLO uplo, CBLAS_TRANSPOSE trans, CBLAS_DIAG diag, int n, std::complex const *Ap, std::complex* x, int incx ) { cblas_ctpmv( layout, uplo, trans, diag, n, Ap, x, incx ); } inline void cblas_tpmv( CBLAS_ORDER layout, CBLAS_UPLO uplo, CBLAS_TRANSPOSE trans, CBLAS_DIAG diag, int n, std::complex const *Ap, std::complex* x, int incx ) { cblas_ztpmv( layout, uplo, trans, diag, n, Ap, x, incx ); } // ----------------------------------------------------------------------------- inline void cblas_trsv( CBLAS_ORDER layout, CBLAS_UPLO uplo, CBLAS_TRANSPOSE trans, CBLAS_DIAG diag, int n, float const *A, int lda, float* x, int incx ) { cblas_strsv( layout, uplo, trans, diag, n, A, lda, x, incx ); } inline void cblas_trsv( CBLAS_ORDER layout, CBLAS_UPLO uplo, CBLAS_TRANSPOSE trans, CBLAS_DIAG diag, int n, double const *A, int lda, double* x, int incx ) { cblas_dtrsv( layout, uplo, trans, diag, n, A, lda, x, incx ); } inline void cblas_trsv( CBLAS_ORDER layout, CBLAS_UPLO uplo, CBLAS_TRANSPOSE trans, CBLAS_DIAG diag, int n, std::complex const *A, int lda, std::complex* x, int incx ) { cblas_ctrsv( layout, uplo, trans, diag, n, A, lda, x, incx ); } inline void cblas_trsv( CBLAS_ORDER layout, CBLAS_UPLO uplo, CBLAS_TRANSPOSE trans, CBLAS_DIAG diag, int n, std::complex const *A, int lda, std::complex* x, int incx ) { cblas_ztrsv( layout, uplo, trans, diag, n, A, lda, x, incx ); } // ----------------------------------------------------------------------------- inline void cblas_tbsv( CBLAS_ORDER layout, CBLAS_UPLO uplo, CBLAS_TRANSPOSE trans, CBLAS_DIAG diag, int n, int k, float const *A, int lda, float* x, int incx ) { cblas_stbsv( layout, uplo, trans, diag, n, k, A, lda, x, incx ); } inline void cblas_tbsv( CBLAS_ORDER layout, CBLAS_UPLO uplo, CBLAS_TRANSPOSE trans, CBLAS_DIAG diag, int n, int k, double const *A, int lda, double* x, int incx ) { cblas_dtbsv( layout, uplo, trans, diag, n, k, A, lda, x, incx ); } inline void cblas_tbsv( CBLAS_ORDER layout, CBLAS_UPLO uplo, CBLAS_TRANSPOSE trans, CBLAS_DIAG diag, int n, int k, std::complex const *A, int lda, std::complex* x, int incx ) { cblas_ctbsv( layout, uplo, trans, diag, n, k, A, lda, x, incx ); } inline void cblas_tbsv( CBLAS_ORDER layout, CBLAS_UPLO uplo, CBLAS_TRANSPOSE trans, CBLAS_DIAG diag, int n, int k, std::complex const *A, int lda, std::complex* x, int incx ) { cblas_ztbsv( layout, uplo, trans, diag, n, k, A, lda, x, incx ); } // ----------------------------------------------------------------------------- inline void cblas_tpsv( CBLAS_ORDER layout, CBLAS_UPLO uplo, CBLAS_TRANSPOSE trans, CBLAS_DIAG diag, int n, float const *Ap, float* x, int incx ) { cblas_stpsv( layout, uplo, trans, diag, n, Ap, x, incx ); } inline void cblas_tpsv( CBLAS_ORDER layout, CBLAS_UPLO uplo, CBLAS_TRANSPOSE trans, CBLAS_DIAG diag, int n, double const *Ap, double* x, int incx ) { cblas_dtpsv( layout, uplo, trans, diag, n, Ap, x, incx ); } inline void cblas_tpsv( CBLAS_ORDER layout, CBLAS_UPLO uplo, CBLAS_TRANSPOSE trans, CBLAS_DIAG diag, int n, std::complex const *Ap, std::complex* x, int incx ) { cblas_ctpsv( layout, uplo, trans, diag, n, Ap, x, incx ); } inline void cblas_tpsv( CBLAS_ORDER layout, CBLAS_UPLO uplo, CBLAS_TRANSPOSE trans, CBLAS_DIAG diag, int n, std::complex const *Ap, std::complex* x, int incx ) { cblas_ztpsv( layout, uplo, trans, diag, n, Ap, x, incx ); } // ----------------------------------------------------------------------------- inline void cblas_ger( CBLAS_ORDER layout, int m, int n, float alpha, float const *x, int incx, float const *y, int incy, float* A, int lda ) { cblas_sger( layout, m, n, alpha, x, incx, y, incy, A, lda ); } inline void cblas_ger( CBLAS_ORDER layout, int m, int n, double alpha, double const *x, int incx, double const *y, int incy, double* A, int lda ) { cblas_dger( layout, m, n, alpha, x, incx, y, incy, A, lda ); } // ----------------------------------------------------------------------------- inline void cblas_geru( CBLAS_ORDER layout, int m, int n, std::complex alpha, std::complex const *x, int incx, std::complex const *y, int incy, std::complex* A, int lda ) { cblas_cgeru( layout, m, n, &alpha, x, incx, y, incy, A, lda ); } inline void cblas_geru( CBLAS_ORDER layout, int m, int n, std::complex alpha, std::complex const *x, int incx, std::complex const *y, int incy, std::complex* A, int lda ) { cblas_zgeru( layout, m, n, &alpha, x, incx, y, incy, A, lda ); } // ----------------------------------------------------------------------------- inline void cblas_gerc( CBLAS_ORDER layout, int m, int n, std::complex alpha, std::complex const *x, int incx, std::complex const *y, int incy, std::complex* A, int lda ) { cblas_cgerc( layout, m, n, &alpha, x, incx, y, incy, A, lda ); } inline void cblas_gerc( CBLAS_ORDER layout, int m, int n, std::complex alpha, std::complex const *x, int incx, std::complex const *y, int incy, std::complex* A, int lda ) { cblas_zgerc( layout, m, n, &alpha, x, incx, y, incy, A, lda ); } // ----------------------------------------------------------------------------- inline void cblas_her( CBLAS_ORDER layout, CBLAS_UPLO uplo, int n, float alpha, std::complex const *x, int incx, std::complex* A, int lda ) { cblas_cher( layout, uplo, n, alpha, x, incx, A, lda ); } inline void cblas_her( CBLAS_ORDER layout, CBLAS_UPLO uplo, int n, double alpha, std::complex const *x, int incx, std::complex* A, int lda ) { cblas_zher( layout, uplo, n, alpha, x, incx, A, lda ); } // ----------------------------------------------------------------------------- inline void cblas_hpr( CBLAS_ORDER layout, CBLAS_UPLO uplo, int n, float alpha, std::complex const *x, int incx, std::complex* Ap ) { cblas_chpr( layout, uplo, n, alpha, x, incx, Ap ); } inline void cblas_hpr( CBLAS_ORDER layout, CBLAS_UPLO uplo, int n, double alpha, std::complex const *x, int incx, std::complex* Ap ) { cblas_zhpr( layout, uplo, n, alpha, x, incx, Ap ); } // ----------------------------------------------------------------------------- inline void cblas_her2( CBLAS_ORDER layout, CBLAS_UPLO uplo, int n, std::complex alpha, std::complex const *x, int incx, std::complex const *y, int incy, std::complex* A, int lda ) { cblas_cher2( layout, uplo, n, &alpha, x, incx, y, incy, A, lda ); } inline void cblas_her2( CBLAS_ORDER layout, CBLAS_UPLO uplo, int n, std::complex alpha, std::complex const *x, int incx, std::complex const *y, int incy, std::complex* A, int lda ) { cblas_zher2( layout, uplo, n, &alpha, x, incx, y, incy, A, lda ); } // ----------------------------------------------------------------------------- inline void cblas_hpr2( CBLAS_ORDER layout, CBLAS_UPLO uplo, int n, std::complex alpha, std::complex const *x, int incx, std::complex const *y, int incy, std::complex* Ap ) { cblas_chpr2( layout, uplo, n, &alpha, x, incx, y, incy, Ap ); } inline void cblas_hpr2( CBLAS_ORDER layout, CBLAS_UPLO uplo, int n, std::complex alpha, std::complex const *x, int incx, std::complex const *y, int incy, std::complex* Ap ) { cblas_zhpr2( layout, uplo, n, &alpha, x, incx, y, incy, Ap ); } // ----------------------------------------------------------------------------- inline void cblas_syr( CBLAS_ORDER layout, CBLAS_UPLO uplo, int n, float alpha, float const *x, int incx, float* A, int lda ) { cblas_ssyr( layout, uplo, n, alpha, x, incx, A, lda ); } inline void cblas_syr( CBLAS_ORDER layout, CBLAS_UPLO uplo, int n, double alpha, double const *x, int incx, double* A, int lda ) { cblas_dsyr( layout, uplo, n, alpha, x, incx, A, lda ); } // ----------------------------------------------------------------------------- inline void cblas_spr( CBLAS_ORDER layout, CBLAS_UPLO uplo, int n, float alpha, float const *x, int incx, float* Ap ) { cblas_sspr( layout, uplo, n, alpha, x, incx, Ap ); } inline void cblas_spr( CBLAS_ORDER layout, CBLAS_UPLO uplo, int n, double alpha, double const *x, int incx, double* Ap ) { cblas_dspr( layout, uplo, n, alpha, x, incx, Ap ); } // ----------------------------------------------------------------------------- inline void cblas_syr2( CBLAS_ORDER layout, CBLAS_UPLO uplo, int n, float alpha, float const *x, int incx, float const *y, int incy, float* A, int lda ) { cblas_ssyr2( layout, uplo, n, alpha, x, incx, y, incy, A, lda ); } inline void cblas_syr2( CBLAS_ORDER layout, CBLAS_UPLO uplo, int n, double alpha, double const *x, int incx, double const *y, int incy, double* A, int lda ) { cblas_dsyr2( layout, uplo, n, alpha, x, incx, y, incy, A, lda ); } // ----------------------------------------------------------------------------- inline void cblas_spr2( CBLAS_ORDER layout, CBLAS_UPLO uplo, int n, float alpha, float const *x, int incx, float const *y, int incy, float* Ap ) { cblas_sspr2( layout, uplo, n, alpha, x, incx, y, incy, Ap ); } inline void cblas_spr2( CBLAS_ORDER layout, CBLAS_UPLO uplo, int n, double alpha, double const *x, int incx, double const *y, int incy, double* Ap ) { cblas_dspr2( layout, uplo, n, alpha, x, incx, y, incy, Ap ); } // ============================================================================= // Level 3 BLAS // ----------------------------------------------------------------------------- inline void cblas_gemm( CBLAS_ORDER layout, CBLAS_TRANSPOSE transA, CBLAS_TRANSPOSE transB, int m, int n, int k, float alpha, float const *A, int lda, float const *B, int ldb, float beta, float* C, int ldc ) { cblas_sgemm( layout, transA, transB, m, n, k, alpha, A, lda, B, ldb, beta, C, ldc ); } inline void cblas_gemm( CBLAS_ORDER layout, CBLAS_TRANSPOSE transA, CBLAS_TRANSPOSE transB, int m, int n, int k, double alpha, double const *A, int lda, double const *B, int ldb, double beta, double* C, int ldc ) { cblas_dgemm( layout, transA, transB, m, n, k, alpha, A, lda, B, ldb, beta, C, ldc ); } inline void cblas_gemm( CBLAS_ORDER layout, CBLAS_TRANSPOSE transA, CBLAS_TRANSPOSE transB, int m, int n, int k, std::complex alpha, std::complex const *A, int lda, std::complex const *B, int ldb, std::complex beta, std::complex* C, int ldc ) { cblas_cgemm( layout, transA, transB, m, n, k, &alpha, A, lda, B, ldb, &beta, C, ldc ); } inline void cblas_gemm( CBLAS_ORDER layout, CBLAS_TRANSPOSE transA, CBLAS_TRANSPOSE transB, int m, int n, int k, std::complex alpha, std::complex const *A, int lda, std::complex const *B, int ldb, std::complex beta, std::complex* C, int ldc ) { cblas_zgemm( layout, transA, transB, m, n, k, &alpha, A, lda, B, ldb, &beta, C, ldc ); } // ----------------------------------------------------------------------------- inline void cblas_trmm( CBLAS_ORDER layout, CBLAS_SIDE side, CBLAS_UPLO uplo, CBLAS_TRANSPOSE trans, CBLAS_DIAG diag, int m, int n, float alpha, float const *A, int lda, float *B, int ldb ) { cblas_strmm( layout, side, uplo, trans, diag, m, n, alpha, A, lda, B, ldb); } inline void cblas_trmm( CBLAS_ORDER layout, CBLAS_SIDE side, CBLAS_UPLO uplo, CBLAS_TRANSPOSE trans, CBLAS_DIAG diag, int m, int n, double alpha, double const *A, int lda, double *B, int ldb ) { cblas_dtrmm( layout, side, uplo, trans, diag, m, n, alpha, A, lda, B, ldb); } inline void cblas_trmm( CBLAS_ORDER layout, CBLAS_SIDE side, CBLAS_UPLO uplo, CBLAS_TRANSPOSE trans, CBLAS_DIAG diag, int m, int n, std::complex alpha, std::complex const *A, int lda, std::complex *B, int ldb ) { cblas_ctrmm( layout, side, uplo, trans, diag, m, n, &alpha, A, lda, B, ldb ); } inline void cblas_trmm( CBLAS_ORDER layout, CBLAS_SIDE side, CBLAS_UPLO uplo, CBLAS_TRANSPOSE trans, CBLAS_DIAG diag, int m, int n, std::complex alpha, std::complex const *A, int lda, std::complex *B, int ldb ) { cblas_ztrmm( layout, side, uplo, trans, diag, m, n, &alpha, A, lda, B, ldb ); } // ----------------------------------------------------------------------------- inline void cblas_trsm( CBLAS_ORDER layout, CBLAS_SIDE side, CBLAS_UPLO uplo, CBLAS_TRANSPOSE trans, CBLAS_DIAG diag, int m, int n, float alpha, float const *A, int lda, float *B, int ldb ) { cblas_strsm( layout, side, uplo, trans, diag, m, n, alpha, A, lda, B, ldb); } inline void cblas_trsm( CBLAS_ORDER layout, CBLAS_SIDE side, CBLAS_UPLO uplo, CBLAS_TRANSPOSE trans, CBLAS_DIAG diag, int m, int n, double alpha, double const *A, int lda, double *B, int ldb ) { cblas_dtrsm( layout, side, uplo, trans, diag, m, n, alpha, A, lda, B, ldb); } inline void cblas_trsm( CBLAS_ORDER layout, CBLAS_SIDE side, CBLAS_UPLO uplo, CBLAS_TRANSPOSE trans, CBLAS_DIAG diag, int m, int n, std::complex alpha, std::complex const *A, int lda, std::complex *B, int ldb ) { cblas_ctrsm( layout, side, uplo, trans, diag, m, n, &alpha, A, lda, B, ldb ); } inline void cblas_trsm( CBLAS_ORDER layout, CBLAS_SIDE side, CBLAS_UPLO uplo, CBLAS_TRANSPOSE trans, CBLAS_DIAG diag, int m, int n, std::complex alpha, std::complex const *A, int lda, std::complex *B, int ldb ) { cblas_ztrsm( layout, side, uplo, trans, diag, m, n, &alpha, A, lda, B, ldb ); } // ----------------------------------------------------------------------------- inline void cblas_hemm( CBLAS_ORDER layout, CBLAS_SIDE side, CBLAS_UPLO uplo, int m, int n, float alpha, float const *A, int lda, float const *B, int ldb, float beta, float* C, int ldc ) { cblas_ssymm( layout, side, uplo, m, n, alpha, A, lda, B, ldb, beta, C, ldc ); } inline void cblas_hemm( CBLAS_ORDER layout, CBLAS_SIDE side, CBLAS_UPLO uplo, int m, int n, double alpha, double const *A, int lda, double const *B, int ldb, double beta, double* C, int ldc ) { cblas_dsymm( layout, side, uplo, m, n, alpha, A, lda, B, ldb, beta, C, ldc ); } inline void cblas_hemm( CBLAS_ORDER layout, CBLAS_SIDE side, CBLAS_UPLO uplo, int m, int n, std::complex alpha, std::complex const *A, int lda, std::complex const *B, int ldb, std::complex beta, std::complex* C, int ldc ) { cblas_chemm( layout, side, uplo, m, n, &alpha, A, lda, B, ldb, &beta, C, ldc ); } inline void cblas_hemm( CBLAS_ORDER layout, CBLAS_SIDE side, CBLAS_UPLO uplo, int m, int n, std::complex alpha, std::complex const *A, int lda, std::complex const *B, int ldb, std::complex beta, std::complex* C, int ldc ) { cblas_zhemm( layout, side, uplo, m, n, &alpha, A, lda, B, ldb, &beta, C, ldc ); } // ----------------------------------------------------------------------------- inline void cblas_symm( CBLAS_ORDER layout, CBLAS_SIDE side, CBLAS_UPLO uplo, int m, int n, float alpha, float const *A, int lda, float const *B, int ldb, float beta, float* C, int ldc ) { cblas_ssymm( layout, side, uplo, m, n, alpha, A, lda, B, ldb, beta, C, ldc ); } inline void cblas_symm( CBLAS_ORDER layout, CBLAS_SIDE side, CBLAS_UPLO uplo, int m, int n, double alpha, double const *A, int lda, double const *B, int ldb, double beta, double* C, int ldc ) { cblas_dsymm( layout, side, uplo, m, n, alpha, A, lda, B, ldb, beta, C, ldc ); } inline void cblas_symm( CBLAS_ORDER layout, CBLAS_SIDE side, CBLAS_UPLO uplo, int m, int n, std::complex alpha, std::complex const *A, int lda, std::complex const *B, int ldb, std::complex beta, std::complex* C, int ldc ) { cblas_csymm( layout, side, uplo, m, n, &alpha, A, lda, B, ldb, &beta, C, ldc ); } inline void cblas_symm( CBLAS_ORDER layout, CBLAS_SIDE side, CBLAS_UPLO uplo, int m, int n, std::complex alpha, std::complex const *A, int lda, std::complex const *B, int ldb, std::complex beta, std::complex* C, int ldc ) { cblas_zsymm( layout, side, uplo, m, n, &alpha, A, lda, B, ldb, &beta, C, ldc ); } // ----------------------------------------------------------------------------- inline void cblas_syrk( CBLAS_ORDER layout, CBLAS_UPLO uplo, CBLAS_TRANSPOSE trans, int n, int k, float alpha, float const *A, int lda, float beta, float* C, int ldc ) { cblas_ssyrk( layout, uplo, trans, n, k, alpha, A, lda, beta, C, ldc ); } inline void cblas_syrk( CBLAS_ORDER layout, CBLAS_UPLO uplo, CBLAS_TRANSPOSE trans, int n, int k, double alpha, double const *A, int lda, double beta, double* C, int ldc ) { cblas_dsyrk( layout, uplo, trans, n, k, alpha, A, lda, beta, C, ldc ); } inline void cblas_syrk( CBLAS_ORDER layout, CBLAS_UPLO uplo, CBLAS_TRANSPOSE trans, int n, int k, std::complex alpha, std::complex const *A, int lda, std::complex beta, std::complex* C, int ldc ) { cblas_csyrk( layout, uplo, trans, n, k, &alpha, A, lda, &beta, C, ldc ); } inline void cblas_syrk( CBLAS_ORDER layout, CBLAS_UPLO uplo, CBLAS_TRANSPOSE trans, int n, int k, std::complex alpha, std::complex const *A, int lda, std::complex beta, std::complex* C, int ldc ) { cblas_zsyrk( layout, uplo, trans, n, k, &alpha, A, lda, &beta, C, ldc ); } // ----------------------------------------------------------------------------- inline void cblas_herk( CBLAS_ORDER layout, CBLAS_UPLO uplo, CBLAS_TRANSPOSE trans, int n, int k, float alpha, float const *A, int lda, float beta, float* C, int ldc ) { cblas_ssyrk( layout, uplo, trans, n, k, alpha, A, lda, beta, C, ldc ); } inline void cblas_herk( CBLAS_ORDER layout, CBLAS_UPLO uplo, CBLAS_TRANSPOSE trans, int n, int k, double alpha, double const *A, int lda, double beta, double* C, int ldc ) { cblas_dsyrk( layout, uplo, trans, n, k, alpha, A, lda, beta, C, ldc ); } inline void cblas_herk( CBLAS_ORDER layout, CBLAS_UPLO uplo, CBLAS_TRANSPOSE trans, int n, int k, float alpha, // note: real std::complex const *A, int lda, float beta, // note: real std::complex* C, int ldc ) { cblas_cherk( layout, uplo, trans, n, k, alpha, A, lda, beta, C, ldc ); } inline void cblas_herk( CBLAS_ORDER layout, CBLAS_UPLO uplo, CBLAS_TRANSPOSE trans, int n, int k, double alpha, // note: real std::complex const *A, int lda, double beta, // note: real std::complex* C, int ldc ) { cblas_zherk( layout, uplo, trans, n, k, alpha, A, lda, beta, C, ldc ); } // ----------------------------------------------------------------------------- inline void cblas_syr2k( CBLAS_ORDER layout, CBLAS_UPLO uplo, CBLAS_TRANSPOSE trans, int n, int k, float alpha, float const *A, int lda, float const *B, int ldb, float beta, float* C, int ldc ) { cblas_ssyr2k( layout, uplo, trans, n, k, alpha, A, lda, B, ldb, beta, C, ldc ); } inline void cblas_syr2k( CBLAS_ORDER layout, CBLAS_UPLO uplo, CBLAS_TRANSPOSE trans, int n, int k, double alpha, double const *A, int lda, double const *B, int ldb, double beta, double* C, int ldc ) { cblas_dsyr2k( layout, uplo, trans, n, k, alpha, A, lda, B, ldb, beta, C, ldc ); } inline void cblas_syr2k( CBLAS_ORDER layout, CBLAS_UPLO uplo, CBLAS_TRANSPOSE trans, int n, int k, std::complex alpha, std::complex const *A, int lda, std::complex const *B, int ldb, std::complex beta, std::complex* C, int ldc ) { cblas_csyr2k( layout, uplo, trans, n, k, &alpha, A, lda, B, ldb, &beta, C, ldc ); } inline void cblas_syr2k( CBLAS_ORDER layout, CBLAS_UPLO uplo, CBLAS_TRANSPOSE trans, int n, int k, std::complex alpha, std::complex const *A, int lda, std::complex const *B, int ldb, std::complex beta, std::complex* C, int ldc ) { cblas_zsyr2k( layout, uplo, trans, n, k, &alpha, A, lda, B, ldb, &beta, C, ldc ); } // ----------------------------------------------------------------------------- inline void cblas_her2k( CBLAS_ORDER layout, CBLAS_UPLO uplo, CBLAS_TRANSPOSE trans, int n, int k, float alpha, float const *A, int lda, float const *B, int ldb, float beta, float* C, int ldc ) { cblas_ssyr2k( layout, uplo, trans, n, k, alpha, A, lda, B, ldb, beta, C, ldc ); } inline void cblas_her2k( CBLAS_ORDER layout, CBLAS_UPLO uplo, CBLAS_TRANSPOSE trans, int n, int k, double alpha, double const *A, int lda, double const *B, int ldb, double beta, double* C, int ldc ) { cblas_dsyr2k( layout, uplo, trans, n, k, alpha, A, lda, B, ldb, beta, C, ldc ); } inline void cblas_her2k( CBLAS_ORDER layout, CBLAS_UPLO uplo, CBLAS_TRANSPOSE trans, int n, int k, std::complex alpha, std::complex const *A, int lda, std::complex const *B, int ldb, float beta, // note: real std::complex* C, int ldc ) { cblas_cher2k( layout, uplo, trans, n, k, &alpha, A, lda, B, ldb, beta, C, ldc ); } inline void cblas_her2k( CBLAS_ORDER layout, CBLAS_UPLO uplo, CBLAS_TRANSPOSE trans, int n, int k, std::complex alpha, std::complex const *A, int lda, std::complex const *B, int ldb, double beta, // note: real std::complex* C, int ldc ) { cblas_zher2k( layout, uplo, trans, n, k, &alpha, A, lda, B, ldb, beta, C, ldc ); } }//namespace blis #endif // #ifndef CBLAS_HH blis-0.9.0/vendor/testcpp/000077500000000000000000000000001422157504600154365ustar00rootroot00000000000000blis-0.9.0/vendor/testcpp/Makefile000066400000000000000000000125501422157504600171010ustar00rootroot00000000000000# BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2014, The University of Texas at Austin # Copyright (C) 2017 - 2019, Advanced Micro Devices, Inc. # # 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(s) of the copyright holder(s) 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 COPYRIGHT # HOLDER 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. # # # # Makefile # # Field G. Van Zee # # Makefile for standalone BLIS test drivers. # # # --- Makefile PHONY target definitions ---------------------------------------- # .PHONY: all \ blis \ clean cleanx # # --- Determine makefile fragment location ------------------------------------- # # Comments: # - DIST_PATH is assumed to not exist if BLIS_INSTALL_PATH is given. # - We must use recursively expanded assignment for LIB_PATH and INC_PATH in # the second case because CONFIG_NAME is not yet set. ifneq ($(strip $(BLIS_INSTALL_PATH)),) LIB_PATH := $(BLIS_INSTALL_PATH)/lib INC_PATH := $(BLIS_INSTALL_PATH)/include/blis SHARE_PATH := $(BLIS_INSTALL_PATH)/share/blis else DIST_PATH := ../.. LIB_PATH = ../../lib/$(CONFIG_NAME) INC_PATH = ../../include/$(CONFIG_NAME) SHARE_PATH := ../.. endif # # --- Include common makefile definitions -------------------------------------- # # Include the common makefile fragment. -include $(SHARE_PATH)/common.mk # # --- BLAS and LAPACK implementations ------------------------------------------ # # BLIS library and header path. This is simply wherever it was installed. #BLIS_LIB_PATH := $(INSTALL_PREFIX)/lib #BLIS_INC_PATH := $(INSTALL_PREFIX)/include/blis # BLIS library. #BLIS_LIB := $(BLIS_LIB_PATH)/libblis.a # BLAS library path(s). This is where the BLAS libraries reside. BLAS_LIB_PATH := $(HOME)/flame/lib # # --- General build definitions ------------------------------------------------ # TEST_SRC_PATH := . CPP_SRC_PATH := ../cpp/ TEST_OBJ_PATH := . # Gather all local object files. TEST_OBJS := $(patsubst $(TEST_SRC_PATH)/%.c, \ $(TEST_OBJ_PATH)/%.o, \ $(wildcard $(TEST_SRC_PATH)/*.c)) # Override the value of CINCFLAGS so that the value of CFLAGS returned by # get-user-cflags-for() is not cluttered up with include paths needed only # while building BLIS. CINCFLAGS := -I$(INC_PATH) CXX = g++ # Use the CFLAGS for the configuration family. override CFLAGS += $(call get-sandbox-cxxflags-for,$(CONFIG_NAME)) # Add local header paths to CFLAGS #CFLAGS = -O0 -g -Wall #CFLAGS += -I$(INC_PATH) override CFLAGS += -I$(TEST_SRC_PATH) override CFLAGS += -I$(CPP_SRC_PATH) LINKER = $(CXX) # Locate the libblis library to which we will link. LIBBLIS_LINK := $(LIB_PATH)/$(LIBBLIS_L) # # --- Targets/rules ------------------------------------------------------------ # # Complete list of possible targets when defining 'all': # # blis # all: blis blis: test_asum_blis.x \ test_axpy_blis.x \ test_copy_blis.x \ test_dot_blis.x \ test_dotc_blis.x \ test_gbmv_blis.x \ test_gemm_blis.x \ test_gemv_blis.x \ test_ger_blis.x \ test_gerc_blis.x \ test_geru_blis.x \ test_hemm_blis.x \ test_hemv_blis.x \ test_her2_blis.x \ test_her_blis.x \ test_herk_blis.x \ test_hpr2_blis.x \ test_hpr_blis.x \ test_nrm2_blis.x \ test_rot_blis.x \ test_rotg_blis.x \ test_rotm_blis.x \ test_rotmg_blis.x \ test_scal_blis.x \ test_sdsdot_blis.x \ test_spr2_blis.x \ test_spr_blis.x \ test_swap_blis.x \ test_symm_blis.x \ test_syr2_blis.x \ test_syr2k_blis.x \ test_syr_blis.x \ test_syrk_blis.x \ test_tbmv_blis.x \ test_tbsv_blis.x \ test_tpmv_blis.x \ test_tpsv_blis.x \ test_trmm_blis.x \ test_trsm_blis.x \ test_trsv_blis.x # --Object file rules -- $(TEST_OBJ_PATH)/%.o: $(TEST_SRC_PATH)/%.cc $(CXX) $(CFLAGS) -c $< -o $@ test_%_blis.o: test_%.cc @$(CXX) $(CFLAGS) -c $< -o $@ # -- Executable file rules -- test_%_blis.x: test_%_blis.o $(LIBBLIS_LINK) @$(LINKER) $^ $(LIBBLIS_LINK) $(LDFLAGS) -o $@ ./$@ # -- Clean rules -- clean: cleanx cleanx: - $(RM_F) *.o *.x blis-0.9.0/vendor/testcpp/test.hh000066400000000000000000000126131422157504600167410ustar00rootroot00000000000000/* * -------------------------------------------------------------------------- * BLISLAB * -------------------------------------------------------------------------- * Copyright (C) 2016, The University of Texas at Austin * * 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 The University of Texas 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 COPYRIGHT * HOLDER 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. * * * test.hh * * * Purpose: * this header file contains all function prototypes. * * Todo: * * * Modification: * * * */ #ifndef TEST_HH #define TEST_HH #include #include #include using namespace std; #define min( i, j ) ( (i)<(j) ? (i): (j) ) #define A( i, j ) A[ (j)*lda + (i) ] #define A_ref( i, j ) A_ref[ (j)*lda_ref + (i) ] #define B( i, j ) B[ (j)*ldb + (i) ] #define B_ref( i, j ) B_ref[ (j)*ldb_ref + (i) ] #define C( i, j ) C[ (j)*ldc + (i) ] #define C_ref( i, j ) C_ref[ (j)*ldc_ref + (i) ] #define X( i ) X[ incx + (i) ] #define X_ref( i, j ) X_ref[ (j)*incx_ref + (i) #define Y( i ) Y[ incy + (i) ] #define Y_ref( i ) Y_ref[ incy_ref + (i) ]\ // Allocate memory and initialise memory with random values void allocate_init_buffer(int *aIn, int m, int n) { aIn = new int [m*n]; for ( int i = 0; i < m*n; i ++ ) { aIn[ i ] = ((int) rand() / ((int) RAND_MAX / 2.0)) - 1.0; } } void allocate_init_buffer(float *&aIn, int m, int n) { aIn = new float [m*n]; for ( int i = 0; i < m*n; i ++ ) { aIn[ i ] = ((float) rand() / ((float) RAND_MAX / 2.0)) - 1.0; } } void allocate_init_buffer(double *&aIn, int m, int n) { aIn = new double [m*n]; for ( int i = 0; i < m*n; i ++ ) { aIn[ i ] = ((double) rand() / ((double) RAND_MAX / 2.0)) - 1.0; } } void allocate_init_buffer(complex *&aIn, int m, int n) { aIn = new complex [m*n]; for ( int i = 0; i < m*n; i ++ ) { float real = ((float) rand() / ((float) RAND_MAX / 2.0)) - 1.0; float imag = ((float) rand() / ((float) RAND_MAX / 2.0)) - 1.0; aIn[i] = {real,imag}; } } void allocate_init_buffer(complex *&aIn, int m, int n) { aIn = new complex [m*n]; for ( int i = 0; i < m*n; i ++ ) { double real = ((double) rand() / ((double) RAND_MAX / 2.0)) - 1.0; double imag = ((double) rand() / ((double) RAND_MAX / 2.0)) - 1.0; aIn[i] = {real,imag}; } } template< typename T > void copy_buffer(T *aSrc, T *&aDest, int m, int n) { aDest = new T [m*n]; for ( int i = 0; i < m*n; i ++ ) { aDest[i] = aSrc[i]; } } template< typename T > int computeErrorM( int lda, int lda_ref, int m, int n, T *A, T *A_ref ) { int i, j; int ret = 0; for ( i = 0; i < m; i ++ ) { for ( j = 0; j < n; j ++ ) { if ( (fabs (A( i, j )) - fabs( A_ref( i, j ))) > 0.0000001 ) { cout << A(i,j) << A_ref(i,j); ret = 1; break; } } } return ret; } template< typename T > int computeErrorV( int incy, int incy_ref, int n, T *Y, T *Y_ref ) { int i; int ret = 0; for ( i = 0; i < n; i ++ ) { if ( (fabs( Y_ref[ i ]) - fabs(Y[ i ] ) ) > 0.00001) { cout << Y[i] << Y_ref[i]; ret = 1; break; } } return ret; } /* *printing matix and vector * */ template void printmatrix( T *A, int lda, int m, int n, char *func_str ) { int i, j; cout << func_str <<"\n"; for ( i = 0; i < m; i ++ ) { for ( j = 0; j < n; j ++ ) { cout<< A[j * lda + i]<<" "; } printf("\n"); } printf("\n"); } template void printvector( T *X, int m, char *func_str ) { int i; cout << func_str <<"\n"; for ( i = 0; i < m; i ++ ) { cout<< X[i]<<" "; cout<<"\n"; } printf("\n"); } #endif blis-0.9.0/vendor/testcpp/test.sh000066400000000000000000000014711422157504600167540ustar00rootroot00000000000000 echo Build BLIS CPP Template tests make clean make echo Run tests ./test_asum_blis.x ./test_axpy_blis.x ./test_copy_blis.x ./test_dot_blis.x ./test_dotc_blis.x ./test_gbmv_blis.x ./test_gemm_blis.x ./test_gemv_blis.x ./test_ger_blis.x ./test_gerc_blis.x ./test_geru_blis.x ./test_hemm_blis.x ./test_hemv_blis.x ./test_her2_blis.x ./test_her_blis.x ./test_herk_blis.x ./test_hpr2_blis.x ./test_hpr_blis.x ./test_nrm2_blis.x ./test_rot_blis.x ./test_rotg_blis.x ./test_rotm_blis.x ./test_rotmg_blis.x ./test_scal_blis.x ./test_sdsdot_blis.x ./test_spr2_blis.x ./test_spr_blis.x ./test_swap_blis.x ./test_symm_blis.x ./test_syr2_blis.x ./test_syr2k_blis.x ./test_syr_blis.x ./test_syrk_blis.x ./test_tbmv_blis.x ./test_tbsv_blis.x ./test_tpmv_blis.x ./test_tpsv_blis.x ./test_trmm_blis.x ./test_trsm_blis.x ./test_trsv_blis.x blis-0.9.0/vendor/testcpp/test_asum.cc000066400000000000000000000072151422157504600177560ustar00rootroot00000000000000/* BLISPP C++ test driver for BLIS CPP asum routine and reference blis asum routine. Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include #include #include "blis.hh" #include "test.hh" using namespace blis; using namespace std; //#define PRINT #define N 6 #define ALPHA 0.5 template< typename T, typename TR> void ref_asum(int64_t n, T *X, TR *asum ) { obj_t obj_x; obj_t obj_asum; num_t dt, dtR; if(is_same::value) dt = BLIS_FLOAT; else if(is_same::value) dt = BLIS_DOUBLE; else if(is_same>::value) dt = BLIS_SCOMPLEX; else if(is_same>::value) dt = BLIS_DCOMPLEX; if(is_same::value) dtR = BLIS_FLOAT; else if(is_same::value) dtR = BLIS_DOUBLE; bli_obj_create_with_attached_buffer( dt, n, 1, X, 1, n,&obj_x ); bli_obj_create_with_attached_buffer( dtR, 1, 1, asum, 1, 1,&obj_asum ); bli_asumv(&obj_x, &obj_asum); } template< typename T, typename TR> void test_asum() { T *X, *X_ref; TR asum, asum_ref; int n; int incx; n = N; incx = 1; srand (time(NULL)); allocate_init_buffer(X , n , 1); copy_buffer(X, X_ref , n ,1); #ifdef PRINT printvector(X, n,(char *) "X"); #endif asum = blis::asum( n, X, incx ); #ifdef PRINT cout<< "Sum of all values in Vector X: " << asum << "\n"; #endif ref_asum(n, X_ref, &asum_ref ); #ifdef PRINT cout<< "Ref Sum of all values in Vector X: " << asum_ref << "\n"; #endif if(computeErrorV(incx, incx, 1, &asum, &asum_ref )==1) printf("%s TEST FAIL\n" , __PRETTY_FUNCTION__); else printf("%s TEST PASS\n" , __PRETTY_FUNCTION__); delete[]( X ); delete[]( X_ref ); } // ----------------------------------------------------------------------------- int main( int argc, char** argv ) { test_asum( ); test_asum( ); test_asum, float>( ); test_asum, double>( ); return 0; } blis-0.9.0/vendor/testcpp/test_axpy.cc000066400000000000000000000072601422157504600177720ustar00rootroot00000000000000/* BLISPP C++ test driver for BLIS CPP gemm routine and reference blis gemm routine. Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include #include #include "blis.hh" #include "test.hh" using namespace blis; using namespace std; //#define PRINT #define N 6 #define ALPHA 1.0 /* * Test application assumes matrices to be column major, non-transposed */ template< typename T> void ref_axpy(int64_t n, T * alpha, T *X, T *Y ) { obj_t obj_x, obj_y, obj_alpha; num_t dt; if(is_same::value) dt = BLIS_FLOAT; else if(is_same::value) dt = BLIS_DOUBLE; else if(is_same>::value) dt = BLIS_SCOMPLEX; else if(is_same>::value) dt = BLIS_DCOMPLEX; bli_obj_create_with_attached_buffer( dt, 1, 1, alpha, 1,1,&obj_alpha ); bli_obj_create_with_attached_buffer( dt, n, 1, X, 1, n,&obj_x ); bli_obj_create_with_attached_buffer( dt, n, 1, Y, 1, n,&obj_y ); bli_axpyv( &obj_alpha, &obj_x, &obj_y ); } template< typename T > void test_axpy( ) { T *X, *Y,*Y_ref; T alpha = ALPHA; int n; int incx, incy; n = N; incx = 1; incy = 1; srand (time(NULL)); allocate_init_buffer(X , n , 1); allocate_init_buffer(Y , n , 1); copy_buffer(Y, Y_ref , n ,1); #ifdef PRINT printvector(X, n,(char *) "X"); printvector(Y, n, (char *) "Y"); #endif blis::axpy( n, alpha, X, incx, Y, incy ); #ifdef PRINT printvector(Y, n,(char *) "Y output"); #endif ref_axpy(n , &alpha , X, Y_ref ); #ifdef PRINT printvector(Y_ref, n, (char *) "Y ref output"); #endif if(computeErrorV(incy, incy , n, Y, Y_ref )==1) printf("%s TEST FAIL\n" , __PRETTY_FUNCTION__); else printf("%s TEST PASS\n" , __PRETTY_FUNCTION__); delete[]( X ); delete[]( Y ); delete[]( Y_ref ); } // ----------------------------------------------------------------------------- int main( int argc, char** argv ) { test_axpy( ); test_axpy( ); test_axpy>( ); test_axpy>( ); return 0; } blis-0.9.0/vendor/testcpp/test_copy.cc000066400000000000000000000070041422157504600177570ustar00rootroot00000000000000/* BLISPP C++ test driver for BLIS CPP gemm routine and reference blis gemm routine. Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include #include #include "blis.hh" #include "test.hh" using namespace blis; using namespace std; //#define PRINT #define N 6 /* * Test application assumes matrices to be column major, non-transposed */ template< typename T> void ref_copy(int64_t n, T *X, T *Y ) { obj_t obj_x, obj_y; num_t dt; if(is_same::value) dt = BLIS_FLOAT; else if(is_same::value) dt = BLIS_DOUBLE; else if(is_same>::value) dt = BLIS_SCOMPLEX; else if(is_same>::value) dt = BLIS_DCOMPLEX; bli_obj_create_with_attached_buffer( dt, n, 1, X, 1, n,&obj_x ); bli_obj_create_with_attached_buffer( dt, n, 1, Y, 1, n,&obj_y ); bli_copyv( &obj_x, &obj_y ); } template< typename T > void test_copy( ) { T *X, *X_ref, *Y,*Y_ref; int n; int incx, incy; n = N; incx = 1; incy = 1; Y = new T[n]; Y_ref = new T[n]; srand (time(NULL)); allocate_init_buffer(X , n , 1); copy_buffer(X, X_ref , n ,1); #ifdef PRINT printvector(X, n,(char *) "X"); #endif blis::copy( n, X, incx, Y, incy ); #ifdef PRINT printvector(Y, n,(char *) "Y output"); #endif ref_copy(n , X_ref, Y_ref ); #ifdef PRINT printvector(Y_ref, n,(char *) "Y ref output"); #endif if(computeErrorV(incy , incy , n, Y, Y_ref )==1) printf("%s TEST FAIL\n" , __PRETTY_FUNCTION__); else printf("%s TEST PASS\n" , __PRETTY_FUNCTION__); delete[]( X ); delete[]( X_ref ); delete[]( Y ); delete[]( Y_ref ); } // ----------------------------------------------------------------------------- int main( int argc, char** argv ) { test_copy( ); test_copy( ); test_copy>(); test_copy>(); return 0; } blis-0.9.0/vendor/testcpp/test_dot.cc000066400000000000000000000067361422157504600176060ustar00rootroot00000000000000/* BLISPP C++ test driver for BLIS CPP gemm routine and reference blis gemm routine. Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include #include #include "blis.hh" #include "test.hh" using namespace blis; using namespace std; //#define PRINT #define N 6 /* * Test application assumes matrices to be column major, non-transposed */ template< typename T, typename TR> void ref_dot(int64_t n, T *X, T *Y, TR *res_ref ) { obj_t obj_x; obj_t obj_y; obj_t obj_res; num_t dt; if(is_same::value) dt = BLIS_FLOAT; else if(is_same::value) dt = BLIS_DOUBLE; bli_obj_create_with_attached_buffer( dt, n, 1, X, 1, n,&obj_x ); bli_obj_create_with_attached_buffer( dt, n, 1, Y, 1, n,&obj_y ); bli_obj_create_with_attached_buffer( dt, 1, 1, res_ref, 1, 1,&obj_res ); bli_dotv(&obj_x, &obj_y, &obj_res ); } template< typename T, typename TR> void test_dot() { T *X, *Y; int n; int incx, incy; TR res = 0, res_ref = 0; n = N; incx = 1; incy = 1; srand (time(NULL)); allocate_init_buffer(X , n , 1); allocate_init_buffer(Y , n , 1); #ifdef PRINT printvector(X, n, (char *)"X"); printvector(Y, n, (char *)"Y"); #endif res = blis::dot( n, X, incx, Y, incy ); #ifdef PRINT printf("Dot product = %E \n", res); #endif ref_dot(n, X, Y , &res_ref ); #ifdef PRINT printf("Dot product ref_dot %E \n", res_ref); #endif if(res != res_ref ) printf("%s TEST FAIL\n" ,__PRETTY_FUNCTION__); else printf("%s TEST PASS\n" , __PRETTY_FUNCTION__); delete[]( X ); delete[]( Y ); } // ----------------------------------------------------------------------------- int main( int argc, char** argv ) { test_dot( ); //test_dot( ); test_dot( ); return 0; } blis-0.9.0/vendor/testcpp/test_dotc.cc000066400000000000000000000067171422157504600177500ustar00rootroot00000000000000/* BLISPP C++ test driver for BLIS CPP dotc routine and reference blis dotc routine. Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include #include #include "blis.hh" #include "test.hh" using namespace blis; using namespace std; //#define PRINT #define N 16 template< typename T > void ref_dotc(int64_t n, T *X, T *Y, T *res_ref ) { obj_t obj_x; obj_t obj_y; obj_t obj_res; num_t dt; if(is_same>::value) dt = BLIS_SCOMPLEX; else if(is_same>::value) dt = BLIS_DCOMPLEX; bli_obj_create_with_attached_buffer( dt, n, 1, X, 1, n, &obj_x ); bli_obj_create_with_attached_buffer( dt, n, 1, Y, 1, n, &obj_y ); bli_obj_set_conj(BLIS_CONJUGATE,&obj_x); bli_obj_create_with_attached_buffer( dt, 1, 1, res_ref, 1, 1,&obj_res ); bli_dotv(&obj_x, &obj_y, &obj_res ); } template< typename T > void test_dotc() { T *X, *Y; int n; int incx, incy; T res = 0, res_ref = 0; n = N; incx = 1; incy = 1; srand (time(NULL)); allocate_init_buffer(X , n , 1); allocate_init_buffer(Y , n , 1); #ifdef PRINT printvector(X, n,(char *) "X"); printvector(Y, n,(char *) "Y"); #endif res = blis::dotc( n, X, incx, Y, incy ); #ifdef PRINT cout<< "Dot product \n" << res << "\n"; #endif ref_dotc(n, X, Y , &res_ref ); #ifdef PRINT cout<< "Dot product ref\n" << res_ref << "\n";; #endif if(res != res_ref ) printf("%s TEST FAIL\n" ,__PRETTY_FUNCTION__); else printf("%s TEST PASS\n" , __PRETTY_FUNCTION__); delete[]( X ); delete[]( Y ); } // ----------------------------------------------------------------------------- int main( int argc, char** argv ) { test_dotc>( ); test_dotc>( ); return 0; } blis-0.9.0/vendor/testcpp/test_gbmv.cc000066400000000000000000000063211422157504600177410ustar00rootroot00000000000000/* BLISPP C++ test driver for BLIS CPP gemm routine and reference blis gemm routine. Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include #include #include "blis.hh" #include "test.hh" using namespace blis; using namespace std; //#define PRINT #define ALPHA -1.0 #define BETA -1.0 #define M 3 #define N 4 template< typename T > void test_gbmv( ) { // int i, j, p; T alpha, beta; int m,n; int KL = 1; int KU = 1; int lda = 4; T A[] = { 0.423f, -0.143f, -0.182f, -0.076f, -0.855f, 0.599f, 0.389f, -0.473f, 0.493f, -0.902f, -0.889f, -0.256f, 0.112f, 0.128f, -0.277f, -0.777f }; T X[] = { 0.488f, 0.029f, -0.633f, 0.84f }; int incX = -1; T Y[] = { 0.874f, 0.322f, -0.477f }; int incY = -1; T Y_ref[] = { -0.656261f, 0.19575f, 0.055905f }; alpha = ALPHA; beta = BETA; m = M; n = N; #ifdef PRINT printmatrix(A, lda ,m,n,(char *) "A"); printvector(Y, m, (char *)"m"); #endif blis::gbmv( CblasColMajor, CblasNoTrans, m, n,KL,KU, alpha, A, lda, X, incX, beta, Y, incY ); #ifdef PRINT printvector(Y, m,(char *)"Y blis:gbmv"); printvector(Y_ref, m, (char *) "Y_ref blis:gbmv" ); #endif if(computeErrorV(incY,incY, m, Y, Y_ref )==1) printf("%s TEST FAIL\n" , __PRETTY_FUNCTION__ ); else printf("%s TEST PASS\n" , __PRETTY_FUNCTION__ ); } // ----------------------------------------------------------------------------- int main( int argc, char** argv ) { test_gbmv( ); test_gbmv( ); test_gbmv>( ); test_gbmv>( ); return 0; } blis-0.9.0/vendor/testcpp/test_gemm.cc000066400000000000000000000107331422157504600177350ustar00rootroot00000000000000/* BLISPP C++ test driver for BLIS CPP gemm routine and reference blis gemm routine. Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include #include #include "blis.hh" #include "test.hh" using namespace blis; using namespace std; //#define PRINT #define ALPHA 1.0 #define BETA 0.0 #define M 5 #define N 6 #define K 4 /* * Test application assumes matrices to be column major, non-transposed */ template< typename T > void ref_gemm(int64_t m, int64_t n, int64_t k, T * alpha, T *A, T *B, T * beta, T *C ) { obj_t obj_a, obj_b, obj_c; obj_t obj_alpha, obj_beta; num_t dt; if(is_same::value) dt = BLIS_FLOAT; else if(is_same::value) dt = BLIS_DOUBLE; else if(is_same>::value) dt = BLIS_SCOMPLEX; else if(is_same>::value) dt = BLIS_DCOMPLEX; bli_obj_create_with_attached_buffer( dt, 1, 1, alpha, 1,1,&obj_alpha ); bli_obj_create_with_attached_buffer( dt, 1, 1, beta, 1,1,&obj_beta ); bli_obj_create_with_attached_buffer( dt, m, k, A, 1,m,&obj_a ); bli_obj_create_with_attached_buffer( dt, k, n, B,1,k,&obj_b ); bli_obj_create_with_attached_buffer( dt, m, n, C, 1,m,&obj_c ); bli_obj_set_conjtrans( BLIS_NO_TRANSPOSE, &obj_a ); bli_obj_set_conjtrans( BLIS_NO_TRANSPOSE, &obj_b ); bli_gemm( &obj_alpha, &obj_a, &obj_b, &obj_beta, &obj_c ); } template< typename T > void test_gemm( ) { T *A, *B, *C, *C_ref; T alpha, beta; int m,n,k; int lda, ldb, ldc, ldc_ref; alpha = ALPHA; beta = BETA; m = M; k = K; n = N; lda = m; ldb = k; ldc = m; ldc_ref = m; srand (time(NULL)); allocate_init_buffer(A , m , k); allocate_init_buffer(B , k , n); allocate_init_buffer(C , m , n); copy_buffer(C, C_ref , m ,n); #ifdef PRINT printmatrix(A, lda ,m,k , (char *)"A"); printmatrix(B, ldb ,k,n, (char *)"B"); printmatrix(C, ldc ,m,n, (char *)"C"); #endif blis::gemm( CblasColMajor, CblasNoTrans, CblasNoTrans, m, n, k, alpha, A, lda, B, ldb, beta, C, ldc ); #ifdef PRINT printmatrix(C,ldc ,m,n , (char *)"C output"); #endif ref_gemm(m, n, k, &alpha, A, B, &beta, C_ref); #ifdef PRINT printmatrix(C_ref, ldc_ref ,m,n, (char *)"C ref output"); #endif if(computeErrorM(ldc, ldc_ref, m, n, C, C_ref )==1) printf("%s TEST FAIL\n" , __PRETTY_FUNCTION__ ); else printf("%s TEST PASS\n" , __PRETTY_FUNCTION__ ); delete[]( A ); delete[]( B ); delete[]( C ); delete[]( C_ref ); } // ----------------------------------------------------------------------------- int main( int argc, char** argv ) { test_gemm( ); test_gemm( ); test_gemm>( ); test_gemm>( ); return 0; } blis-0.9.0/vendor/testcpp/test_gemm.hh000066400000000000000000000057651422157504600177600ustar00rootroot00000000000000/* * -------------------------------------------------------------------------- * BLISLAB * -------------------------------------------------------------------------- * Copyright (C) 2016, The University of Texas at Austin * * 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 The University of Texas 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 COPYRIGHT * HOLDER 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. * * * test_gemm.hh * * * Purpose: * this header file contains all function prototypes. * * Todo: * * * Modification: * * * */ #ifndef TEST_GEMM_HH #define TEST_GEMM_HH #include #include #include using namespace std; #define min( i, j ) ( (i)<(j) ? (i): (j) ) #define A( i, j ) A[ (j)*lda + (i) ] #define B( i, j ) B[ (j)*ldb + (i) ] #define C( i, j ) C[ (j)*ldc + (i) ] #define C_ref( i, j ) C_ref[ (j)*ldc_ref + (i) ] template< typename T > int computeError( int ldc, int ldc_ref, int m, int n, T *C, T *C_ref ) { int i, j; int ret = 0; for ( i = 0; i < m; i ++ ) { for ( j = 0; j < n; j ++ ) { if ( C( i, j ) != C_ref( i, j ) ) { printf( "C[ %d ][ %d ] != C_ref, %E, %E\n", i, j, C( i, j ), C_ref( i, j ) ); ret = 1; break; } } } return ret; } /* * * */ template void bl_dgemm_printmatrix( T *A, int lda, int m, int n ) { int i, j; for ( i = 0; i < m; i ++ ) { for ( j = 0; j < n; j ++ ) { cout<< A[j * lda + i]<<" "; } printf("\n"); } printf("\n"); } #endif blis-0.9.0/vendor/testcpp/test_gemv.cc000066400000000000000000000106401422157504600177430ustar00rootroot00000000000000/* BLISPP C++ test driver for BLIS CPP gemm routine and reference blis gemm routine. Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include #include #include "blis.hh" #include "test.hh" using namespace blis; using namespace std; //#define PRINT #define ALPHA 1.0 #define BETA 0.0 #define M 5 #define N 6 /* * Test application assumes matrices to be column major, non-transposed */ template< typename T > void ref_gemv(int64_t m, int64_t n, T * alpha, T *A, T *X, T * beta, T *Y ) { obj_t obj_a, obj_x, obj_y; obj_t obj_alpha, obj_beta; num_t dt; if(is_same::value) dt = BLIS_FLOAT; else if(is_same::value) dt = BLIS_DOUBLE; else if(is_same>::value) dt = BLIS_SCOMPLEX; else if(is_same>::value) dt = BLIS_DCOMPLEX; bli_obj_create_with_attached_buffer( dt, 1, 1, alpha, 1,1,&obj_alpha ); bli_obj_create_with_attached_buffer( dt, 1, 1, beta, 1,1,&obj_beta ); bli_obj_create_with_attached_buffer( dt, m, n, A, 1,m,&obj_a ); bli_obj_create_with_attached_buffer( dt, n, 1, X, 1,n,&obj_x ); bli_obj_create_with_attached_buffer( dt, m, 1, Y, 1,m,&obj_y ); bli_obj_set_conjtrans( BLIS_NO_TRANSPOSE, &obj_a ); bli_obj_set_conjtrans( BLIS_NO_TRANSPOSE, &obj_x); bli_obj_set_conjtrans( BLIS_NO_TRANSPOSE, &obj_y); bli_gemv( &obj_alpha, &obj_a, &obj_x, &obj_beta, &obj_y ); } template< typename T > void test_gemv( ) { T *A, *Y, *Y_ref, *X; T alpha, beta; int m,n; int lda, incx, incy, incy_ref; alpha = ALPHA; beta = BETA; m = M; n = N; lda = m; incx = 1; incy = 1; incy_ref = 1; srand (time(NULL)); allocate_init_buffer(A , m , n); allocate_init_buffer(X , m , 1); allocate_init_buffer(Y , m , 1); copy_buffer(Y, Y_ref , m ,1); #ifdef PRINT printmatrix(A, lda ,m,n,(char *) "A"); printvector(X, m,(char *) "X"); printvector(Y, m, (char *)"Y"); #endif blis::gemv( CblasColMajor, CblasNoTrans, m, n, alpha, A, lda, X, incx, beta, Y, incy ); #ifdef PRINT printvector(Y, m, (char *)"Y output"); #endif ref_gemv(m, n, &alpha, A, X, &beta, Y_ref); #ifdef PRINT printvector(Y_ref, m, (char *) "Y_Ref output"); #endif if(computeErrorV(incy,incy_ref, m , Y, Y_ref )==1) printf("%s TEST FAIL\n" , __PRETTY_FUNCTION__ ); else printf("%s TEST PASS\n" , __PRETTY_FUNCTION__ ); delete[]( A ); delete[]( X ); delete[]( Y ); delete[]( Y_ref ); } // ----------------------------------------------------------------------------- int main( int argc, char** argv ) { test_gemv( ); test_gemv( ); test_gemv>( ); test_gemv>( ); return 0; } blis-0.9.0/vendor/testcpp/test_ger.cc000066400000000000000000000077621422157504600175750ustar00rootroot00000000000000/* BLISPP C++ test driver for BLIS CPP gemm routine and reference blis gemm routine. Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include #include #include "blis.hh" #include "test.hh" using namespace blis; using namespace std; //#define PRINT #define ALPHA 1.0 #define M 5 #define N 6 /* * Test application assumes matrices to be column major, non-transposed */ template< typename T > void ref_ger(int64_t m, int64_t n, T * alpha, T *X, T *Y, T *A ) { obj_t obj_a; obj_t obj_x; obj_t obj_y; obj_t obj_alpha; num_t dt; if(is_same::value) dt = BLIS_FLOAT; else if(is_same::value) dt = BLIS_DOUBLE; bli_obj_create_with_attached_buffer( dt, 1, 1, alpha, 1,1,&obj_alpha ); bli_obj_create_with_attached_buffer( dt, m, n, A, 1, m, &obj_a ); bli_obj_create_with_attached_buffer( dt, m, 1, X, 1, m,&obj_x ); bli_obj_create_with_attached_buffer( dt, n, 1, Y, 1, n,&obj_y ); //bli_obj_set_struc( BLIS_HERMITIAN, &obj_a ); //bli_obj_set_uplo( BLIS_LOWER, &obj_a); bli_ger( &obj_alpha, &obj_x, &obj_y, &obj_a ); } template< typename T > void test_ger( ) { T *A, *X, *Y, *A_ref; T alpha; int m,n; int lda, incx, incy, lda_ref; alpha = ALPHA; m = M; n = N; lda = m; lda_ref = m; incx = 1; incy = 1; srand (time(NULL)); allocate_init_buffer(A , m , n); allocate_init_buffer(X , m , 1); allocate_init_buffer(Y , n , 1); copy_buffer(A, A_ref , m ,n); #ifdef PRINT printmatrix(A, lda ,m,n,(char *) "A"); printvector(X, m,(char *) "X"); printvector(Y, n,(char *) "Y"); #endif blis::ger( CblasColMajor, m, n, alpha, X, incx, Y, incy, A, lda ); #ifdef PRINT printmatrix(A, lda , m ,n ,(char *) "A output"); #endif ref_ger(m, n, &alpha, X, Y, A_ref); #ifdef PRINT printmatrix(A_ref, lda ,m,n, (char *)"A_ref output"); #endif if(computeErrorM(lda, lda_ref, m, n, A, A_ref )==1) printf("%s TEST FAIL\n" ,__PRETTY_FUNCTION__); else printf("%s TEST PASS\n" , __PRETTY_FUNCTION__); delete[]( A ); delete[]( X ); delete[]( Y ); delete[]( A_ref ); } // ----------------------------------------------------------------------------- int main( int argc, char** argv ) { test_ger( ); test_ger( ); return 0; } blis-0.9.0/vendor/testcpp/test_gerc.cc000066400000000000000000000106751422157504600177350ustar00rootroot00000000000000/* BLISPP C++ test driver for BLIS CPP gemm routine and reference blis gemm routine. Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include #include #include "blis.hh" #include "test.hh" using namespace blis; using namespace std; //#define PRINT #define ALPHA 1.0 #define M 5 #define N 6 /* * Test application assumes matrices to be column major, non-transposed */ template< typename T > void ref_gerc(int64_t m, int64_t n, T * alpha, T *X, T *Y, T *A ) { obj_t obj_a; obj_t obj_x; obj_t obj_y; obj_t obj_alpha; num_t dt; if(is_same::value) dt = BLIS_FLOAT; else if(is_same::value) dt = BLIS_DOUBLE; else if(is_same>::value) dt = BLIS_SCOMPLEX; else if(is_same>::value) dt = BLIS_DCOMPLEX; if(dt == BLIS_FLOAT){ bli_obj_create_with_attached_buffer( BLIS_FLOAT, 1, 1, alpha, 1,1,&obj_alpha ); } else if(dt == BLIS_DOUBLE){ bli_obj_create_with_attached_buffer( BLIS_DOUBLE, 1, 1, alpha, 1,1,&obj_alpha ); } if(dt == BLIS_SCOMPLEX){ bli_obj_create_with_attached_buffer( BLIS_SCOMPLEX, 1, 1, alpha, 1,1,&obj_alpha ); } else if(dt == BLIS_DCOMPLEX){ bli_obj_create_with_attached_buffer( BLIS_DCOMPLEX, 1, 1, alpha, 1,1,&obj_alpha ); } bli_obj_create_with_attached_buffer( dt, m, n, A, 1, m, &obj_a ); bli_obj_create_with_attached_buffer( dt, m, 1, X, 1, m,&obj_x ); bli_obj_create_with_attached_buffer( dt, n, 1, Y, 1, n,&obj_y ); bli_obj_set_conj(BLIS_CONJUGATE,&obj_y); bli_ger( &obj_alpha, &obj_x, &obj_y, &obj_a ); } template< typename T > void test_gerc( ) { T *A, *X, *Y, *A_ref; T alpha; int m,n; int lda, incx, incy, lda_ref; alpha = ALPHA; m = M; n = N; lda = m; lda_ref = m; incx = 1; incy = 1; srand (time(NULL)); allocate_init_buffer(A , m , n); allocate_init_buffer(X , m , 1); allocate_init_buffer(Y , n , 1); copy_buffer(A, A_ref , m ,n); #ifdef PRINT printmatrix(A, lda ,m,n,(char *)"A"); printvector(X, m, (char *)"X"); #endif blis::gerc( CblasColMajor, m, n, alpha, X, incx, Y, incy, A, lda ); #ifdef PRINT printmatrix (A, lda ,m , n,(char *)"A blis::gerc\n"); #endif ref_gerc(m, n, &alpha, X, Y, A_ref); #ifdef PRINT printmatrix(A_ref, lda_ref, m, n, (char *)"A_ref output\n"); #endif if(computeErrorM(lda, lda_ref, m, n, A, A_ref )==1) printf("%s TEST FAIL\n" ,__PRETTY_FUNCTION__); else printf("%s TEST PASS\n" , __PRETTY_FUNCTION__); delete[]( A ); delete[]( X ); delete[]( Y ); delete[]( A_ref ); } // ----------------------------------------------------------------------------- int main( int argc, char** argv ) { test_gerc>( ); test_gerc>( ); return 0; } blis-0.9.0/vendor/testcpp/test_geru.cc000066400000000000000000000105451422157504600177530ustar00rootroot00000000000000/* BLISPP C++ test driver for BLIS CPP gemm routine and reference blis gemm routine. Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include #include #include "blis.hh" #include "test.hh" using namespace blis; using namespace std; //#define PRINT #define ALPHA 1.0 #define M 5 #define N 6 /* * Test application assumes matrices to be column major, non-transposed */ template< typename T > void ref_geru(int64_t m, int64_t n, T * alpha, T *X, T *Y, T *A ) { obj_t obj_a; obj_t obj_x; obj_t obj_y; obj_t obj_alpha; num_t dt; if(is_same::value) dt = BLIS_FLOAT; else if(is_same::value) dt = BLIS_DOUBLE; else if(is_same>::value) dt = BLIS_SCOMPLEX; else if(is_same>::value) dt = BLIS_DCOMPLEX; if(dt == BLIS_FLOAT){ bli_obj_create_with_attached_buffer( BLIS_FLOAT, 1, 1, alpha, 1,1,&obj_alpha ); } else if(dt == BLIS_DOUBLE){ bli_obj_create_with_attached_buffer( BLIS_DOUBLE, 1, 1, alpha, 1,1,&obj_alpha ); } if(dt == BLIS_SCOMPLEX){ bli_obj_create_with_attached_buffer( BLIS_SCOMPLEX, 1, 1, alpha, 1,1,&obj_alpha ); } else if(dt == BLIS_DCOMPLEX){ bli_obj_create_with_attached_buffer( BLIS_DCOMPLEX, 1, 1, alpha, 1,1,&obj_alpha ); } bli_obj_create_with_attached_buffer( dt, m, n, A, 1, m, &obj_a ); bli_obj_create_with_attached_buffer( dt, m, 1, X, 1, m,&obj_x ); bli_obj_create_with_attached_buffer( dt, n, 1, Y, 1, n,&obj_y ); bli_ger( &obj_alpha, &obj_x, &obj_y, &obj_a ); } template< typename T > void test_geru( ) { T *A, *X, *Y, *A_ref; T alpha; int m,n; int lda, incx, incy, lda_ref; alpha = ALPHA; m = M; n = N; lda = m; lda_ref = m; incx = 1; incy = 1; srand (time(NULL)); allocate_init_buffer(A , m , n); allocate_init_buffer(X , m , 1); allocate_init_buffer(Y , n , 1); copy_buffer(A, A_ref , m ,n); #ifdef PRINT printmatrix(A, lda ,m,n,(char *)"A"); printvector(X, m,(char *) "X"); #endif blis::geru( CblasColMajor, m, n, alpha, X, incx, Y, incy, A, lda ); #ifdef PRINT printmatrix (A, lda ,m,n,(char *)"A output"); printvector (X, m,(char *) "X"); #endif ref_geru(m, n, &alpha, X, Y, A_ref); #ifdef PRINT printmatrix(A_ref, lda_ref, m,n,(char *)"A_ref output" ); #endif if(computeErrorM(lda, lda_ref, m, n, A, A_ref )==1) printf("%s TEST FAIL\n" ,__PRETTY_FUNCTION__); else printf("%s TEST PASS\n" , __PRETTY_FUNCTION__); delete[]( A ); delete[]( X ); delete[]( Y ); delete[]( A_ref ); } // ----------------------------------------------------------------------------- int main( int argc, char** argv ) { test_geru>( ); test_geru>( ); return 0; } blis-0.9.0/vendor/testcpp/test_hemm.cc000066400000000000000000000106551422157504600177410ustar00rootroot00000000000000/* BLISPP C++ test driver for BLIS CPP gemm routine and reference blis gemm routine. Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include #include #include "blis.hh" #include "test.hh" using namespace blis; using namespace std; //#define PRINT #define ALPHA 1.0 #define BETA 0.0 #define M 5 #define N 5 /* * Test application assumes matrices to be column major, non-transposed */ template< typename T > void ref_hemm(int64_t m, int64_t n, T * alpha, T *A, T *B, T * beta, T *C ) { obj_t obj_a, obj_b, obj_c; obj_t obj_alpha, obj_beta; num_t dt; if(is_same::value) dt = BLIS_FLOAT; else if(is_same::value) dt = BLIS_DOUBLE; else if(is_same>::value) dt = BLIS_SCOMPLEX; else if(is_same>::value) dt = BLIS_DCOMPLEX; bli_obj_create_with_attached_buffer( dt, 1, 1, alpha, 1,1,&obj_alpha ); bli_obj_create_with_attached_buffer( dt, 1, 1, beta, 1,1,&obj_beta ); bli_obj_create_with_attached_buffer( dt, m, m, A, 1,m,&obj_a ); bli_obj_create_with_attached_buffer( dt, m, n, B, 1,n,&obj_b ); bli_obj_create_with_attached_buffer( dt, m, n, C, 1,m,&obj_c ); bli_obj_set_struc( BLIS_HERMITIAN, &obj_a ); bli_obj_set_uplo( BLIS_LOWER, &obj_a ); bli_mkherm(&obj_a); bli_mktrim(&obj_a); bli_hemm( BLIS_LEFT, &obj_alpha, &obj_a, &obj_b, &obj_beta, &obj_c ); } template< typename T > void test_hemm( ) { T *A, *B, *C, *C_ref; T alpha, beta; int m,n; int lda, ldb, ldc, ldc_ref; alpha = ALPHA; beta = BETA; m = M; n = N; lda = m; ldb = n; ldc = m; ldc_ref = m; srand48 (time(NULL)); srand (time(NULL)); allocate_init_buffer(A , m , m); allocate_init_buffer(B , m , n); allocate_init_buffer(C , m , n); copy_buffer(C, C_ref , m ,n); #ifdef PRINT printmatrix(A, lda ,m,m,(char *) "A"); printmatrix(B, ldb ,m,n,(char *) "B"); printmatrix(C, ldc ,m,n,(char *) "C"); #endif blis::hemm( CblasColMajor, CblasLeft, CblasLower, m, n, alpha, A, lda, B, ldb, beta, C, ldc ); #ifdef PRINT printmatrix(C, ldc ,m,n,(char *) "C output"); #endif ref_hemm(m, n, &alpha, A, B, &beta, C_ref); #ifdef PRINT printmatrix(C_ref, ldc_ref ,m,n,(char *) "C ref output"); #endif if(computeErrorM(ldc, ldc_ref, m, n, C, C_ref )==1) printf("%s TEST FAIL\n" , __PRETTY_FUNCTION__ ); else printf("%s TEST PASS\n" , __PRETTY_FUNCTION__ ); delete[]( A ); delete[]( B ); delete[]( C ); delete[]( C_ref ); } // ----------------------------------------------------------------------------- int main( int argc, char** argv ) { test_hemm>( ); test_hemm>( ); return 0; } blis-0.9.0/vendor/testcpp/test_hemv.cc000066400000000000000000000103741422157504600177500ustar00rootroot00000000000000/* BLISPP C++ test driver for BLIS CPP gemm routine and reference blis gemm routine. Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include #include #include "blis.hh" #include "test.hh" using namespace blis; using namespace std; //#define PRINT #define ALPHA 1.0 #define BETA 0.0 #define N 6 /* * Test application assumes matrices to be column major, non-transposed */ template< typename T > void ref_hemv(int64_t n, T * alpha, T *A, T *X, T * beta, T *Y ) { obj_t obj_a, obj_x, obj_y; obj_t obj_alpha, obj_beta; num_t dt; if(is_same::value) dt = BLIS_FLOAT; else if(is_same::value) dt = BLIS_DOUBLE; else if(is_same>::value) dt = BLIS_SCOMPLEX; else if(is_same>::value) dt = BLIS_DCOMPLEX; bli_obj_create_with_attached_buffer( dt, 1, 1, alpha, 1,1,&obj_alpha ); bli_obj_create_with_attached_buffer( dt, 1, 1, beta, 1,1,&obj_beta ); bli_obj_create_with_attached_buffer( dt, n, n, A, 1,n,&obj_a ); bli_obj_create_with_attached_buffer( dt, n, 1, X, 1,n,&obj_x ); bli_obj_create_with_attached_buffer( dt, n, 1, Y, 1,n,&obj_y ); bli_obj_set_struc( BLIS_HERMITIAN, &obj_a ); bli_obj_set_uplo( BLIS_LOWER, &obj_a ); bli_hemv( &obj_alpha, &obj_a, &obj_x, &obj_beta, &obj_y ); } template< typename T > void test_hemv( ) { T *A, *Y, *Y_ref, *X; T alpha, beta; int n; int lda, incx, incy, incy_ref; alpha = ALPHA; beta = BETA; n = N; lda = n; incx = 1; incy = 1; incy_ref = 1; srand (time(NULL)); allocate_init_buffer(A , n , n); allocate_init_buffer(X , n , 1); allocate_init_buffer(Y , n , 1); copy_buffer(Y, Y_ref , n ,1); #ifdef PRINT printmatrix(A, lda ,n,n, (char *)"A"); printvector(X, n, (char *)"X"); printvector(Y, n, (char *)"Y"); #endif blis::hemv( CblasColMajor, CblasLower, n, alpha, A, lda, X, incx, beta, Y, incy ); #ifdef PRINT printvector(Y, n, (char *)"Y output"); #endif ref_hemv(n, &alpha, A, X, &beta, Y_ref); #ifdef PRINT printvector(Y_ref, n,(char *) "Y_ref output"); #endif if(computeErrorV(incy,incy_ref, n, Y, Y_ref )==1) printf("%s TEST FAIL\n" , __PRETTY_FUNCTION__ ); else printf("%s TEST PASS\n" , __PRETTY_FUNCTION__ ); delete[]( A ); delete[]( X ); delete[]( Y ); delete[]( Y_ref ); } // ----------------------------------------------------------------------------- int main( int argc, char** argv ) { test_hemv>( ); test_hemv>( ); return 0; } blis-0.9.0/vendor/testcpp/test_her.cc000066400000000000000000000076571422157504600176010ustar00rootroot00000000000000/* BLISPP C++ test driver for BLIS CPP gemm routine and reference blis gemm routine. Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include #include #include "blis.hh" #include "test.hh" using namespace blis; using namespace std; //#define PRINT #define ALPHA 1.0 #define N 6 /* * Test application assumes matrices to be column major, non-transposed */ template< typename T > void ref_her(int64_t n, real_type * alpha, T *X, T *A ) { obj_t obj_a; obj_t obj_x; obj_t obj_alpha; num_t dt; if(is_same>::value) dt = BLIS_SCOMPLEX; else if(is_same>::value) dt = BLIS_DCOMPLEX; if(dt == BLIS_SCOMPLEX){ bli_obj_create_with_attached_buffer( BLIS_FLOAT, 1, 1, alpha, 1,1,&obj_alpha ); } else if(dt == BLIS_DCOMPLEX){ bli_obj_create_with_attached_buffer( BLIS_DOUBLE, 1, 1, alpha, 1,1,&obj_alpha ); } bli_obj_create_with_attached_buffer( dt, n, n, A, 1, n, &obj_a ); bli_obj_create_with_attached_buffer( dt, n, 1, X, 1, n,&obj_x ); bli_obj_set_struc( BLIS_HERMITIAN, &obj_a ); bli_obj_set_uplo( BLIS_LOWER, &obj_a); bli_her( &obj_alpha, &obj_x, &obj_a ); } template< typename T > void test_her( ) { T *A, *X, *A_ref; real_type alpha; int n; int lda, incx, lda_ref; alpha = ALPHA; n = N; lda = n; lda_ref = n; incx = 1; srand (time(NULL)); allocate_init_buffer(A , n , n); allocate_init_buffer(X , n , 1); copy_buffer(A, A_ref , n ,n); #ifdef PRINT printmatrix(A, lda ,n,n,(char *) "A"); printvector(X, n,(char *) "X"); #endif blis::her( CblasColMajor, CblasLower, n, alpha, X, incx, A, lda ); #ifdef PRINT printmatrix(A, lda ,n,n, (char *)"A output"); #endif ref_her(n, &alpha, X, A_ref); #ifdef PRINT printmatrix(A_ref, lda_ref, n,n ,(char *) "A refoutput"); #endif if(computeErrorM(lda, lda_ref, n, n, A, A_ref )==1) printf("%s TEST FAIL\n" ,__PRETTY_FUNCTION__); else printf("%s TEST PASS\n" , __PRETTY_FUNCTION__); delete[]( A ); delete[]( X ); delete[]( A_ref ); } // ----------------------------------------------------------------------------- int main( int argc, char** argv ) { test_her>( ); test_her>( ); return 0; } blis-0.9.0/vendor/testcpp/test_her2.cc000066400000000000000000000077601422157504600176560ustar00rootroot00000000000000/* BLISPP C++ test driver for BLIS CPP gemm routine and reference blis gemm routine. Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include #include #include "blis.hh" #include "test.hh" using namespace blis; using namespace std; //#define PRINT #define ALPHA 1.0 #define N 6 /* * Test application assumes matrices to be column major, non-transposed */ template< typename T > void ref_her2(int64_t n, T * alpha, T *X, T *Y, T *A ) { obj_t obj_a; obj_t obj_x, obj_y; obj_t obj_alpha; num_t dt; if(is_same>::value) dt = BLIS_SCOMPLEX; else if(is_same>::value) dt = BLIS_DCOMPLEX; bli_obj_create_with_attached_buffer(dt, 1, 1, alpha, 1,1,&obj_alpha ); bli_obj_create_with_attached_buffer( dt, n, n, A, 1, n, &obj_a ); bli_obj_create_with_attached_buffer( dt, n, 1, X, 1, n,&obj_x ); bli_obj_create_with_attached_buffer( dt, n, 1, Y, 1, n,&obj_y ); bli_obj_set_struc( BLIS_HERMITIAN, &obj_a ); bli_obj_set_uplo( BLIS_LOWER, &obj_a); bli_her2( &obj_alpha, &obj_x, &obj_y, &obj_a ); } template< typename T > void test_her2( ) { T *A, *X, *Y, *A_ref; T alpha; int n; int lda, incx, incy, lda_ref; alpha = ALPHA; n = N; lda = n; lda_ref = n; incx = 1; incy = 1; srand (time(NULL)); allocate_init_buffer(A , n , n); allocate_init_buffer(X , n , 1); allocate_init_buffer(Y , n , 1); copy_buffer(A, A_ref , n ,n); #ifdef PRINT printmatrix(A, lda ,n,n,(char *) "A"); printvector(X, n,(char *) "X"); printvector(Y, n, (char *)"Y"); #endif blis::her2( CblasColMajor, CblasLower, n, alpha, X, incx, Y, incy, A, lda ); #ifdef PRINT printmatrix(A, lda , n , n,(char *) "A output"); #endif ref_her2(n, &alpha, X, Y, A_ref); #ifdef PRINT printmatrix(A_ref, lda , n, n, (char *)"A_ref output"); #endif if(computeErrorM(lda, lda_ref, n, n, A, A_ref )==1) printf("%s TEST FAIL\n" ,__PRETTY_FUNCTION__); else printf("%s TEST PASS\n" , __PRETTY_FUNCTION__); delete[]( A ); delete[]( X ); delete[]( Y ); delete[]( A_ref ); } // ----------------------------------------------------------------------------- int main( int argc, char** argv ) { test_her2>( ); test_her2>( ); return 0; } blis-0.9.0/vendor/testcpp/test_herk.cc000066400000000000000000000105201422157504600177330ustar00rootroot00000000000000/* BLISPP C++ test driver for BLIS CPP herk routine and reference blis herk routine. Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include #include #include "blis.hh" #include "test.hh" using namespace blis; using namespace std; //#define PRINT #define ALPHA 1.0 #define BETA 0.0 #define N 6 #define K 6 /* * Test application assumes matrices to be column major, non-transposed */ template< typename T > void ref_herk(int64_t n, int64_t k, real_type * alpha, T *A, real_type * beta, T *C ) { obj_t obj_a,obj_c; obj_t obj_alpha, obj_beta; num_t dt; if(is_same>::value) dt = BLIS_SCOMPLEX; else if(is_same>::value) dt = BLIS_DCOMPLEX; if(dt == BLIS_SCOMPLEX){ bli_obj_create_with_attached_buffer( BLIS_FLOAT, 1, 1, alpha, 1,1,&obj_alpha ); bli_obj_create_with_attached_buffer( BLIS_FLOAT, 1, 1, beta, 1,1,&obj_beta ); } else if(dt == BLIS_DCOMPLEX){ bli_obj_create_with_attached_buffer( BLIS_DOUBLE, 1, 1, alpha, 1,1,&obj_alpha ); bli_obj_create_with_attached_buffer( BLIS_DOUBLE, 1, 1, beta, 1,1,&obj_beta ); } bli_obj_create_with_attached_buffer( dt, n, k, A, 1,n,&obj_a ); bli_obj_create_with_attached_buffer( dt, n, n, C, 1,n,&obj_c ); bli_obj_set_struc( BLIS_HERMITIAN, &obj_c ); bli_obj_set_uplo( BLIS_LOWER, &obj_c ); bli_obj_set_conjtrans( BLIS_NO_TRANSPOSE, &obj_c ); bli_herk( &obj_alpha, &obj_a, &obj_beta, &obj_c ); } template< typename T > void test_herk( ) { T *A, *C, *C_ref; real_type alpha; real_type beta; int n,k; int lda, ldc, ldc_ref; alpha = ALPHA; beta = BETA; k = K; n = N; lda = k; ldc = n; ldc_ref = n; srand (time(NULL)); allocate_init_buffer(A , n , k); allocate_init_buffer(C , n , n); copy_buffer(C, C_ref , n ,n); #ifdef PRINT printmatrix(A, lda ,n,k, (char *)"A"); printmatrix(C, ldc ,n,n, (char *)"C"); #endif blis::herk( CblasColMajor, CblasLower, CblasNoTrans, n, k, alpha, A, lda, beta, C, ldc ); #ifdef PRINT printmatrix(C, ldc ,n,n, (char *)"C output"); #endif ref_herk(n, k, &alpha, A, &beta, C_ref); #ifdef PRINT printmatrix(C_ref, ldc_ref ,n,n, (char *)"C ref output"); #endif if(computeErrorM(ldc, ldc_ref, n, n, C, C_ref )==1) printf("%s TEST FAIL\n" ,__PRETTY_FUNCTION__); else printf("%s TEST PASS\n" , __PRETTY_FUNCTION__); delete[]( A ); delete[]( C ); delete[]( C_ref ); } // ----------------------------------------------------------------------------- int main( int argc, char** argv ) { test_herk>( ); test_herk>( ); return 0; } blis-0.9.0/vendor/testcpp/test_hpr.cc000066400000000000000000000060221422157504600175750ustar00rootroot00000000000000/* BLISPP C++ test driver for BLIS CPP gemm routine and reference blis gemm routine. Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include #include #include "blis.hh" #include "test.hh" using namespace blis; using namespace std; //#define PRINT #define N 2 /* * Test application assumes matrices to be column major, non-transposed */ template< typename T > void test_hpr( ) { int n; real_type alpha; int incX = -1; alpha = 1.0; n = N; T A[4]; A[0] = { 0.265, 0.362}; A[1] = {-0.855, 0.035}; A[2] = {0.136, 0.133 }; A[3] = { 0.00, 0.00}; T X[2]; X[0] = { -0.278, -0.686}; X[1] = {-0.736, -0.918 }; T A_ref[4]; A_ref[0] = { 1.64942, 0.0}; A_ref[1] = {-0.020644, 0.284692}; A_ref[2] = {0.68388, 0.0 }; A_ref[3] = {0.00, 0.00 }; #ifdef PRINT printmatrix(A, n,n, n,(char *) "A"); printvector(X, n, (char *)"X"); #endif blis::hpr( CblasColMajor, CblasLower, n, alpha, X, incX, A ); #ifdef PRINT printmatrix(A, n , n, n,(char *)"A blis:hpr\n"); printmatrix(A_ref, n, n, n,(char *)"A_ref output\n"); #endif if(computeErrorM(n, n, n, n, A, A_ref )==1) printf("%s TEST FAIL\n" ,__PRETTY_FUNCTION__); else printf("%s TEST PASS\n" , __PRETTY_FUNCTION__); } // ----------------------------------------------------------------------------- int main( int argc, char** argv ) { test_hpr>( ); test_hpr>( ); return 0; } blis-0.9.0/vendor/testcpp/test_hpr2.cc000066400000000000000000000052521422157504600176630ustar00rootroot00000000000000/* BLISPP C++ test driver for BLIS CPP gemm routine and reference blis gemm routine. Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include #include #include "blis.hh" #include "test.hh" using namespace blis; using namespace std; #define N 1 /* * Test application assumes matrices to be column major, non-transposed */ template< typename T > void test_hpr2( ) { int n; int incX = -1; int incY = -1; n = N; T alpha = {-0.3, 0.1}; T A[1]; A[0] = { 0.772, 0.997 }; T X[1]; X[0] = { -0.173, -0.839 }; T Y[1]; Y[0] = { 0.941, -0.422 }; T A_ref[1]; A_ref[0] = { 0.829742, 0.0 }; blis::hpr2( CblasColMajor, CblasLower, n, alpha, X, incX, Y, incY, A ); if(computeErrorM(1, 1, n, n, A, A_ref )==1) printf("%s TEST FAIL\n" ,__PRETTY_FUNCTION__); else printf("%s TEST PASS\n" , __PRETTY_FUNCTION__); } // ----------------------------------------------------------------------------- int main( int argc, char** argv ) { test_hpr2>( ); printf("**************\n"); test_hpr2>( ); return 0; } blis-0.9.0/vendor/testcpp/test_nrm2.cc000066400000000000000000000060071422157504600176650ustar00rootroot00000000000000/* BLISPP C++ test driver for BLIS CPP nrm2 routine and reference blis nrm2 routine. Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include #include #include "blis.hh" #include "test.hh" using namespace blis; using namespace std; //#define PRINT #define N 2 #define ALPHA 0.5 #define TOLERANCE 0.0000001 /* * Test application assumes matrices to be column major, non-transposed */ template< typename T> void test_nrm2() { T X[N]; T nrm2, nrm2_ref; int n; int incx; n = N; incx = 1; if(is_same::value) { X[0] = 0.14f; X[1] = -0.632f; nrm2_ref = 0.647320631527f; } else if(is_same::value) { X[0] = 0.696; X[1] = -0.804; nrm2_ref = 1.06340584915; } #ifdef PRINT printvector(X, n,(char *) "Vector X after blis::nrm2"); #endif nrm2 = blis::nrm2( n, X, incx ); #ifdef PRINT printf("Norm of a Vector %E \n", nrm2); printf("Ref Norm of a Vector %E \n", nrm2_ref); #endif if (fabs(nrm2 - nrm2_ref) > TOLERANCE) printf("%s TEST FAIL\n" , __PRETTY_FUNCTION__); else printf("%s TEST PASS\n" , __PRETTY_FUNCTION__); } // ----------------------------------------------------------------------------- int main( int argc, char** argv ) { test_nrm2( ); test_nrm2( ); return 0; } blis-0.9.0/vendor/testcpp/test_rot.cc000066400000000000000000000064231422157504600176150ustar00rootroot00000000000000/* BLISPP C++ test driver for BLIS CPP rot routine and reference blis rot routine. Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include #include #include "blis.hh" #include "test.hh" using namespace blis; using namespace std; //#define PRINT #define N 1 /* * Test application assumes matrices to be column major, non-transposed */ template< typename T> void test_rot() { T c, s; T X[N], X_ref[N]; T Y[N], Y_ref[N]; int n; int incx, incy; n = N; incx = 1; incy = 1; if(is_same::value){ c = -1.0f; s = 0.0f; X[0] = { -0.314f }; Y[0] = { -0.406f }; X_ref[0] = { 0.314f }; Y_ref[0] = { 0.406f }; }else{ c = -1; s = 0; X[0] = { -0.176 }; Y[0] = { -0.165 }; X_ref[0] = { 0.176 }; Y_ref[0] = { 0.165 }; } #ifdef PRINT printvector(X, n, (char *)"Before blis::rot\nVector X"); printvector(Y, n, (char *)"Vector Y"); #endif blis::rot( N, X, incx, Y, incy, c, s); #ifdef PRINT printvector(X, n, (char *)"After blis::rot\nVector X"); printvector(Y, n, (char *) "Vector Y"); printvector(X, n, (char *) "Expected Output from blis::rot\nVector X"); printvector(Y, n, (char *)"Vector Y"); #endif if((computeErrorV(incx, incx , n, X, X_ref )==1) || (computeErrorV(incy, incy , n, Y, Y_ref )==1)) printf("%s TEST FAIL\n" , __PRETTY_FUNCTION__); else printf("%s TEST PASS\n" , __PRETTY_FUNCTION__); } // ----------------------------------------------------------------------------- int main( int argc, char** argv ) { test_rot( ); test_rot( ); return 0; } blis-0.9.0/vendor/testcpp/test_rotg.cc000066400000000000000000000065551422157504600177720ustar00rootroot00000000000000/* BLISPP C++ test driver for BLIS CPP rotg routine and reference blis rotg routine. Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include #include #include "blis.hh" #include "test.hh" using namespace blis; using namespace std; //#define PRINT /* * Test application assumes matrices to be column major, non-transposed */ template< typename T> void test_rotg() { T a, b, c, s; T a_ref, b_ref, c_ref, s_ref; if(is_same::value) { a = 1.0f; b = 1.0f; a_ref = 1.41421356237f; b_ref = 1.41421356237f; c_ref = 0.707106781187f; s_ref = 0.707106781187f; }else{ a = 1; b = 0; a_ref = 1; b_ref = 0; c_ref = 1; s_ref = 0; } #ifdef PRINT cout<< "Before blis::rotg \na Value : " << a << "\n" ; cout<< "b Value : " << b << "\n" ; #endif blis::rotg( &a, &b, &c, &s ); #ifdef PRINT cout<< "After blis::rotg \na Value : " << a << "\n" ; cout<< "b Value : " << b << "\n" ; cout<< "c Value : " << c << "\n" ; cout<< "s Value : " << s << "\n" ; #endif #ifdef PRINT cout<< "Expected Output\na Value : " << a_ref << "\n" ; cout<< "b Value : " << b_ref << "\n" ; cout<< "c Value : " << c_ref << "\n" ; cout<< "s Value : " << s_ref << "\n" ; #endif if( (a != a_ref ) || (b != b_ref ) || (c != c_ref ) || (s != s_ref )) printf("%s TEST FAIL\n" , __PRETTY_FUNCTION__); else printf("%s TEST PASS\n" , __PRETTY_FUNCTION__); } // ----------------------------------------------------------------------------- int main( int argc, char** argv ) { test_rotg( ); test_rotg( ); return 0; } blis-0.9.0/vendor/testcpp/test_rotm.cc000066400000000000000000000070741422157504600177750ustar00rootroot00000000000000/* BLISPP C++ test driver for BLIS CPP rotm routine and reference blis rotm routine. Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include #include #include "blis.hh" #include "test.hh" using namespace blis; using namespace std; //#define PRINT #define N 1 /* * Test application assumes matrices to be column major, non-transposed */ template< typename T> void test_rotm() { T X[N], X_ref[N]; T Y[N], Y_ref[N]; int n; int incx, incy; const T P[5] = { -1.0f, -4.44982e+03f, -15.5826f, 7.091334e+04f, 2.95912e+04f }; const T P_double[5] = { 1.0, -1.244580625511e+03, 1.11154682624, 2.269384716089e-05, -0.0143785338883 }; n = N; incx = 1; incy = 1; if(is_same::value) { X[0] = { -0.034f }; Y[0] = { -0.56f }; X_ref[0] = { -3.956017e+04f }; Y_ref[0] = { -1.657054e+04f }; }else{ X[0] = { 0.84 }; Y[0] = { -0.711 }; X_ref[0] = { -1.046158725429e+03 }; Y_ref[0] = { -0.829776862405 }; } #ifdef PRINT printvector(X, n, (char *)"Before blis::rot\nVector X"); printvector(Y, n, (char *)"Vector Y"); #endif if(is_same::value) { blis::rotm( N, X, incx, Y, incy, P); }else{ blis::rotm( N, X, incx, Y, incy, P_double); } #ifdef PRINT printvector(X, n, (char *)"After blis::rot\nVector X"); printvector(Y, n, (char *)"Vector Y"); printvector(X, n, (char *)"Expected Output from blis::rot\nVector X"); printvector(Y, n, (char *)"Vector Y"); #endif if((computeErrorV(incx, incx , n, X, X_ref )==1) || (computeErrorV(incy, incy , n, Y, Y_ref )==1)) printf("%s TEST FAIL\n" , __PRETTY_FUNCTION__); else printf("%s TEST PASS\n" , __PRETTY_FUNCTION__); } // ----------------------------------------------------------------------------- int main( int argc, char** argv ) { test_rotm( ); test_rotm( ); return 0; } blis-0.9.0/vendor/testcpp/test_rotmg.cc000066400000000000000000000106631422157504600201420ustar00rootroot00000000000000/* BLISPP C++ test driver for BLIS CPP rotmg routine and reference blis rotmg routine. Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include #include #include "blis.hh" #include "test.hh" using namespace blis; using namespace std; //#define PRINT /* * Test application assumes matrices to be column major, non-transposed */ template< typename T> void test_rotmg() { T d1, d2, b1, b2; T d1_ref, d2_ref, b1_ref; T h[5] = { -999.0f, -999.1f, -999.2f, -999.3f, -999.4f }; T h_ref[5] = {-1.0f, 0.0f, 0.0f, 0.0f,0.0f}; T h_double[5] = { -999.0, -999.1, -999.2, -999.3, -999.4 }; T h_ref_double[5] = { 1, 0, 0, 0}; if(is_same::value) { d1 = -1630.28519312f; d2 = 44320.1964703f; b1 = 1274.7681352f; b2 = 0.983006912864f; d1_ref= 0.0f; d2_ref= 0.0f; b1_ref= 0.0f; }else{ d1 = -49.1978123005; d2 = 0.228703451277; b1 = 1.8901039144; b2 = 7081.47754386; d1_ref= 0; d2_ref= 0; b1_ref= 0; } #ifdef PRINT cout<< "Before blis::rotmg \nd1 Value : " << d1 << "\n" ; cout<< "d2 Value : " << d2 << "\n" ; cout<< "b1 Value : " << b1 << "\n" ; printvector(h, 5,(char *) "param"); #endif if(is_same::value) { blis::rotmg( &d1, &d2, &b1, b2, h ); }else{ blis::rotmg( &d1, &d2, &b1, b2, h_double ); } #ifdef PRINT cout<< "After blis::rotmg \nd1 Value : " << d1 << "\n" ; cout<< "d2 Value : " << d2 << "\n" ; cout<< "b1 Value : " << b1 << "\n" ; printvector(h, 5,(char *) "param"); #endif #ifdef PRINT cout<< "Expected Output from blis::rotmg \nd1 Value : " << d1_ref << "\n" ; cout<< "d2 Value : " << d2_ref << "\n" ; cout<< "b1 Value : " << b1_ref << "\n" ; printvector(h_ref, 5,(char *) "param"); #endif if( (d1 != d1_ref ) || (d2 != d2_ref ) || (b1 != b1_ref ) ) printf("%s TEST FAIL\n" , __PRETTY_FUNCTION__); else if(is_same::value){ if(computeErrorV(1, 1 , 5, h, h_ref )==1) printf("%s TEST FAIL\n" , __PRETTY_FUNCTION__); else printf("%s TEST PASS\n" , __PRETTY_FUNCTION__); }else if(is_same::value){ if(computeErrorV(1, 1 , 5, h_double, h_ref_double )==1) printf("%s TEST FAIL\n" , __PRETTY_FUNCTION__); else printf("%s TEST PASS\n" , __PRETTY_FUNCTION__); }else printf("%s TEST PASS\n" , __PRETTY_FUNCTION__); } // ----------------------------------------------------------------------------- int main( int argc, char** argv ) { test_rotmg( ); test_rotmg( ); return 0; } blis-0.9.0/vendor/testcpp/test_scal.cc000066400000000000000000000077451422157504600177430ustar00rootroot00000000000000/* BLISPP C++ test driver for BLIS CPP gemm routine and reference blis gemm routine. Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include #include #include "blis.hh" #include "test.hh" using namespace blis; using namespace std; //#define PRINT #define N 6 #define ALPHA 0.5 /* * Test application assumes matrices to be column major, non-transposed */ template< typename TA,typename TB> void ref_scal(int64_t n, TA * alpha, TB *X ) { obj_t obj_x; obj_t obj_alpha; num_t dt_x , dt_alpha; if(is_same::value) dt_x = BLIS_FLOAT; else if(is_same::value) dt_x = BLIS_DOUBLE; else if(is_same>::value) dt_x = BLIS_SCOMPLEX; else if(is_same>::value) dt_x = BLIS_DCOMPLEX; if(is_same::value) dt_alpha = BLIS_FLOAT; else if(is_same::value) dt_alpha = BLIS_DOUBLE; else if(is_same>::value) dt_alpha = BLIS_SCOMPLEX; else if(is_same>::value) dt_alpha = BLIS_DCOMPLEX; bli_obj_create_with_attached_buffer( dt_alpha, 1, 1, alpha, 1,1,&obj_alpha ); bli_obj_create_with_attached_buffer( dt_x, n, 1, X, 1, n,&obj_x ); bli_scalv(&obj_alpha, &obj_x ); } template< typename TA, typename TB> void test_scal() { TB *X, *X_ref; TA alpha = ALPHA; int n; int incx; n = N; incx = 1; srand (time(NULL)); allocate_init_buffer(X , n , 1); copy_buffer(X, X_ref , n ,1); #ifdef PRINT printvector(X, n, (char *)"X"); #endif blis::scal( n, alpha, X, incx ); #ifdef PRINT printvector(X, n, (char *)"X output"); #endif ref_scal(n , &alpha , X_ref ); #ifdef PRINT printvector(X_ref, n, (char *)"X ref output"); #endif if(computeErrorV(incx, incx , n, X, X_ref )==1) printf("%s TEST FAIL\n" , __PRETTY_FUNCTION__); else printf("%s TEST PASS\n" , __PRETTY_FUNCTION__); delete[]( X ); delete[]( X_ref ); } // ----------------------------------------------------------------------------- int main( int argc, char** argv ) { test_scal( ); test_scal( ); test_scal , std::complex>( ); test_scal , std::complex>( ); test_scal>( ); test_scal>( ); return 0; } blis-0.9.0/vendor/testcpp/test_sdsdot.cc000066400000000000000000000070131422157504600203050ustar00rootroot00000000000000/* BLISPP C++ test driver for BLIS CPP sdsdot routine and reference blis sdsdot routine. Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include #include #include "blis.hh" #include "test.hh" using namespace blis; using namespace std; //#define PRINT #define N 1 #define ALPHA 0 /* * Test application assumes matrices to be column major, non-transposed */ #if 0 template< typename T > void ref_sdsot(int64_t n, T alpha, T *X, T *Y, T *res_ref ) { obj_t obj_x; obj_t obj_y; obj_t obj_res; obj_t obj_alpha; num_t dt; if(is_same>::value) dt = BLIS_SCOMPLEX; else if(is_same>::value) dt = BLIS_DCOMPLEX; bli_obj_create_with_attached_buffer( dt, n, 1, X, 1, n,&obj_x ); bli_obj_create_with_attached_buffer( dt, n, 1, Y, 1, n,&obj_y ); bli_obj_create_with_attached_buffer( dt, 1, 1, &alpha, 1,1,&obj_alpha ); bli_obj_create_with_attached_buffer( dt, 1, 1, res_ref, 1, 1,&obj_res ); bli_ddots( &obj_x, &obj_y, &obj_res ); } #endif template< typename T > void test_sdsdot() { T X[N], Y[N]; int n; int incx, incy; T res = 0, res_ref = 0; n = N; incx = 1; incy = 1; //srand (time(NULL)); //allocate_init_buffer(X , n , 1); //allocate_init_buffer(Y , n , 1); X[0] = { 0.733f }; Y[0] = { 0.825f }; res_ref = 0.604725f; res = blis::sdsdot( n, ALPHA, X, incx, Y, incy ); #ifdef PRINT printf("Dot product = %E \n", res); #endif //ref_sdsot(n, aplha, X, Y , &res_ref ); #ifdef PRINT printf("Ref Dot product %E \n", res_ref); #endif if(res != res_ref ) printf("%s TEST FAIL\n" ,__PRETTY_FUNCTION__); else printf("%s TEST PASS\n" , __PRETTY_FUNCTION__); } // ----------------------------------------------------------------------------- int main( int argc, char** argv ) { test_sdsdot( ); return 0; } blis-0.9.0/vendor/testcpp/test_spr.cc000066400000000000000000000054711422157504600176170ustar00rootroot00000000000000/* BLISPP C++ test driver for BLIS CPP gemm routine and reference blis gemm routine. Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include #include #include "blis.hh" #include "test.hh" using namespace blis; using namespace std; //#define PRINT #define N 2 /* * Test application assumes matrices to be column major, non-transposed */ template< typename T > void test_spr( ) { int n; int incX = -1; T alpha = -1; n = N; T A[] = { 0.819, 0.175, -0.809 }; T X[] = { -0.645, -0.222 }; T A_ref[] = { 0.769716, 0.03181, -1.225025 }; #ifdef PRINT printmatrix(A, n, n, n,(char *) "A"); printvector(X, n,(char *) "X"); #endif blis::spr( CblasColMajor, CblasLower, n, alpha, X, incX, A ); #ifdef PRINT printmatrix (A, n ,n, n, (char *)"A blis:spr\n"); printmatrix(A_ref, n, n, n,(char *)"A_ref blis:spr \n"); #endif if(computeErrorM(1, 1, n, n, A, A_ref )==1) printf("%s TEST FAIL\n" ,__PRETTY_FUNCTION__); else printf("%s TEST PASS\n" , __PRETTY_FUNCTION__); } // ----------------------------------------------------------------------------- int main( int argc, char** argv ) { test_spr( ); test_spr( ); return 0; } blis-0.9.0/vendor/testcpp/test_spr2.cc000066400000000000000000000060231422157504600176730ustar00rootroot00000000000000/* BLISPP C++ test driver for BLIS CPP gemm routine and reference blis gemm routine. Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include #include #include "blis.hh" #include "test.hh" using namespace blis; using namespace std; //#define PRINT #define ALPHA -1.0f #define N 2 /* * Test application assumes matrices to be column major, non-transposed */ template< typename T > void test_spr2( ) { int n; int incX = -1; int incY = -1; T alpha; alpha = ALPHA; n = N; T A[] = { 0.493f, -0.175f, -0.831f }; T X[] = { -0.163f, 0.489f }; T Y[] = { 0.154f, 0.769f }; T A_ref[]= { -0.259082f, -0.124959f, -0.780796f }; #ifdef PRINT printf("Matrix A\n"); printmatrix(A, incX, n,n,(char *)"A"); printf("Vector X \n"); printvector(X, n, (char *)"X"); #endif blis::spr2( CblasColMajor, CblasLower, n, alpha, X, incX, Y, incY, A ); #ifdef PRINT printf("Matrix A after blis:spr2\n"); printmatrix (A,1 ,n, n,(char *)"A"); printf("A_ref \n"); printmatrix(A_ref, 1, n,n,(char *)"A_ref output"); #endif if(computeErrorM(1, 1, n, n, A, A_ref )==1) printf("%s TEST FAIL\n" ,__PRETTY_FUNCTION__); else printf("%s TEST PASS\n" , __PRETTY_FUNCTION__); } // ----------------------------------------------------------------------------- int main( int argc, char** argv ) { test_spr2( ); test_spr2( ); return 0; } blis-0.9.0/vendor/testcpp/test_swap.cc000066400000000000000000000073111422157504600177600ustar00rootroot00000000000000/* BLISPP C++ test driver for BLIS CPP gemm routine and reference blis gemm routine. Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include #include #include "blis.hh" #include "test.hh" using namespace blis; using namespace std; //#define PRINT #define N 6 /* * Test application assumes matrices to be column major, non-transposed */ template< typename T> void ref_swap(int64_t n, T *X, T *Y ) { obj_t obj_x, obj_y; num_t dt; if(is_same::value) dt = BLIS_FLOAT; else if(is_same::value) dt = BLIS_DOUBLE; else if(is_same>::value) dt = BLIS_SCOMPLEX; else if(is_same>::value) dt = BLIS_DCOMPLEX; bli_obj_create_with_attached_buffer( dt, n, 1, X, 1, n,&obj_x ); bli_obj_create_with_attached_buffer( dt, n, 1, Y, 1, n,&obj_y ); bli_swapv( &obj_x, &obj_y ); } template< typename T > void test_swap( ) { T *X, *X_ref, *Y,*Y_ref; int n; int incx, incy; n = N; incx = 1; incy = 1; srand (time(NULL)); allocate_init_buffer(X , n , 1); allocate_init_buffer(Y , n , 1); copy_buffer(X, X_ref , n ,1); copy_buffer(Y, Y_ref , n ,1); #ifdef PRINT printvector(X, n, (char *)"X"); printvector(Y, n, (char *)"Y"); #endif blis::swap( n, X, incx, Y, incy ); #ifdef PRINT printvector(X, n, (char *)"X output"); printvector(Y, n, (char *)"Y output"); #endif ref_swap(n , X_ref, Y_ref ); #ifdef PRINT printvector(X_ref, n, (char *)"X ref output"); printvector(Y_ref, n, (char *)"Y ref output"); #endif if((computeErrorV(incy, incy,n, Y, Y_ref )==1)||(computeErrorV(incx, incx, n, X, X_ref )==1)) printf("%s TEST FAIL\n" , __PRETTY_FUNCTION__); else printf("%s TEST PASS\n" , __PRETTY_FUNCTION__); delete[]( X ); delete[]( Y ); delete[]( Y_ref ); delete[]( X_ref ); } // ----------------------------------------------------------------------------- int main( int argc, char** argv ) { test_swap( ); test_swap( ); test_swap>( ); test_swap>( ); return 0; } blis-0.9.0/vendor/testcpp/test_symm.cc000066400000000000000000000107651422157504600200020ustar00rootroot00000000000000/* BLISPP C++ test driver for BLIS CPP symm routine and reference blis symm routine. Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include #include #include "blis.hh" #include "test.hh" using namespace blis; using namespace std; //#define PRINT #define ALPHA 1.0 #define BETA 0.0 #define M 5 #define N 5 /* * Test application assumes matrices to be column major, non-transposed */ template< typename T > void ref_symm(int64_t m, int64_t n, // side_t side, T * alpha, T *A, T *B, T * beta, T *C ) { obj_t obj_a, obj_b, obj_c; obj_t obj_alpha, obj_beta; num_t dt; if(is_same::value) dt = BLIS_FLOAT; else if(is_same::value) dt = BLIS_DOUBLE; else if(is_same>::value) dt = BLIS_SCOMPLEX; else if(is_same>::value) dt = BLIS_DCOMPLEX; bli_obj_create_with_attached_buffer( dt, 1, 1, alpha, 1,1,&obj_alpha ); bli_obj_create_with_attached_buffer( dt, 1, 1, beta, 1,1,&obj_beta ); bli_obj_create_with_attached_buffer( dt, m, m, A, 1,m,&obj_a ); bli_obj_create_with_attached_buffer( dt, m, n, B, 1,n,&obj_b ); bli_obj_create_with_attached_buffer( dt, m, n, C, 1,m,&obj_c ); bli_obj_set_struc( BLIS_SYMMETRIC, &obj_a ); bli_obj_set_uplo( BLIS_LOWER, &obj_a ); bli_symm( BLIS_LEFT, &obj_alpha, &obj_a, &obj_b, &obj_beta, &obj_c ); } template< typename T > void test_symm( ) { T *A, *B, *C, *C_ref; T alpha, beta; int m,n; int lda, ldb, ldc, ldc_ref; alpha = ALPHA; beta = BETA; m = M; n = N; lda = m; ldb = n; ldc = m; ldc_ref = m; srand (time(NULL)); allocate_init_buffer(A , m , m); allocate_init_buffer(B , m , n); allocate_init_buffer(C , m , n); copy_buffer(C, C_ref , m ,n); #ifdef PRINT printmatrix(A, lda ,m,m, (char *)"A"); printmatrix(B, ldb ,m,n, (char *)"B"); printmatrix(C, ldc ,m,n, (char *)"C"); #endif blis::symm( CblasColMajor, CblasLeft, CblasLower, m, n, alpha, A, lda, B, ldb, beta, C, ldc ); #ifdef PRINT printmatrix(C, ldc ,m,n, (char *)"C output"); #endif // ref_symm(m, n, side, &alpha, A, B, &beta, C_ref); ref_symm(m, n, &alpha, A, B, &beta, C_ref); #ifdef PRINT printmatrix(C_ref, ldc_ref ,m,n, (char *)"C ref output"); #endif if(computeErrorM(ldc, ldc_ref, m, n, C, C_ref )==1) printf("%s TEST FAIL\n" , __PRETTY_FUNCTION__ ); else printf("%s TEST PASS\n" , __PRETTY_FUNCTION__ ); delete[]( A ); delete[]( B ); delete[]( C ); delete[]( C_ref ); } // ----------------------------------------------------------------------------- int main( int argc, char** argv ) { test_symm( ); test_symm( ); test_symm>( ); test_symm>( ); return 0; } blis-0.9.0/vendor/testcpp/test_syr.cc000066400000000000000000000075231422157504600176300ustar00rootroot00000000000000/* BLISPP C++ test driver for BLIS CPP gemm routine and reference blis gemm routine. Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include #include #include "blis.hh" #include "test.hh" using namespace blis; using namespace std; //#define PRINT #define ALPHA 1.0 #define N 6 /* * Test application assumes matrices to be column major, non-transposed */ template< typename T > void ref_syr(int64_t n, T * alpha, T *X, T *A ) { obj_t obj_a; obj_t obj_x; obj_t obj_alpha; num_t dt; if(is_same::value) dt = BLIS_FLOAT; else if(is_same::value) dt = BLIS_DOUBLE; else if(is_same>::value) dt = BLIS_SCOMPLEX; else if(is_same>::value) dt = BLIS_DCOMPLEX; bli_obj_create_with_attached_buffer( dt, 1, 1, alpha, 1,1,&obj_alpha ); bli_obj_create_with_attached_buffer( dt, n, n, A, 1, n, &obj_a ); bli_obj_create_with_attached_buffer( dt, n, 1, X, 1, n,&obj_x ); bli_obj_set_struc( BLIS_SYMMETRIC, &obj_a ); bli_obj_set_uplo( BLIS_LOWER, &obj_a); bli_syr( &obj_alpha, &obj_x, &obj_a ); } template< typename T > void test_syr( ) { T *A, *X, *A_ref; T alpha; int n; int lda, incx, lda_ref; alpha = ALPHA; n = N; lda = n; lda_ref = n; incx = 1; srand (time(NULL)); allocate_init_buffer(A , n , n); allocate_init_buffer(X , n , 1); copy_buffer(A, A_ref , n ,n); #ifdef PRINT printmatrix(A, lda ,n,n, (char *)"A"); printvector(X, n,(char *) "X"); #endif blis::syr( CblasColMajor, CblasLower, n, alpha, X, incx, A, lda ); #ifdef PRINT printmatrix(A, lda , n , n,(char *) "A output"); #endif ref_syr(n, &alpha, X, A_ref); #ifdef PRINT printmatrix(A_ref, lda , n, n, (char *)"A ref output"); #endif if(computeErrorM(lda, lda_ref, n, n, A, A_ref )==1) printf("%s TEST FAIL\n" ,__PRETTY_FUNCTION__); else printf("%s TEST PASS\n" , __PRETTY_FUNCTION__); delete[]( A ); delete[]( X ); delete[]( A_ref ); } // ----------------------------------------------------------------------------- int main( int argc, char** argv ) { test_syr( ); test_syr( ); return 0; } blis-0.9.0/vendor/testcpp/test_syr2.cc000066400000000000000000000101071422157504600177020ustar00rootroot00000000000000/* BLISPP C++ test driver for BLIS CPP gemm routine and reference blis gemm routine. Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include #include #include "blis.hh" #include "test.hh" using namespace blis; using namespace std; //#define PRINT #define ALPHA 1.0 #define N 6 /* * Test application assumes matrices to be column major, non-transposed */ template< typename T > void ref_syr2(int64_t n, T * alpha, T *X, T *Y, T *A ) { obj_t obj_a; obj_t obj_x, obj_y; obj_t obj_alpha; num_t dt; if(is_same::value) dt = BLIS_FLOAT; else if(is_same::value) dt = BLIS_DOUBLE; else if(is_same>::value) dt = BLIS_SCOMPLEX; else if(is_same>::value) dt = BLIS_DCOMPLEX; bli_obj_create_with_attached_buffer( dt, 1, 1, alpha, 1,1,&obj_alpha ); bli_obj_create_with_attached_buffer( dt, n, n, A, 1, n, &obj_a ); bli_obj_create_with_attached_buffer( dt, n, 1, X, 1, n,&obj_x ); bli_obj_create_with_attached_buffer( dt, n, 1, Y, 1, n,&obj_y ); bli_obj_set_struc( BLIS_SYMMETRIC, &obj_a ); bli_obj_set_uplo( BLIS_LOWER, &obj_a); bli_syr2( &obj_alpha, &obj_x, &obj_y, &obj_a ); } template< typename T > void test_syr2( ) { T *A, *X, *Y, *A_ref; T alpha; int n; int lda, incx, incy, lda_ref; alpha = ALPHA; n = N; lda = n; lda_ref = n; incx = 1; incy = 1; srand (time(NULL)); allocate_init_buffer(A , n , n); allocate_init_buffer(X , n , 1); allocate_init_buffer(Y , n , 1); copy_buffer(A, A_ref , n ,n); #ifdef PRINT printmatrix(A, lda ,n,n,(char *) "A"); printvector(X, n, (char *)"X"); printvector(Y, n, (char *)"Y"); #endif blis::syr2( CblasColMajor, CblasLower, n, alpha, X, incx, Y, incy, A, lda ); #ifdef PRINT printmatrix(A, lda , n , n,(char *) "A output"); #endif ref_syr2(n, &alpha, X, Y, A_ref); #ifdef PRINT printmatrix(A_ref, lda , n, n, (char *)"A_ref output"); #endif if(computeErrorM(lda, lda_ref, n, n, A, A_ref )==1) printf("%s TEST FAIL\n" ,__PRETTY_FUNCTION__); else printf("%s TEST PASS\n" , __PRETTY_FUNCTION__); delete[]( A ); delete[]( X ); delete[]( Y ); delete[]( A_ref ); } // ----------------------------------------------------------------------------- int main( int argc, char** argv ) { test_syr2( ); test_syr2( ); return 0; } blis-0.9.0/vendor/testcpp/test_syr2k.cc000066400000000000000000000107171422157504600200640ustar00rootroot00000000000000/* BLISPP C++ test driver for BLIS CPP syr2k routine and reference blis syr2k routine. Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include #include #include "blis.hh" #include "test.hh" using namespace blis; using namespace std; //#define PRINT #define ALPHA 1.0 #define BETA 0.0 #define N 6 #define K 6 /* * Test application assumes matrices to be column major, non-transposed */ template< typename T > void ref_syr2k(int64_t n, int64_t k, T * alpha, T *A, T *B, T * beta, T *C ) { obj_t obj_a, obj_b, obj_c; obj_t obj_alpha, obj_beta; num_t dt; if(is_same::value) dt = BLIS_FLOAT; else if(is_same::value) dt = BLIS_DOUBLE; else if(is_same>::value) dt = BLIS_SCOMPLEX; else if(is_same>::value) dt = BLIS_DCOMPLEX; bli_obj_create_with_attached_buffer( dt, 1, 1, alpha, 1,1,&obj_alpha ); bli_obj_create_with_attached_buffer( dt, 1, 1, beta, 1,1,&obj_beta ); bli_obj_create_with_attached_buffer( dt, n, k, A, 1,n,&obj_a ); bli_obj_create_with_attached_buffer( dt, k, n, B,1,k,&obj_b ); bli_obj_create_with_attached_buffer( dt, n, n, C, 1,n,&obj_c ); bli_obj_set_struc( BLIS_SYMMETRIC, &obj_c ); bli_obj_set_uplo( BLIS_LOWER, &obj_c ); bli_obj_set_conjtrans( BLIS_NO_TRANSPOSE, &obj_c ); bli_syr2k( &obj_alpha, &obj_a, &obj_b, &obj_beta, &obj_c ); } template< typename T > void test_syr2k( ) { T *A, *B, *C, *C_ref; T alpha; T beta; int n,k; int ldb, lda, ldc, ldc_ref; alpha = ALPHA; beta = BETA; k = K; n = N; lda = n; ldb = k; ldc = n; ldc_ref = n; srand (time(NULL)); allocate_init_buffer(A , n , k); allocate_init_buffer(B , k , n); allocate_init_buffer(C , n , n); copy_buffer(C, C_ref , n ,n); #ifdef PRINT printmatrix(A, lda ,n,k,(char *) "A"); printmatrix(B, ldb ,k,n,(char *) "B"); printmatrix(C, ldc ,n,n,(char *) "C"); #endif blis::syr2k( CblasColMajor, CblasLower, CblasNoTrans, n, k, alpha, A, lda, B, ldb, beta, C, ldc ); #ifdef PRINT printmatrix(C, ldc ,n,n,(char *) "C output"); #endif ref_syr2k(n, k, &alpha, A, B, &beta, C_ref); #ifdef PRINT printmatrix(C_ref, ldc_ref ,n,n,(char *) "C ref output"); #endif if(computeErrorM(ldc, ldc_ref, n, n, C, C_ref )==1) printf("%s TEST FAIL\n" ,__PRETTY_FUNCTION__); else printf("%s TEST PASS\n" , __PRETTY_FUNCTION__); delete[]( A ); delete[]( B ); delete[]( C ); delete[]( C_ref ); } // ----------------------------------------------------------------------------- int main( int argc, char** argv ) { test_syr2k( ); test_syr2k( ); test_syr2k>( ); test_syr2k>( ); return 0; } blis-0.9.0/vendor/testcpp/test_syrk.cc000066400000000000000000000103261422157504600177760ustar00rootroot00000000000000/* BLISPP C++ test driver for BLIS CPP gemm routine and reference blis gemm routine. Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include #include #include "blis.hh" #include "test.hh" using namespace blis; using namespace std; //#define PRINT #define ALPHA 1.0 #define BETA 0.0 #define N 6 #define K 4 /* * Test application assumes matrices to be column major, non-transposed */ template< typename T > void ref_syrk(int64_t n, int64_t k, T * alpha, T *A, T * beta, T *C ) { obj_t obj_a,obj_c; obj_t obj_alpha, obj_beta; num_t dt; if(is_same::value) dt = BLIS_FLOAT; else if(is_same::value) dt = BLIS_DOUBLE; else if(is_same>::value) dt = BLIS_SCOMPLEX; else if(is_same>::value) dt = BLIS_DCOMPLEX; bli_obj_create_with_attached_buffer( dt, 1, 1, alpha, 1,1,&obj_alpha ); bli_obj_create_with_attached_buffer( dt, 1, 1, beta, 1,1,&obj_beta ); bli_obj_create_with_attached_buffer( dt, n, k, A, 1,n,&obj_a ); bli_obj_create_with_attached_buffer( dt, n, n, C, 1,n,&obj_c ); bli_obj_set_struc( BLIS_SYMMETRIC, &obj_c ); bli_obj_set_conjtrans( BLIS_NO_TRANSPOSE, &obj_c ); bli_obj_set_uplo( BLIS_LOWER, &obj_c ); bli_syrk( &obj_alpha, &obj_a, &obj_beta, &obj_c ); } template< typename T > void test_syrk( ) { T *A, *C, *C_ref; T alpha, beta; int n,k; int lda, ldc, ldc_ref; alpha = ALPHA; beta = BETA; k = K; n = N; lda = n; ldc = n; ldc_ref = n; srand (time(NULL)); allocate_init_buffer(A , n , k); allocate_init_buffer(C , n , n); copy_buffer(C, C_ref , n ,n); #ifdef PRINT printmatrix(A, lda ,n,k, (char *)"A"); printmatrix(C, ldc ,n,n, (char *)"C"); #endif blis::syrk( CblasColMajor, CblasLower, CblasNoTrans, n, k, alpha, A, lda, beta, C, ldc ); #ifdef PRINT printmatrix(C, ldc ,n,n, (char *)"C output"); #endif ref_syrk(n, k, &alpha, A, &beta, C_ref); #ifdef PRINT printmatrix(C_ref, ldc_ref ,n,n, (char *)"C ref output"); #endif if(computeErrorM(ldc, ldc_ref, n, n, C, C_ref )==1) printf("%s TEST FAIL\n" ,__PRETTY_FUNCTION__); else printf("%s TEST PASS\n" , __PRETTY_FUNCTION__); delete[]( A ); delete[]( C ); delete[]( C_ref ); } // ----------------------------------------------------------------------------- int main( int argc, char** argv ) { test_syrk( ); test_syrk( ); test_syrk>( ); test_syrk>( ); return 0; } blis-0.9.0/vendor/testcpp/test_tbmv.cc000066400000000000000000000057221422157504600177620ustar00rootroot00000000000000/* BLISPP C++ test driver for BLIS CPP gemm routine and reference blis gemm routine. Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include #include #include "blis.hh" #include "test.hh" using namespace blis; using namespace std; //#define PRINT //#define PRINT #define N 3 #define K 1 /* * Test application assumes matrices to be column major, non-transposed */ template< typename T > void test_tbmv( ) { int n,k,lda; k = K; n = N; lda = n; T A[] = { 0.439f, -0.484f, -0.952f, -0.508f, 0.381f, -0.889f, -0.192f, -0.279f, -0.155f }; T X[] = { -0.089f, -0.688f, -0.203f }; int incX = -1; T X_ref[] = { -0.24504f, 0.447756f, -0.089117f }; #ifdef PRINT printmatrix(A, lda ,n,n,(char *)"A"); printvector(X, n,(char *)"X"); #endif blis::tbmv( CblasColMajor, CblasLower, CblasNoTrans, CblasNonUnit, n, k, A, lda, X, incX ); #ifdef PRINT printvector(X, n,(char *)"X"); printvector(X_ref ,n,(char *) "X output"); #endif if(computeErrorV(incX, incX, n, X, X_ref )==1) printf("%s TEST FAIL\n" , __PRETTY_FUNCTION__); else printf("%s TEST PASS\n" , __PRETTY_FUNCTION__); } // ----------------------------------------------------------------------------- int main( int argc, char** argv ) { test_tbmv( ); test_tbmv( ); test_tbmv>( ); test_tbmv>( ); return 0; } blis-0.9.0/vendor/testcpp/test_tbsv.cc000066400000000000000000000057421422157504600177720ustar00rootroot00000000000000/* BLISPP C++ test driver for BLIS CPP gemm routine and reference blis gemm routine. Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include #include #include "blis.hh" #include "test.hh" using namespace blis; using namespace std; //#define PRINT //#define PRINT #define K 1 #define N 3 /* * Test application assumes matrices to be column major, non-transposed */ template< typename T > void test_tbsv( ) { int n,k,lda; k = K; n = N; lda = n; T A[] = { -0.681f, 0.209f, 0.436f, -0.369f, 0.786f, -0.84f, 0.86f, -0.233f, 0.734f }; T X[] = { -0.305f, 0.61f, -0.831f }; int incX = -1; T X_ref[] = { 0.524539f, -0.961964f, 1.22026f }; #ifdef PRINT printmatrix(A, lda ,n,n,(char *)"A"); printvector(X, n,(char *) "X"); #endif blis::tbsv( CblasColMajor, CblasLower, CblasNoTrans, CblasNonUnit, n, k, A, lda, X, incX ); #ifdef PRINT printvector(X, n, (char *)"X blis::tbsv\n"); printvector(X_ref, n,(char *) "X_ref blis::tbsv output"); #endif if(computeErrorV(1,1, n, X, X_ref )==1) printf("%s TEST FAIL\n" , __PRETTY_FUNCTION__); else printf("%s TEST PASS\n" , __PRETTY_FUNCTION__); } // ----------------------------------------------------------------------------- int main( int argc, char** argv ) { test_tbsv( ); test_tbsv( ); test_tbsv>( ); test_tbsv>( ); return 0; } blis-0.9.0/vendor/testcpp/test_tpmv.cc000066400000000000000000000051351422157504600177760ustar00rootroot00000000000000/* BLISPP C++ test driver for BLIS CPP gemm routine and reference blis gemm routine. Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include #include #include "blis.hh" #include "test.hh" using namespace blis; using namespace std; #define N 2 /* * Test application assumes matrices to be column major, non-transposed */ template< typename T > void test_tpmv( ) { int n; n = N; T A[] = { -0.587f, 0.14f, 0.841f }; T X[] = { -0.213f, 0.885f }; int incX = -1; T X_ref[] = { -0.055233f, -0.519495f }; blis::tpmv( CblasColMajor, CblasLower, CblasNoTrans, CblasNonUnit, n, A, X, incX ); if(computeErrorV(incX, incX, n, X, X_ref )==1) printf("%s TEST FAIL\n" , __PRETTY_FUNCTION__); else printf("%s TEST PASS\n" , __PRETTY_FUNCTION__); } // ----------------------------------------------------------------------------- int main( int argc, char** argv ) { test_tpmv( ); test_tpmv( ); test_tpmv>( ); test_tpmv>( ); return 0; } blis-0.9.0/vendor/testcpp/test_tpsv.cc000066400000000000000000000051361422157504600200050ustar00rootroot00000000000000/* BLISPP C++ test driver for BLIS CPP gemm routine and reference blis gemm routine. Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include #include #include "blis.hh" #include "test.hh" using namespace blis; using namespace std; #define N 2 /* * Test application assumes matrices to be column major, non-transposed */ template< typename T > void test_tpsv( ) { int n; n = N; T A[] = { -0.381f, 0.53f, 0.451f }; T X[] = { 0.144f, 0.032f }; int incX = -1; T X_ref[] = { 0.417992f, -0.0839895f }; blis::tpsv( CblasColMajor, CblasLower, CblasNoTrans, CblasNonUnit, n, A, X, incX ); if(computeErrorV(1,1, n, X, X_ref )==1) printf("%s TEST FAIL\n" , __PRETTY_FUNCTION__); else printf("%s TEST PASS\n" , __PRETTY_FUNCTION__); } // ----------------------------------------------------------------------------- int main( int argc, char** argv ) { test_tpsv( ); test_tpsv( ); test_tpsv>( ); test_tpsv>( ); return 0; } blis-0.9.0/vendor/testcpp/test_trmm.cc000066400000000000000000000102051422157504600177610ustar00rootroot00000000000000/* BLISPP C++ test driver for BLIS CPP trmm routine and reference blis trmm routine. Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include #include #include "blis.hh" #include "test.hh" using namespace blis; using namespace std; //#define PRINT #define ALPHA 1.0 #define M 6 #define N 4 /* * Test application assumes matrices to be column major, non-transposed */ template< typename T > void ref_trmm(int64_t m, int64_t n, T * alpha, T *A, T *B ) { obj_t obj_a, obj_b; obj_t obj_alpha; num_t dt; if(is_same::value) dt = BLIS_FLOAT; else if(is_same::value) dt = BLIS_DOUBLE; else if(is_same>::value) dt = BLIS_SCOMPLEX; else if(is_same>::value) dt = BLIS_DCOMPLEX; bli_obj_create_with_attached_buffer( dt, 1, 1, alpha, 1,1,&obj_alpha ); bli_obj_create_with_attached_buffer( dt, m, m, A, 1,m,&obj_a ); bli_obj_create_with_attached_buffer( dt, m, n, B, 1,m,&obj_b ); bli_obj_set_struc( BLIS_TRIANGULAR, &obj_a ); bli_obj_set_uplo( BLIS_LOWER, &obj_a ); bli_obj_set_conjtrans( BLIS_NO_TRANSPOSE, &obj_a ); bli_obj_set_diag( BLIS_NONUNIT_DIAG, &obj_a ); bli_trmm( BLIS_LEFT, &obj_alpha, &obj_a, &obj_b ); } template< typename T > void test_trmm( ) { T *A, *B, *B_ref; T alpha; int m,n; int lda, ldb, ldb_ref; alpha = ALPHA; m = M; n = N; lda = m; ldb = m; ldb_ref = m; srand (time(NULL)); allocate_init_buffer(A , m , m); allocate_init_buffer(B , m , n); copy_buffer(B, B_ref , m ,n); #ifdef PRINT printmatrix(A, lda ,m,m, (char *)"A"); printmatrix(B, ldb ,m,n, (char *)"B"); #endif blis::trmm( CblasColMajor, CblasLeft, CblasLower, CblasNoTrans, CblasNonUnit, m, n, alpha, A, lda, B, ldb ); #ifdef PRINT printmatrix(B, ldb ,m,n, (char *)"B output"); #endif ref_trmm(m, n, &alpha, A, B_ref); #ifdef PRINT printmatrix(B_ref, ldb_ref ,m,n, (char *)"B ref output"); #endif if(computeErrorM(ldb, ldb_ref, m, n, B, B_ref )==1) printf("%s TEST FAIL\n" , __PRETTY_FUNCTION__); else printf("%s TEST PASS\n" , __PRETTY_FUNCTION__); delete[]( A ); delete[]( B ); delete[]( B_ref ); } // ----------------------------------------------------------------------------- int main( int argc, char** argv ) { test_trmm( ); test_trmm( ); test_trmm>( ); test_trmm>( ); return 0; } blis-0.9.0/vendor/testcpp/test_trsm.cc000066400000000000000000000102321422157504600177670ustar00rootroot00000000000000/* BLISPP C++ test driver for BLIS CPP trsm routine and reference blis trsm routine. Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include #include #include "blis.hh" #include "test.hh" using namespace blis; using namespace std; //#define PRINT #define ALPHA 1.0 #define M 5 #define N 4 /* * Test application assumes matrices to be column major, non-transposed */ template< typename T > void ref_trsm(int64_t m, int64_t n, T * alpha, T *A, T *B ) { obj_t obj_a, obj_b; obj_t obj_alpha; num_t dt; if(is_same::value) dt = BLIS_FLOAT; else if(is_same::value) dt = BLIS_DOUBLE; else if(is_same>::value) dt = BLIS_SCOMPLEX; else if(is_same>::value) dt = BLIS_DCOMPLEX; bli_obj_create_with_attached_buffer( dt, 1, 1, alpha, 1,1,&obj_alpha ); bli_obj_create_with_attached_buffer( dt, m, m, A, 1,m,&obj_a ); bli_obj_create_with_attached_buffer( dt, m, n, B, 1,m,&obj_b ); bli_obj_set_struc( BLIS_TRIANGULAR, &obj_a ); bli_obj_set_uplo( BLIS_LOWER, &obj_a ); bli_obj_set_conjtrans( BLIS_NO_TRANSPOSE, &obj_a ); bli_obj_set_diag( BLIS_NONUNIT_DIAG, &obj_a ); bli_trsm( BLIS_LEFT, &obj_alpha, &obj_a, &obj_b ); } template< typename T > void test_trsm( ) { T *A, *B, *B_ref; T alpha; int m,n; int lda, ldb, ldb_ref; alpha = ALPHA; m = M; n = N; lda = m; ldb = m; ldb_ref = m; srand (time(NULL)); allocate_init_buffer(A , m , m); allocate_init_buffer(B , m , n); copy_buffer(B, B_ref , m ,n); #ifdef PRINT printmatrix(A, lda ,m,m, (char *)"A"); printmatrix(B, ldb ,m,n, (char *)"B"); #endif blis::trsm( CblasColMajor, CblasLeft, CblasLower, CblasNoTrans, CblasNonUnit, m, n, alpha, A, lda, B, ldb ); #ifdef PRINT printmatrix(B, ldb ,m,n, (char *)"B output"); #endif ref_trsm(m, n, &alpha, A, B_ref); #ifdef PRINT printmatrix(B_ref, ldb_ref ,m,n, (char *)"B ref output"); #endif if(computeErrorM(ldb, ldb_ref, m, n, B, B_ref )==1) printf("%s TEST FAIL\n" , __PRETTY_FUNCTION__); else printf("%s TEST PASS\n" , __PRETTY_FUNCTION__); delete[]( A ); delete[]( B ); delete[]( B_ref ); } // ----------------------------------------------------------------------------- int main( int argc, char** argv ) { test_trsm( ); test_trsm( ); test_trsm>( ); test_trsm>( ); return 0; } blis-0.9.0/vendor/testcpp/test_trsv.cc000066400000000000000000000075701422157504600200130ustar00rootroot00000000000000/* BLISPP C++ test driver for BLIS CPP gemm routine and reference blis gemm routine. Copyright (C) 2019, Advanced Micro Devices, Inc. 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(s) of the copyright holder(s) 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 COPYRIGHT HOLDER 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. */ #include #include #include "blis.hh" #include "test.hh" using namespace blis; using namespace std; //#define PRINT //#define PRINT #define M 5 #define N 6 /* * Test application assumes matrices to be column major, non-transposed */ template< typename T > void ref_trsv(int64_t n, T *A, T *X ) { obj_t obj_a, obj_x; num_t dt; if(is_same::value) dt = BLIS_FLOAT; else if(is_same::value) dt = BLIS_DOUBLE; else if(is_same>::value) dt = BLIS_SCOMPLEX; else if(is_same>::value) dt = BLIS_DCOMPLEX; bli_obj_create_with_attached_buffer( dt, n, n, A, 1,n,&obj_a ); bli_obj_create_with_attached_buffer( dt, n, 1, X, 1,n,&obj_x ); bli_obj_set_struc( BLIS_TRIANGULAR, &obj_a ); bli_obj_set_uplo( BLIS_LOWER, &obj_a ); bli_obj_set_onlytrans( BLIS_NO_TRANSPOSE, &obj_a ); bli_obj_set_diag( BLIS_NONUNIT_DIAG, &obj_a ); bli_trsv( &BLIS_ONE, &obj_a, &obj_x ); } template< typename T > void test_trsv( ) { T *A, *X, *X_ref; int n; int lda, incx, incx_ref; n = N; lda = n; incx = 1; incx_ref = 1; srand (time(NULL)); allocate_init_buffer(A , n , n); allocate_init_buffer(X , n , 1); copy_buffer(X, X_ref , n ,1); #ifdef PRINT printmatrix(A, lda ,n,n,(char *) "A"); printvector(X, n,(char *) "X"); #endif blis::trsv( CblasColMajor, CblasLower, CblasNoTrans, CblasNonUnit, n, A, lda, X, incx ); #ifdef PRINT printvector(X, n,(char *) "X output"); #endif ref_trsv(n, A, X_ref); #ifdef PRINT printvector(X_ref, n,(char *) "X ref output"); #endif if(computeErrorV(incx, incx_ref, n, X, X_ref )==1) printf("%s TEST FAIL\n" , __PRETTY_FUNCTION__); else printf("%s TEST PASS\n" , __PRETTY_FUNCTION__); delete[]( A ); delete[]( X ); delete[]( X_ref ); } // ----------------------------------------------------------------------------- int main( int argc, char** argv ) { test_trsv( ); test_trsv( ); test_trsv>( ); test_trsv>( ); return 0; } blis-0.9.0/version000066400000000000000000000000061422157504600140630ustar00rootroot000000000000000.9.0

öEÓò#*±O–ñ¾’اè¨Â¾R°O‘w…}EÒéݓ󕊀}LæÓÏ¡s7êÌ|®‚À§àŸ¾’&OC|%S_Ià“’ˆOw…|&"Ÿ¡ ùêUÈWÊò¹ŸD>—Lä+i€|.™Èç’‰|Eä+%ùÜS _Iäóð€ùJ0_© ÌWÒ€ùœ†ÌçAæóÓ#óí‡è ÌW$`¾XÉ`,0_‘€ùṦéFà+UøŠÀçu@à+i|z­$ðyÁø\¯H|n-ÏÅøô6ðéM$àÓ›HÀWÊñ•\@¾Ò _)ÈW$4þTÉD¾*Á~Ê7¬?-ñ§Œ ‰|º6DÖŸÜilþÉ-ÖæŸÜQmþyiþÉÝÝæŸc½%YÈüsÇg=›òØeóO'Ëüs¼±`¥IûÏEõߘ/‰Rÿ=ü'õ©VÿYõŸÔòRÿ=ø€(õ_ÃsVÿYBõŸÌ.¤þ³z’ê?Idÿ)ãÙÚš’ 8…ù,ù'Œ¦Šòï&¼Ñü“—ÒØü“!¤lþÉÀS6ÿÜ“elþ¹Á½Ç柲ʄùg§!'Í?ÚWóÏü²'ÝŸÓP÷áH3 uãy§Á‚tO§Æº¿¾iþI?ëþ"'2´AïžFfôdmIГöÔ:¾­SËFC‚YÇ÷>ô¤£Žo§POÆÒñ“pj„zÔ³›õŠë<ýxsŽXOä$Ö{¨‰¡§oK°§ßFeƒ<ý6¨Xíé'å¡<ýD+b½ŸNìéÇÛ9 {<ñÊÑæÚf=Æß6ëCö³²žNíb=WEÖÓ!S¬§³3YOU‰õV¬Çs³P÷‚õtrê)QOmêqó7êqC3êñª£^¨+ê¹¹D½&kU¢BF=ì…z–²B=žzó8`Îã}â<üdz‹(e˜ò4 Â<·Œ˜Çk:Œy ÀoÌãÁɘGsžFAœ§çÉUUœç\=µY ÇÓŸAO]7è®Iz.˜¤'z%é  z ÿ_@OtHÐãQÀ¤Ç3w!= @ëK §>ô˜IœÇÅ$ÎSŸÌyâEq‹!æi9dUà–øT¬ÅÀ'¸$ðÔç‘÷\ yßXÍ{‡t~ü|ªLÂ=A"qo§ÎϸGu¨q¹Œ{JÜÓP÷8ÂÂ=%î …{÷Wo?uÓ¸'Õ!qÏð)ÜS.âžA’¸·Uñ¹dៃ¼ýÄÔòös&zûiÍØÛsÞ~BV{û±Åòöãø÷¼>ˆ{~Ã÷JÝÀ=ó2qÏ+†¸ça'î™ É{~|>­|îÏo ŸÎß>Ù ø‚įÅÚ³´Ä'% ˆO-kÏ—¦$>!„ˆ/p>y”ÄçbI|þ@â+¹@|R2‰øÄ8">ª”~G°hƒà9™¸úü½ÔŽ)âËuË 0}þ†U~Ô þBÀ¥Š÷ƽ8Pºq •€â@zïü¬­gQßÑÖS ÚzÊ Ì_dUJ”(9P† æ@±­'¨È2ذ­çA'/ÙzÞr0Ž?ìÿdì)K>{¾Ò/ïg“ù'Œ=© †D609pœFiIcÏþ¿ÉÑì¾8ýµß[‚1 «ÓŸŒfD‚íè_Hð>I3$Áûbà’`¼"¯…ã=ÿ,_FWˆ² Áx.^~vAÙç#è3à x·MZ@˜¥´œOŒQ{+ –$ÀÁØQ6¸ÎM«]õwÀÁñ†nÆ3ÍæK&Ð`L’¶Ð nâ êêhÑ`Dn<À‡0Ky÷„48<#ª€ï~ÒÙ48èísÑúEpë|UïÖWÇ¿ØIa”™,“"Ÿ Y0æpÎs° ë FÈÕïï~†‡,ặEëA"Ó±–,è\„Á¶e¼ ± ®  F¦¶øý•ªƒºö]0x?çŒ5ô.Öž±*€~¹_EÁ°ïtqPVúg³ ÿþbFÏ«;ŸZ´%ŽÑLbÄê§c4?óBœ¥‰’¸ÊPŽ~–rÞèªö‚RJŠX~ý½ãE÷ˆåãð›âE×ÈÐA ­+tôÝ”à›δ¯‚HÿRÒ Û:öÛI1àéˆ×îûenÅpÅy}IÃ’'š%Õ8Ñ(ɉPRM£’%Z%•(Ñ,I‰XRI£’#Z%•Ñ,I‰XRI£’!Z%•Ñ,I‰XÒˆ"·ê¯ïžßþv!ñý!Eó.ç½èæ%Ìsµ¾8àÍëŠçje,÷y™è\­óÝ’±Öˆ§OÄŒµªàcÿ=r­ºûE´]€Ñ˜i}®Õ’+> Íȯ›ãT¹#"¶z_†ÞÒíg‹ª·Z·òÏÚÃ’‘+XF!<>Ùú‰P¾¶ŒcÎ_ˆ´«L®íÑUŸˆz²U…Ç8$·\¨hÊxÎUêbûŽUŠ ‘Còä*µ$¾ =KEáx–'ûѬ§6ïØžôÙsšØTê`Ƶœs‘ª9G>gÿ|r‘*G¼æË¼|f¼’»Î–0q}ÖRâºÔeF…7YF®Ç»éÅíÌufÉñ y޾t?ó¾Ô^Ó„2p.R®œgzbõlá|E˜‘ë±Pžy_êS§b˜œgmÏ´ûx—rî «4+ŠBï’¥aCu±=7T žÜPý$Ï'7T¾ežóņªá‹˜që9è3Àò2 í9¢?óÊÔ^çbÜ™zåUDÜ«¹®ùi£ÖucGÕ ‡Šmyiê2 ÓÑr™Y׃-Õµ‡îK¹g®7·T ét:¾kCO¸,Žykj}>qkê¾×Ñ™·¦.â¾°¥ª}óÖÔVÛwߨR]Nã–*IÇ–ê’ã“P¯¯›Ð6õ²K<óÚÔ§¬ªù5æÔÔšw¦¾µšygj½+à™—¦¾µóÒÔ{‘\¹£Áóe±ÆçÕ\¬ìõ¼4µÕ§—¦öå­6/Mmµ6T Cƒù,SÄ•©~%÷i9«9—¥Ö‹#ž¸+uy¥ÇU©g„“éjOpQª;¥./Ü“Z mØAÕŽ^5åO\“º è8&ÔgW¤^5CD^<.H]VJ°Ï³B?Z }`*ë2â­‘{`)«N›™qU’*Ü3›ˆ+i@q o-ŠÛâ΂Jqq¿|ž™IqS\)n;p²ÅÅÅõOÒ!(.2å³#ÅÅ…¹ùìHq‘ëÌÖ€â¶`Q\‘€â³[Ši [Bí‹ÄpÛÑ0d8—K†‹4ù¡ gû#sá¶Z“d¸hJOÖÃm'´„¸R* ®dÄ .jÎILˆÛNÄ®ÄEU9¯ qÛ‰¸ñ‚8—Cˆ‹4ù\q% ®”ŠÛÎáÜK"œ›G„ÛN¸íáJ \)'n‹e3Ÿ-.$9×€pî6N™„pqñò‘„ K…ù]IWÒáJ9 8µO§^‰â¢œ|Ñ“âŠWrâÔ aœ:*Œ+-Æ9 H.:?÷ˆäªdîL®›$çö‘äJ\I’+\äz²5€¹R`n;óʱ\iX®dËYB–‹\Ó°Q,çrÈrn anK;£Ì•,€¹’%i®$͹“¤¹’4WZš+Ð\‘€æÂTfO*͹ߤ¹"Íi@ sEбVYYÎã@–s& œ;Eš+М3%ÌE±wÂ'`Î)’åJSÀrn YÎ¥å\3YÎååTQ®°«º&\© $ %5‚ä\ @ÎpœÀ8 @q¥æ¤8¥ Ä9 n»ÒÌI ç¶’á\®$ Ι@p% ®´çL¸’ W$ 8Kˆpžß¤¸*Á~ª@Š‹‘è ['·T•œWŠÅ•b@q%(®H@q%(®”üpKåèãÜ>pœË(W~&ÊéÑ‚äü;A®üžç߉q¥ÀÄ87 çVã\D_WAqNç?â” W$ù`¸’"Σ†s™IqÛuä!$)ÎÅ•“â\@B\IçÉpú „s“€p®çIpþ ç*'ÃEޤ°d¸RC2\$Ãyà€q¥È$¹"€J[H+E@ ÎnüŽhÎRÈÁê¾*ä³²œ£}[!Gm+ä,¡BŽ×”[!Ç E¨+(ätCrº4] 9… BN±¤s*äŽû%*å"†AOMrŠj …\‘€å-L,§èób9]›!˜SŒ}ÁÝ‹å_,§@÷b9+=Ér*(犈rN‘$§)Drºi@$WÒ€ää[/’s¹¹Ò8€\H ÄȹK¹’ $W%¹õXB”+ œšC’sU$9Ís¶å'HÎ’«‚Üvü”Hr® WÚ+5äJ19KrEs99w’ W$¹"Ë•rÀrêQNw€åœ$WÚ—$Wò€ätI® ^¬TÌ‘\‘€äŠ$§1Éi͉äÔo‘œ&±HNkW$§^‰ä4Z"¹Ò\iH®¤É©ï$9WN’s'@rE’s¯Hr®‰$W%/«räJå 9Iν"Êé åJ. œså\;Q®¤Ê•4@¹’æ\ºI”sc€r~vD¹’ (WJÊ P®äÊéE ”+•å<¢D9—C”+iÀr®0ç%Ì•\€¹R2h®äÍ•’AsE’8ç#Ε‚“çJðœ%ä9¾„s~˜Ä¹"ÎyÉs.æäÎÊÆç<ä9÷›<ç5C +•ƒèJÉ@º’LW%¹·jøu^Ò€º’TçšHun±Î½"Öé”!¬+%ßÖ+rëJšÎÝUiv%ÍÃÝ•#H°ó£!Øy,vîÁ®Hv®‹`ç¹°s v%À®ܼÅBҹŪ`€])`çع*€]<µ€KÙyì€v~p`»RFÂ]É’pçI¸ó`îÜÝž³N%<ØU%º+ùïœxç à;w|WR$ß..T-à»R®.´à^V3¯ðJ†$ЮH€v®Šhç4D;×E´ó8íJš³ö‘dWr$Ùéõ-²+MÙ•4 ;— °+™v‚]I°s v®Š`ç쪫sìŠ`WrìÜB‚6I]ÉÕ±³*ÓãuKKÍ;«’¼ÜYY.Á.Òì@=î¬ÌE²+¹ï¬û¢©+iNï¬Ùs¢]‘íJ9@»R;Ð.NiE´+¹€v%Ю¤I´s‰vδsûˆvº¿PhçA&Ú¹&¢]© hWríJå@»"Ú•öíJ9@»RÐ΢]‘íÜf¢]‘í\Ñ®”“hWØ^] ÐÎÝ"Ú•\@»*y¾,Z¢ÐΣ´sÝíÊÏD;— ´+)íÜe ]I‘hW‰vEhç¾íŠ ¯­L´+Í ´+O´óßvî8ÐÎ5íJ–D»’"Ñ®í\-Ю@»"H´óàíüÄ€v¥á/¶O–´sÃv.hç2€vEh箽çòvEhW*M´+)íJ+íJŠD»"H´+­H´S-߉É\\ç"sõ‡m¸|X41TÞEQ,4·ujeHs[§r‡4·=ü”š A*HsQL+F—# µ ¤¹8<›Ëñ›j%Â\äI a®J`b `®”˜ ðhsÉK‡lsi m.-¡Ñ僠Ò6ºt]>7M,iti .%‘Ñåƒpb2ºTÁ2ºt&]Z@£K—B£K§¡Ñ¥%4ºtU4ºt94º´„F—–ÐèÒ%ÓêÒihv©42»T™]ª=2»t.š]ꉦ٥ŒÌ.-Ù¥K¥Ù¥%4»t=4»´„f—n/Í.]Í.U²Ì.-¡Ù¥J–Ù¥J–Ù¥sÑìÒ¹hy©‘å¥Ú#ËKç¢å¥%´¼,’´qÁ´¼Ô¢å¥ÛGËKf²å¥%´¼dûlyé4´¼´„–—ÎEËK§¡åe‘¼ëеå¥ÓÐòÒZ^:-/†–—JCËK hyÉñ’å¥J‘å¥%´¼t1´¼,’w]±¶¼tZ^: -/]M/-¡é¥%4½TÉ2½T™^ZBÓKÕ.ÓK—s.]é¥ÀôÒš^ZBÓKCÓK§¡é¥%4½´„¦—EÓKIdz©ºdzi m/‹¤kÅn«ñ¥K¦ñ%מ­/5¢²¾t.Z_ZóK h~éÊaé$´¿”Dö—ª[ö—–ÐþÒ¹Ž/{¬ 0†˜NC L5P˜ÎE Ì" ¦sÑÓ%ÓÓZaÉ»®X™aZ3L h‡©Rd‡©ÖÈÓ¹hˆi 1‹–˜.™–˜zÈÓšbºšbºšbj~ÉS¹dŠ©\2ÅT›eŠé4ç—mV¦˜j L1]M1] M1] M1‹¦˜.ùù²ÍÊSÓS)ú¶Ì-šb:l1ƘNkL sLg9¦0Ç,‚uk…=¦Â“gZØc:? 2•™j-2™=ZdªPZd:,2&™.ô^V3M2Ý ˜dºHØd: l2]Çûe¥UfhÍBi•©Bi– °Y¦‹Xß 4Ë´f™À,³žµÝ4Ët ˜eZ»Lg]&¿#ð²io›±,*îe蔊{qý(å;¸§Ã¢pïyW»a47H÷Þ+½$Œ{á í½êð…1î¯Ï$ÐÝ盾TÒÝmŒmÝÝ6_3Uw·1h‹twÛÖIw·áÚsëîŠ_-¡înëtù£îÎ*ïŠÚ;K¨½ã-GÖÞÅEÏ‹]f•äF#í]\MýQ”wúMÝø¼(5wPq·!¸wE‚‹–Pqg w–Pq·#´w’Hqg w–Pq·ãâv+îœf*Š;K ¸ÓâNÃ-ÅÆ[Š;–ôvŒ7n½%ÔÛ©qÒÛih¤·SUÒÛYB½(½%ÔÛm `$½%ÔÛiuHo§Õ!½K†Þn,¿ÔÖKoçLÐÛ¹ÅÔÛqýXo·ey«íœ„j;6Øj;K¨¶³„j;¶Æj;§¡ÚΪí\;Õv–PmÇž[og õv.ñ–ÞNÍ‘ÞN™¨¸Sk¤¹SÝÒÜñ1XuÇA¶îÎåPwg •wœíVÞqšZy‡¹mÝ+§îN•Kw§4ÒÝ©*éº;Kκˆ¬¼c[¨»s5ÔÝq Ywç4ÔÝYBåÊ¥îÎ-¡îNI¨ºã”•æNÍ•æŽy¤¸s*z;5Nz;g¢Þ®HúºR­·SÁPÛ9Õv® j;Í3©íT‘ÔvzŒRÛYBµGFZ;C­’Pi§¹)¥%TÚ©}RÚ©êìÔ'éì\ÌóeGµÎ®HÞu™Jg§b¨³Ó ‘ÎŽ‘ÊN##•’Pcç$ÔØ) v®ˆ ;·Ž ;§¡ÂÎi¨°S'¥°S.)ì”F ;§¡ÂNM–ÂNc#…žv.† ;K¨°ãŒ•¾Nªë\u÷®z.‘RJc ®SET×q„'Ö¹LjëT$µuJe „²NURY§ÐÕé7Tu.ª:7¢/ÃGUÛ4UuÎU+ ¦N Žš:@MÐÔ©ÔÔ¹ hêø8¨¨sw}ÙQO§FRO§NROç §sèéxD’žNuROçÐÓq(¨¦S%Tӱ﹌µtÚ@¨¥S£¨¥SPÒé7tt΋„ŽN#A[QÂ'¿q»B:N qÌ)áH)Q8äŸÍƒøûŸ<€+°ª-‰S†è¨úéÅcj¥{,åPRËI™ÊÁÏRÎ87-­ÁïRÆ”°„üñ÷ü¾óQ7rò¯FCn×oœÜž?:ù›ùðÎ['–ˆ¶_§Õœ4qæ^R¡$EFI5(2Kr"–TS±$EfI%(²JR"•TR±$EfI%(²JR"•TR±$EfI%(²JR"•ôB'¿÷<4|?rrû¥ÈÉí"'3 ~&ròHw/Ý—ÈÉߟTßFNþ ¯ªŸ–wÏ7/¦Ÿ¾7Uë»êgæéZÆïŽœÁœŽöýÀÉ£óõ?ÿQaŠ-pòÓøï8¹}¯’þƒ“߸ëfWšaœ<ëã›i}ùÜÙj†l‚ UÍXÁï3÷ÃÒó±ÎV3 òØþ#2_\C²çODÕD4ßq ÉÈ|Œ|ü¾Ç1θ›C‘ùuù}Ç¢Q3>ñû^˜q…ß÷>2º³Š¸36â<¾cÎf38ß;ƒ²}8€ð8VÍ(zGn:oDd»Á˜}³Ùú;Þ ,7†âÉ C·3–L!y—ø}Cr´Ï zHÎk‰à7$×ñ½#ì¦Z<ï» ÉÃ×N\:ç¢É9·ÉZòµÎ¶¸þóZF=®ÿ|K|Ø!i'ç:ëîÛ——LâZ¿¶Œ¤8Ïýe*áúÏò8ã®§ù޹òæ­\ÿYZ÷®³÷Ö\wn¥~7Æ ëjíýXóô7û û?_¿BãòÏk)4.ÿ|–BÜòàÝõa¨[uàIí¥§Ñsb+Õj‰Ë?çÛ¡C·®ü¾ÖbòVs:.ÿ|—ÇåŸå9ä•}èaä[ÍŸûs݇âîÏãô‡d?—(ÃCrä>ʽ!yø2D'ß³-‹2®þ\Ç÷½·/“|F»Í3ì‹rÛýåÄíVë–±lûZ÷³ì¥“¶Õ7õ¾eÈr6%Μ9ÞûŒøºæ9°§rĆ”i¸Øãõ¾žâ…Ê=+çs¼žÖƒJ¼ò!pZÅËð(x9šï1E곎g}pM/öT¥‰xWÝöÀ¦z燿Y¼È’7úéë3ÇKýß+Ü6Økz-_u‚ºæ‰9¸­ÅWÕ<'·wÑs~rÛ€5|h·µ7.¯¿?Ämí=E]“ÛÚ;O³â¶ñûÁ!<Á­½7î­¸9¨2À­½ 7:܆ }fŽ;þÜq{7¸m†\NÊJtkñ¡õÈ Ý‚è6{. [‹O±IV‰nC+ [›=1i¢[{_|»˜èÖâÛíìg¢Ûø}‚yÝÆOQÖD·ˆqt›‚'Im¢[‹¿W™è¶ÅìÊݶ ÷±ÝB° Û¶‘Ä€nLtS|h¢›ÂLÝŠ Ñ ÖAF·îÝh$6‘Ýašè¿Af‰nEì¦ðÒd·<ÙÐi«X~ÎÝ&hìJ¶Kv é)ÙmPŠImî7‹ñ¨¹8Én*XìVÓ$»Õr’Ý [ì¦Ð×`7Ç»…„ܘìVó$»m»Žœ`·"» H@%»Õ4Én¥d°Û¶%= ݪàÉ©!Á42ÝÇ 7=4‘[y ·*Ir+ƒx«iÞ¢jœ.o%ø­ ùä·ò˜€p5Å±Ö Š«)’âjš¤¸òà@qexAqåQ‚âÊ€ƒâIšnî<”Nˆ+ q‹äÍæéYâª$!®JâÉ›ÍcÕ`¸šäÆ Ôy W2%Â)v;nÛuÂÕ‰p5M"\©WªÂÕ4‰p¥d \•$ÂÕr.|ÛtšD¸xl;$ïú;®´§(öB¸Ú¾D¸šëÅZVÝ@¸’ WjÂUI"œä áJ{&ÂÕ<‰p /„ ޲@¸*I„«¹ájšd¸Z7,§ WÌd¸ò\ÀpžZ@¸"H‚«yáÊxájšD¸2@¸ÚX –ráʳÂÕ4ÓŒºÔC®äÂÕ40¥v9@¸šÆÔ¥œD¸Ò> \é'®¦i×—>L„«):6UKžÆ>°}ïõe5€âJÝoypØU»W ¸š ¦Õž7À¸šæÕ%ͽÎk`\™¡À¸ÚX{ãª&Ö¥œ»êW’+½É•ƒäjš$¹Òæ7ïy0o%É…#¶¿—=|%¹Ò>\¤Ò‚äjMIrµœ$¹šë½ÙðÈ„9ç!Ì9aÎ5æÜÂ\Í•0WKN˜«iæª$a®æJ˜«uÁáPÏ!a®ö þ†Uò~.o~œǘ0WrQ•­YAž«i gÉ¿#j²´qÏÔ”mH¡ëP!A'p*ãöjê⮼^ª¸3c>KÇXÊTÅ)\uq UL]œÕ{ÐÅ…ÎñHÍXêâ"Ìï›ÐwϿ߄ÂÔÅÏ_¨Ž+‚TÇO¦6N7®Rw„õ^æHm\˜jf#¨ï«;á(µqÎ2µq.기íòÍà˜/ w¨Ž;^îH7žÍžUB}eºÐcò Žs ¨ã‚ʳ–dºÒŠd: R·Áh]ê¸úZªã¶¨Ž“6•ê¸0ËMdƒ:NêPêãœú¸¸u)«…>ÎY s-PÈ©ó©»E«PwFû5¡cVÈ IæA!džY!W$PÈ•\PÈEf€UBÝ™3§$¿"–4PÈñV_*äÊo(äJ(ä8,‚ºš&¡îÏi£ú-uЋéJ¨s1ÔÇñ9[·ÝŸ«:έ™TWF˜ú8>Q]iKB]`ªãøduz¸ÖÈy€©‘‹u¹*å\y*å\.õrò u¥@]©‡ª¹1w”šP§©)¨+£ ¨+½ÔÕ’êj®„ºÚƒ÷ÎG{/ª¹R ¨®<[P]™ ºš&©®¦Iª«uA5·ÃIXWzEÕœ[ ®«uuc¼€ÃäºZnrÝ"yÙ‡{UÍíio'¬+(æ\ ¨®Ô ª«(æÜ^P]­û~×éÊ’Ó¹& ]© HWîDº’%‰®TœS$ÏÕ"’çJžÄ¹2}sU‚«%Ýgªä¼('ÎÕ߉s¥?๲l©’Ó« y®¬cð\?ªäÜojåÁ\y,€¹*y°¡º¨åJ]ï— š9å!Ìyòæüsžj„¹šëÚÖÇ@˜«h抚¹R24sU‚-•S?a®öé=ÖyD˜+íÌ•4ÔÌi´¤™sû¨œÓ’rŽíû•ØÈ¸ÉÅBú!%¿íR±àƧN‡wm À)Ž2 nÓêN6J„ÛcG(Z¹!x¨ÿJ„‹WE¸8êáövVkʽIëvÏ?Kç–§«|HpŠÊL‚+YáBÐ+ÂA"\œ7A\‰p{ûbPYOm.›.h´•§ÀÐD¸’"nì’úG œ‚K᪠R;K"\¼ˆšÉZ&ÂÕŸ™)ÁŽ`{¬ç†á\.IW×ÅVåï8…·&ÀA\$À)fœÂRàÊßàX§øMñèÄoê™øMÕŠßJ1'BdJp!ÚÞE+&ЛÚ"z«åNT6_ô¶Hžì€KyÚ×Ö%½•\ ·’øV%‰o5Wâ›Âû ßJ¯ÀoµœëKžä·Òbð[Í“Ws%À鳑®JàʳÀ ®ôj\© WóÏúû\d àªäÞ8´м;ç?í^æ·ø­Võ(J¦ˆ®y“ßÊ0€ßJ)à·*Ùû—i~«åœk¸Lñ[©üVÓÜ×VRüVKnï—‡pö¾ ø­JÞýËD¿•Ö€ßJ¹¸R7n‘¼_ú‚+OWjÁÕÚïµ} ¸ZJ?¿ô§¨œB¸šæýº p% ®ô WÆWÓ$Ä)ò( ®LcP\-åFüiK’ãjû’ãÊØä<ùÁqµ ŒSË$À¸RSÛž¥`\•0T­ 9·/Æ•w0®s_0®¦Á­N`\©œ·:H!k]ït¤3h­%;6Rµ·3l­†WӜ׺#áÊ@tF®ÕƆ«’v­=˜Wëéï×<íËøáJ Ü"yëa@W‡¶T”û0‚­º€+³ê¹Ú—És_KF±UEíYNX"¸’äÁŽšJ ñ[Iñ~ÝOoN|+‚ãën z«’s=E€Þª!aÜCÐ[©¨Ý_†ÿÿãîMvuÙ‘,½¹žâ#ð†ô椉 ˆg4Pƒzˆf¶ó}›¸7”T5:çç¦ÓétÒÉËÌxkÏ xë?Ï·{ƒÝ|Q±›‹%»¹§’ÝTÑ­%œÇ·þ$7W…äÖS¦&Ó÷Cn½6÷öí$·ž’PÚ½ ¦§¼ßþMrkw¹ù¡n=Ëñ~ú7¹MY~#ð±Å¶ûcBÙaìúÀa”DVãA‚µ—nL„µ~Ndµ—æudµ—Ötdµ—ÞWdµw|å¶øÊ5аæ)·m´®£Ü¶ÑœŽ°æ›BnÛ`“%½m£Áõ6—½M—ÖŽ ²§ô6Õ£ô¶þWÔÛœzÛV6 ’Û60ÕbÍy4Ê•0²Ú± YLnUkÕ©X-.™Ûô ”ÛtI²ZÿYçÖíоÉjq†í]9ŠÕ\q°Z\òñ~‹z^Ý„ÒMZk—­µKŠÖ¢5j_´v„Gó/„µöç‚5· `-ªy~ÜßtÑZÄï¡{YÑÚZæÓK´Öó®ñM ×¢'m*ߪ½l¡€k=OžäØr®µb‹ÖôH¢5½ÑšÞŽh-Ú‰Ö†Ekí @kz릵×6ŠEk:»X´vìvKßÇ­õr‹ÖZAk=OÑZÏS´¦.&ZëW­±?ÖZ–„µÖ4€µÖæ knq°ZK(TÓW@¨Öš¨Öš¬ÖªVÓØ«iˆÕúUïüü«µúƒÕzJ±Zëä`57P­  Z{ ZkL šFœPMßL¡ZkœDµ^J¡ZO)Ts›ƒÔZ·©µRkÏ RkƒÔ\0@­=7@­u€Z¿Õ|?/ Öo] ÖZ ¦/·@­ßé½~ŒS€Z»7@­Õ Öó¨µÔÚ½ÔúÆócœÔZ¨õ<7&M='@­×ïÁ´ÉF¨µæ"©½´ÄNPkµ¨µúÔz!çÆn¾3Ó§#‡æOØCƒÔzžkû1TAj~€Zë µ6ÆÕ>¿kusÕZe€jššjjZ«/H­Õ¨ÖÞ P­ß|b2õͯñc,$«µX­µ0XÍ-Tk•ª9 H­Õ¨ÖSp²ºkVk㇬¦¦ªµHTëu¹ö¬Ö¬Öê[¬Ö‹Åq’›ø^̧zÝ µV_àZ+¼Öž¼æ›'®µf®õbq°ºû qí½¡‚×Zw®õ;?Ûw\kï¼æ<Åkn`òšêO\ë—óûlîV¶V̸¹Ì½ ™Íùí!ä57 y­ç¯½ð˯ùÛI^ó|E^k¥€×ÚC×ÜV¶OÊ˯œf“tEú Aé ÷®Á?»Ù¤”® Ï$$¹Æj’Ýè¸F”{öB(GW)±œ( ¦“«0R„éä×n2V’•»Éµ:®p´›\éœßâïkhWè‚\Ĺì wÌãÆäXí1š/œ­ÈÅ((—=€ŒÈÑö’wßw#ʳ8î9%9n-dŽÝäªI¹äâsY9r¢B ä\$@î¥,AîE|gœË@“ Áárº€ ÷ÒýQv“ã+ºÙ‚Tv“4ø¤Ý¤Mi7)cL€œ¬Hi7 »›Mªšà8_ñtK ›MÒ„Tf“69ü]³Éðõ*ý¾Ù¤,ˆd6é˜M®Ùóñ…;÷‡na4›<6I”Ù$Cõ4³É—¶,2›tšM:f“é8E³É—_{ÙMª~´›ŒE>®‚Ýd̳¸ v“ëô £á¤jX†“~&N†³,ßÊÐ#"b~Pî\ýKZN¶XNF¼Ð;\¯ ,'Cg°œô½ÊrÒµ¡åd»&-'‡=€–“­ XN¶<°œŒI °œ\Wå-ZøüZNÆç˜ìVf«¡±m@Ëɵ‚Ã4\–“þMËÉuo¼]ZNúÞ´œly`9é§¢å$CAÙr²]Ëɘ•>AMÚ“Ór2èZÜË<,'-'[)°œ<û,-'Ý6´œôSÑrÒWÑtÒíGÛÉ–¶“ëµî ‹„|¡í¤kHÛÉ–'m'ÝZ´\DÁ +°\Åc1DãÉvŒ'ÝZ4žt94žtmh=AU?AMZýh>é»Ó|ÒmQæ“k»`?ÙJe« ,(Ý~´ l儲]Ê–Ês¿mìꤪíÛEiAé×K J7(-(OxÒÛ„Ò7‚¥û,-(ý´ tŸ¥e» ”~&ZP¶ ¦e+”nsZPº\ZPºOЂÒmN J߉”­XP¶«`Aé÷K J?9-(ÛUiAÙj Êó*‚Ò}”® -(=¢iAérhAéúÑ‚²¥À‚²§ÔÜê6¥ ¥ëS&”~JšP¶0¡Œõõ׆ңŒ6”~ã´¡lµ åØN°¡tÉ4¢t[ЈÒåЈÒ5,#J·(]?Qº%hDy>äYQ¶ÚÀˆ²Ý F”~ç4¢ô°¢¥žF”úJɈRåʈr-¶Ox÷cQê©dDÙSjvÕsʈRõ“¥z Œ(ÛU0¢dP?QªïˈR#XF”z2¢týhDérhD©V—¥ŸœF”\ã´Çû~?óÑóSÿøÍ~ûùtýN§ý–ò—c¯—¶áÿ=~ZÐãÿø AWÃ"{Aè9?£R±UWJ®h󘎚Ǟ8Tå ×éšûž#çÐØ;„ÉÎsäzÇ©6LŸ3çÐx©µûŒœBãP«ÚxÙŸ™Sè}s/|¥äuºpÕUqÇ“}2¡¶‰ò«Zƒc‡qtç]µ¹pïyÿèGWmõ”û¨÷à×6Q”|à^ÏýyWmµ–ˆƒ;_÷œÚÙ^T`¯Îíl'wÞŸ¦‰£;¿/á®SLbë£æøã.3×öHw©£ý^!F¹ePrÜ¥ö%ö{—BÚø.‰ô½±Ö9žÚ jm÷”FÚŠyjƒ¨5ÅSBi+8OîŒGzpM ¥=GmµGxJ, 9m ¥6ˆ"}ø)¹”oå)±´½Ø§ÔÒÖšOÉ¥­ÅßÒK[eÞRL[…ß=Ë}ÊÀýxK2m¯ö­Í¡ÖàoɦýFµ9ÔSJ8mOýÖæP«ð[Òi¯LmµvxK<í%¿…Uò¹…|êú[-õ²Ï­ôS·Þ¹•€êapn¥ öbJBp®ò L¨¾ªDÔ^™RQû½JGõ[8ãØÎÙ;À¹=?JyÞo9·ÒRÝ4'ílwÚKKuc8µ³_UZj«Í^Kd¿˜s/-Õ/æÜKKí÷*-µç¹Æ7Gi©­E÷ÒRû½KKí)¥¥zža2ó­ßQZjOÙkJu ¥¥º#Ÿyj'Ôyœ˜Oõ*qhgO)!µ5'¶ÚC¦T~ݵùrÞõêþlÜd¢ßûÛ7ŠÞ“â8Ðïzùb$úµ€g@¿è™S* Ømü:q0ŒÄ~Ñ_vY±_èÍ„Áòd ¯¶ÐOnÑb¿X*ã 8°ŸÄ~ÍP'ÙÏf„d¿fÜök~€¿Uqð áoý…ÆG€?›Fþl±ö «q‚g±_ô¨ùa¿#–¤W¶¦Ç‹ˆìÅ~k¹Jï|°_t³×û)ž™Øo­ÛþþA?ÍýÖBˆô[K.̽U²_PÃÓØOÖ;b¿¨Þk`G>,ö‹êÑb¿Ù¶!åUkSì'K ±_<Ã8û­e™ˆ¬Øï¸°?)ö[Ë'¼Íb¿ˆíLû)Ú›Ø/ÂݸS±_ `&ûEI¢Å~­Á~kI(†,öû¤”Íw«qÁ_«1à¯Õ0á¯=à/Œ v\Sð'³(ÁßZ‡qîüE»<Šk'ø;bªØüõ«`ôígüEV«oÆØûÉHKì'+-Á_{À_{LÀ_{(ÀŸbñ þ"…VðÇu‘ÛŠþd&ú“˜èOf^ ¿ž£èï“òðXcX}û©@ñ D½²ª[Ý økmøko ð×SÆþiÀ_{HÀß§`à/ ZÀ_{(ð_k –ΔÀ0p»ˆ{erú€ìŠþÚ#þZ…“þt¨šè¯½7П"3ŠþZuA=¥èï“RÖv´Çýõ€Ñ·ô÷I©HÛ@Пâ>ŠþdÆ'úë)Eí©@=¥è¯½:Ð_{- ?69ÐO?‹ûZíÁ}­’ûúÓÀà;6„RÅ}ñ„X}ýÂúoèGƒK‘ߢ¬‰I~ý¢"¿~«"¿Ö7A~í‘A~ëÅ×ûy ¿ž‚óýü˜ ¿OÊÃNü‚É·k ôë)0ùÖƒƒüZBZ|¯vÀœ ðS”O_ÏÃè¢0/øµ÷0¾¨Úì×^7د=%دu×—¶²Ó¤W3jË“æ²~ê—ö²ª௧ÐföÅy/„¿Ö'^Z;8HŠð­s#ìf[9ý*[Îâ9N)øóSþüT¤?½:ŸŠðײÀ²e#¤êKöóû%û¹ýüÜd¿ž'Ý!è¥ûõkàékÀ~~—d¿Ö`¿Ö`??&Я=ÐÏ/è×è×ó¤C$Ã× ýÚ#ýú#À#²]ÈõŽÏú}RjBm)…~­ _{y‰~Ÿß5¡ªË’þÚS‚þzÊ…¨Öýõrà‰&þ –-ýÍ<€¦Ik½òwhvèÝZQþ9±ÿ»éÏ/ô§h¢¿Z¸ý»áOý‚ìçV&üùþŽ÷&áÅM%öõ‹ ûZ]®ƒ¯€wbT]e)èk¯à`X]ßúý¶ÂÁ º*Ô×SUW]Ô×ît2¬®SÎëz—Ô×îêkõõõŠ_‚ŸQuÉ|:îYÐg§ B_»Õ`\]• èë%ýÇï‡ï€)Œ¬ë”‚¾ÖVƒ¡uÕõ}í-úzm úì„CèkÏîkWûÚ½’ûZmÀ}Ÿ”ÁuÉ}½×õUÅ}í£îëµ)îë%Ã4¼]õn?>—ྖ'¹¯ÿÞŸ9Šû“Ü×Ê÷yV ÷}R^†RgÉ1=]2ƒë:åÆœÚR0§:åùQî+·+¤€þZmn×U) ¿žrü˜T‰žëˆýªÂ?Ç7%þõ<…½œëGýî³*ñ¯õà_{À¿–ø×ò<<ãÝy`ÞSžïá9¯Ï¨ök`ÞSžï'ü×pÚ{»æÑˆ~>ø×Þ&ð¯ÕîåNÁ‘ï=å;[ÿÚ½_F×Õ½mÜÿz98l¢¥0º®ïÍã&ZÊÍÑÊ«pþ{KyL¬…ÎAüs¹Ä?÷òŸÛüׯ¢ÿ¤¯òÁîå“'xwºPú*8Q¶{Ýãç3ðô ^Sè¾Ol×ÕqÈ­ð_O¥aÿ¹J&¶‡ÚéG©GØyü„¯ºÆ·\øQºA€=ü([)ð£ôUÀv°§öž?¡’?¿Ÿïç†Øóð Z Êò¹åñ ¼7O (^ø'Q™ }Ù«AŸB ‹úÂýrƒª¶CAƒ =±O7„}VÕˆ}Œ&#ÍoM“ƒÖÇ7²‰¸ÏûvY2º“ô2P_¬qáŠAÉo>æžÇþʾñx°LØç>ľöØÀ¾&%¾çˆ–ü“€šŸ=ü©ùµ”¾è£î^ÜÒ&ðñ~[øb_¸ÄÂØçI~ŒÜ§Àjâ¾`&÷¹ºä>U ÷éˆ}L‰} % ìSøqŸ%^r_„Šûš{*¼œÀ¯Uà×!ÁÏÕ÷µ'ø“QÞ«8 ® ¸OÑÄ}­ñÀ}ýÎÅ}‘‡r#ò¶ú÷µ€_¼¨$à×Úà×êðë)~Ÿ„—QA~­Æ ¿Vc _ë6@?Käd?õûõ:¿Ç·6Èë°_»7د§ûµÚ€ý¢6;RŠýZmÀ~=¥Ø¯Õì×SŠýÚ;Oøë5.øÛü‚þZÛ€þZý@­6 ¿OÊóã@íî ¿ž’yÝ6 ¿VÐ_¯MÑ_σ€¼-Ï 3®MÑ_¿wÑ_k?Ð_ëÇ ¿v/П'¥¢¿voÐ_¿1y[ž¢¿ž1y[ž¢?rÀ_{y€¿^Äämy þzž÷ǼZð×n øû¤¼ß/دRì×SŠýz1Å~ ¿)ôk ÉÛ®¹¾¥¼?¾7I~­„äU¸¯'”ö‹µGòúúZ§ôµŠúZe}íúÚ­®oïóµ ÖÿXÎ"¼ßÕŸmLH4Ú¬N|½•’ð"xÄ î*« YÿnÀ‹+¯®8¿}ñüÐèŠðžIcyô­íEáÑw=2â„Kß­“ŽèÒgß;ºô­÷ ü)—¾X\‡àÒ÷2|\úÖû¢ØWîÍ󮯧À`9<þéÁWî±èüØu¾±ÜõÁ§o¥lÆ‹Èx>}ñ¹`Júëí´“¥Oßšé\>}4‚µOß-©Œ>}vƃO_ŒPpµ½[\ÅàOŒÆ"qOy î)~‹Ä½–ÂàO 3%qOÁ”$î)H“Ľãùûò Jâž ¦ºç SÝS1÷Îâž‚+IÜóPÝSØ)©{=ÁŸØÛ¤îµ¨{n=ª{í^ þ䇂ºç{QÞóU%ïõßµ ©ÀS’÷\Ê{ ƒ%yÏÍG}¯¥@ßkµÀ×ÊÀ×î…ÏON…¯•\ =g¥ð¹*|ÇŽå¾–Ÿ›Ÿ»>ßš_KÀç.JÏý_Ësï ðµÚ@âsCPâóU”øZ $¾žòüxJ|j*|-K*|î%TøZ±óç8¤Â§DÏ]‹ŸŸ‰Ÿ>·¾ž‚Xnº9>—\Ÿ*C}¯}¯}Ï•¡¾ç– ¾ç—K}¯]}¯Uú^»ô=7õ=¿…Ò÷æNúžïD}OIyÏ·¦¼×R ïù"¨{­\¨{-êžëKu¯ uOA~ îµP÷œBuÏ_ ª{¾Õ=· Õ=·'Õ==Å=¿:Š{þPÜkÅ@Ük¼Þï­!îµêAÜkw‚¸×J¸ç;QÜs‡¤¸çúQÜS´F‰{þ„–¸×Ê…¸×®™?b*JÜs£SÝk÷†¼×îyÏOEyÏmAyÏOEyÏõ¡¼ç{•¼çr)ïµRÎãǤDyÏ÷¦¼×òÌŸ+å½V2ä½V?È{ŠS)yÏ­LyOWAÞSKÞSKÞSm$ïñK,u¯]tÞß®$uO;¥î©ÂR÷ÚUP÷ô:¥îµ{=GÿÞHÝÓL+uÏ@uÏ¥PÞÓ‹‘¼×ò@Þó½(ïéÅXÞ£µŠä=5Õ½v«k|ouÏ—@ÜkY ü ’*qÏy(î¹=)î¹m(RÜ󛣸ç ¸×ÊeTÕ˜âžÂºJÜÓcRÛc1!´0p[_€Uï.ô§ô7ìeäøwR`;”è7b`óq£Îç°×´ï\]À)ô­`¢ÐwÀmÑJßšã¯Ú¯LRŸ<Ë$õ144¥>ÿ¦wß8~XxFÊüJ}ÁÈ©o½I rúV jC©O^m’ú"®ó×*/÷>ù¹É½o}â÷†ö{“{_«1Üûš'´>{š5ÿ>¢ýûìñGÿ>ûÏÁ¿¯§”3BóÃKÿ>ÆÖ¶_K_OAÌnû¿Ϟzòïsú÷]C¸÷]åèÞwýíâ‹èݧ÷ï¾µBÂ"‡Þ}­x÷µ<ôîk)å‹+ëö<ôîs ½û¢7½ûš‡"¼ûœBï>_UÞ}ö5¤w_†Í8÷ÙÎ}­8÷¹#ѹOÝQÎ}·‚s_O)g„vœûZx÷µ”÷ëªIï>wYz÷¹!èÝçRèÝ×SÞ”ôî‹~‰ràÝ·RÆ{9ðîkyàÝ×òÜߥw_»Þ}íx÷9…Þ}®1Ýû\2ÝûÜtïkyàÞ×ò¤{ßz©_­¯ º÷µkàÞ×RàÞ×î÷>÷º÷µg€{ŸŸ“î}=åùñ ôðó)¿ˆdû±ôl)zøµxø¹/ÑÃoå¡'<üzJyøµ«àá×J†‡_» ~úâÐÁÏÅ”ƒŸ¿Îtðó’~þÎÒÁ¯•?7:ü\=:øµ{ÁÁ¯•¿–7¿V2Üü<[”›_»n~ÎA7?ß›n~.—n~-~~î’@Áö9¡Ÿ_»üüZ üüZ üüÜ:åç§E7¿–n~šlåæ×Š}N­tók)ûÏ©•n~žÞèçç/`9úµkàèçÏ<ýäÇO??ÏBôós ÓÏÏíI??÷6úùµ[ÁÏÏï…~~šcèæ×²¤›Ÿ¿7tók)póÓÐËÏO@/¿v¼ü´þ’—Ÿ‹“_»N~­vpòóEðñSËÀÇO…ÈÇ/˜ °?ÕWN~ · '?ÝZ^~­xùéÈ˯Ý^~­dxùµ’áå§Õ*¼üúïšX[¹ðòs ½ü|½üüœôòó½éå×®:ÇÏçñû!¯W†zÿvþq óaÿˆhý[=*û_ø7Ú·Îùƽ®²z¬ê*ë«eµ\(ë÷eµXÕ(«ÇªfYÎŲ>q¯QV‹U²z¬j–å\,ë÷eµXÕ(«G´fYÎŲþ•ˆÖg„ȸÿG‰hý'>ª¿þ†}?¡ÿøƒ/¡³üîGáÿEDëx‹ûóßQDëÿø­›üÇ¿ÑúŒÃGü¬#ðüµXY7‚óFDü›”rFàÝë—Å3}AÞkÍïqœE…~9#´[îŽò€öóÅþ•v,Ï÷©mÞ—Öõëeäü>…)9¿ØŸÍõÜØjkeÛžØë•V1¶ÚÁºÃ­”Äæ8&¦LNÆV{X÷ÀÙïc1À·“?kÿê^+¢ WÌ„æ§Â15<Ë¢‡Ø0¶»"¢n<ÂblÏVŸ zjŽ<6¾G¸Û[!õ_î½ý–qéš0ö½"¢®5'ª¿#2±Â/…Ñ¿´ ÎcG\bÅÈ])u-ŸÜ q‰!o¬1•Ï‘傸Äqbî}½ŒÆY-c¿FñÀUOEDU€ÁûâqæÅ®öŠ}ñùK‹ô;Ž-Ê]êz†<;Rv¾ì#Ì}V)N?Œ”²JrýbÇ;ÖGH®js 0ql6!eÖšc°5?D&޳P‘r•URKÉÈÄáó€R"Ì*%T'$TÅ—aÚµÈZë–ÒJǹÕòmãJw¤ïXÃí¶ Tæ9ŽPâŽÊR±#FœFsZ"ÎmÉçb^y¸`ëñy¢3ºGäðíç½e Ÿ/†îJyò6’Ã8sïê ŽCŸøñ;w¡ÆÈ½«l›òÛY)O>Ctf¤äÞÕ§ bĬ——ϰ‘@ÆÈÝ«UF¬Z)yo’#÷®zóyä3 ž6Fl0®”`牔›M¼¡œ{Ö3¸6Ê1R¸Ã0FX~ó„Ç˧·ÍmÖ{x•’ÛWý•Ïcû´ÍÌÍ«ÞÆ3ý¼ß™›W+åà˜ŸãÍgXVÑÈÇÌÍ«eø̈¸÷éó>~Ö/L£>'Ûx>w½‡ ;c¾#Ÿ!¶0ª>×vTmj7fý~ë=Тq\qRj\Ã}žqµFwmâd„çÓ¢Wn^­7Î(fãW=÷4GÝÚ{`,ϯÏ÷¥èÄ} ŽoŸ1_ç·ö–ˆ\Ç·6o ÅØc«–¨#\û3ĮϧŸÔ!®y¯ O>B+XÕ«ƒ\ó啊2â$׫ Ÿì; ò#ÄY®ùÁ¹0ÓŽ:̵?Tœæ:¾WåîU~ƒðªÂT5¿87b|:Ð5»>Æ1Ÿ’ëL×>ОýÉgXctGJn`õ§Šƒ]{ת“]¿)w Wuœ8l"'W}*p¸kïhœî“ëÁ&Æé®ë~z„:®¦Í8ßõ]¾"­]sëj£²#8ã5>â%œŽwŸ¿´Øíãeˆbþ¬‰UÁhÇËøÄŒí;ÞÒy߇îÀ!¯±¥Vû&ã-7ò”¹êÀ9¯1åð^7&V†¹oé¼ ©_´ÄÁßoÜm3p‚‡ÛûaúðÔ.ÉŸ lmŒyï³]ÄàÍÀõ‰ îÆÇ:€×g’ówLTW()ت-¼ž—ë8àv ;°1ðŠGý`|ž(«0l&®:°5p?x²PÞ @Ç+-TÔ £ö‘ã•ašÆšù஥Q¸1gBÎSch­ ï+ê*¼NMÙ`À8ýv|0„Z¬•“¯“"ðZ gŒ‡† ‰éx †&Þ;Ot$Æj MŒca?xïô&ÞÏ®#ÐGa†Âù|0DE,TŠï±Þ'ÎW®‹4×Wm¸r)\«½ Ï"Þ÷E¼ þ‹úcý]ü—~5X—ïûQ}×U&¬²^x¢t¤$ÞÏdDàÛÝd®$À¼ }¤ðŽQ‡®Vx‡åWe‚³d4EàsŠžŠïçÆñô$Àû]‹º ¥$®«È¹€ŸGxk¢Z,°±p}WiR ì0p8MèÁµÀûÁ&>ù¯¹•üwDz O]ü·.aðßÊÃãOÁí¤ðßzîçïÿÖE<¥ø—_}ðê»}=ƒ@ë!Z¦à¯9þî0¤Û yºÖŽŸ÷×o ì×üªÀ~wˆÁëÅ~íx°ßºŠG¼‚ýz}'Î¥ñÞR±_;õ ì—žUx•Å~몽³_;ž ì×NûµCÄÀ~Ù¯fg¿;VÂèަáDFöëïÿÂÑ4ƒ.`¿¶¾òdšV™»NÄÐÉh@¿v¤ÐïSžLÃEЯVôk'˜ýzÉÅ~}W¨Ø¯Ýök‹%ûµu)د¿ðb¿^ãb¿Ö7§ñ[¡_ß/»q8 Frq_;¾ Ü×J%öEØÏJÀÑ4“.»I}íô P_[1ƒú:xúZ€úÊ€úZëû´Šõ¹¡H}<\«CºxA_{¤b>7™O›ûÀûTRŸ7FI}¢QßÍ<¦>.èM}¯”Ô§MXb_#Ì÷î\Â>9%ìkì3:û4$}è¢>/³‰}^¬û¼ôöi¡Kì‹•nMìÛI“¤>Ú ˆúÔ¦>Q ÏDèóRЧGóq@Ìg óq9cæøT‰ùL¿b>QUA_Ûjô©« úÌ‚>#¡O`(èÓÝ } úüH}fR_ËêSõ¹ˆú¸å)êÓ°4õ‰ˆI}&mRŸkLês7õ±“úôNœÚذ« Ï;C‚>7¡ÏZÐ×vi}:IÐç‡ô©+8µÑT_Ðç%ô9ÇïCß+9ûÏ´÷Å^ãþ¿¨ÿü⫆Ø~w4ÀÄ¥òS4¼ë¡eÒ „ò·Yç+å/àð•§ÕK-0§©X¯ð7 ÜÖ™D­â¾y3~¹/¬3Au…}צFbß*–s3¸/.ÁbÜwGçÄ5Å}ax‰¹ Ü×@ܦ˜´ñ/œ@>âßZçsY ð 3E,’~a3¹1%ÁïB׿ôY!çådå$¿ç4 ùy ð o“ý~>³—àçÒþÖ¼†ù5 ùù€[’_ì“RûÓy¼$?Ç, ùyáLéo-°Q_[QúÓ±¾$¿P¯)!Bú3»PúÓA«þ¼túµµ?K°@¿¶ˆúµ†úµyè×ä@?ïZýb8>ôkõú5‰¸Ä?¯f~m½EôÓ§“è×V¼`?¯‰~¦ _[cý|¦£ÐÏ B _[·‘ý\b?/ìÁ~Þòû©zD?oçýÚŠ‹ìçw²ŸWn„?͸„¿&+Sú³|IúsÉEZzÿ¼Ò—ô§-âŸv:-ýYèþ½4a ò§­NÑŸRþ$4þ´Šð·ÑÆðgš¡ð·ñ|2ÁŸŸšÂŸåVÂßKk –I ® …?Ë¢„?M•þÜ2¤?ËÞþ¤&Qø³¸JáOkMÑŸß„?•CáÏB.•?‹ŒTþü~©üY/åÏOIå¯åý¹?Rù³DKå¯=”?íÆ ÿ¬1Iù³ÖåÏâ*P'…?wýþZ!þüØþ\ÈœÌÂB’ûÛ,üäIì}«°·_!`—‹{‹’­“vi¿ ðSJB`¨‚ÀöPý%ö.Qظ ðs«„Àþê »`\Ø•è‚@•l9ÍvØšØîì²íx%<ƒ[ƒ‚[¯H üÜéީң Ÿ ƒÃ…¼à_Ó&›šèÛdS. lz60°,€SqQÎYF5ª`a l0€ŸÊ\eSÓ*s•Mdra`»Ñs~Í‚€Í:˜†Ú¶•I M’ýÞÍú$!°?AAàçšq|F*°W·°Ù ˆ¥ëƒ{W+ìY ØÌ+À€í™ {ëÆð£ŒiTYŠ~î½Å½²Å½Sÿ}îþ[c-Uü×[ªø¯¸â¿þˆýdÆ‘ü×GEñ_3ÐÿõÑEþ£àýÏâY[뻃Í:óMzeKì{y”¢˜ï@˜i"]Äߨs_«hLcOF+ù}â[´E¾ðÚ_ñ›§[‘øÖòÇ:’øæþJ]+ä/A'‰¯i` ¾yiÅ â‹e ©°ˆoÞZ+ƒø¬xø®S_lßG¢}€/} AB|‹ëgÑÞÇ;ÜŠöÂvu`íÝÛ)}®hï¾D= ½{}£¯í­‚)íÝÃL™Ï²ho±0´×Q:ß=usè|‡–! ½XiMçkÆ<Òù¸¹FÚ‹%éÀ½0ÖþÐÞ]ˆX´×nMÏšu>Ëf ½ç:efšBß­–„¾MlW´×„5 }q”3Ø Bßji<6…>ÙHè G&¤@è{$^SèkjhÏR…> }¯†„>‰Ì¤½}ÃÏRùl›LÔ3ƒõÚŽYo5ùñe½U¹ñe=Eüë5:ß#KÖ[ãFad=Kk¿¯ó­žµaoµóõúN†îì)þ `Ïêa¯iiúd"سVU°Ë=¨m€½50±µO­o0°f×ú„µ7iP'ìYТÖ×îÚkå@ë3©÷¼±A­¯Ie‰{V©õI%íyERŸš˜´ç J}nPÒžBEJê;(íöR_»`oõGXøQê[yÚt–Ô×ò@êó»$ìžRJŸ†JŸŸ€J_+JŸ»5•>›á—Ò×JÒç²Þ¡½D*}6Ô§ÔçÎG©ïÔÞ&YÏy¨ö¹CRíó /ÖkorŸ_TÉ}Š¡)¹Ï#žrŸG/å>w Ê}jsª}éH[ %öù]Rí³Â)OKcû¬zÓÆ³ s¥÷9m<µ×D½Ï#ŒzŸ7Ý(øMí@Sð‹à ÀL~áµ Fƒà·:7ÍE!øM„‡–Þ·æ›í«÷Yy.3OåÞ·¾›÷×ÌSé}êÕÒûlÙF½ÏÖoüôÑ’à§þ(ÁoîB»ü´ï*ÁO !Á/«³^î†<¿µªƒ²DÅÏ%Sò“¹„$? Hò“ƒ4¿V4?u·„½Þ¢ÔüZm ùµR ùµÚÀÐÓ-JÍ¯Ý šŸl¤ùi÷Xš_Ä=sAós9Ôüü†Kók¥@ók¥@ó;á%Éß|)~~¦¢½ö]“â·î‹ŠŸ¾HRüZmÞÓª?}䡸¹—Pòó(ùù™(ùµR ù¹…)ùù©hç©]}I~šV%ùù©(ùiZ•äçÖ)ɯ•ÉÏ¥Pòs)D>–ò[A­y98ÿóâˆtGÌ{y„wqžOÙ!çˆ=ˆM¬ˆÁä<[)Ê©ï¥Aï:©tEz×&>é5¹ŠN}·òtê»xމœúŒJåÕw˜ÈàÖ·ªI½B½0Ï‚AÅ=sP/¤QLëôì“óP¯;ÿÁ±/ì>!ƒÁ±Ïʵ=¯ìéØwÈ¿±´½÷'í5ó'j{­8öqüJÛ —õíÅÚþ¥ÚWÚ^Sûص‚¤_Ÿ-Ó¨íÙ²Ž~}^ÿ—¶ç59ýú4­SÚkz´=hi{VÁ¤íiÙAmo¾?Ýú¼"£¶çåAi{š§¤í=†Qh{²—¶×t;h{“' IÛ“9¥=ûdRÚ³O¡¤=µ'aÏ¥={W¯OC”öšd¿¾æ/HiO¶ªä=›QÛ³¿ ýú,”÷d "¿>ïxKÛs9à=Ùd€÷Z)ã§@Þ³‡(ýúšx/‚›àÞðëkå€÷l¹%¿>É ÷æ—÷>>q÷dÂqï‘(wü°E±¸'±Œ¼×T9ˆ{~*òžÍƤîÙ?¼g-TêžÞÃïË{V ïYN£¼gÀgÉH~}؇–[Ÿ]O©î5÷»ßU÷š“!Õ=kw×åŽêž+CuÏwðY¦ºç.uÏVš¿ëÖç§’º'LŸµZª{Ö5¡îiIݳ‡üúÚ¨îÙ_Äç'§º×@ª{j?©{š©îùSݳ»±ä=+jç× RòžK¡_Ÿ=ý ïµ« ïÙQúžZ‡ú^S©ïYJ¤¾§~A}ÏÃUúž%µýûLÒ÷†Í>¡ï驤ïùNø,ÌQàs|->™ß×÷ܹ¨ï5-ñ½?j使GyOrÔïË{Ö\(ïµ<ã‡Ë¼ä½&þž¼·Ëè“ò¥Oë{›˜úže.ê{¶&¤¾çÚPßkÚô½&—Qß“ )}OÒô=ÕŸjÜ>(’Mà£TGO*!õ=‰aÔ÷šN}Ïô=ksøèå*…ÏÚ>:yPàÓšÀGÕ _K¡Â' Š Ÿœ®­ð9>U†Ÿ…B|VÚ(ðÉÇZ Ÿ>PøNnÚ[äÓË•Ê']“*_SÞ¨òé-PåkºT>¹jKås ÊgI’"Ÿ^D¾@‘¯å€È'ïi‹|’ÔŠmþWâZ›Ó—ïûÄBªy^ñåká]®0sÚ!  Æø>Fž1ø&J) Âôå«S›Eñ úüW’ ™’æ×BÀàœšÚƒ«Š#P9'Õ\òaJÃÌY$8vSD¿Wv‹ ÁX.b+$8§7@‚kqMœ·œ!€‚±ô;?(Fä1ø÷½×/×”s}ù÷í2?¢ƒŸIš~ï%±fž–»èàq4ÁpPþš¤¿G^a`Á;ŽSþ°`#r² !˜Êß®Ö)¿S¾NTþ¿ˆƒHŸ¿òð³"aÐNUtñ›Üš# ®Gç®*`p½E†ùM¿&Š’½óN¿GfŠrñ3Z .l'îPùÛd­l[„Á¡êQùkWÁÅocÆ“ò·kÙ?G“ò·iMå¯A&Ä?ûCÒÇo||üž]ëXúøEåø×Ê¡ø·z…<øø16K‘àsó0ï"ÁˆƒÖ¡‡_s,Œ€¯Ô¡üÙE†~Þó€ò×b-ÛΔ?v³ßP*æd`Ø<’›_``+Â_ËR‘ü’áKIÒZq`¬v±YAÝÏFÐàÀxJ&Ôþäzÿø(›‰6e?[úÊ~:€Ø”jè~¹¿•îqxy­”?KUä@oåIù{mÓ¹•3«¦fåÉ0þd„_Ê_sÙ_¥@ŸEwYòÓÊógt—.1BúóÖ#¥?·0¥?·0¥?;׊mj¹oJ®1¥?+©”þl @é϶ý¢@®»-ýY³ƒô× !ýyW“ÚŸç jžþ€2U“ö'½‹ÚŸ,ù­ýÝb±?Òþþ?Â#¤?i§þä® éOýFÒŸ™yÚžÒŸ¶w%ý]t.’ô'WTIóý{§À®LŠTþZ4™Tþì½Få¯ÝÊŸ¤h+Ò¥„‚* /$å¯Ý ÊŸK¦ò'?X)~›â@AT)Úð•òGg;È~~$ê~òÛ°ð7åfH4ÏÑÕoûà¥ÅŸð§½p vå¤ðç. ;O±/…¿v „?ý¡ðgÑ›Â_Kð§!f[Oã„?jŽPýš"ä­t¤úÙ“³T?ØÐÓÄÕÏo‰ª¯Ç´ÞÊPpÍ G,¸þëÿ”.¬©‚)ÿ®”+]N`ÿç\ç\ÌÓ¯û Á­×$ìå;8%^=ð"÷ø¯-%¢aàqÃenuáV–RZYHke)ÅeÅI0ñ¡oO®—Å4—å—õŸ`z}8£]ò‘§¢Ð2ïéϧcB_·bBÿN†ñ·ë÷2T|Øá Ñ¿ê ‹EcvsúǯºUt˜ÕC×Ú°çbQkN8cø©(&ô¢œ‰Eõ\**ްY­ã¢ð)J™TTË¥¢æ“ . Ÿ¢”IEµ\**Ö0çhE!áS”2©¨–ëÏv—ÇyG÷\߸ûø/züQ¼èññ¢Õ~'^ôyý(ï·ãEÿv×úxÑâƒõ_}z~ëóôß긿údývÏýuYð6b™¼ÞG¼‹ÿ/eÍ×ùBâä{MÙùBþ—Ë/øqÿíþ·°Gxοý¯ÿ¶&ù+4ÿoúãÿ¾ÆgàÝsýíÿö_ÞX¸^‡šë¯°2Yk˜+*Ö”ø `}:€õ™¬¯»ṵ́Ò×ßþÛ¿OOü+«Ïïm®Eÿ‡;XõøÁª·°Öç&w3õ•Zí?‚tqÀÞjܵ\±ª@Êkð‡~”ηǶæ›qøX)÷{ìÿ2s»(W ù­Ö2á.4ßÃÙae‰Éº–¸ûL“ãq¾j}΋âfœUû.pˆ˜3VéU™gÁyε¶À¡åk!¿ÖdóŠ5ZåyóøÇ™Qêóî±=ºGžp#È a¬²òÄBW%¤GÊŒóƒp ÔZɯEÈ ¾Õ©^aR2½CvŒt\÷qðlß0MY 7€qöÏY¦ ¾b >ŸØç©scîÜYìY±v<–FGDÈZÍõ¬¥ÐYKù+ò„wGí!oÙL3]ßËv¨T®¼ª²ß=!ÎgÌïѰEz¢~v™ÃÆ)òD|¨Ú¿©éO›ÂŸk-Äç9l›êªŠ/7†ö|ým µ§ú`ûŽ5øL+üÊÁVS¼¹a 1£]ÛíéÛ —±"w¸ÍM2“ùéKôC—;¤™è‹ÍÃd­™†j´±µÏLÃbìIåû˜ ïØaJûÜ™ð‹mŸ\}Íf5Ç–Õl6Ö!òDo|笘æv }£uvÑ#Fë|s? p.ëLL¦]d Ö3 ÌÈÁj{Ú‘À|kPæ`5¡Ž<–8kB‰cÃ"K,»«Ü+·\f’dQ•ñ®³v4r_9Xm5ËgfÔ‚º*Dþè[/ݘf(¢†P„š¸2|Ÿ®X™d×â!¨W@Æè=銠h¬ˆŒ–Íw­UâÈžCc»kÄöV/fµÛ9?ÅÄ9qÑ“8À¯ LôÈ*$6a¢%bK3[ë çê]ôZ-c5ý#²%®Ð²‹>@ËÐb¬¶”=7 ³×wá^™gîÀàOï3Qiæö[¾à{õÍ;ó¼àË{ä·g¦Ñz]5gŽÖÜ8Ë纯³F«SÂZª‡Ò—£Un÷›[=Ë[ 9oÑÅ7­†«Sî®aµ^)ë‰s¸:å8j¼:%l&÷>‚Á*mœ=aní¬í{â9^SÆ‹„¸²)P…êCº>¬±¡œÃUŸlSÏ´Q~+å­áª=ĈÛWÕåÄ^pŽWYLÇk;z1ñŽr¼Ž ÏŸµ½ ú¨h W~)âjŽ×úšÄ7#Ç«¶Ébo)Ç«¾&±’ãU{JaŠ÷|¾©Üõ©oxX…Åxõ¸½õ¯ÑMólØël%¹ü´Už ›–%çÙ°9`OÄ.ͳasÀ¶”œ]Õµãhذ(uÖÔý² ­(¢3¤qajÅø=¶3kx7ŽLyjfÔrl5ýÌôãBʃъ‘˜ÃÖh­©+Ï…ÍÁªÚÆÁ°5X1 ã`X VLy4lÖØ—¯”ËåHÁÖJ ›ƒ•&WÊó¬y4ìÕºì-o³…<6 KçÁ°ï7Ë‹¹•C*†ÍÁJûxb½æÖ<¶æVèÇqpnUʉ¹U7CÉj¬:åŽî!uäY†g  ÜFΣak°Â<5†­¹Ã.†ÍÁŠ1Ÿ'ÃÖXU1/§VLìy6lUÞüÜjn §¢lôä«J9jnåb O†} ±$®ÁÊ;Åɰ5X•21¹bF΃aknÅw"†}°¹ªzwÍ­¾hMC÷á/ÇJÀÌÊ:†åHÍp½„Q#•†ºy0lŽTºläÁ°9Rù-Ƀas¤rÅþýVc`jå¶rž û´¯Ö1fM­¹•_)æÖXîW¹7æÖUãs«ŸáÁÜÊ%N ›£UåÄÁ°9ZõÕŠƒas¸ª‚§9\ù-Žƒak¸êUÅѰ5\ïÚ \)†ë¬9†­¹•xNÌ­œtòhØ«ÆÐ]¼0·:%òÌ' E¼)鑸§cVïˆövŒÓzjÑ@tÐêÁT£j59aæ|Q 8b™S›ÉÁߥ’¢A‚ã­)8Âv·˜Ÿrð(p[ÍX»Â¤ÀøÂ–¶@ ÜÖdt|(0,3j˜_X¤ ÌÓä ߀{™}‘ó<Ǻ ˜ÁØ* ')âTÕbÀ°¹¨… ðY¢P²ÐÄL @+¡ƒ ÁIÅ`À°iàÁ¥5S…EE­+É€aÓP;üdÀs#üÏKöH À°Â1 Àøªà PP`þ¥è Û¥ € IP`R…c)A! ÎEg,$êæ Às ‡žS•·ˆQ>¤ª©*ÃÀ⦦ª}ÄÀœÕ}5Uƒ=Ä@ ÌnøKƒÀèa5 ñîJ#ŽØ²),Æ‹)c=Bਉ¦AàˆE5°° °•Œ1PðA“»€À&Ï/ c T Gœ‘þÀ˜à ò î„À‘fÇà9dÀÈR"=0­‹øÀ€-0^o%ÃÞ©ŒÉ€#,9? Øò€ÝKÈ€-Ð èð*d@ß ˜Ç ¡Ð] öXµ—At?!Ž\÷7Tg#Ž0«k€€Q ÀèR@€a.VŸ$`~âŠA€‘§ ˜ŽŽ…TÀx¤ZÕ2@µŒ0t½ôd ÆØ­uPÝš 8bÜÔ5`Àvp¬õÃUàÔXfŒÕ‚X@`ËŒ¹"§%A`|‹G¥€cÑ\HŒb@f€À'Õ PlA`ä9|5³ÆGê*|¶r [mœ¹È€š;Ä€ñ I‚}#2`|®k‰KŒÙ^Ðt… ü؉[0`D,*d&jfúu’ý:É€­0 g~1 ‹ æ³.êÝý¾‰€šÃ‰€š5…€ZPƒµÞ‚B  ;0òÔV0:vm 5‹‹[9€ÀÈS=>ñom×£%¶JÆ­¶DcÛa$Alåº~„ÀXàtŒBöj $Œµß¬0`X«ƒHÁ€¹*¬0`,% ÅÉ€ZfŠcÕF*¬©5–›¹c-Œv¬m2`X÷¥’Ãz¥È x®JT•‰€Îl÷.iä ªw™¥oj£‚A=…hÐ) Aƒ(iPÍCÔ ò›ýÏâY ãÛ9>8)1 vvˆ€ûyÂèÌø"\p1U#H€xªX  µ6!à¤@ 7äócãüczÜŒ¿Mרw¬áÂø 59µ,À>÷bŸû±¯UاEê‹[Áé Ô×nêky@}ÎCêsRŸ[ÔSz ûŽ8"ùcêq ì‹1U#‡Ø×Š)ì‹ØŽûÚEÀ¾–ìó7„Ø× öÅUãƒ}-Øç’É}Þ#øµ€_Køµr~í^?·;ÉÏ­ òó‹ ú¹7ýÚ5`?—Kö³ñÙÏÅþ\áÏ=ô×ò€þÚ½@-èÏãŒø×òÿZ ð¯]üó7‰øç!Aüs ñ¯¥þõ„CV)…-øç{ÿ0ìÉ~n,²Ÿ‰ì׊û_ðk@~­_]"ìÓ—Cاª ûô öµ<'§Så9¿Ó©¸Oßfr_+åâ|ªR.ΧJ÷µ”‡ó©Êy9Ÿî”5_Χ57ΧÌCîs•É}=¥fÔv¸¯åøµ{MΨºjrFeA~­˜›3ªRLª*åᤪ”—“*SH~n/’ŸïMòsI~íª“S«®?¦V‘_K™œZaòÉyõcê.Aæc†‡3jý|9â'çR^Ök ;§S¥ëibëµ,çÝÆ¦@¯]29—rÔô´fèµ<7'S•ÐãΤÊÊC"žßÀw~ä;}a xšlxîh¼–ÀÓwD€×ʽ9‡b²ൔ‡s¨Rx.‡€ç<¼–²sÅl(Àk)'çPÌZ¼–À ýJß9áÂ Š‰Xx§E ñ.Ö-ûGí;ho¿»ZH·ß?U½uUˆô{ªÞ¾q}+¤»¹iHY/^s%énš“ÈÉo?þŽl=º«é¼=)UO²‘NÖbº0*«,@:Zœˆèl!C¢ËˆE°ö,¢Ï¥%Ñe4¢â7ÝÜéD¢›keùt¢‹ŽP­G¢‹ŽPë!]ôƒû#êEG€O".â]¿ˆG„Úé|†/‘.ÁHkjXOéæCIŒL7_FÊ"ÔÍ—'xê® æ‚º<é·Ru‘rBë)(BÍyçµÓªPwm|„ºŒVÞe½kß ¯¦ (\®»ö“±~Àu-hwí ÓN´»vZ>í‚ t×®Ý]ÇÅ“@ îÂÉtÿxù]mŸ w×1ö¨æ¡ÈƒP䀻–¸»"„!CÈälqŸx®{MH¥š]Á]d¹?²ÞµžnC,œvtBvŽ×<]«|)Ö¾»"Q¥€ïZ9à»vï4$$à]ƒ6¼kЀ±«jàð®5Àj†€w ìîï2¤_±ø.ícßékŠîüpwŶR‡»kÒñ˜p)ðAÜEÌ?xðî®5ú£€»H)|!Ü9á.où1ð¼ÖÇòýˆz‘RC‘p×RwWmû¨zq2Úý»ˆüUíI¸kWx w>œp×R îâøî"Ka-áÎyw×Å2áÎ÷&ÜEžB^Á]O)¸»n àîª îZÀ]ä· à€»ë~îZ9€»ëfDKÂSwqU}ìw‘œ¸»j§dwÝô› ÙñïÀºëæN É.b¶}üZ»ëæ¦!Á.s‡ÌWl×ò€í¢{WC‘í®g£ö¼‹<ÛǾ3Â]–ƒñ.BÈ=îZгÜéÖ‚;9îîZàîz`´$¸k)€»–¸»VO†M(àƒ¸Á]¤@ܵÀÝ »ÒÑw.‡pwÅ:³¤@À]Kܵ’w‘ ˜X}«b»V خݻØÎ…휲s!$;W…dwÅbºt?]KÙE|Àó£éEžRfHv‘çù]DŒ-öØ9h×îºsÀ]»ø®Ýˆç‹y«¶CÞµz;4@Þõžtº+Èó3òâ¢ùqïó­ÉyíN༞‚9Õ%ƒóZ9à¼Vp^ËÔkÔÓƒöœÖk ˜Q•ØóSöZ`ÏØkY{~M„=×–°çJØs¯'ì¹­{¾9aÏåöÜ{n=žYÏ_²žYÏ$ìµ›íùJÚkíyä’öôºÿJÜjS`ø#}½pù¢@/çÆ -åß÷Þ0‹$6L,Ü^ØJŒ+߯¿µ>#FãããáwìpO’ªwȳª^Óù ë]ph²×h–õ&ƒºÀúÄ" ;wÖX†§øŽ†>‰6ì´ ) ;ex*ÃÎCÎ…0ì<JB†AZU ;#Ps]DY/Ba–8HÃÎqcß.~Nùɰʕag ºÆ€gDüvÊ…N d,ì]äVvÊTL–4´±e§óÀ²S–K2í”ýM;e”$ÓNÙpÉ´S¦lvñ£9žL;e4'ÓN@É´ó¢·«L;}M;íãüÍ£ÇÀvJ+ i­,¥¸¬<çåé1°â²˜æ²œòŸ·:ÆÉíòŸ·úVÀØ}*ÿÿw´Ü_÷…ÕgHy*Vg¼ÂºQ+¸Z@Å3äø Ö9á—†D5#:*å©`N‰í  ¨ˆ#$ÏP.¶ÌSG.Þ*Vç¿÷•rW¬Î8ç&!ÆZ ÔwÃ2þŒØê¬qUÏûÜ*V§:Ŧ(™qÆx<êšÝ÷<*V'C¯žw„mŠ„BŠõûÎqÁ g›ñ?õ÷ç¨0þ{’}z^Dp?¯òõŒXû1R rñÚQq:s¿~¾¥“$Ï8ùo¿{ߌA}!¤s}òžØz~qH畒ߺ™'³eÿxæ…€ºïçså)x”¾¾<)z8ÈäÝ3L'b¥žÏse”NÆà=#ZvR†š=c¸Þ¿8˜ôù–r²R°ÏqF+æ edÔ3Ÿî›ç¬¥“BšæY«9JÊ5ÏZÍQª’A†ïVáèÚg {šg­æ UB±AÆÆÍ ½Ÿoµa:U9׆UŸÂ@µ_µú€\G¦0®Íáê<'fT~úÂR5G«&&T=dÀÃóöï\ž£Âdïéc3­@>£5lRî_â%pF…*PÛ 9¡ªŒ8"zÃ%K›¿6B4™/ä8:óÅ §(Ì·ú&b·‘ùFœ?sáó8ï£ Ì7¢Ãåà#ó˜•ïJó…p¾óEرëÃ|ÛïA_È.wÑ /íB*¨/f…ZÒ“úŽkRR_ù¾ùBzØ>È'Ç "ŸÄ!Ÿ6{ ùYȧàƒB> iB>…Çõ)Òª¨/"ÖR˜Ô kMJêËóß«P_l××ú‡Ô¬«Êõͧ"ˆúÂÅ¢à—Ô' Q_œÌ põ…ÑCõ P_«¨oXúä–!êk) ¾€´ÔJE}‘÷©b@}sÇi3¾yqGì‹Ï^‘!¨o8êAÔ7o̾õ¶€ľÐ®öÍ_3a_¨Õqˆ}~rbß‚btG`Ÿ¼öEJ-·}óE˜EqßœøZˆûB…¨õ7¹/,0òÁ‰}¡K0}óBÜ aßµ}˜¯eóE›Ek€>yšúæÙVÐ7oÖôÉiDÔ7oò%©oÞÀ]@_œûUðEè›O}°É|ò•ô…I5fB_49R_¼Nð(¨Oî"¢¾p¯©q@êk) ¾ë@ˆf_t‹êD¿–ð‹é |ð 7Ú "ø¹ ~òMùEs “übúœò“o ÑOn:B¿kƒ¡ѯz`#¿k«ˆ©?'€ûä©"îÓymâ>ù‰ûÚUà>y üä$ò“«ŠÐ/7oiäwí°.ò»Î‡ˆ ôËeDNáD¿–Rèk†çƒ~ר»D¿–ô“·ØOÎIb¿è7µ û…=Óþa?'öSoüÉÿFðß“Z_þœBú‹«ŽJÙ¹‘о%ü£³”èïª%C£?ucÒ_+ôŃErŒý…±W‘PÒŸ|ŒDn=Ò_ŒÕ"#ÒŸßPŽoÀkCÄz z‰P( œãD€~w$@¹Ô‰5¤„€~›D@ !`,u7_Ϊna"`ËRwz‹•€€ÜÆêÖ$@yó‰ýP$ÀvÐ&Ê9NȃPŸoàu 8µ°åú1I€î$@W(¯E šØ.ê{#¼âŃÝZ$À0b¬ŽN”+¡Pß-`«Ðï—Øjt I€nu ß ÐMJŒ]ÀLô½H€nv ¾@™@M´ÀV¹›3«ªlWÝ@71PŠÐNtcÝè@u `»hrb/"@rH€n+ ¿$@÷t`»æåÌŠ)\¨…ˆ°–g–µéöûÂCKõ«YÂ8·ÕÞµî¡ê·”–ZÕï8¸l£ê'ƒ{«~4”ê§óVýx&BSýÊßíD¿¡ËÄsÀúHü·Ð[ëä?/aÉsJÁ+\S*LŒ¥ò[ÅÆB”ôº1p¾ˆŠ-ÔËjEN LÝmœ«ÐGE€^Ù‘[ F$À–¨uPÃJèu°åêã+ä‡üçe&ùOËòŸ×dä?¹q‹ÿ4 ‰ÿ¼V&ÿIô%þµ,À¿VÌäL¥<à?/ÝÉút‰ÿZ9à?Mãâ??9ù¯¥€ÿbNÙ ÖTÅeøOÓùOãâ?ùOßtñ_Ëlµ¹9W)PmAô'j&Tç"zñNtWÖc“ÿ´r'þ5Ü#ÿai'þ‹nSÚÐ…4þ«¡‘ü×Êÿ¹Ó›ÿ0É‹ÿœBþk)ä?•LþsÉä?WFü'<ÿ©Èh'ÁŸoMøó-ðçÀŸÆ àoÇ¡H‚?±áÏ,µÿ˜¢ŒNþ9øGR2þq~4þ9ñOQøçá;„øOZü§¡,þ3ƒ‘ÿL\à?'ˆÿtù« á?j ÿ {Æ?€ñOKãŸòÿx+ÒŸ»ÑŸŠýq "ú3O‰þœBúãÍ….GøÇ{ ÿøœÂ?§ÿ|'âŸÖ‚…äÑŸHJô§,‚?.0Z< þœ"øCÇ7ü ";ÎÈ1üù*ŸV†‚¿–•k:Ãß ‰ì§}²Ÿ¯!û9 ØOïßìÇ,‚?½IÁŸ:µáODvzJéqFåÝì'b$û©Cþôº ó‡ü×J&ü™*§P3êõ•ÿJ þx+ÒŸK!ýojtÃÛXð§6þøS« þ|sÁŸÊ!ü WÉ~*Øì‡,B?5±ÐO÷6ú)ÑOµúù* ŸšBì§7^ìçʉýt²Ÿóý|±Ÿ(ió®*„2±+cöc9f?_±Ÿ¡ìç<‚? D±_mOüÄ¡?}~*‚ܧo¹OÔ,îS!æ>æ÷ißè§Íž Z¸7³ó6Áï½áái#ÏÁÉSFž4HyðîéŒUá^¸{qï¸(l÷ëL¼§ u>ùi[ðc„9Ÿ‚ øâsW6E¾øÜ½ÝÌSî>}*Í/¦¿ª4?x…@óÃù⽸?ÄHJ~cÞAò0u#ïÅ}aW Þ Wí· ¼×RÀ{ô–îÉÏ\¸'Çñ^¸.=Þ“cŽx/RêÉ{¾p/ÇŒ:sv _‡û£÷Yïé´%ñž¼¥Ä{rzïµðžŠÀ·ªîHàk÷ðµ=³Ä{òkïÉ3K¼§8â=¿<ò^Ä(³]òž{x¯%€÷6€¼w”fÉ{á×´A¬é)jS–´ä=,Þkµï­ÞwEÞ‹qôÕü¢Ÿ×¦y/ü–j„“÷<:|Š )à‹þV\Þsuˆ|nR2ŸÌ5.;T2Ÿ‡˜ÏEèkwº§½ÂÄ|®¯ÝÈçB‰|ò6ò¹Å‰|~ "Ÿ¢DùüˆD>w"ŸŸ‘ÔçnCêk) >=¡Ïès0ŸoæS2Ÿ+Gæk)`¾–æó'€Ì§—@䋞WR,‘O!6„|±,­yƒÈc£¨ÄçîJâk) >_àÓ½|>•"àÓ‹#𩛉øZ¹ >Í"¾vˆOcYÄ×nâÓ%äãC‰øôÙñ¹:$>ç!ñ¹`Ÿ>k">Îu>½Ÿ“Àçð¹ðžÎ$/ÞcpQñžÂÚŠ÷ê]Àþ¼ócî!S`§ àÓµ€/ü¯îðõL©¬y¯Þ“?šx¯§`Fu x¯•àk)| G#à;ר+“KŸË%ðiÝ#às1¾ˆ³Ô>K/àky@|¾9‰¯]âk) ¾vˆO³†ˆÎ¸>'€÷¢” 佞R3ªŠ%ï¹2à=·0yÏmCàk)>¹/ øÜ6¾ž‚ÕÕð¹%|í^¾v/ŸŸ“Ä%Õ>ß‹È×S0¥º ŸëCäóSùZ _+øúþòµK€|~&"_« ϯŠÈçrˆ|¾‘¯¥ùZ9@>¿s"ŸxBÈç™O¥„} r.ì b)=Ø×À}þ.ûÎí‚}6¹/R 'É}ÎCîkyèË[ýFŒh±ÞÑc»´·ã,&K{¬â-íEPÐæ%ÆEëI—3²^D/*£2²ÞŒ5Ì/ õ¬rõ©V¨w]²ÿ¤CßZ«ím/–, ^¬ XåÑ7xD}¬¸íÑgo}/-#åÓg=ÀÞ»±= {áEß@ÐÞ»ËÞ³hÏ®wòé;ÕB>}rx’OŸ|³ìÓ'sJúôÑMÃ>}5´íÙ¿éœúh=)§¾“æ»òê£/‡½úäø'§>z&É©6ÛÍ©Oþyrês œúàedŸ>ažòD8?Æò‹°SŸJ¡OŸäÒG“K¹ôÑ•Æ.}ô2j.};µGºôÑÀ>}“Þ­òéS9òéÓCɧOn\rêS åÔçràÔ'¿D9õÍ—ÅÀ©¯%Øá°gûI·>z Ø­¾vë£k’Ýúäÿ(·>]%Ï>ú*سo•ãMzö9=ûœ‡ž}ôL°gßEã¹öÝ4Æ—k}°ìÚw#¤’|ûî:Þ®}Ñ9:î)‡<ûîA PzöÝöFäÙç<ô컯²f±gßM£Uyöݰ~cŸ/¢gß}ã« ×>Cß>§Ð·ï¡Å¬|ût+úö=4ø“o/’o_ÞÿðÞû|ûɱ <ûÔÚ³¯¥À³Ïåг/&•"9zö=´’k_KkßíKž}/-¿äÚ÷ÐÆH¾}±úKc½H€á&]û^Ihtí{iF×¾WB]û^ªctí‹iñ£îµ”tí[µ¦­'\û^n¯ËµÏ÷¡kßûÓ¸3RJ=£sß+ÉÎ}N¡w_âÀß/§ÔkÛ¨<È»Ïy ÷®‰*£wŸóîe9æèÞ-)±p¯çIÜë7/ܻ †¥‰{íÞÀ½ÌB5/çÔV p¯Ü»"Žà®p¯—\¸×ó0>ŽïU¸×S ÷VŠÄ»Â½^Ná^¦\Ý¿¯_õ"FR|™|JàkÅøÚƒðµ{øz)|=¥€o¥Pnð]ñ¹¨,Å{­¹À{ýVÅ{Y °x¯ßªx¯5 x¯=•üûØ·åÞ§¾$÷>*¹÷é"z÷½RïèݧÑJï> Fy÷©”º€#HÎ}ú;}û4äÛçûÒ·O•뵡 ß>yùöñ›%×>ÕV®}ÏOËNÅäÛÇï¥|ûôÙ•oŸîD×>— ×¾ç§ag»\û| ]ûÚ˵Os€\ûÔ4ríãU!<´0¬4çGìÛ±—Ö"ºà`bàvì_a KÇÿehÁÿý†ÖÇÐÎÖú¬Úm4*­O[ö@)O’úZÔRb\Zé㩺RúNGxÁ¾äd*}Du+}Ü¥ ÒwÿèÒJ•ÔÇx’ú¨1Iê›óý)«¥>ÆÍ´ÔLj­õ=$Zi}8¸ÝR^¶ÔÇCžíÛ·q)Hú[ËF¡oßZ!|ûìŽú³£#µ>½i}N¡Ö§ÚHë{¹Ü&ýE;V‹JëãÑÕ¢¿µ €•+é/CBÿÒàoœ4#üEŒhX£þxú”à¯eüÙ£’ð×R1‹@J+øsh#Ò_LF£›v®)öï@½‚¿–Pì—ëÀ_v„O@—–ú[³¶HŠî+ôµÐ_Lr7d½¢?žÃ%ø‹.-ð{BÏǰs}ç¨þ2ž6¬=kšjy þ"6dá á/¢£]]èkYvPMø‹žŒ0€¿qãhÁ߸&žìgSt²ßúþSYûÅ\ÿ ¥æ©ñ0DÙ¯¥€ý|s²ßx™{ÖD5žOHYÁ“ûbQíDî?åä¾ñ<Œ0SÜ ˆð‹£Ñ`MYà7ç‡übˆoãÎH™ãΈÅyƒójšÊç`Á"¿xÆ÷ãÛ‡g$÷ÙA˜ÜK „Š÷Ÿâ¾±Fÿùñì/Žj÷Ež÷#ôEžÚà%øÅ‡« ­¸/‚‰ÖÚ†Ü77œ?Aôk @¿¹qÿžèqݰèßPþj:<¿¾¹qƒœäç,?9F üâ;[kI’_~y?A]æÆýq’Ÿ¯"úEɵÞ$úµ<@?7Ð/ >>:ŸÛè×€~ê#…~êhB?u4¡Ÿú«ÐO\è§^.öó‹"ûùµýÔÂú\_¢_,·+Z•¾¹#r«Ð/RîOd¹§ ý¢×¢ŽJŸÛJ_O€³¼‹)¥/õ‹¢ ôÉs_B_°ÁѾòJ9è+O-˜BßÜ)2Sè‹”Rq)ôµr ô%y|"»´r ôµ{Aè‹«Je¦Ò×ÊÔçJ}:š‘RŸÚ‚J_ËQJŸ‡J_˥ϕ¡Ò7jòTúÚUPúzJM©î'TúZ(}-JŸ›”JŸëLò‹ðÅŸÀ.nQ’Ÿ‚äçö#úùæD¿H)S _+è×.ºæ§r`¿vÀŸ{á¯åü9…>ç!üµÀ_Ký¹ùH=óC¤¿hPˆÀ?·(ñOÑ$Ääà¿–þÓ›þµß/F+ïLúSÂ_ËBÇ>dia¡SûÄ<½òÔƒ»EYeJïüû×9óüka¡3$æÞc¶:Åá—™æø¯Nqøå+O/ê!¦â²˜æ²œÒÊŠÐ$£‡˜vJ+ i­,¥üg‡…ž}þvXè_u®¨ÏCa¡'Ã_ ýë¾°Ø1÷ò{¤ÞŸý*zLèZ߸Ð,ËŸYVù̲œ‹eõ\*K!ŸUV‹ù¬²”Keµ\*K1ŸUV ú¬²”Keµ\*KAŸUV‹ú¬²”Keý ±¡ÃËõïïĆ>þ(6ôñ±¡Õ!~'6ôÊ7+ßØÐ¿Ý¿~úÏ|µþñ«ïÏo}£þñ›½÷çwë·{ï¯Ëú˱¡g{ývpèÕÿ—ÿû(2ó?‹ý ãüßþ-Ý3ŸÏŸÿJ¬è•ýŸÆŠn‰ÿ÷ø ±¢sê/À›§,q$d˜°§ÎyÆ&ÑAÁFm?­”Üa#ÚÔÁ*+O(å#ö4;¡ëÊ»DÏJyp ÓJɸÆãåg;·lb͘TwfJx~Ú×Ü3aæÎÏbÄiÊ Œd O’~\³Öi¤»°ø,ƒ™•2ªÜµP?ã¬<y‰uÈ:6ÇrkÆí„ ˜|xå7~kF߃ã2Ï”'iWWC‹3T²ä»Dñõ<¡äÍÕ€A×™’È´R2ž•¿§sÆŽÌù¹{l=Ÿrî-íªØ(z?W=3–~ë*ìñ¦O{~òá ’±UbÑ¥*>yñÞ¦éË22”»t×y÷ÊS¯7\ ÏëSlø*t” s\ŸÍô^X)£vHòðã=çè+%;L{Ê8h·æ£*dÍ 3› ‘íòŒÈ÷©Br›e^o.ÚîØ(zûî=ÍXì‹Ý··Ã}d˜´~Iô„þÐXµ;ßëñ¯^¹{Þ¹blYj÷ª—'-}¯ªSûU±Oô½ù³çQï©úçEw¿êÙ2h òÙ3ö_¿$t‡ÓÎÄúöΞê=%öˆ>½.¬¤^ôÌÜGšOD€ì•}b;n~²ÜWŽR'„©ðüTîÝk”ª¥"ÌýÕW"|yò„Ôüâ#øÕ'¤î}&»ò„TuËë81ƒªÂy<êÛûG:ª*uÖ ª¶ÊÓQç§r7fPÌ"×qsÝ™å¹46«òtTw»85&§î+FÍé‰WÈv90ã,$F½+¥ê¾ 96,Z®ô]¹?W NŸ|¦<Õ g›Åùy­ s§+scîÔɃQßÞ¼y0êüŸ»?˜?×Ûx*åM«ÒVŸØ•­!Êž–Ç¢¾uU"Ô•Ç¢ÎOÊ)”ÌcQ? ç¢Æ“ÓúÊcQ38¯ˆ·Y•C7Eý´W8’u‡y屨=–íàxŸr^N¡l¯”u¿ËïêÊcQ£-v`ç~Æ5P±Ä»ò\Ô¾|»2ŒL®vaîx幨o¯až‹:ÚÔzÅ™(}ðæ±¨að>µQ}]~Ä´‘­•§¢æP-ë‰+NE=öþ¢òTÔü¢nvÛ8u Ö¶)o\y,êÕéÞ1‹ê«Ç¢Þm‘ű¨ïÑj“Ç¢Þ½oű¨9V5fòXÔ§¹7_q,êôû+E}#–ÁW‹ÚèáÊcQßÏEON¥#fæQÕyÏ>äóPÔÙGbŠúFC\8ïÊCQ£±®W‡FëUyΜPG˜é<µ­wæ„:Þ ‹íÚ`ˆÆºú só­eá°Þ%ìω6ìÝé9Û`/¡V9„½û}±T"ì=±w[Ø{jÑÐh/Žg}ÁvE{Ïêioi/\»‹‹öFQøW°7bau¸íwbƒ›´çÎ Úó[7íq̈öø4íiÕ%Ú3¥‘öÃ6í]|(ÑÞóÖÀ7í­f»ŠÀ@{û©Ë´Wrf£=šæöö}ä{û³õ{¾¬·Ox¨‹õ"äÛ^ÏP¬·ßpëí^¥Åzû…³ÉÅzû³?Åzû}‰ìjºÚ¯óëéy±^+¬'û#±ÞþÀ|^¬·¿0jëµGî;‰poð­îía¿VìÜs ‰{ÇÓßþ"n¿ˆ/ÎQ­~âkY@|¡_¦ù9‰ïØnNħÃqE|Q¿½.ñÅù¬…w¾cÛ+ð€/tÑÚé ð9…Àwììü>…xóÅZ±ƒÌyp°/œç/úbMZ}‹ÔwXŠúüf@}Çi ,ê;"Ïû«b??Ùï8Ez`¿–ö;NÒ,ØOÅ~Ç@€œÂ¿xÂ^MXlj8U¿H9+ð(а• 8˜H)Tk‰Û½@€qbð[,Œ¶©e 0ή 0N®% P]Rê}ðˆA#t  ú)ðXŸž³²€ÃÈò.X+ Œ.ÀºT0 _°Ý 7z@|Å€n+2àQhÒÐ)dÀH9@|;+Ë!ú¡È€Ñ@^ÀÀV20PE ôcý.‰anŠ”Â@¿\b š¯©V’¤ÀxÛ_ô‚a™Q¯… ¨Q't$¶’‚Ç@„F ëCx"Á–ŒKõ& â;g|ŸêA WKÃÃR,زýƒkayÕM\)$Âà>É@„Á}’“ƒk­ cÂ`O î'‚Qˆ÷«l¯ ƒ¹ð­n\íL)œ1 °_Í­ûc7ÒàZd—ñ ap%ìÚ<¢f t†`Р̣n ^ƒ+eÿ ƒ/ Y ƒ‹Êl•,¸²Œê´@Á¹Ý°Ì îqÒI]D>¬nKþÓ£Eƒ !&|·ªaÐÛ,„ÁvŒwWþÜd„Á<¢'‡aÐ_\ ?„’þd¥/éO^Òþäñ/í/BHÕŠÚŸBöˆ²‡4(szÑ`|ã+`ð¼ê9±àØkÃD(øºQ0Ìö¯Ê”¥¼PPVúBÁ°Û?Âß87B&Xp”È‚:5H,8. ƒ‘Râa0lê ·ƒ2z Òà¾Xpÿ”iºXP6ðbÁðu{cUX0J¾?,Ø® ÊT^,(C~±`\U‚1Y0\$pXPÆóbA?7YPÆóbÁœX ¶À‚nP²`ØÖË Fg.|% Ò(7šñ¯Ý(èk@‚#,—Š9‚nu¢à89ƈ‚2ÿ ÆÛÛ‡5]ë%¡`» (v–äWÓU´_½=² Žº Æâ¥êCŒ÷Y¼ Œº#¡¦«xU5†À‚~SdAy ˆǨ…ŽPÐÕ# úNDÁ0°}o¢`øÖT³ÃE§>RDÁ00Ý á€‚2Å úÁ‰‚íî@ÁXnÕ¶ QpLœdFt?& ÊA¢PPu jà Ç #8¡ î#ŒîvŒÃ¢vΉ‚ô$ Æ7º¶äI‚±^Q‚ÕÄ"A}OD‚j>‘ |TD‚®2QP‡Œ 㪣RÀ‚=%Y°‚šA¹Âˆå !ë‹\ëQ¢`+((§¡ ™Pp¬ò®ªP0|Gö¨p-BAß‹((Û{¡ b„‚®3Q°]Ô'‡,èNA £þ êÄ9±`¤”úD o‘Z‡0mQªX/Š è§&ú p`xÕ”ê@t¿"ê¨;q ›è—@l)à@9@ˆ[p`«Ovr59Pþâ@ú ÛEÀ@´ з%¦‘z Ð!ʉIè^Nôø'Ê=JØ®ú@Œ—PMEtÉ„@¡¾!ÐŒáEè×M l) ÀvoP`K¢‰‰€ñH_1Àþ‘ÿÜ ä?¹¹‰ÿZðŸkKþñÉü¥á_ó@øÃ|:J»þy‚þ¹Пæ8ÑŸÜåD1ånú“»Ÿè¯¥€þü¤?Íq¢¿¸W5'éÏ_+ÒŸ¿VÄ?vÒŸ«LúÓ*Pô7Ö¬Ðýù#Lüó7î.çH,j„Î@üÓÜ.üÓÜ.üó´GüÓT.þÓBGØJ¶<@Miÿ$l´¡ïÈmŽ}\ó$RŸ5ôIö"ômÿwï’sËìûMEÍ:+¬|gNàºcÀ4ÛsjxþpãÿâÒÞ*I.¸jl­ø˜ÁG’IþÁà}Ñ è“-ŠÌ§1ßRA~ ä³å„ÈWæ‚mB>næˆø¼Óâ³í‚Ä·¸ƒ…ħ-^ßzp!GäÓnž˜o-f›à}º\Vз^+1ÐW³ãÙ@_k¡o½¸Æ&ôÕù±c‚¾õ’õЧÛ‚¾ò÷]'è[ëK—зޟ>Cè«ãû÷}ëïQS_ü‡O&¨o½i¯$õEPßz÷—EÐ×çÝ‚ùú¢^ßZ1'Z)€¯”®ð•ŽerôŒÒø¶ÏÆ¢øJ3¼?|ëÛ“ŸÉ×…‘åï¡–´§ȶüYIÓžó!íÕ æH_ÏzœÜSDBážЏW'×Ùò÷àl¤p/r¢åOY÷œF–?µ9qÏy÷*û2Yþ" Mz/2ý©-ˆ{®(pOñ…{?¢ÜÀ½÷*žŸB xÏ=€¼§@â=……ïÕfÒdù‹$À½÷œ9qO¡f…{•ùgÂ=ï[÷ªÈ0óõô䚃öR´W9õçÐ^m£i1n{jÁžJ+ØSÙ{ÚwìEV ½HÚ ÍÏõà|†hM.Ø‹$€=׬§¨£b=çMÖÓCD½<¿^U°§­„=9쥄癤°ç ö" `/%Ï]W°çâö\ožËCØÓž©`Ïš {Š¿*Øsûö"÷†½È°Y5ìEÀ^ä ØsÍ {~аç>JÚso#ð-¯$ì|ŒÕ›ö9_hñ¹¯“øüþH|îÇ$¾€ø<I|!ñi@7ñ9kŸ>.">˜È§€ÏjI}ú:‹úÜ€¤>}¶D}ñ¨/ÊêÓp%ôñ«%æS@[1Ÿ%d>¿þ8S‰ù¶ÌçâÉðÇ F†?Æ·á¯{µÌ~un©%4û1ö¯Í~…a¾Zw-óÕ*«·5döãºKاµ¢°/$4û]™ýÎöÙ@Lì³¹o=˜†ÜIÀ}6Dƒûl¡%øÙßCf?Ùu ~ëJ7Qp_}fš\É}rÄ÷­»÷ÉJÜg».¹ÏöWrßúAM›ý:RD€_¹yõ'Qf¿ŠâØå¡ÙOFQ™ýîöZd÷£Kì~ýºmô“¿'¨/$ ¾²‡¶1›ÔWiº9I}‘ÔW16º“úÊ˯÷eöã­­¢¾eãqòßÅŒ6èm£öz/×=¿¦«gœÏú9è•WNΑôN\ãbÒ{§ˆöª"ê™]ŒzôÅ2êÑLÖ=Þ$փˊQÏ–E÷´z5êq__¨wp÷¨gã£PïBˆ£?@½ŠnßÖ¡Þ}òhPNjLz" “ÞC_To‡0è F zrUŠÀ…ð‘!|Yï˜ì{Bò^°yÏïÁP'ÞÛ¾ø¹E“÷@’tõÔ–€xOjè꩞NWOѼyð$WOµ±\=ÕoÍ{,ºzªßÊÕ“ë…>r­\=5@äêùtÈ$ðï||¡rõtî>öm¹zZ3\=ycš‰O« &>¾)»zj%eäãúP®žl?»zò5ù ŠtõÔâI®ž~ŠÈ§µž\=ÙOìêɯ’]=µ“«'6@ìéɦ1ó©ZrõTåëé§@}ZÑÊ×SkFúzZ ©½ÖÞžütÙÛÓjH}j y{êÕÈÛÓy‰úHòöTÊÛ“#èÈÙS-*gO«¡³§ÓÐÛ“ãUÞžÜ~3ô±cËÛSM,oO½_¹{:oº{ªâr÷T_ô‰äîi×Iº{Ê×ÔÐ'ƒÝ=Ù\òötæd>~íí©w%oO~ÞÌ|‹òö|lÓûš_É|Ä%:{>ßF>ù@>lxÙÙSe‘³§Ê+ä Àãf*YGÞž\œòÉ?EîÓû÷Ý´°ûnYåˆ}z5Â>e%ìóSÄ>bßmûæW?ìSSûü±Ï¥!ö¹4例VBq—¨æ>½=q›Bا·'ìS‹ ûh÷öÅSÀ¾È ØOûLíľ²±ÀAØižtJù­‡lp ?£?É/$ ?aD~ÞT ùÅS ?¿+’Ÿì2"¿báQø¢H ?#qÆz9èF(Û߇¦ ÇzáÂE±^9TÒø·bÿPLXÁ§·f90aÉ„¼¡HLèSddÂåÀ…5fBÞbd&Ĭ`(ä¡°Ê®¥Ç'6ˆÍ„',»vù”Ϙ|>y_©}>EdB…sn÷ëE2!/eëMH”Ë'½çÈ„ðz›˜QåÂãS +cFz©¯(,ltø¤EŸ Μ‘³¯¦±¿'= ìï¹àî !»'͆»§IÁƒ›¹‰[kwOzI‰ǧ¹3§»çýmý« Ì×äîYŸoXûV„_ËÙ“^(¢ÁzæN¬Yë3™ÿäèE¬:µá”8X¡)Ÿ ÝcˆƒQa\€ƒGÝ‚4á B¹ _ qP1íî Ÿ"á`õ‹VL<68öÛÛó‘Q8Yã)z{Þ2G6º-ˆƒU«ÜÀÁãà â .Vä®g:ùçnB¬ÎÝã‰8X!Æ„‰ƒÇƳ²ÄÁãÁÍ8ÂÁã`È*â`ð\¦“uß7±ç«ãÄA á _qð\&¬ŒÚÃ,Xa㎉u‹x³`EZßqȯç*…û ž«ðßn²`è V“ŸÓ±¿Z"}&ó¸P0JŒ‡€‚õAìi‘(ÈûÕE‚oG…“QP-#Ô­òBÁúþ]“«ç±q(x®<F¬hñ½õ |ß?ÏëŽûæm¢àqsOš(øÎBXr_>À.5Q°†K·(Q°ÂÙ7LÇJ°© (¨¯€PPÝQ,XŸàe þ¢-¬@ù€L°`«Ÿ €g¿)€`-¤çè/çvÈØ7fT~@Å~säÀŠçºMÆ?÷,ràX OÇþê)äÀ5,¯ÉÛó¸{Vª‘+òÿ>a`ÍcÛdú{› ~b *E tF€Àº àš ðýzô¹2àqá¼z3`ŹÅi>@`EÐíŽG¬l>8ß×Sª{!ð¸ß„è>Dô $êC(ô{"V^Ëäí©v 5Á4ô $jN%{bÀó£S 'U 0 ûð\°ª!ÖÈOüU(ãubÀósÁ€z—DÀZjí“éO3¼ð¸p¦GX˱τ€ÕÆ3ú{D<޽€ øÎ4¶ã)0àÑÓG0`IÒòWwiô'Ö’ÄרiWÈ%ÐmNŒ‡@€î$ÀŠJ=[þjÕ¹B‚)•S¡Ð-AT€V! Û˜XSG‰¾E¬×ùÀ̇IußyèFŒâŒÐÝ Ÿ-¬î³OþªÓm“íOÓ»PMLb¿ýîƒôƒoÖo?ì±ßß±öØßiúËQ¥¯ZkÔ‡ÿ?F•~‡í_‰*ý&ÿQTéWüfR3èuýã¶ÐQ¥ÏUúª©cìÞõ%oÅsaþ»Ž:¹Š˜tcæ½jï`„D°¶«&Ë-£á]cš~â@úU“åºw¼¾AdW͹õXYéªÞ’ñ¯£v›q|èk,ZG’^ñ^µ,Ëß/wèÀ ‹¼÷¯:â®g„±»Š67¤^ýï"eo?UA׈ßùJÆ\åÐq×y\·«ë¬M£{Ò|Щ§6ž)Mm-ï­gl¸\ç3ÖOŽ_ý.š–ž¶Á¡ë•<¿n¥ðºÊKfN²–?ŽÂ ^×»`¡ÓüL [¦göÁ×û«QBÍ9Âÿ¥šw!É8ÙÔ–ÑqÛ®šJï9MíÝSæÌYݵkr§š»nÉÛ#¸áu¯ B}*Mí¬ì“d›ªt×™ä#‚G¾ ηeQîwÆßŽIÇ»º¿—I͵!Ò§ÒÔ µ%_e]ß0ÀÅïºÛ0™?µvM’åƒHŸ0¼’«FEÔû)ÿ—-"N¾k䵇ªš¸.Vß¶Ió~õXuš÷òîS^çð3ʼ®OV?Uì5e~=XýPErÈÖyÚïÂ¥¹ë£ÒÃzïŠÌyÏiÖÊïÿ×5I¶ !yõTáÅoëŒW ×î\¯àAD^ðímWVKjÛè™ X;Sû¤¸¶žé©çÄhåSËû¥Ê°¼w渲 ÞîdªÂRA#ÎIK»\¦4uS•Zö§G« SAQ8\»µÊó¬ùPm]ÓC/“ÝsiîSQí¡¦ÌÙ¹îµÃe¸+Ýeì9s(ÞWèódSTü¸#‡ô½nSŸ­NmU–r¸Þã¢ÕcÒz~0\¥¦.ZºÖÚóžb\´:5y¹]p´¢Ï­ÑÚ’òù8¦4ÉÿJ=åÙµO5nZ½'É;Ilsš3«5˜Y­¹öަw­ÓSWO­jáaöš“Ü=·²)Æe«Ù³êŽÐ}êYã²Õ)É™•ïeܵzÅw⮘ kΤÀT\ÑÍóÞ…{\¶zgV''V©©£©ó +ÑÔVã®ÕgRÜ>nþ>ßû£‰µ“Œÿ¦îWW^MÅw­Ný¦vîç¡:îZÓì˜Y•÷¸kuzQu×ê3 ÄqÙêÔ\cyÍF—­^ÙµçzMí5n[4v€S²`n ‰çÖ.ϸnuúDŽëV§Ï_]¸:uãqáêÔ¦uáê<^Ç…«ScÔ…«×œæº¿ìyczµ÷h°ëÔu«S׿>S3\Ãr›‚Z&§‚2­N jœ•Á5«‘¢–È“ oYu)ë–Õ\¤Ü×5ò^¿Jý|¦,Ëœš} .X^]ݯ:»®W濺]uêG7®Í°Ž²¥NðÖ Ž©žuµêTìºYu.V-ˆ³«â^UW­®¸™ ŽkU]κVujïºUuêÿu©êTðºSuê\Ï6Í(ϸ;JQ7ªN}øÁMÖP–ÓIÀ‹2ôvKô’ûô¬ 6XÐ×þliÁ]½Ó5·oöÚ®ì•'áî.Ðî9h¿8èîöZöjt7°ñÓišîögÃq1ÐÝ^mº56ݘÑk³Û »Wp÷ž=én¯v5¼ẇaœ|÷J`›$ß9È7ùnW×6O5ß9\7ùîM³›ï¸œ|—’æ»WÒæTâÝþôþ+Ø®~ö6?Ùî•à„ÙN4Øñ'¨.44ÕÕ.m[¿Hu{Ýt?L& º½zΓX̬K5u㩽‰²±Nñˆu-O¬±Ñ‡-‹X7Â|ïyc]J놞%±î•ÀÊG®KIsã°“ëö¢†#¹.%#¼»’ë>0ª‚ë2 ¹î¿sݦAs%人Msÿ%¹îÓaŒuoÞ=„uzHX÷*9ŒuÊJX÷>u5GëT+aÝÆ:Kˆu¼´ËXg=ĺgÖù!b%ÀºWЃ_X÷9ÎXg ±Ž9ëXbc%Ä:KˆuÖL¬ ¸Îr·¬ÌuÖL®c½ÌuÖC®“„\g¹îƒ€áâ: ÈuÊI\g5ä:캙ë$ Ö}`˜4ÖY ¹ÎiÈuÖ3×I1±Nj„uR#¬³„X§j ë–Oq`]üÖY °ÎIˆuÖJ¬Ó«Öù)b*)®³„\·À\m®“fq%ä:^sg®Sîâ:§!×9 ¹ÎiÈuj qÊ,®³\gÅä:+×Y@°SÍEv "؛씓Ð΢4 í¬™h§ í¸Wl´s²ó"Û9 Ùβ5“í\/°Š,¶S²Ýc´ÙNµÛY ÙÎiÈv–íœÙniç£3'Ú©)„vzˆd§z‹ìT>‘òÙ©|"»òŠã^d§âˆì¬d§ÌEv,ŸÀÎZvΉ`Ç{y v~Š`ç¼v̉`§GìÔ ;¥שì;%×Y!¸NE ×Y¸N*€uNpÍEÖY0°.~6Öé5딂X§2ëœXÇ2‘êôPç߸Ɖ¯§™NU ÓY¦sŽ`: Àt~LÇ<‰tÊ“H§'ˆtÒI¤³H‚éõéüw 3Ò©T :ýÐY€N ÀsÎ/B:+Ò…H—’çש DºH¤sʼnt)y0ZY"]èÒ…Hz€t¡L0]=µ´ÿ$˜.%7F+>Ðb:çN¦ ɶLJÀt!i¦ ˜.$`:½:"]d¤s•ˆtn"]JnŒVÌb:k&ÓY3™.žÓ¹ÈdºÐ¦ÓŒ'¦ Í`:71™.Ò4ÓEæ`ºÈüÆÜª$çV&!Ó¹-Èt‘fùš[Åt!Ù8·²Äd:דL’ƒ“«$'gWiÓ¹Ét‘×ÍéUeÓ¹½ÀtNB¦ É‚é•Ïé\>2]<´°ìœ^%98½ZÂé•õ$Ô¹V„ºH¨ =7§W•ùáôJ ¡.$ §Wê!Õ…T’3,ߨÎ$ÕÅC§XV‹Tj.N±ì„¤º(òÍ)VÜs¯¬€u)¸S)°.þÞX‚Æ:— Xç ë"Ec]äÒXJOL¬JÁ^‡Ÿ7fU©,®s=Áuþ;¸ÎÀu~\4×¹PàºÐÑ\—‚ç×é- °‹¿7ØÅßì"E“]dÚdçÖÚ¹à@;?´Ód šì<É‚ìR0MM »4ÙÅMv‘G“k² Mv!h²KÁ=}®ÒÙ4×^UIs›ÌbÛ—ó¿OÕí´:éX£<ûXÝÁýy«s«ÛiùѱºƒÛü×EúaZý0æþšc퇒g±òôdÙç+?L'YŸ¯+?LÕA~˜NsxŽ…žãþ±rÄtšËsì3q]Jî¯+OL¥‘'&×-öÄtšåþ±òÄ´dûšf剩ªËÓIèŠi5§§Ù}vÅ É×4kWL§+¦ôÅÔ3í‹©ÂÑÓÀÓ)àŒéðÆ´Jxc:¼1Þ˜V wL æ^GwLkî˜þ;Ü1õ<Ý1•‚î˜z¿tÇt ¸cZü1™!hL.‘á‘i ðÈôðÈt xdZL ž¯Y”.™!xæö¦K¦tÐ%Ó)à’éÛ“C—L?—L à’i ðÉt 8e:œ2-€W¦š^™Lñ6;ŒJŸË0*XÅÀ·W¨RœvÃI»çl›ÂxÐî]d|2ŒÊ+Á5/>h·Ë‡ƒvè $r·ã¹«UP;XâÈ^•ŽÜ©Ä:r§¼uäÎ9ñÈ%¦P¹ß}mt£u|N"49Ú24e´ejr"jÊTÔ¤hËÔÑ–¥I‰¤)RQ“¢-SSD[–&%’¦HEMжLMmYš”HšþFLæçèeÅC2Ÿ’ùüƒÌ¿ë? Éü¦;~”î+$ó;ÕïC2ÿ‰ï×oߟ¢}­~ûQ‡ýú€ý¤ÃþNÓ_É<Ÿ?ŽÈü6Äÿåÿý?ÿø_Edž‚%ÿßÿQQ«^Êý7Ed>”É?ÿfDæç÷§mëÕ.êÏ]w“ä#÷°Åøõ`8éqÂý]OŒè‡pÛyî:yò‹£K¿‚«c×)E}„J€ñÏ»|ÿ ‡ïáó®†;T$¢O¿‚öØñ#ï{™‚uRÇóù¤†çƒH ý®zégìŸg]»àÒ°¶ ‚±«Ÿg\r—JwDú“ ÂÆMmƒ°à¼~]¦r\{·7Ûó¹3„vFï‚KÃsN_>Ýo­ó•Ô-¼¡¥$Ð‰àØ¯dm;ÄÖ×㽂mŸZý•ì÷ç¬Þ¥ö2KŽ6FXMGšv‚ ÿBr³,Ë}²eG%_ɳu ôÔûk ÉÝ5°ä~뤧îq_ ¼ׯ_zζº–uç5ë¹?ì#’\_ýh}æòÖÆó+¨ûÏŸ©ÄÛrñ% ïíýòÍ-¼mëW7ß¶ç«“lûõU‡íè1’s†iIž¯:l×\ﺂt uéWžçk,Ô ¤sêÒù5Ô ¤sVuûç:¯n ;IÝ@:w¤ºô˜ª¹s'Æý£™÷µ}}mpi–澿¾6ué6uœã³}uôº‚t4וsê ÒùsS×&ÍåèXèlôº-jŸÇWê6¦¯â]Ÿ¯žÞ47Iîã» ’+ÍusÖ9å~~æÏظÑlj¬“‘r¥·îÀÛ§¼ëÒg–ì˜EÕêÒ¹uéšsÂó5²º0‘º8p}å ¯d˜ó#<_]©‹as™Ñµ¬_ß› }·LÝB:¿…‹‘sf_ÙI$ьʧŽëש Ô5¤s?zàó#×óõêÒgjκ„tîHu éÝŸïIõ^4©BñÍû$ÔX7ƒèªxu é¨ÖL¯&~¿„û˜Ûó>—ïâ÷W?Ǥ)¹·¯·pÃÌšŸ{ZÕ,Ÿº„tnÀgÙ¸ÜBsÕ%¤óç¦,ûÇüÔöõ̾}}Ñ^)¡òÕ¤óÒ ® ÇT]¯õU¾óªóº5¯2ÍsÌ_ýåó™Þf­0æÍ2î!ŸYù=Ô´4ס¾òóÚ ¾«ÓÚrY†ÿ÷üÔ¹Î}©ÆÙ<³VOžg¥ê(³ÞgkU|þÞ”š¯:Œ#ÔÓS܉4ë×̪]¶ñŸ ÄL¦+öøÄžÍ^7Ë-dÅtwôF¸fºûZ¹}ØLW\0bsé¤P·?u_ò/bº—#qÝ=˜îà–_0Ý^Û¶ÃL·?Û§cÓêFLçO§P÷ ÎvïPgK" Î{€:oôêöqo?2 ÎW”êö²›wÛ4Ô½‚0ÚP7bB¨Ô Dnø¼‡Õ…¢u¯`ïóíêöheCÝ}4 ¨¥ÏN1 î<äÄu#z4°o@Ý$h·œ«¹s]ýêl ºqÍíó™¶¹ðÂmµ º ¢‹€&º ¢‚±Ý ¢Sôj]þnSC/›ÖÏàÕK«<—‚a‹ŸÏ(ö;Ë®™ƒçöÚ—_]ƒç†ä ž›Ò,m!¼qÏ%ynzjka¤ÙÛàP—ƒ¼ÐMš6:„ža@-WnÜ6J¢›ž¹Ïïò ¢Ë§šèfÉÝuPùšè¦4ƒèüIt~ñ$:½¶:G)'Ðe‚³Íƒï‹=ˆxw—Î’t~u:‡.'Ðù}èRO]êY‡gˆŸi K½ë:çÜ@7=³·…0ž9ÚDø>uÖŽ‹5 äl#¡ß\]öˆºé©»í„ñÔsLÏ4Ðå{k ›$K[ _eÓºì5 t³äéòYÏÞÃñE%ÍùçÙÖÂHb[2ÜøÀÝæBÆ—'ÈM}ž¯¢7ÈåS rSšµm†Ü‰$ÈM’rCÞÚ{¿3½áI3RsÜôûÔ–gbÜT–ƒOIîž-xÎ9E3܈ª¿vIšáFÈüTw³ø¨P3\ªÙzŽ 5û2+Ù{–dø~2Ü”æÜ¦ ÿd¸)MÛíRÏ}|W¦y?Õ —ÝãüÜî pù>NØæC²õ|™’ë;ÍÞ3fHŽõ×Ìèüd·>áÅé¯=£‡•?‡iÞïá„ÿª{Éã¼Ó4¶Mi`žwÇil›ÒÀ@iöõ«[_°Ñ‡äÀÌi=ç>wý¶é'¦Në¸Ï¯oJS[¶RS[æsÃyÕzn˜ê•Õ çU÷“¶úxh{¾*pÃ^o5ÇÜo˜ëCíyó$³¥àÞæqyÃ`jŸ›/%ibËŒšØBMÛ$èIÓ#êÙæ'öž4=T¸­F6Çý5,×R͵ñ£Á$÷‡£ò"¿aÒ´äÁ¤É¬­…ÐZ´6IÖƒUàSÛúfïi“·~Ö¦4Ç1×´6=u}øea8­ª Z‹Z‚ÖfÉ3RК°–‚“¦´4«MZ¶ë×]!Ä2hQäÃÂ.›Ñ9bz¼Ÿ—^Ê7­µÞkGÓÚ;{=«Ó·œX¡Ñ·¼ïbmêùà$:™&¸åî«Xh[Þ÷Ð&!Xà– ‹šà–÷§ÐW«8àÛ1þ~wPpšà–7з<0ÂW¿Ÿ´ny»-p롬i[ßI¨Õ¸õ}«[³U[à–ç ÜòôU4À9‹a€[?ˆ®M\¹Â>°È=‹Zu¢×¸z$íoën´¿­ïw%hû[ÚþæjÁþæL†ýM¡²i+AÛGasµa+‡Ý¹ŽÙ·Ðb û›KûÛúÎZͱ°¿Å#m‹m m+Ì~#¼äB«,ìoQ¬¶¿©j²¿U®€ª6¿©1d~«&^úC ó[ÕÿI\sN²¿åSmKIÛßÔ°0ÀeÞm€K½m€Ë4m€+É•¸–za€‹§`€‹:À§®$;›ìoQØßRñ~οÛþæ†ý-óiû[Ôö·Ì¨íoz¹²¿©Êþz`Kɰì–ý-ÚaØß¢ÅaS/“ý-Ó´ý-Ó´ý-Ó´ý-Ê û›:´ìoYš¶¿¥æç˜~Ãþ¦#û[¦iû[äû[”ö·ÔÓö·ÔÓö·¨ìo™¦íoñ¦`‹7>ìoî0¿¥Ú¶¿M’ÁéWû[d û[<û[¦iû[4ìoùTÛßâ;û[¼˜a‹æƒý-µ´ý-ÓÜËW7ý-szί4°¿Å‹ý-Ó´ý-Êû[´ìo™f_¾~߿Πà2§6ÀåSm€óë„ý-jû[VánÝ8°¿…âa‹± û[41ìo‘ìo©e»Ø•(iû[ôPØß\˜ßò!\áö„ý-ÞìoYÀþ6´àz§€ý-ª\<\ôYà´t.5·.õ n¤9®¯O&,p™×5yXàRï}rR¢–¶ÀÅë….Ú&¸Ð \h† .%ŠëV‡ .%Œëî6Lp™q]K˜à²|×9­Yd‚Ë4Ž«Ž \T ¸x¸h.Xࢀ°ÀÅ7sXà2E[àR‚û!Üè°ÀEóÁÝ ¸|êÆÌêòÝ÷×¼ œÓ´Îzió3´À9'Zà\ZàÔ 4À¹Ai€KÅÇ1÷àò©ë3ph€Ë"ßÇ\%Ü)žç« 0ÀEN0ÀÅS0ÀE5a€Ë4ÛÅn2Òü‹¨Êò¥ìû#ÓW±²šäÞ‘ˆõ4Hîí7mD#È™ìroý?ÈÕq¥f(€Üûá<š²r ‚‹äÞüô# ¹Uf6Ü»¶Ü;H®N´µŽArñ³Iîm18p‚äÖ>Y.’«Ã'pl’{›äBE“œ 9Ý3$’Ûhþk’{~Ò—2þ>"h245Q.£ó/ÛFK_£\¨l–«“š[ƒY³\èh– A³\)]Û×,çz –SSå\o \¤o”[¶è(çÓ4—y7ÍE­@sêd¢¹¨'h.ónš h.4š‹òæ¢|ƒæRGÓ\ä šKIÓ\jišK=Ms™¦i.KÓ4—išæ2¯g./h.Ú 4—išæRÒ4yƒæ¢Ä ¹ÔÜ4—O†ÖÜ4%ÍéšK½s)iœÓ'Z8§o´p.ôçRÒ8—O5Î¥¤qŽß<Ñ\æò™ã™4Ë… Q.MrY´&¹HÒ Ir‘/@ny'“e9M9݃ + ’ìËԸด˜3õȉIÓ9_˜5ýÐ…iÓ9ߘ7æEiÀq¡gp\¦hŽsa€q™¤1.2ÆÅCMqQP\$iŠKAO +.rÄE{â²0#Ömþ¾æòƒáâÅ‚á" ¢ÝZ .ª„‹–ÂeD¼ I#\dÕ‚kö\ꆿ¥Òæ·H~ÓBNü–¾§p„üæâß2 ¢ß†ä˜;ð-Zø–Ï þm¦ñ-õ<ËWû‚ßBø-ô€ßâ)ð›+|K5ÛTkÐ[pD(mxKÉy|½À[®á-Ó4¼eYÞ,ix³ÂÛ$¹X>JÞR˶Nc”ð–5¼E’f7ñ€ØÍ/—ìVõÀ€ˆ‹ "ïû˜ãˆÐÒìæ–!»EñÀn¡ìæ·@v˧šÝ$ùAÜdŸ}[ ¦âì›\ûì[~H?ÉŠÌÓ><û¶‘œà'YA·†k? è(ɰ\r”´Ž’ÛISü$ù›n’òŠü±›dül à&)ð’Üf\¼$-€—¤ô’´^’‘¯½$ýwxIZ°mÓOxI† íÏV/I§€—¤ð’ ÁõUl8Jªêt”T.í(©è(é¿ÃQÒ)à(ép”´Ž’ÀQÒxJ†àù*\%-€«¤÷¬®’ÀUrÓIWÉM3/]%# \%CWÉÀU2$p•LÉÃòÏž’‘äÜçßð”LÉý]xJ†ž’–ÐSRYÓQ2’ÀQÒIà'馡Ÿ¤“ÀMÒ‚ýœ~ÂK2r›¤“ÀK2’ÀKÒIà$Ià$é$ð‘túH*I»HF¸H:Á:åJI àéö ¤“À=ÒxGZçH à‚ë«ß´k¤Ð3Ò èé$pŒ´~‘À-2Ï\0:EF6Ç>7)=#Ý"ôŒt’kV ×H à‚g.:ý"-€[¤ðŠtIéé$pŠŒ$ðŠt8E†`*]"C|".‘núD:Éó=Xé©$ô‰ Á=7*="-€G¤û<è8D†‘VÈÜ_%ƒ7d(7¤’ÐÒmÒÎNwH à iœ!Cp}¥€+¤ËAWH'3d$?¤“À2’ÜëÜòí?¯¹ìôˆ´`Yç²ÓÒíAH'Ùö¯V¥;¤“ì_ãŒÎœûWogH'¸ž¯Ï!¾NB_H%¡+¤Ë÷ÔHWÈlßS#]!Ý*t…´âã«(ç÷ÔHWH?WÈÐzÏŒt†ôCÏ÷ÌH_H%¡+d$Y¿fFúBZ°Mï‹®¡âøšé éÒÓÒI®ï™‘žNrÏŒt„døA*ü `™—¡vƒt’mýN²Ï“£œ #É1ÏŽòŒ$×<=ÊR­H'xÖ¯Ò?óì(ÿGçBH'YçéQþ´ûc-·)ý…`Æ:­övÏóH Ó10D áA$E Á G ¹ÛoYH‚d#¼ƒqo"(~#(’#ส"tŽ ?òŽÜì¨Uo‘áGÞq܆<†©07Á`¾FGáGx#ŽÂ8Â(Ãð‚…áM<?â¿#üY#ü/ÏQø‘—Õ*üƒ“+üÃi+üHñÊ~ä}«}ÌáGx)ˆÂœè= ?ròbˆ>¢>ò¾…£W>ò >­ÁG*ºjV;*ªì5q q®#øHÅ)MçÇw®Å^ƒ0S©¸s“÷c¦Aðªqðæäè#‘ÑGB3¢¼«T¢¢œ'··:üHèEø‘xáG℉¼~Äz~¤š0lJƒð#΋áG" Âð¥8üÈù…eµ}$$?òvT˜~$Ô"üHáGâ)„‰§~Äfø‘Œð#. ÃDŠun<† Â8g†‰4?â&gø‘ÈáG\K†‰§~$žzŽé†qi~ÄZ~$žBø‘x áG" ¼mþÀh…ð#. øæ ?i~$Ò\ó›cø‘xñGâı„ñG\bÆñ``ü‘x ñGœ;ãxP1þˆ[ñGÔÑ;üH(AøWáGBrC† =Æ3-L?â*0üH¤Aøkfø‘ üˆóêð#n>Æ9wlE+þH䄸#þB2þH䄸#üÞ;þˆÛ‚ñGüª$%÷”7㸌?iÄ¥aü‘ þH<…ø#‘7âÄS@i€$$@âšw’ü}}}õ€Äµb’Hƒ$‘fçTG "¸Œ@â¾Ä$‘BD^×—–kžZ‚$$Ab C¸|ŒAbÍŒAâÞÅ$.cÄSˆA’ý{ní$‘1HÜ׃ÄmÃ$QbÄ =ˆAâÖb +Æ qiƒ$$ë÷ÜÊ$νc¸|ŒAâ:0I¤A ’Ђ$®cø]1IèA ’È 1H¤1HT'Å ‘Å bÄSˆAiƒ$Ò IHƒ„h… Q¥‚$ Œ$¡æžæ!… Qó)‰Ó0‰µ0‰«À$Λ!Hô‚„z"xñ²\ã¬X„ãÜÖÞ¬vôbH2ñÏŸs*¦ù›ñ‹×µì_Öß'xH"$)~G¬áµ®`¹'-”¤ž–¥&JB×¶ôÎYÔ˜’ÐYè’äß¿x~ö7~ñýÿyüâô‘åþŒ½Œ`üÕßFO:?SüMº2:qëšbCW¤‚®9Ò1tE|bèÊ(ÆÔåTÔ5Å:†®ˆP ]ǘºœŠº¦hÇÐ1Š¡+#S—SQ×߈düÒYß’ñ_"”ñŸùšýö»ïÒ¾]¿ý°÷~Ï~Ò{§ë/‡3~_üSŸ”ÿÉãßÏøŸ!žñÛÒp·Þ—:œ#´¢DõÔw÷þÑþ.öžoîºLó¨®Üß½ŽI¶.Û(“lÝOAÉ6&Ù«– ½ùzïc’­…ðÑSê}ŒIö|ä˜rc’­+)N”æ“ìµ3(Ër÷FR]Ä…‰ø¾ÂŽ‹¸  Þºv‹U¨ÛHëþ‡O+yz+éºx\e)G—§žQ´§·’îØ;òÌòÎ$ãƒÐÁ Io%Ýëî¦K઼V­7ž}ìhä~ ²ú®¼ÎA°ã¶.äuu°õµ7åJð”’܃`k1}"Å3¶Óc[vY?½“äŒ^É ØÚˆìö\?½“4iÖA° Hz'鮋ÖHî®Â‚¨wëgG•:ÀZû¢#Zü£ÒôVÒ}"êYIÁÖ}cMb}§Óœˆ°¾¸0êP+Eäôôwù\è• ‚­mÝ“Ö:R¯áműç\³ú ØÈ}YÁV‡êeß+)½÷ú+ÙÀÖžìÑUXz/©.yºx% ªP;]$W1 ^É9¶2jKĺô^R]Òýf}ÇݨÂÛè ôô^R]«Á3øõ¾éìµ®½™TàÓAIÖ·â•õ8ïï«SÜèúëº~÷·u­×mí*¨0ë6øµZ¢ØÞ‡¿ÖÈzðÔ1øµ¶£¤9¿Þï<Ž*¬½•Tå{ ¹¿f^½™”%|FC\@ïﱕTMÓ#~Ý>g×Ai¶ÞJrcmëÒUàÇå•ô8tcmÛÀעĽ+UßÁµgEVÇÒoaéíô’<ýô¦¶sàk½˜Ò\Uà æÐ?ïA¯wíëí z.±õNRÔrÿl¬BƒÊº÷NÒ$¹¿ÞÂÞ;I÷CŸøuß½¦d_¦w¹ïwW@í¹÷NRµç†œ†y`¤Yû=í½“äjî×€×,ÌÝ‹ª‡G ÖýðZWöÙ·õø x­½„‚û«Ÿ×žçÔ6Ç:·UÝèytYúlÀzô>Ò¸M§ëtŒ‹i^ Ï”¬Gï#ešóÓUP[õ•žÙ‘jñ¾Îyõ>RJž^aª?öž#sô¬óóõ{éÁü >cIÆ´Zêêö¬+=ç¡PWzÞSÖu¥ç\…ºÒsî$u¥ç:5ÅÙÛH)¹ÖîH{õÙIuÑݵ:ï/½½ï».ôœ_C_èùJ€0°0ûDßè9$ôl=¯>7¦»µ®ô\{V?¡7–Ü<°^?&sÇ%&në|¦:\}ð°Âyö|½^}ô0Zâj#j–¸­¨ñÔÝÛHQš» ©÷0| Aï"ÅH¼Û’Zk]è™ z·55²î=§¬Û¢ç>ötêm›jæ}8XÑw[U£“ÞmV}Ú®ðiÃjäõ,÷”ÓÓ¦ÕÈéé]¤ø=m^M½½‹”Oµ5¾IOo#åS&V}MúBÏ£ ÂX=÷Á÷€WÕ7z†æíSfV·ñöéu²FøöY0±rlnŸ¶´ú#º}VL¬œ)¶O[ý‚·O[[kÆéUæöis«§ãíÓöÖÔÜ×ÌýÚ¿ x¯óϯiuû´Éõ.kãxQ[_æ™ù, æU6ÕÖ·yFoËzò“yâ)¬“5ÓnËŽyÕiög~ ÛÒ&WÕm9÷©–6¹zvÞ–6¹¦äÖÄÚóõ¶´Éµ!hó a´f—ÝÖ6¹F­ê6ÏÂŒçAtÍmm“k´NÝæK™mÝîùômž^cnëi•ƒCÛNÒ×̆÷=À£âÏF?&îõÉXrf¯;å༸‹<5.Ø|ÛfÊ5ê6 |!€µe»å?c"üOó_…æz&þó ?òˆõ?ÍËû‰[&þSD/àr1J] îuýO`­º‰r €Ë;‡\”ô¡C \Þ9ä§o/†\%V?í5ÿ1z˜ð¯Ö÷¨7ðOÁ½„ŠÝþ‹Ãþà¿8Úþ«Tý™þ½$ø(Ŀ긠Â(­ ¶Mü+Sû=Œ£ÄÂÿ\œÆ?‡ þ9h ñï¥*š'þkr¡·ñ¯ò~PâÆ¿1Ô€‘/€Xÿ^¸•5þ½ €µÄ¿w…=âß$)½¿~ä¿ACЂPJ›¦ðß ZÒ‚PJ+ƒ•“ÿ¢Ä࿵úòjþË#”ÒÆý`ä\·“=ðå¾MàZ³)$ €Q+à:à§Àeçp&ÿÕ?$¹æ¿— ~%ìuü–·ÿïþ•úu¿*ï‰XJ!yÖ.]o%ÿâ½ÿʱpü+ &yðß$éHJûAÜÿU6€Zó_TüW.#'%¿%$Í뱊‹ÿòw`é%{6Æ{Fûã5ý¦À%¸&þ‹Jÿ"óÁQIðßZÿ€=Hé€cšø¯ª rÿE5€)i¬Y»7À—½¸˜F‰A€Uñ’&ÀL³nÙû€)èè-®5ø/ê þ[w!ø/^.ø/ê þ«ZÞÿE-Á5H°µŒ4£€%A—Fi€ñ¦€UìŸ'IÏ«ÃjãÓ ŒZãm3Í}MµF­€åaµ ;ÒAS/°$Ø×¾-K¦žÀê£ø0£×SÒ8Ižé½{e6Í™¤ù/«ÙüÅÿE5Á™”Z• €Qñ€o÷aÇf RŠ4 €ñê€ñê€Q+à$é™5$*êWŒn ŒÖõÆ F€QO`¦A|Ñ ’Ò¹þ:ñ_­ªÉv¤äÆÿùÿ\§Æ?ךøç:’ÿü¾É.ùÏ-AþË45: Ð-A¬Ñã!º!Ö¨êDü«j ¦ñ¯Ò,ÿ­ÕýQàÀÔ‚€£®0è.KŒŠ£šÀ| Gõz €ÑÀLsîÙà¿Üs7"þE½ÑVÀ¿÷;‰}⟺é/šô•ô7ý¾Y|¼Ià_¦A¼Q7 ø/^ 0õ à(Óü…˜Ê¶vÐä°.gàF «Ö0F<0`‘` Xkð}"ÀrÈm; p]p¥p]yy°VÆÒ4¾ë@¬öˆ€^3/ÓÝnÚØz=H4Y× '„€^_½z&zÝFôò… è•!0Ó4zE(Ô:u†è!)0%=W…èå)Ð$A Œ§@^‡7z…M ½ @­` ‘@`(ziL”b2 "Z10Ò Œ`@­+…€j" †j€¡ø¦!Þ½b%zÅJt^D@çÕ˜¿¯¯—@4»‘„¨$?'@ç4ª# Ð+X" ³zÖ©aH€Ae$@“ J€RH Њ €Rþ rÿÅCà¿(Í5·&ùO_#óŸi”ügL#ÿYBþ3º-ù9²Rà?3#ùÏÇÜCˆQàŸ“€þLS¤?'ü™ÒÀ~î1b?“žÙýYôS…~jm¡Ÿ:Ñ/ÒýBô ÐÏ™ƒüB€áÇSsŸ GîKÉóõ÷)cqŸ* æ¾| Üçï&¹ÏÅö…`_HîyÓØg ±ÏÅ#ö¹0ľx اÂú" ¨Ï[^¤>?è³Ì‚yÿˆÈçf!ó…äùžGÉ|Þ¦ ó)#"_$ò¥DÓ(ª‘ÏYù¬ÄJ@|þÂøÜÞ$>¿_蹿¦QŸÕøBàÓCÍ{n)ò^<ÞsÎä½x ¼ç† ï9#à^¨ï9 po»èRDÜ‹œž¯!Þ“ZñžÊBÞâ™°§> {¡°Jö¯9T°i@{ꮢ½GWM{‘æþÒÚÓ2U´§‘$ÚóS¤½”`UN¤=ד´i@{‘´Ð^—†–¾šæ&Ì[.^Ü%Kß­[—hé»uÇ-}ïø&jÁÒwË0¦¾ šië³å¶¾÷ë|M˜W·ÑÑôåãUcļ²g~ ¥1OVFRÞûâå€Ù”ç*ò\MRž»)¯FìP ¼Ø<”·\»\H›ò–kB<ÿìèž×-—μ(|óÛ„|WŘùέDÀ‹‚ðJòL>ž,Ë ;¿xÒþŒØº×G^£ÍvÑ`»h°nÛ¥¤Ù.KغQúf;¿w²]´Ë`»åÄ]¢D»h& ]•`Å#ÍvQ`°]pÅÜåS wuü{G^­ëæÜEsÏ:§@h]—tyƒî¢ÄÀ»åäM¬Ä»(ðÎÆyâ]”|åßåSÍwYžkŸŸi¾Ë¼›ïJ›4ø.ô‚ïü:w™¤ñ.%ˆ¯ëÞ¥dØuÓ€ï¢0à»Èºù.ˆ¯97ßEãï¢!xñ/òáEcð2ͺͿ›ñ"o@^Jò¢4€¼”4äUÛ`™ È‹O /sGŒÝ<Ø1esò,”íÊ‹ò‚ò¢@y)Ù0—*gPÞ$é¹ÔY7äeÄØÌ›ò&Éóõ±” Ê‹âò&IO¥* /ë÷äEyy©·!/JÊKIcÞ$™Ç 8/%¸V"Jà U`Ü+¡1¯2ÂD ΋ƒó2 î–ˆ4Û\%pž³çe\/DÙõpç¥WL¤¤§Óà’  èM’{ê3 ½` ½È ¤7I®¯òô²4ˆ³ëšõò)ÄÙ ®œˆ"Ò®Ò4ë9'²žs2ëYÜKIϪ!ÁÕÊ›¸—yãò‰È·O„×O„¤q/%÷:çݸ—9á §îù]÷â)à^äÜ˧°4Ž4¸‚"òÂê9Ľj¦ÅsŸõâ Š( ® ˆœpE¤ÁNÜ‹4པ4ïåS¸‚Âooð^”¼—’ý`_§WP¸–à½Ô‹+(¢4¸‚âýä ?½Dh6ã½_„s:»û~WàZOÆ«UÎŒ·Õâs2åí ]îÈxûzÁƒˆ·ïtC!âí,k:̷ײO5âíïG'á€x{Œš/Ó4âíu„i²äUÄ–š ñöj¢ ñö GÁ…x%¡ëf#Þ^ÇžUxµª¡u­ûq}âí( øn¿/Ük¾ÛožW#ßíÏ"Ðæ»ýùÈ@X|·ßزù®$ô6ß•šÖðöò~Ÿœ9SÒ€ç¼ x~ÿ¼­˜m2ãmï\ƒÅÿ¼+zð¶c¥“#¯ôÒQ³1¯ž¢kicÞ3 /³iÈË¢4ämÇ!ßɆ¼HÈ =€¼IrO•çeŠF½­ÖNÓI¾íÐÌÔ«0JŸ õ²4z•æ˜P/soÔ+Í×dÆ‹¼€zÑèõ¶CóX/J ÖK-ÍzÛ~‹®šõRo³^JšõâÕõ¢ž`½Ì«Y/ÞX/Zy°^æÔ¬Ï€õJrMGù¢æ`½( X/4ƒõ2M³^Jšõ¢ž`½xÃ`½jeÒè5÷ °Þ$¹».M³^äÖ‹zö¢|€½|ªa/òìE Ø‹þØK-ÇñÕO@{©åâXÄÏ»+àÍzYÜf½HÖ‹®֋€õ¶ƒmÖ9# ^´&P/Ú¨—iõ2£F½øhõ2M£^êiÔ‹> ÔcËôb0Ò‹l@z¡¤ƒô¢5Az̘—Ù4æeFÍyz¤!/¾É€¼x€¼èÞò¤¢ /Š ¥ ¼(JxÑ„¼(/>f¼Ìº/ŸjÀË4çÓŸ;œ1àeqð2MžŠÛxç º‹·º‹*ƒîâ¡õž»õ`»(Ø.j¸›$˜CÕr€»¨1ànÛQdÃ]¼SÀ]|w.Ø.ª¶‹¬ÛÅ+Û±áv¡sÇ j;fP\—iNÌ ;Ï…€ë¶¬=¾«±Ï„uѾÀ:·BcSë\!b C¬CÉt~Ed:¿"2» ™.3j¦ó¼L¦ó+"Óeaîu~æ~Ø=¦{Qg “€è¢, ºÐ ¢ó ÑEãè,Ò«%#Ó€ôŽMSHï¨+!§3{“dÌSsu 6éÛ®zMzǦ¹ ¤7IÆD•’&½cã\Ы5í'b¶Ôo4@ïØ4ŸôJrM wlß —O5èåS zÇ;O¯è•„ÈÖ ÷zά½wÐsÊèešgsjÐ ½½”4蕬z“äù*@/Ó4襤AïØÃåé ¨¸ ¼¨Ò ¼c7+6å¥Ò¦¼LÓ”÷~‘¸Ðå•äCÞÒ…sš¦¼B¢US^JšòR²bbP^IpŠ”7¢ƒ0›òJB³_S^¦iÐKIƒ^JôBЛ$w×Á&²½÷ÛFÙºM?›óŽãÛ¤W›óRÒœ÷~’¾Lz©§9/Ó4神æ¼|ª9/Ó4ê…d ^èêM’‡u ]­Q/Ó4ꥤi/sjÚK=M{ÇX\Aó^49xïˆßà½Ts_“’&¾* è@|“äù*ˆ/jè³b0_ªÙ0–µ æË4Í|¡¦‘ÏÝf_fÜÄ]Ä:ø¢À|Q@_Œ'@_dè‹võ¹tƒúò‘¦¾”4õM’žR÷ ù2A#_•v¶çeiù¢€|Qk0_ÔÌ—i–¹]À|nLPŸ« ê‹/¨/¾V ¾h9P_èm苾 ê‹J‚úê¡ÙqÓŠ›úT:B_&hè‹$Í|·ØçW@ìó™ØjŽ•=h¶äùú<‘ú2ó{3ºo›°/žöÕS°)û"opŸß5¹Ï3¹/ò÷¹GûxãˆR¼§$Ã]CW„¨†® QM]NE]S¸kèŠÕЕ!ª©Ë©¨k w ]¢º25u9uý@ÖÛ»~Ü®ÿ*¬ÿÄ÷‡ßµß}_ûƒoä”ê§_ˆÿw¬÷º|åþŸ(õ?”É?ÿn ë·ß»¯kì³ä—ãáòq{öq÷ims˜qcÅ“ÃéûçÄeà+~ö‡ÎÕ<nÔÁžãöܽÙ{Ùòà$²µou×ÞÖ›¯Cíû²3ƒJöºl¯ö7•Ü?ða8¥Yïö„9±Ë»zokßxs?[¿ÄæÈþé­ý`hƒ}ÜFWÁºw=s6S¯ï¶®ÔçÎØÒûçR»0÷@ê³â! ÍÓH]ÚŠ—Ï@êºOðiÁ2ˆú\¯ê•ŒÕ¸Ã‚ï/eWÖ;v÷¥7¶êÁ Z¶.þ®Þzï@c1^÷å4ìï¨UàÏÞÕª[?Prœ.Úý #D"®%ÔÞYüÃpƒûòtÔm'$Z|å.Û¾~F¸oFÚ×¥C‹o\~îìé·%¨¯ƒ[ï{ªOû[³ izWëz‰¡wÈ÷Ñ~‰àûÚÁšf=Zœ®PûZ[טpû‹µU ½AIïkÕ ŠªðtT…ÓÞ7„"vc½8ñ+Ârï”tÔÞÕÜ·µÃŸ2:ðþ~ :Î/ƒ ïeÏ["Òá>lRÕš ³²¿ß†_FïÞçÞ·³£ŸŽ³!¸N?ï+Z‘ÏÕÁOË Ñ»1 1ƒwîeâ¨Ò¿‹üÞtÝ÷ÞѪ›~n:ö©bžï{ohUV7$kÇ>}¿+$½©U– ô¼7÷_F„óôö–VY*Д5Z«ÔVœc×|Ò`öJ:ö©â™ïåÿ¶UÔ¾ß*ÎïNyœ­•„ÜóJ:ôé›CeXÞ4µƒÞýá@bE±|Ë÷©mõõ÷üÀ­¯ŽÐ}|Úîëz¸õÕAÐÜú9-m÷}>4µ¸õÕ#ñXV„·ž¶ûF^K~ǵvH³Ÿ Úî[ÛÃmj?pë«P;î÷÷Ž[_Ÿ•»ãlì–Ÿ¶·¾z@KÛ}ÝÝÜúZ±W¨#Dì2§é{_{‘ß‚»{IOI®}ÕìràÖ×(ÝÚkãHÒFßèkk}=T\ú}dm£oAC; ¸ôÕßÐc}0©>ð’8pík¼¹­¬¾U˜)úÒ×òWè…ï±µÕ÷©MÝÎ —¾>+·gmìʕäK_ãýomõ}vž¾>pé«§ë—¾ÖÐïÕü±õú8ÓܘV¯_!xÖ~·½8æ>ƒ'»co£¯W ÜÐüý§CW›ùFïšv‹ 2_Y€°£ æ«B^Qa1IBß^kÁÞ²mæó…턾ý½ð?}{M¤1°&ª÷{¦© ÔW÷#bêõ-‡‡ ¾"§m¢¾åÐòÔgßž¦¾±Ñ!Õ;’xÌÂ8Aè“’¨oß ¥M}ûÆÈL¤¾}aè5RßX|‚µ@}ŸKHר—iàÑ älê[Œ^M}A© ¾—8qA ©ï¬µG˜Ô·0€Áï|!^àwò”Á/pàwÞtÔ!ø6­øÕzîð«ûaWÀ¯ [=¹ü®Cu øU°u<ÕàwZ¶ütå•ÀÏô%ð£Á¯nŒÅëø]œ²E~+ì"¿ƒH~×ýàEüÞFÇJà·2`!Á/úéj*³㫈ýžÐ1ü=¸]ð÷¡«™àï©„LÒߪâþ–¸ôW@= ?¯¤@¾ŽGø÷ö’ ^BC‹ñ¡ó‰5ãý6þé)â_­±$#þé&á_ÙŒ7ð¯:ò¾p§”5ߘª¸ä!ÿùÎñŸ.ˆÿ½-¸Ïüçò4ÿyñGþÓ}(ä?_*Eþó¢Ãx"Š¥P72‰Mj ÀZ‰@ Ps¿k2 ×™@º–ýQµ,jŽþ9ê’! Ÿȉeù){I€Z ˜õ"nú”ƒ A€Z‰ˆ/†î–c Ø èM&À OàÁx.&@m£Ä À÷2˜á”*t?"–÷˜ XŽ%€9`0Ë`ðŸVRâ?ó)ùïýh}¾ø«AñŸy^èƒ5«ÀdM ±XWDã½oúç6FiH€n`½]|ØH€§&`uPìX’ëÐ*%cb}Æ…äC¼¶/ŒNA,§ "aß)ŠÞ¼è}àÁ+ €ÃcdÀ‹[À@7±Pè `h>÷,¯P›*@7±ðáF2ÐÃCxâKñßÍ«%ÄõyèJÿ¢)Èïü@˜ÿYñÀ¿›·Qˆÿ´Y#þã þiçCøWÑ™PàŸF‡ðÏ/øwóºáŸkIüS椿÷Ë4nü³ZâŸ{ ù¯"Ú@þ;ÅXxÝ‚;àÃ¥°îŸ'î5^¼ýFøþÊ!ºšÀw< €®6Ð/ŽxóÆ! ;ÐmA¼y‹Ðµ"¾ÿ0/ _0ÐmJ¼7å5PŸ1 S]+ [ë¯Ä®>É) °vÆqi °>YûÏ%·¦6üÝœiùóÍ>´üQìIï{âÅL4ýIÁžØ¦¿w*Ïáü²Ü“‡=“X‹3‚WSàùá%Úá»)°V -}Ÿf(ÆÀ&†± xžZ}3Mcày]Ê»1°8!0ðZi-Ž“)^‡frÿžMV¹ÂÀgÂ@]zK ¼.m#ƒËD³cS`ÝÊ‹…(°æoL” ÀZ(0+^D*ƒ (°ìFX$Òüw›&›ïýê´õÏJ…> *ÿ¼úÒ[2`ÍæÐêkH s@@ƒ°Û0M# ÷E}¡0vò€Þ?$ÆZ ¨+êÈ€±¿¬*Ü4z[»Ñ€À°  °«2@`íŬµwEŒõ? PˆdÀ4ÃÁèµ 0Ì4¼ ›  aš½Ü  uš½Æòž Xû@ÐÒ èí@™½Ô$jãQ6@¯¯À€±0'ÚX|Þ¡E¤ ¨Y h†¡ ÐË?" «I|?ZŸÉøœ¼ZL¨ Mx0¤P‹22`¬ÕÉ€^7jº4dÀò뜀šÐÄ€¶$‘5ÙËxiûˆ¨%Œ 0Êsb²gi@šìEÏ&^Üz!VJ0Ðï… ¨Å¨P‹1àûÇ”DŒ4`ÀûÆ&c#  ‹¨u‘P«!à[3€~-D@¿J2`P«1 _ ðaLW1 ;RC s"úÅíUÃ,Œ¼~™„@7(!ЦC0 ûPKV1ࣙ·;G@½$ñßÍùO½Šø÷~L°’ þ¹Ëÿ\zò_]kˆ¬Àî俇7wˆÿXÜjZÁŸú³à/P ðçE'áïát/ø =€?/Š l*±_d5ØÏ+k²ßÃ=J±Ÿ×ìb?göSŸûé%þv™ñnÂ_àï¹hÚûñÝ‚ýzd‰ýÔÅÄ~®á/ÊBøãHü…fÀŸë-ø;i¾"ü©?þ‚ä@ï…F¹Ao•`›$ý…ПßBÓßùùеOôçš7ý4ä8Ðßà EÆ^ÑŸóô÷êadhÑŸõ4ý½uºgú{[ëƒg@ú‹þ\⦿7§Mf;ÒG!èï¬sÅ2ö}BÑßÃkDî‘MÙ‚MQ¾AYoÒŸkEúã‚î_E²¶Ù÷:õLÄW_]ò!ñ:ƒ_ÄwÔ1i¢ˆoãÂ\ÄW»¥`@¯ïñÕëÄÁ :{^Ú*#ñ]Ý?áìyʆBà[y‰ïý|p “Ξï7”6œ=O©å)fùR‚÷j-„Y‘¾ž§,’Ÿz{^‹Ì‰ð÷¼´nðÕ €¯Ž ‡Šþž6™Ñì÷ðC'Ï“ûk >s.Í~¯¾ò­ —'³ß#œ§¿g¤ÙïÑÊMþžbI ß²)s¸{¾}®:| ¿²úíÚ‘ ò­¼ÉLþž;#ì ù“þž²Òßs“_.í~vd¤ÝOU ÙO>Š´ú²fÃåóó|aûðùŽoYý*Ž l°ú™Ýiõ{Ó¬“ϧ]‚dõ³ %Œ~öa¢ÑÏα¾÷{§Ïg aô C~$€ÏM£Ÿ}£|v@¤Ï§î©ðÙvD£_˜ë|rv¥Í/’ Þ #x¯ž„øLвùÉKà[yÒNÀgS/ôÐëS›¾HC£Ÿ¾¾4òÁ™®—>;çø¢ÈèÇ Ç |¾ žÀ­E£Ÿ<™Á{öZ#ï…Óló^X/\wOiâž|®È{Y'_Eõu5ðEËø"ÍŠûîÕÂ>· ϶X|[îÙËM¸çýà^5ýM{TѬ¦[²^2’f½Èˆ¬§ý2 ^ùí­”Ü_]¨#e ^ŒI ^Œ7 ^4%P¯´À¤EÔs3õüIz¶$½pP¥¹îÑ$=9°‰ôœd€^$ëÙo€°g÷^žÝ^I{+ϬŠöì‡MÚ PÐ^äÚ“£Ý=]BÐÞr’FÛÛ“ŸñžvÅ{á ÞSwïÙ»Ž¼§îœÞžôÓï}LÆÞžáêù,«œ6æêéoŽhϾ‹¤=öVÁ¿¾àèiW²žµõÂÙ’~žvã°gX9z²# öÜNáèI#`Ï AØ gPÀž‚°§Ó‚=ë!ì¹Ä„½þ>€ôÜ.$=}bDzÚ0–/²é¹J´ó¹ ‘ô4‰‹ô\%’ž†ºì|΋¤ç27éY IÏ CÒó«$é¹Ä´ó¡aˆyrÛ‘‘Ͻ™˜i€yšÄ‰yþNÊÈçј‚‘OŸhaž&Maµü(€µÐîMhwȯƼ7{D×k´;Šyï@»å­øÃßäfsßõ}ÑîâEFb»KxíÙŠlçxX„»óap.Â]¡!aÁšwéÌàîÜ´üp‡ÆhÍ{' ¬À@w  »kÑ\IkÞÍȤ»W…ö½«}ñtÖ¼›—ÁËœ7šm`Í Û]Ã],ËÜÝ‹Ž4Òšg5À]¸âîbÑFs^Ey›Íyž—iÎ;wa#¶+BÌy†Ð]¸ ÑœW«K0×çÊÏ®ìy^Á€îB è.ò¦AÏf"Ð],ŸAwáõ¼³¯¹,zöÞxö2ZôèÛAº{˜/¬yö°Ú…­y§–Ö¼°ºÁšç-nZó|ò…Ö<[OhͳQ[óì{Dk^”Ö<ïpÓšç3T´æ…˜óä#sž6keγ‹æ‘íl 1OïŸhç]xÚòüZšíÜÀd;ÛÉv6{‘ílö"Û¹02æÙ¶³u‡Æ¼4ï=³÷ŒŒyò°ÛÙnÐÆ¼WË9;tÚþCcžµíl*¡1Ï ólÝ‘1O]ŸÆ<íøÊ˜—æ½iïVƼ0GÒ˜‡½zó\À¶ºmÍÓË“5[˶æ}ìãù3k^âhÍÓë„9Ï9ï"'˜óÂ&¾‹œhγ ^è9Ï}Ÿˆg=hÎÐÁšÖ»m›z ­y÷ìÏù{SžLâ;çBKžm†´ä©?ïB øÎYð\!™òdŸl“uWÆ { ø¬(.·¼¶Ååý“ao»¹ÄèW1V/ºmv—õ²kgq¹ågøsÃÞÎÛŠârÒE‹v½õPyÄåÐn ȯl±x ]ïÖ):rnÂ¶ë ƒA»Þ‡[  ââCwpä´©Šf½Uô¥8.tˆ‘Y϶@˜õN!’¸(Úý8DaÖ ƒÜ0ë-‡NêÁ¬W±9é·Ù§ùl@¤Yo[t¢f=Ÿ,£+§±˜f=[ÛxšïGÄ:ØõìÓÚ§ùN%ÀÏæÚõî”È®çÓ^²ë-Â-Øõ¶Ý’>Î÷h!HøsˆÚõìêX.Œ= ÞÍvðÆAöÜ4d¿ð+…aÏj~¶‰È®·élOó1¨ºOóéô&ÑoßäÛ Ãž7ûÌE»Þ0ì)ˆ {2óü<˜ËûéÚ(¹æà‚¿ð4…aÏ1k¶Œ(š‹#µÐ“sù:Í—¸A>VDú³uH–=Ÿøc4Çjý…Ï(èϤ?ûˆþ\qæÓ§„ðçLøÓQÀŸý} Cðç³f„?ïÛþÂø Œüùåþû„ðçŠ7üy÷„ðg3 áÏ€@ú;ï‰ôgQÒ_M9þt¶ß]änLú³Ÿ&àÏ{„?o¨à8Ÿ¶\tœOÅ#üÙÁ[ðGGB²_Ôìg('ûyˆìç½Åsñ);²ŸúåÊ)ŸÛ†?s'áÏÑoÈÚ„!þù« üN‘ÿ¼-£x.‚iòŸ_”ì{Ò¾ç3.عÙè¼¹Îg˜€öæ&†è7E ÇR`hæy>äy>y…“SÒ hOv0 ødÀ8uô‰*B ö¬:K(T‹åeGô©&ç{¦€.>lFT4!A åþHŒ“y€À{öçôù/ åñ,¿5&@PÃ|vÍäa>nÔ ÝàDÀ8©÷SÔ΂0ÜMÁ€>èH]˜…€> ø3Nîräa>º‰þô0_J°¡ª.#”ã# ÐŽ·4ò…(04ÃÈçî©Ã|:wОTãxóÙ1“‡ùè™ïÃ|Î è©:Ìç¼€€‘ì|~StçÔ×Qv>׳í|`´óùE“óá]e|ëÏ;߯ÂZ¼ŽrÝ—.¼•§ä?%)ê.ôþÁsNÅ4ùÜ_ˆo½W8¾-r°ä­þÞqi(cÿ#$ïŒ:Æõ›ª.M:¯Ô%Iè‚,tIb]uL ý¨¹$ÖE™uYb]ÿ®xÒï¢Ú¥æÅ÷;9Í2ìîæÏ›C@Ÿ—B@ÿ$Áþóg :ìîÑ¿ë /Öôæ.ôÛïºUu˜÷’©¨jû¼+ÿu³* R•QU¦’ªµ`ä ULª”Hª"•Tµ*ÙC“*%’ªH%Uše Mý{RÄ$Òã4¶k¼`²nï2¥î zí_¡¡÷Du>¦?þ$4ôïúÁOBCoç—¾‡†þq·úAhè?ñ±úíwŸ}š~ûQ§ýÝçêǽö÷ºþàmÔ"ù}õ.þ[½”{ëRç“kÝ8^Èÿòïl»¯ûùÿþu|îíÅÿø_ÿ£®áªÌÿ›þú¿¿ƒó]$.÷ùßþã¿•·ëu®j¯¿ º°dÙ©éáê9@õæÕÛP}þËØÔoºŠH]±£Ïþ•ˆÔÛœM|ƒ†Öú·ƒQï"õçÎkPX4‚ßèZá„pµ^>zßuÍã¸o­øV—ž5|.ïBþ¬ÏEùáÉuÙjÎÞÆ]ƒ-¨žrþ²íﳸ‘üÁÅ6Ÿ¨Àaïܼ;R:§wù2ÒVÎ&c ±\ãØûvÖÆDKÊUù-ÍU—8--yJáxH›× náGšqÿ`¥Q ¬µ÷¶±?×·ÃTè°§$]o6¾XÛusѸ¾HþTšŠ“5–Sk¹8•†~,kn Î^¦¿®b¢­vìxÕQ­À_ÁêKŠjõ³Ý­¤Xðm‰±…×júÞöm ïÂÔå‡KI>ºvs8ÛnãTzo¿Íô’À6\h:Í2Bнk*^d¿­ÃåÍ}Ãvñö6å]%Ü.`ÛØ[9ç·çH]ÏxUš“‡ïë:Öµ>ÐçÒËãíþ?ÛÝ‹!o¡û(ËU«ðͱ‹ëò†Ïh‹[ÁÐkþ&Ù± Üž«§†CaÛÞ¾¹WS\«õ¯ÕpoaNn[¬c展§£•Ö[a2úk+l¾îðZ¨eB+æÓ°zmck ›PW½Ç-‚kõâ+‹SWWVš:#CKrµä6¼~ðWOеI Ý«SE¾pYχæã3|p¢Ì/!ýºN‚ul?mck’~|¿.]†ë¡ç·ˆ'ZcyÉ<Þ°Ÿ]>0É9œî£ß縄a[Æ­ù!å¶ ¿ ?Ù7×u´éúQȽeëíå· ô!9ßý9Ò<ým¨|ŸÑ»8¦Ïuã5ªÍº§kÞ¯s¶Í§C*JßhÑ Û ç±ô€Uàñó¸Ç€U'8ϳìÅ[7ÏkX¢w• d XUü¼ï°zÁçsö€­¸b#ÍõÙzÀª{]u¥é•O•Ý>§Y°µÂµªsJcÀª<õ]–½ýÚï¯ý¯ãèѪWGiLåÅÒ-Ó$V3É­®À}ŒÑêg,äêË=$wÛîÞn³`›¢.…£õ€½§S_Ë1ZOžÀªka§ÑZ‘uNÒ /ªðѪJ•ÑaŒV•¸6À{´²?–Æ1Z5îªgöhý0¯KØûÀH¼{ ˆñQ¾xc´jœÕ^ñ­*s9ä®Ýýz*§ºsjÁÚw[ºç÷W!Æh­ €£ÔîgN³?­­ãè©Õ}¦öTÇP倪½‘1RË$´·äé‘êò·¹h ºÞ.*sî’_¶q-ì¹ÅhÆÛlóq-ì4Tǵ°c¨^p#×ÂŽ¡Ê·0î…­$´5Õµ°˜[1•Ž‹aï˜OÖω¹µàjIÏ­¡÷ÂÜÊš{aÏe*̓¹•owÜ ;†*p\ ûdska÷ükaÇHå{¨ka{¤:͆©•]k]öq\$5œ[ûFW€©•ŸÃq/쨂ª¬Ë…©•=k\ {D¯·Â>³äÁÔÊá;®…ƒ•3¡>Þf] ;«ª°®œ[Yœ2XÑj=;çVtÃ×$90·–§ó:9·òÍè=[Öb¬‘pž½lÃÞ“u/,ëÚ‹§q3lO­¬ÄöÁÔÊzÖJ=µb<¼•ÂÔŠ÷²­œY—¶¹¼kH̬œ”Ƶ°ûœæÀ̪NQr·+ßÃvbfUÝ.άè‘[¯\³À7'V–ïÁ¼ª~³ö­®_7Ãöhe‰ëfØžXùêfØ­ìØu3쫎º¶G+?¢ãjØ©£ï&Vk91±:§ «*µ_˜XÕKêªë1Zõ2Ëkáȯ۸¶‡+k^7Ãöpe^u3ì®5 š×UÑc¸V› Á†yUݸ"_õhUV;æVߺ<²‡+‹\—ÃNß ±á‘˶q7ìïN{$,ïŸQ-¬YâH,[YSIð*/…f¸A‚kY´.Æ\µÖb×¥\«MÁ“M‚k‹8“W‡¤ ®eÉh&! Ö…—?ë‚íy¢à§fâ? `}á{v" Ö'uŸPpY¸F –®B ÖG¶­DÁ²´‹(X×+ñâ㞯ÆõÖ­§Q°²Ä½å`Áúdµ,8¾ŽÍy`Á·M `Áu'Ñ·–BDÁW»I (X»û¸e (¸–õ¢%@Á{#(XÛ~Û„‚/Û퉂ãÞì~ (XøßI@‚õ¹Dps `ýœŒ6 ŽHà ne†ÏÔ˜¯¶wN_x\fŒ€­vÔp`¥ç«­gù@ÁòÁÉh `9qÜ Ö·Ös°à—·†ž¯¶}ÕAÞž¯ÆÑÆ{«ËíW+]°Ç|UûÉíÞc¾Ú޾€«Â3 ŽƒAôóU}Àa¨ nµñK `ݬx% V{!$(P°5]ÀàpÌj¬ nýÕ Üß~ Z XP]”(X ܧõ‚õ¾á@‚Ãÿ²Ÿit»ëëÒ›=$A’àX þ,èÑKtç# ÖvbA÷=² ›,¨%TO ª_‰õM –ž™Y¢àXm7÷·ÿ?¤Q°f¹³¡(¨ÉB(Xj:g ¦;‘à;õ³t AM›"ÁmyÚmE(¸­Ø¦ j2 –žµq (Xø­©(¸mX+ Ud’à; )ˆ‚'G¢`MïW €‚Uâ^éËÒZ¼9µnäR  &R¡ &q¡`aÏ8ÄÔºˆ‚õŽFJ `é¹'Œ4@A7 Q°Ê<> BÁ(PÐïœ(X¾ŸNÜ>;s Vß¾‚ëÕÜ mÍ‚î^dÁHÒ,8Ì\Ç/ƒnvÂ`­ÎÆâS0è:µœ ºM ƒÛ‡[,„A·)iËFÁ ; ip­Û'››@ƒÛÛ£·æCÐàXbî¿ º€¤ÁjÒ®hÐmA\l&’«)ΉË;øêÒ€]MÒ`•øhÅ Áúª4µ ºV¤Áµ\‡šô@ƒ. ipøE7‚Ë º¿:ÄÁÑ©~ ¬>õ4¶× ÷¥Šen' –ÓÏ0|‰Ëwúè$Mƒ¥åL•qµû§²>^5‰°¿Ëï ÂòCM |ÛõÂÑ`˜?Ìs0 .'×ù0 ™t XË êš,ƒësý: ŽÉ0h !zMô"š8¸½ß‰kÂAM,ÂAÍÓ¤A/@IƒžçHƒ5ºÞ¤A¯sHƒ^)‚ËÐÜÎm¤AOÕ AÏï¤Áº×FIÐà Ÿ¶‚‹sºÍ‰ƒûv¢šÄA/bˆƒ.q°Æ.±]@â Ö(¤Á½ Œz A¯‰ƒ^SrcqÉ1p°¼ßû7h°à æÎ¦Á¨hÐÒ`-ïà Ô:Œ0X«~ÞkÔ3–ð‚AuÁ ÖP„ÁÐCTóÇ¥Ø@¿«KåE|¹_X]ê)À Ÿ Öi:zöŒ¥2“ [¤AõZÒ ÖǦAi! 0Lƒ"FÒ V®¢A.Bƒœ••aÐ@+d5ƒ–½˜ Š0Lƒ,²hðÞ{Á 4# ßywl ë$‘ÝÂfArYÐ%TéÈ‚AcdAáY0ž rï,tHôS`A—Ç,È÷@ŒÜÉ‚* XÐ/†,èœÀ‚ÎÉ,È$ F² ê@t+ÿCaP;*„A¿sÑ Ù8芉z ÁHBëƒþăB¹æAçýS Œg„"9!;¶xP»VB«ù9ÖMå°’Ù»D„š‚E„LDÍA„;ØŽ@ÈâÙZB¾rañQ'!b[R@hµBÖÉ@¨²Ù! „¬¤ÐHK Ty„ª¶€/Ó@¡r: ƒÓDè§H„z"B«!ú!¡ë@"T=E„l.¡’¥F@¨‡Èƒ*Œx]ß<ˆo­qPZHƒÎš4¨7%´4è­Ñ`!i^% r‹Ï4xd+Ð 7 Mƒo’Þù jsD4h iÐzIƒ–ßÙ&)Ñ 7;MƒõR›Iƒu,–@Ð 7ÁƒÖÜN˜FŒƒ¯äl¸"rÁl<Ïo¬ÏJëžÛ¯­4X+Ã#mƒñhpë·"¤1@(XJïΗ(X§Qü€‚ÚË6 ª´DÁ”`j=î¶yÇÛh«Pp«Ë|Ù€‚õŒ‡`Áªå§­~`ÁÐ t½À‚±`íü¯­¸Y°N²‚(Á‚Ü&úWÁ«…Ÿ'œ»þ-Ä2âßB¢!þ•[Ç/I ¨šôWDwMŽ¡KÙ0Û@ü[qøoý(#ð_™ßz½Kþ{?4+‚ÿê¨s£ù¯¾&`Dð_™èšVÈ#ÞÚd¬ãгgh}rÚeHæÀ·ì÷€ï+ÆÂEæÀ:ÆÕOÁx´Ç­o}A£°¾¯þ˜øÏ†=Yß. ÿEš¥˜ügêþ¸;“Mv&¯ï¹ŠZö‡Ô¥œìL/A êÅé;@-„@ÐÃõ“áøá§Þ3ÔÑ‚^U=ñzN;í_F8BêÀwâ ÿ¹ÁRÆíØLþ+ŠFªÕf [H,i€G\øJí°äJ,`4úÊ$À(…ñ³r‹rÏI€®‰XÒK  «"–\@À#_¿c+‚   ž9 ЂèAt&`Iô³"†dµ =m»€% P´€žÆÀ’“ÿ\Ôï»ôÃ2ÔK†x„©@–œ~’÷@€±PVËP/FàA°“Ÿ@€qõ.müH€±¨³£$ÀH³ê½ðI€n!° ,Å$ú…B,¥€ã…PŒ3ÍjúnÓPZ] Ðiˆ€68 zH‰€n н"º=DÀ"–r€€¥öDÀ’X$‰€%0jº` š=?Œž§©0œXä§*" [Lt?‰€% °H€€Eôd"z”‰€¥`À*ItßÉ€žMd@çú¡“½"À€nÐ} j ’=8d@'Z,Å‚=$À"ªÛ"@Õ-T„€ZåB@ –PƒEÔ` ãI›2 &—°”Òio# P‹Q¨))<Î,è¶‹øò¡Ì j^‹] ÿJ±À¿y$YlCK±‰!Hñ/n4·Š%ð¯$þ¹nòŸë&ÿ¹ä?—Lts€% ЃEÄ@ÿøðWÒþ˜€z@'ùé¼(ò+Ýù¹© ?”JìãÏd>×Aæ+0Ÿ‡•ÌÇ2|¥ÊƽT_)ÀÇB@{î i¯H¨üË,D=—IÔ{{ Q¯¤9¸‹ž+ê'¾Û[ó7o•õ<îRü¹Ð^ICÅŸÚOÚ+Í£âϹwQÔ-½Ÿ’Hïg õ~G§&z¿89¦6Žz¿# I¬÷s&êý,¡ÞïhPBíçߨAhi¤õ#÷X뇊¿ò_-º / £ÐÝ9]\¤¢x‡ýü ¼ ÿMä=|Ôpð]k ܵÆ+tºõ÷ð+?á®?¼© [#ÍZÅvqv¹SÏðÉr/¦žw£&lä>Év¾ §[ÊE¶‹ÓÂXnýùúÙÎ×áÈv¾E¶“·¯ýéú¯ýÅ Á°“WRU,¶óí ²ÝØh»H¶›Á @r¸™0x%’l7Ý¿/·þ—ݾèöâp•' Ýú+’Ü|âr/¦žÓÇz¡nýv]ûó>]ûû`»‘' Öµ?%Áµ¿ÃÑ’q7AíÓµ?:aËͧÝTSìÚƒOó亘t"–{O{†\eåÞÓÞÉMàºH<ພ“rûišQr]ø„‚‡+p“€ëz8é€+›Ü‚B²ÁyLnA}³wÐÜ‚Š$¹®Àuý*ÆÈžQp \×w.r]É® §Uˆž®». )±. 0¬ë;¿ºë˃Àº¾óQëúN?rĺ¾“ˆu!Zëæ¿ß ÕõCäªëÔ º€¾@uý 5¨®@uáš+ ÔõwBE±ç{Ȥº‹,áTçû‡Tç\¤ºðùu/T×O~m"Õ•r@un©®Ÿ9P]?ùT×O^&Õ•º’ê†T×O~ÂÕÅPCaª³„TçšHuѾ¶P]´ 9P]8c‹b/b_.ý…;Éc±òì?7‘ê"ì>Auá5m¹ó×/Þ;&Ô•L€ºR Îŀ题|éúÛª³2]¿n¼_ÈtQJÚt€éJ0]7Q V`º*ÁÖÚxµ›PW$ ºþ¾Òò±.Ò‹b¯O…ê¡\[nýE¨Ž™uÊ$¨ëvO„ºþn"ì:sg ®ëújŠ»y„º†©D¨+yu3. l?sk-uêŠP×Ûó#¡.$Ç¢Ùs.rÓë\¹n¾WÀuE®ë ÷3„vE´ Ijˆvî;ÐÎ]'ÚɉÑ® rk-åíz?ˆd@»ð!¸-h’$¢]É´+ ])hWÒíf„Æd3Ð]‘ðª$÷×"ãÅlß[Ï"ãE®4"â¹ ^ï çvR^l º¼Ü_;\ôJ€^H®E¹WÒ€õJ°^IÖëÉ…õЏ’¶\ü+àž‰Ï‚Äç\$>×Eâ+i’øzÔÌøJ¦D¾"ò¹ŸD¾’È×ßwu~Î!òùÑùJå@>ç"ó¹.2_I³s‹½yðàûP-æ+åúJ9€>Ï B_ɕԧHê+y’út:õiýŒKkÝþ{¦•fõÓynâí¿¸²xÔÛð¬ƒóö_¸Ì}8oè­Þþ;ã%ž—ºH„ÛM‰ðe:Ü¿#îÛEP a´¸ $Üo ‘0êLÓí?©uûÜþkTîñößûC¾ýG“FÝþ´˜‘ºo“•(Ô}ñÌR@}ßF<êû¶†±¾/|ޝ·ÿvšJß·ÓÊQú¾ð›tG}_¨sá$wZnRÝwðp/uŸ’PÛwð´}üÄbm¿„XÛ·Ö¥íã§kûYŸBÛçÖPÛ§ïÚÔö½yîÅÞÓ¥HÛÇïQÖö©}Òö´Þ•¶O%KÛ·ß žƒ/’RAKÛwÐôUÚ¾]ÈGußNCW©ûžÔ}zÂÒ÷í¼ˆ&}ŸÊ‘¾OuIß§RßçLÔ÷é+õ}ªIú>Žô}.—ú>Žô}› G†±·åú_Lÿg¹þçu%}ß¾Ó"•ú>µPú¾fèÒ÷í¼,}ŸL¤ïãä–ºOUQÝ·ÓÌVê¾·ü±¨û6~ºOw|¥îsƒ©ïÛp—Jê> ¨íS¤íÓ`IÛ§š¤ís.jû6‡KÛçr¨íS¤ísÉÔöYBmŸ‡Ú>½Ì¤íÓÛŒÚ>½„¤íSk¤íÛøIQÚ¾ÚRöm¼³*eÇOº>¹t}ª[º¾Ÿ"¥ëÓøI×§~K×§•®Ï%S×§•®ÏåP×·\ÿóPPÕ§r¥êÓ ¥ªÏy¨êÓ˜KÕçLÔõq´¤êS[¨êÓÕ®OOWº>×D]Ÿ]º>®:ëúØ)ëú,¡®Ï¹¨ëc]Öõ¡É¤Âý¦!©0h'I š¾mÇ•#eŸê’²}’®/QëúT•Ô}œkV÷ñà!&tG©îs&ªûÔ+ªû¸:¬îsÝT÷q!ZݧA–ºSÔê>U%uŸê’ºSÔÚ>Ÿ´}?)üÔ+éü4€Òù¹rªý\p—¿äÞº¤Rí§ŽRí·å—e+þÞ¸Ú—H˜ž§ jGFÍcUým/öÃ<fš;«rÝ^á|d‹¹§ÌìD„Ñž\‰$Â8&h B×E"t.a‘€à 7nò%zˆI„q€¾ëí¿R7ˆÐ='–4 ÂRˆ°´D¸?4ß%ZB"t9$B*ŠE"½ËDt²š|î1î[B Àƒá¤WƒO9$Æ"Í¡–$Âý†ß‹âßzê^®3öBÛ‹ËXJªŸê_ÏçTLóçü[¿dpÆG×`‰ýHSfg¶–Øô.íê+Û’Rd¥,I\ÖŒ óT_Ù–¸,Ê\–%mÿÖáQä‰qùkú·¾å[voJÀÿÆÿíX÷ǹÆ9}q;ü9¯bÆÌ«‚5‹²ëjU]W³(§BQ5‘Š’ëjU\W«(¥bQ%‘Š’ëjU\W«(¥bQ%‘Š¢ój•dçÕ*ˆiXÎÏû·>÷ˆPzþñoýG^V¿üðÚùêÕôË—“öóuõõ¤ý±¬Ÿö,.Âmþÿ»Ž¥ÿÑ+>JýþžÖŸ¿y,´wéã÷½KOë¸ùQ±Å±‚“>>!F€º}î0ä|'QK¦ÉõÝËA~Þ^Ÿ§Ãw“ž Þqœ.Îë=IŽ”1Α›öb·s¶ø,ÔkcÚ{&O?pù÷Jæ¶oƒgë=ý¸+y'À™ŽßSú–-~ó§£@8œ6'ÓvfÀ‡È4I'¼ð¤Á£½[ž}ß34ý3N‰98psF$ÅtÓ¢ÔħÕPÖJö§¦¹tÒ¯§Êm3ð¶-‹Î¥Ëul{~R<û=C‡Û—ô+™QÔΈ)?¿Î%Ø0^#s…÷ŸêŸñ¼ãÓÐô½ Ì+¹Ó¯g|¯czçM#ûp|×Б~=#]JâãШƒq§åÂ+iß³ª+‚`•^ÝíH¿ž´©z_Û\­êÔ*ž–²yé,þ9çJŸ«Us"œÄ§WO>ï¤8W«zý„š%Í“ßWìåñŒ8„éÖ“½ŽÙ‘&—Y„IœËuä°i½–n=Ï<=MgîsµêO'¹£NŠ'ÞÔÕQït¥üŒ¥áQ°-i"zpñë9çsúõL¿9jw­zl^=9×F|©Ýk¿ÇqÁÒ]{¶¹Zé«tÆfÕJÿû34k,Ö{Àêr†f}ªSÙÍ/‘ò"ZàýÔõJ¨Í‰OCO]â;l_&_?š‹•M¾" î\¬œI38k+ï…›uÔÙ7qv~`š¡YŸ:ûæQeY¬3:k:áE‹_Iî­ö5+ǵݹ·râÌà¬s­º}On­€rÏ‚c%ݵÅu®U¥‰è¬çSÞ3:볦9rk¯£³{ØÔR}OSscÕ rFgí¾–’–+'ñ ÎÚ–~¹ÜŸlì«ìKghÖ¹TãiM>Ž/g¯#ßמúê‹Ð¬s©Êkš¥*Í[«»··û“Oâ̺žÜZ#מí¹µÆËhž!®+\•ñ ç2­v"<Ô¤]*‚ùÍø¬1g7(!gxÖ§Õ's¹µº5 5·V¶æjÜZÙ«ÐÚû’«skåüŠ­í®ïzrkÁ‰™+6ÕöŒÜZ=¦-]c•öD€Öç\$Ǧå:fˆÖûªãÞÎY²æºrsÕ"{ñ½¶8´æÞÊ~¶Þ–BïÜ[£K¹è#<ëØëTŠð¬ë‚ S\.Ø”ôtõYº¶®¹`94a¤º/V ý¨] sÉm™€a/Ù– 8­û– ¦q±`ïß«g€ÖX°¡K»²œ>ïΕ~EˆÖåÝП VÝ{.X ,%ókÃ^ݽsweÁüD¡\Ô¿´X°Í}¦°`h óð <‚¶$¶dÁyK!w`Á#lñAuÉ‚G^΃#Xðñ>üf<"Šìž¸Üz~Z B%TH0¶¶'% A}P F4öm!ÁÈ{!A]u& òJ‡@0Þߨ;A0l+FR@P~ïϘšøyÃ¥'\×_¼"ä£þÄ5p`|Ÿ[š8p†®žM!ÊÕ…@0¾Æíê™i‚t¢*¼boõíp¸”a ýp‰gŒú,†£R`ä^ìW!0^” —„Àx™æéŸxÍÏ…gDz@`„¿ÎÓ>!°íð†)Œ7pÎBà»Òóe"l¡€ÝÏÁ#ÆûKPFÿ[–  uG~Ë ^qZK¤^î­cèÁj€Ài•’Å$Î`ÜI…€ÀPµŒ,X$€Àå–†ò¥%¤#W !ðW Œ>¤.¦/¦5À9@`¨”z‚ 0F'ß-„ÀPë$²]!°Ô•+xݰ@$zÔI1³1÷Ì0º„Àë[IA`©èÕBtÅ„À¶‰±~=¿C’ß;mÇSQ`˜å·+R`œ®…çZÊö€K] À*I ,¹’cB&x‘¯&„Ä@…FûòÉ=¯‰žµÄÀkà+)ÐËŒx=p[/ I~é!VIb`hsÒC‡xg]ÀÀ’ Xr#בD ¼"y#ø ¨7"1°ä†í×X0°d–º@a`I ,uKÁÓ:-á‹üLlj,Äzˆ];9ÐuKš$Aw”$¨÷IÐí# r¢$Æ8ô¬ øpeÁ"º p`¬ú<’cE'SÝXbàõd0 ÞùbÀkÀ,V ¨µ+ ÷¾0 Þ.b@MO1 :Ô[B¨INÔÊú)ÝG" ‹!jÁ ¯¿BÀ’ èùJôl –\@À°”¼2 °Ôô cE] T@ÀØL޳DÀÈ4Ï B@ˆ€WÃå! WÐÓ•è‡GŒí%0Ð#H¼F&ÿé *þ ÆkÙðŸ‚üç‡Gþs/Éq k™ü§w³øÏƒNþ‹0ùO{"ÐÍ!zª·7÷Ul.@¯  ×%Ði€Úi€Ú€Q`œYsÔ €U‚}•«Œü§Ãø/¬lÀšà¿˜PÙoòŸ.ä¿"ÿ¹Ÿà?mÄ:F‰ÿ®Z!ñŸÎ‹â¿«ã–×O8”&êʹp øÈ“:0vèþr«’A°´r¶/m +KHWÁRú Dô‹è#"0¦ù¾ `;ð­GØÎO, `Xþt ßÜ©ÂòüÔEy2`kƒP|ç=ŽS“cÞßY(°ÝÒT‚Û 301`PÇõ`îUAÐÇû'TÛCå%!PW¢ElƒÏލТÀ¸6Ê"b`øò*lÆåâÀ6i29°o"Pp %A݉9ûr¿ ¸Ú@†¹_¹j‚ îc®u=Á6`Okt€`¼¤2 8°Ý0µúy’ã]—çer .´‹årxUò"º0Pý&º1ÄÀÖoâ1P}"–ªÑÿ’Ü­<¯‰º/ ŒñKÅ(0.'¤žž‹l_Ta—„$ T'Hq9!¿Î½®H_@H%IR`,VÐ%(0 ÷Àt÷ü¹³b``i10앳KÀÀ˜=ùš ºfa ºD l=Í Eèº ñ2YP}$ƃ[ÐÏVøö;5ž@ÀR 0¦Ñ Å_"à ËK!`” (–LD@=H"`”"0J~|!ú1‘Õo"`iPŸX*z] ‹$ÏE¨Ñò±ˆãêÌ–€•Ø:>8š] PͲ—@>`‘5è@Ìñ_Ü)ÿÉ Çüw㦜øÏÝ$ÿÅ©Ê6ò_ƒSYñŸVù/¦54ƒÜTÙà_£ýcSÿu|‚ÿ)¨†øï¸j-ÁñÞß“*€Q ¨ý\è>’];!P3_è>ÓåŽÐOIȧD,õK{A€ÊÔÚ&ºC@Ï G—¨9/þÓü%ÿ øÏ£ þãLü‡Q üÅà&«þ4íEø+þÔÁŸªüyþ<Í­!¦žà/ÖqKJ#üq›1üñõ/øs¯Z:„?-mâF†ìWö‹š¸`? Ù…ü¢C@¸ƒ)›/ðÓ@üô¶øy üüª"øy>·ÌÑH†?¿a~zA üÏG_)À³x,ÀçyMà›>= @|JCâ+_\»8*ñÅ™½-:¿"ñ™QH|% ¯¤ò•4@¾¹ë~+ħn ùJ‹|‘) ‰ˆ|EäÓ ù\9‘OBÈWÐ+‘ÏÍ!ó•L [ëF“R0ßÑq3˜O:f>:‰6óÑOÛÅ|Š„ æc¨C!Ÿ >…4ñÉ骈ϙ|n?™ÏI€|ùJã€|:¸ùª+cY’ùœ„Ì§Šˆ|% /JIÊò•$@¾èѳ _Iäs¯‰|Eê+å€úJ9 >wŠÔ§›¨ÏiH}U’Ûª2‘ú<#@} F!êóS õ)Є¨ÏÓ‘ÔçIBê«l«|¤> À}%¸¯´ÜçÑ"÷y:ý<êD¿’ èWÒý\;ѯ”œèW÷ÇBm}=¢_)è§B?…éúÉ ÐOÇz¡ŸŽþB¿"úÉnOèw4øîú)€…ÐO0„~ò‡-ô“û!¡}ï“üäü^äç ~rÎ/ð“_qŸ"äüè;ÚeIN_x“ëÅZPï=³Ã’{ ‰zñÂH#ë¤àv ïùݸ”ë{~$‹jÏZ&Ýó /G‰N¼ç×S€½p:^óÛa+Ö‹C#4„¼æ×ð!Ý·üøy[·ü¨Yñ-¿‡ yËO—ø€zO„$MÌœ·üšÿù–\œú–ß'¾å×໯ÜòãiQ·üè¤Ú·ünÚ.隟¯ÞñšŸoÚñšïîè–o£ø–Ÿ®é–Ÿ.»öd4-Ø“A´nù9Óà]X?ödž-Ø“¼`O¦×‚=YÀ öÆÎ;œ„½±_8öùšßEËL]óc?}ÍW’|ÍOyͯHxÍïùÐì¹_„=ZÉ‹õ<`=§êØ•“­õ¢—‹^/.n¬¤yµ^øùKÒ¿ m‚^HöE­ÑÂR™JÐ+¹ï! ÚBôú8>@¯ÚöôƸj½ð†”ï’Þ8¨a'éðµÿÍ WRô¢”§ªõÆI¥¼®øÑkz’Þˆ÷ç·Bz%H/ü2å÷’ž%$½ñ¾_®Å¸sœø)Ò ¦.¤7.j³Hzã”r ¤iÎåŠß¸¤‘é…d,Wü¢®\—R© ¤D]_’ÞhÔ“‘ôÆuó_’Þ¸¸ ôB2ãÎ"é H/ ü÷…ôÜ+’žÇ‚¤7>j‹ôâ/ç¢Ú›i³É ½Ñ/ðôÂiÖ¶\òíæõAÞè-#Az!ImZ‚ÞˆûÀº½Ñé0AÏYxůï„/pž“óÆ»Bqå/7ÕÒPžóòÂénüòª$÷Ô‘P^HÎå‚ßèPöû‚_‡-‚(Ïåè‚_¿‰V ¼œU±OçZ(oôÁû{IyãÆ'_Q^É4¯øõÁK ¼ë@,*Q^ìÐþñŠßv¾áwï8™é†ß}ðÖoøYÌ+¹€y‘&1•˜WÒð†Ÿ%¼áwŸ¼«Ç~qÜÏrxÃ/Ô.Y;oøY‚~ÎÄ~7,_tÃ/l‰Ò‹ºq¨™¶xÁï¾yéŽü,á¿ç!_ð{6^ä?KxÁOíÓ¿ûæU=^ð+\ðsí¼à÷ãuÁO]ð{^ŽÃ? €z±Av‰z£Ã‡˜/øv%Øñ‚Ÿ%¼à÷\´å俇]ðs^ð{h¨ ~Nà ~.‡üžyÁOÝÒ¿'Íæ|¿ïÁ9Þ÷ûžN+KÞïsÞïÓê~Ÿ*ç¿Ñ'|ÁïA¬ \ðs^ð+l­„#Û ~Nà ~ì’î÷Y€UÞîS‡t»OÅêvŸZ«Û}Ýq_Å>/Ð'u—ºÝ÷ÀåIÏÓF·û4š¼Ý§×í>It»ï†ÉœPÏïPÝîã*û ÒbÀ8z.üâ\Pðˆ-oÔû}ç¶oÐî· ¡B„€[¾ ·‡w–ˆ€û–Æõ"ÀéÄzñô"wÑ"ÀبÜÃý¾“§rÝï;sñ~ßN`"î;õQ`Àð—ýàÂ_îVQÕ^0üe_‹º¯H‚KSÀ€EÜÏçøÓiÈ€{¸¶M P U"àÞP ·Ù Æ® óO`HVG/á|2¿ü÷‹ÐE, `øß}ß'°Š€{ŽC)I€ÎBÜ›È è.÷‹³‘¹òk °” Ü/Ñ&°H@€‘ëXîø•r@€á}½ãç¹Ft9$@p?å¢%p?é‚‚ ¨–BÀ€¥0à~òr#!ÐÏ—èrÁ€QL0NtpLŒbVÓÎýºÏ— ¸ƒ—ìÀ€ÛIOd@Mc" p'¿´ Ð#NtŠ@÷ˆèMôÈ‘=þ$ÀRУKôˈX%¹Qy-“‹¸Ÿ×ûüî!ª“@÷‰XŠîÇù}qñ➃ÿÜMò߾㪠ùÏ/aò_8º…)%ø¯HÀ%øo?øéü(³vZú »àAÐ_”ÛOÐß~ܸpLú+Ð_)ôWÊý)—èO¯w⟊þ©SÄ¿(wéÀÓ-p&ÿ•b-hxcˆuÅ´Sc,ŒrŽKÉ@ÀÒ  %D@ç"º[D@÷‚èö5uˆ€îЃ ,åvnªÊXš’xŒAƒ4 `•K—À€.– ¨Å* C¦¦œØUU;0&öXnøÑüIX –L@À" P š¨E%,™ãTõ,žñ”Oèö°­*/ !  @·…’än 3ãP…«„@³€¥1@þ+uƒÿô~ÿ¹5à?•Bü‹ ªUÿ.[x°Kˆþ•B€Eüscˆ¥1À?÷‰øçÖ€þ¼vI±zîEÕçL€?·†ðçºIEúó¬!ý©`Â_¼?îþ¶çÀ(ÀŸLøók}Y·„¿R1àÏˉðçwáÏ“†ô§ÃºðÏ!ÿ¹òŸÛCþ+¹ÀŠY#þ+¹ÀÛöPñþ øP<‚ÿÜ/ðŸ&ù/ª‚jò_i1øo™ºØxî;oT’ÿÂW}~S‘Ý5YñýŽÇêµÏØwqÂJIõüüëùœŠiþœÇèv_ózžk°Äž™)³{XKì™¹Ï GÕû´%.‹2—eI)+n‡^Õû´%¥,ÈJY’üµ=F·é-½}í1úÏéú’Çè_I𣜠í=Æ«¿:òýœW1c‚MW—Ñ,ËΠYVõͲœŠeÕT*KÞ UVq­²”Je•T*Kî UVñ­²”Je•T*‹¡U”]B«$¦QA?ï6:¼×$¾v}ü–Ûèã7ÜFÿ0~Åmô›®}•îÃmô×sëG·ÑäõËÞO¿|9s?ßY_ÏÜËúi·Ñ-,:Þ•þ¥ßèw4þ£ÿûrÚü{ΣßÄÿã/3’Ý3НçòçŸq#ý&ÿ]7ÒEøŸ¯Ÿp#ÝθA«¿÷ºÒà ØH$ís»<ÂUÙüšÓâ6ø^Àî-?Qµ+ݵcóÎM‹'F\7*{y>h¡ÚçÇœ'µ íŠÏD3t\mµëºÒ8Œ²ÚŸ‰¦¾Ñ¿’§º¥É´‡³¹S‹ûûiÆÙYÕôò ¢…sƒ»Z÷ð0¯ÃopåÐÂ!мA]ßZhò§;,Û_Ét}ƉþÉ4á,ü|pTÚÚ9­ÞÏ—ƒÜ”(Òìà´÷CâÐx^¸ëÞâ^N#ÖÉŠØt"ß;3Ðϸ<gÆ`pg¦øN7®ü”Ôâ¾p$ç`kÆ9]¢u„Ähq±;ÎŒç¯7¯$ª9à´õ}~e?#:JËqˆŽBÚÅBÎM.Ñæ÷æ1ŒãÌxÞ¸ ×"Lï1Ç_¾ZD´¨#A)ù Â°(ÎŒ¥ä>ï ûnÚã´Ưwédx1T=µ0Fs4ñÁ¯õ1s|gÕ÷6¿M¾ÅâbN»ß©FwáÞ§Ê{N€ùµì==ßóÄxvÜ jw\¹‰L{jØxšßªÏ,æ}<=[‡rÓËݬ{*=Ú~Íæ€Â£Ý÷ sRžÓýÔ¯e°ÂïsçÐLÅÓ{–Ÿ¬Ï ¼9æO|(ºkÁÏ6/zÏOF{öy â­ v퉨gŠð5½J9ñQñª•?×üzVKŽÐ¹×" E_¿'ýº¼Iΰa0ufrŇóã¹V;nj¶p²;ת‹ W*½t<,”vÌó-%ñ¡¨çj™ Ó6Ž=—j»R#ôJž\ªš¡bšKUÏjħ¢§NѰԘKÕ¹Òþ± ×È››e‡þw®U-«P2ÍŪN„ŸÅ%Åh¹V9+ÞÅ{:CýÏ…ù9_k¯äΥʇû’[Ë¥ê4ç‘K•²Ï¥Úq9ð•ܹT&¾Õ©ß·°=òYîYW^÷x%w®UÎâ÷esåbåx¾$yäbuɱEŒš&4RçU¦ É¡J"¬j+cÞãÓÝ]c†U­«µ§²ÆÏ»Ï°ª½<…¾çÿξ9?[ôVµ/ÅÜW®ÖŽk~}O÷åe#¬êYç_ŸaUïZN„×:–43¬ê“i¦:´‡Ié\®óËVŸ1UŸ¥óÂZefLÕQ›w¤ú¦¦is_õH̘ª­_\8s &ùöSµÕ¡‰Û>¹Vñúë3¦ê2ãÞÚ¾×rfLÕeÆÞ=Í®ys©Ï ªw1?îáÊf.Ö«²>£ªÞKÉöUõsFU}j #õ}֮Ϩªc‘ÜØY]N*–KßgXÕ¶äš3½ƒLú ªÚ곌 ª£®ù>ƒªö%Í­•Ë~ÆTÅî;»!Uï½ÎšRunšÐäõ«ac½ ¥ëÓyåôÔ)õpsá¼ä@µÏªÏ’æá֊Ͷϋ¶ó¤’zÏ.«æb¥«¡>#ªŸnú ¨Ú–$Gî¬|æöiªÜj±gn¬¼ õvac= êq[w.Õ _“úô2Í¥7¦éØXy²ÏxªQ7ÝÂöðð2¯H ¸ƒë3žj½ïÙÃoÍ1Q΢úŒ§Z¯Xöˆ§º×Ë9}ÆS­»^ÉÀ]¦ÎrR/å»U}T÷g>EDÕ)8ReÝg@ÕV,æ{DT=Ó¨>“ÆÊ¶—ïOuÞ(’ÜXœ4Nuž€yï3œj$àá~ï¹­*V`ŸáTc¬Á¯G8Õq,¹"œêLûºáTÄÌ»S»ªÂÓöˆ¦Ê ¶903šê _É5v§%Û9]?)y2¨-" öM5>ÞðkÜïQuÊ}ÆRª_œzx™ŸMè7ú ¦Ÿ ;N2=‚©ÎϦ|¹÷Mu*,[~…îMuÞ£Ö6?;ÄGH†¾ëÓðüÈöLÞÒ·ŠPæàËÖsm¼¦ò¨0àÝžü:-¼ÃïøVðx±’ðâ$†%SQš8—xLEi¦I<ÂÈ—èHF„À#l™G…ÀcøK<Â/Ï` GØb&[0jº³ò„À÷Ä”OL8ÏH‰…€Àm‡Ç.A â* x]XÒ·÷i[(NæùHͪP_¾Å€Ûƒ›Ë‚À}ÇMoA >b ¥çãÊôCJÅÄßIšr¢@ÙœˆeÉ ÔÂ*•(P±äE{߀o€@­A`¬­=a(KQàŒ® IîU{ëW`à~‹ßÀ¶•Ô—›•@Š÷NN *€&9Ð $î7ç8Ñ)…¡*Ý Ü;üÄ@½…zÁ #žf~ƒ z(ÈqäÌ\ä@½óÄzo‹å¨]¨8¡â@×NTRq œ¹“•V->³5‰Œñ* T¼TQ`$ɯ:¤@—B Ô># tˆ ¾+ TLZa bÛ Ýb ¢Í #zlö›¨Ð¿Â@Åã*j39°4èpËx½h@P¤‚Š-TÈz wn‚ îë Õ^`¨ê¯LÔHï] Xʆ‚ˆ ,i‚rc)Œ^ä1– èÁ!jD ‚q/p_@PÁ½ ‚Ç÷‰AƹÆàœ ºãäÀ€²<½“ýhÈÁqOr*8Ðr` N²,9ÐÃNÔuk¡ ‡(èJ¬’DÁRW¢ G(XªJ,I€‚¼),#IžI‚1êyÐ" †‘Ž$Èå`Ôó% º.’ ‡”$è$ ÌãD‚ñÌ·äP :IÐó–$èéE,åäTçð‘=iI‚’ §$IÐÝ$ –rÀ‚îYÐ Ÿ,¹z"%X°HÀ‚@² Â„‹K° g;aÐH4 ]2hPÍEƒî:pP¹…ƒž(ÄÁÒà`•`ƒåö%4šµ åNI8¸?' 8¨ÖÂA¹\22¬ºp0Œ°®d2à ÂÁ²½U;‘içI”ñªh°” Œöæç Ò I„@&˜9ZB—C Ô9L@(‹¡Ž±Bwî=Šã€<"ÜÂYùJ„4±6ºvávÃß0Nð[EBXi /Ä.na:+"n WÔ„á}6˜H{&@H¸];‰„Û=BBƒõótö¥…O›åWÅàØ„€¹mŸ…|)eÍ#Å Þ±Ò j£fPĤŒ7ý¢< ¿ƒ¡µBåP Z“Åày œƒV˜Q1øà*£ƒR}H1ØáŸQLxmx7Š ÏgËQ/øp´ˆ„aw§„zAU.½à€{h1áµ 6Á„×N)™P×ýÅ„%˜ðÚòì"$œ²W‰„׎ $$Œš· E¤@Âk„; !ý…‹¯ÜD„+ >¡<³‹K. ¡", #V HV†ùt‰„aD˜Ê"¡"¼vœÏD„×ñÜ@„+¡&‰0n\ jI„Q0õ€¹cÅxB]—D¨k’BB?\"aŒ:ÀHx¥ÑzAB‘°´H¹î cï Ʀ†ŒHè± ºDBÏ "a,õ|R B‘­H„1ùÑ‚H¨`XDBÏs2a˜„‚jÁ„žKdB7˜L·qVÕ × ™0Ž\ùÅ„Lx]ùõTH½<$Œõgˆ„×(BBEܺÉDÂ8¹Àܱ"W¾F„šÇ$Âë¢zd¡'"¼Ü†ùìJ„×±à æ´pðz'n*æ@ƒa·;²Ð`‘€5¢ÁÒ:Р^%¢Á«q& ¾­–Ý@Ò`äê ` AM|Ñ`L꣪K&Р^¤Á" ^-oå‰K± A]Œ *X„hP1·Dƒ×™þgƒŠ¼&Œ‚ŸÔÞ£˜<Ò&L0xåÕ»ƒ×ûof *"™XPo² »IŒí6‘,= z`Á" *$†`Ð#AÔ² úIÝ> HŒñ0a°”ô =€„Á(§-0xu*fƒŠT',µ#„MÏΙÎX ‚AaÐYƒj ºdÁ(&¿FK° Ÿ8Y°TTȱàÕx^& –‚ÞP,èñ# z‘“]YÐãŒ÷ T…`A7,XÊ ƹ±%.‚ã®@’Y0®`2Á‚¥*°`¤‚ã*ç½°`Œí vV•L¼.xÁ ú5IÔÛ–(èæâP(èÊ‚±3¤Î‰,¨ý…0]Èß`ÁÒ:°`äyÍ`iïøØXÅ‚×ySñtÝdÁ" –rÀ‚% X0Pá\´ƒ~)’‹,èw YÐ/v² _¥dA>“½ëõÊ& êŒ&ô6DŒ…œm! j— êt*ô6N,° Nd¿ãbÚJÁ1ÍŠ*ÿ=X†R Ž‹vâ¿ú†ž$†nð“\,CW³Pb´ÍBqkZð'®ào¿wZ—Ò*4Ð,Õˆ ±yn«Uèž.HÈ~þðNöÓ—)±Ÿ>.‹ý¤!·Qèñ©¹¶.Ði¨ tê-ø¹ÁÒÒó²À¯ä¢.>½­ ä KH¿RºªYTþIU`‘@ÈŠ­ tª†ª@:ж*й¨ „ÇnkéWÛš@g¢&þ°­ tUÔª`*)³­¤—oëz@ø·P5S hÕ€t¡m= L¸¤T먤Om«] Õ€¼Ù`5 ÒH h Õ€j Ô€&Z ¨Ú¥T]RºdªÕ-ª5 Rº*¨‡j@×M= %ÔJ"= f‰ô€ªœè3j,è7oá/èçi,= %ÔZB= ŸÔ€š8Rº9TjªK h Õ€ E5 Š•þã­tªU¬Ô€-©†j@5Xj@×E5 û-- TZ€]Õ…PèÆP¨4ÒªSÒjd¤T¨têñÒ'öÉg¹U€tªn`+RÈ-Sا]Ë*ÀB’A(L6mõ4m"/PŸ˜ej»MjOªdzž°`”Aè;«=èÉ/j´-‚çCeO{P©]e*„J³.ƒPÙdÈ&TÙ„J‰)`S\lBeýdàƒhZVZB`‘ÀÆÆ¶›À¾°'K ’ P&•Rv^1 öí 7°lÚòÎ4€q>… (4€6æ¤Q(ýÈØ(ô5Yè4Å(4'…ŒB¥ú”Q(ï¡Û(t_-ByEÿ ÷ÒÖóíÓl­p^¸øMx¡žÏ†â¼¶_1ïÁ¢²šO‡-a‡Ë¤gŒ£šO—çtå ˜Œz>]§ã@áPïćW_ä…;±W¢YO]ÔU8±ã&˜õtœõÀƒ–žd=žM…zàú߇c&=n‰&=nô¾ÿwÐHS¤Ç°D&=nȺ¨L"=eJØÃ+Þ÷ÿ4xb½±_®ÿ)´‹¯ÿðbdÔSK„zê1IñÚLz\»…ô8œ"=N½…ôžEÇWh‹¤§0é)Iï¦y'IßLzæ§"=Á IOóÕ¤Ç)+ÒëR†‘ôøÃŸGj»mð)«ZžQ —S çQOiÎSkzš =ÆŠ3èý~ô¤LJôîOŸQÅ Ç ôœ† ç’z|v½ûSÇWÊ!éé% Ôã·'³ž:%ÖÓp‰õT—XO—×*ëìÄzT’õ±æ×YÏGÖ³„¬g$ëñ ta=ª2Åzîa¯KIØã—NÞ†T°‡Ï·f=~e5ë9Y_ Íz–öÔQž“öø±[°§e&ØÓ ì¹\žž‹`ŸÞÍzQÝÿÓ¨ëþGB×ÿÔ`]ÿs& ž§€îÿ1¢“ïÿÑ÷‡PO NÒ“öÀ×ÿœ ¤§Oú‰z¡ãÙ—û¸IÎ3´“ó¤!çi ˆy¾²IÌóbžÔ*Â<é€ì= ñ‰~·´}y³¯*ú.X™ÛÌCm†<Àyû/¢#¤2à×}2Z5Ò›´Ðú+û¬ÚÃvE‹v ý}OÕD”ºh+°ßðsÞ4‰¤¡'Mlè)'²ô¼êÚ–žCždhéÉËÐóA  z:Ó¯zÊpM†žëlèyJ³GKOê³I€Š~lKOš…ÀÒ“Ñ¢„€ élKÏ›'c™zÒ’D ¨Èæ6õ¼o4õ _È€áªð^M=H‡ ®ûbé©€ã¶ô¤¡†M=qÏSg(;OµŽØöAmÐÛN?DÀpéãËdÀöЬWvžê5°„`@…È–ªÀ€-Üš.Ú>!°mp„(t]„@F©¶xðß ¶î˜Å€ .Œ…t-ʾRS2`Ä2_.þy„€±ßßËÍ?b–< À8<‹²/¶î|³Û_"ÀðNŸ, ÀölPÀ§ÃÎd0àû.ý_/¹O½ }‚ÿœøþ:a ü ?šÛrë/œ”zëÏkŽø§y”ø«`_l<ã©ÅÆ3|zBþ‹ãü§¨êâ¿ðû9U_ô ¿»’ÿZö­ð_¼2DŒ—Ûµ Þ=À6x©‰¨‰%ÔRöí¦=&°Q±w`â*(ñ/Þu¸¬üSlvâ_¬6‰}£»òŸžŠ°4@Ø}‚ãM˜VŠ$Àð_ŸG"`8Rm‹™g¼÷sЉ€ñ–¿!É=µo;a=Ïk(D@½é„€áõþX”}±0G½ó‡ ¥ `l­Úy¾ïZýˆ€ZuBÀ¾SwAŒƒwžâˆ€1P˜›jßq@è^‘ÛÃK¯dÀˆp “ý´ž¶„À˜¶ûbçïøœ¤„@¾‚Ä€1kÅÌsŒ:sWõt:s¢Ÿfžž£dÀˆsð,ʾXl‚[Ï{äBÀ’ ø¾Ïhø |w`ôµ‘ KU@ÀÍp/ê>Ov"`t nd€€ "`´4ŒÃI‚#°e»Œ€~ D@¯0`p|°€58DÀÁŒô²'Æ_RClÌÉ„€­ºß‡}U3‰èAlýV‘ý"%z“K.0 [Hôk È[-NrzºcÜ|ØZ¹‘ cêïÙ) Â|l×ç•¿˜9™‹ ØN: "–\€@¹n–º.n®¸Ã%t› šäóawuí ÀvÑÑ)PÇ«¤À8[íÀ>l¯ÊBŒÉÛ;OM‚áÐ{,$¨GEŒp+Ðup¶íÃIô¬|K¼ò2}·pxT=¨>L¡ºþ… úŠþÕ\NÄ$ÎÅô=®Õ ,±+gÊìJÖ»r~f4¥±’¸,Ê\–%¥¬Ú–~CPJJQ)ˆ‚¿¶{é;. Ƙü!÷ÒÕ‘t‹mé–§éÖ•à‡ÿδC>§+iz˜íò0ûã4¹Û1£ÅT‡À.Æ+òK–d·Ò,©º•FIN„’j•$§Ò*©8•fIJÄ’J•$—Ò*©¸”fIJÄ’J•D—Ò*È.¥Y“°˜Ÿw:Qyž­ýq:ý^`¿üð2úâ}õË—³õóöålý¡¤Ÿv8}ÇQãÝÉÿo:œ~—ìÏ8œ~“åpú¿E¿/ˆqßóXh‡Óý÷Nß-ïx3LY ûvÇ7]2ÑÚØü<ÅtÿŽ}¼œ™+5Ó¤Ÿ¹î ×cZÀ4þŽsÎü–Šöw¼ñöúÅûŽ3×ü¼ Ë¿÷u?ýTYQ{´¢†»_NÂKãótv÷4°îžÓ§Ößwî~Lï¶uyÏ(WúúÜÖâ~öéësG€¡W2·ªW‚9¿GÓôõÉ›ðwïWºû´$|œÅšä• Ü–—äééîó=–Ù¯ør´¤¹3`]0¾’1ÍhxéþŽ(ï÷šäˆ»„g§iYJıêip’ó>G~D¥¯Çû¾z~Du®6Çr~Œ–w,¦«gUw–Ü9ë í¾ïžî>ë}>Gù¨{‡»Åö+yÒÝ'½\ÞáÕn_Ò̘òÓ…åŽñzb¼G-ù9æ5äÒ‹g:î(xô"Îêò*Ä'õõ:“ß½‡Âxc–ï@P(O«à»#‚ãNÃAòÝñ„)R~SL¾{¡ ºzòÝ£Þ@ssz%Ï÷‚wGœb€wGœY³IwÇTóÎ&èî•$ýM´;BÇ»'%ÚE~~Ò'Ú½d3v¢Ý+!ñíÞ\ˆIK´ó]y¢Ý1•ÅYN¢Ý,u%Ú½iŽToíèh·HF:ÇŽ ‰‘‰v¯„Ü´{%ÚM´›þ²7À^l@¶è!ÚMIžµí^Ú@»#&áœlD»#Îò€´D»Zp¢Ý+!›í^I'þ%ÚÍ’÷$ÍD»cÜ8–혊hWKN´+i€voìòD»™æIüK´;â«s«h7kIag_$Ú½xŸÚÕ‰v¯'"²ÝtcžK´+‚$»Y,Yon?GЙ­M²;fŒåÙk]iÈ®4dWJÙÕ4Iv³ä v¥r€Ý”€¿ìŽñÀå7Á®60Á®<¹®–›\WRL¬«)ë^ÉX±î•@³G¬sëˆu5MbK&ÖÍ4 ´ä:÷‰\WËI®«i’릤eíÉuµ=ÉuµœäºÚ¯äº’&¹® ’ëÞª`6®«‚»R.À®¦I°+}ØÍ4{»Wr¬`WÓ$ÙÕ’“ìŽØ2I‚]­*Á®²+UìJÁ »š&ÉÎUóûïIvµž‰v5I²]­&Ù®¦I¶+Õ$ÚÍ$wRg¢ÝL’G2 Ý+A,+¢])hW%‰v® dWªÙUI’]©dW% ›ª«J²+Uuìª.øÎmõÒ`wÄš;»*ØY%Ù½˜fìjš;«F dW%'vVç‚°H’ìj] ;ë; 7pvVçJ²«uÝØYÕu ]M“hWë¹³ª* Ý”LUÐn晟”‰våQíJû€vµà ;«Z´«ivVµlWÓÜçºXÁv5ɃUC¶+•îJ?w¥À]•$ÜÓü-ìÄÞª®'ÜÕLöVWÞ°·:MÇæêæÜØ]5€»šæÁîjÉ„»RpÂ]©;சpW:”pWŠL¸«Y&Ü• ‘pW+pWÆ$ᮦ蹧ºŒœtúùäŽêJ_¸«ŸpWþžpWjH¸+ýH¸«‚ wµŒ w¥–„»šbÂ]MÑî¥È wõïîæðÞÙ¬ w5Ë„»še\ëx'Ý•,Iwex“îj–Iw¥Ð¤»ZF¾”aÒ]Lº«%Lº+%鮌xÒ]M‘:õ"˜tW³¤bSÍú ÇÐ<¡¯ <úë²A7¤ÀS‹¢Àƒi¨x'¼–Y ´wôeíÝOmÒÞYãGíÝÛÒÞ]DMiï,¡öŽ÷2¤½“ßiï"ͶhïJ.hïŽNÚ;y¥’ö.l+{‚!´wº>#íõ–ÔÞ•4ÐÞéz´wò'%í]•Œ¼tR]í †öNwn¤½ÓeiïŠÚ;µw¼…#ånáHyç¡ òΙ »+åBw籡îÎÅPw§Ë<ÒÝ9uw! ZÐÝ•\yŸ‡“º»RHêîJÐÝùySy§KRÞ•z ¼+CyWÒ@yç’©¼ó  òNŽÓ¤¼+(ï<¨¼ã5%éî\9uwº!'ݧuw¥`èîÜ-èîJ »ó³ƒîN3€ª;M©î˜Dš;Íaiîô`¤¹ÓÓ”æÎÅ@sWj‚æNæNC#Í]©š;õRš»’ š»R24wz¿Ps§Ç+Í‹æÎ¢êÎuSuW$PÝéΙTw% Tw¥*¨îJ.èî4³¥»ÓRuW †êÎM¦îÎi¨»+i »+èîTÕq. îÎOÝ])Ê;?*ï<¨¼s)ÐÝ•Š »+èî<#¨»S1Tݹ&ªîÜ>ªîª›*‹TwîUwnUw®š»’š;?mhîJhîä숚;/1ªîܪû*sQuWÒÜW%9¹¯r¸¨ºóSuçÁ¡ê®H:÷UKRuçUGÝ]© º»Òfèî<ÐÝi›’îN£ÕŸ&UwU‚mU§êÎ‹Žª»’«}ì«ÒÝùéQwW$77VvŠÊ;•w¥äá5‡Ú;·™Ú;µw®Ú»’ëäÞª4öV >öViïÜ@jïÜ-jïªäùX±ÔÞéauºBå Cy§÷V ÔݹDèîJ©»óàBwWÊHÝ])#uw®3Uw{¨î<Ð÷Ýê„ê®Tª»Ò„TÝYÕj„æÎ¯hîœ wnÒC¯§Ê‘Š;÷ Š;Ñ–-z;·z»*­N½])c`ãä¾Å[ÅW=w.Š»"HÅ]Ô¡‚ÞÎý„ÞÎC½Û ½ÎKÔÛ•fÂ2Y³z;× [fÎïxy6Ìm3aµµn]è–ûÎÖy¨%ÌÅͽ+A 0§P¦‚¹í«ÁÜöÜÔ&Ï)”©x.®ûõ$Àä9…nÏmÏÉsq^Jã.òÜ6àÞD<çLä¹í°VUvS²U•]Mž‹Ë‡„—ûŽî¸‹çŠöXSÓê\×Ý?V¬¨ÎP]•¬{¬°ÎÓXW’ëÔ>aÓœ{¬°Î-Ö öX—ܽǞ+ÖYB¬ãIÆXç4£¬XaÒëT»°ÎiˆuNC¬³XWÏÇ¢Ö9 ±Î’›Û¬*'Ö©£Â:çÖI@¬+‚enëT °®€uª•Xç2ëŠ ±®dÖñ+¬s-÷ÚJ`K˜Xç¿'ÖùïÄ: ëª ¹NU‚ëŠ\§ZÀuU\çBÛÒOrà:—®ã™_\ç,ÉuÎB®+‚±Ž7¹NÃK®S¡àº’å\F‹\g¸ÎÀu-rS€ë,€?" ’ëJ-à: ~Âk³yÊ5» ÀgUܽûsG’÷vÄr*¼×qƒŽ¸§s²pï¼èî ¸w62"qïôÜ»6ºb!î]J´wÑÖS´w!„®iïâ5AÑÞµ˜`n¢¿õ®NG,D½ awz‚õ.– õœ†¨ç4D=:³6êYBÔ“D¨W$¹ 5Ú° õX‰zˆ¶dÒ _¤yޤg IÏ’žŠ!è9 Aï•´EkWÒôœGôT09OIÄyÎyÄyNCÎSåâ<§™œçBÈy–€óŠ%ä<×Cλ‰Ùœ§¹'λ¥&´覆ëJ‘<)ÀÓlà…+Ç”𜆀§$Àãø‹ïÔCñF|ç$ä;=iòŠ%Þqªï˜Çxg ñŽÓÙx‡‚Mwî\ áNIÈvn ÙΙÈvœ?f;vÛlçrÈvj0Ùβ2‘íT·ØÎIÈvª[lç\d;vSh'ÉŽßdçæ‘ì\7ÉÎiHv|Å™ìT²ÈN¹Dv*Ydç4ùNFœ5“€ìœ„dg ÉŽ‹ÅdǹÉޝd“ÓìŠd§’Ev\ª&;KHv-‘¦ÉÎiHv.‡dç4$;§!Ùi4Hvìô¨Hvn ÉN5‰ìôìDv‘s‘윆d§qÙYB²ÓÌÙ¹v’:!²s9÷Ç–j²s9$;çÙ©"; 2ÉÎ’JÙYB²ÓƒÙ¹’Z,²ÓŠì´$Dv®‹dç’IvNC²S{DvÊ%²+ìªj¡ÈN&²S]$;-‘±ÈÎiHvê¨ÈNUdçæì,Ù©Ÿ$;58ÉN}$Ù©ù$; @vjÉÎe€ìÔv’+Ù©$;g¹×V‚ì\Ç$;M ’æ6ÉN5ì”…d§Ž‘ìœd§Á#Ù©$;WÛ–™G²s ;ײSOIvn'ÈNãM²S¡$;•A²S³Hv€ìÔŽ±œ¶Evê ÉÎ%€ì4|$; @všæ$;ײs¡ ;Nƒâ…yô€âTô=JœóB¤œ˜RRý)ÿj6'B’?ç…yßö ­Z$öwL™«ZbÇûŽ¥,JjY)«eQRÊz^K«ð»”3%¥üþk{`ïÒŒ{ñ_9`þ]§Êýúã˜ûó§<0ÿ0CF{çÅ9îç\›Óè˜vK*”dßÊ(©úVfINÄ’j*–$ßÊ,©øVVIJ¤’J*–$ßÊ,©øVVIJ¤’J*–DïÊ,ÈÞ•U“¨˜Ÿ÷À®q<ßmÜx¶têgÁ¾eh瑎W0)#‚Û'háÎmGà­÷,q~³¿çñÄMöoÓ¹s>Ž—€¦»·1¶Æ‹ß«³çñžÞ§»7úhïYx:sÛá±ì̶ç`òã=ßea2g¤cNáÔáÔÇ óWK{:õsŠã˜ /‚tê†æá€ù›=Ä÷,y?w:0¨é=vŸk)jpéçþ®åcíC¸`/Þ)Cò,Ž!÷-^L}‹c¯Îªßßh½xeTw¡¯äLל𾂑Ís’ ¾95XgË5Hǵ¯¤§wÎÞC2˜¦gÎé×=ðÏyc‰EÌѱ<ìˆ9ºN£ˆ9ú¬’ýúxsô¶ÏŒÅgî+9{6ŽuGÄÑê¹ú•Ìϯu®6Öp´{Ÿ‹»ÙW’Gõv |uêaG¤Äùà#ðÝŠ·““i"äèÚ…9Ú¿ÙAó+9úâiô•œ'‡S¢M?Êžæ3(ßZnkO¡Í€¥e°"î×:‹ãêc™1½Ö.ЮQøú²¢ú¶–;£Ì-]ê.q_É™¨!G×wM„­þP_I;>Þ5rtíCOµgyCEÌÑ}yƒöÔ{–w_ŸÞqé7~ß‹?×}»éW êÞs/õhÝð»Ã-é+9n>ôAGË{-¢Ž®KQGŸà•´{ñÿûJúõñ¾¼ïcéw]ß?tt}tôZjŠ £Ï2¹„Žðh=ô—«Ö<Çç¾úœŸûj„Ý¿9"Æ+¡×\àÓÖ}õùðš’çcª?ô›ëÖ<çÇ\à9ׇ… DŽð| Ÿ°Ñƒ ±€_I×®ŠYA?Z÷lOqGkŸF[gú¾¥t4/Îy´acöx´yìkbOú^}òÇלm}ñb]ßúñšZ'z¼¸$÷êè:$¹­¾ _úö˜%µ“ñ ¾JƺX£˜u¢ïvôÉ);ð=/?ø`µ#òh|sàþQ‡Ëºø²|Ýå³OHÂUÝñ°ùѱDæóÑ¡(/@wF$ö$н\uÐσûߺケ tG¬…3ùíH—ctÍ  ;â£ïžY&н8†[WèÞŸ-u ºc~N¬ì颓¾œAtG|%~pÛô•vtbå$º#ؤÝ1NÌÝ–Ad“èŽÐÌÏ#ð$:;ˆÑA7G–0=lÒñ3ˆnܳÙ×Jtö' ¢³«hÝ4öÀÝéè:­DtGØlYèHœJD÷þ|2¸8ˆn:ŸÎgšDW“èð¥@@gwÕº’àJ?~M´6yn:¯YdK?~Lž{Wz£ÏUÁt:Y~Žlö tG˜@ô|{%Ð9 n¦!íé“ίIt‹äLœEr¥7¿*Ù~³XK~Mïàm:§“wþ¼Ó¡_É2nÉò¤K¿’f}sèVÉ3»ÐPèŽÐqTž³cpòÜá­òœ]Ž'ÏÕÑKžóc$Ï-¥Lž[rMž[$“çê³Kžóó&ÏÕ§™Àÿm×2i®Î´¾=Ëø%Í-øÀu/“æê'ÍÕ~&Í-iÚÁçÀrú¶¾;"E”LwûâŽXÎ4á–Ÿ÷Ç,ºá ל(W2Ýp‡ëj’ä âºqIruFÜp‰[$íþè@’\­ü^'Z‚Ü’åé A®Jäj/ŠPÉ\ã #EhÒ§&ß¹%W»Öºá ·äéû€¡yà"·Hžó³p’[jØOUr‚\mq‚\Í• WKN[rÍ@^,‰rKDЍ’çc©&Ê-uß'£q0ͳ±‚»‡Óc‘(WÊ™(·üÞsCí&®ËÐ’£­Ï,Wj˕րåIkkÀrKš{[_7`¹¥®§­}@°ˆ’bŒu®ƒåÉ~­cL}y)'YnI“ŠK•óþ•ÁsçûBCT4tï‘eFÊ€†î ‰ºwÓïACw"Š 5tû@¼{jèâŒ6’‹RC·¿[Ú•l Ýû˜÷tgÇ2tï» ±† º×0¤ £g(èüw(èÞ×ß•´ÝûZ8²hèŽ;¿âHCGïÎÒÐ÷ª¡³ºã„Ù5tÇy¦¯ ÔÐŰ%I¥†NN¦SCwœ0ö¡†î¸Ò— º8?¶L ºã‚5*èŽ+ÿœÚ¹8]æ_S9Ç¿B3çêZÃn;5sV”B3‡ìPË•?§Z.jÛ!€Ç>T­œ|_S+w¼G¤#I1µra£ Ý_ƒÇ¾“h™Z¹RIjåŽ7gª$Gº–<0e¡–“KªåÔ ©å”Gj¹E'›(Fz9ùñ“^N^ö¤—S㤗«å4xïÛñi(õrò¬(½\­)õrµ¦ÔËÉ£ôrr(½=øI-'ÇRË•b –{zª•¥–+‚ZN¾¡–+„Z®tj¹Ò˜ÔÊ•~C+Wz ­\•¤V®œZ¹R´r%×±ŸKhåܘãx–þ@)WÆJ¹2E ”«Å¶û£PÊ•‡R®¦I¥\­ë¹«ßJèääcR:¹RtrU²ßôŠù\•¤N®4J9ù…”R® ”rZ¤RÊ•ÁR®¦YüìJ+W%c_™J-W$PËÉÕ¥ÔrU’j9ya•^®ÌèåÊ”…b®´йò`¦b®þNÅ\m_*æj)V¡–seâ@1WžsU²Ã§Z Åœ§ ôr¥`èåJÛõ‘"õr¥yÐË•Á‚^®6&s‹äùb(æÊntu«Áb®¼œûö,­b®æ¡¿[lRÌ•Å\•¤b®JR1çáƒ^® NgLwKR/Wžôrµéú6wA©åÊÈÜ«ï[iåJ—nz¿U=ÐÊ•5­\Íua?Õßt«@+W%ýúLs¯Z¹š"µrµ}ãsW…V®ä‚V®äzè WuA+W%t‡«†V®lR}âj,ž¶ŽècŸ¸,·?}€V®,håÊ´yV¿¸RÊ•nB)WŠR®T¥\é”rµœsÝÆ –«…pž†mg,©åj®ûüb¨åÊÃZ®¶8Õr²¬ƒZÎ5Q/ç<Ô˹\êåj)'ֳ˹¶ï%_w=ZJ-çÕrµª«‹ALˆRyÆAP±Œá,c¬ojå<žÔÊ•\´2Ö´¡V®4¶ÉÌõ;•e^™Ñ/ ½Ñ}VÒ[ŒÌSí+ß÷D~'½ÅEÅT³€ÞÞ ›N)HoqMà´Á§Ì¥Ior!&z£ÓRâ[\lܪ}¥ ?o1¦·}$¯¤·¸ ›Î¤·æÔƒÞâ<›(z«‚¹Å ‚=ëLz A¯ôæ ·*ˆ"ßýgm\Lÿ™;5‚ ·ò÷Ä·"H|Û÷Ênï/p&¾ñÏ oåÏÉoãÐå%¿¹üÉonø åßø+áM¿Æwô5Ÿ!Ð͕݊ Ñ­ F¶† Q [i^¢ë|ÖìÉm¥ Émꮸmïum{¶uŠÛT®¸­–“ܶÃlзl%ËH ÚjšéºüNh«Kh‹47Ì+Új®„¶"´•r@m¥P[M“Ô_nΪ|ó§Q[éÕ¤¶ZwR[•$µÕšÛª$±­JÛª$±m‘Ìý¥´ØVjŸØVòÛÊHLn«)’ÛjŠä6}Ó·Õz’Ûª$¹­J’Ûª$¹­Œ'¸­JÆÚ^€[´ø^Œ)kš·RÀ­ôàVÓ$¸•ºn5M‚[­=Á­–ÜŸÛs×…/pãòµÕj’ÚÊÔµ•ÆÚJ5 ¶ÒP[©ÔVs%µÕ’“Újš¶¾G@m¥Å ¶šæù\† ¶Úšå¬~‚ÚJ9 ¶ÒP[M“ØV%‰m5×t]îºm5EkÏØVËMl«-¾±O:ÍÓØ¦çGû€m¥ö‰m¥}À¶šnmÑ80›b¯t Wû˜â¶òL@l‹äþx ¶Ò›ªÛZñ¸Ùtd¯UÉ~|Lq[i €­4ÀÆŠAkµkÔ–Õj‚~}Lž‰je€jåÑÕjšDµR Pm‘ŒÉ T+åÕªnnK®DµòþªÕºÚGkÕÉó1=€jµîçüìÜÝVÉç^ V+iÀj¥d°ZéX­´g²ZÍs3¬¶Hž— X­–“¬Vs%«Õº“Õ8mj.$AÍEÔjŠý^·!‚š† V%×¶Nq‚Z•$©yaÔjš[©Ûsl¥Ijî4Qm‘ŒöÕJÏj%Pm‘Œõ HTSÉ_¸I–r-¶±åfë¤0ëÖî•Ί² ºµƒæÔ­]°5’níâ$êÖ.˜ÉÎÚA;FÀÙuójàì‚•–àÌYgª5éÌ%€ÎT’¢3 :ki 8s€3]ü#œ5(fg­óà¬Áêp¦" g v÷€³†;‚³µ®à¬Á¬\pæÀg.|æ:€hní‚—­ç]šª ¡©ß„´wçN•!9Í)€j Wm„j¯ •ŸDµŽ[BµŽ B5gª©™ µv—«oåWn1ÎTk² ª5™ß՘ɨÖüø`T{{¿˜€j7Bk]—QkáÙUÖºnF$¬•߀µ®‹0„µ¦L„µ’°ÆçoXs§k.‡°¦.Õšl+Èj|êfµw»ß Q›¬V~ƒÕ‡.I…_¼ù:à]ã}ä—ßçeDx¥‹ºÞó-hc\ó›S|Ì¿Q{ˈ í‚¡Éž9âe_PÎQ®FuÒˆÈXOÛa”ñ²Éüèô¼…AÙ5Æüè4£ÏLöy±h~t æ=!˜ßœží¯$?üÆH§ýü‹&ó›SŒôƒ\ùá·|ÎoN×&=ó¾xÕ×~Ï•\Ê=Ž+;@ÏØÇqÎNïÛîYŽéK#kJ?SG¸Ç8×4m~qŠºS{}~qª­Éï¾µÅ÷üâ46ø«%ùå·æ³”tüþžß}KMç6¿8ÅΕqœùá·ä oÿOHèyî8óËoéC¸ } ß¾#<¤®µ‡è¾ÖÕFö¾ü޳÷ìšïìý½ãµvœÏž]hп’'»àŠòËo¤É—îqmgvAÍ»òËïü¨tBòd`Ìp\ùáw¼«| Éyf,‰¿nÝu=Ù|—š~K{¯~f\H~ø¨ʹç§ÇyZ¦¡ï×ãgö€Ît¶Í/NnNÛžì†&B÷ö¥àv¬C{ÛZl~ø-O)"÷®]hùá·J¦}LmL~÷-Ó(ÎìxX˜Ý;vZ…»w_›“_~KsúÖ–i±{çR}ðyéˆØ½³ ¦gG„ï½rù6” q¤e„ߨüB¡µûG¿æ’üæ{çjõ{Q,~²|\º±äGç ÿEäwD¼FæIòÛâ`‰4I~ )ô‹™ m Ðo‹À¥ û… PØOWÿÅ~ïËž`È~Á³p@ö³Ay²_1>¼Æ!—ù`¿r7 ì§‹Mb¿PÖ@ö“%)ÑO·Š„~źègëR¢Ÿ¯zýö.$ŸèV1Ä×D¿˜óp _XG¥~’è«àYØÏ†d?k5É~Vs‘ýh@&ôÛo|]úÄ€¾€~a´C8„Ѭ”È~¶."ûYNö³ìW<ªa iÉ~Öî‘ý¬6$û)äØ/¾úb#ü±êø{SrýÙ(ôW†øgM"ñÏŠcò_m1œ¥•Üb9øKÛ¨ü·üNƒ·üWzþ›qÊA{ÉòC)þ;bQ œä¿#Þ&¨+ù/Ò<$ÂÁ>`ºÿŽ0ÜA]ð—öÎLòè8Ö>À[šŸ ø¯ô ü½"#&ÿ•^ÿÞ§ˆ¥Hþ“ËNñ_éø/ÌÄp:ÿ…7ð_‹É1Ô7à.°¦HœZ” oi–KÏ€¥ŸÀ*»4÷Xz> °¦H¬ØþxË–±Ö4‰€¥ç@À#6’l1°¤–žƒË3Ÿ X'F/I|p—æ^«Æ?î'p‘¤¿´w¨iB`é' °Jk¯`þãñš8O9ÿ!Y° °«^…=àÀ"–~ƒß“‰XsÁ­°VL‚`éH°Œ H°ô$X%Ð…ûyƒ«ä^wÖŸ0Æ‘p3žmQ.°¼M5` HeÁ2dÁ’$QÐÃJŒÐÆ[šçå´\(¨§L|O~yËE$®ÏÙÜ$ÁE’›Õ›«£à1]ó¹HP¾ÌE‚‹$7«SºN`\Hº! ÆÁúF  œ¢ åh](Xs% F.x ÊY:P0º_9 @ÁÚ¾DAKˆ‚.…(XÓÀi6Ü´‹c¾P³Ág¶:E,™®õg‚ ¼³ xÇ!M‚ ‡ èNåÔ] ’i‚®‹ èr‚qÎh¯FJNTÈ=˜À@Ob`•t8¹wÍÀ@÷€è±!Ò¿1PÍ!zø’]5)ÐÅ’ÝiR ˜èn’Ý`R`© èæK@`© X žXŽ0Cô³%z ZN‚@'!ðs÷.»–äHzîü¿šÔçrI}.‡Ô§êúÊCÜëU„¾’ÐWR}å©I}%°¯äö•`_Iö9…Øç'ö•<À¾’ØWRÎ}ibŸ]bŸ¿ØWJö•<À¾’ìcÊïÜš0êõ dÛð÷/õæ½­!éç@½¸Ž IzEêÅñ± ž|¨ õè´Á¢ßX¿ýÞiðAå ú½ÄEóNˆ~*šßIÍšßûȲ‚æGoí?Óü쯑šŸÜ|Jó+)ýŽCV¢ýÔXÔüÞål[@o߆^ÍÏbgj~ônÍ<çZ ~òv)Á¯¤@ðÓ7JðƒÛzë}ô)oÁÎ:(ø©nüèÝ‚_MsßK²!¿ò ü6[§Bð£ÿzq^©8/àŽÜ´Ã¹¯SŽßP9¯Ô WSpÑÿmšôÁoß?H¯¦@ð+õ£—m׿Þ(m£EwzÙvž.~Uc ^©ÏD= [’^© HOQDz¥z ½ÒÄ ½šÒáä×å$éyDõò@¨WSpÓ¿¤<Çò t³­WƒôÊ«OºÙvJ’^© H/^D><á闯蕄?¿Nx>êÌ+Y®µ?€òjM’òÂãÆ¹P^)”§H¢¼RP^yW£‹mVW nË4CÈ+•äÕ”„<Ï`¼Z» >~õæD¼úæD¼’Æ+MÈ+ïä•WMÈ«9ò–”‹_Àgòê»á²M߯‹¦¹[Ïš’ŒWÂ'$áÕWÃc›«7 ¯äá-)¹˜n]•„WêÂ+c„·¤À„ÆïNÂs…xõå xKJ®¦þ&à•^À+Õà-)ÏGõx® ø®$$Þ•ÞÅv ð®ÔxW꼫ïëD¼«õ…£bWŽŠKB®¦® ø®”r3Œê¾«yJÆ)çXŸYCɈðÊ€ðjep¿¿s}üfD™’ró7`ÉðråP^y  ·¤¬MÐ+?@¯¦ÀÝU)ÞÚJ <^•\ð÷w‚ô–”\M­G¤Wkˆ+þz*QÏõ#ëùÝd½ú |_•/X%¥õ~Ú+5íÕr᫤ÀÛæ‹î"¼3âÂ/7nû9>oœ Ì–ˆ7Þ6j´ãœÃ!¦à •Œw…s«…ñÂu¼YðRß»0Dº¼Ô÷ö»›¶žsYŠ›u×y÷. WîãòÊí;PÞ}2Š'nõ½_ù,”wÇʸèyKJÞê WVPÐp«¯Ü¬Ã­¾wŽíTïòV_¿)[òV_y ·úÆöaÚYSp«oð›7öÌ¥¸Õ§«v¾Õwñà‘·ú¢°EÏ«×ñ~t­Oê¬ô<›ÔPÏ“è AÏ@Ðsô¼’Û%@ÍsÄ<'@Ë+o…–ÇP×Öò\Wjy~ŠZž?RË‹ßJļ’j^)j^y7Ô¼RÔ¼òÔ<©ØRóô™óÞJ•˜§,óüîóüÅ<ÊPÌsËPÌs](æùEÐòœ@ƒN¿ R^x#‚Ñ'´¼R.´¼’-¯¤L-¯” -Ï9¨åù«©å•<ÐòJhy®µ¼bx -OŸ){NUGöœÊBsN™ÁœÓßF'RòJ}¡ä¹vTòüj*y5åÃèDJ^I’WžjËPÈ+ ä•yîÒ²æ<>.ô•’5§^EcNý*2æd y% „<R y2h£ŽçÊQÇóPdzQu¼R,t¼òt<×2ž» e¼ò-9Çä•<°ä”E™,9ƒ¦œjMÊx%2ž?2ž*L¯¼ *ž{U¼’*žYrÒ*^© -9UŠ,9Õ²ät -9õ&Yr:M9KÊó™*ž*^1÷„ŠWòŒµ—PÅ+߯”¯¼›¶œJ¡W *iË©Ž#[N½K¶œªl9ùcSNYnn“¹l9]Èø…óÊ›!敇 æ•o‚šç<2åT÷“)§~M˜rúošrúšrÚ“¦œ¬°,99âeÈ©Ïþ©!'ó\Ÿ *õ<¿‰vœ¶œœzž­údÇéÚq¢Ÿ™qÚ”’fœ¬‹Í8m\I3NZ/ÊŠÓµ£§‹ù‘§­LiÅ©biÄiHÈyú$ªy¶\” §ê"NµŒl8U M8eÙžµ Ù‚SÏŒÕäT&œ6ý± §‹¥ '‹•§­(iÁi{MZpªu)å+Ïsµ@•§Ÿi}mÁé7AÊ“´-8]-8‘ò'‘YÖÛçµ§*ë †}óE”ãs‘õNqe=ç²®w6^a“®÷èît½÷úÂ|ŽÅ!aA½,ì5^B•°÷NyÛâÉ¥8ºÿám>_¨ãm>=Ce¯Üøƒ²WnüAÙS$){åb”=…×ñu>— i¯\Þãu>—Ìë|CÞ^¦´WÊ…´¿ï÷”EâÞÛŠ´¤„¸‹=”1ˆ{%Ä=Eò‘º§»…R÷ÿê^øå[¬8U=‰{% Ä=}£Ä½ò"ˆ{oõhè q¯ä¸YV÷èòÞâ^¼’w÷ò8òÚ(¥¸Wr@Ü£Ÿ|‹{þŠ{ï^‰&š÷Jˆ{åM ˤo ¸WʸWò@Üc$‹{~WŠ{.…ê^Éu¯äºç7QÝsûQÝ+y î•Ú@ÝówRÝ+y î•r î•<ÏG)÷œƒòžK¡¼§ §T÷J¨{n ª{þÉ)ï¹È{® õ=g¼WÊúž3@Þsÿ¤¼W¾òžûå=CuO#ŠâžIŠ{® Õ=¿)Õ=Õ=¿â^© Ä=g¸ç†£¸ç,÷Ü…(î¹\Š{Ü÷üI÷ôÕ©íù ©í•BNEÀÀ«©í¹¾ÔöJe îy"¤¸WR®kR÷4—KÞó4LyÏó\Ê{ž<)ïÕ„áÊ"yO!¥$ï)œŒä=E¯’¼§µOò^ÉÃxLÎ}¡Ÿ$ï)¾ ä½R=†cºxnSx5¼‡êž‚ÝHÝs1”÷´ZJßó«©ï)¨ô=­ÕÒ÷°Gúž+8å½’ò^)ò^yô½ò ø´•À§ˆøÁGŸßN¯/ž\¼‡‘¾WŠe4&î…$ð•|¥Æ$ue>¢’ZàS" |~ŠŸ‡_—™‡¡IygޱIýÌg8& |® >÷O |®>ÿ0øüsRàsߢÀWÊa@&Ö_·ÃF*E?’¾§ }O¥¤ï•+eõ¤ïéÇ“¾§˜lÒ÷Nz|’¾×è˜Gúž¶ÚÐ÷š\°PßÓö\úCÝZßc,[ë{ú9¥ï¹6Ô÷Iß{÷ÅçâÊÅÛ|é{tŠ!y¯Tg Â;q/×Tу佷ûx5ä=…ß’¼‡(ÁV÷ü•T÷Þ½ß-êžjGqÏoJqÏ?Å=×—âž¿ˆâÞi/÷ôSâž_ mŸT=GŸÏ_W¼Ÿö nR¶o«^aERg¡õüicz=Ûéeê|ú9=£½»lªž±‡×3îcÏp€V­~ÏÇ®ªn{Ï-ÀyÐ=Ø;¸æ N 2àÛ^ÓÞØ:E¿¿×ÜŠGH/¦ÌH oãôÜ&¼ Á܉GŒ—ÜJÎ¥áÝ£D¼©)yº˜–;¨èFa¹sb¯Ð¶<ÛŠ0šL˜`}=ÔÿÚ6z÷0´SÛ® Öv\ݶ{Ë)äQžûJw×·ª÷¤£ý™)âȨ¾[4dxìô›Õvx*–÷íö²vüý Û?Åò´ÝbKv1;/¬¶~Šå3»M‰<7.´=O¶lÓâ\骾·Ûž'[5åNû¤Ø³ã©R¹õmݨW‹ vl‹í6½öDŠ~¹žêbº…";m{xJߎ3í“ä¶y´UKî;Ýè¦dò¦À©"OòÛ1à"U½äˆÃ­úî{rõsà¬àM¸i>u#Ëó$^êign•}J~‚>óÝ¿g?u¤yÒM´æÏpc`¶³¥×ñ@œ†”ô:þþòôQ·sÀëø®R®t’ê¦9¯{5kgžpÝÌð¤ÏñAc½ÖòxËöUoJú§ŸïÖà¦Xî1[;àrœ.)[ƒ£bº’|îê³5z)%´˜,ž5ËH÷¨²Þ”t9>n¥\ésü]¦wóO~"¾M}†ÐGr $@_ìN¤Ü_ê‹#€ /Ì7€ }ÈSæ±ÊÆm5¨/”ä(–Øw¿üÀ¾²Ã$öéΔ°Ï¸.ì#Ò‘ú õùL‡Ø§+HÂ>}夾‚—¤>Ýtõ½8ðÅ@}ƒ·²E}Þ–ûÂè—ØÌðCûÊɰ¯@?°/6á@b`Ÿ·À>õb_ᨫ7Zä¾rŽî«Åü¼%&ù)P›ÈOëɯìáA~ti"òsóü ¹ü|¨"ð3k%øfÈ}>(Ü—î·Å}g#rŸv ä¾RîľgÄ>†ã ö•ãaŸÀ@اbŸqBØÇ()ľBl >ã©ïdƒa_ùIÀ}åèÜW~lrŸx‚àWP àWKNð £ Ì¿]ËœÀO‡¿ƒv9¿ÆÈ ~ê~¯!÷ÅwŒ•ûÚí‘û̩⾃Ögä¾gçB-î; 3¹/ Œ¯…ûÜ…É}î°â¾Æ]¹¯0'¸¯|¸/Ìl.¤$÷•ƒû<ÈÈ}ñc¦ Э°À}á-iá¾g§A ¹Ïç(ä>q_˜€ònDšâá%¹¯~U‚ßs" ¸À/Ú+—‚_y;Àï9¸©JðóYÁ¯´ À/ÆaNÃ$¿Zn’_iŸ;1ѯp2Яô% _° 8èý:wLD?'úÅ7=`­d¿ÒZ`¿ÒÁ~ž'È~åTìWZì7I ï:Le9É~ž3É~ž¥È~åw8Ÿcý&ÄoÔEøÓ DöS!Æ•µðoŒUÝg¤£)š_§3Gâßœ€ˆSó{6©‚Ðüâ‹D?YmJôk´¤£è÷r¤¢ß­e¢_‹é8Ñ/b»¬ªßÉ~(Õ/bÄäÜ ì§Ö• €± À.8އK;e?Ãpã’þ®Ss?è/6 Ðßu7½8é/¶ c¡¿{[?+’@¿°Âlýb\ âç4ÐÏ'RübéF ¿Îø¤ø½ßŒ=ÐÏñ­øáOÈ}ïäÀï¾ê‹Ý-š µ>Šoú¼§–Ð×¹Sè ûG6 )ôEÿ“Bèó±8•>ïc}eçEèó¦ÐWŽˆ©ôyß ê+û5*}Þ”€úʾOJÏÅû¼-õ=€BßI{xb_Ùg Iê û,Âûü*PŸ§)õiv'õ•Ý¥>—’RŸZœR_Xn"ZŸ6Òú´8ú¼œúž˜ðê„>/b¤¾˜1¸@}åWõ•­#¨¯”“bŸ–TbßÜSòûbøSÚËJK–°Ïµöy "µÏÛsª}þrª}a­‹§ öd!õõ&iïXÊ$ó¹¶”úüÓRë‹}ýªõ…7r$$òuž¶ùžpžŸ ˆFúN€ä9_°¢˜tìÒ“ø¼÷•Ö÷Îhèô@¾',©þå61ŒškÐúT ß¼ª¶H}¥)‰|ï\9Ìyø´¾°D«ÐׄNÐ÷P.´>¡¯äô•7úšÎ­}Ú Kë{˹¨ì%õù]¤>72¨/š «LRŸKRŸ¿ŠÔwG’Ôƒ-AêóNêS·!ôù3 }ïä×Vè'N^È|þ&2Ÿ¿)Å>wX2_Ü»eúÜm}s£?À|ÑÅ|¥0Ÿ;™¯ë¤ÌW^èó7ùÞ1fNèc]Ä|ú$AŸ³€ùÔtb¾¸n„0Ÿzˆ˜oÜ*̧ó ž8‚ùôAb¾¸·„`¾R ˜ïÍ2#ó©9Å|ê{b>Î`B>W˜È§ñ.äó‡ù\D>þ">õVß:Dâ4ñiŽñidˆø4׈øâ¦Fæ!ñ]Û¯PÎ|c—jà‹K^øüE¾Á‰>õ`Ÿ«Gàs— ð•<¾’àSû‘÷ÜAÉ{qiôÞÓ`ïiÜŠ÷Ô©‰{þJâ^ ņ”\Mµ&÷\_âž{qϸ§iX¸çŽNÜóï’¸ç ƒöÜkH{~¥>žßþž k!^Ÿ®¥«Â#(¯Wñ"–p ˆ×tqˆ×±`ñæ…àOJïxûâ6ñ­6ˆxqM•j]"^€á½Øu¶ý3%â½ïÄæ„×ú&q. ïÝ€þZ¾ØtÝÔófnMAðbÓEU0¯€#O2^l~hû™Œ×oNþ@¼±Óã>/¶Tø ^ìlÈUIyã” Ê‹k‰À¾£g,Š€¼ñÈ7®g„`¼kã17o\²wâj%âí:Íâ]§oAy×~|Ê{ƒ6»=ÎN΋ 0¡¤º§=1Õ½±.yÎ¥).~À‹êž šò^×ÊOÒ{Ç4Ê{—™tʵä½kÈèò^ô;䀼÷Ðчl:÷SöšIz×# ˜6&Z’ºŽCâ.1ïí&ÄEˆ{6&æÅ®p8 :ߎ..uO*Õ=›%Ó S¶VT÷lL̳®HuϪ Õ½¸ñþ‚º÷v¸c•÷lÅ%yÏÖ—)ïݲ…¼W47Ê{ƒ`JyO†?’÷Þúµ…ôŠDyÏì/«NéùÔ÷Çå=ËZ½ØòƒŠSß³"}î¨mÕ)­Iúž¬fzÅNŽúž­›©ïùàúž|"Zß“Ù/õ½’úžm¢SßsóöªèO^-ðÑk¢>[uƒöxÖ#uoçx¢ºçß›v¥©îùצºWªuÏ%Ô=kš@=ÛUIݳt+yOíByÏŠ*X¯–}ÏŸ@}Ï¿Üd½¢ø‚õj)øÆ¢îÙm%AÏŽ6 zõ5 zazÎIuÏ?@¯üؽ °øyÏ¿AZuúiÖÙyURfnNÊ{%ì:ÇjÔÙ¹âѦÓóƒl:µîHÚ³ –˜gcAÛtÊD’ʸ•”gSqP^1'&åÙú˜g©””çs?P^±'å)\}^Ê+2=0φb‰yÕ¬F6%“Qç.Ø‚Q§mÇzžfdÔiƒC€ž—uª§ôн^uÊ66I¤M§ŽVÉy6/”I§ŒêdÒisM˜tjz•I§mæhÒ©,“N™aȤS#,9¯X)Ò¤Ó_M“ÎR L:µÎôJ›Ë¤Óo¢I§š‚6:½¶M§­•MgyŒ:Ë«`Ôië[uÊšGF.‡Fò0ê,v•°êtÓЪ³XZ&êùÎ Q¯tk ž§B¢ÞbÃy¬æ<²êÔê)«N-b²êÔ%Xur_.¦ºõ#›N]šè¡Å¿r^m¶k!ZUù.$ÄõÊÞCc(°Ýtª@Na©H2d;[1’íÎ C¶kû=²];¹%Ûõ‡®ugoޣΔd»²ãÛ·å©¢%Ü]§ÎÛw±ðÃä#/í]<ã½C€»r —öÞ)f¼´Çûã‚»ëò B\Ú³©/í툿èK{¼Ï¶+ÞÙótžwöQY žo‡ðÎÞÆ~R𼕂'#;*xýøÀ»² §‚ç›Iº³§ý’îìi™-wöCÛzIGwö¸ ß•{^Tòl~¾³ ƒ¯ìq"Ñ•=µ0…<…¼ýJ^ëÝ* yˆ(äùò…¼¢ymçÇ] y–=€wÞnPdz>À«òt'§ŽW”=èxM§ÔñÞ=€…:žÊ¥ãÉpL:žZ:^Ñú¦Ž÷þXºÄÏ¥PÇ“àBï”q±t<™SÇ“9ˆu<šbIÇ+å@Ç+zàýi9&)çžÐòô[JÊS…%åI•”'•‹RžEØ¢åá§¢–g¥‰b^Ðq.Å<fŠy¥ºól;H1ÏÊÅ<7Å<¿‰bžG*Õ¼¢ÂAÍ;ézMj^É5ÏrªÔÛbžd©yœ ­æ=ºËG5Ï:ÜÕ¼ò.ªy’‰ æI$’šwÜÜ+êÕ¼‹ÛB©yj©yE†£š§wQγ¬%9ÏJä<¿Krž¾ržßD=ƒLz^¸Œ#øÝë¢$=/¶«žWÞD=Ïïú±žg±‚ž¿êG‚ž zÒ]%è¹ zRÙ$èé«(è½£–Ö™ô´dÿDÐóGAл¸Ë¯‚/ÙMAÏÍGAÏ?=ËÀRô(ñRÐs})èY⥠Wò@Ð󈡠çö“ §ö“ §Q•‚ž+CAO$è©KÐ~“íðgYûúÞ¼ØVŽK~ûä³åÂØ²Ï–m÷w½÷šm>óúÞœ QJà6N] LÜù„hž@ •¸wë,èà¾ÀpƒÉžøÞ®€ô €±×åÅÀìÝç¡ósà÷‡Û–"#âþÞ-?¼¿wø``8m=Öû{ïú >^CûZ `ßõ ¼¿wË(ïïô¨û{]+ïïmƒ÷î ïÅeÂÅkK8meep}/ÂUPò›ëU½â‡û{ŠqE Y“Õ§µ#Þß;}ÿm^à6ËL‡š8†Ž›yÏõ£1§é8ã.ëß®«ü`ÀØNÒ4p¼¿ÖÜÉ€ã]Ë!¡Râ»d K‰ocücÝàkÆ%H|›Ið_Ó~ ï¦0H·-òåÁ+|‡Œ×ÐåP^á³¾”wøÊÕÀ„ÀÒ„Àb~ŠK|–ZõM ×!+ åU @+º¤@›w&ÆmÁƒŠÞ–ÆÊº:)0Ì™Io Þ“¸i Æ{È’ Àjßy¥k³Ôø,eÍêù|…“"_ÑÈ òY˦È盪@À¢à eH‘O¡ð$òuMQ)òº‡N‘ÏmL‘϶ò¢@t>;Ô’Îg±:Ÿ¿œ:ß[cX…SçC“‹%D>;‘J‘ÏGsùôÃQäóü ô˜# (óùÚ4u>·°ª’É€E ¤Î7!.®uç¯<’XnßRç³D ,¦úÔùlî sNfBèóY,°\ѤÐçk ú,µ>Ÿ‘Á€Þ¿J蓼%¡¯øsy><ŸP賋í3R£PVŠú,‚Qè³Ï}–©ôÉm•>9 ³E§ ï(õÉ™¤>{ï÷ÊPRú¤yþPé³…¾âu¥á¸žv—úäa:ŸŽ¶¥ói†²A§L©óé>‡P÷/åºEU òÙÑ U¾¢ÿl Ï-òƒB•ÏŽyä¹Åº]·Ø» T>YìØžS‚2Ÿ»ñÏnä»…÷uĺ.™·ì&üéhVðçB ºù&‰O]œŸ%fJ|?…;yy¿ ÙOW¢¥ðÙ± Я^Õ[,‡Ì~„bJ|Ú‰~Ü¥U'ÖÛ›í]{bO*þõÿ™ÞáΔQÊNvgïÿŸ?yι˜§>÷'œX·1Ôü¥Ä½¸ö þ¢g_ñ¯%%ݬÎ\á©`\µ(¦”¢TŠRŠ‹Šx/ñK”ïfŠ‹b’‹rŠ‹úGyŒ~û×û½1=ôt&K׺§=8Ÿvñ<.¹xþA†öËøQ†tóÚìú»n°GHò³ôžß¾ëQÑWÛ’‹E=ï˜Þ—„¿kAÊÂrJ±Cb;©r˜P r&–Ts©¨wžùµ•’òï¥ fQ9ΣbàÆÕåȯk)H™TRÉõG;ņCïþ;¨4ÚwuýÜ~æú¹ýÄõów}டÏñQÞ×®Ÿ¿îR_¸~þsÔoßÍ6_ÍH¿}Õa¿›¥¾î±ß—õ“_#¶Äuö8sŠ R8X>^ÎüåÛßâßküòŸÞöxW±õ’8þvDƒwàþG¥ù_ÿ®ý¾˜½•Ä~.xãÞ¿ýSÔ/n G_™çFúÊùÛþzÛøå?ÿí] ãîà/ÿU/úoú×ÿþÎïþg¿Ç/¿ýíŸBÍ~ M?åŸ÷ý6îù.…GpéÝVߨ§}cŸÓ7öø]·ØgºÅÎÿ)‰Æö¹¾¦L*ü›ÿ¶ìöü`oÏDø+ŽÒƒ³ÂËAGWÂÕþ6î;…VÖûïx§›!áãÚx_ïa°½3öÛQäÂd|‹ˆF8$Œ"[¬]­E´Ÿwoú>{2vú˜æ5ût(–¯Š³Þë[œèÌ?cýÖ¥õGçYLœ/2Xà;½¼GR µÍð‹å©#2Dž÷ÕÉíðòÎ qá{̪ØŽ8@œy:c¶éJ Š¢m¿Ån¤ôΩÁ±ïFÛ#vy±kÅ[Ü!9"˳×"ƒgç£Wû>fà‡Ù!sÆ]“#KpÄ ǵTøÙçX-Ÿ]~6×㈑æ^³ÎiM—b¬ê«ÆÛãçPí¼ö5Ž©•Ìß*GÐxÂÖëGŒð@ ˜>úžCU?Õô ˜mž“KœìKa0»×OéØ~BNã…×9Võáïš–cU½ëJ›«òT\Qšƒµ¤ÌØv¥)®£çh &ž_†„s´r2‰cû9X=XÆü?«SzÏÁªßêz'©9X9†ÂýÿXž¹nŒU6NøÈ\Ff\%z–ÑÞ7æX“Ô3S. Öcèž+rù‚ˆF;kÄkÊ,ç–£ÕÅ$7Õ”ôû9SÄï´ ­¯z'©í¬ß'®9!ÆiKW}Ä=º~¼;ÏÆKë„icWöã`ð9\OÞý «µ£Î!Ìáª.õ{í´q Þ—¶›•¯7Ízs¼*¥çÂêÖ‰ó•9^õ‹‡~}/íõ\Æ+ÇCÄ£ÍñŠ^ñ<¹´j²˜ñhǹ¦LíK‹Î G;‡+¿j†£Ã•_5ÃÑæpEàÃŽ6ßçNîŠh´9\7PðŒG{—æ;Þí(VV½iäÒêÊ\XY9¢g8Ú9ZO{;¶+kœ¶í™‚¥•?æ G›KköÚ¶ÕŸwF£]kD£Å`Å/5ãÑ^w­qÄ-;Î%¥ciõSK+ÍvùªýÂÒz"ôÜ G‹„žõ»±´ºÆ–V~T£½ë’ÍS†ÒŽv®ÇŒ¢½×p´9\•§auÕgF8Ú^6+GD¨ÊŽxF££U?LDš£U?ÞÜO¢F¹vŽV§øzG@hè¡Ð¯¦Q*pÎÅ*nì¹.&ÆõA’cR`œb'‰C–ºv¤Ìµ*Ì74>OÀi~“§ÏdÀ&3é ¸Å­Þ, „š«/0´™}aÀÕ aïÇ€13&’ËS`À2’Þ÷X=“€1’ÁçBu„϶ÙRDÀ#‡zaÀ9w. ZZoPgóJ ðxW, ðí-¼ÞŒ -›‹¡(·…#\ª¢^)ø§{ƒ¼\ Œhv œåe9 À¨{(0$øMΩ8 Hèr}výÎË6¹T× ÀÀ3®ñÓ÷\«Î¾éŠF®UçA^'ž½Éêc.UqpU xRA0>óX@0ìW(¼Ï¥ê<›$ó\ªÎAô"Æ2q/­vÑcé\ªÎvÈWM.Ugøû†7—ªX[h9—ªX$p .90$$zðȵ*~ ÞÒʵÊEœö6 ž;jràùn. ™‚Ïwõ†ÿp`üΈ×Œ•ŽEÁ‘ç^8ÐyÈçäŽÂnQr`,}ÙûÉ%Or`ô±zäÀsðxYR_&F–ßÈ%80 –R'–WÏ †çÄÀ36Ö³‰Î œáä¼@çÛÔù•¤Àóé0^!†Üw.yr>!úÇ#†â—380²äÔE ƒªœàÀvRÔ%ºrà ‚—p,yÀîÁ»ÐD1€`h–yªH,y‚gXe @°äFž<¾ ¶ Ó:9Ð]‰{¦„or ;90Ò<í#žág#Y,90ìÏ®…ÝOÀq0š«9°”l£PÃö-Nr`© 8ð|G`ξäÀ˜P¡àÀøòœÄÉ¥€ ú­@Puê]"A½K$¨ Æ LÔ¸ Æäuå«’ÏŽC‘`y$KÔ–K  gq‘`œY÷,$Jû•xŒÑx'æK  kLp$ŒµŠK`4_¶IPk•Hpî¾Ôì+,¯ Æ/u'>‚ÏŽó‘ M’`¬DW¾üæòúüšÅc'Ó³:Á@®-‘-AпIÐteˆ‚Z/„‚g(è†(è #Ï‘)ƒËëIÌ –<@AQ°ä Æ– „(è·cç—@KänI$8]'% Îo™?'Ip†DÍR’Ã8_’ày’H‚ÚöˆÃθ#Ëë;pr" j_&Œ’Ag Ái€¿àyH‚ÚêŠÃrg.N"Ásrw$<H4"Á3L»²d`)9I0:ª|÷¨ßŒ˜ £ì¹Zü7Ù$Á°ƒ|î* FOéAqÜ”|IðÀÚHE0&Ã<§„"ønVpRME0ð.y†Š`Q ¡†…×VaðM¹°ÿ¥"ØPÆð¾ &a3•)¯ÜVÃz b€ðIa@hš"žïx”ô †C”ê£;í„T¡1„@XFßI›e¡z®€0FÀƒ†ò`pH~¥xCV“ è `© ÐßDÔp :èñAŒn óL ;60йMð]¤i> |{~KžÀðÞˆþ‹³Ôä¿’þ+…€ÿJ ø¯¦ä2å7ÿœ…øç¹„üWSr•rkÕ ä¿’üW^þ+yÀ%üçŸüW²€ÿJJ ( K!ú£€úò_yüç‚ €%ÐCžXR@€%è)‰Xò€=I€/$À’èÑ@ôÐjL‘].°$=숀5…¬l." ›‹X*,ú£ˆ€¥d  j(Ôô",y€€*YXRN.®NÁâºÑX”蔎ÕUï««Pí%T[Ë»®®zêáêÊ’‰€ê:B@9°ä9¸º*åäêŠN)t}ˆ€5…««RVWsquUuîuu–,W×¾ˆ‚~Š èÖ!–”ãcuº 5%!°¤t/¯Ð÷†—W¦pyÕS—×ëC,)—W§<ë%–„Ëë½Ê‚5Ë«:¹¼²~„@·2!ÐíE,O .°Êsq…eo"–’o.±*çá˧ÈéâÀ’(XR.±z*QPk„P°dIÔÜ$Ôò.Ôª!¬)Xcýªûc‘ ú)¢`MÁ"‹µZ$øö`4 IðíÁ0±% -¤\L-ˆc Ü‹,(ê –‚A‚%%I°Ô†WŽwܧûÊÓ6è/|ªl}ÿ)ýíÛ.–ý½ëz’“è¯ñìS—nW—ÃÓÊr)ð¸ž_ø³ÈEøó)+áÏvU„?”éZ  Tt-P–t-Ðy-0ÜÊ%^ñZ`xVÈ< ¿I²¯†ŒEŒnpk¸¼ Ù×cs÷ÍôW.òVàÎãZÒ_?(ËéZ ­¡}-–á¾È›¾è+~¼¨-º¨›bºØé{×iœ¨‹ƒ¦ˆº8]K/´….^žÄ{ üõ1×+//¸XÞ ¼vy<Çå§ðb î‰éf n2úf o2êjà¿h\^PoE1æÍ@Ý~ÔÍÀq˱./è£t3ð¢ýnŽüÂOÖµ^ ,)¸¹ðî]6zo™7.ÚÑéZàuÃ3 ®^´~ÓµÀ›ƒWׇ×ošŽéZàÝ~]´¿~ÓÄP·ýoÞ4gÔ­@?Å[7Íu+ðæ­dÝ |{ÆXÐ/ÊÛ¡âæB¾¡ _y ט›ùZ`IÉ› -ät-Ð)¼øpÒµÀ÷7|öë›t-POéZ`Ä8È^ ,)¹.˜i—k%ô76,¢¿8¯q$éb)øµƒþa)øõÁˆ+TüÞúƒè¨øµSaNp$Ù»¢§àH²] 8‰#IÝë”âN”Ód’ŠŸOŠŸjHůó8CŠ_{à-$ÕRüúM'£TüÚª÷ñG’Þ×w:ñ¤Þ§Nd½O:"¿†m—?×_Š·µRüöYVüÔÂVüÚÇ-@·§?î©©øY\¤äÇï¤âGMÆ‚ŸÔG ~z„zŸFô> ”ü8Ü-øñ,øI©“àG•Æ‚ŸDA*~š}¬øuQ ?ç¡âw4zz¡â[Ù| ŠŸæ#)~‡ðŠŸ®/Kñ;ȤRüt@Š_@^%¿ÀµÄ,J~²ëä·ó$?ZzHñóCTü\0?ç¡â§{ÚRüöíÃæ³|??=%Åoç¥I*~OA$ùÅ?Tìó›$ù©Æ’üvÞl”ätû­PŸ«'Å­%Áϵ£à§UJ‚ß;ë¤e«?~‚¿ —-ø9?¶±¿m£%&¿ Ç?ä¾ð£‡,ྉf•ûÒ qÁ>Ù ‰üdWd½oÓíCÀ_Dƒ8½/ ÆeCê}<éü9áÏåHïÓ‡“ÿTeâ_Ty,Î`Ü¢$À’¸?8ï#–Ú€Km’Ý8’û6^Ö$ú! Ÿ’ܧ¦Ü§_“3å>5;ÐU&–wQîS ‰€n "`y°”Ô>N¨‚¨ _Dt£ƒ£µX ÀhÇô¾,Ï€Ý#I€‘'!›¸?8Öº``)aN®£e€ŸÀ=e*ÒŸßCúsíHáú˜ú‹mx„€þ\â_Ô%9ø¥l‹Égy7ð¯äþÕ”cUµ–Ú÷ûæ-= Ë!¢!ˆ1Dò")ñ/paÅ¿ýî¼Øþ+)à?a‡ø¯¤$ÿÉöQüWŠI|×Á_—ëû¦¸Ú>cð8•ñú^ÜØ2¥ºÌþñsÎÅ<ÍÕöGʽ:ÅUŠZ3Éþub§Ö/Ì å¥(¦”¢TŠRŠ‹šiîêµ[).ŠI.Ê)ÿhWÛaL¿ßûtµ}ÉŸìÞ•ÿÿmgºßwƒs¢ÍX¼ v©è,±M_2±(ùÑfIÅ6 R”S²°{Ñf9Õ‹6 r.”T3©(úÑVIö£­‚˜‡å8‹Š‘m•S¼h« åbIÁÕv\ýÝÞUí߇«í?2GýöÝlóÕŒôÛ—ös–úºÃ~_Öwµ.ÆqVWÛð}ý®‡ì[¿r´ý…Çî~QЛ¸ºÚþk¾°c‡ò.·ÿv…ýož¯Âö¯/aÜo*Ñþ°ß÷‡}ó>]„˜¿/Ïný[D¬Ùæåò3ŽWÞ mpÕµgʘÁüöˆ)?ÏPÎp›57´Üeœó y˜±¼ä=ó¼+zzµ€CÚ·­çÅ”ˆN5÷”oÂ÷uö¹‰„¸dÞ`q1Î3ÏXm_qÆñó.'Â3`z7ìylzƵŸi#[úY¿yѱ=ýŒ;ZG9›>ÏŒÉSSFŸ’Æ…Ëðçt)ÒË÷yÞo7šò2Ã}¥ gTùâØcG!÷“Žgøà9#Ï…sßs:°‰©rC8Á3lvŽ*ÿ¼õo)hŒÎ§â +òŒ–šò›ò¤ qËö»»¾RиáXì »ža6˜Ýœmì)h¼{è-Ë3ˆL-皨{ÄÈ›[ÆwýŸ1)÷ˆ/wdžðð&ì¸Cw†3ïØÓÎør³àˆt5~K›·w¯ßRÑxÇhLœ’ÆÈKgÏC˜Ù:tÏéît_žjó 3‰fBŸýå}×ϰÙyw,o…ó&ÞV(±§½vv›°‰=íuâúÞFÇÌs£3Ì/bO{éÿã Ë…ØÒºi°c+…Ð>£Lìˆy†Ö˦yoêÍ‚»¡3zcsŠÄ*!m§ü¨9s†¾ê7E®ó¨åÆIÖ>gxÀûU„´÷òIÏžCUý*BÚΡÊ/hÛ6r¨r¸Ì¶½L 3¢íSûÞŒh;Ÿc‹Ðö®S_´Í¡Ê ϶W†oJ.«±7Ûó©Ñ1Tñ+´íÊeU?ÝŒi;‡ªß~ߪ¸t8cÚ¶+g­ic3cÚÆPõgEl’9TUç=oeºGFLÛ« .ÄfTÛ«ÕÜÛ\Xõ‹Ï¨¶s¬ê#ö>ÖR›‘ «¿ê§ùIs0#ÚNÓ;ڀ͈¶saÝRœmçXÝqQt´]Æj´Í±ª7GHÛ9VOøœoq¢Ÿc+Û i›csK bŽU}u(?}i«P‡ž;Ÿº²œžëª;NHvs¬êW8.¬«Îs纪¶8n®«ˆi:cÚ^õÝá‰gŽUe‰¶9V1+´¸-»-}+¼ôÝChF´ËªÞFÉs]U…q 1ÚæXu–Áu•ßÞÐæ`åÜÈ^VœÖ6×UV¹oHüã‚.ús!ý¹‘þÜâ¤?Me¿RðÏï&þi ÿ•§Àå)ð_|Õ•` þ+yÀîÅÀ0„¨ݯ€þ9 €Úc㌖R€î²$À¹5úVÐ à?·ÐC¨I]è±@,O[?r·(tK5 £+Íss G806‰G¢0,TæÖèÆ!–Wº¶ £oY_ E`y èQFÔ².tí€þJ`kÀ 6uÀÖýiÏ!ú“tÑŸâ…ÿ´÷"þÅ{ò×%þé~5ñO»/á_lå·ÿüÄ?wYâ_;`Uû'\`“ßµo¿ >ap–+%pßnÌã6lJ~e n^;¦n¸jð€5°P; `¬”¹ß#¶>¨€aIž¥P|§” þ‹€zIà?^IþÅ`i&þ)´•ðöI ¡%úc 7ÁŸÓ þSPì§h™b?gú1¨È¯$<ˆú`¿HòÓ­r¡_\Û†ö³¾JöÓ%m±_¦#ö ³wˆˆÉ~å!°_Ü쩜%ûù²_ãd-°Ÿ®•‹ýâî|î¸É~~ÙOWÏÅ~j>¢ŸZ‹ä§ ¦"?gøù‡#ø)x¦ÀOn~r# ðSZ‚ŸÂ† üâ·Ëð ë¸ì¼$?95ú)î¤Ð¯wÄSû•Úÿ³Oô§‡¢¿R ðOaXïž‹)¹Hi0‘þXTô§p¤¢?ÒŸâ:’þ%Qô§ ˆ¤?RÒŸ" &ý•BA œ)úSˆIáŸßCüóÿÜ#ˆ ¼'üSBáŸÂŒ ÿJ9À¿òvà_)øç@üS{’þÜ ?…ý¹\П⢊þÜGHn@âŸ;(ñO•!ý)Ü¡èÏÕ#ýi~%ü•r.ì§>Mô“¿¡Ÿæ\’Ÿ~‘ŸÚäÇg~š4~êœ?Å…ø)0¤ÀOm'ðÓ2"𓟟:¨ÀOÑ6~ ¡(ðS üÔ±~.™àçúüJ9? ‚ŸzµÀÏðSHŸ¢o&øùW!øéÖ”ÀwŽÄ}þá~ê¯?v+qŸÆ¸Ï?¹ýJا8ªÂ>±Ïúü‰¤>%±¯äIìóoKìs?ö)觸¯¤€û4Cˆû\ ¹¯ä÷¹%È}ú(bŸF˜°O-Lês—!õi(‹úÜI}þpRŸÛ†Ô§ èÓº"èóè“'!AŸ"X úÜ„>wRŸ?ŠØçnOìãü$ês'!õ)´©¨Ï“©OÅú´Î úDUÐç&&ôi#èóWú\A@Ÿ~o2Ÿgº>Ê.XÈWêvqAåOKäóŒAäs‡%ò¹nD>-B>#‘Ï]„Èçß’ÈçAGê+ïõùè‚Ô'ôõi#õyú!õ¹÷ú§ @Iz[Ãâ)sÏ“Æt$½½Ãg¹P/nµì6Ü_¢EÔÓ}*¡ž®yŠõt]T¬§ ›b½"äöâ&m*–ûxÏ—°'ƒx‹}£¢ž.@[éëT™RéTÈzq +U<Â^´,9{ÇųkÒÞ1xDOÚ‹‹ñùh/.seƒ÷"%íñÈ{ÇuæŒ&ÞS8'ñ^¼p—¸§@½ãÂñŽp¯äî•<‰{ @%Ü‹‡r+ ÜÓ«I{ÇÅãxÒžâXˆöb9ì‹ÒWÊíé¶»hÏŠ,qÏNÞsû‘÷Ê»|å)Ÿ8|ºY/às¿"ð)1/vÏbíéžàÓÍuŸ®» øä…@ÀGçâ=W˜¼WðÅFåZŒ=uÇ\À»®s>9_ì¤žÅØЏçCÜ«)¹:C2\òžnã‹÷b¼d}Á{| `Ïm9a¯Ø+{þ…{®aÏ?aÏ%öÜÜ„=¹-ì¹öP’^)¤§ØØ"=ÿŠ$½òj ^)'QïçùƒÀy5!W%וœçBÉy%åäÝ#•Ћ™3…_‚ž\>ô´±éÕ”^6ôPOþÄz%¬ç™œ°—Dzêï$½’pðÖrzr"Ô“¡_Î+Àyª™8O®$Äy%8ÅòÔ(‚›hçWíÂSѱ\ã+)@»øò÷'ÚÅ9Oˆv÷uä€v÷åB»;;¹.¶Õ©“ëÂ%L:çŠÄÀt÷ͦóM¦‹,¸U¦+)`ºûÑ}B@Ý®L¾¦+YÀt÷Ã[dºè‰0@ÓÝÏI™Løhøé |´Ò=oVu‚êJ ¨.pâ\T¼’'©îÙt T÷¼o„&—TçÞK°{v gìÔ]ÈuÏ®‰àºè@©S‘ëž]—áÀuÎC®‹<¬:s5ŠQ²-6œÁCyE®ÓH"Ö•‡@v%dWR@v1˜ž…ìÊ«@vÏ!Ý1Éî9t pç,€»çàmBÂ]IÜi`“íÂïÖ¹hx~ÙîÙ$ÙíJ Øî9p]Fl)iºN¶+yÀvOœ/:^IÛ•rÀváì\ð®¤$Þ='®óî"Ç›ÎIw%tWR@w.|W²€ïž“VCä»ç¼Hsà»hÇ}1àŒ”k1à,y€xN!â='ì=DyOƒÛQ^¤ä®š”÷4Ø„ˆòž R^)”WJÌ 'Ét ¼RHP^y€ö›nä‹òÚ¶Qêå= ÎDyOCÐQ^ô¹;•=P^l}N\×ÃrZRr=}Ú"ãñOð]ɾ{|&‰ïJ øŽ…îž§J„»pGׯdIºóç‘îJ èîé;Œ;wNÜE±c»È²årõC`»§Ã=–ØÎY€v‘%&ˆvå! ]É´{:Œz„vÏÛgl4s!u°]IÛylí4]ˆíâ6ц‹|¹˜>žÎw‘§/^IÜÕ”\MK9€»ò €»’¸ÃäWàÎ)„»(y¤Œº{úC[IÐëCº+OîܹˆwèŽ`»R*Ø®¤ŒõO°]MÁj:x2C¶+)`;"ÙÎlyÎåÖž» áÎcp‡"Ùù7!Ù¹HvÚSí´1Ú¹«íÔïIv1 ªÞy^"ÙyŠ$Ùy6&ÙiíÙéÕÂsõ=·ÄnhÔk{÷Éû7¼µÕ ÛáÖ]YûÖïlðÒ^¬¸Æ‡K{áçwÿ÷¦3Î*ãŲwUØ{:Bô’õ¢ ôÅ`3\qÞOµØ|âv[«"^lp§0Yï™[‘0צçŠQt¼gP‡ê=w\YÏg^Ô‹pá0I﹃o“ô≑KÞsÓ/ @¯fIÐ ×]éHœ ~C·EÅ{Þ½a£™¤'‡_½Øçà¦%@ï¹o¸±ç¹lٖ༚’œJGîÛzOÜ/ÜË}½ç]ƒNø}IÐ+Zp’^d¹«Éæt|šÂ @/~úcǾ¹@Å6í Ð{b:³%é=OWž$½š'IïÉåàç†ç•_œw_¡™U-5%9ï ÄyªÍfÌ| Ö–‰z5Ïd½Ò7{5ËĽZJâÞ}Å©{•ðîP!! &îÕb÷Ê%Yð^}yò^ÌŸ­U ¯–“¼÷L'¿IXÉ{ô~oÞ«) |¥_-'/~á—ëøbšÅpHà«Å$ðÕb&ð•ÖðÕ”kia_-#‰/(  Ä)Çâ²¥ü0 ¾XKîì8 ¾8Hðð•„ä½øN€Z_-%¯¾;¯¦$ð•ÀWKNà‹‰»ç@Là« |塾%a®R¥m|¥6 ¾úTß’2‰/NÓöÔ4A|w@uÎcXÿëSI|¥u@|µ>I|5%‰¯>•ÄÃẫ馃Äà 5ÏÏø<¨@|~5‰¯¦$ñÕbù¼þùÜg‰|5%‘Ï‹‘/¶o¹ÍñÕ—'ñ•Ÿ=³‘ølÎCâ›~¼aË™Äw‡¹Äre/6&Ç(Ä}á®ÀWß=¯&$ñÅaRÎ@“øî›÷{|á° ·ëདྷ¸WËLÜs÷$î…{ºÜCö쯎´·¤Ì55Ns %ðÝad›G0_}*™/Žˆï§^×»c‚Z˜ÌyÎ^ïëÕ”‰}ñØw‡¦Ž¯šØw‡7ç¬ °¯¦$ö•‡À}‘²WQ¯TÜWÞ î«Å$ø•b’ûJBr_IHì«Å&ö•,I}µ.¹l—‡@}KJ¬©¥r ¾+<'÷B}5!©¯–’ÔW‹Iê+µõÕ”¤¾ZNR_-'©¯¦$õÕ”¤¾ZNR_Éê+oõÕ”¤¾R¨¯–“ÔŽüÏœç@}5e‚_-&Á¯3úòæ¿%%ÕRH‚_-$ÁÏ]ÜWrIu)À¾R °¯¼ØWŸJò+'ø•„侫qJî[R&÷•‡&öÅú<E¯ä˜ØWÿ~8J;ˆ.©¯¦$õEð Y}Ž&TœU¿ûâguË:fH†«8‚eJu:ýã看yþš³ê~½k¯ne•b·ÐL²‡Z§Ø-ô˜ñ”ªßk¥¸(&¹(§”¢âr_«~¯•RŠBR)J)ÿhgÕ}úhï_9«þÎÕtú¢nrVýƒ ÂYõ÷Ý ‡Û—w¾¯~„?»Tt–0y_½U³,y¢fQÅ5KRTò°;¢fAÕ5Kr.Us©,ú¢VQvF­’˜G9Ê‘+jT|Q«$åRQÁcuöÇöþkÕÇÏ'[a:ôþØ- nÓÇ—‘õðpÐ"O\„É„;ãW04Iß ñÌÀ½Â~1BÛˆw¾;¼»ØhéýûF€¨½=Qfp»¢ÇUÜi¶Fë—çÇßxSnÄhAÁqƒg«¡zܪ™Vk ±Ôã.ÑSãÿ¼)7.iÀ<¼÷ÞÓlæZ½ÏƶWïihoÍÃtG(®+ëmÝÒT ÕyÎ41…“¬@§ÙMÅÞ”ùš+oõ†*ÓJÙ#xä4[cX°îÄÏjÚÖ#Êf€Ãâ·8Óß(ìÝIÿ Vv}Œ ¦è3ãýMG5Bíãê¹öÑJ±ûH«5FÑëáy; L•ç¹2L! ߯ki`Úࢇcè³#ʈ¯§–¾=§Ý-t{x"¬&¦ÜÄ-)OF)d“_ýZC-ö+¬¢ö¥~éN6ÈïŸOÆ>£¥àû[Ø—²É¯0V9ê„ÇÁë*–«=Ì¼Ž™›¹~Ç©ÖýÍ1çú}Ìî]>ûŽS­»þ á¹pÃ%¢ùwj=µ‚s_ãêõ8Ah6wîÓò«×~t¿óÓ¹<ò"ãUíV{˜í{mßû¹a_Êú†ÝÔ¾×–ë”úLß¶‹}iŸâèU«óœ=G*­_n;ûÒºñ}–.‡x9N9ŸÑWωýIwDå¦R- û<¨/Ö¤=Žûç@åõŽÜ³<1"€j+æÏoÂ…qŠê¿”Ùe >?q„£È{/Çc‹ã¬Ú_ß” ã7¶8кÊ5¶ ÓY«sa—Ê|S®©œQß™¦a¤ªäwZoÕ^w̨³O#¢Îžµ±ˆ;å]3êìÒZwö*ÓĘqg{é7#ÏŽÒæcÆ¥#¸¡×÷Ò!ÇŒ;;j FÜÙ9X9cŽwöZJ¾ Vþ3ðìU¿<Ïr°Î«šcž½k9xvÖ¶§ëÕ1#Ï–.:âGÚêB1fàÙ§L@cž]š4®Æ´2½Œx¶/]û¯çšpc´¢FÜÙe°Žx¶Zà<;«~©x¶ÞZçžËª"hx6îG^Gž}êô7fàÙ²œŒˆ;Kcð|¦cQõ3¡úžõw™îw–¾5ÃζúKÍÀ³O-øÁªª6?Ÿå=3ìl¯íagŸ:âÇ ;[׉agï¥=gäÙñͱ5Gkëª:Z窪Wu.«Ì2¸ªr<‡Ç~,µ¹¸ªr6ÁÉ@­_œkÍÉ!ƒGÄͱÊ><ãÎ>õ]3îl¯#<.í^uZ˜qg—öŒ›Ñ£| ;;jõ"ʪtG;àËgIÁºª9`†ž½êpŽÐ³ç2 gèÙµ~×UTgFž½ëCyvŽT®cºB^óXVÕ3òìS«3#϶úªžËªzãŒ<Û½8={.¥^XV5GŒ“9R¹;3ôìXj÷pYeÊ =;·‹GØ–~3£Š\ß|¥aLŸýÇòTä¾êÛ§CåÙZ¸ä0fèYô­œy#ôìuÖŽ=CÏÖ]Ș¡gÛòÔuçXuÊ•Õ)y5‘TÇŒ<ÂZõÉ,­\åÇŒ<[onŒˆ<»ÜÜ3ò,ú_ˬ¬êóÔäª_ÇÓysáó°ý£Þ«Å+öÙ+RX"ÿ]AbsA!ÿ]ƒr9ùï of¹ÿ…4|Â’ÿî˜Ã€!ó¦ÁЂ>06y÷‘è–x¿»Ÿ‘[n`lÅø®I€¨y2N ©»'FN´ 0vY|& ð¹…Â$Àíį#Ü6\8Ê·Ð(LŒ]SfFÚ¤2àv?|ah Æž©g1 À ê-ß ùóLF`ZÀfà†Ì f ÀíÆ}ô$À÷ol¹I€Âj[p?pr,ÜSs,¸78 î!T%—CTÝ“$€û‰; bÀØ®åá<p?à\ ¸YåS`À’;÷bÀ¨O¶PŽÐÅ€{ÃÅ 1àžópaÀˆ’›= G×€rð@ !8©š ¸wØ©‹÷Ðß¾ÔG¸·<îîIû€ÃAà>ÒN] (ßîbÀýz¦€÷ âËÅj0!Êi… pŸ Wп °¼ Ÿpfý#è0ñêduB ›†¯ÎDôi !pðt#ô».™¸_ã™è@ T˜Xa ›‹¨¸°ÂÀýýY³: @msIû•®øk6 pÏÉ® âÁ £Ä¶  "Ä ½•&êŒMyÎ÷^î…€ÑàG `ä¹TôY! £‹£UrWITÈ]`DÎê%XèOò°NÈØ¸ä¿RøO¡úÄnòŸ?[üÇøÔâ?7:ùOqŽÅºH)þÓUnñ_”s%#’ÿô.òŸÛ†(_2@¿¨Ÿü§mþc,qòŸ‡ü§cU ›‹¨_üç7‰ÿôMâ¿ žÍ&BðŸ®~Šÿv[èž$ÔW‘gDó¬!п ÐJ,ï*¼4§¾B@E­*ظÐ/"úEDÀRðÝÀäg’K0 ~p2 ¿’ Xª,ÅýY`@÷?2 Ë!º¯“=€5}‹Õs€€ž(È€žÿÈ€r¼+t J@ÆS Í›Ë*– 1 g22`, ×Z”\ÁÅ€{¨xIb`ÀØY p¯nÉo`ÀýÄEB`¬é{fîg¾ÛE|)pïØ8‹÷˜y¾Üw„·îÜõ µÑnÂPcË›, ÔNU ¨•p»àÚI ¾–s® n¾]Ä€a&xæS`@Årž¸u¸ój,ÜNR#p{ו'Ÿn')–(^nG˽¡pkäZ2àvா0l57^tÿƒ.¬‰±¥»Î»``\èÎÝ(0pZ¯HÉ+¾%µ$`àÛŠp]#Ð;5Ê€š ¤Ê=€tÀ#"Áνu@9œ’x DÙxnèˆcÍÉM6…Àã9°™ƒxv¸”F„™BàyIˆç»¿9!ð<á9Px6ܔƫòÝÄÀX„²~äÀÛ~€ å9] x^Ü6Ï `š±ŠÏ‡Ã¢ÀóÂuR`\ߨ@Šc”ëZþ&¤À¸„ØAr€ Œb”Á ‘™ øV6ç.Q`F¶…£Ïms¹*y@¥P ®IŠËg‚ý]¤@)0†É½P Ü׋ãn /)ð¼°m*)ð|àäBˆŽXÊžï‡Ü –ªã—K¨pX‚@?E ,) À¨^Â/)Ð_@ t Iå] Àè±Ð!nt`à»#"^1î+@ˆm§RM T¼.a`tɈµföÛ7HMd¿—œh¼IPžvØTšl@ûÁ’iÊÓ"êä\F <Ì•¨Ÿ‘(iEV <°¶(Å`Á_1ñücMšÒÝbŠrdÊ´è4›¢§3Pé´¥\ì@eõI;Ðý&hÂTöp¶eÁij‹NÚÊÂOv ´=±¨­Gi*Ã6ÙʨÎv ²ò&+Å”ªª-AiÀ'KP ÚT%Ë««-Am{)KPå‘%(Mm Šp¸¶…!  AmaJCPZZÊ”Æ[Å”¥ÈT§4mØCØÔu¡)¨:i ªWÙTæ¢2¥%­LAe»*SPqÒ”5–%¨h*âbŠ÷Д¾qe J?¾¶õC´õC´eådJ÷Æ6•]² Aõ*‚ÒG° A!Ò To–(½ÝÛ”^ƒmJoŶ¥›}Ûê禨kG;Pº6‡(ßl;PzY·!(?Ú† ô1mCPÖΆ t›mCP¿š† ~ ABCÐ’CP¿† ~ A;ÂÚ”N»m î¶ÕC²ÕËiJܶ¥÷xÙÒ ¹í@ýêî›ZÈC;PU†2 ³Ð ÔÅÐ ÔyhªO¨ÚFf %‡ªôÉn3P½Kv z—ì@ý.Úª-hʯ’ è7Á Ô/¢(o£ÙÔÅÒTOÉTT: º6p‹˜Ø™Þ>ì@9ðlª®-CP:(·¨®-KP¿– l ‚ºÊ4UÏ–%hI¹k”%¨Þ#KPÕE– *D– úJY‚ê›$:…¦ ~MA]2mAù•2u•i ê‚)º`š‚*E¦ úd êš‚r–)(§Z›‚rÒ”)¨L e *“bÙ‚ÒX¦ N %¨ì>i *S8– H‡È–¥ýS¤ŠeÀ Þ-J5• (ûé€Dë€|[¤Ù“P–QB@+—D@m÷-ÒbI:ê³ àŠRäîçö­ð_Ìÿ aä¿ý€ç-ñ_¤ä9ùO†f–cca6[G[‘ÿ"O³ÿJð_¤$Èÿ7È* Íò¬ÒÞÏ*à€Í_¸»òMgõÖŸ=fùö¸ä½ýùž8ÖO‘°"_2ƒný݈ãk'î­UâK ?ßF#TŸ4\_ƒ›TßÛrÓKâ ùà%ñ±k™øÎNíÄ“‹ÑçÞxëOæ}ºõ‡O¸gd%îÙ¸[”Eê³ùiOZ´·§ƒ¥B{6—#íÙœ´{Ÿ„aÚ|Ê(´g¤N›O[KÒæsœ¼ãG›OÙ0ÊæÓÖ›´ùô‹hóÙá¡·Ø|ÚÂÆ)~m>ým>EË6Ÿ´k”ɧL*eòyÞ|™|êU2ùŒ…øG“O=%“O=“Oýà2ùlۇɧšÂ&Ÿ7`Þ&Ÿ2I¥Í§Ÿ¢Í§Ÿ¢Ñ§ kbô©¯’Õgk4ÅÜ?¬Slõé§hõÙNª{´ú´½&­>mäI³O¿ fŸ~Í>;ÂfÊìS#ÆfŸ4\¥ÕgGhU[}Ê‚WVŸ|HFŸzHFŸ´¢•Íçh¼ŽG›O?D›OMÙ|ªÑeó©-›O™ÑÊæÓ¶£4úTƒÒèÓÑê»OýÚîSë£ì>Y9Û}Â6×fŸZxeöÉnn³OÖÍfŸZœeöé§höÉÖ³Ù§ßE³O?E»OUfŸz•Ì>Ù²úTýdõ© ­>õ ­>ùZ}ú Z}²?ØêS†\²ú ×m À½ò­>iol«O,.6údw°Ñ'«'›O>CÖ+ÏÐäSՓɧ¢Å§¢Å§jG“O=ÔóÑâÓÐâS;‹³nü‰Çuãï}ï4Þø£¨âú(ÝøÓ'èÊŸª§+ªž®ü9¯ü±œ?áýZØöép´Üútê*·/ò.G¼ãè?½€÷IIügLKþ‹}O:6"ÿEÀóYܾèÚ‡ë—vóŠˆÌ=mH ìýámA`‹sÁEñ³I °¼‹öžOãmAÚ{ÚºØÇ±*~íA¤9›{Ê~ó&®Ãeê6`@ÛA’cǸÞü‹ .<ÊÐÞS?0v•}1øÔ¼kƒÏŽÉOÓxŠc`ÀØ*ç5Ù{6 h Àp@›[qR`Ì׸.HƒÏ&­Ø/^öýùµ ~­óŠ 1ð@xÅ010öíÛ¢ø…_àkÁÀˆ)_IŒ˜ >|öNe «×µ~!ñ Qž±Ý/ 80,‚ŸÖL‘`¿OD$î…÷…ýY$Á~ñI0öûB‚ñ”ïýEïK]‚$Ø÷“E“Ïñ"ÁÎ?¹¨by´½geÌB€†Ä@w#Ù{\º"j>ö¸È¿8~‰Ú¥¹10 ®`€n;Ù{ª‚ä@ÏIDÁøŽêø¥ ¬ ö~‚/“û>E{ì „±·Ýdì©ß•OŸ‹×—ò=ýEÀÀ¨ð èÖ“±çà5b`}ÿ¢õyj‘±'û)Ðó=5dìQª±gø¹ÎÁ#cÏw[³-èA Úy›@Æž7ô{rцëÖ¾\ùk7E/Y{öEçëÇñqáÏë†L=¥p"`ìÊW¯…_õo…[£`MtG#Fw·ÐgËh` Œß ÿ¹§‘ÿb(.øËwÜíÃý‰Á;Ä¿À¢s¹í(Ò3ψ]“fîÄ?Y'?ØWgÍÅÙë1ª‡b$ToÖ?|Ê™˜å¯9Á¾b«s×(Åd§·N±»é{.°K]™â¢˜ä¢œRŠŠš}ùêL(eJ)‡ ÿhØW\‡z¿õ8À®®®cñ—|a÷¡ ßýçÌûÈ+öϲ¦Ù!/²ß÷+Fê»T·Å}-Z+6îK–$××,¨¸¾F9Ê‚bJ–b·×,¦º½F9΄‚j•D·×*Èn¯Y³°çP)ry­bŠËk–£L,è/¸ÅŽ8A÷ûÌ¿·Ø`Þúí»9è‹iê·/{êçÔõeOý®¤?î;ÖwäT—ØÕ—õW¾®ÿ.OØ?ótýô_îÌØ~ù￾û³ãÞË¿~çyûMû²˜F‡ÙÏ_w˜kk{÷ÿ7f¿ÓÑŸq˜ýfÿÊaö›ü÷¿…ù@4øíD;Ì¿ï0û –êáûºÏÓË2ÆuñáŠÓ§6}_ÀüŠ“¥{º)À™Ó{½Ø ãνãÕ3 ¨+\±?âÈ.¶O¦\éWj›…ó²i»l¸z„<øæËWŸÓ‘ß”ë×^¬&®±5è–8õ»^<†|>¼)óˆ»æ9fLHIƒo·hÐ-q¦w½ŒÝªô›2—_ËáW„ÊÞÏ"ú^c4(—yu½›Ä_SÜÆ–úMy \ê¡—-S¹ÄÙ5âøë©)W:£°3Ž7åùµº&¸b&Hû¸Þ¸®—>Ž%!ŒÉ¦I[žà½ ¬Þ¶<3¹"JJ_²¼m´Í,@‰ëŠã¯ñ; Þ”>¥øPU#Wlî™'b×õìyìñoßäëë ?ƒÛš#.b/¯~·éÞÉ^(¹r¬ò‡º·/ïQçÞŽ#Ç* ~S¸ªA…ïðP2+ˆ{Ëx­õ©0»8]ã7áɱJ7og»r°º˜8‹–à=¬{»÷¬~y€=ËS"³ºêº÷鎣&¼ÓdJ7pWpïóÀªT8Œ6Gí9w˜˜íKsÅ̘£¿æV6Û^šýû±6êwÆÔ“ÃUOŠص<õæÎñÊïœÍ–öÚÓNÒ îX s¼¢‘ÙjÂ>r´ú™@ì¥EþÞùší¶ö¤;Ôù§Œ…{F»­£õ-æ^ºÍ w;–bBIÛ—§2d]}yº»ªõ}nŒVÖ÷Ì èå©òö*Ÿ!o/p÷ y»4g„¼=뀾gÈÛ§~Ä yÛ–<ýÂ`e7™1o{í&õvùªóÆÊêbî\Yð´Õ]ãwæÛ^>j^|õEôçÒ¢3îmõ+uÇeñcéYÛò™q³/=t¾½ë(‹¨í\žšúoíùöYškF¾}–ú„TÜ–w=¹´ª‚84+Ó@ÈK¯˜¡oë"sÇï^׋{†¾­ëÅJÕ¶´× }»ôÒIž£4û }» Öˆ}{/Í5cßÖ¡o¯sù„‡k+‹‰Ð·£z3¼gèÛ¥ÎзmI‰c°§¬:÷Œ}Û—”†å•}tƾíKJÿX^ïû¶¬1w„¾ãUí7Cߎú;DèÛQ]ëÝÆÂ*7"ß.¯¾¶»vâˆz»ÌGôv™²"æíÒA&Ê.ë·®z¼]挌w[š(âÝ.³ý•=Nï¼s9Õònê¡nçáT’ît»üráÌx©t„¹]FT„¹…ÃËyÞwß0 v¡ ×~v·ÕgÝýöÅòÙ½³/ÿrðRbl‡ëggpÛòaÜv™3¶m)4bÛÖ Õ¡m—ÑL÷ÚšØvÔÑð¬KxµíKB¨ÀåËžǯw´]¦ó‡~_UÍ<)q'‰h¶Õ+WÔ)þ¨#lr]ø´~æ5xm…÷ÈŠ›KÐ^ÁçA8¹.DðŒ¯K®óM r]„>¾Ae vwlPλ¼38Ùîž`“)“íÞ_ê×ý©l÷¶bð‚íBòž&òD»’d÷„=Bò ÈîÙqO°‹1’AvÏ;_gTF’]èæžšd7•ôl+‚àìBZO×Þ$»%e’]y(ÁÎŽ¼ vŽ=E°{x` ®{Nú+'×EJ~@bÝ{Þ;ëžÆÀÝäºòLb]à7×½„ðÍLgÿxdº ˆŒSL¨{Z(II‚ uaL¦«Å$Ó9 .*‹vÒ•,ItOìòFò[]¼ú¾Dt5CÝÓn„¥Ñ•Bÿwwg“³9’$ç½N1Ki“à?Ð)„>ƒ …FB/tˆfænÎʬ®*õšA-*_ÿâŸAš‡€®Â¬ 袜/ ›'Z?€K]³Ì%'OkÏ…s›I…³r¨ÂY9Táj†J…ËK„Ë5 E8­˜©ÁYjp¹(¤W”\e’—åR‚«ÆI‚sËè7ª¸\ÖR«š¥ÀY1Tàj<%ÁU$ÁYJp¹\§Wc. ®®¯4¸ª]\Õ% ®Ú, Î,ûg]•ç­«cipVùµnW‰pVέ…5Ë¡—×êú„g•WÝŠÎÊŸÐàªHjpÕjpùª& Îê€WW„"\]|ŠpÙLjpVÄ݆\N§)ÁYjHpY%¸j3%¸ÊA ._[%ÁU›…aÕÈP‚«FQ‚«¡š\¶‘\5 œÎZ ÎR ®šj¸¬ƒ\õ‹\AÎR@€«V½MN pÙlêoVÀ•QX8+‚1W+ ]§«NpÕ:[ïéÿ»Ñ§ÓrÌchœâvFË3oJÆï/oʓʛòbФ¸ÜAž¯FÌŠ[.þLŠ‹ó‹(©㖛ΓXnÞŸØ(ˆ[nîXKŠ[î »Q’ââl#×a½YÞá=š;eù‡ŠâbŸäáª[³`½±rHqKloA{Hq‘fÐ} Ž•CŒËC´ã, 1®JÇE®‹d7WœHr6Ž3 8ÎJ!ÈY‚\µF girU®qœ5†WIˆqV.1®’â, ).Ã×%ÅUcDqYŒ Î Xnªu“á¬P2\¼’ãsÎ’áªP"œ%!ÂUó…p–† g2\Õ-†«4b¸¬\™(há,®2‘à, ®’à¬\œe"À¹åþÑ.¾Î’€àÜ‚SÕ pe ¿ežä·JB|ËšßÌB|3 ù-¯Sò[^ƒ¸ªŠüVâ›@oe ½UHo9w“Þ2á­~“ÝÊ@t+Ñ­z#v«‹Ý*ÑÍ2Ý,ÑÍZKt³\d·Ê%v˪„n–„èV Ý̲û#(Ñ­JºY¡D7³ݬP¢›•Kt³4D·|D&º¹èV¹„nùÀNt«\B7·h[Bæ"ºY¢›¥!ºY¢›¥!ºå²#t³&?ZL3ÓÃÅ4 C‹©,‚·\òÞ,ͪÅTu Þ,×®Å4ÓìZLÕ+Á[.î o–ëú,¦Io–æþ,¦‰o–†øæ.¦2ߪò›%Ù´˜žˆ¤™üV½À™…gåœZM³*œ¥¹´œf]8ËE€³ºpu%p•KWu à*—ÎÒà¬\ÕN€«& à, Î ¾´ªfå8«ŠgœåÁ•熧ýÁÕô#Áeh"\õ‡g)@pV(®ºG‚³2..¦i¸ÛL„³:‚á,9®ª$ÄÕØâªHBœeÄU¡„83⬠@œ•q¶~’âêJã,0ÎÚ Œ³ãè 'ÆÕXãªä¸ºˆä8KŽ«†½9Î*ÈY‘97<}< r– g­ÈY\ví'¤“Þžk:;:¾å+hŠp:e¸ð­„:‰p± ƒ´$Âíƒj™48EÞ®ÍpÚÉ–ûád6÷Ã)"Øïì‡S8ÛÚ§ \µ.3å~8E™­ýpjoî‡;NöÃ¥™ûá··öÃâÔ~8…™­ q•KâªdmˆSü×Ú—íÉ q™Kâ^µ6ÄUnˆËÖ䆸¬)wÄerG\n(Ì-qq™¹Ž^ûU²¶Ä)êmí‰S`ÖÚW¹´'®:¡=q ÌZ{â²=¹'.{‘{â*—öĽ¹À®Ø—{"sO\6O{âªí‰ËÖ垸‰ÜWkO\åÒž¸jöÄe]¹'.KÎ=qÙÀÜ—ýÎ=q•K{âÊ¢=q•K{â²…¹'®riO\Ž_öpO\v+7ÅU·¸)®òhSœ2Õ¦8µ¦6Å)WmŠ«\ÚW¹´)®ÒhS·½Öž8u³6ÅU1ÚWÅhSœzU›âªmŠ‹4ÀFmŠÓÄÈMq™)7Å™žýº‰jS\Ö›âª\mŠ«\ÚW¹´)®riSœ¦EmŠc`íÚW™´'N³¢öÄeU¹'.›“›âtß×®¸,9wÅ•e_ûÏ'ƒdÓÂ]qU³vÅ•E»â²½¹+.»»â*—vÅå¤È]qf᮸lNîŠË4¹+®,ÚW¹´-.kÏmq9+r[\åÒ¶¸¼Cr[\Õ¥mqÙwm‹Ë®ç¶¸ªŠÛâª5£6œ_Ôß´á¼,µáœí‹ËÖ侸²h_\ö*÷Å•Eûâ*—öÅe¯r_\åÒ¾¸jÏ]+,Óh_\Y´/®rq_\Fî‹+ ÷ÅežÜ—íË}q•Iûâ*—öÅU.í‹3 Wزhc\ÞW¹1.{•ãª.팫\£VØ¥©rտܗ¹rg\Ö•;ãòjåθ*ùè‹líŒ+‹vÆU&íŒËGJn«Êµ5®ø|ÙÜ—mËš°5®þέqeàÖ¸2pkœž™ÚW ¸3®ªàָ싶ÆåÒÖ¸Jq·Ÿ¶ÆU‘sk\%çÖ8µI[ã2½¶Æem+·Æe›´5®Rpk\Ê­qÙsl«¿so\•À½qÙ/í«¸7®²po\´7Î C¯¼¼¸5®pk\¸5.kÅÖ¸úÉ­qÙm«¸7.ëäָʡ³1”€;ãª"¹3N“ùOÄ‹ÎÍqO„kmŸâ,U¼ð‘óÞ×Eí-#繜7cÓç¼°ÀŒœ÷¾?¾+<9Ï à<·L΋zÚsÎk–X†Ì@Îs 8¯Yæ2äpž[znè5 ‚“ÕVB‚ž[znè5˼šnè¹ g‚^³Ä2䀞[&è¹ ×,sr @Ï-=·ôše.Cnè¹ ç€^³ÌeÈ,=·ôÜÐk–¹ ¹eo &è¹e‚^3Ì5È-=·ôÜÐk–¹¹ g‚ž[zÍ2AÏ-=·ôÜÐk–÷kYznè¹ ×,÷Ö-‚ž[&è5ÃÐ ‹@Ï-=·ôše莕 ç€ž[@zÍ2ú+Òs HÏ- ½fýŽé™¤ç^³ŒvÇŠôÜÒs H¯YF¿cEzn鹤×,O¿c…znê™…¨×,O¿c…znê¹¥_r¢ž[&깨ç ^³<ýŽê¹¨ç ^³<ýŽê¹¨ç–méw¬PÏ-@=·[¿c…zÍr÷;V¨ç–{kw¬P¯YîÝ0ŽÏKÔk–ñ¹c‰znÙŽÏKÔk–Ï+ÔsËùYc…zÍ2QÏ-÷g깨×,}ê¹eík¬P¯Y>k¬PÏ-Çgê5Ëgê¹åþ¬±B½fù¬±B=³õܲ~ÖX¡ž[€znÙ?Ë,Q¯>ˬPÏ-×g™ê5Ëg™ê¹e¢ž€zÍÐÆ¨ç†‰zn˜¨× Ázn˜¬ç†Ézn˜¬× w{ž¬ç¶O³_Ök?ïÞlÀž&ì5ÃèÍì¹až&ì5ÃèÏ—€=ÿ9aÏ öšă¿ÏñÅô;O1>«(`¯>‹(hÏ “öÜ0i¯Z³@{n˜´ç†I{Å3Ä=O1qÏ ˆ©k†É{Íð´i`¢Çõ6ÉŸ®SíÚ,Ъ,êù—Ù*“üµÑë²y²T0f™*þkY*óºàè/Š/ &/J+ê}õjmÂo+f¬þþg‡èåøYlèïù:þxlèëùKÁ¡39ÆõÎê³ÅîýN³9ƒ¶ù,±T,)?³ ü¬r2‰Š±4,¥Â>³û¬r*‘ òT*IŸUP~Îr”$‹©4*%Ã>« ûœåd¢,è/‡Ž°ïËÄÏcC_¿úúØÐ¿¹ú¿ˆ ý¦;–îúç“é·±¡ÿÀ#ëoß§ÏÏPûÙDý<³~1QSÒ äº ý¿Ñù¿ftæŠÓìq£ÿAHçëÿŸÈÐôïí§¡ßËü?êŸÿ=Ã0ÿ£ÀÐoâÿó_Þ{hy™ÝþõÏ }ý,0ôßÿb`èqñ^ð>Ô {üÅJ¾X§‡äÂÓJÇuÏSu–€ôu¸õÜ#2®1Õy×$ì&{ pë¹xxϸ—îÖ3în=:!~ÜÜz7ñàÖó¶s~"÷;+WsÆw¸ÂüË»Š-Ø2îsþÇ¡¿¿žùiú¹?_Mß·~tôŽè´ax°%gÜ4î_â¦û×ðÌÓïT¹å-ýF–Yj< t•ø5›ù¬Ëü|½òœ’×0‹D¬ìñÄPñ›Gf¼ïGÑ„8iÝgnþK9!½†{¶zã+#"¶í-Å‹†óôÇQ½‹Ë2[-¤×¤Êòœ³ÕUè ÒÁ÷£±,Èðð'ÄѬ#¢¬ÍfñX’1¢,æz4"òÙl}šF„1Û[ŠÂÊÆCGFDå™ ç4¯ÂÊÎSÆ;Ñð;aÞ[G WS¬ Ï@Ãy<üû„»ÐpÞéóbC´|+FÐ9«",CͲAZÙ„Ux-;ÔP Ðk9 ®XE7¬[âÀ÷^òôØWœ÷Q#ÖÖ¸÷µoôŠŸ«êk £¥yÿC³<z67f¤ýkÙv þ‚=D¯åm×ÚšNmg5oºí¾ál²÷÷K‡Í’×rAÕ¬Ë3·óü¥×Î~Vè³Ï–éçXÐô*aàÔñµ8üôê–éüb¿·Eó‚C²MïK±C­vÅ©°£[NH ;Ï@ DPKsAUðû×rC­qÚè û/ǰ܊¯\ãl5í ¤Ðªé¥I´¯Ò¬C«”8®ñéiöí3þûŽsÇ-ÍM´Ú·Ÿ¸ïªûU”—)N6¼z–ûn³)Žrõ[óµ È¢*bŒvNê»ä,—ÏŒ8Åu·ŸÛªqeOâ¬"Ä¢uqRãçq|¦Nœßj3ú8Gÿ3Ïn­nÄá­£[pz«çzÝ’ìjœ™´·+Ç·Þ-͹®œø*9Žjë·dßj£g·ZëÏ£wî<°&Öxı­6äqfëÞ.kœþöô*ïçÛ¬çüÜ’<³Õ.EÚÚ›>mµšâÔÖ³5îÚ¾7ܵ/?ú2Nmí”ë89+²¦+¤åº¦\tÑ­±#[×ÞYÁ,ÓñÀêÐyYÇM߃*ô^¹Fæ3ö¦÷A= ã¸Ö½ç¢ÿ+ŽÃZ·6(<¬Õ‹=o ?7Žk½Úóî¾·ÞÜ›+e.$qXë襌¶TÆI­}n<ôÌ­Æ=ôB°4tÍ5 ýêF Z›ÖªõÏÙŸÍ<¨ÕS\X*ë ò¤V¯æÙ?Oëg¬>1âœÖ» S©ÝZEqPkŸÙ^vmEìØ³§ÙûËAD+=º…N¹–ç|>/"qNk¿q YŸqNk¿<§ÕÛ7N=ΑkµVžxeèó{'µz)±úõöÜ=ü1Ïðþ.OPݸPñTú±õº®­_‡¸½ú“{îD¸z›ŸzN’h?ǧõër÷»s#ZÛc[_9¬VÑjýá·‘lÇ íL2»Ï9Võaê½/m’Yï·˜=ñ"î`öD̃† fô™`6‘83¹,ˆ“Éeq3óc,¹ìyŸøäK.‹oÚÏb\÷Öu#Ëä²øÈÀÀ“Ëæ¡È¹ fÏÔàËž‡»IeÏ»€ @'©ì ù†Ü6©,ü æî BÙˆsçßÁdã}?ºh˜L6žS<‘,ŽÆ{0 `²¸±ñf2Ùˆs¸0(`²ðUgÉ"85¾ßÉâ x&ˆ¬Ž'‘UdjY<9ØÂ dóþŠÈÂMk€*(fòXDø,à±Hñ 㱯¹¸’à±0¯è%xÌ˘<)»À±± £ˆ‰c!,ì¸öÀ± ƒM³ßN D³Xaì÷D±±]œ[B±àVÒ¤±n™a?_ ÑX…ç…e¡aÂXãŒUÀnÁXK‘pçA˜ü=a¬[b‘i–ÉcÍ2yÌ ‹4¸‡ÄcÍ2y,ƒ… Çjð…c9Ú¢1ù5-¦ÔO k– dyQÄcn˜8Ö*žDæO&ó+ &s ˜¬YÖ~Ád~­ƒÉì*ÉüBÉZ!ÉZš‰d~]d-ÍD²–f"™W>‰Ì'L™_h™"ó< ²f™DÖrM"ki&‘µ4“ÈZí“Èše™M!0™î>é€d­Œ‰džeB™ÀdaÀ©Â2/dæ™&˜…#Ⱡ̼1`³–f²™sŽ™  èlqÎZëÜ|V줳–kà&®\ ³f™t浃Î2¿à¬ü‹Ï¼ò@´þû™]0ËD´VѤ4o0(Í«žæ†Éhn@Ð]+ˆæ³,Í/ ͯ,Íç*Í.­eš„Ö2MBóLКáæ2K™ˆÖš7­Y" ¯‚ƒ'ÊFó`´n™ §[&£5 bñÚô¦µ4‡î¾L31­¥¹Žoš»ß'À´f™˜Ö,ÓÜRë–ñ™C 5œ‡§OX&D絩PkÅ B¯[ΣçA„ÞšŠ@µ–äþÞ€@µVìøÞ€ 5OZó4 µ–fÒZK3iÍïÛ µ–bÒZ+‡P4ËóaКu°Ö ž°Öªž°æW°fi&¬U±dµ–`½û!«YëÈj-×dµn™ké~òe_¬ÖÊ™¬VçˆÕZDQŸ¬Ö~ã Ï3‰Í- 6Ïbki ¸{šIl- Túr•øÃáÉlŒ‘ÿk5-<äñ“jÚÁÐe©¦Å«õ|+¦š¶n8¾=Å´±bÇDŠi%„ALK(•˜ÔébÚ ´°Ý>¦’Æ_çÜ$²`{]êhÚBž:šv™§Ž¦íì©£qÓGÊhù›*š6K¥Š¦ý0©¢ik6U´÷ç‹2šJ„ЦÝß©¢iSIªhU#U´2PEÓ¶ÂTÑÞ„GSÑb96h³‘‘Š–) ¢i;mªh0PE{׌œT´**Z¶B*Ú98¤¢•*ZøÊ‚Ò¨¢½r…ðF­ ¥ŠVÕ>[kU´**šR”Цf”¦L%¤éèÝÒ, …4+™B·2—ަ–Žö#’¼|KG³<”ÒÌB)MÃRRšÎ.)­š')­Ê‘”V’”V%KJ«JJ«>@MÓ¶êRÓ¬&ªinyÚô(5M§— 6—ái ¤Æ£ŒKQ«^JQ«R ¨U¥¨e©Ô,µjš5Ý%¨YÅÔjX$¨Y j5 Ôt{— V—‚Zu@‚ZµF‚ZÕ$AÍ,Ôªn jnÁ7B+™‚š•sö[°5ËuõYššÕDMÍJ¡¦fi(«UÝ’Õª\)kU·Ä5·ŒÏ4—¸fi¨¯å½+yÍ*Ÿ [])l5殺U§¤°Y.*lf¡Â–UK`«b$°U& lU¹6=ÄKc³\Øž3T2[¹d6³Pi«Òæ–ç3K¤´Y9ÚØ«nJh«LÚªKÚê2Ih«b%´Õ`Ih«nKh³r(´Õ”Ðf­¡ÖfjmÖBjmÖž±´‹ ¹­Ú'¹­nyÉm94RÛ,Õ¶ê”Ô¶ÊD½Í’h»oC½M/¥·UŸ ·U±”Û,å6+„r›b”âVÏP)nÕ<)n5XRܬíü­\TÜ̢ݿUÎy´öIt«>Ht³<ݬnŠnu¡$ºÕD’î–Ã%Ù­f„d·j°d·º.’Ý̲÷¨d·š’ݬ\ÊnV e·ê‚d·j0U· ªnéâVª[CÕÍ~SuËRRuÓöôRÝr„Su³r¨ºY9Gß­_ª[^ßTݬ®»oØ/ÕÍr=gÿ­@8•‡Ú[µXÚ[µFÚ[õAÚ›å¢öfi¨½éâýƒ°ÎÂ7§Yüö>](^ßÞ÷·9Ë߶{÷†¼~˜æëÆ×ÜâPÍÉo¯.ir†Tèt†|gøä y]?(ËѲ @¸M(›Î î,ŠC|h!œýg›@¸¸ÞôÇÃY@K$ÁE\hJlËËÁ÷Y=ÞŸÎ »G[ÁÙßApœZgY@p–W^§$83€à2ºœ.»1®ÒàêÏëÑE~³#2JžøÍ ÇÑE~sC(~«f“ß2f)øÍê¿Y à·Þä·¬5ùMM|óLƒf’‘>Óp¬ŠÎ·‘©@o^ èÍ«¾>M¹WÍ•zó4ÏõmèÍÒÞ¬Ò[eÒ›ç½yÐ[Îî¤7Ïuô~“Þ¬}¤·,›'¼å…Kxó4 7O|3 ñÍš³­½&â›urÛžžb?? ¿y©çò`ò[ŒO~³Á#¿å³%ù-ã×'¿yšq¶rÉo–‚üVL|³b‰o^ÌΠŸûÇÒŠ9îö,LzóLצbZƧû}÷C Ôø³q[>’“Û”€Ðæ 6†ýÌþÚÜhs  -×’¤¶¬èýÏ@6¯È–ç$²yš‡»ªœÁ[˜h³p]ÌBlyB[fÙ®OÓIkn9>)@kn9¹³híçÍfË0 Í “Кa°Y2LBsÃ$47LBk†ñiÖ$47LBsÃÓK˜„æ†Ihe¡Õ`ˆÐZš‰hÍ2­Y&£5Ë„´n­ý‚´f¹Žþ{BZ·<ß>LHk– in¤uËóé ­Y&¤ùèÒZš iÍrô~ÒjŽ Òºåi[”Ö,“ÒšeRZ·<힥y{‚ÒZŠIiÝÒk¥µ2&¥ùÈ€ÒZšIiÍ2)­Y&¥5ˤ´n¹¿=}ÄAiÞbPZK31­Y&¦5ËÄ´VÎÄ´–frZKsŸöÓ|tÀi-Íý)wrZ³LTë–ñéhÍ[`k– l-×¶f™ÀÖ,Øše[+ùì³ÌÖ,“ÙšåÁÈ2'¯µZÆõi?­YÖõs €lͲ]Ÿ;ÔÖ,Ç'Åñ|Újk–kÿ¶ï^>×ÔÖ,ÏùíÃØ?íµidÚÚ_×óÓz@[³ì˧ý€¶f9ÎOûÁmÍr-ŸöƒÛšå>¿í¶Ï5në¿ïOÀmͲnŸ>€Û4.`¶ö÷ýø´ ÌÖ-ßûÌÖÒ\ǧýÁlý÷ø¶ÿ¹¾íǧý`¶nŸ>€Ùše;>}³u VTçµö÷óÓ’ký¶íz>í¯5˳Û?¾÷xÍ-àµfY÷OûÁkÝò|ú¼Ö~ßÕ¼Ö-=cÀjíï÷w%«uËw%«™e²Zû½~VR²Z³lgo?Y­YŽ¥½‹ÕZšóì} «5˽ô>Õ82“ÓÚ_ÇömÿŸ¶Óše=>m§yûÁiÍ29-BÒ>yÄÎ ɬMm vVü‡°¿kòÛ™þÀ·ƒ') ß·~ßâ·÷fÀ–ñÛ%ÁøV ˆoïD:¶¶©m`oGîi;¸#;ÚDŒÚЦ?Ÿ}»®x WÙÁo±Î<ß*øÍR€ßŠ@Åo–bmEþ‚ßêïä·"«ä7±ùÍ´5ÿ+Ùß® ÝTßsvºå>@¡3ݶØ6jÔ¦Ô¤¶*Ô–9m•€Ðf¬3o:Œº M}³UŽÉl!4f«¿“Ùd(fSÅl‡öý ÙÊ@b³<$6³ØÜ‚õE­+b«‚¯£ý$¯½—™þâµJB\³jˆkUp-3‰Ö*“h­j­U&še"¬Y¦£g!«Y²š[žOÄjf!«Y.²Z]G±Zu[¬f–µ×$VsËÓê«Y ²šYÈj–‹¬f5“Õ,YÍ,d5·ÜìA–<ú€‹Õ*XÍÒÕÌBVË %T³bˆj–‰¨fiˆj–†¨æ–ñ¹ €jö›¨fyˆjÕ<’Z%©Õ‹Ôª`‘š[Æg‰ÔÌBR3 IÍ-}ˆÔÌBR³<ÏúmiÍÒÖÊ"Z«\¢5KCZ3 iÍr‘ÖÌrô^ŠÖ,iÍÒÖÌBZËK%X³bk–‰°ViknéC#`³ÛÖg‰xÍ ÷'i­ „5+•°æ–ûs kf!¬™ešÿ¾?í¬UkÙ<±Z=åÄk)H ×*iÍŠ=F’ Ö, aÍZwo- Y­ D5Ë1ŽÞz‘Zµ^¤V™DjfÙ´’ª˜ý» Ô*Éq}¬V ˆj–àú,¤"5KBR«$5K2ž>úâ´2¬ŸeT”V…ˆÒ*ÉÞû+H«d4Kr>}f Ó, 1­’ÒjˆÒ,)M™iõs]ZÛÑʰ}VÐ$4³ÐÜr·±O@³$×ÖÆ>ùÌ’ÏÌòôÖŽíÓ|Zå¡å,NBËL4ËD@³L{_=-†òºÞÏÙC„îÛ|² Ê´x8ä_ç«TJóÃ(oÛKRV>~[Àâi°(©üm1·Èþ´Bhñb`ò‚d±¢öu>f½¿´XQ4YQiùg‡Q^·5îå¿Fùù7£ü“é±FhšµRþLµ9‰bGÐ'Ü2ʲ0É(ÊC)³¤JÂZ¸e”ãa’QP ¦Ì’,‹ê!—YV…JfQNY%eä!—YŽ…JfAPY%U*õ*¿¸5éøQù<Àþö›GÑÏWûé¬ý>Â~1kSÖªüÞÉ{\C «\ÿMã*gôæPÊóO«¼®ï ÌkúwWù±¸Êÿq•߉Dßñmžc7ú/ ˆHöÀ|»èJº>qNé¾!&Ù³Mß›}Ýœ4L×›‰Â,`Ÿ®7q¦ ƒ¥=Çt½ÙÇ¢dÏ9]oö÷¾È¯eºÞér{EDôzŸJÇòpgëúÀ‡üÀ\ÓòLÖcáæ‡°LG¸ á/Oœòzl ýθ‘DZ7 úq²F¤9±=,Ó î¸@¹è ð"?Ž á‡_Ë1Y÷¦aãÆ1Yçi:èÀ8§#ëqp×Äk™Z_‹üäÖqOGV/9Ž—=n½x?Ó—ÕóŒéËzœrí~×úéËzò‘ÚÂ9*:p ÞÛiúÀ'}ð_Ë6ÝYS~ÏÛ7òã”Ôk™î¬qþÏÍ\ÇüÍSêßßçôg=®•ûk¶näÇ)oï-ª¤y˜ëž­qŠÐÎö=Ó£Õ-cAª®1=ZI­ax_”g®ƒ³E¬ìµ[¶éÐj•¯áH…Ü~ï'ºPyàH~¼œ±`@c'Ð fì¶Â‘<¾†`ïÖËÜìÂÍÍpÛ GrOó,èƒÅ…åFûNî$ÛÞ™ƒ>d® ®äaÁ–Îm‹H}VʶÞßÛ!.Ë>ÝZ›éÂ2Ї¬{;nôáAè‚xÇ=Ї²\ú°sÿÙkèÃñãÄxÅsjöaÄPÓgr¯=ÎÐm¿¦Iö{_.ô!ëÞáS~¼÷Í‚«¹oÓ­5,'ÓÀ§?ÓÇ¥6ËX4ÍîÏ ¹–ÏïuûÜqZêhs&NK=Úý§¥>˜Øl¸Åi©|Úl² /ïø8-uksæ‚s¹uằªZ{à^î–çnϵ ÎåÕí8*u´$8*Õ;Æõã¬ToL°m¿ qXj`Þ8ÆfÑ}ý*Ü8"Æ›s^5öMzó°qÒƒ­“67öNZó¸–[®»'­î®åžû'=Í~yžƒ«j^8œ”êIÎGO>…8–{©7ÕÌ„m”^îó|¦È3ÎOƲ:0°Òb¬OÎ •6x~åVÓÀ¦ÊjÞ€[¹Íò]•vskÓs™°­ÒÜ8$Õ‡f<ççQŽSRmJìKì­¬Gľàݸú¸/ëñcô<Ø_™Ù쯬nïËþYQ÷å8ú}º/ØbéU\Q³àëî×`_îÏ‚ºÇžáVу5o_TÃŽRíªìëúYPwœêÍ[7.¨||î+_‘­˜ƒëi6o=F'ØWì´ô4×Ñx½W °ò`§¥çÁNË«-m$‚&7O²-O›E{Žºúsfß°ÍÒF<GµÉ¹oûói>NGmi°Í²î&}H±.mØgé–»ßÊ4f³¨¯ü[D}Â:”Ô÷ÄA›ƒØ´Fl³›ñS ~5ì"t€ü¡€AWE~Áù ä·ÁðËå ~Üö%ê‹wÿÁ¦1ò“ÑIê[ßõä¡*ÞYÉ o“ú*R¼¨/˜Iê ‚‹dÈÝÃïÓnoÔw¦¹À/ÎÛYYÀ/#—%øå‰/ ~ŠìMê[ßwЃUß<ÓáAŒiRßK¤pB_Æ Kè˃ìú*Ì‹ /æC™Ð`²6苨H|úÖXqXòÎïo=Ì'ôUk}hCÐW!3}IÌÍ;ó­ïƒ/¹d¾õ½T ˜o’rúÜè[ï‹H/è{ï†8Z –(÷a°ò„¾wÒr'” ¯¾Žú¬Å„¾pãÌè³ú¼}€¾5Ή"J…µÐµ/Ä5ƺÇòQÜék Ìþ"gc¾°,$G0ßN’üÉ æ³3úS]…‰|1OC>ë‘Ï*"ò¹È]؉sŒýT"òYˆ|ë#ºCÈ™÷y¹‘ËÀ{nï­8ŽyZ‚÷b}á§òÞûLbØ~ñ^tIyù©®yϺDÞ Ë-Dȳ0ôSu›ÀgWwŸºHÚ[‡>ΉöìR“ö< ã>½in6´ÃÀ/:¤=ÒžYH{j Q/n8<'…zÖŸÉzÑ›‡4Ö³Ñ%ì­±0 `Ï.4iÏÓ€ö¬ÛÄ=ë6qÏ®>qÏs÷" ?‡‘÷æÙh™¿/J’â=òž•KÞ³ëHÞ³ž“÷l´È{ž¼g='ïé"ö¬Û„=·ÕÕ'íY?‰{Íò|ûÀà§e!îY]Ä=‹‰{ö$îY/‰{6ˆ{^.ƒ>ó‹eÔ20äSMâ^³ÜjÊe$Ôê7q¯z Ü«<Â=·0jާ½ê¥x¯FB¼WsB¼ç†D<Ô2yÏÓ0(ª¥ðåà€÷j Ä{5mÄ{u3ˆ÷¬›ä½fùÜ…â=ë&ÏÓ0.j ¯¦€Ïº9Ï30ju›Àçi5§–ˆÏr‘øltˆ|nóYÈ|6^“ù¬d> 2Ÿ[Õ,×¢iòˆŸÏu ó­óuçOE}6­/žk&õ…{4ƒ“=:2S‡5Aë³g”û"ˆñhz_E£õQˆú¼œsëñé„}ÃNäWáX“ü,ÉÏê"ù%áü5È^ û›-&ùñˆüêµ>Éï}ÝÛ˜‹Ó;Ñ$Éï} q›¼¤…åüÞU–aÍV2áïýße’_”Ò?3ý Ä~ñÀ'8‘ýî Ǽû½³êÀ9ÙO£•ì—mIö{-+±m²_ØÏê&ûe¯“ý¬Å„?KCø³rVwÁßÖ¿œb¿J"ö3ìC#ö«ª“ýr Ä~Æld?³ýÌ"ö«rÄ~‡^Û’ýžhSì§N%úeÁ~…”b¿*VìWÅŠýªãb¿B\±Ÿ¥!ûU§Ä~5’ý²›É~ÕÁ_^À_ÍGÁ_](Á_åüUÏ5KÕbÁ_Ÿà¯z.þ+~ÿY{ÈVÎä?k ù¯ð_üW#!þ+‹ø¯Z,þ«ºÅ5^â¿jø¯Úþ«9 ´šˆ€Õo!`ÐÊ!š…Xs@Xí¾ûZR`• ¬ÑZ R`Þ0‚À2­2`%!Z±DÀN! 5†è–[tNH `Mb!`5F˜KG"`Õ-´rˆ€u1…€V7°&¤ÐÒ­vR •üôHX¥ˆk$DUŠ(°z% ¬ºEV2)°ú ´’ ‚ÕB`@°[A«› h‚`Mk`Y‚f!šeË¥•½Öò ¬ö «ßA+… ˜/ ‚–† h‚`N~q`}zVóÄ58âÀbp`+ ¬+ )ÐJ%¾÷ãÞ1°†Fh“«`b`}ìVR`–B Ìš“sx“-)Ð-£¶N ÌK˜ýN tËèS$)ÐÚC ̱!Z)Ä@³u BR F&!°z ÌgwB`Ι„@ËE¬ºf!Vå×Ñ~«‡B@«™h­#V.!`¦ÐÒ“(-ÍÞ($ÐÊ%Ö<ÖÈ-ÐjÒÙìç?½þÚdz¢x üש Ü»AÖÎ}±§´ùy®±†ÚÕ¾[îyÉ}ïÓqíÜWŠš¸o9° ~‡.±o]%#’úLœÔGPNè{ïƒô‘¤Ü7ŽÄ®_É}na´àA_É‘‚¾ØîÅ4„¾eK§S@ŸÉš„¾ œÃ /väpË ©Ï[ ì ‹Ô1† 1ZØç† 6 °oyŽøëð%"li¶Ø‡ï°¯¢Î û–'½Kˆ}xŽ…Ôg•ûÜì«!öå9U‰}naÀà§³û¬=“ûBµ–'(¸ÏÚGî+e[Üi6R¸Ïsû< ¸Ïú@î[žtí%÷-Où‚ûÂ"R 6ËØz8¸ZLî³4ä>k¹/ZóÈó±ƒkb“ûÜî«[QÜg} ÷yíà>Os­Oä¾å‘+2±Ï+bôà²û¬yľfAôÒªŠØç`Ÿ5ob_4†.Íľ˜H{óóôÖûìN$öy`Ÿ§ö¹Øgb_, —´@ž5‘í!öÙåœØgSŸØçå2Œ°YÀ}na$áêÁ¯.ÁÏ«øyó~^0ÀÏÈPÂUÕ?KAð³R~µj ü¬5?·üše|ú@ðóÚH¸zEðóö0”pÎä>»åÉ}6·È}V5¹Ï*"÷YEä>·€ûš…ÁÀsÞû¼®“kk¶Üçµ_£ÿæ!fá)V Ïɨ‹Iî«¡!öY&bŸ5ØgUûܲ~󬌺rÄ>O£ó2rhˆ}^7Ͱ\<5Ã-Ïç2ûÌBî³’É}Ö±>­5?›&?-’Ÿ§aa³ð «‰a„«$¿fÁÚš—Šäç]`ᬠèW)„~ž‚Çidc„~ž‹jXž¨¡Æˆü¼`©á–¡‰¾Ñ™“‡jXU÷Ñ':ÈÏS<ãÛ<¬¡çÐÏj"û5Ëø´ìç¾,[.ž­á–ñéê³54s5X„?¯ˆGkT¬¡Ý9b?«™ì×,Ï»[À~Ö²Ÿ§Ù×Ïo.¬Ù#²_5èg= ú5ËÓèB¿ìÔObO'îQÅ6ÜÛcO8Õ7º-çf0à^9©Š÷Î%ý%É{çžG‘÷b5åž8ò^,ž}_ßPYxï|;*¿QðÞ\<ðÅâyIÕ›«ÒµÔ.>ßqo˜&ˆ/¢Ðû”ÈËi÷ð¼¶Ú’ä› lC¾¦Â£‰‰|×;~[C¾k¯-x@¾kÏðâD¾kÏðâD¾ëÈðâD¾f‰ö:ŠDÈwÚ('ä‹È-ò¼òÅr¿6¥Ï-@¾+æ]C¾˜¬mg_pÀÞvöE’Íœ<ß÷O¾ˆo‹HÖ›ËÒ]h;û< ˆÏËñE()º¿‘ø&•°} ¾(¹{yFÉò´ò½ï­òñ#òYíù¬&"ßûÆ,§3"Ÿ§òYkˆ|nò¹Èç Ÿ·Èç½òEírÐòEè­ÅÏÚGä³r‰|nòÙ•!òÙhùb,®ææùb¿\ù¬ÅD>›9D>Ïäó’ù^h¢ƒ¶ÏÚGä³4D¾š´$>»¼$>Ÿ]ŸçñYÁ¾7©¤5Ÿ·æ>Úu"ðÙýBâ³¹Eâ3 ‰Ï®‰ÏÆŠÄg"ñYí$>«}ßÛîñ@|у•rˆ¯ºMàóL7oD³<¸9 |6X¾˜Î|QDŸ5‡À÷NéoÛÞ³€÷ì÷ìâ’÷lÈ{ÕKâžMXòž Þ‹^ž÷¬ßä=»tä=+gòžÿ^·o ðž•KÞ³‘!ïm3,Ý4÷¬—Ä=râ^õ›´gƒEÚ³r{Þ˜§ iÏRöªžµŸ°gIÀzv Èz–¨çõ¬ýD=›"D=/øý7PÏî~¢žU Òó€ôlt‰zV0QÏžzD=»yˆzÖ©‰z6¾D=»™ˆzv­‰z^÷uj€•¨ç­yx+W]@=¯ ¨g-&êÅy䨉5µÊ™¨ç)€zÖK¢žÝND=Q¢žç:¹¦fûˆz^7PÏKêÕ¤&êÙå$êÕ¼êU·…zÕ¡^U-ÔÛâÍP›ý††xm{ûjpÄzÕ`±ž—|޶ õ¼Á@=oò³õªz^ìÈ•iˆznê5Ëè³D¨W³M¨ç–cmWA¤÷.ëÒ;Iz6Æ“ôü÷½j’ìÔð€z6d=O²^='Äz5ÙÄz6|d=«¬WWa¢žUDÔ³±"êy±çÞŸ—ºÉsqI͉¤€O²ü‰øÕbÀˆÅ÷Ò–§z-ŠÈŒ¨x ¨† ~wˆ¥ÚÏ7wø=ò}Ñ¿wV=mƒ_Ë40£ÅÉDµÃo©ð/[9G„9ðMïZ³nŽ€a¹´¥o"༕%/¾ËpMŠ”‚XÆW¼ªË&>g*3~-«¶ôMliÍØ-»eÆR=5H€n˜è†ÉÍ0ÚÏIa¸WßãgÒ_·Ì0ªnA0c·LúkD3n–‡íOKD3ΰæÂ¿fA8ãf™aTÝ2ñ¯Y&þ5ËÄ¿n™qTÍük–‰Í2ñ¯[z¹À¿fA@c·Lü Ë#÷P4vËÄ¿fA@c·Lüë–›íKËÄ?·ÿšå½éûïû›bâ_³Lüë–ñéð¯Y&þ5ËÄ¿nŸ>ÿ|Í2¶Ïïñ™'À¿fAHc·Lþë–ñ™'à¿f9ŽošÉÝ2>}6ËýiñÀny¾}@Hc³›!›åùôØ,›åèw4°0ä?7LþkyÐØ’Lüsä?7Lø3ØÏKûy’‰~nØZ% ¿f¸{ÓÁ}n@,c3Lìk†»?ÄI}Í‚HÆn˧íelIúÚïuë­óµ$“ù<ÉD>7Läky&òÙÒEä‹sN~(ó5Ëd¾n™ÁŒÝòÜó÷"±ŒÍèë,¤fY±¾y©âûž3ßùA}Í0>),£eÀñŠfÀñnóçN}Ä/"œEyDG< òu ÖÑ5C¥ –ñ©—4ŸËø\ÊÅkh¼òîµß8©Ã-fÜ,XCÍ‚hÆnÁ‘ÚZqgpfÇÁ8€s õ48µÃÒ÷< p¯¥Y{¹À½fAHc·àôŽf¹?íî5 b»§x4ËýmòÐ,½2LÚk?ïÏßq˜‡pš‡æêG8è¹Çy˜Çy¸a®œV(Žó0Ä<7<(AQÁxžzX ž]Q"žeáµL8ÑÒ฾{B‡X´»o.™ïýº+ÎópKèq\â^K=ÞréÍ ¾sô°R€wÝ2̸ªIwaX•zÄÇ;…”Þ#Ŧ§ ñ.îÐU07ñ.ÒÈ'z¼c¡ð.î:+z¸zÄ÷Ý™Ëc_ïc‹ÞY ×'9XìkZZìë_æ³Ø×Lóc_ÿ¶Y<Út¯â™ÅW[øzQ²XQ4YQiñ¢â,&/hþöbÂà…à·q.æ|èh±bh²‚ÒâEõkeWÏ‹êÆ/Õ?="w¼€¾0l!¹#Šv`ÿõü&Lr…ÙÞÃ`ûuøî©u½þóþû%œ¿ÔûûgÓkìºüj€qJá²,ò6ŠòÈÛ,©Ò° ÁåxÜmÔân³$KÅ¢z o–U‘·Y”EÞVI™Fyo–cq·YGçVI•JEý•èÜûæË”çþá·ÿh€íÿѹß×¢ûú°},[àË¿ŸÛÿY€í¿ÿÕÛï/&qlÍûìögZ|[ÇÍ}ñf1Ýõf2ÎùfÂä§åZÿeìrÆÙ#ìZ;ñ~Ü<ýN º!ßo¹,¿÷ÿüorŒ_7Æüîß$sàX.ùtá9–9ûÌ=罦Sÿ9w…{-SʽÞ÷Jø ¼*®]1©å'•8äÄoøT\ïûü͚ΩåÞ»6ÚË5µÜ8ñ`M÷Ôrïû†ßÿSñœ‹”LòL-÷¾—¬zà<ƒw(à3sÄNŒ· Ï.¿š#¶­¬hà&ËT€â¦…Güñ>ÏßßñiÇo¸T܇öɾ–.(À±Â¥â¾èáˆhÑ…]»|Ž.€R¦–{¿kèÆbàQýÆ~Œc†%‹4 £Q(âMßíy5×1ÕÜ;¾j ×¶Ì…â¢nxlë¡E/§Ç¶M5÷Yå‡q„ÿv!tÄ.Î#ä'jÚ5|\*žEѱSÏg1 |*ž-àLwl×t£œAKøTÄI ÛûL97¾!<,>÷õÀ™Ž/…ï@ôm:ö…+äªÆ¼„ƒÕP‘â_ËtïP!0ï‹:ºp1nßñ>p*Í1Ýç}jãî}-SÐ}jDÇû”è…\SÏuË=õÜgW ð×2õ\½.^јzAï 0ý)âÌÀøaY.ä]jNÌrù“ö~^‚…ñjŽ.v™"¤ýÌÃYÀ¡"ŽÂ„#âÁÏÈoíˆP鑿T@Ð#âRÎk T:ŽûÔ4,ç™bnœ‹µ1͘b®uû7Æ7-çÜö¦‘ëËq§ÂÊ9C{‡Š±}ÞßÓ£">ØÀíæ8÷Ó|ÑÔ;áRáåÓ\Ùã„K….Ây¸ CçÍ{0/ÂyÌñ›óõ|n]eSʵz‚ÔßZ%³÷÷|w ÎäáZ§”7;Ÿ+×6ßø¢jø)á²ø´Ûé‚OE\m>4µðnk3:Ž¿—@Ž”¡æ‚Ïò8÷ì)àRñ¬r¬<âÜÅn²Û ø¶wíCVß¾p—¾xo{.ª â½ýQÔ>_'%à‹ÙÂ×?ßË?| øâP_/Þ‘Ÿ|™Àï|W¾óT<ßû$Õ:Hà;ãdKÀ{µOF¼çóò À¯yL‚i]ÛdÄ{×–oä½{S@mñÞ9tDx¯6”$ï-77F‰÷âel4Þ‹÷@¾Á÷bN«ðÞõ=[CÞ æh‘÷îUßÄ{¶ÈNÞ›ÇIŸä=}OÞ»ÞÎø*—€ï]±±W*ïÖc |ûò>#hß©€Ê |ùÎEÞ»o]ÞÉ{÷¹ñ€¸WKaâÞ±'Ÿ÷îw ù:EÜ3¼îÕ˧ˆ¯ÞîH|ó,bÒ‰¯Þ†H|ùÕ·ˆïÐV3_¾ÿøjµLà«÷Uß­` |ùÌOà±’öμ½D{ïì¬Z´—ŸD{Ë¢½zuí…xLn#íí'ÃEí±P¢Þ¡Ó?õžœe‰zZN“övm½JÚ»Î$iÏ#ÜK:îÅÑa$¡‰{Õá^O¸#îÚ¢—¸W| ܋ۮã^<(XpïydBKâÞ©É{±óPuÇÙLAÞ;ôm1y/^1‰‘ä=k y/öÁ¢5â½£ÈJ体§†$îÝùá¸7¦Ê4ö‹HÚ«ëÚ{ç›(´û-™‡´wå’&Ú‹/³ö¬1¤½ˆ^Bj$íñ£¦P¯º(Ô«b‰z#®:‘¨'Бí&ëÅ]– Ö Æâ#O¬±BX Yïzt!ÅzO>ì{÷“í#ì =‘°÷Ü_Ø Ç’aïñ`o¬¹<öâˆòyï¹Á{‘•·˜€ï}~ñi%â{ŠÔ@|Ñ~ñ½c!*ñåá‡c߯9ÌDà«ùIâ‹©¶ÓÈ.ø¼‰|ñ2†—K1_–+æópä-ä›g£wäËë"äAÄ7"ßÐÇp!ßXuÆ‘/Ç*‘o,üù`xµ"‹÷Æv¨mĽœ‰{C¯ Â=«—¸g=îEðb@{ž„´÷N4Uu\]¾î“öêÂ&íU±€½˜1{ƒ½8W~°½„=ëaϪìEŸÒ`/f Ö䄽ðo¤°gW °Wåöƪ}Óâ=»â½ìqÏ:EÜ‹Ní¬ˆ¸1_€Ä½1~°nßˆÇ Û à³ö øjæMà‹Ët7à«'€oijZx7ÔñvÝ|5[ |õ”ñÍǡė÷­ˆ¯nAŸ×âË{›ÀÑËØ_x² ø¢Áü²@àËIýg‚k‹ùvp•A_D¾{Mè›»*Ät“úâšv/ÞA6þF¹ŒœB_FP+¡Oц‚$óÉ|ur®d¾ˆ Œ2ߦ3~D}q\íÒd>ƒ(Rßq+”e¾UßÄD}žÔn¨£aßµæK?±ÏÓû®Uþ°©ómš¾ ‚ľxxMÔù†n›Ôùb¡ašÀ¾xyyÐùò_2ŸI”ùJt”Ì—_ªJæ+U:Ÿ ˆ˜Üö]U:_0ÓPç+ùE:_ ^“ûìË«¸¯D2é|…©óåÅ“ÎW¯ìÒùê+¹t¾z{•ÎW_ߥó]ya óÕçWq_½&‘ûLª ÷…¿súL¬"÷Ù¹ÏÞœ%ôÕ»¹/œ­I3â¾ðÝc]úê-J_½-Hé»rÒ ý°ü¦Ì7Ii¨òÕk°ïZÉ›¢¾z…—Îç¾ÏH}ù¬M¯ õÕ+0¨/3d `_½W‹úâéJ„»øÒ™ RŸ ê³Sß[¿áüêžàWÝ$øÅ3›¢À¯^1'øÕBšàW¯}¿÷ͳHoû´ìWˤØÏÞûÈ~öŠ.öËUFì7¶üÂ@ö«w±_¾oý¬X¢ßXo~ "ùY/I~µlŠüj}ùÅ—¾³ }õ‚#òór@~Þœ ¿XÝÄ¡ ?{©'ùw~ñµžägã@ò ?ñ›$ò«WH‘߈­ž0€üêe;ÉoÏ/iD?»tD¿±)ê+ÐÏ+úyc€~6Õˆ~QÊ.Yoéo•B¿ºR$?»Ú„¿êÙÏú$öÛr}$ûÅÍA ŸìL´ûU¯É~ѧµ±Ÿ3%ØÏ.7Ù¯ÞMÅ~qéø‡ìgÓ†ìg#Lö³ .ö«^Mö‹éÈ/Èd?a±_œ›H ûÅôã3Šìçåýöü$Kö³±ûÕþêÚ‘ýÂÇJ“ýòNúíG‚лEÿµÈ¯¦ÈOOŸD¿œÂB?ÏEô³4@¿¡“˜FôËnýœL~ž‚ô—%é/{-ü‹^K)þ5Ë£çåE*#þíúö+ü«Ë›ü·ëULüH üWíÿYMà¿Hs°&àžª–ÐjzMÀºxÉœ‰»ÞÍ„•GôwèÈHП •èO€„¿BŸ]mÑ_> Šþòú“þ¬-€?›FIã#÷ÙÀþlÈA5˜¢?KAúË»)é/ÑߨSÚýë‘þÞ¤7ËýÙÅý™…ôWc,ú˧ð¯ýÆšzè³~â_>çRï{×ùÀ¿W[ÈŸÄ›ÌÇ3ꀈïÖ©T¾7!wÇøî=·†¤g§>n ø*Zs_ÆñY˜yvnù1PÈ·æû*‘ïX’ ˆ|û­c(…|Ç&g _¼‹™ÎwŒüHâËs“|g, øŽ'ß® |çûˆ’(€ï<Ý|ç“r/^θ@øBZ[›ÎW¡ã|מnQ¾5Ó|×}h5 ñ]±EŠâ‹4ßu&Q‰øb5dk(ô½ý|ñ™"'¥ïÎïí©ôo’øÞ‹*ÌéÙY)Réò“ð½¯Cél à»·3¡Bß©'š€Ï ¦Ð÷NÉzúL#à 'MÁåúŽ\^ |¦“¥cçJÊNÇÎU¯'Òù2‰p¯äBÉ|é ,•oì\Ç%ò½÷• Q^òH•Ï«›jŸ)y$¾ÑTûò‹„Ô>«‹jß¡ØÜTûÊ=-;óËB:wÊÓ,ž¬Zb_¹ä¥oçþûÊÓTbŸ¥¡Øg¾¦Wÿ,$±¯œö$ö™)ž÷j(žºàûjh$ö™pGµ¯ú)çÎãÉ\”ûö|Kî+9rŸ•B¹ïÐq)÷•˜+¹ïPÈô”ûj´$÷YM”ûJP•âw(o9wæfΜ¶RüÌItïò®¼;ëfâ·+Êm*~5¹¤øÕhIñ«Ï‡Rüæ»é4Pð‹%œÅHðËJüÞÛäìÞoN7~ïZ@Жàwç& 9xÖ(Áï–Sô¾K‡g¤‡géšÒûêž<Pˆ~–‚žoG>NžÕ'‰~ù€L'ÏtòO'ÏüvªŸ¥¡êWcNð«õ8ýäÓϳZLð³ÖHö;ä;–~žVÀÏÆO²_µXŽž¹ üꎞ5i¡ûå£.=k®ÉѳÒü”ægQµöÎiåOê{ïeÝ%ç½´÷Ä[²ä¾¹,í‡><¦¼W§“ööKßV’öž#ÝG)ðíKŠl¤½p(kn×™K—öñ•ï¢öñí¹÷|¯ßø2üt |·öciߥ‘Sß;ŸÌÄm|G¹lRß³í€Ô÷ÞÛum¸gîƒÚÇWoAÄ=Wó€{æS†}|&Ì÷l'…¾rx$î™8–_i‹Ä½Q.¥øNÀž_m“ÀW¬$/×cÑÞûöq»¾gú™öñÝÚT(}¯^pRßS(ÊÔ÷ÊçIú^íâ¾— Aíã+ ú^-›ÜÇ—>oÒ÷ÒO¦ô½|Á‘¾W˱ô=s,}oÒ÷òiRúÞ“¾ŸÒ÷¶ôô$òÕ»Jê{ù ä3%Qú^Ž–¯˜RâË—!_jiÌgÚbŠ|©%¥È—ý$ó•ëF‰|…/ý¶|åÒ˜ ß–ûö$ñåG!I|/y­¬†Àgi$ñ¥$•_ú•IâK*GŸ‰j>sÄė-ðÕKâ3‘ÀW­I‰/5_ —)ñÉC,¾Ò©ð•`"ÞKç¨TøJâïü”_)qkz£ øLâ‘ÆWš¤i|ü¨"¯´Mi|ë¾¦ÒøJOœ_~&N/®Nóît¥_)ÁÒøL®£Æ—^L©ñ™ˆ&‘/•K‰|&àQä«i’"Ÿ>KäËI›"Ÿ¾ø—ÈWB E¾’—$ò•.-‘OßÙSä+AY"_~œ/•/]*_~y/•ïÔ*_u;U>iTùª½ù* 5¾%ñe¯SâË2%¾,… _IºRøL›£ÂgšÚÚûók…¯ÔÅTøª¦Rø„•RøR„N…¯T@)|ù>!…ÏÊùµÄWºåèŠDj|J‘"_© ùLÀ“È—êGŠ|{òE¾C_cKäKe#E¾+éój#Z"ŸÞ‘~Gä+•*E>)¤)ò•Ø%‘/¯L‰|µõN"_ÊRùªWùJ-‚ÈWc,‘/¯oŠ|±J²ßÓoÕùÞ'ÁÒE>k1E>ëU¾*G2ßq¤…2_©d©ó¹Coê|Õbé|Õb }¥üQç«Kç+õU:_Äl¼çUQè‹cÝͳ”^ }U—„>ä¦ÐW’˜„>)ôY }V …¾> }¥gJè‹ðl÷¬çúŽÜk)¡¯¦›„>K¡¯Z#¡OÔ“B_Õ$?OÝ&²vrà„ÃÀƒÑ½rkßU̇`.á[R’_| {îËZ2á„ÀqÊ9S Á‚nßÚ·.ïe•’\ÖÜñÄ­}¡°¬ã­Oª ÏǹóÃ(0‚ÜðuJ[ûž„líó|<°[GY§“ç–Ÿ•¥ù¹¹›x¡ô½}ñD`îíÛó厸ÝÏ'˜‹]žWa ð<2¶Ì„@k !ðØž^¯ýÝɳÈV’ß*áU ï…‚BxµUîí{WP2ð8Í£sûøP’¯'w\qo_~B&Z¯É€çqeô0à»ôÉã4c¹«Qò[5‡Å€×“.‡d@ë8ð)ˆMŒ8½)ð­ún&Š¥äw¤C—4¿Ú3HŒ/{ÛÛwm ýd@SÅ€õ]Y²_Dqn²Ÿâ!Æ 0¿XO¼NIÙDÀ:u,Ð0‘ªß¦×) — ¬=¢À¸P[óòŒÅäŸIÑïÙµOOš_é‚@Àxõ`.æ"­½}¥6íãŒ4¿Ú“š_ ID@“6‰€ö9„xÏe†óÂ%Êç4C¹h¿åä?ÓjÉ·öäþ¢V¦û]#q[ìW$*ö«˜7È%µ[Â_¸slMì«­žd¿{Ñfb¿oîìKñJZ_ɪî%‚þÎeýП}ñ“ÖWᔈd-< î õ¥ÏŠ´¾ÒÆ¥õÕfâŸy?ÿî7—"Äÿ ¯%öÕ–E‰}µ×Tb_}ë$þy]À?s[þ•³™Ä¾ÜjXbŸ¾ï¥ØWÑF2¢KÅfþÕ'ÞòñL,’ØguQì‹ÃQ|{_ ñÑ¥â·ÿjøµ§•+±¯ô—Œè²ò‹Šð/®ÌÓ|ó5¥ÎW›.¥óù~¿»ïHI/Ý RçËû@žEUÚÞWì¨óÙ–@ê|…ÜRªŽä¾X ¯Î}戩í}¹=R:_ÞË©ó™ÊHÏÄÑü¡’ûªWÒùj«¦t>íúùÛúoÿéÿšÓ~Sendstream endobj 6 0 obj 172329 endobj 4 0 obj <> /Contents 5 0 R >> endobj 3 0 obj << /Type /Pages /Kids [ 4 0 R ] /Count 1 >> endobj 1 0 obj <> endobj 7 0 obj <>endobj 9 0 obj <> endobj 10 0 obj <> endobj 8 0 obj <> endobj 11 0 obj <>stream 2020-03-03T12:19:25-06:00 2020-03-03T12:19:25-06:00 GL2PS 1.4.0, (C) 1999-2017 C. Geuzaine gl2ps_renderer figureOctave endstream endobj 2 0 obj <>endobj xref 0 12 0000000000 65535 f 0000172646 00000 n 0000174396 00000 n 0000172587 00000 n 0000172436 00000 n 0000000015 00000 n 0000172414 00000 n 0000172711 00000 n 0000172811 00000 n 0000172752 00000 n 0000172781 00000 n 0000172875 00000 n trailer << /Size 12 /Root 1 0 R /Info 2 0 R /ID [<746C5801E1FAD5E98DDCE5AF05A5C79B><746C5801E1FAD5E98DDCE5AF05A5C79B>] >> startxref 174616 %%EOF blis-0.9.0/docs/graphs/sup/dgemm_rrr_zen_nt1.png000066400000000000000000006731541422157504600216440ustar00rootroot00000000000000‰PNG  IHDRTjûF¦Â &iCCPiccH‰••gP“YÇïó<é…@B‡PC‘*%€”Z(Ò«¨@èPElˆ¸+Šˆ4EE\•"kE ‹‚tƒ,ʺqQAYpß÷?¼ÿ™{ÏoþsæÞsÏùp ˆƒeÁË{bRºÀÛÉŽÌß(ŒŸ–ÂñôtßÕ»­Ä{ºßÏù®‘iü常¼rù)‚t ìeÖÌJOYá£ËLÿÂgWX°\à2ßXáèyìKο,ú’ãëÍ]~ )úÿ†ÿsïŠT8‚ôبÈl¦OrTzV˜ ’™¶Ò —Ëô$GÅ&D~Sðÿ•ü¥Gf§¯DnrÊ&AltL:ó5204_gñÆëK!FÿÏgE_½äzØs û¾zá•tî@úÑWOm¹¯”|:îð3™ÿz¨• €è@(U  t0–À8à|AØø $ȹ`(E`8ª@-hM œà<¸®ƒÛà.L‚—@Þ‚°¢A2¤é@F²† 7È ‚B¡h( Ê€r¡PT UAuPô tºÝ„¡‡Ð84ý }„˜ÓaXÖ‡Ù0v…}áõp4œ çÀùð^¸®‡OÂðø6< á—ð"Â@”]„p$‰BÈV¤)Gê‘V¤éCî!Bdù€Â h(&Je‰rFù¡ø¨TÔVT1ª uÕêEÝC£D¨Ïh2Z­ƒ¶@óÐèhtº]ŽnD·£¯¡‡Ñ“èw †aaÌ0Θ Lf3¦sÓ†¹ŒÄL`æ°X¬ Vk…õÀ†aÓ±ØJìIì%ìvûGÄ)áŒpޏ`\.WŽkÆ]Ä á¦p xq¼:ÞïÀo—àðÝø;øIüA‚À"X| q„„ B+áaŒð†H$ª͉^ÄXâvbññqœøD%i“¸¤Ri/é8é2é!é ™LÖ Û’ƒÉéä½ä&òUòSò{1š˜žO,Bl›XµX‡ØØ+ ž¢NáP6Pr(å”3”;”Yq¼¸†8WJ)Hq¤"¥öHµJ IÍKËIÛJGJJ·IK”aÊ8ÈÄËì—é”y"‹’Õ–õ’Í’="{MvVŽ.g)Ç—+”;-÷H–×–÷–ß,L¾_~NAQÁI!E¡RáªÂ¬"CÑV1N±Lñ¢âŒMÉZ)V©Lé’Ò ¦$“ÃL`V0{™"eyegå å:åå–ŠŸJžJ›ÊU‚*[5JµLµGU¤¦¤æ®–«Ö¢öH¯ÎVQ?¤Þ§>¯ÁÒÐØ­Ñ©1Í’fñX9¬Ö˜&YÓF3U³^ó¾F‹­¯uXë®6¬m¢£]­}GÖ1Õ‰Õ9¬3¸ ½Ê|UÒªúU£º$]Žn¦n‹î¸CÏM/O¯Sš~°þ~ý>ýÏ&   ©†.†y†Ý†iñªî¯&¯v\½mu×êׯ:Æ‘ÆGŒ˜ÐLÜMv›ô˜|253˜¶šÎ˜©™…šÕ˜²élOv1û†9ÚÜÎ|›ùyó¦é§-þ²ÔµŒ·l¶œ^ÃZ¹¦aÍ„•ŠU˜U•Кij}ÔZh£lfSoóÌVÕ6¶ÑvУʼnãœä¼²3°صÛÍs-¸[¸—í{'ûBûªƒŸC•ÃSGÇhÇG‘“‰Óf§ËÎhgWçýΣ<Ÿ×Ĺ˜¹lqéu%¹ú¸V¹>sÓv¸u»Ãî.îÜÇÖª¯MZÛé—ˆÿ2Â6¢,b&Ò*²4r*Ê*ª4j:Ú*ú@ôLŒMLyÌl,7¶*öuœs\mÜ|¼Güñø¥„€„¶D\bhâ¹$jR|Ro²brvò`ŠNJAŠ0Õ"õ`ªHà*hLƒÒÖ§u¥Ó—?Åþ ÍŒ]ã™Ö™Õ™ï³ü³ÎdKd'e÷oÒÞ´gÓTŽcÎO›Q›ù›{r•swäŽoál©Û m ßÚ³Mu[þ¶ÉíNÛOì ìˆßñ[žA^iÞÛ;»óò·çOìrÚÕR V (Ým¹»öÔ±? ìY½§rÏçˆÂ[EEåE‹Åüâ[?þXñãÒÞ¨½%¦%Göaö%íÙo³ÿD©DiNéÄ÷e̲²·7¼Yn\^{ˆp(ã°Â­¢«R­r_åbULÕpµ]u[|ÍžšùÇ‡ŽØi­U¨-ªýx4öèƒ:§ºŽzúòc˜c™Çž7ø7ôýÄþ©©Q¶±¨ñÓñ¤ãÂÞ'z›Ìšššå›KZà–Œ–™“!'ïþlÿsW«nk]£­è8•qêÅ/¡¿Œœv=Ýs†}¦õ¬úÙšvZ{aÔ±©CÔÓ)ì ê<çr®§Û²»ýW½_ŸW>_}AòBÉEÂÅü‹K—r.Í]N¹<{%úÊDÏÆžÇW¯Þïõê¸æzíÆuÇëWû8}—nXÝ8Óâæ¹[ì[·Mowô›ô·ÿfò[û€é@dz;]wÍïv®¼8d3tåžý½ë÷y÷o¯ñy02*|ñ`úaÂÃ×2-<Þ>†+|"þ¤ü©üÓúßµ~oš /ŒÛ÷?óyöx‚?ñò´?'󟓟—O)M5MMŸŸqœ¹ûb݋ɗ)/f þ”ø³æ•櫳ÙþÕ/ M¾¼^ú»øÌ›ãoßöÌyÎ=}—øna¾ð½ÌûØú>|œZÈZÄ.V|ÒúÔýÙõóØRâÒÒ?B,¾“sMT cHRMz&€„ú€èu0ê`:˜pœºQ<bKGDÿÿÿ ½§“ oFFsF×j`` pHYsNNÆÊ/¥tIMEä&>(Ê vpAg´¨“ÁQè€IDATxÚì½{œU™ÿÿ†r!™¤F$‰qL¶†b5Ž¢5+W펫¸…jeÝÅKÖî¯þD—Ýu»×ÙUVW· vÁË*™^YoÜœrÑQÙ©ˆ@ä:eâ“ L% 7a~œ>ÕÕ==3=÷žÉóÎk^é®Ë©SÕõTs>çyžcAAAAAA†äØé®€ ‚ ‚ ‚ ‚ ‚ B½#‚Š ‚ ‚ ‚ ‚ ‚ ˆ "‚ ‚ ‚ ‚ ‚ ‚0"¨‚ ‚ ‚ ‚ ‚ ‚ Œ€*‚ ‚ ‚ ‚ ‚ ‚ # ‚Š ‚ ‚ ‚ ‚ ‚ ˆ "‚ ‚ ‚ ‚ ‚ ‚0G… âº.žçMw5„"aây¾ï»¬ p]wºOI#b›³ƒ ªÚ´ØçÌFìsvS«}ú¾O†Ó]]aˆíΪ½[Gó^Û­?Ä6닉쓂ØçLGì³¾«}J¿tö 69{™-öxT*…BA ±Nð}Ÿææfr¹Éd’T*5®ò‚  P(L÷i cDlsæ“Édhii©jÓbŸ3±ÏÙM-ömmm6Ø$L b»3Ÿ¡Þ­µ¾WÅvë±Íúa¢û¤ ö9Óû¬ÆjŸÒ/]ˆMÎ^f‹=7ÝŽ.’É$étšt:M†´´´P(H$Ó]5AFIär9zzz0M“0 illÄq,Ëšîê ‚0N&b€I„Ñ1Ü»µVÄvax¦³O*ö)Ã3û”~© SͬôP) 477sÌ1ÇJ¥ÊÜiµÚÝØØH&“!“É”Íñ}Ÿd2É1Ç=¸ÚÚÚp]—ÆÆFq]—L&Ccc#ÍÍÍeÊéh¶ ]V¼ÎÃ-¯µ¼ÆÆF<Ïô½Ú6£)s¸óõ<0 I§Ó†AOOOôbêœ|ß~+]æPîaz»Ñî'L ÃÙ&Ì,ûÎëÅ>k=×Zl¥Ú9éßÏ0ŒèÝ€­Fü7Û¬?ÆcŸCÙ&Ô—}ŽÕ6+ëVÍ>'ëÝ9Vû­Åߟú»eYÒ H»wäò†{N—íuN£y·VÚ­^&¶[H»·¶2§º_:RŸt¨sï{U/û¬ކvïHëj)sªÛ½cµOé—Î|¤=;ry3©={TŒãÌ2zzz€l6;0000N§€t:=Ð××7`Æ@GGÇ@__߀ã8À@ggçÀÀÀ@´^ïÛÙÙ9`FTf:Èf³ƒŽaÛvT‡Ñl;À€ã8}}}ÝÝ݆a tvv¹¼–òlÛèììèëëô½Ú6µ”YËùæóùÛ¶£ÿ‰DY‡:§ÊóÕ¿‹^§ËwgÀ²¬¨ÎÃí'L=ÃÙæÀÀÀŒ³Ïál°^ì³Ös­ÅV†:'Çq‰Ä@>ŸH$e×o(ûÛ¬?ÆcŸÃÙæÀÀèln²ís¬¶©ËÎ>'ëÝ9VûÌårÃî7Üû³»»{À4;¾¾èœ„úDÚ½#—7Ò{tºlw¸sêÝ:œÝ ˆíÖÒî­ß~éH}Ò¡Îi<ïÕ±Ïzâhi÷Ž´n¤2§£Ý;Vû”~éÌFÚ³#—7ÓÚ³GÃ8î¬TÒéô€ã8eËLÓH§ÓÙl¶ÌôM§˜|>?`YVÙ¾ŽãDƬÑ?pü{¥!ÖºíHeÆ  d¨åµ”§_öÕ¾µl¤2k9_}õKQ7>ª“6 j¿³.ßqœÃ0Êön?aêÎ6fœ}gƒõbŸµžk-¶2Ô9¥Óéèw4M³lŸ¡ìSl³þ}g›£³¹É¶Ï±Ú¦.s8ûœ¬wçXí3—Ë »ßPöÙ××7`šæ@ww÷¨¯‘0õH»wäòFzN—íwNC½[‡k÷ŠíÖÒî­ß~éH}Ò¡Îi¬ïUýûŠ}ÖGK»w¤u#•9íÞ±Ú§ôKg6Òž¹¼™Öž=Æqg]È/ß÷#7?iš€r¡»×Vn¾ïsÌ1ÇDõàZTYÏ‘–„¾C}jÙD`š&ضM6›Åqœ²k<Ô9UºE†Aeîl•Éý†ÛO˜Z†³M˜™ö9œ Î4û¬ÅV*Ïé¶Ûn£P(ÐÝÝM6›¥§§ß÷ÉårÑ6CÙ§Øf}1û¬GÛ¬¬c-Ëka$ûœ¬wçXì³–ýªÙg.—ò,Â0ŒÂ.ø¾/Ésëi÷ŽL-ïÑé²Ýjçäºî°ïÖ¡Þ«b»õ…´{kcºÚ½#õI‡:§±¼WAì³Þ8šÚ½#­Žéj÷ŽÅ>¥_:³‘öìÈÌ´öìHû͆qÜY—”~¤x¤Ãý†a`Û6ƒÖÅÄÂØ°m{P,¿Z&•¿[<ž¢eYäóyLÓ$•JÑÝÝ•;Ü~ÂÔRK¬`±Ïéc,¶²k×.LÓ,³cÛ¶G´Ï±O˜<ÆcŸÃÙ¦01ŒÕ^FÚo(û Ã0z®A@¡PÔ™êi÷Ö7c±Ý †}·×îÛ­¤Ý[¿LVŸÄ>g Òî­_ÆjŸÒ/ÙH{¶¾™Œ¾èlÇu*¦iâºntÁ}ßȉD"š zP'‰²™"aÒÜÜ\–dL;–eEê1¨ë[(jRQƒ ˆ~/½ŸmÛ@é›N§1M³ì¡9Ü~ÂÔ2œm‚Øçt3[9å”S‚ úÍô~ñ†ìPö)¶Y_ŒÇ>Å6'Ÿ±ÚËHûU³Ïl6KgggôgYÙl–l6;Ý—A¨‚´{뛱خn/õnê½*¶[_H»·~™¬>)ˆ}ΤÝ[¿ŒÕ>¥_:³‘öl}3}ÑÙ0Ž;ëW­Z%¶YgŒÇ>Å6'Ÿ±ÚËhö‹¿?e¶ìÌAÚ½õÍXlWT{·×î»­/¤Ý[¿LFŸ´bŸõ‹´{ë—±Ú§ôKg6Òž­o&º/:[Æq)&‘™uø¾¹ÐÆÝlµëP†Ø¶Í1ÇC__ß ¸˜A`†4~&Ñ^_ÏóÈårtvvâyÞ¤ï'L.ÕlÄ>§“ñÚÊTÙ´0ùŒÇ>Å6'y µ íÞúcªß­B}"íÞúEÚ¯‚´{ë—±^_±ë™´gë©î‹Î$›œu*šj< CÚÚÚèèèÀ²,2™ ¶mWM~4YÉ|4A ›(ɶíQ»4Mt™“QGßõ«›W=º‡­ õ0œÍö9ì=¾ßh™›&‡ñØçL´Í™T¦Þo,ˆÍ~¤Ý;þ2'Ënõ¾£e*~aò‘vïøË›¬2¥ý*H»·~Ëëõ»žÙH{vüeÖ[{v:ö›*f­ R Ó4ÉçóQl6Ó4éè蘖ºèÄIÃÕuºËœŒ:Ž…±*’õ¬d ƒ™ÍöYïö>Õ¶"¶9ó¨û¬w[šŒ2å(Œ•z±[¨;›¬òÄ…¡˜Íö9ì}¬×Ilúè ^ìs¦ØR=ØçX»®êÅafØO½´g†>ì¬ ù%‚ ‚ ‚ ‚ ‚ ‚0Q;ÝAAAAAA¨wDPAAAAAATAAAAAAF@AAAAAA„AEAAAAAaDPAAAAAA㦻ãåì³ÏfýúõÓ]!Ù³gË–-›îj ÉÁƒ9xð K—.îª I½_Ã;vpÕUWñçþçÓ]•ºâ3Ÿù žç±jÕªé®ÊÔû½µwï^æÏŸÏüùó§»*U™ ÏmÛ¶qï½÷Nw5êŽ×½îuum›3áÞ’çÇøØ·oÜxãÓ]•º£ÞÛ¶µRï÷àh¨w{¯•ZiÛVç›ßü&7ÜpC]¿?kåh»§gµþ&Ò¶­N½·mke&´ke¶ú(ïxÇ;øË¿üË +sÆ *ëׯ禛nšîj ɦM›êº~]]]tuu±yóæé®ÊÔû5looŸ·‰æµ¯}-ǼÜ[ã ½½ÖÖVZ[[§»*U™)Ïa0«V­ªë{¦Ü[õ| gÊóCL½·mk¥ÞïÁÑPïö^+µþ&Ò¶­ÎªU«¸ä’KêúÝT+GÛ==¨õ7‘¶muê½m[+3¡ \+³å9Sëo"mÛ¡9þøãëú^¨÷wÉLx.Ô»½'“IæÍ›7¡eÎxA¥Þ©ç`Æ 455Mw5†¥Þ¯¡0s©÷{kãÆ,Y²dº«1$3áù!ÌLf½%ÏAžÙtÖ»½×ÊlúM„ñ!÷tý1[~a|Ì„6p­Ì–{z6ý&ÓE½OÒ¨÷wÉL¸ëÝÞ×­[ÇêÕ«'´LT&™zÙÐÐÐ@CCÃtWcXêý 3—z¿·êý¥9žÂÌd&Ü[òü„á™M÷`½Û{­Ì¦ßDrO׳å7ÆÇLh×Êl¹§gÓo2],Z´hº«0,õþ.™ ÷`½ÛûâÅ‹Y¸pá„–)IéAAAAAAF@AAAAAA„AEA˜v¼Ø_8Ý•AAAá¨'ÂpäQ ×u§»ªÂ"9TA˜5„aH†˜¦Yu}¡PÀ÷} Èþ×/HÃ0ðétzºOqÊðƒêâFåroˆ2L (~öcŸ­bAñÏ,þÅõ)ÀÜX9vñ˜i W\î…âÿ‚ ‚ ‚ ‚ G&“Á¶mÇ)[îû>Éd’îînÂ0$•JEãGc!‚h_×u1M۶˶ ÃB¡Õ%—Ë8N†!A`YVô]…ÍD ¨1"5>¥ñ)·Òê³Où˜ÔD#‚Š ³†L&CtvvFË …¾ïê1ª_$‰D"N<ÏÃ4Í2áD ,žçáyabYÖ Z=òå{ïåÔãgÕgðß[·ÒÓ×Çýsç²jÕ*vïÞÍk_ñ v-X€_Ü~¨W©zUâ£D‘øvVÅ6ê§›N¬,õÂêJ¶îÜÉ7ŽáÓ;w²âÀv-XÀO–-cÿqÇñÒ+8ý¿`ËÊ•¬zê)¼sÏŽi›¦|AAAAŽ^|ßÇó¼Hð}?4₃^îº.A`¶mãû~$¤˜¦‰çyј‘išA€ç©)¨Õ™øñ“É$Ùl˲ÈårÑþzìʲ,\×%—ËaÛ6AÉdÊÆ®‰D4®U(Èf³xžÇ-=Ægßþv|ßÇ5M5æäG{ÑôŒXGIµ¨€ùò-ð³|vþtxðõ¿W˼­ðw¿ƒ»às› 4À¿~Õ¯ù8u=þÞ+à÷xÝŸÂÏÿÌ?@`ÀœÏƒ÷V0þþ*À üKgÀ;Œc Øɵ¯£•ƒzÿˆ "ÂŒ& CÚÚÚ"•Ý0 r¹®ëF^&étÛ¶‰!µˆ#z›\.‡ïûS&¨è—³aÑKÛ÷}v<Èî•+Ù±f »W®díý÷óûx²©‰C=ļuëx~Õ*žþyîÚÅÚ?üùóçsú‘#ìó<víâ®C‡ø» . Ku1EÛ²¬ÈëDz¬²ADרqr¹\t½ à (HX^ñE÷J$A@®8SB—©×‡aH"‘à§±™/*þýUüwÛ¾] fü ¶mó—_Ì/.¸€N ß×Ç-"H$¦ä÷AAAaú‰3ÄÉd2†A:¦P(D“gHÄÐ^&Z1 #û°, ß÷Éår†AGGA¶m“Édxaõj^ûŠWð“ï|'§rÏó"ï-´`YÓØHüÍg>Þ—¾”“¿ÿ}ù>_ýÁøÛo~ŸÕq%…ûi=í4>þ­oñÙÿ/‡Ÿ:Ìé×fûwþš×}øL^úõ¯ó;îà‰þÓ™óƒäæÿ˜kž˜Ïš×¿žçwüø×ßfñ[²˜§üûc0ßçí`ôBîgp¨–.‚`-ïÿ`ûCðŽã`á› 8Áv¸þaøj#K>à!È|²[!x-ÖÃ*¶¹pë æÏÃÓ«áð6h~Â9`ý`ß™<Âyà4Ã#?†ï—Îktþüy'³zîã÷ê²ýÉÀ^æS>Ö=°ô`ýÏB~Üð-øÖN8îÿ½èÐ{LAf$AJ¥ð<|>ã8‘ŠëºtvvFƒøcu¹Œ9¦Ói2™L4SÁ0ŒHù×ËôqõK2‘H†a$м°z5ß»þzô£˜–ÅŽ;˜?>»wïæàÁƒwÊ)·z5ýýý<÷Æ7²|çNŽlØÀÂ… 1ƒ€æ9sø³înî?÷\N™;—7­\ 矯ê¯øŠeç†!ÍÍÍ$˲"¡D{éhCÏŠÐèqQI #ÍÍͤÓi àP(D ß÷1 ƒžžž²ãëåÚåt¼¿ ¨ÆÏßøþG?J¡xíƒ `éYgÁ%—Là'‚ ‚ ‚ B½ÒÜÜÌÀÀ@Ù8‘Ž^’N§#1EG.éè舼F …B4Áµ%™äù;ïä³ÿ8–mó_·ßŽkY<ÐÚŠmÛx¨ˆöÀ¯{ê).|ßûø§ÆF:?ö1.øÊ¯9ýgÿ†ïû|.ûw‡{x.岿ç¿Â¹9‹½x€ÿðÍüp>ë:Âq/}1÷-[ÆÁ`ë𯸂—ì>Èî#óùÃ#°uõ+øÎ«áŒSžç¾ s  .Î~÷–©SÙ»þäþ­¼÷0–¶ý°h?ÜùoÁ~ >˜y€Ó §ñW)Hž Áj°ÿü l€—^Þvààß·½Ö6«(#‰s`à‚§HþøDÌ>…ùŸ„\'¤ï…ÎàŸ{Žm¿>ŒõŠ¥d¿æéPøt '=ô.œŸ™&ð¾sŸmžçBb.x¤ONS¿çŽ=À?3€qÁéÑo¼ýX{ì3,2eÛðW0÷Åý¤ßÙ¨±§«ÞdoþôÇlžÐ{L•ÑñÿC tSòr )…˜aj( X–UÞK 'Ùl6Z6Q±!-ËÂó¼È3#‘HÍf£p[[ ^È^ö2– ˜¦É7½ÿýÀ–Ççàk^þ׼††çŸgÁ®]œô–·ð'}}<þƒ°aÝ:Ž<òo9ë,Î:ë¬(ŒVäQyòɥʜq†úÿ´ÓF}†aÐ×× @ŽãÐÑÑ1æk¿Þµ2¼|ªÅ ‚€}ìc~,AAAAê=©U{©´µµE?LÓ$‘HÐÒÒ¨I¢ÓH$8üóŸ“?þxþî‹_äYàøO~’Ä{ß‹}â‰dï’KxHù>)À‚caï1ÇpßÇ?Îc,ÿÌç¸cœÞ”åÔä³|ä¬hzàåô><‡s/äo^ Æ ÇðÌ¡3xêVŸ9À¾9ÇÒy5|ñWð³$¤ChÍǘ ßú$ìþ$¤ÿðòÀq„\z.Ù¹`Ý~/dö‚ñ°{<öãÇÈÏscé$,h ?Âùßé䤯ÿ¬¾Ö»áŒ{îäÈï›éH­Á| X ¯é;À;w<Á­Ÿ»šîâØÛ OGÛÝÏ`¹£8QÖ&·þæÚŸ¾ëì,üðŽô½—ìRpç¹x¿ùŸžÃ/ùZæ´_ÂïÞö6.>ÿnºé&ž{®7÷m\×eÞ¼y46ú,XpÝ]×qÓM7±aÃöìù4޳ŸG9d2É›ßüwÀZ®½öfÀåþûïçë_ˆ}ûšxÉKþ‚ãŽû1û÷ïç=ïé" ×ñ§ßúSz’=µÜ>5#‚ÊäPIn ”BÃe¶âr§¸*‚0Ùèð^¶mãyÞ¸D€±ÐÓÓƒa|ÿàAV¬XA%¨¶%ÁZW\ANë\àÅuÚ#,-44€Ž¥yÞyƒŽ9~ßš¡©m6aš&‹/žîj‚ ‚ ‚ ‚0I艮:Š(‰C¯ Ã0O|Ê›{Å?ãU¯Â.¹é&r¨ñ›Óæœ@ ðŽ€¹œm?o)æ!r*qXß…Ìç¡cÐvœý7û"á 8÷À÷žžÃÊ/·CúH¬€ÏwÃýsáÿ[~ öË€nðþ –î¬C4àì/‚O< ï9•(Ózꙹ\ ¤O†ðE!Öi ®½íA.Ü}†ÍcÀÉ'D51yçÎø»áøBÏÃz“<þøæîxsHæTh´­[ÿ‚îîÿîá»ßý.]]]ôõeÙyÝ>¾ÿÿã·¿ý-¯yÍ5,[vsæÌá±Çã”SN¡·÷bŽ9f/ýèíÜ#GŽðÄ+xÓ›ÞÍ­·~ Ïóxá…ÇY¼xßþö·yÝë^ÇÏ~ö3~õ«},Yò4?ûYž+¯¼’•+WòŠW¼˜›o>Ä™gžÉÚµkùÈG> '¼ƒ½{·2gÎ~‚ àî»ï礓Ö®}ŽíÛçrúé§sà ?¤¡áqüþ4öïß?¡÷ܱÓ}Ó×#.J0 PÞ(š,ÐQòD÷/…é®° ¸®KKKKô‚´,«j(/-rh‚šPÂG ¥Ô 5¥ÿL“Ãà§+VD«N~ÞYüËÿïAy²e‹ëm”ÀR-» ‚ ‚ ‚ ÌF‚ ˆòTÄ—¹®}×âADa—t>O½¡P ™L*Ëó¼hßʲÃ0, e­Ã]Çÿ×ÇŽ—å·¨¨_å±Aå ¦ß÷I¥RQ>“D"å*I§Óôôô°òoÿ6òHÒÄyPc@mÅÿýêsî»!ñsÈÍ¿]¿²ÿ æ.è|ä³øt^ v Xó 3<¢›üÃm‚¯.ûH/€ôÙ`6Á†µpRö"TN |â;`Bh«{ζáa¿ècªsnh¸…5[·’ÉdŠ!ÍÀ÷açÎyÑ=üå/ßÂÖ­Ü}w/®ëräÈ~ó›ƒÑu»à‚ X¼x1m<ûìñ¸®ËË_þrn½õVV¯~ ð|€/|á „aÈ’%ÿÈâÅw²iÓ&:;;¹ÿþ»9pà{üË¿|›“O>™††ºº®ã-oùßüæ?†!Ï<ó ýýkH$àê«ÿƒOúÓ¼ë]ïbýú?cÞ¼yœsÎEÜpà œtÒI:ô»v-àóŸÿ<ï~÷»ñ·n”B¬'‹ÿýÀ~•DÝØ­¾ ‚ÏCþJ°²ÀIù-ôüX ìúÀ=òD³î­,<Ö¿x•Z¶ëž]l½ýXnÎ.‹êP9Ì5oÞ:þøÇ#xžG.—#›ÍR(Xlذ›d2Igg'a²xñk9çœ#<ù¤E¡PàW¿º‘¹sßÎÍ7Ž÷½ï …­­Åï~÷¿ûÝq¤Óiþú¯ÿšïÿûìÜy)¶ ¯zàÒ—]Æ¿îz#}»~Ë“wÜÁÝÏ<Ãå—_ÎsÏÁ‡>”Â0®¾újvìØÁë_ÿÜ~ûqÉ%¹ð ±í<ûö½ˆ7¿ÙâX@&>úúúò½ï‡iš\tÑL<,ëãäóoâ _ØÀ¹ç¾œë¯ßÈŠð?ÿó?\|ñq,^¼˜DÂÁóÀ¶;ñü<¼aâî;T*Q†ÔMiVëÏqáÄ 4k¡bA˜xÂ0$“ÉÍf‰)ÚFu£n”mº¨wX¾ø=‰T´}ûÿë9 &Ê»$në‚ ‚ ‚ ‚01¸®Í¢%`†ya†A:ŽŠ5z ß0Œh-:há@‹---Qh£L&ƒmÛQ^P |Ö! ljúÛ¶m“Ëåp§LÐÈçó‘G6©X?Çqp]Û¶£óŠ =:EeŸ~8i¨\Z¬i{}L]—¡Ž3Zô9‡a]·7¼á "¨L:—n\ÜÒb`:ŽîçÏ?÷\Yh/=þS 4¡Öì‡ 0ÁŸoÿ5à¿ìÁ9þrøçëÀJ£—zÀ xØi¢°(«V=œ 0Us\zàç?ç±ßØQ½•­‘=Z–Eÿ!~ù˹|ùˉD‚\.Gdyüñ·qà ùèY±ÿ…|êSÿÇI'Èçó\yåc¼ãÏpÊ)çcYkH¥R\~ùó¬[·‚÷¿ÿÛ<ðÀç8ýôÓéê:ÌÁƒ p‡ç>õ)þûŒ3xì' \ŽÏÞ?¤Ó„é,É$¤þ¼ŸüsæÎ¾‰çd2ð’—\ƒŽoš†íí°cX–:÷׿þOxúéž·€0„ø%…¡\,k›77°y3 ˼÷½ÊÇóÔ2Û•¾e¾¯–A†ù<|õ«·×ày°wïVžyæC€ªZZ ¯<ômž=õÔ ½EPA•4£ì _\nÄÖÇí@«õ&¥¼*£T´Šíº.ÙlvÂì‚0›ð}Ÿd2‰ã8ƒr}P!¹($Þœr,„´QÌwB)T—ƒx˜ ‚ ‚ ‚ cG{Žè\ z _ÿ¯—ë0TŽã`YÉdÃ0pœRïµ»»› ( Q¸"- Ä½%4ù|¾jâBE¼üxÈ£tz¨8 ™k³ryü{¥ Ñ=Ô˜×XÆÂª‰)#•=‘cn2~7}üÝÃsÝI'aš&wÝ{/÷Ýw ʱûá… (Þ÷)€CÀ¼R¤¡t¼„Ê{®‚ü”`ýî?Nÿ#ð{T>“œÔÇ Ë}nñ@&Ñ Ò®] ð}U(á ×UÒiŒíÇò‰Ý|€g/½”ÖL~ð$N:ɼ¼ÞýîüÏÿœC2™$ŸÏcY?úÑ^úÒ;H$–ÑÜÜÌ+_ùÿèïŸÃüùó#aï÷¿?À9ç,åÖ[ßΜ9êyò¡¤±ñyž{îr9Ø»7É[ߺŽuëÀXº”k>ýi¾ÿ3xÍ¥o'8³ óß>J€Õ¼Ïë¡mîÑçþ†Æ¹ü)RŸ8‘ÔE;眈uþ 8¤mîÛûÓ‹1^²€Ï~>ïz$“à\º“\n¥FÂînƒBA]}½, R)µÌ4Õ_"mmJÉf‹¿Q…ù½æ5ßç½ï½š>Ö¬Y-7M%¦Yù$\|ò„Þ‹G½ â¡Fç òUd·Ñ¿—ŽË—H$¢ÐBñ´ØAÐÒÒ‚mÛÑ‹Q?lÛÚÚ"×Êø  PPþ`ñ‡²v“´,+š¡?Ô‹2~ì0 ÇõpÇ„4 cØ„ÕÚ-4žÔiªˆÏt¨Ä÷} …B¤ìÖú²ê-8Æ}q¯”Jo’¡Ð6*≠‚ ‚ ‚0^≯õ˜ŽmÛ‘áû>ŽãD†aÐÓÓS6>¡Ç+*Ç,,Ë4®3ÔøÇPÈ ¿0Ùyé¥Ü²u+ÿѲû¯þŠS¯¹†Ë~þsr¹\dG:ƒŽ6äÌç^(œæH,„l à>°Š³ës9`?\FÍÊ5Ô`> †‹ƒK•©t‚ à%'÷„á/8ÿ‹_„Ó?œOç¿|›%ëp6ðèvpóÁp±ïs¿ÈKx€×^õ4½O>Ľ¯ÛÀÛ_ûZÖ^|1Açw¿ÛÇ>”À4MÞóž/ð²—½“ÆÆF|zòy¼­,ùí}ÜõðíØöÇ!“aÓé Âó1Áý7€¹ÌŸ?Ÿ¾þuåõñq1ëÖmWÞ=Ý<ºx1磄 ¯k!^×B ƒ0ùüR̈uù"B3‚}ñ\ò?¹•Äüïá÷žD.ÌaÎíÅö’`Y$æfï&uÉ z@¡@º»S&•R¿ËïÄ_v ŽST§<ì#ÿFpâ» ¼P¹³¸.Ư˜Ûþ¢’šê/ ¹òñǹñä›ð<‡ÿyó1± ¥ªk￟ãN;mBïET(‰&ÃåX%|ÄíÙe…!ýsæÐòº×E/MSR»£yžŶԡ‹´XÒÖÖF¡P §§‡0 #A@»zê—o:.{‰j/dKÇ€ìîîÆ÷ýè¢*º.Q Á¢°£Ëp]·l{3î"™ËåÊÜ4õ9577ê¥Ï竺qêýâ®»nthD'!K$„aÅ®Ô1.Ã0ŒÜù´«Ÿ¾v¾ïGñs¹\t¾Ú-Ó÷}2™LT]†nèèÆ‹e©„®ëÒÑÑ1¤¸ô­o}‹Ó&Ø0vtB-Ã0Ê„D%€VóJRAAA„Ñ ólÜxã<½e ét:ëåý¡óè°Xq†›¤:Z‘DŽvúúúxì±Çh6MZ.»Œùóçã_vÅv—ÒnÙĹÜËÁü1XÐùvÀ€ð0×€•@…,2 ræ2P1åžž>^ô¢9À’¨¶]Ì{RtIéê:„±k'÷k¾P(ðª;î€Ó?‚iBÃÞc¸uÍÎÎ^°‹[žÆÆf’{÷ò•¿ú+þxßýÜ<–¿ó+Üòîwó×aH²eDÇ{÷»ßM×ßÜůŸOKË2úÞ}ÆWîÁ:ïCܳðC´4‡ä=Dxà‡$þÏ"mßOê¢íþ—eÖ«1 åññ‰oç¶ÛVrùålŸÃ×ÿø^þ/¥´ ÇQD.§t ×…lv®«–Y„á²w^\ŽØ&.Rñ·lèÓ7MUH:]JÓѹö±Àÿå è9’Ja$Xw}6_{bî·1<«b¬iA%“Qª–ïsÛË_NºX–ÛOêUq¾@lñy¼ì‰'&ü^œA¥··—ÞÞ^Z[[«®kjj¢©©iÒê¡”û$ÏЮ6J”tPƒ¼ñ$U–e‘ö}r…üÙŸñ×¶¹bŠÊÓ£££cHO‰D" 5©T*Š©Ó4Éårär9lÛŽ’‰i¡E‹$Úe4™LFÂN\éîî&™LL&Ëu,È|>_–tO‹)”<Æáh¢ìS„êÔCÛV„ÁÈ»Sê—z´Ï0Âëvïfçºu<øÜsøÞ÷Ø»w/$|æ‚ È]}5–eÑÝÝ-Ñ0„YK½¶mç-_ÎÖÆF¿å-„K—b ÆŠLˆbj†^ðVBx,˜÷Bß•fÀúfq‡,ø àÝÖ…@*_‡¡Šá9pà×_?‡›o^¢VA`þp+Ïü¯bÑáÃì¿û~~5°‘_ã?IÑ̶—¿œÂž˜{`Þß'àzßܰÆÞßrúéÃü?œg|ä¿vò¯Ÿjä5×|šå¯~9‰ž•æÁy+踦…0£p çôßÇ[…ã,#~ãìûH\µŒï¿z!¹¿I=t34ÌS)\,‹üû dæ¿x5(ñ'•âÂ.Ž?ûÙ:~uǼÃRŠÖxu4@í‰cÛj½ïC™F¬w0ŒŠE'¦RÅH§±+îéÓÓSuÿDµÄƱðn R)‚B¡Þ+¯D” ( 8ÀO.¹„Ö ·rA¥½½-[¶°aÃz{{ihhàæ›o¦¡¡-[¶ÐÞÞΆ xðÁÙ¼y37nœ”zx(Cƒ‘g¯w7üÓ?a“L& Âk‘ãÕ¯~5ÙW¿ºl?ër¤—¬.S{WÄãþÅ=AÚÚÚ"!Ç4ͪ"Ž·7Ô,=@íû>=ÕnÖúC­«D{uh¡A£=F´P”H$¢ÏñrÇÁqœ²XŸñPbq±G‹:)›iše‚‰¦–Pd‰D¢,¤Tå>:Ñ•>§|>_Vïööö1Î6)³Oí™ÿMDLŽvêÅ>AL½´mA(GÞ‚P¿Ô›}f(… úÍÁƒ8·Ý†ÿ×ÍëÉ«ÀšÆF:UvdA˜µÔKÛÖ§”Ôøß!Ë‚®.î>÷Ü(}IXü € h„ÄVÈ5AççÁü= 0>V,ëfÔ¬y‚ /­V†òèïïgþüêK.¾OÁëdÙC»8íøãY亼üÁ›xãKÿÈ/O|äÏçÃþ0K{»ÙäËþ’Ž[®Äu]^xá­œsÎ/~{4Æùüó/`¶ºººX²dIäJ¶~ýzÖ¯_OWWׄ×CçMÉR>@«CiEÛ=PtBø¸aÛvY^ æ£WG‡¸ªæe1‘èðX“M\P.üLÀ²¬²0_³‘ál˜ûô|‹~€çÖ­ãïáë.eáñ°öœ_óá/|Ð4¹ñÆ9päwÝu·Üro4vøž÷Æ4Õñ-K©¯~õ9ùäáºjy(ïŽ%€ "Ÿ/…á%jèœ(Ãašå9ÚN9å–.íÃ0à“Ÿ|€¥KGž¼/¯‹Óñ¬žRA¥µµ•›nº)úÞßßÏwÞISSÛ¶m¤h.Y²$ŠÙ7{öìuÈ%Ÿêƒ³:ì(q%•JÑÙÙIwwwÙ@ºmÛƒÜ<Ç+¨èðZµzgŒç8žçMêqt²y€ÆÆÆI!´Ð1™Ä ³ò\ÚÛÛ¹÷Þ{'õøSÁp¶ ŒÙ>ï½÷^¶lÙRStÝp Pù‹*…OA¨…ÞÞ^ÚÛÛU¼ãÎdØçÞ½{ioo—#aZèêê¢P(°ÿþé®Ê¸©—¶­ LÒ¶¸¶­ L$ºm»gÏžé®Ê¸™î¶m†’WJ7I¥hiiÁ÷ý(¬g.µÐÕÕÅž={¤m;ºm;ÒvÑîè`çòå¼aÎõå¹a¡¢u…€ó°|õ%<Ö—Š;¥\æq¶nÝËÎ;‹ÛJa­ÜMbέê{¡ÀóÏ?ÏO¯f±òøë^G>Ÿ§õí`Us#_ýê«1Mß÷yÝë>CKK#¯yÍŸqï½—pë­q 'É(ßWÊe—À?ÿó\::”P¢‡4µðR ”4"Åœì#R™íaÅŠùÌŸ`Ì¿E½‘N§£gw5¶lÙ2)mÛ)TâÜyç‘kØÆ£Ùqjq;ᄪ&0Š øÃ0J6®…€L&CgggÍ/Ò:èª×3–P~2¡±,‹|¥ÏÙ¡…›árÆL6­­­¬\¹rZŽ=YTÚ&0fû\¹r%6l¨ùØq[ÓÜ‘Âò B5ôÌ™ùóçOwU&”‰²ÏùóçKXaÚhjjbýúõÌ›7oº«2¡LWÛV&iÛÏhÛ¶‚0Qè¶í 'œ0ÝU™P¦²mëÍÅÏ€—ÉÉd‹¡½:;;Å#EMMMœp Ҷݶ]²dɍޝµ˲x÷‡>ÀòåËbn•°¬»Ôvé¿ç^”Ú¢Évoà‚S~G£N­àûà8˜g4À]wq×[ßÊS ìøÖ·¸äÒ+<È`zÛ¶‚0ÑHÛvâÚ¶‚0‘HÛv|mÛâ+ ÿ…B!Š"ã¡©©‰‡zˆã?~º«2!ÔSÛöç{öðÈ¿ü ÖòåèiÔvñ¬^°{Á Áx¿Z†]ÌC# +Îû>_ùÁ|òuÐÒÂ}'žÈš·¿ÿøò9¸è#\tì;˜óú>‹/ç{ß{Žÿw Ó4yÃ>Àý÷ŸÄ}÷ÍaͰ,›?ùuÌ\î<>ô¡’7Šm—'v¯¬—a ^fšµ *ÙìØs¯ŸsΓÕõœ¦ êSÅúõë'EP™r•÷¼ç=455áy^™A­_¿~û×¾}û&tö¬GQÅŒ-Ëd2 zzzH§ÓQBìÉòª˜nÇ¡³³sÒ & ÃIÅ¥–='ž¸×ÄlvûÊ6ajìS{N(7liÖ B‰é¶OA†f:Û¶‚ ¼;¡~™Jû QýËhp]7¯A(§žÚ¶ÏÌËžÓNÃEå’O|:¶—Ö§¯ûß¡óG”åb¨6iÛ¨¼(¾--˜/z%+ìÛfÛüùÜýÌ3ìß¿Ÿç_²€¤ëâyaÒÛ{.ç·×UIY6nÜÈ©§žŠa(‘¦­M†*Šã(¯“±æ±íÚBygîúêÕOüu”1¥*[¶l¡¿¿Ÿ‹.º¨læSSS­­­Q’£ÖÖV¶mÛFoo/_|ñ¸ÿ|”·—¾ŸÃ0¤P(H$0 #Š}7•ÞSaS" èði“},=?›…Ž©`8Ûœlûe‹Ú“É%Ê&ÓoŸ‚ ÍtµmAyw Bý2Õö™Ae‹ß=ÏÃó¼AyqA¨¯¶íöíÛU^šÆFBŠáàVÿø` Ø`]¬%lT2‚€RÆwÓä¸îVžy{S)nv¬'žà o¸ÿüÏÆóÞ@†|ãw0w®Ã£ÞÉm·ô®èaãD1á½ç©ãê¹ëãIÞnYÞ4B]2¥‚Joo/½½½lÚ´©lùUW]ÅæÍ›Ù¼y3×\s 6làÁdóæÍ444Œû¸9”˜ ’ލ—h$ ²YõjÕº³ÝÝi*˜*Cg²g•L…·Ít2’m“fŸmmm8Žƒ‡ò$ëžî "uÄtÛ§ C3]m[A†GÞ‚P¿L¥}ú¨þej2fss3¦iŠgŠ A=µmŸX¶Œƒ«WsÂáÃ<«Ã©é¡9Èå,ó‹¢`j©?ß+åL±, “Á0l°˜LÅq ‘ éÂ/ñõß¼„¥KÉf³ þíß.à´Ó^…a4’NÜ|ó<ü0lÝz>§Ÿ~¿ûòF±,r JH¥ÇÈXYVm!¿ÆÃl㜠¦TPÑÆ77n¤µµ•ÞÞÞhvÂD¢f½ëW¦ëº …A¡½‰Ä¤åü8Ú˜ìP\Sy˲¦ì|¦ƒ‘l&Ï>}ßÇ4MÇ¡ÒÌ!AÓiŸ‚ Ït¶mAyw Bý2•ö™¤JÚu]²Ù¬ŒùÂ0LWÛÖ/þ9±ï zˆƒgÅkÿð-X ï/®°(…÷ Á?P½Ìhϲ¯ù*öi§ÁñEÛ7 ¾´o#ahR(¸A€mÛtv¦±±‘\,XÀÿw3oz„áY„!$“Ê¥ÒÁ-[e «^騶å/ ³:JÓd2åIéGb2³*ùXü^ö}? óG’Mz |2™*O˜t:M.—›’cÕ3“aŸ…BÛ¶ñŠßÅ?LƆ  B}"¶)õ‹Ø§ Ô/ãµÏªo©G tî\A˜ Ö®];ÝU˜2&ãÝR¦‘8@ãÖ­,jläo*®0QÞ) JáMÚÊË2MÈ¿áV¬g^©o@6‹·+À<;ä[»_Ìÿe2d³Y8ÀÙg_Í+_ù1lû<ÏcûöFø‹¿Xi*±Ä+XårJL©W±¤V<Ï‹¼õD`u'¨L!¥—h†¸®͈—ð^“‡Vx'“lvjülÛ–{e’ð}Ÿt:MåE&‚ ‚ ‚ ã!ß÷%ïª0©HÈÈñ£½UæÎ嬳Îâ­€UÌ™‚…2n“(Q–çM wô“»ë Ìw.ÀÖÉMR)üž¥üôÀ >]Ûklldݺkyç;ãË_^i:œu–KÒi•nŶ!“)y Ì–aÁîîny&Ž“c§»SA<2œïûd2,Ë"‘HLwÕf-³=D–0qø¾_|óÍ’w“ ‚ ‚ ‚0M„¨q ÐuI&“QTAê÷à™gžà¸ã”€jö­©CàmDÅ+ê¾_L8_üþè>Š^–…ÎÇ–bYðÎ÷¿Ÿ\.‡çy8p€_þò—<ôÐy<ùdɤJ2ŸH¨Ýt†ˆÙ˜nIÄ”ñsTx¨T†úrGbÄMžç‘N‹Ï04A`Y9Ä;EAAA?:Ü—çyø¾OtV&=¡®ÐS²}ôQ8ë,NÙ¿ 0o~¢60WR6ÐkÛ±|)¹ÆÂóxÑÂS`Å åjbüë¿ä¶Ûvóì³ÇW¿š& Cþó?Ïæ;ßy)ðÉäi¤Ó¥œõ™‡/ Ŭ÷P *¾‡a8iIÈ‚ñ1k°,KÂd #Ímm„ˆwŠ ‚ ‚ ‚0~ ¨ :Ô—a³qš¹ ÌBº.dõãsuÁ¼åÂbƒ¿CåHÁ D2M0¾]Åæò}žÙôfžè! Áõ}šÛÚØ¾};;vìàU¯úvíZO2™$“_þò—¬ZõùüÌÏ‹"L-³^Pñ9÷Ý%ŸÌDé"¨”H$2DÏóøÃk_‹ˆþ‚ ‚ ‚ ÂDÅÛ¶%Ü» Ì öìÙÛy„ô}(c6(%¢?)Þ«ˆç>¨¾˜&?øÁ ¬];ËR“xÓé4O=µŠ¿üËgð}øéOW`Y=Ü{o_úÒ*¾üå×á8ÊE‚ìµ2ëC~yÀümÛ¢|aNŠ "saôAÀ§žÊg§»"‚ ‚ ‚ ÂŒ'Då«‚Ó4%Ü» Ì Üâÿ+V¬Àønñ‹P, að>AÁÞF̳–‚eñô—°k×¾ð…‡X·Nÿnݺ•³ÏndÙ²ãq]p“DÎß²X±b…Zà¡B{ÅCñ}Ÿ?¼ûÝ"¨‚ ‚ ‚ ‚HÖA˜Y„¨qº…>JÿºuÊ;Q¡‡L¢A¹²P]aˆ—t)|ótÄóΟÿ×<ÿüv¾þuƒÖÖÝݰpá²ãH#a<ÌjAJnžørM%qB?$«­³PÏÉ%qÄ(þÅ÷×ËCTCÉD Z<1cÇðcek ±}‡Ì7‹™b9Aq{«X¾ $7L÷ž¡<´{7 .Dr~ ‚ ‚ ‚ Aaˆ1ÁÙ¥mTA& Øzà=?Cr%ªÄ·±ÊÎ:‹ K1Ñ|€išÜu×],]º”8•ÞÞ>\2™é>;a¶1ëÏó°, Ã0&-!ýlB ~ñϦ̻.Z^)XÄ…Pb…4¢ŠÃùiÂ¥\$±(5X,4ðmÅåy¨ÙÓa´"´U<ÏHT'ÜD‚ÕO?=1?ÀQÄ=óæ‘hh˜îj‚ ‚ ‚ ³ˆÉHH/ÂäqäÈþøÇ?2Ðׇi¢bûƒ· C°vÜ ™{Á4±,åiò›ß¤­­ŽŽÞóžÓX·nð¶·ý §Ÿ£­‘ Ϩ•®®.z{{Ù¸q#Û¶m£½½€õë׳yóæé>Ÿ5Ðîy„“0Ca¦ žCÚ”HÜ;Ĥ”¼ J©Øg½<î>›¯r<’b0HP»ÆeõŒ ¨]L %±§ò|MàáùóyÉÁƒ“XƒÙÉsëÖ!M\AAAa"ÐD%B‰ Ì,öïßÏs;w2ÐÓfq„¯Jì>×…N¾ ïs ‘À÷•ÇJCÃc@™ tu¢½ý)þë¿Îá _èã( &™š•k¯½–-[¶pÕUWÐÛÛË{Þó6lØÀúõë¹óÎ;éííåú믟îsŠ0Qƒí†aÌJ1%D %•9A,”g\ü$P¢@PÜÖ¢äm¡…•|­æø‹–Ä$—¯ÏA_·J,àɽ{§ ³ ß÷9|Úi"¨‚ ‚ ‚ ‚žHD(„Ä‘#G8ø›ß°téR§?LspòxoéÛ”}xJPùÅ/Nå©§žçu¯ÛÂc½žsÏ} ù|~VŽ õAM‚ʶmÛ¸ãŽ;¸õÖ[Y¿~=wÞy'K–,áú믧¡¡7bÛ6½½½455M÷ypðàÁYa<.¥X9J"Ї´\‚b* j¬Ö¹B„¡é¤ú5²€ß?ú(¼èEÓ]ÅE†¼pÖYrß ‚ ‚ ‚ J†ã/D„)cÿþýìÞ½›sž{1¼Hƒ7Ä•Pù ù-©²Ϧ ûyõ«÷ò‡?¼‚;NdÉ’Ïópgô•„8¶–î¸ãZ[[#1Tø¯‹.ºˆ†b„¦¦&šššèííîs”÷ÆîÝ»§4næD8•†(16…ÊÒ†N ¨è ôóóJɕזúIø>Ö‰;ªî»wo#ù—'±cÇÕ\vÙØ¦IGGÇtŸ’0‹©IPytuu±aƲe u”`ÚV80¥ÇiDç‰ &Í”„P(*W%t?w¿›Åõ3ß÷F8ZùÎO°ìÙg'¶P¯Vü⟇R+ÛP±ò<”1ëÏ.¥xz“„çy‘ȑɨ€}aâyAÐÖ¦ž©T ×uq]—¶¶6Â0Äq à ™LÒÜÜL¤Ói|ß'‘HDe…nÈo¿Ïó0 £æY[aF~±5S(¢úézëu¾ïGeëeA :Þ¨ãÇ7— gB†|”`âûj]ÑœI¥Ôÿ…x^iY(a¥PPŸÛÚj?¶>¾ ‚ ‚ (…üaæ°ýä“I¸!ÏûÕßÀXóNÉdÀ÷É_úݲý §ˆ]?ûÙ”…üŠEÁf(Ѷ¡Æd]J‚I'ÐCyÒvï$A)Ì— Ì6ö¼ô¥\rüñã/H+”Z™Lÿ´ê¿f h)®Ïÿ/  -R.u,=#öÙ.–§›°¸|„Ìj‚Eø¾WQÕÀ¼çß1ÐavðÀµ0·w.|âƒ<~ÕãlzdÉ­IzØø¢|å]_áû_û>f×=|y'Ïmú/Öœ¸†—~䥼üÏ^Ή·žÈù_<ŸOžúIÞõÓwÑÙ©ž8©T*ªc¡P ”K¬t2™ û~µ¯^ÿU~ð±pðûyèÃA~róO8æÿÃK?òR‚BÀ½_¾—ßø ?tÇßö8÷_r?ß¹â;,yÛ¼æW¾õJ~ÿ A. oä!ÿñ‰ÿྋî£ÿÏûùüË?ÏÞ÷ïåÙåÏr襇Øsúv|bÛß¾=‹ö@îùÔ=¼°ôõ¶ qýG#¨ Br¹’çˆAªõÇ››KÛkD›¼ç©†½UÂP•éyà8ª<Ï=iRoïyÊ]}(‘$™Tûú¾`âõpÝ’ç‹ ‚ ÂÑŒ˜¦—„™Äªà)^¿ôõ¼¾ûõjœ†ŠÉkÅÎUfk’ÎØ jÂÉ'˹çÞ€mÛ³"õƒPÿÔ”C墋.Âu]®½öZZ[[q]—ÖÖÖÈ#¥¿¿ŸöövšššÊ‚ G?ûöí+ó|éíí2lÆ ãò|™ª_j̵¥øÙ@Ã:Ååéâ÷¡(ŽÇ"ùL„饚mÂÄÚçö“O欭[G·S’›W'J Qî[Ý”TMtH+’ʵ«8Ë!R)ÓUŽá ó¹eÄYU‡#ï=ÂÜÏ…ZyˆyWÌãêO\Í?Üù|ëßbíܵ ƒŸ½ûg¼ç²÷pównæ„ÓN`áy Ùù•\pò|kÍ·xì­qê§Âóp÷ÿÝÍsóžcÓG6ññÏ|Ã3¸êSWq]â:žúÉSìyé~ñÄ/Xþ²å¼}õÛÙ»w/K߸”¯ÛÉÊÝ+9µp*¯9ó5Ì~>|[]ƒË¹¼t)˜W˜GÂI0\}ÎÕ|`Î8·ç\ž9éÖ>¹–y'Ïãë]_羓ð[!O¶<ÉáüäÚŸðÆ7¼‘tgšÞøQ²Ëræ9grÉŠK˜sßκê,œ¾úÕ¯òOÿýO$SIø(\|ÙÅ|ç;ßáÎËïdÕªU\ñ¹+¸ú3WsÎÕçpøžÃüãÿ@ëÇZùÚ¿ÆÎ÷ìäÐîCê:ļó˜·z|PU=\²rëJ|ßç·ïÿ-üÊyè ±fÎ./Þƒ<|øaN=þT¶Ÿ¼>óÂøŒ¡™ û¬‚@ ÑÖ¡¶::”Pâ8%ñÂ4Õ²|¾$f„¡-òy%däóª ÏSeX–úìûª¬0„ÆFPË\W-7 ué´Ú¾PPŸƒ TF"QÞYp]õ—Í*Ñ¥­ º»Ë¯‰ëªuŽ£ö ‚R®«ê[(”D}<ßWÿk¡'>Ö Ï]úcgªÚ¶‚ ŒŽ£éÝ)3ɰϭ[·Š "ÀT¶m—ì{Õ«W³ü¾åÑ2Ã(öQZZÔ‡ÎNðUÿÈ0T¿Ìó`ÇŽ5œ~ú7€ ¦û’ G5 *MMMÜ|óÍ\sÍ5lÙ²…ÖÖV6oÞ ¨Ð_›6m¢©©‰ë¯¿¾æë01º€öööÈûEsÓM7•yÂÔJ„?«WOÉ…4Šy{•dkØ?.¶È«_˜NªÙ&L¬}»}{m\í-’DIedPîÚg¨œccwùJ«¿0 ‚+kq‰ yòx §>óYú>uàS̽{.—?v9÷ŸùCŸ‡~2}¢ýì^¹›Eæ"šŒ&‚ à<ó<ú 9Í: xïÃ0 –šKÉãŸe;?Ù¾zÝWø˜ý±hÙ÷c6þvc´ì}§½O‰Ý‚³9[-|Oõ*ëÐb‰D‚T*…eY|ìé‘L&1&Ÿ{1[þq g¼ï ;`ùƒËxû_yð+|zçIœœã^ŸL…}Ö Z4°,%†dky™ÑÂA&£ -Dèr %8ø¾´—‰ÞO "P´g‰ÑeÛjY&£¶Õ¢‰öBI¥TY©”ª{2©Ž«ËrÕ7èë+õÒiµ½.K ¹œ*Ë4KÇÓ)ZüÉfKu3MµÞqÔ1S)ÕÿH&•8£C‘e³êœm[-3MulalLvÛV„±q4½;a¦1Ñöé—íÞ-3Ôa˜ª¶m„Ç„¬]»î+.´!ôÀ\þ\ÙL°Ë/¿—«¯VcétžŸüäTV­zŒ´tb„)¦&A`ýúõQ˜š86l•ñlÙ²…®®.î¼óN®ºêª²uýýýÖˆ Ã÷±G33,J㼂DÞ™‰ g›0qö©ïa•Â+3z&ÿü}ßDz¬è9gYmmmtww—åI&“ôõõEH˜7ù*_¥°­€õ ‹ Y%AtÒétšOä>eYXo²XÍjlÛf•¿ Ó41 ƒlñ9¥sžLZEݯ(æf[Yü§Ñ¿‰öì‹ÿFÙ)ç aÑuÉçKOY`. C5-Š~;;k“+Ž4ï+ß#—Ëq —LÎõœB¦Ê>'-ÄM_{†TC‡Á‚’`ÐÒRòܨ,#.šd2J@Ð"H–ÊÒž)…BÉ«C·¿µÐbY%±Ä¶•8¡EÏSuµ½ö Ñûêº$“%¯ÛVuÓe†ª‡vW·mµ¿öI§Ka¼´P’H¨_Ú+E{»¤Rjÿʺõô”B‚ékhY¥pažW qÿ]âÞ<šj-B‰©jÛ ‚0:fûSf+“iŸOüä'S©Df#SݶmN9°€•»W”¯£ú%Æêß«ÎN>çÁ¿üËI¼ûÝ»ùÊW–óÝï¶òâÇÛß.aþ„©§fAe(FeH6l ©©i‹(o—ë®»nÂN®Ö¤Ë‚ o›0qöÇ?ðœuVõ |” Òɤ»kéDë¶m“L&ééé‰òœ˜¦‰eYø¾O.—S‰ãà8…B×u•HRÜÆ0 òù|´¯ã8Qñ‘É"ÒÈŸ È®¥¢ôì”B¡Àê)òRœl¦Ê>'ƒ0,åÁÿC¡’ (m§Ã[ÅËvÝ’a%1D‹&¦YÊgA‚@‰…BÉ$~,íÓÓ£ÊÖâ ¨ãi(žÿD{è°bZ$µ¯i–<_ô1 Üû&>¹J‡Óž-ZØÑ‹7æ8j™Þ^_»înuLð>ŸWuëéQ‚e2µ¬PPåèë û%©TÉË>“·ÐÑÀT¶mA¨™üî„ÙÎdÛ§x¨ÂØ™Ž¶í¼æ1÷™¹*âHqýý„½ÏÀ%{Þ¿ÿwüïÿ¾Š·sÿýÍÜsÏBÖ®½Ÿ7¿yº¯šp´QSRzPqò®½öZ6mÚÄ5×\ömÛÆtÀõë×ÓÚÚ:(y}?×^{-k׮啯|%[¶l±¼;v°iӦ軇R7Mf¦ 2ój<˜Iš[_—lÚ´‰Ûo¿}º«1! e›0vû¼ýöÛioo/[æ‡÷쩾CˆÊ›•0¤R)|ß/KŸH$"Oíí`š&a’H$0M“d2 (ù|>úœÍfI§Ó˜¦I"‘À)Ž˜Nš§‰0"Û¶mãöÛoç¹çž›îªLmŸ{öìaÓ¦M5ÙñxICÌiqD{m@)I5tX-öË÷Õ¿þìy¥A¬] ګĶÕòl¶$:èmõ6ÚC#:+ •`‘N—Ž©½8´Èàºê³a”„­j1E <0´'ÎP8Ni_MO:f6[5Òé’÷‹Þ^×Qÿ†%Ï-Øtt(ÁÅqÔ:Ó,ý‰„º6Ú›E‡MÓâ“ë*‘%™TÛë߸V¶lÙB{{;O=õÔäÞ|SÄd·ma*‘¶íðTkÛ ÂT°mÛ66mÚÄŽ;¦»*Âdµm~ø0Áp3vaزe ;vì¶íè¶ípãÈýÇõ+1%>„Òׇßœ27ù+0þÀãê«Ì©§~‡óÏ?º/™PÇ´··OJÛ¶fݱ»è¢‹èêêâ=ïy·Þzë äac¥··—ÖÖV®ºê*nºé&ººº¸æškhjjÖfÕªUÜtÓMeËT¤ p†¹|Å¿ÙÂÑö릛n:*:UcµÏK.¹dP<Ü]²úé§Ë7ô)%¯|‰Ž“ ¢JÉd’ÎÎNÂ0Ä0 ÃÀu]lÛŽÞ™L†D"íS(0 ÏóÈçó‘+©iš‘€"Ôëׯ禛n:*%ÇbŸË–-ôîœH|pByí)¢Coé¾®'¥CJ%“j°_‡Ç‚Rw²Jç9I§K¹L´÷‰ë–¬ë¼!:ŸH&£„ ×UeFiPûkg$1¤g˜P„õöX°¬Ò¹Ä=dôï£E–|¾M‡Ó¿§öìÑ2ú÷L¥JÛèœ5Ž3|}6nÜHSS]]]Ó}i&•‰lÛ ÂT!mÛÑ·ma*¶mmmÛ'Pkeb›0•lܸ‘þçæÄOœîªL*“Õ¶µ€—Þz/ü÷5˜«óå66Âþýe‹ùóçs sI§mV¯^B6»›Ç{ X1Ý—G¨S&«ÝV“ ÒÕÕEoo/ÿ÷ÿGCC f^oÙ²eÂ*¦šÖÖV.¾øbºººF›ÏZwîœQú&JL™MA€fƒ· ˜Hû¼ç¹ç8叨£'@%IÏ£ `‚"ƒ À4ÍH0±m; †!®ëÙl˲Èf³d2:::Ã0L|ß'‚(„ "ŠPWL¤}NZôˆçAÑ᪠$¸èüBA‰: ˜^¯îuŸX'X×^…BÉóE{ % N¯½Mô±â9Wâ¹Nja6F’ÐóP´×IÒér‘$•*]¿Eÿæ¶­~7×U0¹\É[G‹fþLj ƒz´MAbŸ‚P¿ˆ} B}2¶é¡”\ì>{‹ MÀuÉ~É!s^´­aÀ’%O³téñÿøÇá5¯ÙÎ…¶L÷¥ŽBjùÕÚÚ‰) ¯®Ÿƒ¦Ã²e³*W‹ëªmâ¹l´8£ó¹ìß?î4~uÏtÛ¦ C#ö)õËxíÓ?Zfnu‡ò”˜½LÖ»ÓN}öTõÁ&rƒÏ|ôÙ+¶3 X·n_þò[ÉçóضÍ-·\É…ž1Ý—F8 ©YP™l´«˜ŽÉ×ßßÏwÞ9êbòê¬/dzv0Qö Ð;wnIœp4&¤är92™L”÷D/Óß;::ð½IgºmS„¡û„úe¬ö©Ç‚fÒÄZA˜ILÚ»ó.X¼x±Òý1Ó„'Ÿ$óл5IËuá–[ž"—ËE“baº¨›é7ndÛ¶m\~ùå455ñàƒ²qãF6nÜ8ê²lˆ’K ‚0~&Ê>C`i_ŸT”wʈ)¾ïcY¶mS(‚€B¡€eYäóy|ß'•J‘.ÆÒ*[W˜ Läûs,„aõÏ: |.§DÂK $ÚãD‡ìÒj߸€O¯ûÈ:|”<&Æs¾?úÄñGÚÓ§Vôï–H”{i1Mç³yç;Wñ–·,]á3Œé¶MA†FìSê—±ÚgH)”úd!x…£™I{w>\ü?êßYÐÝM¢½ŸÂ½¥È…¬]»Ç90”$ÂôR³ òàƒ–%@ëííäîUkÍjÛ]wÝulÛ¶}ûöÑÔÔ4n•s¦ÍLH#B=0” O„}ú¾õ§ªÄ”4.•J‘ÍfñŠñzÂ0ŒÂye2™(l—Î¥"3•ɴϱâû¥_úµkYjà< Ës–d2j½N_MѹU4µ¼ÊGJ‚>ú¸3¬Ù0cп³ö"²,¸ì²=,\xhº«6¡LEÛV„ÑSïNAmŸ‡vï–‰µ‚0ALEÛ68n<ùF¾Ä—J+ ÿ)# )¬ó_ÞwßÕ¤R/ S‡&„i &AeÉ’%lذ¡lÙd58ׯ_?!åÌDµÒgv%¥fãµO=[È0 (£œùGçEéèèˆÈ›¦IAÇ*n“Ïç%ÿ‰pT0QïϱP(”DÏSBŠÎŸÒÑQÊ—j0= U£Ôö:aütaY£÷ÄFO\°ºì²=tuœî*M Ói›‚ ا Ô/c±ÏƒJßO&™‰|wú€y\øð‡­s]õ§CC/Zt„7¿ùv.½ôž9æ+Ì.jTÖ¯__³çI½ÁŒòP±÷Qaö~úSxåÆòø˜cÀ4M‰abš&®ë†!ù|ž °mß÷¥A-Ó€N(¯ÁGE›¥Stž•éD‚ ‚ ÂPÌœÑ%a:X»vítWaÆb°¦MiA€a`šFI —ƒwòÈ#;عÓræ Ât1ê¤ô½½½lÙ²…öövÚÛÛÙ²eK”¨Ð3àƒ WOA¨3B`åÂ…J=gˆ×uI&“ø¾O†8Žƒa„a…þšI¢ª ÌT´'ŠK|¿´\'5C5³(›-.t80 LAAê]„É㎠î(}ÉåÀ÷1ÍR_Ò²àÿq)ßøÆ+°,K&Î ÓΨ’Ò···sà 7ÐÐÐ…»á†hooÇq®ºêªé>Ÿ(™— Ô÷õ÷³øÑGá‡ÀÃ]êdóN1i‚iš¤ÓiZZZèééÁ0 Ra (”J:­âÚærªÁëyJ4Éå”ç‰NF_-ωa(&žKeÆ  C­3P%(§€<*ü!(¯½Êí=À-®Ë÷ ŠË³(qZoGq½‰r{­F¡¸ÿl¸Þ‚ ‚ 1<`÷îݬžîŠ‚0jÎÙNéKqfže•òt:ôôtãyAȘ¯0íÔ,¨ho”ë®»Ž7FËûûû# .D•hºì Ãgè1™†‡Œ×ƒ ×®…¹ŒyŠë*÷NÏó¢¤ó‰D‚¾¾¾é>=A˜õú³íR<ÛL:;•À¢»›¦Zçûªñ›H ð½îMW %añ³…9Ô‹;@ -@C=ßìâç<,nRV ÅeÕ• êEÚz™z(ZïÛQüß*£³X°X·\ñø…â6ºY”/–•£v1^·°¸Ÿ«‡®[PQGAA„:ciOL®„B€êNó'?äìþW–¯4  å½U”gJ.—“ˆD´S“ ²mÛ6n¸án½õÖAɇ"ÅuݺTfZþPcÌAEªÑ?g{ÕÌê1’N§#/Úo¦Ù» ÌT‚ $¤ÄÃÖf2*œW*ÇQ‹W²ÃØü¤´…}Ê]‡”f-¸”^¶Al™ƒŒâ¾m(¡"…5Œâçn” á÷Ó†Yl×h0†Ì(þU »ØûlǶ¥xXyaì\ÃâµÖbÍ8sd ‚ ‚ ‚0ûqv¡?ìÆ;±ïý{Éö¸ÐÓ­×y9‰„x¦uCMIé÷íÛWSaÓ-¤@1"G`Û£‰ð«ü¯Ãm´QP©$ÛG(C= ‚Ƨ8c(4Æ¥¸uttÍf£*‚ L•¡ju0-ª˜f©ýy¥è÷dÒ <±ezý9W±öÜ%@Åÿ3±Ïú½­=,Ò±ãæ(åÑ¢…Ý¥ËÔ¡³t˜,ŽK{¢¤(y¶$QÂÎmÒA¹§G¾¸Þ¦èóèËåUWí{˶kkS¢ŠFÄ¡ž¨IP¹è¢‹F çÕÞÞNSSÓ´{©Ø¨Á×g¯ÇÃmhaĉýŸ/nc£^lÊÉ虤ĶÑ1ÖãhqFÇh׃45âº.¶m“L&£Üžç•å‚€B¡@GG¹œšÚkÛv”´[‹+¶mãû>žçá8†aËåÊ©õ>ñýÃb|Ó4Éd2¤Ói 5z¥óW¸®‹eYd2º»»é[ºG8¹âu‘gâQA<½óiŽ4a F½:&‘H`Û¶¼HaŠÉ劂 j–P–¾ð8$‹#‡zGZ(AÁE ÚÓĤ4‰Á£²«™’˜PWôöYÔ{Ú§$ÒtË浪+A)ôTü½¬ëÜÍàwq¶âÿøçxx¬j^æòH*G_Ôï …©˜µóŠìëªÍZAa$|à™gž‘üš‚Pçø”"&7?v '>Ÿ;<vÌÍªÃæy¥í3™L4*õBM‚JSSW]u×\s Žã°qãFT þþ~\×å†nàú믟îó‰rÀ5G)qj¥Î~H)T…Fô{8”©6!Þ‰mÓûnRž¬6näÞÍ÷²ò¡•ü×áÿbý‚õÌ»t^Î#Û™… l½a+^£¯§Ã6xøö‡ùÛóþ–{ü{øýOÏŸ]ógôu÷áþ·Ë›Î{ïzù» ¡2¦ibY=‘R(°,‹T*E6›„‘D"ïûø¾O"‘ˆÄPeiaˆ„œŽŽR©étPÞ+:Äšatww“J¥è¿áhlÞ[HÏ\Ž `~Ï6¾tyÍûh1/ CÂ0¤¥¥%º‡A˜:<¯änm­)æG¹Œ5àoQ¯M¾Dé™÷Þ0(n@É[#ž«LokSî å‰ö ÑÞ*ñ÷‡[¯ËK34ÒÏž:â¿¿ ‚ Â$Ò¸u«äX„Äc=Ær–co¿ã;Á>-Z§MÙ÷ýhlHê…š€Í›7ÊcB{£ìÛ·þþ~ššš¸þúë¹è¢‹¦û|€a’Ò{¨™­P ÓN <4‡¦–€4ÑLØv€‰†/ÜöZÿª•=?ßÃOžø mºåi#ÍGôQ~tâØ¾k;WÜsdàÐîCܶá6>™ÿ$ù¥yN}æTš~ÑD×y]\úÔ¥¬ßµxöÙgÙðXûÁµüðîbÿ©ÍǺ?Æ¢Ÿ/"üyÈ/Žü‚ÏžñYæuÍcgz' ÷6°xåbö~q/ðÍ÷}“—ýòeßy ]) ÄìT{N08Kåöñ<1ñÁ#‘/}\´kl.(–÷ò‰×?^ÇjLj¯¯¬;”B¬ÅÏ=DÝ qE‡’‰+žm(üby2Ž?n|à˜_ßÖkkÞGçÊd2tƳ‘ ‚0¥à~ ‚‡!» ¼;Áx?$–¼o†uzA¿Ëljòƒé˜ƒ[Aaæàûþø aÒ)¥H)°1ó§ðË¥‘GJª?ßÓ H$c<Š L£Têc·o/y¨è¶ <´wÊ8Ç›››Éf³Q^‡ p]Ó4£#=“Ïçikk#ŸÏãyÞ®jžç‘J¥èììœù!æüfœ¬˜†ƒ”~ãø¥ÖËr””·$êžÈ?ëøüJ^8:¼LýŽÎÞ¿ûOGuõg6›­}'A&k.„{ ìw)ëÁ¹bh­=•JE“ZZZèéé!™Tž—úý†!ÍÍÍôôô” .AD¹¾t^0×uÉçóeÛèü_š\.yЦR)òù<¹\Û¶q'šÙäº.étšB¡y—š¦‰ëªÔˆúØaFÏ D"M~Ðu7M3ê´Û¶M.—Ã0 LӌꯛmÛQ›A Å:¤¡Æ÷}:;;ñ<ß÷£‰ZàÑÇ ‚Çq¢v…?‚ ÂlC÷µußX¿ƒgC_Y˜, ”ûCf ð¶î·±ä«ÿË—7_ËR9T‚ Àó<éïuǬT€ÒÀL5H®ÇbµÇÂÇfõà‡mÛÑ Šçy¸®…$ ¥žf2Òé4†a000 ?K×0 ‰Ä¬i Î1æÀÀiã.jâ‰{ËtRŠå߃[tä%A¦uïh7(=®'"˨xÕ³¯ÕöÚÓ«P(È T¦0T ÙÌà4@âó(Á<ÚF‰–e‘Éd¢p•†aày¦iÒÖÖF‘ˆ·i½­~G&“ÉHðÐâ(Ñ"•JE^¡ºq­')èí}ß'ŸÏS(°m›B¡PæMjYÉdP“´ây^VÐó< àP(ÐÝÝM&“¡¹¹˲"ÑD?Ÿ´£“B¡‰!Z<‰×Ï4MR©T´½.S_}|}=LÓŒ®‘.W‹) Ä}^úºèsÕ×&>ÑC¦H4~ær*N«¶Q-Žj‘Ñ÷ýȾµÄÑÛÀôÝßÚ;½ž=ðô3(”Ö×´š'^†<ýôÓÓ]uaÐv£íLßZ¨×“²wˆÞWïÓÖÖ½‹âè÷­î/' Úº8!A¿#MÓ$›ÍF“}ßÇqœhâ€î·µµEÇÔõÓï;}ÿês°mÃ0¢÷«þ®ÃÇßÓ‰D"j‹tttàû~Y½µp£¯“¾&Õ&iè>¿®·Æ÷}r¹\4F ¯iåy …h’ˆŽ`¡¯k†Ñù’? ²@[?“A(ç„m‡i× —œ†óAhitZõ7 ò+ ­Y3N*Ì.f¥ ”œw3î\)žçEƒ…B!êú¾Íœ×Ët¥££cÑ×ášmƒ¾ð(§^¶–.qÛxGzÊ©¼7ÒCl—E‰):a²‡_L`ÍôT}¦áÀ®»XQƒÛR\¤Œ‡½a ùJèüXË!x<ñg±,ŸDâüh3= ï8®ëFƒz°S{t‚xЃ0aÒÙÙI*•" ÃhC{htttDƒ ú8ÑŠžÜL&£²âïQý^‰fhª=Wâ9šô縷©ÝY zS^Õ2ÄÑí‹áŽW™SJ_o-ðháH éºäóylÛ–Ž‰PF<6õXï }éÿÓé4™L¦làP‡ÅM$„aH[[Ùl–¶¶¶²Iý¹¥¥¥Ì«M?K Ã$€êåZXÕmký̈‹:Z Éd2‘}º®[&¼ú¾Ù¯¾>ú8ZHÖuÕBf|ÀZ£”u_¢òkÛ×ía›1¾özÓý]]Ÿ¸p«—éäøµÑûê²ôuŒ‡.6 ƒÃ‡óÚ×¾vºoK¡ô½¢ïûødíÁ¨ìµ8¡ï ýžI&“e÷’¾➟@ªˆD‰8¶m“Ïç£ûY "zÂ…mÛÑ„‰ÆÆÆH±m›d2I>ŸÄTm‡qïT ²K-dhô„ }Éd2zŽh»O¥R¤ÓéÈ‹6 C\מIAÐÖÖµtûF“Íf£IúÚ8Ž-Ó“(´mÅ·×ïb=BO–H$Ññ‚ (›$÷LÕišìÙ³gºo;A„ áÐáCXq,(¸j2¨dôº¤£È¸PoÔ$¨tuuÑÕÕ5ì6ýýýÓ}.xÀÁƒÕíI0ÎñÝðÒ³Ft#->;&™LÒÙÙÍxF=[M7„g +ÌÜt÷ݼí²ËÊ) jhëÁŸ\.G¡P NG v×u£x|†”îðéë?eè$÷U¾¿«é]ì\½sš¯xýsÆSϳkÁ®š¶Õ¢x(A¦Â?t~rwÁí·?ÃáÃÇuוré™­™L†Ž¥:Û¶Mcc#aFÞš@4èX9˜ßF/Óè÷j|»&>“s(&êÝ:šwNe'ûx•ÛëGeÇ#R©T4ËV6ɬ×Ù€ŒÏÀ®üÓ6è8Žã jËêv›@Ã0$—ËEƒŸz_Mcc#ét:Ê–Íf£Ü‚Ú.µP9Ô=XkÈÏød'=È©'BéSݦÔË‚  »»;š¹ŸMDÏ*=É#.H趨 Öƒ¤zözÜ O{®çóùhp7þLÔÛêðÀPj+ë2ô@y6›D£øïßO—«C*êk­ÃeÄ=t]?»5©TŠÅ‹Oã+hO×u£”Ú†ôD}h¡C „úÞÖÞ Þñw«ö¦Ìård³Ùš&·Å'MÄ…€Jô„¨t:íã8NdÏ–e ²íxÛ “É 9áN÷¿+ŸZˆÌf³Ø¶]õÙQùNÌd2Ñ3I_›jûéçŠmÛ‘GžœPYý Ñã‰D‚–––hŸáÚ$úùœËå¢ÄŽŽŽèÙ¦ÛP›6mš »LazÐRõœçæpò±'CPS2å¡¢óAÕ6© Ô5 *½½½lÛ¶mÄíZ[[k>p?ûöí£©©iбz{{ijj´®æÿô§ÊØÆ™HÜuÝ(\‰a<öØ…€ç¥øøÇ¿EúQ#ª»[e¸#/±xñbÖž{.ŸÿüçYùÐC‘«w$“ɨáïû~Ô™Õ}ÝÐÓ4£YFPÞÁÐr×u£ð/ú÷˜*¾{ÅwYÿ’õÓ}É'Œ¡lÆgŸÏz–Ëkž‰DÔY¬J¨7m|ÀuUֲЙlaÅ#HNa†2YöYÂc$ÿ¬68räÉhP5~KâÅ,Ë4èWmf‘äH*g2…dÓ4éììŒ&5ÄgÏ&/Ùéb²Ú¶cA·‹ôï›ËåèèèˆСäõ ÿ×÷…çyÑŒõ¸ç‚O”ͺփ„•íàj¶]99Q÷]Ü+c´åÇëY),CΈîX•ûhQ©’JOÜÊghüóh<ÖLÓŒBWnS)^Wî °fÍìr¿žÒwçÑæÚÃPבÂ0ŒúJ===‘7”öúÒž*ñûi¸Ù¼ÚkÄ4Íš#h/ÑDÐ1#íS9ÑB =£9Nµv#áyÞ /˜jçÿ/~äð›Û6ÑC@…‚²ÑžƒUÛ+‚0Ô$¨lܸ‘7NèõL›Í›7G˶lÙB{{;6làÁdóæÍc:®eY*Ó=ÂÂ~)aøù|×uyÂÀ¢³Ó$“±1ÍË C5†ë8àyZAÖÎK°l‹-Š©º©Cµ@yHíŽolê†:A¯ž½¤gCkQ%žƒFÇê×¢LpÌóǰ·eïˆÛê0†all,™ª\I8©ì°Åi --`Û¥õAmmês"QòUSeù¾Ú'ÞQÑÉ#â¤RªŒÊ—y¡ ÊÐØvù6™Œ*϶KÛÅëªl˱G–ɰÏA€Þ§!Ø þ:x¼ïq¼ÜÉ4Ÿµ›Ã—]Fܶ{7A.Ç¥×^KhÛ$ÔnØ@¸üK_âkÖDËJ)«„êèk?þ<™ôû1‘HDÇ™¾ð›³„ÉlÛG<ôS\Ñ¿g&“‰Bâ 7 ¿/´×‰n_U¢ïÑÙ:À'Ì.¦äÝ9J´xbšfÊI{(hûëìì,ë§Ä…¹xØ;˲hkk•·¡î#f€JÛûhúNºüÑ죷­gèhsi“ÑÔ­ÒˬÖó‹×i<ÜØlf"í³2 ãcRÇmg}–¹ÏÞ·yx«³d³¥!Ó×õF ƒ,ÓEM‚J?½½½¬_?þYø[¶l¡««‹;3«®ºªl]{{;×_=­­­lÛ¶Ë/¿œÖÖÖ±ÍF°vÔ¦ÚXi&§žú,×_ÿSyäLó46&ééù[þìÏËÙÑxÓTBJK‹µ¬’°bjŒtEñúÒ^yå•ƒÖ Õpj Gwæãë-ËŠbéëÙZú/.¤è™¾z—žõOþ§…Bˆ’êã g›0>û 3ý{GÜVÿÞßxï{¹eɸùæøJå•RͰ²YeØaX¾Þ4¡³³ú>®[̰ $“åÛiáÆ²Tf4PåbI”¶Ó÷Jå ?›-/¯².†QÚ&•RŸã÷ç©?Pâa@ÜK=œÊ÷©uô±…ÉdÚç \Ô¤„KÛ üðôu¿fÁâ§ ·²ôc#•JÁ×¾Fvùr (%´}Åïæš5ø@²¸,衞*ÅY3Љ]Ãâz="î§Q(®kC¥´2‹û̶yJcD/:ÇŒÝ4ÒL]a0SÖ¶­B†466Fá}t˜«x¨§±„tiU:¶ÂL`Jß# û:g‡=}ß$œèAþZú«…«…¡<”†£2tX-Ä'ÓÕº}Ü#®ª…›èzéãŒE­÷éhÏ&2Yö)ï'A?SѶ5€m;Ðþ*¾¯†4âsPã!Š¡Þ¨IPq]—mÛ¶qÓM7EËÚÛÛÙ¸qã¨fÆ 455ÑÛÛ[¶¼««‹%K–DaÃÖ¯_ÏúõëéêêªYí,k¦ŒÐþÌdÔØb"¡ŒÖqÔ8åÓO/`íÚïpÙe¯â{ßsùÒ—þÈ7¾q·Ür%¾¯Æjãïè|^íkY¥Ièž§Ê C5.ªÛ†QŠ èºjŒ¶P¨>¾:ð³“PÍd2™AŠuµ†q|™NÒ¨c k÷uí!ãy¶mÓÖÖÍ« #6—òzg(Û„‰±Ïc;üEãð|Ÿs¿ým>°bó.¿¼\iö´a VJah‹‡Bðýò}Óé’Q·´¨ï¶=8¤˜iÖæU2Ü€–a¨A>¯Ž™Ë .Ó4KÂKµó³m%¬èû²òœ %Öäó£V<¯<3\å:}ý´Îh:§ÚK¨òZÄ ‚Ò¹ÅÏñ(b²í3Ž7Æ?MÀmðàÓÏñÂÙgóÏŸ>H×îVþ{õjO|ùòHñ)…@ð( $Ú¢ôz³¸,2¨æ³[ü_§>Ë „’ jn„‰cÂbnq»J”©Ö¼w 5üâñô Z&“¡¥¥…|>?ëÞq“Éd¶m‡#žCÏNסfS^>A+Sùîß÷q]7Ut^Œ¡«GÃhÅj!îFb,a:{zzF½ÏXB8V<6MsÔ×@î†D"1êßóhÈmV/ö9Zäí* LUÛ¶éÙ&˜ÿßp¦žFH$JC':7– Ô#5 *Õ¸á†ƤBj/—%K–”-ß¶mÛ ²–,YRõgÇŽlÚ´‰›nº‰8ág?£áÈép+¥©°U°,5†jœÑóàŒ3îå]ï:À{ß{ ñ¶·m`áÂK¹å–+£}†* Ê# éèC™Œz(¸nIP‰{f2jœÖóJé ⪬a¨Šëªÿã^/ž§–ù~i™.×óJeÄ9šöŸ.#Žv€Ác×Ó1^Ϭ ñ²Þ·»»»,˜5¦Ãhh‘%“ÉDq}MÓdûöí9rdTùƒê•¡lÆnŸ·ß~;glÞÌŽ¥;X¼úñꆡ Ë•NcÙ6Ïd³4\pÁÔ^€j7¯¾W´WÈT„éÖ`¨¥ƒ™ $LíííÜ~ûíÞ¶³ 2ÑìÛ78E-bͪU«Ê:œ/ùÍ^ùíWªÑ‹!Ðãw:ÒOg§úüÅ/~™;î8>jFù¾rè™smmêfK$ÈE«úH;Xd¶ä°me¬ÚÆ4•@2TCe¤Ù CyÌÄI§?ãÔâáSËD2Yzptv²~ýznºé&6mÚ4¹×´‹}.[¶lèÁÚÀ©°ë©Ç XÃ?z|ä‚È Ôvœ}6i”G€- ¨p\nñ{€z÷¡BuÙíc?'Š>JñÛóp׬Á<þxÌ+pÇ÷q 0M¬†¼•+qÎ;,JŒh;tˆpÿ~Œ;ðŸ{ÁÚN; ³Xž}ó‘Gh6Mœ»î"óÚ×J„ð`Þ< ›6a<÷<ÿ<Á‹^DGñœÒ@ðÜs'œ@vûvüW¿šìöí¤Ö®.™ø7âÅ)ý¤K£Ä H^~9\~¹‚Î?ŸJðÑtÌË’Iþæ7¹ìe/#øáñ,+}ZV¯ÆvxöY‚óΣã«_¥yéRìây@öç?Ç~öYü•+i{æÒO>IaõjÂbáããwÆêÕP<÷ J¨ÒžCÛf§m³þ/þ‚×_uÿzÞyPüm´—Ñx½Oµ‡sWW×8Kªo&ªm[I.—Ãu]º»»gíª0}ÜtÓM´··Ow5&ñ¶mGÂ󉩧†èé$šx>ÝÚ¬0Ôë=¯4ÅqÊÆ ãcË\á›™€IDATù|©a÷<îî.×sâûèu:ÝB|Ì×qÊgßèu:§·ÞGÏ’ÑÓ«yd;N©±Y™¶Á4K3lôq ØW|›§’¥”º©›†QjlC©ñjš%‡Ç)‰PZÑ‚‘ntçrå^:• üd²T× (畼ƒt4%—\7´Õ1•‡J¡P(pÒé4¾ïóµ¯}mô7ü c¼öéË÷̃“«¬,þðžiâÅ™‰0‰Ä z¶4NR©’Á…LÔûS³÷QØ}6ÌÙ9Lxá± ™ûÌܨ³h£:L:ω`·( $ZávLƒâ€ý}÷aüÍß`_XY=sÀ0T‡.—Ã.zL9 Ð+V…ÒÚó0çÖ[aÃ0 Ï=ªãgÛ‘°£;|Æ '`œu–ªïÆd)u.] kªÚÐPv-¢'þòåê/†CÉ+Fw u§6þ‹·tçT7¾ã”ŽoYƒ÷ïì„|àÉ)¿Ÿ¦šÉ´Ï‰@·ƒ´HaÆþדe´€à—é§€n ±íR±e•ÿ±òãûCy›Ó­RO}ŒøöaET¬ÓÛëIG¹X9º¾ÄÎ× ÔžM r'êzërõ9ê²ÃØþºžºÜ%aG/Ó¡„íØöñóÒËÅë`Vì¯ÏÙ)–oT\» J9z}]ôöº?¤ËˆÿŽ¿Ú¸‘µ÷ßÏlf"mÓþüï^o] Å9–úݤ‘q!¡ž©AeýúõlÙ²¥lÙ¾}ûFR,6ö¯)ŽTY”ò¥8¦‡å»ô¹oÍ>ÓÐ@†AÀÇo¼‘WÝuWÉ}£Ò;EOqÑÄãÿkâap|°Ï±ë–TÃÀpòy³¼²QrÚêç«Ç—†¢Ú~ñFZ|ÙHT{ŽÅÊñ\Ü–eJñuúÚåªþñ:U ¡ßOç°‰7´ãûŒ4ƪCªé†¸>§æf=ãÊä%/9H"‘ ìHlQçbñÒ—þhä 8Ùûl~l/¼:¶@OM+z9X¨Ù|žçÉ,„Éf¶5L²Ùò©,GaŸÜu÷<÷Ûc˜û’ç9ëík8`—:ZH±)‰ EñAO?-º3šé48Žê°œq†ú­‚ ú{Sç)ªöòÒ3†xiX¶ušôÿÕ¶Œ7 ´ŒÇÛ¬ø$_ÖJËÓuLëÖñ«_ñÔóÏ3Ù2ŠñJâ^@q*Çh”«uÕ;F7ÀÊ•ê˨Ðl=„ÙØˆ ‘‹~úÚsçâ57sã·¿Mÿš5<òÞ÷ÒQœuáPònÑBšît[Årô,Åxg5>sóh`BmõŽ ÃΣT<„‰d¢í3 C\×Å÷ýÈ#e,yM†$ 4Ò¨§–?û»¡ð OC° ‚m<ù ¸»Ø}-x_ãàß Ö.N’‹Þ•úeØÅØ¡F±±a˜Åw†Õ3:B†Ì<˜E÷ÉD^•gGBmˆ\i ¬x,Ñøôû¡^Pzʾ[¯_jºNA±}Q9J¬]vã#²EL=2kTÔ'>JMÅ:L ^ò’ßLÌ=UÇŒÕ>ÃÑô*~“È5#>ú®]@bñií+Á¹ Œ]¨ß7Cùè|æk(%,Œß_V± ]¥ûР\° ˜æn+/q…#¨8—byÙJ%ˆm뀰:.ÿë`팕Q|ÞùO±°X¯|}ð§üœýœv_ñ²7€y‚“ `@çV0Wû¸»§ ›ú¶Aød‚Ýù–@ø„$Ö/ó½àùŸAØ©xÉc»Xü‡?Ô~Î@&òÝi«zž:5™Lyj@r: uMÍ‚Jooï ÷ï;ï¼sP¸†±ºÒ´¶¶²oß>ºººhmmeÛ¶môöörñÅ×\† <ÿÔóCöÖƒ }æàßb¿W-DÛæ^×Å Ç!—ËÑpá…pá…è"9sµ†òH®ÚZiÐK&±µ *’v›0Œr?`(刀­yôô¢±¢ƒ¸7R»zèø]Åã=ïCÖ‡ÜÍÏÒñ៤5Çßãí§èË[‰þ M~ød:;{8æu°âQ²Y¸ýöóimýㄟW=1nûÜ Ï>÷lù²L¦,WF.“‰rÕÈLaTŒ&¶ß,d"ÞŸp1`þм¢q/o—Z¥Ùg×S_ ,Ç)]SS‹#•¶¬U÷¡ÂèÅæ4°ûÉ'Ùzá…üîe/ƒÝ»Õ%¡¶ü' ~›xëc¸×c`ÝºèØ€z. jVB1ä¥.#iYø¾¯Â¡RòPÑ3ôô/šAÍBÔ9qtšB±>)Tÿü¼é¾àSÀ„Ú&ÉdÆ”DZ„ÁL´}ær¹è·SÇqʽÉô m<¶ŽžÆ®”øZÈ»‚³GÀú9x;À¸Œ60»!s?8Î {:®ã!`0h>L¹[e<¦œK4;ÂòQ¹HõÀ¨Ki`ÕGM?‡Rb4==âz=µ[¿ŒBJ/ƒ,ƒ_hñéê:.(±ÿØq´K¬#â3(t#EOOO—ëzz±ÏT#SÜ6¤ôÓq˜ò”'{k¦4˜R>¨íP›J/èxÄh#¶¿ÞV‹Uú·Ò‚Œw ðgI(âa«}úÕ&ìTP}ŸëÙ)Ôo©M7OtߥRjuRr¡Ð³Œ:(ý†ÚYÏXÑ÷‡žbQÝ6´haÛis‹ß×Q>#‡X¹úÞÔ_­¢HoŽÇm@»ëz¤)%EÔ‚_L(4ã"¥åQ™vEùzY\Ì)ÞÇen"XëŠûžQü¼®âÜüâóɬ8ïbÙ¦æ=ÅÍ×=ç¢ Wz’ïOJe::z^Ñæ ŒC‡U:SŸ¿>—©ú[XE—x#§~òmÛZé<«bÌc–1ÑïÎCó> þ£> î zžå/„z¥&A¥©©‰¦¦&¶mÛ-kmm1ñÐhÙ¼y3×\s 6làÁdóæÍ4T„ß ×û›‹¿IÊJ•­Ó1]uˆ+#ñ©h]KK ù|ß÷q]wTñmÇE¥{I|F¾i–|µqå`¡önÑ3}«e/†OâÜÖ¦þûoÇ…  Vס8Ó8B{Ù˜¦š\1{8üÍ.Ìÿí€Óv•Î+~mm¥ÙÌZ¸‰A)iKüšU&«®Œ“Z)fe*¦|Ä}ÌõµŠ7¾tÝb]- vï~=ËMžChlÜ‹ê±ÌnÆcŸÌ‡»—ßÍì+Õ÷*y‰lÛŽòÖ‚0:ÆeŸEšžXû˜ÓßOó†•<ð­Á}CR©’ˆžJ•žÝµäĆdÞÞÀ;ßð5v£½I¦ýÛéËf´k¡Rÿ®:9žv³vQ6ØAy£f¨!!]tzˆåqÌÖk¯«¡ÖÛ#|¯v¼jq¼ŒÊ©¬G¥ÕÒ¬Ê^kÙ>¾¬¸ÜýÁž •BJ¬Œ ‚;[8Äs.0 à  G]Ó4KedžÌ|ÃÇ4M|ßǶíh€?H$ õ¼]Ÿì»²ìܹ“ñ¡.ÂÌeBÚ¶¨ŸpáóEð*»êå)“@M‚ÊÆÙXL´:QTK¶¹qãÆH¨Ñ"N­èÉ=×¾®"à¢Oøù ßôî(ßGý`t§þÜɆë44`eÛ#»nŒ2B'“ŽgˆS-~Xl•uÛ?a~òøø5c;¾i–o£=rª]£áÎÕ.{Û ¤gTW.‹ *î‡C¼gή…ÌO£Pp†çž{?jê×ì`¨D¸ã²Ïg ñPcñK¨`+îaÏó0M³þìPêˆÉ°OMÑì¶yüá·'óú¶è5‹ý«T KO:CC¢ÃMÄÕ*sp …L³¡è D÷}ÏóHÇ\+s¹¦iÖtŒÑY~“ɲIŽãÐÜÜL"‘¨ù9­'!vRK;tmÝJמ=|õ§—‰nÛj<Ïò¬²ß\„Ú™Ìw'¨g¼ž4ˆ¥Äc€»‚ýž S… ‹‰ØÕà¯Ç*EÁŒ+cK3jƒÚBÄDÛgd‡z^¦ƒ²C›Áž Gi”iÝV %. 5YC{üèÐø¶mãº.ÙX?^—¡Ÿƒ®ëâ8©TŠl6K&“‰ÚŽVÑÛY z_]f2™¤³³“L&C:ŽÚ»®ë’H$H¥RÅ0ì¦i–µ“õçL&C6›%—ËEÇÏçó´µµÑÑÑ•­ËÐaõ}£—éè5Ùl6§Ð:Ly.—#‘H†!¦iò«_ýйsç2›˜¬¶-'Z²¸xí3™RSG.Ñÿ B=R79T4c5Hí¥¸èÈ¢XF«d2ø/ûFXJÎíãûÑCrB!f+cðp]pùé+ªÏ`CÅÕ¯E\ŽÊ0M0×̓ÀÇxã«á¯ß5ûrPÔȘj…7=>O}Ñ!â*~Ó4%wŠ Œƒñ4h5þS°=§ö÷óôßž@:i/…ÚnÍPª ºCDa\â…B0 £A4Ýé+ e±@Â0IJ,ÚÚڢΡmÛAu¿|ï½Ìùßÿ儇¦åŠ+¢g"‘ˆ¼hÃ0$ Cš››éèè •JaÛ6aR(¢°P…‚ŠQ¢;°¦i–uj5ºãQé-£££ƒd2I"‘(ëL…ÞâhG¯mzžG>Ÿ§‘cžë06šášGA•ïF¬ ¦C—Ïfß¾–æR¼Œ‰F‡ZM_<’ ÊC ³Ž‰xwº®[.xjçx¥ ;D÷·a€—{¿PËL³ä/ŽÚ‚PbÌö©ßAº!2C†z´ØP)ZÄ ÃÏó‰Ùl–T*Ewww$.èÁhýŒjii‰DÇqÃ0:žAâ‚…aQûU·m›\.-×íS½eY†å{Óÿ§R©¨ý©… -æè¶tOÑsYïAÙD%Nq¸öPGGG´m¼•ek†¬×ÇÓ¿…n/ëï•}‡{;wr40ïN Øó¼è{|¼Ö0 ‰„ŒÓ uͨ•öövúûû¹îºëhooç†n([ßÔÔ„W9ÓŠƒ»vqãÉ7ò%¾¤¼r9èì$L6ÐY16+†Âêìì$—Ëɬ¿ Ʋ”¨2[œ òÕ|h…Ñt{À¥ªÇ(/FA¨KÂW@cv>¶‡“O.åÉ*æÔ¨'tÇ-ª{ÏjË’É$ŽãDB-”€êT%“I,Ë"ÚÚÚ¢ÙQ†aDŠî„‘0†!©T Ã0p'Btq-|ôõõE¡´ ªý¿Ÿý,ø>…BoóªéÎu6›D“l6uæòù<¦iâº.–eÑÓÓy4莨çyø¾?(Yk‘˜4ì`}1¼¦eÛôtwÓ–L?#»H}Ý13ýš=O›£” @)y²A)™®nÆÄ2§PƒMIJ3w+ãêæq|?(JVÉØönl}P\Pyâ xµHÆ–uÄ>Çóèzè$Ê…]N)GILIQŠ•Ÿ«8/ŠG×Õ­(O×Ìϥ§¾@¹(”§”3¡(FØrfèzè04F옺ñkPY}užý[ë<Fl¿6JñùõµRî-8Å“$‡ð®=uö‡ä›\×UƒŒ–]þ;%Š–rÎnn,¥Ói3eÒ­ L< v-Pϲ)Šä>aF •žÅP SA$|ø¾O:.k£j …B$@„aH"‘ N—y(wttàº.A1?°ö¼Ðå %*ha%›ÍŽè…lÛv™¡=”È Kh}-`Œf¬NB£Î<Ïãœ?.Œ¾Ç•Ê>‹ Ô#5 *×^{-wÜqGÙ,ÆÖÖV®»î:¶lÙÂwÞÉõ×_?m'gôöÒþëvµ !ŸÓÒù@Ï.­e–¥0:t´°:¦‘§Ï|zØõžç‰‡JÏ+ñP©S[V)íOü3”rEù~)rN·ǶKåZÖàhx•ûUG§ÏÐëMS•?Ž>­Ï¶•ÐÇqJûé¶yåù:Ni?Ç©œ½¢Ž]'‘Pû‡¡èvc!¼ÿÓažr«æS ½8-Ä;hº³Ç;žÚõ_w>u=ÃN{ŒèÙ}–eEžù|>šé§ŸKétš\.W–hXw&ugu(aA?×âûV묦Óiv¾üå\=gî1ÇDž“ñmµXG¯w6«Í¶ÓTKK ŽãDŒeY‘Ȥg%ær¹òޝe•r–år|kÇÞ꺸®[Ö)éZ£'î)¨ð¥Á¢ ¥AxDµÒ\ã·Lµ&ï@ìóPÑüâ·TµgkçÛêd® ÊcÎW+#1DyCQ­É0T=âŒÔ쯥ñ2ª]ó¾!>UFµ±¢ø±;PB‰vªµ2ú†(O£s{Xåe~­ýk´Î¢p¶“I4Pª­Q’ePm–BÑɳ–ˆÌ‚ Œe?Y¯œœ²Õ$õŽ÷·‚@ý54<ÅÅÏå’K¾Í'>q;w^Ê×¾¶žo}ë0¿ýí^N=õx®¿þ÷45áŒ3îÅól®¸â Òi'Ê‹¤úT&žgñ£íàw¿{1ÿx?–•§PPÏLF=Wô>ª¯T(˜¤ÓN”â²$“%‘£­M5/ …R•ÐëËm[ƒÒËÆÏU7Iu3¯JZÔÑÁ*tßørÏSÏJÑD޶Z9.(~ž-“±…£‡š•mÛ¶±eËn½õVÖ¯__¶®©©‰Í›7³dÉ>ùÉOrë­·NÛɬéïç÷+~ÏÉœµVƒ@½\*¯zPBp'KÊèƒV »ÉDÄÆŒ7êôÄz=øîûJäËdTó££”WÛ4Õ=›N«}t9¦©Ý4–¥éõà¾m«õú~O§Õ¾º1¨…]‡D¢4øª™ŠÙÀÙl4fI"¡¶‹‹'P/*?ëcÅ¡¦9x]÷x¾_.TTîW­Œxú!Ç)]3]Ý)Ð}( >ú7Ñç?¯KË £¼•âS¼ÐÒË—¿vÜ÷ÕÑ€þé} áÃ{Xzõ¾ºù^×L{¯Æ/zlèÁ~Ã9™L–y $ 2™L>0—ËEƒûZ ñýòä’:T—ö:ÑB@¥k? =;n"g½ø”Sø÷·¾•e×\3þ†¨§@âq‰]×fQêueFYhÌÔØl*•"•JE¡ZZZH$cš…(TGß«Q¨®$jÀ¶›òD²õÊÑ;àÿgïÞãÛ¨î¼ñr¿Ø“@B0 c.NiÊJM)¥Œº\{¡”v»”°O#ív-í>i¥í>¥-Ï^¤’Ý–vªÝÐÝm—xZZºÒjz‚¡©‡[ã%ž&qC’xb‡‰~ŒÎh$˶,ë2²?ï×Ë/ÛºŒŽFóÕœ9ßs©ÆW¤Ø‡å~-ï´pT’å¿\%¬dG¥xög,–íø¡ª¼>"ª†æg›¿ÛsÄõƒ¸þ1MçzM$¾÷½8ujV®| o¾Ù…)SVãò˧A–­[âùçŸÇ¢E‹°uëâºënÁ×¾ö~<ùä™X¹òL( pË-ïB(d`Ïž½øþ÷?ž¹º¶í$9þíßœëBÛg ‰M“°u+`YKH¸ý…ÝQn^ɤó#ˆ*¬m;ו‘H6Y!:²‰ÇˆëMËr¾§t=Û)N\ßézöú4‘Ƚ<ð^³Šï:q½+®“Iç;Qü/®±ES\¿‰ö; ·Ãœ¸T”lg;ϲ·9ð¼%Éù-:ö©j¶ž÷1ù×ø"áä} qœ1“hÂ2MÓ™òk„ó¤¸v…²Ü"çZD׳±ÛÙéÄ×_߉oû .ÌŒlîƒ$IH$¸ñF]d!<’ô%À;ÞÜrKîëöö­oJRîõ¨¸–œk3Q…’åÜdÉXˆ„…·Ó]þRy"A z­BÉš‘ˆÇx;ßÏ0roŸ%}ߊâlOLKïAÁÛPüÉðü÷ ^C$ÊEÙB!àÃ~Ï>ûxiÔds8ïþó°ëò¡kΈk"¿+yQúÕ«Wcpp0ç¶–– ÔìÍl¿;Ξw¶û"á|ñyO†a@Ó4wAUf>‰*ïªßœÀ{„~ž›Ñ€3‰¢(9Óáä£FDeG US'x+[¡P¶çI¡)ŸÊ9””³ÖÞH’¬Xñ+·Öº˜uAÞ ˜‹“¿›Žö¥û¡Ü­xÏò@ €T*å&RDÃ~ pâ€;BÜ&¦î ‡Ã£žÇëò<_ƒ1ïb!Q±P¨aÐu𦡳³Ó]g%~úÓŸÆÁ™3±û'?Á…†)“Ts|3¡R:7áhÀi¬­ÃC™h"3 ¯_õ:°0_4=;5©ª2™BT ³¾2kÈmbô„®;¿S©lã¾ee“Ñh6y¡ë:b±^}µÀÜm)Š‚H$â¶%ù©cÎHjU®J;Òut~‚Ú'Ó»ÛÅßÞÛ U?%›ò–K<¯˜†ùå‚Aàî»_dzÏVvN$‡Ï<œó¿˜S\ãù]Q •¦¦¦!‰’–––œÿÑÓÓSÓ7Ó?¿'¯H< D£PUç‹:wúÙí9É %ªž‹ßxøéSCjG{ö,A(¤#•’r*¤ùÓu‰Ê­wv¡uzFÈËÑpž”}N»íÌo"˜h‡´²¼/!’§Á`ZfL}<w/J;;;s¦¿Å:^âÿ ·V‡ª:_r5ZÈ»NHªˆ„—¦iîâö9‹™* ú% ß™?q]‡CϵŸþÙ§Ÿ€É"Ÿ±m±X [mþ˜šS7Õu§¾:ÑNODõ`ùàБÕbZ­`ˆþå ”“›Ód§Îã%!ª'±X Á`pÈâíÎcd$“I·# •æØ±c¸äÕ(€gx§7a׺&ß+*¡ríµ×býúõØ´i®½öÚ‚Ñ4 èè¨í†ó^ý °ü-N2%ÿ'¬—žDÁÑ32c«=h¶í ¹ýŸÿ¹7ßü1 d×>1 çáÃM3åÌ-KDe±€ ܳy3¾ÖÔ åç•ý%Äâï¡PÈ]ä]UU¨ª EQ I’›pñšT«£u‘«"oï°P(èìì„aC’"š¦A×uÄ3ÝþĈ¢ÿóçŽ/þå_⬶6hšæ^ uvvbÉ’%µ~‹¾·ê§«0xí –ÈÜWD~cš&>qÓ'0£g†{[*5úC1‰‰ø5á •Ø™û•ÌíFæ6;sÐó@@Ô³--óœpæqRæ·šyL"s¿”Ù– g¶2=ó/%s»(WÔów"s¿÷1’çw$³}És»xŽ”yo¢\Èü-Ê¥f~ÌLÙÄmÞµÞÏs½¹f;ó%S^3s¿x®XæÆÊÛçâ3°3ϵóîåö¾ŽwÍnïûô–1çxÉ{ÏVÞëÊ¿éÈÎö(¶gƒF2ï­yÙ<L‚èKÎ…§a»‹/öqþõ±ÇrmÍÌB¢N:v !k>°gáK8w0Û$-.eYvíJ"?)*¡ÒÒÒ‚µk×âöÛoÇÚµk±zõjw„ŠX°~ãÆ¸ûî»köFLùÜyh:”>ú¾œ…¥½ÄÃ08B…¨ l³_›_½óø¸çöHÄ9iÞrËݸå–/#ÉöæK¥|ÑžH4i˜[Ÿù%–.½ Àø*¢Ñ]Lÿ”L&‘H$Ü^}bárï(“`FfÐȼS2ªªŠ@ €ÎÎNw °`0[¬ø™!Ë2n™9S]MMîÔÑhº®ãÖ[9ßhZ^oÁ…w\XëbQîüîÞ‘Ñ¢w-œr Ù†rÑ®{j!·Á?¿a]$=¬ÌOÀóܲI±mN"A÷lC$8D&Žl#'‘ÒlbD$DC¾(c$³=Ùd…Žl"B¼o‘40=·™™×÷‹äƒ·œjæ>NRÄÌ” ž×»[Ï”ž×û0ž¹­ÙÄ”xm@ÈóþÔ¼ßRf»ây²g_‹×Ÿ›ø\äÌc½³ý˞NjmèyÛò¶ç±â>QÆ8€vd1&€÷-\Ø‘² MŽCÿüf;—gWK‡ÓÄüÞ÷ I?ö14î߃Ð3ëñ¹¹bµúá:㎰>( Ïš,Ú¹ Ó[§ÚÛ0J¥œøîˆü¬è5TÖ­[‡¦¦&hš†ûî»/ç¾––lذ¡æ£SvÚ‰9³_”ÏÃІž×DïÈx<>ñ¦ !ò)Àüþ™øÝ¸·%NÝ4™´aÛ‹Ýø¼‹ÍQõØGe:`Ú6Þñަqo/ A–eH’„`0Ó4aš¦»`<0§ëš$dYFoo/ Ãp§hK$‡ÃCF®¼ïÞ{±}ùr¼”HàOøCÌõ,nÿøã㓟üd­ßޝ5l®ø:FDT˲ð{þßxXÿu Àâp6d-8‰À¹Môñ£G€¡£јŸþÅN~RL”ŠìHÉSÖáˆ~NÞ†ÿbE–i8ùû©PŸ+ïèž`‘ûJ”k,—²É¦bØpkÅ–IÐ3Ï H{n`Bedâ` ‡aF€ÎÏ= X§¹=mÅúdÁ`'ï½G^{ ¯þó?#‰ [¬oÎIrž—¿z,æ\¸ŠiZEO@]wFˆD »~¨¦9ÏœÛl;wUzÓt•¤ì‚LÞé,ËÙ†$9ÏͼϜ)µÅë{y·!¦‚«µ{ç<b1w$€¡‹šXVvZ ±‚|þ´â5ľs·!Ê!öMþJóâ1^âóDÂk¸ûÅ>µ3#“Ä~Ɍآ¼Þ÷ž¿Bû£PYiDŠ tMëÂ7]6ä¾p8ÌëDª cZ”~íÚµX»v-ºººÜÛšššÐÖÖVë÷À³ÍÏbêÔ©€,»Óç³m›ÁITe‡¦¼àƨ{¥RpYá;þQ,¤‡ïÇš»ÿŸT¾<îÍ©ª I’`†;À)FeÙ tŸOu&zŽišæŽ,²íÜÉHæŸ{.ö~ðƒ¸ÀÜgž>ô!@oo/.»ì28p Öo÷lÛÆÎÿ>‹Ï÷Ñ  I…,¼ò_2Ó¢¸D/ï¶EwÞ‰DnÃ0´q%ªš{ò Þÿóyt=·‘c¤ÆÑ@’ß0bšÎÿÞÆ¤ñÛ*öörí5Ä~eE«¬,ËBWó$:TàþLFB4êGµ¾ýKéÃTÊÑ\¶#϶³y¼I«J–Kã>(&YUÈpŸ ๶7Y|láÇܬ_k«˜"úöœÇˆN ’$Áþå/ñõ³ÎÂÕ¶3×m€+˜{Fn’ÄKŒ‚îû6Î=¯å'>ļ֦é$Fò·ãý®÷å·m)Jîã†NÙ’}n~BÂû]Ïn'¿qM\Ћsi!¢î¡ªÙÇ{ß»8?‹íxßSþ6òŸãýœ¼±,g‘Uïct]|ðÙ÷æ½?¿Ž#ê ÞÇh™E²²‹|8^š†kvíÂæS§@£“fÿsVnT£î!$X,†p8Ì*ä{cJ¨µ‰2œOnû$ð_ïà|¯æ_ÇéºÎd Q È}ÙEûD]J–IRØÀJä;üò|ERqÖY³ÆôTш.ILÓD(rG¥ˆ‹SÆùˆž‡Þ {Ó§Z–5$¡bš&þvǨªš»°¤mãÏ-ÂO_|±ÖÅ÷­W| ,ý­­ÙFÑSÖoÞ†!¿.,>Ñû2ÿñŠ2´á _08zp¤†! Ûà’[~#Žiæ¾çüÆoÒE<ßûž½ µ‰ÆÙÑHù 3æ'¡d9·áÍ» Ûv^?¢Æ+?¹û ”²ŠÞÊ¢1)ÿûElC”ÀÅMM€O¯÷üâÌs¿„…¦áœpW2;š¤èF}ÓÌ#õ.Ïï=nYμ¹^ÞòÀÐã(|l†—"î½Ç–8>ER– oC|ï‹ÈáŽOqG£¹ß‘Hn4ºP(7)8Z<*G 04᛿ bÞð‘bMÄôpÉiñ¹æv‰Döu ÉÅáÞ‹h˜÷ncÏ\õê«£_“ÔªÆUÀn š&œõ@,t펖N¥°?q§0uƒÃO›0ÒBÙ#%S ®~<\2g´×Ïí5óßk¾‘Þ?0´CD)ååéuŠÙÆh)fVÇÉO„ÒÙ‰|óvïî­íoaþÜKU…eˆœ‰DÂ`2…êFI ¿:mð4·«‰®ýî ƒL¨ÕÀ´·vaV¦rá¬ë:,ËÊmh#¢ª‹Þb;`5­Âof<ŒŸ1™F:1ÅW<wãšçÜÕaʲ,X–5¤QÂ;r$¢(«*n>yÍœ¶dXÓžŽÙ³g;ÿˆ†MÛvN Þ‹L§ûíðÆ2c<£¢ŠyÑ.Ž‹i m‘ÒüÄÆpÛi;Å4®T«f´mT¨¬/®_¦SFö/‰·AÌkS‡mgÞE£» ¦÷˜Ÿ`É?Jlä‹Ç³#Ɔ;‹mZt¨Þñ9Z¼Šû£½ßѶÑß_Ü>Ppª‹üdH4*‡HNçß/¦=é½ç'qò-Z„Ç—/ÇA½fÿf§ öKkùy%G;‰ŠÔ}Í5øýÃ׺¾gxëÄ\Ð䬟" išá®wÍ„ Õƒ •P |Ó qÁ[¢ê2·ÓNX˜µ{·{ )x×S ¢ê³‘YÐu!ðõïGð©p;4mô¶ ¯p8ŒP(äö&ber>íííH&“PÅfU\©ªêŒb‘eìüÛ¿Åϲ”«gfÎ|×™ÙEÇò{uQÍühϸè™ç‘ºêÝÅ<9]wbVŒØÊOTŒÖë(ßtÅ~_ø|zɪiŸå<i¿ wßXG/ð³»Aæy€, mÒ4 Éd’מD5fXÕÓ‡Kö8ë‰6"ÑVËkIªSj]€r:ÿÔî(èÜÑÿöi(ˆ¨:ì©ÀÛ_è¡+`YùS®'`p7¢š²ö"`JCvíºã#"‘ˆ;ÊŒ`êîî†eYˆÅbñB×u6diÖÑYÎÜAbÄ“)D¾ñ‹Wp¥µ$gö9Nœvvf <'U×%&ä÷žSpp•iš¬§ùX²HÓ4hù=p‰|lBŒPƒa÷Ïø$þhõ ™®Ô0 $‰Ü…ƈ¨:fÓìʼn¹s‡¬ï‡ÝµUˆ¨úLæt@:h8ujLë'‹Ž ñx¶mshv9ˆ9Ûëü‚? B–³kg% X–UU‘H$x¬áâW.Ævl½7;UÝö9SðÞí‡ ÿþk¾û‹;$©î¿¿Éÿ,[Vë"ø×.±Ÿ~ѿϽY×uNÿNä6€“3÷ã茣9·‹uÙžêÅ„¡böòvκyîý™†&Q Ìf<YVsÖš=˜‰¨vlöiÀY' ­è!TŒD"@ à6säAˆ¬óØ—Þd¹iš‡Ã\3«HóöÍ«uˆh=GðîôO =~>Ô[׺84‰ÈŽÏ™SëbøW0cscÁéßYO%òÀÒ·aÏÂ%Îÿ™ÑžÞÑíDõ`BŒPùe`Ϭ% w ƒ L¢ZؘͷcŸ‘m¨µ, ¡Pˆ‹ù€t¸è7/á@ãT| ¸¸¨Îµ¢§Ç©°, €s±”m‘bÂþi›¡ª7ÕºDTÀ‘Ù‹±ø±_BósàYª‰)Q„ÈæÝ$’)L¨ùÇÙ¯\‚Ý—ìà Æ–e ²Í–ꊯ*}}}èëë˹måÊ•hllõ¹û± ‡¦ÂjΔµù³I00‰Æ§Ôø4§Ÿv¦™;sI<g\•ÉxΟÊ6`Úó¯aióI˜æÛF|¬mÛˆÅb°,‹ÓhÒ˜ˆ†Œd2‰X,†«¯¾ºÖEªŠRbó¢×.B󱝿YE3Mg„à\”ÚvöG’€üåÊâq@  ‡ûu={¿(%nK&³‹† Á s¿¢8¯!^K´YFvÛâvÓÌ݆¢doÛÄó¼Ìe9[q_8 X–óxUuþÎäïÜÇ…ÃÎZáâýzß‹X;\¼žª:•eg;â~±?ÅmÞ÷.ÊfšÎýápî{5 g‰²‰ëËÊ}\4š»?4-÷eg[¢lªê”ÃûÙ«jöýyß«˜ÒQ<(¼¿À¶—¢££¨C¯®•Ÿšš°èƒxåèr?1«ÖohÂ*%>óÏ1Îm\;…¨œÆsÝ)ì]0«—ºõ-\¦êޝ*ëׯǦM›rnÛ°a:ЍÑÏØ7Ï_uYÁû Ãpçã#¢Ò”ŸKk‡†û®ƒbÛ¶Û[™ˆÆo<çOµ˜cü½¸£ 8Ñ4 –e!òâ”J"Ë2$IÂí·ßŽk¯½¶ÖÅ©¸RbsëY[±{ÖV,.L鑈ó¿71"îm$—åÜYä¼tE£¾˜iNüx‰ê³m݆hœ7Íì¶ #Û %óM3»]obÇ4D¸M$Ä{ô–]ÉoF¼ßü$Š·lÞ$—e9ÏûFüí-71•ÿ™‰÷^(1â}â³Iñþ¼I.ÁûY~ÿû,Ñ^ŸJ‰ÏþùóñÎî£0Ú?Sô™D4v¥Äg~çÛ¶aÛ6Û‚ˆÊh<×€3å×;š_ÂÅ8Ý팀k,RÝñUBepppLè5í…øÝ é00‰Ê¡äøÜØ©ÞìM’$!È…v‰Êf<çOåo€?üþ÷˜{楣6©ª I’`Ï­T²h4Š'N`æÌ™µ.JÅ•›Íº[–“˜Ðu§±;w~D¼3ƒZ¡¶$oûb”ÇhÛíÔ^èuŠ™9Ð[Vñ·÷¶ürJ ·=QfoÙeyô÷RèýzßK©ïËû¼htlÛéý WîBûê—¿ý…'€RâsoãÛpæËû &Tˆ*¨”ø´íÜï?và#*¿ñ\w áï(ØþîíngÀ™RšÉOª'¾J¨tuuáÎ;ï÷v¼•ÛH$˲˜DãTr|éÇMÒÙдl#¦iPU• ²De2®ógón›>ÓÏ9gÔ‡Æb1tvvrt ÛûÞ÷>tuuÕºWJl.ϳ1tßx÷¯w;Væu½å’†yMïþß{Ë-èèõô„™ J‰Ï+7¿„­½OA)à’ D•SJ|šfn‚Ý4M¶•Y9ÚmO·ïÂvÝÑÔ—i ú㛄Êàà àŽ;î@WW±nÝ:¬^½zÄçíÝ»_â \xØÉŽæ÷“$‰‹ŸRŬ_¿›7oWv¾”Ÿ›7oƱ+?ŽÝ'—ä|ÙƒA. HÕ×ׇ7â §—÷DUJ|D•²qãÆŠ´ÛN©õúúúÐÑѵk×â•W^ÁÝwßõë×Ú{qΜ9hnmÅ™»Ñ|ð ;4à ñdxª¤ŽŽ,Y2ñç˜.5>—,Y‚-4ã‚Ù¿Ê™¶"æ T¢ hjjBGGǤ˜R¨”øœ9s&:::Ð?u>¤³ýûŠ¿üËÓ†}¼8Ÿ²ç•CKK ÚÚÚ0cÆŒZ¥¢J=w¦çÏÇ“·Ü‚õ1àlàÛ2„ó[“)4> 'SÖmG‹Ï¹sç⺃Í`ߪ¶¦¦&ܼt)N;í´ñoÌçJ­ÛÞ{ï´´´pê®ñbæ^$*ƒ––,[¶lÂÇçxÚm;::ÐÔÔÀ©†PU5'¡Â)ú¨RV®\Y‘º­o*mmm9óðuttàºë®+ªR»dÉœý¢†YGÂöÌ`YŒü•ɈÊh²\t–ŸK–,AÓÑCHÿdÎÉ2³—;UTccã¤I¨”Ÿ"¡2½i:” žž+pâD˰dVÀf'*‡––\tÑE˜>}z­‹RQ¥ž;ñÆu×a‘¬árcTe¬ÛŽŸç Ôp°¨5rˆÊ©±±rÙe˜:Õ7“ŒTÌxê¶"¡¢ë:Lï(Qµ´´àœsΙð •ñ´Ûvtt ±±*€iÛaÛÙåØž*©­­mb'TúúúÐÓÓ“sÛX¦‚h<܈ ÿìÏr†^˲Œh1«9шÆŸKw¼{ꊜC¡P­ßÑ„1®óç €ïh˜?þ°±, Ñh”£SˆÆ¨ÔØœrúé8z°OqÆÚ ɲ¬QùìL1Ã0`ÛvÎãmÛ†mÛ°, ¶mé<&ž#¶aš¦ûšÞ¿EÇ3ïöMÓtŸ7Ñ•Ÿ³ÃãsÞM«õ; š¸ÆÛ68€8ÝQy•#6qèºN~Þ&!v†§z䛄JWWn¿ývwN¾ÁÁAlÚ´Éía0¢ƒÀ”“‡ñê«9ï5Mc¯¢2W|¦—àÀñ³snêìì¬õ["š0ÆŸ'pø‰ÐÖ¶{ØÅu5¶•¤ÔØlnnÆ»™ ¿TaóëÒÞ}/Ñ8ŸH$`š&4MƒeYˆÅb9ÿkš]׋ÅH$ ib± ÃpX–…P(Ó4sî÷þˆç& ´¶¶B×u˜¦‰@ hmmuÿ7 ­­­Ð4 ¡PÈ}ýP(„X,†ööv˜¦é>'ÿ¹¡PÈ}MñQïëZ–å>GÜ.'®OÄvÄs¼¿Åû6 –eA×õœ÷*þûÓû\ñ9„B!èº]×a†›P‹dŒøÌgJVÛ¶'Å÷~©ñÙtàÌK¹ =Q«n›Á|Tmhnn®u1*ª±‰Ó°ÿ¬÷Á²²k`³3<Õ#ߌ]½z5zzzpóÍ7£¥¥[¶lÁêÕ«G]Ü08:s?~ÿûyرf¦G‡Ã\؈¨ ÆŸ'O`þü~NåB\ȳ·;QyŒëü‰Cxýô¹8pà(Ô)9 qt Q‰JÍé‡ãØ³Ó ”›aî´ –e¹#,Ë‚¢(°, ’$!‹!™L"‘H@UUض Y–¡ë:âñ8b±˜û;™LÂ0 ·Þ-çÞS–e÷5lÛF0Sa—$ɽpz‹×uy±†ÓHÓAˆ q±ÝTÊâÓÛÛ[ðoÏåü^Ìâ1ùÏéõÅ6ÄcóŸ3Ò÷hþsÄoñœ‘ž+:©ä?Gü/öG!â±ùÛ˜ ½ºKÏ™¯½†7.dB…ŠbYÖ¨íÅ-óÏÀyîmlœ%*¯Rã3€×Ó'püøÛ 6)Š‚X,Æ‹R¢•›–…q-zí="¦t2 Á`0gC0„anº¢(0MápØmˆWU5§Áo¸ÄXüW$6ÄÿÅ, ,¶í½–$ÉýŸØT ¥Äç}­­˜=ûmµ.ú°LÓ„,˰m’$¹˜ Ãp“—ÞÄçh ùâûC$[eYv·%~DRV’$÷ûDÓ´œß‘Hñxº®yM‘PÕ4ÍMÒF£Q$‰!É[gc§<âµ%IB"‘@ggç×D"ˆF£Ð4 Ñh±X ápØÝOâùÞ}ãM'“I·ìÞmƒAèºEQÜíȲì~†B!¤R©œçzÔ"±-Fü‰ý*Ê(^?•J!¸û# bðª«j}˜UEÉu[8³²,OŠä0Qµ'6 èf.¾껳·s]ªG¾J¨Îb1¥XúÂ~<Œ3s„ØDT^cÏW—.ʼnçŽeF¨8¼ 7DT>¥œ?­©À‰£sÙCou]‡mÛE5†ÑðÆ›,+¹÷»išÐuªªº Š¢‘Nœ{óG,ˆd…hä,4å{OÓD5Öø|ç;߉÷¿V­ª|Ù Ãp“!"á œâ~ ›ô ƒÃŽ3MÓé%ÞùêEƒ~0t‘HH$n2 Â4M79+ËrÎ(3UUÝd¨]&I’É$dYv3b­ïȵüÑeâ»I4,mv§G`Z"XöËçäö,eà ‘?XKšñݦ98¸oè|¿Š¢¸=/‰¨zN?};¾ô¥âßÚÚŠp8 ]בL&ÝFMŽî *¿ÓO?ÿð(×e¦X£È²,7A¡i’ɤ;BŒÈð&D$I*Ø(?ÜȱüÎ#5è‹„Hˆm‰d@¡©èÄßù£ÍÄïüéÿ¼F¹^l=Äû¸ü©ö†›>o¤mûõ»ó½÷Ü|êSµ.†¯±q–ÈÇv~û¦Þ¯X®±Kõhb$T»gíÆ?ýÓ4÷&ö¨%ò‡oÅÙ‹p·æt_Dþ¡> ülßoQhŠýD"ÁÑdD5RLûa(‚,Ëèííu×½°‰¨r29’hšæN+ÀöI$A½‰’d2 {]+ÿã“Û²ßþ¶ÖEð=6ÎùXz>l;àþ+¦s$ª7#¡Ò°;v>‹—4 ™tæzå¢Ú“öI8¼ð8®ºêu5W3U×âÅW I¨ˆ)0ØhCä?¦i©çrÞi¢êK¿=1µU(rG~Ȳì&Kˆ¨¼Ätv¬ÃùÓ[³§áèÑYîÿÁ`mDT—&DBÅ>ùþ8åh÷Ä G¨ÕÞáÆÃxö·Ëqñ⣜FZö> ò£çÅ‘#‹¡ë€÷ºS,žJDþ"zñ±žKT4aÿþÑ'¦ò‹ ‹u@ˆ¨²˜H!ò/³°¾…Å™L.×@õkB$T¬3›Ñ±°bfÃ0ܹf‰¨v¤ýú÷/A àô΋h‘?Ìxn+N›÷ÞœéÅBôlø!ò]×Ý…œÙ1¨vúûçc¤a"‘¢iÂá0‰ˆªLÓ4ž'‰|Êf>¹_|Âùß¶ÝÑ›DõfB$TÞñrô=ŸÆ73•[.¢Kä/^xN5LÅ;Þ± £'ò›tC‹íB4š½MÓ4ìáGä¢3§D ò7˲H$F9Ê“¨F$I⹒ȯsfŸ‰@h€eÐuÓÖRÝšRë”ÃÀÖéÏÞ ;¯4‚ˆjïÍyoâÐÞ“îÿbN"ª=Àá§Náµ×®È¹]UU.FOä#¡Pˆ…ˆ|âÕW—¡’H$ i:;;yJTCl %ò±eÀX0wîUÀ5;©®Mˆ„ʾ_œƒyçöp’óJùƒôº„ë.Ú ÀÎÉÞzD>ò?Ïâ䝿æ¬bYb±/D‰|²,®½@ä#³fE~ÛO @0ä5(‘°q–ÈÇ^¦ïÏvL0 ƒu\ª["¡r iÌŸï$T‰×i ò‰9‡NàÙߟ À9YŠ©„ˆÈÞœ‡7Ž5æ, (IŸD>‹Å`Ûv­‹ADW_½ÞåÄüïl"ª=˲¸~ ‘™sŽà’ßóž4Ô}BåÔÂw ©ý-¼ûÝgàú)D~Ò¸ã˜>å8'6ÙsÈ?ÌÆåØÓ?_øÂ%îm‘H„·D>aš&Âá0‡ˆ|Ê0 D"N“Iä¶m³s-‘ŸÛãå;ÝÙvKõ¬î*3¦,”Ÿà‚ ¦à1"?ùè½âš?à4Ô²‚Käö °âí?ʹ-sª"ŸH$µ.@’$v"ò1bŒˆüÉ:« æ¼ìümYl¢ºV÷ •§ï@¿uÜýŸÉ"ÿØ•NÞ~ 3>‰|äèTà…_µ»ÿÇb1˜¦YëbQF4åè"ŸÒ4 š¦±nKä#†a°.Käc3^=‚Ù³gp áIõ¬î*gmÝŠÀŽ@QŽN!ò™WgÆ€ÔÛ¶‹Åj]"òØ6íM,<{¯û¿ªªˆF£µ.Á™î‹#TˆüK–eŽN!ò™`0ÈŽD~eÓzŽaióº®3Ju­î*ËÀ’Óv@’$ض I’j]$"ÊØ8ïÃ8rÆ4àE'‘Ï쟺—€Ó£O×õZ‰ˆ2$IB2™¬u1ˆ¨Ó4¡i¯;‰|†øˆüËÜ`é<\ú¿æp:óqŠ>ªguŸP™}ìô#7p*·ì‘@ä/‹íB,ãB×D>cÿzæeFu*ŠÂÑ)D>’H$Økȧ¸v ‘?±#‘Ù0ï¹cX¾ü4væ£ ¡î*;,À¡ÆF6ÖùБ#=8ãŒiPU•ÉN"Ÿ±÷ÍñéÓ¡PˆçQ" ‡Ãĸ$ò/û(ðÊ Ç0oÞÛ9m&MuŸPÙyhŽM™ÂÑ)D>tÖY?Á¥—Naµ. åip3®ºêbÎâ׊¢ÔºHDàøñ㜶„ÈÇR©T­‹@DDTWL ˜òú .¾x.b±,˪u‘ˆÆ¥î*ûö½…ÆÆW9-‘qnL"ÿÙuÚ,_>ˆH$ -‘Ïp >"zæ™g8M ÑÙ¿F‹ôdÙ‰ÍÎ|Tï¦ÖºùúúúÐ×ׇ––´´´Œúø… _Àm·µ@’dŽP!ª°±Æçõ×_×^{ ]tQ­‹N4á5>ÌÛU½’$±BKTAcÍéÓ§³NKT%cÏåË—#׺ØD“ÂX㓈ª£”ØÜ2UÂnS¦iœaˆ&_PÙ¸q#n¾ùfÜwß}¸ùæ›±qãÆQŸsúé§CQN)DTa¥Ä§Àùl‰*«”øìèøb±ÏŸD4žs'UV©×ž’$ÕºèDÏŸDþTJl.<´½ö"œÓzŠ¢pýš|•PY¿~=î¾ûnlذ<ðî¸ãôõõú<Ó4‘L&k]ü‚ü~âïëëCWWW­‹1"¿ïÃÉ¢”ø|õÕW!I’o/<ý~luuuõX+õðý1Y”ŸÉdÁ`З=mëáØâ÷£ÔºíD0‘ŽA¿Ç{±&ÒgR“9>yLûÏDùLÊe²Æg=Ô‹5QŽé‰ô™”C)±ùÜ”íxëûiœuÖVhšæ»ö!¿ŸKêáô{¼ïÚµ ûöí+ë6}3åWWWšššÐÑÑhkkC[[ººº°zõêaŸgY~ó›ß`åÊ•µ~ mܸÑ×ÃS·nÝŠžžžZcD~Þ‡[·nÅ‹/¾ˆU«VÕº(UJ|îÛ·/¿ü2,XàÛ/?[ ë:ÚÚÚ|;ešŸ¿?Þ|óMlß¾½ì'M?*%>ûûûñþ÷¿W_}5>ô¡Õú- áçcKà÷GéöíÛ‡îîn¼õÖ[µ.JE•Z·Ý³gî¿ÿ~_~vcáçcp¬üïÅ*æ3aÝvøø|óÍ7ñâ‹/â¿ÿû¿±téÒZ¿…q™LÇt½í3uÛ={öÔº¨WjÝöþûïÇÂ… ±páÂZ¿…’ÕC¸Xå{¦˜Ï„uÛ‘ë¶'wNÅñž4Ô¯²|³ïÚ‡ü~.©‡ï?ÇûŽ;ðÜsÏ¡µµµ¬ÛõMB¥§§gÈÎojj5K8uêT¬\¹Òw)¬X±Â·e€ãÇ£±±Ñ×eôó>ܼy38€†††Z¥¢J‰ÏÇcêÔ©Ø»w¯o???[ÐØØˆ×_¬uQ òó÷Ç¡C‡ðÒK/áÔ©Sµ.JÅ•ŸS§NÅgœ'Nøòóóó±%ðû£t»ví¶mÛð¶·½­ÖE©¨Rë¶ÇÇÏ~ö3_~vcáçcp¬üïÅ*æ3aÝvøølhhÀ®]»ðóŸÿ\pA­ß¸L¦cº^Œö™ˆºíñãÇk]ÔŠ+µnû³Ÿý K–,Á’%KjýJVuàbM”ï™b>ÖmG®Û¾5ýX´øÝxé¥kqøðáZ¿!ü~.©‡ï?ÇûË/¿ X¶lYY·ë›„ÊÀÀÀÛŠÉnýüç?¯uщ&¼RâóOÿôOñ§ú§µ.:Ñ„WJ|þà?¨u±‰&<Öm‰ü«”ø¼æškpÍ5×ÔºèDë¶DþTjÝö‰'ž¨uщÊÎ7k¨455 ¹ÍÏsØM&ŒO"ÿb|ùc“È¿ŸDþÅø$ò'Æ&Q–o*mmmCq``À·s°M&ŒO"ÿb|ùc“È¿ŸDþÅø$ò'Æ&Q–o*pç\ëééA__®»îºZhÒc|ùã“ÈŸ›DþÅø$ò/Æ'‘?16‰²|³† ¬[··ß~;V®\‰-[¶`ݺuhll¬u±ˆŒO"?c|ùc“È¿ŸDþÅø$ò'Æ&‘£!N§k]¯¾¾>ôõõ¡¥¥…ÃÆˆ|†ñIä_ŒO"blùã“È¿ŸDþÄØ$òaB…ˆˆˆˆˆˆˆˆˆˆˆÈo|³† ‘_1¡BDDDDDDDDDDD4 &TˆˆˆˆˆˆˆˆˆˆˆˆFqÚW¾ò•¯Ôºõª¯¯===îbLÃÝMMMc¾¿œzzz0sæL̘1ÃWå„išÄgœ1¦2TsÿQýO|Ö:6‹)C­ãÓå£ú5R|úéØ*%>k›~Û‡4qT*nku‡òÃ>Ä믿îÛs‡ß¯{zz°mÛ6ß·ÛV½m-M%¹ë®»Òíííé5kÖ¤¯¹æšô‡?üáôÀÀ€{ÿƒ>èÞßÞÞž~ðÁsž?Úýå´sçÎt{{{ú©§žòUù¶lÙ’³¿ô¥/]†jî?ª?ã‰ÏZÇf1e¨u|ú¡|T¿FŠO?[¥Äg­cÓoû&ŽJÅm­ŽÇJÄwµßK¥ÎÓüލ/•¼&õS|Ž7þªù^*yËø¬/•¼&­Å±P‰kW?;ëñ3ñ;¿ì“»îº+}×]w¹|Õ(¿ß¯¿ô¥/¥¯¹æß·ÛÖ¢m •ìܹ3½bÅŠô–-[ÜÛ®¹æš´¦iîÿÞrË–-é+V¤wîÜYôýå$ ïå‡òy÷ÙÀÀ@úšk®I?öØcE•¡šûêËxã³Ö±YLjŸ~(Õ§ÑâÓOÇV)ñYëØôÛ>¤‰¡’q[«ã±ñ]í÷R©ó4¿#êG¥¯IýŸã¿j¾—J^ã2>ëG¥¯Ikq,TâÚÕOçÎzüLü®ÖûäÁLæ3ŸI¯X±¢`B¥ÖŸ©ß¯ER$x •×/ñ]‹¶5®¡R‚¾¾>ttt ­­Í½íÚk¯ÅÀÀ «« MMMèèè´µµ¡­­ ]]]EÝ_NëׯG[[V®\éÞæ‡òuuua``k×®466Â0 \{íµ£–¡šûêÏxâ³Ö±9Zùй¿FŠO?”ê×Hñé§c«”ø¬ul³ŸTŠJÅm­ŽÇJÄwµßK¥ÎÓüލ/•¼&õS|Ž7þªù^*yËø¬/•¼&­Å±P‰kW?;ëñ3ñ;?ì“•+WbõêÕ9qXlùªQ~¿_÷õõaõêÕhllw:2¶­9˜P)AGG6lØàþ?88ˆM›6¹WOOÏyïšššÐ××WÔýåÒÓÓƒM›6!¹½ÖåëëëÃÊ•+±qãFÜvÛm¸ýöÛsÚ‘ÊP­ýGõi<ñYëØ­|ÅÜ_#ŧÊGõk¤øô˱Uj|Ö:6‹ÙGŒO*E¥â¶Çc¥â»Úï¥Rçi~GÔ—J^“ú)>ÇÕ|/•¼Æe|Ö—J^“VûX¨Ôµ«ŸÎã-+ãs(?ì“¶¶6ttt\ߩ߯¯½öZ¬[·ƒƒƒèêêr"á‡ø®eÛ*ã´iÓ&Ü|óÍèèèÀêÕ«d³u^Þi´ûËapp·ß~;î¾ûn7›XìëW£|}}}nÖríÚµhiiÁm·Ýæ¸#•¡壉a¬ñYëØ,¦ µŽO?”&†üøôñ5žø¬ulSÆ'W9ã¶ÚÇc%ã»Úï¥Rçi~GÔ¯r_“ú)>ÇÕ|/•¼Æe|Ö¯r_“VóX¨äµ«ŸÎã-+ãs(¿ï¿}¦~¼6úúúpß}÷aÓ¦Mn2e´2øýÚ½edB¥Dƒƒƒ¸í¶Û°~ýzÜyç¸óÎ;Ýû e?½®Ñî/MÓÐÖÖæ@OOzzz|Q>À9Pï¾ûnttt`ݺuX½z56nÜ8jªU>ª_¥Æg­c³˜2Ô:>ýR>ª_ÃŧŽ­ñÄg­cÓ/û&¦JÄmµÇJÆw-b«çi~GÔŸJ]“ú)>ÇÕ~/•ºÆe|ÖŸJ]“VóX¨äµ«ŸÎã-+ãs(¿ï¿|¦~¾6ÚÚÚ°aÃ<ôÐCØ´i“oÚmkݶƄJ‰Ö¬Yƒ––†‘“¡œƒ-ÿCp3]£Ý_.ƒƒƒ¸ï¾ûpß}÷¡¯¯=ö{ì1_”¯££cHÑûÿHe¨Öþ£úUj|Ö:6G+_1÷—ÃHñé‡òQ}.>ýrl•ŸµŽM?íCšx*·µ8+ßÕ~/•:Oó;¢þTêšÔOñ9Þø«æ{©ä5.ã³þTêš´ÚÇB¥®]ýtîoYŸCù}Ÿøå3õóµñÆqß}÷¹ÿ766æ¼®⻦mkE-]O9|ðÁô5×\“~ê©§r~vîÜé>¦½½=ýÔSO¥ÓétzË–-éöööôÀÀ@Ñ÷—Ûš5kÜ×óCùÒíííé-[¶¸ÿ_sÍ5é|°¨2T{ÿQýo|Ö:6‹)C­ã³Öå£ú5Z|úíØk|Ö:6ý¸©þU2nky<–;¾«ù^*yžæwDý¨ô5©Ÿâs¼ñW­÷Rék\Ægý¨ô5i­Ž…r_»úéÜY¯Ÿ‰ŸùeŸ¬Y³&}×]w¹|•.¿ß¯EùÄ6ýÞn[í¶5&TJp×]w¥W¬X1äÇ >ø`º½½=½fÍšt{{{ÎWÌýå–`ù¡|>ø`zÅŠé5kÖ¤¯¹æšô—¾ô¥¢ËPíýGõc¼ñYëØ,¦ µŽO?”êÓhñé·ck¬ñYëØôã>¤úWɸ­åñXîø®ö{©Ôyšßõ£Òפ~ŠÏñÆ_5ßK%¯qŸõ£Òפµ:Ê}íê§sg½~&~æ—}2\B¥ÖŸi=\‹X¯áçvÛj·­5¤ÓétYÇÛ«¯¯}}}hii)8dh´û'CùÄk455¡­­mLe¨õþ£úæ÷cËïñé‡òÑÄTÇV­¿?ÆsîôË>¤‰e<ǜߎÇñ”µÚï¥Rçi¿}&4>åXoüUó½Tò×OŸ ßD9êé{†ñY]~ß'~ÿLýP¾žžw*,¿Çw5÷!*DDDDDDDDDDDD£à¢ôDDDDDDDDDDDD£`B…ˆˆˆˆˆˆˆˆˆˆˆhL¨‚ """""""""""¢Q0¡BDDDDDDDDDDD4 &TˆˆˆˆˆˆˆˆˆˆˆˆFÁ„ Ñ(˜P!"""""""""""*DDDDDDDDDDDD£`B…ˆˆˆˆˆˆˆˆˆˆˆhL¨‚ """""""""""¢Q0¡BDDDDDDDDDDD4 &TˆˆˆˆˆˆˆˆˆˆˆˆFÁ„ Ñ(˜P!"""""""""""*DDDDDDDDDDDD£`B…ˆˆˆˆˆˆˆˆˆˆˆhL¨‚ """""""""""¢Q0¡BDDDDDDDDDDD4 &TˆˆˆˆˆˆˆˆˆˆˆˆFÁ„ Ñ(˜P!"""""""""""*DDDDDDDDDDDD£`B…ˆˆˆˆˆˆˆˆˆˆˆhL¨‚ """""""""""¢Q0¡BDDDDDDDDDDD4 &TˆˆˆˆˆˆˆˆˆˆˆˆFÁ„ Ñ(˜P!"""""""""""*DDDDDDDDDDDD£`B…ˆˆˆˆˆˆˆˆˆˆˆhL¨bÒ$T4Mƒaµ.ƤfÛ6 ÀišeÙžeYÐ4­Öo‹Ê€ñY¿,Ë׌͉…ñ9±Ÿ¦i¶íZ—Jĸ­_…ΫâvÆîÄÀø¬½r^—Ž¥ÞËøô?Ægm•›ã=w’?1'ž‰““&¡¢ëú„ Ä@ P¶E%™¦‰ÖÖV$ „B!D"‘qoÓ²,èº^ë·Fe0ã³^bs3I’Üߢ›Ï»OŸþ7R|Ž›âþBñY‹s§w[åŒÏbâµØí'6‡{¥ž;½ÿ+ŠÂ‹Ð:3žóª¸ß/±[ïõÞRcw,çU±»õ¡ÖõÞ±>v$õ^ïíºt¸ïŸ±œ[ócSÜÆøô'Ö{ o£\õÞbßc©mFã9wòºÔXŸ~;õRŸTí¸é ¨··7 ÇÓét:FÓÒÑh4N§ÓýýýiI’Òéþþþt8NH§R)÷>ñÜT*•–$)ÝÛÛ›N§Ó9Û‰ÇãC^GUU·cyìH¤Ãápº¿¿?ÝÝÝ–$)J¥ÜûÄßÅlGUU÷}Žö1Û+æý%“É´ªªîï`08¤Ì…Þc"‘ȹ]|⹩TÊ}p8œVÅ}ÜHÏ£ÚòC|–+6Ŷ Åçxb³Ðm•ŠÏÑâe¤ïŸp8œƒéd2™ƒ9Û,›Å¼ÕÖHñ9Rl¦Óéã³çN±­rÇg1ñ:Úöʛý¿RÏét:ÝÝÝ–e9Ýßßï¾ò¿ñœW½÷û%vë½Þ[jì¦R©aÏ«b»ŒÝúã‡zïX;’z¯÷Žv]:Üû)®GŠÍtšñég¬÷ÞF9ë½Å¾ÇRÛŒÆsîäu©¿°>;üvê©>;™Úq'dB%¦ÃápÎm²,ç4Þ a*•J'“É´¢(9Ï ‡Ãîs½9(ñ{ÿÏÄb;9á­ˆ5E¼˜ÿ‹Ù^1ïO|Š“¢ø?ÿµóßc"‘HK’4ìg+^#§%IÊ91Žô<ª-?Äg¹bSl«P|Ž'6 ÝV©ø-^Fúþ‰F£îg'Ëò¨±YÌëQmŸ#Åf:1>kqîÛ*w|¯£m¯˜÷WL¬”óÜÙßߟ–e9ÝÝݳ¯ÈÿÆs^M§ý»õ^ï-5vE¹ÐyÕûŒÝúâ‡zïX;’z¯÷Žv]:Üû)®Gª÷2>ýõÞÂÛ(g½·Ø÷Xj›Q©çNq¯KýƒõÙá·SOõÙÉÔŽ;!§ü2MÓò'ȲìþmÛvÎp[ïc-Ë‚išhhhpü0Ì(ÿý”Ê»Šù¿\dYFgg'TUE<G8²_ ½ÇüaÑ’$Á²,÷ï6ïp¹ÑžGµÃø,¬PìU+>G‹—BïOÓ4躎îînÄãqôööÂ4M$ ÃÇf1¯Gµ3R|Ž›ÀäŠÏbâµЉ•r;‰EmÛî´ ¦iNÚëÉxΫ€?c·Þë½¥Äî#<2ây`ìÖ#Ö{ «e½w´ëÒáÞßHq=\½—ñéo¬÷V«zo)mF¥ž;^—úë³Ã«§úl1Ï›(í¸rQúbæ&îC‘$ ªª"•JÕúmLªª™Ë¯Ø/–üÏ)EEQL&!Ë2"‘º»»‹zÕãÓJ‰˲ ËrN,«ªê>·PlŠÇ2>ýk´ø©B3R|z/j¨x¥ÆJ©çNÛ¶ÝÏʲ,èº>äâ…üg<çU€±[ ¥ÄîîÝ»G<¯ŒÝzÄz¯¿Têºt¤z/ãÓ¿XïõRc³Ôs'¯Ký‡õYÿ©öµh½Åã„¡"Ë24Msw¾iš9_ÎÁ`Ðí!`È}Þ^#¶m£µµ5g@EQÜl1àìS]׋ʢZ–å~>âyªªº÷‹a4…,Ë9•Õ‘žGµÃøôŸRâEĵøœÄó¼ Cc³Ô×£ê)>GŠMq?ã³¼J•RÎñx©TÊýQñxñx¼Ö»F1žóª¸Ÿ±[^¥ÄîŠ+F<¯ŒÝzÄz¯¿Têºt¸z/ãÓßXïõRc³Ôs§ÀëRÿ`}Öªy-:ž×«• 9B%Ã4M´¶¶º_ÌÁ`н_QƒA´··C–圬—,ˈF£îsUUÍy¾ŸÈ²ŒX,†d2éÛ^.’$!£½½ªªºû4õþ"‘dYv{ÄG£Ñ‚¯±téÒ1=ªk²Äg=Ħ·¬cQ¡ñ~ŽŠ¢ ©ÜˆØŸãÓ¿FŠÏ‘b`|Vªœ¥ÄJ)çÎ`0èë}AÃÏy`ìVªœcÝ÷¼ç=Ø»woÁój!ŒÝúÀz¯¿Tâºt¤z¯Ÿ÷±Þë'¥ÆæxÎbßðºÔXŸõŸj^‹Öc;nCf!™ É4Mw8­7CmÛ¶;”ȶm¨ªŠ††ô÷÷ç ý³, ’$ùúåÌ~4Ö}j‰R© èøó¨º&z|ÖKlŽ7^ª×T]…ⳘØŸåÂs ÕxΫc·\ª}^¥úÀz¯¿°þJ^¬÷úG©û³”ç1®ý‰õY¨öµh=Æã„¡" ·ómÛF @gg'EA,ƒªª9²,Ë[ØÇ˲¬JRUuÄ!N¢Œ#Í 8Ú6*Q®áÊZê>-u˜—Ÿ‡‡Mv~ÏrĦȬ—3>+›ÞçŽU-âš*¯P|›@ýÄ'PçNñ¼R0Æ&—ñœWÆ®_b·Z× T]¬÷·r—k´ò–‚çÖ‰‡õ^ÿœ;KÝŸãý×þÁúlqÛ¨D¹Fz^)&ú5ì„N¨ G–e$“I÷à•e5)‹X8i¤²VcÕØf)e(%#Y™Lž_â³\1PîXªÄöª/ŒÏúå—Ø&ǹ“ç@*ÆnuÊåÝcŠå—øœ,õÞñìÆõäâ—Ø&ǹ³×õ…1Yry·UÍkÑzŒÇ =åQ9L©uˆˆˆˆˆˆˆˆˆˆˆˆüŽ """""""""""¢Q0¡BDDDDDDDDDDD4 &TˆˆˆˆˆˆˆˆˆˆˆˆFÁ„ Ñ(˜P!"""""""""""ÅÔZ`¼¾÷½ïaÙ²eµ.Mbûö탢(8ûì³k]_Ùºu+^}õU,\¸°ÖE¡IlûöíøÓ?ýÓZÃw~üãcÁ‚µ.Mb‡FSS.»ì²ZÅwX·¥Zcݶ°?þñ0M“u[ª)Öm cÝ–juÛá±nKµV‰ºmÝ'Tî¿ÿ~\ýõµ.ư}ôQ_—o×®]صk—¯¿ôý¾7oÞ ¼èÌÓÕÕ…Ÿýìg<¶ÆaóæÍX²d –,YRë¢T/ß¼èêÛßþ6Þ÷¾÷Õºê—c‹ß¥Ûµkøú3®¿×m‹å÷cp,üïÅ*ö3aݶ0Ó4ñÝï~wB|oM¶cºû™°n[˜ßë¶Åª‡:p±&Ê÷L±Ÿ ë¶Ã‹ÇãøÄ'>Qëb Ëïç’zø^ð{¼?üðÃøà?ˆuëÖ•m›uŸPYºtiYwH¹õôôøº|]]]èêêòuý¾ׯ_Ïžj\tÑE8xð ¯?»z8¶:::ÐÑÑQë¢T/ß4Ô™gžéëÏ­^Ž-?—¯^¾?h(¿×m‹å÷cp,üïÅ*ö3aݶ°… â²Ë.›ÇÂd;¦ëA±Ÿ ë¶…ù½n[¬z¨k¢|Ïû™°n;¼™3gúúXðû¹¤¾üï›7oÆüùó˺ͺO¨øÝ† j]„ùùKCðû>¤úå÷cËÏ'$ >¾?¨>ÕñÅM¤cÐïñ^¬‰ô™Ðøð˜öŸ‰ò™ÐøÔC¸X嘞HŸI­´µµÕº#òû¹¤ŽA¿Çûe—]†‹.º¨¬Ûä¢ôDDDDDDDDDDDD£`B…ˆˆˆˆˆˆˆˆˆˆˆhL¨‚ ""ª »Ö """""""¢ ÍÌû]n\”žˆh’²2?ùKÈM~XäÌß¶çñÛÈü¶=Ï“=Ï÷Þ® {B“3¯Î{¾šWñX=óX©Ö;Žˆˆˆˆˆˆˆ¨Jl”ÞRè¹ÅlÏÊÿï~üp`/sž'ø˜l ;ÏKXùððý€ö¯ÎýÚaà¬ãÀ«6ð-Ùyœ‡ùœH€Ñüã`õ|3õUÀKønÀn¬Ý€Ùÿį$Ðf8…ÞrOßütì©@b!pîƒÀ ß–þÌyÒ1`×?¥1oÐØÚù ÙÀW¿ ¼u6Ðü%@äÇ%ß9‰û®™‚/„Õëj`ógÿq þø),\5[žKã©8ðêÏÐy ·÷= tö7|ïßÿBY?o&Tˆˆ|ěŠ w4ˆwÈbþÉXñü–2÷1´gÀx‰“½<†çHÈMЈ BNRf$â~ï°M™?²#X”Ìmb4ËËmme~çDDDD_,Ëù_–eƒAH’äÞ‡!Ë…kƒš¦A–e¨ªSû3Mº®$IB8v·EDDTĬ18m2œ¤…§Cg*sN;‡ 7óÜDæ· šù;@> à-3å˜s¿t N¦HGé-àÍÏkÿ˜r€€=8ísÀ%ÿ ÒTÀšãlTýÐp: ô?ؼqþ2pð @íù0µôÌš‹ÏÎÞ»8o=Š2 7^ ìùø!üõ²Sø+¥ þðïѳôt,|¼ ÿ<Ѐ©óvB{CÆ>Æ•>Нÿå – ¶¼þ§›°Í܆³çþ _œ}ïÅÁ›ôbçKçcÓ=÷âèñ?Åi=O\ñb?ù.®¸âÇxùG§á¬‹NâÕÛŽŽò L¨Á²¬a/‹%FˆQ$6² Ùäˆ7©âM„ˆQ&˜¼Ó^Ú/#¹M×믯u±‰ˆˆˆêJ"‘€¢(nÒÃ0 Äb1twwC–e$ ¨ª:lýX×u(ŠUU‘H$H$‡Ým% w[DDD~`Ài§ "›»æ–‘LvÃ8 ^<÷»ëÇž3qѪ³0¸¡lÚ‡ÿ<óÏÐÚªãeói ì=Žû__Œ‹>zǬ’qàÀûð'{`ʾû±jÕÕ˜¶ÛÄ+ÍWàmë_¬YOaÙŠ÷áÿþÙHOIAÌÛ± «Wߟÿü¸ä½_ÆG>¿·þÕ{ð‰/Â׿þ~úÊ*,Yr-~ùËA¨×¸ñ×W`ùòe=V˜P!"ʰ,'Õ!.mÛ†$IÐ4 ¶mxÑ'†SŠ©§,8'L1=–!¦ÚBæ6Ñ«Á{{)lÛ†aÐuÝí ‹Å`ÛÙ ¼Âá0¢Ñè8^¥²4MƒeYnoGÓ4Ýò‹‹rñ>çs’e’$åô€$"""¢ñ‹Çã9õ«@ MÓ6¶8W,C*•ÊÙV$A"‘@2™¬õÛ$"¢IH´Ù„3ÿkÈm»Ñá´ñ؞NJéÇ•Ì} ²³nˆiÇÔ‡Èõ@ø{€v«ó˜x xé4à7ÿ(ÿ»ðS€öcàQˆ_(:€8`u§Ý D̼pØÿ `é}€yÿ`KÀ[G_ÃÑÕgáÈúaü¬ ýo\4ãdÜ­/ÅE«-D‚6¶nýO|ä#ŸÄÏÁþýÿˆÛ×¼ åw3ñ»ß½ ßøÀn|3ºý[úñ¶7FâS‰9sþÚáwáùW>ŠÛ#¯cçÎ…øÁžÇ=ŒÅgÂ%­ýxüñf|á ÷`óæW±t©…O|â<ÁšoíÁáÃOàÊwÎ@:Ý‹cÇVbæLO<ñ;„Ã¯ãØ±=˜3gn¾ù-47ÇqÚi!üÓ?ý þç–`ûöÏâç?ÿ6l¸ ªz>÷¹G°oß;qöÙ2öìѰuk†1·Þz=Ö¬y>øIØ6ðéOïÆÿ÷ÿ]¿ú«Çqøðøô§À³Ï6áÁûqôèÇ1°`=x­¬Ç*5  MÓ„ªª°m‘H²,#•JÕºxE š†aÀ0 ·T’$(J¹'*/Ó4 –Q¼qŸišŽ>‰ض Û¶qÙG? 8~õÕx饗pË–-øÕ¯~…ûú É2 Àýñ&A‚’Èžh;Çðú#aº®Ã0 ƒA¨ª MÓ`dY†mÛîô ápÁ`ÐM:„Ãa(Šâ&ÚÛÛÝãy¸8(…wôŽH€hšUUaš&,Ë‚mÛÐ4 Á`Ð}žHšˆò¨ª EQ §ìÞmÅãqH’˲ܸ•$‰ """¢ *çh’h4šÓñÇ+‹A×uX–…`0ˆd2 ˲ÜÄŒ÷q¢n)êÚ¦A’$D£QwD ‘wºt±ºX÷Ä„“ S§·#ÛF#’+Ad×q•û€ö–L›Ïƒ€|š³Qy ì‚Ñ'è¼Lb$ ØŸZÿĤ¯Hvpýb@M%A@˜hhhE 4_ûÚv0¶PðÌ3sñè£Ý˜³ÀÆ /±cƒøÄ'^ÿÿû{pìØ{±y³çŸÿ<®ºª}3fãÊÿü[Ì›wŽy {ö܉þþ¯ˆã[ÿñ~ÌœyŽ_„Í{?];ž|ò¸é¦[±{÷aÌ™…m?Œ›o~ŠbâŒ3ÎÇ7¾ñ&-z wß}öìy ˜Ø»÷øêWâæ›-\tÑb\zé,¼÷½áœs¾€/|a—ÛŽu÷Ý3ÐÔt Ÿýì­îç±{÷lÞÜ EQ ë:âñ8xàV¬XUuF“|ýë7À0Yt]‚$IpNû3¡(—$ ø¯ÿú  U:íBø°{÷ÀoÞûÌÅܲOL¨TˆmÛ°, Š¢¸•?q›èM-Ë2"‘lÛFgg'4Mƒ¦i5¯ø‰Š­w~\Ó4!˲Û0**ÓŠ¢ º º®#•JUuè¶w¿Šß¢7»(‡(Ÿa°mÛíé.‚Åû ‡ÃnEQ`š&€›Xñ6SýÒu{ßó|÷å—qtÖ,ìœ:÷Þ‹óÎ;oîÚ…M³f¡½¹ €ò'˜àØìÙøl[Nƒs"É“BJiÖǨ8u]w“¦i" ºÓ%ˆãQ¿Åöì ‡Ã…BîHœÞÞÞ/â]Qwj‘´É'˲r¾¼ÉoÁ`²,£¿¿ß}mñ}ÑÙÙ™ó½(ÊYH~üyG¥´¶¶ºåÊßifWîXJé(ê Á`Š¢¸uÃá^S\SJ’äŽduËüÇŠº ˜R¬··¦i" q3p&18kœ@+r)b¦ ;}— µ °ßä :2s~Yßúÿoæ :h¾è?åü(`êÀ×¶ýÜyÀî î‡ý·  ÏÔYö|ë¾ýÀ4hÚ$“€dš8rd&dùøíoᦛ^ÇÛß¾6㦛¾‰ï|g¾úÕ/âôÓt:ŽßþvöïïÁ”)çŸ?n`îÜáÈ‘9"cÖ¬§ðüóspêÔ%8ýô¿Á2-Z„ÇcïÞâùçûÐß.ydnºéèéù2{ì æÏáp¶ ¼òŠ…Xì:¼ã€iÞ™i‡š…¯}:î¿ÿO ú¡oßþQD"™}™i›ùÊW€¶¶«r>“¿ÿû¥pšŸ³Ø×¬™`NÎãÄiÜ;ÛŠhmhªª"B¡âñ¸Û¡×é°«ãKÓ¿„¹¯Ì¸†Š™¦‰X,æ6ˆÆãq·TT½ÄcÅ}ù•Äñ–e´è¢w»èá­ë:$IrEÅâƒÉdº®»p~X¼/‘$ŠF£c®¼zGꈑ;ù½ÎÅc¼ n2%»Áä]øP”WTÌÅû-´¼¹â}™¦‰H$UUÝ狤Õ‡;žxw=÷fßz+ŽœuNmÚ„Kúûqþ¼y¸ÿï@ó‚è ,YRðùʉøÉ¿þ+nùò—ǵÀ»®ëÐuÝ]ÔSÄwžjÑû.‰ £³s,c]†FÝnüˆs"Y#bC|ˆ“ ·'¡ˆKñ»Ø5fDÌy¿Ë1R&»#[D²'ã?ø6lØP–ýGDDDT.Þ©Mke´ëo=U(¥ÌÉdÒMˆ$ ÷º*©Šú)à\ã‰zðh×É’$¹Œœ†•°ÛA‰ˆˆ&ïh Ù)»td×´Õá$UÄý)ö^@Ÿ¨6àdaÔL§Yqú“€È~ %æ“(€} 0îÔÎÃì¨ó¢¶þ0V^r µßÕ‡Y³^‡¦]K¬ÿ aÑ¢píµ'pð`3‰UØ¿ÿóhh¸ 3gþ00Ð Û~o¾Ä¸3fÌÆþý6öñf¼ôÒz,X°—]v>Ú„––xë­ÅX±Â†e}}}?D(¯ýkœsÎ9¸å–óñùÏÿ;¢Ñ(,ËÂ3ÏlÆ=÷| —Íû=îZ¾?]<ßø‹]àrç-K@4*ö‡$©nä®»NƒwRIœS·œ3Eh¡þéÎóœ'‹v)ÑÞ …ÜöY1S‰¨;‰v3ÑŽ.:÷꺞3 Š$I°mg¿íl|xʇq1..Û1Æ„Jx§1 ªªB×utww£½½²,£»»»às½—h¸,Ã0Ü^9¢áÒ4M„Ãaw=‘É ƒno÷üžîÞ¤L1k/ˆFâH$2jïwï¾Óu¶m»^MÓÜ錉DÎsDå[TþKY,|¬k± b,Ë #Ë2úúú0mÚ4tt”1ÕI%Óàô,Pàœï¾zô(¾}à:„KO?Û?ô!lûá¡=ùäcúÜQ¶}äµ×FM¦äŸÄ\¢±_$&b±'®D]Ç"‡ûÞ(‘0±¦(ŠÛãЛðŽò)ñQëä¢7Y$ʰlÙ²š–‹ˆˆˆ¨1:¹–FZTº†Š¦ièïïókƒA·3eYˆD"…BC®Åukkk«ÛÑ®˜ëÐüzªhL!"¢É§@:ówÙé»D$ŒÌš·y>”wÊ{ù ¸+ÓÇÔ€ºÎ4%&€e€Ï$Z2ëž4Þû >¯ñ×ý:^{í?pÖîO`Õª>tuËÚ…††¯aÅŠ3±yóaåÊ5xàcï^çœó.´´ü9ž~úi44Ø8yò~L›öÏxöÙgÝwsüøÇ0sæg08øY¼ç=«°{÷ó8pà¸êªsñÃïyÏ{pÙe—áÙgoÄ?ýÓ7Ýö›îînìܹï}ï{±bÅ |ñ‹_Ȳ„|à™Î þï;ž†þêÕW±êž{á'?45ú{€L»V8lC¶m(žìÈp“,yÛDû˜·SF{{;R©lÛF,s§·I1PAÌ*$f[3A‰6-Ñ!_ ç~‘€Qÿöoÿ†µË×–õcB¥ ÃpGšˆÊ¥8Xò+¡#ÓP…w†hôO$îT:"¹#†X‡B!÷qŬw2ÖžãÎ|vN†°¡¡½½½+éb 4ÑÓ¨»»»äuJªÕFÝ`@À¥—^Z•2Ðð 8‹‚ÎIÒ6 œ\µ ’i"¾g>{«3W£ÕÑá&5ÆBÄVÎk†;ån(FšˆéþçøQÅ©üdIµ×é ƒˆD"ƒE-,ê÷µ‘ •W’$œ~úéµ. ѵžæ¹ù!Å×ÊÞº¯,ˈF£n‡£|ñxñx†a@Ó4w„|Þ„T~rªÖ£ˆˆ¨6ÄÙÀ»˜<âKÜ Äwº àƒ€ò;çÁæ½~ à%8 KA/ÆÍ€ªdnKA0 ÀZœý¶GñÖߎC‡bÛ¶Sø»¿{óç?„Y³®ÂóÏÿkÖÌÁ÷¿Á3 àÙY—áБï¢õÙûp|ÿlaìÜiá7^©S§4aΜoa֬୷¾‹+®¸O=õ.œ¦¦=øýïñÏÿüÏøÜç>‡Å‹Á§?ý üú× p×]w¹çV ;ÛŽø-:Õ øÀd×µvÆñÖ…ž_~?–J`Ûøãû–A²,œZ»Sdša`m<Ž7Á±+¯Ä‹õW81w..|óMlùò—qÖM7áS¦àè¬Y¸àÌ3ñ«¿ú+˜_ÿºÛé>;ƒl¯-^ìÎ@$:­' ·¼’$áoþâ/pª©É]#‹¹kª‰¶5oÇd]ׇ­[?~¼ìÇ*ã x6 #gÄm|kEy¸^J¢‘VpâõB¡Û*¦ì=ÍEy¼½ª%™LæŒâïMŒð½¡:;;릡V¬[áeYj]´I͆sNËt €‹ÁeÈìLâžoãIÀ†æææœuÄYâø(´ýRFQUšè­0‘%“I|÷»ß­u1ˆˆˆˆêžèý9Ö‘þ¢±&­P1³C>±~g*•r{Æb1·ó‘˜ê#„˜ùÀÛSµ“VDD46œ'€“<g†œŠš¹]Ý`If•¿ ANÏÜ €8 ÿÀ™€òŸ’€¢ª³¡‡?Œ§cOÃ4ã8qâ’/B$ò~óƒçNOEGÇÏñä¯>…]Ó. «þýø&Þ–Z‚Ž?†=¸‡Ž\ L|zKö¥ïÅóö`Æ¡…ø“iÓðrf熆ŸcÑ¢sqôè;v ‘HÇ¿†E‹!ø–ýã?â‰npæËºújìÛ´ÉÉîH’3¯–®;«¸‹ù¹€a;ÔËš†¹Ï<ƒööV§ÝØ´|Ä6S’$„>úQĨªŠ+Và§›7ão¶oÇ=ŸûλôR|ëÑGqÚáÃ8·§ßY²ÛpÏÉ“øò‘#8ø—‰oŸ:Hf}ó›¸ÿøq,œ:k2íÂ~û[üð ±dåJ¤×­Ã—_ŽMMÎtm­­@0ˆ¸,ápöœžH¦ X :[$+ ‹9·‰Ë–˜&®zæ̼ð²wL¨”@ô’£?,Ë*Û¢ÂiFÎBÔ@6I#†H[–•“,ñÛ‚é²,»•Z1<+N¨Š­,ËØ±cG­‹1i‰)-WîÙƒÔ¢E02ó<‹iì™2 \†q5¿%S& UU™P!"""*Qþ1õòH÷ç/Z/Ë2’É$b±˜;•‡H„º†‡ÃhooG{{»›8k­(ŠâN© 䎠kyŠu6½=u‰hüD÷B²b4™èø+¦•í[Þ¶*1E6·£¢·—¹X÷`<×Ð"ñJ“ƒH"!;¥—”ùmÿH6øÿùWpzå€ÝØ NîAôЕoŒçáÌ!Ÿ9íÞ½kÖ4C’€nx¶mcÛ¶mؾý<ÌœùùK,œ~=€©XýÜýh>Þ„ÿ3ï:ˆG^ »RX4c?N,ø7ÌÞ¯àÔûÞ‡þþ÷ØðG¯®¼‹žžŠ»ŽÁ—]†Ç/F¤¹û>|ñøéø?Ñ(TÛv’$ÿüÏN‚4 duÝù ÃÈ&Uº»ÄŠa"ve9›Ðu¼øÆ°ÞxÃ]Š€ÛY_¬Y":*Ȳ IQ°63+“išXtø°3À4!~:”óÎÃzÃÀ+·ßŽ)¿øìw½ IUE4Æ'?ùI9rò”)îìFWN?õ) »M"ÔÝí”Û¶ò*Šó¿¦9ç…BÎûDÄ".ÎcMç¿ü2zÏ:«¬Ç]M*}}}èëë€!ëNˆûZZZÐÒÒR‹â$*ebMþþ~H’„ÖÖÖ¢¦Ë)–$Id2Á`ÐíY#†7ÎÂêÍÍÍ%7îV‹79‰Dêj4J±$IšP •‘bÓ{­ãÓ†“H±- Z €öÌ}ÞÑYÀØ×ˉŸã&¾z‰O¢É¨ë¶D“Ï¥K§Óãºß›X׳bºç‘¦žÓh‹ÇŠi\gÊ\q»·Ž/¤M¥R0 £¨©­©ö&k|Š)£ ]§ê™‚ÞµmEƒ&P8vD•X—S$"c±˜ûXG¢ã®Øž˜±@Ì&"z¤‹uxó§¶³ŒˆuyÅH1±Þ‘H²ŠNµ¢!VLù#Ö>PUÕÝf>ï{Ïåë‹w¤›˜¢]Œˆ³¦N§èÎÎΜ÷.ö‹Ý&°¶mCÓ4w›‚¦iÐu©TÊÝÞÏò•W^©õ¡UVõT·5‘ÖK,0…3ð$@¾ Ïp9 ‡à4$©€Ù $V©Â̈‰—_>¦y¦Û^¿mÛ647·âÕWS˜µ÷8ž}éNÛ³sÓ¿à[ÿÓƒßvÿ#Ÿ:…©S_À{÷íÃ;g~/Mé o>Œ8ëO_†ŸX´h;ŽÙ;ðÖ¼y?¼òJüëßÝ MÓÐøòÕ¸îŒ3pó=÷íí@O®ŠF&¡“PÐ4gÁ’dÒI2ˆ¤a<î?»‹;{G„tvvB’$´··»å#ºÄ¨1Ã0H$‡Ý$†ªªhnnvgPQUÕm# î4ù"YâÂO4ÒÙušÄûˆF£îHñ8±_lÛvq-ËB"‘€aP0 #gªÂööv÷5Ä눓,ËhmmuË,’Eq?Kñ¹‰ÎÎ"YdÛ6Î;<ý_Ïê©n+Òc&œA&œ5R½(gÿ üHyBÀfÀZŸyRf°ÇæÍ'ÑÜü,®¼òjlÙ2Ói·?q1Þ%?€‡vÅÎÿÞ‡·f,ÁéG·"üÈ·ðó©ïÇ6œ‡S§æá†ÅßC¨X>w.n ÌÁ ÿmáŒå§a箩¸êŠ+ð‡?üŸúÔ hn^Ã0ðž|@¦­×»îW4ê$PD{°ižiì!IÙdŠà=÷Érn2E’œ–•ݦ½ pãKŒõƵeYˆÇãîw÷{ÍÛfíý[õL5&”­MØ/m~é*Ú¹sgzÅŠé-[¶¸·]sÍ5iMÓÒét:ÝÞÞž~ê©§Òét:½eË–ôŠ+Ò;wîq›kÖ¬©x¹£Ñh:§£ÑhZ’¤t*•ªæn«káp8Fk]ŒŠI&“é|ä#îq[¯F‹ÍtzìñùÔSO¥ïºë®²–3•N§åt:Ýé¹M–åZï>ò±jœ#*­ñ9ö Õ·Jœ#j¡^ë¶D#¹ë®»X·-`¢|oMDÝÝÝúšÓk"œ#&Rݶ»»;N§Ó½½½éÞÞÞt<wÛŽEI˲œîïïwQUUÓýýýétÚi+QU5­(J:§“Éd:N§ƒÁ ûüh4ê¾F:N÷÷÷§ƒÁ`º³³3J¥Ò½½½ét:VU5J¥ÒÁ`°è²«ªšŽF£éÎÎÎ1?g,mb’$¥UUuËZì먪ZôãS©”»Gû¬òŸ3R{Bwww:•J¥ûûûÓéd2é~6ñx<ç±—^zé„8Gø½nN§ÓⓌ¦Ói5í´Iétét:˜N§»Òi©!îÜ“y°”Nw/I§å%étº7ó„ît:M§o½õhzƹqzùå¿JÏŸ }ñô¥ãñÞtgggúÿLù‹ô½MMé§tzîÌ_§ œNéóÎ;/}Î9oOŸ9å¾tdõ_¤-Z”^½zuúË_þrº¡!”þÕ¯~寋8ûûûÇ4~•¨ÛVu„J__:::ÐÖÖæÞvíµ×b``]]]hjjÀn€IDATr‡’µµµ¡­­ ]]]5ï‰`š¦Û^ o¢âx‡ªNDápƒƒƒµ.Ƹ›|Ÿb½”ûqucãaÌDU=Ä'ÑdU¯u[¢‰ŽçÎÉEô¨¥úPñiB¡R©”{¬‰ub½£Eq§¼éîîF$A"‘€¦iP%g*¼d2‰D"UU‡¬ ]³ÈŽ0É'Ö-k˜¦9æö­ü5QF#Ê4–™$ƺª½3Òó í1]Y1Ïë=ˆžüu&¿×m-dG¥ÎÈN{Q€üS@ù% §à pFŸ„Û¥Óà _É,¸ÒÓÓƒ§žš…ï}ï¼þúïÑÙÁŒ·þ çí»öá7ÉcøŸ³~‚·jÃs¸,¨xüä嘹`­ûèç?ï}ï{xî` _x!:N¼ŽH$‚U«Vá+_ÉE"Ž'I’|?ãnJ5_¬££6lpÿĦM›ÐÒÒ‚žžž!sï555¹sö gÇŽ¸í¶ÛÊ^ÖX,æeô~ÉNÔ/M*Ím·Ý†G}´ÖÅ·‘b@Éñùè£býúõã.Ÿ g(⽟ü$4Ms+ŒÞ!ÔDBOOn»í6ìÝ»·ÖE·JÄçÞ½{qÛm·aãÆµ~{4 ‰©&”™õT·%*ë¶Õ©Û•¨ÛN„õ;ý\·ë‘x™¦‰H$UUÝi¢b±˜»Nl?z{{ÑÙÙ‰ÎÎND£Q·ÝH4š†ÃáœdŠàîÝK,þ\,oB§Xbʰ±N™mšfI‰›±k’T¼‡±Ï<óLlذ½p©&V¯^uëÖaÁ‚µ.JYù½nKT ÖmGVŽº-Q)DÝvéÒ¥µ.JYù­n›H$H$Ü5MÄ(”ÎÎNwÝH$Y–sF«pG¦äó®‹R ±Pz)‰ŽRqÇò:Š¢ä,ê^ìö«1‚¬”äˆX?e,ïE×õ!ïgõêÕXºt)ë¶Ãu[益R‰dJ ó¿wÀ $À¾’9D€0œF%8kºÇb€a8IËãOïÅ-GžÄ’7'YÀàѳðùýûñêŒ]¸Ø'„Ýø*æÌ™ƒÇ_|/žqš›ŸÅ¼y¿Gof]“x<Žï5®ºêbtgÖ%!ÿX·n]Eê¶U_”~pp·ß~;úúúpçwºCÅššš†<¶¯¯¯,7Vb‘+ÀY4l,ÉêÕp± Ô.>m8Ó|u0 1]G0D0ä°~šTüŸD䨇º-ÑdÄsçøˆE—Y– ÝÛX,†p8…ææYдKœýˆó>_›‰§íÀŠC›°ÿP§!Œ?¦Ó˜µlxd» žÃå—?Ž-[â¯þê¯ðÙÏ~Ö]?¾Ð¡ÃóÚäQõ*kÖ¬AKK ÃÈ9i¶µµ &600PT¶³œLÓD €,ˈÇãnÅ‘h¢.6ÚŧèP€LO UU‡M4‘ù1>‰Èá÷º-ÑdÅsçø$ †áÎÜ iZ[[ÝŽ‡‰DbÄẮ»=ó‰€{Ÿa9Û¢ÉÇoñiÛ6@ε¦7™dÓ+ (%¡RJ¹JY{¨ÔÆâ±¾Ž,Ë%½ÿ±>g²$HÆÊïu[wª¯€j;#S”‡à,¤u~µ^âŒDA€<ûl3úûi÷ô }œ~â>¶¿™ß&~1åk84{Nœ8óÏ?³fÍBCóøã/Àûßÿ~Ìž=€“HaÞ„ª:BeãÆĵ×^‹®®.÷ö––ttt¸‹utt §§}}}¸îºëªºCÄ[Á`ªª2™B“ÂH±Y«øÔàœ»™Åò4ù1>‰ÈQu[¢ÉˆçÎòÈŸ^7@Ó´! e&‹!•JålK,ÖL&ký6©ÊüŸù‹ÁG"ƒAwäI<‡$ICc¾”䈢(%´¨F§C1ÙX¨ª:æ5Tªi¬ûMQ” =í¸Ÿê¶ d×·à´©pó&°Ÿð`ÿ>šy°åü–eà‘Göà׿þ)¾ÐÄÁ_Çj¯¬ú)^}a9Âì·~©K÷cá™+ðƒÍ6¦ÏÚŠ9sþÇŽÃÇ?þqÌœ9K–ÈX¸ðغõߘ€£UM¨ôõõ¡¯¯oÈB›k׮źuë°nÝ:Ü~ûíX¹r%¶lÙ‚uëÖ¡±±±*e‹~‰„ÊDþ‚$Ê7Zl¨j|ZpNžböɱÎmJ4‘ø->‰(ËÏu[¢ÉŒçÎÊ(g}<»ƒX\\›‹QÞÛEA4u;\ƒA$ ضí6ŒË²ìþmÛ¶;ê€Ó²ÔŽâSL?§(Š;½wZ®BíAâ¶±.üŒ=vÆš´”eczŽªªc.W)IUUÇܾVJGJEQJz?cý.˜èß~ªÛÚpF£ˆ„JN"E$VÔ‡(@è›@*gþ/ÓY|>"‘E¸üòe8í…ç±³ùU|¾‰ñJÿÒtìèŸe ?Ã…^ˆïlNàíçƒmÛ¾„{ï݆o¼W\q"‘þõ_SˆD$¶SŽª&TDð gõêÕèèè@__ŸÛ;¡,ËB"‘pÿf/šlF‹M ºñ™€s¢U˲8:…&-¿Å'eùµnK4ÙÕù3‹¹bj]×ÇÝ@Àý? æ,T]Žç˜¦9âZÞ^å†aÀ0 ¤R©1¿×p8ŒP(䮃 ‡mø´, @ÉdÁ`±X ¡PÝÝÝî”LÝÝÝH$ˆD"n#ªaeÝÝÝî6>ò‘À0 ÷=êºÛ¶'|ƒ¨ßÕ:>-Ë‚™™!‹•|\WR±k´xUzAzñÕhT.%qSJBe¬‰«‘¼üòËß/Õà׺­!þx.ä)p2.!Kóag-Ã0°ç‘%øÆ7öã‚ æãÔ©è›6 Ö´iøÕܹXþ¼_âg@€‰óÏ?GÅõ×_Ë.{;þå_vã–[nàï"QÉvbÊWõEéGS‹Ê¬¦i‡Ã%e§‰&“jħÊ)NW¶mÃ0 žÀˆFÁÆZ"blùW-ã³PCžhD»ù¿ ÏsFk´ô®ƒ" 7ªd$ÉdªªÂ0 7¢ª*âñø2躞3Õ¯ØOb‘{1Š º ݋ۼÓ4)Š‚n¸÷ß¿›Hò&WÈÿ*Ÿ†a º£Tº»»‹n*%¡ÐÛÛ[ùEUë€9Üwë¡C‡j½ ª¦ZçÎÌì]Hdþ—<³ä¯ÁÉ (€Õ g¡xС£õµ^z© ÿGžê¹Ï¾ÛWßÞŒÆ] ÔqñÅWáñÇ/œ8qwÞy'`Ú´ã9e`1 §ê‹Òû‘˜³”Œ6•—gt àĦè‰FDDDDDÕÇ‘J¥ÜŸh4š³¸üXƒA$“Iôööº Ì¡PhÈãlÛrMÇaÛö†lY–s<ù _sçÎE0tG¦†ÁQï„D"p8ìN 7–ÓRF4°‰¨46œ¤J €g}ùÓŸþ×Ýp¦3‘áÌý5 H¥úñ¡½ ˲ð›ßìÃ"Ÿßûÿ°õ­·ã—˜8<¿?;u MMðö·ïÃôéÄ\€+¯¼ÒMÄñ‹­õÛ¦:1é*¢Æ“QíÙÈž(gqÀd2ÉždDDDDD5–ŸÀ(†ahoo²h4ZôâÖ†aàèÑ£C_LYTU…®ëÐ4 Á`½'9±ø¼X[g¬×™¼.%ª.ñ-oˆÆ€Ó¶ŠŠl¦%Äïf§{±ë×[0÷Ä láÂÆáÇqäÔ6<ˆ€ÞÿþÕx×»Þ…«®º \p&>ñ‰£¸ñÆñ­o}«Öo“êФO¨ˆ¹3‰¨ö48 ŽÙ¶ÖÖVwže"""""ªÛ¶Ý鏯B–e˜¦ MÓrn³DäSUš¦¹ÉÃ0 …pË-·À0 7©Rly‚Á ;5G§Ln¦i²,w”‰˜"ŽˆüK¤Ñ¥“LÀž hŸƒ3B%óõ‰Û{ ûl‹A¤7…K` `Ñ¢]8ë¬Ý€oû ؽ{7î¸ã<ñÄÃxñÅ3`FY×Ò¡ÉcR'TB¡Ð9a‰¨6,d§û<<±ÕF @CCÐÜÜœÓCCCÁéÀdYF2™D,C{{;Z[[¡ëzÁº¾X?¥µµ@¡PÈ]k%çl# ŽšP‘$ Á`°à”a4¹ —Ä#*‡K/½´ÖE˜pÄ”_QJ3sûL8É”ÌDC¶ <ÖsæÀ†ö۟⥆V˜°¡hhø9Þ|ó;B8ãŒ3Ü6àýû7ãÁO¹I¢±òÝ¢ôÕ”ßCˆj'çD™ˆÅ iº»»k]$""""¢I)Në~ïÂÍbj%Ñ%ŽŽ˜òW¬§"¦çŽÇã‡Ãî"óÞi»óËã}ýÎÎÎZïNòÃ0L&k] "*’X”R߆“a¹ À¹p*™gÍ}ož˜ŠÆt ó§~ ßxë X°à9\ÕÖ‚½{»pî¹×ãñÇSˆFu$ w}0¹H%›Ô 1\˜Ã<‰jË‚ÓÙ  U×ÑÙÙÉuˆˆˆˆˆ&±Œ.á’ŸH!*†mÛn‚ŽˆüÏ Î2]hw#€«@ ø³ ?ƒímÁù‡/Á–9oÃ3HàŠ‹^ÇS/^‡ÓN; ‡ÂÒ¥K±téxüq§í7¿C=Ûƒ©T“6¡bYEiš\£¨Æt8k§ˆxäPl""""""P(Y–yITGÄzóÒç9`ž`Àÿ}ã·8ý­—ñbz#æ߀}°1댜 .8ŒU«®Ä÷¿ÿ}Ü{ï½X°`¿¨¬&uBEUU„ÃáñoŒˆÆEðO}}ˆÅb<ÉÕ˜¦iîŒ^²,» Çsêlò3±.‚®ëÀŽ´DuBÌ`¢îr’*Òì´ÊR ±ñAÌ:z?ž#ÅTü`Ú»ðõ÷¨™'aÌ»7Þx#n¹åœ{î¹ø‡hÀßÿ}z\å"òš” •H$Ã0 ™P!ª1;óû•ǃ¢(ˆF£µ.Ѥ¦ë:lÛ.8ŠeYî<ôD~%¦ø²m†að:“¨uþ?§Á]PÅ|Þù>Šƒ»¿‰_MÄQ4ã†Ã‡Í$MgÍz W^¹¶mCÓ4tvvr^*»I—P1 Ã=±²'üÄbd~Ëp¾k¢úognCæ69ï9âvïxÞh3*™9³Öo½®™p֣ƈˆˆˆˆ¨öâñø°õóÑ¥'ª5Ã0Ü5S†K‘?Ø™ï*GŠ™¹Á„Û0÷ÉOnÄý÷¯Æ˜ˆù2^Þú2€ŸŽ=Š™3gâ}ïÛË:Û¶ÑÙÙél‹#Ô¨Ì&]B%‘H ²á¶ L8_ˆÞ¤E&©ìþm{î“òþGÞóÄcÄãÄceÏo ÙïÚBÛÊ¿]öÜæ-‚¡ ÙE±œA„@ÀwƒA\ÓÛ[ëÝ]· 8ûÖ°,Vr‰ˆˆˆˆ|Î4MÄb1¤R)÷ÿP(Û¶Ý ‚Á Û€eš&‰t]wG¤ƒA@ @0D"‘pŸÏ‘/T¢#-R‰üÏ„Ó6Gî‚ôHÀYp7sÃC-Ç…gþï5ððñ™8zô,\xá xé%ÝÝÝøÊW¾À@4úUÄb1h𯙉¨"&]BŶm&SJ aè¨ NbÁ@v‡wd‡œ÷cÀIBx©ÈMdä12©&‘J"›Èå7á|›Z3ï'¬ëÀ%—T¹”‡ €nÛ¬ìù„XƒÂË;…à\_$“I¨ªê6`‰knq4Egg' Ã@(‚¢(eÙEÐÝÝ Ë² ª*¯ÙiÜ8Qým‚ZæwÔž0—JÎ*õÎ}ã ܺò¿ðƒ½Í8zÔI¾75=ަ¦&ÜtÓMP†aÀÊtØÉ{¢rSB¥«« }}}X½z5 §§ëׯ´µµaݺuµ~?#â0ÏÌ~@6b 7i ªÌÞåÅÈ 1’È&9$8‰‡b W•‘KxN%y›ô½eS=åQˆX×=ZƒRN ")'£ðÑ„Cöâ p.B‚pÈ{NÙÕz8•h=ï1qÏ6¼/ô:A íñæ¡ëº›8q‹ ºÓ(ÎâõŠ¢¸Vñxš¦ålC–ewý UU sµÇã$ Š¢°ƒ•eYãßU…‰ÜÓ•šNj€>Pl8ç6³ßz =ÿ·°³gߊ7ß¼MM°jÕ*Äb1H’Y–!It]çˆGª˜¢*wÜq6n܈µk×úúú°fͬ\¹mmmØ´iúúúp÷Ýw×ú= Ë4ÍœÊ_½³‘ý²£*rÞ/r§ØÊŸ^KŒ #;í•깨Ò48×q¦iò≈ˆˆˆ&áÚxRÃü=œð(ÛNn o’ÅÎežßѲ,˜¦‰†††œÛ½ „³Ó#UÂDjû!š D›¥u${›ü~ `Z&LÍÄñÓÎÇ#ÇŽW\¥ý?Å‘#/â²ËcÍšwžkYîÚÙD•TTB¥§§=özè!´µµ6mÚ„¦¦&Ü}÷ÝhllÄêÕ«¡ª*úúúÐÒÒRë÷5¬z¨¬y§•²<¿ÕÌߢ’è”dgþVó¶GîìD~c Óù.aÏ""""¢:4ÒHI’ ªª»Þ Q5†Qm?D”Ë`Í”`¼°3 ŸÜ¼oû‡À»OÝ„}÷Y0ÍGðÒKßÄܹGÜ©&#‘’É$§û¢Š›R̃{ì1ttt¸ÉÀ™þëÚk¯Ecc# ¥¥---èëë«õ{–iš¾<©špÖY²àŒ¼hÏÜ&’+áÌýAý™Ÿœé¶:áL?¥z~¢È&\ˆüH\vÙ™¹-9¿íP¢WEþEªmÛÐõÜùt]G"‘>-‘H@Ó4X–åÞ‹Å8½•E0Ìé \hŠ0Ó4Ýú§mÛhmmR—%*7ŽP!ª_Ò€mÄô‡ÆKSNÇ®yóœû3S{µ¶6£¯¯ÑhÔRÒ¶mȲÌN»TQE%T uÒÕÕ…•+WæÜ&’+~e×xÑkNÂ$ gQóœÄ‰¹ º3?pF™á$Iâ¨Íš"D•`À9ž è]\Zž‘Õ¬æËg%–e¹¡bÎéX,æ^÷6MÓ`Û6LÓ„eYhhh@"‘p/4MC{{;‰„;Í¡¸ˆÏÏ¿Ð%"G9F† ÚˆD.Ôû;“ÛD$sÒ7Mç9âo"""¿hhhòã%ÖOiooG @,˹_¬ŸÐÞÞî6zU G¨Õï’€=ÎõÑÓOŸÓvìÀf_‰ŸMqÖôVÉd6œ‰'Ÿ¼­­­œ©*y~¡j(jʯ¦¦&<öØcîÿ›6mttt¸· ¢§§MMME½ðàà r5}}}CF¸¬\¹²,‰]×ašfÅ{Á‹EÞÍÌß@vº.±6‰h:.v1w¢j*›@ùãSÄ…f9s(—Dƒ“‘àXÙ…>ãpæÉ3‘#/œ¹M û·G<Û #Äb˜X±ï-3êF’$X–å&5DO Ó4 ÑÚÚŠÎÎN†Ã0ðäWžÄ“_ym³ÚpëÊ[±éë›°ñgñÍ|ˆïzø]˜?>ì„ë?~=ú>Þ‡?¬þ¶ÎÙŠ=܃åK–cùòåØ÷÷ûÐs~.ürýüQ œ?€{VÝK²ï»I™B¢¼‰DÑ`|ë,^¼Íf<û7ÏâæU7ãùçŸÇE3/Âk_~ ÿæ V­Zåì±ÿ,àdãI<|æÃ¸¹ñf<Òõ.|âBœöo§¡é@æÏŸÇžy ×ýÓuxùÿ½Œt-Ý‚û¿x?>ûÏâ×»~ Y’1cÑ üèÅá“Ë>‰‡žrTƪý«ðæ®71û³³ îû‰¾Oµâs²J$YÂEÆ»¦9I˜hÔyn4ê$S$ P z{äI4êlÛ0œ¿-+›L±,@UPÈy¼—e9ÏlÛÙ>àÌ;9hÄC=´û7€s/9{ø%ð“Ã?ÁÂO-ÄÜ‹çâþïÇ‹nÄïù{<½áiìÜ+µ+±mÛ6…3gž‰ÿ½êã¥ÿz ºøCøú׿Žh4ŠÕ Wcû9Ûñ‘ÁÁ?Ä+s_Aê‡)\¸ñ‡ã°, Oñx_}áp·J·º£Y„+n¹ÂýûõÀ²w,H ý}ï6ïÀ5³ob@XÝÀ?|ã°ëÂ]øõŒ_ã׫ Ó4‘L&ñîÀ»‘J¥ðSã§À_:Oÿÿøÿ¿ÇÝþ÷0ÎÇùxI{ ÑE‹ÅýLtÈ´ŠÁ`š¦!þtÛC’$ض MÓ½Ïy^8v¦/³-¿D,CòIw 4À©(- / {¬Z¸Lº Çp sí¹Xn-Gü8,_€#ö„>Â÷^/Ç¿Œ×î~ [Žÿ õZÅg½2 'QQˆi: 1º$wþN&‡&@TÕù;ÏÉ Ms²œ‘âM†ˆÐIñÛ;X"á¼¾HrH’ó81jEQr3†áüض³ ‘€1Mç·¦9ïEÜ/F²˜¦óZNùÅT–•›l¡ÒÕªnKD#ã¹³:dYF2™t×ë“e¹,ib«t|Özºw¢zV«º­@yî¬"ÆFó…ï! ¼î¬0½gÏAÜwßm0Mš¦¹S¡ó¼CÕVTBÚÚÚ füV®\9¦`Z¹rå°‹×wuuáÎ;ï¬Èµ,«äj n[ª;ë §“:×4¡‰b¤ØÊŸœ“e~Ò`1•WιYË d0 ÀišˆF£ˆD"H&“0UÓMÆî1÷ Š¥p®}.¾ }ò2~wôw°—ÚÀ›€õK Éß$±¬}º»»¡idY†úQ[ô-¸AºÝÝÝC^Û»hZEæü•á,ΔñÅí_D"‘@8Îùz3s…=󉿽e'“Ùá>ùß³â1âýH’äNñ&îó¾¶Ø–÷ý‹×Ο"B¼^~ï³g¿ð, ör Û¶m+ÿ~¬jÆg¥‰$@0˜mô÷N 9ÿºî$dÙuáĶïׇHTƒÙÄG,æ$E$ɹ?w¶)^OŒFÛ‰ ÛvÊÑßïüŸHd“&Þ×ÕõlrÈMntvfŸ+¦ß²m'9£iÎoQ­J¥œm‰íÛvö¾d2;M˜xh4{›,;Û¯%’2" “ÿU"IÙÄN08´,Šâì7OXò²#pÄkPV­ê¶D4²‰tîô»`0ÈÑ4&ŒO"ÿªIÝö€#vø X´h¾÷ÌGp lƒ“PÙ¿?Nžœï®Ï¥ë:Ÿ§š(zQú¾¾>ÜqǸí¶Ûpûí·£§§€³ýX2“mmmèèè²ÖÊàà àŽ;îÀùçŸK/½7nu{{÷îÅúõëG}\)“€œ6Ünä.¡ Ér†;nÞ¼¹ÖÅ(‹áb(=>7oÞ\ðq6œv½ @;œ¬K ÎH1Ï^Y–åc °, †aÀ¶mw]Û¶‹ÅH$`,ËrOÚ¢üb ƒx<Žx<Žh4 Y–Ñßßïއݓ¾Ÿˆ²N4}}}X°`Nž,q¶•H8÷™¦óXïàA‘²÷™fö½‰ûò?çátuuA×u:t¨êÇ_%ÔªnKT ¬ÛŽl¸ºíD¦ë:b±b±ôB_øe&^Küˆµÿò3Ú(wÃ0F|œišîk$‰!¯á7}}}X¿~=öîÝ[뢔E%붦iNÈëò¯®®.ìÝ»—uÛaˆºíp TÀ!@Ú`>œ#éÁÛf=…þ€Š%K^Bss3EA"‘€™¹m:D…lܸ±"uÛ¢*·ÝvºººÐÖÖ†¾¾>¬Y³fä`£¾¾>ttt`íÚµxå•Wp÷ÝwÕØ3gΜ¢:cM¨DàtŒ‚‹ÇÓð:::°dÉ’Z£âJÏ%K–`åÊ•Cnwú ð…‹gXX*ó 2Ö…Å 7‹ IšˆE2ìÈ™d2 Ó4Ý„ˆxŒX“I’$ƒAw!N±½ª2ÝZkMMMèèèÀÌ™3k]”Š+%>gΜ‰ŽŽŽ! €V‹¸Æ ‘,𠳉ñ[–³I ‘‹‰”p8;Å•¸Í4çZV6#F¦D"¹ëœˆ×SxƒÙÛŨ ;ŠEŒèPUg{b”G"‘*L$LÄZ&²œ»N‹w”àüN¥œd‡id×w‹ÝÎvÅ~ñþ-¦#IÄþŠÅ²ï=sÊ'F×x“V€óúbÙ„Ž¸OןX̹Ml[ì/ÓÌ&Ë kî͘1£&Ç_µTºnKT ¬Û–V·ˆlÛF{{;bâËNº½½Ý­SW‚èÄdš¦;¥KkkkNb$‘HŒšPI$H$“@‰DÑ#Nò%ÿ5üFÔmçÌ™Xë2Þº­eYL¨PUµ´´`Μ9¬ÛCÔm %P½ä×é¸kåšÛÞ³Ž<‰Ÿ4½€ŒiÓ¦app¦iºm08B…F´råÊŠÔm‹J¨tuu¡¯¯=ôÖ­[‡‡zMMMeíÓÖÖ–3uXGG®»îºQsîܹ£^t†1¦j¦ýÂíO4œÉrÑYj|.Y²mmmCn/8BÅDv±"±˜|ˆ95 ”iá³mÛ½¸R¶m# "‘H@–eH’„P(äŽFÑ4Í}|<Ggg'¢Ñè„Ý1ˆÑ““!¡RJ|V3¡R¨Ãwdƒ‰"!bº«X,7‰!~Û¶ÓÀ/î‰MËŽ”ål‚$ËŽB1ÍlRÈ& Äh1êCüœûĈEÉ&H€ì¨1]—(g0˜M€xËÙÝMxÄãÙ„‹˜ÚÌûu"³‰‘,²œMÊÙ’x}À™f È&i‚Agê3QIr#’U"eYN"'t!âñâsû/qnÓõì~ŒÅ²ÓŽ%ÙéÑÄÔe‚wÿ´´´à¢‹.ÂôéÓ+~üÕR%ë¶D•ºmiuÛ‰( AQôööº£°{{{¡( ""ã_!ñx©T ©T ÝÝÝPeL=Ũs1L¾X,†ÎÎN÷}¥R)÷ZÀ¯DÝvîܹµ.JÅ·n;ì,DÒÒÒ‚¹sç²n; Q·mllö1Ö<o1ͳdbæñãx Î:k7_ÅUW=†+^€,Ëîú)’$qAzQ[[[Eê¶E¯¡’ð_{íµe-H__s*¨#ÛX3BņÓ1à¨"¯rǧgð‰nÛNlZpæ×‹Â™K/\ò¦]š¦!C×u¨ª Û¶: §K’Y–aYlÛF"‘€ªª0M†a ³³Ó­ˆ‹Ç°RN~UéóçxéºÓh/ˆ)²€l‚DÈo„÷N½åMºˆûÄ6ĺ!b}“d2;bÈŽðÛ‹F³ ÑÙ‰a8 1-–Ht¨ª“L‡„ƒ7 "FˈoâÈMàâýx³y“%BþRK²œ]T^S—yšYP$e¼£{DâEL¦ªÙI<î¼gñyÅã@kkîÚ*b_‰9âóó&¡ÄtibÝ–înç9ø@uÃZð{lMfŒÏ‘‰:qÿûâñ8Z[[s¦ÉÒ4Í]'Ï»Ÿišî(EQF ܆mÛ‡Ã#ö0k&Qÿ‡Ãîh–Ѷ!®¨öÊŸY’h’«è¹óþ ™®r´<6å·¿ý44ü#Žý:êqÛzD»ãj¡è„J¥uuuá¾ûîÃC=„ÆÆF bÓ¦MX»ví¸·-²–#>ÙöÜ2´åM(åŽOÎ˲œD…˜_p‚°Dâ"H’$wTŠè½ ªª;³¡bÛ6:;;¡iÚÅÍE…#PÈï*yþ/og!1êC,‚žÏ;{ˆ7!ÖœFýp8;•øí}±Æ‡,g“¡“Ðõlö³SWƒÙ‘ b 1M—Hˆ6oÒD$sR™žTâv ›‰ ¯B·jG*æëÇûš#QÕl"E‰!¯îîÜQ0b‹$‹ØG±ÐßïQfñbˆ÷&:Z‰m‹ëïHmÑñJt ïÈûX,{}/¾øC\qÅ¿ÕúЪ¨Šž;›‘mÝ%á§ÞŒ ·ÍÍÙXÇ·eY\7…j®è«Ù-[¶à¶Ûnsÿ Ò÷ôôäKQèBK4 {oóöüÒõl£»¸ñNé¥iÙ‹8q±#Wë–¹Iq!¤i¹¤â¢GôD·‰g¢œºî”ûvˆàM®ùŒ@q#JêwŠ0!9#.˜Eâ*ÎöxL$ÄE°ŒO~²Ö﮼ªY·%¢âùñÜ À9Ùäw-¡’rõ.PåÝN~Be´×É#IÒˆ Û¶qú駹Ɩ$É]":7544ä]×ÝõEYEY¼å ƒnÒŲ,D"„B!ôöö÷ùQYT*>kÕk]$J¼Ó Š:P~2DtàõX‘PÕìz|€³d2{<>zN´P=­”zj¡‘ÐÞí³Íü:´÷9ÞKrïãÄí…Þ§¸o¸ËùBeײ쌰öÞæ%¦ì×-âÿBåõN±kÛÀÙgÿ ¶l9wì;ÙǪZ·=g*ø8ðêÒF¬hÛ¶}—]ölÎÃDÇØX,6¦‘‹DåVTB¥©© +W®Ì¹­RÎJ,ò'Pó‰dJœæ‹¨åˆOÎt_¶m㦣7Ÿ.}[b>dÑÎ4M躎d2é.B)z¨ƒA&RÆ!ȳ¸vC©Å ¢Ñ[L‡$†j‹^Ob8¶¦ ]ˆÛ; ]ôP×ÿÞוåÜ‹oo¥É¬V‹äŠ$E~hyן£8^Äq!‘HöR¬o"†ûÙD‰w½hÔyž8†Ä~1BL1à]wD´Cyo¯‹9?©ÔеK€¡TbÑwrÚbÚ/ïþ£^^~ù0^|ñüZ»*&ËÖDõ¨¦ñYÌpÅÑê­…2þ¥¼Nž`0ˆX,Vpqo±àû=÷܃õë×çÜçMÂH’UU 6xuñwY–‹¡"¦ûò&db±˜»Ž‹aˆÅbèöœìÅHš@ 0æ}E•Sj|Zù£¶*HÓ²ÓÚŠz®·þ*’&¢9ª˜ößüëšüÏßLŠ’»nàh$ hnþ9dùµ.zU”ûÜÙ @>@ ;Ô°, GŽÉ™’Ѷm¤R©œQˆDµRTB¥­­­è‘'~3ÒtL¦UŸ g4Ø‹¿è U)1 Ãp“'Š¢¸ ’‰i½D¹x<Î9‘Ç@\ˆ9¶ Ùõ'‰ìh ›,¢w•:-z¨‹ D"›\ äb¸¸î …:\Š9Eƒ»x=ÛvÊ 9÷‹¡â;wÞZë]:áyGsÄbÙ^sâv“¬8FDbMŸËëó~¿©îy"Býh@âkEfÉÛñÀeeÛ™¦‰išär9IF/´œ) *ëׯgÆ ttt„!À6lØÀúõëI&“Üpà ­¾ž1¨™êQ|’¶A„:P“Ù?´˜9Öœº“ËåÐu=L†iÛö˜xËíB.4Ö“É qžÉ”ò ¨äw*®Íj¶¿®—â·F‹Uøg•¨Ð¶‘E \C°¯J®Â/©jÿ·¯¯ñiûÌ.¢‰Ý£‚„ïÂJt_ooÉsÄuK⇠Ï庥çÐ÷Ká ´­ŠC ¥ÕÂÃMÕˤZ¼å†ãÿëÅ¿ÊLqYµí=o¾h*µot;*– ‚ Â4Éf³¡xàí[ëºN___Øç®œÈ˜N§Ërªõ£££eÛEÂU®«F-ÛDÑu½l5ñJ%¾¯Vv¡=q+áM5èW> kð6þ2'kpU²ý’wWŸW½êØeÛ,¼à]¦¯»áSœF’‘‘•eÛ8ŽF*‘ü)B«©YPY¿~=7n䦛nbÍš5áò‘‘6nÜÆO£¨RÙ8Ê!ž)‚Ð* >zÒGùá{8åý3™L83Á²¬0ódÉ3[…*’Ê¡f9%¥õj@X ÉdyÈìj³ê£iH*ü‘˜V¹PT¨¥þq”åZBr Ç6–<«Jø€Ò3Á³ìyÁs¤žuõ¼{^ð¼çó¥^…BÉ+êqRiÖ*ÇŽú\¹L1m/ðJÑ"Š7TŸÝ >ôâ2­ø?d Üb J3: @ÐXÅý’qƒÅ¿^q@H?ŠÇ‹ž;]\Ÿ%èéû‘ò(¡Æ/î—|÷‹çHË• º°#‚ ³¨\(1Ñz]×c~·'b ãûþ”ű¿³à1à>l÷aȇù.ü´Îé šFCÍ:QE‰êêyׂ³ÌL‹÷îåpÇÇ X†Q–OEZIM‚ÊÀÀ6làŽ;î“|¨££#Q,ËŠ âºnèv Áøƒx§Bkp¤O~êInXTß»Âu]LÓ Ã|išVfã3…ÊaÛ¥díÑÜTqðS…9R^ Jà€`@Y…2R¨çfЖ£B½x^)ßI"QÊ‹åŽ3öYVaµ¢ÉᣂŒZ®„(y[)t}l‚x]‡¤¢"ˆGIÜPôˆ Q/‘ áUl· è%, ò=ê4ðaÕC äŠßÕúld{“@´ òWÃ(žk¨¸Ü-žKõÚ£÷!:!Ë)nÓWÜÇ”Á-^S_ä:¬â9êø>(“,Þ"×–,î¶¢¶I#ž1‚ Ç âÕ!´3ª9ô°/;°2 iMŸñš5™Ú/B¨¹húm¸z¿ö̽·qdÞ N8aWÙ¶j2­Ê•+­¤&AeÓ¦MtwwS¢Üpà ¬_¿>Ü6xžº+R”ÆE„ÚÉår$ Ç!‘Hàû~x_Ç Óq}$Ä5vyƽg°óí;ë:F"‘c6†A*•š1AÅqJ!‹T®•ÿAÅÕUa‹ #9t¶;T‚½Ê—Žçy¡‹œJ&X(èíí%ŸÏã8Θø£žçáº.žçaGÊÒé4–e…^цu- …c %gß¾}Œ¾rj±-Ë"™LbYV(ª$“Iúû›ãoæû—‰ V!³TÎÕŒ†ãÊfKƒÍj½ô3…Ù†òF‰Š‰J\Q¡ä ”¬S…³S!½¢^,Ú7Áèwkä]b‚ …e Ò')MaòŠËò”‡Éò‹Û+CyO¨iˆ%1Á$ðÚHP ϥ†i”¼2Ô9”ð¢Ží·Q¢I¡X®dñØ=Å}|q'zl%ø(‘CõðÍÈõÄèû+KI\©dr”Ä+ÕtH¯#‰„AaF¨–CÅ&h¦$€ûl8΂|Ø(“?!6xËž†Í{8ó„Ÿñ»÷+9çœ{ËÃmÇ!™LЍ"Ă𕅠Ö$ªlÚ´)V!¿<Ï#™,õúmÊ£d´Jñ<]×ñ}?\fYVCPÍØ·,+¼n×uâ©T Ó4ÃýÕ•D"A*•Â0 ºººÊbjšF"‘ —Ë‘ÏçI¥Rôõõáû>¹\ŽþþþPdQç1Eí Z44åmJPéëë#“É”yžÕ‹Ê)MÄî8A¸¡L¦z(“ ‚“ɉgË«\%‚0[‰&‰WÞW½½ÁgµÞó‚ïét °(!źÌß…Ä; d“@'øoc¥pSÊ´•ÈàQ/º(‰ÊÓDåÑ(y€$Ä5‚Áþ ¥°\JLQâ†Ò”¼LT™Ôñú(Å.Œæ7Qa·¢ EίÂfQ\fVl¯B~A¼ÝhÇ{í¦«”[]»W¼×fq›¢vÎÎs8k ÕW$‚ Â,¢2‡J† éQì üCôBОíì,yG׊šÿ"Bƒéß ópßÈ{€{èèx™½{»Ê6‰sN.áØ£&AåÊ+¯œ4œ×úõëY±bE¬¼T¢†fT|qó­DVËó¼p¹··7‡2™ Ùl]×qß÷±,‹t:†ãR&‰D˲Èçó¡(£î‹Ê?á8¦iâº.†a„ž&•(‘¤/Òê(céºN:E%àBHœ 7/¹™µkÞO=W¶mcÛ6š¦Õ3S‰&¶ øf2¥Äì¹\0{¾«+N”÷‰„焀褿d2L ä©’L=ºŽ€ûµbدL`KÞ¿¹r?n/$ <Ö/ áPEz)åòHTà¹â2µ í¥Ây©Ð^•‰ò@QIá)n«×)×¹¨³›ª¾Tu§Ä›èºl•í+Ѫ¬Ó86zâÑëT^>*O‹'ÿêd†_[›´ ‚0ód2å#Ô$<5©)“ÉÔ4SØqœqg»®F>Ð4d2Y6iJM¬Ä4MLÓw½®ëå+‹ÿ U&“ÿf7a´‚æG?`[A;Võë4-è NeÈB59Ahajùýàì¿„9sö:ï|çñèúÅe“·!.Ô$¨¬X±‚n¸o¼‘d2Éš5kèèè`dd˲ذa·ÜrK«¯'ÄqœòÆÁ¬„V¢Œ?—Ë… <%„är¹Pà°mÇq°m›B¡€eYd³Y\×Åqòù<–eašfè½R9kßqúúúp]—t:z²TC5(•2X¸êüÊ+&‡Dð"4 Û¶CáF-Ó4 MÓÂëTáÚ\×EÓ4Q¢g Æ_Á²˦ôœU†”«çYPùúú‚ßhX.ÚK…ô¡œh‚y§(,„Ỏ@ö•Åäô߇äoƒÿø/v"à‚ó¼Рo)p'A/×(ê*‡‰CÉC¤2´” «•¥4;"IÐSÎQDTe_mÆ¡Ú/êR˫Ȥ<‰05¢÷»ø;ýbÓ/`S« &‚ ŒG.— ûhô/3™ ýýýèºN.—«)ž}.— ûæeá¸s¹²~±ã8aôuLÛ¶ËÂY+&[¯ð}Ÿžžž² ™L&Œ¼ 9`f79ŠÎ±n0q®2RôT'ÍÅyr® ´+. ýzV½–N»›;wÒÑquYd•·¹š€.­¢&A`ݺu@ (o”ááaFFFX±b·Ür W^ye«¯§ ÕÐR&×Êáx˲BAEyž¨—Aooo¦K56‰ÉdÛ¶ñ“ *ãþþ`8ÚxV3ê I /ãá8EÑqèg––'“ú6X_ÿ_€èù.èCßÿö  ôL1*V’Rh¨â†^<Pò2I”oœlœÂE=OAAhÙl¶,ê@OOO8Ù¯<Ï 'ÊÙ¶]Ö†Ïd2ôõõ•?•J…bÇxe˜¬ŒQz{{1 cÌñR©©Tªi¹…Ö£"ÆæÞ\0i®£Ah† ÿüÌñü|×™ttŒðË_.óteé!.Ô,¨@ ª$“I6mÚÄ–-[€ }œÂ|)¢*3“ßUå1Éd2¡zªømÛ&‘H`Fèn¬DÏóʼ6Òé4©TŠt:M2™¬:sFÍ䉾Pâ$$(‘C¹‚+¡Ä4Mzzzض-˜ê›ËåÂÏÊ›F %*GK¡PEå®Íj&“ e¦¼]*oŒú=Ô,«8Ý«c À„ýkÚ^ Š*7I;£iZ8(:kH (@Ù,¥jÂQ4G‹j|'«Œ€«\3Ùl6ŒÃ«Ä+ÏóÈår¡(£bô††]Seš‡<³é™šï³â!áÆn¸p«^¥u¶]¡~’ÉbÂùÍ`Ý ÞOƒåîÿ;…Ï'—ò¨(TÕ6E§²©#¯nA¡ÍÈÐú| Æw…R_J¹Pú¦ÅÛ¶í0wŠš@¨ú]*O¨št˜H$ªŠ-Ñ2aăñÖáD;"»u 5ø.Ì. à— Zk*´a!¨h´ÞfaÖñ ð¼~Á0_v€¥K—räHILQczã B«˜² 2ƒƒƒlذ!6‚Š28›)$£÷F|­âçÐC Æ¨h0òƒÿø0‹¿°˜ŸžþS>pà|ñì/²ï™}œzë©ääüè Ÿá3,ú—Eìø¬zxÏžú,#ƒfj|àc`ž1¯¥Õw+†Dã´©ße¢"K´Q¬Â‡á(k:tˆ—7¿Ì¦Ô&Ÿu˜ßXüüÉþ„¾øQÜ]Ü´[‹WÅ_Þ6ÅìêÁß…{¶únµ>ÀÌùåô7ŽýA}?øíGiš†UÌz]Ùys‹±p¢ú£aÞ*†*•¼‚ L+äEÑŸm8ÿ’¯w'8;{´¬ÀKÌ0ʓ׃„XA„J¦˜¾¡%¨ÜžQj!¬&²©¾™ õ¬•|>išaÄT*…išd³Ù2Á¤² j²ÕDe¬E$‘¹Ù‹KÉéÙq—#Sœ\¡I¬„ã¶o–qæ™§pç¥Uš¦MöQZEÕ¸¡f¶+A¥&zZ¶9‚©:½Å¿`Ãß÷c.Þ|1?ÝüSw.柮ÿ' ÀZnñ±ýï]ý^®þÂÕ¼ù{oæË¿Á¢_,â”OžÂãŸ|œ7.#/›/£¡Aæyó‚ã*'E@W§$²DE› ׈ÏLÜ‚Qò4©æGî½W¼vuo&Â*Þ›Dñsq°4Á=ÕƒcÎMÌÀtÌ`{.ó..Ô.dÿg÷³õÕ[ñ}Ó4Éd2üÎ…¿ÃcócÞÁydþ#Ö«¶`øhðŽõï`ç¯ïlõ¯{\@vÍÛUu}&36¿‰ ÓV9[M%˜ÏçÇzŸ¤ÓÁ:Ü(‚Ð0FÀûðvCúÿãEÐ;Òk{Ó´à¿ä#A„ÙAe~˲èéé©F«Û¶Ñ4ÞÞ^€0¦ëº¡ ¢rdBÐîO¥Rôöö–E4¨7‡J.—›Pü‘Ð1³5äûåïAˆ>à,ƒÄ¹ðøñçÂKϰtéÞ² ±*—ˆ*Bܘµ‚Šrýµ™döùŸ 4xï Ä'a÷?îæÏ<ÀÖÝ[¹ï×ïÃ[åñk¿ö»<ö½å¼0÷¶<ÿ2ýýýø¾eY¼9ÿfþVÿÛðzQ ДRY dñ¼ÁÀ¿V,O¦¸^£Ø"  T£@yѨÏ)Ñ%z|%Êä(%ûµÔM*; Þõ w瀳ŒóÀú% _T,£ÎhIð^c+˜›Áþ觃~8·û Pœ„”ý(8ÿ ú[@OƒæƒóÐ~ Fü‡Áùx !ûÞ ì‹û 0Bï³  ©ÿŽBú“`}ü½¾¼¸GÀ;š ÆÊ`æ³þºâ}Q™å’ÁýA§Ü{GyËøâL=ƒzê·7) ..tü¤#ºÞWü—ËåH§Ó<ôÐC3ÿ€·!>ÀBØ~üvÎäÌòu>ôõ0A¤®ëaÈ5σžž`;éûÂÌ l.÷$>Éo€©X‰R]¦¼TAA˜}ø¾æ%™ ÇqðO&“Á²,4M = SŒÑ4žGËèè(Ùl–L&Cgg'†a iŽãN§Ã¾œ0»Xö¦71`,¥Y‚Ê£³«ˆí>Å>/¥@"*‘½Cyp‘á<ÚpÜÂ,n§ð)Íõ‹û©ðzd½A0¼U-:¼O)ø‡ËØ9§ªéî·.¯Þ¬·‹×¤ÎYY~( R¶o4PŒK)˜Š9ž B¢¾»‘û¥îEå= Å´âz¯bÿdäsµn‹Ú>z/¢÷Ì'>øÛ5_Ú²—¥ùùC\uÕ…e‰ʧ[K^,A˜ijT˜t»îîîšO<22Âðð0+V¬s®ÁÁAV¬X1f]­¨ü)*jW‚ó4¥0XÊÓÒ`ýå—ïæàÁyüæoncéÒûðý¥hÚ½\vÙe˜¦‰eYacOÍ¢©HRߣÀj™ú«i¥Š¾P(÷­6 ?Ú(¨Ö@ˆ–a¼çf‡4.}à‚þHÞ3v›ñÆ·+ËœN—»éVzú)AJí«ò:N)‡eÛF°\‰Kº,ó¼ Á•LËl»´ï±8?žmÂôíSßÌ ‹v®*…Þ8í´ ð<Ó4qÝÀ];ŒË;„n[n釭L¢:X*S¶ÄÝÚœfÚçÔûÕgÌÁ}90%å•¢ë¥w°xb Ç:ÍlÛ ‚P?3ZwÎ"FGGë^Ÿ' ¸®ëeû“ƒœ¦icf&÷õõMX†ÉÖCc%N‡“. …‚$¤¶ÏË–ñkíÓftý”8¡Ö•è ‚ž˜ƒÄ½ûiÈJÉRT*X5T¥Ä ³x\^‰3ê/Å}T Ž¨à¡¶ÓRß&(¥¨%R~u-:¥QaÈ£$)Â-þODÊ¡"ÐW{«õQ±§—’¥ˆíªL~d7r,ƒ’X¢Ê¦ÖG£ÃSql/r¼Å”‹/ZäœêÚÔýˆ 2•çUçˆþNÏþÍßðޝ~uªT¬iVÛ6úÛ› Î;ï«|à_*ÛNÓ4,ËÂ4MÉ¡"ÄŽš•w½ë]¬^½šU«V5ìÄJi\·n]¸lãÆ¬_¿žÕ«W³eËÖ­[Çš5k¦|l5»eŒêìR ÒGÉ !òÆO¥‚ŠwÆa¾øÅŸãy™ÌçH&“e.¦i6Å=x¶´ë\, .ØÛª§/i•ãçÑÏÊó§–INj?Ë ÆÞ=ºº‚}]7X6[~ŸÉ¨f›Ðû<:ÿhÙŒß/ŸÕžL§>u”W¼â×Éd2,_þ^~ô#“ºÍúçÒÈ­RÙ2E—%%°TV²ýýÁ6ÑX{PRq\·ä𤠡D× 4Þï8¸£„Ç«‚*µN¹CUªt™LéšÔuH<3ašiŸ•xß-~pA_VZžL–Þ¯ê})BsÛ¶‚ ÔÏLÖÂÔ™‰A2MÓd0.¦4Ú>GV®‚îY3<§kñkšê\ú‰¶¯|jö©Ü¯ž¹ý‰ –%&Ùn2òSØV‰Ú$ë-‚Aúì$ešèÜ*qô±QÝ«¸oe9ìâ6Û€«þñáä“ë¸#ñeFÚ¶:`À“_øÐ˜Užç‘Íf%<£KjT,Ëb``€[o½5\¶~ýzÖ¬Y3e5rãÆlÚ´‰{n¸¡lÝúõë¹å–[èîîf``€«¯¾šîîî)ŸÃó<ιúê±.|ÊgÐ…”U YR É¥ÍóyèéùMt]Çu]²Ù,¹\Ž|>®ëá`°Ìj]AíÒѺrÔóÎΰN§KÉÒ=/h”årÁßtº”'g¶0‘mÂôíÓ; g]õ8Æý¥&“)oì&LŸE‹Ó|ý©sùÐYËø½}”B í4XïÉ¢ÂH¾†æX5Âu¡··$ÄDéºÁ­ë‡‹i–+nê!1Œ`¹mË«uÒR©`»B0¹RôÝ‘H“ZVù@)Á%šˆ)zÍ–Uй¤D£èL=ßÖ«¸wÊ Kh;šmŸÕжAßU€éÏ£a”ÂVªPŠélɽ^ͬS³âª=mQ×þjL˜ÿLbÈL´mA˜:­¨;A¨fاïû¼´`&Aw®&!æLÖ'PëÀ¯ZßDõeÆ›òoÿò—ÌŸ?ïNó˜Ñ¶í«u]]×Ëf±$ ™Ñ2t8¼·?hui¦-…Bðœd2¥ñóÅ‹KÎÛ·'èîÞÙê¢N›ñlcŸþ Ðõ7{Ùÿ® ²TŽ ešˆ¦ñ¦\ÄÞOlâ?ç_H6«Ä¶m«é<5‘ÍŽï bš%qÄqÊ?»§c•¸g¢ >ÚŠ¯©rßJ±C•QŲ«r“ÉÒq£ñï¢e„’:ØÓ<ÐÓm”8ÑqÕ½Px^`4†QÏ-ŠR$£qø¢÷(z uÇpÖófÛgÅ8n?ô|FG+xœG(†Ðà{茰W¢ ]$pëï'[T˜„ÁL®N‚4f*µI–`¥XÍAþâß$%Q¦åÑÏ£IÊ<¯_²r›¨mV¶'Ôzig´-3Õ¶ajÌhÝ)”h†}º®Ë‘SOe×,šô(­`&Ú¶EÁ*cÁûMÎ;ï <äW&“©)´£ ´‚º•zQaÃ.\X¶|```Œ8³páªl”íÛ·³víÚ2ïÏóx±£ƒC)À£ j¹ lúÓAH'M Æ5-ðÄ1 ÏóH$ض]îK˜Þ¥ Ï’|íÑqkÓ,‰gµ–ÁÁW—µºˆÓf<Û„úíó®»îŠ.¢GàСCá Ûó¼§ÀÝS6ùÍùóIQ ÿññÇâgŒè§J°ÔêrŒG4!S”ñ’ù~ &C¹¸dY¥Š’²P)¨DC¦E—9NɃ¦ò©Ti;Ó{o•Hãº%Ïå©=†®—_c‘§¾úUlÛfÁ /4éG™YmŸ»wïfíÚµ\yå•c¿*Àó®à«ã„mÃ\' ü›WQ7”d ’^j‘Ï*ñ ”âEÛÅ¿*ö³Š¥«›Ð€.J⊊iœ$âz¯lTÓ°ŠëlÇAì1Œ;ÃgÍÖõRŒèáaôÿùŸàâ”+bÑ, ÙÛ‹÷ì³hš†ö Á1"*°·s'|á 車7Ë÷ñn¹íMoÂ'Žò¹ÞâÅèCCÁ³\PÙ¢rÙ«{£6©â¬U¼½/|íÀ´÷¼§®0Ælܸ‘7rþùç·º( a&Ú¶‚0S¬]»–íÛ·O)7f\izÛv–“ÉdÐud•:%—Ë¡iÉd’L&3¦Ïìû>¹\ŽD"aU·¦ÆÀÀëׯgûöÙÑÁnFÛöæ›oæð¾Àjªv¡ilܸ‘Í›7óº×½®ÕEiÍjÛ®[·®,•„¶}ÈÁûMž|rlȯ´²ÐÖ¯_Ï]wÝÕð¶íŒ *ã1<<Œ‡Æêï'MyÒÒ\2‰‘LbÙǃÇÃ.Þ×|æì}s÷n²Ÿþ4ÖÇ?Ãø‡À>ûl²k×â®[‡ñá— “J|šITÈØM›6Íð™g–F¶ma¦¶íÄDÛ¶³¨h%È3šÁ4M’É$¹\Ó4C±Ä÷}zzz0 #œHU¹0uV­ZÅ­·ÞÊÚµk[]”¦SoÛöÚk¯å§Æƒß“¡afY³f ßýîwgMȯñhtÛV;¡–\òåÚ0f}*•b[##•Ç$Íj·ÅFP©63app°L½œ29‚Ñ„,áV§˜ê@ÃG³-ð}ŽüÛ¿±ù/ÿÃ0ð}MÓЋ-+ Û¶mììéL¦< OeösÏ+åOPT2ZV)i5”»>D×'µµ¢á‰¢åŒRYÇ)% Ñõ±YÂÕ1T¸× .£J±Ô½¬Ž'ñáÓJq£Ç€Rþ …ëÛ¨{éyÁ9¢×“˕©ëýýå××ÓSúìû¥ÑóôöûªÄ9Jý‰^Z¯Ž½*ött`-_Î6 ·w/‰ë®Ãëê›;ó•¯$ŸH`ɯ|Þ<ôþþàßßOA׃b¼ü2Ù?û34ÛÆ,†ÖJR²‡cíØAæ oÀÇ;ÐN<ŸRx0cùr€µhQ ’,_N’W‹³l=ý(yJž0*$Yž@Q’^çÅ“$‰ò” ƒÀË&M)¬™JŽÙ_<– kæ„4SçR^:`_|1Ú«_ˆLEoGÓÂs".¼0S²€·t)}@jñbz¿õ-¼È¹|€|í…HíÚ…5w.ùÇ#Y¬«J?ª†ND®?Uü“”œ}õÈ6ê³¹ž¢7é#v,Д¶­  Aì³6t]Ƕm‘ .¶mÓ>*¦äkÉu(U˜Ž}œ7/LA)BcixÝ9<ÓÏzè蛀¹0Ù$LAh!5 *ƒƒƒcf+ÝsÏ=cfÖ«ü¬ZµŠ7–-®+±Ñ§žÊo"èÕW„ÛsH¿÷1èýX0gšügG `…¾¾><†f<Á1*“oFà¤DŒj¹*…œjL_Ñ0Êsq(a¤²lÑC®;VPQù4<Äñdzs„E˜ˆFا~ìš· MÓ°íâmÍF\ÅŠÏ•Êa;f[e>›zÇx‡½‘õ'€ó %áAŽ—mÍÀ+Ó°Ý# Ä+ 5oÁØ¿óÿãð}ý[ß"M0؞ݶ >úQ Ó Eñ°ÖøÜ稴øðÉÔ4´Ï}nüÂjÉ«¯&A0H}¢£r»ªå*k£Ê²¨`­Ù”'Ƭæ;•¬²^Õ~Fd/ò=ú¹çøãð÷ŠWœYåø %f(¥óŽ;½£#¾z.¼0ô€áÈò |¨Ð¨ŠÏ‚mÛ¡¨™L°¦¸ÎÎY8WO**_uàðK-HJÿûƒî}=DúÏÿç[ß ±{7xÚŸþi н=òw­òDl Ðl¶Qµ“N¹ðcT¬soÙ2X´hÊ÷@½9«ÕüjÙPtá /@&AÊ o’N‹Ê™£Ž—%\l+C žhÅÏYJ¢‹^\ÖüÝž=<ðš×4è®Æ“FÛ¦ #öYÍ?‘(èë+w¾‡`½ç•ÚÒº^=õ:FtûjçI$&îN&“I:;;CÄó<|ßÇ0Œ2AE‰)¾ï‹˜"L›zíó…bøÖjs&a&رcG«‹ÐTUwúûn‡w3tÉ<ü‡|Îíx¸(Õ52.$Ä™š•5kÖŒMZÛÖ­[Ç7ÞÈêÕ«Ù²e ëÖ­«êö5–-Ã8…pdÁëûéyö6Ò6¿J„¨LÓÄ0 ,Ë’`É傆ÌlÏ#µû¬³f½ Ó³O`$èl$»· ½yuÙ6Éd2Hü,­_A˜2ª?ñaëÃpòr8èßuáLž7à$ÒžGâŸ@ÿÑ ›-yJT$l¦Žzûé»vÁ%—ÌÀ µÉ=;«”±R°IPò˜‰>BK‚’Ø£øðöílÚ¼Þò–æ_g i˜m ‚ÐpZmŸãE_˵¼¢« "µìWË6š¦ašfè•RþK‘J¥H§Óär9,˪šÈ^¦B=öùМ9œ|àç‰wJÛâû>žçV0ŠWŒz¢þšL&v]MÓ‚|ËÅ1 ò¿ÚdjÇq0MÇqÐu=ü«ÊVY>×u9|øp«oߌШºÓŒ‡Ÿà±À¸Å`xx_¸N öŽãÔô,B+hY•j ‰Ö¬Yz¾(¯˜©â8/}6æ-Àe>ü[ ‹$‰ëæWÍmlšfø¢4gSÂécÛÁì'y÷µã%ÂŽ}ú€q˜0´WïõýCåÛär9‰„Ø¡ L@3ì³ ¶Á^–KMòa°â®»ð>ýkС£ßyg«oE,P¸z¼Zs¹éŠKo» ëÚkÑŠ3,1ƒW®ëây^Ù2ÇqÐ4­±Ï+ÍŒ¨5—[*„Xÿ”÷lOšÕ¶az4½îœå¨¾²Tòù|8 ©H§Ó¤Óit]'•JIz¡fiŸ?þ8§.½ð˜šß£œ=Ï›0t¶*TÎ`Ïó°m{ܾïãº.º®cYétšÞÞÞÐc Úæt]Û¶I&“d2²Ù,=== 2™L8qRy¶©óCy[Ú¶m²Ùlx uL%Ò¦R)²Ù,]]]ôõõaYV8v`===äóyR©‰D"<6ÞU•»U]SOO}}}d2™0r¦ieã„êæy©TŠd2Þw€Î8ãŒV? ¥émÛS`àÀš¦ñË_–&“ù¾/¼{¦$¨¬_¿ž‘‘nºé&Ö¯_φ ÊÖ¯X±bL,Õ©ÒˆÆìáWœL‰|&ºŽ™~WÕqÇqp˲èïï—™ñ‚0 Ӳϓƒ?Îû1Îy™Ê´ÅétZlP¦ACƒ<Ø{&,6áµ:¼ø®¯Ýõ(_ùÛ¿…ûî›<‡XÌq]wŒð :nÑõ©T*4RÊhgÔ4M\×Å-ÆQ1 #;TgM ™L&<§šÝæû>™LÓ4±, ]×9ûv¼k¯åÄ¡!r¹®ë†çÂYtj™ê¸F;“ C×K±bz{¡¿Êñ3²ÅÿÇú›=µªy^ôÖÿÕÐ\Uuù®êUWïq/²ŠujPª+¢õI’ žò‹Ûf(%žSÛCòÑGPx04Ì6üÊž¯ðösßÎ+ó•œyÁ™¥:Ã…#¯9½ﺗ_Ûõk¼ô¥—üÈ çþ×¹âñœrò)l5·rüÊã1,ƒá§†9úÇGøÎËŸYÀY ÎbÉEKü^Ì¥&w\yo}î­áùòÚŸ0:4ÊUs¯bdd„3?|&Ÿêûš¯awÚ-å?þ÷?XyüJn}äVnüÎtþG'×pà¶ÛncÎÒ9¬|j%KþßVo ¢U,ýìÒ0Ñ^ÒLû$ûxxäa®yøÎxä ®;tº¥cwÚ,²1šÀÔÍà¾ë¹¼™gQ~}‰>vÍÛŲIJR¯¶+¶[ ÓúûúÁ‚Ñì(П ¾÷A¹ Ãöõ‚}uMƒÒÄ&ÕÎqà„SOà›|s&L£å4¢îÔöƒ·Ë#™LrÛmóÃuš¦‰(/Äžš•Ï~ö³Ü}÷Ýe*aww77Ýt7näž{îá–[niõõ°õða´=>ü­›4Èféí›. •J¡iZYÃPh,®;y áØÀ>|0˜åÑ7Šqéñc¶‘Ž— ´—pPíQŽ8À¥/=ÎÎ/½Þºþ$›—º¢mÕ¼EÔ ÚèL8˲Æ4Ò=Ï£··—d2æRƒ ,h:ƶípð(™L†³õ”°¢Úê<žç…í%å}§f°™¦‰çy˜¦I.—Ã0 ²Ù,š¦ñèe—qÞSOqäþûIúÓcÄuÝ*L©jǨY}ÑíÕçj’çyᬾ ½Õ:Ï \O§8SìXRf”åƒCjð‚5ö©b¶é@oqYt G=Ž[üÈr-òÙ¯X¦„50•©(‡*—Q,‹èPå²+Ê“#OIȉ %ÁE¯Ø?Z¶¨p`RžÈ‹ÜCU6‡r‘"*TxÅíÔà”‹#~d;"çIFÖ©2¨Ášè=P÷Û£üz”~¢$+ÒDï™*gô:´òãÌ}q.‚ Pa¿Ô¬ïÉÈçótuuUõÄ„frpÞ<|÷$Œ·øuLô1´Þ9J¢I†Ò{_‰Ö6¥w°j*©ºB;I©Î€PDùðC‹†ø³?û3~ýÒ_ç­é·²ØZ\J(—&÷vÍéâÓ?ø4¯»8œ„óaýÃhŽÆæmæ¿~ÿ¿xÈ|(œ@“N§ƒÐSÓÑÿNçB.„¿ NÝau°ÿÎýüùÏÿœÓþó´°Ýyù§/#˹Ìõæò†¿{#=Ây¯;|8Ï?/¬ë®Ö®N¹þpa‘¿Ü -Œïxì Ã×îûú«qò©'‡Ç&K©}àµ;®…?„‹ý‹×÷nJõsD”Pm‹sÃ9ÀkàÂS/`‹‚í¢ûy¥ÏzFÓeÞ²’ðe+ˆdCœSµˆOÕãê~dY¥úZ•]‡v½K3=ë1ãûk°.ü)¾‚Ï|æ‚p]Ô»HâJM‚ÊÀÀ7näŽ;î`ÕªUeëV¬XÁºuëX¸p!ŸùÌg¸ãŽ;ZzAÿ÷«_ñžíoƒkæÁ{³åɯ#¨™ðb¨ÍÁ0À÷%œà„sv¾ÌɺŽû¿ HfO³$„Öb t8`ÃÞ%‡y×q¶öZ½á Õ3Ͼï‡.ÿЍ˜¡Èår˜¦†P¨JLP#ê³ ‹ \öÕñ”Ljše«–E]úªƒJÕfRULRÛ©uªMrÉé§óšO~’w~úÓa9£¨A­è¾jMÓp]7JTÙ]ד.êÕR‰ºoe! *ßϾ„“÷vkð‹ÿ{ :ýjТrltŽBµyCµÌaˆ>æµüÜz•ý&+‡9É÷ÊcèU¶IÖpŒè6Q³LŒó¹ÚqÆÓÇcžìzõö«v-Ùq¶¯¬f•ãTGÖ?B÷±â¢"Ô„Tji¯kšF>Ÿ/ËU Á$…ÊcÊd*¡‘ì>ë,º>´S_,HQª-J‰ÝL P\ïÔ1Ñ÷qvì粉;Ñw¾YZïà 9ZØŽúÌ?Lz¹8/¥k:™T†D"NÔùÒã_{! 8Í8^­—N·Ã0B[w"LNIžB¶Xà²6éxõ„Ëÿ~yé{Ô;t¼:#²ü﬿#±4ÁüÏçÔß8µúöPž`/RÞÊ{XvÎè>ãÕ•zÅ1¢1f£“ò‘òT{…MÖÖ‰z¡ UÙ& £FEP™ _ØN.÷&L³”ÛK¼S„v &Aåî»ï¦»»{Œ˜å†nÀ²,&Ü®Ùì^ñjV>õrXXVõ µj6g>ŸcmÉd0™Un­À3pö3›9rd/‰ßE¿|¬{h.—7†« Í'õH¼žÈÀª7âÉ·ÈåϽó¹™}—WÎhu]·,~q.—#™LÒÛÛÎÔSÞ*™L†|>†#) a˜¬¨ ­÷ûûÇføPâMTÄ™‰¶Â¡Õ«Y~ÒIuyÍ*GÝ+õÝuݲfêºÔýªì˜kš6yøEM *ùtZfNÌ.¥"JD‰ˆ£µ  ftt4üœL&ËêĨ‡ct»èúèòjÛB3xà#§£=@Pgæ êÌ^‚Á÷~ÊÝg ”êÕ PaZUû³¯¯¯l‚®šÌ¢ò>¨6˜ÚÆ0Œ°-¦r†N–7Tµ;ãœ_TE{‰å$åhHÑÁo-Ä|×/›¯ú~’CEˆ;u'¥_³f ###eËV¬XÁððpK/èäC'sÁóûSñý ìTµ¤dÑBãqœ@Ì/oAñҞ͜|ðÞùcCϨ08‚ ´ÿø`rû|Vo¼—óìSq?Û® Í •J…!« ”0Så"Qž)š¦ÑÙÙɶmÛ0M3 ÏÕÛÄ,Êf³ø¾vp5M«:‹6îõþ¢¯|…뺺‚œ%uPù.Õu]×CÏ%0©í/^ÆÍVÛ¨<-•Šã8áñH$ “ þÊû»ù¤D¹Õ‚ÐÞ¨¼:Q[V¹ˆTx"•‡ÁªØOͨ÷‹Ÿ3Å}”ÂEÃÇAyȸ$¥|Ñp9ÑrEÏkT”O…T!“T®…O0€mÏ£ÊcGΕŽ,KW”G‘ ‚I}ŽæºP¡•ç:F¥g—U,{_ŽT÷"UWc¼õêx•CmS­üQáA‘®²¾Zù‰ì«O°Qåûy"ªÎP7'YVK¤…èöÕÊ0Õõ“C‡§n{ª†‚›lót^uòñEÑŒ*…B0Ä-*sx+Ï“l6[uÒŽ¦i¡gï±NlÃ})”0*ó~b‰¹y€7¿¹+âE(*B»P“ ²bÅ n¸án¼ñFn¸áÖ¬Yz¨¨„õ7nä–[niõõ°oÙ2X´FªMZÕud2yÌÎ"„–ph„áS—°oß Tšžã8¤Ói±IAh!j2¥½s''²<¬?ëÕ+\×3oÛvcZå8I$$‰19K¢ ßg¥ÊxxÞŒç$Ñ4­,g z²ôôôP(Â`êw7´ƒeÿ}?Zt]ÜU§‹ «#B¼q ò4ôÿ&l·Z2æc¨Z„™äø³ó×ïžÛ,Ès½y^Ð6Ñõ0¼ +kYÛòù`}6‹U mzí»ß´?}?Ø¿Þ~jÞ0íL5æX1‘Ø*´–'\<Èœ9]Øvû‹± %'EjΡ²nÝ:.\ˆeYlذ¡lÝŠ+¸õÖ[[îpž÷4¼ÛÀ÷«çN±,«|†¥ MÇ?¯ƒ¿6^Çÿ|o9û·åëLÓ”_‚Ðb\@{9˜i6åÆôÑ«(*d—a˜¦‰çya˜.Ïó&œ?Qá³bàõ¡ë:Û¶m#“É„m¦I'¤Dã}:Nð_¨¹}‚Tˆ,öÊ!ðühýk\Ž9ŽŽ÷}àž$e³*„ 5`ûÓÓN šäó ë¸®K"‘@³m¸í¶Ò‘hÛ'— ŽçyAc9‘(µ}l;8^tfR´ëºÁzUß/÷–q]èí öWç¬<¿eÇUÞ6¦Y~ŽÊö—뎃Ÿ‰$?2 Æ4ü£×§ŽQ™×q0<Ͼøbp¼‰Êacï…ºÓ ÎÁù¢åˆ–A«òž7þþYàC>hŰoêž©òDq#q}ìyÔùu½$²Ucî‹/"Le>O¿â,8›Ã‡K‹UþLAˆ;SJJà 7pà 7°iÓ¦pÙÂ… YµjU«¯Ú¯óF€®ccÆFßûŽã„Æ)*3‡?¿8ü,cÖÅÚMXŽ‚äS[±®ÔYIЇ˜ÎX¸mÛa.Žd2†ŠºoSž'S¡Z§µ…d³Y|ßǶm’ÉdY{…ò^)Ç*;Ö¾_Šc.m°ÚP‰œg õÁØA‰zŽ%¿³p,`16YºD•„–ðòcóñ~VeE¤=’ÉdÂÜ'^&ÿ®^ÍRÏÃÊdJ!በ!<^Ø¡¢3Ã’ñê?Ã(7”W¯ÚÞ0‚˜õÊ«Æ4ÇžGõU{ªr½®—·¿ªµ)ÕzUïWG×K^=ãQì(\wÝuÕË¡Îm[T›DÕÛ[.¸T ;¶|Vç¨T»‡¾_Ú_ý^¦Yî…mY\ýå/³»Êx‡P…#À?iŒìy3+WŽð¦7•VU†ƒ„¸2%AEO”jìÚµ‹Ã{Nª‹Ê¹\ÇqmuQá˜Bß##+Ç´³ÜèLAZËþÝôÿÐÃI¼M£ÌõºVT,åt:MOO‰D‚|>_ÂK˜ÕQ‹*±=ÀÐÐ$ |ß“µf2ú«Ä$ïíí Â:ª‡*• "æÏoõeÅ—êá‚*ÉdJaI |¶,ƒ¹\ivfå€@OOðW JT†k«œu c”R©òœÑA (ͼUë!Xy«5ÕŽ¡WÉdy9,+(‡ï—fÝF¯ÅóJ#£rÆk´c¡»&*G5/­Ê—ªš%¬fáV ‘žWºïê·«ŠyùÙn£iZÉÛ¶P`§eq¡¦•çó¬|G™hÒËT'"Œ¥A×Ço„OÖ8¯eBDôÚªµÑu=È;3“•c²s¨ëŸ(RÅdëal{¦¬Œ¸NRÖÉ®EÓ&>O±¬ÿ~à÷Þy'B  ƒþb;G>ûF6l(=¶"¦íB]‚J\Ù²ýE:_ê‚þKe]çy^ØñaÙ/½´`LÛNÂýBLX<ò úßo•&ÈÕBÔËÌu]ìâ`g¿xƒNÃh‹0Y}}}躎ã8d2<Ï#›ÍbÛv™xæº.Ùl6x4-€W³ÿìÏZ}ñ¦RWSá7r¹±Æ©êщ&ózšl  ‘˜<ÝdmìèÌ[õLTbšAYÕºJ/Öj³S«GÍv­–—HÓ‚kQÇ®æM£„%2x^ùy« ,ÑÐ$ÑsM&Ï4ƒã«£jû«uê|•eM$Ê…Øj×-kµ{¯fÅší©ËjÆ#ðN‘*OZоçô®£À»«®O¥Re¡¦UZÃ0¤Í*3ɉ€ £ÿ9ÄSOýÇqÆz½ BL™U‚ʳsNåÜÁ]ø~PVÖ‰…B!ta9i'K¶ÞEÚÉ•-V³ÙAh-Þ“À•k@«>!a",ËÂó<<Ï£P(!_6Ð.ÔA›*¥âêe¿u¡P ··7ÌW7nRÉB/üÆoðk¿ök­¾„øâSJj­ë±Ê«#BŸÀ3%ZoÚv)4]eÂj(y›E©l «z@‰Ï•ÇPI‘' í£’¡9Îøy¢IšÕ>Q”Çd4t¥ õªTÂO5AE]Kµ0~ÑÙP= e•–ÕrŒd²ü¾ZVàá§ÊïyåÞ~ÕŽQyßm»Tf±rl!•*yÆ)±l¼|ѲFï«JJ®ÊUy-¸ ÀÇÞzjÕuUC“ ‚0ó¸KæÂn—}ûÎàòËU•¥‡“ô¡˜U‚ÊÀÙ\òô2™òv‹ïûh•q1A˜|ÀøåNþëðYc&¤Y–…iš2 AbÀwÖCþãSï³÷ööbš&ŽãŒ™õ'[DÃ8¦R)4M#Nã8ÙÈà—ïû¼êU¯juqãC0Pkj"¦B\ñ€ÊÀŽT¤ÑÐuQj‰”0Ù6*¬ÝDLæý¤Ä˜‰*ýZr$LÖ†¯åZjÈM0aYj9Æd±L+MPÝ&›-yU»öD"ØN‰*µxÙUž'› ž#õûˆGOí<‚þ¶Óª®* ÖKb‚ñÌ ,#Æzž‡mÛ¤¥Ý+´ ³JPyùø—8oõqüÕ­åaœU2zÓ4Ë:ô‚ ÌOÀèžQÞpæ×0Œò„ˆ)‚žN(¥·¨Å™Óó<|ߎ‹"Q¡½úûûñ}¿ê6Žãð…/|›o¾¹ÕÅ/29OâEîkµŸ zK¾ÎÆÓ¯×©¶Sªm_K9T¿f¼óÕ‚O×kÞ„±={{zz$—® Äm÷ð³zµš¦‰¦iÒ¯Ú†ãZ]€†áºlyõ«±ù’É$¾ïKîAh‡O<ÌwÿfÌòL¥k½ ­á¹{Ùµ½<ûdär9lÛÆ²,4M“YBÍJ¨ç¶m\×ŶípùŸÿùŸsàÀižaó;S0HAf–°¥ v:Ó>” !û™yU—§Ói G+qâ”}°Vç ÿ.\”J¥p£a(!æÌßçuî¯>î¼1«2™ŒT¢‚Ð*–Áso¼ˆŽÓ÷g†‹;;;e¦ ÄÜËÏàÔŽ—qÝãkÚ%—ËI½Ú,f©'­SŒ³ßÙÙI"‘àÁä¼óΛæQg1) ¾QC8AZƒfAœµïlAhGŒÏ\8fY&“‘öª Ĉ`ºÐy<´w„Çë —g³YñNÚŠX *ƒƒƒ –-[½z5“îëwu1øØ.6õ-f4™LJX!A˜&õÚ§û œô³à`i™ë’H$¤Â„1ú“ø×¿<–5±s„ïûtuu‘H$Ä#E¨%žû¾®ëd2þôOÿ”;v´ºhM§nÛvÁÒ‚ÐLê¶Ox6iIp-ÍbZmÛ‰DBAh ÓµMЇ‚ÏÑ}2™ }µÄ„˜+AeýúõÜsÏ=eËn½õVº»»'Ý×=a«q²T%¾¡~êµOÿ%xù»>‹ …Ë4MC×u„Q¯}z€»ÂƒyóÉüQƒµPû\.‡ab¿B]hšŠé÷Þ{/?ûÙÏZ]¤¦SÛÖ“DÄ‚Ðdê¶Ox{aÆmÔuƒI*"ŠiyÏ £´Nõƒm;(ža”vœ =‡eÛE?{^p Ó >«ïºì¥Ú14­<_»ëßÇ;F"”Í0J×¢PåõŠù¤¢×¥Ž§–«É ¦Y:‡úit=(ƒïË4­üÚUŸ}Ùi§±$2P3©TŠB¡0%ûõ<]×±,kL¨0Çq0 £êñ\× —+ÖuÝ0lƒ U u\õ®Ñ4 ×u1MÇqÐu½ê¾ª½ iÚ˜²)!IÄ`a*Ôc›;´ý°>%ô‹Ò€¿G >(ª öOw˜W'Hª¡EÖ©ò¨ïQ1EYtô8J8’ÐâVìßJ¼:×Å‘éˆ@>ðÈ«^/¼ÐêËh:u·m“µoªÒ•H@& ”çóJ• U-™f ¬hlÛ6N¦P†jD«²jÕZe-[t?õ]]ÛDT›ã½Žè9£ç©Ü¯ò<éHtÄZ&8W»Þè~õ#:QíÑeÑýÇ»oã•síÚ×M^È6g:}OEoo/ýýšOÉtmÓv}ãøú¿Ëu× —K¸/¡Ýˆ 222Àg?ûY6mÚDGGëÖ­cÍš5î·}ûvÖ®]Ë™o¿ž³7?†~Yy"25 "Í`íÚµlß¾}zê|P¯}Þu×]Ì}}Çí}swÍ+['±l…f200ÀúõëÙ½{w«‹Òtê±ÏÝ»w³víZ†>õ)Ò÷]ÈeðÀ$çéííeùòåX–E:Ʋ,t]Çq<ÏÃ0Œ°Îu"S;•Ha¹h<â2ß÷CáÃ÷ýPÑuß÷Cá¤r_µ­:Fôœ†a„‚ŒÚNC•Y­ÆœÛuÝ1mµNMÔPÿÕvêœ^qj©®ëxžG"‘ ™L†¹g”0ä8ét: GQ(ÊÄß÷éééAÓ4úúúH¥Rø¾O¡P —Ë…û«2% lÛË”ÍfÉårhšF2™ ÷) ø¾eY$“ÉpÃ0H$¸Åiµ†a`Û6º®‡÷ضíp¦§ºGõˆã7ndãÆœþùÍ0‰ØPoÝÙ¿gkÿ÷y÷ïÜJŽ@|Pb„$˜ºh2™gYô™w]]ÓB1T=SÑÉŽãàUüöš¦ž'Å)隦áGlÛ/N)W¦aè”?Kê³*¯:Ÿú[Í~£©ã8¡EXõ\+»TDÏ«Ök‘kWÇP‚¬ïûeeŒ'ú^¨¤²Œe÷ºŠÀ«–«²Dß+ª<ýžµ´°Ôñ+Ïõ£o›çv}ŠOY{1¶í[îz —~úÒê®\@WW0®ÄåY¢¼2òù’§H5ÁDt{¡ªm»}ûöV¥éL§m{å•W†Û¥Ó’‹L˜6n܈mÛ¼üòË­.JS™î¸íºuëðW­â¬Ÿ?ÀÒ¥sÃmlÛ–±[¡)¬_¿ž»îº«áã¶±Téîîæ†nàÖ[oeÓ¦MÜxã¬X±b‹>çœs¸õÖ[Ißúïlíf«]šéâyétZf“ MãÖ[oeýúõ­.FÓ©×>ßýîwóßgœÏI/=Íë__ ùeÛ6ÉéN­„ Xµj·Þz+k×®muQšN=öyæ™grë­·’Ì¯Ñ ¯™`îòË/Ç÷}öíÛÇ‹/¾Hggg˜KE×õp0?›Íâº.ét:l«L5ØÈ†rt qªñ±U™¢ß£ÉTPƒ¬ÉdrÌÀhgg'ŽãÏçCOMÓ( ôööVI”x¡Ä—ÞÞÞPÐÉd2ضM>Ÿ'•JÁ€Aoo/Éd’t:M&“!“Éà8NèU£òÉ9Ž ?–e…åj º··€mÛ¶‘ÉdÂϹ\.X ðVJ$d³YR©¦iŽ «á8¹\.qÇ!™L²fÍV¬XÁ¦M›ö,Ä‘é´mÿðÖ[éú)y{¨»ëû>Nñ7Tÿ•}A¹¨ ÖG½ÃÆ Õó¢ÄЍø`Ûö1õ,¨m”à¢DU.%¸*‘S "Q#*N¨õÑ}¢çPÇWï%ê*”@” „ªLJDñ<¯ì¼ÑíÕçh9•hZªí§Ê­Ê ®Y•1zÌJ!v¼²DÅœè}V÷7ê±§ÄŸè5DßÃJôQφišeçó›ßÌÏþó&XD¼˜NÛöÒº´KË–»nÞ)‘¢):á6øý´²g ZeBbµç"ºMT`TËÕßj"ãDDŸ£Z…òhY£Ç‰z’F×G…AET­výÕÄÆèó½—Ñ{ Öiš¾¿*]­¾¯|7ªûÍÿ}¿EQç‹–=êm å6¯ì±r‚GµcGyþùçkú}Ú™é´mj’‰ ÌkÖ¬aÑ¢Eüð‡?luQšÊtÇmÿ*æØ-E1‘ ·B³X·n]SŽAE ~)º»»y×»ÞŦM›jR‘\y§ôÿŠƒ‘eÑAêgZöyèæá»yÛÛ~=\$ Ç¡qLË>÷ÏÏ»*LšªðFÜ™vÛÂpª‚ 4ŽFئ ,œ3×¾ö'¤Ó¯nõ% BÝ×ê(”«˜ŠÉ722Â=÷ÜÊ+jÚÿ¥ùKyê©óˆ†X·,K”NAhӲϗ籗R,Qß÷%9  4騧ÿÜóp¨”‚ ]]]¡WD\f¸ õašf80Õ××z ö÷÷‡ÂK2™dhhÓ4I&“˜¦†nS´j€7:p­>G‰¢^6Ñ\jpÚ÷}~ñ‹_´ú¶4zmsßé§£ïWWWWè9T«˜ÒhTþ"5[\y,)‘Gy"e2,Ë ÿær¹ðsWWŽãÐÓÓƒëºôôô„^pŽã„ëS©Tx µoooo¸Ú×u]/^~·mÇq°,+üï8¶m‡^^ê´Ì½½½a#õ<+­\..‹æ2‰†‘‰†þQÂc4tR44™:¯š5­ëzh›jp<êU¤Džh®¢¨7œÚJ«Ú>úYí£þFÏÝN•Ó0 æÏŸ?ãÏÙLSwÝ9êÁ‚¾wÜ1ÂO¼Ë.û/ …Û¶m#›Í’ÍfÃû/u¨ LéŽ „„fÐÛøÈ‹çrå•§‡ßUˆbAh'b㡲f͸úê«Y±b[¶laÍš5“&7Rô¿¶“Õ»wõ€®;­ Ó²Ï8å”ÃáW¿_Â~ Bc˜Ž}z/‡>¼ Ö;ž }}}èºNWWW8À.Ì&ê¬Dgéªw´iš¤R©p ?š":k^ÍàWÎÑñÑ<ã勘Ôk› ž{Žÿ2¹¦i6´¾TA"‘…†¨'†B JTµ,+ÌÝ£rýe"ÊÓR™0({‡†zB©¿…B!è¯Dí«&c¨}”§k_4IÅ8DE(…ž²}Õ>*„ú®þV{Oªû¤îƒÚ¶2d›ú[ËÌøÊ}Ô9&Û*÷©ü[É~ðƒIïi»S¯}Ž,>À—¿|;‡a·¡L%œÚleºcC* eº¶©øïç°øÙ’7¬ã8u…†„VAছnb``€ááaV¬X1%•ó5?=ÂégžI´-ÛÕÕ%a…¡AÔkŸÎ¢hª±òð5‚ 4†úëÏ#è§a9‡Šee™Ê*TŒ ô÷÷‡ä*¯ ”‡GÑu=RT(¡Ê„Á*ä‘bÇŽ­¾´¦3¶­ÊuS–eàaFÚIyLôööbFhãª^®æ‘¦Ö)Á@‰j ¿šà3Þàòxï”c}ðPh õØç#—]Æ;Šžw7Ý´š]»ÞÙr1E…UŒ†³Ëår$“É2*åY¨–—cb²ýh¢õÊü#¹\Žl6†•Så°,+ »W™‡Å¶í0Œ]>Ÿ'•J…ß³Ùl˜T^Õ=Ñ0u¶m“N§I¥R …²cEϽê=ݶ¯¯žžžð{:ï™ÊÕ¢0 #,k.—£¯¯Å‹S(èíí¥P(„ž…Q¡:ÊÏ4Íð^©ëTsE1]å‚Ö¹¶msÖYgµôy›)¦SN”{G„é1Ûð€ÁeƒÜ¸à¥p™Œ íH¬ ,ßT<eƒ–e‰˜" ¦û¼|àW8ï«À—ÂNŠ ¥®úóÌ3á³Y°àþà¸úêŽpöµøo2!²&Úá‰&ÛUy!Òé4‰D‚ÎÎβÜ-jpò,4Mãío;hõ¥Íõئš][Ë@­¸T᪔7P4Quô·‚ñ“›·z`Xfšzûžo~óA®¹fyÃmF‰#jÀ=‘H„mg%TG£;ŽC6› …Ѝ`%¯Âhx:Uf*O½Ÿ•Çat ¿RàPïU/Dsü¨÷¿à1áæ‰DY(I]×CO¸JÏ5õw¢A6%ônÛ¶­,dLåyUy£!ôÔ¾ÊC­ò¼ª|ÕÚA•^fjÜAý­eBŠÚ¦šÇ^´|•×»víÚ†>sqf:cC28+Íc:¶©=õ"׌þ”•+KáE£õ‹ ´ ±TêÁýÕpoyËn4-˜ ¬„“„¸3ò‹ýÌ=®äª:R‚ Ä€!à)8xð ,(4ˆÎ^„ÉH&“á >”çwPƒújMÓ4.¼ðÂcFP©5 :*Ü–ëºd2`¬*3t¡ñüÝßý+‹_Ê×¾¶´îcDsJ©wd&“ ½,T[YÓ´0ŸUµös¥çX-¡èQOè¶ã ôO^o¼Ptã…—«|75B˜ªÌ1Tí¼ãí7Ñ5 í‡mÛ®V√·•¿>|{ÌK€`ì¶–ð­‚7f… âßù#^}ð¾Y¸Ll!xæ?«Ä¶‚ Äw)0 ¿båÊ•eëÔŒX©O…Z‰J¥Óépr‹ Ù¥A´W¼â<øàƒ­.rlQ^&­·,«ª÷‰ Íåßx”7¿ùýSÞ/j·J\VB´a¡Í+›®%?ÎtÑU˜mxž'ÞÕ‚Süû€ÓàÀeá2æPê#¡Ý˜‚ £»èÔ1æ–f Y–%.c‚ÐbN|ñ æ-}‰W½êàòšÃ—‚03è»–/ÿW]UªC}ß1E˜*¯ ³žÕLÑD"iš|ç;ßiucçyãÚ_.—ÃuÝ ©WCEá©§ö<¨ìçº.F°NÓÊëûÁµŸÚ×ó‚ÿêÒ4-øåÛèzéøãß÷ƒm†QýÚTYÔ9ŸŽ§Ä σB!8—çA:üµíÒ࿚£¤M ÖGEÓ Ž¥Ï‰D°aÇíí –ù>¤R%!FÓ‚ëPåReTƒZ–J˲ÙrQ‚óhZ鼦œO_×KåQŸ•㬺_}}Á>¾œÏ¶KÇÐõrÂ0‚eŽS.d¸n°åT×iÁòB¡ô{f³¥ó)4-(›`2™òßSÓJû©c¨ëˆþ^ê™P×\MËdJB”*À³Ï^JoïžV›@, B¦«‹|€ú©î»ï>æò‹/&Qì›ú€Dwõ*¾G—y€Vü?~ñ¿ùî¿Gí×9þTÐ"û×J=ç™h³¸®r}³ËfF¶þ>¥ß½Q÷MýÞS½™À'qær8ôË8xðQ ˆŽÉd$ä—Ð–Ì AÅ=ã,Nucþqð]Å“–[Ah-þi>þÏcá¹çV@bÇÂyüã?îfÁ‚Ÿ ëWÁ¤åE Â̳gÏŽ?þRºº‚ÁpÃÃÈàyét’zMsÛ¶Òçþþ±ë•@ ˜¬]ŒFTFÔ9\­'Z†jŽäÑeÕúÖÕÊ]Iô|££c×GÃêW»—“•q¢ãU[-³*[ôÚÆs4šìÜÑãÖûLDËý¼~ýw€îú:ËÙ±cG»–âyyöY8é$.¸à¾å-l¶WÇ›äûxË&#ºð¯<ŽN0P¯Ê”€£ÐŠËÔ#æ0V¤q"ÇŒNÃp#Ç4+ yUÖG÷QÛWÓ‰,WûhUÎãGÎQyêQÁJÝ¿Ê>ÑóF×EÏïGŽQy¿¢ç‰>3êså9fä: 1nø¢‹&{ Ži$d­ ƝÂÉW¿ŽÕÿ±xŸL†ÚšY!¨pæB~¼ùŒÐ½]Ó4S!hÏkX̲÷ü Œ§/Bëñ÷î…}ðøã÷ð{¿w0\nÛ6¾ï‹ "-bÁ‚œrJ–¿üË` ÜqLÓlºMÊœA˜œ;v°7µ˜“5(¼÷}Ç ëÏÙ:‰È¬qÙD˧züzÏßìënæ~ãá?ëmgòù¼x¨BLqÏ‚û¿9Ÿ³—¾alu]=Ø¡8®ÕhÃû_Éñ'žŒ¦N•øT„ÖrÊÈ)=z”eË´º(‚ TàzúÎýüË¿\IooW¸\Ó´0® 3Ï¡CËÙ¼¹#ô:PI¬Ah=û~ë·Xºs.YÊ=.,ËÂó<’ɤثÐ44`OÑó_¨NWW×ô"BSðöÿø0¯~õ)@ Xr_ íʬT¼‡æ³ð¼g ¤x§B<>u GO9€išxž'3Þ!N,XÀð³¯àøã†Eð<K%A¡%,Xð\~ÉqÒé´ Ð BLèzò(ËW¾¬«‹D"!“„¦c‡O9¥Õň5…ñâ( ‚Ðz~/ÍÙö=S©”x” mˬT¶ýê–ž´f¹îdiáA˜ žÓ†¸â¢» ‚„ü„8±ïÑe\pÁIeK¥#*­Gé'¶mKGSbÄþ]ó¸,’šÁu]=…åÐüù­.Bl‘h%‚c<ðç>Ïù§ü8¬3Å;EhgÚ^P9åð),yÛÖ}äD p“d‚ŽœôÞó: ˜ù.¦ Äg¼üÌK¼ò•Cá²L&#§ ÄÛ¶I$2P+1bÇŽ3ÃÏ®ë’Éd¤}+ÌðÂg´º±E×u‰ˆ qŃ_,|‘g7Ÿƒa2áVh{Ú^P9}ßé þû\|===2“Ob¡/°oÎQ #$qã¼âÔm\uÕ…@àE–ÍfeR‚ Ä×uEL„˜1oÞA”~âyžxu 3Іx¨L„ã82$1fߣ'pèÈ/€ ï)ýN¡i{Aå©%OñܾŜþ>òù|«‹$B‘ÞÜÁ»Ïýk²Ù¬4p!NìØËÏ1‡‹.:¼SÇiu©A(¢ëº*‚3.»ì #ð “Á[¡¼âÑG[]„Ø¢ëºØ¤ Ä ?g Ú’`ZêP¡Ýi{Aå¢_ýŠ ~û~ã7.Dz, „ñè/;yäé+ñW®\ÉÆe°VšL=ö¹{÷)œ}öKd³Y ™)M¢Ûaf¨Ç>ßö¶·IÎ1A˜¤þ„xR¯m>ñò|æ>ŒmÛ¸®ÛêË„isB« eýúõÜrË-tww300ÀÕW_Mww7+V¬wŸ%K–ðÞ÷¾Wf B“©Ç>W®\É9çœ#ƒµ‚Ðdê±Ï7½éw¹ûn]×I&“­¾A˜•Ôc›‚ Ì bŸ‚_Ä>!žÔc›çî9—]ÎÜ L„YAl}ôQ¶mÛÆñÇ/öY'›7oæ`ùòå­.JUâüþØ·o=ö;wîluQšN=öùË_þ’ÞÞ^.»ì2^÷º×µúÆçgK!ïúÙ¹s'[·nåì³ÏnuQšJ½mÛG}”ÞÞ^.½ôÒV_´ˆó38UânïµRËo"mÛñíó¹çžãÎ;ïdëÖ­\pÁ­¾„iq,=ÓíÂd¿‰jÛ6z@(ŽL§m»|ùò¶~Ú¡ \+³å=SËo"mÛ‰Ÿ×ç¶>Á9'þ ÷Þ{/oxÃb7>÷º¤Þ q¶÷­[·âºnÃÛn±T†‡‡Ç,«Åóø .䢋.jõ%TE)·BýÄù.Z´ˆ½{÷bF«‹ÒTê±ÏîînöîÝËòåË9çœsZ} ã–1ÎĽ|qæÅ_dÅŠ:t¨ÕEi:õØçu×]ÇË/¿Ìé§ŸÎé§ŸÞêKhKânŸq.ßsÏ=Ggg'«W¯nuQšJ½mÛÞÞÞX·mk%ÎÏà±z-µ\‡´mÇÇ0 Þ÷¾÷źm[+ÇÒ3Ý.Lv-ªm[íÙmHÛvv0›ìs2¤m;1ÿßÚßàðáa^ÿúóçÏoõeŒáXzV›EœïáòåË¹à‚ ¸æškzÜØ* .³lppU«VM¸ß'?ùÉV]8†‰óK£‘ÔcŸ]tQÛ B;P}®]»¶ÕÅ„Y´m…vDÚ¶ãÛçYgźuëZ]tA˜õHÛV≴m…v¤YmÛØäPYµjÕ÷¥ááaI:&1@ìSâ‹Ø§ ıMAˆ/bŸ‚_Ä>!žˆm B‰Ø*ÝÝÝ ‡ÉŒä]ïzW«‹&Ç!žˆm B|û„ø"ö)ñDlSJÄ&äÀºuë¸ñÆY½z5[¶laݺuttt´ºX‚ ö)qFìSâ‰Ø¦ ıOAˆ/bŸ‚OÄ6!`Îèèèh« eppÁÁAV¬X!nc‚3Ä>!¾ˆ} B<Û„ø"ö)ñEìSâ‰Ø¦ ÄPPAAAAAAˆ±É¡"‚ ‚ ‚ ‚ ‚ ‚WDPAAAAAA˜TAAAAAA&AAAAAAA„I8þóŸÿüç[]ˆveppY±bŸë.\8åõd``€“O>™¹sçÆª|###¸®ËÈÈgœqÆ”Ê0“÷Oh?¦cŸ­¶ÍZÊÐjûŒCù„öe"ûŒÓ³U}¶Ú6ãv…ÙC³ì¶UÏc3ì{¦¯¥Yõ´¼#Ú‹föIãdŸÓµ¿™¼–föqÅ>Û‹föI[ñ,4£ï§ºsºeûKîÉÈÈÏ>ûll뎸÷xòÉ'c?n;ãck£B]Ü|óÍ£]]]£×_ýèW\1úþ÷¿txx8\ûí·‡ë»ººFo¿ýö²ý'[ßHž~úéÑ®®®Ñûï¿?VåÛ²eKÙ=üÌg>Ssfòþ íÇtì³Õ¶YKZmŸq(ŸÐ¾LdŸqz¶ê±ÏVÛfÜî¡0{h–ݶêyl†}Ïôµ4«ž–wD{ÑÌ>iœìsºö7“×ÒÌ>®Øg{ÑÌ>i+ž…fô]ãTw¶ãowârOn¾ùæÑ›o¾yÊ囉òǽoü™Ï|fôŠ+®ˆý¸m+ÆÖDP©ƒ§Ÿ~zôüóÏݲeK¸ìŠ+®µ,+üý!·lÙ2zþùç>ýôÓ5¯o$êÁˆ>Xq(_ôž ^qÅ£wß}wMe˜Éû'´ÓµÏVÛf-ehµ}Æ¡|B{2™}ÆéÙªÇ>[m›q»‡Âì ™vÛªç±ö=Ó×Ò¬zZÞíC³û¤q²ÏéÚßL^K3û¸bŸíC³û¤­xšÑwSÝÙŽ¿IÜiõ=¹ýöÛG?ö±žþùU•Vÿ¦qï+R <ÕÊûnÅØšäP©ƒÁÁAº»»YµjU¸ìÊ+¯dxx€M›6±páBº»»Xµj«V­bÓ¦M5­o$ëׯgÕªU¬^½:\‡òmÚ´‰ááan¸á:::p‡+¯¼rÒ2ÌäýÚéØg«ms²òÕ²¾LdŸq(ŸÐ¾LdŸqz¶ê±ÏVÛf-÷HìS¨‡fÙm«žÇfØ÷L_K³êiyG´Íì“ÆÉ>§k3y-ÍìãŠ}¶Íì“¶âYhFß5Nug;þ&q'÷dõêÕ¬Y³¦Ìk-ßL”?î}ãÁÁAÖ¬YCGG@ŽLÆÖDP©ƒîînn½õÖðûÈÈ÷ÜsOøp Œ‰{·páBkZß(¸çž{H&“c–·º|ƒƒƒ¬^½š7²víZn¼ñƲ‡v¢2ÌÔýÚ“éØg«ms²òÕ²¾LdŸq(ŸÐ¾LdŸqy¶êµÏVÛf-÷HìS¨‡fÙm+žÇfÙ÷L_K³êiyG´Íì“ÆÉ>§k3y-ÍìãŠ}¶Íì“Îô³Ð¬¾kœêÎé–Uìs,q¸'«V­¢»»»j^Œ8ü¦qï_y啬[·Ž‘‘6mÚ J€ˆƒ}·rlM•irÏ=÷põÕWÓÝÝÍš5k€’Z%ú#M¶¾ŒŒŒpã7rË-·„jb­çŸ‰ò †ªå 7ÜÀŠ+X»vmøàNT†™(Ÿ0;˜ª}¶Ú6k)C«í3åf•ö‡gk:öÙjÛ¬¥ bŸÂti¤ÝÎôóØLûžékiV=-ïˆö¥Ñ}Ò8Ùçtío&¯¥™}\±Ïö¥Ñ}Ò™|šÙwSÝ9ݲŠ}Ž%î÷$n¿iûÆŠÁÁA6lØÀ=÷ÜŠ)“•!î}÷F”Q•:aíÚµ¬_¿ž›nº‰›nº)\WMýŒ*\“­o–e±jÕªÐUlxx˜bQ>Ô[n¹…îînÖ­[Çš5kظqã¤e˜©ò íK½öÙjÛ¬¥ ­¶Ï¸”Oh_ƳÏ8<[Ó±ÏVÛf\î¡0;i†ÝÎôóØLûn…m5£ž–wDûѬ>iœìsºö7Ó×Ò¬>®ØgûѬ>éL> Íì»Æ©îœnYÅ>Ç÷{—ß4Î}cŪU«¸õÖ[¹ãŽ;¸çž{b3nÛê±5Têäúë¯gÅŠ8ŽS¦ÐAð°UþÃÃáÒ5ÙúF122† ذaƒƒƒÜ}÷ÝÜ}÷ݱ(_ww÷1ú}¢2ÌÔýÚ—zí³Õ¶9YùjYß&²Ï8”OhoƳϸ<[õÚg«m3N÷P˜}4Ãn[ñ<6˾gúZšUOË;¢ýhVŸ4Nö9]û›ÉkifWì³ýhVŸt¦Ÿ…fõ]ãTwN·¬bŸc‰û=‰Ëoç¾ñÆÙ°aCø½£££ì¼q°ï–Ž­Õ”º^(ãöÛo½âŠ+Fï¿ÿþ²ÿO?ýt¸MWW×èý÷ß?::::ºeË–Ñ®®®Ñáááš×7šë¯¿><_Ê7<<<ÚÕÕ5ºeË–ðûW\1zûí·×T†™¾Bû0]ûlµmÖR†VÛg«Ë'´/“ÙgÜž­©Úg«m3Ž÷Phši·­|mß3y-ͬ§åÑ>4»O'ûœ®ýÍÔµ4»+öÙ>4»OÚªg¡Ñ}×8Õíú›Ä™¸Ü“믿~ôæ›ožrùš]þ¸÷UùÔ1ã>n;Óck"¨ÔÁÍ7ß§K#&=B½«v;Q½jFMÇÛšÍl°ÏVõKÅ>…fÓîöYm6¢î„fÐîö(LάõP±m›ÎÎNæÌ™C*•ó +õ{ñâÅd22™L¨º®Koo/sæÌ _⊞ž,ËbñâÅ,^¼˲Èd2,^¼˜ÎÎÎ2õt*ÛŽG&“ ÿº®3ZöZ‰–ÇqœI¿Oåx]Ÿz‘¤Ói4McÛ¶mecµër]7ümÔ1'r ‹þŽSÙO˜yZmŸ°Mhœ}V³½™²ÏÉìe¼kR¿™¦iá_Õˆ­vŸÔ~bŸñg"ûœÈ6Õújö9Óu'4Ï>k±×Z7ÛŒ«ugô»aÒ m3¦S¯ªõq°ÝJ»·Ñ¶Ûªzu¼kšJ½ªî‘Øn{ÐêvïT·ÙÐî¬_:Þ5M¥n­´MµLì3žH»·œF·{k½ÆzÇŒ¦SwJ¿4~H{v,íÖž=¦ÆqGg!Û¶mF³Ùìèèèèh:FÓéôèèèèèÐÐШ¦i£…Bathhh4™LŽ£}}}á:µo__ߨ¦i£Û¶m-;N6›sÓ4ÃrLeÛ‰PeSŸ“ÉäèÐÐÐhÿ¨¦iáºZŽcšfx“}¯åxµ\_>Ÿ5M3ü›H$Æ”¹Úuår¹²åê·Pûöõõ…çH&“£†a„ÛM´ŸÐZâ`Ÿ²Mu¬éÚg5Û›)ûœÌ^&º¦d29šH$Fóùüh"‘(;f5Û¬å|Bk™È>'²ÍÑÑÑ í³u§:V£í³{ìx°Íñ®©Þºsttt´¿¿T×õÑ¡¡¡ðz„ø3z5º>.¶-›úÞ ÛmU½:Ñ5W¯ªãŠí¶qh÷NuÛ‰h÷vïdýÒñ®i"»žÈ6GGÅ>㌴{«£‘íÞZ¯±Þ1£éÔÒ/Òžÿ8íÔž=–Æqg¥ ’N§G“ÉdÙ2]×Ëš¨¨‡°¯¯o4ŸÏ†Q¶o2™ ÷jPê~¯4ÄZ·ˆÊŠ1j$Si”a¼–ﵯ–ëS/BU)ªï•箼®\.7ªiÚ¸¿­:G2™Õ4­¬bœh?¡µÄÁ>e›êXÓµÏj¶7Sö9™½LtMét:üít]ŸÔ6k9ŸÐZ&²Ï‰lstttBûlEÝ©ŽÕhû¬Å^';^-×W‹­4²îÕu}´¿¿J÷Gh=Ó©WGGãg»Õ: Í°ÝVÕ«]Óxõjôb»íEÚ½SÝv"Ú½Ý;Y¿t¼kšÈ®'j÷Š}Æi÷V?F#Û½µ^c½cFõÖjôKヴgÇ?N;µg¥qÜYòËuÝÐåO¡ëzøÙ÷ý2wÛè¶žçáº.sæÌ ÿÇÍͨòÚ¦Bô>Ôò½QèºN¡PÀ4M²Ù,ÉdrÌ}­v]•nÑš¦áy^ø=êÒuõ›l?¡uˆ}V§šíÍ”}Nf/ծɲ,lÛ¦¿¿Ÿl6˶mÛp]—\.Œo›µœOhÙçD¶ Ç–}Öb¯ [iTÝ™Ëå0 ß÷ð ®ëJ2Å6`:õ*Û¶ÛªzµÚ5}ï{ß›°^±ÝvDÚ½Õie»w²~éx×4‘]×îûŒ7Òî­N«Ú½õŒÕ[w*¤_¤=;>íÔž­e¿Ù2Ž;+“Ò×›t¼EÓ4LÓ¤¯¯¯Õ—1k0MsL,¿Z_$•¿Se EÃ0ÈçóèºN*•¢¿¿¿¦ý„Ö!ö?ê±ÏóÐu½Ì–MÓ ÷­f›j[±Ïø2™}NÔ ™È>£¡v굕zëNß÷ÃßÊóH{6~Ìd_t:çk³ÒC%™Lâº.á‹9‘H„ë à ‘HÐÕÕ…®ëeª—®ë¤ÓizzzÂ}MÓ,Û¦ÑuL&C>Ÿoé}­MÓÈf³tuuašfxO“ÉdMמJ¥Ðu=œŸN§«n«ÎqÎ9çLi?afûŒõØ‹jÐDGÃ0H§Óc7Ê6Õï$ö_&²Ï‰lÄ>›Uþzl¥žº3‘HÈlÙ6e:õ*ÄÏv£vÛ®Ïd=¶û–·¼…Ý»wW­W«!¶ÛH»7^4£_:Q»Wl3ÞH»7>Ôk›Ó©;Õ=“~i<ölü˜É¾h;ŽãÎ)&’™•¸®ºÓFjß÷CW"ß÷1M“9sæ044Tæúçyš¦µüáWe©¼Žvcª÷Ôqr¹}}}8ŽÓôý„™Eì3L×^fÊ®…™¥š}Öb› öÙ(¤¦ÊtêUˆí¶³ÝÂÌ׫B{ íÞx!íW!Š´{ãC½÷³žýĮ㉴gãÁL÷EÛÑg¥‡Šb¼›ïû>===  à “É`šfÙC®ëzÓûDñöÙ.u§Ú¯ÄÆŽ-¦S¯BülwºÇhF¹¦ÊL׫B|‘voùq]®©"íW!Š´{ãSwÖ{?§û;ˆ]ÇiÏ–£åš*3Ým{œÕ‚ÊxèºN>Ÿã´éºN¡PhIYT⤉Ê:ǘ‰cÖS†zÉvP2…ñ‰‹}6ÊmKÍ8ÞLÚ‹ØgûÛ„c£î”:Phb»3S®è±Ä…Z‰‹}+íÞéܱëc‹¸Ø&ug+»n/Ä&g¦\ÑcÍd_´íqV‡üAAAAAAhǵº‚ ‚ ‚ ‚ ‚ ‚ qGAAAAAA„IAEAAAAAaDPAAAAAA˜TAAAAAA&AAAAAAA„I8¡Õ˜.úЇ¸à‚ Z]Œqyþùç9í´ÓZ]Œq9|ø0‡bÁ‚­.ʸÄýîܹ“ßú­ßâÒK/muQbÅwÞÉøC–/_ÞꢌKÜŸ­}ûö1wî\N:é¤V¥*íðþغu+_ýêW[]ŒØñÇüÇœyæ™­.Ƹ´Ã³%ïé—oÅŠ|èCjuQbGÜÛ¶µ÷gp*ÄÝÞk¥ÖßDÚ¶ÕÙ¼y3ÿþïÿë¶m­kÏt;Pëo"mÛêĽm[+íЮ•Ùòž©õ7‘¶íø\sÍ5tuuµºã÷º¤Þ q·÷'Ÿ|’k®¹†·¾õ­ ;fÛ *{öì¡»»»ÕÅ—õë×óÞ÷¾·ÕÅ—G}”ÞùÎw¶º(ã÷{hÛ6###­.Flû¬Û¶Yµj]tQ«‹R•vxÜÿý­.B,yê©§xÿûßßêbŒK;<[òþ˜>ú(ƒƒƒ­.F,‰{Û¶Vâþ N…¸Û{­Ôú›HÛ¶:êžÌû<Öžév ÖßDÚ¶Õ‰{Û¶VÚ¡ \+³å=Sëo"mÛñyüñÇùØÇ>ÖêbŒKÜë’vx/ÄÝÞ¿ÿýï³eËT¢,Z´(ÖÚîîîX—oáÂ…,X° ÖeŒû=Ü´ióçÏou1bÇé§ŸÎòåËcýÛÅýÙdõêÕ¬ZµªÕE©J;¼?-ZÔê"Ä’SO=5Ö¿[;<[òþ˜>{÷îmubIÜÛ¶µÒÏ`­ÄÝÞk¥ÖßDÚ¶Õ™?~ìÛ¶µr¬=Óí@­¿‰´m«÷¶m­´C¸VfË{f*¿‰´m«÷¶mÜë’vx/ÄÝÞ_ñŠW°dÉ’†³í•¸³nݺVaBV­ZÛ—†"î÷Ph_âþl­Y³¦ÕE˜vxíI;<[òþ„‰™MÏ`Üí½VfÓo"Ly¦ãÇlùM„éÑmàZ™-ÏôlúMZÅ9çœÓê"LHÜë’vxãnï\pAßCIJ/‚ ‚ ‚ ‚ ‚ ‚0 "¨‚ ‚ ‚ ‚ ‚ ‚ L‚„üAf ¿øW‹|w#ëMÀ)þbDöñŠû©eF«/JAAAA8&AEA˜Ÿ@¸ˆŠnd¹YB € X”Äè1ÕßDñ³dŠŸM@/þ¯]NñØCÅýrÅý(î—lõAAAAf"¨‚ Ì¢Þ•"DTQBCŽêB…Ú®ò¸QñCc¬7‰F ¢¨c+1¥@ pÔz Z•å‰q¶ úÂÒ¸–WÜF#g¢ø7[üìËdGŽïŒCyMº7"¨‚ Ä%ZèˆTå¥>{” zd½Vüž£Tùùb‡ÆäT[a޳}‚@ÐЩ]LQåœ ZñÞ¸ת˜ÿúÿ€·¾uŠGAAAAh1媂N0¢=@?eƒ.îN0–—>ë§€ýH¾3X–»Œ«ƒC¦ÿ)È ‚öjй¼sÀ>Þé|8ümà ¬çÀß öi íûçßÎàœ Úóà-¶‚{8óà+[áyÜÀÐç{2x?€GÏ„_®þ©àŸÞNðÀ?üðÿB°Gáœ]ðÔàïçžÙðŸEA„FåÑ(©åJåW¢‡ª/• aRRTîåã •D=R¢3 &c*¢ˆ*cžæç7Q!Áª'ܵ“K ‚ ‚ ‚ Âl¤Z Aä’'D'°r ½Ê¾e“U-puð÷€¹&Ø×þop߆ÉÍོûá/záO? æ äzÅ`=}_-Þ Úã; ý/‚¤æ‚Ñß}¼…àöÕ`>ì¯ý2Xf½–:N€Ü›@¼%àï„/ÁÃ瀾8/] ÉÛ`ÎÙ ?”•nÈíYH> Öåpæ[!÷CÐ=HÀ—_„…7ß÷(üþùÇð3V_îiÞ ÿýc¸ó xÓp÷Cr¾úE¸åÏÁ8 Œ] o…Ñ_Á~+¸Gš¼6^ÖwA"Øï+¯‡“àÿmìåŸÖÐçBA„& ¹¥>”òŒ”»JBPé*±¤šçH‚é3UéP«È3 ‚û6UÁGAAAA¡Â™«± •ç5Qü¯œErÅõ>à÷ð ¢t¨è!û0ôuÛfv€þ¸G ïÕgH— †œöÃÀa°/Žï,ȼ#Åõྖ¾zôAðÎÿ)€; ÿl8þ-ÐÛWnæa°æÝ ö§ÁßæSà Ã9w@îZð–Cú)øÖ·FÙyÚ(ï¼â8Üs!}Üñ)Øœ€ä!pçCr|eÞÃ<µõbú.V÷à÷4ÐN„þåÀr0è¹7²z1ô¼|>|ºè=c,÷68àAþDÐËÝ-p¦ÿ¾´9ÀåWËo7œl7gÜùx便ßïßž‚ü?^÷ß?aÁù•@DP™5*‚P §âsXy2VP° þûÇ9–MðÎÉ"ÔŠ 6â ‚ ‚ ‚ ³ƒ¨·ˆšü Áø‚M œx£ Ï)EÙÊÆ‹`ͶÕ^þ&s„<Ü ÖZàeè}ü£ÅpT‡añíÚ ÎªÀäà¸-pZ¸CßðÕ[à‡—CòRð‚;æ÷]þ‰A¡u`«¶äQxG÷ž$éódøí…/ñÒžaŒã–^ä&¹i~¸ .=-8Nú\øï_næ•‹!{Ò°s9Òé4ŽIô¿Ë‘OÙI¾ðàQnzê)|ÿA‰–_ð@+ÞÌ;îä´Ó.&Ï98ŽƒaX–ÆÃhž‡¦i ilݺ•§v:ç…¿‰®G¢©gŒ<ÌÉ›ÏÂ7Žö-2?òzì|jÃ[ÎFvmX¥Ãº¿:‡_ÛÙÐgG•qP¿IA¢cA„ å!³<ÊòM‚÷v½"¬šõ ÔŽ‰¼£AAAA›òñ›@$ÉŒóôú!ÐAgGð×; ú.Èíµ#ÿ>è_žoAß߃þ(h€þþ(`‚u¼ê÷áÙ  ? ‰§àÁaËpÞÉ»!ùv¸%ø°n%˜çT¸Ò…t´Ó¡æ.îúŠå×€w}’9þyä ¼]ƒ÷ïçŠs‡Xñšü‚}þx=,Áµm<à*-Á–°èky== ë<³u+o]ú~ð<|ßÇód2Òé4þ:žw2¹\MÓH$œ}özè·ñ<ÞÞ^úûûY¶ìwß}„ÞÞQ(ð}ŸÿþöÚ]XÖ?ãy‰D‚tÚÄuÁ¶Säóyþá¾ÇÑ£Wáû`Y†aàû–™E TšŽÊ_¦”Ÿ@ýÉp9‚ LR¥©O²òrP³ 3Ià5bÄÄ”÷€ ‚ ‚ ‚ÐŽ¸®‹aL> Ð÷}|ßG×gg€e¯8S>:ã}²{£fÛkšVu!ž8ã<¦ŒîzšÆm[·ò“ Ж/¢Œ¼øà-ŽãD}_…¡ŸŒòûÿ8‡ä~ð@ò·F»`dd„Ž‹;ØòG[è|ßc ¿âà­Û!_ó(½Éa©Ì«ƒ²ôábÀÉdГItt6nükN;íR4®‚1)Û…|¶|Rïþ]óø“§žçILÃÀu5vá;¿{ ·ï¿{U¯¸‘]»¾ÎЕ>¶m£ë:Éd‚„ ®ûöÞ½†Aoï^òùŸ10ðV®\Éå—_ί~õmyä>ü/¼ð'žx"/¿<—ü`˜7½éÉd’OúûüüçgòÎw®"™LbY?úÑ\Žý86¢Â4MLÓ¤··—d2‰ã½k]×Éård³Y,Ë*;Žš+ Ãû®êú5MÃ4MlÛÆó¼p]×I$á½³m›|>”×uCqD]¿*»ê§ªû–Éd0 #,³ºOªžçqÍ5×pÒI'µú‘™õ¨|´“Ëœ}äOŸx"Œó¨PáŸøæ79ùÀòŸúK–,㸃ÇaŒ òàî…Aî¤ì„=ôüÑ_]ÆG¾zbpò!xå+Ÿ$kºüçWÿ“,ùÿôÍbîÜϲùå͘é’äñÈã`~¨T®;îäɇV {‹°]˲8räÏ9ùä“Ù¼Ù mù©§–0oÞþ²kr]Xõñƒ¼òÎ y衇¸í¶Û8tèZ¾ûËØOÜζmÛX¾ü:àKüÏÿ<È©§þŒ_ûµ_Ã÷ƒ»õÈ#/L&ñ<«®º“íÛOãÛßNpÛýç}úÓ|ŽÃU'‹CgŸÍßö6Þ{è÷ö|SO]Áu×õó‰O|]7xŒÏ}.°×Å‹“JíåÝï>ŸC‡^F×u¶n=‹W¾²tz 7ܰl6Ë]wíæo„ÎÎ/¼p/žç±xñbN:é\n»íkE¯“4ë×åŸÿù¶m ¼[’É$Ù¬OgçVþø7óŸÿùi.¹äI~ñ‹ìÙs#Û¶AWW7Þx ÷Ýw&ø‡Cü×ÝÌÆGyþÁ¢Eïä û Nß÷RCŸET*°T5J‰Ž£!~«?Zi‚P;>=ª¿pÉÑ£,?tˆçÍC#°U@0øòO°k×.~üêWsäÔS¹ìăŠÈõöRH§±m›ÛFÓ4\×åë¿û»°lGŽ!÷Å/–5ª…B¡j9Õà¿eYacr̵L0óÇ÷ý°Ñ¨}ªlJhPÇ·m»ìœ@èJ©Æÿ÷ž÷pλß;}ûÈ?ø Þÿþ/º®ÓÓÓƒ®ëá;I}V vÕíìì ËmdF—Ù¶MOOCCC¡;§ºît:6~s¹¾ïcšfYc‚F»º/½½½áúè=Ìd2á_uŸ h Û¶ÍYgÕêGUAA¡L8°¬`*¯išá ¼0T ‚>P´_fYVYÿ+™Lbšfx¼èSTDð}?ü®PÖt]µM´šËå°, ÇqH&“eëTßÌqz{{‹³Ç“aÒ¶mz{{1 ƒžžžp"ŸmÛ¤Ói,Ë"™L†}V%òtuu…×éû~(”ôõõáy^؇Tû3ì{Éçó†mÛaˆ¢d2I.— ˲Ð4-ìçª{¬úª©TŠD" ,JPJ¥R˜¦Y¶¯º_úÒ—ø½ßû½V?b³žßùùÏùÜÉ'óá•+Ãñ Ê°é>0XS ˜,ôèQ8î8¾ó¦7±ÿ¤“xåîQž=y¯ûÉ–í_@òHìðÞÚà¿€>ø½/=Ëï<ýß}ä‚gýÙg¿Ç5_ý6ù|𻽻ÑÑ9õÔSË&‰:h¡—E>Ÿç‹_¼—¡¡kéééá´ÓNãƒü _þò0›6¢³óL.¹ä’¢ iâysùö·¿Í?øA®¸â æÏ…ÂBÎ=w]]]ìß¿ŸŽŽwrÇÿÌu×½™k¯½–8•={öòêWë|ä#¿M.—ã÷~ï­|ÿûåƒ|€ü¾úÕ¯²hчY²ä ã ©ýûù‹w½‹3ÿ÷D~²è>ûÞñn×…ï}ov|.¸ãº'¸ï³Ÿ]笷,çå—ç’Ëý žçqäÈ pÙ¸ñlÎ:ë.®ºêBî¹çB†‡Ïã/ÿòñð]öáogÓ¦Çùƒ?x-Ý݃|ö³I®¿þ1N?}÷Ýw+¹èz‚ŽèèÛ&Ïz\yåkÖ¼žÛo¿‚¯}m?Ž“`Íšã¸óÎ wŠaô“ÉÀ’%ð¦7ÝËóÏw¼Ê>J: ŸÜ*ÿ6§±Ïâ1/¨¨ÁVƒÎ"\Õ f´g"ÛLMP‰V‚•8ŽƒmÛ¡RžHTÏœ`ÛvX¹V›…]y®‰ÎYó=‰Ìo€+!*ñ‰PªSÇP³$Tåíº.…B¡ìÔ, ¬4+jf„j(¨F†iše÷M5`r¹¦i†§*¿š-¡5ªLÙl6œí î:×<@ww÷´î¹0uz)…âë#AŸÈfY92B"ò›ëv~Ñ‹/²Óu9nx˜Ãßú{á…a£«§8¨¯îûûûCdãÆœvÍ5°t)?ÿùÏyUñYSŠjÄ©Fžz.”ÝáÌš\.–K=‡ª¡ AƒW5†Õó¬fç¨ÙHéb"0Û¶éêê*›q”ÏçÇØ¬mÛá,€?|áö]/¸à ©@nšèýŒûŽª†j\**…$eßÑsVšj9w´ÓQ(ÊŽ“ÏçY»vm]Ï— ‚ ‚ B-¨‰m‰D" ÔW‰NDSc…B¡Ìƒ$ê)1Ñ„»ñÆ^T¯ã…°Rc4ŠÊ>›ê·Mtìè¾¹\.ô”‰¢Æn¢bêãE¯'Z–þþñãècTö3£û¨2Wö%U%žT»7jR"@*•"N‡ým%¦TòÞ÷¾—M›6MzŸ„éqäÈî]°€wRJ _9ZpûOÀÊ•|mÿ~N9åv¾ø"‡æÏç*k'ßK^@*ó†rϲÇ1Üe¤?À> ¼¾ãOøü©ŸgPäÉ}OòKÂÁà`é'8þøÓËžß\î¿ÿ_I$‚mžþbvïîÀqLÓ¤³³“½{{ƒOýæoòÌ¡CÅçWçë_?ÀºuÍå—_@_ß(¾Ÿâƒü!Ë–-cÑ¢E¼ð»xá…w“Lþ6÷ß?†a˭䬳nbîÜûH§Ótvf¸ì²ùÄ'þÓ žå-[º¹ûîGyþùôööây}}·ãy ióÐuåßø½_~û§‘L^®‹ÿ®ß†O/Ç}¢÷Ží_þÎÉïṟ克00ðm²ºÅ?{&þËÉçñöÓßÀ®ŸŽòöîSùù›¹óÎWóÎwÂæÍ›Y·n^ø$ïäøã/妛žáÀ.öïÿ²ÙKI¥`ùòC,^¼—ßøgY»ö ¾øÅ­<8­[ÌÈȹœrÊ üÑÍÅ÷MþéŸÞm?ÂÑ£ÿ͆ AR{Ó„lör, ®»îþõ_—’NÃãž—Níiè³xÌ ** ‘ ýÕs-¨ü ŒÐõö·W}¹«AÑhx›|>ÎW*º¨O&“¡Ë£RñpÖvtæÚ>Z¡ªÁV·è&A­¬Ô‹^Í ˆGQƒÂjö;PL.Ôº–ªŠ]‰ ¦i†3 Ôà©„6 #,µ,«LQ U.U᪲¦R©ð¸ê<¦i†×© ===a…ÖÕÕº„êºÎ¶mÛ™í‹/&™L†3”È¢î‰aá „ÊkŒÎ’w]—L&VصÄ]ü¯„ø‚ ²R"ÄHE£3“ɰwñb–<õßÿàð/Å %à©ÿJ”L§ÓxžÇ•ë׳ç¿€¥Ky饗ÆÌêQÏšu£žÁèçhYÔ³¥fסNjš“ËåÈçócl¾Úy'P‰Dy#òÞ{x衇`åʦýNÊeºÙDÝÂÅÛOAA„f£¼Ô$:5F¡ÆúúúÊú—ѱ™(ãõ_Ú5/ÇdÂKúkš¦éÓWí?G·h 038p€]óæÑC)ºP4Ù|¸oÞ<þáÐ!:å.ÿ‡GH\ĶŸÎ‹ß™KOâW ÷d\úUÒˆpÛm·ñ³oÀqÇÝÎÈ[F¸­ë6t½< B%ÁétÐõ<éô§ÃrãÁ:?ýéqtwwãy»w朎ŸÐÕÕÅçN>™¿ÂÐÞŽyè6~ïßÿŸ¾þõär9æÏÿ8<°œú§â/þâ/H$ŒŒ¬áðá›øÈG6òùÏžÎÎNŽ;îS\}õã|þ×]ìU«øÑ^ĸðEN=£“|þZúú²8Nà£ëjR:œ}ök¹ðÂoðÿp ©T_øÂ^òùEôõÇ€5 û‘m CöÉðÿ³÷ïñq”çÝ?þÆÆØ#{„‰mŒ‚3Âb“&Œ€T$PÈ(ÒœHVN›¶Á-ÞmúKJ’ºÙIÒ’–>ͳ›èyZš4Í.í×)IÛXÛ‡$¥€SMCBŠ AC8Xœ5àÇ6-Ûøþýqï53»ZI«ÃJ+ù~¿^z­vvæž{f÷ž¹çú\Úþázú¼«aÓcX¿\D0ÿJšNÙÅ>ý6îÛµ†?ÿ¼é¿ÿsðQò?ý(ɯœÅ¼Óx½w3ëÞmóÚÀR CÙÒ}Ÿö÷`ë çÒù_äï7?ë¶ó–3Oæw¼Dï)&ÿsëf~ë·òÜqÇ{hkÛûN³8½åß¹æÂVö5¿—ú§A6nüÏþðËüsÇhk;ËR‚Jܽ`ÁïÒÜü—Ì™3‡TJ *“‚G”C/‰€#GŸ$|Ÿ¿?ŸžW²\ĉ’#¼çy´µµa™LÃ0¬ˆAÐØØˆa$“IÇ # úúú›h6› Û¿Üd‰}}}a$G[[[(DHšYO<$$:FúoYÉd2ì—ïû¸®KKK –e‘H$ÂI@¹@<P___‰¾´ŸËåÂu$eÅsœH„¢ÅHëAz~ض]Ì©Wêao«ˆS===%홦ÞðGºñ‹X$ç´|?Û¶m«Ñ¯TSN{ñ5A©‚ã8¡0ÒÖ¦.’Ùl6+_)@å7+â_œòßÈg>óþòÐ!|ßçä“+_2ÓétU^;#EHô•ôk´ÉÚD&Øû÷ïçÐÂ…œsÎ9ãnc4âBÇTQtF£Ñh4F3³ñ‰œn Àÿ<ÈѧŸæçW_M²˜ *Nš©6¢A£ÑŒƒo~3÷m!2F%“Pàûx¦ÉgŸí½—žÌÜG¡}{ ÍþoÎüèe\œ[È{;çB¼.ð~×yÏ#|Ùù2?ýi sæìeãÆ$étš¯ñ5n¸á0÷ßÿ lO* Òÿ¿ýÿWˆEeÝwß}ü¯ß¿ /¾Hÿž!õÁ],Y²„\Ž•--œ½íd~:÷j^¹º‹ççÍã=Û¶ñõÿú«*ñ®ÿ±ÇX¸c÷¬\IOÏ÷ß?¸.ÿvÁ¯ó‰Kú ¥…DO¶mÜû¶õí–ÐÓCþ–𳟑}ê°s'™o-àíoŸG>?|¶nýóç–Ðð쳜uÖòy%Â47C"ù<$“ɨô[^߸â p!—ïÞ…ø½çãýùì8Lú‡Wãs#IÚÛá߸†ÇŸüÎÙÓŒÝÒÇï~·úÆL“΋ÚIIRøÌvþªó³ì<õT윅sõÏY¾s'ßZúßðùK¸í¶%´­Þêݽ|é‰Û!¸Ú°m«PÀxu9² `$yøá‡Ùú·óï·Ýƪÿú/蹉 ø=îùýߟôzÈÓ"¨ô÷÷Óßß0$U’|ÖÔÔDSSSÍú%ªÒ…Jû04:E'@[[;;;iºòÊoèB¡½Š+ÙíííCÔoñHÛ/~.‚L¡Pbø‡ÈØ*mU2Æ£BÊSf‰¨"*ã8atG¥ˆ)*ω9åÇN§I¥Rá{ñº¯v1Zê!9>9'£lEÄ/qOûÙn°ilÆ?¯õø¬DÖ÷ L3LÏ'¢_"‘( ‘–z 2†ûΪù|tõjþìá‡ñ}Ÿ†U«¦äXké´xñbžééa×êÕÔNN‰)š‰SÏãS£9Ñ©‡¹­F£оwj4õK=OÉZb_}á~|æ™ÜpÚiüÇöí<ùµ¯a ¼zß}|ãg?ãÞ/~±¢ÍF£™MÔÃÜÖEÙhÅ¢ãû>ø> .¿œ5 †BŠÜöðä-‹³^<+`>àÚÁ7W±¤ëdðßÿ5ȻԆAÇ¿‰––%|š?~>ïÿ;I&£‚[¶<Ñ#¯ÓÜÜÌï½ï}|úã'›…'îêfÞÖM\iÛ<øû¿Ï»Owh»ù«Üø¿ßÅ“§žÊOzŽÓ µõwø³§žâcŸü$oÿùnþÆ1þvùrÒé4û{Œ¿0øÎ<ÓøË¿ðŽ÷õñ¶|Œ/}Ÿâ*Èf¼þ4ßÛHpßã¸ënSÇí{ù?ãvÐyÓužöìÁn~¯ï'¸¾CÀƒby€ž §Ò~× :´==Û1æžÎ¾ØÁÏÎÿÿ¸ýv”’ɨš$Ž£Þƒzõ}H¥”À":²uUÖU 䯛Õe¢ÖøÄ'VÃ'~¦˜W—~¹˜YI³öý°¶¸8ý£÷¨íw*u0Þ¶ ÓNÝ.S+§!‘ ÃqèìL’oƒóÎÛǹ‹±êsŸ ×1 ƒ‹/æØé§OêïsÊ•ŽŽ6oÞÌÚµkéïï§¡¡o}ë[444°yóf:::X»v-[·neãÆ¬[·®&ýðPžIÔßw•­'uS?p€Ø6¶eñ¹üÇ’TQñ4[q$*e4’ÉdIú©JÛX–5DŒ©D¥mãeIVPã iŒï¯­­mLµƺ‰©¥Ç‡ÔN)?¶ÙÆHc˜Òñ'nܽ›;çÍã©ØòT* ›ñï_­«LFÃ@…•ÞuøpÍ()bV –,YÀž={j¡SR°:Ó©×ñ©Ñhêgn«ÑhJÑ÷N¦~©§ñ™EÕÒM mWÞy'+¾÷=‚Õ«YéûÜßÙ‰‘ÉVŸ¨àªÑÌ&êen+ÎíÉ¢ÝÇ÷}¸ö_þ…U7ÞXqðø¼ýÇ?fîÀqÚï:Ì;¾»ÿ\Xò‘%ð9 m)èêBåŽ/Û=th GŽCÊ:ÄM«+–,aû¯Ž‘H$ø’aÀÿþßF'GzÅ÷{Œ·îÝË~²Ÿg,ãÈ‘§øÙßÈøßêà¾Ã6ç&‡ÿ•ÿ}n)(+ôÚµ;ùæ7ÿ‹t:ÍѦ&.[÷Sœ‡¿K⟓üô§Á÷i»nW¼§uý ®ñ3Üm«±mH.Âû¯‹ønñ-Y‚,!u»Iço‚õ± 0Ï]A×_>G*?—öv0öÎÁ\º óaôÍ)þôO÷욃½z¹ÆßaÛó—ÒÙI±(¼ú+7q‹Y·½] Qqs[&‰/ þ/1ÑcGM$Jϳœwµm´m—•·­Œa¨~-Zt÷­oåzÏ‹: *¦›L¦TPéïïç¶ÛnãŽ;î`Íš5Å£Š>oØ°ŽŽn½õVZ[[éííåú믧µµuÒO‰D1P‚ D©¾Ê¿æÍ›7óò¯ý//X  QŸY´ˆ/ÿð‡ÌÉåh/Öñ¨ÄXŒï¦i’J¥*F‹L&–e…uHj‰Wƒê#ÆŠiš%éÏj‰ä=­•84ÝŒ66)Ÿq|ßç÷V¬`™çqôšk0Çó5MýÌm5M)úÞ©ÑÔ/õ0>T­ñpïÏã®[ná¾o}‹ü«¯A‰S«ŽGÑœÔãܶ­­¿¹ï>ÒË–qòÑ£¬zî9lTT™ ÌÛ¿Ÿž%KxꢋHÞ“‚“€nz 6¾à§QŠ)„ùã¢/k¹oˆësÏ‘j¼KZ¿€Ë-˜é47.½ƒëþ_Ž×ÿíßxîõ×ùæéoäÔ³Ïæå—Åܯ~•ûû>u€%'ïãºÕ«Yyê©Åôî{÷¾Àí·ßfzòIã,H}Ì®$vŒ=Êú¸Ç7Q((‘#™Tƒú^(žW¯"vär‹Á²0MÅb~ôR¬ô¥àû$Løç>Œwx ™»VòÇüß\Ñ´ Ï[U¢WT2³ˆRþYù{È¢TFÂ4£h—‘mq€ïëÇ)Ö„©" a¢Ì©ùbô÷÷ÓÚÚJ€k®¹†½{÷ÒÝÝÍâÅ‹ÃP²5kÖ°fͺ»»'½*ò¤§ø Ü––Р ʈþÝï~—þð‡´46†FÎD°ÿ{ßcþãóÞ›ož”>IÍ©0ØKqöZ"ÆÔ©0vJm“Z‹…g«ñv¤± LéøŒóûO?Í÷ßÏ#ôGáoª½½\.G&“Á²¬!¿gÓ4']P9ùä“Ù±cgÌ©Ý%³<’¬–ìß¿€ß\° fûï`ªBágsôX½ŽOFS?s[FSоwj4õËtOhA9Óö™  ÍÒÞÞÎß|êSaÊðZ9†j4õL½Ím¥žÑoÿÙŸñÔEqÑ‘#€Bßwÿý¼i`€£>ÈS]Äûž;„ýST™ŽUðö½A}‡1ð\rɹ%cÝ4‹ëº®*"’J1wÑ"öþ8o<ýt>ñYßç«ÿp=Ÿ}éƒì<õTÇá}ß¹…óßúßýîîÐFyð`/­ïžÃâW_…bgÛ†£Gñãï ÷éy‘(!bNç÷æ‘É(¡${[#A º”Ë©uR)% 8ŽÊ|U,‘]ÒV:]Ü>;8àŠ+v±gÏ¿sÙe_äg?{#_þò*ŠuéGEœ!´·«éë«ÙO¢BŸJíÁSe·RA¥µµ•M›6…ïÙ²e MMMôööQ4/^æìŽmÛ¶±~ýú1õë°LŠÈKT…ëº8ŽÃ{ßû^ÞqÓMaè)ÀÍË—sëý÷óÓNã–•+'åܘ¦9%7ìt:MOOÏ”üÀ\×­¹‘³Æór¤ýJžöëׯçî»ï®éþ§‚‘Æ&0îñy÷ÝwÓÑÑ1®>¹ÀC«Vqóöí¤ÓilÛ£Qä÷›L&éêêªùo`áÂ…<üðÃ5è˜*–/_ÎŽ;سgÏ”ìoºr ÷öö²~ýzvíÚ5-ûŸLj1>wíÚÅúõëÙ¼yótžæDRìÞ½{º»2aêen«ÑLzn[»¹­F3dn»mÛ¶éîÊ„™Î¹­´@õŒßÒÒF£èÚšñ ç¶ÕÍm{{{ÇÔM6ïÑGi)Öi^¾|yh›;xS/{ÙCÓ)ªO|Û•å) þ ÅF’@¢²ðŸÿyˆÆÆ=êM(%Åó0¼Èÿá •Â7MνæQŽ46ràÅ9ò™Ï„Û/øÀ°m›D"ÁÝwßͲe§°zõ\’ÅŠ}è×8ûìÓðW‡*‡ïÃÒ¥Kyüñ_'Ÿ/F#5zz¢,URÃĶU°EÜ„kJë)¢,Xé4tvª×8¦94âæâ‹/fîÜò¥/ý1þðÕ˜¦Úo5—¿ÎÎaÖ‹w†êÄ™©¢£££&sÛ)TâlÙ²% [·n]è§š±sÎ9§d°WC@”⠔´½ ŒPÉçó¸®ËŸ¾ímaÞ>Á0 >yÝuØ(±3?]'q†1%žÜ9Pë}uvvÖ6qÏë®»Ž7޹>°áõ×1‡Oüã$“ILÓ$›Í†7'`Hý”ZÑÐÐÀ7ÞÈ‚Ft€ú ÷[›,,XÀÁ+j~,¦i†¡—µ&Y(¬Y³†M›6±lÙ²)éÃT1YãsÙ²elÚ´IçŠ×L ëÖ­cãÆ,]ºtº»2©LçÜV£™,ôÜvdÆ;·Õh&ŠÌmk]qª™Ê¹mHL±P59óù<Éd’L&3«#Þ5µEÏmGFæ¶ñ¨—jé=x£‹ñ†·¿ %¨ˆ#¼øÌŸ3Ÿt§»öè\~™˜AßÌÊþ_þüçç<È£‡Ï`çw¾ÃÉçǾeËøìOßKãÑ?gÇÛߎíûXÖ ¿@:ýs,Ëâo<À³Ï¾•TJ¢G,‚n¿Ö®ývy"ÂIsîs¤—DbG&£>“(1™X–Z¦èŠQnV1M¥2Z5©£Ƕ‡F²L˜i¾ŽJɉ ¦Ìf8å*7ÜpMMM¸®[rÓ\³fÍ0±½{÷Nja#å‘àQ*¬¸®²–È”tì×u%œTÂ@Ý”§Æ{æH$f•‘L&knžn†›05ãSøú®] tvò·¿ù›%çܲ¬’¢€SIm˪—í«ÆEÜvîÜ9%éË2™Lɵ´ˆø4Û=Êêe|j4š¡LçÜV£Ñ ¾wj4õËTŽO)@߉²  …]]]:2E£©@½Ìm_xá^xáÞú󟪖¼åÀêm«yöçÏrýk×ów^‰•€žÊ@[¤B‹(ò# ¹™§&uê-àyìüÎwÈ{ïJx<7ï Üpà aÖ?üÃxê©§È•Ž+®¸‚sÎi ¢ý¸n©x‘Ï+áÂzê_°/ P€ÆFµk‰1M%®HýPIµ&¡aë™”Q®uTYf2"¤L5S¡²yóf¹æškJŠ555ÑÚÚ9jmm¥··—þþ~®½öÚ ï·€º‰Êm2þss3†a`¶mÉdrLEÛõíW3ÓilÖz|–sëÁƒÜ¸x1ïî쬛ɭÍÔ‰*c¹öŒ¸à‚ ¸ì²Ëj~,µSNêi|j4šR¦kn«ÑhFFß;5šúeªÇ§C˜õPµ™L&,>¯Ñh"êinûܪUð‘ðñ¯}mÇçÎyö¾¸ü‹°°Áùd¾[ºm¹}ݲŠQ+©”R"l›Ïßt.ø¹¯ó9ëTÎþÀ¸ôŸ`ݺFÞý›·sÑÀyUàaëÖ ¹à‚Ar¹\I›ž§Rt 3zÙ¶V õY*ï>Hò½ÛñŽ4ây¥é¼r¹¡ÂF:­Ö©&È"žòk$Ê×™Þic*”…)TúûûéïïRhsÆ lܸ‘7rÓM7±víZ¶nÝÊÆKŠÁUçDn¢YÀq@)Y味%M•FS-£M fã3ÎÍ÷ÝÇö¹sùü%—Ô˜"LÅe9—ËÕü¸- øÀ¦àh¦ß÷§¤–ÎtQ/ãS£Ñ eºæ¶fdô½S£©_¦r|¦Š¯¢ô†a 1Œj4ÅtÍmÝâŸXg} ñá‡9îû\wàK¨°|þr–_zË{Ï–¶åyQú,ÃÚÚð®ÿž·W}Nóñ ó oÆu]¼K/ÅÍfY¹ò;<óÌŸ`'aÛ6ù|ž €çž{Ïëb¯ a"ä{zÔ{Û.F©¬z®XE¾ß*fX–*ô^¾¬šÈ“ñúâJtÌl#‚)M?¥‚Š ¾áX·n­­­ô÷÷‡Þ “…D¥(aEòe¦Óé’Ñ××7ësñk4åŒ66¡¶ãSø—#GøÊEaÖi!ñZK­õ&"Í,Ë"™LÎjï²zŸf(Ó9·Õh4ãïMý2UãÓG9×öß lÛÖÏ\ÍÔÃÜ6@‰¡ÇŽã=¶at=\üÀ†»çõC¯+oøý²í‹©¸<¯éaY¸·ÿ XÍ sæð_¶MÒ¶¹òʼð‚ÚÆ²,‰ç·«®j Ÿ‡tÚÆ²lÚÛá7~ãÜÿ›I$”Ø!éº|ÚÛ£ô[¶Õ; Sye³`Ûø¾Šh9~|äã·¬Ú§äšmšr¡P •JM©]hÊ‹ÒF-¤‡2„Z¨ñæ¢`ˆW³¾¹j4ÃS‹ñé8NXÃhû…òÉ:S4õ‰ÕÐÆ ¦>ÑcS£©_ôøÔhê—‰ŽÏªæ‚àºî”dÐhf;µ¸wúDYA<”ݶè”ð °Á¿N;õËÞ}Šòš7yJØ¡-‚÷ÝîÝ*V6OæZxvð‚ð°uë°dÉGð<Û¶ñ<ÓOŒaã=ïYJ*_ú’JÉ%)Ž£öåºC ½[ã*XbšCS–i†'‘H„u±¦òú>åE駃ȡDø³þ~,Ë"—Ëéô^Í4“Ïç¹ÇÎ>õT.ܾ}º»£Ñh4F£Ñh4šN\Pq‹… ´˜¢ÑÔ'>Êv °cÇN>¹, Îx¼ã™RÔ)ÊSi™{¸ì¤ÿ†‡Va"†é4Î=Wò•=Ía ˆ¥K/å꫟Ã0 LÓĶm¾ô¥€Š2q]\’H¨f õ¾¸y¸^.š“É…« ºQM¦rË*ÙL3 RÊcª¯ïu¡R+ä´zžÇŸ¤Rض=©ÅŸgqM¦fxžGü°¡µwÝÅ_ë¼ÕF£Ñh4F£™*;‰Øòù¼Žj×hf;vì€+Xvà@´Ð« ÓAit €Wðù·¾wñû<±mõÑÜü{,Y¢ê¦üò—bY>_úÒ{1M߇;£ú+%bšQÔK¡Pº/ÓŒ>SŒ±,J¢Sª­¢™Ìú•u#|ßǶíI¿™jAE£;®ëbÛ6ÿÝØÈ‘¯½®#ÆjœÂR£Ñh4F£Ñh4“@H¢ŠKýÜz~ÖÔh4 øsæÐ°{77¾IuÛŠ&ÀXPüߊfÝ0E–„Ž<û,Öâ‡0ÿîÓÅ0¸÷Þm<ðÀ_ñoÿ¶Ã0p]—… òò˧sèÐB•Þ«<$,ŸH@ðß½+xpï—p]U°Ü²,¾ûݧY´è,¾ò•“˜;×,ÖM¹sO墋ބµR‚öÅæâf*Iï¥ÑÀ ¡Ò—Ë…E‡$å—F£™~zúúØÝо_÷^Cåé5F£Ñh4FS_¸¨ ¾ïcYVM2”h4šÚW¬`õêÕ*Peˆ‰ÕY ÐÇ ì߯T•d’¹ò'ÌŸ¿;Ÿ$•Jðì³?§¹¹‘ 01 Èår$ðÚkç°zõR@‰)®;Ýg@3S˜Õ*jÌYÏ?¨pO}#Õhêß÷iZ¿žë€ ™Äª˜p²¾¨ÿV‡NU¨Ñh4F£Ñhf>JPq]Wg'Ñhf(¶dQbJ¥´)ŠQ*ÙlqIþñჟËâÛ_þ9K—¾ÌÅ_Ìòå*Be``- ìÝ;‡ P› ÐÕUÜŸ6ŽhÆÈ¬T p<Ã0ð<éî–F£A *§]q¨óÊ\‰âŸF£Ñh4F£Ñh꟢c{ Ò½k§4¦6HŠõ·ÿä'Ê£Ü÷}‚ ˜ð͉‚ëºìX³fF³+:E£Ñh4F£Ñhf#>Å A5H÷L¼ F3 `çÎêT¨·P:­—øâÇwòSóÉ¿õáâ={þææ‡BQµ±±ÛV›ø¾ú“èf<ÌêIîeš&AÔ<Ý—ŒuMíð)I^[³¨ÉÔ¹I±å‚ð ±ÏËåmÈ5;E$Œhðø,;å”éîÆ þýj4F£Ñh4šÙD@äX«Ñhf&ð‹}û8`Aa˜ÉÒ"ô©”zj¥™ ©¶SI§ß®ó–·|'žØA_ß6^{í­äó°|ù…¡’Lªt_Ù¬ŽHÑŒŸY/¨HÞL×ukZŒÞàÄôVðˆ&,.Q¬^qy\ì ø|z#m˜@¾¸Ì rp+¶M¡ø^ö[) ×(Û&Uü¿³¬ýø÷'íùÅþH=»¬­,ðÚWpÆ‚´N÷—1Ãð€¦»F£Ñh4F£™%ˆA×OÑhfGÅèïçåo|VÝ.xo£ÌÐì< ‡ŽCp Ë‚k¯íÇqþžL&Ãm·ý7çŸ>>zwÝõ:+WB&C¡â8ÐÙ©^5šñ2&A¥»»›þþ~Ö­[@oo/¬Y³†7N÷ñ Áu],˪¹wÂL½U»Å¾(áÀGEpH$H\(ñ$½!Ûf‰D”B±Ý ÐR|­$eÉú‚D™ôPYH©DKq_Õnc „”á>¤¿&‘`#ËãÇâs—-ãüíÛ'ë+9!‚€…ïx‡Žèš&NDñW£Ñh4F£ÑÌ~¤ ýdg(±Q¶F3ùìÛ· Ÿç’3Î(YQ$‰Cß&xªR_ËÂJ¦I$à{ß;“Ë/W¦~ð-\uU{÷>ÃÎWò䓪nÊñãªL<¯Úži4•©ZP¹ùæ›Ù¼y36l ¿¿Ÿn¸µkײfͶlÙB?·Þzët ntàyÉd’B¡pBy(H´H%T@$`ˆxâQ*˜$P“,Q$F¼èZ’ê„#—h¢a¦:•j׋Ó3çÒ"Šš)ï£ übÉЂʘð<£oy‹T¦ ü®Ñh4F£Ñhfbã¡¢ÑÌ$ñÊUŽCC×+ì¿{[Ü`ëâÛi|vízÛoO?¼‹ÓOÿ >¸ËŠ ÏDZ,•úK£/U *½½½ÜsÏ=ÜqǬY³€-[¶°xñbn½õVX·n¶mÓßßOSSÓt ŒÝßÇ4M,Ëš7ÔxäH%†˜Dõ𤮇[|m'*¨-&Añ³Ü0ûˆ‹-^Ûª5SƒId€6*|ö’ÍÒŒ‰Ë–ÍØÈ.F£Ñh4F£ÑÔb‘ÔïffpìØ1ü¢ýeŒ¬°âÊ•$—eÀ¾|Ÿ PuQš›—óÉOþ„ýèt^~y_¼˜üົÁ4!¨¦#1Qƒ§æ„¦*Aåž{µ5S@¥ÿºæškh(Ö@hjj¢©©©®ˆ¼ÒétÍ‹ÒORDŒø>êz"†ýÑõÅD‰'I”H"Ûu1Ôø¯¯ãg¤4agìÝ;ÝÝ›q¼xàK ±qº»rÂ13®‚F£Ñh4F36â6S-¨h43‡C ²Ó÷I$Ê#\ œex¤ì¯Ñe¹\˜çÛß^H"q&ž÷Ÿ<÷ÜìÛ·ƒÞÞïÉd¦ûÐ4³”9Õ®X.’tww³víÚ’e uT`Ú^xá…PD©71%@û,QÍP©¥ZŠý—ú$i ¯øÚƒªIÒE$¢Äk”$ŠëÕ×ÑÎ|$ʧœ4pÙ£Nw÷fß}í5ÎÙ½{º»qB¢Ó¬i4'¨²‘[–hÛ÷£eÍÍê5ŸW  #j4F£ÑLÉÚáyžT4šÄΕ+1%‡I,G¹e¡TσTªbú®ùó·Óܼ‡ïÿ ìÙÓÀŠ+´˜¢©)U *‹/¦»»;|¿eËZ[[Ãeƒƒƒôöö²xñâé>&@¿óöí›Ò›èHö•<Ðû“bêê¦/uN¯Ö-ÔúåÛú¾úß¡À‘¯‹i4F£ÑŒŠØO´ ¢ÑÌ.||;I’\û“k•§ø æû@[›zÊçI¶ï!®“üìgß`` “K.™SWŽþšÙMU)¿®¹æòù<7ß|3­­­äóyZ[[Ãêàà 455•¤‰ÁÁAöîÝ[ùÒßßOÉzk×®ÿ€¨Ö…t’4\bŸ‘È©Y"âH%Q¤h‡ ë£h4ÓE¥± “;>w®\Éê‡_%^5°²Dj£û¿€ª˜PöUi^݆œÉâçÑ@tGØN£™b¦b|Îv|_åÑG'ÛºN@6 ™ŒE 5YwèìŒ×UmÉ6µ E*T[‰D´OË"Ì÷+û1Mµù\Úlo‡®.õÚÓ /‰„z®ve{Y¦™z¦dn«ÑhÆŒ¾wj4õK­ÆçâÖfÌLÕÜ6¼vè5–/_NÓ¢¦ÐcYÅç*Ó„´ªöl>û3ç=tu©m ÞüæÜwß§X¾\­fš•Ÿñ4šÉ¤*A¥©©‰o}ë[ÜtÓMlÞ¼™ÖÖV6nܨÔ_ëׯ§©©‰[o½µêç‹ù-¤€ŽŽŽ0úEØ´iSI$LµÀÞgžáÃÖÔ$¸±PöÛf¢ô[Ã~/Ç/kK£™.*M˜Üñ9'–ޝj”’޽ŠRNî ˜J©t»¾í¯¹úú”`bšê/½âûѨ‰ºˆAíÃu£~Z–ÍFB‡…$“‘xR(¨?ÃPûpõy¨6eßùjŸ©”Ú>•Rë'“‘ÔܬÞ[–Ú&“)kF;oÉäèëiJ©õÜV£ÑŒÙzïÔhf“=>Å®bM‘H£™ÍLÕÜ6\td>ïzÓ»8Û=[Ùx õL’H ’ 2 mjõŒ•gÏžN:©yóöcÛ‹õ<ÔÓ3ÝgO3Û©JPX³f n…Ük×®ÓàÙ¼y3ÝÝÝlÙ²… 6”|6888i“X°Ÿ{cŠdI©wÒÉøìž³ív¯3“ÌmJE C#iÊ‘ Ø‡ZBrK°)~¢bN…Ø9•¾H$P9y* d…âú•ÎÕ ÂTÏ©@R]ÅoÏ’+¾<$ªd$âBC\¨6\W‰"P¸®ú,¢uDЈG ø¾P²Ù(¢DŽÃ÷Õk> *–Î÷Ãú("t$“ªÒ—T*j;Ôÿމ²ï|>F\7Z–H¨WÈú'â>RŸ%“Që¤ÓÑ1Ú¶Š —ÈËŠŽQ *Õ3Us[F36fÓ½S£™mÔj|€áyuWCW£™ILÇÜv÷üÝœ½«˜ñ(²'P|N‹=$>÷Üs,\xwÞyïx‡OXìÚµ‹óÏ™LäÔ¦ÑÔš 1hhhÓ@Z»v-ëÖ­«˜¬»»{H¨çDð§0á¸D£Ì6ad¼è’3‘Æ&Lîø\¸cÇÈ+x¨4\ÊŸ+þMƼ¸³Ø–ˆ‚Y\ž(þù”Šò'Ûˆr{æ‹}6cývŠ #~ñs%ê8Åm›‹ïýØ2’ºŠ}pPb„Dè´Õ‘"Mù²¶e=‰ÐÉ—çxŽBéo{ñ3'ÖŽëW¾¸~ª¸¾믬Ÿ%Š bý÷cÇ*E¥‚â2/v,RhJÎI¡¸/§ø™ëû ÀTŽÏZ7òK‘ø3¯,‹ ©Tô™ å>"6€JQú­xá÷t:C|_-—6Eìñ¼H¬ËRË$%¾LÒl"DÔ°,õ—N«å™Œ1$Å—Dà$*jFÂÓ‰HJ$¢×Uï¥ïòW—Ú6ŸW)ÉD8 µŽ¤ “è©á"ÂK>¯ŽG„-9ñs+ß‹ãèz.åLåÜV£ÑTÏlºwj4³ZŽÏ týfLÇÜöô£§+{Ø}ÌÈA.bñÅô÷ÏãñÇO)öç¾ùÍ‹Y¾|> žmtúcÍTPµ ÒßßÏÍ7ßÌúõë¹é¦›èíí×׬YCkkëâõƒƒƒÜ|óÍœþù\rÉ%lÞ¼yÔö¶mÛÆúõëÃ÷>Êh¡n¤¶Nœ7åœH¾ ëׯçî»ïžînL ÃMÿø¼ûî»éèè(Y滞zjä Dá^ñô]µ&žÚ+ôÿOE“$PÂI'*šBć Q¨š]|/í%ŠËD Ê?ë*¶ÑWü?ºˆåŠïE¼±b}’KZ’(êÃ%šx8Åý%QÂDš¨¸“.ûŠmø(‘£¹¸²ä8âÑ@Nq[+Ö§¾âwÕë[¢xnÅýItL’(•šDî$Šíߤ‹}’è¡öb}Åe"FåˆD‰’º:E!¬··—õë×sàÅSôã©-“=>wíÚÅúõë«ÇãARaÅ@ÒaA$rÈ{IqÑ«D@ÉQ¬I8dŸ¶]Z#¢e†¡Úô¼(j\–É:"`€8<¯4õV2©–'jQÊ/‰v‘iG"¡þ:;ÕûL…(1Y&©¹,KµJ¸H§Õ²žõÚ×§¶ÉdÔz"¾Hûú¢>ȾÓéâƒHq?’‚LPr9µ,—‹„-ed;ù¿PPÿ{žzFÄ–jÙ¼y3ìÞ½»&¿¿©¦Ös[f*ÑsÛ‘©4·Õh¦™ÛnÛ¶mº»2)ÔjnûØþýº~ŠfÊÑsÛ‘‘¹íHväù¯ÏWö‡Xaiq‚î¿ÿ}¼ë]ÇY¸ð<òQ|¿“¿ù›ûš*M95™ÛVòK쮹溻»¹á†¸ãŽ;&M™ìïï§µµ• 6°iÓ&º»»¹é¦›hjj1æœsÎaÓ¦Má{©WœèB9ný'R”ΦM›Nˆ‡ªñŽÏë®»nH>܇q᫯VÞ €2´×[¾Ëuq)ÿq›(á#NÑxFº™ ë”3\Z®ò.ñvã…š$­˜…-Ò±Ïìâ1ˆz%NÄûßI1_bñ}|ûá&("ñJk×sŸ†}±vE ’2eû4cí•÷¡ õ{!v\ kºÖ°é”Mܽkv…Fb<ãsÙ²e%÷ÎÉF¢3LSÛ»º¢ôVñ[³ÁC¢C|?\7šL‹hlZZ”à ‘EbÄE”ÎΨˆ¼D—H½‰‘´W™L"Žåõ\¤†¡–[ÖÈâÉX©6ï¯*ñ~Š—$éØXîêRý§ ë닾+ÇQÇá8Qä¤ +¯ý’ÏGQ>ɤzM§Õç"Ö´·G9ºuëhjj¢»»»6?À:a²æ¶ÍT¢ç¶cŸÛj4SÁš5kØ´iÓ !¸OdnÛ‚v¬ÕL=zn;þ¹­˜þÞŸ‚y»ZX|^,7éŠVÚß¿Ÿ9sb&¯¾:ŸnøÀtŸMS«y[U‚Jww7ýýý<ôÐC444`Û6›7ož´ŽÉAhmmåÚk¯¥»»{7n&€IDAT̹ùÄŽ™Ÿaaž.³+ºc6ˆCÅdŽÏç^y…Õ«W—.tP†uáņé¦Àð¢B=1’¢,zÁO}š‘.Z#Õ`°bÛ§GYg¤}ÇkàtÅþwÔþ G \Çuc<¨™ÅdŽÏÉB"DD$$JEŒò2IŽ %’‚Jj|Äø‰DTŸDRS‰ñ^ ûòü,áÞmmj™Ô9ƒggi!xI%5RâÂD%qC¦éá~¿uŠœŸ¸è#ÇbÛÑñH”Šã¨s$b‘ï«‚÷==QÄK__iJ±x ´B!Š˜)¯3۩DZ©Ñhz|j4õËDÆçl²§h4õF-îR.wùü‹#ÇPq–Ÿ>z”·½òJéB)ôÞC}‚ 3CL©·qº;2I¸(!.î½Ò…ÀNp¹É¾NqED )x.‘R0Ð0Ô«Ôíh1ÎËÿ©R(¨ljÒuIKÜh/QɤD¨‘T]Õ*‘ýKt†u‚üvÊ‘Ôe’̶•`ŸN™f”‚L„¹$}˜|_RËŲJë°HMœÙN=ŽMF£ÐãS£©_&:>=]”^£© µ¼w^±ë åi£œ?N>™Ì@²$ï×±cÏÐÔô×\óK–/ŸOSÓQÎ;ï¼é>5š ¥Ÿ,$TLrò ²eË–1§Žïûú&ZÔ£m\3v&k|ô¿á Xb­ PÆåƩьõ;ŠG6å9aĘÜñ9YHŠëFQ(ñ"òñT[¾E…HŠ­T*Šp/2ØK¡x©"ÆzF’ÉH¨(C ¾ËÿqdÝUHù>ÊÏ‹¼—s_Ö×§¾'©•“Lªè‰>’,?øÁ2\0݇XSêqlj4…ŸMý2Þñ÷¯²ô¤N£™tj~ïŒ?£yÖÛçá,Û>¬™&|ô£**åþû¿eÁoÿö<Þò–EÓ}j4' U×P©5ëÖ­£··—믿ž¦¦&¶nÝʺuëX·nÝ˜Ú PcÐ÷}7³Ð’Öì`²Æ'ÀiO=M)L^Ê_´æÖcÄšçyÃNö]×Å0 ,Ë"‚!ñHÛŽH8=öÿ8ð}Øóé­æñë¯çyáú“.t¨h”¸¨’ ô‰j–3™ãs²°¬¨fŠëFbŠ×¥Pz¼}"¡>ë鉢D %¸¤Ó‘HbYê}”µF~bå?Ñä¿wIQ–H ‰aJ ’¦M"‚$µšëªÏ6n<‡w¿{v{“ÕãØÔh4 =>5šúe¼ãSjYëLMm¨Õ½sÏž=C:‰/ü?<ï¢ÐY2à;ßéæ–[ÎäÒKÿËRé=è5Ó@Õ‚ÊÖ­[K  õ÷÷ ÷ª¶ˆf¥õn¹åz{{Ù»w/MMMãV9MÀé5šz`¸1<ãÓæíß¯Þø¨¨”IÔ=óù<¾ï“‰pÓ4Éd28ŽSòYœ¶¶6:;;q]×uÉår×!Ãq’E ­¸"|HÊAÓ4illd``€l6‹išáç™L†B¡D) 1k®çyضM>Ÿ'›ÍÒÕÕE*•², ÃÀqúúú( ˜¦‰ïû ’É$Ùl–t:¶+ûÌår<òGpøÛïÅš?_¥ËŠ™E|’ös¹N1Gœ· Âsåyžç‘ËåB!¥P(`ÛvØ9–B¡€ëºØ¶§eY¡8ííítu1·š…:«lÙ,uJ«åø+’R+Ž'B"L¤è|*¥çÊfUÍ©³"齤ö (ã{:~‡H4‘4SRÓ"1† *#!BMrœ"£f(ñïL~'ñ(¡—^êcÁ‚Ç€wOwW'ZÎm5Íø©§{§F£)e²Ç§ ä=]ÍU£™ ¦bnë¡•!©Ã, ç·¶‘¹ë"@=ó °fÍûضíî¸Ã£««+|VÔh¦šªR~-^¼˜µk×–,«Õ¤sÍš5´¶¶N¸í f\„Jaº; ÑŒÂDÇgìzàõ&;yýjoo',ËÂ+›@§Ói‰¾ï”¹.AŠí!‘!@(&žçÑÖÖ®oF؆çy466’Ïç) ´µµáy===ø¾O6› ûàº.Ùl˲B!"ŸÏãy¾ïãº.A„Q:&ŸÏ—8ä‹îù"lˆ€‘ËåJ®†aH$Èçó<ûÃg9òꌗŸ’ý8Žƒçyá¹(‘Hàº.ŽãP(èêê"›Íb¹\Žææf|ßÇ÷}r¹–e…ç3[Ìå”Édèìì Å–ööv<ÏÃqœP4J&“ø¾¾—cî; ‚€À T›ú @šr&ëþY-2<\7Š‘eŽ£DYîû‘°"¯Q"ë@i¡t(- /”GL˜¦J15Q†ÑZ55âê«_™x#3„©›¦zôøÔhê—ñŽÏZ¦ûÒŽðÍäÞ; éGGùñe?Žf³àº'5â8‘£Þw¾s˜—^zD"Ag±(f<±F3•T¡²fÍšª#O4ãÃ@)³³Ô©Z£ÔoüÜ3΀öâ›I0‚B”^ªP( ™@;ŽŠ"V¸®K"‘ ‰1 ƒd2I¡P…‘D"Q"¶HäG>Ÿ'ŸÏ‡Ÿù¾»©ÛaK:ÆqBÁ¢§§'Ü_$“ÉPô‘Èd2FžÄÓkÅ£X2#X€‡”÷ìÙÃæE§qøÈa~ïö ¬1Ö„û P(à8N"âR6› (ù¿¯ÌÂmš&…Bß÷Kú+Q;ñ¾uvv†"“ì'LÓ ­¸€bš&©TŠÎÎÎPðÉd2úâ9MH 'ˆêe@T”ܲ¢ÿe²+…à!*^ßÙÕÖˆájEY¢Ñh4F£9tèPMÛ×yP4šÉ§õÎåüÚ÷oÄûÓâ³`@&C½’ÆF•º« æÍ›Çç?¿Ž––³H§Ó#ÚC4šZ3æ*ýýýtww‡)¿ššš¸öÚk‡†gM3Þ ó”¬5Íl&ž}VÍDǘ٩‰nTXblã»Dtˆ âºn(RÈ{‰X1M“žž@¥þJ§ÓX–í“É$¶m‡©©DXA&™L†!Òn|i;~×h“¸¸ÐÒÒBOOO‰€2Ùµ_}ôQ~qÆ•\þÂë¬}ÿZ>’ø¦i†)ΉDIJ.!. TƒDíííáñ‡DÐÈ>˹P(`F˜n­§§‡B¡@:.‰:jii!‘HT¬9£™|U·cî2ÎûúúÂ""–HÝ ¬ß!5A$•a ÚÛÛÉd2´··Ó×ׇa´´´ËåÈd2¡H“ÍfKÄJQ ñec½Ég2™šO Ö¼oúgئ]³ýI„ÉXS/Vêˆ-ñ¶D*ŸÏ‡ßã8aÚ²-[¶Ôô|žÈ˜¦I\7*/õQÏS‚J6«Ä”rAEnÕ¶=4µ×¬"OT/JjµD®Žæ0ÛÅϬâÿRʵkyf$Šï‰½êXF£Ñh4³q©ÕŽUÍÌb?ûiüX#,.ð88ÈæÍ›éèè¨ QÅfRË3hÆ…ÕTbàøqnxõ µ!¢I¼–F*• ‹¯' ÚÛÛ1MÏó¨A"DŒI§Óaí‘p½ÎÎÎp»l6‹çycŽÒ+É)È[ôó†ŸsêwÕ<Ïk-‘Èù-aÍ€SN9¥æ}8Q 5×5 å1dÛêÏuU /Ióe0RR&3CÄ”€HÜpQ“ 8¬â« 8DHUã'[\¿@$¨Èÿžš).K „YnÆþÏÛµQVƒdñ5(nJ¨É©ØöÒŸ,*:°;£Øžˆ3"ܱcÒh4F£©s`ÅÁƒng8fÂtU£™I8¨Ç’Ü«+á?€¶â‰Dø€wÀû—ÙÃYgí —Ëi1E3íTU”¾··—Ûn»o}ë[%b @CC6l`ãÆaäé&^Tz¦ 5Tf ZPÑTbÇÂ…4îiœÐDj›Äk‹HdG&“Á0 2™ Éd×u‡Üh«MßNмKÄËL抳¯àÒ_ÎåôE§sÞyçÕt_ñâôµ"›Íùž-Ë"N“H$8묳jºÿ ×…¶âDWN¹¤÷5áõ<‘"©¿Fc t·RÚz *Ä^]Ôysl}¯¸M{q™ˆÙâŸ[\_./f±­,‘à‘/þo 2&J)ÄÚŠÛ¥Qu¦2Å×J ÉÛÈ—ebËÒ@O±í¾âÿÒŽ_\OŽ]¢\ˆíWŽ»hA=Ôx¨§¶ØqºÅvüâ6:g©F£Ñh4š:`Çý÷׬í™eaÒhf>`ú-Œ9šJêè|Þüæƒ,Y²„B¡ Í´SU„Jww7­­­¬Y³fØu6lØ@GGG¸ît3¡Á壌Shä±P™?ôMZ3›Y20ÀÂC £Ô7ã ™L†ÅÜMÓ ‹ÌÇ듈¿Rº©ñFMäóù!Å×g";vì`ßÊ¥<óÌó\ÌÅÓÝ¥ !"šÔºÑL ñú)…BTl^¢V&IVí1–j,Œqˆ"I$:C">dýtq=‰à0QƒI$ˆ×ƒ¼Åm¤QDŠˆ)JðÈE¤¤‰¢B2(áÂŒí+M…2Z¤DŸPÜŸ`—½&bŸÉeNÎWñxãÑ/9¢´d~ñ8ÝØ¾µ+§F£Ñh4š)f¬)‡5Íô ~^O¾ ï¢÷*'½öv•îõ|Y(D|+VôrÕUçðÎwÖ6sˆFS U *{÷î­ª±zR€’"ÅãBRm¤™Òt³é¶?›ŽE39øÀÁƒYzéÒ )ÇqH$arÓ4‡4ÇEa¼Ñk===3.ò­óÞ>•‹sá™Ë¹øÜ™<’ÚKRi¦)8Ë´F*¥R{™fiµêÞš 4B¢E!D÷ÝTq™Dpˆð‘$2öÇ ö‘¿½Ø®UܯQü“IÑ%û1„bûmD©·rÅöŒâgN±/Y”ø B¢¸^š¨®I¦ø¹D¢˜Å6EÜÉ¥Ö*Ä>¯íV.qq§’#Ëüâyq( _ìØ_Q”Zôô¢é>BF£Ñh4F3MÀwÝÏ£—= «ß«?üèARž5-K=_ΟÿSÖ®½pVØe43ŸªR~-^¼¸*Q¥»»{º•ÒgL*âM›¢4 HeeAÙ6ÍDãj”µ4³ X¾};kïZ;®íèêê”XbÛ6žç•ÔϨ³%¤tþÖù|ö÷žæmoÛ<+ò Z–…ïûu“rr¶cšQJ¨Inæz°öƒý ¦–ˆyÔ}TòáJŠ,ˆ„,Jˆh&Š$1Ej}ˆ£C¶¸,_\' œDtÉG†HRÞtq™ÔÉÄömÛ‘à&I•$ŠR5ˆD»Øv(~–(þÙÅei¢T\¥ö²ˆÒr  &Qú­$õ!¦Œ“H$êB Zñe*XJýÍß>ŸÅ¯,žî^k4F£Ñh4šiâ¬Þ…\þ«ËI&Á»w°$g´ç©ì_‰„ª»i𿬱Ëhf>U *×\s ½½½# &455M{”Š ½Q™ƒ2ÈÈŸKQ!Ê¿/›BÄ@ÓŽ28DÆ IyQNPö:‰¸®Ö„"Ýù|ž F¬Žãàº.Žã„ÿ‹QR ÔAàºî¸ Ö³ÀV«™dN>v2 w,s„ŠD£€*@o…B×uK ÌkFgÅŠÌŸ?ŸwŸûîéîʤ!us4µÃqÔ„6ÿw(nο@â|HlB݄ˤH%Hê¨v"!¢«ø*)°DİŠëv¢n*RD ²Kš,I«%…¤ìJ—õû"ûé$ª=’+.“È«ø¿k§%tˆØR §(i6!éÌ@·ÔwÒ.80ݽÓh4F3‹ðgŸ}V\5š:GJ4‚³ j¤pìXT¨“¨vÊÿþß›1 ?ÌN¡ÑÔU¥üjjjbÆ ÜtÓM$“IÖ­[GCCƒƒƒäóyn»í6n½õÖé>åDZñ_ò‹Çi e0i!ʱރé-ÅÏÄËÔŒ­ÓI” Ã%JG")KD¨É  >6‘lŒ °5‰°ñ<Ã0°, ÇqH&“¡P’H$Èf•›¯mÛ´··cš&†aÏçñ}?L}fšfxN …™L†l6‹a%¢‹a¸®K6› ÛJ§Ó¡ "µ'Äx](H$”ƒsçBñ7¢Ñ€ +?•]Wìb«Æ´­LŠ¥VŠü}ßÇqò9F,XÀƒ/ò ëÓÝ• £½T¦Ž ö€¿šÜ&¶ƒ×< Öÿß*®(÷¼JÈý2SaI%©± 4µÔpº©¤šJ¢îÉÂHYभxMí‰ïCgbï Õ¥”Õh4F£X¸c‡~6Ðh꜀Èû©ÓžâŒ¿::EêA³ˆdGxæ™ghkû¸ëáj4µ *A`ãÆ€*Ì,Ñ({÷îepp¦¦&n½õV®¹æšé>@ô+ÖT"² ” Ò^|…R/Ö¸ÑÆ"òhÏ-Qjñ°Wñv à…K^`åVräGØÓ¾‡…ß^È㶉K/¥÷Î^šÛšÙ{Æ^>þ÷çû×}Ÿ=gìá‰w<Á¾G÷‘Ïç¹úõ«¹âŠ+Âh©_!EÁ …–e÷üë=|¶é³ì8†Ú©ÊÓ§DE}=¢ëñÚ5q}LŠ Çóíkf çöìeÕo«z}×uK„?ß÷ñ}?TDôÓ“æ±qd×¾xø‹³ÂÞ0ŒŠÂ®fr‘pkž÷ d ¬_‚烱¢låñ^› J‘j‰G¤h4F£ÑhNXîØ1Ý]Ðh4Uâëv®äÜ<wï6h|£ÊïU¤P€\‚à:|ÿ¡¢©+ªT@‰*Éd’îîn¶nÝ ¨BôÓæ«œ!Eéó(#|@T¶“¨,D J† ±x¯@WÑðëú*‹l>«úõÛªŸ_ÿyž\ù$Û·s±s1»ÏÙÍx€ç·>ñ%ƒ[¼•÷ïàɵOböšüÚßÿoJ¾‰ÿü¯ÿäÜwŸËîŸïæ¢ÌE˜Éo|ë7øþußgηçpÝ–ëØóù=<ókÏð‘'?ÂÊ÷¯ýÝ!._p9«®XX—[Àk ?¾êÇàÁ{ «‚Uî9Ì $HÐüø¾}ìÛ|ÿ¡ïså9WråKWòʦWÈͰcá^ÿîëüÁ/þ€{ûïåÈî#° ø[à;±óDâ…lå3»ø}ÅϽK$°H1`Y'G”þEŠÝ Þ†ßç,0Ï3û7ª^ßu],˶m,Ë¢P(”ˆ¥Á¥&¼¸ìEŸnœîžhfÏAþðžÄuà?ög!áC°tº;Gi$‹F£Ñh4æ„d*jkj4š‰ LuÏ>û,¿óÎߟýŒô-ç…Ÿò`šÐÖæÐÕÕ¥)5uŘ€††®¹æš!Ñ(ýýýlÞ¼9Œd™\Ô€ôË©‹’G )Rìv’Ú%†a`FIʬööv‰D¨¤f2<Ïãâw]Œaض“WÙOí<5Lóõµ'¿Fúýi6¿m3Þë^Úö¤ÿ$;¿³“uöº!ýø^ú{,1–„ï—|s —riÉ: þvÁÈé–bâÑ|{>| –³€/ð`¿N?v;Á„(åà…€?8À{΀CÀ{wŽñ|—§©$hÉuTŠKaã%²Ä…k)€\ì3éQÚÖÔøð/?<¦mLÓ$ŸÏcYVøW1úLS=&ì{t …ÓÝÍLb8Éy`Þ¢"VLRmÐÕ5tuqlˆ§ãs‡D"1.Ô÷ýqE¢ÅÓiÖ¢}F£Ñh4Mý SAk43ñ‰>iÏI,X°sá²·¯Àþ]ð}UÃÓ¶Õó\.—›èî4šIgÌ‚Êpô÷÷sÛm·M« *ˆ!(7ЏÅ?©{Ò7ñýAlÏy1 ¹®‹mÛxžGgg'®ë’H$°m›T*E2™ ÿ\×¥¯¯/Üβ,‰Éd²âd`$CÔ”L J¢y̲+†að>Àßþä¼üpc û#Q-ådÊÖñ‹Éâ2‰Z2PQ/ñ¨–.”è&ÅŽýb{Yc·—¢Åšª€+ÿó蘶‘š?"Vê òäÐÞÜÎÂ…ZPÑŒŽã@& Áà‡à-¯¥3Œ’º±íLÓ ëpY–ÖîŠßÇR©™Œº`KIY&uÂLÓ$›Í†÷JP×ÏóÂmA¥$uŸg†B¡@:SUš¦IX–Ös]ÇqH§ÓazAÛ¶ÉçóôôôŒxÝÉf³ašÑxí2‰ª“ãjnnï벋Å)ò,<Ï£«« ×uCG ß÷Kj¨É«»™5F£ÑhúyQ£™Y\øê…˜ÇžA|ムzÎô+ tvvR(H$d³Y²Ùl(°¡°!bDOOÙl–\.‡ïû´µµ‘H$H¥RáýÞ4ÍPp‘W lWîÛA„×-Aæ–e…í¤ÓéPH‘ZQ""‰˜"‘¬ñ÷ñeñócYV8§ÐhêqH."Ìó<,ËÂuÝpÜÅ?“ðø˜1Ò0Œ!ë%â¦çyḗq+û’öエ 5ܤýøØªó&×ÕZ¢£õ4EÆ¢ïû%‚¿8ŒÅ Àó<|ß'‘HÏçÇu+T•tPúw>;éB=¶k4š™ÁÁƒyâ¬' .ß Q¼\†úK§Á0,}ÍÖÔ%³JP P‚JøÔˆ2œKqø ""IáÄÎ0 R©  &ííí¡¨" ª<¨4 L&“³*ßç\c.Ì.˜îžTAôû0cË„ ¥5Yd@.½÷R޽ëØtEÝã„M/ÿɘ¶iii¡³³sVº@ÏG4UüÜÀ‡Ä»Àþ |ík;Ù³çv‰Ï…ëåóùÐpÒÖÖF:¹÷% LÓ¤¹¹9ŒÞlii!N‡©À’É$Ùl6Oå^žN§ ‚€B¡@___Éõ@„P÷Ñød[¶7M3L(÷å¸aVèìì ×?~ü8Ý¿%bD¢LFK[VÉ(9š!H ¹Ò¿L&3â~İêy^(ƈ%ç¿’aX£+"ÜÅsbÜ”1w"’ôœAÏçK„ ¿‰D"Œê!DTââiyA¿bp7Ù‡üöEHA³½½=kd\‹ÑVŽMËx»}.me³Ù’}Ë1ض]r<Ò'Ù^öÇ4ÍðÜÅÓKße9Ÿåý‰‹Ir^å;âb•["bË1‰1|pp°îjdjƆŒrá^îËò^DÃD"þö$¢2…)Îò[ö}Ÿt:=d<ˆÓƒ8f³ÙÐéPÆ…DiÊoR–Aô\mšf¸Dº–ÿÖåZÐÕÕ:BHÛÒgi[#eÊÜ#™L–D¯Êµ@œlÛWœCâb­s\P’TßrNãÇ”8GÈø”ë©\\×Å0ŒðÞîû>¯¼òÊtÿ¼4fR8öÒ1®;åºð}¡ DßWù<˜f!¼¦j4õĬT<`ÅÁƒÑU?c)¾Ê½Ñ@=˜åóùða,N‡e===%C@ÕÞd³éñÌ‘g¸è «€Å@ä‘C=‚drl‰D"L"–u¡FgJÂ9_?‡¾ÉÈ#7Ë1ŽÂŽ…;ªZ·½½ÎÎNr¹\hÕL"bŸÑÎìšð¶ÿ Àݮ˗?K__¶ *†-B‰ˆqƒKÜ@"†…\.‡mÛ%BH¥û¥|&mįÕ\* Õ^SDà4Õ2÷­jû(×H1 ‹À%©Ïä:*ß“^š1jzžFY‹1/ŽmÛ%a‰%´’"OÄŽ|>:‰¸Á°Â 2AøÛ”Ï*+kM%ïy1tŽ„Ì[s¹\xž$*]Γëºär9òù|Éy‘ó/Ô8åB±ˆ¶m‡Qu²AÖ|åº,†d™wÇ íb4‚€¯ýë5?ך±!i-ã¿1ÆÇ…Ayv‡ù®ÛÚÚJîÉmmm$“Iòù<‰D¢DH‘T“õ)Ͻ¾ï‡¿ç¾¾¾PЗ”ÖRóSëŒD‰ŠÀ cYþ/Ïï8NÉ6‚8WÈyˆWÇqp'¼_˘ˆ÷YÆŒKMD¨k¨{«D¯Jšîææf€ðÆ…&9ßé*Ë€0êµ’$ßQ\•û¸)žçÑÒÒŠIZP9çff°â±ƒœû¹@"2„eZºsçNlÛÔ)Ž5uÉIÇÅ sº»»éîîqÁÁA6oÞÌÓO?]ÕŽÙ»w/MMM%Ëûûûéïï§©©iÈg•X¿~=›6mT¦Æ‡f ³“ŒQu.2LÈ;>ÙŒ{„‰W‹mÛ´··‡µÚH¡¸lp—^z‰¿Y¾œE>H¡P=lÄ#JŒ;2ÑO~e’+F9ÙF„IåbÛvxq!¦<åC­ÙÕ´‹í³‹?rñtŸöIa¸± cŸrݺJ¿ñüQ>qõ¬{~ݨ}hii!—Ëá8ŽNõU ÚP‚sçtw¤öÄï³ÉŸÕœ—àMÐr*ô½Ú<5Á½ð²GyòÍñÎN>üå/³zp}ðAÞô®w±ìñÇñ:;éCù2t¦Ó<Ûm “–usVÓÖÖ¦:œŒkŸïû´··‡žöbü–¨¡é¤ü1¨ÅÜv<È*^›G ¢’jO¢ÂÄ€ÿ=ˆ@"Ëê±E3¥tttÐÚÚ:k¢Tj5·,DT‹‹wbè‡(òAƳäãŽg’:³³³³$òk8<Ï Ÿs«uêó}Ÿææfr¹\(ÄI°¾¾¾ŠÏÁ²MWWWÕ±B¡ÞǺM___Õ׬l6‹ã8 Tõ /×Ò|>O&”¶¶6‚  ³³³ê¾µ´´AX?ND˲ôÜvÖ¯_ÏÇ>ö1 …BM X·¡R‹i4åè¹íð”_·ò¨²Å‰õùç+XøÍ´}ÍÄuUNPé¦ûûBSÓß“N§µ“­fBÔbn[U„J?½½½£®7–މ—Müb³yóf:::X»v-[·neãÆ¬[7ºñ5γÏ>Ëò¦¼nÆ dÂ*¡üâ5„uO4¥466ò¹Ï}Žo}k8Y—pg |€— cKKK‰ç2NÚEÌ’WY&"K[›Ê–*^—’Ÿ>.¶ÔªÕüΰæ¬5Ó}º'Jc&6>àØþcmª®(½„¼O·ÁoV££Sf$µŸC(F0yŸƒW·A†<Κ&ûúhظÏóØò¡qæw²ò/ÿ’¥kÖðùýû¹%œxÀ%Ÿÿ<¿õ[´£´»*§YÜEº¸^ùÔøD^ÄhV-0^LÓ ‹ÜËõT¼xmÛÖN “L­æ¶ÕŸ aº7‰BaJ#¢+=œ†1ÄÓ\£™ÉLɽsˆðé8N8ãQdq£ðhÑ…"ŽTk°—¹öX T"ÊÆEÃ0J®/•¶'¸j‘uǺÍX3È6ÕÞ ãQ)c!^j,}«y6™ìñ©ç6ÍäQ«¹­\Ýæ½6‹XùÉ68¿¾¾¯R™fÍÍ…Y•ÍG3{¨JP¹öÚkY»v-kÖLÜh¼yófº»»Ù²e 6l(ù¬££ƒ[o½•ÖÖVz{{¹þúëimm­Jñe´Ý·oï–‰á¢ÂâᢒŠ@nÎåIÍP®jhÀþü+_჋•|6ÜŰ’0%^9•ãA.—+OÄ×qœ0lóûK} Ïf³tvv†©$ß~µì=cïtŸîIa¤± Ÿ°ð”CüêÍ¿u]‰4ƒ_Õ¸®ª”=‹8&ÐZðŒ¡–ã³o'Ãvþä ØêžÍ¼Àg~ÓsÌ9÷7pÖ­ãÕ®.>rá…,\à•¥KÕö¨Ir°d ¯½õ­P÷g¯¸žòJJyù¹Åu’@3p¼øžb[íF¾ˆ0û„—x-†É¢\œ–{pcccmÛÓÓ¦<™ÍF›ZQ˹m5HŠ-1ZÆëiÇ͉ÌTÞ;«A"QÇ Ÿ--Ë¢³³³äÙ£¹¹yHJ«ÑOͬL&3ægÚñDOJ²j1 c\ÛŒÕÉѲ¬1G2Œç<ÇnP^i6RoãS£ÑDLÅÜÖì]À~|ÎWÏɤ2ëtv*³N[[*,± ÑÔU *ù|žÞÞÞ’­ŽŽÖ­[7æA³víZšššèïï/YÞÝÝÍâÅ‹Ã(—5kÖ°fͺ»»«V;}`Íöí«V)ËÍ851¬KŠä—z)šêYT&¦L&’o6ŸÏ™ —çã•ü¹’ \Š$¦Ói2™L˜Û6žOWt$Ùl¿ˆ76arÆçª_gá¡…£®'ù½%—wq¡z•êd…‚ºË Ù¬ZîºÉ€eiae$ºP–lÍŒ¡Öã3Ná-@3œòSõ>àõeXiÆUN’Ü’%ì<õT@ !K!·]yï?7QBˆQ\f Ä§øHP1cË DÑ+ÐX|×q>å‚D¹Hñ«A¥¨AŸjM%bê¨ä é1;¶ ö¿ËðÓ”Z{Wf2™°Ö…üM§Ó¡“‚vµœÛŽ„¤ø‘Ú:‚FSÊTÞ;GBÒèI¦ƒt:=¢Ø9ÖÈ ¤îPµÔ³à:U}ë9“gñ0gÌá>\/ãS£Ñ e*æ¶ à´;^aÞa… ‡• Çó ¥E™{r¹Ü¬·Ãif.ã.JÛm·K…”(—Å‹—,ïííÒÖâÅ‹+Þ`ãìß¿Ÿîîîp@/¢ô.cNi÷ŒN™Ðž“šÉÆEy ×’j.Ó4Ãs×u‡„wÇ#a¤0h¡P£] z‚h’{Ï=÷̚€ÃMÿøÜ¾}»J¸f swÏ­JP‘‚š%‘L® ©ضºË–‡–ßç)±Å0J•lVý†úK$¢md»j¨²ÙÒõ, âUA ÚízJš.ã×IL(‚o&088ÈÖ­[9tèÐtweR˜ìñyèÐ!º»»+ç½] ,‡g< Çß4û—ð¡ŒÈ—?Îu›61Ÿ(òÄF]óóá›’Ô^ê–\Ì&F®¸^†Hl±ˆ"Pò±¶ ”pbÿZŠmˆðâÅö!Q.íÅm¤/v±íN”–h 3¹âú™âúF±½T¬ ¹âä‹Ëš‹ÛÀ=í´ðØ:gpsß>Œ£G –-#5w.î)§Dçäõ×±÷îÅ]¸{ï^8åLÃ@®xãI÷U@‰4c½¢È=ÔqZZZÂBÆã1æ…þþ~žxâ Ž9R³}L%µžÛ–#îyXë'šÉ¢»»›íÛ·Ow7&…ZÎmÇ’¹!•J…Ë«¹¶Ž5uÔ·8¢™dn»ÿþéîʤP‹¹moo/ƒƒƒ5í·.{¯©„žÛV7·]»v- €zv¹ãÀßñ±eWÁ¹™ß…âô– P&•¶¶”®©«™0½½½5™ÛŽ[P™löîš6©±æÀáC§˜âÉ.–—1ÐÞÞF,X–…ã8$“ÉIËe®™|Æc@M“)¶èy^˜ND7ñ0{î¹çØ»w﬈ïøÜ¾};[·nåŒ5kØwdóÞ>oä ²Y®üû¿çrãQ%‘P£aY•E Û.Pâ Ï+C^‡»i{^-JL‰ïO"eä5‘ˆŽAöå8‘°ËEûõýÒÏÊ…ž P}M$Ô6AP*è”÷±\ð ÏÇè§r¦³wï^º»»g 2Ú±–3ÚøA¥¢cÄÏ€·ÂßqþgݾgœFž´tÏ76†"ŠE$‚$ˆn¿&‘aÇ–ÅõdDÛ¨h‰n±Šm™Å÷å%9”x’)®J,ñãèQRÇŽ‘Ü»—¶3Î ùÚk,£AÚŽ%y÷ÝØ/¿ŒùÚk8©-ž8@â'?ÁüÅ/hÿô§É}æ3¤6nÄ^¹’¬ôûÉ'inj"ùOÿDþïÄ|æz®½ñb¬bÖ½÷‚xÍÍt½ÿý¤þîïH^xa8%éúÑðx€Üë¯ã­\‰ÑØHöú땈dÛxÙ,øÙ{îÁŸ7ÂÛßNrÑ"òÅó`íÜ ?øél/‘À[½šÂ‡? †AN¾‡¿ý[¼E‹°ž}㡇(¤RdÖ­6:G"V¤xp>Ÿ§«««f¢ŠÔ擪ÙÊdÌmË ‚€T*5®T=M5Ì&Ae$&:·MPñ<ööö°üXRXV/Esb"sÛLwW¦äXË©fnûÄOðꫯNw÷5' zn;22·mjj*9G7>w#\¸~Ó ˜‘¿Äü¡k§h&ƒ­[·ÎnA¥’gBÿ¨“ÕeË–±qãFò2¾ÏùóΗÁ0Nãºnh0%T‡˜ŸÙtæ ÃrA÷ôGúR.0U‹@A0i©ÚšššØ¸q£ŠšåŒg|.Y²dHñÏTYÿB%ìyü<5‡Ÿ?÷çß¾X¨Û«Do€2ÐÛD·Ý¸ô)ëÈ·:dTg³˜É$fÑpdd³$‹¿#JÅÔl;è)¦ø³3‚d’l±íÄu×á]uÖ½÷’1M°,2Éd|ùË+V¨ß™ëҙϗF¼55ASIσ¿ù›02%}¬ /$pÓMꃋ/.9¾À>;] ÉÎnÛXRp·¸(‡Šzyíò˹è»ì2Î<kÁz- Ó›€»|9^*EK*FÚt¡D%§ØfáÓŸÆ šìhGE²$víÂ|ðAÌ×^#uýõ¤)Šc¦É•wßgÛÜøž÷°æÖ[ùÌEA±mŠç¡³¸¾_l/‹¸ªý"twwW¹ÅÌd¢sÛJHáéq‹)2jE<¯fF²qãF:::¦»5g¢sÛáp]7LÜÙÙI{{û˜Ç«~öÔTBÏmGŸÛJzofªÑsÛñÍmçÙ_{¼ÍÆË*sJ@{»ú\êk4aݺu£FQ‡ºTÖ¬YÃæÍ›K–íÝ»·ê”b’áëŽÁÕ4}¨©út_®Ë¶{ïåÇgžÉ ŸùLXïâ®.å .᥆B1hÆ'¼qcª!å14ž`ÞF³áqÀ²¬0ÕWy$ŠeY|øÃžî.Öœ‰ŽO€¶5 ;‡ýÜ~þ@æ _˜žƒN°,%LL†wÄhã?™šÎ,ŽiŽÞøç•Öuµ €–TiÛñÉŠç©™LÑ(çEõi„lV-7 Õ^"Qú¹ç©s?öò6'ºV q©<Û z-‰ÉŸP¬}âÃ/þæ=Ç|8ýô—Ù×û»¬8®Æ(¨Û«üJÇíßÖV*¤Éoµ ~çåãR–y^ø{5 L—EW—2ê—]Gä×b|éKÑÂJ®aŒXc©«2 ”˜•ºÿ~‚ `ç²eôœ~zø;_†;ç#^N;-ÀX¸ÔUWÁ¾}ô|ù˸ø‡dñóÚk¹¸ó®»¸ó?ࢠ"W‡•"Mú%éÜÚ‰¢ T¤LŽH`Ë¢Ißv"0YcSÈçóضFÐAŠIx—äųˆrêÅCŤÀ,óŠïãƒ]ÂÀ2¨/;ædÛ÷‰ Iá¤x(Z¼xR>Ö(<Ì$Ê (}°Ëú(¶/¡q20¥¿Ò¦ÛÞŒõQ@P¶±6­Øþ„dñÜ%bÇYˆõ‰Ø±K¿¤0±eò]ØÃìCBó$l/^Ô)®^Æ×÷_rZÅc•܉f¬…âzr®$·¢K±ÍTñ‹œÙLöøòù<¦i†…æ§%ÚDÆœ{¥ã\rdÆswúeëÆ¯RœLÆ·üÆ%¼´€ºNH{ñëH<äTÂ[ Ŷeœ—÷ߌõG~¯ñX9éëp7iù}Ç?—>ÊØ”}Dc†Þ¬Êi9Ïr\åíJíØúã}8žÈ¶3ñŽOß÷k>ÞN”9ŒFS‰É¾wþÚþŸÁ+§6‰Dô(†:[SÏT-¨ô÷÷ñVÚ²eËv8ºÑhmm ÃX[[[éíí¥¿¿Ÿk¯½¶ªíe~sú±ÓÕ¤e¤ì@âáíº`ÛÛ¶ñÂ000¦r ‹_ôô 5Þe2¥©u*¥ÝÉçK3b ZZ¢mm;Jã3 gìÙ‚ïû'tîÆ‰ŽO€3‚3J¸®cEÃ뺸<Âííó¾ld|–{²ÏdŠ×>2™áë½XÖÈÑ40º¸#"ÍH×µÑÚóïy‘ðR~-=Á™ŒñâñÃðº,~…§.b°f<·&Ëä^*Ž A Æ’D=Å¿ËÑÒûɬ—ëÃ$bo ÷Íofβe0þ¤¶_ÔÐ@Oñ•ÁA¬ÿwH&KÄšôÂ…8ãF?d™ä”å )n¥ß²mÜ *¢DÜào«ü Ÿ‹ -åŒì¿@i¸ ÆZ‹"£«ä5”~ÇÅ#i'¾9Çñ}Ä—É1‹YޝܠìǶ•ã!E¾¯¸±[þµ3Û6.J×_,c¶3Ù㔘âû~‰7mr,sG) $Ž!ù=ˆp*†ûxÎM*ä;MSZÀL¾wŸ(lQ„Jûd_‘˜jוBfq1O~¿ñ1&cDD¾lqÿòy.Öu£0‰Š˜±ýˆP!EÓÂðK"ÑPDJ+¶n\€¡x>Ñï¿=öy%9ˆK¦ØW)˜&>IqÑÓ§T°•ëA¼¸œ¡r=“c”ë®ÜD%‡§ˆWò]f!qÚìN5 Ÿµ¬µu°ÑhêɾwîŸ÷‹Ê&^êQ1 PpuÄ™¦®©êiVŠÖÆÃK[[['=dfãÆÜtÓM¬]»–­[·²qãÆ1å ´€[îP¢Ñît–¥Rå»]—¿hkãà‚aòj §NÁ¶‡±ë ûA y(ö}%źn´ß¸w¸¯µPL‹R’†§<%O>ªâ䂤2<¯tÕ‚BÛbR©(MOÌHkS4¸ˆw¹x¹7Á)ö©3Nd1E˜èøÜ}ònÖÆ §®[ò{¢d2Yó‰ð˜I§•GýlTl[ûJ)¼&›x=˜ñ"ýîz*ugäús‚ -Ÿ‚w!°GE ä·%" ”Fü¼ø¥b<ÂSƱäJíB‰jVlq€Ò0ßxYØâ‘åžÕ™$_…x”f\ô„ÒßW\ä“þɵJ"Òä8¡T”¡>~.â‚nÜQ¢ü±³<’N3c˜Ì±9pJ‹ŠÏ‰…‚zd4ͨYz2ÓÀk4“LU‚ʺuëFÌ;6mÚTq?"Ôˆˆ3VÞ¿°BxnY‰a„†QÇQwº\.GØ¤ÓæM £Ô1Úq”}5Ÿl“…B¨ÏŒÓZ0Û²”à"bE¹à ^Ûâå/bIyDL\0)7ž–)ËÅ’ø¾ºº¢Ô>qr9µ PÇPn0—“åyê}yþö¶ÒvËS«IZùÜ4KO´ç©}H-I‰o#•*݇e•е;ÂóCÛ8¨46abãÓΙûj©Pây%E2™¤½½½>ódV“jk¦`ÛjÌÌŠéøBAE±<Ë¨ÅøŒàÐQX2¶ÿ°ë_᳉¯ ¯'ªå¿è 𘱞y&|^ž6‚ ª¿dšÊa¸X°Þq<Ï#“ÉT%|[({Bù= œóØcü|×®é<ÒI§Vs[×uù?óþ—ö_ oelk4MÍï ÆiÅk£DaÄ££ÄÀžF帰QtÇH[|7ãõ™M¾ å‘_µb<纒Ñ8þýU€F¤œ2»ŠÒ×||ÆÓÚ‰€)!³"r‰'`†¦ÍqáRà1"áÀ޵/i:Ä»4u QôY<ª1`¨@€¿LØ Š$uÁ»,Yn—öÅ?ÆËÅ®—G"Џ"ûáÆ½Æ#Mã)(ͲuA E±È7w XcìX$õ§œcy仑ܽòxš!¸„xtk¼¸ø˜‹µ8¤ÿ"F‹ åÇ>áJ>/©âëÈù‘slÀâ‹g]ÊÌZÍmå´Î}þ£J` J1LyÊLf Ô]¾…‰Nf¯^uutƒ‚(Ò#—«èáìy—_þ›AÀ­·®À0¢ì$É$47+¿Ø‹²YeK2 PË%³—+Éd”å$™TËÒéÈ‘ZšQmqïîJBÇhQ0£}^‡zÜ 6\[#-ïêÙy´ÈÑ>qd¤“9šÒ%âTü¼”_¸[ZÔ:ms‚ .ŸoÿàÑ‚2‘ÐqÒétýâœMõr¡«×s=$z¨Ü˜ïºÍòæ3ÎÛ3Œ‰Þ?xNºN ŽýødÞ¶jUô™Dú~tÍ1}¦àò<¯Ä0®ë–Diø¾?äš%5·lÛÆ÷}‚ ‹Ëç‰D"̳ïû>Édß÷ùúð8¸ãü·¾51äÂq ÃÀ0 ,ËÂ4M‚ Àqr¹\ø@‚ ÿ/?¦Š˜¦J÷'ÅI‘Dª$ R©T”zj¤dE¥=ž~ì šî¯yJ˜èØ<û_ÎæŒÿu ß¿pºE£™uLƽ3‚Ê×W‡È YMáÄ{ÄÐh*2îñY 2z‹q]Rɉy£“Ê‘B|–}ÞV>Fc~w^2 (ób†ÙþA}èÛ¥)¢14=Ê£KNæ¼¹ûJ½þ%:¥ˆþôaö|2ïܹ“íWme®ýž!h6– O>Ìœ9sxåõ×1ç/:‰e§œ¢ÖÍDp¢½Ìä´?8‡qîœ9ô~ä &°§±1lßȨ}\tä=ß=Μ9sX20À±cÇ8xð gdÎ…b_Œ$,8x˜?>§¿ü2w7òøœvÚi,úäK¼~Öbv§rÉksxúðQÎ_4'?}˜¹ÇçÒpÒk¼ö;¯Ñðòk d颥<óø3,ø³7sôèQ.=e.¿úäAN›‹¶½ÄÒ¥KÙ|æë\õêkœúÒN¶¼ÿ¼éé>~mÑél;È/Ï<“kûæ±uÁ«¼´~¯¾Ê© O%¸, õÒå<¾óqNZÛÌöíÛ9ÿØ<~ñÙ3Xúú\æÿr+Á,Ž=J»»‡ÿïº ¸áëeµAg)½wÀÃ?ÌysÞ-+f…6 how´ ¢©{Æ$¨ttt088È-·ÜBGG·Ýv[ÉçMMM¸ñˆˆià™ÓŸ‰©î¾ò²¬ ¦ pèÐL3Í_ýÕ%üð‡‹9ë,µ‰ë*ûè09§û~iI•L¦´œJ"¡v™HDZN2©D—lVµ—ÏGÙ½$óŽëFå R©Hˆ[•Ô‘!FJ È«Øs|¿ÔÎ?\‰A².‰mµÒzÜÏ6&û‰e©ÌT\'*l” *•èêR_`W×ì0BO5ƒpãs7Fï}ˆ@‘Ëåô sª˜M)ì #JŸ'‘Ãà´¿þëéîáÌâF˜ß /ºK_;§ô3‰ö¨ñYÄÅADø:®ëbY¾ïcY…BÏóÈår¡ð!‚†çyضã8aûÉd’l6æÊ‘#N‡m·´´„¢J6› ×$ŸÏsÝ•Wòý àÅ?ú#ò7Ü@ôôôÐÜÜLWWW‰ˆ"ó-Û¶C‘#—Ë‘J¥H§Óá:¾ï“N§±m›|> ×’fqØënÙ}Ѳ¬ÐXèyù|žd2 …B(I›Ú&8 xpÅSWÐôþ Š¥¦fÈõ0¬iÔBäÝ^M*7F3¹ Mñ6I)¦ª}Šã¾û].]ºtÄú ž{޶;îàâ%KÔ4— j J](0MSÍ-!têÙÓÒŠ·¼…»¿øEþફÂù©ëº$Šs>Šë?¼go|ã|äÒé4©T Û¶Ù¶t)‰Ý»ùÑœ9œzùåXüÇd2™pî(×9i+›Í’Édhoo'×Ù‰ã8\—Hpï‡NE¦iª¿sÏÅqö46rñ’%ø¾ÏÚ7ŸçæO}Š[›ßû^ …Éd’ïÜÎ{öÆù„šKg³Ù°M9[·oçmW_ÍÁÞþ†EÂW\Æo?ð$s/½”§.yÏï~‘­g5ðÐò×¹~ñ2^¼ï>þçmo¦é½üáüùÜ;8È«¯¦ïå­øörN}òdn>í0Áe«qð}¶ òݹsIüü^~¾{7÷¾ç=|úÞ»82øäýÈg> ðüEm¼±ø>n×Ô¶!ÍLà¤ãǯfÅ›o¾™{d2Ɇ èèè ··—[n¹…Í›7³eËn½õVÖ¬Y3¥°~ýz6mÚDêæö·oþ[>}ÿ§Õ²¹Y©<Ëã7î¡¿¦é²ÿµ|ðƒW–Ø…D̘,;‘èL’¥Ë²¢WÉVeQÙ“x)Éø%†Ò¿B¡4%Y¼Üƒd÷‘í¤”I¡ A…¢;„a(Á'•Šú‡$CX6)ÇÙlt ⠞ϫm¤}ËŠJ­ˆ#)Ó$Ø£½½T8’c–}ÇëÇ£MS­/íÂPGõZÓÑÑAkk+­­­S·Ó@ww7ÝÝÝlܸ‘¶°ÏÈ’>>|  –––ª<ž5š± ÷M)åçÅCÙ2À—¯:ÆÜG‰išô$ó¥7ªÂ+§†òèJã8˜¦Yò&Q–e…i?ƒ ÐlÛ¦P(„‹ˆ$ííítuu‘ÏçÉd2APâ•,BG\Ä냀뺸®Ëgî¾›e=6æó!ÇŸÏç ‚ A‚  ­­\ÑKDLƒ 9ß9EO‘ƒ+Vð¿ž~š×þàÂjÏó‚€D"A2™¬(fʼnß#4¥Äǧ›rÙº}+ŸþÏOOw·4'zn[™J×­|>O>ŸçΛîdÅï­ˆÒßÔYöÚ‰0–[µЕ֓eòÜYx/*}*÷YÖ—ÏÄÑPœË ¥¬i2=kËgò¬[îH(Y­ãÙ( Ô–P¾d«Åøó¹C>¯þO$¢ç\y>þÒ—þ™ûïÿøÔÿêœõë׳lÙ2lÛÆNÙ•kñL^Ñ(‘J¥ÂÚ â@#óV™§šƒÊ¼É*«/šJ¥Èd2¡“ŽÌóÊ×-ßw¡O$¢Ò/ZŸ¼%pñÅ#®3&£žF£™TÀÜÁ 8é¼}Ìݺ”®¯>7fÕE3~3šb<ÏR[Éu]²ÙlÉD;•J…w‰D"ôâ=ß÷q]7|5 #qË +_ï+ÞLåZ%µñ‡É#>ª@¶—rʸ¶’e7gÃ0èêêÂ0 ²Ùl(zˆ!0}â8…B!<Þáª8©XüÕÅóÕb»©T PÞdÝSmZ0Íx°ë]¼sÓ;§»'fÿÁã|ëæo±¢{E”ç¿ÆbJ<ôHˆQ^„ÓTNl™Läè&ÏE²¾î‹3›úËËnJVÉÎ Žpò*ÏpRîSóÄANö•ÉDÛ˾åyNžåÙNþ¤|¦LI¤4 ìÛ0¢>Ëó°d2p®9<ÆŸ3!Ên Ñy¾È3·üÉ3f>m'¶­ö+çSê¯Êûø¹Íç#§ÃTJ½ƒYÃŒÓrþN™e5T&Ïóhol¯IT˜¤q®Þ§ã8X–¦‡Ï$ŠWæT‰DbȲÓ4Ãynµ†å±ˆ(•¶«–‰Îw5áÒ?º”îµÝá"ljl¡Ú6¤™ T%¨ÜsÏ=´¶¶Ž}²aÃòù<½½½S¥QHeižÉÊ7×…––=<òÈÿá†Þ \9åý­ÄDì†1ôp+E•Ê:•NM|ÙDmfííêbSâ”Ûæ,kh½úøv哸ø2Ã*~x^”+ž^M™K”L–ã‘<--ªövÕ7‚´#ÆØ±öÀŠƒ+F\G<¦5Íô`îo_þ*¦y:Ù¿ÈsÖ­#mÛ`Ytvv–¤B+ ø¾_±ÆŒf à‰Oð1ëcÓÝF3 k»×²ö¢µ*Ô3^@z‘ç¹  Qfq ã¾ü%kãDÏ[Ù¬Z&QŽ -"Ž@$ÂH„†³”¡’ÞZ–IƉ䇽øs^OOitŠÜeßÒ–PÍã‚”•ve:#·@‰Va©šgßòuÊ£bâÇ”®”/Q,âÔ•Eà‘6Ê×yà‡&ç‡5Kyó¯Þ<©ãPæFâ1Ÿ.ûrÛÚÚÂHIÃZN"‘£™5 p ^{í5V¼t'åöX×uÃg=¦žwQúuëÖ188X²¬©©‰½{÷NˈéaåΕîð¡åüóÂÎ_ã¯ÿú½|ðƒõ!¦Ì6LSM¦§"µþHÂQüóáú2œønă)›Uë;N$°Ì› µu{ít&#Á)’Û-öyžzêh4šiâa`žú÷àí 8璬ౚG¤Ä‹¨çóùPT- 8ŽÖ&$^“Äó< à³³³bêÛ¶‡ˆ´uÿ +––ê²±N¹î&‰0ݘ¤–‚€T*5$2(LY»yZ–…%.ÁæÀ. ¤Óiš››ééé© Ñj&qôÁ£<±æ‰éî†F£† ¸dÎ%Qõæ Þbââ†ñtOñÑÕ-K&£2â<¿uÇõðògž¸3ÛhÏlåmq;—,“ý–·%ÍHTr¶‹¿Ž—álã¥àÆËxúVÍ4¤N2«ÎX\0©EÜÚÚÚH§Óaä®ëº¤R©0-l.—«j~9sÐòú¸qgÏÑ?EÔ¢šzaÁÁ4x0|/÷(mÒ̪T/^¬Xqùó·ó­oÝ<æÐFMõˆ1l'‰D”ëV²ÈÅsø~å+ÿL}TÖLâàÁƒìX¸£4/]ñ:×aÍ4r0W9'¼öÒ"å úw;Àž\U<^WÃu]òù|h|—eét:L9%%ñV•&Øõa2“‰ PR_¥§§‡l6~’Ë[ŠÚ— ‡\g'®ëbÛ6Ùl–B¡¦ÈÐ×ù±qì™cœÿ{çOw74Í0¸®Ëo¾ú›ðͱo›ÍF)†¥n%D)‘%}–D*Èÿ2–˯¤’ÿãx¨gä‘îŽ~ñÏ$Òƒ‚â¶VñµšøqÙ&ÞNɹª²fÂ$˜ðÍóà«_ýGZH&ÓCD)ßLÓæ­omओÎÃu—”Ô‹õOÙ&õb!²ÄëÄÊX—è¯ ˆÒ³KÚ>Z%£F<µ|.)çâ׉|¾4»´/× IͯW+™>²ÙH´•w’éC›Ñ4“ïG)¿‚ À—¤FSÇT%¨\sÍ5ttt°eË®¹æšŠëäóy¦­x¡‰òt_xÙœ›í-q¹qÝèuýõOñOÿô5¶tY I§+‡:ÏD,+Êã[É[êŒ3¦'*k¦±zõjx,Ïèº÷×hf3Ï€µÜ+aÙ²1ÍføÛ/Mê.š››I&“a„‰xöI D"A6›Å4ÍÐáÁ4Í!õ@4µÇ4MÇÁ4MlÛ#‰r¹\øÓÞÞ^RƒÆ÷},ÛÆjiQÑ*ÉdX·&—Ë…UZZZøÆ7¾1݇Yßðèyj¡P£©c\×åŠÕW°0±pÔuÅØù°/€£¤úà° ß’]‘(‘±!…z¾u,`™êÕE ‘~¤%ŽDBJö±÷ñøãËB!¢ú>Éä¥ –ÖÆ•Ûu¹èiš¥5mÇÂhö”øçåëzÞð™8âÛˆc¥¾q!FRüIí$I§.â8ÒÆù<“QâŒøC¹n©ˆ#ç®ÚÚP‚ØÛ%5¡8ÀJZÁxû¾_}j?ͱþî‚sCÃQÍÍÑx*Ï: ÑÔ+U *MMMlذ›nº‰ 6°nݺ0BE ÖoÞ¼™[o½uZfåΕ\õÀ1ø­ÒÁ'SÛ†¥K·aY–6ÐhÆÄx'Aõðpúg*Æg³Ù0„º‚@M˜$ç±xõIžæöö¨VD õ™ÔëinVëõô(oˆD"*)Þ<ñ<ÍlÆX¿ñøãìzuâíÅ ç‹O8™Lß÷ÃÔŽã`ÛvÉýX î't˜wÐMÓRGTÑùöövlÛ#‰‰žç‘ÍfU­•\.zº~úÓŸ’Ëåðžò`u?*À".J¯ÛjýK ƒ” ÍD‚ˆ2¨@†È¸Ķñ€¶â¾“(ã<”FŠˆèáÅ^ @ÃéÅëÆúÒR\ŸWŠ>aÂ/ö­¡‘+""ˆT dÿ"FÈùQEž/²ÅÏŠ¶TDbв«Ëg.‘XBñû1JΣûßd¨Ð$bQ’H$Éì—Ší3‰²õ'ŠídcçJD£ ¶LúV ^Â.nÿöÓNCS™Õƒ«GüB¤vêSOíÂ4]¶lÙ€ã$™\H"P(X¸p —_Þ„i.q_ñˆ°J¶ßé¶W3}(6‰÷9éRÉ9.ÉÔUþ7Í(e¡ü/¢ D"´ÓÞ^Z¯VDxz2qÑǶ£6EL’ýHêyù¾m[ý/ö‚øqÊ~òyuœñ>Jÿ‡CR/‚Ú¾¹YÏk«æ(œýêi4|à*`èãT43ªk¨lܸ‘Å‹“Ïç¹í¶ÛJ>kjjbÓ¦MÓ",<´c§y`¸d¹(ã*g¤ÊÁ®¨F3u¼éå¶­„ U&âùù‡C¼aLSM†Ä‹F&h¹\4©m&žGº¥%òjiQŸårÑDO&c®«þâ´ P‚‹ˆ5APšz¤>‹«ÑÔ;þe`̇O}èO1Œ¥Àw&Ö^Ñh.5’<Ï ß‹€¢Ó?U@ÎI[[uš)@„±d2‰ad2 …–e…õmòù|ø½¶µµ)ÑÌ0°,‹ÿÚ¼\'•âãï|'[çÏ'—ËñÕ¯~•·½ímÓ}xõKö<¼ëo´ ¢ÑÔ#žçqñG.ƹ%2ÔçP‚@¢ø¾Í€n5à`Ua`¡Œç#Éëñ›H€Êöäx´ˆ¬S­ëB|*[I€©4ÕƤ²˜ï§¼Æ#nD”®ýòe>Jl¨äÐ?œ“õ}ÅoÊ‹mSÍv¢ßGb û’ˆžòm\`÷9猡Ç';@"C¹e©W©EôÀ—_~9Ÿüd7A "§}ß'NèèÐ*ˆ 1•ü âŸWŠ´‰‹4qßJy—úQòÜ_‰¸Óc¥Nñ~‰¨ÒÞ¥t—4õ¦©þwœH€» º[øIDÌÑ£§¡}…ªÃm€ç\ ™u@ôaªa¦ÞSQú 6°aú»»Ãe‹/fÍšú¨Ñ» —ÌéóO‡|–H¨"©…BAq4š)æÔgNeÉÅQž~W_ÝÀêÕ*R¢‰,“0añV©dc¬äßUO,ì;“Qíg2jR”ͪu eÔÔn"žÈ ¢I¸ãD^5¦yÉäó‘çK[[ä1#¢M2YšWÂ¥+å¢9xQ$l“ÍF“Ô¸ˆS> •É¢Ö’5y¬Óá•ÇúùRã&®š„&}ßÇó¼0-”•׌BL¼I&þ½Å ÓÛ¶¦nK¥R$‰PhÉår\{íµœñ ¤Ó466ò†– pširoK ‹/žîC«kžÝý¬~ Ôhê”®¾>Þ»õzÖÏU‚@ÍùG͹¼â¼u,ó¯zŽÑÄ;Ö©§Áð"ÈHûÝEkè~Æ„.i¾ÆÂx|«†û XÀ/ÆÑÞ‰Â÷®ýžR£Š? ü^€;á‚‹è2? †ÁŽwþ™ÿƒàžç‘ÏçI$ÚNTÈ3¼aL¾c¢d ˆ‹/ñ(”xD (;€LËÅ uk’ÉÈùR¦jO>ù 1S©fŒÃðØþÇXÇºŠŽ¨Ú^3“ "Lw$Êp¼ý'oç”O^^åâ'êw*• sk4š©ãäc'c^P:î\þôOO瓟ÜËõ×GÞ(mmê5™¾ÈæDˆïCD‡®®h%3žåd•0æL&r$ÑÂ÷Õ$˲¢"£q‘EBˆ[ZÔ¶ò -Q1EW¬ë ”Hid(ž5"@ù~4Á‹GÚHtôUŠŸ‚Ú¶¥¥T¸Éå¢j"øø¾:žµ›JEç.“Qï%[­»º¢°k€DØI$”$ùr!¾\â £)åɵOr臦»f¾’JQ¸æ8íeÙ—Gͯ&”.x4/˜¸¯ÜJ+PÃЉQ<®L¤ÊÝÀe2)yx`hA™`Ê>ÅÃHðˆ>­¯åÇ-–¶8åsŠÑŽW&b¡uÝ¡Ç+ŸË¾*M&eR\> ®Ãõ5¾ŸòãŸÓJŸKD3 ¡‚ÕröN:WÝŒ¹ã~¸¡N³ÙóßÿÍ3ÿú¯\ùÁJ êþÚ×øæ›ÞD£T‰/ÿ‹—ÚHò¹¶3Õ=µ"ÓÙø.ÿú*Õt)ÆÑ~/ãÃ:ýç÷ÑåpçÎÃøþv …‚.Ñ ™ŒKP©gNýµw†ÿ·´¨ žýºººhkk›î.j4'O¬~‚•-s]ø­ßz”%Kz€$©”2šg2S›&k´ü·2oŽG™Tú<¾m|^>'—l™ ÉçÙ¬:'#âN¼ý®®Rïø¼Þó"(N¼8 ˆ.ò,èºÑ~D(Òˆ .Ô> µLŽ£­-J‰ŸPJˆ8Ò¶!”TmqÑD"„Ä;(]#—nñ,’gÑTJõEž×å»’‚‡š‘‘"¯ì„‡÷ÞÅŠÓvù¼¹®‹ëº%EåmÛÆó<,ËÒöãa†(‚qON©­bš&©TŠ®®.‰DøûÐFccá_.Äü°6Ìh4õˆ\ö“}|Ó<Î[iPË|ÝlÛŹ]¼zs¸aL`‰’„F ¢Èˆq7.LzžZ'Žx·ñ\4P:¡„¨8€e•†a—[E|Žøg•ŒÉåòù¡¡æâu#H®xå}(7l‹§[%÷ˆñB åW…*³øñÊĹüœ‰p?öò‡ÇZì±ü¼É~‚@µSvο: Åîf+ÅŸA6 öï,ÇÌÜ®ŠY–ãÐõ¹ÏEë».×ÿð‡4~úÓC2Ç‰Ò ˆÇXü7ÑÒRÞË磇.(õhƒhKÛâ™Wr,~©Ç˜To‡è!Èï>þ{µxÿãÄÓT# 7¶â}.?Wyè‡æ„çõݯ³â râ³mu+üìgŸÇqnÖ‘bšìTÄgeõàê’d³†¡î!}}*õˆã8aêF35¸Àê§Ï¤ñÐOÂIž7Œ%ø¾Y<Õúõ8×’yædö­üùJ¢7âQ²\(wR‹·1œßFjÆÄýâÏs•H•¶6%€”¯7\™B†;Ÿ²N¼ržËŸ)’IõWi..¹mÅ¡LÚ®ôü­Š¸E'ø¿üÇ;ù·Ûïâ:j¾Ÿïéé!‚ ÐÑ ãÁuÕÄ%QÏ _*“L&Ãï>“É©TŠÎÎÎ0ý›ëº:í[•,{qÙØ#»Äà1’‡·`Ê¿‡JÚøï0nÊU| —ŒSþP\¾ŸxØh¼¯rÓ­”óC ¢b.?Þ¸¡In4• £bÔ”>—œË£ÅÊ Eb,‹ßÔ*q¥¯Ã}7òY¥}T³N5ü£y½Ç=°ƒ€e/¾ˆfx|àÜž½¼õʳÃe…$Þöéà«ÐVüí”ñßs:]Ùð8š!)>iŽÑÚ0Íháî7òé:4Ú~ª¹†Uªv]ÞÆhíŒ&ØÇw¼ÇRÍ:‰Äè÷ïѾ»*ŽwÛgŒÞוb„J>;Õűæû>]]]¥óSÓdåý÷W~ÈK$FþÎG²+Éà DB^ÇŽELÅñ<õð5Òo»üº^)J^åá;~<â-(EE$×v¹À¿ŸÆ+ÕÇÛ–cJ¥*‹Ä’z@<ËEâööðûS# ×—âmˆgžx,ʃaüüÅû!÷ÌòPÂææÒóSÞF>ÍAÄ»oBáˆ'&>pøða¾ðÔ?Ù0 ò“Ÿ|‘ Hà8]uRKR£‰Y%¨|˜‹;€åóù0¯»F£™böÀ“”Q;^8k,Ô;bCªõ}=—«õ=™H‘ø¸cn­ö“ÍŽ­¾¶8ÿŽÅ /6³Jz¹aÀªUÕî g>à-…WŽaîÞ9aœjðýeþíÿ¦Þº(ærÊsR?`j4ÓÎ/šæ°géÃÐÖFpï#$ºn›fj0#§6Ýݨ_<ÔÖ YœÇF3íxÀów°ÿ´ýá2•q4˜1ö!f“ ²–Œ<‘+yEkAE£™–À±×ŸÃ£‚ Àq‚ZZô'‘L&Jq[KL³ö龦j~2žýHôúxÊh&Æ‘{XôÚk$#wm !ÙÉd’ÎÎÎéîþìa–ÌS$Ý—,’̶m|ßÇ÷}¾ò•¯Lw7ë–§à¾SîS5T¤–É,ùmh4³ƒƒ ø”»l÷È3±ì•f†¢ï£x»Ï)+èÔïM±æ+8ΛJêÇzž‡mÛZPÑÌfMÊ/Ážù,+¾-JøtQ#fzðÃàŠu`Y¸®r²UuY#oæzÇqj[?E0ÍÙãá(£Z‹PR¨^?#k7üÚ OóèÂÆÙ£®ŸÍfI$ôŒTŒS3>ªI34Cˆ×OI§Ó¸Å‹¤_ýÕ¯~5Ý]Ô”!‘~r]•º®ñÚ«Õ Þâ/Qí½Sö©ÑÌŽ?Žñb’ÿ‰«KÍh4õƒç‘þÜñ’EŽã(FSxÀÛƒÓybÃ;øÏ<¡¨¼þ¢FSïÔ• ÒßßOɲµk×ÒÐÐ0ê¶{úŸâ¡3^çò@=üÅí´ºvŠF3qÆ;>ƒWáï¤c‰Ô4š))‚D˜mε<ýR'y¬)¼ÆŠýfÛw3V&rÿ´îƒ îŒ#Ëâû—Œ¸n¡PÀ²,²Ù¬žðjªF$õ—çy|ìccçÎÓݵš3Þ±¹âàÁÒ‚èzž§þ—én"ÕBO$¢zåR¨W‚^d®.hk‹Ú•u½K?§žZ²,‘HhAE£™D&òÜ) x„={ZÂ9žeãôó¥fFQW‚JGG[¶l)Y¶iÓ&Z[G/‹xÒŽìµ>穇ªx}Õh&ÎDÆçÓsä7øP}!9õgŽSût\SÔƒcU-÷3ÖçÙÏ û9M:Ÿ‰ïÓúìž{%÷Œ’½Ë4M<Ï#=[B©4SBüzoš&–eñ¯ÿú¯<ûì³Óݵš3Þ±ùá‡*¹P˧ԿÑ"‘ˆ â2ÝQ`,µÎ+r—ßóäÞ!¢I|Ò?ÛV¢ÆHí–¿O?>úúÄ%à¥û”’=’5-. ‰ÈGêÇK©\.¨’ÉÒÚŒqâbD¼ ”â÷B¶‰=™LTžöS„é‡ô9“QŸ‰hbYÑ>å»AI¾3iCDªø>äŹ喯à P–~<ãs`ÉÞü(p_^^;th4µb<ãÓ;çú’ºŠ…B×uµ=H£™D&òÜ)ìÞq›7ŸMcc4WÔ…è53ºTÇ<ã\pú™ÍfõMT£™ 㟯ò;î ŸâÅË}¦ ×”P3"¦©—ï7LCýo÷)Á?¦U\&˜ê/þ 1ÔN²CþùWÐzìØØ¿“ÆxÆç‹Ë–±ìù3 &Ši4šÉg<ã³<5¥eY3ê™S£™ LÔnïúYø©CÜqÇ¥á˜miiáøT4šI ®•îînn¹å–1oçóæspÁÁгL Ÿmmmº~ŠF3 Œw|Ùy„¿|¢{GôÐišæŒI÷‘—çlAqŸ}Œw|‡ÕënÃæ¸®çyA0£Æ®F3ÝŒwlž|òÉx@*ÏpU\`([½ÇÈZ‚0Ù·-qúI^±¿c¹j 7äøaÚ Šfl]y/}ÿe}PÚT{_ŽÍPÄf}ñ‘O¢ãDY›Á¶m°rå8ZšYŒg|6ì{wm Øð†’È#fªxeÕªéî”0žñYî0ÖÖÖF__ßtŠF3«ïÜVðçwÿüÇ¿ •Š–k1E3Ó˜3ݸùæ›9ÿüó¹ä’Kؼyó¨ÛmÛ¶¹ûnï{íË·“L–ÞDµ'­¦–¬_¿ž»ï¾{º»QsÆ;>ï¾ûn~Ùp%)&ÜZW*׌ˆeÁlËØTžš¦··—õë׳k×®éîZÍÏøÜµkëׯç=»0²°gOã¨ûÉçó:ÚS3)lÞ¼™ŽŽvïÞ=Ý]©)ã½wyê)þí7“÷ Ý„½9ø¾”=]|ío²Q`&a161 ŠÇoŒ°Y¶®ìÛŽ}fÿìØòøûJßaù²áÖ—ï§šßÆHmþËúõ<ûÿ0¥ßÓt0ÞñyAú>1wØõÇ!™L’˜ …„4ÓκuëØ¸q#K—.î®Ô”ñÞ;O>óLþ¿oäd>¢o•š)FÏmGŸoiz Wû2†1ûœS4õÌm.\8Ý]©9ãÛ>öØu¬[·PsWO«žš)BÏmG·ÛnÚ´‰5kÖ°ïu•&!îg«á5µbãÆ5™ÛÖ "ÉÃ×ÚÚʵ×^;êÀŒÝK°, Ï‹Ò}Y–¥?Í$0‘ñù¦þ¸{¯,ñâÓ)ƒ¦—BavÔƒu™Ì‰]Ce¢÷O~âðè£×pôhÓ°«†¡sPk4cd¼c³Þ<öœóV~'¡Ó i4µb¼ãsÛÜâ¹7œ7«RÁj4õƄ綠4š0c`ð% ˽Ôu]òù)«Â§ÑL u#¨ô÷÷ÓÛÛ[²¬¡¡¡êíO:þ†a”ÖttŠF39Ld|Zº‡ó——¼µ·Ðô’N×¾ ½fê˜Ðýs!:z?K–,vÇqtª/fŒwl®X°€›vlÆ^§¥ÞR9åË|ßÇó<|ßÇ÷}‚ Àu]‚ ªå}¡PÀ÷} …®ëâº.¾ï‡à®ëâ8¾ïymkk£P(à8NÉú…B¡d[ÏóhkkÃó<š››Ãmey>ŸÇqÇ!ŸÏÓÞÞŽã8477S(JÖõ}Ÿ––\× —·´´”lç8©T*|ï¿¥¥¥ä}[[Ùl–T*E6› û’ÏçKÖ©ôÚÞÞ^Ò÷ø1 ·ÍÍ7ß<Ý?£š3‘{ç“§\ Ó}i45d¢¶!P郴ŸF3¹Ltlð–ùM$‘ ¢á53‘º)JßÝÝÍm·ÝÆwÜACCƒƒƒlÙ²… 6Tµýž“%¨46Rƒ~¦¾ÖhꕉŒÏy»VñøÑ9¡—­ïû$gª•h– OÿìbB÷ϘÛûW®{©¢'¼ã8˜¦©Sôi4ã`¼có”SNáÁïÉ•çMM?ƒ Àó<,Ë" ÃÀu]LÓ¤P(„ãß4ÍPüí,ËÂ÷}‰mmmtuu‘ÍfI§Óáûööv2™ žç…mÅÈrÛ¶Éçó¤Ói²Ù,™L¦D`1MÏó0 #쟴aš&A`šf(üÚ¶aák&“Á², Ã(y6me]˲è*>DHcy/¯qd.#)*,ËÂ4ÍpÝžžž°?ñ÷#ÍÊ·iÿåý(_W^Gª!0ܶ)6;Sïø¼pûvºNùõúyˆÖhf!µ A Ói45`¢cÓŒç!d_MB6«D•B¡ ³!hfu3\·n½½½\ýõ455±uëVÖ­[æÀ‘°ÿ´‹YBiqÀB¡@.—›îCÓhf<Ÿ§>…… †ÆZñ6ÕïÍä0¡ûçAxiq‡½ å€Aµs‚F3v&26}rSŠ`â8N(d$“IR©ét:.ÚÚÚèìì ÅÛ¶Ca”h ËÊ"¾¼q¢’ç¡,“9ôå¡Z b#Æâ‚OüUÚ”¶FšwL†h¬…ç™Åxǧ l]p9×Ïð¯[Æx­ïï2‡k¼‚2z‹¨)ïãÂ©ëºØ¶ëº$“ÉÐà&¯¾ï—ˆ´"úñ*ÇPÒ¦ì?ŸÏ“L&K„^YãÛȹJ$d³Y‰…Bd2I>ŸÇ¶í¡×0Œ!⯈ƲMüU®½²é¿,K$aEx~ùoœîŸOÍ™ÐÜÂïJ£ÑL.›æJøá| ׿ºÚ^3©A”7Too/{÷©‰¦¦¦ª¶óN“_?Ÿ‹ŒÓßœi4š‰3žñùì9çп¢Ÿ›>µX Dœfò÷ýó¬ãìXtÏ>Û0$BERóéñªÑŒŸñŽÍ‰ ©ª2™ …BL&F~ˆ":0Dlñ£ÜK0­«okf!㟞að†7¬šÒúF•D Ó4Cc|<ÊLŒÿŽãÉd†¼f³YlÛ.DX°, ·X!8.TÈuÄqºººÂë‹ã8$‰PøÂÿE´•kôU^e[‰0“ã”u‰Dxܱc$êLþ@EÕ¡#m¥ÓiÇ!—Ë•œ3‰‚ÑBú Ç/çRö/õäÊ#Û$’/.ò¸®[ÒÇòÈ9y•udŸ@‰À$}L§Ó¡PsüÌ3§îÇ7Läþ)çW£ÑL>žÛþŸ. igxÍLä¤ãÇŸîNL„õë×óâÿÙÄÖf.ùïu¤R*åW{{ûˆ!îÍdÑÑÑAkkkX˜K£èîîæŸ·oçȾóxìï›ð¼FZZZÂTM­Y¿~=›6mšînÔr^šwÀ{>øGÜóÒ×yþùÒ²jâ‘®=ü4µ »»›îîn6nÜ8Ý]©;Þÿþ¿dÁ‚/QÍ4Öó¼0ÅMŰ'ÞÑÍXÐsÛÊtwwsçwÒÞî°jÕb&Ó^+5…â‘©TŠÎÎÎP p‡t:M¡P¨h0.ª!›Í–²­ïå³ørÍô¢ç¶•‰Ÿm ÒLzn;<2>] ëoîå§…G¸å–ÏàºÉ@*•Ò‚Š¦¦Ôbn[W*ãf0úWì>úáQ£©öÿ|7‹-ÔâžÜj4õƒyžmx–sæ ùL§æÓh¦‡3ÎxÑleA„)MÒét˜>&^kC×?Òh&Ÿ3Î8ƒÏ}n1#”µ©ŠB¡Š'qáSÒêY–EOO†a ©‡3™y櫉>Ó×ÍLCÿf5šú$޳ƒ;Þ‡eiªû¡vàÓÌDf‡ rð OîúgøëÛOyîTF3=œµâÞù`ù|^§üÒhꉅðôÓGùíßú‘®¢ÑÔ'y"‚‰aÚ«O£™BÆó˜)‘ Žã„µ>,˪XHÏ“5šñãyžvÒhêܹÃPù¼§ÍŒdv*l§yŲYÐÏ“Mý`¼là=ÞÄ®'—ó»¿«r4ë‡D¦Žøå o|ã)î”ÜæZPÑhê ß÷Cç1Êj4š©e,%…ÚÛÛCC‘iš:í­FSc¤æF£©OÎøÙ>.»,2EK *f¦1+‘Áá¹k1 2¦óEk4õÁKK10p*é/¬TnÌ®‰æHÐh4“ÆñƒÏ±k×x%¢ŠžØj4õ…çya½)¯Ñh¦žW^YÌîÝ#¯---d2Òé´¾Ÿj4SˆazÌi4õÊ ð|`qúêc€º_º®«„43’9obúhXȶ³!cÐó<òK£©v,[È §„ï+¥5Ðh4ÓƒŸ{€“O¾¬DLq]wº»¦ÑhÊ( X–¥4šif``ɈŸ·µµQ(èëë#‘HhîF3Åäóùéî‚F£Æ7ʾ°PÎðÚF¤™©ÌŠ•·<û,O¾r5‹<°¬Ïóô Ôhê€ù‡æóÚ“Ë,_ŽãhcFS'ø@sW@Óe`Y•|¦Sói4õC*•"™LjìFSÇäóy|ß'—Ëé{¨F3èÓMý4¼³ùìñ%@ä0¤Ç¬f&2+"TNÞw!O|3¶­‹èj4õƧ„‚ŠåÔhêˆ;ŸÅæ ìÙÓ.’°k6S£©,ËÒbŠFS'<ûì9”?jú¾iš¤ÓimÒh¦Çq¦» füƒ0ïåC¡}(‘Hè‚ôšˬTö~]‰e)cM}ðê鯲mÞ6@¥âÓ5šúÁ4ØñêÙ´¶¾. ‚@ƒ4š:"•JiG!¦ŽhlÜS’&3ÚÚÚ°,KUfš ‚€ÎÎÎéî†F£Ž}ð¦†]á[-€jf2³BPyåÞ¹¼ë]€®Ÿ¢ÑÔò•mœýÂ9€*¨ µMýàŸ¼”]OÏá‚ ¢:Gù|^G§h4u„mÛÚQH£©#ÞþöÇ€± Èf³ôõõi1E£©<ÏÓ5T4š:Æ?ug¿Ú¾ÏårÓÝ%fÜÌxA¥á´«h¸ôý¨ò‚·m[ƒ4š:áü§bÎ1%væóyý°©ÑÔ—ÁþÝ xÿû×–,Ö§FóÿgïÝãä(«üÿw !7˜I…@ØX!\œ€B•ºèšµgÜEÖä«éVwY\ÍÚ-.¨¸»vËüDoÓq7xÛ%SŠ¢Ñ)Df§"JP˜2aŒI0¤’I ·ùýQýTW÷Üz.=]=9ï×k^Ó]×§.§ŸËç9çDƒD"Qé"‚0 ŽãHÛV"„abZ"ÌôŽð»içþ¤ië ÕLÕ *»O=Jßm;Ùµë477WºH‚ ä8t`/ï[ðåà»Ä€„± šùY|ÙlVlT"D<ïAˆ(®ëbÛ6Éd²ÒE!G&“‘h%‚aæüéE^õŠíÁ÷t:]é" ˜©zAeÿìýþÃL.¿|žçÑÑÑQé" ‚ãá#¯äçÓ¯dÖ» DŸÿ¼£¿¼8øîº®xx BDp]—L&Séb‚0®ëÊ$Aˆñx\ìR"Š<ø^<þ%ÀŸÌgÛv¥‹%c¦ê•…þ3¿äVtÝ7H˲*]$ArôÍéãèŒç%·‘ Dÿ¸Ÿeý~ [Çq$t‰ DMÓ$l‰ DÏó°m[<È!b¤R)iË BDq¶Â\w'ŸßHž@¡ú©zAåœGå?~ 13!jl<õRœÖçyb›‚1Ÿö<µËÿøƒ·âE&ÑAòŽ Btñøàƒ‘Îmõw«µµuÄ{\Iªá÷ãX`¬ö©ë:†aDRð¬†wK~?„‘«mN¦Ò;u{/•©ôLÆË±nŸòNG©òL&‚cÙ>«¡ \*SåžJÏd¼ŒÕ6ÿ¯Ïm;•+çDrì6êuI5¼ƒQ·÷‡zˆG}tB•îîîŠfmm-½½½Ãî÷ðÃ3cÆŒÈ>¼;vD¶l‡âÙgŸ¥»»»ÒE’(ßÃîînŽ9Â’%K‚Je*2û¼÷Þ{Ù¾};äñǯô% J”ß-€={öð«_ýŠ7Vº(ƒåßC‡±cÇžþùJ¥ìŒÅ>}ôQî½÷^N?ýt¾ýíoWúåwK!¿ã+ÛîÝ»9ãŒ3*]”²2Ö¶­ã8¬ZµŠúúúJ_¸ˆò;8Z¢nï¥RÊ3‘¶íÐö¹cǾñop÷Ýw³téÒJ_¸8–Þéja¤g¢Ú¶GŽ©tQËÎXÛ¶«V­bÁ‚,\¸°Ò—0fª¡ \*Såw¦”g"mÛáÛ¶~øaŽö­¦­ Î:ë¬Èõ?£^—TÃïB”í}ÇŽìÙ³‡ .¸`BAåÀ–•âÎåJ¦ c±Ïë®»Žë®»®ÒE„)ÏXìóW¿úU¥‹-Sž±¶m÷»ßUºè‚0å‹}þíßþ-û·[é¢ Â”GÚ¶‚MÆÚ¶íééªtÑa‰LȯÚÚÚËFR9A˜Ä>!ºˆ} B4Û„è"ö)ÑEìS¢‰Ø¦ 䉌 R__?À8 IÇ!ˆ} Btû„h"¶)ÑEìS¢‹Ø§ D±MAÈA¥±±‘‰€º»»éííåŠ+®¨tÑá˜GìS¢‹Ø§ D±MAˆ.bŸ‚]Ä>!šˆm BžÈäPذa×^{-+W®dÛ¶mlذšššJKÄ>!ʈ} B4Û„è"ö)ÑEìS¢‰Ø¦ øLëïïï¯t!ÂôööÒÛÛK]]¸ BÄû„è"ö)ÑDlS¢‹Ø§ D±OAˆ&b›‚AAEAAAAA!jD&‡Š ‚ ‚ ‚ ‚ ‚ BTAEAAAAAaDPAAAAAAã?õ©O}ªÒ…¨Vz{{éîî’1 µ ¶¶vÔë'’îînfÍšÅÌ™3#U¾¾¾>Ç¡¯¯SO=uTe˜Ìû'Tã±ÏJÛf)e¨´}F¡|Bõ2œ}FéÝ‹}VÚ6£v…©C¹ì¶Rïc9ì{²¯¥\õ´üFTåì“FÉ>Çk“y-åìãŠ}Våì“Vâ](Gß5JuçxË*ö9(Ü“¾¾>ž~úéÈÖQïwwwóä“OF~ÜvÒÇÖú…1qÓM7õ744ô¯]»¶ÿÒK/íç;ßÙàÀ`ýí·ß¬ohhè¿ýöÛ öiýDòÔSOõ744ô?ðÀ‘*ß¶mÛ îáõ×__r&óþ ÕÇxì³Ò¶YJ*mŸQ(ŸP½ gŸQz·ÆbŸ•¶Í¨ÝCaêP.»­ÔûXûžìk)W=-¿ÕE9û¤Q²ÏñÚßd^K9û¸bŸÕE9û¤•xÊÑwRÝYÏ$êDåžÜtÓMý7ÝtÓ¨Ë7åzßøúë¯ï¿ôÒK#?n[‰±5TÆÀSO=ÕÆgôoÛ¶-Xv饗ög³Ùà{øAnÛ¶­ÿŒ3Îèê©§J^?‘¨#übE¡|á{vàÀþK/½´ÿž{î)© “yÿ„êb¼öYiÛ,¥ •¶Ï(”O¨NF²Ï(½[c±ÏJÛfÔî¡05(§ÝVê},‡}Oöµ”«ž–߈ê¡Ü}Ò(Ùçxío2¯¥œ}\±Ïê¡Ü}ÒJ¼ åè»F©î¬Ægu*}On¿ýöþú§ê?ãŒ3T*ýL£Þ7V¤x+oTì»ck’Ce ôööÒØØH}}}°lõêÕ8p€ÎÎNjkkill ¾¾žúúz:;;KZ?‘´¶¶R__ÏÊ•+ƒeQ(_gg'`ýúõÔÔÔ`Û6«W¯± “yÿ„êc<öYiÛ©|¥¬Ÿ†³Ï(”O¨^†³Ï(½[c±ÏJÛf)÷HìS å²ÛJ½å°ïɾ–rÕÓòQ]”³O%û¯ýMæµ”³+öY]”³OZ‰w¡}×(ÕÕøL¢NîÉÊ•+iii)°ÃRË7åz߸··—––jjj‚pd2¶æ#‚ÊhlldÓ¦MÁ÷¾¾>¶lÙ¼\ÝÝÝâÞÕÖÖÒÛÛ[Òú‰¢»»›-[¶Ç,¯tùz{{Y¹r%›7ofݺu\{íµ/ípe˜¬û'T'ã±ÏJÛæHå+eýD0œ}F¡|Bõ2œ}FåÝ«}VÚ6K¹GbŸÂX(—ÝVâ},—}Oöµ”«ž–߈ꢜ}Ò(Ùçxío2¯¥œ}\±Ïꢜ}ÒÉ~ÊÕwRÝ9Þ²Š}$ ÷¤¾¾žÆÆÆAóbDá™F½o¼zõj6lØ@__p¡ˆ(Øw%ÇÖDP'[¶laÍš5466ÒÒÒäÕº0á‡4Òú‰ ¯¯k¯½–[n¹%PK=ÿd”¯··7P-ׯ_O]]ëÖ­ ^ÜáÊ0妣µÏJÛf)e¨´}F¡|ÂÔ Ø>£ðnÇ>+m›¥”AìS/i·“ý>–Ó¾'ûZÊUOËoDõ2Ñ}Ò(Ùçxío2¯¥œ}\±Ïêe¢û¤“ù.”³ï¥ºs¼eûHÔïIÔžiûÆŠÞÞ^6nÜÈ–-[1e¤2D½ï>eAeŒôõõ±nÝ:Z[[¹ñƹñƃuƒ©Ÿa…k¤õA6›¥¾¾>p;pàÝÝÝtwwG¢|࿨·Ür lذ––6oÞi”ìs¼ö7Ù×R®>®ØgõQ®tGXg€IDAT>éd¾ åì»F©îoYÅ>õ{•gå¾±¢¾¾žM›6qÇw°eË–ÈŒÛVzlM•1²víZêêê°m»@¡ÿe+~”®‘ÖO}}}lܸ‘7ÒÛÛË=÷ÜÃ=÷܉ò566PÃ߇+ÃdÝ?¡z«}VÚ6G*_)ë'‚áì3 媛¡ì3*ïÖXí³Ò¶¥{(L=Êa·•xËeß“}-媧å7¢ú(WŸ4Jö9^û›Ìk)gWì³ú(WŸt²ß…rõ]£TwŽ·¬bŸ‰ú=‰Ê3rßxóæÍlܸ1ø^SSSpÞ(ØwEÇÖJJ]/pûí·÷_zé¥ý<ð@ÁßSO=lÓÐÐÐÿÀô÷÷÷÷oÛ¶­¿¡¡¡ÿÀ%¯ŸhÖ®]œ/ å;pà@CCCÿ¶mÛ‚ï—^ziÿí·ß^R&ûþ ÕÃxí³Ò¶YJ*mŸ•.ŸP½ŒdŸQ{·FkŸ•¶Í(ÞC¡ú)§ÝVò}œhûžÌk)g=-¿ÕC¹û¤Q²ÏñÚßd]K¹û¸bŸÕC¹û¤•z&ºï¥º³ZŸI”‰Ê=Y»vmÿM7Ý4êò•»üQï«ò©cF}Üv²ÇÖDP7ÝtSÿgœ1à/l ·ß~{CCCÿÚµkû ^¸RÖO4Å/VÊwûí·÷ŸqÆýk×®í¿ôÒKû¯¿þú’Ë0Ù÷O¨ÆkŸ•¶ÍRÊPiûŒBù„êd$ûŒÚ»5Zû¬´mFñ ÕO9í¶’ïãDÛ÷d_K¹êiù¨ÊÝ'’}Ž×þ&óZÊÙÇû¬ÊÝ'­Ô»0Ñ}×(ÕÕúL¢LTîÉP‚J¥Ÿi5ô•­¨sDyÜv²ÇÖ¦õ÷÷÷O¨¿ÐÛÛKoo/uuuƒº ´þX(Ÿ:Gmm-õõõ£*C¥ïŸPÝDýÝŠº}F¡|ÂÔ¤Þ­Jÿ~Œ§îŒÊ=¦ãyç¢ö>ާ¬“}-媧£öL„ñ1UÞ…ñÚßd^K9û¸Qz&Âø™*ïB5ýΈ}N.Q¿'Q¦Q(_www +êö=™÷PAAAAAA„¤ô‚ ‚ ‚ ‚ ‚ ‚ # ‚Š ‚ ‚ ‚ ‚ ‚ ˆ "‚ ‚ ‚ ‚ ‚ ‚0"¨‚ ‚ ‚ ‚ ‚ ‚ Œ€*‚ ‚ ‚ ‚ ‚ ‚ # ‚Š ‚ ‚ ‚ ‚ ‚ ˆ "‚ ‚ ‚ ‚ ‚ ‚0"¨‚ ‚ ‚ ‚ ‚ ‚ Œ€*‚ ‚ ‚ ‚ ‚ ‚ # ‚Š ‚ ‚ ‚ ‚ ‚ ˆ "‚ ‚ ‚ ‚ ‚ ‚0"¨‚ ‚ ‚ ‚ ‚ ‚ Œ€*‚ ‚ ‚ ‚ ‚ ‚ # ‚Š ‚ ‚ ‚ ‚ ‚ ˆ "‚ ‚ ‚ ‚ ‚ ‚0"¨‚ ‚ ‚ ‚ ‚ ‚ Œ€*‚ ‚ ‚ ‚ ‚ ‚ # ‚Š ‚ ‚ ‚ ‚ ‚ ˆ "‚ ‚ ‚ ‚ ‚ ‚0"¨‚ ‚ ‚ ‚ ‚ ‚ Œ€*‚ ‚ ‚ ‚ ‚ ‚ # ‚Š ‚ ‚ ‚ ‚ ‚ ˆ "‚ ‚ ‚ ‚ ‚ ‚0"¨‚ ‚ ‚ ‚ ‚ ‚ Œ€*‚ ‚ ‚ ‚ ‚ ‚ # ‚Š ‚ ‚ ‚ ‚ ‚ ˆ "‚ ‚ ‚ ‚ ‚ ‚0"¨‚ ‚ ‚ ‚ ‚ ‚ Œ€*‚ ‚ ‚ ‚ ‚ ‚ # ‚Š ‚ ‚ ‚ ‚ ‚ ˆ "‚ ‚ ‚ ‚ ‚ ‚0"¨‚ ‚ ‚ ‚ ‚ ‚ Œ€*‚ ‚ ‚ ‚ ‚ ‚ # ‚Š ‚ ‚ ‚ ‚ ‚ ˆ "‚ ‚ ‚ ‚ ‚ ‚0Çœ ’Íf±m»ÒÅ8¦ð<Û¶qgBŽçº.Ùl¶Ò—%”±ÏêÁuÝAíZìsj"¶YýŒÆ6ÇÁó¼JY˜Äv«‹ÁêV±Ý©‹ØçäS©~©Øfu!¶YÆjŸã­;…è#6YýLE›<æ˲ªÖ›šš‚J"ü9Ê8ŽÃòåËÉd2477“H$Æ}L×u±,«Ò—&”±Ïê •JÑÐÐ0¨]‹}NMÄ6«ŸRmÓuÝcú>M5Äv«‡¡êV±Ý©‹ØçäR©~©Øfõ1Uls°ïQe¬ö9ÞºS¨¦ŠMV‹=–ƒ©h“Ó+]¡tlÛf¶„?G™ææf’É$ÉdÏóhhhÀ²,b±X¥‹&J5ÚçXp]—L&COOº®ãyóçÏ'cF¥‹'8Vls¢˜ˆ&A˜Ž%Û®n-±]a2©Fû¬T¿TlS˜LŠíq*ÛçDÔ‚Pnª±¾JcÊ{¨X–ÅòåË™6m‰DbÀË«”ðùóç“J¥H¥Rbè8ÍÍÍL›6-øAW455‘Íf™?>óçÏ'›Í’J¥˜?>Ë—/ÔÓR·‰T*ü_»vmð¹u3\Û¶|l›R7Ü5©‹d2 €¦iôôôTŠêXágà8Nð,Ô1‡s ?·Ñì'Tžáìs8ÛTë³ÏÑØ\5Øçhls4×Tн fŸêišüW Ø¡îØgõQéºs´ÛÅDÚæ`Ë*eŸƒÙf)ûßµ_x™a"ŽV1b»ßî-õšÆZ¯£ª[Åv«i÷V®Ý;ÙýÒðw±Íè3žºS­‚}†mS½»áïÃQÉvïHö9Ñu§ôK£´g«³=;Ö¾hÕÚdÿ¦§§§èO§ÓýýýýýÉd²èO&“ýýýýýûöíë×4­¿½½½ß¾}ýñx¼èïèèÖ©};::ú5Mëïéééïïï/8N:pÓ4Gµ])¨².e?Ó4ƒë*þ>Ø6#¯”kjkkë7M3ø‹Å”èÇãýûöíëïêêê×4­?“É,W÷^íÛÑÑœ#÷†l7Ü~B´Î>‡³Íþþþaís46W ö9ÛÍ5•b/ƒÙgGGG<ïÅbýmmmý±X¬à>‰}V?Q¨;G»ípL”m¶¬Rö9”m·ßP¶©èêêê×u½ß¾}Á5 Õ…Øn~¿‰l÷–zMã©Wûûû‡¬[Åv§ÒîÍïW‰vïd÷KûûÅ6«…ñÔáõQ±Ïb{,Õ>+ÙîÉ>'ºî”~i´‘öl~¿jkÏŽµ/Z­69¥•d2ÙÇ –éº^ð…@½¤ýmmmý†aìǃ}ÃZ”zøáïaA¥”íJa<†¨~@û>Ô²áŽWÊ5©>U!ªïÅe ¾išý™L¦_Ó´!Ÿ¥:G<ï×4­À‡ÛOˆÃÙçp¶Ùßß?¬}ŽÆæªÁ>Gc›£¹¦Rìe0ûT¶¬ž•®ëûˆ}V?Q¨;G»ípL”m¶¬Rö9”m·ßP¶©ž¡®ëý]]]Ǫ ±Ýü~Ùî-õšÆS¯ªm«[Åv§ÒîÍïW‰vïd÷KÅ6«‡ñÔýýѳÏñ*•j÷ŽdŸ]wJ¿4ÚH{6¿_µµgÇÚ­V›œÒ!¿Ç Üÿº®Ÿ=Ï+p¿ oëº.Žã0mÚ´à¯*\ކ |݃}jÙDœ·½½Ó4I§ÓÄãñ÷±øÜ¢5MÃuÝà{Ø-ì.7Ò~BtÎ>‡³M8öì³¶ ¥ÙKñ½¿ë®»°,‹®®.Òé4===8ŽC&“ ¶û¬n¤îüº‡ZV)û¬îi¿¡l3“É`žçaÇ9f“&V+b»ƒ_÷`߇Z6^ÆR¯d³ÙaëV±ÝêGÚ½¯»ÔïyÞÉê—ŠmVã©;ajÙg%Û½#ÙçDÖ ýÒ(#íÙÁ¯{°ïC-/cmÏŽ´ïT³É)”¾”X¥C= MÓ0M“ŽŽŽJ_FÕbšæ€8~C]1ÅÏ¥8f¢a´µµ¡ë:‰D‚®®®’ö¢ÃHö9Üçpö؆g,ö²k×.t]/°eÓ4 öû¬n¤îŒcµ—áöÌ6•-{žü~º®‹eY:,B´Û­<ã±ÛáêV±ÝêGÚ½•¥ýR±Íê`§RwFƒ±ÚËPû(ÛŒÅb‘¿BiˆíVž±Ú­¬nÛH»·²Lv¿Tì³zOÝ Ñ³Ïb{œÊö9ÖºSÝ'é—FiÏVžñØÇXú¢ã=g¥˜–K(3¥q'p¯ Ï¢ö¶û,ÿñ&±ëê&*6{œècŽÇ>޵>ì1òKAAAAAa<Wé‚ ‚ ‚ ‚ ‚ ‚ DTAAAAAAF@AAAAAA„AEAAAAAaDPAAAAAATAAAAAAF@AAAAAA„˜^錗·¼å-,]º´ÒÅ’={ö°páÂJcHŽ9‘#G˜7o^¥‹2$Q¿‡{öìáøoûÛ+]”HqóÍ7ÓÑÑùgåòíß¿ŸY³f1kÖ¬JePªá÷cÇŽüìg?«t1"Gss3sçέt1†¤Þ-ùý‡bÙ²eÜtÓM•.JäˆzÛ¶T¢þކ¨Û{©”úL¤m;8?øÁøêW¿:%Þ…cí®J}&Ò¶œ¨·mK¥ÚÀ¥2U~gJ}&Ò¶š .¸€W¿úÕ•.ÆD½.©†ß…¨ÛûÿøGÞûÞ÷²nݺ ;fÕ *K—.eÓ¦M•.Ƭ[·.Òåëì줳³“ 6Tº(Cõ{ØÚÚÊ‚ *]ŒÈqÁðÒK/É»5Z[[ill¤±±±ÒE”jùý2wîÜH¿ûÕònEùVËï‡0¨·mK%êïàhˆº½—J©ÏDÚ¶ƒ³`ÁÞò–·Dºn*•cí®J}&Ò¶œ¨·mK¥ÚÀ¥2U~gJ}&Ò¶šþþþH¿ Q¯Kªáw!êöÞÜÜÌK/½4¡Ç”_efõêÕ•.°ÔÕÕEöGCõ{(T/Q·©«««t1†¤~?„ê¤Þ-ùý„á™Jï`Ôí½T¦Ò3Ƈ¼ÓÑcª<a|TC¸T¦Ê;=•žI¥ˆú$¨×%ÕðFÝÞ—,YÂ)§œ2¡Ç¬z•¨ÓÒÒRé" K]]]¤8 ú÷P¨^¢þnE½Ò¬†ß¡:©†wK~?ax¦Ò;u{/•©ôL„ñ!ïtô˜*ÏDÕÐ.•©òNO¥gR)¢ ¢_—TÃ;u{/‡ "*‚ ‚ ‚ ‚ ‚ ‚ # ‚Š ‚ ‚ ‚ ‚ ‚ ÂHÈ/AaBð'ôÝÌ-³rßõÜz-÷ÙÈ}·rË4 dCû( ]´,›;Ž:¹c‚ ‚ ‚ ‚ B9AEáÅÍý/lxƒlãåþb¹mœ¢ý‹‰åþ[@¾èáá nè˜.É-å¾;@sîWn*S˜O^x1;·¾HåÎÙž[§ÎóÃO~²Ò·YAAAA˜ ÂãLzn™ƒ?7¼s¨<çAE¡ŠQ¢ˆ:T…¢D‹ÁhË­K@”Há’-ÂØ¹e%–KÇSìÜ>¥zŽØ¹}Õöêš¼‡Š+g¾Cè{ªèº^ñ裰lYyn¾ ‚ ‚ ‚ Â1B¼%<ÆÓŒ?¹UEiÀ7<ø{Íÿl» éþXŽ‘[o³<Ø\­ùû¦^€÷Ây§À¼×úÛ9Àc.\£çÇ‹< kCÌÌGA1reSL\àÜGá¾nxóßÈ9|DPA¨0Ê D©êvÑÿ°h¢*%–¨ÐYác)pE¥–5…ö10ŒÖP˜%n§ˆ .ÎŒ÷<ámtò‹/ªx¹e àuÝÝðַ޲ô‚ ‚ ‚ ‚ &<ƒÖ$?È£ƒã‚aP0 ô·¿ƒÿ=×ÿl}´Uù´š™eùðëñÜá,àÔÇ¡öeXzpœßÂý†·Ì„ÿ¹ ´>ðŽ€5Ü€e¹‰·‡ÀÞ :xóÀ«ïx˜±¾ùsðú“¡,þ5Øoçx0Ÿ„‡ï€wÁÿ?pƒä—á¾{à›o‡Æ—Á=’?†ßd ñï7Ý í‡sþžýÄOþ™7Á­Ÿ€?½b§Kà“·Á* fÞ6fÐÇ"‚Š U‰RœUÝ¡á«Ñ.¥‹“AØýòa­-W^!1òžFî³Ê;Ò>Ž2„cÌGù å>Cá=ßË/>úè$]± ‚ ‚ ‚ Â0„‰²à]žz-ໜ3A›æÙà}¼ÙpÃãðÑ?ÁË?ï4_¸¸j|f 8ËÁ›éÿ9ÿöÞ^8WÁ¼]ðìÐü_¹m^€~Nz¬W}þòþÿ„YG`÷ƒ6ôãaglºþîap.o,¹27CòNˆŸ™·+@{’Ÿ}.¸WÁ†ý{‰ýx±/ƒ~>Ü>²_„ÛŸ|ï^×Í:Ž›^½žXȦ†Ùh—¤fÁk¾_ޝø˜ðû¿<ÍåwÏã2çÀ, ™?Àõ߆Øã@ þåC/S»û%ž0ÿÇ1øðeØŸ¹u'~äÄ }Œ"¨‚PU(ñÄÂïVÖ-|ñ Ö ò.ú¨ÏTZYTòt5I@ ÅB ¡íÚÉ{nh¡í›re“Y£÷‰ åp üü*æëAAAAÊIHæ>»Ÿý]àè¡q‰p›ás/Àg?š ™]ðØásàœ×‚v2XÍpüƒ°h^±Å`7ƒƒŸý-ìúgÐ÷€7–|R×€±´Ãའó÷»b·C|ü  î}¨ó‰i°b_‡›vÂŽ¸äãÀã{#\÷üazŸç?©EŸ ÆÙYÆ,0_ ì…ßÌ;À%ÛžäÛ³_ÁßÍ_Ì¡ãŸw"Ó€¿¿k—ý¿9ÔÖÖò­[ï⩇ßFúrxä› ]}+\x¸>xÏ»Ù|þfHÍç¿ËÂ… Ñ~z!w6ÞÉi±ÓˆÞ¿cY;K¼+ÀÏ~ü^zù.\ÕÇdÿƒtÙzx ßÌ_yÎŒ&Ô•N>9{lûë¨û\­¢“ ‚ ‚ ‚ ÕC "¬ A®å–‡Ày¬·Bìÿ s*tü8 R›àäÿ‚;~=küãØŸ„¹ß‚ÞËÁ æaø“?;®\Ö{!6~¡ÁŸççrâ.ôÇ@>ùë¿p¥s ŸÎ©6š 󡭌ǀ•ðÒ¡'xlÑÒ—çFM–Âûoûµ>¸Ä_üÐw¿Á¼Ÿ^Jìýµ,_¾œŽŽ\WÇu!a/§§§‡Z÷fL›Æn<Êï–¥°m›øÓq Χ>u ×zYºººØµk÷Ý×ËG_ÍL&¹è¢‹xï{ÿ“üàÄ8—\r mmó°›ço|ÏóX·îqœÎe—9¤R)޽†;ïü¿ü廉'}‘¥¥e?à2o^Œt:ã8,ZÔÈí·¿À²e®ërÛm·±µ+ÅY_Á+98¡ï€*‚ TªÂR I …‡p²ôtn½Jˆe—r‚ÊëD#VÌÌý5åÊ Î?Ô þX½a¢ª¬ZÐ)|ö‚ ‚ ‚ ‚ ‚ “؇À=ÙY`½ º î<àçx=xs€e~®’ß„æç³¼«aþÇÀ[êç!Iî‡û¶ÁÌéðssaßgÃúç¢ÏšEÛ 3‚‰º f[…âhº÷>í…&óÆÀi†‡z×x˜˜c×»p]ÛÛNáy±XØÐÐÔ@{{;º®óŽw¼ƒÇ›ƒmÛ´µµá8?ùÉËüô§X–E6›åÊ+ÄÑ£Gñ<ŽŽlÛféÒ½|êSW²x±‰mÛ\xáLvヌ¯~õ—tttà8W_½“Ý»Oãœs à “ɰ|¹EMÍKd26mmq2™ ‡œãŽ«¥­­D"Àc-añâÃ\{í-\|ñb¦M›Æ²eOÐßÿJn¾ù=Ú‰aèú>þñ­üú×þÈÝ—¾t"Gû—ÐóÊ—¹@AŽ5,| _Ȉ—°F>¿Jf„mSäó–{ˆ„“ºˆè!‚ ‚ ‚ ‚0ÕȆälüÁ$2{@_ b‚u<;dÖ‚¾ÓÏIâÍ€YïσdèO@óUÀç4èû vî]r”Ÿ?y<é9Óƒœ¹¶ Ùlá8Ôέ[Yºt)Ë‚en.½ãø‚„çùJÏÖ­[qši<î{ì±9¼ýí¾Ìò‡?üx#?¾×u1M3·Ï<ÚÚÚÈf³8ŽÃªUdË–ŸcYÏ“L&I$>üy^x¡]ŸGss3¦i²r¥Ëu×}{ïýo4MÃqZZ.å—¿¼˜¶6Èf³œ|òeôö.æðá¢i¦iòÞ÷‚¦A,f ëFî°dÉýÌœy º¾„t:ÍW¾òÇï—½­­-¸öGù·ßžæê«çÒÕՅ㜎aøÇÔõŽýè ¼÷½GÑušó…êüÝßÁÓÖNœX DA"K¿_ÈK.ÂÄèvèOyŸxÀ¾!öWÛ ‚ ‚ ‚ ‚ ÕK~LÀy(åd6,?:Ž÷pë»á”“r¡ßW±|ž<Ú-ðNïJøð‘ípõ*`•I£ HÏ€ØBÿû¿ØÍ_qSÅÙÊaY…e«­­åÏ>Œçy455ÑÞÞÎ /Ôá83pœd2 ÍŸÿüj^ýê.lÛæƒüð~,ËfΜÇp‡·½íõL›ÖÇ~´‹ÿýß6lÛæ£ý sçÞ,º®cÝx6G¼Ë¹âŠ.t]§££ƒ¦¦Ü½r¡«« €¦&8xð¦M;€X,emû‚R<ÇÎ ¢½ùÍ_.¸.ÀT ’Iÿ³aÀ>p.ë×× i}}ùsê¡ÀÝ»oÅq‚#Çkj‚ŽÿÜgž9ƒ‹.ºˆLÆ?G<î .ÿû©åL?Ô;¡ïÏqå|9AƃCÞ;%ÆØCié¹c-ÏO…‰êÁ÷v‘Q‚ ‚ ‚ ‚ ÇösÙç9;¡i¸ÓýDò.z š¿3¾„ä}»Ú–ÂB z40Ò`¾ßLv`qh6¯‰?àö<9ãŒ3xðÁKð¼P9là¿I©Àƒþ?¶n]N6›Å0 4MãñÇgëÖ­Äãq,Ë"÷c·Üwß}¸®K{{;‹/&‘ØÏM7­"ãº.¿ùÍqlßþlÛ, ÃàŸþéjÎ9çb±¦iÅ`ß>Þ9í;l¿ùO~!R)xäÚÎoC;°=_à¾>R×Φ½}@p-±˜ïiCÉÁï»®#® çWK{»ÿòëìÐÌæt:_$×õÏ麭iþ¹Õ¾Ù¬¼†³þÈ¢?ÍœÐ÷GA"G3~æà'Üêbt Þ‹Q‰êÛsÇ‹çŽ'ÉÌAAAA¦..¾·ˆÂ~~ÿè tÍè'$'ÂÖïÀqÿ æ`ñçà5'Ãûä%Ð~š?¾4›Áôm <ÏÃó‹ïòŽgƶ#x;Á™ ñN¨ù ¬8ÒóAÛéE°Ðƒ×¹¹I¾¹A¥X¬Ðƒ`Μ£d2`Y©œ ø÷Üó –eACýûS¼ôÜsœM#ÿR[K,ã¢ú]ݳ‡Ù³ë‰Åbd2úúú˜;w¯ý§Ð4x<ÎßüÍWyôÑkñ¾p?¤ÓiÎ?w|³ž¸áìcû'îÚEìÊ#X_Ù øÕWÎfùòùAh± ”–ŠÕ¥i¤n]‚~^-ºž‹L“Ìö4Ï…š{àù5¿Gû×À=á¬üÅïÚ…Þú!â¯ùUಢ¿ôÆî» ¹‰ $˜þÑwb­ù_˜?cù~uXÜ_ü `çNLÍÁ¶}±ÄýÎVt×W\Ì å˾};8ÆÉÛƒcäœvp]°¿ò΃/ gvö0ˆ "B¤°ñ]"Û‰Nxwü‡ˆÎø!‚ ‚ ‚ ‚0)¸®›KÆ><ËCŸÀíós£|}ÇsüûÓ/¢€§ž>ŽÚO=Gl$3\ —Ÿ çãlèÊE¾ºÿþðÃvß² ¦f/]t®ë’H$xî¹EløaþâÄãq?ðnï ~ßµ5O<ÁsÏ=ǬäU³óÙ³®Çt]øÑ¸sm'+Ÿy†ÿø%:::Ð4+¯|€7¾ñnÞõ®Ï‚m“Ô4zz>†9ó~¬[w£Yž§c,ÙͲ]G|ÑÂu}!áÆN’w6Ûxú©‡xæ¾ï£ÏÞ…óÀÿÀ\øˆïRäΡD‰0¹Üðxš3f€i’þÿføÏä™Zì‹®‡}û°^…§âË,^L<­ãÌy¤Ó8Ž/zÐÕ…u\‹ŸødÖ,À_ž>øx¯¿ï//‚®ÓÖæ 0ZG;ÉU?÷•î!‘ȉY÷ÝMMÓ ‰Ž“ór±,bßz‰œO>‰1Ö™Õ#P‘¤ô½½½ôöúÉ`]WWWG]]]%Š'Ç,ÃÙfx}9íÓÅWþËô›7jLüY SM€¯›ê# ö)ÂàHÛV¢‰Ô‚]Ä>!ºDµm›H$H&“˜æðÁÛUy°fƒñô,˜ Àûº^d£û O?ê»üdŒ‡e0|)}¥ÿûöœ{îÿõ8Žƒã8üìg-ìÞý¿¼øâ~nnläOÀŒÿÀ‡žûß=ñnÜÿïlìmåõó?Ç[ž|m߯M¬úånxìgÊ;øß¸é«@óÐuh\óc>l0§ \MÓ9ñ-ËøÝŽ•¬Ýy[=OÿûVþá·YV-úÿAøB Îo§cÿð0ÉÆwß#ÄáÙgÏâÖ[Ÿâ†qÍ5ÏáºGùèGÏ¿þë÷Øóš)4-ä¹s≸/œ³èlМ@ØH¥R¼öMÈ:Ö!ýyömwþ_@óÃ~Y$Ü41ÒÿûïÄ=ÿ¥}/hïå´/îÁ}ë;ò3¡c1 v×,´/–í]œtA¥µµ•Í›7³råJz{{©©©á¶Ûn£¦¦†Í›7ÓÚÚÊÊ•+Ù¶m6l ¥¥e²‹(Ç$ÃÙ&Pvû´ñ“E5¯‰Çøò¸Âx¨´} ‚04Ò¶„h"u§ D±OAˆ.QnÛ^¼xÄmÔdØ\Ú ìU0ï`?'Ä='ójo1Ïn¾ ,àÁ¾Wø“ys ÔMÓÿ Ssx1=¿ú5®ërÝ»ßÍ“/¿ÌÇOù·m[Ë9g¼Lª¡ã~ö3Þ8ý ñmïáî‹v’~òñÖ>hñô‘Ö­¿šl6Ë#ÇŸÍÃ÷“O~}‹íäñC |í„_s¦îñçînî{áVΚE]]_ßö÷¼Ç¹ b1Þ{ô1ž«y'—üÝ9lÚô n½ƒ[oíä›ß¼’¦¦ñ<Ý»o¥··—M'àÈ‘Ù477³÷Ð?òµÅ‹ywëjxàJÿ=>V­Â/×E×ufÎÜFss3‡_ÌÂ…Wñƒü»v}ƒY³®äðáOr×]ËøÚ×®Ã0’À…hš/xhZ>„XcãNvî|Ž¥Káæ›ÿ“3ÎXMÿ¥477³dɧ±íEd2¾÷½+hnÖ™??pà'žojòÅÓÛ¶‰ÅLš›áë_ÿ:º~Ã0xÝëN'‘¨åõ¯ßEw÷-ÜyçEüò—aóæÏò½ïý8b1tÏÏå’,Ó»8©‚Joo/7näŽ;î ¾¾>÷²šlÞ¼™õë×ÓÚÚÊ-·ÜBcc#ÝÝݬY³†ÆÆF™ ef$ÛÊnŸJPòýà—ñær‰Síz¦*Q°OAGÚ¶‚M¤î„è"ö)Ñ%êmÛ®¼’­óçc’º¡ÂÆ«/Ûÿrî­Å¹´#pò³xæÄZ¦ÿøœ|Áý|gå‡á?ÞíÂÕßý:°*8¾ëú"ÁÏÿö^zßû0M“W<óþ<‹óÎ;ëúúøâ—¿Ì¿~agïþ¿ÿÇnÓ¤ïáã9aÚÉôüå$²§¿ŽßÞû3¶üÊfñâOR[ûfîinfîܹìÝ{˜o\Ë·¾u€~ðùð‡çÐÔÿÙv;v,൯õÐ<—›cóp]?Ê»g¯çɆyäzæÎ]Ç)§<Ä]wuòÈ#'ÐÒòq~ô£yó›7ðÁ®"•‚E‹žã oxŒDb ¤R°mÛÉzß½k7>üÏ@’ÇgÑÔô7ìßoqöÙÏ›Þô×¼ï}iN?ýulÞ¼Œ––ŸrÍ5 ùå/÷qÆâÁ_ËUW]Ä~ðe\÷T4ÍåÙgòûß?Ë7¾ñe,kžçñÌ3ÿŸÿ<‹o}ëØö8zÔlÛ¾]×ùýïäôÓÃöí¯Ãó‡ã8d2–,ù0uuËH¥Þ‰a†ÁñÇ_Ǿðöïÿûö½ŠiÓ~Éå—ßÄ}÷õrÉ%‹ð<½{Âuß]œìf‚˜Ô*½½½466F °zõj8@gg'µµµ+Y}}=õõõtvv{ÌC‡¸ ”‹ÎÎNvîÜYébŒ›álS]çXìsçÎtwwS*i  ñ™,¦² Ò××Ggg'GŽ©tQÆM9ìóÈ‘#tvvnÜ‚0™ôööòè£òüóÏWº(r-Ò¶¦Ҷض­ Lªm{èСJeÜHÛV˜jHÛ¶´¶m__ßø ˜Ë0žÂÍ®’Ì+q%õ üè¸ÙœÐ Þ8£ë ¯ýñàÁ‹žÁÛwïöC¢è¾WÅ3ÏüMph×uÙ´é>î»ïóòË\ñ»ßñ¥û7fõ÷óô‚>>û®wñ òìYgñKOçǯÀˆÇijjâë¦Éi¯>ÌôéßÃúÉ˼xÒI€ÆÑ£KØ¿?===lÚ´‰}쫼õ­WqÏ=ïdåÊ9€ï™¡ë:?þqnL×aþ|t]gïÞ÷sîßœG{{;¯{Ýe$“IZZNç=ï¹™L&òeËøÇ|+ äE¡•+ç`šæ{{8¬X±‚T*Å‚;8óÌeÏž=ìÜ9“d2ÉÇ>v>ŸúÔ7X³f ±XŒóÎ[†¦Á¯½ŒÙ³ýi'tû÷Ïç5¯y—^ºžåË—cYO=õ[Ž=Ê·¿ýLÓ¤««‹––žþÄb1’É$_ÿúÛ0 Ø?‹aÛ6 , ¦¦†††‰–eñâ‹'±hÑ'±,‹ŽŽ:::xÏ{ÞÆg>s ûöíÃÉÅc»æšØv†žž^óš-| óÄ?¦¡¡l6ËÏþ_\~ùô¶¶rë­·N¸­Lª ÒØØÈ¦M›‚ï}}}lÙ²…ºº:º»»(šµµµ#VˆÏ>û¬t:…Š1U:ÃÙ&0fûܹs'Û¶m+© þ¬‚©<È/LªÁ7•rاt:…JÒÛÛKww7G­tQÆ´m…©†´m'®m+‰jÛ>û쳕.ʸ‘¶­0Õ¶mim[%šŽåið½ƒÉ„–;ø¢J3àœ ·µœÀôCÏrúïpù7ûø×§Ï¤_§H§ÓÁ~·Ýö/½ôRTþ]çŸÏìGÄ´—^â†gŸå’{îáËï{sÍdÑ9çpÎóÏ3ý”S8ï-o¡vÁ–6>‡ãh´µµñ×}.k×>ÏsÏý€×½î´··óÍoþ'×\s6 ¼Ã0ؽ{ŽŸh=”k$•x­†ñxœk¯ý!}}ïFÓtfÏžM2™ „’ð¶Î I“Iÿ<póÍo£§§‡oû\×à®»ÞÁÎgDZm?™»eîoÛyOæÏßʼyû8xp:K–¼þþ~ÚÚÚ¸á†÷ðàƒ—ðÒK¯%™ôc͘f {åB‰=‡®ëÌž½ 7”peþüiœuÖ³†A<Çu]®¸â>~þów£ëzÁu¨r†ã8¼ç=ÏçX¶ì-¼øâ¿±lÙ2îºë.b1ß_Éq¶ly-ëÖ­ã‚ .×»7“*¨„Ù²eKàÖÒÒ2¨a•â2¶páB6lØP©ËŽq6lØÀªU«Æ Ql›À˜ísÕªU#ÆÓlÆwÑTÉè…òãŒÿ‘§®®Ž 60oÞ¼JeB™(ûœ7o6l4¨ ”›ÆÆFb±'tR¥‹2¡HÛV˜ HÛvxJiÛ B9PmÛ… Vº(Š´m…©€´m‡Gµm'",ØüùóÙ½d ×ð€?îßÏ÷î¥{ña^|úžüÒÇX;w.oZqRAâtÅý?ü3/¿\KëêÕ¼´w/wÿõ_s]ßÜ:ë0'½óìý÷燇³°i+O=uw<3o»¶¶6¦OŸÎwž¦ù'žx ¿ýíüô§Ÿã-oY†¦i46žÍë_?›E‹fHÜ^,Š€ï©¢ò·èºÜÓN›‹ën‹ùƒÊ]bù&aLš›ý¼$þy5tÝO&ŸÍæ·s]Yø±X>—‰âÌ3Ç/~±°`;%tŸ7¼ÍâųX´¨‘“Nz˲•E‹vrá…ÒÞÞŽ¦iX–ÅO¬aöìÙ9–Âû¥ð<¯`ý{Þs6žÁ¼yóøð‡?Œiš¸¹¼0---eiÛNº Ò××ǺuëhmmåÆoäÆo|U³™] “ÇP¶ åµOHm1Åÿ!"…7þC“L¥ìS„‘‘¶­ D©;!ºˆ} Bt‰ZÛ¶©©)ȧqtÉŽäÂPÙ€³ÇߦmÞ<ú,`Ù#/sbß <ÿÜ ÇaÞWç VL_%È©o_ø,sŽ;À‡¶àŒ{ïåÇ55|nÑ L?õï{ßûX}džÁÎ×°oß>Þöž÷€a ë:3Þ%o~ókñ$›õ½<ÚÚÂyB-Ë9TJå½DÔÓô‹ì 7ùcX–z.t™:g<^(rFÞFÑÖVø]•),ž &ÐÜwß&¶n_°.,ꄉÇóŸ[ZNç±ÇVòWõÃ\™üßõ®óQC†aàyþHÕüùó1Ã…)(«„ýR˜¦Ic£/Z½ímoÃ4M<ÏCÓÊ;Ê8é‚ÊÚµk©««Ã¶í‚Ùõõõ ñÀ’tL&‰¡lÊkŸ.ÐÄÇ{ 22Õ¡ú¨”} ‚02Ò¶„h"u§ D±OAˆ.QiÛºø“AÇ¡¡¡Ó4©©©a÷’%耾œZWÃsúæò53H§» Ž—Í‚ýÕ'óîÝŹ§~Ÿ‡®»‰íÛÇé¯{ÒtæÍëᡇö’L&I$¸®ŸCÄÊ©¦irþùó ¼LL“@(ö<Ñuhhð?‡ÃjÅã¾¢– æµ¾X¡Ä…¦A"á{–„›Íôfio/<^*åŸ;,z 6,,ƆÁöí¿aæÌ™Ê‹z¨k vؾýôÏ’Â{ä_\SÓ|–-[6¤ ¢iÚ ÇÐuÿ¨U®[þQ¼IT6oÞL__«W¯¦³³3øSIT\PðãfööörÅWLfá˜d8ÛÊjŸ~N°( *&S'L–䨩>*iŸ‚ ´m!šHÝ)ÑEìS¢K”Ú¶YÀÂÌïïï'™L²ø°Ò+èóÁ› ×ùÛ7ÿß~ôã ÍÀ0Qo{[ üéÙ‹xzÎ^uÉ_³ïcãSßø‡æøãwð‡?¼ Ïó0M“ŽøãçùWÇŽƒqòÉô¬¼ç…÷ðÜsÏ1Ƕéëëãå“–ñƒÜÏgN#NsõÕ³Ù¸±…Í›kƒ\ÍÍpùåŸÀu׿’¢çË—É "Th®0ÅÛ¨íR©ÁÃk55A¿ÿYy£{”¨\*ê»:fعCÓ†üJ§}q'•òË¥Ê[¬SÆÈâF©tumÏ ÄÃ0Œ uuuaYCa9T~”b\×êÚ'cÜiRe|CÑÒÒBcc#½½½ÔÕÕ‰K§ L#Ù&”Ç>':—‡ã8Á,‚á'¨²lžG&“ f!ÿ$g2LÓÌ%÷úx®ëâ8F.Þæ˜ï—ç‘Ífƒø’±AjjuÇÁqLÓ$ãyž“²èü*i[[[ zX–…®ëÁ~ªâ‹‡jqµÎ²,\× Œ†lçyMMMÁ1TÅæyÉdMÓ‚óÚ¶®ëÁýöA:FÓ4ÇAÓ´àúlÛÆ0ŒÐL/¸¦©$ÞTÊ>AiÛ B4‘ºS¢‹Ø§ D—(µm9‘#G¸ïÿûÿøG|•Úƒ5,Ú¿“øýKhøøïyló2ž5‹ïý4|ý“ûa²ššpþæ+4m»“õßþ6û®¼’„iòü›OæÌi‡8ûì·ašgcYK–Øœw^¿þµ?‹ÅÈfáÙg?aø¡Ä #Ÿ‡D%y‹Žãÿ…s•èº/’xEƒ`áá¶j°åº^(¨€ïe¢rŸ8Ž_†b­a°ü&©Tá²T*ïi3éôð‚Çp„ÇnÚ‹ãåÖ[ÖÀ{Tx=ú ã`Pòk2˜TA¥¤²„è2Ñöé0±!¨²Ù,š¦ *¨¨AvÛ¶±m›¶¶¶‚í,ËÂ0 ²Ù,¶mãy®ëúÂ@®6;tè™/})ÐW¢‹iš‚%Ôù²9Ëx÷\þæ+_aÑ¢E477cš&ÍÍÍh¡Î£ %bض] ¸H¤ë:@“H$èïï'“É‹ÅH§Óè¢f477cFp-†a`Û6ñx<,Ë¢¡¡!c<Ï ÜCÛÛÛY¾|9étšL&ƒeY¢M&“aîܹø†E©?!šˆm Btû„è"ö)Ñd²lóW¿úÛ·ogÿ{ßë' ÎúÌqüSg//<}*œÓOšÎ¹g¿Lò꼘¢ŽX _a0 8ñDôùûyö/¯ä;ÏÞF³çñ‡¾>–.}‚lö¡`RèøO€ïÁašyacÆŒÁñ•x¡Ä%¦¨mãqX¾Ü*L3ì51¸H>L•¬ðyÃÛe³…ᵊsªÀ@oð½C£TÅ?—žûóTcKãA=cš¾:üP¹V&’È *‚ [LD-Ïó˜?þ ?®Jinn.ˆÓ¨ÄÛ¶±E ê+/ Û¶I¥Rì¼ùfŒ%KøÚ×¾ÆîÜ }<¼S–/_#‘H„lºr5XCC™L&(£®ë¤R)’Édp>Ó4I$˜áº.mmm¼[R©T.Aš”e(•_yš¸®Ëgþïÿ8rä¿øÅ/‚Y©TŠX,6d¾(¥‘ô2•ëf"‘ò‘»¹è¢ËÈfShšÆîÝæÈ‘1}ú½ØöÛ0ÍBáD ±˜ïùáy… äóŒ¸î@Á#œã$¼mÇñ™ŽŽÂ„ìÅÎ`¡»Âzi&š •ÐÞu}ÏŽÑx«”“ñäm _{r°¤5Œ*‚ T„,~rôR~ï•0Ò3”wI<Âe†A*• Bd% LÓ¤£££À;BT…UëbDy}| ¯}},^¼xÐòÅb1âñøˆúñâ —ƒàºnàù2ãu•8ÿüóË&B¨ò9Ž3)•ÙDÝAAAA*ËáÇy¹¶–yýý85Óˆ~ìbÛ¯¸Þ L ÁÇr1»üɵNíßp÷î•|è•Çsß…òýïŸÃ³þš+ŽgçίÓÞî‡ ¸ä’Kؽû™àœ–•ÏK¢Âg)OŽ«MóE‘ðÕdÒ_¦"Žÿ¿xHÈ4 …5<¥Ê>Þp(!¢%¹®ž©B s„'TA˜tl /¦´°­eYA‚õ`ÿœ7‡Ê™ލë:‰D Lsõëéé)©¬±XŒlÝÊ^|‘+V ºÍPž3£A×õ q}¹Ù½{7³fÍb^™Ï£ò­”[è˜ OAAAA&‡3fph˜6 ÐvÏÃ'?Ìõ矹!×ûgÇa¾6—û¶c+ —\.ãÛwžäõ×së­³¨­}™£GÏÃó´\^Ý4?üáfN>ù¢@,Q"ŠaäÅ º+š+<¤¶ {X–/¨‡ülŽmxȲümЇ8FRÑ4ßÑxš”*ÀT “°DA*Bˆ3²‡ŠJ”onnr”$‰Ï%  •œ~,¼üë_óØ«_Íù'T¶û¡DŸr‹*gœq;ŽåèÑ£œ=„ÇÍD B~•[ìP‰êETAAA„êÆó|¸¬Ç7M3ÈqSnlèTAA¡ d€)”n@"…dsŸUx÷“_:£ô9`6qpûB@*åÇáÒ4²÷ÔÇZ¹ò ¬[÷Î9çyjjÞŒ®ëF×õ½2²ÙçO§ýÿá!ÃðÃ~©! %rçPQÛ†÷-N6_*ñxùs¤R…×*‚ÊØ_‚€ÿãíá‡`”ÀAådžò!Qa¯Ç¡££#ðÖP¹2*ÚiËš5“ržX,Vv⤓Nb÷OðÂI'ñºÓO/ë¹âñxº­\†A6›áFAA„©‡?¸k.~¨j¬`bc!‚¾Í©q}Çq8ò©O¡ÿÒåþè÷E7¿!±Ø¡Y»ÿó?÷ðûß×q晽<è‡9¿ð ¼!á¡¥DººòIáapAÄó؇%È„«P±|ùèC…Mˇ+F*B¤lž¹GÞ£A‰à7d4ÀÂÿá-þ P¿a±Äa `¢–¹ã8@¬è8áãkø Õ…òà8±X,˜• ˜È$óQ¥ÜâÀŠ+`ëVÞ\SSÖs‡c+JH‘xž‚ ‚ ‚ Œ\A (j¢eù¼Ÿ©JR޲ÀÎE‹`Ö,8Œ?ðg`ÈáºÐÑÝTªë¯þêb/Ïû§œrà‹$j_% {£ æ¹Þf†7‚ó•{¾¨ -æy#‡/GaBP¢ø %r¨u 5»Ã#/r¸äE½è;¡å^n¹ÚÇÎÛÄ8 òâ‹:œ¡“Ÿ†:¶‘û¯…ÎmM¡ãŸzÙe4:TéGPµ477“N§ÑuT*…mÛ´··LÓ”AsAAAaB°ñû÷Åã ‚ L.Nî¯cß>f¾ç=ØÀÅ;ÁëMÍ€œ_&ö®~`NÐÙ¹Ûþ'ÚÛÛùêW?ËUW]Ïg?û]yä*®»ÎKа‡½Qâq?zX±§I8¼—:F©Œu¾l{{ùÃ~Ù¶/¦¸îà!Ì„‘• ÒÙÙIoo/---twwÓÚÚ @}}=6l¨ôõã@ :~Ã"ìöìpÈ # -ô=CÞÖÆŸÕ£5ÆŠFÞw¬çÓð=T”À]œ­£øwæmû÷s0—´\(°ç£çy¸®‹®ë¸®K[[Û‰*à 'žÈÁƒ+]Œ A½•'‚ ‚ Bõá òã&ûý‚ Lj‚ö¾}û8sáBvÞÖbˆ›ä'÷íún;ñ9ÝÁ¾ð¦7Ì?üƒé䪫®çW¿:‰¿û» qœùÎÕÞ>ðüÊc#•ò§0Í|ˆ/È'©/%­ïX=ZlÛ?Ç`aÄ&‚tÚ“4Í?06JTn¸á6oÞÌúõëèííeíÚµ¬\¹’úúz¶lÙBoo/·ÜrK¥¯IÀ°VaªÂˆŠK¨á‹j™NÞ«Ã%NKyeÄÈÿÀÆããX9ßüÐCœÔØXébTÊÛü„âɤDMåOÊËÓ'žÈI'TébLº®Ónñ‚ ‚ ‚ Ah;â"Q£¯¯ý”|®W÷ø†ªDSO…Çóœ HStw&‘HL&ùÚ×NæÒKß…eYÀ@U"“ñw/,’É|ây…¦æ\q_(©æ¹¾™Œ_~]÷Åal”$¨twwsÏ=÷pÇwP__À–-[¨­­å–[n¡¦¦†––LÓ¤··—ºººJ_×”&^Ë¥PÇ‚çˆ}œœ¡mÛØ¶-!½&8ï¼ó˜1cF¥‹"‚ ‚ ‚0)4ãGÞcZAÊÈþýûÙsô(,\ˆ7ÌN8´œÙ¡ðZžGºï4ýr°Ÿ;v츃»î:—Ÿý¬™+¾Ëš5¯%O!­Òé¼H¡¼S–//,ƒë,—¦å…ÃðÑÐPÞ{¡.¯*‡®çË¡iþç°8£f[Y–¿¯ ‹ùÇP?«Ž“O¾¨bä*ñH GÂø©–¶­ kKu§ T“Ñ÷ìªôE B•R‰¶íYÛþÄî%KÐÒ ßžŽß¹ÉŦڿu?éÁÛy×»šØ°a ?ùÉ“œ~ºMWWÏóû=ªÏåy~ß­8Oˆi2¨3åö™,Òé|Ô“¨.c¢ä*õõõتWbåÊ•£2žÍ›7ÓÙÙÉ–-[X¿~}Áº¾¾¾È4b•²ùå—9óûß§æ_þ…žžR©=]]hšF*•ÂÍl˜¦‰ã8·Ú/=BÐwÇqÐu½@*FݯRÂ>‰Ø3ñ g›01ö™Â×+ cÛÄb±‘=S|cTBŠ:JEMIòr'o&Ÿ¸H–ã ,&¾x¢b’¥rU!ÅŒ\9’¹²häEeŠJŒqsÛ‘Û‡Ð÷0nèÃ]¿R¡R¹ãu‡†ÚGÝÖâòL$NîØJÐR×£\`ÓäC¯)˦ìár‡Q¢–N^Í;0˜ ûŒÊ Ã4}ïövð?.Œ)«BêªpYáÆ²:†¦ùBƒŠw«„U†«Õ° 7•ˆÂuó.ê*t—<ÚÚò"Œò8Ñõ|Ã]‰%JQÇ ‡ö¬\wEïèÈ—K+ü]ݧl6/)qÇuý{©Ž™Íúû–ËE 7â>8ÕÒ¶„cc±î„ja2ìSE9ƺ ‚0n*Ù¶=kÇYÜ›ûl^öaüNQ—/þèG»¸øân¾øÅsˆÇã€Çúõ—òîw¿.˜X¦&Ò©°^jÂZ8œWxòÛh(wÂøÉ"•òûÍž'‚ÊX)YPŠšššQÒÊ•+©««à"¾·Ë7ÞX±›‘J¥|ƒÔuš×9Âqõõ¬I&1CY‡t]'›Íâ8íííÁ€p6›%N¢ASSÍÍÍhšF,Ë;B€iš,_¾œ¦¦&:::H$´µµ dŽÇã,_¾Ã0H&“hšF{{û€kH$444‹ÅˆÅbضM{{{ZI‰'™ÜÈ“®ëÁŸ2”WmÛ¸cÛv ÚAù4M D °à‹ÅH§Ó444àyº®ãyÉd²@¼q]7¸_º®ž9ÅBPXÀ1 ×u <{”°¥Ž¡Ê¦„+%F©ë £¼„Â÷<,©ãLu†³M˜8ûTcï*!½bP!-…ß Va¼ÆJxßvü5#;¬ªa]øƒû͹í”(b‘MT¸1=·ÞÈ}V‚A¿õî…öQ‚M{î{"wmJ(P¡ÉR¹mÝPySä§X5ç–«û£åŽ•ÆN¬Aʮġ°¸’Í[_yû¨r*ÁD…R#´A^81ñ“Cy NVèž‘[®D%ZÙ¹kR¢Y±÷ú®Ê¦>›EÏÖç{a&Ë>+…ò¼H& ó•`¡yj¶‘mûé´¿}W—߸-ž÷öäP¨*Xå9 ¯W ä°x¡ë¾Î]¢¼;t=¿iO‰+žç ;j{•wEy¤R¾Xdy—tÏË'ET%Šhš/0õôøÿÓiyss^ÌQeR"KXôQbŠªÖ4-ßv]ÿ:ŠC›)/T'Êm[A8–™êu§ T3“aŸ6?§l¸¹a‚0U¨DÛv÷’%œpÊ ÄïtHeÁÛÑGœÛ5dÉ’%üÕ_-ⳟõ‡³?ô¡¿¥¥åã\wÝûƒ‰eÅÓë'ªÉn£EMø«fÂÑŽ¡Î²Q² ÒÛÛËÆéíí¥¦¦†x<^r¾”0jŸâäõ}}}Üpà tvvRSSÆ hiiöx;vì`ݺulÚ´i\7"“ÉÉdx|íZþyϹá†!Dašf T„Ú‹·‹ÇãÁ`ýpttt(À ƒ÷º®Óßß?âu‡SÇRƒÕJh©Lá}†o»NMÓp]—D"ˆ%]9%Ù²¬ÀƒF·øZ=Ï Ä‘pè²âÁvÇq°,+†”'~T92™ ¶m"Œº—aQË0Œ@øR‘òàQ;ét]×o#uœ{ï½wÔ¢bTÊ6aìöy÷ÝwyÑ’…o—|®¬”0:¾÷‡úÜNÞ3Å&/8¨WÓΕ3Æà9ZœÜr%.˜¹c4ËÀl|‘Á¥Ð7ÝÈ-SçèÊS‰*1 'W+·\å”QçO[ÖósÇTâ‰úùjÝw-·„tòB”–+¿•»?áòªkÉæ¶‹“_Úse|Gy ¥s÷Fyà$Šî…‘ÛÇ%ï £¶O‘€Øþºí|yË—9i×IñÖTœ‰¶Ï={ö°nÝ:V¯^=¢—%„E“l6?˜Ù5Ø:È‹aŒ¦&ß{#\Å„Cr©*EU3ªñ­„µÞ¶ýuÙ¬¿­ò~Q"„ ¦âòªsxž¿o2™ßF•W…3Í|C6›Í'L *|äEâÐb®ë{î¨óææ…x•¨0Ê£%›õ÷Q^2–•/‹zá|2ªL¼Â9hgtñÍ›7³yófÎ8ãŒÊ¼xLTÛ¶‚0Ö­[ÇŽ;¤m;Åm[A˜,º»»immeÇŽ•.Ê„Pî¶­š6Ñc…2‘[ iֶۖݰaÃãÈÏx–æ'ö3»o·<˜à=ýzÍÞ‚¤%O>ù$޳ÞÞKˆÅbL›Ö„ëú¦p¸ä0CÊ9Vë¾-Lðe#ÑÚÚÊÝwß=ámÛ’•uëÖ~‚úÎÎNÖ®]ËwÜ1 yØXéíí¥±±‘õë׳iÓ&:;;¹öÚk©««ö¢—.]:îg6›åöÿ£§‡{÷rýwò™|„x<>@$ }8A¡Ä‹‘ÐuX,F"‘ ™,G\ž±SJø-F,|=®ëÂÄhî‡6LÞ™0JðPÞ.êüÅå(¥üªlCá8©T*ð°‰ÅbAÎÓ4ùÈG>ÂÁƒËô¢ÁXíó­o}kA‡3áÊqœÀ¾T8=À„/&-ôß}vžË$Ÿ«¥˜°ðBÑçŽ!öJ@*Îá.cØ\Â÷¬¸¬aQb~¨ÜáŸ2åM£Î.ËÀŸÂ¼à2Ôµ„Ë>O;yJ‰TznûЫPpŸÂçW^5ªÌà?Ÿ¶ü½Yöä2>÷ñÏa%,¦:c±Ï… NÚ`­M”‡ƒè…Âò"†ª6Ô6JœP„ú¡°á¬<2ž$á`JPBCssÞë#œ›$LØE%|WçtÿG‡¿N áãd³yáCCÓ|±¥©É÷4I¥òâ‘jTî•„^•AÓòenk˯Sçð¼|–d2>%¼(È—I•Û²òbJXX {ç(ïšLåˆìïøl†¢¥¥…ºº::;;'嬕lÛ ÂXÙ´i­­­•.FÙ™¨¶­ LõõõlÚ´)—™ÊLDÛÖfð4›ãA9Î B1Ò¶Ûv΋sxÕŸç¡w’Þ±cF{ÁXÈ•W¾]ŸG]ÝÓxžÇæÍí¬XñA`±˜ß/)ÞSýN! ùUœ³t*R®v[I‚Jgg'½½½üú׿¦¦¦ð®7oÞ<× ìa¢Ž>o˜Á<' £ÐÍY•5,$‡ùêêÊ'Ž÷¼BïRKýŒÅbÇ+!F]c6›¿Ë—çsŸÄbùýÕñTX±pU"{uTˆ°° cš~CÙ0òB–]”y±EmçºþýVÇQ¡Ê”'ŠëæóÕ„c«0lÊ#G i õœ%·ò(Ú¦ >bŸ‚]&Â>Ë ØÈWŽUÊYwNïŸûAwÉO4=|˜ìóï&næ;y=ô/d³K0Œ·aoàýï¯á÷¿_øý–tzð xÇ‚'F©„ûÂ*ì¶0zŽ+uÃÆÆÆ@LßSe"éíí¥»»»`Yø|M*•"›Íòo_úÏ~ÿû\3s&™ùóq]—d2) ÏljÊ×RnAe²H&“ƒz+œvÚi•.^Ù)‡}:Å™¼–“Ï 5…\µÈ§Æëì_Òü)t=*gË1Êdן¥Íž¬O% ‡ÚRÛ©ÿáz5 _<£(Þ«˜p(0u.u^%(o%B„“Î+/ÃÈç?ljÊ—¿Øc&ö…Ö+•Ê Éd^ô°,0ÔõkZ^ Ñ4%À(ñ(Ï—K¹h+qEå‚Qb”:ž€”‡Œãø"J{{þ~ªã«ãªÆ´aøåH$ò÷SuNÔ½õ¼|¨1µ.œ#F‰.êáeÇÊ ±(Ú¦ >bŸ‚]&Â>UjFA&ŽrÖÏMŽôã`ª0ÞÙ,é¥_Áñ ](fϾ%H;ະbÅ fÍš¬W}‘b¯ [ÔЀp_]õo…ÑS² Rn”«˜ŠÉ×××Ç–-[&,¤X•K#›ÍÒó±ñ¾šš`Bó¾}û†8J'NÓÓÓ$œª›rØgà]äáçÁèÂ÷4ŽÙËŽã`Õ”–e X6jTøª©†;þCTÿš*âИÌús4¨Æl¸¦ÖS¹œ:C ¬+1%œD] ؇· 7.K ±˜®L&ïá¡Ä UåÅâyyÑ"\.ååy(Ö+›õ. ò!»\×+¦<<Ôù•€cyQEÝ3å¢